summaryrefslogtreecommitdiffstats
path: root/ecomp-sdk
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-sdk')
-rw-r--r--ecomp-sdk/LICENSE.txt19
-rw-r--r--ecomp-sdk/README.md12
-rw-r--r--ecomp-sdk/epsdk-analytics/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-analytics/README.md16
-rw-r--r--ecomp-sdk/epsdk-analytics/license/licenses.properties1
-rw-r--r--ecomp-sdk/epsdk-analytics/license/my_license/header.txt11
-rw-r--r--ecomp-sdk/epsdk-analytics/license/my_license/license.txt4
-rw-r--r--ecomp-sdk/epsdk-analytics/pom.xml209
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java91
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java)15
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java)19
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java151
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java)10
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java)20
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java)55
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java)32
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java)35
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java)12
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java)21
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java)12
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java86
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnEditJSON.java110
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnJSON.java41
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/DefinitionJSON.java215
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ElementJSON.java33
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/FormEditJSON.java113
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/IdNameBooleanJSON.java32
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ImportJSON.java54
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ListJSON.java40
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/MessageJSON.java55
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/NameBooleanJSON.java25
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryJSON.java60
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryResultJSON.java70
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/SearchFieldJSON.java41
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/WizardJSON.java9
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java)6
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java)34
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java)73
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java)7
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java58
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java)24
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java)20
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java)26
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java)15
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java)10
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java)237
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java)7
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java)7
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java212
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java344
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java271
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java)39
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java)10
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java)7
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java)5
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java67
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java367
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java78
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java)7
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java)44
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java)12
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java85
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java)20
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java190
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java1752
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java)9
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java)17
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java)16
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/jar/ExtractJar.java237
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java)26
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java)8
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java)12
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java)3
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java)21
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java)2
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java)4
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java444
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java)0
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java)1
-rw-r--r--ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java (renamed from ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java)0
-rw-r--r--ecomp-sdk/epsdk-app-common/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-app-common/README.md31
-rw-r--r--ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDDLMySql_1707_Common.sql1399
-rw-r--r--ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDMLMySql_1707_Common.sql2837
-rw-r--r--ecomp-sdk/epsdk-app-common/db-scripts/readme.txt54
-rw-r--r--ecomp-sdk/epsdk-app-common/pom.xml294
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AdminController.java52
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AngularAdminController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AngularAdminController.java)7
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/CacheAdminController.java248
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FavoritesController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FavoritesController.java)13
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FnMenuController.java223
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FuncMenuController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FuncMenuController.java)19
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/LogoutController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/LogoutController.java)13
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ManifestController.java111
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/MenuListController.java255
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/PostSearchController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/PostSearchController.java)58
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileController.java)15
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileSearchController.java163
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleController.java342
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleFunctionListController.java172
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleListController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleListController.java)37
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SDKLoginController.java99
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SingleSignOnController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/SingleSignOnController.java)87
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UsageListController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UsageListController.java)20
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UserProfileController.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/UserProfileController.java)22
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/WelcomeController.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/WelcomeController.java)4
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/package-info.java6
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/AngularSinglePageController.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/AngularSinglePageController.java)7
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastController.java)5
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastListController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastListController.java)5
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CallflowController.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/CallflowController.java)5
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CamundaCockpitController.java60
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborateListController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborateListController.java)5
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborationController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborationController.java)16
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/DS2SampleController.java54
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElasticSearchController.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/ElasticSearchController.java)6
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElementModelController.java87
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/LeafletMapContoller.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/LeafletMapContoller.java)4
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/NetMapController.java57
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/PostDroolsController.java122
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ReportDashboardController.java46
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/SamplePageController.java50
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/package-info.java5
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/model/Result.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/model/Result.java)2
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java)6
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java)2
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/IAdminAuthExtension.java65
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/OnBoardingApiServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/OnBoardingApiServiceImpl.java)87
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java)2
-rw-r--r--ecomp-sdk/epsdk-app-common/src/main/webapp/app/fusion/external/d3/js/intro.js1
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/SanityTest.java (renamed from ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/SanityTest.java)2
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java (renamed from ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java)6
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java (renamed from ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java)2
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/core/MockApplicationContextTestSuite.java127
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java (renamed from ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java)4
-rw-r--r--ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/workflow/services/WorkflowScheduleServiceTest.java (renamed from ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceTest.java)7
-rw-r--r--ecomp-sdk/epsdk-app-os/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-app-os/README.md66
-rw-r--r--ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDDLMySql_1707_OS.sql12
-rw-r--r--ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_1707_OS.sql40
-rw-r--r--ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql57
-rw-r--r--ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql59
-rw-r--r--ecomp-sdk/epsdk-app-os/db-scripts/readme.txt36
-rw-r--r--ecomp-sdk/epsdk-app-os/distribution.xml33
-rw-r--r--ecomp-sdk/epsdk-app-os/pom.xml305
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java)63
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java47
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java57
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/FusionLicenseManagerImpl.java69
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/LicenseableClassImpl.java62
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/login/LoginStrategyImpl.java70
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/Register.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/Register.java)27
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java (renamed from ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java)48
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java64
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/resources/logback.xml (renamed from ecomp-sdk/sdk-app/src/main/resources/logback.xml)30
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/resources/portal.properties52
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties69
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/defs/definitions.xml17
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/conf/fusion.properties29
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/footer.jsp17
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/header.jsp1
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/left-menu.jsp778
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/index.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/index.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login.jsp113
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp117
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml17
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/font_icons.css1
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ionicons.css1493
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.eot (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.eot)bin120724 -> 120724 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.svg (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.svg)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.ttf (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.ttf)bin188508 -> 188508 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.woff (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.woff)bin67904 -> 67904 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/ds-profile/post-controller.js3
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/samplePage-route.js19
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-services/postSearch.js5
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/post.html3
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html59
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html189
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/samplePage.html62
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/footer.html13
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/utils/page-resource-ds2.js97
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/view-models/footer.html17
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css116
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/fusion-sunny.css362
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png)bin951 -> 951 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login-550x360.jpgbin0 -> 62502 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login.jpgbin0 -> 21266 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp.png)bin107597 -> 107597 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp_trans.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp_trans.png)bin109926 -> 109926 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/flexslider.css275
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eotbin0 -> 2082 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg19
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttfbin0 -> 1892 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woffbin0 -> 1268 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/images/blank.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blank.gif)bin49 -> 49 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/scribble.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/scribble.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/slider.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/slider.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/spacegallery.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/spacegallery.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/welcome.css173
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/area_chart.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/area_chart.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/bar_chart.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/bar_chart.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/worddata.csv1
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/donut_d3.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/donut_d3.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/donut.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/donut.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/gauges.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/gauges.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/worddata.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/worddata.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/line_chart.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/line_chart.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/pie_chart.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/pie_chart.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/wordcloud.html36
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png)bin552 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-next.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-next.png)bin1561 -> 1561 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-prev.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-prev.png)bin1557 -> 1557 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png)bin202465 -> 202465 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png)bin21222 -> 21222 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png)bin11536 -> 11536 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png)bin26131 -> 26131 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png)bin192031 -> 192031 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png)bin3021 -> 3021 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png)bin179361 -> 179361 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/copyicon.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon.png)bin235 -> 235 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/deleteicon.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon.gif)bin579 -> 579 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/example-frame.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/example-frame.png)bin33699 -> 33699 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/loading.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading.gif)bin6820 -> 6820 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png)bin22762 -> 22762 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png)bin22772 -> 22772 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png)bin24012 -> 24012 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png)bin23902 -> 23902 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png)bin22349 -> 22349 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png)bin23674 -> 23674 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png)bin22845 -> 22845 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png)bin10575 -> 10575 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png)bin10460 -> 10460 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png)bin10420 -> 10420 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png)bin8941 -> 8941 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png)bin10590 -> 10590 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/FusionCharts.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/FusionCharts.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/charts.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/charts.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/eye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/eye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/scribble.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/scribble.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/spacegallery.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/spacegallery.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/utils.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/utils.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/custom.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/custom.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png)bin133 -> 133 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg)bin5755 -> 5755 bytes
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/prettify.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/prettify.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-app-overlay/README.md24
-rw-r--r--ecomp-sdk/epsdk-app-overlay/pom.xml52
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/resources/att-rules.drl (renamed from ecomp-sdk/sdk-app/src/main/resources/att-rules.drl)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/resources/cache.ccf (renamed from ecomp-sdk/sdk-app/src/main/resources/cache.ccf)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/resources/mchange-log.properties (renamed from ecomp-sdk/sdk-app/src/main/resources/mchange-log.properties)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/resources/state-rules.drl (renamed from ecomp-sdk/sdk-app/src/main/resources/state-rules.drl)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/quartz.properties (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/quartz.properties)1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor.properties (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor.properties)37
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/.gitignore)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_pdf.properties30
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/sql.properties)27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties.oracle282
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/conf/fusion.properties43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/defs/definitions.xml194
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/.gitignore (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ds2/template.jsp101
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp)27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp)120
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/include.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/include.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/sequence/details.jsp1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp)28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp)19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp)25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/folderNav.jsp464
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/testTree.jsp229
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/error.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/error.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/leafletMap.jsp216
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/login_external_ng.jsp79
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/net_map.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/net_map.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/web.xml10
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.js3930
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js56
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.js)102
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js14
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.js321
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js.map (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js.map)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-csp.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-csp.css)1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.js)49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js)10
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js.map (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js.map)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.js)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js.map (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js.map)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.js)12
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js12
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-mocks.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-mocks.js)441
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.js)158
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js14
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.js991
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js15
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.js683
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js16
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-scenario.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-scenario.js)2956
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.js628
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js13
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.js29018
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js295
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js.map8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/errors.json1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-dj.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-er.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-et.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-na.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-za.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak-gh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am-et.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-001.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ae.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-bh.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dj.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eh.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-er.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-il.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-iq.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-jo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-km.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-kw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-lb.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ly.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ma.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-mr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-om.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ps.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-qa.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sa.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sd.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-so.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ss.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-td.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-tn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ye.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast-es.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl-az.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn-az.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be-by.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem-zm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg-bg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn-ml.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-ml.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-bd.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-cn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br-fr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl-ba.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn-ba.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn-er.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-ad.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es-valencia.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-fr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-it.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr-us.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-iq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-ir.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-iq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-ir.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn-iq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs-cz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy-gb.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-dk.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-gl.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-at.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-be.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-ch.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-de.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-li.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-lu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje-ne.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb-de.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo-sn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz-bt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-gh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-tg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-cy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-gr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-001.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-150.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ag.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ai.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-as.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-au.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-be.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bs.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ca.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ck.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cx.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-er.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fj.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gy.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-hk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ie.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-im.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-io.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-iso.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-je.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-jm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ki.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-kn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ky.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ls.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mp.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ms.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-my.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-na.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nf.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ng.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ph.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-rw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ss.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sx.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-to.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-um.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-us.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ws.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo-001.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-419.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ar.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-bo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-co.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-do.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ea.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ec.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-es.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gq.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-hn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ic.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-mx.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ni.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pa.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pe.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ph.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-py.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-sv.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-us.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-uy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ve.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et-ee.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu-es.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-af.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-ir.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-gn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-mr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-sn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi-fi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil-ph.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo-fo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-be.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bi.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bj.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ca.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cd.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ch.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ci.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cm.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dj.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-fr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ga.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gp.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gq.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ht.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-km.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-lu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ma.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mc.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ml.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mq.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-nc.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ne.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pm.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-re.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-rw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sc.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-td.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-vu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-wf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-yt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur-it.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy-nl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga-ie.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd-gb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl-es.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-ch.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-fr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-li.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv-im.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-gh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ne.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ng.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw-us.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he-il.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-ba.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-hr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb-de.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu-hu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy-am.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia-fr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id-id.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig-ng.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii-cn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is-is.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-ch.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-it.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-sm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_iw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja-jp.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka-ge.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab-dz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea-cv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq-ml.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl-kz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl-gl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km-kh.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kp.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh-de.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw-gb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl-kg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb-lu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt-us.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-ao.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cd.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cf.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo-la.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt-lt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu-cd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv-lv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe-mu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg-mg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh-mz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk-mk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl-mn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-bn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-my.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-sg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt-mt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my-mm.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq-na.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-no.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-sj.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd-zw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-np.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-aw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-be.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-bq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-cw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-nl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sx.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn-no.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no-no.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus-sd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-et.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ge.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ru.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab-pk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl-pl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps-af.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-ao.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-br.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-cv.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-gw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-pt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-st.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-tl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-bo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-ec.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-pe.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm-ch.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn-bi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-md.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-ro.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-by.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-md.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ru.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ua.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw-rw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah-ru.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-fi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-no.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-se.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh-mz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses-ml.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg-cf.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn-ma.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng-ma.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si-lk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk-sk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl-si.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn-fi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn-zw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-dj.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-et.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-so.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-al.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-mk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-xk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-ba.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-me.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-rs.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-xk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-ba.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-me.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-rs.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-xk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-sz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy-er.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-ls.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-za.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-ax.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-fi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-se.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-cd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc-cd.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-lk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-my.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-sg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te-in.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ke.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl-tj.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th-th.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-er.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-et.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig-er.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tl.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-bw.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to-to.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-cy.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-tr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq-ne.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn-ma.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab-cn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk-ua.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-in.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-pk.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab-af.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl-uz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn-uz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn-lr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii-lr.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve-za.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi-vn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo-001.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun-tz.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae-ch.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal-et.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh-za.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh.js115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog-ug.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav-cm.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi-001.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-bj.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-ng.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh-ma.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh.js128
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-cn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-cn.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-hk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-mo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-sg.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-hk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-mo.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-tw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hk.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-tw.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu-za.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.json1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.txt1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/index.js2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css115
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.js7776
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js10
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.js7412
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.min.js10
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.css145
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.css1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.js8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.js2239
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.less167
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/index.js2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.css2005
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.eotbin0 -> 10320 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.js28935
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.css4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.js15
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.svg56
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.ttfbin0 -> 10156 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.woffbin0 -> 5728 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-sortable/v0.13.4/sortable.min.js8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/README.md26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/b2b-angular.css11827
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/horse_shoe.jpgbin0 -> 16573 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/icon-flyout.pngbin0 -> 947 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/treebg.pngbin0 -> 82 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/widget-thumbnail.pngbin0 -> 1929 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js22054
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/horse_shoe.jpgbin0 -> 16573 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/icon-flyout.pngbin0 -> 947 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/treebg.pngbin0 -> 82 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/widget-thumbnail.pngbin0 -> 1929 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/styles/images/icon-flyout.pngbin0 -> 947 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/bootstrap/bs.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/bootstrap/bs.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/css/nv.d3.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/css/nv.d3.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/cie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/cie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/core.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/core.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.geom.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.geom.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/fisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/fisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/hive.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/hive.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/horizon.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/horizon.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/intro.js2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bullet.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bullet.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/distribution.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/distribution.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/legend.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/legend.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/line.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/line.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/outro.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/outro.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/sankey.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/sankey.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/tooltip.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/tooltip.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/utils.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/utils.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ds2/js/appDS2.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ebz/copyrighted-material-removed.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/gis/js/local.js178
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/detect-element-resize.js147
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/jquery.resize.js164
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/.bower.json25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.js9814
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.js4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.map1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.css478
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.js9
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js14932
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/images/blank.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/images/blank.gif)bin49 -> 49 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/scribble.css40
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/slider.css142
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/spacegallery.css18
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/area_chart.html49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/bar_chart.html95
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/busy_hour_traffic.html188
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/d3_gauges_demo.html39
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer2.csv16
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer3.csv2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/worddata.csv (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/worddata.csv)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/donut_d3.html43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/area_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/donut.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/gauges.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/line_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/pie_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/worddata.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/line_chart.html49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/pie_chart.html38
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/traffic_distribution.html205
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/wordcloud.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/wordcloud.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/Calendar-16x16.pngbin0 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-next.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-next.png)bin1561 -> 1561 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-prev.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-prev.png)bin1557 -> 1557 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_drive_test_map.pngbin0 -> 202465 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_county.pngbin0 -> 21222 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_regression.pngbin0 -> 11536 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_ios_throughput.pngbin0 -> 26131 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map.pngbin0 -> 192031 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map_legend.pngbin0 -> 3021 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_nova_sdn_map.pngbin0 -> 179361 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/copyicon.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/copyicon.png)bin235 -> 235 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/deleteicon.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/deleteicon.gif)bin579 -> 579 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/example-frame.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/example-frame.png)bin33699 -> 33699 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/loading.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/loading.gif)bin6820 -> 6820 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/1_mon.pngbin0 -> 22762 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/2_tue.pngbin0 -> 22772 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/3_wed.pngbin0 -> 24012 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/4_thu.pngbin0 -> 23902 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/5_fri.pngbin0 -> 22349 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/6_sat.pngbin0 -> 23674 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/7_sun.pngbin0 -> 22845 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_IN.pngbin0 -> 10575 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_OUT.pngbin0 -> 10460 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat.pngbin0 -> 10420 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Def.pngbin0 -> 8941 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Priority.pngbin0 -> 10590 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/FusionCharts.js361
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/charts.js132
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/eye.js34
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/scribble.js19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/slides.min.jquery.js20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/spacegallery.js235
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/utils.js252
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/bootstrap.min.css351
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/custom.css97
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/jquery.jOrgChart.css51
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/prettify.css1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example.html85
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example_vsp.html88
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/bkgd.pngbin0 -> 133 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/raspberry.jpgbin0 -> 5755 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/jquery.jOrgChart.js267
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/prettify.js28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/showdown/0.3.4/showdown.js1454
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/utils/js/browserCheck.js5
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/fonts/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js15
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js97
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js81
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html65
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html7
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm33
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html70
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-closed-cloop.js28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-controller.js940
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-menu-edit.js184
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-route.js43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-whitelist.js3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate-list-controller.js71
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/collaborate.js7
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/workflowController.js490
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborateList-route.js19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaboration-controller.js266
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-profile/self-profile-controller.js358
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-import-controller.js20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-router.js37
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-run-controller.js326
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-search-controller.js184
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-step-controller.js900
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/drools-controller.js53
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js15
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebook-controller.js170
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js85
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowApp.js5
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowController.js513
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowRouting.js8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js339
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-route.js19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-search-controller-DS2.js64
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/sampleProfileController.js22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/usage-list-controller.js39
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-controller.js408
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-route.js7
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js64
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2Header.js152
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2LeftMenu.js89
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/footer.js27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/error_modal.html19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modal.html20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modalpopup.html20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminMenuService.js129
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminService.js453
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-modal/modalService.js38
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-profile/selfProfileService.js114
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/raptorReportFactory.js331
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/stepFormFactory.js198
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-sample-page/droolsService.js53
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/headerServiceDS2.js483
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/leftMenuServiceDS2.js110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/manifestService.js24
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalService.js57
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalServiceDS2.js31
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/profileServiceDS2.js78
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/sampleService.js19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/userInfoServiceDS2.js32
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-landing.html66
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html65
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html110
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-preview.html24
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-remove.html26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-schedule.html130
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/b2b-leftnav-ext.html43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html102
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin.html66
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin_closed_loop.html17
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html76
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaboration.html182
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html73
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/admin-menu-del-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-region-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/clearItem-region-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/collaborate-list-toggle-profile-active-status.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fn-menu-edit.html129
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html136
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-child-add-confirm.html25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-confirm-activation.html23
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-delete-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-add-confirm.html25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-role-del-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-add.html32
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-del-confirm.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-edit.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-child-roles-modal.html34
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-modal.html36
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html63
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role.html96
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html42
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/usage.html43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add-confirm.html25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add.html36
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-del-confirm.html23
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile.html67
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/all-reports.html74
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/dynamicform.js113
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/step-form-directive.js14
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-del-confirm.html26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-formfield-del-confirm.html26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-col-edit.html125
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html149
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html62
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-import.html14
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-run.html91
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html54
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step1.json218
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step2.json34
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step3.json19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step4.json25
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step5.json28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html101
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools-list.html32
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools.html55
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/frame_insert.html27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-frame.html74
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html80
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-viz.html7
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Header.html69
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Left_menu.html3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/loginSnippet.html63
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-content.html191
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-sample.html112
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome.html151
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-closed-cloop.js28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-whitelist.js3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js60
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js)19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js44
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js21
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/footer.js11
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/header.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/header.js)77
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/leftMenu.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/leftMenu.js)41
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/jquery.resize.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/jquery.resize.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/debug.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/debug.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/modalService.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/modalService.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/moment.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/moment.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/network/net_map.js947
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/adminService.js141
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/headerService.js70
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/leftMenuService.js35
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/profileService.js79
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/userInfoService.js32
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js103
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/directives/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/utils/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/header.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/header.html)36
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/left_menu.html27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_closed_loop.html20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html42
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html52
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html)21
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html)19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html)19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html75
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html27
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/customWidgetSettings.js133
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/dataModel.js58
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.js167
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.less24
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/directives.js230
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/explicitSave.js33
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.css146
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.js3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.less16
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index_original.css113
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/layouts.js72
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/report_whitelist.js3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/resize.js45
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/configurableWidgetModalOptions.html6
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/customSettingsTemplate.html19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/fluid.html8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/r-cloud.html8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html29
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/resizable.html6
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html5
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/widgetSpecificSettings.html19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css6658
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.less3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/angular-markdown-directive/markdown.js36
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsCtrl.js34
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsRaptorReportCtrl.js215
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-raptor-report-template.html26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-rcloud-notebook-template.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/altDashboard.html49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html74
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.js427
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.less88
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.spec.js878
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-raptor-report-template.html58
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html22
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModal.html13
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModalCtrl.js32
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.html19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.js151
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.spec.js392
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.js246
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.spec.js164
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.js64
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.spec.js104
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/DashboardState.js180
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.js253
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.spec.js692
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDataModel.js45
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDefCollection.js56
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.js112
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.spec.js156
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/report-dashboard.html220
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/ecomp.css135
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/fusion-sunny.css362
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/global.css178
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/jquery-ui.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/jquery-ui.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/bs-workflow.css134
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/workflows.css31
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js45
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/droolsController.js11
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/directives/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/external/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/services/droolsService.js57
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/utils/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/fonts/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html)26
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html42
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/images/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/external/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/fonts/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-icon.pngbin0 -> 465 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-text.pngbin0 -> 295 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-icon.pngbin0 -> 565 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-text.pngbin0 -> 632 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-icon.pngbin0 -> 1065 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-text.pngbin0 -> 901 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-text.pngbin0 -> 650 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-text.pngbin0 -> 780 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-text.pngbin0 -> 645 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/com-icon.pngbin0 -> 437 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-icon.pngbin0 -> 201 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-text.pngbin0 -> 572 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/default-icon.pngbin0 -> 329 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-icon.pngbin0 -> 700 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-text.pngbin0 -> 820 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-icon.pngbin0 -> 700 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-text.pngbin0 -> 851 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-icon.pngbin0 -> 774 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-text.pngbin0 -> 739 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-icon.pngbin0 -> 437 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-text.pngbin0 -> 439 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-text.pngbin0 -> 604 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/emsc-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-icon.pngbin0 -> 1127 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-text.pngbin0 -> 627 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-text.pngbin0 -> 551 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-text.pngbin0 -> 701 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-icon.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-text.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-text.pngbin0 -> 755 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-text.pngbin0 -> 376 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-text.pngbin0 -> 726 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-text.pngbin0 -> 757 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-text.pngbin0 -> 657 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-icon.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-text.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-text.pngbin0 -> 649 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-icon.pngbin0 -> 696 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-text.pngbin0 -> 595 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-icon.pngbin0 -> 953 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-text.pngbin0 -> 638 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrg-rdf-text.pngbin0 -> 769 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-text.pngbin0 -> 771 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-text.pngbin0 -> 1140 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-text.pngbin0 -> 823 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-text.pngbin0 -> 550 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-icon.pngbin0 -> 232 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-text.pngbin0 -> 252 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-icon.pngbin0 -> 437 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-text.pngbin0 -> 504 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msc-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-icon.pngbin0 -> 465 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-text.pngbin0 -> 318 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/multi-icon.pngbin0 -> 329 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-icon.pngbin0 -> 464 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-text.pngbin0 -> 295 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-icon.pngbin0 -> 393 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-text.pngbin0 -> 258 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-icon.pngbin0 -> 393 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-text.pngbin0 -> 258 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-icon.pngbin0 -> 391 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-text.pngbin0 -> 258 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-icon.pngbin0 -> 391 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-text.pngbin0 -> 258 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-icon.pngbin0 -> 1127 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-text.pngbin0 -> 499 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-icon.pngbin0 -> 700 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-text.pngbin0 -> 596 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-icon.pngbin0 -> 785 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-text.pngbin0 -> 539 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-icon.pngbin0 -> 785 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-text.pngbin0 -> 594 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-text.pngbin0 -> 744 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-text.pngbin0 -> 807 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-icon.pngbin0 -> 953 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-text.pngbin0 -> 735 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/psap-icon.pngbin0 -> 322 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-icon.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-text.pngbin0 -> 95 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-text.pngbin0 -> 540 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-icon.pngbin0 -> 591 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-text.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-text.pngbin0 -> 632 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-icon.pngbin0 -> 437 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-text.pngbin0 -> 861 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-icon.pngbin0 -> 855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-text.pngbin0 -> 704 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-icon.pngbin0 -> 491 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-text.pngbin0 -> 696 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-icon.pngbin0 -> 230 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-text.pngbin0 -> 469 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-icon.pngbin0 -> 388 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-text.pngbin0 -> 884 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-icon.pngbin0 -> 774 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-text.pngbin0 -> 753 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-icon.pngbin0 -> 286 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-text.pngbin0 -> 418 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-icon.pngbin0 -> 646 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-text.pngbin0 -> 1011 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/switch-icon.pngbin0 -> 877 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-icon.pngbin0 -> 437 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-text.pngbin0 -> 858 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-icon.pngbin0 -> 774 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-text.pngbin0 -> 1242 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ue-icon.pngbin0 -> 577 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/uephone-icon.pngbin0 -> 1190 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-icon.pngbin0 -> 1065 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-text.pngbin0 -> 826 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/images/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js61
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js11
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/styles/dummy.txt)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/styles/dummy.txt0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/index.jsp24
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/manifest.jsp (renamed from ecomp-sdk/sdk-app/src/main/webapp/manifest.jsp)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css173
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/fusion-sunny.css362
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/css/nv.d3.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/css/nv.d3.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/cie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/cie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/colorbrewer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/colorbrewer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/core.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/core.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.geom.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.geom.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/fisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/fisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/hive.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/hive.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/horizon.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/horizon.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/interactiveLayer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/interactiveLayer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/intro.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/intro.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis-min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis-min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/boilerplate.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/boilerplate.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bullet.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bullet.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bulletChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bulletChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/distribution.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/distribution.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/indentedTree.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/indentedTree.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/legend.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/legend.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/line.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/line.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pieChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pieChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparkline.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparkline.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedArea.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedArea.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/outro.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/outro.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/sankey.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/sankey.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/tooltip.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/tooltip.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/utils.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/utils.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/gis/js/local.js178
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js2244
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js168
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/jquery.resize.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/jquery.resize.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/debug.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/debug.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/moment.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/moment.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Entries9
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Repository1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Root0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Tag1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/Style.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/Style.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/calendar.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/calendar.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/dashboard.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/dashboard.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/drupal.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/drupal.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/novamap.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/novamap.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/picker.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/picker.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/ral.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/ral.css)2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/raptor.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/raptor.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/context-menu.css57
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/drag-drop-folder-tree.css64
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/cie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/cie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/core.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/core.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/hive.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/hive.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/horizon.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/horizon.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/intro.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/intro.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/line.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/line.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/outro.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/outro.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/sankey.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/sankey.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/utils.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/utils.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/data.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/data.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/moment.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/moment.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/multiselect.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/multiselect.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/quick_links.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/quick_links.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.html)19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.js)45
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.html (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.html)3
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.js)8
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ATT_Business_logo.gifbin0 -> 8203 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/RAPTOR_BANNER.jpgbin0 -> 6249 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/accessicon.gifbin0 -> 329 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/active.gifbin0 -> 338 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/addbtn.pngbin0 -> 662 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ajax-loader.gifbin0 -> 673 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add.gifbin0 -> 469 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_edge.gifbin0 -> 564 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_multiple.gifbin0 -> 748 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_one.gifbin0 -> 631 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_back.gifbin0 -> 621 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_cancel.gifbin0 -> 652 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left.gifbin0 -> 382 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left2.gifbin0 -> 399 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_next.gifbin0 -> 609 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_plus.gifbin0 -> 67 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.gifbin0 -> 686 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.pngbin0 -> 29837 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right.gifbin0 -> 381 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right2.gifbin0 -> 399 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_save.gifbin0 -> 606 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/att-globe1.jpgbin0 -> 5855 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/button_import.pngbin0 -> 546 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon.gifbin0 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav.gifbin0 -> 538 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav1.gifbin0 -> 1065 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calender_icon.gifbin0 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankdown.gifbin0 -> 192 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankup.gifbin0 -> 193 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columndown.gifbin0 -> 124 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnup.gifbin0 -> 126 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/crosshairs.pngbin0 -> 218 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/csv_icon.gifbin0 -> 447 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/deleteicon.gifbin0 -> 80 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/downloadicon.gifbin0 -> 74 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.jpgbin0 -> 761 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.pngbin0 -> 3186 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon.gifbin0 -> 1055 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon_multi.gifbin0 -> 1026 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow-right.gifbin0 -> 201 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow.gifbin0 -> 195 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowdn.gifbin0 -> 74 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowup.gifbin0 -> 106 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/h.pngbin0 -> 380 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/inactive.gifbin0 -> 352 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loader.gifbin0 -> 958 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loading.gifbin0 -> 4176 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/lookup_arrow.gifbin0 -> 645 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/blue.pngbin0 -> 1309 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/green.pngbin0 -> 1190 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/lightblue.pngbin0 -> 1269 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/map_iphone.jpgbin0 -> 712 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/orange.pngbin0 -> 3413 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/pink.pngbin0 -> 1321 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/purple.pngbin0 -> 1324 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/red.pngbin0 -> 1305 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/yellow.pngbin0 -> 1309 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/minus.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/minus.gif)bin75 -> 75 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/modify_icon.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/modify_icon.gif)bin246 -> 246 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/page.gifbin0 -> 554 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_large.gifbin0 -> 434 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_small.gifbin0 -> 361 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pen_paper.gifbin0 -> 618 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/plus.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/plus.gif)bin78 -> 78 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/popupicon.gifbin0 -> 79 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/position.pngbin0 -> 267 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/printer.gifbin0 -> 1019 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/progress.gifbin0 -> 734 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/question_mark.jpgbin0 -> 426 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_dk.gifbin0 -> 155 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_lt.gifbin0 -> 897 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/r_back.gifbin0 -> 918 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor.jpgbin0 -> 889 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.gifbin0 -> 3150 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.jpgbin0 -> 1827 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/required.gifbin0 -> 854 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/shareicon.gifbin0 -> 542 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/sv.pngbin0 -> 11373 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left.gifbin0 -> 137 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left_sel.gifbin0 -> 106 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right.gifbin0 -> 138 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right_sel.gifbin0 -> 104 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/test_run.gifbin0 -> 330 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/text.gifbin0 -> 141 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/context-menu-gradient.gifbin0 -> 807 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_folder.gifbin0 -> 1120 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_minus.gifbin0 -> 197 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_plus.gifbin0 -> 200 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet.gifbin0 -> 906 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_crosstab.gifbin0 -> 1144 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_dashboard.gifbin0 -> 1164 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_graph.gifbin0 -> 983 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind1.gifbin0 -> 53 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind2.gifbin0 -> 56 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_close.gifbin0 -> 283 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_dots.gifbin0 -> 68 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_folder.gifbin0 -> 980 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_lastsub.gifbin0 -> 78 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_open.gifbin0 -> 286 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_sub.gifbin0 -> 265 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowleft.gifbin0 -> 854 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowright.gifbin0 -> 845 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/txt_icon.gifbin0 -> 154 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF033.pngbin0 -> 520 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF034.pngbin0 -> 536 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF035.pngbin0 -> 487 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF036.pngbin0 -> 482 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/BorderLayout-24x24.pngbin0 -> 1369 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/Calendar-16x16.pngbin0 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/DeleteCross-16x16.pngbin0 -> 750 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/addbtn.pngbin0 -> 662 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/button_import.pngbin0 -> 546 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon-highlighted.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon-highlighted.png)bin264 -> 264 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon.pngbin0 -> 235 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/cross-small.pngbin0 -> 291 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.gifbin0 -> 447 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.jpg (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.jpg)bin632 -> 632 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.png)bin938 -> 938 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.gif)bin592 -> 592 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.png)bin566 -> 566 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon.gifbin0 -> 579 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/downloadicon.gifbin0 -> 74 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/editicon.gif (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/editicon.gif)bin360 -> 360 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excel2007.jpgbin0 -> 761 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon.gifbin0 -> 1055 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon_multi.gifbin0 -> 1026 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/executeicon.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/executeicon.png)bin1076 -> 1076 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/file_import.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_import.png)bin653 -> 653 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pdficon_small.gifbin0 -> 361 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pen_paper.gifbin0 -> 618 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pencil-small.pngbin0 -> 309 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-add.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-add.png)bin724 -> 724 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-favorite.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-favorite.png)bin693 -> 693 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-my.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-my.png)bin739 -> 739 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-public.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-public.png)bin776 -> 776 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report.png)bin563 -> 563 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/reports.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/reports.png)bin769 -> 769 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.gifbin0 -> 223 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.png (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search.png)bin3501 -> 3501 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/tick-small.pngbin0 -> 283 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/cingular_button.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/cingular_button.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/drupal.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/drupal.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/editabledropdown.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/editabledropdown.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/gmap.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/gmap.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/label_quantum.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/label_quantum.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/nova_button.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/nova_button.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/other_scripts.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/other_scripts.js)4
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/persist_table_header.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/persist_table_header.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/projected_overlay.js129
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/raptor.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/raptor.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/rounded-corners.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/rounded-corners.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/script.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/script.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/ajax.js194
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/context-menu.js444
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/drag-drop-folder-tree.js1059
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot)bin8728 -> 8728 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js26735
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf)bin8564 -> 8564 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff)bin4792 -> 4792 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/flexslider.css275
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eotbin0 -> 2082 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttfbin0 -> 1892 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woffbin0 -> 1268 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/images/blank.gifbin0 -> 49 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/scribble.css40
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/slider.css142
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/spacegallery.css18
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/welcome.css173
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/area_chart.html49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/bar_chart.html95
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html39
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv16
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv2
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/worddata.csv1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/donut_d3.html43
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/donut.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/gauges.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/worddata.min.js1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/line_chart.html49
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/pie_chart.html38
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/wordcloud.html36
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/Calendar-16x16.pngbin0 -> 552 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-next.pngbin0 -> 1561 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-prev.pngbin0 -> 1557 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.pngbin0 -> 202465 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.pngbin0 -> 21222 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.pngbin0 -> 11536 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.pngbin0 -> 26131 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.pngbin0 -> 192031 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.pngbin0 -> 3021 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.pngbin0 -> 179361 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/copyicon.pngbin0 -> 235 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/deleteicon.gifbin0 -> 579 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/example-frame.pngbin0 -> 33699 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/loading.gifbin0 -> 6820 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.pngbin0 -> 22762 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.pngbin0 -> 22772 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.pngbin0 -> 24012 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.pngbin0 -> 23902 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.pngbin0 -> 22349 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.pngbin0 -> 23674 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.pngbin0 -> 22845 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.pngbin0 -> 10575 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.pngbin0 -> 10460 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.pngbin0 -> 10420 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.pngbin0 -> 8941 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.pngbin0 -> 10590 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/FusionCharts.js361
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/charts.js132
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/eye.js34
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js5
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/scribble.js19
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js20
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/spacegallery.js235
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/utils.js252
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css351
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/custom.css97
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css51
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css1
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example.html85
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html88
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.pngbin0 -> 133 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpgbin0 -> 5755 bytes
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js267
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/prettify.js28
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-1.10.2.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-1.10.2.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-ui.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-ui.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery.mask.min.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery.mask.min.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/modalService.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/js/modalService.js)0
-rw-r--r--ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/search.js (renamed from ecomp-sdk/sdk-app/src/main/webapp/static/js/search.js)3
-rw-r--r--ecomp-sdk/epsdk-core/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-core/README.md168
-rw-r--r--ecomp-sdk/epsdk-core/license/licenses.properties1
-rw-r--r--ecomp-sdk/epsdk-core/license/my_license/header.txt11
-rw-r--r--ecomp-sdk/epsdk-core/license/my_license/license.txt4
-rw-r--r--ecomp-sdk/epsdk-core/pom.xml406
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/FusionObject.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/FusionObject.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/auth/LoginStrategy.java131
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java193
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java)3
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java67
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java)20
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java139
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java43
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java)1
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java)1
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/App.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/App.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java106
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java124
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java187
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java85
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java)11
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java)19
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Role.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Role.java)14
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/User.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/User.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java)3
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java)18
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java)15
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java)3
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java1209
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java)13
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java)12
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManager.java60
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManagerUtils.java74
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/LicenseableClass.java38
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java32
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java234
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java484
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java)35
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java)17
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java)28
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java)6
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java)85
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java)1
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java)4
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java)3
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java)14
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java)8
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java290
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java1029
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java)20
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java)20
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java36
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java)41
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java)11
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java)11
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java207
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java)74
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java116
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java105
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java)2
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java327
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java)5
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java213
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java)0
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java (renamed from ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java)3
-rw-r--r--ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java423
-rw-r--r--ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockApplicationContextTestSuite.java114
-rw-r--r--ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockHibernateMappingLocations.java23
-rw-r--r--ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockApplicationContextTestSuite.java143
-rw-r--r--ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockHibernateMappingLocations.java42
-rw-r--r--ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/controller/sessionmgt/PortalCommunicationTest.java75
-rw-r--r--ecomp-sdk/epsdk-fw/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-fw/README.md111
-rw-r--r--ecomp-sdk/epsdk-fw/pom.xml87
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java175
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java)3
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java)2
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java618
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunicationService.java161
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/exception/PortalAPIException.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIException.java)7
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutBindingListener.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutBindingListener.java)5
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutHandler.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutHandler.java)55
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserContextListener.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserContextListener.java)8
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserSessionListener.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserSessionListener.java)5
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java)4
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java)4
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java342
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/CipherUtil.java125
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiConstants.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiConstants.java)8
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiProperties.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiProperties.java)16
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOFilter.java75
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOUtil.java45
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java)4
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java)2
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/PortalTimeoutVO.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutVO.java)6
-rw-r--r--ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java (renamed from ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java)4
-rw-r--r--ecomp-sdk/epsdk-workflow/.gitignore5
-rw-r--r--ecomp-sdk/epsdk-workflow/README.md18
-rw-r--r--ecomp-sdk/epsdk-workflow/pom.xml114
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java)3
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java)3
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java)16
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java)1
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java)2
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java)1
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java)2
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java16
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java (renamed from ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java)0
-rw-r--r--ecomp-sdk/epsdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml (renamed from ecomp-sdk/sdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml)0
-rw-r--r--ecomp-sdk/pom.xml141
-rw-r--r--ecomp-sdk/quantum/.gitignore1
-rw-r--r--ecomp-sdk/quantum/README.md11
-rw-r--r--ecomp-sdk/quantum/pom.xml330
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java196
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java58
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java155
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java28
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AdminAuthGenericController.java134
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CacheAdminController.java252
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ElementModelController.java91
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ExternalLoginController.java121
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FnMenuController.java224
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/MenuListController.java245
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileSearchController.java149
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleController.java332
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleFunctionListController.java184
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java79
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java123
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java187
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java85
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java991
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java32
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java193
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java323
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java269
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java915
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java36
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java203
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java210
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java74
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CipherUtil.java125
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncTest.java39
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java279
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java195
-rw-r--r--ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java373
-rw-r--r--ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java127
-rw-r--r--ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockHibernateMappingLocations.java20
-rw-r--r--ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/controller/sessionmgt/PortalCommunicationTest.java56
-rw-r--r--ecomp-sdk/sdk-analytics/.gitignore2
-rw-r--r--ecomp-sdk/sdk-analytics/README.md8
-rw-r--r--ecomp-sdk/sdk-analytics/pom.xml160
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java89
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java112
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java82
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartGen.java73
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java43
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java213
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java333
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java1298
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java66
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java363
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java75
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java85
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java191
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java410
-rw-r--r--ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java445
-rw-r--r--ecomp-sdk/sdk-app/.gitignore1
-rw-r--r--ecomp-sdk/sdk-app/README.md14
-rw-r--r--ecomp-sdk/sdk-app/db-scripts/EcompSdkDDLMySql_1610_Complete_OS.sql1402
-rw-r--r--ecomp-sdk/sdk-app/db-scripts/EcompSdkDMLMySql_1610_Complete_OS.sql2891
-rw-r--r--ecomp-sdk/sdk-app/distribution.xml21
-rw-r--r--ecomp-sdk/sdk-app/pom.xml361
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java60
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java37
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/PostDroolsController.java138
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java34
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/InitUebHandler.java73
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/MainUebHandler.java104
-rw-r--r--ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/WidgetNotificationHandler.java46
-rw-r--r--ecomp-sdk/sdk-app/src/main/resources/portal.properties69
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties39
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_pdf.properties49
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/system.properties86
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/defs/definitions.xml22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/conf/fusion.properties61
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/defs/definitions.xml240
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/collaborateList.jsp146
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html120
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/jcs_admin.jsp144
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/post_search.jsp356
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile.jsp442
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile_search.jsp104
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role.jsp286
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_function_list.jsp213
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_list.jsp139
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/usage_list.jsp87
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/leafletMap.jsp288
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/login_external.jsp154
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/user_profile.jsp84
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/welcome.jsp630
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/web.xml17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.js4121
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js56
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.js322
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.js1016
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.js717
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.js729
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.js30428
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js307
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js.map8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/errors.json1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.json1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.txt1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-animate.js3721
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-cookies.js206
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.js911
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.min.js14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-sanitize.js647
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-touch.js628
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular.js22024
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/app.js6
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.js99
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.min.js1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/gestures.js1495
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ng_base.js4
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ui-charts-tpls.js3909
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/footer.css311
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/header.css1866
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/portal_ebz_header.css63
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/fn-ebz.css1614
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/images/no_favorites_star.pngbin2794 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/attHeaderSnippet.js210
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/footer.js110
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.js20451
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.min.js22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/base.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/btn.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/demo.css2
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/dtpk.css9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/frms.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/ie/backgroundsize.min.htc12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/images/upanddown.pngbin1033 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/pages/iconography.css2
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/sldr.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/style.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/tbs.css1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/.gitignore4
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/LICENSE21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/bower.json31
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/component.json19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/composer.json36
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.css1480
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.min.css11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-font.less27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-icons.less1473
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-variables.less747
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/ionicons.less3
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert-circled.pngbin2551 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert.pngbin766 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add-contact.pngbin3279 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add.pngbin240 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-alarm.pngbin6428 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-archive.pngbin1628 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-back.pngbin1218 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-left.pngbin1451 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-right.pngbin1462 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-forward.pngbin1191 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-left.pngbin1499 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-right.pngbin1482 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-battery.pngbin238 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-book.pngbin3746 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-calendar.pngbin849 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-call.pngbin4766 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-camera.pngbin3871 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-chat.pngbin3577 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-checkmark.pngbin1846 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-clock.pngbin5268 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-close.pngbin2156 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contact.pngbin3658 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contacts.pngbin4299 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-data.pngbin4808 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-developer.pngbin4115 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-display.pngbin4909 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-download.pngbin4890 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-drawer.pngbin190 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-dropdown.pngbin777 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-earth.pngbin6517 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-folder.pngbin1688 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-forums.pngbin1739 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-friends.pngbin4868 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-hand.pngbin4650 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-image.pngbin1433 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-inbox.pngbin3018 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-information.pngbin3370 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-keypad.pngbin1055 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-lightbulb.pngbin3515 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-locate.pngbin5003 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-location.pngbin3067 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mail.pngbin3455 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-microphone.pngbin3267 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mixer.pngbin2727 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-more.pngbin224 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-note.pngbin249 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-playstore.pngbin3165 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-printer.pngbin1721 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-promotion.pngbin2374 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-reminder.pngbin2890 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-remove.pngbin160 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-search.pngbin4232 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-send.pngbin2079 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-settings.pngbin3883 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-share.pngbin3212 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social-user.pngbin3644 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social.pngbin3849 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-sort.pngbin197 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stair-drawer.pngbin209 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-star.pngbin2926 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stopwatch.pngbin5225 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-storage.pngbin233 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-back.pngbin1796 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-home.pngbin1107 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-windows.pngbin202 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-timer.pngbin3904 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-trash.pngbin2865 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-user-menu.pngbin3568 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-volume.pngbin6022 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-wifi.pngbin4868 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/aperture.pngbin9500 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/archive.pngbin2445 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-a.pngbin1173 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-b.pngbin1307 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-c.pngbin1966 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-expand.pngbin2498 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-left.pngbin2478 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-right.pngbin2545 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-left.pngbin2440 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-right.pngbin2440 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-a.pngbin1260 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-b.pngbin1608 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-c.pngbin1662 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-move.pngbin1948 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-resize.pngbin1266 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-left.pngbin1082 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-right.pngbin1124 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-a.pngbin1317 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-b.pngbin1671 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-c.pngbin1657 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-shrink.pngbin2594 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-swap.pngbin1521 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-a.pngbin1115 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-b.pngbin1343 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-c.pngbin2002 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/asterisk.pngbin4023 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/at.pngbin5852 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bag.pngbin3665 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-charging.pngbin1897 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-empty.pngbin1019 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-full.pngbin982 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-half.pngbin1320 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-low.pngbin1342 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beaker.pngbin3931 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beer.pngbin4559 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bluetooth.pngbin2909 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bonfire.pngbin4852 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bookmark.pngbin1102 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/briefcase.pngbin1475 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bug.pngbin4736 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calculator.pngbin1315 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calendar.pngbin2577 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/camera.pngbin4190 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/card.pngbin1494 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cash.pngbin3435 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox-working.pngbin2301 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox.pngbin1870 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatboxes.pngbin2562 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble-working.pngbin3028 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble.pngbin2579 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubbles.pngbin3751 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-circled.pngbin3687 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-round.pngbin2367 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark.pngbin2134 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-down.pngbin1689 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-left.pngbin1769 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-right.pngbin1831 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-up.pngbin1677 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clipboard.pngbin2593 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clock.pngbin5866 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-circled.pngbin3809 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-round.pngbin2177 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close.pngbin2244 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/closed-captioning.pngbin3665 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cloud.pngbin2067 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-download.pngbin2423 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-working.pngbin2433 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code.pngbin1720 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/coffee.pngbin3205 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compass.pngbin7318 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compose.pngbin4296 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/connection-bars.pngbin214 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/contrast.pngbin4087 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cube.pngbin3265 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/disc.pngbin4935 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document-text.pngbin1918 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document.pngbin1914 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/drag.pngbin178 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/earth.pngbin6476 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/edit.pngbin2741 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/egg.pngbin4234 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eject.pngbin3209 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/email.pngbin3125 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye-disabled.pngbin3558 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye.pngbin3297 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/female.pngbin2779 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/filing.pngbin2349 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/film-marker.pngbin2645 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fireball.pngbin3325 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flag.pngbin2337 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flame.pngbin3012 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash-off.pngbin5437 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash.pngbin1965 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flask.pngbin2939 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/folder.pngbin1689 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork-repo.pngbin3236 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork.pngbin3007 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/forward.pngbin2142 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/funnel.pngbin3354 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-a.pngbin2548 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-b.pngbin3623 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-a.pngbin3806 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-b.pngbin2756 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/grid.pngbin1066 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/hammer.pngbin2493 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/happy.pngbin5732 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/headphone.pngbin4082 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart-broken.pngbin4007 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart.pngbin2322 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-buoy.pngbin5824 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-circled.pngbin3940 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help.pngbin2678 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/home.pngbin1275 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icecream.pngbin2317 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus-outline.pngbin4071 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus.pngbin3888 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/image.pngbin2952 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/images.pngbin5073 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information-circled.pngbin3300 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information.pngbin2236 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ionic.pngbin5541 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm-outline.pngbin5769 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm.pngbin3922 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums-outline.pngbin231 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums.pngbin226 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball-outline.pngbin5767 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball.pngbin5675 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics-outline.pngbin5847 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics.pngbin4406 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-back.pngbin881 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-down.pngbin1451 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-forward.pngbin898 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-left.pngbin1550 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-right.pngbin1537 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-down.pngbin1632 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-left.pngbin1258 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-right.pngbin1235 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-up.pngbin1647 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-up.pngbin1482 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at-outline.pngbin4303 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at.pngbin4153 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode-outline.pngbin233 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode.pngbin219 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball-outline.pngbin6676 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball.pngbin5565 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball-outline.pngbin6200 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball.pngbin6525 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell-outline.pngbin3615 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell.pngbin2769 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt-outline.pngbin2384 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt.pngbin1892 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks-outline.pngbin2454 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks.pngbin2172 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box-outline.pngbin1602 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box.pngbin1032 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase-outline.pngbin1359 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase.pngbin1316 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers-outline.pngbin372 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers.pngbin357 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator-outline.pngbin1785 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator.pngbin1500 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar-outline.pngbin236 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar.pngbin230 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera-outline.pngbin3582 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera.pngbin3099 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart-outline.pngbin2861 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart.pngbin2200 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes-outline.pngbin901 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes.pngbin512 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble-outline.pngbin3640 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble.pngbin2259 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-empty.pngbin920 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-outline.pngbin4706 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark.pngbin3080 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-filled.pngbin6478 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-outline.pngbin4120 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock-outline.pngbin4320 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock.pngbin2762 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-empty.pngbin1204 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-outline.pngbin4999 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close.pngbin3426 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download-outline.pngbin3953 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download.pngbin2782 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-outline.pngbin3339 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload-outline.pngbin3927 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload.pngbin2815 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud.pngbin2082 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night-outline.pngbin3814 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night.pngbin2870 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-outline.pngbin2280 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy.pngbin1572 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog-outline.pngbin8008 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog.pngbin6029 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose-outline.pngbin1584 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose.pngbin2061 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact-outline.pngbin4846 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact.pngbin4218 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy-outline.pngbin927 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy.pngbin782 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download-outline.pngbin1163 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download.pngbin1135 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-drag.pngbin165 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email-outline.pngbin2592 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email.pngbin4167 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-expand.pngbin485 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye-outline.pngbin4381 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye.pngbin2973 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward-outline.pngbin2726 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward.pngbin2158 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing-outline.pngbin2041 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing.pngbin1933 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film-outline.pngbin772 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film.pngbin722 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag-outline.pngbin1928 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag.pngbin1483 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder-outline.pngbin1606 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder.pngbin1640 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football-outline.pngbin6266 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football.pngbin5391 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear-outline.pngbin5721 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear.pngbin3445 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses-outline.pngbin3597 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses.pngbin2350 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart-outline.pngbin3097 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart.pngbin2078 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-empty.pngbin1669 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-outline.pngbin5608 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help.pngbin3587 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home-outline.pngbin1710 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home.pngbin1518 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite-outline.pngbin3028 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite.pngbin2989 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-empty.pngbin837 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-outline.pngbin4563 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information.pngbin2959 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-ionic-outline.pngbin5780 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad-outline.pngbin7485 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad.pngbin7505 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb-outline.pngbin3791 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb.pngbin2696 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location-outline.pngbin4116 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location.pngbin2767 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked-outline.pngbin2640 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked.pngbin2674 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop-strong.pngbin4101 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop.pngbin4270 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit-outline.pngbin1386 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit.pngbin1373 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-off.pngbin7597 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-outline.pngbin3550 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic.pngbin3878 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-empty.pngbin153 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-outline.pngbin4137 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus.pngbin2520 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor-outline.pngbin225 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor.pngbin230 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon-outline.pngbin2566 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon.pngbin1784 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more-outline.pngbin1598 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more.pngbin1700 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-note.pngbin1521 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-notes.pngbin2124 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate-outline.pngbin4901 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate.pngbin3333 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper-outline.pngbin1361 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper.pngbin1197 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane-outline.pngbin2952 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane.pngbin4805 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny-outline.pngbin4823 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny.pngbin4052 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause-outline.pngbin227 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause.pngbin213 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw-outline.pngbin6318 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw.pngbin4119 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people-outline.pngbin5295 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people.pngbin3439 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person-outline.pngbin3189 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person.pngbin2046 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd-outline.pngbin3246 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd.pngbin2110 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos-outline.pngbin234 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos.pngbin226 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie-outline.pngbin4549 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie.pngbin3646 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play-outline.pngbin1474 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play.pngbin1216 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-empty.pngbin204 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-outline.pngbin4415 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus.pngbin2970 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag-outline.pngbin3007 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag.pngbin2593 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags-outline.pngbin3563 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags.pngbin3219 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer-outline.pngbin1764 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer.pngbin1456 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse-strong.pngbin3326 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse.pngbin2955 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy-outline.pngbin3346 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy.pngbin2567 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording-outline.pngbin4926 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording.pngbin3762 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo-outline.pngbin3094 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo.pngbin2054 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-empty.pngbin2685 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-outline.pngbin6021 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh.pngbin4579 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reload.pngbin4195 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera-outline.pngbin3404 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera.pngbin3019 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind-outline.pngbin2898 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind.pngbin2362 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search-strong.pngbin3329 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search.pngbin3361 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings-strong.pngbin1714 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings.pngbin2160 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-shrink.pngbin490 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward-outline.pngbin1890 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward.pngbin1533 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward-outline.pngbin1827 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward.pngbin1556 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-snowy.pngbin3775 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer-outline.pngbin4678 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer.pngbin5748 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-half.pngbin3431 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-outline.pngbin3572 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star.pngbin2463 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch-outline.pngbin4823 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch.pngbin3451 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny-outline.pngbin2669 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny.pngbin2506 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone-outline.pngbin3779 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone.pngbin2352 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball-outline.pngbin5535 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball.pngbin6356 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm-outline.pngbin3053 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm.pngbin2492 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time-outline.pngbin5875 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time.pngbin4136 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer-outline.pngbin4578 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer.pngbin6013 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle-outline.pngbin5660 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle.pngbin4825 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash-outline.pngbin4497 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash.pngbin2760 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo-outline.pngbin3114 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo.pngbin1954 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked-outline.pngbin2580 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked.pngbin2605 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload-outline.pngbin1128 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload.pngbin1085 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam-outline.pngbin2038 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam.pngbin2715 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-high.pngbin2977 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-low.pngbin956 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass-outline.pngbin2527 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass.pngbin2013 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world-outline.pngbin7420 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world.pngbin10031 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipad.pngbin1356 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/iphone.pngbin1651 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipod.pngbin3207 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/jet.pngbin2856 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/key.pngbin2722 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/knife.pngbin1822 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/laptop.pngbin2474 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/leaf.pngbin3440 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/levels.pngbin2431 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/lightbulb.pngbin2474 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/link.pngbin2306 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-a.pngbin3941 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-b.pngbin5473 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-c.pngbin4337 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-d.pngbin6618 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/location.pngbin2739 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/locked.pngbin2494 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-in.pngbin1460 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-out.pngbin1637 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/loop.pngbin3794 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/magnet.pngbin4495 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/male.pngbin3788 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/man.pngbin2126 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/map.pngbin4906 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/medkit.pngbin1605 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/merge.pngbin3879 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-a.pngbin4098 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-b.pngbin2576 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-c.pngbin1726 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-circled.pngbin2655 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-round.pngbin937 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus.pngbin160 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/model-s.pngbin4262 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/monitor.pngbin1469 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/more.pngbin3357 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mouse.pngbin2891 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/music-note.pngbin2519 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon-round.pngbin1628 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon.pngbin175 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navigate.pngbin1693 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/network.pngbin3041 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/no-smoking.pngbin5816 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/nuclear.pngbin3618 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/outlet.pngbin2882 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paper-airplane.pngbin3678 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paperclip.pngbin2710 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pause.pngbin1340 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-add.pngbin2410 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-stalker.pngbin3272 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person.pngbin2258 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pie-graph.pngbin3608 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pin.pngbin2270 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pinpoint.pngbin4799 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pizza.pngbin4548 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plane.pngbin3218 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/planet.pngbin4319 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/play.pngbin1787 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/playstation.pngbin3275 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-circled.pngbin3114 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-round.pngbin1567 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus.pngbin223 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/podium.pngbin209 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pound.pngbin2383 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/power.pngbin4727 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetag.pngbin2457 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetags.pngbin2906 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/printer.pngbin1869 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pull-request.pngbin3613 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/qr-scanner.pngbin1842 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/quote.pngbin1743 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/radio-waves.pngbin4978 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/record.pngbin3779 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/refresh.pngbin3582 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply-all.pngbin3033 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply.pngbin2131 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-a.pngbin6449 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-b.pngbin5913 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/sad.pngbin5517 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/scissors.pngbin5061 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/search.pngbin3229 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/settings.pngbin4141 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/share.pngbin2616 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/shuffle.pngbin3420 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-backward.pngbin2421 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-forward.pngbin2402 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android-outline.pngbin3772 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android.pngbin2784 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple-outline.pngbin4104 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple.pngbin2647 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin-outline.pngbin3790 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin.pngbin2424 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer-outline.pngbin3913 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer.pngbin4687 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews-outline.pngbin4754 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews.pngbin4242 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble-outline.pngbin5588 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble.pngbin6983 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox-outline.pngbin5113 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox.pngbin6161 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook-outline.pngbin1788 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook.pngbin1402 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare-outline.pngbin3364 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare.pngbin3021 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-freebsd-devil.pngbin5300 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github-outline.pngbin7475 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github.pngbin4561 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google-outline.pngbin3890 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google.pngbin3682 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus-outline.pngbin4071 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus.pngbin3888 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews-outline.pngbin1994 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews.pngbin1905 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram-outline.pngbin3317 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram.pngbin4403 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin-outline.pngbin2370 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin.pngbin2275 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest-outline.pngbin6933 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest.pngbin5532 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit-outline.pngbin6414 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit.pngbin4498 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss-outline.pngbin5945 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss.pngbin4789 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype-outline.pngbin5608 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype.pngbin4269 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr-outline.pngbin2725 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr.pngbin1946 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tux.pngbin7103 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter-outline.pngbin5569 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter.pngbin3405 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd-outline.pngbin5744 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd.pngbin3446 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo-outline.pngbin5525 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo.pngbin3456 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows-outline.pngbin1775 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows.pngbin2550 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress-outline.pngbin6418 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress.pngbin5465 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo-outline.pngbin2119 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo.pngbin1729 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube-outline.pngbin4655 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube.pngbin2511 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speakerphone.pngbin4310 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speedometer.pngbin4238 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/spoon.pngbin2306 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/star.pngbin2195 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stats-bars.pngbin218 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/steam.pngbin3875 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stop.pngbin1090 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thermometer.pngbin1980 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsdown.pngbin2288 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsup.pngbin2356 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle-filled.pngbin3194 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle.pngbin3599 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-a.pngbin2752 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-b.pngbin1882 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trophy.pngbin3579 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/umbrella.pngbin3416 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/university.pngbin3167 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/unlocked.pngbin2412 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/upload.pngbin2480 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/usb.pngbin3950 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/videocamera.pngbin2381 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-high.pngbin4334 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-low.pngbin2136 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-medium.pngbin3174 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-mute.pngbin4803 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wand.pngbin1933 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/waterdrop.pngbin3169 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wifi.pngbin3037 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wineglass.pngbin3734 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/woman.pngbin3592 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wrench.pngbin2866 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/xbox.pngbin4958 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/readme.md60
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-font.scss27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-icons.scss1473
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-variables.scss741
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/ionicons.scss15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert-circled.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add-circle.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alarm-clock.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alert.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-apps.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-archive.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-back.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-down.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown-circle.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft-circle.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright-circle.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup-circle.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-forward.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-up.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-attach.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bar.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bicycle.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-boat.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bookmark.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bulb.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bus.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-calendar.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-call.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-camera.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cancel.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-car.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cart.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-chat.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-blank.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline-blank.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkmark-circle.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-clipboard.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-close.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-circle.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-done.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-color-palette.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-compass.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contact.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contacts.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contract.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-create.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-delete.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-desktop.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-document.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done-all.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-download.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-drafts.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-exit.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-expand.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-film.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder-open.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-funnel.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-globe.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hand.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hangout.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-happy.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-home.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-image.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-laptop.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-list.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-locate.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-lock.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-mail.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-map.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-menu.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone-off.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-horizontal.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-vertical.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-navigate.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-none.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-off.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-open.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-options.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-people.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person-add.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-landscape.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-portrait.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-pin.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-plane.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-playstore.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-print.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-off.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-on.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-refresh.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove-circle.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-restaurant.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sad.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-search.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-send.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-settings.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share-alt.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-half.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-stopwatch.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-subway.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sunny.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sync.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-textsms.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-time.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-train.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-unlock.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-upload.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-down.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-mute.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-off.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-up.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-walk.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-warning.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-watch.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-wifi.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/aperture.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/archive.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-a.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-b.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-c.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-expand.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-left.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-right.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-left.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-right.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-a.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-b.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-c.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-move.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-resize.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-left.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-right.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-a.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-b.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-c.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-shrink.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-swap.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-a.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-b.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-c.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/asterisk.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/at.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace-outline.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bag.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-charging.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-empty.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-full.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-half.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-low.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beaker.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beer.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bluetooth.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bonfire.svg32
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bookmark.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bowtie.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/briefcase.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bug.svg30
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calculator.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calendar.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/camera.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/card.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cash.svg31
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox-working.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatboxes.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble-working.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubbles.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-circled.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-round.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-down.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-left.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-right.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-up.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clipboard.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clock.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-circled.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-round.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/closed-captioning.svg31
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cloud.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-download.svg31
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-working.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/coffee.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compass.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compose.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/connection-bars.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/contrast.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/crop.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cube.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/disc.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document-text.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/drag.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/earth.svg44
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/easel.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/edit.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/egg.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eject.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email-unread.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask-bubbles.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye-disabled.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/female.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/filing.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/film-marker.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fireball.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flag.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flame.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash-off.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/folder.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork-repo.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/forward.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/funnel.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-a.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-b.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/grid.svg32
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/hammer.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy-outline.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/headphone.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart-broken.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-buoy.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-circled.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/home.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/icecream.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/image.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/images.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information-circled.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ionic.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm-outline.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-back.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-down.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-forward.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-left.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-right.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-down.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-left.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-right.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-up.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-up.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at-outline.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball-outline.svg35
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball-outline.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body-outline.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-empty.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-filled.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-empty.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog-outline.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter-outline.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop-strong.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-drag.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye-outline.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing-outline.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film-outline.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower-outline.svg75
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower.svg38
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a-outline.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b-outline.svg35
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear-outline.svg40
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-empty.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-empty.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-ionic-outline.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad-outline.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list-outline.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop-strong.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-off.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-empty.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor-outline.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-note.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-notes.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition-outline.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny-outline.svg33
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw-outline.svg43
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people-outline.svg44
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd-outline.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play-outline.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-empty.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-outline.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse-strong.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-empty.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reload.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose-outline.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search-strong.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings-strong.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle-strong.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-snowy.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-half.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-outline.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny-outline.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time-outline.svg36
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-high.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-low.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipad.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/iphone.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipod.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/jet.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/key.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/knife.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/laptop.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/leaf.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/levels.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lightbulb.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/link.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-a.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-b.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-c.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-d.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/location.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lock-combination.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/locked.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-in.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-out.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/loop.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/magnet.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/male.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/man.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/map.svg30
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/medkit.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/merge.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-a.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-b.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-c.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-circled.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-round.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/model-s.svg33
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/monitor.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/more.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mouse.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/music-note.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon-round.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navigate.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/network.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/no-smoking.svg33
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/nuclear.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/outlet.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbrush.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbucket.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paper-airplane.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paperclip.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pause.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-add.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-stalker.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pie-graph.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pin.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pinpoint.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pizza.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plane.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/planet.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/play.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/playstation.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-circled.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-round.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/podium.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pound.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/power.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetag.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetags.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/printer.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pull-request.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/qr-scanner.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/quote.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/radio-waves.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/record.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/refresh.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply-all.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-a.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-b.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad-outline.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/scissors.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/search.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/settings.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/share.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/shuffle.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-backward.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-forward.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android-outline.svg29
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple-outline.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin-outline.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen-outline.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews-outline.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble-outline.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook-outline.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-freebsd-devil.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github-outline.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus-outline.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram-outline.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript-outline.svg27
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-markdown.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-nodejs.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-octocat.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest-outline.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-python.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit-outline.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-sass.svg35
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype-outline.svg26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat-outline.svg42
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat.svg31
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tux.svg53
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch-outline.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter-outline.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd-outline.svg44
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd.svg24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo-outline.svg23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp-outline.svg25
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows-outline.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress-outline.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo-outline.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen-outline.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube-outline.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can-outline.svg28
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speakerphone.svg19
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speedometer.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/spoon.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/star.svg7
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stats-bars.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/steam.svg20
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stop.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thermometer.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsdown.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsup.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle-filled.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/transgender.svg12
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-a.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-b.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trophy.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt-outline.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt.svg8
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/umbrella.svg18
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/university.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/unlocked.svg10
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/upload.svg9
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/usb.svg22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/videocamera.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-high.svg15
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-low.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-medium.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-mute.svg14
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wand.svg17
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/waterdrop.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wifi.svg16
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wineglass.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/woman.svg13
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wrench.svg11
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/xbox.svg21
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/utils/js/browserCheck.js24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js34
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js179
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js65
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html85
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm54
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html90
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/adminController.js65
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/admin_menu_edit.js230
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js79
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js63
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/fn_menu_add_popup_controller.js281
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/jcs-admin-controller.js83
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js40
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/post-search-controller.js202
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-controller.js286
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-search-controller.js80
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profileController.js38
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-controller.js226
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-function-list-controller.js157
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-list-controller.js102
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolefunctionpopupController.js84
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolepopupmodelController.js205
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/self-profile-controller.js284
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/usage-list-controller.js41
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowApp.js24
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowController.js509
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowRouting.js26
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/footer.js30
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/adminService.js160
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/headerService.js89
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/leftMenuService.js54
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/profileService.js98
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/userInfoService.js51
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js122
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/page-resource.js95
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/admin.html115
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/profile.html50
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/footer.html42
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/left_menu.html41
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_menu_edit.html175
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html61
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html71
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/collaborate_list.html57
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/jcs_admin.html87
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html82
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html46
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/post_search.html139
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_detail.html188
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_search.html72
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role.html118
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_function_list.html88
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_list.html61
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/self_profile.html183
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/usage_list.html64
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-landing.html130
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-listing.html85
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-new.html108
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-preview.html36
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-remove.html38
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-schedule.html116
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/fusion-sunny.css362
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/workflows/workflows.css50
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js62
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js64
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/droolsController.js30
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/services/droolsService.js76
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html47
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html61
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js80
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js23
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js30
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sample.html60
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html22
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/singlePageSample.html87
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/fusion-sunny.css362
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/jquery-ui.css1225
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/layout/layout-default-latest.css224
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Rlogo.jpgbin3173 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Thumbs.dbbin102912 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_icon.pngbin2388 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_list_spacer.gifbin73 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/active.pngbin682 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add.pngbin352 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add_tool_button.pngbin31105 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/addicon.pngbin463 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/application_window_bg.jpgbin914 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/backButton.pngbin816 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blueButton.pngbin1468 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/bubble.pngbin662 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/cache.pngbin1081 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/calendar.gifbin929 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/chevron.pngbin252 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/close_container.gifbin85 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/collapsed-icon.pngbin1379 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/column-bg.pngbin165 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-add.pngbin755 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-search.pngbin976 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers.pngbin749 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/decrypted.pngbin628 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/error_type.gifbin398 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/excelicon_multi.gifbin1028 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/expanded-icon.pngbin1372 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file-add.pngbin675 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_save-all.pngbin610 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/filter_icon.pngbin29069 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_add.pngbin772 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_closed.pngbin559 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_delete.pngbin767 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_edit.pngbin829 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_open.pngbin632 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_user.pngbin887 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/funnel.pngbin543 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/fusion.gifbin8821 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/grayButton.pngbin1361 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/gray_add_tool_button.pngbin30883 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/headerChatIcon.pngbin465 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/icon_remove_all.gifbin982 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/inactive.pngbin842 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/info_type.gifbin291 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/leftButton.pngbin681 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading_bar.gifbin28954 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/login_button.gifbin1222 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/m1.gifbin636 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/mail.pngbin449 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/map.pngbin611 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/no_favorites_star.pngbin2794 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-add.pngbin589 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-search.pngbin876 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note.pngbin583 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/notes.pngbin673 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offline.pngbin3483 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offlineMsg.gifbin1004 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/online.pngbin888 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/page.gifbin131 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pagination.pngbin724 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-e-w-toggle.pngbin459 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-n-s-toggle.pngbin335 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pix.gifbin49 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/printer.gifbin1036 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/profile.pngbin462 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-active.pngbin545 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-disabled.pngbin421 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-active.pngbin541 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-disabled.pngbin421 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-active.pngbin416 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-disabled.pngbin326 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-active.pngbin421 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-disabled.pngbin322 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_last.pngbin506 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_previous.pngbin381 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/return_to_top.gifbin846 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/rightButton.pngbin731 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search_profile.pngbin880 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_asc.gifbin57 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_desc.gifbin58 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/spacer.gifbin43 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/success_type.gifbin260 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/swoosh.gifbin14250 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-hm.pngbin249 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-v-hm.pngbin317 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab.pngbin343 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-add.pngbin3314 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-delete.pngbin3342 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-edit.pngbin3348 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table.pngbin496 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tabs-bg.pngbin147 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.gifbin414 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.pngbin531 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolbar.pngbin171 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/users.pngbin938 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/warning_type.gifbin1055 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/webphone.icobin241 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/whiteButton.pngbin1430 -> 0 bytes
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/intro.js1
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js26735
-rw-r--r--ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/welcome.css169
-rw-r--r--ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java126
-rw-r--r--ecomp-sdk/sdk-workflow/.gitignore1
-rw-r--r--ecomp-sdk/sdk-workflow/README.md7
-rw-r--r--ecomp-sdk/sdk-workflow/pom.xml111
-rw-r--r--ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/HibernateConfiguration.java20
-rw-r--r--ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java35
-rw-r--r--ecomp-sdk/thirdparty/.gitignore1
-rw-r--r--ecomp-sdk/thirdparty/README.md23
-rw-r--r--ecomp-sdk/thirdparty/pom.xml93
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/ECOMPSSOFilter.java77
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/SecureServlet.java61
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/UnSecureServlet.java61
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/CipherUtil.java125
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/ECOMPSSO.java238
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java133
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java498
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunication.java161
-rw-r--r--ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java178
4202 files changed, 333564 insertions, 176652 deletions
diff --git a/ecomp-sdk/LICENSE.txt b/ecomp-sdk/LICENSE.txt
deleted file mode 100644
index 880bbc9d..00000000
--- a/ecomp-sdk/LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * ============LICENSE_START===========================================================
- * ====================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * ====================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================================
- * ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.
- */ \ No newline at end of file
diff --git a/ecomp-sdk/README.md b/ecomp-sdk/README.md
index f3a52dcb..7af36cb6 100644
--- a/ecomp-sdk/README.md
+++ b/ecomp-sdk/README.md
@@ -1,15 +1,17 @@
-ECOMP Portal SDK
-================
+# ECOMP Portal SDK
This is the parent Maven project for the following
-ECOMP Portal SDK maven child projects:
+ECOMP Portal SDK child Maven projects:
* SDK Framework library
* SDK Core library
* SDK Analytics library
* SDK Workflow library
+* SDK Common Application library
+* SDK Common Overlay Web Application
-This area also includes the ECOMP Portal SDK web application, which
-is a sample web app to build and deploy to a Tomcat instance.
+This area also includes ECOMP Portal SDK web application projects
+for AT&T internal use and open source distribution, but they are
+not child Maven projects.
Release notes are published in each project.
diff --git a/ecomp-sdk/epsdk-analytics/.gitignore b/ecomp-sdk/epsdk-analytics/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-analytics/README.md b/ecomp-sdk/epsdk-analytics/README.md
new file mode 100644
index 00000000..be0b376c
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/README.md
@@ -0,0 +1,16 @@
+# ECOMP Portal SDK Analytics
+
+## Overview
+
+This is the Maven project for the ECOMP Portal SDK Analytics library,
+which is distributed as epsdk-analytics-N.N.N.jar. This library
+requires Hibernate and Spring, and provides data-visualization
+features including charts, maps and reports ("Raptor").
+
+## Release Notes
+
+Version 1.1.0
+- [Portal-7] Improvements added as part of the rebasing process
+
+Version 1.0.0
+- Initial release
diff --git a/ecomp-sdk/epsdk-analytics/license/licenses.properties b/ecomp-sdk/epsdk-analytics/license/licenses.properties
new file mode 100644
index 00000000..4b0e28e7
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/license/licenses.properties
@@ -0,0 +1 @@
+my_license=My license
diff --git a/ecomp-sdk/epsdk-analytics/license/my_license/header.txt b/ecomp-sdk/epsdk-analytics/license/my_license/header.txt
new file mode 100644
index 00000000..c026b6b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/license/my_license/header.txt
@@ -0,0 +1,11 @@
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/ecomp-sdk/epsdk-analytics/license/my_license/license.txt b/ecomp-sdk/epsdk-analytics/license/my_license/license.txt
new file mode 100644
index 00000000..bf326153
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/license/my_license/license.txt
@@ -0,0 +1,4 @@
+name=my_license
+description=<null>
+licenseURL=<null>
+headerURL=<null> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-analytics/pom.xml b/ecomp-sdk/epsdk-analytics/pom.xml
new file mode 100644
index 00000000..41be4f28
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/pom.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-analytics</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>jar</packaging>
+ <name>ECOMP Portal SDK Analytics</name>
+ <description>Provides analytics features for SDK applications</description>
+ <url>https://wiki.onap.org/display/DW/Portal</url>
+
+ <!-- repositories are inherited from parent -->
+
+ <build>
+ <plugins>
+ <!--
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>license-maven-plugin</artifactId>
+ <version>1.10</version>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ <licenseName>my_license</licenseName>
+ <licenseResolver>${project.baseUri}/license</licenseResolver>
+ <inceptionYear>2017</inceptionYear>
+ <organizationName>AT&amp;T Intellectual Property</organizationName>
+ <projectName>eCOMP Portal SDK</projectName>
+ <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage>
+ <processStartTag>================================================================================</processStartTag>
+ <sectionDelimiter>================================================================================</sectionDelimiter>
+ <processEndTag>================================================================================</processEndTag>
+ <roots>
+ <root>src/main</root>
+ </roots>
+ <excludes>
+ <exclude>*.png</exclude>
+ <exclude>*.drl</exclude>
+ <exclude>*.gif</exclude>
+ <exclude>*.jpeg</exclude>
+ <exclude>*.jpg</exclude>
+ <exclude>*.bmp</exclude>
+ <exclude>*.ico</exclude>
+ <exclude>*.svg</exclude>
+ </excludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>first</id>
+ <goals>
+ <goal>update-file-header</goal>
+ </goals>
+ <phase>process-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+ </plugins>
+ </build>
+
+ <dependencies>
+
+ <!-- sdk-core -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <!-- Raptor required Libraries -->
+ <!-- for static charts -->
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.10</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <!-- for generating PDF -->
+ <dependency>
+ <groupId>com.lowagie</groupId>
+ <artifactId>itext</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+ <!-- bridge to implement commons-logging using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${springframework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <!-- for generating excel/csv/excelx -->
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi</artifactId>
+ <version>3.5-FINAL</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ <version>3.5-FINAL</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-scratchpad</artifactId>
+ <version>3.5-FINAL</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-contrib</artifactId>
+ <version>3.5-FINAL</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java
new file mode 100644
index 00000000..7065c9b9
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java
@@ -0,0 +1,91 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * @author sundar
+ * This class is used to get version and Build information when
+ * user run "java -jar raptor_classes.jar" command.
+ */
+public class AntBuild {
+
+ public static String buildNum = "";
+
+ public static void main(String[] args) {
+ System.out.println("Jar (raptor_classes.jar) Information: ");
+ readManifest();
+ }
+
+ public static void readManifest() {
+ try {
+ Class clazz = AntBuild.class;
+ String classContainer = clazz.getProtectionDomain().getCodeSource().getLocation().toString();
+ URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF");
+ Manifest manifest = new Manifest(manifestUrl.openStream());
+
+ //JarFile jar = new JarFile("../lib/raptor_classes.jar");
+ //Manifest manifest = jar.getManifest();
+
+ Attributes attribs = manifest.getMainAttributes();
+ Iterator it = attribs.entrySet().iterator();
+ while(it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Attributes.Name attributeName = (Attributes.Name) entry.getKey();
+ String attributeValue = (String) entry.getValue();
+ if (attributeName.toString().equals("Created-By"))
+ System.out.println("Java HotSpot(TM) Client VM " + " : " + attributeValue);
+ else if (attributeName.toString().equals("Java-Version"))
+ System.out.println("Java Version " + " : " + attributeValue);
+ else if (attributeName.toString().equals("Java-Runtime-Version"))
+ System.out.println("Java Runtime Version " + " : " + attributeValue);
+ else if (attributeName.toString().equals("Ant-Version"))
+ System.out.println(attributeName.toString() + " : " + attributeValue);
+ else {
+ if(attributeName.toString().startsWith("Raptor")) {
+ if (attributeName.toString().startsWith("Raptor-Build-Version"))
+ buildNum = attributeValue;
+ System.out.println(attributeName.toString() + " : " + attributeValue);
+ }
+ }
+ }
+
+ } catch (IOException e) {
+ System.err.println("Cannot read jar-file manifest: "
+ + e.getMessage());
+ }
+ }
+
+ public static String getBuildNum() {
+ if (buildNum.length()>0)
+ return buildNum;
+ else {
+ readManifest();
+ return buildNum;
+ }
+ }
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java
index 9a45c19c..9a45c19c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/RaptorObject.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java
index 826d7a29..2aa8b7bd 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/config/ConfigLoader.java
@@ -19,16 +19,12 @@
*/
package org.openecomp.portalsdk.analytics.config;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Properties;
+import java.io.*;
+import java.util.*;
+import javax.servlet.*;
-import javax.servlet.ServletContext;
-
-import org.openecomp.portalsdk.analytics.controller.Action;
-import org.openecomp.portalsdk.analytics.controller.ActionMapping;
-import org.openecomp.portalsdk.analytics.util.Log;
+import org.openecomp.portalsdk.analytics.controller.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class ConfigLoader {
// public static final String RAPTOR_ACTION_MAP =
@@ -49,6 +45,7 @@ public class ConfigLoader {
public static final String RAPTOR_PDF_PROPERTIES = "raptor_pdf";
// private static String internalFilesPath =
+ // "/WEB-INF/classes/org/openecomp/portalsdk/analytics/config"; // Used for internal files that
// are not supposed to be modified by the user; may be unavailable in some
// cases - so defaults are expected
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java
index 3d14dcbf..853901fb 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Action.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import java.util.StringTokenizer;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
public class Action extends org.openecomp.portalsdk.analytics.RaptorObject {
private String action = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java
index e0cd8d2f..d030c994 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionHandler.java
@@ -1363,14 +1363,14 @@ public class ActionHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
ReportLoader.deleteReportRecord(reportID);
- return "deleted:true";
+ return "{\"deleted\":true}";
//nextPage = reportSearchExecute(request, nextPage);
} catch (RaptorException e) {
nextPage = (new ErrorHandler()).processFatalError(request, e);
}
//return nextPage;
- return "deleted:false";
+ return "{\"deleted\":false}";
} // reportDelete
private String generateSearchString(HttpServletRequest request) {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java
index 93fff254..723b5fd1 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ActionMapping.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import java.util.HashMap;
+import java.util.*;
public class ActionMapping extends HashMap {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java
index b2be8510..c233b4a0 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/Controller.java
@@ -17,19 +17,19 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.analytics.controller;
+ package org.openecomp.portalsdk.analytics.controller;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+import java.lang.reflect.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import org.openecomp.portalsdk.analytics.controller.*;
import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportParamValues;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
public class Controller extends org.openecomp.portalsdk.analytics.RaptorObject {
@@ -54,6 +54,7 @@ public class Controller extends org.openecomp.portalsdk.analytics.RaptorObject {
logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
+ "]. RaptorException: " + e.getMessage()));
// if (actionKey.equals("system_upgrade")) // System override
+// return att.raptor.util.upgrade.SystemUpgrade.upgradeDB(request);
return (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
"[Controller.processRequest]Invalid raptor action [" + actionKey
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java
new file mode 100644
index 00000000..75d88d0f
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java
@@ -0,0 +1,151 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.controller;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.*;
+import javax.servlet.http.*;
+
+import org.openecomp.portalsdk.analytics.error.*;
+import org.openecomp.portalsdk.analytics.model.definition.ReportDefinition;
+import org.openecomp.portalsdk.analytics.model.runtime.ErrorJSONRuntime;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+public class ErrorHandler extends org.openecomp.portalsdk.analytics.RaptorObject {
+
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ErrorHandler.class);
+
+ public ErrorHandler() {
+ }
+
+ public void processError(HttpServletRequest request, String errorMsg) {
+ //Log.write(errorMsg, 2);
+ logger.error(EELFLoggerDelegate.debugLogger, (errorMsg));
+ ArrayList error_list = (ArrayList) request.getAttribute(AppConstants.RI_ERROR_LIST);
+ if (error_list == null)
+ error_list = new ArrayList(1);
+ error_list.add(errorMsg);
+ request.setAttribute(AppConstants.RI_ERROR_LIST, error_list);
+ } // processError
+
+ public void processError(HttpServletRequest request, RaptorException e) {
+ processError(request, "Exception: " + e.getMessage());
+ } // processError
+
+ private String getSessionLog(HttpServletRequest request) {
+ String[] sessionVariablesToLog = Globals.getLogVariablesInSession().split(",");
+ StringBuffer sessionLogStrBuf = new StringBuffer("\n");
+ sessionLogStrBuf.append("***** ADDITIONAL INFORMATION ******");
+ HttpSession session = request.getSession();
+ ReportRuntime rr = (ReportRuntime) session.getAttribute(AppConstants.SI_REPORT_RUNTIME);
+ ReportDefinition rdef = (ReportDefinition) session.getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ if(rr!=null) {
+ sessionLogStrBuf.append("\nWHILE RUNNING");
+ sessionLogStrBuf.append("\nReport Id="+rr.getReportID()+";\t");
+ sessionLogStrBuf.append("Report Name="+rr.getReportName()+";\t\n");
+ } else if (rdef != null) {
+ sessionLogStrBuf.append("\nWHILE CREATING/UPDATING");
+ sessionLogStrBuf.append("\nReport Id="+rdef.getReportID()+";\t");
+ sessionLogStrBuf.append("Report Name="+rdef.getReportName()+";\t\n");
+ }
+ for (int i = 0; i < sessionVariablesToLog.length; i++) {
+ if(session.getAttribute(sessionVariablesToLog[i])!=null)
+ sessionLogStrBuf.append(sessionVariablesToLog[i]+"="+(String)session.getAttribute(sessionVariablesToLog[i])+";\t");
+ }
+ sessionLogStrBuf.append("\n***********************************");
+ sessionLogStrBuf.append("\n");
+ return sessionLogStrBuf.toString();
+ }
+ public String processFatalError(HttpServletRequest request, RaptorException e) {
+ //Log.write("Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage()), 1);
+ logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage())+" "+ getSessionLog(request) + e.getMessage()),AlarmSeverityEnum.MAJOR);
+ if (e instanceof ReportSQLException) {
+ String errorSQL = ((ReportSQLException) e).getReportSQL();
+ if (nvl(errorSQL).length() > 0)
+ request.setAttribute("c_error_sql", errorSQL);
+ } // if
+ AppUtils.processErrorNotification(request, e);
+
+ request.setAttribute(AppConstants.RI_EXCEPTION, e);
+ return AppUtils.getErrorPage();
+ } // processFatalError
+
+ public String processFatalErrorJSON(HttpServletRequest request, RaptorException e) {
+ //Log.write("Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage()), 1);
+ logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage())+" "+ getSessionLog(request) + e.getMessage()),AlarmSeverityEnum.MAJOR);
+ if (e instanceof ReportSQLException) {
+ String errorSQL = ((ReportSQLException) e).getReportSQL();
+ if (nvl(errorSQL).length() > 0)
+ request.setAttribute("c_error_sql", errorSQL);
+ } // if
+ //AppUtils.processErrorNotification(request, e);
+
+ request.setAttribute(AppConstants.RI_EXCEPTION, e);
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage(e.toString());
+ errorJSONRuntime.setStacktrace(getStackTrace(e));
+ ObjectMapper mapper = new ObjectMapper();
+ //mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ //mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ String jsonInString = "";
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ return jsonInString;
+ } // processFatalError
+
+ public static String getStackTrace(Throwable aThrowable) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(result);
+ aThrowable.printStackTrace(printWriter);
+ return result.toString();
+ }
+ public String processFatalErrorWMenu(HttpServletRequest request, RaptorException e) {
+ //Log.write("Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage()), 1);
+ logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage())+" "+ getSessionLog(request) + e.getMessage()),AlarmSeverityEnum.MAJOR);
+ if (e instanceof ReportSQLException) {
+ String errorSQL = ((ReportSQLException) e).getReportSQL();
+ if (nvl(errorSQL).length() > 0)
+ request.setAttribute("c_error_sql", errorSQL);
+ } // if
+ AppUtils.processErrorNotification(request, e);
+
+ request.setAttribute(AppConstants.RI_EXCEPTION, e);
+ return AppUtils.getErrorPageWMenu();
+ } // processFatalError
+
+} // ErrorHandler
+
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java
index a9204db1..b193ec4b 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardProcessor.java
@@ -471,6 +471,8 @@ public class WizardProcessor extends org.openecomp.portalsdk.analytics.RaptorObj
if (menuIDs != null)
for (int i = 0; i < menuIDs.length; i++)
menuID += (menuID.length() == 0 ? "" : "|") + menuIDs[i];
+ /* else
+ menuID = "";*/
// boolean additionalFieldsShown = AppUtils.getRequestNvlValue(request,
// "additionalFieldsShown").equals("Y");
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java
index 3a843873..81308909 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequence.java
@@ -17,12 +17,14 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.analytics.controller;
+ package org.openecomp.portalsdk.analytics.controller;
-import java.util.Vector;
+import java.util.*;
-import org.openecomp.portalsdk.analytics.model.definition.ReportDefinition;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.model.definition.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequence extends Vector {
// private String currentStep = AppConstants.WS_DEFINITION;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java
index 2f16dcca..686c8b7b 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceCrossTab.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceCrossTab extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java
index d883e27e..d8424f2c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceDashboard.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceDashboard extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java
index 1ae4e8a6..2015a7b9 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceLinear.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceLinear extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java
index 663c30c9..db2f8c6f 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedCrossTab.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceSQLBasedCrossTab extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java
index 77996380..7f64cb9a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedHive.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceSQLBasedHive extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java
index eb90d3d6..a19c66b4 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinear.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceSQLBasedLinear extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java
index e43bf288..5c8759d9 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/WizardSequenceSQLBasedLinearDatamining.java
@@ -19,8 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.controller;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class WizardSequenceSQLBasedLinearDatamining extends WizardSequence {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java
index f0de41f8..f0de41f8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java
index 98938f49..98938f49 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorRuntimeException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java
index 3339ba5f..3339ba5f 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/RaptorSchedularException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java
index f78810ee..f78810ee 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ReportSQLException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java
index ed88f5ff..ed88f5ff 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserAccessException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java
index 31476bf6..0145ecfd 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/UserDefinedException.java
@@ -23,6 +23,7 @@
package org.openecomp.portalsdk.analytics.error;
/**
+ * @author sundar
* This class is exclusively used to print error messages to user.
*
*/
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java
index ee26abd0..ee26abd0 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/error/ValidationException.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java
index 00445606..00445606 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/Line.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java
index 249b277c..249b277c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineCollection.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java
index fd9ec94c..fd9ec94c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/line/LineInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java
index a87af423..a87af423 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/ColorProperties.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java
index 7c66f4be..036e83bf 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GMapProperties.java
@@ -19,6 +19,9 @@
*/
package org.openecomp.portalsdk.analytics.gmap.map;
+import java.io.InputStream;
+import java.util.Properties;
+
import org.openecomp.portalsdk.analytics.system.Globals;
public class GMapProperties {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java
index ed3fe8bd..ed3fe8bd 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/GeoCoordinate.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java
index cef1f4ad..cef1f4ad 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/MapConstant.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java
index ba245064..ba245064 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/NovaMap.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java
index f5237ccf..9100637c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/map/layer/SwingLayer.java
@@ -23,6 +23,7 @@ import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.geom.Point2D;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java
index a58eb458..a58eb458 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/Node.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java
index 35801a4d..35801a4d 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeCollection.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java
index d1676e02..d1676e02 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/node/NodeInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java
index d938869a..b281c230 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/MapUtils.java
@@ -19,7 +19,15 @@
*/
package org.openecomp.portalsdk.analytics.gmap.utils;
+import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
public class MapUtils {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java
index 26cbb114..26cbb114 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/gmap/utils/SwingWorker.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java
index 5bf4e003..2757c595 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/DataCache.java
@@ -19,25 +19,17 @@
*/
package org.openecomp.portalsdk.analytics.model;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Vector;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.error.ReportSQLException;
-import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
-import org.openecomp.portalsdk.analytics.model.definition.DBColumnInfo;
-import org.openecomp.portalsdk.analytics.model.definition.TableJoin;
-import org.openecomp.portalsdk.analytics.model.definition.TableSource;
-import org.openecomp.portalsdk.analytics.model.runtime.LookupDBInfo;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
-import org.openecomp.portalsdk.analytics.system.DbUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.model.definition.*;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class DataCache extends org.openecomp.portalsdk.analytics.RaptorObject {
private static Vector dataViewActions = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java
index c663e69c..be950b99 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportHandler.java
@@ -3068,7 +3068,17 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
if(type == 3 && rr.getSemaphoreList()==null && !(rr.getReportType().equals(AppConstants.RT_CROSSTAB)) ) { //type = 3 is whole
//String sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
- String sql_whole = rr.getWholeSQL();
+ //String sql_whole = rr.getWholeSQL();
+ String sql_whole = "";
+ sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
+
+ if(sql_whole==null) {
+ if (!rr.getReportType().equals(AppConstants.RT_HIVE))
+ sql_whole = rr.getWholeSQL();
+ else
+ sql_whole = rr.getReportSQL();
+ }
+
returnValue = paintExcelData(wb, rowNum, col, rd, styles,rr, sheet, sql_whole, sos, request);
} else if(type == 2) {
returnValue = paintExcelData(wb, rowNum, col, rd, styles,rr, sheet, "", sos, request);
@@ -3087,7 +3097,17 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
returnValue = paintExcelData(wb, rowNum, col, rd, styles,rr, sheet, "", sos, request);
}
} else {
- returnValue = paintExcelData(wb, rowNum, col, rd, styles,rr, sheet, rr.getWholeSQL(), sos, request);
+ String sql_whole = "";
+ sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
+
+ if(sql_whole==null) {
+ if (!rr.getReportType().equals(AppConstants.RT_HIVE))
+ sql_whole = rr.getWholeSQL();
+ else
+ sql_whole = rr.getReportSQL();
+ }
+
+ returnValue = paintExcelData(wb, rowNum, col, rd, styles,rr, sheet, sql_whole, sos, request);
}
}
if( returnValue == 0 ) {
@@ -3376,6 +3396,7 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
FileOutputStream fileOutTemp = new FileOutputStream(tmp);
Writer fw = new OutputStreamWriter(fileOutTemp, XML_ENCODING);
String sql_whole = rrDashRep.getWholeSQL();
+
SpreadsheetWriter sw = new SpreadsheetWriter(fw);
sw.beginSheet();
@@ -3474,10 +3495,14 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
//String sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
String sql_whole = "";
- if (!rr.getReportType().equals(AppConstants.RT_HIVE))
- sql_whole = rr.getWholeSQL();
- else
- sql_whole = rr.getReportSQL();
+ sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
+
+ if(sql_whole==null) {
+ if (!rr.getReportType().equals(AppConstants.RT_HIVE))
+ sql_whole = rr.getWholeSQL();
+ else
+ sql_whole = rr.getReportSQL();
+ }
SpreadsheetWriter sw = new SpreadsheetWriter(fw);
@@ -3689,10 +3714,18 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
+ runtime.freeMemory() / mb);
System.out.println("Total Memory:" + runtime.totalMemory() / mb);
System.out.println("Max Memory:" + runtime.maxMemory() / mb);
- if (!rr.getReportType().equals(AppConstants.RT_HIVE))
- sql_whole = rr.getWholeSQL();
- else
- sql_whole = rr.getReportSQL();
+
+ sql_whole = "";
+ sql_whole = (String) request.getAttribute(AppConstants.RI_REPORT_SQL_WHOLE);
+
+ if(sql_whole==null) {
+ if (!rr.getReportType().equals(AppConstants.RT_HIVE))
+ sql_whole = rr.getWholeSQL();
+ else
+ sql_whole = rr.getReportSQL();
+ }
+
+
if(nvl(sql_whole).length()>0) {
try {
conn = ConnectionUtils.getConnection(rr.getDbInfo());
@@ -4793,7 +4826,7 @@ public class ReportHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
cellNum = -1;
colHash = new HashMap();
for (int i = 1; i <= numberOfColumns; i++) {
- colHash.put(rsmd.getColumnName(i).toUpperCase(), strip.stripHtml(rs.getString(i)));
+ colHash.put(rsmd.getColumnLabel(i).toUpperCase(), strip.stripHtml(rs.getString(i)));
}
rd.reportDataRows.resetNext();
dr = rd.reportDataRows.getNext();
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java
index 2197de66..ddbf442c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/ReportLoader.java
@@ -38,10 +38,13 @@
*/
package org.openecomp.portalsdk.analytics.model;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -140,7 +143,7 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
while ((len = in.read(buffer)) != -1)
sb.append(buffer, 0, len);
in.close();*/
- throw new RaptorException("only maria db support for this ");
+ throw new RaptorException("only maria db support for this ");
}
} catch (SQLException ex) {
throw new ReportSQLException (ex.getMessage(), ex.getCause());
@@ -165,7 +168,11 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
ResultSet rs = null;
try {
- String sql = Globals.getDBUpdateReportXml();
+ String sql = "";
+ if(!Globals.isMySQL())
+ sql = Globals.getDBUpdateReportXml();
+ else
+ sql = Globals.getDBUpdateReportXmlMySqlSelect();
stmt = connection.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
stmt.setInt(1,Integer.parseInt(reportID));
@@ -183,7 +190,7 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
//clob.trim(reportXML.length());
out = ((weblogic.jdbc.vendor.oracle.OracleThinClob)clob).getCharacterOutputStream();
} else*/
- if (Globals.isPostgreSQL() || Globals.isMySQL()) {
+ if (Globals.isPostgreSQL()) {
if (rs.next()) {
rs.updateString("report_xml",reportXML);
rs.updateRow();
@@ -192,17 +199,28 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
}
else
throw new RaptorException("Report " + reportID + " not found in the database");
+ } else if (Globals.isMySQL()) {
+ if(rs.next()) {
+ final InputStream stream = rs.getBinaryStream( "report_xml" );
+ InputStream streamNew = new ByteArrayInputStream(reportXML.getBytes(StandardCharsets.UTF_8));
+ final PreparedStatement update = connection.prepareStatement( Globals.getDBUpdateReportXmlMySql() );
+ update.setBinaryStream( 1,streamNew );
+ update.setInt( 2,Integer.parseInt(reportID) );
+ update.execute();
+ } else
+ throw new RaptorException("Report " + reportID + " not found in the database");
+
} else {
/*oracle.sql.CLOB clob = null;
if (rs.next())
- clob = (oracle.sql.CLOB) rs.getObject(1);
+ clob = (oracle.sql.CLOB) rs.getObject(2);
else
throw new RaptorException("Report " + reportID + " not found in the database");
if (clob.length() > reportXML.length())
clob.trim(reportXML.length());
out = clob.getCharacterOutputStream();*/
- throw new RaptorException("only maria db support for this ");
+ throw new RaptorException("only maria db support for this ");
}
if(!(Globals.isPostgreSQL() || Globals.isMySQL())) {
out.write(reportXML);
@@ -247,7 +265,7 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
sql = sql.replace("[rw.getOwnerID()]",rw.getOwnerID());
sql = sql.replace("[rw.getUpdateID()]",rw.getUpdateID());
sql = sql.replace("[rw.getUpdateDate()]",rw.getUpdateDate());
- sql = sql.replace("[Globals.getOracleTimeFormat()]", Globals.getOracleTimeFormat());
+ sql = sql.replace("[Globals.getTimeFormat()]", Globals.getTimeFormat());
sql = sql.replace("[(rw.isDashboardType()]", (rw.isDashboardType()?"Y":"N"));
sql = sql.replace("[(rw.getReportType().equals(AppConstants.RT_DASHBOARD)]", (rw.getReportType().equals(AppConstants.RT_DASHBOARD)?"Y":"N"));
sql = sql.replace("[rw.getReportID()]", rw.getReportID());
@@ -366,7 +384,7 @@ public class ReportLoader extends org.openecomp.portalsdk.analytics.RaptorObject
sql = sql.replace("[rw.getOwnerID()]", rw.getOwnerID());
sql = sql.replace("[rw.getCreateID()]", rw.getCreateID());
sql = sql.replace("[rw.getCreateDate()]", rw.getCreateDate());
- sql = sql.replace("[Globals.getOracleTimeFormat()]", Globals.getOracleTimeFormat());
+ sql = sql.replace("[Globals.getTimeFormat()]", Globals.getTimeFormat());
sql = sql.replace("[rw.getUpdateID()]", rw.getUpdateID());
sql = sql.replace("[rw.getUpdateDate()]", rw.getUpdateDate());
sql = sql.replace("[rw.isDashboardType()]", (rw.isDashboardType()?"Y":"N"));
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java
index 428bc90a..1a15e938 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/SearchHandler.java
@@ -43,28 +43,16 @@
*/
package org.openecomp.portalsdk.analytics.model;
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.Iterator;
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+import javax.servlet.http.*;
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.analytics.controller.ErrorHandler;
+import org.openecomp.portalsdk.analytics.controller.*;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.model.search.ReportSearchResult;
-import org.openecomp.portalsdk.analytics.model.search.ReportSearchResultJSON;
-import org.openecomp.portalsdk.analytics.model.search.SearchResultColumn;
-import org.openecomp.portalsdk.analytics.model.search.SearchResultField;
-import org.openecomp.portalsdk.analytics.model.search.SearchResultRow;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.DbUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.HtmlStripper;
+import org.openecomp.portalsdk.analytics.model.search.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class SearchHandler extends org.openecomp.portalsdk.analytics.RaptorObject {
private static final String HTML_FORM = "forma";
@@ -196,7 +184,8 @@ public class SearchHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
String sql = Globals.getLoadReportSearchResult();
String rep_id = "";
String rep_id_options = "";
- String rep_id_sql = " AND FORMAT(cr.rep_id, 0) like coalesce('%%', FORMAT(cr.rep_id, 0)) ";
+ String rep_id_sql = Globals.getLoadReportSearchRepIdSql();
+ //rep_id_sql = " AND ROUND(cr.rep_id, 0) like coalesce('%%', ROUND(cr.rep_id, 0)) ";
if(request.getParameter("rep_id")!=null) {
rep_id = request.getParameter("rep_id");
}
@@ -224,14 +213,14 @@ public class SearchHandler extends org.openecomp.portalsdk.analytics.RaptorObjec
rep_id_sql = " AND cr.rep_id > "+ rep_id+" ";
break;
default:
- rep_id_sql = " AND FORMAT(cr.rep_id, 0) like coalesce('%%', FORMAT(cr.rep_id, 0)) ";
+ rep_id_sql = Globals.getLoadReportSearchRepIdSql();
break;
}
} else {
rep_id_sql = " AND cr.rep_id = "+ rep_id+" ";
}
} else {
- rep_id_sql = " AND FORMAT(cr.rep_id, 0) like coalesce('%%', FORMAT(cr.rep_id, 0)) "; //equal is default
+ rep_id_sql = Globals.getLoadReportSearchRepIdSql(); //equal is default
}
sql = sql.replace("[fReportID]", rep_id_sql);
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java
index 7b15db55..7b15db55 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ChartSeqComparator.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java
index d7fdc33a..96326639 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameColLookup.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.model.base;
+import java.util.*;
+
public class IdNameColLookup extends IdNameLookup {
private String colId = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java
index dba3db03..3e6d6f42 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameList.java
@@ -19,10 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.model.base;
-import java.util.Vector;
+import java.util.*;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.system.*;
public class IdNameList extends Vector {
protected int pageNo = -1;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java
index e4424f62..73f65c89 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameLookup.java
@@ -19,7 +19,13 @@
*/
package org.openecomp.portalsdk.analytics.model.base;
+import java.util.*;
+
import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.model.*;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class IdNameLookup extends IdNameSql {
private String dbTableName = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java
index 9928ad80..602025fe 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameSql.java
@@ -37,14 +37,14 @@
*/
package org.openecomp.portalsdk.analytics.model.base;
-import java.util.HashMap;
+import java.util.*;
+import org.openecomp.portalsdk.analytics.controller.ActionHandler;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.Utils;
+import org.openecomp.portalsdk.analytics.model.*;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
public class IdNameSql extends IdNameList {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java
index 5ac81f7b..763a44c0 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/IdNameValue.java
@@ -90,7 +90,7 @@ public class IdNameValue {
}
/**
- * @param visibility the visibility to set
+ * @param readOnly the value to set
*/
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java
index 8a6f2a9e..4ccff331 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/NameComparator.java
@@ -21,6 +21,8 @@ package org.openecomp.portalsdk.analytics.model.base;
import java.util.Comparator;
+import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
+
public class NameComparator implements Comparator {
public int compare(Object o1, Object o2) {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java
index 930f508c..930f508c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderBySeqComparator.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java
index e6c013dc..e6c013dc 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/OrderSeqComparator.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java
index f281ac4d..40a3f266 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportSecurity.java
@@ -19,22 +19,19 @@
*/
package org.openecomp.portalsdk.analytics.model.base;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Vector;
+import java.io.*;
+import java.sql.*;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.error.UserAccessException;
-import org.openecomp.portalsdk.analytics.model.definition.SecurityEntry;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.DbUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.Utils;
+import org.openecomp.portalsdk.analytics.controller.ActionHandler;
+import org.openecomp.portalsdk.analytics.error.*;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.model.definition.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
public class ReportSecurity extends org.openecomp.portalsdk.analytics.RaptorObject {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java
index f856318d..1638a396 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/base/ReportWrapper.java
@@ -191,7 +191,7 @@ public class ReportWrapper extends org.openecomp.portalsdk.analytics.RaptorObjec
+ reportID);*/
String r_sql = Globals.getReportWrapperFormat();
- r_sql = r_sql.replace("[Globals.getOracleTimeFormat()]", Globals.getOracleTimeFormat());
+ r_sql = r_sql.replace("[Globals.getTimeFormat()]", Globals.getTimeFormat());
r_sql = r_sql.replace("[reportID]", reportID);
DataSet ds = DbUtils
@@ -3824,12 +3824,12 @@ public class ReportWrapper extends org.openecomp.portalsdk.analytics.RaptorObjec
}
if(getDBType().equals(AppConstants.MYSQL)) {
- partSql = "LIMIT "+ String.valueOf(startRow)+" , "+ String.valueOf(getPageSize());
+ partSql = partSql+ " LIMIT "+ String.valueOf(startRow)+" , "+ String.valueOf(endRow);
} else if(getDBType().equals(AppConstants.ORACLE)) {
reportSQL = reportSQL.replace(" AS ", " ");
- partSql = "where rownum >= "+ String.valueOf(startRow)+" and rownum <= "+(Integer.parseInt(String.valueOf(startRow)) + Integer.parseInt(String.valueOf(getPageSize())));
+ partSql = "where rownum >= "+ String.valueOf(startRow)+" and rownum <= "+(Integer.parseInt(String.valueOf(startRow)) + Integer.parseInt(String.valueOf(endRow)));
} else if(getDBType().equals(AppConstants.POSTGRESQL)) {
- partSql = "LIMIT "+ String.valueOf(getPageSize())+" , "+ String.valueOf(startRow);//limit [pageSize] offset [startRow]
+ partSql = partSql + " LIMIT "+ String.valueOf(endRow)+" , "+ String.valueOf(startRow);//limit [pageSize] offset [startRow]
}
// Limit only to MYSQL or MariaDB
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java
index 4496fdca..4496fdca 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DBColumnInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java
index 8972e54a..8972e54a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/DrillDownParamDef.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java
index a9d9be85..a9d9be85 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/Marker.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java
index 71ec9f87..9d66717a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportDefinition.java
@@ -73,7 +73,6 @@ import org.openecomp.portalsdk.analytics.xmlobj.JavascriptItemType;
import org.openecomp.portalsdk.analytics.xmlobj.ObjectFactory;
import org.openecomp.portalsdk.analytics.xmlobj.PredefinedValueList;
import org.openecomp.portalsdk.analytics.xmlobj.SemaphoreType;
-import org.openecomp.portalsdk.core.controller.FavoritesController;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
/**<HR/>
@@ -96,7 +95,7 @@ import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
public class ReportDefinition extends ReportWrapper implements Serializable {
- static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FavoritesController.class);
+ static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ReportDefinition.class);
private ReportSchedule reportSchedule = null;
@@ -221,6 +220,7 @@ public class ReportDefinition extends ReportWrapper implements Serializable {
} //canPersistDashboard
private boolean canPersistLinearReport() {
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& canPersistLinearReport");
boolean visibleColExist = false;
if (getDataSourceList().getDataSource().size() > 0) {
@@ -234,6 +234,7 @@ public class ReportDefinition extends ReportWrapper implements Serializable {
} // for
} // if
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& visibleColExist " + visibleColExist);
return visibleColExist;
} // canPersistLinearReport
@@ -264,14 +265,19 @@ public class ReportDefinition extends ReportWrapper implements Serializable {
} // canPersistReport
public void persistReport(HttpServletRequest request) throws RaptorException {
- if (!canPersistReport())
+ if (!canPersistReport()) {
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& In !canPersistReport ReportType: " + getReportType());
return;
+ } else {
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& Not In !canPersistReport");
+ }
Connection connection = null;
try {
String userID = AppUtils.getUserID(request);
String reportXML = marshal();
logger.debug(EELFLoggerDelegate.debugLogger, ("Ocurring during Schedule "));
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& Report ID " + reportID);
if (nvl(reportID, "-1").equals("-1")) {
connection = DbUtils.startTransaction();
// Add report
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java
index db69e9d8..db69e9d8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportLogEntry.java
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java
new file mode 100644
index 00000000..e3c417a1
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java
@@ -0,0 +1,86 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.openecomp.portalsdk.analytics.RaptorObject;
+import org.openecomp.portalsdk.analytics.view.DataRow;
+import org.openecomp.portalsdk.analytics.view.DataValue;
+import org.openecomp.portalsdk.analytics.view.ReportData;
+
+public class ReportMap extends RaptorObject {
+ String markerColor = "";
+ String addressColumn = "";
+ String dataColumn = "";
+ String isMapAllowedYN = "";
+ String addAddressInDataYN = "";
+ List markers = new ArrayList();
+
+ public String getIsMapAllowedYN() {
+ return isMapAllowedYN;
+ }
+ public void setIsMapAllowedYN(String isMapAllowedYN) {
+ this.isMapAllowedYN = isMapAllowedYN;
+ }
+ public ReportMap(String markerColor, String addressColumn, String dataColumn, String isMapAllowed, String addAddressInDataYN){
+ this.setMarkerColor(markerColor);
+ this.setAddressColumn(addressColumn);
+ this.setDataColumn(dataColumn);
+ this.setIsMapAllowedYN(isMapAllowed);
+ this.setAddAddressInDataYN(addAddressInDataYN);
+ }
+ public String getAddressColumn() {
+ return addressColumn;
+ }
+ public void setAddressColumn(String addressColumn) {
+ this.addressColumn = addressColumn;
+ }
+ public String getDataColumn() {
+ return dataColumn;
+ }
+ public void setDataColumn(String dataColumn) {
+ this.dataColumn = dataColumn;
+ }
+ public String getMarkerColor() {
+ return markerColor;
+ }
+ public void setMarkerColor(String markerColor) {
+ this.markerColor = markerColor;
+ }
+ public List getMarkers() {
+ return markers;
+ }
+ public void setMarkers(List markers) {
+ this.markers = markers;
+ }
+ public String getAddAddressInDataYN() {
+ return addAddressInDataYN;
+ }
+ public void setAddAddressInDataYN(String addAddressInDataYN) {
+ this.addAddressInDataYN = addAddressInDataYN;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java
index d95c91b5..d95c91b5 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportSchedule.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java
index 4feddd6e..c5edb12a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/SecurityEntry.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.model.definition;
-import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
+import org.openecomp.portalsdk.analytics.model.base.*;
public class SecurityEntry extends IdNameValue {
private boolean readOnly = true;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java
index 6022d5a1..6022d5a1 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableJoin.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java
index dc5b385a..dc5b385a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/TableSource.java
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnEditJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnEditJSON.java
new file mode 100644
index 00000000..4e08a697
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnEditJSON.java
@@ -0,0 +1,110 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public class ColumnEditJSON implements WizardJSON {
+
+ private String tabId;
+ private String tabName;
+
+ private String colId;
+ private String colName;
+ private String displayAlignment;
+ private String displayHeaderAlignment;
+ private boolean sortable;
+ private boolean visible;
+
+ private String drilldownURL;
+ private String drilldownParams;
+ private String drilldownType;
+
+ public String getTabId() {
+ return tabId;
+ }
+ public void setTabId(String tabId) {
+ this.tabId = tabId;
+ }
+ public String getTabName() {
+ return tabName;
+ }
+ public void setTabName(String tabName) {
+ this.tabName = tabName;
+ }
+ public String getColId() {
+ return colId;
+ }
+ public void setColId(String colId) {
+ this.colId = colId;
+ }
+ public String getColName() {
+ return colName;
+ }
+ public void setColName(String colName) {
+ this.colName = colName;
+ }
+ public String getDisplayAlignment() {
+ return displayAlignment;
+ }
+ public void setDisplayAlignment(String displayAlignment) {
+ this.displayAlignment = displayAlignment;
+ }
+ public String getDisplayHeaderAlignment() {
+ return displayHeaderAlignment;
+ }
+ public void setDisplayHeaderAlignment(String displayHeaderAlignment) {
+ this.displayHeaderAlignment = displayHeaderAlignment;
+ }
+ public boolean isSortable() {
+ return sortable;
+ }
+ public void setSortable(boolean sortable) {
+ this.sortable = sortable;
+ }
+ public boolean isVisible() {
+ return visible;
+ }
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+ public String getDrilldownURL() {
+ return drilldownURL;
+ }
+ public void setDrilldownURL(String drilldownURL) {
+ this.drilldownURL = drilldownURL;
+ }
+ public String getDrilldownParams() {
+ return drilldownParams;
+ }
+ public void setDrilldownParams(String drilldownParams) {
+ this.drilldownParams = drilldownParams;
+ }
+ public String getDrilldownType() {
+ return drilldownType;
+ }
+ public void setDrilldownType(String drilldownType) {
+ this.drilldownType = drilldownType;
+ }
+
+
+
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnJSON.java
new file mode 100644
index 00000000..8f83c3ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ColumnJSON.java
@@ -0,0 +1,41 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public class ColumnJSON implements ElementJSON {
+
+ private String id;
+ private String name;
+ public String getId() {
+ return id;
+ }
+ public void setId(String id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/DefinitionJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/DefinitionJSON.java
new file mode 100644
index 00000000..68211005
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/DefinitionJSON.java
@@ -0,0 +1,215 @@
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.List;
+
+public class DefinitionJSON implements WizardJSON {
+
+ private String tabName;
+ private String tabId;
+
+ private String reportId;
+ private String reportName;
+ private String reportDescr;
+ private String reportType;
+ private String dbInfo;
+ private String formHelpText;
+ private Integer pageSize;
+ private List<IdNameBooleanJSON> displayArea = null;
+ private Boolean hideFormFieldsAfterRun;
+ private Integer maxRowsInExcelCSVDownload;
+ private Integer frozenColumns;
+ private String dataGridAlign;
+ private String emptyMessage;
+ private String dataContainerHeight;
+ private String dataContainerWidth;
+ private List<NameBooleanJSON> displayOptions = null;
+ private Boolean runtimeColSortDisabled;
+ private Integer numFormCols;
+ private String reportTitle;
+ private String reportSubTitle;
+
+ @Override
+ public String getTabName() {
+ return tabName;
+ }
+
+ @Override
+ public void setTabName(String tabName) {
+ this.tabName = tabName;
+ }
+
+ @Override
+ public String getTabId() {
+ return tabId;
+ }
+
+ @Override
+ public void setTabId(String tabId) {
+ this.tabId = tabId;
+ }
+
+
+
+ public String getReportId() {
+ return reportId;
+ }
+
+ public void setReportId(String reportId) {
+ this.reportId = reportId;
+ }
+
+ public String getReportName() {
+ return reportName;
+ }
+
+ public void setReportName(String reportName) {
+ this.reportName = reportName;
+ }
+
+ public String getReportDescr() {
+ return reportDescr;
+ }
+
+ public void setReportDescr(String reportDescr) {
+ this.reportDescr = reportDescr;
+ }
+
+ public String getReportType() {
+ return reportType;
+ }
+
+ public void setReportType(String reportType) {
+ this.reportType = reportType;
+ }
+
+ public String getDbInfo() {
+ return dbInfo;
+ }
+
+ public void setDbInfo(String dbInfo) {
+ this.dbInfo = dbInfo;
+ }
+
+ public String getFormHelpText() {
+ return formHelpText;
+ }
+
+ public void setFormHelpText(String formHelpText) {
+ this.formHelpText = formHelpText;
+ }
+
+ public Integer getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(Integer pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public List<IdNameBooleanJSON> getDisplayArea() {
+ return displayArea;
+ }
+
+ public void setDisplayArea(List<IdNameBooleanJSON> displayArea) {
+ this.displayArea = displayArea;
+ }
+
+ public Boolean getHideFormFieldsAfterRun() {
+ return hideFormFieldsAfterRun;
+ }
+
+ public void setHideFormFieldsAfterRun(Boolean hideFormFieldsAfterRun) {
+ this.hideFormFieldsAfterRun = hideFormFieldsAfterRun;
+ }
+
+ public Integer getMaxRowsInExcelCSVDownload() {
+ return maxRowsInExcelCSVDownload;
+ }
+
+ public void setMaxRowsInExcelCSVDownload(Integer maxRowsInExcelCSVDownload) {
+ this.maxRowsInExcelCSVDownload = maxRowsInExcelCSVDownload;
+ }
+
+ public Integer getFrozenColumns() {
+ return frozenColumns;
+ }
+
+ public void setFrozenColumns(Integer frozenColumns) {
+ this.frozenColumns = frozenColumns;
+ }
+
+ public String getDataGridAlign() {
+ return dataGridAlign;
+ }
+
+ public void setDataGridAlign(String dataGridAlign) {
+ this.dataGridAlign = dataGridAlign;
+ }
+
+ public String getEmptyMessage() {
+ return emptyMessage;
+ }
+
+ public void setEmptyMessage(String emptyMessage) {
+ this.emptyMessage = emptyMessage;
+ }
+
+ public String getDataContainerHeight() {
+ return dataContainerHeight;
+ }
+
+ public void setDataContainerHeight(String dataContainerHeight) {
+ this.dataContainerHeight = dataContainerHeight;
+ }
+
+ public String getDataContainerWidth() {
+ return dataContainerWidth;
+ }
+
+ public void setDataContainerWidth(String dataContainerWidth) {
+ this.dataContainerWidth = dataContainerWidth;
+ }
+
+ public List<NameBooleanJSON> getDisplayOptions() {
+ return displayOptions;
+ }
+
+ public void setDisplayOptions(List<NameBooleanJSON> displayOptions) {
+ this.displayOptions = displayOptions;
+ }
+
+ public Boolean getRuntimeColSortDisabled() {
+ return runtimeColSortDisabled;
+ }
+
+ public void setRuntimeColSortDisabled(Boolean runtimeColSortDisabled) {
+ this.runtimeColSortDisabled = runtimeColSortDisabled;
+ }
+
+ public Integer getNumFormCols() {
+ return numFormCols;
+ }
+
+ public void setNumFormCols(Integer numFormCols) {
+ this.numFormCols = numFormCols;
+ }
+
+ public String getReportTitle() {
+ return reportTitle;
+ }
+
+ public void setReportTitle(String reportTitle) {
+ this.reportTitle = reportTitle;
+ }
+
+ public String getReportSubTitle() {
+ return reportSubTitle;
+ }
+
+ public void setReportSubTitle(String reportSubTitle) {
+ this.reportSubTitle = reportSubTitle;
+ }
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ElementJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ElementJSON.java
new file mode 100644
index 00000000..aba1e8b4
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ElementJSON.java
@@ -0,0 +1,33 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+
+public interface ElementJSON {
+
+ // To be defined by child class
+ public String getId();
+ public String getName();
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/FormEditJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/FormEditJSON.java
new file mode 100644
index 00000000..47b6d1b0
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/FormEditJSON.java
@@ -0,0 +1,113 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.List;
+
+public class FormEditJSON implements WizardJSON {
+
+ private String tabId;
+ private String tabName;
+
+ private String fieldId;
+ private String fieldName;
+ private String fieldType;
+ private boolean visible;
+ private String defaultValue;
+ private String fieldDefaultSQL;
+ private String fieldSQL;
+ private String validationType;
+ private List<IdNameBooleanJSON> predefinedValueList;
+
+
+ public String getTabId() {
+ return tabId;
+ }
+ public void setTabId(String tabId) {
+ this.tabId = tabId;
+ }
+ public String getTabName() {
+ return tabName;
+ }
+ public void setTabName(String tabName) {
+ this.tabName = tabName;
+ }
+
+
+ public String getFieldId() {
+ return fieldId;
+ }
+ public void setFieldId(String fieldId) {
+ this.fieldId = fieldId;
+ }
+ public String getFieldName() {
+ return fieldName;
+ }
+ public void setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ public String getFieldType() {
+ return fieldType;
+ }
+ public void setFieldType(String fieldType) {
+ this.fieldType = fieldType;
+ }
+ public boolean isVisible() {
+ return visible;
+ }
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+ public String getFieldDefaultSQL() {
+ return fieldDefaultSQL;
+ }
+ public void setFieldDefaultSQL(String fieldDefaultSQL) {
+ this.fieldDefaultSQL = fieldDefaultSQL;
+ }
+ public String getValidationType() {
+ return validationType;
+ }
+ public void setValidationType(String validationType) {
+ this.validationType = validationType;
+ }
+ public List<IdNameBooleanJSON> getPredefinedValueList() {
+ return predefinedValueList;
+ }
+ public void setPredefinedValueList(List<IdNameBooleanJSON> predefinedValueList) {
+ this.predefinedValueList = predefinedValueList;
+ }
+ public String getFieldSQL() {
+ return fieldSQL;
+ }
+ public void setFieldSQL(String fieldSQL) {
+ this.fieldSQL = fieldSQL;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/IdNameBooleanJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/IdNameBooleanJSON.java
new file mode 100644
index 00000000..50add1f4
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/IdNameBooleanJSON.java
@@ -0,0 +1,32 @@
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public class IdNameBooleanJSON {
+
+ private String id;
+ private String name;
+ private boolean selected;
+
+ public String getId() {
+ return id;
+ }
+ public void setId(String id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ImportJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ImportJSON.java
new file mode 100644
index 00000000..282b7c41
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ImportJSON.java
@@ -0,0 +1,54 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.List;
+
+public class ImportJSON implements WizardJSON {
+
+ private String tabId;
+ private String tabName;
+
+ private String reportXML;
+
+
+ public String getTabId() {
+ return tabId;
+ }
+ public void setTabId(String tabId) {
+ this.tabId = tabId;
+ }
+ public String getTabName() {
+ return tabName;
+ }
+ public void setTabName(String tabName) {
+ this.tabName = tabName;
+ }
+ public String getReportXML() {
+ return reportXML;
+ }
+ public void setReportXML(String reportXML) {
+ this.reportXML = reportXML;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ListJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ListJSON.java
new file mode 100644
index 00000000..34c2c99b
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/ListJSON.java
@@ -0,0 +1,40 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+
+public class ListJSON {
+
+ private ArrayList<ElementJSON> elements;
+
+ public ArrayList<ElementJSON> getElements() {
+ return elements;
+ }
+
+ public void setElements(ArrayList<ElementJSON> elements) {
+ this.elements = elements;
+ }
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/MessageJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/MessageJSON.java
new file mode 100644
index 00000000..d3955448
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/MessageJSON.java
@@ -0,0 +1,55 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+import org.openecomp.portalsdk.analytics.view.DataValue;
+import org.openecomp.portalsdk.analytics.xmlobj.ColFilterList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+
+public class MessageJSON {
+
+ private String message;
+ private String anyStacktrace;
+ public String getMessage() {
+ return message;
+ }
+ public void setMessage(String message) {
+ this.message = message;
+ }
+ public String getAnyStacktrace() {
+ return anyStacktrace;
+ }
+ public void setAnyStacktrace(String anyStacktrace) {
+ this.anyStacktrace = anyStacktrace;
+ }
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/NameBooleanJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/NameBooleanJSON.java
new file mode 100644
index 00000000..7f191d93
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/NameBooleanJSON.java
@@ -0,0 +1,25 @@
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public class NameBooleanJSON {
+
+ private String name;
+ private boolean selected;
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryJSON.java
new file mode 100644
index 00000000..ece9a02c
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryJSON.java
@@ -0,0 +1,60 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.openecomp.portalsdk.analytics.model.definition.wizard.WizardJSON;
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+
+public class QueryJSON implements WizardJSON {
+
+ private String query;
+ private String tabName;
+ private String tabId;
+
+
+ public String getTabName() {
+ return tabName;
+ }
+
+ public void setTabName(String tabName) {
+ this.tabName = tabName;
+ }
+
+ public String getTabId() {
+ return tabId;
+ }
+
+ public void setTabId(String tabId) {
+ this.tabId = tabId;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryResultJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryResultJSON.java
new file mode 100644
index 00000000..41c8bca0
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/QueryResultJSON.java
@@ -0,0 +1,70 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+
+public class QueryResultJSON {
+
+ private String query;
+
+ private int totalRows;
+ private ArrayList<String> reportDataColumns;
+ private ArrayList<Map<String,String>> reportDataRows;
+
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ public int getTotalRows() {
+ return totalRows;
+ }
+
+ public void setTotalRows(int totalRows) {
+ this.totalRows = totalRows;
+ }
+
+ public ArrayList<String> getReportDataColumns() {
+ return reportDataColumns;
+ }
+
+ public void setReportDataColumns(ArrayList<String> reportDataColumns) {
+ this.reportDataColumns = reportDataColumns;
+ }
+
+ public ArrayList<Map<String, String>> getReportDataRows() {
+ return reportDataRows;
+ }
+
+ public void setReportDataRows(ArrayList<Map<String, String>> reportDataRows) {
+ this.reportDataRows = reportDataRows;
+ }
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/SearchFieldJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/SearchFieldJSON.java
new file mode 100644
index 00000000..3689619c
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/SearchFieldJSON.java
@@ -0,0 +1,41 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public class SearchFieldJSON implements ElementJSON {
+
+ private String id;
+ private String name;
+ public String getId() {
+ return id;
+ }
+ public void setId(String id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/WizardJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/WizardJSON.java
new file mode 100644
index 00000000..8ef937c1
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/wizard/WizardJSON.java
@@ -0,0 +1,9 @@
+package org.openecomp.portalsdk.analytics.model.definition.wizard;
+
+public interface WizardJSON {
+
+ public String getTabName();
+ public void setTabName(String tabName);
+ public String getTabId();
+ public void setTabId(String tabId);
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java
index 34e38062..c724a20a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PageEvent.java
@@ -190,17 +190,17 @@ class PageEvent extends PdfPageEventHelper {
private void addLeftFooter(PdfPTable table, Font font) {
Font font1 = new Font(font);
- font1.setSize(Globals.getAttProprieraryFontSize());
+ font1.setSize(Globals.getPDFFooterFontSize());
if (isEmpty(pb.getLeftFooter()))
- table.addCell(new Paragraph(" " + Globals.getAttProprietary(), font1));
+ table.addCell(new Paragraph(" " + Globals.getPDFFooter(), font1));
else
table.addCell(new Paragraph(pb.getLeftFooter(), font));
}
private void addHeaderDummy(PdfPTable table, Font font) {
Font font1 = new Font(font);
- font1.setSize(Globals.getAttProprieraryFontSize());
+ font1.setSize(Globals.getPDFFooterFontSize());
table.addCell(new Paragraph("Header row", font1));
}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java
index 31b26435..31b26435 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfBean.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java
index deac806d..c27ba0c5 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/pdf/PdfReportHandler.java
@@ -17,8 +17,8 @@
* limitations under the License.
* ================================================================================
*/
-/* ===========================================================================================
+/* ===========================================================================================
* This class is part of <I>RAPTOR (Rapid Application Programming Tool for OLAP Reporting)</I>
* Raptor : This tool is used to generate different kinds of reports with lot of utilities
* ===========================================================================================
@@ -111,7 +111,10 @@ import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
-
+/**
+ * @author mwliu and sundar
+ *
+ */
public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorObject{
/**
@@ -345,6 +348,11 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
ArrayList paraList = null;
if(nvl(rr.getReportTitle()).length()>0) {
add2Cells(table,"Report Title : ",nvl(rr.getReportTitle()));
+ if(nvl(rr.getReportSubTitle()).length()>0) {
+ add2Cells(table,"Report Sub-Title : ",nvl(rr.getReportSubTitle()));
+ System.out.println("Adding the report sub-title ");
+ }
+
} else {
add2Cells(table,"Report Name : ",nvl(rr.getReportName()));
}
@@ -785,7 +793,7 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
String chartTitle = Globals.getDisplayChartTitle()? rr.getReportName():"";
chartTitle = rr.getFormFieldFilled(chartTitle);
- filename = null;/* (String) ChartGen.generateChart( chartType,
+ filename = null; /*(String) ChartGen.generateChart( chartType,
request.getSession(),
ds,
legendColumnName,
@@ -809,8 +817,8 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
AppConstants.WEB_VERSION,
additionalChartOptionsMap,
true
- );
-*/ try {
+ );*/
+ try {
Image image = Image.getInstance(downloadFileName);
images.add(image);
} catch (MalformedURLException e) {
@@ -838,7 +846,7 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
String chartTitle = Globals.getDisplayChartTitle()? rr.getReportName():"";
chartTitle = rr.getFormFieldFilled(chartTitle);
- filename = null;/*(String) ChartGen.generateChart( chartType,
+ filename = null; /*(String) ChartGen.generateChart( chartType,
request.getSession(),
ds,
legendColumnName,
@@ -862,8 +870,8 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
AppConstants.WEB_VERSION,
additionalChartOptionsMap,
true
- );
-*/ try {
+ );*/
+ try {
Image image = Image.getInstance(downloadFileName);
images.add(image);
} catch (MalformedURLException e) {
@@ -923,10 +931,10 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
int mb = 1024*1024;
Runtime runtime = Runtime.getRuntime();
int returnValue = 0;
- sql_whole = rr.getWholeSQL();
- if(rd.getDataRowCount() >= rr.getReportDataSize()) {
- sql_whole="";
- }
+ //sql_whole = rr.getWholeSQL();
+ //if(rd.getDataRowCount() >= rr.getReportDataSize()) {
+ //sql_whole="";
+ //}
float f[] = getRelativeWidths(rd, rr.getReportType().equals(AppConstants.RT_CROSSTAB));
PdfPTable table = new PdfPTable(f);
table.setWidthPercentage(100f);
@@ -1022,7 +1030,7 @@ public class PdfReportHandler extends org.openecomp.portalsdk.analytics.RaptorOb
*/ rowCount++;
colHash = new HashMap();
for (int i = 1; i <= numberOfColumns; i++) {
- colHash.put(rsmd.getColumnName(i), rs.getString(i));
+ colHash.put(rsmd.getColumnLabel(i).toUpperCase(), rs.getString(i));
}
rd.reportDataRows.resetNext();
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java
index 7e99dc6e..7e99dc6e 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/BarChartOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java
index 93fab6e9..93fab6e9 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CategoryAxisJSON.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java
index c46f48ac..18d31278 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartD3Helper.java
@@ -238,6 +238,10 @@ public class ChartD3Helper {
//String width, String height, boolean animation, String rotateLabels, boolean staggerLabels, boolean showMaxMin, boolean showLegend, boolean showControls, String topMargin, String bottomMargin, boolean showTitle, String subType
+ boolean isEmbedded = false;
+ if(request.getParameter("embedded")!=null) {
+ isEmbedded = true;
+ }
String width = chartOptionsMap.get("width");
String height = chartOptionsMap.get("height");
boolean animation = getBooleanValue(chartOptionsMap.get("animation"), true);
@@ -273,7 +277,6 @@ public class ChartD3Helper {
HttpSession session = null;
session = request.getSession();
-
String chartType = reportRuntime.getChartType();
List l = reportRuntime.getAllColumns();
List lGroups = reportRuntime.getAllChartGroups();
@@ -298,6 +301,8 @@ public class ChartD3Helper {
title = parseTitle(title, formValues);
+ String chartScriptsPath = (isEmbedded?AppUtils.getChartScriptsPath(""):AppUtils.getChartScriptsPath());
+
if(displayChart) {
DataSet ds = null;
try {
@@ -445,7 +450,7 @@ public class ChartD3Helper {
wholeScript.append("<html>\n");
wholeScript.append("<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF8\">\n");
wholeScript.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n");
- wholeScript.append("<link href=\""+ AppUtils.getBaseFolderURL() +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
+ wholeScript.append("<link href=\""+ chartScriptsPath +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
//wholeScript.append("")
wholeScript.append("<style>\n " +
" body { \n" +
@@ -485,14 +490,14 @@ public class ChartD3Helper {
wholeScript.append("<div id=\"chart"+reportRuntime.getReportID()+"\"> <svg></svg> </div> \n");
//js files
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/d3.v3.min.js\"></script>");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/nv.d3.min.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/tooltip.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/utils.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/axis.min.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/d3.v3.min.js\"></script>");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/nv.d3.min.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/tooltip.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/utils.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/axis.min.js\"></script> \n");
//wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/discreteBar.js\"></script> \n");
//wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/discreteBarChart.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/multiChart.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/multiChart.js\"></script> \n");
//json
wholeScript.append("<script> \n");
wholeScript.append("historicalBarChart = [ \n");
@@ -902,6 +907,8 @@ public class ChartD3Helper {
date1 = new java.util.Date(initialDate.longValue());
if(formatFlag==HOURFLAG)
date1 = DateUtils.addHours(date1, 1);
+ else if(formatFlag==MINFLAG)
+ date1 = DateUtils.addMinutes(date1, 30);
else if (formatFlag == DAYFLAG)
date1 = DateUtils.addDays(date1, 1);
else if (formatFlag == MONTHFLAG)
@@ -1347,7 +1354,7 @@ public class ChartD3Helper {
wholeScript.append("<html>\n");
wholeScript.append("<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF8\">\n");
wholeScript.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n");
- wholeScript.append("<link href=\""+ AppUtils.getBaseFolderURL() +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
+ wholeScript.append("<link href=\""+ chartScriptsPath +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
wholeScript.append("<style>\n " +
" body { \n" +
" overflow-y:scroll; \n" +
@@ -1388,9 +1395,9 @@ public class ChartD3Helper {
wholeScript.append("<div id=\"chart"+reportRuntime.getReportID()+"\"> <svg></svg> </div> \n");
//js files
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/d3.v3.min.js\"></script>\n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/nv.d3.min.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/axis.min.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/d3.v3.min.js\"></script>\n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/nv.d3.min.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/axis.min.js\"></script> \n");
//wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/cumulativeLineChart.js\"></script> \n");
//if(multipleSeries)
//wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/multiChart.js\"></script> \n");
@@ -1779,7 +1786,9 @@ public class ChartD3Helper {
}
wholeScript.append(" .tickFormat(function(d) { \n");
- if(formatFlag==HOURFLAG)
+ if(formatFlag==DAYFLAG)
+ wholeScript.append(" return d3.time.format('%m/%d/%Y')(new Date(d)) }); \n");
+ else if(formatFlag==HOURFLAG)
wholeScript.append(" return d3.time.format('%x %H')(new Date(d)) }); \n");
else if(formatFlag==MINFLAG)
wholeScript.append(" return d3.time.format('%x %H:%M')(new Date(d)) }); \n");
@@ -1897,12 +1906,12 @@ public class ChartD3Helper {
wholeScript.append("<div id=\"chart"+reportRuntime.getReportID()+"\"><svg></svg></div>");
//"<svg id=\"test2\"></svg>\n");
//js files
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/d3.v3.min.js\"></script>\n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/nv.d3.min.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/legend.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/pie.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/pieChart.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/utils.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/d3.v3.min.js\"></script>\n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/nv.d3.min.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/legend.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/pie.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/pieChart.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/utils.js\"></script> \n");
wholeScript.append("<script> \n");
wholeScript.append("historicalBarChart = [ \n");
@@ -2155,9 +2164,9 @@ public class ChartD3Helper {
wholeScript.append(" <head>\n");
//wholeScript.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7; IE=EmulateIE9\">\n");
wholeScript.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n");
- wholeScript.append("<script type=\"text/javascript\" src=\""+ AppUtils.getBaseFolderURL() +"dy3/js/dygraph-combined.js\"></script>\n");
- wholeScript.append("<script type=\"text/javascript\" src=\""+ AppUtils.getBaseFolderURL() +"dy3/js/moment.min.js\"></script>\n");
- wholeScript.append("<script type=\"text/javascript\" src=\""+ AppUtils.getBaseFolderURL() +"dy3/js/interaction.min.js\"></script>\n");
+ wholeScript.append("<script type=\"text/javascript\" src=\""+ chartScriptsPath +"dy3/js/dygraph-combined.js\"></script>\n");
+ wholeScript.append("<script type=\"text/javascript\" src=\""+ chartScriptsPath +"dy3/js/moment.min.js\"></script>\n");
+ wholeScript.append("<script type=\"text/javascript\" src=\""+ chartScriptsPath +"dy3/js/interaction.min.js\"></script>\n");
wholeScript.append("<script type=\"text/javascript\">\n");
if(AppUtils.nvl(reportRuntime.getTimeAxisType()).equals("30min")) {
@@ -2959,7 +2968,7 @@ public class ChartD3Helper {
} else if (chartType.equals(AppConstants.GT_SCATTER)) {
- wholeScript.append("<link href=\""+ AppUtils.getBaseFolderURL() +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
+ wholeScript.append("<link href=\""+ chartScriptsPath +"d3/css/nv.d3.css\" rel=\"stylesheet\" type=\"text/css\">\n");
wholeScript.append("<style>\n " +
" body { \n" +
" overflow-y:scroll; \n" +
@@ -2982,15 +2991,15 @@ public class ChartD3Helper {
wholeScript.append("<body> \n");
wholeScript.append("<div id=\"chart1\"><svg></svg></div>");
//js files
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/d3.v2.js\"></script>\n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/nv.d3.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/tooltip.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/utils.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/legend.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/axis.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/distribution.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/scatter.js\"></script> \n");
- wholeScript.append("<script src=\""+ AppUtils.getBaseFolderURL() +"d3/js/models/scatterChart.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/d3.v2.js\"></script>\n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/nv.d3.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/tooltip.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/utils.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/legend.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/axis.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/distribution.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/scatter.js\"></script> \n");
+ wholeScript.append("<script src=\""+ chartScriptsPath +"d3/js/models/scatterChart.js\"></script> \n");
wholeScript.append("<script> \n");
wholeScript.append("nv.addGraph(function() { \n" +
" var width1=900, height1=220; \n" +
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java
index 85f8dc8a..c03fb7ae 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSON.java
@@ -20,6 +20,9 @@
package org.openecomp.portalsdk.analytics.model.runtime;
import java.util.ArrayList;
+import java.util.Map;
+
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
class Row {
private String displayValue;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java
index d08626c1..d08626c1 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartJSONHelper.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java
index 3fb24402..b035187d 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartWebRuntime.java
@@ -35,10 +35,13 @@ import javax.servlet.http.HttpSession;
import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.model.ReportHandler;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
import org.openecomp.portalsdk.analytics.system.AppUtils;
import org.openecomp.portalsdk.analytics.util.AppConstants;
import org.openecomp.portalsdk.analytics.view.ReportData;
import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
public class ChartWebRuntime implements Serializable {
@@ -134,8 +137,8 @@ public class ChartWebRuntime implements Serializable {
//if(genReportData)
//reportData = rr.loadHiveLinearReportData(rr.getWholeSQL(),user_id.toString(), 10000,request);
} else {
- //if(genReportData)
- //reportData = rr.loadReportData(0, user_id.toString(), 10000,request, false /*download*/);
+ if(genReportData)
+ reportData = rr.loadReportData(0, user_id.toString(), 10000,request, false /*download*/);
}
} catch (RaptorException ex) {
ex.printStackTrace();
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java
index e8ba2ee5..e3e9fc67 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/CommonChartOptions.java
@@ -78,4 +78,4 @@ public class CommonChartOptions {
public void setRightMargin(int rightMargin) {
this.rightMargin = rightMargin;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java
new file mode 100644
index 00000000..04068ef2
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java
@@ -0,0 +1,58 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.runtime;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
+import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+import org.openecomp.portalsdk.analytics.view.DataValue;
+import org.openecomp.portalsdk.analytics.xmlobj.ColFilterList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+
+public class ErrorJSONRuntime {
+
+ private String errormessage;
+ private String stacktrace;
+
+ public String getErrormessage() {
+ return errormessage;
+ }
+ public void setErrormessage(String errormessage) {
+ this.errormessage = errormessage;
+ }
+ public String getStacktrace() {
+ return stacktrace;
+ }
+ public void setStacktrace(String stacktrace) {
+ this.stacktrace = stacktrace;
+ }
+
+
+
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java
index 3b3060bb..3b3060bb 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FlexTimeSeriesChartOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java
index ea215679..6d9730a5 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormField.java
@@ -44,28 +44,20 @@ package org.openecomp.portalsdk.analytics.model.runtime;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.swing.text.html.HTMLDocument.HTMLReader.HiddenAction;
+
+import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
import org.openecomp.portalsdk.analytics.error.UserDefinedException;
-import org.openecomp.portalsdk.analytics.model.base.IdNameList;
-import org.openecomp.portalsdk.analytics.model.base.IdNameLookup;
-import org.openecomp.portalsdk.analytics.model.base.IdNameSql;
-import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.Utils;
-import org.openecomp.portalsdk.analytics.xmlobj.JavascriptItemType;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class FormField extends org.openecomp.portalsdk.analytics.RaptorObject implements Serializable {
private static final String HTML_FORM = "formd";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java
index 57fec736..410c0cd9 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/FormatProcessor.java
@@ -19,19 +19,13 @@
*/
package org.openecomp.portalsdk.analytics.model.runtime;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import org.openecomp.portalsdk.analytics.RaptorObject;
-import org.openecomp.portalsdk.analytics.system.DbUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.view.DataRow;
-import org.openecomp.portalsdk.analytics.view.DataValue;
-import org.openecomp.portalsdk.analytics.view.HtmlFormatter;
-import org.openecomp.portalsdk.analytics.xmlobj.FormatType;
-import org.openecomp.portalsdk.analytics.xmlobj.SemaphoreType;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.view.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class FormatProcessor extends RaptorObject {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java
index 1bc3bbba..1bc3bbba 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/Item.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java
index 118356a7..118356a7 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/LookupDBInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java
index d9e93f55..9b5bf8d8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/RangeAxisJSON.java
@@ -90,4 +90,4 @@ public class RangeAxisJSON {
return "";
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java
index 7e185618..bce35a6b 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportFormFields.java
@@ -19,26 +19,16 @@
*/
package org.openecomp.portalsdk.analytics.model.runtime;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
-
-import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import javax.servlet.http.*;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.model.DataCache;
-import org.openecomp.portalsdk.analytics.model.base.ReportWrapper;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.Utils;
-import org.openecomp.portalsdk.analytics.xmlobj.ColFilterType;
-import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
-import org.openecomp.portalsdk.analytics.xmlobj.FormFieldType;
+import org.openecomp.portalsdk.analytics.model.*;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.model.definition.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class ReportFormFields extends Vector {
private int nextElemIdx = 0;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java
index 7556a310..78f413a6 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportJSONRuntime.java
@@ -23,8 +23,16 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.json.JSONObject;
import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
import org.openecomp.portalsdk.analytics.view.ColumnHeader;
+import org.openecomp.portalsdk.analytics.view.DataValue;
+import org.openecomp.portalsdk.analytics.xmlobj.ColFilterList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnList;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
/*class MetaColumn {
private String tableId;
@@ -539,6 +547,7 @@ public class ReportJSONRuntime {
private String colIdxTobeFreezed;
private int numFormCols;
private String message;
+ private boolean hideFormFieldsAfterRun;
public boolean isChartAvailable() {
@@ -687,6 +696,12 @@ public class ReportJSONRuntime {
public void setChartWizardAvailable(boolean chartWizardAvilable) {
this.chartWizardAvailable = chartWizardAvilable;
}
+ public boolean isHideFormFieldsAfterRun() {
+ return hideFormFieldsAfterRun;
+ }
+ public void setHideFormFieldsAfterRun(boolean hideFormFieldsAfterRun) {
+ this.hideFormFieldsAfterRun = hideFormFieldsAfterRun;
+ }
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java
index e3bbe4d0..30c76cd8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamDateValueParser.java
@@ -19,14 +19,16 @@
*/
package org.openecomp.portalsdk.analytics.model.runtime;
+import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.GregorianCalendar;
+import java.util.*;
+import javax.servlet.http.*;
+import org.openecomp.portalsdk.analytics.model.base.*;
import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.Utils;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class ReportParamDateValueParser {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java
index 66b5f517..ebc103d1 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValues.java
@@ -33,11 +33,10 @@ import org.openecomp.portalsdk.analytics.util.AppConstants;
import org.openecomp.portalsdk.analytics.util.DataSet;
import org.openecomp.portalsdk.analytics.util.Utils;
import org.openecomp.portalsdk.analytics.util.XSSFilter;
-import org.openecomp.portalsdk.core.controller.FavoritesController;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
public class ReportParamValues extends Hashtable {
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FavoritesController.class);
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ReportParamValues.class);
private Hashtable paramIsMultiValue = null;
private Hashtable paramIsTextAreaValue = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java
index f4bb9800..f4bb9800 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportParamValuesForPDFExcel.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java
index fd8fadcb..78097d6d 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ReportRuntime.java
@@ -597,7 +597,6 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
} // loadChartData
public String getReportDataSQL(String userId, int downloadLimit, HttpServletRequest request) throws RaptorException {
- //String reportSQL = generateSQL(reportParamValues, userId, request);
String reportSQL = "";
if(doesReportContainsGroupFormField()) {
reportSQL = generateSubsetSQL(0, downloadLimit,userId, request, true, reportParamValues);
@@ -616,9 +615,6 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
if(isGoBackAction && rd!=null) return rd;
if (rd == null) { // Commented So that Data is refreshed from DB again
if (getReportDataSize() < 0)
- //if (pageNo > 0)
- //pageNo = 0;
-
if (getReportType().equals(AppConstants.RT_CROSSTAB))
rd = loadCrossTabReportData(pageNo, userId, downloadLimit, request, download);
else if (getReportType().equals(AppConstants.RT_LINEAR))
@@ -640,19 +636,8 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
private ReportData loadCrossTabReportData(int pageNo, String userId, int downloadLimit, HttpServletRequest request, boolean download) throws RaptorException {
String reportSQL = generateSQL(reportParamValues, userId, request);
setWholeSQL(reportSQL);
- //if(getReportDefType().equals(AppConstants.RD_SQL_BASED))
- // reportSQL = new SQLCorrector().fixCrosstabSQL(new StringBuffer(reportSQL));
cachedSQL = reportSQL;
wholeSQL = reportSQL;
- //if (crossTabOrderManager == null
- ///*&& (!getReportDefType().equals(AppConstants.RD_SQL_BASED))*/)
- //crossTabOrderManager = new CrossTabOrderManager(this, userId,request);
-/* boolean isGoBackAction = AppUtils.getRequestFlag(request, AppConstants.RI_GO_BACK);
- if(isGoBackAction) {
- crossTabOrderManager = null;
- crossTabOrderManager = new CrossTabOrderManager(this, userId,request);
- }
-*/
List reportCols = getAllColumns();
// replace the request parameter specified in the drill down
DataColumnType dataColumnRequest = getCrossTabValueColumn();
@@ -696,15 +681,6 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
if (crossTabOrderManager == null)
crossTabOrderManager = new CrossTabOrderManager(this, userId,request);
ds = ConnectionUtils.getDataSet(reportSQL, dbInfo);
- // if ( (remDbInfo!=null) && (!remDbInfo.equals(AppConstants.DB_LOCAL)))
- // ds = RemDbUtils.executeQuery(reportSQL);
- // else
- // ds = DbUtils.executeQuery(reportSQL);
- /*
- * } catch(SQLException e) { throw new
- * ReportSQLException("[ReportRuntime.loadCrossTabReportData]
- * "+e.getMessage(), reportSQL); }
- */
ReportData rd = new ReportData(pageNo, false);
ReportFormFields childReportFormFields = null;
@@ -1292,7 +1268,7 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
else {
visibleCols.add(count,null);
rd.createColumn(dc.getColId(), AppConstants.HIDDEN, dc.getDisplayWidthInPxls(), dc.getDisplayHeaderAlignment(),
- false, null,false, dc.getLevel()!=null?dc.getLevel():0, dc.getStart()!=null?dc.getStart():0, dc.getColspan()!=null?dc.getColspan():0, dc.isIsSortable()!=null?dc.isIsSortable():false);
+ true, null,false, dc.getLevel()!=null?dc.getLevel():0, dc.getStart()!=null?dc.getStart():0, dc.getColspan()!=null?dc.getColspan():0, dc.isIsSortable()!=null?dc.isIsSortable():false);
// formatProcessors.add(count,null);
}
count++;
@@ -1587,8 +1563,8 @@ public class ReportRuntime extends ReportWrapper implements Cloneable, Serializa
} // if
else {
visibleCols.add(count,null);
- rd.createColumn(dc.getColId(), AppConstants.HIDDEN, dc.getDisplayWidthInPxls(), dc.getDisplayHeaderAlignment(),
- false, null,false, dc.getLevel()!=null?dc.getLevel():0, dc.getStart()!=null?dc.getStart():0, dc.getColspan()!=null?dc.getColspan():0, dc.isIsSortable()!=null?dc.isIsSortable():false);
+ rd.createColumn(dc.getColId(), "", dc.getDisplayWidthInPxls(), dc.getDisplayHeaderAlignment(),
+ true, null,false, dc.getLevel()!=null?dc.getLevel():0, dc.getStart()!=null?dc.getStart():0, dc.getColspan()!=null?dc.getColspan():0, dc.isIsSortable()!=null?dc.isIsSortable():false);
// formatProcessors.add(count,null);
}
count++;
@@ -2525,11 +2501,6 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
}
return title;
}
-// public static void main (String args[])throws Exception {
-// ReportRuntime rr = new ReportRuntime();
-// String sql= " SELECT NULL TOTAL_AC20, NULL TOTAL_AC21, NULL TOTAL_AC22, NULL TOTAL_CO1, NULL TOTAL_BR2, NULL TOTAL_CO3, NULL TOTAL_CO4, NULL TOTAL_HO20, NULL TOTAL_DU9, NULL TOTAL_HO19, NULL TOTAL_CU10, NULL TOTAL_AC11,TO_CHAR (SUM(TO_NUMBER (SE29,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_SE29,TO_CHAR (SUM(TO_NUMBER (BR6,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_BR6,TO_CHAR (SUM(TO_NUMBER (TR7,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_TR7,TO_CHAR (SUM(TO_NUMBER (FE8,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_FE8,TO_CHAR (SUM(TO_NUMBER (TA12,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_TA12,TO_CHAR (SUM(TO_NUMBER (UN13,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_UN13,TO_CHAR (SUM(TO_NUMBER (TA27,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_TA27,TO_CHAR (SUM(TO_NUMBER (TA28,'$9,999,999,990.99')),'$9,999,999,990.99') TOTAL_TA28, NULL TOTAL_CU20, NULL TOTAL_MG23, NULL TOTAL_CU27, NULL TOTAL_CU24, NULL TOTAL_CU28, NULL TOTAL_AC24, NULL TOTAL_CU21, NULL TOTAL_RE25, NULL TOTAL_BI29 FROM (SELECT substr(ACCT_ID,1,3) ac20, substr(ACCT_ID,5,5) ac21, substr(ACCT_ID,11,25) ac22, ci1.CONF_ID co1, ci1.BRIDGE_ID br2, ci1.CONF_RESERVE_DATE co3, ci1.CONF_RESERVE_TIME co4, ci1.HOST_PARTICIPANT_NUMBER ho20, to_number(duration_in_minutes) du9, ci1.HOST_PARTICIPANT_NAME ho19, ci1.CUSTOMER_CONF_ID cu10, ci1.ACCESS_METHOD ac11, TO_CHAR(ci1.SETUP_CHARGES,'$9,999,999,990.99') se29, TO_CHAR(ci1.BRIDGE_CHARGES,'$9,999,999,990.99') br6, TO_CHAR(ci1.TRANSPORT_CHARGES,'$9,999,999,990.99') tr7, TO_CHAR(ci1.FEATURES_CHARGES,'$9,999,999,990.99') fe8, TO_CHAR(ci1.TAXES,'$9,999,999,990.99') ta12, TO_CHAR(Univ_connect_charges+admin_exp_fee+nvl(property_tax_allotment,0)+nvl(federal_regulatory_fee,0),'$9,999,999,990.99') un13, TO_CHAR(setup_charges+Bridge_charges + transport_charges + features_charges-discount,'$9,999,999,990.99') ta27, TO_CHAR(setup_charges + bridge_charges + transport_charges + features_charges + taxes + univ_connect_charges+admin_exp_fee+nvl(property_tax_allotment,0)+nvl(federal_regulatory_fee,0)-discount,'$9,999,999,990.99') ta28, ci1.CUST_ID cu20, ci2.MGD_SVC_FEE mg23, NULL cu27, to_char( DURATION_IN_MINUTES * mgd_svc_fee ,'$9,990.99') cu24, NULL cu28, ci2.ACCESS_DESCRIPTION ac24, decode ( cust_id , '0011681500002' , '00002' , decode ( cust_id , '0011681500092' , '00092' , decode ( cust_id , '0011681500093' , '00093' , substr(cust_id,9,5) ))) cu21, ci1.RECORD_TYPE re25, ci1.BILL_MONTH bi29 FROM CIS_AUDIO ci1, CIS_MGD_SVC_FEE ci2 WHERE ci2.ACCESS_METHOD (+)=ci1.ACCESS_METHOD AND substr(ACCT_ID,1,3) = '215' AND decode ( cust_id , '0011681500002' , '00002' , decode ( cust_id , '0011681500092' , '00092' , decode ( cust_id , '0011681500093' , '00093' , substr(cust_id,9,5) ))) IN ('00002') AND ci1.BILL_MONTH = 'NOV 2006' ORDER BY ci1.ACCESS_METHOD ASC) totalSQL";
-// rr.parseReportSQL(sql);
-// }
public synchronized Object clone() {
try {
@@ -2540,206 +2511,13 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
}
}
- /* private Vector addForecastData(String sql) throws Exception {
- InstanceQuery instTrainQuery = new InstanceQuery();
- //instTrainQuery.setDatabaseURL("jdbc:idb:=experiments.prp");
- instTrainQuery.setUsername("fusionapp");
- instTrainQuery.setPassword("i64eq4aunp");
- Instances data = instTrainQuery.retrieveInstances(sql);
-
- ArrayList<String> forecastArray = new ArrayList<String>();
-
- List reportCols = getAllColumns();
- DataColumnType dct = null;
- Iterator iter = null;
-
- String dateAttribute = "";
-
- for(iter=reportCols.iterator(); iter.hasNext(); ) {
- dct = (DataColumnType) iter.next();
- if(nvl(dct.getDataMiningCol()).equals(AppConstants.DM_FORECASTING_ATTR))
- forecastArray.add(dct.getColId().toUpperCase());
- }
-
- for(iter=reportCols.iterator(); iter.hasNext(); ) {
- dct = (DataColumnType) iter.next();
- if(nvl(dct.getDataMiningCol()).equals(AppConstants.DM_DATE_ATTR))
- dateAttribute = dct.getColId().toUpperCase();
- }
-
-
- int forecastUnits = getForecastingPeriod();
- // new forecaster
- WekaForecaster forecaster = new WekaForecaster();
-
- // set the targets we want to forecast. This method calls
- // setFieldsToLag() on the lag maker object for us
- StringBuffer forecastAttribute = new StringBuffer("");
- for (int i=0; i < forecastArray.size(); i++) {
- forecastAttribute.append(forecastArray.get(i));
- if(i<forecastArray.size()-1) forecastAttribute.append(",");
- }
- forecaster.setFieldsToForecast(forecastAttribute.toString());
-
- // default underlying classifier is SMOreg (SVM) - we'll use
- // gaussian processes for regression instead
- if(getClassifier().equals(AppConstants.DM_GAUSSIAN_CLASSIFIER))
- forecaster.setBaseForecaster(new GaussianProcesses());
- else if (getClassifier().equals(AppConstants.DM_SVM_CLASSIFIER))
- forecaster.setBaseForecaster(new weka.classifiers.functions.SMOreg());
-
- forecaster.getTSLagMaker().setTimeStampField(dateAttribute); // date time stamp
- forecaster.getTSLagMaker().setMinLag(1);
- forecaster.getTSLagMaker().setMaxLag(12); // monthly data
-
- // add a month of the year indicator field
- forecaster.getTSLagMaker().setAddMonthOfYear(true);
-
- // add a quarter of the year indicator field
- forecaster.getTSLagMaker().setAddQuarterOfYear(true);
-
- // build the model
- forecaster.buildForecaster(data, System.out);
-
- // prime the forecaster with enough recent historical data
- // to cover up to the maximum lag. In our case, we could just supply
- // the 12 most recent historical instances, as this covers our maximum
- // lag period
- forecaster.primeForecaster(data);
-
- // forecast for 12 units (months) beyond the end of the
- // training data
- List<List<NumericPrediction>> forecast = forecaster.forecast(getForecastingPeriod(), System.out);
-
- String dateFormat = "";
- if(nvl(getForecastingTimeFormat()).length()>0)
- dateFormat = getForecastingTimeFormat();
- java.text.SimpleDateFormat sdf = null;
- java.text.SimpleDateFormat sdf1 = null;
- java.text.SimpleDateFormat sdf2 = null;
- if(dateFormat.equals("Default")) {
- sdf = new SimpleDateFormat("yyyy-MM-dd\'T\'HH:mm:ss");
- sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- } else {
- sdf = new SimpleDateFormat("yyyy-MM-dd\'T\'HH:mm:ss");
- sdf1 = new SimpleDateFormat(dateFormat);
- sdf2 = new SimpleDateFormat("MM/yyyy");
- }
- // output the predictions. Outer list is over the steps; inner list is over
- // the targets
- int k = 0;
- int flag = 0;
- Enumeration<Attribute> enum1 = data.lastInstance().enumerateAttributes();
- Attribute attrib = null;
-
- HashMap<String, Object> predictedHashMap = new HashMap<String, Object>();
-
- while(enum1.hasMoreElements()) {
- attrib = enum1.nextElement();
- System.out.println(attrib.name() + " " + attrib.index());
- }
- Vector<Vector> forecastedDataSet = new Vector<Vector>();
- Vector forecastedData = new Vector();
- Date d = null;
- Date forecastedDate = null;
- Calendar c1 = Calendar.getInstance();
- for (int i = 0; i < forecastUnits; i++) {
- TSLagMaker ts = forecaster.getTSLagMaker();
- //java.sql.Timestamp ts1 = new java.sql.Timestamp(new Long(ts.getCurrentTimeStampValue()).longValue());
- //System.out.println(data.lastInstance().dataset().attribute(0).getDateFormat());//parseDate("yyyy-MM-dd\'T\'HH:mm:ss")
- //System.out.println(data.lastInstance().dataset().lastInstance().stringValue(0) + " " + sdf.parse(data.lastInstance().dataset().lastInstance().stringValue(0)));
- d = sdf.parse(data.lastInstance().dataset().lastInstance().stringValue(0));
- c1.setTime(d);
- c1.add(Calendar.MONTH, i+1);
- forecastedDate = c1.getTime();
- List<NumericPrediction> predsAtStep = forecast.get(i);
- predictedHashMap.put(dateAttribute, sdf1.format(forecastedDate));
- predictedHashMap.put(dateAttribute+"_FORMAT", sdf2.format(forecastedDate));
-
- for (int j = 0; j < forecastArray.size(); j++) {
- NumericPrediction predForTarget = predsAtStep.get(j);
- predictedHashMap.put(forecastArray.get(j), new Integer(new Double(predForTarget.predicted()).intValue()).toString());
- //System.out.print(forecastArray.get(j)+" " + predForTarget.predicted());
- }
-
- enum1 = data.lastInstance().enumerateAttributes();
- while(enum1.hasMoreElements()) {
- attrib = enum1.nextElement();
- if((!attrib.name().equals(dateAttribute)) && (!attrib.name().equals(dateAttribute+"_FORMAT"))){
- for (int h=0; h < forecastArray.size(); h++) {
- if(attrib.name().equals(forecastArray.get(h))) {
- forecastedData.add(predictedHashMap.get(attrib.name()));
- flag = 1;
- }
-
- }
- } else if(attrib.name().equals(dateAttribute+"_FORMAT")) {
- forecastedData.add(predictedHashMap.get(dateAttribute+"_FORMAT"));
- flag = 1;
- } else if(attrib.name().equals(dateAttribute)) {
- forecastedData.add(predictedHashMap.get(dateAttribute));
- flag = 1;
- }
- if(flag == 0) {
- forecastedData.add("");
- } / *else {
- forecastedData.add(predictedHashMap.get(dateAttribute));
- forecastedData.add(predictedHashMap.get(dateAttribute+"_format"));
- }* /
- //System.out.println(attrib.name() + " " + attrib.index());
-
-
-
-
-
- flag = 0;
-
- }
- forecastedDataSet.add(forecastedData);
- predictedHashMap = new HashMap<String, Object>();
- forecastedData = new Vector();
- enum1 = data.lastInstance().enumerateAttributes();
- }
- setReportDataSize(getReportDataSize()+getForecastingPeriod());
- return forecastedDataSet;
- } */
-
public VisualManager getVisualManager() {
return visualManager;
}
public String getReportSQLWithRowNum(String _orderBy, boolean asc) {
String sql = getWholeSQL();
- int closeBracketPos = 0;
- /*if (nvl(_orderBy).length() > 0) {
- if(sql.lastIndexOf(")")!= -1) closeBracketPos = sql.lastIndexOf(")");
- int idxOrderBy = (closeBracketPos>0)?sql.toUpperCase().indexOf("ORDER BY", closeBracketPos):sql.toUpperCase().lastIndexOf("ORDER BY");
- DataColumnType dct = getColumnById(_orderBy+"_sort");
- if(dct!=null && dct.getColName().length()>0) {
- _orderBy = _orderBy+"_sort";
- }
- if (idxOrderBy < 0)
- sql += " ORDER BY " + _orderBy + " " + (asc ? "ASC" : "DESC");
- else {
- int braketCount = 0;
- int idxOrderByClauseEnd = 0;
- for (idxOrderByClauseEnd = idxOrderBy; idxOrderByClauseEnd < sql.length(); idxOrderByClauseEnd++) {
- char ch = sql.charAt(idxOrderByClauseEnd);
-
- if (ch == '(')
- braketCount++;
- else if (ch == ')') {
- if (braketCount == 0)
- break;
- braketCount--;
- }
- } // for
-
- sql = sql.substring(0, idxOrderBy) + " ORDER BY " + _orderBy + " "
- + (asc ? "ASC" : "DESC") + sql.substring(idxOrderByClauseEnd);
- } // else
- } // if*/
-
+ int closeBracketPos = 0;
// Added reportSQLOnlyFirstPart which has Column information with Rownum
return nvl(getReportSQLOnlyFirstPart()) + " " + sql + ") x ";
@@ -2894,9 +2672,13 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
private boolean isAllowEdit(HttpServletRequest request) {
boolean allowEdit = false;
+ String userId = AppUtils.getUserID(request);
try {
if( AppUtils.isAdminUser(request) || AppUtils.isSuperUser(request) ) {
allowEdit = true;
+ } else {
+ if(getOwnerID().equals(userId)) allowEdit = true;
+ else allowEdit = false;
}
} catch (RaptorException ex) {
allowEdit = false;
@@ -2908,6 +2690,7 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
ObjectMapper mapper = new ObjectMapper();
ReportJSONRuntime reportJSONRuntime = new ReportJSONRuntime();
reportJSONRuntime.setReportTitle(getReportTitle());
+ //reportJSONRuntime.setReportSubTitle(getReportSubTitle());
reportJSONRuntime.setReportID(getReportID());
reportJSONRuntime.setReportDescr(getReportDescr());
reportJSONRuntime.setReportName(getReportName());
@@ -2925,6 +2708,7 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
reportJSONRuntime.setChartWizardAvailable(displayChartWizard);
reportJSONRuntime.setDisplayData(!isDisplayOptionHideData());
reportJSONRuntime.setDisplayForm(!isDisplayOptionHideForm());
+ reportJSONRuntime.setHideFormFieldsAfterRun(isHideFormFieldAfterRun());
reportJSONRuntime.setDisplayExcel(!isDisplayOptionHideExcelIcons());
reportJSONRuntime.setDisplayPDF(!isDisplayOptionHidePDFIcons());
ArrayList<IdNameValue> formFieldValues = new ArrayList<IdNameValue>();
@@ -3216,7 +3000,6 @@ public List getMapMarkers(ReportData rd, org.openecomp.portalsdk.analytics.xmlob
private void refreshFormFieldsWithLatestValue(HttpServletRequest request, String userId, FormField ff_src, ArrayList<FormFieldJSON> formFieldJSONList) {
ArrayList<IdNameValue> formFieldValues = new ArrayList<IdNameValue>();
- //ArrayList<FormFieldJSON> formFieldJSONList = new ArrayList<FormFieldJSON>();
List<String> requestValueList = null;
IdNameList lookup = null;
lookup = ff_src.getLookupList();
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java
index 9e6f657f..9e6f657f 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/TimeSeriesChartOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java
index 9587de53..07929ea1 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/VisualManager.java
@@ -19,10 +19,11 @@
*/
package org.openecomp.portalsdk.analytics.model.runtime;
-import java.util.HashMap;
+import java.util.*;
-import org.openecomp.portalsdk.analytics.RaptorObject;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.analytics.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class VisualManager extends RaptorObject {
private HashMap hiddenCols = new HashMap();
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java
index ec7999e0..567dfeb3 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResult.java
@@ -19,9 +19,10 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class ReportSearchResult extends SearchResult {
private static final String HTML_FORM = "forma";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java
index fda50d54..1c170d36 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/ReportSearchResultJSON.java
@@ -19,15 +19,13 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
-import java.util.ArrayList;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java
new file mode 100644
index 00000000..7d33cab5
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java
@@ -0,0 +1,212 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.model.search;
+
+import java.util.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+
+public class SearchResult{
+ private int pageNo = -1;
+
+ private int pageSize = 50;
+
+ private int dataSize = -1;
+
+ private int writeAccessColIndex = -1;
+
+ private int ownerIndicatorColIndex = -1;
+
+ private String csvPageFileName = null;
+
+
+
+ private String csvAllRowsFileName = null;
+
+ private String excelAllRowsFileName = null;
+
+ public ArrayList searchResultColumns = new ArrayList();
+
+ public ArrayList searchResultRows = new ArrayList();
+
+ public SearchResult(int pageNo) {
+ this(pageNo, Globals.getDefaultPageSize());
+ } // SearchResult
+
+ public SearchResult(int pageNo, int pageSize) {
+ this(pageNo, pageSize, -1, -1);
+ } // SearchResult
+
+ public SearchResult(int pageNo, int pageSize, int writeAccessColIndex,
+ int ownerIndicatorColIndex) {
+ super();
+
+ this.pageNo = pageNo;
+ this.pageSize = pageSize;
+
+ this.writeAccessColIndex = writeAccessColIndex;
+ this.ownerIndicatorColIndex = ownerIndicatorColIndex;
+ } // SearchResult
+
+ public int getPageNo() {
+ return pageNo;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public int getDataSize() {
+ return dataSize;
+ }
+
+ public String getCsvPageFileName() {
+ return csvPageFileName;
+ }
+
+ public String getCsvAllRowsFileName() {
+ return csvAllRowsFileName;
+ }
+
+ public String getExcelAllRowsFileName() {
+ return excelAllRowsFileName;
+ }
+
+ private void setDataSize(int dataSize) {
+ this.dataSize = dataSize;
+ }
+
+ public void setCsvPageFileName(String csvPageFileName) {
+ this.csvPageFileName = csvPageFileName;
+ }
+
+
+
+ public void setCsvAllRowsFileName(String csvAllRowsFileName) {
+ this.csvAllRowsFileName = csvAllRowsFileName;
+ }
+
+
+
+ public void addColumn(SearchResultColumn column) {
+ searchResultColumns.add(column);
+ } // addColumn
+
+ public SearchResultColumn getColumn(int index) {
+ return (SearchResultColumn) searchResultColumns.get(index);
+ } // getColumn
+
+ public int getNumColumns() {
+ return searchResultColumns.size();
+ } // getNumColumns
+
+ public int getNumRows() {
+ return searchResultRows.size();
+ } // getNumRows
+
+ public SearchResultRow getRow(int index) {
+ return (SearchResultRow) searchResultRows.get(index);
+ } // getRow
+
+ public void parseData(DataSet ds, HttpServletRequest request) throws RaptorException {
+ // Presumes single ID field in the first column of the DataSet and row
+ // number in the first SearchResultColumn
+ String userID = AppUtils.getUserID(request);
+ setDataSize(ds.getRowCount());
+
+ int startRow = (pageNo >= 0) ? (pageNo * pageSize) : 0;
+ int endRow = (pageNo >= 0) ? Math.min(startRow + pageSize, ds.getRowCount()) : ds
+ .getRowCount();
+ for (int r = startRow; r < endRow; r++) {
+ SearchResultRow row = new SearchResultRow();
+ searchResultRows.add(row);
+
+ String idValue = ds.getString(r, 0);
+
+ boolean bCanEdit = true;
+ if (writeAccessColIndex >= 0) {
+ String isReadOnlyValue = nvl(ds.getString(r, writeAccessColIndex), "Y");
+ bCanEdit = AppUtils.isSuperUser(request) || AppUtils.isAdminUser(request)
+ || isReadOnlyValue.equals("N");
+ }
+
+ boolean bCanDelete = bCanEdit;
+ if (Globals.getDeleteOnlyByOwner() && ownerIndicatorColIndex >= 0) {
+ String isOwnedByUserRecord = nvl(ds.getString(r, ownerIndicatorColIndex), "N");
+ bCanDelete = AppUtils.isSuperUser(request) || isOwnedByUserRecord.equals("Y");
+ }
+
+ boolean bCanSchedule = ds.getString(r, getNumColumns()-3).equals("Y");
+
+ row.addSearchResultField(new SearchResultField("" + (r + 1), idValue,
+ getColumn(0), true));
+ boolean isAuthorized = true;
+ for (int c = 1; c < getNumColumns(); c++) {
+ SearchResultColumn column = getColumn(c);
+ isAuthorized = true;
+
+ if(column.isCopyLink())
+ isAuthorized = Globals.getCanCopyOnReadOnly()? true:bCanEdit;
+ else if (column.isDeleteLink())
+ isAuthorized = bCanDelete;
+ else if (column.isEditLink())
+ isAuthorized = bCanEdit;
+ else if (column.isScheduleLink())
+ isAuthorized = bCanSchedule;
+
+ row.addSearchResultField(new SearchResultField(
+ (column.getLinkURL() == null) ? ds.getString(r, c) : column
+ .getLinkTitle(), idValue, column, isAuthorized
+ ));
+ } // for
+ } // for
+ } // parseData
+
+ public void truncateToPage(int pageNo) {
+ if (this.pageNo >= 0 || pageNo < 0)
+ return;
+
+ this.pageNo = pageNo;
+
+ int startRow = pageNo * pageSize;
+ int endRow = Math.min(startRow + pageSize, dataSize);
+
+ for (int r = getNumRows() - 1; r >= endRow; r--)
+ searchResultRows.remove(r);
+
+ for (int r = startRow - 1; r >= 0; r--)
+ searchResultRows.remove(r);
+ } // truncateToPage
+
+ /** *********************************************************************** */
+
+ private String nvl(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ private String nvl(String s, String sDefault) {
+ return nvl(s).equals("") ? sDefault : s;
+ }
+
+} // SearchResult
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java
index bca1f4cf..3c0f68e4 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultColumn.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
+import org.openecomp.portalsdk.analytics.util.*;
+
public class SearchResultColumn extends org.openecomp.portalsdk.analytics.RaptorObject {
private String columnId = "";
private String columnTitle = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java
index a0621553..bae32b19 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultField.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.analytics.util.*;
public class SearchResultField extends org.openecomp.portalsdk.analytics.RaptorObject {
private String columnId;
@@ -65,11 +65,13 @@ public class SearchResultField extends org.openecomp.portalsdk.analytics.RaptorO
setDisplayValue(displayValue);
setAlignment(column.getAlignment());
if(column.getColumnId().equals("edit")) {
- setDrillDownLink("report_wizard.htm?action=report.edit&c_master="+linkIdValue);
+// setDrillDownLink("report_wizard.htm?action=report.edit&c_master="+linkIdValue);
+ setDrillDownLink("report#/report_wizard/"+linkIdValue);
setDrillDownImage(column.getLinkImg());
setConfirmationText(null);
} else if(column.getColumnId().equals("copy")) {
- setDrillDownLink("report_wizard.htm?action=report.copy&c_master="+linkIdValue);
+// setDrillDownLink("report_wizard.htm?action=report.copy&c_master="+linkIdValue);
+ setDrillDownLink("report#/report_wizard/copy/"+linkIdValue);
setDrillDownImage(column.getLinkImg());
setConfirmationText(column.getLinkConfirmMsg());
} else if(column.getColumnId().equals("delete")) {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java
index 00e18f12..fb565a84 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultJSON.java
@@ -19,7 +19,13 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
-import java.util.ArrayList;
+import java.util.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class SearchResultJSON{
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java
index 21fb0254..8f53f0b3 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResultRow.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.model.search;
-import java.util.ArrayList;
+import java.util.*;
class ColumnContent {
String columnId;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java
index d5162cc1..e3f2694a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SchedulerUtil.java
@@ -36,11 +36,11 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.error.ReportSQLException;
import org.openecomp.portalsdk.analytics.system.DbUtils;
-
+//import oracle.jdbc.*;
+//import oracle.sql.BLOB;
public class SchedulerUtil {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java
index 6f51cee4..28208bca 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendEmail.java
@@ -41,6 +41,7 @@ import org.openecomp.portalsdk.analytics.system.Globals;
+
public class SendEmail {
SchedulerUtil schedulerUtil;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java
index 40adbee4..fefad844 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/scheduler/SendNotifications.java
@@ -25,6 +25,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
+import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
@@ -32,6 +33,7 @@ import org.openecomp.portalsdk.analytics.error.RaptorException;
import org.openecomp.portalsdk.analytics.error.ReportSQLException;
import org.openecomp.portalsdk.analytics.scheduler.SchedulerUtil.Executor;
import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.util.Log;
public class SendNotifications {
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java
new file mode 100644
index 00000000..2b87b1ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java
@@ -0,0 +1,344 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import javax.servlet.http.*;
+
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.util.*;
+
+public class AppUtils /* implements IAppUtils */{
+ private static String baseURL = null;
+
+ private AppUtils() {
+ }
+
+ /** ******************************************************** */
+
+ public static String generateFileName(HttpServletRequest request, String fileTypeExtension) {
+ return AppConstants.FILE_PREFIX + getUserID(request) + fileTypeExtension;
+ } // generateFileName
+
+ public static String generateUniqueFileName(HttpServletRequest request, String reportName, String fileTypeExtension) {
+ String formattedReportName = new HtmlStripper().stripSpecialCharacters(reportName);
+ String formattedDate = new SimpleDateFormat("MMddyyyyHHmm").format(new Date());
+ return formattedReportName+formattedDate+getUserID(request)+fileTypeExtension;
+ } // generateFileName
+
+ public static String getRequestValue(HttpServletRequest request, String valueID) {
+ String value = (String) request.getAttribute(valueID);
+ if (value == null)
+ value = request.getParameter(valueID);
+ return value;
+ } // getRequestValue
+
+ public static String getRequestNvlValue(HttpServletRequest request, String valueID) {
+ String value = getRequestValue(request, valueID);
+ return (value == null) ? "" : value;
+ } // getRequestValue
+
+ public static boolean getRequestFlag(HttpServletRequest request, String valueID) {
+ String value = getRequestNvlValue(request, valueID);
+ return value.toLowerCase().equals("true") || value.toUpperCase().startsWith("Y");
+ } // getRequestFlag
+
+ /** ******************************************************** */
+
+ public static String getUserID(HttpServletRequest request) {
+ return Globals.getAppUtils().getUserID(request);
+ } // getUserID
+
+ public static String getUserName(HttpServletRequest request) {
+ return Globals.getAppUtils().getUserName(request);
+ } // getUserName
+
+ public static String getUserName(String userId) {
+ return Globals.getAppUtils().getUserName(userId);
+ } // getUserName
+
+ public static String getUserEmail(String userId) {
+ return Globals.getAppUtils().getUserEmail(userId);
+ } // getUserEmail
+
+ public static String getUserEmail(HttpServletRequest request) {
+ return Globals.getAppUtils().getUserEmail(request);
+ } // getUserEmail
+
+ public static String getUserLoginId(HttpServletRequest request) {
+ return Globals.getAppUtils().getUserLoginId(request);
+ } // getUserLoginId
+
+ public static String getUserLoginId(String userId) {
+ return Globals.getAppUtils().getUserLoginId(userId);
+ } // getUserLoginId
+
+ public static String getUserBackdoorLoginId(HttpServletRequest request) {
+ return Globals.getAppUtils().getUserBackdoorLoginId(request);
+ } // getUserBackdoorLoginId
+
+ public static Vector getAllUsers(String customizedQuery, String param, boolean isAdmin) {
+ return Globals.getAppUtils().getAllUsers(customizedQuery, param, isAdmin);
+ } // getAllUsers
+
+ public static String getRoleName(String roleId) {
+ return Globals.getAppUtils().getRoleName(roleId);
+ } // getRoleName
+
+ public static Vector getAllRoles(String customizedQuery, String param, boolean isAdmin) {
+ return Globals.getAppUtils().getAllRoles(customizedQuery, param, isAdmin);
+ } // getAllRoles
+
+ public static boolean isUserInRole(HttpServletRequest request, String roleId) throws RaptorException {
+ return Globals.getAppUtils().isUserInRole(request,roleId);
+ } // isUserInRole
+
+// public static boolean isUserInRole(String userId, String roleId) throws RaptorException {
+// return Globals.getAppUtils().isUserInRole(userId, roleId);
+// } // isUserInRole
+
+ public static Vector getUserRoles(HttpServletRequest request) throws RaptorException {
+ return Globals.getAppUtils().getUserRoles(request);
+ } // getUserRoles
+
+ public static Vector getUserRoles(String userID) throws RaptorException {
+ return Globals.getAppUtils().getUserRoles(userID);
+ } // getUserRoles
+
+// public static Vector getUserRoles(HttpServletRequest request) throws RaptorException {
+// return Globals.getAppUtils().getUserRoles(request);
+// } // getUserRoles
+
+ public static void resetUserCache() {
+ Globals.getAppUtils().resetUserCache();
+ } // resetUserCache
+
+ public static String getSuperRoleID() {
+ return Globals.getAppUtils().getSuperRoleID();
+ } // getSuperRoleID
+
+ public static Vector getAdminRoleIDs() {
+ return Globals.getAppUtils().getAdminRoleIDs();
+ } // getAdminRoleIDs
+
+ // This is changed to check for Admin User as admin user also need super user privilege if explicitly specified in properties file.
+ public static boolean isSuperUser(HttpServletRequest request)throws RaptorException {
+ if(Globals.isAdminRoleEquivalenttoSuperRole()) return isAdminUser(request);
+ else return isUserInRole(request, getSuperRoleID());
+ } // isSuperUser
+
+ /*public static boolean isSuperUser(String userId) throws RaptorException {
+ if(Globals.isAdminRoleEquivalenttoSuperRole()) return isAdminUser(userId);
+ else return isUserInRole(userId, getSuperRoleID());
+ } // isSuperUser
+ */
+
+ public static boolean isAdminUser(HttpServletRequest request) throws RaptorException {
+ if (isSuperUser(request))
+ return true;
+ for (int i = 0; i < getAdminRoleIDs().size(); i++)
+ if (isUserInRole(request, (String) getAdminRoleIDs().get(i)))
+ return true;
+
+ return false;
+ } // isAdminUser
+
+ /*public static boolean isAdminUser(String userId) throws RaptorException {
+ if (isSuperUser(userId))
+ return true;
+
+ for (int i = 0; i < getAdminRoleIDs().size(); i++)
+ if (isUserInRole(userId, (String) getAdminRoleIDs().get(i)))
+ return true;
+
+ return false;
+ } // isAdminUser
+ */
+
+ public static String getTempFolderPath() {
+ String path = Globals.getAppUtils().getTempFolderPath();
+ if (path.endsWith(File.separator) || path.endsWith("/")){
+ return path;
+ } else {
+ path = path + File.separator;
+ return path;
+ }
+ } // getTempFolderPath
+
+ public static String getUploadFolderPath() {
+ String path = Globals.getAppUtils().getUploadFolderPath();
+ if (path.endsWith(File.separator)){
+ return path;
+ } else {
+ path = path + File.separator;
+ return path;
+ }
+ } // getUploadFolderPath
+
+ public static String getTempFolderURL() {
+ return Globals.getAppUtils().getTempFolderURL();
+ } // getTempFolderURL
+
+ public static String getUploadFolderURL() {
+ return Globals.getAppUtils().getUploadFolderURL();
+ } // getUploadFolderURL
+
+ public static String getSMTPServer()throws Exception {
+ return Globals.getAppUtils().getSMTPServer();
+ } // getSMTPServer
+
+ public static String getDefaultEmailSender() throws RaptorException {
+ return Globals.getAppUtils().getDefaultEmailSender();
+ } // getDefaultEmailSender
+
+ public static String getErrorPage() {
+ return getJspContextPath() + Globals.getAppUtils().getErrorPage();
+ } // getErrorPage
+
+ public static String getErrorPageWMenu() {
+ return getJspContextPath() + Globals.getAppUtils().getErrorPageWMenu();
+ } // getErrorPage
+
+ public static String getJspContextPath() {
+ return Globals.getAppUtils().getJspContextPath();
+ } // getJspContextPath
+
+ public static String getImgFolderURL() {
+ return Globals.getAppUtils().getImgFolderURL();
+ } // getImgFolderURL
+
+ public static String getBaseFolderURL() {
+ return Globals.getAppUtils().getBaseFolderURL();
+ } // getBaseFolderURL
+
+ public static String getChartScriptsPath() {
+ return getFolderPathAdj()+getBaseFolderURL();
+ } // getBaseFolderURL
+
+ public static String getChartScriptsPath(String folderAdj1) {
+ return folderAdj1+getBaseFolderURL();
+ } // getBaseFolderURL
+
+ public static String getFolderPathAdj() {
+ return Globals.getAppUtils().getFolderPathAdj();
+ } // getBaseFolderURL
+
+
+ /*
+ * public static String getReportExecuteActionURL() { return
+ * Globals.getAppUtils().getReportExecuteActionURL(); } //
+ * getReportExecuteActionURL
+ *
+ * public static String getDataViewActionURL() { return
+ * Globals.getAppUtils().getDataViewActionURL(); } // getDataViewActionURL
+ *
+ * public static String getDataViewActionParam() { return
+ * Globals.getAppUtils().getDataViewActionParam(); } //
+ * getDataViewActionParam
+ */
+ public static String getDirectAccessURL() {
+ return Globals.getAppUtils().getDirectAccessURL();
+ } // getDirectAccessURL
+
+ public static String getBaseURL() {
+ if (baseURL == null) {
+ baseURL = getBaseActionURL();
+ if (baseURL.indexOf("?") > 0)
+ baseURL = baseURL.substring(0, baseURL.indexOf("?"));
+ } // if
+
+ return baseURL;
+ } // getBaseURL
+
+ public static String getBaseActionURL() {
+ return Globals.getAppUtils().getBaseActionURL();
+ } // getBaseActionURL
+
+ public static String getDrillActionURL() {
+ return Globals.getAppUtils().getDrillActionURL();
+ } // getBaseActionURL
+
+ public static String getRaptorActionURL() {
+ return Globals.getAppUtils().getBaseActionURL() + "raptor&" + AppConstants.RI_ACTION
+ + "=";
+ } // getRaptorActionURL
+
+ public static String getRaptorActionURLNG() {
+ return Globals.getAppUtils().getBaseActionURLNG();
+ } // getRaptorActionURL
+
+ public static String getReportExecuteActionURL() {
+ return getRaptorActionURL() + "report.run.container&" + AppConstants.RI_REPORT_ID + "="; // getBaseActionParam();
+ } // getReportExecuteActionURL
+
+ public static String getReportExecuteActionURLNG() {
+ return getRaptorActionURLNG() + "report_run/"; // getBaseActionParam();
+ } // getReportExecuteActionURL
+
+ public static String getBaseActionParam() {
+ return Globals.getAppUtils().getBaseActionParam();
+ } // getBaseActionParam
+
+ public static Vector getQuickLinksMenuIDs() {
+ return Globals.getAppUtils().getQuickLinksMenuIDs();
+ } // getQuickLinksMenuIDs
+
+ public static String getMenuLabel(String menuId) {
+ return Globals.getAppUtils().getMenuLabel(menuId);
+ } // getMenuLabel
+
+ public static String getReportDbColsMaskSQL() {
+ return Globals.getAppUtils().getReportDbColsMaskSQL();
+ } // getReportDbColsMaskSQL
+
+ public static String getReportDbLookupsSQL() {
+ return Globals.getAppUtils().getReportDbLookupsSQL();
+ } // getReportDbLookupsSQL
+
+ public static void processErrorNotification(HttpServletRequest request, RaptorException e) {
+ Globals.getAppUtils().processErrorNotification(request, e);
+ } // processErrorNotification
+
+ public static String getExcelTemplatePath() {
+ String path = Globals.getAppUtils().getExcelTemplatePath();
+ if (path.endsWith(File.separator)){
+ return path;
+ } else {
+ path = path + File.separator;
+ return path;
+ }
+ } // getTempFolderPath
+
+ public static String nvl(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ public static boolean isNotEmpty(String s) {
+ return nvl(s).length()>0;
+ }
+ public static String nvls(String s, String sDefault) {
+ return nvl(s).equals("") ? sDefault : s;
+ }
+
+} // AppUtils
+
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java
index 58fb3f25..58fb3f25 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ConnectionUtils.java
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java
new file mode 100644
index 00000000..1a80f656
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java
@@ -0,0 +1,271 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+
+import javax.sql.DataSource;
+
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.error.ReportSQLException;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
+import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.web.support.AppUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DbUtils /* implements IDbUtils */{
+
+ static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DbUtils.class);
+
+ private static DataSource dataSource;
+
+ public DbUtils() {
+ }
+
+ public static Connection getConnection() throws ReportSQLException {
+ try {
+ return AppUtils.getDatasource().getConnection();
+ } catch(SQLException ex) {
+ ex.printStackTrace();
+ }
+ return null;
+ } // getConnection
+
+ public static void clearConnection(Connection con) throws ReportSQLException {
+ try {
+ if ((con != null) && !con.isClosed())
+ Globals.getDbUtils().clearConnection(con);
+ } catch (SQLException ex) {
+ throw new ReportSQLException(ex.getMessage(), ex.getCause());
+ } catch (Exception ex2 ) {
+ throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
+ }
+ } // clearConnection
+
+ public static Connection startTransaction() throws ReportSQLException {
+ Connection con = null;
+ try {
+ con = getConnection();
+ con.setAutoCommit(false);
+ } catch (SQLException ex) {
+ throw new ReportSQLException (ex.getMessage(), ex.getCause());
+ } catch (Exception ex2 ) {
+ throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
+ }
+ return con;
+ } // startTransaction
+
+ public static void commitTransaction(Connection con) throws ReportSQLException {
+ try {
+ con.commit();
+ } catch (SQLException ex) {
+ throw new ReportSQLException (ex.getMessage(), ex.getCause());
+ } catch (Exception ex2 ) {
+ throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
+ }
+ } // commitTransaction
+
+ public static void rollbackTransaction(Connection con) throws ReportSQLException {
+ try {
+ con.rollback();
+ clearConnection(con);
+ } catch (SQLException ex) {
+ throw new ReportSQLException (ex.getMessage(), ex.getCause());
+ } catch (Exception ex2 ) {
+ throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
+ }
+ } // rollbackTransaction
+
+ public static String executeCall(Connection con, String sql, boolean expectResult)
+ throws ReportSQLException {
+ String result = null;
+
+ try {
+ if(con.isClosed()) con = getConnection();
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL Call] " + sql));
+ CallableStatement stmt = con.prepareCall(sql);
+ if (expectResult)
+ stmt.registerOutParameter(1, Types.CHAR);
+ stmt.executeUpdate();
+ if (expectResult)
+ result = stmt.getString(1);
+ stmt.close();
+ con.commit();
+ } catch (SQLException e) {
+ throw new ReportSQLException(e.getMessage(), sql);
+ } finally {
+ clearConnection(con);
+ }
+
+ return result;
+ } // executeCall
+
+ public static String executeCall(String sql, boolean expectResult)
+ throws RaptorException {
+ Connection con = null;
+ con = getConnection();
+ String result = executeCall(con, sql, expectResult);
+ //con.commit();
+ return result;
+ } // executeCall
+
+ public static int executeUpdate(Connection con, String sql) throws ReportSQLException {
+ int rcode = -1;
+ try {
+ Statement stmt = con.createStatement();
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL Update] " + sql));
+ rcode = stmt.executeUpdate(sql);
+ stmt.close();
+ //con.commit();
+ } catch (SQLException e) {
+ //e.printStackTrace();
+ throw new ReportSQLException(e.getMessage(), sql);
+ }
+ return rcode;
+ } // executeUpdate
+
+ public static int executeUpdate(String sql) throws ReportSQLException {
+ Connection con = null;
+ try {
+ con = getConnection();
+ int rcode = executeUpdate(con, sql);
+ if(Globals.getDBType().equals("oracle"))
+ con.commit();
+
+ return rcode;
+ } catch (SQLException e) {
+ throw new ReportSQLException(e.getMessage(), sql);
+ } finally {
+ clearConnection(con);
+ }
+ } // executeUpdate
+
+ public static DataSet executeQuery(Connection con, String sql) throws ReportSQLException {
+ return executeQuery(con, sql, Integer.MAX_VALUE);
+ } // executeQuery
+
+ public static DataSet executeQuery(Connection con, String sql, int maxRowLimit)
+ throws ReportSQLException {
+ try {
+ if(con.isClosed()) con = getConnection();
+ //con.
+ Statement stmt = con.createStatement();
+
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL] " + sql));
+ ResultSet rs = stmt.executeQuery(sql);
+ DataSet ds = new DataSet(rs, maxRowLimit);
+
+ if(rs!=null)
+ rs.close();
+ if(stmt!=null)
+ stmt.close();
+
+ return ds;
+ } catch (SQLException e) {
+ throw new ReportSQLException(e.getMessage(), sql);
+ }
+ } // executeQuery
+
+ public static DataSet executeQuery(String sql) throws ReportSQLException {
+ return executeQuery(sql, Integer.MAX_VALUE);
+ } // executeQuery
+
+ public static DataSet executeQuery(String sql, int maxRowLimit) throws ReportSQLException {
+ Connection con = null;
+ try {
+ con = getConnection();
+ return executeQuery(con, sql, maxRowLimit);
+ }catch (ReportSQLException ex) {
+ logger.error(EELFLoggerDelegate.debugLogger, ("Error " + sql));
+ throw new ReportSQLException(ex.getMessage(), ex);
+ }catch(Exception ex1) {
+ throw new ReportSQLException(ex1.getMessage(), ex1.getCause());
+ } finally {
+ clearConnection(con);
+ }
+ } // executeQuery
+
+ //For ZK Support
+
+ public static int executeQuery(ReportRuntime rr, int dateOption) {
+ Connection con = null;
+ int rowCount = 0;
+ try {
+ con = ConnectionUtils.getConnection(rr.getDBInfo());
+ String wholeSql = rr.getWholeSQL();
+
+ DataColumnType dc = rr.getColumnWhichNeedEnhancedPagination();
+ String date_ColId = dc.getColId();
+ String dataFormat = dc.getColFormat();
+ if(dataFormat!=null && dataFormat.length()>0)
+ date_ColId = "to_date("+date_ColId+", '"+ dataFormat +"')";
+ String sql = "";
+ if(dateOption == 1)
+ sql = "select count(distinct to_char("+date_ColId+", 'YYYY/MM')) from ("+wholeSql+")";
+ else if (dateOption == 3)
+ sql = "select count(distinct to_char("+date_ColId+", 'YYYY/MM/DD')) from ("+wholeSql+")";
+ else if (dateOption == 2)
+ sql = "select count(distinct to_char("+date_ColId+", 'YYYY')) from ("+wholeSql+")";
+ DataSet ds = executeQuery(con, sql.toString());
+ rowCount = ds.getInt(0,0);
+ } catch (ReportSQLException ex) {
+ ex.printStackTrace();
+ }catch(Exception ex1) {
+ ex1.printStackTrace();
+ } finally {
+ try {
+ clearConnection(con);
+ } catch (ReportSQLException ex2) {
+ ex2.printStackTrace();
+ }
+ }
+ return rowCount;
+ }
+
+ public String nvl(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ public static String nvls(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ public static String nvl(String s, String sDefault) {
+ return nvls(s).equals("") ? sDefault : s;
+ }
+
+ public static DataSource getDataSource() {
+ return dataSource;
+ }
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ dataSource = dataSource;
+ }
+
+} // DbUtils
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java
index 8d769d4f..5536af0a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/ExecuteQuery.java
@@ -19,6 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.system;
+import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java
index f02600eb..ec6de3a4 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/Globals.java
@@ -111,6 +111,8 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
private static String sheet_name = "Raptor Reports";
+ private static String jFreeVersion = AppConstants.JFV_0911;
+
private static boolean allowSQLBasedReports = true; // whether to allow
// SQL-based report
// definition (security
@@ -476,7 +478,8 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
systemName = nvls(raptorProperties.getProperty("system_name"), "MSA Databank");
baseTitle = nvls(raptorProperties.getProperty("base_title"), "ANALYSIS");
-
+ jFreeVersion = nvls(raptorProperties.getProperty("jfree_version"),
+ AppConstants.JFV_0911);
allowSQLBasedReports = nvls(
raptorProperties.getProperty("allow_sql_based_reports"), "yes")
@@ -567,7 +570,7 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
printFooterInDownload = nvls(
raptorProperties.getProperty("print_footer_in_download"), "no")
.toUpperCase().startsWith("Y");
- footerFirstLine = nvls(raptorProperties.getProperty("footer_first_line"), "");
+ footerFirstLine = nvls(raptorProperties.getProperty("footer_first_line"), "AT&T Proprietary");
footerSecondLine = nvls(raptorProperties.getProperty("footer_second_line"), "Use Pursuant to Company Instructions");
reportsInPoPUpWindow = nvls(
raptorProperties.getProperty("report_in_popup_window"), "no")
@@ -655,6 +658,10 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return baseTitle;
}
+ public static String getJFreeVersion() {
+ return jFreeVersion;
+ }
+
public static String getSystemName() {
return systemName;
}
@@ -765,9 +772,10 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return javaTimeFormat;
}
- public static String getOracleTimeFormat() {
+/* public static String getOracleTimeFormat() {
return oracleTimeFormat;
}
+*/
public static String getRaptorVersion() {
return raptorVersion;
@@ -900,9 +908,9 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return nvls(raptorPdfProperties.getProperty("pdf_data_alternate_color"),"true").trim().equalsIgnoreCase("true");
}
- public static String getAttProprietary() {
+ public static String getPDFFooter() {
- return nvls(raptorPdfProperties.getProperty("pdf_att_proprietary"));
+ return nvls(raptorPdfProperties.getProperty("pdf_footer"));
}
public static boolean isCreatedOwnerInfoNeeded() {
@@ -951,11 +959,11 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return nvls(raptorPdfProperties.getProperty("pdf_word_after_page_number"));
}
- public static float getAttProprieraryFontSize() {
+ public static float getPDFFooterFontSize() {
float size = 7f;
try {
- size = Float.parseFloat(nvls(raptorPdfProperties.getProperty("pdf_att_proprierary_font_size")).trim());
+ size = Float.parseFloat(nvls(raptorPdfProperties.getProperty("pdf_footer_font_size")).trim());
} catch (Exception ex) {
}
@@ -1036,6 +1044,10 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return nvls(raptorProperties.getProperty("schedule_custom_query_for_users"),"").trim();
}
+ public static String getTimeFormat() {
+ return nvls(raptorProperties.getProperty("time_format"),"%m/%d/%Y %h:%i:%s %p").trim();
+ }
+
public static String getCustomizedScheduleQueryForRoles() {
return nvls(raptorProperties.getProperty("schedule_custom_query_for_roles"),"").trim();
}
@@ -1714,6 +1726,14 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return nvls(sqlProperty.getProperty("db.update.report.xml"));
}
+ public static String getDBUpdateReportXmlMySql(){
+ return nvls(sqlProperty.getProperty("db.update.report.xml.mysql"));
+ }
+
+ public static String getDBUpdateReportXmlMySqlSelect(){
+ return nvls(sqlProperty.getProperty("db.update.report.xml.mysql.select"));
+ }
+
public static String getUpdateCustomReportRec(){
return nvls(sqlProperty.getProperty("update.custom.report.rec"));
}
@@ -2136,6 +2156,10 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
return nvls(sqlProperty.getProperty("load.report.search.result"));
}
+ public static String getLoadReportSearchRepIdSql(){
+ return nvls(sqlProperty.getProperty("load.report.search.rep_id_sql"));
+ }
+
public static String getLoadReportSearchInstr(){
return nvls(sqlProperty.getProperty("load.report.search.instr"));
}
@@ -2279,4 +2303,5 @@ public class Globals extends org.openecomp.portalsdk.analytics.RaptorObject {
public static boolean isSystemInitialized() {
return systemInitialized;
}
+
} // Globals
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java
index e239a3f9..e459dde7 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IAppUtils.java
@@ -19,12 +19,12 @@
*/
package org.openecomp.portalsdk.analytics.system;
-import java.util.Vector;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.error.ReportSQLException;
public interface IAppUtils {
void initializeAppUtils(ServletContext servletContext);
@@ -172,4 +172,6 @@ public interface IAppUtils {
/** Returns Excel template PATH web URL */
String getExcelTemplatePath();
+
+ String getFolderPathAdj();
} // IAppUtils
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java
index 5ee42719..9ec2a40f 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/IDbUtils.java
@@ -19,10 +19,11 @@
*/
package org.openecomp.portalsdk.analytics.system;
-import java.sql.Connection;
-
-import javax.servlet.ServletContext;
+import java.sql.*;
+import java.util.*;
+import javax.servlet.*;
+import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
import org.openecomp.portalsdk.analytics.error.ReportSQLException;
public interface IDbUtils {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java
index b9753a51..7351fb41 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RDbUtils.java
@@ -19,9 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.system;
-import java.sql.Connection;
-
-import javax.servlet.ServletContext;
+import java.sql.*;
+import javax.servlet.*;
import org.openecomp.portalsdk.analytics.error.ReportSQLException;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java
index 733a0a38..733a0a38 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/RemDbUtils.java
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java
new file mode 100644
index 00000000..b5aba1df
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java
@@ -0,0 +1,67 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * @author sundar
+ * This class is used to get version and Build information when
+ * user run "java -jar raptor_fusion.jar" command.
+ */
+public class AntBuild {
+
+ public static void main(String[] args) {
+ System.out.println("Jar (raptor_fusion.jar) Information: ");
+ readManifest();
+ }
+
+ public static void readManifest() {
+ try {
+ JarFile jar = new JarFile("./raptor_fusion.jar");
+ Manifest manifest = jar.getManifest();
+
+ Attributes attribs = manifest.getMainAttributes();
+ Iterator it = attribs.entrySet().iterator();
+ while(it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Attributes.Name attributeName = (Attributes.Name) entry.getKey();
+ String attributeValue = (String) entry.getValue();
+ if (attributeName.toString().equals("Created-By"))
+ System.out.println("JDK Version " + " : " + attributeValue);
+ else if (attributeName.toString().equals("Ant-Version"))
+ System.out.println(attributeName.toString() + " : " + attributeValue);
+ else {
+ if(attributeName.toString().startsWith("Raptor"))
+ System.out.println(attributeName.toString() + " : " + attributeValue);
+ }
+ }
+
+ } catch (IOException e) {
+ System.err.println("Cannot read jar-file manifest: "
+ + e.getMessage());
+ }
+ }
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java
new file mode 100644
index 00000000..6ee8e5dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java
@@ -0,0 +1,367 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.analytics.config.ConfigLoader;
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
+import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.system.IAppUtils;
+import org.openecomp.portalsdk.analytics.system.fusion.adapter.RaptorAdapter;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;;
+
+public class AppUtils extends org.openecomp.portalsdk.analytics.RaptorObject implements IAppUtils {
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AppUtils.class);
+
+
+ private static String tempFolderPath = "/artemis/PROJECT1/MSA/databank/WEB-INF/temp/";
+ private static String uploadFolderPath = "/artemis/PROJECT1/MSA/databank/WEB-INF/upload/";
+ private static String tempFolderURL = "temp/";
+ private static String uploadFolderURL = "upload/";
+ private static String SMTPServer = "todo.smtp.server.com";
+ private static String defaultEmailSender = "todo.email.sender.com";
+ private static String errorPage = "error_page";
+ private static String errorPageWMenu = "error_page_wmenu";
+ private static String jspContextPath = "raptor/";
+ private static String imgFolderURL = "raptor/images/";
+ private static String baseFolderURL = "raptor/";
+ //private static String reportExecuteActionURL = "dispatcher?action=raptor&r_action=report.run&c_master=";
+ //private static String dataViewActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID
+ //private static String dataViewActionParam = "c_master=";
+ private static String directAccessURL = "http://localhost:8082/databank/dispatcher?direct.access=raptor&r_action=report.run&show=";
+ private static String baseActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
+ private static String baseActionURLNG = "report#/"; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
+ private static String drillActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
+ private static String baseActionParam = "c_master=";
+ private static String superRoleID = "1";
+ private static Vector adminRoleIDs = new Vector();
+ private static Vector quickLinksMenuIDs = new Vector();
+
+ private static Properties raptorAppProperties;
+
+ private static String encryptedSMTPServer = "";
+ public AppUtils() {}
+
+ public void initializeAppUtils(ServletContext servletContext) {
+ try {
+ Properties appProperties = ConfigLoader.getProperties(servletContext, ConfigLoader.APP_PROPERTIES, Globals.getSystemType());
+ raptorAppProperties = appProperties;
+ tempFolderPath = appProperties.getProperty("temp_folder_path");
+ uploadFolderPath = appProperties.getProperty("upload_folder_path");
+ tempFolderURL = appProperties.getProperty("temp_folder_url");
+ uploadFolderURL = appProperties.getProperty("upload_folder_url");
+ SMTPServer = appProperties.getProperty("smtp_server");
+ encryptedSMTPServer = appProperties.getProperty("encrypted_smtp_server");
+ defaultEmailSender = appProperties.getProperty("default_email_sender");
+ errorPage = appProperties.getProperty("error_page");
+ jspContextPath = appProperties.getProperty("jsp_context_path");
+ imgFolderURL = appProperties.getProperty("img_folder_url");
+ baseFolderURL = appProperties.getProperty("base_folder_url");
+/* reportExecuteActionURL = appProperties.getProperty("report_execute_action_url");
+ dataViewActionURL = appProperties.getProperty("data_view_action_url");
+ dataViewActionParam = appProperties.getProperty("data_view_action_param");*/
+ directAccessURL = appProperties.getProperty("direct_access_url");
+ baseActionURL = appProperties.getProperty("base_action_url");
+ baseActionURLNG = appProperties.getProperty("base_action_url_ng");
+ drillActionURL = appProperties.getProperty("drill_action_url");
+ baseActionParam = appProperties.getProperty("base_action_param");
+ superRoleID = appProperties.getProperty("super_role_id");
+
+ adminRoleIDs.removeAllElements();
+ StringTokenizer st = new StringTokenizer(appProperties.getProperty("admin_role_ids"), ",");
+ while(st.hasMoreTokens())
+ adminRoleIDs.add(st.nextToken());
+
+ quickLinksMenuIDs.removeAllElements();
+ st = new StringTokenizer(appProperties.getProperty("quick_links_menu_ids"), ",");
+ while(st.hasMoreTokens())
+ quickLinksMenuIDs.add(st.nextToken());
+ } catch(Exception e) {
+ logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] AppUtils.initializeAppUtils: Unable to load properties ["+Globals.getSystemType()+"_"+ConfigLoader.APP_PROPERTIES+"]. Exception: "+e.getMessage()));
+ //throw new RuntimeException(e.getMessage());
+ }
+ } // initializeAppUtils
+
+ public static void getFullURL(HttpServletRequest req) {
+ String applicationBase = "";
+ if (applicationBase == null) {
+ applicationBase = req.getScheme() + "://" + req.getServerName() +
+ getPort(req) + req.getContextPath();
+ }
+ }
+
+ private static String getPort(HttpServletRequest req) {
+ if ("http".equalsIgnoreCase(req.getScheme()) && req.getServerPort() != 80 ||
+ "https".equalsIgnoreCase(req.getScheme()) && req.getServerPort() != 443 ) {
+ return (":" + req.getServerPort());
+ } else {
+ return "";
+ }
+ }
+ public String getUserID(HttpServletRequest request) {
+ String pdfAttachmentKey = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "pdfAttachmentKey");
+ String report_email_sent_log_id = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "log_id");
+ boolean isEmailAttachment = false;
+ if(pdfAttachmentKey != null && report_email_sent_log_id !=null)
+ isEmailAttachment = true;
+ if(isEmailAttachment) {
+ return RaptorAdapter.getUserID(org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "user_id"));
+ } else
+ return RaptorAdapter.getUserID(request);
+ } // getUserID
+
+ public Vector getAllUsers(String customizedQuery, String param, boolean isAdmin) {
+ Map map = RaptorAdapter.getAllUsers(customizedQuery, param, isAdmin);
+
+ Vector vector = new Vector(map.size());
+ for(Iterator iter=map.keySet().iterator(); iter.hasNext(); ) {
+ Long key = (Long) iter.next();
+ vector.add(new IdNameValue(""+key, (String) map.get(key)));
+ } // for
+
+ return vector;
+ } // getAllUsers
+
+ public String getRoleName(String roleId) {
+ return RaptorAdapter.getRoleName(roleId);
+ } // getRoleName
+
+ public Vector getAllRoles(String customizedQuery, String param, boolean isAdmin) {
+ Map map = RaptorAdapter.getAllRolesUsingCustomizedQuery(customizedQuery, param, isAdmin);
+
+ Vector vector = new Vector(map.size());
+ for(Iterator iter=map.keySet().iterator(); iter.hasNext(); ) {
+ Long key = (Long) iter.next();
+ vector.add(new IdNameValue(""+key, (String) map.get(key)));
+ } // for
+
+ return vector;
+ } // getAllRoles
+
+ public String getUserName(HttpServletRequest request) {
+ return RaptorAdapter.getUserName(request);
+ } // getUserName
+
+ public String getUserName(String userId) {
+ return RaptorAdapter.getUserName(userId);
+ } // getUserName
+
+ public String getUserEmail(String userId) {
+ return RaptorAdapter.getUserEmail(userId);
+ } // getUserEmail
+
+ public String getUserEmail(HttpServletRequest request) {
+ return RaptorAdapter.getUserEmail(request);
+ } // getUserEmail
+
+ public String getUserLoginId(HttpServletRequest request) {
+ return RaptorAdapter.getUserLoginId(request);
+ } // getUserLoginId
+
+ public String getUserLoginId(String userId) {
+ return RaptorAdapter.getUserLoginId(userId);
+ } // getUserLoginId
+
+ public String getUserBackdoorLoginId(HttpServletRequest request) {
+ String pdfAttachmentKey = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "pdfAttachmentKey");
+ String report_email_sent_log_id = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "log_id");
+ boolean isEmailAttachment = false;
+ if(pdfAttachmentKey != null && report_email_sent_log_id !=null)
+ isEmailAttachment = true;
+ if(isEmailAttachment) {
+ return RaptorAdapter.getUserBackdoorLoginId(org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "user_id"));
+ } else
+ return RaptorAdapter.getUserBackdoorLoginId(request);
+ } // getUserBackdoorLoginId
+
+ public boolean isUserInRole(HttpServletRequest request, String roleId) {
+ return RaptorAdapter.isCurrentUserInRole(request, roleId);
+ } // isUserInRole
+
+ public Vector getUserRoles(HttpServletRequest request) {
+// Map map = RaptorAdapter.getAllRoles(userId);
+ Set set = RaptorAdapter.getUserRoles(request);
+
+ Vector vector = new Vector(set.size());
+ for(Iterator iter=set.iterator(); iter.hasNext(); ) {
+ Long key = (Long) iter.next();
+ vector.add(""+key);
+ //vector.add(new IdNameValue(""+key, (String) map.get(key)));
+ } // for
+
+ return vector;
+ } // getUserRoles
+
+ public Vector getUserRoles(String userId) {
+ Set set = RaptorAdapter.getUserRoles(userId);
+
+ Vector vector = new Vector(set.size());
+ for(Iterator iter=set.iterator(); iter.hasNext(); ) {
+ Long key = (Long) iter.next();
+ vector.add(""+key);
+ //vector.add(new IdNameValue(""+key, (String) map.get(key)));
+ } // for
+
+ return vector;
+ //return null;
+ } // getUserRoles
+
+ public void resetUserCache() {
+ //org.openecomp.portalsdk.core.web.support.AppUtils.removeObjectFromCache(RaptorAdapter.KEY_USER_ROLES_CACHE);
+ } // resetUserCache
+
+ public String getSuperRoleID(){
+ return superRoleID;
+ } // getSuperRoleID
+
+ public Vector getAdminRoleIDs(){
+ return adminRoleIDs;
+ } // getAdminRoleIDs
+
+
+ public String getTempFolderPath() {
+ return tempFolderPath;
+ } // getTempFolderPath
+
+ public String getUploadFolderPath() {
+ return uploadFolderPath;
+ } // getUploadFolderPath
+
+ public String getTempFolderURL() {
+ return tempFolderURL;
+ } // getTempFolderURL
+
+ public String getUploadFolderURL() {
+ return uploadFolderURL;
+ } // getUploadFolderURL
+
+ public String getSMTPServer() {
+ return SMTPServer;
+ } // getSMTPServer
+
+ public String getDefaultEmailSender() {
+ return defaultEmailSender;
+ } // getDefaultEmailSender
+
+ public String getErrorPage() {
+ return errorPage;
+ } // getErrorPage
+
+ public String getJspContextPath() {
+ return jspContextPath;
+ } // getJspContextPath
+
+ public String getImgFolderURL() {
+ return imgFolderURL;
+ } // getImgFolderURL
+
+ public String getBaseFolderURL() {
+ return baseFolderURL;
+ } // getBaseFolderURL
+
+/* public String getReportExecuteActionURL() {
+ return reportExecuteActionURL;
+ } // getReportExecuteActionURL
+
+ public String getDataViewActionURL() {
+ return dataViewActionURL;
+ } // getDataViewActionURL
+
+ public String getDataViewActionParam() {
+ return dataViewActionParam;
+ } // getDataViewActionParam
+*/
+ public String getDirectAccessURL() {
+ return directAccessURL.trim();
+ } // getDirectAccessURL
+
+ public String getBaseActionURL() {
+ return baseActionURL;
+ } // getBaseActionURL
+
+ public String getBaseActionURLNG() {
+ return baseActionURLNG;
+ } // getBaseActionURLNG
+
+ public String getDrillActionURL() {
+ return drillActionURL;
+ } // getBaseActionURL
+
+ public String getBaseActionParam() {
+ return baseActionParam;
+ } // getBaseActionParam
+
+ public Vector getQuickLinksMenuIDs(){
+ return quickLinksMenuIDs;
+ } // getQuickLinksMenuIDs
+
+ public String getMenuLabel(String menuId) {
+ //return menuId.substring(0, 1).toUpperCase()+menuId.substring(1).toLowerCase();
+ return menuId;
+ } // getMenuLabel
+
+ public String getReportDbColsMaskSQL() {
+ return null;
+/* Example:
+ return "SELECT f.table_name, UPPER(f.column_name) column_name, f.label "+
+ "FROM fields f WHERE f.active_yn = 'Y'"; */
+ } // getReportDbColsMaskSQL
+
+ public String getReportDbLookupsSQL() {
+ return null;
+/* Example:
+ return "SELECT DISTINCT f.table_name, UPPER(f.column_name) column_name, f.lookup_table, f.lookup_id_field, f.lookup_name_field "+
+ "FROM fields f WHERE f.active_yn = 'Y'"; */
+ } // getReportDbLookupsSQL
+
+ public void processErrorNotification(HttpServletRequest request, RaptorException e) {
+ //RaptorAdapter.processErrorNotification(request, e);
+} // processErrorNotification
+
+ public String getErrorPageWMenu() {
+ return errorPageWMenu;
+ }
+
+ public String getExcelTemplatePath() {
+ return nvls(raptorAppProperties.getProperty("excel_template_path"), "");
+ }
+ /**
+ * @return the encryptedSMTPServer
+ */
+ public String getEncryptedSMTPServer() {
+ return encryptedSMTPServer;
+ }
+
+ public String getFolderPathAdj(){
+ return nvls(raptorAppProperties.getProperty("folder_path_adj"), "");
+ }
+
+} // AppUtils
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java
new file mode 100644
index 00000000..5232fc74
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java
@@ -0,0 +1,78 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion;
+
+import java.sql.*;
+import java.util.*;
+
+import javax.servlet.*;
+
+import org.openecomp.portalsdk.analytics.config.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.system.fusion.adapter.FusionAdapter;
+import org.openecomp.portalsdk.analytics.system.fusion.adapter.RaptorAdapter;
+import org.openecomp.portalsdk.analytics.system.fusion.adapter.SpringContext;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+
+public class DbUtils implements IDbUtils {
+
+ @Autowired
+ public RaptorAdapter raptorAdapter;
+ @Autowired
+ public FusionAdapter fusionAdapter;
+
+ public DbUtils() {}
+
+ public void initializeDbUtils(ServletContext servletContext) {
+ raptorAdapter = (RaptorAdapter)SpringContext.getApplicationContext().getBean("raptorAdapter");
+ } // initializeDbUtils
+
+ public Connection getConnection() {
+ return raptorAdapter.getConnection();
+ } // getConnection
+
+ public void clearConnection(Connection con) {
+ raptorAdapter.releaseConnection(con);
+ } // clearConnection
+
+ public RaptorAdapter getRaptorAdapter() {
+ return raptorAdapter;
+ }
+
+ public void setRaptorAdapter(RaptorAdapter raptorAdapter) {
+ this.raptorAdapter = raptorAdapter;
+ }
+
+ public FusionAdapter getFusionAdapter() {
+ return fusionAdapter;
+ }
+
+ public void setFusionAdapter(FusionAdapter fusionAdapter) {
+ this.fusionAdapter = fusionAdapter;
+ }
+
+
+
+
+
+} // DbUtils
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java
index 4f8f7427..85eda259 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/RemoteDbUtils.java
@@ -20,12 +20,19 @@
package org.openecomp.portalsdk.analytics.system.fusion;
import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
import javax.servlet.ServletContext;
+import org.openecomp.portalsdk.analytics.error.ReportSQLException;
import org.openecomp.portalsdk.analytics.system.RDbUtils;
import org.openecomp.portalsdk.analytics.system.fusion.adapter.RaptorAdapter;
import org.openecomp.portalsdk.analytics.system.fusion.adapter.SpringContext;
+import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.util.Log;
+import org.springframework.beans.factory.annotation.Autowired;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java
index 1e2de464..6a70d258 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/AdapterSessionFactoryContainer.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.system.fusion.adapter;
-import java.util.LinkedHashMap;
+import java.util.*;
public class AdapterSessionFactoryContainer {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java
index a9ea0979..a9ea0979 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/DateUtils.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java
index 33b6ec2d..4b6c6d78 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/FusionAdapter.java
@@ -19,15 +19,24 @@
*/
package org.openecomp.portalsdk.analytics.system.fusion.adapter;
-import java.sql.Connection;
-import java.util.Map;
+import java.sql.*;
+import java.util.*;
-import javax.servlet.ServletContext;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.servlet.*;
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
import org.openecomp.portalsdk.core.FusionObject;
+import org.openecomp.portalsdk.core.service.DataAccessService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
import org.springframework.beans.factory.annotation.Autowired;
-
-import com.mchange.v2.c3p0.ComboPooledDataSource;
+import org.springframework.context.annotation.Configuration;
public class FusionAdapter implements FusionObject {
@@ -38,12 +47,7 @@ public class FusionAdapter implements FusionObject {
private Map<String,ComboPooledDataSource> dataSourceMap;
//private SessionFactory sessionFactory;
- private ServletContext servletContext;
-
- // private static Connection connection = null;
-
- //private static AdapterSessionFactoryContainer sessionFactoryContainer;
-
+ private ServletContext servletContext;
public FusionAdapter() {
}
@@ -57,30 +61,14 @@ public class FusionAdapter implements FusionObject {
this.servletContext = servletContext;
}
- // public static AdapterSessionFactoryContainer getSessionFactoryContainer() {
- // return sessionFactoryContainer;
- // }
-
- //public static LinkedHashMap getSessionFactories() {
- // return getSessionFactoryContainer().getSessionFactories();
- //}
-
-
- //public void setSessionFactoryContainer(AdapterSessionFactoryContainer sessionFactoryContainer) {
- // this.sessionFactoryContainer = sessionFactoryContainer;
- //}
-
-
/** Gets connection to the database **/
public Connection getConnection() {
- //Session session = sessionFactory.getCurrentSession();
Connection connection = null;
try {
connection = getDataSource().getConnection();
} catch(Exception ex) {
ex.printStackTrace();
}
-
return connection;
}
@@ -102,10 +90,8 @@ public class FusionAdapter implements FusionObject {
public void releaseConnection(Connection conn) {
try {
conn.close();
- //logger.debug("releasing connection from adapter...");
}
catch (Exception e) {
- //logger.error("Error while closing the connection.");
e.printStackTrace();
}
}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java
index 5b4af3f9..c46d6730 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/IdName.java
@@ -19,12 +19,18 @@
*/
package org.openecomp.portalsdk.analytics.system.fusion.adapter;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
import org.openecomp.portalsdk.core.domain.support.DomainVo;
/**
* <p>IdName.java</p>
* <p>Represents a id/name data object.</p>
*/
+@Entity
public class IdName extends DomainVo {
private String name;
@@ -32,7 +38,9 @@ public class IdName extends DomainVo {
public IdName() {}
-
+ @Id
+ @GeneratedValue
+ @Column(name = "ID", unique = true, nullable = false)
public Long getId() {
return id;
}
@@ -56,4 +64,4 @@ public class IdName extends DomainVo {
return (c1 == null || c2 == null) ? 1 : c1.compareTo(c2);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java
index 71663bc2..71663bc2 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Item.java
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java
new file mode 100644
index 00000000..c77835ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java
@@ -0,0 +1,85 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion.adapter;
+
+
+import java.io.*;
+
+import org.openecomp.portalsdk.core.domain.FusionVo;
+import org.openecomp.portalsdk.core.domain.support.NameValueId;
+
+
+
+public class Lookup extends FusionVo implements Serializable {
+
+ private NameValueId nameValueId = new NameValueId();
+
+ public Lookup() {}
+
+ public Lookup(String label, String value) {
+ this();
+ setLabel(label);
+ setValue(value);
+ }
+
+ public String getValue() {
+ return getNameValueId().getVal();
+ }
+
+ public String getLabel() {
+ return getNameValueId().getLab();
+ }
+
+ public void setValue(String value) {
+ getNameValueId().setVal(value);
+ }
+
+ public void setLabel(String label) {
+ getNameValueId().setLab(label);
+ }
+
+ public NameValueId getNameValueId() {
+ return nameValueId;
+ }
+
+ public void setNameValueId(NameValueId nameValueId) {
+ this.nameValueId = nameValueId;
+ }
+
+ // required by ZK for to set the selectedItems of Listboxes (used heavily for <select>-style drop-downs)
+ public int hashCode() {
+ int hash = getValue().hashCode();
+ hash = hash + getLabel().hashCode();
+
+ return hash;
+ }
+
+ public boolean equals( Object obj ) {
+ boolean equivalent = false;
+
+ Lookup lookup = (Lookup)obj;
+ if( lookup.getValue().equals(getValue()) && lookup.getLabel().equals(getLabel())) {
+ equivalent = true;
+ }
+
+ return equivalent;
+ }
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java
index 99cc0272..2111935c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/RaptorAdapter.java
@@ -44,7 +44,6 @@ import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-
@Service("raptorAdapter")
public class RaptorAdapter extends FusionAdapter {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java
index 1d46290a..1d46290a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/SpringContext.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java
index 203ee9cc..203ee9cc 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/controller/FileServletController.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java
index 9f6ed7d6..a35d6ce3 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/CR_Report.java
@@ -20,7 +20,7 @@
package org.openecomp.portalsdk.analytics.system.fusion.domain;
-import java.util.Date;
+import java.util.*;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.domain.support.DomainVo;;
@@ -29,6 +29,7 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;;
* <p>CR_Report.java</p>
* <p>Represents a RAPTOR report data object.</p>
*
+ * @author Sundar Ramalingam
* @version 1.0
*/
public class CR_Report extends DomainVo {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java
index 75b2d119..75b2d119 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/QuickLink.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java
index cb85f368..cb85f368 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/RaptorSearch.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java
index e11f3bcb..e11f3bcb 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/domain/ReportInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java
index 26276579..afde57e6 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorService.java
@@ -19,8 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.system.fusion.service;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java
index e8e0cf31..1427a2ea 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/service/RaptorServiceImpl.java
@@ -19,13 +19,33 @@
*/
package org.openecomp.portalsdk.analytics.system.fusion.service;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.sql.DataSource;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
import org.openecomp.portalsdk.analytics.system.fusion.domain.CR_Report;
+import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.service.DataAccessService;
import org.openecomp.portalsdk.core.service.support.FusionService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.context.ApplicationContext;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.orm.hibernate3.SessionFactoryUtils;
+import org.springframework.web.multipart.MultipartFile;
public class RaptorServiceImpl extends FusionService implements RaptorService {
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java
new file mode 100644
index 00000000..4b425ab3
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java
@@ -0,0 +1,190 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion.web;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Method;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.analytics.controller.Action;
+import org.openecomp.portalsdk.analytics.controller.ErrorHandler;
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
+import org.openecomp.portalsdk.analytics.model.runtime.ErrorJSONRuntime;
+import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+@Controller
+@RequestMapping("/")
+public class RaptorController extends RestrictedBaseController {
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RaptorController.class);
+
+ @RequestMapping(value = { "/report" }, method = RequestMethod.GET)
+ public ModelAndView report(HttpServletRequest request) {
+ request.getSession().setAttribute("isEmbedded", false);
+ return new ModelAndView("report");
+ }
+
+ @RequestMapping(value = { "/reportDS1" }, method = RequestMethod.GET)
+ public ModelAndView reportDS1(HttpServletRequest request) {
+ request.getSession().setAttribute("isEmbedded", false);
+ return new ModelAndView("reportDS1");
+ }
+
+ @RequestMapping(value = { "/report_embedded" }, method = RequestMethod.GET)
+ public ModelAndView reportEmbedded(HttpServletRequest request) {
+ request.getSession().setAttribute("isEmbedded", true);
+ return new ModelAndView("report_embedded");
+ }
+
+ @RequestMapping(value = { "/report_sample" }, method = RequestMethod.GET)
+ public ModelAndView reportSample(HttpServletRequest request) {
+ return new ModelAndView("report_sample");
+ }
+
+ @RequestMapping(value = { "/report_import.htm" }, method = RequestMethod.GET)
+ public ModelAndView reportImport(HttpServletRequest request) throws IOException {
+ String viewName = "report_import";
+ Action action = null;
+ String actionKey = "report.import";
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+ try {
+ action = Globals.getRaptorActionMapping().getAction(actionKey);
+ if (action == null)
+ throw new RaptorRuntimeException("Action not found");
+ } catch (RaptorException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. RaptorException: " + e.getMessage()));
+ viewName = new ErrorHandler().processFatalError(request,
+ new RaptorRuntimeException("[Controller.processRequest]Invalid raptor action [" + actionKey
+ + "]. Exception: " + e.getMessage()));
+ }
+ return new ModelAndView(viewName, "model", null);
+ }
+
+ @RequestMapping(value = { "/report_wizard.htm" }, method = { RequestMethod.POST, RequestMethod.GET })
+ public ModelAndView reportWizard(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ String viewName = "";
+ String actionKey = nvl(request.getParameter(AppConstants.RI_ACTION), request.getParameter("action"));
+ actionKey = nvl(actionKey, "report.run");
+ Action action = null;
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+ try {
+ action = Globals.getRaptorActionMapping().getAction(actionKey);
+ if (action == null)
+ throw new RaptorRuntimeException("Action not found");
+ } catch (RaptorException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. RaptorException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalError(request,
+ new RaptorRuntimeException("[Controller.processRequest]Invalid raptor action [" + actionKey
+ + "]. Exception: " + e.getMessage()));
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage(e.toString());
+ errorJSONRuntime.setStacktrace(getStackTrace(e));
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ String jsonInString = "";
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ }
+
+ try {
+ Class<?>[] paramTypes = new Class[2];
+ paramTypes[0] = Class.forName("javax.servlet.http.HttpServletRequest");
+ paramTypes[1] = Class.forName("java.lang.String");
+
+ Class<?> handlerClass = Class.forName(action.getControllerClass());
+ Object handler = handlerClass.newInstance();
+ Method handlerMethod = handlerClass.getMethod(action.getControllerMethod(), paramTypes);
+
+ Object[] paramValues = new Object[2];
+ paramValues[0] = request;
+ paramValues[1] = action.getJspName();
+ viewName = (String) handlerMethod.invoke(handler, paramValues);
+ } catch (Exception e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. Exception: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalError(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage(e.toString());
+ errorJSONRuntime.setStacktrace(getStackTrace(e));
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ String jsonInString = "";
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ }
+ return new ModelAndView(viewName, "model", null);
+ }
+
+ private String nvl(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ private String nvl(String s, String sDefault) {
+ return nvl(s).equals("") ? sDefault : s;
+ }
+
+ public static String getStackTrace(Throwable aThrowable) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(result);
+ aThrowable.printStackTrace(printWriter);
+ return result.toString();
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java
new file mode 100644
index 00000000..3afe3522
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java
@@ -0,0 +1,1752 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.system.fusion.web;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.openecomp.portalsdk.analytics.controller.Action;
+import org.openecomp.portalsdk.analytics.controller.ErrorHandler;
+import org.openecomp.portalsdk.analytics.error.RaptorException;
+import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
+import org.openecomp.portalsdk.analytics.error.ReportSQLException;
+import org.openecomp.portalsdk.analytics.error.UserDefinedException;
+import org.openecomp.portalsdk.analytics.model.ReportHandler;
+import org.openecomp.portalsdk.analytics.model.definition.ReportDefinition;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.ColumnEditJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.ColumnJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.DefinitionJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.FormEditJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.IdNameBooleanJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.ImportJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.MessageJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.NameBooleanJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.QueryJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.QueryResultJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.SearchFieldJSON;
+import org.openecomp.portalsdk.analytics.model.definition.wizard.WizardJSON;
+import org.openecomp.portalsdk.analytics.model.pdf.PdfReportHandler;
+import org.openecomp.portalsdk.analytics.model.runtime.CategoryAxisJSON;
+import org.openecomp.portalsdk.analytics.model.runtime.ChartJSON;
+
+import org.openecomp.portalsdk.analytics.model.runtime.ErrorJSONRuntime;
+import org.openecomp.portalsdk.analytics.model.runtime.FormField;
+import org.openecomp.portalsdk.analytics.model.runtime.RangeAxisJSON;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportFormFields;
+import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
+
+import org.openecomp.portalsdk.analytics.system.AppUtils;
+import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
+import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.util.AppConstants;
+import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.util.Utils;
+import org.openecomp.portalsdk.analytics.util.XSSFilter;
+import org.openecomp.portalsdk.analytics.view.ReportData;
+import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+import org.openecomp.portalsdk.analytics.xmlobj.FormFieldList;
+import org.openecomp.portalsdk.analytics.xmlobj.FormFieldType;
+import org.openecomp.portalsdk.analytics.xmlobj.ObjectFactory;
+import org.openecomp.portalsdk.analytics.xmlobj.PredefinedValueList;
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+@Controller
+@RequestMapping("/")
+public class RaptorControllerAsync extends UnRestrictedBaseController {
+ String viewName;
+
+ @RequestMapping(value = { "/raptor.htm" }, method = RequestMethod.GET)
+ public void RaptorSearch(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, RaptorException {
+ // System.out.println("Inside RAPTOR run ");
+ /*
+ * List items = null; int reportId =
+ * ServletRequestUtils.getIntParameter(request, "report_id", 0);
+ * //String task = ServletRequestUtils.getStringParameter(request,
+ * "task", TASK_GET);
+ *
+ * HashMap additionalParams = new HashMap();
+ * additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request);
+ *
+ * return new ModelAndView(getViewName(), "model", null);
+ *
+ * //return new ModelAndView(getViewName(), "model", null);
+ * //System.out.println("Fill with proper code"); //return null;
+ */
+ viewName = "";
+ String actionKey = nvl(request.getParameter(AppConstants.RI_ACTION), request.getParameter("action"));
+ actionKey = nvl(actionKey, "report.run");
+
+ HttpSession session = request.getSession();
+ User user = UserUtils.getUserSession(request);
+
+ if (actionKey.equals("report.download.excel2007.session") || actionKey.equals("report.download.csv.session")
+ || actionKey.equals("report.download.excel.session")
+ || actionKey.equals("report.download.pdf.session")) {
+ if (session != null && user != null) {
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+ ReportRuntime rr = null;
+ ReportData rd = null;
+ String parent = "";
+ int parentFlag = 0;
+ if (!nvl(request.getParameter("parent"), "").equals("N"))
+ parent = nvl(request.getParameter("parent"), "");
+ if (parent.startsWith("parent_"))
+ parentFlag = 1;
+ if (parentFlag == 1) {
+ rr = (ReportRuntime) request.getSession().getAttribute(parent + "_rr");
+ rd = (ReportData) request.getSession().getAttribute(parent + "_rd");
+ }
+
+ boolean isEmbedded = false;
+ Object temp = request.getSession().getAttribute("isEmbedded");
+ if (temp != null) {
+ isEmbedded = (boolean) temp;
+ }
+ if (isEmbedded) {
+ String reportID = AppUtils.getRequestValue(request, AppConstants.RI_REPORT_ID);
+ if (rr == null)
+ rr = (ReportRuntime) ((HashMap) request.getSession()
+ .getAttribute(AppConstants.EMBEDDED_REPORTRUNTIME_MAP)).get(reportID);
+ if (rd == null)
+ rd = (ReportData) ((HashMap) request.getSession()
+ .getAttribute(AppConstants.EMBEDDED_REPORTDATA_MAP)).get(reportID);
+ } else {
+ if (rr == null)
+ rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
+ if (rd == null)
+ rd = (ReportData) request.getSession().getAttribute(AppConstants.RI_REPORT_DATA);
+ }
+ String user_id = AppUtils.getUserID(request);
+ int downloadLimit = 0;
+ if (rr != null)
+ downloadLimit = (rr.getMaxRowsInExcelDownload() > 0) ? rr.getMaxRowsInExcelDownload()
+ : Globals.getDownloadLimit();
+ if (actionKey.equals("report.csv.download"))
+ downloadLimit = Globals.getCSVDownloadLimit();
+ String sql_whole = rr.getReportDataSQL(user_id, downloadLimit, request);
+ request.setAttribute(AppConstants.RI_REPORT_SQL_WHOLE, sql_whole);
+ try {
+ OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream());
+
+ if (actionKey.equals("report.download.pdf.session")) {
+ new PdfReportHandler().createPdfFileContent(request, response, 3);
+ } else if (actionKey.equals("report.download.csv.session")) {
+ (new ReportHandler()).createCSVFileContent(out, rd, rr, request, response);
+ } else if (actionKey.equals("report.download.excel.session")) {
+ new ReportHandler().createExcelFileContent(out, rd, rr, request, response, user_id, 3); // 3
+ // whole
+ } else {
+
+ new ReportHandler().createExcel2007FileContent(out, rd, rr, request, response, user_id, 3); // 3
+ // whole
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // Log.write("Fatal error [report_download_xlsx.jsp]:
+ // "+e.getMessage());
+ }
+ } else {
+ response.sendRedirect("login.htm");
+ }
+ } else {
+ if (session != null && user != null) {
+ Action action = null;
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+ try {
+ action = Globals.getRaptorActionMapping().getAction(actionKey);
+ if (action == null)
+ throw new RaptorRuntimeException("Action not found");
+ } catch (RaptorException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. RaptorException: " + e.getMessage()));
+ // if (actionKey.equals("system_upgrade")) // System
+ // override
+ // return
+ // att.raptor.util.upgrade.SystemUpgrade.upgradeDB(request);
+
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException("[Controller.processRequest]Invalid raptor action [" + actionKey
+ + "]. Exception: " + e.getMessage()));
+ }
+
+ try {
+ Class[] paramTypes = new Class[2];
+ paramTypes[0] = Class.forName("javax.servlet.http.HttpServletRequest");
+ paramTypes[1] = Class.forName("java.lang.String");
+
+ Class handlerClass = Class.forName(action.getControllerClass());
+ Object handler = handlerClass.newInstance();
+ Method handlerMethod = handlerClass.getMethod(action.getControllerMethod(), paramTypes);
+
+ Object[] paramValues = new Object[2];
+ paramValues[0] = request;
+ paramValues[1] = action.getJspName();
+ ;
+
+ viewName = (String) handlerMethod.invoke(handler, paramValues);
+ // ObjectMapper mapper = new ObjectMapper();
+ if (!actionKey.equals("chart.run"))
+ response.setContentType("application/json");
+ else
+ response.setContentType("text/html");
+
+ } catch (ClassNotFoundException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. ClassNotFoundException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+ } catch (IllegalAccessException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. IllegalAccessException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+ } catch (InstantiationException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. InstantiationException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+ } catch (NoSuchMethodException e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. NoSuchMethodException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action ["
+ + actionKey + "]. InvocationTargetException: " + e.getMessage()));
+ viewName = (new ErrorHandler()).processFatalErrorJSON(request,
+ new RaptorRuntimeException(
+ "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
+ + e.getMessage()));
+ } finally {
+ PrintWriter out = response.getWriter();
+ out.write(viewName);
+ // System.out.println("******Viewname******"+viewName);
+ }
+ // return new ModelAndView(getViewName(), "model", null);
+ } else {
+ PrintWriter out = response.getWriter();
+ out.write("session has timed out for user");
+ }
+
+ }
+ }
+
+ @RequestMapping(value = "/report/wizard/list_columns", method = RequestMethod.GET, produces="application/json")
+ public @ResponseBody ArrayList<ColumnJSON> listColumns(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, RaptorException {
+ //PrintWriter out = response.getWriter();
+ ReportDefinition rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ List<DataColumnType> reportColumnList = rdef.getAllColumns();
+ ArrayList<ColumnJSON> listJSON = new ArrayList<ColumnJSON>();
+ ColumnJSON columnJSON = new ColumnJSON();
+
+ for (DataColumnType reportColumnType : reportColumnList) {
+ columnJSON = new ColumnJSON();
+ columnJSON.setId(reportColumnType.getColId());
+ columnJSON.setName(reportColumnType.getColName());
+ listJSON.add(columnJSON);
+ }
+/* String jsonInString = "";
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(listJSON);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+*/
+ return listJSON;
+ }
+
+ @RequestMapping(value = "/report/wizard/list_formfields", method = RequestMethod.GET, produces="application/json")
+ public @ResponseBody ArrayList<SearchFieldJSON> listFormFields(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, RaptorException {
+ //PrintWriter out = response.getWriter();
+ ReportDefinition rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ ArrayList<SearchFieldJSON> listJSON = new ArrayList<SearchFieldJSON>();
+ SearchFieldJSON fieldJSON = new SearchFieldJSON();
+ if (rdef.getFormFieldList() != null) {
+ for (Iterator iter = rdef.getFormFieldList().getFormField().iterator(); iter.hasNext();) {
+ fieldJSON = new SearchFieldJSON();
+ FormFieldType fft = (FormFieldType) iter.next();
+ String fieldId = fft.getFieldId();
+ String fieldDisplay = fft.getFieldName();
+ fieldJSON.setId(fieldId);
+ fieldJSON.setName(fieldDisplay);
+ listJSON.add(fieldJSON);
+ }
+ }
+
+/* String jsonInString = "";
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(listJSON);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ out.write(jsonInString);
+*/
+ return listJSON;
+ }
+
+ @RequestMapping(value = "/report/wizard/list_child_report_ff/{reportID}", method = RequestMethod.GET, produces="application/json")
+ public @ResponseBody ArrayList<SearchFieldJSON> listChildReportFormFields(@PathVariable("reportID") String reportID, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ //PrintWriter out = response.getWriter();
+ ReportRuntime ddRr = (new ReportHandler()).loadReportRuntime(request, reportID, false);
+ ArrayList<SearchFieldJSON> listJSON = new ArrayList<SearchFieldJSON>();
+ SearchFieldJSON fieldJSON = new SearchFieldJSON();
+
+ ReportFormFields ddReportFormFields = ddRr.getReportFormFields();
+ if (ddReportFormFields != null) {
+ for (ddReportFormFields.resetNext(); ddReportFormFields.hasNext();) {
+ FormField ff = ddReportFormFields.getNext();
+ if (!ff.getFieldType().equals(FormField.FFT_BLANK)) {
+ fieldJSON = new SearchFieldJSON();
+ fieldJSON.setId(ff.getFieldName());
+ fieldJSON.setName(ff.getFieldDisplayName());
+ listJSON.add(fieldJSON);
+ }
+ }
+ }
+/* String jsonInString = "";
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(listJSON);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ out.write(jsonInString);
+*/
+ return listJSON;
+ }
+
+ @RequestMapping(value = "report/wizard/copy_report/{reportID}", method = RequestMethod.GET, produces="application/json")
+ public @ResponseBody MessageJSON copyReport(@PathVariable("reportID") String reportID, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ //PrintWriter out = response.getWriter();
+ //String jsonInString = "";
+ MessageJSON messageJSON = new MessageJSON();
+ try {
+
+ ReportHandler rh = new ReportHandler();
+ ReportDefinition rdef = rh.loadReportDefinition(request, reportID);
+ rdef.setAsCopy(request);
+ request.getSession().setAttribute(AppConstants.SI_REPORT_DEFINITION, rdef);
+ messageJSON.setMessage("Success- Report Copied.");
+ messageJSON.setAnyStacktrace(rdef.getReportID() + " is Modified and added to session and DB.");
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ } catch (RaptorException e) {
+ request.setAttribute("error_extra_msg", "While copying report " + reportID);
+ messageJSON.setMessage("Failed - While copying report " + reportID);
+ messageJSON.setAnyStacktrace(getStackTrace(e));
+// ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+// errorJSONRuntime.setErrormessage("While copying report " + reportID);
+// errorJSONRuntime.setStacktrace(getStackTrace(e));
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ return messageJSON;
+ }
+
+ return messageJSON;
+ }
+
+
+ @RequestMapping(value = "report/wizard/import_report", method = RequestMethod.POST, consumes="application/json")
+ public MessageJSON importReport(@RequestBody ImportJSON importJSON, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ //PrintWriter out = response.getWriter();
+ //String jsonInString = "";
+ MessageJSON messageJSON = new MessageJSON();
+ try {
+ String reportXML = importJSON.getReportXML();
+
+ ReportHandler rh = new ReportHandler();
+ ReportDefinition rdef = rh.createReportDefinition(request, "-1", reportXML);
+ rdef.updateReportDefType();
+ rdef.generateWizardSequence(request);
+ rdef.setReportName("Import: " + rdef.getReportName());
+ rdef.clearAllDrillDowns();
+
+ request.getSession().setAttribute(AppConstants.SI_REPORT_DEFINITION, rdef);
+
+ messageJSON.setMessage("Success- Report imported.");
+ messageJSON.setAnyStacktrace(rdef.getReportID() + " is Modified and added to session and DB.");
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+
+ } catch (RaptorException e) {
+ request.setAttribute("error_extra_msg", "Unable to parse XML. Nested error: ");
+ messageJSON.setMessage("Unable to parse XML. Nested error: ");
+ messageJSON.setAnyStacktrace(getStackTrace(e));
+/* ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Unable to parse XML. Nested error: ");
+ errorJSONRuntime.setStacktrace(getStackTrace(e));
+*/
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ return messageJSON;
+ }
+
+ return messageJSON;
+
+ }
+
+ @RequestMapping(value = "report/wizard/save_formfield_tab_data", method = RequestMethod.POST)
+ public MessageJSON saveFFTabWiseData(@RequestBody FormEditJSON formEditJSON, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ ReportDefinition rdef = null;
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+
+ String tabId = formEditJSON.getTabId();
+ //String errorString = "";
+ MessageJSON messageJSON = new MessageJSON();
+
+ //PrintWriter out = response.getWriter();
+ //String jsonInString = "";
+ try {
+ if (rdef != null) {
+
+ String fieldId = formEditJSON.getFieldId();
+
+ if (rdef.getFormFieldList() != null) {
+ for (FormFieldType fft : rdef.getFormFieldList().getFormField()) {
+ if (fft.getFieldId().equals(fieldId)) {
+ fft.setFieldName(formEditJSON.getFieldName());
+ fft.setFieldType(formEditJSON.getFieldType());
+ fft.setVisible(formEditJSON.isVisible() ? "Y" : "N");
+ fft.setDefaultValue(formEditJSON.getDefaultValue());
+ fft.setFieldDefaultSQL(formEditJSON.getFieldDefaultSQL());
+ fft.setFieldSQL(formEditJSON.getFieldSQL());
+ fft.setValidationType(formEditJSON.getValidationType());
+
+ // clear predefined value
+ if (fft.getPredefinedValueList() != null) {
+ for (Iterator iter = fft.getPredefinedValueList().getPredefinedValue()
+ .iterator(); iter.hasNext();)
+ iter.remove();
+ }
+
+ List<IdNameBooleanJSON> predefList = formEditJSON.getPredefinedValueList();
+ for (IdNameBooleanJSON item : predefList) {
+ PredefinedValueList predefinedValueList = new ObjectFactory()
+ .createPredefinedValueList();
+ fft.setPredefinedValueList(predefinedValueList);
+ fft.getPredefinedValueList().getPredefinedValue().add(item.getId());
+ }
+
+ }
+ }
+ }
+
+
+ persistReportDefinition(request, rdef);
+ messageJSON.setMessage("Success formfield Details of given report is saved in session.");
+ messageJSON.setAnyStacktrace(rdef.getReportID() + " is Modified and added to session and DB.");
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/ } else {
+ messageJSON.setMessage("Report Definition is not in session");
+ messageJSON.setAnyStacktrace("Report Definition is not in session");
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/ }
+ } catch (Exception ex) {
+
+ messageJSON.setMessage("Error occured while formfield details Tab");
+ messageJSON.setAnyStacktrace(getStackTrace(ex));
+
+/* ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Error occured while formfield column details Tab");
+ errorJSONRuntime.setStacktrace(getStackTrace(ex));
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ return messageJSON;
+ }
+
+ return messageJSON;
+ }
+
+ @RequestMapping(value = "report/wizard/save_col_tab_data", method = RequestMethod.POST)
+ public MessageJSON saveColTabWiseData(@RequestBody ColumnEditJSON columnEditJSON, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ ReportDefinition rdef = null;
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+
+ //String errorString = "";
+ //String jsonInString = "";
+ //PrintWriter out = response.getWriter();
+ MessageJSON messageJSON = new MessageJSON();
+
+ try {
+ if (rdef != null) {
+ String colId = columnEditJSON.getColId();
+ List<DataColumnType> reportColumnList = rdef.getAllColumns();
+
+ for (DataColumnType reportColumnType : reportColumnList) {
+ // columnJSON = new ColumnJSON();
+ if (reportColumnType.getColId().equals(colId)) {
+ reportColumnType.setColName(columnEditJSON.getColName());
+ reportColumnType.setDisplayAlignment(columnEditJSON.getDisplayAlignment());
+ reportColumnType.setDisplayHeaderAlignment(columnEditJSON.getDisplayHeaderAlignment());
+ reportColumnType.setIsSortable(columnEditJSON.isSortable());
+ reportColumnType.setVisible(columnEditJSON.isVisible());
+ reportColumnType.setDrillDownURL(columnEditJSON.getDrilldownURL());
+ reportColumnType.setDrillDownParams(columnEditJSON.getDrilldownParams());
+ reportColumnType.setDrillDownType(columnEditJSON.getDrilldownType());
+
+ }
+
+ }
+ persistReportDefinition(request, rdef);
+ messageJSON.setMessage("Success Column Details of given report is saved in session.");
+ messageJSON.setAnyStacktrace(rdef.getReportID() + " is Modified and added to session and DB.");
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ } else {
+ messageJSON.setMessage("Report Definition is not in session");
+ messageJSON.setAnyStacktrace("");
+
+/* ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Report Definition is not in session;");
+ errorJSONRuntime.setStacktrace("");
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/ }
+ } catch (Exception ex) {
+ messageJSON.setMessage("Error occured while saving column details Tab");
+ messageJSON.setAnyStacktrace(getStackTrace(ex));
+
+/* ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Error occured while saving column details Tab");
+ errorJSONRuntime.setStacktrace(getStackTrace(ex));
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ return messageJSON;
+ }
+
+ return messageJSON;
+ }
+
+ @RequestMapping(value = "report/wizard/save_def_tab_data/{id}", method = RequestMethod.POST)
+ public MessageJSON saveDefTabWiseData(@PathVariable("id") String id, @RequestBody DefinitionJSON definitionJSON,
+ HttpServletRequest request, HttpServletResponse response) throws IOException, RaptorException {
+ ReportDefinition rdef = null;
+ ReportRuntime rr = null;
+ String tabId = definitionJSON.getTabId();
+ String errorString = "";
+ boolean newReport = false;
+ //String jsonInString = "";
+ //PrintWriter out = response.getWriter();
+ MessageJSON messageJSON = new MessageJSON();
+
+
+
+ /*
+ * rdef = (ReportDefinition) request.getSession().getAttribute(
+ * AppConstants.SI_REPORT_DEFINITION); if(rdef!=null) { rdef = (new
+ * ReportHandler()).loadReportDefinition(request, id); } else {
+ */
+ try {
+ if (id.equals("InSession")) {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ newReport = false;
+
+ } else if (id.equals("Create")) {
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, "-1");
+ newReport = true;
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& CHECK Report Type " + (AppUtils.nvl(rdef.getReportType()).length()<=0));
+ if(AppUtils.nvl(rdef.getReportType()).length()<=0) {
+ rdef.setReportType(AppConstants.RT_LINEAR);
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& ADDED Report Type in session ");
+ }
+
+
+ } else if (AppUtils.nvl(id).length() > 0) {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
+
+ if (rdef != null && !rdef.getReportID().equals(id)) {
+ request.getSession().removeAttribute(AppConstants.SI_REPORT_DEFINITION);
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ } else if (rr != null && !rr.getReportID().equals(id)) {
+ request.getSession().removeAttribute(AppConstants.SI_REPORT_RUNTIME);
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ } else if (rdef == null) {
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ }
+ newReport = false;
+
+ } else {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ newReport = true;
+ }
+ // }
+
+ if (rdef != null) {
+ String reportName = definitionJSON.getReportName();
+ if (AppUtils.nvl(reportName).length() <= 0)
+ errorString = "ReportName cannot be null;";
+ rdef.setReportName(reportName);
+
+ String reportDescr = definitionJSON.getReportDescr();
+ rdef.setReportDescr(reportDescr);
+
+ String formHelpText = definitionJSON.getFormHelpText();
+ rdef.setFormHelpText(formHelpText);
+
+ Integer pageSize = definitionJSON.getPageSize();
+ rdef.setPageSize(pageSize);
+
+ List<IdNameBooleanJSON> menuIds = definitionJSON.getDisplayArea();
+ for (IdNameBooleanJSON menuId : menuIds) {
+ if (menuId.isSelected()) {
+ rdef.setMenuID(menuId.getName());
+ }
+
+ }
+
+ Boolean hideFormFieldsAfterRun = definitionJSON.getHideFormFieldsAfterRun();
+ rdef.setHideFormFieldAfterRun(hideFormFieldsAfterRun);
+ Integer maxRowsInExcelCSVDownload = definitionJSON.getMaxRowsInExcelCSVDownload();
+ rdef.setMaxRowsInExcelDownload(maxRowsInExcelCSVDownload);
+ Integer frozenColumns = definitionJSON.getFrozenColumns();
+ rdef.setFrozenColumns(frozenColumns);
+ String dataGridAlign = definitionJSON.getDataGridAlign();
+ rdef.setDataGridAlign(dataGridAlign);
+ String emptyMessage = definitionJSON.getEmptyMessage();
+ rdef.setEmptyMessage(emptyMessage);
+ String dataContainerHeight = definitionJSON.getDataContainerHeight();
+ rdef.setDataContainerHeight(dataContainerHeight);
+ String dataContainerWidth = definitionJSON.getDataContainerWidth();
+ rdef.setDataContainerWidth(dataContainerWidth);
+ boolean runtimeColSortDisabled = definitionJSON.getRuntimeColSortDisabled();
+ rdef.setRuntimeColSortDisabled(runtimeColSortDisabled);
+ Integer numFormCols = definitionJSON.getNumFormCols();
+ rdef.setNumFormCols(Integer.toString(numFormCols));
+ String reportTitle = definitionJSON.getReportTitle();
+ rdef.setReportTitle(reportTitle);
+ String reportSubTitle = definitionJSON.getReportSubTitle();
+ rdef.setReportSubTitle(reportSubTitle);
+
+ List<NameBooleanJSON> displayOptions = definitionJSON.getDisplayOptions();
+ StringBuffer displayOptionStr = new StringBuffer("NNNNNNN");
+ for (NameBooleanJSON displayOption : displayOptions) {
+ if (displayOption.isSelected()) {
+ if (displayOption.getName().equals("HideFormFields")) {
+ displayOptionStr.setCharAt(0, 'Y');
+ } else if (displayOption.getName().equals("HideChart")) {
+ displayOptionStr.setCharAt(1, 'Y');
+ } else if (displayOption.getName().equals("HideReportData")) {
+ displayOptionStr.setCharAt(2, 'Y');
+ } else if (displayOption.getName().equals("HideExcel")) {
+ displayOptionStr.setCharAt(5, 'Y');
+ } else if (displayOption.getName().equals("HidePdf")) {
+ displayOptionStr.setCharAt(6, 'Y');
+ }
+ }
+
+ }
+
+ rdef.setDisplayOptions(displayOptionStr.toString());
+ }
+ persistReportDefinition(request, rdef);
+ messageJSON.setMessage("Success Definition of given report is saved in session.");
+ messageJSON.setAnyStacktrace((newReport ? " New Report info is added to Session "
+ : rdef.getReportID() + " is Modified and added to session and DB."));
+
+/* ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/ } catch (Exception ex) {
+ messageJSON.setMessage("Error occured while saving definition Tab");
+ messageJSON.setAnyStacktrace(getStackTrace(ex));
+
+/* ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Error occured while saving definition Tab");
+ errorJSONRuntime.setStacktrace(getStackTrace(ex));
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+*/
+ return messageJSON;
+ }
+
+ return messageJSON;
+ }
+
+/* @RequestMapping(value = "report/wizard/save_tab_wise_data/{reportID}", method = RequestMethod.POST)
+ public void saveTabWiseData(@PathVariable("reportID") String reportID, @RequestBody WizardJSON wizardJSON,
+ HttpServletRequest request, HttpServletResponse response) throws IOException, RaptorException {
+ ReportDefinition rdef = null;
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ if (rdef != null) {
+ rdef = (new ReportHandler()).loadReportDefinition(request, reportID);
+ }
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& CHECK Report Type " + (AppUtils.nvl(rdef.getReportType()).length()<=0));
+ if(AppUtils.nvl(rdef.getReportType()).length()<=0) {
+ rdef.setReportType(AppConstants.RT_LINEAR);
+ System.out.println("&&&&&&&&&&&&&&&&&&&&&& ADDED Report Type in session ");
+ }
+ // ReportDefinition rdef = (ReportDefinition)
+ // request.getSession().getAttribute(
+ // AppConstants.SI_REPORT_DEFINITION);
+ String tabId = wizardJSON.getTabId();
+ String errorString = "";
+ if (rdef != null) {
+ if (tabId.equals("Def")) {
+ String reportName = ((DefinitionJSON) wizardJSON).getReportName();
+ if (AppUtils.nvl(reportName).length() <= 0)
+ errorString = "ReportName cannot be null;";
+ rdef.setReportName(reportName);
+
+ String reportDescr = ((DefinitionJSON) wizardJSON).getReportDescr();
+ rdef.setReportDescr(reportDescr);
+
+ String formHelpText = ((DefinitionJSON) wizardJSON).getFormHelpText();
+ rdef.setFormHelpText(formHelpText);
+
+ Integer pageSize = ((DefinitionJSON) wizardJSON).getPageSize();
+ rdef.setPageSize(pageSize);
+
+ List<IdNameBooleanJSON> menuIds = ((DefinitionJSON) wizardJSON).getDisplayArea();
+ for (IdNameBooleanJSON menuId : menuIds) {
+ if (menuId.isSelected()) {
+ rdef.setMenuID(menuId.getName());
+ }
+
+ }
+
+ Boolean hideFormFieldsAfterRun = ((DefinitionJSON) wizardJSON).getHideFormFieldsAfterRun();
+ rdef.setHideFormFieldAfterRun(hideFormFieldsAfterRun);
+ Integer maxRowsInExcelCSVDownload = ((DefinitionJSON) wizardJSON).getMaxRowsInExcelCSVDownload();
+ rdef.setMaxRowsInExcelDownload(maxRowsInExcelCSVDownload);
+ Integer frozenColumns = ((DefinitionJSON) wizardJSON).getFrozenColumns();
+ rdef.setFrozenColumns(frozenColumns);
+ String dataGridAlign = ((DefinitionJSON) wizardJSON).getDataGridAlign();
+ rdef.setDataGridAlign(dataGridAlign);
+ String emptyMessage = ((DefinitionJSON) wizardJSON).getEmptyMessage();
+ rdef.setEmptyMessage(emptyMessage);
+ String dataContainerHeight = ((DefinitionJSON) wizardJSON).getDataContainerHeight();
+ rdef.setDataContainerHeight(dataContainerHeight);
+ String dataContainerWidth = ((DefinitionJSON) wizardJSON).getDataContainerWidth();
+ rdef.setDataContainerWidth(dataContainerWidth);
+ boolean runtimeColSortDisabled = ((DefinitionJSON) wizardJSON).getRuntimeColSortDisabled();
+ rdef.setRuntimeColSortDisabled(runtimeColSortDisabled);
+ Integer numFormCols = ((DefinitionJSON) wizardJSON).getNumFormCols();
+ rdef.setNumFormCols(Integer.toString(numFormCols));
+ String reportTitle = ((DefinitionJSON) wizardJSON).getReportTitle();
+ rdef.setReportTitle(reportTitle);
+ String reportSubTitle = ((DefinitionJSON) wizardJSON).getReportSubTitle();
+ rdef.setReportSubTitle(reportSubTitle);
+
+ List<NameBooleanJSON> displayOptions = ((DefinitionJSON) wizardJSON).getDisplayOptions();
+ StringBuffer displayOptionStr = new StringBuffer("NNNNNNN");
+ for (NameBooleanJSON displayOption : displayOptions) {
+ if (displayOption.isSelected()) {
+ if (displayOption.getName().equals("HideFormFields")) {
+ displayOptionStr.setCharAt(0, 'Y');
+ } else if (displayOption.getName().equals("HideChart")) {
+ displayOptionStr.setCharAt(1, 'Y');
+ } else if (displayOption.getName().equals("HideReportData")) {
+ displayOptionStr.setCharAt(2, 'Y');
+ } else if (displayOption.getName().equals("HideExcel")) {
+ displayOptionStr.setCharAt(5, 'Y');
+ } else if (displayOption.getName().equals("HidePdf")) {
+ displayOptionStr.setCharAt(6, 'Y');
+ }
+ }
+
+ }
+
+ rdef.setDisplayOptions(displayOptionStr.toString());
+
+ } else if (tabId.equals("ColEdit")) {
+ String colId = ((ColumnEditJSON) wizardJSON).getColId();
+ List<DataColumnType> reportColumnList = rdef.getAllColumns();
+
+ for (DataColumnType reportColumnType : reportColumnList) {
+ // columnJSON = new ColumnJSON();
+ if (reportColumnType.getColId().equals(colId)) {
+ reportColumnType.setColName(((ColumnEditJSON) wizardJSON).getColName());
+ reportColumnType.setDisplayAlignment(((ColumnEditJSON) wizardJSON).getDisplayAlignment());
+ reportColumnType
+ .setDisplayHeaderAlignment(((ColumnEditJSON) wizardJSON).getDisplayHeaderAlignment());
+ reportColumnType.setIsSortable(((ColumnEditJSON) wizardJSON).isSortable());
+ reportColumnType.setVisible(((ColumnEditJSON) wizardJSON).isVisible());
+ reportColumnType.setDrillDownURL(((ColumnEditJSON) wizardJSON).getDrilldownURL());
+ reportColumnType.setDrillDownParams(((ColumnEditJSON) wizardJSON).getDrilldownParams());
+ reportColumnType.setDrillDownType(((ColumnEditJSON) wizardJSON).getDrilldownType());
+
+ }
+
+ }
+ } else if (tabId.equals("FormEdit")) {
+ String fieldId = ((FormEditJSON) wizardJSON).getFieldId();
+
+ if (rdef.getFormFieldList() != null) {
+ for (FormFieldType fft : rdef.getFormFieldList().getFormField()) {
+ if (fft.getFieldId().equals(fieldId)) {
+ fft.setFieldName(((FormEditJSON) wizardJSON).getFieldName());
+ fft.setFieldType(((FormEditJSON) wizardJSON).getFieldType());
+ fft.setVisible(((FormEditJSON) wizardJSON).isVisible() ? "Y" : "N");
+ fft.setDefaultValue(((FormEditJSON) wizardJSON).getDefaultValue());
+ fft.setFieldDefaultSQL(((FormEditJSON) wizardJSON).getFieldDefaultSQL());
+ fft.setValidationType(((FormEditJSON) wizardJSON).getValidationType());
+
+ // clear predefined value
+ if (fft.getPredefinedValueList() != null) {
+ for (Iterator iter = fft.getPredefinedValueList().getPredefinedValue().iterator(); iter
+ .hasNext();)
+ iter.remove();
+ }
+
+ List<IdNameBooleanJSON> predefList = ((FormEditJSON) wizardJSON).getPredefinedValueList();
+ for (IdNameBooleanJSON item : predefList) {
+ PredefinedValueList predefinedValueList = new ObjectFactory()
+ .createPredefinedValueList();
+ fft.setPredefinedValueList(predefinedValueList);
+ fft.getPredefinedValueList().getPredefinedValue().add(item.getId());
+ }
+
+ }
+ }
+ }
+ } // formedit
+ persistReportDefinition(request, rdef);
+
+ String jsonInString = "";
+
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Success");
+ errorJSONRuntime.setStacktrace("Report changed");
+ PrintWriter out = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ out.write(jsonInString);
+
+ }
+ }*/
+
+ @RequestMapping(value = {"/report/wizard/retrieve_tab_wise_data/{tabId}/{id}", "/report/wizard/retrieve_tab_wise_data/{tabId}/{id}/{detailId}"}, method = RequestMethod.GET)
+ public @ResponseBody String retrieveTabWiseData( @PathVariable Map<String, String> pathVariables, /*@PathVariable("tabId") String tabId, @PathVariable("id") String id, @PathVariable("detailId") String detailId,*/
+ HttpServletRequest request, HttpServletResponse response) throws IOException, RaptorException {
+ ReportDefinition rdef = null;
+ ReportRuntime rr = null;
+ boolean newReport = false;
+ String jsonInString = "";
+ String tabId = "";
+ String id = "";
+ String detailId = "";
+
+ if (pathVariables.containsKey("tabId")) {
+ tabId = pathVariables.get("tabId");
+ }
+ if (pathVariables.containsKey("id")) {
+ id = pathVariables.get("id");
+ }
+ if (pathVariables.containsKey("detailId")) {
+ detailId = pathVariables.get("detailId");
+ }
+
+
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+
+ if (tabId.equals("Def") && id.equals("InSession")) {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ newReport = false;
+
+ } else if (tabId.equals("Def") && id.equals("Create")) {
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, "-1");
+ rdef.setReportType(AppConstants.RT_LINEAR);
+ newReport = true;
+
+ } else if (tabId.equals("Def") && AppUtils.nvl(id).length() > 0) {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
+
+ if (rdef != null && !rdef.getReportID().equals(id)) {
+ request.getSession().removeAttribute(AppConstants.SI_REPORT_DEFINITION);
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ } else if (rr != null && !rr.getReportID().equals(id)) {
+ request.getSession().removeAttribute(AppConstants.SI_REPORT_RUNTIME);
+ removeVariablesFromSession(request);
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ } else if (rdef == null) {
+ rdef = (new ReportHandler()).loadReportDefinition(request, id);
+ }
+ newReport = false;
+
+ } else {
+ rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ }
+ WizardJSON wizardJSON = null;
+ if (tabId.equals("Def")) {
+ wizardJSON = new DefinitionJSON();
+ ((DefinitionJSON) wizardJSON).setTabId("Def");
+ ((DefinitionJSON) wizardJSON).setTabName("Definition");
+
+ ((DefinitionJSON) wizardJSON).setReportId((rdef != null) ? rdef.getReportID() + "" : "");
+ ((DefinitionJSON) wizardJSON).setReportName((rdef != null) ? rdef.getReportName() : "");
+ ((DefinitionJSON) wizardJSON).setReportDescr((rdef != null) ? rdef.getReportDescr() : "");
+ ((DefinitionJSON) wizardJSON).setReportType((rdef != null) ? rdef.getReportType() : AppConstants.RT_LINEAR);
+ ((DefinitionJSON) wizardJSON).setDbInfo((rdef != null) ? rdef.getDBInfo() : "");
+ ((DefinitionJSON) wizardJSON).setFormHelpText((rdef != null) ? rdef.getFormHelpText() : "");
+ ((DefinitionJSON) wizardJSON).setPageSize((rdef != null) ? rdef.getPageSize() : 50);
+ List<IdNameBooleanJSON> displayArea = new ArrayList<IdNameBooleanJSON>();
+ IdNameBooleanJSON idNameJSON = new IdNameBooleanJSON();
+ String qMenu = "";
+ for (int i = 0; i < AppUtils.getQuickLinksMenuIDs().size(); i++) {
+ idNameJSON = new IdNameBooleanJSON();
+ qMenu = (String) AppUtils.getQuickLinksMenuIDs().get(i);
+ idNameJSON.setId(qMenu);
+ idNameJSON.setName(qMenu);
+ if (rdef != null && (rdef.getMenuID().equals(qMenu))) {
+ idNameJSON.setSelected(true);
+ }
+ displayArea.add(idNameJSON);
+ }
+ ((DefinitionJSON) wizardJSON).setDisplayArea(displayArea);
+ ((DefinitionJSON) wizardJSON)
+ .setHideFormFieldsAfterRun((rdef != null) ? rdef.isHideFormFieldAfterRun() : false);
+ ((DefinitionJSON) wizardJSON)
+ .setMaxRowsInExcelCSVDownload((rdef != null) ? rdef.getMaxRowsInExcelDownload() : 500);
+ ((DefinitionJSON) wizardJSON).setFrozenColumns((rdef != null) ? rdef.getFrozenColumns() : 0);
+ ((DefinitionJSON) wizardJSON).setDataGridAlign((rdef != null) ? rdef.getDataGridAlign() : "left");
+ ((DefinitionJSON) wizardJSON).setEmptyMessage((rdef != null) ? rdef.getEmptyMessage() : "No records found");
+ ((DefinitionJSON) wizardJSON)
+ .setDataContainerHeight((rdef != null) ? rdef.getDataContainerHeight() : "600");
+ ((DefinitionJSON) wizardJSON).setDataContainerWidth((rdef != null) ? rdef.getDataContainerWidth() : "900");
+ List<NameBooleanJSON> displayOptions = new ArrayList<NameBooleanJSON>();
+ NameBooleanJSON nameBooleanJSON = new NameBooleanJSON();
+ nameBooleanJSON.setName("HideFormFields");
+ nameBooleanJSON.setSelected((rdef != null) ? rdef.isDisplayOptionHideForm() : false);
+ displayOptions.add(nameBooleanJSON);
+
+ nameBooleanJSON = new NameBooleanJSON();
+ nameBooleanJSON.setName("HideChart");
+ nameBooleanJSON.setSelected((rdef != null) ? rdef.isDisplayOptionHideChart() : false);
+ displayOptions.add(nameBooleanJSON);
+
+ nameBooleanJSON = new NameBooleanJSON();
+ nameBooleanJSON.setName("HideReportData");
+ nameBooleanJSON.setSelected((rdef != null) ? rdef.isDisplayOptionHideData() : false);
+ displayOptions.add(nameBooleanJSON);
+
+ nameBooleanJSON = new NameBooleanJSON();
+ nameBooleanJSON.setName("HideExcel");
+ nameBooleanJSON.setSelected((rdef != null) ? rdef.isDisplayOptionHideExcelIcons() : false);
+ displayOptions.add(nameBooleanJSON);
+
+ nameBooleanJSON = new NameBooleanJSON();
+ nameBooleanJSON.setName("HidePdf");
+ nameBooleanJSON.setSelected((rdef != null) ? rdef.isDisplayOptionHidePDFIcons() : false);
+ displayOptions.add(nameBooleanJSON);
+
+ ((DefinitionJSON) wizardJSON).setDisplayOptions(displayOptions);
+
+ ((DefinitionJSON) wizardJSON)
+ .setRuntimeColSortDisabled((rdef != null) ? rdef.isRuntimeColSortDisabled() : false);
+ ((DefinitionJSON) wizardJSON).setNumFormCols((rdef != null) ? rdef.getNumFormColsAsInt() : 1);
+ ((DefinitionJSON) wizardJSON).setReportTitle((rdef != null) ? rdef.getReportTitle() : "");
+ ((DefinitionJSON) wizardJSON).setReportSubTitle((rdef != null) ? rdef.getReportSubTitle() : "");
+
+ } else if (tabId.equals("Sql")) {
+ wizardJSON = new QueryJSON();
+ ((QueryJSON) wizardJSON).setTabId("Sql");
+ ((QueryJSON) wizardJSON).setTabName("Sql");
+ ((QueryJSON) wizardJSON).setQuery(rdef.getReportSQL());
+
+ } else if (tabId.equals("ColEdit") && rdef != null) {
+ // wizardJSON = new QueryJSON();
+ // ((QueryJSON)
+ // wizardJSON).setQuery((rdef!=null)?rdef.getReportSQL():"");
+ wizardJSON = new ColumnEditJSON();
+ ((ColumnEditJSON) wizardJSON).setTabId("ColEdit");
+ ((ColumnEditJSON) wizardJSON).setTabName("Column Edit");
+
+ List<DataColumnType> reportColumnList = rdef.getAllColumns();
+
+ for (DataColumnType reportColumnType : reportColumnList) {
+ // columnJSON = new ColumnJSON();
+ if (reportColumnType.getColId().equals(id)) {
+ ((ColumnEditJSON) wizardJSON).setColId(reportColumnType.getColId());
+ ((ColumnEditJSON) wizardJSON).setColName(reportColumnType.getColName());
+ ((ColumnEditJSON) wizardJSON).setDisplayAlignment(reportColumnType.getDisplayAlignment());
+ ((ColumnEditJSON) wizardJSON)
+ .setDisplayHeaderAlignment(reportColumnType.getDisplayHeaderAlignment());
+ ((ColumnEditJSON) wizardJSON).setSortable(
+ reportColumnType.isIsSortable() == null ? false : reportColumnType.isIsSortable());
+ ((ColumnEditJSON) wizardJSON).setVisible(reportColumnType.isVisible());
+ ((ColumnEditJSON) wizardJSON).setDrilldownURL(
+ reportColumnType.getDrillDownURL() == null ? "" : reportColumnType.getDrillDownURL());
+ ((ColumnEditJSON) wizardJSON).setDrilldownParams(
+ reportColumnType.getDrillDownParams() == null ? "" : reportColumnType.getDrillDownParams());
+ ((ColumnEditJSON) wizardJSON).setDrilldownType(
+ reportColumnType.getDrillDownType() == null ? "" : reportColumnType.getDrillDownType());
+
+ }
+ }
+
+ } else if (tabId.equals("FormEdit") && rdef != null) {
+ wizardJSON = new FormEditJSON();
+ ((FormEditJSON) wizardJSON).setTabId("FormEdit");
+ ((FormEditJSON) wizardJSON).setTabName("Form Edit");
+ FormFieldType currField = null;
+ try {
+ if (id.equals("add")) {
+
+ currField = rdef.addFormFieldType(new ObjectFactory(), "", "", "", "", "", "", "", "", null, null, "",
+ "");
+ ((FormEditJSON) wizardJSON).setFieldId(currField.getFieldId());
+ ((FormEditJSON) wizardJSON).setFieldName(currField.getFieldName());
+ ((FormEditJSON) wizardJSON).setFieldType(currField.getFieldType());
+ ((FormEditJSON) wizardJSON).setVisible(currField.getVisible().toUpperCase().startsWith("Y"));
+ ((FormEditJSON) wizardJSON).setDefaultValue(currField.getDefaultValue());
+ ((FormEditJSON) wizardJSON).setFieldDefaultSQL(currField.getFieldDefaultSQL());
+ ((FormEditJSON) wizardJSON).setFieldSQL(currField.getFieldSQL());
+ ((FormEditJSON) wizardJSON).setValidationType(currField.getValidationType());
+
+ } else if (id.equals("delete")) {
+ rdef.deleteFormField(detailId);
+ persistReportDefinition(request, rdef);
+ MessageJSON messageJSON = new MessageJSON();
+ messageJSON.setMessage("Formfield " + detailId+ " Deleted");
+ messageJSON.setAnyStacktrace("Given formfield deleted");
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageJSON);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+
+
+ }
+ if (rdef.getFormFieldList() != null) {
+ for (FormFieldType fft : rdef.getFormFieldList().getFormField()) {
+ if (fft.getFieldId().equals(id)) {
+ ((FormEditJSON) wizardJSON).setFieldId(fft.getFieldId());
+ ((FormEditJSON) wizardJSON).setFieldName(fft.getFieldName());
+ ((FormEditJSON) wizardJSON).setFieldType(fft.getFieldType());
+ ((FormEditJSON) wizardJSON).setVisible(fft.getVisible().toUpperCase().startsWith("Y"));
+ ((FormEditJSON) wizardJSON).setDefaultValue(fft.getDefaultValue());
+ ((FormEditJSON) wizardJSON).setFieldDefaultSQL(fft.getFieldDefaultSQL());
+ ((FormEditJSON) wizardJSON).setFieldSQL(fft.getFieldSQL());
+ ((FormEditJSON) wizardJSON).setValidationType(fft.getValidationType());
+
+ PredefinedValueList preDefined = fft.getPredefinedValueList();
+
+ if (preDefined != null) {
+ List<IdNameBooleanJSON> preDefinedList = new ArrayList<IdNameBooleanJSON>();
+ IdNameBooleanJSON idNameBooleanJSON = new IdNameBooleanJSON();
+
+ for (String v : preDefined.getPredefinedValue()) {
+ idNameBooleanJSON = new IdNameBooleanJSON();
+ idNameBooleanJSON.setId(v);
+ idNameBooleanJSON.setName(v);
+ preDefinedList.add(idNameBooleanJSON);
+ }
+ ((FormEditJSON) wizardJSON).setPredefinedValueList(preDefinedList);
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Error occured while retreiving formedit definition Tab");
+ errorJSONRuntime.setStacktrace(getStackTrace(ex));
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+
+ }
+
+ }
+
+
+ //PrintWriter out = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(wizardJSON);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return jsonInString;
+ }
+
+ @RequestMapping(value = "/report/wizard/retrieve_data/{validate}", method = RequestMethod.POST)
+ public String retrieveDataForGivenQuery(@PathVariable("validate") boolean validate, @RequestBody QueryJSON queryJSON, HttpServletRequest request,
+ HttpServletResponse response) throws IOException, RaptorException {
+ String sql = queryJSON.getQuery();
+ String jsonInString = "";
+ //PrintWriter out = response.getWriter();
+
+ ServletContext servletContext = request.getSession().getServletContext();
+ if (!Globals.isSystemInitialized()) {
+ Globals.initializeSystem(servletContext);
+ }
+
+ ReportDefinition rdef = (ReportDefinition) request.getSession().getAttribute(AppConstants.SI_REPORT_DEFINITION);
+ if (rdef == null) {
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Report Definition is not in session;");
+ errorJSONRuntime.setStacktrace("");
+
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+ }
+ } else {
+ if (!sql.trim().toUpperCase().startsWith("SELECT")) {
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ errorJSONRuntime.setErrormessage("Invalid statement - the SQL must start with the keyword SELECT");
+ errorJSONRuntime.setStacktrace("SQL Error");
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ } else {
+ DataSet ds = null;
+ String remoteDb = request.getParameter("remoteDbPrefix");
+ // comment below two lines to test
+ String remoteDbPrefix = (remoteDb != null && !remoteDb.equalsIgnoreCase("null")) ? remoteDb
+ : rdef.getDBInfo();
+ String userId = AppUtils.getUserID(request);
+ // String userId = "1";
+ sql = Utils.replaceInString(sql, "[LOGGED_USERID]", userId);
+ sql = Utils.replaceInString(sql, "[USERID]", userId);
+ String[] reqParameters = Globals.getRequestParams().split(",");
+ String[] sessionParameters = Globals.getSessionParams().split(",");
+ javax.servlet.http.HttpSession session = request.getSession();
+ logger.debug(EELFLoggerDelegate.debugLogger, ("B4 testRunSQL " + sql));
+ if (request != null) {
+ for (int i = 0; i < reqParameters.length; i++) {
+ if (!reqParameters[i].startsWith("ff"))
+ sql = Utils.replaceInString(sql, "[" + reqParameters[i].toUpperCase() + "]",
+ request.getParameter(reqParameters[i].toUpperCase()));
+ else
+ sql = Utils.replaceInString(sql, "[" + reqParameters[i].toUpperCase() + "]",
+ request.getParameter(reqParameters[i]));
+ }
+ }
+ if (session != null) {
+ for (int i = 0; i < sessionParameters.length; i++) {
+ // if(!sessionParameters[i].startsWith("ff"))
+ // sql = Utils.replaceInString(sql, "[" +
+ // sessionParameters[i].toUpperCase()+"]",
+ // (String)session.getAttribute(sessionParameters[i].toUpperCase())
+ // );
+ // else {
+ logger.debug(EELFLoggerDelegate.debugLogger, (" Session " + " sessionParameters[i] "
+ + sessionParameters[i] + " " + (String) session.getAttribute(sessionParameters[i])));
+ sql = Utils.replaceInString(sql, "[" + sessionParameters[i].toUpperCase() + "]",
+ (String) session.getAttribute(sessionParameters[i]));
+ // }
+ }
+ }
+ logger.debug(EELFLoggerDelegate.debugLogger, ("After testRunSQL " + sql));
+ try {
+
+ response.setContentType("application/json");
+ ds = ConnectionUtils.getDataSet(sql, "local", true);
+ /*
+ * SimpleModule module = new SimpleModule();
+ * module.addSerializer(new ResultSetSerializer());
+ *
+ * ObjectMapper objectMapper = new ObjectMapper();
+ * objectMapper.registerModule(module);
+ *
+ * ObjectNode objectNode = objectMapper.createObjectNode();
+ * objectNode.putPOJO("results", ds);
+ *
+ * objectMapper.writeValue(writer, objectNode);
+ */
+
+ QueryResultJSON queryResultJSON = new QueryResultJSON();
+ queryResultJSON.setQuery(queryJSON.getQuery());
+
+ int numColumns = ds.getColumnCount();
+ queryResultJSON.setTotalRows(ds.getRowCount());
+
+ int count = 0;
+ Map<String, String> dvJSON = null;
+ ArrayList<String> colList = new ArrayList<String>();
+ ArrayList<Map<String, String>> reportDataRows = new ArrayList<Map<String, String>>();
+ if (!ds.isEmpty()) {
+ count = 0;
+
+ for (int i = 0; i < ds.getColumnCount(); i++) {
+ colList.add(ds.getColumnName(i));
+ }
+ queryResultJSON.setReportDataColumns(colList);
+ if (queryResultJSON.getTotalRows() > 0) {
+ count = 0;
+ dvJSON = new HashMap<String, String>();
+ // for(rd.reportDataRows.resetNext();
+ // rd.reportDataRows.hasNext(); count++) {
+ for (int r = 0; r < Math.min(ds.getRowCount(), 100); r++) {
+ dvJSON = new HashMap<String, String>();
+ for (int c = 0; c < ds.getColumnCount(); c++) {
+ // jgen.writeFieldName(columnNames[c]);
+ // jgen.writeString(ds.getString(r, c));
+ try {
+ dvJSON.put(ds.getColumnName(c), ds.getString(r, c));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+ }
+ reportDataRows.add(dvJSON);
+
+ }
+ }
+
+ }
+ queryResultJSON.setReportDataRows(reportDataRows);
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ // String jsonInString = "";
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(queryResultJSON);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ }
+
+ // return queryResultJSON;
+
+ } catch (ReportSQLException ex) {
+ ex.printStackTrace();
+ ErrorJSONRuntime errorJSONRuntime = new ErrorJSONRuntime();
+ if(sql.contains("[")) {
+ errorJSONRuntime.setErrormessage("Formfield information is present in the query, hence couldn't execute");
+ errorJSONRuntime.setStacktrace("Formfield information is present in the query, hence couldn't execute");
+ } else {
+ errorJSONRuntime.setErrormessage(ex.getMessage());
+ errorJSONRuntime.setStacktrace(getStackTrace(ex));
+ }
+ ObjectMapper mapper = new ObjectMapper();
+ // mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
+ // mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ try {
+ jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorJSONRuntime);
+ } catch (Exception ex1) {
+ ex1.printStackTrace();
+
+ }
+ }
+ if(validate) {
+ String query = XSSFilter.filterRequestOnlyScript(queryJSON.getQuery());
+ request.setAttribute("sqlValidated", "N");
+ rdef.parseReportSQL(query);
+ request.setAttribute("sqlValidated", "Y");
+ persistReportDefinition(request, rdef);
+
+ }
+
+ }
+ }
+ return jsonInString;
+
+ }
+
+ @RequestMapping(value = "save_chart", method = RequestMethod.POST)
+ public void reportChartReceive(@RequestBody ChartJSON chartJSON, HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ ReportRuntime reportRuntime;
+ // System.out.println("*****Hit RaptorChart******");
+
+ // System.out.println("chartJSON"+chartJSON.getRangeAxisList());
+ // System.out.println("chartJSON"+chartJSON.getCommonChartOptions().getLegendPosition());
+ reportRuntime = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME); // changing
+ // session
+ // to
+ // request
+ String reportID = request.getParameter("c_master");
+ if (reportRuntime == null && AppUtils.nvl(reportID).length() > 0) {
+ try {
+ ReportHandler rh = new ReportHandler();
+ reportRuntime = rh.loadReportRuntime(request, reportID);
+ } catch (RaptorException ex) {
+ ex.printStackTrace();
+
+ }
+ }
+
+ if (reportRuntime != null) {
+ String chartType = chartJSON.getChartType();
+ reportRuntime.setChartType(chartJSON.getChartType());
+ reportRuntime.setChartAnimate(chartJSON.isAnimation());
+ reportRuntime.setChartWidth(chartJSON.getWidth());
+ reportRuntime.setChartHeight(chartJSON.getHeight());
+ reportRuntime.setShowChartTitle(chartJSON.isShowTitle());
+
+ String domainAxis = null;
+ domainAxis = chartJSON.getDomainAxis();
+
+ List<DataColumnType> reportCols = reportRuntime.getAllColumns();
+
+ for (Iterator<DataColumnType> iter = reportCols.iterator(); iter.hasNext();) {
+ DataColumnType dct = (DataColumnType) iter.next();
+ if (dct.getColId().equals(domainAxis)) {
+ dct.setColOnChart(AppConstants.GC_LEGEND);
+ } else {
+ dct.setColOnChart(null);
+ }
+ }
+
+ CategoryAxisJSON categoryAxisJSON = chartJSON.getCategoryAxisJSON();
+ String categoryAxis = null;
+
+ categoryAxis = (categoryAxisJSON != null ? categoryAxisJSON.getValue() : "");
+
+ reportCols = reportRuntime.getAllColumns();
+
+ for (Iterator<DataColumnType> iter = reportCols.iterator(); iter.hasNext();) {
+ DataColumnType dct = (DataColumnType) iter.next();
+ if (dct.getColId().equals(categoryAxis)) {
+ dct.setChartSeries(true);
+ } else {
+ dct.setChartSeries(false);
+ }
+ }
+
+ ArrayList<RangeAxisJSON> rangeAxisList = chartJSON.getRangeAxisList();
+ int r = 0;
+ for (int i = 0; i < rangeAxisList.size(); i++) {
+ RangeAxisJSON rangeAxisJSON = rangeAxisList.get(i);
+ String rangeAxis = rangeAxisJSON.getRangeAxis();
+ String rangeYAxis = AppUtils.nvl(rangeAxisJSON.getRangeYAxis());
+ String rangeChartGroup = AppUtils.nvl(rangeAxisJSON.getRangeChartGroup());
+ String rangeColor = AppUtils.nvl(rangeAxisJSON.getRangeColor());
+ String rangeLineType = AppUtils.nvl(rangeAxisJSON.getRangeLineType());
+
+ rangefor: for (Iterator<DataColumnType> iterator = reportCols.iterator(); iterator.hasNext();) {
+ DataColumnType dct = (DataColumnType) iterator.next();
+ if (dct.getColId().equals(rangeAxis)) {
+ dct.setChartSeq(++r);
+ dct.setColOnChart("0");
+ dct.setYAxis(rangeYAxis); // +"|"+dct.getColId());
+ dct.setChartGroup(rangeChartGroup); // +"|"+dct.getColId());
+ dct.setChartColor(rangeColor);
+ dct.setChartLineType(rangeLineType);
+
+ if (chartType.equals(AppConstants.GT_ANNOTATION_CHART)
+ || chartType.equals(AppConstants.GT_FLEX_TIME_CHARTS)) {
+ if (rangeAxisJSON.isShowAsArea()) {
+ dct.setIsRangeAxisFilled(true);
+ } else {
+ dct.setIsRangeAxisFilled(false);
+ }
+ }
+ break rangefor;
+ }
+ }
+
+ }
+
+ reportRuntime.setChartLeftAxisLabel(chartJSON.getPrimaryAxisLabel());
+ reportRuntime.setChartRightAxisLabel(chartJSON.getSecondaryAxisLabel());
+
+ reportRuntime.setRangeAxisLowerLimit(chartJSON.getMinRange());
+ reportRuntime.setRangeAxisUpperLimit(chartJSON.getMaxRange());
+
+ if (chartType.equals(AppConstants.GT_ANNOTATION_CHART)
+ || chartType.equals(AppConstants.GT_FLEX_TIME_CHARTS)) {
+ if (chartJSON.getFlexTimeSeriesChartOptions() != null) {
+ reportRuntime.setZoomIn(chartJSON.getFlexTimeSeriesChartOptions().getZoomIn());
+ reportRuntime.setTimeAxisType(chartJSON.getFlexTimeSeriesChartOptions().getTimeAxisType());
+ }
+
+ }
+
+ if (chartType.equals(AppConstants.GT_TIME_SERIES)) {
+ if (chartJSON.getTimeSeriesChartOptions() != null) {
+ reportRuntime.setTimeSeriesRender(chartJSON.getTimeSeriesChartOptions().getLineChartRenderer());
+ reportRuntime.setShowXAxisLabel(chartJSON.getTimeSeriesChartOptions().isShowXAxisLabel());
+ reportRuntime.setAddXAxisTickers(chartJSON.getTimeSeriesChartOptions().isAddXAxisTicker());
+ reportRuntime.setTimeAxis(chartJSON.getTimeSeriesChartOptions().isNonTimeAxis());
+ reportRuntime.setMultiSeries(chartJSON.getTimeSeriesChartOptions().isMultiSeries());
+ }
+
+ }
+
+ if (chartType.equals(AppConstants.GT_BAR_3D)) {
+ if (chartJSON.getBarChartOptions() != null) {
+ reportRuntime.setChartOrientation(
+ chartJSON.getBarChartOptions().isVerticalOrientation() ? "vertical" : "horizontal");
+ reportRuntime.setChartStacked(chartJSON.getBarChartOptions().isStackedChart());
+ reportRuntime.setBarControls(chartJSON.getBarChartOptions().isDisplayBarControls());
+ reportRuntime.setXAxisDateType(chartJSON.getBarChartOptions().isxAxisDateType());
+ reportRuntime.setLessXaxisTickers(chartJSON.getBarChartOptions().isMinimizeXAxisTickers());
+ reportRuntime.setTimeAxis(chartJSON.getBarChartOptions().isTimeAxis());
+ reportRuntime.setLogScale(chartJSON.getBarChartOptions().isyAxisLogScale());
+ }
+ }
+
+ reportRuntime.setLegendLabelAngle(chartJSON.getCommonChartOptions().getLegendLabelAngle());
+ reportRuntime.setLegendPosition(chartJSON.getCommonChartOptions().getLegendPosition());
+ reportRuntime.setChartLegendDisplay(chartJSON.getCommonChartOptions().isHideLegend() ? "Y" : "N");
+ reportRuntime.setAnimateAnimatedChart(chartJSON.getCommonChartOptions().isAnimateAnimatedChart());
+
+ reportRuntime.setTopMargin(chartJSON.getCommonChartOptions().getTopMargin());
+ reportRuntime.setBottomMargin(chartJSON.getCommonChartOptions().getBottomMargin());
+ reportRuntime.setLeftMargin(chartJSON.getCommonChartOptions().getLeftMargin());
+ reportRuntime.setRightMargin(chartJSON.getCommonChartOptions().getRightMargin());
+
+ for (Iterator<DataColumnType> iterator = reportCols.iterator(); iterator.hasNext();) {
+ DataColumnType dct = (DataColumnType) iterator.next();
+ if (!(AppUtils.nvl(dct.getColOnChart()).equals(AppConstants.GC_LEGEND)
+ || (dct.getChartSeq() != null && dct.getChartSeq() > 0) || dct.isChartSeries())) {
+ dct.setChartSeq(-1);
+ dct.setChartColor(null);
+ dct.setColOnChart(null);
+ dct.setCreateInNewChart(false);
+ dct.setChartGroup(null);
+ dct.setYAxis(null);
+ }
+ }
+
+ try {
+ reportRuntime.persistLinearReport(request);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ logger.error("While SAVING CHART", ex);
+ }
+ }
+
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+
+ public String nvl(String s) {
+ return (s == null) ? "" : s;
+ }
+
+ public String nvl(String s, String sDefault) {
+ return nvl(s).equals("") ? sDefault : s;
+ }
+
+ public static String getStackTrace(Throwable aThrowable) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(result);
+ aThrowable.printStackTrace(printWriter);
+ return result.toString();
+ }
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RaptorControllerAsync.class);
+
+ public void persistReportDefinition(HttpServletRequest request, ReportDefinition rdef) throws RaptorException {
+ ReportRuntime rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
+ if (rr != null && rr.getReportID().equals(rdef.getReportID()))
+ request.getSession().removeAttribute(AppConstants.SI_REPORT_RUNTIME);
+ rdef.persistReport(request);
+ } // persistReportDefinition
+
+ // Remove from session
+ private void removeVariablesFromSession(HttpServletRequest request) {
+ HttpSession session = request.getSession();
+ session.removeAttribute(AppConstants.DRILLDOWN_REPORTS_LIST);
+ session.removeAttribute(AppConstants.DRILLDOWN_INDEX);
+ session.removeAttribute(AppConstants.FORM_DRILLDOWN_INDEX);
+ session.removeAttribute(AppConstants.SI_BACKUP_FOR_REP_ID);
+ session.removeAttribute(AppConstants.SI_COLUMN_LOOKUP);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_REP_ID);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_REPORTRUNTIME_MAP);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_REPORTRUNTIME);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_REPORTDATA_MAP);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_CHARTDATA_MAP);
+ session.removeAttribute(AppConstants.SI_DASHBOARD_DISPLAYTYPE_MAP);
+ session.removeAttribute(AppConstants.SI_DATA_SIZE_FOR_TEXTFIELD_POPUP);
+ session.removeAttribute(AppConstants.SI_MAP);
+ session.removeAttribute(AppConstants.SI_MAP_OBJECT);
+ session.removeAttribute(AppConstants.SI_REPORT_DEFINITION);
+ session.removeAttribute(AppConstants.SI_REPORT_RUNTIME);
+ session.removeAttribute(AppConstants.SI_REPORT_RUN_BACKUP);
+ session.removeAttribute(AppConstants.SI_REPORT_SCHEDULE);
+ session.removeAttribute(AppConstants.RI_REPORT_DATA);
+ session.removeAttribute(AppConstants.RI_CHART_DATA);
+ session.removeAttribute(AppConstants.SI_FORMFIELD_INFO);
+ session.removeAttribute(AppConstants.SI_FORMFIELD_DOWNLOAD_INFO);
+ session.removeAttribute(AppConstants.EMBEDDED_REPORTRUNTIME_MAP);
+ session.removeAttribute(AppConstants.EMBEDDED_REPORTDATA_MAP);
+ Enumeration<String> enum1 = session.getAttributeNames();
+ String attributeName = "";
+ while (enum1.hasMoreElements()) {
+ attributeName = enum1.nextElement();
+ if (attributeName.startsWith("parent_")) {
+ session.removeAttribute(attributeName);
+ }
+ }
+ }
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java
index b5df482b..a84d2174 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/ReportsSearchListController.java
@@ -20,11 +20,14 @@
package org.openecomp.portalsdk.analytics.system.fusion.web;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+import javax.servlet.http.*;
+
+import org.openecomp.portalsdk.analytics.system.fusion.domain.CR_Report;
import org.openecomp.portalsdk.analytics.system.fusion.service.RaptorService;
-import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.bind.*;
+import org.springframework.web.servlet.*;
public class ReportsSearchListController {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java
index 3ec5c5e8..7728e99e 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/AppConstants.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.analytics.util;
-import org.openecomp.portalsdk.analytics.model.base.IdNameList;
+import java.awt.Color;
+
+import org.openecomp.portalsdk.analytics.model.base.*;
/**<HR/>
* This class is part of <B><I>RAPTOR (Rapid Application Programming Tool for OLAP Reporting)</I></B><BR/>
@@ -390,17 +392,21 @@ public class AppConstants {
// Non-standard chart types
public final static String GT_MTD_BAR = "MTDBarChart";
+ // JFree latest version only chart type
public final static String GT_METER = "MeterChart";
public final static String GT_STACK_BAR = "StackedBarChart";
-
+
+ public static Color GREEN_COLOR = new Color(0, 128, 0);
// chart filter
public final static int CHART_ALL_COLUMNS = 0;
public final static int CHART_WITHOUT_NEWCHART_COLUMNS = 1;
public final static int CHART_NEWCHART_COLUMNS = 2;
-
+ // chart colors
+ public static Color[] CHART_SERIES_COLORS = { Color.black, GREEN_COLOR, Color.red,
+ Color.blue, Color.magenta, Color.orange, Color.cyan, Color.pink, Color.yellow };
// Chart columns
public final static String GC_LEGEND = "LEGEND";
@@ -577,7 +583,10 @@ public class AppConstants {
public static final String OJ_JOINED = "JOINED"; // cur_table =
// join_table (+)
-
+ // JFree versions
+ public static final String JFV_0911 = "0.9.11";
+
+ public static final String JFV_LATEST = "latest";
// List of Available Total Functions
public static final String TOTAL_SUM_ID = "SUM(";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java
index e70a2ed2..f0740399 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/DataSet.java
@@ -20,10 +20,10 @@
package org.openecomp.portalsdk.analytics.util;
import java.io.Serializable;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.util.Vector;
+import java.sql.*;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.system.Globals;
public class DataSet extends Vector implements Serializable {
private Vector columnNames = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java
index 6a03354e..67370d96 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/ExcelColorDef.java
@@ -26,9 +26,6 @@ import org.apache.poi.hssf.util.HSSFColor;
public class ExcelColorDef {
- /**
- * @param args
- */
public static HashMap colors = new HashMap();
public static void initializeExcelColorDef() {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java
index c1ffa70f..9c76c368 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/HtmlStripper.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.util;
+import java.io.*;
+
import org.openecomp.portalsdk.analytics.RaptorObject;
public class HtmlStripper extends RaptorObject// this function can be accessed publicly
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java
index 3220eeb2..3220eeb2 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Log.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java
index 2d9bef42..2d9bef42 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/RemDbInfo.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java
index 15b4042a..15b4042a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/SQLCorrector.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java
index 731a50ee..0dc6da17 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Scheduler.java
@@ -20,12 +20,12 @@
package org.openecomp.portalsdk.analytics.util;
import java.sql.SQLException;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.util.*;
+import org.openecomp.portalsdk.analytics.error.ReportSQLException;
import org.openecomp.portalsdk.analytics.scheduler.SendNotifications;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class Scheduler extends TimerTask {
private Timer timer = new Timer(true);
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java
index 1995c567..e8ca4292 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/Utils.java
@@ -19,23 +19,17 @@
*/
package org.openecomp.portalsdk.analytics.util;
-import java.io.File;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
+import java.util.*;
import java.util.regex.Pattern;
+import java.io.File;
+import java.text.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.system.*;
import org.openecomp.portalsdk.analytics.system.fusion.adapter.Item;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java
index e6d01994..1d8af016 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/XSSFilter.java
@@ -21,6 +21,7 @@ package org.openecomp.portalsdk.analytics.util;
/**
*
+ * @author Sundar
* This class is used to filter javascript tags to avoid XSS attacks.
*/
public class XSSFilter {
@@ -87,4 +88,4 @@ public class XSSFilter {
private static String nvl(String s) {
return (s == null) ? "" : s;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/jar/ExtractJar.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/jar/ExtractJar.java
new file mode 100644
index 00000000..822456d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/jar/ExtractJar.java
@@ -0,0 +1,237 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.analytics.util.jar;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+public class ExtractJar {
+
+ public static int bufferSize = 8192;
+ public static String JARFILE = "raptor_upgrade.jar";
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length > 0 && args[0] != null && args[0].length() > 0)
+ extractFilesFromJar(args[0]);
+ else {
+ System.out.println("Current Directory is taken as webapp path");
+ String currentDir = new File(".").getAbsolutePath();
+ extractFilesFromJar(currentDir);
+ }
+ }
+
+ /**
+ *
+ * @param jarFile
+ * @throws Exception
+ */
+ public static void readJar(File jarFile) throws Exception {
+ JarInputStream in = new JarInputStream(new FileInputStream(jarFile));
+ JarEntry je;
+ while ((je = in.getNextJarEntry()) != null) {
+ if (je.isDirectory() == false) {
+ if (je.getName().startsWith("org/openecomp/portalsdk/analytics/config/")) {
+ System.out.println(je.getName() + " " + je.getTime());
+
+ }
+ }
+ }
+ in.close();
+ }
+
+ /**
+ *
+ * @param directory
+ * @throws IOException
+ */
+ public static void extractFilesFromJar(String directory) throws IOException {
+ Class clazz = ExtractJar.class;
+ URL jarUrl = clazz.getProtectionDomain().getCodeSource().getLocation();
+
+ JarInputStream entryStream = new JarInputStream(jarUrl.openStream());
+ JarEntry entry;
+
+ while (true) {
+ entry = entryStream.getNextJarEntry();
+ if (entry == null)
+ break;
+ if (entry.getName().indexOf("jarutil") < 0) {
+ System.out.println(entry.getName());
+ File file = new File(directory, entry.getName());
+ if (entry.isDirectory()) {
+ if (!file.exists())
+ file.mkdirs();
+ } else {
+ File dir = new File(file.getParent());
+ if (!dir.exists())
+ dir.mkdirs();
+ if (file.exists())
+ file.delete();
+ FileOutputStream fout = new FileOutputStream(file);
+ copy(entryStream, fout);
+ fout.close();
+
+ if (entry.getTime() >= 0)
+ file.setLastModified(entry.getTime());
+ }
+
+ }
+ entryStream.closeEntry();
+ }
+ entryStream.close();
+ System.out.println("/WEB-INF/classes/org/openecomp/portalsdk/analytics");
+ System.out.println("Delete .... ");
+
+ File file1 = new File(directory, "/WEB-INF/classes/org/openecomp/portalsdk/analytics");
+
+ deleteDir(file1);
+ System.out.println("Deleted ....");
+
+ System.out.println("raptor_upgrade_setup.jar");
+ file1 = new File(directory, "/raptor_upgrade_setup.jar");
+
+ deleteDir(file1);
+ System.out.println("Deleted ....");
+
+ System.out.println("/org");
+ System.out.println("Delete .... ");
+
+ file1 = new File(directory, "/org");
+ System.out.println(" ********************************* ");
+ deleteDir(file1);
+ System.out.println("Deleted ....");
+ System.out.println("org");
+ System.out.println("Delete .... ");
+
+ System.out.println("************************************************");
+ System.out.println("* *");
+ System.out.println("* *");
+ System.out.println("* RAPTOR SETUP COMPLETE. *");
+ System.out.println("* *");
+ System.out.println("* Thank you for upgrading. *");
+ System.out.println("* *");
+ System.out.println("************************************************");
+ }
+
+ /**
+ *
+ * @param in
+ * @param out
+ * @param byteCount
+ * @throws IOException
+ */
+ public static void copy(InputStream in, OutputStream out, long byteCount) throws IOException {
+ byte buffer[] = new byte[bufferSize];
+ int len = bufferSize;
+ if (byteCount >= 0) {
+ while (byteCount > 0) {
+ if (byteCount < bufferSize)
+ len = in.read(buffer, 0, (int) byteCount);
+ else
+ len = in.read(buffer, 0, bufferSize);
+ if (len == -1)
+ break;
+
+ byteCount -= len;
+ out.write(buffer, 0, len);
+ }
+ } else {
+ while (true) {
+ len = in.read(buffer, 0, bufferSize);
+ if (len < 0)
+ break;
+ out.write(buffer, 0, len);
+ }
+ }
+ }
+
+ /**
+ * Copy Reader to Writer for byteCount bytes or until EOF or exception.
+ *
+ * @param in
+ * @param out
+ * @param byteCount
+ * @throws IOException
+ */
+ public static void copy(Reader in, Writer out, long byteCount) throws IOException {
+ char buffer[] = new char[bufferSize];
+ int len = bufferSize;
+ if (byteCount >= 0) {
+ while (byteCount > 0) {
+ if (byteCount < bufferSize)
+ len = in.read(buffer, 0, (int) byteCount);
+ else
+ len = in.read(buffer, 0, bufferSize);
+
+ if (len == -1)
+ break;
+ byteCount -= len;
+ out.write(buffer, 0, len);
+ }
+ } else {
+ while (true) {
+ len = in.read(buffer, 0, bufferSize);
+ if (len == -1)
+ break;
+ out.write(buffer, 0, len);
+ }
+ }
+ }
+
+ /**
+ * Copy Stream in to Stream out until EOF or exception.
+ *
+ * @param in
+ * @param out
+ * @throws IOException
+ */
+ public static void copy(InputStream in, OutputStream out) throws IOException {
+ copy(in, out, -1);
+ }
+
+ public static boolean deleteDir(File dir) {
+ System.out.println("Name: " + dir.getName() + " " + dir.isDirectory());
+ if (dir.isDirectory()) {
+ String[] children = dir.list();
+ System.out.println(children);
+ for (int i = 0; i < children.length; i++) {
+ boolean success = deleteDir(new File(dir, children[i]));
+ if (!success) {
+ return false;
+ }
+ }
+ }
+
+ return dir.delete();
+ }
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java
index 3c1f0dd4..fc39af91 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/util/upgrade/SystemUpgrade.java
@@ -19,19 +19,21 @@
*/
package org.openecomp.portalsdk.analytics.util.upgrade;
-import java.sql.Connection;
-import java.util.Iterator;
-import java.util.StringTokenizer;
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+import javax.servlet.http.*;
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.analytics.model.ReportLoader;
-import org.openecomp.portalsdk.analytics.model.base.ReportWrapper;
-import org.openecomp.portalsdk.analytics.model.definition.ReportDefinition;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.DbUtils;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+import org.openecomp.portalsdk.analytics.controller.*;
+import org.openecomp.portalsdk.analytics.error.*;
+import org.openecomp.portalsdk.analytics.model.*;
+import org.openecomp.portalsdk.analytics.model.base.*;
+import org.openecomp.portalsdk.analytics.model.definition.*;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.view.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class SystemUpgrade extends org.openecomp.portalsdk.analytics.RaptorObject {
private static final String upgradeFromVersion = "1.x";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java
index c52125e5..ffec6065 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeader.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.view;
+import org.openecomp.portalsdk.analytics.util.*;
+
public class ColumnHeader extends org.openecomp.portalsdk.analytics.RaptorObject {
private String columnTitle = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java
index b1f581ed..196da89c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnHeaderRow.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.util.*;
public class ColumnHeaderRow extends Vector {
private String rowHeight = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java
index 5045cd58..5045cd58 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ColumnVisual.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java
index 34cc10d3..8970d1a8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabColumnValues.java
@@ -19,11 +19,11 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.system.ConnectionUtils;
-import org.openecomp.portalsdk.analytics.util.DataSet;
+import org.openecomp.portalsdk.analytics.error.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
public class CrossTabColumnValues extends org.openecomp.portalsdk.analytics.RaptorObject {
private String colId = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java
index 55c2c757..090fd863 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabOrderManager.java
@@ -19,16 +19,16 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Iterator;
-import java.util.Vector;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.openecomp.portalsdk.analytics.RaptorObject;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
+import org.openecomp.portalsdk.analytics.error.*;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class CrossTabOrderManager extends RaptorObject {
private Vector colHeaderValues = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java
index bb5e9dc6..1f0928c2 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/CrossTabTotalValue.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
public class CrossTabTotalValue extends org.openecomp.portalsdk.analytics.RaptorObject {
private Vector headerValues = null;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java
index aa53be1d..93fcc0e7 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataRow.java
@@ -19,8 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.ArrayList;
-import java.util.Vector;
+import java.util.*;
public class DataRow/* extends Vector*/ {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java
index 605cb226..8eb090c4 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/DataValue.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.view;
+import org.openecomp.portalsdk.analytics.util.*;
+
public class DataValue extends org.openecomp.portalsdk.analytics.RaptorObject {
private String displayValue = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java
index fa54a1d9..fa54a1d9 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/HtmlFormatter.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java
index 6bbe0127..f717e44c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportColumnHeaderRows.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
public class ReportColumnHeaderRows extends Vector {
private int nextElemIdx = 0;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java
index 5ef15dc4..0e1e55ee 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportData.java
@@ -20,15 +20,12 @@
package org.openecomp.portalsdk.analytics.view;
import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
+import java.util.*;
-import org.openecomp.portalsdk.analytics.model.runtime.FormatProcessor;
-import org.openecomp.portalsdk.analytics.model.runtime.VisualManager;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.Utils;
+import org.openecomp.portalsdk.analytics.model.runtime.*;
+import org.openecomp.portalsdk.analytics.system.*;
+import org.openecomp.portalsdk.analytics.util.*;
+import org.openecomp.portalsdk.analytics.xmlobj.*;
public class ReportData extends org.openecomp.portalsdk.analytics.RaptorObject implements Serializable {
// private static final boolean sortData = true; // sort cross-tab data by
@@ -462,8 +459,12 @@ public class ReportData extends org.openecomp.portalsdk.analytics.RaptorObject i
ch.setSortable(sortable);
//chr.addColumnHeader(new ColumnHeader(displayName, (displayWidth > 100) ? "10%" : (""
// + displayWidth + "%"), 1, isRuntimeColSortDisabled ? null : colId));
- chr.addColumnHeader(ch);
- columnVisuals.add(new ColumnVisual(colId, displayName, currentlyVisible, currentSort));
+
+ if (displayName != "Hidden") {
+
+ chr.addColumnHeader(ch);
+ columnVisuals.add(new ColumnVisual(colId, displayName, currentlyVisible, currentSort));
+ }
} // createColumn
public void columnVisualShowHide(String colId, boolean newVisible) {
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java
index e2c9a6e5..db150d53 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportDataRows.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
public class ReportDataRows extends Vector {
private int nextElemIdx = 0;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java
index e3e4f817..f887e5f2 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/ReportRowHeaderCols.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
public class ReportRowHeaderCols extends Vector {
private int nextElemIdx = 0;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java
index c4c6b1be..1eb7a522 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeader.java
@@ -19,6 +19,8 @@
*/
package org.openecomp.portalsdk.analytics.view;
+import org.openecomp.portalsdk.analytics.util.*;
+
public class RowHeader extends org.openecomp.portalsdk.analytics.RaptorObject {
private String rowTitle = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java
index 2b405e84..c5366f57 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/view/RowHeaderCol.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.analytics.view;
-import java.util.Vector;
+import java.util.*;
+
+import org.openecomp.portalsdk.analytics.util.*;
public class RowHeaderCol extends Vector {
private String columnWidth = "";
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java
index 48ae70a8..48ae70a8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartAdditionalOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java
index f097f3fa..f097f3fa 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillFormfield.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java
index 3fc3eec3..8ba7e2da 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ChartDrillOptions.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java
index a429ae99..ad332aa6 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java
index 4ba660ed..4ba660ed 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ColFilterType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java
index 58c7e30d..58c7e30d 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/CustomReportType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java
index 4c3b483b..b8437aa4 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java
index c6d17485..c6d17485 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardEditorReport.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java
index 8e44cfe1..42f1e410 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReports.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java
index 1755e70e..4a983aeb 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DashboardReportsNew.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java
index 79e6e0b2..41e8d9ae 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java
index c710a1ea..c710a1ea 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataColumnType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java
index 1e39348a..3dd7e118 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java
index 08b066c8..08b066c8 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataSourceType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java
index c26bce7c..c26bce7c 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/DataminingOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java
index 104ee1c1..dc798c84 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java
index 77922c7a..77922c7a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormFieldType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java
index aa49a81c..34361c25 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java
index 5c0abf8a..5c0abf8a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/FormatType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java
index 102e3fc5..102e3fc5 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptItemType.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java
index 9c8cea79..fe7fb7bb 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/JavascriptList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java
index 7c4d784a..7c4d784a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Marker.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java
index 5515cd23..5515cd23 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ObjectFactory.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java
index 78d727c2..78d727c2 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PDFAdditionalOptions.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java
index b008d566..6a8e445a 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/PredefinedValueList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java
new file mode 100644
index 00000000..796f6058
--- /dev/null
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java
@@ -0,0 +1,444 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.5-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2016.06.07 at 02:07:29 PM EDT
+//
+
+
+package org.openecomp.portalsdk.analytics.xmlobj;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for ReportMap complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="ReportMap">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="markerColor" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="useDefaultSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="height" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="width" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="isMapAllowedYN" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="addAddressInDataYN" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="addressColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="dataColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="defaultMapType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="latColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="longColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="colorColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="legendColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="markers" type="{}Marker" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "ReportMap", propOrder = {
+ "markerColor",
+ "useDefaultSize",
+ "height",
+ "width",
+ "isMapAllowedYN",
+ "addAddressInDataYN",
+ "addressColumn",
+ "dataColumn",
+ "defaultMapType",
+ "latColumn",
+ "longColumn",
+ "colorColumn",
+ "legendColumn",
+ "markers"
+})
+public class ReportMap {
+
+ protected String markerColor;
+ protected String useDefaultSize;
+ protected String height;
+ protected String width;
+ protected String isMapAllowedYN;
+ protected String addAddressInDataYN;
+ protected String addressColumn;
+ protected String dataColumn;
+ protected String defaultMapType;
+ protected String latColumn;
+ protected String longColumn;
+ protected String colorColumn;
+ protected String legendColumn;
+ protected List<Marker> markers;
+
+ /**
+ * Gets the value of the markerColor property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMarkerColor() {
+ return markerColor;
+ }
+
+ /**
+ * Sets the value of the markerColor property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMarkerColor(String value) {
+ this.markerColor = value;
+ }
+
+ /**
+ * Gets the value of the useDefaultSize property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getUseDefaultSize() {
+ return useDefaultSize;
+ }
+
+ /**
+ * Sets the value of the useDefaultSize property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setUseDefaultSize(String value) {
+ this.useDefaultSize = value;
+ }
+
+ /**
+ * Gets the value of the height property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the value of the height property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setHeight(String value) {
+ this.height = value;
+ }
+
+ /**
+ * Gets the value of the width property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the value of the width property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setWidth(String value) {
+ this.width = value;
+ }
+
+ /**
+ * Gets the value of the isMapAllowedYN property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getIsMapAllowedYN() {
+ return isMapAllowedYN;
+ }
+
+ /**
+ * Sets the value of the isMapAllowedYN property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setIsMapAllowedYN(String value) {
+ this.isMapAllowedYN = value;
+ }
+
+ /**
+ * Gets the value of the addAddressInDataYN property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getAddAddressInDataYN() {
+ return addAddressInDataYN;
+ }
+
+ /**
+ * Sets the value of the addAddressInDataYN property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setAddAddressInDataYN(String value) {
+ this.addAddressInDataYN = value;
+ }
+
+ /**
+ * Gets the value of the addressColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getAddressColumn() {
+ return addressColumn;
+ }
+
+ /**
+ * Sets the value of the addressColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setAddressColumn(String value) {
+ this.addressColumn = value;
+ }
+
+ /**
+ * Gets the value of the dataColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getDataColumn() {
+ return dataColumn;
+ }
+
+ /**
+ * Sets the value of the dataColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setDataColumn(String value) {
+ this.dataColumn = value;
+ }
+
+ /**
+ * Gets the value of the defaultMapType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getDefaultMapType() {
+ return defaultMapType;
+ }
+
+ /**
+ * Sets the value of the defaultMapType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setDefaultMapType(String value) {
+ this.defaultMapType = value;
+ }
+
+ /**
+ * Gets the value of the latColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getLatColumn() {
+ return latColumn;
+ }
+
+ /**
+ * Sets the value of the latColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setLatColumn(String value) {
+ this.latColumn = value;
+ }
+
+ /**
+ * Gets the value of the longColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getLongColumn() {
+ return longColumn;
+ }
+
+ /**
+ * Sets the value of the longColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setLongColumn(String value) {
+ this.longColumn = value;
+ }
+
+ /**
+ * Gets the value of the colorColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getColorColumn() {
+ return colorColumn;
+ }
+
+ /**
+ * Sets the value of the colorColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setColorColumn(String value) {
+ this.colorColumn = value;
+ }
+
+ /**
+ * Gets the value of the legendColumn property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getLegendColumn() {
+ return legendColumn;
+ }
+
+ /**
+ * Sets the value of the legendColumn property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setLegendColumn(String value) {
+ this.legendColumn = value;
+ }
+
+ /**
+ * Gets the value of the markers property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the markers property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getMarkers().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Marker }
+ *
+ *
+ */
+ public List<Marker> getMarkers() {
+ if (markers == null) {
+ markers = new ArrayList<Marker>();
+ }
+ return this.markers;
+ }
+
+}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java
index fdb833d0..fdb833d0 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/Reports.java
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java
index 12c426d4..215e3b41 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreList.java
@@ -29,7 +29,6 @@ package org.openecomp.portalsdk.analytics.xmlobj;
import java.util.ArrayList;
import java.util.List;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java
index 61323a58..61323a58 100644
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java
+++ b/ecomp-sdk/epsdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/SemaphoreType.java
diff --git a/ecomp-sdk/epsdk-app-common/.gitignore b/ecomp-sdk/epsdk-app-common/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-app-common/README.md b/ecomp-sdk/epsdk-app-common/README.md
new file mode 100644
index 00000000..c3a9fab9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/README.md
@@ -0,0 +1,31 @@
+# ECOMP SDK Web Application Common Files
+
+## Overview
+
+This is a Maven project with the ECOMP SDK classes that are used in the open-source version of the ECOMP SDK sample web
+application. Those specific versions are built using separate Maven projects.
+
+The java code depends on the following ECOMP SDK libraries that are developed
+by the ECOMP Portal team:
+
+* ECOMP SDK Framework library
+* ECOMP SDK Core library
+* ECOMP SDK Analytics library
+* ECOMP SDK Workflow library
+
+Use Apache Maven to build, package and deploy this webapp to a Maven repository.
+This project is not intended to be deployed to a web container like Tomcat.
+
+## Release Notes
+
+SDK is currently using AngularJS version 1.4.8 for compatibility with b2b library
+version 1.0.1. Note that previous versions of the EPSDK web application used
+AngularJS version 1.5.0.
+
+### OpenECOMP Distributions
+
+Version 1.1.0
+- [Portal-7] Improvements added as part of the rebasing process
+
+Version 1.0.0
+- Initial release
diff --git a/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDDLMySql_1707_Common.sql b/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDDLMySql_1707_Common.sql
new file mode 100644
index 00000000..ae534dd2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDDLMySql_1707_Common.sql
@@ -0,0 +1,1399 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This script creates tables in the 1707 COMMON version of the ECOMP SDK application database.
+-- Additional DDL scripts may be required!
+--
+-- Note to database admin: set the MySQL system variable called lower_case_table_names to 1
+-- It can be set 3 different ways:
+-- command-line options (Cmd-line),
+-- options valid in configuration files (Option file), or
+-- server system variables (System Var).
+--
+-- When set to 1 table names are stored in lowercase on disk and comparisons are not case sensitive.
+--
+-- MySql/MariaDB Version compatibility information
+--
+-- bash-4.2$ mysql --version – cluster version
+-- mysql Ver 15.1 Distrib 10.1.17-MariaDB, for Linux (x86_64) using readline 5.1
+--
+-- All versions newer or older than these DO NOT necessarily mean they are compatible.
+-- ---------------------------------------------------------------------------------------------------------------
+
+SET FOREIGN_KEY_CHECKS=1;
+
+CREATE DATABASE IF NOT EXISTS ecomp_sdk;
+
+USE ecomp_sdk;
+
+-- ---------- create table SECTION
+--
+-- NAME: CR_FAVORITE_REPORTS; TYPE: TABLE
+--
+create table cr_favorite_reports (
+ USER_ID INTEGER NOT NULL,
+ REP_ID INTEGER NOT NULL
+);
+
+--
+-- NAME: CR_FILEHIST_LOG; TYPE: TABLE
+--
+create table cr_filehist_log (
+ SCHEDULE_ID NUMERIC(11,0) NOT NULL,
+ URL CHARACTER VARYING(4000),
+ NOTES CHARACTER VARYING(3500),
+ RUN_TIME TIMESTAMP
+);
+
+--
+-- NAME: CR_FOLDER; TYPE: TABLE
+--
+create table cr_folder (
+ FOLDER_ID INTEGER NOT NULL,
+ FOLDER_NAME CHARACTER VARYING(50) NOT NULL,
+ DESCR CHARACTER VARYING(500),
+ CREATE_ID INTEGER NOT NULL,
+ CREATE_DATE TIMESTAMP NOT NULL,
+ PARENT_FOLDER_ID INTEGER,
+ PUBLIC_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
+);
+
+--
+-- NAME: CR_FOLDER_ACCESS; TYPE: TABLE
+--
+create table cr_folder_access (
+ FOLDER_ACCESS_ID NUMERIC(11,0) NOT NULL,
+ FOLDER_ID NUMERIC(11,0) NOT NULL,
+ ORDER_NO NUMERIC(11,0) NOT NULL,
+ ROLE_ID NUMERIC(11,0),
+ USER_ID NUMERIC(11,0),
+ READ_ONLY_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
+);
+
+--
+-- NAME: CR_HIST_USER_MAP; TYPE: TABLE
+--
+create table cr_hist_user_map (
+ HIST_ID INT(11) NOT NULL,
+ USER_ID INT(11) NOT NULL
+);
+
+--
+-- NAME: CR_LU_FILE_TYPE; TYPE: TABLE
+--
+create table cr_lu_file_type (
+ LOOKUP_ID NUMERIC(2,0) NOT NULL,
+ LOOKUP_DESCR CHARACTER VARYING(255) NOT NULL,
+ ACTIVE_YN CHARACTER(1) DEFAULT 'Y',
+ ERROR_CODE NUMERIC(11,0)
+);
+
+--
+-- NAME: CR_RAPTOR_ACTION_IMG; TYPE: TABLE
+--
+create table cr_raptor_action_img (
+ IMAGE_ID CHARACTER VARYING(100) NOT NULL,
+ IMAGE_LOC CHARACTER VARYING(400)
+);
+
+--
+-- NAME: CR_RAPTOR_PDF_IMG; TYPE: TABLE
+--
+create table cr_raptor_pdf_img (
+ IMAGE_ID CHARACTER VARYING(100) NOT NULL,
+ IMAGE_LOC CHARACTER VARYING(400)
+);
+
+--
+-- NAME: CR_REMOTE_SCHEMA_INFO; TYPE: TABLE
+--
+create table cr_remote_schema_info (
+ SCHEMA_PREFIX CHARACTER VARYING(5) NOT NULL,
+ SCHEMA_DESC CHARACTER VARYING(75) NOT NULL,
+ DATASOURCE_TYPE CHARACTER VARYING(100)
+);
+
+--
+-- NAME: CR_REPORT; TYPE: TABLE
+--
+create table cr_report (
+ REP_ID NUMERIC(11,0) NOT NULL,
+ TITLE CHARACTER VARYING(100) NOT NULL,
+ DESCR CHARACTER VARYING(255),
+ PUBLIC_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
+ REPORT_XML TEXT,
+ CREATE_ID NUMERIC(11,0),
+ CREATE_DATE TIMESTAMP default now(),
+ MAINT_ID NUMERIC(11,0),
+ MAINT_DATE TIMESTAMP DEFAULT NOW(),
+ MENU_ID CHARACTER VARYING(500),
+ MENU_APPROVED_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
+ OWNER_ID NUMERIC(11,0),
+ FOLDER_ID INTEGER DEFAULT 0,
+ DASHBOARD_TYPE_YN CHARACTER VARYING(1) DEFAULT 'N',
+ DASHBOARD_YN CHARACTER VARYING(1) DEFAULT 'N'
+);
+
+--
+-- NAME: CR_REPORT_ACCESS; TYPE: TABLE
+--
+create table cr_report_access (
+ REP_ID NUMERIC(11,0) NOT NULL,
+ ORDER_NO NUMERIC(11,0) NOT NULL,
+ ROLE_ID NUMERIC(11,0),
+ USER_ID NUMERIC(11,0),
+ READ_ONLY_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
+);
+
+--
+-- NAME: CR_REPORT_DWNLD_LOG; TYPE: TABLE
+--
+create table cr_report_dwnld_log (
+ USER_ID NUMERIC(11,0) NOT NULL,
+ REP_ID INTEGER NOT NULL,
+ FILE_NAME CHARACTER VARYING(100) NOT NULL,
+ DWNLD_START_TIME TIMESTAMP DEFAULT NOW() NOT NULL,
+ RECORD_READY_TIME TIMESTAMP DEFAULT NOW(),
+ FILTER_PARAMS CHARACTER VARYING(2000)
+);
+
+--
+-- NAME: CR_REPORT_EMAIL_SENT_LOG; TYPE: TABLE
+--
+create table cr_report_email_sent_log (
+ LOG_ID INTEGER NOT NULL,
+ SCHEDULE_ID NUMERIC(11,0),
+ GEN_KEY CHARACTER VARYING(25) NOT NULL,
+ REP_ID NUMERIC(11,0) NOT NULL,
+ USER_ID NUMERIC(11,0),
+ SENT_DATE TIMESTAMP DEFAULT NOW(),
+ ACCESS_FLAG CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
+ TOUCH_DATE TIMESTAMP DEFAULT NOW()
+);
+
+--
+-- NAME: CR_REPORT_FILE_HISTORY; TYPE: TABLE
+--
+create table cr_report_file_history (
+ HIST_ID INT(11) NOT NULL,
+ SCHED_USER_ID NUMERIC(11,0) NOT NULL,
+ SCHEDULE_ID NUMERIC(11,0) NOT NULL,
+ USER_ID NUMERIC(11,0) NOT NULL,
+ REP_ID NUMERIC(11,0),
+ RUN_DATE TIMESTAMP,
+ RECURRENCE CHARACTER VARYING(50),
+ FILE_TYPE_ID NUMERIC(2,0),
+ FILE_NAME CHARACTER VARYING(80),
+ FILE_BLOB BLOB,
+ FILE_SIZE NUMERIC(11,0),
+ RAPTOR_URL CHARACTER VARYING(4000),
+ ERROR_YN CHARACTER(1) DEFAULT 'N',
+ ERROR_CODE NUMERIC(11,0),
+ DELETED_YN CHARACTER(1) DEFAULT 'N',
+ DELETED_BY NUMERIC(38,0)
+);
+
+--
+-- NAME: CR_REPORT_LOG; TYPE: TABLE
+--
+create table cr_report_log (
+ REP_ID NUMERIC(11,0) NOT NULL,
+ LOG_TIME TIMESTAMP NOT NULL,
+ USER_ID NUMERIC(11,0) NOT NULL,
+ ACTION CHARACTER VARYING(2000) NOT NULL,
+ ACTION_VALUE CHARACTER VARYING(50),
+ FORM_FIELDS CHARACTER VARYING(4000)
+);
+
+--
+-- NAME: CR_REPORT_SCHEDULE; TYPE: TABLE
+--
+create table cr_report_schedule (
+ SCHEDULE_ID NUMERIC(11,0) NOT NULL,
+ SCHED_USER_ID NUMERIC(11,0) NOT NULL,
+ REP_ID NUMERIC(11,0) NOT NULL,
+ ENABLED_YN CHARACTER VARYING(1) NOT NULL,
+ START_DATE TIMESTAMP DEFAULT NOW(),
+ END_DATE TIMESTAMP DEFAULT NOW(),
+ RUN_DATE TIMESTAMP DEFAULT NOW(),
+ RECURRENCE CHARACTER VARYING(50),
+ CONDITIONAL_YN CHARACTER VARYING(1) NOT NULL,
+ CONDITION_SQL CHARACTER VARYING(4000),
+ NOTIFY_TYPE INTEGER DEFAULT 0,
+ MAX_ROW INTEGER DEFAULT 1000,
+ INITIAL_FORMFIELDS CHARACTER VARYING(3500),
+ PROCESSED_FORMFIELDS CHARACTER VARYING(3500),
+ FORMFIELDS CHARACTER VARYING(3500),
+ CONDITION_LARGE_SQL TEXT,
+ ENCRYPT_YN CHARACTER(1) DEFAULT 'N',
+ ATTACHMENT_YN CHARACTER(1) DEFAULT 'Y'
+);
+
+--
+-- NAME: CR_REPORT_SCHEDULE_USERS; TYPE: TABLE
+--
+create table cr_report_schedule_users (
+ SCHEDULE_ID NUMERIC(11,0) NOT NULL,
+ REP_ID NUMERIC(11,0) NOT NULL,
+ USER_ID NUMERIC(11,0) NOT NULL,
+ ROLE_ID NUMERIC(11,0),
+ ORDER_NO NUMERIC(11,0) NOT NULL
+);
+
+--
+-- NAME: CR_REPORT_TEMPLATE_MAP; TYPE: TABLE
+--
+create table cr_report_template_map (
+ REPORT_ID INTEGER NOT NULL,
+ TEMPLATE_FILE CHARACTER VARYING(200)
+);
+
+--
+-- NAME: CR_SCHEDULE_ACTIVITY_LOG; TYPE: TABLE
+--
+create table cr_schedule_activity_log (
+ SCHEDULE_ID NUMERIC(11,0) NOT NULL,
+ URL CHARACTER VARYING(4000),
+ NOTES CHARACTER VARYING(2000),
+ RUN_TIME TIMESTAMP
+);
+
+--
+-- NAME: CR_TABLE_JOIN; TYPE: TABLE
+--
+create table cr_table_join (
+ SRC_TABLE_NAME CHARACTER VARYING(30) NOT NULL,
+ DEST_TABLE_NAME CHARACTER VARYING(30) NOT NULL,
+ JOIN_EXPR CHARACTER VARYING(500) NOT NULL
+);
+
+--
+-- NAME: CR_TABLE_ROLE; TYPE: TABLE
+--
+create table cr_table_role (
+ TABLE_NAME CHARACTER VARYING(30) NOT NULL,
+ ROLE_ID NUMERIC(11,0) NOT NULL
+);
+
+--
+-- NAME: CR_TABLE_SOURCE; TYPE: TABLE
+--
+create table cr_table_source (
+ TABLE_NAME CHARACTER VARYING(30) NOT NULL,
+ DISPLAY_NAME CHARACTER VARYING(30) NOT NULL,
+ PK_FIELDS CHARACTER VARYING(200),
+ WEB_VIEW_ACTION CHARACTER VARYING(50),
+ LARGE_DATA_SOURCE_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
+ FILTER_SQL CHARACTER VARYING(4000),
+ SOURCE_DB CHARACTER VARYING(50)
+);
+
+--
+-- NAME: FN_LU_TIMEZONE; TYPE: TABLE
+--
+create table fn_lu_timezone (
+ TIMEZONE_ID INT(11) NOT NULL,
+ TIMEZONE_NAME CHARACTER VARYING(100) NOT NULL,
+ TIMEZONE_VALUE CHARACTER VARYING(100) NOT NULL
+);
+
+create table fn_user (
+ USER_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ ORG_ID INT(11),
+ MANAGER_ID INT(11),
+ FIRST_NAME CHARACTER VARYING(50),
+ MIDDLE_NAME CHARACTER VARYING(50),
+ LAST_NAME CHARACTER VARYING(50),
+ PHONE CHARACTER VARYING(25),
+ FAX CHARACTER VARYING(25),
+ CELLULAR CHARACTER VARYING(25),
+ EMAIL CHARACTER VARYING(50),
+ ADDRESS_ID NUMERIC(11,0),
+ ALERT_METHOD_CD CHARACTER VARYING(10),
+ HRID CHARACTER VARYING(20),
+ ORG_USER_ID CHARACTER VARYING(20),
+ ORG_CODE CHARACTER VARYING(30),
+ LOGIN_ID CHARACTER VARYING(25),
+ LOGIN_PWD CHARACTER VARYING(25),
+ LAST_LOGIN_DATE TIMESTAMP,
+ ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
+ CREATED_ID INT(11),
+ CREATED_DATE TIMESTAMP DEFAULT NOW(),
+ MODIFIED_ID INT(11),
+ MODIFIED_DATE TIMESTAMP default now(),
+ IS_INTERNAL_YN CHARACTER(1) DEFAULT 'N' NOT NULL,
+ ADDRESS_LINE_1 CHARACTER VARYING(100),
+ ADDRESS_LINE_2 CHARACTER VARYING(100),
+ CITY CHARACTER VARYING(50),
+ STATE_CD CHARACTER VARYING(3),
+ ZIP_CODE CHARACTER VARYING(11),
+ COUNTRY_CD CHARACTER VARYING(3),
+ LOCATION_CLLI CHARACTER VARYING(8),
+ ORG_MANAGER_USERID CHARACTER VARYING(20),
+ COMPANY CHARACTER VARYING(100),
+ DEPARTMENT_NAME CHARACTER VARYING(100),
+ JOB_TITLE CHARACTER VARYING(100),
+ TIMEZONE INT(11),
+ DEPARTMENT CHARACTER VARYING(25),
+ BUSINESS_UNIT CHARACTER VARYING(25),
+ BUSINESS_UNIT_NAME CHARACTER VARYING(100),
+ COST_CENTER CHARACTER VARYING(25),
+ FIN_LOC_CODE CHARACTER VARYING(10),
+ SILO_STATUS CHARACTER VARYING(10)
+);
+
+--
+-- NAME: FN_ROLE; TYPE: TABLE
+--
+create table fn_role (
+ ROLE_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ ROLE_NAME CHARACTER VARYING(50) NOT NULL,
+ ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
+ PRIORITY NUMERIC(4,0)
+);
+
+--
+-- NAME: FN_AUDIT_ACTION; TYPE: TABLE
+--
+create table fn_audit_action (
+ AUDIT_ACTION_ID INTEGER NOT NULL,
+ CLASS_NAME CHARACTER VARYING(500) NOT NULL,
+ METHOD_NAME CHARACTER VARYING(50) NOT NULL,
+ AUDIT_ACTION_CD CHARACTER VARYING(20) NOT NULL,
+ AUDIT_ACTION_DESC CHARACTER VARYING(200),
+ ACTIVE_YN CHARACTER VARYING(1)
+);
+
+--
+-- NAME: FN_AUDIT_ACTION_LOG; TYPE: TABLE
+--
+create table fn_audit_action_log (
+ AUDIT_LOG_ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ AUDIT_ACTION_CD CHARACTER VARYING(200),
+ ACTION_TIME TIMESTAMP,
+ USER_ID NUMERIC(11,0),
+ CLASS_NAME CHARACTER VARYING(100),
+ METHOD_NAME CHARACTER VARYING(50),
+ SUCCESS_MSG CHARACTER VARYING(20),
+ ERROR_MSG CHARACTER VARYING(500)
+);
+
+--
+-- NAME: FN_LU_ACTIVITY; TYPE: TABLE
+--
+create table fn_lu_activity (
+ ACTIVITY_CD CHARACTER VARYING(50) NOT NULL PRIMARY KEY,
+ ACTIVITY CHARACTER VARYING(50) NOT NULL
+);
+
+--
+-- NAME: FN_AUDIT_LOG; TYPE: TABLE
+--
+create table fn_audit_log (
+ LOG_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ USER_ID INT(11) NOT NULL,
+ ACTIVITY_CD CHARACTER VARYING(50) NOT NULL,
+ AUDIT_DATE TIMESTAMP DEFAULT NOW() NOT NULL,
+ COMMENTS CHARACTER VARYING(1000),
+ AFFECTED_RECORD_ID_BK CHARACTER VARYING(500),
+ AFFECTED_RECORD_ID CHARACTER VARYING(4000),
+ CONSTRAINT FK_FN_AUDIT_REF_209_FN_USER FOREIGN KEY (USER_ID) REFERENCES FN_USER(USER_ID)
+);
+
+--
+-- NAME: FN_BROADCAST_MESSAGE; TYPE: TABLE
+--
+create table fn_broadcast_message (
+ MESSAGE_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ MESSAGE_TEXT CHARACTER VARYING(1000) NOT NULL,
+ MESSAGE_LOCATION_ID NUMERIC(11,0) NOT NULL,
+ BROADCAST_START_DATE TIMESTAMP NOT NULL DEFAULT NOW(),
+ BROADCAST_END_DATE TIMESTAMP NOT NULL DEFAULT NOW(),
+ ACTIVE_YN CHARACTER(1) DEFAULT 'Y' NOT NULL,
+ SORT_ORDER NUMERIC(4,0) NOT NULL,
+ BROADCAST_SITE_CD CHARACTER VARYING(50)
+);
+
+--
+-- NAME: FN_CHAT_LOGS; TYPE: TABLE
+--
+create table fn_chat_logs (
+ CHAT_LOG_ID INTEGER NOT NULL,
+ CHAT_ROOM_ID INTEGER,
+ USER_ID INTEGER,
+ MESSAGE CHARACTER VARYING(1000),
+ MESSAGE_DATE_TIME TIMESTAMP
+);
+
+--
+-- NAME: FN_CHAT_ROOM; TYPE: TABLE
+--
+create table fn_chat_room (
+ CHAT_ROOM_ID INTEGER NOT NULL,
+ NAME CHARACTER VARYING(50) NOT NULL,
+ DESCRIPTION CHARACTER VARYING(500),
+ OWNER_ID INTEGER,
+ CREATED_DATE TIMESTAMP DEFAULT NOW(),
+ UPDATED_DATE TIMESTAMP DEFAULT NOW()
+);
+
+--
+-- NAME: FN_CHAT_USERS; TYPE: TABLE
+--
+create table fn_chat_users (
+ CHAT_ROOM_ID INTEGER,
+ USER_ID INTEGER,
+ LAST_ACTIVITY_DATE_TIME TIMESTAMP,
+ CHAT_STATUS CHARACTER VARYING(20),
+ ID INTEGER NOT NULL
+);
+
+--
+-- NAME: FN_DATASOURCE; TYPE: TABLE
+--
+create table fn_datasource (
+ ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ NAME CHARACTER VARYING(50),
+ DRIVER_NAME CHARACTER VARYING(256),
+ SERVER CHARACTER VARYING(256),
+ PORT INTEGER,
+ USER_NAME CHARACTER VARYING(256),
+ PASSWORD CHARACTER VARYING(256),
+ URL CHARACTER VARYING(256),
+ MIN_POOL_SIZE INTEGER,
+ MAX_POOL_SIZE INTEGER,
+ ADAPTER_ID INTEGER,
+ DS_TYPE CHARACTER VARYING(20)
+);
+
+--
+-- NAME: FN_FUNCTION; TYPE: TABLE
+--
+create table fn_function (
+ FUNCTION_CD CHARACTER VARYING(30) NOT NULL PRIMARY KEY,
+ FUNCTION_NAME CHARACTER VARYING(50) NOT NULL
+);
+
+--
+-- NAME: FN_LU_ALERT_METHOD; TYPE: TABLE
+--
+create table fn_lu_alert_method (
+ ALERT_METHOD_CD CHARACTER VARYING(10) NOT NULL,
+ ALERT_METHOD CHARACTER VARYING(50) NOT NULL
+);
+
+--
+-- NAME: FN_LU_BROADCAST_SITE; TYPE: TABLE
+--
+create table fn_lu_broadcast_site (
+ BROADCAST_SITE_CD CHARACTER VARYING(50) NOT NULL,
+ BROADCAST_SITE_DESCR CHARACTER VARYING(100)
+);
+--
+-- NAME: FN_LU_MENU_SET; TYPE: TABLE
+--
+create table fn_lu_menu_set (
+ MENU_SET_CD CHARACTER VARYING(10) NOT NULL PRIMARY KEY,
+ MENU_SET_NAME CHARACTER VARYING(50) NOT NULL
+);
+
+--
+-- NAME: FN_LU_PRIORITY; TYPE: TABLE
+--
+create table fn_lu_priority (
+ PRIORITY_ID NUMERIC(11,0) NOT NULL,
+ PRIORITY CHARACTER VARYING(50) NOT NULL,
+ ACTIVE_YN CHARACTER(1) NOT NULL,
+ SORT_ORDER NUMERIC(5,0)
+);
+
+--
+-- NAME: FN_LU_ROLE_TYPE; TYPE: TABLE
+--
+create table fn_lu_role_type (
+ ROLE_TYPE_ID NUMERIC(11,0) NOT NULL,
+ ROLE_TYPE CHARACTER VARYING(50) NOT NULL
+);
+--
+-- NAME: FN_LU_TAB_SET; TYPE: TABLE
+--
+create table fn_lu_tab_set (
+ TAB_SET_CD CHARACTER VARYING(30) NOT NULL,
+ TAB_SET_NAME CHARACTER VARYING(50) NOT NULL
+);
+
+--
+-- NAME: FN_MENU; TYPE: TABLE
+--
+create table fn_menu (
+ MENU_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ LABEL CHARACTER VARYING(100),
+ PARENT_ID INT(11),
+ SORT_ORDER NUMERIC(4,0),
+ ACTION CHARACTER VARYING(200),
+ FUNCTION_CD CHARACTER VARYING(30),
+ ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
+ SERVLET CHARACTER VARYING(50),
+ QUERY_STRING CHARACTER VARYING(200),
+ EXTERNAL_URL CHARACTER VARYING(200),
+ TARGET CHARACTER VARYING(25),
+ MENU_SET_CD CHARACTER VARYING(10) DEFAULT 'APP',
+ SEPARATOR_YN CHARACTER(1) DEFAULT 'N',
+ IMAGE_SRC CHARACTER VARYING(100),
+ CONSTRAINT FK_FN_MENU_REF_196_FN_MENU FOREIGN KEY (PARENT_ID) REFERENCES FN_MENU(MENU_ID),
+ CONSTRAINT FK_FN_MENU_MENU_SET_CD FOREIGN KEY (MENU_SET_CD) REFERENCES FN_LU_MENU_SET(MENU_SET_CD),
+ CONSTRAINT FK_FN_MENU_REF_223_FN_FUNCT FOREIGN KEY (FUNCTION_CD) REFERENCES FN_FUNCTION(FUNCTION_CD)
+);
+
+--
+-- NAME: FN_ORG; TYPE: TABLE
+--
+create table fn_org (
+ ORG_ID INT(11) NOT NULL,
+ ORG_NAME CHARACTER VARYING(50) NOT NULL,
+ ACCESS_CD CHARACTER VARYING(10)
+);
+
+--
+-- NAME: FN_RESTRICTED_URL; TYPE: TABLE
+--
+create table fn_restricted_url (
+ RESTRICTED_URL CHARACTER VARYING(250) NOT NULL,
+ FUNCTION_CD CHARACTER VARYING(30) NOT NULL
+);
+
+--
+-- NAME: FN_ROLE_COMPOSITE; TYPE: TABLE
+--
+create table fn_role_composite (
+ PARENT_ROLE_ID INT(11) NOT NULL,
+ CHILD_ROLE_ID INT(11) NOT NULL,
+ CONSTRAINT FK_FN_ROLE_COMPOSITE_CHILD FOREIGN KEY (CHILD_ROLE_ID) REFERENCES FN_ROLE(ROLE_ID),
+ CONSTRAINT FK_FN_ROLE_COMPOSITE_PARENT FOREIGN KEY (PARENT_ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
+);
+
+--
+-- NAME: FN_ROLE_FUNCTION; TYPE: TABLE
+--
+create table fn_role_function (
+ ROLE_ID INT(11) NOT NULL,
+ FUNCTION_CD CHARACTER VARYING(30) NOT NULL,
+ CONSTRAINT FK_FN_ROLE__REF_198_FN_ROLE FOREIGN KEY (ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
+);
+
+--
+-- NAME: FN_TAB; TYPE: TABLE
+--
+create table fn_tab (
+ TAB_CD CHARACTER VARYING(30) NOT NULL,
+ TAB_NAME CHARACTER VARYING(50) NOT NULL,
+ TAB_DESCR CHARACTER VARYING(100),
+ ACTION CHARACTER VARYING(100) NOT NULL,
+ FUNCTION_CD CHARACTER VARYING(30) NOT NULL,
+ ACTIVE_YN CHARACTER(1) NOT NULL,
+ SORT_ORDER NUMERIC(11,0) NOT NULL,
+ PARENT_TAB_CD CHARACTER VARYING(30),
+ TAB_SET_CD CHARACTER VARYING(30)
+);
+
+--
+-- NAME: FN_TAB_SELECTED; TYPE: TABLE
+--
+create table fn_tab_selected (
+ SELECTED_TAB_CD CHARACTER VARYING(30) NOT NULL,
+ TAB_URI CHARACTER VARYING(40) NOT NULL
+);
+
+--
+-- NAME: FN_USER_PSEUDO_ROLE; TYPE: TABLE
+--
+create table fn_user_pseudo_role (
+ PSEUDO_ROLE_ID INT(11) NOT NULL,
+ USER_ID INT(11) NOT NULL
+);
+
+--
+-- NAME: FN_USER_ROLE; TYPE: TABLE
+--
+create table fn_user_role (
+ USER_ID INT(10) NOT NULL,
+ ROLE_ID INT(10) NOT NULL,
+ PRIORITY NUMERIC(4,0),
+ APP_ID INT(11) DEFAULT 1,
+ CONSTRAINT FK_FN_USER__REF_172_FN_USER FOREIGN KEY (USER_ID) REFERENCES FN_USER(USER_ID),
+ CONSTRAINT FK_FN_USER__REF_175_FN_ROLE FOREIGN KEY (ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
+);
+--
+-- NAME: SCHEMA_INFO; TYPE: TABLE
+--
+create table schema_info (
+ SCHEMA_ID CHARACTER VARYING(25) NOT NULL,
+ SCHEMA_DESC CHARACTER VARYING(75) NOT NULL,
+ DATASOURCE_TYPE CHARACTER VARYING(100),
+ CONNECTION_URL VARCHAR(200) NOT NULL,
+ USER_NAME VARCHAR(45) NOT NULL,
+ PASSWORD VARCHAR(45) NULL DEFAULT NULL,
+ DRIVER_CLASS VARCHAR(100) NOT NULL,
+ MIN_POOL_SIZE INT NOT NULL,
+ MAX_POOL_SIZE INT NOT NULL,
+ IDLE_CONNECTION_TEST_PERIOD INT NOT NULL
+
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_APP; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_app (
+ APP_ID int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ APP_NAME varchar(100) NOT NULL DEFAULT '?',
+ APP_IMAGE_URL varchar(256) DEFAULT NULL,
+ APP_DESCRIPTION varchar(512) DEFAULT NULL,
+ APP_NOTES varchar(4096) DEFAULT NULL,
+ APP_URL varchar(256) DEFAULT NULL,
+ APP_ALTERNATE_URL varchar(256) DEFAULT NULL,
+ APP_REST_ENDPOINT varchar(2000) DEFAULT NULL,
+ ML_APP_NAME varchar(50) NOT NULL DEFAULT '?',
+ ML_APP_ADMIN_ID varchar(7) NOT NULL DEFAULT '?',
+ MOTS_ID int(11) DEFAULT NULL,
+ APP_PASSWORD varchar(256) NOT NULL DEFAULT '?',
+ OPEN char(1) DEFAULT 'N',
+ ENABLED char(1) DEFAULT 'Y',
+ THUMBNAIL mediumblob,
+ APP_USERNAME varchar(50),
+ UEB_KEY VARCHAR(256) DEFAULT NULL,
+ UEB_SECRET VARCHAR(256) DEFAULT NULL,
+ UEB_TOPIC_NAME VARCHAR(256) DEFAULT NULL
+
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_FN_WORKFLOW; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_workflow (
+ id mediumint(9) NOT NULL AUTO_INCREMENT,
+ name varchar(20) NOT NULL,
+ description varchar(500) DEFAULT NULL,
+ run_link varchar(300) DEFAULT NULL,
+ suspend_link varchar(300) DEFAULT NULL,
+ modified_link varchar(300) DEFAULT NULL,
+ active_yn varchar(300) DEFAULT NULL,
+ created varchar(300) DEFAULT NULL,
+ created_by int(11) DEFAULT NULL,
+ modified varchar(300) DEFAULT NULL,
+ modified_by int(11) DEFAULT NULL,
+ workflow_key varchar(50) DEFAULT NULL,
+ PRIMARY KEY (id),
+ UNIQUE KEY name (name)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_SCHEDULE_WORKFLOWS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_schedule_workflows (
+ id_schedule_workflows bigint(25) PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ workflow_server_url varchar(45) DEFAULT NULL,
+ workflow_key varchar(45) NOT NULL,
+ workflow_arguments varchar(45) DEFAULT NULL,
+ startDateTimeCron varchar(45) DEFAULT NULL,
+ endDateTime TIMESTAMP DEFAULT NOW(),
+ start_date_time TIMESTAMP DEFAULT NOW(),
+ recurrence varchar(45) DEFAULT NULL
+ );
+
+-- For demo reporting application add : demo_bar_chart, demo_bar_chart_inter, demo_line_chart, demo_pie_chart and demo_util_chart
+-- demo_scatter_chart, demo_scatter_plot
+-- ----------------------------------------------------------
+-- NAME: DEMO_BAR_CHART; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_bar_chart (
+ label varchar(20),
+ value numeric(25,15)
+ );
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_BAR_CHART_INTER; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_bar_chart_inter (
+ spam_date date,
+ num_rpt_sources numeric(10,0),
+ num_det_sources numeric(10,0)
+ );
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_LINE_CHART; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_line_chart (
+ series varchar(20),
+ log_date date,
+ data_value numeric(10,5)
+ );
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_PIE_CHART; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_pie_chart (
+ legend varchar(20),
+ data_value numeric(10,5)
+ );
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_UTIL_CHART; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_util_chart (
+ traffic_date date,
+ util_perc numeric(10,5)
+ );
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_SCATTER_CHART; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_scatter_chart (
+ rainfall numeric(10,2),
+ key_value varchar(20),
+ measurements numeric(10,2)
+);
+
+-- ----------------------------------------------------------
+-- NAME: DEMO_SCATTER_PLOT; TYPE: TABLE
+-- ----------------------------------------------------------
+create table demo_scatter_plot
+(
+ SERIES VARCHAR(20),
+ VALUEX numeric(25,15),
+ VALUEY numeric(25,15)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_JOB_DETAILS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_job_details (
+SCHED_NAME VARCHAR(120) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+JOB_CLASS_NAME VARCHAR(250) NOT NULL,
+IS_DURABLE VARCHAR(1) NOT NULL,
+IS_NONCONCURRENT VARCHAR(1) NOT NULL,
+IS_UPDATE_DATA VARCHAR(1) NOT NULL,
+REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_triggers (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+NEXT_FIRE_TIME BIGINT(13) NULL,
+PREV_FIRE_TIME BIGINT(13) NULL,
+PRIORITY INTEGER NULL,
+TRIGGER_STATE VARCHAR(16) NOT NULL,
+TRIGGER_TYPE VARCHAR(8) NOT NULL,
+START_TIME BIGINT(13) NOT NULL,
+END_TIME BIGINT(13) NULL,
+CALENDAR_NAME VARCHAR(200) NULL,
+MISFIRE_INSTR SMALLINT(2) NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+REFERENCES FN_QZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_SIMPLE_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_simple_triggers (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+REPEAT_COUNT BIGINT(7) NOT NULL,
+REPEAT_INTERVAL BIGINT(12) NOT NULL,
+TIMES_TRIGGERED BIGINT(10) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_CRON_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_cron_triggers (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+CRON_EXPRESSION VARCHAR(120) NOT NULL,
+TIME_ZONE_ID VARCHAR(80),
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_SIMPROP_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_simprop_triggers
+ (
+ SCHED_NAME VARCHAR(120) NOT NULL,
+ TRIGGER_NAME VARCHAR(200) NOT NULL,
+ TRIGGER_GROUP VARCHAR(200) NOT NULL,
+ STR_PROP_1 VARCHAR(512) NULL,
+ STR_PROP_2 VARCHAR(512) NULL,
+ STR_PROP_3 VARCHAR(512) NULL,
+ INT_PROP_1 INT NULL,
+ INT_PROP_2 INT NULL,
+ LONG_PROP_1 BIGINT NULL,
+ LONG_PROP_2 BIGINT NULL,
+ DEC_PROP_1 NUMERIC(13,4) NULL,
+ DEC_PROP_2 NUMERIC(13,4) NULL,
+ BOOL_PROP_1 VARCHAR(1) NULL,
+ BOOL_PROP_2 VARCHAR(1) NULL,
+ PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+ FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+ REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_BLOB_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_blob_triggers (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+BLOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_CALENDARS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_calendars (
+SCHED_NAME VARCHAR(120) NOT NULL,
+CALENDAR_NAME VARCHAR(200) NOT NULL,
+CALENDAR BLOB NOT NULL,
+PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_PAUSED_TRIGGER_GRPS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_paused_trigger_grps (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_FIRED_TRIGGERS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_fired_triggers (
+SCHED_NAME VARCHAR(120) NOT NULL,
+ENTRY_ID VARCHAR(95) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+FIRED_TIME BIGINT(13) NOT NULL,
+SCHED_TIME BIGINT(13) NOT NULL,
+PRIORITY INTEGER NOT NULL,
+STATE VARCHAR(16) NOT NULL,
+JOB_NAME VARCHAR(200) NULL,
+JOB_GROUP VARCHAR(200) NULL,
+IS_NONCONCURRENT VARCHAR(1) NULL,
+REQUESTS_RECOVERY VARCHAR(1) NULL,
+PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_SCHEDULER_STATE; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_scheduler_state (
+SCHED_NAME VARCHAR(120) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
+CHECKIN_INTERVAL BIGINT(13) NOT NULL,
+PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+
+-- ----------------------------------------------------------
+-- NAME: FN_QZ_LOCKS; TYPE: TABLE
+-- ----------------------------------------------------------
+create table fn_qz_locks (
+SCHED_NAME VARCHAR(120) NOT NULL,
+LOCK_NAME VARCHAR(40) NOT NULL,
+PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+
+--
+-- name: rcloudinvocation; type: table
+--
+create table rcloudinvocation (
+ id varchar(128) not null primary key,
+ created timestamp not null,
+ userinfo varchar(2048) not null,
+ notebookid varchar(128) not null,
+ parameters varchar(2048) default null,
+ tokenreaddate timestamp null
+);
+
+--
+-- name: rcloudnotebook; type: table
+--
+create table rcloudnotebook (
+ notebookname varchar(128) not null primary key,
+ notebookid varchar(128) not null
+);
+
+--
+-- Name: fn_lu_message_location; Type: TABLE
+--
+
+CREATE TABLE fn_lu_message_location (
+ message_location_id numeric(11,0) NOT NULL,
+ message_location_descr character varying(30) NOT NULL
+);
+
+-- ------------------ CREATE VIEW SECTION
+--
+-- NAME: V_URL_ACCESS; TYPE: VIEW
+--
+CREATE VIEW v_url_access AS
+ SELECT DISTINCT M.ACTION AS URL,
+ M.FUNCTION_CD
+ FROM FN_MENU M
+ WHERE (M.ACTION IS NOT NULL)
+UNION
+ SELECT DISTINCT T.ACTION AS URL,
+ T.FUNCTION_CD
+ FROM FN_TAB T
+ WHERE (T.ACTION IS NOT NULL)
+UNION
+ SELECT R.RESTRICTED_URL AS URL,
+ R.FUNCTION_CD
+ FROM FN_RESTRICTED_URL R;
+
+-- ------------------ ALTER TABLE ADD CONSTRAINT PRIMARY KEY SECTION
+--
+-- NAME: CR_FAVORITE_REPORTS_USER_IDREP_ID; TYPE: CONSTRAINT
+--
+alter table cr_favorite_reports
+ add constraint cr_favorite_reports_user_idrep_id primary key (user_id, rep_id);
+--
+-- NAME: CR_FOLDER_FOLDER_ID; TYPE: CONSTRAINT
+--
+alter table cr_folder
+ add constraint cr_folder_folder_id primary key (folder_id);
+--
+-- NAME: CR_FOLDER_ACCESS_FOLDER_ACCESS_ID; TYPE: CONSTRAINT
+--
+alter table cr_folder_access
+ add constraint cr_folder_access_folder_access_id primary key (folder_access_id);
+--
+-- NAME: CR_HIST_USER_MAP_HIST_IDUSER_ID; TYPE: CONSTRAINT
+--
+alter table cr_hist_user_map
+ add constraint cr_hist_user_map_hist_iduser_id primary key (hist_id, user_id);
+--
+-- NAME: CR_LU_FILE_TYPE_LOOKUP_ID; TYPE: CONSTRAINT
+--
+alter table cr_lu_file_type
+ add constraint cr_lu_file_type_lookup_id primary key (lookup_id);
+--
+-- NAME: CR_RAPTOR_ACTION_IMG_IMAGE_ID; TYPE: CONSTRAINT
+--
+alter table cr_raptor_action_img
+ add constraint cr_raptor_action_img_image_id primary key (image_id);
+--
+-- NAME: CR_RAPTOR_PDF_IMG_IMAGE_ID; TYPE: CONSTRAINT
+--
+alter table cr_raptor_pdf_img
+ add constraint cr_raptor_pdf_img_image_id primary key (image_id);
+--
+-- NAME: CR_REMOTE_SCHEMA_INFO_SCHEMA_PREFIX; TYPE: CONSTRAINT
+--
+alter table cr_remote_schema_info
+ add constraint cr_remote_schema_info_schema_prefix primary key (schema_prefix);
+--
+-- NAME: CR_REPORT_REP_ID; TYPE: CONSTRAINT
+--
+alter table cr_report
+ add constraint cr_report_rep_id primary key (rep_id);
+--
+-- NAME: CR_REPORT_ACCESS_REP_IDORDER_NO; TYPE: CONSTRAINT
+--
+alter table cr_report_access
+ add constraint cr_report_access_rep_idorder_no primary key (rep_id, order_no);
+--
+-- NAME: CR_REPORT_EMAIL_SENT_LOG_LOG_ID; TYPE: CONSTRAINT
+--
+alter table cr_report_email_sent_log
+ add constraint cr_report_email_sent_log_log_id primary key (log_id);
+--
+-- NAME: CR_REPORT_FILE_HISTORY_HIST_ID; TYPE: CONSTRAINT
+--
+alter table cr_report_file_history
+ add constraint cr_report_file_history_hist_id primary key (hist_id);
+--
+-- NAME: CR_REPORT_SCHEDULE_SCHEDULE_ID; TYPE: CONSTRAINT
+--
+alter table cr_report_schedule
+ add constraint cr_report_schedule_schedule_id primary key (schedule_id);
+--
+-- NAME: CR_REPORT_SCHEDULE_USERS_SCHEDULE_IDREP_IDUSER_IDORDER_NO; TYPE: CONSTRAINT
+--
+alter table cr_report_schedule_users
+ add constraint cr_report_schedule_users_schedule_idrep_iduser_idorder_no primary key (schedule_id, rep_id, user_id, order_no);
+--
+-- NAME: CR_REPORT_TEMPLATE_MAP_REPORT_ID; TYPE: CONSTRAINT
+--
+alter table cr_report_template_map
+ add constraint cr_report_template_map_report_id primary key (report_id);
+--
+-- NAME: CR_TABLE_ROLE_TABLE_NAMEROLE_ID; TYPE: CONSTRAINT
+--
+alter table cr_table_role
+ add constraint cr_table_role_table_namerole_id primary key (table_name, role_id);
+--
+-- NAME: CR_TABLE_SOURCE_TABLE_NAME; TYPE: CONSTRAINT
+--
+alter table cr_table_source
+ add constraint cr_table_source_table_name primary key (table_name);
+--
+-- NAME: FN_AUDIT_ACTION_AUDIT_ACTION_ID; TYPE: CONSTRAINT
+--
+alter table fn_audit_action
+ add constraint fn_audit_action_audit_action_id primary key (audit_action_id);
+--
+-- NAME: FN_CHAT_LOGS_CHAT_LOG_ID; TYPE: CONSTRAINT
+--
+alter table fn_chat_logs
+ add constraint fn_chat_logs_chat_log_id primary key (chat_log_id);
+--
+-- NAME: FN_CHAT_ROOM_CHAT_ROOM_ID; TYPE: CONSTRAINT
+--
+alter table fn_chat_room
+ add constraint fn_chat_room_chat_room_id primary key (chat_room_id);
+--
+-- NAME: FN_CHAT_USERS_ID; TYPE: CONSTRAINT
+--
+alter table fn_chat_users
+ add constraint fn_chat_users_id primary key (id);
+--
+-- NAME: FN_LU_ALERT_METHOD_ALERT_METHOD_CD; TYPE: CONSTRAINT
+--
+alter table fn_lu_alert_method
+ add constraint fn_lu_alert_method_alert_method_cd primary key (alert_method_cd);
+--
+-- NAME: FN_LU_BROADCAST_SITE_BROADCAST_SITE_CD; TYPE: CONSTRAINT
+--
+alter table fn_lu_broadcast_site
+ add constraint fn_lu_broadcast_site_broadcast_site_cd primary key (broadcast_site_cd);
+--
+-- NAME: FN_LU_PRIORITY_PRIORITY_ID; TYPE: CONSTRAINT
+--
+alter table fn_lu_priority
+ add constraint fn_lu_priority_priority_id primary key (priority_id);
+--
+-- NAME: FN_LU_ROLE_TYPE_ROLE_TYPE_ID; TYPE: CONSTRAINT
+--
+alter table fn_lu_role_type
+ add constraint fn_lu_role_type_role_type_id primary key (role_type_id);
+--
+-- NAME: FN_LU_TAB_SET_TAB_SET_CD; TYPE: CONSTRAINT
+--
+alter table fn_lu_tab_set
+ add constraint fn_lu_tab_set_tab_set_cd primary key (tab_set_cd);
+--
+-- NAME: FN_LU_TIMEZONE_TIMEZONE_ID; TYPE: CONSTRAINT
+--
+alter table fn_lu_timezone
+ add constraint fn_lu_timezone_timezone_id primary key (timezone_id);
+--
+-- NAME: FN_ORG_ORG_ID; TYPE: CONSTRAINT
+--
+alter table fn_org
+ add constraint fn_org_org_id primary key (org_id);
+--
+-- NAME: FN_RESTRICTED_URL_RESTRICTED_URLFUNCTION_CD; TYPE: CONSTRAINT
+--
+alter table fn_restricted_url
+ add constraint fn_restricted_url_restricted_urlfunction_cd primary key (restricted_url, function_cd);
+--
+-- NAME: FN_ROLE_COMPOSITE_PARENT_ROLE_IDCHILD_ROLE_ID; TYPE: CONSTRAINT
+--
+alter table fn_role_composite
+ add constraint fn_role_composite_parent_role_idchild_role_id primary key (parent_role_id, child_role_id);
+--
+-- NAME: FN_ROLE_FUNCTION_ROLE_IDFUNCTION_CD; TYPE: CONSTRAINT
+--
+alter table fn_role_function
+ add constraint fn_role_function_role_idfunction_cd primary key (role_id, function_cd);
+--
+-- NAME: FN_TAB_TAB_CD; TYPE: CONSTRAINT
+--
+alter table fn_tab
+ add constraint fn_tab_tab_cd primary key (tab_cd);
+--
+-- NAME: FN_TAB_SELECTED_SELECTED_TAB_CDTAB_URI; TYPE: CONSTRAINT
+--
+alter table fn_tab_selected
+ add constraint fn_tab_selected_selected_tab_cdtab_uri primary key (selected_tab_cd, tab_uri);
+--
+-- NAME: FN_USER_PSEUDO_ROLE_PSEUDO_ROLE_IDUSER_ID; TYPE: CONSTRAINT
+--
+alter table fn_user_pseudo_role
+ add constraint fn_user_pseudo_role_pseudo_role_iduser_id primary key (pseudo_role_id, user_id);
+--
+-- NAME: FN_USER_ROLE_USER_IDROLE_ID; TYPE: CONSTRAINT
+--
+alter table fn_user_role
+ add constraint fn_user_role_user_idrole_id primary key (user_id, role_id, app_id);
+--
+-- Name: fn_lu_message_location_MESSAGE_LOCATION_ID; Type: CONSTRAINT
+--
+
+ALTER TABLE fn_lu_message_location
+ ADD CONSTRAINT fn_lu_message_location_MESSAGE_LOCATION_ID PRIMARY KEY (message_location_id);
+
+-- ------------------ CREATE INDEX SECTION
+--
+-- NAME: CR_REPORT_CREATE_IDPUBLIC_YNTITLE; TYPE: INDEX
+--
+create index cr_report_create_idpublic_yntitle using btree on cr_report (create_id, public_yn, title);
+--
+-- NAME: CR_TABLE_JOIN_DEST_TABLE_NAME; TYPE: INDEX
+--
+create index cr_table_join_dest_table_name using btree on cr_table_join (dest_table_name);
+--
+-- NAME: CR_TABLE_JOIN_SRC_TABLE_NAME; TYPE: INDEX
+--
+create index cr_table_join_src_table_name using btree on cr_table_join (src_table_name);
+--
+-- NAME: FN_AUDIT_LOG_ACTIVITY_CD; TYPE: INDEX
+--
+create index fn_audit_log_activity_cd using btree on fn_audit_log (activity_cd);
+--
+-- NAME: FN_AUDIT_LOG_USER_ID; TYPE: INDEX
+--
+create index fn_audit_log_user_id using btree on fn_audit_log (user_id);
+--
+-- NAME: FN_MENU_FUNCTION_CD; TYPE: INDEX
+--
+create index fn_menu_function_cd using btree on fn_menu (function_cd);
+--
+-- NAME: FN_ORG_ACCESS_CD; TYPE: INDEX
+--
+create index fn_org_access_cd using btree on fn_org (access_cd);
+--
+-- NAME: FN_ROLE_FUNCTION_FUNCTION_CD; TYPE: INDEX
+--
+create index fn_role_function_function_cd using btree on fn_role_function (function_cd);
+--
+-- NAME: FN_ROLE_FUNCTION_ROLE_ID; TYPE: INDEX
+--
+create index fn_role_function_role_id using btree on fn_role_function (role_id);
+--
+-- NAME: FN_USER_ADDRESS_ID; TYPE: INDEX
+--
+create index fn_user_address_id using btree on fn_user (address_id);
+--
+-- NAME: FN_USER_ALERT_METHOD_CD; TYPE: INDEX
+--
+create index fn_user_alert_method_cd using btree on fn_user (alert_method_cd);
+--
+-- NAME: FN_USER_HRID; TYPE: INDEX
+--
+create unique index fn_user_hrid using btree on fn_user (hrid);
+--
+-- NAME: FN_USER_LOGIN_ID; TYPE: INDEX
+--
+create unique index fn_user_login_id using btree on fn_user (login_id);
+--
+-- NAME: FN_USER_ORG_ID; TYPE: INDEX
+--
+create index fn_user_org_id using btree on fn_user (org_id);
+--
+-- NAME: FN_USER_ROLE_ROLE_ID; TYPE: INDEX
+--
+create index fn_user_role_role_id using btree on fn_user_role (role_id);
+--
+-- NAME: FN_USER_ROLE_USER_ID; TYPE: INDEX
+--
+create index fn_user_role_user_id using btree on fn_user_role (user_id);
+--
+-- NAME: FK_FN_USER__REF_178_FN_APP_idx; TYPE: INDEX
+--
+create index fk_fn_user__ref_178_fn_app_IDX on fn_user_role (app_id);
+
+-- ----------------------------------------------------------
+-- NAME: QUARTZ TYPE: INDEXES
+-- ----------------------------------------------------------
+create index idx_fn_qz_j_req_recovery on fn_qz_job_details(sched_name,requests_recovery);
+create index idx_fn_qz_j_grp on fn_qz_job_details(sched_name,job_group);
+create index idx_fn_qz_t_j on fn_qz_triggers(sched_name,job_name,job_group);
+create index idx_fn_qz_t_jg on fn_qz_triggers(sched_name,job_group);
+create index idx_fn_qz_t_c on fn_qz_triggers(sched_name,calendar_name);
+create index idx_fn_qz_t_g on fn_qz_triggers(sched_name,trigger_group);
+create index idx_fn_qz_t_state on fn_qz_triggers(sched_name,trigger_state);
+create index idx_fn_qz_t_n_state on fn_qz_triggers(sched_name,trigger_name,trigger_group,trigger_state);
+create index idx_fn_qz_t_n_g_state on fn_qz_triggers(sched_name,trigger_group,trigger_state);
+create index idx_fn_qz_t_next_fire_time on fn_qz_triggers(sched_name,next_fire_time);
+create index idx_fn_qz_t_nft_st on fn_qz_triggers(sched_name,trigger_state,next_fire_time);
+create index idx_fn_qz_t_nft_misfire on fn_qz_triggers(sched_name,misfire_instr,next_fire_time);
+create index idx_fn_qz_t_nft_st_misfire on fn_qz_triggers(sched_name,misfire_instr,next_fire_time,trigger_state);
+create index idx_fn_qz_t_nft_st_misfire_grp on fn_qz_triggers(sched_name,misfire_instr,next_fire_time,trigger_group,trigger_state);
+create index idx_fn_qz_ft_trig_inst_name on fn_qz_fired_triggers(sched_name,instance_name);
+create index idx_fn_qz_ft_inst_job_req_rcvry on fn_qz_fired_triggers(sched_name,instance_name,requests_recovery);
+create index idx_fn_qz_ft_j_g on fn_qz_fired_triggers(sched_name,job_name,job_group);
+create index idx_fn_qz_ft_jg on fn_qz_fired_triggers(sched_name,job_group);
+create index idx_fn_qz_ft_t_g on fn_qz_fired_triggers(sched_name,trigger_name,trigger_group);
+create index idx_fn_qz_ft_tg on fn_qz_fired_triggers(sched_name,trigger_group);
+
+-- ------------------ ALTER TABLE ADD CONSTRAINT FOREIGN KEY SECTION
+--
+-- NAME: FK_FN_AUDIT_REF_205_FN_LU_AC; TYPE: CONSTRAINT
+--
+alter table fn_audit_log
+ add constraint fk_fn_audit_ref_205_fn_lu_ac foreign key (activity_cd) references fn_lu_activity(activity_cd);
+--
+-- NAME: FK_FN_ROLE__REF_201_FN_FUNCT; TYPE: CONSTRAINT
+--
+alter table fn_role_function
+ add constraint fk_fn_role__ref_201_fn_funct foreign key (function_cd) references fn_function(function_cd);
+--
+-- NAME: FK_FN_USER__REF_178_FN_APP; TYPE: FK CONSTRAINT
+--
+alter table fn_user_role
+ add constraint fk_fn_user__ref_178_fn_app foreign key (app_id) references fn_app(app_id);
+--
+-- NAME: FK_CR_REPOR_REF_14707_CR_REPOR; TYPE: FK CONSTRAINT
+--
+alter table cr_report_schedule
+ add constraint fk_cr_repor_ref_14707_cr_repor foreign key (rep_id) references cr_report(rep_id);
+--
+-- NAME: FK_CR_REPOR_REF_14716_CR_REPOR; TYPE: FK CONSTRAINT
+--
+alter table cr_report_schedule_users
+ add constraint fk_cr_repor_ref_14716_cr_repor foreign key (schedule_id) references cr_report_schedule(schedule_id);
+--
+-- NAME: FK_CR_REPOR_REF_17645_CR_REPOR; TYPE: FK CONSTRAINT
+--
+alter table cr_report_log
+ add constraint fk_cr_repor_ref_17645_cr_repor foreign key (rep_id) references cr_report(rep_id);
+--
+-- NAME: FK_CR_REPOR_REF_8550_CR_REPOR; TYPE: FK CONSTRAINT
+--
+alter table cr_report_access
+ add constraint fk_cr_repor_ref_8550_cr_repor foreign key (rep_id) references cr_report(rep_id);
+--
+-- NAME: FK_CR_REPORT_REP_ID; TYPE: FK CONSTRAINT
+--
+alter table cr_report_email_sent_log
+ add constraint fk_cr_report_rep_id foreign key (rep_id) references cr_report(rep_id);
+--
+-- NAME: FK_CR_TABLE_REF_311_CR_TAB; TYPE: FK CONSTRAINT
+--
+alter table cr_table_join
+ add constraint fk_cr_table_ref_311_cr_tab foreign key (src_table_name) references cr_table_source(table_name);
+--
+-- NAME: FK_CR_TABLE_REF_315_CR_TAB; TYPE: FK CONSTRAINT
+--
+alter table cr_table_join
+ add constraint fk_cr_table_ref_315_cr_tab foreign key (dest_table_name) references cr_table_source(table_name);
+--
+-- NAME: FK_CR_TABLE_REF_32384_CR_TABLE; TYPE: FK CONSTRAINT
+--
+alter table cr_table_role
+ add constraint fk_cr_table_ref_32384_cr_table foreign key (table_name) references cr_table_source(table_name);
+--
+-- NAME: FK_FN_TAB_FUNCTION_CD; TYPE: FK CONSTRAINT
+--
+alter table fn_tab
+ add constraint fk_fn_tab_function_cd foreign key (function_cd) references fn_function(function_cd);
+--
+-- NAME: FK_FN_TAB_SELECTED_TAB_CD; TYPE: FK CONSTRAINT
+--
+alter table fn_tab_selected
+ add constraint fk_fn_tab_selected_tab_cd foreign key (selected_tab_cd) references fn_tab(tab_cd);
+--
+-- NAME: FK_FN_TAB_SET_CD; TYPE: FK CONSTRAINT
+--
+alter table fn_tab
+ add constraint fk_fn_tab_set_cd foreign key (tab_set_cd) references fn_lu_tab_set(tab_set_cd);
+--
+-- NAME: FK_FN_USER_REF_110_FN_ORG; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_fn_user_ref_110_fn_org foreign key (org_id) references fn_org(org_id);
+--
+-- NAME: FK_FN_USER_REF_123_FN_LU_AL; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_fn_user_ref_123_fn_lu_al foreign key (alert_method_cd) references fn_lu_alert_method(alert_method_cd);
+--
+-- NAME: FK_FN_USER_REF_197_FN_USER; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_fn_user_ref_197_fn_user foreign key (manager_id) references fn_user(user_id);
+--
+-- NAME: FK_FN_USER_REF_198_FN_USER; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_fn_user_ref_198_fn_user foreign key (created_id) references fn_user(user_id);
+--
+-- NAME: FK_FN_USER_REF_199_FN_USER; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_fn_user_ref_199_fn_user foreign key (modified_id) references fn_user(user_id);
+--
+-- NAME: FK_PARENT_KEY_CR_FOLDER; TYPE: FK CONSTRAINT
+--
+alter table cr_folder
+ add constraint fk_parent_key_cr_folder foreign key (parent_folder_id) references cr_folder(folder_id);
+--
+-- NAME: FK_PSEUDO_ROLE_PSEUDO_ROLE_ID; TYPE: FK CONSTRAINT
+--
+alter table fn_user_pseudo_role
+ add constraint fk_pseudo_role_pseudo_role_id foreign key (pseudo_role_id) references fn_role(role_id);
+--
+-- NAME: FK_PSEUDO_ROLE_USER_ID; TYPE: FK CONSTRAINT
+--
+alter table fn_user_pseudo_role
+ add constraint fk_pseudo_role_user_id foreign key (user_id) references fn_user(user_id);
+--
+-- NAME: FK_RESTRICTED_URL_FUNCTION_CD; TYPE: FK CONSTRAINT
+--
+alter table fn_restricted_url
+ add constraint fk_restricted_url_function_cd foreign key (function_cd) references fn_function(function_cd);
+--
+-- NAME: FK_TIMEZONE; TYPE: FK CONSTRAINT
+--
+alter table fn_user
+ add constraint fk_timezone foreign key (timezone) references fn_lu_timezone(timezone_id);
+--
+-- NAME: SYS_C0014614; TYPE: FK CONSTRAINT
+--
+alter table cr_report_file_history
+ add constraint sys_c0014614 foreign key (file_type_id) references cr_lu_file_type(lookup_id);
+--
+-- NAME: SYS_C0014615; TYPE: FK CONSTRAINT
+--
+alter table cr_report_file_history
+ add constraint sys_c0014615 foreign key (rep_id) references cr_report(rep_id);
+--
+-- NAME: SYS_C0014616; TYPE: FK CONSTRAINT
+--
+alter table cr_hist_user_map
+ add constraint sys_c0014616 foreign key (hist_id) references cr_report_file_history(hist_id);
+--
+-- NAME: SYS_C0014617; TYPE: FK CONSTRAINT
+--
+alter table cr_hist_user_map
+ add constraint sys_c0014617 foreign key (user_id) references fn_user(user_id);
+
+commit;
diff --git a/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDMLMySql_1707_Common.sql b/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDMLMySql_1707_Common.sql
new file mode 100644
index 00000000..5a015370
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/db-scripts/EcompSdkDMLMySql_1707_Common.sql
@@ -0,0 +1,2837 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This script populates tables in the 1707 COMMON version of the ECOMP SDK application database.
+-- Additional DML scripts may be required!
+-- ---------------------------------------------------------------------------------------------------------------
+
+SET FOREIGN_KEY_CHECKS=1;
+
+USE ecomp_sdk;
+
+-- fn_function
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_process','Process List');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job','Job Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job_create','Job Create');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job_designer','Process in Designer view');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_task','Task Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_task_search','Task Search');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_map','Map Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_sample','Sample Pages Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('login','Login');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_home','Home Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_customer','Customer Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_reports','Reports Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile','Profile Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_admin','Admin Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_feedback','Feedback Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_help','Help Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_logout','Logout Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_notes','Notes Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_ajax','Ajax Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_customer_create','Customer Create');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile_create','Profile Create');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile_import','Profile Import');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_tab','Sample Tab Menu');
+Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('view_reports','View Raptor reports');
+
+-- fn_lu_activity
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_role','add_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_role','remove_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_user_role','add_user_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_user_role','remove_user_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_role_function','add_role_function');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_role_function','remove_role_function');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_child_role','add_child_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_child_role','remove_child_role');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('mobile_login','Mobile Login');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('mobile_logout','Mobile Logout');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('login','Login');
+Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('logout','Logout');
+
+-- fn_lu_alert_method
+Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('PHONE','Phone');
+Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('FAX','Fax');
+Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('PAGER','Pager');
+Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('EMAIL','Email');
+Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('SMS','SMS');
+
+-- fn_lu_menu_set
+Insert into fn_lu_menu_set (MENU_SET_CD,MENU_SET_NAME) values ('APP','Application Menu');
+
+-- fn_lu_priority
+Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (10,'Low','Y',10);
+Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (20,'Normal','Y',20);
+Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (30,'High','Y',30);
+Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (40,'Urgent','Y',40);
+Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (50,'Fatal','Y',50);
+
+-- fn_lu_tab_set
+Insert into fn_lu_tab_set (TAB_SET_CD,TAB_SET_NAME) values ('APP','Application Tabs');
+
+-- fn_lu_timezone
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (10,'US/Eastern','US/Eastern');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (20,'US/Central','US/Central');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (30,'US/Mountain','US/Mountain');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (40,'US/Arizona','America/Phoenix');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (50,'US/Pacific','US/Pacific');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (60,'US/Alaska','US/Alaska');
+Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (70,'US/Hawaii','US/Hawaii');
+
+-- fn_restricted_url
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('attachment.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('broadcast.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('file_upload.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('job.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('role.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('role_function.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('test.htm','menu_admin');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('async_test.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('chatWindow.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('contact_list.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('customer_dynamic_list.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('event.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('event_list.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('mobile_welcome.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map.htm','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('template.jsp','menu_home');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('jbpm_designer.htm','menu_job_create');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('jbpm_drools.htm','menu_job_create');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('process_job.htm','menu_job_create');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('profile.htm','menu_profile_create');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor2.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_blob_extract.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_email_attachment.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_search.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('report_list.htm','menu_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gauge.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gmap_controller.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gmap_frame.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map_download.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map_grid_search.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_animated_map.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map_2.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map_3.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub1.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub2_link1.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub2_link2.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub3.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab3.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab4.htm','menu_tab');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor.htm','view_reports');
+INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_blob_extract.htm','view_reports');
+
+-- fn_role
+Insert into fn_role (ROLE_ID,ROLE_NAME,ACTIVE_YN,PRIORITY) values (16,'Standard User','Y',5);
+Insert into fn_role (ROLE_ID,ROLE_NAME,ACTIVE_YN,PRIORITY) values (1,'System Administrator','Y',1);
+
+-- fn_role_composite
+Insert into fn_role_composite (PARENT_ROLE_ID,CHILD_ROLE_ID) values (1,16);
+
+-- fn_role_function
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'login');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_admin');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_ajax');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_customer');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_customer_create');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_feedback');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_help');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_home');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_job');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_job_create');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_logout');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_notes');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_process');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile_create');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile_import');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_reports');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_sample');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_tab');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'login');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_ajax');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_customer');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_customer_create');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_home');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_logout');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_map');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_profile');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_reports');
+Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_tab');
+
+-- fn_tab
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB1_S1','Left Tab 1','Sub - Sub Tab 1 Information','tab2_sub1.htm','menu_tab','Y',10,'TAB2_SUB1','APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB1','Tab 1','Tab 1 Information','tab1.htm','menu_tab','Y',10,null,'APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2','Tab 2','Tab 2 Information','tab2_sub1.htm','menu_tab','Y',20,null,'APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB3','Tab 3','Tab 3 Information','tab3.htm','menu_tab','Y',30,null,'APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB4','Tab 4','Tab 4 Information','tab4.htm','menu_tab','Y',40,null,'APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB1','Sub Tab 1','Sub Tab 1 Information','tab2_sub1.htm','menu_tab','Y',10,'TAB2','APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB2','Sub Tab 2','Sub Tab 2 Information','tab2_sub2.htm','menu_tab','Y',20,'TAB2','APP');
+Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB3','Sub Tab 3','Sub Tab 3 Information','tab2_sub3.htm','menu_tab','Y',30,'TAB2','APP');
+
+-- fn_tab_selected
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB1','tab1');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub1');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub2');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub3');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB1','tab2_sub1');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB1_S1','tab2_sub1');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB2','tab2_sub2');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB3','tab2_sub3');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB3','tab3');
+Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB4','tab4');
+
+-- DEMO_BAR_CHART
+Insert into demo_bar_chart (label, value) values ('A', 29.765957771107);
+Insert into demo_bar_chart (label, value) values ('B', 0);
+Insert into demo_bar_chart (label, value) values ('C', 32.807804682612);
+Insert into demo_bar_chart (label, value) values ('D', 196.45946739256);
+Insert into demo_bar_chart (label, value) values ('E', 0.19434030906893);
+Insert into demo_bar_chart (label, value) values ('F', 98.079782601442);
+Insert into demo_bar_chart (label, value) values ('G', 13.925743130903);
+Insert into demo_bar_chart (label, value) values ('H', 5.1387322875705);
+
+-- DEMO_BAR_CHART_INTER
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('6-Mar-13','%e-%b-%y'), 198, 220);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('5-Mar-13','%e-%b-%y'), 198, 220);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('4-Mar-13','%e-%b-%y'), 238, 235);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('3-Mar-13','%e-%b-%y'), 238, 235);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('2-Mar-13','%e-%b-%y'), 256, 275);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('1-Mar-13','%e-%b-%y'), 239, 260);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('28-Feb-13','%e-%b-%y'), 247, 255);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('27-Feb-13','%e-%b-%y'), 252, 265);
+Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('26-Feb-13','%e-%b-%y'), 198, 220);
+
+-- DEMO_LINE_CHART
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-May-12','%e-%b-%y'),582.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Apr-12','%e-%b-%y'),583.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Apr-12','%e-%b-%y'),603);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Apr-12','%e-%b-%y'),607.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Apr-12','%e-%b-%y'),610);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Apr-12','%e-%b-%y'),560.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Apr-12','%e-%b-%y'),571.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Apr-12','%e-%b-%y'),572.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Apr-12','%e-%b-%y'),587.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Apr-12','%e-%b-%y'),608.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Apr-12','%e-%b-%y'),609.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Apr-12','%e-%b-%y'),580.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Apr-12','%e-%b-%y'),605.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Apr-12','%e-%b-%y'),622.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Apr-12','%e-%b-%y'),626.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Apr-12','%e-%b-%y'),628.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Apr-12','%e-%b-%y'),636.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Apr-12','%e-%b-%y'),633.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Apr-12','%e-%b-%y'),624.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-12','%e-%b-%y'),629.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Apr-12','%e-%b-%y'),618.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-12','%e-%b-%y'),599.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Mar-12','%e-%b-%y'),609.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Mar-12','%e-%b-%y'),617.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Mar-12','%e-%b-%y'),614.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-12','%e-%b-%y'),606.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-12','%e-%b-%y'),596.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Mar-12','%e-%b-%y'),599.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Mar-12','%e-%b-%y'),602.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Mar-12','%e-%b-%y'),605.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-12','%e-%b-%y'),601.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-12','%e-%b-%y'),585.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Mar-12','%e-%b-%y'),585.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Mar-12','%e-%b-%y'),589.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Mar-12','%e-%b-%y'),568.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-12','%e-%b-%y'),552);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-12','%e-%b-%y'),545.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Mar-12','%e-%b-%y'),541.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Mar-12','%e-%b-%y'),530.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Mar-12','%e-%b-%y'),530.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Mar-12','%e-%b-%y'),533.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-12','%e-%b-%y'),545.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Mar-12','%e-%b-%y'),544.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Feb-12','%e-%b-%y'),542.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Feb-12','%e-%b-%y'),535.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Feb-12','%e-%b-%y'),525.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Feb-12','%e-%b-%y'),522.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Feb-12','%e-%b-%y'),516.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Feb-12','%e-%b-%y'),513.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Feb-12','%e-%b-%y'),514.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-12','%e-%b-%y'),502.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-12','%e-%b-%y'),502.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-12','%e-%b-%y'),497.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Feb-12','%e-%b-%y'),509.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Feb-12','%e-%b-%y'),502.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-12','%e-%b-%y'),493.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-12','%e-%b-%y'),493.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-12','%e-%b-%y'),476.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Feb-12','%e-%b-%y'),468.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Feb-12','%e-%b-%y'),463.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-12','%e-%b-%y'),459.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-12','%e-%b-%y'),455.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-12','%e-%b-%y'),456.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jan-12','%e-%b-%y'),456.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jan-12','%e-%b-%y'),453.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-12','%e-%b-%y'),447.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-12','%e-%b-%y'),444.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-12','%e-%b-%y'),446.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jan-12','%e-%b-%y'),420.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jan-12','%e-%b-%y'),427.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-12','%e-%b-%y'),420.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-12','%e-%b-%y'),427.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-12','%e-%b-%y'),429.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jan-12','%e-%b-%y'),424.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jan-12','%e-%b-%y'),419.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jan-12','%e-%b-%y'),421.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jan-12','%e-%b-%y'),422.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jan-12','%e-%b-%y'),423.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Jan-12','%e-%b-%y'),421.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jan-12','%e-%b-%y'),422.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jan-12','%e-%b-%y'),418.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jan-12','%e-%b-%y'),413.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jan-12','%e-%b-%y'),411.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-11','%e-%b-%y'),405);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Dec-11','%e-%b-%y'),405.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Dec-11','%e-%b-%y'),402.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Dec-11','%e-%b-%y'),406.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Dec-11','%e-%b-%y'),403.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Dec-11','%e-%b-%y'),398.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Dec-11','%e-%b-%y'),396.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Dec-11','%e-%b-%y'),395.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Dec-11','%e-%b-%y'),382.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Dec-11','%e-%b-%y'),381.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Dec-11','%e-%b-%y'),378.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Dec-11','%e-%b-%y'),380.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Dec-11','%e-%b-%y'),388.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Dec-11','%e-%b-%y'),391.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Dec-11','%e-%b-%y'),393.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Dec-11','%e-%b-%y'),390.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Dec-11','%e-%b-%y'),389.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Dec-11','%e-%b-%y'),390.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Dec-11','%e-%b-%y'),393.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Dec-11','%e-%b-%y'),389.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Dec-11','%e-%b-%y'),387.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Nov-11','%e-%b-%y'),382.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Nov-11','%e-%b-%y'),373.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Nov-11','%e-%b-%y'),376.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Nov-11','%e-%b-%y'),363.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Nov-11','%e-%b-%y'),366.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Nov-11','%e-%b-%y'),376.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Nov-11','%e-%b-%y'),369.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-11','%e-%b-%y'),374.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Nov-11','%e-%b-%y'),377.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Nov-11','%e-%b-%y'),384.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Nov-11','%e-%b-%y'),388.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Nov-11','%e-%b-%y'),379.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Nov-11','%e-%b-%y'),384.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-11','%e-%b-%y'),385.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Nov-11','%e-%b-%y'),395.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Nov-11','%e-%b-%y'),406.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Nov-11','%e-%b-%y'),399.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-11','%e-%b-%y'),400.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Nov-11','%e-%b-%y'),403.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Nov-11','%e-%b-%y'),397.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Nov-11','%e-%b-%y'),396.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Oct-11','%e-%b-%y'),404.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Oct-11','%e-%b-%y'),404.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-11','%e-%b-%y'),404.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Oct-11','%e-%b-%y'),400.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Oct-11','%e-%b-%y'),397.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Oct-11','%e-%b-%y'),405.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-11','%e-%b-%y'),392.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Oct-11','%e-%b-%y'),395.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Oct-11','%e-%b-%y'),398.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Oct-11','%e-%b-%y'),422.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Oct-11','%e-%b-%y'),419.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Oct-11','%e-%b-%y'),422);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-11','%e-%b-%y'),408.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Oct-11','%e-%b-%y'),402.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Oct-11','%e-%b-%y'),400.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Oct-11','%e-%b-%y'),388.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-11','%e-%b-%y'),369.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Oct-11','%e-%b-%y'),377.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Oct-11','%e-%b-%y'),378.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Oct-11','%e-%b-%y'),372.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Oct-11','%e-%b-%y'),374.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Sep-11','%e-%b-%y'),381.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-11','%e-%b-%y'),390.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Sep-11','%e-%b-%y'),397.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Sep-11','%e-%b-%y'),399.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Sep-11','%e-%b-%y'),403.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-11','%e-%b-%y'),404.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Sep-11','%e-%b-%y'),401.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Sep-11','%e-%b-%y'),412.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Sep-11','%e-%b-%y'),413.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Sep-11','%e-%b-%y'),411.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Sep-11','%e-%b-%y'),400.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-11','%e-%b-%y'),392.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Sep-11','%e-%b-%y'),389.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Sep-11','%e-%b-%y'),384.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Sep-11','%e-%b-%y'),379.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-11','%e-%b-%y'),377.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Sep-11','%e-%b-%y'),384.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Sep-11','%e-%b-%y'),383.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Sep-11','%e-%b-%y'),379.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-11','%e-%b-%y'),374.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Sep-11','%e-%b-%y'),381.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-11','%e-%b-%y'),384.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Aug-11','%e-%b-%y'),389.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Aug-11','%e-%b-%y'),389.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Aug-11','%e-%b-%y'),383.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-11','%e-%b-%y'),373.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Aug-11','%e-%b-%y'),376.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Aug-11','%e-%b-%y'),373.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Aug-11','%e-%b-%y'),356.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-11','%e-%b-%y'),356.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Aug-11','%e-%b-%y'),366.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-11','%e-%b-%y'),380.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Aug-11','%e-%b-%y'),380.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Aug-11','%e-%b-%y'),383.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Aug-11','%e-%b-%y'),376.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-11','%e-%b-%y'),373.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Aug-11','%e-%b-%y'),363.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Aug-11','%e-%b-%y'),374.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Aug-11','%e-%b-%y'),353.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-11','%e-%b-%y'),373.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Aug-11','%e-%b-%y'),377.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Aug-11','%e-%b-%y'),392.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Aug-11','%e-%b-%y'),388.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Aug-11','%e-%b-%y'),396.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-11','%e-%b-%y'),390.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-11','%e-%b-%y'),391.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jul-11','%e-%b-%y'),392.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jul-11','%e-%b-%y'),403.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jul-11','%e-%b-%y'),398.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-11','%e-%b-%y'),393.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-11','%e-%b-%y'),387.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jul-11','%e-%b-%y'),386.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Jul-11','%e-%b-%y'),376.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jul-11','%e-%b-%y'),373.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Jul-11','%e-%b-%y'),364.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-11','%e-%b-%y'),357.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Jul-11','%e-%b-%y'),358.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jul-11','%e-%b-%y'),353.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jul-11','%e-%b-%y'),354);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-11','%e-%b-%y'),359.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Jul-11','%e-%b-%y'),357.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jul-11','%e-%b-%y'),351.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Jul-11','%e-%b-%y'),349.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-11','%e-%b-%y'),343.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jun-11','%e-%b-%y'),335.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jun-11','%e-%b-%y'),334.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Jun-11','%e-%b-%y'),335.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jun-11','%e-%b-%y'),332.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jun-11','%e-%b-%y'),326.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-11','%e-%b-%y'),331.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jun-11','%e-%b-%y'),322.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jun-11','%e-%b-%y'),325.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jun-11','%e-%b-%y'),315.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-11','%e-%b-%y'),320.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jun-11','%e-%b-%y'),325.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jun-11','%e-%b-%y'),326.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jun-11','%e-%b-%y'),332.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jun-11','%e-%b-%y'),326.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jun-11','%e-%b-%y'),325.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-11','%e-%b-%y'),331.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jun-11','%e-%b-%y'),332.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jun-11','%e-%b-%y'),332.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jun-11','%e-%b-%y'),338.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-11','%e-%b-%y'),343.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jun-11','%e-%b-%y'),346.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jun-11','%e-%b-%y'),345.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-May-11','%e-%b-%y'),347.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-May-11','%e-%b-%y'),337.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-May-11','%e-%b-%y'),335);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-May-11','%e-%b-%y'),336.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-May-11','%e-%b-%y'),332.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-May-11','%e-%b-%y'),334.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-May-11','%e-%b-%y'),335.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-11','%e-%b-%y'),340.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-11','%e-%b-%y'),339.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-May-11','%e-%b-%y'),336.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-May-11','%e-%b-%y'),333.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-11','%e-%b-%y'),340.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-May-11','%e-%b-%y'),346.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-11','%e-%b-%y'),347.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-May-11','%e-%b-%y'),349.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-May-11','%e-%b-%y'),347.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-May-11','%e-%b-%y'),346.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-11','%e-%b-%y'),346.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-May-11','%e-%b-%y'),349.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-May-11','%e-%b-%y'),348.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-May-11','%e-%b-%y'),346.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-11','%e-%b-%y'),350.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Apr-11','%e-%b-%y'),346.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-11','%e-%b-%y'),350.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Apr-11','%e-%b-%y'),350.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Apr-11','%e-%b-%y'),353.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Apr-11','%e-%b-%y'),350.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Apr-11','%e-%b-%y'),342.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Apr-11','%e-%b-%y'),337.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Apr-11','%e-%b-%y'),331.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Apr-11','%e-%b-%y'),327.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Apr-11','%e-%b-%y'),332.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Apr-11','%e-%b-%y'),336.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Apr-11','%e-%b-%y'),332.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Apr-11','%e-%b-%y'),330.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Apr-11','%e-%b-%y'),335.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Apr-11','%e-%b-%y'),338.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Apr-11','%e-%b-%y'),338.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Apr-11','%e-%b-%y'),338.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Apr-11','%e-%b-%y'),341.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Apr-11','%e-%b-%y'),344.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Mar-11','%e-%b-%y'),348.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Mar-11','%e-%b-%y'),348.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Mar-11','%e-%b-%y'),350.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Mar-11','%e-%b-%y'),350.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Mar-11','%e-%b-%y'),351.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Mar-11','%e-%b-%y'),344.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Mar-11','%e-%b-%y'),339.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Mar-11','%e-%b-%y'),341.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Mar-11','%e-%b-%y'),339.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Mar-11','%e-%b-%y'),330.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Mar-11','%e-%b-%y'),334.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Mar-11','%e-%b-%y'),330.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Mar-11','%e-%b-%y'),345.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Mar-11','%e-%b-%y'),353.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Mar-11','%e-%b-%y'),351.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Mar-11','%e-%b-%y'),346.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Mar-11','%e-%b-%y'),352.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Mar-11','%e-%b-%y'),355.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Mar-11','%e-%b-%y'),355.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Mar-11','%e-%b-%y'),360);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Mar-11','%e-%b-%y'),359.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Mar-11','%e-%b-%y'),352.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Mar-11','%e-%b-%y'),349.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Feb-11','%e-%b-%y'),353.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Feb-11','%e-%b-%y'),348.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Feb-11','%e-%b-%y'),342.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Feb-11','%e-%b-%y'),342.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Feb-11','%e-%b-%y'),338.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-11','%e-%b-%y'),350.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-11','%e-%b-%y'),358.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-11','%e-%b-%y'),363.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-11','%e-%b-%y'),359.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Feb-11','%e-%b-%y'),359.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Feb-11','%e-%b-%y'),356.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-11','%e-%b-%y'),354.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-11','%e-%b-%y'),358.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-11','%e-%b-%y'),355.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Feb-11','%e-%b-%y'),351.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Feb-11','%e-%b-%y'),346.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-11','%e-%b-%y'),343.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-11','%e-%b-%y'),344.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-11','%e-%b-%y'),345.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jan-11','%e-%b-%y'),339.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Jan-11','%e-%b-%y'),336.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-11','%e-%b-%y'),343.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-11','%e-%b-%y'),343.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-11','%e-%b-%y'),341.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jan-11','%e-%b-%y'),337.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jan-11','%e-%b-%y'),326.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-11','%e-%b-%y'),332.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-11','%e-%b-%y'),338.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-11','%e-%b-%y'),340.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jan-11','%e-%b-%y'),348.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jan-11','%e-%b-%y'),345.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jan-11','%e-%b-%y'),344.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jan-11','%e-%b-%y'),341.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jan-11','%e-%b-%y'),342.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jan-11','%e-%b-%y'),336.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jan-11','%e-%b-%y'),333.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jan-11','%e-%b-%y'),334);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jan-11','%e-%b-%y'),331.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jan-11','%e-%b-%y'),329.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Dec-10','%e-%b-%y'),322.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Dec-10','%e-%b-%y'),323.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Dec-10','%e-%b-%y'),325.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Dec-10','%e-%b-%y'),325.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Dec-10','%e-%b-%y'),324.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-10','%e-%b-%y'),323.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-10','%e-%b-%y'),325.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Dec-10','%e-%b-%y'),324.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Dec-10','%e-%b-%y'),322.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Dec-10','%e-%b-%y'),320.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-10','%e-%b-%y'),321.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-10','%e-%b-%y'),320.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-10','%e-%b-%y'),320.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Dec-10','%e-%b-%y'),321.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-10','%e-%b-%y'),320.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Dec-10','%e-%b-%y'),319.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-10','%e-%b-%y'),321.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-10','%e-%b-%y'),318.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Dec-10','%e-%b-%y'),320.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Dec-10','%e-%b-%y'),317.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-10','%e-%b-%y'),318.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Dec-10','%e-%b-%y'),316.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-10','%e-%b-%y'),311.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Nov-10','%e-%b-%y'),316.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-10','%e-%b-%y'),315);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Nov-10','%e-%b-%y'),314.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Nov-10','%e-%b-%y'),308.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Nov-10','%e-%b-%y'),313.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Nov-10','%e-%b-%y'),306.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Nov-10','%e-%b-%y'),308.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Nov-10','%e-%b-%y'),300.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Nov-10','%e-%b-%y'),301.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Nov-10','%e-%b-%y'),307.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Nov-10','%e-%b-%y'),308.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Nov-10','%e-%b-%y'),316.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Nov-10','%e-%b-%y'),318.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Nov-10','%e-%b-%y'),316.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Nov-10','%e-%b-%y'),318.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Nov-10','%e-%b-%y'),317.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Nov-10','%e-%b-%y'),318.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Nov-10','%e-%b-%y'),312.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Nov-10','%e-%b-%y'),309.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Nov-10','%e-%b-%y'),304.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Oct-10','%e-%b-%y'),300.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Oct-10','%e-%b-%y'),305.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Oct-10','%e-%b-%y'),307.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Oct-10','%e-%b-%y'),308.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Oct-10','%e-%b-%y'),308.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Oct-10','%e-%b-%y'),307.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Oct-10','%e-%b-%y'),309.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Oct-10','%e-%b-%y'),310.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Oct-10','%e-%b-%y'),309.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Oct-10','%e-%b-%y'),318);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Oct-10','%e-%b-%y'),314.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Oct-10','%e-%b-%y'),302.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Oct-10','%e-%b-%y'),300.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Oct-10','%e-%b-%y'),298.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Oct-10','%e-%b-%y'),295.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Oct-10','%e-%b-%y'),294.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Oct-10','%e-%b-%y'),289.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Oct-10','%e-%b-%y'),289.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Oct-10','%e-%b-%y'),288.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Oct-10','%e-%b-%y'),278.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Oct-10','%e-%b-%y'),282.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Sep-10','%e-%b-%y'),283.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Sep-10','%e-%b-%y'),287.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Sep-10','%e-%b-%y'),286.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Sep-10','%e-%b-%y'),291.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Sep-10','%e-%b-%y'),292.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Sep-10','%e-%b-%y'),288.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Sep-10','%e-%b-%y'),287.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Sep-10','%e-%b-%y'),283.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Sep-10','%e-%b-%y'),283.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Sep-10','%e-%b-%y'),275.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Sep-10','%e-%b-%y'),276.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Sep-10','%e-%b-%y'),270.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Sep-10','%e-%b-%y'),268.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Sep-10','%e-%b-%y'),267.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Sep-10','%e-%b-%y'),263.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Sep-10','%e-%b-%y'),263.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Sep-10','%e-%b-%y'),262.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Sep-10','%e-%b-%y'),257.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Sep-10','%e-%b-%y'),258.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Sep-10','%e-%b-%y'),258.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-10','%e-%b-%y'),252.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Sep-10','%e-%b-%y'),250.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-10','%e-%b-%y'),243.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Aug-10','%e-%b-%y'),242.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-10','%e-%b-%y'),241.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-10','%e-%b-%y'),240.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-10','%e-%b-%y'),242.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Aug-10','%e-%b-%y'),239.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Aug-10','%e-%b-%y'),245.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Aug-10','%e-%b-%y'),249.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-10','%e-%b-%y'),249.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-10','%e-%b-%y'),253.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-10','%e-%b-%y'),251.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Aug-10','%e-%b-%y'),247.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-10','%e-%b-%y'),249.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Aug-10','%e-%b-%y'),251.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-10','%e-%b-%y'),250.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Aug-10','%e-%b-%y'),259.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Aug-10','%e-%b-%y'),261.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Aug-10','%e-%b-%y'),260.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-10','%e-%b-%y'),261.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Aug-10','%e-%b-%y'),262.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Aug-10','%e-%b-%y'),261.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Aug-10','%e-%b-%y'),261.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jul-10','%e-%b-%y'),257.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-10','%e-%b-%y'),258.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-10','%e-%b-%y'),260.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Jul-10','%e-%b-%y'),264.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jul-10','%e-%b-%y'),259.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jul-10','%e-%b-%y'),259.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-10','%e-%b-%y'),259.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-10','%e-%b-%y'),254.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jul-10','%e-%b-%y'),251.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Jul-10','%e-%b-%y'),245.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jul-10','%e-%b-%y'),249.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jul-10','%e-%b-%y'),251.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-10','%e-%b-%y'),252.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Jul-10','%e-%b-%y'),251.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jul-10','%e-%b-%y'),257.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Jul-10','%e-%b-%y'),259.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-10','%e-%b-%y'),258.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jul-10','%e-%b-%y'),258.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jul-10','%e-%b-%y'),248.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Jul-10','%e-%b-%y'),246.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jul-10','%e-%b-%y'),246.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Jul-10','%e-%b-%y'),248.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jun-10','%e-%b-%y'),251.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jun-10','%e-%b-%y'),256.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jun-10','%e-%b-%y'),268.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Jun-10','%e-%b-%y'),266.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jun-10','%e-%b-%y'),269);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Jun-10','%e-%b-%y'),270.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jun-10','%e-%b-%y'),273.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jun-10','%e-%b-%y'),270.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jun-10','%e-%b-%y'),274.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Jun-10','%e-%b-%y'),271.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jun-10','%e-%b-%y'),267.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Jun-10','%e-%b-%y'),259.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jun-10','%e-%b-%y'),254.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jun-10','%e-%b-%y'),253.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jun-10','%e-%b-%y'),250.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Jun-10','%e-%b-%y'),243.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jun-10','%e-%b-%y'),249.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Jun-10','%e-%b-%y'),250.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jun-10','%e-%b-%y'),255.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jun-10','%e-%b-%y'),263.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jun-10','%e-%b-%y'),263.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Jun-10','%e-%b-%y'),260.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-May-10','%e-%b-%y'),256.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-May-10','%e-%b-%y'),256.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-May-10','%e-%b-%y'),253.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-May-10','%e-%b-%y'),244.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-May-10','%e-%b-%y'),245.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-May-10','%e-%b-%y'),246.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-10','%e-%b-%y'),242.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-May-10','%e-%b-%y'),237.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-10','%e-%b-%y'),248.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-10','%e-%b-%y'),252.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-May-10','%e-%b-%y'),254.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-10','%e-%b-%y'),253.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-10','%e-%b-%y'),258.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-May-10','%e-%b-%y'),262.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-10','%e-%b-%y'),256.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-May-10','%e-%b-%y'),253.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-10','%e-%b-%y'),235.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-10','%e-%b-%y'),246.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-10','%e-%b-%y'),255.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-May-10','%e-%b-%y'),258.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-May-10','%e-%b-%y'),266.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Apr-10','%e-%b-%y'),261.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-10','%e-%b-%y'),268.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-10','%e-%b-%y'),261.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-10','%e-%b-%y'),262.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Apr-10','%e-%b-%y'),269.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-10','%e-%b-%y'),270.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Apr-10','%e-%b-%y'),266.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-10','%e-%b-%y'),259.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Apr-10','%e-%b-%y'),244.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Apr-10','%e-%b-%y'),247.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Apr-10','%e-%b-%y'),247.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-10','%e-%b-%y'),248.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Apr-10','%e-%b-%y'),245.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Apr-10','%e-%b-%y'),242.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Apr-10','%e-%b-%y'),242.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-10','%e-%b-%y'),241.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Apr-10','%e-%b-%y'),239.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-10','%e-%b-%y'),240.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Apr-10','%e-%b-%y'),239.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Apr-10','%e-%b-%y'),238.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-10','%e-%b-%y'),235.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-10','%e-%b-%y'),235.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('31-Mar-10','%e-%b-%y'),235);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-10','%e-%b-%y'),235.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Mar-10','%e-%b-%y'),232.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-10','%e-%b-%y'),230.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-10','%e-%b-%y'),226.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-10','%e-%b-%y'),229.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-10','%e-%b-%y'),228.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Mar-10','%e-%b-%y'),224.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-10','%e-%b-%y'),222.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Mar-10','%e-%b-%y'),224.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Mar-10','%e-%b-%y'),224.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-10','%e-%b-%y'),224.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Mar-10','%e-%b-%y'),223.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-10','%e-%b-%y'),226.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Mar-10','%e-%b-%y'),225.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Mar-10','%e-%b-%y'),224.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-10','%e-%b-%y'),223.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Mar-10','%e-%b-%y'),219.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Mar-10','%e-%b-%y'),218.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Mar-10','%e-%b-%y'),210.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Mar-10','%e-%b-%y'),209.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-10','%e-%b-%y'),208.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Mar-10','%e-%b-%y'),208.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-10','%e-%b-%y'),204.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Feb-10','%e-%b-%y'),202);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Feb-10','%e-%b-%y'),200.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Feb-10','%e-%b-%y'),197.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Feb-10','%e-%b-%y'),200.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-10','%e-%b-%y'),201.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-10','%e-%b-%y'),202.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-10','%e-%b-%y'),202.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-10','%e-%b-%y'),203.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-10','%e-%b-%y'),200.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Feb-10','%e-%b-%y'),200.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Feb-10','%e-%b-%y'),198.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-10','%e-%b-%y'),195.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-10','%e-%b-%y'),196.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-10','%e-%b-%y'),194.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Feb-10','%e-%b-%y'),195.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Feb-10','%e-%b-%y'),192.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-10','%e-%b-%y'),199.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-10','%e-%b-%y'),195.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-10','%e-%b-%y'),194.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jan-10','%e-%b-%y'),192.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Jan-10','%e-%b-%y'),199.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-10','%e-%b-%y'),207.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-10','%e-%b-%y'),205.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-10','%e-%b-%y'),203.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Jan-10','%e-%b-%y'),197.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jan-10','%e-%b-%y'),208.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-10','%e-%b-%y'),211.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-10','%e-%b-%y'),215.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-10','%e-%b-%y'),205.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-10','%e-%b-%y'),205.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Jan-10','%e-%b-%y'),209.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jan-10','%e-%b-%y'),210.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jan-10','%e-%b-%y'),207.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jan-10','%e-%b-%y'),210.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jan-10','%e-%b-%y'),211.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-10','%e-%b-%y'),210.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Jan-10','%e-%b-%y'),210.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jan-10','%e-%b-%y'),214.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jan-10','%e-%b-%y'),214.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jan-10','%e-%b-%y'),210.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Dec-09','%e-%b-%y'),210.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-09','%e-%b-%y'),211.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Dec-09','%e-%b-%y'),209.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Dec-09','%e-%b-%y'),211.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Dec-09','%e-%b-%y'),209.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-09','%e-%b-%y'),209.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-09','%e-%b-%y'),202.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-09','%e-%b-%y'),200.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Dec-09','%e-%b-%y'),198.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-09','%e-%b-%y'),195.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Dec-09','%e-%b-%y'),191.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-09','%e-%b-%y'),195.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-09','%e-%b-%y'),194.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-09','%e-%b-%y'),196.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Dec-09','%e-%b-%y'),194.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-09','%e-%b-%y'),196.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Dec-09','%e-%b-%y'),197.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-09','%e-%b-%y'),189.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-09','%e-%b-%y'),188.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-09','%e-%b-%y'),193.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Dec-09','%e-%b-%y'),196.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-09','%e-%b-%y'),196.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Dec-09','%e-%b-%y'),196.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-09','%e-%b-%y'),199.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-09','%e-%b-%y'),200.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-09','%e-%b-%y'),204.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Nov-09','%e-%b-%y'),204.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Nov-09','%e-%b-%y'),204.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Nov-09','%e-%b-%y'),205.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Nov-09','%e-%b-%y'),199.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Nov-09','%e-%b-%y'),200.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-09','%e-%b-%y'),205.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Nov-09','%e-%b-%y'),207);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Nov-09','%e-%b-%y'),206.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Nov-09','%e-%b-%y'),204.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Nov-09','%e-%b-%y'),201.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Nov-09','%e-%b-%y'),203.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-09','%e-%b-%y'),202.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Nov-09','%e-%b-%y'),201.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Nov-09','%e-%b-%y'),194.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Nov-09','%e-%b-%y'),194.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-09','%e-%b-%y'),190.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Nov-09','%e-%b-%y'),188.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Nov-09','%e-%b-%y'),189.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Oct-09','%e-%b-%y'),188.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Oct-09','%e-%b-%y'),196.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Oct-09','%e-%b-%y'),192.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-09','%e-%b-%y'),197.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Oct-09','%e-%b-%y'),202.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Oct-09','%e-%b-%y'),203.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Oct-09','%e-%b-%y'),205.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-09','%e-%b-%y'),204.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Oct-09','%e-%b-%y'),198.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Oct-09','%e-%b-%y'),189.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Oct-09','%e-%b-%y'),188.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Oct-09','%e-%b-%y'),190.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Oct-09','%e-%b-%y'),191.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-09','%e-%b-%y'),190.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Oct-09','%e-%b-%y'),190.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Oct-09','%e-%b-%y'),190.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Oct-09','%e-%b-%y'),189.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-09','%e-%b-%y'),190.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Oct-09','%e-%b-%y'),190.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Oct-09','%e-%b-%y'),186.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Oct-09','%e-%b-%y'),184.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Oct-09','%e-%b-%y'),180.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Sep-09','%e-%b-%y'),185.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-09','%e-%b-%y'),185.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Sep-09','%e-%b-%y'),186.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Sep-09','%e-%b-%y'),182.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Sep-09','%e-%b-%y'),183.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-09','%e-%b-%y'),185.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Sep-09','%e-%b-%y'),184.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Sep-09','%e-%b-%y'),184.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Sep-09','%e-%b-%y'),185.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Sep-09','%e-%b-%y'),184.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Sep-09','%e-%b-%y'),181.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-09','%e-%b-%y'),175.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Sep-09','%e-%b-%y'),173.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Sep-09','%e-%b-%y'),172.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Sep-09','%e-%b-%y'),172.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-09','%e-%b-%y'),171.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Sep-09','%e-%b-%y'),172.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Sep-09','%e-%b-%y'),170.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Sep-09','%e-%b-%y'),166.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-09','%e-%b-%y'),165.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Sep-09','%e-%b-%y'),165.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-09','%e-%b-%y'),168.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Aug-09','%e-%b-%y'),170.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-09','%e-%b-%y'),169.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-09','%e-%b-%y'),167.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-09','%e-%b-%y'),169.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Aug-09','%e-%b-%y'),169.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Aug-09','%e-%b-%y'),169.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Aug-09','%e-%b-%y'),166.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-09','%e-%b-%y'),164.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-09','%e-%b-%y'),164);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-09','%e-%b-%y'),159.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Aug-09','%e-%b-%y'),166.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-09','%e-%b-%y'),168.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Aug-09','%e-%b-%y'),165.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Aug-09','%e-%b-%y'),164.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Aug-09','%e-%b-%y'),165.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Aug-09','%e-%b-%y'),163.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Aug-09','%e-%b-%y'),165.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Aug-09','%e-%b-%y'),165.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Aug-09','%e-%b-%y'),166.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jul-09','%e-%b-%y'),163.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jul-09','%e-%b-%y'),162.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jul-09','%e-%b-%y'),160.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Jul-09','%e-%b-%y'),160);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jul-09','%e-%b-%y'),160.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jul-09','%e-%b-%y'),159.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jul-09','%e-%b-%y'),157.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jul-09','%e-%b-%y'),156.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jul-09','%e-%b-%y'),151.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jul-09','%e-%b-%y'),152.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jul-09','%e-%b-%y'),151.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jul-09','%e-%b-%y'),147.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jul-09','%e-%b-%y'),146.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jul-09','%e-%b-%y'),142.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jul-09','%e-%b-%y'),142.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jul-09','%e-%b-%y'),138.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jul-09','%e-%b-%y'),136.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jul-09','%e-%b-%y'),137.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jul-09','%e-%b-%y'),135.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jul-09','%e-%b-%y'),138.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jul-09','%e-%b-%y'),140.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jul-09','%e-%b-%y'),140.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-09','%e-%b-%y'),142.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jun-09','%e-%b-%y'),142.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jun-09','%e-%b-%y'),141.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jun-09','%e-%b-%y'),142.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jun-09','%e-%b-%y'),139.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jun-09','%e-%b-%y'),136.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-09','%e-%b-%y'),134.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jun-09','%e-%b-%y'),137.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jun-09','%e-%b-%y'),139.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jun-09','%e-%b-%y'),135.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-09','%e-%b-%y'),135.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Jun-09','%e-%b-%y'),136.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jun-09','%e-%b-%y'),136.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jun-09','%e-%b-%y'),136.97);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jun-09','%e-%b-%y'),139.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jun-09','%e-%b-%y'),140.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-09','%e-%b-%y'),142.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Jun-09','%e-%b-%y'),143.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jun-09','%e-%b-%y'),144.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jun-09','%e-%b-%y'),143.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-09','%e-%b-%y'),140.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jun-09','%e-%b-%y'),139.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jun-09','%e-%b-%y'),139.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-May-09','%e-%b-%y'),135.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-May-09','%e-%b-%y'),135.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-May-09','%e-%b-%y'),133.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-May-09','%e-%b-%y'),130.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-May-09','%e-%b-%y'),122.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-09','%e-%b-%y'),124.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-May-09','%e-%b-%y'),125.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-09','%e-%b-%y'),127.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-09','%e-%b-%y'),126.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-May-09','%e-%b-%y'),122.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-09','%e-%b-%y'),122.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-09','%e-%b-%y'),119.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-May-09','%e-%b-%y'),124.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-09','%e-%b-%y'),129.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-May-09','%e-%b-%y'),129.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-09','%e-%b-%y'),129.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-09','%e-%b-%y'),132.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-09','%e-%b-%y'),132.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-May-09','%e-%b-%y'),132.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-May-09','%e-%b-%y'),127.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Apr-09','%e-%b-%y'),125.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-09','%e-%b-%y'),125.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-09','%e-%b-%y'),123.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-09','%e-%b-%y'),124.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Apr-09','%e-%b-%y'),123.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-09','%e-%b-%y'),125.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Apr-09','%e-%b-%y'),121.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-09','%e-%b-%y'),121.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Apr-09','%e-%b-%y'),120.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Apr-09','%e-%b-%y'),123.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Apr-09','%e-%b-%y'),121.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-09','%e-%b-%y'),117.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Apr-09','%e-%b-%y'),118.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Apr-09','%e-%b-%y'),120.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Apr-09','%e-%b-%y'),119.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-09','%e-%b-%y'),119.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Apr-09','%e-%b-%y'),116.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-09','%e-%b-%y'),115);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Apr-09','%e-%b-%y'),118.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-09','%e-%b-%y'),115.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-09','%e-%b-%y'),112.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-09','%e-%b-%y'),108.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('31-Mar-09','%e-%b-%y'),105.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-09','%e-%b-%y'),104.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Mar-09','%e-%b-%y'),106.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-09','%e-%b-%y'),109.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-09','%e-%b-%y'),106.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-09','%e-%b-%y'),106.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-09','%e-%b-%y'),107.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Mar-09','%e-%b-%y'),101.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-09','%e-%b-%y'),101.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Mar-09','%e-%b-%y'),101.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Mar-09','%e-%b-%y'),99.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-09','%e-%b-%y'),95.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Mar-09','%e-%b-%y'),95.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-09','%e-%b-%y'),96.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Mar-09','%e-%b-%y'),92.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Mar-09','%e-%b-%y'),88.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-09','%e-%b-%y'),83.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Mar-09','%e-%b-%y'),85.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Mar-09','%e-%b-%y'),88.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Mar-09','%e-%b-%y'),91.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Mar-09','%e-%b-%y'),88.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-09','%e-%b-%y'),87.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Feb-09','%e-%b-%y'),89.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-09','%e-%b-%y'),89.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Feb-09','%e-%b-%y'),91.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Feb-09','%e-%b-%y'),90.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Feb-09','%e-%b-%y'),86.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Feb-09','%e-%b-%y'),91.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-09','%e-%b-%y'),90.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-09','%e-%b-%y'),94.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-09','%e-%b-%y'),94.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Feb-09','%e-%b-%y'),99.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Feb-09','%e-%b-%y'),99.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Feb-09','%e-%b-%y'),96.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Feb-09','%e-%b-%y'),97.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Feb-09','%e-%b-%y'),102.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Feb-09','%e-%b-%y'),99.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Feb-09','%e-%b-%y'),96.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Feb-09','%e-%b-%y'),93.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Feb-09','%e-%b-%y'),92.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Feb-09','%e-%b-%y'),91.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jan-09','%e-%b-%y'),90.13);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Jan-09','%e-%b-%y'),93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jan-09','%e-%b-%y'),94.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jan-09','%e-%b-%y'),90.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jan-09','%e-%b-%y'),89.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jan-09','%e-%b-%y'),88.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jan-09','%e-%b-%y'),88.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Jan-09','%e-%b-%y'),82.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jan-09','%e-%b-%y'),78.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jan-09','%e-%b-%y'),82.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-09','%e-%b-%y'),83.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jan-09','%e-%b-%y'),85.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jan-09','%e-%b-%y'),87.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Jan-09','%e-%b-%y'),88.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jan-09','%e-%b-%y'),90.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jan-09','%e-%b-%y'),92.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-09','%e-%b-%y'),91.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jan-09','%e-%b-%y'),93.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jan-09','%e-%b-%y'),94.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jan-09','%e-%b-%y'),90.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jan-09','%e-%b-%y'),85.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Dec-08','%e-%b-%y'),85.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-08','%e-%b-%y'),86.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Dec-08','%e-%b-%y'),86.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Dec-08','%e-%b-%y'),85.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Dec-08','%e-%b-%y'),85.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-08','%e-%b-%y'),85.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-08','%e-%b-%y'),86.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-08','%e-%b-%y'),85.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Dec-08','%e-%b-%y'),90);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-08','%e-%b-%y'),89.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Dec-08','%e-%b-%y'),89.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-08','%e-%b-%y'),95.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-08','%e-%b-%y'),94.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Dec-08','%e-%b-%y'),98.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Dec-08','%e-%b-%y'),95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-08','%e-%b-%y'),98.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Dec-08','%e-%b-%y'),100.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-08','%e-%b-%y'),99.72);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Dec-08','%e-%b-%y'),94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-08','%e-%b-%y'),91.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Dec-08','%e-%b-%y'),95.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-08','%e-%b-%y'),92.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Dec-08','%e-%b-%y'),88.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Nov-08','%e-%b-%y'),92.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-08','%e-%b-%y'),95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-08','%e-%b-%y'),95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Nov-08','%e-%b-%y'),90.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Nov-08','%e-%b-%y'),92.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Nov-08','%e-%b-%y'),82.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Nov-08','%e-%b-%y'),80.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Nov-08','%e-%b-%y'),86.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-08','%e-%b-%y'),89.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Nov-08','%e-%b-%y'),88.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Nov-08','%e-%b-%y'),90.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Nov-08','%e-%b-%y'),96.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Nov-08','%e-%b-%y'),90.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Nov-08','%e-%b-%y'),94.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-08','%e-%b-%y'),95.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Nov-08','%e-%b-%y'),98.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Nov-08','%e-%b-%y'),99.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Nov-08','%e-%b-%y'),103.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-08','%e-%b-%y'),110.99);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Nov-08','%e-%b-%y'),106.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Oct-08','%e-%b-%y'),107.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Oct-08','%e-%b-%y'),111.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Oct-08','%e-%b-%y'),104.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Oct-08','%e-%b-%y'),99.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-08','%e-%b-%y'),92.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Oct-08','%e-%b-%y'),96.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Oct-08','%e-%b-%y'),98.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Oct-08','%e-%b-%y'),96.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-08','%e-%b-%y'),91.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Oct-08','%e-%b-%y'),98.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Oct-08','%e-%b-%y'),97.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Oct-08','%e-%b-%y'),101.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Oct-08','%e-%b-%y'),97.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Oct-08','%e-%b-%y'),104.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-08','%e-%b-%y'),110.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Oct-08','%e-%b-%y'),96.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Oct-08','%e-%b-%y'),88.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Oct-08','%e-%b-%y'),89.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-08','%e-%b-%y'),89.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Oct-08','%e-%b-%y'),98.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Oct-08','%e-%b-%y'),97.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Oct-08','%e-%b-%y'),100.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Oct-08','%e-%b-%y'),109.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Sep-08','%e-%b-%y'),113.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-08','%e-%b-%y'),105.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Sep-08','%e-%b-%y'),128.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Sep-08','%e-%b-%y'),131.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Sep-08','%e-%b-%y'),128.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-08','%e-%b-%y'),126.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Sep-08','%e-%b-%y'),131.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Sep-08','%e-%b-%y'),140.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Sep-08','%e-%b-%y'),134.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Sep-08','%e-%b-%y'),127.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Sep-08','%e-%b-%y'),139.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-08','%e-%b-%y'),140.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Sep-08','%e-%b-%y'),148.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Sep-08','%e-%b-%y'),152.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Sep-08','%e-%b-%y'),151.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-08','%e-%b-%y'),151.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Sep-08','%e-%b-%y'),157.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Sep-08','%e-%b-%y'),160.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Sep-08','%e-%b-%y'),161.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Sep-08','%e-%b-%y'),166.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Sep-08','%e-%b-%y'),166.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Aug-08','%e-%b-%y'),169.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Aug-08','%e-%b-%y'),173.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-08','%e-%b-%y'),174.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-08','%e-%b-%y'),173.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-08','%e-%b-%y'),172.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Aug-08','%e-%b-%y'),176.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Aug-08','%e-%b-%y'),174.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Aug-08','%e-%b-%y'),175.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-08','%e-%b-%y'),173.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-08','%e-%b-%y'),175.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Aug-08','%e-%b-%y'),175.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Aug-08','%e-%b-%y'),179.32);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-08','%e-%b-%y'),179.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Aug-08','%e-%b-%y'),176.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-08','%e-%b-%y'),173.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Aug-08','%e-%b-%y'),169.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Aug-08','%e-%b-%y'),163.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Aug-08','%e-%b-%y'),164.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-08','%e-%b-%y'),160.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Aug-08','%e-%b-%y'),153.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Aug-08','%e-%b-%y'),156.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Jul-08','%e-%b-%y'),158.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jul-08','%e-%b-%y'),159.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-08','%e-%b-%y'),157.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-08','%e-%b-%y'),154.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jul-08','%e-%b-%y'),162.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jul-08','%e-%b-%y'),159.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jul-08','%e-%b-%y'),166.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-08','%e-%b-%y'),162.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-08','%e-%b-%y'),166.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jul-08','%e-%b-%y'),165.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Jul-08','%e-%b-%y'),171.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jul-08','%e-%b-%y'),172.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jul-08','%e-%b-%y'),169.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-08','%e-%b-%y'),173.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jul-08','%e-%b-%y'),172.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jul-08','%e-%b-%y'),176.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Jul-08','%e-%b-%y'),174.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-08','%e-%b-%y'),179.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jul-08','%e-%b-%y'),175.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jul-08','%e-%b-%y'),170.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jul-08','%e-%b-%y'),168.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-08','%e-%b-%y'),174.68);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Jun-08','%e-%b-%y'),167.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jun-08','%e-%b-%y'),170.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jun-08','%e-%b-%y'),168.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jun-08','%e-%b-%y'),177.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jun-08','%e-%b-%y'),173.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-08','%e-%b-%y'),173.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jun-08','%e-%b-%y'),175.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jun-08','%e-%b-%y'),180.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jun-08','%e-%b-%y'),178.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-08','%e-%b-%y'),181.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jun-08','%e-%b-%y'),176.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jun-08','%e-%b-%y'),172.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Jun-08','%e-%b-%y'),173.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jun-08','%e-%b-%y'),180.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jun-08','%e-%b-%y'),185.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-08','%e-%b-%y'),181.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jun-08','%e-%b-%y'),185.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jun-08','%e-%b-%y'),189.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Jun-08','%e-%b-%y'),185.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-08','%e-%b-%y'),185.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jun-08','%e-%b-%y'),186.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-May-08','%e-%b-%y'),188.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-May-08','%e-%b-%y'),186.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-May-08','%e-%b-%y'),187.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-May-08','%e-%b-%y'),186.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-May-08','%e-%b-%y'),181.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-May-08','%e-%b-%y'),177.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-08','%e-%b-%y'),178.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-May-08','%e-%b-%y'),185.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-08','%e-%b-%y'),183.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-May-08','%e-%b-%y'),187.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-May-08','%e-%b-%y'),189.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-08','%e-%b-%y'),186.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-08','%e-%b-%y'),189.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-May-08','%e-%b-%y'),188.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-May-08','%e-%b-%y'),183.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-May-08','%e-%b-%y'),185.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-08','%e-%b-%y'),182.59);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-08','%e-%b-%y'),186.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-08','%e-%b-%y'),184.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-May-08','%e-%b-%y'),180.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-May-08','%e-%b-%y'),180);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Apr-08','%e-%b-%y'),173.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-08','%e-%b-%y'),175.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-08','%e-%b-%y'),172.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Apr-08','%e-%b-%y'),169.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Apr-08','%e-%b-%y'),168.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-08','%e-%b-%y'),162.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Apr-08','%e-%b-%y'),160.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-08','%e-%b-%y'),168.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Apr-08','%e-%b-%y'),161.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Apr-08','%e-%b-%y'),154.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Apr-08','%e-%b-%y'),153.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-08','%e-%b-%y'),148.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Apr-08','%e-%b-%y'),147.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Apr-08','%e-%b-%y'),147.14);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Apr-08','%e-%b-%y'),154.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-08','%e-%b-%y'),151.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Apr-08','%e-%b-%y'),152.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-08','%e-%b-%y'),155.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Apr-08','%e-%b-%y'),153.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-08','%e-%b-%y'),151.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-08','%e-%b-%y'),147.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-08','%e-%b-%y'),149.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Mar-08','%e-%b-%y'),143.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Mar-08','%e-%b-%y'),143.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Mar-08','%e-%b-%y'),140.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-08','%e-%b-%y'),145.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-08','%e-%b-%y'),140.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-08','%e-%b-%y'),139.53);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Mar-08','%e-%b-%y'),133.27);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Mar-08','%e-%b-%y'),129.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Mar-08','%e-%b-%y'),132.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Mar-08','%e-%b-%y'),126.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Mar-08','%e-%b-%y'),126.61);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Mar-08','%e-%b-%y'),127.94);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Mar-08','%e-%b-%y'),126.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Mar-08','%e-%b-%y'),127.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Mar-08','%e-%b-%y'),119.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Mar-08','%e-%b-%y'),122.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Mar-08','%e-%b-%y'),120.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Mar-08','%e-%b-%y'),124.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Mar-08','%e-%b-%y'),124.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Mar-08','%e-%b-%y'),121.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Feb-08','%e-%b-%y'),125.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Feb-08','%e-%b-%y'),129.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Feb-08','%e-%b-%y'),122.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-08','%e-%b-%y'),119.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Feb-08','%e-%b-%y'),119.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Feb-08','%e-%b-%y'),119.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Feb-08','%e-%b-%y'),121.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Feb-08','%e-%b-%y'),123.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-08','%e-%b-%y'),122.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Feb-08','%e-%b-%y'),124.63);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Feb-08','%e-%b-%y'),127.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Feb-08','%e-%b-%y'),129.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Feb-08','%e-%b-%y'),124.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Feb-08','%e-%b-%y'),129.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Feb-08','%e-%b-%y'),125.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Feb-08','%e-%b-%y'),121.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Feb-08','%e-%b-%y'),122);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Feb-08','%e-%b-%y'),129.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Feb-08','%e-%b-%y'),131.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Feb-08','%e-%b-%y'),133.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Jan-08','%e-%b-%y'),135.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jan-08','%e-%b-%y'),132.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jan-08','%e-%b-%y'),131.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jan-08','%e-%b-%y'),130.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jan-08','%e-%b-%y'),130.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jan-08','%e-%b-%y'),135.6);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jan-08','%e-%b-%y'),139.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jan-08','%e-%b-%y'),155.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-08','%e-%b-%y'),161.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jan-08','%e-%b-%y'),160.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Jan-08','%e-%b-%y'),159.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-08','%e-%b-%y'),169.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jan-08','%e-%b-%y'),178.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jan-08','%e-%b-%y'),172.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jan-08','%e-%b-%y'),178.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jan-08','%e-%b-%y'),179.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Jan-08','%e-%b-%y'),171.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-08','%e-%b-%y'),177.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jan-08','%e-%b-%y'),180.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jan-08','%e-%b-%y'),194.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jan-08','%e-%b-%y'),194.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Dec-07','%e-%b-%y'),198.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Dec-07','%e-%b-%y'),199.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Dec-07','%e-%b-%y'),198.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Dec-07','%e-%b-%y'),198.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-07','%e-%b-%y'),198.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Dec-07','%e-%b-%y'),193.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Dec-07','%e-%b-%y'),187.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Dec-07','%e-%b-%y'),183.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-07','%e-%b-%y'),182.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Dec-07','%e-%b-%y'),184.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-07','%e-%b-%y'),190.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Dec-07','%e-%b-%y'),191.83);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Dec-07','%e-%b-%y'),190.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Dec-07','%e-%b-%y'),188.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-07','%e-%b-%y'),194.21);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-07','%e-%b-%y'),194.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Dec-07','%e-%b-%y'),189.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Dec-07','%e-%b-%y'),185.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-07','%e-%b-%y'),179.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Dec-07','%e-%b-%y'),178.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-07','%e-%b-%y'),182.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Nov-07','%e-%b-%y'),184.29);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Nov-07','%e-%b-%y'),180.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-07','%e-%b-%y'),174.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-07','%e-%b-%y'),172.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Nov-07','%e-%b-%y'),171.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Nov-07','%e-%b-%y'),168.46);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Nov-07','%e-%b-%y'),168.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Nov-07','%e-%b-%y'),163.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Nov-07','%e-%b-%y'),166.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Nov-07','%e-%b-%y'),164.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Nov-07','%e-%b-%y'),166.11);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Nov-07','%e-%b-%y'),169.96);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Nov-07','%e-%b-%y'),153.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Nov-07','%e-%b-%y'),165.37);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Nov-07','%e-%b-%y'),175.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Nov-07','%e-%b-%y'),186.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Nov-07','%e-%b-%y'),191.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Nov-07','%e-%b-%y'),186.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Nov-07','%e-%b-%y'),187.87);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Nov-07','%e-%b-%y'),187.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Oct-07','%e-%b-%y'),189.95);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Oct-07','%e-%b-%y'),187);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Oct-07','%e-%b-%y'),185.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Oct-07','%e-%b-%y'),184.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Oct-07','%e-%b-%y'),182.78);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Oct-07','%e-%b-%y'),185.93);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Oct-07','%e-%b-%y'),186.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Oct-07','%e-%b-%y'),174.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Oct-07','%e-%b-%y'),170.42);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Oct-07','%e-%b-%y'),173.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Oct-07','%e-%b-%y'),172.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Oct-07','%e-%b-%y'),169.58);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Oct-07','%e-%b-%y'),166.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Oct-07','%e-%b-%y'),167.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Oct-07','%e-%b-%y'),162.23);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Oct-07','%e-%b-%y'),166.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Oct-07','%e-%b-%y'),167.86);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Oct-07','%e-%b-%y'),167.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Oct-07','%e-%b-%y'),161.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Oct-07','%e-%b-%y'),156.24);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Oct-07','%e-%b-%y'),157.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Oct-07','%e-%b-%y'),158.45);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Oct-07','%e-%b-%y'),156.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Sep-07','%e-%b-%y'),153.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Sep-07','%e-%b-%y'),154.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Sep-07','%e-%b-%y'),152.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Sep-07','%e-%b-%y'),153.18);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Sep-07','%e-%b-%y'),148.28);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Sep-07','%e-%b-%y'),144.15);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Sep-07','%e-%b-%y'),140.31);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Sep-07','%e-%b-%y'),140.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Sep-07','%e-%b-%y'),140.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Sep-07','%e-%b-%y'),138.41);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Sep-07','%e-%b-%y'),138.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Sep-07','%e-%b-%y'),137.2);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Sep-07','%e-%b-%y'),136.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Sep-07','%e-%b-%y'),135.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Sep-07','%e-%b-%y'),136.71);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Sep-07','%e-%b-%y'),131.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Sep-07','%e-%b-%y'),135.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Sep-07','%e-%b-%y'),136.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Sep-07','%e-%b-%y'),144.16);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Aug-07','%e-%b-%y'),138.48);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Aug-07','%e-%b-%y'),136.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Aug-07','%e-%b-%y'),134.08);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Aug-07','%e-%b-%y'),126.82);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Aug-07','%e-%b-%y'),132.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Aug-07','%e-%b-%y'),135.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Aug-07','%e-%b-%y'),131.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Aug-07','%e-%b-%y'),132.51);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Aug-07','%e-%b-%y'),127.57);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Aug-07','%e-%b-%y'),122.22);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Aug-07','%e-%b-%y'),122.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Aug-07','%e-%b-%y'),117.05);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Aug-07','%e-%b-%y'),119.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Aug-07','%e-%b-%y'),124.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Aug-07','%e-%b-%y'),127.79);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Aug-07','%e-%b-%y'),125);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Aug-07','%e-%b-%y'),126.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Aug-07','%e-%b-%y'),134.01);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Aug-07','%e-%b-%y'),135.03);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Aug-07','%e-%b-%y'),135.25);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Aug-07','%e-%b-%y'),131.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Aug-07','%e-%b-%y'),136.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Aug-07','%e-%b-%y'),135);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jul-07','%e-%b-%y'),131.76);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jul-07','%e-%b-%y'),141.43);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jul-07','%e-%b-%y'),143.85);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Jul-07','%e-%b-%y'),146);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jul-07','%e-%b-%y'),137.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jul-07','%e-%b-%y'),134.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jul-07','%e-%b-%y'),143.7);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jul-07','%e-%b-%y'),143.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jul-07','%e-%b-%y'),140);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Jul-07','%e-%b-%y'),138.12);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jul-07','%e-%b-%y'),138.91);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jul-07','%e-%b-%y'),138.1);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jul-07','%e-%b-%y'),137.73);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jul-07','%e-%b-%y'),134.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jul-07','%e-%b-%y'),132.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jul-07','%e-%b-%y'),132.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jul-07','%e-%b-%y'),130.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jul-07','%e-%b-%y'),132.3);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jul-07','%e-%b-%y'),132.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jul-07','%e-%b-%y'),127.17);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jul-07','%e-%b-%y'),121.26);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Jun-07','%e-%b-%y'),122.04);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jun-07','%e-%b-%y'),120.56);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jun-07','%e-%b-%y'),121.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jun-07','%e-%b-%y'),119.65);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Jun-07','%e-%b-%y'),122.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jun-07','%e-%b-%y'),123);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Jun-07','%e-%b-%y'),123.9);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jun-07','%e-%b-%y'),121.55);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Jun-07','%e-%b-%y'),123.66);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jun-07','%e-%b-%y'),125.09);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jun-07','%e-%b-%y'),120.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jun-07','%e-%b-%y'),118.75);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jun-07','%e-%b-%y'),117.5);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jun-07','%e-%b-%y'),120.38);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jun-07','%e-%b-%y'),120.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jun-07','%e-%b-%y'),124.49);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jun-07','%e-%b-%y'),124.07);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jun-07','%e-%b-%y'),123.64);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jun-07','%e-%b-%y'),122.67);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jun-07','%e-%b-%y'),121.33);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Jun-07','%e-%b-%y'),118.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-May-07','%e-%b-%y'),121.19);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-May-07','%e-%b-%y'),118.77);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-May-07','%e-%b-%y'),114.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-May-07','%e-%b-%y'),113.62);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-May-07','%e-%b-%y'),110.69);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-May-07','%e-%b-%y'),112.89);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-May-07','%e-%b-%y'),113.54);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-May-07','%e-%b-%y'),111.98);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-May-07','%e-%b-%y'),110.02);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-May-07','%e-%b-%y'),109.44);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-May-07','%e-%b-%y'),107.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-May-07','%e-%b-%y'),107.52);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-May-07','%e-%b-%y'),109.36);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-May-07','%e-%b-%y'),108.74);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-May-07','%e-%b-%y'),107.34);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-May-07','%e-%b-%y'),106.88);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-May-07','%e-%b-%y'),105.06);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-May-07','%e-%b-%y'),103.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-May-07','%e-%b-%y'),100.81);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-May-07','%e-%b-%y'),100.4);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-May-07','%e-%b-%y'),100.39);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-May-07','%e-%b-%y'),99.47);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Apr-07','%e-%b-%y'),99.8);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Apr-07','%e-%b-%y'),99.92);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Apr-07','%e-%b-%y'),98.84);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Apr-07','%e-%b-%y'),95.35);
+Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Apr-07','%e-%b-%y'),93.24);
+
+-- DEMO_PIE_CHART
+Insert into demo_pie_chart (legend, data_value) values ('One', 5);
+Insert into demo_pie_chart (legend, data_value) values ('Two', 2);
+Insert into demo_pie_chart (legend, data_value) values ('Three', 9);
+Insert into demo_pie_chart (legend, data_value) values ('Four', 7);
+Insert into demo_pie_chart (legend, data_value) values ('Five', 4);
+Insert into demo_pie_chart (legend, data_value) values ('Six', 3);
+Insert into demo_pie_chart (legend, data_value) values ('Seven', .5);
+
+
+-- DEMO_SCATTER_CHART
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.1, 'Particulate', 122);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.3, 'Particulate', 117);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.7, 'Particulate', 112);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.4, 'Particulate', 114);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.9, 'Particulate', 110);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.0, 'Particulate', 114);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (3.6, 'Particulate', 128);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (1.9, 'Particulate', 137);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.3, 'Particulate', 104);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (6.9, 'Humidity', 119);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.9, 'Humidity', 118);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (9.8, 'Humidity', 103);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.9, 'Humidity', 137);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (6.8, 'Humidity', 102);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.7, 'Humidity', 89);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (2.7, 'Humidity', 98);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (3.7, 'Humidity', 145);
+Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.4, 'Humidity', 118);
+
+-- DEMO_SCATTER_PLOT
+
+-- SET DEFINE OFF;
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -46.5901128883449, -464.477370615131);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -85.0293361247543, -362.252178232471);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 70.9700275365898, 402.214363675566);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -50.1110580054506, -310.108907443154);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 85.043005750476, 813.481841353449);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -14.2356123424179, -134.200903707809);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -66.7014933188071, -445.754374526706);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -79.941582021797, -694.089097548454);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -64.4665101305822, -431.660620986243);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 13.718818366452, 100.010719918027);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 35.457456199233, 223.254643848734);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 55.2326402548387, 268.940835852805);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -32.9989160276248, -237.280626944034);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -0.464911506111831, -2.65656324666862);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -59.0205101710777, -498.895652307826);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 28.0939970575828, 117.200615553207);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 31.7305239061572, 186.662624012256);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 50.9035126419798, 440.937283203403);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 58.3875046571053, 547.879249694999);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 76.7846997917459, 525.020578968308);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 1.73485745801611, 7.28149474936192);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 15.304841061276, 71.2374666595537);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 75.1342455000693, 381.145932349436);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -58.2087417684623, -573.630956069476);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 76.7977837302114, 624.733726327778);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 56.3295585433654, 309.697529902676);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -9.27601440680639, -49.5126219388194);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 98.3002030040236, 765.653589829535);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -25.0987502451517, -174.651201240269);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 39.9215299020147, 337.889176256456);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 77.9225832868337, 356.183903852096);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 75.4311841137638, 14.5258766665983);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 58.9445375968278, 376.359576288564);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', 46.9521897141796, 3.5679984193934);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -49.0378307695689, -230.816092788509);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -96.2461776340861, -863.765255159092);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -96.3388912796447, -538.147283544646);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -21.4684477767032, -200.140077054848);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -30.3532837083366, -226.462637188158);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample0', -17.5055590488884, -118.709622452841);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 56.6394671790491, 385.48951169801);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 70.4622912302344, 356.986529538635);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 58.2647422222769, 489.418744916999);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -92.16093253903, -425.576081634713);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -2.64574970943097, -26.190027661226);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -16.7568654181289, -117.460886096034);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 68.215377945908, 606.917788617984);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 53.7387814434413, 367.53491797949);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -51.8861573715238, -289.998186955562);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -15.9721784074351, -75.335027134323);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 63.2540648905791, 602.546517566905);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -53.376167960458, -470.921238684285);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 40.8307443439851, 276.112653117961);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -13.0540977188468, -127.648158921993);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -43.7358336047599, -435.080470107322);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -74.5673321340732, -617.960236798371);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -6.47907144443936, -55.654651151187);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 68.1915507628225, 352.320728639801);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -23.5393521654339, -137.714557244391);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 28.3621412621467, 141.103859877604);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -99.5615230664525, -974.857161307048);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -77.7132553058204, -736.182131225006);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 95.9321864873013, 478.286112499176);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 97.7451855292708, 940.301427763062);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -10.2483179758141, -70.1145330070458);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -24.0750124187893, -113.523998470537);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -5.5721118558967, -43.8516395203455);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -55.5378338160537, -368.506951528332);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 52.6669516338013, 38.2926120131942);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -74.1981412067658, -436.990411988621);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -8.70511941690364, -71.3277811558721);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 63.2921735621378, 534.825008407329);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 97.9066635843841, 678.994971737474);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -83.1613916743288, -494.53303650568);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 23.4730547863992, 223.031148353333);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 40.6105099506845, 199.937366405274);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 35.4473225526307, 331.61786915261);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 27.2050975460142, 146.277993239147);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', -1.54684302938646, -12.6706471561247);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample1', 45.8386162291745, 401.780882699918);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 43.4241956158593, 228.71488367607);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -23.4517134254585, -165.958577325218);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -98.8954664030229, -829.964553125469);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 48.0527046113198, 451.527720751234);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -77.8912947988124, -416.867729852279);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 23.8325471824168, 206.907438743452);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 83.2787398847467, 814.01250022556);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 49.1572992549647, 451.03037365466);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -11.1351768833872, -57.3863334655361);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 71.1980242104626, 572.745863967841);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 15.0952976022392, 103.30274980367);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 75.0300005037414, 406.581640027236);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -82.0092720309019, -690.340287049552);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 40.2433497232209, 363.579616486762);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 26.8157962678174, 262.150124949525);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -83.9563210001448, -432.739081022174);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -20.6480437627346, -161.330015497217);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 37.1388896882226, 161.352404658606);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 20.2126667486174, 168.833789818416);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 58.3723632769494, 293.206814023827);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -20.2876832456236, -88.0090685884954);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 72.9768050433371, 691.684023528398);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -21.6612128833675, -130.834158714088);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 97.4870524045038, 806.47904449193);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 60.6688063197852, 255.749289305775);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -44.235772358471, -336.262226570567);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -47.39573087854, -321.133647936626);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -24.7522484346097, -204.548308435727);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -42.903238078129, -239.651563752902);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 20.4656734934697, 172.700213789797);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 56.0665747085147, 365.360390019834);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 31.9979219049038, 237.490140339893);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -29.9884426739069, -203.821484170813);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 13.5011085362703, 79.4784314297668);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 41.8402945507358, 297.04934398378);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -84.9323678979223, -345.2331996232);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', -42.2469964847455, -361.468816319656);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 98.1057699772752, 445.181262282444);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 95.5327901766563, 522.663100406047);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample2', 35.0916611161316, 246.796980313209);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 99.3987950082867, 401.97428571655);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -3.0419413965969, -14.5325761725203);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -79.388026451666, -701.817589967372);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -88.451242397524, -668.370526000304);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 34.3131838963851, 254.418322223563);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -61.518208630511, -347.521623572776);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 45.6124480237487, 356.33565541369);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -1.0716036518037, -7.80544934354423);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 31.7371714687412, 283.925868763573);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -76.771029786315, -626.268489584739);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -67.913690110843, -614.736930677921);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 34.9311671860034, 171.384205820777);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 94.3264454603021, 914.267819214392);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 76.7493996267558, 705.649611960615);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -87.795202856922, -749.505178721718);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 2.10914716736019, 15.4036733330536);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -50.456669557937, -318.410608422062);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -94.646644883092, -734.660992935541);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 34.9170862075359, 347.583881438806);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 44.3524585090071, 294.615219199443);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -67.191016143335, -609.956472872497);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -78.826443879164, -369.129912603377);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -50.427554400015, -418.144241602024);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -70.371769526721, -307.02193189609);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 16.3220947890044, 97.0997346831135);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -47.067245718878, -398.27032236792);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 5.91206661301702, 24.7239863780181);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -99.621681801868, -843.593457399484);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 87.4503492670535, 695.345037859433);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -91.176921118057, -683.305064255346);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -0.6632900001386, -5.34157539224209);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 2.98188785882178, 12.1181973600389);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 30.6008700087597, 205.922863867274);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 7.90348761612496, 65.5271597329641);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 40.3565229854156, 268.058138389501);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 37.6892733312091, 247.519083233639);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 16.4759733864001, 107.72661087278);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -53.578492311122, -369.768816039059);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', 77.1292326560541, 765.262108306778);
+Insert into demo_scatter_plot
+ (SERIES, VALUEX, VALUEY)
+ Values
+ ('Sample3', -79.566811593352, -677.545127214159);
+
+-- DEMO_UTIL_CHART
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-17','%Y-%m-%d'),53.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-10','%Y-%m-%d'),62.95747);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-21','%Y-%m-%d'),48.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-22','%Y-%m-%d'),51.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-11','%Y-%m-%d'),56.13373);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-23','%Y-%m-%d'),53.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-12','%Y-%m-%d'),57.05287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-24','%Y-%m-%d'),51.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-13','%Y-%m-%d'),55.78947);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-25','%Y-%m-%d'),54.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-14','%Y-%m-%d'),63.34907);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-26','%Y-%m-%d'),50.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-15','%Y-%m-%d'),52.21327);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-27','%Y-%m-%d'),48.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-16','%Y-%m-%d'),51.32080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-28','%Y-%m-%d'),50.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-17','%Y-%m-%d'),58.35720);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-29','%Y-%m-%d'),51.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-18','%Y-%m-%d'),57.62293);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-30','%Y-%m-%d'),67.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-19','%Y-%m-%d'),55.25000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-01','%Y-%m-%d'),59.89393);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-20','%Y-%m-%d'),58.79573);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-02','%Y-%m-%d'),61.20753);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-21','%Y-%m-%d'),54.09720);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-03','%Y-%m-%d'),58.98340);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-22','%Y-%m-%d'),59.95813);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-04','%Y-%m-%d'),59.55873);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-23','%Y-%m-%d'),62.03067);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-05','%Y-%m-%d'),58.73680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-24','%Y-%m-%d'),61.97620);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-06','%Y-%m-%d'),59.89967);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-25','%Y-%m-%d'),58.00207);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-07','%Y-%m-%d'),60.67973);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-26','%Y-%m-%d'),59.95440);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-08','%Y-%m-%d'),60.85913);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-27','%Y-%m-%d'),55.43747);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-09','%Y-%m-%d'),60.62460);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-28','%Y-%m-%d'),52.53933);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-10','%Y-%m-%d'),59.51887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-29','%Y-%m-%d'),57.46260);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-11','%Y-%m-%d'),61.57187);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-30','%Y-%m-%d'),60.04787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-12','%Y-%m-%d'),60.70000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-31','%Y-%m-%d'),58.79480);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-13','%Y-%m-%d'),69.85133);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-01','%Y-%m-%d'),54.40107);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-14','%Y-%m-%d'),68.99620);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-02','%Y-%m-%d'),62.26007);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-15','%Y-%m-%d'),67.64080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-03','%Y-%m-%d'),60.72360);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-16','%Y-%m-%d'),59.71433);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-04','%Y-%m-%d'),60.95847);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-17','%Y-%m-%d'),59.99667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-05','%Y-%m-%d'),59.45920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-18','%Y-%m-%d'),63.27207);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-06','%Y-%m-%d'),60.58620);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-19','%Y-%m-%d'),60.32080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-07','%Y-%m-%d'),61.94207);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-20','%Y-%m-%d'),57.32907);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-08','%Y-%m-%d'),59.03327);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-21','%Y-%m-%d'),59.76933);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-09','%Y-%m-%d'),62.83087);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-22','%Y-%m-%d'),59.12453);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-10','%Y-%m-%d'),59.36840);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-23','%Y-%m-%d'),57.10167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-11','%Y-%m-%d'),56.11480);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-24','%Y-%m-%d'),58.45820);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-12','%Y-%m-%d'),62.23393);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-25','%Y-%m-%d'),59.45440);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-13','%Y-%m-%d'),59.72313);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-26','%Y-%m-%d'),60.12807);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-14','%Y-%m-%d'),53.37093);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-27','%Y-%m-%d'),59.11760);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-15','%Y-%m-%d'),52.99233);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-28','%Y-%m-%d'),57.32020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-16','%Y-%m-%d'),55.99080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-29','%Y-%m-%d'),59.80360);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-17','%Y-%m-%d'),53.93853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-30','%Y-%m-%d'),66.73280);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-18','%Y-%m-%d'),55.99313);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-31','%Y-%m-%d'),58.78673);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-19','%Y-%m-%d'),68.23393);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-01','%Y-%m-%d'),58.82773);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-20','%Y-%m-%d'),61.86213);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-02','%Y-%m-%d'),63.12100);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-21','%Y-%m-%d'),61.20307);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-03','%Y-%m-%d'),59.70467);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-22','%Y-%m-%d'),61.05900);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-04','%Y-%m-%d'),58.85173);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-23','%Y-%m-%d'),58.41040);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-05','%Y-%m-%d'),61.21880);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-24','%Y-%m-%d'),59.15967);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-06','%Y-%m-%d'),58.99920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-25','%Y-%m-%d'),56.42153);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-07','%Y-%m-%d'),59.94693);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-26','%Y-%m-%d'),60.46580);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-08','%Y-%m-%d'),66.27293);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-27','%Y-%m-%d'),57.44333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-09','%Y-%m-%d'),61.46773);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-28','%Y-%m-%d'),56.88887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-10','%Y-%m-%d'),59.70467);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-29','%Y-%m-%d'),61.85773);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-11','%Y-%m-%d'),60.16000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-30','%Y-%m-%d'),61.96400);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-12','%Y-%m-%d'),61.20300);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-01','%Y-%m-%d'),65.88833);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-13','%Y-%m-%d'),60.95673);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-02','%Y-%m-%d'),62.67920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-14','%Y-%m-%d'),60.70207);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-03','%Y-%m-%d'),63.52047);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-15','%Y-%m-%d'),61.02520);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-04','%Y-%m-%d'),58.60280);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-16','%Y-%m-%d'),60.33953);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-05','%Y-%m-%d'),63.74487);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-17','%Y-%m-%d'),61.20300);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-06','%Y-%m-%d'),59.94880);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-18','%Y-%m-%d'),63.12100);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-07','%Y-%m-%d'),59.44380);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-23','%Y-%m-%d'),61.09153);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-08','%Y-%m-%d'),59.16320);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-24','%Y-%m-%d'),61.28867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-09','%Y-%m-%d'),60.84593);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-25','%Y-%m-%d'),60.95673);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-10','%Y-%m-%d'),58.84113);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-26','%Y-%m-%d'),60.61100);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-11','%Y-%m-%d'),62.59827);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-27','%Y-%m-%d'),61.22913);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-12','%Y-%m-%d'),60.94660);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-28','%Y-%m-%d'),58.88507);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-13','%Y-%m-%d'),59.37593);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-29','%Y-%m-%d'),59.73693);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-14','%Y-%m-%d'),67.21840);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-30','%Y-%m-%d'),62.45307);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-15','%Y-%m-%d'),68.56020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-01','%Y-%m-%d'),61.30167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-16','%Y-%m-%d'),57.56493);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-02','%Y-%m-%d'),62.92727);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-17','%Y-%m-%d'),57.02280);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-03','%Y-%m-%d'),60.05887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-18','%Y-%m-%d'),56.20947);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-06','%Y-%m-%d'),61.20100);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-19','%Y-%m-%d'),55.69353);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-07','%Y-%m-%d'),60.66120);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-20','%Y-%m-%d'),57.17640);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-08','%Y-%m-%d'),59.78180);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-21','%Y-%m-%d'),57.50867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-09','%Y-%m-%d'),58.74653);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-22','%Y-%m-%d'),61.67860);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-10','%Y-%m-%d'),59.77893);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-23','%Y-%m-%d'),57.34867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-11','%Y-%m-%d'),67.34500);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-24','%Y-%m-%d'),61.68080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-12','%Y-%m-%d'),57.07293);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-25','%Y-%m-%d'),55.55793);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-13','%Y-%m-%d'),57.37567);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-26','%Y-%m-%d'),55.81013);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-14','%Y-%m-%d'),63.97820);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-27','%Y-%m-%d'),59.85540);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-15','%Y-%m-%d'),56.06647);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-28','%Y-%m-%d'),61.05073);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-16','%Y-%m-%d'),53.66347);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-29','%Y-%m-%d'),59.81253);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-23','%Y-%m-%d'),56.50813);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-30','%Y-%m-%d'),61.02047);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-24','%Y-%m-%d'),53.19667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-31','%Y-%m-%d'),60.60413);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-25','%Y-%m-%d'),51.57133);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-01','%Y-%m-%d'),57.43067);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-26','%Y-%m-%d'),45.98160);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-02','%Y-%m-%d'),58.63027);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-27','%Y-%m-%d'),49.21113);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-03','%Y-%m-%d'),59.08127);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-28','%Y-%m-%d'),49.67213);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-04','%Y-%m-%d'),59.37373);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-29','%Y-%m-%d'),52.94053);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-05','%Y-%m-%d'),58.13413);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-30','%Y-%m-%d'),57.55727);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-06','%Y-%m-%d'),57.18893);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-31','%Y-%m-%d'),61.76900);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-07','%Y-%m-%d'),56.72853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-01','%Y-%m-%d'),56.51953);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-08','%Y-%m-%d'),56.47340);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-02','%Y-%m-%d'),61.04853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-09','%Y-%m-%d'),62.02333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-03','%Y-%m-%d'),70.06067);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-10','%Y-%m-%d'),61.21787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-04','%Y-%m-%d'),60.97787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-11','%Y-%m-%d'),62.01087);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-05','%Y-%m-%d'),59.25967);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-12','%Y-%m-%d'),62.67573);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-06','%Y-%m-%d'),56.12287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-13','%Y-%m-%d'),59.23993);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-07','%Y-%m-%d'),63.99913);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-14','%Y-%m-%d'),67.34973);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-08','%Y-%m-%d'),58.71127);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-15','%Y-%m-%d'),60.93753);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-09','%Y-%m-%d'),64.01913);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-16','%Y-%m-%d'),54.52607);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-17','%Y-%m-%d'),57.81127);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-18','%Y-%m-%d'),63.53027);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-19','%Y-%m-%d'),58.13000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-20','%Y-%m-%d'),58.46827);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-21','%Y-%m-%d'),65.27807);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-22','%Y-%m-%d'),53.74513);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-23','%Y-%m-%d'),60.99107);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-24','%Y-%m-%d'),60.45427);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-25','%Y-%m-%d'),56.16847);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-26','%Y-%m-%d'),59.04040);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-27','%Y-%m-%d'),54.62040);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-28','%Y-%m-%d'),56.34687);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-29','%Y-%m-%d'),54.81560);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-30','%Y-%m-%d'),60.22753);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-01','%Y-%m-%d'),59.07307);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-02','%Y-%m-%d'),59.73553);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-03','%Y-%m-%d'),68.69447);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-04','%Y-%m-%d'),68.91767);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-05','%Y-%m-%d'),67.86460);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-06','%Y-%m-%d'),64.43120);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-01','%Y-%m-%d'),61.22507);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-07','%Y-%m-%d'),60.67793);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-02','%Y-%m-%d'),63.27533);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-08','%Y-%m-%d'),62.47060);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-03','%Y-%m-%d'),69.88087);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-09','%Y-%m-%d'),58.26053);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-04','%Y-%m-%d'),66.84920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-10','%Y-%m-%d'),61.03340);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-05','%Y-%m-%d'),61.57367);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-11','%Y-%m-%d'),57.32620);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-06','%Y-%m-%d'),60.52293);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-12','%Y-%m-%d'),63.10353);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-07','%Y-%m-%d'),62.21027);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-13','%Y-%m-%d'),61.73167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-08','%Y-%m-%d'),63.20380);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-14','%Y-%m-%d'),65.31080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-09','%Y-%m-%d'),62.72427);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-15','%Y-%m-%d'),64.67620);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-10','%Y-%m-%d'),61.59373);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-16','%Y-%m-%d'),62.87287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-11','%Y-%m-%d'),61.21280);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-17','%Y-%m-%d'),60.14680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-12','%Y-%m-%d'),60.79787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-18','%Y-%m-%d'),63.01007);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-13','%Y-%m-%d'),60.00080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-19','%Y-%m-%d'),57.82680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-14','%Y-%m-%d'),60.82333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-20','%Y-%m-%d'),62.59173);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-15','%Y-%m-%d'),59.62020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-21','%Y-%m-%d'),61.65607);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-16','%Y-%m-%d'),60.27420);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-23','%Y-%m-%d'),61.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-17','%Y-%m-%d'),60.06200);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-24','%Y-%m-%d'),59.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-18','%Y-%m-%d'),60.88900);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-25','%Y-%m-%d'),50.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-19','%Y-%m-%d'),59.92547);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-26','%Y-%m-%d'),60.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-20','%Y-%m-%d'),59.99853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-27','%Y-%m-%d'),62.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-21','%Y-%m-%d'),58.65873);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-28','%Y-%m-%d'),61.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-22','%Y-%m-%d'),60.61000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-29','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-23','%Y-%m-%d'),59.92280);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-30','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-24','%Y-%m-%d'),59.52427);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-31','%Y-%m-%d'),62.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-25','%Y-%m-%d'),59.44887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-01','%Y-%m-%d'),60.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-26','%Y-%m-%d'),60.23540);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-02','%Y-%m-%d'),62.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-27','%Y-%m-%d'),61.18333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-03','%Y-%m-%d'),62.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-28','%Y-%m-%d'),60.88133);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-04','%Y-%m-%d'),60.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-29','%Y-%m-%d'),61.74160);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-06','%Y-%m-%d'),62.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-30','%Y-%m-%d'),60.25647);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-08','%Y-%m-%d'),61.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-31','%Y-%m-%d'),60.41220);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-09','%Y-%m-%d'),63.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-01','%Y-%m-%d'),59.21053);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-10','%Y-%m-%d'),61.82227);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-02','%Y-%m-%d'),55.04713);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-11','%Y-%m-%d'),61.89553);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-03','%Y-%m-%d'),56.08473);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-12','%Y-%m-%d'),60.90127);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-04','%Y-%m-%d'),64.51107);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-13','%Y-%m-%d'),62.23660);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-05','%Y-%m-%d'),56.75193);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-14','%Y-%m-%d'),61.76947);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-06','%Y-%m-%d'),61.64240);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-15','%Y-%m-%d'),63.08853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-07','%Y-%m-%d'),61.33653);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-16','%Y-%m-%d'),60.12627);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-08','%Y-%m-%d'),69.28867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-17','%Y-%m-%d'),60.60020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-09','%Y-%m-%d'),60.87507);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-18','%Y-%m-%d'),60.43440);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-10','%Y-%m-%d'),68.08707);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-19','%Y-%m-%d'),65.02820);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-11','%Y-%m-%d'),60.57680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-20','%Y-%m-%d'),62.95593);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-12','%Y-%m-%d'),61.52467);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-21','%Y-%m-%d'),61.23967);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-13','%Y-%m-%d'),58.06567);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-22','%Y-%m-%d'),62.61853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-14','%Y-%m-%d'),59.80807);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-23','%Y-%m-%d'),63.64227);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-15','%Y-%m-%d'),79.90007);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-24','%Y-%m-%d'),63.42147);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-16','%Y-%m-%d'),54.75020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-25','%Y-%m-%d'),60.82687);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-17','%Y-%m-%d'),65.69500);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-26','%Y-%m-%d'),60.66260);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-18','%Y-%m-%d'),68.56247);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-27','%Y-%m-%d'),60.12767);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-19','%Y-%m-%d'),72.67153);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-28','%Y-%m-%d'),60.51513);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-20','%Y-%m-%d'),71.30720);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-29','%Y-%m-%d'),61.71520);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-21','%Y-%m-%d'),57.75233);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-30','%Y-%m-%d'),60.89553);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-22','%Y-%m-%d'),59.04200);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-31','%Y-%m-%d'),63.50540);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-23','%Y-%m-%d'),62.30153);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-01','%Y-%m-%d'),62.37533);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-24','%Y-%m-%d'),67.68287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-02','%Y-%m-%d'),60.31400);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-25','%Y-%m-%d'),69.21800);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-03','%Y-%m-%d'),63.43920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-26','%Y-%m-%d'),69.75993);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-04','%Y-%m-%d'),61.20487);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-27','%Y-%m-%d'),64.64113);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-05','%Y-%m-%d'),62.11167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-28','%Y-%m-%d'),60.10053);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-06','%Y-%m-%d'),59.96140);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-29','%Y-%m-%d'),58.67653);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-07','%Y-%m-%d'),62.60727);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-30','%Y-%m-%d'),58.29180);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-08','%Y-%m-%d'),61.95493);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-01','%Y-%m-%d'),60.56173);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-09','%Y-%m-%d'),58.89653);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-02','%Y-%m-%d'),57.15840);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-10','%Y-%m-%d'),66.20167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-03','%Y-%m-%d'),54.49167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-11','%Y-%m-%d'),64.76873);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-04','%Y-%m-%d'),61.54087);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-12','%Y-%m-%d'),69.90680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-05','%Y-%m-%d'),63.86073);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-13','%Y-%m-%d'),68.49253);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-06','%Y-%m-%d'),64.13460);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-14','%Y-%m-%d'),63.19360);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-07','%Y-%m-%d'),65.30087);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-15','%Y-%m-%d'),63.35453);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-08','%Y-%m-%d'),64.46353);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-16','%Y-%m-%d'),59.78020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-09','%Y-%m-%d'),62.81193);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-17','%Y-%m-%d'),60.70760);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-10','%Y-%m-%d'),56.14480);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-18','%Y-%m-%d'),58.05167);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-11','%Y-%m-%d'),61.47853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-19','%Y-%m-%d'),57.12700);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-12','%Y-%m-%d'),63.39287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-20','%Y-%m-%d'),59.49013);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-13','%Y-%m-%d'),64.30640);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-21','%Y-%m-%d'),59.18607);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-14','%Y-%m-%d'),64.29447);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-22','%Y-%m-%d'),60.94680);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-15','%Y-%m-%d'),65.63307);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-23','%Y-%m-%d'),59.85807);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-16','%Y-%m-%d'),62.32887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-24','%Y-%m-%d'),60.06767);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-17','%Y-%m-%d'),56.52853);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-25','%Y-%m-%d'),61.60267);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-18','%Y-%m-%d'),70.26520);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-26','%Y-%m-%d'),60.94220);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-19','%Y-%m-%d'),64.38267);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-27','%Y-%m-%d'),59.99040);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-20','%Y-%m-%d'),63.01447);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-28','%Y-%m-%d'),63.05567);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-21','%Y-%m-%d'),61.89200);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-22','%Y-%m-%d'),62.06920);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-23','%Y-%m-%d'),68.49253);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-24','%Y-%m-%d'),69.98867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-25','%Y-%m-%d'),60.26940);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-26','%Y-%m-%d'),62.91493);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-09','%Y-%m-%d'),62.28433);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-27','%Y-%m-%d'),62.36827);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-10','%Y-%m-%d'),64.38787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-11','%Y-%m-%d'),61.17093);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-28','%Y-%m-%d'),60.33887);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-12','%Y-%m-%d'),57.17713);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-29','%Y-%m-%d'),83.89220);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-13','%Y-%m-%d'),57.69653);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-30','%Y-%m-%d'),60.96747);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-14','%Y-%m-%d'),55.97980);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-31','%Y-%m-%d'),57.80627);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-15','%Y-%m-%d'),62.08940);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-01','%Y-%m-%d'),61.60173);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-16','%Y-%m-%d'),83.81047);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-02','%Y-%m-%d'),63.23627);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-17','%Y-%m-%d'),61.32540);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-03','%Y-%m-%d'),58.39987);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-18','%Y-%m-%d'),61.08900);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-04','%Y-%m-%d'),69.51947);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-19','%Y-%m-%d'),67.26267);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-05','%Y-%m-%d'),69.67787);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-20','%Y-%m-%d'),58.71120);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-06','%Y-%m-%d'),62.40513);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-21','%Y-%m-%d'),55.77320);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-07','%Y-%m-%d'),61.01893);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-22','%Y-%m-%d'),59.99420);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-08','%Y-%m-%d'),61.34813);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-23','%Y-%m-%d'),60.83867);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-24','%Y-%m-%d'),59.57020);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-25','%Y-%m-%d'),63.20393);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-17','%Y-%m-%d'),67.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-26','%Y-%m-%d'),58.30480);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-18','%Y-%m-%d'),64.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-27','%Y-%m-%d'),58.79667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-19','%Y-%m-%d'),60.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-28','%Y-%m-%d'),54.04967);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-20','%Y-%m-%d'),57.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-29','%Y-%m-%d'),57.88313);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-21','%Y-%m-%d'),58.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-30','%Y-%m-%d'),56.94940);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-22','%Y-%m-%d'),59.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-01','%Y-%m-%d'),65.01080);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-23','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-02','%Y-%m-%d'),64.97013);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-24','%Y-%m-%d'),59.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-03','%Y-%m-%d'),65.06647);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-25','%Y-%m-%d'),59.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-04','%Y-%m-%d'),64.08287);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-26','%Y-%m-%d'),76.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-05','%Y-%m-%d'),65.40367);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-27','%Y-%m-%d'),59.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-06','%Y-%m-%d'),72.61373);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-28','%Y-%m-%d'),59.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-07','%Y-%m-%d'),72.53120);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-29','%Y-%m-%d'),58.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-08','%Y-%m-%d'),72.54133);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-26','%Y-%m-%d'),58.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-30','%Y-%m-%d'),54.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-01','%Y-%m-%d'),58.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-02','%Y-%m-%d'),59.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-03','%Y-%m-%d'),58.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-04','%Y-%m-%d'),60.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-05','%Y-%m-%d'),101.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-06','%Y-%m-%d'),58.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-07','%Y-%m-%d'),59.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-08','%Y-%m-%d'),56.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-09','%Y-%m-%d'),57.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-10','%Y-%m-%d'),65.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-11','%Y-%m-%d'),56.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-12','%Y-%m-%d'),54.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-13','%Y-%m-%d'),68.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-14','%Y-%m-%d'),69.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-15','%Y-%m-%d'),66.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-16','%Y-%m-%d'),58.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-17','%Y-%m-%d'),60.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-18','%Y-%m-%d'),58.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-19','%Y-%m-%d'),55.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-20','%Y-%m-%d'),55.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-21','%Y-%m-%d'),57.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-22','%Y-%m-%d'),57.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-23','%Y-%m-%d'),58.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-24','%Y-%m-%d'),57.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-25','%Y-%m-%d'),58.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-26','%Y-%m-%d'),61.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-27','%Y-%m-%d'),57.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-28','%Y-%m-%d'),58.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-29','%Y-%m-%d'),59.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-30','%Y-%m-%d'),55.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-31','%Y-%m-%d'),53.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-01','%Y-%m-%d'),56.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-02','%Y-%m-%d'),57.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-03','%Y-%m-%d'),55.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-04','%Y-%m-%d'),57.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-05','%Y-%m-%d'),65.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-06','%Y-%m-%d'),55.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-07','%Y-%m-%d'),57.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-08','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-09','%Y-%m-%d'),60.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-10','%Y-%m-%d'),58.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-11','%Y-%m-%d'),58.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-12','%Y-%m-%d'),57.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-13','%Y-%m-%d'),57.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-14','%Y-%m-%d'),55.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-15','%Y-%m-%d'),55.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-16','%Y-%m-%d'),58.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-17','%Y-%m-%d'),58.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-18','%Y-%m-%d'),64.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-19','%Y-%m-%d'),59.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-20','%Y-%m-%d'),57.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-21','%Y-%m-%d'),57.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-22','%Y-%m-%d'),59.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-23','%Y-%m-%d'),56.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-24','%Y-%m-%d'),58.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-25','%Y-%m-%d'),57.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-26','%Y-%m-%d'),57.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-27','%Y-%m-%d'),53.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-28','%Y-%m-%d'),58.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-29','%Y-%m-%d'),56.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-30','%Y-%m-%d'),58.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-01','%Y-%m-%d'),60.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-02','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-03','%Y-%m-%d'),58.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-04','%Y-%m-%d'),77.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-05','%Y-%m-%d'),56.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-06','%Y-%m-%d'),55.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-07','%Y-%m-%d'),57.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-08','%Y-%m-%d'),57.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-09','%Y-%m-%d'),71.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-10','%Y-%m-%d'),62.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-11','%Y-%m-%d'),59.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-12','%Y-%m-%d'),59.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-13','%Y-%m-%d'),62.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-14','%Y-%m-%d'),59.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-15','%Y-%m-%d'),59.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-16','%Y-%m-%d'),62.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-17','%Y-%m-%d'),66.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-18','%Y-%m-%d'),59.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-19','%Y-%m-%d'),60.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-20','%Y-%m-%d'),57.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-21','%Y-%m-%d'),60.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-22','%Y-%m-%d'),59.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-23','%Y-%m-%d'),61.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-24','%Y-%m-%d'),57.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-25','%Y-%m-%d'),52.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-09','%Y-%m-%d'),70.77980);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-10','%Y-%m-%d'),70.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-11','%Y-%m-%d'),60.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-12','%Y-%m-%d'),58.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-13','%Y-%m-%d'),58.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-14','%Y-%m-%d'),58.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-15','%Y-%m-%d'),68.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-16','%Y-%m-%d'),84.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-17','%Y-%m-%d'),61.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-18','%Y-%m-%d'),64.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-19','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-20','%Y-%m-%d'),77.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-21','%Y-%m-%d'),60.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-22','%Y-%m-%d'),65.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-23','%Y-%m-%d'),68.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-24','%Y-%m-%d'),58.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-25','%Y-%m-%d'),56.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-26','%Y-%m-%d'),58.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-27','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-28','%Y-%m-%d'),59.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-29','%Y-%m-%d'),58.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-30','%Y-%m-%d'),59.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-27','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-31','%Y-%m-%d'),57.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-28','%Y-%m-%d'),305.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-01','%Y-%m-%d'),59.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-29','%Y-%m-%d'),62.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-02','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-30','%Y-%m-%d'),60.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-03','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-31','%Y-%m-%d'),60.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-04','%Y-%m-%d'),83.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-01','%Y-%m-%d'),55.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-05','%Y-%m-%d'),59.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-02','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-06','%Y-%m-%d'),58.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-03','%Y-%m-%d'),61.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-07','%Y-%m-%d'),59.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-04','%Y-%m-%d'),62.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-08','%Y-%m-%d'),57.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-05','%Y-%m-%d'),61.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-09','%Y-%m-%d'),58.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-06','%Y-%m-%d'),61.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-10','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-07','%Y-%m-%d'),62.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-11','%Y-%m-%d'),58.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-08','%Y-%m-%d'),100.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-12','%Y-%m-%d'),57.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-09','%Y-%m-%d'),62.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-13','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-10','%Y-%m-%d'),66.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-14','%Y-%m-%d'),58.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-11','%Y-%m-%d'),61.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-15','%Y-%m-%d'),59.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-12','%Y-%m-%d'),60.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-16','%Y-%m-%d'),61.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-13','%Y-%m-%d'),61.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-17','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-14','%Y-%m-%d'),60.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-18','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-15','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-19','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-16','%Y-%m-%d'),61.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-20','%Y-%m-%d'),60.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-17','%Y-%m-%d'),70.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-21','%Y-%m-%d'),63.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-18','%Y-%m-%d'),61.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-22','%Y-%m-%d'),58.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-19','%Y-%m-%d'),61.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-23','%Y-%m-%d'),59.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-20','%Y-%m-%d'),61.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-24','%Y-%m-%d'),59.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-21','%Y-%m-%d'),61.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-25','%Y-%m-%d'),63.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-22','%Y-%m-%d'),60.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-26','%Y-%m-%d'),61.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-23','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-27','%Y-%m-%d'),60.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-24','%Y-%m-%d'),60.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-28','%Y-%m-%d'),57.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-25','%Y-%m-%d'),61.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-29','%Y-%m-%d'),59.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-26','%Y-%m-%d'),61.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-30','%Y-%m-%d'),57.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-27','%Y-%m-%d'),61.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-31','%Y-%m-%d'),59.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-28','%Y-%m-%d'),61.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-01','%Y-%m-%d'),58.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-29','%Y-%m-%d'),61.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-02','%Y-%m-%d'),61.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-30','%Y-%m-%d'),61.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-03','%Y-%m-%d'),59.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-31','%Y-%m-%d'),59.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-04','%Y-%m-%d'),59.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-01','%Y-%m-%d'),60.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-05','%Y-%m-%d'),59.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-02','%Y-%m-%d'),60.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-06','%Y-%m-%d'),61.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-03','%Y-%m-%d'),60.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-07','%Y-%m-%d'),59.20000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-04','%Y-%m-%d'),61.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-08','%Y-%m-%d'),61.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-05','%Y-%m-%d'),60.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-09','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-06','%Y-%m-%d'),60.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-10','%Y-%m-%d'),60.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-07','%Y-%m-%d'),60.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-11','%Y-%m-%d'),58.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-08','%Y-%m-%d'),61.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-12','%Y-%m-%d'),58.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-09','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-13','%Y-%m-%d'),58.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-10','%Y-%m-%d'),60.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-14','%Y-%m-%d'),60.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-11','%Y-%m-%d'),60.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-15','%Y-%m-%d'),62.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-12','%Y-%m-%d'),59.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-16','%Y-%m-%d'),65.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-13','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-14','%Y-%m-%d'),69.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-15','%Y-%m-%d'),59.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-16','%Y-%m-%d'),59.80000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-17','%Y-%m-%d'),60.46667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-18','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-19','%Y-%m-%d'),62.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-20','%Y-%m-%d'),60.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-21','%Y-%m-%d'),59.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-22','%Y-%m-%d'),61.40000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-23','%Y-%m-%d'),60.93333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-24','%Y-%m-%d'),64.13333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-25','%Y-%m-%d'),61.53333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-26','%Y-%m-%d'),59.06667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-27','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-28','%Y-%m-%d'),60.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-29','%Y-%m-%d'),61.00000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-01','%Y-%m-%d'),61.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-02','%Y-%m-%d'),61.66667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-03','%Y-%m-%d'),60.73333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-04','%Y-%m-%d'),61.26667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-05','%Y-%m-%d'),61.60000);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-06','%Y-%m-%d'),61.33333);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-07','%Y-%m-%d'),61.86667);
+INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-08','%Y-%m-%d'),62.00000);
+
+commit;
diff --git a/ecomp-sdk/epsdk-app-common/db-scripts/readme.txt b/ecomp-sdk/epsdk-app-common/db-scripts/readme.txt
new file mode 100644
index 00000000..d128cbd3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/db-scripts/readme.txt
@@ -0,0 +1,54 @@
+This Readme file contains a description of all the database scripts located in
+
+ epsdk-app-common / db-scripts /
+
+***************************************************************************************************************************************
+
+Directions:
+
+DDL
+EcompSdkDDLMySql_1707_Common.sql - this is the DDL entries that are in common
+
+DML
+EcompSdkDMLMySql_1707_Common.sql - this is the DML entries that are in common
+
+
+***************************************************************************************************************************************
+ epsdk-app-common / db-scripts /
+***************************************************************************************************************************************
+5.EcompSdkDDLMySql_1707_Common.sql This script creates tables in the 1707 COMMON version of the ECOMP SDK application database.
+ Additional DDL scripts may be required for different versions!
+6.EcompSdkDMLMySql_1707_Common.sql This script populates tables in the 1707 COMMON version of the ECOMP SDK application database.
+ Additional DML scripts are required for different versions!
+
+
+*****************************************************
+Upgrading from 1607 SDK to 1610 SDK
+*****************************************************
+EcompSdkDDL_1610_Add.sql This is the Upgrade script for the 1610 Version of the SDK database called ecomp_sdk;
+ upgrading from the 1607 version
+EcompSdkDML_1610_Add.sql This is the Upgrade script for the default data for the 1610 Version of the SDK database called ecomp_sdk;
+ upgrading from the 1607 version
+*****************************************************
+Upgrading from 1610 SDK to 1702 SDK
+*****************************************************
+If you are starting with a 1610 environment and want to bring it up to 1702,
+you can run the following scripts in this order:
+EcompSdkDML_1702_Add_1.sql
+EcompSdkDML_1702_Add_2.sql
+EcompSdkDML_1702_Add_3.sql
+EcompSdkDML_1702_Add_4.sql
+EcompSdkDML_1702_Add_5.sql
+
+You can roll back the changes from the corresponding 1702 Add scripts with these rollback scripts:
+EcompSdkDML_1702_Rollback_1.sql
+EcompSdkDML_1702_Rollback_2.sql
+EcompSdkDML_1702_Rollback_3.sql
+EcompSdkDML_1702_Rollback_4.sql
+EcompSdkDML_1702_Rollback_5.sql
+
+*****************************************************
+Complete Scripts for 1702
+*****************************************************
+EcompSdkDDLMySql_1702.sql This is for the 1702 DDL Version of SDK database called ecomp_sdk
+EcompSdkDMLMySql_1702.sql This is for the default data for 1702 Version of SDK database called ecomp_sdk
diff --git a/ecomp-sdk/epsdk-app-common/pom.xml b/ecomp-sdk/epsdk-app-common/pom.xml
new file mode 100644
index 00000000..dbf4733b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/pom.xml
@@ -0,0 +1,294 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-app-common</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>jar</packaging>
+ <name>ECOMP Portal SDK Webapp Common Classes</name>
+ <description>ECOMP Portal SDK Web Application common classes</description>
+ <url>https://wiki.onap.org/display/DW/Portal</url>
+
+ <properties>
+ <encoding>UTF-8</encoding>
+ <epsdk.version>1.1.0-SNAPSHOT</epsdk.version>
+ <springframework.version>4.2.0.RELEASE</springframework.version>
+ <hibernate.version>4.3.11.Final</hibernate.version>
+ <!-- Skip assembling the zip; assemble via mvn -Dskipassembly=false .. -->
+ <skipassembly>true</skipassembly>
+ <!-- Tests usually require some setup that maven cannot do, so skip. -->
+ <skiptests>true</skiptests>
+ <nexusproxy>https://nexus.onap.org</nexusproxy>
+ <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
+ <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
+ <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
+ </properties>
+
+ <repositories>
+ <repository>
+ <!-- Releases repository has ECOMP release artifacts -->
+ <id>ecomp-releases</id>
+ <name>OpenECOMP - Release Repository</name>
+ <url>${nexusproxy}/${releaseNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>ecomp-snapshots</id>
+ <name>OpenECOMP - Snapshot Repository</name>
+ <url>${nexusproxy}/${snapshotNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Staging repository has ECOMP staging artifacts -->
+ <id>ecomp-staging</id>
+ <name>OpenECOMP - Staging Repository</name>
+ <url>${nexusproxy}/${stagingNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>oss-snapshots</id>
+ <name>oss Central - Snapshots</name>
+ <url>https://oss.sonatype.org/service/local/repositories/releases/content/</url>
+ </repository>
+ </repositories>
+
+ <profiles>
+ <!-- disable doclint, a new feature in Java 8, when generating javadoc -->
+ <profile>
+ <id>doclint-java8-disable</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.4</version>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <build>
+
+ <plugins>
+ <!-- Compile to Java 1.8 class output format -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+
+ <!-- Put version into jar also -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <archive-version>${project.version}</archive-version>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+
+ <!-- Generate javadoc jar; see profile for Java 8 -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.3</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Generate source jar -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <skipTests>${skiptests}</skipTests>
+ <includes>
+ <include>**/Test*.java</include>
+ <include>**/*Test.java</include>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <additionalClasspathElements>
+ <additionalClasspathElement>${basedir}/war</additionalClasspathElement>
+ </additionalClasspathElements>
+ <systemPropertyVariables>
+ <container.classpath>classpath:</container.classpath>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+
+ </plugins>
+ </build>
+ <dependencies>
+ <!-- SDK components -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-core</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-analytics</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-workflow</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <!-- Mapper -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ <version>0.9.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>io.searchbox</groupId>
+ <artifactId>jest</artifactId>
+ <version>2.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ <!-- Elastic Search -->
+ <dependency>
+ <groupId>org.elasticsearch</groupId>
+ <artifactId>elasticsearch</artifactId>
+ <version>2.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160212</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>2.2.1</version>
+ <exclusions>
+ <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
+ <exclusion>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- bridge to implement commons-logging using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${springframework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AdminController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AdminController.java
new file mode 100644
index 00000000..c0904704
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AdminController.java
@@ -0,0 +1,52 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+public class AdminController {
+ @Controller
+ @RequestMapping("/")
+ public class AngularSinglePageController extends RestrictedBaseController {
+
+ @RequestMapping(value = { "/admin" }, method = RequestMethod.GET)
+ public ModelAndView view(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView("admin", "model", model);
+ }
+
+ @RequestMapping(value = { "/admin2" }, method = RequestMethod.GET)
+ public ModelAndView adminView(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView("admin2", "model", model);
+ }
+
+
+ }
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AngularAdminController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AngularAdminController.java
index e3aab7dd..7441106f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AngularAdminController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/AngularAdminController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,13 +17,14 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -47,4 +48,4 @@ public class AngularAdminController extends RestrictedBaseController{
return new ModelAndView(getViewName(),"model", model);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/CacheAdminController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/CacheAdminController.java
new file mode 100644
index 00000000..81d35f3d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/CacheAdminController.java
@@ -0,0 +1,248 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.jcs.JCS;
+import org.apache.jcs.admin.CacheRegionInfo;
+import org.apache.jcs.admin.JCSAdminBean;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+@Controller
+@RequestMapping("/")
+public class CacheAdminController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CacheAdminController.class);
+
+ private JCSAdminBean jcsAdminBean = new JCSAdminBean();
+
+ @RequestMapping(value = { "/jcs_admin" }, method = RequestMethod.GET)
+ public ModelAndView cacheAdmin(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+
+ model.put("model", getRegions());
+
+ return new ModelAndView(getViewName(), model);
+ }
+
+ @RequestMapping(value = { "/get_regions" }, method = RequestMethod.GET)
+ public void getRegions(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ JsonMessage msg = new JsonMessage(getRegions().toString());
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRegions failed", e);
+ }
+ }
+
+ @RequestMapping(value = { "/jcs_admin/clearRegion" }, method = RequestMethod.GET)
+ public void clearRegion(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String cacheName = (String) request.getParameter("cacheName");
+ clearCacheRegion(cacheName);
+
+ response.setContentType("application/json");
+ PrintWriter out = response.getWriter();
+ out.write(getRegions().toString());
+ }
+
+ @RequestMapping(value = { "/jcs_admin/clearAll" }, method = RequestMethod.GET)
+ public void clearAll(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ clearAllRegions();
+
+ response.setContentType("application/json");
+ PrintWriter out = response.getWriter();
+ out.write(getRegions().toString());
+ }
+
+ @RequestMapping(value = { "/jcs_admin/clearItem" }, method = RequestMethod.GET)
+ public void clearItem(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String keyName = (String) request.getParameter("keyName");
+ String cacheName = (String) request.getParameter("cacheName");
+ clearCacheRegionItem(cacheName, keyName);
+
+ response.setContentType("application/json");
+ PrintWriter out = response.getWriter();
+ out.write(getRegions().toString());
+ }
+
+ @RequestMapping(value = { "/jcs_admin/showItemDetails" }, method = RequestMethod.GET)
+ public void showItemDetails(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String cacheName = (String) request.getParameter("cacheName");
+ String keyName = (String) request.getParameter("keyName");
+ String details = null;
+
+ try {
+ details = getItemDetails(cacheName, keyName);
+ } catch (Exception e) {
+ details = "There was an error retrieving the region details. Please try again.";
+ logger.error(EELFLoggerDelegate.errorLogger, "showItemDetails failed for cache name " + cacheName, e);
+ }
+ JSONObject j = new JSONObject(details);
+ response.setContentType("application/json");
+ // response.setContentType("text/plain");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ }
+
+ @RequestMapping(value = { "/jcs_admin/showRegionDetails" }, method = RequestMethod.GET)
+ public void showRegionDetails(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String cacheName = (String) request.getParameter("cacheName");
+ String details = null;
+ ObjectMapper mapper = new ObjectMapper();
+ JSONObject j = null;
+ try {
+ details = getRegionStats(cacheName);
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(details));
+ j = new JSONObject(msg);
+
+ } catch (Exception e) {
+ details = "There was an error retrieving the region details. Please try again.";
+ logger.error(EELFLoggerDelegate.errorLogger, "showRegionDetailed failed for cache name " + cacheName, e);
+ }
+
+ response.setContentType("application/json");
+
+ PrintWriter out = response.getWriter();
+ // out.write(details);
+ out.write(j.toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ public JSONArray getRegions() {
+ LinkedList<CacheRegionInfo> regions = null;
+ JSONArray ja = new JSONArray();
+ try {
+ regions = getJcsAdminBean().buildCacheInfo();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+ for (CacheRegionInfo cri : regions) {
+ if (cri.getCache().getCacheName() != null && !cri.getCache().getCacheName().equals("[object Object]")) {
+ JSONObject jo = new JSONObject();
+ jo.put("cacheName", cri.getCache().getCacheName());
+ jo.put("size", cri.getCache().getSize());
+ jo.put("byteCount", cri.getByteCount());
+ jo.put("status", cri.getStatus());
+ jo.put("hitCountRam", cri.getCache().getHitCountRam());
+ jo.put("hitCountAux", cri.getCache().getHitCountAux());
+ jo.put("missCountNotFound", cri.getCache().getMissCountNotFound());
+ jo.put("missCountExpired", cri.getCache().getMissCountExpired());
+ jo.put("items",
+ new JSONArray(mapper.writeValueAsString(getRegionItems(cri.getCache().getCacheName()))));
+ ja.put(jo);
+ }
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRegions failed", e);
+ }
+
+ return ja;
+ }
+
+ private String getRegionStats(String cacheName) throws Exception {
+ String stats = "";
+
+ JCS cache = JCS.getInstance(cacheName);
+ stats = cache.getStats();
+
+ return stats;
+ }
+
+ private String getItemDetails(String cacheName, String keyName) throws Exception {
+ String details = "";
+
+ JCS cache = JCS.getInstance(cacheName);
+ ICacheElement element = cache.getCacheElement(keyName);
+
+ if (element != null) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+ details = mapper.writeValueAsString(element);
+ }
+
+ return details;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private List getRegionItems(String cacheName) {
+ List items = null;
+
+ try {
+ items = getJcsAdminBean().buildElementInfo(cacheName);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRegionItems failed for cache name " + cacheName, e);
+ }
+ return items;
+ }
+
+ private void clearAllRegions() {
+ try {
+ getJcsAdminBean().clearAllRegions();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "clearAllRegions faield", e);
+ }
+ }
+
+ private void clearCacheRegion(String cacheName) {
+ try {
+ getJcsAdminBean().clearRegion(cacheName);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "clearCacheRegion failed for cache name " + cacheName, e);
+ }
+ }
+
+ private void clearCacheRegionItem(String cacheName, String keyName) {
+ try {
+ getJcsAdminBean().removeItem(cacheName, keyName);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "clearCacheRegionItem failed for key name " + keyName, e);
+ }
+ }
+
+ public JCSAdminBean getJcsAdminBean() {
+ return jcsAdminBean;
+ }
+
+ public void setJcsAdminBean(JCSAdminBean jcsAdminBean) {
+ this.jcsAdminBean = jcsAdminBean;
+ }
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FavoritesController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FavoritesController.java
index b2ad61f4..023f8d7b 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FavoritesController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FavoritesController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
@@ -27,14 +27,15 @@ import javax.servlet.http.HttpSession;
import org.json.JSONArray;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.App;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.aspect.AuditLog;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.onboarding.rest.FavoritesClient;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
import org.openecomp.portalsdk.core.service.AppService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
@@ -48,12 +49,12 @@ import org.springframework.web.bind.annotation.RequestMethod;
@org.springframework.context.annotation.Configuration
@EnableAspectJAutoProxy
@AuditLog
-public class FavoritesController extends UnRestrictedBaseController {
+public class FavoritesController extends RestrictedBaseController {
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FavoritesController.class);
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FavoritesController.class);
@Autowired
- AppService appService;
+ private AppService appService;
/**
* Makes the REST API call to Portal Back-end and retrieves Favorite menu
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FnMenuController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FnMenuController.java
new file mode 100644
index 00000000..2c589991
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FnMenuController.java
@@ -0,0 +1,223 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.Menu;
+import org.openecomp.portalsdk.core.domain.MenuData;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.FnMenuService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * A controller for Admin to add/edit/delete menu items from FN_MENU.
+ */
+
+@Controller
+@RequestMapping("/")
+public class FnMenuController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FnMenuController.class);
+
+ @Autowired
+ FnMenuService service;
+
+ private String viewName;
+
+ @RequestMapping(value = { "/admin_fn_menu/get_parent_list" }, method = RequestMethod.GET)
+ public void getParentList(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ response.getWriter().write(mapper.writeValueAsString(service.getParentList()));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getParentListFailed", e);
+ response.setCharacterEncoding("UTF-8");
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ }
+ }
+
+ @RequestMapping(value = { "/admin_fn_menu/get_function_cd_list" }, method = RequestMethod.GET)
+ public void getFunctionCDList(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ response.getWriter().write(mapper.writeValueAsString(service.getFunctionCDList()));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getFunctionCDList", e);
+ response.setCharacterEncoding("UTF-8");
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ }
+
+ }
+
+ @RequestMapping(value = { "/admin_fn_menu" }, method = RequestMethod.GET)
+ public void getFnMenuList(HttpServletRequest request, HttpServletResponse response) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+ List<MenuData> temp = null;
+ List<List<MenuData>> childItemList = new ArrayList<List<MenuData>>();
+ List<MenuData> parentList = new ArrayList<>();
+
+ try {
+ temp = service.getFnMenuItems();
+ for (MenuData menu : temp) {
+ MenuData parentData = new MenuData();
+ parentData.setId(menu.getId());
+ parentData.setLabel(menu.getLabel());
+ if (menu.getParentMenu() != null) {
+ parentData.setParentId(menu.getParentMenu().getId());
+ }
+ parentData.setAction(menu.getAction());
+ parentData.setFunctionCd(menu.getFunctionCd());
+ parentData.setImageSrc(menu.getImageSrc());
+ parentData.setSortOrder(menu.getSortOrder());
+ parentData.setActive(menu.isActive());
+ parentData.setServlet(menu.getServlet());
+ parentData.setQueryString(menu.getQueryString());
+ parentData.setExternalUrl(menu.getExternalUrl());
+ parentData.setTarget(menu.getTarget());
+ parentData.setMenuSetCode(menu.getMenuSetCode());
+ parentData.setSeparator(menu.isSeparator());
+ parentData.setImageSrc(menu.getImageSrc());
+ parentList.add(parentData);
+ List<MenuData> tempList = new ArrayList<MenuData>();
+ // int countChildAction = 0;
+ /*
+ * for(Object o:menu.getChildMenus()){ Menu m = (Menu)o; Menu
+ * data = new Menu(); data.setId(m.getId());
+ * data.setLabel(m.getLabel()); data.setAction(m.getAction());
+ * data.setImageSrc(m.getImageSrc()); tempList.add(data); }
+ */
+ childItemList.add(tempList);
+ }
+ model.put("fnMenuItems", parentList);
+ // JsonMessage msg = new
+ // JsonMessage(mapper.writeValueAsString(parentList),mapper.writeValueAsString(childItemList),"none");
+
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getFnMenuList failed", e);
+ }
+
+ }
+
+ @RequestMapping(value = { "/admin_fn_menu/updateFnMenu" }, method = RequestMethod.POST)
+ public ModelAndView updateFnMenu(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ Menu fnMenuItem = mapper.readValue(root.get("availableFnMenuItem").toString(), Menu.class);
+
+ service.saveFnMenu(fnMenuItem);
+ request.getSession()
+ .removeAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
+ request.getSession().removeAttribute(SystemProperties.LEFT_MENU_CHILDREND);
+ request.getSession().removeAttribute(SystemProperties.LEFT_MENU_PARENT);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application / json");
+ request.setCharacterEncoding("UTF-8");
+
+ PrintWriter out = response.getWriter();
+ String responseString = mapper.writeValueAsString(service.getMenuItem(fnMenuItem.getId()));
+
+ out.write(responseString);
+
+ return null;
+
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "updateFnMenu failed", e);
+ response.setCharacterEncoding("UTF-8");
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ }
+ return null;
+
+ }
+
+ @RequestMapping(value = { "/admin_fn_menu/removeMenuItem" }, method = RequestMethod.POST)
+ public ModelAndView removeFnMenu(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ Menu fnMenuItem = mapper.readValue(root.get("fnMenuItem").toString(), Menu.class);
+ Menu fnMenuItemRow = service.getMenuItemRow(fnMenuItem.getId());
+
+ service.removeMenuItem(fnMenuItemRow);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application / json");
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ String responseString = mapper.writeValueAsString(service.getMenuItem(fnMenuItem.getId()));
+ out.write(responseString);
+
+ return null;
+
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "removeFnMenu failed", e);
+ response.setCharacterEncoding("UTF-8");
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ }
+ return null;
+
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FuncMenuController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FuncMenuController.java
index 5baebf00..8e17eaae 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FuncMenuController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/FuncMenuController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
@@ -28,20 +28,21 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.App;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.aspect.AuditLog;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
import org.openecomp.portalsdk.core.onboarding.rest.FunctionalMenuClient;
import org.openecomp.portalsdk.core.onboarding.ueb.UebException;
import org.openecomp.portalsdk.core.onboarding.ueb.UebManager;
import org.openecomp.portalsdk.core.onboarding.ueb.UebMsg;
import org.openecomp.portalsdk.core.onboarding.ueb.UebMsgTypes;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.service.AppService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.slf4j.MDC;
@@ -55,12 +56,12 @@ import org.springframework.web.bind.annotation.RequestMethod;
@RequestMapping("/")
@org.springframework.context.annotation.Configuration
@EnableAspectJAutoProxy
-public class FuncMenuController extends UnRestrictedBaseController{
+public class FuncMenuController extends RestrictedBaseController{
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FuncMenuController.class);
+
@Autowired
AppService appService;
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FuncMenuController.class);
@AuditLog
@RequestMapping(value = {"/get_functional_menu" }, method = RequestMethod.GET)
@@ -171,4 +172,4 @@ public class FuncMenuController extends UnRestrictedBaseController{
return fnMenu;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/LogoutController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/LogoutController.java
index 57983621..467bd3c9 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/LogoutController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/LogoutController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,16 +17,17 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -39,8 +40,10 @@ import org.springframework.web.servlet.ModelAndView;
@RequestMapping("/")
public class LogoutController extends UnRestrictedBaseController{
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LogoutController.class);
+
private User user;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LogoutController.class);
+
/**
* @param request
* @param response
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ManifestController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ManifestController.java
new file mode 100644
index 00000000..ae212b50
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ManifestController.java
@@ -0,0 +1,111 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * This controller responds to a request for the web application manifest,
+ * returning a JSON with the information that was created at build time.
+ *
+ * Manifest entries have names with hyphens, which means Javascript code can't
+ * simply use the shorthand object.key; instead use object['key'].
+ */
+@RestController
+@RequestMapping("/")
+public class ManifestController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ManifestController.class);
+
+ /**
+ * Required to obtain the webapp manifest.
+ */
+ @Autowired
+ private ServletContext context;
+
+ /** Path to resource on classpath */
+ private final String MANIFEST_RESOURCE_PATH = "/META-INF/MANIFEST.MF";
+
+ /**
+ * Gets the content of the webapp manifest file META-INF/MANIFEST.MF.
+ *
+ * @return Attributes object with key-value pairs from the manifest
+ * @throws IOException
+ */
+ private Attributes getWebappManifest() throws IOException {
+ // Manifest is formatted as Java-style properties
+ InputStream inputStream = context.getResourceAsStream(MANIFEST_RESOURCE_PATH);
+ if (inputStream == null)
+ throw new IOException("getWebappManifest: failed to get resource at path " + MANIFEST_RESOURCE_PATH);
+ Manifest manifest = new Manifest(inputStream);
+ inputStream.close();
+ return manifest.getMainAttributes();
+ }
+
+ /**
+ * Gets the webapp manifest contents as a JSON object.
+ *
+ * @param request
+ * @return A map of key-value pairs. On success:
+ *
+ * <pre>
+ * {
+ * "key1": "value1",
+ * "key2": "value2"
+ * }
+ * </pre>
+ *
+ * On failure:
+ *
+ * <pre>
+ * { "error": "message" }
+ * </pre>
+ */
+ @RequestMapping(value = { "/manifest" }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public Map<Object, Object> getManifest(HttpServletRequest request) {
+ try {
+ Attributes attributes = getWebappManifest();
+ return attributes;
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getManifest failed", ex);
+ Map<Object, Object> response = new HashMap<Object, Object>();
+ response.put("error", "failed to get manifest: " + ex.toString());
+ return response;
+ }
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/MenuListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/MenuListController.java
new file mode 100644
index 00000000..ce5ec975
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/MenuListController.java
@@ -0,0 +1,255 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.MenuData;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.openecomp.portalsdk.core.restful.client.SharedContextRestClient;
+import org.openecomp.portalsdk.core.restful.domain.SharedContext;
+import org.openecomp.portalsdk.core.service.FnMenuService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+@RequestMapping("/")
+public class MenuListController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MenuListController.class);
+
+ @Autowired
+ private FnMenuService fnMenuService;
+ @Autowired
+ private SharedContextRestClient sharedContextRestClient;
+
+ /**
+ *
+ * Gets Menu items and stores into session.
+ *
+ * @param request
+ * @param response
+ */
+ @SuppressWarnings("unchecked")
+ @RequestMapping(value = { "/get_menu" }, method = RequestMethod.GET)
+ public void getMenu(HttpServletRequest request, HttpServletResponse response) {
+ logger.debug(EELFLoggerDelegate.debugLogger, "getMenu begins");
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ Set<MenuData> menuResult = null;
+ HttpSession session = request.getSession();
+ List<List<MenuData>> childItemList = (List<List<MenuData>>) session
+ .getAttribute(SystemProperties.LEFT_MENU_CHILDREND);
+ List<MenuData> parentList = (List<MenuData>) session.getAttribute(SystemProperties.LEFT_MENU_PARENT);
+ if (parentList == null || childItemList == null || parentList.size() == 0 || childItemList.size() == 0) {
+ childItemList = new ArrayList<List<MenuData>>();
+ parentList = new ArrayList<MenuData>();
+ menuResult = (Set<MenuData>) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
+ fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
+ logger.debug(EELFLoggerDelegate.debugLogger, "storing leftmenu items into session");
+ session.setAttribute(SystemProperties.LEFT_MENU_PARENT, parentList);
+ session.setAttribute(SystemProperties.LEFT_MENU_CHILDREND, childItemList);
+ }
+ String userName = (String) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME));
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(parentList),
+ mapper.writeValueAsString(childItemList), userName);
+ JSONObject j = new JSONObject(msg);
+ response.setContentType("application/json");
+ response.getWriter().write(j.toString());
+ logger.debug(EELFLoggerDelegate.debugLogger, "getMenu ends");
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getMenu failed", e);
+ }
+ }
+
+ /**
+ *
+ * Gets app name from system.properties file.
+ *
+ * @param request
+ * @param response
+ */
+ @RequestMapping(value = { "/get_app_name" }, method = RequestMethod.GET)
+ public void getAppName(HttpServletRequest request, HttpServletResponse response) {
+ logger.debug(EELFLoggerDelegate.debugLogger, "getAppName begins");
+ HttpSession session = request.getSession(true);
+ try {
+ String appName = (String) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME));
+ if (appName != null && appName.equals("app_display_name")) {
+ appName = "";
+ }
+ JsonMessage msg = new JsonMessage(appName);
+ JSONObject j = new JSONObject(msg);
+ response.setContentType("application/json");
+ response.getWriter().write(j.toString());
+ logger.debug(EELFLoggerDelegate.debugLogger, "getAppName ends");
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getAppName failed", e);
+ }
+ }
+
+ /**
+ * Apparently unused?
+ *
+ * @param request
+ * @return Map with childItemList and parentList keys, associated values.
+ */
+ @SuppressWarnings("unchecked")
+ @ModelAttribute("menu")
+ public Map<String, Object> getLeftMenuJSP(HttpServletRequest request) {
+ logger.debug(EELFLoggerDelegate.debugLogger, "getLeftMenuJSP begins");
+ ObjectMapper mapper = new ObjectMapper();
+ Map<String, Object> model = new HashMap<String, Object>();
+ try {
+ HttpSession session = request.getSession();
+ List<List<MenuData>> childItemList = (List<List<MenuData>>) session
+ .getAttribute(SystemProperties.LEFT_MENU_CHILDREND);
+ List<MenuData> parentList = (List<MenuData>) session.getAttribute(SystemProperties.LEFT_MENU_PARENT);
+ if (parentList == null || childItemList == null) {
+ childItemList = new ArrayList<List<MenuData>>();
+ parentList = new ArrayList<MenuData>();
+ Set<MenuData> menuResult = (Set<MenuData>) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
+ fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
+ session.setAttribute(SystemProperties.LEFT_MENU_PARENT, parentList);
+ session.setAttribute(SystemProperties.LEFT_MENU_CHILDREND, childItemList);
+ }
+ model.put("childItemList", mapper.writeValueAsString(childItemList));
+ model.put("parentList", mapper.writeValueAsString(parentList));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getLeftMenuJSP failed", e);
+ }
+ logger.debug(EELFLoggerDelegate.debugLogger, "getLeftMenuJSP ends");
+ return model;
+ }
+
+ /**
+ * Answers requests for user information, which is fetched from the shared
+ * context at Portal.
+ *
+ * @param request
+ * @param response
+ */
+ @RequestMapping(value = { "/get_userinfo" }, method = RequestMethod.GET)
+ public void getUserInfo(HttpServletRequest request, HttpServletResponse response) {
+ logger.debug(EELFLoggerDelegate.debugLogger, "getUserInfo begins");
+ try {
+ String contextId = null;
+ if (request.getCookies() != null) {
+ for (Cookie ck : request.getCookies()) {
+ if (ck.getName().equalsIgnoreCase("EPService"))
+ contextId = ck.getValue();
+ }
+ }
+ logger.debug(EELFLoggerDelegate.debugLogger, "getUserInfo: ContextId is : " + contextId);
+ List<SharedContext> sharedContextRes = sharedContextRestClient.getUserContext(contextId);
+ logger.debug(EELFLoggerDelegate.debugLogger, "getUserInfo: Shared Context Response is {}",
+ sharedContextRes);
+ Map<String, Object> model = new HashMap<String, Object>();
+ for (SharedContext sharedContext : sharedContextRes) {
+ model.put(sharedContext.getCkey(), sharedContext.getCvalue());
+ }
+ JSONObject j = new JSONObject(model);
+ response.setContentType("application/json");
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getUserInfo failed", e);
+ }
+ }
+
+ /**
+ * Get User information from app sessions
+ *
+ * @param request
+ * @param response
+ */
+ @RequestMapping(value = { "/get_topMenuInfo" }, method = RequestMethod.GET)
+ public void getTopMenu(HttpServletRequest request, HttpServletResponse response) {
+
+ HttpSession session = request.getSession();
+ try {
+ String userName = (String) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME));
+ String firstName = (String) session.getAttribute(SystemProperties.FIRST_NAME);
+ String lastName = (String) session.getAttribute(SystemProperties.LAST_NAME);
+ User user = (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
+ Map<String, String> map = new HashMap<String, String>();
+ String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
+ String portalDomain = redirectUrl.substring(0, redirectUrl.lastIndexOf('/'));
+ String portalUrl = portalDomain + "/process_csp";
+ String getAccessUrl = portalDomain + "/get_access";
+ String contactUsLink = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
+ map.put("portalUrl", portalUrl);
+ map.put("contactUsLink", contactUsLink);
+ map.put("userName", userName);
+ map.put("firstName", firstName);
+ map.put("lastName", lastName);
+ map.put("userid", user.getOrgUserId());
+ map.put("email", user.getEmail());
+ map.put("getAccessUrl", getAccessUrl);
+ JSONObject j = new JSONObject(map);
+ response.setContentType("application/json");
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "Failed to serialize JSON", e);
+ }
+
+ }
+
+ @RequestMapping(value = { "/page_redirect" }, method = RequestMethod.GET)
+ public void pageRedirect(HttpServletRequest request, HttpServletResponse response) {
+ String pageToURL = null;
+ try {
+ String pageTo = request.getParameter("page");
+ if (pageTo.equals("contact"))
+ pageToURL = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
+ else if (pageTo.equals("access")) {
+ String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
+ String portalDomain = redirectUrl.substring(0, redirectUrl.lastIndexOf('/'));
+ pageToURL = portalDomain + "/get_access";
+ }
+ response.getWriter().write(pageToURL);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "pageRedirect failed", e);
+ }
+ }
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/PostSearchController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/PostSearchController.java
index fa5a1082..2da1e6a6 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/PostSearchController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/PostSearchController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -31,14 +31,14 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import org.openecomp.portalsdk.core.command.PostSearchBean;
+import org.openecomp.portalsdk.core.command.support.SearchResult;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.Lookup;
import org.openecomp.portalsdk.core.domain.Profile;
-import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.LdapService;
import org.openecomp.portalsdk.core.service.PostSearchService;
import org.openecomp.portalsdk.core.service.ProfileService;
-import org.openecomp.portalsdk.core.service.UserProfileService;
import org.openecomp.portalsdk.core.web.support.JsonMessage;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -56,7 +56,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@RequestMapping("/")
public class PostSearchController extends RestrictedBaseController {
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PostSearchController.class);
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PostSearchController.class);
@SuppressWarnings("rawtypes")
private static List sortByList = null;
@@ -65,21 +65,10 @@ public class PostSearchController extends RestrictedBaseController {
private PostSearchService postSearchService;
@Autowired
- LdapService ldapService;
+ private LdapService ldapService;
@Autowired
private ProfileService profileService;
-
- @Autowired
- UserProfileService userProfileService;
-
- public UserProfileService getUserProfileService() {
- return userProfileService;
- }
-
- public void setUserProfileService(UserProfileService userProfileService) {
- this.userProfileService = userProfileService;
- }
@RequestMapping(value = { "/post_search" }, method = RequestMethod.GET)
public ModelAndView welcome(HttpServletRequest request,
@@ -125,13 +114,14 @@ public class PostSearchController extends RestrictedBaseController {
private HashMap getExistingUsers() {
HashMap existingUsers = new HashMap();
+ // get the list of user ids in the system
List<Profile> list = profileService.findAll();
if (list != null) {
Iterator<Profile> i = list.iterator();
while (i.hasNext()) {
Profile user = i.next();
- String orgUserId = user.getOrgUserId();
+ String orgUserId = user.getOrgUserId(); // userid scalar
Long id = user.getId(); // id scalar
if (orgUserId != null)
existingUsers.put(orgUserId, id);
@@ -149,15 +139,15 @@ public class PostSearchController extends RestrictedBaseController {
PostSearchBean postSearchBean = mapper.readValue(root.get("postSearchBean").toString(),
PostSearchBean.class);
- //postSearchBean.setSearchResult(loadSearchResultData(request, postSearchBean));
- List<User> users = loadSearchResultDataFromFnTableOrExt(request,postSearchBean);
+ postSearchBean.setSearchResult(loadSearchResultData(request, postSearchBean));
+
response.setCharacterEncoding("UTF-8");
response.setContentType("application / json");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
- String responseString = mapper.writeValueAsString(users);
- JSONObject j = new JSONObject("{users: " + responseString + "}");
+ String responseString = mapper.writeValueAsString(postSearchBean);
+ JSONObject j = new JSONObject("{postSearchBean: " + responseString + "}");
out.write(j.toString());
} catch (Exception ex) {
@@ -182,9 +172,9 @@ public class PostSearchController extends RestrictedBaseController {
return sortByList;
} // getSortByList
- private List<User> loadSearchResultDataFromFnTableOrExt(HttpServletRequest request, PostSearchBean searchCriteria)
+ private SearchResult loadSearchResultData(HttpServletRequest request, PostSearchBean searchCriteria)
throws Exception {
- return userProfileService.searchPost(searchCriteria.getUser(), searchCriteria.getSortBy1(),
+ return ldapService.searchPost(searchCriteria.getUser(), searchCriteria.getSortBy1(),
searchCriteria.getSortBy2(), searchCriteria.getSortBy3(), searchCriteria.getPageNo(),
searchCriteria.getNewDataSize(), UserUtils.getUserSession(request).getId().intValue());
}
@@ -196,21 +186,23 @@ public class PostSearchController extends RestrictedBaseController {
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
JsonNode root = mapper.readTree(request.getReader());
PostSearchBean postSearch = mapper.readValue(root.get("postSearchBean").toString(), PostSearchBean.class);
-
- postSearchService.process(request, postSearch);
- List<User> users = loadSearchResultDataFromFnTableOrExt(request,postSearch);
-
+ String errorMsg = "{}";
+ try{
+ postSearchService.process(request, postSearch);
+ postSearch.setSearchResult(loadSearchResultData(request, postSearch));
+ }catch(Exception e){
+ errorMsg=e.getMessage();
+ logger.error(EELFLoggerDelegate.errorLogger,"Exception occurred while performing PostSearchController.process. Details:", e);
+ }
logger.info(EELFLoggerDelegate.auditLogger, "Import new user from webphone ");
-
-
response.setCharacterEncoding("UTF-8");
response.setContentType("application / json");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
- String userString = mapper.writeValueAsString(users);
- JSONObject j = new JSONObject("{users: " + userString + ",existingUsers: "
- + mapper.writeValueAsString(getExistingUsers()) + "}");
+ String postSearchString = mapper.writeValueAsString(postSearch);
+ JSONObject j = new JSONObject("{postSearchBean: " + postSearchString + ",existingUsers: "
+ + mapper.writeValueAsString(getExistingUsers()) + ",errorMsg:"+errorMsg+"}");
out.write(j.toString());
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileController.java
index 1fd7800f..a774274c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import java.io.IOException;
import java.io.PrintWriter;
@@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
@@ -52,13 +53,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@RequestMapping("/")
public class ProfileController extends RestrictedBaseController {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProfileController.class);
+
@Autowired
UserProfileService service;
+
@Autowired
RoleService roleService;
- String viewName;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProfileController.class);
+ private String viewName;
@RequestMapping(value = { "/profile" }, method = RequestMethod.GET)
public ModelAndView profile(HttpServletRequest request) {
@@ -84,7 +87,7 @@ public class ProfileController extends RestrictedBaseController {
model.put("profile", mapper.writeValueAsString(profile));
model.put("profileId", mapper.writeValueAsString(profileId));
} catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "profile: failed to write JSON" + e.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "profile: failed to write JSON", e);
}
return new ModelAndView("profile", "model", model);
}
@@ -346,4 +349,4 @@ public class ProfileController extends RestrictedBaseController {
return roleService.getAvailableRoles();
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileSearchController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileSearchController.java
new file mode 100644
index 00000000..c5614f80
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/ProfileSearchController.java
@@ -0,0 +1,163 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.MenuData;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.FnMenuService;
+import org.openecomp.portalsdk.core.service.UserProfileService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+@RequestMapping("/")
+public class ProfileSearchController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProfileSearchController.class);
+
+ @Autowired
+ UserProfileService service;
+
+ @Autowired
+ FnMenuService fnMenuService;
+
+ @RequestMapping(value = { "/profile_search" }, method = RequestMethod.GET)
+ public ModelAndView ProfileSearch(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+ List<User> profileList = null;
+ logger.info(EELFLoggerDelegate.applicationLogger, "Initiating ProfileSearch in ProfileSearchController");
+ try {
+ profileList = service.findAll();
+ model.putAll(setDashboardData(request));
+ model.put("profileList", mapper.writeValueAsString(profileList));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "error while profile_search process in ProfileSearchController" + e.getMessage());
+ }
+ return new ModelAndView(getViewName(), "model", model);
+ }
+
+ @RequestMapping(value = { "/get_user" }, method = RequestMethod.GET)
+ public void GetUser(HttpServletRequest request, HttpServletResponse response) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "Initiating get_user in ProfileSearchController");
+ ObjectMapper mapper = new ObjectMapper();
+ List<User> profileList = null;
+ try {
+ profileList = service.findAll();
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(profileList));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "error while get_user process in ProfileSearchController" + e.getMessage());
+ }
+ }
+
+ @RequestMapping(value = { "/get_user_pagination" }, method = RequestMethod.GET)
+ public void getUserPagination(HttpServletRequest request, HttpServletResponse response) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+ logger.info(EELFLoggerDelegate.applicationLogger, "Initiating get_user_pagination in ProfileSearchController");
+ int pageNum = Integer.parseInt(request.getParameter("pageNum"));
+ int viewPerPage = Integer.parseInt(request.getParameter("viewPerPage"));
+ List<User> profileList = null;
+ try {
+ profileList = service.findAll();
+ model.put("totalPage", (int) Math.ceil((double) profileList.size() / viewPerPage));
+ profileList = profileList.subList(
+ viewPerPage * (pageNum - 1) < profileList.size() ? viewPerPage * (pageNum - 1) : profileList.size(),
+ viewPerPage * pageNum < profileList.size() ? viewPerPage * pageNum : profileList.size());
+ model.put("profileList", mapper.writeValueAsString(profileList));
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "error while get_user_pagination process in ProfileSearchController" + e.getMessage());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, Object> setDashboardData(HttpServletRequest request) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ Map<String, Object> model = new HashMap<String, Object>();
+ List<List<MenuData>> childItemList = new ArrayList<List<MenuData>>();
+ List<MenuData> parentList = new ArrayList<MenuData>();
+ logger.info(EELFLoggerDelegate.applicationLogger, "Initiating setDashboardData in ProfileSearchController");
+ HttpSession session = request.getSession();
+ try {
+ Set<MenuData> menuResult = (Set<MenuData>) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
+ fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "error while setDashboardData process in ProfileSearchController" + e.getMessage());
+ }
+ model.put("childItemList", mapper.writeValueAsString(childItemList));
+ model.put("parentList", mapper.writeValueAsString(parentList));
+ return model;
+ }
+
+ @RequestMapping(value = { "/profile/toggleProfileActive" }, method = RequestMethod.GET)
+ public void toggleProfileActive(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ try {
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Initiating toggleProfileActive in ProfileSearchController");
+ String userId = request.getParameter("profile_id");
+ User user = (User) service.getUser(userId);
+ user.setActive(!user.getActive());
+ service.saveUser(user);
+ logger.info(EELFLoggerDelegate.auditLogger,
+ "Change active status for user " + user.getId() + " to " + user.getActive());
+ ObjectMapper mapper = new ObjectMapper();
+ response.setContentType("application/json");
+ PrintWriter out = response.getWriter();
+ out.write(mapper.writeValueAsString(user.getActive()));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "error while toggleProfileActive process in ProfileSearchController" + e.getMessage());
+ }
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleController.java
new file mode 100644
index 00000000..ca902c49
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleController.java
@@ -0,0 +1,342 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.RoleFunction;
+import org.openecomp.portalsdk.core.logging.aspect.EELFLoggerAdvice;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.RoleService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.ServletRequestUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+@Controller
+@RequestMapping("/")
+public class RoleController extends RestrictedBaseController {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleController.class);
+
+ @Autowired
+ RoleService roleService;
+
+ private String viewName;
+
+ @RequestMapping(value = { "/role" }, method = RequestMethod.GET)
+ public ModelAndView role(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+
+ Role role = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+ logger.info("role_id" + role.getId());
+ try {
+ model.put("availableRoleFunctions", mapper.writeValueAsString(roleService.getRoleFunctions()));
+ model.put("availableRoles", mapper.writeValueAsString(roleService.getAvailableChildRoles(role.getId())));
+ model.put("role", mapper.writeValueAsString(role));
+ } catch (Exception e) {
+ logger.error("role: failed", e);
+ logger.error(EELFLoggerDelegate.errorLogger, "role failed", e);
+ }
+ return new ModelAndView(getViewName(), model);
+ }
+
+ @RequestMapping(value = { "/get_role" }, method = RequestMethod.GET)
+ public void getRole(HttpServletRequest request, HttpServletResponse response) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+
+ Role role = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+ logger.info(EELFLoggerDelegate.applicationLogger, "role_id" + role.getId());
+ try {
+ model.put("availableRoleFunctions", mapper.writeValueAsString(roleService.getRoleFunctions()));
+ model.put("availableRoles", mapper.writeValueAsString(roleService.getAvailableChildRoles(role.getId())));
+ model.put("role", mapper.writeValueAsString(role));
+
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRole failed", e);
+ }
+
+ }
+
+ /**
+ * Creates a new role or updates an existing role.
+ *
+ * @param request
+ * @param response
+ * @return Always returns null.
+ * @throws IOException
+ * If the write to the result project fails
+ */
+ @RequestMapping(value = { "/role/saveRole" }, method = RequestMethod.POST)
+ public ModelAndView saveRole(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ JSONObject j = null;
+ logger.debug(EELFLoggerDelegate.debugLogger, "RoleController.save");
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ Role role = mapper.readValue(root.get("role").toString(), Role.class);
+
+ List<Role> childRoles = mapper.readValue(root.get("childRoles").toString(),
+ TypeFactory.defaultInstance().constructCollectionType(List.class, Role.class));
+
+ List<RoleFunction> roleFunctions = mapper.readValue(root.get("roleFunctions").toString(),
+ TypeFactory.defaultInstance().constructCollectionType(List.class, RoleFunction.class));
+
+ Role domainRole = null;
+ if (role.getId() != null) {
+ doAuditLog("saveRole: updating existing role {}", role.getId());
+ domainRole = roleService.getRole(role.getId());
+
+ domainRole.setName(role.getName());
+ domainRole.setPriority(role.getPriority());
+ } else {
+ doAuditLog("saveRole: creating new role", role.getName());
+ // check for existing role of same name
+ List<Role> roles = roleService.getAvailableRoles();
+ for (Role existRole : roles)
+ if (existRole.getName().equalsIgnoreCase(role.getName()))
+ throw new Exception("role already exists: " + existRole.getName());
+
+ domainRole = new Role();
+ domainRole.setName(role.getName());
+ domainRole.setPriority(role.getPriority());
+ if (role.getChildRoles().size() > 0) {
+ for (Object childRole : childRoles) {
+ domainRole.addChildRole((Role) childRole);
+ }
+ }
+ if (role.getRoleFunctions().size() > 0) {
+ for (Object roleFunction : roleFunctions) {
+ domainRole.addRoleFunction((RoleFunction) roleFunction);
+ }
+ }
+ }
+
+ roleService.saveRole(domainRole);
+
+ String responseString = mapper.writeValueAsString(domainRole);
+ j = new JSONObject("{role: " + responseString + "}");
+ } catch (Exception e) {
+ // Produce JSON error message
+ logger.error(EELFLoggerDelegate.errorLogger, "saveRole failed", e);
+ j = new JSONObject("{error: '" + e.getMessage() + "'}");
+ }
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ return null;
+ }
+
+ @RequestMapping(value = { "/role/removeRoleFunction" }, method = RequestMethod.POST)
+ public ModelAndView removeRoleFunction(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeRoleFunction");
+ try {
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ RoleFunction roleFunction = mapper.readValue(root.get("roleFunction").toString(), RoleFunction.class);
+
+ Role domainRole = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+ doAuditLog("Remove role function {} from role {}", roleFunction.getCode(),
+ ServletRequestUtils.getIntParameter(request, "role_id", 0));
+
+ domainRole.removeRoleFunction(roleFunction.getCode());
+
+ roleService.saveRole(domainRole);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ String responseString = mapper.writeValueAsString(domainRole);
+ JSONObject j = new JSONObject("{role: " + responseString + "}");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ return null;
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "removeRole failed", e);
+ response.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ return null;
+ }
+
+ }
+
+ @RequestMapping(value = { "/role/addRoleFunction" }, method = RequestMethod.POST)
+ public ModelAndView addRoleFunction(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeRoleFunction");
+ try {
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ RoleFunction roleFunction = mapper.readValue(root.get("roleFunction").toString(), RoleFunction.class);
+
+ Role domainRole = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+
+ domainRole.addRoleFunction(roleFunction);
+
+ roleService.saveRole(domainRole);
+ doAuditLog("Add role function {} to role {}", roleFunction.getCode(),
+ ServletRequestUtils.getIntParameter(request, "role_id", 0));
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ String responseString = mapper.writeValueAsString(domainRole);
+ JSONObject j = new JSONObject("{role: " + responseString + "}");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ return null;
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "removeRoleFunction failed", e);
+ response.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ return null;
+ }
+
+ }
+
+ @RequestMapping(value = { "/role/removeChildRole" }, method = RequestMethod.POST)
+ public ModelAndView removeChildRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeChileRole");
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ Role childRole = mapper.readValue(root.get("childRole").toString(), Role.class);
+
+ Role domainRole = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+
+ domainRole.removeChildRole(childRole.getId());
+ doAuditLog("remove child role {} from role {}", childRole.getId(),
+ ServletRequestUtils.getIntParameter(request, "role_id", 0));
+
+ roleService.saveRole(domainRole);
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ String responseString = mapper.writeValueAsString(domainRole);
+ JSONObject j = new JSONObject("{role: " + responseString + "}");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ return null;
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "removeChildRole failed", e);
+ response.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ return null;
+ }
+
+ }
+
+ @RequestMapping(value = { "/role/addChildRole" }, method = RequestMethod.POST)
+ public ModelAndView addChildRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.addChileRole");
+ try {
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ Role childRole = mapper.readValue(root.get("childRole").toString(), Role.class);
+
+ Role domainRole = roleService.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
+
+ domainRole.addChildRole(childRole);
+
+ roleService.saveRole(domainRole);
+ doAuditLog("Add child role {} to role {}", childRole.getId(),
+ ServletRequestUtils.getIntParameter(request, "role_id", 0));
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json");
+ String responseString = mapper.writeValueAsString(domainRole);
+ JSONObject j = new JSONObject("{role: " + responseString + "}");
+ PrintWriter out = response.getWriter();
+ out.write(j.toString());
+ return null;
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "addChildRole failed", e);
+ response.setCharacterEncoding("UTF-8");
+ PrintWriter out = response.getWriter();
+ out.write(e.getMessage());
+ return null;
+ }
+
+ }
+
+ /**
+ * Sets context with begin and end timestamps at current date & time, writes
+ * the specified message and parameters to the audit log, then removes the
+ * timestamps from context.
+ *
+ * @param message
+ * @param parameters
+ */
+ private void doAuditLog(String message, Object... parameters) {
+ final String currentDateTime = EELFLoggerAdvice.getCurrentDateTimeUTC();
+ // Set the MDC with audit properties
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, currentDateTime);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, currentDateTime);
+ logger.info(EELFLoggerDelegate.auditLogger, message, parameters);
+ MDC.remove(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.AUDITLOG_END_TIMESTAMP);
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleFunctionListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleFunctionListController.java
new file mode 100644
index 00000000..13b3a7c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleFunctionListController.java
@@ -0,0 +1,172 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.domain.RoleFunction;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.RoleService;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+@RequestMapping("/")
+public class RoleFunctionListController extends RestrictedBaseController {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleFunctionListController.class);
+
+ @Autowired
+ RoleService service;
+
+ private String viewName;
+
+ @RequestMapping(value = {"/role_function_list" }, method = RequestMethod.GET)
+ public ModelAndView welcome(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+ model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "welcome failed", e);
+ }
+
+ return new ModelAndView(getViewName(),model);
+ }
+
+ @RequestMapping(value = {"/get_role_functions" }, method = RequestMethod.GET)
+ public void getRoleFunctionList(HttpServletRequest request,HttpServletResponse response) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+ model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getROleFunctionList failed", e);
+ }
+
+ }
+
+ @RequestMapping(value = {"/role_function_list/saveRoleFunction" }, method = RequestMethod.POST)
+ public void saveRoleFunction(HttpServletRequest request,
+ HttpServletResponse response, @RequestBody String roleFunc) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ String restCallStatus = "";
+ try {
+ String data = roleFunc;
+ RoleFunction availableRoleFunction = mapper.readValue(data, RoleFunction.class);
+ String code = availableRoleFunction.getCode();
+ RoleFunction domainRoleFunction = service.getRoleFunction(code);
+ domainRoleFunction.setName(availableRoleFunction.getName());
+ domainRoleFunction.setCode(code);
+ restCallStatus="success";
+ service.saveRoleFunction(domainRoleFunction);
+ } catch (Exception e) {
+ restCallStatus="fail";
+ logger.error(EELFLoggerDelegate.errorLogger, "saveRoleFunction failed", e);
+ }
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(restCallStatus));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ }
+
+ @RequestMapping(value = {"/role_function_list/addRoleFunction" }, method = RequestMethod.POST)
+ public void addRoleFunction(HttpServletRequest request,
+ HttpServletResponse response, @RequestBody String roleFunc) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ String restCallStatus = "";
+ boolean canSave=true;
+ try {
+ String data = roleFunc;
+ RoleFunction availableRoleFunction = mapper.readValue(data, RoleFunction.class);
+ String code = availableRoleFunction.getCode();
+ RoleFunction domainRoleFunction = service.getRoleFunction(code);
+ domainRoleFunction.setName(availableRoleFunction.getName());
+ domainRoleFunction.setCode(code);
+ List<RoleFunction> currentRoleFunction = service.getRoleFunctions();
+ restCallStatus="success";
+ for(RoleFunction roleF:currentRoleFunction){
+ if(roleF.getCode().equals(code)){
+ restCallStatus="code exists";
+ canSave=false;
+ break;
+ }
+ }
+ if(canSave)
+ service.saveRoleFunction(domainRoleFunction);
+ } catch (Exception e) {
+ restCallStatus="fail";
+ logger.error(EELFLoggerDelegate.errorLogger, "addRoleFunction failed", e);
+ }
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(restCallStatus));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ }
+
+ @RequestMapping(value = {"/role_function_list/removeRoleFunction" }, method = RequestMethod.POST)
+ public void removeRoleFunction(HttpServletRequest request,
+ HttpServletResponse response, @RequestBody String roleFunc) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ String restCallStatus = "";
+ try {
+ String data = roleFunc;
+
+ RoleFunction availableRoleFunction = mapper.readValue(data, RoleFunction.class);
+
+ RoleFunction domainRoleFunction = service.getRoleFunction(availableRoleFunction.getCode());
+
+ service.deleteRoleFunction(domainRoleFunction);
+ logger.info(EELFLoggerDelegate.auditLogger, "Remove role function " + domainRoleFunction.getName());
+ restCallStatus="success";
+ } catch (Exception e) {
+ restCallStatus="fail";
+ logger.error(EELFLoggerDelegate.errorLogger, "removeRoleFunction failed", e);
+ }
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(restCallStatus));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleListController.java
index 78fbc19f..be08d4e9 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleListController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/RoleListController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,9 +17,8 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.RoleService;
@@ -38,34 +38,29 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
-import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
@RequestMapping("/")
public class RoleListController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleListController.class);
@Autowired
RoleService service;
- String viewName;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleListController.class);
-
+
+ private String viewName;
@RequestMapping(value = {"/role_list" }, method = RequestMethod.GET)
- public ModelAndView role(HttpServletRequest request) {
+ public ModelAndView getRoleList(HttpServletRequest request) {
Map<String, Object> model = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
try {
model.put("availableRoles", mapper.writeValueAsString(service.getAvailableRoles()));
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRoleList failed", e);
}
return new ModelAndView(getViewName(),model);
@@ -81,12 +76,8 @@ public class RoleListController extends RestrictedBaseController {
JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
JSONObject j = new JSONObject(msg);
response.getWriter().write(j.toString());
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getRoles failed", e);
}
}
@@ -96,7 +87,6 @@ public class RoleListController extends RestrictedBaseController {
HttpServletResponse response) throws Exception {
try {
-
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonNode root = mapper.readTree(request.getReader());
@@ -122,6 +112,7 @@ public class RoleListController extends RestrictedBaseController {
return null;
} catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "toggleRole failed", e);
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
@@ -160,7 +151,7 @@ public class RoleListController extends RestrictedBaseController {
return null;
} catch (Exception e) {
- System.out.println(e);
+ logger.error(EELFLoggerDelegate.errorLogger, "removeRole failed", e);
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SDKLoginController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SDKLoginController.java
new file mode 100644
index 00000000..10d2b95a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SDKLoginController.java
@@ -0,0 +1,99 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.auth.LoginStrategy;
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.service.LoginService;
+import org.openecomp.portalsdk.core.service.ProfileService;
+import org.openecomp.portalsdk.core.web.support.AppUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+@Controller
+@RequestMapping("/")
+public class SDKLoginController extends UnRestrictedBaseController {
+ @Autowired
+ ProfileService service;
+ @Autowired
+ private LoginService loginService;
+ @Autowired
+ private LoginStrategy loginStrategy;
+
+ private String viewName;
+
+ @RequestMapping(value = { "/login.htm" }, method = RequestMethod.GET)
+ public ModelAndView login(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView("login", "model", model);
+ }
+
+ @RequestMapping(value = { "/login_external.htm" }, method = RequestMethod.GET)
+ public ModelAndView externalLogin(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView("login_external", "model", model);
+ }
+
+ @RequestMapping(value = { "/login_external" }, method = RequestMethod.POST)
+ public ModelAndView doexternalLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return loginStrategy.doExternalLogin(request, response);
+ }
+
+ @RequestMapping(value = { "/doLogin" }, method = RequestMethod.GET)
+ public ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return loginStrategy.doLogin(request, response);
+ }
+
+ public String getJessionId(HttpServletRequest request) {
+ return request.getSession().getId();
+ }
+
+ protected void initateSessionMgtHandler(HttpServletRequest request) {
+ String jSessionId = getJessionId(request);
+ PortalTimeoutHandler.sessionCreated(jSessionId, jSessionId, AppUtils.getSession(request));
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public void setViewName(String viewName) {
+ this.viewName = viewName;
+ }
+
+ public LoginService getLoginService() {
+ return loginService;
+ }
+
+ public void setLoginService(LoginService loginService) {
+ this.loginService = loginService;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/SingleSignOnController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SingleSignOnController.java
index 4a0fb6f7..9ffa1d1d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/SingleSignOnController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/SingleSignOnController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import java.net.URLDecoder;
import java.net.URLEncoder;
@@ -28,16 +28,16 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
+import org.openecomp.portalsdk.core.auth.LoginStrategy;
import org.openecomp.portalsdk.core.command.LoginBean;
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.menu.MenuProperties;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.service.LoginService;
-import org.openecomp.portalsdk.core.service.ProfileService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.AppUtils;
import org.openecomp.portalsdk.core.web.support.UserUtils;
@@ -52,19 +52,15 @@ import org.springframework.web.util.WebUtils;
@RequestMapping("/")
public class SingleSignOnController extends UnRestrictedBaseController {
- private static final String EP_SERVICE = "EPService";
- private static final String USER_ID = "UserId";
- public static final String DEFAULT_SUCCESS_VIEW = "welcome";
- public static final String DEFAULT_FAILURE_VIEW = "login";
- public static final String ERROR_MESSAGE_KEY = "error";
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SingleSignOnController.class);
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SingleSignOnController.class);
-
- @Autowired
- ProfileService service;
@Autowired
private LoginService loginService;
- String viewName;
+
+ @Autowired
+ private LoginStrategy loginStrategy;
+
+ private String viewName;
private String welcomeView;
public String getWelcomeView() {
@@ -99,9 +95,10 @@ public class SingleSignOnController extends UnRestrictedBaseController {
session = AppUtils.getSession(request);
User user = UserUtils.getUserSession(request);
if (session == null || user == null) {
- String orgUserId = "";
- orgUserId = getUserIdFromCookie(request);
- commandBean.setUserid(orgUserId);
+
+ final String authMech = SystemProperties.getProperty(SystemProperties.AUTHENTICATION_MECHANISM);
+ String userId = loginStrategy.getUserId(request);
+ commandBean.setUserid(userId);
commandBean = getLoginService().findUser(commandBean,
(String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY),
additionalParamsMap);
@@ -109,7 +106,7 @@ public class SingleSignOnController extends UnRestrictedBaseController {
String loginErrorMessage = (commandBean.getLoginErrorMessage() != null)
? commandBean.getLoginErrorMessage()
: SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND;
- model.put(ERROR_MESSAGE_KEY, SystemProperties.getProperty(loginErrorMessage));
+ model.put(LoginStrategy.ERROR_MESSAGE_KEY, SystemProperties.getProperty(loginErrorMessage));
final String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL)
+ "?noUserError=Yes";
logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: user is null, redirect URL is {}",
@@ -117,13 +114,20 @@ public class SingleSignOnController extends UnRestrictedBaseController {
return new ModelAndView("redirect:" + redirectUrl);
} else {
// store the user's information in the session
-
+ String loginMethod;
+ if (null == authMech || "".equals(authMech) || "BOTH".equals(authMech)) {
+ loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
+ } else if ("CSP".equals(authMech)) {
+ loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
+ } else {
+ loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_WEB_JUNCTION);
+ }
UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
- commandBean.getBusinessDirectMenu(), "");
+ commandBean.getBusinessDirectMenu(), loginMethod);
initateSessionMgtHandler(request);
logger.debug(EELFLoggerDelegate.debugLogger,
"singleSignOnLogin: create new user session for expired user {}; user {} exists in the system",
- commandBean.getUser().getOrgUserId());
+ userId, commandBean.getUser().getOrgUserId());
return new ModelAndView("redirect:" + forwardURL);
}
} // user is null or session is null
@@ -136,18 +140,21 @@ public class SingleSignOnController extends UnRestrictedBaseController {
} else {
/*
- * Login cookie not found, or redirect-to-portal parameter was found.
+ * Login cookie not found, or redirect-to-portal parameter was
+ * found.
*
* Redirect the user to the portal with a suitable return URL. The
* forwardURL parameter that arrives as a parameter is a partial
* (not absolute) request path for a page in the application. The
* challenge here is to compute the correct absolute path for the
* original request so the portal can redirect the user back to the
- * right place.
+ * right place. If the application sits behind WebJunction, or if
+ * separate FE-BE hosts are used, then the URL yielded by the
+ * request has a host name that is not reachable by the user.
*/
String returnToAppUrl = null;
if (SystemProperties.containsProperty(SystemProperties.APP_BASE_URL)) {
- // New feature:
+ // New feature as of 1610, release 3.3.3:
// application can publish a base URL in system.properties
String appUrl = SystemProperties.getProperty(SystemProperties.APP_BASE_URL);
returnToAppUrl = appUrl + (appUrl.endsWith("/") ? "" : "/") + forwardURL;
@@ -161,14 +168,15 @@ public class SingleSignOnController extends UnRestrictedBaseController {
// should always find the specified token.
returnToAppUrl = ((HttpServletRequest) request).getRequestURL().toString().replace("single_signon.htm",
forwardURL);
- logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}", returnToAppUrl);
+ logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}",
+ returnToAppUrl);
}
final String encodedReturnToAppUrl = URLEncoder.encode(returnToAppUrl, "UTF-8");
// Also send the application's UEB key so Portal can block URL
// reflection attacks.
final String uebAppKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
final String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
- final String portalUrl = url.substring(0, url.lastIndexOf('/')) + "/processSingleSignOn";
+ final String portalUrl = url.substring(0, url.lastIndexOf('/')) + "/process_csp";
final String redirectUrl = portalUrl + "?uebAppKey=" + uebAppKey + "&redirectUrl=" + encodedReturnToAppUrl;
logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: portal-bound redirect URL is {}",
redirectUrl);
@@ -183,30 +191,13 @@ public class SingleSignOnController extends UnRestrictedBaseController {
}
public boolean isLoginCookieExist(HttpServletRequest request) {
- Cookie ep = WebUtils.getCookie(request, EP_SERVICE);
+ Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
return (ep != null);
}
-
- public static String getUserIdFromCookie(HttpServletRequest request) throws Exception {
- String userId = "";
- Cookie[] cookies = request.getCookies();
- Cookie userIdcookie = null;
- if (cookies != null)
- for (Cookie cookie : cookies)
- if (cookie.getName().equals(USER_ID))
- userIdcookie = cookie;
- if(userIdcookie!=null){
- userId = CipherUtil.decrypt(userIdcookie.getValue(),
- SystemProperties.getProperty(SystemProperties.Decryption_Key));
- }
- return userId;
-
- }
public String getPortalJSessionId(HttpServletRequest request) {
- Cookie ep = WebUtils.getCookie(request, EP_SERVICE);
+ Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
return ep.getValue();
-
}
public String getJessionId(HttpServletRequest request) {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UsageListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UsageListController.java
index c5616575..d7dfbaa5 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UsageListController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UsageListController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.core;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -31,6 +31,7 @@ import javax.servlet.http.HttpSession;
import org.json.JSONArray;
import org.json.JSONObject;
import org.openecomp.portalsdk.core.command.UserRowBean;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.util.UsageUtils;
import org.openecomp.portalsdk.core.web.support.JsonMessage;
@@ -43,7 +44,7 @@ import org.springframework.web.servlet.ModelAndView;
@RequestMapping("/")
public class UsageListController extends RestrictedBaseController {
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UsageListController.class);
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UsageListController.class);
@SuppressWarnings({ "unchecked", "rawtypes" })
@RequestMapping(value = { "/usage_list" }, method = RequestMethod.GET)
@@ -75,7 +76,7 @@ public class UsageListController extends RestrictedBaseController {
ja.put(jo);
}
} catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "usageList 1: failed" + e.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "usageList failed", e);
}
model.put("model", ja);
@@ -83,9 +84,10 @@ public class UsageListController extends RestrictedBaseController {
return new ModelAndView(getViewName(), model);
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@RequestMapping(value = { "/get_usage_list" }, method = RequestMethod.GET)
- public void usageList(HttpServletRequest request, HttpServletResponse response) {
+ public void getUsageList(HttpServletRequest request, HttpServletResponse response) {
+
HttpSession httpSession = request.getSession();
HashMap activeUsers = (HashMap) httpSession.getServletContext().getAttribute("activeUsers");
if (activeUsers.size() == 0) {
@@ -111,7 +113,7 @@ public class UsageListController extends RestrictedBaseController {
ja.put(jo);
}
} catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "usageList 2: failed" + e.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "getUsageList failed", e);
}
JsonMessage msg;
try {
@@ -119,7 +121,7 @@ public class UsageListController extends RestrictedBaseController {
JSONObject j = new JSONObject(msg);
response.getWriter().write(j.toString());
} catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "usageList 3: failed" + e.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "getUsageList failed to serialize", e);
}
}
@@ -152,7 +154,7 @@ public class UsageListController extends RestrictedBaseController {
ja.put(jo);
}
} catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "removeSession: failed" + e.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "removeSession failed", e);
}
response.setContentType("application/json");
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/UserProfileController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UserProfileController.java
index 2f4ea93d..cee60e48 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/UserProfileController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/UserProfileController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,9 +17,8 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.core;
-import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.Profile;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.ProfileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@@ -35,8 +35,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
@@ -48,25 +46,23 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@RequestMapping("/")
public class UserProfileController extends RestrictedBaseController {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UserProfileController.class);
+
@Autowired
ProfileService service;
@RequestMapping(value = { "/user_profile" }, method = RequestMethod.GET)
- public ModelAndView ProfileSearch(HttpServletRequest request) {
+ public ModelAndView userProfile(HttpServletRequest request) {
Map<String, Object> model = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
List<Profile> profileList = service.findAll();
try {
model.put("customerInfo", mapper.writeValueAsString(profileList));
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "userProfile failed", e);
}
return new ModelAndView("user_profile", "model", model);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/WelcomeController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/WelcomeController.java
index 06853f0e..5ebe907f 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/WelcomeController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/WelcomeController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.core;
import javax.servlet.http.HttpServletRequest;
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/package-info.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/package-info.java
new file mode 100644
index 00000000..0930ab3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/core/package-info.java
@@ -0,0 +1,6 @@
+package org.openecomp.portalapp.controller.core;
+
+/**
+ * Provides controllers for EPSDK application core functionality such as logging
+ * in, managing roles, editing menus, etc.
+ */
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/AngularSinglePageController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/AngularSinglePageController.java
index e654a51c..efcd4291 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/AngularSinglePageController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/AngularSinglePageController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,19 +17,20 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.sample;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
-import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+
/**
* Controller for a single-page application sample. The view is restricted to
* authenticated users. The named view resolves to page singlePageSample.html,
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastController.java
index 6dfe9cac..9c04ce89 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.sample;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.BroadcastMessage;
import org.openecomp.portalsdk.core.service.BroadcastService;
import org.openecomp.portalsdk.core.util.SystemProperties;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastListController.java
index 7e0789c2..41603460 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/BroadcastListController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/BroadcastListController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.sample;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.BroadcastMessage;
import org.openecomp.portalsdk.core.service.BroadcastService;
import org.openecomp.portalsdk.core.web.support.JsonMessage;
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/CallflowController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CallflowController.java
index a3d1be5f..b25cbef4 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/CallflowController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CallflowController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.sample;
import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.springframework.stereotype.Controller;
@@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
+
/**
* Controller for a message sequence chart view. The view is restricted to
* authenticated users. The view name defaults to the request name with no
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CamundaCockpitController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CamundaCockpitController.java
new file mode 100644
index 00000000..e5cfb3f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CamundaCockpitController.java
@@ -0,0 +1,60 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+
+
+/**
+ * @author chris zeng
+ *
+ */
+
+@Controller
+@RequestMapping("/")
+public class CamundaCockpitController extends RestrictedBaseController {
+ @SuppressWarnings("rawtypes")
+ @RequestMapping(value = {"/get_camunda_cockpit_link" }, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public Map getCamundaCockpitLink(HttpServletRequest request,HttpServletResponse response) {
+ Map<String,String> map = new HashMap<String,String>();
+ String camundaCockpitUrl = "";
+ String camundaCockpitlinkDefined = "false";
+ if (SystemProperties.containsProperty("camunda_cockpit_link")){
+ camundaCockpitUrl = SystemProperties.getProperty("camunda_cockpit_link");
+ camundaCockpitlinkDefined = "true";
+ };
+ map.put("link_defined", camundaCockpitlinkDefined);
+ map.put("camunda_cockpit_link", camundaCockpitUrl);
+ return map;
+ };
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborateListController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborateListController.java
index 9e43e948..03aaab5f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborateListController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborateListController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.sample;
import java.util.HashMap;
import java.util.List;
@@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.UserProfileService;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborationController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborationController.java
index a9c1d44b..55920bb8 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CollaborationController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/CollaborationController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,13 +17,14 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.controller;
+package org.openecomp.portalapp.controller.sample;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.stereotype.Controller;
@@ -43,5 +44,12 @@ public class CollaborationController extends RestrictedBaseController{
model.put("name",(user.getFirstName() + " " + (user.getLastName() != null? user.getLastName().substring(0,1): "" )));
return new ModelAndView(getViewName(),"model", model);
}
-
-}
+ @RequestMapping(value = {"/openCollaboration" }, method = RequestMethod.GET)
+ public ModelAndView openCollaboration(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ User user = UserUtils.getUserSession(request);
+
+ model.put("name",(user.getFirstName() + " " + (user.getLastName() != null? user.getLastName().substring(0,1): "" )));
+ return new ModelAndView("openCollaboration","model", model);
+ }
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/DS2SampleController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/DS2SampleController.java
new file mode 100644
index 00000000..17f33c77
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/DS2SampleController.java
@@ -0,0 +1,54 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
+import org.openecomp.portalsdk.core.service.ProfileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+
+/**
+ * Controller for user profile view. The view is restricted to authenticated
+ * users. The view name resolves to page user_profile.jsp which uses Angular.
+ */
+
+@Controller
+@RequestMapping("/")
+public class DS2SampleController extends UnRestrictedBaseController {
+
+ @Autowired
+ ProfileService service;
+
+ @RequestMapping(value = { "/ds2_sample" }, method = RequestMethod.GET)
+ public ModelAndView ProfileSearch(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView("ds2_sample", "model", model);
+ }
+
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/ElasticSearchController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElasticSearchController.java
index 69ff63db..69e5051f 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/ElasticSearchController.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElasticSearchController.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.sample;
import java.io.IOException;
@@ -125,4 +125,4 @@ public class ElasticSearchController extends RestrictedBaseController{
public boolean isRESTfulCall() {
return true;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElementModelController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElementModelController.java
new file mode 100644
index 00000000..e36458fd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ElementModelController.java
@@ -0,0 +1,87 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.ElementLinkService;
+import org.openecomp.portalsdk.core.service.ElementMapService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/")
+public class ElementModelController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ElementModelController.class);
+
+ @RequestMapping(value = { "/elementMapLayout" }, method = RequestMethod.GET, produces = "text/plain")
+ public String layout(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ String collapseDomains = request.getParameter("collapsedDomains");
+ String expandDomains = request.getParameter("expandedDomains");
+
+ String contentFileName = request.getParameter("contentFileName");
+ String layoutFileName = request.getParameter("layoutFileName");
+
+ final String realPath = request.getServletContext().getRealPath("/");
+ logger.debug(EELFLoggerDelegate.debugLogger, "layout: servlet context real path: {}", realPath);
+
+ ElementMapService eltMapSvc = new ElementMapService();
+ String yamlString = eltMapSvc.buildElementMapYaml(
+ new String[] { collapseDomains, expandDomains, realPath, contentFileName, layoutFileName });
+
+ return yamlString;
+ }
+
+ @RequestMapping(value = { "/elementMapLink" }, method = RequestMethod.GET, produces = "text/plain")
+ public String callflow(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ String callFlowName = request.getParameter("callFlowName");
+ String callFlowStep = request.getParameter("callFlowStep");
+
+ final String realPath = request.getServletContext().getRealPath("/");
+ logger.debug(EELFLoggerDelegate.debugLogger, "callflow: servlet context real path: {}", realPath);
+
+ ElementLinkService eltLinkSvc = new ElementLinkService();
+ String yamlString = eltLinkSvc.buildElementLinkYaml(new String[] { realPath, callFlowName, callFlowStep });
+
+ return yamlString;
+ }
+
+ /*
+ public ModelAndView callflowAdditional(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ Map<String, Object> model = new HashMap<String, Object>();
+ String callFlowName = request.getParameter("callFlowName");
+ String callFlowStep = request.getParameter("callFlowStep");
+
+ ElementLinkService main = new ElementLinkService();
+ String yamlString = main.main2(new String[] { callFlowName, callFlowStep });
+ model.put("output_string", yamlString);
+ return new ModelAndView("data_out", "model", model);
+ }
+ */
+
+}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/LeafletMapContoller.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/LeafletMapContoller.java
index 4c603fe1..bda3c0aa 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/LeafletMapContoller.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/LeafletMapContoller.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalapp.controller;
+package org.openecomp.portalapp.controller.sample;
import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.springframework.stereotype.Controller;
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/NetMapController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/NetMapController.java
new file mode 100644
index 00000000..1961edf8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/NetMapController.java
@@ -0,0 +1,57 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Controller for a network map view that uses iframes. The view is restricted
+ * to authenticated users.
+ */
+@Controller
+@RequestMapping("/")
+public class NetMapController extends RestrictedBaseController {
+
+ @RequestMapping(value = { "/net_map" }, method = RequestMethod.GET)
+ public ModelAndView plot(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put("frame_int", "net_map_int");
+ // This view resolves to page frame_insert.jsp
+ return new ModelAndView("frame_insert", model);
+ }
+
+ @RequestMapping(value = { "/net_map_int" }, method = RequestMethod.GET)
+ public ModelAndView plot2() {
+ // The view name defaults to the request without any suffix.
+ final String defaultViewName = null;
+ // This view resolves to page net_map.jsp
+ return new ModelAndView(defaultViewName);
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/PostDroolsController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/PostDroolsController.java
new file mode 100644
index 00000000..5a0719ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/PostDroolsController.java
@@ -0,0 +1,122 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.openecomp.portalsdk.core.command.PostDroolsBean;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.PostDroolsService;
+import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+@RequestMapping("/")
+public class PostDroolsController extends RestrictedBaseController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PostDroolsController.class);
+
+ @Autowired
+ private PostDroolsService postDroolsService;
+
+ @RequestMapping(value = { "/drools" }, method = RequestMethod.GET)
+ public ModelAndView drools(HttpServletRequest request) {
+ return new ModelAndView(getViewName());
+ }
+
+ @RequestMapping(value = { "/getDrools" }, method = RequestMethod.GET)
+ public void getDrools(HttpServletRequest request, HttpServletResponse response) {
+ // Map<String, Object> model = new HashMap<String, Object>();
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ List<PostDroolsBean> beanList = postDroolsService.fetchDroolBeans();
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(beanList));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getDrools failed", e);
+ }
+ }
+
+ @RequestMapping(value = { "/getDroolDetails" }, method = RequestMethod.GET)
+ public void getDroolDetails(HttpServletRequest request, HttpServletResponse response) {
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+
+ PostDroolsBean postDroolsBean = new PostDroolsBean();
+ String selectedFile = request.getParameter("selectedFile");
+ postDroolsBean.setDroolsFile(selectedFile);// sample populated
+ // postDroolsBean.setSelectedRules("[\"NJ\",\"NY\",\"KY\"]");
+ postDroolsBean.setClassName(postDroolsService.retrieveClass(selectedFile));
+
+ JsonMessage msg = new JsonMessage(mapper.writeValueAsString(postDroolsBean));
+ JSONObject j = new JSONObject(msg);
+ response.getWriter().write(j.toString());
+
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getDroolDetails failed", e);
+ }
+ }
+
+ @RequestMapping(value = { "/post_drools/execute" }, method = RequestMethod.POST)
+ public ModelAndView search(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ JsonNode root = mapper.readTree(request.getReader());
+ PostDroolsBean postDroolsBean = mapper.readValue(root.get("postDroolsBean").toString(),
+ PostDroolsBean.class);
+
+ String resultsString = postDroolsService.execute(postDroolsBean.getDroolsFile(),
+ postDroolsBean.getClassName(), postDroolsBean.getSelectedRules());
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application / json");
+ request.setCharacterEncoding("UTF-8");
+
+ PrintWriter out = response.getWriter();
+ // String responseString = mapper.writeValueAsString(resultsString);
+ JSONObject j = new JSONObject("{resultsString: " + resultsString + "}");
+
+ out.write(j.toString());
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "search failed", e);
+ }
+
+ return null;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ReportDashboardController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ReportDashboardController.java
new file mode 100644
index 00000000..9cc44c86
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/ReportDashboardController.java
@@ -0,0 +1,46 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Report dashboard
+ *
+ */
+
+@Controller
+@RequestMapping("/")
+public class ReportDashboardController extends RestrictedBaseController {
+ @RequestMapping(value = {"/report_dashboard" }, method = RequestMethod.GET)
+ public ModelAndView adminView(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ return new ModelAndView(getViewName(),"model", model);
+ }
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/SamplePageController.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/SamplePageController.java
new file mode 100644
index 00000000..e01bb8c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/SamplePageController.java
@@ -0,0 +1,50 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.controller.sample;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Controller for a network map view that uses iframes. The view is restricted
+ * to authenticated users.
+ */
+@Controller
+@RequestMapping("/")
+public class SamplePageController extends RestrictedBaseController {
+
+ @RequestMapping(value = { "/samplePage" }, method = RequestMethod.GET)
+ public ModelAndView plot(HttpServletRequest request) {
+ Map<String, Object> model = new HashMap<String, Object>();
+ /*model.put("frame_int", "net_map_int");
+ // This view resolves to page frame_insert.jsp
+ return new ModelAndView("frame_insert", model);*/
+ return new ModelAndView("samplePage", "model", model);
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/package-info.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/package-info.java
new file mode 100644
index 00000000..8c04d60f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/controller/sample/package-info.java
@@ -0,0 +1,5 @@
+package org.openecomp.portalapp.controller.sample;
+
+/**
+ * Provides controllers for EPSDK application sample pages such as call flow etc.
+ */
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/model/Result.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/model/Result.java
index 5e09cb2c..ba07bd32 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/model/Result.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/model/Result.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java
index b308efbb..f6206187 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogJob.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -19,7 +19,6 @@
*/
package org.openecomp.portalapp.scheduler;
-import org.openecomp.portalapp.conf.ExternalAppConfig;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
@@ -31,8 +30,7 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
@DisallowConcurrentExecution
public class LogJob extends QuartzJobBean {
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ExternalAppConfig.class);
-
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LogJob.class);
@Override
protected void executeInternal(JobExecutionContext ctx)
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java
index dce9e26b..bffc3d00 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/scheduler/LogRegistry.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/IAdminAuthExtension.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/IAdminAuthExtension.java
new file mode 100644
index 00000000..c670c2ba
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/IAdminAuthExtension.java
@@ -0,0 +1,65 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+
+package org.openecomp.portalapp.service;
+
+import java.util.Set;
+
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.User;
+
+/**
+ * Defines methods that can be used to extend the features of the user/role
+ * provisioning class supplied in EPSDK-Common.
+ */
+public interface IAdminAuthExtension {
+
+ /**
+ * Invoked from OnBoardingApiServiceImpl#pushUser after user was saved. App
+ * developers can provide a class with their own logic following this
+ * action; for example, updating app's related tables
+ *
+ * @param user
+ * User object sent by Portal
+ */
+ public void saveUserExtension(User user);
+
+ /**
+ * Invoked from OnBoardingApiServiceImpl#editUser after user was updated.
+ * App developers can provide a class with their own logic following this
+ * action; for example, updating app's related tables
+ *
+ * @param user
+ * User object sent by Portal
+ */
+ public void editUserExtension(User user);
+
+ /**
+ * Invoked from OnBoardingApiServiceImpl#pushUserRole after user's roles
+ * were updated. App developers can provide a class with their own logic
+ * following this action; for example, updating app's related tables
+ *
+ * @param roles
+ * Roles object sent by Portal
+ * @param user
+ * User object sent by Portal
+ */
+ public void saveUserRoleExtension(Set<Role> roles, User user);
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/OnBoardingApiServiceImpl.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/OnBoardingApiServiceImpl.java
index 1d71afd6..cb822494 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/OnBoardingApiServiceImpl.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/service/OnBoardingApiServiceImpl.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.client;
+package org.openecomp.portalapp.service;
import java.util.ArrayList;
import java.util.Iterator;
@@ -28,13 +28,15 @@ import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
+import org.openecomp.portalsdk.core.auth.LoginStrategy;
import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.domain.UserApp;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.onboarding.client.AppContextManager;
import org.openecomp.portalsdk.core.onboarding.crossapi.IPortalRestAPIService;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalAPIException;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
import org.openecomp.portalsdk.core.restful.domain.EcompRole;
import org.openecomp.portalsdk.core.restful.domain.EcompUser;
import org.openecomp.portalsdk.core.service.RoleService;
@@ -54,12 +56,16 @@ import org.springframework.context.ApplicationContext;
* servlet from the ecompFW library, we cannot use Spring injections here. This
* 'injection' is done indirectly using AppContextManager class.
*
-
+ * @author Ikram Ikramullah
+ *
*/
-@SuppressWarnings("rawtypes")
public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
- RoleService roleService;
- UserProfileService userProfileService;
+
+ private RoleService roleService;
+ private UserProfileService userProfileService;
+ private IAdminAuthExtension adminAuthExtensionServiceImpl;
+
+ private LoginStrategy loginStrategy;
EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(OnBoardingApiServiceImpl.class);
@@ -71,6 +77,9 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
throw new RuntimeException("OnBoardingApiServiceImpl ctor failed to get appContext");
roleService = appContext.getBean(RoleService.class);
userProfileService = appContext.getBean(UserProfileService.class);
+ loginStrategy = appContext.getBean(LoginStrategy.class);
+ // initialize the base class definition for Admin Auth Extension
+ adminAuthExtensionServiceImpl = appContext.getBean(IAdminAuthExtension.class);
}
private void setCurrentAttributes(User user, EcompUser userJson) {
@@ -95,21 +104,31 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
public void pushUser(EcompUser userJson) throws PortalAPIException {
if (logger.isDebugEnabled())
- logger.debug(EELFLoggerDelegate.debugLogger, "pushUser was invoked: " + userJson);
+ logger.debug(EELFLoggerDelegate.debugLogger, "pushUser was invoked: {}", userJson);
User user = new User();
String response = "";
try {
// Set input attributes to the object obout to be saved
setCurrentAttributes(user, userJson);
user.setRoles(new TreeSet<Role>());
- user.setUserApps(new TreeSet());
- user.setPseudoRoles(new TreeSet());
+ user.setUserApps(new TreeSet<UserApp>());
+ user.setPseudoRoles(new TreeSet<Role>());
userProfileService.saveUser(user);
logger.debug(EELFLoggerDelegate.debugLogger, "push user success.");
+
+ // After successful creation, call admin auth extension
+ if (adminAuthExtensionServiceImpl != null) {
+ try {
+ adminAuthExtensionServiceImpl.saveUserExtension(user);
+ } catch (Exception ex) {
+ logger.error("pushUser: saveUserExtension failed", ex);
+ }
+ }
+
response = "push user success.";
response = JSONUtil.convertResponseToJSON(response);
} catch (Exception e) {
- response = "OnboardingApiService.pushUser failed";
+ response = "OnboardingApiService.pushUser failed";
logger.error(EELFLoggerDelegate.errorLogger, response, e);
throw new PortalAPIException(response, e);
} finally {
@@ -121,7 +140,8 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
public void editUser(String loginId, EcompUser userJson) throws PortalAPIException {
if (logger.isDebugEnabled())
- logger.debug(EELFLoggerDelegate.debugLogger, "OnboardingApi editUser was invoked with loginID " + loginId + ", JSON: " + userJson);
+ logger.debug(EELFLoggerDelegate.debugLogger, "OnboardingApi editUser was invoked with loginID {}, JSON {}",
+ loginId, userJson);
User editUser = new User();
String response = "";
try {
@@ -136,6 +156,16 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
domainUser = editUser;
userProfileService.saveUser(domainUser);
logger.debug(EELFLoggerDelegate.debugLogger, "edit user success.");
+
+ // After successful edit, call the admin auth extension
+ if (adminAuthExtensionServiceImpl != null) {
+ try {
+ adminAuthExtensionServiceImpl.editUserExtension(domainUser);
+ } catch (Exception ex) {
+ logger.error("editUser: editUserExtension failed", ex);
+ }
+ }
+
response = "edit user success.";
response = JSONUtil.convertResponseToJSON(response);
} catch (Exception e) {
@@ -153,12 +183,12 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
public EcompUser getUser(String loginId) throws PortalAPIException {
try {
if (logger.isDebugEnabled())
- logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: " + loginId);
+ logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: {}", loginId);
User user = userProfileService.getUserByLoginId(loginId);
if (user == null) {
logger.info(EELFLoggerDelegate.debugLogger, "User + " + loginId + " doesn't exist");
return null;
- // Unforunately, Portal is not ready to accept proper error
+ // Unfortunately, Portal is not ready to accept proper error
// response yet ..
// commenting throw clauses until portal is ready
// throw new PortalAPIException("User + " + loginId + " doesn't
@@ -169,7 +199,7 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
String response = "OnboardingApiService.getUser failed";
logger.error(EELFLoggerDelegate.errorLogger, response, e);
return null;
- // Unforunately, Portal is not ready to accept proper error response
+ // Unfortunately, Portal is not ready to accept proper error response
// yet .. commenting throw clauses until portal is ready
// throw new PortalAPIException(response, e);
}
@@ -210,8 +240,9 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
public void pushUserRole(String loginId, List<EcompRole> rolesJson) throws PortalAPIException {
String response = "";
try {
- logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: " + loginId);
- logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## rolesJson: " + rolesJson);
+ if (logger.isDebugEnabled())
+ logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: {}, roles Json {}", loginId,
+ rolesJson);
User user = userProfileService.getUserByLoginId(loginId);
/*
* List<EcompRole> ecompRoles = mapper.readValue(rolesJson,
@@ -226,6 +257,15 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
replaceExistingRoles(roles, user);
logger.debug(EELFLoggerDelegate.debugLogger, "push user role success.");
+
+ // After successful creation, call admin auth extension
+ if (adminAuthExtensionServiceImpl != null) {
+ try {
+ adminAuthExtensionServiceImpl.saveUserRoleExtension(roles, user);
+ } catch (Exception ex) {
+ logger.error("pushUserRole: saveUserRoleExtension failed", ex);
+ }
+ }
response = "push user role success.";
response = JSONUtil.convertResponseToJSON(response);
@@ -242,7 +282,7 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
@Override
public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException {
if (logger.isDebugEnabled())
- logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: " + loginId);
+ logger.debug(EELFLoggerDelegate.debugLogger, "## REST API ## loginId: {}", loginId);
List<EcompRole> ecompRoles = new ArrayList<EcompRole>();
try {
User user = userProfileService.getUserByLoginId(loginId);
@@ -265,9 +305,9 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
private void replaceExistingRoles(SortedSet<Role> roles, User user) {
// 1. remove existing roles
Set<UserApp> userApps = user.getUserApps();
- Iterator appsItr = userApps.iterator();
+ Iterator<UserApp> appsItr = userApps.iterator();
while (appsItr.hasNext()) {
- UserApp tempUserApp = (UserApp) appsItr.next();
+ UserApp tempUserApp = appsItr.next();
boolean roleFound = false;
for (Role role : roles) {
if (tempUserApp.getRole().getId().equals(role.getId())) {
@@ -313,4 +353,9 @@ public class OnBoardingApiServiceImpl implements IPortalRestAPIService {
public void updateSessionTimeOuts(String sessionMap) throws Exception {
PortalTimeoutHandler.updateSessionExtensions(sessionMap);
}
+
+ @Override
+ public String getUserId(HttpServletRequest request) throws PortalAPIException {
+ return loginStrategy.getUserId(request);
+ }
}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java
index 48c51195..00c1d869 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java
+++ b/ecomp-sdk/epsdk-app-common/src/main/java/org/openecomp/portalapp/util/CustomLoggingFilter.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/epsdk-app-common/src/main/webapp/app/fusion/external/d3/js/intro.js b/ecomp-sdk/epsdk-app-common/src/main/webapp/app/fusion/external/d3/js/intro.js
new file mode 100644
index 00000000..0c3a3282
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/main/webapp/app/fusion/external/d3/js/intro.js
@@ -0,0 +1 @@
+(function(){})
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/SanityTest.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/SanityTest.java
index d455b843..96d6b0fc 100644
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/SanityTest.java
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/SanityTest.java
@@ -2,7 +2,7 @@ package org.openecomp.portalapp;
import org.junit.Assert;
import org.junit.Test;
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
+import org.openecomp.portalapp.core.MockApplicationContextTestSuite;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java
index 099cf518..2751a66d 100644
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/CollaborationControllerTest.java
@@ -2,13 +2,15 @@ package org.openecomp.portalapp.controller;
import org.junit.Assert;
import org.junit.Test;
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
+import org.openecomp.portalapp.core.MockApplicationContextTestSuite;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+
public class CollaborationControllerTest extends MockApplicationContextTestSuite{
@Test
@@ -16,7 +18,7 @@ public class CollaborationControllerTest extends MockApplicationContextTestSuite
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/collaborate_list");
User user = new User();
user.setId(1l);
- user.setOrgUserId("abc");
+ //user.setOrgUserId("abc");
requestBuilder.sessionAttr(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME), user);
ResultActions ra =getMockMvc().perform(requestBuilder);
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java
index 4622f66e..0f06ea7f 100644
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/controller/NetMapTest.java
@@ -2,7 +2,7 @@ package org.openecomp.portalapp.controller;
import org.junit.Assert;
import org.junit.Test;
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
+import org.openecomp.portalapp.core.MockApplicationContextTestSuite;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
diff --git a/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/core/MockApplicationContextTestSuite.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/core/MockApplicationContextTestSuite.java
new file mode 100644
index 00000000..8a86cd57
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/core/MockApplicationContextTestSuite.java
@@ -0,0 +1,127 @@
+package org.openecomp.portalapp.core;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.openecomp.portalsdk.core.conf.AppConfig;
+import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
+import org.openecomp.portalsdk.core.util.CacheManager;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+
+
+
+/**
+ *
+ *
+ *
+ * In order to write a unit test,
+ * 1. inherit this class - See SanityTest.java
+ * 2. place the "war" folder on your test class's classpath
+ * 3. run the test with the following VM argument; This is important because when starting the application from Container, the System Properties file (SystemProperties.java) can have the direct path
+ * but, when running from the Mock Junit container, the path should be prefixed with "classpath" to enable the mock container to search for the file in the classpath
+ * -Dcontainer.classpath="classpath:"
+ *
+ */
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {MockAppConfig.class})
+@ActiveProfiles(value="test")
+public class MockApplicationContextTestSuite {
+
+ @Autowired
+ public WebApplicationContext wac;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void setup() {
+ if(mockMvc == null) {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+
+ }
+ }
+
+ public Object getBean(String name) {
+ return this.wac.getBean(name);
+ }
+
+
+ public MockMvc getMockMvc() {
+ return mockMvc;
+ }
+
+ public void setMockMvc(MockMvc mockMvc) {
+ this.mockMvc = mockMvc;
+ }
+
+ public WebApplicationContext getWebApplicationContext() {
+ return wac;
+ }
+
+
+
+
+}
+
+
+ @Configuration
+ @ComponentScan(basePackages = "org.openecomp",
+ excludeFilters = {
+ }
+ )
+ @Profile("test")
+ class MockAppConfig extends AppConfig {
+
+ @Bean
+ public SystemProperties systemProperties(){
+ return new MockSystemProperties();
+ }
+
+ @Bean
+ public AbstractCacheManager cacheManager() {
+ return new CacheManager() {
+
+ public void configure() throws IOException {
+
+ }
+ };
+ }
+
+ protected String[] tileDefinitions() {
+ return new String[] {"classpath:/WEB-INF/fusion/defs/definitions.xml", "classpath:/WEB-INF/defs/definitions.xml"};
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ //registry.addInterceptor(new SessionTimeoutInterceptor()).excludePathPatterns(getExcludeUrlPathsForSessionTimeout());
+ //registry.addInterceptor(resourceInterceptor());
+ }
+
+ public static class MockSystemProperties extends SystemProperties {
+
+ public MockSystemProperties() {
+ }
+
+ }
+
+ }
+
+
+
+
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java
index f7f30fe5..ea78a779 100644
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/service/ProfileServiceTest.java
@@ -4,7 +4,7 @@ import java.util.List;
import org.junit.Assert;
import org.junit.Test;
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
+import org.openecomp.portalapp.core.MockApplicationContextTestSuite;
import org.openecomp.portalsdk.core.domain.Profile;
import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.service.ProfileService;
@@ -12,6 +12,8 @@ import org.openecomp.portalsdk.core.service.UserProfileService;
import org.springframework.beans.factory.annotation.Autowired;
+
+
public class ProfileServiceTest extends MockApplicationContextTestSuite {
@Autowired
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceTest.java b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/workflow/services/WorkflowScheduleServiceTest.java
index 584bad78..c390a84c 100644
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceTest.java
+++ b/ecomp-sdk/epsdk-app-common/src/test/java/org/openecomp/portalapp/workflow/services/WorkflowScheduleServiceTest.java
@@ -1,13 +1,16 @@
-package org.openecomp.portalsdk.workflow.services;
+package org.openecomp.portalapp.workflow.services;
import java.util.Calendar;
import org.junit.Assert;
import org.junit.Test;
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
+import org.openecomp.portalapp.core.MockApplicationContextTestSuite;
import org.openecomp.portalsdk.workflow.domain.WorkflowSchedule;
+import org.openecomp.portalsdk.workflow.services.WorkflowScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
+
+
public class WorkflowScheduleServiceTest extends MockApplicationContextTestSuite {
@Autowired
diff --git a/ecomp-sdk/epsdk-app-os/.gitignore b/ecomp-sdk/epsdk-app-os/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-app-os/README.md b/ecomp-sdk/epsdk-app-os/README.md
new file mode 100644
index 00000000..90b6d07d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/README.md
@@ -0,0 +1,66 @@
+# ECOMP SDK Web Application for Open Source
+
+## Overview
+
+This is a Maven project with the ECOMP SDK web application for public release,
+containing files specific to requirements of the open-source version. This
+project uses the Maven war plugin to copy in ("overlay") the contents of the
+ECOMP SDK web application overlay files distribution at package time.
+
+Use Apache Maven to build, package and deploy this webapp to a web container
+like Apache Tomcat. Eclipse users must install the M2E-WTP connector, see
+https://www.eclipse.org/m2e-wtp/
+
+## Release Notes
+
+All of the release notes in the epsdk-app-common and epsdk-app-overlay areas apply here!
+
+Build 1.2.8, ?? ??? 2017
+* put new entries here *
+
+Build 1.2.7, 10 Apr 2017
+- Drop shared context property
+
+Build 1.2.6, 23 Mar 2017
+- DE270905 Removed total page/current page text boxes from bottom of Profile Search page
+- DE272154 SDK-App: self profile page, changes on drop downs not saved
+- DE273128 Revise left menu to have unique IDs
+- DE271378 fixed Camunda Page link in fn_menu; additional links were updated: Notebook
+- US847688 Abstraction of support page content for AT&T vs Open Source in SQL Scripts
+- Add sample defs/definitions.xml file for partner applications to configure jsp pages
+- Downgrade angularJS from 1.5.0 to 1.4.8
+
+Build 1.2.5, 16 Mar 2017
+- DE272709 Update icon names from DS1 to DS2 in database load script
+- Upgrade to EPSDK libraries version 1.2.5
+
+Build 1.2.4, 10 Mar 2017
+- DE272042 Add missing includes so left menu appears on collaborate and notebook pages
+- DE272193 Fix class/icon name to restore role icon on Self Profile page
+- Restore spinners by changing class name from icon-spinner to icon-primary-spinner
+- DE272202 updated ionicon.css for open source version of report search page
+- Removed unused js files from samplePage.html in epsdk-app-os
+- Upgrade to EPSDK libraries version 1.2.4
+
+Build 1.2.3, 8 Mar 2017
+- DE271038 Remove references to famous telecommunications company from system.properties
+- Upgrade to EPSDK libraries version 1.2.3
+
+Build 1.2.2, 6 Mar 2017
+- DE270658 EPSDK-app-os header is covering part of left menu.
+- DE271510 Pages not loading in IE and FF properly. Drop page-resource-ds2.js; load scripts in HTML directly
+- Remove references to famous telecommunications company hosts from fusion.properties, portal.properties
+- Upgrade to EPSDK libraries version 1.2.2
+
+Build 1.2.1, 2 Mar 2017
+- DE269231 Separated footer files on OS module displaying black footer with no content
+- US847688 Split database scripts; include full set in distributions
+- US847706 Refactored AdminAuthExtension to implement interface expected in OnboardingApiServiceImpl
+- Added class conf/HibernateMappingLocations - moved out of common to apps
+- Added file logback.xml to src/main/resources with appropriate logger names
+- Extend HibernateMappingLocations with method that returns list of package names to scan
+- Remove references to famous telecommunications company hosts from system.properties file
+- Upgrade to EPSDK libraries version 1.2.1
+
+Build 1.2.0, 9 Feb 2017
+- Initial release
diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDDLMySql_1707_OS.sql b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDDLMySql_1707_OS.sql
new file mode 100644
index 00000000..1b1ce059
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDDLMySql_1707_OS.sql
@@ -0,0 +1,12 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This script adds tables for the 1707 OPEN-SOURCE version of the ECOMP SDK application database.
+-- The DDL 1707 COMMON script must be executed first!
+-- ---------------------------------------------------------------------------------------------------------------
+
+SET FOREIGN_KEY_CHECKS=1;
+
+USE ecomp_sdk;
+
+-- No additional tables required at this time
+
+commit;
diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_1707_OS.sql b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_1707_OS.sql
new file mode 100644
index 00000000..839baa07
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkDMLMySql_1707_OS.sql
@@ -0,0 +1,40 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This script populates tables in the 1707 OPEN-SOURCE version of the ECOMP SDK application database.
+-- The DML 1707 COMMON script must be executed first!
+-- ---------------------------------------------------------------------------------------------------------------
+
+SET FOREIGN_KEY_CHECKS=1;
+
+USE ecomp_sdk;
+
+-- fn_menu
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (1, 'Root', NULL, 10, NULL, 'menu_home', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', NULL); -- we need even though it's inactive
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (5000, 'Sample Pages', 1, 30, 'sample.htm', 'menu_sample', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-documents-book');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (2, 'Home', 1, 10, 'welcome.htm', 'menu_home', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-building-home');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (8, 'Reports', 1, 40, 'report.htm', 'menu_reports', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-misc-piechart');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (9, 'Profile', 1, 90, 'userProfile', 'menu_profile', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-people-oneperson');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (10, 'Admin', 1, 110, 'role_list.htm', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-content-star');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (84, 'All Reports', 8, 50, 'report', 'menu_reports', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/reports.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) values (87, 'Create Reports', 8, 120, 'report_wizard.htm?r_action=report.create', 'menu_reports', 'Y', NULL, 'r_action=report.create', NULL, NULL, 'APP', 'N', NULL);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) values (88, 'Sample Dashboard', 8, 130, 'report_dashboard', 'menu_reports', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (89, 'Import', 8, 140, 'report_wizard.htm?action=report.import', 'menu_reports', 'N', null, null, null, null, 'APP', 'N', null);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (94, 'Self', 9, 40,'userProfile#/self_profile', 'menu_profile', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/profile.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (101, 'Roles', 10, 20, 'admin#/admin', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/users.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (102, 'Role Functions', 10, 30, 'admin#/role_function_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (105, 'Cache Admin', 10, 40, 'admin#/jcs_admin', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/cache.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (108, 'Usage', 10, 80, 'admin#/usage_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/users.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (121, 'Collaboration', 5000, 100, 'samplePage#/collaborate_list', 'menu_sample', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/bubble.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (930, 'Search', 9, 15, 'userProfile', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/search_profile.png');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (150022, 'Menus', 10, 60, 'admin#/admin_menu_edit', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (150038,'Notebook',5000,135,'samplePage#/notebook','menu_sample','Y',NULL,NULL,NULL,NULL,'APP','N',NULL);
+
+-- fn_user
+Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (1,null,null,'Demo',null,'User',null,null,null,'demo@email.com',null,null,null,'demo',null,'demo','demo',str_to_date('24-OCT-16','%d-%M-%Y'),'Y',null,str_to_date('17-OCT-16','%d-%M-%Y'),1,str_to_date('24-OCT-16','%d-%M-%Y'),'N',null,null,null,'NJ',null,'US',null,null,null,null,null,10,null,null,null,null,null,null);
+
+-- fn_app
+Insert into fn_app (APP_ID,APP_NAME,APP_IMAGE_URL,APP_DESCRIPTION,APP_NOTES,APP_URL,APP_ALTERNATE_URL,APP_REST_ENDPOINT,ML_APP_NAME,ML_APP_ADMIN_ID,MOTS_ID,APP_PASSWORD,OPEN,ENABLED,THUMBNAIL,APP_USERNAME,UEB_KEY,UEB_SECRET,UEB_TOPIC_NAME) VALUES (1,'Default',null,'Some Default Description','Some Default Note',null,null,null,'ECPP','?','1','app_password_here','N','N',null,'Default',null,null,'ECOMP-PORTAL-INBOX');
+
+-- fn_user_role
+Insert into fn_user_role (USER_ID,ROLE_ID,PRIORITY,APP_ID) values (1,1,null,1);
+
+commit; \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql
new file mode 100644
index 00000000..cb57443d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql
@@ -0,0 +1,57 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This rollback script is for the OpenSource ECOMP SDK App database from version 1707 to 1610.2.
+-- change size on 3 name columns from fn_user for the Opensource version
+-- changed DS1 icon names to DS2 icon names
+-- removed unnecessary fn_menu entries, updated fn_menu actions
+-- ---------------------------------------------------------------------------------------------------------------
+
+USE ecomp_sdk;
+
+update fn_menu
+set image_src = 'ion-home'
+where menu_id = 2 and label = 'Home';
+
+update fn_menu
+set image_src = 'ion-android-apps'
+where menu_id = 5000 and label = 'Sample Pages';
+
+update fn_menu
+set image_src = 'ion-ios-paper'
+where menu_id = 8 and label = 'Reports';
+
+update fn_menu
+set image_src = 'ion-person'
+where menu_id = 9 and label = 'Profile';
+
+update fn_menu
+set image_src = 'ion-gear-a'
+where menu_id = 10 and label = 'Admin';
+
+update fn_menu
+set action = 'collaborate_list.htm'
+where menu_id = 121 and label = 'Collaboration';
+
+update fn_menu
+set action = 'notebook.htm'
+where menu_id = 150038 and label = 'Notebook';
+
+update fn_menu
+set action = 'admin'
+where menu_id = 101 and label = 'Roles';
+
+delete from fn_menu
+where menu_id = 150022 and label = 'Menus';
+
+delete from fn_menu
+where menu_id = 89 and label = 'Import';
+
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (13, 'Application Logout', 1, 130, 'app_logout.htm', 'menu_logout', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'icon-sign-out');
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (92, 'Import User', 9, 30, null, 'menu_profile_import', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (103, 'Broadcast Messages', 10, 50, 'admin#/broadcast_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/bubble.png');
+
+alter table fn_user
+ CHANGE COLUMN FIRST_NAME FIRST_NAME VARCHAR(25) NULL DEFAULT NULL ,
+ CHANGE COLUMN MIDDLE_NAME MIDDLE_NAME VARCHAR(25) NULL DEFAULT NULL ,
+ CHANGE COLUMN LAST_NAME LAST_NAME VARCHAR(25) NULL DEFAULT NULL;
+
+commit;
diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql
new file mode 100644
index 00000000..81522f82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/db-scripts/EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql
@@ -0,0 +1,59 @@
+-- ---------------------------------------------------------------------------------------------------------------
+-- This script upgrades the OpenSource ECOMP SDK App database from version 1610.2 to 1707.
+-- change size on 3 name columns from fn_user for the Opensource version
+-- changed DS1 icon names to DS2 icon names
+-- removed unnecessary fn_menu entries, updated fn_menu actions
+-- ---------------------------------------------------------------------------------------------------------------
+
+USE ecomp_sdk;
+
+update fn_menu
+set image_src = 'icon-building-home'
+where menu_id = 2 and label = 'Home';
+
+update fn_menu
+set image_src = 'icon-documents-book'
+where menu_id = 5000 and label = 'Sample Pages';
+
+update fn_menu
+set image_src = 'icon-misc-piechart'
+where menu_id = 8 and label = 'Reports';
+
+update fn_menu
+set image_src = 'icon-people-oneperson'
+where menu_id = 9 and label = 'Profile';
+
+update fn_menu
+set image_src = 'icon-content-star'
+where menu_id = 10 and label = 'Admin';
+
+update fn_menu
+set action = 'samplePage#/collaborate_list'
+where menu_id = 121 and label = 'Collaboration';
+
+update fn_menu
+set action = 'samplePage#/notebook'
+where menu_id = 150038 and label = 'Notebook';
+
+update fn_menu
+set action = 'admin#/admin'
+where menu_id = 101 and label = 'Roles';
+
+delete from fn_menu
+where menu_id = 13 and label = 'Application Logout';
+
+delete from fn_menu
+where menu_id = 92 and label = 'Import User';
+
+delete from fn_menu
+where menu_id = 103 and label = 'Broadcast Messages';
+
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (89, 'Import', 8, 140, 'report_wizard.htm?action=report.import', 'menu_reports', 'Y', null, null, null, null, 'APP', 'N', null);
+INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (150022, 'Menus', 10, 60, 'admin#/admin_menu_edit', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
+
+alter table fn_user
+ CHANGE COLUMN FIRST_NAME FIRST_NAME VARCHAR(50) NULL DEFAULT NULL ,
+ CHANGE COLUMN MIDDLE_NAME MIDDLE_NAME VARCHAR(50) NULL DEFAULT NULL ,
+ CHANGE COLUMN LAST_NAME LAST_NAME VARCHAR(50) NULL DEFAULT NULL;
+
+commit;
diff --git a/ecomp-sdk/epsdk-app-os/db-scripts/readme.txt b/ecomp-sdk/epsdk-app-os/db-scripts/readme.txt
new file mode 100644
index 00000000..5f1be1bc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/db-scripts/readme.txt
@@ -0,0 +1,36 @@
+This Readme file contains a description of open source scripts located in
+
+ epsdk-app-os / db-scripts /
+
+***************************************************************************************************************************************
+
+Directions:
+
+DDL
+For an Opensource instance run only script EcompSdkDDLMySql_1707_Common.sql;
+
+EcompSdkDDLMySql_1707_Common.sql - common DDL entries
+EcompSdkDDLMySql_1707_OS.sql is only a placeholder at this time.
+
+DML
+
+For an Opensource instance run script EcompSdkDMLMySql_1707_Common.sql and script EcompSdkDMLMySql_1707_OS.sql;
+
+EcompSdkDMLMySql_1707_Common.sql - common DML entries
+EcompSdkDMLMySql_1707_OS.sql - DML entries for Opensource needs
+
+To Upgrade the OpenSource 1610.2 version to the 1707 version, run script EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql
+and to remove those changes run EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql.
+
+EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql
+EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql
+
+
+***************************************************************************************************************************************
+epsdk-app-os / db-scripts /
+***************************************************************************************************************************************
+EcompSdkDDLMySql_1707_OS.sql It is empty for now; just a logical placeholder
+EcompSdkDMLMySql_1707_OS.sql This script populates tables in the 1707 OPEN-SOURCE version of the ECOMP SDK application database.
+ After The DML 1707 COMMON script is run.
+EcompSdkMySql_Upgrade_1610.2_to_1707_OS.sql This script upgrades the ECOMP SDK App database from version 1610.2 to 1707.
+EcompSdkMySql_Rollback_1707_to_1610.2_OS.sql This script rolls-back the upgrade for the ECOMP SDK App database
diff --git a/ecomp-sdk/epsdk-app-os/distribution.xml b/ecomp-sdk/epsdk-app-os/distribution.xml
new file mode 100644
index 00000000..23a170ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/distribution.xml
@@ -0,0 +1,33 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>distribution</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>${basedir}</directory>
+ <outputDirectory />
+ <excludes>
+ <exclude>.classpath</exclude>
+ <exclude>.project</exclude>
+ <exclude>.settings/</exclude>
+ <exclude>bin/</exclude>
+ <exclude>target/</exclude>
+ <exclude>distribution.xml</exclude>
+ <exclude>**/WEB-INF/conf/system.properties.*</exclude>
+ </excludes>
+ </fileSet>
+ <!-- Include common database scripts for partner convenience -->
+ <fileSet>
+ <directory>../epsdk-app-common</directory>
+ <outputDirectory />
+ <includes>
+ <include>db-scripts/*</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/ecomp-sdk/epsdk-app-os/pom.xml b/ecomp-sdk/epsdk-app-os/pom.xml
new file mode 100644
index 00000000..efcbbe0a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/pom.xml
@@ -0,0 +1,305 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <!-- This is the Maven project object model (POM) file for the open-source SDK web app.
+ This is NOT the Portal - but it is developed and supported by the Portal team. -->
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-app-os</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>ECOMP SDK Webapp for OpenSource</name>
+ <description>ECOMP SDK Web Application for public release</description>
+ <scm>
+ <connection>scm:git:https://todourl/</connection>
+ </scm>
+
+ <properties>
+ <encoding>UTF-8</encoding>
+ <epsdk.version>1.1.0-SNAPSHOT</epsdk.version>
+ <springframework.version>4.2.0.RELEASE</springframework.version>
+ <hibernate.version>4.3.11.Final</hibernate.version>
+ <!-- Skip assembling the zip; assemble via mvn -Dskipassembly=false .. -->
+ <skipassembly>true</skipassembly>
+ <!-- Tests usually require some setup that maven cannot do, so skip. -->
+ <skiptests>true</skiptests>
+ <nexusproxy>https://nexus.onap.org</nexusproxy>
+ <snapshotNexusPath>content/repositories/snapshots/</snapshotNexusPath>
+ <releaseNexusPath>content/repositories/releases/</releaseNexusPath>
+ <stagingNexusPath>content/repositories/staging/</stagingNexusPath>
+ </properties>
+
+ <repositories>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>ecomp-releases</id>
+ <name>OpenECOMP - Release Repository</name>
+ <url>${nexusproxy}/${releaseNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>ecomp-snapshots</id>
+ <name>OpenECOMP - Snapshot Repository</name>
+ <url>${nexusproxy}/${snapshotNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Staging repository has ECOMP staging artifacts -->
+ <id>ecomp-staging</id>
+ <name>OpenECOMP - Staging Repository</name>
+ <url>${nexusproxy}/${stagingNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>ecomp-public</id>
+ <name>ecomp onap public Repository</name>
+ <url>https://nexus.onap.org/content/groups/public</url>
+ </repository>
+ </repositories>
+
+ <profiles>
+ <!-- disable doclint, a new feature in Java 8, when generating javadoc -->
+ <profile>
+ <id>doclint-java8-disable</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.4</version>
+ <configuration>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <build>
+
+ <plugins>
+ <!-- Compile to Java 1.8 class output format -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <skipTests>${skiptests}</skipTests>
+ <includes>
+ <include>**/Test*.java</include>
+ <include>**/*Test.java</include>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <additionalClasspathElements>
+ <additionalClasspathElement>${basedir}/war</additionalClasspathElement>
+ </additionalClasspathElements>
+ <systemPropertyVariables>
+ <container.classpath>classpath:</container.classpath>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+ <!-- add version number to manifest -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ </manifest>
+ <manifestEntries>
+ <Build-Number>${project.version}</Build-Number>
+ <Build-Time>${maven.build.timestamp}</Build-Time>
+ </manifestEntries>
+ </archive>
+ <overlays>
+ <overlay>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-app-overlay</artifactId>
+ </overlay>
+ </overlays>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>3.0.0</version>
+ <configuration>
+ <skipAssembly>${skipassembly}</skipAssembly>
+ <descriptors>
+ <descriptor>${basedir}/distribution.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- SDK overlay war -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-app-overlay</artifactId>
+ <version>${epsdk.version}</version>
+ <type>war</type>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-app-common</artifactId>
+ <version>${epsdk.version}</version>
+ <type>jar</type>
+ </dependency>
+ <!-- SDK components -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-core</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-analytics</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-workflow</artifactId>
+ <version>${epsdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <!-- Mapper -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ <version>0.9.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>io.searchbox</groupId>
+ <artifactId>jest</artifactId>
+ <version>2.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ <!-- Elastic Search -->
+ <dependency>
+ <groupId>org.elasticsearch</groupId>
+ <artifactId>elasticsearch</artifactId>
+ <version>2.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160212</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>2.2.1</version>
+ <exclusions>
+ <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
+ <exclusion>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- bridge to implement commons-logging using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${springframework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java
index ff9f0f1a..9745f968 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppConfig.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -22,10 +22,9 @@ package org.openecomp.portalapp.conf;
import java.util.ArrayList;
import java.util.List;
+import org.openecomp.portalapp.login.LoginStrategyImpl;
import org.openecomp.portalapp.scheduler.RegistryAdapter;
-import org.openecomp.portalapp.uebhandler.InitUebHandler;
-import org.openecomp.portalapp.uebhandler.MainUebHandler;
-import org.openecomp.portalapp.uebhandler.WidgetNotificationHandler;
+import org.openecomp.portalsdk.core.auth.LoginStrategy;
import org.openecomp.portalsdk.core.conf.AppConfig;
import org.openecomp.portalsdk.core.conf.Configurable;
import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
@@ -48,9 +47,8 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
/**
- * Configures Spring features in the ECOMP Portal SDK sample application.
- * Subclasses the ECOMP Portal SDK core AppConfig class to reuse interceptors,
- * view resolvers and other features defined there.
+ * ECOMP Portal SDK sample application. ECOMP Portal SDK core AppConfig class to
+ * reuse interceptors, view resolvers and other features defined there.
*/
@Configuration
@EnableWebMvc
@@ -60,7 +58,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
@EnableAsync
@EnableScheduling
public class ExternalAppConfig extends AppConfig implements Configurable {
-
+
private RegistryAdapter schedulerRegistryAdapter;
@Configuration
@@ -88,6 +86,9 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
* @see org.openecomp.portalsdk.core.conf.AppConfig#dataAccessService()
*/
public DataAccessService dataAccessService() {
+ // Echo the JDBC URL to assist developers when starting the app.
+ System.out.println("ExternalAppConfig: " + SystemProperties.DB_CONNECTIONURL + " is "
+ + SystemProperties.getProperty(SystemProperties.DB_CONNECTIONURL));
return super.dataAccessService();
}
@@ -111,7 +112,7 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.setExcludeUrlPathsForSessionTimeout("/login_external", "*/login_external.htm", "login", "/login.htm",
- "/api*","/single_signon.htm","/single_signon");
+ "/api*", "/single_signon.htm", "/single_signon");
super.addInterceptors(registry);
}
@@ -124,48 +125,15 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
public AbstractCacheManager cacheManager() {
return new CacheManager();
}
-
- /**
- * Creates and returns a new instance of a {@link MainUebHandler}.
- *
- * @return New instance of {@link MainUebHandler}.
- */
- @Bean
- public MainUebHandler mainUebHandler() {
-
- return new MainUebHandler();
- }
-
- /**
- * Creates and returns a new instance of a {@link InitUebHandler}.
- *
- * @return New instance of {@link InitUebHandler}.
- */
- @Bean
- public InitUebHandler initUebHandler() {
-
- return new InitUebHandler();
- }
/**
- * Creates and returns a new instance of a {@link WidgetNotificationHandler}
- * .
- *
- * @return New instance of {@link WidgetNotificationHandler}.
- */
- @Bean
- public WidgetNotificationHandler widgetNotificationHandler() {
- return new WidgetNotificationHandler();
- }
-
- /**
* Creates and returns a new instance of a {@link SchedulerFactoryBean} and
* populates it with triggers.
*
* @return New instance of {@link SchedulerFactoryBean}
- * @throws Exception
+ * @throws Exception
*/
- // @Bean // ANNOTATION COMMENTED OUT
+ // @Bean // ANNOTATION COMMENTED OUT
// APPLICATIONS REQUIRING QUARTZ SHOULD RESTORE ANNOTATION
public SchedulerFactoryBean schedulerFactoryBean() throws Exception {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
@@ -175,7 +143,6 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
return scheduler;
}
-
/**
* Sets the scheduler registry adapter.
*
@@ -185,4 +152,10 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
public void setSchedulerRegistryAdapter(final RegistryAdapter schedulerRegistryAdapter) {
this.schedulerRegistryAdapter = schedulerRegistryAdapter;
}
+
+ @Bean
+ public LoginStrategy loginStrategy() {
+
+ return new LoginStrategyImpl();
+ }
}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java
new file mode 100644
index 00000000..6d7c72d1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java
@@ -0,0 +1,47 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.conf;
+
+import org.openecomp.portalsdk.core.conf.AppInitializer;
+
+public class ExternalAppInitializer extends AppInitializer {
+
+ @Override
+ protected Class<?>[] getRootConfigClasses() {
+ return super.getRootConfigClasses();
+ }
+
+ @Override
+ protected Class<?>[] getServletConfigClasses() {
+ Class<?> appConfigClass = ExternalAppConfig.class;
+ // Show something on stdout to indicate the app is starting.
+ System.out.println("ExternalAppInitializer: servlet configuration class is " + appConfigClass.getName());
+ return new Class[] { appConfigClass };
+ }
+
+ /*
+ * URL request will direct to the Spring dispatcher for processing
+ */
+ @Override
+ protected String[] getServletMappings() {
+ return super.getServletMappings();
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java
new file mode 100644
index 00000000..cf6ee2f0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java
@@ -0,0 +1,57 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.conf;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import org.openecomp.portalsdk.core.conf.HibernateMappingLocatable;
+
+@Component
+@Profile("src")
+public class HibernateMappingLocations implements HibernateMappingLocatable {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.portalsdk.core.conf.HibernateMappingLocatable#
+ * getMappingLocations()
+ */
+ @Override
+ public Resource[] getMappingLocations() {
+ return new Resource[] { new ClassPathResource("../fusion/orm/Fusion.hbm.xml"),
+ new ClassPathResource("../fusion/orm/Workflow.hbm.xml"),
+ new ClassPathResource("../fusion/orm/RNoteBookIntegration.hbm.xml") };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openecomp.portalsdk.core.conf.HibernateMappingLocatable#
+ * getPackagesToScan()
+ */
+ @Override
+ public String[] getPackagesToScan() {
+ return new String[] { "org.openecomp" };
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/FusionLicenseManagerImpl.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/FusionLicenseManagerImpl.java
new file mode 100644
index 00000000..4993a005
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/FusionLicenseManagerImpl.java
@@ -0,0 +1,69 @@
+package org.openecomp.portalapp.lm;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.openecomp.portalsdk.core.lm.FusionLicenseManager;
+import org.springframework.stereotype.Component;
+
+/*
+ * Please note that this class is not being used; its a dummy stub to have a qualifying bean for the interface.
+ */
+
+@Component
+public class FusionLicenseManagerImpl implements FusionLicenseManager {
+
+ @Override
+ public void initKeyStoreParam() {
+
+ }
+
+ @Override
+ public void initCipherParam() {
+
+ }
+
+ @Override
+ public void initLicenseParam() {
+
+ }
+
+ @Override
+ public void doInitWork() {
+
+ }
+
+ @Override
+ public int installLicense() {
+ return 0;
+ }
+
+ @Override
+ public synchronized int verifyLicense(ServletContext context) {
+ return 0;
+ }
+
+ @Override
+ public void generateLicense(Map<String, String> clientInfoMap, List<String> ipAddressList) throws Exception {
+
+ }
+
+ @Override
+ public String nvl(String s) {
+ return null;
+ }
+
+ @Override
+ public Date getExpiredDate() {
+ return null;
+ }
+
+ @Override
+ public void setExpiredDate(Date expiredDate) {
+
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/LicenseableClassImpl.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/LicenseableClassImpl.java
new file mode 100644
index 00000000..91fe7870
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/lm/LicenseableClassImpl.java
@@ -0,0 +1,62 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.lm;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import org.openecomp.portalsdk.core.lm.LicenseableClass;
+
+/*
+ * Please note that this class is not being used; its a dummy stub to have a qualifying bean for the interface.
+ */
+
+public class LicenseableClassImpl implements LicenseableClass {
+
+ public String getApplicationName() {
+ return "";
+ }
+
+ public InputStream getPublicKeystoreAsInputStream() throws FileNotFoundException {
+ return null;
+ }
+
+ public String getAlias() {
+ return "";
+ }
+
+ public String getKeyPasswd() {
+ return "";
+ }
+
+ public String getPublicKeystorePassword() {
+ return "";
+ }
+
+ public String getCipherParamPassword() {
+ return "";
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Class getClassToLicense() {
+ return this.getClass();
+ }
+}
+
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/login/LoginStrategyImpl.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/login/LoginStrategyImpl.java
new file mode 100644
index 00000000..9f742ce9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/login/LoginStrategyImpl.java
@@ -0,0 +1,70 @@
+package org.openecomp.portalapp.login;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.auth.LoginStrategy;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.springframework.web.servlet.ModelAndView;
+
+public class LoginStrategyImpl extends LoginStrategy {
+
+ @Override
+ public ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ //'login' for opensource is same as 'external' login.
+ return doExternalLogin(request, response);
+ }
+
+ @Override
+ public String getUserId(HttpServletRequest request) throws PortalAPIException {
+ // Check ECOMP Portal cookie
+ if (!isLoginCookieExist(request))
+ return null;
+
+ String userid = null;
+ try {
+ userid = getUserIdFromCookie(request);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return userid;
+ }
+
+ private static String getUserIdFromCookie(HttpServletRequest request) throws Exception {
+ String userId = "";
+ Cookie[] cookies = request.getCookies();
+ Cookie userIdcookie = null;
+ if (cookies != null)
+ for (Cookie cookie : cookies)
+ if (cookie.getName().equals(USER_ID))
+ userIdcookie = cookie;
+ if(userIdcookie!=null){
+ userId = CipherUtil.decrypt(userIdcookie.getValue(),
+ PortalApiProperties.getProperty(PortalApiConstants.Decryption_Key));
+ }
+ return userId;
+
+ }
+
+ private static boolean isLoginCookieExist(HttpServletRequest request) {
+ Cookie ep = getCookie(request, EP_SERVICE);
+ return (ep != null);
+ }
+
+ private static Cookie getCookie(HttpServletRequest request, String cookieName) {
+ Cookie[] cookies = request.getCookies();
+ if (cookies != null)
+ for (Cookie cookie : cookies)
+ if (cookie.getName().equals(cookieName))
+ return cookie;
+
+ return null;
+ }
+
+
+}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/Register.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/Register.java
index 3a29520e..e5d30e5b 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/Register.java
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/Register.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -31,21 +31,17 @@ import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
@Component
-@DependsOn({"logRegistry", "systemProperties"})
+@DependsOn({ "logRegistry", "systemProperties" })
public class Register implements Registerable {
EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(Register.class);
-
private List<Trigger> scheduleTriggers = new ArrayList<Trigger>();
Trigger trigger[] = new Trigger[1];
-
@Autowired
private LogRegistry logRegistry;
-
-
@Override
public Trigger[] getTriggers() {
return getScheduleTriggers().toArray(trigger);
@@ -53,19 +49,17 @@ public class Register implements Registerable {
@Override
public void registerTriggers() {
- // if the property value is not available; the cron will not be added and can be ignored. its safe to ignore the exceptions
+ // if the property value is not available; the cron will not be added
+ // and can be ignored. its safe to ignore the exceptions
try {
- if(SystemProperties.getProperty(SystemProperties.LOG_CRON) != null)
+ if (SystemProperties.getProperty(SystemProperties.LOG_CRON) != null)
getScheduleTriggers().add(logRegistry.getTrigger());
-
- } catch(IllegalStateException ies) {
+ } catch (IllegalStateException ies) {
logger.info(EELFLoggerDelegate.debugLogger, ("Log Cron not available"));
}
-
-
+
}
-
-
+
public List<Trigger> getScheduleTriggers() {
return scheduleTriggers;
}
@@ -73,10 +67,5 @@ public class Register implements Registerable {
public void setScheduleTriggers(List<Trigger> scheduleTriggers) {
this.scheduleTriggers = scheduleTriggers;
}
-
-
-
-
-
}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java
index 1bc43fee..b3f6cbeb 100644
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/scheduler/RegistryAdapter.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -30,79 +30,63 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
-/**
- * TODO REFACTOR
- * moved from org.openecomp.portalsdk.core.scheduler
- * to org.openecomp.portalapp.scheduler
- *
- */
@Component
public class RegistryAdapter {
-
+
@Autowired
private Registerable registry;
-
+
@Autowired
private WorkflowScheduleService workflowScheduleService;
-
+
private SchedulerFactoryBean schedulerBean;
-
+
Trigger trigger[] = new Trigger[1];
-
+
public Trigger[] getTriggers() {
-
+
registry.registerTriggers();
-
+
List<Trigger> allTriggers = new ArrayList<Trigger>();
-
+
List<Trigger> coreTriggers = addCoreTriggers();
final Trigger[] extTriggerArray = registry.getTriggers();
-
+
allTriggers.addAll(Arrays.asList(extTriggerArray));
allTriggers.addAll(coreTriggers);
-
+
return allTriggers.toArray(trigger);
-
-
}
-
-
+
public List<Trigger> addCoreTriggers() {
- //On startup of the application after crash recovery, invoke workflow schedule trigger
+ // On startup of the application after crash recovery, invoke workflow
+ // schedule trigger
List<Trigger> triggers = getWorkflowScheduleService().triggerWorkflowScheduling();
return triggers;
}
-
public void setSchedulerBean(SchedulerFactoryBean _schedulerBean) {
schedulerBean = _schedulerBean;
-
}
public SchedulerFactoryBean getSchedulerBean() {
return schedulerBean;
-
}
-
public Registerable getRegistry() {
return registry;
}
-
public void setRegistry(Registerable registry) {
this.registry = registry;
}
-
public WorkflowScheduleService getWorkflowScheduleService() {
return workflowScheduleService;
}
-
- public void setWorkflowScheduleService(
- WorkflowScheduleService workflowScheduleService) {
+ public void setWorkflowScheduleService(WorkflowScheduleService workflowScheduleService) {
this.workflowScheduleService = workflowScheduleService;
}
-
+
}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java
new file mode 100644
index 00000000..2b9b60e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java
@@ -0,0 +1,64 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalapp.service;
+
+import java.util.Set;
+
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@Service("adminAuthExtension")
+@Transactional
+/**
+ * Provides empty implementations of the methods in IAdminAuthExtension.
+ */
+public class AdminAuthExtension implements IAdminAuthExtension {
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AdminAuthExtension.class);
+
+ /*
+ * (non-Javadoc)
+ * @see org.openecomp.portalapp.service.IAdminAuthExtension#saveUserExtension(org.openecomp.portalsdk.core.domain.User)
+ */
+ public void saveUserExtension(User user) {
+ logger.debug("saveUserExtension");
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.openecomp.portalapp.service.IAdminAuthExtension#editUserExtension(org.openecomp.portalsdk.core.domain.User)
+ */
+ public void editUserExtension(User user) {
+ logger.debug("editUserExtension");
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.openecomp.portalapp.service.IAdminAuthExtension#saveUserRoleExtension(java.util.Set, org.openecomp.portalsdk.core.domain.User)
+ */
+ public void saveUserRoleExtension(Set<Role> roles, User user) {
+ logger.debug("saveUserRoleExtension");
+ }
+
+}
diff --git a/ecomp-sdk/sdk-app/src/main/resources/logback.xml b/ecomp-sdk/epsdk-app-os/src/main/resources/logback.xml
index 4f773ee2..c944721f 100644
--- a/ecomp-sdk/sdk-app/src/main/resources/logback.xml
+++ b/ecomp-sdk/epsdk-app-os/src/main/resources/logback.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
================================================================================
- eCOMP Portal SDK
+ ECOMP Portal SDK
================================================================================
Copyright (C) 2017 AT&T Intellectual Property
================================================================================
@@ -21,14 +21,14 @@
<configuration scan="true" scanPeriod="3 seconds" debug="true">
<!--
- Logback files for the ECOMP SDK Application "ecomp_app"
- are created in directory ${catalina.base}/logs/ecomp_app;
- e.g., apache-tomcat-8.0.35/logs/ecomp_app/application.log
+ Logback files for the ECOMP Portal SDK Application "epsdk-app-os"
+ are created in directory ${catalina.base}/logs/epsdk_app_os;
+ e.g., apache-tomcat-8.0.35/logs/epsdk_app_os/application.log
-->
<!--<jmxConfigurator /> -->
<!-- specify the component name -->
- <property name="componentName" value="ep_sdk_app"></property>
+ <property name="componentName" value="epsdk_app_os"></property>
<!-- specify the base path of the log directory -->
<property name="logDirPrefix" value="${catalina.base}/logs"></property>
@@ -327,38 +327,38 @@
<!-- ============================================================================ -->
<!-- EELF loggers -->
<!-- ============================================================================ -->
- <logger name="com.att.eelf" level="debug" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf" level="debug" additivity="false">
<appender-ref ref="asyncEELF" />
</logger>
<!--
- <logger name="com.att.eelf.security" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.security" level="info" additivity="false">
<appender-ref ref="asyncEELFSecurity" />
</logger>
- <logger name="com.att.eelf.perf" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.perf" level="info" additivity="false">
<appender-ref ref="asyncEELFPerformance" />
</logger>
- <logger name="com.att.eelf.server" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.server" level="info" additivity="false">
<appender-ref ref="asyncEELFServer" />
</logger>
- <logger name="com.att.eelf.policy" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.policy" level="info" additivity="false">
<appender-ref ref="asyncEELFPolicy" />
</logger>
-->
- <logger name="com.att.eelf.audit" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.audit" level="info" additivity="false">
<appender-ref ref="asyncEELFAudit" />
</logger>
- <logger name="com.att.eelf.metrics" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.metrics" level="info" additivity="false">
<appender-ref ref="asyncEELFMetrics" />
</logger>
- <logger name="com.att.eelf.error" level="info" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.error" level="info" additivity="false">
<appender-ref ref="asyncEELFError" />
</logger>
- <logger name="com.att.eelf.debug" level="debug" additivity="false">
+ <logger name="org.openecomp.epsdk.eelf.debug" level="debug" additivity="false">
<appender-ref ref="asyncEELFDebug" />
</logger>
@@ -367,4 +367,4 @@
<appender-ref ref="asyncEELF" />
</root>
-</configuration>
+</configuration> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/resources/portal.properties b/ecomp-sdk/epsdk-app-os/src/main/resources/portal.properties
new file mode 100644
index 00000000..76c679e5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/resources/portal.properties
@@ -0,0 +1,52 @@
+###
+# ================================================================================
+# ECOMP Portal SDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ================================================================================
+###
+# Properties read by ECOMP Framework library, ecompFW.jar
+
+##########################################################################
+# The following properties should NOT be changed by partner applications.
+##########################################################################
+
+portal.api.prefix = /api
+max.idle.time = 5
+user.attribute.name = user_attribute
+
+#Use REST API instead of UEB to fetch the functional menu data
+use_rest_for_functional_menu=true
+
+##########################################################################
+# The following properties MUST be changed by partner applications.
+##########################################################################
+
+# Name of java class that implements the OnBoardingApiService interface.
+portal.api.impl.class = org.openecomp.portalapp.service.OnBoardingApiServiceImpl
+
+# URL of the Portal where this app is onboarded
+ecomp_redirect_url = https://portal.openecomp.org/ecompportal/process_csp
+
+# URL of the ECOMP Portal REST API
+ecomp_rest_url = http://portal.openecomp.org:50580/ecompportal/auxapi
+
+# Applications do not need to run a UEB listener after 1607.
+ueb_listeners_enable = false
+
+# UEB Configuration
+# If key ueb_listeners_enable is set to false,
+# then only the ueb_app_key is required.
+ueb_app_key = REPLACE-ME-UEB-APP-KEY-EPSDK-APP-OS
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties
new file mode 100644
index 00000000..1f8aac82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/conf/system.properties
@@ -0,0 +1,69 @@
+# Properties read by ECOMP Core library, epsdk-core.jar
+
+##########################################################################
+# The following properties should NOT be changed by partner applications.
+##########################################################################
+
+application_user_id = 30000
+post_default_role_id = 16
+clustered = true
+
+#Enable Fusion Mobile capabilities for the application
+mobile_enable = false
+
+# Cache config file is needed on the classpath
+cache_config_file_path = /WEB-INF/classes/cache.ccf
+cache_switch = 199
+cache_load_on_startup = false
+
+user_name = fullName
+decryption_key = AGLDdG4D04BKm2IxIWEr8o==
+
+##########################################################################
+# The following properties REQUIRE changes by partner applications.
+##########################################################################
+
+
+#Mysql
+db.driver = com.mysql.jdbc.Driver
+db.connectionURL = jdbc:mysql://localhost:3306/ecomp_sdk_os
+db.userName = xxxx
+db.password = xxxxxxxx
+db.encrypt_flag = false
+db.hib.dialect = org.hibernate.dialect.MySQLDialect
+db.min_pool_size = 5
+db.max_pool_size = 10
+hb.dialect = org.hibernate.dialect.MySQLDialect
+# SQL statements are logged to stdout
+hb.show_sql = true
+hb.idle_connection_test_period = 3600
+
+app_display_name = EP SDK App OS
+# license file area
+files_path = /tmp
+
+#element map files
+element_map_file_path = app/fusionapp/files/
+element_map_icon_path = app/fusionapp/icons/
+
+#Cron Schedules have 6 required fields and 1 optional field:
+# Seconds Minutes Hours Day-of-Month Month Day-of-Week Year
+log_cron = 0 0/1 * * * ?;
+#sessiontimeout_feed_cron = 0 * * * * ? *
+
+# Link shown in Help menu
+contact_us_link = https://wiki.onap.org/display/DW/Portal
+
+# An Unique 128-bit value defined to identify a specific version
+# of an application deployed on a specific virtual machine.
+# This value must be generated and updated by the application
+# which is using the ECOMP SDK at the time of its deployment.
+# Online Unique UUID generator - https://www.uuidgenerator.net/
+instance_uuid=8da691c9-987d-43ed-a358-00ac2f35685d
+
+# Application base URL has the host and app context only; a proper prefix of the on-boarded URL.
+# Only required for applications using FE/BE separation. For example:
+# app_base_url = https://www.openecomp.org/app_context/
+
+#authenticate user server
+authenticate_user_server=http://todo_enter_auth_server_hostname:8383/openid-connect-server-webapp/allUsers \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/defs/definitions.xml b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/defs/definitions.xml
new file mode 100644
index 00000000..22f75c9d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/defs/definitions.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
+ "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
+
+<!--
+ This tiles definitions file is defs/definitions.xml.
+ It maps tokens used by app controllers to JSP file paths.
+ Applications that use JSP pages should modify this file.
+ Configured by ExternalAppConfig#addTileDefinitions().
+-->
+
+<tiles-definitions>
+
+ <definition name="tileKey" template="/path/to/page_template.html"/>
+
+</tiles-definitions>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/conf/fusion.properties b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
new file mode 100644
index 00000000..25465cb1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
@@ -0,0 +1,29 @@
+# login settings
+login_method_backdoor = backdoor
+login_method_attribute_name = login_method
+
+#login message
+login.error.hrid.empty = Login failed, please contact system administrator.
+login.error.hrid.not-found = User not found, please contact system administrator.
+login.error.user.inactive = Account is disabled, please contact system administrator.
+
+# User Session settings
+user_attribute_name = user
+roles_attribute_name = roles
+role_functions_attribute_name = role_functions
+
+# Import-user LDAP settings
+post_initial_context_factory = com.sun.jndi.ldap.LdapCtxFactory
+post_provider_url = ldap://ldap.mycompany.com:389
+post_security_principal = ou=people,o=mycompany,c=us
+post_max_result_size = 499
+
+# menu settings
+menu_query_name = menuData
+application_menu_set_name = APP
+application_menu_attribute_name = applicationMenuData
+business_direct_menu_set_name = BD
+business_direct_menu_attribute_name = businessDirectMenuData
+
+# Role settings
+sys_admin_role_id = 1
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/footer.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/footer.jsp
new file mode 100644
index 00000000..3374b75f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/footer.jsp
@@ -0,0 +1,17 @@
+<script src="./app/fusion/external/angular-1.5/angular.min.js"></script>
+<script src="app/fusion/external/ds2/js/b2b-angular/b2b-library.min.js"></script>
+<link rel="stylesheet" type="text/css" href="./app/fusion/external/ds2/css/b2b-angular/b2b-angular.css"></style>
+
+<div style="position: relative; bottom: 0; left: 0; width: 100%">
+ <footer class="b2b-footer-wrapper" role="contentinfo"
+ aria-label="footer">
+ <div class="b2b-footer-container" b2b-column-switch-footer>
+ <!-- footer-link-items='footerItems' -->
+ <!-- <hr> -->
+ <div style="margin-top: -25px;" class="divider-bottom-footer">
+ <div class="span12 footerLogo">
+ </div>
+ </div>
+ </div>
+ </footer>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/header.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/header.jsp
new file mode 100644
index 00000000..94213a2a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/header.jsp
@@ -0,0 +1 @@
+<div ds2-menu id="menuContainer" class="menu-container" ></div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/left-menu.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/left-menu.jsp
new file mode 100644
index 00000000..cbf7f8ad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/jsp/ds2/left-menu.jsp
@@ -0,0 +1,778 @@
+<%--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ --%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
+<%@ page isELIgnored="false"%>
+<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%>
+<%@ page import="org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties"%>
+<%@ page import="org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants"%>
+<%@ page import="org.openecomp.portalsdk.core.domain.MenuData"%>
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
+
+
+<!-- <script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/app.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
+<script src="static/js/jquery-1.10.2.js"></script>
+<script src="app/fusion/scripts/modalService.js"></script>
+<script src="static/js/jquery.mask.min.js" type="text/javascript"></script>
+<script src="static/js/jquery-ui.js" type="text/javascript"></script>
+<script src="app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
+<script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
+<script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
+<script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
+<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/0.10.0/lodash.min.js"></script>
+<script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
+<script src="app/fusion/scripts/services/userInfoService.js"></script>
+<script src="app/fusion/scripts/services/leftMenuService.js"></script> -->
+
+
+<jsp:include page="/WEB-INF/fusion/jsp/ebz/loginSnippet.html" ></jsp:include>
+
+
+<c:set var="UserName" value="<%= session.getAttribute(\"fullName\")%>" />
+<c:set var="UserFirstName" value="<%= session.getAttribute(\"first_name\")%>" />
+
+<%
+ String contactUsLink = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
+ String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
+ String portalUrl = redirectUrl.substring(0, redirectUrl.lastIndexOf('/')) + "/process_csp";
+ String getAccessLink = redirectUrl.substring(0, redirectUrl.lastIndexOf('/')) + "/get_access";
+%>
+<c:set var="returnPortalUrl" value="<%=portalUrl%>" />
+<c:set var="contactUsLink" value="<%=contactUsLink%>" />
+<c:set var="getAccessLink" value="<%=getAccessLink%>" />
+
+<style>
+</style>
+
+<%@include file="/WEB-INF/fusion/jsp/ebz/loginSnippet.html" %>
+
+<div style="position: relative; z-index: 999;">
+ <div ng-controller="headerController">
+
+ <div class="headerContainer" id="headerContainer" ng-cloak ng-show="{{showHeader}}">
+ <div id="megaMenuContainer" class="megaMenuContainer" style="margin-top: 0; overflow: visible;">
+ <div>
+ <!--for mega Menu-->
+ <!-- Mega Menu parent-tab directive with three models menu-items, active-sub-menu, active-menu -->
+ <div id="topMenu" class="top-megamenu" ng-mouseleave="activeClickSubMenu.x.active=false; activeClickMenu.x.active=false">
+ <div style="float:left;width:100%;"parent-tab menu-items="megaMenuDataObject" active-sub-menu='activeClickSubMenu.x' active-menu='activeClickMenu.x'>
+ <div parentmenu-tabs mega-menu="true" menu-items="megaMenuDataObject" style="height:55px;">
+ <div style="float:left">
+ <li class="megamenu__item" style="line-height:55px;" onclick="returnToPortal()">
+ <img src="app/fusion/external/ebz/images/att_logo.png" class="ATTLogo" ></span>
+ <strong style="font-weight: 400 !important; font-family: "Omnes-ECOMP-W02", Arial !important; font-size: 18px;" id='returnPortal' >ECOMP Portal</strong>
+ </li>
+ <div menu-tabs mega-menu="true" tab-name="item.text" menu-item="item" active-menu="activeClickMenu.x"
+ ng-repeat="item in megaMenuDataObject" style="font-size: 18px;" ng-mousedown="loadFavorites()" >
+ <div parentmenu-tabs sub-menu="true" ng-show="activeClickMenu.x.active && item.active" menu-items="activeClickMenu.x.children">
+ <!-- Second level menu -->
+ <div>
+ <div menu-tabs sub-menu="true" tab-name="subItem.text"
+ tab-url="subItem.url" menu-item="subItem"
+ ng-repeat="subItem in activeClickMenu.x.children | orderBy : 'column'" active-menu="activeClickSubMenu.x"
+ sub-item-active="{{subItem.active}}" style="float:left;" aria-label="{{subItem.text}}"
+ ng-mouseenter="submenuLevelAction(subItem.text,subItem.column)"
+ ng-mouseleave="submenuLevelAction(subItem.text,subItem.column)"
+ ng-click="submenuLevelAction(subItem.text,subItem.column)" >
+ <i ng-if="subItem.text=='Favorites'" id="favorite-star"
+ class="icon-star favorites-icon-active">
+ </i>
+ </div>
+
+ <div class="sub__menu" ng-mouseleave="activeClickSubMenu.x.active=false" >
+ <ul ng-show="activeClickSubMenu.x.active" role="menubar" class="columns">
+ <!-- Third level menu -->
+ <div menu-tabs menu-item="subItem"
+ class="columns-div"
+ ng-repeat="subItem in activeClickSubMenu.x.children | orderBy : 'column'"
+ ng-show="activeClickSubMenu.x.active">
+
+ <i id="favorite-selector-third-level"
+ ng-show="isUrlFavorite(subItem.menuId)==false"
+ class="icon-star favorites-icon-inactive"
+ ng-if="subItem.url.length > 1">
+ </i>
+ <i id="favorite-selector-third-level"
+ ng-show="isUrlFavorite(subItem.menuId)"
+ class="icon-star favorites-icon-active"
+ ng-if="subItem.url.length > 1">
+ </i>
+ <span class="title" aria-label="{{subItem.text}}"
+ ng-click="goToUrl(subItem)">{{subItem.text}}</span>
+ <!-- Fourth level menus -->
+ <div att-links-list="">
+ <i id="favorite-selector-fourth-level"
+ class="icon-star favorites-icon-inactive"
+ ng-show="isUrlFavorite(tabValue.menuId)==false"
+ ng-if="tabValue.url.length > 1">
+
+ </i>
+ <i id="favorite-selector-fourth-level"
+ class="icon-star favorites-icon-active"
+ ng-show="isUrlFavorite(tabValue.menuId)"
+ ng-if="tabValue.url.length > 1">
+
+ </i>
+ <span role="menuitem" att-links-list-item=""
+ ng-repeat="tabValue in subItem.children"
+ ng-click="goToUrl(tabValue)"
+ att-accessibility-click="13,32"
+ ng-class="{'disabled': tabValue.disabled}">{{tabValue.text}}</span>
+ </div>
+ <hr ng-show="!$last"/>
+
+ </div>
+ </ul>
+ <!-- Favorites level menu -->
+ <div class="favorites-window" ng-show='favoritesWindow' ng-mouseleave="hideFavoritesWindow()">
+ <div id="favorites-menu-items" ng-show="showFavorites">
+ <div ng-repeat="subItem in favoritesMenuItems" att-links-list="" style='display: inline'>
+ <i id="favorite-selector-favorites-list" class="icon-star favorites-icon-active">
+ </i>
+ <a id="favorites-list" aria-label="{{subItem.text}}"
+ ng-click="goToUrl(subItem)"
+ style="margin-left: 3px; margin-right: 20px; text-decoration: none; color: #666666;">
+ {{subItem.text}}
+ </a>
+ </div>
+ <div>
+ <br>
+ <p style='font-weight: 400; font-family: "Omnes-ECOMP-W02", Arial !important;
+ font-size: 18px; text-align: center; background-color: lightgray;
+ width: 400px; margin-left: 25%; margin-right: 25%;'>
+ Manage favorites on ECOMP Portal.
+ </p>
+ </div>
+ </div>
+ <!-- Favorites when empty -->
+ <div id="favorites-empty" ng-show='favoritesWindow' ng-show="emptyFavorites">
+ <div id="favorites-empty" ng-show="emptyFavorites" class="favorites-window-empty">
+ <div>
+ <img src="app/fusion/external/ebz/images/no_favorites_star.png">
+ <p class='favoritesLargeText'>No Favorites</p>
+ <p class='favoritesNormalText'>Manage favorites on ECOMP Portal.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div >
+ <li class="megamenu__item" style="line-height:55px;" ng-if="loadMenufail">
+ <strong style="font-weight: 400 !important; font-family: "Omnes-ECOMP-W02", Arial !important; font-size: 18px;" >Unable to load menus</strong>
+ </li>
+<!-- <li class="megamenu__item" style="width: 20%;">&nbsp;</li>
+ --> </div>
+ <!-- Login Snippet-->
+ <div style="float:right">
+ <li id="bcLoginSnippet" class="megamenu__item" style="width: 140px;" >
+ <div popover="loginSnippet.html" aria-label="Login Snippet" referby="loginSnippet" att-accessibility-click="13,32" popover-style="\" popover-placement="below" style="width: 200px;">
+ <div class="icon-user-small login-snippet-icon"></div>
+ <div class="login-snippet-text" style="display: inline-block; font-size:12px; margin-left:5px;overflow: hidden; max-height: 31px; max-width:120px; padding-top: 0px; margin-top: 0px; white-space: nowrap;" ng-bind="userProfile.firstName"></div>
+ </div>
+ </li>
+ <li class="megamenu__item" style="width:120px;">&nbsp;</li>
+ </div>
+
+ </div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="license-notification" id="license-notification">
+ <a href="javascript:void(0)" style="background-color:#bbb;" class="button button--small" tooltip="Please contact ECOMP Portal team to get the license" tooltip-placement="below" tooltip-style="light" tooltip-popup-delay="500" >
+ <span style="">{{app_name_full}}</span>
+ </a>
+ </div>
+ <div style="position: relative; color: black; top: 70px;">
+ <div ng-cloak>
+ <span ng-style="adjustHLeftMenu('burgerIcon')" style="z-index:998; position:fixed; left:0%; font-size:35px; margin-left:10px;text-decoration:none;">
+ <a ng-click="toggleDrawer();isOpen = !isOpen" href="javascript:void(0);" class="arrow-icon-left" >
+ <span class="icon-hamburger"></span></a>
+ <span ng-init="isOpen = true" ng-show="isOpen" style="font-size:16px; position:relative; top:-8px; left:-15px;">&nbsp&nbsp&nbsp {{app_name}}</span>
+ </span>
+ <div att-drawer drawer-slide="left" drawer-custom-top="{{drawer_custom_top}}px" drawer-size="200px" drawer-open="drawerOpen" drawer-custom-height="100%" >
+ <div ng-style="adjustHLeftMenu('leftMenu')">
+ <div class="attDrawer" style="margin-top:{{drawer_margin_top}}px;">
+ <div style="margin-left:10px; margin-right:10px;">
+ <accordion close-others="true" css="att-accordion--no-box">
+ <accordion-group ng-repeat="parent in menuItems" heading="{{parent.parentLabel}}" child="{{parent.parentAction}}" parent-link="{{parent.parentAction}}" image-source="{{parent.parentImageSrc}}" child-length="{{parent.childItemList.length}}" is-open="parent.open">
+ <div ng-repeat="subMenu in parent.childItemList" style="font-size:12px; margin-left:10px;">
+ <a href="{{subMenu.action}}" style="font-size:12px; color:#666666;" >{{subMenu.label}}</a>
+ </div>
+ </accordion-group>
+ </accordion>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+ function returnToPortal(){
+ window.location.href = "<c:out value='${returnPortalUrl}'/>";
+ }
+ detectScrollEvent = function() {
+ var footerOff = $('#footerContainer').offset().top;
+ var headOff = $('#headerContainer').offset().top;
+ var winHeight = $(window).height();
+ if ((footerOff - headOff) <= winHeight) {
+ $('.att-drawer').css({
+ "height" : footerOff - headOff - 55
+ });
+ } else {
+ $('.att-drawer').css({
+ "height" : "94vh"
+ });
+ }
+ }
+ $(window).scroll(function() {
+ if ($('.att-drawer').is(':visible')) {
+ detectScrollEvent();
+ }
+ });
+ app.controller("headerController", function($scope, $timeout, $log, $http, UserInfoService, $window, $cookies,LeftMenuService) {
+ // $log.debug('HeaderController started');
+ $scope.jsonMenuData = [];
+ $scope.loadMenufail=false;
+ $scope.app_name = "";
+ $scope.app_name_full = "";
+ $scope.megaMenuDataObject =[];
+ $scope.activeClickSubMenu = {
+ x: ''
+ };
+ $scope.activeClickMenu = {
+ x: ''
+ };
+ $scope.favoritesMenuItems = [];
+ $scope.favoriteItemsCount = 0;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ $scope.favoritesWindow = false;
+ $scope.userProfile={
+ firstName:'',
+ lastName:'',
+ fullName:'',
+ email:''
+ }
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
+ $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
+ if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
+ $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
+ if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
+ $scope.userProfile.email = userInfo.USER_EMAIL;
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoService.getFunctionalMenuStaticDetailSession()
+ .then(function (res) {
+ $scope.userProfile.firstName = res.firstName;
+ $scope.redirectUrl = res.portalUrl;
+ });
+ }
+ $scope.getTopMenuStaticInfo=function() {
+ var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('failed getting static User information');
+ $scope.getUserNameFromSession();
+ }else{
+ $log.info('Received static User information');
+ var resData = res;
+ $scope.inputUserInfo(resData);
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ }
+ },
+ function(err) {
+ $log.info('failed getting static User information');
+ }
+ );
+ }
+
+ var unflatten = function( array, parent, tree ){
+ tree = typeof tree !== 'undefined' ? tree : [];
+ parent = typeof parent !== 'undefined' ? parent : { menuId: null };
+ var children = _.filter( array, function(child){ return child.parentMenuId == parent.menuId; });
+
+ if( !_.isEmpty( children ) ){
+ if( parent.menuId === null ){
+ tree = children;
+ }else{
+ parent['children'] = children
+ }
+ _.each( children, function( child ){ unflatten( array, child ) } );
+ }
+
+ return tree;
+ }
+
+ var menuStructureConvert = function(menuItems) {
+ var megaMenuDataObjectTemp = [
+ {
+ text: "ECOMP",
+ children:menuItems
+ },
+ {
+ text: "Help",
+ children: [{
+ text:"Contact Us",
+ url:"<c:out value='${contactUsLink}'/>"
+ },
+ {
+ text:"Get Access",
+ url:"<c:out value='${getAccessLink}'/>"
+ }]
+ }
+ ];
+ return megaMenuDataObjectTemp;
+ };
+
+
+ /*Left Menu*/
+ LeftMenuService.getAppName().then(function(response){
+ var j = response;
+ try{
+ if(j && j !== "null" && j!== "undefined"){
+ // console.log("app name is " + $scope.app_name);
+ $scope.app_name_full = j.data;
+ var processed_app_name = j.data;
+ if(processed_app_name.indexOf("[")<=-1) {
+ if (document.getElementById('license-notification')!=null)
+ document.getElementById('license-notification').style.display = "none";
+ }
+ var n = processed_app_name.length;
+ if (n > 15) {
+ n = 15;
+ }
+ $scope.app_name = processed_app_name.substr(0, n);
+ }else{
+ throw "Get app_name response is not an object/is empty";
+ }
+ }catch (e) {
+ console.log("error happened while trying to get app name "+e);
+ return;
+ }
+ },function(error){
+ console.log('getAppName failed', error);
+ });
+
+ $scope.getTopMenuStaticInfo();
+ $scope.getMenu=function() {
+
+ $http({
+ method: "GET",
+ url: 'get_functional_menu',
+// TIMEOUT USED FOR LOCAL TESTING ONLY
+// timeout: 100
+ }).success(function (response) {
+ if(response == '101: Timeout') {
+ $log.error('Timeout attempting to get_functional_menu');
+ // TIMEOUT USED FOR LOCAL TESTING ONLY
+// $scope.createErrorMenu();
+ $scope.megaMenuDataObject = menuStructureConvert('');
+ }else {
+ $log.debug('get_functional_menu success: ' + response);
+ if(typeof response != 'undefined' && response.length!=0 && typeof response[0] != 'undefined' && typeof response[0].error!="undefined"){
+// createErrorMenu() USED FOR LOCAL TESTING ONLY
+// $scope.createErrorMenu();
+ $scope.megaMenuDataObject = menuStructureConvert('');
+ // $scope.loadMenufail=true;
+ }else{
+ $scope.jsonMenuData = unflatten( response );
+ $scope.megaMenuDataObject = menuStructureConvert($scope.jsonMenuData);
+ }
+ }
+ }).error(function (response){
+// createErrorMenu() USED FOR LOCAL TESTING ONLY
+// $scope.createErrorMenu();
+
+ //$scope.loadMenufail=true;
+ $scope.megaMenuDataObject = menuStructureConvert('');
+ $log.debug('REST API failed get_functional_menu...'+ response);
+ });
+ }
+ $scope.adjustHLeftMenu = function (type){
+ $scope.showHeader = ($cookies.show_app_header == undefined ? true : $cookies.show_app_header);
+
+ if($scope.showHeader == true) {
+ $scope.drawer_margin_top = 60;
+ $scope.drawer_custom_top = 54;
+ $scope.toggle_drawer_top = 55;
+ }
+ else {
+
+ $scope.drawer_margin_top = 50;
+ $scope.drawer_custom_top = 0;
+ $scope.toggle_drawer_top = 10;
+ }
+ if(type=='burgerIcon'){
+ return { "top": $scope.toggle_drawer_top+"px"};
+ }else if(type=='leftMenu'){
+ return { "margin-top": $scope.drawer_margin_top+"px"};
+ }else
+ return;
+ }
+ $scope.adjustHeader=function() {
+ $scope.showHeader = ($cookies.show_app_header == undefined ? true : $cookies.show_app_header);
+
+ if($scope.showHeader == true) {
+ $scope.drawer_margin_top = 50;
+ $scope.drawer_custom_top = 54;
+ $scope.toggle_drawer_top = 55;
+ }
+ else {
+
+ $scope.drawer_margin_top = 40;
+ $scope.drawer_custom_top = 0;
+ $scope.toggle_drawer_top = 10;
+ }
+
+
+ }
+
+
+ //$scope.getMenu();
+ $scope.adjustHeader();
+
+
+ /* **************************************************************************/
+ /* Logic for the favorite menus is here */
+
+ $scope.loadFavorites = function () {
+ $log.debug('loadFavorites has happened.');
+ if ($scope.favoritesMenuItems == '') {
+ $scope.generateFavoriteItems();
+ $log.debug('loadFavorites is calling generateFavoriteItems()');
+ } else {
+ $log.debug('loadFavorites is NOT calling generateFavoriteItems()');
+ }
+ }
+
+ $scope.goToUrl = function (item) {
+ $log.info("goToUrl called")
+ $log.info(item);
+
+ var url = item.url;
+ var restrictedApp = item.restrictedApp;
+ $log.debug('Restricted app status is: ' + restrictedApp);
+ if (!url) {
+ $log.info('No url found for this application, doing nothing..');
+ return;
+ }
+ if (restrictedApp) {
+ $window.open(url, '_blank');
+ } else {
+ $window.open(url, '_self');
+ }
+
+ }
+
+ $scope.submenuLevelAction = function(index, column) {
+ if ($scope.favoritesMenuItems == '') {
+ $scope.generateFavoriteItems();
+ $log.debug('submenuLevelAction is calling generateFavoriteItems()');
+ }
+ $log.debug('item hovered/clicked: ' + index + '; column = ' + column);
+ if (column == 2) { // 2 is Design
+ $scope.favoritesWindow = false;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+ if (index=='Favorites' && $scope.favoriteItemsCount != 0) {
+ $log.debug('Showing Favorites window');
+ $scope.favoritesWindow = true;
+ $scope.showFavorites = true;
+ $scope.emptyFavorites = false;
+ }
+ if (index=='Favorites' && $scope.favoriteItemsCount == 0) {
+ $log.debug('Hiding Favorites window in favor of No Favorites Window');
+ $scope.favoritesWindow = true;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = true;
+ }
+ if (column > 2) {
+ $scope.favoritesWindow = false;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+ };
+
+ $scope.hideFavoritesWindow = function() {
+ $log.debug('$scope.hideFavoritesWindow has been called');
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+
+ $scope.isUrlFavorite = function (menuId) {
+// $log.debug('array objects in menu favorites = ' + $scope.favoriteItemsCount + '; menuId=' + menuId);
+ var jsonMenu = JSON.stringify($scope.favoritesMenuItems);
+ var isMenuFavorite = jsonMenu.indexOf('menuId\":' + menuId);
+ if (isMenuFavorite==-1) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ $scope.generateFavoriteItems = function() {
+ $http({
+ method: "GET",
+ url: 'get_favorites',
+ // TIMEOUT USED FOR LOCAL TESTING ONLY
+// timeout: 100
+ }).success(function (response) {
+ if (response == '101: Timeout') {
+ $log.error('Timeout attempting to get_favorites_menu');
+ } else {
+ if(typeof response != 'undefined' && response.length!=0 && typeof response[0] != 'undefined' && typeof response[0].error!="undefined"){
+ $log.error('REST API failed get_favorites' + response);
+ }else{
+ $log.debug('get_favorites = ' + JSON.stringify(response));
+ $scope.favoritesMenuItems = response;
+ $scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
+ $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ }
+ }
+ }).error(function (response){
+ $log.error('REST API failed get_favorites' + response);
+ //createFavoriteErrorMenu() USED FOR LOCAL TESTING ONLY
+// $scope.createFavoriteErrorMenu();
+ });
+ }
+
+ $scope.createFavoriteErrorMenu=function() {
+ $scope.favoritesMenuItems = [
+//
+ ];
+ $scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
+ $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ }
+
+ /* end of Favorite Menu code */
+ /* **************************************************************************/
+
+
+ /* **************************************************************************/
+ // THIS IS USED FOR LOCAL TESTING ONLY
+ /* **************************************************************************/
+
+ $scope.createErrorMenu=function() {
+ $scope.jsonMenuData = [
+ {
+ "menuId": 1,
+ "column": 2,
+ "text": "Design",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 2,
+ "column": 3,
+ "text": "Infrastructure Ordering",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 3,
+ "column": 4,
+ "text": "Service Creation",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 4,
+ "column": 5,
+ "text": "Service Mgmt",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 90,
+ "column": 1,
+ "text": "Google",
+ "parentMenuId": 1,
+ "url": "http://google.com"
+ },
+ {
+ "menuId": 91,
+ "column": 1,
+ "text": "Mike Little's Coffee Cup",
+ "parentMenuId": 2,
+ "url": "http://coffee.com"
+ },
+ {
+ "menuId": 92,
+ "column": 2,
+ "text": "Andy and his Astrophotgraphy",
+ "parentMenuId": 3,
+ "url": "http://nightskypix.com"
+ },
+ {
+ "menuId": 93,
+ "column": 1,
+ "text": "JSONLint",
+ "parentMenuId": 4,
+ "url": "http://http://jsonlint.com"
+ },
+ {
+ "menuId": 94,
+ "column": 2,
+ "text": "HROneStop",
+ "parentMenuId": 4,
+ "url": "http://ebiz.sbc.com/hronestop"
+ },
+
+ {
+ "menuId": 96,
+ "column": 3,
+ "text": "3rd Level App1c R200",
+ "parentMenuId": 4,
+ "url": "http://app1c.com"
+ },
+ {
+ "menuId": 97,
+ "column": 1,
+ "text": "3rd Level App4b R16",
+ "parentMenuId": 5,
+ "url": "http://app4b.com"
+ },
+ {
+ "menuId": 98,
+ "column": 2,
+ "text": "3rd Level App2b R16",
+ "parentMenuId": 5,
+ "url": "http://app2b.com"
+ },
+ {
+ "menuId": 99,
+ "column": 1,
+ "text": "Favorites",
+ "parentMenuId": null,
+ "url": ""
+ }
+ ];
+ $scope.jsonMenuData = unflatten( $scope.jsonMenuData );
+ $scope.megaMenuDataObject = menuStructureConvert($scope.jsonMenuData);
+// $log.debug(JSON.stringify($scope.jsonMenuData));
+ }
+ var childItemList="";
+ var parentList = "";
+ try{
+ childItemList = ${menu.childItemList};
+ parentList = ${menu.parentList};
+ }catch(err){
+ console.log("ebz_header: failed to get child/parent lists", err);
+ }
+
+ var pageUrl = window.location.href.split('/')[window.location.href.split('/').length-1];
+
+ $scope.menuItems = [];
+ for (var i = 0; i < parentList.length; i++) {
+ $scope.openCurrentMenu = false;
+ if(pageUrl==parentList[i].action)
+ $scope.openCurrentMenu = true;
+ $scope.childItemList = childItemList[i];
+ for(chIndex in $scope.childItemList){
+ if($scope.childItemList.length>0)
+ if($scope.childItemList[chIndex].action!=null){
+ if($scope.childItemList[chIndex].action==pageUrl)
+ $scope.openCurrentMenu = true;
+ }
+ }
+ $scope.item = {
+ parentLabel : parentList[i].label,
+ parentAction : parentList[i].action,
+ parentImageSrc : parentList[i].imageSrc,
+ open:$scope.openCurrentMenu,
+ childItemList : $scope.childItemList
+ }
+ $scope.menuItems.push($scope.item);
+ }
+ $scope.arrowShow = true;
+ $scope.drawerOpen = false;
+ $scope.subMenuContent = false;
+ $scope.toggleSubMenu = function() {
+ $scope.subMenuContent = !$scope.subMenuContent;
+ };
+
+ var drawerOpen = 'open';
+ if (drawerOpen == 'open') {
+ $scope.drawerOpen = true;
+ $scope.arrowShow = true;
+ } else {
+ $scope.arrowShow = false;
+ }
+ $scope.arrowShow = true;
+ $scope.drawerOpen = false;
+ $scope.toggleDrawer = function() {
+ $scope.drawerOpen = !($scope.drawerOpen);
+ if ($scope.drawerOpen) {
+ $scope.arrowShow = true;
+ if (document.getElementById('mContent')!=null)
+ document.getElementById('mContent').style.marginLeft = "0px";
+ } else {
+ $scope.arrowShow = false;
+ if (document.getElementById('mContent')!=null)
+ document.getElementById('mContent').style.marginLeft = "-150px";
+ }
+ };
+ //var drawerOpen = getCookie('drawerOpen');
+ if (drawerOpen == 'open') {
+ $scope.drawerOpen = true;
+ $scope.arrowShow = true;
+ } else {
+ $scope.arrowShow = false;
+ }
+ $timeout(function() {
+ detectScrollEvent();
+ }, 800);
+
+ });
+
+ app.filter("ellipsis", function(){
+ return function(text, length){
+ if (text) {
+ var ellipsis = text.length > length ? "..." : "";
+ return text.slice(0, length) + ellipsis;
+ };
+ return text;
+ }
+ });
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml
index 6638b4bc..6638b4bc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/fusion/orm/RNoteBookIntegration.hbm.xml
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/index.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/index.jsp
index f6030c97..f6030c97 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/index.jsp
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/index.jsp
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login.jsp
new file mode 100644
index 00000000..09320356
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login.jsp
@@ -0,0 +1,113 @@
+<%--
+ ================================================================================
+ ECOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+--%>
+<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%>
+<!DOCTYPE html>
+<%
+ // Name is defined by app; do not throw if missing
+ final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME)
+ ? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)
+ : SystemProperties.APP_DISPLAY_NAME;
+%>
+
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Login</title>
+ <style>
+ html {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ }
+ body {
+ padding-top: 15px;
+ }
+ .logo {
+ position: fixed;
+ left: 15px;
+ top: 15px;
+ z-index: -1;
+ }
+ .loginError {
+ font-size: 18px;
+ color: red;
+ text-align: center;
+ }
+ .login {
+ font-size: 16px;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+ width: 100%;
+ }
+ .login input[type=submit] {
+ font-size: 16px;
+ }
+ .terms {
+ font-size: 10px;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .terms a {
+ font-size: 10px;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="login">
+ <img src="static/fusion/images/ecomp_trans.png" />
+ <h2>
+ <%=appDisplayName%>
+ </h2>
+ <br />
+ <form action="login_external" method="POST">
+ <label for="loginId">Login ID:</label>
+ <input id="loginId" name="loginId" type="text" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;" maxlength="30">
+ <br/>
+ <br/>
+ <label for="password">Password:</label>
+ <input id="password" name="password" type="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
+ maxlength="30" >
+ <br />
+ <br />
+ <input id="loginBtn" type="submit" alt="Login" value="Login">
+ </form>
+ </div>
+ <br />
+ <br />
+ <div class="loginError">${model.error}</div>
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <div id="footer">
+ <div class="terms">
+ Copyright 2017 Open ECOMP and Linux Foundation.
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp
new file mode 100644
index 00000000..9d099bf0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp
@@ -0,0 +1,117 @@
+<%--
+ ================================================================================
+ ECOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+--%>
+<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%>
+<!DOCTYPE html>
+<%
+ // Name is defined by app; do not throw if missing
+ final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME)
+ ? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)
+ : SystemProperties.APP_DISPLAY_NAME;
+%>
+
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <style>
+ html {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ }
+ body {
+ padding-top: 15px;
+ }
+ .logo {
+ position: fixed;
+ left: 15px;
+ top: 15px;
+ z-index: -1;
+ }
+ .loginError {
+ font-size: 18px;
+ color: red;
+ text-align: center;
+ }
+ .login {
+ font-size: 16px;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+ width: 100%;
+ }
+ .login input[type=submit] {
+ font-size: 16px;
+ }
+ .terms {
+ font-size: 10px;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .terms a {
+ font-size: 10px;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ </style>
+ </head>
+ <body>
+
+ <div class="login">
+ <img src="static/fusion/images/ecomp_trans.png" />
+ <h2>
+ <%=appDisplayName%>
+ </h2>
+ <br />
+ <form action="login_external" method="POST">
+ <label for="loginId">Login ID:</label>
+ <input id="loginId" name="loginId" type="text" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;" maxlength="30">
+ <br/>
+ <br/>
+ <label for="password">Password:</label>
+ <input id="password" name="password" type="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
+ maxlength="30" >
+ <br />
+ <br />
+ <input id="loginBtn" type="submit" alt="Login" value="Login">
+ </form>
+ </div>
+ <br />
+ <br />
+ <div class="loginError">${model.error}</div>
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <div id="footer">
+ <div class="terms">
+ Copyright 2017 Open ECOMP and Linux Foundation.
+ </div>
+ <p>
+ <div class="terms">
+
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..0290f1fc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+ version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee">
+
+ <display-name>ecomp-sdk-app-os</display-name>
+
+ <!-- The app can function on a HA cluster -->
+ <distributable />
+
+ <session-config>
+ <session-timeout>7</session-timeout>
+ <tracking-mode>COOKIE</tracking-mode>
+ </session-config>
+
+</web-app> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/font_icons.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/font_icons.css
new file mode 100644
index 00000000..0aa5b857
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/font_icons.css
@@ -0,0 +1 @@
+/* font_icons.css is in open source - this empty file prevents 404 error in browser */
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ionicons.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ionicons.css
new file mode 100644
index 00000000..3f7fef61
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ionicons.css
@@ -0,0 +1,1493 @@
+@charset "UTF-8";
+/*!
+ Ionicons, v2.0.0
+ Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
+ https://twitter.com/benjsperry https://twitter.com/ionicframework
+ MIT License: https://github.com/driftyco/ionicons
+
+ Android-style icons originally built by Google’s
+ Material Design Icons: https://github.com/google/material-design-icons
+ used under CC BY http://creativecommons.org/licenses/by/4.0/
+ Modified icons to fit ionicon’s grid from original.
+*/
+@font-face { font-family: "Ionicons"; src: url("../fonts/ionicons.eot?v=2.0.0"); src: url("../fonts/ionicons.eot?v=2.0.0#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=2.0.0") format("truetype"), url("../fonts/ionicons.woff?v=2.0.0") format("woff"), url("../fonts/ionicons.svg?v=2.0.0#Ionicons") format("svg"); font-weight: normal; font-style: normal; }
+.ion, .ionicons, .ion-alert:before, .icon-securityalerts-alertL:before, .icon-controls-add-maximize:before, .icon-controls-add-maximize-circle:before, .icon-misc-time:before, .icoSecurityalerts:before,.icon-apps-marketplace:before ,.icon-content-grid:before, .icon-documents-archive:before, .ion-android-arrow-back:before, .icon-arrows-vertical-arrow-down:before, .ion-android-arrow-dropdown:before, .icoArrows-download:before, .ion-android-arrow-dropleft:before, .icoArrows-incoming-call:before, .ion-android-arrow-dropright:before, .icon-arrows-outgoing-call:before, .ion-android-arrow-dropup:before, .icon-arrows-upload:before, .icon-arrows-straight-arrow:before, .icoArrows-vertical-arrow:before, .ion-android-attach:before, .ion-android-bar:before, .ion-android-bicycle:before, .ion-android-boat:before, .ion-android-bookmark:before, .ion-android-bulb:before, .ion-android-bus:before, .ion-android-calendar:before, .ion-android-call:before, .ion-android-camera:before, .ion-android-cancel:before, .ion-android-car:before, .ion-android-cart:before, .ion-android-chat:before, .ion-android-checkbox:before, .ion-android-checkbox-blank:before, .ion-android-checkbox-outline:before, .ion-android-checkbox-outline-blank:before, .ion-android-checkmark-circle:before, .ion-android-clipboard:before, .ion-android-close:before, .ion-android-cloud:before, .ion-android-cloud-circle:before, .ion-android-cloud-done:before, .ion-android-cloud-outline:before, .ion-android-color-palette:before, .ion-android-compass:before, .ion-android-contact:before, .ion-android-contacts:before, .ion-android-contract:before, .ion-android-create:before, .ion-android-delete:before, .ion-android-desktop:before, .ion-android-document:before, .ion-android-done:before, .ion-android-done-all:before, .ion-android-download:before, .ion-android-drafts:before, .ion-android-exit:before, .ion-android-expand:before, .ion-android-favorite:before, .ion-android-favorite-outline:before, .ion-android-film:before, .ion-android-folder:before, .ion-android-folder-open:before, .ion-android-funnel:before, .ion-android-globe:before, .ion-android-hand:before, .ion-android-hangout:before, .ion-android-happy:before, .ion-android-home:before, .ion-android-image:before, .ion-android-laptop:before, .ion-android-list:before, .ion-android-locate:before, .ion-android-lock:before, .ion-android-mail:before, .ion-android-map:before, .ion-android-menu:before, .ion-android-microphone:before, .ion-android-microphone-off:before, .ion-android-more-horizontal:before, .ion-android-more-vertical:before, .ion-android-navigate:before, .ion-android-notifications:before, .ion-android-notifications-none:before, .ion-android-notifications-off:before, .ion-android-open:before, .ion-android-options:before, .ion-android-people:before, .ion-android-person:before, .icon-people-userbookmark:before, .ion-android-phone-landscape:before, .ion-android-phone-portrait:before, .ion-android-pin:before, .ion-android-plane:before, .ion-android-playstore:before, .ion-android-print:before, .ion-android-radio-button-off:before, .ion-android-radio-button-on:before, .ion-android-refresh:before, .ion-android-remove:before, .ion-android-remove-circle:before, .ion-android-restaurant:before, .ion-android-sad:before, .ion-android-search:before, .ion-android-send:before, .ion-android-settings:before, .ion-android-share:before, .ion-android-share-alt:before, .ion-android-star:before, .ion-android-star-half:before, .ion-android-star-outline:before, .ion-android-stopwatch:before, .ion-android-subway:before, .ion-android-sunny:before, .ion-android-sync:before, .ion-android-textsms:before, .ion-android-time:before, .ion-android-train:before, .ion-android-unlock:before, .ion-android-upload:before, .ion-android-volume-down:before, .ion-android-volume-mute:before, .ion-android-volume-off:before, .ion-android-volume-up:before, .ion-android-walk:before, .ion-android-warning:before, .ion-android-watch:before, .ion-android-wifi:before, .ion-aperture:before, .ion-archive:before, .ion-arrow-down-a:before, .ion-arrow-down-b:before, .ion-arrow-down-c:before, .ion-arrow-expand:before, .ion-arrow-graph-down-left:before, .ion-arrow-graph-down-right:before, .ion-arrow-graph-up-left:before, .ion-arrow-graph-up-right:before, .ion-arrow-left-a:before, .ion-arrow-left-b:before, .ion-arrow-left-c:before, .ion-arrow-move:before, .ion-arrow-resize:before, .ion-arrow-return-left:before, .ion-arrow-return-right:before, .ion-arrow-right-a:before, .ion-arrow-right-b:before, .ion-arrow-right-c:before, .ion-arrow-shrink:before, .ion-arrow-swap:before, .ion-arrow-up-a:before, .ion-arrow-up-b:before, .ion-arrow-up-c:before, .ion-asterisk:before, .ion-at:before, .ion-backspace:before, .ion-backspace-outline:before, .ion-bag:before, .ion-battery-charging:before, .ion-battery-empty:before, .ion-battery-full:before, .ion-battery-half:before, .ion-battery-low:before, .ion-beaker:before, .ion-beer:before, .ion-bluetooth:before, .ion-bonfire:before, .ion-bookmark:before, .ion-bowtie:before, .ion-briefcase:before, .ion-bug:before, .ion-calculator:before, .ion-calendar:before, .ion-camera:before, .ion-card:before, .ion-cash:before, .ion-chatbox:before, .ion-chatbox-working:before, .ion-chatboxes:before, .ion-chatbubble:before, .ion-chatbubble-working:before, .ion-chatbubbles:before, .ion-checkmark:before, .ion-checkmark-circled:before, .ion-checkmark-round:before, .icon-chevron-down:before, .icon-controls-left:before, .icon-controls-right:before, .icon-chevron-up:before, .ion-clipboard:before, .ion-clock:before, .ion-close:before, .ion-close-circled:before, .ion-close-round:before, .ion-closed-captioning:before, .ion-cloud:before, .ion-code:before, .ion-code-download:before, .ion-code-working:before, .ion-coffee:before, .ion-compass:before, .ion-compose:before, .icoDocuments-report:before, .ion-contrast:before, .ion-crop:before, .ion-cube:before, .ion-disc:before, .ion-document:before, .ion-document-text:before, .ion-drag:before, .ion-earth:before, .ion-easel:before, .icon-edit:before,.icon-misc-pen:before, .ion-egg:before, .ion-eject:before, .ion-email:before, .ion-email-unread:before, .ion-erlenmeyer-flask:before, .ion-erlenmeyer-flask-bubbles:before, .icon-overview:before, .ion-eye-disabled:before, .ion-female:before, .ion-filing:before, .ion-film-marker:before, .ion-fireball:before, .ion-flag:before, .ion-flame:before, .ion-flash:before, .ion-flash-off:before, .ion-folder:before, .ion-fork:before, .ion-fork-repo:before, .ion-forward:before, .ion-funnel:before, .icon-settings:before,.ion-gear-a:before, .ion-gear-b:before, .ion-grid:before, .ion-hammer:before, .ion-happy:before, .ion-happy-outline:before, .ion-headphone:before, .ion-heart:before, .ion-heart-broken:before, .ion-help:before, .ion-help-buoy:before, .ion-help-circled:before, .icon-building-home:before, .ion-icecream:before, .ion-image:before, .ion-images:before, .ion-information:before, .ion-information-circled:before, .ion-ionic:before, .ion-ios-alarm:before, .ion-ios-alarm-outline:before, .ion-ios-albums:before, .ion-ios-albums-outline:before, .ion-ios-americanfootball:before, .ion-ios-americanfootball-outline:before, .ion-ios-analytics:before, .ion-ios-analytics-outline:before, .ion-ios-arrow-back:before, .icon-controls-down:before, .ion-ios-arrow-forward:before, .ion-ios-arrow-left:before, .ion-ios-arrow-right:before, .ion-ios-arrow-thin-down:before, .ion-ios-arrow-thin-left:before, .ion-ios-arrow-thin-right:before, .ion-ios-arrow-thin-up:before, .icon-controls-up:before, .ion-ios-at:before, .ion-ios-at-outline:before, .ion-ios-barcode:before, .ion-ios-barcode-outline:before, .ion-ios-baseball:before, .ion-ios-baseball-outline:before, .ion-ios-basketball:before, .ion-ios-basketball-outline:before, .ion-ios-bell:before, .ion-ios-bell-outline:before, .ion-ios-body:before, .ion-ios-body-outline:before, .ion-ios-bolt:before, .ion-ios-bolt-outline:before, .icon-documents-book:before, .icoDocuments-book-outline:before, .icoDocuments-bookmarks:before, .icoDocuments-bookmarks-outline:before, .ion-ios-box:before, .ion-ios-box-outline:before, .ion-ios-briefcase:before, .ion-ios-briefcase-outline:before,.icon-add-widget:before , .ion-ios-browsers:before, .ion-ios-browsers-outline:before, .ion-ios-calculator:before, .ion-ios-calculator-outline:before, .ion-ios-calendar:before, .ion-ios-calendar-outline:before, .ion-ios-camera:before, .ion-ios-camera-outline:before, .ion-ios-cart:before, .ion-ios-cart-outline:before, .ion-ios-chatboxes:before, .ion-ios-chatboxes-outline:before, .ion-ios-chatbubble:before, .ion-ios-chatbubble-outline:before, .ion-ios-checkmark:before, .ion-ios-checkmark-empty:before, .ion-ios-checkmark-outline:before, .ion-ios-circle-filled:before, .ion-ios-circle-outline:before, .ion-ios-clock:before, .ion-ios-clock-outline:before, .ion-ios-close:before, .ion-ios-close-empty:before, .ion-ios-close-outline:before, .ion-ios-cloud:before, .ion-ios-cloud-download:before, .ion-ios-cloud-download-outline:before, .ion-ios-cloud-outline:before, .ion-ios-cloud-upload:before, .ion-ios-cloud-upload-outline:before, .ion-ios-cloudy:before, .ion-ios-cloudy-night:before, .ion-ios-cloudy-night-outline:before, .ion-ios-cloudy-outline:before, .ion-ios-cog:before, .ion-ios-cog-outline:before, .ion-ios-color-filter:before, .ion-ios-color-filter-outline:before, .ion-ios-color-wand:before, .ion-ios-color-wand-outline:before, .ion-ios-compose:before, .ion-ios-compose-outline:before, .ion-ios-contact:before, .ion-ios-contact-outline:before, .icon-documents-copy:before, .ion-ios-copy-outline:before, .ion-ios-crop:before, .ion-ios-crop-strong:before, .ion-ios-download:before, .ion-ios-download-outline:before, .ion-ios-drag:before, .ion-ios-email:before, .ion-ios-email-outline:before, .ion-ios-eye:before, .ion-ios-eye-outline:before, .ion-ios-fastforward:before, .ion-ios-fastforward-outline:before, .ion-ios-filing:before, .ion-ios-filing-outline:before, .ion-ios-film:before, .ion-ios-film-outline:before, .icon-content-flag:before, .ion-ios-flag-outline:before, .ion-ios-flame:before, .ion-ios-flame-outline:before, .ion-ios-flask:before, .ion-ios-flask-outline:before, .ion-ios-flower:before, .ion-ios-flower-outline:before, .ion-ios-folder:before, .ion-ios-folder-outline:before, .ion-ios-football:before, .ion-ios-football-outline:before, .ion-ios-game-controller-a:before, .ion-ios-game-controller-a-outline:before, .ion-ios-game-controller-b:before, .ion-ios-game-controller-b-outline:before, .ion-ios-gear:before, .ion-ios-gear-outline:before, .ion-ios-glasses:before, .ion-ios-glasses-outline:before, .ion-ios-grid-view:before, .ion-ios-grid-view-outline:before, .ion-ios-heart:before, .ion-ios-heart-outline:before, .ion-ios-help:before, .ion-ios-help-empty:before, .ion-ios-help-outline:before, .ion-ios-home:before, .ion-ios-home-outline:before, .ion-ios-infinite:before, .ion-ios-infinite-outline:before, .ion-ios-information:before, .ion-ios-information-empty:before, .ion-ios-information-outline:before, .ion-ios-ionic-outline:before, .ion-ios-keypad:before, .ion-ios-keypad-outline:before, .ion-ios-lightbulb:before, .ion-ios-lightbulb-outline:before, .ion-ios-list:before, .ion-ios-list-outline:before, .ion-ios-location:before, .ion-ios-location-outline:before, .ion-ios-locked:before, .ion-ios-locked-outline:before, .ion-ios-loop:before, .ion-ios-loop-strong:before, .ion-ios-medical:before, .ion-ios-medical-outline:before, .ion-ios-medkit:before, .ion-ios-medkit-outline:before, .ion-ios-mic:before, .ion-ios-mic-off:before, .ion-ios-mic-outline:before, .ion-ios-minus:before, .ion-ios-minus-empty:before, .icon-primary-accordion-minus:before, .ion-ios-monitor:before, .ion-ios-monitor-outline:before, .ion-ios-moon:before, .ion-ios-moon-outline:before, .ion-ios-more:before, .ion-ios-more-outline:before, .ion-ios-musical-note:before, .ion-ios-musical-notes:before, .ion-ios-navigate:before, .ion-ios-navigate-outline:before, .ion-ios-nutrition:before, .ion-ios-nutrition-outline:before, .ion-ios-paper:before, .ion-ios-paper-outline:before, .ion-ios-paperplane:before, .ion-ios-paperplane-outline:before, .ion-ios-partlysunny:before, .ion-ios-partlysunny-outline:before, .ion-ios-pause:before, .ion-ios-pause-outline:before, .ion-ios-paw:before, .ion-ios-paw-outline:before, .ion-ios-people:before, .ion-ios-people-outline:before, .ion-ios-person:before, .ion-ios-person-outline:before, .ion-ios-personadd:before, .ion-ios-personadd-outline:before, .ion-ios-photos:before, .ion-ios-photos-outline:before, .icon-misc-piechart:before, .icon-misc-piechart-outline:before, .ion-ios-pint:before, .ion-ios-pint-outline:before, .ion-ios-play:before, .ion-ios-play-outline:before, .ion-ios-plus:before, .ion-ios-plus-empty:before, .icon-primary-accordion-plus:before, .ion-ios-pricetag:before, .ion-ios-pricetag-outline:before, .ion-ios-pricetags:before, .ion-ios-pricetags-outline:before, .ion-ios-printer:before, .ion-ios-printer-outline:before, .ion-ios-pulse:before, .ion-ios-pulse-strong:before, .ion-ios-rainy:before, .ion-ios-rainy-outline:before, .ion-ios-recording:before, .ion-ios-recording-outline:before, .ion-ios-redo:before, .ion-ios-redo-outline:before, .ion-ios-refresh:before, .ion-ios-refresh-empty:before, .ion-ios-refresh-outline:before, .ion-ios-reload:before, .ion-ios-reverse-camera:before, .ion-ios-reverse-camera-outline:before, .ion-ios-rewind:before, .ion-ios-rewind-outline:before, .ion-ios-rose:before, .ion-ios-rose-outline:before, .ion-ios-search:before, .ion-ios-search-strong:before, .ion-ios-settings:before, .ion-ios-settings-strong:before, .ion-ios-shuffle:before, .ion-ios-shuffle-strong:before, .ion-ios-skipbackward:before, .ion-ios-skipbackward-outline:before, .ion-ios-skipforward:before, .ion-ios-skipforward-outline:before, .ion-ios-snowy:before, .ion-ios-speedometer:before, .ion-ios-speedometer-outline:before, .icon-star:before,.ion-ios-star:before, .ion-ios-star-half:before, .ion-ios-star-outline:before, .ion-ios-stopwatch:before, .ion-ios-stopwatch-outline:before, .ion-ios-sunny:before, .ion-ios-sunny-outline:before, .ion-ios-telephone:before, .ion-ios-telephone-outline:before, .ion-ios-tennisball:before, .ion-ios-tennisball-outline:before, .ion-ios-thunderstorm:before, .ion-ios-thunderstorm-outline:before, .ion-ios-time:before, .ion-ios-time-outline:before, .ion-ios-timer:before, .ion-ios-timer-outline:before, .ion-ios-toggle:before, .ion-ios-toggle-outline:before, .ion-ios-trash:before, .ion-ios-trash-outline:before, .ion-ios-undo:before, .ion-ios-undo-outline:before, .ion-ios-unlocked:before, .ion-ios-unlocked-outline:before, .ion-ios-upload:before, .ion-ios-upload-outline:before, .ion-ios-videocam:before, .ion-ios-videocam-outline:before, .ion-ios-volume-high:before, .ion-ios-volume-low:before, .ion-ios-wineglass:before, .ion-ios-wineglass-outline:before, .ion-ios-world:before, .ion-ios-world-outline:before, .ion-ipad:before, .ion-iphone:before, .ion-ipod:before, .ion-jet:before, .ion-key:before, .ion-knife:before, .ion-laptop:before, .ion-leaf:before, .ion-levels:before, .ion-lightbulb:before, .ion-link:before, .ion-load-a:before, .ion-load-b:before, .ion-load-c:before, .ion-load-d:before, .ion-location:before, .ion-lock-combination:before, .ion-locked:before, .ion-log-in:before, .icon-building-door:before, .ion-loop:before, .ion-magnet:before, .ion-male:before, .ion-man:before, .ion-map:before, .ion-medkit:before, .ion-merge:before, .ion-mic-a:before, .ion-mic-b:before, .ion-mic-c:before, .ion-minus:before, .ion-minus-circled:before, .ion-minus-round:before, .ion-model-s:before, .ion-monitor:before, .ion-more:before, .ion-mouse:before, .ion-music-note:before, .ion-navicon:before, .icon-content-gridguide:before, .ion-navigate:before, .ion-network:before, .ion-no-smoking:before, .ion-nuclear:before, .ion-outlet:before, .ion-paintbrush:before, .ion-paintbucket:before, .ion-paper-airplane:before, .ion-paperclip:before, .ion-pause:before, .icon-user:before, .icon-people-oneperson:before, .icon-people-oneperson-add:before, .icon-people-oneperson-stalker:before, .ion-pie-graph:before, .ion-pin:before, .ion-pinpoint:before, .ion-pizza:before, .ion-plane:before, .ion-planet:before, .icon-controls-pointer:before, .ion-playstation:before, .ion-plus:before, .ion-plus-circled:before, .ion-plus-round:before, .ion-podium:before, .ion-pound:before, .ion-power:before, .ion-pricetag:before, .ion-pricetags:before, .ion-printer:before, .ion-pull-request:before, .ion-qr-scanner:before, .ion-quote:before, .ion-radio-waves:before, .ion-record:before, .icon-arrows-replay-restart:before, .ion-reply:before, .ion-reply-all:before, .ion-ribbon-a:before, .ion-ribbon-b:before, .ion-sad:before, .ion-sad-outline:before, .ion-scissors:before, .ion-search:before, .ion-settings:before, .ion-share:before, .ion-shuffle:before, .ion-skip-backward:before, .ion-skip-forward:before, .ion-social-android:before, .ion-social-android-outline:before, .ion-social-angular:before, .ion-social-angular-outline:before, .ion-social-apple:before, .ion-social-apple-outline:before, .ion-social-bitcoin:before, .ion-social-bitcoin-outline:before, .ion-social-buffer:before, .ion-social-buffer-outline:before, .ion-social-chrome:before, .ion-social-chrome-outline:before, .ion-social-codepen:before, .ion-social-codepen-outline:before, .ion-social-css3:before, .ion-social-css3-outline:before, .ion-social-designernews:before, .ion-social-designernews-outline:before, .ion-social-dribbble:before, .ion-social-dribbble-outline:before, .ion-social-dropbox:before, .ion-social-dropbox-outline:before, .ion-social-euro:before, .ion-social-euro-outline:before, .ion-social-facebook:before, .ion-social-facebook-outline:before, .ion-social-foursquare:before, .ion-social-foursquare-outline:before, .ion-social-freebsd-devil:before, .ion-social-github:before, .ion-social-github-outline:before, .ion-social-google:before, .ion-social-google-outline:before, .ion-social-googleplus:before, .ion-social-googleplus-outline:before, .ion-social-hackernews:before, .ion-social-hackernews-outline:before, .ion-social-html5:before, .ion-social-html5-outline:before, .ion-social-instagram:before, .ion-social-instagram-outline:before, .ion-social-javascript:before, .ion-social-javascript-outline:before, .ion-social-linkedin:before, .ion-social-linkedin-outline:before, .ion-social-markdown:before, .ion-social-nodejs:before, .ion-social-octocat:before, .ion-social-pinterest:before, .ion-social-pinterest-outline:before, .ion-social-python:before, .ion-social-reddit:before, .ion-social-reddit-outline:before, .ion-social-rss:before, .ion-social-rss-outline:before, .ion-social-sass:before, .ion-social-skype:before, .ion-social-skype-outline:before, .ion-social-snapchat:before, .ion-social-snapchat-outline:before, .ion-social-tumblr:before, .ion-social-tumblr-outline:before, .ion-social-tux:before, .ion-social-twitch:before, .ion-social-twitch-outline:before, .ion-social-twitter:before, .ion-social-twitter-outline:before, .ion-social-usd:before, .ion-social-usd-outline:before, .ion-social-vimeo:before, .ion-social-vimeo-outline:before, .ion-social-whatsapp:before, .ion-social-whatsapp-outline:before, .ion-social-windows:before, .ion-social-windows-outline:before, .ion-social-wordpress:before, .ion-social-wordpress-outline:before, .ion-social-yahoo:before, .ion-social-yahoo-outline:before, .ion-social-yen:before, .ion-social-yen-outline:before, .ion-social-youtube:before, .ion-social-youtube-outline:before, .ion-soup-can:before, .ion-soup-can-outline:before, .ion-speakerphone:before, .ion-speedometer:before, .ion-spoon:before, .icon-content-star:before, .ion-stats-bars:before, .ion-steam:before, .ion-stop:before, .ion-thermometer:before, .ion-thumbsdown:before, .ion-thumbsup:before, .ion-toggle:before, .ion-toggle-filled:before, .ion-transgender:before, .icon-misc-trash:before, .ion-trash-b:before, .ion-trophy:before, .ion-tshirt:before, .ion-tshirt-outline:before, .ion-umbrella:before, .ion-university:before, .ion-unlocked:before, .icon-arrows-upload:before, .ion-usb:before, .ion-videocamera:before, .ion-volume-high:before, .ion-volume-low:before, .ion-volume-medium:before, .ion-volume-mute:before, .ion-wand:before, .ion-waterdrop:before, .ion-wifi:before, .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, .ion-xbox:before { display: inline-block; font-family: "Ionicons"; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; text-rendering: auto; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
+
+.ion-alert:before { content: "\f101"; }
+
+.icoSecurityalerts-alert:before { content: "\f100"; }
+
+.icon-controls-add-maximize:before { content: "\f2c7"; }
+
+.icon-controls-add-maximize-circle:before { content: "\f359"; }
+
+.icon-misc-time:before { content: "\f35a"; }
+
+.icoSecurityalerts:before { content: "\f35b"; }
+
+.icon-content-grid:before { content: "\f35c"; }
+
+.icon-documents-archive:before { content: "\f2c9"; }
+
+.ion-android-arrow-back:before { content: "\f2ca"; }
+
+.icon-arrows-vertical-arrow-down:before { content: "\f35d"; }
+
+.ion-android-arrow-dropdown:before { content: "\f35f"; }
+
+.icon-arrows-download:before { content: "\f35e"; }
+
+.ion-android-arrow-dropleft:before { content: "\f361"; }
+
+.icon-arrows-incoming-call:before { content: "\f360"; }
+
+.ion-android-arrow-dropright:before { content: "\f363"; }
+
+.icoArrows-outgoing-call:before { content: "\f362"; }
+
+.ion-android-arrow-dropup:before { content: "\f365"; }
+
+.icoArrows-upload:before { content: "\f364"; }
+
+.icoArrows-straight-arrow:before { content: "\f30f"; }
+
+.icon-arrows-vertical-arrow:before { content: "\f366"; }
+
+.ion-android-attach:before { content: "\f367"; }
+
+.ion-android-bar:before { content: "\f368"; }
+
+.ion-android-bicycle:before { content: "\f369"; }
+
+.ion-android-boat:before { content: "\f36a"; }
+
+.ion-android-bookmark:before { content: "\f36b"; }
+
+.ion-android-bulb:before { content: "\f36c"; }
+
+.ion-android-bus:before { content: "\f36d"; }
+
+.ion-android-calendar:before { content: "\f2d1"; }
+
+.ion-android-call:before { content: "\f2d2"; }
+
+.ion-android-camera:before { content: "\f2d3"; }
+
+.ion-android-cancel:before { content: "\f36e"; }
+
+.ion-android-car:before { content: "\f36f"; }
+
+.ion-android-cart:before { content: "\f370"; }
+
+.ion-android-chat:before { content: "\f2d4"; }
+
+.ion-android-checkbox:before { content: "\f374"; }
+
+.ion-android-checkbox-blank:before { content: "\f371"; }
+
+.ion-android-checkbox-outline:before { content: "\f373"; }
+
+.ion-android-checkbox-outline-blank:before { content: "\f372"; }
+
+.ion-android-checkmark-circle:before { content: "\f375"; }
+
+.ion-android-clipboard:before { content: "\f376"; }
+
+.ion-android-close:before { content: "\f2d7"; }
+
+.ion-android-cloud:before { content: "\f37a"; }
+
+.ion-android-cloud-circle:before { content: "\f377"; }
+
+.ion-android-cloud-done:before { content: "\f378"; }
+
+.ion-android-cloud-outline:before { content: "\f379"; }
+
+.ion-android-color-palette:before { content: "\f37b"; }
+
+.ion-android-compass:before { content: "\f37c"; }
+
+.ion-android-contact:before { content: "\f2d8"; }
+
+.ion-android-contacts:before { content: "\f2d9"; }
+
+.ion-android-contract:before { content: "\f37d"; }
+
+.ion-android-create:before { content: "\f37e"; }
+
+.ion-android-delete:before { content: "\f37f"; }
+
+.ion-android-desktop:before { content: "\f380"; }
+
+.ion-android-document:before { content: "\f381"; }
+
+.ion-android-done:before { content: "\f383"; }
+
+.ion-android-done-all:before { content: "\f382"; }
+
+.ion-android-download:before { content: "\f2dd"; }
+
+.ion-android-drafts:before { content: "\f384"; }
+
+.ion-android-exit:before { content: "\f385"; }
+
+.ion-android-expand:before { content: "\f386"; }
+
+.ion-android-favorite:before { content: "\f388"; }
+
+.ion-android-favorite-outline:before { content: "\f387"; }
+
+.ion-android-film:before { content: "\f389"; }
+
+.ion-android-folder:before { content: "\f2e0"; }
+
+.ion-android-folder-open:before { content: "\f38a"; }
+
+.ion-android-funnel:before { content: "\f38b"; }
+
+.ion-android-globe:before { content: "\f38c"; }
+
+.ion-android-hand:before { content: "\f2e3"; }
+
+.ion-android-hangout:before { content: "\f38d"; }
+
+.ion-android-happy:before { content: "\f38e"; }
+
+.ion-android-home:before { content: "\f38f"; }
+
+.ion-android-image:before { content: "\f2e4"; }
+
+.ion-android-laptop:before { content: "\f390"; }
+
+.ion-android-list:before { content: "\f391"; }
+
+.ion-android-locate:before { content: "\f2e9"; }
+
+.ion-android-lock:before { content: "\f392"; }
+
+.ion-android-mail:before { content: "\f2eb"; }
+
+.ion-android-map:before { content: "\f393"; }
+
+.ion-android-menu:before { content: "\f394"; }
+
+.ion-android-microphone:before { content: "\f2ec"; }
+
+.ion-android-microphone-off:before { content: "\f395"; }
+
+.ion-android-more-horizontal:before { content: "\f396"; }
+
+.ion-android-more-vertical:before { content: "\f397"; }
+
+.ion-android-navigate:before { content: "\f398"; }
+
+.ion-android-notifications:before { content: "\f39b"; }
+
+.ion-android-notifications-none:before { content: "\f399"; }
+
+.ion-android-notifications-off:before { content: "\f39a"; }
+
+.ion-android-open:before { content: "\f39c"; }
+
+.ion-android-options:before { content: "\f39d"; }
+
+.ion-android-people:before { content: "\f39e"; }
+
+.ion-android-person:before { content: "\f3a0"; }
+
+.icon-people-userbookmark:before { content: "\f39f"; }
+
+.ion-android-phone-landscape:before { content: "\f3a1"; }
+
+.ion-android-phone-portrait:before { content: "\f3a2"; }
+
+.ion-android-pin:before { content: "\f3a3"; }
+
+.ion-android-plane:before { content: "\f3a4"; }
+
+.ion-android-playstore:before { content: "\f2f0"; }
+
+.ion-android-print:before { content: "\f3a5"; }
+
+.ion-android-radio-button-off:before { content: "\f3a6"; }
+
+.ion-android-radio-button-on:before { content: "\f3a7"; }
+
+.ion-android-refresh:before { content: "\f3a8"; }
+
+.ion-android-remove:before { content: "\f2f4"; }
+
+.ion-android-remove-circle:before { content: "\f3a9"; }
+
+.ion-android-restaurant:before { content: "\f3aa"; }
+
+.ion-android-sad:before { content: "\f3ab"; }
+
+.ion-android-search:before { content: "\f2f5"; }
+
+.ion-android-send:before { content: "\f2f6"; }
+
+.ion-android-settings:before { content: "\f2f7"; }
+
+.ion-android-share:before { content: "\f2f8"; }
+
+.ion-android-share-alt:before { content: "\f3ac"; }
+
+.ion-android-star:before { content: "\f2fc"; }
+
+.ion-android-star-half:before { content: "\f3ad"; }
+
+.ion-android-star-outline:before { content: "\f3ae"; }
+
+.ion-android-stopwatch:before { content: "\f2fd"; }
+
+.ion-android-subway:before { content: "\f3af"; }
+
+.ion-android-sunny:before { content: "\f3b0"; }
+
+.ion-android-sync:before { content: "\f3b1"; }
+
+.ion-android-textsms:before { content: "\f3b2"; }
+
+.ion-android-time:before { content: "\f3b3"; }
+
+.ion-android-train:before { content: "\f3b4"; }
+
+.ion-android-unlock:before { content: "\f3b5"; }
+
+.ion-android-upload:before { content: "\f3b6"; }
+
+.ion-android-volume-down:before { content: "\f3b7"; }
+
+.ion-android-volume-mute:before { content: "\f3b8"; }
+
+.ion-android-volume-off:before { content: "\f3b9"; }
+
+.ion-android-volume-up:before { content: "\f3ba"; }
+
+.ion-android-walk:before { content: "\f3bb"; }
+
+.ion-android-warning:before { content: "\f3bc"; }
+
+.ion-android-watch:before { content: "\f3bd"; }
+
+.ion-android-wifi:before { content: "\f305"; }
+
+.ion-aperture:before { content: "\f313"; }
+
+.ion-archive:before { content: "\f102"; }
+
+.ion-arrow-down-a:before { content: "\f103"; }
+
+.ion-arrow-down-b:before { content: "\f104"; }
+
+.ion-arrow-down-c:before { content: "\f105"; }
+
+.ion-arrow-expand:before { content: "\f25e"; }
+
+.ion-arrow-graph-down-left:before { content: "\f25f"; }
+
+.ion-arrow-graph-down-right:before { content: "\f260"; }
+
+.ion-arrow-graph-up-left:before { content: "\f261"; }
+
+.ion-arrow-graph-up-right:before { content: "\f262"; }
+
+.ion-arrow-left-a:before { content: "\f106"; }
+
+.ion-arrow-left-b:before { content: "\f107"; }
+
+.ion-arrow-left-c:before { content: "\f108"; }
+
+.ion-arrow-move:before { content: "\f263"; }
+
+.ion-arrow-resize:before { content: "\f264"; }
+
+.ion-arrow-return-left:before { content: "\f265"; }
+
+.ion-arrow-return-right:before { content: "\f266"; }
+
+.ion-arrow-right-a:before { content: "\f109"; }
+
+.ion-arrow-right-b:before { content: "\f10a"; }
+
+.ion-arrow-right-c:before { content: "\f10b"; }
+
+.ion-arrow-shrink:before { content: "\f267"; }
+
+.ion-arrow-swap:before { content: "\f268"; }
+
+.ion-arrow-up-a:before { content: "\f10c"; }
+
+.ion-arrow-up-b:before { content: "\f10d"; }
+
+.ion-arrow-up-c:before { content: "\f10e"; }
+
+.ion-asterisk:before { content: "\f314"; }
+
+.ion-at:before { content: "\f10f"; }
+
+.ion-backspace:before { content: "\f3bf"; }
+
+.ion-backspace-outline:before { content: "\f3be"; }
+
+.ion-bag:before { content: "\f110"; }
+
+.ion-battery-charging:before { content: "\f111"; }
+
+.ion-battery-empty:before { content: "\f112"; }
+
+.ion-battery-full:before { content: "\f113"; }
+
+.ion-battery-half:before { content: "\f114"; }
+
+.ion-battery-low:before { content: "\f115"; }
+
+.ion-beaker:before { content: "\f269"; }
+
+.ion-beer:before { content: "\f26a"; }
+
+.ion-bluetooth:before { content: "\f116"; }
+
+.ion-bonfire:before { content: "\f315"; }
+
+.ion-bookmark:before { content: "\f26b"; }
+
+.ion-bowtie:before { content: "\f3c0"; }
+
+.ion-briefcase:before { content: "\f26c"; }
+
+.ion-bug:before { content: "\f2be"; }
+
+.ion-calculator:before { content: "\f26d"; }
+
+.ion-calendar:before { content: "\f117"; }
+
+.ion-camera:before { content: "\f118"; }
+
+.ion-card:before { content: "\f119"; }
+
+.ion-cash:before { content: "\f316"; }
+
+.ion-chatbox:before { content: "\f11b"; }
+
+.ion-chatbox-working:before { content: "\f11a"; }
+
+.ion-chatboxes:before { content: "\f11c"; }
+
+.ion-chatbubble:before { content: "\f11e"; }
+
+.ion-chatbubble-working:before { content: "\f11d"; }
+
+.ion-chatbubbles:before { content: "\f11f"; }
+
+.ion-checkmark:before { content: "\f122"; }
+
+.ion-checkmark-circled:before { content: "\f120"; }
+
+.ion-checkmark-round:before { content: "\f121"; }
+
+.icon-chevron-down:before { content: "\f123"; }
+
+
+.icon-controls-left:before { content: "\f124"; }
+
+.icon-controls-right:before { content: "\f125"; }
+
+.icon-chevron-up:before { content: "\f126"; }
+
+.ion-clipboard:before { content: "\f127"; }
+
+.ion-clock:before { content: "\f26e"; }
+
+.ion-close:before { content: "\f12a"; }
+
+.ion-close-circled:before { content: "\f128"; }
+
+.ion-close-round:before { content: "\f129"; }
+
+.ion-closed-captioning:before { content: "\f317"; }
+
+.ion-cloud:before { content: "\f12b"; }
+
+.ion-code:before { content: "\f271"; }
+
+.ion-code-download:before { content: "\f26f"; }
+
+.ion-code-working:before { content: "\f270"; }
+
+.ion-coffee:before { content: "\f272"; }
+
+.ion-compass:before { content: "\f273"; }
+
+.ion-compose:before { content: "\f12c"; }
+
+.icoDocuments-report:before { content: "\f274"; }
+
+.ion-contrast:before { content: "\f275"; }
+
+.ion-crop:before { content: "\f3c1"; }
+
+.ion-cube:before { content: "\f318"; }
+
+.ion-disc:before { content: "\f12d"; }
+
+.ion-document:before { content: "\f12f"; }
+
+.ion-document-text:before { content: "\f12e"; }
+
+.ion-drag:before { content: "\f130"; }
+
+.ion-earth:before { content: "\f276"; }
+
+.ion-easel:before { content: "\f3c2"; }
+
+.icon-misc-pen:before { content: "\f2bf"; }
+
+.ion-egg:before { content: "\f277"; }
+
+.ion-eject:before { content: "\f131"; }
+
+.ion-email:before { content: "\f132"; }
+
+.ion-email-unread:before { content: "\f3c3"; }
+
+.ion-erlenmeyer-flask:before { content: "\f3c5"; }
+
+.ion-erlenmeyer-flask-bubbles:before { content: "\f3c4"; }
+
+.icon-overview:before { content: "\f133"; }
+
+.ion-eye-disabled:before { content: "\f306"; }
+
+.ion-female:before { content: "\f278"; }
+
+.ion-filing:before { content: "\f134"; }
+
+.ion-film-marker:before { content: "\f135"; }
+
+.ion-fireball:before { content: "\f319"; }
+
+.ion-flag:before { content: "\f279"; }
+
+.ion-flame:before { content: "\f31a"; }
+
+.ion-flash:before { content: "\f137"; }
+
+.ion-flash-off:before { content: "\f136"; }
+
+.ion-folder:before { content: "\f139"; }
+
+.ion-fork:before { content: "\f27a"; }
+
+.ion-fork-repo:before { content: "\f2c0"; }
+
+.ion-forward:before { content: "\f13a"; }
+
+.ion-funnel:before { content: "\f31b"; }
+
+.ion-gear-a:before { content: "\f13d"; }
+
+.ion-gear-b:before { content: "\f13e"; }
+
+.ion-grid:before { content: "\f13f"; }
+
+.ion-hammer:before { content: "\f27b"; }
+
+.ion-happy:before { content: "\f31c"; }
+
+.ion-happy-outline:before { content: "\f3c6"; }
+
+.ion-headphone:before { content: "\f140"; }
+
+.ion-heart:before { content: "\f141"; }
+
+.ion-heart-broken:before { content: "\f31d"; }
+
+.ion-help:before { content: "\f143"; }
+
+.ion-help-buoy:before { content: "\f27c"; }
+
+.ion-help-circled:before { content: "\f142"; }
+
+.icon-building-home:before { content: "\f144"; }
+
+.ion-icecream:before { content: "\f27d"; }
+
+.ion-image:before { content: "\f147"; }
+
+.ion-images:before { content: "\f148"; }
+
+.ion-information:before { content: "\f14a"; }
+
+.ion-information-circled:before { content: "\f149"; }
+
+.ion-ionic:before { content: "\f14b"; }
+
+.ion-ios-alarm:before { content: "\f3c8"; }
+
+.ion-ios-alarm-outline:before { content: "\f3c7"; }
+
+.ion-ios-albums:before { content: "\f3ca"; }
+
+.ion-ios-albums-outline:before { content: "\f3c9"; }
+
+.ion-ios-americanfootball:before { content: "\f3cc"; }
+
+.ion-ios-americanfootball-outline:before { content: "\f3cb"; }
+
+.ion-ios-analytics:before { content: "\f3ce"; }
+
+.ion-ios-analytics-outline:before { content: "\f3cd"; }
+
+.ion-ios-arrow-back:before { content: "\f3cf"; }
+
+.icon-controls-down:before { content: "\f3d0"; }
+
+.ion-ios-arrow-forward:before { content: "\f3d1"; }
+
+.ion-ios-arrow-left:before { content: "\f3d2"; }
+
+.ion-ios-arrow-right:before { content: "\f3d3"; }
+
+.ion-ios-arrow-thin-down:before { content: "\f3d4"; }
+
+.ion-ios-arrow-thin-left:before { content: "\f3d5"; }
+
+.ion-ios-arrow-thin-right:before { content: "\f3d6"; }
+
+.ion-ios-arrow-thin-up:before { content: "\f3d7"; }
+
+.icon-controls-up:before { content: "\f3d8"; }
+
+.ion-ios-at:before { content: "\f3da"; }
+
+.ion-ios-at-outline:before { content: "\f3d9"; }
+
+.ion-ios-barcode:before { content: "\f3dc"; }
+
+.ion-ios-barcode-outline:before { content: "\f3db"; }
+
+.ion-ios-baseball:before { content: "\f3de"; }
+
+.ion-ios-baseball-outline:before { content: "\f3dd"; }
+
+.ion-ios-basketball:before { content: "\f3e0"; }
+
+.ion-ios-basketball-outline:before { content: "\f3df"; }
+
+.ion-ios-bell:before { content: "\f3e2"; }
+
+.ion-ios-bell-outline:before { content: "\f3e1"; }
+
+.ion-ios-body:before { content: "\f3e4"; }
+
+.ion-ios-body-outline:before { content: "\f3e3"; }
+
+.ion-ios-bolt:before { content: "\f3e6"; }
+
+.ion-ios-bolt-outline:before { content: "\f3e5"; }
+
+.icon-documents-book:before { content: "\f3e8"; }
+
+.icoDocuments-book-outline:before { content: "\f3e7"; }
+
+.icoDocuments-bookmarks:before { content: "\f3ea"; }
+
+.icoDocuments-bookmarks-outline:before { content: "\f3e9"; }
+
+.ion-ios-box:before { content: "\f3ec"; }
+
+.ion-ios-box-outline:before { content: "\f3eb"; }
+
+.ion-ios-briefcase:before { content: "\f3ee"; }
+
+.ion-ios-briefcase-outline:before { content: "\f3ed"; }
+
+.ion-ios-browsers:before { content: "\f3f0"; }
+
+.ion-ios-browsers-outline:before { content: "\f3ef"; }
+
+.ion-ios-calculator:before { content: "\f3f2"; }
+
+.ion-ios-calculator-outline:before { content: "\f3f1"; }
+
+.ion-ios-calendar:before { content: "\f3f4"; }
+
+.ion-ios-calendar-outline:before { content: "\f3f3"; }
+
+.ion-ios-camera:before { content: "\f3f6"; }
+
+.ion-ios-camera-outline:before { content: "\f3f5"; }
+
+.ion-ios-cart:before { content: "\f3f8"; }
+
+.ion-ios-cart-outline:before { content: "\f3f7"; }
+
+.ion-ios-chatboxes:before { content: "\f3fa"; }
+
+.ion-ios-chatboxes-outline:before { content: "\f3f9"; }
+
+.ion-ios-chatbubble:before { content: "\f3fc"; }
+
+.ion-ios-chatbubble-outline:before { content: "\f3fb"; }
+
+.ion-ios-checkmark:before { content: "\f3ff"; }
+
+.ion-ios-checkmark-empty:before { content: "\f3fd"; }
+
+.ion-ios-checkmark-outline:before { content: "\f3fe"; }
+
+.ion-ios-circle-filled:before { content: "\f400"; }
+
+.ion-ios-circle-outline:before { content: "\f401"; }
+
+.ion-ios-clock:before { content: "\f403"; }
+
+.ion-ios-clock-outline:before { content: "\f402"; }
+
+.ion-ios-close:before { content: "\f406"; }
+
+.ion-ios-close-empty:before { content: "\f404"; }
+
+.ion-ios-close-outline:before { content: "\f405"; }
+
+.ion-ios-cloud:before { content: "\f40c"; }
+
+.ion-ios-cloud-download:before { content: "\f408"; }
+
+.ion-ios-cloud-download-outline:before { content: "\f407"; }
+
+.ion-ios-cloud-outline:before { content: "\f409"; }
+
+.ion-ios-cloud-upload:before { content: "\f40b"; }
+
+.ion-ios-cloud-upload-outline:before { content: "\f40a"; }
+
+.ion-ios-cloudy:before { content: "\f410"; }
+
+.ion-ios-cloudy-night:before { content: "\f40e"; }
+
+.ion-ios-cloudy-night-outline:before { content: "\f40d"; }
+
+.ion-ios-cloudy-outline:before { content: "\f40f"; }
+
+.ion-ios-cog:before { content: "\f412"; }
+
+.ion-ios-cog-outline:before { content: "\f411"; }
+
+.ion-ios-color-filter:before { content: "\f414"; }
+
+.ion-ios-color-filter-outline:before { content: "\f413"; }
+
+.ion-ios-color-wand:before { content: "\f416"; }
+
+.ion-ios-color-wand-outline:before { content: "\f415"; }
+
+.ion-ios-compose:before { content: "\f418"; }
+
+.ion-ios-compose-outline:before { content: "\f417"; }
+
+.ion-ios-contact:before { content: "\f41a"; }
+
+.ion-ios-contact-outline:before { content: "\f419"; }
+
+.icon-documents-copy:before { content: "\f41c"; }
+
+.ion-ios-copy-outline:before { content: "\f41b"; }
+
+.ion-ios-crop:before { content: "\f41e"; }
+
+.ion-ios-crop-strong:before { content: "\f41d"; }
+
+.ion-ios-download:before { content: "\f420"; }
+
+.ion-ios-download-outline:before { content: "\f41f"; }
+
+.ion-ios-drag:before { content: "\f421"; }
+
+.ion-ios-email:before { content: "\f423"; }
+
+.ion-ios-email-outline:before { content: "\f422"; }
+
+.ion-ios-eye:before { content: "\f425"; }
+
+.ion-ios-eye-outline:before { content: "\f424"; }
+
+.ion-ios-fastforward:before { content: "\f427"; }
+
+.ion-ios-fastforward-outline:before { content: "\f426"; }
+
+.ion-ios-filing:before { content: "\f429"; }
+
+.ion-ios-filing-outline:before { content: "\f428"; }
+
+.ion-ios-film:before { content: "\f42b"; }
+
+.ion-ios-film-outline:before { content: "\f42a"; }
+
+.icon-content-flag:before { content: "\f42d"; }
+
+.ion-ios-flag-outline:before { content: "\f42c"; }
+
+.ion-ios-flame:before { content: "\f42f"; }
+
+.ion-ios-flame-outline:before { content: "\f42e"; }
+
+.ion-ios-flask:before { content: "\f431"; }
+
+.ion-ios-flask-outline:before { content: "\f430"; }
+
+.ion-ios-flower:before { content: "\f433"; }
+
+.ion-ios-flower-outline:before { content: "\f432"; }
+
+.ion-ios-folder:before { content: "\f435"; }
+
+.ion-ios-folder-outline:before { content: "\f434"; }
+
+.ion-ios-football:before { content: "\f437"; }
+
+.ion-ios-football-outline:before { content: "\f436"; }
+
+.ion-ios-game-controller-a:before { content: "\f439"; }
+
+.ion-ios-game-controller-a-outline:before { content: "\f438"; }
+
+.ion-ios-game-controller-b:before { content: "\f43b"; }
+
+.ion-ios-game-controller-b-outline:before { content: "\f43a"; }
+
+.ion-ios-gear:before { content: "\f43d"; }
+
+.ion-ios-gear-outline:before { content: "\f43c"; }
+
+.ion-ios-glasses:before { content: "\f43f"; }
+
+.ion-ios-glasses-outline:before { content: "\f43e"; }
+
+.ion-ios-grid-view:before { content: "\f441"; }
+
+.ion-ios-grid-view-outline:before { content: "\f440"; }
+
+.ion-ios-heart:before { content: "\f443"; }
+
+.ion-ios-heart-outline:before { content: "\f442"; }
+
+.ion-ios-help:before { content: "\f446"; }
+
+.ion-ios-help-empty:before { content: "\f444"; }
+
+.ion-ios-help-outline:before { content: "\f445"; }
+
+.ion-ios-home:before { content: "\f448"; }
+
+.ion-ios-home-outline:before { content: "\f447"; }
+
+.ion-ios-infinite:before { content: "\f44a"; }
+
+.ion-ios-infinite-outline:before { content: "\f449"; }
+
+.ion-ios-information:before { content: "\f44d"; }
+
+.ion-ios-information-empty:before { content: "\f44b"; }
+
+.ion-ios-information-outline:before { content: "\f44c"; }
+
+.ion-ios-ionic-outline:before { content: "\f44e"; }
+
+.ion-ios-keypad:before { content: "\f450"; }
+
+.ion-ios-keypad-outline:before { content: "\f44f"; }
+
+.ion-ios-lightbulb:before { content: "\f452"; }
+
+.ion-ios-lightbulb-outline:before { content: "\f451"; }
+
+.ion-ios-list:before { content: "\f454"; }
+
+.ion-ios-list-outline:before { content: "\f453"; }
+
+.ion-ios-location:before { content: "\f456"; }
+
+.ion-ios-location-outline:before { content: "\f455"; }
+
+.ion-ios-locked:before { content: "\f458"; }
+
+.ion-ios-locked-outline:before { content: "\f457"; }
+
+.ion-ios-loop:before { content: "\f45a"; }
+
+.ion-ios-loop-strong:before { content: "\f459"; }
+
+.ion-ios-medical:before { content: "\f45c"; }
+
+.ion-ios-medical-outline:before { content: "\f45b"; }
+
+.ion-ios-medkit:before { content: "\f45e"; }
+
+.ion-ios-medkit-outline:before { content: "\f45d"; }
+
+.ion-ios-mic:before { content: "\f461"; }
+
+.ion-ios-mic-off:before { content: "\f45f"; }
+
+.ion-ios-mic-outline:before { content: "\f460"; }
+
+.ion-ios-minus:before { content: "\f464"; }
+
+.ion-ios-minus-empty:before { content: "\f462"; }
+
+.icon-primary-accordion-minus:before { content: "\f463"; }
+
+.ion-ios-monitor:before { content: "\f466"; }
+
+.ion-ios-monitor-outline:before { content: "\f465"; }
+
+.ion-ios-moon:before { content: "\f468"; }
+
+.ion-ios-moon-outline:before { content: "\f467"; }
+
+.ion-ios-more:before { content: "\f46a"; }
+
+.ion-ios-more-outline:before { content: "\f469"; }
+
+.ion-ios-musical-note:before { content: "\f46b"; }
+
+.ion-ios-musical-notes:before { content: "\f46c"; }
+
+.ion-ios-navigate:before { content: "\f46e"; }
+
+.ion-ios-navigate-outline:before { content: "\f46d"; }
+
+.ion-ios-nutrition:before { content: "\f470"; }
+
+.ion-ios-nutrition-outline:before { content: "\f46f"; }
+
+.ion-ios-paper:before { content: "\f472"; }
+
+.ion-ios-paper-outline:before { content: "\f471"; }
+
+.ion-ios-paperplane:before { content: "\f474"; }
+
+.ion-ios-paperplane-outline:before { content: "\f473"; }
+
+.ion-ios-partlysunny:before { content: "\f476"; }
+
+.ion-ios-partlysunny-outline:before { content: "\f475"; }
+
+.ion-ios-pause:before { content: "\f478"; }
+
+.ion-ios-pause-outline:before { content: "\f477"; }
+
+.ion-ios-paw:before { content: "\f47a"; }
+
+.ion-ios-paw-outline:before { content: "\f479"; }
+
+.ion-ios-people:before { content: "\f47c"; }
+
+.ion-ios-people-outline:before { content: "\f47b"; }
+
+.ion-ios-person:before { content: "\f47e"; }
+
+.ion-ios-person-outline:before { content: "\f47d"; }
+
+.ion-ios-personadd:before { content: "\f480"; }
+
+.ion-ios-personadd-outline:before { content: "\f47f"; }
+
+.ion-ios-photos:before { content: "\f482"; }
+
+.ion-ios-photos-outline:before { content: "\f481"; }
+
+.icon-misc-piechart:before { content: "\f484"; }
+
+.icon-misc-piechart-outline:before { content: "\f483"; }
+
+.ion-ios-pint:before { content: "\f486"; }
+
+.ion-ios-pint-outline:before { content: "\f485"; }
+
+.ion-ios-play:before { content: "\f488"; }
+
+.ion-ios-play-outline:before { content: "\f487"; }
+
+.ion-ios-plus:before { content: "\f48b"; }
+
+.ion-ios-plus-empty:before { content: "\f489"; }
+
+.icon-primary-accordion-plus:before { content: "\f48a"; }
+
+.ion-ios-pricetag:before { content: "\f48d"; }
+
+.ion-ios-pricetag-outline:before { content: "\f48c"; }
+
+.ion-ios-pricetags:before { content: "\f48f"; }
+
+.ion-ios-pricetags-outline:before { content: "\f48e"; }
+
+.ion-ios-printer:before { content: "\f491"; }
+
+.ion-ios-printer-outline:before { content: "\f490"; }
+
+.ion-ios-pulse:before { content: "\f493"; }
+
+.ion-ios-pulse-strong:before { content: "\f492"; }
+
+.ion-ios-rainy:before { content: "\f495"; }
+
+.ion-ios-rainy-outline:before { content: "\f494"; }
+
+.ion-ios-recording:before { content: "\f497"; }
+
+.ion-ios-recording-outline:before { content: "\f496"; }
+
+.ion-ios-redo:before { content: "\f499"; }
+
+.ion-ios-redo-outline:before { content: "\f498"; }
+
+.ion-ios-refresh:before { content: "\f49c"; }
+
+.ion-ios-refresh-empty:before { content: "\f49a"; }
+
+.ion-ios-refresh-outline:before { content: "\f49b"; }
+
+.ion-ios-reload:before { content: "\f49d"; }
+
+.ion-ios-reverse-camera:before { content: "\f49f"; }
+
+.ion-ios-reverse-camera-outline:before { content: "\f49e"; }
+
+.ion-ios-rewind:before { content: "\f4a1"; }
+
+.ion-ios-rewind-outline:before { content: "\f4a0"; }
+
+.ion-ios-rose:before { content: "\f4a3"; }
+
+.ion-ios-rose-outline:before { content: "\f4a2"; }
+
+.ion-ios-search:before { content: "\f4a5"; }
+
+.ion-ios-search-strong:before { content: "\f4a4"; }
+
+.ion-ios-settings:before { content: "\f4a7"; }
+
+.ion-ios-settings-strong:before { content: "\f4a6"; }
+
+.ion-ios-shuffle:before { content: "\f4a9"; }
+
+.ion-ios-shuffle-strong:before { content: "\f4a8"; }
+
+.ion-ios-skipbackward:before { content: "\f4ab"; }
+
+.ion-ios-skipbackward-outline:before { content: "\f4aa"; }
+
+.ion-ios-skipforward:before { content: "\f4ad"; }
+
+.ion-ios-skipforward-outline:before { content: "\f4ac"; }
+
+.ion-ios-snowy:before { content: "\f4ae"; }
+
+.ion-ios-speedometer:before { content: "\f4b0"; }
+
+.ion-ios-speedometer-outline:before { content: "\f4af"; }
+
+.ion-ios-star:before { content: "\f4b3"; }
+
+.ion-ios-star-half:before { content: "\f4b1"; }
+
+.ion-ios-star-outline:before { content: "\f4b2"; }
+
+.ion-ios-stopwatch:before { content: "\f4b5"; }
+
+.ion-ios-stopwatch-outline:before { content: "\f4b4"; }
+
+.ion-ios-sunny:before { content: "\f4b7"; }
+
+.ion-ios-sunny-outline:before { content: "\f4b6"; }
+
+.ion-ios-telephone:before { content: "\f4b9"; }
+
+.ion-ios-telephone-outline:before { content: "\f4b8"; }
+
+.ion-ios-tennisball:before { content: "\f4bb"; }
+
+.ion-ios-tennisball-outline:before { content: "\f4ba"; }
+
+.ion-ios-thunderstorm:before { content: "\f4bd"; }
+
+.ion-ios-thunderstorm-outline:before { content: "\f4bc"; }
+
+.ion-ios-time:before { content: "\f4bf"; }
+
+.ion-ios-time-outline:before { content: "\f4be"; }
+
+.ion-ios-timer:before { content: "\f4c1"; }
+
+.ion-ios-timer-outline:before { content: "\f4c0"; }
+
+.ion-ios-toggle:before { content: "\f4c3"; }
+
+.ion-ios-toggle-outline:before { content: "\f4c2"; }
+
+.ion-ios-trash:before { content: "\f4c5"; }
+
+.ion-ios-trash-outline:before { content: "\f4c4"; }
+
+.ion-ios-undo:before { content: "\f4c7"; }
+
+.ion-ios-undo-outline:before { content: "\f4c6"; }
+
+.ion-ios-unlocked:before { content: "\f4c9"; }
+
+.ion-ios-unlocked-outline:before { content: "\f4c8"; }
+
+.ion-ios-upload:before { content: "\f4cb"; }
+
+.ion-ios-upload-outline:before { content: "\f4ca"; }
+
+.ion-ios-videocam:before { content: "\f4cd"; }
+
+.ion-ios-videocam-outline:before { content: "\f4cc"; }
+
+.ion-ios-volume-high:before { content: "\f4ce"; }
+
+.ion-ios-volume-low:before { content: "\f4cf"; }
+
+.ion-ios-wineglass:before { content: "\f4d1"; }
+
+.ion-ios-wineglass-outline:before { content: "\f4d0"; }
+
+.ion-ios-world:before { content: "\f4d3"; }
+
+.ion-ios-world-outline:before { content: "\f4d2"; }
+
+.ion-ipad:before { content: "\f1f9"; }
+
+.ion-iphone:before { content: "\f1fa"; }
+
+.ion-ipod:before { content: "\f1fb"; }
+
+.ion-jet:before { content: "\f295"; }
+
+.ion-key:before { content: "\f296"; }
+
+.ion-knife:before { content: "\f297"; }
+
+.ion-laptop:before { content: "\f1fc"; }
+
+.ion-leaf:before { content: "\f1fd"; }
+
+.ion-levels:before { content: "\f298"; }
+
+.ion-lightbulb:before { content: "\f299"; }
+
+.ion-link:before { content: "\f1fe"; }
+
+.ion-load-a:before { content: "\f29a"; }
+
+.ion-load-b:before { content: "\f29b"; }
+
+.ion-load-c:before { content: "\f29c"; }
+
+.ion-load-d:before { content: "\f29d"; }
+
+.ion-location:before { content: "\f1ff"; }
+
+.ion-lock-combination:before { content: "\f4d4"; }
+
+.ion-locked:before { content: "\f200"; }
+
+.ion-log-in:before { content: "\f29e"; }
+
+.icon-building-door:before { content: "\f29f"; }
+
+.ion-loop:before { content: "\f201"; }
+
+.ion-magnet:before { content: "\f2a0"; }
+
+.ion-male:before { content: "\f2a1"; }
+
+.ion-man:before { content: "\f202"; }
+
+.ion-map:before { content: "\f203"; }
+
+.ion-medkit:before { content: "\f2a2"; }
+
+.ion-merge:before { content: "\f33f"; }
+
+.ion-mic-a:before { content: "\f204"; }
+
+.ion-mic-b:before { content: "\f205"; }
+
+.ion-mic-c:before { content: "\f206"; }
+
+.ion-minus:before { content: "\f209"; }
+
+.ion-minus-circled:before { content: "\f207"; }
+
+.ion-minus-round:before { content: "\f208"; }
+
+.ion-model-s:before { content: "\f2c1"; }
+
+.ion-monitor:before { content: "\f20a"; }
+
+.ion-more:before { content: "\f20b"; }
+
+.ion-mouse:before { content: "\f340"; }
+
+.ion-music-note:before { content: "\f20c"; }
+
+.ion-navicon:before { content: "\f20e"; }
+
+.icon-content-gridguide:before { content: "\f20d"; }
+
+.ion-navigate:before { content: "\f2a3"; }
+
+.ion-network:before { content: "\f341"; }
+
+.ion-no-smoking:before { content: "\f2c2"; }
+
+.ion-nuclear:before { content: "\f2a4"; }
+
+.ion-outlet:before { content: "\f342"; }
+
+.ion-paintbrush:before { content: "\f4d5"; }
+
+.ion-paintbucket:before { content: "\f4d6"; }
+
+.ion-paper-airplane:before { content: "\f2c3"; }
+
+.ion-paperclip:before { content: "\f20f"; }
+
+.ion-pause:before { content: "\f210"; }
+
+.icon-people-oneperson:before { content: "\f213"; }
+
+.icon-people-oneperson-add:before { content: "\f211"; }
+
+.icon-people-oneperson-stalker:before { content: "\f212"; }
+
+.ion-pie-graph:before { content: "\f2a5"; }
+
+.ion-pin:before { content: "\f2a6"; }
+
+.ion-pinpoint:before { content: "\f2a7"; }
+
+.ion-pizza:before { content: "\f2a8"; }
+
+.ion-plane:before { content: "\f214"; }
+
+.ion-planet:before { content: "\f343"; }
+
+.icon-controls-pointer:before { content: "\f215"; }
+
+.ion-playstation:before { content: "\f30a"; }
+
+.ion-plus:before { content: "\f218"; }
+
+.ion-plus-circled:before { content: "\f216"; }
+
+.ion-plus-round:before { content: "\f217"; }
+
+.ion-podium:before { content: "\f344"; }
+
+.ion-pound:before { content: "\f219"; }
+
+.ion-power:before { content: "\f2a9"; }
+
+.ion-pricetag:before { content: "\f2aa"; }
+
+.ion-pricetags:before { content: "\f2ab"; }
+
+.ion-printer:before { content: "\f21a"; }
+
+.ion-pull-request:before { content: "\f345"; }
+
+.ion-qr-scanner:before { content: "\f346"; }
+
+.ion-quote:before { content: "\f347"; }
+
+.ion-radio-waves:before { content: "\f2ac"; }
+
+.ion-record:before { content: "\f21b"; }
+
+.icon-arrows-replay-restart:before { content: "\f21c"; }
+
+.ion-reply:before { content: "\f21e"; }
+
+.ion-reply-all:before { content: "\f21d"; }
+
+.ion-ribbon-a:before { content: "\f348"; }
+
+.ion-ribbon-b:before { content: "\f349"; }
+
+.ion-sad:before { content: "\f34a"; }
+
+.ion-sad-outline:before { content: "\f4d7"; }
+
+.ion-scissors:before { content: "\f34b"; }
+
+.ion-search:before { content: "\f21f"; }
+
+.ion-settings:before { content: "\f2ad"; }
+
+.ion-share:before { content: "\f220"; }
+
+.ion-shuffle:before { content: "\f221"; }
+
+.ion-skip-backward:before { content: "\f222"; }
+
+.ion-skip-forward:before { content: "\f223"; }
+
+.ion-social-android:before { content: "\f225"; }
+
+.ion-social-android-outline:before { content: "\f224"; }
+
+.ion-social-angular:before { content: "\f4d9"; }
+
+.ion-social-angular-outline:before { content: "\f4d8"; }
+
+.ion-social-apple:before { content: "\f227"; }
+
+.ion-social-apple-outline:before { content: "\f226"; }
+
+.ion-social-bitcoin:before { content: "\f2af"; }
+
+.ion-social-bitcoin-outline:before { content: "\f2ae"; }
+
+.ion-social-buffer:before { content: "\f229"; }
+
+.ion-social-buffer-outline:before { content: "\f228"; }
+
+.ion-social-chrome:before { content: "\f4db"; }
+
+.ion-social-chrome-outline:before { content: "\f4da"; }
+
+.ion-social-codepen:before { content: "\f4dd"; }
+
+.ion-social-codepen-outline:before { content: "\f4dc"; }
+
+.ion-social-css3:before { content: "\f4df"; }
+
+.ion-social-css3-outline:before { content: "\f4de"; }
+
+.ion-social-designernews:before { content: "\f22b"; }
+
+.ion-social-designernews-outline:before { content: "\f22a"; }
+
+.ion-social-dribbble:before { content: "\f22d"; }
+
+.ion-social-dribbble-outline:before { content: "\f22c"; }
+
+.ion-social-dropbox:before { content: "\f22f"; }
+
+.ion-social-dropbox-outline:before { content: "\f22e"; }
+
+.ion-social-euro:before { content: "\f4e1"; }
+
+.ion-social-euro-outline:before { content: "\f4e0"; }
+
+.ion-social-facebook:before { content: "\f231"; }
+
+.ion-social-facebook-outline:before { content: "\f230"; }
+
+.ion-social-foursquare:before { content: "\f34d"; }
+
+.ion-social-foursquare-outline:before { content: "\f34c"; }
+
+.ion-social-freebsd-devil:before { content: "\f2c4"; }
+
+.ion-social-github:before { content: "\f233"; }
+
+.ion-social-github-outline:before { content: "\f232"; }
+
+.ion-social-google:before { content: "\f34f"; }
+
+.ion-social-google-outline:before { content: "\f34e"; }
+
+.ion-social-googleplus:before { content: "\f235"; }
+
+.ion-social-googleplus-outline:before { content: "\f234"; }
+
+.ion-social-hackernews:before { content: "\f237"; }
+
+.ion-social-hackernews-outline:before { content: "\f236"; }
+
+.ion-social-html5:before { content: "\f4e3"; }
+
+.ion-social-html5-outline:before { content: "\f4e2"; }
+
+.ion-social-instagram:before { content: "\f351"; }
+
+.ion-social-instagram-outline:before { content: "\f350"; }
+
+.ion-social-javascript:before { content: "\f4e5"; }
+
+.ion-social-javascript-outline:before { content: "\f4e4"; }
+
+.ion-social-linkedin:before { content: "\f239"; }
+
+.ion-social-linkedin-outline:before { content: "\f238"; }
+
+.ion-social-markdown:before { content: "\f4e6"; }
+
+.ion-social-nodejs:before { content: "\f4e7"; }
+
+.ion-social-octocat:before { content: "\f4e8"; }
+
+.ion-social-pinterest:before { content: "\f2b1"; }
+
+.ion-social-pinterest-outline:before { content: "\f2b0"; }
+
+.ion-social-python:before { content: "\f4e9"; }
+
+.ion-social-reddit:before { content: "\f23b"; }
+
+.ion-social-reddit-outline:before { content: "\f23a"; }
+
+.ion-social-rss:before { content: "\f23d"; }
+
+.ion-social-rss-outline:before { content: "\f23c"; }
+
+.ion-social-sass:before { content: "\f4ea"; }
+
+.ion-social-skype:before { content: "\f23f"; }
+
+.ion-social-skype-outline:before { content: "\f23e"; }
+
+.ion-social-snapchat:before { content: "\f4ec"; }
+
+.ion-social-snapchat-outline:before { content: "\f4eb"; }
+
+.ion-social-tumblr:before { content: "\f241"; }
+
+.ion-social-tumblr-outline:before { content: "\f240"; }
+
+.ion-social-tux:before { content: "\f2c5"; }
+
+.ion-social-twitch:before { content: "\f4ee"; }
+
+.ion-social-twitch-outline:before { content: "\f4ed"; }
+
+.ion-social-twitter:before { content: "\f243"; }
+
+.ion-social-twitter-outline:before { content: "\f242"; }
+
+.ion-social-usd:before { content: "\f353"; }
+
+.ion-social-usd-outline:before { content: "\f352"; }
+
+.ion-social-vimeo:before { content: "\f245"; }
+
+.ion-social-vimeo-outline:before { content: "\f244"; }
+
+.ion-social-whatsapp:before { content: "\f4f0"; }
+
+.ion-social-whatsapp-outline:before { content: "\f4ef"; }
+
+.ion-social-windows:before { content: "\f247"; }
+
+.ion-social-windows-outline:before { content: "\f246"; }
+
+.ion-social-wordpress:before { content: "\f249"; }
+
+.ion-social-wordpress-outline:before { content: "\f248"; }
+
+.ion-social-yahoo:before { content: "\f24b"; }
+
+.ion-social-yahoo-outline:before { content: "\f24a"; }
+
+.ion-social-yen:before { content: "\f4f2"; }
+
+.ion-social-yen-outline:before { content: "\f4f1"; }
+
+.ion-social-youtube:before { content: "\f24d"; }
+
+.ion-social-youtube-outline:before { content: "\f24c"; }
+
+.ion-soup-can:before { content: "\f4f4"; }
+
+.ion-soup-can-outline:before { content: "\f4f3"; }
+
+.ion-speakerphone:before { content: "\f2b2"; }
+
+.ion-speedometer:before { content: "\f2b3"; }
+
+.ion-spoon:before { content: "\f2b4"; }
+
+.icon-content-star:before { content: "\f24e"; }
+
+.ion-stats-bars:before { content: "\f2b5"; }
+
+.ion-steam:before { content: "\f30b"; }
+
+.ion-stop:before { content: "\f24f"; }
+
+.ion-thermometer:before { content: "\f2b6"; }
+
+.ion-thumbsdown:before { content: "\f250"; }
+
+.ion-thumbsup:before { content: "\f251"; }
+
+.ion-toggle:before { content: "\f355"; }
+
+.ion-toggle-filled:before { content: "\f354"; }
+
+.ion-transgender:before { content: "\f4f5"; }
+
+.icon-misc-trash:before { content: "\f252"; }
+
+.ion-trash-b:before { content: "\f253"; }
+
+.ion-trophy:before { content: "\f356"; }
+
+.ion-tshirt:before { content: "\f4f7"; }
+
+.ion-tshirt-outline:before { content: "\f4f6"; }
+
+.ion-umbrella:before { content: "\f2b7"; }
+
+.ion-university:before { content: "\f357"; }
+
+.ion-unlocked:before { content: "\f254"; }
+
+.icon-arrows-upload:before { content: "\f255"; }
+
+.ion-usb:before { content: "\f2b8"; }
+
+.ion-videocamera:before { content: "\f256"; }
+
+.ion-volume-high:before { content: "\f257"; }
+
+.ion-volume-low:before { content: "\f258"; }
+
+.ion-volume-medium:before { content: "\f259"; }
+
+.ion-volume-mute:before { content: "\f25a"; }
+
+.ion-wand:before { content: "\f358"; }
+
+.ion-waterdrop:before { content: "\f25b"; }
+
+.ion-wifi:before { content: "\f25c"; }
+
+.ion-wineglass:before { content: "\f2b9"; }
+
+.ion-woman:before { content: "\f25d"; }
+
+.ion-wrench:before { content: "\f2ba"; }
+
+.ion-xbox:before { content: "\f30c"; }
+
+.icon-user:before { content: "\f213"; }
+
+.icon-star:before { content: "\f4b3"; }
+
+.icon-edit:before { content: "\f2bf"; }
+
+.icon-settings:before { content: "\f13d"; }
+
+.icon-apps-marketplace:before { content: "\f35c"; }
+
+.icon-add-widget:before { content: "\f3f0"; } \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.eot b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.eot
index 92a3f20a..92a3f20a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.eot
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.eot
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.svg b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.svg
index 49fc8f36..49fc8f36 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.svg
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.svg
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.ttf b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.ttf
index c4e46324..c4e46324 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.ttf
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.ttf
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.woff b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.woff
index 5f3a14e0..5f3a14e0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/fonts/ionicons.woff
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/fonts/ionicons.woff
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/ds-profile/post-controller.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/ds-profile/post-controller.js
new file mode 100644
index 00000000..b9de4be8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/ds-profile/post-controller.js
@@ -0,0 +1,3 @@
+appDS2.controller('postController', function($scope, $http, $modal, $routeParams, $rootScope,PostService){
+
+});
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/samplePage-route.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/samplePage-route.js
new file mode 100644
index 00000000..b2042b85
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-controllers/samplePage-route.js
@@ -0,0 +1,19 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/collaborate_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html',
+ controller: 'collaborateListControllerDS2'
+ })
+ .when('/drools/:filename', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/drools.html',
+ controller: 'droolsController'
+ })
+ .when('/droolsList', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/drools-list.html',
+ controller: 'droolsListController'
+ })
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/net_map.html',
+ controller : 'netMapController'
+ });
+});
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-services/postSearch.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-services/postSearch.js
new file mode 100644
index 00000000..cf225def
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-services/postSearch.js
@@ -0,0 +1,5 @@
+appDS2.factory('PostService', function ($http, $q) {
+ return {
+
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/post.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/post.html
new file mode 100644
index 00000000..43bec521
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/post.html
@@ -0,0 +1,3 @@
+<div id="page-content">
+ <h1 class="heading-page" id="profileSearch">User Search</h1>
+</div>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html
new file mode 100644
index 00000000..36b8c2a4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html
@@ -0,0 +1,59 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="profileSearch">Profile Search</h1>
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img"
+ aria-label="Please wait while we load your content"></i>
+ </div>
+
+ <div ng-hide="showLoader">
+ <table class="striped" table-data="tableData">
+ <thead>
+ <tr>
+ <th>User ID</th>
+ <th>Last Name</th>
+ <th>First Name</th>
+ <th>Email</th>
+ <th>User ID</th>
+ <th>Manager User ID</th>
+ <th>Edit</th>
+ <th>Active?</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="rowData in tableData">
+ <tr>
+ <td>{{rowData.id}}</td>
+ <td>{{rowData.lastName}}</td>
+ <td>{{rowData.firstName}}</td>
+ <td>{{rowData.email}}</td>
+ <td>{{rowData.orgUserId}}</td>
+ <td>{{rowData.orgManagerUserId}}</td>
+ <!-- Include an edit image with respective redirection -->
+ <td><a href="#/profile/{{rowData.id}}" class="icon-misc-pen"
+ style="color: #888; font-size: 20px;"></a></td>
+ <td>
+ <div class="form-row">
+ <label class="btn-switch-label" tabindex="0" role="option">
+ <input type="checkbox" b2b-switches ng-model="rowData.active"
+ ng-disabled="allDisabled" aria-disabled="{{allDisabled}}">
+ <div class="sr-text hidden-spoken" ng-if="!allDisabled">Double
+ tap to turn</div>
+ </label>
+ </div>
+ </td>
+
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="well" style="padding-bottom: 35px;">
+ <div class="row -page short">
+ <div b2b-pagination="" total-pages="totalPages1"
+ current-page="currentPage1" click-handler="customHandler"
+ role="navigation" aria-label="Customer Data Pages"></div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html
new file mode 100644
index 00000000..3b5ef525
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html
@@ -0,0 +1,189 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="profileSearch">{{pageTitle}}</h1>
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img" aria-label="Please wait while we load your content"></i>
+ </div>
+ <div ng-hide="showLoader" >
+ <h3 class="heading-small">Please edit the profile details below:</h3>
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-2a">*First Name</label>
+ <div class="field-group">
+ <input id="textinputID-2a" b2b-reset="" class="span12" type="text" data-ng-model="profile.lastName">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">*Last Name</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.firstName">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Organization User ID</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.orgUserId" disabled="true">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Organization Manager ID</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.orgManagerUserId" disabled="true">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-2a">Login Id</label>
+ <div class="field-group">
+ <input id="textinputID-2a" b2b-reset="" class="span12" type="text" data-ng-model="profile.loginId" disabled="true">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Password</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.loginPwd" disabled="true">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">*Phone</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.phone">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Fax</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.fax">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-2a">Cellular</label>
+ <div class="field-group">
+ <input id="textinputID-2a" b2b-reset="" class="span12" type="text" data-ng-model="profile.cellular">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">*Email</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.email">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Address 1</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.address1">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Address 2</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.address2">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-2a">City</label>
+ <div class="field-group">
+ <input id="textinputID-2a" b2b-reset="" class="span12" type="text" data-ng-model="profile.city">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">State</label>
+ <select name="dropdown1" b2b-dropdown ng-model="stateList.selected.value">
+ <option b2b-dropdown-list option-repeat="d in stateList.options" value="{{d.value}}" init-value="{{stateList.selected.title}}">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Zip Code</label>
+ <div class="field-group">
+ <input id="textinputID-3a" b2b-reset="" class="span12" type="text" data-ng-model="profile.zipCode">
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">Country</label>
+ <select name="dropdown1" b2b-dropdown ng-model="selectedCountry.value">
+ <option b2b-dropdown-list option-repeat="d in countries" value="{{d.value}}" init-value="{{selectedCountry.title}}">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="span3">
+ <div class="form-row">
+ <label for="textinputID-3a">Time Zone</label>
+ <select name="dropdown1" b2b-dropdown ng-model="selectedTimeZone.value">
+ <option b2b-dropdown-list option-repeat="d in timeZones" value="{{d.value}}" init-value="{{selectedTimeZone.title}}">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+
+ <div>
+ <button class="btn btn-alt btn-small" type="button" ng-click="saveProfile()">Save</button>
+ </div>
+ <br>
+ <div>
+ Role
+ <a ng-click="addNewRoleFunctionModalPopup(role.roleFunctions,role.name, role);" class="icon-primary-accordion-plus" size="small"></a>
+ </div>
+
+ <div id="rolesTable" title="Role Functions">
+ <table class="striped" table-data="profile.roles">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Delete</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="rowData in profile.roles">
+ <tr>
+ <td ng-bind="rowData['name']"></td>
+
+ <td>
+ <div style="font-size: 20px;">
+ <a href="javascript:void(0)" ng-click="removeRole(rowData);" class="icon-misc-trash"></a>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/samplePage.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/samplePage.html
new file mode 100644
index 00000000..06d62f67
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/samplePage.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App demonstration pages using DS2 look and feel -->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+ <title>Sample Page</title>
+
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src="app/fusion/external/utils/js/browserCheck.js"></script>
+
+ <!-- Page-specific items -->
+ <script src="app/fusion/scripts/DS2-services/adminService.js"></script>
+ <script src="app/fusion/scripts/DS2-services/adminMenuService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-controllers/samplePage-route.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/collaborateList-route.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/collaborate-list-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-services/ds2-sample-page/droolsService.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/drools-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/notebook-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js"></script>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/footer.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/footer.html
new file mode 100644
index 00000000..f4d8d7ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/DS2-view-models/footer.html
@@ -0,0 +1,13 @@
+<div style="width: 100%">
+ <footer class="b2b-footer-wrapper" role="contentinfo" aria-label="footer">
+ <div class="b2b-footer-container" >
+ <div class="divider-bottom-footer">
+ <div class="span12 footerLogo">
+ <p class="copyright-text">
+ Copyright 2017 Open ECOMP and Linux Foundation. <span class="build_number">Build Number: {{build_number}}</span>
+ </p>
+ </div>
+ </div>
+ </div>
+ </footer>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/utils/page-resource-ds2.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/utils/page-resource-ds2.js
new file mode 100644
index 00000000..d0af6cbc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/utils/page-resource-ds2.js
@@ -0,0 +1,97 @@
+function loadjscssfile(filename, filetype){
+ if (filetype=="js"){ //if filename is a external JavaScript file
+ var done = false;
+ var script = document.createElement('script');
+ script.src = filename;
+ script.async = false;
+ document.head.appendChild(script);
+ }else if (filetype=="css"){ //if filename is an external CSS file
+ var fileref=document.createElement("link")
+ fileref.setAttribute("rel", "stylesheet")
+ fileref.setAttribute("type", "text/css")
+ fileref.setAttribute("async", false)
+ fileref.setAttribute("href", filename)
+ document.head.appendChild(fileref);
+ }
+}
+
+function loadResource(){
+ /*********************AngularJs***************************/
+ loadjscssfile("./app/fusion/external/angular-1.5/angular.min.js", "js");
+ loadjscssfile("./app/fusion/external/angular-1.5/angular-messages.js", "js");
+ loadjscssfile("./app/fusion/external/angular-1.5/angular-touch.js", "js");
+ loadjscssfile("./app/fusion/external/angular-1.5/angular-sanitize.min.js", "js");
+ loadjscssfile("./app/fusion/external/angular-1.5/angular-route.min.js", "js");
+ loadjscssfile("./app/fusion/external/angular-1.5/angular-cookies.min.js", "js");
+
+ loadjscssfile("./app/fusion/external/ds2/js/b2b-angular/b2b-library.min.js", "js");
+/* loadjscssfile("./app/fusion/external/ds2/js/digital-ng-library/digital.ng.library.min.js", "js");
+*/
+ loadjscssfile("./app/fusion/external/jquery/dist/jquery.min.js", "js");
+
+ /*********************Angular Gridster***************************/
+ loadjscssfile("./app/fusion/external/angular-gridster/dist/angular-gridster.min.css", "css");
+ loadjscssfile("./app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css", "css");
+ loadjscssfile("./app/fusion/external/javascript-detect-element-resize/jquery.resize.js", "js");
+ loadjscssfile("./app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js", "js");
+ loadjscssfile("./app/fusion/external/angular-gridster/dist/angular-gridster.min.js", "js");
+
+ /*********************Angular UI grid***************************/
+ loadjscssfile("./app/fusion/external/angular-ui-grid/ui-grid.js", "js");
+ loadjscssfile("./app/fusion/external/angular-ui-grid/ui-grid.css", "css");
+
+ loadjscssfile("./app/fusion/external/ds2/js/appDS2.js", "js");
+
+ loadjscssfile("./app/fusion/scripts/DS2-services/headerServiceDS2.js", "js");
+ loadjscssfile("./app/fusion/scripts/DS2-services/leftMenuServiceDS2.js", "js");
+ loadjscssfile("./app/fusion/scripts/DS2-services/manifestService.js", "js");
+ loadjscssfile("./app/fusion/scripts/DS2-directives/footer.js", "js");
+ loadjscssfile("./app/fusion/scripts/DS2-directives/ds2Header.js", "js");
+ loadjscssfile("./app/fusion/scripts/DS2-directives/ds2LeftMenu.js", "js");
+ loadjscssfile("./app/fusion/external/ds2/js/digital-ng-library/digital-design-library.js", "js");
+
+ /*******DS2 styles*******/
+ loadjscssfile("./app/fusion/external/ds2/css/b2b-angular/b2b-angular.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/extras/ds2-accordion.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/extras/ds2-bootstrap-datepicker.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/extras/ds2-cc-input-field.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/extras/ds2-tooltip.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/extras/x-tabs-pills.css", "css");
+
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-accordion.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-bootstrap-datepicker.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-c2c.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-cc-input-field.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-filmstrip.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-filters.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-legacynav-fix.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-marquee.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-pagination.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-popover.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-progressbar.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ds2-tooltip.css", "css");
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/global.css", "css");
+
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/digital-design-library.css", "css");
+ /*******DS2 ICONS*******/
+
+ loadjscssfile("./app/fusion/external/ds2/css/digital-ng-library/ionicons.css", "css");
+ loadjscssfile("./app/fusion/styles/ecomp.css", "css");
+ loadjscssfile("./app/fusion/external/angular-gridster/dist/angular-gridster.min.css", "css");
+
+}
+
+window.onload = loadResource();
+/*window.onload = function(){
+ var appLoadingInterval = setInterval(function(){ loadApp() }, 10000);
+ var count=0;
+ function loadApp(){
+ count++
+ if(typeof angular !== 'undefined') {
+ angular.bootstrap(document, ['abs']);
+ clearInterval(appLoadingInterval);
+ }else if(count>10){
+ clearInterval(appLoadingInterval);
+ }
+ }
+}*/ \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/view-models/footer.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/view-models/footer.html
new file mode 100644
index 00000000..7cbff474
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/app/fusion/scripts/view-models/footer.html
@@ -0,0 +1,17 @@
+<!-- This is a placeholder for the open-source SDK-App footer -->
+<script src="app/fusion/external/ebz/js/footer.js"></script>
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
+<div class="footerContainer" id="footerContainer">
+ <div class="footerWrapper" id="footerWrapper">
+ <div class="attFooterInfo" style="text-align: center;">
+ <div class="footerLastSection">
+ <div class="footerText">
+ <p class="copyright-text">
+ Copyright Open ECOMP and Linux Foundation 2017.
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css
index a9edba8f..a9edba8f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css
new file mode 100644
index 00000000..4bf19bfa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css
@@ -0,0 +1,116 @@
+/* ui-gridster.css */
+.gridster-container {
+ background-color: #EFEFEF;
+ color: #fff;
+ border: 1px dashed;
+ overflow-y: auto;
+ overflow-x: hidden; }
+
+/* app css for attGridtser */
+.gridster-item-container {
+ background-color: #FFFFFF;
+ position: relative;
+ margin-left: auto;
+ margin-right: auto;
+ min-height: 79px;
+ height: 100%; }
+ .gridster-item-container .gridster-item-header {
+ /* gridster-item Header */
+ position: relative;
+ height: 50px !important;
+ border: 1px solid #d3d3d3;
+ border-bottom: 0;
+ background-color: #E5E5E5;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ z-index: 1;
+ -webkit-border-radius: 2px 2px 0 0;
+ -moz-border-radius: 2px 2px 0 0;
+ -ms-border-radius: 2px 2px 0 0;
+ -o-border-radius: 2px 2px 0 0;
+ border-radius: 2px 2px 0 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: hidden;
+ /* IE6-8 */ }
+ .gridster-item-container .gridster-item-header .gridster-item-handle {
+ cursor: move;
+ margin: 12px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border: 0;
+ vertical-align: middle;
+ -ms-interpolation-mode: bicubic;
+ display: block; }
+ .gridster-item-container .gridster-item-header .gridster-item-header-content {
+ line-height: 44px;
+ margin-left: 26px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 18px;
+ color: #444444;
+ float: left; }
+ .gridster-item-container .gridster-item-header .gridster-item-sub-header-content {
+ position: absolute;
+ top: 29.5px;
+ left: 26px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 12px;
+ color: #444444; }
+ .gridster-item-container .gridster-item-header .gridster-item-header-buttons-container {
+ position: absolute;
+ right: 10px;
+ top: 10px;
+ overflow: hidden;
+ text-align: right;
+ height: 30px;
+ color: #444444; }
+ .gridster-item-container .gridster-item-body {
+ /* gridster-item Body */
+ position: absolute;
+ width: 100%;
+ top: 50px;
+ left: 0;
+ right: 0;
+ bottom: 29px;
+ border: 1px solid #d3d3d3;
+ box-sizing: border-box;
+ overflow: auto;
+ color: #444444;
+ /* text-align: center; */ }
+ .gridster-item-container .gridster-item-footer {
+ /* gridster-item Footer */
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ height: 29px !important;
+ text-align: left;
+ cursor: pointer;
+ border: 1px solid #d3d3d3;
+ border-top: 0;
+ background-color: #F2F2F2;
+ -webkit-border-radius: 0 0 2px 2px;
+ -moz-border-radius: 0 0 2px 2px;
+ -ms-border-radius: 0 0 2px 2px;
+ -o-border-radius: 0 0 2px 2px;
+ border-radius: 0 0 2px 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ text-decoration: none;
+ /* IE6-8 */ }
+ .gridster-item-container .gridster-item-footer:hover {
+ background-color: #E5E5E5;
+ color: #565656;
+ text-decoration: underline; }
+ .gridster-item-container .gridster-item-footer .gridster-item-footer-content {
+ line-height: 30px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 12px;
+ color: #565656;
+ margin: 20px;
+ text-decoration: none; }
+ .gridster-item-container .gridster-item-footer .gridster-item-footer-content:hover {
+ color: #199ddf;
+ text-decoration: underline; }
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/fusion-sunny.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/fusion-sunny.css
new file mode 100644
index 00000000..f9154a1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/css/fusion-sunny.css
@@ -0,0 +1,362 @@
+ input, textarea, select, div {
+ font-family: Arial;
+ font-size: 11px;
+ font-weight: normal;
+ }
+
+ form {
+ margin-top: 5px;
+ }
+
+
+ .applicationWindow { border-width: 0px 0px 1px 0px;
+ border-style: solid;
+ border-color: #959595;
+ box-shadow: inset 0 0 10px #000000;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+
+ .feedbackMessage { width: 99%;
+ font-family: Arial;
+ font-size: 11px;
+ color: #1f1f1f;
+ padding: 3px;
+ border: 1px #eeb420 solid;
+ margin: 3px;
+ background: #fff9e5;
+ }
+
+ .menubar {
+ border-width: 0px 0px 0px 1px; border-style: solid; border-color: #959595;
+ }
+
+ .footer {
+ /*clear: both;*/
+ border-width: 0px 1px 0px 1px; border-style: solid; border-color: #959595;
+ font-family: Verdana,Arial,Helvetica, sans-serif;
+ font-size: 9px;
+ padding: 10px 10px 30px 10px;
+ background: white;
+ }
+
+ .pageTitle {
+ font-family: Arial;
+ font-size: 18px;
+ font-weight: bold;
+ margin-top: 5px;
+ }
+
+ .content {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ font-family: Arial;
+ font-size: 11px;
+ padding: 5px;
+ background: white;
+ /*height: 600px;*/
+ }
+
+ .popupContent {
+ font-family: Arial;
+ font-size: 11px;
+ padding: 3px;
+ }
+
+ .logo {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ text-align: right;
+ }
+
+ .sep {
+ border: 1px solid black
+ }
+
+ .logo { /*position: relative;*/
+ float:left;
+ padding-top: 25px;
+ padding-left: 25px;
+ }
+
+ .applicationLogo { float:right;
+ padding-top: 25px;
+ padding-right: 25px;
+ }
+
+ .applinkWhite { font-family: Arial;
+ font-size: 13px;
+ font-weight: 900;
+ color: #FFFFFF;
+ text-decoration: none; }
+
+ .terms { font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 9px;
+ }
+
+ .broadcastMessage { color: red; }
+ .broadcastMessageList { color: red; }
+
+ .button {
+ margin: 5px 1px 5px 1px;
+ padding: 3px; }
+
+ .toolbarbutton:hover {
+ color:#005491;
+ }
+
+ .headerText { font-family: Arial;
+ font-size: 15px;
+ font-weight: 700;
+ color: #000000; }
+
+ .headerBackground { background: #336699; }
+
+ .errorMessageText { font-family: Arial;
+ font-size: 11px;
+ font-weight: bold;
+ color: red; }
+
+
+ .normalText { font-family: Arial;
+ font-size: 11px;
+ color: #000000; }
+
+ .normalTextRed { font-family: Arial;
+ font-size: 11px;
+ color: red; }
+
+
+ .smallNormalText { font-family: Arial;
+ font-size: 9px;
+ color: #000000; }
+
+ .tableBorder { border:1px outset teal }
+
+ .validationError { background: #b9eaff; }
+
+ .templatebody {
+ background: url(../images/body_graphic.jpg) repeat-x;
+ /*margin: 40px 80px 40px 80px;*/
+ }
+
+ /*--------------------- General Content ------------------------------------*/
+
+ .relative {
+ position:relative;
+ }
+
+ .clear{
+ clear:both;
+ }
+
+ .left {
+ float: left;
+ }
+
+ .leftCentered{
+ float: left;
+ text-align: center;
+ }
+
+ .right {
+ float: right;
+ }
+
+ .rightAligned{
+ text-align: right;
+ }
+
+ .centered {
+ text-align: center;
+ align: center;
+ }
+
+
+ .noWrap{
+ white-space:nowrap;
+ }
+
+ .disabled {
+ color:gray;
+ cursor:hand;
+ }
+
+ /*--------------------- Tab styles -------------------------------------*/
+
+ .current {
+ font-weight: bold;
+ border-width: 1px 1px 1px 1px;
+ border-color: silver;
+ border-style: solid;
+ }
+
+ .subTab {
+ font-weight:bold;
+ font-family: Arial;
+ font-size: 11px;
+ color: #0F3B82;
+ }
+
+
+ /*--------------------- Grid styles ------------------------------------*/
+
+ /* Grid navigation and header styles */
+ .gridFilterLabel {font-size: 7pt;
+ font-align: justify;
+ font-weight: bold;
+ display: block;}
+
+ .gridFilterText {height: 17px;
+ font-size: 8pt;
+ width: 60%;
+ font-align: justify;}
+
+ .gridNavigationBar { font-family:Arial,Verdana;
+ font-size:11px;
+ font-weight:normal;
+ color:#000;
+ margin: 0px;
+ width: 100%;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .navLinks { float: left;
+ margin-right:15px;
+ padding-top: 2px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls { float: left;
+ margin-right: 15px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .pageInfo { float: right;
+ vertical-align: middle;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageInfo input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+
+ .gridNavigationBar span { padding: 3px; }
+
+ .gridNavigationBar a {
+ text-decoration:underline;
+ color:#000;
+ font-weight:normal;
+ }
+
+ .gridNavigationBar img { vertical-align: middle; }
+
+ .gridBulkUpdateRow {
+ height: 35px;
+ line-height: 35px;
+ }
+
+ .gridBulkUpdateRow input {
+ vertical-align: middle;
+ }
+
+
+ /* dummy class used to lock the form elements of a grid - ex. bulk transaction processing */
+ .alwaysEnabled {}
+
+ .hidden {
+ display: none;
+ }
+
+ .selectedPage {
+ background-color:#C4DFFB;
+ color: white;
+ border-style: solid;
+ border-width: 1px;
+ border-color: gray;
+ padding-left: 3px;
+ padding-right: 3px;
+ vertical-align: middle;
+ }
+
+ .selectedRow{
+ /*background-color:#C4DFFB;*/
+ }
+
+ /* Action Item styles */
+ .actionList {
+ margin-left: -20px;
+ margin-right: -10px;
+ padding-left: 5px;
+ }
+
+ .actionList li {
+ float:left;
+ padding-left: 3px;
+ padding-right: 3px;
+ }
+
+ .actionList li a {
+ text-decoration:none;
+ color:#000;
+ }
+
+ /* Filter Operator List styles */
+
+ .filterList {
+ margin: 0px;
+ }
+
+ .filterList li {
+ list-style-type: none;
+ padding:3px 3px 3px 2px;
+ cursor:hand;
+ font-size:11px;
+ }
+
+ .filterList li:hover {
+ background: #404040;
+ }
+
+ .filterList li a {
+ color: #000;
+ text-decoration: none;
+ }
+
+ .filterList li:hover a {
+ color: white;
+ }
+
+ .filterList li a:hover {
+ text-decoration: none;
+ color: white;
+ }
+
+ .filterListItem a {
+ text-decoration:none;
+ padding:3px 2px 3px 2px;
+ }
+
+
+ /*---------------------- Customized ZK Styles ------------------------------*/
+
+ .z-datebox input, .z-timebox input {
+ font-family: Arial;
+ font-size: 11px;
+ height: 15px;
+ margin-top:1px;
+ }
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png
index 29b92cc5..29b92cc5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/att_angular_gridster/grips.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login-550x360.jpg b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login-550x360.jpg
new file mode 100644
index 00000000..618b1a92
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login-550x360.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login.jpg b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login.jpg
new file mode 100644
index 00000000..618b20e9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp-login.jpg
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp.png
index b355f109..b355f109 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp_trans.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp_trans.png
index 4e8381c1..4e8381c1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/ecomp_trans.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/images/ecomp_trans.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js
index 985fa434..985fa434 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js
index 3ca3db7d..3ca3db7d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/flexslider.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/flexslider.css
new file mode 100644
index 00000000..c459ef44
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/flexslider.css
@@ -0,0 +1,275 @@
+/*
+ * jQuery FlexSlider v2.6.0
+ * http://www.woothemes.com/flexslider/
+ *
+ * Copyright 2012 WooThemes
+ * Free to use under the GPLv2 and later license.
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Contributing author: Tyler Smith (@mbmufffin)
+ *
+ */
+/* ====================================================================================================================
+ * FONT-FACE
+ * ====================================================================================================================*/
+@font-face {
+ font-family: 'flexslider-icon';
+ src: url('fonts/flexslider-icon.eot');
+ src: url('fonts/flexslider-icon.eot?#iefix') format('embedded-opentype'), url('fonts/flexslider-icon.woff') format('woff'), url('fonts/flexslider-icon.ttf') format('truetype'), url('fonts/flexslider-icon.svg#flexslider-icon') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+/* ====================================================================================================================
+ * RESETS
+ * ====================================================================================================================*/
+.flex-container a:hover,
+.flex-slider a:hover {
+ outline: none;
+}
+.slides,
+.slides > li,
+.flex-control-nav,
+.flex-direction-nav {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+.flex-pauseplay span {
+ text-transform: capitalize;
+}
+/* ====================================================================================================================
+ * BASE STYLES
+ * ====================================================================================================================*/
+.flexslider {
+ margin: 0;
+ padding: 0;
+}
+.flexslider .slides > li {
+ display: none;
+ -webkit-backface-visibility: hidden;
+}
+.flexslider .slides img {
+ width: 100%;
+ display: block;
+}
+.flexslider .slides:after {
+ content: "\0020";
+ display: block;
+ clear: both;
+ visibility: hidden;
+ line-height: 0;
+ height: 0;
+}
+html[xmlns] .flexslider .slides {
+ display: block;
+}
+* html .flexslider .slides {
+ height: 1%;
+}
+.no-js .flexslider .slides > li:first-child {
+ display: block;
+}
+/* ====================================================================================================================
+ * DEFAULT THEME
+ * ====================================================================================================================*/
+.flexslider {
+ margin: 0 0 60px;
+ background: #ffffff;
+ border: 4px solid #ffffff;
+ position: relative;
+ zoom: 1;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ -o-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+}
+.flexslider .slides {
+ zoom: 1;
+}
+.flexslider .slides img {
+ height: auto;
+ -moz-user-select: none;
+}
+.flex-viewport {
+ max-height: 2000px;
+ -webkit-transition: all 1s ease;
+ -moz-transition: all 1s ease;
+ -ms-transition: all 1s ease;
+ -o-transition: all 1s ease;
+ transition: all 1s ease;
+}
+.loading .flex-viewport {
+ max-height: 300px;
+}
+.carousel li {
+ margin-right: 5px;
+}
+.flex-direction-nav {
+ *height: 0;
+}
+.flex-direction-nav a {
+ text-decoration: none;
+ display: block;
+ width: 40px;
+ height: 40px;
+ margin: -20px 0 0;
+ position: absolute;
+ top: 50%;
+ z-index: 10;
+ overflow: hidden;
+ opacity: 0;
+ cursor: pointer;
+ color: rgba(0, 0, 0, 0.8);
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
+ -webkit-transition: all 0.3s ease-in-out;
+ -moz-transition: all 0.3s ease-in-out;
+ -ms-transition: all 0.3s ease-in-out;
+ -o-transition: all 0.3s ease-in-out;
+ transition: all 0.3s ease-in-out;
+}
+.flex-direction-nav a:before {
+ font-family: "flexslider-icon";
+ font-size: 40px;
+ display: inline-block;
+ content: '\f001';
+ color: rgba(0, 0, 0, 0.8);
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
+}
+.flex-direction-nav a.flex-next:before {
+ content: '\f002';
+}
+.flex-direction-nav .flex-prev {
+ left: -50px;
+}
+.flex-direction-nav .flex-next {
+ right: -50px;
+ text-align: right;
+}
+.flexslider:hover .flex-direction-nav .flex-prev {
+ opacity: 0.7;
+ left: 10px;
+}
+.flexslider:hover .flex-direction-nav .flex-prev:hover {
+ opacity: 1;
+}
+.flexslider:hover .flex-direction-nav .flex-next {
+ opacity: 0.7;
+ right: 10px;
+}
+.flexslider:hover .flex-direction-nav .flex-next:hover {
+ opacity: 1;
+}
+.flex-direction-nav .flex-disabled {
+ opacity: 0!important;
+ filter: alpha(opacity=0);
+ cursor: default;
+ z-index: -1;
+}
+.flex-pauseplay a {
+ display: block;
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ bottom: 5px;
+ left: 10px;
+ opacity: 0.8;
+ z-index: 10;
+ overflow: hidden;
+ cursor: pointer;
+ color: #000;
+}
+.flex-pauseplay a:before {
+ font-family: "flexslider-icon";
+ font-size: 20px;
+ display: inline-block;
+ content: '\f004';
+}
+.flex-pauseplay a:hover {
+ opacity: 1;
+}
+.flex-pauseplay a.flex-play:before {
+ content: '\f003';
+}
+.flex-control-nav {
+ width: 100%;
+ position: absolute;
+ bottom: -40px;
+ text-align: center;
+}
+.flex-control-nav li {
+ margin: 0 6px;
+ display: inline-block;
+ zoom: 1;
+ *display: inline;
+}
+.flex-control-paging li a {
+ width: 11px;
+ height: 11px;
+ display: block;
+ background: #666;
+ background: rgba(0, 0, 0, 0.5);
+ cursor: pointer;
+ text-indent: -9999px;
+ -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -o-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
+.flex-control-paging li a:hover {
+ background: #333;
+ background: rgba(0, 0, 0, 0.7);
+}
+.flex-control-paging li a.flex-active {
+ background: #000;
+ background: rgba(0, 0, 0, 0.9);
+ cursor: default;
+}
+.flex-control-thumbs {
+ margin: 5px 0 0;
+ position: static;
+ overflow: hidden;
+}
+.flex-control-thumbs li {
+ width: 25%;
+ float: left;
+ margin: 0;
+}
+.flex-control-thumbs img {
+ width: 100%;
+ height: auto;
+ display: block;
+ opacity: .7;
+ cursor: pointer;
+ -moz-user-select: none;
+ -webkit-transition: all 1s ease;
+ -moz-transition: all 1s ease;
+ -ms-transition: all 1s ease;
+ -o-transition: all 1s ease;
+ transition: all 1s ease;
+}
+.flex-control-thumbs img:hover {
+ opacity: 1;
+}
+.flex-control-thumbs .flex-active {
+ opacity: 1;
+ cursor: default;
+}
+/* ====================================================================================================================
+ * RESPONSIVE
+ * ====================================================================================================================*/
+@media screen and (max-width: 860px) {
+ .flex-direction-nav .flex-prev {
+ opacity: 1;
+ left: 10px;
+ }
+ .flex-direction-nav .flex-next {
+ opacity: 1;
+ right: 10px;
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot
new file mode 100644
index 00000000..97c4196f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg
new file mode 100644
index 00000000..89fd1ab8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="14"></iconset>
+</metadata>
+<defs>
+<font id="flexslider-icon" horiz-adv-x="448" >
+<font-face units-per-em="448" ascent="384" descent="-64" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode="&#xf001;" d="M 185.50-9.25l-163.00,162.75q-9.25,9.25 -9.25,22.625t 9.25,22.625l 163.00,162.75q 9.25,9.25 22.625,9.25t 22.625-9.25l 18.75-18.75q 9.25-9.25 9.25-22.625t-9.25-22.625l-121.50-121.50l 121.50-121.25q 9.25-9.50 9.25-22.75t-9.25-22.50l-18.75-18.75q-9.25-9.25 -22.625-9.25t-22.625,9.25z" horiz-adv-x="288" />
+<glyph unicode="&#xf002;" d="M 274.75,176.00q0.00-13.00 -9.25-22.75l-163.00-162.75q-9.25-9.25 -22.50-9.25t-22.50,9.25l-19.00,18.75q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 121.50,121.50l-121.50,121.25q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 19.00,18.75q 9.00,9.50 22.50,9.50t 22.50-9.50l 163.00-162.75q 9.25-9.25 9.25-22.50z" horiz-adv-x="288" />
+<glyph unicode="&#xf003;" d="M 346.00,152.25l-332.00-184.50q-5.75-3.25 -9.875-0.75t-4.125,9.00l0.00,368.00 q0.00,6.50 4.125,9.00t 9.875-0.75l 332.00-184.50q 5.75-3.25 5.75-7.75t-5.75-7.75z" horiz-adv-x="352" />
+<glyph unicode="&#xf004;" d="M 384.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 160.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf005;" d="M 402.75,208.00q0.00-13.25 -9.25-22.50l-162.75-162.75q-9.50-9.50 -22.75-9.50q-13.50,0.00 -22.50,9.50l-162.75,162.75q-9.50,9.00 -9.50,22.50q0.00,13.25 9.50,22.75l 18.50,18.75q 9.75,9.25 22.75,9.25q 13.25,0.00 22.50-9.25l 121.50-121.50l 121.50,121.50q 9.25,9.25 22.50,9.25q 13.00,0.00 22.75-9.25l 18.75-18.75q 9.25-9.75 9.25-22.75z" horiz-adv-x="416" />
+<glyph unicode="&#x20;" horiz-adv-x="224" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
+</font></defs></svg> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf
new file mode 100644
index 00000000..05432986
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff
new file mode 100644
index 00000000..10c4eeb8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blank.gif b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/images/blank.gif
index 75b945d2..75b945d2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blank.gif
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/images/blank.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/scribble.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/scribble.css
index 9986f2ac..9986f2ac 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/scribble.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/scribble.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/slider.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/slider.css
index f609403c..f609403c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/slider.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/slider.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/spacegallery.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/spacegallery.css
index ce4fd57c..ce4fd57c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/spacegallery.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/spacegallery.css
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/welcome.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/welcome.css
new file mode 100644
index 00000000..ea1af26e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/css/welcome.css
@@ -0,0 +1,173 @@
+/* Area Chart */
+
+#areaChart {
+ overflow: hidden;}
+
+#lineChart {
+ overflow: hidden;
+}
+
+#areaChart svg {
+ height: 200px;
+ width: 380px;
+ min-width: 100px;
+ min-height: 100px;
+}
+
+#lineChart svg {
+ height: 200px;
+ width: 380px;
+ min-width: 100px;
+ min-height: 100px;
+}
+
+#areaChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
+ background-color: rgb(255, 255, 255);
+}
+
+#lineChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
+ background-color: rgb(255, 255, 255);
+}
+
+#areaChart .nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height: 370px;
+ text-align: center;
+ vertical-align: middle;
+}
+
+#lineChart .nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height: 370px;
+ text-align: center;
+ vertical-align: middle;
+}
+
+#areaChart .nodatainner {
+ padding: 10px;
+}
+
+#lineChart .nodatainner {
+ padding: 10px;
+}
+
+/* Area Chart END */
+
+.button--small, [class*=bg-] .button--small {
+ font-size: 14px;
+ };
+
+/* Gridster (EBIZ) */
+
+.gridster-item-container .gridster-item-body{
+bottom:0px;
+}
+.gridster-item-container{
+min-height:50px;
+}
+.att-accordion {
+ border-width: 0px;
+}
+
+/* End Gridster */
+
+#myGallery {
+ width: 100%;
+ height: 400px;
+}
+
+#myGallery img {
+ border: 2px solid #52697E;
+}
+
+a.loading {
+ background: #fff url(../images/ajax_small.gif) no-repeat center;
+}
+
+.center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+
+#selectedTrafficDay ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#selectedTrafficDay li {
+ float: left;
+ border: 1px solid #000;
+ border-bottom-width: 0;
+ margin: 3px 3px 3px 3px;
+ padding: 5px 5px 5px 5px;
+ background-color: #F2F2F2;
+ color: #696969;
+}
+
+#SelectedTrafficeDayView {
+ padding: 0 1em;
+}
+
+#selectedTrafficDay .active1 {
+ background-color: #FFF;
+ color: #000;
+}
+
+#BusyHourTraffic ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#BusyHourTraffic li {
+ float: left;
+ border: 1px solid #000;
+ border-bottom-width: 0;
+ margin: 3px 3px 3px 3px;
+ padding: 5px 5px 5px 5px;
+ background-color: #F2F2F2;
+ color: #696969;
+}
+
+#BusyHourTrafficView {
+ padding: 0 1em;
+}
+
+#BusyHourTraffic .active2 {
+ background-color: #FFF;
+ color: #000;
+}
+
+#slider {
+ width: 600px;
+ margin: 0 auto;
+ clear: left;
+}
+
+@media only screen and (device-width: 768px) {
+ #slider {
+ width: 400px;
+ }
+}
+
+#container {
+
+}
+
+#title {
+ float:left;
+ width:100%;
+ height:30px;
+ margin:;
+ color:#222222;
+ text-shadow: 1px 1px 2px #A0A0A0;
+}
+
+.content{
+ margin-right:-230px;
+ top:50px;
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/area_chart.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/area_chart.html
index 30ef2011..30ef2011 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/area_chart.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/area_chart.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/bar_chart.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/bar_chart.html
index 0be16ec1..0be16ec1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/bar_chart.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/bar_chart.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html
index 94596e73..94596e73 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv
index 406143ea..406143ea 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv
index 046383e4..046383e4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/worddata.csv b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/worddata.csv
new file mode 100644
index 00000000..762cb423
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/data/worddata.csv
@@ -0,0 +1 @@
+text,frequency service,98 portal,70 management,70 virtual,56 design,56 VNF,56 studio,42 operations,42 inventory,42 POLO,42 D2.0,42 ASDC,42 router,28 restart,28 process,28 platform,28 manage,28 loop,28 licensing,28 license,28 integrated,28 flow-through,28 enable,28 data,28 controller,28 control,28 configure,28 component,28 common,28 asset,28 application,28 ECOMP,28 workflow,14 waterfall,14 visual,14 view,14 vCTS,14 utilization,14 user,14 usage,14 troubleshoot,14 transformation,14 track,14 topolgies,14 topics,14 time,14 tickets,14 thresholds,14 templates,14 structures,14 standards-based,14 software,14 reuse,14 repository,14 reports,14 release,14 recipes,14 real-time,14 provisioning,14 properties,14 project-based,14 processes,14 physical,14 oversight,14 openl-loop,14 network,14 monitor,14 modeling,14 model-driven,14 model,14 message,14 maximize,14 manually,14 machine,14 layer,14 interact,14 instances,14 initiate,14 increase,14 imported,14 impacts,14 host,14 function,14 feeds,14 features,14 faults,14 extended,14 engines,14 engine,14 dynamic,14 document-driven,14 determine,14 dashboard,14 current,14 creation,14 created,14 create,14 configuration,14 composer,14 components,14 collective,14 certification,14 bus,14 basis,14 available,14 automation,14 automated,14 associated,14 assignment,14 appropriate,14 against,14 aervice,14 adminstrators,14 activation,14 action,14 VMs,14 VM,14 VLAN,14 SDN,14 SDK,14 SBG,14 SAM,14 RUBY,14 Policy,14 PODS,14 Ops,14 GFP,14 F5FW,14 DMaaP,14 DCAE,14 DBC,14 CPADS,14 AT&T,14 APP-C,14 AOTS-TM,14 ALTS,14 A&AI,14
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/donut_d3.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/donut_d3.html
index afcac359..afcac359 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/donut_d3.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/donut_d3.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js
index 9b3decb9..9b3decb9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/donut.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/donut.min.js
index 60c4fd4b..60c4fd4b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/donut.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/donut.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/gauges.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/gauges.min.js
index c0fd7484..c0fd7484 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/gauges.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/gauges.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js
index e501260b..e501260b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js
index f78eec70..f78eec70 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/worddata.min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/worddata.min.js
index 6b827460..6b827460 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/js/worddata.min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/js/worddata.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/line_chart.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/line_chart.html
index d4ba57a4..d4ba57a4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/line_chart.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/line_chart.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/pie_chart.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/pie_chart.html
index ebbdd9c0..ebbdd9c0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/pie_chart.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/pie_chart.html
diff --git a/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/wordcloud.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/wordcloud.html
new file mode 100644
index 00000000..6cf00079
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/html/wordcloud.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+ <title>Word Cloud Example</title>
+ <meta charset="utf-8" />
+<script src="../../d3/js/d3.v3.min.js" type="text/JavaScript"></script>
+<script src="../../d3/js/colorbrewer.js" type="text/JavaScript"></script>
+<script src="../../d3/js/d3.layout.cloud.js" type="text/JavaScript"></script>
+
+</head>
+<style>
+ svg {
+ height: 350px;
+ width: 420px;
+ border: 1px solid gray;
+ }
+
+</style>
+<body>
+
+<div id="viz">
+ <svg>
+ </svg>
+</div>
+<div id="controls" />
+</body>
+ <footer>
+
+<script>
+var cloudSize = 200;
+var dataURL = "data/worddata.csv";
+var keywords = ["VNF", "portal", "D2.0", "service", "management", "ECOMP"];
+</script>
+<script src="js/worddata.min.js" type="text/JavaScript"></script>
+ </footer>
+
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png
index ac970bda..ac970bda 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-next.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-next.png
index 1a4f72c6..1a4f72c6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-next.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-next.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-prev.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-prev.png
index 8211eba1..8211eba1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/arrow-prev.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/arrow-prev.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png
index 78a8873b..78a8873b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png
index df471d7d..df471d7d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png
index e59fc189..e59fc189 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png
index 76a2d2b7..76a2d2b7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png
index 174ef9b8..174ef9b8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png
index f7f2719a..f7f2719a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png
index ee0ddef9..ee0ddef9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/copyicon.png
index 6c1c3c15..6c1c3c15 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/copyicon.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon.gif b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/deleteicon.gif
index 4b07af82..4b07af82 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon.gif
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/deleteicon.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/example-frame.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/example-frame.png
index 31f2fe1c..31f2fe1c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/example-frame.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/example-frame.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading.gif b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/loading.gif
index cccb0fc9..cccb0fc9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading.gif
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/loading.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png
index d46eee50..d46eee50 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png
index ed82aad3..ed82aad3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png
index 8f8c0328..8f8c0328 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png
index 750dca5d..750dca5d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png
index 599e51f1..599e51f1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png
index 70323ea0..70323ea0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png
index 9d579d68..9d579d68 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png
index af1ac0a7..af1ac0a7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png
index 935b5386..935b5386 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png
index 916a655f..916a655f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png
index a8b516d9..a8b516d9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png
index 2cf81411..2cf81411 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/FusionCharts.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/FusionCharts.js
index 4c174dfa..4c174dfa 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/FusionCharts.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/FusionCharts.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/charts.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/charts.js
index 4bebbd36..4bebbd36 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/charts.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/charts.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/eye.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/eye.js
index 8a281dc3..8a281dc3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/eye.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/eye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js
index 5ad6c377..5ad6c377 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/scribble.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/scribble.js
index 5384b304..5384b304 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/scribble.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/scribble.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js
index 1a1fcdd8..1a1fcdd8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/spacegallery.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/spacegallery.js
index 69ab2ccc..69ab2ccc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/spacegallery.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/spacegallery.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/utils.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/utils.js
index d9be8532..d9be8532 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/js/utils.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/js/utils.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css
index 3424a5f1..3424a5f1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/custom.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/custom.css
index b7df8c25..b7df8c25 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/custom.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/custom.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css
index ffabe274..ffabe274 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css
index d44b3a22..d44b3a22 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example.html
index 543b0f92..543b0f92 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html
index a2e3703d..a2e3703d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png
index 3bbaf5ee..3bbaf5ee 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg
index e79a0515..e79a0515 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js
index 89411b29..89411b29 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/prettify.js b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/prettify.js
index eef5ad7e..eef5ad7e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/org_chart/prettify.js
+++ b/ecomp-sdk/epsdk-app-os/src/main/webapp/static/fusion/sample/org_chart/prettify.js
diff --git a/ecomp-sdk/epsdk-app-overlay/.gitignore b/ecomp-sdk/epsdk-app-overlay/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-app-overlay/README.md b/ecomp-sdk/epsdk-app-overlay/README.md
new file mode 100644
index 00000000..174d4458
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/README.md
@@ -0,0 +1,24 @@
+# ECOMP SDK Web Application Overlay Files
+
+## Overlay Project
+
+This is a Maven project with the ECOMP SDK web application overlay. This
+project has common CSS, JavaScript, JSP and HTML files that are used in
+the AT&T internal version and the open-source version of the ECOMP SDK
+sample web application. Those specific versions are built using separate
+Maven projects that copy in ("overlay") the contents of this project at
+package time. This is not a stand-alone web application.
+
+## Release Notes
+
+SDK is currently using AngularJS version 1.4.8 for compatibility with b2b library
+version 1.0.1. Note that previous versions of the EPSDK web application used
+AngularJS version 1.5.0.
+
+### OpenECOMP Distributions
+
+Version 1.1.0
+- [Portal-7] Improvements added as part of the rebasing process
+
+Version 1.0.0
+- Initial release
diff --git a/ecomp-sdk/epsdk-app-overlay/pom.xml b/ecomp-sdk/epsdk-app-overlay/pom.xml
new file mode 100644
index 00000000..7365115b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-app-overlay</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>war</packaging>
+ <name>ECOMP Portal SDK Webapp Overlay Files</name>
+ <description>ECOMP Portal SDK Web Application overlay project</description>
+ <url>https://wiki.onap.org/display/DW/Portal</url>
+
+ <properties>
+ <encoding>UTF-8</encoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <!-- Silence Eclipse warnings by declaring Java 1.8 class output format -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- Silence Eclipse warning on JSPs by declaring dependencies -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/ecomp-sdk/sdk-app/src/main/resources/att-rules.drl b/ecomp-sdk/epsdk-app-overlay/src/main/resources/att-rules.drl
index e15c3fb1..e15c3fb1 100644
--- a/ecomp-sdk/sdk-app/src/main/resources/att-rules.drl
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/resources/att-rules.drl
diff --git a/ecomp-sdk/sdk-app/src/main/resources/cache.ccf b/ecomp-sdk/epsdk-app-overlay/src/main/resources/cache.ccf
index d21404b0..d21404b0 100644
--- a/ecomp-sdk/sdk-app/src/main/resources/cache.ccf
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/resources/cache.ccf
diff --git a/ecomp-sdk/sdk-app/src/main/resources/mchange-log.properties b/ecomp-sdk/epsdk-app-overlay/src/main/resources/mchange-log.properties
index 77e260bb..77e260bb 100644
--- a/ecomp-sdk/sdk-app/src/main/resources/mchange-log.properties
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/resources/mchange-log.properties
diff --git a/ecomp-sdk/sdk-app/src/main/resources/state-rules.drl b/ecomp-sdk/epsdk-app-overlay/src/main/resources/state-rules.drl
index 586ae6b7..586ae6b7 100644
--- a/ecomp-sdk/sdk-app/src/main/resources/state-rules.drl
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/resources/state-rules.drl
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/quartz.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/quartz.properties
index 23340ddc..9472ce70 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/quartz.properties
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/quartz.properties
@@ -27,4 +27,3 @@ org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor.properties
index 68b1f707..d566f027 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor.properties
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor.properties
@@ -1,22 +1,3 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
##C## Mention the name of the framework. At present RAPTOR supports FUSION
system=fusion
##C## Determines the priority for the debug message.
@@ -97,8 +78,8 @@ jfree_version=latest
display_all_users=yes
##Sheet name
sheet_name=raptor
-#shell_script_name=/home/sundar/test.sh
-#download_query_folder=/titan/PROJECT3/RAPTOR/raptor/dwnld/query/
+#shell_script_name=/home/XXXX/test.sh
+#download_query_folder=/XXXXXX/raptor/dwnld/query/
## this directory is mentioned if the flat file is downloaded using shell script
shell_script_dir=/titan/PROJECT3/RAPTOR/raptor/dwnld/
flat_file_lower_limit=1
@@ -107,8 +88,8 @@ flat_file_upper_limit=200000
request_get_params=isEmbedded
print_footer_in_download=yes
## footer mentioned here appears in downloaded excel
-footer_first_line=TODO footer first line
-footer_second_line=Use Pursuant to Company Instructions
+footer_first_line=footer message 1
+footer_second_line=footer message 2
## to run report in popup window
report_in_popup_window=yes
## to run each report in new popup window if the above is selected
@@ -134,13 +115,13 @@ schedule_limit=10
#schedule_custom_query_for_roles=getAllRolesByCustomer
# customized query if you need any restrictions for schedule and security tab for prisms example
#schedule_custom_query_for_users=SELECT au.user_id, au.first_name||' '||au.last_name user_name FROM app_user au order by 2
-schedule_custom_query_for_users=SELECT au.user_id id, au.first_name||' '||au.last_name name FROM app_user au where user_id = 1 order by 2
+schedule_custom_query_for_users=SELECT au.user_id id, concat(au.first_name,' ',au.last_name) name FROM fn_user au order by 2
#schedule_custom_query_for_roles=SELECT ar.role_id, ar.descr role_name FROM app_role ar order by 2
schedule_date_pattern=MM/dd/yyyy hh:mm:ss a
## This is used to display in right format in chart timestamp axis as we give in the sql
#chart_yearly_format=yyyy
#chart_monthly_format=MMM-yyyy
-#chart_daily_format=MM-dd-yyyy
+chart_daily_format=MM/dd/yyyy
chart_hourly_format=MM/dd HH
#chart_minute_format=HH:mm
chart_minute_format=MM-dd-yyyy-HH:mm
@@ -155,7 +136,7 @@ display_session_param_pdfexcel=login_id;Login Id
session_params_for_displaying_in_scheduling=login_id;Login Id
application_server=tomcat
#gmap properties
-gmap_key=ABQIAAAAToJSSetKBMjBJx8MiRw4ghQiU0SbbKnm8C5eu25cpyLwgkLzyRShrQTbgZtqnKAqZU9JwcSq1bKwiA
+gmap_key=XXXXXXXXXXXXXXXXXXXX
PROJECT-FOLDER=/Users/sundar/git/st_quantum/quantum/target/quantum-1.0
#
MARKET-SHAPEFILE-FOLDER=resources/files
@@ -183,5 +164,9 @@ adjust_content_based_on_height=yes
custom_submit_button_text=Run Button
customize_formfield_layout=yes
#db_type=postgresql
+#### ORACLE ####
#db_type=oracle
+#time_format=MM/DD/YYYY HH:MI:SS AM
+#### MARIADB ####
db_type=mysql
+time_format=%m/%d/%Y %h:%i:%s %p
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties
new file mode 100644
index 00000000..33ae0572
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties
@@ -0,0 +1,20 @@
+temp_folder_path=/demeter/WebApps/dev/ECOMP_PORTAL/temp/
+upload_folder_path=/demeter/WebApps/dev/ECOMP_PORTAL/files/
+excel_template_path=/demeter/WebApps/dev/ECOMP_PORTAL/files/raptor_template/
+temp_folder_url=temp/
+upload_folder_url=upload/
+smtp_server=todo.smtp.com
+default_email_sender=email-name@email.com
+error_page=error_page
+jsp_context_path=raptor/
+img_folder_url=static/fusion/raptor/images/
+base_folder_url=static/fusion/raptor/
+direct_access_url=http://localhost:8080/quantum/raptor_email_attachment.htm?action=raptor&source_page=report_run&display_content=y
+#base_action_url=report.htm#/report_run/
+drill_action_url=report.htm#/report_run/c_master=
+base_action_url=report_wizard.htm?action=
+base_action_url_ng=report#/
+base_action_param=c_master=
+super_role_id=1
+admin_role_ids=1
+quick_links_menu_ids=HOME,CUSTOMER,REPORTS
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/.gitignore b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/.gitignore
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_pdf.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_pdf.properties
new file mode 100644
index 00000000..d7f8249c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/raptor_pdf.properties
@@ -0,0 +1,30 @@
+## pdf file specific properties
+pdf_data_font_size=9
+pdf_data_font_family=Arial
+#reduce the font size from html config
+pdf_data_font_size_offset=2
+pdf_data_alternate_color=true
+#data row background(white), alternate(light light blue/gray)
+pdf_data_background_alternate_hex_code=#EDEDED
+pdf_data_default_background_hex_code=#FFFFFF
+#header font (white) background (gray)
+pdf_data_table_header_font_hex_code=#FFFFFF
+pdf_data_table_header_background_hex_code=#8A9BB3
+#footer header
+pdf_footer_font_size=9
+pdf_footer_font_family=Arial
+pdf_footer=footer message
+pdf_footer_font_size=7
+pdf_date_timezone=GMT
+pdf_date_pattern=MM/dd/yyyy hh:mm:ss a
+##page number position at 1 - footer middle, 0 -- header right, 2 - both
+pdf_page_number_position=1
+pdf_word_before_page_number=Page
+pdf_word_after_page_number=
+pdf_coverpage_firstcolumn_size=0.3
+pdf_image_auto_rotate=false
+display_create_owner_info=true
+#session_info=customer,customerId
+display_loginid_for_downloaded_by=false
+# please use false if you want landscape to be default.
+is_default_orientation_portrait=true
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/sql.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties
index ac52f3c9..c643bb97 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/sql.properties
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties
@@ -1,22 +1,3 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
#SQL Statements for PostgreSQL
#ReportLoader.java
@@ -35,13 +16,15 @@ formfield.id.name.sql.suffix=
report.security.create= SELECT coalesce(cr.owner_id, cr.create_id) AS owner_id, cr.create_id, DATE_FORMAT(cr.create_date, '%m/%d/%Y') create_date, maint_id, DATE_FORMAT(cr.maint_date, '%m/%d/%Y') update_date, cr.public_yn FROM cr_report cr WHERE cr.rep_id = [rw.getReportID()]
+db.update.report.xml.mysql=UPDATE cr_report SET report_xml=? WHERE rep_id=?
+db.update.report.xml.mysql.select=SELECT rep_id,report_xml FROM cr_report where rep_id = ?
db.update.report.xml = SELECT cr.rep_id, cr.report_xml FROM cr_report cr WHERE rep_id=? FOR UPDATE
-update.custom.report.rec = UPDATE cr_report SET title='[Utils.oracleSafe(rw.getReportName())]', descr='[Utils.oracleSafe(rw.getReportDescr())]', public_yn='[(rw.isPublic()]', menu_id='[rw.getMenuID()]', menu_approved_yn='[(rw.isMenuApproved()]', owner_id=[rw.getOwnerID()], maint_id=[rw.getUpdateID()], maint_date=STR_TO_DATE('[rw.getUpdateDate()]', '[Globals.getOracleTimeFormat()]'), dashboard_type_yn='[(rw.isDashboardType()]', dashboard_yn= '[(rw.getReportType().equals(AppConstants.RT_DASHBOARD)]' WHERE rep_id = [rw.getReportID()]
+update.custom.report.rec = UPDATE cr_report SET title='[Utils.oracleSafe(rw.getReportName())]', descr='[Utils.oracleSafe(rw.getReportDescr())]', public_yn='[(rw.isPublic()]', menu_id='[rw.getMenuID()]', menu_approved_yn='[(rw.isMenuApproved()]', owner_id=[rw.getOwnerID()], maint_id=[rw.getUpdateID()], maint_date=STR_TO_DATE('[rw.getUpdateDate()]', '[Globals.getTimeFormat()]'), dashboard_type_yn='[(rw.isDashboardType()]', dashboard_yn= '[(rw.getReportType().equals(AppConstants.RT_DASHBOARD)]' WHERE rep_id = [rw.getReportID()]
is.report.already.scheduled = select rep_id from cr_report_schedule where rep_id = ?
-create.custom.report.rec = INSERT INTO cr_report(rep_id, title, descr, public_yn, menu_id, menu_approved_yn, report_xml, owner_id, create_id, create_date, maint_id, maint_date, dashboard_type_yn, dashboard_yn, folder_id) VALUES([rw.getReportID()], '[Utils.oracleSafe(rw.getReportName())]', '[Utils.oracleSafe(rw.getReportDescr())]', '[rw.isPublic()]', '[rw.getMenuID()]', '[rw.isMenuApproved()]', '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>', [rw.getOwnerID()], [rw.getCreateID()], STR_TO_DATE('[rw.getCreateDate()]', '[Globals.getOracleTimeFormat()]'), [rw.getUpdateID()], STR_TO_DATE('[rw.getUpdateDate()]', '[Globals.getOracleTimeFormat()]'), '[rw.isDashboardType()]', '[rw.getReportType().equals(AppConstants.RT_DASHBOARD)]',[rw.getFolderId()])
+create.custom.report.rec = INSERT INTO cr_report(rep_id, title, descr, public_yn, menu_id, menu_approved_yn, report_xml, owner_id, create_id, create_date, maint_id, maint_date, dashboard_type_yn, dashboard_yn, folder_id) VALUES([rw.getReportID()], '[Utils.oracleSafe(rw.getReportName())]', '[Utils.oracleSafe(rw.getReportDescr())]', '[rw.isPublic()]', '[rw.getMenuID()]', '[rw.isMenuApproved()]', '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>', [rw.getOwnerID()], [rw.getCreateID()], STR_TO_DATE('[rw.getCreateDate()]', '[Globals.getTimeFormat()]'), [rw.getUpdateID()], STR_TO_DATE('[rw.getUpdateDate()]', '[Globals.getTimeFormat()]'), '[rw.isDashboardType()]', '[rw.getReportType().equals(AppConstants.RT_DASHBOARD)]',[rw.getFolderId()])
get.user.report.names = SELECT cr.rep_id, cr.title FROM cr_report cr WHERE coalesce(cr.owner_id, cr.create_id) = [userID]
@@ -127,7 +110,7 @@ download.all.insert = insert into cr_report_dwnld_log (user_id,rep_id,file_name,
#ReportWrapper.java
-report.wrapper.format = SELECT coalesce(cr.owner_id, cr.create_id) owner_id, cr.create_id, DATE_FORMAT(cr.create_date, '[Globals.getOracleTimeFormat()]') create_date, maint_id, DATE_FORMAT(cr.maint_date, '[Globals.getOracleTimeFormat()]') update_date, cr.menu_id, cr.menu_approved_yn FROM cr_report cr WHERE cr.rep_id= [reportID]
+report.wrapper.format = SELECT coalesce(cr.owner_id, cr.create_id) owner_id, cr.create_id, DATE_FORMAT(cr.create_date, '[Globals.getTimeFormat()]') create_date, maint_id, DATE_FORMAT(cr.maint_date, '[Globals.getTimeFormat()]') update_date, cr.menu_id, cr.menu_approved_yn FROM cr_report cr WHERE cr.rep_id= [reportID]
generate.subset.sql = SELECT [colNames.toString()] FROM (SELECT [colNames.toString()] FROM ([reportSQL]) AS x ) AS y
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties.oracle b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties.oracle
new file mode 100644
index 00000000..2c5af5e9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/conf/sql.properties.oracle
@@ -0,0 +1,282 @@
+#SQL Statements for OracleSQL
+
+#ReportLoader.java
+
+load.custom.report.xml = SELECT cr.report_xml FROM cr_report cr WHERE rep_id=?
+
+# need to copy to oracle
+load.remoteDB.schema = SELECT 'local' SCHEMA_ID, 'local' SCHEMA_DESC, null DATASOURCE_TYPE FROM DUAL union SELECT a.SCHEMA_ID, a.SCHEMA_DESC, DATASOURCE_TYPE FROM SCHEMA_INFO a where schema_id <> 'local' order by schema_id
+load.remoteDB.schema.where = SELECT a.SCHEMA_ID, a.SCHEMA_DESC, DATASOURCE_TYPE FROM SCHEMA_INFO a where schema_id = '[schema_id]'
+#formfield rendering
+
+formfield.id.name.sql.prefix=SELECT id, name FROM (
+formfield.id.name.sql=SELECT id, name
+
+formfield.id.name.sql.suffix=
+
+report.security.create= SELECT nvl(cr.owner_id, cr.create_id) AS owner_id, cr.create_id, TO_CHAR(cr.create_date, 'MM/dd/YYYY') create_date, maint_id, TO_CHAR(cr.maint_date, 'MM/dd/YYYY') update_date, cr.public_yn FROM cr_report cr WHERE cr.rep_id = [rw.getReportID()]
+
+db.update.report.xml = SELECT cr.rep_id, cr.report_xml FROM cr_report cr WHERE rep_id=? FOR UPDATE
+
+update.custom.report.rec = UPDATE cr_report SET title='[Utils.oracleSafe(rw.getReportName())]', descr='[Utils.oracleSafe(rw.getReportDescr())]', public_yn='[(rw.isPublic()]', menu_id='[rw.getMenuID()]', menu_approved_yn='[(rw.isMenuApproved()]', owner_id=[rw.getOwnerID()], maint_id=[rw.getUpdateID()], maint_date=TO_DATE('[rw.getUpdateDate()]', '[Globals.getTimeFormat()]'), dashboard_type_yn='[(rw.isDashboardType()]', dashboard_yn= '[(rw.getReportType().equals(AppConstants.RT_DASHBOARD)]' WHERE rep_id = [rw.getReportID()]
+
+is.report.already.scheduled = select rep_id from cr_report_schedule where rep_id = ?
+
+create.custom.report.rec = INSERT INTO cr_report(rep_id, title, descr, public_yn, menu_id, menu_approved_yn, report_xml, owner_id, create_id, create_date, maint_id, maint_date, dashboard_type_yn, dashboard_yn, folder_id) VALUES([rw.getReportID()], '[Utils.oracleSafe(rw.getReportName())]', '[Utils.oracleSafe(rw.getReportDescr())]', '[rw.isPublic()]', '[rw.getMenuID()]', '[rw.isMenuApproved()]', '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>', [rw.getOwnerID()], [rw.getCreateID()], TO_DATE('[rw.getCreateDate()]', '[Globals.getTimeFormat()]'), [rw.getUpdateID()], TO_DATE('[rw.getUpdateDate()]', '[Globals.getTimeFormat()]'), '[rw.isDashboardType()]', '[rw.getReportType().equals(AppConstants.RT_DASHBOARD)]',[rw.getFolderId()])
+
+get.user.report.names = SELECT cr.rep_id, cr.title FROM cr_report cr WHERE nvl(cr.owner_id, cr.create_id) = [userID]
+
+get.report.owner.id = SELECT nvl(cr.owner_id, cr.create_id) owner FROM cr_report cr WHERE rep_id = ?
+
+delete.report.record.log = DELETE FROM cr_report_log WHERE rep_id = [reportID]
+
+delete.report.record.users = DELETE FROM cr_report_schedule_users WHERE rep_id = [reportID]
+
+delete.report.record.schedule = DELETE FROM cr_report_schedule WHERE rep_id = [reportID]
+
+delete.report.record.access = DELETE FROM cr_report_access WHERE rep_id = [reportID]
+
+delete.report.record.email = DELETE FROM cr_report_email_sent_log WHERE rep_id = [reportID]
+
+delete.report.record.favorite = DELETE FROM cr_favorite_reports WHERE rep_id = [reportID]
+
+delete.report.record.report = DELETE FROM cr_report WHERE rep_id = [reportID]
+
+load.quick.links = select finalcr.rep_id, finalcr.title, finalcr.descr from (SELECT cr.rep_id, cr.title, cr.descr FROM (SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL (SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra LEFT JOIN cr_report cr ON cr.rep_id = ra.rep_id WHERE cr.menu_id LIKE '%[nvls(menuId)]%' AND cr.menu_approved_yn = 'Y' AND (nvl(cr.owner_id, cr.create_id) = [userID] OR cr.public_yn = 'Y' OR ra.read_only_yn IS NOT NULL) UNION SELECT cr.rep_id, cr.title, cr.descr FROM cr_report cr WHERE cr.menu_id LIKE '%[nvls(menuId)]%' AND (nvl(cr.owner_id, cr.create_id) = [userID] OR cr.public_yn = 'Y' or EXISTS (select * from fn_user_role where user_id=[userID] and role_id in (1)))) finalcr ORDER BY finalcr.title
+
+load.folder.reports = SELECT cr.rep_id, cr.rep_id report_id, ([rep_title_sql] || (CASE WHEN cr.public_yn = 'Y' THEN '' ELSE '[PRIVATE_ICON]' END)||cr.title||'</a>') title, cr.descr, (au.first_name||' '||au.last_name) owner_name, TO_CHAR(cr.create_date, 'MM/DD/YYYY') create_date, (CASE WHEN nvl(cr.owner_id, cr.create_id) = [userID] THEN 'N' ELSE nvl(ra.read_only_yn, 'Y') END) read_only_yn, DECODE(NVL(cr.owner_id, cr.create_id), [userID], 'Y', 'N') user_is_owner_yn FROM cr_report cr JOIN app_user au ON nvl(cr.owner_id, cr.create_id) = au.user_id AND cr.folder_id= '[folderId]' LEFT JOIN (SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL(SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra ON cr.rep_id = ra.rep_id
+
+load.folder.reports.user = AND nvl(cr.owner_id, cr.create_id) = [userID]
+
+load.folder.reports.publicsql = AND (nvl(cr.owner_id, cr.create_id) = [userID] OR cr.public_yn = 'Y' OR ra.read_only_yn IS NOT NULL)
+
+load.quick.download.links = SELECT a.file_name, b.title,to_char(a.dwnld_start_time, 'Dy DD-Mon-YYYY HH24:MI:SS') as time, a.dwnld_start_time FROM cr_report_dwnld_log a, cr_report b where a.user_id = [userID] and a.rep_id = b.rep_id and (a.dwnld_start_time) >= to_date(to_char(sysdate-24/24, 'mm/dd/yyyy'), 'mm/dd/yyyy') and a.record_ready_time is not null order by a.dwnld_start_time desc
+
+load.reports.to.schedule = SELECT cr.rep_id, Initcap(cr.title), cr.descr FROM cr_report cr, (SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL (SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra WHERE cr.rep_id = ra.rep_id (+) AND (cr.public_yn = 'Y' OR ra.read_only_yn IS NOT NULL or cr.owner_id = [userID] ) ORDER BY Initcap(cr.title)
+
+load.reports.to.add.in.dashboard = SELECT cr.rep_id, cr.title, cr.descr FROM cr_report cr, (SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL (SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra WHERE cr.rep_id = ra.rep_id (+) AND (nvl(cr.owner_id, cr.create_id) = [userID] OR cr.public_yn = 'Y' OR ra.read_only_yn IS NOT NULL) AND (cr.dashboard_yn = 'N' or cr.dashboard_yn is null) ORDER BY cr.title
+
+load.my.recent.links = select rep_id, title, descr, form_fields from ( select rownum, rep_id, title, descr, form_fields from (select cr.rep_id, cr.title, a.form_fields, cr.descr, a.log_time, a.user_id, a.action, a.action_value from cr_report_log a, cr_report cr where user_id = [userID] and action = 'Report Execution Time' and a.rep_id = cr.rep_id order by log_time desc) x where rownum <= 6 ) y where rownum >= 1
+
+create.report.log.entry = INSERT INTO cr_report_log (rep_id, log_time, user_id, action, action_value, form_fields) VALUES([reportID], SYSDATE, [userID], '[action]' , '[executionTime]', '[form_fields]')
+
+create.report.log.entry.exec.time = INSERT INTO cr_report_log (rep_id, log_time, user_id, action, action_value, form_fields) VALUES([reportID], sysdate+1/(24*60*60), [userID], '[action]' , '[executionTime]', '[formFields]')
+
+clear.report.log.entries = DELETE from cr_report_log WHERE rep_id = ? and user_id = ?
+
+load.report.log.entries = SELECT x.log_time, x.user_id, (CASE WHEN x.action = 'Report Execution Time' THEN '<a href=\"[AppUtils.getRaptorActionURL()]report.run.container&c_master='||x.rep_id||'&'||x.form_fields||'&fromReportLog=Y&display_content=Y&noFormFields=Y&refresh=Y\">'||x.action||'</a>' ELSE x.action END) action, (CASE WHEN x.action = 'Report Execution Time' THEN action_value ELSE 'N/A' END) time_taken, (CASE WHEN x.action = 'Report Execution Time' THEN '<a href=\"[AppUtils.getRaptorActionURL()]report.run.container&c_master='||x.rep_id||'&'||x.form_fields||'&fromReportLog=Y&display_content=Y&noFormFields=Y&refresh=Y\"><img src=\"[AppUtils.getImgFolderURL()]test_run.gif\" width=\"12\" height=\"12\" border=0 alt=\"Run report\"/></a>' ELSE 'N/A' END) run_image, x.name FROM (SELECT rl.rep_id, TO_CHAR(rl.log_time, 'Month DD, YYYY HH:MI:SS AM') log_time, rl.action_value, fuser.last_name ||', '||fuser.first_name name, rl.user_id, rl.action, rl.form_fields FROM cr_report_log rl, fn_user fuser WHERE rl.rep_id = [nvls(reportId)] and rl.action != 'Report Run' and fuser.user_id = rl.user_id ORDER BY rl.log_time DESC) x WHERE ROWNUM <= 100
+
+does.user.can.schedule.report = select crs.sched_user_id, count(*) from cr_report_schedule crs where sched_user_id = [userId] group by crs.sched_user_id having count(*) >= [Globals.getScheduleLimit()]
+
+does.user.can.schedule = select crs.schedule_id from cr_report_schedule crs where schedule_id = [scheduleId]
+
+get.system.date.time = select to_char(sysdate,'MM/dd/yyyy HH24:mi:ss') from dual
+
+get.next.day.date.time = select to_char(sysdate+1,'MM/dd/yyyy HH24:mi:ss') from dual
+
+get.next.fifteen.minutes.date.time = select to_char(sysdate+15/(24*60),'MM/dd/yyyy HH24:mi:ss') from dual
+
+get.next.thirty.minutes.date.time = select to_char(sysdate+30/(24*60),'MM/dd/yyyy HH24:mi:ss') from dual
+
+get.template.file = select template_file from cr_report_template_map where report_id = [reportId]
+
+load.pdf.img.lookup = select image_id, image_loc from cr_raptor_pdf_img
+
+load.action.img.lookup = select image_id, image_loc from cr_raptor_action_img
+
+#ActionHandler.java
+
+report.values.map.def.a = SELECT x FROM (SELECT DISTINCT
+
+report.values.map.def.b = TO_CHAR([colName], '[nvl(displayFormat, AppConstants.DEFAULT_DATE_FORMAT)]')
+
+report.values.map.def.c = [colName]
+
+report.values.map.def.d = x FROM [rdef.getTableById(tableId).getTableName()] WHERE [colName] IS NOT NULL ORDER BY 1) xx WHERE <= [Globals.getDefaultPageSize()]
+
+test.sched.cond.popup = SELECT 1 FROM DUAL WHERE EXISTS ([sql])
+
+download.all.email.sent = Select user_id, rep_id from CR_REPORT_EMAIL_SENT_LOG where rownum = 1 and gen_key='[pdfAttachmentKey.trim()]' and log_id =[report_email_sent_log_id.trim()] and (sysdate - sent_date) < 1
+
+download.all.gen.key = select schedule_id from cr_report_email_sent_log u where U.GEN_KEY = '[pdfAttachmentKey]'
+
+download.all.retrieve = SELECT au.user_id FROM (SELECT rs.schedule_id, rs.rep_id FROM cr_report_schedule rs WHERE rs.enabled_yn='Y' AND rs.run_date IS NOT NULL AND rs.schedule_id = [scheduleId]) x, cr_report r, app_user au WHERE x.rep_id = r.rep_id AND au.user_id IN (SELECT rsu.user_id FROM cr_report_schedule_users rsu WHERE rsu.schedule_id = x.schedule_id and rsu.schedule_id = [scheduleId] UNION SELECT ur.user_id FROM fn_user_role ur WHERE ur.role_id IN (SELECT rsu2.role_id FROM cr_report_schedule_users rsu2 WHERE rsu2.schedule_id = x.schedule_id and rsu2.schedule_id = [scheduleId]))
+
+download.all.insert = insert into cr_report_dwnld_log (user_id,rep_id,file_name,dwnld_start_time,filter_params) values (?,?,?,?,?)
+
+#ReportWrapper.java
+
+report.wrapper.format = SELECT NVL(cr.owner_id, cr.create_id) owner_id, cr.create_id, TO_CHAR(cr.create_date, '[Globals.getTimeFormat()]') create_date, maint_id, TO_CHAR(cr.maint_date, '[Globals.getTimeFormat()]') update_date, cr.menu_id, cr.menu_approved_yn FROM cr_report cr WHERE cr.rep_id=[reportID]
+
+generate.subset.sql = SELECT [colNames.toString()] FROM (SELECT ROWNUM rnum, [colNames.toString()] FROM ([reportSQL]) x ) y
+
+report.sql.only.first.part = SELECT rnum,[colNames.toString()] FROM (SELECT ROWNUM rnum, [colNames.toString()] FROM (
+
+report.sql.only.second.part.a = WHERE ROWNUM <= [endRow]
+
+report.sql.only.second.part.b = ) y WHERE rnum >= [startRow] and rownum <= ([startRow]+[pageSize]) ORDER BY rnum
+
+report.sql.only.second.part.b.noorderby = AND rnum >= [startRow]
+
+generate.sql.visual.select = SELECT
+
+generate.sql.visual.count = COUNT(*) cnt
+
+generate.sql.visual.dual = FROM DUAL
+
+#ReportRuntime.java
+
+load.crosstab.report.data = SELECT ROWNUM rnum, [colNames.toString()] FROM ([reportSQL])
+
+#RaptorRunHandler.java
+
+generate.sql.handler = select ROWNUM rnum, x.* from ([sql]) x where rownum <= 2
+
+generate.sql.select = SELECT [colNames.toString()] FROM (SELECT ROWNUM rnum, [colNames.toString()] FROM ([sql]) x
+
+#ReportSchedule.java
+
+load.schedule.data = SELECT rs.enabled_yn, TO_CHAR(rs.start_date, 'MM/DD/YYYY') start_date, TO_CHAR(rs.end_date, 'MM/DD/YYYY') end_date, TO_CHAR(rs.run_date, 'MM/DD/YYYY') run_date, NVL(TO_CHAR(rs.run_date, 'HH'), '12') run_hour, NVL(TO_CHAR(rs.run_date, 'MI'), '00') run_min, NVL(TO_CHAR(rs.run_date, 'AM'), 'AM') run_ampm, rs.recurrence, rs.conditional_yn, rs.notify_type, rs.max_row, rs.initial_formfields, rs.schedule_id, NVL(TO_CHAR(rs.end_date, 'HH'), '11') end_hour, NVL(TO_CHAR(rs.end_date, 'MI'), '45') end_min, NVL(TO_CHAR(rs.end_date, 'AM'), 'PM') end_ampm, encrypt_yn, attachment_yn FROM cr_report_schedule rs WHERE rs.rep_id = [reportID]
+
+load.schedule.getid = SELECT rsu.user_id, fuser.last_name||', '||fuser.first_name, fuser.login_id FROM cr_report_schedule_users rsu, fn_user fuser WHERE rsu.rep_id = [reportID] AND rsu.schedule_id = [getScheduleID()] and rsu.user_id IS NOT NULL and rsu.user_id = fuser.user_id
+
+load.schedule.users = SELECT rsu.role_id FROM cr_report_schedule_users rsu WHERE rsu.rep_id = [reportID] AND rsu.schedule_id = [getScheduleID()] AND rsu.role_id IS NOT NULL
+
+new.schedule.data = select SEQ_CR_REPORT_SCHEDULE.nextval from dual
+
+new.report.data = select SEQ_CR_REPORT.nextval from dual
+execute.update = DELETE cr_report_schedule_users WHERE rep_id = [reportID] and schedule_id = [getScheduleID()]
+
+execute.update.users = INSERT INTO cr_report_schedule_users (schedule_id, rep_id, user_id, role_id, order_no) VALUES([getScheduleID()], [reportID], [emailToUsers.get(i)).getId()], NULL, [(i + 1)])
+
+execute.update.roles = INSERT INTO cr_report_schedule_users (schedule_id, rep_id, user_id, role_id, order_no) VALUES([getScheduleID()], [reportID], NULL, [emailToRoles.get(i)).getId()], [((emailToUsers.size() + i + 1)])
+
+execute.update.activity = INSERT into cr_schedule_activity_log (schedule_id, notes, run_time) values ([getScheduleID()],'Submitted:Schedule',TO_DATE('[getRunDate()] [getRunHour()]:[getRunMin()] [getRunAMPM()]', 'MM/DD/YYYY HH:MI AM'))
+
+delete.schedule.data = SELECT 1 FROM cr_report_schedule WHERE rep_id = [reportID] and sched_user_id = [getScheduleUserID()] and schedule_id = [getScheduleID()]
+
+delete.schedule.data.users = DELETE from cr_report_schedule_users WHERE rep_id = [reportID] and schedule_id = [getScheduleID()]
+
+delete.schedule.data.id = DELETE FROM cr_report_schedule where rep_id = [reportID] and sched_user_id = [getScheduleUserID()] and schedule_id = [getScheduleID()]
+
+load.cond.sql = SELECT condition_large_sql FROM cr_report_schedule WHERE schedule_id=?
+
+load.cond.sql.select = SELECT condition_sql FROM cr_report_schedule WHERE schedule_id = [scheduleId]
+
+persist.cond.sql.update = update cr_report_schedule set condition_large_sql = EMPTY_CLOB() where schedule_id = [scheduleId]
+
+persist.cond.sql.large = SELECT condition_large_sql FROM cr_report_schedule cr WHERE schedule_id=? FOR UPDATE
+
+persist.cond.sql.set = update cr_report_schedule set condition_sql = ? where schedule_id = [scheduleId]
+
+#DataCache.java
+
+get.data.view.actions = SELECT ts.web_view_action FROM cr_table_source ts WHERE ts.web_view_action IS NOT NULL
+
+get.public.report.id.names = SELECT rep_id, title FROM cr_report WHERE public_yn = 'Y' ORDER BY title
+
+get.private.accessible.names.a = SELECT cr.rep_id, cr.title FROM cr_report cr WHERE cr.rep_id not in (select rep_id from cr_report_access cra where user_id = '[user_id]'
+
+get.private.accessible.names.if = OR role_id in (
+
+get.private.accessible.names.b = ) AND public_yn = 'N' and cr.owner_id = '[user_id]' order by 2
+
+get.group.accessible.names.a = SELECT cr.rep_id, cr.title FROM cr_report cr WHERE cr.rep_id in (select rep_id from cr_report_access cra where user_id = '[user_id]'
+
+get.group.accessible.names.b = ) AND public_yn = 'N' order by 2
+
+get.report.table.sources.a = SELECT table_name, display_name, pk_fields, web_view_action, large_data_source_yn, filter_sql FROM cr_table_source
+
+get.report.table.sources.where = where SOURCE_DB= '[dBInfo]'
+
+get.report.table.sources.if = where SOURCE_DB is null or SOURCE_DB = '[AppConstants.DB_LOCAL]'
+
+get.report.table.sources.else = ORDER BY table_name
+
+grab.report.table.a = SELECT ts.table_name, ts.display_name, ts.pk_fields, ts.web_view_action, ts.large_data_source_yn, ts.filter_sql FROM cr_table_source ts WHERE
+
+grab.report.table.if = ts.SOURCE_DB= '[dBInfo]'
+
+grab.report.table.else = (ts.SOURCE_DB is null or ts.SOURCE_DB = '[AppConstants.DB_LOCAL]')
+
+grab.report.table.b = minus SELECT ts.table_name, ts.display_name, ts.pk_fields, ts.web_view_action, ts.large_data_source_yn, ts.filter_sql from cr_table_source ts where table_name in (select table_name from cr_table_role where role_id not IN [sb.toString()]) and
+
+grab.report.table.c = ORDER BY 1
+
+get.report.table.crjoin = SELECT src_table_name, dest_table_name, join_expr FROM cr_table_join
+
+get.report.table.joins = SELECT tj.src_table_name, tj.dest_table_name, tj.join_expr FROM cr_table_join tj WHERE ((EXISTS (SELECT 1 FROM cr_table_role trs WHERE trs.table_name=tj.src_table_name AND trs.role_id IN [sb.toString()])) OR (NOT EXISTS (SELECT 1 FROM cr_table_role trs WHERE trs.table_name=tj.src_table_name))) AND ((EXISTS (SELECT 1 FROM cr_table_role trd WHERE trd.table_name=tj.dest_table_name AND trd.role_id IN [sb.toString()])) OR (NOT EXISTS (SELECT 1 FROM cr_table_role trd WHERE trd.table_name=tj.dest_table_name)))
+
+generate.report.table.col = SELECT a.table_name, a.column_name, a.data_type, a.label FROM user_column_def a WHERE a.table_name = '[tableName.toUpperCase()]' ORDER BY a.column_id
+
+generate.db.user.sql.a = SELECT utc.table_name, utc.column_name, utc.data_type,
+
+generate.db.user.sql.if = utc.column_name label FROM user_tab_columns utc
+
+generate.db.user.sql.else = nvl(x.label, utc.column_name) label FROM user_tab_columns utc
+
+generate.db.user.sql.b = WHERE utc.table_name = '[tableName.toUpperCase()]'
+
+generate.db.user.sql.c = AND utc.table_name = x.table_name AND utc.column_name = x.column_name
+
+generate.db.user.sql.d = ORDER BY utc.column_id
+
+#SearchHandler.java
+
+load.report.search.result = SELECT cr.rep_id, cr.rep_id report_id, [rep_title_sql] title, cr.descr, (au.first_name||' '||au.last_name) owner_name, TO_CHAR(cr.create_date, 'MM/DD/YYYY'), (CASE WHEN nvl(cr.owner_id, cr.create_id) = [userID] THEN 'N' ELSE nvl(ra.read_only_yn, 'Y') END) read_only_yn, (CASE WHEN nvl(cr.owner_id, cr.create_id) = [userID] THEN 'Y' ELSE 'N' END) user_is_owner_yn, (case when report_xml like '%<allowSchedule>N</allowSchedule>%' then 'N' when report_xml like '%<allowSchedule>Y</allowSchedule>%' or 1 = (select distinct 1 from cr_report_schedule where rep_id = cr.rep_id) then 'Y' else 'N' end) FROM cr_report cr JOIN fn_user au ON nvl (cr.owner_id, cr.create_id) = au.user_id [fReportID] [fReportName] LEFT JOIN(SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL (SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra ON ra.rep_id = cr.rep_id
+
+load.report.search.rep_id_sql = AND ROUND(cr.rep_id, 0) like nvl('%%', ROUND(cr.rep_id, 0))
+
+load.report.search.instr = AND INSTR('|'||cr.menu_id||'|', '|'||'[menuId]'||'|') > 0
+
+load.report.search.result.user = AND nvl(cr.owner_id, cr.create_id) = [userID]
+
+load.report.search.result.public = AND (nvl(cr.owner_id, cr.create_id) = [userID] OR cr.public_yn = 'Y' OR ra.read_only_yn IS NOT NULL)
+
+load.report.search.result.fav = AND cr.rep_id in (select rep_id from cr_favorite_reports where user_id = [userID]
+
+load.report.search.result.sort = ORDER BY DECODE(nvl(cr.owner_id, cr.create_id), [userID], ' ', upper(au.first_name||' '||au.last_name)), upper(cr.title)
+
+load.folder.report.result = SELECT cr.rep_id, cr.rep_id report_id, [rep_title_sql]||DECODE(cr.public_yn, 'Y', '', '[PRIVATE_ICON]')||cr.title||'</a>' title, cr.descr, au.first_name||' '||au.last_name owner_name, TO_CHAR(cr.create_date, 'MM/DD/YYYY') create_date, DECODE(NVL(cr.owner_id, cr.create_id), [userID], 'N', NVL(ra.read_only_yn, 'Y')) read_only_yn, DECODE(NVL(cr.owner_id, cr.create_id), [userID], 'Y', 'N') user_is_owner_yn FROM cr_report cr, app_user au, (SELECT rep_id, MIN(read_only_yn) read_only_yn FROM ((SELECT ua.rep_id, ua.read_only_yn FROM cr_report_access ua WHERE ua.user_id = [userID]) UNION ALL (SELECT ra.rep_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.role_id IN ([roleList.toString()]))) report_access GROUP BY rep_id) ra WHERE TO_CHAR(cr.rep_id) = nvl('[fReportID]', TO_CHAR(cr.rep_id)) AND UPPER(cr.title) LIKE UPPER('%[fReportName]%') AND nvl(cr.owner_id, cr.create_id) = au.user_id AND cr.rep_id = ra.rep_id (+)
+
+load.folder.report.result.sort = ORDER BY DECODE(nvl(cr.owner_id, cr.create_id), [userID], ' ', au.first_name||' '||au.last_name), cr.title
+
+#WizardProcessor.java
+
+process.filter.add.edit = '[argValue]' FROM dual
+
+#ReportDefinition.java
+
+persist.report.adhoc = SELECT [Globals.getAdhocReportSequence()].nextval FROM dual
+
+#Globals.java
+
+initialize.roles = SELECT 1 FROM dual WHERE EXISTS (SELECT 1 FROM cr_table_role)
+
+initialize.version = SELECT cr_raptor.get_version FROM dual
+
+# scheduler
+
+scheduler.available.schedules = SELECT x.rep_id, x.schedule_id, x.conditional_yn, x.condition_large_sql, x.notify_type, x.max_row, x.initial_formfields, x.processed_formfields, r.title, x.user_id FROM ( SELECT rs.rep_id, rs.schedule_id, rs.sched_user_id user_id, rs.conditional_yn, rs.condition_large_sql, rs.notify_type, rs.max_row, rs.initial_formfields, rs.processed_formfields FROM cr_report_schedule rs WHERE rs.enabled_yn='Y' AND rs.start_date <= [currentDate] AND (rs.end_date >= [currentDate] or rs.end_date is null ) AND rs.run_date IS NOT NULL ) x, cr_report r WHERE x.rep_id = r.rep_id
+
+random.string = select DBMS_RANDOM.STRING('X',DBMS_RANDOM.VALUE(20,25)) random from dual
+
+scheduler.user.emails = SELECT au.user_id FROM (SELECT rs.schedule_id, rs.rep_id FROM cr_report_schedule rs WHERE rs.enabled_yn='Y' AND rs.start_date <= sysdate AND trunc(rs.end_date+1)-1/86400 >= sysdate AND rs.run_date IS NOT NULL AND rs.schedule_id = [p_schedule_id] ) x, cr_report r, fn_user au WHERE x.rep_id = r.rep_id AND au.user_id IN (SELECT rsu.user_id FROM cr_report_schedule_users rsu WHERE rsu.schedule_id = x.schedule_id and rsu.schedule_id = [p_schedule_id] UNION SELECT ur.user_id FROM fn_user_role ur WHERE ur.role_id IN (SELECT rsu2.role_id FROM cr_report_schedule_users rsu2 WHERE rsu2.schedule_id = x.schedule_id and rsu2.schedule_id = [p_schedule_id]))
+
+# basic sql
+
+convert.to.raw = utl_raw.cast_to_raw
+
+seq.next.val = SELECT [sequenceName].nextval as ID FROM dual
+
+current.date.string = sysdate
+
+# report security
+report.user.access = SELECT ra.role_id, ra.user_id, ra.read_only_yn FROM cr_report_access ra WHERE ra.rep_id = [reportID]
+add.user.access = INSERT INTO cr_report_access (rep_id, order_no, role_id, user_id, read_only_yn) VALUES([reportID], IFNULL((select order_no from (SELECT MAX(order_no) AS order_no FROM cr_report_access WHERE rep_id=[reportID]) AS temp), 0)+1, NULL, [userID], '[readOnlyAccess]')
+update.user.access = UPDATE cr_report_access SET read_only_yn='[readOnlyAccess]' WHERE rep_id=[reportID] AND user_id=[userID]
+remove.user.access = DELETE FROM cr_report_access WHERE rep_id=[reportID] AND user_id=[userID]
+add.role.access = INSERT INTO cr_report_access (rep_id, order_no, role_id, user_id, read_only_yn) VALUES([reportID], IFNULL((select order_no from (SELECT MAX(order_no) AS order_no FROM cr_report_access WHERE rep_id=[reportID]) AS temp), 0)+1, [roleID], NULL, '[readOnlyAccess]')
+update.role.access = UPDATE cr_report_access SET read_only_yn='[readOnlyAccess]' WHERE rep_id=[reportID] AND role_id=[roleID]
+remove.role.access = DELETE FROM cr_report_access WHERE rep_id=[reportID] AND role_id=[roleID]
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/conf/fusion.properties b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
new file mode 100644
index 00000000..99b68cbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
@@ -0,0 +1,43 @@
+# validator settings
+#default_error_message = Default error message
+
+#login message
+login.error.hrid.empty = Login failed, please contact system administrator.
+login.error.hrid.not-found = User not found, please contact system administrator.
+login.error.user.inactive = Account is disabled, please contact system administrator.
+
+authentication_mechanism = BOTH
+
+user_attribute_name = user
+
+
+# Web Junction settings
+#web_junction_user_id_header_name = iv-user
+
+# User Session settings
+#user_attribute_name = user
+roles_attribute_name = roles
+role_functions_attribute_name = role_functions
+#client_device_attribute_name = client_device
+#client_device_emulation = false
+
+# menu settings
+menu_query_name = menuData
+#menu_properties_file_location = /WEB-INF/fusion/menu/
+application_menu_set_name = APP
+application_menu_attribute_name = applicationMenuData
+#application_menu_properties_name = menu.properties
+business_direct_menu_set_name = BD
+#business_direct_menu_properties_name = bd.menu.properties
+business_direct_menu_attribute_name = businessDirectMenuData
+
+# RAPTOR config settings
+#raptor_config_file_path = /WEB-INF/conf/
+
+# Role settings
+sys_admin_role_id = 1
+#sys_admin_role_function_delete_from_ui = true
+
+# Profile Search settings
+#profile_search_report_id=181
+#callable_profile_search_report_id=386
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/defs/definitions.xml b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/defs/definitions.xml
new file mode 100644
index 00000000..2e9c8bf6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/defs/definitions.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
+ "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
+
+<!-- This tiles definitions file is fusion/defs/definitions.xml. It maps
+ tokens used by SDK-core controllers to JSP file paths. To minimize upgrade
+ effort, this file should not be changed by on-boarding applications. -->
+
+<tiles-definitions>
+
+ <definition name="ebz_template" template="/WEB-INF/fusion/jsp/ebz_template.jsp">
+ <put-attribute name="title" value=""></put-attribute>
+ <put-attribute name="header"
+ value="/WEB-INF/fusion/jsp/ebz/ebz_header.jsp"></put-attribute>
+ <put-attribute name="body" value=""></put-attribute>
+ <put-attribute name="footer"
+ value="/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp"></put-attribute>
+ </definition>
+
+ <definition name="ds2_template" template="/WEB-INF/fusion/jsp/ds2/template.jsp">
+ <put-attribute name="title" value="report"></put-attribute>
+ <put-attribute name="header" value="/WEB-INF/fusion/jsp/ds2/header.jsp"></put-attribute>
+ <put-attribute name="body" value=""></put-attribute>
+ </definition>
+
+
+ <definition name="ebz_template_noheader_nofooter"
+ template="/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp">
+ <put-attribute name="body" value=""></put-attribute>
+ </definition>
+
+ <definition name="ebz_template_report_embedded"
+ template="/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp">
+ <put-attribute name="body" value=""></put-attribute>
+ </definition>
+
+ <definition extends="ebz_template" name="es_search_demo">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/jsp/es_search_demo.jsp"></put-attribute>
+ <put-attribute name="viewName" value="elastic_search"></put-attribute>
+ </definition>
+
+ <definition extends="ebz_template" name="es_suggest_demo">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/jsp/es_suggest_demo.jsp"></put-attribute>
+ <put-attribute name="viewName" value="elastic_search"></put-attribute>
+ </definition>
+
+ <definition extends="ebz_template" name="error">
+ <put-attribute name="body" value="/WEB-INF/jsp/error.jsp"></put-attribute>
+ <put-attribute name="viewName" value="error"></put-attribute>
+ </definition>
+
+ <!-- <definition name="notebook"
+ template="app/fusion/notebook-integration/scripts/view-models/notebook.htm" /> -->
+
+
+ <!-- <definition name="nbooktest"
+ template="app/fusion/notebook-integration/scripts/view-models/notebook-frame.html"/>
+ -->
+ <definition name="nbooktest"
+ template="app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-frame.html"/>
+
+ <definition extends="ebz_template" name="broadcast_list">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/jsp/broadcast_list.jsp"></put-attribute>
+ <put-attribute name="viewName" value="broadcast_list"></put-attribute>
+ </definition>
+ <definition extends="ebz_template" name="broadcast">
+ <put-attribute name="body" value="/WEB-INF/fusion/jsp/broadcast.jsp"></put-attribute>
+ <put-attribute name="viewName" value="broadcast"></put-attribute>
+ </definition>
+
+
+ <definition extends="ebz_template" name="chart_wizard">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/jsp/chart_wizard.jsp"></put-attribute>
+ <put-attribute name="viewName" value="chart_wizard"></put-attribute>
+ </definition>
+
+ <definition name="collaboration"
+ template="/WEB-INF/fusion/jsp/webrtc/collaboration.jsp" />
+ <!-- <definition name="user_profile_list" template="/app/fusion/scripts/view-models/admin-page/profile.html"
+ /> -->
+ <definition name="user_profile_list"
+ template="/app/fusion/scripts/DS2-view-models/ds2-profile/profile.html" />
+
+ <!-- <definition name="admin" template="/app/fusion/scripts/view-models/admin-page/admin.html"
+ /> -->
+ <definition name="openCollaboration"
+ template="/app/fusion/scripts/DS2-view-models/ds2-admin/collaboration.html" />
+ <definition name="workflows"
+ template="/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-landing.html" />
+ <definition name="report_dashboard"
+ template="/app/fusion/scripts/view-models/reportdashboard-page/src/report-dashboard.html" />
+
+ <definition name="ds2_sample"
+ template="/app/fusionapp/scripts/DS2-view-models/sampleDS2.html" />
+
+ <definition name="admin"
+ template="/app/fusion/scripts/DS2-view-models/ds2-admin/admin.html" />
+ <definition name="samplePage"
+ template="/app/fusion/scripts/DS2-view-models/ds2-samplePages/samplePage.html" />
+ <definition name="welcome"
+ template="/app/fusion/scripts/DS2-view-models/welcome.html" />
+
+ <definition extends="ds2_template" name="report_wizard">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/report_wizard.jsp"></put-attribute>
+ <put-attribute name="viewName" value="report_wizard"></put-attribute>
+ </definition>
+ <definition extends="ebz_template" name="wizard_schedule_only">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/wizard_schedule_only.jsp"></put-attribute>
+ <put-attribute name="viewName" value="wizard_schedule_only"></put-attribute>
+ </definition>
+
+ <definition extends="ds2_template" name="report_import">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/report_import.jsp"></put-attribute>
+ <put-attribute name="viewName" value="report_import"></put-attribute>
+ </definition>
+
+ <definition name="report"
+ template="/app/fusion/scripts/DS2-view-models/ds2-reports/all-reports.html" />
+
+ <definition extends="ebz_template" name="reportDS1">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/report_ebz.jsp"></put-attribute>
+ </definition>
+
+ <definition extends="ebz_template_report_embedded" name="report_embedded">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/report_ebz.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template" name="report_sample">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/report_sample.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="test_run_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/test_run_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="date_start_field_run_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="date_end_field_run_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="test_field_run_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/test_field_run_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="default_field_run_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/default_field_run_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_testrun_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_testrun_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_semaphore">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_semaphore.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_import_semaphore">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_import_semaphore.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_table_cols">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_table_cols.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_drill_down_report">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_drill_down_report.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template_noheader_nofooter" name="popup_sql">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/popup_sql.jsp"></put-attribute>
+ </definition>
+ <definition extends="ebz_template" name="error_page">
+ <put-attribute name="body"
+ value="/WEB-INF/fusion/raptor/error_page.jsp"></put-attribute>
+ </definition>
+ <definition name="data_out" template="/WEB-INF/fusion/jsp/data_out.jsp" />
+
+ <!-- <definition name="test_field_run_sql" template="/WEB-INF/fusion/raptor/test_field_run_sql.jsp"/>
+ <definition name="popup_testrun_sql" template="/WEB-INF/fusion/raptor/popup_testrun_sql.jsp"/> -->
+
+</tiles-definitions>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/.gitignore
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/.gitignore
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp
index d4e7810c..0b700867 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast.jsp
@@ -134,4 +134,4 @@ app.controller('broadcastController', function ($scope, modalService, $modal){
});
-</script>
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp
index 2f6c68b5..401f413b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/broadcast_list.jsp
@@ -76,7 +76,7 @@
</div>
</td>
<td att-table-body width="10%">
- <div ng-click="remove(message);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
+ <div ng-click="remove(message);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-trash"></a></div>
</td>
</tr>
@@ -198,4 +198,4 @@ app.controller('broadcastListController', function ($scope){
};
});
-</script>
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp
index f3fb7a74..f3fb7a74 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/data_out.jsp
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ds2/template.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ds2/template.jsp
new file mode 100644
index 00000000..ac210a3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ds2/template.jsp
@@ -0,0 +1,101 @@
+<%--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ --%>
+<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
+
+<!DOCTYPE html>
+<html>
+ <head>
+<%-- <%@ include file="/WEB-INF/fusion/jsp/ds2/meta.jsp" %> --%>
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-gridster/dist/angular-gridster.min.css">
+ <!-- digital-design-library must be loaded late -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/digital-design-library.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+
+ <!-- Common scripts -->
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+ <!-- Report Dashboard Specific items -->
+ <script src="app/fusion/ase/scripts/menus/bootstrap.min.js"></script>
+ <script src="app/fusion/ase/scripts/menus/jquery-ui.min.js"></script>
+ <script src="app/fusion/external/lodash/4.5.1/lodash.js"></script>
+ <script src="app/fusion/external/showdown/0.3.4/showdown.js"></script>
+
+ <!--<script src="app/fusion/external/angular-1.5/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.5/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.5/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.5/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.5/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.5/angular-cookies.min.js"></script>-->
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/ds2/js/digital-ng-library/digital-design-library.js"></script>
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <!-- EPSDK App scripts and common services -->
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src= "app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+
+ </head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+<%-- <div>
+ <tiles:insertAttribute name="header" />
+ </div> --%>
+
+ <div class="applicationWindow">
+ <br>
+ <div class="content" id="mContent">
+ <div class="body-content-jsp">
+ <tiles:insertAttribute name="body" />
+ </div>
+ </div>
+ <br>
+ <div ds2-Footer class="footer-container"></div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp
index 5a33314f..bd5206eb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp
@@ -18,29 +18,24 @@
================================================================================
--%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-<script src="app/fusion/external/ebz/js/footer.js"></script>
-<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
-
+<script src="app/fusion/external/ebz/js/footer.js"></script>
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
<div class="footerContainer" id="footerContainer">
<div class="footerWrapper" id="footerWrapper">
-
- <div class="footerItem">
-
- </div>
- <div class="attFooterInfo">
+ <div class="attFooterInfo" style="text-align: center;">
<div class="footerLastSection">
- <div id="attFooterLogo" class="attLogo" tabindex='0'></div>
-
- <br>
- <div class="privacyPolicy">
+ <div class="footerText">
+ <p class="copyright-text">
+ </p>
+ </div>
+ <div class="displayInline">
+ <a href="#" class="footer-logo">
+ </a>
</div>
</div>
</div>
</div>
</div>
-</div>
-
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp
index 05c07f0d..1d3ba8e7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp
@@ -21,15 +21,14 @@
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ page isELIgnored="false"%>
<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%>
-<%@ page import="org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties"%>
-<%@ page import="org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants"%>
+<%@ page import="org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties"%>
+<%@ page import="org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants"%>
<%@ page import="org.openecomp.portalsdk.core.domain.MenuData"%>
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
-<!-- Icons -->
-<link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
+
<script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
<script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
<script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
@@ -58,7 +57,7 @@
<%
String contactUsLink = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
- String portalUrl = redirectUrl.substring(0, redirectUrl.lastIndexOf('/')) + "/processSingleSignOn";
+ String portalUrl = redirectUrl.substring(0, redirectUrl.lastIndexOf('/')) + "/process_csp";
String getAccessLink = redirectUrl.substring(0, redirectUrl.lastIndexOf('/')) + "/get_access";
%>
<c:set var="returnPortalUrl" value="<%=portalUrl%>" />
@@ -107,9 +106,8 @@
<div parentmenu-tabs mega-menu="true" menu-items="megaMenuDataObject" style="height:55px;">
<div style="float:left">
<li class="megamenu__item" style="line-height:55px;" onclick="returnToPortal()">
-
-<!-- <a id='returnPortal' class="primaryMenuOptionLink" style="font-weight: 400 !important; font-family: Arial !important; font-size: 18px;">ECOMP</a>
- --> <strong style="font-weight: 400 !important; font-family: Arial !important; font-size: 18px;" id='returnPortal' >ECOMP Portal</strong>
+ <img src="app/fusion/external/ebz/images/logo.png" class="logo" ></span>
+> <strong style="font-weight: 400 !important; font-family: Omnes-ECOMP-W02, Arial !important; font-size: 18px;" id='returnPortal' >ECOMP Portal</strong>
</li>
<div menu-tabs mega-menu="true" tab-name="item.text" menu-item="item" active-menu="activeClickMenu.x"
ng-repeat="item in megaMenuDataObject" style="font-size: 18px;" ng-mousedown="loadFavorites()" >
@@ -186,7 +184,7 @@
</div>
<div>
<br>
- <p style='font-weight: 400; font-family: Arial !important;
+ <p style='font-weight: 400; font-family: Omnes-ECOMP-W02, Arial !important;
font-size: 18px; text-align: center; background-color: lightgray;
width: 400px; margin-left: 25%; margin-right: 25%;'>
Manage favorites on ECOMP Portal.
@@ -210,7 +208,7 @@
</div>
</div >
<li class="megamenu__item" style="line-height:55px;" ng-if="loadMenufail">
- <strong style="font-weight: 400 !important; font-family: Arial !important; font-size: 18px;" >Unable to load menus</strong>
+ <strong style="font-weight: 400 !important; font-family: Omnes-ECOMP-W02, Arial !important; font-size: 18px;" >Unable to load menus</strong>
</li>
<!-- <li class="megamenu__item" style="width: 20%;">&nbsp;</li>
--> </div>
@@ -218,7 +216,7 @@
<div style="float:right">
<li id="bcLoginSnippet" class="megamenu__item" style="width: 140px;" >
<div popover="loginSnippet.html" aria-label="Login Snippet" referby="loginSnippet" att-accessibility-click="13,32" popover-style="\" popover-placement="below" style="width: 200px;">
- <div class="ion-android-person login-snippet-icon" style="display:inline-block"></div>
+ <div class="icon-user-small login-snippet-icon"></div>
<div class="login-snippet-text" style="display: inline-block; font-size:12px; margin-left:5px;overflow: hidden; max-height: 31px; max-width:120px; padding-top: 0px; margin-top: 0px; white-space: nowrap;" ng-bind="userProfile.firstName"></div>
</div>
</li>
@@ -232,12 +230,16 @@
</div>
</div>
</div>
-
+ <div class="license-notification" id="license-notification">
+ <a href="javascript:void(0)" style="background-color:#bbb;" class="button button--small" tooltip="Please contact ECOMP Portal team to get the license" tooltip-placement="below" tooltip-style="light" tooltip-popup-delay="500" >
+ <span style="">{{app_name_full}}</span>
+ </a>
+ </div>
<div style="position: relative; color: black; top: 70px;">
<div ng-cloak>
<span ng-style="adjustHLeftMenu('burgerIcon')" style="z-index:998; position:fixed; left:0%; font-size:35px; margin-left:10px;text-decoration:none;">
<a ng-click="toggleDrawer();isOpen = !isOpen" href="javascript:void(0);" class="arrow-icon-left" >
- <span class="ion-navicon-round"></span></a>
+ <span class="icon-hamburger"></span></a>
<span ng-init="isOpen = true" ng-show="isOpen" style="font-size:16px; position:relative; top:-8px; left:-15px;">&nbsp&nbsp&nbsp {{app_name}}</span>
</span>
<div att-drawer drawer-slide="left" drawer-custom-top="{{drawer_custom_top}}px" drawer-size="200px" drawer-open="drawerOpen" drawer-custom-height="100%" >
@@ -283,7 +285,7 @@
}
});
app.controller("headerController", function($scope, $timeout, $log, $http, UserInfoService, $window, $cookies,LeftMenuService) {
- $log.debug('HeaderController started');
+ // $log.debug('HeaderController started');
$scope.jsonMenuData = [];
$scope.loadMenufail=false;
$scope.app_name = "";
@@ -389,23 +391,27 @@
var j = response;
try{
if(j && j !== "null" && j!== "undefined"){
- console.log("app name is " + $scope.app_name);
+ // console.log("app name is " + $scope.app_name);
$scope.app_name_full = j.data;
var processed_app_name = j.data;
+ if(processed_app_name.indexOf("[")<=-1) {
+ if (document.getElementById('license-notification')!=null)
+ document.getElementById('license-notification').style.display = "none";
+ }
var n = processed_app_name.length;
if (n > 15) {
n = 15;
}
$scope.app_name = processed_app_name.substr(0, n);
}else{
- throw "Get app_name respsone is not an object/is empty";
+ throw "Get app_name response is not an object/is empty";
}
}catch (e) {
console.log("error happened while trying to get app name "+e);
return;
}
},function(error){
- console.log("error happened while calling getAppName "+error);
+ console.log('getAppName failed', error);
});
$scope.getTopMenuStaticInfo();
@@ -588,13 +594,18 @@
}
}).error(function (response){
$log.error('REST API failed get_favorites' + response);
-
+ //createFavoriteErrorMenu() USED FOR LOCAL TESTING ONLY
+// $scope.createFavoriteErrorMenu();
});
}
$scope.createFavoriteErrorMenu=function() {
$scope.favoritesMenuItems = [
-
+// {
+// "menuId": "93",
+// "text": "XXX",
+// "url": "XXX"
+// }
];
$scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
$log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
@@ -639,69 +650,6 @@
"url": ""
},
{
- "menuId": 90,
- "column": 1,
- "text": "Google",
- "parentMenuId": 1,
- "url": "http://google.com"
- },
- {
- "menuId": 91,
- "column": 1,
- "text": "Mike Little's Coffee Cup",
- "parentMenuId": 2,
- "url": "http://coffee.com"
- },
- {
- "menuId": 92,
- "column": 2,
- "text": "Andy and his Astrophotgraphy",
- "parentMenuId": 3,
- "url": "http://nightskypix.com"
- },
- {
- "menuId": 93,
- "column": 1,
- "text": "JSONLint",
- "parentMenuId": 4,
- "url": "http://http://jsonlint.com"
- },
- {
- "menuId": 94,
- "column": 2,
- "text": "HROneStop",
- "parentMenuId": 4,
- "url": ""
- },
- {
- "menuId": 95,
- "column": 2,
- "text": "4th Level App4a R16",
- "parentMenuId": 4,
- "url": ""
- },
- {
- "menuId": 96,
- "column": 3,
- "text": "3rd Level App1c R200",
- "parentMenuId": 4,
- "url": "http://app1c.com"
- },
- {
- "menuId": 97,
- "column": 1,
- "text": "3rd Level App4b R16",
- "parentMenuId": 5,
- "url": "http://app4b.com"
- },
- {
- "menuId": 98,
- "column": 2,
- "text": "3rd Level App2b R16",
- "parentMenuId": 5,
- "url": "http://app2b.com"
- },
- {
"menuId": 99,
"column": 1,
"text": "Favorites",
@@ -719,7 +667,7 @@
childItemList = ${menu.childItemList};
parentList = ${menu.parentList};
}catch(err){
- console.log("error while getting left menu");
+ console.log("ebz_header: failed to get child/parent lists", err);
}
var pageUrl = window.location.href.split('/')[window.location.href.split('/').length-1];
@@ -767,11 +715,11 @@
if ($scope.drawerOpen) {
$scope.arrowShow = true;
if (document.getElementById('mContent')!=null)
- document.getElementById('mContent').style.marginLeft = "210px";
+ document.getElementById('mContent').style.marginLeft = "0px";
} else {
$scope.arrowShow = false;
if (document.getElementById('mContent')!=null)
- document.getElementById('mContent').style.marginLeft = "50px";
+ document.getElementById('mContent').style.marginLeft = "-150px";
}
};
//var drawerOpen = getCookie('drawerOpen');
@@ -796,4 +744,4 @@
return text;
}
});
-</script>
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html
new file mode 100644
index 00000000..ae5e13ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html
@@ -0,0 +1,115 @@
+<!--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ -->
+<script type="text/ng-template" id="loginSnippet.html">
+ <div style="line-height: normal; right: 167px; min-height: 200px; height: auto; width: auto; " ng-controller="loginSnippetCtrl" >
+ <div id="reg-header-snippet">
+ <div class="reg-profilePicture" style="min-height: 215px; width: auto; " id="reg-profile-links">
+ <div id="reg-profileImage">
+ <div style="clear: both; height: 80px; position: relative; width: 80px;">
+
+ <span style=" background-position: -1px -1px; height: 81px;left: 0;position: absolute;top: 0;width: 81px;">&nbsp;</span>
+ </div>
+ </div>
+ <div id="reg-logout-div">
+ <a class="reg-logout-btn" href="logout.htm">Log Out</a>
+ </div>
+ </div>
+ <div tabindex="0" class="reg-profileDetails" id="reg-profiledetails-id">
+ <ul class="reg-Details-table" style="list-style: none;">
+ <li><div class="reg-userName-table"><div id="reg-userName-table-row"><div id="reg-userName-table-cell"><h3 id="reg-userName" ng-bind="userProfile.fullName"></h3><span class="visuallyhidden">.</span></div></div></div></li>
+ <li><div class="reg-userEmail-label"><span class="reg-userEmail-label-spn">EMAIL<span class="visuallyhidden">:</span></span></div></li>
+ <li><div class="reg-userEmail-value"><span class="reg-userEmail-value-spn" ng-bind="userProfile.email"><span class="visuallyhidden">.</span></span></div></li>
+ <li><div class="reg-userRole-label"><span class="reg-userRole-label-spn">orgUserId<span class="visuallyhidden">:</span></span></div></li>
+ <li><div class="reg-userRole-value"><span class="reg-userRole-value-spn" ng-bind="userProfile.orgUserId"><span class="visuallyhidden"></span></span></div></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </script>
+ <script type="text/ng-template" id="chat_box.html">
+
+ <div style="width: auto;">
+
+ <div style="font-size: 24px; font-family: Omnes-ECOMP-W02, Arial;line-height: 26px;color: #444444;text-align: center;">
+ <span>Live Chat</span>
+ </div>
+
+ </div>
+ </script>
+
+<script>
+var loginSnippetCtrl = function ($scope,$http, $log,UserInfoService){
+ /*Define fields*/
+ $scope.userProfile={
+ firstName:'',
+ lastName:'',
+ fullName:'',
+ email:''
+ }
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
+ $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
+ if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
+ $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
+ if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
+ $scope.userProfile.email = userInfo.USER_EMAIL;
+
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoService.getFunctionalMenuStaticDetailSession()
+ .then(function (response) {
+ var j = response;
+ // console.log(response);
+ $scope.userProfile.fullName = response.userName;
+ $scope.userProfile.email = response.email;
+ });
+ }
+ /*getting user info from shared context*/
+ $scope.getUserName=function() {
+ var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('loginSnippet::getUserName: failed to get user info from shared context');
+ $scope.getUserNameFromSession();
+ }else{
+ // $log.info('Received User information from shared context',res);
+ var resData = res;
+ $scope.inputUserInfo(resData);
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ }
+ },
+ function(err) {
+ console.log('error');
+ }
+ );
+ };
+ /*call the get user info function*/
+ try{
+ $scope.getUserName();
+ }catch(err){
+ $log.info('Error while getting User information',err);
+ }
+}
+ </script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp
index 59b61d19..93f96369 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template.jsp
@@ -42,4 +42,4 @@
</div>
</div>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp
index 98dccb4c..a579fdc0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp
@@ -32,4 +32,4 @@
</div>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp
index 4281a063..4cdfe51d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp
@@ -45,4 +45,4 @@
</div>
</div>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp
index eae5324b..61458524 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_search_demo.jsp
@@ -66,7 +66,7 @@ app.controller('elasticSearchController',['$scope','$http',function ($scope,$htt
<div class="demoElas" ng-controller="elasticSearchController">
<div class="form-field" align="center">
<input type="text" placeholder="What are you looking for?" class="search__large-iconform" ng-model="searchText" ng-change="test()">
- <i class="ion-search">&nbsp;</i>
+ <i class="icon-search">&nbsp;</i>
</div>
<table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
@@ -94,4 +94,4 @@ app.controller('elasticSearchController',['$scope','$http',function ($scope,$htt
</tbody>
</table>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp
index 05cfaf55..abae598b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/es_suggest_demo.jsp
@@ -94,4 +94,4 @@ app.controller('elasticSearchController',['$scope','$http',function ($scope,$htt
</tbody>
</table>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp
index 5f550c68..ed50b5dd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/frame_insert.jsp
@@ -41,4 +41,4 @@
iFrameRef.css('border','none');
}
}
-</script>
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/include.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/include.jsp
index cd6a5e09..cd6a5e09 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/include.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/include.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp
index 3c4ff52a..0a361803 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/meta.jsp
@@ -33,4 +33,4 @@
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
-</head>
+</head> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html
index 0766cecd..0766cecd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html
index c163002d..c163002d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_role.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html
index ee0b5121..ee0b5121 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/popup_modal_rolefunction.html
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/sequence/details.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/sequence/details.jsp
new file mode 100644
index 00000000..eacdfbe0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/sequence/details.jsp
@@ -0,0 +1 @@
+<iframe style="border:none" src="app/fusion/sequence/view-models/details.html" height="700" width="1300"></iframe> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp
index ff6c985e..9bf0ed74 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/jsp/webrtc/collaboration.jsp
@@ -136,6 +136,7 @@
<script type="text/javascript" src="app/fusion/scripts/webrtc/RTCMultiConnection.js"></script>
<script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
<script type="text/javascript" src="app/fusion/scripts/layout/debug.js"></script>
+
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
@@ -151,6 +152,7 @@
<script src="app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js"></script>
<script src="app/fusion/scripts/att_angular_gridster/angular-gridster.js"></script>
<script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
+ <script type="text/javascript" src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script>
<style>
body{background-color:#fff;font-size:14px;font-size:.875rem;margin:0;padding:0px 0 20px;position:relative}
</style>
@@ -311,7 +313,7 @@
// var websocket = localStorage.getItem('notifySocket');
//if( websocket != null) {
// handling websocket peer broadcast session
- var currentUser = "${sessionScope.user.orgUserId}";
+ var currentUser = "${sessionScope.user.sbcid}";
var initialPageVisit = "${sessionScope.initialPageVisit}";
var remoteUser = '';
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml
index 28060a7c..28060a7c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Fusion.hbm.xml
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml
index 3d8852cb..3d8852cb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/orm/Workflow.hbm.xml
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp
index 0bd373b7..0bd373b7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_header_include.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp
index 5abbb5ad..5abbb5ad 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/custom_js_include.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp
index fd2f9c36..fd2f9c36 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp
index 69827262..69827262 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp
index 95c99f37..95c99f37 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/default_field_run_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp
index d5d25249..d5d25249 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/disclaimer.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp
index 8158e604..8158e604 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_include.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp
index 8ee73be0..8ee73be0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/error_page.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp
index c4fbe9e8..c4fbe9e8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/footer.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp
index 53959482..6838f3ac 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_drill_down_report.jsp
@@ -80,7 +80,28 @@
} // setParams
-//-->
+
+
+ window.onbeforeunload = check;
+ function check()
+ {
+ var opener = window.opener;
+ var newParams = collectValues();
+ //alert(newParams);
+ //console.log(newParams);
+ if(!newParams) {
+ if(opener) {
+ var oDom = opener.document;
+ var elem = oDom.getElementById("drillDownCtl");
+ var elements = elem.options;
+
+ for(var i = 0; i < elements.length; i++){
+ elements[i].selected = false;
+ }
+
+ }
+ }
+ } //-->
</script>
</head>
@@ -498,7 +519,8 @@
}
%>
//alert(newParams);
- setParams(newParams);
+ return newParams;
+
} // collectValues
function setCheckBoxValues() {
@@ -583,7 +605,7 @@
</tr>
<tr>
- <td colspan="3" align="center"><input type="Button" class=button value="Complete" onClick="collectValues()"></td>
+ <td colspan="3" align="center"><input type="Button" class=button value="Complete" onClick="setParams(collectValues())"></td>
</tr>
</table>
</form>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp
index d73a7fe2..d73a7fe2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_import_semaphore.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp
index 39eafb24..39eafb24 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_semaphore.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp
index c685bb13..c685bb13 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp
index 9dec6a53..9dec6a53 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_table_cols.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp
index a5dbd502..a5dbd502 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/popup_testrun_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp
index 81158047..81158047 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_csv.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp
index e5ae9dde..e5ae9dde 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_pdf.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp
index a82470d8..a82470d8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_download_xls.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp
index 8d42b65b..8d42b65b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_ebz.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp
index 014f98ac..bb62def0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_import.jsp
@@ -26,10 +26,25 @@
<title>Import</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/raptor.css">
+ <style>
+ #page-content {
+ width:80%
+ }
+
+ table#pageContentTable,
+ table#pageContentTable td,
+ table#pageContentTable tr
+ {
+ border: none !important;
+ }
+ </style>
+</head>
<br><br>
+<body>
+<div id="page-content" style="margin-right:20px">
<form name="forma" action="<%= AppUtils.getBaseURL() %>" method="post">
<input type="hidden" name="action" value="raptor">
<input type="hidden" name="<%= AppConstants.RI_ACTION %>" value="report.import.save">
@@ -59,8 +74,8 @@
</form>
-<jsp:include page="disclaimer.jsp" flush="true" />
-
+<%-- <jsp:include page="disclaimer.jsp" flush="true" /> --%>
+</div>
</body>
</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp
index cfbfad14..cfbfad14 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_sample.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp
index 480bdbcb..480bdbcb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_search.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp
index cdfe943a..8448b249 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/report_wizard.jsp
@@ -36,14 +36,12 @@
<%@ page import="org.openecomp.portalsdk.analytics.model.*" %>
<%@ page import="org.openecomp.portalsdk.analytics.model.base.*" %>
<%@ page import="org.openecomp.portalsdk.analytics.model.definition.*" %>
-<%@ page import="org.openecomp.portalsdk.analytics.model.runtime.*" %>
+<%@ page import="org.openecomp.portalsdk.analytics.model.runtime.*" %>
<%@ page import="org.openecomp.portalsdk.analytics.controller.*" %>
<%@ page import="org.openecomp.portalsdk.analytics.system.*" %>
<%@ page import="org.openecomp.portalsdk.analytics.util.*" %>
<%@ page errorPage="error_page.jsp" %>
-<html>
- <body>
<script language="Javascript" src="<%= AppUtils.getBaseFolderURL() %>js/form-field-tooltip.js"></script>
<script language="Javascript" src="<%= AppUtils.getBaseFolderURL() %>js/other_scripts.js"></script>
<style>
@@ -117,7 +115,21 @@ td, th {
<jsp:include page="error_include.jsp" flush="true" />
-<table width="100%" >
+
+<style>
+#page-content {
+ width:80%
+}
+
+table#pageContentTable,
+table#pageContentTable td,
+table#pageContentTable tr
+{
+ border: none !important;
+}
+</style>
+<div id="page-content">
+<table id="pageContentTable" width="100%" >
<tr><td id="folderTreeContainer" width="1%" height='300' valign='top' ><table>
<!--<jsp:include page="tree/folderNav.jsp" flush="true" >
<jsp:param name="doCollapseTree" value="Y" />
@@ -136,7 +148,7 @@ td, th {
<input type="hidden" id="<%= AppConstants.RI_WIZARD_ACTION %>" name="<%= AppConstants.RI_WIZARD_ACTION %>" value="<%= AppConstants.WA_BACK %>">
<input type="hidden" name="<%= AppConstants.RI_JAVASCRIPT_ITEM_ID %>" value="">
-<table width="94%" border="0" cellspacing="0" cellpadding="0" align=center>
+<table style="border: none !important;" width="94%" border="0" cellspacing="0" cellpadding="0" align=center>
<tr><td>
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="margin: 0px;">
<tr>
@@ -214,7 +226,7 @@ td, th {
<% } %>
</td></tr><tr><td>
- <table width="100%" border="0" cellspacing="1" cellpadding="3">
+ <table style="border: none !important;" width="100%" border="0" cellspacing="1" cellpadding="3">
<tr>
<td width="10%" align="right">
&nbsp;
@@ -246,6 +258,7 @@ td, th {
</td>
</tr>
</table>
+</div>
<%--<jsp:include page="disclaimer.jsp" flush="true" />--%>
<script>
//document.getElementById('loadingMessageDiv').style.display='none';
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp
index 2fdcee46..2fdcee46 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_field_run_sql.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp
index 1c30437b..1c30437b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/test_run_sql.jsp
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/folderNav.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/folderNav.jsp
new file mode 100644
index 00000000..38951994
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/folderNav.jsp
@@ -0,0 +1,464 @@
+<%@page import="org.openecomp.portalsdk.analytics.system.AppUtils" %>
+<%@page import="org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime"%>
+<%@page import="org.openecomp.portalsdk.analytics.util.AppConstants"%>
+<%@page import="org.openecomp.portalsdk.analytics.system.Globals"%>
+
+<%
+ boolean isFolderAllowed = false;
+ ReportRuntime rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
+ boolean adminUser = AppUtils.isAdminUser(request);
+ if (Globals.isFolderTreeAllowed()) {
+ if(adminUser) {
+ isFolderAllowed = true;
+ } else if (!Globals.isFolderTreeAllowedOnlyForAdminUsers()) {
+ isFolderAllowed = true;
+ } else isFolderAllowed = false;
+ }
+
+
+
+%>
+
+
+<script src='dwr/engine.js'></script>
+<script src='dwr/util.js'></script>
+<script src='dwr/interface/folderNavAjax.js'></script>
+
+
+<script>
+ var imgFolder = '<%=AppUtils.getImgFolderURL()%>';
+ var isFolderAllowed = '<%= isFolderAllowed%>';
+</script>
+<script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/ajax.js"></script>
+<script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/context-menu.js"></script>
+<script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/drag-drop-folder-tree.js">
+<script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/raptor.js">
+</script>
+<link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/raptor.css">
+<link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/tree/drag-drop-folder-tree.css">
+<link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/tree/context-menu.css">
+<style type="text/css">
+/* CSS for the demo */
+img{
+ border:0px;
+}
+</style>
+<script>
+ var doCollapse = '<%=request.getParameter("doCollapseTree")%>';
+ var selectedFolderId;
+ var ajaxObjects = new Array();
+
+ // Use something like this if you want to save data by Ajax.
+ function saveMyTree()
+ {
+ saveString = treeObj.getNodeOrders();
+ alert(saveString);
+ var ajaxIndex = ajaxObjects.length;
+ ajaxObjects[ajaxIndex] = new sack();
+ var url = 'tree';
+ //var url = 'tree';
+ ajaxObjects[ajaxIndex].requestFile = url; // Specifying which file to get
+ ajaxObjects[ajaxIndex].onCompletion = function() { saveComplete(ajaxIndex); } ; // Specify function that will be executed after file has been found
+ ajaxObjects[ajaxIndex].runAJAX(url); // Execute AJAX function
+
+ }
+ function saveComplete(index)
+ {
+ alert(ajaxObjects[index].response);
+ }
+
+
+ // Call this function if you want to save it by a form.
+ function saveMyTree_byForm()
+ {
+ displayFolderInfo();
+ var data=folderNavAjax.saveFolderStructure(treeObj.getNodeOrders(), "<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+
+ }
+
+ function cancelMyTree_byForm(){
+ //document.treeFrm.submit();
+ displayFolderInfo();
+ var data=folderNavAjax.getFolderListString("<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+ }
+
+ function deleteMyTree_byForm()
+ {
+ //document.treeForm.submit();
+ displayFolderInfo();
+ var data=folderNavAjax.deleteFolderStructure(document.treeFrm.deleteIds.value, "<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+ }
+
+ function addMyTree_byForm()
+ {
+ //document.treeFrm.submit();
+ displayFolderInfo();
+ selectedFolderId = document.treeFrm.saveString.value;
+ var data=folderNavAjax.createNewFolder(document.treeFrm.saveString.value, document.treeFrm.newName.value, "<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+
+ }
+
+ function renameMyTree_byForm()
+ {
+ //document.treeFrm.submit();
+ displayFolderInfo();
+ var data=folderNavAjax.renameFolder(document.treeFrm.renameId.value, document.treeFrm.newName.value, "<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+
+ }
+
+ function createFolder(){
+ if(JSTreeObj.selectedItem == null || JSTreeObj.selectedItem.parentNode.id.substr(0,3) == '000')
+ return;
+ if (JSTreeObj.isAddAllowed(JSTreeObj.selectedItem.parentNode.id) == false){
+ alert("You do not have rights on this folder");
+ return;
+ }
+ selectedFolderId = JSTreeObj.selectedItem.parentNode.id;
+ displayFolderInfo();
+ if (JSTreeObj.addItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem) == false){
+ hideFolderInfo();
+ }
+ }
+
+ function deleteFolder(){
+ if(JSTreeObj.selectedItem == null) {
+ return;
+ }
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ if (JSTreeObj.isDeleteAllowed(id) == false){
+ alert("You do not have rights on this folder");
+ return;
+ }
+ if(id.substr(0,3) == '000') {
+ return;
+ }
+ displayFolderInfo();
+ if (JSTreeObj.deleteItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem) == false){
+ hideFolderInfo();
+ }
+ }
+
+ function runReport()
+ {
+
+ if (JSTreeObj == null || JSTreeObj.selectedItem == null){
+ return;
+ }
+
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ if(id.substr(0,3) != '000') {
+ return;
+ }
+ //displayFolderInfo();
+ id = id.substr(3, id.length);
+ addBreadCrumb(true, id);
+ if (window.frames && window.frames[0] && window.frames[0].name == 'content_Iframe'){
+ window.frames[0].location='<%= AppUtils.getRaptorActionURL() %>report.run&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ }
+ else if (document.getElementById('searchContentContainer')){
+ document.getElementById('searchContentContainer').innerHTML = "<div id='breadCrumbArea'> </div><iframe name='content_Iframe' frameborder='0' id='content_Iframe' src='<%= AppUtils.getRaptorActionURL() %>report.run&c_master=" + id + "&PAGE_ID=HOME&refresh=Y' width='100%' height='450' ></iframe>";
+ //document.getElementById('content_Iframe').height=document.body.offsetHeight - 210;
+ resizeWindow();
+ document.getElementById('content_Iframe').location = '<%= AppUtils.getRaptorActionURL() %>report.run&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+
+ }else{
+
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.run&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+
+ }
+ function editReport()
+ {
+ if (JSTreeObj == null || JSTreeObj.selectedItem == null){
+ return;
+ }
+
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ if(id.substr(0,3) != '000') {
+ return;
+ }
+ id = id.substr(3, id.length);
+ if (window.frames && window.frames[0] && window.frames[0].name == 'content_Iframe'){
+ window.frames[0].location='<%= AppUtils.getRaptorActionURL() %>report.edit&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ }
+ else if (document.getElementById('searchContentContainer')){
+ document.getElementById('searchContentContainer').innerHTML = "<div id='breadCrumbArea'> </div><iframe name='content_Iframe' frameborder='0' id='content_Iframe' src='<%= AppUtils.getRaptorActionURL() %>report.edit&c_master=" + id + "&PAGE_ID=HOME&refresh=Y' width='100%' height='450' ></iframe>";
+ //document.getElementById('content_Iframe').height=document.body.offsetHeight - 210;
+ resizeWindow();
+ document.getElementById('content_Iframe').location = '<%= AppUtils.getRaptorActionURL() %>report.edit&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+
+ }else{
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.edit&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+ }
+ function deleteReport()
+ {
+ if (JSTreeObj == null || JSTreeObj.selectedItem == null){
+ return;
+ }
+
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ if(id.substr(0,3) != '000') {
+ return;
+ }
+ id = id.substr(3, id.length);
+ if (window.frames && window.frames[0] && window.frames[0].name == 'content_Iframe'){
+ window.frames[0].location='<%= AppUtils.getRaptorActionURL() %>report.delete&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ }
+ else if (document.getElementById('searchContentContainer')){
+ document.getElementById('searchContentContainer').innerHTML = "<div id='breadCrumbArea'> </div><iframe name='content_Iframe' frameborder='0' id='content_Iframe' src='<%= AppUtils.getRaptorActionURL() %>report.delete&c_master=" + id + "&PAGE_ID=HOME&refresh=Y' width='100%' height='450' ></iframe>";
+ //document.getElementById('content_Iframe').height=document.body.offsetHeight - 210;
+ resizeWindow();
+ document.getElementById('content_Iframe').location = '<%= AppUtils.getRaptorActionURL() %>report.delete&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+
+ }
+ else{
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.delete&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+
+ }
+ function createReport()
+ {
+ if (JSTreeObj == null || JSTreeObj.selectedItem == null){
+ return;
+ }
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ addBreadCrumb(false, id);
+ if (window.frames && window.frames[0] && window.frames[0].name == 'content_Iframe'){
+ window.frames[0].location='<%= AppUtils.getRaptorActionURL() %>report.create&folder_id=' + id + '&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ }
+ else if (document.getElementById('searchContentContainer')){
+ document.getElementById('searchContentContainer').innerHTML = "<div id='breadCrumbArea'> </div><iframe name='content_Iframe' frameborder='0' id='content_Iframe' src='<%= AppUtils.getRaptorActionURL() %>report.create&folder_id=" + id + "&c_master=' + id + '&PAGE_ID=HOME&refresh=Y' width='100%' height='450' ></iframe>";
+ //document.getElementById('content_Iframe').height=document.body.offsetHeight - 210;
+ resizeWindow();
+ document.getElementById('content_Iframe').location = '<%= AppUtils.getRaptorActionURL() %>report.create.container&folder_id=' + id + '&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+
+ }
+ else{
+ displayFolderInfo();
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.create.container&folder_id=' + id + '&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+ }
+ function getFolderReports(id)
+ {
+ addBreadCrumb(false, id);
+ if (window.frames && window.frames[0] && window.frames[0].name == 'content_Iframe'){
+ window.frames[0].location='<%= AppUtils.getRaptorActionURL() %>report.folderlist_iframe&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ }
+ else if (document.getElementById('searchContentContainer')){
+ document.getElementById('searchContentContainer').innerHTML = "<div id='breadCrumbArea'> </div><iframe name='content_Iframe' frameborder='0' id='content_Iframe' src='<%= AppUtils.getRaptorActionURL() %>report.folderlist_iframe&c_master=" + id + "&PAGE_ID=HOME&refresh=Y' width='100%' height='450' ></iframe>";
+ //document.getElementById('content_Iframe').height=document.body.offsetHeight - 210;
+ resizeWindow();
+ document.getElementById('content_Iframe').location = "<%= AppUtils.getRaptorActionURL() %>report.folderlist_iframe&c_master=" + id + "&PAGE_ID=HOME&refresh=Y";
+
+ }
+ else{
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.folderlist&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+ }
+
+ function getAllFolderReports()
+ {
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ document.treeFrm.action='<%= AppUtils.getRaptorActionURL() %>report.folderlist&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.treeFrm.submit();
+ }
+
+
+ function displayFolderInfo()
+ {
+ var infoDiv = document.getElementById('loadingMessageDiv');
+ if (infoDiv == null)
+ return;
+ infoDiv.style.left = document.body.offsetWidth - 100 ;
+ infoDiv.style.top = document.getElementById('scrollableTable').style.top;
+ infoDiv.style.display='block';
+ }
+ function hideFolderInfo()
+ {
+ var infoDiv = document.getElementById('loadingMessageDiv');
+ if (infoDiv == null)
+ return;
+ infoDiv.style.display='none';
+ }
+
+ function displayTree(id){
+ if (isFolderAllowed ){
+ if (id != null)
+ selectedFolderId = id;
+ if (document.getElementById('reportFolderTree') == null){
+ displayFolderInfo();
+ var data=folderNavAjax.getFolderListString("<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+ }
+ document.getElementById('expandedTree').style.display='block';
+ document.getElementById('collapsedTree').style.display='none';
+ if (document.getElementById('folderTreeContainer'))
+ document.getElementById('folderTreeContainer').width="25%";
+
+ //document.getElementById('scrollableTable').style.height=window.screen.height - 320;
+ //document.getElementById('scrollableTable').style.height=document.body.offsetHeight - 260;
+ resizeWindow();
+ folderNavAjax.displayTree();
+ }
+
+
+ }
+ function hideTree(){
+ document.getElementById('expandedTree').style.display='none';
+ document.getElementById('collapsedTree').style.display='block';
+ //GET BREAD CRUMBS and assign
+ if (document.getElementById('folderTreeContainer'))
+ document.getElementById('folderTreeContainer').width="2px";
+ folderNavAjax.hideTree();
+ }
+ function refreshTree(id){
+
+ if (isFolderAllowed ){
+ if (id != null)
+ selectedFolderId = id;
+ displayFolderInfo();
+ var data=folderNavAjax.getFolderListString("<%=AppUtils.getUserID(request)%>", fillFolderStructure);
+
+ document.getElementById('expandedTree').style.display='block';
+ document.getElementById('collapsedTree').style.display='none';
+ if (document.getElementById('folderTreeContainer'))
+ document.getElementById('folderTreeContainer').width="25%";
+
+ //document.getElementById('scrollableTable').style.height=document.body.offsetHeight - 210;
+ resizeWindow();
+ folderNavAjax.displayTree(selectedFolderId);
+ }
+ }
+ function addBreadCrumb(isReport, id){
+ // if (id != null)
+ // var data=folderNavAjax.getBreadCrumb(isReport, id, addBreadCrumbCallback);
+
+ }
+ function addBreadCrumbCallback(data){
+ var collapsedTree = document.getElementById('breadCrumbArea');
+ if (collapsedTree == null)
+ return;
+ collapsedTree.innerHTML = "<font class=rtabletext style='background-color:white'>" + data + "</font>";
+ }
+ function collapseAllTree(){
+ treeObj.collapseAll();
+ }
+</script>
+
+<form name='treeFrm' method='post'>
+
+ <input type='hidden' id='newName' name='newName'/>
+ <input type='hidden' id='saveString' name='saveString'/>
+ <input type='hidden' id='deleteIds' name='deleteIds'/>
+ <input type='hidden' id='renameId' name='renameId'/>
+
+
+ <tr id="def" height="0">
+ <td colspan="10"></td>
+ </tr>
+
+ <tr width="100%" ><td valign='top' width='300'>
+ <% if(isFolderAllowed) { %>
+ <div id="expandedTree" style="position:absoulte;top:0;width:100%;height:25px;display:none;">
+ <table width="100%" border="0" cellspacing="1" align="left">
+ <tr>
+ <td colspan=2 align="right"><img border="0" src="<%= AppUtils.getImgFolderURL() %>tree/grnarrowleft.gif" onClick="javascript:hideTree()" alt='Hide Folder Tree' style='cursor:hand'>
+ &nbsp;&nbsp;&nbsp;
+ </td>
+
+ </tr>
+ <tr>
+ <td colspan=3>
+ <div id="scrollableTable" class="scrollableTable" style="position:absoulte;top:0;width:100%;height:430px;display:block;overflow:scroll">
+ <table id="folderTree" width="100%" border="0" cellspacing="1" align="center">
+ <tr>
+ <td nowrap>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id='loadingMessageDiv' style="position:absolute;top:150;left:650;width:40px;height:25px;display:none">
+ <table><tr bgcolor='red'><td class=rcolheader> Loading...</td></tr></table>
+ </div>
+
+ </td>
+ </tr>
+ <tr>
+ <td class=rtabletext width='100%'>
+ <a href="#" onclick='javascript:createFolder();'>New Folder</a> |
+ <a href="#" onclick='javascript:deleteFolder();'>Delete Folder</a> |
+ <a href="#" onclick='javascript:runReport();'>Run</a> |
+ <a href="#" onclick="treeObj.collapseAll()">Collapse</a> |
+ <a href="#" onclick="treeObj.expandAll()">Expand</a> |
+ <a href="#" onclick="javascript:refreshTree()">Refresh Tree</a>
+ </td>
+ <td ></td>
+ </tr>
+
+ </table>
+ </div>
+ <% } %>
+
+
+ </td></tr>
+ <% if(isFolderAllowed) { %>
+ <div id="collapsedTree" style="position:absolute;top=122;display:block;width:550">
+ <img border="0" src="<%= AppUtils.getImgFolderURL() %>tree/grnarrowright.gif" onClick="javascript:displayTree()" alt='Show Folder Tree' style='cursor:hand'>
+ </div>
+ <% } %>
+
+
+
+</form>
+
+
+<script type="text/javascript">
+
+ <% if(isFolderAllowed) { %>
+ document.body.scroll="no";
+ <% } %>
+
+ //window.onscroll = floatMenu;
+ window.onresize = resizeWindow;
+
+ function floatMenu()
+ {
+ var elem = document.getElementById("def");
+ var sy = document.body.scrollTop;
+ //elem.style.left = startX;
+ if (sy == null || sy == 0)
+ sy = 1;
+ elem.height = sy ;
+ }
+
+
+ function fillFolderStructure(data){
+ document.getElementById("folderTree").childNodes[0].childNodes[0].childNodes[0].innerHTML=data;
+ initializeTree();
+ hideFolderInfo();
+
+ }
+
+ function initializeTree(){
+ treeObj = new JSDragDropTree();
+ treeObj.setTreeId('reportFolderTree');
+ treeObj.setMaximumDepth(7);
+ treeObj.setMessageMaximumDepthReached('Maximum depth reached'); // If you want to show a message when maximum depth is reached, i.e. on drop.
+ treeObj.initTree(selectedFolderId);
+ treeObj.expandAll();
+ treeObj.collapseAll();
+ if (selectedFolderId && selectedFolderId != '0')
+ treeObj.showSelectedNode(selectedFolderId);
+
+ }
+
+ if (doCollapse == 'N')
+ refreshTree();
+</script>
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/testTree.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/testTree.jsp
new file mode 100644
index 00000000..1521790d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/tree/testTree.jsp
@@ -0,0 +1,229 @@
+<%@page import="org.openecomp.portalsdk.analytics.system.AppUtils" %>
+
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <jsp:include page="header.jsp" flush="true" />
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
+ <title>Folder tree with Drag and Drop capabilities</title>
+ <script>
+ var imgFolder = '<%=AppUtils.getImgFolderURL()%>';
+ </script>
+ <script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/ajax.js"></script>
+ <script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/context-menu.js"></script>
+ <script type="text/javascript" src="<%= AppUtils.getBaseFolderURL() %>js/tree/drag-drop-folder-tree.js">
+
+ /************************************************************************************************************
+ (C) www.dhtmlgoodies.com, July 2006
+
+ Update log:
+
+
+ This is a script from www.dhtmlgoodies.com. You will find this and a lot of other scripts at our website.
+
+ Terms of use:
+ You are free to use this script as long as the copyright message is kept intact.
+
+ For more detailed license information, see http://www.dhtmlgoodies.com/index.html?page=termsOfUse
+
+ Thank you!
+
+ www.dhtmlgoodies.com
+ Alf Magne Kalleland
+
+ ************************************************************************************************************/
+ </script>
+ <link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/raptor.css">
+ <link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/tree/drag-drop-folder-tree.css">
+ <link rel="stylesheet" type="text/css" href="<%= AppUtils.getBaseFolderURL() %>css/tree/context-menu.css">
+
+ <style type="text/css">
+ /* CSS for the demo */
+ img{
+ border:0px;
+ }
+ </style>
+ <script type="text/javascript">
+ //--------------------------------
+ // Save functions
+ //--------------------------------
+ var ajaxObjects = new Array();
+
+ // Use something like this if you want to save data by Ajax.
+ function saveMyTree()
+ {
+ saveString = treeObj.getNodeOrders();
+ alert(saveString);
+ var ajaxIndex = ajaxObjects.length;
+ ajaxObjects[ajaxIndex] = new sack();
+ var url = 'tree';
+ //var url = 'tree';
+ ajaxObjects[ajaxIndex].requestFile = url; // Specifying which file to get
+ ajaxObjects[ajaxIndex].onCompletion = function() { saveComplete(ajaxIndex); } ; // Specify function that will be executed after file has been found
+ ajaxObjects[ajaxIndex].runAJAX(url); // Execute AJAX function
+
+ }
+ function saveComplete(index)
+ {
+ alert(ajaxObjects[index].response);
+ }
+
+
+ // Call this function if you want to save it by a form.
+ function saveMyTree_byForm()
+ {
+ document.myForm.elements['saveString'].value = treeObj.getNodeOrders();
+ document.myForm.elements['task'].value = 'save';
+ document.myForm.submit();
+ }
+
+ function cancelMyTree_byForm(){
+ document.myForm.elements['task'].value = '';
+ document.myForm.submit();
+ }
+
+ function deleteMyTree_byForm()
+ {
+ document.myForm.elements['task'].value = 'delete';
+ document.myForm.submit();
+ }
+
+ function addMyTree_byForm()
+ {
+ document.myForm.elements['task'].value = 'new';
+ document.myForm.submit();
+ }
+
+ function runReport()
+ {
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ alert("123" + id);
+ //document.myForm.action='<%=AppUtils.getReportExecuteActionURL()%>'+JSTreeObj.selectedItem;
+ document.myForm.action='dispatcher?action=raptor&r_action=report.run&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+
+ document.myForm.submit();
+ }
+
+ function editReport()
+ {
+ var id = JSTreeObj.selectedItem.parentNode.id.replace(/[^0-9]/gi,'');
+ alert("123" + id);
+ document.myForm.action='dispatcher?action=raptor&r_action=report.edit&c_master=' + id + '&PAGE_ID=HOME&refresh=Y';
+ document.myForm.submit();
+ }
+
+ function expandTree(){
+ document.getElementById('expandedTree').style.display='block';
+ document.getElementById('expandedTreeHeader').style.display='block';
+ document.getElementById('collapsedTree').style.display='none';
+ }
+ function collapseTree(){
+ document.getElementById('expandedTree').style.display='none';
+ document.getElementById('expandedTreeHeader').style.display='none';
+ document.getElementById('collapsedTree').style.display='block';
+ }
+ </script>
+
+</head>
+<body>
+ <form name="reportForm" method="post">
+ <table width="94%" border="0" cellspacing="1" align="center">
+ <tr><td>
+ <div id="collapsedTree" style="position:absoulte;top:0;width:100%;height:25px;display:none;">
+ <table width="94%" border="0" cellspacing="1" align="left">
+ <tr>
+ <td class=rtabletext align=left>
+ <img border="0" src="<%= AppUtils.getImgFolderURL() %>tree/dhtmlgoodies_plus.gif" onClick="javascript:expandTree()" alt='Show Folder Tree'>
+ Root Node
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td></tr>
+
+
+ <tr><td>
+ <div id="expandedTreeHeader" style="position:absoulte;top:0;width:100%;height:25px;display:block;">
+ <table width="94%" border="0" cellspacing="1" align="left">
+ <tr>
+ <td class=rtabletext >
+ <img border="0" src="<%= AppUtils.getImgFolderURL() %>tree/dhtmlgoodies_minus.gif" onClick="javascript:collapseTree()" alt='Hide Folder Tree'>
+ &nbsp;&nbsp;&nbsp;
+ <!--<input type='button' class=rsmallbutton id='createFolder' value='Create Folder' onclick='javascript:JSTreeObj.addItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem);'/>
+ <input type='button' class=rsmallbutton id='createFolder' value='Run' onclick='javascript:JSTreeObj.addItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem);'/>
+ <input type='button' class=rsmallbutton id='createFolder' value='Edit' onclick='javascript:JSTreeObj.addItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem);'/>-->
+ <a href="#" onclick='javascript:JSTreeObj.addItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem);'>Create Folder</a> |
+ <a href="#" onclick='javascript:JSTreeObj.deleteItem(JSTreeObj.selectedItem, JSTreeObj.selectedItem);'>Delete Fodler</a> |
+ <a href="#" onclick='javascript:runReport();'>Run Report</a> |
+ <a href="#" onclick='javascript:editReport();'>Edit Report</a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="expandedTree" style="position:absoulte;top:0;width:100%;height:160px;display:block">
+ <table>
+ <tr>
+
+ <td width="50%">
+ <div id="scrollableTable" class="scrollableTable" style="position:absoulte;top:0;width:100%;height:150px;display:block">
+ <table width="94%" border="0" cellspacing="1" align="center">
+ <tr>
+ <td >
+ <%=request.getAttribute("folderList")%>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ <td width="50%" valign="bottom">
+ <table>
+ <tr><td width="100%" class=rtabletext >
+ <a href="#" onclick="treeObj.collapseAll()">Collapse all</a> |
+ <a href="#" onclick="treeObj.expandAll()">Expand all</a>
+ </td></tr>
+ <tr><td width="100%">
+ <input type="button" class=rsmallbutton onclick="saveMyTree_byForm()" value="Save">
+ <input type="button" class=rsmallbutton onclick="cancelMyTree_byForm()" value="Cancel">
+ </td></tr>
+ </table>
+
+ </td>
+ </tr>
+
+ </table>
+ </div>
+ </td>
+ </tr>
+ <tr><td colspan=2>
+ <div class="scrollableTable" style="width:100%;height:400px;">
+ <iframe id="reportFrame" name="reportFrame" width="100%" height="100%">
+
+ </iframe>
+ </div>
+ </td></tr>
+ </table>
+ </Form>
+ <script type="text/javascript">
+ treeObj = new JSDragDropTree();
+ treeObj.setTreeId('reportFolderTree');
+ treeObj.setMaximumDepth(7);
+ treeObj.setMessageMaximumDepthReached('Maximum depth reached'); // If you want to show a message when maximum depth is reached, i.e. on drop.
+ treeObj.initTree();
+ treeObj.expandAll();
+
+ </script>
+
+ <!-- Form - if you want to save it by form submission and not Ajax -->
+ <form name="myForm" action="tree" method="post">
+ <input type="hidden" name="saveString">
+ <input type="hidden" name="task">
+ <input type="hidden" name="newName">
+ <input type="hidden" name="deleteIds">
+ </form>
+
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp
index 76fe7a58..76fe7a58 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_adhoc_schedule.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp
index 959adc23..959adc23 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_chart.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp
index ab67b802..ab67b802 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_add_multi.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp
index cc6b68b0..cc6b68b0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_edit.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp
index 454cf7d5..454cf7d5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_list.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp
index fc1870c6..fc1870c6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_columns_order_all.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp
index 33cabe7e..33cabe7e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_data_forecasting.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp
index ec61e3fd..ec61e3fd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_definition.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp
index 7589f73f..7589f73f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_edit.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp
index 71898b35..71898b35 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_filters_list.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp
index 185f65c1..185f65c1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_edit.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp
index 8470dbbc..8470dbbc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_form_fields_list.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp
index d225cb56..d225cb56 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_javascript.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp
index 2b170385..2b170385 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_log.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp
index 50fe1da6..50fe1da6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_map.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp
index 688e7ff7..688e7ff7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_run.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp
index b8d1ad1c..b8d1ad1c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp
index 206e23de..206e23de 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_formfield_include.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp
index 70c9812a..70c9812a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_multiple.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp
index ad3c612e..ad3c612e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp
index af951cc2..af951cc2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_schedule_only_from_search.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp
index 18c450ba..18c450ba 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_edit.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp
index 63bf9cd3..63bf9cd3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_list.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp
index 9e04f2b8..9e04f2b8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sorting_order_all.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp
index d8152c05..d8152c05 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_sql_def.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp
index 88ecda31..88ecda31 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_edit.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp
index 47fd435f..47fd435f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_tables_list.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp
index b5c68045..b5c68045 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/fusion/raptor/wizard_user_access.jsp
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/error.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/error.jsp
index 2a48507c..2a48507c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/error.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/error.jsp
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/leafletMap.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/leafletMap.jsp
new file mode 100644
index 00000000..e11070d1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/leafletMap.jsp
@@ -0,0 +1,216 @@
+<%--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ --%>
+<!DOCTYPE html>
+
+<html>
+<head>
+
+ <meta charset="UTF-8">
+
+ <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
+ <script src="app/fusion/external/leaflet-0.7.3/leaflet.js"></script>
+ <link rel="stylesheet" href="app/fusion/external/leaflet-0.7.3/leaflet.css" />
+
+ <style>
+ #map {
+ height: 450px;
+ width: 800px;
+ }
+ .animateOff {
+ color: red;
+ }
+ .animateOn {
+ color: green;
+ }
+ </style>
+<!--
+ <script src="static/fusion/gis/js/local.js"></script>
+ -->
+ <script>
+
+ var siteData = [
+
+ ];
+
+ var pipeData = [
+
+ ];
+ </script>
+
+
+</head>
+<body>
+ <div id="map"></div>
+ <button id="forwardButton" onclick="stepForward();">Step Forward</button>
+ <button id="playPause" onclick="playPause();">Play</button>
+ <div>
+ <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header sortable="false" key="id">Site</th>
+ <th att-table-header sortable="false" key="lastName">Usage</th>
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" id="topTenSites">
+ </tbody>
+ </table>
+ <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header sortable="false" key="id">Link</th>
+ <th att-table-header sortable="false" key="lastName">Usage</th>
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" id="topTenLinks">
+ </tbody>
+ </table>
+ </div>
+
+ <script>
+ var map = L.map('map').setView([40, -96], 4);
+ <!-- please add your map location -->
+ L.tileLayer('http://XXX/tiles-light/{z}/{x}/{y}.png', {maxZoom:18}).addTo(map);
+
+ var dataLayer = addDataLayers(map, null);
+
+ function addDataLayers(map, dataLayer) {
+ if (dataLayer!=null) {
+ map.removeLayer(dataLayer);
+ }
+
+ dataLayer = L.layerGroup();
+
+ var siteInfo = [];
+
+ var pipeLayer = L.layerGroup();
+ for (var i=0; i<pipeData.length; i++) {
+ var pipe = pipeData[i];
+
+ var usage = pipe.usage;
+ if (!usage || Math.random()<0.05) {
+ //console.log("Rerolling " + pipe.name);
+ usage = Math.floor(Math.random()*33 + Math.random()*33 + Math.random()*34);
+ } else {
+ //console.log("Adjusting " + pipe.name);
+ usage = Math.floor(usage + Math.random()*15 - Math.random()*15);
+ }
+ if (usage<0) usage = 0;
+ while (usage>100) usage -= Math.floor(20*Math.random());
+ if (usage>90) usage -= Math.floor(20*Math.random());
+
+ pipe.usage = usage;
+
+ var color = "black";
+ if (usage>60) color = "yellow";
+ if (usage>70) color = "orange";
+ if (usage>80) color = "red";
+ pipeLayer.addLayer(L.polyline([[pipe.lat_a, pipe.lon_a], [pipe.lat_z, pipe.lon_z]], {"color": color, "title": pipe.name}).bindPopup(pipe.name + "<br/>" + pipe.title + "<br/>" + usage + "% usage"));
+
+ var siteA = siteInfo[pipe.id_a];
+ if (siteA) {
+ siteA.usage += usage;
+ siteA.maxUsage += 100;
+ //console.log("Site a id = " + pipe.id_a + ", object existed = " + siteA + ", usage = " + siteA.usage + ", max = " + siteA.maxUsage);
+ } else {
+ siteA = {};
+ siteA.usage = usage;
+ siteA.maxUsage = 100;
+ siteInfo[pipe.id_a] = siteA;
+ //console.log("Site a id = " + pipe.id_a + ", object is new = " + siteA + ", usage = " + siteA.usage + ", max = " + siteA.maxUsage);
+ }
+
+ var siteZ = siteInfo[pipe.id_z];
+ if (siteZ) {
+ siteZ.usage += usage;
+ siteZ.maxUsage += 100;
+ //console.log("Site z id = " + pipe.id_z + ", object existed = " + siteZ + ", usage = " + siteZ.usage + ", max = " + siteZ.maxUsage);
+ } else {
+ siteZ = {};
+ siteZ.usage = usage;
+ siteZ.maxUsage = 100;
+ siteInfo[pipe.id_z] = siteZ;
+ //console.log("Site z id = " + pipe.id_z + ", object is new = " + siteZ + ", usage = " + siteZ.usage + ", max = " + siteZ.maxUsage);
+ }
+ }
+ dataLayer.addLayer(pipeLayer);
+
+ var dataCenterLayer = L.layerGroup();
+ for (var i=0; i<siteData.length; i++) {
+ var site = siteData[i];
+// {"id": "slkut", "name": "Salt Lake City, UT", "title": "250G", "lat": 40.75, "lon": -111.88},
+ var info = siteInfo[site.id];
+ var color = "black";
+ if (info.usage/info.maxUsage>.6) color = "yellow";
+ if (info.usage/info.maxUsage>.7) color = "orange";
+ if (info.usage/info.maxUsage>.8) color = "red";
+ var pct = Math.floor(100*info.usage/info.maxUsage);
+ site.usage = pct;
+// dataCenterLayer.addLayer(L.marker([site.lat, site.lon], {"title": site.name}).bindPopup(site.name + "<br/>" + pipe.title + "<br/>" + info.usage + "/" + info.maxUsage));
+ dataCenterLayer.addLayer(L.circleMarker([site.lat, site.lon], {"color": color, "title": site.name, "fillOpacity": .5}).bindPopup(site.name + "<br/>" + pipe.title + "<br/>" + pct + "%"));
+ }
+ dataLayer.addLayer(dataCenterLayer);
+
+ dataLayer.addTo(map);
+
+ siteData.sort(function(a,b){return b.usage-a.usage});
+ var topTenHtml = "";
+ for (var i=0; i<10; i++) {
+ topTenHtml = topTenHtml + "<tr><td att-table-body>" + siteData[i].name + "</td><td att-table-body>" + siteData[i].usage + "%</td></tr>";
+ }
+ document.getElementById("topTenSites").innerHTML = topTenHtml;
+
+ pipeData.sort(function(a,b){return b.usage-a.usage});
+ topTenHtml = "";
+ for (var i=0; i<10; i++) {
+ topTenHtml = topTenHtml + "<tr><td att-table-body>" + pipeData[i].name + "</td><td att-table-body>" + pipeData[i].usage + "%</td></tr>";
+ }
+ document.getElementById("topTenLinks").innerHTML = topTenHtml;
+
+ return dataLayer;
+ }
+
+ function stepForward() {
+ dataLayer = addDataLayers(map, dataLayer);
+ }
+
+ var intervalObj = null;
+ function playPause() {
+ if (intervalObj==null) {
+ document.getElementById('playPause').innerHTML = "Pause";
+ document.getElementById('forwardButton').disabled = true;
+ intervalObj = window.setInterval(function(){dataLayer = addDataLayers(map, dataLayer);},1500);
+ } else {
+ document.getElementById('playPause').innerHTML = "Play";
+ document.getElementById('forwardButton').disabled = false;
+ clearInterval(intervalObj);
+ intervalObj = null;
+ }
+ }
+
+ function onMapClick(e) {
+ //alert("You clicked the map at " + e.latlng);
+ dataLayer = addDataLayers(map, dataLayer);
+ }
+
+ map.on('click', onMapClick);
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/login_external_ng.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/login_external_ng.jsp
new file mode 100644
index 00000000..cb6def1e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/login_external_ng.jsp
@@ -0,0 +1,79 @@
+<%--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ --%>
+<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties" %>
+<c:set var="title" value="Login" />
+<c:set var="isMobileEnabled"
+ value="<%=(SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE)!= null && SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE).trim().equals(\"true\"))%>" />
+
+<!DOCTYPE html>
+<html ng-app="abs">
+ <head>
+
+ <title>
+ Login
+ </title>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
+ <style>
+ .terms {
+ font-family: Verdana,Arial,Helvetica, sans-serif;
+ font-size: 9px;
+ }
+ </style>
+ </head>
+ <body style="padding-top: 15px;">
+ <form action="login_external" method="post">
+ <div style="position: fixed; left:15px; top:15px;z-index:-1;">
+ </div>
+ <div class="centered style="-webkit-transform: translateZ(0);background:white, z-index:0;">
+ <br/>
+ <div align="center" style="margin-left:auto;margin-right:auto;width:40%;padding:6px;opacity:0.7;background-color:white">
+ <img src="static/fusion/images/ecomp_trans.png"/>
+ <h2> ECOMP Portal </h2>
+ <div align="center" id="errorInfo" style="align:center;font-size:14px;margin-left:5px"><span style="color:red">${model.error}</span></div>
+ <br>
+ <label>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<label class="form-field__label">Login ID:</label>
+ </label>
+ <input type="text" class="fn-ebz-text" name="loginId" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
+ maxlength="30" />
+ <br/>
+ <br/>
+ <label >&nbsp;Password:</label>
+ <input type="password" class="span3" name="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
+ maxlength="30" onkeydown="if (event.keyCode == 13) document.getElementById('loginBtn').click()"/>
+ <br />
+ <br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <input id="loginBtn" type="submit" type="image" src="static/fusion/images/login_button.gif" alt="Login" />
+ <br>
+ </div>
+ </div>
+ <br/><br/><br/><br/><br/><br/><br/>
+ <div id="footer">
+ </div>
+ </form>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/net_map.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/net_map.jsp
index 2a341467..2a341467 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/net_map.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/jsp/net_map.jsp
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/web.xml b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..3f84f06a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+ version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee">
+
+ <!-- This is a stub web.xml in the common area -->
+ <display-name>ecomp-sdk-app-common</display-name>
+
+</web-app>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.js
new file mode 100644
index 00000000..30610044
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.js
@@ -0,0 +1,3930 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/* jshint ignore:start */
+var noop = angular.noop;
+var extend = angular.extend;
+var jqLite = angular.element;
+var forEach = angular.forEach;
+var isArray = angular.isArray;
+var isString = angular.isString;
+var isObject = angular.isObject;
+var isUndefined = angular.isUndefined;
+var isDefined = angular.isDefined;
+var isFunction = angular.isFunction;
+var isElement = angular.isElement;
+
+var ELEMENT_NODE = 1;
+var COMMENT_NODE = 8;
+
+var ADD_CLASS_SUFFIX = '-add';
+var REMOVE_CLASS_SUFFIX = '-remove';
+var EVENT_CLASS_PREFIX = 'ng-';
+var ACTIVE_CLASS_SUFFIX = '-active';
+
+var NG_ANIMATE_CLASSNAME = 'ng-animate';
+var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren';
+
+// Detect proper transitionend/animationend event names.
+var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
+
+// If unprefixed events are not supported but webkit-prefixed are, use the latter.
+// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
+// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
+// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
+// Register both events in case `window.onanimationend` is not supported because of that,
+// do the same for `transitionend` as Safari is likely to exhibit similar behavior.
+// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
+// therefore there is no reason to test anymore for other vendor prefixes:
+// http://caniuse.com/#search=transition
+if (isUndefined(window.ontransitionend) && isDefined(window.onwebkittransitionend)) {
+ CSS_PREFIX = '-webkit-';
+ TRANSITION_PROP = 'WebkitTransition';
+ TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
+} else {
+ TRANSITION_PROP = 'transition';
+ TRANSITIONEND_EVENT = 'transitionend';
+}
+
+if (isUndefined(window.onanimationend) && isDefined(window.onwebkitanimationend)) {
+ CSS_PREFIX = '-webkit-';
+ ANIMATION_PROP = 'WebkitAnimation';
+ ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
+} else {
+ ANIMATION_PROP = 'animation';
+ ANIMATIONEND_EVENT = 'animationend';
+}
+
+var DURATION_KEY = 'Duration';
+var PROPERTY_KEY = 'Property';
+var DELAY_KEY = 'Delay';
+var TIMING_KEY = 'TimingFunction';
+var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
+var ANIMATION_PLAYSTATE_KEY = 'PlayState';
+var SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
+
+var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
+var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
+var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
+var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
+
+var isPromiseLike = function(p) {
+ return p && p.then ? true : false;
+};
+
+function assertArg(arg, name, reason) {
+ if (!arg) {
+ throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
+ }
+ return arg;
+}
+
+function mergeClasses(a,b) {
+ if (!a && !b) return '';
+ if (!a) return b;
+ if (!b) return a;
+ if (isArray(a)) a = a.join(' ');
+ if (isArray(b)) b = b.join(' ');
+ return a + ' ' + b;
+}
+
+function packageStyles(options) {
+ var styles = {};
+ if (options && (options.to || options.from)) {
+ styles.to = options.to;
+ styles.from = options.from;
+ }
+ return styles;
+}
+
+function pendClasses(classes, fix, isPrefix) {
+ var className = '';
+ classes = isArray(classes)
+ ? classes
+ : classes && isString(classes) && classes.length
+ ? classes.split(/\s+/)
+ : [];
+ forEach(classes, function(klass, i) {
+ if (klass && klass.length > 0) {
+ className += (i > 0) ? ' ' : '';
+ className += isPrefix ? fix + klass
+ : klass + fix;
+ }
+ });
+ return className;
+}
+
+function removeFromArray(arr, val) {
+ var index = arr.indexOf(val);
+ if (val >= 0) {
+ arr.splice(index, 1);
+ }
+}
+
+function stripCommentsFromElement(element) {
+ if (element instanceof jqLite) {
+ switch (element.length) {
+ case 0:
+ return [];
+ break;
+
+ case 1:
+ // there is no point of stripping anything if the element
+ // is the only element within the jqLite wrapper.
+ // (it's important that we retain the element instance.)
+ if (element[0].nodeType === ELEMENT_NODE) {
+ return element;
+ }
+ break;
+
+ default:
+ return jqLite(extractElementNode(element));
+ break;
+ }
+ }
+
+ if (element.nodeType === ELEMENT_NODE) {
+ return jqLite(element);
+ }
+}
+
+function extractElementNode(element) {
+ if (!element[0]) return element;
+ for (var i = 0; i < element.length; i++) {
+ var elm = element[i];
+ if (elm.nodeType == ELEMENT_NODE) {
+ return elm;
+ }
+ }
+}
+
+function $$addClass($$jqLite, element, className) {
+ forEach(element, function(elm) {
+ $$jqLite.addClass(elm, className);
+ });
+}
+
+function $$removeClass($$jqLite, element, className) {
+ forEach(element, function(elm) {
+ $$jqLite.removeClass(elm, className);
+ });
+}
+
+function applyAnimationClassesFactory($$jqLite) {
+ return function(element, options) {
+ if (options.addClass) {
+ $$addClass($$jqLite, element, options.addClass);
+ options.addClass = null;
+ }
+ if (options.removeClass) {
+ $$removeClass($$jqLite, element, options.removeClass);
+ options.removeClass = null;
+ }
+ }
+}
+
+function prepareAnimationOptions(options) {
+ options = options || {};
+ if (!options.$$prepared) {
+ var domOperation = options.domOperation || noop;
+ options.domOperation = function() {
+ options.$$domOperationFired = true;
+ domOperation();
+ domOperation = noop;
+ };
+ options.$$prepared = true;
+ }
+ return options;
+}
+
+function applyAnimationStyles(element, options) {
+ applyAnimationFromStyles(element, options);
+ applyAnimationToStyles(element, options);
+}
+
+function applyAnimationFromStyles(element, options) {
+ if (options.from) {
+ element.css(options.from);
+ options.from = null;
+ }
+}
+
+function applyAnimationToStyles(element, options) {
+ if (options.to) {
+ element.css(options.to);
+ options.to = null;
+ }
+}
+
+function mergeAnimationOptions(element, target, newOptions) {
+ var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
+ var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
+ var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
+
+ if (newOptions.preparationClasses) {
+ target.preparationClasses = concatWithSpace(newOptions.preparationClasses, target.preparationClasses);
+ delete newOptions.preparationClasses;
+ }
+
+ // noop is basically when there is no callback; otherwise something has been set
+ var realDomOperation = target.domOperation !== noop ? target.domOperation : null;
+
+ extend(target, newOptions);
+
+ // TODO(matsko or sreeramu): proper fix is to maintain all animation callback in array and call at last,but now only leave has the callback so no issue with this.
+ if (realDomOperation) {
+ target.domOperation = realDomOperation;
+ }
+
+ if (classes.addClass) {
+ target.addClass = classes.addClass;
+ } else {
+ target.addClass = null;
+ }
+
+ if (classes.removeClass) {
+ target.removeClass = classes.removeClass;
+ } else {
+ target.removeClass = null;
+ }
+
+ return target;
+}
+
+function resolveElementClasses(existing, toAdd, toRemove) {
+ var ADD_CLASS = 1;
+ var REMOVE_CLASS = -1;
+
+ var flags = {};
+ existing = splitClassesToLookup(existing);
+
+ toAdd = splitClassesToLookup(toAdd);
+ forEach(toAdd, function(value, key) {
+ flags[key] = ADD_CLASS;
+ });
+
+ toRemove = splitClassesToLookup(toRemove);
+ forEach(toRemove, function(value, key) {
+ flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
+ });
+
+ var classes = {
+ addClass: '',
+ removeClass: ''
+ };
+
+ forEach(flags, function(val, klass) {
+ var prop, allow;
+ if (val === ADD_CLASS) {
+ prop = 'addClass';
+ allow = !existing[klass];
+ } else if (val === REMOVE_CLASS) {
+ prop = 'removeClass';
+ allow = existing[klass];
+ }
+ if (allow) {
+ if (classes[prop].length) {
+ classes[prop] += ' ';
+ }
+ classes[prop] += klass;
+ }
+ });
+
+ function splitClassesToLookup(classes) {
+ if (isString(classes)) {
+ classes = classes.split(' ');
+ }
+
+ var obj = {};
+ forEach(classes, function(klass) {
+ // sometimes the split leaves empty string values
+ // incase extra spaces were applied to the options
+ if (klass.length) {
+ obj[klass] = true;
+ }
+ });
+ return obj;
+ }
+
+ return classes;
+}
+
+function getDomNode(element) {
+ return (element instanceof angular.element) ? element[0] : element;
+}
+
+function applyGeneratedPreparationClasses(element, event, options) {
+ var classes = '';
+ if (event) {
+ classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
+ }
+ if (options.addClass) {
+ classes = concatWithSpace(classes, pendClasses(options.addClass, ADD_CLASS_SUFFIX));
+ }
+ if (options.removeClass) {
+ classes = concatWithSpace(classes, pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX));
+ }
+ if (classes.length) {
+ options.preparationClasses = classes;
+ element.addClass(classes);
+ }
+}
+
+function clearGeneratedClasses(element, options) {
+ if (options.preparationClasses) {
+ element.removeClass(options.preparationClasses);
+ options.preparationClasses = null;
+ }
+ if (options.activeClasses) {
+ element.removeClass(options.activeClasses);
+ options.activeClasses = null;
+ }
+}
+
+function blockTransitions(node, duration) {
+ // we use a negative delay value since it performs blocking
+ // yet it doesn't kill any existing transitions running on the
+ // same element which makes this safe for class-based animations
+ var value = duration ? '-' + duration + 's' : '';
+ applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
+ return [TRANSITION_DELAY_PROP, value];
+}
+
+function blockKeyframeAnimations(node, applyBlock) {
+ var value = applyBlock ? 'paused' : '';
+ var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
+ applyInlineStyle(node, [key, value]);
+ return [key, value];
+}
+
+function applyInlineStyle(node, styleTuple) {
+ var prop = styleTuple[0];
+ var value = styleTuple[1];
+ node.style[prop] = value;
+}
+
+function concatWithSpace(a,b) {
+ if (!a) return b;
+ if (!b) return a;
+ return a + ' ' + b;
+}
+
+var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
+ var queue, cancelFn;
+
+ function scheduler(tasks) {
+ // we make a copy since RAFScheduler mutates the state
+ // of the passed in array variable and this would be difficult
+ // to track down on the outside code
+ queue = queue.concat(tasks);
+ nextTick();
+ }
+
+ queue = scheduler.queue = [];
+
+ /* waitUntilQuiet does two things:
+ * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through
+ * 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
+ *
+ * The motivation here is that animation code can request more time from the scheduler
+ * before the next wave runs. This allows for certain DOM properties such as classes to
+ * be resolved in time for the next animation to run.
+ */
+ scheduler.waitUntilQuiet = function(fn) {
+ if (cancelFn) cancelFn();
+
+ cancelFn = $$rAF(function() {
+ cancelFn = null;
+ fn();
+ nextTick();
+ });
+ };
+
+ return scheduler;
+
+ function nextTick() {
+ if (!queue.length) return;
+
+ var items = queue.shift();
+ for (var i = 0; i < items.length; i++) {
+ items[i]();
+ }
+
+ if (!cancelFn) {
+ $$rAF(function() {
+ if (!cancelFn) nextTick();
+ });
+ }
+ }
+}];
+
+var $$AnimateChildrenDirective = [function() {
+ return function(scope, element, attrs) {
+ var val = attrs.ngAnimateChildren;
+ if (angular.isString(val) && val.length === 0) { //empty attribute
+ element.data(NG_ANIMATE_CHILDREN_DATA, true);
+ } else {
+ attrs.$observe('ngAnimateChildren', function(value) {
+ value = value === 'on' || value === 'true';
+ element.data(NG_ANIMATE_CHILDREN_DATA, value);
+ });
+ }
+ };
+}];
+
+var ANIMATE_TIMER_KEY = '$$animateCss';
+
+/**
+ * @ngdoc service
+ * @name $animateCss
+ * @kind object
+ *
+ * @description
+ * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes
+ * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT
+ * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or
+ * directives to create more complex animations that can be purely driven using CSS code.
+ *
+ * Note that only browsers that support CSS transitions and/or keyframe animations are capable of
+ * rendering animations triggered via `$animateCss` (bad news for IE9 and lower).
+ *
+ * ## Usage
+ * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
+ * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
+ * any automatic control over cancelling animations and/or preventing animations from being run on
+ * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to
+ * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
+ * the CSS animation.
+ *
+ * The example below shows how we can create a folding animation on an element using `ng-if`:
+ *
+ * ```html
+ * <!-- notice the `fold-animation` CSS class -->
+ * <div ng-if="onOff" class="fold-animation">
+ * This element will go BOOM
+ * </div>
+ * <button ng-click="onOff=true">Fold In</button>
+ * ```
+ *
+ * Now we create the **JavaScript animation** that will trigger the CSS transition:
+ *
+ * ```js
+ * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element, doneFn) {
+ * var height = element[0].offsetHeight;
+ * return $animateCss(element, {
+ * from: { height:'0px' },
+ * to: { height:height + 'px' },
+ * duration: 1 // one second
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ## More Advanced Uses
+ *
+ * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks
+ * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code.
+ *
+ * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation,
+ * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with
+ * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order
+ * to provide a working animation that will run in CSS.
+ *
+ * The example below showcases a more advanced version of the `.fold-animation` from the example above:
+ *
+ * ```js
+ * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element, doneFn) {
+ * var height = element[0].offsetHeight;
+ * return $animateCss(element, {
+ * addClass: 'red large-text pulse-twice',
+ * easing: 'ease-out',
+ * from: { height:'0px' },
+ * to: { height:height + 'px' },
+ * duration: 1 // one second
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * Since we're adding/removing CSS classes then the CSS transition will also pick those up:
+ *
+ * ```css
+ * /&#42; since a hardcoded duration value of 1 was provided in the JavaScript animation code,
+ * the CSS classes below will be transitioned despite them being defined as regular CSS classes &#42;/
+ * .red { background:red; }
+ * .large-text { font-size:20px; }
+ *
+ * /&#42; we can also use a keyframe animation and $animateCss will make it work alongside the transition &#42;/
+ * .pulse-twice {
+ * animation: 0.5s pulse linear 2;
+ * -webkit-animation: 0.5s pulse linear 2;
+ * }
+ *
+ * @keyframes pulse {
+ * from { transform: scale(0.5); }
+ * to { transform: scale(1.5); }
+ * }
+ *
+ * @-webkit-keyframes pulse {
+ * from { -webkit-transform: scale(0.5); }
+ * to { -webkit-transform: scale(1.5); }
+ * }
+ * ```
+ *
+ * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen.
+ *
+ * ## How the Options are handled
+ *
+ * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation
+ * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline
+ * styles using the `from` and `to` properties.
+ *
+ * ```js
+ * var animator = $animateCss(element, {
+ * from: { background:'red' },
+ * to: { background:'blue' }
+ * });
+ * animator.start();
+ * ```
+ *
+ * ```css
+ * .rotating-animation {
+ * animation:0.5s rotate linear;
+ * -webkit-animation:0.5s rotate linear;
+ * }
+ *
+ * @keyframes rotate {
+ * from { transform: rotate(0deg); }
+ * to { transform: rotate(360deg); }
+ * }
+ *
+ * @-webkit-keyframes rotate {
+ * from { -webkit-transform: rotate(0deg); }
+ * to { -webkit-transform: rotate(360deg); }
+ * }
+ * ```
+ *
+ * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is
+ * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition
+ * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition
+ * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied
+ * and spread across the transition and keyframe animation.
+ *
+ * ## What is returned
+ *
+ * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually
+ * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are
+ * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties:
+ *
+ * ```js
+ * var animator = $animateCss(element, { ... });
+ * ```
+ *
+ * Now what do the contents of our `animator` variable look like:
+ *
+ * ```js
+ * {
+ * // starts the animation
+ * start: Function,
+ *
+ * // ends (aborts) the animation
+ * end: Function
+ * }
+ * ```
+ *
+ * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends.
+ * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been
+ * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
+ * and that changing them will not reconfigure the parameters of the animation.
+ *
+ * ### runner.done() vs runner.then()
+ * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
+ * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
+ * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
+ * unless you really need a digest to kick off afterwards.
+ *
+ * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
+ * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code).
+ * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works.
+ *
+ * @param {DOMElement} element the element that will be animated
+ * @param {object} options the animation-related options that will be applied during the animation
+ *
+ * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
+ * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
+ * * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and
+ * `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted.
+ * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
+ * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
+ * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
+ * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
+ * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
+ * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation.
+ * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation.
+ * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0`
+ * is provided then the animation will be skipped entirely.
+ * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is
+ * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value
+ * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same
+ * CSS delay value.
+ * * `stagger` - A numeric time value representing the delay between successively animated elements
+ * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
+ * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a
+ * * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
+ * * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.)
+ * * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
+ * the animation is closed. This is useful for when the styles are used purely for the sake of
+ * the animation and do not have a lasting visual effect on the element (e.g. a colapse and open animation).
+ * By default this value is set to `false`.
+ *
+ * @return {object} an object with start and end methods and details about the animation.
+ *
+ * * `start` - The method to start the animation. This will return a `Promise` when called.
+ * * `end` - This method will cancel the animation and remove all applied CSS classes and styles.
+ */
+var ONE_SECOND = 1000;
+var BASE_TEN = 10;
+
+var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
+var CLOSING_TIME_BUFFER = 1.5;
+
+var DETECT_CSS_PROPERTIES = {
+ transitionDuration: TRANSITION_DURATION_PROP,
+ transitionDelay: TRANSITION_DELAY_PROP,
+ transitionProperty: TRANSITION_PROP + PROPERTY_KEY,
+ animationDuration: ANIMATION_DURATION_PROP,
+ animationDelay: ANIMATION_DELAY_PROP,
+ animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY
+};
+
+var DETECT_STAGGER_CSS_PROPERTIES = {
+ transitionDuration: TRANSITION_DURATION_PROP,
+ transitionDelay: TRANSITION_DELAY_PROP,
+ animationDuration: ANIMATION_DURATION_PROP,
+ animationDelay: ANIMATION_DELAY_PROP
+};
+
+function getCssKeyframeDurationStyle(duration) {
+ return [ANIMATION_DURATION_PROP, duration + 's'];
+}
+
+function getCssDelayStyle(delay, isKeyframeAnimation) {
+ var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP;
+ return [prop, delay + 's'];
+}
+
+function computeCssStyles($window, element, properties) {
+ var styles = Object.create(null);
+ var detectedStyles = $window.getComputedStyle(element) || {};
+ forEach(properties, function(formalStyleName, actualStyleName) {
+ var val = detectedStyles[formalStyleName];
+ if (val) {
+ var c = val.charAt(0);
+
+ // only numerical-based values have a negative sign or digit as the first value
+ if (c === '-' || c === '+' || c >= 0) {
+ val = parseMaxTime(val);
+ }
+
+ // by setting this to null in the event that the delay is not set or is set directly as 0
+ // then we can still allow for zegative values to be used later on and not mistake this
+ // value for being greater than any other negative value.
+ if (val === 0) {
+ val = null;
+ }
+ styles[actualStyleName] = val;
+ }
+ });
+
+ return styles;
+}
+
+function parseMaxTime(str) {
+ var maxValue = 0;
+ var values = str.split(/\s*,\s*/);
+ forEach(values, function(value) {
+ // it's always safe to consider only second values and omit `ms` values since
+ // getComputedStyle will always handle the conversion for us
+ if (value.charAt(value.length - 1) == 's') {
+ value = value.substring(0, value.length - 1);
+ }
+ value = parseFloat(value) || 0;
+ maxValue = maxValue ? Math.max(value, maxValue) : value;
+ });
+ return maxValue;
+}
+
+function truthyTimingValue(val) {
+ return val === 0 || val != null;
+}
+
+function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
+ var style = TRANSITION_PROP;
+ var value = duration + 's';
+ if (applyOnlyDuration) {
+ style += DURATION_KEY;
+ } else {
+ value += ' linear all';
+ }
+ return [style, value];
+}
+
+function createLocalCacheLookup() {
+ var cache = Object.create(null);
+ return {
+ flush: function() {
+ cache = Object.create(null);
+ },
+
+ count: function(key) {
+ var entry = cache[key];
+ return entry ? entry.total : 0;
+ },
+
+ get: function(key) {
+ var entry = cache[key];
+ return entry && entry.value;
+ },
+
+ put: function(key, value) {
+ if (!cache[key]) {
+ cache[key] = { total: 1, value: value };
+ } else {
+ cache[key].total++;
+ }
+ }
+ };
+}
+
+// we do not reassign an already present style value since
+// if we detect the style property value again we may be
+// detecting styles that were added via the `from` styles.
+// We make use of `isDefined` here since an empty string
+// or null value (which is what getPropertyValue will return
+// for a non-existing style) will still be marked as a valid
+// value for the style (a falsy value implies that the style
+// is to be removed at the end of the animation). If we had a simple
+// "OR" statement then it would not be enough to catch that.
+function registerRestorableStyles(backup, node, properties) {
+ forEach(properties, function(prop) {
+ backup[prop] = isDefined(backup[prop])
+ ? backup[prop]
+ : node.style.getPropertyValue(prop);
+ });
+}
+
+var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
+ var gcsLookup = createLocalCacheLookup();
+ var gcsStaggerLookup = createLocalCacheLookup();
+
+ this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
+ '$$forceReflow', '$sniffer', '$$rAFScheduler', '$animate',
+ function($window, $$jqLite, $$AnimateRunner, $timeout,
+ $$forceReflow, $sniffer, $$rAFScheduler, $animate) {
+
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+
+ var parentCounter = 0;
+ function gcsHashFn(node, extraClasses) {
+ var KEY = "$$ngAnimateParentKey";
+ var parentNode = node.parentNode;
+ var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
+ return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
+ }
+
+ function computeCachedCssStyles(node, className, cacheKey, properties) {
+ var timings = gcsLookup.get(cacheKey);
+
+ if (!timings) {
+ timings = computeCssStyles($window, node, properties);
+ if (timings.animationIterationCount === 'infinite') {
+ timings.animationIterationCount = 1;
+ }
+ }
+
+ // we keep putting this in multiple times even though the value and the cacheKey are the same
+ // because we're keeping an interal tally of how many duplicate animations are detected.
+ gcsLookup.put(cacheKey, timings);
+ return timings;
+ }
+
+ function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
+ var stagger;
+
+ // if we have one or more existing matches of matching elements
+ // containing the same parent + CSS styles (which is how cacheKey works)
+ // then staggering is possible
+ if (gcsLookup.count(cacheKey) > 0) {
+ stagger = gcsStaggerLookup.get(cacheKey);
+
+ if (!stagger) {
+ var staggerClassName = pendClasses(className, '-stagger');
+
+ $$jqLite.addClass(node, staggerClassName);
+
+ stagger = computeCssStyles($window, node, properties);
+
+ // force the conversion of a null value to zero incase not set
+ stagger.animationDuration = Math.max(stagger.animationDuration, 0);
+ stagger.transitionDuration = Math.max(stagger.transitionDuration, 0);
+
+ $$jqLite.removeClass(node, staggerClassName);
+
+ gcsStaggerLookup.put(cacheKey, stagger);
+ }
+ }
+
+ return stagger || {};
+ }
+
+ var cancelLastRAFRequest;
+ var rafWaitQueue = [];
+ function waitUntilQuiet(callback) {
+ rafWaitQueue.push(callback);
+ $$rAFScheduler.waitUntilQuiet(function() {
+ gcsLookup.flush();
+ gcsStaggerLookup.flush();
+
+ // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
+ // PLEASE EXAMINE THE `$$forceReflow` service to understand why.
+ var pageWidth = $$forceReflow();
+
+ // we use a for loop to ensure that if the queue is changed
+ // during this looping then it will consider new requests
+ for (var i = 0; i < rafWaitQueue.length; i++) {
+ rafWaitQueue[i](pageWidth);
+ }
+ rafWaitQueue.length = 0;
+ });
+ }
+
+ function computeTimings(node, className, cacheKey) {
+ var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
+ var aD = timings.animationDelay;
+ var tD = timings.transitionDelay;
+ timings.maxDelay = aD && tD
+ ? Math.max(aD, tD)
+ : (aD || tD);
+ timings.maxDuration = Math.max(
+ timings.animationDuration * timings.animationIterationCount,
+ timings.transitionDuration);
+
+ return timings;
+ }
+
+ return function init(element, options) {
+ var restoreStyles = {};
+ var node = getDomNode(element);
+ if (!node
+ || !node.parentNode
+ || !$animate.enabled()) {
+ return closeAndReturnNoopAnimator();
+ }
+
+ options = prepareAnimationOptions(options);
+
+ var temporaryStyles = [];
+ var classes = element.attr('class');
+ var styles = packageStyles(options);
+ var animationClosed;
+ var animationPaused;
+ var animationCompleted;
+ var runner;
+ var runnerHost;
+ var maxDelay;
+ var maxDelayTime;
+ var maxDuration;
+ var maxDurationTime;
+
+ if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
+ return closeAndReturnNoopAnimator();
+ }
+
+ var method = options.event && isArray(options.event)
+ ? options.event.join(' ')
+ : options.event;
+
+ var isStructural = method && options.structural;
+ var structuralClassName = '';
+ var addRemoveClassName = '';
+
+ if (isStructural) {
+ structuralClassName = pendClasses(method, EVENT_CLASS_PREFIX, true);
+ } else if (method) {
+ structuralClassName = method;
+ }
+
+ if (options.addClass) {
+ addRemoveClassName += pendClasses(options.addClass, ADD_CLASS_SUFFIX);
+ }
+
+ if (options.removeClass) {
+ if (addRemoveClassName.length) {
+ addRemoveClassName += ' ';
+ }
+ addRemoveClassName += pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX);
+ }
+
+ // there may be a situation where a structural animation is combined together
+ // with CSS classes that need to resolve before the animation is computed.
+ // However this means that there is no explicit CSS code to block the animation
+ // from happening (by setting 0s none in the class name). If this is the case
+ // we need to apply the classes before the first rAF so we know to continue if
+ // there actually is a detected transition or keyframe animation
+ if (options.applyClassesEarly && addRemoveClassName.length) {
+ applyAnimationClasses(element, options);
+ }
+
+ var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
+ var fullClassName = classes + ' ' + preparationClasses;
+ var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
+ var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
+ var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
+
+ // there is no way we can trigger an animation if no styles and
+ // no classes are being applied which would then trigger a transition,
+ // unless there a is raw keyframe value that is applied to the element.
+ if (!containsKeyframeAnimation
+ && !hasToStyles
+ && !preparationClasses) {
+ return closeAndReturnNoopAnimator();
+ }
+
+ var cacheKey, stagger;
+ if (options.stagger > 0) {
+ var staggerVal = parseFloat(options.stagger);
+ stagger = {
+ transitionDelay: staggerVal,
+ animationDelay: staggerVal,
+ transitionDuration: 0,
+ animationDuration: 0
+ };
+ } else {
+ cacheKey = gcsHashFn(node, fullClassName);
+ stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
+ }
+
+ if (!options.$$skipPreparationClasses) {
+ $$jqLite.addClass(element, preparationClasses);
+ }
+
+ var applyOnlyDuration;
+
+ if (options.transitionStyle) {
+ var transitionStyle = [TRANSITION_PROP, options.transitionStyle];
+ applyInlineStyle(node, transitionStyle);
+ temporaryStyles.push(transitionStyle);
+ }
+
+ if (options.duration >= 0) {
+ applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
+ var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration);
+
+ // we set the duration so that it will be picked up by getComputedStyle later
+ applyInlineStyle(node, durationStyle);
+ temporaryStyles.push(durationStyle);
+ }
+
+ if (options.keyframeStyle) {
+ var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle];
+ applyInlineStyle(node, keyframeStyle);
+ temporaryStyles.push(keyframeStyle);
+ }
+
+ var itemIndex = stagger
+ ? options.staggerIndex >= 0
+ ? options.staggerIndex
+ : gcsLookup.count(cacheKey)
+ : 0;
+
+ var isFirst = itemIndex === 0;
+
+ // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
+ // without causing any combination of transitions to kick in. By adding a negative delay value
+ // it forces the setup class' transition to end immediately. We later then remove the negative
+ // transition delay to allow for the transition to naturally do it's thing. The beauty here is
+ // that if there is no transition defined then nothing will happen and this will also allow
+ // other transitions to be stacked on top of each other without any chopping them out.
+ if (isFirst && !options.skipBlocking) {
+ blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
+ }
+
+ var timings = computeTimings(node, fullClassName, cacheKey);
+ var relativeDelay = timings.maxDelay;
+ maxDelay = Math.max(relativeDelay, 0);
+ maxDuration = timings.maxDuration;
+
+ var flags = {};
+ flags.hasTransitions = timings.transitionDuration > 0;
+ flags.hasAnimations = timings.animationDuration > 0;
+ flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all';
+ flags.applyTransitionDuration = hasToStyles && (
+ (flags.hasTransitions && !flags.hasTransitionAll)
+ || (flags.hasAnimations && !flags.hasTransitions));
+ flags.applyAnimationDuration = options.duration && flags.hasAnimations;
+ flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions);
+ flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations;
+ flags.recalculateTimingStyles = addRemoveClassName.length > 0;
+
+ if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
+ maxDuration = options.duration ? parseFloat(options.duration) : maxDuration;
+
+ if (flags.applyTransitionDuration) {
+ flags.hasTransitions = true;
+ timings.transitionDuration = maxDuration;
+ applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
+ temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration));
+ }
+
+ if (flags.applyAnimationDuration) {
+ flags.hasAnimations = true;
+ timings.animationDuration = maxDuration;
+ temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration));
+ }
+ }
+
+ if (maxDuration === 0 && !flags.recalculateTimingStyles) {
+ return closeAndReturnNoopAnimator();
+ }
+
+ if (options.delay != null) {
+ var delayStyle = parseFloat(options.delay);
+
+ if (flags.applyTransitionDelay) {
+ temporaryStyles.push(getCssDelayStyle(delayStyle));
+ }
+
+ if (flags.applyAnimationDelay) {
+ temporaryStyles.push(getCssDelayStyle(delayStyle, true));
+ }
+ }
+
+ // we need to recalculate the delay value since we used a pre-emptive negative
+ // delay value and the delay value is required for the final event checking. This
+ // property will ensure that this will happen after the RAF phase has passed.
+ if (options.duration == null && timings.transitionDuration > 0) {
+ flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst;
+ }
+
+ maxDelayTime = maxDelay * ONE_SECOND;
+ maxDurationTime = maxDuration * ONE_SECOND;
+ if (!options.skipBlocking) {
+ flags.blockTransition = timings.transitionDuration > 0;
+ flags.blockKeyframeAnimation = timings.animationDuration > 0 &&
+ stagger.animationDelay > 0 &&
+ stagger.animationDuration === 0;
+ }
+
+ if (options.from) {
+ if (options.cleanupStyles) {
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.from));
+ }
+ applyAnimationFromStyles(element, options);
+ }
+
+ if (flags.blockTransition || flags.blockKeyframeAnimation) {
+ applyBlocking(maxDuration);
+ } else if (!options.skipBlocking) {
+ blockTransitions(node, false);
+ }
+
+ // TODO(matsko): for 1.5 change this code to have an animator object for better debugging
+ return {
+ $$willAnimate: true,
+ end: endFn,
+ start: function() {
+ if (animationClosed) return;
+
+ runnerHost = {
+ end: endFn,
+ cancel: cancelFn,
+ resume: null, //this will be set during the start() phase
+ pause: null
+ };
+
+ runner = new $$AnimateRunner(runnerHost);
+
+ waitUntilQuiet(start);
+
+ // we don't have access to pause/resume the animation
+ // since it hasn't run yet. AnimateRunner will therefore
+ // set noop functions for resume and pause and they will
+ // later be overridden once the animation is triggered
+ return runner;
+ }
+ };
+
+ function endFn() {
+ close();
+ }
+
+ function cancelFn() {
+ close(true);
+ }
+
+ function close(rejected) { // jshint ignore:line
+ // if the promise has been called already then we shouldn't close
+ // the animation again
+ if (animationClosed || (animationCompleted && animationPaused)) return;
+ animationClosed = true;
+ animationPaused = false;
+
+ if (!options.$$skipPreparationClasses) {
+ $$jqLite.removeClass(element, preparationClasses);
+ }
+ $$jqLite.removeClass(element, activeClasses);
+
+ blockKeyframeAnimations(node, false);
+ blockTransitions(node, false);
+
+ forEach(temporaryStyles, function(entry) {
+ // There is only one way to remove inline style properties entirely from elements.
+ // By using `removeProperty` this works, but we need to convert camel-cased CSS
+ // styles down to hyphenated values.
+ node.style[entry[0]] = '';
+ });
+
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+
+ if (Object.keys(restoreStyles).length) {
+ forEach(restoreStyles, function(value, prop) {
+ value ? node.style.setProperty(prop, value)
+ : node.style.removeProperty(prop);
+ });
+ }
+
+ // the reason why we have this option is to allow a synchronous closing callback
+ // that is fired as SOON as the animation ends (when the CSS is removed) or if
+ // the animation never takes off at all. A good example is a leave animation since
+ // the element must be removed just after the animation is over or else the element
+ // will appear on screen for one animation frame causing an overbearing flicker.
+ if (options.onDone) {
+ options.onDone();
+ }
+
+ // if the preparation function fails then the promise is not setup
+ if (runner) {
+ runner.complete(!rejected);
+ }
+ }
+
+ function applyBlocking(duration) {
+ if (flags.blockTransition) {
+ blockTransitions(node, duration);
+ }
+
+ if (flags.blockKeyframeAnimation) {
+ blockKeyframeAnimations(node, !!duration);
+ }
+ }
+
+ function closeAndReturnNoopAnimator() {
+ runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: cancelFn
+ });
+
+ // should flush the cache animation
+ waitUntilQuiet(noop);
+ close();
+
+ return {
+ $$willAnimate: false,
+ start: function() {
+ return runner;
+ },
+ end: endFn
+ };
+ }
+
+ function start() {
+ if (animationClosed) return;
+ if (!node.parentNode) {
+ close();
+ return;
+ }
+
+ var startTime, events = [];
+
+ // even though we only pause keyframe animations here the pause flag
+ // will still happen when transitions are used. Only the transition will
+ // not be paused since that is not possible. If the animation ends when
+ // paused then it will not complete until unpaused or cancelled.
+ var playPause = function(playAnimation) {
+ if (!animationCompleted) {
+ animationPaused = !playAnimation;
+ if (timings.animationDuration) {
+ var value = blockKeyframeAnimations(node, animationPaused);
+ animationPaused
+ ? temporaryStyles.push(value)
+ : removeFromArray(temporaryStyles, value);
+ }
+ } else if (animationPaused && playAnimation) {
+ animationPaused = false;
+ close();
+ }
+ };
+
+ // checking the stagger duration prevents an accidently cascade of the CSS delay style
+ // being inherited from the parent. If the transition duration is zero then we can safely
+ // rely that the delay value is an intential stagger delay style.
+ var maxStagger = itemIndex > 0
+ && ((timings.transitionDuration && stagger.transitionDuration === 0) ||
+ (timings.animationDuration && stagger.animationDuration === 0))
+ && Math.max(stagger.animationDelay, stagger.transitionDelay);
+ if (maxStagger) {
+ $timeout(triggerAnimationStart,
+ Math.floor(maxStagger * itemIndex * ONE_SECOND),
+ false);
+ } else {
+ triggerAnimationStart();
+ }
+
+ // this will decorate the existing promise runner with pause/resume methods
+ runnerHost.resume = function() {
+ playPause(true);
+ };
+
+ runnerHost.pause = function() {
+ playPause(false);
+ };
+
+ function triggerAnimationStart() {
+ // just incase a stagger animation kicks in when the animation
+ // itself was cancelled entirely
+ if (animationClosed) return;
+
+ applyBlocking(false);
+
+ forEach(temporaryStyles, function(entry) {
+ var key = entry[0];
+ var value = entry[1];
+ node.style[key] = value;
+ });
+
+ applyAnimationClasses(element, options);
+ $$jqLite.addClass(element, activeClasses);
+
+ if (flags.recalculateTimingStyles) {
+ fullClassName = node.className + ' ' + preparationClasses;
+ cacheKey = gcsHashFn(node, fullClassName);
+
+ timings = computeTimings(node, fullClassName, cacheKey);
+ relativeDelay = timings.maxDelay;
+ maxDelay = Math.max(relativeDelay, 0);
+ maxDuration = timings.maxDuration;
+
+ if (maxDuration === 0) {
+ close();
+ return;
+ }
+
+ flags.hasTransitions = timings.transitionDuration > 0;
+ flags.hasAnimations = timings.animationDuration > 0;
+ }
+
+ if (flags.applyAnimationDelay) {
+ relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay)
+ ? parseFloat(options.delay)
+ : relativeDelay;
+
+ maxDelay = Math.max(relativeDelay, 0);
+ timings.animationDelay = relativeDelay;
+ delayStyle = getCssDelayStyle(relativeDelay, true);
+ temporaryStyles.push(delayStyle);
+ node.style[delayStyle[0]] = delayStyle[1];
+ }
+
+ maxDelayTime = maxDelay * ONE_SECOND;
+ maxDurationTime = maxDuration * ONE_SECOND;
+
+ if (options.easing) {
+ var easeProp, easeVal = options.easing;
+ if (flags.hasTransitions) {
+ easeProp = TRANSITION_PROP + TIMING_KEY;
+ temporaryStyles.push([easeProp, easeVal]);
+ node.style[easeProp] = easeVal;
+ }
+ if (flags.hasAnimations) {
+ easeProp = ANIMATION_PROP + TIMING_KEY;
+ temporaryStyles.push([easeProp, easeVal]);
+ node.style[easeProp] = easeVal;
+ }
+ }
+
+ if (timings.transitionDuration) {
+ events.push(TRANSITIONEND_EVENT);
+ }
+
+ if (timings.animationDuration) {
+ events.push(ANIMATIONEND_EVENT);
+ }
+
+ startTime = Date.now();
+ var timerTime = maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime;
+ var endTime = startTime + timerTime;
+
+ var animationsData = element.data(ANIMATE_TIMER_KEY) || [];
+ var setupFallbackTimer = true;
+ if (animationsData.length) {
+ var currentTimerData = animationsData[0];
+ setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
+ if (setupFallbackTimer) {
+ $timeout.cancel(currentTimerData.timer);
+ } else {
+ animationsData.push(close);
+ }
+ }
+
+ if (setupFallbackTimer) {
+ var timer = $timeout(onAnimationExpired, timerTime, false);
+ animationsData[0] = {
+ timer: timer,
+ expectedEndTime: endTime
+ };
+ animationsData.push(close);
+ element.data(ANIMATE_TIMER_KEY, animationsData);
+ }
+
+ element.on(events.join(' '), onAnimationProgress);
+ if (options.to) {
+ if (options.cleanupStyles) {
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
+ }
+ applyAnimationToStyles(element, options);
+ }
+ }
+
+ function onAnimationExpired() {
+ var animationsData = element.data(ANIMATE_TIMER_KEY);
+
+ // this will be false in the event that the element was
+ // removed from the DOM (via a leave animation or something
+ // similar)
+ if (animationsData) {
+ for (var i = 1; i < animationsData.length; i++) {
+ animationsData[i]();
+ }
+ element.removeData(ANIMATE_TIMER_KEY);
+ }
+ }
+
+ function onAnimationProgress(event) {
+ event.stopPropagation();
+ var ev = event.originalEvent || event;
+ var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
+
+ /* Firefox (or possibly just Gecko) likes to not round values up
+ * when a ms measurement is used for the animation */
+ var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
+
+ /* $manualTimeStamp is a mocked timeStamp value which is set
+ * within browserTrigger(). This is only here so that tests can
+ * mock animations properly. Real events fallback to event.timeStamp,
+ * or, if they don't, then a timeStamp is automatically created for them.
+ * We're checking to see if the timeStamp surpasses the expected delay,
+ * but we're using elapsedTime instead of the timeStamp on the 2nd
+ * pre-condition since animations sometimes close off early */
+ if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
+ // we set this flag to ensure that if the transition is paused then, when resumed,
+ // the animation will automatically close itself since transitions cannot be paused.
+ animationCompleted = true;
+ close();
+ }
+ }
+ }
+ };
+ }];
+}];
+
+var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) {
+ $$animationProvider.drivers.push('$$animateCssDriver');
+
+ var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim';
+ var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor';
+
+ var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
+ var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
+
+ function isDocumentFragment(node) {
+ return node.parentNode && node.parentNode.nodeType === 11;
+ }
+
+ this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document',
+ function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) {
+
+ // only browsers that support these properties can render animations
+ if (!$sniffer.animations && !$sniffer.transitions) return noop;
+
+ var bodyNode = $document[0].body;
+ var rootNode = getDomNode($rootElement);
+
+ var rootBodyElement = jqLite(
+ // this is to avoid using something that exists outside of the body
+ // we also special case the doc fragement case because our unit test code
+ // appends the $rootElement to the body after the app has been bootstrapped
+ isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
+ );
+
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+
+ return function initDriverFn(animationDetails) {
+ return animationDetails.from && animationDetails.to
+ ? prepareFromToAnchorAnimation(animationDetails.from,
+ animationDetails.to,
+ animationDetails.classes,
+ animationDetails.anchors)
+ : prepareRegularAnimation(animationDetails);
+ };
+
+ function filterCssClasses(classes) {
+ //remove all the `ng-` stuff
+ return classes.replace(/\bng-\S+\b/g, '');
+ }
+
+ function getUniqueValues(a, b) {
+ if (isString(a)) a = a.split(' ');
+ if (isString(b)) b = b.split(' ');
+ return a.filter(function(val) {
+ return b.indexOf(val) === -1;
+ }).join(' ');
+ }
+
+ function prepareAnchoredAnimation(classes, outAnchor, inAnchor) {
+ var clone = jqLite(getDomNode(outAnchor).cloneNode(true));
+ var startingClasses = filterCssClasses(getClassVal(clone));
+
+ outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
+
+ clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME);
+
+ rootBodyElement.append(clone);
+
+ var animatorIn, animatorOut = prepareOutAnimation();
+
+ // the user may not end up using the `out` animation and
+ // only making use of the `in` animation or vice-versa.
+ // In either case we should allow this and not assume the
+ // animation is over unless both animations are not used.
+ if (!animatorOut) {
+ animatorIn = prepareInAnimation();
+ if (!animatorIn) {
+ return end();
+ }
+ }
+
+ var startingAnimator = animatorOut || animatorIn;
+
+ return {
+ start: function() {
+ var runner;
+
+ var currentAnimation = startingAnimator.start();
+ currentAnimation.done(function() {
+ currentAnimation = null;
+ if (!animatorIn) {
+ animatorIn = prepareInAnimation();
+ if (animatorIn) {
+ currentAnimation = animatorIn.start();
+ currentAnimation.done(function() {
+ currentAnimation = null;
+ end();
+ runner.complete();
+ });
+ return currentAnimation;
+ }
+ }
+ // in the event that there is no `in` animation
+ end();
+ runner.complete();
+ });
+
+ runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: endFn
+ });
+
+ return runner;
+
+ function endFn() {
+ if (currentAnimation) {
+ currentAnimation.end();
+ }
+ }
+ }
+ };
+
+ function calculateAnchorStyles(anchor) {
+ var styles = {};
+
+ var coords = getDomNode(anchor).getBoundingClientRect();
+
+ // we iterate directly since safari messes up and doesn't return
+ // all the keys for the coods object when iterated
+ forEach(['width','height','top','left'], function(key) {
+ var value = coords[key];
+ switch (key) {
+ case 'top':
+ value += bodyNode.scrollTop;
+ break;
+ case 'left':
+ value += bodyNode.scrollLeft;
+ break;
+ }
+ styles[key] = Math.floor(value) + 'px';
+ });
+ return styles;
+ }
+
+ function prepareOutAnimation() {
+ var animator = $animateCss(clone, {
+ addClass: NG_OUT_ANCHOR_CLASS_NAME,
+ delay: true,
+ from: calculateAnchorStyles(outAnchor)
+ });
+
+ // read the comment within `prepareRegularAnimation` to understand
+ // why this check is necessary
+ return animator.$$willAnimate ? animator : null;
+ }
+
+ function getClassVal(element) {
+ return element.attr('class') || '';
+ }
+
+ function prepareInAnimation() {
+ var endingClasses = filterCssClasses(getClassVal(inAnchor));
+ var toAdd = getUniqueValues(endingClasses, startingClasses);
+ var toRemove = getUniqueValues(startingClasses, endingClasses);
+
+ var animator = $animateCss(clone, {
+ to: calculateAnchorStyles(inAnchor),
+ addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd,
+ removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove,
+ delay: true
+ });
+
+ // read the comment within `prepareRegularAnimation` to understand
+ // why this check is necessary
+ return animator.$$willAnimate ? animator : null;
+ }
+
+ function end() {
+ clone.remove();
+ outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
+ }
+ }
+
+ function prepareFromToAnchorAnimation(from, to, classes, anchors) {
+ var fromAnimation = prepareRegularAnimation(from, noop);
+ var toAnimation = prepareRegularAnimation(to, noop);
+
+ var anchorAnimations = [];
+ forEach(anchors, function(anchor) {
+ var outElement = anchor['out'];
+ var inElement = anchor['in'];
+ var animator = prepareAnchoredAnimation(classes, outElement, inElement);
+ if (animator) {
+ anchorAnimations.push(animator);
+ }
+ });
+
+ // no point in doing anything when there are no elements to animate
+ if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return;
+
+ return {
+ start: function() {
+ var animationRunners = [];
+
+ if (fromAnimation) {
+ animationRunners.push(fromAnimation.start());
+ }
+
+ if (toAnimation) {
+ animationRunners.push(toAnimation.start());
+ }
+
+ forEach(anchorAnimations, function(animation) {
+ animationRunners.push(animation.start());
+ });
+
+ var runner = new $$AnimateRunner({
+ end: endFn,
+ cancel: endFn // CSS-driven animations cannot be cancelled, only ended
+ });
+
+ $$AnimateRunner.all(animationRunners, function(status) {
+ runner.complete(status);
+ });
+
+ return runner;
+
+ function endFn() {
+ forEach(animationRunners, function(runner) {
+ runner.end();
+ });
+ }
+ }
+ };
+ }
+
+ function prepareRegularAnimation(animationDetails) {
+ var element = animationDetails.element;
+ var options = animationDetails.options || {};
+
+ if (animationDetails.structural) {
+ options.event = animationDetails.event;
+ options.structural = true;
+ options.applyClassesEarly = true;
+
+ // we special case the leave animation since we want to ensure that
+ // the element is removed as soon as the animation is over. Otherwise
+ // a flicker might appear or the element may not be removed at all
+ if (animationDetails.event === 'leave') {
+ options.onDone = options.domOperation;
+ }
+ }
+
+ // We assign the preparationClasses as the actual animation event since
+ // the internals of $animateCss will just suffix the event token values
+ // with `-active` to trigger the animation.
+ if (options.preparationClasses) {
+ options.event = concatWithSpace(options.event, options.preparationClasses);
+ }
+
+ var animator = $animateCss(element, options);
+
+ // the driver lookup code inside of $$animation attempts to spawn a
+ // driver one by one until a driver returns a.$$willAnimate animator object.
+ // $animateCss will always return an object, however, it will pass in
+ // a flag as a hint as to whether an animation was detected or not
+ return animator.$$willAnimate ? animator : null;
+ }
+ }];
+}];
+
+// TODO(matsko): use caching here to speed things up for detection
+// TODO(matsko): add documentation
+// by the time...
+
+var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
+ this.$get = ['$injector', '$$AnimateRunner', '$$jqLite',
+ function($injector, $$AnimateRunner, $$jqLite) {
+
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+ // $animateJs(element, 'enter');
+ return function(element, event, classes, options) {
+ // the `classes` argument is optional and if it is not used
+ // then the classes will be resolved from the element's className
+ // property as well as options.addClass/options.removeClass.
+ if (arguments.length === 3 && isObject(classes)) {
+ options = classes;
+ classes = null;
+ }
+
+ options = prepareAnimationOptions(options);
+ if (!classes) {
+ classes = element.attr('class') || '';
+ if (options.addClass) {
+ classes += ' ' + options.addClass;
+ }
+ if (options.removeClass) {
+ classes += ' ' + options.removeClass;
+ }
+ }
+
+ var classesToAdd = options.addClass;
+ var classesToRemove = options.removeClass;
+
+ // the lookupAnimations function returns a series of animation objects that are
+ // matched up with one or more of the CSS classes. These animation objects are
+ // defined via the module.animation factory function. If nothing is detected then
+ // we don't return anything which then makes $animation query the next driver.
+ var animations = lookupAnimations(classes);
+ var before, after;
+ if (animations.length) {
+ var afterFn, beforeFn;
+ if (event == 'leave') {
+ beforeFn = 'leave';
+ afterFn = 'afterLeave'; // TODO(matsko): get rid of this
+ } else {
+ beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1);
+ afterFn = event;
+ }
+
+ if (event !== 'enter' && event !== 'move') {
+ before = packageAnimations(element, event, options, animations, beforeFn);
+ }
+ after = packageAnimations(element, event, options, animations, afterFn);
+ }
+
+ // no matching animations
+ if (!before && !after) return;
+
+ function applyOptions() {
+ options.domOperation();
+ applyAnimationClasses(element, options);
+ }
+
+ return {
+ start: function() {
+ var closeActiveAnimations;
+ var chain = [];
+
+ if (before) {
+ chain.push(function(fn) {
+ closeActiveAnimations = before(fn);
+ });
+ }
+
+ if (chain.length) {
+ chain.push(function(fn) {
+ applyOptions();
+ fn(true);
+ });
+ } else {
+ applyOptions();
+ }
+
+ if (after) {
+ chain.push(function(fn) {
+ closeActiveAnimations = after(fn);
+ });
+ }
+
+ var animationClosed = false;
+ var runner = new $$AnimateRunner({
+ end: function() {
+ endAnimations();
+ },
+ cancel: function() {
+ endAnimations(true);
+ }
+ });
+
+ $$AnimateRunner.chain(chain, onComplete);
+ return runner;
+
+ function onComplete(success) {
+ animationClosed = true;
+ applyOptions();
+ applyAnimationStyles(element, options);
+ runner.complete(success);
+ }
+
+ function endAnimations(cancelled) {
+ if (!animationClosed) {
+ (closeActiveAnimations || noop)(cancelled);
+ onComplete(cancelled);
+ }
+ }
+ }
+ };
+
+ function executeAnimationFn(fn, element, event, options, onDone) {
+ var args;
+ switch (event) {
+ case 'animate':
+ args = [element, options.from, options.to, onDone];
+ break;
+
+ case 'setClass':
+ args = [element, classesToAdd, classesToRemove, onDone];
+ break;
+
+ case 'addClass':
+ args = [element, classesToAdd, onDone];
+ break;
+
+ case 'removeClass':
+ args = [element, classesToRemove, onDone];
+ break;
+
+ default:
+ args = [element, onDone];
+ break;
+ }
+
+ args.push(options);
+
+ var value = fn.apply(fn, args);
+ if (value) {
+ if (isFunction(value.start)) {
+ value = value.start();
+ }
+
+ if (value instanceof $$AnimateRunner) {
+ value.done(onDone);
+ } else if (isFunction(value)) {
+ // optional onEnd / onCancel callback
+ return value;
+ }
+ }
+
+ return noop;
+ }
+
+ function groupEventedAnimations(element, event, options, animations, fnName) {
+ var operations = [];
+ forEach(animations, function(ani) {
+ var animation = ani[fnName];
+ if (!animation) return;
+
+ // note that all of these animations will run in parallel
+ operations.push(function() {
+ var runner;
+ var endProgressCb;
+
+ var resolved = false;
+ var onAnimationComplete = function(rejected) {
+ if (!resolved) {
+ resolved = true;
+ (endProgressCb || noop)(rejected);
+ runner.complete(!rejected);
+ }
+ };
+
+ runner = new $$AnimateRunner({
+ end: function() {
+ onAnimationComplete();
+ },
+ cancel: function() {
+ onAnimationComplete(true);
+ }
+ });
+
+ endProgressCb = executeAnimationFn(animation, element, event, options, function(result) {
+ var cancelled = result === false;
+ onAnimationComplete(cancelled);
+ });
+
+ return runner;
+ });
+ });
+
+ return operations;
+ }
+
+ function packageAnimations(element, event, options, animations, fnName) {
+ var operations = groupEventedAnimations(element, event, options, animations, fnName);
+ if (operations.length === 0) {
+ var a,b;
+ if (fnName === 'beforeSetClass') {
+ a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass');
+ b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass');
+ } else if (fnName === 'setClass') {
+ a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass');
+ b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass');
+ }
+
+ if (a) {
+ operations = operations.concat(a);
+ }
+ if (b) {
+ operations = operations.concat(b);
+ }
+ }
+
+ if (operations.length === 0) return;
+
+ // TODO(matsko): add documentation
+ return function startAnimation(callback) {
+ var runners = [];
+ if (operations.length) {
+ forEach(operations, function(animateFn) {
+ runners.push(animateFn());
+ });
+ }
+
+ runners.length ? $$AnimateRunner.all(runners, callback) : callback();
+
+ return function endFn(reject) {
+ forEach(runners, function(runner) {
+ reject ? runner.cancel() : runner.end();
+ });
+ };
+ };
+ }
+ };
+
+ function lookupAnimations(classes) {
+ classes = isArray(classes) ? classes : classes.split(' ');
+ var matches = [], flagMap = {};
+ for (var i=0; i < classes.length; i++) {
+ var klass = classes[i],
+ animationFactory = $animateProvider.$$registeredAnimations[klass];
+ if (animationFactory && !flagMap[klass]) {
+ matches.push($injector.get(animationFactory));
+ flagMap[klass] = true;
+ }
+ }
+ return matches;
+ }
+ }];
+}];
+
+var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) {
+ $$animationProvider.drivers.push('$$animateJsDriver');
+ this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) {
+ return function initDriverFn(animationDetails) {
+ if (animationDetails.from && animationDetails.to) {
+ var fromAnimation = prepareAnimation(animationDetails.from);
+ var toAnimation = prepareAnimation(animationDetails.to);
+ if (!fromAnimation && !toAnimation) return;
+
+ return {
+ start: function() {
+ var animationRunners = [];
+
+ if (fromAnimation) {
+ animationRunners.push(fromAnimation.start());
+ }
+
+ if (toAnimation) {
+ animationRunners.push(toAnimation.start());
+ }
+
+ $$AnimateRunner.all(animationRunners, done);
+
+ var runner = new $$AnimateRunner({
+ end: endFnFactory(),
+ cancel: endFnFactory()
+ });
+
+ return runner;
+
+ function endFnFactory() {
+ return function() {
+ forEach(animationRunners, function(runner) {
+ // at this point we cannot cancel animations for groups just yet. 1.5+
+ runner.end();
+ });
+ };
+ }
+
+ function done(status) {
+ runner.complete(status);
+ }
+ }
+ };
+ } else {
+ return prepareAnimation(animationDetails);
+ }
+ };
+
+ function prepareAnimation(animationDetails) {
+ // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations
+ var element = animationDetails.element;
+ var event = animationDetails.event;
+ var options = animationDetails.options;
+ var classes = animationDetails.classes;
+ return $$animateJs(element, event, classes, options);
+ }
+ }];
+}];
+
+var NG_ANIMATE_ATTR_NAME = 'data-ng-animate';
+var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
+var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
+ var PRE_DIGEST_STATE = 1;
+ var RUNNING_STATE = 2;
+
+ var rules = this.rules = {
+ skip: [],
+ cancel: [],
+ join: []
+ };
+
+ function isAllowed(ruleType, element, currentAnimation, previousAnimation) {
+ return rules[ruleType].some(function(fn) {
+ return fn(element, currentAnimation, previousAnimation);
+ });
+ }
+
+ function hasAnimationClasses(options, and) {
+ options = options || {};
+ var a = (options.addClass || '').length > 0;
+ var b = (options.removeClass || '').length > 0;
+ return and ? a && b : a || b;
+ }
+
+ rules.join.push(function(element, newAnimation, currentAnimation) {
+ // if the new animation is class-based then we can just tack that on
+ return !newAnimation.structural && hasAnimationClasses(newAnimation.options);
+ });
+
+ rules.skip.push(function(element, newAnimation, currentAnimation) {
+ // there is no need to animate anything if no classes are being added and
+ // there is no structural animation that will be triggered
+ return !newAnimation.structural && !hasAnimationClasses(newAnimation.options);
+ });
+
+ rules.skip.push(function(element, newAnimation, currentAnimation) {
+ // why should we trigger a new structural animation if the element will
+ // be removed from the DOM anyway?
+ return currentAnimation.event == 'leave' && newAnimation.structural;
+ });
+
+ rules.skip.push(function(element, newAnimation, currentAnimation) {
+ // if there is an ongoing current animation then don't even bother running the class-based animation
+ return currentAnimation.structural && currentAnimation.state === RUNNING_STATE && !newAnimation.structural;
+ });
+
+ rules.cancel.push(function(element, newAnimation, currentAnimation) {
+ // there can never be two structural animations running at the same time
+ return currentAnimation.structural && newAnimation.structural;
+ });
+
+ rules.cancel.push(function(element, newAnimation, currentAnimation) {
+ // if the previous animation is already running, but the new animation will
+ // be triggered, but the new animation is structural
+ return currentAnimation.state === RUNNING_STATE && newAnimation.structural;
+ });
+
+ rules.cancel.push(function(element, newAnimation, currentAnimation) {
+ var nO = newAnimation.options;
+ var cO = currentAnimation.options;
+
+ // if the exact same CSS class is added/removed then it's safe to cancel it
+ return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
+ });
+
+ this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
+ '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', '$$forceReflow',
+ function($$rAF, $rootScope, $rootElement, $document, $$HashMap,
+ $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) {
+
+ var activeAnimationsLookup = new $$HashMap();
+ var disabledElementsLookup = new $$HashMap();
+ var animationsEnabled = null;
+
+ function postDigestTaskFactory() {
+ var postDigestCalled = false;
+ return function(fn) {
+ // we only issue a call to postDigest before
+ // it has first passed. This prevents any callbacks
+ // from not firing once the animation has completed
+ // since it will be out of the digest cycle.
+ if (postDigestCalled) {
+ fn();
+ } else {
+ $rootScope.$$postDigest(function() {
+ postDigestCalled = true;
+ fn();
+ });
+ }
+ };
+ }
+
+ // Wait until all directive and route-related templates are downloaded and
+ // compiled. The $templateRequest.totalPendingRequests variable keeps track of
+ // all of the remote templates being currently downloaded. If there are no
+ // templates currently downloading then the watcher will still fire anyway.
+ var deregisterWatch = $rootScope.$watch(
+ function() { return $templateRequest.totalPendingRequests === 0; },
+ function(isEmpty) {
+ if (!isEmpty) return;
+ deregisterWatch();
+
+ // Now that all templates have been downloaded, $animate will wait until
+ // the post digest queue is empty before enabling animations. By having two
+ // calls to $postDigest calls we can ensure that the flag is enabled at the
+ // very end of the post digest queue. Since all of the animations in $animate
+ // use $postDigest, it's important that the code below executes at the end.
+ // This basically means that the page is fully downloaded and compiled before
+ // any animations are triggered.
+ $rootScope.$$postDigest(function() {
+ $rootScope.$$postDigest(function() {
+ // we check for null directly in the event that the application already called
+ // .enabled() with whatever arguments that it provided it with
+ if (animationsEnabled === null) {
+ animationsEnabled = true;
+ }
+ });
+ });
+ }
+ );
+
+ var callbackRegistry = {};
+
+ // remember that the classNameFilter is set during the provider/config
+ // stage therefore we can optimize here and setup a helper function
+ var classNameFilter = $animateProvider.classNameFilter();
+ var isAnimatableClassName = !classNameFilter
+ ? function() { return true; }
+ : function(className) {
+ return classNameFilter.test(className);
+ };
+
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+
+ function normalizeAnimationOptions(element, options) {
+ return mergeAnimationOptions(element, options, {});
+ }
+
+ function findCallbacks(parent, element, event) {
+ var targetNode = getDomNode(element);
+ var targetParentNode = getDomNode(parent);
+
+ var matches = [];
+ var entries = callbackRegistry[event];
+ if (entries) {
+ forEach(entries, function(entry) {
+ if (entry.node.contains(targetNode)) {
+ matches.push(entry.callback);
+ } else if (event === 'leave' && entry.node.contains(targetParentNode)) {
+ matches.push(entry.callback);
+ }
+ });
+ }
+
+ return matches;
+ }
+
+ return {
+ on: function(event, container, callback) {
+ var node = extractElementNode(container);
+ callbackRegistry[event] = callbackRegistry[event] || [];
+ callbackRegistry[event].push({
+ node: node,
+ callback: callback
+ });
+ },
+
+ off: function(event, container, callback) {
+ var entries = callbackRegistry[event];
+ if (!entries) return;
+
+ callbackRegistry[event] = arguments.length === 1
+ ? null
+ : filterFromRegistry(entries, container, callback);
+
+ function filterFromRegistry(list, matchContainer, matchCallback) {
+ var containerNode = extractElementNode(matchContainer);
+ return list.filter(function(entry) {
+ var isMatch = entry.node === containerNode &&
+ (!matchCallback || entry.callback === matchCallback);
+ return !isMatch;
+ });
+ }
+ },
+
+ pin: function(element, parentElement) {
+ assertArg(isElement(element), 'element', 'not an element');
+ assertArg(isElement(parentElement), 'parentElement', 'not an element');
+ element.data(NG_ANIMATE_PIN_DATA, parentElement);
+ },
+
+ push: function(element, event, options, domOperation) {
+ options = options || {};
+ options.domOperation = domOperation;
+ return queueAnimation(element, event, options);
+ },
+
+ // this method has four signatures:
+ // () - global getter
+ // (bool) - global setter
+ // (element) - element getter
+ // (element, bool) - element setter<F37>
+ enabled: function(element, bool) {
+ var argCount = arguments.length;
+
+ if (argCount === 0) {
+ // () - Global getter
+ bool = !!animationsEnabled;
+ } else {
+ var hasElement = isElement(element);
+
+ if (!hasElement) {
+ // (bool) - Global setter
+ bool = animationsEnabled = !!element;
+ } else {
+ var node = getDomNode(element);
+ var recordExists = disabledElementsLookup.get(node);
+
+ if (argCount === 1) {
+ // (element) - Element getter
+ bool = !recordExists;
+ } else {
+ // (element, bool) - Element setter
+ bool = !!bool;
+ if (!bool) {
+ disabledElementsLookup.put(node, true);
+ } else if (recordExists) {
+ disabledElementsLookup.remove(node);
+ }
+ }
+ }
+ }
+
+ return bool;
+ }
+ };
+
+ function queueAnimation(element, event, options) {
+ var node, parent;
+ element = stripCommentsFromElement(element);
+ if (element) {
+ node = getDomNode(element);
+ parent = element.parent();
+ }
+
+ options = prepareAnimationOptions(options);
+
+ // we create a fake runner with a working promise.
+ // These methods will become available after the digest has passed
+ var runner = new $$AnimateRunner();
+
+ // this is used to trigger callbacks in postDigest mode
+ var runInNextPostDigestOrNow = postDigestTaskFactory();
+
+ if (isArray(options.addClass)) {
+ options.addClass = options.addClass.join(' ');
+ }
+
+ if (options.addClass && !isString(options.addClass)) {
+ options.addClass = null;
+ }
+
+ if (isArray(options.removeClass)) {
+ options.removeClass = options.removeClass.join(' ');
+ }
+
+ if (options.removeClass && !isString(options.removeClass)) {
+ options.removeClass = null;
+ }
+
+ if (options.from && !isObject(options.from)) {
+ options.from = null;
+ }
+
+ if (options.to && !isObject(options.to)) {
+ options.to = null;
+ }
+
+ // there are situations where a directive issues an animation for
+ // a jqLite wrapper that contains only comment nodes... If this
+ // happens then there is no way we can perform an animation
+ if (!node) {
+ close();
+ return runner;
+ }
+
+ var className = [node.className, options.addClass, options.removeClass].join(' ');
+ if (!isAnimatableClassName(className)) {
+ close();
+ return runner;
+ }
+
+ var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
+
+ // this is a hard disable of all animations for the application or on
+ // the element itself, therefore there is no need to continue further
+ // past this point if not enabled
+ var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
+ var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
+ var hasExistingAnimation = !!existingAnimation.state;
+
+ // there is no point in traversing the same collection of parent ancestors if a followup
+ // animation will be run on the same element that already did all that checking work
+ if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) {
+ skipAnimations = !areAnimationsAllowed(element, parent, event);
+ }
+
+ if (skipAnimations) {
+ close();
+ return runner;
+ }
+
+ if (isStructural) {
+ closeChildAnimations(element);
+ }
+
+ var newAnimation = {
+ structural: isStructural,
+ element: element,
+ event: event,
+ close: close,
+ options: options,
+ runner: runner
+ };
+
+ if (hasExistingAnimation) {
+ var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation);
+ if (skipAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ close();
+ return runner;
+ } else {
+ mergeAnimationOptions(element, existingAnimation.options, options);
+ return existingAnimation.runner;
+ }
+ }
+
+ var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation);
+ if (cancelAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ // this will end the animation right away and it is safe
+ // to do so since the animation is already running and the
+ // runner callback code will run in async
+ existingAnimation.runner.end();
+ } else if (existingAnimation.structural) {
+ // this means that the animation is queued into a digest, but
+ // hasn't started yet. Therefore it is safe to run the close
+ // method which will call the runner methods in async.
+ existingAnimation.close();
+ } else {
+ // this will merge the new animation options into existing animation options
+ mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
+ return existingAnimation.runner;
+ }
+ } else {
+ // a joined animation means that this animation will take over the existing one
+ // so an example would involve a leave animation taking over an enter. Then when
+ // the postDigest kicks in the enter will be ignored.
+ var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
+ if (joinAnimationFlag) {
+ if (existingAnimation.state === RUNNING_STATE) {
+ normalizeAnimationOptions(element, options);
+ } else {
+ applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
+
+ event = newAnimation.event = existingAnimation.event;
+ options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
+
+ //we return the same runner since only the option values of this animation will
+ //be fed into the `existingAnimation`.
+ return existingAnimation.runner;
+ }
+ }
+ }
+ } else {
+ // normalization in this case means that it removes redundant CSS classes that
+ // already exist (addClass) or do not exist (removeClass) on the element
+ normalizeAnimationOptions(element, options);
+ }
+
+ // when the options are merged and cleaned up we may end up not having to do
+ // an animation at all, therefore we should check this before issuing a post
+ // digest callback. Structural animations will always run no matter what.
+ var isValidAnimation = newAnimation.structural;
+ if (!isValidAnimation) {
+ // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
+ isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
+ || hasAnimationClasses(newAnimation.options);
+ }
+
+ if (!isValidAnimation) {
+ close();
+ clearElementAnimationState(element);
+ return runner;
+ }
+
+ // the counter keeps track of cancelled animations
+ var counter = (existingAnimation.counter || 0) + 1;
+ newAnimation.counter = counter;
+
+ markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation);
+
+ $rootScope.$$postDigest(function() {
+ var animationDetails = activeAnimationsLookup.get(node);
+ var animationCancelled = !animationDetails;
+ animationDetails = animationDetails || {};
+
+ // if addClass/removeClass is called before something like enter then the
+ // registered parent element may not be present. The code below will ensure
+ // that a final value for parent element is obtained
+ var parentElement = element.parent() || [];
+
+ // animate/structural/class-based animations all have requirements. Otherwise there
+ // is no point in performing an animation. The parent node must also be set.
+ var isValidAnimation = parentElement.length > 0
+ && (animationDetails.event === 'animate'
+ || animationDetails.structural
+ || hasAnimationClasses(animationDetails.options));
+
+ // this means that the previous animation was cancelled
+ // even if the follow-up animation is the same event
+ if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) {
+ // if another animation did not take over then we need
+ // to make sure that the domOperation and options are
+ // handled accordingly
+ if (animationCancelled) {
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ }
+
+ // if the event changed from something like enter to leave then we do
+ // it, otherwise if it's the same then the end result will be the same too
+ if (animationCancelled || (isStructural && animationDetails.event !== event)) {
+ options.domOperation();
+ runner.end();
+ }
+
+ // in the event that the element animation was not cancelled or a follow-up animation
+ // isn't allowed to animate from here then we need to clear the state of the element
+ // so that any future animations won't read the expired animation data.
+ if (!isValidAnimation) {
+ clearElementAnimationState(element);
+ }
+
+ return;
+ }
+
+ // this combined multiple class to addClass / removeClass into a setClass event
+ // so long as a structural event did not take over the animation
+ event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true)
+ ? 'setClass'
+ : animationDetails.event;
+
+ markElementAnimationState(element, RUNNING_STATE);
+ var realRunner = $$animation(element, event, animationDetails.options);
+
+ realRunner.done(function(status) {
+ close(!status);
+ var animationDetails = activeAnimationsLookup.get(node);
+ if (animationDetails && animationDetails.counter === counter) {
+ clearElementAnimationState(getDomNode(element));
+ }
+ notifyProgress(runner, event, 'close', {});
+ });
+
+ // this will update the runner's flow-control events based on
+ // the `realRunner` object.
+ runner.setHost(realRunner);
+ notifyProgress(runner, event, 'start', {});
+ });
+
+ return runner;
+
+ function notifyProgress(runner, event, phase, data) {
+ runInNextPostDigestOrNow(function() {
+ var callbacks = findCallbacks(parent, element, event);
+ if (callbacks.length) {
+ // do not optimize this call here to RAF because
+ // we don't know how heavy the callback code here will
+ // be and if this code is buffered then this can
+ // lead to a performance regression.
+ $$rAF(function() {
+ forEach(callbacks, function(callback) {
+ callback(element, phase, data);
+ });
+ });
+ }
+ });
+ runner.progress(event, phase, data);
+ }
+
+ function close(reject) { // jshint ignore:line
+ clearGeneratedClasses(element, options);
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ options.domOperation();
+ runner.complete(!reject);
+ }
+ }
+
+ function closeChildAnimations(element) {
+ var node = getDomNode(element);
+ var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']');
+ forEach(children, function(child) {
+ var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME));
+ var animationDetails = activeAnimationsLookup.get(child);
+ switch (state) {
+ case RUNNING_STATE:
+ animationDetails.runner.end();
+ /* falls through */
+ case PRE_DIGEST_STATE:
+ if (animationDetails) {
+ activeAnimationsLookup.remove(child);
+ }
+ break;
+ }
+ });
+ }
+
+ function clearElementAnimationState(element) {
+ var node = getDomNode(element);
+ node.removeAttribute(NG_ANIMATE_ATTR_NAME);
+ activeAnimationsLookup.remove(node);
+ }
+
+ function isMatchingElement(nodeOrElmA, nodeOrElmB) {
+ return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
+ }
+
+ function areAnimationsAllowed(element, parentElement, event) {
+ var bodyElement = jqLite($document[0].body);
+ var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
+ var rootElementDetected = isMatchingElement(element, $rootElement);
+ var parentAnimationDetected = false;
+ var animateChildren;
+
+ var parentHost = element.data(NG_ANIMATE_PIN_DATA);
+ if (parentHost) {
+ parentElement = parentHost;
+ }
+
+ while (parentElement && parentElement.length) {
+ if (!rootElementDetected) {
+ // angular doesn't want to attempt to animate elements outside of the application
+ // therefore we need to ensure that the rootElement is an ancestor of the current element
+ rootElementDetected = isMatchingElement(parentElement, $rootElement);
+ }
+
+ var parentNode = parentElement[0];
+ if (parentNode.nodeType !== ELEMENT_NODE) {
+ // no point in inspecting the #document element
+ break;
+ }
+
+ var details = activeAnimationsLookup.get(parentNode) || {};
+ // either an enter, leave or move animation will commence
+ // therefore we can't allow any animations to take place
+ // but if a parent animation is class-based then that's ok
+ if (!parentAnimationDetected) {
+ parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode);
+ }
+
+ if (isUndefined(animateChildren) || animateChildren === true) {
+ var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA);
+ if (isDefined(value)) {
+ animateChildren = value;
+ }
+ }
+
+ // there is no need to continue traversing at this point
+ if (parentAnimationDetected && animateChildren === false) break;
+
+ if (!rootElementDetected) {
+ // angular doesn't want to attempt to animate elements outside of the application
+ // therefore we need to ensure that the rootElement is an ancestor of the current element
+ rootElementDetected = isMatchingElement(parentElement, $rootElement);
+ if (!rootElementDetected) {
+ parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
+ if (parentHost) {
+ parentElement = parentHost;
+ }
+ }
+ }
+
+ if (!bodyElementDetected) {
+ // we also need to ensure that the element is or will be apart of the body element
+ // otherwise it is pointless to even issue an animation to be rendered
+ bodyElementDetected = isMatchingElement(parentElement, bodyElement);
+ }
+
+ parentElement = parentElement.parent();
+ }
+
+ var allowAnimation = !parentAnimationDetected || animateChildren;
+ return allowAnimation && rootElementDetected && bodyElementDetected;
+ }
+
+ function markElementAnimationState(element, state, details) {
+ details = details || {};
+ details.state = state;
+
+ var node = getDomNode(element);
+ node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
+
+ var oldValue = activeAnimationsLookup.get(node);
+ var newValue = oldValue
+ ? extend(oldValue, details)
+ : details;
+ activeAnimationsLookup.put(node, newValue);
+ }
+ }];
+}];
+
+var $$AnimateAsyncRunFactory = ['$$rAF', function($$rAF) {
+ var waitQueue = [];
+
+ function waitForTick(fn) {
+ waitQueue.push(fn);
+ if (waitQueue.length > 1) return;
+ $$rAF(function() {
+ for (var i = 0; i < waitQueue.length; i++) {
+ waitQueue[i]();
+ }
+ waitQueue = [];
+ });
+ }
+
+ return function() {
+ var passed = false;
+ waitForTick(function() {
+ passed = true;
+ });
+ return function(callback) {
+ passed ? callback() : waitForTick(callback);
+ };
+ };
+}];
+
+var $$AnimateRunnerFactory = ['$q', '$sniffer', '$$animateAsyncRun',
+ function($q, $sniffer, $$animateAsyncRun) {
+
+ var INITIAL_STATE = 0;
+ var DONE_PENDING_STATE = 1;
+ var DONE_COMPLETE_STATE = 2;
+
+ AnimateRunner.chain = function(chain, callback) {
+ var index = 0;
+
+ next();
+ function next() {
+ if (index === chain.length) {
+ callback(true);
+ return;
+ }
+
+ chain[index](function(response) {
+ if (response === false) {
+ callback(false);
+ return;
+ }
+ index++;
+ next();
+ });
+ }
+ };
+
+ AnimateRunner.all = function(runners, callback) {
+ var count = 0;
+ var status = true;
+ forEach(runners, function(runner) {
+ runner.done(onProgress);
+ });
+
+ function onProgress(response) {
+ status = status && response;
+ if (++count === runners.length) {
+ callback(status);
+ }
+ }
+ };
+
+ function AnimateRunner(host) {
+ this.setHost(host);
+
+ this._doneCallbacks = [];
+ this._runInAnimationFrame = $$animateAsyncRun();
+ this._state = 0;
+ }
+
+ AnimateRunner.prototype = {
+ setHost: function(host) {
+ this.host = host || {};
+ },
+
+ done: function(fn) {
+ if (this._state === DONE_COMPLETE_STATE) {
+ fn();
+ } else {
+ this._doneCallbacks.push(fn);
+ }
+ },
+
+ progress: noop,
+
+ getPromise: function() {
+ if (!this.promise) {
+ var self = this;
+ this.promise = $q(function(resolve, reject) {
+ self.done(function(status) {
+ status === false ? reject() : resolve();
+ });
+ });
+ }
+ return this.promise;
+ },
+
+ then: function(resolveHandler, rejectHandler) {
+ return this.getPromise().then(resolveHandler, rejectHandler);
+ },
+
+ 'catch': function(handler) {
+ return this.getPromise()['catch'](handler);
+ },
+
+ 'finally': function(handler) {
+ return this.getPromise()['finally'](handler);
+ },
+
+ pause: function() {
+ if (this.host.pause) {
+ this.host.pause();
+ }
+ },
+
+ resume: function() {
+ if (this.host.resume) {
+ this.host.resume();
+ }
+ },
+
+ end: function() {
+ if (this.host.end) {
+ this.host.end();
+ }
+ this._resolve(true);
+ },
+
+ cancel: function() {
+ if (this.host.cancel) {
+ this.host.cancel();
+ }
+ this._resolve(false);
+ },
+
+ complete: function(response) {
+ var self = this;
+ if (self._state === INITIAL_STATE) {
+ self._state = DONE_PENDING_STATE;
+ self._runInAnimationFrame(function() {
+ self._resolve(response);
+ });
+ }
+ },
+
+ _resolve: function(response) {
+ if (this._state !== DONE_COMPLETE_STATE) {
+ forEach(this._doneCallbacks, function(fn) {
+ fn(response);
+ });
+ this._doneCallbacks.length = 0;
+ this._state = DONE_COMPLETE_STATE;
+ }
+ }
+ };
+
+ return AnimateRunner;
+}];
+
+var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
+ var NG_ANIMATE_REF_ATTR = 'ng-animate-ref';
+
+ var drivers = this.drivers = [];
+
+ var RUNNER_STORAGE_KEY = '$$animationRunner';
+
+ function setRunner(element, runner) {
+ element.data(RUNNER_STORAGE_KEY, runner);
+ }
+
+ function removeRunner(element) {
+ element.removeData(RUNNER_STORAGE_KEY);
+ }
+
+ function getRunner(element) {
+ return element.data(RUNNER_STORAGE_KEY);
+ }
+
+ this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$HashMap', '$$rAFScheduler',
+ function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap, $$rAFScheduler) {
+
+ var animationQueue = [];
+ var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
+
+ function sortAnimations(animations) {
+ var tree = { children: [] };
+ var i, lookup = new $$HashMap();
+
+ // this is done first beforehand so that the hashmap
+ // is filled with a list of the elements that will be animated
+ for (i = 0; i < animations.length; i++) {
+ var animation = animations[i];
+ lookup.put(animation.domNode, animations[i] = {
+ domNode: animation.domNode,
+ fn: animation.fn,
+ children: []
+ });
+ }
+
+ for (i = 0; i < animations.length; i++) {
+ processNode(animations[i]);
+ }
+
+ return flatten(tree);
+
+ function processNode(entry) {
+ if (entry.processed) return entry;
+ entry.processed = true;
+
+ var elementNode = entry.domNode;
+ var parentNode = elementNode.parentNode;
+ lookup.put(elementNode, entry);
+
+ var parentEntry;
+ while (parentNode) {
+ parentEntry = lookup.get(parentNode);
+ if (parentEntry) {
+ if (!parentEntry.processed) {
+ parentEntry = processNode(parentEntry);
+ }
+ break;
+ }
+ parentNode = parentNode.parentNode;
+ }
+
+ (parentEntry || tree).children.push(entry);
+ return entry;
+ }
+
+ function flatten(tree) {
+ var result = [];
+ var queue = [];
+ var i;
+
+ for (i = 0; i < tree.children.length; i++) {
+ queue.push(tree.children[i]);
+ }
+
+ var remainingLevelEntries = queue.length;
+ var nextLevelEntries = 0;
+ var row = [];
+
+ for (i = 0; i < queue.length; i++) {
+ var entry = queue[i];
+ if (remainingLevelEntries <= 0) {
+ remainingLevelEntries = nextLevelEntries;
+ nextLevelEntries = 0;
+ result.push(row);
+ row = [];
+ }
+ row.push(entry.fn);
+ entry.children.forEach(function(childEntry) {
+ nextLevelEntries++;
+ queue.push(childEntry);
+ });
+ remainingLevelEntries--;
+ }
+
+ if (row.length) {
+ result.push(row);
+ }
+
+ return result;
+ }
+ }
+
+ // TODO(matsko): document the signature in a better way
+ return function(element, event, options) {
+ options = prepareAnimationOptions(options);
+ var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
+
+ // there is no animation at the current moment, however
+ // these runner methods will get later updated with the
+ // methods leading into the driver's end/cancel methods
+ // for now they just stop the animation from starting
+ var runner = new $$AnimateRunner({
+ end: function() { close(); },
+ cancel: function() { close(true); }
+ });
+
+ if (!drivers.length) {
+ close();
+ return runner;
+ }
+
+ setRunner(element, runner);
+
+ var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
+ var tempClasses = options.tempClasses;
+ if (tempClasses) {
+ classes += ' ' + tempClasses;
+ options.tempClasses = null;
+ }
+
+ animationQueue.push({
+ // this data is used by the postDigest code and passed into
+ // the driver step function
+ element: element,
+ classes: classes,
+ event: event,
+ structural: isStructural,
+ options: options,
+ beforeStart: beforeStart,
+ close: close
+ });
+
+ element.on('$destroy', handleDestroyedElement);
+
+ // we only want there to be one function called within the post digest
+ // block. This way we can group animations for all the animations that
+ // were apart of the same postDigest flush call.
+ if (animationQueue.length > 1) return runner;
+
+ $rootScope.$$postDigest(function() {
+ var animations = [];
+ forEach(animationQueue, function(entry) {
+ // the element was destroyed early on which removed the runner
+ // form its storage. This means we can't animate this element
+ // at all and it already has been closed due to destruction.
+ if (getRunner(entry.element)) {
+ animations.push(entry);
+ } else {
+ entry.close();
+ }
+ });
+
+ // now any future animations will be in another postDigest
+ animationQueue.length = 0;
+
+ var groupedAnimations = groupAnimations(animations);
+ var toBeSortedAnimations = [];
+
+ forEach(groupedAnimations, function(animationEntry) {
+ toBeSortedAnimations.push({
+ domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element),
+ fn: function triggerAnimationStart() {
+ // it's important that we apply the `ng-animate` CSS class and the
+ // temporary classes before we do any driver invoking since these
+ // CSS classes may be required for proper CSS detection.
+ animationEntry.beforeStart();
+
+ var startAnimationFn, closeFn = animationEntry.close;
+
+ // in the event that the element was removed before the digest runs or
+ // during the RAF sequencing then we should not trigger the animation.
+ var targetElement = animationEntry.anchors
+ ? (animationEntry.from.element || animationEntry.to.element)
+ : animationEntry.element;
+
+ if (getRunner(targetElement)) {
+ var operation = invokeFirstDriver(animationEntry);
+ if (operation) {
+ startAnimationFn = operation.start;
+ }
+ }
+
+ if (!startAnimationFn) {
+ closeFn();
+ } else {
+ var animationRunner = startAnimationFn();
+ animationRunner.done(function(status) {
+ closeFn(!status);
+ });
+ updateAnimationRunners(animationEntry, animationRunner);
+ }
+ }
+ });
+ });
+
+ // we need to sort each of the animations in order of parent to child
+ // relationships. This ensures that the child classes are applied at the
+ // right time.
+ $$rAFScheduler(sortAnimations(toBeSortedAnimations));
+ });
+
+ return runner;
+
+ // TODO(matsko): change to reference nodes
+ function getAnchorNodes(node) {
+ var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']';
+ var items = node.hasAttribute(NG_ANIMATE_REF_ATTR)
+ ? [node]
+ : node.querySelectorAll(SELECTOR);
+ var anchors = [];
+ forEach(items, function(node) {
+ var attr = node.getAttribute(NG_ANIMATE_REF_ATTR);
+ if (attr && attr.length) {
+ anchors.push(node);
+ }
+ });
+ return anchors;
+ }
+
+ function groupAnimations(animations) {
+ var preparedAnimations = [];
+ var refLookup = {};
+ forEach(animations, function(animation, index) {
+ var element = animation.element;
+ var node = getDomNode(element);
+ var event = animation.event;
+ var enterOrMove = ['enter', 'move'].indexOf(event) >= 0;
+ var anchorNodes = animation.structural ? getAnchorNodes(node) : [];
+
+ if (anchorNodes.length) {
+ var direction = enterOrMove ? 'to' : 'from';
+
+ forEach(anchorNodes, function(anchor) {
+ var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR);
+ refLookup[key] = refLookup[key] || {};
+ refLookup[key][direction] = {
+ animationID: index,
+ element: jqLite(anchor)
+ };
+ });
+ } else {
+ preparedAnimations.push(animation);
+ }
+ });
+
+ var usedIndicesLookup = {};
+ var anchorGroups = {};
+ forEach(refLookup, function(operations, key) {
+ var from = operations.from;
+ var to = operations.to;
+
+ if (!from || !to) {
+ // only one of these is set therefore we can't have an
+ // anchor animation since all three pieces are required
+ var index = from ? from.animationID : to.animationID;
+ var indexKey = index.toString();
+ if (!usedIndicesLookup[indexKey]) {
+ usedIndicesLookup[indexKey] = true;
+ preparedAnimations.push(animations[index]);
+ }
+ return;
+ }
+
+ var fromAnimation = animations[from.animationID];
+ var toAnimation = animations[to.animationID];
+ var lookupKey = from.animationID.toString();
+ if (!anchorGroups[lookupKey]) {
+ var group = anchorGroups[lookupKey] = {
+ structural: true,
+ beforeStart: function() {
+ fromAnimation.beforeStart();
+ toAnimation.beforeStart();
+ },
+ close: function() {
+ fromAnimation.close();
+ toAnimation.close();
+ },
+ classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes),
+ from: fromAnimation,
+ to: toAnimation,
+ anchors: [] // TODO(matsko): change to reference nodes
+ };
+
+ // the anchor animations require that the from and to elements both have at least
+ // one shared CSS class which effictively marries the two elements together to use
+ // the same animation driver and to properly sequence the anchor animation.
+ if (group.classes.length) {
+ preparedAnimations.push(group);
+ } else {
+ preparedAnimations.push(fromAnimation);
+ preparedAnimations.push(toAnimation);
+ }
+ }
+
+ anchorGroups[lookupKey].anchors.push({
+ 'out': from.element, 'in': to.element
+ });
+ });
+
+ return preparedAnimations;
+ }
+
+ function cssClassesIntersection(a,b) {
+ a = a.split(' ');
+ b = b.split(' ');
+ var matches = [];
+
+ for (var i = 0; i < a.length; i++) {
+ var aa = a[i];
+ if (aa.substring(0,3) === 'ng-') continue;
+
+ for (var j = 0; j < b.length; j++) {
+ if (aa === b[j]) {
+ matches.push(aa);
+ break;
+ }
+ }
+ }
+
+ return matches.join(' ');
+ }
+
+ function invokeFirstDriver(animationDetails) {
+ // we loop in reverse order since the more general drivers (like CSS and JS)
+ // may attempt more elements, but custom drivers are more particular
+ for (var i = drivers.length - 1; i >= 0; i--) {
+ var driverName = drivers[i];
+ if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check
+
+ var factory = $injector.get(driverName);
+ var driver = factory(animationDetails);
+ if (driver) {
+ return driver;
+ }
+ }
+ }
+
+ function beforeStart() {
+ element.addClass(NG_ANIMATE_CLASSNAME);
+ if (tempClasses) {
+ $$jqLite.addClass(element, tempClasses);
+ }
+ }
+
+ function updateAnimationRunners(animation, newRunner) {
+ if (animation.from && animation.to) {
+ update(animation.from.element);
+ update(animation.to.element);
+ } else {
+ update(animation.element);
+ }
+
+ function update(element) {
+ getRunner(element).setHost(newRunner);
+ }
+ }
+
+ function handleDestroyedElement() {
+ var runner = getRunner(element);
+ if (runner && (event !== 'leave' || !options.$$domOperationFired)) {
+ runner.end();
+ }
+ }
+
+ function close(rejected) { // jshint ignore:line
+ element.off('$destroy', handleDestroyedElement);
+ removeRunner(element);
+
+ applyAnimationClasses(element, options);
+ applyAnimationStyles(element, options);
+ options.domOperation();
+
+ if (tempClasses) {
+ $$jqLite.removeClass(element, tempClasses);
+ }
+
+ element.removeClass(NG_ANIMATE_CLASSNAME);
+ runner.complete(!rejected);
+ }
+ };
+ }];
+}];
+
+/* global angularAnimateModule: true,
+
+ $$AnimateAsyncRunFactory,
+ $$rAFSchedulerFactory,
+ $$AnimateChildrenDirective,
+ $$AnimateRunnerFactory,
+ $$AnimateQueueProvider,
+ $$AnimationProvider,
+ $AnimateCssProvider,
+ $$AnimateCssDriverProvider,
+ $$AnimateJsProvider,
+ $$AnimateJsDriverProvider,
+*/
+
+/**
+ * @ngdoc module
+ * @name ngAnimate
+ * @description
+ *
+ * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
+ * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an Angular app.
+ *
+ * <div doc-module-components="ngAnimate"></div>
+ *
+ * # Usage
+ * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
+ * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For
+ * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within
+ * the HTML element that the animation will be triggered on.
+ *
+ * ## Directive Support
+ * The following directives are "animation aware":
+ *
+ * | Directive | Supported Animations |
+ * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
+ * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
+ * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
+ * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
+ * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
+ * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
+ * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
+ * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
+ * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
+ * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
+ * | {@link module:ngMessages#animations ngMessage} | enter and leave |
+ *
+ * (More information can be found by visiting each the documentation associated with each directive.)
+ *
+ * ## CSS-based Animations
+ *
+ * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
+ * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation.
+ *
+ * The example below shows how an `enter` animation can be made possible on an element using `ng-if`:
+ *
+ * ```html
+ * <div ng-if="bool" class="fade">
+ * Fade me in out
+ * </div>
+ * <button ng-click="bool=true">Fade In!</button>
+ * <button ng-click="bool=false">Fade Out!</button>
+ * ```
+ *
+ * Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
+ *
+ * ```css
+ * /&#42; The starting CSS styles for the enter animation &#42;/
+ * .fade.ng-enter {
+ * transition:0.5s linear all;
+ * opacity:0;
+ * }
+ *
+ * /&#42; The finishing CSS styles for the enter animation &#42;/
+ * .fade.ng-enter.ng-enter-active {
+ * opacity:1;
+ * }
+ * ```
+ *
+ * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two
+ * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition
+ * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards.
+ *
+ * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions:
+ *
+ * ```css
+ * /&#42; now the element will fade out before it is removed from the DOM &#42;/
+ * .fade.ng-leave {
+ * transition:0.5s linear all;
+ * opacity:1;
+ * }
+ * .fade.ng-leave.ng-leave-active {
+ * opacity:0;
+ * }
+ * ```
+ *
+ * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class:
+ *
+ * ```css
+ * /&#42; there is no need to define anything inside of the destination
+ * CSS class since the keyframe will take charge of the animation &#42;/
+ * .fade.ng-leave {
+ * animation: my_fade_animation 0.5s linear;
+ * -webkit-animation: my_fade_animation 0.5s linear;
+ * }
+ *
+ * @keyframes my_fade_animation {
+ * from { opacity:1; }
+ * to { opacity:0; }
+ * }
+ *
+ * @-webkit-keyframes my_fade_animation {
+ * from { opacity:1; }
+ * to { opacity:0; }
+ * }
+ * ```
+ *
+ * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element.
+ *
+ * ### CSS Class-based Animations
+ *
+ * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different
+ * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added
+ * and removed.
+ *
+ * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class:
+ *
+ * ```html
+ * <div ng-show="bool" class="fade">
+ * Show and hide me
+ * </div>
+ * <button ng-click="bool=true">Toggle</button>
+ *
+ * <style>
+ * .fade.ng-hide {
+ * transition:0.5s linear all;
+ * opacity:0;
+ * }
+ * </style>
+ * ```
+ *
+ * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since
+ * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest.
+ *
+ * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation
+ * with CSS styles.
+ *
+ * ```html
+ * <div ng-class="{on:onOff}" class="highlight">
+ * Highlight this box
+ * </div>
+ * <button ng-click="onOff=!onOff">Toggle</button>
+ *
+ * <style>
+ * .highlight {
+ * transition:0.5s linear all;
+ * }
+ * .highlight.on-add {
+ * background:white;
+ * }
+ * .highlight.on {
+ * background:yellow;
+ * }
+ * .highlight.on-remove {
+ * background:black;
+ * }
+ * </style>
+ * ```
+ *
+ * We can also make use of CSS keyframes by placing them within the CSS classes.
+ *
+ *
+ * ### CSS Staggering Animations
+ * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
+ * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
+ * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
+ * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
+ * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
+ *
+ * ```css
+ * .my-animation.ng-enter {
+ * /&#42; standard transition code &#42;/
+ * transition: 1s linear all;
+ * opacity:0;
+ * }
+ * .my-animation.ng-enter-stagger {
+ * /&#42; this will have a 100ms delay between each successive leave animation &#42;/
+ * transition-delay: 0.1s;
+ *
+ * /&#42; As of 1.4.4, this must always be set: it signals ngAnimate
+ * to not accidentally inherit a delay property from another CSS class &#42;/
+ * transition-duration: 0s;
+ * }
+ * .my-animation.ng-enter.ng-enter-active {
+ * /&#42; standard transition styles &#42;/
+ * opacity:1;
+ * }
+ * ```
+ *
+ * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
+ * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
+ * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
+ * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired.
+ *
+ * The following code will issue the **ng-leave-stagger** event on the element provided:
+ *
+ * ```js
+ * var kids = parent.children();
+ *
+ * $animate.leave(kids[0]); //stagger index=0
+ * $animate.leave(kids[1]); //stagger index=1
+ * $animate.leave(kids[2]); //stagger index=2
+ * $animate.leave(kids[3]); //stagger index=3
+ * $animate.leave(kids[4]); //stagger index=4
+ *
+ * window.requestAnimationFrame(function() {
+ * //stagger has reset itself
+ * $animate.leave(kids[5]); //stagger index=0
+ * $animate.leave(kids[6]); //stagger index=1
+ *
+ * $scope.$digest();
+ * });
+ * ```
+ *
+ * Stagger animations are currently only supported within CSS-defined animations.
+ *
+ * ### The `ng-animate` CSS class
+ *
+ * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation.
+ * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations).
+ *
+ * Therefore, animations can be applied to an element using this temporary class directly via CSS.
+ *
+ * ```css
+ * .zipper.ng-animate {
+ * transition:0.5s linear all;
+ * }
+ * .zipper.ng-enter {
+ * opacity:0;
+ * }
+ * .zipper.ng-enter.ng-enter-active {
+ * opacity:1;
+ * }
+ * .zipper.ng-leave {
+ * opacity:1;
+ * }
+ * .zipper.ng-leave.ng-leave-active {
+ * opacity:0;
+ * }
+ * ```
+ *
+ * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove
+ * the CSS class once an animation has completed.)
+ *
+ *
+ * ## JavaScript-based Animations
+ *
+ * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
+ * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
+ * `module.animation()` module function we can register the ainmation.
+ *
+ * Let's see an example of a enter/leave animation using `ngRepeat`:
+ *
+ * ```html
+ * <div ng-repeat="item in items" class="slide">
+ * {{ item }}
+ * </div>
+ * ```
+ *
+ * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`:
+ *
+ * ```js
+ * myModule.animation('.slide', [function() {
+ * return {
+ * // make note that other events (like addClass/removeClass)
+ * // have different function input parameters
+ * enter: function(element, doneFn) {
+ * jQuery(element).fadeIn(1000, doneFn);
+ *
+ * // remember to call doneFn so that angular
+ * // knows that the animation has concluded
+ * },
+ *
+ * move: function(element, doneFn) {
+ * jQuery(element).fadeIn(1000, doneFn);
+ * },
+ *
+ * leave: function(element, doneFn) {
+ * jQuery(element).fadeOut(1000, doneFn);
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
+ * greensock.js and velocity.js.
+ *
+ * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define
+ * our animations inside of the same registered animation, however, the function input arguments are a bit different:
+ *
+ * ```html
+ * <div ng-class="color" class="colorful">
+ * this box is moody
+ * </div>
+ * <button ng-click="color='red'">Change to red</button>
+ * <button ng-click="color='blue'">Change to blue</button>
+ * <button ng-click="color='green'">Change to green</button>
+ * ```
+ *
+ * ```js
+ * myModule.animation('.colorful', [function() {
+ * return {
+ * addClass: function(element, className, doneFn) {
+ * // do some cool animation and call the doneFn
+ * },
+ * removeClass: function(element, className, doneFn) {
+ * // do some cool animation and call the doneFn
+ * },
+ * setClass: function(element, addedClass, removedClass, doneFn) {
+ * // do some cool animation and call the doneFn
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ## CSS + JS Animations Together
+ *
+ * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
+ * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
+ * charge of the animation**:
+ *
+ * ```html
+ * <div ng-if="bool" class="slide">
+ * Slide in and out
+ * </div>
+ * ```
+ *
+ * ```js
+ * myModule.animation('.slide', [function() {
+ * return {
+ * enter: function(element, doneFn) {
+ * jQuery(element).slideIn(1000, doneFn);
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * ```css
+ * .slide.ng-enter {
+ * transition:0.5s linear all;
+ * transform:translateY(-100px);
+ * }
+ * .slide.ng-enter.ng-enter-active {
+ * transform:translateY(0);
+ * }
+ * ```
+ *
+ * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the
+ * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from
+ * our own JS-based animation code:
+ *
+ * ```js
+ * myModule.animation('.slide', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element) {
+* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
+ * return $animateCss(element, {
+ * event: 'enter',
+ * structural: true
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
+ *
+ * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or
+ * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that
+ * data into `$animateCss` directly:
+ *
+ * ```js
+ * myModule.animation('.slide', ['$animateCss', function($animateCss) {
+ * return {
+ * enter: function(element) {
+ * return $animateCss(element, {
+ * event: 'enter',
+ * structural: true,
+ * addClass: 'maroon-setting',
+ * from: { height:0 },
+ * to: { height: 200 }
+ * });
+ * }
+ * }
+ * }]);
+ * ```
+ *
+ * Now we can fill in the rest via our transition CSS code:
+ *
+ * ```css
+ * /&#42; the transition tells ngAnimate to make the animation happen &#42;/
+ * .slide.ng-enter { transition:0.5s linear all; }
+ *
+ * /&#42; this extra CSS class will be absorbed into the transition
+ * since the $animateCss code is adding the class &#42;/
+ * .maroon-setting { background:red; }
+ * ```
+ *
+ * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over.
+ *
+ * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
+ *
+ * ## Animation Anchoring (via `ng-animate-ref`)
+ *
+ * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
+ * structural areas of an application (like views) by pairing up elements using an attribute
+ * called `ng-animate-ref`.
+ *
+ * Let's say for example we have two views that are managed by `ng-view` and we want to show
+ * that there is a relationship between two components situated in within these views. By using the
+ * `ng-animate-ref` attribute we can identify that the two components are paired together and we
+ * can then attach an animation, which is triggered when the view changes.
+ *
+ * Say for example we have the following template code:
+ *
+ * ```html
+ * <!-- index.html -->
+ * <div ng-view class="view-animation">
+ * </div>
+ *
+ * <!-- home.html -->
+ * <a href="#/banner-page">
+ * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
+ * </a>
+ *
+ * <!-- banner-page.html -->
+ * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
+ * ```
+ *
+ * Now, when the view changes (once the link is clicked), ngAnimate will examine the
+ * HTML contents to see if there is a match reference between any components in the view
+ * that is leaving and the view that is entering. It will scan both the view which is being
+ * removed (leave) and inserted (enter) to see if there are any paired DOM elements that
+ * contain a matching ref value.
+ *
+ * The two images match since they share the same ref value. ngAnimate will now create a
+ * transport element (which is a clone of the first image element) and it will then attempt
+ * to animate to the position of the second image element in the next view. For the animation to
+ * work a special CSS class called `ng-anchor` will be added to the transported element.
+ *
+ * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then
+ * ngAnimate will handle the entire transition for us as well as the addition and removal of
+ * any changes of CSS classes between the elements:
+ *
+ * ```css
+ * .banner.ng-anchor {
+ * /&#42; this animation will last for 1 second since there are
+ * two phases to the animation (an `in` and an `out` phase) &#42;/
+ * transition:0.5s linear all;
+ * }
+ * ```
+ *
+ * We also **must** include animations for the views that are being entered and removed
+ * (otherwise anchoring wouldn't be possible since the new view would be inserted right away).
+ *
+ * ```css
+ * .view-animation.ng-enter, .view-animation.ng-leave {
+ * transition:0.5s linear all;
+ * position:fixed;
+ * left:0;
+ * top:0;
+ * width:100%;
+ * }
+ * .view-animation.ng-enter {
+ * transform:translateX(100%);
+ * }
+ * .view-animation.ng-leave,
+ * .view-animation.ng-enter.ng-enter-active {
+ * transform:translateX(0%);
+ * }
+ * .view-animation.ng-leave.ng-leave-active {
+ * transform:translateX(-100%);
+ * }
+ * ```
+ *
+ * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur:
+ * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away
+ * from its origin. Once that animation is over then the `in` stage occurs which animates the
+ * element to its destination. The reason why there are two animations is to give enough time
+ * for the enter animation on the new element to be ready.
+ *
+ * The example above sets up a transition for both the in and out phases, but we can also target the out or
+ * in phases directly via `ng-anchor-out` and `ng-anchor-in`.
+ *
+ * ```css
+ * .banner.ng-anchor-out {
+ * transition: 0.5s linear all;
+ *
+ * /&#42; the scale will be applied during the out animation,
+ * but will be animated away when the in animation runs &#42;/
+ * transform: scale(1.2);
+ * }
+ *
+ * .banner.ng-anchor-in {
+ * transition: 1s linear all;
+ * }
+ * ```
+ *
+ *
+ *
+ *
+ * ### Anchoring Demo
+ *
+ <example module="anchoringExample"
+ name="anchoringExample"
+ id="anchoringExample"
+ deps="angular-animate.js;angular-route.js"
+ animations="true">
+ <file name="index.html">
+ <a href="#/">Home</a>
+ <hr />
+ <div class="view-container">
+ <div ng-view class="view"></div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchoringExample', ['ngAnimate', 'ngRoute'])
+ .config(['$routeProvider', function($routeProvider) {
+ $routeProvider.when('/', {
+ templateUrl: 'home.html',
+ controller: 'HomeController as home'
+ });
+ $routeProvider.when('/profile/:id', {
+ templateUrl: 'profile.html',
+ controller: 'ProfileController as profile'
+ });
+ }])
+ .run(['$rootScope', function($rootScope) {
+ $rootScope.records = [
+ { id:1, title: "Miss Beulah Roob" },
+ { id:2, title: "Trent Morissette" },
+ { id:3, title: "Miss Ava Pouros" },
+ { id:4, title: "Rod Pouros" },
+ { id:5, title: "Abdul Rice" },
+ { id:6, title: "Laurie Rutherford Sr." },
+ { id:7, title: "Nakia McLaughlin" },
+ { id:8, title: "Jordon Blanda DVM" },
+ { id:9, title: "Rhoda Hand" },
+ { id:10, title: "Alexandrea Sauer" }
+ ];
+ }])
+ .controller('HomeController', [function() {
+ //empty
+ }])
+ .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) {
+ var index = parseInt($routeParams.id, 10);
+ var record = $rootScope.records[index - 1];
+
+ this.title = record.title;
+ this.id = record.id;
+ }]);
+ </file>
+ <file name="home.html">
+ <h2>Welcome to the home page</h1>
+ <p>Please click on an element</p>
+ <a class="record"
+ ng-href="#/profile/{{ record.id }}"
+ ng-animate-ref="{{ record.id }}"
+ ng-repeat="record in records">
+ {{ record.title }}
+ </a>
+ </file>
+ <file name="profile.html">
+ <div class="profile record" ng-animate-ref="{{ profile.id }}">
+ {{ profile.title }}
+ </div>
+ </file>
+ <file name="animations.css">
+ .record {
+ display:block;
+ font-size:20px;
+ }
+ .profile {
+ background:black;
+ color:white;
+ font-size:100px;
+ }
+ .view-container {
+ position:relative;
+ }
+ .view-container > .view.ng-animate {
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ min-height:500px;
+ }
+ .view.ng-enter, .view.ng-leave,
+ .record.ng-anchor {
+ transition:0.5s linear all;
+ }
+ .view.ng-enter {
+ transform:translateX(100%);
+ }
+ .view.ng-enter.ng-enter-active, .view.ng-leave {
+ transform:translateX(0%);
+ }
+ .view.ng-leave.ng-leave-active {
+ transform:translateX(-100%);
+ }
+ .record.ng-anchor-out {
+ background:red;
+ }
+ </file>
+ </example>
+ *
+ * ### How is the element transported?
+ *
+ * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
+ * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
+ * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
+ * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
+ * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
+ * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
+ * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
+ * will become visible since the shim class will be removed.
+ *
+ * ### How is the morphing handled?
+ *
+ * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
+ * what CSS classes differ between the starting element and the destination element. These different CSS classes
+ * will be added/removed on the anchor element and a transition will be applied (the transition that is provided
+ * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
+ * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
+ * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
+ * the cloned element is placed inside of root element which is likely close to the body element).
+ *
+ * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body.
+ *
+ *
+ * ## Using $animate in your directive code
+ *
+ * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
+ * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
+ * imagine we have a greeting box that shows and hides itself when the data changes
+ *
+ * ```html
+ * <greeting-box active="onOrOff">Hi there</greeting-box>
+ * ```
+ *
+ * ```js
+ * ngModule.directive('greetingBox', ['$animate', function($animate) {
+ * return function(scope, element, attrs) {
+ * attrs.$observe('active', function(value) {
+ * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
+ * });
+ * });
+ * }]);
+ * ```
+ *
+ * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element
+ * in our HTML code then we can trigger a CSS or JS animation to happen.
+ *
+ * ```css
+ * /&#42; normally we would create a CSS class to reference on the element &#42;/
+ * greeting-box.on { transition:0.5s linear all; background:green; color:white; }
+ * ```
+ *
+ * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's
+ * possible be sure to visit the {@link ng.$animate $animate service API page}.
+ *
+ *
+ * ### Preventing Collisions With Third Party Libraries
+ *
+ * Some third-party frameworks place animation duration defaults across many element or className
+ * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
+ * is expecting actual animations on these elements and has to wait for their completion.
+ *
+ * You can prevent this unwanted behavior by using a prefix on all your animation classes:
+ *
+ * ```css
+ * /&#42; prefixed with animate- &#42;/
+ * .animate-fade-add.animate-fade-add-active {
+ * transition:1s linear all;
+ * opacity:0;
+ * }
+ * ```
+ *
+ * You then configure `$animate` to enforce this prefix:
+ *
+ * ```js
+ * $animateProvider.classNameFilter(/animate-/);
+ * ```
+ *
+ * This also may provide your application with a speed boost since only specific elements containing CSS class prefix
+ * will be evaluated for animation when any DOM changes occur in the application.
+ *
+ * ## Callbacks and Promises
+ *
+ * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger
+ * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has
+ * ended by chaining onto the returned promise that animation method returns.
+ *
+ * ```js
+ * // somewhere within the depths of the directive
+ * $animate.enter(element, parent).then(function() {
+ * //the animation has completed
+ * });
+ * ```
+ *
+ * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
+ * anymore.)
+ *
+ * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
+ * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view
+ * routing controller to hook into that:
+ *
+ * ```js
+ * ngModule.controller('HomePageController', ['$animate', function($animate) {
+ * $animate.on('enter', ngViewElement, function(element) {
+ * // the animation for this route has completed
+ * }]);
+ * }])
+ * ```
+ *
+ * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
+ */
+
+/**
+ * @ngdoc service
+ * @name $animate
+ * @kind object
+ *
+ * @description
+ * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
+ *
+ * Click here {@link ng.$animate to learn more about animations with `$animate`}.
+ */
+angular.module('ngAnimate', [])
+ .directive('ngAnimateChildren', $$AnimateChildrenDirective)
+ .factory('$$rAFScheduler', $$rAFSchedulerFactory)
+
+ .factory('$$AnimateRunner', $$AnimateRunnerFactory)
+ .factory('$$animateAsyncRun', $$AnimateAsyncRunFactory)
+
+ .provider('$$animateQueue', $$AnimateQueueProvider)
+ .provider('$$animation', $$AnimationProvider)
+
+ .provider('$animateCss', $AnimateCssProvider)
+ .provider('$$animateCssDriver', $$AnimateCssDriverProvider)
+
+ .provider('$$animateJs', $$AnimateJsProvider)
+ .provider('$$animateJsDriver', $$AnimateJsDriverProvider);
+
+
+})(window, window.angular);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js
new file mode 100644
index 00000000..9461603d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js
@@ -0,0 +1,56 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(H,u,Sa){'use strict';function wa(a,b,c){if(!a)throw ngMinErr("areq",b||"?",c||"required");return a}function xa(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;X(a)&&(a=a.join(" "));X(b)&&(b=b.join(" "));return a+" "+b}function Ia(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function T(a,b,c){var d="";a=X(a)?a:a&&I(a)&&a.length?a.split(/\s+/):[];q(a,function(a,s){a&&0<a.length&&(d+=0<s?" ":"",d+=c?b+a:a+b)});return d}function Ja(a){if(a instanceof L)switch(a.length){case 0:return[];
+case 1:if(1===a[0].nodeType)return a;break;default:return L(ma(a))}if(1===a.nodeType)return L(a)}function ma(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Ka(a,b,c){q(b,function(b){a.addClass(b,c)})}function La(a,b,c){q(b,function(b){a.removeClass(b,c)})}function N(a){return function(b,c){c.addClass&&(Ka(a,b,c.addClass),c.addClass=null);c.removeClass&&(La(a,b,c.removeClass),c.removeClass=null)}}function ia(a){a=a||{};if(!a.$$prepared){var b=a.domOperation||
+M;a.domOperation=function(){a.$$domOperationFired=!0;b();b=M};a.$$prepared=!0}return a}function da(a,b){ya(a,b);za(a,b)}function ya(a,b){b.from&&(a.css(b.from),b.from=null)}function za(a,b){b.to&&(a.css(b.to),b.to=null)}function Q(a,b,c){var d=(b.addClass||"")+" "+(c.addClass||""),e=(b.removeClass||"")+" "+(c.removeClass||"");a=Ma(a.attr("class"),d,e);c.preparationClasses&&(b.preparationClasses=Y(c.preparationClasses,b.preparationClasses),delete c.preparationClasses);d=b.domOperation!==M?b.domOperation:
+null;Aa(b,c);d&&(b.domOperation=d);b.addClass=a.addClass?a.addClass:null;b.removeClass=a.removeClass?a.removeClass:null;return b}function Ma(a,b,c){function d(a){I(a)&&(a=a.split(" "));var b={};q(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);q(b,function(a,b){e[b]=1});c=d(c);q(c,function(a,b){e[b]=1===e[b]?null:-1});var s={addClass:"",removeClass:""};q(e,function(b,c){var e,d;1===b?(e="addClass",d=!a[c]):-1===b&&(e="removeClass",d=a[c]);d&&(s[e].length&&(s[e]+=" "),s[e]+=c)});
+return s}function B(a){return a instanceof u.element?a[0]:a}function Na(a,b,c){var d="";b&&(d=T(b,"ng-",!0));c.addClass&&(d=Y(d,T(c.addClass,"-add")));c.removeClass&&(d=Y(d,T(c.removeClass,"-remove")));d.length&&(c.preparationClasses=d,a.addClass(d))}function ja(a,b){var c=b?"-"+b+"s":"";ea(a,[fa,c]);return[fa,c]}function na(a,b){var c=b?"paused":"",d=U+"PlayState";ea(a,[d,c]);return[d,c]}function ea(a,b){a.style[b[0]]=b[1]}function Y(a,b){return a?b?a+" "+b:a:b}function Ba(a,b,c){var d=Object.create(null),
+e=a.getComputedStyle(b)||{};q(c,function(a,b){var c=e[a];if(c){var v=c.charAt(0);if("-"===v||"+"===v||0<=v)c=Oa(c);0===c&&(c=null);d[b]=c}});return d}function Oa(a){var b=0;a=a.split(/\s*,\s*/);q(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function oa(a){return 0===a||null!=a}function Ca(a,b){var c=O,d=a+"s";b?c+="Duration":d+=" linear all";return[c,d]}function Da(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},
+count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}function Ea(a,b,c){q(c,function(c){a[c]=V(a[c])?a[c]:b.style.getPropertyValue(c)})}var M=u.noop,Aa=u.extend,L=u.element,q=u.forEach,X=u.isArray,I=u.isString,pa=u.isObject,qa=u.isUndefined,V=u.isDefined,Fa=u.isFunction,ra=u.isElement,O,sa,U,ta;qa(H.ontransitionend)&&V(H.onwebkittransitionend)?(O="WebkitTransition",sa="webkitTransitionEnd transitionend"):
+(O="transition",sa="transitionend");qa(H.onanimationend)&&V(H.onwebkitanimationend)?(U="WebkitAnimation",ta="webkitAnimationEnd animationend"):(U="animation",ta="animationend");var ka=U+"Delay",ua=U+"Duration",fa=O+"Delay";H=O+"Duration";var Pa={transitionDuration:H,transitionDelay:fa,transitionProperty:O+"Property",animationDuration:ua,animationDelay:ka,animationIterationCount:U+"IterationCount"},Qa={transitionDuration:H,transitionDelay:fa,animationDuration:ua,animationDelay:ka};u.module("ngAnimate",
+[]).directive("ngAnimateChildren",[function(){return function(a,b,c){a=c.ngAnimateChildren;u.isString(a)&&0===a.length?b.data("$$ngAnimateChildren",!0):c.$observe("ngAnimateChildren",function(a){b.data("$$ngAnimateChildren","on"===a||"true"===a)})}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d=d.concat(a);c()}function c(){if(d.length){for(var b=d.shift(),h=0;h<b.length;h++)b[h]();e||a(function(){e||c()})}}var d,e;d=b.queue=[];b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=
+null;b();c()})};return b}]).factory("$$AnimateRunner",["$q","$sniffer","$$animateAsyncRun",function(a,b,c){function d(a){this.setHost(a);this._doneCallbacks=[];this._runInAnimationFrame=c();this._state=0}d.chain=function(a,b){function c(){if(d===a.length)b(!0);else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};d.all=function(a,b){function c(h){v=v&&h;++d===a.length&&b(v)}var d=0,v=!0;q(a,function(a){a.done(c)})};d.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?
+a():this._doneCallbacks.push(a)},progress:M,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();
+this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._runInAnimationFrame(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(q(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return d}]).factory("$$animateAsyncRun",["$$rAF",function(a){function b(b){c.push(b);1<c.length||a(function(){for(var a=0;a<c.length;a++)c[a]();c=[]})}var c=[];return function(){var a=
+!1;b(function(){a=!0});return function(c){a?c():b(c)}}}]).provider("$$animateQueue",["$animateProvider",function(a){function b(a,b,c,q){return d[a].some(function(a){return a(b,c,q)})}function c(a,b){a=a||{};var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var d=this.rules={skip:[],cancel:[],join:[]};d.join.push(function(a,b,d){return!b.structural&&c(b.options)});d.skip.push(function(a,b,d){return!b.structural&&!c(b.options)});d.skip.push(function(a,b,c){return"leave"==
+c.event&&b.structural});d.skip.push(function(a,b,c){return c.structural&&2===c.state&&!b.structural});d.cancel.push(function(a,b,c){return c.structural&&b.structural});d.cancel.push(function(a,b,c){return 2===c.state&&b.structural});d.cancel.push(function(a,b,c){a=b.options;c=c.options;return a.addClass&&a.addClass===c.removeClass||a.removeClass&&a.removeClass===c.addClass});this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite",
+"$$forceReflow",function(d,s,h,g,v,r,$,u,R,C){function D(){var a=!1;return function(b){a?b():s.$$postDigest(function(){a=!0;b()})}}function K(a,b,c){var f=B(b),d=B(a),n=[];(a=t[c])&&q(a,function(a){a.node.contains(f)?n.push(a.callback):"leave"===c&&a.node.contains(d)&&n.push(a.callback)});return n}function l(a,f,k){function n(b,c,f,t){R(function(){var b=K(v,a,c);b.length&&d(function(){q(b,function(b){b(a,f,t)})})});b.progress(c,f,t)}function t(b){var c=a,f=k;f.preparationClasses&&(c.removeClass(f.preparationClasses),
+f.preparationClasses=null);f.activeClasses&&(c.removeClass(f.activeClasses),f.activeClasses=null);Ha(a,k);da(a,k);k.domOperation();h.complete(!b)}var A,v;if(a=Ja(a))A=B(a),v=a.parent();k=ia(k);var h=new $,R=D();X(k.addClass)&&(k.addClass=k.addClass.join(" "));k.addClass&&!I(k.addClass)&&(k.addClass=null);X(k.removeClass)&&(k.removeClass=k.removeClass.join(" "));k.removeClass&&!I(k.removeClass)&&(k.removeClass=null);k.from&&!pa(k.from)&&(k.from=null);k.to&&!pa(k.to)&&(k.to=null);if(!A)return t(),h;
+var z=[A.className,k.addClass,k.removeClass].join(" ");if(!Ra(z))return t(),h;var l=0<=["enter","move","leave"].indexOf(f),g=!G||F.get(A),z=!g&&m.get(A)||{},C=!!z.state;g||C&&1==z.state||(g=!la(a,v,f));if(g)return t(),h;l&&y(a);g={structural:l,element:a,event:f,close:t,options:k,runner:h};if(C){if(b("skip",a,g,z)){if(2===z.state)return t(),h;Q(a,z.options,k);return z.runner}if(b("cancel",a,g,z))if(2===z.state)z.runner.end();else if(z.structural)z.close();else return Q(a,z.options,g.options),z.runner;
+else if(b("join",a,g,z))if(2===z.state)Q(a,k,{});else return Na(a,l?f:null,k),f=g.event=z.event,k=Q(a,z.options,g.options),z.runner}else Q(a,k,{});(C=g.structural)||(C="animate"===g.event&&0<Object.keys(g.options.to||{}).length||c(g.options));if(!C)return t(),w(a),h;var u=(z.counter||0)+1;g.counter=u;x(a,1,g);s.$$postDigest(function(){var b=m.get(A),d=!b,b=b||{},K=0<(a.parent()||[]).length&&("animate"===b.event||b.structural||c(b.options));if(d||b.counter!==u||!K){d&&(Ha(a,k),da(a,k));if(d||l&&b.event!==
+f)k.domOperation(),h.end();K||w(a)}else f=!b.structural&&c(b.options,!0)?"setClass":b.event,x(a,2),b=r(a,f,b.options),b.done(function(b){t(!b);(b=m.get(A))&&b.counter===u&&w(B(a));n(h,f,"close",{})}),h.setHost(b),n(h,f,"start",{})});return h}function y(a){a=B(a).querySelectorAll("[data-ng-animate]");q(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=m.get(a);switch(b){case 2:c.runner.end();case 1:c&&m.remove(a)}})}function w(a){a=B(a);a.removeAttribute("data-ng-animate");m.remove(a)}
+function f(a,b){return B(a)===B(b)}function la(a,b,c){c=L(g[0].body);var d=f(a,c)||"HTML"===a[0].nodeName,t=f(a,h),n=!1,w;for((a=a.data("$ngAnimatePin"))&&(b=a);b&&b.length;){t||(t=f(b,h));a=b[0];if(1!==a.nodeType)break;var x=m.get(a)||{};n||(n=x.structural||F.get(a));if(qa(w)||!0===w)a=b.data("$$ngAnimateChildren"),V(a)&&(w=a);if(n&&!1===w)break;t||(t=f(b,h),t||(a=b.data("$ngAnimatePin"))&&(b=a));d||(d=f(b,c));b=b.parent()}return(!n||w)&&t&&d}function x(a,b,c){c=c||{};c.state=b;a=B(a);a.setAttribute("data-ng-animate",
+b);c=(b=m.get(a))?Aa(b,c):c;m.put(a,c)}var m=new v,F=new v,G=null,A=s.$watch(function(){return 0===u.totalPendingRequests},function(a){a&&(A(),s.$$postDigest(function(){s.$$postDigest(function(){null===G&&(G=!0)})}))}),t={},n=a.classNameFilter(),Ra=n?function(a){return n.test(a)}:function(){return!0},Ha=N(R);return{on:function(a,b,c){b=ma(b);t[a]=t[a]||[];t[a].push({node:b,callback:c})},off:function(a,b,c){function f(a,b,c){var d=ma(b);return a.filter(function(a){return!(a.node===d&&(!c||a.callback===
+c))})}var d=t[a];d&&(t[a]=1===arguments.length?null:f(d,b,c))},pin:function(a,b){wa(ra(a),"element","not an element");wa(ra(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return l(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!G;else if(ra(a)){var f=B(a),d=F.get(f);1===c?b=!d:(b=!!b)?d&&F.remove(f):F.put(f,!0)}else b=G=!!a;return b}}}]}]).provider("$$animation",["$animateProvider",function(a){function b(a){return a.data("$$animationRunner")}
+var c=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(a,e,s,h,g,v){function r(a){function b(a){if(a.processed)return a;a.processed=!0;var f=a.domNode,d=f.parentNode;e.put(f,a);for(var x;d;){if(x=e.get(d)){x.processed||(x=b(x));break}d=d.parentNode}(x||c).children.push(a);return a}var c={children:[]},d,e=new g;for(d=0;d<a.length;d++){var h=a[d];e.put(h.domNode,a[d]={domNode:h.domNode,fn:h.fn,children:[]})}for(d=0;d<a.length;d++)b(a[d]);
+return function(a){var b=[],c=[],d;for(d=0;d<a.children.length;d++)c.push(a.children[d]);a=c.length;var m=0,e=[];for(d=0;d<c.length;d++){var h=c[d];0>=a&&(a=m,m=0,b.push(e),e=[]);e.push(h.fn);h.children.forEach(function(a){m++;c.push(a)});a--}e.length&&b.push(e);return b}(c)}var $=[],u=N(a);return function(g,C,D){function K(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];q(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}
+function l(a){var b=[],c={};q(a,function(a,f){var d=B(a.element),t=0<=["enter","move"].indexOf(a.event),d=a.structural?K(d):[];if(d.length){var m=t?"to":"from";q(d,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][m]={animationID:f,element:L(a)}})}else b.push(a)});var f={},d={};q(c,function(c,m){var w=c.from,e=c.to;if(w&&e){var h=a[w.animationID],g=a[e.animationID],x=w.animationID.toString();if(!d[x]){var A=d[x]={structural:!0,beforeStart:function(){h.beforeStart();g.beforeStart()},
+close:function(){h.close();g.close()},classes:y(h.classes,g.classes),from:h,to:g,anchors:[]};A.classes.length?b.push(A):(b.push(h),b.push(g))}d[x].anchors.push({out:w.element,"in":e.element})}else w=w?w.animationID:e.animationID,e=w.toString(),f[e]||(f[e]=!0,b.push(a[w]))});return b}function y(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],f=0;f<a.length;f++){var d=a[f];if("ng-"!==d.substring(0,3))for(var m=0;m<b.length;m++)if(d===b[m]){c.push(d);break}}return c.join(" ")}function w(a){for(var b=
+c.length-1;0<=b;b--){var f=c[b];if(s.has(f)&&(f=s.get(f)(a)))return f}}function f(a,c){a.from&&a.to?(b(a.from.element).setHost(c),b(a.to.element).setHost(c)):b(a.element).setHost(c)}function la(){var a=b(g);!a||"leave"===C&&D.$$domOperationFired||a.end()}function x(b){g.off("$destroy",la);g.removeData("$$animationRunner");u(g,D);da(g,D);D.domOperation();A&&a.removeClass(g,A);g.removeClass("ng-animate");F.complete(!b)}D=ia(D);var m=0<=["enter","move","leave"].indexOf(C),F=new h({end:function(){x()},
+cancel:function(){x(!0)}});if(!c.length)return x(),F;g.data("$$animationRunner",F);var G=xa(g.attr("class"),xa(D.addClass,D.removeClass)),A=D.tempClasses;A&&(G+=" "+A,D.tempClasses=null);$.push({element:g,classes:G,event:C,structural:m,options:D,beforeStart:function(){g.addClass("ng-animate");A&&a.addClass(g,A)},close:x});g.on("$destroy",la);if(1<$.length)return F;e.$$postDigest(function(){var a=[];q($,function(c){b(c.element)?a.push(c):c.close()});$.length=0;var c=l(a),d=[];q(c,function(a){d.push({domNode:B(a.from?
+a.from.element:a.element),fn:function(){a.beforeStart();var c,d=a.close;if(b(a.anchors?a.from.element||a.to.element:a.element)){var m=w(a);m&&(c=m.start)}c?(c=c(),c.done(function(a){d(!a)}),f(a,c)):d()}})});v(r(d))});return F}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Da(),c=Da();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$animate",function(a,e,s,h,g,v,r,u){function Ga(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||
+(c.$$ngAnimateParentKey=++l))+"-"+a.getAttribute("class")+"-"+b}function R(w,f,h,g){var m;0<b.count(h)&&(m=c.get(h),m||(f=T(f,"-stagger"),e.addClass(w,f),m=Ba(a,w,g),m.animationDuration=Math.max(m.animationDuration,0),m.transitionDuration=Math.max(m.transitionDuration,0),e.removeClass(w,f),c.put(h,m)));return m||{}}function C(a){y.push(a);r.waitUntilQuiet(function(){b.flush();c.flush();for(var a=g(),d=0;d<y.length;d++)y[d](a);y.length=0})}function D(c,f,e){f=b.get(e);f||(f=Ba(a,c,Pa),"infinite"===
+f.animationIterationCount&&(f.animationIterationCount=1));b.put(e,f);c=f;e=c.animationDelay;f=c.transitionDelay;c.maxDelay=e&&f?Math.max(e,f):e||f;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var K=N(e),l=0,y=[];return function(a,c){function d(){m()}function g(){m(!0)}function m(b){if(!(ga||va&&k)){ga=!0;k=!1;c.$$skipPreparationClasses||e.removeClass(a,Z);e.removeClass(a,Y);na(n,!1);ja(n,!1);q(y,function(a){n.style[a[0]]=""});K(a,c);da(a,c);Object.keys(t).length&&
+q(t,function(a,b){a?n.style.setProperty(b,a):n.style.removeProperty(b)});if(c.onDone)c.onDone();H&&H.complete(!b)}}function F(a){p.blockTransition&&ja(n,a);p.blockKeyframeAnimation&&na(n,!!a)}function G(){H=new s({end:d,cancel:g});C(M);m();return{$$willAnimate:!1,start:function(){return H},end:d}}function A(){function b(){if(!ga){F(!1);q(y,function(a){n.style[a[0]]=a[1]});K(a,c);e.addClass(a,Y);if(p.recalculateTimingStyles){ha=n.className+" "+Z;aa=Ga(n,ha);E=D(n,ha,aa);W=E.maxDelay;I=Math.max(W,0);
+J=E.maxDuration;if(0===J){m();return}p.hasTransitions=0<E.transitionDuration;p.hasAnimations=0<E.animationDuration}p.applyAnimationDelay&&(W="boolean"!==typeof c.delay&&oa(c.delay)?parseFloat(c.delay):W,I=Math.max(W,0),E.animationDelay=W,ca=[ka,W+"s"],y.push(ca),n.style[ca[0]]=ca[1]);N=1E3*I;z=1E3*J;if(c.easing){var k,l=c.easing;p.hasTransitions&&(k=O+"TimingFunction",y.push([k,l]),n.style[k]=l);p.hasAnimations&&(k=U+"TimingFunction",y.push([k,l]),n.style[k]=l)}E.transitionDuration&&x.push(sa);E.animationDuration&&
+x.push(ta);A=Date.now();var v=N+1.5*z;k=A+v;var l=a.data("$$animateCss")||[],r=!0;if(l.length){var G=l[0];(r=k>G.expectedEndTime)?h.cancel(G.timer):l.push(m)}r&&(v=h(d,v,!1),l[0]={timer:v,expectedEndTime:k},l.push(m),a.data("$$animateCss",l));a.on(x.join(" "),g);c.to&&(c.cleanupStyles&&Ea(t,n,Object.keys(c.to)),za(a,c))}}function d(){var b=a.data("$$animateCss");if(b){for(var c=1;c<b.length;c++)b[c]();a.removeData("$$animateCss")}}function g(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||
+b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-A,0)>=N&&b>=J&&(va=!0,m())}if(!ga)if(n.parentNode){var A,x=[],l=function(a){if(va)k&&a&&(k=!1,m());else if(k=!a,E.animationDuration)if(a=na(n,k),k)y.push(a);else{var b=y,c=b.indexOf(a);0<=a&&b.splice(c,1)}},v=0<V&&(E.transitionDuration&&0===S.transitionDuration||E.animationDuration&&0===S.animationDuration)&&Math.max(S.animationDelay,S.transitionDelay);v?h(b,Math.floor(v*V*1E3),!1):b();L.resume=function(){l(!0)};L.pause=function(){l(!1)}}else m()}
+var t={},n=B(a);if(!n||!n.parentNode||!u.enabled())return G();c=ia(c);var y=[],r=a.attr("class"),l=Ia(c),ga,k,va,H,L,I,N,J,z;if(0===c.duration||!v.animations&&!v.transitions)return G();var ba=c.event&&X(c.event)?c.event.join(" "):c.event,Q="",P="";ba&&c.structural?Q=T(ba,"ng-",!0):ba&&(Q=ba);c.addClass&&(P+=T(c.addClass,"-add"));c.removeClass&&(P.length&&(P+=" "),P+=T(c.removeClass,"-remove"));c.applyClassesEarly&&P.length&&K(a,c);var Z=[Q,P].join(" ").trim(),ha=r+" "+Z,Y=T(Z,"-active"),r=l.to&&0<
+Object.keys(l.to).length;if(!(0<(c.keyframeStyle||"").length||r||Z))return G();var aa,S;0<c.stagger?(l=parseFloat(c.stagger),S={transitionDelay:l,animationDelay:l,transitionDuration:0,animationDuration:0}):(aa=Ga(n,ha),S=R(n,Z,aa,Qa));c.$$skipPreparationClasses||e.addClass(a,Z);c.transitionStyle&&(l=[O,c.transitionStyle],ea(n,l),y.push(l));0<=c.duration&&(l=0<n.style[O].length,l=Ca(c.duration,l),ea(n,l),y.push(l));c.keyframeStyle&&(l=[U,c.keyframeStyle],ea(n,l),y.push(l));var V=S?0<=c.staggerIndex?
+c.staggerIndex:b.count(aa):0;(ba=0===V)&&!c.skipBlocking&&ja(n,9999);var E=D(n,ha,aa),W=E.maxDelay;I=Math.max(W,0);J=E.maxDuration;var p={};p.hasTransitions=0<E.transitionDuration;p.hasAnimations=0<E.animationDuration;p.hasTransitionAll=p.hasTransitions&&"all"==E.transitionProperty;p.applyTransitionDuration=r&&(p.hasTransitions&&!p.hasTransitionAll||p.hasAnimations&&!p.hasTransitions);p.applyAnimationDuration=c.duration&&p.hasAnimations;p.applyTransitionDelay=oa(c.delay)&&(p.applyTransitionDuration||
+p.hasTransitions);p.applyAnimationDelay=oa(c.delay)&&p.hasAnimations;p.recalculateTimingStyles=0<P.length;if(p.applyTransitionDuration||p.applyAnimationDuration)J=c.duration?parseFloat(c.duration):J,p.applyTransitionDuration&&(p.hasTransitions=!0,E.transitionDuration=J,l=0<n.style[O+"Property"].length,y.push(Ca(J,l))),p.applyAnimationDuration&&(p.hasAnimations=!0,E.animationDuration=J,y.push([ua,J+"s"]));if(0===J&&!p.recalculateTimingStyles)return G();if(null!=c.delay){var ca=parseFloat(c.delay);
+p.applyTransitionDelay&&y.push([fa,ca+"s"]);p.applyAnimationDelay&&y.push([ka,ca+"s"])}null==c.duration&&0<E.transitionDuration&&(p.recalculateTimingStyles=p.recalculateTimingStyles||ba);N=1E3*I;z=1E3*J;c.skipBlocking||(p.blockTransition=0<E.transitionDuration,p.blockKeyframeAnimation=0<E.animationDuration&&0<S.animationDelay&&0===S.animationDuration);c.from&&(c.cleanupStyles&&Ea(t,n,Object.keys(c.from)),ya(a,c));p.blockTransition||p.blockKeyframeAnimation?F(J):c.skipBlocking||ja(n,!1);return{$$willAnimate:!0,
+end:d,start:function(){if(!ga)return L={end:d,cancel:g,resume:null,pause:null},H=new s(L),C(A),H}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(a,c,d,e,s,h,g){function v(a){return a.replace(/\bng-\S+\b/g,"")}function r(a,b){I(a)&&(a=a.split(" "));I(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}
+function u(c,e,g){function h(a){var b={},c=B(a).getBoundingClientRect();q(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=C.scrollTop;break;case "left":d+=C.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function f(){var c=v(g.attr("class")||""),d=r(c,m),c=r(m,c),d=a(x,{to:h(g),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function s(){x.remove();e.removeClass("ng-animate-shim");g.removeClass("ng-animate-shim")}var x=
+L(B(e).cloneNode(!0)),m=v(x.attr("class")||"");e.addClass("ng-animate-shim");g.addClass("ng-animate-shim");x.addClass("ng-anchor");D.append(x);var F;c=function(){var c=a(x,{addClass:"ng-anchor-out",delay:!0,from:h(e)});return c.$$willAnimate?c:null}();if(!c&&(F=f(),!F))return s();var G=c||F;return{start:function(){function a(){c&&c.end()}var b,c=G.start();c.done(function(){c=null;if(!F&&(F=f()))return c=F.start(),c.done(function(){c=null;s();b.complete()}),c;s();b.complete()});return b=new d({end:a,
+cancel:a})}}}function H(a,b,c,e){var f=R(a,M),g=R(b,M),h=[];q(e,function(a){(a=u(c,a.out,a["in"]))&&h.push(a)});if(f||g||0!==h.length)return{start:function(){function a(){q(b,function(a){a.end()})}var b=[];f&&b.push(f.start());g&&b.push(g.start());q(h,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function R(c){var d=c.element,e=c.options||{};c.structural&&(e.event=c.event,e.structural=!0,e.applyClassesEarly=!0,"leave"===c.event&&(e.onDone=
+e.domOperation));e.preparationClasses&&(e.event=Y(e.event,e.preparationClasses));c=a(d,e);return c.$$willAnimate?c:null}if(!s.animations&&!s.transitions)return M;var C=g[0].body;c=B(e);var D=L(c.parentNode&&11===c.parentNode.nodeType||C.contains(c)?c:C);N(h);return function(a){return a.from&&a.to?H(a.from,a.to,a.classes,a.anchors):R(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(b,c,d){function e(c){c=X(c)?c:c.split(" ");
+for(var d=[],e={},r=0;r<c.length;r++){var q=c[r],s=a.$$registeredAnimations[q];s&&!e[q]&&(d.push(b.get(s)),e[q]=!0)}return d}var s=N(d);return function(a,b,d,r){function u(){r.domOperation();s(a,r)}function H(a,b,d,e,f){switch(d){case "animate":b=[b,e.from,e.to,f];break;case "setClass":b=[b,D,K,f];break;case "addClass":b=[b,D,f];break;case "removeClass":b=[b,K,f];break;default:b=[b,f]}b.push(e);if(a=a.apply(a,b))if(Fa(a.start)&&(a=a.start()),a instanceof c)a.done(f);else if(Fa(a))return a;return M}
+function B(a,b,d,e,f){var g=[];q(e,function(e){var h=e[f];h&&g.push(function(){var e,f,g=!1,k=function(a){g||(g=!0,(f||M)(a),e.complete(!a))};e=new c({end:function(){k()},cancel:function(){k(!0)}});f=H(h,a,b,d,function(a){k(!1===a)});return e})});return g}function C(a,b,d,e,f){var g=B(a,b,d,e,f);if(0===g.length){var h,l;"beforeSetClass"===f?(h=B(a,"removeClass",d,e,"beforeRemoveClass"),l=B(a,"addClass",d,e,"beforeAddClass")):"setClass"===f&&(h=B(a,"removeClass",d,e,"removeClass"),l=B(a,"addClass",
+d,e,"addClass"));h&&(g=g.concat(h));l&&(g=g.concat(l))}if(0!==g.length)return function(a){var b=[];g.length&&q(g,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){q(b,function(b){a?b.cancel():b.end()})}}}3===arguments.length&&pa(d)&&(r=d,d=null);r=ia(r);d||(d=a.attr("class")||"",r.addClass&&(d+=" "+r.addClass),r.removeClass&&(d+=" "+r.removeClass));var D=r.addClass,K=r.removeClass,l=e(d),y,w;if(l.length){var f,I;"leave"==b?(I="leave",f="afterLeave"):(I="before"+b.charAt(0).toUpperCase()+
+b.substr(1),f=b);"enter"!==b&&"move"!==b&&(y=C(a,b,r,l,I));w=C(a,b,r,l,f)}if(y||w)return{start:function(){function b(c){f=!0;u();da(a,r);g.complete(c)}var d,e=[];y&&e.push(function(a){d=y(a)});e.length?e.push(function(a){u();a(!0)}):u();w&&e.push(function(a){d=w(a)});var f=!1,g=new c({end:function(){f||((d||M)(void 0),b(void 0))},cancel:function(){f||((d||M)(!0),b(!0))}});c.chain(e,b);return g}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");
+this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)}return function(a){if(a.from&&a.to){var b=d(a.from),h=d(a.to);if(b||h)return{start:function(){function a(){return function(){q(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());h&&d.push(h.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular);
+//# sourceMappingURL=angular-animate.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js.map
new file mode 100644
index 00000000..11d5fe57
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-animate.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-animate.min.js",
+"lineCount":55,
+"mappings":"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",
+"sources":["angular-animate.js"],
+"names":["window","angular","undefined","assertArg","arg","name","reason","ngMinErr","mergeClasses","a","b","isArray","join","packageStyles","options","styles","to","from","pendClasses","classes","fix","isPrefix","className","isString","length","split","forEach","klass","i","stripCommentsFromElement","element","jqLite","ELEMENT_NODE","nodeType","extractElementNode","elm","$$addClass","$$jqLite","addClass","$$removeClass","removeClass","applyAnimationClassesFactory","prepareAnimationOptions","$$prepared","domOperation","noop","options.domOperation","$$domOperationFired","applyAnimationStyles","applyAnimationFromStyles","applyAnimationToStyles","css","mergeAnimationOptions","target","newOptions","toAdd","toRemove","resolveElementClasses","attr","preparationClasses","concatWithSpace","realDomOperation","extend","existing","splitClassesToLookup","obj","flags","value","key","ADD_CLASS","REMOVE_CLASS","val","prop","allow","getDomNode","applyGeneratedPreparationClasses","event","EVENT_CLASS_PREFIX","ADD_CLASS_SUFFIX","REMOVE_CLASS_SUFFIX","blockTransitions","node","duration","applyInlineStyle","TRANSITION_DELAY_PROP","blockKeyframeAnimations","applyBlock","ANIMATION_PROP","ANIMATION_PLAYSTATE_KEY","styleTuple","style","computeCssStyles","$window","properties","Object","create","detectedStyles","getComputedStyle","formalStyleName","actualStyleName","c","charAt","parseMaxTime","str","maxValue","values","substring","parseFloat","Math","max","truthyTimingValue","getCssTransitionDurationStyle","applyOnlyDuration","TRANSITION_PROP","DURATION_KEY","createLocalCacheLookup","cache","flush","count","entry","total","get","put","registerRestorableStyles","backup","isDefined","getPropertyValue","isObject","isUndefined","isFunction","isElement","TRANSITIONEND_EVENT","ANIMATIONEND_EVENT","ontransitionend","onwebkittransitionend","onanimationend","onwebkitanimationend","ANIMATION_DELAY_PROP","DELAY_KEY","ANIMATION_DURATION_PROP","TRANSITION_DURATION_PROP","DETECT_CSS_PROPERTIES","transitionDuration","transitionDelay","transitionProperty","PROPERTY_KEY","animationDuration","animationDelay","animationIterationCount","ANIMATION_ITERATION_COUNT_KEY","DETECT_STAGGER_CSS_PROPERTIES","module","directive","$$AnimateChildrenDirective","scope","attrs","ngAnimateChildren","data","NG_ANIMATE_CHILDREN_DATA","$observe","factory","$$rAFSchedulerFactory","$$rAF","scheduler","tasks","queue","concat","nextTick","items","shift","cancelFn","waitUntilQuiet","scheduler.waitUntilQuiet","fn","$$AnimateRunnerFactory","$q","$sniffer","$$animateAsyncRun","AnimateRunner","host","setHost","_doneCallbacks","_runInAnimationFrame","_state","chain","AnimateRunner.chain","callback","next","index","response","all","AnimateRunner.all","runners","onProgress","status","runner","done","prototype","DONE_COMPLETE_STATE","push","progress","getPromise","promise","self","resolve","reject","then","resolveHandler","rejectHandler","catch","handler","finally","pause","resume","end","_resolve","cancel","complete","INITIAL_STATE","DONE_PENDING_STATE","$$AnimateAsyncRunFactory","waitForTick","waitQueue","passed","provider","$$AnimateQueueProvider","$animateProvider","isAllowed","ruleType","currentAnimation","previousAnimation","rules","some","hasAnimationClasses","and","skip","newAnimation","structural","RUNNING_STATE","state","nO","cO","$get","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$forceReflow","postDigestTaskFactory","postDigestCalled","$$postDigest","findCallbacks","parent","targetNode","targetParentNode","matches","entries","callbackRegistry","contains","queueAnimation","notifyProgress","phase","runInNextPostDigestOrNow","callbacks","close","activeClasses","applyAnimationClasses","isAnimatableClassName","isStructural","indexOf","skipAnimations","animationsEnabled","disabledElementsLookup","existingAnimation","activeAnimationsLookup","hasExistingAnimation","PRE_DIGEST_STATE","areAnimationsAllowed","closeChildAnimations","skipAnimationFlag","cancelAnimationFlag","joinAnimationFlag","isValidAnimation","keys","clearElementAnimationState","counter","markElementAnimationState","animationDetails","animationCancelled","realRunner","children","querySelectorAll","child","parseInt","getAttribute","NG_ANIMATE_ATTR_NAME","remove","removeAttribute","isMatchingElement","nodeOrElmA","nodeOrElmB","parentElement","bodyElement","body","bodyElementDetected","nodeName","rootElementDetected","parentAnimationDetected","animateChildren","parentHost","NG_ANIMATE_PIN_DATA","parentNode","details","setAttribute","newValue","oldValue","deregisterWatch","$watch","totalPendingRequests","isEmpty","classNameFilter","test","on","container","off","filterFromRegistry","list","matchContainer","matchCallback","containerNode","filter","arguments","pin","enabled","bool","argCount","hasElement","recordExists","$$AnimationProvider","getRunner","RUNNER_STORAGE_KEY","drivers","$injector","$$rAFScheduler","sortAnimations","animations","processNode","processed","elementNode","domNode","lookup","parentEntry","tree","animation","flatten","result","remainingLevelEntries","nextLevelEntries","row","childEntry","animationQueue","getAnchorNodes","hasAttribute","NG_ANIMATE_REF_ATTR","SELECTOR","anchors","groupAnimations","preparedAnimations","refLookup","enterOrMove","anchorNodes","direction","anchor","animationID","usedIndicesLookup","anchorGroups","operations","fromAnimation","toAnimation","lookupKey","toString","group","beforeStart","cssClassesIntersection","indexKey","aa","j","invokeFirstDriver","driverName","has","driver","updateAnimationRunners","newRunner","handleDestroyedElement","rejected","removeData","tempClasses","NG_ANIMATE_CLASSNAME","groupedAnimations","toBeSortedAnimations","animationEntry","triggerAnimationStart","startAnimationFn","closeFn","targetElement","operation","start","animationRunner","$AnimateCssProvider","gcsLookup","gcsStaggerLookup","$timeout","$animate","gcsHashFn","extraClasses","parentCounter","computeCachedCssStaggerStyles","cacheKey","stagger","staggerClassName","rafWaitQueue","pageWidth","computeTimings","timings","aD","tD","maxDelay","maxDuration","init","endFn","animationClosed","animationCompleted","animationPaused","$$skipPreparationClasses","temporaryStyles","restoreStyles","setProperty","removeProperty","onDone","applyBlocking","blockTransition","blockKeyframeAnimation","closeAndReturnNoopAnimator","$$willAnimate","recalculateTimingStyles","fullClassName","relativeDelay","hasTransitions","hasAnimations","applyAnimationDelay","delay","delayStyle","maxDelayTime","ONE_SECOND","maxDurationTime","easing","easeProp","easeVal","TIMING_KEY","events","startTime","Date","now","timerTime","CLOSING_TIME_BUFFER","endTime","animationsData","ANIMATE_TIMER_KEY","setupFallbackTimer","currentTimerData","expectedEndTime","timer","onAnimationExpired","onAnimationProgress","cleanupStyles","stopPropagation","ev","originalEvent","timeStamp","$manualTimeStamp","elapsedTime","toFixed","ELAPSED_TIME_MAX_DECIMAL_PLACES","playPause","playAnimation","arr","splice","maxStagger","itemIndex","floor","runnerHost","runnerHost.resume","runnerHost.pause","transitions","method","structuralClassName","addRemoveClassName","applyClassesEarly","trim","ACTIVE_CLASS_SUFFIX","hasToStyles","keyframeStyle","staggerVal","transitionStyle","durationStyle","staggerIndex","isFirst","skipBlocking","SAFE_FAST_FORWARD_DURATION_VALUE","hasTransitionAll","applyTransitionDuration","applyAnimationDuration","applyTransitionDelay","$$AnimateCssDriverProvider","$$animationProvider","$animateCss","filterCssClasses","replace","getUniqueValues","prepareAnchoredAnimation","outAnchor","inAnchor","calculateAnchorStyles","coords","getBoundingClientRect","bodyNode","scrollTop","scrollLeft","prepareInAnimation","endingClasses","startingClasses","animator","clone","NG_ANIMATE_SHIM_CLASS_NAME","cloneNode","NG_ANIMATE_ANCHOR_CLASS_NAME","rootBodyElement","append","animatorIn","animatorOut","prepareOutAnimation","NG_OUT_ANCHOR_CLASS_NAME","startingAnimator","prepareFromToAnchorAnimation","prepareRegularAnimation","anchorAnimations","outElement","inElement","animationRunners","rootNode","initDriverFn","$$AnimateJsProvider","lookupAnimations","flagMap","animationFactory","$$registeredAnimations","applyOptions","executeAnimationFn","args","classesToAdd","classesToRemove","apply","groupEventedAnimations","fnName","ani","endProgressCb","resolved","onAnimationComplete","packageAnimations","startAnimation","animateFn","before","after","afterFn","beforeFn","toUpperCase","substr","onComplete","success","closeActiveAnimations","cancelled","$$AnimateJsDriverProvider","$$animateJs","prepareAnimation","endFnFactory"]
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.js
index 99f5cc42..8a8e73b2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
@@ -21,23 +21,19 @@
*
* For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following
* directives are supported:
- * `ngModel`, `ngChecked`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`,
- * `ngDblClick`, and `ngMessages`.
+ * `ngModel`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, `ngDblClick`, and `ngMessages`.
*
* Below is a more detailed breakdown of the attributes handled by ngAria:
*
* | Directive | Supported Attributes |
* |---------------------------------------------|----------------------------------------------------------------------------------------|
- * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
* | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
- * | {@link ng.directive:ngRequired ngRequired} | aria-required |
- * | {@link ng.directive:ngChecked ngChecked} | aria-checked |
- * | {@link ng.directive:ngValue ngValue} | aria-checked |
* | {@link ng.directive:ngShow ngShow} | aria-hidden |
* | {@link ng.directive:ngHide ngHide} | aria-hidden |
* | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
* | {@link module:ngMessages ngMessages} | aria-live |
- * | {@link ng.directive:ngClick ngClick} | tabindex, keypress event, button role |
+ * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
+ * | {@link ng.directive:ngClick ngClick} | tabindex, keypress event, button role |
*
* Find out more information about each directive by reading the
* {@link guide/accessibility ngAria Developer Guide}.
@@ -99,6 +95,7 @@ function $AriaProvider() {
ariaDisabled: true,
ariaRequired: true,
ariaInvalid: true,
+ ariaMultiline: true,
ariaValue: true,
tabindex: true,
bindKeypress: true,
@@ -116,10 +113,11 @@ function $AriaProvider() {
* - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags
* - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags
* - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags
+ * - **ariaMultiline** – `{boolean}` – Enables/disables aria-multiline tags
* - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and aria-valuenow tags
* - **tabindex** – `{boolean}` – Enables/disables tabindex tags
- * - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on `div` and
- * `li` elements with ng-click
+ * - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on `&lt;div&gt;` and
+ * `&lt;li&gt;` elements with ng-click
* - **bindRoleForClick** – `{boolean}` – Adds role=button to non-interactive elements like `div`
* using ng-click, making them more accessible to users of assistive technologies
*
@@ -158,15 +156,15 @@ function $AriaProvider() {
*
*```js
* ngAriaModule.directive('ngDisabled', ['$aria', function($aria) {
- * return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
+ * return $aria.$$watchExpr('ngDisabled', 'aria-disabled');
* }])
*```
* Shown above, the ngAria module creates a directive with the same signature as the
* traditional `ng-disabled` directive. But this ngAria version is dedicated to
- * solely managing accessibility attributes on custom elements. The internal `$aria` service is
- * used to watch the boolean attribute `ngDisabled`. If it has not been explicitly set by the
- * developer, `aria-disabled` is injected as an attribute with its value synchronized to the
- * value in `ngDisabled`.
+ * solely managing accessibility attributes. The internal `$aria` service is used to watch the
+ * boolean attribute `ngDisabled`. If it has not been explicitly set by the developer,
+ * `aria-disabled` is injected as an attribute with its value synchronized to the value in
+ * `ngDisabled`.
*
* Because ngAria hooks into the `ng-disabled` directive, developers do not have to do
* anything to enable this feature. The `aria-disabled` attribute is automatically managed
@@ -174,15 +172,12 @@ function $AriaProvider() {
*
* The full list of directives that interface with ngAria:
* * **ngModel**
- * * **ngChecked**
- * * **ngRequired**
- * * **ngDisabled**
- * * **ngValue**
* * **ngShow**
* * **ngHide**
* * **ngClick**
* * **ngDblclick**
* * **ngMessages**
+ * * **ngDisabled**
*
* Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each
* directive.
@@ -208,25 +203,13 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
.directive('ngHide', ['$aria', function($aria) {
return $aria.$$watchExpr('ngHide', 'aria-hidden', [], false);
}])
-.directive('ngValue', ['$aria', function($aria) {
- return $aria.$$watchExpr('ngValue', 'aria-checked', nodeBlackList, false);
-}])
-.directive('ngChecked', ['$aria', function($aria) {
- return $aria.$$watchExpr('ngChecked', 'aria-checked', nodeBlackList, false);
-}])
-.directive('ngRequired', ['$aria', function($aria) {
- return $aria.$$watchExpr('ngRequired', 'aria-required', nodeBlackList, false);
-}])
.directive('ngModel', ['$aria', function($aria) {
- function shouldAttachAttr(attr, normalizedAttr, elem, allowBlacklistEls) {
- return $aria.config(normalizedAttr) && !elem.attr(attr) && (allowBlacklistEls || !isNodeOneOf(elem, nodeBlackList));
+ function shouldAttachAttr(attr, normalizedAttr, elem) {
+ return $aria.config(normalizedAttr) && !elem.attr(attr);
}
function shouldAttachRole(role, elem) {
- // if element does not have role attribute
- // AND element type is equal to role (if custom element has a type equaling shape) <-- remove?
- // AND element is not INPUT
return !elem.attr('role') && (elem.attr('type') === role) && (elem[0].nodeName !== 'INPUT');
}
@@ -236,19 +219,20 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' :
((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' :
- (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' : '';
+ (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' :
+ (type || role) === 'textbox' || elem[0].nodeName === 'TEXTAREA' ? 'multiline' : '';
}
return {
restrict: 'A',
- require: 'ngModel',
+ require: '?ngModel',
priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
compile: function(elem, attr) {
var shape = getShape(attr, elem);
return {
pre: function(scope, elem, attr, ngModel) {
- if (shape === 'checkbox') {
+ if (shape === 'checkbox' && attr.type !== 'checkbox') {
//Use the input[checkbox] $isEmpty implementation for elements with checkbox roles
ngModel.$isEmpty = function(value) {
return value === false;
@@ -256,18 +240,29 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
}
},
post: function(scope, elem, attr, ngModel) {
- var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem, false);
+ var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem)
+ && !isNodeOneOf(elem, nodeBlackList);
function ngAriaWatchModelValue() {
return ngModel.$modelValue;
}
- function getRadioReaction(newVal) {
- var boolVal = (attr.value == ngModel.$viewValue);
- elem.attr('aria-checked', boolVal);
+ function getRadioReaction() {
+ if (needsTabIndex) {
+ needsTabIndex = false;
+ return function ngAriaRadioReaction(newVal) {
+ var boolVal = (attr.value == ngModel.$viewValue);
+ elem.attr('aria-checked', boolVal);
+ elem.attr('tabindex', 0 - !boolVal);
+ };
+ } else {
+ return function ngAriaRadioReaction(newVal) {
+ elem.attr('aria-checked', (attr.value == ngModel.$viewValue));
+ };
+ }
}
- function getCheckboxReaction() {
+ function ngAriaCheckboxReaction() {
elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
}
@@ -277,9 +272,9 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
if (shouldAttachRole(shape, elem)) {
elem.attr('role', shape);
}
- if (shouldAttachAttr('aria-checked', 'ariaChecked', elem, false)) {
+ if (shouldAttachAttr('aria-checked', 'ariaChecked', elem)) {
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
- getRadioReaction : getCheckboxReaction);
+ getRadioReaction() : ngAriaCheckboxReaction);
}
if (needsTabIndex) {
elem.attr('tabindex', 0);
@@ -316,17 +311,22 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
elem.attr('tabindex', 0);
}
break;
+ case 'multiline':
+ if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
+ elem.attr('aria-multiline', true);
+ }
+ break;
}
- if (!attr.hasOwnProperty('ngRequired') && ngModel.$validators.required
- && shouldAttachAttr('aria-required', 'ariaRequired', elem, false)) {
- // ngModel.$error.required is undefined on custom controls
- attr.$observe('required', function() {
- elem.attr('aria-required', !!attr['required']);
+ if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
+ scope.$watch(function ngAriaRequiredWatch() {
+ return ngModel.$error.required;
+ }, function ngAriaRequiredReaction(newVal) {
+ elem.attr('aria-required', !!newVal);
});
}
- if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem, true)) {
+ if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem)) {
scope.$watch(function ngAriaInvalidWatch() {
return ngModel.$invalid;
}, function ngAriaInvalidReaction(newVal) {
@@ -339,7 +339,7 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
};
}])
.directive('ngDisabled', ['$aria', function($aria) {
- return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
+ return $aria.$$watchExpr('ngDisabled', 'aria-disabled', []);
}])
.directive('ngMessages', function() {
return {
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js
new file mode 100644
index 00000000..4e6fb7c7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js
@@ -0,0 +1,14 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(u,n,v){'use strict';var r="BUTTON A INPUT TEXTAREA SELECT DETAILS SUMMARY".split(" "),p=function(a,c){if(-1!==c.indexOf(a[0].nodeName))return!0};n.module("ngAria",["ng"]).provider("$aria",function(){function a(a,f,l,m){return function(d,e,b){var g=b.$normalize(f);!c[g]||p(e,l)||b[g]||d.$watch(b[a],function(b){b=m?!b:!!b;e.attr(f,b)})}}var c={ariaHidden:!0,ariaChecked:!0,ariaDisabled:!0,ariaRequired:!0,ariaInvalid:!0,ariaMultiline:!0,ariaValue:!0,tabindex:!0,bindKeypress:!0,bindRoleForClick:!0};
+this.config=function(a){c=n.extend(c,a)};this.$get=function(){return{config:function(a){return c[a]},$$watchExpr:a}}}).directive("ngShow",["$aria",function(a){return a.$$watchExpr("ngShow","aria-hidden",[],!0)}]).directive("ngHide",["$aria",function(a){return a.$$watchExpr("ngHide","aria-hidden",[],!1)}]).directive("ngModel",["$aria",function(a){function c(c,m,d){return a.config(m)&&!d.attr(c)}function k(a,c){return!c.attr("role")&&c.attr("type")===a&&"INPUT"!==c[0].nodeName}function f(a,c){var d=
+a.type,e=a.role;return"checkbox"===(d||e)||"menuitemcheckbox"===e?"checkbox":"radio"===(d||e)||"menuitemradio"===e?"radio":"range"===d||"progressbar"===e||"slider"===e?"range":"textbox"===(d||e)||"TEXTAREA"===c[0].nodeName?"multiline":""}return{restrict:"A",require:"?ngModel",priority:200,compile:function(l,m){var d=f(m,l);return{pre:function(a,b,c,h){"checkbox"===d&&"checkbox"!==c.type&&(h.$isEmpty=function(b){return!1===b})},post:function(e,b,g,h){function f(){return h.$modelValue}function m(){return q?
+(q=!1,function(a){a=g.value==h.$viewValue;b.attr("aria-checked",a);b.attr("tabindex",0-!a)}):function(a){b.attr("aria-checked",g.value==h.$viewValue)}}function l(){b.attr("aria-checked",!h.$isEmpty(h.$viewValue))}var q=c("tabindex","tabindex",b)&&!p(b,r);switch(d){case "radio":case "checkbox":k(d,b)&&b.attr("role",d);c("aria-checked","ariaChecked",b)&&e.$watch(f,"radio"===d?m():l);q&&b.attr("tabindex",0);break;case "range":k(d,b)&&b.attr("role","slider");if(a.config("ariaValue")){var n=!b.attr("aria-valuemin")&&
+(g.hasOwnProperty("min")||g.hasOwnProperty("ngMin")),s=!b.attr("aria-valuemax")&&(g.hasOwnProperty("max")||g.hasOwnProperty("ngMax")),t=!b.attr("aria-valuenow");n&&g.$observe("min",function(a){b.attr("aria-valuemin",a)});s&&g.$observe("max",function(a){b.attr("aria-valuemax",a)});t&&e.$watch(f,function(a){b.attr("aria-valuenow",a)})}q&&b.attr("tabindex",0);break;case "multiline":c("aria-multiline","ariaMultiline",b)&&b.attr("aria-multiline",!0)}h.$validators.required&&c("aria-required","ariaRequired",
+b)&&e.$watch(function(){return h.$error.required},function(a){b.attr("aria-required",!!a)});c("aria-invalid","ariaInvalid",b)&&e.$watch(function(){return h.$invalid},function(a){b.attr("aria-invalid",!!a)})}}}}}]).directive("ngDisabled",["$aria",function(a){return a.$$watchExpr("ngDisabled","aria-disabled",[])}]).directive("ngMessages",function(){return{restrict:"A",require:"?ngMessages",link:function(a,c,k,f){c.attr("aria-live")||c.attr("aria-live","assertive")}}}).directive("ngClick",["$aria","$parse",
+function(a,c){return{restrict:"A",compile:function(k,f){var l=c(f.ngClick,null,!0);return function(c,d,e){if(!p(d,r)&&(a.config("bindRoleForClick")&&!d.attr("role")&&d.attr("role","button"),a.config("tabindex")&&!d.attr("tabindex")&&d.attr("tabindex",0),a.config("bindKeypress")&&!e.ngKeypress))d.on("keypress",function(a){function d(){l(c,{$event:a})}var e=a.which||a.keyCode;32!==e&&13!==e||c.$apply(d)})}}}}]).directive("ngDblclick",["$aria",function(a){return function(c,k,f){!a.config("tabindex")||
+k.attr("tabindex")||p(k,r)||k.attr("tabindex",0)}}])})(window,window.angular);
+//# sourceMappingURL=angular-aria.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js.map
new file mode 100644
index 00000000..13000e15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-aria.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-aria.min.js",
+"lineCount":13,
+"mappings":"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",
+"sources":["angular-aria.js"],
+"names":["window","angular","undefined","nodeBlackList","isNodeOneOf","elem","nodeTypeArray","indexOf","nodeName","module","provider","ngAriaModule","$AriaProvider","watchExpr","attrName","ariaAttr","negate","scope","attr","ariaCamelName","$normalize","config","$watch","boolVal","ariaHidden","ariaChecked","ariaDisabled","ariaRequired","ariaInvalid","ariaMultiline","ariaValue","tabindex","bindKeypress","bindRoleForClick","this.config","newConfig","extend","$get","this.$get","key","$$watchExpr","directive","$aria","shouldAttachAttr","normalizedAttr","shouldAttachRole","role","getShape","type","restrict","require","priority","compile","shape","pre","ngModel","$isEmpty","ngModel.$isEmpty","value","post","ngAriaWatchModelValue","$modelValue","getRadioReaction","needsTabIndex","ngAriaRadioReaction","newVal","$viewValue","ngAriaCheckboxReaction","needsAriaValuemin","hasOwnProperty","needsAriaValuemax","needsAriaValuenow","$observe","ngAriaValueMinReaction","ngAriaValueNowReaction","$validators","required","ngAriaRequiredWatch","$error","ngAriaRequiredReaction","ngAriaInvalidWatch","$invalid","ngAriaInvalidReaction","link","ngMessages","$parse","fn","ngClick","ngKeypress","on","event","callback","$event","keyCode","which","$apply"]
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.js
new file mode 100644
index 00000000..8a04e120
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.js
@@ -0,0 +1,321 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/**
+ * @ngdoc module
+ * @name ngCookies
+ * @description
+ *
+ * # ngCookies
+ *
+ * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
+ *
+ *
+ * <div doc-module-components="ngCookies"></div>
+ *
+ * See {@link ngCookies.$cookies `$cookies`} for usage.
+ */
+
+
+angular.module('ngCookies', ['ng']).
+ /**
+ * @ngdoc provider
+ * @name $cookiesProvider
+ * @description
+ * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
+ * */
+ provider('$cookies', [function $CookiesProvider() {
+ /**
+ * @ngdoc property
+ * @name $cookiesProvider#defaults
+ * @description
+ *
+ * Object containing default options to pass when setting cookies.
+ *
+ * The object may have following properties:
+ *
+ * - **path** - `{string}` - The cookie will be available only for this path and its
+ * sub-paths. By default, this would be the URL that appears in your base tag.
+ * - **domain** - `{string}` - The cookie will be available only for this domain and
+ * its sub-domains. For obvious security reasons the user agent will not accept the
+ * cookie if the current domain is not a sub domain or equals to the requested domain.
+ * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
+ * or a Date object indicating the exact date/time this cookie will expire.
+ * - **secure** - `{boolean}` - The cookie will be available only in secured connection.
+ *
+ * Note: by default the address that appears in your `<base>` tag will be used as path.
+ * This is important so that cookies will be visible for all routes in case html5mode is enabled
+ *
+ **/
+ var defaults = this.defaults = {};
+
+ function calcOptions(options) {
+ return options ? angular.extend({}, defaults, options) : defaults;
+ }
+
+ /**
+ * @ngdoc service
+ * @name $cookies
+ *
+ * @description
+ * Provides read/write access to browser's cookies.
+ *
+ * <div class="alert alert-info">
+ * Up until Angular 1.3, `$cookies` exposed properties that represented the
+ * current browser cookie values. In version 1.4, this behavior has changed, and
+ * `$cookies` now provides a standard api of getters, setters etc.
+ * </div>
+ *
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
+ *
+ * @example
+ *
+ * ```js
+ * angular.module('cookiesExample', ['ngCookies'])
+ * .controller('ExampleController', ['$cookies', function($cookies) {
+ * // Retrieving a cookie
+ * var favoriteCookie = $cookies.get('myFavorite');
+ * // Setting a cookie
+ * $cookies.put('myFavorite', 'oatmeal');
+ * }]);
+ * ```
+ */
+ this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
+ return {
+ /**
+ * @ngdoc method
+ * @name $cookies#get
+ *
+ * @description
+ * Returns the value of given cookie key
+ *
+ * @param {string} key Id to use for lookup.
+ * @returns {string} Raw cookie value.
+ */
+ get: function(key) {
+ return $$cookieReader()[key];
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookies#getObject
+ *
+ * @description
+ * Returns the deserialized value of given cookie key
+ *
+ * @param {string} key Id to use for lookup.
+ * @returns {Object} Deserialized cookie value.
+ */
+ getObject: function(key) {
+ var value = this.get(key);
+ return value ? angular.fromJson(value) : value;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookies#getAll
+ *
+ * @description
+ * Returns a key value object with all the cookies
+ *
+ * @returns {Object} All cookies
+ */
+ getAll: function() {
+ return $$cookieReader();
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookies#put
+ *
+ * @description
+ * Sets a value for given cookie key
+ *
+ * @param {string} key Id for the `value`.
+ * @param {string} value Raw value to be stored.
+ * @param {Object=} options Options object.
+ * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
+ */
+ put: function(key, value, options) {
+ $$cookieWriter(key, value, calcOptions(options));
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookies#putObject
+ *
+ * @description
+ * Serializes and sets a value for given cookie key
+ *
+ * @param {string} key Id for the `value`.
+ * @param {Object} value Value to be stored.
+ * @param {Object=} options Options object.
+ * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
+ */
+ putObject: function(key, value, options) {
+ this.put(key, angular.toJson(value), options);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookies#remove
+ *
+ * @description
+ * Remove given cookie
+ *
+ * @param {string} key Id of the key-value pair to delete.
+ * @param {Object=} options Options object.
+ * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
+ */
+ remove: function(key, options) {
+ $$cookieWriter(key, undefined, calcOptions(options));
+ }
+ };
+ }];
+ }]);
+
+angular.module('ngCookies').
+/**
+ * @ngdoc service
+ * @name $cookieStore
+ * @deprecated
+ * @requires $cookies
+ *
+ * @description
+ * Provides a key-value (string-object) storage, that is backed by session cookies.
+ * Objects put or retrieved from this storage are automatically serialized or
+ * deserialized by angular's toJson/fromJson.
+ *
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
+ *
+ * <div class="alert alert-danger">
+ * **Note:** The $cookieStore service is **deprecated**.
+ * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
+ * </div>
+ *
+ * @example
+ *
+ * ```js
+ * angular.module('cookieStoreExample', ['ngCookies'])
+ * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
+ * // Put cookie
+ * $cookieStore.put('myFavorite','oatmeal');
+ * // Get cookie
+ * var favoriteCookie = $cookieStore.get('myFavorite');
+ * // Removing a cookie
+ * $cookieStore.remove('myFavorite');
+ * }]);
+ * ```
+ */
+ factory('$cookieStore', ['$cookies', function($cookies) {
+
+ return {
+ /**
+ * @ngdoc method
+ * @name $cookieStore#get
+ *
+ * @description
+ * Returns the value of given cookie key
+ *
+ * @param {string} key Id to use for lookup.
+ * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
+ */
+ get: function(key) {
+ return $cookies.getObject(key);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookieStore#put
+ *
+ * @description
+ * Sets a value for given cookie key
+ *
+ * @param {string} key Id for the `value`.
+ * @param {Object} value Value to be stored.
+ */
+ put: function(key, value) {
+ $cookies.putObject(key, value);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cookieStore#remove
+ *
+ * @description
+ * Remove given cookie
+ *
+ * @param {string} key Id of the key-value pair to delete.
+ */
+ remove: function(key) {
+ $cookies.remove(key);
+ }
+ };
+
+ }]);
+
+/**
+ * @name $$cookieWriter
+ * @requires $document
+ *
+ * @description
+ * This is a private service for writing cookies
+ *
+ * @param {string} name Cookie name
+ * @param {string=} value Cookie value (if undefined, cookie will be deleted)
+ * @param {Object=} options Object with options that need to be stored for the cookie.
+ */
+function $$CookieWriter($document, $log, $browser) {
+ var cookiePath = $browser.baseHref();
+ var rawDocument = $document[0];
+
+ function buildCookieString(name, value, options) {
+ var path, expires;
+ options = options || {};
+ expires = options.expires;
+ path = angular.isDefined(options.path) ? options.path : cookiePath;
+ if (angular.isUndefined(value)) {
+ expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
+ value = '';
+ }
+ if (angular.isString(expires)) {
+ expires = new Date(expires);
+ }
+
+ var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
+ str += path ? ';path=' + path : '';
+ str += options.domain ? ';domain=' + options.domain : '';
+ str += expires ? ';expires=' + expires.toUTCString() : '';
+ str += options.secure ? ';secure' : '';
+
+ // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
+ // - 300 cookies
+ // - 20 cookies per unique domain
+ // - 4096 bytes per cookie
+ var cookieLength = str.length + 1;
+ if (cookieLength > 4096) {
+ $log.warn("Cookie '" + name +
+ "' possibly not set or overflowed because it was too large (" +
+ cookieLength + " > 4096 bytes)!");
+ }
+
+ return str;
+ }
+
+ return function(name, value, options) {
+ rawDocument.cookie = buildCookieString(name, value, options);
+ };
+}
+
+$$CookieWriter.$inject = ['$document', '$log', '$browser'];
+
+angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
+ this.$get = $$CookieWriter;
+});
+
+
+})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js
index d0f126a9..6a1bab08 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js
@@ -1,6 +1,6 @@
/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT
*/
(function(p,c,n){'use strict';function l(b,a,g){var d=g.baseHref(),k=b[0];return function(b,e,f){var g,h;f=f||{};h=f.expires;g=c.isDefined(f.path)?f.path:d;c.isUndefined(e)&&(h="Thu, 01 Jan 1970 00:00:00 GMT",e="");c.isString(h)&&(h=new Date(h));e=encodeURIComponent(b)+"="+encodeURIComponent(e);e=e+(g?";path="+g:"")+(f.domain?";domain="+f.domain:"");e+=h?";expires="+h.toUTCString():"";e+=f.secure?";secure":"";f=e.length+1;4096<f&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js.map
index 555b5103..d269e1f2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.min.js.map
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-cookies.min.js.map
@@ -2,7 +2,7 @@
"version":3,
"file":"angular-cookies.min.js",
"lineCount":8,
-"mappings":"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",
+"mappings":"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",
"sources":["angular-cookies.js"],
"names":["window","angular","undefined","$$CookieWriter","$document","$log","$browser","cookiePath","baseHref","rawDocument","name","value","options","path","expires","isDefined","isUndefined","isString","Date","str","encodeURIComponent","domain","toUTCString","secure","cookieLength","length","warn","cookie","module","provider","$CookiesProvider","defaults","$get","$$cookieReader","$$cookieWriter","get","key","getObject","fromJson","getAll","put","extend","putObject","toJson","remove","factory","$cookies","$inject","$$CookieWriterProvider"]
}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-csp.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-csp.css
index 23134fdf..f3cd926c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-csp.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-csp.css
@@ -1,3 +1,4 @@
+/* Include this file in your html if you are using the CSP mode. */
@charset "UTF-8";
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.js
index 77948fd5..992b129b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.js
@@ -1,40 +1,12 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function() {'use strict';
function isFunction(value) {return typeof value === 'function';};
-/* global: toDebugString: true */
-
-function serializeObject(obj) {
- var seen = [];
-
- return JSON.stringify(obj, function(key, val) {
- val = toJsonReplacer(key, val);
- if (isObject(val)) {
-
- if (seen.indexOf(val) >= 0) return '...';
-
- seen.push(val);
- }
- return val;
- });
-}
-
-function toDebugString(obj) {
- if (typeof obj === 'function') {
- return obj.toString().replace(/ \{[\s\S]*$/, '');
- } else if (isUndefined(obj)) {
- return 'undefined';
- } else if (typeof obj !== 'string') {
- return serializeObject(obj);
- }
- return obj;
-}
-
/**
* @description
*
@@ -87,7 +59,7 @@ function minErr(module, ErrorConstructor) {
return match;
});
- message += '\nhttp://errors.angularjs.org/1.5.0/' +
+ message += '\nhttp://errors.angularjs.org/1.4.8/' +
(module ? module + '/' : '') + code;
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -175,7 +147,7 @@ function setupModuleLoader(window) {
* unspecified then the module is being retrieved for further configuration.
* @param {Function=} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
- * @returns {angular.Module} new module with the {@link angular.Module} api.
+ * @returns {module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
@@ -383,19 +355,6 @@ function setupModuleLoader(window) {
/**
* @ngdoc method
- * @name angular.Module#component
- * @module ng
- * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
- * @param {Object} options Component definition object (a simplified
- * {@link ng.$compile#directive-definition-object directive definition object})
- *
- * @description
- * See {@link ng.$compileProvider#component $compileProvider.component()}.
- */
- component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
-
- /**
- * @ngdoc method
* @name angular.Module#config
* @module ng
* @param {Function} configFn Execute this function on module load. Useful for service
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js
index 316ee26e..67d08168 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js
@@ -1,10 +1,10 @@
/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT
*/
-(function(){'use strict';function d(b){return function(){var a=arguments[0],e;e="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.5.0/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){e=e+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,c;c=arguments[a];c="function"==typeof c?c.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof c?"undefined":"string"!=typeof c?JSON.stringify(c):c;e+=d(c)}return Error(e)}}(function(b){function a(c,a,b){return c[a]||(c[a]=b())}var e=d("$injector"),n=d("ng");
+(function(){'use strict';function d(b){return function(){var a=arguments[0],e;e="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.8/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){e=e+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,c;c=arguments[a];c="function"==typeof c?c.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof c?"undefined":"string"!=typeof c?JSON.stringify(c):c;e+=d(c)}return Error(e)}}(function(b){function a(c,a,b){return c[a]||(c[a]=b())}var e=d("$injector"),n=d("ng");
b=a(b,"angular",Object);b.$$minErr=b.$$minErr||d;return a(b,"module",function(){var c={};return function(b,d,h){if("hasOwnProperty"===b)throw n("badname","module");d&&c.hasOwnProperty(b)&&(c[b]=null);return a(c,b,function(){function c(a,b,d,e){e||(e=f);return function(){e[d||"push"]([a,b,arguments]);return g}}function a(c,e){return function(a,d){d&&"function"===typeof d&&(d.$$moduleName=b);f.push([c,e,arguments]);return g}}if(!d)throw e("nomod",b);var f=[],k=[],l=[],m=c("$injector","invoke","push",
-k),g={_invokeQueue:f,_configBlocks:k,_runBlocks:l,requires:d,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:c("$provide","value"),constant:c("$provide","constant","unshift"),decorator:a("$provide","decorator"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),component:a("$compileProvider","component"),config:m,run:function(a){l.push(a);
-return this}};h&&m(h);return g})}})})(window)})(window);
+k),g={_invokeQueue:f,_configBlocks:k,_runBlocks:l,requires:d,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:c("$provide","value"),constant:c("$provide","constant","unshift"),decorator:a("$provide","decorator"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:m,run:function(a){l.push(a);return this}};h&&m(h);
+return g})}})})(window)})(window);
//# sourceMappingURL=angular-loader.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js.map
index 67ebb8b6..d59cf1c6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-loader.min.js.map
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-loader.min.js.map
@@ -2,7 +2,7 @@
"version":3,
"file":"angular-loader.min.js",
"lineCount":9,
-"mappings":"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",
+"mappings":"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",
"sources":["angular-loader.js"],
-"names":["minErr","setupModuleLoader","window","ensure","obj","name","factory","$injectorMinErr","ngMinErr","angular","Object","$$minErr","modules","module","requires","configFn","context","hasOwnProperty","invokeLater","provider","method","insertMethod","queue","invokeQueue","arguments","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","push","configBlocks","runBlocks","config","_invokeQueue","_configBlocks","_runBlocks","service","value","constant","decorator","animation","filter","controller","directive","component","run","block"]
+"names":["minErr","setupModuleLoader","window","ensure","obj","name","factory","$injectorMinErr","ngMinErr","angular","Object","$$minErr","modules","module","requires","configFn","context","hasOwnProperty","invokeLater","provider","method","insertMethod","queue","invokeQueue","arguments","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","push","configBlocks","runBlocks","config","_invokeQueue","_configBlocks","_runBlocks","service","value","constant","decorator","animation","filter","controller","directive","run","block"]
}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.js
index 0c3c6c18..6cdcdd7a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js
index f85a5876..3d69b5ac 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js
@@ -1,6 +1,6 @@
/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT
*/
(function(h){'use strict';function C(a){if(null==a)return"";switch(typeof a){case "string":return a;case "number":return""+a;default:return D(a)}}function f(a,b){for(var d=a.split(/\n/g),k=0;k<d.length;k++){var c=d[k];if(b>=c.length)b-=c.length;else return{h:k+1,f:b+1}}}function t(a){function b(){return a}var d=u[a];if(null!=d)return d;b.$$watchDelegate=function(b,d,c){var e=b.$watch(v,function(){m(d)&&d.call(null,a,a,b);e()},c);return e};u[a]=b;b.exp=a;b.expressions=[];return b}function F(a,b){function d(a){return void 0==
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js.map
index a6da634b..a6da634b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-message-format.min.js.map
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-message-format.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.js
index 0d206230..8263976b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
@@ -570,14 +570,13 @@ angular.module('ngMessages', [])
*
* @param {expression} ngMessage|when a string value corresponding to the message key.
*/
- .directive('ngMessage', ngMessageDirectiveFactory())
+ .directive('ngMessage', ngMessageDirectiveFactory('AE'))
/**
* @ngdoc directive
* @name ngMessageExp
* @restrict AE
- * @priority 1
* @scope
*
* @description
@@ -603,14 +602,13 @@ angular.module('ngMessages', [])
*
* @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
*/
- .directive('ngMessageExp', ngMessageDirectiveFactory());
+ .directive('ngMessageExp', ngMessageDirectiveFactory('A'));
-function ngMessageDirectiveFactory() {
+function ngMessageDirectiveFactory(restrict) {
return ['$animate', function($animate) {
return {
restrict: 'AE',
transclude: 'element',
- priority: 1, // must run before ngBind, otherwise the text is set on the comment
terminal: true,
require: '^^ngMessages',
link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js
new file mode 100644
index 00000000..e7f8119d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js
@@ -0,0 +1,12 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(z,h,A){'use strict';function m(h){return["$animate",function(r){return{restrict:"AE",transclude:"element",terminal:!0,require:"^^ngMessages",link:function(n,f,a,g,l){var c=f[0],p,h=a.ngMessage||a.when;a=a.ngMessageExp||a.whenExp;var k=function(b){p=b?v(b)?b:b.split(/[\s,]+/):null;g.reRender()};a?(k(n.$eval(a)),n.$watchCollection(a,k)):k(h);var e,q;g.register(c,q={test:function(b){var a=p;b=a?v(a)?0<=a.indexOf(b):a.hasOwnProperty(b):void 0;return b},attach:function(){e||l(n,function(b){r.enter(b,
+null,f);e=b;var a=e.$$attachId=g.getAttachId();e.on("$destroy",function(){e&&e.$$attachId===a&&(g.deregister(c),q.detach())})})},detach:function(){if(e){var b=e;e=null;r.leave(b)}}})}}}]}var v=h.isArray,w=h.forEach,x=h.isString,y=h.element;h.module("ngMessages",[]).directive("ngMessages",["$animate",function(h){function r(f,a){return x(a)&&0===a.length||n(f.$eval(a))}function n(f){return x(f)?f.length:!!f}return{require:"ngMessages",restrict:"AE",controller:["$element","$scope","$attrs",function(f,
+a,g){function l(b,a){for(var d=a,f=[];d&&d!==b;){var c=d.$$ngMessageNode;if(c&&c.length)return k[c];d.childNodes.length&&-1==f.indexOf(d)?(f.push(d),d=d.childNodes[d.childNodes.length-1]):d=d.previousSibling||d.parentNode}}var c=this,p=0,m=0;this.getAttachId=function(){return m++};var k=this.messages={},e,q;this.render=function(b){b=b||{};e=!1;q=b;for(var p=r(a,g.ngMessagesMultiple)||r(a,g.multiple),d=[],k={},s=c.head,l=!1,m=0;null!=s;){m++;var t=s.message,u=!1;l||w(b,function(a,b){!u&&n(a)&&t.test(b)&&
+!k[b]&&(u=k[b]=!0,t.attach())});u?l=!p:d.push(t);s=s.next}w(d,function(b){b.detach()});d.length!==m?h.setClass(f,"ng-active","ng-inactive"):h.setClass(f,"ng-inactive","ng-active")};a.$watchCollection(g.ngMessages||g["for"],c.render);this.reRender=function(){e||(e=!0,a.$evalAsync(function(){e&&q&&c.render(q)}))};this.register=function(b,a){var d=p.toString();k[d]={message:a};var e=f[0],g=k[d];c.head?(e=l(e,b))?(g.next=e.next,e.next=g):(g.next=c.head,c.head=g):c.head=g;b.$$ngMessageNode=d;p++;c.reRender()};
+this.deregister=function(b){var a=b.$$ngMessageNode;delete b.$$ngMessageNode;var d=k[a];(b=l(f[0],b))?b.next=d.next:c.head=d.next;delete k[a];c.reRender()}}]}}]).directive("ngMessagesInclude",["$templateRequest","$document","$compile",function(h,m,n){return{restrict:"AE",require:"^^ngMessages",link:function(f,a,g){var l=g.ngMessagesInclude||g.src;h(l).then(function(c){n(c)(f,function(c){a.after(c);c=y(m[0].createComment(" ngMessagesInclude: "+l+" "));a.after(c);a.remove()})})}}}]).directive("ngMessage",
+m("AE")).directive("ngMessageExp",m("A"))})(window,window.angular);
+//# sourceMappingURL=angular-messages.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js.map
new file mode 100644
index 00000000..506e76c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-messages.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-messages.min.js",
+"lineCount":11,
+"mappings":"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",
+"sources":["angular-messages.js"],
+"names":["window","angular","undefined","ngMessageDirectiveFactory","restrict","$animate","transclude","terminal","require","link","scope","element","attrs","ngMessagesCtrl","$transclude","commentNode","records","staticExp","ngMessage","when","dynamicExp","ngMessageExp","whenExp","assignRecords","items","isArray","split","reRender","$eval","$watchCollection","currentElement","messageCtrl","register","test","name","collection","indexOf","hasOwnProperty","attach","elm","enter","$$attachId","getAttachId","on","deregister","detach","leave","forEach","isString","jqLite","module","directive","isAttrTruthy","attr","length","truthy","val","controller","$element","$scope","$attrs","findPreviousMessage","parent","comment","prevNode","parentLookup","prevKey","$$ngMessageNode","messages","childNodes","push","previousSibling","parentNode","ctrl","latestKey","nextAttachId","this.getAttachId","renderLater","cachedCollection","render","this.render","multiple","ngMessagesMultiple","unmatchedMessages","matchedKeys","messageItem","head","messageFound","totalMessages","message","messageUsed","value","key","next","setClass","ACTIVE_CLASS","INACTIVE_CLASS","ngMessages","this.reRender","$evalAsync","this.register","nextKey","toString","messageNode","match","this.deregister","$templateRequest","$document","$compile","src","ngMessagesInclude","then","html","contents","after","anchor","createComment","remove"]
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-mocks.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-mocks.js
index 34d36087..917d8427 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-mocks.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-mocks.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
@@ -758,15 +758,6 @@ angular.mock.TzDate = function(offset, timestamp) {
angular.mock.TzDate.prototype = Date.prototype;
/* jshint +W101 */
-
-/**
- * @ngdoc service
- * @name $animate
- *
- * @description
- * Mock implementation of the {@link ng.$animate `$animate`} service. Exposes two additional methods
- * for testing animations.
- */
angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
.config(['$provide', function($provide) {
@@ -799,50 +790,9 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
return queueFn;
});
- $provide.decorator('$$animateJs', ['$delegate', function($delegate) {
- var runners = [];
-
- var animateJsConstructor = function() {
- var animator = $delegate.apply($delegate, arguments);
- // If no javascript animation is found, animator is undefined
- if (animator) {
- runners.push(animator);
- }
- return animator;
- };
-
- animateJsConstructor.$closeAndFlush = function() {
- runners.forEach(function(runner) {
- runner.end();
- });
- runners = [];
- };
-
- return animateJsConstructor;
- }]);
-
- $provide.decorator('$animateCss', ['$delegate', function($delegate) {
- var runners = [];
-
- var animateCssConstructor = function(element, options) {
- var animator = $delegate(element, options);
- runners.push(animator);
- return animator;
- };
-
- animateCssConstructor.$closeAndFlush = function() {
- runners.forEach(function(runner) {
- runner.end();
- });
- runners = [];
- };
-
- return animateCssConstructor;
- }]);
-
- $provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF', '$animateCss', '$$animateJs',
+ $provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF',
'$$forceReflow', '$$animateAsyncRun', '$rootScope',
- function($delegate, $timeout, $browser, $$rAF, $animateCss, $$animateJs,
+ function($delegate, $timeout, $browser, $$rAF,
$$forceReflow, $$animateAsyncRun, $rootScope) {
var animate = {
queue: [],
@@ -854,35 +804,7 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
return $$forceReflow.totalReflows;
},
enabled: $delegate.enabled,
- /**
- * @ngdoc method
- * @name $animate#closeAndFlush
- * @description
- *
- * This method will close all pending animations (both {@link ngAnimate#javascript-based-animations Javascript}
- * and {@link ngAnimate.$animateCss CSS}) and it will also flush any remaining animation frames and/or callbacks.
- */
- closeAndFlush: function() {
- // we allow the flush command to swallow the errors
- // because depending on whether CSS or JS animations are
- // used, there may not be a RAF flush. The primary flush
- // at the end of this function must throw an exception
- // because it will track if there were pending animations
- this.flush(true);
- $animateCss.$closeAndFlush();
- $$animateJs.$closeAndFlush();
- this.flush();
- },
- /**
- * @ngdoc method
- * @name $animate#flush
- * @description
- *
- * This method is used to flush the pending callbacks and animation frames to either start
- * an animation or conclude an animation. Note that this will not actually close an
- * actively running animation (see {@link ngMock.$animate#closeAndFlush `closeAndFlush()`} for that).
- */
- flush: function(hideErrors) {
+ flush: function() {
$rootScope.$digest();
var doNextRun, somethingFlushed = false;
@@ -899,7 +821,7 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
}
} while (doNextRun);
- if (!somethingFlushed && !hideErrors) {
+ if (!somethingFlushed) {
throw new Error('No pending animations ready to be closed or flushed');
}
@@ -1028,7 +950,7 @@ angular.mock.dump = function(object) {
* - `$httpBackend.when` - specifies a backend definition
*
*
- * ## Request Expectations vs Backend Definitions
+ * # Request Expectations vs Backend Definitions
*
* Request expectations provide a way to make assertions about requests made by the application and
* to define responses for those requests. The test will fail if the expected requests are not made
@@ -1084,7 +1006,7 @@ angular.mock.dump = function(object) {
* the request. The response from the first matched definition is returned.
*
*
- * ## Flushing HTTP requests
+ * # Flushing HTTP requests
*
* The $httpBackend used in production always responds to requests asynchronously. If we preserved
* this behavior in unit testing, we'd have to create async unit tests, which are hard to write,
@@ -1094,7 +1016,7 @@ angular.mock.dump = function(object) {
* the async api of the backend, while allowing the test to execute synchronously.
*
*
- * ## Unit testing with mock $httpBackend
+ * # Unit testing with mock $httpBackend
* The following code shows how to setup and use the mock backend when unit testing a controller.
* First we create the controller under test:
*
@@ -1108,18 +1030,18 @@ angular.mock.dump = function(object) {
function MyController($scope, $http) {
var authToken;
- $http.get('/auth.py').then(function(response) {
- authToken = response.headers('A-Token');
- $scope.user = response.data;
+ $http.get('/auth.py').success(function(data, status, headers) {
+ authToken = headers('A-Token');
+ $scope.user = data;
});
$scope.saveMessage = function(message) {
var headers = { 'Authorization': authToken };
$scope.status = 'Saving...';
- $http.post('/add-msg.py', message, { headers: headers } ).then(function(response) {
+ $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
$scope.status = '';
- }).catch(function() {
+ }).error(function() {
$scope.status = 'Failed...';
});
};
@@ -1210,87 +1132,7 @@ angular.mock.dump = function(object) {
$httpBackend.flush();
});
});
- ```
- *
- * ## Dynamic responses
- *
- * You define a response to a request by chaining a call to `respond()` onto a definition or expectation.
- * If you provide a **callback** as the first parameter to `respond(callback)` then you can dynamically generate
- * a response based on the properties of the request.
- *
- * The `callback` function should be of the form `function(method, url, data, headers, params)`.
- *
- * ### Query parameters
- *
- * By default, query parameters on request URLs are parsed into the `params` object. So a request URL
- * of `/list?q=searchstr&orderby=-name` would set `params` to be `{q: 'searchstr', orderby: '-name'}`.
- *
- * ### Regex parameter matching
- *
- * If an expectation or definition uses a **regex** to match the URL, you can provide an array of **keys** via a
- * `params` argument. The index of each **key** in the array will match the index of a **group** in the
- * **regex**.
- *
- * The `params` object in the **callback** will now have properties with these keys, which hold the value of the
- * corresponding **group** in the **regex**.
- *
- * This also applies to the `when` and `expect` shortcut methods.
- *
- *
- * ```js
- * $httpBackend.expect('GET', /\/user\/(.+)/, undefined, undefined, ['id'])
- * .respond(function(method, url, data, headers, params) {
- * // for requested url of '/user/1234' params is {id: '1234'}
- * });
- *
- * $httpBackend.whenPATCH(/\/user\/(.+)\/article\/(.+)/, undefined, undefined, ['user', 'article'])
- * .respond(function(method, url, data, headers, params) {
- * // for url of '/user/1234/article/567' params is {user: '1234', article: '567'}
- * });
- * ```
- *
- * ## Matching route requests
- *
- * For extra convenience, `whenRoute` and `expectRoute` shortcuts are available. These methods offer colon
- * delimited matching of the url path, ignoring the query string. This allows declarations
- * similar to how application routes are configured with `$routeProvider`. Because these methods convert
- * the definition url to regex, declaration order is important. Combined with query parameter parsing,
- * the following is possible:
- *
- ```js
- $httpBackend.whenRoute('GET', '/users/:id')
- .respond(function(method, url, data, headers, params) {
- return [200, MockUserList[Number(params.id)]];
- });
-
- $httpBackend.whenRoute('GET', '/users')
- .respond(function(method, url, data, headers, params) {
- var userList = angular.copy(MockUserList),
- defaultSort = 'lastName',
- count, pages, isPrevious, isNext;
-
- // paged api response '/v1/users?page=2'
- params.page = Number(params.page) || 1;
-
- // query for last names '/v1/users?q=Archer'
- if (params.q) {
- userList = $filter('filter')({lastName: params.q});
- }
-
- pages = Math.ceil(userList.length / pagingLength);
- isPrevious = params.page > 1;
- isNext = params.page < pages;
-
- return [200, {
- count: userList.length,
- previous: isPrevious,
- next: isNext,
- // sort field -> '/v1/users?sortBy=firstName'
- results: $filter('orderBy')(userList, params.sortBy || defaultSort)
- .splice((params.page - 1) * pagingLength, pagingLength)
- }];
- });
- ```
+ ```
*/
angular.mock.$HttpBackendProvider = function() {
this.$get = ['$rootScope', '$timeout', createHttpBackendMock];
@@ -1347,7 +1189,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
return handleResponse;
function handleResponse() {
- var response = wrapped.response(method, url, data, headers, wrapped.params(url));
+ var response = wrapped.response(method, url, data, headers);
xhr.$$respHeaders = response[2];
callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
copy(response[3] || ''));
@@ -1416,21 +1258,20 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current definition.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers, params)}`
+ * | function(function(method, url, data, headers)}`
* – The respond method takes a set of static data to be returned or a function that can
* return an array containing response status (number), response data (string), response
* headers (Object), and the text for the status (string). The respond method returns the
* `requestHandler` object for possible overrides.
*/
- $httpBackend.when = function(method, url, data, headers, keys) {
- var definition = new MockHttpExpectation(method, url, data, headers, keys),
+ $httpBackend.when = function(method, url, data, headers) {
+ var definition = new MockHttpExpectation(method, url, data, headers),
chain = {
respond: function(status, data, headers, statusText) {
definition.passThrough = undefined;
@@ -1460,7 +1301,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1475,7 +1315,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1490,7 +1329,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1507,7 +1345,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1524,7 +1361,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1538,59 +1374,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
*
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
createShortMethods('when');
- /**
- * @ngdoc method
- * @name $httpBackend#whenRoute
- * @description
- * Creates a new backend definition that compares only with the requested route.
- *
- * @param {string} method HTTP method.
- * @param {string} url HTTP url string that supports colon param matching.
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled. See #when for more info.
- */
- $httpBackend.whenRoute = function(method, url) {
- var pathObj = parseRoute(url);
- return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys);
- };
-
- function parseRoute(url) {
- var ret = {
- regexp: url
- },
- keys = ret.keys = [];
-
- if (!url || !angular.isString(url)) return ret;
-
- url = url
- .replace(/([().])/g, '\\$1')
- .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
- var optional = option === '?' ? option : null;
- var star = option === '*' ? option : null;
- keys.push({ name: key, optional: !!optional });
- slash = slash || '';
- return ''
- + (optional ? '' : slash)
- + '(?:'
- + (optional ? slash : '')
- + (star && '(.+?)' || '([^/]+)')
- + (optional || '')
- + ')'
- + (optional || '');
- })
- .replace(/([\/$\*])/g, '\\$1');
-
- ret.regexp = new RegExp('^' + url, 'i');
- return ret;
- }
/**
* @ngdoc method
@@ -1606,21 +1395,20 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* is in JSON format.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current expectation.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers, params)}`
+ * | function(function(method, url, data, headers)}`
* – The respond method takes a set of static data to be returned or a function that can
* return an array containing response status (number), response data (string), response
* headers (Object), and the text for the status (string). The respond method returns the
* `requestHandler` object for possible overrides.
*/
- $httpBackend.expect = function(method, url, data, headers, keys) {
- var expectation = new MockHttpExpectation(method, url, data, headers, keys),
+ $httpBackend.expect = function(method, url, data, headers) {
+ var expectation = new MockHttpExpectation(method, url, data, headers),
chain = {
respond: function(status, data, headers, statusText) {
expectation.response = createResponse(status, data, headers, statusText);
@@ -1632,6 +1420,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
return chain;
};
+
/**
* @ngdoc method
* @name $httpBackend#expectGET
@@ -1641,7 +1430,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled. See #expect for more info.
@@ -1656,7 +1444,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1671,7 +1458,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1689,7 +1475,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1707,7 +1492,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1725,7 +1509,6 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
@@ -1739,30 +1522,12 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
*
* @param {string|RegExp|function(string)} url HTTP url or function that receives an url
* and returns true if the url matches the current definition.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
* request is handled. You can save this object for later use and invoke `respond` again in
* order to change how a matched request is handled.
*/
createShortMethods('expect');
- /**
- * @ngdoc method
- * @name $httpBackend#expectRoute
- * @description
- * Creates a new request expectation that compares only with the requested route.
- *
- * @param {string} method HTTP method.
- * @param {string} url HTTP url string that supports colon param matching.
- * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
- * request is handled. You can save this object for later use and invoke `respond` again in
- * order to change how a matched request is handled. See #expect for more info.
- */
- $httpBackend.expectRoute = function(method, url) {
- var pathObj = parseRoute(url);
- return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys);
- };
-
/**
* @ngdoc method
@@ -1852,20 +1617,20 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
function createShortMethods(prefix) {
angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
- $httpBackend[prefix + method] = function(url, headers, keys) {
- return $httpBackend[prefix](method, url, undefined, headers, keys);
+ $httpBackend[prefix + method] = function(url, headers) {
+ return $httpBackend[prefix](method, url, undefined, headers);
};
});
angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
- $httpBackend[prefix + method] = function(url, data, headers, keys) {
- return $httpBackend[prefix](method, url, data, headers, keys);
+ $httpBackend[prefix + method] = function(url, data, headers) {
+ return $httpBackend[prefix](method, url, data, headers);
};
});
}
}
-function MockHttpExpectation(method, url, data, headers, keys) {
+function MockHttpExpectation(method, url, data, headers) {
this.data = data;
this.headers = headers;
@@ -1904,59 +1669,6 @@ function MockHttpExpectation(method, url, data, headers, keys) {
this.toString = function() {
return method + ' ' + url;
};
-
- this.params = function(u) {
- return angular.extend(parseQuery(), pathParams());
-
- function pathParams() {
- var keyObj = {};
- if (!url || !angular.isFunction(url.test) || !keys || keys.length === 0) return keyObj;
-
- var m = url.exec(u);
- if (!m) return keyObj;
- for (var i = 1, len = m.length; i < len; ++i) {
- var key = keys[i - 1];
- var val = m[i];
- if (key && val) {
- keyObj[key.name || key] = val;
- }
- }
-
- return keyObj;
- }
-
- function parseQuery() {
- var obj = {}, key_value, key,
- queryStr = u.indexOf('?') > -1
- ? u.substring(u.indexOf('?') + 1)
- : "";
-
- angular.forEach(queryStr.split('&'), function(keyValue) {
- if (keyValue) {
- key_value = keyValue.replace(/\+/g,'%20').split('=');
- key = tryDecodeURIComponent(key_value[0]);
- if (angular.isDefined(key)) {
- var val = angular.isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!hasOwnProperty.call(obj, key)) {
- obj[key] = val;
- } else if (angular.isArray(obj[key])) {
- obj[key].push(val);
- } else {
- obj[key] = [obj[key],val];
- }
- }
- }
- });
- return obj;
- }
- function tryDecodeURIComponent(value) {
- try {
- return decodeURIComponent(value);
- } catch (e) {
- // Ignore any invalid uri component
- }
- }
- };
}
function createMockXhr() {
@@ -2125,7 +1837,7 @@ angular.mock.$RootElementProvider = function() {
*
* // Controller definition ...
*
- * myMod.controller('MyDirectiveController', ['$log', function($log) {
+ * myMod.controller('MyDirectiveController', ['log', function($log) {
* $log.info(this.name);
* })];
*
@@ -2171,49 +1883,6 @@ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
};
}];
-/**
- * @ngdoc service
- * @name $componentController
- * @description
- * A service that can be used to create instances of component controllers.
- * <div class="alert alert-info">
- * Be aware that the controller will be instantiated and attached to the scope as specified in
- * the component definition object. That means that you must always provide a `$scope` object
- * in the `locals` param.
- * </div>
- * @param {string} componentName the name of the component whose controller we want to instantiate
- * @param {Object} locals Injection locals for Controller.
- * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
- * to simulate the `bindToController` feature and simplify certain kinds of tests.
- * @param {string=} ident Override the property name to use when attaching the controller to the scope.
- * @return {Object} Instance of requested controller.
- */
-angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) {
- return {
- $get: ['$controller','$injector', function($controller,$injector) {
- return function $componentController(componentName, locals, bindings, ident) {
- // get all directives associated to the component name
- var directives = $injector.get(componentName + 'Directive');
- // look for those directives that are components
- var candidateDirectives = directives.filter(function(directiveInfo) {
- // components have controller, controllerAs and restrict:'E'
- return directiveInfo.controller && directiveInfo.controllerAs && directiveInfo.restrict === 'E';
- });
- // check if valid directives found
- if (candidateDirectives.length === 0) {
- throw new Error('No component found');
- }
- if (candidateDirectives.length > 1) {
- throw new Error('Too many components found');
- }
- // get the info of the component
- var directiveInfo = candidateDirectives[0];
- return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
- };
- }]
- };
-}];
-
/**
* @ngdoc module
@@ -2237,8 +1906,7 @@ angular.module('ngMock', ['ng']).provider({
$log: angular.mock.$LogProvider,
$interval: angular.mock.$IntervalProvider,
$httpBackend: angular.mock.$HttpBackendProvider,
- $rootElement: angular.mock.$RootElementProvider,
- $componentController: angular.mock.$ComponentControllerProvider
+ $rootElement: angular.mock.$RootElementProvider
}).config(['$provide', function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
@@ -2325,15 +1993,13 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current definition.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
*
* - respond –
* `{function([status,] data[, headers, statusText])
- * | function(function(method, url, data, headers, params)}`
+ * | function(function(method, url, data, headers)}`
* – The respond method takes a set of static data to be returned or a function that can return
* an array containing response status (number), response data (string), response headers
* (Object), and the text for the status (string).
@@ -2353,8 +2019,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2370,8 +2034,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2387,8 +2049,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2405,8 +2065,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url matches the current definition.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2423,8 +2081,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url matches the current definition.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2441,8 +2097,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
* and returns true if the url matches the current definition.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(Object|function(Object))=} headers HTTP headers.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2457,21 +2111,6 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
*
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
* and returns true if the url matches the current definition.
- * @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
- * {@link ngMock.$httpBackend $httpBackend mock}.
- * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
- * control how a matched request is handled. You can save this object for later use and invoke
- * `respond` or `passThrough` again in order to change how a matched request is handled.
- */
-/**
- * @ngdoc method
- * @name $httpBackend#whenRoute
- * @module ngMockE2E
- * @description
- * Creates a new backend definition that compares only with the requested route.
- *
- * @param {string} method HTTP method.
- * @param {string} url HTTP url string that supports colon param matching.
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
* control how a matched request is handled. You can save this object for later use and invoke
* `respond` or `passThrough` again in order to change how a matched request is handled.
@@ -2604,12 +2243,10 @@ if (window.jasmine || window.mocha) {
currentSpec.$injector = null;
currentSpec.$modules = null;
- currentSpec.$providerInjector = null;
currentSpec = null;
if (injector) {
injector.get('$rootElement').off();
- injector.get('$rootScope').$destroy();
}
// clean up jquery's fragment cache
@@ -2653,21 +2290,16 @@ if (window.jasmine || window.mocha) {
if (currentSpec.$injector) {
throw new Error('Injector already created, can not register a module!');
} else {
- var fn, modules = currentSpec.$modules || (currentSpec.$modules = []);
+ var modules = currentSpec.$modules || (currentSpec.$modules = []);
angular.forEach(moduleFns, function(module) {
if (angular.isObject(module) && !angular.isArray(module)) {
- fn = function($provide) {
+ modules.push(function($provide) {
angular.forEach(module, function(value, key) {
$provide.value(key, value);
});
- };
+ });
} else {
- fn = module;
- }
- if (currentSpec.$providerInjector) {
- currentSpec.$providerInjector.invoke(fn);
- } else {
- modules.push(fn);
+ modules.push(module);
}
});
}
@@ -2781,9 +2413,6 @@ if (window.jasmine || window.mocha) {
function workFn() {
var modules = currentSpec.$modules || [];
var strictDi = !!currentSpec.$injectorStrict;
- modules.unshift(function($injector) {
- currentSpec.$providerInjector = $injector;
- });
modules.unshift('ngMock');
modules.unshift('ng');
var injector = currentSpec.$injector;
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.js
index 444be83c..335859f7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.js
@@ -1,6 +1,6 @@
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
@@ -68,9 +68,6 @@ function shallowClearAndCopy(src, dst) {
* @ngdoc service
* @name $resource
* @requires $http
- * @requires ng.$log
- * @requires $q
- * @requires ng.$timeout
*
* @description
* A factory which creates a resource object that lets you interact with
@@ -105,7 +102,7 @@ function shallowClearAndCopy(src, dst) {
* can escape it with `/\.`.
*
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
- * `actions` methods. If a parameter value is a function, it will be executed every time
+ * `actions` methods. If any of the parameter value is a function, it will be executed every time
* when a param value needs to be obtained for a request (unless the param was overridden).
*
* Each key value in the parameter object is first bound to url template if present and then any
@@ -115,9 +112,9 @@ function shallowClearAndCopy(src, dst) {
* URL `/path/greet?salutation=Hello`.
*
* If the parameter value is prefixed with `@` then the value for that parameter will be extracted
- * from the corresponding property on the `data` object (provided when calling an action method).
- * For example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of
- * `someParam` will be `data.someProp`.
+ * from the corresponding property on the `data` object (provided when calling an action method). For
+ * example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
+ * will be `data.someProp`.
*
* @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend
* the default set of resource actions. The declaration should be created in the format of {@link
@@ -151,21 +148,15 @@ function shallowClearAndCopy(src, dst) {
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version.
- * By default, transformResponse will contain one function that checks if the response looks
- * like a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior,
- * set `transformResponse` to an empty array: `transformResponse: []`
+ * By default, transformResponse will contain one function that checks if the response looks like
+ * a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set
+ * `transformResponse` to an empty array: `transformResponse: []`
* - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
* caching.
- * - **`timeout`** – `{number}` – timeout in milliseconds.<br />
- * **Note:** In contrast to {@link ng.$http#usage $http.config}, {@link ng.$q promises} are
- * **not** supported in $resource, because the same value would be used for multiple requests.
- * If you are looking for a way to cancel requests, you should use the `cancellable` option.
- * - **`cancellable`** – `{boolean}` – if set to true, the request made by a "non-instance" call
- * will be cancelled (if not already completed) by calling `$cancelRequest()` on the call's
- * return value. Calling `$cancelRequest()` for a non-cancellable or an already
- * completed/cancelled request will have no effect.<br />
+ * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
+ * should abort the request when resolved.
* - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
* XHR object. See
* [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)
@@ -177,13 +168,12 @@ function shallowClearAndCopy(src, dst) {
* with `http response` object. See {@link ng.$http $http interceptors}.
*
* @param {Object} options Hash with custom settings that should extend the
- * default `$resourceProvider` behavior. The supported options are:
+ * default `$resourceProvider` behavior. The only supported option is
+ *
+ * Where:
*
* - **`stripTrailingSlashes`** – {boolean} – If true then the trailing
* slashes from any calculated URL will be stripped. (Defaults to true.)
- * - **`cancellable`** – {boolean} – If true, the request made by a "non-instance" call will be
- * cancelled (if not already completed) by calling `$cancelRequest()` on the call's return value.
- * This can be overwritten per action. (Defaults to false.)
*
* @returns {Object} A resource "class" object with methods for the default set of resource actions
* optionally extended with custom `actions`. The default set contains these actions:
@@ -231,7 +221,7 @@ function shallowClearAndCopy(src, dst) {
* Class actions return empty instance (with additional properties below).
* Instance actions return promise of the action.
*
- * The Resource instances and collections have these additional properties:
+ * The Resource instances and collection have these additional properties:
*
* - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
* instance or collection.
@@ -241,7 +231,7 @@ function shallowClearAndCopy(src, dst) {
* {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
* rendering until the resource(s) are loaded.
*
- * On failure, the promise is rejected with the {@link ng.$http http response} object, without
+ * On failure, the promise is resolved with the {@link ng.$http http response} object, without
* the `resource` property.
*
* If an interceptor object was provided, the promise will instead be resolved with the value
@@ -251,11 +241,6 @@ function shallowClearAndCopy(src, dst) {
* rejection), `false` before that. Knowing if the Resource has been resolved is useful in
* data-binding.
*
- * The Resource instances and collections have these additional methods:
- *
- * - `$cancelRequest`: If there is a cancellable, pending request related to the instance or
- * collection, calling this method will abort the request.
- *
* @example
*
* # Credit card resource
@@ -300,11 +285,6 @@ function shallowClearAndCopy(src, dst) {
*
* Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
* `headers`.
- *
- * @example
- *
- * # User resource
- *
* When the data is returned from the server then the object is an instance of the resource type and
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
* operations (create, read, update, delete) on server-side data.
@@ -323,10 +303,10 @@ function shallowClearAndCopy(src, dst) {
*
```js
var User = $resource('/user/:userId', {userId:'@id'});
- User.get({userId:123}, function(user, getResponseHeaders){
- user.abc = true;
- user.$save(function(user, putResponseHeaders) {
- //user => saved user object
+ User.get({userId:123}, function(u, getResponseHeaders){
+ u.abc = true;
+ u.$save(function(u, putResponseHeaders) {
+ //u => saved user object
//putResponseHeaders => $http header getter
});
});
@@ -341,11 +321,8 @@ function shallowClearAndCopy(src, dst) {
$scope.user = user;
});
```
- *
- * @example
- *
+
* # Creating a custom 'PUT' request
- *
* In this example we create a custom method on our resource to make a PUT request
* ```js
* var app = angular.module('app', ['ngResource', 'ngRoute']);
@@ -373,34 +350,6 @@ function shallowClearAndCopy(src, dst) {
* // This will PUT /notes/ID with the note object in the request payload
* }]);
* ```
- *
- * @example
- *
- * # Cancelling requests
- *
- * If an action's configuration specifies that it is cancellable, you can cancel the request related
- * to an instance or collection (as long as it is a result of a "non-instance" call):
- *
- ```js
- // ...defining the `Hotel` resource...
- var Hotel = $resource('/api/hotel/:id', {id: '@id'}, {
- // Let's make the `query()` method cancellable
- query: {method: 'get', isArray: true, cancellable: true}
- });
-
- // ...somewhere in the PlanVacationController...
- ...
- this.onDestinationChanged = function onDestinationChanged(destination) {
- // We don't care about any pending request for hotels
- // in a different destination any more
- this.availableHotels.$cancelRequest();
-
- // Let's query for hotels in '<destination>'
- // (calls: /api/hotel?location=<destination>)
- this.availableHotels = Hotel.query({location: destination});
- };
- ```
- *
*/
angular.module('ngResource', ['ng']).
provider('$resource', function() {
@@ -421,7 +370,7 @@ angular.module('ngResource', ['ng']).
}
};
- this.$get = ['$http', '$log', '$q', '$timeout', function($http, $log, $q, $timeout) {
+ this.$get = ['$http', '$q', function($http, $q) {
var noop = angular.noop,
forEach = angular.forEach,
@@ -489,9 +438,7 @@ angular.module('ngResource', ['ng']).
}
if (!(new RegExp("^\\d+$").test(param)) && param &&
(new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
- urlParams[param] = {
- isQueryParamValue: (new RegExp("\\?.*=:" + param + "(?:\\W|$)")).test(url)
- };
+ urlParams[param] = true;
}
});
url = url.replace(/\\:/g, ':');
@@ -501,14 +448,10 @@ angular.module('ngResource', ['ng']).
});
params = params || {};
- forEach(self.urlParams, function(paramInfo, urlParam) {
+ forEach(self.urlParams, function(_, urlParam) {
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
if (angular.isDefined(val) && val !== null) {
- if (paramInfo.isQueryParamValue) {
- encodedVal = encodeUriQuery(val, true);
- } else {
- encodedVal = encodeUriSegment(val);
- }
+ encodedVal = encodeUriSegment(val);
url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
return encodedVal + p1;
});
@@ -580,20 +523,6 @@ angular.module('ngResource', ['ng']).
forEach(actions, function(action, name) {
var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
- var numericTimeout = action.timeout;
- var cancellable = angular.isDefined(action.cancellable) ? action.cancellable :
- (options && angular.isDefined(options.cancellable)) ? options.cancellable :
- provider.defaults.cancellable;
-
- if (numericTimeout && !angular.isNumber(numericTimeout)) {
- $log.debug('ngResource:\n' +
- ' Only numeric values are allowed as `timeout`.\n' +
- ' Promises are not supported in $resource, because the same value would ' +
- 'be used for multiple requests. If you are looking for a way to cancel ' +
- 'requests, you should use the `cancellable` option.');
- delete action.timeout;
- numericTimeout = null;
- }
Resource[name] = function(a1, a2, a3, a4) {
var params = {}, data, success, error;
@@ -642,8 +571,6 @@ angular.module('ngResource', ['ng']).
defaultResponseInterceptor;
var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
undefined;
- var timeoutDeferred;
- var numericTimeoutPromise;
forEach(action, function(value, key) {
switch (key) {
@@ -653,27 +580,21 @@ angular.module('ngResource', ['ng']).
case 'params':
case 'isArray':
case 'interceptor':
- case 'cancellable':
+ break;
+ case 'timeout':
+ httpConfig[key] = value;
break;
}
});
- if (!isInstanceCall && cancellable) {
- timeoutDeferred = $q.defer();
- httpConfig.timeout = timeoutDeferred.promise;
-
- if (numericTimeout) {
- numericTimeoutPromise = $timeout(timeoutDeferred.resolve, numericTimeout);
- }
- }
-
if (hasBody) httpConfig.data = data;
route.setUrlParams(httpConfig,
extend({}, extractParams(data, action.params || {}), params),
action.url);
var promise = $http(httpConfig).then(function(response) {
- var data = response.data;
+ var data = response.data,
+ promise = value.$promise;
if (data) {
// Need to convert action.isArray to boolean in case it is undefined
@@ -698,26 +619,22 @@ angular.module('ngResource', ['ng']).
}
});
} else {
- var promise = value.$promise; // Save the promise
shallowClearAndCopy(data, value);
- value.$promise = promise; // Restore the promise
+ value.$promise = promise;
}
}
+
+ value.$resolved = true;
+
response.resource = value;
return response;
}, function(response) {
+ value.$resolved = true;
+
(error || noop)(response);
- return $q.reject(response);
- });
- promise.finally(function() {
- value.$resolved = true;
- if (!isInstanceCall && cancellable) {
- value.$cancelRequest = angular.noop;
- $timeout.cancel(numericTimeoutPromise);
- timeoutDeferred = numericTimeoutPromise = httpConfig.timeout = null;
- }
+ return $q.reject(response);
});
promise = promise.then(
@@ -734,7 +651,6 @@ angular.module('ngResource', ['ng']).
// - return the instance / collection
value.$promise = promise;
value.$resolved = false;
- if (cancellable) value.$cancelRequest = timeoutDeferred.resolve;
return value;
}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js
new file mode 100644
index 00000000..c3fb7aab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js
@@ -0,0 +1,14 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(I,f,C){'use strict';function D(t,e){e=e||{};f.forEach(e,function(f,k){delete e[k]});for(var k in t)!t.hasOwnProperty(k)||"$"===k.charAt(0)&&"$"===k.charAt(1)||(e[k]=t[k]);return e}var y=f.$$minErr("$resource"),B=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;f.module("ngResource",["ng"]).provider("$resource",function(){var t=/^https?:\/\/[^\/]*/,e=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}};
+this.$get=["$http","$q",function(k,F){function w(f,g){this.template=f;this.defaults=r({},e.defaults,g);this.urlParams={}}function z(l,g,s,h){function c(a,q){var c={};q=r({},g,q);u(q,function(b,q){x(b)&&(b=b());var m;if(b&&b.charAt&&"@"==b.charAt(0)){m=a;var d=b.substr(1);if(null==d||""===d||"hasOwnProperty"===d||!B.test("."+d))throw y("badmember",d);for(var d=d.split("."),n=0,g=d.length;n<g&&f.isDefined(m);n++){var e=d[n];m=null!==m?m[e]:C}}else m=b;c[q]=m});return c}function G(a){return a.resource}
+function d(a){D(a||{},this)}var t=new w(l,h);s=r({},e.defaults.actions,s);d.prototype.toJSON=function(){var a=r({},this);delete a.$promise;delete a.$resolved;return a};u(s,function(a,q){var g=/^(POST|PUT|PATCH)$/i.test(a.method);d[q]=function(b,A,m,e){var n={},h,l,s;switch(arguments.length){case 4:s=e,l=m;case 3:case 2:if(x(A)){if(x(b)){l=b;s=A;break}l=A;s=m}else{n=b;h=A;l=m;break}case 1:x(b)?l=b:g?h=b:n=b;break;case 0:break;default:throw y("badargs",arguments.length);}var w=this instanceof d,p=w?
+h:a.isArray?[]:new d(h),v={},z=a.interceptor&&a.interceptor.response||G,B=a.interceptor&&a.interceptor.responseError||C;u(a,function(a,b){switch(b){default:v[b]=H(a);break;case "params":case "isArray":case "interceptor":break;case "timeout":v[b]=a}});g&&(v.data=h);t.setUrlParams(v,r({},c(h,a.params||{}),n),a.url);n=k(v).then(function(b){var c=b.data,m=p.$promise;if(c){if(f.isArray(c)!==!!a.isArray)throw y("badcfg",q,a.isArray?"array":"object",f.isArray(c)?"array":"object",v.method,v.url);a.isArray?
+(p.length=0,u(c,function(b){"object"===typeof b?p.push(new d(b)):p.push(b)})):(D(c,p),p.$promise=m)}p.$resolved=!0;b.resource=p;return b},function(b){p.$resolved=!0;(s||E)(b);return F.reject(b)});n=n.then(function(b){var a=z(b);(l||E)(a,b.headers);return a},B);return w?n:(p.$promise=n,p.$resolved=!1,p)};d.prototype["$"+q]=function(b,a,c){x(b)&&(c=a,a=b,b={});b=d[q].call(this,b,this,a,c);return b.$promise||b}});d.bind=function(a){return z(l,r({},g,a),s)};return d}var E=f.noop,u=f.forEach,r=f.extend,
+H=f.copy,x=f.isFunction;w.prototype={setUrlParams:function(l,g,e){var h=this,c=e||h.template,k,d,r="",a=h.urlParams={};u(c.split(/\W/),function(d){if("hasOwnProperty"===d)throw y("badname");!/^\d+$/.test(d)&&d&&(new RegExp("(^|[^\\\\]):"+d+"(\\W|$)")).test(c)&&(a[d]=!0)});c=c.replace(/\\:/g,":");c=c.replace(t,function(a){r=a;return""});g=g||{};u(h.urlParams,function(a,e){k=g.hasOwnProperty(e)?g[e]:h.defaults[e];f.isDefined(k)&&null!==k?(d=encodeURIComponent(k).replace(/%40/gi,"@").replace(/%3A/gi,
+":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(new RegExp(":"+e+"(\\W|$)","g"),function(b,a){return d+a})):c=c.replace(new RegExp("(/?):"+e+"(\\W|$)","g"),function(b,a,c){return"/"==c.charAt(0)?c:a+c})});h.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");l.url=r+c.replace(/\/\\\./,"/.");u(g,function(a,c){h.urlParams[c]||(l.params=l.params||{},l.params[c]=
+a)})}};return z}]})})(window,window.angular);
+//# sourceMappingURL=angular-resource.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js.map
new file mode 100644
index 00000000..c2302084
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-resource.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-resource.min.js",
+"lineCount":13,
+"mappings":"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",
+"sources":["angular-resource.js"],
+"names":["window","angular","undefined","shallowClearAndCopy","src","dst","forEach","value","key","hasOwnProperty","charAt","$resourceMinErr","$$minErr","MEMBER_NAME_REGEX","module","provider","PROTOCOL_AND_DOMAIN_REGEX","defaults","stripTrailingSlashes","actions","method","isArray","$get","$http","$q","Route","template","extend","urlParams","resourceFactory","url","paramDefaults","options","extractParams","data","actionParams","ids","isFunction","path","test","keys","split","i","ii","length","isDefined","obj","defaultResponseInterceptor","response","resource","Resource","route","prototype","toJSON","Resource.prototype.toJSON","$promise","$resolved","action","name","hasBody","a1","a2","a3","a4","params","success","error","arguments","isInstanceCall","httpConfig","responseInterceptor","interceptor","responseErrorInterceptor","responseError","copy","setUrlParams","promise","then","item","push","noop","reject","headers","result","call","bind","Resource.bind","additionalParamDefaults","config","actionUrl","self","val","encodedVal","protocolAndDomain","param","RegExp","replace","match","_","urlParam","encodeURIComponent","p1","leadingSlashes","tail"]
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.js
new file mode 100644
index 00000000..86ab235d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.js
@@ -0,0 +1,991 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/**
+ * @ngdoc module
+ * @name ngRoute
+ * @description
+ *
+ * # ngRoute
+ *
+ * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
+ *
+ * ## Example
+ * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
+ *
+ *
+ * <div doc-module-components="ngRoute"></div>
+ */
+ /* global -ngRouteModule */
+var ngRouteModule = angular.module('ngRoute', ['ng']).
+ provider('$route', $RouteProvider),
+ $routeMinErr = angular.$$minErr('ngRoute');
+
+/**
+ * @ngdoc provider
+ * @name $routeProvider
+ *
+ * @description
+ *
+ * Used for configuring routes.
+ *
+ * ## Example
+ * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
+ *
+ * ## Dependencies
+ * Requires the {@link ngRoute `ngRoute`} module to be installed.
+ */
+function $RouteProvider() {
+ function inherit(parent, extra) {
+ return angular.extend(Object.create(parent), extra);
+ }
+
+ var routes = {};
+
+ /**
+ * @ngdoc method
+ * @name $routeProvider#when
+ *
+ * @param {string} path Route path (matched against `$location.path`). If `$location.path`
+ * contains redundant trailing slash or is missing one, the route will still match and the
+ * `$location.path` will be updated to add or drop the trailing slash to exactly match the
+ * route definition.
+ *
+ * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
+ * to the next slash are matched and stored in `$routeParams` under the given `name`
+ * when the route matches.
+ * * `path` can contain named groups starting with a colon and ending with a star:
+ * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
+ * when the route matches.
+ * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
+ *
+ * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
+ * `/color/brown/largecode/code/with/slashes/edit` and extract:
+ *
+ * * `color: brown`
+ * * `largecode: code/with/slashes`.
+ *
+ *
+ * @param {Object} route Mapping information to be assigned to `$route.current` on route
+ * match.
+ *
+ * Object properties:
+ *
+ * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
+ * newly created scope or the name of a {@link angular.Module#controller registered
+ * controller} if passed as a string.
+ * - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
+ * If present, the controller will be published to scope under the `controllerAs` name.
+ * - `template` – `{string=|function()=}` – html template as a string or a function that
+ * returns an html template as a string which should be used by {@link
+ * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
+ * This property takes precedence over `templateUrl`.
+ *
+ * If `template` is a function, it will be called with the following parameters:
+ *
+ * - `{Array.<Object>}` - route parameters extracted from the current
+ * `$location.path()` by applying the current route
+ *
+ * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
+ * template that should be used by {@link ngRoute.directive:ngView ngView}.
+ *
+ * If `templateUrl` is a function, it will be called with the following parameters:
+ *
+ * - `{Array.<Object>}` - route parameters extracted from the current
+ * `$location.path()` by applying the current route
+ *
+ * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
+ * be injected into the controller. If any of these dependencies are promises, the router
+ * will wait for them all to be resolved or one to be rejected before the controller is
+ * instantiated.
+ * If all the promises are resolved successfully, the values of the resolved promises are
+ * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
+ * fired. If any of the promises are rejected the
+ * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
+ * is:
+ *
+ * - `key` – `{string}`: a name of a dependency to be injected into the controller.
+ * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
+ * Otherwise if function, then it is {@link auto.$injector#invoke injected}
+ * and the return value is treated as the dependency. If the result is a promise, it is
+ * resolved before its value is injected into the controller. Be aware that
+ * `ngRoute.$routeParams` will still refer to the previous route within these resolve
+ * functions. Use `$route.current.params` to access the new route parameters, instead.
+ *
+ * - `redirectTo` – {(string|function())=} – value to update
+ * {@link ng.$location $location} path with and trigger route redirection.
+ *
+ * If `redirectTo` is a function, it will be called with the following parameters:
+ *
+ * - `{Object.<string>}` - route parameters extracted from the current
+ * `$location.path()` by applying the current route templateUrl.
+ * - `{string}` - current `$location.path()`
+ * - `{Object}` - current `$location.search()`
+ *
+ * The custom `redirectTo` function is expected to return a string which will be used
+ * to update `$location.path()` and `$location.search()`.
+ *
+ * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
+ * or `$location.hash()` changes.
+ *
+ * If the option is set to `false` and url in the browser changes, then
+ * `$routeUpdate` event is broadcasted on the root scope.
+ *
+ * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
+ *
+ * If the option is set to `true`, then the particular route can be matched without being
+ * case sensitive
+ *
+ * @returns {Object} self
+ *
+ * @description
+ * Adds a new route definition to the `$route` service.
+ */
+ this.when = function(path, route) {
+ //copy original route object to preserve params inherited from proto chain
+ var routeCopy = angular.copy(route);
+ if (angular.isUndefined(routeCopy.reloadOnSearch)) {
+ routeCopy.reloadOnSearch = true;
+ }
+ if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
+ routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
+ }
+ routes[path] = angular.extend(
+ routeCopy,
+ path && pathRegExp(path, routeCopy)
+ );
+
+ // create redirection for trailing slashes
+ if (path) {
+ var redirectPath = (path[path.length - 1] == '/')
+ ? path.substr(0, path.length - 1)
+ : path + '/';
+
+ routes[redirectPath] = angular.extend(
+ {redirectTo: path},
+ pathRegExp(redirectPath, routeCopy)
+ );
+ }
+
+ return this;
+ };
+
+ /**
+ * @ngdoc property
+ * @name $routeProvider#caseInsensitiveMatch
+ * @description
+ *
+ * A boolean property indicating if routes defined
+ * using this provider should be matched using a case insensitive
+ * algorithm. Defaults to `false`.
+ */
+ this.caseInsensitiveMatch = false;
+
+ /**
+ * @param path {string} path
+ * @param opts {Object} options
+ * @return {?Object}
+ *
+ * @description
+ * Normalizes the given path, returning a regular expression
+ * and the original path.
+ *
+ * Inspired by pathRexp in visionmedia/express/lib/utils.js.
+ */
+ function pathRegExp(path, opts) {
+ var insensitive = opts.caseInsensitiveMatch,
+ ret = {
+ originalPath: path,
+ regexp: path
+ },
+ keys = ret.keys = [];
+
+ path = path
+ .replace(/([().])/g, '\\$1')
+ .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
+ var optional = option === '?' ? option : null;
+ var star = option === '*' ? option : null;
+ keys.push({ name: key, optional: !!optional });
+ slash = slash || '';
+ return ''
+ + (optional ? '' : slash)
+ + '(?:'
+ + (optional ? slash : '')
+ + (star && '(.+?)' || '([^/]+)')
+ + (optional || '')
+ + ')'
+ + (optional || '');
+ })
+ .replace(/([\/$\*])/g, '\\$1');
+
+ ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
+ return ret;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $routeProvider#otherwise
+ *
+ * @description
+ * Sets route definition that will be used on route change when no other route definition
+ * is matched.
+ *
+ * @param {Object|string} params Mapping information to be assigned to `$route.current`.
+ * If called with a string, the value maps to `redirectTo`.
+ * @returns {Object} self
+ */
+ this.otherwise = function(params) {
+ if (typeof params === 'string') {
+ params = {redirectTo: params};
+ }
+ this.when(null, params);
+ return this;
+ };
+
+
+ this.$get = ['$rootScope',
+ '$location',
+ '$routeParams',
+ '$q',
+ '$injector',
+ '$templateRequest',
+ '$sce',
+ function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
+
+ /**
+ * @ngdoc service
+ * @name $route
+ * @requires $location
+ * @requires $routeParams
+ *
+ * @property {Object} current Reference to the current route definition.
+ * The route definition contains:
+ *
+ * - `controller`: The controller constructor as define in route definition.
+ * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
+ * controller instantiation. The `locals` contain
+ * the resolved values of the `resolve` map. Additionally the `locals` also contain:
+ *
+ * - `$scope` - The current route scope.
+ * - `$template` - The current route template HTML.
+ *
+ * @property {Object} routes Object with all route configuration Objects as its properties.
+ *
+ * @description
+ * `$route` is used for deep-linking URLs to controllers and views (HTML partials).
+ * It watches `$location.url()` and tries to map the path to an existing route definition.
+ *
+ * Requires the {@link ngRoute `ngRoute`} module to be installed.
+ *
+ * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
+ *
+ * The `$route` service is typically used in conjunction with the
+ * {@link ngRoute.directive:ngView `ngView`} directive and the
+ * {@link ngRoute.$routeParams `$routeParams`} service.
+ *
+ * @example
+ * This example shows how changing the URL hash causes the `$route` to match a route against the
+ * URL, and the `ngView` pulls in the partial.
+ *
+ * <example name="$route-service" module="ngRouteExample"
+ * deps="angular-route.js" fixBase="true">
+ * <file name="index.html">
+ * <div ng-controller="MainController">
+ * Choose:
+ * <a href="Book/Moby">Moby</a> |
+ * <a href="Book/Moby/ch/1">Moby: Ch1</a> |
+ * <a href="Book/Gatsby">Gatsby</a> |
+ * <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
+ * <a href="Book/Scarlet">Scarlet Letter</a><br/>
+ *
+ * <div ng-view></div>
+ *
+ * <hr />
+ *
+ * <pre>$location.path() = {{$location.path()}}</pre>
+ * <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
+ * <pre>$route.current.params = {{$route.current.params}}</pre>
+ * <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
+ * <pre>$routeParams = {{$routeParams}}</pre>
+ * </div>
+ * </file>
+ *
+ * <file name="book.html">
+ * controller: {{name}}<br />
+ * Book Id: {{params.bookId}}<br />
+ * </file>
+ *
+ * <file name="chapter.html">
+ * controller: {{name}}<br />
+ * Book Id: {{params.bookId}}<br />
+ * Chapter Id: {{params.chapterId}}
+ * </file>
+ *
+ * <file name="script.js">
+ * angular.module('ngRouteExample', ['ngRoute'])
+ *
+ * .controller('MainController', function($scope, $route, $routeParams, $location) {
+ * $scope.$route = $route;
+ * $scope.$location = $location;
+ * $scope.$routeParams = $routeParams;
+ * })
+ *
+ * .controller('BookController', function($scope, $routeParams) {
+ * $scope.name = "BookController";
+ * $scope.params = $routeParams;
+ * })
+ *
+ * .controller('ChapterController', function($scope, $routeParams) {
+ * $scope.name = "ChapterController";
+ * $scope.params = $routeParams;
+ * })
+ *
+ * .config(function($routeProvider, $locationProvider) {
+ * $routeProvider
+ * .when('/Book/:bookId', {
+ * templateUrl: 'book.html',
+ * controller: 'BookController',
+ * resolve: {
+ * // I will cause a 1 second delay
+ * delay: function($q, $timeout) {
+ * var delay = $q.defer();
+ * $timeout(delay.resolve, 1000);
+ * return delay.promise;
+ * }
+ * }
+ * })
+ * .when('/Book/:bookId/ch/:chapterId', {
+ * templateUrl: 'chapter.html',
+ * controller: 'ChapterController'
+ * });
+ *
+ * // configure html5 to get links working on jsfiddle
+ * $locationProvider.html5Mode(true);
+ * });
+ *
+ * </file>
+ *
+ * <file name="protractor.js" type="protractor">
+ * it('should load and compile correct template', function() {
+ * element(by.linkText('Moby: Ch1')).click();
+ * var content = element(by.css('[ng-view]')).getText();
+ * expect(content).toMatch(/controller\: ChapterController/);
+ * expect(content).toMatch(/Book Id\: Moby/);
+ * expect(content).toMatch(/Chapter Id\: 1/);
+ *
+ * element(by.partialLinkText('Scarlet')).click();
+ *
+ * content = element(by.css('[ng-view]')).getText();
+ * expect(content).toMatch(/controller\: BookController/);
+ * expect(content).toMatch(/Book Id\: Scarlet/);
+ * });
+ * </file>
+ * </example>
+ */
+
+ /**
+ * @ngdoc event
+ * @name $route#$routeChangeStart
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted before a route change. At this point the route services starts
+ * resolving all of the dependencies needed for the route change to occur.
+ * Typically this involves fetching the view template as well as any dependencies
+ * defined in `resolve` route property. Once all of the dependencies are resolved
+ * `$routeChangeSuccess` is fired.
+ *
+ * The route change (and the `$location` change that triggered it) can be prevented
+ * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
+ * for more details about event object.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {Route} next Future route information.
+ * @param {Route} current Current route information.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $route#$routeChangeSuccess
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted after a route change has happened successfully.
+ * The `resolve` dependencies are now available in the `current.locals` property.
+ *
+ * {@link ngRoute.directive:ngView ngView} listens for the directive
+ * to instantiate the controller and render the view.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {Route} current Current route information.
+ * @param {Route|Undefined} previous Previous route information, or undefined if current is
+ * first route entered.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $route#$routeChangeError
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted if any of the resolve promises are rejected.
+ *
+ * @param {Object} angularEvent Synthetic event object
+ * @param {Route} current Current route information.
+ * @param {Route} previous Previous route information.
+ * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $route#$routeUpdate
+ * @eventType broadcast on root scope
+ * @description
+ * The `reloadOnSearch` property has been set to false, and we are reusing the same
+ * instance of the Controller.
+ *
+ * @param {Object} angularEvent Synthetic event object
+ * @param {Route} current Current/previous route information.
+ */
+
+ var forceReload = false,
+ preparedRoute,
+ preparedRouteIsUpdateOnly,
+ $route = {
+ routes: routes,
+
+ /**
+ * @ngdoc method
+ * @name $route#reload
+ *
+ * @description
+ * Causes `$route` service to reload the current route even if
+ * {@link ng.$location $location} hasn't changed.
+ *
+ * As a result of that, {@link ngRoute.directive:ngView ngView}
+ * creates new scope and reinstantiates the controller.
+ */
+ reload: function() {
+ forceReload = true;
+ $rootScope.$evalAsync(function() {
+ // Don't support cancellation of a reload for now...
+ prepareRoute();
+ commitRoute();
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $route#updateParams
+ *
+ * @description
+ * Causes `$route` service to update the current URL, replacing
+ * current route parameters with those specified in `newParams`.
+ * Provided property names that match the route's path segment
+ * definitions will be interpolated into the location's path, while
+ * remaining properties will be treated as query params.
+ *
+ * @param {!Object<string, string>} newParams mapping of URL parameter names to values
+ */
+ updateParams: function(newParams) {
+ if (this.current && this.current.$$route) {
+ newParams = angular.extend({}, this.current.params, newParams);
+ $location.path(interpolate(this.current.$$route.originalPath, newParams));
+ // interpolate modifies newParams, only query params are left
+ $location.search(newParams);
+ } else {
+ throw $routeMinErr('norout', 'Tried updating route when with no current route');
+ }
+ }
+ };
+
+ $rootScope.$on('$locationChangeStart', prepareRoute);
+ $rootScope.$on('$locationChangeSuccess', commitRoute);
+
+ return $route;
+
+ /////////////////////////////////////////////////////
+
+ /**
+ * @param on {string} current url
+ * @param route {Object} route regexp to match the url against
+ * @return {?Object}
+ *
+ * @description
+ * Check if the route matches the current url.
+ *
+ * Inspired by match in
+ * visionmedia/express/lib/router/router.js.
+ */
+ function switchRouteMatcher(on, route) {
+ var keys = route.keys,
+ params = {};
+
+ if (!route.regexp) return null;
+
+ var m = route.regexp.exec(on);
+ if (!m) return null;
+
+ for (var i = 1, len = m.length; i < len; ++i) {
+ var key = keys[i - 1];
+
+ var val = m[i];
+
+ if (key && val) {
+ params[key.name] = val;
+ }
+ }
+ return params;
+ }
+
+ function prepareRoute($locationEvent) {
+ var lastRoute = $route.current;
+
+ preparedRoute = parseRoute();
+ preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
+ && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
+ && !preparedRoute.reloadOnSearch && !forceReload;
+
+ if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
+ if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
+ if ($locationEvent) {
+ $locationEvent.preventDefault();
+ }
+ }
+ }
+ }
+
+ function commitRoute() {
+ var lastRoute = $route.current;
+ var nextRoute = preparedRoute;
+
+ if (preparedRouteIsUpdateOnly) {
+ lastRoute.params = nextRoute.params;
+ angular.copy(lastRoute.params, $routeParams);
+ $rootScope.$broadcast('$routeUpdate', lastRoute);
+ } else if (nextRoute || lastRoute) {
+ forceReload = false;
+ $route.current = nextRoute;
+ if (nextRoute) {
+ if (nextRoute.redirectTo) {
+ if (angular.isString(nextRoute.redirectTo)) {
+ $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
+ .replace();
+ } else {
+ $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
+ .replace();
+ }
+ }
+ }
+
+ $q.when(nextRoute).
+ then(function() {
+ if (nextRoute) {
+ var locals = angular.extend({}, nextRoute.resolve),
+ template, templateUrl;
+
+ angular.forEach(locals, function(value, key) {
+ locals[key] = angular.isString(value) ?
+ $injector.get(value) : $injector.invoke(value, null, null, key);
+ });
+
+ if (angular.isDefined(template = nextRoute.template)) {
+ if (angular.isFunction(template)) {
+ template = template(nextRoute.params);
+ }
+ } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
+ if (angular.isFunction(templateUrl)) {
+ templateUrl = templateUrl(nextRoute.params);
+ }
+ if (angular.isDefined(templateUrl)) {
+ nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
+ template = $templateRequest(templateUrl);
+ }
+ }
+ if (angular.isDefined(template)) {
+ locals['$template'] = template;
+ }
+ return $q.all(locals);
+ }
+ }).
+ then(function(locals) {
+ // after route change
+ if (nextRoute == $route.current) {
+ if (nextRoute) {
+ nextRoute.locals = locals;
+ angular.copy(nextRoute.params, $routeParams);
+ }
+ $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
+ }
+ }, function(error) {
+ if (nextRoute == $route.current) {
+ $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
+ }
+ });
+ }
+ }
+
+
+ /**
+ * @returns {Object} the current active route, by matching it against the URL
+ */
+ function parseRoute() {
+ // Match a route
+ var params, match;
+ angular.forEach(routes, function(route, path) {
+ if (!match && (params = switchRouteMatcher($location.path(), route))) {
+ match = inherit(route, {
+ params: angular.extend({}, $location.search(), params),
+ pathParams: params});
+ match.$$route = route;
+ }
+ });
+ // No route matched; fallback to "otherwise" route
+ return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
+ }
+
+ /**
+ * @returns {string} interpolation of the redirect path with the parameters
+ */
+ function interpolate(string, params) {
+ var result = [];
+ angular.forEach((string || '').split(':'), function(segment, i) {
+ if (i === 0) {
+ result.push(segment);
+ } else {
+ var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
+ var key = segmentMatch[1];
+ result.push(params[key]);
+ result.push(segmentMatch[2] || '');
+ delete params[key];
+ }
+ });
+ return result.join('');
+ }
+ }];
+}
+
+ngRouteModule.provider('$routeParams', $RouteParamsProvider);
+
+
+/**
+ * @ngdoc service
+ * @name $routeParams
+ * @requires $route
+ *
+ * @description
+ * The `$routeParams` service allows you to retrieve the current set of route parameters.
+ *
+ * Requires the {@link ngRoute `ngRoute`} module to be installed.
+ *
+ * The route parameters are a combination of {@link ng.$location `$location`}'s
+ * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
+ * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
+ *
+ * In case of parameter name collision, `path` params take precedence over `search` params.
+ *
+ * The service guarantees that the identity of the `$routeParams` object will remain unchanged
+ * (but its properties will likely change) even when a route change occurs.
+ *
+ * Note that the `$routeParams` are only updated *after* a route change completes successfully.
+ * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
+ * Instead you can use `$route.current.params` to access the new route's parameters.
+ *
+ * @example
+ * ```js
+ * // Given:
+ * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
+ * // Route: /Chapter/:chapterId/Section/:sectionId
+ * //
+ * // Then
+ * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
+ * ```
+ */
+function $RouteParamsProvider() {
+ this.$get = function() { return {}; };
+}
+
+ngRouteModule.directive('ngView', ngViewFactory);
+ngRouteModule.directive('ngView', ngViewFillContentFactory);
+
+
+/**
+ * @ngdoc directive
+ * @name ngView
+ * @restrict ECA
+ *
+ * @description
+ * # Overview
+ * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
+ * including the rendered template of the current route into the main layout (`index.html`) file.
+ * Every time the current route changes, the included view changes with it according to the
+ * configuration of the `$route` service.
+ *
+ * Requires the {@link ngRoute `ngRoute`} module to be installed.
+ *
+ * @animations
+ * enter - animation is used to bring new content into the browser.
+ * leave - animation is used to animate existing content away.
+ *
+ * The enter and leave animation occur concurrently.
+ *
+ * @scope
+ * @priority 400
+ * @param {string=} onload Expression to evaluate whenever the view updates.
+ *
+ * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
+ * $anchorScroll} to scroll the viewport after the view is updated.
+ *
+ * - If the attribute is not set, disable scrolling.
+ * - If the attribute is set without value, enable scrolling.
+ * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
+ * as an expression yields a truthy value.
+ * @example
+ <example name="ngView-directive" module="ngViewExample"
+ deps="angular-route.js;angular-animate.js"
+ animations="true" fixBase="true">
+ <file name="index.html">
+ <div ng-controller="MainCtrl as main">
+ Choose:
+ <a href="Book/Moby">Moby</a> |
+ <a href="Book/Moby/ch/1">Moby: Ch1</a> |
+ <a href="Book/Gatsby">Gatsby</a> |
+ <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
+ <a href="Book/Scarlet">Scarlet Letter</a><br/>
+
+ <div class="view-animate-container">
+ <div ng-view class="view-animate"></div>
+ </div>
+ <hr />
+
+ <pre>$location.path() = {{main.$location.path()}}</pre>
+ <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
+ <pre>$route.current.params = {{main.$route.current.params}}</pre>
+ <pre>$routeParams = {{main.$routeParams}}</pre>
+ </div>
+ </file>
+
+ <file name="book.html">
+ <div>
+ controller: {{book.name}}<br />
+ Book Id: {{book.params.bookId}}<br />
+ </div>
+ </file>
+
+ <file name="chapter.html">
+ <div>
+ controller: {{chapter.name}}<br />
+ Book Id: {{chapter.params.bookId}}<br />
+ Chapter Id: {{chapter.params.chapterId}}
+ </div>
+ </file>
+
+ <file name="animations.css">
+ .view-animate-container {
+ position:relative;
+ height:100px!important;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .view-animate {
+ padding:10px;
+ }
+
+ .view-animate.ng-enter, .view-animate.ng-leave {
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
+
+ display:block;
+ width:100%;
+ border-left:1px solid black;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ padding:10px;
+ }
+
+ .view-animate.ng-enter {
+ left:100%;
+ }
+ .view-animate.ng-enter.ng-enter-active {
+ left:0;
+ }
+ .view-animate.ng-leave.ng-leave-active {
+ left:-100%;
+ }
+ </file>
+
+ <file name="script.js">
+ angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
+ .config(['$routeProvider', '$locationProvider',
+ function($routeProvider, $locationProvider) {
+ $routeProvider
+ .when('/Book/:bookId', {
+ templateUrl: 'book.html',
+ controller: 'BookCtrl',
+ controllerAs: 'book'
+ })
+ .when('/Book/:bookId/ch/:chapterId', {
+ templateUrl: 'chapter.html',
+ controller: 'ChapterCtrl',
+ controllerAs: 'chapter'
+ });
+
+ $locationProvider.html5Mode(true);
+ }])
+ .controller('MainCtrl', ['$route', '$routeParams', '$location',
+ function($route, $routeParams, $location) {
+ this.$route = $route;
+ this.$location = $location;
+ this.$routeParams = $routeParams;
+ }])
+ .controller('BookCtrl', ['$routeParams', function($routeParams) {
+ this.name = "BookCtrl";
+ this.params = $routeParams;
+ }])
+ .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
+ this.name = "ChapterCtrl";
+ this.params = $routeParams;
+ }]);
+
+ </file>
+
+ <file name="protractor.js" type="protractor">
+ it('should load and compile correct template', function() {
+ element(by.linkText('Moby: Ch1')).click();
+ var content = element(by.css('[ng-view]')).getText();
+ expect(content).toMatch(/controller\: ChapterCtrl/);
+ expect(content).toMatch(/Book Id\: Moby/);
+ expect(content).toMatch(/Chapter Id\: 1/);
+
+ element(by.partialLinkText('Scarlet')).click();
+
+ content = element(by.css('[ng-view]')).getText();
+ expect(content).toMatch(/controller\: BookCtrl/);
+ expect(content).toMatch(/Book Id\: Scarlet/);
+ });
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngView#$viewContentLoaded
+ * @eventType emit on the current ngView scope
+ * @description
+ * Emitted every time the ngView content is reloaded.
+ */
+ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
+function ngViewFactory($route, $anchorScroll, $animate) {
+ return {
+ restrict: 'ECA',
+ terminal: true,
+ priority: 400,
+ transclude: 'element',
+ link: function(scope, $element, attr, ctrl, $transclude) {
+ var currentScope,
+ currentElement,
+ previousLeaveAnimation,
+ autoScrollExp = attr.autoscroll,
+ onloadExp = attr.onload || '';
+
+ scope.$on('$routeChangeSuccess', update);
+ update();
+
+ function cleanupLastView() {
+ if (previousLeaveAnimation) {
+ $animate.cancel(previousLeaveAnimation);
+ previousLeaveAnimation = null;
+ }
+
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ if (currentElement) {
+ previousLeaveAnimation = $animate.leave(currentElement);
+ previousLeaveAnimation.then(function() {
+ previousLeaveAnimation = null;
+ });
+ currentElement = null;
+ }
+ }
+
+ function update() {
+ var locals = $route.current && $route.current.locals,
+ template = locals && locals.$template;
+
+ if (angular.isDefined(template)) {
+ var newScope = scope.$new();
+ var current = $route.current;
+
+ // Note: This will also link all children of ng-view that were contained in the original
+ // html. If that content contains controllers, ... they could pollute/change the scope.
+ // However, using ng-view on an element with additional content does not make sense...
+ // Note: We can't remove them in the cloneAttchFn of $transclude as that
+ // function is called before linking the content, which would apply child
+ // directives to non existing elements.
+ var clone = $transclude(newScope, function(clone) {
+ $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
+ if (angular.isDefined(autoScrollExp)
+ && (!autoScrollExp || scope.$eval(autoScrollExp))) {
+ $anchorScroll();
+ }
+ });
+ cleanupLastView();
+ });
+
+ currentElement = clone;
+ currentScope = current.scope = newScope;
+ currentScope.$emit('$viewContentLoaded');
+ currentScope.$eval(onloadExp);
+ } else {
+ cleanupLastView();
+ }
+ }
+ }
+ };
+}
+
+// This directive is called during the $transclude call of the first `ngView` directive.
+// It will replace and compile the content of the element with the loaded template.
+// We need this directive so that the element content is already filled when
+// the link function of another directive on the same element as ngView
+// is called.
+ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
+function ngViewFillContentFactory($compile, $controller, $route) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ link: function(scope, $element) {
+ var current = $route.current,
+ locals = current.locals;
+
+ $element.html(locals.$template);
+
+ var link = $compile($element.contents());
+
+ if (current.controller) {
+ locals.$scope = scope;
+ var controller = $controller(current.controller, locals);
+ if (current.controllerAs) {
+ scope[current.controllerAs] = controller;
+ }
+ $element.data('$ngControllerController', controller);
+ $element.children().data('$ngControllerController', controller);
+ }
+
+ link(scope);
+ }
+ };
+}
+
+
+})(window, window.angular);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js
new file mode 100644
index 00000000..3c5fd343
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js
@@ -0,0 +1,15 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(p,c,C){'use strict';function v(r,h,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,f,b,d,y){function z(){k&&(g.cancel(k),k=null);l&&(l.$destroy(),l=null);m&&(k=g.leave(m),k.then(function(){k=null}),m=null)}function x(){var b=r.current&&r.current.locals;if(c.isDefined(b&&b.$template)){var b=a.$new(),d=r.current;m=y(b,function(b){g.enter(b,null,m||f).then(function(){!c.isDefined(t)||t&&!a.$eval(t)||h()});z()});l=d.scope=b;l.$emit("$viewContentLoaded");
+l.$eval(w)}else z()}var l,m,k,t=b.autoscroll,w=b.onload||"";a.$on("$routeChangeSuccess",x);x()}}}function A(c,h,g){return{restrict:"ECA",priority:-400,link:function(a,f){var b=g.current,d=b.locals;f.html(d.$template);var y=c(f.contents());b.controller&&(d.$scope=a,d=h(b.controller,d),b.controllerAs&&(a[b.controllerAs]=d),f.data("$ngControllerController",d),f.children().data("$ngControllerController",d));y(a)}}}p=c.module("ngRoute",["ng"]).provider("$route",function(){function r(a,f){return c.extend(Object.create(a),
+f)}function h(a,c){var b=c.caseInsensitiveMatch,d={originalPath:a,regexp:a},g=d.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,c,b,d){a="?"===d?d:null;d="*"===d?d:null;g.push({name:b,optional:!!a});c=c||"";return""+(a?"":c)+"(?:"+(a?c:"")+(d&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=new RegExp("^"+a+"$",b?"i":"");return d}var g={};this.when=function(a,f){var b=c.copy(f);c.isUndefined(b.reloadOnSearch)&&(b.reloadOnSearch=!0);
+c.isUndefined(b.caseInsensitiveMatch)&&(b.caseInsensitiveMatch=this.caseInsensitiveMatch);g[a]=c.extend(b,a&&h(a,b));if(a){var d="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";g[d]=c.extend({redirectTo:a},h(d,b))}return this};this.caseInsensitiveMatch=!1;this.otherwise=function(a){"string"===typeof a&&(a={redirectTo:a});this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(a,f,b,d,h,p,x){function l(b){var e=s.current;
+(v=(n=k())&&e&&n.$$route===e.$$route&&c.equals(n.pathParams,e.pathParams)&&!n.reloadOnSearch&&!w)||!e&&!n||a.$broadcast("$routeChangeStart",n,e).defaultPrevented&&b&&b.preventDefault()}function m(){var u=s.current,e=n;if(v)u.params=e.params,c.copy(u.params,b),a.$broadcast("$routeUpdate",u);else if(e||u)w=!1,(s.current=e)&&e.redirectTo&&(c.isString(e.redirectTo)?f.path(t(e.redirectTo,e.params)).search(e.params).replace():f.url(e.redirectTo(e.pathParams,f.path(),f.search())).replace()),d.when(e).then(function(){if(e){var a=
+c.extend({},e.resolve),b,f;c.forEach(a,function(b,e){a[e]=c.isString(b)?h.get(b):h.invoke(b,null,null,e)});c.isDefined(b=e.template)?c.isFunction(b)&&(b=b(e.params)):c.isDefined(f=e.templateUrl)&&(c.isFunction(f)&&(f=f(e.params)),c.isDefined(f)&&(e.loadedTemplateUrl=x.valueOf(f),b=p(f)));c.isDefined(b)&&(a.$template=b);return d.all(a)}}).then(function(f){e==s.current&&(e&&(e.locals=f,c.copy(e.params,b)),a.$broadcast("$routeChangeSuccess",e,u))},function(b){e==s.current&&a.$broadcast("$routeChangeError",
+e,u,b)})}function k(){var a,b;c.forEach(g,function(d,g){var q;if(q=!b){var h=f.path();q=d.keys;var l={};if(d.regexp)if(h=d.regexp.exec(h)){for(var k=1,m=h.length;k<m;++k){var n=q[k-1],p=h[k];n&&p&&(l[n.name]=p)}q=l}else q=null;else q=null;q=a=q}q&&(b=r(d,{params:c.extend({},f.search(),a),pathParams:a}),b.$$route=d)});return b||g[null]&&r(g[null],{params:{},pathParams:{}})}function t(a,b){var d=[];c.forEach((a||"").split(":"),function(a,c){if(0===c)d.push(a);else{var f=a.match(/(\w+)(?:[?*])?(.*)/),
+g=f[1];d.push(b[g]);d.push(f[2]||"");delete b[g]}});return d.join("")}var w=!1,n,v,s={routes:g,reload:function(){w=!0;a.$evalAsync(function(){l();m()})},updateParams:function(a){if(this.current&&this.current.$$route)a=c.extend({},this.current.params,a),f.path(t(this.current.$$route.originalPath,a)),f.search(a);else throw B("norout");}};a.$on("$locationChangeStart",l);a.$on("$locationChangeSuccess",m);return s}]});var B=c.$$minErr("ngRoute");p.provider("$routeParams",function(){this.$get=function(){return{}}});
+p.directive("ngView",v);p.directive("ngView",A);v.$inject=["$route","$anchorScroll","$animate"];A.$inject=["$compile","$controller","$route"]})(window,window.angular);
+//# sourceMappingURL=angular-route.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js.map
new file mode 100644
index 00000000..c0b2f5ca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-route.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-route.min.js",
+"lineCount":14,
+"mappings":"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",
+"sources":["angular-route.js"],
+"names":["window","angular","undefined","ngViewFactory","$route","$anchorScroll","$animate","restrict","terminal","priority","transclude","link","scope","$element","attr","ctrl","$transclude","cleanupLastView","previousLeaveAnimation","cancel","currentScope","$destroy","currentElement","leave","then","update","locals","current","isDefined","$template","newScope","$new","clone","enter","onNgViewEnter","autoScrollExp","$eval","$emit","onloadExp","autoscroll","onload","$on","ngViewFillContentFactory","$compile","$controller","html","contents","controller","$scope","controllerAs","data","children","ngRouteModule","module","provider","$RouteProvider","inherit","parent","extra","extend","Object","create","pathRegExp","path","opts","insensitive","caseInsensitiveMatch","ret","originalPath","regexp","keys","replace","_","slash","key","option","optional","star","push","name","RegExp","routes","when","this.when","route","routeCopy","copy","isUndefined","reloadOnSearch","redirectPath","length","substr","redirectTo","otherwise","this.otherwise","params","$get","$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce","prepareRoute","$locationEvent","lastRoute","preparedRouteIsUpdateOnly","preparedRoute","parseRoute","$$route","equals","pathParams","forceReload","$broadcast","defaultPrevented","preventDefault","commitRoute","nextRoute","isString","interpolate","search","url","resolve","template","templateUrl","forEach","value","get","invoke","isFunction","loadedTemplateUrl","valueOf","all","error","match","m","exec","on","i","len","val","string","result","split","segment","segmentMatch","join","reload","$evalAsync","updateParams","newParams","$routeMinErr","$$minErr","$RouteParamsProvider","this.$get","directive","$inject"]
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.js
new file mode 100644
index 00000000..5e5c1f20
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.js
@@ -0,0 +1,683 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $sanitizeMinErr = angular.$$minErr('$sanitize');
+
+/**
+ * @ngdoc module
+ * @name ngSanitize
+ * @description
+ *
+ * # ngSanitize
+ *
+ * The `ngSanitize` module provides functionality to sanitize HTML.
+ *
+ *
+ * <div doc-module-components="ngSanitize"></div>
+ *
+ * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
+ */
+
+/*
+ * HTML Parser By Misko Hevery (misko@hevery.com)
+ * based on: HTML Parser By John Resig (ejohn.org)
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * // Use like so:
+ * htmlParser(htmlString, {
+ * start: function(tag, attrs, unary) {},
+ * end: function(tag) {},
+ * chars: function(text) {},
+ * comment: function(text) {}
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $sanitize
+ * @kind function
+ *
+ * @description
+ * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
+ * then serialized back to properly escaped html string. This means that no unsafe input can make
+ * it into the returned string, however, since our parser is more strict than a typical browser
+ * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
+ * browser, won't make it through the sanitizer. The input may also contain SVG markup.
+ * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
+ * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
+ *
+ * @param {string} html HTML input.
+ * @returns {string} Sanitized HTML.
+ *
+ * @example
+ <example module="sanitizeExample" deps="angular-sanitize.js">
+ <file name="index.html">
+ <script>
+ angular.module('sanitizeExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
+ $scope.snippet =
+ '<p style="color:blue">an html\n' +
+ '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
+ 'snippet</p>';
+ $scope.deliberatelyTrustDangerousSnippet = function() {
+ return $sce.trustAsHtml($scope.snippet);
+ };
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+ <table>
+ <tr>
+ <td>Directive</td>
+ <td>How</td>
+ <td>Source</td>
+ <td>Rendered</td>
+ </tr>
+ <tr id="bind-html-with-sanitize">
+ <td>ng-bind-html</td>
+ <td>Automatically uses $sanitize</td>
+ <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+ <td><div ng-bind-html="snippet"></div></td>
+ </tr>
+ <tr id="bind-html-with-trust">
+ <td>ng-bind-html</td>
+ <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
+ <td>
+ <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
+&lt;/div&gt;</pre>
+ </td>
+ <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
+ </tr>
+ <tr id="bind-default">
+ <td>ng-bind</td>
+ <td>Automatically escapes</td>
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+ <td><div ng-bind="snippet"></div></td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should sanitize the html snippet by default', function() {
+ expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
+ toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
+ });
+
+ it('should inline raw snippet if bound to a trusted value', function() {
+ expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
+ toBe("<p style=\"color:blue\">an html\n" +
+ "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
+ "snippet</p>");
+ });
+
+ it('should escape snippet without any filter', function() {
+ expect(element(by.css('#bind-default div')).getInnerHtml()).
+ toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
+ "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
+ "snippet&lt;/p&gt;");
+ });
+
+ it('should update', function() {
+ element(by.model('snippet')).clear();
+ element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
+ expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
+ toBe('new <b>text</b>');
+ expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
+ 'new <b onclick="alert(1)">text</b>');
+ expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
+ "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
+ });
+ </file>
+ </example>
+ */
+function $SanitizeProvider() {
+ this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
+ return function(html) {
+ var buf = [];
+ htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
+ return !/^unsafe/.test($$sanitizeUri(uri, isImage));
+ }));
+ return buf.join('');
+ };
+ }];
+}
+
+function sanitizeText(chars) {
+ var buf = [];
+ var writer = htmlSanitizeWriter(buf, angular.noop);
+ writer.chars(chars);
+ return buf.join('');
+}
+
+
+// Regular Expressions for parsing tags and attributes
+var START_TAG_REGEXP =
+ /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
+ END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
+ ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
+ BEGIN_TAG_REGEXP = /^</,
+ BEGING_END_TAGE_REGEXP = /^<\//,
+ COMMENT_REGEXP = /<!--(.*?)-->/g,
+ DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
+ CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
+ SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ // Match everything outside of normal chars and " (quote character)
+ NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
+
+
+// Good source of info about elements and attributes
+// http://dev.w3.org/html5/spec/Overview.html#semantics
+// http://simon.html5.org/html-elements
+
+// Safe Void Elements - HTML5
+// http://dev.w3.org/html5/spec/Overview.html#void-elements
+var voidElements = makeMap("area,br,col,hr,img,wbr");
+
+// Elements that you can, intentionally, leave open (and which close themselves)
+// http://dev.w3.org/html5/spec/Overview.html#optional-tags
+var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
+ optionalEndTagInlineElements = makeMap("rp,rt"),
+ optionalEndTagElements = angular.extend({},
+ optionalEndTagInlineElements,
+ optionalEndTagBlockElements);
+
+// Safe Block Elements - HTML5
+var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
+ "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
+ "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
+
+// Inline Elements - HTML5
+var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
+ "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
+ "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
+
+// SVG Elements
+// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
+// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
+// They can potentially allow for arbitrary javascript to be executed. See #11290
+var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
+ "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
+ "radialGradient,rect,stop,svg,switch,text,title,tspan,use");
+
+// Special Elements (can contain anything)
+var specialElements = makeMap("script,style");
+
+var validElements = angular.extend({},
+ voidElements,
+ blockElements,
+ inlineElements,
+ optionalEndTagElements,
+ svgElements);
+
+//Attributes that have href and hence need to be sanitized
+var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
+
+var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
+ 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
+ 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
+ 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
+ 'valign,value,vspace,width');
+
+// SVG attributes (without "id" and "name" attributes)
+// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
+var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
+ 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
+ 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
+ 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
+ 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
+ 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
+ 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
+ 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
+ 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
+ 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
+ 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
+ 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
+ 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
+ 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
+ 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
+
+var validAttrs = angular.extend({},
+ uriAttrs,
+ svgAttrs,
+ htmlAttrs);
+
+function makeMap(str, lowercaseKeys) {
+ var obj = {}, items = str.split(','), i;
+ for (i = 0; i < items.length; i++) {
+ obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true;
+ }
+ return obj;
+}
+
+
+/**
+ * @example
+ * htmlParser(htmlString, {
+ * start: function(tag, attrs, unary) {},
+ * end: function(tag) {},
+ * chars: function(text) {},
+ * comment: function(text) {}
+ * });
+ *
+ * @param {string} html string
+ * @param {object} handler
+ */
+function htmlParser(html, handler) {
+ if (typeof html !== 'string') {
+ if (html === null || typeof html === 'undefined') {
+ html = '';
+ } else {
+ html = '' + html;
+ }
+ }
+ var index, chars, match, stack = [], last = html, text;
+ stack.last = function() { return stack[stack.length - 1]; };
+
+ while (html) {
+ text = '';
+ chars = true;
+
+ // Make sure we're not in a script or style element
+ if (!stack.last() || !specialElements[stack.last()]) {
+
+ // Comment
+ if (html.indexOf("<!--") === 0) {
+ // comments containing -- are not allowed unless they terminate the comment
+ index = html.indexOf("--", 4);
+
+ if (index >= 0 && html.lastIndexOf("-->", index) === index) {
+ if (handler.comment) handler.comment(html.substring(4, index));
+ html = html.substring(index + 3);
+ chars = false;
+ }
+ // DOCTYPE
+ } else if (DOCTYPE_REGEXP.test(html)) {
+ match = html.match(DOCTYPE_REGEXP);
+
+ if (match) {
+ html = html.replace(match[0], '');
+ chars = false;
+ }
+ // end tag
+ } else if (BEGING_END_TAGE_REGEXP.test(html)) {
+ match = html.match(END_TAG_REGEXP);
+
+ if (match) {
+ html = html.substring(match[0].length);
+ match[0].replace(END_TAG_REGEXP, parseEndTag);
+ chars = false;
+ }
+
+ // start tag
+ } else if (BEGIN_TAG_REGEXP.test(html)) {
+ match = html.match(START_TAG_REGEXP);
+
+ if (match) {
+ // We only have a valid start-tag if there is a '>'.
+ if (match[4]) {
+ html = html.substring(match[0].length);
+ match[0].replace(START_TAG_REGEXP, parseStartTag);
+ }
+ chars = false;
+ } else {
+ // no ending tag found --- this piece should be encoded as an entity.
+ text += '<';
+ html = html.substring(1);
+ }
+ }
+
+ if (chars) {
+ index = html.indexOf("<");
+
+ text += index < 0 ? html : html.substring(0, index);
+ html = index < 0 ? "" : html.substring(index);
+
+ if (handler.chars) handler.chars(decodeEntities(text));
+ }
+
+ } else {
+ // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w].
+ html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
+ function(all, text) {
+ text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
+
+ if (handler.chars) handler.chars(decodeEntities(text));
+
+ return "";
+ });
+
+ parseEndTag("", stack.last());
+ }
+
+ if (html == last) {
+ throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
+ "of html: {0}", html);
+ }
+ last = html;
+ }
+
+ // Clean up any remaining tags
+ parseEndTag();
+
+ function parseStartTag(tag, tagName, rest, unary) {
+ tagName = angular.lowercase(tagName);
+ if (blockElements[tagName]) {
+ while (stack.last() && inlineElements[stack.last()]) {
+ parseEndTag("", stack.last());
+ }
+ }
+
+ if (optionalEndTagElements[tagName] && stack.last() == tagName) {
+ parseEndTag("", tagName);
+ }
+
+ unary = voidElements[tagName] || !!unary;
+
+ if (!unary) {
+ stack.push(tagName);
+ }
+
+ var attrs = {};
+
+ rest.replace(ATTR_REGEXP,
+ function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
+ var value = doubleQuotedValue
+ || singleQuotedValue
+ || unquotedValue
+ || '';
+
+ attrs[name] = decodeEntities(value);
+ });
+ if (handler.start) handler.start(tagName, attrs, unary);
+ }
+
+ function parseEndTag(tag, tagName) {
+ var pos = 0, i;
+ tagName = angular.lowercase(tagName);
+ if (tagName) {
+ // Find the closest opened tag of the same type
+ for (pos = stack.length - 1; pos >= 0; pos--) {
+ if (stack[pos] == tagName) break;
+ }
+ }
+
+ if (pos >= 0) {
+ // Close all the open elements, up the stack
+ for (i = stack.length - 1; i >= pos; i--)
+ if (handler.end) handler.end(stack[i]);
+
+ // Remove the open elements from the stack
+ stack.length = pos;
+ }
+ }
+}
+
+var hiddenPre=document.createElement("pre");
+/**
+ * decodes all entities into regular string
+ * @param value
+ * @returns {string} A string with decoded entities.
+ */
+function decodeEntities(value) {
+ if (!value) { return ''; }
+
+ hiddenPre.innerHTML = value.replace(/</g,"&lt;");
+ // innerText depends on styling as it doesn't display hidden elements.
+ // Therefore, it's better to use textContent not to cause unnecessary reflows.
+ return hiddenPre.textContent;
+}
+
+/**
+ * Escapes all potentially dangerous characters, so that the
+ * resulting string can be safely inserted into attribute or
+ * element text.
+ * @param value
+ * @returns {string} escaped text
+ */
+function encodeEntities(value) {
+ return value.
+ replace(/&/g, '&amp;').
+ replace(SURROGATE_PAIR_REGEXP, function(value) {
+ var hi = value.charCodeAt(0);
+ var low = value.charCodeAt(1);
+ return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
+ }).
+ replace(NON_ALPHANUMERIC_REGEXP, function(value) {
+ return '&#' + value.charCodeAt(0) + ';';
+ }).
+ replace(/</g, '&lt;').
+ replace(/>/g, '&gt;');
+}
+
+/**
+ * create an HTML/XML writer which writes to buffer
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
+ * @returns {object} in the form of {
+ * start: function(tag, attrs, unary) {},
+ * end: function(tag) {},
+ * chars: function(text) {},
+ * comment: function(text) {}
+ * }
+ */
+function htmlSanitizeWriter(buf, uriValidator) {
+ var ignore = false;
+ var out = angular.bind(buf, buf.push);
+ return {
+ start: function(tag, attrs, unary) {
+ tag = angular.lowercase(tag);
+ if (!ignore && specialElements[tag]) {
+ ignore = tag;
+ }
+ if (!ignore && validElements[tag] === true) {
+ out('<');
+ out(tag);
+ angular.forEach(attrs, function(value, key) {
+ var lkey=angular.lowercase(key);
+ var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
+ if (validAttrs[lkey] === true &&
+ (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
+ out(' ');
+ out(key);
+ out('="');
+ out(encodeEntities(value));
+ out('"');
+ }
+ });
+ out(unary ? '/>' : '>');
+ }
+ },
+ end: function(tag) {
+ tag = angular.lowercase(tag);
+ if (!ignore && validElements[tag] === true) {
+ out('</');
+ out(tag);
+ out('>');
+ }
+ if (tag == ignore) {
+ ignore = false;
+ }
+ },
+ chars: function(chars) {
+ if (!ignore) {
+ out(encodeEntities(chars));
+ }
+ }
+ };
+}
+
+
+// define ngSanitize module and register $sanitize service
+angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
+
+/* global sanitizeText: false */
+
+/**
+ * @ngdoc filter
+ * @name linky
+ * @kind function
+ *
+ * @description
+ * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
+ * plain email address links.
+ *
+ * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
+ *
+ * @param {string} text Input text.
+ * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
+ * @returns {string} Html-linkified text.
+ *
+ * @usage
+ <span ng-bind-html="linky_expression | linky"></span>
+ *
+ * @example
+ <example module="linkyExample" deps="angular-sanitize.js">
+ <file name="index.html">
+ <script>
+ angular.module('linkyExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.snippet =
+ 'Pretty text with some links:\n'+
+ 'http://angularjs.org/,\n'+
+ 'mailto:us@somewhere.org,\n'+
+ 'another@somewhere.org,\n'+
+ 'and one more: ftp://127.0.0.1/.';
+ $scope.snippetWithTarget = 'http://angularjs.org/';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+ <table>
+ <tr>
+ <td>Filter</td>
+ <td>Source</td>
+ <td>Rendered</td>
+ </tr>
+ <tr id="linky-filter">
+ <td>linky filter</td>
+ <td>
+ <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
+ </td>
+ <td>
+ <div ng-bind-html="snippet | linky"></div>
+ </td>
+ </tr>
+ <tr id="linky-target">
+ <td>linky target</td>
+ <td>
+ <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
+ </td>
+ <td>
+ <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
+ </td>
+ </tr>
+ <tr id="escaped-html">
+ <td>no filter</td>
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
+ <td><div ng-bind="snippet"></div></td>
+ </tr>
+ </table>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should linkify the snippet with urls', function() {
+ expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
+ toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
+ 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
+ expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
+ });
+
+ it('should not linkify snippet without the linky filter', function() {
+ expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
+ toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
+ 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
+ expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
+ });
+
+ it('should update', function() {
+ element(by.model('snippet')).clear();
+ element(by.model('snippet')).sendKeys('new http://link.');
+ expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
+ toBe('new http://link.');
+ expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
+ expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
+ .toBe('new http://link.');
+ });
+
+ it('should work with the target property', function() {
+ expect(element(by.id('linky-target')).
+ element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
+ toBe('http://angularjs.org/');
+ expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
+ });
+ </file>
+ </example>
+ */
+angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
+ var LINKY_URL_REGEXP =
+ /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
+ MAILTO_REGEXP = /^mailto:/i;
+
+ return function(text, target) {
+ if (!text) return text;
+ var match;
+ var raw = text;
+ var html = [];
+ var url;
+ var i;
+ while ((match = raw.match(LINKY_URL_REGEXP))) {
+ // We can not end in these as they are sometimes found at the end of the sentence
+ url = match[0];
+ // if we did not match ftp/http/www/mailto then assume mailto
+ if (!match[2] && !match[4]) {
+ url = (match[3] ? 'http://' : 'mailto:') + url;
+ }
+ i = match.index;
+ addText(raw.substr(0, i));
+ addLink(url, match[0].replace(MAILTO_REGEXP, ''));
+ raw = raw.substring(i + match[0].length);
+ }
+ addText(raw);
+ return $sanitize(html.join(''));
+
+ function addText(text) {
+ if (!text) {
+ return;
+ }
+ html.push(sanitizeText(text));
+ }
+
+ function addLink(url, text) {
+ html.push('<a ');
+ if (angular.isDefined(target)) {
+ html.push('target="',
+ target,
+ '" ');
+ }
+ html.push('href="',
+ url.replace(/"/g, '&quot;'),
+ '">');
+ addText(text);
+ html.push('</a>');
+ }
+ };
+}]);
+
+
+})(window, window.angular);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js
new file mode 100644
index 00000000..a1e654ce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js
@@ -0,0 +1,16 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(n,h,p){'use strict';function E(a){var f=[];r(f,h.noop).chars(a);return f.join("")}function g(a,f){var d={},c=a.split(","),b;for(b=0;b<c.length;b++)d[f?h.lowercase(c[b]):c[b]]=!0;return d}function F(a,f){function d(a,b,d,l){b=h.lowercase(b);if(s[b])for(;e.last()&&t[e.last()];)c("",e.last());u[b]&&e.last()==b&&c("",b);(l=v[b]||!!l)||e.push(b);var m={};d.replace(G,function(b,a,f,c,d){m[a]=q(f||c||d||"")});f.start&&f.start(b,m,l)}function c(b,a){var c=0,d;if(a=h.lowercase(a))for(c=e.length-
+1;0<=c&&e[c]!=a;c--);if(0<=c){for(d=e.length-1;d>=c;d--)f.end&&f.end(e[d]);e.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,e=[],m=a,l;for(e.last=function(){return e[e.length-1]};a;){l="";k=!0;if(e.last()&&w[e.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");f.chars&&f.chars(q(b));return""}),c("",e.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",
+b)===b&&(f.comment&&f.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(x.test(a)){if(b=a.match(x))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(y))a=a.substring(b[0].length),b[0].replace(y,c),k=!1}else K.test(a)&&((b=a.match(z))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(z,d)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),f.chars&&f.chars(q(l)))}if(a==m)throw L("badparse",a);m=a}c()}function q(a){if(!a)return"";A.innerHTML=
+a.replace(/</g,"&lt;");return A.textContent}function B(a){return a.replace(/&/g,"&amp;").replace(M,function(a){var d=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(d-55296)+(a-56320)+65536)+";"}).replace(N,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function r(a,f){var d=!1,c=h.bind(a,a.push);return{start:function(a,k,e){a=h.lowercase(a);!d&&w[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(k,function(d,e){var k=h.lowercase(e),g="img"===a&&"src"===k||
+"background"===k;!0!==O[k]||!0===D[k]&&!f(d,g)||(c(" "),c(e),c('="'),c(B(d)),c('"'))}),c(e?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(B(a))}}}var L=h.$$minErr("$sanitize"),z=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,y=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,x=/<!DOCTYPE([^>]*?)>/i,
+I=/<!\[CDATA\[(.*?)]]\x3e/g,M=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,N=/([^\#-~| |!])/g,v=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var u=h.extend({},p,n),s=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),t=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
+n=g("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan,use");var w=g("script,style"),C=h.extend({},v,s,t,u,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width");
+p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan",
+!0);var O=h.extend({},D,p,n),A=document.createElement("pre");h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(f){var d=[];F(f,r(d,function(c,b){return!/^unsafe/.test(a(c,b))}));return d.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var f=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,d=/^mailto:/i;return function(c,b){function k(a){a&&g.push(E(a))}function e(a,
+c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"&quot;"),'">');k(c);g.push("</a>")}if(!c)return c;for(var m,l=c,g=[],n,p;m=l.match(f);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),e(n,m[0].replace(d,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular);
+//# sourceMappingURL=angular-sanitize.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js.map
new file mode 100644
index 00000000..2f360f4d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-sanitize.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-sanitize.min.js",
+"lineCount":15,
+"mappings":"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",
+"sources":["angular-sanitize.js"],
+"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","lowercaseKeys","obj","items","split","i","length","lowercase","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","text","stack.last","specialElements","RegExp","all","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","hiddenPre","innerHTML","textContent","encodeEntities","SURROGATE_PAIR_REGEXP","hi","charCodeAt","low","NON_ALPHANUMERIC_REGEXP","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","svgElements","htmlAttrs","svgAttrs","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"]
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-scenario.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-scenario.js
index 20af805f..78dd37d0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-scenario.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-scenario.js
@@ -9190,8 +9190,8 @@ return jQuery;
}));
/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document){
@@ -9249,7 +9249,7 @@ function minErr(module, ErrorConstructor) {
return match;
});
- message += '\nhttp://errors.angularjs.org/1.5.0/' +
+ message += '\nhttp://errors.angularjs.org/1.4.8/' +
(module ? module + '/' : '') + code;
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
@@ -9380,9 +9380,29 @@ var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
var hasOwnProperty = Object.prototype.hasOwnProperty;
-var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
@@ -9402,7 +9422,7 @@ var manualUppercase = function(s) {
// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
-// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
+// with correct but slower alternatives.
if ('i' !== 'I'.toLowerCase()) {
lowercase = manualLowercase;
uppercase = manualUppercase;
@@ -9445,7 +9465,7 @@ function isArrayLike(obj) {
// arrays, strings and jQuery/jqLite objects are array like
// * jqLite is either the jQuery or jqLite constructor function
- // * we have to check the existence of jqLite first as this method is called
+ // * we have to check the existance of jqLite first as this method is called
// via the forEach method when constructing the jqLite object in the first place
if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
@@ -9456,8 +9476,7 @@ function isArrayLike(obj) {
// NodeList objects (with `item` method) and
// other objects with suitable length characteristics are array-like
return isNumber(length) &&
- (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function');
-
+ (length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
}
/**
@@ -9554,7 +9573,7 @@ function forEachSorted(obj, iterator, context) {
* @returns {function(*, string)}
*/
function reverseParams(iteratorFn) {
- return function(value, key) {iteratorFn(key, value);};
+ return function(value, key) { iteratorFn(key, value); };
}
/**
@@ -9925,10 +9944,6 @@ function isTypedArray(value) {
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
}
-function isArrayBuffer(obj) {
- return toString.call(obj) === '[object ArrayBuffer]';
-}
-
var trim = function(value) {
return isString(value) ? value.trim() : value;
@@ -9966,7 +9981,7 @@ function isElement(node) {
* @returns {object} in the form of {key1:true, key2:true, ...}
*/
function makeMap(str) {
- var obj = {}, items = str.split(','), i;
+ var obj = {}, items = str.split(","), i;
for (i = 0; i < items.length; i++) {
obj[items[i]] = true;
}
@@ -10053,7 +10068,7 @@ function copy(source, destination) {
var stackDest = [];
if (destination) {
- if (isTypedArray(destination) || isArrayBuffer(destination)) {
+ if (isTypedArray(destination)) {
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
}
if (source === destination) {
@@ -10127,10 +10142,22 @@ function copy(source, destination) {
}
var needsRecurse = false;
- var destination = copyType(source);
+ var destination;
- if (destination === undefined) {
- destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
+ if (isArray(source)) {
+ destination = [];
+ needsRecurse = true;
+ } else if (isTypedArray(source)) {
+ destination = new source.constructor(source);
+ } else if (isDate(source)) {
+ destination = new Date(source.getTime());
+ } else if (isRegExp(source)) {
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ destination.lastIndex = source.lastIndex;
+ } else if (isFunction(source.cloneNode)) {
+ destination = source.cloneNode(true);
+ } else {
+ destination = Object.create(getPrototypeOf(source));
needsRecurse = true;
}
@@ -10141,45 +10168,6 @@ function copy(source, destination) {
? copyRecurse(source, destination)
: destination;
}
-
- function copyType(source) {
- switch (toString.call(source)) {
- case '[object Int8Array]':
- case '[object Int16Array]':
- case '[object Int32Array]':
- case '[object Float32Array]':
- case '[object Float64Array]':
- case '[object Uint8Array]':
- case '[object Uint8ClampedArray]':
- case '[object Uint16Array]':
- case '[object Uint32Array]':
- return new source.constructor(copyElement(source.buffer));
-
- case '[object ArrayBuffer]':
- //Support: IE10
- if (!source.slice) {
- var copied = new ArrayBuffer(source.byteLength);
- new Uint8Array(copied).set(new Uint8Array(source));
- return copied;
- }
- return source.slice(0);
-
- case '[object Boolean]':
- case '[object Number]':
- case '[object String]':
- case '[object Date]':
- return new source.constructor(source.valueOf());
-
- case '[object RegExp]':
- var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
- re.lastIndex = source.lastIndex;
- return re;
- }
-
- if (isFunction(source.cloneNode)) {
- return source.cloneNode(true);
- }
- }
}
/**
@@ -10242,37 +10230,38 @@ function equals(o1, o2) {
if (o1 === null || o2 === null) return false;
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2 && t1 == 'object') {
- if (isArray(o1)) {
- if (!isArray(o2)) return false;
- if ((length = o1.length) == o2.length) {
- for (key = 0; key < length; key++) {
+ if (t1 == t2) {
+ if (t1 == 'object') {
+ if (isArray(o1)) {
+ if (!isArray(o2)) return false;
+ if ((length = o1.length) == o2.length) {
+ for (key = 0; key < length; key++) {
+ if (!equals(o1[key], o2[key])) return false;
+ }
+ return true;
+ }
+ } else if (isDate(o1)) {
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
+ } else if (isRegExp(o1)) {
+ return isRegExp(o2) ? o1.toString() == o2.toString() : false;
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
+ keySet = createMap();
+ for (key in o1) {
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
if (!equals(o1[key], o2[key])) return false;
+ keySet[key] = true;
+ }
+ for (key in o2) {
+ if (!(key in keySet) &&
+ key.charAt(0) !== '$' &&
+ isDefined(o2[key]) &&
+ !isFunction(o2[key])) return false;
}
return true;
}
- } else if (isDate(o1)) {
- if (!isDate(o2)) return false;
- return equals(o1.getTime(), o2.getTime());
- } else if (isRegExp(o1)) {
- if (!isRegExp(o2)) return false;
- return o1.toString() == o2.toString();
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
- isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
- keySet = createMap();
- for (key in o1) {
- if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
- if (!equals(o1[key], o2[key])) return false;
- keySet[key] = true;
- }
- for (key in o2) {
- if (!(key in keySet) &&
- key.charAt(0) !== '$' &&
- isDefined(o2[key]) &&
- !isFunction(o2[key])) return false;
- }
- return true;
}
}
return false;
@@ -10449,7 +10438,7 @@ function toJsonReplacer(key, value) {
* @returns {string|undefined} JSON-ified string representing `obj`.
*/
function toJson(obj, pretty) {
- if (isUndefined(obj)) return undefined;
+ if (typeof obj === 'undefined') return undefined;
if (!isNumber(pretty)) {
pretty = pretty ? 2 : null;
}
@@ -10476,10 +10465,7 @@ function fromJson(json) {
}
-var ALL_COLONS = /:/g;
function timezoneToOffset(timezone, fallback) {
- // IE/Edge do not "understand" colon (`:`) in timezone
- timezone = timezone.replace(ALL_COLONS, '');
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
@@ -10494,9 +10480,8 @@ function addDateMinutes(date, minutes) {
function convertTimezoneToLocal(date, timezone, reverse) {
reverse = reverse ? -1 : 1;
- var dateTimezoneOffset = date.getTimezoneOffset();
- var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
- return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
+ var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
+ return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
}
@@ -10515,7 +10500,7 @@ function startingTag(element) {
return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
elemHtml.
match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
} catch (e) {
return lowercase(elemHtml);
}
@@ -10958,6 +10943,7 @@ function snake_case(name, separator) {
}
var bindJQueryFired = false;
+var skipDestroyOnNextJQueryCleanData;
function bindJQuery() {
var originalCleanData;
@@ -10991,11 +10977,15 @@ function bindJQuery() {
originalCleanData = jQuery.cleanData;
jQuery.cleanData = function(elems) {
var events;
- for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- events = jQuery._data(elem, "events");
- if (events && events.$destroy) {
- jQuery(elem).triggerHandler('$destroy');
+ if (!skipDestroyOnNextJQueryCleanData) {
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
+ }
}
+ } else {
+ skipDestroyOnNextJQueryCleanData = false;
}
originalCleanData(elems);
};
@@ -11189,7 +11179,7 @@ function setupModuleLoader(window) {
* unspecified then the module is being retrieved for further configuration.
* @param {Function=} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
- * @returns {angular.Module} new module with the {@link angular.Module} api.
+ * @returns {module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
@@ -11397,19 +11387,6 @@ function setupModuleLoader(window) {
/**
* @ngdoc method
- * @name angular.Module#component
- * @module ng
- * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
- * @param {Object} options Component definition object (a simplified
- * {@link ng.$compile#directive-definition-object directive definition object})
- *
- * @description
- * See {@link ng.$compileProvider#component $compileProvider.component()}.
- */
- component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
-
- /**
- * @ngdoc method
* @name angular.Module#config
* @module ng
* @param {Function} configFn Execute this function on module load. Useful for service
@@ -11559,14 +11536,11 @@ function toDebugString(obj) {
$AnchorScrollProvider,
$AnimateProvider,
$CoreAnimateCssProvider,
- $$CoreAnimateJsProvider,
$$CoreAnimateQueueProvider,
- $$AnimateRunnerFactoryProvider,
- $$AnimateAsyncRunFactoryProvider,
+ $$CoreAnimateRunnerProvider,
$BrowserProvider,
$CacheFactoryProvider,
$ControllerProvider,
- $DateProvider,
$DocumentProvider,
$ExceptionHandlerProvider,
$FilterProvider,
@@ -11616,11 +11590,11 @@ function toDebugString(obj) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.5.0', // all of these placeholder strings will be replaced by grunt's
+ full: '1.4.8', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
- minor: 5,
- dot: 0,
- codeName: 'ennoblement-facilitation'
+ minor: 4,
+ dot: 8,
+ codeName: 'ice-manipulation'
};
@@ -11722,10 +11696,8 @@ function publishExternalAPI(angular) {
$anchorScroll: $AnchorScrollProvider,
$animate: $AnimateProvider,
$animateCss: $CoreAnimateCssProvider,
- $$animateJs: $$CoreAnimateJsProvider,
$$animateQueue: $$CoreAnimateQueueProvider,
- $$AnimateRunner: $$AnimateRunnerFactoryProvider,
- $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
+ $$AnimateRunner: $$CoreAnimateRunnerProvider,
$browser: $BrowserProvider,
$cacheFactory: $CacheFactoryProvider,
$controller: $ControllerProvider,
@@ -11796,22 +11768,16 @@ function publishExternalAPI(angular) {
*
* If jQuery is available, `angular.element` is an alias for the
* [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
- * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
- *
- * jqLite is a tiny, API-compatible subset of jQuery that allows
- * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most
- * commonly needed functionality with the goal of having a very small footprint.
+ * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
*
- * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the
- * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a
- * specific version of jQuery if multiple versions exist on the page.
+ * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
+ * commonly needed functionality with the goal of having a very small footprint.</div>
*
- * <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or
- * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
*
- * <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
- * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
- * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
+ * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
+ * jqLite; they are never raw DOM references.</div>
*
* ## Angular's jqLite
* jqLite provides only the following jQuery methods:
@@ -11824,8 +11790,7 @@ function publishExternalAPI(angular) {
* - [`children()`](http://api.jquery.com/children/) - Does not support selectors
* - [`clone()`](http://api.jquery.com/clone/)
* - [`contents()`](http://api.jquery.com/contents/)
- * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
- * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
* - [`data()`](http://api.jquery.com/data/)
* - [`detach()`](http://api.jquery.com/detach/)
* - [`empty()`](http://api.jquery.com/empty/)
@@ -11959,12 +11924,6 @@ function jqLiteHasData(node) {
return false;
}
-function jqLiteCleanData(nodes) {
- for (var i = 0, ii = nodes.length; i < ii; i++) {
- jqLiteRemoveData(nodes[i]);
- }
-}
-
function jqLiteBuildFragment(html, context) {
var tmp, tag, wrap,
fragment = context.createDocumentFragment(),
@@ -12017,16 +11976,6 @@ function jqLiteParseHTML(html, context) {
return [];
}
-function jqLiteWrapNode(node, wrapper) {
- var parent = node.parentNode;
-
- if (parent) {
- parent.replaceChild(wrapper, node);
- }
-
- wrapper.appendChild(node);
-}
-
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
var jqLiteContains = Node.prototype.contains || function(arg) {
@@ -12277,7 +12226,7 @@ function jqLiteRemove(element, keepData) {
function jqLiteDocumentLoaded(action, win) {
win = win || window;
if (win.document.readyState === 'complete') {
- // Force the action to be run async for consistent behavior
+ // Force the action to be run async for consistent behaviour
// from the action's point of view
// i.e. it will definitely not be in a $apply
win.setTimeout(action);
@@ -12363,8 +12312,7 @@ function getAliasedAttrName(name) {
forEach({
data: jqLiteData,
removeData: jqLiteRemoveData,
- hasData: jqLiteHasData,
- cleanData: jqLiteCleanData
+ hasData: jqLiteHasData
}, function(fn, name) {
JQLite[name] = fn;
});
@@ -12719,7 +12667,12 @@ forEach({
},
wrap: function(element, wrapNode) {
- jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);
+ wrapNode = jqLite(wrapNode).eq(0).clone()[0];
+ var parent = element.parentNode;
+ if (parent) {
+ parent.replaceChild(wrapNode, element);
+ }
+ wrapNode.appendChild(element);
},
remove: jqLiteRemove,
@@ -12997,23 +12950,17 @@ var $$HashMapProvider = [function() {
* Implicit module which gets automatically added to each {@link auto.$injector $injector}.
*/
-var ARROW_ARG = /^([^\(]+?)=>/;
var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
-function extractArgs(fn) {
- var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
- args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
- return args;
-}
-
function anonFn(fn) {
// For anonymous functions, showing at the very least the function signature can help in
// debugging.
- var args = extractArgs(fn);
+ var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
+ args = fnText.match(FN_ARGS);
if (args) {
return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
}
@@ -13022,6 +12969,7 @@ function anonFn(fn) {
function annotate(fn, strictDi, name) {
var $inject,
+ fnText,
argDecl,
last;
@@ -13036,7 +12984,8 @@ function annotate(fn, strictDi, name) {
throw $injectorMinErr('strictdi',
'{0} is not using explicit annotation and cannot be invoked in strict mode', name);
}
- argDecl = extractArgs(fn);
+ fnText = fn.toString().replace(STRIP_COMMENTS, '');
+ argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
arg.replace(FN_ARG, function(all, underscore, name) {
$inject.push(name);
@@ -13426,20 +13375,8 @@ function annotate(fn, strictDi, name) {
*
* Register a **service constructor**, which will be invoked with `new` to create the service
* instance.
- * This is short for registering a service where its provider's `$get` property is a factory
- * function that returns an instance instantiated by the injector from the service constructor
- * function.
- *
- * Internally it looks a bit like this:
- *
- * ```
- * {
- * $get: function() {
- * return $injector.instantiate(constructor);
- * }
- * }
- * ```
- *
+ * This is short for registering a service where its provider's `$get` property is the service
+ * constructor function that will be used to instantiate the service instance.
*
* You should use {@link auto.$provide#service $provide.service(class)} if you define your service
* as a type/class.
@@ -13540,7 +13477,7 @@ function annotate(fn, strictDi, name) {
* @description
*
* Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
- * intercepts the creation of a service, allowing it to override or modify the behavior of the
+ * intercepts the creation of a service, allowing it to override or modify the behaviour of the
* service. The object returned by the decorator may be the original service, or a new service
* object which replaces or wraps and delegates to the original service.
*
@@ -13589,19 +13526,14 @@ function createInjector(modulesToLoad, strictDi) {
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
})),
instanceCache = {},
- protoInstanceInjector =
+ instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(serviceName, caller) {
var provider = providerInjector.get(serviceName + providerSuffix, caller);
- return instanceInjector.invoke(
- provider.$get, provider, undefined, serviceName);
- }),
- instanceInjector = protoInstanceInjector;
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
+ }));
- providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
- var runBlocks = loadModules(modulesToLoad);
- instanceInjector = protoInstanceInjector.get('$injector');
- instanceInjector.strictDi = strictDi;
- forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
+
+ forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
return instanceInjector;
@@ -13751,66 +13683,47 @@ function createInjector(modulesToLoad, strictDi) {
}
}
+ function invoke(fn, self, locals, serviceName) {
+ if (typeof locals === 'string') {
+ serviceName = locals;
+ locals = null;
+ }
- function injectionArgs(fn, locals, serviceName) {
var args = [],
- $inject = createInjector.$$annotate(fn, strictDi, serviceName);
+ $inject = createInjector.$$annotate(fn, strictDi, serviceName),
+ length, i,
+ key;
- for (var i = 0, length = $inject.length; i < length; i++) {
- var key = $inject[i];
+ for (i = 0, length = $inject.length; i < length; i++) {
+ key = $inject[i];
if (typeof key !== 'string') {
throw $injectorMinErr('itkn',
'Incorrect injection token! Expected service name as string, got {0}', key);
}
- args.push(locals && locals.hasOwnProperty(key) ? locals[key] :
- getService(key, serviceName));
- }
- return args;
- }
-
- function isClass(func) {
- // IE 9-11 do not support classes and IE9 leaks with the code below.
- if (msie <= 11) {
- return false;
- }
- // Workaround for MS Edge.
- // Check https://connect.microsoft.com/IE/Feedback/Details/2211653
- return typeof func === 'function'
- && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func));
- }
-
- function invoke(fn, self, locals, serviceName) {
- if (typeof locals === 'string') {
- serviceName = locals;
- locals = null;
+ args.push(
+ locals && locals.hasOwnProperty(key)
+ ? locals[key]
+ : getService(key, serviceName)
+ );
}
-
- var args = injectionArgs(fn, locals, serviceName);
if (isArray(fn)) {
- fn = fn[fn.length - 1];
+ fn = fn[length];
}
- if (!isClass(fn)) {
- // http://jsperf.com/angularjs-invoke-apply-vs-switch
- // #5388
- return fn.apply(self, args);
- } else {
- args.unshift(null);
- return new (Function.prototype.bind.apply(fn, args))();
- }
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
}
-
function instantiate(Type, locals, serviceName) {
// Check if Type is annotated and use just the given function at n-1 as parameter
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
- var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
- var args = injectionArgs(Type, locals, serviceName);
- // Empty object at position 0 is ignored for invocation with `new`, but required.
- args.unshift(null);
- return new (Function.prototype.bind.apply(ctor, args))();
- }
+ // Object creation: http://jsperf.com/create-constructor/2
+ var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
+ var returnedValue = invoke(Type, instance, locals, serviceName);
+ return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
+ }
return {
invoke: invoke,
@@ -14150,8 +14063,27 @@ function prepareAnimateOptions(options) {
: {};
}
-var $$CoreAnimateJsProvider = function() {
- this.$get = function() {};
+var $$CoreAnimateRunnerProvider = function() {
+ this.$get = ['$q', '$$rAF', function($q, $$rAF) {
+ function AnimateRunner() {}
+ AnimateRunner.all = noop;
+ AnimateRunner.chain = noop;
+ AnimateRunner.prototype = {
+ end: noop,
+ cancel: noop,
+ resume: noop,
+ pause: noop,
+ complete: noop,
+ then: function(pass, fail) {
+ return $q(function(resolve) {
+ $$rAF(function() {
+ resolve();
+ });
+ }).then(pass, fail);
+ }
+ };
+ return AnimateRunner;
+ }];
};
// this is prefixed with Core since it conflicts with
@@ -14179,12 +14111,7 @@ var $$CoreAnimateQueueProvider = function() {
addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
}
- var runner = new $$AnimateRunner(); // jshint ignore:line
-
- // since there are no animations to run the runner needs to be
- // notified that the animation call is complete.
- runner.complete();
- return runner;
+ return new $$AnimateRunner(); // jshint ignore:line
}
};
@@ -14426,8 +14353,8 @@ var $AnimateProvider = ['$provide', function($provide) {
* // remove all the animation event listeners listening for `enter` on the given element and its children
* $animate.off('enter', container);
*
- * // remove the event listener function provided by `callback` that is set
- * // to listen for `enter` on the given `container` as well as its children
+ * // remove the event listener function provided by `listenerFn` that is set
+ * // to listen for `enter` on the given `element` as well as its children
* $animate.off('enter', container, callback);
* ```
*
@@ -14649,30 +14576,17 @@ var $AnimateProvider = ['$provide', function($provide) {
* @kind function
*
* @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
- * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take
- * on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and
- * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding
- * style in `to`, the style in `from` is applied immediately, and no animation is run.
- * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`
- * method (or as part of the `options` parameter):
- *
- * ```js
- * ngModule.animation('.my-inline-animation', function() {
- * return {
- * animate : function(element, from, to, done, options) {
- * //animation
- * done();
- * }
- * }
- * });
- * ```
+ * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
+ * on the provided styles. For example, if a transition animation is set for the given className then the provided from and
+ * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles
+ * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter).
*
* @param {DOMElement} element the element which the CSS styles will be applied to
* @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
* @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
* @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
* this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
- * (Note that if no animation is detected then this value will not be applied to the element.)
+ * (Note that if no animation is detected then this value will not be appplied to the element.)
* @param {object=} options an optional collection of options/styles that will be applied to the element
*
* @return {Promise} the animation callback promise
@@ -14690,190 +14604,6 @@ var $AnimateProvider = ['$provide', function($provide) {
}];
}];
-var $$AnimateAsyncRunFactoryProvider = function() {
- this.$get = ['$$rAF', function($$rAF) {
- var waitQueue = [];
-
- function waitForTick(fn) {
- waitQueue.push(fn);
- if (waitQueue.length > 1) return;
- $$rAF(function() {
- for (var i = 0; i < waitQueue.length; i++) {
- waitQueue[i]();
- }
- waitQueue = [];
- });
- }
-
- return function() {
- var passed = false;
- waitForTick(function() {
- passed = true;
- });
- return function(callback) {
- passed ? callback() : waitForTick(callback);
- };
- };
- }];
-};
-
-var $$AnimateRunnerFactoryProvider = function() {
- this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
- function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
-
- var INITIAL_STATE = 0;
- var DONE_PENDING_STATE = 1;
- var DONE_COMPLETE_STATE = 2;
-
- AnimateRunner.chain = function(chain, callback) {
- var index = 0;
-
- next();
- function next() {
- if (index === chain.length) {
- callback(true);
- return;
- }
-
- chain[index](function(response) {
- if (response === false) {
- callback(false);
- return;
- }
- index++;
- next();
- });
- }
- };
-
- AnimateRunner.all = function(runners, callback) {
- var count = 0;
- var status = true;
- forEach(runners, function(runner) {
- runner.done(onProgress);
- });
-
- function onProgress(response) {
- status = status && response;
- if (++count === runners.length) {
- callback(status);
- }
- }
- };
-
- function AnimateRunner(host) {
- this.setHost(host);
-
- var rafTick = $$animateAsyncRun();
- var timeoutTick = function(fn) {
- $timeout(fn, 0, false);
- };
-
- this._doneCallbacks = [];
- this._tick = function(fn) {
- var doc = $document[0];
-
- // the document may not be ready or attached
- // to the module for some internal tests
- if (doc && doc.hidden) {
- timeoutTick(fn);
- } else {
- rafTick(fn);
- }
- };
- this._state = 0;
- }
-
- AnimateRunner.prototype = {
- setHost: function(host) {
- this.host = host || {};
- },
-
- done: function(fn) {
- if (this._state === DONE_COMPLETE_STATE) {
- fn();
- } else {
- this._doneCallbacks.push(fn);
- }
- },
-
- progress: noop,
-
- getPromise: function() {
- if (!this.promise) {
- var self = this;
- this.promise = $q(function(resolve, reject) {
- self.done(function(status) {
- status === false ? reject() : resolve();
- });
- });
- }
- return this.promise;
- },
-
- then: function(resolveHandler, rejectHandler) {
- return this.getPromise().then(resolveHandler, rejectHandler);
- },
-
- 'catch': function(handler) {
- return this.getPromise()['catch'](handler);
- },
-
- 'finally': function(handler) {
- return this.getPromise()['finally'](handler);
- },
-
- pause: function() {
- if (this.host.pause) {
- this.host.pause();
- }
- },
-
- resume: function() {
- if (this.host.resume) {
- this.host.resume();
- }
- },
-
- end: function() {
- if (this.host.end) {
- this.host.end();
- }
- this._resolve(true);
- },
-
- cancel: function() {
- if (this.host.cancel) {
- this.host.cancel();
- }
- this._resolve(false);
- },
-
- complete: function(response) {
- var self = this;
- if (self._state === INITIAL_STATE) {
- self._state = DONE_PENDING_STATE;
- self._tick(function() {
- self._resolve(response);
- });
- }
- },
-
- _resolve: function(response) {
- if (this._state !== DONE_COMPLETE_STATE) {
- forEach(this._doneCallbacks, function(fn) {
- fn(response);
- });
- this._doneCallbacks.length = 0;
- this._state = DONE_COMPLETE_STATE;
- }
- }
- };
-
- return AnimateRunner;
- }];
-};
-
/**
* @ngdoc service
* @name $animateCss
@@ -14886,18 +14616,37 @@ var $$AnimateRunnerFactoryProvider = function() {
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
*/
var $CoreAnimateCssProvider = function() {
- this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
+ this.$get = ['$$rAF', '$q', function($$rAF, $q) {
- return function(element, initialOptions) {
- // all of the animation functions should create
- // a copy of the options data, however, if a
- // parent service has already created a copy then
- // we should stick to using that
- var options = initialOptions || {};
- if (!options.$$prepared) {
- options = copy(options);
+ var RAFPromise = function() {};
+ RAFPromise.prototype = {
+ done: function(cancel) {
+ this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
+ },
+ end: function() {
+ this.done();
+ },
+ cancel: function() {
+ this.done(true);
+ },
+ getPromise: function() {
+ if (!this.defer) {
+ this.defer = $q.defer();
+ }
+ return this.defer.promise;
+ },
+ then: function(f1,f2) {
+ return this.getPromise().then(f1,f2);
+ },
+ 'catch': function(f1) {
+ return this.getPromise()['catch'](f1);
+ },
+ 'finally': function(f1) {
+ return this.getPromise()['finally'](f1);
}
+ };
+ return function(element, options) {
// there is no point in applying the styles since
// there is no animation that goes on at all in
// this version of $animateCss.
@@ -14910,8 +14659,7 @@ var $CoreAnimateCssProvider = function() {
options.from = null;
}
- /* jshint newcap: false */
- var closed, runner = new $$AnimateRunner();
+ var closed, runner = new RAFPromise();
return {
start: run,
end: run
@@ -14919,16 +14667,16 @@ var $CoreAnimateCssProvider = function() {
function run() {
$$rAF(function() {
- applyAnimationContents();
+ close();
if (!closed) {
- runner.complete();
+ runner.done();
}
closed = true;
});
return runner;
}
- function applyAnimationContents() {
+ function close() {
if (options.addClass) {
element.addClass(options.addClass);
options.addClass = null;
@@ -15836,7 +15584,7 @@ function $TemplateCacheProvider() {
* When this property is set to true, the HTML compiler will collect DOM nodes between
* nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
* together as the directive elements. It is recommended that this feature be used on directives
- * which are not strictly behavioral (such as {@link ngClick}), and which
+ * which are not strictly behavioural (such as {@link ngClick}), and which
* do not manipulate or replace child nodes (such as {@link ngInclude}).
*
* #### `priority`
@@ -15874,62 +15622,35 @@ function $TemplateCacheProvider() {
* is bound to the parent scope, via matching attributes on the directive's element:
*
* * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
- * always a string since DOM attributes are strings. If no `attr` name is specified then the
- * attribute name is assumed to be the same as the local name. Given `<my-component
- * my-attr="hello {{name}}">` and the isolate scope definition `scope: { localName:'@myAttr' }`,
- * the directive's scope property `localName` will reflect the interpolated value of `hello
- * {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's
- * scope. The `name` is read from the parent scope (not the directive's scope).
- *
- * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression
- * passed via the attribute `attr`. The expression is evaluated in the context of the parent scope.
- * If no `attr` name is specified then the attribute name is assumed to be the same as the local
- * name. Given `<my-component my-attr="parentModel">` and the isolate scope definition `scope: {
- * localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the
- * value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in
- * `localModel` and vice versa. Optional attributes should be marked as such with a question mark:
- * `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't
- * optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`})
- * will be thrown upon discovering changes to the local value, since it will be impossible to sync
- * them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`}
- * method is used for tracking changes, and the equality check is based on object identity.
- * However, if an object literal or an array literal is passed as the binding expression, the
- * equality check is done by value (using the {@link angular.equals} function). It's also possible
- * to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection
- * `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional).
- *
- * * `<` or `<attr` - set up a one-way (one-directional) binding between a local scope property and an
- * expression passed via the attribute `attr`. The expression is evaluated in the context of the
- * parent scope. If no `attr` name is specified then the attribute name is assumed to be the same as the
- * local name. You can also make the binding optional by adding `?`: `<?` or `<?attr`.
- *
- * For example, given `<my-component my-attr="parentModel">` and directive definition of
- * `scope: { localModel:'<myAttr' }`, then the isolated scope property `localModel` will reflect the
+ * always a string since DOM attributes are strings. If no `attr` name is specified then the
+ * attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="hello {{name}}">` and widget definition
+ * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
+ * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
+ * `localName` property on the widget scope. The `name` is read from the parent scope (not
+ * component scope).
+ *
+ * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
+ * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
+ * name is specified then the attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="parentModel">` and widget definition of
+ * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
* value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
- * in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however
- * two caveats:
- * 1. one-way binding does not copy the value from the parent to the isolate scope, it simply
- * sets the same value. That means if your bound value is an object, changes to its properties
- * in the isolated scope will be reflected in the parent scope (because both reference the same object).
- * 2. one-way binding watches changes to the **identity** of the parent value. That means the
- * {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference
- * to the value has changed. In most cases, this should not be of concern, but can be important
- * to know if you one-way bind to an object, and then replace that object in the isolated scope.
- * If you now change a property of the object in your parent scope, the change will not be
- * propagated to the isolated scope, because the identity of the object on the parent scope
- * has not changed. Instead you must assign a new object.
- *
- * One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
- * back to the parent. However, it does not make this completely impossible.
- *
- * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
- * no `attr` name is specified then the attribute name is assumed to be the same as the local name.
- * Given `<my-component my-attr="count = count + value">` and the isolate scope definition `scope: {
- * localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for
- * the `count = count + value` expression. Often it's desirable to pass data from the isolated scope
- * via an expression to the parent scope. This can be done by passing a map of local variable names
- * and values into the expression wrapper fn. For example, if the expression is `increment(amount)`
- * then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`.
+ * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
+ * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
+ * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
+ * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
+ * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
+ *
+ * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
+ * If no `attr` name is specified then the attribute name is assumed to be the same as the
+ * local name. Given `<widget my-attr="count = count + value">` and widget definition of
+ * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
+ * a function wrapper for the `count = count + value` expression. Often it's desirable to
+ * pass data from the isolated scope via an expression to the parent scope, this can be
+ * done by passing a map of local variable names and values into the expression wrapper fn.
+ * For example, if the expression is `increment(amount)` then we can specify the amount value
+ * by calling the `localFn` as `localFn({amount: 22})`.
*
* In general it's possible to apply more than one directive to one element, but there might be limitations
* depending on the type of scope required by the directives. The following points will help explain these limitations.
@@ -15947,32 +15668,9 @@ function $TemplateCacheProvider() {
*
*
* #### `bindToController`
- * This property is used to bind scope properties directly to the controller. It can be either
- * `true` or an object hash with the same format as the `scope` property. Additionally, a controller
- * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller
- * definition: `controller: 'myCtrl as myAlias'`.
- *
- * When an isolate scope is used for a directive (see above), `bindToController: true` will
- * allow a component to have its properties bound to the controller, rather than to scope.
- *
- * After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller
- * properties. You can access these bindings once they have been initialized by providing a controller method called
- * `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings
- * initialized.
- *
- * <div class="alert alert-warning">
- * **Deprecation warning:** although bindings for non-ES6 class controllers are currently
- * bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization
- * code that relies upon bindings inside a `$onInit` method on the controller, instead.
- * </div>
- *
- * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
- * This will set up the scope bindings to the controller directly. Note that `scope` can still be used
- * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate
- * scope (useful for component directives).
- *
- * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`.
- *
+ * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
+ * allow a component to have its properties bound to the controller, rather than to scope. When the controller
+ * is instantiated, the initial values of the isolate scope bindings are already available.
*
* #### `controller`
* Controller constructor function. The controller is instantiated before the
@@ -15984,10 +15682,10 @@ function $TemplateCacheProvider() {
* * `$element` - Current element
* * `$attrs` - Current attributes object for the element
* * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
- * `function([scope], cloneLinkingFn, futureParentElement, slotName)`:
- * * `scope`: (optional) override the scope.
- * * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content.
- * * `futureParentElement` (optional):
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ * * `scope`: optional argument to override the scope.
+ * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
+ * * `futureParentElement`:
* * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
* * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
* * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
@@ -15995,34 +15693,14 @@ function $TemplateCacheProvider() {
* as those elements need to created and cloned in a special way when they are defined outside their
* usual containers (e.g. like `<svg>`).
* * See also the `directive.templateNamespace` property.
- * * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`)
- * then the default translusion is provided.
- * The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns
- * `true` if the specified slot contains content (i.e. one or more DOM nodes).
*
- * The controller can provide the following methods that act as life-cycle hooks:
- * * `$onInit` - Called on each controller after all the controllers on an element have been constructed and
- * had their bindings initialized (and before the pre &amp; post linking functions for the directives on
- * this element). This is a good place to put initialization code for your controller.
*
* #### `require`
* Require another directive and inject its controller as the fourth argument to the linking function. The
- * `require` property can be a string, an array or an object:
- * * a **string** containing the name of the directive to pass to the linking function
- * * an **array** containing the names of directives to pass to the linking function. The argument passed to the
- * linking function will be an array of controllers in the same order as the names in the `require` property
- * * an **object** whose property values are the names of the directives to pass to the linking function. The argument
- * passed to the linking function will also be an object with matching keys, whose values will hold the corresponding
- * controllers.
- *
- * If the `require` property is an object and `bindToController` is truthy, then the required controllers are
- * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers
- * have been constructed but before `$onInit` is called.
- * See the {@link $compileProvider#component} helper for an example of how this can be used.
- *
- * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is
- * raised (unless no link function is specified and the required controllers are not being bound to the directive
- * controller, in which case error checking is skipped). The name can be prefixed with:
+ * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
+ * injected argument will be an array in corresponding order. If no such directive can be
+ * found, or if the directive does not have a controller, then an error is raised (unless no link function
+ * is specified, in which case error checking is skipped). The name can be prefixed with:
*
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
@@ -16115,6 +15793,14 @@ function $TemplateCacheProvider() {
* The contents are compiled and provided to the directive as a **transclusion function**. See the
* {@link $compile#transclusion Transclusion} section below.
*
+ * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
+ * directive's element or the entire element:
+ *
+ * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
+ * * `'element'` - transclude the whole of the directive's element including any directives on this
+ * element that defined at a lower priority than this directive. When used, the `template`
+ * property is ignored.
+ *
*
* #### `compile`
*
@@ -16142,7 +15828,7 @@ function $TemplateCacheProvider() {
* <div class="alert alert-warning">
* **Note:** The compile function cannot handle directives that recursively use themselves in their
- * own templates or compile functions. Compiling these directives results in an infinite loop and
+ * own templates or compile functions. Compiling these directives results in an infinite loop and a
* stack overflow errors.
*
* This can be avoided by manually using $compile in the postLink function to imperatively compile
@@ -16244,34 +15930,6 @@ function $TemplateCacheProvider() {
* Testing Transclusion Directives}.
* </div>
*
- * There are three kinds of transclusion depending upon whether you want to transclude just the contents of the
- * directive's element, the entire element or multiple parts of the element contents:
- *
- * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
- * * `'element'` - transclude the whole of the directive's element including any directives on this
- * element that defined at a lower priority than this directive. When used, the `template`
- * property is ignored.
- * * **`{...}` (an object hash):** - map elements of the content onto transclusion "slots" in the template.
- *
- * **Mult-slot transclusion** is declared by providing an object for the `transclude` property.
- *
- * This object is a map where the keys are the name of the slot to fill and the value is an element selector
- * used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`)
- * and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc).
- *
- * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
- *
- * If the element selector is prefixed with a `?` then that slot is optional.
- *
- * For example, the transclude object `{ slotA: '?myCustomElement' }` maps `<my-custom-element>` elements to
- * the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive.
- *
- * Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements
- * in the transclude content. If you wish to know if an optional slot was filled with content, then you can call
- * `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and
- * injectable into the directive's controller.
- *
- *
* #### Transclusion Functions
*
* When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
@@ -16292,7 +15950,7 @@ function $TemplateCacheProvider() {
* content and the `scope` is the newly created transclusion scope, to which the clone is bound.
*
* <div class="alert alert-info">
- * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function
+ * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
* since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
* </div>
*
@@ -16324,7 +15982,7 @@ function $TemplateCacheProvider() {
* </div>
*
* The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
- * automatically destroy their transcluded clones as necessary so you do not need to worry about this if
+ * automatically destroy their transluded clones as necessary so you do not need to worry about this if
* you are simply using {@link ngTransclude} to inject the transclusion into your directive.
*
*
@@ -16349,19 +16007,19 @@ function $TemplateCacheProvider() {
*
* The `$parent` scope hierarchy will look like this:
*
- ```
- - $rootScope
- - isolate
- - transclusion
- ```
+ * ```
+ * - $rootScope
+ * - isolate
+ * - transclusion
+ * ```
*
* but the scopes will inherit prototypically from different scopes to their `$parent`.
*
- ```
- - $rootScope
- - transclusion
- - isolate
- ```
+ * ```
+ * - $rootScope
+ * - transclusion
+ * - isolate
+ * ```
*
*
* ### Attributes
@@ -16369,9 +16027,10 @@ function $TemplateCacheProvider() {
* The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
* `link()` or `compile()` functions. It has a variety of uses.
*
- * * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways:
- * 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access
- * to the attributes.
+ * accessing *Normalized attribute names:*
+ * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
+ * the attributes object allows for normalized access to
+ * the attributes.
*
* * *Directive inter-communication:* All directives share the same instance of the attributes
* object which allows the directives to use the attributes object as inter directive
@@ -16492,15 +16151,8 @@ function $TemplateCacheProvider() {
* directives; if given, it will be passed through to the link functions of
* directives found in `element` during compilation.
* * `transcludeControllers` - an object hash with keys that map controller names
- * to a hash with the key `instance`, which maps to the controller instance;
- * if given, it will make the controllers available to directives on the compileNode:
- * ```
- * {
- * parent: {
- * instance: parentControllerInstance
- * }
- * }
- * ```
+ * to controller instances; if given, it will make the controllers
+ * available to directives.
* * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
* the cloned elements; only needed for transcludes that are allowed to contain non html
* elements (e.g. SVG elements). See also the directive.controller property.
@@ -16561,7 +16213,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
function parseIsolateBindings(scope, directiveName, isController) {
- var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
+ var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
var bindings = {};
@@ -16648,8 +16300,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
* will match as <code>ng-bind</code>), or an object map of directives where the keys are the
* names and the values are the factories.
- * @param {Function|Array} directiveFactory An injectable directive factory function. See the
- * {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
+ * @param {Function|Array} directiveFactory An injectable directive factory function. See
+ * {@link guide/directive} for more info.
* @returns {ng.$compileProvider} Self for chaining.
*/
this.directive = function registerDirective(name, directiveFactory) {
@@ -16696,128 +16348,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return this;
};
- /**
- * @ngdoc method
- * @name $compileProvider#component
- * @module ng
- * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`)
- * @param {Object} options Component definition object (a simplified
- * {@link ng.$compile#directive-definition-object directive definition object}),
- * with the following properties (all optional):
- *
- * - `controller` – `{(string|function()=}` – controller constructor function that should be
- * associated with newly created scope or the name of a {@link ng.$compile#-controller-
- * registered controller} if passed as a string. An empty `noop` function by default.
- * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
- * If present, the controller will be published to scope under the `controllerAs` name.
- * If not present, this will default to be `$ctrl`.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used as the contents of this component.
- * Empty string by default.
- *
- * If `template` is a function, then it is {@link auto.$injector#invoke injected} with
- * the following locals:
- *
- * - `$element` - Current element
- * - `$attrs` - Current attributes object for the element
- *
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
- * template that should be used as the contents of this component.
- *
- * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
- * the following locals:
- *
- * - `$element` - Current element
- * - `$attrs` - Current attributes object for the element
- *
- * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
- * Component properties are always bound to the component controller and not to the scope.
- * See {@link ng.$compile#-bindtocontroller- `bindToController`}.
- * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.
- * Disabled by default.
- * - `$...` – `{function()=}` – additional annotations to provide to the directive factory function.
- *
- * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls.
- * @description
- * Register a **component definition** with the compiler. This is a shorthand for registering a special
- * type of directive, which represents a self-contained UI component in your application. Such components
- * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`).
- *
- * Component definitions are very simple and do not require as much configuration as defining general
- * directives. Component definitions usually consist only of a template and a controller backing it.
- *
- * In order to make the definition easier, components enforce best practices like use of `controllerAs`,
- * `bindToController`. They always have **isolate scope** and are restricted to elements.
- *
- * Here are a few examples of how you would usually define components:
- *
- * ```js
- * var myMod = angular.module(...);
- * myMod.component('myComp', {
- * template: '<div>My name is {{$ctrl.name}}</div>',
- * controller: function() {
- * this.name = 'shahar';
- * }
- * });
- *
- * myMod.component('myComp', {
- * template: '<div>My name is {{$ctrl.name}}</div>',
- * bindings: {name: '@'}
- * });
- *
- * myMod.component('myComp', {
- * templateUrl: 'views/my-comp.html',
- * controller: 'MyCtrl as ctrl',
- * bindings: {name: '@'}
- * });
- *
- * ```
- * For more examples, and an in-depth guide, see the {@link guide/component component guide}.
- *
- * <br />
- * See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
- */
- this.component = function registerComponent(name, options) {
- var controller = options.controller || function() {};
-
- function factory($injector) {
- function makeInjectable(fn) {
- if (isFunction(fn) || isArray(fn)) {
- return function(tElement, tAttrs) {
- return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
- };
- } else {
- return fn;
- }
- }
-
- var template = (!options.template && !options.templateUrl ? '' : options.template);
- return {
- controller: controller,
- controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
- template: makeInjectable(template),
- templateUrl: makeInjectable(options.templateUrl),
- transclude: options.transclude,
- scope: {},
- bindToController: options.bindings || {},
- restrict: 'E',
- require: options.require
- };
- }
-
- // Copy any annotation properties (starting with $) over to the factory function
- // These could be used by libraries such as the new component router
- forEach(options, function(val, key) {
- if (key.charAt(0) === '$') {
- factory[key] = val;
- }
- });
-
- factory.$inject = ['$injector'];
-
- return this.directive(name, factory);
- };
-
/**
* @ngdoc method
@@ -16911,12 +16441,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
- '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
+ '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
- $controller, $rootScope, $sce, $animate, $$sanitizeUri) {
+ $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
- var SIMPLE_ATTR_NAME = /^\w/;
- var specialAttrHolder = document.createElement('div');
var Attributes = function(element, attributesToCopy) {
if (attributesToCopy) {
var keys = Object.keys(attributesToCopy);
@@ -17052,7 +16580,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeName = nodeName_(this.$$element);
- if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||
+ if ((nodeName === 'a' && key === 'href') ||
(nodeName === 'img' && key === 'src')) {
// sanitize a[href] and img[src] values
this[key] = value = $$sanitizeUri(value, key === 'src');
@@ -17096,11 +16624,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (value === null || isUndefined(value)) {
this.$$element.removeAttr(attrName);
} else {
- if (SIMPLE_ATTR_NAME.test(attrName)) {
- this.$$element.attr(attrName, value);
- } else {
- setSpecialAttr(this.$$element[0], attrName, value);
- }
+ this.$$element.attr(attrName, value);
}
}
@@ -17131,8 +16655,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* @param {string} key Normalized key. (ie ngAttribute) .
* @param {function(interpolatedValue)} fn Function that will be called whenever
the interpolated value of the attribute changes.
- * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation
- * guide} for more info.
+ * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
* @returns {function()} Returns a deregistration function for this observer.
*/
$observe: function(key, fn) {
@@ -17154,18 +16677,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
};
- function setSpecialAttr(element, attrName, value) {
- // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute`
- // so we have to jump through some hoops to get such an attribute
- // https://github.com/angular/angular.js/pull/13318
- specialAttrHolder.innerHTML = "<span " + attrName + ">";
- var attributes = specialAttrHolder.firstChild.attributes;
- var attribute = attributes[0];
- // We have to remove the attribute from its container element before we can add it to the destination element
- attributes.removeNamedItem(attribute.name);
- attribute.value = value;
- element.attributes.setNamedItem(attribute);
- }
function safeAddClass($element, className) {
try {
@@ -17179,7 +16690,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var startSymbol = $interpolate.startSymbol(),
endSymbol = $interpolate.endSymbol(),
- denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}')
+ denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
? identity
: function denormalizeTemplate(template) {
return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
@@ -17223,19 +16734,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// modify it.
$compileNodes = jqLite($compileNodes);
}
-
- var NOT_EMPTY = /\S+/;
-
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
- for (var i = 0, len = $compileNodes.length; i < len; i++) {
- var domNode = $compileNodes[i];
-
- if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {
- jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span'));
+ forEach($compileNodes, function(node, index) {
+ if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
}
- }
-
+ });
var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);
@@ -17306,7 +16811,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (!node) {
return 'html';
} else {
- return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html';
+ return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
}
}
@@ -17440,17 +16945,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
});
};
- // We need to attach the transclusion slots onto the `boundTranscludeFn`
- // so that they are available inside the `controllersBoundTransclude` function
- var boundSlots = boundTranscludeFn.$$slots = createMap();
- for (var slotName in transcludeFn.$$slots) {
- if (transcludeFn.$$slots[slotName]) {
- boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);
- } else {
- boundSlots[slotName] = null;
- }
- }
-
return boundTranscludeFn;
}
@@ -17610,37 +17104,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
/**
- * A function generator that is used to support both eager and lazy compilation
- * linking function.
- * @param eager
- * @param $compileNodes
- * @param transcludeFn
- * @param maxPriority
- * @param ignoreDirective
- * @param previousCompileContext
- * @returns {Function}
- */
- function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {
- if (eager) {
- return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
- }
-
- var compiled;
-
- return function() {
- if (!compiled) {
- compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
-
- // Null out all of these references in order to make them eligible for garbage collection
- // since this is a potentially long lived closure
- $compileNodes = transcludeFn = previousCompileContext = null;
- }
-
- return compiled.apply(this, arguments);
- };
- }
-
- /**
* Once the directives have been collected, their compile functions are executed. This method
* is responsible for inlining directive templates as well as terminating the application
* of the directives if the terminal directive has been reached.
@@ -17684,8 +17147,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
replaceDirective = originalReplaceDirective,
childTranscludeFn = transcludeFn,
linkFn,
- didScanForMultipleTransclusion = false,
- mightHaveMultipleTransclusionError = false,
directiveValue;
// executes all directives on the current element
@@ -17728,27 +17189,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
directiveName = directive.name;
- // If we encounter a condition that can result in transclusion on the directive,
- // then scan ahead in the remaining directives for others that may cause a multiple
- // transclusion error to be thrown during the compilation process. If a matching directive
- // is found, then we know that when we encounter a transcluded directive, we need to eagerly
- // compile the `transclude` function rather than doing it lazily in order to throw
- // exceptions at the correct time
- if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))
- || (directive.transclude && !directive.$$tlb))) {
- var candidateDirective;
-
- for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {
- if ((candidateDirective.transclude && !candidateDirective.$$tlb)
- || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {
- mightHaveMultipleTransclusionError = true;
- break;
- }
- }
-
- didScanForMultipleTransclusion = true;
- }
-
if (!directive.templateUrl && directive.controller) {
directiveValue = directive.controller;
controllerDirectives = controllerDirectives || createMap();
@@ -17778,7 +17218,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
compileNode = $compileNode[0];
replaceWith(jqCollection, sliceArgs($template), compileNode);
- childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,
+ childTranscludeFn = compile($template, transcludeFn, terminalPriority,
replaceDirective && replaceDirective.name, {
// Don't pass in:
// - controllerDirectives - otherwise we'll create duplicates controllers
@@ -17790,69 +17230,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nonTlbTranscludeDirective: nonTlbTranscludeDirective
});
} else {
-
- var slots = createMap();
-
$template = jqLite(jqLiteClone(compileNode)).contents();
-
- if (isObject(directiveValue)) {
-
- // We have transclusion slots,
- // collect them up, compile them and store their transclusion functions
- $template = [];
-
- var slotMap = createMap();
- var filledSlots = createMap();
-
- // Parse the element selectors
- forEach(directiveValue, function(elementSelector, slotName) {
- // If an element selector starts with a ? then it is optional
- var optional = (elementSelector.charAt(0) === '?');
- elementSelector = optional ? elementSelector.substring(1) : elementSelector;
-
- slotMap[elementSelector] = slotName;
-
- // We explicitly assign `null` since this implies that a slot was defined but not filled.
- // Later when calling boundTransclusion functions with a slot name we only error if the
- // slot is `undefined`
- slots[slotName] = null;
-
- // filledSlots contains `true` for all slots that are either optional or have been
- // filled. This is used to check that we have not missed any required slots
- filledSlots[slotName] = optional;
- });
-
- // Add the matching elements into their slot
- forEach($compileNode.contents(), function(node) {
- var slotName = slotMap[directiveNormalize(nodeName_(node))];
- if (slotName) {
- filledSlots[slotName] = true;
- slots[slotName] = slots[slotName] || [];
- slots[slotName].push(node);
- } else {
- $template.push(node);
- }
- });
-
- // Check for required slots that were not filled
- forEach(filledSlots, function(filled, slotName) {
- if (!filled) {
- throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);
- }
- });
-
- for (var slotName in slots) {
- if (slots[slotName]) {
- // Only define a transclusion function if the slot was filled
- slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);
- }
- }
- }
-
$compileNode.empty(); // clear contents
- childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,
+ childTranscludeFn = compile($template, transcludeFn, undefined,
undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
- childTranscludeFn.$$slots = slots;
}
}
@@ -18015,11 +17396,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
for (var i = 0, ii = require.length; i < ii; i++) {
value[i] = getControllers(directiveName, require[i], $element, elementControllers);
}
- } else if (isObject(require)) {
- value = {};
- forEach(require, function(controller, property) {
- value[property] = getControllers(directiveName, controller, $element, elementControllers);
- });
}
return value || null;
@@ -18057,7 +17433,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
- var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
+ var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
attrs, removeScopeBindingWatches, removeControllerBindingWatches;
if (compileNode === linkNode) {
@@ -18080,10 +17456,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
transcludeFn = controllersBoundTransclude;
transcludeFn.$$boundTransclude = boundTranscludeFn;
- // expose the slots on the `$transclude` function
- transcludeFn.isSlotFilled = function(slotName) {
- return !!boundTranscludeFn.$$slots[slotName];
- };
}
if (controllerDirectives) {
@@ -18128,21 +17500,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
- // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
- forEach(controllerDirectives, function(controllerDirective, name) {
- var require = controllerDirective.require;
- if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
- extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
- }
- });
-
- // Trigger the `$onInit` method on all controllers that have one
- forEach(elementControllers, function(controller) {
- if (isFunction(controller.instance.$onInit)) {
- controller.instance.$onInit();
- }
- });
-
// PRELINKING
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
linkFn = preLinkFns[i];
@@ -18178,11 +17535,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// This is the function that is injected as `$transclude`.
// Note: all arguments are optional!
- function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
+ function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
var transcludeControllers;
+
// No scope passed in:
if (!isScope(scope)) {
- slotName = futureParentElement;
futureParentElement = cloneAttachFn;
cloneAttachFn = scope;
scope = undefined;
@@ -18194,23 +17551,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (!futureParentElement) {
futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
}
- if (slotName) {
- // slotTranscludeFn can be one of three things:
- // * a transclude function - a filled slot
- // * `null` - an optional slot that was not filled
- // * `undefined` - a slot that was not declared (i.e. invalid)
- var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
- if (slotTranscludeFn) {
- return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
- } else if (isUndefined(slotTranscludeFn)) {
- throw $compileMinErr('noslot',
- 'No parent directive that requires a transclusion with slot name "{0}". ' +
- 'Element: {1}',
- slotName, startingTag($element));
- }
- } else {
- return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
- }
+ return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
}
}
}
@@ -18642,14 +17983,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
parent.replaceChild(newNode, firstElementToRemove);
}
- // Append all the `elementsToRemove` to a fragment. This will...
- // - remove them from the DOM
- // - allow them to still be traversed with .nextSibling
- // - allow a single fragment.qSA to fetch all elements being removed
+ // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
var fragment = document.createDocumentFragment();
- for (i = 0; i < removeCount; i++) {
- fragment.appendChild(elementsToRemove[i]);
- }
+ fragment.appendChild(firstElementToRemove);
if (jqLite.hasData(firstElementToRemove)) {
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
@@ -18657,18 +17993,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// event listeners (which is the main use of private data) wouldn't work anyway.
jqLite.data(newNode, jqLite.data(firstElementToRemove));
- // Remove $destroy event listeners from `firstElementToRemove`
- jqLite(firstElementToRemove).off('$destroy');
+ // Remove data of the replaced element. We cannot just call .remove()
+ // on the element it since that would deallocate scope that is needed
+ // for the new node. Instead, remove the data "manually".
+ if (!jQuery) {
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
+ } else {
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
+ // the replaced element. The cleanData version monkey-patched by Angular would cause
+ // the scope to be trashed and we do need the very same scope to work with the new
+ // element. However, we cannot just cache the non-patched version and use it here as
+ // that would break if another library patches the method after Angular does (one
+ // example is jQuery UI). Instead, set a flag indicating scope destroying should be
+ // skipped this one time.
+ skipDestroyOnNextJQueryCleanData = true;
+ jQuery.cleanData([firstElementToRemove]);
+ }
}
- // Cleanup any data/listeners on the elements and children.
- // This includes invoking the $destroy event on any elements with listeners.
- jqLite.cleanData(fragment.querySelectorAll('*'));
-
- // Update the jqLite collection to only contain the `newNode`
- for (i = 1; i < removeCount; i++) {
- delete elementsToRemove[i];
+ for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
+ var element = elementsToRemove[k];
+ jqLite(element).remove(); // must do this way to clean up expando
+ fragment.appendChild(element);
+ delete elementsToRemove[k];
}
+
elementsToRemove[0] = newNode;
elementsToRemove.length = 1;
}
@@ -18697,7 +18046,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
optional = definition.optional,
mode = definition.mode, // @, =, or &
lastValue,
- parentGet, parentSet, compare, removeWatch;
+ parentGet, parentSet, compare;
switch (mode) {
@@ -18711,15 +18060,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
});
attrs.$$observers[attrName].$$scope = scope;
- lastValue = attrs[attrName];
- if (isString(lastValue)) {
+ if (isString(attrs[attrName])) {
// If the attribute has been provided then we trigger an interpolation to ensure
// the value is there for use in the link fn
- destination[scopeName] = $interpolate(lastValue)(scope);
- } else if (isBoolean(lastValue)) {
- // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted
- // the value to boolean rather than a string, so we special case this situation
- destination[scopeName] = lastValue;
+ destination[scopeName] = $interpolate(attrs[attrName])(scope);
}
break;
@@ -18740,8 +18084,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// reset the change, or we will throw this exception on every $digest
lastValue = destination[scopeName] = parentGet(scope);
throw $compileMinErr('nonassign',
- "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
- attrs[attrName], attrName, directive.name);
+ "Expression '{0}' used with directive '{1}' is non-assignable!",
+ attrs[attrName], directive.name);
};
lastValue = destination[scopeName] = parentGet(scope);
var parentValueWatch = function parentValueWatch(parentValue) {
@@ -18758,6 +18102,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return lastValue = parentValue;
};
parentValueWatch.$stateful = true;
+ var removeWatch;
if (definition.collection) {
removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
} else {
@@ -18766,24 +18111,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
removeWatchCollection.push(removeWatch);
break;
- case '<':
- if (!hasOwnProperty.call(attrs, attrName)) {
- if (optional) break;
- attrs[attrName] = void 0;
- }
- if (optional && !attrs[attrName]) break;
-
- parentGet = $parse(attrs[attrName]);
-
- destination[scopeName] = parentGet(scope);
-
- removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newParentValue) {
- destination[scopeName] = newParentValue;
- }, parentGet.literal);
-
- removeWatchCollection.push(removeWatch);
- break;
-
case '&':
// Don't assign Object.prototype method to scope
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
@@ -18912,7 +18239,7 @@ function removeComments(jqNodes) {
var $controllerMinErr = minErr('$controller');
-var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/;
+var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
function identifierForController(controller, ident) {
if (ident && isString(ident)) return ident;
if (isString(controller)) {
@@ -19703,7 +19030,7 @@ function $HttpProvider() {
*
* ```
* module.run(function($http) {
- * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
+ * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
* });
* ```
*
@@ -19931,13 +19258,13 @@ function $HttpProvider() {
*
* ### Cross Site Request Forgery (XSRF) Protection
*
- * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by
- * which the attacker can trick an authenticated user into unknowingly executing actions on your
- * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
- * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
- * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
- * cookie, your server can be assured that the XHR came from JavaScript running on your domain.
- * The header will not be set for cross-domain requests.
+ * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
+ * an unauthorized site can gain your user's private data. Angular provides a mechanism
+ * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
+ * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
+ * JavaScript that runs on your domain could read the cookie, your server can be assured that
+ * the XHR came from JavaScript running on your domain. The header will not be set for
+ * cross-domain requests.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
@@ -20096,14 +19423,10 @@ function $HttpProvider() {
*/
function $http(requestConfig) {
- if (!isObject(requestConfig)) {
+ if (!angular.isObject(requestConfig)) {
throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
}
- if (!isString(requestConfig.url)) {
- throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);
- }
-
var config = extend({
method: 'get',
transformRequest: defaults.transformRequest,
@@ -20216,7 +19539,7 @@ function $HttpProvider() {
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
- // using for-in instead of forEach to avoid unnecessary iteration after header has been found
+ // using for-in instead of forEach to avoid unecessary iteration after header has been found
defaultHeadersIteration:
for (defHeaderName in defHeaders) {
lowercaseDefHeaderName = lowercase(defHeaderName);
@@ -20715,16 +20038,8 @@ $interpolateMinErr.interr = function(text, err) {
*
* Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
*
- * <div class="alert alert-danger">
- * This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular
- * template within a Python Jinja template (or any other template language). Mixing templating
- * languages is **very dangerous**. The embedding template language will not safely escape Angular
- * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)
- * security bugs!
- * </div>
- *
* @example
-<example name="custom-interpolation-markup" module="customInterpolationApp">
+<example module="customInterpolationApp">
<file name="index.html">
<script>
var customInterpolationApp = angular.module('customInterpolationApp', []);
@@ -20739,7 +20054,7 @@ $interpolateMinErr.interr = function(text, err) {
this.label = "This binding is brought you by // interpolation symbols.";
});
</script>
-<div ng-controller="DemoController as demo">
+<div ng-app="App" ng-controller="DemoController as demo">
//demo.label//
</div>
</file>
@@ -20823,15 +20138,6 @@ function $InterpolateProvider() {
return value;
}
- //TODO: this is the same as the constantWatchDelegate in parse.js
- function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {
- var unwatch;
- return unwatch = scope.$watch(function constantInterpolateWatch(scope) {
- unwatch();
- return constantInterp(scope);
- }, listener, objectEquality);
- }
-
/**
* @ngdoc service
* @name $interpolate
@@ -20927,19 +20233,6 @@ function $InterpolateProvider() {
* - `context`: evaluation context for all expressions embedded in the interpolated text
*/
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
- // Provide a quick exit and simplified result function for text with no interpolation
- if (!text.length || text.indexOf(startSymbol) === -1) {
- var constantInterp;
- if (!mustHaveExpression) {
- var unescapedText = unescapeText(text);
- constantInterp = valueFn(unescapedText);
- constantInterp.exp = text;
- constantInterp.expressions = [];
- constantInterp.$$watchDelegate = constantWatchDelegate;
- }
- return constantInterp;
- }
-
allOrNothing = !!allOrNothing;
var startIndex,
endIndex,
@@ -21076,8 +20369,8 @@ function $InterpolateProvider() {
}
function $IntervalProvider() {
- this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser',
- function($rootScope, $window, $q, $$q, $browser) {
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
+ function($rootScope, $window, $q, $$q) {
var intervals = {};
@@ -21218,12 +20511,11 @@ function $IntervalProvider() {
count = isDefined(count) ? count : 0;
+ promise.then(null, null, (!hasParams) ? fn : function() {
+ fn.apply(null, args);
+ });
+
promise.$$intervalId = setInterval(function tick() {
- if (skipApply) {
- $browser.defer(callback);
- } else {
- $rootScope.$evalAsync(callback);
- }
deferred.notify(iteration++);
if (count > 0 && iteration >= count) {
@@ -21239,14 +20531,6 @@ function $IntervalProvider() {
intervals[promise.$$intervalId] = deferred;
return promise;
-
- function callback() {
- if (!hasParams) {
- fn(iteration);
- } else {
- fn.apply(null, args);
- }
- }
}
@@ -22486,22 +21770,23 @@ function ensureSafeMemberName(name, fullExpression) {
return name;
}
-function getStringValue(name) {
+function getStringValue(name, fullExpression) {
+ // From the JavaScript docs:
// Property names must be strings. This means that non-string objects cannot be used
// as keys in an object. Any non-string object, including a number, is typecasted
// into a string via the toString method.
- // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names
- //
- // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it
- // to a string. It's not always possible. If `name` is an object and its `toString` method is
- // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown:
//
- // TypeError: Cannot convert object to primitive value
- //
- // For performance reasons, we don't catch this error here and allow it to propagate up the call
- // stack. Note that you'll get the same error in JavaScript if you try to access a property using
- // such a 'broken' object as a key.
- return name + '';
+ // So, to ensure that we are checking the same `name` that JavaScript would use,
+ // we cast it to a string, if possible.
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
+ // this is, this will handle objects that misbehave.
+ name = name + '';
+ if (!isString(name)) {
+ throw $parseMinErr('iseccst',
+ 'Cannot convert object to primitive value! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
}
function ensureSafeObject(obj, fullExpression) {
@@ -22762,7 +22047,6 @@ AST.ArrayExpression = 'ArrayExpression';
AST.Property = 'Property';
AST.ObjectExpression = 'ObjectExpression';
AST.ThisExpression = 'ThisExpression';
-AST.LocalsExpression = 'LocalsExpression';
// Internal use only
AST.NGValueParameter = 'NGValueParameter';
@@ -23063,8 +22347,7 @@ AST.prototype = {
'false': { type: AST.Literal, value: false },
'null': { type: AST.Literal, value: null },
'undefined': {type: AST.Literal, value: undefined },
- 'this': {type: AST.ThisExpression },
- '$locals': {type: AST.LocalsExpression }
+ 'this': {type: AST.ThisExpression }
}
};
@@ -23184,10 +22467,6 @@ function findConstantAndWatchExpressions(ast, $filter) {
ast.constant = false;
ast.toWatch = [];
break;
- case AST.LocalsExpression:
- ast.constant = false;
- ast.toWatch = [];
- break;
}
}
@@ -23431,9 +22710,6 @@ ASTCompiler.prototype = {
intoId = intoId || this.nextId();
self.recurse(ast.object, left, undefined, function() {
self.if_(self.notNull(left), function() {
- if (create && create !== 1) {
- self.addEnsureSafeAssignContext(left);
- }
if (ast.computed) {
right = self.nextId();
self.recurse(ast.property, right);
@@ -23515,7 +22791,7 @@ ASTCompiler.prototype = {
right = this.nextId();
left = {};
if (!isAssignable(ast.left)) {
- throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
+ throw $parseMinErr('lval', 'Trying to assing a value to a non l-value');
}
this.recurse(ast.left, undefined, left, function() {
self.if_(self.notNull(left.context), function() {
@@ -23557,10 +22833,6 @@ ASTCompiler.prototype = {
this.assign(intoId, 's');
recursionFn('s');
break;
- case AST.LocalsExpression:
- this.assign(intoId, 'l');
- recursionFn('l');
- break;
case AST.NGValueParameter:
this.assign(intoId, 'v');
recursionFn('v');
@@ -23668,7 +22940,7 @@ ASTCompiler.prototype = {
},
getStringValue: function(item) {
- this.assign(item, 'getStringValue(' + item + ')');
+ this.assign(item, 'getStringValue(' + item + ',text)');
},
ensureSafeAssignContext: function(item) {
@@ -23888,10 +23160,6 @@ ASTInterpreter.prototype = {
return function(scope) {
return context ? {value: scope} : scope;
};
- case AST.LocalsExpression:
- return function(scope, locals) {
- return context ? {value: locals} : locals;
- };
case AST.NGValueParameter:
return function(scope, locals, assign, inputs) {
return context ? {value: assign} : assign;
@@ -24056,11 +23324,8 @@ ASTInterpreter.prototype = {
rhs = right(scope, locals, assign, inputs);
rhs = getStringValue(rhs);
ensureSafeMemberName(rhs, expression);
- if (create && create !== 1) {
- ensureSafeAssignContext(lhs);
- if (lhs && !(lhs[rhs])) {
- lhs[rhs] = {};
- }
+ if (create && create !== 1 && lhs && !(lhs[rhs])) {
+ lhs[rhs] = {};
}
value = lhs[rhs];
ensureSafeObject(value, expression);
@@ -24075,11 +23340,8 @@ ASTInterpreter.prototype = {
nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
return function(scope, locals, assign, inputs) {
var lhs = left(scope, locals, assign, inputs);
- if (create && create !== 1) {
- ensureSafeAssignContext(lhs);
- if (lhs && !(lhs[right])) {
- lhs[right] = {};
- }
+ if (create && create !== 1 && lhs && !(lhs[right])) {
+ lhs[right] = {};
}
var value = lhs != null ? lhs[right] : undefined;
if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
@@ -24120,6 +23382,9 @@ Parser.prototype = {
}
};
+var getterFnCacheDefault = createMap();
+var getterFnCacheExpensive = createMap();
+
function isPossiblyDangerousMemberName(name) {
return name == 'constructor';
}
@@ -24195,19 +23460,10 @@ function $ParseProvider() {
csp: noUnsafeEval,
expensiveChecks: true
};
- var runningChecksEnabled = false;
- $parse.$$runningExpensiveChecks = function() {
- return runningChecksEnabled;
- };
-
- return $parse;
-
- function $parse(exp, interceptorFn, expensiveChecks) {
+ return function $parse(exp, interceptorFn, expensiveChecks) {
var parsedExpression, oneTime, cacheKey;
- expensiveChecks = expensiveChecks || runningChecksEnabled;
-
switch (typeof exp) {
case 'string':
exp = exp.trim();
@@ -24233,9 +23489,6 @@ function $ParseProvider() {
} else if (parsedExpression.inputs) {
parsedExpression.$$watchDelegate = inputsWatchDelegate;
}
- if (expensiveChecks) {
- parsedExpression = expensiveChecksInterceptor(parsedExpression);
- }
cache[cacheKey] = parsedExpression;
}
return addInterceptor(parsedExpression, interceptorFn);
@@ -24244,33 +23497,9 @@ function $ParseProvider() {
return addInterceptor(exp, interceptorFn);
default:
- return addInterceptor(noop, interceptorFn);
- }
- }
-
- function expensiveChecksInterceptor(fn) {
- if (!fn) return fn;
- expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate;
- expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign);
- expensiveCheckFn.constant = fn.constant;
- expensiveCheckFn.literal = fn.literal;
- for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) {
- fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]);
+ return noop;
}
- expensiveCheckFn.inputs = fn.inputs;
-
- return expensiveCheckFn;
-
- function expensiveCheckFn(scope, locals, assign, inputs) {
- var expensiveCheckOldValue = runningChecksEnabled;
- runningChecksEnabled = true;
- try {
- return fn(scope, locals, assign, inputs);
- } finally {
- runningChecksEnabled = expensiveCheckOldValue;
- }
- }
- }
+ };
function expressionInputDirtyCheck(newValue, oldValueOfValue) {
@@ -24387,9 +23616,13 @@ function $ParseProvider() {
function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
var unwatch;
return unwatch = scope.$watch(function constantWatch(scope) {
- unwatch();
return parsedExpression(scope);
- }, listener, objectEquality);
+ }, function constantListener(value, old, scope) {
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ unwatch();
+ }, objectEquality);
}
function addInterceptor(parsedExpression, interceptorFn) {
@@ -24482,7 +23715,7 @@ function $ParseProvider() {
*
* Note: progress/notify callbacks are not currently supported via the ES6-style interface.
*
- * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise.
+ * Note: unlike ES6 behaviour, an exception thrown in the constructor function will NOT implicitly reject the promise.
*
* However, the more traditional CommonJS-style usage is still available, and documented below.
*
@@ -24672,6 +23905,18 @@ function $$QProvider() {
*/
function qFactory(nextTick, exceptionHandler) {
var $qMinErr = minErr('$q', TypeError);
+ function callOnce(self, resolveFn, rejectFn) {
+ var called = false;
+ function wrap(fn) {
+ return function(value) {
+ if (called) return;
+ called = true;
+ fn.call(self, value);
+ };
+ }
+
+ return [wrap(resolveFn), wrap(rejectFn)];
+ }
/**
* @ngdoc method
@@ -24684,12 +23929,7 @@ function qFactory(nextTick, exceptionHandler) {
* @returns {Deferred} Returns a new instance of deferred.
*/
var defer = function() {
- var d = new Deferred();
- //Necessary to support unbound execution :/
- d.resolve = simpleBind(d, d.resolve);
- d.reject = simpleBind(d, d.reject);
- d.notify = simpleBind(d, d.notify);
- return d;
+ return new Deferred();
};
function Promise() {
@@ -24762,6 +24002,10 @@ function qFactory(nextTick, exceptionHandler) {
function Deferred() {
this.promise = new Promise();
+ //Necessary to support unbound execution :/
+ this.resolve = simpleBind(this, this.resolve);
+ this.reject = simpleBind(this, this.reject);
+ this.notify = simpleBind(this, this.notify);
}
extend(Deferred.prototype, {
@@ -24779,34 +24023,23 @@ function qFactory(nextTick, exceptionHandler) {
},
$$resolve: function(val) {
- var then;
- var that = this;
- var done = false;
+ var then, fns;
+
+ fns = callOnce(this, this.$$resolve, this.$$reject);
try {
if ((isObject(val) || isFunction(val))) then = val && val.then;
if (isFunction(then)) {
this.promise.$$state.status = -1;
- then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify));
+ then.call(val, fns[0], fns[1], this.notify);
} else {
this.promise.$$state.value = val;
this.promise.$$state.status = 1;
scheduleProcessQueue(this.promise.$$state);
}
} catch (e) {
- rejectPromise(e);
+ fns[1](e);
exceptionHandler(e);
}
-
- function resolvePromise(val) {
- if (done) return;
- done = true;
- that.$$resolve(val);
- }
- function rejectPromise(val) {
- if (done) return;
- done = true;
- that.$$reject(val);
- }
},
reject: function(reason) {
@@ -24995,6 +24228,11 @@ function qFactory(nextTick, exceptionHandler) {
throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
}
+ if (!(this instanceof Q)) {
+ // More useful when $Q is the Promise itself.
+ return new Q(resolver);
+ }
+
var deferred = new Deferred();
function resolveFn(value) {
@@ -25010,10 +24248,6 @@ function qFactory(nextTick, exceptionHandler) {
return deferred.promise;
};
- // Let's make the instanceof operator work for promises, so that
- // `new $q(fn) instanceof $q` would evaluate to true.
- $Q.prototype = Promise.prototype;
-
$Q.defer = defer;
$Q.reject = reject;
$Q.when = when;
@@ -25147,8 +24381,8 @@ function $RootScopeProvider() {
return ChildScope;
}
- this.$get = ['$exceptionHandler', '$parse', '$browser',
- function($exceptionHandler, $parse, $browser) {
+ this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
+ function($injector, $exceptionHandler, $parse, $browser) {
function destroyChildScope($event) {
$event.currentScope.$$destroyed = true;
@@ -25432,7 +24666,7 @@ function $RootScopeProvider() {
* - `newVal` contains the current value of the `watchExpression`
* - `oldVal` contains the previous value of the `watchExpression`
* - `scope` refers to the current scope
- * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of
+ * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
* comparing for reference equality.
* @returns {function()} Returns a deregistration function for this listener.
*/
@@ -25797,7 +25031,7 @@ function $RootScopeProvider() {
*
*/
$digest: function() {
- var watch, value, last, fn, get,
+ var watch, value, last,
watchers,
length,
dirty, ttl = TTL,
@@ -25843,8 +25077,7 @@ function $RootScopeProvider() {
// Most common watches are on primitives, in which case we can short
// circuit it with === operator, only when === fails do we use .equals
if (watch) {
- get = watch.get;
- if ((value = get(current)) !== (last = watch.last) &&
+ if ((value = watch.get(current)) !== (last = watch.last) &&
!(watch.eq
? equals(value, last)
: (typeof value === 'number' && typeof last === 'number'
@@ -25852,8 +25085,7 @@ function $RootScopeProvider() {
dirty = true;
lastDirtyWatch = watch;
watch.last = watch.eq ? copy(value, null) : value;
- fn = watch.fn;
- fn(value, ((last === initWatchVal) ? value : last), current);
+ watch.fn(value, ((last === initWatchVal) ? value : last), current);
if (ttl < 5) {
logIdx = 4 - ttl;
if (!watchLog[logIdx]) watchLog[logIdx] = [];
@@ -26053,7 +25285,7 @@ function $RootScopeProvider() {
});
}
- asyncQueue.push({scope: this, expression: $parse(expr), locals: locals});
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
},
$$postDigest: function(fn) {
@@ -26145,7 +25377,6 @@ function $RootScopeProvider() {
$applyAsync: function(expr) {
var scope = this;
expr && applyAsyncQueue.push($applyAsyncExpression);
- expr = $parse(expr);
scheduleApplyAsync();
function $applyAsyncExpression() {
@@ -26421,21 +25652,6 @@ function $RootScopeProvider() {
}
/**
- * @ngdoc service
- * @name $rootElement
- *
- * @description
- * The root element of Angular application. This is either the element where {@link
- * ng.directive:ngApp ngApp} was declared or the element passed into
- * {@link angular.bootstrap}. The element represents the root element of application. It is also the
- * location where the application's {@link auto.$injector $injector} service gets
- * published, and can be retrieved using `$rootElement.injector()`.
- */
-
-
-// the implementation is in angular.bootstrap
-
-/**
* @description
* Private service to sanitize uris for links and images. Used by $compile and $sanitize.
*/
@@ -26649,15 +25865,13 @@ function $SceDelegateProvider() {
* @kind function
*
* @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
*
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
*
- * <div class="alert alert-warning">
- * **Note:** an empty whitelist array will block all URLs!
- * </div>
+ * Note: **an empty whitelist array will block all URLs**!
*
* @return {Array} the currently set whitelist array.
*
@@ -26680,17 +25894,17 @@ function $SceDelegateProvider() {
* @kind function
*
* @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
*
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
*
- * The typical usage for the blacklist is to **block
- * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
- * these would otherwise be trusted but actually return content from the redirected domain.
+ * The typical usage for the blacklist is to **block
+ * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
+ * these would otherwise be trusted but actually return content from the redirected domain.
*
- * Finally, **the blacklist overrides the whitelist** and has the final say.
+ * Finally, **the blacklist overrides the whitelist** and has the final say.
*
* @return {Array} the currently set blacklist array.
*
@@ -26849,11 +26063,6 @@ function $SceDelegateProvider() {
* returns the originally supplied value if the queried context type is a supertype of the
* created type. If this condition isn't satisfied, throws an exception.
*
- * <div class="alert alert-danger">
- * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting
- * (XSS) vulnerability in your application.
- * </div>
- *
* @param {string} type The kind of context in which this value is to be used.
* @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
* `$sceDelegate.trustAs`} call.
@@ -27661,63 +26870,26 @@ function $SnifferProvider() {
var $compileMinErr = minErr('$compile');
/**
- * @ngdoc provider
- * @name $templateRequestProvider
+ * @ngdoc service
+ * @name $templateRequest
+ *
* @description
- * Used to configure the options passed to the {@link $http} service when making a template request.
+ * The `$templateRequest` service runs security checks then downloads the provided template using
+ * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
+ * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
+ * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
+ * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
+ * when `tpl` is of type string and `$templateCache` has the matching entry.
+ *
+ * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
+ * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
+ *
+ * @return {Promise} a promise for the HTTP response data of the given URL.
*
- * For example, it can be used for specifying the "Accept" header that is sent to the server, when
- * requesting a template.
+ * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
*/
function $TemplateRequestProvider() {
-
- var httpOptions;
-
- /**
- * @ngdoc method
- * @name $templateRequestProvider#httpOptions
- * @description
- * The options to be passed to the {@link $http} service when making the request.
- * You can use this to override options such as the "Accept" header for template requests.
- *
- * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the
- * options if not overridden here.
- *
- * @param {string=} value new value for the {@link $http} options.
- * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter.
- */
- this.httpOptions = function(val) {
- if (val) {
- httpOptions = val;
- return this;
- }
- return httpOptions;
- };
-
- /**
- * @ngdoc service
- * @name $templateRequest
- *
- * @description
- * The `$templateRequest` service runs security checks then downloads the provided template using
- * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
- * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
- * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
- * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
- * when `tpl` is of type string and `$templateCache` has the matching entry.
- *
- * If you want to pass custom options to the `$http` service, such as setting the Accept header you
- * can configure this via {@link $templateRequestProvider#httpOptions}.
- *
- * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
- * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
- *
- * @return {Promise} a promise for the HTTP response data of the given URL.
- *
- * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
- */
this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
-
function handleRequestFn(tpl, ignoreRequestError) {
handleRequestFn.totalPendingRequests++;
@@ -27740,10 +26912,12 @@ function $TemplateRequestProvider() {
transformResponse = null;
}
- return $http.get(tpl, extend({
- cache: $templateCache,
- transformResponse: transformResponse
- }, httpOptions))
+ var httpOptions = {
+ cache: $templateCache,
+ transformResponse: transformResponse
+ };
+
+ return $http.get(tpl, httpOptions)
['finally'](function() {
handleRequestFn.totalPendingRequests--;
})
@@ -27914,8 +27088,8 @@ function $TimeoutProvider() {
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
* @param {...*=} Pass additional parameters to the executed function.
- * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise
- * will be resolved with the return value of the `fn` function.
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
+ * promise will be resolved with is the return value of the `fn` function.
*
*/
function timeout(fn, delay, invokeApply) {
@@ -28591,10 +27765,6 @@ function getTypeForFilter(val) {
return (val === null) ? 'null' : typeof val;
}
-var MAX_DIGITS = 22;
-var DECIMAL_SEP = '.';
-var ZERO_CHAR = '0';
-
/**
* @ngdoc filter
* @name currency
@@ -28684,7 +27854,7 @@ function currencyFilter($locale) {
* @param {(number|string)=} fractionSize Number of decimal places to round the number to.
* If this is not provided then the fraction size is computed from the current locale's number
* formatting pattern. In the case of the default locale, it will be 3.
- * @returns {string} Number rounded to fractionSize and places a “,†after each third digit.
+ * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit.
*
* @example
<example module="numberFilterExample">
@@ -28719,6 +27889,8 @@ function currencyFilter($locale) {
</file>
</example>
*/
+
+
numberFilter.$inject = ['$locale'];
function numberFilter($locale) {
var formats = $locale.NUMBER_FORMATS;
@@ -28732,194 +27904,93 @@ function numberFilter($locale) {
};
}
-/**
- * Parse a number (as a string) into three components that can be used
- * for formatting the number.
- *
- * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)
- *
- * @param {string} numStr The number to parse
- * @return {object} An object describing this number, containing the following keys:
- * - d : an array of digits containing leading zeros as necessary
- * - i : the number of the digits in `d` that are to the left of the decimal point
- * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
- *
- */
-function parse(numStr) {
- var exponent = 0, digits, numberOfIntegerDigits;
- var i, j, zeros;
-
- // Decimal point?
- if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
- numStr = numStr.replace(DECIMAL_SEP, '');
- }
+var DECIMAL_SEP = '.';
+function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
+ if (isObject(number)) return '';
- // Exponential form?
- if ((i = numStr.search(/e/i)) > 0) {
- // Work out the exponent.
- if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
- numberOfIntegerDigits += +numStr.slice(i + 1);
- numStr = numStr.substring(0, i);
- } else if (numberOfIntegerDigits < 0) {
- // There was no decimal point or exponent so it is an integer.
- numberOfIntegerDigits = numStr.length;
- }
+ var isNegative = number < 0;
+ number = Math.abs(number);
- // Count the number of leading zeros.
- for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++);
+ var isInfinity = number === Infinity;
+ if (!isInfinity && !isFinite(number)) return '';
- if (i == (zeros = numStr.length)) {
- // The digits are all zero.
- digits = [0];
- numberOfIntegerDigits = 1;
- } else {
- // Count the number of trailing zeros
- zeros--;
- while (numStr.charAt(zeros) == ZERO_CHAR) zeros--;
+ var numStr = number + '',
+ formatedText = '',
+ hasExponent = false,
+ parts = [];
- // Trailing zeros are insignificant so ignore them
- numberOfIntegerDigits -= i;
- digits = [];
- // Convert string to array of digits without leading/trailing zeros.
- for (j = 0; i <= zeros; i++, j++) {
- digits[j] = +numStr.charAt(i);
- }
- }
+ if (isInfinity) formatedText = '\u221e';
- // If the number overflows the maximum allowed digits then use an exponent.
- if (numberOfIntegerDigits > MAX_DIGITS) {
- digits = digits.splice(0, MAX_DIGITS - 1);
- exponent = numberOfIntegerDigits - 1;
- numberOfIntegerDigits = 1;
- }
-
- return { d: digits, e: exponent, i: numberOfIntegerDigits };
-}
-
-/**
- * Round the parsed number to the specified number of decimal places
- * This function changed the parsedNumber in-place
- */
-function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
- var digits = parsedNumber.d;
- var fractionLen = digits.length - parsedNumber.i;
-
- // determine fractionSize if it is not specified; `+fractionSize` converts it to a number
- fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
-
- // The index of the digit to where rounding is to occur
- var roundAt = fractionSize + parsedNumber.i;
- var digit = digits[roundAt];
-
- if (roundAt > 0) {
- digits.splice(roundAt);
+ if (!isInfinity && numStr.indexOf('e') !== -1) {
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
+ number = 0;
} else {
- // We rounded to zero so reset the parsedNumber
- parsedNumber.i = 1;
- digits.length = roundAt = fractionSize + 1;
- for (var i=0; i < roundAt; i++) digits[i] = 0;
+ formatedText = numStr;
+ hasExponent = true;
}
+ }
- if (digit >= 5) digits[roundAt - 1]++;
-
- // Pad out with zeros to get the required fraction length
- for (; fractionLen < fractionSize; fractionLen++) digits.push(0);
-
+ if (!isInfinity && !hasExponent) {
+ var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
- // Do any carrying, e.g. a digit was rounded up to 10
- var carry = digits.reduceRight(function(carry, d, i, digits) {
- d = d + carry;
- digits[i] = d % 10;
- return Math.floor(d / 10);
- }, 0);
- if (carry) {
- digits.unshift(carry);
- parsedNumber.i++;
+ // determine fractionSize if it is not specified
+ if (isUndefined(fractionSize)) {
+ fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
}
-}
-/**
- * Format a number into a string
- * @param {number} number The number to format
- * @param {{
- * minFrac, // the minimum number of digits required in the fraction part of the number
- * maxFrac, // the maximum number of digits required in the fraction part of the number
- * gSize, // number of digits in each group of separated digits
- * lgSize, // number of digits in the last group of digits before the decimal separator
- * negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
- * posPre, // the string to go in front of a positive number
- * negSuf, // the string to go after a negative number (e.g. `)`)
- * posSuf // the string to go after a positive number
- * }} pattern
- * @param {string} groupSep The string to separate groups of number (e.g. `,`)
- * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
- * @param {[type]} fractionSize The size of the fractional part of the number
- * @return {string} The number formatted as a string
- */
-function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
+ // inspired by:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
- if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
+ var fraction = ('' + number).split(DECIMAL_SEP);
+ var whole = fraction[0];
+ fraction = fraction[1] || '';
- var isInfinity = !isFinite(number);
- var isZero = false;
- var numStr = Math.abs(number) + '',
- formattedText = '',
- parsedNumber;
+ var i, pos = 0,
+ lgroup = pattern.lgSize,
+ group = pattern.gSize;
- if (isInfinity) {
- formattedText = '\u221e';
- } else {
- parsedNumber = parse(numStr);
-
- roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
-
- var digits = parsedNumber.d;
- var integerLen = parsedNumber.i;
- var exponent = parsedNumber.e;
- var decimals = [];
- isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);
-
- // pad zeros for small numbers
- while (integerLen < 0) {
- digits.unshift(0);
- integerLen++;
- }
-
- // extract decimals digits
- if (integerLen > 0) {
- decimals = digits.splice(integerLen);
- } else {
- decimals = digits;
- digits = [0];
+ if (whole.length >= (lgroup + group)) {
+ pos = whole.length - lgroup;
+ for (i = 0; i < pos; i++) {
+ if ((pos - i) % group === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
}
- // format the integer digits with grouping separators
- var groups = [];
- if (digits.length > pattern.lgSize) {
- groups.unshift(digits.splice(-pattern.lgSize).join(''));
- }
- while (digits.length > pattern.gSize) {
- groups.unshift(digits.splice(-pattern.gSize).join(''));
- }
- if (digits.length) {
- groups.unshift(digits.join(''));
+ for (i = pos; i < whole.length; i++) {
+ if ((whole.length - i) % lgroup === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
}
- formattedText = groups.join(groupSep);
- // append the decimal digits
- if (decimals.length) {
- formattedText += decimalSep + decimals.join('');
+ // format fraction part.
+ while (fraction.length < fractionSize) {
+ fraction += '0';
}
- if (exponent) {
- formattedText += 'e+' + exponent;
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
+ } else {
+ if (fractionSize > 0 && number < 1) {
+ formatedText = number.toFixed(fractionSize);
+ number = parseFloat(formatedText);
+ formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
}
}
- if (number < 0 && !isZero) {
- return pattern.negPre + formattedText + pattern.negSuf;
- } else {
- return pattern.posPre + formattedText + pattern.posSuf;
+
+ if (number === 0) {
+ isNegative = false;
}
+
+ parts.push(isNegative ? pattern.negPre : pattern.posPre,
+ formatedText,
+ isNegative ? pattern.negSuf : pattern.posSuf);
+ return parts.join('');
}
function padNumber(num, digits, trim) {
@@ -28929,7 +28000,7 @@ function padNumber(num, digits, trim) {
num = -num;
}
num = '' + num;
- while (num.length < digits) num = ZERO_CHAR + num;
+ while (num.length < digits) num = '0' + num;
if (trim) {
num = num.substr(num.length - digits);
}
@@ -29198,13 +28269,13 @@ function dateFilter($locale) {
var dateTimezoneOffset = date.getTimezoneOffset();
if (timezone) {
- dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
+ dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
date = convertTimezoneToLocal(date, timezone, true);
}
forEach(parts, function(value) {
fn = DATE_FORMATS[value];
text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
- : value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
+ : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
});
return text;
@@ -29408,9 +28479,8 @@ function limitToFilter() {
* Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
* for strings and numerically for numbers. Note: if you notice numbers are not being sorted
* as expected, make sure they are actually being saved as numbers and not strings.
- * Array-like values (e.g. NodeLists, jQuery objects, TypedArrays, Strings, etc) are also supported.
*
- * @param {Array} array The array (or array-like object) to sort.
+ * @param {Array} array The array to sort.
* @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
* used by the comparator to determine the order of elements.
*
@@ -29441,6 +28511,17 @@ function limitToFilter() {
* `reverse` is not set, which means it defaults to `false`.
<example module="orderByExample">
<file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ }]);
+ </script>
<div ng-controller="ExampleController">
<table class="friend">
<tr>
@@ -29456,17 +28537,6 @@ function limitToFilter() {
</table>
</div>
</file>
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- }]);
- </file>
</example>
*
* The predicate and reverse parameters can be controlled dynamically through scope properties,
@@ -29474,24 +28544,49 @@ function limitToFilter() {
* @example
<example module="orderByExample">
<file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ $scope.predicate = 'age';
+ $scope.reverse = true;
+ $scope.order = function(predicate) {
+ $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
+ $scope.predicate = predicate;
+ };
+ }]);
+ </script>
+ <style type="text/css">
+ .sortorder:after {
+ content: '\25b2';
+ }
+ .sortorder.reverse:after {
+ content: '\25bc';
+ }
+ </style>
<div ng-controller="ExampleController">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
- <button ng-click="predicate=''">Set to unsorted</button>
+ [ <a href="" ng-click="predicate=''">unsorted</a> ]
<table class="friend">
<tr>
- <th>
- <button ng-click="order('name')">Name</button>
- <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('phone')">Phone Number</button>
- <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('age')">Age</button>
- <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
- </th>
+ <th>
+ <a href="" ng-click="order('name')">Name</a>
+ <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
+ </th>
+ <th>
+ <a href="" ng-click="order('phone')">Phone Number</a>
+ <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
+ </th>
+ <th>
+ <a href="" ng-click="order('age')">Age</a>
+ <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
+ </th>
</tr>
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
<td>{{friend.name}}</td>
@@ -29501,31 +28596,6 @@ function limitToFilter() {
</table>
</div>
</file>
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- $scope.predicate = 'age';
- $scope.reverse = true;
- $scope.order = function(predicate) {
- $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
- $scope.predicate = predicate;
- };
- }]);
- </file>
- <file name="style.css">
- .sortorder:after {
- content: '\25b2';
- }
- .sortorder.reverse:after {
- content: '\25bc';
- }
- </file>
</example>
*
* It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
@@ -29537,30 +28607,21 @@ function limitToFilter() {
* @example
<example module="orderByExample">
<file name="index.html">
- <div ng-controller="ExampleController">
- <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
- <table class="friend">
- <tr>
- <th>
- <button ng-click="order('name')">Name</button>
- <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('phone')">Phone Number</button>
- <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('age')">Age</button>
- <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
- </th>
- </tr>
- <tr ng-repeat="friend in friends">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
</file>
<file name="script.js">
@@ -29574,33 +28635,19 @@ function limitToFilter() {
{ name: 'Adam', phone: '555-5678', age: 35 },
{ name: 'Julie', phone: '555-8765', age: 29 }
];
- $scope.order = function(predicate) {
- $scope.predicate = predicate;
- $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
- $scope.friends = orderBy($scope.friends, predicate, $scope.reverse);
+ $scope.order = function(predicate, reverse) {
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
};
- $scope.order('age', true);
+ $scope.order('-age',false);
}]);
</file>
-
- <file name="style.css">
- .sortorder:after {
- content: '\25b2';
- }
- .sortorder.reverse:after {
- content: '\25bc';
- }
- </file>
</example>
*/
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse) {
return function(array, sortPredicate, reverseOrder) {
- if (array == null) return array;
- if (!isArrayLike(array)) {
- throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array);
- }
+ if (!(isArrayLike(array))) return array;
if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
if (sortPredicate.length === 0) { sortPredicate = ['+']; }
@@ -29923,7 +28970,20 @@ var htmlAnchorDirective = valueFn({
* {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
*
* A special directive is necessary because we cannot use interpolation inside the `disabled`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
+ * attribute. The following example would make the button enabled on Chrome/Firefox
+ * but not on older IEs:
+ *
+ * ```html
+ * <!-- See below for an example of ng-disabled being used correctly -->
+ * <div ng-init="isDisabled = false">
+ * <button disabled="{{isDisabled}}">Disabled</button>
+ * </div>
+ * ```
+ *
+ * This is because the HTML specification does not require browsers to preserve the values of
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
*
* @example
<example>
@@ -29958,9 +29018,15 @@ var htmlAnchorDirective = valueFn({
* Note that this directive should not be used together with {@link ngModel `ngModel`},
* as this can lead to unexpected behavior.
*
- * A special directive is necessary because we cannot use interpolation inside the `checked`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
+ * ### Why do we need `ngChecked`?
*
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as checked. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngChecked` directive solves this problem for the `checked` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
* @example
<example>
<file name="index.html">
@@ -29989,12 +29055,13 @@ var htmlAnchorDirective = valueFn({
* @priority 100
*
* @description
- *
- * Sets the `readOnly` attribute on the element, if the expression inside `ngReadonly` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `readOnly`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as readonly. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngReadonly` directive solves this problem for the `readonly` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
* @example
<example>
<file name="index.html">
@@ -30023,11 +29090,13 @@ var htmlAnchorDirective = valueFn({
* @priority 100
*
* @description
- *
- * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `selected`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as selected. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngSelected` directive solves this problem for the `selected` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
*
* @example
<example>
@@ -30059,12 +29128,13 @@ var htmlAnchorDirective = valueFn({
* @priority 100
*
* @description
- *
- * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `open`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as open. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngOpen` directive solves this problem for the `open` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
* @example
<example>
<file name="index.html">
@@ -30310,7 +29380,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
*
* However, if the method is used programmatically, for example by adding dynamically created controls,
* or controls that have been previously removed without destroying their corresponding DOM element,
- * it's the developers responsibility to make sure the current state propagates to the parent form.
+ * it's the developers responsiblity to make sure the current state propagates to the parent form.
*
* For example, if an input control is added that is already `$dirty` and has `$error` properties,
* calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
@@ -30520,9 +29590,13 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
*
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
- * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
- * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
- * of controls needs to be determined.
+ * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
+ * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
+ * using Angular validation directives in forms that are dynamically generated using the
+ * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
+ * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
+ * `ngForm` directive and nest these in an outer `form` element.
+ *
*
* # CSS classes
* - `ng-valid` is set if the form is valid.
@@ -30743,18 +29817,7 @@ var ngFormDirective = formDirectiveFactory(true);
// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
-// Note: We are being more lenient, because browsers are too.
-// 1. Scheme
-// 2. Slashes
-// 3. Username
-// 4. Password
-// 5. Hostname
-// 6. Port
-// 7. Path
-// 8. Query
-// 9. Fragment
-// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999
-var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i;
+var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
@@ -30787,8 +29850,8 @@ var inputType = {
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
* that contains the regular expression body that will be converted to a regular expression
* as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -31075,7 +30138,7 @@ var inputType = {
*
* @description
* Input with time validation and transformation. In browsers that do not yet support
- * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
* local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
* Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
*
@@ -31422,8 +30485,8 @@ var inputType = {
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
* that contains the regular expression body that will be converted to a regular expression
* as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -31520,8 +30583,8 @@ var inputType = {
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
* that contains the regular expression body that will be converted to a regular expression
* as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -31619,8 +30682,8 @@ var inputType = {
* @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
* that contains the regular expression body that will be converted to a regular expression
* as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -32080,7 +31143,11 @@ function badInputChecker(scope, element, attr, ctrl) {
if (nativeValidation) {
ctrl.$parsers.push(function(value) {
var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
- return validity.badInput || validity.typeMismatch ? undefined : value;
+ // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
+ // - also sets validity.badInput (should only be validity.typeMismatch).
+ // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
+ // - can ignore this case as we can still read out the erroneous email...
+ return validity.badInput && !validity.typeMismatch ? undefined : value;
});
}
}
@@ -32252,8 +31319,8 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
* length.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -32291,8 +31358,8 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
* length.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * value does not match a RegExp found by evaluating the Angular expression given in the attribute value.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp
* after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
@@ -33518,7 +32585,7 @@ var ngControllerDirective = [function() {
*
* * no-inline-style: this stops Angular from injecting CSS styles into the DOM
*
- * * no-unsafe-eval: this stops Angular from optimizing $parse with unsafe eval of strings
+ * * no-unsafe-eval: this stops Angular from optimising $parse with unsafe eval of strings
*
* You can use these values in the following combinations:
*
@@ -33535,7 +32602,7 @@ var ngControllerDirective = [function() {
* inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
*
* * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
- * run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
+ * run eval - no automcatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
*
* * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
* styles nor use eval, which is the same as an empty: ng-csp.
@@ -34514,8 +33581,6 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
//set the 2nd param to true to ignore the template request error so that the inner
//contents and scope can be cleaned up.
$templateRequest(src, true).then(function(response) {
- if (scope.$$destroyed) return;
-
if (thisChangeId !== changeCounter) return;
var newScope = scope.$new();
ctrl.template = response;
@@ -34537,8 +33602,6 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
currentScope.$emit('$includeContentLoaded', src);
scope.$eval(onloadExp);
}, function() {
- if (scope.$$destroyed) return;
-
if (thisChangeId === changeCounter) {
cleanupLastIncludeContent();
scope.$emit('$includeContentError', src);
@@ -34567,7 +33630,7 @@ var ngIncludeFillContentDirective = ['$compile',
priority: -400,
require: 'ngInclude',
link: function(scope, $element, $attr, ctrl) {
- if (toString.call($element[0]).match(/SVG/)) {
+ if (/SVG/.test($element[0].toString())) {
// WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
// support innerHTML, so detect this here and try to generate the contents
// specially.
@@ -34796,9 +33859,7 @@ var VALID_CLASS = 'ng-valid',
DIRTY_CLASS = 'ng-dirty',
UNTOUCHED_CLASS = 'ng-untouched',
TOUCHED_CLASS = 'ng-touched',
- PENDING_CLASS = 'ng-pending',
- EMPTY_CLASS = 'ng-empty',
- NOT_EMPTY_CLASS = 'ng-not-empty';
+ PENDING_CLASS = 'ng-pending';
var ngModelMinErr = minErr('ngModel');
@@ -35102,17 +34163,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
return isUndefined(value) || value === '' || value === null || value !== value;
};
- this.$$updateEmptyClasses = function(value) {
- if (ctrl.$isEmpty(value)) {
- $animate.removeClass($element, NOT_EMPTY_CLASS);
- $animate.addClass($element, EMPTY_CLASS);
- } else {
- $animate.removeClass($element, EMPTY_CLASS);
- $animate.addClass($element, NOT_EMPTY_CLASS);
- }
- };
-
-
var currentValidationRunId = 0;
/**
@@ -35230,14 +34280,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* which may be caused by a pending debounced event or because the input is waiting for a some
* future event.
*
- * If you have an input that uses `ng-model-options` to set up debounced updates or updates that
- * depend on special events such as blur, you can have a situation where there is a period when
- * the `$viewValue` is out of sync with the ngModel's `$modelValue`.
- *
- * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update
- * and reset the input to the last committed view value.
+ * If you have an input that uses `ng-model-options` to set up debounced events or events such
+ * as blur you can have a situation where there is a period when the `$viewValue`
+ * is out of synch with the ngModel's `$modelValue`.
*
- * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue`
+ * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
* programmatically before these debounced/future events have resolved/occurred, because Angular's
* dirty checking mechanism is not able to tell whether the model has actually changed or not.
*
@@ -35250,63 +34297,39 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* angular.module('cancel-update-example', [])
*
* .controller('CancelUpdateController', ['$scope', function($scope) {
- * $scope.model = {};
- *
- * $scope.setEmpty = function(e, value, rollback) {
+ * $scope.resetWithCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myForm.myInput1.$rollbackViewValue();
+ * $scope.myValue = '';
+ * }
+ * };
+ * $scope.resetWithoutCancel = function(e) {
* if (e.keyCode == 27) {
- * e.preventDefault();
- * if (rollback) {
- * $scope.myForm[value].$rollbackViewValue();
- * }
- * $scope.model[value] = '';
+ * $scope.myValue = '';
* }
* };
* }]);
* </file>
* <file name="index.html">
* <div ng-controller="CancelUpdateController">
- * <p>Both of these inputs are only updated if they are blurred. Hitting escape should
- * empty them. Follow these steps and observe the difference:</p>
- * <ol>
- * <li>Type something in the input. You will see that the model is not yet updated</li>
- * <li>Press the Escape key.
- * <ol>
- * <li> In the first example, nothing happens, because the model is already '', and no
- * update is detected. If you blur the input, the model will be set to the current view.
- * </li>
- * <li> In the second example, the pending update is cancelled, and the input is set back
- * to the last committed view value (''). Blurring the input does nothing.
- * </li>
- * </ol>
- * </li>
- * </ol>
+ * <p>Try typing something in each input. See that the model only updates when you
+ * blur off the input.
+ * </p>
+ * <p>Now see what happens if you start typing then press the Escape key</p>
*
* <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
- * <div>
- * <p id="inputDescription1">Without $rollbackViewValue():</p>
- * <input name="value1" aria-describedby="inputDescription1" ng-model="model.value1"
- * ng-keydown="setEmpty($event, 'value1')">
- * value1: "{{ model.value1 }}"
- * </div>
- *
- * <div>
- * <p id="inputDescription2">With $rollbackViewValue():</p>
- * <input name="value2" aria-describedby="inputDescription2" ng-model="model.value2"
- * ng-keydown="setEmpty($event, 'value2', true)">
- * value2: "{{ model.value2 }}"
- * </div>
+ * <p id="inputDescription1">With $rollbackViewValue()</p>
+ * <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue"
+ * ng-keydown="resetWithCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ *
+ * <p id="inputDescription2">Without $rollbackViewValue()</p>
+ * <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue"
+ * ng-keydown="resetWithoutCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
* </form>
* </div>
* </file>
- <file name="style.css">
- div {
- display: table-cell;
- }
- div:nth-child(1) {
- padding-right: 30px;
- }
-
- </file>
* </example>
*/
this.$rollbackViewValue = function() {
@@ -35420,7 +34443,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
forEach(ctrl.$asyncValidators, function(validator, name) {
var promise = validator(modelValue, viewValue);
if (!isPromiseLike(promise)) {
- throw ngModelMinErr('nopromise',
+ throw ngModelMinErr("$asyncValidators",
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
}
setValidity(name, undefined);
@@ -35476,7 +34499,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
return;
}
- ctrl.$$updateEmptyClasses(viewValue);
ctrl.$$lastCommittedViewValue = viewValue;
// change to dirty
@@ -35575,7 +34597,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* However, custom controls might also pass objects to this method. In this case, we should make
* a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
* perform a deep watch of objects, it only looks for a change of identity. If you only change
- * the property of the object then ngModel will not realize that the object has changed and
+ * the property of the object then ngModel will not realise that the object has changed and
* will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
* not change properties of the copy once it has been passed to `$setViewValue`.
* Otherwise you may cause the model value on the scope to change incorrectly.
@@ -35659,7 +34681,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
viewValue = formatters[idx](viewValue);
}
if (ctrl.$viewValue !== viewValue) {
- ctrl.$$updateEmptyClasses(viewValue);
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
ctrl.$render();
@@ -35690,8 +34711,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* require.
* - Providing validation behavior (i.e. required, number, email, url).
* - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
- * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,
- * `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations.
+ * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
* - Registering the control with its parent {@link ng.directive:form form}.
*
* Note: `ngModel` will try to bind to the property given by evaluating the expression on the
@@ -35719,22 +34739,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* - {@link ng.directive:select select}
* - {@link ng.directive:textarea textarea}
*
- * # Complex Models (objects or collections)
- *
- * By default, `ngModel` watches the model by reference, not value. This is important to know when
- * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the
- * object or collection change, `ngModel` will not be notified and so the input will not be re-rendered.
- *
- * The model must be assigned an entirely new object or collection before a re-rendering will occur.
- *
- * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression
- * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or
- * if the select is given the `multiple` attribute.
- *
- * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the
- * first level of the object (or only changing the properties of an item in the collection if it's an array) will still
- * not trigger a re-rendering of the model.
- *
* # CSS classes
* The following CSS classes are added and removed on the associated input/select/textarea element
* depending on the validity of the model.
@@ -35748,16 +34752,13 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* - `ng-touched`: the control has been blurred
* - `ng-untouched`: the control hasn't been blurred
* - `ng-pending`: any `$asyncValidators` are unfulfilled
- * - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined
- * by the {@link ngModel.NgModelController#$isEmpty} method
- * - `ng-not-empty`: the view contains a non-empty value
*
* Keep in mind that ngAnimate can detect each of these classes when added and removed.
*
* ## Animation Hooks
*
* Animations within models are triggered when any of the associated CSS classes are added and removed
- * on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`,
+ * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
* `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
* The animations that are triggered within ngModel are similar to how they work in ngClass and
* animations can be hooked into using CSS transitions, keyframes as well as JS animations.
@@ -36650,10 +35651,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
var optionTemplate = document.createElement('option'),
optGroupTemplate = document.createElement('optgroup');
+
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
- var selectCtrl = ctrls[0];
+ // if ngModel is not defined, we don't need to do anything
var ngModelCtrl = ctrls[1];
+ if (!ngModelCtrl) return;
+
+ var selectCtrl = ctrls[0];
var multiple = attr.multiple;
// The emptyOption allows the application developer to provide their own custom "empty"
@@ -36884,7 +35889,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
(current === emptyOption_ ||
current === unknownOption_ ||
current.nodeType === NODE_TYPE_COMMENT ||
- (nodeName_(current) === 'option' && current.value === ''))) {
+ current.value === '')) {
current = current.nextSibling;
}
}
@@ -36913,7 +35918,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
var groupElement;
var optionElement;
- if (isDefined(option.group)) {
+ if (option.group) {
// This option is to live in a group
// See if we have already created this group
@@ -36974,8 +35979,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// Check to see if the value has changed due to the update to the options
if (!ngModelCtrl.$isEmpty(previousValue)) {
var nextValue = selectCtrl.readValue();
- var isNotPrimitive = ngOptions.trackBy || multiple;
- if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
+ if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
ngModelCtrl.$setViewValue(nextValue);
ngModelCtrl.$render();
}
@@ -36987,7 +35991,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
return {
restrict: 'A',
terminal: true,
- require: ['select', 'ngModel'],
+ require: ['select', '?ngModel'],
link: {
pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
// Deactivate the SelectController.register method to prevent
@@ -37215,7 +36219,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
}
// If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
- // In JS `NaN !== NaN`, so we have to explicitly check.
+ // In JS `NaN !== NaN`, so we have to exlicitly check.
if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
watchRemover();
var whenExpFn = whensExpFns[count];
@@ -37332,7 +36336,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
* by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
* will not have to rebuild the DOM elements for items it has already rendered, even if the
* JavaScript objects in the collection have been substituted for new ones. For large collections,
- * this significantly improves rendering performance. If you don't have a unique identifier,
+ * this signifincantly improves rendering performance. If you don't have a unique identifier,
* `track by $index` can also provide a performance boost.
* </div>
* ```html
@@ -37409,8 +36413,6 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
*
* **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
*
- * See the example below for defining CSS animations with ngRepeat.
- *
* @element ANY
* @scope
* @priority 1000
@@ -37463,11 +36465,22 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
* For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
*
* @example
- * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed
- * results by name. New (entering) and removed (leaving) items are animated.
- <example module="ngRepeat" name="ngRepeat" deps="angular-animate.js" animations="true">
+ * This example initializes the scope to a list of names and
+ * then uses `ngRepeat` to display every person:
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
<file name="index.html">
- <div ng-controller="repeatController">
+ <div ng-init="friends = [
+ {name:'John', age:25, gender:'boy'},
+ {name:'Jessie', age:30, gender:'girl'},
+ {name:'Johanna', age:28, gender:'girl'},
+ {name:'Joy', age:15, gender:'girl'},
+ {name:'Mary', age:28, gender:'girl'},
+ {name:'Peter', age:95, gender:'boy'},
+ {name:'Sebastian', age:50, gender:'boy'},
+ {name:'Erika', age:27, gender:'girl'},
+ {name:'Patrick', age:40, gender:'boy'},
+ {name:'Samantha', age:60, gender:'girl'}
+ ]">
I have {{friends.length}} friends. They are:
<input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
<ul class="example-animate-container">
@@ -37480,22 +36493,6 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
</ul>
</div>
</file>
- <file name="script.js">
- angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
- $scope.friends = [
- {name:'John', age:25, gender:'boy'},
- {name:'Jessie', age:30, gender:'girl'},
- {name:'Johanna', age:28, gender:'girl'},
- {name:'Joy', age:15, gender:'girl'},
- {name:'Mary', age:28, gender:'girl'},
- {name:'Peter', age:95, gender:'boy'},
- {name:'Sebastian', age:50, gender:'boy'},
- {name:'Erika', age:27, gender:'girl'},
- {name:'Patrick', age:40, gender:'boy'},
- {name:'Samantha', age:60, gender:'girl'}
- ];
- });
- </file>
<file name="animations.css">
.example-animate-container {
background:white;
@@ -37506,7 +36503,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
}
.animate-repeat {
- line-height:30px;
+ line-height:40px;
list-style:none;
box-sizing:border-box;
}
@@ -37528,7 +36525,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
.animate-repeat.ng-move.ng-move-active,
.animate-repeat.ng-enter.ng-enter-active {
opacity:1;
- max-height:30px;
+ max-height:40px;
}
</file>
<file name="protractor.js" type="protractor">
@@ -38385,186 +37382,67 @@ var ngSwitchDefaultDirective = ngDirective({
* @description
* Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
*
- * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name
- * as the value of the `ng-transclude` or `ng-transclude-slot` attribute.
- *
- * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing
- * content of this element will be removed before the transcluded content is inserted.
- * If the transcluded content is empty, the existing content is left intact. This lets you provide fallback content in the case
- * that no transcluded content is provided.
+ * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
*
* @element ANY
*
- * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty
- * or its value is the same as the name of the attribute then the default slot is used.
- *
* @example
- * ### Basic transclusion
- * This example demonstrates basic transclusion of content into a component directive.
- * <example name="simpleTranscludeExample" module="transcludeExample">
- * <file name="index.html">
- * <script>
- * angular.module('transcludeExample', [])
- * .directive('pane', function(){
- * return {
- * restrict: 'E',
- * transclude: true,
- * scope: { title:'@' },
- * template: '<div style="border: 1px solid black;">' +
- * '<div style="background-color: gray">{{title}}</div>' +
- * '<ng-transclude></ng-transclude>' +
- * '</div>'
- * };
- * })
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.title = 'Lorem Ipsum';
- * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <input ng-model="title" aria-label="title"> <br/>
- * <textarea ng-model="text" aria-label="text"></textarea> <br/>
- * <pane title="{{title}}">{{text}}</pane>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have transcluded', function() {
- * var titleElement = element(by.model('title'));
- * titleElement.clear();
- * titleElement.sendKeys('TITLE');
- * var textElement = element(by.model('text'));
- * textElement.clear();
- * textElement.sendKeys('TEXT');
- * expect(element(by.binding('title')).getText()).toEqual('TITLE');
- * expect(element(by.binding('text')).getText()).toEqual('TEXT');
- * });
- * </file>
- * </example>
- *
- * @example
- * ### Transclude fallback content
- * This example shows how to use `NgTransclude` with fallback content, that
- * is displayed if no transcluded content is provided.
- *
- * <example module="transcludeFallbackContentExample">
- * <file name="index.html">
- * <script>
- * angular.module('transcludeFallbackContentExample', [])
- * .directive('myButton', function(){
- * return {
- * restrict: 'E',
- * transclude: true,
- * scope: true,
- * template: '<button style="cursor: pointer;">' +
- * '<ng-transclude>' +
- * '<b style="color: red;">Button1</b>' +
- * '</ng-transclude>' +
- * '</button>'
- * };
- * });
- * </script>
- * <!-- fallback button content -->
- * <my-button id="fallback"></my-button>
- * <!-- modified button content -->
- * <my-button id="modified">
- * <i style="color: green;">Button2</i>
- * </my-button>
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have different transclude element content', function() {
- * expect(element(by.id('fallback')).getText()).toBe('Button1');
- * expect(element(by.id('modified')).getText()).toBe('Button2');
- * });
- * </file>
- * </example>
+ <example module="transcludeExample">
+ <file name="index.html">
+ <script>
+ angular.module('transcludeExample', [])
+ .directive('pane', function(){
+ return {
+ restrict: 'E',
+ transclude: true,
+ scope: { title:'@' },
+ template: '<div style="border: 1px solid black;">' +
+ '<div style="background-color: gray">{{title}}</div>' +
+ '<ng-transclude></ng-transclude>' +
+ '</div>'
+ };
+ })
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.title = 'Lorem Ipsum';
+ $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input ng-model="title" aria-label="title"> <br/>
+ <textarea ng-model="text" aria-label="text"></textarea> <br/>
+ <pane title="{{title}}">{{text}}</pane>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should have transcluded', function() {
+ var titleElement = element(by.model('title'));
+ titleElement.clear();
+ titleElement.sendKeys('TITLE');
+ var textElement = element(by.model('text'));
+ textElement.clear();
+ textElement.sendKeys('TEXT');
+ expect(element(by.binding('title')).getText()).toEqual('TITLE');
+ expect(element(by.binding('text')).getText()).toEqual('TEXT');
+ });
+ </file>
+ </example>
*
- * @example
- * ### Multi-slot transclusion
- * This example demonstrates using multi-slot transclusion in a component directive.
- * <example name="multiSlotTranscludeExample" module="multiSlotTranscludeExample">
- * <file name="index.html">
- * <style>
- * .title, .footer {
- * background-color: gray
- * }
- * </style>
- * <div ng-controller="ExampleController">
- * <input ng-model="title" aria-label="title"> <br/>
- * <textarea ng-model="text" aria-label="text"></textarea> <br/>
- * <pane>
- * <pane-title><a ng-href="{{link}}">{{title}}</a></pane-title>
- * <pane-body><p>{{text}}</p></pane-body>
- * </pane>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('multiSlotTranscludeExample', [])
- * .directive('pane', function(){
- * return {
- * restrict: 'E',
- * transclude: {
- * 'title': '?paneTitle',
- * 'body': 'paneBody',
- * 'footer': '?paneFooter'
- * },
- * template: '<div style="border: 1px solid black;">' +
- * '<div class="title" ng-transclude="title">Fallback Title</div>' +
- * '<div ng-transclude="body"></div>' +
- * '<div class="footer" ng-transclude="footer">Fallback Footer</div>' +
- * '</div>'
- * };
- * })
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.title = 'Lorem Ipsum';
- * $scope.link = "https://google.com";
- * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- * }]);
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have transcluded the title and the body', function() {
- * var titleElement = element(by.model('title'));
- * titleElement.clear();
- * titleElement.sendKeys('TITLE');
- * var textElement = element(by.model('text'));
- * textElement.clear();
- * textElement.sendKeys('TEXT');
- * expect(element(by.css('.title')).getText()).toEqual('TITLE');
- * expect(element(by.binding('text')).getText()).toEqual('TEXT');
- * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer');
- * });
- * </file>
- * </example>
*/
-var ngTranscludeMinErr = minErr('ngTransclude');
var ngTranscludeDirective = ngDirective({
restrict: 'EAC',
link: function($scope, $element, $attrs, controller, $transclude) {
-
- if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {
- // If the attribute is of the form: `ng-transclude="ng-transclude"`
- // then treat it like the default
- $attrs.ngTransclude = '';
- }
-
- function ngTranscludeCloneAttachFn(clone) {
- if (clone.length) {
- $element.empty();
- $element.append(clone);
- }
- }
-
if (!$transclude) {
- throw ngTranscludeMinErr('orphan',
+ throw minErr('ngTransclude')('orphan',
'Illegal use of ngTransclude directive in the template! ' +
'No parent directive that requires a transclusion found. ' +
'Element: {0}',
startingTag($element));
}
- // If there is no slot name defined or the slot name is not optional
- // then transclude the slot
- var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
- $transclude(ngTranscludeCloneAttachFn, null, slotName);
+ $transclude(function(clone) {
+ $element.empty();
+ $element.append(clone);
+ });
}
});
@@ -38696,9 +37574,6 @@ var SelectController =
// Tell the select control that an option, with the given value, has been added
self.addOption = function(value, element) {
- // Skip comment nodes, as they only pollute the `optionsMap`
- if (element[0].nodeType === NODE_TYPE_COMMENT) return;
-
assertNotHasOwnProperty(value, '"option value"');
if (value === '') {
self.emptyOption = element;
@@ -38773,7 +37648,7 @@ var SelectController =
*
* The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
* between the scope and the `<select>` control (including setting default values).
- * It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
+ * ÃŒt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
* {@link ngOptions `ngOptions`} directives.
*
* When an item in the `<select>` menu is selected, the value of the selected option will be bound
@@ -38783,7 +37658,7 @@ var SelectController =
*
* <div class="alert alert-warning">
* Note that the value of a `select` directive used without `ngOptions` is always a string.
- * When the model needs to be bound to a non-string value, you must either explicitly convert it
+ * When the model needs to be bound to a non-string value, you must either explictly convert it
* using a directive (see example below) or use `ngOptions` to specify the set of options.
* This is because an option element can only be bound to string values at present.
* </div>
@@ -38975,8 +37850,7 @@ var selectDirective = function() {
controller: SelectController,
priority: 1,
link: {
- pre: selectPreLink,
- post: selectPostLink
+ pre: selectPreLink
}
};
@@ -38990,6 +37864,13 @@ var selectDirective = function() {
selectCtrl.ngModelCtrl = ngModelCtrl;
+ // We delegate rendering to the `writeValue` method, which can be changed
+ // if the select can have multiple selected values or if the options are being
+ // generated by `ngOptions`
+ ngModelCtrl.$render = function() {
+ selectCtrl.writeValue(ngModelCtrl.$viewValue);
+ };
+
// When the selected item(s) changes we delegate getting the value of the select control
// to the `readValue` method, which can be changed if the select can have multiple
// selected values or if the options are being generated by `ngOptions`
@@ -39043,23 +37924,6 @@ var selectDirective = function() {
}
}
-
- function selectPostLink(scope, element, attrs, ctrls) {
- // if ngModel is not defined, we don't need to do anything
- var ngModelCtrl = ctrls[1];
- if (!ngModelCtrl) return;
-
- var selectCtrl = ctrls[0];
-
- // We delegate rendering to the `writeValue` method, which can be changed
- // if the select can have multiple selected values or if the options are being
- // generated by `ngOptions`.
- // This must be done in the postLink fn to prevent $render to be called before
- // all nodes have been linked correctly.
- ngModelCtrl.$render = function() {
- selectCtrl.writeValue(ngModelCtrl.$viewValue);
- };
- }
};
@@ -39071,6 +37935,7 @@ var optionDirective = ['$interpolate', function($interpolate) {
restrict: 'E',
priority: 100,
compile: function(element, attr) {
+
if (isDefined(attr.value)) {
// If the value attribute is defined, check if it contains an interpolation
var interpolateValueFn = $interpolate(attr.value, true);
@@ -39084,6 +37949,7 @@ var optionDirective = ['$interpolate', function($interpolate) {
}
return function(scope, element, attr) {
+
// This is an optimization over using ^^ since we don't want to have to search
// all the way to the root of the DOM for every single option element
var selectCtrlName = '$selectController',
@@ -39104,64 +37970,6 @@ var styleDirective = valueFn({
terminal: false
});
-/**
- * @ngdoc directive
- * @name ngRequired
- *
- * @description
- *
- * ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be
- * applied to custom controls.
- *
- * The directive sets the `required` attribute on the element if the Angular expression inside
- * `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we
- * cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}
- * for more info.
- *
- * The validator will set the `required` error key to true if the `required` attribute is set and
- * calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the
- * {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the
- * `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing
- * custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.
- *
- * @example
- * <example name="ngRequiredDirective" module="ngRequiredExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngRequiredExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.required = true;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="required">Toggle required: </label>
- * <input type="checkbox" ng-model="required" id="required" />
- * <br>
- * <label for="input">This input must be filled if `required` is true: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-required="required" /><br>
- * <hr>
- * required error set? = <code>{{form.input.$error.required}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var required = element(by.binding('form.input.$error.required'));
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should set the required error', function() {
- expect(required.getText()).toContain('true');
-
- input.sendKeys('123');
- expect(required.getText()).not.toContain('true');
- expect(model.getText()).toContain('123');
- });
- * </file>
- * </example>
- */
var requiredDirective = function() {
return {
restrict: 'A',
@@ -39181,81 +37989,7 @@ var requiredDirective = function() {
};
};
-/**
- * @ngdoc directive
- * @name ngPattern
- *
- * @description
- *
- * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * does not match a RegExp which is obtained by evaluating the Angular expression given in the
- * `ngPattern` attribute value:
- * * If the expression evaluates to a RegExp object, then this is used directly.
- * * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it
- * in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
- *
- * <div class="alert alert-info">
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * </div>
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `pattern` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is
- * not available.
- * </li>
- * <li>
- * The `ngPattern` attribute must be an expression, while the `pattern` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngPatternDirective" module="ngPatternExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngPatternExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.regex = '\\d+';
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="regex">Set a pattern (regex string): </label>
- * <input type="text" ng-model="regex" id="regex" />
- * <br>
- * <label for="input">This input is restricted by the current pattern: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-pattern="regex" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default pattern', function() {
- input.sendKeys('aaa');
- expect(model.getText()).not.toContain('aaa');
- input.clear().then(function() {
- input.sendKeys('123');
- expect(model.getText()).toContain('123');
- });
- });
- * </file>
- * </example>
- */
var patternDirective = function() {
return {
restrict: 'A',
@@ -39287,72 +38021,7 @@ var patternDirective = function() {
};
};
-/**
- * @ngdoc directive
- * @name ngMaxlength
- *
- * @description
- *
- * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * is longer than the integer obtained by evaluating the Angular expression given in the
- * `ngMaxlength` attribute value.
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint
- * validation is not available.
- * </li>
- * <li>
- * The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngMaxlengthDirective" module="ngMaxlengthExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngMaxlengthExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.maxlength = 5;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="maxlength">Set a maxlength: </label>
- * <input type="number" ng-model="maxlength" id="maxlength" />
- * <br>
- * <label for="input">This input is restricted by the current maxlength: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-maxlength="maxlength" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default maxlength', function() {
- input.sendKeys('abcdef');
- expect(model.getText()).not.toContain('abcdef');
- input.clear().then(function() {
- input.sendKeys('abcde');
- expect(model.getText()).toContain('abcde');
- });
- });
- * </file>
- * </example>
- */
var maxlengthDirective = function() {
return {
restrict: 'A',
@@ -39373,70 +38042,6 @@ var maxlengthDirective = function() {
};
};
-/**
- * @ngdoc directive
- * @name ngMinlength
- *
- * @description
- *
- * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * is shorter than the integer obtained by evaluating the Angular expression given in the
- * `ngMinlength` attribute value.
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `minlength` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint
- * validation is not available.
- * </li>
- * <li>
- * The `ngMinlength` value must be an expression, while the `minlength` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngMinlengthDirective" module="ngMinlengthExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngMinlengthExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.minlength = 3;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="minlength">Set a minlength: </label>
- * <input type="number" ng-model="minlength" id="minlength" />
- * <br>
- * <label for="input">This input is restricted by the current minlength: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-minlength="minlength" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default minlength', function() {
- input.sendKeys('ab');
- expect(model.getText()).not.toContain('ab');
-
- input.sendKeys('abc');
- expect(model.getText()).toContain('abc');
- });
- * </file>
- * </example>
- */
var minlengthDirective = function() {
return {
restrict: 'A',
@@ -39549,20 +38154,6 @@ $provide.value("$locale", {
"Nov",
"Dec"
],
- "STANDALONEMONTH": [
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- ],
"WEEKENDRANGE": [
5,
6
@@ -39606,7 +38197,6 @@ $provide.value("$locale", {
]
},
"id": "en-us",
- "localeID": "en_US",
"pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.js
new file mode 100644
index 00000000..f622e943
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.js
@@ -0,0 +1,628 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {'use strict';
+
+/**
+ * @ngdoc module
+ * @name ngTouch
+ * @description
+ *
+ * # ngTouch
+ *
+ * The `ngTouch` module provides touch events and other helpers for touch-enabled devices.
+ * The implementation is based on jQuery Mobile touch event handling
+ * ([jquerymobile.com](http://jquerymobile.com/)).
+ *
+ *
+ * See {@link ngTouch.$swipe `$swipe`} for usage.
+ *
+ * <div doc-module-components="ngTouch"></div>
+ *
+ */
+
+// define ngTouch module
+/* global -ngTouch */
+var ngTouch = angular.module('ngTouch', []);
+
+function nodeName_(element) {
+ return angular.lowercase(element.nodeName || (element[0] && element[0].nodeName));
+}
+
+/* global ngTouch: false */
+
+ /**
+ * @ngdoc service
+ * @name $swipe
+ *
+ * @description
+ * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe
+ * behavior, to make implementing swipe-related directives more convenient.
+ *
+ * Requires the {@link ngTouch `ngTouch`} module to be installed.
+ *
+ * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by
+ * `ngCarousel` in a separate component.
+ *
+ * # Usage
+ * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
+ * which is to be watched for swipes, and an object with four handler functions. See the
+ * documentation for `bind` below.
+ */
+
+ngTouch.factory('$swipe', [function() {
+ // The total distance in any direction before we make the call on swipe vs. scroll.
+ var MOVE_BUFFER_RADIUS = 10;
+
+ var POINTER_EVENTS = {
+ 'mouse': {
+ start: 'mousedown',
+ move: 'mousemove',
+ end: 'mouseup'
+ },
+ 'touch': {
+ start: 'touchstart',
+ move: 'touchmove',
+ end: 'touchend',
+ cancel: 'touchcancel'
+ }
+ };
+
+ function getCoordinates(event) {
+ var originalEvent = event.originalEvent || event;
+ var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
+ var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];
+
+ return {
+ x: e.clientX,
+ y: e.clientY
+ };
+ }
+
+ function getEvents(pointerTypes, eventType) {
+ var res = [];
+ angular.forEach(pointerTypes, function(pointerType) {
+ var eventName = POINTER_EVENTS[pointerType][eventType];
+ if (eventName) {
+ res.push(eventName);
+ }
+ });
+ return res.join(' ');
+ }
+
+ return {
+ /**
+ * @ngdoc method
+ * @name $swipe#bind
+ *
+ * @description
+ * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
+ * object containing event handlers.
+ * The pointer types that should be used can be specified via the optional
+ * third argument, which is an array of strings `'mouse'` and `'touch'`. By default,
+ * `$swipe` will listen for `mouse` and `touch` events.
+ *
+ * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
+ * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
+ * `event`. `cancel` receives the raw `event` as its single parameter.
+ *
+ * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
+ * watching for `touchmove` or `mousemove` events. These events are ignored until the total
+ * distance moved in either dimension exceeds a small threshold.
+ *
+ * Once this threshold is exceeded, either the horizontal or vertical delta is greater.
+ * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.
+ * - If the vertical distance is greater, this is a scroll, and we let the browser take over.
+ * A `cancel` event is sent.
+ *
+ * `move` is called on `mousemove` and `touchmove` after the above logic has determined that
+ * a swipe is in progress.
+ *
+ * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.
+ *
+ * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling
+ * as described above.
+ *
+ */
+ bind: function(element, eventHandlers, pointerTypes) {
+ // Absolute total movement, used to control swipe vs. scroll.
+ var totalX, totalY;
+ // Coordinates of the start position.
+ var startCoords;
+ // Last event's position.
+ var lastPos;
+ // Whether a swipe is active.
+ var active = false;
+
+ pointerTypes = pointerTypes || ['mouse', 'touch'];
+ element.on(getEvents(pointerTypes, 'start'), function(event) {
+ startCoords = getCoordinates(event);
+ active = true;
+ totalX = 0;
+ totalY = 0;
+ lastPos = startCoords;
+ eventHandlers['start'] && eventHandlers['start'](startCoords, event);
+ });
+ var events = getEvents(pointerTypes, 'cancel');
+ if (events) {
+ element.on(events, function(event) {
+ active = false;
+ eventHandlers['cancel'] && eventHandlers['cancel'](event);
+ });
+ }
+
+ element.on(getEvents(pointerTypes, 'move'), function(event) {
+ if (!active) return;
+
+ // Android will send a touchcancel if it thinks we're starting to scroll.
+ // So when the total distance (+ or - or both) exceeds 10px in either direction,
+ // we either:
+ // - On totalX > totalY, we send preventDefault() and treat this as a swipe.
+ // - On totalY > totalX, we let the browser handle it as a scroll.
+
+ if (!startCoords) return;
+ var coords = getCoordinates(event);
+
+ totalX += Math.abs(coords.x - lastPos.x);
+ totalY += Math.abs(coords.y - lastPos.y);
+
+ lastPos = coords;
+
+ if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
+ return;
+ }
+
+ // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.
+ if (totalY > totalX) {
+ // Allow native scrolling to take over.
+ active = false;
+ eventHandlers['cancel'] && eventHandlers['cancel'](event);
+ return;
+ } else {
+ // Prevent the browser from scrolling.
+ event.preventDefault();
+ eventHandlers['move'] && eventHandlers['move'](coords, event);
+ }
+ });
+
+ element.on(getEvents(pointerTypes, 'end'), function(event) {
+ if (!active) return;
+ active = false;
+ eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
+ });
+ }
+ };
+}]);
+
+/* global ngTouch: false,
+ nodeName_: false
+*/
+
+/**
+ * @ngdoc directive
+ * @name ngClick
+ *
+ * @description
+ * A more powerful replacement for the default ngClick designed to be used on touchscreen
+ * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
+ * the click event. This version handles them immediately, and then prevents the
+ * following click event from propagating.
+ *
+ * Requires the {@link ngTouch `ngTouch`} module to be installed.
+ *
+ * This directive can fall back to using an ordinary click event, and so works on desktop
+ * browsers as well as mobile.
+ *
+ * This directive also sets the CSS class `ng-click-active` while the element is being held
+ * down (by a mouse click or touch) so you can restyle the depressed element if you wish.
+ *
+ * @element ANY
+ * @param {expression} ngClick {@link guide/expression Expression} to evaluate
+ * upon tap. (Event object is available as `$event`)
+ *
+ * @example
+ <example module="ngClickExample" deps="angular-touch.js">
+ <file name="index.html">
+ <button ng-click="count = count + 1" ng-init="count=0">
+ Increment
+ </button>
+ count: {{ count }}
+ </file>
+ <file name="script.js">
+ angular.module('ngClickExample', ['ngTouch']);
+ </file>
+ </example>
+ */
+
+ngTouch.config(['$provide', function($provide) {
+ $provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
+ // drop the default ngClick directive
+ $delegate.shift();
+ return $delegate;
+ }]);
+}]);
+
+ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
+ function($parse, $timeout, $rootElement) {
+ var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
+ var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
+ var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
+ var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
+
+ var ACTIVE_CLASS_NAME = 'ng-click-active';
+ var lastPreventedTime;
+ var touchCoordinates;
+ var lastLabelClickCoordinates;
+
+
+ // TAP EVENTS AND GHOST CLICKS
+ //
+ // Why tap events?
+ // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
+ // double-tapping, and then fire a click event.
+ //
+ // This delay sucks and makes mobile apps feel unresponsive.
+ // So we detect touchstart, touchcancel and touchend ourselves and determine when
+ // the user has tapped on something.
+ //
+ // What happens when the browser then generates a click event?
+ // The browser, of course, also detects the tap and fires a click after a delay. This results in
+ // tapping/clicking twice. We do "clickbusting" to prevent it.
+ //
+ // How does it work?
+ // We attach global touchstart and click handlers, that run during the capture (early) phase.
+ // So the sequence for a tap is:
+ // - global touchstart: Sets an "allowable region" at the point touched.
+ // - element's touchstart: Starts a touch
+ // (- touchcancel ends the touch, no click follows)
+ // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
+ // too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
+ // - preventGhostClick() removes the allowable region the global touchstart created.
+ // - The browser generates a click event.
+ // - The global click handler catches the click, and checks whether it was in an allowable region.
+ // - If preventGhostClick was called, the region will have been removed, the click is busted.
+ // - If the region is still there, the click proceeds normally. Therefore clicks on links and
+ // other elements without ngTap on them work normally.
+ //
+ // This is an ugly, terrible hack!
+ // Yeah, tell me about it. The alternatives are using the slow click events, or making our users
+ // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
+ // encapsulates this ugly logic away from the user.
+ //
+ // Why not just put click handlers on the element?
+ // We do that too, just to be sure. If the tap event caused the DOM to change,
+ // it is possible another element is now in that position. To take account for these possibly
+ // distinct elements, the handlers are global and care only about coordinates.
+
+ // Checks if the coordinates are close enough to be within the region.
+ function hit(x1, y1, x2, y2) {
+ return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
+ }
+
+ // Checks a list of allowable regions against a click location.
+ // Returns true if the click should be allowed.
+ // Splices out the allowable region from the list after it has been used.
+ function checkAllowableRegions(touchCoordinates, x, y) {
+ for (var i = 0; i < touchCoordinates.length; i += 2) {
+ if (hit(touchCoordinates[i], touchCoordinates[i + 1], x, y)) {
+ touchCoordinates.splice(i, i + 2);
+ return true; // allowable region
+ }
+ }
+ return false; // No allowable region; bust it.
+ }
+
+ // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
+ // was called recently.
+ function onClick(event) {
+ if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
+ return; // Too old.
+ }
+
+ var touches = event.touches && event.touches.length ? event.touches : [event];
+ var x = touches[0].clientX;
+ var y = touches[0].clientY;
+ // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
+ // and on the input element). Depending on the exact browser, this second click we don't want
+ // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label
+ // click event
+ if (x < 1 && y < 1) {
+ return; // offscreen
+ }
+ if (lastLabelClickCoordinates &&
+ lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) {
+ return; // input click triggered by label click
+ }
+ // reset label click coordinates on first subsequent click
+ if (lastLabelClickCoordinates) {
+ lastLabelClickCoordinates = null;
+ }
+ // remember label click coordinates to prevent click busting of trigger click event on input
+ if (nodeName_(event.target) === 'label') {
+ lastLabelClickCoordinates = [x, y];
+ }
+
+ // Look for an allowable region containing this click.
+ // If we find one, that means it was created by touchstart and not removed by
+ // preventGhostClick, so we don't bust it.
+ if (checkAllowableRegions(touchCoordinates, x, y)) {
+ return;
+ }
+
+ // If we didn't find an allowable region, bust the click.
+ event.stopPropagation();
+ event.preventDefault();
+
+ // Blur focused form elements
+ event.target && event.target.blur && event.target.blur();
+ }
+
+
+ // Global touchstart handler that creates an allowable region for a click event.
+ // This allowable region can be removed by preventGhostClick if we want to bust it.
+ function onTouchStart(event) {
+ var touches = event.touches && event.touches.length ? event.touches : [event];
+ var x = touches[0].clientX;
+ var y = touches[0].clientY;
+ touchCoordinates.push(x, y);
+
+ $timeout(function() {
+ // Remove the allowable region.
+ for (var i = 0; i < touchCoordinates.length; i += 2) {
+ if (touchCoordinates[i] == x && touchCoordinates[i + 1] == y) {
+ touchCoordinates.splice(i, i + 2);
+ return;
+ }
+ }
+ }, PREVENT_DURATION, false);
+ }
+
+ // On the first call, attaches some event handlers. Then whenever it gets called, it creates a
+ // zone around the touchstart where clicks will get busted.
+ function preventGhostClick(x, y) {
+ if (!touchCoordinates) {
+ $rootElement[0].addEventListener('click', onClick, true);
+ $rootElement[0].addEventListener('touchstart', onTouchStart, true);
+ touchCoordinates = [];
+ }
+
+ lastPreventedTime = Date.now();
+
+ checkAllowableRegions(touchCoordinates, x, y);
+ }
+
+ // Actual linking function.
+ return function(scope, element, attr) {
+ var clickHandler = $parse(attr.ngClick),
+ tapping = false,
+ tapElement, // Used to blur the element after a tap.
+ startTime, // Used to check if the tap was held too long.
+ touchStartX,
+ touchStartY;
+
+ function resetState() {
+ tapping = false;
+ element.removeClass(ACTIVE_CLASS_NAME);
+ }
+
+ element.on('touchstart', function(event) {
+ tapping = true;
+ tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
+ // Hack for Safari, which can target text nodes instead of containers.
+ if (tapElement.nodeType == 3) {
+ tapElement = tapElement.parentNode;
+ }
+
+ element.addClass(ACTIVE_CLASS_NAME);
+
+ startTime = Date.now();
+
+ // Use jQuery originalEvent
+ var originalEvent = event.originalEvent || event;
+ var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
+ var e = touches[0];
+ touchStartX = e.clientX;
+ touchStartY = e.clientY;
+ });
+
+ element.on('touchcancel', function(event) {
+ resetState();
+ });
+
+ element.on('touchend', function(event) {
+ var diff = Date.now() - startTime;
+
+ // Use jQuery originalEvent
+ var originalEvent = event.originalEvent || event;
+ var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
+ originalEvent.changedTouches :
+ ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
+ var e = touches[0];
+ var x = e.clientX;
+ var y = e.clientY;
+ var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));
+
+ if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
+ // Call preventGhostClick so the clickbuster will catch the corresponding click.
+ preventGhostClick(x, y);
+
+ // Blur the focused element (the button, probably) before firing the callback.
+ // This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
+ // I couldn't get anything to work reliably on Android Chrome.
+ if (tapElement) {
+ tapElement.blur();
+ }
+
+ if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
+ element.triggerHandler('click', [event]);
+ }
+ }
+
+ resetState();
+ });
+
+ // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
+ // something else nearby.
+ element.onclick = function(event) { };
+
+ // Actual click handler.
+ // There are three different kinds of clicks, only two of which reach this point.
+ // - On desktop browsers without touch events, their clicks will always come here.
+ // - On mobile browsers, the simulated "fast" click will call this.
+ // - But the browser's follow-up slow click will be "busted" before it reaches this handler.
+ // Therefore it's safe to use this directive on both mobile and desktop.
+ element.on('click', function(event, touchend) {
+ scope.$apply(function() {
+ clickHandler(scope, {$event: (touchend || event)});
+ });
+ });
+
+ element.on('mousedown', function(event) {
+ element.addClass(ACTIVE_CLASS_NAME);
+ });
+
+ element.on('mousemove mouseup', function(event) {
+ element.removeClass(ACTIVE_CLASS_NAME);
+ });
+
+ };
+}]);
+
+/* global ngTouch: false */
+
+/**
+ * @ngdoc directive
+ * @name ngSwipeLeft
+ *
+ * @description
+ * Specify custom behavior when an element is swiped to the left on a touchscreen device.
+ * A leftward swipe is a quick, right-to-left slide of the finger.
+ * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag
+ * too.
+ *
+ * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to
+ * the `ng-swipe-left` or `ng-swipe-right` DOM Element.
+ *
+ * Requires the {@link ngTouch `ngTouch`} module to be installed.
+ *
+ * @element ANY
+ * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate
+ * upon left swipe. (Event object is available as `$event`)
+ *
+ * @example
+ <example module="ngSwipeLeftExample" deps="angular-touch.js">
+ <file name="index.html">
+ <div ng-show="!showActions" ng-swipe-left="showActions = true">
+ Some list content, like an email in the inbox
+ </div>
+ <div ng-show="showActions" ng-swipe-right="showActions = false">
+ <button ng-click="reply()">Reply</button>
+ <button ng-click="delete()">Delete</button>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngSwipeLeftExample', ['ngTouch']);
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSwipeRight
+ *
+ * @description
+ * Specify custom behavior when an element is swiped to the right on a touchscreen device.
+ * A rightward swipe is a quick, left-to-right slide of the finger.
+ * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag
+ * too.
+ *
+ * Requires the {@link ngTouch `ngTouch`} module to be installed.
+ *
+ * @element ANY
+ * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate
+ * upon right swipe. (Event object is available as `$event`)
+ *
+ * @example
+ <example module="ngSwipeRightExample" deps="angular-touch.js">
+ <file name="index.html">
+ <div ng-show="!showActions" ng-swipe-left="showActions = true">
+ Some list content, like an email in the inbox
+ </div>
+ <div ng-show="showActions" ng-swipe-right="showActions = false">
+ <button ng-click="reply()">Reply</button>
+ <button ng-click="delete()">Delete</button>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngSwipeRightExample', ['ngTouch']);
+ </file>
+ </example>
+ */
+
+function makeSwipeDirective(directiveName, direction, eventName) {
+ ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {
+ // The maximum vertical delta for a swipe should be less than 75px.
+ var MAX_VERTICAL_DISTANCE = 75;
+ // Vertical distance should not be more than a fraction of the horizontal distance.
+ var MAX_VERTICAL_RATIO = 0.3;
+ // At least a 30px lateral motion is necessary for a swipe.
+ var MIN_HORIZONTAL_DISTANCE = 30;
+
+ return function(scope, element, attr) {
+ var swipeHandler = $parse(attr[directiveName]);
+
+ var startCoords, valid;
+
+ function validSwipe(coords) {
+ // Check that it's within the coordinates.
+ // Absolute vertical distance must be within tolerances.
+ // Horizontal distance, we take the current X - the starting X.
+ // This is negative for leftward swipes and positive for rightward swipes.
+ // After multiplying by the direction (-1 for left, +1 for right), legal swipes
+ // (ie. same direction as the directive wants) will have a positive delta and
+ // illegal ones a negative delta.
+ // Therefore this delta must be positive, and larger than the minimum.
+ if (!startCoords) return false;
+ var deltaY = Math.abs(coords.y - startCoords.y);
+ var deltaX = (coords.x - startCoords.x) * direction;
+ return valid && // Short circuit for already-invalidated swipes.
+ deltaY < MAX_VERTICAL_DISTANCE &&
+ deltaX > 0 &&
+ deltaX > MIN_HORIZONTAL_DISTANCE &&
+ deltaY / deltaX < MAX_VERTICAL_RATIO;
+ }
+
+ var pointerTypes = ['touch'];
+ if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
+ pointerTypes.push('mouse');
+ }
+ $swipe.bind(element, {
+ 'start': function(coords, event) {
+ startCoords = coords;
+ valid = true;
+ },
+ 'cancel': function(event) {
+ valid = false;
+ },
+ 'end': function(coords, event) {
+ if (validSwipe(coords)) {
+ scope.$apply(function() {
+ element.triggerHandler(eventName);
+ swipeHandler(scope, {$event: event});
+ });
+ }
+ }
+ }, pointerTypes);
+ };
+ }]);
+}
+
+// Left is negative X-coordinate, right is positive.
+makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');
+makeSwipeDirective('ngSwipeRight', 1, 'swiperight');
+
+
+
+})(window, window.angular);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js
new file mode 100644
index 00000000..165fba28
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js
@@ -0,0 +1,13 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(x,s,y){'use strict';function t(f,k,p){n.directive(f,["$parse","$swipe",function(c,e){return function(l,m,g){function h(a){if(!b)return!1;var d=Math.abs(a.y-b.y);a=(a.x-b.x)*k;return r&&75>d&&0<a&&30<a&&.3>d/a}var d=c(g[f]),b,r,a=["touch"];s.isDefined(g.ngSwipeDisableMouse)||a.push("mouse");e.bind(m,{start:function(a,d){b=a;r=!0},cancel:function(a){r=!1},end:function(a,b){h(a)&&l.$apply(function(){m.triggerHandler(p);d(l,{$event:b})})}},a)}}])}var n=s.module("ngTouch",[]);n.factory("$swipe",
+[function(){function f(c){c=c.originalEvent||c;var e=c.touches&&c.touches.length?c.touches:[c];c=c.changedTouches&&c.changedTouches[0]||e[0];return{x:c.clientX,y:c.clientY}}function k(c,e){var l=[];s.forEach(c,function(c){(c=p[c][e])&&l.push(c)});return l.join(" ")}var p={mouse:{start:"mousedown",move:"mousemove",end:"mouseup"},touch:{start:"touchstart",move:"touchmove",end:"touchend",cancel:"touchcancel"}};return{bind:function(c,e,l){var m,g,h,d,b=!1;l=l||["mouse","touch"];c.on(k(l,"start"),function(a){h=
+f(a);b=!0;g=m=0;d=h;e.start&&e.start(h,a)});var r=k(l,"cancel");if(r)c.on(r,function(a){b=!1;e.cancel&&e.cancel(a)});c.on(k(l,"move"),function(a){if(b&&h){var c=f(a);m+=Math.abs(c.x-d.x);g+=Math.abs(c.y-d.y);d=c;10>m&&10>g||(g>m?(b=!1,e.cancel&&e.cancel(a)):(a.preventDefault(),e.move&&e.move(c,a)))}});c.on(k(l,"end"),function(a){b&&(b=!1,e.end&&e.end(f(a),a))})}}}]);n.config(["$provide",function(f){f.decorator("ngClickDirective",["$delegate",function(k){k.shift();return k}])}]);n.directive("ngClick",
+["$parse","$timeout","$rootElement",function(f,k,p){function c(d,b,c){for(var a=0;a<d.length;a+=2){var e=d[a+1],g=c;if(25>Math.abs(d[a]-b)&&25>Math.abs(e-g))return d.splice(a,a+2),!0}return!1}function e(d){if(!(2500<Date.now()-m)){var b=d.touches&&d.touches.length?d.touches:[d],e=b[0].clientX,b=b[0].clientY;if(!(1>e&&1>b||h&&h[0]===e&&h[1]===b)){h&&(h=null);var a=d.target;"label"===s.lowercase(a.nodeName||a[0]&&a[0].nodeName)&&(h=[e,b]);c(g,e,b)||(d.stopPropagation(),d.preventDefault(),d.target&&
+d.target.blur&&d.target.blur())}}}function l(d){d=d.touches&&d.touches.length?d.touches:[d];var b=d[0].clientX,c=d[0].clientY;g.push(b,c);k(function(){for(var a=0;a<g.length;a+=2)if(g[a]==b&&g[a+1]==c){g.splice(a,a+2);break}},2500,!1)}var m,g,h;return function(d,b,h){var a=f(h.ngClick),k=!1,q,n,t,v;b.on("touchstart",function(a){k=!0;q=a.target?a.target:a.srcElement;3==q.nodeType&&(q=q.parentNode);b.addClass("ng-click-active");n=Date.now();a=a.originalEvent||a;a=(a.touches&&a.touches.length?a.touches:
+[a])[0];t=a.clientX;v=a.clientY});b.on("touchcancel",function(a){k=!1;b.removeClass("ng-click-active")});b.on("touchend",function(a){var d=Date.now()-n,f=a.originalEvent||a,u=(f.changedTouches&&f.changedTouches.length?f.changedTouches:f.touches&&f.touches.length?f.touches:[f])[0],f=u.clientX,u=u.clientY,w=Math.sqrt(Math.pow(f-t,2)+Math.pow(u-v,2));k&&750>d&&12>w&&(g||(p[0].addEventListener("click",e,!0),p[0].addEventListener("touchstart",l,!0),g=[]),m=Date.now(),c(g,f,u),q&&q.blur(),s.isDefined(h.disabled)&&
+!1!==h.disabled||b.triggerHandler("click",[a]));k=!1;b.removeClass("ng-click-active")});b.onclick=function(a){};b.on("click",function(b,c){d.$apply(function(){a(d,{$event:c||b})})});b.on("mousedown",function(a){b.addClass("ng-click-active")});b.on("mousemove mouseup",function(a){b.removeClass("ng-click-active")})}}]);t("ngSwipeLeft",-1,"swipeleft");t("ngSwipeRight",1,"swiperight")})(window,window.angular);
+//# sourceMappingURL=angular-touch.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js.map
new file mode 100644
index 00000000..029bd32c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular-touch.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular-touch.min.js",
+"lineCount":12,
+"mappings":"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",
+"sources":["angular-touch.js"],
+"names":["window","angular","undefined","makeSwipeDirective","directiveName","direction","eventName","ngTouch","directive","$parse","$swipe","scope","element","attr","validSwipe","coords","startCoords","deltaY","Math","abs","y","deltaX","x","valid","MAX_VERTICAL_DISTANCE","MIN_HORIZONTAL_DISTANCE","MAX_VERTICAL_RATIO","swipeHandler","pointerTypes","isDefined","push","bind","start","event","cancel","end","$apply","triggerHandler","$event","module","factory","getCoordinates","originalEvent","touches","length","e","changedTouches","clientX","clientY","getEvents","eventType","res","forEach","pointerType","POINTER_EVENTS","join","move","eventHandlers","totalX","totalY","lastPos","active","on","events","MOVE_BUFFER_RADIUS","preventDefault","config","$provide","decorator","$delegate","shift","$timeout","$rootElement","checkAllowableRegions","touchCoordinates","i","CLICKBUSTER_THRESHOLD","x1","y1","y2","splice","onClick","PREVENT_DURATION","Date","now","lastPreventedTime","lastLabelClickCoordinates","target","lowercase","nodeName","stopPropagation","blur","onTouchStart","clickHandler","ngClick","tapping","tapElement","startTime","touchStartX","touchStartY","srcElement","nodeType","parentNode","addClass","ACTIVE_CLASS_NAME","removeClass","diff","dist","sqrt","pow","TAP_DURATION","MOVE_TOLERANCE","addEventListener","disabled","onclick","element.onclick","touchend"]
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.js
new file mode 100644
index 00000000..a3aee7d6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.js
@@ -0,0 +1,29018 @@
+/**
+ * @license AngularJS v1.4.8
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document, undefined) {'use strict';
+
+/**
+ * @description
+ *
+ * This object provides a utility for producing rich Error messages within
+ * Angular. It can be called as follows:
+ *
+ * var exampleMinErr = minErr('example');
+ * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
+ *
+ * The above creates an instance of minErr in the example namespace. The
+ * resulting error will have a namespaced error code of example.one. The
+ * resulting error will replace {0} with the value of foo, and {1} with the
+ * value of bar. The object is not restricted in the number of arguments it can
+ * take.
+ *
+ * If fewer arguments are specified than necessary for interpolation, the extra
+ * interpolation markers will be preserved in the final string.
+ *
+ * Since data will be parsed statically during a build step, some restrictions
+ * are applied with respect to how minErr instances are created and called.
+ * Instances should have names of the form namespaceMinErr for a minErr created
+ * using minErr('namespace') . Error codes, namespaces and template strings
+ * should all be static strings, not variables or general expressions.
+ *
+ * @param {string} module The namespace to use for the new minErr instance.
+ * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
+ * error from returned function, for cases when a particular type of error is useful.
+ * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
+ */
+
+function minErr(module, ErrorConstructor) {
+ ErrorConstructor = ErrorConstructor || Error;
+ return function() {
+ var SKIP_INDEXES = 2;
+
+ var templateArgs = arguments,
+ code = templateArgs[0],
+ message = '[' + (module ? module + ':' : '') + code + '] ',
+ template = templateArgs[1],
+ paramPrefix, i;
+
+ message += template.replace(/\{\d+\}/g, function(match) {
+ var index = +match.slice(1, -1),
+ shiftedIndex = index + SKIP_INDEXES;
+
+ if (shiftedIndex < templateArgs.length) {
+ return toDebugString(templateArgs[shiftedIndex]);
+ }
+
+ return match;
+ });
+
+ message += '\nhttp://errors.angularjs.org/1.4.8/' +
+ (module ? module + '/' : '') + code;
+
+ for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
+ message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
+ encodeURIComponent(toDebugString(templateArgs[i]));
+ }
+
+ return new ErrorConstructor(message);
+ };
+}
+
+/* We need to tell jshint what variables are being exported */
+/* global angular: true,
+ msie: true,
+ jqLite: true,
+ jQuery: true,
+ slice: true,
+ splice: true,
+ push: true,
+ toString: true,
+ ngMinErr: true,
+ angularModule: true,
+ uid: true,
+ REGEX_STRING_REGEXP: true,
+ VALIDITY_STATE_PROPERTY: true,
+
+ lowercase: true,
+ uppercase: true,
+ manualLowercase: true,
+ manualUppercase: true,
+ nodeName_: true,
+ isArrayLike: true,
+ forEach: true,
+ forEachSorted: true,
+ reverseParams: true,
+ nextUid: true,
+ setHashKey: true,
+ extend: true,
+ toInt: true,
+ inherit: true,
+ merge: true,
+ noop: true,
+ identity: true,
+ valueFn: true,
+ isUndefined: true,
+ isDefined: true,
+ isObject: true,
+ isBlankObject: true,
+ isString: true,
+ isNumber: true,
+ isDate: true,
+ isArray: true,
+ isFunction: true,
+ isRegExp: true,
+ isWindow: true,
+ isScope: true,
+ isFile: true,
+ isFormData: true,
+ isBlob: true,
+ isBoolean: true,
+ isPromiseLike: true,
+ trim: true,
+ escapeForRegexp: true,
+ isElement: true,
+ makeMap: true,
+ includes: true,
+ arrayRemove: true,
+ copy: true,
+ shallowCopy: true,
+ equals: true,
+ csp: true,
+ jq: true,
+ concat: true,
+ sliceArgs: true,
+ bind: true,
+ toJsonReplacer: true,
+ toJson: true,
+ fromJson: true,
+ convertTimezoneToLocal: true,
+ timezoneToOffset: true,
+ startingTag: true,
+ tryDecodeURIComponent: true,
+ parseKeyValue: true,
+ toKeyValue: true,
+ encodeUriSegment: true,
+ encodeUriQuery: true,
+ angularInit: true,
+ bootstrap: true,
+ getTestability: true,
+ snake_case: true,
+ bindJQuery: true,
+ assertArg: true,
+ assertArgFn: true,
+ assertNotHasOwnProperty: true,
+ getter: true,
+ getBlockNodes: true,
+ hasOwnProperty: true,
+ createMap: true,
+
+ NODE_TYPE_ELEMENT: true,
+ NODE_TYPE_ATTRIBUTE: true,
+ NODE_TYPE_TEXT: true,
+ NODE_TYPE_COMMENT: true,
+ NODE_TYPE_DOCUMENT: true,
+ NODE_TYPE_DOCUMENT_FRAGMENT: true,
+*/
+
+////////////////////////////////////
+
+/**
+ * @ngdoc module
+ * @name ng
+ * @module ng
+ * @description
+ *
+ * # ng (core module)
+ * The ng module is loaded by default when an AngularJS application is started. The module itself
+ * contains the essential components for an AngularJS application to function. The table below
+ * lists a high level breakdown of each of the services/factories, filters, directives and testing
+ * components available within this core module.
+ *
+ * <div doc-module-components="ng"></div>
+ */
+
+var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
+
+// The name of a form control's ValidityState property.
+// This is used so that it's possible for internal tests to create mock ValidityStates.
+var VALIDITY_STATE_PROPERTY = 'validity';
+
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @module ng
+ * @kind function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
+var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
+
+
+var manualLowercase = function(s) {
+ /* jshint bitwise: false */
+ return isString(s)
+ ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
+ : s;
+};
+var manualUppercase = function(s) {
+ /* jshint bitwise: false */
+ return isString(s)
+ ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
+ : s;
+};
+
+
+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
+// with correct but slower alternatives.
+if ('i' !== 'I'.toLowerCase()) {
+ lowercase = manualLowercase;
+ uppercase = manualUppercase;
+}
+
+
+var
+ msie, // holds major version number for IE, or NaN if UA is not IE.
+ jqLite, // delay binding since jQuery could be loaded after us.
+ jQuery, // delay binding
+ slice = [].slice,
+ splice = [].splice,
+ push = [].push,
+ toString = Object.prototype.toString,
+ getPrototypeOf = Object.getPrototypeOf,
+ ngMinErr = minErr('ng'),
+
+ /** @name angular */
+ angular = window.angular || (window.angular = {}),
+ angularModule,
+ uid = 0;
+
+/**
+ * documentMode is an IE-only property
+ * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
+ */
+msie = document.documentMode;
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
+ * String ...)
+ */
+function isArrayLike(obj) {
+
+ // `null`, `undefined` and `window` are not array-like
+ if (obj == null || isWindow(obj)) return false;
+
+ // arrays, strings and jQuery/jqLite objects are array like
+ // * jqLite is either the jQuery or jqLite constructor function
+ // * we have to check the existance of jqLite first as this method is called
+ // via the forEach method when constructing the jqLite object in the first place
+ if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // "length" in obj used to prevent JIT error (gh-11508)
+ var length = "length" in Object(obj) && obj.length;
+
+ // NodeList objects (with `item` method) and
+ // other objects with suitable length characteristics are array-like
+ return isNumber(length) &&
+ (length >= 0 && (length - 1) in obj || typeof obj.item == 'function');
+}
+
+/**
+ * @ngdoc function
+ * @name angular.forEach
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+ * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
+ * is the value of an object property or an array element, `key` is the object property key or
+ * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
+ *
+ * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
+ * using the `hasOwnProperty` method.
+ *
+ * Unlike ES262's
+ * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
+ * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
+ * return the value provided.
+ *
+ ```js
+ var values = {name: 'misko', gender: 'male'};
+ var log = [];
+ angular.forEach(values, function(value, key) {
+ this.push(key + ': ' + value);
+ }, log);
+ expect(log).toEqual(['name: misko', 'gender: male']);
+ ```
+ *
+ * @param {Object|Array} obj Object to iterate over.
+ * @param {Function} iterator Iterator function.
+ * @param {Object=} context Object to become context (`this`) for the iterator function.
+ * @returns {Object|Array} Reference to `obj`.
+ */
+
+function forEach(obj, iterator, context) {
+ var key, length;
+ if (obj) {
+ if (isFunction(obj)) {
+ for (key in obj) {
+ // Need to check if hasOwnProperty exists,
+ // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
+ if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (isArray(obj) || isArrayLike(obj)) {
+ var isPrimitive = typeof obj !== 'object';
+ for (key = 0, length = obj.length; key < length; key++) {
+ if (isPrimitive || key in obj) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else if (obj.forEach && obj.forEach !== forEach) {
+ obj.forEach(iterator, context, obj);
+ } else if (isBlankObject(obj)) {
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
+ for (key in obj) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ } else if (typeof obj.hasOwnProperty === 'function') {
+ // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ } else {
+ // Slow path for objects which do not have a method `hasOwnProperty`
+ for (key in obj) {
+ if (hasOwnProperty.call(obj, key)) {
+ iterator.call(context, obj[key], key, obj);
+ }
+ }
+ }
+ }
+ return obj;
+}
+
+function forEachSorted(obj, iterator, context) {
+ var keys = Object.keys(obj).sort();
+ for (var i = 0; i < keys.length; i++) {
+ iterator.call(context, obj[keys[i]], keys[i]);
+ }
+ return keys;
+}
+
+
+/**
+ * when using forEach the params are value, key, but it is often useful to have key, value.
+ * @param {function(string, *)} iteratorFn
+ * @returns {function(*, string)}
+ */
+function reverseParams(iteratorFn) {
+ return function(value, key) { iteratorFn(key, value); };
+}
+
+/**
+ * A consistent way of creating unique IDs in angular.
+ *
+ * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
+ * we hit number precision issues in JavaScript.
+ *
+ * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
+ *
+ * @returns {number} an unique alpha-numeric string
+ */
+function nextUid() {
+ return ++uid;
+}
+
+
+/**
+ * Set or clear the hashkey for an object.
+ * @param obj object
+ * @param h the hashkey (!truthy to delete the hashkey)
+ */
+function setHashKey(obj, h) {
+ if (h) {
+ obj.$$hashKey = h;
+ } else {
+ delete obj.$$hashKey;
+ }
+}
+
+
+function baseExtend(dst, objs, deep) {
+ var h = dst.$$hashKey;
+
+ for (var i = 0, ii = objs.length; i < ii; ++i) {
+ var obj = objs[i];
+ if (!isObject(obj) && !isFunction(obj)) continue;
+ var keys = Object.keys(obj);
+ for (var j = 0, jj = keys.length; j < jj; j++) {
+ var key = keys[j];
+ var src = obj[key];
+
+ if (deep && isObject(src)) {
+ if (isDate(src)) {
+ dst[key] = new Date(src.valueOf());
+ } else if (isRegExp(src)) {
+ dst[key] = new RegExp(src);
+ } else if (src.nodeName) {
+ dst[key] = src.cloneNode(true);
+ } else if (isElement(src)) {
+ dst[key] = src.clone();
+ } else {
+ if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
+ baseExtend(dst[key], [src], true);
+ }
+ } else {
+ dst[key] = src;
+ }
+ }
+ }
+
+ setHashKey(dst, h);
+ return dst;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.extend
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
+ * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
+ *
+ * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
+ * {@link angular.merge} for this.
+ *
+ * @param {Object} dst Destination object.
+ * @param {...Object} src Source object(s).
+ * @returns {Object} Reference to `dst`.
+ */
+function extend(dst) {
+ return baseExtend(dst, slice.call(arguments, 1), false);
+}
+
+
+/**
+* @ngdoc function
+* @name angular.merge
+* @module ng
+* @kind function
+*
+* @description
+* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
+* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
+* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
+*
+* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
+* objects, performing a deep copy.
+*
+* @param {Object} dst Destination object.
+* @param {...Object} src Source object(s).
+* @returns {Object} Reference to `dst`.
+*/
+function merge(dst) {
+ return baseExtend(dst, slice.call(arguments, 1), true);
+}
+
+
+
+function toInt(str) {
+ return parseInt(str, 10);
+}
+
+
+function inherit(parent, extra) {
+ return extend(Object.create(parent), extra);
+}
+
+/**
+ * @ngdoc function
+ * @name angular.noop
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that performs no operations. This function can be useful when writing code in the
+ * functional style.
+ ```js
+ function foo(callback) {
+ var result = calculateResult();
+ (callback || angular.noop)(result);
+ }
+ ```
+ */
+function noop() {}
+noop.$inject = [];
+
+
+/**
+ * @ngdoc function
+ * @name angular.identity
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * A function that returns its first argument. This function is useful when writing code in the
+ * functional style.
+ *
+ ```js
+ function transformer(transformationFn, value) {
+ return (transformationFn || angular.identity)(value);
+ };
+ ```
+ * @param {*} value to be returned.
+ * @returns {*} the value passed in.
+ */
+function identity($) {return $;}
+identity.$inject = [];
+
+
+function valueFn(value) {return function() {return value;};}
+
+function hasCustomToString(obj) {
+ return isFunction(obj.toString) && obj.toString !== toString;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isUndefined
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is undefined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is undefined.
+ */
+function isUndefined(value) {return typeof value === 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDefined
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is defined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is defined.
+ */
+function isDefined(value) {return typeof value !== 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isObject
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+ * considered to be objects. Note that JavaScript arrays are objects.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Object` but not `null`.
+ */
+function isObject(value) {
+ // http://jsperf.com/isobject4
+ return value !== null && typeof value === 'object';
+}
+
+
+/**
+ * Determine if a value is an object with a null prototype
+ *
+ * @returns {boolean} True if `value` is an `Object` with a null prototype
+ */
+function isBlankObject(value) {
+ return value !== null && typeof value === 'object' && !getPrototypeOf(value);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isString
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `String`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `String`.
+ */
+function isString(value) {return typeof value === 'string';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isNumber
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `Number`.
+ *
+ * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
+ *
+ * If you wish to exclude these then you can use the native
+ * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
+ * method.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Number`.
+ */
+function isNumber(value) {return typeof value === 'number';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDate
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a value is a date.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Date`.
+ */
+function isDate(value) {
+ return toString.call(value) === '[object Date]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isArray
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is an `Array`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Array`.
+ */
+var isArray = Array.isArray;
+
+/**
+ * @ngdoc function
+ * @name angular.isFunction
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a `Function`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Function`.
+ */
+function isFunction(value) {return typeof value === 'function';}
+
+
+/**
+ * Determines if a value is a regular expression object.
+ *
+ * @private
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `RegExp`.
+ */
+function isRegExp(value) {
+ return toString.call(value) === '[object RegExp]';
+}
+
+
+/**
+ * Checks if `obj` is a window object.
+ *
+ * @private
+ * @param {*} obj Object to check
+ * @returns {boolean} True if `obj` is a window obj.
+ */
+function isWindow(obj) {
+ return obj && obj.window === obj;
+}
+
+
+function isScope(obj) {
+ return obj && obj.$evalAsync && obj.$watch;
+}
+
+
+function isFile(obj) {
+ return toString.call(obj) === '[object File]';
+}
+
+
+function isFormData(obj) {
+ return toString.call(obj) === '[object FormData]';
+}
+
+
+function isBlob(obj) {
+ return toString.call(obj) === '[object Blob]';
+}
+
+
+function isBoolean(value) {
+ return typeof value === 'boolean';
+}
+
+
+function isPromiseLike(obj) {
+ return obj && isFunction(obj.then);
+}
+
+
+var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
+function isTypedArray(value) {
+ return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
+}
+
+
+var trim = function(value) {
+ return isString(value) ? value.trim() : value;
+};
+
+// Copied from:
+// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
+// Prereq: s is a string.
+var escapeForRegexp = function(s) {
+ return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
+ replace(/\x08/g, '\\x08');
+};
+
+
+/**
+ * @ngdoc function
+ * @name angular.isElement
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if a reference is a DOM element (or wrapped jQuery element).
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
+ */
+function isElement(node) {
+ return !!(node &&
+ (node.nodeName // we are a direct element
+ || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
+}
+
+/**
+ * @param str 'key1,key2,...'
+ * @returns {object} in the form of {key1:true, key2:true, ...}
+ */
+function makeMap(str) {
+ var obj = {}, items = str.split(","), i;
+ for (i = 0; i < items.length; i++) {
+ obj[items[i]] = true;
+ }
+ return obj;
+}
+
+
+function nodeName_(element) {
+ return lowercase(element.nodeName || (element[0] && element[0].nodeName));
+}
+
+function includes(array, obj) {
+ return Array.prototype.indexOf.call(array, obj) != -1;
+}
+
+function arrayRemove(array, value) {
+ var index = array.indexOf(value);
+ if (index >= 0) {
+ array.splice(index, 1);
+ }
+ return index;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.copy
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Creates a deep copy of `source`, which should be an object or an array.
+ *
+ * * If no destination is supplied, a copy of the object or array is created.
+ * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
+ * are deleted and then all elements/properties from the source are copied to it.
+ * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
+ * * If `source` is identical to 'destination' an exception will be thrown.
+ *
+ * @param {*} source The source that will be used to make a copy.
+ * Can be any type, including primitives, `null`, and `undefined`.
+ * @param {(Object|Array)=} destination Destination into which the source is copied. If
+ * provided, must be of the same type as `source`.
+ * @returns {*} The copy or updated `destination`, if `destination` was specified.
+ *
+ * @example
+ <example module="copyExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form novalidate class="simple-form">
+ Name: <input type="text" ng-model="user.name" /><br />
+ E-mail: <input type="email" ng-model="user.email" /><br />
+ Gender: <input type="radio" ng-model="user.gender" value="male" />male
+ <input type="radio" ng-model="user.gender" value="female" />female<br />
+ <button ng-click="reset()">RESET</button>
+ <button ng-click="update(user)">SAVE</button>
+ </form>
+ <pre>form = {{user | json}}</pre>
+ <pre>master = {{master | json}}</pre>
+ </div>
+
+ <script>
+ angular.module('copyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.master= {};
+
+ $scope.update = function(user) {
+ // Example with 1 argument
+ $scope.master= angular.copy(user);
+ };
+
+ $scope.reset = function() {
+ // Example with 2 arguments
+ angular.copy($scope.master, $scope.user);
+ };
+
+ $scope.reset();
+ }]);
+ </script>
+ </file>
+ </example>
+ */
+function copy(source, destination) {
+ var stackSource = [];
+ var stackDest = [];
+
+ if (destination) {
+ if (isTypedArray(destination)) {
+ throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
+ }
+ if (source === destination) {
+ throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
+ }
+
+ // Empty the destination object
+ if (isArray(destination)) {
+ destination.length = 0;
+ } else {
+ forEach(destination, function(value, key) {
+ if (key !== '$$hashKey') {
+ delete destination[key];
+ }
+ });
+ }
+
+ stackSource.push(source);
+ stackDest.push(destination);
+ return copyRecurse(source, destination);
+ }
+
+ return copyElement(source);
+
+ function copyRecurse(source, destination) {
+ var h = destination.$$hashKey;
+ var result, key;
+ if (isArray(source)) {
+ for (var i = 0, ii = source.length; i < ii; i++) {
+ destination.push(copyElement(source[i]));
+ }
+ } else if (isBlankObject(source)) {
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
+ for (key in source) {
+ destination[key] = copyElement(source[key]);
+ }
+ } else if (source && typeof source.hasOwnProperty === 'function') {
+ // Slow path, which must rely on hasOwnProperty
+ for (key in source) {
+ if (source.hasOwnProperty(key)) {
+ destination[key] = copyElement(source[key]);
+ }
+ }
+ } else {
+ // Slowest path --- hasOwnProperty can't be called as a method
+ for (key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ destination[key] = copyElement(source[key]);
+ }
+ }
+ }
+ setHashKey(destination, h);
+ return destination;
+ }
+
+ function copyElement(source) {
+ // Simple values
+ if (!isObject(source)) {
+ return source;
+ }
+
+ // Already copied values
+ var index = stackSource.indexOf(source);
+ if (index !== -1) {
+ return stackDest[index];
+ }
+
+ if (isWindow(source) || isScope(source)) {
+ throw ngMinErr('cpws',
+ "Can't copy! Making copies of Window or Scope instances is not supported.");
+ }
+
+ var needsRecurse = false;
+ var destination;
+
+ if (isArray(source)) {
+ destination = [];
+ needsRecurse = true;
+ } else if (isTypedArray(source)) {
+ destination = new source.constructor(source);
+ } else if (isDate(source)) {
+ destination = new Date(source.getTime());
+ } else if (isRegExp(source)) {
+ destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
+ destination.lastIndex = source.lastIndex;
+ } else if (isFunction(source.cloneNode)) {
+ destination = source.cloneNode(true);
+ } else {
+ destination = Object.create(getPrototypeOf(source));
+ needsRecurse = true;
+ }
+
+ stackSource.push(source);
+ stackDest.push(destination);
+
+ return needsRecurse
+ ? copyRecurse(source, destination)
+ : destination;
+ }
+}
+
+/**
+ * Creates a shallow copy of an object, an array or a primitive.
+ *
+ * Assumes that there are no proto properties for objects.
+ */
+function shallowCopy(src, dst) {
+ if (isArray(src)) {
+ dst = dst || [];
+
+ for (var i = 0, ii = src.length; i < ii; i++) {
+ dst[i] = src[i];
+ }
+ } else if (isObject(src)) {
+ dst = dst || {};
+
+ for (var key in src) {
+ if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst || src;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.equals
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Determines if two objects or two values are equivalent. Supports value types, regular
+ * expressions, arrays and objects.
+ *
+ * Two objects or values are considered equivalent if at least one of the following is true:
+ *
+ * * Both objects or values pass `===` comparison.
+ * * Both objects or values are of the same type and all of their properties are equal by
+ * comparing them with `angular.equals`.
+ * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
+ * * Both values represent the same regular expression (In JavaScript,
+ * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
+ * representation matches).
+ *
+ * During a property comparison, properties of `function` type and properties with names
+ * that begin with `$` are ignored.
+ *
+ * Scope and DOMWindow objects are being compared only by identify (`===`).
+ *
+ * @param {*} o1 Object or value to compare.
+ * @param {*} o2 Object or value to compare.
+ * @returns {boolean} True if arguments are equal.
+ */
+function equals(o1, o2) {
+ if (o1 === o2) return true;
+ if (o1 === null || o2 === null) return false;
+ if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+ var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+ if (t1 == t2) {
+ if (t1 == 'object') {
+ if (isArray(o1)) {
+ if (!isArray(o2)) return false;
+ if ((length = o1.length) == o2.length) {
+ for (key = 0; key < length; key++) {
+ if (!equals(o1[key], o2[key])) return false;
+ }
+ return true;
+ }
+ } else if (isDate(o1)) {
+ if (!isDate(o2)) return false;
+ return equals(o1.getTime(), o2.getTime());
+ } else if (isRegExp(o1)) {
+ return isRegExp(o2) ? o1.toString() == o2.toString() : false;
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
+ isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
+ keySet = createMap();
+ for (key in o1) {
+ if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+ if (!equals(o1[key], o2[key])) return false;
+ keySet[key] = true;
+ }
+ for (key in o2) {
+ if (!(key in keySet) &&
+ key.charAt(0) !== '$' &&
+ isDefined(o2[key]) &&
+ !isFunction(o2[key])) return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+var csp = function() {
+ if (!isDefined(csp.rules)) {
+
+
+ var ngCspElement = (document.querySelector('[ng-csp]') ||
+ document.querySelector('[data-ng-csp]'));
+
+ if (ngCspElement) {
+ var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
+ ngCspElement.getAttribute('data-ng-csp');
+ csp.rules = {
+ noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
+ noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
+ };
+ } else {
+ csp.rules = {
+ noUnsafeEval: noUnsafeEval(),
+ noInlineStyle: false
+ };
+ }
+ }
+
+ return csp.rules;
+
+ function noUnsafeEval() {
+ try {
+ /* jshint -W031, -W054 */
+ new Function('');
+ /* jshint +W031, +W054 */
+ return false;
+ } catch (e) {
+ return true;
+ }
+ }
+};
+
+/**
+ * @ngdoc directive
+ * @module ng
+ * @name ngJq
+ *
+ * @element ANY
+ * @param {string=} ngJq the name of the library available under `window`
+ * to be used for angular.element
+ * @description
+ * Use this directive to force the angular.element library. This should be
+ * used to force either jqLite by leaving ng-jq blank or setting the name of
+ * the jquery variable under window (eg. jQuery).
+ *
+ * Since angular looks for this directive when it is loaded (doesn't wait for the
+ * DOMContentLoaded event), it must be placed on an element that comes before the script
+ * which loads angular. Also, only the first instance of `ng-jq` will be used and all
+ * others ignored.
+ *
+ * @example
+ * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
+ ```html
+ <!doctype html>
+ <html ng-app ng-jq>
+ ...
+ ...
+ </html>
+ ```
+ * @example
+ * This example shows how to use a jQuery based library of a different name.
+ * The library name must be available at the top most 'window'.
+ ```html
+ <!doctype html>
+ <html ng-app ng-jq="jQueryLib">
+ ...
+ ...
+ </html>
+ ```
+ */
+var jq = function() {
+ if (isDefined(jq.name_)) return jq.name_;
+ var el;
+ var i, ii = ngAttrPrefixes.length, prefix, name;
+ for (i = 0; i < ii; ++i) {
+ prefix = ngAttrPrefixes[i];
+ if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
+ name = el.getAttribute(prefix + 'jq');
+ break;
+ }
+ }
+
+ return (jq.name_ = name);
+};
+
+function concat(array1, array2, index) {
+ return array1.concat(slice.call(array2, index));
+}
+
+function sliceArgs(args, startIndex) {
+ return slice.call(args, startIndex || 0);
+}
+
+
+/* jshint -W101 */
+/**
+ * @ngdoc function
+ * @name angular.bind
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+ * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
+ * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
+ * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
+ *
+ * @param {Object} self Context which `fn` should be evaluated in.
+ * @param {function()} fn Function to be bound.
+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+ */
+/* jshint +W101 */
+function bind(self, fn) {
+ var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+ if (isFunction(fn) && !(fn instanceof RegExp)) {
+ return curryArgs.length
+ ? function() {
+ return arguments.length
+ ? fn.apply(self, concat(curryArgs, arguments, 0))
+ : fn.apply(self, curryArgs);
+ }
+ : function() {
+ return arguments.length
+ ? fn.apply(self, arguments)
+ : fn.call(self);
+ };
+ } else {
+ // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+ return fn;
+ }
+}
+
+
+function toJsonReplacer(key, value) {
+ var val = value;
+
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
+ val = undefined;
+ } else if (isWindow(value)) {
+ val = '$WINDOW';
+ } else if (value && document === value) {
+ val = '$DOCUMENT';
+ } else if (isScope(value)) {
+ val = '$SCOPE';
+ }
+
+ return val;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.toJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
+ * stripped since angular uses this notation internally.
+ *
+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
+ * If set to an integer, the JSON output will contain that many spaces per indentation.
+ * @returns {string|undefined} JSON-ified string representing `obj`.
+ */
+function toJson(obj, pretty) {
+ if (typeof obj === 'undefined') return undefined;
+ if (!isNumber(pretty)) {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.fromJson
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Deserializes a JSON string.
+ *
+ * @param {string} json JSON string to deserialize.
+ * @returns {Object|Array|string|number} Deserialized JSON string.
+ */
+function fromJson(json) {
+ return isString(json)
+ ? JSON.parse(json)
+ : json;
+}
+
+
+function timezoneToOffset(timezone, fallback) {
+ var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
+ return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
+}
+
+
+function addDateMinutes(date, minutes) {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + minutes);
+ return date;
+}
+
+
+function convertTimezoneToLocal(date, timezone, reverse) {
+ reverse = reverse ? -1 : 1;
+ var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
+ return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
+}
+
+
+/**
+ * @returns {string} Returns the string representation of the element.
+ */
+function startingTag(element) {
+ element = jqLite(element).clone();
+ try {
+ // turns out IE does not let you set .html() on elements which
+ // are not allowed to have children. So we just ignore it.
+ element.empty();
+ } catch (e) {}
+ var elemHtml = jqLite('<div>').append(element).html();
+ try {
+ return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
+ elemHtml.
+ match(/^(<[^>]+>)/)[1].
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ } catch (e) {
+ return lowercase(elemHtml);
+ }
+
+}
+
+
+/////////////////////////////////////////////////
+
+/**
+ * Tries to decode the URI component without throwing an exception.
+ *
+ * @private
+ * @param str value potential URI component to check.
+ * @returns {boolean} True if `value` can be decoded
+ * with the decodeURIComponent function.
+ */
+function tryDecodeURIComponent(value) {
+ try {
+ return decodeURIComponent(value);
+ } catch (e) {
+ // Ignore any invalid uri component
+ }
+}
+
+
+/**
+ * Parses an escaped url query string into key-value pairs.
+ * @returns {Object.<string,boolean|Array>}
+ */
+function parseKeyValue(/**string*/keyValue) {
+ var obj = {};
+ forEach((keyValue || "").split('&'), function(keyValue) {
+ var splitPoint, key, val;
+ if (keyValue) {
+ key = keyValue = keyValue.replace(/\+/g,'%20');
+ splitPoint = keyValue.indexOf('=');
+ if (splitPoint !== -1) {
+ key = keyValue.substring(0, splitPoint);
+ val = keyValue.substring(splitPoint + 1);
+ }
+ key = tryDecodeURIComponent(key);
+ if (isDefined(key)) {
+ val = isDefined(val) ? tryDecodeURIComponent(val) : true;
+ if (!hasOwnProperty.call(obj, key)) {
+ obj[key] = val;
+ } else if (isArray(obj[key])) {
+ obj[key].push(val);
+ } else {
+ obj[key] = [obj[key],val];
+ }
+ }
+ }
+ });
+ return obj;
+}
+
+function toKeyValue(obj) {
+ var parts = [];
+ forEach(obj, function(value, key) {
+ if (isArray(value)) {
+ forEach(value, function(arrayValue) {
+ parts.push(encodeUriQuery(key, true) +
+ (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
+ });
+ } else {
+ parts.push(encodeUriQuery(key, true) +
+ (value === true ? '' : '=' + encodeUriQuery(value, true)));
+ }
+ });
+ return parts.length ? parts.join('&') : '';
+}
+
+
+/**
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+ * segments:
+ * segment = *pchar
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriSegment(val) {
+ return encodeUriQuery(val, true).
+ replace(/%26/gi, '&').
+ replace(/%3D/gi, '=').
+ replace(/%2B/gi, '+');
+}
+
+
+/**
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+ * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
+ * encoded per http://tools.ietf.org/html/rfc3986:
+ * query = *( pchar / "/" / "?" )
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriQuery(val, pctEncodeSpaces) {
+ return encodeURIComponent(val).
+ replace(/%40/gi, '@').
+ replace(/%3A/gi, ':').
+ replace(/%24/g, '$').
+ replace(/%2C/gi, ',').
+ replace(/%3B/gi, ';').
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
+}
+
+var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
+
+function getNgAttribute(element, ngAttr) {
+ var attr, i, ii = ngAttrPrefixes.length;
+ for (i = 0; i < ii; ++i) {
+ attr = ngAttrPrefixes[i] + ngAttr;
+ if (isString(attr = element.getAttribute(attr))) {
+ return attr;
+ }
+ }
+ return null;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngApp
+ * @module ng
+ *
+ * @element ANY
+ * @param {angular.Module} ngApp an optional application
+ * {@link angular.module module} name to load.
+ * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
+ * created in "strict-di" mode. This means that the application will fail to invoke functions which
+ * do not use explicit function annotation (and are thus unsuitable for minification), as described
+ * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
+ * tracking down the root of these bugs.
+ *
+ * @description
+ *
+ * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
+ * designates the **root element** of the application and is typically placed near the root element
+ * of the page - e.g. on the `<body>` or `<html>` tags.
+ *
+ * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
+ * found in the document will be used to define the root element to auto-bootstrap as an
+ * application. To run multiple applications in an HTML document you must manually bootstrap them using
+ * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
+ *
+ * You can specify an **AngularJS module** to be used as the root module for the application. This
+ * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
+ * should contain the application code needed or have dependencies on other modules that will
+ * contain the code. See {@link angular.module} for more information.
+ *
+ * In the example below if the `ngApp` directive were not placed on the `html` element then the
+ * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
+ * would not be resolved to `3`.
+ *
+ * `ngApp` is the easiest, and most common way to bootstrap an application.
+ *
+ <example module="ngAppDemo">
+ <file name="index.html">
+ <div ng-controller="ngAppDemoController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ });
+ </file>
+ </example>
+ *
+ * Using `ngStrictDi`, you would see something like this:
+ *
+ <example ng-app-included="true">
+ <file name="index.html">
+ <div ng-app="ngAppStrictDemo" ng-strict-di>
+ <div ng-controller="GoodController1">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style (see
+ script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="GoodController2">
+ Name: <input ng-model="name"><br />
+ Hello, {{name}}!
+
+ <p>This renders because the controller does not fail to
+ instantiate, by using explicit annotation style
+ (see script.js for details)
+ </p>
+ </div>
+
+ <div ng-controller="BadController">
+ I can add: {{a}} + {{b}} = {{ a+b }}
+
+ <p>The controller could not be instantiated, due to relying
+ on automatic function annotations (which are disabled in
+ strict mode). As such, the content of this section is not
+ interpolated, and there should be an error in your web console.
+ </p>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('ngAppStrictDemo', [])
+ // BadController will fail to instantiate, due to relying on automatic function annotation,
+ // rather than an explicit annotation
+ .controller('BadController', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ })
+ // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
+ // due to using explicit annotations using the array style and $inject property, respectively.
+ .controller('GoodController1', ['$scope', function($scope) {
+ $scope.a = 1;
+ $scope.b = 2;
+ }])
+ .controller('GoodController2', GoodController2);
+ function GoodController2($scope) {
+ $scope.name = "World";
+ }
+ GoodController2.$inject = ['$scope'];
+ </file>
+ <file name="style.css">
+ div[ng-controller] {
+ margin-bottom: 1em;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ border: 1px solid;
+ padding: .5em;
+ }
+ div[ng-controller^=Good] {
+ border-color: #d6e9c6;
+ background-color: #dff0d8;
+ color: #3c763d;
+ }
+ div[ng-controller^=Bad] {
+ border-color: #ebccd1;
+ background-color: #f2dede;
+ color: #a94442;
+ margin-bottom: 0;
+ }
+ </file>
+ </example>
+ */
+function angularInit(element, bootstrap) {
+ var appElement,
+ module,
+ config = {};
+
+ // The element `element` has priority over any other element
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+
+ if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
+ appElement = element;
+ module = element.getAttribute(name);
+ }
+ });
+ forEach(ngAttrPrefixes, function(prefix) {
+ var name = prefix + 'app';
+ var candidate;
+
+ if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
+ appElement = candidate;
+ module = candidate.getAttribute(name);
+ }
+ });
+ if (appElement) {
+ config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
+ bootstrap(appElement, module ? [module] : [], config);
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.bootstrap
+ * @module ng
+ * @description
+ * Use this function to manually start up angular application.
+ *
+ * See: {@link guide/bootstrap Bootstrap}
+ *
+ * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
+ * They must use {@link ng.directive:ngApp ngApp}.
+ *
+ * Angular will detect if it has been loaded into the browser more than once and only allow the
+ * first loaded script to be bootstrapped and will report a warning to the browser console for
+ * each of the subsequent scripts. This prevents strange results in applications, where otherwise
+ * multiple instances of Angular try to work on the DOM.
+ *
+ * ```html
+ * <!doctype html>
+ * <html>
+ * <body>
+ * <div ng-controller="WelcomeController">
+ * {{greeting}}
+ * </div>
+ *
+ * <script src="angular.js"></script>
+ * <script>
+ * var app = angular.module('demo', [])
+ * .controller('WelcomeController', function($scope) {
+ * $scope.greeting = 'Welcome!';
+ * });
+ * angular.bootstrap(document, ['demo']);
+ * </script>
+ * </body>
+ * </html>
+ * ```
+ *
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
+ * Each item in the array should be the name of a predefined module or a (DI annotated)
+ * function that will be invoked by the injector as a `config` block.
+ * See: {@link angular.module modules}
+ * @param {Object=} config an object for defining configuration options for the application. The
+ * following keys are supported:
+ *
+ * * `strictDi` - disable automatic function annotation for the application. This is meant to
+ * assist in finding bugs which break minified code. Defaults to `false`.
+ *
+ * @returns {auto.$injector} Returns the newly created injector for this app.
+ */
+function bootstrap(element, modules, config) {
+ if (!isObject(config)) config = {};
+ var defaultConfig = {
+ strictDi: false
+ };
+ config = extend(defaultConfig, config);
+ var doBootstrap = function() {
+ element = jqLite(element);
+
+ if (element.injector()) {
+ var tag = (element[0] === document) ? 'document' : startingTag(element);
+ //Encode angle brackets to prevent input from being sanitized to empty string #8683
+ throw ngMinErr(
+ 'btstrpd',
+ "App Already Bootstrapped with this Element '{0}'",
+ tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
+ }
+
+ modules = modules || [];
+ modules.unshift(['$provide', function($provide) {
+ $provide.value('$rootElement', element);
+ }]);
+
+ if (config.debugInfoEnabled) {
+ // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
+ modules.push(['$compileProvider', function($compileProvider) {
+ $compileProvider.debugInfoEnabled(true);
+ }]);
+ }
+
+ modules.unshift('ng');
+ var injector = createInjector(modules, config.strictDi);
+ injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
+ function bootstrapApply(scope, element, compile, injector) {
+ scope.$apply(function() {
+ element.data('$injector', injector);
+ compile(element)(scope);
+ });
+ }]
+ );
+ return injector;
+ };
+
+ var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
+ var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
+
+ if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
+ config.debugInfoEnabled = true;
+ window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
+ }
+
+ if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
+ return doBootstrap();
+ }
+
+ window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
+ angular.resumeBootstrap = function(extraModules) {
+ forEach(extraModules, function(module) {
+ modules.push(module);
+ });
+ return doBootstrap();
+ };
+
+ if (isFunction(angular.resumeDeferredBootstrap)) {
+ angular.resumeDeferredBootstrap();
+ }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.reloadWithDebugInfo
+ * @module ng
+ * @description
+ * Use this function to reload the current application with debug information turned on.
+ * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
+ *
+ * See {@link ng.$compileProvider#debugInfoEnabled} for more.
+ */
+function reloadWithDebugInfo() {
+ window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
+ window.location.reload();
+}
+
+/**
+ * @name angular.getTestability
+ * @module ng
+ * @description
+ * Get the testability service for the instance of Angular on the given
+ * element.
+ * @param {DOMElement} element DOM element which is the root of angular application.
+ */
+function getTestability(rootElement) {
+ var injector = angular.element(rootElement).injector();
+ if (!injector) {
+ throw ngMinErr('test',
+ 'no injector found for element argument to getTestability');
+ }
+ return injector.get('$$testability');
+}
+
+var SNAKE_CASE_REGEXP = /[A-Z]/g;
+function snake_case(name, separator) {
+ separator = separator || '_';
+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+}
+
+var bindJQueryFired = false;
+var skipDestroyOnNextJQueryCleanData;
+function bindJQuery() {
+ var originalCleanData;
+
+ if (bindJQueryFired) {
+ return;
+ }
+
+ // bind to jQuery if present;
+ var jqName = jq();
+ jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
+ !jqName ? undefined : // use jqLite
+ window[jqName]; // use jQuery specified by `ngJq`
+
+ // Use jQuery if it exists with proper functionality, otherwise default to us.
+ // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
+ // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
+ // versions. It will not work for sure with jQuery <1.7, though.
+ if (jQuery && jQuery.fn.on) {
+ jqLite = jQuery;
+ extend(jQuery.fn, {
+ scope: JQLitePrototype.scope,
+ isolateScope: JQLitePrototype.isolateScope,
+ controller: JQLitePrototype.controller,
+ injector: JQLitePrototype.injector,
+ inheritedData: JQLitePrototype.inheritedData
+ });
+
+ // All nodes removed from the DOM via various jQuery APIs like .remove()
+ // are passed through jQuery.cleanData. Monkey-patch this method to fire
+ // the $destroy event on all removed nodes.
+ originalCleanData = jQuery.cleanData;
+ jQuery.cleanData = function(elems) {
+ var events;
+ if (!skipDestroyOnNextJQueryCleanData) {
+ for (var i = 0, elem; (elem = elems[i]) != null; i++) {
+ events = jQuery._data(elem, "events");
+ if (events && events.$destroy) {
+ jQuery(elem).triggerHandler('$destroy');
+ }
+ }
+ } else {
+ skipDestroyOnNextJQueryCleanData = false;
+ }
+ originalCleanData(elems);
+ };
+ } else {
+ jqLite = JQLite;
+ }
+
+ angular.element = jqLite;
+
+ // Prevent double-proxying.
+ bindJQueryFired = true;
+}
+
+/**
+ * throw error if the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+ if (!arg) {
+ throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
+ }
+ return arg;
+}
+
+function assertArgFn(arg, name, acceptArrayAnnotation) {
+ if (acceptArrayAnnotation && isArray(arg)) {
+ arg = arg[arg.length - 1];
+ }
+
+ assertArg(isFunction(arg), name, 'not a function, got ' +
+ (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
+ return arg;
+}
+
+/**
+ * throw error if the name given is hasOwnProperty
+ * @param {String} name the name to test
+ * @param {String} context the context in which the name is used, such as module or directive
+ */
+function assertNotHasOwnProperty(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
+ }
+}
+
+/**
+ * Return the value accessible from the object by path. Any undefined traversals are ignored
+ * @param {Object} obj starting object
+ * @param {String} path path to traverse
+ * @param {boolean} [bindFnToScope=true]
+ * @returns {Object} value as accessible by path
+ */
+//TODO(misko): this function needs to be removed
+function getter(obj, path, bindFnToScope) {
+ if (!path) return obj;
+ var keys = path.split('.');
+ var key;
+ var lastInstance = obj;
+ var len = keys.length;
+
+ for (var i = 0; i < len; i++) {
+ key = keys[i];
+ if (obj) {
+ obj = (lastInstance = obj)[key];
+ }
+ }
+ if (!bindFnToScope && isFunction(obj)) {
+ return bind(lastInstance, obj);
+ }
+ return obj;
+}
+
+/**
+ * Return the DOM siblings between the first and last node in the given array.
+ * @param {Array} array like object
+ * @returns {Array} the inputted object or a jqLite collection containing the nodes
+ */
+function getBlockNodes(nodes) {
+ // TODO(perf): update `nodes` instead of creating a new object?
+ var node = nodes[0];
+ var endNode = nodes[nodes.length - 1];
+ var blockNodes;
+
+ for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
+ if (blockNodes || nodes[i] !== node) {
+ if (!blockNodes) {
+ blockNodes = jqLite(slice.call(nodes, 0, i));
+ }
+ blockNodes.push(node);
+ }
+ }
+
+ return blockNodes || nodes;
+}
+
+
+/**
+ * Creates a new object without a prototype. This object is useful for lookup without having to
+ * guard against prototypically inherited properties via hasOwnProperty.
+ *
+ * Related micro-benchmarks:
+ * - http://jsperf.com/object-create2
+ * - http://jsperf.com/proto-map-lookup/2
+ * - http://jsperf.com/for-in-vs-object-keys2
+ *
+ * @returns {Object}
+ */
+function createMap() {
+ return Object.create(null);
+}
+
+var NODE_TYPE_ELEMENT = 1;
+var NODE_TYPE_ATTRIBUTE = 2;
+var NODE_TYPE_TEXT = 3;
+var NODE_TYPE_COMMENT = 8;
+var NODE_TYPE_DOCUMENT = 9;
+var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
+
+/**
+ * @ngdoc type
+ * @name angular.Module
+ * @module ng
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+ var $injectorMinErr = minErr('$injector');
+ var ngMinErr = minErr('ng');
+
+ function ensure(obj, name, factory) {
+ return obj[name] || (obj[name] = factory());
+ }
+
+ var angular = ensure(window, 'angular', Object);
+
+ // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
+ angular.$$minErr = angular.$$minErr || minErr;
+
+ return ensure(angular, 'module', function() {
+ /** @type {Object.<string, angular.Module>} */
+ var modules = {};
+
+ /**
+ * @ngdoc function
+ * @name angular.module
+ * @module ng
+ * @description
+ *
+ * The `angular.module` is a global place for creating, registering and retrieving Angular
+ * modules.
+ * All modules (angular core or 3rd party) that should be available to an application must be
+ * registered using this mechanism.
+ *
+ * Passing one argument retrieves an existing {@link angular.Module},
+ * whereas passing more than one argument creates a new {@link angular.Module}
+ *
+ *
+ * # Module
+ *
+ * A module is a collection of services, directives, controllers, filters, and configuration information.
+ * `angular.module` is used to configure the {@link auto.$injector $injector}.
+ *
+ * ```js
+ * // Create a new module
+ * var myModule = angular.module('myModule', []);
+ *
+ * // register a new service
+ * myModule.value('appName', 'MyCoolApp');
+ *
+ * // configure existing services inside initialization blocks.
+ * myModule.config(['$locationProvider', function($locationProvider) {
+ * // Configure existing providers
+ * $locationProvider.hashPrefix('!');
+ * }]);
+ * ```
+ *
+ * Then you can create an injector and load your modules like this:
+ *
+ * ```js
+ * var injector = angular.injector(['ng', 'myModule'])
+ * ```
+ *
+ * However it's more likely that you'll just use
+ * {@link ng.directive:ngApp ngApp} or
+ * {@link angular.bootstrap} to simplify this process for you.
+ *
+ * @param {!string} name The name of the module to create or retrieve.
+ * @param {!Array.<string>=} requires If specified then new module is being created. If
+ * unspecified then the module is being retrieved for further configuration.
+ * @param {Function=} configFn Optional configuration function for the module. Same as
+ * {@link angular.Module#config Module#config()}.
+ * @returns {module} new module with the {@link angular.Module} api.
+ */
+ return function module(name, requires, configFn) {
+ var assertNotHasOwnProperty = function(name, context) {
+ if (name === 'hasOwnProperty') {
+ throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
+ }
+ };
+
+ assertNotHasOwnProperty(name, 'module');
+ if (requires && modules.hasOwnProperty(name)) {
+ modules[name] = null;
+ }
+ return ensure(modules, name, function() {
+ if (!requires) {
+ throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
+ "the module name or forgot to load it. If registering a module ensure that you " +
+ "specify the dependencies as the second argument.", name);
+ }
+
+ /** @type {!Array.<Array.<*>>} */
+ var invokeQueue = [];
+
+ /** @type {!Array.<Function>} */
+ var configBlocks = [];
+
+ /** @type {!Array.<Function>} */
+ var runBlocks = [];
+
+ var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
+
+ /** @type {angular.Module} */
+ var moduleInstance = {
+ // Private state
+ _invokeQueue: invokeQueue,
+ _configBlocks: configBlocks,
+ _runBlocks: runBlocks,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#requires
+ * @module ng
+ *
+ * @description
+ * Holds the list of modules which the injector will load before the current module is
+ * loaded.
+ */
+ requires: requires,
+
+ /**
+ * @ngdoc property
+ * @name angular.Module#name
+ * @module ng
+ *
+ * @description
+ * Name of the module.
+ */
+ name: name,
+
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#provider
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerType Construction function for creating new instance of the
+ * service.
+ * @description
+ * See {@link auto.$provide#provider $provide.provider()}.
+ */
+ provider: invokeLaterAndSetModuleName('$provide', 'provider'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#factory
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} providerFunction Function for creating new instance of the service.
+ * @description
+ * See {@link auto.$provide#factory $provide.factory()}.
+ */
+ factory: invokeLaterAndSetModuleName('$provide', 'factory'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#service
+ * @module ng
+ * @param {string} name service name
+ * @param {Function} constructor A constructor function that will be instantiated.
+ * @description
+ * See {@link auto.$provide#service $provide.service()}.
+ */
+ service: invokeLaterAndSetModuleName('$provide', 'service'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#value
+ * @module ng
+ * @param {string} name service name
+ * @param {*} object Service instance object.
+ * @description
+ * See {@link auto.$provide#value $provide.value()}.
+ */
+ value: invokeLater('$provide', 'value'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#constant
+ * @module ng
+ * @param {string} name constant name
+ * @param {*} object Constant value.
+ * @description
+ * Because the constants are fixed, they get applied before other provide methods.
+ * See {@link auto.$provide#constant $provide.constant()}.
+ */
+ constant: invokeLater('$provide', 'constant', 'unshift'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#decorator
+ * @module ng
+ * @param {string} The name of the service to decorate.
+ * @param {Function} This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance.
+ * @description
+ * See {@link auto.$provide#decorator $provide.decorator()}.
+ */
+ decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#animation
+ * @module ng
+ * @param {string} name animation name
+ * @param {Function} animationFactory Factory function for creating new instance of an
+ * animation.
+ * @description
+ *
+ * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
+ *
+ *
+ * Defines an animation hook that can be later used with
+ * {@link $animate $animate} service and directives that use this service.
+ *
+ * ```js
+ * module.animation('.animation-name', function($inject1, $inject2) {
+ * return {
+ * eventName : function(element, done) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function cancellationFunction(element) {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ * })
+ * ```
+ *
+ * See {@link ng.$animateProvider#register $animateProvider.register()} and
+ * {@link ngAnimate ngAnimate module} for more information.
+ */
+ animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#filter
+ * @module ng
+ * @param {string} name Filter name - this must be a valid angular expression identifier
+ * @param {Function} filterFactory Factory function for creating new instance of filter.
+ * @description
+ * See {@link ng.$filterProvider#register $filterProvider.register()}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ */
+ filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#controller
+ * @module ng
+ * @param {string|Object} name Controller name, or an object map of controllers where the
+ * keys are the names and the values are the constructors.
+ * @param {Function} constructor Controller constructor function.
+ * @description
+ * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+ */
+ controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#directive
+ * @module ng
+ * @param {string|Object} name Directive name, or an object map of directives where the
+ * keys are the names and the values are the factories.
+ * @param {Function} directiveFactory Factory function for creating new instance of
+ * directives.
+ * @description
+ * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+ */
+ directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#config
+ * @module ng
+ * @param {Function} configFn Execute this function on module load. Useful for service
+ * configuration.
+ * @description
+ * Use this method to register work which needs to be performed on module loading.
+ * For more about how to configure services, see
+ * {@link providers#provider-recipe Provider Recipe}.
+ */
+ config: config,
+
+ /**
+ * @ngdoc method
+ * @name angular.Module#run
+ * @module ng
+ * @param {Function} initializationFn Execute this function after injector creation.
+ * Useful for application initialization.
+ * @description
+ * Use this method to register work which should be performed when the injector is done
+ * loading all modules.
+ */
+ run: function(block) {
+ runBlocks.push(block);
+ return this;
+ }
+ };
+
+ if (configFn) {
+ config(configFn);
+ }
+
+ return moduleInstance;
+
+ /**
+ * @param {string} provider
+ * @param {string} method
+ * @param {String=} insertMethod
+ * @returns {angular.Module}
+ */
+ function invokeLater(provider, method, insertMethod, queue) {
+ if (!queue) queue = invokeQueue;
+ return function() {
+ queue[insertMethod || 'push']([provider, method, arguments]);
+ return moduleInstance;
+ };
+ }
+
+ /**
+ * @param {string} provider
+ * @param {string} method
+ * @returns {angular.Module}
+ */
+ function invokeLaterAndSetModuleName(provider, method) {
+ return function(recipeName, factoryFunction) {
+ if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
+ invokeQueue.push([provider, method, arguments]);
+ return moduleInstance;
+ };
+ }
+ });
+ };
+ });
+
+}
+
+/* global: toDebugString: true */
+
+function serializeObject(obj) {
+ var seen = [];
+
+ return JSON.stringify(obj, function(key, val) {
+ val = toJsonReplacer(key, val);
+ if (isObject(val)) {
+
+ if (seen.indexOf(val) >= 0) return '...';
+
+ seen.push(val);
+ }
+ return val;
+ });
+}
+
+function toDebugString(obj) {
+ if (typeof obj === 'function') {
+ return obj.toString().replace(/ \{[\s\S]*$/, '');
+ } else if (isUndefined(obj)) {
+ return 'undefined';
+ } else if (typeof obj !== 'string') {
+ return serializeObject(obj);
+ }
+ return obj;
+}
+
+/* global angularModule: true,
+ version: true,
+
+ $CompileProvider,
+
+ htmlAnchorDirective,
+ inputDirective,
+ inputDirective,
+ formDirective,
+ scriptDirective,
+ selectDirective,
+ styleDirective,
+ optionDirective,
+ ngBindDirective,
+ ngBindHtmlDirective,
+ ngBindTemplateDirective,
+ ngClassDirective,
+ ngClassEvenDirective,
+ ngClassOddDirective,
+ ngCloakDirective,
+ ngControllerDirective,
+ ngFormDirective,
+ ngHideDirective,
+ ngIfDirective,
+ ngIncludeDirective,
+ ngIncludeFillContentDirective,
+ ngInitDirective,
+ ngNonBindableDirective,
+ ngPluralizeDirective,
+ ngRepeatDirective,
+ ngShowDirective,
+ ngStyleDirective,
+ ngSwitchDirective,
+ ngSwitchWhenDirective,
+ ngSwitchDefaultDirective,
+ ngOptionsDirective,
+ ngTranscludeDirective,
+ ngModelDirective,
+ ngListDirective,
+ ngChangeDirective,
+ patternDirective,
+ patternDirective,
+ requiredDirective,
+ requiredDirective,
+ minlengthDirective,
+ minlengthDirective,
+ maxlengthDirective,
+ maxlengthDirective,
+ ngValueDirective,
+ ngModelOptionsDirective,
+ ngAttributeAliasDirectives,
+ ngEventDirectives,
+
+ $AnchorScrollProvider,
+ $AnimateProvider,
+ $CoreAnimateCssProvider,
+ $$CoreAnimateQueueProvider,
+ $$CoreAnimateRunnerProvider,
+ $BrowserProvider,
+ $CacheFactoryProvider,
+ $ControllerProvider,
+ $DocumentProvider,
+ $ExceptionHandlerProvider,
+ $FilterProvider,
+ $$ForceReflowProvider,
+ $InterpolateProvider,
+ $IntervalProvider,
+ $$HashMapProvider,
+ $HttpProvider,
+ $HttpParamSerializerProvider,
+ $HttpParamSerializerJQLikeProvider,
+ $HttpBackendProvider,
+ $xhrFactoryProvider,
+ $LocationProvider,
+ $LogProvider,
+ $ParseProvider,
+ $RootScopeProvider,
+ $QProvider,
+ $$QProvider,
+ $$SanitizeUriProvider,
+ $SceProvider,
+ $SceDelegateProvider,
+ $SnifferProvider,
+ $TemplateCacheProvider,
+ $TemplateRequestProvider,
+ $$TestabilityProvider,
+ $TimeoutProvider,
+ $$RAFProvider,
+ $WindowProvider,
+ $$jqLiteProvider,
+ $$CookieReaderProvider
+*/
+
+
+/**
+ * @ngdoc object
+ * @name angular.version
+ * @module ng
+ * @description
+ * An object that contains information about the current AngularJS version.
+ *
+ * This object has the following properties:
+ *
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ */
+var version = {
+ full: '1.4.8', // all of these placeholder strings will be replaced by grunt's
+ major: 1, // package task
+ minor: 4,
+ dot: 8,
+ codeName: 'ice-manipulation'
+};
+
+
+function publishExternalAPI(angular) {
+ extend(angular, {
+ 'bootstrap': bootstrap,
+ 'copy': copy,
+ 'extend': extend,
+ 'merge': merge,
+ 'equals': equals,
+ 'element': jqLite,
+ 'forEach': forEach,
+ 'injector': createInjector,
+ 'noop': noop,
+ 'bind': bind,
+ 'toJson': toJson,
+ 'fromJson': fromJson,
+ 'identity': identity,
+ 'isUndefined': isUndefined,
+ 'isDefined': isDefined,
+ 'isString': isString,
+ 'isFunction': isFunction,
+ 'isObject': isObject,
+ 'isNumber': isNumber,
+ 'isElement': isElement,
+ 'isArray': isArray,
+ 'version': version,
+ 'isDate': isDate,
+ 'lowercase': lowercase,
+ 'uppercase': uppercase,
+ 'callbacks': {counter: 0},
+ 'getTestability': getTestability,
+ '$$minErr': minErr,
+ '$$csp': csp,
+ 'reloadWithDebugInfo': reloadWithDebugInfo
+ });
+
+ angularModule = setupModuleLoader(window);
+
+ angularModule('ng', ['ngLocale'], ['$provide',
+ function ngModule($provide) {
+ // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
+ $provide.provider({
+ $$sanitizeUri: $$SanitizeUriProvider
+ });
+ $provide.provider('$compile', $CompileProvider).
+ directive({
+ a: htmlAnchorDirective,
+ input: inputDirective,
+ textarea: inputDirective,
+ form: formDirective,
+ script: scriptDirective,
+ select: selectDirective,
+ style: styleDirective,
+ option: optionDirective,
+ ngBind: ngBindDirective,
+ ngBindHtml: ngBindHtmlDirective,
+ ngBindTemplate: ngBindTemplateDirective,
+ ngClass: ngClassDirective,
+ ngClassEven: ngClassEvenDirective,
+ ngClassOdd: ngClassOddDirective,
+ ngCloak: ngCloakDirective,
+ ngController: ngControllerDirective,
+ ngForm: ngFormDirective,
+ ngHide: ngHideDirective,
+ ngIf: ngIfDirective,
+ ngInclude: ngIncludeDirective,
+ ngInit: ngInitDirective,
+ ngNonBindable: ngNonBindableDirective,
+ ngPluralize: ngPluralizeDirective,
+ ngRepeat: ngRepeatDirective,
+ ngShow: ngShowDirective,
+ ngStyle: ngStyleDirective,
+ ngSwitch: ngSwitchDirective,
+ ngSwitchWhen: ngSwitchWhenDirective,
+ ngSwitchDefault: ngSwitchDefaultDirective,
+ ngOptions: ngOptionsDirective,
+ ngTransclude: ngTranscludeDirective,
+ ngModel: ngModelDirective,
+ ngList: ngListDirective,
+ ngChange: ngChangeDirective,
+ pattern: patternDirective,
+ ngPattern: patternDirective,
+ required: requiredDirective,
+ ngRequired: requiredDirective,
+ minlength: minlengthDirective,
+ ngMinlength: minlengthDirective,
+ maxlength: maxlengthDirective,
+ ngMaxlength: maxlengthDirective,
+ ngValue: ngValueDirective,
+ ngModelOptions: ngModelOptionsDirective
+ }).
+ directive({
+ ngInclude: ngIncludeFillContentDirective
+ }).
+ directive(ngAttributeAliasDirectives).
+ directive(ngEventDirectives);
+ $provide.provider({
+ $anchorScroll: $AnchorScrollProvider,
+ $animate: $AnimateProvider,
+ $animateCss: $CoreAnimateCssProvider,
+ $$animateQueue: $$CoreAnimateQueueProvider,
+ $$AnimateRunner: $$CoreAnimateRunnerProvider,
+ $browser: $BrowserProvider,
+ $cacheFactory: $CacheFactoryProvider,
+ $controller: $ControllerProvider,
+ $document: $DocumentProvider,
+ $exceptionHandler: $ExceptionHandlerProvider,
+ $filter: $FilterProvider,
+ $$forceReflow: $$ForceReflowProvider,
+ $interpolate: $InterpolateProvider,
+ $interval: $IntervalProvider,
+ $http: $HttpProvider,
+ $httpParamSerializer: $HttpParamSerializerProvider,
+ $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
+ $httpBackend: $HttpBackendProvider,
+ $xhrFactory: $xhrFactoryProvider,
+ $location: $LocationProvider,
+ $log: $LogProvider,
+ $parse: $ParseProvider,
+ $rootScope: $RootScopeProvider,
+ $q: $QProvider,
+ $$q: $$QProvider,
+ $sce: $SceProvider,
+ $sceDelegate: $SceDelegateProvider,
+ $sniffer: $SnifferProvider,
+ $templateCache: $TemplateCacheProvider,
+ $templateRequest: $TemplateRequestProvider,
+ $$testability: $$TestabilityProvider,
+ $timeout: $TimeoutProvider,
+ $window: $WindowProvider,
+ $$rAF: $$RAFProvider,
+ $$jqLite: $$jqLiteProvider,
+ $$HashMap: $$HashMapProvider,
+ $$cookieReader: $$CookieReaderProvider
+ });
+ }
+ ]);
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* global JQLitePrototype: true,
+ addEventListenerFn: true,
+ removeEventListenerFn: true,
+ BOOLEAN_ATTR: true,
+ ALIASED_ATTR: true,
+*/
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @module ng
+ * @kind function
+ *
+ * @description
+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+ *
+ * If jQuery is available, `angular.element` is an alias for the
+ * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
+ * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
+ *
+ * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
+ * commonly needed functionality with the goal of having a very small footprint.</div>
+ *
+ * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
+ *
+ * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
+ * jqLite; they are never raw DOM references.</div>
+ *
+ * ## Angular's jqLite
+ * jqLite provides only the following jQuery methods:
+ *
+ * - [`addClass()`](http://api.jquery.com/addClass/)
+ * - [`after()`](http://api.jquery.com/after/)
+ * - [`append()`](http://api.jquery.com/append/)
+ * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
+ * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
+ * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
+ * - [`clone()`](http://api.jquery.com/clone/)
+ * - [`contents()`](http://api.jquery.com/contents/)
+ * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
+ * - [`data()`](http://api.jquery.com/data/)
+ * - [`detach()`](http://api.jquery.com/detach/)
+ * - [`empty()`](http://api.jquery.com/empty/)
+ * - [`eq()`](http://api.jquery.com/eq/)
+ * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
+ * - [`hasClass()`](http://api.jquery.com/hasClass/)
+ * - [`html()`](http://api.jquery.com/html/)
+ * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
+ * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
+ * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
+ * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
+ * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
+ * - [`prepend()`](http://api.jquery.com/prepend/)
+ * - [`prop()`](http://api.jquery.com/prop/)
+ * - [`ready()`](http://api.jquery.com/ready/)
+ * - [`remove()`](http://api.jquery.com/remove/)
+ * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
+ * - [`removeClass()`](http://api.jquery.com/removeClass/)
+ * - [`removeData()`](http://api.jquery.com/removeData/)
+ * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
+ * - [`text()`](http://api.jquery.com/text/)
+ * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
+ * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
+ * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
+ * - [`val()`](http://api.jquery.com/val/)
+ * - [`wrap()`](http://api.jquery.com/wrap/)
+ *
+ * ## jQuery/jqLite Extras
+ * Angular also provides the following additional methods and events to both jQuery and jqLite:
+ *
+ * ### Events
+ * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
+ * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
+ * element before it is removed.
+ *
+ * ### Methods
+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+ * retrieves controller associated with the `ngController` directive. If `name` is provided as
+ * camelCase directive name, then the controller for this directive will be retrieved (e.g.
+ * `'ngModel'`).
+ * - `injector()` - retrieves the injector of the current element or its parent.
+ * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
+ * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
+ * be enabled.
+ * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
+ * current element. This getter should be used only on elements that contain a directive which starts a new isolate
+ * scope. Calling `scope()` on this element always returns the original non-isolate scope.
+ * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+ * parent element is reached.
+ *
+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+ * @returns {Object} jQuery object.
+ */
+
+JQLite.expando = 'ng339';
+
+var jqCache = JQLite.cache = {},
+ jqId = 1,
+ addEventListenerFn = function(element, type, fn) {
+ element.addEventListener(type, fn, false);
+ },
+ removeEventListenerFn = function(element, type, fn) {
+ element.removeEventListener(type, fn, false);
+ };
+
+/*
+ * !!! This is an undocumented "private" function !!!
+ */
+JQLite._data = function(node) {
+ //jQuery always returns an object on cache miss
+ return this.cache[node[this.expando]] || {};
+};
+
+function jqNextId() { return ++jqId; }
+
+
+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
+var jqLiteMinErr = minErr('jqLite');
+
+/**
+ * Converts snake_case to camelCase.
+ * Also there is special case for Moz prefix starting with upper case letter.
+ * @param name Name to normalize
+ */
+function camelCase(name) {
+ return name.
+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+ return offset ? letter.toUpperCase() : letter;
+ }).
+ replace(MOZ_HACK_REGEXP, 'Moz$1');
+}
+
+var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
+var HTML_REGEXP = /<|&#?\w+;/;
+var TAG_NAME_REGEXP = /<([\w:-]+)/;
+var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
+
+var wrapMap = {
+ 'option': [1, '<select multiple="multiple">', '</select>'],
+
+ 'thead': [1, '<table>', '</table>'],
+ 'col': [2, '<table><colgroup>', '</colgroup></table>'],
+ 'tr': [2, '<table><tbody>', '</tbody></table>'],
+ 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
+ '_default': [0, "", ""]
+};
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function jqLiteIsTextNode(html) {
+ return !HTML_REGEXP.test(html);
+}
+
+function jqLiteAcceptsData(node) {
+ // The window object can accept data but has no nodeType
+ // Otherwise we are only interested in elements (1) and documents (9)
+ var nodeType = node.nodeType;
+ return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
+}
+
+function jqLiteHasData(node) {
+ for (var key in jqCache[node.ng339]) {
+ return true;
+ }
+ return false;
+}
+
+function jqLiteBuildFragment(html, context) {
+ var tmp, tag, wrap,
+ fragment = context.createDocumentFragment(),
+ nodes = [], i;
+
+ if (jqLiteIsTextNode(html)) {
+ // Convert non-html into a text node
+ nodes.push(context.createTextNode(html));
+ } else {
+ // Convert html into DOM nodes
+ tmp = tmp || fragment.appendChild(context.createElement("div"));
+ tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
+ wrap = wrapMap[tag] || wrapMap._default;
+ tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
+
+ // Descend through wrappers to the right content
+ i = wrap[0];
+ while (i--) {
+ tmp = tmp.lastChild;
+ }
+
+ nodes = concat(nodes, tmp.childNodes);
+
+ tmp = fragment.firstChild;
+ tmp.textContent = "";
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+ fragment.innerHTML = ""; // Clear inner HTML
+ forEach(nodes, function(node) {
+ fragment.appendChild(node);
+ });
+
+ return fragment;
+}
+
+function jqLiteParseHTML(html, context) {
+ context = context || document;
+ var parsed;
+
+ if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
+ return [context.createElement(parsed[1])];
+ }
+
+ if ((parsed = jqLiteBuildFragment(html, context))) {
+ return parsed.childNodes;
+ }
+
+ return [];
+}
+
+
+// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
+var jqLiteContains = Node.prototype.contains || function(arg) {
+ // jshint bitwise: false
+ return !!(this.compareDocumentPosition(arg) & 16);
+ // jshint bitwise: true
+};
+
+/////////////////////////////////////////////
+function JQLite(element) {
+ if (element instanceof JQLite) {
+ return element;
+ }
+
+ var argIsString;
+
+ if (isString(element)) {
+ element = trim(element);
+ argIsString = true;
+ }
+ if (!(this instanceof JQLite)) {
+ if (argIsString && element.charAt(0) != '<') {
+ throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
+ }
+ return new JQLite(element);
+ }
+
+ if (argIsString) {
+ jqLiteAddNodes(this, jqLiteParseHTML(element));
+ } else {
+ jqLiteAddNodes(this, element);
+ }
+}
+
+function jqLiteClone(element) {
+ return element.cloneNode(true);
+}
+
+function jqLiteDealoc(element, onlyDescendants) {
+ if (!onlyDescendants) jqLiteRemoveData(element);
+
+ if (element.querySelectorAll) {
+ var descendants = element.querySelectorAll('*');
+ for (var i = 0, l = descendants.length; i < l; i++) {
+ jqLiteRemoveData(descendants[i]);
+ }
+ }
+}
+
+function jqLiteOff(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
+
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var handle = expandoStore && expandoStore.handle;
+
+ if (!handle) return; //no listeners registered
+
+ if (!type) {
+ for (type in events) {
+ if (type !== '$destroy') {
+ removeEventListenerFn(element, type, handle);
+ }
+ delete events[type];
+ }
+ } else {
+
+ var removeHandler = function(type) {
+ var listenerFns = events[type];
+ if (isDefined(fn)) {
+ arrayRemove(listenerFns || [], fn);
+ }
+ if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
+ removeEventListenerFn(element, type, handle);
+ delete events[type];
+ }
+ };
+
+ forEach(type.split(' '), function(type) {
+ removeHandler(type);
+ if (MOUSE_EVENT_MAP[type]) {
+ removeHandler(MOUSE_EVENT_MAP[type]);
+ }
+ });
+ }
+}
+
+function jqLiteRemoveData(element, name) {
+ var expandoId = element.ng339;
+ var expandoStore = expandoId && jqCache[expandoId];
+
+ if (expandoStore) {
+ if (name) {
+ delete expandoStore.data[name];
+ return;
+ }
+
+ if (expandoStore.handle) {
+ if (expandoStore.events.$destroy) {
+ expandoStore.handle({}, '$destroy');
+ }
+ jqLiteOff(element);
+ }
+ delete jqCache[expandoId];
+ element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
+ }
+}
+
+
+function jqLiteExpandoStore(element, createIfNecessary) {
+ var expandoId = element.ng339,
+ expandoStore = expandoId && jqCache[expandoId];
+
+ if (createIfNecessary && !expandoStore) {
+ element.ng339 = expandoId = jqNextId();
+ expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
+ }
+
+ return expandoStore;
+}
+
+
+function jqLiteData(element, key, value) {
+ if (jqLiteAcceptsData(element)) {
+
+ var isSimpleSetter = isDefined(value);
+ var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
+ var massGetter = !key;
+ var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
+ var data = expandoStore && expandoStore.data;
+
+ if (isSimpleSetter) { // data('key', value)
+ data[key] = value;
+ } else {
+ if (massGetter) { // data()
+ return data;
+ } else {
+ if (isSimpleGetter) { // data('key')
+ // don't force creation of expandoStore if it doesn't exist yet
+ return data && data[key];
+ } else { // mass-setter: data({key1: val1, key2: val2})
+ extend(data, key);
+ }
+ }
+ }
+ }
+}
+
+function jqLiteHasClass(element, selector) {
+ if (!element.getAttribute) return false;
+ return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
+ indexOf(" " + selector + " ") > -1);
+}
+
+function jqLiteRemoveClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ forEach(cssClasses.split(' '), function(cssClass) {
+ element.setAttribute('class', trim(
+ (" " + (element.getAttribute('class') || '') + " ")
+ .replace(/[\n\t]/g, " ")
+ .replace(" " + trim(cssClass) + " ", " "))
+ );
+ });
+ }
+}
+
+function jqLiteAddClass(element, cssClasses) {
+ if (cssClasses && element.setAttribute) {
+ var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
+ .replace(/[\n\t]/g, " ");
+
+ forEach(cssClasses.split(' '), function(cssClass) {
+ cssClass = trim(cssClass);
+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
+ existingClasses += cssClass + ' ';
+ }
+ });
+
+ element.setAttribute('class', trim(existingClasses));
+ }
+}
+
+
+function jqLiteAddNodes(root, elements) {
+ // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
+
+ if (elements) {
+
+ // if a Node (the most common case)
+ if (elements.nodeType) {
+ root[root.length++] = elements;
+ } else {
+ var length = elements.length;
+
+ // if an Array or NodeList and not a Window
+ if (typeof length === 'number' && elements.window !== elements) {
+ if (length) {
+ for (var i = 0; i < length; i++) {
+ root[root.length++] = elements[i];
+ }
+ }
+ } else {
+ root[root.length++] = elements;
+ }
+ }
+ }
+}
+
+
+function jqLiteController(element, name) {
+ return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
+}
+
+function jqLiteInheritedData(element, name, value) {
+ // if element is the document object work with the html element instead
+ // this makes $(document).scope() possible
+ if (element.nodeType == NODE_TYPE_DOCUMENT) {
+ element = element.documentElement;
+ }
+ var names = isArray(name) ? name : [name];
+
+ while (element) {
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ if (isDefined(value = jqLite.data(element, names[i]))) return value;
+ }
+
+ // If dealing with a document fragment node with a host element, and no parent, use the host
+ // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
+ // to lookup parent controllers.
+ element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
+ }
+}
+
+function jqLiteEmpty(element) {
+ jqLiteDealoc(element, true);
+ while (element.firstChild) {
+ element.removeChild(element.firstChild);
+ }
+}
+
+function jqLiteRemove(element, keepData) {
+ if (!keepData) jqLiteDealoc(element);
+ var parent = element.parentNode;
+ if (parent) parent.removeChild(element);
+}
+
+
+function jqLiteDocumentLoaded(action, win) {
+ win = win || window;
+ if (win.document.readyState === 'complete') {
+ // Force the action to be run async for consistent behaviour
+ // from the action's point of view
+ // i.e. it will definitely not be in a $apply
+ win.setTimeout(action);
+ } else {
+ // No need to unbind this handler as load is only ever called once
+ jqLite(win).on('load', action);
+ }
+}
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = {
+ ready: function(fn) {
+ var fired = false;
+
+ function trigger() {
+ if (fired) return;
+ fired = true;
+ fn();
+ }
+
+ // check if document is already loaded
+ if (document.readyState === 'complete') {
+ setTimeout(trigger);
+ } else {
+ this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
+ // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+ // jshint -W064
+ JQLite(window).on('load', trigger); // fallback to window.onload for others
+ // jshint +W064
+ }
+ },
+ toString: function() {
+ var value = [];
+ forEach(this, function(e) { value.push('' + e);});
+ return '[' + value.join(', ') + ']';
+ },
+
+ eq: function(index) {
+ return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+ },
+
+ length: 0,
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+var BOOLEAN_ATTR = {};
+forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
+ BOOLEAN_ATTR[lowercase(value)] = value;
+});
+var BOOLEAN_ELEMENTS = {};
+forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
+ BOOLEAN_ELEMENTS[value] = true;
+});
+var ALIASED_ATTR = {
+ 'ngMinlength': 'minlength',
+ 'ngMaxlength': 'maxlength',
+ 'ngMin': 'min',
+ 'ngMax': 'max',
+ 'ngPattern': 'pattern'
+};
+
+function getBooleanAttrName(element, name) {
+ // check dom last since we will most likely fail on name
+ var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+ // booleanAttr is here twice to minimize DOM access
+ return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
+}
+
+function getAliasedAttrName(name) {
+ return ALIASED_ATTR[name];
+}
+
+forEach({
+ data: jqLiteData,
+ removeData: jqLiteRemoveData,
+ hasData: jqLiteHasData
+}, function(fn, name) {
+ JQLite[name] = fn;
+});
+
+forEach({
+ data: jqLiteData,
+ inheritedData: jqLiteInheritedData,
+
+ scope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
+ },
+
+ isolateScope: function(element) {
+ // Can't use jqLiteData here directly so we stay compatible with jQuery!
+ return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
+ },
+
+ controller: jqLiteController,
+
+ injector: function(element) {
+ return jqLiteInheritedData(element, '$injector');
+ },
+
+ removeAttr: function(element, name) {
+ element.removeAttribute(name);
+ },
+
+ hasClass: jqLiteHasClass,
+
+ css: function(element, name, value) {
+ name = camelCase(name);
+
+ if (isDefined(value)) {
+ element.style[name] = value;
+ } else {
+ return element.style[name];
+ }
+ },
+
+ attr: function(element, name, value) {
+ var nodeType = element.nodeType;
+ if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
+ return;
+ }
+ var lowercasedName = lowercase(name);
+ if (BOOLEAN_ATTR[lowercasedName]) {
+ if (isDefined(value)) {
+ if (!!value) {
+ element[name] = true;
+ element.setAttribute(name, lowercasedName);
+ } else {
+ element[name] = false;
+ element.removeAttribute(lowercasedName);
+ }
+ } else {
+ return (element[name] ||
+ (element.attributes.getNamedItem(name) || noop).specified)
+ ? lowercasedName
+ : undefined;
+ }
+ } else if (isDefined(value)) {
+ element.setAttribute(name, value);
+ } else if (element.getAttribute) {
+ // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+ // some elements (e.g. Document) don't have get attribute, so return undefined
+ var ret = element.getAttribute(name, 2);
+ // normalize non-existing attributes to undefined (as jQuery)
+ return ret === null ? undefined : ret;
+ }
+ },
+
+ prop: function(element, name, value) {
+ if (isDefined(value)) {
+ element[name] = value;
+ } else {
+ return element[name];
+ }
+ },
+
+ text: (function() {
+ getText.$dv = '';
+ return getText;
+
+ function getText(element, value) {
+ if (isUndefined(value)) {
+ var nodeType = element.nodeType;
+ return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
+ }
+ element.textContent = value;
+ }
+ })(),
+
+ val: function(element, value) {
+ if (isUndefined(value)) {
+ if (element.multiple && nodeName_(element) === 'select') {
+ var result = [];
+ forEach(element.options, function(option) {
+ if (option.selected) {
+ result.push(option.value || option.text);
+ }
+ });
+ return result.length === 0 ? null : result;
+ }
+ return element.value;
+ }
+ element.value = value;
+ },
+
+ html: function(element, value) {
+ if (isUndefined(value)) {
+ return element.innerHTML;
+ }
+ jqLiteDealoc(element, true);
+ element.innerHTML = value;
+ },
+
+ empty: jqLiteEmpty
+}, function(fn, name) {
+ /**
+ * Properties: writes return selection, reads return first value
+ */
+ JQLite.prototype[name] = function(arg1, arg2) {
+ var i, key;
+ var nodeCount = this.length;
+
+ // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+ // in a way that survives minification.
+ // jqLiteEmpty takes no arguments but is a setter.
+ if (fn !== jqLiteEmpty &&
+ (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
+ if (isObject(arg1)) {
+
+ // we are a write, but the object properties are the key/values
+ for (i = 0; i < nodeCount; i++) {
+ if (fn === jqLiteData) {
+ // data() takes the whole object in jQuery
+ fn(this[i], arg1);
+ } else {
+ for (key in arg1) {
+ fn(this[i], key, arg1[key]);
+ }
+ }
+ }
+ // return self for chaining
+ return this;
+ } else {
+ // we are a read, so read the first child.
+ // TODO: do we still need this?
+ var value = fn.$dv;
+ // Only if we have $dv do we iterate over all, otherwise it is just the first element.
+ var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
+ for (var j = 0; j < jj; j++) {
+ var nodeValue = fn(this[j], arg1, arg2);
+ value = value ? value + nodeValue : nodeValue;
+ }
+ return value;
+ }
+ } else {
+ // we are a write, so apply to all children
+ for (i = 0; i < nodeCount; i++) {
+ fn(this[i], arg1, arg2);
+ }
+ // return self for chaining
+ return this;
+ }
+ };
+});
+
+function createEventHandler(element, events) {
+ var eventHandler = function(event, type) {
+ // jQuery specific api
+ event.isDefaultPrevented = function() {
+ return event.defaultPrevented;
+ };
+
+ var eventFns = events[type || event.type];
+ var eventFnsLength = eventFns ? eventFns.length : 0;
+
+ if (!eventFnsLength) return;
+
+ if (isUndefined(event.immediatePropagationStopped)) {
+ var originalStopImmediatePropagation = event.stopImmediatePropagation;
+ event.stopImmediatePropagation = function() {
+ event.immediatePropagationStopped = true;
+
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ }
+
+ if (originalStopImmediatePropagation) {
+ originalStopImmediatePropagation.call(event);
+ }
+ };
+ }
+
+ event.isImmediatePropagationStopped = function() {
+ return event.immediatePropagationStopped === true;
+ };
+
+ // Some events have special handlers that wrap the real handler
+ var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ if ((eventFnsLength > 1)) {
+ eventFns = shallowCopy(eventFns);
+ }
+
+ for (var i = 0; i < eventFnsLength; i++) {
+ if (!event.isImmediatePropagationStopped()) {
+ handlerWrapper(element, event, eventFns[i]);
+ }
+ }
+ };
+
+ // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
+ // events on `element`
+ eventHandler.elem = element;
+ return eventHandler;
+}
+
+function defaultHandlerWrapper(element, event, handler) {
+ handler.call(element, event);
+}
+
+function specialMouseHandlerWrapper(target, event, handler) {
+ // Refer to jQuery's implementation of mouseenter & mouseleave
+ // Read about mouseenter and mouseleave:
+ // http://www.quirksmode.org/js/events_mouse.html#link8
+ var related = event.relatedTarget;
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if (!related || (related !== target && !jqLiteContains.call(target, related))) {
+ handler.call(target, event);
+ }
+}
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+ removeData: jqLiteRemoveData,
+
+ on: function jqLiteOn(element, type, fn, unsupported) {
+ if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
+
+ // Do not add event handlers to non-elements because they will not be cleaned up.
+ if (!jqLiteAcceptsData(element)) {
+ return;
+ }
+
+ var expandoStore = jqLiteExpandoStore(element, true);
+ var events = expandoStore.events;
+ var handle = expandoStore.handle;
+
+ if (!handle) {
+ handle = expandoStore.handle = createEventHandler(element, events);
+ }
+
+ // http://jsperf.com/string-indexof-vs-split
+ var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
+ var i = types.length;
+
+ var addHandler = function(type, specialHandlerWrapper, noEventListener) {
+ var eventFns = events[type];
+
+ if (!eventFns) {
+ eventFns = events[type] = [];
+ eventFns.specialHandlerWrapper = specialHandlerWrapper;
+ if (type !== '$destroy' && !noEventListener) {
+ addEventListenerFn(element, type, handle);
+ }
+ }
+
+ eventFns.push(fn);
+ };
+
+ while (i--) {
+ type = types[i];
+ if (MOUSE_EVENT_MAP[type]) {
+ addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
+ addHandler(type, undefined, true);
+ } else {
+ addHandler(type);
+ }
+ }
+ },
+
+ off: jqLiteOff,
+
+ one: function(element, type, fn) {
+ element = jqLite(element);
+
+ //add the listener twice so that when it is called
+ //you can remove the original function and still be
+ //able to call element.off(ev, fn) normally
+ element.on(type, function onFn() {
+ element.off(type, fn);
+ element.off(type, onFn);
+ });
+ element.on(type, fn);
+ },
+
+ replaceWith: function(element, replaceNode) {
+ var index, parent = element.parentNode;
+ jqLiteDealoc(element);
+ forEach(new JQLite(replaceNode), function(node) {
+ if (index) {
+ parent.insertBefore(node, index.nextSibling);
+ } else {
+ parent.replaceChild(node, element);
+ }
+ index = node;
+ });
+ },
+
+ children: function(element) {
+ var children = [];
+ forEach(element.childNodes, function(element) {
+ if (element.nodeType === NODE_TYPE_ELEMENT) {
+ children.push(element);
+ }
+ });
+ return children;
+ },
+
+ contents: function(element) {
+ return element.contentDocument || element.childNodes || [];
+ },
+
+ append: function(element, node) {
+ var nodeType = element.nodeType;
+ if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
+
+ node = new JQLite(node);
+
+ for (var i = 0, ii = node.length; i < ii; i++) {
+ var child = node[i];
+ element.appendChild(child);
+ }
+ },
+
+ prepend: function(element, node) {
+ if (element.nodeType === NODE_TYPE_ELEMENT) {
+ var index = element.firstChild;
+ forEach(new JQLite(node), function(child) {
+ element.insertBefore(child, index);
+ });
+ }
+ },
+
+ wrap: function(element, wrapNode) {
+ wrapNode = jqLite(wrapNode).eq(0).clone()[0];
+ var parent = element.parentNode;
+ if (parent) {
+ parent.replaceChild(wrapNode, element);
+ }
+ wrapNode.appendChild(element);
+ },
+
+ remove: jqLiteRemove,
+
+ detach: function(element) {
+ jqLiteRemove(element, true);
+ },
+
+ after: function(element, newElement) {
+ var index = element, parent = element.parentNode;
+ newElement = new JQLite(newElement);
+
+ for (var i = 0, ii = newElement.length; i < ii; i++) {
+ var node = newElement[i];
+ parent.insertBefore(node, index.nextSibling);
+ index = node;
+ }
+ },
+
+ addClass: jqLiteAddClass,
+ removeClass: jqLiteRemoveClass,
+
+ toggleClass: function(element, selector, condition) {
+ if (selector) {
+ forEach(selector.split(' '), function(className) {
+ var classCondition = condition;
+ if (isUndefined(classCondition)) {
+ classCondition = !jqLiteHasClass(element, className);
+ }
+ (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
+ });
+ }
+ },
+
+ parent: function(element) {
+ var parent = element.parentNode;
+ return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
+ },
+
+ next: function(element) {
+ return element.nextElementSibling;
+ },
+
+ find: function(element, selector) {
+ if (element.getElementsByTagName) {
+ return element.getElementsByTagName(selector);
+ } else {
+ return [];
+ }
+ },
+
+ clone: jqLiteClone,
+
+ triggerHandler: function(element, event, extraParameters) {
+
+ var dummyEvent, eventFnsCopy, handlerArgs;
+ var eventName = event.type || event;
+ var expandoStore = jqLiteExpandoStore(element);
+ var events = expandoStore && expandoStore.events;
+ var eventFns = events && events[eventName];
+
+ if (eventFns) {
+ // Create a dummy event to pass to the handlers
+ dummyEvent = {
+ preventDefault: function() { this.defaultPrevented = true; },
+ isDefaultPrevented: function() { return this.defaultPrevented === true; },
+ stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
+ isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
+ stopPropagation: noop,
+ type: eventName,
+ target: element
+ };
+
+ // If a custom event was provided then extend our dummy event with it
+ if (event.type) {
+ dummyEvent = extend(dummyEvent, event);
+ }
+
+ // Copy event handlers in case event handlers array is modified during execution.
+ eventFnsCopy = shallowCopy(eventFns);
+ handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
+
+ forEach(eventFnsCopy, function(fn) {
+ if (!dummyEvent.isImmediatePropagationStopped()) {
+ fn.apply(element, handlerArgs);
+ }
+ });
+ }
+ }
+}, function(fn, name) {
+ /**
+ * chaining functions
+ */
+ JQLite.prototype[name] = function(arg1, arg2, arg3) {
+ var value;
+
+ for (var i = 0, ii = this.length; i < ii; i++) {
+ if (isUndefined(value)) {
+ value = fn(this[i], arg1, arg2, arg3);
+ if (isDefined(value)) {
+ // any function which returns a value needs to be wrapped
+ value = jqLite(value);
+ }
+ } else {
+ jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
+ }
+ }
+ return isDefined(value) ? value : this;
+ };
+
+ // bind legacy bind/unbind to on/off
+ JQLite.prototype.bind = JQLite.prototype.on;
+ JQLite.prototype.unbind = JQLite.prototype.off;
+});
+
+
+// Provider for private $$jqLite service
+function $$jqLiteProvider() {
+ this.$get = function $$jqLite() {
+ return extend(JQLite, {
+ hasClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteHasClass(node, classes);
+ },
+ addClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteAddClass(node, classes);
+ },
+ removeClass: function(node, classes) {
+ if (node.attr) node = node[0];
+ return jqLiteRemoveClass(node, classes);
+ }
+ });
+ };
+}
+
+/**
+ * Computes a hash of an 'obj'.
+ * Hash of a:
+ * string is string
+ * number is number as string
+ * object is either result of calling $$hashKey function on the object or uniquely generated id,
+ * that is also assigned to the $$hashKey property of the object.
+ *
+ * @param obj
+ * @returns {string} hash string such that the same input will have the same hash string.
+ * The resulting string key is in 'type:hashKey' format.
+ */
+function hashKey(obj, nextUidFn) {
+ var key = obj && obj.$$hashKey;
+
+ if (key) {
+ if (typeof key === 'function') {
+ key = obj.$$hashKey();
+ }
+ return key;
+ }
+
+ var objType = typeof obj;
+ if (objType == 'function' || (objType == 'object' && obj !== null)) {
+ key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
+ } else {
+ key = objType + ':' + obj;
+ }
+
+ return key;
+}
+
+/**
+ * HashMap which can use objects as keys
+ */
+function HashMap(array, isolatedUid) {
+ if (isolatedUid) {
+ var uid = 0;
+ this.nextUid = function() {
+ return ++uid;
+ };
+ }
+ forEach(array, this.put, this);
+}
+HashMap.prototype = {
+ /**
+ * Store key value pair
+ * @param key key to store can be any type
+ * @param value value to store can be any type
+ */
+ put: function(key, value) {
+ this[hashKey(key, this.nextUid)] = value;
+ },
+
+ /**
+ * @param key
+ * @returns {Object} the value for the key
+ */
+ get: function(key) {
+ return this[hashKey(key, this.nextUid)];
+ },
+
+ /**
+ * Remove the key/value pair
+ * @param key
+ */
+ remove: function(key) {
+ var value = this[key = hashKey(key, this.nextUid)];
+ delete this[key];
+ return value;
+ }
+};
+
+var $$HashMapProvider = [function() {
+ this.$get = [function() {
+ return HashMap;
+ }];
+}];
+
+/**
+ * @ngdoc function
+ * @module ng
+ * @name angular.injector
+ * @kind function
+ *
+ * @description
+ * Creates an injector object that can be used for retrieving services as well as for
+ * dependency injection (see {@link guide/di dependency injection}).
+ *
+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+ * {@link angular.module}. The `ng` module must be explicitly added.
+ * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
+ * disallows argument name annotation inference.
+ * @returns {injector} Injector object. See {@link auto.$injector $injector}.
+ *
+ * @example
+ * Typical usage
+ * ```js
+ * // create an injector
+ * var $injector = angular.injector(['ng']);
+ *
+ * // use the injector to kick off your application
+ * // use the type inference to auto inject arguments, or use implicit injection
+ * $injector.invoke(function($rootScope, $compile, $document) {
+ * $compile($document)($rootScope);
+ * $rootScope.$digest();
+ * });
+ * ```
+ *
+ * Sometimes you want to get access to the injector of a currently running Angular app
+ * from outside Angular. Perhaps, you want to inject and compile some markup after the
+ * application has been bootstrapped. You can do this using the extra `injector()` added
+ * to JQuery/jqLite elements. See {@link angular.element}.
+ *
+ * *This is fairly rare but could be the case if a third party library is injecting the
+ * markup.*
+ *
+ * In the following example a new block of HTML containing a `ng-controller`
+ * directive is added to the end of the document body by JQuery. We then compile and link
+ * it into the current AngularJS scope.
+ *
+ * ```js
+ * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
+ * $(document.body).append($div);
+ *
+ * angular.element(document).injector().invoke(function($compile) {
+ * var scope = angular.element($div).scope();
+ * $compile($div)(scope);
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc module
+ * @name auto
+ * @description
+ *
+ * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
+ */
+
+var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+var $injectorMinErr = minErr('$injector');
+
+function anonFn(fn) {
+ // For anonymous functions, showing at the very least the function signature can help in
+ // debugging.
+ var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
+ args = fnText.match(FN_ARGS);
+ if (args) {
+ return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
+ }
+ return 'fn';
+}
+
+function annotate(fn, strictDi, name) {
+ var $inject,
+ fnText,
+ argDecl,
+ last;
+
+ if (typeof fn === 'function') {
+ if (!($inject = fn.$inject)) {
+ $inject = [];
+ if (fn.length) {
+ if (strictDi) {
+ if (!isString(name) || !name) {
+ name = fn.name || anonFn(fn);
+ }
+ throw $injectorMinErr('strictdi',
+ '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
+ }
+ fnText = fn.toString().replace(STRIP_COMMENTS, '');
+ argDecl = fnText.match(FN_ARGS);
+ forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
+ arg.replace(FN_ARG, function(all, underscore, name) {
+ $inject.push(name);
+ });
+ });
+ }
+ fn.$inject = $inject;
+ }
+ } else if (isArray(fn)) {
+ last = fn.length - 1;
+ assertArgFn(fn[last], 'fn');
+ $inject = fn.slice(0, last);
+ } else {
+ assertArgFn(fn, 'fn', true);
+ }
+ return $inject;
+}
+
+///////////////////////////////////////
+
+/**
+ * @ngdoc service
+ * @name $injector
+ *
+ * @description
+ *
+ * `$injector` is used to retrieve object instances as defined by
+ * {@link auto.$provide provider}, instantiate types, invoke methods,
+ * and load modules.
+ *
+ * The following always holds true:
+ *
+ * ```js
+ * var $injector = angular.injector();
+ * expect($injector.get('$injector')).toBe($injector);
+ * expect($injector.invoke(function($injector) {
+ * return $injector;
+ * })).toBe($injector);
+ * ```
+ *
+ * # Injection Function Annotation
+ *
+ * JavaScript does not have annotations, and annotations are needed for dependency injection. The
+ * following are all valid ways of annotating function with injection arguments and are equivalent.
+ *
+ * ```js
+ * // inferred (only works if code not minified/obfuscated)
+ * $injector.invoke(function(serviceA){});
+ *
+ * // annotated
+ * function explicit(serviceA) {};
+ * explicit.$inject = ['serviceA'];
+ * $injector.invoke(explicit);
+ *
+ * // inline
+ * $injector.invoke(['serviceA', function(serviceA){}]);
+ * ```
+ *
+ * ## Inference
+ *
+ * In JavaScript calling `toString()` on a function returns the function definition. The definition
+ * can then be parsed and the function arguments can be extracted. This method of discovering
+ * annotations is disallowed when the injector is in strict mode.
+ * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
+ * argument names.
+ *
+ * ## `$inject` Annotation
+ * By adding an `$inject` property onto a function the injection parameters can be specified.
+ *
+ * ## Inline
+ * As an array of injection names, where the last item in the array is the function to call.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#get
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @param {string=} caller An optional string to provide the origin of the function call for error messages.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#invoke
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
+ * injected according to the {@link guide/di $inject Annotation} rules.
+ * @param {Object=} self The `this` for the invoked method.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {*} the value returned by the invoked `fn` function.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#has
+ *
+ * @description
+ * Allows the user to query if the particular service exists.
+ *
+ * @param {string} name Name of the service to query.
+ * @returns {boolean} `true` if injector has given service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#instantiate
+ * @description
+ * Create a new instance of JS type. The method takes a constructor function, invokes the new
+ * operator, and supplies all of the arguments to the constructor function as specified by the
+ * constructor annotation.
+ *
+ * @param {Function} Type Annotated constructor function.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this
+ * object first, before the `$injector` is consulted.
+ * @returns {Object} new instance of `Type`.
+ */
+
+/**
+ * @ngdoc method
+ * @name $injector#annotate
+ *
+ * @description
+ * Returns an array of service names which the function is requesting for injection. This API is
+ * used by the injector to determine which services need to be injected into the function when the
+ * function is invoked. There are three ways in which the function can be annotated with the needed
+ * dependencies.
+ *
+ * # Argument names
+ *
+ * The simplest form is to extract the dependencies from the arguments of the function. This is done
+ * by converting the function into a string using `toString()` method and extracting the argument
+ * names.
+ * ```js
+ * // Given
+ * function MyController($scope, $route) {
+ * // ...
+ * }
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * ```
+ *
+ * You can disallow this method by using strict injection mode.
+ *
+ * This method does not work with code minification / obfuscation. For this reason the following
+ * annotation strategies are supported.
+ *
+ * # The `$inject` property
+ *
+ * If a function has an `$inject` property and its value is an array of strings, then the strings
+ * represent names of services to be injected into the function.
+ * ```js
+ * // Given
+ * var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ * // ...
+ * }
+ * // Define function dependencies
+ * MyController['$inject'] = ['$scope', '$route'];
+ *
+ * // Then
+ * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * ```
+ *
+ * # The array notation
+ *
+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property
+ * is very inconvenient. In these situations using the array notation to specify the dependencies in
+ * a way that survives minification is a better choice:
+ *
+ * ```js
+ * // We wish to write this (not minification / obfuscation safe)
+ * injector.invoke(function($compile, $rootScope) {
+ * // ...
+ * });
+ *
+ * // We are forced to write break inlining
+ * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ * // ...
+ * };
+ * tmpFn.$inject = ['$compile', '$rootScope'];
+ * injector.invoke(tmpFn);
+ *
+ * // To better support inline function the inline annotation is supported
+ * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ * // ...
+ * }]);
+ *
+ * // Therefore
+ * expect(injector.annotate(
+ * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
+ * ).toEqual(['$compile', '$rootScope']);
+ * ```
+ *
+ * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
+ * be retrieved as described above.
+ *
+ * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
+ *
+ * @returns {Array.<string>} The names of the services which the function requires.
+ */
+
+
+
+
+/**
+ * @ngdoc service
+ * @name $provide
+ *
+ * @description
+ *
+ * The {@link auto.$provide $provide} service has a number of methods for registering components
+ * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
+ * {@link angular.Module}.
+ *
+ * An Angular **service** is a singleton object created by a **service factory**. These **service
+ * factories** are functions which, in turn, are created by a **service provider**.
+ * The **service providers** are constructor functions. When instantiated they must contain a
+ * property called `$get`, which holds the **service factory** function.
+ *
+ * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
+ * correct **service provider**, instantiating it and then calling its `$get` **service factory**
+ * function to get the instance of the **service**.
+ *
+ * Often services have no configuration options and there is no need to add methods to the service
+ * provider. The provider will be no more than a constructor function with a `$get` property. For
+ * these cases the {@link auto.$provide $provide} service has additional helper methods to register
+ * services without specifying a provider.
+ *
+ * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
+ * {@link auto.$injector $injector}
+ * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
+ * providers and services.
+ * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
+ * services, not providers.
+ * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
+ * that will be wrapped in a **service provider** object, whose `$get` property will contain the
+ * given factory function.
+ * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
+ * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
+ * a new object using the given constructor function.
+ *
+ * See the individual methods for more information and examples.
+ */
+
+/**
+ * @ngdoc method
+ * @name $provide#provider
+ * @description
+ *
+ * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
+ * are constructor functions, whose instances are responsible for "providing" a factory for a
+ * service.
+ *
+ * Service provider names start with the name of the service they provide followed by `Provider`.
+ * For example, the {@link ng.$log $log} service has a provider called
+ * {@link ng.$logProvider $logProvider}.
+ *
+ * Service provider objects can have additional methods which allow configuration of the provider
+ * and its service. Importantly, you can configure what kind of service is created by the `$get`
+ * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
+ * method {@link ng.$logProvider#debugEnabled debugEnabled}
+ * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
+ * console or not.
+ *
+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
+ 'Provider'` key.
+ * @param {(Object|function())} provider If the provider is:
+ *
+ * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
+ * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
+ * - `Constructor`: a new instance of the provider will be created using
+ * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
+ *
+ * @returns {Object} registered provider instance
+
+ * @example
+ *
+ * The following example shows how to create a simple event tracking service and register it using
+ * {@link auto.$provide#provider $provide.provider()}.
+ *
+ * ```js
+ * // Define the eventTracker provider
+ * function EventTrackerProvider() {
+ * var trackingUrl = '/track';
+ *
+ * // A provider method for configuring where the tracked events should been saved
+ * this.setTrackingUrl = function(url) {
+ * trackingUrl = url;
+ * };
+ *
+ * // The service factory function
+ * this.$get = ['$http', function($http) {
+ * var trackedEvents = {};
+ * return {
+ * // Call this to track an event
+ * event: function(event) {
+ * var count = trackedEvents[event] || 0;
+ * count += 1;
+ * trackedEvents[event] = count;
+ * return count;
+ * },
+ * // Call this to save the tracked events to the trackingUrl
+ * save: function() {
+ * $http.post(trackingUrl, trackedEvents);
+ * }
+ * };
+ * }];
+ * }
+ *
+ * describe('eventTracker', function() {
+ * var postSpy;
+ *
+ * beforeEach(module(function($provide) {
+ * // Register the eventTracker provider
+ * $provide.provider('eventTracker', EventTrackerProvider);
+ * }));
+ *
+ * beforeEach(module(function(eventTrackerProvider) {
+ * // Configure eventTracker provider
+ * eventTrackerProvider.setTrackingUrl('/custom-track');
+ * }));
+ *
+ * it('tracks events', inject(function(eventTracker) {
+ * expect(eventTracker.event('login')).toEqual(1);
+ * expect(eventTracker.event('login')).toEqual(2);
+ * }));
+ *
+ * it('saves to the tracking url', inject(function(eventTracker, $http) {
+ * postSpy = spyOn($http, 'post');
+ * eventTracker.event('login');
+ * eventTracker.save();
+ * expect(postSpy).toHaveBeenCalled();
+ * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ * }));
+ * });
+ * ```
+ */
+
+/**
+ * @ngdoc method
+ * @name $provide#factory
+ * @description
+ *
+ * Register a **service factory**, which will be called to return the service instance.
+ * This is short for registering a service where its provider consists of only a `$get` property,
+ * which is the given service factory function.
+ * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
+ * configure your service in a provider.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
+ * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service
+ * ```js
+ * $provide.factory('ping', ['$http', function($http) {
+ * return function ping() {
+ * return $http.send('/ping');
+ * };
+ * }]);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#service
+ * @description
+ *
+ * Register a **service constructor**, which will be invoked with `new` to create the service
+ * instance.
+ * This is short for registering a service where its provider's `$get` property is the service
+ * constructor function that will be used to instantiate the service instance.
+ *
+ * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
+ * as a type/class.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
+ * that will be instantiated.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here is an example of registering a service using
+ * {@link auto.$provide#service $provide.service(class)}.
+ * ```js
+ * var Ping = function($http) {
+ * this.$http = $http;
+ * };
+ *
+ * Ping.$inject = ['$http'];
+ *
+ * Ping.prototype.send = function() {
+ * return this.$http.get('/ping');
+ * };
+ * $provide.service('ping', Ping);
+ * ```
+ * You would then inject and use this service like this:
+ * ```js
+ * someModule.controller('Ctrl', ['ping', function(ping) {
+ * ping.send();
+ * }]);
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#value
+ * @description
+ *
+ * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
+ * number, an array, an object or a function. This is short for registering a service where its
+ * provider's `$get` property is a factory function that takes no arguments and returns the **value
+ * service**.
+ *
+ * Value services are similar to constant services, except that they cannot be injected into a
+ * module configuration function (see {@link angular.Module#config}) but they can be overridden by
+ * an Angular
+ * {@link auto.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the instance.
+ * @param {*} value The value.
+ * @returns {Object} registered provider instance
+ *
+ * @example
+ * Here are some examples of creating value services.
+ * ```js
+ * $provide.value('ADMIN_USER', 'admin');
+ *
+ * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *
+ * $provide.value('halfOf', function(value) {
+ * return value / 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#constant
+ * @description
+ *
+ * Register a **constant service**, such as a string, a number, an array, an object or a function,
+ * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
+ * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
+ * be overridden by an Angular {@link auto.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the constant.
+ * @param {*} value The constant value.
+ * @returns {Object} registered instance
+ *
+ * @example
+ * Here a some examples of creating constants:
+ * ```js
+ * $provide.constant('SHARD_HEIGHT', 306);
+ *
+ * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *
+ * $provide.constant('double', function(value) {
+ * return value * 2;
+ * });
+ * ```
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $provide#decorator
+ * @description
+ *
+ * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
+ * intercepts the creation of a service, allowing it to override or modify the behaviour of the
+ * service. The object returned by the decorator may be the original service, or a new service
+ * object which replaces or wraps and delegates to the original service.
+ *
+ * @param {string} name The name of the service to decorate.
+ * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
+ * instantiated and should return the decorated service instance. The function is called using
+ * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
+ * Local injection arguments:
+ *
+ * * `$delegate` - The original service instance, which can be monkey patched, configured,
+ * decorated or delegated to.
+ *
+ * @example
+ * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
+ * calls to {@link ng.$log#error $log.warn()}.
+ * ```js
+ * $provide.decorator('$log', ['$delegate', function($delegate) {
+ * $delegate.warn = $delegate.error;
+ * return $delegate;
+ * }]);
+ * ```
+ */
+
+
+function createInjector(modulesToLoad, strictDi) {
+ strictDi = (strictDi === true);
+ var INSTANTIATING = {},
+ providerSuffix = 'Provider',
+ path = [],
+ loadedModules = new HashMap([], true),
+ providerCache = {
+ $provide: {
+ provider: supportObject(provider),
+ factory: supportObject(factory),
+ service: supportObject(service),
+ value: supportObject(value),
+ constant: supportObject(constant),
+ decorator: decorator
+ }
+ },
+ providerInjector = (providerCache.$injector =
+ createInternalInjector(providerCache, function(serviceName, caller) {
+ if (angular.isString(caller)) {
+ path.push(caller);
+ }
+ throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
+ })),
+ instanceCache = {},
+ instanceInjector = (instanceCache.$injector =
+ createInternalInjector(instanceCache, function(serviceName, caller) {
+ var provider = providerInjector.get(serviceName + providerSuffix, caller);
+ return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
+ }));
+
+
+ forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
+
+ return instanceInjector;
+
+ ////////////////////////////////////
+ // $provider
+ ////////////////////////////////////
+
+ function supportObject(delegate) {
+ return function(key, value) {
+ if (isObject(key)) {
+ forEach(key, reverseParams(delegate));
+ } else {
+ return delegate(key, value);
+ }
+ };
+ }
+
+ function provider(name, provider_) {
+ assertNotHasOwnProperty(name, 'service');
+ if (isFunction(provider_) || isArray(provider_)) {
+ provider_ = providerInjector.instantiate(provider_);
+ }
+ if (!provider_.$get) {
+ throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
+ }
+ return providerCache[name + providerSuffix] = provider_;
+ }
+
+ function enforceReturnValue(name, factory) {
+ return function enforcedReturnValue() {
+ var result = instanceInjector.invoke(factory, this);
+ if (isUndefined(result)) {
+ throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
+ }
+ return result;
+ };
+ }
+
+ function factory(name, factoryFn, enforce) {
+ return provider(name, {
+ $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
+ });
+ }
+
+ function service(name, constructor) {
+ return factory(name, ['$injector', function($injector) {
+ return $injector.instantiate(constructor);
+ }]);
+ }
+
+ function value(name, val) { return factory(name, valueFn(val), false); }
+
+ function constant(name, value) {
+ assertNotHasOwnProperty(name, 'constant');
+ providerCache[name] = value;
+ instanceCache[name] = value;
+ }
+
+ function decorator(serviceName, decorFn) {
+ var origProvider = providerInjector.get(serviceName + providerSuffix),
+ orig$get = origProvider.$get;
+
+ origProvider.$get = function() {
+ var origInstance = instanceInjector.invoke(orig$get, origProvider);
+ return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
+ };
+ }
+
+ ////////////////////////////////////
+ // Module Loading
+ ////////////////////////////////////
+ function loadModules(modulesToLoad) {
+ assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
+ var runBlocks = [], moduleFn;
+ forEach(modulesToLoad, function(module) {
+ if (loadedModules.get(module)) return;
+ loadedModules.put(module, true);
+
+ function runInvokeQueue(queue) {
+ var i, ii;
+ for (i = 0, ii = queue.length; i < ii; i++) {
+ var invokeArgs = queue[i],
+ provider = providerInjector.get(invokeArgs[0]);
+
+ provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+ }
+ }
+
+ try {
+ if (isString(module)) {
+ moduleFn = angularModule(module);
+ runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+ runInvokeQueue(moduleFn._invokeQueue);
+ runInvokeQueue(moduleFn._configBlocks);
+ } else if (isFunction(module)) {
+ runBlocks.push(providerInjector.invoke(module));
+ } else if (isArray(module)) {
+ runBlocks.push(providerInjector.invoke(module));
+ } else {
+ assertArgFn(module, 'module');
+ }
+ } catch (e) {
+ if (isArray(module)) {
+ module = module[module.length - 1];
+ }
+ if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
+ // Safari & FF's stack traces don't contain error.message content
+ // unlike those of Chrome and IE
+ // So if stack doesn't contain message, we create a new string that contains both.
+ // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
+ /* jshint -W022 */
+ e = e.message + '\n' + e.stack;
+ }
+ throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
+ module, e.stack || e.message || e);
+ }
+ });
+ return runBlocks;
+ }
+
+ ////////////////////////////////////
+ // internal Injector
+ ////////////////////////////////////
+
+ function createInternalInjector(cache, factory) {
+
+ function getService(serviceName, caller) {
+ if (cache.hasOwnProperty(serviceName)) {
+ if (cache[serviceName] === INSTANTIATING) {
+ throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
+ serviceName + ' <- ' + path.join(' <- '));
+ }
+ return cache[serviceName];
+ } else {
+ try {
+ path.unshift(serviceName);
+ cache[serviceName] = INSTANTIATING;
+ return cache[serviceName] = factory(serviceName, caller);
+ } catch (err) {
+ if (cache[serviceName] === INSTANTIATING) {
+ delete cache[serviceName];
+ }
+ throw err;
+ } finally {
+ path.shift();
+ }
+ }
+ }
+
+ function invoke(fn, self, locals, serviceName) {
+ if (typeof locals === 'string') {
+ serviceName = locals;
+ locals = null;
+ }
+
+ var args = [],
+ $inject = createInjector.$$annotate(fn, strictDi, serviceName),
+ length, i,
+ key;
+
+ for (i = 0, length = $inject.length; i < length; i++) {
+ key = $inject[i];
+ if (typeof key !== 'string') {
+ throw $injectorMinErr('itkn',
+ 'Incorrect injection token! Expected service name as string, got {0}', key);
+ }
+ args.push(
+ locals && locals.hasOwnProperty(key)
+ ? locals[key]
+ : getService(key, serviceName)
+ );
+ }
+ if (isArray(fn)) {
+ fn = fn[length];
+ }
+
+ // http://jsperf.com/angularjs-invoke-apply-vs-switch
+ // #5388
+ return fn.apply(self, args);
+ }
+
+ function instantiate(Type, locals, serviceName) {
+ // Check if Type is annotated and use just the given function at n-1 as parameter
+ // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
+ // Object creation: http://jsperf.com/create-constructor/2
+ var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
+ var returnedValue = invoke(Type, instance, locals, serviceName);
+
+ return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
+ }
+
+ return {
+ invoke: invoke,
+ instantiate: instantiate,
+ get: getService,
+ annotate: createInjector.$$annotate,
+ has: function(name) {
+ return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
+ }
+ };
+ }
+}
+
+createInjector.$$annotate = annotate;
+
+/**
+ * @ngdoc provider
+ * @name $anchorScrollProvider
+ *
+ * @description
+ * Use `$anchorScrollProvider` to disable automatic scrolling whenever
+ * {@link ng.$location#hash $location.hash()} changes.
+ */
+function $AnchorScrollProvider() {
+
+ var autoScrollingEnabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $anchorScrollProvider#disableAutoScrolling
+ *
+ * @description
+ * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
+ * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
+ * Use this method to disable automatic scrolling.
+ *
+ * If automatic scrolling is disabled, one must explicitly call
+ * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
+ * current hash.
+ */
+ this.disableAutoScrolling = function() {
+ autoScrollingEnabled = false;
+ };
+
+ /**
+ * @ngdoc service
+ * @name $anchorScroll
+ * @kind function
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
+ * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
+ * in the
+ * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
+ *
+ * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
+ * match any anchor whenever it changes. This can be disabled by calling
+ * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
+ *
+ * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
+ * vertical scroll-offset (either fixed or dynamic).
+ *
+ * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
+ * {@link ng.$location#hash $location.hash()} will be used.
+ *
+ * @property {(number|function|jqLite)} yOffset
+ * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
+ * positioned elements at the top of the page, such as navbars, headers etc.
+ *
+ * `yOffset` can be specified in various ways:
+ * - **number**: A fixed number of pixels to be used as offset.<br /><br />
+ * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
+ * a number representing the offset (in pixels).<br /><br />
+ * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
+ * the top of the page to the element's bottom will be used as offset.<br />
+ * **Note**: The element will be taken into account only as long as its `position` is set to
+ * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
+ * their height and/or positioning according to the viewport's size.
+ *
+ * <br />
+ * <div class="alert alert-warning">
+ * In order for `yOffset` to work properly, scrolling should take place on the document's root and
+ * not some child element.
+ * </div>
+ *
+ * @example
+ <example module="anchorScrollExample">
+ <file name="index.html">
+ <div id="scrollArea" ng-controller="ScrollController">
+ <a ng-click="gotoBottom()">Go to bottom</a>
+ <a id="bottom"></a> You're at the bottom!
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollExample', [])
+ .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
+ function ($scope, $location, $anchorScroll) {
+ $scope.gotoBottom = function() {
+ // set the location.hash to the id of
+ // the element you wish to scroll to.
+ $location.hash('bottom');
+
+ // call $anchorScroll()
+ $anchorScroll();
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ #scrollArea {
+ height: 280px;
+ overflow: auto;
+ }
+
+ #bottom {
+ display: block;
+ margin-top: 2000px;
+ }
+ </file>
+ </example>
+ *
+ * <hr />
+ * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
+ * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
+ *
+ * @example
+ <example module="anchorScrollOffsetExample">
+ <file name="index.html">
+ <div class="fixed-header" ng-controller="headerCtrl">
+ <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
+ Go to anchor {{x}}
+ </a>
+ </div>
+ <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
+ Anchor {{x}} of 5
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('anchorScrollOffsetExample', [])
+ .run(['$anchorScroll', function($anchorScroll) {
+ $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
+ }])
+ .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
+ function ($anchorScroll, $location, $scope) {
+ $scope.gotoAnchor = function(x) {
+ var newHash = 'anchor' + x;
+ if ($location.hash() !== newHash) {
+ // set the $location.hash to `newHash` and
+ // $anchorScroll will automatically scroll to it
+ $location.hash('anchor' + x);
+ } else {
+ // call $anchorScroll() explicitly,
+ // since $location.hash hasn't changed
+ $anchorScroll();
+ }
+ };
+ }
+ ]);
+ </file>
+ <file name="style.css">
+ body {
+ padding-top: 50px;
+ }
+
+ .anchor {
+ border: 2px dashed DarkOrchid;
+ padding: 10px 10px 200px 10px;
+ }
+
+ .fixed-header {
+ background-color: rgba(0, 0, 0, 0.2);
+ height: 50px;
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ }
+
+ .fixed-header > a {
+ display: inline-block;
+ margin: 5px 15px;
+ }
+ </file>
+ </example>
+ */
+ this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
+ var document = $window.document;
+
+ // Helper function to get first anchor from a NodeList
+ // (using `Array#some()` instead of `angular#forEach()` since it's more performant
+ // and working in all supported browsers.)
+ function getFirstAnchor(list) {
+ var result = null;
+ Array.prototype.some.call(list, function(element) {
+ if (nodeName_(element) === 'a') {
+ result = element;
+ return true;
+ }
+ });
+ return result;
+ }
+
+ function getYOffset() {
+
+ var offset = scroll.yOffset;
+
+ if (isFunction(offset)) {
+ offset = offset();
+ } else if (isElement(offset)) {
+ var elem = offset[0];
+ var style = $window.getComputedStyle(elem);
+ if (style.position !== 'fixed') {
+ offset = 0;
+ } else {
+ offset = elem.getBoundingClientRect().bottom;
+ }
+ } else if (!isNumber(offset)) {
+ offset = 0;
+ }
+
+ return offset;
+ }
+
+ function scrollTo(elem) {
+ if (elem) {
+ elem.scrollIntoView();
+
+ var offset = getYOffset();
+
+ if (offset) {
+ // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
+ // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
+ // top of the viewport.
+ //
+ // IF the number of pixels from the top of `elem` to the end of the page's content is less
+ // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
+ // way down the page.
+ //
+ // This is often the case for elements near the bottom of the page.
+ //
+ // In such cases we do not need to scroll the whole `offset` up, just the difference between
+ // the top of the element and the offset, which is enough to align the top of `elem` at the
+ // desired position.
+ var elemTop = elem.getBoundingClientRect().top;
+ $window.scrollBy(0, elemTop - offset);
+ }
+ } else {
+ $window.scrollTo(0, 0);
+ }
+ }
+
+ function scroll(hash) {
+ hash = isString(hash) ? hash : $location.hash();
+ var elm;
+
+ // empty hash, scroll to the top of the page
+ if (!hash) scrollTo(null);
+
+ // element with given id
+ else if ((elm = document.getElementById(hash))) scrollTo(elm);
+
+ // first anchor with given name :-D
+ else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
+
+ // no element and hash == 'top', scroll to the top of the page
+ else if (hash === 'top') scrollTo(null);
+ }
+
+ // does not scroll when user clicks on anchor link that is currently on
+ // (no url change, no $location.hash() change), browser native does scroll
+ if (autoScrollingEnabled) {
+ $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
+ function autoScrollWatchAction(newVal, oldVal) {
+ // skip the initial scroll if $location.hash is empty
+ if (newVal === oldVal && newVal === '') return;
+
+ jqLiteDocumentLoaded(function() {
+ $rootScope.$evalAsync(scroll);
+ });
+ });
+ }
+
+ return scroll;
+ }];
+}
+
+var $animateMinErr = minErr('$animate');
+var ELEMENT_NODE = 1;
+var NG_ANIMATE_CLASSNAME = 'ng-animate';
+
+function mergeClasses(a,b) {
+ if (!a && !b) return '';
+ if (!a) return b;
+ if (!b) return a;
+ if (isArray(a)) a = a.join(' ');
+ if (isArray(b)) b = b.join(' ');
+ return a + ' ' + b;
+}
+
+function extractElementNode(element) {
+ for (var i = 0; i < element.length; i++) {
+ var elm = element[i];
+ if (elm.nodeType === ELEMENT_NODE) {
+ return elm;
+ }
+ }
+}
+
+function splitClasses(classes) {
+ if (isString(classes)) {
+ classes = classes.split(' ');
+ }
+
+ // Use createMap() to prevent class assumptions involving property names in
+ // Object.prototype
+ var obj = createMap();
+ forEach(classes, function(klass) {
+ // sometimes the split leaves empty string values
+ // incase extra spaces were applied to the options
+ if (klass.length) {
+ obj[klass] = true;
+ }
+ });
+ return obj;
+}
+
+// if any other type of options value besides an Object value is
+// passed into the $animate.method() animation then this helper code
+// will be run which will ignore it. While this patch is not the
+// greatest solution to this, a lot of existing plugins depend on
+// $animate to either call the callback (< 1.2) or return a promise
+// that can be changed. This helper function ensures that the options
+// are wiped clean incase a callback function is provided.
+function prepareAnimateOptions(options) {
+ return isObject(options)
+ ? options
+ : {};
+}
+
+var $$CoreAnimateRunnerProvider = function() {
+ this.$get = ['$q', '$$rAF', function($q, $$rAF) {
+ function AnimateRunner() {}
+ AnimateRunner.all = noop;
+ AnimateRunner.chain = noop;
+ AnimateRunner.prototype = {
+ end: noop,
+ cancel: noop,
+ resume: noop,
+ pause: noop,
+ complete: noop,
+ then: function(pass, fail) {
+ return $q(function(resolve) {
+ $$rAF(function() {
+ resolve();
+ });
+ }).then(pass, fail);
+ }
+ };
+ return AnimateRunner;
+ }];
+};
+
+// this is prefixed with Core since it conflicts with
+// the animateQueueProvider defined in ngAnimate/animateQueue.js
+var $$CoreAnimateQueueProvider = function() {
+ var postDigestQueue = new HashMap();
+ var postDigestElements = [];
+
+ this.$get = ['$$AnimateRunner', '$rootScope',
+ function($$AnimateRunner, $rootScope) {
+ return {
+ enabled: noop,
+ on: noop,
+ off: noop,
+ pin: noop,
+
+ push: function(element, event, options, domOperation) {
+ domOperation && domOperation();
+
+ options = options || {};
+ options.from && element.css(options.from);
+ options.to && element.css(options.to);
+
+ if (options.addClass || options.removeClass) {
+ addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
+ }
+
+ return new $$AnimateRunner(); // jshint ignore:line
+ }
+ };
+
+
+ function updateData(data, classes, value) {
+ var changed = false;
+ if (classes) {
+ classes = isString(classes) ? classes.split(' ') :
+ isArray(classes) ? classes : [];
+ forEach(classes, function(className) {
+ if (className) {
+ changed = true;
+ data[className] = value;
+ }
+ });
+ }
+ return changed;
+ }
+
+ function handleCSSClassChanges() {
+ forEach(postDigestElements, function(element) {
+ var data = postDigestQueue.get(element);
+ if (data) {
+ var existing = splitClasses(element.attr('class'));
+ var toAdd = '';
+ var toRemove = '';
+ forEach(data, function(status, className) {
+ var hasClass = !!existing[className];
+ if (status !== hasClass) {
+ if (status) {
+ toAdd += (toAdd.length ? ' ' : '') + className;
+ } else {
+ toRemove += (toRemove.length ? ' ' : '') + className;
+ }
+ }
+ });
+
+ forEach(element, function(elm) {
+ toAdd && jqLiteAddClass(elm, toAdd);
+ toRemove && jqLiteRemoveClass(elm, toRemove);
+ });
+ postDigestQueue.remove(element);
+ }
+ });
+ postDigestElements.length = 0;
+ }
+
+
+ function addRemoveClassesPostDigest(element, add, remove) {
+ var data = postDigestQueue.get(element) || {};
+
+ var classesAdded = updateData(data, add, true);
+ var classesRemoved = updateData(data, remove, false);
+
+ if (classesAdded || classesRemoved) {
+
+ postDigestQueue.put(element, data);
+ postDigestElements.push(element);
+
+ if (postDigestElements.length === 1) {
+ $rootScope.$$postDigest(handleCSSClassChanges);
+ }
+ }
+ }
+ }];
+};
+
+/**
+ * @ngdoc provider
+ * @name $animateProvider
+ *
+ * @description
+ * Default implementation of $animate that doesn't perform any animations, instead just
+ * synchronously performs DOM updates and resolves the returned runner promise.
+ *
+ * In order to enable animations the `ngAnimate` module has to be loaded.
+ *
+ * To see the functional implementation check out `src/ngAnimate/animate.js`.
+ */
+var $AnimateProvider = ['$provide', function($provide) {
+ var provider = this;
+
+ this.$$registeredAnimations = Object.create(null);
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#register
+ *
+ * @description
+ * Registers a new injectable animation factory function. The factory function produces the
+ * animation object which contains callback functions for each event that is expected to be
+ * animated.
+ *
+ * * `eventFn`: `function(element, ... , doneFunction, options)`
+ * The element to animate, the `doneFunction` and the options fed into the animation. Depending
+ * on the type of animation additional arguments will be injected into the animation function. The
+ * list below explains the function signatures for the different animation methods:
+ *
+ * - setClass: function(element, addedClasses, removedClasses, doneFunction, options)
+ * - addClass: function(element, addedClasses, doneFunction, options)
+ * - removeClass: function(element, removedClasses, doneFunction, options)
+ * - enter, leave, move: function(element, doneFunction, options)
+ * - animate: function(element, fromStyles, toStyles, doneFunction, options)
+ *
+ * Make sure to trigger the `doneFunction` once the animation is fully complete.
+ *
+ * ```js
+ * return {
+ * //enter, leave, move signature
+ * eventFn : function(element, done, options) {
+ * //code to run the animation
+ * //once complete, then run done()
+ * return function endFunction(wasCancelled) {
+ * //code to cancel the animation
+ * }
+ * }
+ * }
+ * ```
+ *
+ * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
+ * @param {Function} factory The factory function that will be executed to return the animation
+ * object.
+ */
+ this.register = function(name, factory) {
+ if (name && name.charAt(0) !== '.') {
+ throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
+ }
+
+ var key = name + '-animation';
+ provider.$$registeredAnimations[name.substr(1)] = key;
+ $provide.factory(key, factory);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $animateProvider#classNameFilter
+ *
+ * @description
+ * Sets and/or returns the CSS class regular expression that is checked when performing
+ * an animation. Upon bootstrap the classNameFilter value is not set at all and will
+ * therefore enable $animate to attempt to perform an animation on any element that is triggered.
+ * When setting the `classNameFilter` value, animations will only be performed on elements
+ * that successfully match the filter expression. This in turn can boost performance
+ * for low-powered devices as well as applications containing a lot of structural operations.
+ * @param {RegExp=} expression The className expression which will be checked against all animations
+ * @return {RegExp} The current CSS className expression value. If null then there is no expression value
+ */
+ this.classNameFilter = function(expression) {
+ if (arguments.length === 1) {
+ this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
+ if (this.$$classNameFilter) {
+ var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
+ if (reservedRegex.test(this.$$classNameFilter.toString())) {
+ throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
+
+ }
+ }
+ }
+ return this.$$classNameFilter;
+ };
+
+ this.$get = ['$$animateQueue', function($$animateQueue) {
+ function domInsert(element, parentElement, afterElement) {
+ // if for some reason the previous element was removed
+ // from the dom sometime before this code runs then let's
+ // just stick to using the parent element as the anchor
+ if (afterElement) {
+ var afterNode = extractElementNode(afterElement);
+ if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
+ afterElement = null;
+ }
+ }
+ afterElement ? afterElement.after(element) : parentElement.prepend(element);
+ }
+
+ /**
+ * @ngdoc service
+ * @name $animate
+ * @description The $animate service exposes a series of DOM utility methods that provide support
+ * for animation hooks. The default behavior is the application of DOM operations, however,
+ * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
+ * to ensure that animation runs with the triggered DOM operation.
+ *
+ * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
+ * included and only when it is active then the animation hooks that `$animate` triggers will be
+ * functional. Once active then all structural `ng-` directives will trigger animations as they perform
+ * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
+ * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
+ *
+ * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
+ *
+ * To learn more about enabling animation support, click here to visit the
+ * {@link ngAnimate ngAnimate module page}.
+ */
+ return {
+ // we don't call it directly since non-existant arguments may
+ // be interpreted as null within the sub enabled function
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#on
+ * @kind function
+ * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
+ * has fired on the given element or among any of its children. Once the listener is fired, the provided callback
+ * is fired with the following params:
+ *
+ * ```js
+ * $animate.on('enter', container,
+ * function callback(element, phase) {
+ * // cool we detected an enter animation within the container
+ * }
+ * );
+ * ```
+ *
+ * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
+ * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
+ * as well as among its children
+ * @param {Function} callback the callback function that will be fired when the listener is triggered
+ *
+ * The arguments present in the callback function are:
+ * * `element` - The captured DOM element that the animation was fired on.
+ * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
+ */
+ on: $$animateQueue.on,
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#off
+ * @kind function
+ * @description Deregisters an event listener based on the event which has been associated with the provided element. This method
+ * can be used in three different ways depending on the arguments:
+ *
+ * ```js
+ * // remove all the animation event listeners listening for `enter`
+ * $animate.off('enter');
+ *
+ * // remove all the animation event listeners listening for `enter` on the given element and its children
+ * $animate.off('enter', container);
+ *
+ * // remove the event listener function provided by `listenerFn` that is set
+ * // to listen for `enter` on the given `element` as well as its children
+ * $animate.off('enter', container, callback);
+ * ```
+ *
+ * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
+ * @param {DOMElement=} container the container element the event listener was placed on
+ * @param {Function=} callback the callback function that was registered as the listener
+ */
+ off: $$animateQueue.off,
+
+ /**
+ * @ngdoc method
+ * @name $animate#pin
+ * @kind function
+ * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
+ * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
+ * element despite being outside the realm of the application or within another application. Say for example if the application
+ * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated
+ * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
+ * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
+ *
+ * Note that this feature is only active when the `ngAnimate` module is used.
+ *
+ * @param {DOMElement} element the external element that will be pinned
+ * @param {DOMElement} parentElement the host parent element that will be associated with the external element
+ */
+ pin: $$animateQueue.pin,
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#enabled
+ * @kind function
+ * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
+ * function can be called in four ways:
+ *
+ * ```js
+ * // returns true or false
+ * $animate.enabled();
+ *
+ * // changes the enabled state for all animations
+ * $animate.enabled(false);
+ * $animate.enabled(true);
+ *
+ * // returns true or false if animations are enabled for an element
+ * $animate.enabled(element);
+ *
+ * // changes the enabled state for an element and its children
+ * $animate.enabled(element, true);
+ * $animate.enabled(element, false);
+ * ```
+ *
+ * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
+ * @param {boolean=} enabled whether or not the animations will be enabled for the element
+ *
+ * @return {boolean} whether or not animations are enabled
+ */
+ enabled: $$animateQueue.enabled,
+
+ /**
+ * @ngdoc method
+ * @name $animate#cancel
+ * @kind function
+ * @description Cancels the provided animation.
+ *
+ * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
+ */
+ cancel: function(runner) {
+ runner.end && runner.end();
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#enter
+ * @kind function
+ * @description Inserts the element into the DOM either after the `after` element (if provided) or
+ * as the first child within the `parent` element and then triggers an animation.
+ * A promise is returned that will be resolved during the next digest once the animation
+ * has completed.
+ *
+ * @param {DOMElement} element the element which will be inserted into the DOM
+ * @param {DOMElement} parent the parent element which will append the element as
+ * a child (so long as the after element is not present)
+ * @param {DOMElement=} after the sibling element after which the element will be appended
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ enter: function(element, parent, after, options) {
+ parent = parent && jqLite(parent);
+ after = after && jqLite(after);
+ parent = parent || after.parent();
+ domInsert(element, parent, after);
+ return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
+ },
+
+ /**
+ *
+ * @ngdoc method
+ * @name $animate#move
+ * @kind function
+ * @description Inserts (moves) the element into its new position in the DOM either after
+ * the `after` element (if provided) or as the first child within the `parent` element
+ * and then triggers an animation. A promise is returned that will be resolved
+ * during the next digest once the animation has completed.
+ *
+ * @param {DOMElement} element the element which will be moved into the new DOM position
+ * @param {DOMElement} parent the parent element which will append the element as
+ * a child (so long as the after element is not present)
+ * @param {DOMElement=} after the sibling element after which the element will be appended
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ move: function(element, parent, after, options) {
+ parent = parent && jqLite(parent);
+ after = after && jqLite(after);
+ parent = parent || after.parent();
+ domInsert(element, parent, after);
+ return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#leave
+ * @kind function
+ * @description Triggers an animation and then removes the element from the DOM.
+ * When the function is called a promise is returned that will be resolved during the next
+ * digest once the animation has completed.
+ *
+ * @param {DOMElement} element the element which will be removed from the DOM
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ leave: function(element, options) {
+ return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
+ element.remove();
+ });
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#addClass
+ * @kind function
+ *
+ * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
+ * execution, the addClass operation will only be handled after the next digest and it will not trigger an
+ * animation if element already contains the CSS class or if the class is removed at a later step.
+ * Note that class-based animations are treated differently compared to structural animations
+ * (like enter, move and leave) since the CSS classes may be added/removed at different points
+ * depending if CSS or JavaScript animations are used.
+ *
+ * @param {DOMElement} element the element which the CSS classes will be applied to
+ * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ addClass: function(element, className, options) {
+ options = prepareAnimateOptions(options);
+ options.addClass = mergeClasses(options.addclass, className);
+ return $$animateQueue.push(element, 'addClass', options);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#removeClass
+ * @kind function
+ *
+ * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
+ * execution, the removeClass operation will only be handled after the next digest and it will not trigger an
+ * animation if element does not contain the CSS class or if the class is added at a later step.
+ * Note that class-based animations are treated differently compared to structural animations
+ * (like enter, move and leave) since the CSS classes may be added/removed at different points
+ * depending if CSS or JavaScript animations are used.
+ *
+ * @param {DOMElement} element the element which the CSS classes will be applied to
+ * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ removeClass: function(element, className, options) {
+ options = prepareAnimateOptions(options);
+ options.removeClass = mergeClasses(options.removeClass, className);
+ return $$animateQueue.push(element, 'removeClass', options);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#setClass
+ * @kind function
+ *
+ * @description Performs both the addition and removal of a CSS classes on an element and (during the process)
+ * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
+ * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
+ * passed. Note that class-based animations are treated differently compared to structural animations
+ * (like enter, move and leave) since the CSS classes may be added/removed at different points
+ * depending if CSS or JavaScript animations are used.
+ *
+ * @param {DOMElement} element the element which the CSS classes will be applied to
+ * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
+ * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ setClass: function(element, add, remove, options) {
+ options = prepareAnimateOptions(options);
+ options.addClass = mergeClasses(options.addClass, add);
+ options.removeClass = mergeClasses(options.removeClass, remove);
+ return $$animateQueue.push(element, 'setClass', options);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $animate#animate
+ * @kind function
+ *
+ * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
+ * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
+ * on the provided styles. For example, if a transition animation is set for the given className then the provided from and
+ * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles
+ * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter).
+ *
+ * @param {DOMElement} element the element which the CSS styles will be applied to
+ * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
+ * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
+ * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
+ * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
+ * (Note that if no animation is detected then this value will not be appplied to the element.)
+ * @param {object=} options an optional collection of options/styles that will be applied to the element
+ *
+ * @return {Promise} the animation callback promise
+ */
+ animate: function(element, from, to, className, options) {
+ options = prepareAnimateOptions(options);
+ options.from = options.from ? extend(options.from, from) : from;
+ options.to = options.to ? extend(options.to, to) : to;
+
+ className = className || 'ng-inline-animate';
+ options.tempClasses = mergeClasses(options.tempClasses, className);
+ return $$animateQueue.push(element, 'animate', options);
+ }
+ };
+ }];
+}];
+
+/**
+ * @ngdoc service
+ * @name $animateCss
+ * @kind object
+ *
+ * @description
+ * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
+ * then the `$animateCss` service will actually perform animations.
+ *
+ * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
+ */
+var $CoreAnimateCssProvider = function() {
+ this.$get = ['$$rAF', '$q', function($$rAF, $q) {
+
+ var RAFPromise = function() {};
+ RAFPromise.prototype = {
+ done: function(cancel) {
+ this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
+ },
+ end: function() {
+ this.done();
+ },
+ cancel: function() {
+ this.done(true);
+ },
+ getPromise: function() {
+ if (!this.defer) {
+ this.defer = $q.defer();
+ }
+ return this.defer.promise;
+ },
+ then: function(f1,f2) {
+ return this.getPromise().then(f1,f2);
+ },
+ 'catch': function(f1) {
+ return this.getPromise()['catch'](f1);
+ },
+ 'finally': function(f1) {
+ return this.getPromise()['finally'](f1);
+ }
+ };
+
+ return function(element, options) {
+ // there is no point in applying the styles since
+ // there is no animation that goes on at all in
+ // this version of $animateCss.
+ if (options.cleanupStyles) {
+ options.from = options.to = null;
+ }
+
+ if (options.from) {
+ element.css(options.from);
+ options.from = null;
+ }
+
+ var closed, runner = new RAFPromise();
+ return {
+ start: run,
+ end: run
+ };
+
+ function run() {
+ $$rAF(function() {
+ close();
+ if (!closed) {
+ runner.done();
+ }
+ closed = true;
+ });
+ return runner;
+ }
+
+ function close() {
+ if (options.addClass) {
+ element.addClass(options.addClass);
+ options.addClass = null;
+ }
+ if (options.removeClass) {
+ element.removeClass(options.removeClass);
+ options.removeClass = null;
+ }
+ if (options.to) {
+ element.css(options.to);
+ options.to = null;
+ }
+ }
+ };
+ }];
+};
+
+/* global stripHash: true */
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name $browser
+ * @requires $log
+ * @description
+ * This object has two goals:
+ *
+ * - hide all the global state in the browser caused by the window object
+ * - abstract away all the browser specific features and inconsistencies
+ *
+ * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
+ * service, which can be used for convenient testing of the application without the interaction with
+ * the real browser apis.
+ */
+/**
+ * @param {object} window The global window object.
+ * @param {object} document jQuery wrapped document.
+ * @param {object} $log window.console or an object with the same interface.
+ * @param {object} $sniffer $sniffer service
+ */
+function Browser(window, document, $log, $sniffer) {
+ var self = this,
+ rawDocument = document[0],
+ location = window.location,
+ history = window.history,
+ setTimeout = window.setTimeout,
+ clearTimeout = window.clearTimeout,
+ pendingDeferIds = {};
+
+ self.isMock = false;
+
+ var outstandingRequestCount = 0;
+ var outstandingRequestCallbacks = [];
+
+ // TODO(vojta): remove this temporary api
+ self.$$completeOutstandingRequest = completeOutstandingRequest;
+ self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
+
+ /**
+ * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
+ * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
+ */
+ function completeOutstandingRequest(fn) {
+ try {
+ fn.apply(null, sliceArgs(arguments, 1));
+ } finally {
+ outstandingRequestCount--;
+ if (outstandingRequestCount === 0) {
+ while (outstandingRequestCallbacks.length) {
+ try {
+ outstandingRequestCallbacks.pop()();
+ } catch (e) {
+ $log.error(e);
+ }
+ }
+ }
+ }
+ }
+
+ function getHash(url) {
+ var index = url.indexOf('#');
+ return index === -1 ? '' : url.substr(index);
+ }
+
+ /**
+ * @private
+ * Note: this method is used only by scenario runner
+ * TODO(vojta): prefix this method with $$ ?
+ * @param {function()} callback Function that will be called when no outstanding request
+ */
+ self.notifyWhenNoOutstandingRequests = function(callback) {
+ if (outstandingRequestCount === 0) {
+ callback();
+ } else {
+ outstandingRequestCallbacks.push(callback);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////
+ // URL API
+ //////////////////////////////////////////////////////////////
+
+ var cachedState, lastHistoryState,
+ lastBrowserUrl = location.href,
+ baseElement = document.find('base'),
+ pendingLocation = null;
+
+ cacheState();
+ lastHistoryState = cachedState;
+
+ /**
+ * @name $browser#url
+ *
+ * @description
+ * GETTER:
+ * Without any argument, this method just returns current value of location.href.
+ *
+ * SETTER:
+ * With at least one argument, this method sets url to new value.
+ * If html5 history api supported, pushState/replaceState is used, otherwise
+ * location.href/location.replace is used.
+ * Returns its own instance to allow chaining
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@link ng.$location $location service} to change url.
+ *
+ * @param {string} url New url (when used as setter)
+ * @param {boolean=} replace Should new url replace current history record?
+ * @param {object=} state object to use with pushState/replaceState
+ */
+ self.url = function(url, replace, state) {
+ // In modern browsers `history.state` is `null` by default; treating it separately
+ // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
+ // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
+ if (isUndefined(state)) {
+ state = null;
+ }
+
+ // Android Browser BFCache causes location, history reference to become stale.
+ if (location !== window.location) location = window.location;
+ if (history !== window.history) history = window.history;
+
+ // setter
+ if (url) {
+ var sameState = lastHistoryState === state;
+
+ // Don't change anything if previous and current URLs and states match. This also prevents
+ // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
+ // See https://github.com/angular/angular.js/commit/ffb2701
+ if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
+ return self;
+ }
+ var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
+ lastBrowserUrl = url;
+ lastHistoryState = state;
+ // Don't use history API if only the hash changed
+ // due to a bug in IE10/IE11 which leads
+ // to not firing a `hashchange` nor `popstate` event
+ // in some cases (see #9143).
+ if ($sniffer.history && (!sameBase || !sameState)) {
+ history[replace ? 'replaceState' : 'pushState'](state, '', url);
+ cacheState();
+ // Do the assignment again so that those two variables are referentially identical.
+ lastHistoryState = cachedState;
+ } else {
+ if (!sameBase || pendingLocation) {
+ pendingLocation = url;
+ }
+ if (replace) {
+ location.replace(url);
+ } else if (!sameBase) {
+ location.href = url;
+ } else {
+ location.hash = getHash(url);
+ }
+ if (location.href !== url) {
+ pendingLocation = url;
+ }
+ }
+ return self;
+ // getter
+ } else {
+ // - pendingLocation is needed as browsers don't allow to read out
+ // the new location.href if a reload happened or if there is a bug like in iOS 9 (see
+ // https://openradar.appspot.com/22186109).
+ // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
+ return pendingLocation || location.href.replace(/%27/g,"'");
+ }
+ };
+
+ /**
+ * @name $browser#state
+ *
+ * @description
+ * This method is a getter.
+ *
+ * Return history.state or null if history.state is undefined.
+ *
+ * @returns {object} state
+ */
+ self.state = function() {
+ return cachedState;
+ };
+
+ var urlChangeListeners = [],
+ urlChangeInit = false;
+
+ function cacheStateAndFireUrlChange() {
+ pendingLocation = null;
+ cacheState();
+ fireUrlChange();
+ }
+
+ function getCurrentState() {
+ try {
+ return history.state;
+ } catch (e) {
+ // MSIE can reportedly throw when there is no state (UNCONFIRMED).
+ }
+ }
+
+ // This variable should be used *only* inside the cacheState function.
+ var lastCachedState = null;
+ function cacheState() {
+ // This should be the only place in $browser where `history.state` is read.
+ cachedState = getCurrentState();
+ cachedState = isUndefined(cachedState) ? null : cachedState;
+
+ // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
+ if (equals(cachedState, lastCachedState)) {
+ cachedState = lastCachedState;
+ }
+ lastCachedState = cachedState;
+ }
+
+ function fireUrlChange() {
+ if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
+ return;
+ }
+
+ lastBrowserUrl = self.url();
+ lastHistoryState = cachedState;
+ forEach(urlChangeListeners, function(listener) {
+ listener(self.url(), cachedState);
+ });
+ }
+
+ /**
+ * @name $browser#onUrlChange
+ *
+ * @description
+ * Register callback function that will be called, when url changes.
+ *
+ * It's only called when the url is changed from outside of angular:
+ * - user types different url into address bar
+ * - user clicks on history (forward/back) button
+ * - user clicks on a link
+ *
+ * It's not called when url is changed by $browser.url() method
+ *
+ * The listener gets called with new url as parameter.
+ *
+ * NOTE: this api is intended for use only by the $location service. Please use the
+ * {@link ng.$location $location service} to monitor url changes in angular apps.
+ *
+ * @param {function(string)} listener Listener function to be called when url changes.
+ * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
+ */
+ self.onUrlChange = function(callback) {
+ // TODO(vojta): refactor to use node's syntax for events
+ if (!urlChangeInit) {
+ // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
+ // don't fire popstate when user change the address bar and don't fire hashchange when url
+ // changed by push/replaceState
+
+ // html5 history api - popstate event
+ if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
+ // hashchange event
+ jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
+
+ urlChangeInit = true;
+ }
+
+ urlChangeListeners.push(callback);
+ return callback;
+ };
+
+ /**
+ * @private
+ * Remove popstate and hashchange handler from window.
+ *
+ * NOTE: this api is intended for use only by $rootScope.
+ */
+ self.$$applicationDestroyed = function() {
+ jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
+ };
+
+ /**
+ * Checks whether the url has changed outside of Angular.
+ * Needs to be exported to be able to check for changes that have been done in sync,
+ * as hashchange/popstate events fire in async.
+ */
+ self.$$checkUrlChange = fireUrlChange;
+
+ //////////////////////////////////////////////////////////////
+ // Misc API
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * @name $browser#baseHref
+ *
+ * @description
+ * Returns current <base href>
+ * (always relative - without domain)
+ *
+ * @returns {string} The current base href
+ */
+ self.baseHref = function() {
+ var href = baseElement.attr('href');
+ return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
+ };
+
+ /**
+ * @name $browser#defer
+ * @param {function()} fn A function, who's execution should be deferred.
+ * @param {number=} [delay=0] of milliseconds to defer the function execution.
+ * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
+ *
+ * @description
+ * Executes a fn asynchronously via `setTimeout(fn, delay)`.
+ *
+ * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
+ * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
+ * via `$browser.defer.flush()`.
+ *
+ */
+ self.defer = function(fn, delay) {
+ var timeoutId;
+ outstandingRequestCount++;
+ timeoutId = setTimeout(function() {
+ delete pendingDeferIds[timeoutId];
+ completeOutstandingRequest(fn);
+ }, delay || 0);
+ pendingDeferIds[timeoutId] = true;
+ return timeoutId;
+ };
+
+
+ /**
+ * @name $browser#defer.cancel
+ *
+ * @description
+ * Cancels a deferred task identified with `deferId`.
+ *
+ * @param {*} deferId Token returned by the `$browser.defer` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ self.defer.cancel = function(deferId) {
+ if (pendingDeferIds[deferId]) {
+ delete pendingDeferIds[deferId];
+ clearTimeout(deferId);
+ completeOutstandingRequest(noop);
+ return true;
+ }
+ return false;
+ };
+
+}
+
+function $BrowserProvider() {
+ this.$get = ['$window', '$log', '$sniffer', '$document',
+ function($window, $log, $sniffer, $document) {
+ return new Browser($window, $document, $log, $sniffer);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $cacheFactory
+ *
+ * @description
+ * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
+ * them.
+ *
+ * ```js
+ *
+ * var cache = $cacheFactory('cacheId');
+ * expect($cacheFactory.get('cacheId')).toBe(cache);
+ * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
+ *
+ * cache.put("key", "value");
+ * cache.put("another key", "another value");
+ *
+ * // We've specified no options on creation
+ * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
+ *
+ * ```
+ *
+ *
+ * @param {string} cacheId Name or id of the newly created cache.
+ * @param {object=} options Options object that specifies the cache behavior. Properties:
+ *
+ * - `{number=}` `capacity` — turns the cache into LRU cache.
+ *
+ * @returns {object} Newly created cache object with the following set of methods:
+ *
+ * - `{object}` `info()` — Returns id, size, and options of cache.
+ * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
+ * it.
+ * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
+ * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
+ * - `{void}` `removeAll()` — Removes all cached values.
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
+ *
+ * @example
+ <example module="cacheExampleApp">
+ <file name="index.html">
+ <div ng-controller="CacheController">
+ <input ng-model="newCacheKey" placeholder="Key">
+ <input ng-model="newCacheValue" placeholder="Value">
+ <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
+
+ <p ng-if="keys.length">Cached Values</p>
+ <div ng-repeat="key in keys">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="cache.get(key)"></b>
+ </div>
+
+ <p>Cache Info</p>
+ <div ng-repeat="(key, value) in cache.info()">
+ <span ng-bind="key"></span>
+ <span>: </span>
+ <b ng-bind="value"></b>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cacheExampleApp', []).
+ controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
+ $scope.keys = [];
+ $scope.cache = $cacheFactory('cacheId');
+ $scope.put = function(key, value) {
+ if (angular.isUndefined($scope.cache.get(key))) {
+ $scope.keys.push(key);
+ }
+ $scope.cache.put(key, angular.isUndefined(value) ? null : value);
+ };
+ }]);
+ </file>
+ <file name="style.css">
+ p {
+ margin: 10px 0 3px;
+ }
+ </file>
+ </example>
+ */
+function $CacheFactoryProvider() {
+
+ this.$get = function() {
+ var caches = {};
+
+ function cacheFactory(cacheId, options) {
+ if (cacheId in caches) {
+ throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
+ }
+
+ var size = 0,
+ stats = extend({}, options, {id: cacheId}),
+ data = createMap(),
+ capacity = (options && options.capacity) || Number.MAX_VALUE,
+ lruHash = createMap(),
+ freshEnd = null,
+ staleEnd = null;
+
+ /**
+ * @ngdoc type
+ * @name $cacheFactory.Cache
+ *
+ * @description
+ * A cache object used to store and retrieve data, primarily used by
+ * {@link $http $http} and the {@link ng.directive:script script} directive to cache
+ * templates and other data.
+ *
+ * ```js
+ * angular.module('superCache')
+ * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
+ * return $cacheFactory('super-cache');
+ * }]);
+ * ```
+ *
+ * Example test:
+ *
+ * ```js
+ * it('should behave like a cache', inject(function(superCache) {
+ * superCache.put('key', 'value');
+ * superCache.put('another key', 'another value');
+ *
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 2
+ * });
+ *
+ * superCache.remove('another key');
+ * expect(superCache.get('another key')).toBeUndefined();
+ *
+ * superCache.removeAll();
+ * expect(superCache.info()).toEqual({
+ * id: 'super-cache',
+ * size: 0
+ * });
+ * }));
+ * ```
+ */
+ return caches[cacheId] = {
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#put
+ * @kind function
+ *
+ * @description
+ * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
+ * retrieved later, and incrementing the size of the cache if the key was not already
+ * present in the cache. If behaving like an LRU cache, it will also remove stale
+ * entries from the set.
+ *
+ * It will not insert undefined values into the cache.
+ *
+ * @param {string} key the key under which the cached data is stored.
+ * @param {*} value the value to store alongside the key. If it is undefined, the key
+ * will not be stored.
+ * @returns {*} the value stored.
+ */
+ put: function(key, value) {
+ if (isUndefined(value)) return;
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
+
+ refresh(lruEntry);
+ }
+
+ if (!(key in data)) size++;
+ data[key] = value;
+
+ if (size > capacity) {
+ this.remove(staleEnd.key);
+ }
+
+ return value;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#get
+ * @kind function
+ *
+ * @description
+ * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the data to be retrieved
+ * @returns {*} the value stored.
+ */
+ get: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ refresh(lruEntry);
+ }
+
+ return data[key];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#remove
+ * @kind function
+ *
+ * @description
+ * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
+ *
+ * @param {string} key the key of the entry to be removed
+ */
+ remove: function(key) {
+ if (capacity < Number.MAX_VALUE) {
+ var lruEntry = lruHash[key];
+
+ if (!lruEntry) return;
+
+ if (lruEntry == freshEnd) freshEnd = lruEntry.p;
+ if (lruEntry == staleEnd) staleEnd = lruEntry.n;
+ link(lruEntry.n,lruEntry.p);
+
+ delete lruHash[key];
+ }
+
+ if (!(key in data)) return;
+
+ delete data[key];
+ size--;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#removeAll
+ * @kind function
+ *
+ * @description
+ * Clears the cache object of any entries.
+ */
+ removeAll: function() {
+ data = createMap();
+ size = 0;
+ lruHash = createMap();
+ freshEnd = staleEnd = null;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#destroy
+ * @kind function
+ *
+ * @description
+ * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
+ * removing it from the {@link $cacheFactory $cacheFactory} set.
+ */
+ destroy: function() {
+ data = null;
+ stats = null;
+ lruHash = null;
+ delete caches[cacheId];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#info
+ * @kind function
+ *
+ * @description
+ * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
+ *
+ * @returns {object} an object with the following properties:
+ * <ul>
+ * <li>**id**: the id of the cache instance</li>
+ * <li>**size**: the number of entries kept in the cache instance</li>
+ * <li>**...**: any additional properties from the options object when creating the
+ * cache.</li>
+ * </ul>
+ */
+ info: function() {
+ return extend({}, stats, {size: size});
+ }
+ };
+
+
+ /**
+ * makes the `entry` the freshEnd of the LRU linked list
+ */
+ function refresh(entry) {
+ if (entry != freshEnd) {
+ if (!staleEnd) {
+ staleEnd = entry;
+ } else if (staleEnd == entry) {
+ staleEnd = entry.n;
+ }
+
+ link(entry.n, entry.p);
+ link(entry, freshEnd);
+ freshEnd = entry;
+ freshEnd.n = null;
+ }
+ }
+
+
+ /**
+ * bidirectionally links two entries of the LRU linked list
+ */
+ function link(nextEntry, prevEntry) {
+ if (nextEntry != prevEntry) {
+ if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
+ if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory#info
+ *
+ * @description
+ * Get information about all the caches that have been created
+ *
+ * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
+ */
+ cacheFactory.info = function() {
+ var info = {};
+ forEach(caches, function(cache, cacheId) {
+ info[cacheId] = cache.info();
+ });
+ return info;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $cacheFactory#get
+ *
+ * @description
+ * Get access to a cache object by the `cacheId` used when it was created.
+ *
+ * @param {string} cacheId Name or id of a cache to access.
+ * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
+ */
+ cacheFactory.get = function(cacheId) {
+ return caches[cacheId];
+ };
+
+
+ return cacheFactory;
+ };
+}
+
+/**
+ * @ngdoc service
+ * @name $templateCache
+ *
+ * @description
+ * The first time a template is used, it is loaded in the template cache for quick retrieval. You
+ * can load templates directly into the cache in a `script` tag, or by consuming the
+ * `$templateCache` service directly.
+ *
+ * Adding via the `script` tag:
+ *
+ * ```html
+ * <script type="text/ng-template" id="templateId.html">
+ * <p>This is the content of the template</p>
+ * </script>
+ * ```
+ *
+ * **Note:** the `script` tag containing the template does not need to be included in the `head` of
+ * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
+ * element with ng-app attribute), otherwise the template will be ignored.
+ *
+ * Adding via the `$templateCache` service:
+ *
+ * ```js
+ * var myApp = angular.module('myApp', []);
+ * myApp.run(function($templateCache) {
+ * $templateCache.put('templateId.html', 'This is the content of the template');
+ * });
+ * ```
+ *
+ * To retrieve the template later, simply use it in your HTML:
+ * ```html
+ * <div ng-include=" 'templateId.html' "></div>
+ * ```
+ *
+ * or get it via Javascript:
+ * ```js
+ * $templateCache.get('templateId.html')
+ * ```
+ *
+ * See {@link ng.$cacheFactory $cacheFactory}.
+ *
+ */
+function $TemplateCacheProvider() {
+ this.$get = ['$cacheFactory', function($cacheFactory) {
+ return $cacheFactory('templates');
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
+ *
+ * DOM-related variables:
+ *
+ * - "node" - DOM Node
+ * - "element" - DOM Element or Node
+ * - "$node" or "$element" - jqLite-wrapped node or element
+ *
+ *
+ * Compiler related stuff:
+ *
+ * - "linkFn" - linking fn of a single directive
+ * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
+ * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
+ * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $compile
+ * @kind function
+ *
+ * @description
+ * Compiles an HTML string or DOM into a template and produces a template function, which
+ * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
+ *
+ * The compilation is a process of walking the DOM tree and matching DOM elements to
+ * {@link ng.$compileProvider#directive directives}.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** This document is an in-depth reference of all directive options.
+ * For a gentle introduction to directives with examples of common use cases,
+ * see the {@link guide/directive directive guide}.
+ * </div>
+ *
+ * ## Comprehensive Directive API
+ *
+ * There are many different options for a directive.
+ *
+ * The difference resides in the return value of the factory function.
+ * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
+ * or just the `postLink` function (all other properties will have the default values).
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's recommended to use the "directive definition object" form.
+ * </div>
+ *
+ * Here's an example directive declared with a Directive Definition Object:
+ *
+ * ```js
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * priority: 0,
+ * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
+ * // or
+ * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
+ * transclude: false,
+ * restrict: 'A',
+ * templateNamespace: 'html',
+ * scope: false,
+ * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
+ * controllerAs: 'stringIdentifier',
+ * bindToController: false,
+ * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
+ * compile: function compile(tElement, tAttrs, transclude) {
+ * return {
+ * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * }
+ * // or
+ * // return function postLink( ... ) { ... }
+ * },
+ * // or
+ * // link: {
+ * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
+ * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
+ * // }
+ * // or
+ * // link: function postLink( ... ) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * });
+ * ```
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Any unspecified options will use the default value. You can see the default values below.
+ * </div>
+ *
+ * Therefore the above can be simplified as:
+ *
+ * ```js
+ * var myModule = angular.module(...);
+ *
+ * myModule.directive('directiveName', function factory(injectables) {
+ * var directiveDefinitionObject = {
+ * link: function postLink(scope, iElement, iAttrs) { ... }
+ * };
+ * return directiveDefinitionObject;
+ * // or
+ * // return function postLink(scope, iElement, iAttrs) { ... }
+ * });
+ * ```
+ *
+ *
+ *
+ * ### Directive Definition Object
+ *
+ * The directive definition object provides instructions to the {@link ng.$compile
+ * compiler}. The attributes are:
+ *
+ * #### `multiElement`
+ * When this property is set to true, the HTML compiler will collect DOM nodes between
+ * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
+ * together as the directive elements. It is recommended that this feature be used on directives
+ * which are not strictly behavioural (such as {@link ngClick}), and which
+ * do not manipulate or replace child nodes (such as {@link ngInclude}).
+ *
+ * #### `priority`
+ * When there are multiple directives defined on a single DOM element, sometimes it
+ * is necessary to specify the order in which the directives are applied. The `priority` is used
+ * to sort the directives before their `compile` functions get called. Priority is defined as a
+ * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
+ * are also run in priority order, but post-link functions are run in reverse order. The order
+ * of directives with the same priority is undefined. The default priority is `0`.
+ *
+ * #### `terminal`
+ * If set to true then the current `priority` will be the last set of directives
+ * which will execute (any directives at the current priority will still execute
+ * as the order of execution on same `priority` is undefined). Note that expressions
+ * and other directives used in the directive's template will also be excluded from execution.
+ *
+ * #### `scope`
+ * The scope property can be `true`, an object or a falsy value:
+ *
+ * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
+ *
+ * * **`true`:** A new child scope that prototypically inherits from its parent will be created for
+ * the directive's element. If multiple directives on the same element request a new scope,
+ * only one new scope is created. The new scope rule does not apply for the root of the template
+ * since the root of the template always gets a new scope.
+ *
+ * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
+ * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
+ * scope. This is useful when creating reusable components, which should not accidentally read or modify
+ * data in the parent scope.
+ *
+ * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
+ * directive's element. These local properties are useful for aliasing values for templates. The keys in
+ * the object hash map to the name of the property on the isolate scope; the values define how the property
+ * is bound to the parent scope, via matching attributes on the directive's element:
+ *
+ * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
+ * always a string since DOM attributes are strings. If no `attr` name is specified then the
+ * attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="hello {{name}}">` and widget definition
+ * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
+ * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
+ * `localName` property on the widget scope. The `name` is read from the parent scope (not
+ * component scope).
+ *
+ * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
+ * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
+ * name is specified then the attribute name is assumed to be the same as the local name.
+ * Given `<widget my-attr="parentModel">` and widget definition of
+ * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
+ * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
+ * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
+ * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
+ * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
+ * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
+ * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
+ *
+ * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
+ * If no `attr` name is specified then the attribute name is assumed to be the same as the
+ * local name. Given `<widget my-attr="count = count + value">` and widget definition of
+ * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
+ * a function wrapper for the `count = count + value` expression. Often it's desirable to
+ * pass data from the isolated scope via an expression to the parent scope, this can be
+ * done by passing a map of local variable names and values into the expression wrapper fn.
+ * For example, if the expression is `increment(amount)` then we can specify the amount value
+ * by calling the `localFn` as `localFn({amount: 22})`.
+ *
+ * In general it's possible to apply more than one directive to one element, but there might be limitations
+ * depending on the type of scope required by the directives. The following points will help explain these limitations.
+ * For simplicity only two directives are taken into account, but it is also applicable for several directives:
+ *
+ * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
+ * * **child scope** + **no scope** => Both directives will share one single child scope
+ * * **child scope** + **child scope** => Both directives will share one single child scope
+ * * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
+ * its parent's scope
+ * * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
+ * be applied to the same element.
+ * * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
+ * cannot be applied to the same element.
+ *
+ *
+ * #### `bindToController`
+ * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
+ * allow a component to have its properties bound to the controller, rather than to scope. When the controller
+ * is instantiated, the initial values of the isolate scope bindings are already available.
+ *
+ * #### `controller`
+ * Controller constructor function. The controller is instantiated before the
+ * pre-linking phase and can be accessed by other directives (see
+ * `require` attribute). This allows the directives to communicate with each other and augment
+ * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
+ *
+ * * `$scope` - Current scope associated with the element
+ * * `$element` - Current element
+ * * `$attrs` - Current attributes object for the element
+ * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ * * `scope`: optional argument to override the scope.
+ * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
+ * * `futureParentElement`:
+ * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
+ * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
+ * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
+ * and when the `cloneLinkinFn` is passed,
+ * as those elements need to created and cloned in a special way when they are defined outside their
+ * usual containers (e.g. like `<svg>`).
+ * * See also the `directive.templateNamespace` property.
+ *
+ *
+ * #### `require`
+ * Require another directive and inject its controller as the fourth argument to the linking function. The
+ * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
+ * injected argument will be an array in corresponding order. If no such directive can be
+ * found, or if the directive does not have a controller, then an error is raised (unless no link function
+ * is specified, in which case error checking is skipped). The name can be prefixed with:
+ *
+ * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
+ * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
+ * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
+ * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
+ * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
+ * `null` to the `link` fn if not found.
+ * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
+ * `null` to the `link` fn if not found.
+ *
+ *
+ * #### `controllerAs`
+ * Identifier name for a reference to the controller in the directive's scope.
+ * This allows the controller to be referenced from the directive template. This is especially
+ * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
+ * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
+ * `controllerAs` reference might overwrite a property that already exists on the parent scope.
+ *
+ *
+ * #### `restrict`
+ * String of subset of `EACM` which restricts the directive to a specific directive
+ * declaration style. If omitted, the defaults (elements and attributes) are used.
+ *
+ * * `E` - Element name (default): `<my-directive></my-directive>`
+ * * `A` - Attribute (default): `<div my-directive="exp"></div>`
+ * * `C` - Class: `<div class="my-directive: exp;"></div>`
+ * * `M` - Comment: `<!-- directive: my-directive exp -->`
+ *
+ *
+ * #### `templateNamespace`
+ * String representing the document type used by the markup in the template.
+ * AngularJS needs this information as those elements need to be created and cloned
+ * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
+ *
+ * * `html` - All root nodes in the template are HTML. Root nodes may also be
+ * top-level elements such as `<svg>` or `<math>`.
+ * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
+ * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
+ *
+ * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
+ *
+ * #### `template`
+ * HTML markup that may:
+ * * Replace the contents of the directive's element (default).
+ * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
+ * * Wrap the contents of the directive's element (if `transclude` is true).
+ *
+ * Value may be:
+ *
+ * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
+ * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
+ * function api below) and returns a string value.
+ *
+ *
+ * #### `templateUrl`
+ * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
+ *
+ * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
+ * for later when the template has been resolved. In the meantime it will continue to compile and link
+ * sibling and parent elements as though this element had not contained any directives.
+ *
+ * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
+ * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
+ * case when only one deeply nested directive has `templateUrl`.
+ *
+ * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
+ *
+ * You can specify `templateUrl` as a string representing the URL or as a function which takes two
+ * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
+ * a string value representing the url. In either case, the template URL is passed through {@link
+ * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
+ *
+ *
+ * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
+ * specify what the template should replace. Defaults to `false`.
+ *
+ * * `true` - the template will replace the directive's element.
+ * * `false` - the template will replace the contents of the directive's element.
+ *
+ * The replacement process migrates all of the attributes / classes from the old element to the new
+ * one. See the {@link guide/directive#template-expanding-directive
+ * Directives Guide} for an example.
+ *
+ * There are very few scenarios where element replacement is required for the application function,
+ * the main one being reusable custom components that are used within SVG contexts
+ * (because SVG doesn't work with custom elements in the DOM tree).
+ *
+ * #### `transclude`
+ * Extract the contents of the element where the directive appears and make it available to the directive.
+ * The contents are compiled and provided to the directive as a **transclusion function**. See the
+ * {@link $compile#transclusion Transclusion} section below.
+ *
+ * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
+ * directive's element or the entire element:
+ *
+ * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
+ * * `'element'` - transclude the whole of the directive's element including any directives on this
+ * element that defined at a lower priority than this directive. When used, the `template`
+ * property is ignored.
+ *
+ *
+ * #### `compile`
+ *
+ * ```js
+ * function compile(tElement, tAttrs, transclude) { ... }
+ * ```
+ *
+ * The compile function deals with transforming the template DOM. Since most directives do not do
+ * template transformation, it is not used often. The compile function takes the following arguments:
+ *
+ * * `tElement` - template element - The element where the directive has been declared. It is
+ * safe to do template transformation on the element and child elements only.
+ *
+ * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
+ * between all directive compile functions.
+ *
+ * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
+ *
+ * <div class="alert alert-warning">
+ * **Note:** The template instance and the link instance may be different objects if the template has
+ * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
+ * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
+ * should be done in a linking function rather than in a compile function.
+ * </div>
+
+ * <div class="alert alert-warning">
+ * **Note:** The compile function cannot handle directives that recursively use themselves in their
+ * own templates or compile functions. Compiling these directives results in an infinite loop and a
+ * stack overflow errors.
+ *
+ * This can be avoided by manually using $compile in the postLink function to imperatively compile
+ * a directive's template instead of relying on automatic template compilation via `template` or
+ * `templateUrl` declaration or manual compilation inside the compile function.
+ * </div>
+ *
+ * <div class="alert alert-danger">
+ * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
+ * e.g. does not know about the right outer scope. Please use the transclude function that is passed
+ * to the link function instead.
+ * </div>
+
+ * A compile function can have a return value which can be either a function or an object.
+ *
+ * * returning a (post-link) function - is equivalent to registering the linking function via the
+ * `link` property of the config object when the compile function is empty.
+ *
+ * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
+ * control when a linking function should be called during the linking phase. See info about
+ * pre-linking and post-linking functions below.
+ *
+ *
+ * #### `link`
+ * This property is used only if the `compile` property is not defined.
+ *
+ * ```js
+ * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
+ * ```
+ *
+ * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
+ * executed after the template has been cloned. This is where most of the directive logic will be
+ * put.
+ *
+ * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
+ * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
+ *
+ * * `iElement` - instance element - The element where the directive is to be used. It is safe to
+ * manipulate the children of the element only in `postLink` function since the children have
+ * already been linked.
+ *
+ * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
+ * between all directive linking functions.
+ *
+ * * `controller` - the directive's required controller instance(s) - Instances are shared
+ * among all directives, which allows the directives to use the controllers as a communication
+ * channel. The exact value depends on the directive's `require` property:
+ * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
+ * * `string`: the controller instance
+ * * `array`: array of controller instances
+ *
+ * If a required controller cannot be found, and it is optional, the instance is `null`,
+ * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
+ *
+ * Note that you can also require the directive's own controller - it will be made available like
+ * any other controller.
+ *
+ * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
+ * This is the same as the `$transclude`
+ * parameter of directive controllers, see there for details.
+ * `function([scope], cloneLinkingFn, futureParentElement)`.
+ *
+ * #### Pre-linking function
+ *
+ * Executed before the child elements are linked. Not safe to do DOM transformation since the
+ * compiler linking function will fail to locate the correct elements for linking.
+ *
+ * #### Post-linking function
+ *
+ * Executed after the child elements are linked.
+ *
+ * Note that child elements that contain `templateUrl` directives will not have been compiled
+ * and linked since they are waiting for their template to load asynchronously and their own
+ * compilation and linking has been suspended until that occurs.
+ *
+ * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
+ * for their async templates to be resolved.
+ *
+ *
+ * ### Transclusion
+ *
+ * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
+ * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
+ * scope from where they were taken.
+ *
+ * Transclusion is used (often with {@link ngTransclude}) to insert the
+ * original contents of a directive's element into a specified place in the template of the directive.
+ * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
+ * content has access to the properties on the scope from which it was taken, even if the directive
+ * has isolated scope.
+ * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
+ *
+ * This makes it possible for the widget to have private state for its template, while the transcluded
+ * content has access to its originating scope.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** When testing an element transclude directive you must not place the directive at the root of the
+ * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
+ * Testing Transclusion Directives}.
+ * </div>
+ *
+ * #### Transclusion Functions
+ *
+ * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
+ * function** to the directive's `link` function and `controller`. This transclusion function is a special
+ * **linking function** that will return the compiled contents linked to a new transclusion scope.
+ *
+ * <div class="alert alert-info">
+ * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
+ * ngTransclude will deal with it for us.
+ * </div>
+ *
+ * If you want to manually control the insertion and removal of the transcluded content in your directive
+ * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
+ * object that contains the compiled DOM, which is linked to the correct transclusion scope.
+ *
+ * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
+ * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
+ * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
+ * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
+ * </div>
+ *
+ * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
+ * attach function**:
+ *
+ * ```js
+ * var transcludedContent, transclusionScope;
+ *
+ * $transclude(function(clone, scope) {
+ * element.append(clone);
+ * transcludedContent = clone;
+ * transclusionScope = scope;
+ * });
+ * ```
+ *
+ * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
+ * associated transclusion scope:
+ *
+ * ```js
+ * transcludedContent.remove();
+ * transclusionScope.$destroy();
+ * ```
+ *
+ * <div class="alert alert-info">
+ * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
+ * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it),
+ * then you are also responsible for calling `$destroy` on the transclusion scope.
+ * </div>
+ *
+ * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
+ * automatically destroy their transluded clones as necessary so you do not need to worry about this if
+ * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
+ *
+ *
+ * #### Transclusion Scopes
+ *
+ * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
+ * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
+ * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
+ * was taken.
+ *
+ * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
+ * like this:
+ *
+ * ```html
+ * <div ng-app>
+ * <div isolate>
+ * <div transclusion>
+ * </div>
+ * </div>
+ * </div>
+ * ```
+ *
+ * The `$parent` scope hierarchy will look like this:
+ *
+ * ```
+ * - $rootScope
+ * - isolate
+ * - transclusion
+ * ```
+ *
+ * but the scopes will inherit prototypically from different scopes to their `$parent`.
+ *
+ * ```
+ * - $rootScope
+ * - transclusion
+ * - isolate
+ * ```
+ *
+ *
+ * ### Attributes
+ *
+ * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
+ * `link()` or `compile()` functions. It has a variety of uses.
+ *
+ * accessing *Normalized attribute names:*
+ * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
+ * the attributes object allows for normalized access to
+ * the attributes.
+ *
+ * * *Directive inter-communication:* All directives share the same instance of the attributes
+ * object which allows the directives to use the attributes object as inter directive
+ * communication.
+ *
+ * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
+ * allowing other directives to read the interpolated value.
+ *
+ * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
+ * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
+ * the only way to easily get the actual value because during the linking phase the interpolation
+ * hasn't been evaluated yet and so the value is at this time set to `undefined`.
+ *
+ * ```js
+ * function linkingFn(scope, elm, attrs, ctrl) {
+ * // get the attribute value
+ * console.log(attrs.ngModel);
+ *
+ * // change the attribute
+ * attrs.$set('ngModel', 'new value');
+ *
+ * // observe changes to interpolated attribute
+ * attrs.$observe('ngModel', function(value) {
+ * console.log('ngModel has changed value to ' + value);
+ * });
+ * }
+ * ```
+ *
+ * ## Example
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Typically directives are registered with `module.directive`. The example below is
+ * to illustrate how `$compile` works.
+ * </div>
+ *
+ <example module="compileExample">
+ <file name="index.html">
+ <script>
+ angular.module('compileExample', [], function($compileProvider) {
+ // configure new 'compile' directive by passing a directive
+ // factory function. The factory function injects the '$compile'
+ $compileProvider.directive('compile', function($compile) {
+ // directive factory creates a link function
+ return function(scope, element, attrs) {
+ scope.$watch(
+ function(scope) {
+ // watch the 'compile' expression for changes
+ return scope.$eval(attrs.compile);
+ },
+ function(value) {
+ // when the 'compile' expression changes
+ // assign it into the current DOM
+ element.html(value);
+
+ // compile the new DOM and link it to the current
+ // scope.
+ // NOTE: we only compile .childNodes so that
+ // we don't get into infinite loop compiling ourselves
+ $compile(element.contents())(scope);
+ }
+ );
+ };
+ });
+ })
+ .controller('GreeterController', ['$scope', function($scope) {
+ $scope.name = 'Angular';
+ $scope.html = 'Hello {{name}}';
+ }]);
+ </script>
+ <div ng-controller="GreeterController">
+ <input ng-model="name"> <br/>
+ <textarea ng-model="html"></textarea> <br/>
+ <div compile="html"></div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should auto compile', function() {
+ var textarea = $('textarea');
+ var output = $('div[compile]');
+ // The initial state reads 'Hello Angular'.
+ expect(output.getText()).toBe('Hello Angular');
+ textarea.clear();
+ textarea.sendKeys('{{name}}!');
+ expect(output.getText()).toBe('Angular!');
+ });
+ </file>
+ </example>
+
+ *
+ *
+ * @param {string|DOMElement} element Element or HTML string to compile into a template function.
+ * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
+ *
+ * <div class="alert alert-danger">
+ * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
+ * e.g. will not use the right outer scope. Please pass the transclude function as a
+ * `parentBoundTranscludeFn` to the link function instead.
+ * </div>
+ *
+ * @param {number} maxPriority only apply directives lower than given priority (Only effects the
+ * root element(s), not their children)
+ * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
+ * (a DOM element/tree) to a scope. Where:
+ *
+ * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
+ * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
+ * `template` and call the `cloneAttachFn` function allowing the caller to attach the
+ * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
+ * called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
+ *
+ * * `clonedElement` - is a clone of the original `element` passed into the compiler.
+ * * `scope` - is the current scope with which the linking function is working with.
+ *
+ * * `options` - An optional object hash with linking options. If `options` is provided, then the following
+ * keys may be used to control linking behavior:
+ *
+ * * `parentBoundTranscludeFn` - the transclude function made available to
+ * directives; if given, it will be passed through to the link functions of
+ * directives found in `element` during compilation.
+ * * `transcludeControllers` - an object hash with keys that map controller names
+ * to controller instances; if given, it will make the controllers
+ * available to directives.
+ * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
+ * the cloned elements; only needed for transcludes that are allowed to contain non html
+ * elements (e.g. SVG elements). See also the directive.controller property.
+ *
+ * Calling the linking function returns the element of the template. It is either the original
+ * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
+ *
+ * After linking the view is not updated until after a call to $digest which typically is done by
+ * Angular automatically.
+ *
+ * If you need access to the bound view, there are two ways to do it:
+ *
+ * - If you are not asking the linking function to clone the template, create the DOM element(s)
+ * before you send them to the compiler and keep this reference around.
+ * ```js
+ * var element = $compile('<p>{{total}}</p>')(scope);
+ * ```
+ *
+ * - if on the other hand, you need the element to be cloned, the view reference from the original
+ * example would not point to the clone, but rather to the original template that was cloned. In
+ * this case, you can access the clone via the cloneAttachFn:
+ * ```js
+ * var templateElement = angular.element('<p>{{total}}</p>'),
+ * scope = ....;
+ *
+ * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
+ * //attach the clone to DOM document at the right place
+ * });
+ *
+ * //now we have reference to the cloned DOM via `clonedElement`
+ * ```
+ *
+ *
+ * For information on how the compiler works, see the
+ * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
+ */
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc provider
+ * @name $compileProvider
+ *
+ * @description
+ */
+$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
+function $CompileProvider($provide, $$sanitizeUriProvider) {
+ var hasDirectives = {},
+ Suffix = 'Directive',
+ COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
+ CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
+ ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
+ REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
+
+ // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
+ // The assumption is that future DOM event attribute names will begin with
+ // 'on' and be composed of only English letters.
+ var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
+
+ function parseIsolateBindings(scope, directiveName, isController) {
+ var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
+
+ var bindings = {};
+
+ forEach(scope, function(definition, scopeName) {
+ var match = definition.match(LOCAL_REGEXP);
+
+ if (!match) {
+ throw $compileMinErr('iscp',
+ "Invalid {3} for directive '{0}'." +
+ " Definition: {... {1}: '{2}' ...}",
+ directiveName, scopeName, definition,
+ (isController ? "controller bindings definition" :
+ "isolate scope definition"));
+ }
+
+ bindings[scopeName] = {
+ mode: match[1][0],
+ collection: match[2] === '*',
+ optional: match[3] === '?',
+ attrName: match[4] || scopeName
+ };
+ });
+
+ return bindings;
+ }
+
+ function parseDirectiveBindings(directive, directiveName) {
+ var bindings = {
+ isolateScope: null,
+ bindToController: null
+ };
+ if (isObject(directive.scope)) {
+ if (directive.bindToController === true) {
+ bindings.bindToController = parseIsolateBindings(directive.scope,
+ directiveName, true);
+ bindings.isolateScope = {};
+ } else {
+ bindings.isolateScope = parseIsolateBindings(directive.scope,
+ directiveName, false);
+ }
+ }
+ if (isObject(directive.bindToController)) {
+ bindings.bindToController =
+ parseIsolateBindings(directive.bindToController, directiveName, true);
+ }
+ if (isObject(bindings.bindToController)) {
+ var controller = directive.controller;
+ var controllerAs = directive.controllerAs;
+ if (!controller) {
+ // There is no controller, there may or may not be a controllerAs property
+ throw $compileMinErr('noctrl',
+ "Cannot bind to controller without directive '{0}'s controller.",
+ directiveName);
+ } else if (!identifierForController(controller, controllerAs)) {
+ // There is a controller, but no identifier or controllerAs property
+ throw $compileMinErr('noident',
+ "Cannot bind to controller without identifier for directive '{0}'.",
+ directiveName);
+ }
+ }
+ return bindings;
+ }
+
+ function assertValidDirectiveName(name) {
+ var letter = name.charAt(0);
+ if (!letter || letter !== lowercase(letter)) {
+ throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
+ }
+ if (name !== name.trim()) {
+ throw $compileMinErr('baddir',
+ "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
+ name);
+ }
+ }
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#directive
+ * @kind function
+ *
+ * @description
+ * Register a new directive with the compiler.
+ *
+ * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
+ * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
+ * names and the values are the factories.
+ * @param {Function|Array} directiveFactory An injectable directive factory function. See
+ * {@link guide/directive} for more info.
+ * @returns {ng.$compileProvider} Self for chaining.
+ */
+ this.directive = function registerDirective(name, directiveFactory) {
+ assertNotHasOwnProperty(name, 'directive');
+ if (isString(name)) {
+ assertValidDirectiveName(name);
+ assertArg(directiveFactory, 'directiveFactory');
+ if (!hasDirectives.hasOwnProperty(name)) {
+ hasDirectives[name] = [];
+ $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
+ function($injector, $exceptionHandler) {
+ var directives = [];
+ forEach(hasDirectives[name], function(directiveFactory, index) {
+ try {
+ var directive = $injector.invoke(directiveFactory);
+ if (isFunction(directive)) {
+ directive = { compile: valueFn(directive) };
+ } else if (!directive.compile && directive.link) {
+ directive.compile = valueFn(directive.link);
+ }
+ directive.priority = directive.priority || 0;
+ directive.index = index;
+ directive.name = directive.name || name;
+ directive.require = directive.require || (directive.controller && directive.name);
+ directive.restrict = directive.restrict || 'EA';
+ var bindings = directive.$$bindings =
+ parseDirectiveBindings(directive, directive.name);
+ if (isObject(bindings.isolateScope)) {
+ directive.$$isolateBindings = bindings.isolateScope;
+ }
+ directive.$$moduleName = directiveFactory.$$moduleName;
+ directives.push(directive);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ return directives;
+ }]);
+ }
+ hasDirectives[name].push(directiveFactory);
+ } else {
+ forEach(name, reverseParams(registerDirective));
+ }
+ return this;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#aHrefSanitizationWhitelist
+ * @kind function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at preventing XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.aHrefSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#imgSrcSanitizationWhitelist
+ * @kind function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during img[src] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.imgSrcSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
+ return this;
+ } else {
+ return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $compileProvider#debugInfoEnabled
+ *
+ * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
+ * current debugInfoEnabled state
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ *
+ * @kind function
+ *
+ * @description
+ * Call this method to enable/disable various debug runtime information in the compiler such as adding
+ * binding information and a reference to the current scope on to DOM elements.
+ * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
+ * * `ng-binding` CSS class
+ * * `$binding` data property containing an array of the binding expressions
+ *
+ * You may want to disable this in production for a significant performance boost. See
+ * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
+ *
+ * The default value is true.
+ */
+ var debugInfoEnabled = true;
+ this.debugInfoEnabled = function(enabled) {
+ if (isDefined(enabled)) {
+ debugInfoEnabled = enabled;
+ return this;
+ }
+ return debugInfoEnabled;
+ };
+
+ this.$get = [
+ '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
+ '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
+ function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
+ $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
+
+ var Attributes = function(element, attributesToCopy) {
+ if (attributesToCopy) {
+ var keys = Object.keys(attributesToCopy);
+ var i, l, key;
+
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i];
+ this[key] = attributesToCopy[key];
+ }
+ } else {
+ this.$attr = {};
+ }
+
+ this.$$element = element;
+ };
+
+ Attributes.prototype = {
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$normalize
+ * @kind function
+ *
+ * @description
+ * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
+ * `data-`) to its normalized, camelCase form.
+ *
+ * Also there is special case for Moz prefix starting with upper case letter.
+ *
+ * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
+ *
+ * @param {string} name Name to normalize
+ */
+ $normalize: directiveNormalize,
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$addClass
+ * @kind function
+ *
+ * @description
+ * Adds the CSS class value specified by the classVal parameter to the element. If animations
+ * are enabled then an animation will be triggered for the class addition.
+ *
+ * @param {string} classVal The className value that will be added to the element
+ */
+ $addClass: function(classVal) {
+ if (classVal && classVal.length > 0) {
+ $animate.addClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$removeClass
+ * @kind function
+ *
+ * @description
+ * Removes the CSS class value specified by the classVal parameter from the element. If
+ * animations are enabled then an animation will be triggered for the class removal.
+ *
+ * @param {string} classVal The className value that will be removed from the element
+ */
+ $removeClass: function(classVal) {
+ if (classVal && classVal.length > 0) {
+ $animate.removeClass(this.$$element, classVal);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$updateClass
+ * @kind function
+ *
+ * @description
+ * Adds and removes the appropriate CSS class values to the element based on the difference
+ * between the new and old CSS class values (specified as newClasses and oldClasses).
+ *
+ * @param {string} newClasses The current CSS className value
+ * @param {string} oldClasses The former CSS className value
+ */
+ $updateClass: function(newClasses, oldClasses) {
+ var toAdd = tokenDifference(newClasses, oldClasses);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(this.$$element, toAdd);
+ }
+
+ var toRemove = tokenDifference(oldClasses, newClasses);
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(this.$$element, toRemove);
+ }
+ },
+
+ /**
+ * Set a normalized attribute on the element in a way such that all directives
+ * can share the attribute. This function properly handles boolean attributes.
+ * @param {string} key Normalized key. (ie ngAttribute)
+ * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
+ * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
+ * Defaults to true.
+ * @param {string=} attrName Optional none normalized name. Defaults to key.
+ */
+ $set: function(key, value, writeAttr, attrName) {
+ // TODO: decide whether or not to throw an error if "class"
+ //is set through this function since it may cause $updateClass to
+ //become unstable.
+
+ var node = this.$$element[0],
+ booleanKey = getBooleanAttrName(node, key),
+ aliasedKey = getAliasedAttrName(key),
+ observer = key,
+ nodeName;
+
+ if (booleanKey) {
+ this.$$element.prop(key, value);
+ attrName = booleanKey;
+ } else if (aliasedKey) {
+ this[aliasedKey] = value;
+ observer = aliasedKey;
+ }
+
+ this[key] = value;
+
+ // translate normalized key to actual key
+ if (attrName) {
+ this.$attr[key] = attrName;
+ } else {
+ attrName = this.$attr[key];
+ if (!attrName) {
+ this.$attr[key] = attrName = snake_case(key, '-');
+ }
+ }
+
+ nodeName = nodeName_(this.$$element);
+
+ if ((nodeName === 'a' && key === 'href') ||
+ (nodeName === 'img' && key === 'src')) {
+ // sanitize a[href] and img[src] values
+ this[key] = value = $$sanitizeUri(value, key === 'src');
+ } else if (nodeName === 'img' && key === 'srcset') {
+ // sanitize img[srcset] values
+ var result = "";
+
+ // first check if there are spaces because it's not the same pattern
+ var trimmedSrcset = trim(value);
+ // ( 999x ,| 999w ,| ,|, )
+ var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
+ var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
+
+ // split srcset into tuple of uri and descriptor except for the last item
+ var rawUris = trimmedSrcset.split(pattern);
+
+ // for each tuples
+ var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
+ for (var i = 0; i < nbrUrisWith2parts; i++) {
+ var innerIdx = i * 2;
+ // sanitize the uri
+ result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
+ // add the descriptor
+ result += (" " + trim(rawUris[innerIdx + 1]));
+ }
+
+ // split the last item into uri and descriptor
+ var lastTuple = trim(rawUris[i * 2]).split(/\s/);
+
+ // sanitize the last uri
+ result += $$sanitizeUri(trim(lastTuple[0]), true);
+
+ // and add the last descriptor if any
+ if (lastTuple.length === 2) {
+ result += (" " + trim(lastTuple[1]));
+ }
+ this[key] = value = result;
+ }
+
+ if (writeAttr !== false) {
+ if (value === null || isUndefined(value)) {
+ this.$$element.removeAttr(attrName);
+ } else {
+ this.$$element.attr(attrName, value);
+ }
+ }
+
+ // fire observers
+ var $$observers = this.$$observers;
+ $$observers && forEach($$observers[observer], function(fn) {
+ try {
+ fn(value);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$observe
+ * @kind function
+ *
+ * @description
+ * Observes an interpolated attribute.
+ *
+ * The observer function will be invoked once during the next `$digest` following
+ * compilation. The observer is then invoked whenever the interpolated value
+ * changes.
+ *
+ * @param {string} key Normalized key. (ie ngAttribute) .
+ * @param {function(interpolatedValue)} fn Function that will be called whenever
+ the interpolated value of the attribute changes.
+ * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
+ * @returns {function()} Returns a deregistration function for this observer.
+ */
+ $observe: function(key, fn) {
+ var attrs = this,
+ $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
+ listeners = ($$observers[key] || ($$observers[key] = []));
+
+ listeners.push(fn);
+ $rootScope.$evalAsync(function() {
+ if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
+ // no one registered attribute interpolation function, so lets call it manually
+ fn(attrs[key]);
+ }
+ });
+
+ return function() {
+ arrayRemove(listeners, fn);
+ };
+ }
+ };
+
+
+ function safeAddClass($element, className) {
+ try {
+ $element.addClass(className);
+ } catch (e) {
+ // ignore, since it means that we are trying to set class on
+ // SVG element, where class name is read-only.
+ }
+ }
+
+
+ var startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
+ ? identity
+ : function denormalizeTemplate(template) {
+ return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
+ },
+ NG_ATTR_BINDING = /^ngAttr[A-Z]/;
+ var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
+
+ compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
+ var bindings = $element.data('$binding') || [];
+
+ if (isArray(binding)) {
+ bindings = bindings.concat(binding);
+ } else {
+ bindings.push(binding);
+ }
+
+ $element.data('$binding', bindings);
+ } : noop;
+
+ compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
+ safeAddClass($element, 'ng-binding');
+ } : noop;
+
+ compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
+ var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
+ $element.data(dataName, scope);
+ } : noop;
+
+ compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
+ safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
+ } : noop;
+
+ return compile;
+
+ //================================
+
+ function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ if (!($compileNodes instanceof jqLite)) {
+ // jquery always rewraps, whereas we need to preserve the original selector so that we can
+ // modify it.
+ $compileNodes = jqLite($compileNodes);
+ }
+ // We can not compile top level text elements since text nodes can be merged and we will
+ // not be able to attach scope data to them, so we will wrap them in <span>
+ forEach($compileNodes, function(node, index) {
+ if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
+ }
+ });
+ var compositeLinkFn =
+ compileNodes($compileNodes, transcludeFn, $compileNodes,
+ maxPriority, ignoreDirective, previousCompileContext);
+ compile.$$addScopeClass($compileNodes);
+ var namespace = null;
+ return function publicLinkFn(scope, cloneConnectFn, options) {
+ assertArg(scope, 'scope');
+
+ if (previousCompileContext && previousCompileContext.needsNewScope) {
+ // A parent directive did a replace and a directive on this element asked
+ // for transclusion, which caused us to lose a layer of element on which
+ // we could hold the new transclusion scope, so we will create it manually
+ // here.
+ scope = scope.$parent.$new();
+ }
+
+ options = options || {};
+ var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
+ transcludeControllers = options.transcludeControllers,
+ futureParentElement = options.futureParentElement;
+
+ // When `parentBoundTranscludeFn` is passed, it is a
+ // `controllersBoundTransclude` function (it was previously passed
+ // as `transclude` to directive.link) so we must unwrap it to get
+ // its `boundTranscludeFn`
+ if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
+ parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
+ }
+
+ if (!namespace) {
+ namespace = detectNamespaceForChildElements(futureParentElement);
+ }
+ var $linkNode;
+ if (namespace !== 'html') {
+ // When using a directive with replace:true and templateUrl the $compileNodes
+ // (or a child element inside of them)
+ // might change, so we need to recreate the namespace adapted compileNodes
+ // for call to the link function.
+ // Note: This will already clone the nodes...
+ $linkNode = jqLite(
+ wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
+ );
+ } else if (cloneConnectFn) {
+ // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
+ // and sometimes changes the structure of the DOM.
+ $linkNode = JQLitePrototype.clone.call($compileNodes);
+ } else {
+ $linkNode = $compileNodes;
+ }
+
+ if (transcludeControllers) {
+ for (var controllerName in transcludeControllers) {
+ $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
+ }
+ }
+
+ compile.$$addScopeInfo($linkNode, scope);
+
+ if (cloneConnectFn) cloneConnectFn($linkNode, scope);
+ if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
+ return $linkNode;
+ };
+ }
+
+ function detectNamespaceForChildElements(parentElement) {
+ // TODO: Make this detect MathML as well...
+ var node = parentElement && parentElement[0];
+ if (!node) {
+ return 'html';
+ } else {
+ return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
+ }
+ }
+
+ /**
+ * Compile function matches each node in nodeList against the directives. Once all directives
+ * for a particular node are collected their compile functions are executed. The compile
+ * functions return values - the linking functions - are combined into a composite linking
+ * function, which is the a linking function for the node.
+ *
+ * @param {NodeList} nodeList an array of nodes or NodeList to compile
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new child of the transcluded parent scope.
+ * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
+ * the rootElement must be set the jqLite collection of the compile root. This is
+ * needed so that the jqLite collection items can be replaced with widgets.
+ * @param {number=} maxPriority Max directive priority.
+ * @returns {Function} A composite linking function of all of the matched directives or null.
+ */
+ function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
+ previousCompileContext) {
+ var linkFns = [],
+ attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
+
+ for (var i = 0; i < nodeList.length; i++) {
+ attrs = new Attributes();
+
+ // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
+ directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
+ ignoreDirective);
+
+ nodeLinkFn = (directives.length)
+ ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
+ null, [], [], previousCompileContext)
+ : null;
+
+ if (nodeLinkFn && nodeLinkFn.scope) {
+ compile.$$addScopeClass(attrs.$$element);
+ }
+
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
+ !(childNodes = nodeList[i].childNodes) ||
+ !childNodes.length)
+ ? null
+ : compileNodes(childNodes,
+ nodeLinkFn ? (
+ (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
+ && nodeLinkFn.transclude) : transcludeFn);
+
+ if (nodeLinkFn || childLinkFn) {
+ linkFns.push(i, nodeLinkFn, childLinkFn);
+ linkFnFound = true;
+ nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
+ }
+
+ //use the previous context only for the first element in the virtual group
+ previousCompileContext = null;
+ }
+
+ // return a linking function if we have found anything, null otherwise
+ return linkFnFound ? compositeLinkFn : null;
+
+ function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
+ var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
+ var stableNodeList;
+
+
+ if (nodeLinkFnFound) {
+ // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
+ // offsets don't get screwed up
+ var nodeListLength = nodeList.length;
+ stableNodeList = new Array(nodeListLength);
+
+ // create a sparse array by only copying the elements which have a linkFn
+ for (i = 0; i < linkFns.length; i+=3) {
+ idx = linkFns[i];
+ stableNodeList[idx] = nodeList[idx];
+ }
+ } else {
+ stableNodeList = nodeList;
+ }
+
+ for (i = 0, ii = linkFns.length; i < ii;) {
+ node = stableNodeList[linkFns[i++]];
+ nodeLinkFn = linkFns[i++];
+ childLinkFn = linkFns[i++];
+
+ if (nodeLinkFn) {
+ if (nodeLinkFn.scope) {
+ childScope = scope.$new();
+ compile.$$addScopeInfo(jqLite(node), childScope);
+ } else {
+ childScope = scope;
+ }
+
+ if (nodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(
+ scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
+
+ } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
+ childBoundTranscludeFn = parentBoundTranscludeFn;
+
+ } else if (!parentBoundTranscludeFn && transcludeFn) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
+
+ } else {
+ childBoundTranscludeFn = null;
+ }
+
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
+
+ } else if (childLinkFn) {
+ childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
+ }
+ }
+ }
+ }
+
+ function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
+
+ var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
+
+ if (!transcludedScope) {
+ transcludedScope = scope.$new(false, containingScope);
+ transcludedScope.$$transcluded = true;
+ }
+
+ return transcludeFn(transcludedScope, cloneFn, {
+ parentBoundTranscludeFn: previousBoundTranscludeFn,
+ transcludeControllers: controllers,
+ futureParentElement: futureParentElement
+ });
+ };
+
+ return boundTranscludeFn;
+ }
+
+ /**
+ * Looks for directives on the given node and adds them to the directive collection which is
+ * sorted.
+ *
+ * @param node Node to search.
+ * @param directives An array to which the directives are added to. This array is sorted before
+ * the function returns.
+ * @param attrs The shared attrs object which is used to populate the normalized attributes.
+ * @param {number=} maxPriority Max directive priority.
+ */
+ function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
+ var nodeType = node.nodeType,
+ attrsMap = attrs.$attr,
+ match,
+ className;
+
+ switch (nodeType) {
+ case NODE_TYPE_ELEMENT: /* Element */
+ // use the node name: <directive>
+ addDirective(directives,
+ directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
+
+ // iterate over the attributes
+ for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
+ j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
+ var attrStartName = false;
+ var attrEndName = false;
+
+ attr = nAttrs[j];
+ name = attr.name;
+ value = trim(attr.value);
+
+ // support ngAttr attribute binding
+ ngAttrName = directiveNormalize(name);
+ if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
+ name = name.replace(PREFIX_REGEXP, '')
+ .substr(8).replace(/_(.)/g, function(match, letter) {
+ return letter.toUpperCase();
+ });
+ }
+
+ var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
+ if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
+ attrStartName = name;
+ attrEndName = name.substr(0, name.length - 5) + 'end';
+ name = name.substr(0, name.length - 6);
+ }
+
+ nName = directiveNormalize(name.toLowerCase());
+ attrsMap[nName] = name;
+ if (isNgAttr || !attrs.hasOwnProperty(nName)) {
+ attrs[nName] = value;
+ if (getBooleanAttrName(node, nName)) {
+ attrs[nName] = true; // presence means true
+ }
+ }
+ addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
+ addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
+ attrEndName);
+ }
+
+ // use class as directive
+ className = node.className;
+ if (isObject(className)) {
+ // Maybe SVGAnimatedString
+ className = className.animVal;
+ }
+ if (isString(className) && className !== '') {
+ while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
+ nName = directiveNormalize(match[2]);
+ if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[3]);
+ }
+ className = className.substr(match.index + match[0].length);
+ }
+ }
+ break;
+ case NODE_TYPE_TEXT: /* Text Node */
+ if (msie === 11) {
+ // Workaround for #11781
+ while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
+ node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
+ node.parentNode.removeChild(node.nextSibling);
+ }
+ }
+ addTextInterpolateDirective(directives, node.nodeValue);
+ break;
+ case NODE_TYPE_COMMENT: /* Comment */
+ try {
+ match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
+ if (match) {
+ nName = directiveNormalize(match[1]);
+ if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
+ attrs[nName] = trim(match[2]);
+ }
+ }
+ } catch (e) {
+ // turns out that under some circumstances IE9 throws errors when one attempts to read
+ // comment's node value.
+ // Just ignore it and continue. (Can't seem to reproduce in test case.)
+ }
+ break;
+ }
+
+ directives.sort(byPriority);
+ return directives;
+ }
+
+ /**
+ * Given a node with an directive-start it collects all of the siblings until it finds
+ * directive-end.
+ * @param node
+ * @param attrStart
+ * @param attrEnd
+ * @returns {*}
+ */
+ function groupScan(node, attrStart, attrEnd) {
+ var nodes = [];
+ var depth = 0;
+ if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
+ do {
+ if (!node) {
+ throw $compileMinErr('uterdir',
+ "Unterminated attribute, found '{0}' but no matching '{1}' found.",
+ attrStart, attrEnd);
+ }
+ if (node.nodeType == NODE_TYPE_ELEMENT) {
+ if (node.hasAttribute(attrStart)) depth++;
+ if (node.hasAttribute(attrEnd)) depth--;
+ }
+ nodes.push(node);
+ node = node.nextSibling;
+ } while (depth > 0);
+ } else {
+ nodes.push(node);
+ }
+
+ return jqLite(nodes);
+ }
+
+ /**
+ * Wrapper for linking function which converts normal linking function into a grouped
+ * linking function.
+ * @param linkFn
+ * @param attrStart
+ * @param attrEnd
+ * @returns {Function}
+ */
+ function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
+ return function(scope, element, attrs, controllers, transcludeFn) {
+ element = groupScan(element[0], attrStart, attrEnd);
+ return linkFn(scope, element, attrs, controllers, transcludeFn);
+ };
+ }
+
+ /**
+ * Once the directives have been collected, their compile functions are executed. This method
+ * is responsible for inlining directive templates as well as terminating the application
+ * of the directives if the terminal directive has been reached.
+ *
+ * @param {Array} directives Array of collected directives to execute their compile function.
+ * this needs to be pre-sorted by priority order.
+ * @param {Node} compileNode The raw DOM node to apply the compile functions to
+ * @param {Object} templateAttrs The shared attribute function
+ * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
+ * scope argument is auto-generated to the new
+ * child of the transcluded parent scope.
+ * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
+ * argument has the root jqLite array so that we can replace nodes
+ * on it.
+ * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
+ * compiling the transclusion.
+ * @param {Array.<Function>} preLinkFns
+ * @param {Array.<Function>} postLinkFns
+ * @param {Object} previousCompileContext Context used for previous compilation of the current
+ * node
+ * @returns {Function} linkFn
+ */
+ function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
+ jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
+ previousCompileContext) {
+ previousCompileContext = previousCompileContext || {};
+
+ var terminalPriority = -Number.MAX_VALUE,
+ newScopeDirective = previousCompileContext.newScopeDirective,
+ controllerDirectives = previousCompileContext.controllerDirectives,
+ newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
+ templateDirective = previousCompileContext.templateDirective,
+ nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
+ hasTranscludeDirective = false,
+ hasTemplate = false,
+ hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
+ $compileNode = templateAttrs.$$element = jqLite(compileNode),
+ directive,
+ directiveName,
+ $template,
+ replaceDirective = originalReplaceDirective,
+ childTranscludeFn = transcludeFn,
+ linkFn,
+ directiveValue;
+
+ // executes all directives on the current element
+ for (var i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ var attrStart = directive.$$start;
+ var attrEnd = directive.$$end;
+
+ // collect multiblock sections
+ if (attrStart) {
+ $compileNode = groupScan(compileNode, attrStart, attrEnd);
+ }
+ $template = undefined;
+
+ if (terminalPriority > directive.priority) {
+ break; // prevent further processing of directives
+ }
+
+ if (directiveValue = directive.scope) {
+
+ // skip the check for directives with async templates, we'll check the derived sync
+ // directive when the template arrives
+ if (!directive.templateUrl) {
+ if (isObject(directiveValue)) {
+ // This directive is trying to add an isolated scope.
+ // Check that there is no scope of any kind already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
+ directive, $compileNode);
+ newIsolateScopeDirective = directive;
+ } else {
+ // This directive is trying to add a child scope.
+ // Check that there is no isolated scope already
+ assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
+ $compileNode);
+ }
+ }
+
+ newScopeDirective = newScopeDirective || directive;
+ }
+
+ directiveName = directive.name;
+
+ if (!directive.templateUrl && directive.controller) {
+ directiveValue = directive.controller;
+ controllerDirectives = controllerDirectives || createMap();
+ assertNoDuplicate("'" + directiveName + "' controller",
+ controllerDirectives[directiveName], directive, $compileNode);
+ controllerDirectives[directiveName] = directive;
+ }
+
+ if (directiveValue = directive.transclude) {
+ hasTranscludeDirective = true;
+
+ // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
+ // This option should only be used by directives that know how to safely handle element transclusion,
+ // where the transcluded nodes are added or replaced after linking.
+ if (!directive.$$tlb) {
+ assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
+ nonTlbTranscludeDirective = directive;
+ }
+
+ if (directiveValue == 'element') {
+ hasElementTranscludeDirective = true;
+ terminalPriority = directive.priority;
+ $template = $compileNode;
+ $compileNode = templateAttrs.$$element =
+ jqLite(document.createComment(' ' + directiveName + ': ' +
+ templateAttrs[directiveName] + ' '));
+ compileNode = $compileNode[0];
+ replaceWith(jqCollection, sliceArgs($template), compileNode);
+
+ childTranscludeFn = compile($template, transcludeFn, terminalPriority,
+ replaceDirective && replaceDirective.name, {
+ // Don't pass in:
+ // - controllerDirectives - otherwise we'll create duplicates controllers
+ // - newIsolateScopeDirective or templateDirective - combining templates with
+ // element transclusion doesn't make sense.
+ //
+ // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
+ // on the same element more than once.
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ } else {
+ $template = jqLite(jqLiteClone(compileNode)).contents();
+ $compileNode.empty(); // clear contents
+ childTranscludeFn = compile($template, transcludeFn, undefined,
+ undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
+ }
+ }
+
+ if (directive.template) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ directiveValue = (isFunction(directive.template))
+ ? directive.template($compileNode, templateAttrs)
+ : directive.template;
+
+ directiveValue = denormalizeTemplate(directiveValue);
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ if (jqLiteIsTextNode(directiveValue)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ directiveName, '');
+ }
+
+ replaceWith(jqCollection, $compileNode, compileNode);
+
+ var newTemplateAttrs = {$attr: {}};
+
+ // combine directives from the original node and from the template:
+ // - take the array of directives for this element
+ // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
+ // - collect directives from the template and sort them by priority
+ // - combine directives as: processed + template + unprocessed
+ var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
+ var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
+
+ if (newIsolateScopeDirective || newScopeDirective) {
+ // The original directive caused the current element to be replaced but this element
+ // also needs to have a new scope, so we need to tell the template directives
+ // that they would need to get their scope from further up, if they require transclusion
+ markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
+ }
+ directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
+ mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
+
+ ii = directives.length;
+ } else {
+ $compileNode.html(directiveValue);
+ }
+ }
+
+ if (directive.templateUrl) {
+ hasTemplate = true;
+ assertNoDuplicate('template', templateDirective, directive, $compileNode);
+ templateDirective = directive;
+
+ if (directive.replace) {
+ replaceDirective = directive;
+ }
+
+ nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
+ templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
+ controllerDirectives: controllerDirectives,
+ newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
+ newIsolateScopeDirective: newIsolateScopeDirective,
+ templateDirective: templateDirective,
+ nonTlbTranscludeDirective: nonTlbTranscludeDirective
+ });
+ ii = directives.length;
+ } else if (directive.compile) {
+ try {
+ linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
+ if (isFunction(linkFn)) {
+ addLinkFns(null, linkFn, attrStart, attrEnd);
+ } else if (linkFn) {
+ addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
+ }
+ } catch (e) {
+ $exceptionHandler(e, startingTag($compileNode));
+ }
+ }
+
+ if (directive.terminal) {
+ nodeLinkFn.terminal = true;
+ terminalPriority = Math.max(terminalPriority, directive.priority);
+ }
+
+ }
+
+ nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
+ nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
+ nodeLinkFn.templateOnThisElement = hasTemplate;
+ nodeLinkFn.transclude = childTranscludeFn;
+
+ previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
+
+ // might be normal or delayed nodeLinkFn depending on if templateUrl is present
+ return nodeLinkFn;
+
+ ////////////////////
+
+ function addLinkFns(pre, post, attrStart, attrEnd) {
+ if (pre) {
+ if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
+ pre.require = directive.require;
+ pre.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ pre = cloneAndAnnotateFn(pre, {isolateScope: true});
+ }
+ preLinkFns.push(pre);
+ }
+ if (post) {
+ if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
+ post.require = directive.require;
+ post.directiveName = directiveName;
+ if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
+ post = cloneAndAnnotateFn(post, {isolateScope: true});
+ }
+ postLinkFns.push(post);
+ }
+ }
+
+
+ function getControllers(directiveName, require, $element, elementControllers) {
+ var value;
+
+ if (isString(require)) {
+ var match = require.match(REQUIRE_PREFIX_REGEXP);
+ var name = require.substring(match[0].length);
+ var inheritType = match[1] || match[3];
+ var optional = match[2] === '?';
+
+ //If only parents then start at the parent element
+ if (inheritType === '^^') {
+ $element = $element.parent();
+ //Otherwise attempt getting the controller from elementControllers in case
+ //the element is transcluded (and has no data) and to avoid .data if possible
+ } else {
+ value = elementControllers && elementControllers[name];
+ value = value && value.instance;
+ }
+
+ if (!value) {
+ var dataName = '$' + name + 'Controller';
+ value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
+ }
+
+ if (!value && !optional) {
+ throw $compileMinErr('ctreq',
+ "Controller '{0}', required by directive '{1}', can't be found!",
+ name, directiveName);
+ }
+ } else if (isArray(require)) {
+ value = [];
+ for (var i = 0, ii = require.length; i < ii; i++) {
+ value[i] = getControllers(directiveName, require[i], $element, elementControllers);
+ }
+ }
+
+ return value || null;
+ }
+
+ function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) {
+ var elementControllers = createMap();
+ for (var controllerKey in controllerDirectives) {
+ var directive = controllerDirectives[controllerKey];
+ var locals = {
+ $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
+ $element: $element,
+ $attrs: attrs,
+ $transclude: transcludeFn
+ };
+
+ var controller = directive.controller;
+ if (controller == '@') {
+ controller = attrs[directive.name];
+ }
+
+ var controllerInstance = $controller(controller, locals, true, directive.controllerAs);
+
+ // For directives with element transclusion the element is a comment,
+ // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
+ // clean up (http://bugs.jquery.com/ticket/8335).
+ // Instead, we save the controllers for the element in a local hash and attach to .data
+ // later, once we have the actual element.
+ elementControllers[directive.name] = controllerInstance;
+ if (!hasElementTranscludeDirective) {
+ $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
+ }
+ }
+ return elementControllers;
+ }
+
+ function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
+ var linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
+ attrs, removeScopeBindingWatches, removeControllerBindingWatches;
+
+ if (compileNode === linkNode) {
+ attrs = templateAttrs;
+ $element = templateAttrs.$$element;
+ } else {
+ $element = jqLite(linkNode);
+ attrs = new Attributes($element, templateAttrs);
+ }
+
+ controllerScope = scope;
+ if (newIsolateScopeDirective) {
+ isolateScope = scope.$new(true);
+ } else if (newScopeDirective) {
+ controllerScope = scope.$parent;
+ }
+
+ if (boundTranscludeFn) {
+ // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
+ // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
+ transcludeFn = controllersBoundTransclude;
+ transcludeFn.$$boundTransclude = boundTranscludeFn;
+ }
+
+ if (controllerDirectives) {
+ elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope);
+ }
+
+ if (newIsolateScopeDirective) {
+ // Initialize isolate scope bindings for new isolate scope directive.
+ compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
+ templateDirective === newIsolateScopeDirective.$$originalDirective)));
+ compile.$$addScopeClass($element, true);
+ isolateScope.$$isolateBindings =
+ newIsolateScopeDirective.$$isolateBindings;
+ removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
+ isolateScope.$$isolateBindings,
+ newIsolateScopeDirective);
+ if (removeScopeBindingWatches) {
+ isolateScope.$on('$destroy', removeScopeBindingWatches);
+ }
+ }
+
+ // Initialize bindToController bindings
+ for (var name in elementControllers) {
+ var controllerDirective = controllerDirectives[name];
+ var controller = elementControllers[name];
+ var bindings = controllerDirective.$$bindings.bindToController;
+
+ if (controller.identifier && bindings) {
+ removeControllerBindingWatches =
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
+ }
+
+ var controllerResult = controller();
+ if (controllerResult !== controller.instance) {
+ // If the controller constructor has a return value, overwrite the instance
+ // from setupControllers
+ controller.instance = controllerResult;
+ $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
+ removeControllerBindingWatches && removeControllerBindingWatches();
+ removeControllerBindingWatches =
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
+ }
+ }
+
+ // PRELINKING
+ for (i = 0, ii = preLinkFns.length; i < ii; i++) {
+ linkFn = preLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // RECURSION
+ // We only pass the isolate scope, if the isolate directive has a template,
+ // otherwise the child elements do not belong to the isolate directive.
+ var scopeToChild = scope;
+ if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
+ scopeToChild = isolateScope;
+ }
+ childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
+
+ // POSTLINKING
+ for (i = postLinkFns.length - 1; i >= 0; i--) {
+ linkFn = postLinkFns[i];
+ invokeLinkFn(linkFn,
+ linkFn.isolateScope ? isolateScope : scope,
+ $element,
+ attrs,
+ linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
+ transcludeFn
+ );
+ }
+
+ // This is the function that is injected as `$transclude`.
+ // Note: all arguments are optional!
+ function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
+ var transcludeControllers;
+
+ // No scope passed in:
+ if (!isScope(scope)) {
+ futureParentElement = cloneAttachFn;
+ cloneAttachFn = scope;
+ scope = undefined;
+ }
+
+ if (hasElementTranscludeDirective) {
+ transcludeControllers = elementControllers;
+ }
+ if (!futureParentElement) {
+ futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
+ }
+ return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
+ }
+ }
+ }
+
+ // Depending upon the context in which a directive finds itself it might need to have a new isolated
+ // or child scope created. For instance:
+ // * if the directive has been pulled into a template because another directive with a higher priority
+ // asked for element transclusion
+ // * if the directive itself asks for transclusion but it is at the root of a template and the original
+ // element was replaced. See https://github.com/angular/angular.js/issues/12936
+ function markDirectiveScope(directives, isolateScope, newScope) {
+ for (var j = 0, jj = directives.length; j < jj; j++) {
+ directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
+ }
+ }
+
+ /**
+ * looks up the directive and decorates it with exception handling and proper parameters. We
+ * call this the boundDirective.
+ *
+ * @param {string} name name of the directive to look up.
+ * @param {string} location The directive must be found in specific format.
+ * String containing any of theses characters:
+ *
+ * * `E`: element name
+ * * `A': attribute
+ * * `C`: class
+ * * `M`: comment
+ * @returns {boolean} true if directive was added.
+ */
+ function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
+ endAttrName) {
+ if (name === ignoreDirective) return null;
+ var match = null;
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ try {
+ directive = directives[i];
+ if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
+ directive.restrict.indexOf(location) != -1) {
+ if (startAttrName) {
+ directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
+ }
+ tDirectives.push(directive);
+ match = directive;
+ }
+ } catch (e) { $exceptionHandler(e); }
+ }
+ }
+ return match;
+ }
+
+
+ /**
+ * looks up the directive and returns true if it is a multi-element directive,
+ * and therefore requires DOM nodes between -start and -end markers to be grouped
+ * together.
+ *
+ * @param {string} name name of the directive to look up.
+ * @returns true if directive was registered as multi-element.
+ */
+ function directiveIsMultiElement(name) {
+ if (hasDirectives.hasOwnProperty(name)) {
+ for (var directive, directives = $injector.get(name + Suffix),
+ i = 0, ii = directives.length; i < ii; i++) {
+ directive = directives[i];
+ if (directive.multiElement) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * When the element is replaced with HTML template then the new attributes
+ * on the template need to be merged with the existing attributes in the DOM.
+ * The desired effect is to have both of the attributes present.
+ *
+ * @param {object} dst destination attributes (original DOM)
+ * @param {object} src source attributes (from the directive template)
+ */
+ function mergeTemplateAttributes(dst, src) {
+ var srcAttr = src.$attr,
+ dstAttr = dst.$attr,
+ $element = dst.$$element;
+
+ // reapply the old attributes to the new element
+ forEach(dst, function(value, key) {
+ if (key.charAt(0) != '$') {
+ if (src[key] && src[key] !== value) {
+ value += (key === 'style' ? ';' : ' ') + src[key];
+ }
+ dst.$set(key, value, true, srcAttr[key]);
+ }
+ });
+
+ // copy the new attributes on the old attrs object
+ forEach(src, function(value, key) {
+ if (key == 'class') {
+ safeAddClass($element, value);
+ dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
+ } else if (key == 'style') {
+ $element.attr('style', $element.attr('style') + ';' + value);
+ dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
+ // `dst` will never contain hasOwnProperty as DOM parser won't let it.
+ // You will get an "InvalidCharacterError: DOM Exception 5" error if you
+ // have an attribute like "has-own-property" or "data-has-own-property", etc.
+ } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
+ dst[key] = value;
+ dstAttr[key] = srcAttr[key];
+ }
+ });
+ }
+
+
+ function compileTemplateUrl(directives, $compileNode, tAttrs,
+ $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
+ var linkQueue = [],
+ afterTemplateNodeLinkFn,
+ afterTemplateChildLinkFn,
+ beforeTemplateCompileNode = $compileNode[0],
+ origAsyncDirective = directives.shift(),
+ derivedSyncDirective = inherit(origAsyncDirective, {
+ templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
+ }),
+ templateUrl = (isFunction(origAsyncDirective.templateUrl))
+ ? origAsyncDirective.templateUrl($compileNode, tAttrs)
+ : origAsyncDirective.templateUrl,
+ templateNamespace = origAsyncDirective.templateNamespace;
+
+ $compileNode.empty();
+
+ $templateRequest(templateUrl)
+ .then(function(content) {
+ var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
+
+ content = denormalizeTemplate(content);
+
+ if (origAsyncDirective.replace) {
+ if (jqLiteIsTextNode(content)) {
+ $template = [];
+ } else {
+ $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
+ }
+ compileNode = $template[0];
+
+ if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
+ throw $compileMinErr('tplrt',
+ "Template for directive '{0}' must have exactly one root element. {1}",
+ origAsyncDirective.name, templateUrl);
+ }
+
+ tempTemplateAttrs = {$attr: {}};
+ replaceWith($rootElement, $compileNode, compileNode);
+ var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
+
+ if (isObject(origAsyncDirective.scope)) {
+ // the original directive that caused the template to be loaded async required
+ // an isolate scope
+ markDirectiveScope(templateDirectives, true);
+ }
+ directives = templateDirectives.concat(directives);
+ mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
+ } else {
+ compileNode = beforeTemplateCompileNode;
+ $compileNode.html(content);
+ }
+
+ directives.unshift(derivedSyncDirective);
+
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
+ childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
+ previousCompileContext);
+ forEach($rootElement, function(node, i) {
+ if (node == compileNode) {
+ $rootElement[i] = $compileNode[0];
+ }
+ });
+ afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
+
+ while (linkQueue.length) {
+ var scope = linkQueue.shift(),
+ beforeTemplateLinkNode = linkQueue.shift(),
+ linkRootElement = linkQueue.shift(),
+ boundTranscludeFn = linkQueue.shift(),
+ linkNode = $compileNode[0];
+
+ if (scope.$$destroyed) continue;
+
+ if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
+ var oldClasses = beforeTemplateLinkNode.className;
+
+ if (!(previousCompileContext.hasElementTranscludeDirective &&
+ origAsyncDirective.replace)) {
+ // it was cloned therefore we have to clone as well.
+ linkNode = jqLiteClone(compileNode);
+ }
+ replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
+
+ // Copy in CSS classes from original node
+ safeAddClass(jqLite(linkNode), oldClasses);
+ }
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ } else {
+ childBoundTranscludeFn = boundTranscludeFn;
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
+ childBoundTranscludeFn);
+ }
+ linkQueue = null;
+ });
+
+ return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
+ var childBoundTranscludeFn = boundTranscludeFn;
+ if (scope.$$destroyed) return;
+ if (linkQueue) {
+ linkQueue.push(scope,
+ node,
+ rootElement,
+ childBoundTranscludeFn);
+ } else {
+ if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
+ childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
+ }
+ afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
+ }
+ };
+ }
+
+
+ /**
+ * Sorting function for bound directives.
+ */
+ function byPriority(a, b) {
+ var diff = b.priority - a.priority;
+ if (diff !== 0) return diff;
+ if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
+ return a.index - b.index;
+ }
+
+ function assertNoDuplicate(what, previousDirective, directive, element) {
+
+ function wrapModuleNameIfDefined(moduleName) {
+ return moduleName ?
+ (' (module: ' + moduleName + ')') :
+ '';
+ }
+
+ if (previousDirective) {
+ throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
+ previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
+ directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
+ }
+ }
+
+
+ function addTextInterpolateDirective(directives, text) {
+ var interpolateFn = $interpolate(text, true);
+ if (interpolateFn) {
+ directives.push({
+ priority: 0,
+ compile: function textInterpolateCompileFn(templateNode) {
+ var templateNodeParent = templateNode.parent(),
+ hasCompileParent = !!templateNodeParent.length;
+
+ // When transcluding a template that has bindings in the root
+ // we don't have a parent and thus need to add the class during linking fn.
+ if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
+
+ return function textInterpolateLinkFn(scope, node) {
+ var parent = node.parent();
+ if (!hasCompileParent) compile.$$addBindingClass(parent);
+ compile.$$addBindingInfo(parent, interpolateFn.expressions);
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
+ node[0].nodeValue = value;
+ });
+ };
+ }
+ });
+ }
+ }
+
+
+ function wrapTemplate(type, template) {
+ type = lowercase(type || 'html');
+ switch (type) {
+ case 'svg':
+ case 'math':
+ var wrapper = document.createElement('div');
+ wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
+ return wrapper.childNodes[0].childNodes;
+ default:
+ return template;
+ }
+ }
+
+
+ function getTrustedContext(node, attrNormalizedName) {
+ if (attrNormalizedName == "srcdoc") {
+ return $sce.HTML;
+ }
+ var tag = nodeName_(node);
+ // maction[xlink:href] can source SVG. It's not limited to <maction>.
+ if (attrNormalizedName == "xlinkHref" ||
+ (tag == "form" && attrNormalizedName == "action") ||
+ (tag != "img" && (attrNormalizedName == "src" ||
+ attrNormalizedName == "ngSrc"))) {
+ return $sce.RESOURCE_URL;
+ }
+ }
+
+
+ function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
+ var trustedContext = getTrustedContext(node, name);
+ allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
+
+ var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
+
+ // no interpolation found -> ignore
+ if (!interpolateFn) return;
+
+
+ if (name === "multiple" && nodeName_(node) === "select") {
+ throw $compileMinErr("selmulti",
+ "Binding to the 'multiple' attribute is not supported. Element: {0}",
+ startingTag(node));
+ }
+
+ directives.push({
+ priority: 100,
+ compile: function() {
+ return {
+ pre: function attrInterpolatePreLinkFn(scope, element, attr) {
+ var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
+
+ if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
+ throw $compileMinErr('nodomevents',
+ "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
+ "ng- versions (such as ng-click instead of onclick) instead.");
+ }
+
+ // If the attribute has changed since last $interpolate()ed
+ var newValue = attr[name];
+ if (newValue !== value) {
+ // we need to interpolate again since the attribute value has been updated
+ // (e.g. by another directive's compile function)
+ // ensure unset/empty values make interpolateFn falsy
+ interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
+ value = newValue;
+ }
+
+ // if attribute was updated so that there is no interpolation going on we don't want to
+ // register any observers
+ if (!interpolateFn) return;
+
+ // initialize attr object so that it's ready in case we need the value for isolate
+ // scope initialization, otherwise the value would not be available from isolate
+ // directive's linking fn during linking phase
+ attr[name] = interpolateFn(scope);
+
+ ($$observers[name] || ($$observers[name] = [])).$$inter = true;
+ (attr.$$observers && attr.$$observers[name].$$scope || scope).
+ $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
+ //special case for class attribute addition + removal
+ //so that class changes can tap into the animation
+ //hooks provided by the $animate service. Be sure to
+ //skip animations when the first digest occurs (when
+ //both the new and the old values are the same) since
+ //the CSS classes are the non-interpolated values
+ if (name === 'class' && newValue != oldValue) {
+ attr.$updateClass(newValue, oldValue);
+ } else {
+ attr.$set(name, newValue);
+ }
+ });
+ }
+ };
+ }
+ });
+ }
+
+
+ /**
+ * This is a special jqLite.replaceWith, which can replace items which
+ * have no parents, provided that the containing jqLite collection is provided.
+ *
+ * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
+ * in the root of the tree.
+ * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
+ * the shell, but replace its DOM node reference.
+ * @param {Node} newNode The new DOM node.
+ */
+ function replaceWith($rootElement, elementsToRemove, newNode) {
+ var firstElementToRemove = elementsToRemove[0],
+ removeCount = elementsToRemove.length,
+ parent = firstElementToRemove.parentNode,
+ i, ii;
+
+ if ($rootElement) {
+ for (i = 0, ii = $rootElement.length; i < ii; i++) {
+ if ($rootElement[i] == firstElementToRemove) {
+ $rootElement[i++] = newNode;
+ for (var j = i, j2 = j + removeCount - 1,
+ jj = $rootElement.length;
+ j < jj; j++, j2++) {
+ if (j2 < jj) {
+ $rootElement[j] = $rootElement[j2];
+ } else {
+ delete $rootElement[j];
+ }
+ }
+ $rootElement.length -= removeCount - 1;
+
+ // If the replaced element is also the jQuery .context then replace it
+ // .context is a deprecated jQuery api, so we should set it only when jQuery set it
+ // http://api.jquery.com/context/
+ if ($rootElement.context === firstElementToRemove) {
+ $rootElement.context = newNode;
+ }
+ break;
+ }
+ }
+ }
+
+ if (parent) {
+ parent.replaceChild(newNode, firstElementToRemove);
+ }
+
+ // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(firstElementToRemove);
+
+ if (jqLite.hasData(firstElementToRemove)) {
+ // Copy over user data (that includes Angular's $scope etc.). Don't copy private
+ // data here because there's no public interface in jQuery to do that and copying over
+ // event listeners (which is the main use of private data) wouldn't work anyway.
+ jqLite.data(newNode, jqLite.data(firstElementToRemove));
+
+ // Remove data of the replaced element. We cannot just call .remove()
+ // on the element it since that would deallocate scope that is needed
+ // for the new node. Instead, remove the data "manually".
+ if (!jQuery) {
+ delete jqLite.cache[firstElementToRemove[jqLite.expando]];
+ } else {
+ // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
+ // the replaced element. The cleanData version monkey-patched by Angular would cause
+ // the scope to be trashed and we do need the very same scope to work with the new
+ // element. However, we cannot just cache the non-patched version and use it here as
+ // that would break if another library patches the method after Angular does (one
+ // example is jQuery UI). Instead, set a flag indicating scope destroying should be
+ // skipped this one time.
+ skipDestroyOnNextJQueryCleanData = true;
+ jQuery.cleanData([firstElementToRemove]);
+ }
+ }
+
+ for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
+ var element = elementsToRemove[k];
+ jqLite(element).remove(); // must do this way to clean up expando
+ fragment.appendChild(element);
+ delete elementsToRemove[k];
+ }
+
+ elementsToRemove[0] = newNode;
+ elementsToRemove.length = 1;
+ }
+
+
+ function cloneAndAnnotateFn(fn, annotation) {
+ return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
+ }
+
+
+ function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
+ try {
+ linkFn(scope, $element, attrs, controllers, transcludeFn);
+ } catch (e) {
+ $exceptionHandler(e, startingTag($element));
+ }
+ }
+
+
+ // Set up $watches for isolate scope and controller bindings. This process
+ // only occurs for isolate scopes and new scopes with controllerAs.
+ function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
+ var removeWatchCollection = [];
+ forEach(bindings, function(definition, scopeName) {
+ var attrName = definition.attrName,
+ optional = definition.optional,
+ mode = definition.mode, // @, =, or &
+ lastValue,
+ parentGet, parentSet, compare;
+
+ switch (mode) {
+
+ case '@':
+ if (!optional && !hasOwnProperty.call(attrs, attrName)) {
+ destination[scopeName] = attrs[attrName] = void 0;
+ }
+ attrs.$observe(attrName, function(value) {
+ if (isString(value)) {
+ destination[scopeName] = value;
+ }
+ });
+ attrs.$$observers[attrName].$$scope = scope;
+ if (isString(attrs[attrName])) {
+ // If the attribute has been provided then we trigger an interpolation to ensure
+ // the value is there for use in the link fn
+ destination[scopeName] = $interpolate(attrs[attrName])(scope);
+ }
+ break;
+
+ case '=':
+ if (!hasOwnProperty.call(attrs, attrName)) {
+ if (optional) break;
+ attrs[attrName] = void 0;
+ }
+ if (optional && !attrs[attrName]) break;
+
+ parentGet = $parse(attrs[attrName]);
+ if (parentGet.literal) {
+ compare = equals;
+ } else {
+ compare = function(a, b) { return a === b || (a !== a && b !== b); };
+ }
+ parentSet = parentGet.assign || function() {
+ // reset the change, or we will throw this exception on every $digest
+ lastValue = destination[scopeName] = parentGet(scope);
+ throw $compileMinErr('nonassign',
+ "Expression '{0}' used with directive '{1}' is non-assignable!",
+ attrs[attrName], directive.name);
+ };
+ lastValue = destination[scopeName] = parentGet(scope);
+ var parentValueWatch = function parentValueWatch(parentValue) {
+ if (!compare(parentValue, destination[scopeName])) {
+ // we are out of sync and need to copy
+ if (!compare(parentValue, lastValue)) {
+ // parent changed and it has precedence
+ destination[scopeName] = parentValue;
+ } else {
+ // if the parent can be assigned then do so
+ parentSet(scope, parentValue = destination[scopeName]);
+ }
+ }
+ return lastValue = parentValue;
+ };
+ parentValueWatch.$stateful = true;
+ var removeWatch;
+ if (definition.collection) {
+ removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
+ } else {
+ removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
+ }
+ removeWatchCollection.push(removeWatch);
+ break;
+
+ case '&':
+ // Don't assign Object.prototype method to scope
+ parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
+
+ // Don't assign noop to destination if expression is not valid
+ if (parentGet === noop && optional) break;
+
+ destination[scopeName] = function(locals) {
+ return parentGet(scope, locals);
+ };
+ break;
+ }
+ });
+
+ return removeWatchCollection.length && function removeWatches() {
+ for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
+ removeWatchCollection[i]();
+ }
+ };
+ }
+ }];
+}
+
+var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
+/**
+ * Converts all accepted directives format into proper directive name.
+ * @param name Name to normalize
+ */
+function directiveNormalize(name) {
+ return camelCase(name.replace(PREFIX_REGEXP, ''));
+}
+
+/**
+ * @ngdoc type
+ * @name $compile.directive.Attributes
+ *
+ * @description
+ * A shared object between directive compile / linking functions which contains normalized DOM
+ * element attributes. The values reflect current binding state `{{ }}`. The normalization is
+ * needed since all of these are treated as equivalent in Angular:
+ *
+ * ```
+ * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
+ * ```
+ */
+
+/**
+ * @ngdoc property
+ * @name $compile.directive.Attributes#$attr
+ *
+ * @description
+ * A map of DOM element attribute names to the normalized name. This is
+ * needed to do reverse lookup from normalized name back to actual name.
+ */
+
+
+/**
+ * @ngdoc method
+ * @name $compile.directive.Attributes#$set
+ * @kind function
+ *
+ * @description
+ * Set DOM element attribute value.
+ *
+ *
+ * @param {string} name Normalized element attribute name of the property to modify. The name is
+ * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
+ * property to the original name.
+ * @param {string} value Value to set the attribute to. The value can be an interpolated string.
+ */
+
+
+
+/**
+ * Closure compiler type information
+ */
+
+function nodesetLinkingFn(
+ /* angular.Scope */ scope,
+ /* NodeList */ nodeList,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function directiveLinkingFn(
+ /* nodesetLinkingFn */ nodesetLinkingFn,
+ /* angular.Scope */ scope,
+ /* Node */ node,
+ /* Element */ rootElement,
+ /* function(Function) */ boundTranscludeFn
+) {}
+
+function tokenDifference(str1, str2) {
+ var values = '',
+ tokens1 = str1.split(/\s+/),
+ tokens2 = str2.split(/\s+/);
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values += (values.length > 0 ? ' ' : '') + token;
+ }
+ return values;
+}
+
+function removeComments(jqNodes) {
+ jqNodes = jqLite(jqNodes);
+ var i = jqNodes.length;
+
+ if (i <= 1) {
+ return jqNodes;
+ }
+
+ while (i--) {
+ var node = jqNodes[i];
+ if (node.nodeType === NODE_TYPE_COMMENT) {
+ splice.call(jqNodes, i, 1);
+ }
+ }
+ return jqNodes;
+}
+
+var $controllerMinErr = minErr('$controller');
+
+
+var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
+function identifierForController(controller, ident) {
+ if (ident && isString(ident)) return ident;
+ if (isString(controller)) {
+ var match = CNTRL_REG.exec(controller);
+ if (match) return match[3];
+ }
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $controllerProvider
+ * @description
+ * The {@link ng.$controller $controller service} is used by Angular to create new
+ * controllers.
+ *
+ * This provider allows controller registration via the
+ * {@link ng.$controllerProvider#register register} method.
+ */
+function $ControllerProvider() {
+ var controllers = {},
+ globals = false;
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#register
+ * @param {string|Object} name Controller name, or an object map of controllers where the keys are
+ * the names and the values are the constructors.
+ * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
+ * annotations in the array notation).
+ */
+ this.register = function(name, constructor) {
+ assertNotHasOwnProperty(name, 'controller');
+ if (isObject(name)) {
+ extend(controllers, name);
+ } else {
+ controllers[name] = constructor;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#allowGlobals
+ * @description If called, allows `$controller` to find controller constructors on `window`
+ */
+ this.allowGlobals = function() {
+ globals = true;
+ };
+
+
+ this.$get = ['$injector', '$window', function($injector, $window) {
+
+ /**
+ * @ngdoc service
+ * @name $controller
+ * @requires $injector
+ *
+ * @param {Function|string} constructor If called with a function then it's considered to be the
+ * controller constructor function. Otherwise it's considered to be a string which is used
+ * to retrieve the controller constructor using the following steps:
+ *
+ * * check if a controller with given name is registered via `$controllerProvider`
+ * * check if evaluating the string on the current scope returns a constructor
+ * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
+ * `window` object (not recommended)
+ *
+ * The string can use the `controller as property` syntax, where the controller instance is published
+ * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
+ * to work correctly.
+ *
+ * @param {Object} locals Injection locals for Controller.
+ * @return {Object} Instance of given controller.
+ *
+ * @description
+ * `$controller` service is responsible for instantiating controllers.
+ *
+ * It's just a simple call to {@link auto.$injector $injector}, but extracted into
+ * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
+ */
+ return function(expression, locals, later, ident) {
+ // PRIVATE API:
+ // param `later` --- indicates that the controller's constructor is invoked at a later time.
+ // If true, $controller will allocate the object with the correct
+ // prototype chain, but will not invoke the controller until a returned
+ // callback is invoked.
+ // param `ident` --- An optional label which overrides the label parsed from the controller
+ // expression, if any.
+ var instance, match, constructor, identifier;
+ later = later === true;
+ if (ident && isString(ident)) {
+ identifier = ident;
+ }
+
+ if (isString(expression)) {
+ match = expression.match(CNTRL_REG);
+ if (!match) {
+ throw $controllerMinErr('ctrlfmt',
+ "Badly formed controller string '{0}'. " +
+ "Must match `__name__ as __id__` or `__name__`.", expression);
+ }
+ constructor = match[1],
+ identifier = identifier || match[3];
+ expression = controllers.hasOwnProperty(constructor)
+ ? controllers[constructor]
+ : getter(locals.$scope, constructor, true) ||
+ (globals ? getter($window, constructor, true) : undefined);
+
+ assertArgFn(expression, constructor, true);
+ }
+
+ if (later) {
+ // Instantiate controller later:
+ // This machinery is used to create an instance of the object before calling the
+ // controller's constructor itself.
+ //
+ // This allows properties to be added to the controller before the constructor is
+ // invoked. Primarily, this is used for isolate scope bindings in $compile.
+ //
+ // This feature is not intended for use by applications, and is thus not documented
+ // publicly.
+ // Object creation: http://jsperf.com/create-constructor/2
+ var controllerPrototype = (isArray(expression) ?
+ expression[expression.length - 1] : expression).prototype;
+ instance = Object.create(controllerPrototype || null);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ var instantiate;
+ return instantiate = extend(function() {
+ var result = $injector.invoke(expression, instance, locals, constructor);
+ if (result !== instance && (isObject(result) || isFunction(result))) {
+ instance = result;
+ if (identifier) {
+ // If result changed, re-assign controllerAs value to scope.
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+ }
+ return instance;
+ }, {
+ instance: instance,
+ identifier: identifier
+ });
+ }
+
+ instance = $injector.instantiate(expression, locals, constructor);
+
+ if (identifier) {
+ addIdentifier(locals, identifier, instance, constructor || expression.name);
+ }
+
+ return instance;
+ };
+
+ function addIdentifier(locals, identifier, instance, name) {
+ if (!(locals && isObject(locals.$scope))) {
+ throw minErr('$controller')('noscp',
+ "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
+ name, identifier);
+ }
+
+ locals.$scope[identifier] = instance;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $document
+ * @requires $window
+ *
+ * @description
+ * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
+ *
+ * @example
+ <example module="documentExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p>$document title: <b ng-bind="title"></b></p>
+ <p>window.document title: <b ng-bind="windowTitle"></b></p>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('documentExample', [])
+ .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
+ $scope.title = $document[0].title;
+ $scope.windowTitle = angular.element(window.document)[0].title;
+ }]);
+ </file>
+ </example>
+ */
+function $DocumentProvider() {
+ this.$get = ['$window', function(window) {
+ return jqLite(window.document);
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $exceptionHandler
+ * @requires ng.$log
+ *
+ * @description
+ * Any uncaught exception in angular expressions is delegated to this service.
+ * The default implementation simply delegates to `$log.error` which logs it into
+ * the browser console.
+ *
+ * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
+ * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
+ *
+ * ## Example:
+ *
+ * ```js
+ * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
+ * return function(exception, cause) {
+ * exception.message += ' (caused by "' + cause + '")';
+ * throw exception;
+ * };
+ * });
+ * ```
+ *
+ * This example will override the normal action of `$exceptionHandler`, to make angular
+ * exceptions fail hard when they happen, instead of just logging to the console.
+ *
+ * <hr />
+ * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
+ * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
+ * (unless executed during a digest).
+ *
+ * If you wish, you can manually delegate exceptions, e.g.
+ * `try { ... } catch(e) { $exceptionHandler(e); }`
+ *
+ * @param {Error} exception Exception associated with the error.
+ * @param {string=} cause optional information about the context in which
+ * the error was thrown.
+ *
+ */
+function $ExceptionHandlerProvider() {
+ this.$get = ['$log', function($log) {
+ return function(exception, cause) {
+ $log.error.apply($log, arguments);
+ };
+ }];
+}
+
+var $$ForceReflowProvider = function() {
+ this.$get = ['$document', function($document) {
+ return function(domNode) {
+ //the line below will force the browser to perform a repaint so
+ //that all the animated elements within the animation frame will
+ //be properly updated and drawn on screen. This is required to
+ //ensure that the preparation animation is properly flushed so that
+ //the active state picks up from there. DO NOT REMOVE THIS LINE.
+ //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
+ //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
+ //WILL TAKE YEARS AWAY FROM YOUR LIFE.
+ if (domNode) {
+ if (!domNode.nodeType && domNode instanceof jqLite) {
+ domNode = domNode[0];
+ }
+ } else {
+ domNode = $document[0].body;
+ }
+ return domNode.offsetWidth + 1;
+ };
+ }];
+};
+
+var APPLICATION_JSON = 'application/json';
+var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
+var JSON_START = /^\[|^\{(?!\{)/;
+var JSON_ENDS = {
+ '[': /]$/,
+ '{': /}$/
+};
+var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
+var $httpMinErr = minErr('$http');
+var $httpMinErrLegacyFn = function(method) {
+ return function() {
+ throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method);
+ };
+};
+
+function serializeValue(v) {
+ if (isObject(v)) {
+ return isDate(v) ? v.toISOString() : toJson(v);
+ }
+ return v;
+}
+
+
+function $HttpParamSerializerProvider() {
+ /**
+ * @ngdoc service
+ * @name $httpParamSerializer
+ * @description
+ *
+ * Default {@link $http `$http`} params serializer that converts objects to strings
+ * according to the following rules:
+ *
+ * * `{'foo': 'bar'}` results in `foo=bar`
+ * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
+ * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
+ * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
+ *
+ * Note that serializer will sort the request parameters alphabetically.
+ * */
+
+ this.$get = function() {
+ return function ngParamSerializer(params) {
+ if (!params) return '';
+ var parts = [];
+ forEachSorted(params, function(value, key) {
+ if (value === null || isUndefined(value)) return;
+ if (isArray(value)) {
+ forEach(value, function(v, k) {
+ parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v)));
+ });
+ } else {
+ parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
+ }
+ });
+
+ return parts.join('&');
+ };
+ };
+}
+
+function $HttpParamSerializerJQLikeProvider() {
+ /**
+ * @ngdoc service
+ * @name $httpParamSerializerJQLike
+ * @description
+ *
+ * Alternative {@link $http `$http`} params serializer that follows
+ * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
+ * The serializer will also sort the params alphabetically.
+ *
+ * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
+ *
+ * ```js
+ * $http({
+ * url: myUrl,
+ * method: 'GET',
+ * params: myParams,
+ * paramSerializer: '$httpParamSerializerJQLike'
+ * });
+ * ```
+ *
+ * It is also possible to set it as the default `paramSerializer` in the
+ * {@link $httpProvider#defaults `$httpProvider`}.
+ *
+ * Additionally, you can inject the serializer and use it explicitly, for example to serialize
+ * form data for submission:
+ *
+ * ```js
+ * .controller(function($http, $httpParamSerializerJQLike) {
+ * //...
+ *
+ * $http({
+ * url: myUrl,
+ * method: 'POST',
+ * data: $httpParamSerializerJQLike(myData),
+ * headers: {
+ * 'Content-Type': 'application/x-www-form-urlencoded'
+ * }
+ * });
+ *
+ * });
+ * ```
+ *
+ * */
+ this.$get = function() {
+ return function jQueryLikeParamSerializer(params) {
+ if (!params) return '';
+ var parts = [];
+ serialize(params, '', true);
+ return parts.join('&');
+
+ function serialize(toSerialize, prefix, topLevel) {
+ if (toSerialize === null || isUndefined(toSerialize)) return;
+ if (isArray(toSerialize)) {
+ forEach(toSerialize, function(value, index) {
+ serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
+ });
+ } else if (isObject(toSerialize) && !isDate(toSerialize)) {
+ forEachSorted(toSerialize, function(value, key) {
+ serialize(value, prefix +
+ (topLevel ? '' : '[') +
+ key +
+ (topLevel ? '' : ']'));
+ });
+ } else {
+ parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
+ }
+ }
+ };
+ };
+}
+
+function defaultHttpResponseTransform(data, headers) {
+ if (isString(data)) {
+ // Strip json vulnerability protection prefix and trim whitespace
+ var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
+
+ if (tempData) {
+ var contentType = headers('Content-Type');
+ if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
+ data = fromJson(tempData);
+ }
+ }
+ }
+
+ return data;
+}
+
+function isJsonLike(str) {
+ var jsonStart = str.match(JSON_START);
+ return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
+}
+
+/**
+ * Parse headers into key value object
+ *
+ * @param {string} headers Raw headers as a string
+ * @returns {Object} Parsed headers as key value object
+ */
+function parseHeaders(headers) {
+ var parsed = createMap(), i;
+
+ function fillInParsed(key, val) {
+ if (key) {
+ parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
+ }
+ }
+
+ if (isString(headers)) {
+ forEach(headers.split('\n'), function(line) {
+ i = line.indexOf(':');
+ fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));
+ });
+ } else if (isObject(headers)) {
+ forEach(headers, function(headerVal, headerKey) {
+ fillInParsed(lowercase(headerKey), trim(headerVal));
+ });
+ }
+
+ return parsed;
+}
+
+
+/**
+ * Returns a function that provides access to parsed headers.
+ *
+ * Headers are lazy parsed when first requested.
+ * @see parseHeaders
+ *
+ * @param {(string|Object)} headers Headers to provide access to.
+ * @returns {function(string=)} Returns a getter function which if called with:
+ *
+ * - if called with single an argument returns a single header value or null
+ * - if called with no arguments returns an object containing all headers.
+ */
+function headersGetter(headers) {
+ var headersObj;
+
+ return function(name) {
+ if (!headersObj) headersObj = parseHeaders(headers);
+
+ if (name) {
+ var value = headersObj[lowercase(name)];
+ if (value === void 0) {
+ value = null;
+ }
+ return value;
+ }
+
+ return headersObj;
+ };
+}
+
+
+/**
+ * Chain all given functions
+ *
+ * This function is used for both request and response transforming
+ *
+ * @param {*} data Data to transform.
+ * @param {function(string=)} headers HTTP headers getter fn.
+ * @param {number} status HTTP status code of the response.
+ * @param {(Function|Array.<Function>)} fns Function or an array of functions.
+ * @returns {*} Transformed data.
+ */
+function transformData(data, headers, status, fns) {
+ if (isFunction(fns)) {
+ return fns(data, headers, status);
+ }
+
+ forEach(fns, function(fn) {
+ data = fn(data, headers, status);
+ });
+
+ return data;
+}
+
+
+function isSuccess(status) {
+ return 200 <= status && status < 300;
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $httpProvider
+ * @description
+ * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
+ * */
+function $HttpProvider() {
+ /**
+ * @ngdoc property
+ * @name $httpProvider#defaults
+ * @description
+ *
+ * Object containing default values for all {@link ng.$http $http} requests.
+ *
+ * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
+ * that will provide the cache for all requests who set their `cache` property to `true`.
+ * If you set the `defaults.cache = false` then only requests that specify their own custom
+ * cache object will be cached. See {@link $http#caching $http Caching} for more information.
+ *
+ * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
+ * Defaults value is `'XSRF-TOKEN'`.
+ *
+ * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
+ * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
+ *
+ * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
+ * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
+ * setting default headers.
+ * - **`defaults.headers.common`**
+ * - **`defaults.headers.post`**
+ * - **`defaults.headers.put`**
+ * - **`defaults.headers.patch`**
+ *
+ *
+ * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
+ * used to the prepare string representation of request parameters (specified as an object).
+ * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
+ * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
+ *
+ **/
+ var defaults = this.defaults = {
+ // transform incoming response data
+ transformResponse: [defaultHttpResponseTransform],
+
+ // transform outgoing request data
+ transformRequest: [function(d) {
+ return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
+ }],
+
+ // default headers
+ headers: {
+ common: {
+ 'Accept': 'application/json, text/plain, */*'
+ },
+ post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
+ patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
+ },
+
+ xsrfCookieName: 'XSRF-TOKEN',
+ xsrfHeaderName: 'X-XSRF-TOKEN',
+
+ paramSerializer: '$httpParamSerializer'
+ };
+
+ var useApplyAsync = false;
+ /**
+ * @ngdoc method
+ * @name $httpProvider#useApplyAsync
+ * @description
+ *
+ * Configure $http service to combine processing of multiple http responses received at around
+ * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
+ * significant performance improvement for bigger applications that make many HTTP requests
+ * concurrently (common during application bootstrap).
+ *
+ * Defaults to false. If no value is specified, returns the current configured value.
+ *
+ * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
+ * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
+ * to load and share the same digest cycle.
+ *
+ * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
+ * otherwise, returns the current configured value.
+ **/
+ this.useApplyAsync = function(value) {
+ if (isDefined(value)) {
+ useApplyAsync = !!value;
+ return this;
+ }
+ return useApplyAsync;
+ };
+
+ var useLegacyPromise = true;
+ /**
+ * @ngdoc method
+ * @name $httpProvider#useLegacyPromiseExtensions
+ * @description
+ *
+ * Configure `$http` service to return promises without the shorthand methods `success` and `error`.
+ * This should be used to make sure that applications work without these methods.
+ *
+ * Defaults to true. If no value is specified, returns the current configured value.
+ *
+ * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.
+ *
+ * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
+ * otherwise, returns the current configured value.
+ **/
+ this.useLegacyPromiseExtensions = function(value) {
+ if (isDefined(value)) {
+ useLegacyPromise = !!value;
+ return this;
+ }
+ return useLegacyPromise;
+ };
+
+ /**
+ * @ngdoc property
+ * @name $httpProvider#interceptors
+ * @description
+ *
+ * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
+ * pre-processing of request or postprocessing of responses.
+ *
+ * These service factories are ordered by request, i.e. they are applied in the same order as the
+ * array, on request, but reverse order, on response.
+ *
+ * {@link ng.$http#interceptors Interceptors detailed info}
+ **/
+ var interceptorFactories = this.interceptors = [];
+
+ this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
+ function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
+
+ var defaultCache = $cacheFactory('$http');
+
+ /**
+ * Make sure that default param serializer is exposed as a function
+ */
+ defaults.paramSerializer = isString(defaults.paramSerializer) ?
+ $injector.get(defaults.paramSerializer) : defaults.paramSerializer;
+
+ /**
+ * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
+ * The reversal is needed so that we can build up the interception chain around the
+ * server request.
+ */
+ var reversedInterceptors = [];
+
+ forEach(interceptorFactories, function(interceptorFactory) {
+ reversedInterceptors.unshift(isString(interceptorFactory)
+ ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
+ });
+
+ /**
+ * @ngdoc service
+ * @kind function
+ * @name $http
+ * @requires ng.$httpBackend
+ * @requires $cacheFactory
+ * @requires $rootScope
+ * @requires $q
+ * @requires $injector
+ *
+ * @description
+ * The `$http` service is a core Angular service that facilitates communication with the remote
+ * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
+ * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
+ *
+ * For unit testing applications that use `$http` service, see
+ * {@link ngMock.$httpBackend $httpBackend mock}.
+ *
+ * For a higher level of abstraction, please check out the {@link ngResource.$resource
+ * $resource} service.
+ *
+ * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
+ * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
+ * it is important to familiarize yourself with these APIs and the guarantees they provide.
+ *
+ *
+ * ## General usage
+ * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —
+ * that is used to generate an HTTP request and returns a {@link ng.$q promise}.
+ *
+ * ```js
+ * // Simple GET request example:
+ * $http({
+ * method: 'GET',
+ * url: '/someUrl'
+ * }).then(function successCallback(response) {
+ * // this callback will be called asynchronously
+ * // when the response is available
+ * }, function errorCallback(response) {
+ * // called asynchronously if an error occurs
+ * // or server returns response with an error status.
+ * });
+ * ```
+ *
+ * The response object has these properties:
+ *
+ * - **data** – `{string|Object}` – The response body transformed with the transform
+ * functions.
+ * - **status** – `{number}` – HTTP status code of the response.
+ * - **headers** – `{function([headerName])}` – Header getter function.
+ * - **config** – `{Object}` – The configuration object that was used to generate the request.
+ * - **statusText** – `{string}` – HTTP status text of the response.
+ *
+ * A response status code between 200 and 299 is considered a success status and
+ * will result in the success callback being called. Note that if the response is a redirect,
+ * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
+ * called for such responses.
+ *
+ *
+ * ## Shortcut methods
+ *
+ * Shortcut methods are also available. All shortcut methods require passing in the URL, and
+ * request data must be passed in for POST/PUT requests. An optional config can be passed as the
+ * last argument.
+ *
+ * ```js
+ * $http.get('/someUrl', config).then(successCallback, errorCallback);
+ * $http.post('/someUrl', data, config).then(successCallback, errorCallback);
+ * ```
+ *
+ * Complete list of shortcut methods:
+ *
+ * - {@link ng.$http#get $http.get}
+ * - {@link ng.$http#head $http.head}
+ * - {@link ng.$http#post $http.post}
+ * - {@link ng.$http#put $http.put}
+ * - {@link ng.$http#delete $http.delete}
+ * - {@link ng.$http#jsonp $http.jsonp}
+ * - {@link ng.$http#patch $http.patch}
+ *
+ *
+ * ## Writing Unit Tests that use $http
+ * When unit testing (using {@link ngMock ngMock}), it is necessary to call
+ * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
+ * request using trained responses.
+ *
+ * ```
+ * $httpBackend.expectGET(...);
+ * $http.get(...);
+ * $httpBackend.flush();
+ * ```
+ *
+ * ## Deprecation Notice
+ * <div class="alert alert-danger">
+ * The `$http` legacy promise methods `success` and `error` have been deprecated.
+ * Use the standard `then` method instead.
+ * If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to
+ * `false` then these methods will throw {@link $http:legacy `$http/legacy`} error.
+ * </div>
+ *
+ * ## Setting HTTP Headers
+ *
+ * The $http service will automatically add certain HTTP headers to all requests. These defaults
+ * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
+ * object, which currently contains this default configuration:
+ *
+ * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
+ * - `Accept: application/json, text/plain, * / *`
+ * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
+ * - `Content-Type: application/json`
+ * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
+ * - `Content-Type: application/json`
+ *
+ * To add or overwrite these defaults, simply add or remove a property from these configuration
+ * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
+ * with the lowercased HTTP method name as the key, e.g.
+ * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.
+ *
+ * The defaults can also be set at runtime via the `$http.defaults` object in the same
+ * fashion. For example:
+ *
+ * ```
+ * module.run(function($http) {
+ * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
+ * });
+ * ```
+ *
+ * In addition, you can supply a `headers` property in the config object passed when
+ * calling `$http(config)`, which overrides the defaults without changing them globally.
+ *
+ * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
+ * Use the `headers` property, setting the desired header to `undefined`. For example:
+ *
+ * ```js
+ * var req = {
+ * method: 'POST',
+ * url: 'http://example.com',
+ * headers: {
+ * 'Content-Type': undefined
+ * },
+ * data: { test: 'test' }
+ * }
+ *
+ * $http(req).then(function(){...}, function(){...});
+ * ```
+ *
+ * ## Transforming Requests and Responses
+ *
+ * Both requests and responses can be transformed using transformation functions: `transformRequest`
+ * and `transformResponse`. These properties can be a single function that returns
+ * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
+ * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
+ *
+ * ### Default Transformations
+ *
+ * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
+ * `defaults.transformResponse` properties. If a request does not provide its own transformations
+ * then these will be applied.
+ *
+ * You can augment or replace the default transformations by modifying these properties by adding to or
+ * replacing the array.
+ *
+ * Angular provides the following default transformations:
+ *
+ * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
+ *
+ * - If the `data` property of the request configuration object contains an object, serialize it
+ * into JSON format.
+ *
+ * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
+ *
+ * - If XSRF prefix is detected, strip it (see Security Considerations section below).
+ * - If JSON response is detected, deserialize it using a JSON parser.
+ *
+ *
+ * ### Overriding the Default Transformations Per Request
+ *
+ * If you wish override the request/response transformations only for a single request then provide
+ * `transformRequest` and/or `transformResponse` properties on the configuration object passed
+ * into `$http`.
+ *
+ * Note that if you provide these properties on the config object the default transformations will be
+ * overwritten. If you wish to augment the default transformations then you must include them in your
+ * local transformation array.
+ *
+ * The following code demonstrates adding a new response transformation to be run after the default response
+ * transformations have been run.
+ *
+ * ```js
+ * function appendTransform(defaults, transform) {
+ *
+ * // We can't guarantee that the default transformation is an array
+ * defaults = angular.isArray(defaults) ? defaults : [defaults];
+ *
+ * // Append the new transformation to the defaults
+ * return defaults.concat(transform);
+ * }
+ *
+ * $http({
+ * url: '...',
+ * method: 'GET',
+ * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
+ * return doTransform(value);
+ * })
+ * });
+ * ```
+ *
+ *
+ * ## Caching
+ *
+ * To enable caching, set the request configuration `cache` property to `true` (to use default
+ * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
+ * When the cache is enabled, `$http` stores the response from the server in the specified
+ * cache. The next time the same request is made, the response is served from the cache without
+ * sending a request to the server.
+ *
+ * Note that even if the response is served from cache, delivery of the data is asynchronous in
+ * the same way that real requests are.
+ *
+ * If there are multiple GET requests for the same URL that should be cached using the same
+ * cache, but the cache is not populated yet, only one request to the server will be made and
+ * the remaining requests will be fulfilled using the response from the first request.
+ *
+ * You can change the default cache to a new object (built with
+ * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
+ * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
+ * their `cache` property to `true` will now use this cache object.
+ *
+ * If you set the default cache to `false` then only requests that specify their own custom
+ * cache object will be cached.
+ *
+ * ## Interceptors
+ *
+ * Before you start creating interceptors, be sure to understand the
+ * {@link ng.$q $q and deferred/promise APIs}.
+ *
+ * For purposes of global error handling, authentication, or any kind of synchronous or
+ * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
+ * able to intercept requests before they are handed to the server and
+ * responses before they are handed over to the application code that
+ * initiated these requests. The interceptors leverage the {@link ng.$q
+ * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
+ *
+ * The interceptors are service factories that are registered with the `$httpProvider` by
+ * adding them to the `$httpProvider.interceptors` array. The factory is called and
+ * injected with dependencies (if specified) and returns the interceptor.
+ *
+ * There are two kinds of interceptors (and two kinds of rejection interceptors):
+ *
+ * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to
+ * modify the `config` object or create a new one. The function needs to return the `config`
+ * object directly, or a promise containing the `config` or a new `config` object.
+ * * `requestError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ * * `response`: interceptors get called with http `response` object. The function is free to
+ * modify the `response` object or create a new one. The function needs to return the `response`
+ * object directly, or as a promise containing the `response` or a new `response` object.
+ * * `responseError`: interceptor gets called when a previous interceptor threw an error or
+ * resolved with a rejection.
+ *
+ *
+ * ```js
+ * // register the interceptor as a service
+ * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+ * return {
+ * // optional method
+ * 'request': function(config) {
+ * // do something on success
+ * return config;
+ * },
+ *
+ * // optional method
+ * 'requestError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * },
+ *
+ *
+ *
+ * // optional method
+ * 'response': function(response) {
+ * // do something on success
+ * return response;
+ * },
+ *
+ * // optional method
+ * 'responseError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * }
+ * };
+ * });
+ *
+ * $httpProvider.interceptors.push('myHttpInterceptor');
+ *
+ *
+ * // alternatively, register the interceptor via an anonymous factory
+ * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
+ * return {
+ * 'request': function(config) {
+ * // same as above
+ * },
+ *
+ * 'response': function(response) {
+ * // same as above
+ * }
+ * };
+ * });
+ * ```
+ *
+ * ## Security Considerations
+ *
+ * When designing web applications, consider security threats from:
+ *
+ * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
+ *
+ * Both server and the client must cooperate in order to eliminate these threats. Angular comes
+ * pre-configured with strategies that address these issues, but for this to work backend server
+ * cooperation is required.
+ *
+ * ### JSON Vulnerability Protection
+ *
+ * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
+ * allows third party website to turn your JSON resource URL into
+ * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
+ * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
+ * Angular will automatically strip the prefix before processing it as JSON.
+ *
+ * For example if your server needs to return:
+ * ```js
+ * ['one','two']
+ * ```
+ *
+ * which is vulnerable to attack, your server can return:
+ * ```js
+ * )]}',
+ * ['one','two']
+ * ```
+ *
+ * Angular will strip the prefix, before processing the JSON.
+ *
+ *
+ * ### Cross Site Request Forgery (XSRF) Protection
+ *
+ * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
+ * an unauthorized site can gain your user's private data. Angular provides a mechanism
+ * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
+ * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
+ * JavaScript that runs on your domain could read the cookie, your server can be assured that
+ * the XHR came from JavaScript running on your domain. The header will not be set for
+ * cross-domain requests.
+ *
+ * To take advantage of this, your server needs to set a token in a JavaScript readable session
+ * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
+ * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
+ * that only JavaScript running on your domain could have sent the request. The token must be
+ * unique for each user and must be verifiable by the server (to prevent the JavaScript from
+ * making up its own tokens). We recommend that the token is a digest of your site's
+ * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
+ * for added security.
+ *
+ * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
+ * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
+ * or the per-request config object.
+ *
+ * In order to prevent collisions in environments where multiple Angular apps share the
+ * same domain or subdomain, we recommend that each application uses unique cookie name.
+ *
+ * @param {object} config Object describing the request to be made and how it should be
+ * processed. The object has following properties:
+ *
+ * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
+ * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
+ * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
+ * with the `paramSerializer` and appended as GET parameters.
+ * - **data** – `{string|Object}` – Data to be sent as the request message data.
+ * - **headers** – `{Object}` – Map of strings or functions which return strings representing
+ * HTTP headers to send to the server. If the return value of a function is null, the
+ * header will not be sent. Functions accept a config object as an argument.
+ * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
+ * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
+ * - **transformRequest** –
+ * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * request body and headers and returns its transformed (typically serialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default Transformations}
+ * - **transformResponse** –
+ * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
+ * transform function or an array of such functions. The transform function takes the http
+ * response body, headers and status and returns its transformed (typically deserialized) version.
+ * See {@link ng.$http#overriding-the-default-transformations-per-request
+ * Overriding the Default TransformationjqLiks}
+ * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
+ * prepare the string representation of request parameters (specified as an object).
+ * If specified as string, it is interpreted as function registered with the
+ * {@link $injector $injector}, which means you can create your own serializer
+ * by registering it as a {@link auto.$provide#service service}.
+ * The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
+ * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
+ * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
+ * GET request, otherwise if a cache instance built with
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
+ * caching.
+ * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
+ * that should abort the request when resolved.
+ * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
+ * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
+ * for more information.
+ * - **responseType** - `{string}` - see
+ * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
+ *
+ * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
+ * when the request succeeds or fails.
+ *
+ *
+ * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
+ * requests. This is primarily meant to be used for debugging purposes.
+ *
+ *
+ * @example
+<example module="httpExample">
+<file name="index.html">
+ <div ng-controller="FetchController">
+ <select ng-model="method" aria-label="Request method">
+ <option>GET</option>
+ <option>JSONP</option>
+ </select>
+ <input type="text" ng-model="url" size="80" aria-label="URL" />
+ <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
+ <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
+ <button id="samplejsonpbtn"
+ ng-click="updateModel('JSONP',
+ 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
+ Sample JSONP
+ </button>
+ <button id="invalidjsonpbtn"
+ ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
+ Invalid JSONP
+ </button>
+ <pre>http status code: {{status}}</pre>
+ <pre>http response data: {{data}}</pre>
+ </div>
+</file>
+<file name="script.js">
+ angular.module('httpExample', [])
+ .controller('FetchController', ['$scope', '$http', '$templateCache',
+ function($scope, $http, $templateCache) {
+ $scope.method = 'GET';
+ $scope.url = 'http-hello.html';
+
+ $scope.fetch = function() {
+ $scope.code = null;
+ $scope.response = null;
+
+ $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
+ then(function(response) {
+ $scope.status = response.status;
+ $scope.data = response.data;
+ }, function(response) {
+ $scope.data = response.data || "Request failed";
+ $scope.status = response.status;
+ });
+ };
+
+ $scope.updateModel = function(method, url) {
+ $scope.method = method;
+ $scope.url = url;
+ };
+ }]);
+</file>
+<file name="http-hello.html">
+ Hello, $http!
+</file>
+<file name="protractor.js" type="protractor">
+ var status = element(by.binding('status'));
+ var data = element(by.binding('data'));
+ var fetchBtn = element(by.id('fetchbtn'));
+ var sampleGetBtn = element(by.id('samplegetbtn'));
+ var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
+ var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
+
+ it('should make an xhr GET request', function() {
+ sampleGetBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('200');
+ expect(data.getText()).toMatch(/Hello, \$http!/);
+ });
+
+// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
+// it('should make a JSONP request to angularjs.org', function() {
+// sampleJsonpBtn.click();
+// fetchBtn.click();
+// expect(status.getText()).toMatch('200');
+// expect(data.getText()).toMatch(/Super Hero!/);
+// });
+
+ it('should make JSONP request to invalid URL and invoke the error handler',
+ function() {
+ invalidJsonpBtn.click();
+ fetchBtn.click();
+ expect(status.getText()).toMatch('0');
+ expect(data.getText()).toMatch('Request failed');
+ });
+</file>
+</example>
+ */
+ function $http(requestConfig) {
+
+ if (!angular.isObject(requestConfig)) {
+ throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
+ }
+
+ var config = extend({
+ method: 'get',
+ transformRequest: defaults.transformRequest,
+ transformResponse: defaults.transformResponse,
+ paramSerializer: defaults.paramSerializer
+ }, requestConfig);
+
+ config.headers = mergeHeaders(requestConfig);
+ config.method = uppercase(config.method);
+ config.paramSerializer = isString(config.paramSerializer) ?
+ $injector.get(config.paramSerializer) : config.paramSerializer;
+
+ var serverRequest = function(config) {
+ var headers = config.headers;
+ var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
+
+ // strip content-type if data is undefined
+ if (isUndefined(reqData)) {
+ forEach(headers, function(value, header) {
+ if (lowercase(header) === 'content-type') {
+ delete headers[header];
+ }
+ });
+ }
+
+ if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
+ config.withCredentials = defaults.withCredentials;
+ }
+
+ // send request
+ return sendReq(config, reqData).then(transformResponse, transformResponse);
+ };
+
+ var chain = [serverRequest, undefined];
+ var promise = $q.when(config);
+
+ // apply interceptors
+ forEach(reversedInterceptors, function(interceptor) {
+ if (interceptor.request || interceptor.requestError) {
+ chain.unshift(interceptor.request, interceptor.requestError);
+ }
+ if (interceptor.response || interceptor.responseError) {
+ chain.push(interceptor.response, interceptor.responseError);
+ }
+ });
+
+ while (chain.length) {
+ var thenFn = chain.shift();
+ var rejectFn = chain.shift();
+
+ promise = promise.then(thenFn, rejectFn);
+ }
+
+ if (useLegacyPromise) {
+ promise.success = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+
+ promise.error = function(fn) {
+ assertArgFn(fn, 'fn');
+
+ promise.then(null, function(response) {
+ fn(response.data, response.status, response.headers, config);
+ });
+ return promise;
+ };
+ } else {
+ promise.success = $httpMinErrLegacyFn('success');
+ promise.error = $httpMinErrLegacyFn('error');
+ }
+
+ return promise;
+
+ function transformResponse(response) {
+ // make a copy since the response must be cacheable
+ var resp = extend({}, response);
+ resp.data = transformData(response.data, response.headers, response.status,
+ config.transformResponse);
+ return (isSuccess(response.status))
+ ? resp
+ : $q.reject(resp);
+ }
+
+ function executeHeaderFns(headers, config) {
+ var headerContent, processedHeaders = {};
+
+ forEach(headers, function(headerFn, header) {
+ if (isFunction(headerFn)) {
+ headerContent = headerFn(config);
+ if (headerContent != null) {
+ processedHeaders[header] = headerContent;
+ }
+ } else {
+ processedHeaders[header] = headerFn;
+ }
+ });
+
+ return processedHeaders;
+ }
+
+ function mergeHeaders(config) {
+ var defHeaders = defaults.headers,
+ reqHeaders = extend({}, config.headers),
+ defHeaderName, lowercaseDefHeaderName, reqHeaderName;
+
+ defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
+
+ // using for-in instead of forEach to avoid unecessary iteration after header has been found
+ defaultHeadersIteration:
+ for (defHeaderName in defHeaders) {
+ lowercaseDefHeaderName = lowercase(defHeaderName);
+
+ for (reqHeaderName in reqHeaders) {
+ if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
+ continue defaultHeadersIteration;
+ }
+ }
+
+ reqHeaders[defHeaderName] = defHeaders[defHeaderName];
+ }
+
+ // execute if header value is a function for merged headers
+ return executeHeaderFns(reqHeaders, shallowCopy(config));
+ }
+ }
+
+ $http.pendingRequests = [];
+
+ /**
+ * @ngdoc method
+ * @name $http#get
+ *
+ * @description
+ * Shortcut method to perform `GET` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#delete
+ *
+ * @description
+ * Shortcut method to perform `DELETE` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#head
+ *
+ * @description
+ * Shortcut method to perform `HEAD` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#jsonp
+ *
+ * @description
+ * Shortcut method to perform `JSONP` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request.
+ * The name of the callback should be the string `JSON_CALLBACK`.
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethods('get', 'delete', 'head', 'jsonp');
+
+ /**
+ * @ngdoc method
+ * @name $http#post
+ *
+ * @description
+ * Shortcut method to perform `POST` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#put
+ *
+ * @description
+ * Shortcut method to perform `PUT` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+
+ /**
+ * @ngdoc method
+ * @name $http#patch
+ *
+ * @description
+ * Shortcut method to perform `PATCH` request.
+ *
+ * @param {string} url Relative or absolute URL specifying the destination of the request
+ * @param {*} data Request content
+ * @param {Object=} config Optional configuration object
+ * @returns {HttpPromise} Future object
+ */
+ createShortMethodsWithData('post', 'put', 'patch');
+
+ /**
+ * @ngdoc property
+ * @name $http#defaults
+ *
+ * @description
+ * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
+ * default headers, withCredentials as well as request and response transformations.
+ *
+ * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
+ */
+ $http.defaults = defaults;
+
+
+ return $http;
+
+
+ function createShortMethods(names) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, config) {
+ return $http(extend({}, config || {}, {
+ method: name,
+ url: url
+ }));
+ };
+ });
+ }
+
+
+ function createShortMethodsWithData(name) {
+ forEach(arguments, function(name) {
+ $http[name] = function(url, data, config) {
+ return $http(extend({}, config || {}, {
+ method: name,
+ url: url,
+ data: data
+ }));
+ };
+ });
+ }
+
+
+ /**
+ * Makes the request.
+ *
+ * !!! ACCESSES CLOSURE VARS:
+ * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
+ */
+ function sendReq(config, reqData) {
+ var deferred = $q.defer(),
+ promise = deferred.promise,
+ cache,
+ cachedResp,
+ reqHeaders = config.headers,
+ url = buildUrl(config.url, config.paramSerializer(config.params));
+
+ $http.pendingRequests.push(config);
+ promise.then(removePendingReq, removePendingReq);
+
+
+ if ((config.cache || defaults.cache) && config.cache !== false &&
+ (config.method === 'GET' || config.method === 'JSONP')) {
+ cache = isObject(config.cache) ? config.cache
+ : isObject(defaults.cache) ? defaults.cache
+ : defaultCache;
+ }
+
+ if (cache) {
+ cachedResp = cache.get(url);
+ if (isDefined(cachedResp)) {
+ if (isPromiseLike(cachedResp)) {
+ // cached request has already been sent, but there is no response yet
+ cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
+ } else {
+ // serving from cache
+ if (isArray(cachedResp)) {
+ resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
+ } else {
+ resolvePromise(cachedResp, 200, {}, 'OK');
+ }
+ }
+ } else {
+ // put the promise for the non-transformed response into cache as a placeholder
+ cache.put(url, promise);
+ }
+ }
+
+
+ // if we won't have the response in cache, set the xsrf headers and
+ // send the request to the backend
+ if (isUndefined(cachedResp)) {
+ var xsrfValue = urlIsSameOrigin(config.url)
+ ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
+ : undefined;
+ if (xsrfValue) {
+ reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
+ }
+
+ $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
+ config.withCredentials, config.responseType);
+ }
+
+ return promise;
+
+
+ /**
+ * Callback registered to $httpBackend():
+ * - caches the response if desired
+ * - resolves the raw $http promise
+ * - calls $apply
+ */
+ function done(status, response, headersString, statusText) {
+ if (cache) {
+ if (isSuccess(status)) {
+ cache.put(url, [status, response, parseHeaders(headersString), statusText]);
+ } else {
+ // remove promise from the cache
+ cache.remove(url);
+ }
+ }
+
+ function resolveHttpPromise() {
+ resolvePromise(response, status, headersString, statusText);
+ }
+
+ if (useApplyAsync) {
+ $rootScope.$applyAsync(resolveHttpPromise);
+ } else {
+ resolveHttpPromise();
+ if (!$rootScope.$$phase) $rootScope.$apply();
+ }
+ }
+
+
+ /**
+ * Resolves the raw $http promise.
+ */
+ function resolvePromise(response, status, headers, statusText) {
+ //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
+ status = status >= -1 ? status : 0;
+
+ (isSuccess(status) ? deferred.resolve : deferred.reject)({
+ data: response,
+ status: status,
+ headers: headersGetter(headers),
+ config: config,
+ statusText: statusText
+ });
+ }
+
+ function resolvePromiseWithResult(result) {
+ resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
+ }
+
+ function removePendingReq() {
+ var idx = $http.pendingRequests.indexOf(config);
+ if (idx !== -1) $http.pendingRequests.splice(idx, 1);
+ }
+ }
+
+
+ function buildUrl(url, serializedParams) {
+ if (serializedParams.length > 0) {
+ url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams;
+ }
+ return url;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $xhrFactory
+ *
+ * @description
+ * Factory function used to create XMLHttpRequest objects.
+ *
+ * Replace or decorate this service to create your own custom XMLHttpRequest objects.
+ *
+ * ```
+ * angular.module('myApp', [])
+ * .factory('$xhrFactory', function() {
+ * return function createXhr(method, url) {
+ * return new window.XMLHttpRequest({mozSystem: true});
+ * };
+ * });
+ * ```
+ *
+ * @param {string} method HTTP method of the request (GET, POST, PUT, ..)
+ * @param {string} url URL of the request.
+ */
+function $xhrFactoryProvider() {
+ this.$get = function() {
+ return function createXhr() {
+ return new window.XMLHttpRequest();
+ };
+ };
+}
+
+/**
+ * @ngdoc service
+ * @name $httpBackend
+ * @requires $window
+ * @requires $document
+ * @requires $xhrFactory
+ *
+ * @description
+ * HTTP backend used by the {@link ng.$http service} that delegates to
+ * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
+ *
+ * You should never need to use this service directly, instead use the higher-level abstractions:
+ * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
+ *
+ * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
+ * $httpBackend} which can be trained with responses.
+ */
+function $HttpBackendProvider() {
+ this.$get = ['$browser', '$window', '$document', '$xhrFactory', function($browser, $window, $document, $xhrFactory) {
+ return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]);
+ }];
+}
+
+function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
+ // TODO(vojta): fix the signature
+ return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
+ $browser.$$incOutstandingRequestCount();
+ url = url || $browser.url();
+
+ if (lowercase(method) == 'jsonp') {
+ var callbackId = '_' + (callbacks.counter++).toString(36);
+ callbacks[callbackId] = function(data) {
+ callbacks[callbackId].data = data;
+ callbacks[callbackId].called = true;
+ };
+
+ var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
+ callbackId, function(status, text) {
+ completeRequest(callback, status, callbacks[callbackId].data, "", text);
+ callbacks[callbackId] = noop;
+ });
+ } else {
+
+ var xhr = createXhr(method, url);
+
+ xhr.open(method, url, true);
+ forEach(headers, function(value, key) {
+ if (isDefined(value)) {
+ xhr.setRequestHeader(key, value);
+ }
+ });
+
+ xhr.onload = function requestLoaded() {
+ var statusText = xhr.statusText || '';
+
+ // responseText is the old-school way of retrieving response (supported by IE9)
+ // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
+ var response = ('response' in xhr) ? xhr.response : xhr.responseText;
+
+ // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
+ var status = xhr.status === 1223 ? 204 : xhr.status;
+
+ // fix status code when it is 0 (0 status is undocumented).
+ // Occurs when accessing file resources or on Android 4.1 stock browser
+ // while retrieving files from application cache.
+ if (status === 0) {
+ status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
+ }
+
+ completeRequest(callback,
+ status,
+ response,
+ xhr.getAllResponseHeaders(),
+ statusText);
+ };
+
+ var requestError = function() {
+ // The response is always empty
+ // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
+ completeRequest(callback, -1, null, null, '');
+ };
+
+ xhr.onerror = requestError;
+ xhr.onabort = requestError;
+
+ if (withCredentials) {
+ xhr.withCredentials = true;
+ }
+
+ if (responseType) {
+ try {
+ xhr.responseType = responseType;
+ } catch (e) {
+ // WebKit added support for the json responseType value on 09/03/2013
+ // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
+ // known to throw when setting the value "json" as the response type. Other older
+ // browsers implementing the responseType
+ //
+ // The json response type can be ignored if not supported, because JSON payloads are
+ // parsed on the client-side regardless.
+ if (responseType !== 'json') {
+ throw e;
+ }
+ }
+ }
+
+ xhr.send(isUndefined(post) ? null : post);
+ }
+
+ if (timeout > 0) {
+ var timeoutId = $browserDefer(timeoutRequest, timeout);
+ } else if (isPromiseLike(timeout)) {
+ timeout.then(timeoutRequest);
+ }
+
+
+ function timeoutRequest() {
+ jsonpDone && jsonpDone();
+ xhr && xhr.abort();
+ }
+
+ function completeRequest(callback, status, response, headersString, statusText) {
+ // cancel timeout and subsequent timeout promise resolution
+ if (isDefined(timeoutId)) {
+ $browserDefer.cancel(timeoutId);
+ }
+ jsonpDone = xhr = null;
+
+ callback(status, response, headersString, statusText);
+ $browser.$$completeOutstandingRequest(noop);
+ }
+ };
+
+ function jsonpReq(url, callbackId, done) {
+ // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
+ // - fetches local scripts via XHR and evals them
+ // - adds and immediately removes script elements from the document
+ var script = rawDocument.createElement('script'), callback = null;
+ script.type = "text/javascript";
+ script.src = url;
+ script.async = true;
+
+ callback = function(event) {
+ removeEventListenerFn(script, "load", callback);
+ removeEventListenerFn(script, "error", callback);
+ rawDocument.body.removeChild(script);
+ script = null;
+ var status = -1;
+ var text = "unknown";
+
+ if (event) {
+ if (event.type === "load" && !callbacks[callbackId].called) {
+ event = { type: "error" };
+ }
+ text = event.type;
+ status = event.type === "error" ? 404 : 200;
+ }
+
+ if (done) {
+ done(status, text);
+ }
+ };
+
+ addEventListenerFn(script, "load", callback);
+ addEventListenerFn(script, "error", callback);
+ rawDocument.body.appendChild(script);
+ return callback;
+ }
+}
+
+var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');
+$interpolateMinErr.throwNoconcat = function(text) {
+ throw $interpolateMinErr('noconcat',
+ "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
+ "interpolations that concatenate multiple expressions when a trusted value is " +
+ "required. See http://docs.angularjs.org/api/ng.$sce", text);
+};
+
+$interpolateMinErr.interr = function(text, err) {
+ return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
+};
+
+/**
+ * @ngdoc provider
+ * @name $interpolateProvider
+ *
+ * @description
+ *
+ * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
+ *
+ * @example
+<example module="customInterpolationApp">
+<file name="index.html">
+<script>
+ var customInterpolationApp = angular.module('customInterpolationApp', []);
+
+ customInterpolationApp.config(function($interpolateProvider) {
+ $interpolateProvider.startSymbol('//');
+ $interpolateProvider.endSymbol('//');
+ });
+
+
+ customInterpolationApp.controller('DemoController', function() {
+ this.label = "This binding is brought you by // interpolation symbols.";
+ });
+</script>
+<div ng-app="App" ng-controller="DemoController as demo">
+ //demo.label//
+</div>
+</file>
+<file name="protractor.js" type="protractor">
+ it('should interpolate binding with custom symbols', function() {
+ expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
+ });
+</file>
+</example>
+ */
+function $InterpolateProvider() {
+ var startSymbol = '{{';
+ var endSymbol = '}}';
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#startSymbol
+ * @description
+ * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * @param {string=} value new value to set the starting symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.startSymbol = function(value) {
+ if (value) {
+ startSymbol = value;
+ return this;
+ } else {
+ return startSymbol;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $interpolateProvider#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * @param {string=} value new value to set the ending symbol to.
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
+ */
+ this.endSymbol = function(value) {
+ if (value) {
+ endSymbol = value;
+ return this;
+ } else {
+ return endSymbol;
+ }
+ };
+
+
+ this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
+ var startSymbolLength = startSymbol.length,
+ endSymbolLength = endSymbol.length,
+ escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
+ escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
+
+ function escape(ch) {
+ return '\\\\\\' + ch;
+ }
+
+ function unescapeText(text) {
+ return text.replace(escapedStartRegexp, startSymbol).
+ replace(escapedEndRegexp, endSymbol);
+ }
+
+ function stringify(value) {
+ if (value == null) { // null || undefined
+ return '';
+ }
+ switch (typeof value) {
+ case 'string':
+ break;
+ case 'number':
+ value = '' + value;
+ break;
+ default:
+ value = toJson(value);
+ }
+
+ return value;
+ }
+
+ /**
+ * @ngdoc service
+ * @name $interpolate
+ * @kind function
+ *
+ * @requires $parse
+ * @requires $sce
+ *
+ * @description
+ *
+ * Compiles a string with markup into an interpolation function. This service is used by the
+ * HTML {@link ng.$compile $compile} service for data binding. See
+ * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
+ * interpolation markup.
+ *
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var exp = $interpolate('Hello {{name | uppercase}}!');
+ * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
+ * ```
+ *
+ * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
+ * `true`, the interpolation function will return `undefined` unless all embedded expressions
+ * evaluate to a value other than `undefined`.
+ *
+ * ```js
+ * var $interpolate = ...; // injected
+ * var context = {greeting: 'Hello', name: undefined };
+ *
+ * // default "forgiving" mode
+ * var exp = $interpolate('{{greeting}} {{name}}!');
+ * expect(exp(context)).toEqual('Hello !');
+ *
+ * // "allOrNothing" mode
+ * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
+ * expect(exp(context)).toBeUndefined();
+ * context.name = 'Angular';
+ * expect(exp(context)).toEqual('Hello Angular!');
+ * ```
+ *
+ * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
+ *
+ * ####Escaped Interpolation
+ * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
+ * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
+ * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
+ * or binding.
+ *
+ * This enables web-servers to prevent script injection attacks and defacing attacks, to some
+ * degree, while also enabling code examples to work without relying on the
+ * {@link ng.directive:ngNonBindable ngNonBindable} directive.
+ *
+ * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
+ * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
+ * interpolation start/end markers with their escaped counterparts.**
+ *
+ * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
+ * output when the $interpolate service processes the text. So, for HTML elements interpolated
+ * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
+ * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
+ * this is typically useful only when user-data is used in rendering a template from the server, or
+ * when otherwise untrusted data is used by a directive.
+ *
+ * <example>
+ * <file name="index.html">
+ * <div ng-init="username='A user'">
+ * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
+ * </p>
+ * <p><strong>{{username}}</strong> attempts to inject code which will deface the
+ * application, but fails to accomplish their task, because the server has correctly
+ * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
+ * characters.</p>
+ * <p>Instead, the result of the attempted script injection is visible, and can be removed
+ * from the database by an administrator.</p>
+ * </div>
+ * </file>
+ * </example>
+ *
+ * @param {string} text The text with markup to interpolate.
+ * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
+ * embedded expression in order to return an interpolation function. Strings with no
+ * embedded expression will return null for the interpolation function.
+ * @param {string=} trustedContext when provided, the returned function passes the interpolated
+ * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
+ * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
+ * provides Strict Contextual Escaping for details.
+ * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
+ * unless all embedded expressions evaluate to a value other than `undefined`.
+ * @returns {function(context)} an interpolation function which is used to compute the
+ * interpolated string. The function has these parameters:
+ *
+ * - `context`: evaluation context for all expressions embedded in the interpolated text
+ */
+ function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
+ allOrNothing = !!allOrNothing;
+ var startIndex,
+ endIndex,
+ index = 0,
+ expressions = [],
+ parseFns = [],
+ textLength = text.length,
+ exp,
+ concat = [],
+ expressionPositions = [];
+
+ while (index < textLength) {
+ if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
+ ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
+ if (index !== startIndex) {
+ concat.push(unescapeText(text.substring(index, startIndex)));
+ }
+ exp = text.substring(startIndex + startSymbolLength, endIndex);
+ expressions.push(exp);
+ parseFns.push($parse(exp, parseStringifyInterceptor));
+ index = endIndex + endSymbolLength;
+ expressionPositions.push(concat.length);
+ concat.push('');
+ } else {
+ // we did not find an interpolation, so we have to add the remainder to the separators array
+ if (index !== textLength) {
+ concat.push(unescapeText(text.substring(index)));
+ }
+ break;
+ }
+ }
+
+ // Concatenating expressions makes it hard to reason about whether some combination of
+ // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
+ // single expression be used for iframe[src], object[src], etc., we ensure that the value
+ // that's used is assigned or constructed by some JS code somewhere that is more testable or
+ // make it obvious that you bound the value to some user controlled value. This helps reduce
+ // the load when auditing for XSS issues.
+ if (trustedContext && concat.length > 1) {
+ $interpolateMinErr.throwNoconcat(text);
+ }
+
+ if (!mustHaveExpression || expressions.length) {
+ var compute = function(values) {
+ for (var i = 0, ii = expressions.length; i < ii; i++) {
+ if (allOrNothing && isUndefined(values[i])) return;
+ concat[expressionPositions[i]] = values[i];
+ }
+ return concat.join('');
+ };
+
+ var getValue = function(value) {
+ return trustedContext ?
+ $sce.getTrusted(trustedContext, value) :
+ $sce.valueOf(value);
+ };
+
+ return extend(function interpolationFn(context) {
+ var i = 0;
+ var ii = expressions.length;
+ var values = new Array(ii);
+
+ try {
+ for (; i < ii; i++) {
+ values[i] = parseFns[i](context);
+ }
+
+ return compute(values);
+ } catch (err) {
+ $exceptionHandler($interpolateMinErr.interr(text, err));
+ }
+
+ }, {
+ // all of these properties are undocumented for now
+ exp: text, //just for compatibility with regular watchers created via $watch
+ expressions: expressions,
+ $$watchDelegate: function(scope, listener) {
+ var lastValue;
+ return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
+ var currValue = compute(values);
+ if (isFunction(listener)) {
+ listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
+ }
+ lastValue = currValue;
+ });
+ }
+ });
+ }
+
+ function parseStringifyInterceptor(value) {
+ try {
+ value = getValue(value);
+ return allOrNothing && !isDefined(value) ? value : stringify(value);
+ } catch (err) {
+ $exceptionHandler($interpolateMinErr.interr(text, err));
+ }
+ }
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#startSymbol
+ * @description
+ * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
+ *
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} start symbol.
+ */
+ $interpolate.startSymbol = function() {
+ return startSymbol;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name $interpolate#endSymbol
+ * @description
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
+ *
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
+ * the symbol.
+ *
+ * @returns {string} end symbol.
+ */
+ $interpolate.endSymbol = function() {
+ return endSymbol;
+ };
+
+ return $interpolate;
+ }];
+}
+
+function $IntervalProvider() {
+ this.$get = ['$rootScope', '$window', '$q', '$$q',
+ function($rootScope, $window, $q, $$q) {
+ var intervals = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $interval
+ *
+ * @description
+ * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
+ * milliseconds.
+ *
+ * The return value of registering an interval function is a promise. This promise will be
+ * notified upon each tick of the interval, and will be resolved after `count` iterations, or
+ * run indefinitely if `count` is not defined. The value of the notification will be the
+ * number of iterations that have run.
+ * To cancel an interval, call `$interval.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
+ * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
+ * time.
+ *
+ * <div class="alert alert-warning">
+ * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
+ * with them. In particular they are not automatically destroyed when a controller's scope or a
+ * directive's element are destroyed.
+ * You should take this into consideration and make sure to always cancel the interval at the
+ * appropriate moment. See the example below for more details on how and when to do this.
+ * </div>
+ *
+ * @param {function()} fn A function that should be called repeatedly.
+ * @param {number} delay Number of milliseconds between each function call.
+ * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
+ * indefinitely.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @param {...*=} Pass additional parameters to the executed function.
+ * @returns {promise} A promise which will be notified on each iteration.
+ *
+ * @example
+ * <example module="intervalExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('intervalExample', [])
+ * .controller('ExampleController', ['$scope', '$interval',
+ * function($scope, $interval) {
+ * $scope.format = 'M/d/yy h:mm:ss a';
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ *
+ * var stop;
+ * $scope.fight = function() {
+ * // Don't start a new fight if we are already fighting
+ * if ( angular.isDefined(stop) ) return;
+ *
+ * stop = $interval(function() {
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
+ * $scope.blood_1 = $scope.blood_1 - 3;
+ * $scope.blood_2 = $scope.blood_2 - 4;
+ * } else {
+ * $scope.stopFight();
+ * }
+ * }, 100);
+ * };
+ *
+ * $scope.stopFight = function() {
+ * if (angular.isDefined(stop)) {
+ * $interval.cancel(stop);
+ * stop = undefined;
+ * }
+ * };
+ *
+ * $scope.resetFight = function() {
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
+ * };
+ *
+ * $scope.$on('$destroy', function() {
+ * // Make sure that the interval is destroyed too
+ * $scope.stopFight();
+ * });
+ * }])
+ * // Register the 'myCurrentTime' directive factory method.
+ * // We inject $interval and dateFilter service since the factory method is DI.
+ * .directive('myCurrentTime', ['$interval', 'dateFilter',
+ * function($interval, dateFilter) {
+ * // return the directive link function. (compile function not needed)
+ * return function(scope, element, attrs) {
+ * var format, // date format
+ * stopTime; // so that we can cancel the time updates
+ *
+ * // used to update the UI
+ * function updateTime() {
+ * element.text(dateFilter(new Date(), format));
+ * }
+ *
+ * // watch the expression, and update the UI on change.
+ * scope.$watch(attrs.myCurrentTime, function(value) {
+ * format = value;
+ * updateTime();
+ * });
+ *
+ * stopTime = $interval(updateTime, 1000);
+ *
+ * // listen on DOM destroy (removal) event, and cancel the next UI update
+ * // to prevent updating time after the DOM element was removed.
+ * element.on('$destroy', function() {
+ * $interval.cancel(stopTime);
+ * });
+ * }
+ * }]);
+ * </script>
+ *
+ * <div>
+ * <div ng-controller="ExampleController">
+ * <label>Date format: <input ng-model="format"></label> <hr/>
+ * Current time is: <span my-current-time="format"></span>
+ * <hr/>
+ * Blood 1 : <font color='red'>{{blood_1}}</font>
+ * Blood 2 : <font color='red'>{{blood_2}}</font>
+ * <button type="button" data-ng-click="fight()">Fight</button>
+ * <button type="button" data-ng-click="stopFight()">StopFight</button>
+ * <button type="button" data-ng-click="resetFight()">resetFight</button>
+ * </div>
+ * </div>
+ *
+ * </file>
+ * </example>
+ */
+ function interval(fn, delay, count, invokeApply) {
+ var hasParams = arguments.length > 4,
+ args = hasParams ? sliceArgs(arguments, 4) : [],
+ setInterval = $window.setInterval,
+ clearInterval = $window.clearInterval,
+ iteration = 0,
+ skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise;
+
+ count = isDefined(count) ? count : 0;
+
+ promise.then(null, null, (!hasParams) ? fn : function() {
+ fn.apply(null, args);
+ });
+
+ promise.$$intervalId = setInterval(function tick() {
+ deferred.notify(iteration++);
+
+ if (count > 0 && iteration >= count) {
+ deferred.resolve(iteration);
+ clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+
+ }, delay);
+
+ intervals[promise.$$intervalId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $interval#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`.
+ *
+ * @param {Promise=} promise returned by the `$interval` function.
+ * @returns {boolean} Returns `true` if the task was successfully canceled.
+ */
+ interval.cancel = function(promise) {
+ if (promise && promise.$$intervalId in intervals) {
+ intervals[promise.$$intervalId].reject('canceled');
+ $window.clearInterval(promise.$$intervalId);
+ delete intervals[promise.$$intervalId];
+ return true;
+ }
+ return false;
+ };
+
+ return interval;
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $locale
+ *
+ * @description
+ * $locale service provides localization rules for various Angular components. As of right now the
+ * only public api is:
+ *
+ * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
+ */
+
+var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
+ DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
+var $locationMinErr = minErr('$location');
+
+
+/**
+ * Encode path using encodeUriSegment, ignoring forward slashes
+ *
+ * @param {string} path Path to encode
+ * @returns {string}
+ */
+function encodePath(path) {
+ var segments = path.split('/'),
+ i = segments.length;
+
+ while (i--) {
+ segments[i] = encodeUriSegment(segments[i]);
+ }
+
+ return segments.join('/');
+}
+
+function parseAbsoluteUrl(absoluteUrl, locationObj) {
+ var parsedUrl = urlResolve(absoluteUrl);
+
+ locationObj.$$protocol = parsedUrl.protocol;
+ locationObj.$$host = parsedUrl.hostname;
+ locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
+}
+
+
+function parseAppUrl(relativeUrl, locationObj) {
+ var prefixed = (relativeUrl.charAt(0) !== '/');
+ if (prefixed) {
+ relativeUrl = '/' + relativeUrl;
+ }
+ var match = urlResolve(relativeUrl);
+ locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
+ match.pathname.substring(1) : match.pathname);
+ locationObj.$$search = parseKeyValue(match.search);
+ locationObj.$$hash = decodeURIComponent(match.hash);
+
+ // make sure path starts with '/';
+ if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
+ locationObj.$$path = '/' + locationObj.$$path;
+ }
+}
+
+
+/**
+ *
+ * @param {string} begin
+ * @param {string} whole
+ * @returns {string} returns text from whole after begin or undefined if it does not begin with
+ * expected string.
+ */
+function beginsWith(begin, whole) {
+ if (whole.indexOf(begin) === 0) {
+ return whole.substr(begin.length);
+ }
+}
+
+
+function stripHash(url) {
+ var index = url.indexOf('#');
+ return index == -1 ? url : url.substr(0, index);
+}
+
+function trimEmptyHash(url) {
+ return url.replace(/(#.+)|#$/, '$1');
+}
+
+
+function stripFile(url) {
+ return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
+}
+
+/* return the server only (scheme://host:port) */
+function serverBase(url) {
+ return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
+}
+
+
+/**
+ * LocationHtml5Url represents an url
+ * This object is exposed as $location service when HTML5 mode is enabled and supported
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} basePrefix url path prefix
+ */
+function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
+ this.$$html5 = true;
+ basePrefix = basePrefix || '';
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given html5 (regular) url string into properties
+ * @param {string} url HTML5 url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var pathUrl = beginsWith(appBaseNoFile, url);
+ if (!isString(pathUrl)) {
+ throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
+ appBaseNoFile);
+ }
+
+ parseAppUrl(pathUrl, this);
+
+ if (!this.$$path) {
+ this.$$path = '/';
+ }
+
+ this.$$compose();
+ };
+
+ /**
+ * Compose url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+ var appUrl, prevAppUrl;
+ var rewrittenUrl;
+
+ if (isDefined(appUrl = beginsWith(appBase, url))) {
+ prevAppUrl = appUrl;
+ if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
+ rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
+ } else {
+ rewrittenUrl = appBase + prevAppUrl;
+ }
+ } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
+ rewrittenUrl = appBaseNoFile + appUrl;
+ } else if (appBaseNoFile == url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when developer doesn't opt into html5 mode.
+ * It also serves as the base class for html5 mode fallback on legacy browsers.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
+
+ parseAbsoluteUrl(appBase, this);
+
+
+ /**
+ * Parse given hashbang url into properties
+ * @param {string} url Hashbang url
+ * @private
+ */
+ this.$$parse = function(url) {
+ var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
+ var withoutHashUrl;
+
+ if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
+
+ // The rest of the url starts with a hash so we have
+ // got either a hashbang path or a plain hash fragment
+ withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
+ if (isUndefined(withoutHashUrl)) {
+ // There was no hashbang prefix so we just have a hash fragment
+ withoutHashUrl = withoutBaseUrl;
+ }
+
+ } else {
+ // There was no hashbang path nor hash fragment:
+ // If we are in HTML5 mode we use what is left as the path;
+ // Otherwise we ignore what is left
+ if (this.$$html5) {
+ withoutHashUrl = withoutBaseUrl;
+ } else {
+ withoutHashUrl = '';
+ if (isUndefined(withoutBaseUrl)) {
+ appBase = url;
+ this.replace();
+ }
+ }
+ }
+
+ parseAppUrl(withoutHashUrl, this);
+
+ this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
+
+ this.$$compose();
+
+ /*
+ * In Windows, on an anchor node on documents loaded from
+ * the filesystem, the browser will return a pathname
+ * prefixed with the drive name ('/C:/path') when a
+ * pathname without a drive is set:
+ * * a.setAttribute('href', '/foo')
+ * * a.pathname === '/C:/foo' //true
+ *
+ * Inside of Angular, we're always using pathnames that
+ * do not include drive names for routing.
+ */
+ function removeWindowsDriveName(path, url, base) {
+ /*
+ Matches paths for file protocol on windows,
+ such as /C:/foo/bar, and captures only /foo/bar.
+ */
+ var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
+
+ var firstPathSegmentMatch;
+
+ //Get the relative path from the input URL.
+ if (url.indexOf(base) === 0) {
+ url = url.replace(base, '');
+ }
+
+ // The input URL intentionally contains a first path segment that ends with a colon.
+ if (windowsFilePathExp.exec(url)) {
+ return path;
+ }
+
+ firstPathSegmentMatch = windowsFilePathExp.exec(path);
+ return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
+ }
+ };
+
+ /**
+ * Compose hashbang url and update `absUrl` property
+ * @private
+ */
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
+ };
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (stripHash(appBase) == stripHash(url)) {
+ this.$$parse(url);
+ return true;
+ }
+ return false;
+ };
+}
+
+
+/**
+ * LocationHashbangUrl represents url
+ * This object is exposed as $location service when html5 history api is enabled but the browser
+ * does not support it.
+ *
+ * @constructor
+ * @param {string} appBase application base URL
+ * @param {string} appBaseNoFile application base URL stripped of any filename
+ * @param {string} hashPrefix hashbang prefix
+ */
+function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
+ this.$$html5 = true;
+ LocationHashbangUrl.apply(this, arguments);
+
+ this.$$parseLinkUrl = function(url, relHref) {
+ if (relHref && relHref[0] === '#') {
+ // special case for links to hash fragments:
+ // keep the old url and only replace the hash fragment
+ this.hash(relHref.slice(1));
+ return true;
+ }
+
+ var rewrittenUrl;
+ var appUrl;
+
+ if (appBase == stripHash(url)) {
+ rewrittenUrl = url;
+ } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
+ rewrittenUrl = appBase + hashPrefix + appUrl;
+ } else if (appBaseNoFile === url + '/') {
+ rewrittenUrl = appBaseNoFile;
+ }
+ if (rewrittenUrl) {
+ this.$$parse(rewrittenUrl);
+ }
+ return !!rewrittenUrl;
+ };
+
+ this.$$compose = function() {
+ var search = toKeyValue(this.$$search),
+ hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
+
+ this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
+ // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
+ this.$$absUrl = appBase + hashPrefix + this.$$url;
+ };
+
+}
+
+
+var locationPrototype = {
+
+ /**
+ * Are we in html5 mode?
+ * @private
+ */
+ $$html5: false,
+
+ /**
+ * Has any change been replacing?
+ * @private
+ */
+ $$replace: false,
+
+ /**
+ * @ngdoc method
+ * @name $location#absUrl
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return full url representation with all segments encoded according to rules specified in
+ * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var absUrl = $location.absUrl();
+ * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @return {string} full url
+ */
+ absUrl: locationGetter('$$absUrl'),
+
+ /**
+ * @ngdoc method
+ * @name $location#url
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
+ *
+ * Change path, search and hash, when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var url = $location.url();
+ * // => "/some/path?foo=bar&baz=xoxo"
+ * ```
+ *
+ * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
+ * @return {string} url
+ */
+ url: function(url) {
+ if (isUndefined(url)) {
+ return this.$$url;
+ }
+
+ var match = PATH_MATCH.exec(url);
+ if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
+ if (match[2] || match[1] || url === '') this.search(match[3] || '');
+ this.hash(match[5] || '');
+
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#protocol
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return protocol of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var protocol = $location.protocol();
+ * // => "http"
+ * ```
+ *
+ * @return {string} protocol of current url
+ */
+ protocol: locationGetter('$$protocol'),
+
+ /**
+ * @ngdoc method
+ * @name $location#host
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return host of current url.
+ *
+ * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var host = $location.host();
+ * // => "example.com"
+ *
+ * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
+ * host = $location.host();
+ * // => "example.com"
+ * host = location.host;
+ * // => "example.com:8080"
+ * ```
+ *
+ * @return {string} host of current url.
+ */
+ host: locationGetter('$$host'),
+
+ /**
+ * @ngdoc method
+ * @name $location#port
+ *
+ * @description
+ * This method is getter only.
+ *
+ * Return port of current url.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var port = $location.port();
+ * // => 80
+ * ```
+ *
+ * @return {Number} port
+ */
+ port: locationGetter('$$port'),
+
+ /**
+ * @ngdoc method
+ * @name $location#path
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return path of current url when called without any parameter.
+ *
+ * Change path when called with parameter and return `$location`.
+ *
+ * Note: Path should always begin with forward slash (/), this method will add the forward slash
+ * if it is missing.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var path = $location.path();
+ * // => "/some/path"
+ * ```
+ *
+ * @param {(string|number)=} path New path
+ * @return {string} path
+ */
+ path: locationGetterSetter('$$path', function(path) {
+ path = path !== null ? path.toString() : '';
+ return path.charAt(0) == '/' ? path : '/' + path;
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#search
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return search part (as object) of current url when called without any parameter.
+ *
+ * Change search part when called with parameter and return `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
+ * var searchObject = $location.search();
+ * // => {foo: 'bar', baz: 'xoxo'}
+ *
+ * // set foo to 'yipee'
+ * $location.search('foo', 'yipee');
+ * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
+ * ```
+ *
+ * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
+ * hash object.
+ *
+ * When called with a single argument the method acts as a setter, setting the `search` component
+ * of `$location` to the specified value.
+ *
+ * If the argument is a hash object containing an array of values, these values will be encoded
+ * as duplicate search parameters in the url.
+ *
+ * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
+ * will override only a single search property.
+ *
+ * If `paramValue` is an array, it will override the property of the `search` component of
+ * `$location` specified via the first argument.
+ *
+ * If `paramValue` is `null`, the property specified via the first argument will be deleted.
+ *
+ * If `paramValue` is `true`, the property specified via the first argument will be added with no
+ * value nor trailing equal sign.
+ *
+ * @return {Object} If called with no arguments returns the parsed `search` object. If called with
+ * one or more arguments returns `$location` object itself.
+ */
+ search: function(search, paramValue) {
+ switch (arguments.length) {
+ case 0:
+ return this.$$search;
+ case 1:
+ if (isString(search) || isNumber(search)) {
+ search = search.toString();
+ this.$$search = parseKeyValue(search);
+ } else if (isObject(search)) {
+ search = copy(search, {});
+ // remove object undefined or null properties
+ forEach(search, function(value, key) {
+ if (value == null) delete search[key];
+ });
+
+ this.$$search = search;
+ } else {
+ throw $locationMinErr('isrcharg',
+ 'The first argument of the `$location#search()` call must be a string or an object.');
+ }
+ break;
+ default:
+ if (isUndefined(paramValue) || paramValue === null) {
+ delete this.$$search[search];
+ } else {
+ this.$$search[search] = paramValue;
+ }
+ }
+
+ this.$$compose();
+ return this;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $location#hash
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Returns the hash fragment when called without any parameters.
+ *
+ * Changes the hash fragment when called with a parameter and returns `$location`.
+ *
+ *
+ * ```js
+ * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
+ * var hash = $location.hash();
+ * // => "hashValue"
+ * ```
+ *
+ * @param {(string|number)=} hash New hash fragment
+ * @return {string} hash
+ */
+ hash: locationGetterSetter('$$hash', function(hash) {
+ return hash !== null ? hash.toString() : '';
+ }),
+
+ /**
+ * @ngdoc method
+ * @name $location#replace
+ *
+ * @description
+ * If called, all changes to $location during the current `$digest` will replace the current history
+ * record, instead of adding a new one.
+ */
+ replace: function() {
+ this.$$replace = true;
+ return this;
+ }
+};
+
+forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
+ Location.prototype = Object.create(locationPrototype);
+
+ /**
+ * @ngdoc method
+ * @name $location#state
+ *
+ * @description
+ * This method is getter / setter.
+ *
+ * Return the history state object when called without any parameter.
+ *
+ * Change the history state object when called with one parameter and return `$location`.
+ * The state object is later passed to `pushState` or `replaceState`.
+ *
+ * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
+ * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
+ * older browsers (like IE9 or Android < 4.0), don't use this method.
+ *
+ * @param {object=} state State object for pushState or replaceState
+ * @return {object} state
+ */
+ Location.prototype.state = function(state) {
+ if (!arguments.length) {
+ return this.$$state;
+ }
+
+ if (Location !== LocationHtml5Url || !this.$$html5) {
+ throw $locationMinErr('nostate', 'History API state support is available only ' +
+ 'in HTML5 mode and only in browsers supporting HTML5 History API');
+ }
+ // The user might modify `stateObject` after invoking `$location.state(stateObject)`
+ // but we're changing the $$state reference to $browser.state() during the $digest
+ // so the modification window is narrow.
+ this.$$state = isUndefined(state) ? null : state;
+
+ return this;
+ };
+});
+
+
+function locationGetter(property) {
+ return function() {
+ return this[property];
+ };
+}
+
+
+function locationGetterSetter(property, preprocess) {
+ return function(value) {
+ if (isUndefined(value)) {
+ return this[property];
+ }
+
+ this[property] = preprocess(value);
+ this.$$compose();
+
+ return this;
+ };
+}
+
+
+/**
+ * @ngdoc service
+ * @name $location
+ *
+ * @requires $rootElement
+ *
+ * @description
+ * The $location service parses the URL in the browser address bar (based on the
+ * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
+ * available to your application. Changes to the URL in the address bar are reflected into
+ * $location service and changes to $location are reflected into the browser address bar.
+ *
+ * **The $location service:**
+ *
+ * - Exposes the current URL in the browser address bar, so you can
+ * - Watch and observe the URL.
+ * - Change the URL.
+ * - Synchronizes the URL with the browser when the user
+ * - Changes the address bar.
+ * - Clicks the back or forward button (or clicks a History link).
+ * - Clicks on a link.
+ * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
+ *
+ * For more information see {@link guide/$location Developer Guide: Using $location}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $locationProvider
+ * @description
+ * Use the `$locationProvider` to configure how the application deep linking paths are stored.
+ */
+function $LocationProvider() {
+ var hashPrefix = '',
+ html5Mode = {
+ enabled: false,
+ requireBase: true,
+ rewriteLinks: true
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#hashPrefix
+ * @description
+ * @param {string=} prefix Prefix for hash part (containing path and search)
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.hashPrefix = function(prefix) {
+ if (isDefined(prefix)) {
+ hashPrefix = prefix;
+ return this;
+ } else {
+ return hashPrefix;
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $locationProvider#html5Mode
+ * @description
+ * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
+ * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
+ * properties:
+ * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
+ * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
+ * support `pushState`.
+ * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
+ * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
+ * true, and a base tag is not present, an error will be thrown when `$location` is injected.
+ * See the {@link guide/$location $location guide for more information}
+ * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
+ * enables/disables url rewriting for relative links.
+ *
+ * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
+ */
+ this.html5Mode = function(mode) {
+ if (isBoolean(mode)) {
+ html5Mode.enabled = mode;
+ return this;
+ } else if (isObject(mode)) {
+
+ if (isBoolean(mode.enabled)) {
+ html5Mode.enabled = mode.enabled;
+ }
+
+ if (isBoolean(mode.requireBase)) {
+ html5Mode.requireBase = mode.requireBase;
+ }
+
+ if (isBoolean(mode.rewriteLinks)) {
+ html5Mode.rewriteLinks = mode.rewriteLinks;
+ }
+
+ return this;
+ } else {
+ return html5Mode;
+ }
+ };
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeStart
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted before a URL will change.
+ *
+ * This change can be prevented by calling
+ * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
+ * details about event object. Upon successful change
+ * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ /**
+ * @ngdoc event
+ * @name $location#$locationChangeSuccess
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted after a URL was changed.
+ *
+ * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
+ * the browser supports the HTML5 History API.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {string} newUrl New URL
+ * @param {string=} oldUrl URL that was before it was changed.
+ * @param {string=} newState New history state object
+ * @param {string=} oldState History state object that was before it was changed.
+ */
+
+ this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
+ function($rootScope, $browser, $sniffer, $rootElement, $window) {
+ var $location,
+ LocationMode,
+ baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
+ initialUrl = $browser.url(),
+ appBase;
+
+ if (html5Mode.enabled) {
+ if (!baseHref && html5Mode.requireBase) {
+ throw $locationMinErr('nobase',
+ "$location in HTML5 mode requires a <base> tag to be present!");
+ }
+ appBase = serverBase(initialUrl) + (baseHref || '/');
+ LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
+ } else {
+ appBase = stripHash(initialUrl);
+ LocationMode = LocationHashbangUrl;
+ }
+ var appBaseNoFile = stripFile(appBase);
+
+ $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
+ $location.$$parseLinkUrl(initialUrl, initialUrl);
+
+ $location.$$state = $browser.state();
+
+ var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
+
+ function setBrowserUrlWithFallback(url, replace, state) {
+ var oldUrl = $location.url();
+ var oldState = $location.$$state;
+ try {
+ $browser.url(url, replace, state);
+
+ // Make sure $location.state() returns referentially identical (not just deeply equal)
+ // state object; this makes possible quick checking if the state changed in the digest
+ // loop. Checking deep equality would be too expensive.
+ $location.$$state = $browser.state();
+ } catch (e) {
+ // Restore old values if pushState fails
+ $location.url(oldUrl);
+ $location.$$state = oldState;
+
+ throw e;
+ }
+ }
+
+ $rootElement.on('click', function(event) {
+ // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
+ // currently we open nice url link and redirect then
+
+ if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
+
+ var elm = jqLite(event.target);
+
+ // traverse the DOM up to find first A tag
+ while (nodeName_(elm[0]) !== 'a') {
+ // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
+ if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
+ }
+
+ var absHref = elm.prop('href');
+ // get the actual href attribute - see
+ // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
+ var relHref = elm.attr('href') || elm.attr('xlink:href');
+
+ if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
+ // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
+ // an animation.
+ absHref = urlResolve(absHref.animVal).href;
+ }
+
+ // Ignore when url is started with javascript: or mailto:
+ if (IGNORE_URI_REGEXP.test(absHref)) return;
+
+ if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
+ if ($location.$$parseLinkUrl(absHref, relHref)) {
+ // We do a preventDefault for all urls that are part of the angular application,
+ // in html5mode and also without, so that we are able to abort navigation without
+ // getting double entries in the location history.
+ event.preventDefault();
+ // update location manually
+ if ($location.absUrl() != $browser.url()) {
+ $rootScope.$apply();
+ // hack to work around FF6 bug 684208 when scenario runner clicks on links
+ $window.angular['ff-684208-preventDefault'] = true;
+ }
+ }
+ }
+ });
+
+
+ // rewrite hashbang url <> html5 url
+ if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
+ $browser.url($location.absUrl(), true);
+ }
+
+ var initializing = true;
+
+ // update $location when $browser url changes
+ $browser.onUrlChange(function(newUrl, newState) {
+
+ if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
+ // If we are navigating outside of the app then force a reload
+ $window.location.href = newUrl;
+ return;
+ }
+
+ $rootScope.$evalAsync(function() {
+ var oldUrl = $location.absUrl();
+ var oldState = $location.$$state;
+ var defaultPrevented;
+ newUrl = trimEmptyHash(newUrl);
+ $location.$$parse(newUrl);
+ $location.$$state = newState;
+
+ defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ newState, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ setBrowserUrlWithFallback(oldUrl, false, oldState);
+ } else {
+ initializing = false;
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ if (!$rootScope.$$phase) $rootScope.$digest();
+ });
+
+ // update browser
+ $rootScope.$watch(function $locationWatch() {
+ var oldUrl = trimEmptyHash($browser.url());
+ var newUrl = trimEmptyHash($location.absUrl());
+ var oldState = $browser.state();
+ var currentReplace = $location.$$replace;
+ var urlOrStateChanged = oldUrl !== newUrl ||
+ ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
+
+ if (initializing || urlOrStateChanged) {
+ initializing = false;
+
+ $rootScope.$evalAsync(function() {
+ var newUrl = $location.absUrl();
+ var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
+ $location.$$state, oldState).defaultPrevented;
+
+ // if the location was changed by a `$locationChangeStart` handler then stop
+ // processing this location change
+ if ($location.absUrl() !== newUrl) return;
+
+ if (defaultPrevented) {
+ $location.$$parse(oldUrl);
+ $location.$$state = oldState;
+ } else {
+ if (urlOrStateChanged) {
+ setBrowserUrlWithFallback(newUrl, currentReplace,
+ oldState === $location.$$state ? null : $location.$$state);
+ }
+ afterLocationChange(oldUrl, oldState);
+ }
+ });
+ }
+
+ $location.$$replace = false;
+
+ // we don't need to return anything because $evalAsync will make the digest loop dirty when
+ // there is a change
+ });
+
+ return $location;
+
+ function afterLocationChange(oldUrl, oldState) {
+ $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
+ $location.$$state, oldState);
+ }
+}];
+}
+
+/**
+ * @ngdoc service
+ * @name $log
+ * @requires $window
+ *
+ * @description
+ * Simple service for logging. Default implementation safely writes the message
+ * into the browser's console (if present).
+ *
+ * The main purpose of this service is to simplify debugging and troubleshooting.
+ *
+ * The default is to log `debug` messages. You can use
+ * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
+ *
+ * @example
+ <example module="logExample">
+ <file name="script.js">
+ angular.module('logExample', [])
+ .controller('LogController', ['$scope', '$log', function($scope, $log) {
+ $scope.$log = $log;
+ $scope.message = 'Hello World!';
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="LogController">
+ <p>Reload this page with open console, enter text and hit the log button...</p>
+ <label>Message:
+ <input type="text" ng-model="message" /></label>
+ <button ng-click="$log.log(message)">log</button>
+ <button ng-click="$log.warn(message)">warn</button>
+ <button ng-click="$log.info(message)">info</button>
+ <button ng-click="$log.error(message)">error</button>
+ <button ng-click="$log.debug(message)">debug</button>
+ </div>
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc provider
+ * @name $logProvider
+ * @description
+ * Use the `$logProvider` to configure how the application logs messages
+ */
+function $LogProvider() {
+ var debug = true,
+ self = this;
+
+ /**
+ * @ngdoc method
+ * @name $logProvider#debugEnabled
+ * @description
+ * @param {boolean=} flag enable or disable debug level messages
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ */
+ this.debugEnabled = function(flag) {
+ if (isDefined(flag)) {
+ debug = flag;
+ return this;
+ } else {
+ return debug;
+ }
+ };
+
+ this.$get = ['$window', function($window) {
+ return {
+ /**
+ * @ngdoc method
+ * @name $log#log
+ *
+ * @description
+ * Write a log message
+ */
+ log: consoleLog('log'),
+
+ /**
+ * @ngdoc method
+ * @name $log#info
+ *
+ * @description
+ * Write an information message
+ */
+ info: consoleLog('info'),
+
+ /**
+ * @ngdoc method
+ * @name $log#warn
+ *
+ * @description
+ * Write a warning message
+ */
+ warn: consoleLog('warn'),
+
+ /**
+ * @ngdoc method
+ * @name $log#error
+ *
+ * @description
+ * Write an error message
+ */
+ error: consoleLog('error'),
+
+ /**
+ * @ngdoc method
+ * @name $log#debug
+ *
+ * @description
+ * Write a debug message
+ */
+ debug: (function() {
+ var fn = consoleLog('debug');
+
+ return function() {
+ if (debug) {
+ fn.apply(self, arguments);
+ }
+ };
+ }())
+ };
+
+ function formatError(arg) {
+ if (arg instanceof Error) {
+ if (arg.stack) {
+ arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
+ ? 'Error: ' + arg.message + '\n' + arg.stack
+ : arg.stack;
+ } else if (arg.sourceURL) {
+ arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
+ }
+ }
+ return arg;
+ }
+
+ function consoleLog(type) {
+ var console = $window.console || {},
+ logFn = console[type] || console.log || noop,
+ hasApply = false;
+
+ // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
+ // The reason behind this is that console.log has type "object" in IE8...
+ try {
+ hasApply = !!logFn.apply;
+ } catch (e) {}
+
+ if (hasApply) {
+ return function() {
+ var args = [];
+ forEach(arguments, function(arg) {
+ args.push(formatError(arg));
+ });
+ return logFn.apply(console, args);
+ };
+ }
+
+ // we are IE which either doesn't have window.console => this is noop and we do nothing,
+ // or we are IE where console.log doesn't have apply so we log at least first 2 args
+ return function(arg1, arg2) {
+ logFn(arg1, arg2 == null ? '' : arg2);
+ };
+ }
+ }];
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $parseMinErr = minErr('$parse');
+
+// Sandboxing Angular Expressions
+// ------------------------------
+// Angular expressions are generally considered safe because these expressions only have direct
+// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
+// obtaining a reference to native JS functions such as the Function constructor.
+//
+// As an example, consider the following Angular expression:
+//
+// {}.toString.constructor('alert("evil JS code")')
+//
+// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
+// against the expression language, but not to prevent exploits that were enabled by exposing
+// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
+// practice and therefore we are not even trying to protect against interaction with an object
+// explicitly exposed in this way.
+//
+// In general, it is not possible to access a Window object from an angular expression unless a
+// window or some DOM object that has a reference to window is published onto a Scope.
+// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
+// native objects.
+//
+// See https://docs.angularjs.org/guide/security
+
+
+function ensureSafeMemberName(name, fullExpression) {
+ if (name === "__defineGetter__" || name === "__defineSetter__"
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
+ || name === "__proto__") {
+ throw $parseMinErr('isecfld',
+ 'Attempting to access a disallowed field in Angular expressions! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function getStringValue(name, fullExpression) {
+ // From the JavaScript docs:
+ // Property names must be strings. This means that non-string objects cannot be used
+ // as keys in an object. Any non-string object, including a number, is typecasted
+ // into a string via the toString method.
+ //
+ // So, to ensure that we are checking the same `name` that JavaScript would use,
+ // we cast it to a string, if possible.
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
+ // this is, this will handle objects that misbehave.
+ name = name + '';
+ if (!isString(name)) {
+ throw $parseMinErr('iseccst',
+ 'Cannot convert object to primitive value! '
+ + 'Expression: {0}', fullExpression);
+ }
+ return name;
+}
+
+function ensureSafeObject(obj, fullExpression) {
+ // nifty check if obj is Function that is fast and works across iframes and other contexts
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isWindow(obj)
+ obj.window === obj) {
+ throw $parseMinErr('isecwindow',
+ 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// isElement(obj)
+ obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
+ throw $parseMinErr('isecdom',
+ 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (// block Object so that we can't get hold of dangerous Object.* methods
+ obj === Object) {
+ throw $parseMinErr('isecobj',
+ 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+ return obj;
+}
+
+var CALL = Function.prototype.call;
+var APPLY = Function.prototype.apply;
+var BIND = Function.prototype.bind;
+
+function ensureSafeFunction(obj, fullExpression) {
+ if (obj) {
+ if (obj.constructor === obj) {
+ throw $parseMinErr('isecfn',
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ } else if (obj === CALL || obj === APPLY || obj === BIND) {
+ throw $parseMinErr('isecff',
+ 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
+ fullExpression);
+ }
+ }
+}
+
+function ensureSafeAssignContext(obj, fullExpression) {
+ if (obj) {
+ if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||
+ obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {
+ throw $parseMinErr('isecaf',
+ 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);
+ }
+ }
+}
+
+var OPERATORS = createMap();
+forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
+var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
+
+
+/////////////////////////////////////////
+
+
+/**
+ * @constructor
+ */
+var Lexer = function(options) {
+ this.options = options;
+};
+
+Lexer.prototype = {
+ constructor: Lexer,
+
+ lex: function(text) {
+ this.text = text;
+ this.index = 0;
+ this.tokens = [];
+
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (ch === '"' || ch === "'") {
+ this.readString(ch);
+ } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
+ this.readNumber();
+ } else if (this.isIdent(ch)) {
+ this.readIdent();
+ } else if (this.is(ch, '(){}[].,;:?')) {
+ this.tokens.push({index: this.index, text: ch});
+ this.index++;
+ } else if (this.isWhitespace(ch)) {
+ this.index++;
+ } else {
+ var ch2 = ch + this.peek();
+ var ch3 = ch2 + this.peek(2);
+ var op1 = OPERATORS[ch];
+ var op2 = OPERATORS[ch2];
+ var op3 = OPERATORS[ch3];
+ if (op1 || op2 || op3) {
+ var token = op3 ? ch3 : (op2 ? ch2 : ch);
+ this.tokens.push({index: this.index, text: token, operator: true});
+ this.index += token.length;
+ } else {
+ this.throwError('Unexpected next character ', this.index, this.index + 1);
+ }
+ }
+ }
+ return this.tokens;
+ },
+
+ is: function(ch, chars) {
+ return chars.indexOf(ch) !== -1;
+ },
+
+ peek: function(i) {
+ var num = i || 1;
+ return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
+ },
+
+ isNumber: function(ch) {
+ return ('0' <= ch && ch <= '9') && typeof ch === "string";
+ },
+
+ isWhitespace: function(ch) {
+ // IE treats non-breaking space as \u00A0
+ return (ch === ' ' || ch === '\r' || ch === '\t' ||
+ ch === '\n' || ch === '\v' || ch === '\u00A0');
+ },
+
+ isIdent: function(ch) {
+ return ('a' <= ch && ch <= 'z' ||
+ 'A' <= ch && ch <= 'Z' ||
+ '_' === ch || ch === '$');
+ },
+
+ isExpOperator: function(ch) {
+ return (ch === '-' || ch === '+' || this.isNumber(ch));
+ },
+
+ throwError: function(error, start, end) {
+ end = end || this.index;
+ var colStr = (isDefined(start)
+ ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
+ : ' ' + end);
+ throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
+ error, colStr, this.text);
+ },
+
+ readNumber: function() {
+ var number = '';
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = lowercase(this.text.charAt(this.index));
+ if (ch == '.' || this.isNumber(ch)) {
+ number += ch;
+ } else {
+ var peekCh = this.peek();
+ if (ch == 'e' && this.isExpOperator(peekCh)) {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ peekCh && this.isNumber(peekCh) &&
+ number.charAt(number.length - 1) == 'e') {
+ number += ch;
+ } else if (this.isExpOperator(ch) &&
+ (!peekCh || !this.isNumber(peekCh)) &&
+ number.charAt(number.length - 1) == 'e') {
+ this.throwError('Invalid exponent');
+ } else {
+ break;
+ }
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: number,
+ constant: true,
+ value: Number(number)
+ });
+ },
+
+ readIdent: function() {
+ var start = this.index;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ if (!(this.isIdent(ch) || this.isNumber(ch))) {
+ break;
+ }
+ this.index++;
+ }
+ this.tokens.push({
+ index: start,
+ text: this.text.slice(start, this.index),
+ identifier: true
+ });
+ },
+
+ readString: function(quote) {
+ var start = this.index;
+ this.index++;
+ var string = '';
+ var rawString = quote;
+ var escape = false;
+ while (this.index < this.text.length) {
+ var ch = this.text.charAt(this.index);
+ rawString += ch;
+ if (escape) {
+ if (ch === 'u') {
+ var hex = this.text.substring(this.index + 1, this.index + 5);
+ if (!hex.match(/[\da-f]{4}/i)) {
+ this.throwError('Invalid unicode escape [\\u' + hex + ']');
+ }
+ this.index += 4;
+ string += String.fromCharCode(parseInt(hex, 16));
+ } else {
+ var rep = ESCAPE[ch];
+ string = string + (rep || ch);
+ }
+ escape = false;
+ } else if (ch === '\\') {
+ escape = true;
+ } else if (ch === quote) {
+ this.index++;
+ this.tokens.push({
+ index: start,
+ text: rawString,
+ constant: true,
+ value: string
+ });
+ return;
+ } else {
+ string += ch;
+ }
+ this.index++;
+ }
+ this.throwError('Unterminated quote', start);
+ }
+};
+
+var AST = function(lexer, options) {
+ this.lexer = lexer;
+ this.options = options;
+};
+
+AST.Program = 'Program';
+AST.ExpressionStatement = 'ExpressionStatement';
+AST.AssignmentExpression = 'AssignmentExpression';
+AST.ConditionalExpression = 'ConditionalExpression';
+AST.LogicalExpression = 'LogicalExpression';
+AST.BinaryExpression = 'BinaryExpression';
+AST.UnaryExpression = 'UnaryExpression';
+AST.CallExpression = 'CallExpression';
+AST.MemberExpression = 'MemberExpression';
+AST.Identifier = 'Identifier';
+AST.Literal = 'Literal';
+AST.ArrayExpression = 'ArrayExpression';
+AST.Property = 'Property';
+AST.ObjectExpression = 'ObjectExpression';
+AST.ThisExpression = 'ThisExpression';
+
+// Internal use only
+AST.NGValueParameter = 'NGValueParameter';
+
+AST.prototype = {
+ ast: function(text) {
+ this.text = text;
+ this.tokens = this.lexer.lex(text);
+
+ var value = this.program();
+
+ if (this.tokens.length !== 0) {
+ this.throwError('is an unexpected token', this.tokens[0]);
+ }
+
+ return value;
+ },
+
+ program: function() {
+ var body = [];
+ while (true) {
+ if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
+ body.push(this.expressionStatement());
+ if (!this.expect(';')) {
+ return { type: AST.Program, body: body};
+ }
+ }
+ },
+
+ expressionStatement: function() {
+ return { type: AST.ExpressionStatement, expression: this.filterChain() };
+ },
+
+ filterChain: function() {
+ var left = this.expression();
+ var token;
+ while ((token = this.expect('|'))) {
+ left = this.filter(left);
+ }
+ return left;
+ },
+
+ expression: function() {
+ return this.assignment();
+ },
+
+ assignment: function() {
+ var result = this.ternary();
+ if (this.expect('=')) {
+ result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
+ }
+ return result;
+ },
+
+ ternary: function() {
+ var test = this.logicalOR();
+ var alternate;
+ var consequent;
+ if (this.expect('?')) {
+ alternate = this.expression();
+ if (this.consume(':')) {
+ consequent = this.expression();
+ return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};
+ }
+ }
+ return test;
+ },
+
+ logicalOR: function() {
+ var left = this.logicalAND();
+ while (this.expect('||')) {
+ left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };
+ }
+ return left;
+ },
+
+ logicalAND: function() {
+ var left = this.equality();
+ while (this.expect('&&')) {
+ left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};
+ }
+ return left;
+ },
+
+ equality: function() {
+ var left = this.relational();
+ var token;
+ while ((token = this.expect('==','!=','===','!=='))) {
+ left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };
+ }
+ return left;
+ },
+
+ relational: function() {
+ var left = this.additive();
+ var token;
+ while ((token = this.expect('<', '>', '<=', '>='))) {
+ left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };
+ }
+ return left;
+ },
+
+ additive: function() {
+ var left = this.multiplicative();
+ var token;
+ while ((token = this.expect('+','-'))) {
+ left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };
+ }
+ return left;
+ },
+
+ multiplicative: function() {
+ var left = this.unary();
+ var token;
+ while ((token = this.expect('*','/','%'))) {
+ left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };
+ }
+ return left;
+ },
+
+ unary: function() {
+ var token;
+ if ((token = this.expect('+', '-', '!'))) {
+ return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };
+ } else {
+ return this.primary();
+ }
+ },
+
+ primary: function() {
+ var primary;
+ if (this.expect('(')) {
+ primary = this.filterChain();
+ this.consume(')');
+ } else if (this.expect('[')) {
+ primary = this.arrayDeclaration();
+ } else if (this.expect('{')) {
+ primary = this.object();
+ } else if (this.constants.hasOwnProperty(this.peek().text)) {
+ primary = copy(this.constants[this.consume().text]);
+ } else if (this.peek().identifier) {
+ primary = this.identifier();
+ } else if (this.peek().constant) {
+ primary = this.constant();
+ } else {
+ this.throwError('not a primary expression', this.peek());
+ }
+
+ var next;
+ while ((next = this.expect('(', '[', '.'))) {
+ if (next.text === '(') {
+ primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };
+ this.consume(')');
+ } else if (next.text === '[') {
+ primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };
+ this.consume(']');
+ } else if (next.text === '.') {
+ primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };
+ } else {
+ this.throwError('IMPOSSIBLE');
+ }
+ }
+ return primary;
+ },
+
+ filter: function(baseExpression) {
+ var args = [baseExpression];
+ var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};
+
+ while (this.expect(':')) {
+ args.push(this.expression());
+ }
+
+ return result;
+ },
+
+ parseArguments: function() {
+ var args = [];
+ if (this.peekToken().text !== ')') {
+ do {
+ args.push(this.expression());
+ } while (this.expect(','));
+ }
+ return args;
+ },
+
+ identifier: function() {
+ var token = this.consume();
+ if (!token.identifier) {
+ this.throwError('is not a valid identifier', token);
+ }
+ return { type: AST.Identifier, name: token.text };
+ },
+
+ constant: function() {
+ // TODO check that it is a constant
+ return { type: AST.Literal, value: this.consume().value };
+ },
+
+ arrayDeclaration: function() {
+ var elements = [];
+ if (this.peekToken().text !== ']') {
+ do {
+ if (this.peek(']')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ elements.push(this.expression());
+ } while (this.expect(','));
+ }
+ this.consume(']');
+
+ return { type: AST.ArrayExpression, elements: elements };
+ },
+
+ object: function() {
+ var properties = [], property;
+ if (this.peekToken().text !== '}') {
+ do {
+ if (this.peek('}')) {
+ // Support trailing commas per ES5.1.
+ break;
+ }
+ property = {type: AST.Property, kind: 'init'};
+ if (this.peek().constant) {
+ property.key = this.constant();
+ } else if (this.peek().identifier) {
+ property.key = this.identifier();
+ } else {
+ this.throwError("invalid key", this.peek());
+ }
+ this.consume(':');
+ property.value = this.expression();
+ properties.push(property);
+ } while (this.expect(','));
+ }
+ this.consume('}');
+
+ return {type: AST.ObjectExpression, properties: properties };
+ },
+
+ throwError: function(msg, token) {
+ throw $parseMinErr('syntax',
+ 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
+ token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
+ },
+
+ consume: function(e1) {
+ if (this.tokens.length === 0) {
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ }
+
+ var token = this.expect(e1);
+ if (!token) {
+ this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
+ }
+ return token;
+ },
+
+ peekToken: function() {
+ if (this.tokens.length === 0) {
+ throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
+ }
+ return this.tokens[0];
+ },
+
+ peek: function(e1, e2, e3, e4) {
+ return this.peekAhead(0, e1, e2, e3, e4);
+ },
+
+ peekAhead: function(i, e1, e2, e3, e4) {
+ if (this.tokens.length > i) {
+ var token = this.tokens[i];
+ var t = token.text;
+ if (t === e1 || t === e2 || t === e3 || t === e4 ||
+ (!e1 && !e2 && !e3 && !e4)) {
+ return token;
+ }
+ }
+ return false;
+ },
+
+ expect: function(e1, e2, e3, e4) {
+ var token = this.peek(e1, e2, e3, e4);
+ if (token) {
+ this.tokens.shift();
+ return token;
+ }
+ return false;
+ },
+
+
+ /* `undefined` is not a constant, it is an identifier,
+ * but using it as an identifier is not supported
+ */
+ constants: {
+ 'true': { type: AST.Literal, value: true },
+ 'false': { type: AST.Literal, value: false },
+ 'null': { type: AST.Literal, value: null },
+ 'undefined': {type: AST.Literal, value: undefined },
+ 'this': {type: AST.ThisExpression }
+ }
+};
+
+function ifDefined(v, d) {
+ return typeof v !== 'undefined' ? v : d;
+}
+
+function plusFn(l, r) {
+ if (typeof l === 'undefined') return r;
+ if (typeof r === 'undefined') return l;
+ return l + r;
+}
+
+function isStateless($filter, filterName) {
+ var fn = $filter(filterName);
+ return !fn.$stateful;
+}
+
+function findConstantAndWatchExpressions(ast, $filter) {
+ var allConstants;
+ var argsToWatch;
+ switch (ast.type) {
+ case AST.Program:
+ allConstants = true;
+ forEach(ast.body, function(expr) {
+ findConstantAndWatchExpressions(expr.expression, $filter);
+ allConstants = allConstants && expr.expression.constant;
+ });
+ ast.constant = allConstants;
+ break;
+ case AST.Literal:
+ ast.constant = true;
+ ast.toWatch = [];
+ break;
+ case AST.UnaryExpression:
+ findConstantAndWatchExpressions(ast.argument, $filter);
+ ast.constant = ast.argument.constant;
+ ast.toWatch = ast.argument.toWatch;
+ break;
+ case AST.BinaryExpression:
+ findConstantAndWatchExpressions(ast.left, $filter);
+ findConstantAndWatchExpressions(ast.right, $filter);
+ ast.constant = ast.left.constant && ast.right.constant;
+ ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
+ break;
+ case AST.LogicalExpression:
+ findConstantAndWatchExpressions(ast.left, $filter);
+ findConstantAndWatchExpressions(ast.right, $filter);
+ ast.constant = ast.left.constant && ast.right.constant;
+ ast.toWatch = ast.constant ? [] : [ast];
+ break;
+ case AST.ConditionalExpression:
+ findConstantAndWatchExpressions(ast.test, $filter);
+ findConstantAndWatchExpressions(ast.alternate, $filter);
+ findConstantAndWatchExpressions(ast.consequent, $filter);
+ ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;
+ ast.toWatch = ast.constant ? [] : [ast];
+ break;
+ case AST.Identifier:
+ ast.constant = false;
+ ast.toWatch = [ast];
+ break;
+ case AST.MemberExpression:
+ findConstantAndWatchExpressions(ast.object, $filter);
+ if (ast.computed) {
+ findConstantAndWatchExpressions(ast.property, $filter);
+ }
+ ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);
+ ast.toWatch = [ast];
+ break;
+ case AST.CallExpression:
+ allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
+ argsToWatch = [];
+ forEach(ast.arguments, function(expr) {
+ findConstantAndWatchExpressions(expr, $filter);
+ allConstants = allConstants && expr.constant;
+ if (!expr.constant) {
+ argsToWatch.push.apply(argsToWatch, expr.toWatch);
+ }
+ });
+ ast.constant = allConstants;
+ ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
+ break;
+ case AST.AssignmentExpression:
+ findConstantAndWatchExpressions(ast.left, $filter);
+ findConstantAndWatchExpressions(ast.right, $filter);
+ ast.constant = ast.left.constant && ast.right.constant;
+ ast.toWatch = [ast];
+ break;
+ case AST.ArrayExpression:
+ allConstants = true;
+ argsToWatch = [];
+ forEach(ast.elements, function(expr) {
+ findConstantAndWatchExpressions(expr, $filter);
+ allConstants = allConstants && expr.constant;
+ if (!expr.constant) {
+ argsToWatch.push.apply(argsToWatch, expr.toWatch);
+ }
+ });
+ ast.constant = allConstants;
+ ast.toWatch = argsToWatch;
+ break;
+ case AST.ObjectExpression:
+ allConstants = true;
+ argsToWatch = [];
+ forEach(ast.properties, function(property) {
+ findConstantAndWatchExpressions(property.value, $filter);
+ allConstants = allConstants && property.value.constant;
+ if (!property.value.constant) {
+ argsToWatch.push.apply(argsToWatch, property.value.toWatch);
+ }
+ });
+ ast.constant = allConstants;
+ ast.toWatch = argsToWatch;
+ break;
+ case AST.ThisExpression:
+ ast.constant = false;
+ ast.toWatch = [];
+ break;
+ }
+}
+
+function getInputs(body) {
+ if (body.length != 1) return;
+ var lastExpression = body[0].expression;
+ var candidate = lastExpression.toWatch;
+ if (candidate.length !== 1) return candidate;
+ return candidate[0] !== lastExpression ? candidate : undefined;
+}
+
+function isAssignable(ast) {
+ return ast.type === AST.Identifier || ast.type === AST.MemberExpression;
+}
+
+function assignableAST(ast) {
+ if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
+ return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};
+ }
+}
+
+function isLiteral(ast) {
+ return ast.body.length === 0 ||
+ ast.body.length === 1 && (
+ ast.body[0].expression.type === AST.Literal ||
+ ast.body[0].expression.type === AST.ArrayExpression ||
+ ast.body[0].expression.type === AST.ObjectExpression);
+}
+
+function isConstant(ast) {
+ return ast.constant;
+}
+
+function ASTCompiler(astBuilder, $filter) {
+ this.astBuilder = astBuilder;
+ this.$filter = $filter;
+}
+
+ASTCompiler.prototype = {
+ compile: function(expression, expensiveChecks) {
+ var self = this;
+ var ast = this.astBuilder.ast(expression);
+ this.state = {
+ nextId: 0,
+ filters: {},
+ expensiveChecks: expensiveChecks,
+ fn: {vars: [], body: [], own: {}},
+ assign: {vars: [], body: [], own: {}},
+ inputs: []
+ };
+ findConstantAndWatchExpressions(ast, self.$filter);
+ var extra = '';
+ var assignable;
+ this.stage = 'assign';
+ if ((assignable = assignableAST(ast))) {
+ this.state.computing = 'assign';
+ var result = this.nextId();
+ this.recurse(assignable, result);
+ this.return_(result);
+ extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
+ }
+ var toWatch = getInputs(ast.body);
+ self.stage = 'inputs';
+ forEach(toWatch, function(watch, key) {
+ var fnKey = 'fn' + key;
+ self.state[fnKey] = {vars: [], body: [], own: {}};
+ self.state.computing = fnKey;
+ var intoId = self.nextId();
+ self.recurse(watch, intoId);
+ self.return_(intoId);
+ self.state.inputs.push(fnKey);
+ watch.watchId = key;
+ });
+ this.state.computing = 'fn';
+ this.stage = 'main';
+ this.recurse(ast);
+ var fnString =
+ // The build and minification steps remove the string "use strict" from the code, but this is done using a regex.
+ // This is a workaround for this until we do a better job at only removing the prefix only when we should.
+ '"' + this.USE + ' ' + this.STRICT + '";\n' +
+ this.filterPrefix() +
+ 'var fn=' + this.generateFunction('fn', 's,l,a,i') +
+ extra +
+ this.watchFns() +
+ 'return fn;';
+
+ /* jshint -W054 */
+ var fn = (new Function('$filter',
+ 'ensureSafeMemberName',
+ 'ensureSafeObject',
+ 'ensureSafeFunction',
+ 'getStringValue',
+ 'ensureSafeAssignContext',
+ 'ifDefined',
+ 'plus',
+ 'text',
+ fnString))(
+ this.$filter,
+ ensureSafeMemberName,
+ ensureSafeObject,
+ ensureSafeFunction,
+ getStringValue,
+ ensureSafeAssignContext,
+ ifDefined,
+ plusFn,
+ expression);
+ /* jshint +W054 */
+ this.state = this.stage = undefined;
+ fn.literal = isLiteral(ast);
+ fn.constant = isConstant(ast);
+ return fn;
+ },
+
+ USE: 'use',
+
+ STRICT: 'strict',
+
+ watchFns: function() {
+ var result = [];
+ var fns = this.state.inputs;
+ var self = this;
+ forEach(fns, function(name) {
+ result.push('var ' + name + '=' + self.generateFunction(name, 's'));
+ });
+ if (fns.length) {
+ result.push('fn.inputs=[' + fns.join(',') + '];');
+ }
+ return result.join('');
+ },
+
+ generateFunction: function(name, params) {
+ return 'function(' + params + '){' +
+ this.varsPrefix(name) +
+ this.body(name) +
+ '};';
+ },
+
+ filterPrefix: function() {
+ var parts = [];
+ var self = this;
+ forEach(this.state.filters, function(id, filter) {
+ parts.push(id + '=$filter(' + self.escape(filter) + ')');
+ });
+ if (parts.length) return 'var ' + parts.join(',') + ';';
+ return '';
+ },
+
+ varsPrefix: function(section) {
+ return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';
+ },
+
+ body: function(section) {
+ return this.state[section].body.join('');
+ },
+
+ recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
+ var left, right, self = this, args, expression;
+ recursionFn = recursionFn || noop;
+ if (!skipWatchIdCheck && isDefined(ast.watchId)) {
+ intoId = intoId || this.nextId();
+ this.if_('i',
+ this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),
+ this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)
+ );
+ return;
+ }
+ switch (ast.type) {
+ case AST.Program:
+ forEach(ast.body, function(expression, pos) {
+ self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });
+ if (pos !== ast.body.length - 1) {
+ self.current().body.push(right, ';');
+ } else {
+ self.return_(right);
+ }
+ });
+ break;
+ case AST.Literal:
+ expression = this.escape(ast.value);
+ this.assign(intoId, expression);
+ recursionFn(expression);
+ break;
+ case AST.UnaryExpression:
+ this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });
+ expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';
+ this.assign(intoId, expression);
+ recursionFn(expression);
+ break;
+ case AST.BinaryExpression:
+ this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });
+ this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });
+ if (ast.operator === '+') {
+ expression = this.plus(left, right);
+ } else if (ast.operator === '-') {
+ expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);
+ } else {
+ expression = '(' + left + ')' + ast.operator + '(' + right + ')';
+ }
+ this.assign(intoId, expression);
+ recursionFn(expression);
+ break;
+ case AST.LogicalExpression:
+ intoId = intoId || this.nextId();
+ self.recurse(ast.left, intoId);
+ self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));
+ recursionFn(intoId);
+ break;
+ case AST.ConditionalExpression:
+ intoId = intoId || this.nextId();
+ self.recurse(ast.test, intoId);
+ self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));
+ recursionFn(intoId);
+ break;
+ case AST.Identifier:
+ intoId = intoId || this.nextId();
+ if (nameId) {
+ nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');
+ nameId.computed = false;
+ nameId.name = ast.name;
+ }
+ ensureSafeMemberName(ast.name);
+ self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),
+ function() {
+ self.if_(self.stage === 'inputs' || 's', function() {
+ if (create && create !== 1) {
+ self.if_(
+ self.not(self.nonComputedMember('s', ast.name)),
+ self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));
+ }
+ self.assign(intoId, self.nonComputedMember('s', ast.name));
+ });
+ }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))
+ );
+ if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) {
+ self.addEnsureSafeObject(intoId);
+ }
+ recursionFn(intoId);
+ break;
+ case AST.MemberExpression:
+ left = nameId && (nameId.context = this.nextId()) || this.nextId();
+ intoId = intoId || this.nextId();
+ self.recurse(ast.object, left, undefined, function() {
+ self.if_(self.notNull(left), function() {
+ if (ast.computed) {
+ right = self.nextId();
+ self.recurse(ast.property, right);
+ self.getStringValue(right);
+ self.addEnsureSafeMemberName(right);
+ if (create && create !== 1) {
+ self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
+ }
+ expression = self.ensureSafeObject(self.computedMember(left, right));
+ self.assign(intoId, expression);
+ if (nameId) {
+ nameId.computed = true;
+ nameId.name = right;
+ }
+ } else {
+ ensureSafeMemberName(ast.property.name);
+ if (create && create !== 1) {
+ self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
+ }
+ expression = self.nonComputedMember(left, ast.property.name);
+ if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) {
+ expression = self.ensureSafeObject(expression);
+ }
+ self.assign(intoId, expression);
+ if (nameId) {
+ nameId.computed = false;
+ nameId.name = ast.property.name;
+ }
+ }
+ }, function() {
+ self.assign(intoId, 'undefined');
+ });
+ recursionFn(intoId);
+ }, !!create);
+ break;
+ case AST.CallExpression:
+ intoId = intoId || this.nextId();
+ if (ast.filter) {
+ right = self.filter(ast.callee.name);
+ args = [];
+ forEach(ast.arguments, function(expr) {
+ var argument = self.nextId();
+ self.recurse(expr, argument);
+ args.push(argument);
+ });
+ expression = right + '(' + args.join(',') + ')';
+ self.assign(intoId, expression);
+ recursionFn(intoId);
+ } else {
+ right = self.nextId();
+ left = {};
+ args = [];
+ self.recurse(ast.callee, right, left, function() {
+ self.if_(self.notNull(right), function() {
+ self.addEnsureSafeFunction(right);
+ forEach(ast.arguments, function(expr) {
+ self.recurse(expr, self.nextId(), undefined, function(argument) {
+ args.push(self.ensureSafeObject(argument));
+ });
+ });
+ if (left.name) {
+ if (!self.state.expensiveChecks) {
+ self.addEnsureSafeObject(left.context);
+ }
+ expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';
+ } else {
+ expression = right + '(' + args.join(',') + ')';
+ }
+ expression = self.ensureSafeObject(expression);
+ self.assign(intoId, expression);
+ }, function() {
+ self.assign(intoId, 'undefined');
+ });
+ recursionFn(intoId);
+ });
+ }
+ break;
+ case AST.AssignmentExpression:
+ right = this.nextId();
+ left = {};
+ if (!isAssignable(ast.left)) {
+ throw $parseMinErr('lval', 'Trying to assing a value to a non l-value');
+ }
+ this.recurse(ast.left, undefined, left, function() {
+ self.if_(self.notNull(left.context), function() {
+ self.recurse(ast.right, right);
+ self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
+ self.addEnsureSafeAssignContext(left.context);
+ expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
+ self.assign(intoId, expression);
+ recursionFn(intoId || expression);
+ });
+ }, 1);
+ break;
+ case AST.ArrayExpression:
+ args = [];
+ forEach(ast.elements, function(expr) {
+ self.recurse(expr, self.nextId(), undefined, function(argument) {
+ args.push(argument);
+ });
+ });
+ expression = '[' + args.join(',') + ']';
+ this.assign(intoId, expression);
+ recursionFn(expression);
+ break;
+ case AST.ObjectExpression:
+ args = [];
+ forEach(ast.properties, function(property) {
+ self.recurse(property.value, self.nextId(), undefined, function(expr) {
+ args.push(self.escape(
+ property.key.type === AST.Identifier ? property.key.name :
+ ('' + property.key.value)) +
+ ':' + expr);
+ });
+ });
+ expression = '{' + args.join(',') + '}';
+ this.assign(intoId, expression);
+ recursionFn(expression);
+ break;
+ case AST.ThisExpression:
+ this.assign(intoId, 's');
+ recursionFn('s');
+ break;
+ case AST.NGValueParameter:
+ this.assign(intoId, 'v');
+ recursionFn('v');
+ break;
+ }
+ },
+
+ getHasOwnProperty: function(element, property) {
+ var key = element + '.' + property;
+ var own = this.current().own;
+ if (!own.hasOwnProperty(key)) {
+ own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');
+ }
+ return own[key];
+ },
+
+ assign: function(id, value) {
+ if (!id) return;
+ this.current().body.push(id, '=', value, ';');
+ return id;
+ },
+
+ filter: function(filterName) {
+ if (!this.state.filters.hasOwnProperty(filterName)) {
+ this.state.filters[filterName] = this.nextId(true);
+ }
+ return this.state.filters[filterName];
+ },
+
+ ifDefined: function(id, defaultValue) {
+ return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';
+ },
+
+ plus: function(left, right) {
+ return 'plus(' + left + ',' + right + ')';
+ },
+
+ return_: function(id) {
+ this.current().body.push('return ', id, ';');
+ },
+
+ if_: function(test, alternate, consequent) {
+ if (test === true) {
+ alternate();
+ } else {
+ var body = this.current().body;
+ body.push('if(', test, '){');
+ alternate();
+ body.push('}');
+ if (consequent) {
+ body.push('else{');
+ consequent();
+ body.push('}');
+ }
+ }
+ },
+
+ not: function(expression) {
+ return '!(' + expression + ')';
+ },
+
+ notNull: function(expression) {
+ return expression + '!=null';
+ },
+
+ nonComputedMember: function(left, right) {
+ return left + '.' + right;
+ },
+
+ computedMember: function(left, right) {
+ return left + '[' + right + ']';
+ },
+
+ member: function(left, right, computed) {
+ if (computed) return this.computedMember(left, right);
+ return this.nonComputedMember(left, right);
+ },
+
+ addEnsureSafeObject: function(item) {
+ this.current().body.push(this.ensureSafeObject(item), ';');
+ },
+
+ addEnsureSafeMemberName: function(item) {
+ this.current().body.push(this.ensureSafeMemberName(item), ';');
+ },
+
+ addEnsureSafeFunction: function(item) {
+ this.current().body.push(this.ensureSafeFunction(item), ';');
+ },
+
+ addEnsureSafeAssignContext: function(item) {
+ this.current().body.push(this.ensureSafeAssignContext(item), ';');
+ },
+
+ ensureSafeObject: function(item) {
+ return 'ensureSafeObject(' + item + ',text)';
+ },
+
+ ensureSafeMemberName: function(item) {
+ return 'ensureSafeMemberName(' + item + ',text)';
+ },
+
+ ensureSafeFunction: function(item) {
+ return 'ensureSafeFunction(' + item + ',text)';
+ },
+
+ getStringValue: function(item) {
+ this.assign(item, 'getStringValue(' + item + ',text)');
+ },
+
+ ensureSafeAssignContext: function(item) {
+ return 'ensureSafeAssignContext(' + item + ',text)';
+ },
+
+ lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
+ var self = this;
+ return function() {
+ self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);
+ };
+ },
+
+ lazyAssign: function(id, value) {
+ var self = this;
+ return function() {
+ self.assign(id, value);
+ };
+ },
+
+ stringEscapeRegex: /[^ a-zA-Z0-9]/g,
+
+ stringEscapeFn: function(c) {
+ return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);
+ },
+
+ escape: function(value) {
+ if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'";
+ if (isNumber(value)) return value.toString();
+ if (value === true) return 'true';
+ if (value === false) return 'false';
+ if (value === null) return 'null';
+ if (typeof value === 'undefined') return 'undefined';
+
+ throw $parseMinErr('esc', 'IMPOSSIBLE');
+ },
+
+ nextId: function(skip, init) {
+ var id = 'v' + (this.state.nextId++);
+ if (!skip) {
+ this.current().vars.push(id + (init ? '=' + init : ''));
+ }
+ return id;
+ },
+
+ current: function() {
+ return this.state[this.state.computing];
+ }
+};
+
+
+function ASTInterpreter(astBuilder, $filter) {
+ this.astBuilder = astBuilder;
+ this.$filter = $filter;
+}
+
+ASTInterpreter.prototype = {
+ compile: function(expression, expensiveChecks) {
+ var self = this;
+ var ast = this.astBuilder.ast(expression);
+ this.expression = expression;
+ this.expensiveChecks = expensiveChecks;
+ findConstantAndWatchExpressions(ast, self.$filter);
+ var assignable;
+ var assign;
+ if ((assignable = assignableAST(ast))) {
+ assign = this.recurse(assignable);
+ }
+ var toWatch = getInputs(ast.body);
+ var inputs;
+ if (toWatch) {
+ inputs = [];
+ forEach(toWatch, function(watch, key) {
+ var input = self.recurse(watch);
+ watch.input = input;
+ inputs.push(input);
+ watch.watchId = key;
+ });
+ }
+ var expressions = [];
+ forEach(ast.body, function(expression) {
+ expressions.push(self.recurse(expression.expression));
+ });
+ var fn = ast.body.length === 0 ? function() {} :
+ ast.body.length === 1 ? expressions[0] :
+ function(scope, locals) {
+ var lastValue;
+ forEach(expressions, function(exp) {
+ lastValue = exp(scope, locals);
+ });
+ return lastValue;
+ };
+ if (assign) {
+ fn.assign = function(scope, value, locals) {
+ return assign(scope, locals, value);
+ };
+ }
+ if (inputs) {
+ fn.inputs = inputs;
+ }
+ fn.literal = isLiteral(ast);
+ fn.constant = isConstant(ast);
+ return fn;
+ },
+
+ recurse: function(ast, context, create) {
+ var left, right, self = this, args, expression;
+ if (ast.input) {
+ return this.inputs(ast.input, ast.watchId);
+ }
+ switch (ast.type) {
+ case AST.Literal:
+ return this.value(ast.value, context);
+ case AST.UnaryExpression:
+ right = this.recurse(ast.argument);
+ return this['unary' + ast.operator](right, context);
+ case AST.BinaryExpression:
+ left = this.recurse(ast.left);
+ right = this.recurse(ast.right);
+ return this['binary' + ast.operator](left, right, context);
+ case AST.LogicalExpression:
+ left = this.recurse(ast.left);
+ right = this.recurse(ast.right);
+ return this['binary' + ast.operator](left, right, context);
+ case AST.ConditionalExpression:
+ return this['ternary?:'](
+ this.recurse(ast.test),
+ this.recurse(ast.alternate),
+ this.recurse(ast.consequent),
+ context
+ );
+ case AST.Identifier:
+ ensureSafeMemberName(ast.name, self.expression);
+ return self.identifier(ast.name,
+ self.expensiveChecks || isPossiblyDangerousMemberName(ast.name),
+ context, create, self.expression);
+ case AST.MemberExpression:
+ left = this.recurse(ast.object, false, !!create);
+ if (!ast.computed) {
+ ensureSafeMemberName(ast.property.name, self.expression);
+ right = ast.property.name;
+ }
+ if (ast.computed) right = this.recurse(ast.property);
+ return ast.computed ?
+ this.computedMember(left, right, context, create, self.expression) :
+ this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression);
+ case AST.CallExpression:
+ args = [];
+ forEach(ast.arguments, function(expr) {
+ args.push(self.recurse(expr));
+ });
+ if (ast.filter) right = this.$filter(ast.callee.name);
+ if (!ast.filter) right = this.recurse(ast.callee, true);
+ return ast.filter ?
+ function(scope, locals, assign, inputs) {
+ var values = [];
+ for (var i = 0; i < args.length; ++i) {
+ values.push(args[i](scope, locals, assign, inputs));
+ }
+ var value = right.apply(undefined, values, inputs);
+ return context ? {context: undefined, name: undefined, value: value} : value;
+ } :
+ function(scope, locals, assign, inputs) {
+ var rhs = right(scope, locals, assign, inputs);
+ var value;
+ if (rhs.value != null) {
+ ensureSafeObject(rhs.context, self.expression);
+ ensureSafeFunction(rhs.value, self.expression);
+ var values = [];
+ for (var i = 0; i < args.length; ++i) {
+ values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression));
+ }
+ value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression);
+ }
+ return context ? {value: value} : value;
+ };
+ case AST.AssignmentExpression:
+ left = this.recurse(ast.left, true, 1);
+ right = this.recurse(ast.right);
+ return function(scope, locals, assign, inputs) {
+ var lhs = left(scope, locals, assign, inputs);
+ var rhs = right(scope, locals, assign, inputs);
+ ensureSafeObject(lhs.value, self.expression);
+ ensureSafeAssignContext(lhs.context);
+ lhs.context[lhs.name] = rhs;
+ return context ? {value: rhs} : rhs;
+ };
+ case AST.ArrayExpression:
+ args = [];
+ forEach(ast.elements, function(expr) {
+ args.push(self.recurse(expr));
+ });
+ return function(scope, locals, assign, inputs) {
+ var value = [];
+ for (var i = 0; i < args.length; ++i) {
+ value.push(args[i](scope, locals, assign, inputs));
+ }
+ return context ? {value: value} : value;
+ };
+ case AST.ObjectExpression:
+ args = [];
+ forEach(ast.properties, function(property) {
+ args.push({key: property.key.type === AST.Identifier ?
+ property.key.name :
+ ('' + property.key.value),
+ value: self.recurse(property.value)
+ });
+ });
+ return function(scope, locals, assign, inputs) {
+ var value = {};
+ for (var i = 0; i < args.length; ++i) {
+ value[args[i].key] = args[i].value(scope, locals, assign, inputs);
+ }
+ return context ? {value: value} : value;
+ };
+ case AST.ThisExpression:
+ return function(scope) {
+ return context ? {value: scope} : scope;
+ };
+ case AST.NGValueParameter:
+ return function(scope, locals, assign, inputs) {
+ return context ? {value: assign} : assign;
+ };
+ }
+ },
+
+ 'unary+': function(argument, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = argument(scope, locals, assign, inputs);
+ if (isDefined(arg)) {
+ arg = +arg;
+ } else {
+ arg = 0;
+ }
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'unary-': function(argument, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = argument(scope, locals, assign, inputs);
+ if (isDefined(arg)) {
+ arg = -arg;
+ } else {
+ arg = 0;
+ }
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'unary!': function(argument, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = !argument(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary+': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var lhs = left(scope, locals, assign, inputs);
+ var rhs = right(scope, locals, assign, inputs);
+ var arg = plusFn(lhs, rhs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary-': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var lhs = left(scope, locals, assign, inputs);
+ var rhs = right(scope, locals, assign, inputs);
+ var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary*': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary/': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary%': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary===': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary!==': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary==': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary!=': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary<': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary>': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary<=': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary>=': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary&&': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'binary||': function(left, right, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ 'ternary?:': function(test, alternate, consequent, context) {
+ return function(scope, locals, assign, inputs) {
+ var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);
+ return context ? {value: arg} : arg;
+ };
+ },
+ value: function(value, context) {
+ return function() { return context ? {context: undefined, name: undefined, value: value} : value; };
+ },
+ identifier: function(name, expensiveChecks, context, create, expression) {
+ return function(scope, locals, assign, inputs) {
+ var base = locals && (name in locals) ? locals : scope;
+ if (create && create !== 1 && base && !(base[name])) {
+ base[name] = {};
+ }
+ var value = base ? base[name] : undefined;
+ if (expensiveChecks) {
+ ensureSafeObject(value, expression);
+ }
+ if (context) {
+ return {context: base, name: name, value: value};
+ } else {
+ return value;
+ }
+ };
+ },
+ computedMember: function(left, right, context, create, expression) {
+ return function(scope, locals, assign, inputs) {
+ var lhs = left(scope, locals, assign, inputs);
+ var rhs;
+ var value;
+ if (lhs != null) {
+ rhs = right(scope, locals, assign, inputs);
+ rhs = getStringValue(rhs);
+ ensureSafeMemberName(rhs, expression);
+ if (create && create !== 1 && lhs && !(lhs[rhs])) {
+ lhs[rhs] = {};
+ }
+ value = lhs[rhs];
+ ensureSafeObject(value, expression);
+ }
+ if (context) {
+ return {context: lhs, name: rhs, value: value};
+ } else {
+ return value;
+ }
+ };
+ },
+ nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
+ return function(scope, locals, assign, inputs) {
+ var lhs = left(scope, locals, assign, inputs);
+ if (create && create !== 1 && lhs && !(lhs[right])) {
+ lhs[right] = {};
+ }
+ var value = lhs != null ? lhs[right] : undefined;
+ if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
+ ensureSafeObject(value, expression);
+ }
+ if (context) {
+ return {context: lhs, name: right, value: value};
+ } else {
+ return value;
+ }
+ };
+ },
+ inputs: function(input, watchId) {
+ return function(scope, value, locals, inputs) {
+ if (inputs) return inputs[watchId];
+ return input(scope, value, locals);
+ };
+ }
+};
+
+/**
+ * @constructor
+ */
+var Parser = function(lexer, $filter, options) {
+ this.lexer = lexer;
+ this.$filter = $filter;
+ this.options = options;
+ this.ast = new AST(this.lexer);
+ this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :
+ new ASTCompiler(this.ast, $filter);
+};
+
+Parser.prototype = {
+ constructor: Parser,
+
+ parse: function(text) {
+ return this.astCompiler.compile(text, this.options.expensiveChecks);
+ }
+};
+
+var getterFnCacheDefault = createMap();
+var getterFnCacheExpensive = createMap();
+
+function isPossiblyDangerousMemberName(name) {
+ return name == 'constructor';
+}
+
+var objectValueOf = Object.prototype.valueOf;
+
+function getValueOf(value) {
+ return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
+}
+
+///////////////////////////////////
+
+/**
+ * @ngdoc service
+ * @name $parse
+ * @kind function
+ *
+ * @description
+ *
+ * Converts Angular {@link guide/expression expression} into a function.
+ *
+ * ```js
+ * var getter = $parse('user.name');
+ * var setter = getter.assign;
+ * var context = {user:{name:'angular'}};
+ * var locals = {user:{name:'local'}};
+ *
+ * expect(getter(context)).toEqual('angular');
+ * setter(context, 'newValue');
+ * expect(context.user.name).toEqual('newValue');
+ * expect(getter(context, locals)).toEqual('local');
+ * ```
+ *
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ *
+ * The returned function also has the following properties:
+ * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
+ * literal.
+ * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
+ * constant literals.
+ * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
+ * set to a function to change its value on the given context.
+ *
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $parseProvider
+ *
+ * @description
+ * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
+ * service.
+ */
+function $ParseProvider() {
+ var cacheDefault = createMap();
+ var cacheExpensive = createMap();
+
+ this.$get = ['$filter', function($filter) {
+ var noUnsafeEval = csp().noUnsafeEval;
+ var $parseOptions = {
+ csp: noUnsafeEval,
+ expensiveChecks: false
+ },
+ $parseOptionsExpensive = {
+ csp: noUnsafeEval,
+ expensiveChecks: true
+ };
+
+ return function $parse(exp, interceptorFn, expensiveChecks) {
+ var parsedExpression, oneTime, cacheKey;
+
+ switch (typeof exp) {
+ case 'string':
+ exp = exp.trim();
+ cacheKey = exp;
+
+ var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
+ parsedExpression = cache[cacheKey];
+
+ if (!parsedExpression) {
+ if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
+ oneTime = true;
+ exp = exp.substring(2);
+ }
+ var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
+ var lexer = new Lexer(parseOptions);
+ var parser = new Parser(lexer, $filter, parseOptions);
+ parsedExpression = parser.parse(exp);
+ if (parsedExpression.constant) {
+ parsedExpression.$$watchDelegate = constantWatchDelegate;
+ } else if (oneTime) {
+ parsedExpression.$$watchDelegate = parsedExpression.literal ?
+ oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
+ } else if (parsedExpression.inputs) {
+ parsedExpression.$$watchDelegate = inputsWatchDelegate;
+ }
+ cache[cacheKey] = parsedExpression;
+ }
+ return addInterceptor(parsedExpression, interceptorFn);
+
+ case 'function':
+ return addInterceptor(exp, interceptorFn);
+
+ default:
+ return noop;
+ }
+ };
+
+ function expressionInputDirtyCheck(newValue, oldValueOfValue) {
+
+ if (newValue == null || oldValueOfValue == null) { // null/undefined
+ return newValue === oldValueOfValue;
+ }
+
+ if (typeof newValue === 'object') {
+
+ // attempt to convert the value to a primitive type
+ // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
+ // be cheaply dirty-checked
+ newValue = getValueOf(newValue);
+
+ if (typeof newValue === 'object') {
+ // objects/arrays are not supported - deep-watching them would be too expensive
+ return false;
+ }
+
+ // fall-through to the primitive equality check
+ }
+
+ //Primitive or NaN
+ return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
+ }
+
+ function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
+ var inputExpressions = parsedExpression.inputs;
+ var lastResult;
+
+ if (inputExpressions.length === 1) {
+ var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ inputExpressions = inputExpressions[0];
+ return scope.$watch(function expressionInputWatch(scope) {
+ var newInputValue = inputExpressions(scope);
+ if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
+ lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
+ oldInputValueOf = newInputValue && getValueOf(newInputValue);
+ }
+ return lastResult;
+ }, listener, objectEquality, prettyPrintExpression);
+ }
+
+ var oldInputValueOfValues = [];
+ var oldInputValues = [];
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
+ oldInputValues[i] = null;
+ }
+
+ return scope.$watch(function expressionInputsWatch(scope) {
+ var changed = false;
+
+ for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
+ var newInputValue = inputExpressions[i](scope);
+ if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
+ oldInputValues[i] = newInputValue;
+ oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
+ }
+ }
+
+ if (changed) {
+ lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
+ }
+
+ return lastResult;
+ }, listener, objectEquality, prettyPrintExpression);
+ }
+
+ function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ if (isDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isDefined(lastValue)) {
+ unwatch();
+ }
+ });
+ }
+ }, objectEquality);
+ }
+
+ function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch, lastValue;
+ return unwatch = scope.$watch(function oneTimeWatch(scope) {
+ return parsedExpression(scope);
+ }, function oneTimeListener(value, old, scope) {
+ lastValue = value;
+ if (isFunction(listener)) {
+ listener.call(this, value, old, scope);
+ }
+ if (isAllDefined(value)) {
+ scope.$$postDigest(function() {
+ if (isAllDefined(lastValue)) unwatch();
+ });
+ }
+ }, objectEquality);
+
+ function isAllDefined(value) {
+ var allDefined = true;
+ forEach(value, function(val) {
+ if (!isDefined(val)) allDefined = false;
+ });
+ return allDefined;
+ }
+ }
+
+ function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
+ var unwatch;
+ return unwatch = scope.$watch(function constantWatch(scope) {
+ return parsedExpression(scope);
+ }, function constantListener(value, old, scope) {
+ if (isFunction(listener)) {
+ listener.apply(this, arguments);
+ }
+ unwatch();
+ }, objectEquality);
+ }
+
+ function addInterceptor(parsedExpression, interceptorFn) {
+ if (!interceptorFn) return parsedExpression;
+ var watchDelegate = parsedExpression.$$watchDelegate;
+ var useInputs = false;
+
+ var regularWatch =
+ watchDelegate !== oneTimeLiteralWatchDelegate &&
+ watchDelegate !== oneTimeWatchDelegate;
+
+ var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
+ var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
+ return interceptorFn(value, scope, locals);
+ } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
+ var value = parsedExpression(scope, locals, assign, inputs);
+ var result = interceptorFn(value, scope, locals);
+ // we only return the interceptor's result if the
+ // initial value is defined (for bind-once)
+ return isDefined(value) ? result : value;
+ };
+
+ // Propagate $$watchDelegates other then inputsWatchDelegate
+ if (parsedExpression.$$watchDelegate &&
+ parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
+ fn.$$watchDelegate = parsedExpression.$$watchDelegate;
+ } else if (!interceptorFn.$stateful) {
+ // If there is an interceptor, but no watchDelegate then treat the interceptor like
+ // we treat filters - it is assumed to be a pure function unless flagged with $stateful
+ fn.$$watchDelegate = inputsWatchDelegate;
+ useInputs = !parsedExpression.inputs;
+ fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
+ }
+
+ return fn;
+ }
+ }];
+}
+
+/**
+ * @ngdoc service
+ * @name $q
+ * @requires $rootScope
+ *
+ * @description
+ * A service that helps you run functions asynchronously, and use their return values (or exceptions)
+ * when they are done processing.
+ *
+ * This is an implementation of promises/deferred objects inspired by
+ * [Kris Kowal's Q](https://github.com/kriskowal/q).
+ *
+ * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
+ * implementations, and the other which resembles ES6 promises to some degree.
+ *
+ * # $q constructor
+ *
+ * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
+ * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
+ * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
+ *
+ * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
+ * available yet.
+ *
+ * It can be used like so:
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * // perform some asynchronous operation, resolve or reject the promise when appropriate.
+ * return $q(function(resolve, reject) {
+ * setTimeout(function() {
+ * if (okToGreet(name)) {
+ * resolve('Hello, ' + name + '!');
+ * } else {
+ * reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ * });
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * });
+ * ```
+ *
+ * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
+ *
+ * Note: unlike ES6 behaviour, an exception thrown in the constructor function will NOT implicitly reject the promise.
+ *
+ * However, the more traditional CommonJS-style usage is still available, and documented below.
+ *
+ * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
+ * interface for interacting with an object that represents the result of an action that is
+ * performed asynchronously, and may or may not be finished at any given point in time.
+ *
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
+ * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
+ *
+ * ```js
+ * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
+ * // are available in the current lexical scope (they could have been injected or passed in).
+ *
+ * function asyncGreet(name) {
+ * var deferred = $q.defer();
+ *
+ * setTimeout(function() {
+ * deferred.notify('About to greet ' + name + '.');
+ *
+ * if (okToGreet(name)) {
+ * deferred.resolve('Hello, ' + name + '!');
+ * } else {
+ * deferred.reject('Greeting ' + name + ' is not allowed.');
+ * }
+ * }, 1000);
+ *
+ * return deferred.promise;
+ * }
+ *
+ * var promise = asyncGreet('Robin Hood');
+ * promise.then(function(greeting) {
+ * alert('Success: ' + greeting);
+ * }, function(reason) {
+ * alert('Failed: ' + reason);
+ * }, function(update) {
+ * alert('Got notification: ' + update);
+ * });
+ * ```
+ *
+ * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
+ * comes in the way of guarantees that promise and deferred APIs make, see
+ * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
+ *
+ * Additionally the promise api allows for composition that is very hard to do with the
+ * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
+ * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
+ * section on serial or parallel joining of promises.
+ *
+ * # The Deferred API
+ *
+ * A new instance of deferred is constructed by calling `$q.defer()`.
+ *
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
+ * that can be used for signaling the successful or unsuccessful completion, as well as the status
+ * of the task.
+ *
+ * **Methods**
+ *
+ * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
+ * constructed via `$q.reject`, the promise will be rejected instead.
+ * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
+ * resolving it with a rejection constructed via `$q.reject`.
+ * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
+ * multiple times before the promise is either resolved or rejected.
+ *
+ * **Properties**
+ *
+ * - promise – `{Promise}` – promise object associated with this deferred.
+ *
+ *
+ * # The Promise API
+ *
+ * A new promise instance is created when a deferred instance is created and can be retrieved by
+ * calling `deferred.promise`.
+ *
+ * The purpose of the promise object is to allow for interested parties to get access to the result
+ * of the deferred task when it completes.
+ *
+ * **Methods**
+ *
+ * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
+ * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
+ * as soon as the result is available. The callbacks are called with a single argument: the result
+ * or rejection reason. Additionally, the notify callback may be called zero or more times to
+ * provide a progress indication, before the promise is resolved or rejected.
+ *
+ * This method *returns a new promise* which is resolved or rejected via the return value of the
+ * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved
+ * with the value which is resolved in that promise using
+ * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).
+ * It also notifies via the return value of the `notifyCallback` method. The promise cannot be
+ * resolved or rejected from the notifyCallback method.
+ *
+ * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
+ *
+ * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
+ * but to do so without modifying the final value. This is useful to release resources or do some
+ * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
+ * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
+ * more information.
+ *
+ * # Chaining promises
+ *
+ * Because calling the `then` method of a promise returns a new derived promise, it is easily
+ * possible to create a chain of promises:
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * return result + 1;
+ * });
+ *
+ * // promiseB will be resolved immediately after promiseA is resolved and its value
+ * // will be the result of promiseA incremented by 1
+ * ```
+ *
+ * It is possible to create chains of any length and since a promise can be resolved with another
+ * promise (which will defer its resolution further), it is possible to pause/defer resolution of
+ * the promises at any point in the chain. This makes it possible to implement powerful APIs like
+ * $http's response interceptors.
+ *
+ *
+ * # Differences between Kris Kowal's Q and $q
+ *
+ * There are two main differences:
+ *
+ * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
+ * mechanism in angular, which means faster propagation of resolution or rejection into your
+ * models and avoiding unnecessary browser repaints, which would result in flickering UI.
+ * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
+ * all the important functionality needed for common async tasks.
+ *
+ * # Testing
+ *
+ * ```js
+ * it('should simulate promise', inject(function($q, $rootScope) {
+ * var deferred = $q.defer();
+ * var promise = deferred.promise;
+ * var resolvedValue;
+ *
+ * promise.then(function(value) { resolvedValue = value; });
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Simulate resolving of promise
+ * deferred.resolve(123);
+ * // Note that the 'then' function does not get called synchronously.
+ * // This is because we want the promise API to always be async, whether or not
+ * // it got called synchronously or asynchronously.
+ * expect(resolvedValue).toBeUndefined();
+ *
+ * // Propagate promise resolution to 'then' functions using $apply().
+ * $rootScope.$apply();
+ * expect(resolvedValue).toEqual(123);
+ * }));
+ * ```
+ *
+ * @param {function(function, function)} resolver Function which is responsible for resolving or
+ * rejecting the newly created promise. The first parameter is a function which resolves the
+ * promise, the second parameter is a function which rejects the promise.
+ *
+ * @returns {Promise} The newly created promise.
+ */
+function $QProvider() {
+
+ this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $rootScope.$evalAsync(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+function $$QProvider() {
+ this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
+ return qFactory(function(callback) {
+ $browser.defer(callback);
+ }, $exceptionHandler);
+ }];
+}
+
+/**
+ * Constructs a promise manager.
+ *
+ * @param {function(function)} nextTick Function for executing functions in the next turn.
+ * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
+ * debugging purposes.
+ * @returns {object} Promise manager.
+ */
+function qFactory(nextTick, exceptionHandler) {
+ var $qMinErr = minErr('$q', TypeError);
+ function callOnce(self, resolveFn, rejectFn) {
+ var called = false;
+ function wrap(fn) {
+ return function(value) {
+ if (called) return;
+ called = true;
+ fn.call(self, value);
+ };
+ }
+
+ return [wrap(resolveFn), wrap(rejectFn)];
+ }
+
+ /**
+ * @ngdoc method
+ * @name ng.$q#defer
+ * @kind function
+ *
+ * @description
+ * Creates a `Deferred` object which represents a task which will finish in the future.
+ *
+ * @returns {Deferred} Returns a new instance of deferred.
+ */
+ var defer = function() {
+ return new Deferred();
+ };
+
+ function Promise() {
+ this.$$state = { status: 0 };
+ }
+
+ extend(Promise.prototype, {
+ then: function(onFulfilled, onRejected, progressBack) {
+ if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
+ return this;
+ }
+ var result = new Deferred();
+
+ this.$$state.pending = this.$$state.pending || [];
+ this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
+ if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
+
+ return result.promise;
+ },
+
+ "catch": function(callback) {
+ return this.then(null, callback);
+ },
+
+ "finally": function(callback, progressBack) {
+ return this.then(function(value) {
+ return handleCallback(value, true, callback);
+ }, function(error) {
+ return handleCallback(error, false, callback);
+ }, progressBack);
+ }
+ });
+
+ //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
+ function simpleBind(context, fn) {
+ return function(value) {
+ fn.call(context, value);
+ };
+ }
+
+ function processQueue(state) {
+ var fn, deferred, pending;
+
+ pending = state.pending;
+ state.processScheduled = false;
+ state.pending = undefined;
+ for (var i = 0, ii = pending.length; i < ii; ++i) {
+ deferred = pending[i][0];
+ fn = pending[i][state.status];
+ try {
+ if (isFunction(fn)) {
+ deferred.resolve(fn(state.value));
+ } else if (state.status === 1) {
+ deferred.resolve(state.value);
+ } else {
+ deferred.reject(state.value);
+ }
+ } catch (e) {
+ deferred.reject(e);
+ exceptionHandler(e);
+ }
+ }
+ }
+
+ function scheduleProcessQueue(state) {
+ if (state.processScheduled || !state.pending) return;
+ state.processScheduled = true;
+ nextTick(function() { processQueue(state); });
+ }
+
+ function Deferred() {
+ this.promise = new Promise();
+ //Necessary to support unbound execution :/
+ this.resolve = simpleBind(this, this.resolve);
+ this.reject = simpleBind(this, this.reject);
+ this.notify = simpleBind(this, this.notify);
+ }
+
+ extend(Deferred.prototype, {
+ resolve: function(val) {
+ if (this.promise.$$state.status) return;
+ if (val === this.promise) {
+ this.$$reject($qMinErr(
+ 'qcycle',
+ "Expected promise to be resolved with value other than itself '{0}'",
+ val));
+ } else {
+ this.$$resolve(val);
+ }
+
+ },
+
+ $$resolve: function(val) {
+ var then, fns;
+
+ fns = callOnce(this, this.$$resolve, this.$$reject);
+ try {
+ if ((isObject(val) || isFunction(val))) then = val && val.then;
+ if (isFunction(then)) {
+ this.promise.$$state.status = -1;
+ then.call(val, fns[0], fns[1], this.notify);
+ } else {
+ this.promise.$$state.value = val;
+ this.promise.$$state.status = 1;
+ scheduleProcessQueue(this.promise.$$state);
+ }
+ } catch (e) {
+ fns[1](e);
+ exceptionHandler(e);
+ }
+ },
+
+ reject: function(reason) {
+ if (this.promise.$$state.status) return;
+ this.$$reject(reason);
+ },
+
+ $$reject: function(reason) {
+ this.promise.$$state.value = reason;
+ this.promise.$$state.status = 2;
+ scheduleProcessQueue(this.promise.$$state);
+ },
+
+ notify: function(progress) {
+ var callbacks = this.promise.$$state.pending;
+
+ if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
+ nextTick(function() {
+ var callback, result;
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
+ result = callbacks[i][0];
+ callback = callbacks[i][3];
+ try {
+ result.notify(isFunction(callback) ? callback(progress) : progress);
+ } catch (e) {
+ exceptionHandler(e);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ /**
+ * @ngdoc method
+ * @name $q#reject
+ * @kind function
+ *
+ * @description
+ * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
+ * used to forward rejection in a chain of promises. If you are dealing with the last promise in
+ * a promise chain, you don't need to worry about it.
+ *
+ * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
+ * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
+ * a promise error callback and you want to forward the error to the promise derived from the
+ * current promise, you have to "rethrow" the error by returning a rejection constructed via
+ * `reject`.
+ *
+ * ```js
+ * promiseB = promiseA.then(function(result) {
+ * // success: do something and resolve promiseB
+ * // with the old or a new result
+ * return result;
+ * }, function(reason) {
+ * // error: handle the error if possible and
+ * // resolve promiseB with newPromiseOrValue,
+ * // otherwise forward the rejection to promiseB
+ * if (canHandle(reason)) {
+ * // handle the error and recover
+ * return newPromiseOrValue;
+ * }
+ * return $q.reject(reason);
+ * });
+ * ```
+ *
+ * @param {*} reason Constant, message, exception or an object representing the rejection reason.
+ * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
+ */
+ var reject = function(reason) {
+ var result = new Deferred();
+ result.reject(reason);
+ return result.promise;
+ };
+
+ var makePromise = function makePromise(value, resolved) {
+ var result = new Deferred();
+ if (resolved) {
+ result.resolve(value);
+ } else {
+ result.reject(value);
+ }
+ return result.promise;
+ };
+
+ var handleCallback = function handleCallback(value, isResolved, callback) {
+ var callbackOutput = null;
+ try {
+ if (isFunction(callback)) callbackOutput = callback();
+ } catch (e) {
+ return makePromise(e, false);
+ }
+ if (isPromiseLike(callbackOutput)) {
+ return callbackOutput.then(function() {
+ return makePromise(value, isResolved);
+ }, function(error) {
+ return makePromise(error, false);
+ });
+ } else {
+ return makePromise(value, isResolved);
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#when
+ * @kind function
+ *
+ * @description
+ * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
+ * the promise comes from a source that can't be trusted.
+ *
+ * @param {*} value Value or a promise
+ * @param {Function=} successCallback
+ * @param {Function=} errorCallback
+ * @param {Function=} progressCallback
+ * @returns {Promise} Returns a promise of the passed value or promise
+ */
+
+
+ var when = function(value, callback, errback, progressBack) {
+ var result = new Deferred();
+ result.resolve(value);
+ return result.promise.then(callback, errback, progressBack);
+ };
+
+ /**
+ * @ngdoc method
+ * @name $q#resolve
+ * @kind function
+ *
+ * @description
+ * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
+ *
+ * @param {*} value Value or a promise
+ * @param {Function=} successCallback
+ * @param {Function=} errorCallback
+ * @param {Function=} progressCallback
+ * @returns {Promise} Returns a promise of the passed value or promise
+ */
+ var resolve = when;
+
+ /**
+ * @ngdoc method
+ * @name $q#all
+ * @kind function
+ *
+ * @description
+ * Combines multiple promises into a single promise that is resolved when all of the input
+ * promises are resolved.
+ *
+ * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
+ * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
+ * each value corresponding to the promise at the same index/key in the `promises` array/hash.
+ * If any of the promises is resolved with a rejection, this resulting promise will be rejected
+ * with the same rejection value.
+ */
+
+ function all(promises) {
+ var deferred = new Deferred(),
+ counter = 0,
+ results = isArray(promises) ? [] : {};
+
+ forEach(promises, function(promise, key) {
+ counter++;
+ when(promise).then(function(value) {
+ if (results.hasOwnProperty(key)) return;
+ results[key] = value;
+ if (!(--counter)) deferred.resolve(results);
+ }, function(reason) {
+ if (results.hasOwnProperty(key)) return;
+ deferred.reject(reason);
+ });
+ });
+
+ if (counter === 0) {
+ deferred.resolve(results);
+ }
+
+ return deferred.promise;
+ }
+
+ var $Q = function Q(resolver) {
+ if (!isFunction(resolver)) {
+ throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
+ }
+
+ if (!(this instanceof Q)) {
+ // More useful when $Q is the Promise itself.
+ return new Q(resolver);
+ }
+
+ var deferred = new Deferred();
+
+ function resolveFn(value) {
+ deferred.resolve(value);
+ }
+
+ function rejectFn(reason) {
+ deferred.reject(reason);
+ }
+
+ resolver(resolveFn, rejectFn);
+
+ return deferred.promise;
+ };
+
+ $Q.defer = defer;
+ $Q.reject = reject;
+ $Q.when = when;
+ $Q.resolve = resolve;
+ $Q.all = all;
+
+ return $Q;
+}
+
+function $$RAFProvider() { //rAF
+ this.$get = ['$window', '$timeout', function($window, $timeout) {
+ var requestAnimationFrame = $window.requestAnimationFrame ||
+ $window.webkitRequestAnimationFrame;
+
+ var cancelAnimationFrame = $window.cancelAnimationFrame ||
+ $window.webkitCancelAnimationFrame ||
+ $window.webkitCancelRequestAnimationFrame;
+
+ var rafSupported = !!requestAnimationFrame;
+ var raf = rafSupported
+ ? function(fn) {
+ var id = requestAnimationFrame(fn);
+ return function() {
+ cancelAnimationFrame(id);
+ };
+ }
+ : function(fn) {
+ var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
+ return function() {
+ $timeout.cancel(timer);
+ };
+ };
+
+ raf.supported = rafSupported;
+
+ return raf;
+ }];
+}
+
+/**
+ * DESIGN NOTES
+ *
+ * The design decisions behind the scope are heavily favored for speed and memory consumption.
+ *
+ * The typical use of scope is to watch the expressions, which most of the time return the same
+ * value as last time so we optimize the operation.
+ *
+ * Closures construction is expensive in terms of speed as well as memory:
+ * - No closures, instead use prototypical inheritance for API
+ * - Internal state needs to be stored on scope directly, which means that private state is
+ * exposed as $$____ properties
+ *
+ * Loop operations are optimized by using while(count--) { ... }
+ * - This means that in order to keep the same order of execution as addition we have to add
+ * items to the array at the beginning (unshift) instead of at the end (push)
+ *
+ * Child scopes are created and removed often
+ * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists
+ *
+ * There are fewer watches than observers. This is why you don't want the observer to be implemented
+ * in the same way as watch. Watch requires return of the initialization function which is expensive
+ * to construct.
+ */
+
+
+/**
+ * @ngdoc provider
+ * @name $rootScopeProvider
+ * @description
+ *
+ * Provider for the $rootScope service.
+ */
+
+/**
+ * @ngdoc method
+ * @name $rootScopeProvider#digestTtl
+ * @description
+ *
+ * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
+ * assuming that the model is unstable.
+ *
+ * The current default is 10 iterations.
+ *
+ * In complex applications it's possible that the dependencies between `$watch`s will result in
+ * several digest iterations. However if an application needs more than the default 10 digest
+ * iterations for its model to stabilize then you should investigate what is causing the model to
+ * continuously change during the digest.
+ *
+ * Increasing the TTL could have performance implications, so you should not change it without
+ * proper justification.
+ *
+ * @param {number} limit The number of digest iterations.
+ */
+
+
+/**
+ * @ngdoc service
+ * @name $rootScope
+ * @description
+ *
+ * Every application has a single root {@link ng.$rootScope.Scope scope}.
+ * All other scopes are descendant scopes of the root scope. Scopes provide separation
+ * between the model and the view, via a mechanism for watching the model for changes.
+ * They also provide event emission/broadcast and subscription facility. See the
+ * {@link guide/scope developer guide on scopes}.
+ */
+function $RootScopeProvider() {
+ var TTL = 10;
+ var $rootScopeMinErr = minErr('$rootScope');
+ var lastDirtyWatch = null;
+ var applyAsyncId = null;
+
+ this.digestTtl = function(value) {
+ if (arguments.length) {
+ TTL = value;
+ }
+ return TTL;
+ };
+
+ function createChildScopeClass(parent) {
+ function ChildScope() {
+ this.$$watchers = this.$$nextSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$$watchersCount = 0;
+ this.$id = nextUid();
+ this.$$ChildScope = null;
+ }
+ ChildScope.prototype = parent;
+ return ChildScope;
+ }
+
+ this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
+ function($injector, $exceptionHandler, $parse, $browser) {
+
+ function destroyChildScope($event) {
+ $event.currentScope.$$destroyed = true;
+ }
+
+ function cleanUpScope($scope) {
+
+ if (msie === 9) {
+ // There is a memory leak in IE9 if all child scopes are not disconnected
+ // completely when a scope is destroyed. So this code will recurse up through
+ // all this scopes children
+ //
+ // See issue https://github.com/angular/angular.js/issues/10706
+ $scope.$$childHead && cleanUpScope($scope.$$childHead);
+ $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);
+ }
+
+ // The code below works around IE9 and V8's memory leaks
+ //
+ // See:
+ // - https://code.google.com/p/v8/issues/detail?id=2073#c26
+ // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
+ // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
+
+ $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
+ $scope.$$childTail = $scope.$root = $scope.$$watchers = null;
+ }
+
+ /**
+ * @ngdoc type
+ * @name $rootScope.Scope
+ *
+ * @description
+ * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
+ * {@link auto.$injector $injector}. Child scopes are created using the
+ * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
+ * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
+ * an in-depth introduction and usage examples.
+ *
+ *
+ * # Inheritance
+ * A scope can inherit from a parent scope, as in this example:
+ * ```js
+ var parent = $rootScope;
+ var child = parent.$new();
+
+ parent.salutation = "Hello";
+ expect(child.salutation).toEqual('Hello');
+
+ child.salutation = "Welcome";
+ expect(child.salutation).toEqual('Welcome');
+ expect(parent.salutation).toEqual('Hello');
+ * ```
+ *
+ * When interacting with `Scope` in tests, additional helper methods are available on the
+ * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
+ * details.
+ *
+ *
+ * @param {Object.<string, function()>=} providers Map of service factory which need to be
+ * provided for the current scope. Defaults to {@link ng}.
+ * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
+ * append/override services provided by `providers`. This is handy
+ * when unit-testing and having the need to override a default
+ * service.
+ * @returns {Object} Newly created scope.
+ *
+ */
+ function Scope() {
+ this.$id = nextUid();
+ this.$$phase = this.$parent = this.$$watchers =
+ this.$$nextSibling = this.$$prevSibling =
+ this.$$childHead = this.$$childTail = null;
+ this.$root = this;
+ this.$$destroyed = false;
+ this.$$listeners = {};
+ this.$$listenerCount = {};
+ this.$$watchersCount = 0;
+ this.$$isolateBindings = null;
+ }
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$id
+ *
+ * @description
+ * Unique scope ID (monotonically increasing) useful for debugging.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$parent
+ *
+ * @description
+ * Reference to the parent scope.
+ */
+
+ /**
+ * @ngdoc property
+ * @name $rootScope.Scope#$root
+ *
+ * @description
+ * Reference to the root scope.
+ */
+
+ Scope.prototype = {
+ constructor: Scope,
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$new
+ * @kind function
+ *
+ * @description
+ * Creates a new child {@link ng.$rootScope.Scope scope}.
+ *
+ * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
+ * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
+ *
+ * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
+ * desired for the scope and its child scopes to be permanently detached from the parent and
+ * thus stop participating in model change detection and listener notification by invoking.
+ *
+ * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
+ * parent scope. The scope is isolated, as it can not see parent scope properties.
+ * When creating widgets, it is useful for the widget to not accidentally read parent
+ * state.
+ *
+ * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
+ * of the newly created scope. Defaults to `this` scope if not provided.
+ * This is used when creating a transclude scope to correctly place it
+ * in the scope hierarchy while maintaining the correct prototypical
+ * inheritance.
+ *
+ * @returns {Object} The newly created child scope.
+ *
+ */
+ $new: function(isolate, parent) {
+ var child;
+
+ parent = parent || this;
+
+ if (isolate) {
+ child = new Scope();
+ child.$root = this.$root;
+ } else {
+ // Only create a child scope class if somebody asks for one,
+ // but cache it to allow the VM to optimize lookups.
+ if (!this.$$ChildScope) {
+ this.$$ChildScope = createChildScopeClass(this);
+ }
+ child = new this.$$ChildScope();
+ }
+ child.$parent = parent;
+ child.$$prevSibling = parent.$$childTail;
+ if (parent.$$childHead) {
+ parent.$$childTail.$$nextSibling = child;
+ parent.$$childTail = child;
+ } else {
+ parent.$$childHead = parent.$$childTail = child;
+ }
+
+ // When the new scope is not isolated or we inherit from `this`, and
+ // the parent scope is destroyed, the property `$$destroyed` is inherited
+ // prototypically. In all other cases, this property needs to be set
+ // when the parent scope is destroyed.
+ // The listener needs to be added after the parent is set
+ if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
+
+ return child;
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watch
+ * @kind function
+ *
+ * @description
+ * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
+ *
+ * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
+ * $digest()} and should return the value that will be watched. (`watchExpression` should not change
+ * its value when executed multiple times with the same input because it may be executed multiple
+ * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
+ * [idempotent](http://en.wikipedia.org/wiki/Idempotence).
+ * - The `listener` is called only when the value from the current `watchExpression` and the
+ * previous call to `watchExpression` are not equal (with the exception of the initial run,
+ * see below). Inequality is determined according to reference inequality,
+ * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
+ * via the `!==` Javascript operator, unless `objectEquality == true`
+ * (see next point)
+ * - When `objectEquality == true`, inequality of the `watchExpression` is determined
+ * according to the {@link angular.equals} function. To save the value of the object for
+ * later comparison, the {@link angular.copy} function is used. This therefore means that
+ * watching complex objects will have adverse memory and performance implications.
+ * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
+ * This is achieved by rerunning the watchers until no changes are detected. The rerun
+ * iteration limit is 10 to prevent an infinite loop deadlock.
+ *
+ *
+ * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
+ * you can register a `watchExpression` function with no `listener`. (Be prepared for
+ * multiple calls to your `watchExpression` because it will execute multiple times in a
+ * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
+ *
+ * After a watcher is registered with the scope, the `listener` fn is called asynchronously
+ * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
+ * watcher. In rare cases, this is undesirable because the listener is called when the result
+ * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
+ * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
+ * listener was called due to initialization.
+ *
+ *
+ *
+ * # Example
+ * ```js
+ // let's assume that scope was dependency injected as the $rootScope
+ var scope = $rootScope;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+
+
+
+ // Using a function as a watchExpression
+ var food;
+ scope.foodCounter = 0;
+ expect(scope.foodCounter).toEqual(0);
+ scope.$watch(
+ // This function returns the value being watched. It is called for each turn of the $digest loop
+ function() { return food; },
+ // This is the change listener, called when the value returned from the above function changes
+ function(newValue, oldValue) {
+ if ( newValue !== oldValue ) {
+ // Only increment the counter if the value changed
+ scope.foodCounter = scope.foodCounter + 1;
+ }
+ }
+ );
+ // No digest has been run so the counter will be zero
+ expect(scope.foodCounter).toEqual(0);
+
+ // Run the digest but since food has not changed count will still be zero
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(0);
+
+ // Update food and run digest. Now the counter will increment
+ food = 'cheeseburger';
+ scope.$digest();
+ expect(scope.foodCounter).toEqual(1);
+
+ * ```
+ *
+ *
+ *
+ * @param {(function()|string)} watchExpression Expression that is evaluated on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
+ * a call to the `listener`.
+ *
+ * - `string`: Evaluated as {@link guide/expression expression}
+ * - `function(scope)`: called with current `scope` as a parameter.
+ * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
+ * of `watchExpression` changes.
+ *
+ * - `newVal` contains the current value of the `watchExpression`
+ * - `oldVal` contains the previous value of the `watchExpression`
+ * - `scope` refers to the current scope
+ * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
+ * comparing for reference equality.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {
+ var get = $parse(watchExp);
+
+ if (get.$$watchDelegate) {
+ return get.$$watchDelegate(this, listener, objectEquality, get, watchExp);
+ }
+ var scope = this,
+ array = scope.$$watchers,
+ watcher = {
+ fn: listener,
+ last: initWatchVal,
+ get: get,
+ exp: prettyPrintExpression || watchExp,
+ eq: !!objectEquality
+ };
+
+ lastDirtyWatch = null;
+
+ if (!isFunction(listener)) {
+ watcher.fn = noop;
+ }
+
+ if (!array) {
+ array = scope.$$watchers = [];
+ }
+ // we use unshift since we use a while loop in $digest for speed.
+ // the while loop reads in reverse order.
+ array.unshift(watcher);
+ incrementWatchersCount(this, 1);
+
+ return function deregisterWatch() {
+ if (arrayRemove(array, watcher) >= 0) {
+ incrementWatchersCount(scope, -1);
+ }
+ lastDirtyWatch = null;
+ };
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchGroup
+ * @kind function
+ *
+ * @description
+ * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
+ * If any one expression in the collection changes the `listener` is executed.
+ *
+ * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
+ * call to $digest() to see if any items changes.
+ * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
+ *
+ * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
+ * watched using {@link ng.$rootScope.Scope#$watch $watch()}
+ *
+ * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
+ * expression in `watchExpressions` changes
+ * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
+ * those of `watchExpression`
+ * The `scope` refers to the current scope.
+ * @returns {function()} Returns a de-registration function for all listeners.
+ */
+ $watchGroup: function(watchExpressions, listener) {
+ var oldValues = new Array(watchExpressions.length);
+ var newValues = new Array(watchExpressions.length);
+ var deregisterFns = [];
+ var self = this;
+ var changeReactionScheduled = false;
+ var firstRun = true;
+
+ if (!watchExpressions.length) {
+ // No expressions means we call the listener ASAP
+ var shouldCall = true;
+ self.$evalAsync(function() {
+ if (shouldCall) listener(newValues, newValues, self);
+ });
+ return function deregisterWatchGroup() {
+ shouldCall = false;
+ };
+ }
+
+ if (watchExpressions.length === 1) {
+ // Special case size of one
+ return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
+ newValues[0] = value;
+ oldValues[0] = oldValue;
+ listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
+ });
+ }
+
+ forEach(watchExpressions, function(expr, i) {
+ var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
+ newValues[i] = value;
+ oldValues[i] = oldValue;
+ if (!changeReactionScheduled) {
+ changeReactionScheduled = true;
+ self.$evalAsync(watchGroupAction);
+ }
+ });
+ deregisterFns.push(unwatchFn);
+ });
+
+ function watchGroupAction() {
+ changeReactionScheduled = false;
+
+ if (firstRun) {
+ firstRun = false;
+ listener(newValues, newValues, self);
+ } else {
+ listener(newValues, oldValues, self);
+ }
+ }
+
+ return function deregisterWatchGroup() {
+ while (deregisterFns.length) {
+ deregisterFns.shift()();
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$watchCollection
+ * @kind function
+ *
+ * @description
+ * Shallow watches the properties of an object and fires whenever any of the properties change
+ * (for arrays, this implies watching the array items; for object maps, this implies watching
+ * the properties). If a change is detected, the `listener` callback is fired.
+ *
+ * - The `obj` collection is observed via standard $watch operation and is examined on every
+ * call to $digest() to see if any items have been added, removed, or moved.
+ * - The `listener` is called whenever anything within the `obj` has changed. Examples include
+ * adding, removing, and moving items belonging to an object or array.
+ *
+ *
+ * # Example
+ * ```js
+ $scope.names = ['igor', 'matias', 'misko', 'james'];
+ $scope.dataCount = 4;
+
+ $scope.$watchCollection('names', function(newNames, oldNames) {
+ $scope.dataCount = newNames.length;
+ });
+
+ expect($scope.dataCount).toEqual(4);
+ $scope.$digest();
+
+ //still at 4 ... no changes
+ expect($scope.dataCount).toEqual(4);
+
+ $scope.names.pop();
+ $scope.$digest();
+
+ //now there's been a change
+ expect($scope.dataCount).toEqual(3);
+ * ```
+ *
+ *
+ * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
+ * expression value should evaluate to an object or an array which is observed on each
+ * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
+ * collection will trigger a call to the `listener`.
+ *
+ * @param {function(newCollection, oldCollection, scope)} listener a callback function called
+ * when a change is detected.
+ * - The `newCollection` object is the newly modified data obtained from the `obj` expression
+ * - The `oldCollection` object is a copy of the former collection data.
+ * Due to performance considerations, the`oldCollection` value is computed only if the
+ * `listener` function declares two or more arguments.
+ * - The `scope` argument refers to the current scope.
+ *
+ * @returns {function()} Returns a de-registration function for this listener. When the
+ * de-registration function is executed, the internal watch operation is terminated.
+ */
+ $watchCollection: function(obj, listener) {
+ $watchCollectionInterceptor.$stateful = true;
+
+ var self = this;
+ // the current value, updated on each dirty-check run
+ var newValue;
+ // a shallow copy of the newValue from the last dirty-check run,
+ // updated to match newValue during dirty-check run
+ var oldValue;
+ // a shallow copy of the newValue from when the last change happened
+ var veryOldValue;
+ // only track veryOldValue if the listener is asking for it
+ var trackVeryOldValue = (listener.length > 1);
+ var changeDetected = 0;
+ var changeDetector = $parse(obj, $watchCollectionInterceptor);
+ var internalArray = [];
+ var internalObject = {};
+ var initRun = true;
+ var oldLength = 0;
+
+ function $watchCollectionInterceptor(_value) {
+ newValue = _value;
+ var newLength, key, bothNaN, newItem, oldItem;
+
+ // If the new value is undefined, then return undefined as the watch may be a one-time watch
+ if (isUndefined(newValue)) return;
+
+ if (!isObject(newValue)) { // if primitive
+ if (oldValue !== newValue) {
+ oldValue = newValue;
+ changeDetected++;
+ }
+ } else if (isArrayLike(newValue)) {
+ if (oldValue !== internalArray) {
+ // we are transitioning from something which was not an array into array.
+ oldValue = internalArray;
+ oldLength = oldValue.length = 0;
+ changeDetected++;
+ }
+
+ newLength = newValue.length;
+
+ if (oldLength !== newLength) {
+ // if lengths do not match we need to trigger change notification
+ changeDetected++;
+ oldValue.length = oldLength = newLength;
+ }
+ // copy the items to oldValue and look for changes.
+ for (var i = 0; i < newLength; i++) {
+ oldItem = oldValue[i];
+ newItem = newValue[i];
+
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[i] = newItem;
+ }
+ }
+ } else {
+ if (oldValue !== internalObject) {
+ // we are transitioning from something which was not an object into object.
+ oldValue = internalObject = {};
+ oldLength = 0;
+ changeDetected++;
+ }
+ // copy the items to oldValue and look for changes.
+ newLength = 0;
+ for (key in newValue) {
+ if (hasOwnProperty.call(newValue, key)) {
+ newLength++;
+ newItem = newValue[key];
+ oldItem = oldValue[key];
+
+ if (key in oldValue) {
+ bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
+ if (!bothNaN && (oldItem !== newItem)) {
+ changeDetected++;
+ oldValue[key] = newItem;
+ }
+ } else {
+ oldLength++;
+ oldValue[key] = newItem;
+ changeDetected++;
+ }
+ }
+ }
+ if (oldLength > newLength) {
+ // we used to have more keys, need to find them and destroy them.
+ changeDetected++;
+ for (key in oldValue) {
+ if (!hasOwnProperty.call(newValue, key)) {
+ oldLength--;
+ delete oldValue[key];
+ }
+ }
+ }
+ }
+ return changeDetected;
+ }
+
+ function $watchCollectionAction() {
+ if (initRun) {
+ initRun = false;
+ listener(newValue, newValue, self);
+ } else {
+ listener(newValue, veryOldValue, self);
+ }
+
+ // make a copy for the next time a collection is changed
+ if (trackVeryOldValue) {
+ if (!isObject(newValue)) {
+ //primitive
+ veryOldValue = newValue;
+ } else if (isArrayLike(newValue)) {
+ veryOldValue = new Array(newValue.length);
+ for (var i = 0; i < newValue.length; i++) {
+ veryOldValue[i] = newValue[i];
+ }
+ } else { // if object
+ veryOldValue = {};
+ for (var key in newValue) {
+ if (hasOwnProperty.call(newValue, key)) {
+ veryOldValue[key] = newValue[key];
+ }
+ }
+ }
+ }
+ }
+
+ return this.$watch(changeDetector, $watchCollectionAction);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$digest
+ * @kind function
+ *
+ * @description
+ * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
+ * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
+ * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
+ * until no more listeners are firing. This means that it is possible to get into an infinite
+ * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
+ * iterations exceeds 10.
+ *
+ * Usually, you don't call `$digest()` directly in
+ * {@link ng.directive:ngController controllers} or in
+ * {@link ng.$compileProvider#directive directives}.
+ * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
+ * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
+ *
+ * If you want to be notified whenever `$digest()` is called,
+ * you can register a `watchExpression` function with
+ * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
+ *
+ * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
+ *
+ * # Example
+ * ```js
+ var scope = ...;
+ scope.name = 'misko';
+ scope.counter = 0;
+
+ expect(scope.counter).toEqual(0);
+ scope.$watch('name', function(newValue, oldValue) {
+ scope.counter = scope.counter + 1;
+ });
+ expect(scope.counter).toEqual(0);
+
+ scope.$digest();
+ // the listener is always called during the first $digest loop after it was registered
+ expect(scope.counter).toEqual(1);
+
+ scope.$digest();
+ // but now it will not be called unless the value changes
+ expect(scope.counter).toEqual(1);
+
+ scope.name = 'adam';
+ scope.$digest();
+ expect(scope.counter).toEqual(2);
+ * ```
+ *
+ */
+ $digest: function() {
+ var watch, value, last,
+ watchers,
+ length,
+ dirty, ttl = TTL,
+ next, current, target = this,
+ watchLog = [],
+ logIdx, logMsg, asyncTask;
+
+ beginPhase('$digest');
+ // Check for changes to browser url that happened in sync before the call to $digest
+ $browser.$$checkUrlChange();
+
+ if (this === $rootScope && applyAsyncId !== null) {
+ // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
+ // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
+ $browser.defer.cancel(applyAsyncId);
+ flushApplyAsync();
+ }
+
+ lastDirtyWatch = null;
+
+ do { // "while dirty" loop
+ dirty = false;
+ current = target;
+
+ while (asyncQueue.length) {
+ try {
+ asyncTask = asyncQueue.shift();
+ asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ lastDirtyWatch = null;
+ }
+
+ traverseScopesLoop:
+ do { // "traverse the scopes" loop
+ if ((watchers = current.$$watchers)) {
+ // process our watches
+ length = watchers.length;
+ while (length--) {
+ try {
+ watch = watchers[length];
+ // Most common watches are on primitives, in which case we can short
+ // circuit it with === operator, only when === fails do we use .equals
+ if (watch) {
+ if ((value = watch.get(current)) !== (last = watch.last) &&
+ !(watch.eq
+ ? equals(value, last)
+ : (typeof value === 'number' && typeof last === 'number'
+ && isNaN(value) && isNaN(last)))) {
+ dirty = true;
+ lastDirtyWatch = watch;
+ watch.last = watch.eq ? copy(value, null) : value;
+ watch.fn(value, ((last === initWatchVal) ? value : last), current);
+ if (ttl < 5) {
+ logIdx = 4 - ttl;
+ if (!watchLog[logIdx]) watchLog[logIdx] = [];
+ watchLog[logIdx].push({
+ msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
+ newVal: value,
+ oldVal: last
+ });
+ }
+ } else if (watch === lastDirtyWatch) {
+ // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
+ // have already been tested.
+ dirty = false;
+ break traverseScopesLoop;
+ }
+ }
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $broadcast
+ if (!(next = ((current.$$watchersCount && current.$$childHead) ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ } while ((current = next));
+
+ // `break traverseScopesLoop;` takes us to here
+
+ if ((dirty || asyncQueue.length) && !(ttl--)) {
+ clearPhase();
+ throw $rootScopeMinErr('infdig',
+ '{0} $digest() iterations reached. Aborting!\n' +
+ 'Watchers fired in the last 5 iterations: {1}',
+ TTL, watchLog);
+ }
+
+ } while (dirty || asyncQueue.length);
+
+ clearPhase();
+
+ while (postDigestQueue.length) {
+ try {
+ postDigestQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc event
+ * @name $rootScope.Scope#$destroy
+ * @eventType broadcast on scope being destroyed
+ *
+ * @description
+ * Broadcasted when a scope and its children are being destroyed.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$destroy
+ * @kind function
+ *
+ * @description
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
+ * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
+ * propagate to the current scope and its children. Removal also implies that the current
+ * scope is eligible for garbage collection.
+ *
+ * The `$destroy()` is usually used by directives such as
+ * {@link ng.directive:ngRepeat ngRepeat} for managing the
+ * unrolling of the loop.
+ *
+ * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
+ * Application code can register a `$destroy` event handler that will give it a chance to
+ * perform any necessary cleanup.
+ *
+ * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
+ * clean up DOM bindings before an element is removed from the DOM.
+ */
+ $destroy: function() {
+ // We can't destroy a scope that has been already destroyed.
+ if (this.$$destroyed) return;
+ var parent = this.$parent;
+
+ this.$broadcast('$destroy');
+ this.$$destroyed = true;
+
+ if (this === $rootScope) {
+ //Remove handlers attached to window when $rootScope is removed
+ $browser.$$applicationDestroyed();
+ }
+
+ incrementWatchersCount(this, -this.$$watchersCount);
+ for (var eventName in this.$$listenerCount) {
+ decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
+ }
+
+ // sever all the references to parent scopes (after this cleanup, the current scope should
+ // not be retained by any of our references and should be eligible for garbage collection)
+ if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
+ if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
+ if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
+ if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
+
+ // Disable listeners, watchers and apply/digest methods
+ this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
+ this.$on = this.$watch = this.$watchGroup = function() { return noop; };
+ this.$$listeners = {};
+
+ // Disconnect the next sibling to prevent `cleanUpScope` destroying those too
+ this.$$nextSibling = null;
+ cleanUpScope(this);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$eval
+ * @kind function
+ *
+ * @description
+ * Executes the `expression` on the current scope and returns the result. Any exceptions in
+ * the expression are propagated (uncaught). This is useful when evaluating Angular
+ * expressions.
+ *
+ * # Example
+ * ```js
+ var scope = ng.$rootScope.Scope();
+ scope.a = 1;
+ scope.b = 2;
+
+ expect(scope.$eval('a+b')).toEqual(3);
+ expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
+ * ```
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ * @returns {*} The result of evaluating the expression.
+ */
+ $eval: function(expr, locals) {
+ return $parse(expr)(this, locals);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$evalAsync
+ * @kind function
+ *
+ * @description
+ * Executes the expression on the current scope at a later point in time.
+ *
+ * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
+ * that:
+ *
+ * - it will execute after the function that scheduled the evaluation (preferably before DOM
+ * rendering).
+ * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
+ * `expression` execution.
+ *
+ * Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
+ * will be scheduled. However, it is encouraged to always call code that changes the model
+ * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
+ *
+ * @param {(string|function())=} expression An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with the current `scope` parameter.
+ *
+ * @param {(object)=} locals Local variables object, useful for overriding values in scope.
+ */
+ $evalAsync: function(expr, locals) {
+ // if we are outside of an $digest loop and this is the first time we are scheduling async
+ // task also schedule async auto-flush
+ if (!$rootScope.$$phase && !asyncQueue.length) {
+ $browser.defer(function() {
+ if (asyncQueue.length) {
+ $rootScope.$digest();
+ }
+ });
+ }
+
+ asyncQueue.push({scope: this, expression: expr, locals: locals});
+ },
+
+ $$postDigest: function(fn) {
+ postDigestQueue.push(fn);
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$apply
+ * @kind function
+ *
+ * @description
+ * `$apply()` is used to execute an expression in angular from outside of the angular
+ * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
+ * Because we are calling into the angular framework we need to perform proper scope life
+ * cycle of {@link ng.$exceptionHandler exception handling},
+ * {@link ng.$rootScope.Scope#$digest executing watches}.
+ *
+ * ## Life cycle
+ *
+ * # Pseudo-Code of `$apply()`
+ * ```js
+ function $apply(expr) {
+ try {
+ return $eval(expr);
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ $root.$digest();
+ }
+ }
+ * ```
+ *
+ *
+ * Scope's `$apply()` method transitions through the following stages:
+ *
+ * 1. The {@link guide/expression expression} is executed using the
+ * {@link ng.$rootScope.Scope#$eval $eval()} method.
+ * 2. Any exceptions from the execution of the expression are forwarded to the
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
+ * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
+ *
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ *
+ * @returns {*} The result of evaluating the expression.
+ */
+ $apply: function(expr) {
+ try {
+ beginPhase('$apply');
+ try {
+ return this.$eval(expr);
+ } finally {
+ clearPhase();
+ }
+ } catch (e) {
+ $exceptionHandler(e);
+ } finally {
+ try {
+ $rootScope.$digest();
+ } catch (e) {
+ $exceptionHandler(e);
+ throw e;
+ }
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$applyAsync
+ * @kind function
+ *
+ * @description
+ * Schedule the invocation of $apply to occur at a later time. The actual time difference
+ * varies across browsers, but is typically around ~10 milliseconds.
+ *
+ * This can be used to queue up multiple expressions which need to be evaluated in the same
+ * digest.
+ *
+ * @param {(string|function())=} exp An angular expression to be executed.
+ *
+ * - `string`: execute using the rules as defined in {@link guide/expression expression}.
+ * - `function(scope)`: execute the function with current `scope` parameter.
+ */
+ $applyAsync: function(expr) {
+ var scope = this;
+ expr && applyAsyncQueue.push($applyAsyncExpression);
+ scheduleApplyAsync();
+
+ function $applyAsyncExpression() {
+ scope.$eval(expr);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$on
+ * @kind function
+ *
+ * @description
+ * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
+ * discussion of event life cycle.
+ *
+ * The event listener function format is: `function(event, args...)`. The `event` object
+ * passed into the listener has the following attributes:
+ *
+ * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
+ * `$broadcast`-ed.
+ * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
+ * event propagates through the scope hierarchy, this property is set to null.
+ * - `name` - `{string}`: name of the event.
+ * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
+ * further event propagation (available only for events that were `$emit`-ed).
+ * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
+ * to true.
+ * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
+ *
+ * @param {string} name Event name to listen on.
+ * @param {function(event, ...args)} listener Function to call when the event is emitted.
+ * @returns {function()} Returns a deregistration function for this listener.
+ */
+ $on: function(name, listener) {
+ var namedListeners = this.$$listeners[name];
+ if (!namedListeners) {
+ this.$$listeners[name] = namedListeners = [];
+ }
+ namedListeners.push(listener);
+
+ var current = this;
+ do {
+ if (!current.$$listenerCount[name]) {
+ current.$$listenerCount[name] = 0;
+ }
+ current.$$listenerCount[name]++;
+ } while ((current = current.$parent));
+
+ var self = this;
+ return function() {
+ var indexOfListener = namedListeners.indexOf(listener);
+ if (indexOfListener !== -1) {
+ namedListeners[indexOfListener] = null;
+ decrementListenerCount(self, 1, name);
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$emit
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` upwards through the scope hierarchy notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$emit` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event traverses upwards toward the root scope and calls all
+ * registered listeners along the way. The event will stop propagating if one of the listeners
+ * cancels it.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to emit.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
+ */
+ $emit: function(name, args) {
+ var empty = [],
+ namedListeners,
+ scope = this,
+ stopPropagation = false,
+ event = {
+ name: name,
+ targetScope: scope,
+ stopPropagation: function() {stopPropagation = true;},
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ },
+ listenerArgs = concat([event], arguments, 1),
+ i, length;
+
+ do {
+ namedListeners = scope.$$listeners[name] || empty;
+ event.currentScope = scope;
+ for (i = 0, length = namedListeners.length; i < length; i++) {
+
+ // if listeners were deregistered, defragment the array
+ if (!namedListeners[i]) {
+ namedListeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+ try {
+ //allow all listeners attached to the current scope to run
+ namedListeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ //if any listener on the current scope stops propagation, prevent bubbling
+ if (stopPropagation) {
+ event.currentScope = null;
+ return event;
+ }
+ //traverse upwards
+ scope = scope.$parent;
+ } while (scope);
+
+ event.currentScope = null;
+
+ return event;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name $rootScope.Scope#$broadcast
+ * @kind function
+ *
+ * @description
+ * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
+ * registered {@link ng.$rootScope.Scope#$on} listeners.
+ *
+ * The event life cycle starts at the scope on which `$broadcast` was called. All
+ * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
+ * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
+ * scope and calls all registered listeners along the way. The event cannot be canceled.
+ *
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * @param {string} name Event name to broadcast.
+ * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
+ * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
+ */
+ $broadcast: function(name, args) {
+ var target = this,
+ current = target,
+ next = target,
+ event = {
+ name: name,
+ targetScope: target,
+ preventDefault: function() {
+ event.defaultPrevented = true;
+ },
+ defaultPrevented: false
+ };
+
+ if (!target.$$listenerCount[name]) return event;
+
+ var listenerArgs = concat([event], arguments, 1),
+ listeners, i, length;
+
+ //down while you can, then up and next sibling or up and next sibling until back at root
+ while ((current = next)) {
+ event.currentScope = current;
+ listeners = current.$$listeners[name] || [];
+ for (i = 0, length = listeners.length; i < length; i++) {
+ // if listeners were deregistered, defragment the array
+ if (!listeners[i]) {
+ listeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+
+ try {
+ listeners[i].apply(null, listenerArgs);
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+
+ // Insanity Warning: scope depth-first traversal
+ // yes, this code is a bit crazy, but it works and we have tests to prove it!
+ // this piece should be kept in sync with the traversal in $digest
+ // (though it differs due to having the extra check for $$listenerCount)
+ if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
+ (current !== target && current.$$nextSibling)))) {
+ while (current !== target && !(next = current.$$nextSibling)) {
+ current = current.$parent;
+ }
+ }
+ }
+
+ event.currentScope = null;
+ return event;
+ }
+ };
+
+ var $rootScope = new Scope();
+
+ //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
+ var asyncQueue = $rootScope.$$asyncQueue = [];
+ var postDigestQueue = $rootScope.$$postDigestQueue = [];
+ var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
+
+ return $rootScope;
+
+
+ function beginPhase(phase) {
+ if ($rootScope.$$phase) {
+ throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
+ }
+
+ $rootScope.$$phase = phase;
+ }
+
+ function clearPhase() {
+ $rootScope.$$phase = null;
+ }
+
+ function incrementWatchersCount(current, count) {
+ do {
+ current.$$watchersCount += count;
+ } while ((current = current.$parent));
+ }
+
+ function decrementListenerCount(current, count, name) {
+ do {
+ current.$$listenerCount[name] -= count;
+
+ if (current.$$listenerCount[name] === 0) {
+ delete current.$$listenerCount[name];
+ }
+ } while ((current = current.$parent));
+ }
+
+ /**
+ * function used as an initial value for watchers.
+ * because it's unique we can easily tell it apart from other values
+ */
+ function initWatchVal() {}
+
+ function flushApplyAsync() {
+ while (applyAsyncQueue.length) {
+ try {
+ applyAsyncQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
+ applyAsyncId = null;
+ }
+
+ function scheduleApplyAsync() {
+ if (applyAsyncId === null) {
+ applyAsyncId = $browser.defer(function() {
+ $rootScope.$apply(flushApplyAsync);
+ });
+ }
+ }
+ }];
+}
+
+/**
+ * @description
+ * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
+ */
+function $$SanitizeUriProvider() {
+ var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
+ imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
+
+ /**
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.aHrefSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ aHrefSanitizationWhitelist = regexp;
+ return this;
+ }
+ return aHrefSanitizationWhitelist;
+ };
+
+
+ /**
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during img[src] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
+ * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
+ * regular expression. If a match is found, the original url is written into the dom. Otherwise,
+ * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.imgSrcSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ imgSrcSanitizationWhitelist = regexp;
+ return this;
+ }
+ return imgSrcSanitizationWhitelist;
+ };
+
+ this.$get = function() {
+ return function sanitizeUri(uri, isImage) {
+ var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
+ var normalizedVal;
+ normalizedVal = urlResolve(uri).href;
+ if (normalizedVal !== '' && !normalizedVal.match(regex)) {
+ return 'unsafe:' + normalizedVal;
+ }
+ return uri;
+ };
+ };
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Any commits to this file should be reviewed with security in mind. *
+ * Changes to this file can potentially create security vulnerabilities. *
+ * An approval from 2 Core members with history of modifying *
+ * this file is required. *
+ * *
+ * Does the change somehow allow for arbitrary javascript to be executed? *
+ * Or allows for someone to change the prototype of built-in objects? *
+ * Or gives undesired access to variables likes document or window? *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+var $sceMinErr = minErr('$sce');
+
+var SCE_CONTEXTS = {
+ HTML: 'html',
+ CSS: 'css',
+ URL: 'url',
+ // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
+ // url. (e.g. ng-include, script src, templateUrl)
+ RESOURCE_URL: 'resourceUrl',
+ JS: 'js'
+};
+
+// Helper functions follow.
+
+function adjustMatcher(matcher) {
+ if (matcher === 'self') {
+ return matcher;
+ } else if (isString(matcher)) {
+ // Strings match exactly except for 2 wildcards - '*' and '**'.
+ // '*' matches any character except those from the set ':/.?&'.
+ // '**' matches any character (like .* in a RegExp).
+ // More than 2 *'s raises an error as it's ill defined.
+ if (matcher.indexOf('***') > -1) {
+ throw $sceMinErr('iwcard',
+ 'Illegal sequence *** in string matcher. String: {0}', matcher);
+ }
+ matcher = escapeForRegexp(matcher).
+ replace('\\*\\*', '.*').
+ replace('\\*', '[^:/.?&;]*');
+ return new RegExp('^' + matcher + '$');
+ } else if (isRegExp(matcher)) {
+ // The only other type of matcher allowed is a Regexp.
+ // Match entire URL / disallow partial matches.
+ // Flags are reset (i.e. no global, ignoreCase or multiline)
+ return new RegExp('^' + matcher.source + '$');
+ } else {
+ throw $sceMinErr('imatcher',
+ 'Matchers may only be "self", string patterns or RegExp objects');
+ }
+}
+
+
+function adjustMatchers(matchers) {
+ var adjustedMatchers = [];
+ if (isDefined(matchers)) {
+ forEach(matchers, function(matcher) {
+ adjustedMatchers.push(adjustMatcher(matcher));
+ });
+ }
+ return adjustedMatchers;
+}
+
+
+/**
+ * @ngdoc service
+ * @name $sceDelegate
+ * @kind function
+ *
+ * @description
+ *
+ * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
+ * Contextual Escaping (SCE)} services to AngularJS.
+ *
+ * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
+ * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
+ * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
+ * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
+ * work because `$sce` delegates to `$sceDelegate` for these operations.
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
+ *
+ * The default instance of `$sceDelegate` should work out of the box with little pain. While you
+ * can override it completely to change the behavior of `$sce`, the common case would
+ * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
+ * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
+ * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
+ * $sceDelegateProvider.resourceUrlWhitelist} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ */
+
+/**
+ * @ngdoc provider
+ * @name $sceDelegateProvider
+ * @description
+ *
+ * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
+ * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
+ * that the URLs used for sourcing Angular templates are safe. Refer {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
+ * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
+ *
+ * For the general details about this service in Angular, read the main page for {@link ng.$sce
+ * Strict Contextual Escaping (SCE)}.
+ *
+ * **Example**: Consider the following case. <a name="example"></a>
+ *
+ * - your app is hosted at url `http://myapp.example.com/`
+ * - but some of your templates are hosted on other domains you control such as
+ * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
+ * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
+ *
+ * Here is what a secure configuration for this scenario might look like:
+ *
+ * ```
+ * angular.module('myApp', []).config(function($sceDelegateProvider) {
+ * $sceDelegateProvider.resourceUrlWhitelist([
+ * // Allow same origin resource loads.
+ * 'self',
+ * // Allow loading from our assets domain. Notice the difference between * and **.
+ * 'http://srv*.assets.example.com/**'
+ * ]);
+ *
+ * // The blacklist overrides the whitelist so the open redirect here is blocked.
+ * $sceDelegateProvider.resourceUrlBlacklist([
+ * 'http://myapp.example.com/clickThru**'
+ * ]);
+ * });
+ * ```
+ */
+
+function $SceDelegateProvider() {
+ this.SCE_CONTEXTS = SCE_CONTEXTS;
+
+ // Resource URLs can also be trusted by policy.
+ var resourceUrlWhitelist = ['self'],
+ resourceUrlBlacklist = [];
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlWhitelist
+ * @kind function
+ *
+ * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * Note: **an empty whitelist array will block all URLs**!
+ *
+ * @return {Array} the currently set whitelist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
+ * same origin resource requests.
+ *
+ * @description
+ * Sets/Gets the whitelist of trusted resource URLs.
+ */
+ this.resourceUrlWhitelist = function(value) {
+ if (arguments.length) {
+ resourceUrlWhitelist = adjustMatchers(value);
+ }
+ return resourceUrlWhitelist;
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegateProvider#resourceUrlBlacklist
+ * @kind function
+ *
+ * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
+ * provided. This must be an array or null. A snapshot of this array is used so further
+ * changes to the array are ignored.
+ *
+ * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
+ * allowed in this array.
+ *
+ * The typical usage for the blacklist is to **block
+ * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
+ * these would otherwise be trusted but actually return content from the redirected domain.
+ *
+ * Finally, **the blacklist overrides the whitelist** and has the final say.
+ *
+ * @return {Array} the currently set blacklist array.
+ *
+ * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
+ * is no blacklist.)
+ *
+ * @description
+ * Sets/Gets the blacklist of trusted resource URLs.
+ */
+
+ this.resourceUrlBlacklist = function(value) {
+ if (arguments.length) {
+ resourceUrlBlacklist = adjustMatchers(value);
+ }
+ return resourceUrlBlacklist;
+ };
+
+ this.$get = ['$injector', function($injector) {
+
+ var htmlSanitizer = function htmlSanitizer(html) {
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ };
+
+ if ($injector.has('$sanitize')) {
+ htmlSanitizer = $injector.get('$sanitize');
+ }
+
+
+ function matchUrl(matcher, parsedUrl) {
+ if (matcher === 'self') {
+ return urlIsSameOrigin(parsedUrl);
+ } else {
+ // definitely a regex. See adjustMatchers()
+ return !!matcher.exec(parsedUrl.href);
+ }
+ }
+
+ function isResourceUrlAllowedByPolicy(url) {
+ var parsedUrl = urlResolve(url.toString());
+ var i, n, allowed = false;
+ // Ensure that at least one item from the whitelist allows this url.
+ for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
+ if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
+ allowed = true;
+ break;
+ }
+ }
+ if (allowed) {
+ // Ensure that no item from the blacklist blocked this url.
+ for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
+ if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
+ allowed = false;
+ break;
+ }
+ }
+ }
+ return allowed;
+ }
+
+ function generateHolderType(Base) {
+ var holderType = function TrustedValueHolderType(trustedValue) {
+ this.$$unwrapTrustedValue = function() {
+ return trustedValue;
+ };
+ };
+ if (Base) {
+ holderType.prototype = new Base();
+ }
+ holderType.prototype.valueOf = function sceValueOf() {
+ return this.$$unwrapTrustedValue();
+ };
+ holderType.prototype.toString = function sceToString() {
+ return this.$$unwrapTrustedValue().toString();
+ };
+ return holderType;
+ }
+
+ var trustedValueHolderBase = generateHolderType(),
+ byType = {};
+
+ byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
+ byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#trustAs
+ *
+ * @description
+ * Returns an object that is trusted by angular for use in specified strict
+ * contextual escaping contexts (such as ng-bind-html, ng-include, any src
+ * attribute interpolation, any dom event binding attribute interpolation
+ * such as for onclick, etc.) that uses the provided value.
+ * See {@link ng.$sce $sce} for enabling strict contextual escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resourceUrl, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+ function trustAs(type, trustedValue) {
+ var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (!Constructor) {
+ throw $sceMinErr('icontext',
+ 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
+ type, trustedValue);
+ }
+ if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
+ return trustedValue;
+ }
+ // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
+ // mutable objects, we ensure here that the value passed in is actually a string.
+ if (typeof trustedValue !== 'string') {
+ throw $sceMinErr('itype',
+ 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
+ type);
+ }
+ return new Constructor(trustedValue);
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#valueOf
+ *
+ * @description
+ * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
+ *
+ * If the passed parameter is not a value that had been returned by {@link
+ * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
+ *
+ * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
+ * call or anything else.
+ * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
+ * `value` unchanged.
+ */
+ function valueOf(maybeTrusted) {
+ if (maybeTrusted instanceof trustedValueHolderBase) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ } else {
+ return maybeTrusted;
+ }
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sceDelegate#getTrusted
+ *
+ * @description
+ * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
+ * returns the originally supplied value if the queried context type is a supertype of the
+ * created type. If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} call.
+ * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
+ * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
+ */
+ function getTrusted(type, maybeTrusted) {
+ if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
+ return maybeTrusted;
+ }
+ var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
+ if (constructor && maybeTrusted instanceof constructor) {
+ return maybeTrusted.$$unwrapTrustedValue();
+ }
+ // If we get here, then we may only take one of two actions.
+ // 1. sanitize the value for the requested type, or
+ // 2. throw an exception.
+ if (type === SCE_CONTEXTS.RESOURCE_URL) {
+ if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
+ return maybeTrusted;
+ } else {
+ throw $sceMinErr('insecurl',
+ 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
+ maybeTrusted.toString());
+ }
+ } else if (type === SCE_CONTEXTS.HTML) {
+ return htmlSanitizer(maybeTrusted);
+ }
+ throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
+ }
+
+ return { trustAs: trustAs,
+ getTrusted: getTrusted,
+ valueOf: valueOf };
+ }];
+}
+
+
+/**
+ * @ngdoc provider
+ * @name $sceProvider
+ * @description
+ *
+ * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
+ * - enable/disable Strict Contextual Escaping (SCE) in a module
+ * - override the default implementation with a custom delegate
+ *
+ * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
+ */
+
+/* jshint maxlen: false*/
+
+/**
+ * @ngdoc service
+ * @name $sce
+ * @kind function
+ *
+ * @description
+ *
+ * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
+ *
+ * # Strict Contextual Escaping
+ *
+ * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
+ * contexts to result in a value that is marked as safe to use for that context. One example of
+ * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
+ * to these contexts as privileged or SCE contexts.
+ *
+ * As of version 1.2, Angular ships with SCE enabled by default.
+ *
+ * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
+ * one to execute arbitrary javascript by the use of the expression() syntax. Refer
+ * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
+ * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
+ * to the top of your HTML document.
+ *
+ * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
+ * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
+ *
+ * Here's an example of a binding in a privileged context:
+ *
+ * ```
+ * <input ng-model="userHtml" aria-label="User input">
+ * <div ng-bind-html="userHtml"></div>
+ * ```
+ *
+ * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
+ * disabled, this application allows the user to render arbitrary HTML into the DIV.
+ * In a more realistic example, one may be rendering user comments, blog articles, etc. via
+ * bindings. (HTML is just one example of a context where rendering user controlled input creates
+ * security vulnerabilities.)
+ *
+ * For the case of HTML, you might use a library, either on the client side, or on the server side,
+ * to sanitize unsafe HTML before binding to the value and rendering it in the document.
+ *
+ * How would you ensure that every place that used these types of bindings was bound to a value that
+ * was sanitized by your library (or returned as safe for rendering by your server?) How can you
+ * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
+ * properties/fields and forgot to update the binding to the sanitized value?
+ *
+ * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
+ * determine that something explicitly says it's safe to use a value for binding in that
+ * context. You can then audit your code (a simple grep would do) to ensure that this is only done
+ * for those values that you can easily tell are safe - because they were received from your server,
+ * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
+ * allowing only the files in a specific directory to do this. Ensuring that the internal API
+ * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
+ *
+ * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
+ * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
+ * obtain values that will be accepted by SCE / privileged contexts.
+ *
+ *
+ * ## How does it work?
+ *
+ * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
+ * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
+ * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
+ * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
+ *
+ * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
+ * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
+ * simplified):
+ *
+ * ```
+ * var ngBindHtmlDirective = ['$sce', function($sce) {
+ * return function(scope, element, attr) {
+ * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
+ * element.html(value || '');
+ * });
+ * };
+ * }];
+ * ```
+ *
+ * ## Impact on loading templates
+ *
+ * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
+ * `templateUrl`'s specified by {@link guide/directive directives}.
+ *
+ * By default, Angular only loads templates from the same domain and protocol as the application
+ * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
+ * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
+ * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
+ *
+ * *Please note*:
+ * The browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy apply in addition to this and may further restrict whether the template is successfully
+ * loaded. This means that without the right CORS policy, loading templates from a different domain
+ * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
+ * browsers.
+ *
+ * ## This feels like too much overhead
+ *
+ * It's important to remember that SCE only applies to interpolation expressions.
+ *
+ * If your expressions are constant literals, they're automatically trusted and you don't need to
+ * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
+ * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
+ *
+ * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
+ * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
+ *
+ * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
+ * templates in `ng-include` from your application's domain without having to even know about SCE.
+ * It blocks loading templates from other domains or loading templates over http from an https
+ * served document. You can change these by setting your own custom {@link
+ * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
+ * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
+ *
+ * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
+ * application that's secure and can be audited to verify that with much more ease than bolting
+ * security onto an application later.
+ *
+ * <a name="contexts"></a>
+ * ## What trusted context types are supported?
+ *
+ * | Context | Notes |
+ * |---------------------|----------------|
+ * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
+ * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
+ * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
+ * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
+ * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
+ *
+ * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
+ *
+ * Each element in these arrays must be one of the following:
+ *
+ * - **'self'**
+ * - The special **string**, `'self'`, can be used to match against all URLs of the **same
+ * domain** as the application document using the **same protocol**.
+ * - **String** (except the special value `'self'`)
+ * - The string is matched against the full *normalized / absolute URL* of the resource
+ * being tested (substring matches are not good enough.)
+ * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
+ * match themselves.
+ * - `*`: matches zero or more occurrences of any character other than one of the following 6
+ * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use
+ * in a whitelist.
+ * - `**`: matches zero or more occurrences of *any* character. As such, it's not
+ * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
+ * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
+ * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
+ * http://foo.example.com/templates/**).
+ * - **RegExp** (*see caveat below*)
+ * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
+ * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
+ * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
+ * have good test coverage). For instance, the use of `.` in the regex is correct only in a
+ * small number of cases. A `.` character in the regex used when matching the scheme or a
+ * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
+ * is highly recommended to use the string patterns and only fall back to regular expressions
+ * as a last resort.
+ * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
+ * matched against the **entire** *normalized / absolute URL* of the resource being tested
+ * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
+ * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
+ * - If you are generating your JavaScript from some other templating engine (not
+ * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
+ * remember to escape your regular expression (and be aware that you might need more than
+ * one level of escaping depending on your templating engine and the way you interpolated
+ * the value.) Do make use of your platform's escaping mechanism as it might be good
+ * enough before coding your own. E.g. Ruby has
+ * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
+ * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
+ * Javascript lacks a similar built in function for escaping. Take a look at Google
+ * Closure library's [goog.string.regExpEscape(s)](
+ * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
+ *
+ * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
+ *
+ * ## Show me an example using SCE.
+ *
+ * <example module="mySceApp" deps="angular-sanitize.js">
+ * <file name="index.html">
+ * <div ng-controller="AppController as myCtrl">
+ * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
+ * <b>User comments</b><br>
+ * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
+ * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
+ * exploit.
+ * <div class="well">
+ * <div ng-repeat="userComment in myCtrl.userComments">
+ * <b>{{userComment.name}}</b>:
+ * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
+ * <br>
+ * </div>
+ * </div>
+ * </div>
+ * </file>
+ *
+ * <file name="script.js">
+ * angular.module('mySceApp', ['ngSanitize'])
+ * .controller('AppController', ['$http', '$templateCache', '$sce',
+ * function($http, $templateCache, $sce) {
+ * var self = this;
+ * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
+ * self.userComments = userComments;
+ * });
+ * self.explicitlyTrustedHtml = $sce.trustAsHtml(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * }]);
+ * </file>
+ *
+ * <file name="test_data.json">
+ * [
+ * { "name": "Alice",
+ * "htmlComment":
+ * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
+ * },
+ * { "name": "Bob",
+ * "htmlComment": "<i>Yes!</i> Am I the only other one?"
+ * }
+ * ]
+ * </file>
+ *
+ * <file name="protractor.js" type="protractor">
+ * describe('SCE doc demo', function() {
+ * it('should sanitize untrusted values', function() {
+ * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
+ * .toBe('<span>Is <i>anyone</i> reading this?</span>');
+ * });
+ *
+ * it('should NOT sanitize explicitly trusted values', function() {
+ * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
+ * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
+ * 'sanitization.&quot;">Hover over this text.</span>');
+ * });
+ * });
+ * </file>
+ * </example>
+ *
+ *
+ *
+ * ## Can I disable SCE completely?
+ *
+ * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
+ * for little coding overhead. It will be much harder to take an SCE disabled application and
+ * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
+ * for cases where you have a lot of existing code that was written before SCE was introduced and
+ * you're migrating them a module at a time.
+ *
+ * That said, here's how you can completely disable SCE:
+ *
+ * ```
+ * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ * // Completely disable SCE. For demonstration purposes only!
+ * // Do not use in new projects.
+ * $sceProvider.enabled(false);
+ * });
+ * ```
+ *
+ */
+/* jshint maxlen: 100 */
+
+function $SceProvider() {
+ var enabled = true;
+
+ /**
+ * @ngdoc method
+ * @name $sceProvider#enabled
+ * @kind function
+ *
+ * @param {boolean=} value If provided, then enables/disables SCE.
+ * @return {boolean} true if SCE is enabled, false otherwise.
+ *
+ * @description
+ * Enables/disables SCE and returns the current value.
+ */
+ this.enabled = function(value) {
+ if (arguments.length) {
+ enabled = !!value;
+ }
+ return enabled;
+ };
+
+
+ /* Design notes on the default implementation for SCE.
+ *
+ * The API contract for the SCE delegate
+ * -------------------------------------
+ * The SCE delegate object must provide the following 3 methods:
+ *
+ * - trustAs(contextEnum, value)
+ * This method is used to tell the SCE service that the provided value is OK to use in the
+ * contexts specified by contextEnum. It must return an object that will be accepted by
+ * getTrusted() for a compatible contextEnum and return this value.
+ *
+ * - valueOf(value)
+ * For values that were not produced by trustAs(), return them as is. For values that were
+ * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
+ * trustAs is wrapping the given values into some type, this operation unwraps it when given
+ * such a value.
+ *
+ * - getTrusted(contextEnum, value)
+ * This function should return the a value that is safe to use in the context specified by
+ * contextEnum or throw and exception otherwise.
+ *
+ * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
+ * opaque or wrapped in some holder object. That happens to be an implementation detail. For
+ * instance, an implementation could maintain a registry of all trusted objects by context. In
+ * such a case, trustAs() would return the same object that was passed in. getTrusted() would
+ * return the same object passed in if it was found in the registry under a compatible context or
+ * throw an exception otherwise. An implementation might only wrap values some of the time based
+ * on some criteria. getTrusted() might return a value and not throw an exception for special
+ * constants or objects even if not wrapped. All such implementations fulfill this contract.
+ *
+ *
+ * A note on the inheritance model for SCE contexts
+ * ------------------------------------------------
+ * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
+ * is purely an implementation details.
+ *
+ * The contract is simply this:
+ *
+ * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
+ * will also succeed.
+ *
+ * Inheritance happens to capture this in a natural way. In some future, we
+ * may not use inheritance anymore. That is OK because no code outside of
+ * sce.js and sceSpecs.js would need to be aware of this detail.
+ */
+
+ this.$get = ['$parse', '$sceDelegate', function(
+ $parse, $sceDelegate) {
+ // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
+ // the "expression(javascript expression)" syntax which is insecure.
+ if (enabled && msie < 8) {
+ throw $sceMinErr('iequirks',
+ 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
+ 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
+ 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
+ }
+
+ var sce = shallowCopy(SCE_CONTEXTS);
+
+ /**
+ * @ngdoc method
+ * @name $sce#isEnabled
+ * @kind function
+ *
+ * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
+ * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
+ *
+ * @description
+ * Returns a boolean indicating if SCE is enabled.
+ */
+ sce.isEnabled = function() {
+ return enabled;
+ };
+ sce.trustAs = $sceDelegate.trustAs;
+ sce.getTrusted = $sceDelegate.getTrusted;
+ sce.valueOf = $sceDelegate.valueOf;
+
+ if (!enabled) {
+ sce.trustAs = sce.getTrusted = function(type, value) { return value; };
+ sce.valueOf = identity;
+ }
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAs
+ *
+ * @description
+ * Converts Angular {@link guide/expression expression} into a function. This is like {@link
+ * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
+ * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
+ * *result*)}
+ *
+ * @param {string} type The kind of SCE context in which this result will be used.
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+ sce.parseAs = function sceParseAs(type, expr) {
+ var parsed = $parse(expr);
+ if (parsed.literal && parsed.constant) {
+ return parsed;
+ } else {
+ return $parse(expr, function(value) {
+ return sce.getTrusted(type, value);
+ });
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAs
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
+ * returns an object that is trusted by angular for use in specified strict contextual
+ * escaping contexts (such as ng-bind-html, ng-include, any src attribute
+ * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
+ * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
+ * escaping.
+ *
+ * @param {string} type The kind of context in which this value is safe for use. e.g. url,
+ * resourceUrl, html, js and css.
+ * @param {*} value The value that that should be considered trusted/safe.
+ * @returns {*} A value that can be used to stand in for the provided `value` in places
+ * where Angular expects a $sce.trustAs() return value.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsHtml(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
+ * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
+ * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsResourceUrl(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the return
+ * value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#trustAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.trustAsJs(value)` →
+ * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
+ *
+ * @param {*} value The value to trustAs.
+ * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
+ * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
+ * only accept expressions that are either literal constants or are the
+ * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrusted
+ *
+ * @description
+ * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
+ * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
+ * originally supplied value if the queried context type is a supertype of the created type.
+ * If this condition isn't satisfied, throws an exception.
+ *
+ * @param {string} type The kind of context in which this value is to be used.
+ * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
+ * call.
+ * @returns {*} The value the was originally provided to
+ * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
+ * Otherwise, throws an exception.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedHtml
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedHtml(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedCss
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedCss(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
+ *
+ * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#getTrustedJs
+ *
+ * @description
+ * Shorthand method. `$sce.getTrustedJs(value)` →
+ * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
+ *
+ * @param {*} value The value to pass to `$sce.getTrusted`.
+ * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsHtml
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsHtml(expression string)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsCss
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsCss(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsResourceUrl
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsResourceUrl(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ /**
+ * @ngdoc method
+ * @name $sce#parseAsJs
+ *
+ * @description
+ * Shorthand method. `$sce.parseAsJs(value)` →
+ * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
+ *
+ * @param {string} expression String expression to compile.
+ * @returns {function(context, locals)} a function which represents the compiled expression:
+ *
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (typically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
+ */
+
+ // Shorthand delegations.
+ var parse = sce.parseAs,
+ getTrusted = sce.getTrusted,
+ trustAs = sce.trustAs;
+
+ forEach(SCE_CONTEXTS, function(enumValue, name) {
+ var lName = lowercase(name);
+ sce[camelCase("parse_as_" + lName)] = function(expr) {
+ return parse(enumValue, expr);
+ };
+ sce[camelCase("get_trusted_" + lName)] = function(value) {
+ return getTrusted(enumValue, value);
+ };
+ sce[camelCase("trust_as_" + lName)] = function(value) {
+ return trustAs(enumValue, value);
+ };
+ });
+
+ return sce;
+ }];
+}
+
+/**
+ * !!! This is an undocumented "private" service !!!
+ *
+ * @name $sniffer
+ * @requires $window
+ * @requires $document
+ *
+ * @property {boolean} history Does the browser support html5 history api ?
+ * @property {boolean} transitions Does the browser support CSS transition events ?
+ * @property {boolean} animations Does the browser support CSS animation events ?
+ *
+ * @description
+ * This is very simple implementation of testing browser's features.
+ */
+function $SnifferProvider() {
+ this.$get = ['$window', '$document', function($window, $document) {
+ var eventSupport = {},
+ android =
+ toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
+ boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
+ document = $document[0] || {},
+ vendorPrefix,
+ vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
+ bodyStyle = document.body && document.body.style,
+ transitions = false,
+ animations = false,
+ match;
+
+ if (bodyStyle) {
+ for (var prop in bodyStyle) {
+ if (match = vendorRegex.exec(prop)) {
+ vendorPrefix = match[0];
+ vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
+ break;
+ }
+ }
+
+ if (!vendorPrefix) {
+ vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
+ }
+
+ transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
+ animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
+
+ if (android && (!transitions || !animations)) {
+ transitions = isString(bodyStyle.webkitTransition);
+ animations = isString(bodyStyle.webkitAnimation);
+ }
+ }
+
+
+ return {
+ // Android has history.pushState, but it does not update location correctly
+ // so let's not use the history API at all.
+ // http://code.google.com/p/android/issues/detail?id=17471
+ // https://github.com/angular/angular.js/issues/904
+
+ // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
+ // so let's not use the history API also
+ // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
+ // jshint -W018
+ history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
+ // jshint +W018
+ hasEvent: function(event) {
+ // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
+ // it. In particular the event is not fired when backspace or delete key are pressed or
+ // when cut operation is performed.
+ // IE10+ implements 'input' event but it erroneously fires under various situations,
+ // e.g. when placeholder changes, or a form is focused.
+ if (event === 'input' && msie <= 11) return false;
+
+ if (isUndefined(eventSupport[event])) {
+ var divElm = document.createElement('div');
+ eventSupport[event] = 'on' + event in divElm;
+ }
+
+ return eventSupport[event];
+ },
+ csp: csp(),
+ vendorPrefix: vendorPrefix,
+ transitions: transitions,
+ animations: animations,
+ android: android
+ };
+ }];
+}
+
+var $compileMinErr = minErr('$compile');
+
+/**
+ * @ngdoc service
+ * @name $templateRequest
+ *
+ * @description
+ * The `$templateRequest` service runs security checks then downloads the provided template using
+ * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
+ * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
+ * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
+ * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
+ * when `tpl` is of type string and `$templateCache` has the matching entry.
+ *
+ * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
+ * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
+ *
+ * @return {Promise} a promise for the HTTP response data of the given URL.
+ *
+ * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
+ */
+function $TemplateRequestProvider() {
+ this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
+ function handleRequestFn(tpl, ignoreRequestError) {
+ handleRequestFn.totalPendingRequests++;
+
+ // We consider the template cache holds only trusted templates, so
+ // there's no need to go through whitelisting again for keys that already
+ // are included in there. This also makes Angular accept any script
+ // directive, no matter its name. However, we still need to unwrap trusted
+ // types.
+ if (!isString(tpl) || !$templateCache.get(tpl)) {
+ tpl = $sce.getTrustedResourceUrl(tpl);
+ }
+
+ var transformResponse = $http.defaults && $http.defaults.transformResponse;
+
+ if (isArray(transformResponse)) {
+ transformResponse = transformResponse.filter(function(transformer) {
+ return transformer !== defaultHttpResponseTransform;
+ });
+ } else if (transformResponse === defaultHttpResponseTransform) {
+ transformResponse = null;
+ }
+
+ var httpOptions = {
+ cache: $templateCache,
+ transformResponse: transformResponse
+ };
+
+ return $http.get(tpl, httpOptions)
+ ['finally'](function() {
+ handleRequestFn.totalPendingRequests--;
+ })
+ .then(function(response) {
+ $templateCache.put(tpl, response.data);
+ return response.data;
+ }, handleError);
+
+ function handleError(resp) {
+ if (!ignoreRequestError) {
+ throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})',
+ tpl, resp.status, resp.statusText);
+ }
+ return $q.reject(resp);
+ }
+ }
+
+ handleRequestFn.totalPendingRequests = 0;
+
+ return handleRequestFn;
+ }];
+}
+
+function $$TestabilityProvider() {
+ this.$get = ['$rootScope', '$browser', '$location',
+ function($rootScope, $browser, $location) {
+
+ /**
+ * @name $testability
+ *
+ * @description
+ * The private $$testability service provides a collection of methods for use when debugging
+ * or by automated test and debugging tools.
+ */
+ var testability = {};
+
+ /**
+ * @name $$testability#findBindings
+ *
+ * @description
+ * Returns an array of elements that are bound (via ng-bind or {{}})
+ * to expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The binding expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression. Filters and whitespace are ignored.
+ */
+ testability.findBindings = function(element, expression, opt_exactMatch) {
+ var bindings = element.getElementsByClassName('ng-binding');
+ var matches = [];
+ forEach(bindings, function(binding) {
+ var dataBinding = angular.element(binding).data('$binding');
+ if (dataBinding) {
+ forEach(dataBinding, function(bindingName) {
+ if (opt_exactMatch) {
+ var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
+ if (matcher.test(bindingName)) {
+ matches.push(binding);
+ }
+ } else {
+ if (bindingName.indexOf(expression) != -1) {
+ matches.push(binding);
+ }
+ }
+ });
+ }
+ });
+ return matches;
+ };
+
+ /**
+ * @name $$testability#findModels
+ *
+ * @description
+ * Returns an array of elements that are two-way found via ng-model to
+ * expressions matching the input.
+ *
+ * @param {Element} element The element root to search from.
+ * @param {string} expression The model expression to match.
+ * @param {boolean} opt_exactMatch If true, only returns exact matches
+ * for the expression.
+ */
+ testability.findModels = function(element, expression, opt_exactMatch) {
+ var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
+ for (var p = 0; p < prefixes.length; ++p) {
+ var attributeEquals = opt_exactMatch ? '=' : '*=';
+ var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
+ var elements = element.querySelectorAll(selector);
+ if (elements.length) {
+ return elements;
+ }
+ }
+ };
+
+ /**
+ * @name $$testability#getLocation
+ *
+ * @description
+ * Shortcut for getting the location in a browser agnostic way. Returns
+ * the path, search, and hash. (e.g. /path?a=b#hash)
+ */
+ testability.getLocation = function() {
+ return $location.url();
+ };
+
+ /**
+ * @name $$testability#setLocation
+ *
+ * @description
+ * Shortcut for navigating to a location without doing a full page reload.
+ *
+ * @param {string} url The location url (path, search and hash,
+ * e.g. /path?a=b#hash) to go to.
+ */
+ testability.setLocation = function(url) {
+ if (url !== $location.url()) {
+ $location.url(url);
+ $rootScope.$digest();
+ }
+ };
+
+ /**
+ * @name $$testability#whenStable
+ *
+ * @description
+ * Calls the callback when $timeout and $http requests are completed.
+ *
+ * @param {function} callback
+ */
+ testability.whenStable = function(callback) {
+ $browser.notifyWhenNoOutstandingRequests(callback);
+ };
+
+ return testability;
+ }];
+}
+
+function $TimeoutProvider() {
+ this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
+ function($rootScope, $browser, $q, $$q, $exceptionHandler) {
+
+ var deferreds = {};
+
+
+ /**
+ * @ngdoc service
+ * @name $timeout
+ *
+ * @description
+ * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
+ * block and delegates any exceptions to
+ * {@link ng.$exceptionHandler $exceptionHandler} service.
+ *
+ * The return value of calling `$timeout` is a promise, which will be resolved when
+ * the delay has passed and the timeout function, if provided, is executed.
+ *
+ * To cancel a timeout request, call `$timeout.cancel(promise)`.
+ *
+ * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
+ * synchronously flush the queue of deferred functions.
+ *
+ * If you only want a promise that will be resolved after some specified delay
+ * then you can call `$timeout` without the `fn` function.
+ *
+ * @param {function()=} fn A function, whose execution should be delayed.
+ * @param {number=} [delay=0] Delay in milliseconds.
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
+ * @param {...*=} Pass additional parameters to the executed function.
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
+ * promise will be resolved with is the return value of the `fn` function.
+ *
+ */
+ function timeout(fn, delay, invokeApply) {
+ if (!isFunction(fn)) {
+ invokeApply = delay;
+ delay = fn;
+ fn = noop;
+ }
+
+ var args = sliceArgs(arguments, 3),
+ skipApply = (isDefined(invokeApply) && !invokeApply),
+ deferred = (skipApply ? $$q : $q).defer(),
+ promise = deferred.promise,
+ timeoutId;
+
+ timeoutId = $browser.defer(function() {
+ try {
+ deferred.resolve(fn.apply(null, args));
+ } catch (e) {
+ deferred.reject(e);
+ $exceptionHandler(e);
+ }
+ finally {
+ delete deferreds[promise.$$timeoutId];
+ }
+
+ if (!skipApply) $rootScope.$apply();
+ }, delay);
+
+ promise.$$timeoutId = timeoutId;
+ deferreds[timeoutId] = deferred;
+
+ return promise;
+ }
+
+
+ /**
+ * @ngdoc method
+ * @name $timeout#cancel
+ *
+ * @description
+ * Cancels a task associated with the `promise`. As a result of this, the promise will be
+ * resolved with a rejection.
+ *
+ * @param {Promise=} promise Promise returned by the `$timeout` function.
+ * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
+ * canceled.
+ */
+ timeout.cancel = function(promise) {
+ if (promise && promise.$$timeoutId in deferreds) {
+ deferreds[promise.$$timeoutId].reject('canceled');
+ delete deferreds[promise.$$timeoutId];
+ return $browser.defer.cancel(promise.$$timeoutId);
+ }
+ return false;
+ };
+
+ return timeout;
+ }];
+}
+
+// NOTE: The usage of window and document instead of $window and $document here is
+// deliberate. This service depends on the specific behavior of anchor nodes created by the
+// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
+// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
+// doesn't know about mocked locations and resolves URLs to the real document - which is
+// exactly the behavior needed here. There is little value is mocking these out for this
+// service.
+var urlParsingNode = document.createElement("a");
+var originUrl = urlResolve(window.location.href);
+
+
+/**
+ *
+ * Implementation Notes for non-IE browsers
+ * ----------------------------------------
+ * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
+ * results both in the normalizing and parsing of the URL. Normalizing means that a relative
+ * URL will be resolved into an absolute URL in the context of the application document.
+ * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
+ * properties are all populated to reflect the normalized URL. This approach has wide
+ * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ *
+ * Implementation Notes for IE
+ * ---------------------------
+ * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
+ * browsers. However, the parsed components will not be set if the URL assigned did not specify
+ * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
+ * work around that by performing the parsing in a 2nd step by taking a previously normalized
+ * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
+ * properties such as protocol, hostname, port, etc.
+ *
+ * References:
+ * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
+ * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
+ * http://url.spec.whatwg.org/#urlutils
+ * https://github.com/angular/angular.js/pull/2902
+ * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
+ *
+ * @kind function
+ * @param {string} url The URL to be parsed.
+ * @description Normalizes and parses a URL.
+ * @returns {object} Returns the normalized URL as a dictionary.
+ *
+ * | member name | Description |
+ * |---------------|----------------|
+ * | href | A normalized version of the provided URL if it was not an absolute URL |
+ * | protocol | The protocol including the trailing colon |
+ * | host | The host and port (if the port is non-default) of the normalizedUrl |
+ * | search | The search params, minus the question mark |
+ * | hash | The hash string, minus the hash symbol
+ * | hostname | The hostname
+ * | port | The port, without ":"
+ * | pathname | The pathname, beginning with "/"
+ *
+ */
+function urlResolve(url) {
+ var href = url;
+
+ if (msie) {
+ // Normalize before parse. Refer Implementation Notes on why this is
+ // done in two steps on IE.
+ urlParsingNode.setAttribute("href", href);
+ href = urlParsingNode.href;
+ }
+
+ urlParsingNode.setAttribute('href', href);
+
+ // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
+ return {
+ href: urlParsingNode.href,
+ protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
+ host: urlParsingNode.host,
+ search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
+ hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
+ hostname: urlParsingNode.hostname,
+ port: urlParsingNode.port,
+ pathname: (urlParsingNode.pathname.charAt(0) === '/')
+ ? urlParsingNode.pathname
+ : '/' + urlParsingNode.pathname
+ };
+}
+
+/**
+ * Parse a request URL and determine whether this is a same-origin request as the application document.
+ *
+ * @param {string|object} requestUrl The url of the request as a string that will be resolved
+ * or a parsed URL object.
+ * @returns {boolean} Whether the request is for the same origin as the application document.
+ */
+function urlIsSameOrigin(requestUrl) {
+ var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
+ return (parsed.protocol === originUrl.protocol &&
+ parsed.host === originUrl.host);
+}
+
+/**
+ * @ngdoc service
+ * @name $window
+ *
+ * @description
+ * A reference to the browser's `window` object. While `window`
+ * is globally available in JavaScript, it causes testability problems, because
+ * it is a global variable. In angular we always refer to it through the
+ * `$window` service, so it may be overridden, removed or mocked for testing.
+ *
+ * Expressions, like the one defined for the `ngClick` directive in the example
+ * below, are evaluated with respect to the current scope. Therefore, there is
+ * no risk of inadvertently coding in a dependency on a global value in such an
+ * expression.
+ *
+ * @example
+ <example module="windowExample">
+ <file name="index.html">
+ <script>
+ angular.module('windowExample', [])
+ .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
+ $scope.greeting = 'Hello, World!';
+ $scope.doGreeting = function(greeting) {
+ $window.alert(greeting);
+ };
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="text" ng-model="greeting" aria-label="greeting" />
+ <button ng-click="doGreeting(greeting)">ALERT</button>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should display the greeting in the input box', function() {
+ element(by.model('greeting')).sendKeys('Hello, E2E Tests');
+ // If we click the button it will block the test runner
+ // element(':button').click();
+ });
+ </file>
+ </example>
+ */
+function $WindowProvider() {
+ this.$get = valueFn(window);
+}
+
+/**
+ * @name $$cookieReader
+ * @requires $document
+ *
+ * @description
+ * This is a private service for reading cookies used by $http and ngCookies
+ *
+ * @return {Object} a key/value map of the current cookies
+ */
+function $$CookieReader($document) {
+ var rawDocument = $document[0] || {};
+ var lastCookies = {};
+ var lastCookieString = '';
+
+ function safeDecodeURIComponent(str) {
+ try {
+ return decodeURIComponent(str);
+ } catch (e) {
+ return str;
+ }
+ }
+
+ return function() {
+ var cookieArray, cookie, i, index, name;
+ var currentCookieString = rawDocument.cookie || '';
+
+ if (currentCookieString !== lastCookieString) {
+ lastCookieString = currentCookieString;
+ cookieArray = lastCookieString.split('; ');
+ lastCookies = {};
+
+ for (i = 0; i < cookieArray.length; i++) {
+ cookie = cookieArray[i];
+ index = cookie.indexOf('=');
+ if (index > 0) { //ignore nameless cookies
+ name = safeDecodeURIComponent(cookie.substring(0, index));
+ // the first value that is seen for a cookie is the most
+ // specific one. values for the same cookie name that
+ // follow are for less specific paths.
+ if (isUndefined(lastCookies[name])) {
+ lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
+ }
+ }
+ }
+ }
+ return lastCookies;
+ };
+}
+
+$$CookieReader.$inject = ['$document'];
+
+function $$CookieReaderProvider() {
+ this.$get = $$CookieReader;
+}
+
+/* global currencyFilter: true,
+ dateFilter: true,
+ filterFilter: true,
+ jsonFilter: true,
+ limitToFilter: true,
+ lowercaseFilter: true,
+ numberFilter: true,
+ orderByFilter: true,
+ uppercaseFilter: true,
+ */
+
+/**
+ * @ngdoc provider
+ * @name $filterProvider
+ * @description
+ *
+ * Filters are just functions which transform input to an output. However filters need to be
+ * Dependency Injected. To achieve this a filter definition consists of a factory function which is
+ * annotated with dependencies and is responsible for creating a filter function.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ *
+ * ```js
+ * // Filter registration
+ * function MyModule($provide, $filterProvider) {
+ * // create a service to demonstrate injection (not always needed)
+ * $provide.value('greet', function(name){
+ * return 'Hello ' + name + '!';
+ * });
+ *
+ * // register a filter factory which uses the
+ * // greet service to demonstrate DI.
+ * $filterProvider.register('greet', function(greet){
+ * // return the filter function which uses the greet service
+ * // to generate salutation
+ * return function(text) {
+ * // filters need to be forgiving so check input validity
+ * return text && greet(text) || text;
+ * };
+ * });
+ * }
+ * ```
+ *
+ * The filter function is registered with the `$injector` under the filter name suffix with
+ * `Filter`.
+ *
+ * ```js
+ * it('should be the same instance', inject(
+ * function($filterProvider) {
+ * $filterProvider.register('reverse', function(){
+ * return ...;
+ * });
+ * },
+ * function($filter, reverseFilter) {
+ * expect($filter('reverse')).toBe(reverseFilter);
+ * });
+ * ```
+ *
+ *
+ * For more information about how angular filters work, and how to create your own filters, see
+ * {@link guide/filter Filters} in the Angular Developer Guide.
+ */
+
+/**
+ * @ngdoc service
+ * @name $filter
+ * @kind function
+ * @description
+ * Filters are used for formatting data displayed to the user.
+ *
+ * The general syntax in templates is as follows:
+ *
+ * {{ expression [| filter_name[:parameter_value] ... ] }}
+ *
+ * @param {String} name Name of the filter function to retrieve
+ * @return {Function} the filter function
+ * @example
+ <example name="$filter" module="filterExample">
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <h3>{{ originalText }}</h3>
+ <h3>{{ filteredText }}</h3>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('filterExample', [])
+ .controller('MainCtrl', function($scope, $filter) {
+ $scope.originalText = 'hello';
+ $scope.filteredText = $filter('uppercase')($scope.originalText);
+ });
+ </file>
+ </example>
+ */
+$FilterProvider.$inject = ['$provide'];
+function $FilterProvider($provide) {
+ var suffix = 'Filter';
+
+ /**
+ * @ngdoc method
+ * @name $filterProvider#register
+ * @param {string|Object} name Name of the filter function, or an object map of filters where
+ * the keys are the filter names and the values are the filter factories.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
+ * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
+ * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
+ * (`myapp_subsection_filterx`).
+ * </div>
+ * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.
+ * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
+ * of the registered filter instances.
+ */
+ function register(name, factory) {
+ if (isObject(name)) {
+ var filters = {};
+ forEach(name, function(filter, key) {
+ filters[key] = register(key, filter);
+ });
+ return filters;
+ } else {
+ return $provide.factory(name + suffix, factory);
+ }
+ }
+ this.register = register;
+
+ this.$get = ['$injector', function($injector) {
+ return function(name) {
+ return $injector.get(name + suffix);
+ };
+ }];
+
+ ////////////////////////////////////////
+
+ /* global
+ currencyFilter: false,
+ dateFilter: false,
+ filterFilter: false,
+ jsonFilter: false,
+ limitToFilter: false,
+ lowercaseFilter: false,
+ numberFilter: false,
+ orderByFilter: false,
+ uppercaseFilter: false,
+ */
+
+ register('currency', currencyFilter);
+ register('date', dateFilter);
+ register('filter', filterFilter);
+ register('json', jsonFilter);
+ register('limitTo', limitToFilter);
+ register('lowercase', lowercaseFilter);
+ register('number', numberFilter);
+ register('orderBy', orderByFilter);
+ register('uppercase', uppercaseFilter);
+}
+
+/**
+ * @ngdoc filter
+ * @name filter
+ * @kind function
+ *
+ * @description
+ * Selects a subset of items from `array` and returns it as a new array.
+ *
+ * @param {Array} array The source array.
+ * @param {string|Object|function()} expression The predicate to be used for selecting items from
+ * `array`.
+ *
+ * Can be one of:
+ *
+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
+ * objects with string properties in `array` that match this string will be returned. This also
+ * applies to nested object properties.
+ * The predicate can be negated by prefixing the string with `!`.
+ *
+ * - `Object`: A pattern object can be used to filter specific properties on objects contained
+ * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
+ * which have property `name` containing "M" and property `phone` containing "1". A special
+ * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
+ * property of the object or its nested object properties. That's equivalent to the simple
+ * substring match with a `string` as described above. The predicate can be negated by prefixing
+ * the string with `!`.
+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
+ * not containing "M".
+ *
+ * Note that a named property will match properties on the same level only, while the special
+ * `$` property will match properties on the same level or deeper. E.g. an array item like
+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
+ * **will** be matched by `{$: 'John'}`.
+ *
+ * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
+ * The function is called for each element of the array, with the element, its index, and
+ * the entire array itself as arguments.
+ *
+ * The final result is an array of those elements that the predicate returned true for.
+ *
+ * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
+ * determining if the expected value (from the filter expression) and actual value (from
+ * the object in the array) should be considered a match.
+ *
+ * Can be one of:
+ *
+ * - `function(actual, expected)`:
+ * The function will be given the object value and the predicate value to compare and
+ * should return true if both values should be considered equal.
+ *
+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
+ * This is essentially strict comparison of expected and actual.
+ *
+ * - `false|undefined`: A short hand for a function which will look for a substring match in case
+ * insensitive way.
+ *
+ * Primitive values are converted to strings. Objects are not compared against primitives,
+ * unless they have a custom `toString` method (e.g. `Date` objects).
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div ng-init="friends = [{name:'John', phone:'555-1276'},
+ {name:'Mary', phone:'800-BIG-MARY'},
+ {name:'Mike', phone:'555-4321'},
+ {name:'Adam', phone:'555-5678'},
+ {name:'Julie', phone:'555-8765'},
+ {name:'Juliette', phone:'555-5678'}]"></div>
+
+ <label>Search: <input ng-model="searchText"></label>
+ <table id="searchTextResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friend in friends | filter:searchText">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ </tr>
+ </table>
+ <hr>
+ <label>Any: <input ng-model="search.$"></label> <br>
+ <label>Name only <input ng-model="search.name"></label><br>
+ <label>Phone only <input ng-model="search.phone"></label><br>
+ <label>Equality <input type="checkbox" ng-model="strict"></label><br>
+ <table id="searchObjResults">
+ <tr><th>Name</th><th>Phone</th></tr>
+ <tr ng-repeat="friendObj in friends | filter:search:strict">
+ <td>{{friendObj.name}}</td>
+ <td>{{friendObj.phone}}</td>
+ </tr>
+ </table>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var expectFriendNames = function(expectedNames, key) {
+ element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
+ arr.forEach(function(wd, i) {
+ expect(wd.getText()).toMatch(expectedNames[i]);
+ });
+ });
+ };
+
+ it('should search across all fields when filtering with a string', function() {
+ var searchText = element(by.model('searchText'));
+ searchText.clear();
+ searchText.sendKeys('m');
+ expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
+
+ searchText.clear();
+ searchText.sendKeys('76');
+ expectFriendNames(['John', 'Julie'], 'friend');
+ });
+
+ it('should search in specific fields when filtering with a predicate object', function() {
+ var searchAny = element(by.model('search.$'));
+ searchAny.clear();
+ searchAny.sendKeys('i');
+ expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
+ });
+ it('should use a equal comparison when comparator is true', function() {
+ var searchName = element(by.model('search.name'));
+ var strict = element(by.model('strict'));
+ searchName.clear();
+ searchName.sendKeys('Julie');
+ strict.click();
+ expectFriendNames(['Julie'], 'friendObj');
+ });
+ </file>
+ </example>
+ */
+function filterFilter() {
+ return function(array, expression, comparator) {
+ if (!isArrayLike(array)) {
+ if (array == null) {
+ return array;
+ } else {
+ throw minErr('filter')('notarray', 'Expected array but received: {0}', array);
+ }
+ }
+
+ var expressionType = getTypeForFilter(expression);
+ var predicateFn;
+ var matchAgainstAnyProp;
+
+ switch (expressionType) {
+ case 'function':
+ predicateFn = expression;
+ break;
+ case 'boolean':
+ case 'null':
+ case 'number':
+ case 'string':
+ matchAgainstAnyProp = true;
+ //jshint -W086
+ case 'object':
+ //jshint +W086
+ predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
+ break;
+ default:
+ return array;
+ }
+
+ return Array.prototype.filter.call(array, predicateFn);
+ };
+}
+
+// Helper functions for `filterFilter`
+function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
+ var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
+ var predicateFn;
+
+ if (comparator === true) {
+ comparator = equals;
+ } else if (!isFunction(comparator)) {
+ comparator = function(actual, expected) {
+ if (isUndefined(actual)) {
+ // No substring matching against `undefined`
+ return false;
+ }
+ if ((actual === null) || (expected === null)) {
+ // No substring matching against `null`; only match against `null`
+ return actual === expected;
+ }
+ if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {
+ // Should not compare primitives against objects, unless they have custom `toString` method
+ return false;
+ }
+
+ actual = lowercase('' + actual);
+ expected = lowercase('' + expected);
+ return actual.indexOf(expected) !== -1;
+ };
+ }
+
+ predicateFn = function(item) {
+ if (shouldMatchPrimitives && !isObject(item)) {
+ return deepCompare(item, expression.$, comparator, false);
+ }
+ return deepCompare(item, expression, comparator, matchAgainstAnyProp);
+ };
+
+ return predicateFn;
+}
+
+function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
+ var actualType = getTypeForFilter(actual);
+ var expectedType = getTypeForFilter(expected);
+
+ if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
+ return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
+ } else if (isArray(actual)) {
+ // In case `actual` is an array, consider it a match
+ // if ANY of it's items matches `expected`
+ return actual.some(function(item) {
+ return deepCompare(item, expected, comparator, matchAgainstAnyProp);
+ });
+ }
+
+ switch (actualType) {
+ case 'object':
+ var key;
+ if (matchAgainstAnyProp) {
+ for (key in actual) {
+ if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
+ return true;
+ }
+ }
+ return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
+ } else if (expectedType === 'object') {
+ for (key in expected) {
+ var expectedVal = expected[key];
+ if (isFunction(expectedVal) || isUndefined(expectedVal)) {
+ continue;
+ }
+
+ var matchAnyProperty = key === '$';
+ var actualVal = matchAnyProperty ? actual : actual[key];
+ if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return comparator(actual, expected);
+ }
+ break;
+ case 'function':
+ return false;
+ default:
+ return comparator(actual, expected);
+ }
+}
+
+// Used for easily differentiating between `null` and actual `object`
+function getTypeForFilter(val) {
+ return (val === null) ? 'null' : typeof val;
+}
+
+/**
+ * @ngdoc filter
+ * @name currency
+ * @kind function
+ *
+ * @description
+ * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
+ * symbol for current locale is used.
+ *
+ * @param {number} amount Input to filter.
+ * @param {string=} symbol Currency symbol or identifier to be displayed.
+ * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
+ * @returns {string} Formatted number.
+ *
+ *
+ * @example
+ <example module="currencyExample">
+ <file name="index.html">
+ <script>
+ angular.module('currencyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.amount = 1234.56;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input type="number" ng-model="amount" aria-label="amount"> <br>
+ default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
+ custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
+ no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should init with 1234.56', function() {
+ expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
+ expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
+ });
+ it('should update', function() {
+ if (browser.params.browser == 'safari') {
+ // Safari does not understand the minus key. See
+ // https://github.com/angular/protractor/issues/481
+ return;
+ }
+ element(by.model('amount')).clear();
+ element(by.model('amount')).sendKeys('-1234');
+ expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');
+ expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');
+ expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');
+ });
+ </file>
+ </example>
+ */
+currencyFilter.$inject = ['$locale'];
+function currencyFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(amount, currencySymbol, fractionSize) {
+ if (isUndefined(currencySymbol)) {
+ currencySymbol = formats.CURRENCY_SYM;
+ }
+
+ if (isUndefined(fractionSize)) {
+ fractionSize = formats.PATTERNS[1].maxFrac;
+ }
+
+ // if null or undefined pass it through
+ return (amount == null)
+ ? amount
+ : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
+ replace(/\u00A4/g, currencySymbol);
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name number
+ * @kind function
+ *
+ * @description
+ * Formats a number as text.
+ *
+ * If the input is null or undefined, it will just be returned.
+ * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
+ * If the input is not a number an empty string is returned.
+ *
+ *
+ * @param {number|string} number Number to format.
+ * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
+ * If this is not provided then the fraction size is computed from the current locale's number
+ * formatting pattern. In the case of the default locale, it will be 3.
+ * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit.
+ *
+ * @example
+ <example module="numberFilterExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberFilterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = 1234.56789;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <label>Enter number: <input ng-model='val'></label><br>
+ Default formatting: <span id='number-default'>{{val | number}}</span><br>
+ No fractions: <span>{{val | number:0}}</span><br>
+ Negative number: <span>{{-val | number:4}}</span>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format numbers', function() {
+ expect(element(by.id('number-default')).getText()).toBe('1,234.568');
+ expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
+ });
+
+ it('should update', function() {
+ element(by.model('val')).clear();
+ element(by.model('val')).sendKeys('3374.333');
+ expect(element(by.id('number-default')).getText()).toBe('3,374.333');
+ expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
+ expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
+ });
+ </file>
+ </example>
+ */
+
+
+numberFilter.$inject = ['$locale'];
+function numberFilter($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+ return function(number, fractionSize) {
+
+ // if null or undefined pass it through
+ return (number == null)
+ ? number
+ : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
+ fractionSize);
+ };
+}
+
+var DECIMAL_SEP = '.';
+function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
+ if (isObject(number)) return '';
+
+ var isNegative = number < 0;
+ number = Math.abs(number);
+
+ var isInfinity = number === Infinity;
+ if (!isInfinity && !isFinite(number)) return '';
+
+ var numStr = number + '',
+ formatedText = '',
+ hasExponent = false,
+ parts = [];
+
+ if (isInfinity) formatedText = '\u221e';
+
+ if (!isInfinity && numStr.indexOf('e') !== -1) {
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
+ number = 0;
+ } else {
+ formatedText = numStr;
+ hasExponent = true;
+ }
+ }
+
+ if (!isInfinity && !hasExponent) {
+ var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
+
+ // determine fractionSize if it is not specified
+ if (isUndefined(fractionSize)) {
+ fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
+ }
+
+ // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
+ // inspired by:
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
+ number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
+
+ var fraction = ('' + number).split(DECIMAL_SEP);
+ var whole = fraction[0];
+ fraction = fraction[1] || '';
+
+ var i, pos = 0,
+ lgroup = pattern.lgSize,
+ group = pattern.gSize;
+
+ if (whole.length >= (lgroup + group)) {
+ pos = whole.length - lgroup;
+ for (i = 0; i < pos; i++) {
+ if ((pos - i) % group === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+ }
+
+ for (i = pos; i < whole.length; i++) {
+ if ((whole.length - i) % lgroup === 0 && i !== 0) {
+ formatedText += groupSep;
+ }
+ formatedText += whole.charAt(i);
+ }
+
+ // format fraction part.
+ while (fraction.length < fractionSize) {
+ fraction += '0';
+ }
+
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
+ } else {
+ if (fractionSize > 0 && number < 1) {
+ formatedText = number.toFixed(fractionSize);
+ number = parseFloat(formatedText);
+ formatedText = formatedText.replace(DECIMAL_SEP, decimalSep);
+ }
+ }
+
+ if (number === 0) {
+ isNegative = false;
+ }
+
+ parts.push(isNegative ? pattern.negPre : pattern.posPre,
+ formatedText,
+ isNegative ? pattern.negSuf : pattern.posSuf);
+ return parts.join('');
+}
+
+function padNumber(num, digits, trim) {
+ var neg = '';
+ if (num < 0) {
+ neg = '-';
+ num = -num;
+ }
+ num = '' + num;
+ while (num.length < digits) num = '0' + num;
+ if (trim) {
+ num = num.substr(num.length - digits);
+ }
+ return neg + num;
+}
+
+
+function dateGetter(name, size, offset, trim) {
+ offset = offset || 0;
+ return function(date) {
+ var value = date['get' + name]();
+ if (offset > 0 || value > -offset) {
+ value += offset;
+ }
+ if (value === 0 && offset == -12) value = 12;
+ return padNumber(value, size, trim);
+ };
+}
+
+function dateStrGetter(name, shortForm) {
+ return function(date, formats) {
+ var value = date['get' + name]();
+ var get = uppercase(shortForm ? ('SHORT' + name) : name);
+
+ return formats[get][value];
+ };
+}
+
+function timeZoneGetter(date, formats, offset) {
+ var zone = -1 * offset;
+ var paddedZone = (zone >= 0) ? "+" : "";
+
+ paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
+ padNumber(Math.abs(zone % 60), 2);
+
+ return paddedZone;
+}
+
+function getFirstThursdayOfYear(year) {
+ // 0 = index of January
+ var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
+ // 4 = index of Thursday (+1 to account for 1st = 5)
+ // 11 = index of *next* Thursday (+1 account for 1st = 12)
+ return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
+}
+
+function getThursdayThisWeek(datetime) {
+ return new Date(datetime.getFullYear(), datetime.getMonth(),
+ // 4 = index of Thursday
+ datetime.getDate() + (4 - datetime.getDay()));
+}
+
+function weekGetter(size) {
+ return function(date) {
+ var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
+ thisThurs = getThursdayThisWeek(date);
+
+ var diff = +thisThurs - +firstThurs,
+ result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
+
+ return padNumber(result, size);
+ };
+}
+
+function ampmGetter(date, formats) {
+ return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
+}
+
+function eraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
+}
+
+function longEraGetter(date, formats) {
+ return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
+}
+
+var DATE_FORMATS = {
+ yyyy: dateGetter('FullYear', 4),
+ yy: dateGetter('FullYear', 2, 0, true),
+ y: dateGetter('FullYear', 1),
+ MMMM: dateStrGetter('Month'),
+ MMM: dateStrGetter('Month', true),
+ MM: dateGetter('Month', 2, 1),
+ M: dateGetter('Month', 1, 1),
+ dd: dateGetter('Date', 2),
+ d: dateGetter('Date', 1),
+ HH: dateGetter('Hours', 2),
+ H: dateGetter('Hours', 1),
+ hh: dateGetter('Hours', 2, -12),
+ h: dateGetter('Hours', 1, -12),
+ mm: dateGetter('Minutes', 2),
+ m: dateGetter('Minutes', 1),
+ ss: dateGetter('Seconds', 2),
+ s: dateGetter('Seconds', 1),
+ // while ISO 8601 requires fractions to be prefixed with `.` or `,`
+ // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
+ sss: dateGetter('Milliseconds', 3),
+ EEEE: dateStrGetter('Day'),
+ EEE: dateStrGetter('Day', true),
+ a: ampmGetter,
+ Z: timeZoneGetter,
+ ww: weekGetter(2),
+ w: weekGetter(1),
+ G: eraGetter,
+ GG: eraGetter,
+ GGG: eraGetter,
+ GGGG: longEraGetter
+};
+
+var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
+ NUMBER_STRING = /^\-?\d+$/;
+
+/**
+ * @ngdoc filter
+ * @name date
+ * @kind function
+ *
+ * @description
+ * Formats `date` to a string based on the requested `format`.
+ *
+ * `format` string can be composed of the following elements:
+ *
+ * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
+ * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
+ * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
+ * * `'MMMM'`: Month in year (January-December)
+ * * `'MMM'`: Month in year (Jan-Dec)
+ * * `'MM'`: Month in year, padded (01-12)
+ * * `'M'`: Month in year (1-12)
+ * * `'dd'`: Day in month, padded (01-31)
+ * * `'d'`: Day in month (1-31)
+ * * `'EEEE'`: Day in Week,(Sunday-Saturday)
+ * * `'EEE'`: Day in Week, (Sun-Sat)
+ * * `'HH'`: Hour in day, padded (00-23)
+ * * `'H'`: Hour in day (0-23)
+ * * `'hh'`: Hour in AM/PM, padded (01-12)
+ * * `'h'`: Hour in AM/PM, (1-12)
+ * * `'mm'`: Minute in hour, padded (00-59)
+ * * `'m'`: Minute in hour (0-59)
+ * * `'ss'`: Second in minute, padded (00-59)
+ * * `'s'`: Second in minute (0-59)
+ * * `'sss'`: Millisecond in second, padded (000-999)
+ * * `'a'`: AM/PM marker
+ * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
+ * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
+ * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
+ * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
+ * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
+ *
+ * `format` string can also be one of the following predefined
+ * {@link guide/i18n localizable formats}:
+ *
+ * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
+ * (e.g. Sep 3, 2010 12:05:08 PM)
+ * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)
+ * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
+ * (e.g. Friday, September 3, 2010)
+ * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
+ * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
+ * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
+ * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
+ * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
+ *
+ * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
+ * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
+ * (e.g. `"h 'o''clock'"`).
+ *
+ * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
+ * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
+ * specified in the string input, the time is considered to be in the local timezone.
+ * @param {string=} format Formatting rules (see Description). If not specified,
+ * `mediumDate` is used.
+ * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the
+ * continental US time zone abbreviations, but for general use, use a time zone offset, for
+ * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
+ * If not specified, the timezone of the browser will be used.
+ * @returns {string} Formatted string or the input if input is not recognized as date/millis.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
+ <span>{{1288323623006 | date:'medium'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
+ <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
+ <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
+ <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
+ <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should format date', function() {
+ expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
+ toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
+ expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
+ expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
+ toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
+ expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
+ toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
+ });
+ </file>
+ </example>
+ */
+dateFilter.$inject = ['$locale'];
+function dateFilter($locale) {
+
+
+ var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
+ // 1 2 3 4 5 6 7 8 9 10 11
+ function jsonStringToDate(string) {
+ var match;
+ if (match = string.match(R_ISO8601_STR)) {
+ var date = new Date(0),
+ tzHour = 0,
+ tzMin = 0,
+ dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
+ timeSetter = match[8] ? date.setUTCHours : date.setHours;
+
+ if (match[9]) {
+ tzHour = toInt(match[9] + match[10]);
+ tzMin = toInt(match[9] + match[11]);
+ }
+ dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
+ var h = toInt(match[4] || 0) - tzHour;
+ var m = toInt(match[5] || 0) - tzMin;
+ var s = toInt(match[6] || 0);
+ var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
+ timeSetter.call(date, h, m, s, ms);
+ return date;
+ }
+ return string;
+ }
+
+
+ return function(date, format, timezone) {
+ var text = '',
+ parts = [],
+ fn, match;
+
+ format = format || 'mediumDate';
+ format = $locale.DATETIME_FORMATS[format] || format;
+ if (isString(date)) {
+ date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);
+ }
+
+ if (isNumber(date)) {
+ date = new Date(date);
+ }
+
+ if (!isDate(date) || !isFinite(date.getTime())) {
+ return date;
+ }
+
+ while (format) {
+ match = DATE_FORMATS_SPLIT.exec(format);
+ if (match) {
+ parts = concat(parts, match, 1);
+ format = parts.pop();
+ } else {
+ parts.push(format);
+ format = null;
+ }
+ }
+
+ var dateTimezoneOffset = date.getTimezoneOffset();
+ if (timezone) {
+ dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
+ date = convertTimezoneToLocal(date, timezone, true);
+ }
+ forEach(parts, function(value) {
+ fn = DATE_FORMATS[value];
+ text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
+ : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
+ });
+
+ return text;
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name json
+ * @kind function
+ *
+ * @description
+ * Allows you to convert a JavaScript object into JSON string.
+ *
+ * This filter is mostly useful for debugging. When using the double curly {{value}} notation
+ * the binding is automatically converted to JSON.
+ *
+ * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
+ * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
+ * @returns {string} JSON string.
+ *
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
+ <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should jsonify filtered objects', function() {
+ expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
+ });
+ </file>
+ </example>
+ *
+ */
+function jsonFilter() {
+ return function(object, spacing) {
+ if (isUndefined(spacing)) {
+ spacing = 2;
+ }
+ return toJson(object, spacing);
+ };
+}
+
+
+/**
+ * @ngdoc filter
+ * @name lowercase
+ * @kind function
+ * @description
+ * Converts string to lowercase.
+ * @see angular.lowercase
+ */
+var lowercaseFilter = valueFn(lowercase);
+
+
+/**
+ * @ngdoc filter
+ * @name uppercase
+ * @kind function
+ * @description
+ * Converts string to uppercase.
+ * @see angular.uppercase
+ */
+var uppercaseFilter = valueFn(uppercase);
+
+/**
+ * @ngdoc filter
+ * @name limitTo
+ * @kind function
+ *
+ * @description
+ * Creates a new array or string containing only a specified number of elements. The elements
+ * are taken from either the beginning or the end of the source array, string or number, as specified by
+ * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
+ * converted to a string.
+ *
+ * @param {Array|string|number} input Source array, string or number to be limited.
+ * @param {string|number} limit The length of the returned array or string. If the `limit` number
+ * is positive, `limit` number of items from the beginning of the source array/string are copied.
+ * If the number is negative, `limit` number of items from the end of the source array/string
+ * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
+ * the input will be returned unchanged.
+ * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
+ * indicates an offset from the end of `input`. Defaults to `0`.
+ * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
+ * had less than `limit` elements.
+ *
+ * @example
+ <example module="limitToExample">
+ <file name="index.html">
+ <script>
+ angular.module('limitToExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.numbers = [1,2,3,4,5,6,7,8,9];
+ $scope.letters = "abcdefghi";
+ $scope.longNumber = 2345432342;
+ $scope.numLimit = 3;
+ $scope.letterLimit = 3;
+ $scope.longNumberLimit = 3;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <label>
+ Limit {{numbers}} to:
+ <input type="number" step="1" ng-model="numLimit">
+ </label>
+ <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
+ <label>
+ Limit {{letters}} to:
+ <input type="number" step="1" ng-model="letterLimit">
+ </label>
+ <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
+ <label>
+ Limit {{longNumber}} to:
+ <input type="number" step="1" ng-model="longNumberLimit">
+ </label>
+ <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var numLimitInput = element(by.model('numLimit'));
+ var letterLimitInput = element(by.model('letterLimit'));
+ var longNumberLimitInput = element(by.model('longNumberLimit'));
+ var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
+ var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
+ var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
+
+ it('should limit the number array to first three items', function() {
+ expect(numLimitInput.getAttribute('value')).toBe('3');
+ expect(letterLimitInput.getAttribute('value')).toBe('3');
+ expect(longNumberLimitInput.getAttribute('value')).toBe('3');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abc');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
+ });
+
+ // There is a bug in safari and protractor that doesn't like the minus key
+ // it('should update the output when -3 is entered', function() {
+ // numLimitInput.clear();
+ // numLimitInput.sendKeys('-3');
+ // letterLimitInput.clear();
+ // letterLimitInput.sendKeys('-3');
+ // longNumberLimitInput.clear();
+ // longNumberLimitInput.sendKeys('-3');
+ // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
+ // expect(limitedLetters.getText()).toEqual('Output letters: ghi');
+ // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
+ // });
+
+ it('should not exceed the maximum size of input array', function() {
+ numLimitInput.clear();
+ numLimitInput.sendKeys('100');
+ letterLimitInput.clear();
+ letterLimitInput.sendKeys('100');
+ longNumberLimitInput.clear();
+ longNumberLimitInput.sendKeys('100');
+ expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
+ expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
+ expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
+ });
+ </file>
+ </example>
+*/
+function limitToFilter() {
+ return function(input, limit, begin) {
+ if (Math.abs(Number(limit)) === Infinity) {
+ limit = Number(limit);
+ } else {
+ limit = toInt(limit);
+ }
+ if (isNaN(limit)) return input;
+
+ if (isNumber(input)) input = input.toString();
+ if (!isArray(input) && !isString(input)) return input;
+
+ begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
+ begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
+
+ if (limit >= 0) {
+ return input.slice(begin, begin + limit);
+ } else {
+ if (begin === 0) {
+ return input.slice(limit, input.length);
+ } else {
+ return input.slice(Math.max(0, begin + limit), begin);
+ }
+ }
+ };
+}
+
+/**
+ * @ngdoc filter
+ * @name orderBy
+ * @kind function
+ *
+ * @description
+ * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
+ * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
+ * as expected, make sure they are actually being saved as numbers and not strings.
+ *
+ * @param {Array} array The array to sort.
+ * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
+ * used by the comparator to determine the order of elements.
+ *
+ * Can be one of:
+ *
+ * - `function`: Getter function. The result of this function will be sorted using the
+ * `<`, `===`, `>` operator.
+ * - `string`: An Angular expression. The result of this expression is used to compare elements
+ * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
+ * 3 first characters of a property called `name`). The result of a constant expression
+ * is interpreted as a property name to be used in comparisons (for example `"special name"`
+ * to sort object by the value of their `special name` property). An expression can be
+ * optionally prefixed with `+` or `-` to control ascending or descending sort order
+ * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
+ * element itself is used to compare where sorting.
+ * - `Array`: An array of function or string predicates. The first predicate in the array
+ * is used for sorting, but when two items are equivalent, the next predicate is used.
+ *
+ * If the predicate is missing or empty then it defaults to `'+'`.
+ *
+ * @param {boolean=} reverse Reverse the order of the array.
+ * @returns {Array} Sorted copy of the source array.
+ *
+ *
+ * @example
+ * The example below demonstrates a simple ngRepeat, where the data is sorted
+ * by age in descending order (predicate is set to `'-age'`).
+ * `reverse` is not set, which means it defaults to `false`.
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th>Name</th>
+ <th>Phone Number</th>
+ <th>Age</th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:'-age'">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * The predicate and reverse parameters can be controlled dynamically through scope properties,
+ * as shown in the next example.
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <script>
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ $scope.predicate = 'age';
+ $scope.reverse = true;
+ $scope.order = function(predicate) {
+ $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
+ $scope.predicate = predicate;
+ };
+ }]);
+ </script>
+ <style type="text/css">
+ .sortorder:after {
+ content: '\25b2';
+ }
+ .sortorder.reverse:after {
+ content: '\25bc';
+ }
+ </style>
+ <div ng-controller="ExampleController">
+ <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
+ <hr/>
+ [ <a href="" ng-click="predicate=''">unsorted</a> ]
+ <table class="friend">
+ <tr>
+ <th>
+ <a href="" ng-click="order('name')">Name</a>
+ <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
+ </th>
+ <th>
+ <a href="" ng-click="order('phone')">Phone Number</a>
+ <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
+ </th>
+ <th>
+ <a href="" ng-click="order('age')">Age</a>
+ <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
+ </th>
+ </tr>
+ <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+ </example>
+ *
+ * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
+ * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
+ * desired parameters.
+ *
+ * Example:
+ *
+ * @example
+ <example module="orderByExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <table class="friend">
+ <tr>
+ <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
+ (<a href="" ng-click="order('-name',false)">^</a>)</th>
+ <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
+ <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
+ </tr>
+ <tr ng-repeat="friend in friends">
+ <td>{{friend.name}}</td>
+ <td>{{friend.phone}}</td>
+ <td>{{friend.age}}</td>
+ </tr>
+ </table>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
+ var orderBy = $filter('orderBy');
+ $scope.friends = [
+ { name: 'John', phone: '555-1212', age: 10 },
+ { name: 'Mary', phone: '555-9876', age: 19 },
+ { name: 'Mike', phone: '555-4321', age: 21 },
+ { name: 'Adam', phone: '555-5678', age: 35 },
+ { name: 'Julie', phone: '555-8765', age: 29 }
+ ];
+ $scope.order = function(predicate, reverse) {
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
+ };
+ $scope.order('-age',false);
+ }]);
+ </file>
+</example>
+ */
+orderByFilter.$inject = ['$parse'];
+function orderByFilter($parse) {
+ return function(array, sortPredicate, reverseOrder) {
+
+ if (!(isArrayLike(array))) return array;
+
+ if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
+ if (sortPredicate.length === 0) { sortPredicate = ['+']; }
+
+ var predicates = processPredicates(sortPredicate, reverseOrder);
+ // Add a predicate at the end that evaluates to the element index. This makes the
+ // sort stable as it works as a tie-breaker when all the input predicates cannot
+ // distinguish between two elements.
+ predicates.push({ get: function() { return {}; }, descending: reverseOrder ? -1 : 1});
+
+ // The next three lines are a version of a Swartzian Transform idiom from Perl
+ // (sometimes called the Decorate-Sort-Undecorate idiom)
+ // See https://en.wikipedia.org/wiki/Schwartzian_transform
+ var compareValues = Array.prototype.map.call(array, getComparisonObject);
+ compareValues.sort(doComparison);
+ array = compareValues.map(function(item) { return item.value; });
+
+ return array;
+
+ function getComparisonObject(value, index) {
+ return {
+ value: value,
+ predicateValues: predicates.map(function(predicate) {
+ return getPredicateValue(predicate.get(value), index);
+ })
+ };
+ }
+
+ function doComparison(v1, v2) {
+ var result = 0;
+ for (var index=0, length = predicates.length; index < length; ++index) {
+ result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
+ if (result) break;
+ }
+ return result;
+ }
+ };
+
+ function processPredicates(sortPredicate, reverseOrder) {
+ reverseOrder = reverseOrder ? -1 : 1;
+ return sortPredicate.map(function(predicate) {
+ var descending = 1, get = identity;
+
+ if (isFunction(predicate)) {
+ get = predicate;
+ } else if (isString(predicate)) {
+ if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
+ descending = predicate.charAt(0) == '-' ? -1 : 1;
+ predicate = predicate.substring(1);
+ }
+ if (predicate !== '') {
+ get = $parse(predicate);
+ if (get.constant) {
+ var key = get();
+ get = function(value) { return value[key]; };
+ }
+ }
+ }
+ return { get: get, descending: descending * reverseOrder };
+ });
+ }
+
+ function isPrimitive(value) {
+ switch (typeof value) {
+ case 'number': /* falls through */
+ case 'boolean': /* falls through */
+ case 'string':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function objectValue(value, index) {
+ // If `valueOf` is a valid function use that
+ if (typeof value.valueOf === 'function') {
+ value = value.valueOf();
+ if (isPrimitive(value)) return value;
+ }
+ // If `toString` is a valid function and not the one from `Object.prototype` use that
+ if (hasCustomToString(value)) {
+ value = value.toString();
+ if (isPrimitive(value)) return value;
+ }
+ // We have a basic object so we use the position of the object in the collection
+ return index;
+ }
+
+ function getPredicateValue(value, index) {
+ var type = typeof value;
+ if (value === null) {
+ type = 'string';
+ value = 'null';
+ } else if (type === 'string') {
+ value = value.toLowerCase();
+ } else if (type === 'object') {
+ value = objectValue(value, index);
+ }
+ return { value: value, type: type };
+ }
+
+ function compare(v1, v2) {
+ var result = 0;
+ if (v1.type === v2.type) {
+ if (v1.value !== v2.value) {
+ result = v1.value < v2.value ? -1 : 1;
+ }
+ } else {
+ result = v1.type < v2.type ? -1 : 1;
+ }
+ return result;
+ }
+}
+
+function ngDirective(directive) {
+ if (isFunction(directive)) {
+ directive = {
+ link: directive
+ };
+ }
+ directive.restrict = directive.restrict || 'AC';
+ return valueFn(directive);
+}
+
+/**
+ * @ngdoc directive
+ * @name a
+ * @restrict E
+ *
+ * @description
+ * Modifies the default behavior of the html A tag so that the default action is prevented when
+ * the href attribute is empty.
+ *
+ * This change permits the easy creation of action links with the `ngClick` directive
+ * without changing the location or causing page reloads, e.g.:
+ * `<a href="" ng-click="list.addItem()">Add Item</a>`
+ */
+var htmlAnchorDirective = valueFn({
+ restrict: 'E',
+ compile: function(element, attr) {
+ if (!attr.href && !attr.xlinkHref) {
+ return function(scope, element) {
+ // If the linked element is not an anchor tag anymore, do nothing
+ if (element[0].nodeName.toLowerCase() !== 'a') return;
+
+ // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
+ var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
+ 'xlink:href' : 'href';
+ element.on('click', function(event) {
+ // if we have no href url, then don't navigate anywhere.
+ if (!element.attr(href)) {
+ event.preventDefault();
+ }
+ });
+ };
+ }
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngHref
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in an href attribute will
+ * make the link go to the wrong URL if the user clicks it before
+ * Angular has a chance to replace the `{{hash}}` markup with its
+ * value. Until Angular replaces the markup the link will be broken
+ * and will most likely return a 404 error. The `ngHref` directive
+ * solves this problem.
+ *
+ * The wrong way to write it:
+ * ```html
+ * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
+ * ```
+ *
+ * @element A
+ * @param {template} ngHref any string which can contain `{{}}` markup.
+ *
+ * @example
+ * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
+ * in links and their different behaviors:
+ <example>
+ <file name="index.html">
+ <input ng-model="value" /><br />
+ <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
+ <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
+ <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
+ <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
+ <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
+ <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should execute ng-click but not reload when href without value', function() {
+ element(by.id('link-1')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('1');
+ expect(element(by.id('link-1')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when href empty string', function() {
+ element(by.id('link-2')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('2');
+ expect(element(by.id('link-2')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click and change url when ng-href specified', function() {
+ expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
+
+ element(by.id('link-3')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/123$/);
+ });
+ }, 5000, 'page should navigate to /123');
+ });
+
+ it('should execute ng-click but not reload when href empty string and name specified', function() {
+ element(by.id('link-4')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('4');
+ expect(element(by.id('link-4')).getAttribute('href')).toBe('');
+ });
+
+ it('should execute ng-click but not reload when no href but name specified', function() {
+ element(by.id('link-5')).click();
+ expect(element(by.model('value')).getAttribute('value')).toEqual('5');
+ expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
+ });
+
+ it('should only change url when only ng-href', function() {
+ element(by.model('value')).clear();
+ element(by.model('value')).sendKeys('6');
+ expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
+
+ element(by.id('link-6')).click();
+
+ // At this point, we navigate away from an Angular page, so we need
+ // to use browser.driver to get the base webdriver.
+ browser.wait(function() {
+ return browser.driver.getCurrentUrl().then(function(url) {
+ return url.match(/\/6$/);
+ });
+ }, 5000, 'page should navigate to /6');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrc
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrc` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrc any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngSrcset
+ * @restrict A
+ * @priority 99
+ *
+ * @description
+ * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
+ * work right: The browser will fetch from the URL with the literal
+ * text `{{hash}}` until Angular replaces the expression inside
+ * `{{hash}}`. The `ngSrcset` directive solves this problem.
+ *
+ * The buggy way to write it:
+ * ```html
+ * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
+ * ```
+ *
+ * The correct way to write it:
+ * ```html
+ * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
+ * ```
+ *
+ * @element IMG
+ * @param {template} ngSrcset any string which can contain `{{}}` markup.
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngDisabled
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ *
+ * This directive sets the `disabled` attribute on the element if the
+ * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
+ *
+ * A special directive is necessary because we cannot use interpolation inside the `disabled`
+ * attribute. The following example would make the button enabled on Chrome/Firefox
+ * but not on older IEs:
+ *
+ * ```html
+ * <!-- See below for an example of ng-disabled being used correctly -->
+ * <div ng-init="isDisabled = false">
+ * <button disabled="{{isDisabled}}">Disabled</button>
+ * </div>
+ * ```
+ *
+ * This is because the HTML specification does not require browsers to preserve the values of
+ * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/>
+ <button ng-model="button" ng-disabled="checked">Button</button>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle button', function() {
+ expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
+ * then the `disabled` attribute will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngChecked
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
+ *
+ * Note that this directive should not be used together with {@link ngModel `ngModel`},
+ * as this can lead to unexpected behavior.
+ *
+ * ### Why do we need `ngChecked`?
+ *
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as checked. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngChecked` directive solves this problem for the `checked` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/>
+ <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input">
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check both checkBoxes', function() {
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
+ element(by.model('master')).click();
+ expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
+ * then the `checked` attribute will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngReadonly
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as readonly. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngReadonly` directive solves this problem for the `readonly` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/>
+ <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" />
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle readonly attr', function() {
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
+ element(by.model('checked')).click();
+ expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element INPUT
+ * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
+ * then special attribute "readonly" will be set on the element
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSelected
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as selected. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngSelected` directive solves this problem for the `selected` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/>
+ <select aria-label="ngSelected demo">
+ <option>Hello!</option>
+ <option id="greet" ng-selected="selected">Greetings!</option>
+ </select>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should select Greetings!', function() {
+ expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
+ element(by.model('selected')).click();
+ expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element OPTION
+ * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
+ * then special attribute "selected" will be set on the element
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngOpen
+ * @restrict A
+ * @priority 100
+ *
+ * @description
+ * The HTML specification does not require browsers to preserve the values of boolean attributes
+ * such as open. (Their presence means true and their absence means false.)
+ * If we put an Angular interpolation expression into such an attribute then the
+ * binding information would be lost when the browser removes the attribute.
+ * The `ngOpen` directive solves this problem for the `open` attribute.
+ * This complementary directive is not removed by the browser and so provides
+ * a permanent reliable place to store the binding information.
+ * @example
+ <example>
+ <file name="index.html">
+ <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/>
+ <details id="details" ng-open="open">
+ <summary>Show/Hide me</summary>
+ </details>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should toggle open', function() {
+ expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
+ element(by.model('open')).click();
+ expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
+ });
+ </file>
+ </example>
+ *
+ * @element DETAILS
+ * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
+ * then special attribute "open" will be set on the element
+ */
+
+var ngAttributeAliasDirectives = {};
+
+// boolean attrs are evaluated
+forEach(BOOLEAN_ATTR, function(propName, attrName) {
+ // binding to multiple is not supported
+ if (propName == "multiple") return;
+
+ function defaultLinkFn(scope, element, attr) {
+ scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
+ attr.$set(attrName, !!value);
+ });
+ }
+
+ var normalized = directiveNormalize('ng-' + attrName);
+ var linkFn = defaultLinkFn;
+
+ if (propName === 'checked') {
+ linkFn = function(scope, element, attr) {
+ // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
+ if (attr.ngModel !== attr[normalized]) {
+ defaultLinkFn(scope, element, attr);
+ }
+ };
+ }
+
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ link: linkFn
+ };
+ };
+});
+
+// aliased input attrs are evaluated
+forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
+ ngAttributeAliasDirectives[ngAttr] = function() {
+ return {
+ priority: 100,
+ link: function(scope, element, attr) {
+ //special case ngPattern when a literal regular expression value
+ //is used as the expression (this way we don't have to watch anything).
+ if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
+ var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
+ if (match) {
+ attr.$set("ngPattern", new RegExp(match[1], match[2]));
+ return;
+ }
+ }
+
+ scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
+ attr.$set(ngAttr, value);
+ });
+ }
+ };
+ };
+});
+
+// ng-src, ng-srcset, ng-href are interpolated
+forEach(['src', 'srcset', 'href'], function(attrName) {
+ var normalized = directiveNormalize('ng-' + attrName);
+ ngAttributeAliasDirectives[normalized] = function() {
+ return {
+ priority: 99, // it needs to run after the attributes are interpolated
+ link: function(scope, element, attr) {
+ var propName = attrName,
+ name = attrName;
+
+ if (attrName === 'href' &&
+ toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
+ name = 'xlinkHref';
+ attr.$attr[name] = 'xlink:href';
+ propName = null;
+ }
+
+ attr.$observe(normalized, function(value) {
+ if (!value) {
+ if (attrName === 'href') {
+ attr.$set(name, null);
+ }
+ return;
+ }
+
+ attr.$set(name, value);
+
+ // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
+ // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
+ // to set the property as well to achieve the desired effect.
+ // we use attr[attrName] value since $set can sanitize the url.
+ if (msie && propName) element.prop(propName, attr[name]);
+ });
+ }
+ };
+ };
+});
+
+/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
+ */
+var nullFormCtrl = {
+ $addControl: noop,
+ $$renameControl: nullFormRenameControl,
+ $removeControl: noop,
+ $setValidity: noop,
+ $setDirty: noop,
+ $setPristine: noop,
+ $setSubmitted: noop
+},
+SUBMITTED_CLASS = 'ng-submitted';
+
+function nullFormRenameControl(control, name) {
+ control.$name = name;
+}
+
+/**
+ * @ngdoc type
+ * @name form.FormController
+ *
+ * @property {boolean} $pristine True if user has not interacted with the form yet.
+ * @property {boolean} $dirty True if user has already interacted with the form.
+ * @property {boolean} $valid True if all of the containing forms and controls are valid.
+ * @property {boolean} $invalid True if at least one containing control or form is invalid.
+ * @property {boolean} $pending True if at least one containing control or form is pending.
+ * @property {boolean} $submitted True if user has submitted the form even if its invalid.
+ *
+ * @property {Object} $error Is an object hash, containing references to controls or
+ * forms with failing validators, where:
+ *
+ * - keys are validation tokens (error names),
+ * - values are arrays of controls or forms that have a failing validator for given error name.
+ *
+ * Built-in validation tokens:
+ *
+ * - `email`
+ * - `max`
+ * - `maxlength`
+ * - `min`
+ * - `minlength`
+ * - `number`
+ * - `pattern`
+ * - `required`
+ * - `url`
+ * - `date`
+ * - `datetimelocal`
+ * - `time`
+ * - `week`
+ * - `month`
+ *
+ * @description
+ * `FormController` keeps track of all its controls and nested forms as well as the state of them,
+ * such as being valid/invalid or dirty/pristine.
+ *
+ * Each {@link ng.directive:form form} directive creates an instance
+ * of `FormController`.
+ *
+ */
+//asks for $scope to fool the BC controller module
+FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
+function FormController(element, attrs, $scope, $animate, $interpolate) {
+ var form = this,
+ controls = [];
+
+ // init state
+ form.$error = {};
+ form.$$success = {};
+ form.$pending = undefined;
+ form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$valid = true;
+ form.$invalid = false;
+ form.$submitted = false;
+ form.$$parentForm = nullFormCtrl;
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$rollbackViewValue
+ *
+ * @description
+ * Rollback all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is typically needed by the reset button of
+ * a form that uses `ng-model-options` to pend updates.
+ */
+ form.$rollbackViewValue = function() {
+ forEach(controls, function(control) {
+ control.$rollbackViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$commitViewValue
+ *
+ * @description
+ * Commit all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ form.$commitViewValue = function() {
+ forEach(controls, function(control) {
+ control.$commitViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$addControl
+ * @param {object} control control object, either a {@link form.FormController} or an
+ * {@link ngModel.NgModelController}
+ *
+ * @description
+ * Register a control with the form. Input elements using ngModelController do this automatically
+ * when they are linked.
+ *
+ * Note that the current state of the control will not be reflected on the new parent form. This
+ * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
+ * state.
+ *
+ * However, if the method is used programmatically, for example by adding dynamically created controls,
+ * or controls that have been previously removed without destroying their corresponding DOM element,
+ * it's the developers responsiblity to make sure the current state propagates to the parent form.
+ *
+ * For example, if an input control is added that is already `$dirty` and has `$error` properties,
+ * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
+ */
+ form.$addControl = function(control) {
+ // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
+ // and not added to the scope. Now we throw an error.
+ assertNotHasOwnProperty(control.$name, 'input');
+ controls.push(control);
+
+ if (control.$name) {
+ form[control.$name] = control;
+ }
+
+ control.$$parentForm = form;
+ };
+
+ // Private API: rename a form control
+ form.$$renameControl = function(control, newName) {
+ var oldName = control.$name;
+
+ if (form[oldName] === control) {
+ delete form[oldName];
+ }
+ form[newName] = control;
+ control.$name = newName;
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$removeControl
+ * @param {object} control control object, either a {@link form.FormController} or an
+ * {@link ngModel.NgModelController}
+ *
+ * @description
+ * Deregister a control from the form.
+ *
+ * Input elements using ngModelController do this automatically when they are destroyed.
+ *
+ * Note that only the removed control's validation state (`$errors`etc.) will be removed from the
+ * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
+ * different from case to case. For example, removing the only `$dirty` control from a form may or
+ * may not mean that the form is still `$dirty`.
+ */
+ form.$removeControl = function(control) {
+ if (control.$name && form[control.$name] === control) {
+ delete form[control.$name];
+ }
+ forEach(form.$pending, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$error, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+ forEach(form.$$success, function(value, name) {
+ form.$setValidity(name, null, control);
+ });
+
+ arrayRemove(controls, control);
+ control.$$parentForm = nullFormCtrl;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setValidity
+ *
+ * @description
+ * Sets the validity of a form control.
+ *
+ * This method will also propagate to parent forms.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: element,
+ set: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ object[property] = [controller];
+ } else {
+ var index = list.indexOf(controller);
+ if (index === -1) {
+ list.push(controller);
+ }
+ }
+ },
+ unset: function(object, property, controller) {
+ var list = object[property];
+ if (!list) {
+ return;
+ }
+ arrayRemove(list, controller);
+ if (list.length === 0) {
+ delete object[property];
+ }
+ },
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setDirty
+ *
+ * @description
+ * Sets the form to a dirty state.
+ *
+ * This method can be called to add the 'ng-dirty' class and set the form to a dirty
+ * state (ng-dirty class). This method will also propagate to parent forms.
+ */
+ form.$setDirty = function() {
+ $animate.removeClass(element, PRISTINE_CLASS);
+ $animate.addClass(element, DIRTY_CLASS);
+ form.$dirty = true;
+ form.$pristine = false;
+ form.$$parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setPristine
+ *
+ * @description
+ * Sets the form to its pristine state.
+ *
+ * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
+ * state (ng-pristine class). This method will also propagate to all the controls contained
+ * in this form.
+ *
+ * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
+ * saving or resetting it.
+ */
+ form.$setPristine = function() {
+ $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
+ form.$dirty = false;
+ form.$pristine = true;
+ form.$submitted = false;
+ forEach(controls, function(control) {
+ control.$setPristine();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setUntouched
+ *
+ * @description
+ * Sets the form to its untouched state.
+ *
+ * This method can be called to remove the 'ng-touched' class and set the form controls to their
+ * untouched state (ng-untouched class).
+ *
+ * Setting a form controls back to their untouched state is often useful when setting the form
+ * back to its pristine state.
+ */
+ form.$setUntouched = function() {
+ forEach(controls, function(control) {
+ control.$setUntouched();
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name form.FormController#$setSubmitted
+ *
+ * @description
+ * Sets the form to its submitted state.
+ */
+ form.$setSubmitted = function() {
+ $animate.addClass(element, SUBMITTED_CLASS);
+ form.$submitted = true;
+ form.$$parentForm.$setSubmitted();
+ };
+}
+
+/**
+ * @ngdoc directive
+ * @name ngForm
+ * @restrict EAC
+ *
+ * @description
+ * Nestable alias of {@link ng.directive:form `form`} directive. HTML
+ * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
+ * sub-group of controls needs to be determined.
+ *
+ * Note: the purpose of `ngForm` is to group controls,
+ * but not to be a replacement for the `<form>` tag with all of its capabilities
+ * (e.g. posting to the server, ...).
+ *
+ * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ *
+ */
+
+ /**
+ * @ngdoc directive
+ * @name form
+ * @restrict E
+ *
+ * @description
+ * Directive that instantiates
+ * {@link form.FormController FormController}.
+ *
+ * If the `name` attribute is specified, the form controller is published onto the current scope under
+ * this name.
+ *
+ * # Alias: {@link ng.directive:ngForm `ngForm`}
+ *
+ * In Angular, forms can be nested. This means that the outer form is valid when all of the child
+ * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
+ * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
+ * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
+ * using Angular validation directives in forms that are dynamically generated using the
+ * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
+ * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
+ * `ngForm` directive and nest these in an outer `form` element.
+ *
+ *
+ * # CSS classes
+ * - `ng-valid` is set if the form is valid.
+ * - `ng-invalid` is set if the form is invalid.
+ * - `ng-pending` is set if the form is pending.
+ * - `ng-pristine` is set if the form is pristine.
+ * - `ng-dirty` is set if the form is dirty.
+ * - `ng-submitted` is set if the form was submitted.
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ *
+ * # Submitting a form and preventing the default action
+ *
+ * Since the role of forms in client-side Angular applications is different than in classical
+ * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
+ * page reload that sends the data to the server. Instead some javascript logic should be triggered
+ * to handle the form submission in an application-specific way.
+ *
+ * For this reason, Angular prevents the default action (form submission to the server) unless the
+ * `<form>` element has an `action` attribute specified.
+ *
+ * You can use one of the following two ways to specify what javascript method should be called when
+ * a form is submitted:
+ *
+ * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
+ * - {@link ng.directive:ngClick ngClick} directive on the first
+ * button or input field of type submit (input[type=submit])
+ *
+ * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
+ * or {@link ng.directive:ngClick ngClick} directives.
+ * This is because of the following form submission rules in the HTML specification:
+ *
+ * - If a form has only one input field then hitting enter in this field triggers form submit
+ * (`ngSubmit`)
+ * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
+ * doesn't trigger submit
+ * - if a form has one or more input fields and one or more buttons or input[type=submit] then
+ * hitting enter in any of the input fields will trigger the click handler on the *first* button or
+ * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
+ *
+ * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
+ * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * ## Animation Hooks
+ *
+ * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
+ * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
+ * other validations that are performed within the form. Animations in ngForm are similar to how
+ * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
+ * as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style a form element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-form {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-form.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
+ <file name="index.html">
+ <script>
+ angular.module('formExample', [])
+ .controller('FormController', ['$scope', function($scope) {
+ $scope.userType = 'guest';
+ }]);
+ </script>
+ <style>
+ .my-form {
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-form.ng-invalid {
+ background: red;
+ }
+ </style>
+ <form name="myForm" ng-controller="FormController" class="my-form">
+ userType: <input name="input" ng-model="userType" required>
+ <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
+ <code>userType = {{userType}}</code><br>
+ <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
+ <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
+ <code>myForm.$valid = {{myForm.$valid}}</code><br>
+ <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should initialize to model', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+
+ expect(userType.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ var userType = element(by.binding('userType'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var userInput = element(by.model('userType'));
+
+ userInput.clear();
+ userInput.sendKeys('');
+
+ expect(userType.getText()).toEqual('userType =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ *
+ * @param {string=} name Name of the form. If specified, the form controller will be published into
+ * related scope, under this name.
+ */
+var formDirectiveFactory = function(isNgForm) {
+ return ['$timeout', '$parse', function($timeout, $parse) {
+ var formDirective = {
+ name: 'form',
+ restrict: isNgForm ? 'EAC' : 'E',
+ require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
+ controller: FormController,
+ compile: function ngFormCompile(formElement, attr) {
+ // Setup initial state of the control
+ formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
+
+ var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
+
+ return {
+ pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
+ var controller = ctrls[0];
+
+ // if `action` attr is not present on the form, prevent the default action (submission)
+ if (!('action' in attr)) {
+ // we can't use jq events because if a form is destroyed during submission the default
+ // action is not prevented. see #1238
+ //
+ // IE 9 is not affected because it doesn't fire a submit event and try to do a full
+ // page reload if the form was destroyed by submission of the form via a click handler
+ // on a button in the form. Looks like an IE9 specific bug.
+ var handleFormSubmission = function(event) {
+ scope.$apply(function() {
+ controller.$commitViewValue();
+ controller.$setSubmitted();
+ });
+
+ event.preventDefault();
+ };
+
+ addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+
+ // unregister the preventDefault listener so that we don't not leak memory but in a
+ // way that will achieve the prevention of the default action.
+ formElement.on('$destroy', function() {
+ $timeout(function() {
+ removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
+ }, 0, false);
+ });
+ }
+
+ var parentFormCtrl = ctrls[1] || controller.$$parentForm;
+ parentFormCtrl.$addControl(controller);
+
+ var setter = nameAttr ? getSetter(controller.$name) : noop;
+
+ if (nameAttr) {
+ setter(scope, controller);
+ attr.$observe(nameAttr, function(newValue) {
+ if (controller.$name === newValue) return;
+ setter(scope, undefined);
+ controller.$$parentForm.$$renameControl(controller, newValue);
+ setter = getSetter(controller.$name);
+ setter(scope, controller);
+ });
+ }
+ formElement.on('$destroy', function() {
+ controller.$$parentForm.$removeControl(controller);
+ setter(scope, undefined);
+ extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
+ });
+ }
+ };
+ }
+ };
+
+ return formDirective;
+
+ function getSetter(expression) {
+ if (expression === '') {
+ //create an assignable expression, so forms with an empty name can be renamed later
+ return $parse('this[""]').assign;
+ }
+ return $parse(expression).assign || noop;
+ }
+ }];
+};
+
+var formDirective = formDirectiveFactory();
+var ngFormDirective = formDirectiveFactory(true);
+
+/* global VALID_CLASS: false,
+ INVALID_CLASS: false,
+ PRISTINE_CLASS: false,
+ DIRTY_CLASS: false,
+ UNTOUCHED_CLASS: false,
+ TOUCHED_CLASS: false,
+ ngModelMinErr: false,
+*/
+
+// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
+var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
+// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
+var URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
+var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
+var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
+var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
+var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
+var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
+var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
+
+var inputType = {
+
+ /**
+ * @ngdoc input
+ * @name input[text]
+ *
+ * @description
+ * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Adds `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="text-input-directive" module="textInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('textInputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ text: 'guest',
+ word: /^\s*\w*\s*$/
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>Single word:
+ <input type="text" name="input" ng-model="example.text"
+ ng-pattern="example.word" required ng-trim="false">
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.pattern">
+ Single word only!</span>
+ </div>
+ <tt>text = {{example.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('example.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('guest');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if multi word', function() {
+ input.clear();
+ input.sendKeys('hello world');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'text': textInputType,
+
+ /**
+ * @ngdoc input
+ * @name input[date]
+ *
+ * @description
+ * Input with date validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
+ * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
+ * modern browsers do not yet support this input type, it is important to provide cues to users on the
+ * expected input format via a placeholder or label.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
+ * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
+ * constraint validation.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
+ * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
+ * constraint validation.
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="date-input-directive" module="dateInputExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateInputExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 22)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ <label for="exampleInput">Pick a date in 2013:</label>
+ <input type="date" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.date">
+ Not a valid date!</span>
+ </div>
+ <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (see https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10-22');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'date': createDateInputType('date', DATE_REGEXP,
+ createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
+ 'yyyy-MM-dd'),
+
+ /**
+ * @ngdoc input
+ * @name input[datetime-local]
+ *
+ * @description
+ * Input with datetime validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
+ * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
+ * Note that `min` will also add native HTML5 constraint validation.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
+ * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
+ * Note that `max` will also add native HTML5 constraint validation.
+ * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
+ * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="datetimelocal-input-directive" module="dateExample">
+ <file name="index.html">
+ <script>
+ angular.module('dateExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2010, 11, 28, 14, 57)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ <label for="exampleInput">Pick a date between in 2013:</label>
+ <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.datetimelocal">
+ Not a valid date!</span>
+ </div>
+ <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2010-12-28T14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01T23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
+ createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
+ 'yyyy-MM-ddTHH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[time]
+ *
+ * @description
+ * Input with time validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
+ * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
+ * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
+ * native HTML5 constraint validation.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
+ * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
+ * native HTML5 constraint validation.
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
+ * `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
+ * `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="time-input-directive" module="timeExample">
+ <file name="index.html">
+ <script>
+ angular.module('timeExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(1970, 0, 1, 14, 57, 0)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ <label for="exampleInput">Pick a between 8am and 5pm:</label>
+ <input type="time" id="exampleInput" name="input" ng-model="example.value"
+ placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.time">
+ Not a valid date!</span>
+ </div>
+ <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "HH:mm:ss"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('14:57:00');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('23:59:00');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'time': createDateInputType('time', TIME_REGEXP,
+ createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
+ 'HH:mm:ss.sss'),
+
+ /**
+ * @ngdoc input
+ * @name input[week]
+ *
+ * @description
+ * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
+ * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * week format (yyyy-W##), for example: `2013-W02`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
+ * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
+ * native HTML5 constraint validation.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
+ * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
+ * native HTML5 constraint validation.
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="week-input-directive" module="weekExample">
+ <file name="index.html">
+ <script>
+ angular.module('weekExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 0, 3)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ <label>Pick a date between in 2013:
+ <input id="exampleInput" type="week" name="input" ng-model="example.value"
+ placeholder="YYYY-W##" min="2012-W32"
+ max="2013-W52" required />
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.week">
+ Not a valid date!</span>
+ </div>
+ <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-Www"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-W01');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-W01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
+
+ /**
+ * @ngdoc input
+ * @name input[month]
+ *
+ * @description
+ * Input with month validation and transformation. In browsers that do not yet support
+ * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * month format (yyyy-MM), for example: `2009-01`.
+ *
+ * The model must always be a Date object, otherwise Angular will throw an error.
+ * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
+ * If the model is not set to the first of the month, the next view to model update will set it
+ * to the first of the month.
+ *
+ * The timezone to be used to read/write the `Date` instance in the model can be defined using
+ * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
+ * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
+ * native HTML5 constraint validation.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
+ * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
+ * native HTML5 constraint validation.
+ * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
+ * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
+ * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
+ * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
+
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="month-input-directive" module="monthExample">
+ <file name="index.html">
+ <script>
+ angular.module('monthExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.example = {
+ value: new Date(2013, 9, 1)
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="DateController as dateCtrl">
+ <label for="exampleInput">Pick a month in 2013:</label>
+ <input id="exampleInput" type="month" name="input" ng-model="example.value"
+ placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.month">
+ Not a valid month!</span>
+ </div>
+ <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value | date: "yyyy-MM"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'month': createDateInputType('month', MONTH_REGEXP,
+ createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
+ 'yyyy-MM'),
+
+ /**
+ * @ngdoc input
+ * @name input[number]
+ *
+ * @description
+ * Text input with number validation and transformation. Sets the `number` validation
+ * error if not a valid number.
+ *
+ * <div class="alert alert-warning">
+ * The model must always be of type `number` otherwise Angular will throw an error.
+ * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
+ * error docs for more information and an example of how to convert your model if necessary.
+ * </div>
+ *
+ * ## Issues with HTML5 constraint validation
+ *
+ * In browsers that follow the
+ * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
+ * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
+ * If a non-number is entered in the input, the browser will report the value as an empty string,
+ * which means the view / model values in `ngModel` and subsequently the scope value
+ * will also be an empty string.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="number-input-directive" module="numberExample">
+ <file name="index.html">
+ <script>
+ angular.module('numberExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.example = {
+ value: 12
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>Number:
+ <input type="number" name="input" ng-model="example.value"
+ min="0" max="99" required>
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.number">
+ Not valid number!</span>
+ </div>
+ <tt>value = {{example.value}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('example.value'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('example.value'));
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('12');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if over max', function() {
+ input.clear();
+ input.sendKeys('123');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'number': numberInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[url]
+ *
+ * @description
+ * Text input with URL validation. Sets the `url` validation error key if the content is not a
+ * valid URL.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
+ * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
+ * the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="url-input-directive" module="urlExample">
+ <file name="index.html">
+ <script>
+ angular.module('urlExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.url = {
+ text: 'http://google.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>URL:
+ <input type="url" name="input" ng-model="url.text" required>
+ <label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.url">
+ Not valid url!</span>
+ </div>
+ <tt>text = {{url.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('url.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('url.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('http://google.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not url', function() {
+ input.clear();
+ input.sendKeys('box');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'url': urlInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[email]
+ *
+ * @description
+ * Text input with email validation. Sets the `email` validation error key if not a valid email
+ * address.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
+ * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
+ * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
+ * any length.
+ * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
+ * that contains the regular expression body that will be converted to a regular expression
+ * as in the ngPattern directive.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="email-input-directive" module="emailExample">
+ <file name="index.html">
+ <script>
+ angular.module('emailExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.email = {
+ text: 'me@example.com'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>Email:
+ <input type="email" name="input" ng-model="email.text" required>
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.email">
+ Not valid email!</span>
+ </div>
+ <tt>text = {{email.text}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var text = element(by.binding('email.text'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('email.text'));
+
+ it('should initialize to model', function() {
+ expect(text.getText()).toContain('me@example.com');
+ expect(valid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input.clear();
+ input.sendKeys('');
+ expect(text.getText()).toEqual('text =');
+ expect(valid.getText()).toContain('false');
+ });
+
+ it('should be invalid if not email', function() {
+ input.clear();
+ input.sendKeys('xxx');
+
+ expect(valid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+ 'email': emailInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[radio]
+ *
+ * @description
+ * HTML radio button.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string} value The value to which the `ngModel` expression should be set when selected.
+ * Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
+ * too. Use `ngValue` if you need complex models (`number`, `object`, ...).
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
+ * is selected. Should be used instead of the `value` attribute if you need
+ * a non-string `ngModel` (`boolean`, `array`, ...).
+ *
+ * @example
+ <example name="radio-input-directive" module="radioExample">
+ <file name="index.html">
+ <script>
+ angular.module('radioExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.color = {
+ name: 'blue'
+ };
+ $scope.specialValue = {
+ "id": "12345",
+ "value": "green"
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>
+ <input type="radio" ng-model="color.name" value="red">
+ Red
+ </label><br/>
+ <label>
+ <input type="radio" ng-model="color.name" ng-value="specialValue">
+ Green
+ </label><br/>
+ <label>
+ <input type="radio" ng-model="color.name" value="blue">
+ Blue
+ </label><br/>
+ <tt>color = {{color.name | json}}</tt><br/>
+ </form>
+ Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var color = element(by.binding('color.name'));
+
+ expect(color.getText()).toContain('blue');
+
+ element.all(by.model('color.name')).get(0).click();
+
+ expect(color.getText()).toContain('red');
+ });
+ </file>
+ </example>
+ */
+ 'radio': radioInputType,
+
+
+ /**
+ * @ngdoc input
+ * @name input[checkbox]
+ *
+ * @description
+ * HTML checkbox.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
+ * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="checkbox-input-directive" module="checkboxExample">
+ <file name="index.html">
+ <script>
+ angular.module('checkboxExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.checkboxModel = {
+ value1 : true,
+ value2 : 'YES'
+ };
+ }]);
+ </script>
+ <form name="myForm" ng-controller="ExampleController">
+ <label>Value1:
+ <input type="checkbox" ng-model="checkboxModel.value1">
+ </label><br/>
+ <label>Value2:
+ <input type="checkbox" ng-model="checkboxModel.value2"
+ ng-true-value="'YES'" ng-false-value="'NO'">
+ </label><br/>
+ <tt>value1 = {{checkboxModel.value1}}</tt><br/>
+ <tt>value2 = {{checkboxModel.value2}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should change state', function() {
+ var value1 = element(by.binding('checkboxModel.value1'));
+ var value2 = element(by.binding('checkboxModel.value2'));
+
+ expect(value1.getText()).toContain('true');
+ expect(value2.getText()).toContain('YES');
+
+ element(by.model('checkboxModel.value1')).click();
+ element(by.model('checkboxModel.value2')).click();
+
+ expect(value1.getText()).toContain('false');
+ expect(value2.getText()).toContain('NO');
+ });
+ </file>
+ </example>
+ */
+ 'checkbox': checkboxInputType,
+
+ 'hidden': noop,
+ 'button': noop,
+ 'submit': noop,
+ 'reset': noop,
+ 'file': noop
+};
+
+function stringBasedInputType(ctrl) {
+ ctrl.$formatters.push(function(value) {
+ return ctrl.$isEmpty(value) ? value : value.toString();
+ });
+}
+
+function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+}
+
+function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ var type = lowercase(element[0].type);
+
+ // In composition mode, users are still inputing intermediate text buffer,
+ // hold the listener until composition is done.
+ // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
+ if (!$sniffer.android) {
+ var composing = false;
+
+ element.on('compositionstart', function(data) {
+ composing = true;
+ });
+
+ element.on('compositionend', function() {
+ composing = false;
+ listener();
+ });
+ }
+
+ var listener = function(ev) {
+ if (timeout) {
+ $browser.defer.cancel(timeout);
+ timeout = null;
+ }
+ if (composing) return;
+ var value = element.val(),
+ event = ev && ev.type;
+
+ // By default we will trim the value
+ // If the attribute ng-trim exists we will avoid trimming
+ // If input type is 'password', the value is never trimmed
+ if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
+ value = trim(value);
+ }
+
+ // If a control is suffering from bad input (due to native validators), browsers discard its
+ // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
+ // control's value is the same empty value twice in a row.
+ if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
+ ctrl.$setViewValue(value, event);
+ }
+ };
+
+ // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
+ // input event on backspace, delete or cut
+ if ($sniffer.hasEvent('input')) {
+ element.on('input', listener);
+ } else {
+ var timeout;
+
+ var deferListener = function(ev, input, origValue) {
+ if (!timeout) {
+ timeout = $browser.defer(function() {
+ timeout = null;
+ if (!input || input.value !== origValue) {
+ listener(ev);
+ }
+ });
+ }
+ };
+
+ element.on('keydown', function(event) {
+ var key = event.keyCode;
+
+ // ignore
+ // command modifiers arrows
+ if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
+
+ deferListener(event, this, this.value);
+ });
+
+ // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
+ if ($sniffer.hasEvent('paste')) {
+ element.on('paste cut', deferListener);
+ }
+ }
+
+ // if user paste into input using mouse on older browser
+ // or form autocomplete on newer browser, we need "change" event to catch it
+ element.on('change', listener);
+
+ ctrl.$render = function() {
+ // Workaround for Firefox validation #12102.
+ var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
+ if (element.val() !== value) {
+ element.val(value);
+ }
+ };
+}
+
+function weekParser(isoWeek, existingDate) {
+ if (isDate(isoWeek)) {
+ return isoWeek;
+ }
+
+ if (isString(isoWeek)) {
+ WEEK_REGEXP.lastIndex = 0;
+ var parts = WEEK_REGEXP.exec(isoWeek);
+ if (parts) {
+ var year = +parts[1],
+ week = +parts[2],
+ hours = 0,
+ minutes = 0,
+ seconds = 0,
+ milliseconds = 0,
+ firstThurs = getFirstThursdayOfYear(year),
+ addDays = (week - 1) * 7;
+
+ if (existingDate) {
+ hours = existingDate.getHours();
+ minutes = existingDate.getMinutes();
+ seconds = existingDate.getSeconds();
+ milliseconds = existingDate.getMilliseconds();
+ }
+
+ return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
+ }
+ }
+
+ return NaN;
+}
+
+function createDateParser(regexp, mapping) {
+ return function(iso, date) {
+ var parts, map;
+
+ if (isDate(iso)) {
+ return iso;
+ }
+
+ if (isString(iso)) {
+ // When a date is JSON'ified to wraps itself inside of an extra
+ // set of double quotes. This makes the date parsing code unable
+ // to match the date string and parse it as a date.
+ if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
+ iso = iso.substring(1, iso.length - 1);
+ }
+ if (ISO_DATE_REGEXP.test(iso)) {
+ return new Date(iso);
+ }
+ regexp.lastIndex = 0;
+ parts = regexp.exec(iso);
+
+ if (parts) {
+ parts.shift();
+ if (date) {
+ map = {
+ yyyy: date.getFullYear(),
+ MM: date.getMonth() + 1,
+ dd: date.getDate(),
+ HH: date.getHours(),
+ mm: date.getMinutes(),
+ ss: date.getSeconds(),
+ sss: date.getMilliseconds() / 1000
+ };
+ } else {
+ map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
+ }
+
+ forEach(parts, function(part, index) {
+ if (index < mapping.length) {
+ map[mapping[index]] = +part;
+ }
+ });
+ return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
+ }
+ }
+
+ return NaN;
+ };
+}
+
+function createDateInputType(type, regexp, parseDate, format) {
+ return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
+ var previousDate;
+
+ ctrl.$$parserName = type;
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (regexp.test(value)) {
+ // Note: We cannot read ctrl.$modelValue, as there might be a different
+ // parser/formatter in the processing chain so that the model
+ // contains some different data format!
+ var parsedDate = parseDate(value, previousDate);
+ if (timezone) {
+ parsedDate = convertTimezoneToLocal(parsedDate, timezone);
+ }
+ return parsedDate;
+ }
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (value && !isDate(value)) {
+ throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
+ }
+ if (isValidDate(value)) {
+ previousDate = value;
+ if (previousDate && timezone) {
+ previousDate = convertTimezoneToLocal(previousDate, timezone, true);
+ }
+ return $filter('date')(value, format, timezone);
+ } else {
+ previousDate = null;
+ return '';
+ }
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
+ };
+ attr.$observe('min', function(val) {
+ minVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
+ };
+ attr.$observe('max', function(val) {
+ maxVal = parseObservedDateValue(val);
+ ctrl.$validate();
+ });
+ }
+
+ function isValidDate(value) {
+ // Invalid Date: getTime() returns NaN
+ return value && !(value.getTime && value.getTime() !== value.getTime());
+ }
+
+ function parseObservedDateValue(val) {
+ return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
+ }
+ };
+}
+
+function badInputChecker(scope, element, attr, ctrl) {
+ var node = element[0];
+ var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
+ if (nativeValidation) {
+ ctrl.$parsers.push(function(value) {
+ var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
+ // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
+ // - also sets validity.badInput (should only be validity.typeMismatch).
+ // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
+ // - can ignore this case as we can still read out the erroneous email...
+ return validity.badInput && !validity.typeMismatch ? undefined : value;
+ });
+ }
+}
+
+function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ badInputChecker(scope, element, attr, ctrl);
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+
+ ctrl.$$parserName = 'number';
+ ctrl.$parsers.push(function(value) {
+ if (ctrl.$isEmpty(value)) return null;
+ if (NUMBER_REGEXP.test(value)) return parseFloat(value);
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if (!ctrl.$isEmpty(value)) {
+ if (!isNumber(value)) {
+ throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
+ }
+ value = value.toString();
+ }
+ return value;
+ });
+
+ if (isDefined(attr.min) || attr.ngMin) {
+ var minVal;
+ ctrl.$validators.min = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
+ };
+
+ attr.$observe('min', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ minVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+
+ if (isDefined(attr.max) || attr.ngMax) {
+ var maxVal;
+ ctrl.$validators.max = function(value) {
+ return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
+ };
+
+ attr.$observe('max', function(val) {
+ if (isDefined(val) && !isNumber(val)) {
+ val = parseFloat(val, 10);
+ }
+ maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
+ // TODO(matsko): implement validateLater to reduce number of validations
+ ctrl.$validate();
+ });
+ }
+}
+
+function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'url';
+ ctrl.$validators.url = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
+ };
+}
+
+function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+ // Note: no badInputChecker here by purpose as `url` is only a validation
+ // in browsers, i.e. we can always read out input.value even if it is not valid!
+ baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
+ stringBasedInputType(ctrl);
+
+ ctrl.$$parserName = 'email';
+ ctrl.$validators.email = function(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+ return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
+ };
+}
+
+function radioInputType(scope, element, attr, ctrl) {
+ // make the name unique, if not defined
+ if (isUndefined(attr.name)) {
+ element.attr('name', nextUid());
+ }
+
+ var listener = function(ev) {
+ if (element[0].checked) {
+ ctrl.$setViewValue(attr.value, ev && ev.type);
+ }
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ var value = attr.value;
+ element[0].checked = (value == ctrl.$viewValue);
+ };
+
+ attr.$observe('value', ctrl.$render);
+}
+
+function parseConstantExpr($parse, context, name, expression, fallback) {
+ var parseFn;
+ if (isDefined(expression)) {
+ parseFn = $parse(expression);
+ if (!parseFn.constant) {
+ throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
+ '`{1}`.', name, expression);
+ }
+ return parseFn(context);
+ }
+ return fallback;
+}
+
+function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
+ var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
+ var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
+
+ var listener = function(ev) {
+ ctrl.$setViewValue(element[0].checked, ev && ev.type);
+ };
+
+ element.on('click', listener);
+
+ ctrl.$render = function() {
+ element[0].checked = ctrl.$viewValue;
+ };
+
+ // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
+ // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
+ // it to a boolean.
+ ctrl.$isEmpty = function(value) {
+ return value === false;
+ };
+
+ ctrl.$formatters.push(function(value) {
+ return equals(value, trueValue);
+ });
+
+ ctrl.$parsers.push(function(value) {
+ return value ? trueValue : falseValue;
+ });
+}
+
+
+/**
+ * @ngdoc directive
+ * @name textarea
+ * @restrict E
+ *
+ * @description
+ * HTML textarea element control with angular data-binding. The data-binding and validation
+ * properties of this element are exactly the same as those of the
+ * {@link ng.directive:input input element}.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name input
+ * @restrict E
+ *
+ * @description
+ * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
+ * input state control, and validation.
+ * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
+ *
+ * <div class="alert alert-warning">
+ * **Note:** Not every feature offered is available for all input types.
+ * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
+ * </div>
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {boolean=} ngRequired Sets `required` attribute if set to true
+ * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
+ * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
+ * length.
+ * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
+ * a RegExp found by evaluating the Angular expression given in the attribute value.
+ * If the expression evaluates to a RegExp object, then this is used directly.
+ * If the expression evaluates to a string, then it will be converted to a RegExp
+ * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
+ * `new RegExp('^abc$')`.<br />
+ * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
+ * start at the index of the last search's match, thus not taking the whole input value into
+ * account.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
+ * This parameter is ignored for input[type=password] controls, which will never trim the
+ * input.
+ *
+ * @example
+ <example name="input-directive" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = {name: 'guest', last: 'visitor'};
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <form name="myForm">
+ <label>
+ User name:
+ <input type="text" name="userName" ng-model="user.name" required>
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.userName.$error.required">
+ Required!</span>
+ </div>
+ <label>
+ Last name:
+ <input type="text" name="lastName" ng-model="user.last"
+ ng-minlength="3" ng-maxlength="10">
+ </label>
+ <div role="alert">
+ <span class="error" ng-show="myForm.lastName.$error.minlength">
+ Too short!</span>
+ <span class="error" ng-show="myForm.lastName.$error.maxlength">
+ Too long!</span>
+ </div>
+ </form>
+ <hr>
+ <tt>user = {{user}}</tt><br/>
+ <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>
+ <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>
+ <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>
+ <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>
+ <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var user = element(by.exactBinding('user'));
+ var userNameValid = element(by.binding('myForm.userName.$valid'));
+ var lastNameValid = element(by.binding('myForm.lastName.$valid'));
+ var lastNameError = element(by.binding('myForm.lastName.$error'));
+ var formValid = element(by.binding('myForm.$valid'));
+ var userNameInput = element(by.model('user.name'));
+ var userLastInput = element(by.model('user.last'));
+
+ it('should initialize to model', function() {
+ expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
+ expect(userNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if empty when required', function() {
+ userNameInput.clear();
+ userNameInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"last":"visitor"}');
+ expect(userNameValid.getText()).toContain('false');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be valid if empty when min length is set', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('');
+
+ expect(user.getText()).toContain('{"name":"guest","last":""}');
+ expect(lastNameValid.getText()).toContain('true');
+ expect(formValid.getText()).toContain('true');
+ });
+
+ it('should be invalid if less than required min length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('xx');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('minlength');
+ expect(formValid.getText()).toContain('false');
+ });
+
+ it('should be invalid if longer than max length', function() {
+ userLastInput.clear();
+ userLastInput.sendKeys('some ridiculously long name');
+
+ expect(user.getText()).toContain('{"name":"guest"}');
+ expect(lastNameValid.getText()).toContain('false');
+ expect(lastNameError.getText()).toContain('maxlength');
+ expect(formValid.getText()).toContain('false');
+ });
+ </file>
+ </example>
+ */
+var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
+ function($browser, $sniffer, $filter, $parse) {
+ return {
+ restrict: 'E',
+ require: ['?ngModel'],
+ link: {
+ pre: function(scope, element, attr, ctrls) {
+ if (ctrls[0]) {
+ (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
+ $browser, $filter, $parse);
+ }
+ }
+ }
+ };
+}];
+
+
+
+var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
+/**
+ * @ngdoc directive
+ * @name ngValue
+ *
+ * @description
+ * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
+ * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
+ * the bound value.
+ *
+ * `ngValue` is useful when dynamically generating lists of radio buttons using
+ * {@link ngRepeat `ngRepeat`}, as shown below.
+ *
+ * Likewise, `ngValue` can be used to generate `<option>` elements for
+ * the {@link select `select`} element. In that case however, only strings are supported
+ * for the `value `attribute, so the resulting `ngModel` will always be a string.
+ * Support for `select` models with non-string values is available via `ngOptions`.
+ *
+ * @element input
+ * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
+ * of the `input` element
+ *
+ * @example
+ <example name="ngValue-directive" module="valueExample">
+ <file name="index.html">
+ <script>
+ angular.module('valueExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.names = ['pizza', 'unicorns', 'robots'];
+ $scope.my = { favorite: 'unicorns' };
+ }]);
+ </script>
+ <form ng-controller="ExampleController">
+ <h2>Which is your favorite?</h2>
+ <label ng-repeat="name in names" for="{{name}}">
+ {{name}}
+ <input type="radio"
+ ng-model="my.favorite"
+ ng-value="name"
+ id="{{name}}"
+ name="favorite">
+ </label>
+ <div>You chose {{my.favorite}}</div>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var favorite = element(by.binding('my.favorite'));
+
+ it('should initialize to model', function() {
+ expect(favorite.getText()).toContain('unicorns');
+ });
+ it('should bind the values to the inputs', function() {
+ element.all(by.model('my.favorite')).get(0).click();
+ expect(favorite.getText()).toContain('pizza');
+ });
+ </file>
+ </example>
+ */
+var ngValueDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ compile: function(tpl, tplAttr) {
+ if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
+ return function ngValueConstantLink(scope, elm, attr) {
+ attr.$set('value', scope.$eval(attr.ngValue));
+ };
+ } else {
+ return function ngValueLink(scope, elm, attr) {
+ scope.$watch(attr.ngValue, function valueWatchAction(value) {
+ attr.$set('value', value);
+ });
+ };
+ }
+ }
+ };
+};
+
+/**
+ * @ngdoc directive
+ * @name ngBind
+ * @restrict AC
+ *
+ * @description
+ * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
+ * with the value of a given expression, and to update the text content when the value of that
+ * expression changes.
+ *
+ * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
+ * `{{ expression }}` which is similar but less verbose.
+ *
+ * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
+ * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
+ * element attribute, it makes the bindings invisible to the user while the page is loading.
+ *
+ * An alternative solution to this problem would be using the
+ * {@link ng.directive:ngCloak ngCloak} directive.
+ *
+ *
+ * @element ANY
+ * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+ * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.name = 'Whirled';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <label>Enter name: <input type="text" ng-model="name"></label><br>
+ Hello <span ng-bind="name"></span>!
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var nameInput = element(by.model('name'));
+
+ expect(element(by.binding('name')).getText()).toBe('Whirled');
+ nameInput.clear();
+ nameInput.sendKeys('world');
+ expect(element(by.binding('name')).getText()).toBe('world');
+ });
+ </file>
+ </example>
+ */
+var ngBindDirective = ['$compile', function($compile) {
+ return {
+ restrict: 'AC',
+ compile: function ngBindCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBind);
+ element = element[0];
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
+ element.textContent = isUndefined(value) ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindTemplate
+ *
+ * @description
+ * The `ngBindTemplate` directive specifies that the element
+ * text content should be replaced with the interpolation of the template
+ * in the `ngBindTemplate` attribute.
+ * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
+ * expressions. This directive is needed since some HTML elements
+ * (such as TITLE and OPTION) cannot contain SPAN elements.
+ *
+ * @element ANY
+ * @param {string} ngBindTemplate template of form
+ * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
+ *
+ * @example
+ * Try it here: enter text in text box and watch the greeting change.
+ <example module="bindExample">
+ <file name="index.html">
+ <script>
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.salutation = 'Hello';
+ $scope.name = 'World';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <label>Salutation: <input type="text" ng-model="salutation"></label><br>
+ <label>Name: <input type="text" ng-model="name"></label><br>
+ <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind', function() {
+ var salutationElem = element(by.binding('salutation'));
+ var salutationInput = element(by.model('salutation'));
+ var nameInput = element(by.model('name'));
+
+ expect(salutationElem.getText()).toBe('Hello World!');
+
+ salutationInput.clear();
+ salutationInput.sendKeys('Greetings');
+ nameInput.clear();
+ nameInput.sendKeys('user');
+
+ expect(salutationElem.getText()).toBe('Greetings user!');
+ });
+ </file>
+ </example>
+ */
+var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
+ return {
+ compile: function ngBindTemplateCompile(templateElement) {
+ $compile.$$addBindingClass(templateElement);
+ return function ngBindTemplateLink(scope, element, attr) {
+ var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
+ $compile.$$addBindingInfo(element, interpolateFn.expressions);
+ element = element[0];
+ attr.$observe('ngBindTemplate', function(value) {
+ element.textContent = isUndefined(value) ? '' : value;
+ });
+ };
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngBindHtml
+ *
+ * @description
+ * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
+ * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
+ * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
+ * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
+ * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
+ *
+ * You may also bypass sanitization for values you know are safe. To do so, bind to
+ * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
+ * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
+ *
+ * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
+ * will have an exception (instead of an exploit.)
+ *
+ * @element ANY
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
+ *
+ * @example
+
+ <example module="bindHtmlExample" deps="angular-sanitize.js">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <p ng-bind-html="myHTML"></p>
+ </div>
+ </file>
+
+ <file name="script.js">
+ angular.module('bindHtmlExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.myHTML =
+ 'I am an <code>HTML</code>string with ' +
+ '<a href="#">links!</a> and other <em>stuff</em>';
+ }]);
+ </file>
+
+ <file name="protractor.js" type="protractor">
+ it('should check ng-bind-html', function() {
+ expect(element(by.binding('myHTML')).getText()).toBe(
+ 'I am an HTMLstring with links! and other stuff');
+ });
+ </file>
+ </example>
+ */
+var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
+ return {
+ restrict: 'A',
+ compile: function ngBindHtmlCompile(tElement, tAttrs) {
+ var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
+ var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
+ return (value || '').toString();
+ });
+ $compile.$$addBindingClass(tElement);
+
+ return function ngBindHtmlLink(scope, element, attr) {
+ $compile.$$addBindingInfo(element, attr.ngBindHtml);
+
+ scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
+ // we re-evaluate the expr because we want a TrustedValueHolderType
+ // for $sce, not a string
+ element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
+ });
+ };
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngChange
+ *
+ * @description
+ * Evaluate the given expression when the user changes the input.
+ * The expression is evaluated immediately, unlike the JavaScript onchange event
+ * which only triggers at the end of a change (usually, when the user leaves the
+ * form element or presses the return key).
+ *
+ * The `ngChange` expression is only evaluated when a change in the input value causes
+ * a new value to be committed to the model.
+ *
+ * It will not be evaluated:
+ * * if the value returned from the `$parsers` transformation pipeline has not changed
+ * * if the input has continued to be invalid since the model will stay `null`
+ * * if the model is changed programmatically and not by a change to the input value
+ *
+ *
+ * Note, this directive requires `ngModel` to be present.
+ *
+ * @element input
+ * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
+ * in input value.
+ *
+ * @example
+ * <example name="ngChange-directive" module="changeExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('changeExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.counter = 0;
+ * $scope.change = function() {
+ * $scope.counter++;
+ * };
+ * }]);
+ * </script>
+ * <div ng-controller="ExampleController">
+ * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
+ * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
+ * <label for="ng-change-example2">Confirmed</label><br />
+ * <tt>debug = {{confirmed}}</tt><br/>
+ * <tt>counter = {{counter}}</tt><br/>
+ * </div>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var counter = element(by.binding('counter'));
+ * var debug = element(by.binding('confirmed'));
+ *
+ * it('should evaluate the expression if changing from view', function() {
+ * expect(counter.getText()).toContain('0');
+ *
+ * element(by.id('ng-change-example1')).click();
+ *
+ * expect(counter.getText()).toContain('1');
+ * expect(debug.getText()).toContain('true');
+ * });
+ *
+ * it('should not evaluate the expression if changing from model', function() {
+ * element(by.id('ng-change-example2')).click();
+
+ * expect(counter.getText()).toContain('0');
+ * expect(debug.getText()).toContain('true');
+ * });
+ * </file>
+ * </example>
+ */
+var ngChangeDirective = valueFn({
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ ctrl.$viewChangeListeners.push(function() {
+ scope.$eval(attr.ngChange);
+ });
+ }
+});
+
+function classDirective(name, selector) {
+ name = 'ngClass' + name;
+ return ['$animate', function($animate) {
+ return {
+ restrict: 'AC',
+ link: function(scope, element, attr) {
+ var oldVal;
+
+ scope.$watch(attr[name], ngClassWatchAction, true);
+
+ attr.$observe('class', function(value) {
+ ngClassWatchAction(scope.$eval(attr[name]));
+ });
+
+
+ if (name !== 'ngClass') {
+ scope.$watch('$index', function($index, old$index) {
+ // jshint bitwise: false
+ var mod = $index & 1;
+ if (mod !== (old$index & 1)) {
+ var classes = arrayClasses(scope.$eval(attr[name]));
+ mod === selector ?
+ addClasses(classes) :
+ removeClasses(classes);
+ }
+ });
+ }
+
+ function addClasses(classes) {
+ var newClasses = digestClassCounts(classes, 1);
+ attr.$addClass(newClasses);
+ }
+
+ function removeClasses(classes) {
+ var newClasses = digestClassCounts(classes, -1);
+ attr.$removeClass(newClasses);
+ }
+
+ function digestClassCounts(classes, count) {
+ // Use createMap() to prevent class assumptions involving property
+ // names in Object.prototype
+ var classCounts = element.data('$classCounts') || createMap();
+ var classesToUpdate = [];
+ forEach(classes, function(className) {
+ if (count > 0 || classCounts[className]) {
+ classCounts[className] = (classCounts[className] || 0) + count;
+ if (classCounts[className] === +(count > 0)) {
+ classesToUpdate.push(className);
+ }
+ }
+ });
+ element.data('$classCounts', classCounts);
+ return classesToUpdate.join(' ');
+ }
+
+ function updateClasses(oldClasses, newClasses) {
+ var toAdd = arrayDifference(newClasses, oldClasses);
+ var toRemove = arrayDifference(oldClasses, newClasses);
+ toAdd = digestClassCounts(toAdd, 1);
+ toRemove = digestClassCounts(toRemove, -1);
+ if (toAdd && toAdd.length) {
+ $animate.addClass(element, toAdd);
+ }
+ if (toRemove && toRemove.length) {
+ $animate.removeClass(element, toRemove);
+ }
+ }
+
+ function ngClassWatchAction(newVal) {
+ if (selector === true || scope.$index % 2 === selector) {
+ var newClasses = arrayClasses(newVal || []);
+ if (!oldVal) {
+ addClasses(newClasses);
+ } else if (!equals(newVal,oldVal)) {
+ var oldClasses = arrayClasses(oldVal);
+ updateClasses(oldClasses, newClasses);
+ }
+ }
+ oldVal = shallowCopy(newVal);
+ }
+ }
+ };
+
+ function arrayDifference(tokens1, tokens2) {
+ var values = [];
+
+ outer:
+ for (var i = 0; i < tokens1.length; i++) {
+ var token = tokens1[i];
+ for (var j = 0; j < tokens2.length; j++) {
+ if (token == tokens2[j]) continue outer;
+ }
+ values.push(token);
+ }
+ return values;
+ }
+
+ function arrayClasses(classVal) {
+ var classes = [];
+ if (isArray(classVal)) {
+ forEach(classVal, function(v) {
+ classes = classes.concat(arrayClasses(v));
+ });
+ return classes;
+ } else if (isString(classVal)) {
+ return classVal.split(' ');
+ } else if (isObject(classVal)) {
+ forEach(classVal, function(v, k) {
+ if (v) {
+ classes = classes.concat(k.split(' '));
+ }
+ });
+ return classes;
+ }
+ return classVal;
+ }
+ }];
+}
+
+/**
+ * @ngdoc directive
+ * @name ngClass
+ * @restrict AC
+ *
+ * @description
+ * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
+ * an expression that represents all classes to be added.
+ *
+ * The directive operates in three different ways, depending on which of three types the expression
+ * evaluates to:
+ *
+ * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
+ * names.
+ *
+ * 2. If the expression evaluates to an object, then for each key-value pair of the
+ * object with a truthy value the corresponding key is used as a class name.
+ *
+ * 3. If the expression evaluates to an array, each element of the array should either be a string as in
+ * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array
+ * to give you more control over what CSS classes appear. See the code below for an example of this.
+ *
+ *
+ * The directive won't add duplicate classes if a particular class was already set.
+ *
+ * When the expression changes, the previously added classes are removed and only then are the
+ * new classes added.
+ *
+ * @animations
+ * **add** - happens just before the class is applied to the elements
+ *
+ * **remove** - happens just before the class is removed from the element
+ *
+ * @element ANY
+ * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class
+ * names, an array, or a map of class names to boolean values. In the case of a map, the
+ * names of the properties whose values are truthy will be added as css classes to the
+ * element.
+ *
+ * @example Example that demonstrates basic bindings via ngClass directive.
+ <example>
+ <file name="index.html">
+ <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
+ <label>
+ <input type="checkbox" ng-model="deleted">
+ deleted (apply "strike" class)
+ </label><br>
+ <label>
+ <input type="checkbox" ng-model="important">
+ important (apply "bold" class)
+ </label><br>
+ <label>
+ <input type="checkbox" ng-model="error">
+ error (apply "has-error" class)
+ </label>
+ <hr>
+ <p ng-class="style">Using String Syntax</p>
+ <input type="text" ng-model="style"
+ placeholder="Type: bold strike red" aria-label="Type: bold strike red">
+ <hr>
+ <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
+ <input ng-model="style1"
+ placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br>
+ <input ng-model="style2"
+ placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br>
+ <input ng-model="style3"
+ placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br>
+ <hr>
+ <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p>
+ <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br>
+ <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label>
+ </file>
+ <file name="style.css">
+ .strike {
+ text-decoration: line-through;
+ }
+ .bold {
+ font-weight: bold;
+ }
+ .red {
+ color: red;
+ }
+ .has-error {
+ color: red;
+ background-color: yellow;
+ }
+ .orange {
+ color: orange;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var ps = element.all(by.css('p'));
+
+ it('should let you toggle the class', function() {
+
+ expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
+ expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
+
+ element(by.model('important')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/bold/);
+
+ element(by.model('error')).click();
+ expect(ps.first().getAttribute('class')).toMatch(/has-error/);
+ });
+
+ it('should let you toggle string example', function() {
+ expect(ps.get(1).getAttribute('class')).toBe('');
+ element(by.model('style')).clear();
+ element(by.model('style')).sendKeys('red');
+ expect(ps.get(1).getAttribute('class')).toBe('red');
+ });
+
+ it('array example should have 3 classes', function() {
+ expect(ps.get(2).getAttribute('class')).toBe('');
+ element(by.model('style1')).sendKeys('bold');
+ element(by.model('style2')).sendKeys('strike');
+ element(by.model('style3')).sendKeys('red');
+ expect(ps.get(2).getAttribute('class')).toBe('bold strike red');
+ });
+
+ it('array with map example should have 2 classes', function() {
+ expect(ps.last().getAttribute('class')).toBe('');
+ element(by.model('style4')).sendKeys('bold');
+ element(by.model('warning')).click();
+ expect(ps.last().getAttribute('class')).toBe('bold orange');
+ });
+ </file>
+ </example>
+
+ ## Animations
+
+ The example below demonstrates how to perform animations using ngClass.
+
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
+ <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
+ <br>
+ <span class="base-class" ng-class="myVar">Sample Text</span>
+ </file>
+ <file name="style.css">
+ .base-class {
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .base-class.my-class {
+ color: red;
+ font-size:3em;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class', function() {
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+
+ element(by.id('setbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).
+ toMatch(/my-class/);
+
+ element(by.id('clearbtn')).click();
+
+ expect(element(by.css('.base-class')).getAttribute('class')).not.
+ toMatch(/my-class/);
+ });
+ </file>
+ </example>
+
+
+ ## ngClass and pre-existing CSS3 Transitions/Animations
+ The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
+ Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
+ any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
+ to view the step by step details of {@link $animate#addClass $animate.addClass} and
+ {@link $animate#removeClass $animate.removeClass}.
+ */
+var ngClassDirective = classDirective('', true);
+
+/**
+ * @ngdoc directive
+ * @name ngClassOdd
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
+ * of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}}
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassOddDirective = classDirective('Odd', 0);
+
+/**
+ * @ngdoc directive
+ * @name ngClassEven
+ * @restrict AC
+ *
+ * @description
+ * The `ngClassOdd` and `ngClassEven` directives work exactly as
+ * {@link ng.directive:ngClass ngClass}, except they work in
+ * conjunction with `ngRepeat` and take effect only on odd (even) rows.
+ *
+ * This directive can be applied only within the scope of an
+ * {@link ng.directive:ngRepeat ngRepeat}.
+ *
+ * @element ANY
+ * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
+ * result of the evaluation can be a string representing space delimited class names or an array.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
+ <li ng-repeat="name in names">
+ <span ng-class-odd="'odd'" ng-class-even="'even'">
+ {{name}} &nbsp; &nbsp; &nbsp;
+ </span>
+ </li>
+ </ol>
+ </file>
+ <file name="style.css">
+ .odd {
+ color: red;
+ }
+ .even {
+ color: blue;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-class-odd and ng-class-even', function() {
+ expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
+ toMatch(/odd/);
+ expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
+ toMatch(/even/);
+ });
+ </file>
+ </example>
+ */
+var ngClassEvenDirective = classDirective('Even', 1);
+
+/**
+ * @ngdoc directive
+ * @name ngCloak
+ * @restrict AC
+ *
+ * @description
+ * The `ngCloak` directive is used to prevent the Angular html template from being briefly
+ * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
+ * directive to avoid the undesirable flicker effect caused by the html template display.
+ *
+ * The directive can be applied to the `<body>` element, but the preferred usage is to apply
+ * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
+ * of the browser view.
+ *
+ * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
+ * `angular.min.js`.
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```css
+ * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
+ * display: none !important;
+ * }
+ * ```
+ *
+ * When this css rule is loaded by the browser, all html elements (including their children) that
+ * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
+ * during the compilation of the template it deletes the `ngCloak` element attribute, making
+ * the compiled element visible.
+ *
+ * For the best result, the `angular.js` script must be loaded in the head section of the html
+ * document; alternatively, the css rule above must be included in the external stylesheet of the
+ * application.
+ *
+ * @element ANY
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div id="template1" ng-cloak>{{ 'hello' }}</div>
+ <div id="template2" class="ng-cloak">{{ 'world' }}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should remove the template directive and css class', function() {
+ expect($('#template1').getAttribute('ng-cloak')).
+ toBeNull();
+ expect($('#template2').getAttribute('ng-cloak')).
+ toBeNull();
+ });
+ </file>
+ </example>
+ *
+ */
+var ngCloakDirective = ngDirective({
+ compile: function(element, attr) {
+ attr.$set('ngCloak', undefined);
+ element.removeClass('ng-cloak');
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngController
+ *
+ * @description
+ * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
+ * supports the principles behind the Model-View-Controller design pattern.
+ *
+ * MVC components in angular:
+ *
+ * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
+ * are accessed through bindings.
+ * * View — The template (HTML with data bindings) that is rendered into the View.
+ * * Controller — The `ngController` directive specifies a Controller class; the class contains business
+ * logic behind the application to decorate the scope with functions and values
+ *
+ * Note that you can also attach controllers to the DOM by declaring it in a route definition
+ * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
+ * again using `ng-controller` in the template itself. This will cause the controller to be attached
+ * and executed twice.
+ *
+ * @element ANY
+ * @scope
+ * @priority 500
+ * @param {expression} ngController Name of a constructor function registered with the current
+ * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
+ * that on the current scope evaluates to a constructor function.
+ *
+ * The controller instance can be published into a scope property by specifying
+ * `ng-controller="as propertyName"`.
+ *
+ * If the current `$controllerProvider` is configured to use globals (via
+ * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
+ * also be the name of a globally accessible constructor function (not recommended).
+ *
+ * @example
+ * Here is a simple form for editing user contact information. Adding, removing, clearing, and
+ * greeting are methods declared on the controller (see source tab). These methods can
+ * easily be called from the angular markup. Any changes to the data are automatically reflected
+ * in the View without the need for a manual update.
+ *
+ * Two different declaration styles are included below:
+ *
+ * * one binds methods and properties directly onto the controller using `this`:
+ * `ng-controller="SettingsController1 as settings"`
+ * * one injects `$scope` into the controller:
+ * `ng-controller="SettingsController2"`
+ *
+ * The second option is more common in the Angular community, and is generally used in boilerplates
+ * and in this guide. However, there are advantages to binding properties directly to the controller
+ * and avoiding scope.
+ *
+ * * Using `controller as` makes it obvious which controller you are accessing in the template when
+ * multiple controllers apply to an element.
+ * * If you are writing your controllers as classes you have easier access to the properties and
+ * methods, which will appear on the scope, from inside the controller code.
+ * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
+ * inheritance masking primitives.
+ *
+ * This example demonstrates the `controller as` syntax.
+ *
+ * <example name="ngControllerAs" module="controllerAsExample">
+ * <file name="index.html">
+ * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
+ * <label>Name: <input type="text" ng-model="settings.name"/></label>
+ * <button ng-click="settings.greet()">greet</button><br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in settings.contacts">
+ * <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
+ * <button ng-click="settings.clearContact(contact)">clear</button>
+ * <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button>
+ * </li>
+ * <li><button ng-click="settings.addContact()">add</button></li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerAsExample', [])
+ * .controller('SettingsController1', SettingsController1);
+ *
+ * function SettingsController1() {
+ * this.name = "John Smith";
+ * this.contacts = [
+ * {type: 'phone', value: '408 555 1212'},
+ * {type: 'email', value: 'john.smith@example.org'} ];
+ * }
+ *
+ * SettingsController1.prototype.greet = function() {
+ * alert(this.name);
+ * };
+ *
+ * SettingsController1.prototype.addContact = function() {
+ * this.contacts.push({type: 'email', value: 'yourname@example.org'});
+ * };
+ *
+ * SettingsController1.prototype.removeContact = function(contactToRemove) {
+ * var index = this.contacts.indexOf(contactToRemove);
+ * this.contacts.splice(index, 1);
+ * };
+ *
+ * SettingsController1.prototype.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller as', function() {
+ * var container = element(by.id('ctrl-as-exmpl'));
+ * expect(container.element(by.model('settings.name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in settings.contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ *
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.buttonText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.buttonText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in settings.contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ * </example>
+ *
+ * This example demonstrates the "attach to `$scope`" style of controller.
+ *
+ * <example name="ngController" module="controllerExample">
+ * <file name="index.html">
+ * <div id="ctrl-exmpl" ng-controller="SettingsController2">
+ * <label>Name: <input type="text" ng-model="name"/></label>
+ * <button ng-click="greet()">greet</button><br/>
+ * Contact:
+ * <ul>
+ * <li ng-repeat="contact in contacts">
+ * <select ng-model="contact.type" id="select_{{$index}}">
+ * <option>phone</option>
+ * <option>email</option>
+ * </select>
+ * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
+ * <button ng-click="clearContact(contact)">clear</button>
+ * <button ng-click="removeContact(contact)">X</button>
+ * </li>
+ * <li>[ <button ng-click="addContact()">add</button> ]</li>
+ * </ul>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('controllerExample', [])
+ * .controller('SettingsController2', ['$scope', SettingsController2]);
+ *
+ * function SettingsController2($scope) {
+ * $scope.name = "John Smith";
+ * $scope.contacts = [
+ * {type:'phone', value:'408 555 1212'},
+ * {type:'email', value:'john.smith@example.org'} ];
+ *
+ * $scope.greet = function() {
+ * alert($scope.name);
+ * };
+ *
+ * $scope.addContact = function() {
+ * $scope.contacts.push({type:'email', value:'yourname@example.org'});
+ * };
+ *
+ * $scope.removeContact = function(contactToRemove) {
+ * var index = $scope.contacts.indexOf(contactToRemove);
+ * $scope.contacts.splice(index, 1);
+ * };
+ *
+ * $scope.clearContact = function(contact) {
+ * contact.type = 'phone';
+ * contact.value = '';
+ * };
+ * }
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should check controller', function() {
+ * var container = element(by.id('ctrl-exmpl'));
+ *
+ * expect(container.element(by.model('name'))
+ * .getAttribute('value')).toBe('John Smith');
+ *
+ * var firstRepeat =
+ * container.element(by.repeater('contact in contacts').row(0));
+ * var secondRepeat =
+ * container.element(by.repeater('contact in contacts').row(1));
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('408 555 1212');
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('john.smith@example.org');
+ *
+ * firstRepeat.element(by.buttonText('clear')).click();
+ *
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
+ * .toBe('');
+ *
+ * container.element(by.buttonText('add')).click();
+ *
+ * expect(container.element(by.repeater('contact in contacts').row(2))
+ * .element(by.model('contact.value'))
+ * .getAttribute('value'))
+ * .toBe('yourname@example.org');
+ * });
+ * </file>
+ *</example>
+
+ */
+var ngControllerDirective = [function() {
+ return {
+ restrict: 'A',
+ scope: true,
+ controller: '@',
+ priority: 500
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngCsp
+ *
+ * @element html
+ * @description
+ *
+ * Angular has some features that can break certain
+ * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
+ *
+ * If you intend to implement these rules then you must tell Angular not to use these features.
+ *
+ * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
+ *
+ *
+ * The following rules affect Angular:
+ *
+ * * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions
+ * (among other things). Angular makes use of this in the {@link $parse} service to provide a 30%
+ * increase in the speed of evaluating Angular expressions.
+ *
+ * * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular
+ * makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}).
+ * To make these directives work when a CSP rule is blocking inline styles, you must link to the
+ * `angular-csp.css` in your HTML manually.
+ *
+ * If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval
+ * and automatically deactivates this feature in the {@link $parse} service. This autodetection,
+ * however, triggers a CSP error to be logged in the console:
+ *
+ * ```
+ * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
+ * script in the following Content Security Policy directive: "default-src 'self'". Note that
+ * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
+ * ```
+ *
+ * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
+ * directive on an element of the HTML document that appears before the `<script>` tag that loads
+ * the `angular.js` file.
+ *
+ * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
+ *
+ * You can specify which of the CSP related Angular features should be deactivated by providing
+ * a value for the `ng-csp` attribute. The options are as follows:
+ *
+ * * no-inline-style: this stops Angular from injecting CSS styles into the DOM
+ *
+ * * no-unsafe-eval: this stops Angular from optimising $parse with unsafe eval of strings
+ *
+ * You can use these values in the following combinations:
+ *
+ *
+ * * No declaration means that Angular will assume that you can do inline styles, but it will do
+ * a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous versions
+ * of Angular.
+ *
+ * * A simple `ng-csp` (or `data-ng-csp`) attribute will tell Angular to deactivate both inline
+ * styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous versions
+ * of Angular.
+ *
+ * * Specifying only `no-unsafe-eval` tells Angular that we must not use eval, but that we can inject
+ * inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
+ *
+ * * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
+ * run eval - no automcatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
+ *
+ * * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
+ * styles nor use eval, which is the same as an empty: ng-csp.
+ * E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">`
+ *
+ * @example
+ * This example shows how to apply the `ngCsp` directive to the `html` tag.
+ ```html
+ <!doctype html>
+ <html ng-app ng-csp>
+ ...
+ ...
+ </html>
+ ```
+ * @example
+ // Note: the suffix `.csp` in the example name triggers
+ // csp mode in our http server!
+ <example name="example.csp" module="cspExample" ng-csp="true">
+ <file name="index.html">
+ <div ng-controller="MainController as ctrl">
+ <div>
+ <button ng-click="ctrl.inc()" id="inc">Increment</button>
+ <span id="counter">
+ {{ctrl.counter}}
+ </span>
+ </div>
+
+ <div>
+ <button ng-click="ctrl.evil()" id="evil">Evil</button>
+ <span id="evilError">
+ {{ctrl.evilError}}
+ </span>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('cspExample', [])
+ .controller('MainController', function() {
+ this.counter = 0;
+ this.inc = function() {
+ this.counter++;
+ };
+ this.evil = function() {
+ // jshint evil:true
+ try {
+ eval('1+2');
+ } catch (e) {
+ this.evilError = e.message;
+ }
+ };
+ });
+ </file>
+ <file name="protractor.js" type="protractor">
+ var util, webdriver;
+
+ var incBtn = element(by.id('inc'));
+ var counter = element(by.id('counter'));
+ var evilBtn = element(by.id('evil'));
+ var evilError = element(by.id('evilError'));
+
+ function getAndClearSevereErrors() {
+ return browser.manage().logs().get('browser').then(function(browserLog) {
+ return browserLog.filter(function(logEntry) {
+ return logEntry.level.value > webdriver.logging.Level.WARNING.value;
+ });
+ });
+ }
+
+ function clearErrors() {
+ getAndClearSevereErrors();
+ }
+
+ function expectNoErrors() {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ expect(filteredLog.length).toEqual(0);
+ if (filteredLog.length) {
+ console.log('browser console errors: ' + util.inspect(filteredLog));
+ }
+ });
+ }
+
+ function expectError(regex) {
+ getAndClearSevereErrors().then(function(filteredLog) {
+ var found = false;
+ filteredLog.forEach(function(log) {
+ if (log.message.match(regex)) {
+ found = true;
+ }
+ });
+ if (!found) {
+ throw new Error('expected an error that matches ' + regex);
+ }
+ });
+ }
+
+ beforeEach(function() {
+ util = require('util');
+ webdriver = require('protractor/node_modules/selenium-webdriver');
+ });
+
+ // For now, we only test on Chrome,
+ // as Safari does not load the page with Protractor's injected scripts,
+ // and Firefox webdriver always disables content security policy (#6358)
+ if (browser.params.browser !== 'chrome') {
+ return;
+ }
+
+ it('should not report errors when the page is loaded', function() {
+ // clear errors so we are not dependent on previous tests
+ clearErrors();
+ // Need to reload the page as the page is already loaded when
+ // we come here
+ browser.driver.getCurrentUrl().then(function(url) {
+ browser.get(url);
+ });
+ expectNoErrors();
+ });
+
+ it('should evaluate expressions', function() {
+ expect(counter.getText()).toEqual('0');
+ incBtn.click();
+ expect(counter.getText()).toEqual('1');
+ expectNoErrors();
+ });
+
+ it('should throw and report an error when using "eval"', function() {
+ evilBtn.click();
+ expect(evilError.getText()).toMatch(/Content Security Policy/);
+ expectError(/Content Security Policy/);
+ });
+ </file>
+ </example>
+ */
+
+// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
+// bootstrap the system (before $parse is instantiated), for this reason we just have
+// the csp() fn that looks for the `ng-csp` attribute anywhere in the current doc
+
+/**
+ * @ngdoc directive
+ * @name ngClick
+ *
+ * @description
+ * The ngClick directive allows you to specify custom behavior when
+ * an element is clicked.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
+ * click. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-click="count = count + 1" ng-init="count=0">
+ Increment
+ </button>
+ <span>
+ count: {{count}}
+ </span>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-click', function() {
+ expect(element(by.binding('count')).getText()).toMatch('0');
+ element(by.css('button')).click();
+ expect(element(by.binding('count')).getText()).toMatch('1');
+ });
+ </file>
+ </example>
+ */
+/*
+ * A collection of directives that allows creation of custom event handlers that are defined as
+ * angular expressions and are compiled and executed within the current scope.
+ */
+var ngEventDirectives = {};
+
+// For events that might fire synchronously during DOM manipulation
+// we need to execute their event handlers asynchronously using $evalAsync,
+// so that they are not executed in an inconsistent state.
+var forceAsyncEvents = {
+ 'blur': true,
+ 'focus': true
+};
+forEach(
+ 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
+ function(eventName) {
+ var directiveName = directiveNormalize('ng-' + eventName);
+ ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
+ return {
+ restrict: 'A',
+ compile: function($element, attr) {
+ // We expose the powerful $event object on the scope that provides access to the Window,
+ // etc. that isn't protected by the fast paths in $parse. We explicitly request better
+ // checks at the cost of speed since event handler expressions are not executed as
+ // frequently as regular change detection.
+ var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
+ return function ngEventHandler(scope, element) {
+ element.on(eventName, function(event) {
+ var callback = function() {
+ fn(scope, {$event:event});
+ };
+ if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
+ scope.$evalAsync(callback);
+ } else {
+ scope.$apply(callback);
+ }
+ });
+ };
+ }
+ };
+ }];
+ }
+);
+
+/**
+ * @ngdoc directive
+ * @name ngDblclick
+ *
+ * @description
+ * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
+ * a dblclick. (The Event object is available as `$event`)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-dblclick="count = count + 1" ng-init="count=0">
+ Increment (on double click)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousedown
+ *
+ * @description
+ * The ngMousedown directive allows you to specify custom behavior on mousedown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
+ * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousedown="count = count + 1" ng-init="count=0">
+ Increment (on mouse down)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseup
+ *
+ * @description
+ * Specify custom behavior on mouseup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
+ * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseup="count = count + 1" ng-init="count=0">
+ Increment (on mouse up)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngMouseover
+ *
+ * @description
+ * Specify custom behavior on mouseover event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
+ * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseover="count = count + 1" ng-init="count=0">
+ Increment (when mouse is over)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseenter
+ *
+ * @description
+ * Specify custom behavior on mouseenter event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
+ * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseenter="count = count + 1" ng-init="count=0">
+ Increment (when mouse enters)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMouseleave
+ *
+ * @description
+ * Specify custom behavior on mouseleave event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
+ * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mouseleave="count = count + 1" ng-init="count=0">
+ Increment (when mouse leaves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngMousemove
+ *
+ * @description
+ * Specify custom behavior on mousemove event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
+ * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <button ng-mousemove="count = count + 1" ng-init="count=0">
+ Increment (when mouse moves)
+ </button>
+ count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeydown
+ *
+ * @description
+ * Specify custom behavior on keydown event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
+ * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keydown="count = count + 1" ng-init="count=0">
+ key down count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeyup
+ *
+ * @description
+ * Specify custom behavior on keyup event.
+ *
+ * @element ANY
+ * @priority 0
+ * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
+ * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <p>Typing in the input box below updates the key count</p>
+ <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
+
+ <p>Typing in the input box below updates the keycode</p>
+ <input ng-keyup="event=$event">
+ <p>event keyCode: {{ event.keyCode }}</p>
+ <p>event altKey: {{ event.altKey }}</p>
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngKeypress
+ *
+ * @description
+ * Specify custom behavior on keypress event.
+ *
+ * @element ANY
+ * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
+ * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
+ * and can be interrogated for keyCode, altKey, etc.)
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-keypress="count = count + 1" ng-init="count=0">
+ key press count: {{count}}
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc directive
+ * @name ngSubmit
+ *
+ * @description
+ * Enables binding angular expressions to onsubmit events.
+ *
+ * Additionally it prevents the default action (which for form means sending the request to the
+ * server and reloading the current page), but only if the form does not contain `action`,
+ * `data-action`, or `x-action` attributes.
+ *
+ * <div class="alert alert-warning">
+ * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
+ * `ngSubmit` handlers together. See the
+ * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
+ * for a detailed discussion of when `ngSubmit` may be triggered.
+ * </div>
+ *
+ * @element form
+ * @priority 0
+ * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
+ * ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example module="submitExample">
+ <file name="index.html">
+ <script>
+ angular.module('submitExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [];
+ $scope.text = 'hello';
+ $scope.submit = function() {
+ if ($scope.text) {
+ $scope.list.push(this.text);
+ $scope.text = '';
+ }
+ };
+ }]);
+ </script>
+ <form ng-submit="submit()" ng-controller="ExampleController">
+ Enter text and hit enter:
+ <input type="text" ng-model="text" name="text" />
+ <input type="submit" id="submit" value="Submit" />
+ <pre>list={{list}}</pre>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-submit', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ expect(element(by.model('text')).getAttribute('value')).toBe('');
+ });
+ it('should ignore empty strings', function() {
+ expect(element(by.binding('list')).getText()).toBe('list=[]');
+ element(by.css('#submit')).click();
+ element(by.css('#submit')).click();
+ expect(element(by.binding('list')).getText()).toContain('hello');
+ });
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngFocus
+ *
+ * @description
+ * Specify custom behavior on focus event.
+ *
+ * Note: As the `focus` event is executed synchronously when calling `input.focus()`
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
+ * focus. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngBlur
+ *
+ * @description
+ * Specify custom behavior on blur event.
+ *
+ * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
+ * an element has lost focus.
+ *
+ * Note: As the `blur` event is executed synchronously also during DOM manipulations
+ * (e.g. removing a focussed input),
+ * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
+ * during an `$apply` to ensure a consistent state.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
+ * blur. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ * See {@link ng.directive:ngClick ngClick}
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCopy
+ *
+ * @description
+ * Specify custom behavior on copy event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
+ * copy. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
+ copied: {{copied}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngCut
+ *
+ * @description
+ * Specify custom behavior on cut event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
+ * cut. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
+ cut: {{cut}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngPaste
+ *
+ * @description
+ * Specify custom behavior on paste event.
+ *
+ * @element window, input, select, textarea, a
+ * @priority 0
+ * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
+ * paste. ({@link guide/expression#-event- Event object is available as `$event`})
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
+ pasted: {{paste}}
+ </file>
+ </example>
+ */
+
+/**
+ * @ngdoc directive
+ * @name ngIf
+ * @restrict A
+ * @multiElement
+ *
+ * @description
+ * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
+ * {expression}. If the expression assigned to `ngIf` evaluates to a false
+ * value then the element is removed from the DOM, otherwise a clone of the
+ * element is reinserted into the DOM.
+ *
+ * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
+ * element in the DOM rather than changing its visibility via the `display` css property. A common
+ * case when this difference is significant is when using css selectors that rely on an element's
+ * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
+ *
+ * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
+ * is created when the element is restored. The scope created within `ngIf` inherits from
+ * its parent scope using
+ * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
+ * An important implication of this is if `ngModel` is used within `ngIf` to bind to
+ * a javascript primitive defined in the parent scope. In this case any modifications made to the
+ * variable within the child scope will override (hide) the value in the parent scope.
+ *
+ * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
+ * is if an element's class attribute is directly modified after it's compiled, using something like
+ * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
+ * the added class will be lost because the original compiled state is used to regenerate the element.
+ *
+ * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
+ * and `leave` effects.
+ *
+ * @animations
+ * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
+ * leave - happens just before the `ngIf` contents are removed from the DOM
+ *
+ * @element ANY
+ * @scope
+ * @priority 600
+ * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
+ * the element is removed from the DOM tree. If it is truthy a copy of the compiled
+ * element is added to the DOM tree.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/>
+ Show when checked:
+ <span ng-if="checked" class="animate-if">
+ This is removed when the checkbox is unchecked.
+ </span>
+ </file>
+ <file name="animations.css">
+ .animate-if {
+ background:white;
+ border:1px solid black;
+ padding:10px;
+ }
+
+ .animate-if.ng-enter, .animate-if.ng-leave {
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+ }
+
+ .animate-if.ng-enter,
+ .animate-if.ng-leave.ng-leave-active {
+ opacity:0;
+ }
+
+ .animate-if.ng-leave,
+ .animate-if.ng-enter.ng-enter-active {
+ opacity:1;
+ }
+ </file>
+ </example>
+ */
+var ngIfDirective = ['$animate', function($animate) {
+ return {
+ multiElement: true,
+ transclude: 'element',
+ priority: 600,
+ terminal: true,
+ restrict: 'A',
+ $$tlb: true,
+ link: function($scope, $element, $attr, ctrl, $transclude) {
+ var block, childScope, previousElements;
+ $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
+
+ if (value) {
+ if (!childScope) {
+ $transclude(function(clone, newScope) {
+ childScope = newScope;
+ clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block = {
+ clone: clone
+ };
+ $animate.enter(clone, $element.parent(), $element);
+ });
+ }
+ } else {
+ if (previousElements) {
+ previousElements.remove();
+ previousElements = null;
+ }
+ if (childScope) {
+ childScope.$destroy();
+ childScope = null;
+ }
+ if (block) {
+ previousElements = getBlockNodes(block.clone);
+ $animate.leave(previousElements).then(function() {
+ previousElements = null;
+ });
+ block = null;
+ }
+ }
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngInclude
+ * @restrict ECA
+ *
+ * @description
+ * Fetches, compiles and includes an external HTML fragment.
+ *
+ * By default, the template URL is restricted to the same domain and protocol as the
+ * application document. This is done by calling {@link $sce#getTrustedResourceUrl
+ * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
+ * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
+ * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
+ * ng.$sce Strict Contextual Escaping}.
+ *
+ * In addition, the browser's
+ * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
+ * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
+ * policy may further restrict whether the template is successfully loaded.
+ * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
+ * access on some browsers.
+ *
+ * @animations
+ * enter - animation is used to bring new content into the browser.
+ * leave - animation is used to animate existing content away.
+ *
+ * The enter and leave animation occur concurrently.
+ *
+ * @scope
+ * @priority 400
+ *
+ * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
+ * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
+ * @param {string=} onload Expression to evaluate when a new partial is loaded.
+ * <div class="alert alert-warning">
+ * **Note:** When using onload on SVG elements in IE11, the browser will try to call
+ * a function with the name on the window element, which will usually throw a
+ * "function is undefined" error. To fix this, you can instead use `data-onload` or a
+ * different form that {@link guide/directive#normalization matches} `onload`.
+ * </div>
+ *
+ * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
+ * $anchorScroll} to scroll the viewport after the content is loaded.
+ *
+ * - If the attribute is not set, disable scrolling.
+ * - If the attribute is set without value, enable scrolling.
+ * - Otherwise enable scrolling only if the expression evaluates to truthy value.
+ *
+ * @example
+ <example module="includeExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="template" ng-options="t.name for t in templates">
+ <option value="">(blank)</option>
+ </select>
+ url of the template: <code>{{template.url}}</code>
+ <hr/>
+ <div class="slide-animate-container">
+ <div class="slide-animate" ng-include="template.url"></div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('includeExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.templates =
+ [ { name: 'template1.html', url: 'template1.html'},
+ { name: 'template2.html', url: 'template2.html'} ];
+ $scope.template = $scope.templates[0];
+ }]);
+ </file>
+ <file name="template1.html">
+ Content of template1.html
+ </file>
+ <file name="template2.html">
+ Content of template2.html
+ </file>
+ <file name="animations.css">
+ .slide-animate-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .slide-animate {
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter, .slide-animate.ng-leave {
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ display:block;
+ padding:10px;
+ }
+
+ .slide-animate.ng-enter {
+ top:-50px;
+ }
+ .slide-animate.ng-enter.ng-enter-active {
+ top:0;
+ }
+
+ .slide-animate.ng-leave {
+ top:0;
+ }
+ .slide-animate.ng-leave.ng-leave-active {
+ top:50px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var templateSelect = element(by.model('template'));
+ var includeElem = element(by.css('[ng-include]'));
+
+ it('should load template1.html', function() {
+ expect(includeElem.getText()).toMatch(/Content of template1.html/);
+ });
+
+ it('should load template2.html', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ // See https://github.com/angular/protractor/issues/480
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(2).click();
+ expect(includeElem.getText()).toMatch(/Content of template2.html/);
+ });
+
+ it('should change to blank', function() {
+ if (browser.params.browser == 'firefox') {
+ // Firefox can't handle using selects
+ return;
+ }
+ templateSelect.click();
+ templateSelect.all(by.css('option')).get(0).click();
+ expect(includeElem.isPresent()).toBe(false);
+ });
+ </file>
+ </example>
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentRequested
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted every time the ngInclude content is requested.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentLoaded
+ * @eventType emit on the current ngInclude scope
+ * @description
+ * Emitted every time the ngInclude content is reloaded.
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+
+
+/**
+ * @ngdoc event
+ * @name ngInclude#$includeContentError
+ * @eventType emit on the scope ngInclude was declared in
+ * @description
+ * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
+ *
+ * @param {Object} angularEvent Synthetic event object.
+ * @param {String} src URL of content to load.
+ */
+var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
+ function($templateRequest, $anchorScroll, $animate) {
+ return {
+ restrict: 'ECA',
+ priority: 400,
+ terminal: true,
+ transclude: 'element',
+ controller: angular.noop,
+ compile: function(element, attr) {
+ var srcExp = attr.ngInclude || attr.src,
+ onloadExp = attr.onload || '',
+ autoScrollExp = attr.autoscroll;
+
+ return function(scope, $element, $attr, ctrl, $transclude) {
+ var changeCounter = 0,
+ currentScope,
+ previousElement,
+ currentElement;
+
+ var cleanupLastIncludeContent = function() {
+ if (previousElement) {
+ previousElement.remove();
+ previousElement = null;
+ }
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+ if (currentElement) {
+ $animate.leave(currentElement).then(function() {
+ previousElement = null;
+ });
+ previousElement = currentElement;
+ currentElement = null;
+ }
+ };
+
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
+ var afterAnimation = function() {
+ if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
+ $anchorScroll();
+ }
+ };
+ var thisChangeId = ++changeCounter;
+
+ if (src) {
+ //set the 2nd param to true to ignore the template request error so that the inner
+ //contents and scope can be cleaned up.
+ $templateRequest(src, true).then(function(response) {
+ if (thisChangeId !== changeCounter) return;
+ var newScope = scope.$new();
+ ctrl.template = response;
+
+ // Note: This will also link all children of ng-include that were contained in the original
+ // html. If that content contains controllers, ... they could pollute/change the scope.
+ // However, using ng-include on an element with additional content does not make sense...
+ // Note: We can't remove them in the cloneAttchFn of $transclude as that
+ // function is called before linking the content, which would apply child
+ // directives to non existing elements.
+ var clone = $transclude(newScope, function(clone) {
+ cleanupLastIncludeContent();
+ $animate.enter(clone, null, $element).then(afterAnimation);
+ });
+
+ currentScope = newScope;
+ currentElement = clone;
+
+ currentScope.$emit('$includeContentLoaded', src);
+ scope.$eval(onloadExp);
+ }, function() {
+ if (thisChangeId === changeCounter) {
+ cleanupLastIncludeContent();
+ scope.$emit('$includeContentError', src);
+ }
+ });
+ scope.$emit('$includeContentRequested', src);
+ } else {
+ cleanupLastIncludeContent();
+ ctrl.template = null;
+ }
+ });
+ };
+ }
+ };
+}];
+
+// This directive is called during the $transclude call of the first `ngInclude` directive.
+// It will replace and compile the content of the element with the loaded template.
+// We need this directive so that the element content is already filled when
+// the link function of another directive on the same element as ngInclude
+// is called.
+var ngIncludeFillContentDirective = ['$compile',
+ function($compile) {
+ return {
+ restrict: 'ECA',
+ priority: -400,
+ require: 'ngInclude',
+ link: function(scope, $element, $attr, ctrl) {
+ if (/SVG/.test($element[0].toString())) {
+ // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
+ // support innerHTML, so detect this here and try to generate the contents
+ // specially.
+ $element.empty();
+ $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
+ function namespaceAdaptedClone(clone) {
+ $element.append(clone);
+ }, {futureParentElement: $element});
+ return;
+ }
+
+ $element.html(ctrl.template);
+ $compile($element.contents())(scope);
+ }
+ };
+ }];
+
+/**
+ * @ngdoc directive
+ * @name ngInit
+ * @restrict AC
+ *
+ * @description
+ * The `ngInit` directive allows you to evaluate an expression in the
+ * current scope.
+ *
+ * <div class="alert alert-danger">
+ * This directive can be abused to add unnecessary amounts of logic into your templates.
+ * There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
+ * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
+ * server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
+ * rather than `ngInit` to initialize values on a scope.
+ * </div>
+ *
+ * <div class="alert alert-warning">
+ * **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
+ * sure you have parentheses to ensure correct operator precedence:
+ * <pre class="prettyprint">
+ * `<div ng-init="test1 = ($index | toString)"></div>`
+ * </pre>
+ * </div>
+ *
+ * @priority 450
+ *
+ * @element ANY
+ * @param {expression} ngInit {@link guide/expression Expression} to eval.
+ *
+ * @example
+ <example module="initExample">
+ <file name="index.html">
+ <script>
+ angular.module('initExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [['a', 'b'], ['c', 'd']];
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
+ <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
+ <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
+ </div>
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should alias index positions', function() {
+ var elements = element.all(by.css('.example-init'));
+ expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
+ expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
+ expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
+ expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
+ });
+ </file>
+ </example>
+ */
+var ngInitDirective = ngDirective({
+ priority: 450,
+ compile: function() {
+ return {
+ pre: function(scope, element, attrs) {
+ scope.$eval(attrs.ngInit);
+ }
+ };
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngList
+ *
+ * @description
+ * Text input that converts between a delimited string and an array of strings. The default
+ * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
+ * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
+ *
+ * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
+ * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
+ * list item is respected. This implies that the user of the directive is responsible for
+ * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
+ * tab or newline character.
+ * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
+ * when joining the list items back together) and whitespace around each list item is stripped
+ * before it is added to the model.
+ *
+ * ### Example with Validation
+ *
+ * <example name="ngList-directive" module="listExample">
+ * <file name="app.js">
+ * angular.module('listExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.names = ['morpheus', 'neo', 'trinity'];
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <form name="myForm" ng-controller="ExampleController">
+ * <label>List: <input name="namesInput" ng-model="names" ng-list required></label>
+ * <span role="alert">
+ * <span class="error" ng-show="myForm.namesInput.$error.required">
+ * Required!</span>
+ * </span>
+ * <br>
+ * <tt>names = {{names}}</tt><br/>
+ * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
+ * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
+ * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ * </form>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * var listInput = element(by.model('names'));
+ * var names = element(by.exactBinding('names'));
+ * var valid = element(by.binding('myForm.namesInput.$valid'));
+ * var error = element(by.css('span.error'));
+ *
+ * it('should initialize to model', function() {
+ * expect(names.getText()).toContain('["morpheus","neo","trinity"]');
+ * expect(valid.getText()).toContain('true');
+ * expect(error.getCssValue('display')).toBe('none');
+ * });
+ *
+ * it('should be invalid if empty', function() {
+ * listInput.clear();
+ * listInput.sendKeys('');
+ *
+ * expect(names.getText()).toContain('');
+ * expect(valid.getText()).toContain('false');
+ * expect(error.getCssValue('display')).not.toBe('none');
+ * });
+ * </file>
+ * </example>
+ *
+ * ### Example - splitting on newline
+ * <example name="ngList-directive-newlines">
+ * <file name="index.html">
+ * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
+ * <pre>{{ list | json }}</pre>
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it("should split the text by newlines", function() {
+ * var listInput = element(by.model('list'));
+ * var output = element(by.binding('list | json'));
+ * listInput.sendKeys('abc\ndef\nghi');
+ * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]');
+ * });
+ * </file>
+ * </example>
+ *
+ * @element input
+ * @param {string=} ngList optional delimiter that should be used to split the value.
+ */
+var ngListDirective = function() {
+ return {
+ restrict: 'A',
+ priority: 100,
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ // We want to control whitespace trimming so we use this convoluted approach
+ // to access the ngList attribute, which doesn't pre-trim the attribute
+ var ngList = element.attr(attr.$attr.ngList) || ', ';
+ var trimValues = attr.ngTrim !== 'false';
+ var separator = trimValues ? trim(ngList) : ngList;
+
+ var parse = function(viewValue) {
+ // If the viewValue is invalid (say required but empty) it will be `undefined`
+ if (isUndefined(viewValue)) return;
+
+ var list = [];
+
+ if (viewValue) {
+ forEach(viewValue.split(separator), function(value) {
+ if (value) list.push(trimValues ? trim(value) : value);
+ });
+ }
+
+ return list;
+ };
+
+ ctrl.$parsers.push(parse);
+ ctrl.$formatters.push(function(value) {
+ if (isArray(value)) {
+ return value.join(ngList);
+ }
+
+ return undefined;
+ });
+
+ // Override the standard $isEmpty because an empty array means the input is empty.
+ ctrl.$isEmpty = function(value) {
+ return !value || !value.length;
+ };
+ }
+ };
+};
+
+/* global VALID_CLASS: true,
+ INVALID_CLASS: true,
+ PRISTINE_CLASS: true,
+ DIRTY_CLASS: true,
+ UNTOUCHED_CLASS: true,
+ TOUCHED_CLASS: true,
+*/
+
+var VALID_CLASS = 'ng-valid',
+ INVALID_CLASS = 'ng-invalid',
+ PRISTINE_CLASS = 'ng-pristine',
+ DIRTY_CLASS = 'ng-dirty',
+ UNTOUCHED_CLASS = 'ng-untouched',
+ TOUCHED_CLASS = 'ng-touched',
+ PENDING_CLASS = 'ng-pending';
+
+var ngModelMinErr = minErr('ngModel');
+
+/**
+ * @ngdoc type
+ * @name ngModel.NgModelController
+ *
+ * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
+ * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
+ * is set.
+ * @property {*} $modelValue The value in the model that the control is bound to.
+ * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
+ the control reads value from the DOM. The functions are called in array order, each passing
+ its return value through to the next. The last return value is forwarded to the
+ {@link ngModel.NgModelController#$validators `$validators`} collection.
+
+Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
+`$viewValue`}.
+
+Returning `undefined` from a parser means a parse error occurred. In that case,
+no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
+will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
+is set to `true`. The parse error is stored in `ngModel.$error.parse`.
+
+ *
+ * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
+ the model value changes. The functions are called in reverse array order, each passing the value through to the
+ next. The last return value is used as the actual DOM value.
+ Used to format / convert values for display in the control.
+ * ```js
+ * function formatter(value) {
+ * if (value) {
+ * return value.toUpperCase();
+ * }
+ * }
+ * ngModel.$formatters.push(formatter);
+ * ```
+ *
+ * @property {Object.<string, function>} $validators A collection of validators that are applied
+ * whenever the model value changes. The key value within the object refers to the name of the
+ * validator while the function refers to the validation operation. The validation operation is
+ * provided with the model value as an argument and must return a true or false value depending
+ * on the response of that validation.
+ *
+ * ```js
+ * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ * return /[0-9]+/.test(value) &&
+ * /[a-z]+/.test(value) &&
+ * /[A-Z]+/.test(value) &&
+ * /\W+/.test(value);
+ * };
+ * ```
+ *
+ * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
+ * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
+ * is expected to return a promise when it is run during the model validation process. Once the promise
+ * is delivered then the validation status will be set to true when fulfilled and false when rejected.
+ * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
+ * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
+ * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
+ * will only run once all synchronous validators have passed.
+ *
+ * Please note that if $http is used then it is important that the server returns a success HTTP response code
+ * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
+ *
+ * ```js
+ * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
+ * var value = modelValue || viewValue;
+ *
+ * // Lookup user by username
+ * return $http.get('/api/users/' + value).
+ * then(function resolved() {
+ * //username exists, this means validation fails
+ * return $q.reject('exists');
+ * }, function rejected() {
+ * //username does not exist, therefore this validation passes
+ * return true;
+ * });
+ * };
+ * ```
+ *
+ * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
+ * view value has changed. It is called with no arguments, and its return value is ignored.
+ * This can be used in place of additional $watches against the model value.
+ *
+ * @property {Object} $error An object hash with all failing validator ids as keys.
+ * @property {Object} $pending An object hash with all pending validator ids as keys.
+ *
+ * @property {boolean} $untouched True if control has not lost focus yet.
+ * @property {boolean} $touched True if control has lost focus.
+ * @property {boolean} $pristine True if user has not interacted with the control yet.
+ * @property {boolean} $dirty True if user has already interacted with the control.
+ * @property {boolean} $valid True if there is no error.
+ * @property {boolean} $invalid True if at least one error on the control.
+ * @property {string} $name The name attribute of the control.
+ *
+ * @description
+ *
+ * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
+ * The controller contains services for data-binding, validation, CSS updates, and value formatting
+ * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
+ * listening to DOM events.
+ * Such DOM related logic should be provided by other directives which make use of
+ * `NgModelController` for data-binding to control elements.
+ * Angular provides this DOM logic for most {@link input `input`} elements.
+ * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
+ * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
+ *
+ * @example
+ * ### Custom Control Example
+ * This example shows how to use `NgModelController` with a custom control to achieve
+ * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
+ * collaborate together to achieve the desired result.
+ *
+ * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
+ * contents be edited in place by the user.
+ *
+ * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
+ * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
+ * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
+ * that content using the `$sce` service.
+ *
+ * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
+ <file name="style.css">
+ [contenteditable] {
+ border: 1px solid black;
+ background-color: white;
+ min-height: 20px;
+ }
+
+ .ng-invalid {
+ border: 1px solid red;
+ }
+
+ </file>
+ <file name="script.js">
+ angular.module('customControl', ['ngSanitize']).
+ directive('contenteditable', ['$sce', function($sce) {
+ return {
+ restrict: 'A', // only activate on element attribute
+ require: '?ngModel', // get a hold of NgModelController
+ link: function(scope, element, attrs, ngModel) {
+ if (!ngModel) return; // do nothing if no ng-model
+
+ // Specify how UI should be updated
+ ngModel.$render = function() {
+ element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
+ };
+
+ // Listen for change events to enable binding
+ element.on('blur keyup change', function() {
+ scope.$evalAsync(read);
+ });
+ read(); // initialize
+
+ // Write data to the model
+ function read() {
+ var html = element.html();
+ // When we clear the content editable the browser leaves a <br> behind
+ // If strip-br attribute is provided then we strip this out
+ if ( attrs.stripBr && html == '<br>' ) {
+ html = '';
+ }
+ ngModel.$setViewValue(html);
+ }
+ }
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <form name="myForm">
+ <div contenteditable
+ name="myWidget" ng-model="userContent"
+ strip-br="true"
+ required>Change me!</div>
+ <span ng-show="myForm.myWidget.$error.required">Required!</span>
+ <hr>
+ <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should data-bind and become invalid', function() {
+ if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
+ // SafariDriver can't handle contenteditable
+ // and Firefox driver can't clear contenteditables very well
+ return;
+ }
+ var contentEditable = element(by.css('[contenteditable]'));
+ var content = 'Change me!';
+
+ expect(contentEditable.getText()).toEqual(content);
+
+ contentEditable.clear();
+ contentEditable.sendKeys(protractor.Key.BACK_SPACE);
+ expect(contentEditable.getText()).toEqual('');
+ expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
+ });
+ </file>
+ * </example>
+ *
+ *
+ */
+var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
+ function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
+ this.$viewValue = Number.NaN;
+ this.$modelValue = Number.NaN;
+ this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
+ this.$validators = {};
+ this.$asyncValidators = {};
+ this.$parsers = [];
+ this.$formatters = [];
+ this.$viewChangeListeners = [];
+ this.$untouched = true;
+ this.$touched = false;
+ this.$pristine = true;
+ this.$dirty = false;
+ this.$valid = true;
+ this.$invalid = false;
+ this.$error = {}; // keep invalid keys here
+ this.$$success = {}; // keep valid keys here
+ this.$pending = undefined; // keep pending keys here
+ this.$name = $interpolate($attr.name || '', false)($scope);
+ this.$$parentForm = nullFormCtrl;
+
+ var parsedNgModel = $parse($attr.ngModel),
+ parsedNgModelAssign = parsedNgModel.assign,
+ ngModelGet = parsedNgModel,
+ ngModelSet = parsedNgModelAssign,
+ pendingDebounce = null,
+ parserValid,
+ ctrl = this;
+
+ this.$$setOptions = function(options) {
+ ctrl.$options = options;
+ if (options && options.getterSetter) {
+ var invokeModelGetter = $parse($attr.ngModel + '()'),
+ invokeModelSetter = $parse($attr.ngModel + '($$$p)');
+
+ ngModelGet = function($scope) {
+ var modelValue = parsedNgModel($scope);
+ if (isFunction(modelValue)) {
+ modelValue = invokeModelGetter($scope);
+ }
+ return modelValue;
+ };
+ ngModelSet = function($scope, newValue) {
+ if (isFunction(parsedNgModel($scope))) {
+ invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
+ } else {
+ parsedNgModelAssign($scope, ctrl.$modelValue);
+ }
+ };
+ } else if (!parsedNgModel.assign) {
+ throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
+ $attr.ngModel, startingTag($element));
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$render
+ *
+ * @description
+ * Called when the view needs to be updated. It is expected that the user of the ng-model
+ * directive will implement this method.
+ *
+ * The `$render()` method is invoked in the following situations:
+ *
+ * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
+ * committed value then `$render()` is called to update the input control.
+ * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
+ * the `$viewValue` are different from last time.
+ *
+ * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
+ * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue`
+ * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
+ * invoked if you only change a property on the objects.
+ */
+ this.$render = noop;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$isEmpty
+ *
+ * @description
+ * This is called when we need to determine if the value of an input is empty.
+ *
+ * For instance, the required directive does this to work out if the input has data or not.
+ *
+ * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
+ *
+ * You can override this for input directives whose concept of being empty is different from the
+ * default. The `checkboxInputType` directive does this because in its case a value of `false`
+ * implies empty.
+ *
+ * @param {*} value The value of the input to check for emptiness.
+ * @returns {boolean} True if `value` is "empty".
+ */
+ this.$isEmpty = function(value) {
+ return isUndefined(value) || value === '' || value === null || value !== value;
+ };
+
+ var currentValidationRunId = 0;
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setValidity
+ *
+ * @description
+ * Change the validity state, and notify the form.
+ *
+ * This method can be called within $parsers/$formatters or a custom validation implementation.
+ * However, in most cases it should be sufficient to use the `ngModel.$validators` and
+ * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
+ *
+ * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
+ * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
+ * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
+ * The `validationErrorKey` should be in camelCase and will get converted into dash-case
+ * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
+ * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
+ * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
+ * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
+ * Skipped is used by Angular when validators do not run because of parse errors and
+ * when `$asyncValidators` do not run because any of the `$validators` failed.
+ */
+ addSetValidityMethod({
+ ctrl: this,
+ $element: $element,
+ set: function(object, property) {
+ object[property] = true;
+ },
+ unset: function(object, property) {
+ delete object[property];
+ },
+ $animate: $animate
+ });
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setPristine
+ *
+ * @description
+ * Sets the control to its pristine state.
+ *
+ * This method can be called to remove the `ng-dirty` class and set the control to its pristine
+ * state (`ng-pristine` class). A model is considered to be pristine when the control
+ * has not been changed from when first compiled.
+ */
+ this.$setPristine = function() {
+ ctrl.$dirty = false;
+ ctrl.$pristine = true;
+ $animate.removeClass($element, DIRTY_CLASS);
+ $animate.addClass($element, PRISTINE_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setDirty
+ *
+ * @description
+ * Sets the control to its dirty state.
+ *
+ * This method can be called to remove the `ng-pristine` class and set the control to its dirty
+ * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
+ * from when first compiled.
+ */
+ this.$setDirty = function() {
+ ctrl.$dirty = true;
+ ctrl.$pristine = false;
+ $animate.removeClass($element, PRISTINE_CLASS);
+ $animate.addClass($element, DIRTY_CLASS);
+ ctrl.$$parentForm.$setDirty();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setUntouched
+ *
+ * @description
+ * Sets the control to its untouched state.
+ *
+ * This method can be called to remove the `ng-touched` class and set the control to its
+ * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
+ * by default, however this function can be used to restore that state if the model has
+ * already been touched by the user.
+ */
+ this.$setUntouched = function() {
+ ctrl.$touched = false;
+ ctrl.$untouched = true;
+ $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setTouched
+ *
+ * @description
+ * Sets the control to its touched state.
+ *
+ * This method can be called to remove the `ng-untouched` class and set the control to its
+ * touched state (`ng-touched` class). A model is considered to be touched when the user has
+ * first focused the control element and then shifted focus away from the control (blur event).
+ */
+ this.$setTouched = function() {
+ ctrl.$touched = true;
+ ctrl.$untouched = false;
+ $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$rollbackViewValue
+ *
+ * @description
+ * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
+ * which may be caused by a pending debounced event or because the input is waiting for a some
+ * future event.
+ *
+ * If you have an input that uses `ng-model-options` to set up debounced events or events such
+ * as blur you can have a situation where there is a period when the `$viewValue`
+ * is out of synch with the ngModel's `$modelValue`.
+ *
+ * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
+ * programmatically before these debounced/future events have resolved/occurred, because Angular's
+ * dirty checking mechanism is not able to tell whether the model has actually changed or not.
+ *
+ * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
+ * input which may have such events pending. This is important in order to make sure that the
+ * input field will be updated with the new model value and any pending operations are cancelled.
+ *
+ * <example name="ng-model-cancel-update" module="cancel-update-example">
+ * <file name="app.js">
+ * angular.module('cancel-update-example', [])
+ *
+ * .controller('CancelUpdateController', ['$scope', function($scope) {
+ * $scope.resetWithCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myForm.myInput1.$rollbackViewValue();
+ * $scope.myValue = '';
+ * }
+ * };
+ * $scope.resetWithoutCancel = function(e) {
+ * if (e.keyCode == 27) {
+ * $scope.myValue = '';
+ * }
+ * };
+ * }]);
+ * </file>
+ * <file name="index.html">
+ * <div ng-controller="CancelUpdateController">
+ * <p>Try typing something in each input. See that the model only updates when you
+ * blur off the input.
+ * </p>
+ * <p>Now see what happens if you start typing then press the Escape key</p>
+ *
+ * <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
+ * <p id="inputDescription1">With $rollbackViewValue()</p>
+ * <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue"
+ * ng-keydown="resetWithCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ *
+ * <p id="inputDescription2">Without $rollbackViewValue()</p>
+ * <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue"
+ * ng-keydown="resetWithoutCancel($event)"><br/>
+ * myValue: "{{ myValue }}"
+ * </form>
+ * </div>
+ * </file>
+ * </example>
+ */
+ this.$rollbackViewValue = function() {
+ $timeout.cancel(pendingDebounce);
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
+ ctrl.$render();
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$validate
+ *
+ * @description
+ * Runs each of the registered validators (first synchronous validators and then
+ * asynchronous validators).
+ * If the validity changes to invalid, the model will be set to `undefined`,
+ * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
+ * If the validity changes to valid, it will set the model to the last available valid
+ * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
+ */
+ this.$validate = function() {
+ // ignore $validate before model is initialized
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ return;
+ }
+
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ // Note: we use the $$rawModelValue as $modelValue might have been
+ // set to undefined during a view -> model update that found validation
+ // errors. We can't parse the view here, since that could change
+ // the model although neither viewValue nor the model on the scope changed
+ var modelValue = ctrl.$$rawModelValue;
+
+ var prevValid = ctrl.$valid;
+ var prevModelValue = ctrl.$modelValue;
+
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+
+ ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
+ // If there was no change in validity, don't update the model
+ // This prevents changing an invalid modelValue to undefined
+ if (!allowInvalid && prevValid !== allValid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ });
+
+ };
+
+ this.$$runValidators = function(modelValue, viewValue, doneCallback) {
+ currentValidationRunId++;
+ var localValidationRunId = currentValidationRunId;
+
+ // check parser error
+ if (!processParseErrors()) {
+ validationDone(false);
+ return;
+ }
+ if (!processSyncValidators()) {
+ validationDone(false);
+ return;
+ }
+ processAsyncValidators();
+
+ function processParseErrors() {
+ var errorKey = ctrl.$$parserName || 'parse';
+ if (isUndefined(parserValid)) {
+ setValidity(errorKey, null);
+ } else {
+ if (!parserValid) {
+ forEach(ctrl.$validators, function(v, name) {
+ setValidity(name, null);
+ });
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ }
+ // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
+ setValidity(errorKey, parserValid);
+ return parserValid;
+ }
+ return true;
+ }
+
+ function processSyncValidators() {
+ var syncValidatorsValid = true;
+ forEach(ctrl.$validators, function(validator, name) {
+ var result = validator(modelValue, viewValue);
+ syncValidatorsValid = syncValidatorsValid && result;
+ setValidity(name, result);
+ });
+ if (!syncValidatorsValid) {
+ forEach(ctrl.$asyncValidators, function(v, name) {
+ setValidity(name, null);
+ });
+ return false;
+ }
+ return true;
+ }
+
+ function processAsyncValidators() {
+ var validatorPromises = [];
+ var allValid = true;
+ forEach(ctrl.$asyncValidators, function(validator, name) {
+ var promise = validator(modelValue, viewValue);
+ if (!isPromiseLike(promise)) {
+ throw ngModelMinErr("$asyncValidators",
+ "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
+ }
+ setValidity(name, undefined);
+ validatorPromises.push(promise.then(function() {
+ setValidity(name, true);
+ }, function(error) {
+ allValid = false;
+ setValidity(name, false);
+ }));
+ });
+ if (!validatorPromises.length) {
+ validationDone(true);
+ } else {
+ $q.all(validatorPromises).then(function() {
+ validationDone(allValid);
+ }, noop);
+ }
+ }
+
+ function setValidity(name, isValid) {
+ if (localValidationRunId === currentValidationRunId) {
+ ctrl.$setValidity(name, isValid);
+ }
+ }
+
+ function validationDone(allValid) {
+ if (localValidationRunId === currentValidationRunId) {
+
+ doneCallback(allValid);
+ }
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$commitViewValue
+ *
+ * @description
+ * Commit a pending update to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
+ * usually handles calling this in response to input events.
+ */
+ this.$commitViewValue = function() {
+ var viewValue = ctrl.$viewValue;
+
+ $timeout.cancel(pendingDebounce);
+
+ // If the view value has not changed then we should just exit, except in the case where there is
+ // a native validator on the element. In this case the validation state may have changed even though
+ // the viewValue has stayed empty.
+ if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
+ return;
+ }
+ ctrl.$$lastCommittedViewValue = viewValue;
+
+ // change to dirty
+ if (ctrl.$pristine) {
+ this.$setDirty();
+ }
+ this.$$parseAndValidate();
+ };
+
+ this.$$parseAndValidate = function() {
+ var viewValue = ctrl.$$lastCommittedViewValue;
+ var modelValue = viewValue;
+ parserValid = isUndefined(modelValue) ? undefined : true;
+
+ if (parserValid) {
+ for (var i = 0; i < ctrl.$parsers.length; i++) {
+ modelValue = ctrl.$parsers[i](modelValue);
+ if (isUndefined(modelValue)) {
+ parserValid = false;
+ break;
+ }
+ }
+ }
+ if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ // ctrl.$modelValue has not been touched yet...
+ ctrl.$modelValue = ngModelGet($scope);
+ }
+ var prevModelValue = ctrl.$modelValue;
+ var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+ ctrl.$$rawModelValue = modelValue;
+
+ if (allowInvalid) {
+ ctrl.$modelValue = modelValue;
+ writeToModelIfNeeded();
+ }
+
+ // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
+ // This can happen if e.g. $setViewValue is called from inside a parser
+ ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
+ if (!allowInvalid) {
+ // Note: Don't check ctrl.$valid here, as we could have
+ // external validators (e.g. calculated on the server),
+ // that just call $setValidity and need the model value
+ // to calculate their validity.
+ ctrl.$modelValue = allValid ? modelValue : undefined;
+ writeToModelIfNeeded();
+ }
+ });
+
+ function writeToModelIfNeeded() {
+ if (ctrl.$modelValue !== prevModelValue) {
+ ctrl.$$writeModelToScope();
+ }
+ }
+ };
+
+ this.$$writeModelToScope = function() {
+ ngModelSet($scope, ctrl.$modelValue);
+ forEach(ctrl.$viewChangeListeners, function(listener) {
+ try {
+ listener();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ });
+ };
+
+ /**
+ * @ngdoc method
+ * @name ngModel.NgModelController#$setViewValue
+ *
+ * @description
+ * Update the view value.
+ *
+ * This method should be called when a control wants to change the view value; typically,
+ * this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
+ * directive calls it when the value of the input changes and {@link ng.directive:select select}
+ * calls it when an option is selected.
+ *
+ * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
+ * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
+ * value sent directly for processing, finally to be applied to `$modelValue` and then the
+ * **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
+ * in the `$viewChangeListeners` list, are called.
+ *
+ * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
+ * and the `default` trigger is not listed, all those actions will remain pending until one of the
+ * `updateOn` events is triggered on the DOM element.
+ * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
+ * directive is used with a custom debounce for this particular event.
+ * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
+ * is specified, once the timer runs out.
+ *
+ * When used with standard inputs, the view value will always be a string (which is in some cases
+ * parsed into another type, such as a `Date` object for `input[date]`.)
+ * However, custom controls might also pass objects to this method. In this case, we should make
+ * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
+ * perform a deep watch of objects, it only looks for a change of identity. If you only change
+ * the property of the object then ngModel will not realise that the object has changed and
+ * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
+ * not change properties of the copy once it has been passed to `$setViewValue`.
+ * Otherwise you may cause the model value on the scope to change incorrectly.
+ *
+ * <div class="alert alert-info">
+ * In any case, the value passed to the method should always reflect the current value
+ * of the control. For example, if you are calling `$setViewValue` for an input element,
+ * you should pass the input DOM value. Otherwise, the control and the scope model become
+ * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
+ * the control's DOM value in any way. If we want to change the control's DOM value
+ * programmatically, we should update the `ngModel` scope expression. Its new value will be
+ * picked up by the model controller, which will run it through the `$formatters`, `$render` it
+ * to update the DOM, and finally call `$validate` on it.
+ * </div>
+ *
+ * @param {*} value value from the view.
+ * @param {string} trigger Event that triggered the update.
+ */
+ this.$setViewValue = function(value, trigger) {
+ ctrl.$viewValue = value;
+ if (!ctrl.$options || ctrl.$options.updateOnDefault) {
+ ctrl.$$debounceViewValueCommit(trigger);
+ }
+ };
+
+ this.$$debounceViewValueCommit = function(trigger) {
+ var debounceDelay = 0,
+ options = ctrl.$options,
+ debounce;
+
+ if (options && isDefined(options.debounce)) {
+ debounce = options.debounce;
+ if (isNumber(debounce)) {
+ debounceDelay = debounce;
+ } else if (isNumber(debounce[trigger])) {
+ debounceDelay = debounce[trigger];
+ } else if (isNumber(debounce['default'])) {
+ debounceDelay = debounce['default'];
+ }
+ }
+
+ $timeout.cancel(pendingDebounce);
+ if (debounceDelay) {
+ pendingDebounce = $timeout(function() {
+ ctrl.$commitViewValue();
+ }, debounceDelay);
+ } else if ($rootScope.$$phase) {
+ ctrl.$commitViewValue();
+ } else {
+ $scope.$apply(function() {
+ ctrl.$commitViewValue();
+ });
+ }
+ };
+
+ // model -> value
+ // Note: we cannot use a normal scope.$watch as we want to detect the following:
+ // 1. scope value is 'a'
+ // 2. user enters 'b'
+ // 3. ng-change kicks in and reverts scope value to 'a'
+ // -> scope value did not change since the last digest as
+ // ng-change executes in apply phase
+ // 4. view should be changed back to 'a'
+ $scope.$watch(function ngModelWatch() {
+ var modelValue = ngModelGet($scope);
+
+ // if scope model value and ngModel value are out of sync
+ // TODO(perf): why not move this to the action fn?
+ if (modelValue !== ctrl.$modelValue &&
+ // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
+ (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
+ ) {
+ ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
+ parserValid = undefined;
+
+ var formatters = ctrl.$formatters,
+ idx = formatters.length;
+
+ var viewValue = modelValue;
+ while (idx--) {
+ viewValue = formatters[idx](viewValue);
+ }
+ if (ctrl.$viewValue !== viewValue) {
+ ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
+ ctrl.$render();
+
+ ctrl.$$runValidators(modelValue, viewValue, noop);
+ }
+ }
+
+ return modelValue;
+ });
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngModel
+ *
+ * @element input
+ * @priority 1
+ *
+ * @description
+ * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
+ * property on the scope using {@link ngModel.NgModelController NgModelController},
+ * which is created and exposed by this directive.
+ *
+ * `ngModel` is responsible for:
+ *
+ * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
+ * require.
+ * - Providing validation behavior (i.e. required, number, email, url).
+ * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
+ * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
+ * - Registering the control with its parent {@link ng.directive:form form}.
+ *
+ * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
+ * current scope. If the property doesn't already exist on this scope, it will be created
+ * implicitly and added to the scope.
+ *
+ * For best practices on using `ngModel`, see:
+ *
+ * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
+ *
+ * For basic examples, how to use `ngModel`, see:
+ *
+ * - {@link ng.directive:input input}
+ * - {@link input[text] text}
+ * - {@link input[checkbox] checkbox}
+ * - {@link input[radio] radio}
+ * - {@link input[number] number}
+ * - {@link input[email] email}
+ * - {@link input[url] url}
+ * - {@link input[date] date}
+ * - {@link input[datetime-local] datetime-local}
+ * - {@link input[time] time}
+ * - {@link input[month] month}
+ * - {@link input[week] week}
+ * - {@link ng.directive:select select}
+ * - {@link ng.directive:textarea textarea}
+ *
+ * # CSS classes
+ * The following CSS classes are added and removed on the associated input/select/textarea element
+ * depending on the validity of the model.
+ *
+ * - `ng-valid`: the model is valid
+ * - `ng-invalid`: the model is invalid
+ * - `ng-valid-[key]`: for each valid key added by `$setValidity`
+ * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
+ * - `ng-pristine`: the control hasn't been interacted with yet
+ * - `ng-dirty`: the control has been interacted with
+ * - `ng-touched`: the control has been blurred
+ * - `ng-untouched`: the control hasn't been blurred
+ * - `ng-pending`: any `$asyncValidators` are unfulfilled
+ *
+ * Keep in mind that ngAnimate can detect each of these classes when added and removed.
+ *
+ * ## Animation Hooks
+ *
+ * Animations within models are triggered when any of the associated CSS classes are added and removed
+ * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
+ * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
+ * The animations that are triggered within ngModel are similar to how they work in ngClass and
+ * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
+ *
+ * The following example shows a simple way to utilize CSS transitions to style an input element
+ * that has been rendered as invalid after it has been validated:
+ *
+ * <pre>
+ * //be sure to include ngAnimate as a module to hook into more
+ * //advanced animations
+ * .my-input {
+ * transition:0.5s linear all;
+ * background: white;
+ * }
+ * .my-input.ng-invalid {
+ * background: red;
+ * color:white;
+ * }
+ * </pre>
+ *
+ * @example
+ * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
+ <file name="index.html">
+ <script>
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = '1';
+ }]);
+ </script>
+ <style>
+ .my-input {
+ transition:all linear 0.5s;
+ background: transparent;
+ }
+ .my-input.ng-invalid {
+ color:white;
+ background: red;
+ }
+ </style>
+ <p id="inputDescription">
+ Update input to see transitions when valid/invalid.
+ Integer is a valid value.
+ </p>
+ <form name="testForm" ng-controller="ExampleController">
+ <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input"
+ aria-describedby="inputDescription" />
+ </form>
+ </file>
+ * </example>
+ *
+ * ## Binding to a getter/setter
+ *
+ * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
+ * function that returns a representation of the model when called with zero arguments, and sets
+ * the internal state of a model when called with an argument. It's sometimes useful to use this
+ * for models that have an internal representation that's different from what the model exposes
+ * to the view.
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
+ * frequently than other parts of your code.
+ * </div>
+ *
+ * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
+ * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
+ * a `<form>`, which will enable this behavior for all `<input>`s within it. See
+ * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
+ *
+ * The following example shows how to use `ngModel` with a getter/setter:
+ *
+ * @example
+ * <example name="ngModel-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ <label>Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </label>
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ * </example>
+ */
+var ngModelDirective = ['$rootScope', function($rootScope) {
+ return {
+ restrict: 'A',
+ require: ['ngModel', '^?form', '^?ngModelOptions'],
+ controller: NgModelController,
+ // Prelink needs to run before any input directive
+ // so that we can set the NgModelOptions in NgModelController
+ // before anyone else uses it.
+ priority: 1,
+ compile: function ngModelCompile(element) {
+ // Setup initial state of the control
+ element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
+
+ return {
+ pre: function ngModelPreLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0],
+ formCtrl = ctrls[1] || modelCtrl.$$parentForm;
+
+ modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
+
+ // notify others, especially parent forms
+ formCtrl.$addControl(modelCtrl);
+
+ attr.$observe('name', function(newValue) {
+ if (modelCtrl.$name !== newValue) {
+ modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
+ }
+ });
+
+ scope.$on('$destroy', function() {
+ modelCtrl.$$parentForm.$removeControl(modelCtrl);
+ });
+ },
+ post: function ngModelPostLink(scope, element, attr, ctrls) {
+ var modelCtrl = ctrls[0];
+ if (modelCtrl.$options && modelCtrl.$options.updateOn) {
+ element.on(modelCtrl.$options.updateOn, function(ev) {
+ modelCtrl.$$debounceViewValueCommit(ev && ev.type);
+ });
+ }
+
+ element.on('blur', function(ev) {
+ if (modelCtrl.$touched) return;
+
+ if ($rootScope.$$phase) {
+ scope.$evalAsync(modelCtrl.$setTouched);
+ } else {
+ scope.$apply(modelCtrl.$setTouched);
+ }
+ });
+ }
+ };
+ }
+ };
+}];
+
+var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
+
+/**
+ * @ngdoc directive
+ * @name ngModelOptions
+ *
+ * @description
+ * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
+ * events that will trigger a model update and/or a debouncing delay so that the actual update only
+ * takes place when a timer expires; this timer will be reset after another change takes place.
+ *
+ * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
+ * be different from the value in the actual model. This means that if you update the model you
+ * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
+ * order to make sure it is synchronized with the model and that any debounced action is canceled.
+ *
+ * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
+ * method is by making sure the input is placed inside a form that has a `name` attribute. This is
+ * important because `form` controllers are published to the related scope under the name in their
+ * `name` attribute.
+ *
+ * Any pending changes will take place immediately when an enclosing form is submitted via the
+ * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
+ * to have access to the updated model.
+ *
+ * `ngModelOptions` has an effect on the element it's declared on and its descendants.
+ *
+ * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
+ * - `updateOn`: string specifying which event should the input be bound to. You can set several
+ * events using an space delimited list. There is a special event called `default` that
+ * matches the default events belonging of the control.
+ * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
+ * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
+ * custom value for each event. For example:
+ * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
+ * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
+ * not validate correctly instead of the default behavior of setting the model to undefined.
+ * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
+ `ngModel` as getters/setters.
+ * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
+ * `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the
+ * continental US time zone abbreviations, but for general use, use a time zone offset, for
+ * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
+ * If not specified, the timezone of the browser will be used.
+ *
+ * @example
+
+ The following example shows how to override immediate updates. Changes on the inputs within the
+ form will update the model only when the control loses focus (blur event). If `escape` key is
+ pressed while the input field is focused, the value is reset to the value in the current model.
+
+ <example name="ngModelOptions-directive-blur" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ <label>Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ updateOn: 'blur' }"
+ ng-keyup="cancel($event)" />
+ </label><br />
+ <label>Other data:
+ <input type="text" ng-model="user.data" />
+ </label><br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ <pre>user.data = <span ng-bind="user.data"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'John', data: '' };
+
+ $scope.cancel = function(e) {
+ if (e.keyCode == 27) {
+ $scope.userForm.userName.$rollbackViewValue();
+ }
+ };
+ }]);
+ </file>
+ <file name="protractor.js" type="protractor">
+ var model = element(by.binding('user.name'));
+ var input = element(by.model('user.name'));
+ var other = element(by.model('user.data'));
+
+ it('should allow custom events', function() {
+ input.sendKeys(' Doe');
+ input.click();
+ expect(model.getText()).toEqual('John');
+ other.click();
+ expect(model.getText()).toEqual('John Doe');
+ });
+
+ it('should $rollbackViewValue when model changes', function() {
+ input.sendKeys(' Doe');
+ expect(input.getAttribute('value')).toEqual('John Doe');
+ input.sendKeys(protractor.Key.ESCAPE);
+ expect(input.getAttribute('value')).toEqual('John');
+ other.click();
+ expect(model.getText()).toEqual('John');
+ });
+ </file>
+ </example>
+
+ This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
+ If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
+
+ <example name="ngModelOptions-directive-debounce" module="optionsExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ <label>Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ debounce: 1000 }" />
+ </label>
+ <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button>
+ <br />
+ </form>
+ <pre>user.name = <span ng-bind="user.name"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'Igor' };
+ }]);
+ </file>
+ </example>
+
+ This one shows how to bind to getter/setters:
+
+ <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ <label>Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </label>
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function(newName) {
+ // Note that newName can be undefined for two reasons:
+ // 1. Because it is called as a getter and thus called with no arguments
+ // 2. Because the property should actually be set to undefined. This happens e.g. if the
+ // input is invalid
+ return arguments.length ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ </example>
+ */
+var ngModelOptionsDirective = function() {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$attrs', function($scope, $attrs) {
+ var that = this;
+ this.$options = copy($scope.$eval($attrs.ngModelOptions));
+ // Allow adding/overriding bound events
+ if (isDefined(this.$options.updateOn)) {
+ this.$options.updateOnDefault = false;
+ // extract "default" pseudo-event from list of events that can trigger a model update
+ this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
+ that.$options.updateOnDefault = true;
+ return ' ';
+ }));
+ } else {
+ this.$options.updateOnDefault = true;
+ }
+ }]
+ };
+};
+
+
+
+// helper methods
+function addSetValidityMethod(context) {
+ var ctrl = context.ctrl,
+ $element = context.$element,
+ classCache = {},
+ set = context.set,
+ unset = context.unset,
+ $animate = context.$animate;
+
+ classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
+
+ ctrl.$setValidity = setValidity;
+
+ function setValidity(validationErrorKey, state, controller) {
+ if (isUndefined(state)) {
+ createAndSet('$pending', validationErrorKey, controller);
+ } else {
+ unsetAndCleanup('$pending', validationErrorKey, controller);
+ }
+ if (!isBoolean(state)) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ if (state) {
+ unset(ctrl.$error, validationErrorKey, controller);
+ set(ctrl.$$success, validationErrorKey, controller);
+ } else {
+ set(ctrl.$error, validationErrorKey, controller);
+ unset(ctrl.$$success, validationErrorKey, controller);
+ }
+ }
+ if (ctrl.$pending) {
+ cachedToggleClass(PENDING_CLASS, true);
+ ctrl.$valid = ctrl.$invalid = undefined;
+ toggleValidationCss('', null);
+ } else {
+ cachedToggleClass(PENDING_CLASS, false);
+ ctrl.$valid = isObjectEmpty(ctrl.$error);
+ ctrl.$invalid = !ctrl.$valid;
+ toggleValidationCss('', ctrl.$valid);
+ }
+
+ // re-read the state as the set/unset methods could have
+ // combined state in ctrl.$error[validationError] (used for forms),
+ // where setting/unsetting only increments/decrements the value,
+ // and does not replace it.
+ var combinedState;
+ if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
+ combinedState = undefined;
+ } else if (ctrl.$error[validationErrorKey]) {
+ combinedState = false;
+ } else if (ctrl.$$success[validationErrorKey]) {
+ combinedState = true;
+ } else {
+ combinedState = null;
+ }
+
+ toggleValidationCss(validationErrorKey, combinedState);
+ ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
+ }
+
+ function createAndSet(name, value, controller) {
+ if (!ctrl[name]) {
+ ctrl[name] = {};
+ }
+ set(ctrl[name], value, controller);
+ }
+
+ function unsetAndCleanup(name, value, controller) {
+ if (ctrl[name]) {
+ unset(ctrl[name], value, controller);
+ }
+ if (isObjectEmpty(ctrl[name])) {
+ ctrl[name] = undefined;
+ }
+ }
+
+ function cachedToggleClass(className, switchValue) {
+ if (switchValue && !classCache[className]) {
+ $animate.addClass($element, className);
+ classCache[className] = true;
+ } else if (!switchValue && classCache[className]) {
+ $animate.removeClass($element, className);
+ classCache[className] = false;
+ }
+ }
+
+ function toggleValidationCss(validationErrorKey, isValid) {
+ validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
+
+ cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
+ cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
+ }
+}
+
+function isObjectEmpty(obj) {
+ if (obj) {
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * @ngdoc directive
+ * @name ngNonBindable
+ * @restrict AC
+ * @priority 1000
+ *
+ * @description
+ * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
+ * DOM element. This is useful if the element contains what appears to be Angular directives and
+ * bindings but which should be ignored by Angular. This could be the case if you have a site that
+ * displays snippets of code, for instance.
+ *
+ * @element ANY
+ *
+ * @example
+ * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
+ * but the one wrapped in `ngNonBindable` is left alone.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <div>Normal: {{1 + 2}}</div>
+ <div ng-non-bindable>Ignored: {{1 + 2}}</div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-non-bindable', function() {
+ expect(element(by.binding('1 + 2')).getText()).toContain('3');
+ expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
+ });
+ </file>
+ </example>
+ */
+var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
+
+/* global jqLiteRemove */
+
+var ngOptionsMinErr = minErr('ngOptions');
+
+/**
+ * @ngdoc directive
+ * @name ngOptions
+ * @restrict A
+ *
+ * @description
+ *
+ * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
+ * elements for the `<select>` element using the array or object obtained by evaluating the
+ * `ngOptions` comprehension expression.
+ *
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
+ * similar result. However, `ngOptions` provides some benefits such as reducing memory and
+ * increasing speed by not creating a new scope for each repeated instance, as well as providing
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
+ * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
+ * to a non-string value. This is because an option element can only be bound to string values at
+ * present.
+ *
+ * When an item in the `<select>` menu is selected, the array element or object property
+ * represented by the selected option will be bound to the model identified by the `ngModel`
+ * directive.
+ *
+ * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
+ * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
+ * option. See example below for demonstration.
+ *
+ * ## Complex Models (objects or collections)
+ *
+ * By default, `ngModel` watches the model by reference, not value. This is important to know when
+ * binding the select to a model that is an object or a collection.
+ *
+ * One issue occurs if you want to preselect an option. For example, if you set
+ * the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
+ * because the objects are not identical. So by default, you should always reference the item in your collection
+ * for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
+ *
+ * Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
+ * of the item not by reference, but by the result of the `track by` expression. For example, if your
+ * collection items have an id property, you would `track by item.id`.
+ *
+ * A different issue with objects or collections is that ngModel won't detect if an object property or
+ * a collection item changes. For that reason, `ngOptions` additionally watches the model using
+ * `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
+ * This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
+ * has not changed identity, but only a property on the object or an item in the collection changes.
+ *
+ * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
+ * if the model is an array). This means that changing a property deeper than the first level inside the
+ * object/collection will not trigger a re-rendering.
+ *
+ * ## `select` **`as`**
+ *
+ * Using `select` **`as`** will bind the result of the `select` expression to the model, but
+ * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
+ * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
+ * is used, the result of that expression will be set as the value of the `option` and `select` elements.
+ *
+ *
+ * ### `select` **`as`** and **`track by`**
+ *
+ * <div class="alert alert-warning">
+ * Be careful when using `select` **`as`** and **`track by`** in the same expression.
+ * </div>
+ *
+ * Given this array of items on the $scope:
+ *
+ * ```js
+ * $scope.items = [{
+ * id: 1,
+ * label: 'aLabel',
+ * subItem: { name: 'aSubItem' }
+ * }, {
+ * id: 2,
+ * label: 'bLabel',
+ * subItem: { name: 'bSubItem' }
+ * }];
+ * ```
+ *
+ * This will work:
+ *
+ * ```html
+ * <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
+ * ```
+ * ```js
+ * $scope.selected = $scope.items[0];
+ * ```
+ *
+ * but this will not work:
+ *
+ * ```html
+ * <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
+ * ```
+ * ```js
+ * $scope.selected = $scope.items[0].subItem;
+ * ```
+ *
+ * In both examples, the **`track by`** expression is applied successfully to each `item` in the
+ * `items` array. Because the selected option has been set programmatically in the controller, the
+ * **`track by`** expression is also applied to the `ngModel` value. In the first example, the
+ * `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
+ * no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
+ * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
+ * is not matched against any `<option>` and the `<select>` appears as having no selected value.
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} required The control is considered valid only if value is entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {comprehension_expression=} ngOptions in one of the following forms:
+ *
+ * * for array data sources:
+ * * `label` **`for`** `value` **`in`** `array`
+ * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
+ * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
+ * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
+ * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
+ * (for including a filter with `track by`)
+ * * for object data sources:
+ * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
+ * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
+ * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`group by`** `group`
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
+ * * `select` **`as`** `label` **`disable when`** `disable`
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
+ *
+ * Where:
+ *
+ * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
+ * * `value`: local variable which will refer to each item in the `array` or each property value
+ * of `object` during iteration.
+ * * `key`: local variable which will refer to a property name in `object` during iteration.
+ * * `label`: The result of this expression will be the label for `<option>` element. The
+ * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
+ * * `select`: The result of this expression will be bound to the model of the parent `<select>`
+ * element. If not specified, `select` expression will default to `value`.
+ * * `group`: The result of this expression will be used to group options using the `<optgroup>`
+ * DOM element.
+ * * `disable`: The result of this expression will be used to disable the rendered `<option>`
+ * element. Return `true` to disable.
+ * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
+ * used to identify the objects in the array. The `trackexpr` will most likely refer to the
+ * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
+ * even when the options are recreated (e.g. reloaded from the server).
+ *
+ * @example
+ <example module="selectExample">
+ <file name="index.html">
+ <script>
+ angular.module('selectExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.colors = [
+ {name:'black', shade:'dark'},
+ {name:'white', shade:'light', notAnOption: true},
+ {name:'red', shade:'dark'},
+ {name:'blue', shade:'dark', notAnOption: true},
+ {name:'yellow', shade:'light', notAnOption: false}
+ ];
+ $scope.myColor = $scope.colors[2]; // red
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <ul>
+ <li ng-repeat="color in colors">
+ <label>Name: <input ng-model="color.name"></label>
+ <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label>
+ <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button>
+ </li>
+ <li>
+ <button ng-click="colors.push({})">add</button>
+ </li>
+ </ul>
+ <hr/>
+ <label>Color (null not allowed):
+ <select ng-model="myColor" ng-options="color.name for color in colors"></select>
+ </label><br/>
+ <label>Color (null allowed):
+ <span class="nullable">
+ <select ng-model="myColor" ng-options="color.name for color in colors">
+ <option value="">-- choose color --</option>
+ </select>
+ </span></label><br/>
+
+ <label>Color grouped by shade:
+ <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
+ </select>
+ </label><br/>
+
+ <label>Color grouped by shade, with some disabled:
+ <select ng-model="myColor"
+ ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
+ </select>
+ </label><br/>
+
+
+
+ Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>.
+ <br/>
+ <hr/>
+ Currently selected: {{ {selected_color:myColor} }}
+ <div style="border:solid 1px black; height:20px"
+ ng-style="{'background-color':myColor.name}">
+ </div>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should check ng-options', function() {
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
+ element.all(by.model('myColor')).first().click();
+ element.all(by.css('select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
+ element(by.css('.nullable select[ng-model="myColor"]')).click();
+ element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
+ expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
+ });
+ </file>
+ </example>
+ */
+
+// jshint maxlen: false
+// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
+var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
+ // 1: value expression (valueFn)
+ // 2: label expression (displayFn)
+ // 3: group by expression (groupByFn)
+ // 4: disable when expression (disableWhenFn)
+ // 5: array item variable name
+ // 6: object item key variable name
+ // 7: object item value variable name
+ // 8: collection expression
+ // 9: track by expression
+// jshint maxlen: 100
+
+
+var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
+
+ function parseOptionsExpression(optionsExp, selectElement, scope) {
+
+ var match = optionsExp.match(NG_OPTIONS_REGEXP);
+ if (!(match)) {
+ throw ngOptionsMinErr('iexp',
+ "Expected expression in form of " +
+ "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
+ " but got '{0}'. Element: {1}",
+ optionsExp, startingTag(selectElement));
+ }
+
+ // Extract the parts from the ngOptions expression
+
+ // The variable name for the value of the item in the collection
+ var valueName = match[5] || match[7];
+ // The variable name for the key of the item in the collection
+ var keyName = match[6];
+
+ // An expression that generates the viewValue for an option if there is a label expression
+ var selectAs = / as /.test(match[0]) && match[1];
+ // An expression that is used to track the id of each object in the options collection
+ var trackBy = match[9];
+ // An expression that generates the viewValue for an option if there is no label expression
+ var valueFn = $parse(match[2] ? match[1] : valueName);
+ var selectAsFn = selectAs && $parse(selectAs);
+ var viewValueFn = selectAsFn || valueFn;
+ var trackByFn = trackBy && $parse(trackBy);
+
+ // Get the value by which we are going to track the option
+ // if we have a trackFn then use that (passing scope and locals)
+ // otherwise just hash the given viewValue
+ var getTrackByValueFn = trackBy ?
+ function(value, locals) { return trackByFn(scope, locals); } :
+ function getHashOfValue(value) { return hashKey(value); };
+ var getTrackByValue = function(value, key) {
+ return getTrackByValueFn(value, getLocals(value, key));
+ };
+
+ var displayFn = $parse(match[2] || match[1]);
+ var groupByFn = $parse(match[3] || '');
+ var disableWhenFn = $parse(match[4] || '');
+ var valuesFn = $parse(match[8]);
+
+ var locals = {};
+ var getLocals = keyName ? function(value, key) {
+ locals[keyName] = key;
+ locals[valueName] = value;
+ return locals;
+ } : function(value) {
+ locals[valueName] = value;
+ return locals;
+ };
+
+
+ function Option(selectValue, viewValue, label, group, disabled) {
+ this.selectValue = selectValue;
+ this.viewValue = viewValue;
+ this.label = label;
+ this.group = group;
+ this.disabled = disabled;
+ }
+
+ function getOptionValuesKeys(optionValues) {
+ var optionValuesKeys;
+
+ if (!keyName && isArrayLike(optionValues)) {
+ optionValuesKeys = optionValues;
+ } else {
+ // if object, extract keys, in enumeration order, unsorted
+ optionValuesKeys = [];
+ for (var itemKey in optionValues) {
+ if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
+ optionValuesKeys.push(itemKey);
+ }
+ }
+ }
+ return optionValuesKeys;
+ }
+
+ return {
+ trackBy: trackBy,
+ getTrackByValue: getTrackByValue,
+ getWatchables: $parse(valuesFn, function(optionValues) {
+ // Create a collection of things that we would like to watch (watchedArray)
+ // so that they can all be watched using a single $watchCollection
+ // that only runs the handler once if anything changes
+ var watchedArray = [];
+ optionValues = optionValues || [];
+
+ var optionValuesKeys = getOptionValuesKeys(optionValues);
+ var optionValuesLength = optionValuesKeys.length;
+ for (var index = 0; index < optionValuesLength; index++) {
+ var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
+ var value = optionValues[key];
+
+ var locals = getLocals(optionValues[key], key);
+ var selectValue = getTrackByValueFn(optionValues[key], locals);
+ watchedArray.push(selectValue);
+
+ // Only need to watch the displayFn if there is a specific label expression
+ if (match[2] || match[1]) {
+ var label = displayFn(scope, locals);
+ watchedArray.push(label);
+ }
+
+ // Only need to watch the disableWhenFn if there is a specific disable expression
+ if (match[4]) {
+ var disableWhen = disableWhenFn(scope, locals);
+ watchedArray.push(disableWhen);
+ }
+ }
+ return watchedArray;
+ }),
+
+ getOptions: function() {
+
+ var optionItems = [];
+ var selectValueMap = {};
+
+ // The option values were already computed in the `getWatchables` fn,
+ // which must have been called to trigger `getOptions`
+ var optionValues = valuesFn(scope) || [];
+ var optionValuesKeys = getOptionValuesKeys(optionValues);
+ var optionValuesLength = optionValuesKeys.length;
+
+ for (var index = 0; index < optionValuesLength; index++) {
+ var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
+ var value = optionValues[key];
+ var locals = getLocals(value, key);
+ var viewValue = viewValueFn(scope, locals);
+ var selectValue = getTrackByValueFn(viewValue, locals);
+ var label = displayFn(scope, locals);
+ var group = groupByFn(scope, locals);
+ var disabled = disableWhenFn(scope, locals);
+ var optionItem = new Option(selectValue, viewValue, label, group, disabled);
+
+ optionItems.push(optionItem);
+ selectValueMap[selectValue] = optionItem;
+ }
+
+ return {
+ items: optionItems,
+ selectValueMap: selectValueMap,
+ getOptionFromViewValue: function(value) {
+ return selectValueMap[getTrackByValue(value)];
+ },
+ getViewValueFromOption: function(option) {
+ // If the viewValue could be an object that may be mutated by the application,
+ // we need to make a copy and not return the reference to the value on the option.
+ return trackBy ? angular.copy(option.viewValue) : option.viewValue;
+ }
+ };
+ }
+ };
+ }
+
+
+ // we can't just jqLite('<option>') since jqLite is not smart enough
+ // to create it in <select> and IE barfs otherwise.
+ var optionTemplate = document.createElement('option'),
+ optGroupTemplate = document.createElement('optgroup');
+
+
+ function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
+
+ // if ngModel is not defined, we don't need to do anything
+ var ngModelCtrl = ctrls[1];
+ if (!ngModelCtrl) return;
+
+ var selectCtrl = ctrls[0];
+ var multiple = attr.multiple;
+
+ // The emptyOption allows the application developer to provide their own custom "empty"
+ // option when the viewValue does not match any of the option values.
+ var emptyOption;
+ for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) {
+ if (children[i].value === '') {
+ emptyOption = children.eq(i);
+ break;
+ }
+ }
+
+ var providedEmptyOption = !!emptyOption;
+
+ var unknownOption = jqLite(optionTemplate.cloneNode(false));
+ unknownOption.val('?');
+
+ var options;
+ var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);
+
+
+ var renderEmptyOption = function() {
+ if (!providedEmptyOption) {
+ selectElement.prepend(emptyOption);
+ }
+ selectElement.val('');
+ emptyOption.prop('selected', true); // needed for IE
+ emptyOption.attr('selected', true);
+ };
+
+ var removeEmptyOption = function() {
+ if (!providedEmptyOption) {
+ emptyOption.remove();
+ }
+ };
+
+
+ var renderUnknownOption = function() {
+ selectElement.prepend(unknownOption);
+ selectElement.val('?');
+ unknownOption.prop('selected', true); // needed for IE
+ unknownOption.attr('selected', true);
+ };
+
+ var removeUnknownOption = function() {
+ unknownOption.remove();
+ };
+
+ // Update the controller methods for multiple selectable options
+ if (!multiple) {
+
+ selectCtrl.writeValue = function writeNgOptionsValue(value) {
+ var option = options.getOptionFromViewValue(value);
+
+ if (option && !option.disabled) {
+ if (selectElement[0].value !== option.selectValue) {
+ removeUnknownOption();
+ removeEmptyOption();
+
+ selectElement[0].value = option.selectValue;
+ option.element.selected = true;
+ option.element.setAttribute('selected', 'selected');
+ }
+ } else {
+ if (value === null || providedEmptyOption) {
+ removeUnknownOption();
+ renderEmptyOption();
+ } else {
+ removeEmptyOption();
+ renderUnknownOption();
+ }
+ }
+ };
+
+ selectCtrl.readValue = function readNgOptionsValue() {
+
+ var selectedOption = options.selectValueMap[selectElement.val()];
+
+ if (selectedOption && !selectedOption.disabled) {
+ removeEmptyOption();
+ removeUnknownOption();
+ return options.getViewValueFromOption(selectedOption);
+ }
+ return null;
+ };
+
+ // If we are using `track by` then we must watch the tracked value on the model
+ // since ngModel only watches for object identity change
+ if (ngOptions.trackBy) {
+ scope.$watch(
+ function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },
+ function() { ngModelCtrl.$render(); }
+ );
+ }
+
+ } else {
+
+ ngModelCtrl.$isEmpty = function(value) {
+ return !value || value.length === 0;
+ };
+
+
+ selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
+ options.items.forEach(function(option) {
+ option.element.selected = false;
+ });
+
+ if (value) {
+ value.forEach(function(item) {
+ var option = options.getOptionFromViewValue(item);
+ if (option && !option.disabled) option.element.selected = true;
+ });
+ }
+ };
+
+
+ selectCtrl.readValue = function readNgOptionsMultiple() {
+ var selectedValues = selectElement.val() || [],
+ selections = [];
+
+ forEach(selectedValues, function(value) {
+ var option = options.selectValueMap[value];
+ if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));
+ });
+
+ return selections;
+ };
+
+ // If we are using `track by` then we must watch these tracked values on the model
+ // since ngModel only watches for object identity change
+ if (ngOptions.trackBy) {
+
+ scope.$watchCollection(function() {
+ if (isArray(ngModelCtrl.$viewValue)) {
+ return ngModelCtrl.$viewValue.map(function(value) {
+ return ngOptions.getTrackByValue(value);
+ });
+ }
+ }, function() {
+ ngModelCtrl.$render();
+ });
+
+ }
+ }
+
+
+ if (providedEmptyOption) {
+
+ // we need to remove it before calling selectElement.empty() because otherwise IE will
+ // remove the label from the element. wtf?
+ emptyOption.remove();
+
+ // compile the element since there might be bindings in it
+ $compile(emptyOption)(scope);
+
+ // remove the class, which is added automatically because we recompile the element and it
+ // becomes the compilation root
+ emptyOption.removeClass('ng-scope');
+ } else {
+ emptyOption = jqLite(optionTemplate.cloneNode(false));
+ }
+
+ // We need to do this here to ensure that the options object is defined
+ // when we first hit it in writeNgOptionsValue
+ updateOptions();
+
+ // We will re-render the option elements if the option values or labels change
+ scope.$watchCollection(ngOptions.getWatchables, updateOptions);
+
+ // ------------------------------------------------------------------ //
+
+
+ function updateOptionElement(option, element) {
+ option.element = element;
+ element.disabled = option.disabled;
+ // NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
+ // selects in certain circumstances when multiple selects are next to each other and display
+ // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
+ // See https://github.com/angular/angular.js/issues/11314 for more info.
+ // This is unfortunately untestable with unit / e2e tests
+ if (option.label !== element.label) {
+ element.label = option.label;
+ element.textContent = option.label;
+ }
+ if (option.value !== element.value) element.value = option.selectValue;
+ }
+
+ function addOrReuseElement(parent, current, type, templateElement) {
+ var element;
+ // Check whether we can reuse the next element
+ if (current && lowercase(current.nodeName) === type) {
+ // The next element is the right type so reuse it
+ element = current;
+ } else {
+ // The next element is not the right type so create a new one
+ element = templateElement.cloneNode(false);
+ if (!current) {
+ // There are no more elements so just append it to the select
+ parent.appendChild(element);
+ } else {
+ // The next element is not a group so insert the new one
+ parent.insertBefore(element, current);
+ }
+ }
+ return element;
+ }
+
+
+ function removeExcessElements(current) {
+ var next;
+ while (current) {
+ next = current.nextSibling;
+ jqLiteRemove(current);
+ current = next;
+ }
+ }
+
+
+ function skipEmptyAndUnknownOptions(current) {
+ var emptyOption_ = emptyOption && emptyOption[0];
+ var unknownOption_ = unknownOption && unknownOption[0];
+
+ // We cannot rely on the extracted empty option being the same as the compiled empty option,
+ // because the compiled empty option might have been replaced by a comment because
+ // it had an "element" transclusion directive on it (such as ngIf)
+ if (emptyOption_ || unknownOption_) {
+ while (current &&
+ (current === emptyOption_ ||
+ current === unknownOption_ ||
+ current.nodeType === NODE_TYPE_COMMENT ||
+ current.value === '')) {
+ current = current.nextSibling;
+ }
+ }
+ return current;
+ }
+
+
+ function updateOptions() {
+
+ var previousValue = options && selectCtrl.readValue();
+
+ options = ngOptions.getOptions();
+
+ var groupMap = {};
+ var currentElement = selectElement[0].firstChild;
+
+ // Ensure that the empty option is always there if it was explicitly provided
+ if (providedEmptyOption) {
+ selectElement.prepend(emptyOption);
+ }
+
+ currentElement = skipEmptyAndUnknownOptions(currentElement);
+
+ options.items.forEach(function updateOption(option) {
+ var group;
+ var groupElement;
+ var optionElement;
+
+ if (option.group) {
+
+ // This option is to live in a group
+ // See if we have already created this group
+ group = groupMap[option.group];
+
+ if (!group) {
+
+ // We have not already created this group
+ groupElement = addOrReuseElement(selectElement[0],
+ currentElement,
+ 'optgroup',
+ optGroupTemplate);
+ // Move to the next element
+ currentElement = groupElement.nextSibling;
+
+ // Update the label on the group element
+ groupElement.label = option.group;
+
+ // Store it for use later
+ group = groupMap[option.group] = {
+ groupElement: groupElement,
+ currentOptionElement: groupElement.firstChild
+ };
+
+ }
+
+ // So now we have a group for this option we add the option to the group
+ optionElement = addOrReuseElement(group.groupElement,
+ group.currentOptionElement,
+ 'option',
+ optionTemplate);
+ updateOptionElement(option, optionElement);
+ // Move to the next element
+ group.currentOptionElement = optionElement.nextSibling;
+
+ } else {
+
+ // This option is not in a group
+ optionElement = addOrReuseElement(selectElement[0],
+ currentElement,
+ 'option',
+ optionTemplate);
+ updateOptionElement(option, optionElement);
+ // Move to the next element
+ currentElement = optionElement.nextSibling;
+ }
+ });
+
+
+ // Now remove all excess options and group
+ Object.keys(groupMap).forEach(function(key) {
+ removeExcessElements(groupMap[key].currentOptionElement);
+ });
+ removeExcessElements(currentElement);
+
+ ngModelCtrl.$render();
+
+ // Check to see if the value has changed due to the update to the options
+ if (!ngModelCtrl.$isEmpty(previousValue)) {
+ var nextValue = selectCtrl.readValue();
+ if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
+ ngModelCtrl.$setViewValue(nextValue);
+ ngModelCtrl.$render();
+ }
+ }
+
+ }
+ }
+
+ return {
+ restrict: 'A',
+ terminal: true,
+ require: ['select', '?ngModel'],
+ link: {
+ pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
+ // Deactivate the SelectController.register method to prevent
+ // option directives from accidentally registering themselves
+ // (and unwanted $destroy handlers etc.)
+ ctrls[0].registerOption = noop;
+ },
+ post: ngOptionsPostLink
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngPluralize
+ * @restrict EA
+ *
+ * @description
+ * `ngPluralize` is a directive that displays messages according to en-US localization rules.
+ * These rules are bundled with angular.js, but can be overridden
+ * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
+ * by specifying the mappings between
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * and the strings to be displayed.
+ *
+ * # Plural categories and explicit number rules
+ * There are two
+ * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
+ * in Angular's default en-US locale: "one" and "other".
+ *
+ * While a plural category may match many numbers (for example, in en-US locale, "other" can match
+ * any number that is not 1), an explicit number rule can only match one number. For example, the
+ * explicit number rule for "3" matches the number 3. There are examples of plural categories
+ * and explicit number rules throughout the rest of this documentation.
+ *
+ * # Configuring ngPluralize
+ * You configure ngPluralize by providing 2 attributes: `count` and `when`.
+ * You can also provide an optional attribute, `offset`.
+ *
+ * The value of the `count` attribute can be either a string or an {@link guide/expression
+ * Angular expression}; these are evaluated on the current scope for its bound value.
+ *
+ * The `when` attribute specifies the mappings between plural categories and the actual
+ * string to be displayed. The value of the attribute should be a JSON object.
+ *
+ * The following example shows how to configure ngPluralize:
+ *
+ * ```html
+ * <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ * 'one': '1 person is viewing.',
+ * 'other': '{} people are viewing.'}">
+ * </ng-pluralize>
+ *```
+ *
+ * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
+ * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
+ * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
+ * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
+ * show "a dozen people are viewing".
+ *
+ * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
+ * into pluralized strings. In the previous example, Angular will replace `{}` with
+ * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
+ * for <span ng-non-bindable>{{numberExpression}}</span>.
+ *
+ * If no rule is defined for a category, then an empty string is displayed and a warning is generated.
+ * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`.
+ *
+ * # Configuring ngPluralize with offset
+ * The `offset` attribute allows further customization of pluralized text, which can result in
+ * a better user experience. For example, instead of the message "4 people are viewing this document",
+ * you might display "John, Kate and 2 others are viewing this document".
+ * The offset attribute allows you to offset a number by any desired value.
+ * Let's take a look at an example:
+ *
+ * ```html
+ * <ng-pluralize count="personCount" offset=2
+ * when="{'0': 'Nobody is viewing.',
+ * '1': '{{person1}} is viewing.',
+ * '2': '{{person1}} and {{person2}} are viewing.',
+ * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ * </ng-pluralize>
+ * ```
+ *
+ * Notice that we are still using two plural categories(one, other), but we added
+ * three explicit number rules 0, 1 and 2.
+ * When one person, perhaps John, views the document, "John is viewing" will be shown.
+ * When three people view the document, no explicit number rule is found, so
+ * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
+ * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
+ * is shown.
+ *
+ * Note that when you specify offsets, you must provide explicit number rules for
+ * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
+ * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
+ * plural categories "one" and "other".
+ *
+ * @param {string|expression} count The variable to be bound to.
+ * @param {string} when The mapping between plural category to its corresponding strings.
+ * @param {number=} offset Offset to deduct from the total number.
+ *
+ * @example
+ <example module="pluralizeExample">
+ <file name="index.html">
+ <script>
+ angular.module('pluralizeExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.person1 = 'Igor';
+ $scope.person2 = 'Misko';
+ $scope.personCount = 1;
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/>
+ <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/>
+ <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/>
+
+ <!--- Example with simple pluralization rules for en locale --->
+ Without Offset:
+ <ng-pluralize count="personCount"
+ when="{'0': 'Nobody is viewing.',
+ 'one': '1 person is viewing.',
+ 'other': '{} people are viewing.'}">
+ </ng-pluralize><br>
+
+ <!--- Example with offset --->
+ With Offset(2):
+ <ng-pluralize count="personCount" offset=2
+ when="{'0': 'Nobody is viewing.',
+ '1': '{{person1}} is viewing.',
+ '2': '{{person1}} and {{person2}} are viewing.',
+ 'one': '{{person1}}, {{person2}} and one other person are viewing.',
+ 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
+ </ng-pluralize>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should show correct pluralized string', function() {
+ var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var countInput = element(by.model('personCount'));
+
+ expect(withoutOffset.getText()).toEqual('1 person is viewing.');
+ expect(withOffset.getText()).toEqual('Igor is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('0');
+
+ expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
+ expect(withOffset.getText()).toEqual('Nobody is viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('2');
+
+ expect(withoutOffset.getText()).toEqual('2 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('3');
+
+ expect(withoutOffset.getText()).toEqual('3 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
+
+ countInput.clear();
+ countInput.sendKeys('4');
+
+ expect(withoutOffset.getText()).toEqual('4 people are viewing.');
+ expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
+ });
+ it('should show data-bound names', function() {
+ var withOffset = element.all(by.css('ng-pluralize')).get(1);
+ var personCount = element(by.model('personCount'));
+ var person1 = element(by.model('person1'));
+ var person2 = element(by.model('person2'));
+ personCount.clear();
+ personCount.sendKeys('4');
+ person1.clear();
+ person1.sendKeys('Di');
+ person2.clear();
+ person2.sendKeys('Vojta');
+ expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
+ });
+ </file>
+ </example>
+ */
+var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {
+ var BRACE = /{}/g,
+ IS_WHEN = /^when(Minus)?(.+)$/;
+
+ return {
+ link: function(scope, element, attr) {
+ var numberExp = attr.count,
+ whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
+ offset = attr.offset || 0,
+ whens = scope.$eval(whenExp) || {},
+ whensExpFns = {},
+ startSymbol = $interpolate.startSymbol(),
+ endSymbol = $interpolate.endSymbol(),
+ braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
+ watchRemover = angular.noop,
+ lastCount;
+
+ forEach(attr, function(expression, attributeName) {
+ var tmpMatch = IS_WHEN.exec(attributeName);
+ if (tmpMatch) {
+ var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
+ whens[whenKey] = element.attr(attr.$attr[attributeName]);
+ }
+ });
+ forEach(whens, function(expression, key) {
+ whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
+
+ });
+
+ scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
+ var count = parseFloat(newVal);
+ var countIsNaN = isNaN(count);
+
+ if (!countIsNaN && !(count in whens)) {
+ // If an explicit number rule such as 1, 2, 3... is defined, just use it.
+ // Otherwise, check it against pluralization rules in $locale service.
+ count = $locale.pluralCat(count - offset);
+ }
+
+ // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
+ // In JS `NaN !== NaN`, so we have to exlicitly check.
+ if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
+ watchRemover();
+ var whenExpFn = whensExpFns[count];
+ if (isUndefined(whenExpFn)) {
+ if (newVal != null) {
+ $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp);
+ }
+ watchRemover = noop;
+ updateElementText();
+ } else {
+ watchRemover = scope.$watch(whenExpFn, updateElementText);
+ }
+ lastCount = count;
+ }
+ });
+
+ function updateElementText(newText) {
+ element.text(newText || '');
+ }
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngRepeat
+ * @multiElement
+ *
+ * @description
+ * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
+ * instance gets its own scope, where the given loop variable is set to the current collection item,
+ * and `$index` is set to the item index or key.
+ *
+ * Special properties are exposed on the local scope of each template instance, including:
+ *
+ * | Variable | Type | Details |
+ * |-----------|-----------------|-----------------------------------------------------------------------------|
+ * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
+ * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
+ * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
+ * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
+ * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
+ * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
+ *
+ * <div class="alert alert-info">
+ * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
+ * This may be useful when, for instance, nesting ngRepeats.
+ * </div>
+ *
+ *
+ * # Iterating over object properties
+ *
+ * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
+ * syntax:
+ *
+ * ```js
+ * <div ng-repeat="(key, value) in myObj"> ... </div>
+ * ```
+ *
+ * You need to be aware that the JavaScript specification does not define the order of keys
+ * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive
+ * used to sort the keys alphabetically.)
+ *
+ * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
+ * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
+ * keys in the order in which they were defined, although there are exceptions when keys are deleted
+ * and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
+ *
+ * If this is not desired, the recommended workaround is to convert your object into an array
+ * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
+ * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
+ * or implement a `$watch` on the object yourself.
+ *
+ *
+ * # Tracking and Duplicates
+ *
+ * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
+ * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
+ *
+ * * When an item is added, a new instance of the template is added to the DOM.
+ * * When an item is removed, its template instance is removed from the DOM.
+ * * When items are reordered, their respective templates are reordered in the DOM.
+ *
+ * To minimize creation of DOM elements, `ngRepeat` uses a function
+ * to "keep track" of all items in the collection and their corresponding DOM elements.
+ * For example, if an item is added to the collection, ngRepeat will know that all other items
+ * already have DOM elements, and will not re-render them.
+ *
+ * The default tracking function (which tracks items by their identity) does not allow
+ * duplicate items in arrays. This is because when there are duplicates, it is not possible
+ * to maintain a one-to-one mapping between collection items and DOM elements.
+ *
+ * If you do need to repeat duplicate items, you can substitute the default tracking behavior
+ * with your own using the `track by` expression.
+ *
+ * For example, you may track items by the index of each item in the collection, using the
+ * special scope property `$index`:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * You may also use arbitrary expressions in `track by`, including references to custom functions
+ * on the scope:
+ * ```html
+ * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
+ * {{n}}
+ * </div>
+ * ```
+ *
+ * <div class="alert alert-success">
+ * If you are working with objects that have an identifier property, you should track
+ * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
+ * will not have to rebuild the DOM elements for items it has already rendered, even if the
+ * JavaScript objects in the collection have been substituted for new ones. For large collections,
+ * this signifincantly improves rendering performance. If you don't have a unique identifier,
+ * `track by $index` can also provide a performance boost.
+ * </div>
+ * ```html
+ * <div ng-repeat="model in collection track by model.id">
+ * {{model.name}}
+ * </div>
+ * ```
+ *
+ * When no `track by` expression is provided, it is equivalent to tracking by the built-in
+ * `$id` function, which tracks items by their identity:
+ * ```html
+ * <div ng-repeat="obj in collection track by $id(obj)">
+ * {{obj.prop}}
+ * </div>
+ * ```
+ *
+ * <div class="alert alert-warning">
+ * **Note:** `track by` must always be the last expression:
+ * </div>
+ * ```
+ * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
+ * {{model.name}}
+ * </div>
+ * ```
+ *
+ * # Special repeat start and end points
+ * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
+ * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
+ * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
+ * up to and including the ending HTML tag where **ng-repeat-end** is placed.
+ *
+ * The example below makes use of this feature:
+ * ```html
+ * <header ng-repeat-start="item in items">
+ * Header {{ item }}
+ * </header>
+ * <div class="body">
+ * Body {{ item }}
+ * </div>
+ * <footer ng-repeat-end>
+ * Footer {{ item }}
+ * </footer>
+ * ```
+ *
+ * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
+ * ```html
+ * <header>
+ * Header A
+ * </header>
+ * <div class="body">
+ * Body A
+ * </div>
+ * <footer>
+ * Footer A
+ * </footer>
+ * <header>
+ * Header B
+ * </header>
+ * <div class="body">
+ * Body B
+ * </div>
+ * <footer>
+ * Footer B
+ * </footer>
+ * ```
+ *
+ * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
+ * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
+ *
+ * @animations
+ * **.enter** - when a new item is added to the list or when an item is revealed after a filter
+ *
+ * **.leave** - when an item is removed from the list or when an item is filtered out
+ *
+ * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
+ *
+ * @element ANY
+ * @scope
+ * @priority 1000
+ * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
+ * formats are currently supported:
+ *
+ * * `variable in expression` – where variable is the user defined loop variable and `expression`
+ * is a scope expression giving the collection to enumerate.
+ *
+ * For example: `album in artist.albums`.
+ *
+ * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
+ * and `expression` is the scope expression giving the collection to enumerate.
+ *
+ * For example: `(name, age) in {'adam':10, 'amalie':12}`.
+ *
+ * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
+ * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
+ * is specified, ng-repeat associates elements by identity. It is an error to have
+ * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
+ * mapped to the same DOM element, which is not possible.)
+ *
+ * Note that the tracking expression must come last, after any filters, and the alias expression.
+ *
+ * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
+ * will be associated by item identity in the array.
+ *
+ * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
+ * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
+ * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
+ * element in the same way in the DOM.
+ *
+ * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
+ * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
+ * property is same.
+ *
+ * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
+ * to items in conjunction with a tracking expression.
+ *
+ * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
+ * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
+ * when a filter is active on the repeater, but the filtered result set is empty.
+ *
+ * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
+ * the items have been processed through the filter.
+ *
+ * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
+ * (and not as operator, inside an expression).
+ *
+ * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
+ *
+ * @example
+ * This example initializes the scope to a list of names and
+ * then uses `ngRepeat` to display every person:
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-init="friends = [
+ {name:'John', age:25, gender:'boy'},
+ {name:'Jessie', age:30, gender:'girl'},
+ {name:'Johanna', age:28, gender:'girl'},
+ {name:'Joy', age:15, gender:'girl'},
+ {name:'Mary', age:28, gender:'girl'},
+ {name:'Peter', age:95, gender:'boy'},
+ {name:'Sebastian', age:50, gender:'boy'},
+ {name:'Erika', age:27, gender:'girl'},
+ {name:'Patrick', age:40, gender:'boy'},
+ {name:'Samantha', age:60, gender:'girl'}
+ ]">
+ I have {{friends.length}} friends. They are:
+ <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
+ <ul class="example-animate-container">
+ <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
+ [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
+ </li>
+ <li class="animate-repeat" ng-if="results.length == 0">
+ <strong>No results found...</strong>
+ </li>
+ </ul>
+ </div>
+ </file>
+ <file name="animations.css">
+ .example-animate-container {
+ background:white;
+ border:1px solid black;
+ list-style:none;
+ margin:0;
+ padding:0 10px;
+ }
+
+ .animate-repeat {
+ line-height:40px;
+ list-style:none;
+ box-sizing:border-box;
+ }
+
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter,
+ .animate-repeat.ng-leave {
+ transition:all linear 0.5s;
+ }
+
+ .animate-repeat.ng-leave.ng-leave-active,
+ .animate-repeat.ng-move,
+ .animate-repeat.ng-enter {
+ opacity:0;
+ max-height:0;
+ }
+
+ .animate-repeat.ng-leave,
+ .animate-repeat.ng-move.ng-move-active,
+ .animate-repeat.ng-enter.ng-enter-active {
+ opacity:1;
+ max-height:40px;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var friends = element.all(by.repeater('friend in friends'));
+
+ it('should render initial data set', function() {
+ expect(friends.count()).toBe(10);
+ expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
+ expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
+ expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
+ expect(element(by.binding('friends.length')).getText())
+ .toMatch("I have 10 friends. They are:");
+ });
+
+ it('should update repeater when filter predicate changes', function() {
+ expect(friends.count()).toBe(10);
+
+ element(by.model('q')).sendKeys('ma');
+
+ expect(friends.count()).toBe(2);
+ expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
+ expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
+ });
+ </file>
+ </example>
+ */
+var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
+ var NG_REMOVED = '$$NG_REMOVED';
+ var ngRepeatMinErr = minErr('ngRepeat');
+
+ var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
+ // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
+ scope[valueIdentifier] = value;
+ if (keyIdentifier) scope[keyIdentifier] = key;
+ scope.$index = index;
+ scope.$first = (index === 0);
+ scope.$last = (index === (arrayLength - 1));
+ scope.$middle = !(scope.$first || scope.$last);
+ // jshint bitwise: false
+ scope.$odd = !(scope.$even = (index&1) === 0);
+ // jshint bitwise: true
+ };
+
+ var getBlockStart = function(block) {
+ return block.clone[0];
+ };
+
+ var getBlockEnd = function(block) {
+ return block.clone[block.clone.length - 1];
+ };
+
+
+ return {
+ restrict: 'A',
+ multiElement: true,
+ transclude: 'element',
+ priority: 1000,
+ terminal: true,
+ $$tlb: true,
+ compile: function ngRepeatCompile($element, $attr) {
+ var expression = $attr.ngRepeat;
+ var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
+
+ var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
+ expression);
+ }
+
+ var lhs = match[1];
+ var rhs = match[2];
+ var aliasAs = match[3];
+ var trackByExp = match[4];
+
+ match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
+
+ if (!match) {
+ throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
+ lhs);
+ }
+ var valueIdentifier = match[3] || match[1];
+ var keyIdentifier = match[2];
+
+ if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
+ /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
+ throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
+ aliasAs);
+ }
+
+ var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
+ var hashFnLocals = {$id: hashKey};
+
+ if (trackByExp) {
+ trackByExpGetter = $parse(trackByExp);
+ } else {
+ trackByIdArrayFn = function(key, value) {
+ return hashKey(value);
+ };
+ trackByIdObjFn = function(key) {
+ return key;
+ };
+ }
+
+ return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
+
+ if (trackByExpGetter) {
+ trackByIdExpFn = function(key, value, index) {
+ // assign key, value, and $index to the locals so that they can be used in hash functions
+ if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
+ hashFnLocals[valueIdentifier] = value;
+ hashFnLocals.$index = index;
+ return trackByExpGetter($scope, hashFnLocals);
+ };
+ }
+
+ // Store a list of elements from previous run. This is a hash where key is the item from the
+ // iterator, and the value is objects with following properties.
+ // - scope: bound scope
+ // - element: previous element.
+ // - index: position
+ //
+ // We are using no-proto object so that we don't need to guard against inherited props via
+ // hasOwnProperty.
+ var lastBlockMap = createMap();
+
+ //watch props
+ $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
+ var index, length,
+ previousNode = $element[0], // node that cloned nodes should be inserted after
+ // initialized to the comment node anchor
+ nextNode,
+ // Same as lastBlockMap but it has the current state. It will become the
+ // lastBlockMap on the next iteration.
+ nextBlockMap = createMap(),
+ collectionLength,
+ key, value, // key/value of iteration
+ trackById,
+ trackByIdFn,
+ collectionKeys,
+ block, // last object information {scope, element, id}
+ nextBlockOrder,
+ elementsToRemove;
+
+ if (aliasAs) {
+ $scope[aliasAs] = collection;
+ }
+
+ if (isArrayLike(collection)) {
+ collectionKeys = collection;
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
+ } else {
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
+ // if object, extract keys, in enumeration order, unsorted
+ collectionKeys = [];
+ for (var itemKey in collection) {
+ if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
+ collectionKeys.push(itemKey);
+ }
+ }
+ }
+
+ collectionLength = collectionKeys.length;
+ nextBlockOrder = new Array(collectionLength);
+
+ // locate existing items
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ trackById = trackByIdFn(key, value, index);
+ if (lastBlockMap[trackById]) {
+ // found previously seen block
+ block = lastBlockMap[trackById];
+ delete lastBlockMap[trackById];
+ nextBlockMap[trackById] = block;
+ nextBlockOrder[index] = block;
+ } else if (nextBlockMap[trackById]) {
+ // if collision detected. restore lastBlockMap and throw an error
+ forEach(nextBlockOrder, function(block) {
+ if (block && block.scope) lastBlockMap[block.id] = block;
+ });
+ throw ngRepeatMinErr('dupes',
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
+ expression, trackById, value);
+ } else {
+ // new never before seen block
+ nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
+ nextBlockMap[trackById] = true;
+ }
+ }
+
+ // remove leftover items
+ for (var blockKey in lastBlockMap) {
+ block = lastBlockMap[blockKey];
+ elementsToRemove = getBlockNodes(block.clone);
+ $animate.leave(elementsToRemove);
+ if (elementsToRemove[0].parentNode) {
+ // if the element was not removed yet because of pending animation, mark it as deleted
+ // so that we can ignore it later
+ for (index = 0, length = elementsToRemove.length; index < length; index++) {
+ elementsToRemove[index][NG_REMOVED] = true;
+ }
+ }
+ block.scope.$destroy();
+ }
+
+ // we are not using forEach for perf reasons (trying to avoid #call)
+ for (index = 0; index < collectionLength; index++) {
+ key = (collection === collectionKeys) ? index : collectionKeys[index];
+ value = collection[key];
+ block = nextBlockOrder[index];
+
+ if (block.scope) {
+ // if we have already seen this object, then we need to reuse the
+ // associated scope/element
+
+ nextNode = previousNode;
+
+ // skip nodes that are already pending removal via leave animation
+ do {
+ nextNode = nextNode.nextSibling;
+ } while (nextNode && nextNode[NG_REMOVED]);
+
+ if (getBlockStart(block) != nextNode) {
+ // existing item which got moved
+ $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
+ }
+ previousNode = getBlockEnd(block);
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ } else {
+ // new item which we don't know about
+ $transclude(function ngRepeatTransclude(clone, scope) {
+ block.scope = scope;
+ // http://jsperf.com/clone-vs-createcomment
+ var endNode = ngRepeatEndComment.cloneNode(false);
+ clone[clone.length++] = endNode;
+
+ // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
+ $animate.enter(clone, null, jqLite(previousNode));
+ previousNode = endNode;
+ // Note: We only need the first/last node of the cloned nodes.
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
+ // by a directive with templateUrl when its template arrives.
+ block.clone = clone;
+ nextBlockMap[block.id] = block;
+ updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
+ });
+ }
+ }
+ lastBlockMap = nextBlockMap;
+ });
+ };
+ }
+ };
+}];
+
+var NG_HIDE_CLASS = 'ng-hide';
+var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
+/**
+ * @ngdoc directive
+ * @name ngShow
+ * @multiElement
+ *
+ * @description
+ * The `ngShow` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
+ * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is visible) -->
+ * <div ng-show="myValue"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is hidden) -->
+ * <div ng-show="myValue" class="ng-hide"></div>
+ * ```
+ *
+ * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
+ * with extra animation classes that can be added.
+ *
+ * ```css
+ * .ng-hide:not(.ng-hide-animate) {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngShow`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass except that
+ * you must also include the !important flag to override the display property
+ * so that you can perform an animation when the element is hidden during the time of the animation.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * /&#42; this is required as of 1.3x to properly
+ * apply all styling in a show/hide animation &#42;/
+ * transition: 0s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add-active,
+ * .my-element.ng-hide-remove-active {
+ * /&#42; the transition is defined in the active class &#42;/
+ * transition: 1s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
+ * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
+ *
+ * @element ANY
+ * @param {expression} ngShow If the {@link guide/expression expression} is truthy
+ * then the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-show" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-show" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-show {
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-show.ng-hide-add, .animate-show.ng-hide-remove {
+ transition: all linear 0.5s;
+ }
+
+ .animate-show.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngShowDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
+ // we're adding a temporary, animation-specific class for ng-hide since this way
+ // we can control when the element is actually displayed on screen without having
+ // to have a global/greedy CSS selector that breaks when other animations are run.
+ // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
+ $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+
+/**
+ * @ngdoc directive
+ * @name ngHide
+ * @multiElement
+ *
+ * @description
+ * The `ngHide` directive shows or hides the given HTML element based on the expression
+ * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
+ * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
+ * in AngularJS and sets the display style to none (using an !important flag).
+ * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
+ *
+ * ```html
+ * <!-- when $scope.myValue is truthy (element is hidden) -->
+ * <div ng-hide="myValue" class="ng-hide"></div>
+ *
+ * <!-- when $scope.myValue is falsy (element is visible) -->
+ * <div ng-hide="myValue"></div>
+ * ```
+ *
+ * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
+ * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
+ * from the element causing the element not to appear hidden.
+ *
+ * ## Why is !important used?
+ *
+ * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
+ * can be easily overridden by heavier selectors. For example, something as simple
+ * as changing the display style on a HTML list item would make hidden elements appear visible.
+ * This also becomes a bigger issue when dealing with CSS frameworks.
+ *
+ * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
+ * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
+ * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
+ *
+ * ### Overriding `.ng-hide`
+ *
+ * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
+ * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
+ * class in CSS:
+ *
+ * ```css
+ * .ng-hide {
+ * /&#42; this is just another form of hiding an element &#42;/
+ * display: block!important;
+ * position: absolute;
+ * top: -9999px;
+ * left: -9999px;
+ * }
+ * ```
+ *
+ * By default you don't need to override in CSS anything and the animations will work around the display style.
+ *
+ * ## A note about animations with `ngHide`
+ *
+ * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
+ * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
+ * CSS class is added and removed for you instead of your own CSS class.
+ *
+ * ```css
+ * //
+ * //a working example can be found at the bottom of this page
+ * //
+ * .my-element.ng-hide-add, .my-element.ng-hide-remove {
+ * transition: 0.5s linear all;
+ * }
+ *
+ * .my-element.ng-hide-add { ... }
+ * .my-element.ng-hide-add.ng-hide-add-active { ... }
+ * .my-element.ng-hide-remove { ... }
+ * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
+ * ```
+ *
+ * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
+ * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
+ *
+ * @animations
+ * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
+ * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
+ *
+ * @element ANY
+ * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
+ * the element is shown or hidden respectively.
+ *
+ * @example
+ <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/>
+ <div>
+ Show:
+ <div class="check-element animate-hide" ng-show="checked">
+ <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
+ </div>
+ </div>
+ <div>
+ Hide:
+ <div class="check-element animate-hide" ng-hide="checked">
+ <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
+ </div>
+ </div>
+ </file>
+ <file name="glyphicons.css">
+ @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
+ </file>
+ <file name="animations.css">
+ .animate-hide {
+ transition: all linear 0.5s;
+ line-height: 20px;
+ opacity: 1;
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+
+ .animate-hide.ng-hide {
+ line-height: 0;
+ opacity: 0;
+ padding: 0 10px;
+ }
+
+ .check-element {
+ padding: 10px;
+ border: 1px solid black;
+ background: white;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
+ var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
+
+ it('should check ng-show / ng-hide', function() {
+ expect(thumbsUp.isDisplayed()).toBeFalsy();
+ expect(thumbsDown.isDisplayed()).toBeTruthy();
+
+ element(by.model('checked')).click();
+
+ expect(thumbsUp.isDisplayed()).toBeTruthy();
+ expect(thumbsDown.isDisplayed()).toBeFalsy();
+ });
+ </file>
+ </example>
+ */
+var ngHideDirective = ['$animate', function($animate) {
+ return {
+ restrict: 'A',
+ multiElement: true,
+ link: function(scope, element, attr) {
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
+ // The comment inside of the ngShowDirective explains why we add and
+ // remove a temporary class for the show/hide animation
+ $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
+ tempClasses: NG_HIDE_IN_PROGRESS_CLASS
+ });
+ });
+ }
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name ngStyle
+ * @restrict AC
+ *
+ * @description
+ * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
+ *
+ * @element ANY
+ * @param {expression} ngStyle
+ *
+ * {@link guide/expression Expression} which evals to an
+ * object whose keys are CSS style names and values are corresponding values for those CSS
+ * keys.
+ *
+ * Since some CSS style names are not valid keys for an object, they must be quoted.
+ * See the 'background-color' style in the example below.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <input type="button" value="set color" ng-click="myStyle={color:'red'}">
+ <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
+ <input type="button" value="clear" ng-click="myStyle={}">
+ <br/>
+ <span ng-style="myStyle">Sample Text</span>
+ <pre>myStyle={{myStyle}}</pre>
+ </file>
+ <file name="style.css">
+ span {
+ color: black;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var colorSpan = element(by.css('span'));
+
+ it('should check ng-style', function() {
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ element(by.css('input[value=\'set color\']')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
+ element(by.css('input[value=clear]')).click();
+ expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
+ });
+ </file>
+ </example>
+ */
+var ngStyleDirective = ngDirective(function(scope, element, attr) {
+ scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
+ if (oldStyles && (newStyles !== oldStyles)) {
+ forEach(oldStyles, function(val, style) { element.css(style, '');});
+ }
+ if (newStyles) element.css(newStyles);
+ }, true);
+});
+
+/**
+ * @ngdoc directive
+ * @name ngSwitch
+ * @restrict EA
+ *
+ * @description
+ * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
+ * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
+ * as specified in the template.
+ *
+ * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
+ * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
+ * matches the value obtained from the evaluated expression. In other words, you define a container element
+ * (where you place the directive), place an expression on the **`on="..."` attribute**
+ * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
+ * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
+ * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
+ * attribute is displayed.
+ *
+ * <div class="alert alert-info">
+ * Be aware that the attribute values to match against cannot be expressions. They are interpreted
+ * as literal string values to match against.
+ * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
+ * value of the expression `$scope.someVal`.
+ * </div>
+
+ * @animations
+ * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
+ * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
+ *
+ * @usage
+ *
+ * ```
+ * <ANY ng-switch="expression">
+ * <ANY ng-switch-when="matchValue1">...</ANY>
+ * <ANY ng-switch-when="matchValue2">...</ANY>
+ * <ANY ng-switch-default>...</ANY>
+ * </ANY>
+ * ```
+ *
+ *
+ * @scope
+ * @priority 1200
+ * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
+ * On child elements add:
+ *
+ * * `ngSwitchWhen`: the case statement to match against. If match then this
+ * case will be displayed. If the same match appears multiple times, all the
+ * elements will be displayed.
+ * * `ngSwitchDefault`: the default case when no other case match. If there
+ * are multiple default cases, all of them will be displayed when no other
+ * case match.
+ *
+ *
+ * @example
+ <example module="switchExample" deps="angular-animate.js" animations="true">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <select ng-model="selection" ng-options="item for item in items">
+ </select>
+ <code>selection={{selection}}</code>
+ <hr/>
+ <div class="animate-switch-container"
+ ng-switch on="selection">
+ <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
+ <div class="animate-switch" ng-switch-when="home">Home Span</div>
+ <div class="animate-switch" ng-switch-default>default</div>
+ </div>
+ </div>
+ </file>
+ <file name="script.js">
+ angular.module('switchExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.items = ['settings', 'home', 'other'];
+ $scope.selection = $scope.items[0];
+ }]);
+ </file>
+ <file name="animations.css">
+ .animate-switch-container {
+ position:relative;
+ background:white;
+ border:1px solid black;
+ height:40px;
+ overflow:hidden;
+ }
+
+ .animate-switch {
+ padding:10px;
+ }
+
+ .animate-switch.ng-animate {
+ transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
+
+ position:absolute;
+ top:0;
+ left:0;
+ right:0;
+ bottom:0;
+ }
+
+ .animate-switch.ng-leave.ng-leave-active,
+ .animate-switch.ng-enter {
+ top:-50px;
+ }
+ .animate-switch.ng-leave,
+ .animate-switch.ng-enter.ng-enter-active {
+ top:0;
+ }
+ </file>
+ <file name="protractor.js" type="protractor">
+ var switchElem = element(by.css('[ng-switch]'));
+ var select = element(by.model('selection'));
+
+ it('should start in settings', function() {
+ expect(switchElem.getText()).toMatch(/Settings Div/);
+ });
+ it('should change to home', function() {
+ select.all(by.css('option')).get(1).click();
+ expect(switchElem.getText()).toMatch(/Home Span/);
+ });
+ it('should select default', function() {
+ select.all(by.css('option')).get(2).click();
+ expect(switchElem.getText()).toMatch(/default/);
+ });
+ </file>
+ </example>
+ */
+var ngSwitchDirective = ['$animate', function($animate) {
+ return {
+ require: 'ngSwitch',
+
+ // asks for $scope to fool the BC controller module
+ controller: ['$scope', function ngSwitchController() {
+ this.cases = {};
+ }],
+ link: function(scope, element, attr, ngSwitchController) {
+ var watchExpr = attr.ngSwitch || attr.on,
+ selectedTranscludes = [],
+ selectedElements = [],
+ previousLeaveAnimations = [],
+ selectedScopes = [];
+
+ var spliceFactory = function(array, index) {
+ return function() { array.splice(index, 1); };
+ };
+
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
+ var i, ii;
+ for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
+ $animate.cancel(previousLeaveAnimations[i]);
+ }
+ previousLeaveAnimations.length = 0;
+
+ for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
+ var selected = getBlockNodes(selectedElements[i].clone);
+ selectedScopes[i].$destroy();
+ var promise = previousLeaveAnimations[i] = $animate.leave(selected);
+ promise.then(spliceFactory(previousLeaveAnimations, i));
+ }
+
+ selectedElements.length = 0;
+ selectedScopes.length = 0;
+
+ if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
+ forEach(selectedTranscludes, function(selectedTransclude) {
+ selectedTransclude.transclude(function(caseElement, selectedScope) {
+ selectedScopes.push(selectedScope);
+ var anchor = selectedTransclude.element;
+ caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
+ var block = { clone: caseElement };
+
+ selectedElements.push(block);
+ $animate.enter(caseElement, anchor.parent(), anchor);
+ });
+ });
+ }
+ });
+ }
+ };
+}];
+
+var ngSwitchWhenDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attrs, ctrl, $transclude) {
+ ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
+ ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
+ }
+});
+
+var ngSwitchDefaultDirective = ngDirective({
+ transclude: 'element',
+ priority: 1200,
+ require: '^ngSwitch',
+ multiElement: true,
+ link: function(scope, element, attr, ctrl, $transclude) {
+ ctrl.cases['?'] = (ctrl.cases['?'] || []);
+ ctrl.cases['?'].push({ transclude: $transclude, element: element });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name ngTransclude
+ * @restrict EAC
+ *
+ * @description
+ * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
+ *
+ * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
+ *
+ * @element ANY
+ *
+ * @example
+ <example module="transcludeExample">
+ <file name="index.html">
+ <script>
+ angular.module('transcludeExample', [])
+ .directive('pane', function(){
+ return {
+ restrict: 'E',
+ transclude: true,
+ scope: { title:'@' },
+ template: '<div style="border: 1px solid black;">' +
+ '<div style="background-color: gray">{{title}}</div>' +
+ '<ng-transclude></ng-transclude>' +
+ '</div>'
+ };
+ })
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.title = 'Lorem Ipsum';
+ $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
+ }]);
+ </script>
+ <div ng-controller="ExampleController">
+ <input ng-model="title" aria-label="title"> <br/>
+ <textarea ng-model="text" aria-label="text"></textarea> <br/>
+ <pane title="{{title}}">{{text}}</pane>
+ </div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should have transcluded', function() {
+ var titleElement = element(by.model('title'));
+ titleElement.clear();
+ titleElement.sendKeys('TITLE');
+ var textElement = element(by.model('text'));
+ textElement.clear();
+ textElement.sendKeys('TEXT');
+ expect(element(by.binding('title')).getText()).toEqual('TITLE');
+ expect(element(by.binding('text')).getText()).toEqual('TEXT');
+ });
+ </file>
+ </example>
+ *
+ */
+var ngTranscludeDirective = ngDirective({
+ restrict: 'EAC',
+ link: function($scope, $element, $attrs, controller, $transclude) {
+ if (!$transclude) {
+ throw minErr('ngTransclude')('orphan',
+ 'Illegal use of ngTransclude directive in the template! ' +
+ 'No parent directive that requires a transclusion found. ' +
+ 'Element: {0}',
+ startingTag($element));
+ }
+
+ $transclude(function(clone) {
+ $element.empty();
+ $element.append(clone);
+ });
+ }
+});
+
+/**
+ * @ngdoc directive
+ * @name script
+ * @restrict E
+ *
+ * @description
+ * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
+ * template can be used by {@link ng.directive:ngInclude `ngInclude`},
+ * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
+ * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
+ * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
+ *
+ * @param {string} type Must be set to `'text/ng-template'`.
+ * @param {string} id Cache name of the template.
+ *
+ * @example
+ <example>
+ <file name="index.html">
+ <script type="text/ng-template" id="/tpl.html">
+ Content of the template.
+ </script>
+
+ <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
+ <div id="tpl-content" ng-include src="currentTpl"></div>
+ </file>
+ <file name="protractor.js" type="protractor">
+ it('should load template defined inside script tag', function() {
+ element(by.css('#tpl-link')).click();
+ expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
+ });
+ </file>
+ </example>
+ */
+var scriptDirective = ['$templateCache', function($templateCache) {
+ return {
+ restrict: 'E',
+ terminal: true,
+ compile: function(element, attr) {
+ if (attr.type == 'text/ng-template') {
+ var templateUrl = attr.id,
+ text = element[0].text;
+
+ $templateCache.put(templateUrl, text);
+ }
+ }
+ };
+}];
+
+var noopNgModelController = { $setViewValue: noop, $render: noop };
+
+function chromeHack(optionElement) {
+ // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
+ // Adding an <option selected="selected"> element to a <select required="required"> should
+ // automatically select the new element
+ if (optionElement[0].hasAttribute('selected')) {
+ optionElement[0].selected = true;
+ }
+}
+
+/**
+ * @ngdoc type
+ * @name select.SelectController
+ * @description
+ * The controller for the `<select>` directive. This provides support for reading
+ * and writing the selected value(s) of the control and also coordinates dynamically
+ * added `<option>` elements, perhaps by an `ngRepeat` directive.
+ */
+var SelectController =
+ ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
+
+ var self = this,
+ optionsMap = new HashMap();
+
+ // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
+ self.ngModelCtrl = noopNgModelController;
+
+ // The "unknown" option is one that is prepended to the list if the viewValue
+ // does not match any of the options. When it is rendered the value of the unknown
+ // option is '? XXX ?' where XXX is the hashKey of the value that is not known.
+ //
+ // We can't just jqLite('<option>') since jqLite is not smart enough
+ // to create it in <select> and IE barfs otherwise.
+ self.unknownOption = jqLite(document.createElement('option'));
+ self.renderUnknownOption = function(val) {
+ var unknownVal = '? ' + hashKey(val) + ' ?';
+ self.unknownOption.val(unknownVal);
+ $element.prepend(self.unknownOption);
+ $element.val(unknownVal);
+ };
+
+ $scope.$on('$destroy', function() {
+ // disable unknown option so that we don't do work when the whole select is being destroyed
+ self.renderUnknownOption = noop;
+ });
+
+ self.removeUnknownOption = function() {
+ if (self.unknownOption.parent()) self.unknownOption.remove();
+ };
+
+
+ // Read the value of the select control, the implementation of this changes depending
+ // upon whether the select can have multiple values and whether ngOptions is at work.
+ self.readValue = function readSingleValue() {
+ self.removeUnknownOption();
+ return $element.val();
+ };
+
+
+ // Write the value to the select control, the implementation of this changes depending
+ // upon whether the select can have multiple values and whether ngOptions is at work.
+ self.writeValue = function writeSingleValue(value) {
+ if (self.hasOption(value)) {
+ self.removeUnknownOption();
+ $element.val(value);
+ if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy
+ } else {
+ if (value == null && self.emptyOption) {
+ self.removeUnknownOption();
+ $element.val('');
+ } else {
+ self.renderUnknownOption(value);
+ }
+ }
+ };
+
+
+ // Tell the select control that an option, with the given value, has been added
+ self.addOption = function(value, element) {
+ assertNotHasOwnProperty(value, '"option value"');
+ if (value === '') {
+ self.emptyOption = element;
+ }
+ var count = optionsMap.get(value) || 0;
+ optionsMap.put(value, count + 1);
+ self.ngModelCtrl.$render();
+ chromeHack(element);
+ };
+
+ // Tell the select control that an option, with the given value, has been removed
+ self.removeOption = function(value) {
+ var count = optionsMap.get(value);
+ if (count) {
+ if (count === 1) {
+ optionsMap.remove(value);
+ if (value === '') {
+ self.emptyOption = undefined;
+ }
+ } else {
+ optionsMap.put(value, count - 1);
+ }
+ }
+ };
+
+ // Check whether the select control has an option matching the given value
+ self.hasOption = function(value) {
+ return !!optionsMap.get(value);
+ };
+
+
+ self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
+
+ if (interpolateValueFn) {
+ // The value attribute is interpolated
+ var oldVal;
+ optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {
+ if (isDefined(oldVal)) {
+ self.removeOption(oldVal);
+ }
+ oldVal = newVal;
+ self.addOption(newVal, optionElement);
+ });
+ } else if (interpolateTextFn) {
+ // The text content is interpolated
+ optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {
+ optionAttrs.$set('value', newVal);
+ if (oldVal !== newVal) {
+ self.removeOption(oldVal);
+ }
+ self.addOption(newVal, optionElement);
+ });
+ } else {
+ // The value attribute is static
+ self.addOption(optionAttrs.value, optionElement);
+ }
+
+ optionElement.on('$destroy', function() {
+ self.removeOption(optionAttrs.value);
+ self.ngModelCtrl.$render();
+ });
+ };
+}];
+
+/**
+ * @ngdoc directive
+ * @name select
+ * @restrict E
+ *
+ * @description
+ * HTML `SELECT` element with angular data-binding.
+ *
+ * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
+ * between the scope and the `<select>` control (including setting default values).
+ * ÃŒt also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
+ * {@link ngOptions `ngOptions`} directives.
+ *
+ * When an item in the `<select>` menu is selected, the value of the selected option will be bound
+ * to the model identified by the `ngModel` directive. With static or repeated options, this is
+ * the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
+ * If you want dynamic value attributes, you can use interpolation inside the value attribute.
+ *
+ * <div class="alert alert-warning">
+ * Note that the value of a `select` directive used without `ngOptions` is always a string.
+ * When the model needs to be bound to a non-string value, you must either explictly convert it
+ * using a directive (see example below) or use `ngOptions` to specify the set of options.
+ * This is because an option element can only be bound to string values at present.
+ * </div>
+ *
+ * If the viewValue of `ngModel` does not match any of the options, then the control
+ * will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
+ *
+ * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
+ * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
+ * option. See example below for demonstration.
+ *
+ * <div class="alert alert-info">
+ * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
+ * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
+ * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
+ * comprehension expression, and additionally in reducing memory and increasing speed by not creating
+ * a new scope for each repeated instance.
+ * </div>
+ *
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} multiple Allows multiple options to be selected. The selected values will be
+ * bound to the model as an array.
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds required attribute and required validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
+ * when you want to data-bind to the required attribute.
+ * @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
+ * interaction with the select element.
+ * @param {string=} ngOptions sets the options that the select is populated with and defines what is
+ * set on the model on selection. See {@link ngOptions `ngOptions`}.
+ *
+ * @example
+ * ### Simple `select` elements with static options
+ *
+ * <example name="static-select" module="staticSelect">
+ * <file name="index.html">
+ * <div ng-controller="ExampleController">
+ * <form name="myForm">
+ * <label for="singleSelect"> Single select: </label><br>
+ * <select name="singleSelect" ng-model="data.singleSelect">
+ * <option value="option-1">Option 1</option>
+ * <option value="option-2">Option 2</option>
+ * </select><br>
+ *
+ * <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
+ * <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
+ * <option value="">---Please select---</option> <!-- not selected / blank option -->
+ * <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
+ * <option value="option-2">Option 2</option>
+ * </select><br>
+ * <button ng-click="forceUnknownOption()">Force unknown option</button><br>
+ * <tt>singleSelect = {{data.singleSelect}}</tt>
+ *
+ * <hr>
+ * <label for="multipleSelect"> Multiple select: </label><br>
+ * <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
+ * <option value="option-1">Option 1</option>
+ * <option value="option-2">Option 2</option>
+ * <option value="option-3">Option 3</option>
+ * </select><br>
+ * <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
+ * </form>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('staticSelect', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.data = {
+ * singleSelect: null,
+ * multipleSelect: [],
+ * option1: 'option-1',
+ * };
+ *
+ * $scope.forceUnknownOption = function() {
+ * $scope.data.singleSelect = 'nonsense';
+ * };
+ * }]);
+ * </file>
+ *</example>
+ *
+ * ### Using `ngRepeat` to generate `select` options
+ * <example name="ngrepeat-select" module="ngrepeatSelect">
+ * <file name="index.html">
+ * <div ng-controller="ExampleController">
+ * <form name="myForm">
+ * <label for="repeatSelect"> Repeat select: </label>
+ * <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
+ * <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
+ * </select>
+ * </form>
+ * <hr>
+ * <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('ngrepeatSelect', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.data = {
+ * repeatSelect: null,
+ * availableOptions: [
+ * {id: '1', name: 'Option A'},
+ * {id: '2', name: 'Option B'},
+ * {id: '3', name: 'Option C'}
+ * ],
+ * };
+ * }]);
+ * </file>
+ *</example>
+ *
+ *
+ * ### Using `select` with `ngOptions` and setting a default value
+ * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
+ *
+ * <example name="select-with-default-values" module="defaultValueSelect">
+ * <file name="index.html">
+ * <div ng-controller="ExampleController">
+ * <form name="myForm">
+ * <label for="mySelect">Make a choice:</label>
+ * <select name="mySelect" id="mySelect"
+ * ng-options="option.name for option in data.availableOptions track by option.id"
+ * ng-model="data.selectedOption"></select>
+ * </form>
+ * <hr>
+ * <tt>option = {{data.selectedOption}}</tt><br/>
+ * </div>
+ * </file>
+ * <file name="app.js">
+ * angular.module('defaultValueSelect', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.data = {
+ * availableOptions: [
+ * {id: '1', name: 'Option A'},
+ * {id: '2', name: 'Option B'},
+ * {id: '3', name: 'Option C'}
+ * ],
+ * selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
+ * };
+ * }]);
+ * </file>
+ *</example>
+ *
+ *
+ * ### Binding `select` to a non-string value via `ngModel` parsing / formatting
+ *
+ * <example name="select-with-non-string-options" module="nonStringSelect">
+ * <file name="index.html">
+ * <select ng-model="model.id" convert-to-number>
+ * <option value="0">Zero</option>
+ * <option value="1">One</option>
+ * <option value="2">Two</option>
+ * </select>
+ * {{ model }}
+ * </file>
+ * <file name="app.js">
+ * angular.module('nonStringSelect', [])
+ * .run(function($rootScope) {
+ * $rootScope.model = { id: 2 };
+ * })
+ * .directive('convertToNumber', function() {
+ * return {
+ * require: 'ngModel',
+ * link: function(scope, element, attrs, ngModel) {
+ * ngModel.$parsers.push(function(val) {
+ * return parseInt(val, 10);
+ * });
+ * ngModel.$formatters.push(function(val) {
+ * return '' + val;
+ * });
+ * }
+ * };
+ * });
+ * </file>
+ * <file name="protractor.js" type="protractor">
+ * it('should initialize to model', function() {
+ * var select = element(by.css('select'));
+ * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');
+ * });
+ * </file>
+ * </example>
+ *
+ */
+var selectDirective = function() {
+
+ return {
+ restrict: 'E',
+ require: ['select', '?ngModel'],
+ controller: SelectController,
+ priority: 1,
+ link: {
+ pre: selectPreLink
+ }
+ };
+
+ function selectPreLink(scope, element, attr, ctrls) {
+
+ // if ngModel is not defined, we don't need to do anything
+ var ngModelCtrl = ctrls[1];
+ if (!ngModelCtrl) return;
+
+ var selectCtrl = ctrls[0];
+
+ selectCtrl.ngModelCtrl = ngModelCtrl;
+
+ // We delegate rendering to the `writeValue` method, which can be changed
+ // if the select can have multiple selected values or if the options are being
+ // generated by `ngOptions`
+ ngModelCtrl.$render = function() {
+ selectCtrl.writeValue(ngModelCtrl.$viewValue);
+ };
+
+ // When the selected item(s) changes we delegate getting the value of the select control
+ // to the `readValue` method, which can be changed if the select can have multiple
+ // selected values or if the options are being generated by `ngOptions`
+ element.on('change', function() {
+ scope.$apply(function() {
+ ngModelCtrl.$setViewValue(selectCtrl.readValue());
+ });
+ });
+
+ // If the select allows multiple values then we need to modify how we read and write
+ // values from and to the control; also what it means for the value to be empty and
+ // we have to add an extra watch since ngModel doesn't work well with arrays - it
+ // doesn't trigger rendering if only an item in the array changes.
+ if (attr.multiple) {
+
+ // Read value now needs to check each option to see if it is selected
+ selectCtrl.readValue = function readMultipleValue() {
+ var array = [];
+ forEach(element.find('option'), function(option) {
+ if (option.selected) {
+ array.push(option.value);
+ }
+ });
+ return array;
+ };
+
+ // Write value now needs to set the selected property of each matching option
+ selectCtrl.writeValue = function writeMultipleValue(value) {
+ var items = new HashMap(value);
+ forEach(element.find('option'), function(option) {
+ option.selected = isDefined(items.get(option.value));
+ });
+ };
+
+ // we have to do it on each watch since ngModel watches reference, but
+ // we need to work of an array, so we need to see if anything was inserted/removed
+ var lastView, lastViewRef = NaN;
+ scope.$watch(function selectMultipleWatch() {
+ if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {
+ lastView = shallowCopy(ngModelCtrl.$viewValue);
+ ngModelCtrl.$render();
+ }
+ lastViewRef = ngModelCtrl.$viewValue;
+ });
+
+ // If we are a multiple select then value is now a collection
+ // so the meaning of $isEmpty changes
+ ngModelCtrl.$isEmpty = function(value) {
+ return !value || value.length === 0;
+ };
+
+ }
+ }
+};
+
+
+// The option directive is purely designed to communicate the existence (or lack of)
+// of dynamically created (and destroyed) option elements to their containing select
+// directive via its controller.
+var optionDirective = ['$interpolate', function($interpolate) {
+ return {
+ restrict: 'E',
+ priority: 100,
+ compile: function(element, attr) {
+
+ if (isDefined(attr.value)) {
+ // If the value attribute is defined, check if it contains an interpolation
+ var interpolateValueFn = $interpolate(attr.value, true);
+ } else {
+ // If the value attribute is not defined then we fall back to the
+ // text content of the option element, which may be interpolated
+ var interpolateTextFn = $interpolate(element.text(), true);
+ if (!interpolateTextFn) {
+ attr.$set('value', element.text());
+ }
+ }
+
+ return function(scope, element, attr) {
+
+ // This is an optimization over using ^^ since we don't want to have to search
+ // all the way to the root of the DOM for every single option element
+ var selectCtrlName = '$selectController',
+ parent = element.parent(),
+ selectCtrl = parent.data(selectCtrlName) ||
+ parent.parent().data(selectCtrlName); // in case we are in optgroup
+
+ if (selectCtrl) {
+ selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);
+ }
+ };
+ }
+ };
+}];
+
+var styleDirective = valueFn({
+ restrict: 'E',
+ terminal: false
+});
+
+var requiredDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+ attr.required = true; // force truthy in case we are on non input element
+
+ ctrl.$validators.required = function(modelValue, viewValue) {
+ return !attr.required || !ctrl.$isEmpty(viewValue);
+ };
+
+ attr.$observe('required', function() {
+ ctrl.$validate();
+ });
+ }
+ };
+};
+
+
+var patternDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var regexp, patternExp = attr.ngPattern || attr.pattern;
+ attr.$observe('pattern', function(regex) {
+ if (isString(regex) && regex.length > 0) {
+ regex = new RegExp('^' + regex + '$');
+ }
+
+ if (regex && !regex.test) {
+ throw minErr('ngPattern')('noregexp',
+ 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
+ regex, startingTag(elm));
+ }
+
+ regexp = regex || undefined;
+ ctrl.$validate();
+ });
+
+ ctrl.$validators.pattern = function(modelValue, viewValue) {
+ // HTML5 pattern constraint validates the input value, so we validate the viewValue
+ return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
+ };
+ }
+ };
+};
+
+
+var maxlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var maxlength = -1;
+ attr.$observe('maxlength', function(value) {
+ var intVal = toInt(value);
+ maxlength = isNaN(intVal) ? -1 : intVal;
+ ctrl.$validate();
+ });
+ ctrl.$validators.maxlength = function(modelValue, viewValue) {
+ return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
+ };
+ }
+ };
+};
+
+var minlengthDirective = function() {
+ return {
+ restrict: 'A',
+ require: '?ngModel',
+ link: function(scope, elm, attr, ctrl) {
+ if (!ctrl) return;
+
+ var minlength = 0;
+ attr.$observe('minlength', function(value) {
+ minlength = toInt(value) || 0;
+ ctrl.$validate();
+ });
+ ctrl.$validators.minlength = function(modelValue, viewValue) {
+ return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
+ };
+ }
+ };
+};
+
+if (window.angular.bootstrap) {
+ //AngularJS is already loaded, so we can return here...
+ console.log('WARNING: Tried to load angular more than once.');
+ return;
+}
+
+//try to bind to jquery now so that one can write jqLite(document).ready()
+//but we will rebind on bootstrap again.
+bindJQuery();
+
+publishExternalAPI(angular);
+
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-us",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
+
+ jqLite(document).ready(function() {
+ angularInit(document, bootstrap);
+ });
+
+})(window, document);
+
+!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js
new file mode 100644
index 00000000..b4f9b07e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js
@@ -0,0 +1,295 @@
+/*
+ AngularJS v1.4.8
+ (c) 2010-2015 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(S,X,u){'use strict';function G(a){return function(){var b=arguments[0],d;d="["+(a?a+":":"")+b+"] http://errors.angularjs.org/1.4.8/"+(a?a+"/":"")+b;for(b=1;b<arguments.length;b++){d=d+(1==b?"?":"&")+"p"+(b-1)+"=";var c=encodeURIComponent,e;e=arguments[b];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;d+=c(e)}return Error(d)}}function za(a){if(null==a||Xa(a))return!1;if(I(a)||E(a)||B&&a instanceof B)return!0;
+var b="length"in Object(a)&&a.length;return Q(b)&&(0<=b&&b-1 in a||"function"==typeof a.item)}function n(a,b,d){var c,e;if(a)if(z(a))for(c in a)"prototype"==c||"length"==c||"name"==c||a.hasOwnProperty&&!a.hasOwnProperty(c)||b.call(d,a[c],c,a);else if(I(a)||za(a)){var f="object"!==typeof a;c=0;for(e=a.length;c<e;c++)(f||c in a)&&b.call(d,a[c],c,a)}else if(a.forEach&&a.forEach!==n)a.forEach(b,d,a);else if(nc(a))for(c in a)b.call(d,a[c],c,a);else if("function"===typeof a.hasOwnProperty)for(c in a)a.hasOwnProperty(c)&&
+b.call(d,a[c],c,a);else for(c in a)qa.call(a,c)&&b.call(d,a[c],c,a);return a}function oc(a,b,d){for(var c=Object.keys(a).sort(),e=0;e<c.length;e++)b.call(d,a[c[e]],c[e]);return c}function pc(a){return function(b,d){a(d,b)}}function Td(){return++nb}function Mb(a,b,d){for(var c=a.$$hashKey,e=0,f=b.length;e<f;++e){var g=b[e];if(H(g)||z(g))for(var h=Object.keys(g),k=0,l=h.length;k<l;k++){var m=h[k],r=g[m];d&&H(r)?da(r)?a[m]=new Date(r.valueOf()):Ma(r)?a[m]=new RegExp(r):r.nodeName?a[m]=r.cloneNode(!0):
+Nb(r)?a[m]=r.clone():(H(a[m])||(a[m]=I(r)?[]:{}),Mb(a[m],[r],!0)):a[m]=r}}c?a.$$hashKey=c:delete a.$$hashKey;return a}function M(a){return Mb(a,ra.call(arguments,1),!1)}function Ud(a){return Mb(a,ra.call(arguments,1),!0)}function ea(a){return parseInt(a,10)}function Ob(a,b){return M(Object.create(a),b)}function x(){}function Ya(a){return a}function na(a){return function(){return a}}function qc(a){return z(a.toString)&&a.toString!==sa}function q(a){return"undefined"===typeof a}function y(a){return"undefined"!==
+typeof a}function H(a){return null!==a&&"object"===typeof a}function nc(a){return null!==a&&"object"===typeof a&&!rc(a)}function E(a){return"string"===typeof a}function Q(a){return"number"===typeof a}function da(a){return"[object Date]"===sa.call(a)}function z(a){return"function"===typeof a}function Ma(a){return"[object RegExp]"===sa.call(a)}function Xa(a){return a&&a.window===a}function Za(a){return a&&a.$evalAsync&&a.$watch}function $a(a){return"boolean"===typeof a}function sc(a){return a&&Q(a.length)&&
+Vd.test(sa.call(a))}function Nb(a){return!(!a||!(a.nodeName||a.prop&&a.attr&&a.find))}function Wd(a){var b={};a=a.split(",");var d;for(d=0;d<a.length;d++)b[a[d]]=!0;return b}function ta(a){return F(a.nodeName||a[0]&&a[0].nodeName)}function ab(a,b){var d=a.indexOf(b);0<=d&&a.splice(d,1);return d}function bb(a,b){function d(a,b){var d=b.$$hashKey,e;if(I(a)){e=0;for(var f=a.length;e<f;e++)b.push(c(a[e]))}else if(nc(a))for(e in a)b[e]=c(a[e]);else if(a&&"function"===typeof a.hasOwnProperty)for(e in a)a.hasOwnProperty(e)&&
+(b[e]=c(a[e]));else for(e in a)qa.call(a,e)&&(b[e]=c(a[e]));d?b.$$hashKey=d:delete b.$$hashKey;return b}function c(a){if(!H(a))return a;var b=e.indexOf(a);if(-1!==b)return f[b];if(Xa(a)||Za(a))throw Aa("cpws");var b=!1,c;I(a)?(c=[],b=!0):sc(a)?c=new a.constructor(a):da(a)?c=new Date(a.getTime()):Ma(a)?(c=new RegExp(a.source,a.toString().match(/[^\/]*$/)[0]),c.lastIndex=a.lastIndex):z(a.cloneNode)?c=a.cloneNode(!0):(c=Object.create(rc(a)),b=!0);e.push(a);f.push(c);return b?d(a,c):c}var e=[],f=[];if(b){if(sc(b))throw Aa("cpta");
+if(a===b)throw Aa("cpi");I(b)?b.length=0:n(b,function(a,c){"$$hashKey"!==c&&delete b[c]});e.push(a);f.push(b);return d(a,b)}return c(a)}function ia(a,b){if(I(a)){b=b||[];for(var d=0,c=a.length;d<c;d++)b[d]=a[d]}else if(H(a))for(d in b=b||{},a)if("$"!==d.charAt(0)||"$"!==d.charAt(1))b[d]=a[d];return b||a}function ma(a,b){if(a===b)return!0;if(null===a||null===b)return!1;if(a!==a&&b!==b)return!0;var d=typeof a,c;if(d==typeof b&&"object"==d)if(I(a)){if(!I(b))return!1;if((d=a.length)==b.length){for(c=
+0;c<d;c++)if(!ma(a[c],b[c]))return!1;return!0}}else{if(da(a))return da(b)?ma(a.getTime(),b.getTime()):!1;if(Ma(a))return Ma(b)?a.toString()==b.toString():!1;if(Za(a)||Za(b)||Xa(a)||Xa(b)||I(b)||da(b)||Ma(b))return!1;d=$();for(c in a)if("$"!==c.charAt(0)&&!z(a[c])){if(!ma(a[c],b[c]))return!1;d[c]=!0}for(c in b)if(!(c in d)&&"$"!==c.charAt(0)&&y(b[c])&&!z(b[c]))return!1;return!0}return!1}function cb(a,b,d){return a.concat(ra.call(b,d))}function tc(a,b){var d=2<arguments.length?ra.call(arguments,2):
+[];return!z(b)||b instanceof RegExp?b:d.length?function(){return arguments.length?b.apply(a,cb(d,arguments,0)):b.apply(a,d)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}}function Xd(a,b){var d=b;"string"===typeof a&&"$"===a.charAt(0)&&"$"===a.charAt(1)?d=u:Xa(b)?d="$WINDOW":b&&X===b?d="$DOCUMENT":Za(b)&&(d="$SCOPE");return d}function db(a,b){if("undefined"===typeof a)return u;Q(b)||(b=b?2:null);return JSON.stringify(a,Xd,b)}function uc(a){return E(a)?JSON.parse(a):a}function vc(a,
+b){var d=Date.parse("Jan 01, 1970 00:00:00 "+a)/6E4;return isNaN(d)?b:d}function Pb(a,b,d){d=d?-1:1;var c=vc(b,a.getTimezoneOffset());b=a;a=d*(c-a.getTimezoneOffset());b=new Date(b.getTime());b.setMinutes(b.getMinutes()+a);return b}function ua(a){a=B(a).clone();try{a.empty()}catch(b){}var d=B("<div>").append(a).html();try{return a[0].nodeType===Na?F(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+F(b)})}catch(c){return F(d)}}function wc(a){try{return decodeURIComponent(a)}catch(b){}}
+function xc(a){var b={};n((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=wc(e),y(e)&&(f=y(f)?wc(f):!0,qa.call(b,e)?I(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Qb(a){var b=[];n(a,function(a,c){I(a)?n(a,function(a){b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))}):b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))});return b.length?b.join("&"):""}function ob(a){return ja(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,
+"=").replace(/%2B/gi,"+")}function ja(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function Yd(a,b){var d,c,e=Oa.length;for(c=0;c<e;++c)if(d=Oa[c]+b,E(d=a.getAttribute(d)))return d;return null}function Zd(a,b){var d,c,e={};n(Oa,function(b){b+="app";!d&&a.hasAttribute&&a.hasAttribute(b)&&(d=a,c=a.getAttribute(b))});n(Oa,function(b){b+="app";var e;!d&&(e=a.querySelector("["+b.replace(":",
+"\\:")+"]"))&&(d=e,c=e.getAttribute(b))});d&&(e.strictDi=null!==Yd(d,"strict-di"),b(d,c?[c]:[],e))}function yc(a,b,d){H(d)||(d={});d=M({strictDi:!1},d);var c=function(){a=B(a);if(a.injector()){var c=a[0]===X?"document":ua(a);throw Aa("btstrpd",c.replace(/</,"&lt;").replace(/>/,"&gt;"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=eb(b,d.strictDi);c.invoke(["$rootScope",
+"$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;S&&e.test(S.name)&&(d.debugInfoEnabled=!0,S.name=S.name.replace(e,""));if(S&&!f.test(S.name))return c();S.name=S.name.replace(f,"");fa.resumeBootstrap=function(a){n(a,function(a){b.push(a)});return c()};z(fa.resumeDeferredBootstrap)&&fa.resumeDeferredBootstrap()}function $d(){S.name="NG_ENABLE_DEBUG_INFO!"+S.name;S.location.reload()}
+function ae(a){a=fa.element(a).injector();if(!a)throw Aa("test");return a.get("$$testability")}function zc(a,b){b=b||"_";return a.replace(be,function(a,c){return(c?b:"")+a.toLowerCase()})}function ce(){var a;if(!Ac){var b=pb();(oa=q(b)?S.jQuery:b?S[b]:u)&&oa.fn.on?(B=oa,M(oa.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),a=oa.cleanData,oa.cleanData=function(b){var c;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=b[e]);e++)(c=
+oa._data(f,"events"))&&c.$destroy&&oa(f).triggerHandler("$destroy");a(b)}):B=N;fa.element=B;Ac=!0}}function qb(a,b,d){if(!a)throw Aa("areq",b||"?",d||"required");return a}function Qa(a,b,d){d&&I(a)&&(a=a[a.length-1]);qb(z(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ra(a,b){if("hasOwnProperty"===a)throw Aa("badname",b);}function Bc(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g<f;g++)c=b[g],a&&(a=(e=a)[c]);return!d&&
+z(a)?tc(e,a):a}function rb(a){for(var b=a[0],d=a[a.length-1],c,e=1;b!==d&&(b=b.nextSibling);e++)if(c||a[e]!==b)c||(c=B(ra.call(a,0,e))),c.push(b);return c||a}function $(){return Object.create(null)}function de(a){function b(a,b,c){return a[b]||(a[b]=c())}var d=G("$injector"),c=G("ng");a=b(a,"angular",Object);a.$$minErr=a.$$minErr||G;return b(a,"module",function(){var a={};return function(f,g,h){if("hasOwnProperty"===f)throw c("badname","module");g&&a.hasOwnProperty(f)&&(a[f]=null);return b(a,f,function(){function a(b,
+d,e,f){f||(f=c);return function(){f[e||"push"]([b,d,arguments]);return v}}function b(a,d){return function(b,e){e&&z(e)&&(e.$$moduleName=f);c.push([a,d,arguments]);return v}}if(!g)throw d("nomod",f);var c=[],e=[],t=[],A=a("$injector","invoke","push",e),v={_invokeQueue:c,_configBlocks:e,_runBlocks:t,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide",
+"decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider","register"),directive:b("$compileProvider","directive"),config:A,run:function(a){t.push(a);return this}};h&&A(h);return v})}})}function ee(a){M(a,{bootstrap:yc,copy:bb,extend:M,merge:Ud,equals:ma,element:B,forEach:n,injector:eb,noop:x,bind:tc,toJson:db,fromJson:uc,identity:Ya,isUndefined:q,isDefined:y,isString:E,isFunction:z,isObject:H,isNumber:Q,isElement:Nb,isArray:I,
+version:fe,isDate:da,lowercase:F,uppercase:sb,callbacks:{counter:0},getTestability:ae,$$minErr:G,$$csp:Ba,reloadWithDebugInfo:$d});Sb=de(S);Sb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:ge});a.provider("$compile",Cc).directive({a:he,input:Dc,textarea:Dc,form:ie,script:je,select:ke,style:le,option:me,ngBind:ne,ngBindHtml:oe,ngBindTemplate:pe,ngClass:qe,ngClassEven:re,ngClassOdd:se,ngCloak:te,ngController:ue,ngForm:ve,ngHide:we,ngIf:xe,ngInclude:ye,ngInit:ze,ngNonBindable:Ae,
+ngPluralize:Be,ngRepeat:Ce,ngShow:De,ngStyle:Ee,ngSwitch:Fe,ngSwitchWhen:Ge,ngSwitchDefault:He,ngOptions:Ie,ngTransclude:Je,ngModel:Ke,ngList:Le,ngChange:Me,pattern:Ec,ngPattern:Ec,required:Fc,ngRequired:Fc,minlength:Gc,ngMinlength:Gc,maxlength:Hc,ngMaxlength:Hc,ngValue:Ne,ngModelOptions:Oe}).directive({ngInclude:Pe}).directive(tb).directive(Ic);a.provider({$anchorScroll:Qe,$animate:Re,$animateCss:Se,$$animateQueue:Te,$$AnimateRunner:Ue,$browser:Ve,$cacheFactory:We,$controller:Xe,$document:Ye,$exceptionHandler:Ze,
+$filter:Jc,$$forceReflow:$e,$interpolate:af,$interval:bf,$http:cf,$httpParamSerializer:df,$httpParamSerializerJQLike:ef,$httpBackend:ff,$xhrFactory:gf,$location:hf,$log:jf,$parse:kf,$rootScope:lf,$q:mf,$$q:nf,$sce:of,$sceDelegate:pf,$sniffer:qf,$templateCache:rf,$templateRequest:sf,$$testability:tf,$timeout:uf,$window:vf,$$rAF:wf,$$jqLite:xf,$$HashMap:yf,$$cookieReader:zf})}])}function fb(a){return a.replace(Af,function(a,d,c,e){return e?c.toUpperCase():c}).replace(Bf,"Moz$1")}function Kc(a){a=a.nodeType;
+return 1===a||!a||9===a}function Lc(a,b){var d,c,e=b.createDocumentFragment(),f=[];if(Tb.test(a)){d=d||e.appendChild(b.createElement("div"));c=(Cf.exec(a)||["",""])[1].toLowerCase();c=ka[c]||ka._default;d.innerHTML=c[1]+a.replace(Df,"<$1></$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=cb(f,d.childNodes);d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";n(f,function(a){e.appendChild(a)});return e}function N(a){if(a instanceof N)return a;var b;E(a)&&(a=U(a),
+b=!0);if(!(this instanceof N)){if(b&&"<"!=a.charAt(0))throw Ub("nosel");return new N(a)}if(b){b=X;var d;a=(d=Ef.exec(a))?[b.createElement(d[1])]:(d=Lc(a,b))?d.childNodes:[]}Mc(this,a)}function Vb(a){return a.cloneNode(!0)}function ub(a,b){b||vb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;c<e;c++)vb(d[c])}function Nc(a,b,d,c){if(y(c))throw Ub("offargs");var e=(c=wb(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];y(d)&&ab(c||[],d);y(d)&&c&&0<c.length||
+(a.removeEventListener(b,f,!1),delete e[b])};n(b.split(" "),function(a){g(a);xb[a]&&g(xb[a])})}else for(b in e)"$destroy"!==b&&a.removeEventListener(b,f,!1),delete e[b]}function vb(a,b){var d=a.ng339,c=d&&gb[d];c&&(b?delete c.data[b]:(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),Nc(a)),delete gb[d],a.ng339=u))}function wb(a,b){var d=a.ng339,d=d&&gb[d];b&&!d&&(a.ng339=d=++Ff,d=gb[d]={events:{},data:{},handle:u});return d}function Wb(a,b,d){if(Kc(a)){var c=y(d),e=!c&&b&&!H(b),f=!b;a=(a=wb(a,
+!e))&&a.data;if(c)a[b]=d;else{if(f)return a;if(e)return a&&a[b];M(a,b)}}}function yb(a,b){return a.getAttribute?-1<(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+b+" "):!1}function zb(a,b){b&&a.setAttribute&&n(b.split(" "),function(b){a.setAttribute("class",U((" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+U(b)+" "," ")))})}function Ab(a,b){if(b&&a.setAttribute){var d=(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");n(b.split(" "),
+function(a){a=U(a);-1===d.indexOf(" "+a+" ")&&(d+=a+" ")});a.setAttribute("class",U(d))}}function Mc(a,b){if(b)if(b.nodeType)a[a.length++]=b;else{var d=b.length;if("number"===typeof d&&b.window!==b){if(d)for(var c=0;c<d;c++)a[a.length++]=b[c]}else a[a.length++]=b}}function Oc(a,b){return Bb(a,"$"+(b||"ngController")+"Controller")}function Bb(a,b,d){9==a.nodeType&&(a=a.documentElement);for(b=I(b)?b:[b];a;){for(var c=0,e=b.length;c<e;c++)if(y(d=B.data(a,b[c])))return d;a=a.parentNode||11===a.nodeType&&
+a.host}}function Pc(a){for(ub(a,!0);a.firstChild;)a.removeChild(a.firstChild)}function Xb(a,b){b||ub(a);var d=a.parentNode;d&&d.removeChild(a)}function Gf(a,b){b=b||S;if("complete"===b.document.readyState)b.setTimeout(a);else B(b).on("load",a)}function Qc(a,b){var d=Cb[b.toLowerCase()];return d&&Rc[ta(a)]&&d}function Hf(a,b){var d=function(c,d){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=b[d||c.type],g=f?f.length:0;if(g){if(q(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;
+c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};var k=f.specialHandlerWrapper||If;1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||k(a,c,f[l])}};d.elem=a;return d}function If(a,b,d){d.call(a,b)}function Jf(a,b,d){var c=b.relatedTarget;c&&(c===a||Kf.call(a,c))||d.call(a,b)}function xf(){this.$get=function(){return M(N,
+{hasClass:function(a,b){a.attr&&(a=a[0]);return yb(a,b)},addClass:function(a,b){a.attr&&(a=a[0]);return Ab(a,b)},removeClass:function(a,b){a.attr&&(a=a[0]);return zb(a,b)}})}}function Ca(a,b){var d=a&&a.$$hashKey;if(d)return"function"===typeof d&&(d=a.$$hashKey()),d;d=typeof a;return d="function"==d||"object"==d&&null!==a?a.$$hashKey=d+":"+(b||Td)():d+":"+a}function Sa(a,b){if(b){var d=0;this.nextUid=function(){return++d}}n(a,this.put,this)}function Lf(a){return(a=a.toString().replace(Sc,"").match(Tc))?
+"function("+(a[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function eb(a,b){function d(a){return function(b,c){if(H(b))n(b,pc(a));else return a(b,c)}}function c(a,b){Ra(a,"service");if(z(b)||I(b))b=t.instantiate(b);if(!b.$get)throw Da("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=v.invoke(b,this);if(q(c))throw Da("undef",a);return c}}function f(a,b,d){return c(a,{$get:!1!==d?e(a,b):b})}function g(a){qb(q(a)||I(a),"modulesToLoad","not an array");var b=[],c;n(a,function(a){function d(a){var b,
+c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=t.get(e[0]);f[e[1]].apply(f,e[2])}}if(!m.get(a)){m.put(a,!0);try{E(a)?(c=Sb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(t.invoke(a)):I(a)?b.push(t.invoke(a)):Qa(a,"module")}catch(e){throw I(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Da("modulerr",a,e.stack||e.message||e);}}});return b}function h(a,c){function d(b,e){if(a.hasOwnProperty(b)){if(a[b]===
+k)throw Da("cdep",b+" <- "+l.join(" <- "));return a[b]}try{return l.unshift(b),a[b]=k,a[b]=c(b,e)}catch(f){throw a[b]===k&&delete a[b],f;}finally{l.shift()}}function e(a,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=eb.$$annotate(a,b,g),l,m,t;m=0;for(l=k.length;m<l;m++){t=k[m];if("string"!==typeof t)throw Da("itkn",t);h.push(f&&f.hasOwnProperty(t)?f[t]:d(t,g))}I(a)&&(a=a[l]);return a.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((I(a)?a[a.length-1]:a).prototype||
+null);a=e(a,d,b,c);return H(a)||z(a)?a:d},get:d,annotate:eb.$$annotate,has:function(b){return r.hasOwnProperty(b+"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var k={},l=[],m=new Sa([],!0),r={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,na(b),!1)}),constant:d(function(a,b){Ra(a,"constant");r[a]=b;A[a]=b}),decorator:function(a,b){var c=t.get(a+"Provider"),d=c.$get;c.$get=function(){var a=
+v.invoke(d,c);return v.invoke(b,null,{$delegate:a})}}}},t=r.$injector=h(r,function(a,b){fa.isString(b)&&l.push(b);throw Da("unpr",l.join(" <- "));}),A={},v=A.$injector=h(A,function(a,b){var c=t.get(a+"Provider",b);return v.invoke(c.$get,c,u,a)});n(g(a),function(a){a&&v.invoke(a)});return v}function Qe(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window","$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ta(a))return b=
+a,!0});return b}function f(a){if(a){a.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():Nb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):Q(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=E(a)?a:d.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=b.document;a&&c.$watch(function(){return d.hash()},function(a,b){a===b&&""===a||Gf(function(){c.$evalAsync(g)})});
+return g}]}function hb(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;I(a)&&(a=a.join(" "));I(b)&&(b=b.join(" "));return a+" "+b}function Mf(a){E(a)&&(a=a.split(" "));var b=$();n(a,function(a){a.length&&(b[a]=!0)});return b}function Ea(a){return H(a)?a:{}}function Nf(a,b,d,c){function e(a){try{a.apply(null,ra.call(arguments,1))}finally{if(v--,0===v)for(;T.length;)try{T.pop()()}catch(b){d.error(b)}}}function f(){L=null;g();h()}function g(){a:{try{p=m.state;break a}catch(a){}p=void 0}p=q(p)?
+null:p;ma(p,J)&&(p=J);J=p}function h(){if(w!==k.url()||C!==p)w=k.url(),C=p,n(aa,function(a){a(k.url(),p)})}var k=this,l=a.location,m=a.history,r=a.setTimeout,t=a.clearTimeout,A={};k.isMock=!1;var v=0,T=[];k.$$completeOutstandingRequest=e;k.$$incOutstandingRequestCount=function(){v++};k.notifyWhenNoOutstandingRequests=function(a){0===v?a():T.push(a)};var p,C,w=l.href,ga=b.find("base"),L=null;g();C=p;k.url=function(b,d,e){q(e)&&(e=null);l!==a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=
+C===e;if(w===b&&(!c.history||f))return k;var h=w&&Fa(w)===Fa(b);w=b;C=e;if(!c.history||h&&f){if(!h||L)L=b;d?l.replace(b):h?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b;l.href!==b&&(L=b)}else m[d?"replaceState":"pushState"](e,"",b),g(),C=p;return k}return L||l.href.replace(/%27/g,"'")};k.state=function(){return p};var aa=[],D=!1,J=null;k.onUrlChange=function(b){if(!D){if(c.history)B(a).on("popstate",f);B(a).on("hashchange",f);D=!0}aa.push(b);return b};k.$$applicationDestroyed=function(){B(a).off("hashchange popstate",
+f)};k.$$checkUrlChange=h;k.baseHref=function(){var a=ga.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};k.defer=function(a,b){var c;v++;c=r(function(){delete A[c];e(a)},b||0);A[c]=!0;return c};k.defer.cancel=function(a){return A[a]?(delete A[a],t(a),e(x),!0):!1}}function Ve(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new Nf(a,c,b,d)}]}function We(){this.$get=function(){function a(a,c){function e(a){a!=r&&(t?t==a&&(t=a.n):t=a,f(a.n,a.p),f(a,r),r=a,
+r.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw G("$cacheFactory")("iid",a);var g=0,h=M({},c,{id:a}),k=$(),l=c&&c.capacity||Number.MAX_VALUE,m=$(),r=null,t=null;return b[a]={put:function(a,b){if(!q(b)){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}a in k||g++;k[a]=b;g>l&&this.remove(t.key);return b}},get:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return k[a]},remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b==r&&(r=b.p);b==t&&
+(t=b.n);f(b.n,b.p);delete m[a]}a in k&&(delete k[a],g--)},removeAll:function(){k=$();g=0;m=$();r=t=null},destroy:function(){m=h=k=null;delete b[a]},info:function(){return M({},h,{size:g})}}}var b={};a.info=function(){var a={};n(b,function(b,e){a[e]=b.info()});return a};a.get=function(a){return b[a]};return a}}function rf(){this.$get=["$cacheFactory",function(a){return a("templates")}]}function Cc(a,b){function d(a,b,c){var d=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,e={};n(a,function(a,f){var g=a.match(d);
+if(!g)throw ha("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function c(a){var b=a.charAt(0);if(!b||b!==F(b))throw ha("baddir",a);if(a!==a.trim())throw ha("baddir",a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=Wd("ngSrc,ngSrcset,src,srcset"),k=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function t(b,f){Ra(b,"directive");
+E(b)?(c(b),qb(f,"directiveFactory"),e.hasOwnProperty(b)||(e[b]=[],a.factory(b+"Directive",["$injector","$exceptionHandler",function(a,c){var f=[];n(e[b],function(e,g){try{var h=a.invoke(e);z(h)?h={compile:na(h)}:!h.compile&&h.link&&(h.compile=na(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||b;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,m=h.name,t={isolateScope:null,bindToController:null};H(l.scope)&&(!0===l.bindToController?(t.bindToController=d(l.scope,
+m,!0),t.isolateScope={}):t.isolateScope=d(l.scope,m,!1));H(l.bindToController)&&(t.bindToController=d(l.bindToController,m,!0));if(H(t.bindToController)){var v=l.controller,R=l.controllerAs;if(!v)throw ha("noctrl",m);var V;a:if(R&&E(R))V=R;else{if(E(v)){var n=Uc.exec(v);if(n){V=n[3];break a}}V=void 0}if(!V)throw ha("noident",m);}var s=k.$$bindings=t;H(s.isolateScope)&&(h.$$isolateBindings=s.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(u){c(u)}});return f}])),e[b].push(f)):n(b,pc(t));
+return this};this.aHrefSanitizationWhitelist=function(a){return y(a)?(b.aHrefSanitizationWhitelist(a),this):b.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(a){return y(a)?(b.imgSrcSanitizationWhitelist(a),this):b.imgSrcSanitizationWhitelist()};var m=!0;this.debugInfoEnabled=function(a){return y(a)?(m=a,this):m};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,
+b,c,d,p,C,w,ga,L,aa,D){function J(a,b){try{a.addClass(b)}catch(c){}}function K(a,b,c,d,e){a instanceof B||(a=B(a));n(a,function(b,c){b.nodeType==Na&&b.nodeValue.match(/\S+/)&&(a[c]=B(b).wrap("<span></span>").parent()[0])});var f=O(a,b,a,c,d,e);K.$$addScopeClass(a);var g=null;return function(b,c,d){qb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var h=d.parentBoundTranscludeFn,k=d.transcludeControllers;d=d.futureParentElement;h&&h.$$boundTransclude&&(h=h.$$boundTransclude);g||(g=(d=
+d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Yb(g,B("<div>").append(a).html())):c?Pa.clone.call(a):a;if(k)for(var l in k)d.data("$"+l+"Controller",k[l].instance);K.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,h);return d}}function O(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,m,t,w,D;if(p)for(D=Array(c.length),m=0;m<h.length;m+=3)f=h[m],D[f]=c[f];else D=c;m=0;for(t=h.length;m<t;)k=D[h[m++]],c=h[m++],f=h[m++],c?(c.scope?(l=a.$new(),K.$$addScopeInfo(B(k),
+l)):l=a,w=c.transcludeOnThisElement?R(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?R(a,b):null,c(f,l,k,d,w)):f&&f(a,k.childNodes,u,e)}for(var h=[],k,l,m,t,p,w=0;w<a.length;w++){k=new fa;l=V(a[w],[],k,0===w?d:u,e);(f=l.length?Z(l,a[w],k,b,c,null,[],[],f):null)&&f.scope&&K.$$addScopeClass(k.$$element);k=f&&f.terminal||!(m=a[w].childNodes)||!m.length?null:O(m,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(w,f,k),t=!0,p=p||f;f=null}return t?g:null}function R(a,
+b,c){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function V(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case 1:P(b,va(ta(a)),"E",d,e);for(var l,m,t,p=a.attributes,w=0,D=p&&p.length;w<D;w++){var K=!1,A=!1;l=p[w];k=l.name;m=U(l.value);l=va(k);if(t=ka.test(l))k=k.replace(Vc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});(l=l.match(la))&&G(l[1])&&(K=k,A=k.substr(0,k.length-
+5)+"end",k=k.substr(0,k.length-6));l=va(k.toLowerCase());h[l]=k;if(t||!c.hasOwnProperty(l))c[l]=m,Qc(a,l)&&(c[l]=!0);W(a,b,m,l,t);P(b,l,"A",d,e,K,A)}a=a.className;H(a)&&(a=a.animVal);if(E(a)&&""!==a)for(;k=g.exec(a);)l=va(k[2]),P(b,l,"C",d,e)&&(c[l]=U(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ha)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);N(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=
+va(k[1]),P(b,l,"M",d,e)&&(c[l]=U(k[2]))}catch(R){}}b.sort(Ia);return b}function Ta(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ha("uterdir",b,c);1==a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return B(d)}function s(a,b,c){return function(d,e,f,g,h){e=Ta(e[0],b,c);return a(d,e,f,g,h)}}function Z(a,b,d,e,f,g,h,l,m){function t(a,b,c,d){if(a){c&&(a=s(a,c,d));a.require=q.require;a.directiveName=x;if(O===
+q||q.$$isolateScope)a=ca(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=s(b,c,d));b.require=q.require;b.directiveName=x;if(O===q||q.$$isolateScope)b=ca(b,{isolateScope:!0});l.push(b)}}function p(a,b,c,d){var e;if(E(b)){var f=b.match(k);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;e||(d="$"+b+"Controller",e=g?c.inheritedData(d):c.data(d));if(!e&&!f)throw ha("ctreq",b,a);}else if(I(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=p(a,b[g],c,d);return e||
+null}function w(a,b,c,d,e,f){var g=$(),h;for(h in d){var k=d[h],l={$scope:k===O||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},m=k.controller;"@"==m&&(m=b[k.name]);l=C(m,l,!0,k.controllerAs);g[k.name]=l;aa||a.data("$"+k.name+"Controller",l.instance)}return g}function D(a,c,e,f,g){function k(a,b,c){var d;Za(a)||(c=b,b=a,a=u);aa&&(d=v);c||(c=aa?V.parent():V);return g(a,b,d,c,Ta)}var m,t,A,v,C,V,Ga;b===e?(f=d,V=d.$$element):(V=B(e),f=new fa(V,d));A=c;O?t=c.$new(!0):R&&(A=c.$parent);g&&(C=k,
+C.$$boundTransclude=g);T&&(v=w(V,f,C,T,t,c));O&&(K.$$addScopeInfo(V,t,!0,!(J&&(J===O||J===O.$$originalDirective))),K.$$addScopeClass(V,!0),t.$$isolateBindings=O.$$isolateBindings,(Ga=ba(c,f,t,t.$$isolateBindings,O))&&t.$on("$destroy",Ga));for(var n in v){Ga=T[n];var ga=v[n],L=Ga.$$bindings.bindToController;ga.identifier&&L&&(m=ba(A,f,ga.instance,L,Ga));var q=ga();q!==ga.instance&&(ga.instance=q,V.data("$"+Ga.name+"Controller",q),m&&m(),m=ba(A,f,ga.instance,L,Ga))}F=0;for(M=h.length;F<M;F++)m=h[F],
+ea(m,m.isolateScope?t:c,V,f,m.require&&p(m.directiveName,m.require,V,v),C);var Ta=c;O&&(O.template||null===O.templateUrl)&&(Ta=t);a&&a(Ta,e.childNodes,u,g);for(F=l.length-1;0<=F;F--)m=l[F],ea(m,m.isolateScope?t:c,V,f,m.require&&p(m.directiveName,m.require,V,v),C)}m=m||{};for(var A=-Number.MAX_VALUE,R=m.newScopeDirective,T=m.controllerDirectives,O=m.newIsolateScopeDirective,J=m.templateDirective,n=m.nonTlbTranscludeDirective,ga=!1,L=!1,aa=m.hasElementTranscludeDirective,Z=d.$$element=B(b),q,x,P,Ia=
+e,G,F=0,M=a.length;F<M;F++){q=a[F];var N=q.$$start,Q=q.$$end;N&&(Z=Ta(b,N,Q));P=u;if(A>q.priority)break;if(P=q.scope)q.templateUrl||(H(P)?(Ua("new/isolated scope",O||R,q,Z),O=q):Ua("new/isolated scope",O,q,Z)),R=R||q;x=q.name;!q.templateUrl&&q.controller&&(P=q.controller,T=T||$(),Ua("'"+x+"' controller",T[x],q,Z),T[x]=q);if(P=q.transclude)ga=!0,q.$$tlb||(Ua("transclusion",n,q,Z),n=q),"element"==P?(aa=!0,A=q.priority,P=Z,Z=d.$$element=B(X.createComment(" "+x+": "+d[x]+" ")),b=Z[0],Y(f,ra.call(P,0),
+b),Ia=K(P,e,A,g&&g.name,{nonTlbTranscludeDirective:n})):(P=B(Vb(b)).contents(),Z.empty(),Ia=K(P,e,u,u,{needsNewScope:q.$$isolateScope||q.$$newScope}));if(q.template)if(L=!0,Ua("template",J,q,Z),J=q,P=z(q.template)?q.template(Z,d):q.template,P=ja(P),q.replace){g=q;P=Tb.test(P)?Xc(Yb(q.templateNamespace,U(P))):[];b=P[0];if(1!=P.length||1!==b.nodeType)throw ha("tplrt",x,"");Y(f,Z,b);P={$attr:{}};var Wc=V(b,[],P),W=a.splice(F+1,a.length-(F+1));(O||R)&&y(Wc,O,R);a=a.concat(Wc).concat(W);S(d,P);M=a.length}else Z.html(P);
+if(q.templateUrl)L=!0,Ua("template",J,q,Z),J=q,q.replace&&(g=q),D=Of(a.splice(F,a.length-F),Z,d,f,ga&&Ia,h,l,{controllerDirectives:T,newScopeDirective:R!==q&&R,newIsolateScopeDirective:O,templateDirective:J,nonTlbTranscludeDirective:n}),M=a.length;else if(q.compile)try{G=q.compile(Z,d,Ia),z(G)?t(null,G,N,Q):G&&t(G.pre,G.post,N,Q)}catch(da){c(da,ua(Z))}q.terminal&&(D.terminal=!0,A=Math.max(A,q.priority))}D.scope=R&&!0===R.scope;D.transcludeOnThisElement=ga;D.templateOnThisElement=L;D.transclude=Ia;
+m.hasElementTranscludeDirective=aa;return D}function y(a,b,c){for(var d=0,e=a.length;d<e;d++)a[d]=Ob(a[d],{$$isolateScope:b,$$newScope:c})}function P(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var m;d=a.get(d+"Directive");for(var p=0,w=d.length;p<w;p++)try{m=d[p],(q(g)||g>m.priority)&&-1!=m.restrict.indexOf(f)&&(k&&(m=Ob(m,{$$start:k,$$end:l})),b.push(m),h=m)}catch(D){c(D)}}return h}function G(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=
+c[d],b.multiElement)return!0;return!1}function S(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;n(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});n(b,function(b,f){"class"==f?(J(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function Of(a,b,c,e,f,g,h,k){var l=[],m,t,p=b[0],w=a.shift(),D=Ob(w,{templateUrl:null,
+transclude:null,replace:null,$$originalDirective:w}),A=z(w.templateUrl)?w.templateUrl(b,c):w.templateUrl,K=w.templateNamespace;b.empty();d(A).then(function(d){var T,v;d=ja(d);if(w.replace){d=Tb.test(d)?Xc(Yb(K,U(d))):[];T=d[0];if(1!=d.length||1!==T.nodeType)throw ha("tplrt",w.name,A);d={$attr:{}};Y(e,b,T);var C=V(T,[],d);H(w.scope)&&y(C,!0);a=C.concat(a);S(c,d)}else T=p,b.html(d);a.unshift(D);m=Z(a,T,c,f,b,w,g,h,k);n(e,function(a,c){a==T&&(e[c]=b[0])});for(t=O(b[0].childNodes,f);l.length;){d=l.shift();
+v=l.shift();var ga=l.shift(),L=l.shift(),C=b[0];if(!d.$$destroyed){if(v!==p){var q=v.className;k.hasElementTranscludeDirective&&w.replace||(C=Vb(T));Y(ga,B(v),C);J(B(C),q)}v=m.transcludeOnThisElement?R(d,m.transclude,L):L;m(t,d,C,e,v)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(m.transcludeOnThisElement&&(a=R(b,m.transclude,e)),m(t,b,c,d,a)))}}function Ia(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Ua(a,
+b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ha("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ua(d));}function N(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&K.$$addBindingClass(a);return function(a,c){var e=c.parent();b||K.$$addBindingClass(e);K.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Yb(a,b){a=F(a||"html");switch(a){case "svg":case "math":var c=X.createElement("div");
+c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return L.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return L.RESOURCE_URL}function W(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var k=b(d,!0,g,f);if(k){if("multiple"===e&&"select"===ta(a))throw ha("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers=$());if(l.test(e))throw ha("nodomevents");
+var m=h[e];m!==d&&(k=m&&b(m,!0,g,f),d=m);k&&(h[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(k,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e,a)}))}}}})}}function Y(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=X.createDocumentFragment();a.appendChild(d);
+B.hasData(d)&&(B.data(c,B.data(d)),oa?(Rb=!0,oa.cleanData([d])):delete B.cache[d[B.expando]]);d=1;for(e=b.length;d<e;d++)f=b[d],B(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function ca(a,b){return M(function(){return a.apply(null,arguments)},a,b)}function ea(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ua(d))}}function ba(a,c,d,e,f){var g=[];n(e,function(e,h){var k=e.attrName,l=e.optional,m,t,w,D;switch(e.mode){case "@":l||qa.call(c,k)||(d[h]=c[k]=void 0);c.$observe(k,function(a){E(a)&&
+(d[h]=a)});c.$$observers[k].$$scope=a;E(c[k])&&(d[h]=b(c[k])(a));break;case "=":if(!qa.call(c,k)){if(l)break;c[k]=void 0}if(l&&!c[k])break;t=p(c[k]);D=t.literal?ma:function(a,b){return a===b||a!==a&&b!==b};w=t.assign||function(){m=d[h]=t(a);throw ha("nonassign",c[k],f.name);};m=d[h]=t(a);l=function(b){D(b,d[h])||(D(b,m)?w(a,b=d[h]):d[h]=b);return m=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(p(c[k],l),null,t.literal);g.push(l);break;case "&":t=c.hasOwnProperty(k)?p(c[k]):
+x;if(t===x&&l)break;d[h]=function(b){return t(a,b)}}});return g.length&&function(){for(var a=0,b=g.length;a<b;++a)g[a]()}}var fa=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};fa.prototype={$normalize:va,$addClass:function(a){a&&0<a.length&&aa.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&aa.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=Yc(a,b);c&&c.length&&aa.addClass(this.$$element,
+c);(c=Yc(b,a))&&c.length&&aa.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=Qc(this.$$element[0],a),g=Zc[a],h=a;f?(this.$$element.prop(a,b),e=f):g&&(this[g]=b,h=g);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=zc(a,"-"));f=ta(this.$$element);if("a"===f&&"href"===a||"img"===f&&"src"===a)this[a]=b=D(b,"src"===a);else if("img"===f&&"srcset"===a){for(var f="",g=U(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(g)?k:/(,)/,g=g.split(k),k=Math.floor(g.length/2),l=0;l<
+k;l++)var m=2*l,f=f+D(U(g[m]),!0),f=f+(" "+U(g[m+1]));g=U(g[2*l]).split(/\s/);f+=D(U(g[0]),!0);2===g.length&&(f+=" "+U(g[1]));this[a]=b=f}!1!==d&&(null===b||q(b)?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&n(a[h],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=$()),e=d[a]||(d[a]=[]);e.push(b);w.$evalAsync(function(){e.$$inter||!c.hasOwnProperty(a)||q(c[a])||b(c[a])});return function(){ab(e,b)}}};var da=b.startSymbol(),
+ia=b.endSymbol(),ja="{{"==da||"}}"==ia?Ya:function(a){return a.replace(/\{\{/g,da).replace(/}}/g,ia)},ka=/^ngAttr[A-Z]/,la=/^(.+)Start$/;K.$$addBindingInfo=m?function(a,b){var c=a.data("$binding")||[];I(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:x;K.$$addBindingClass=m?function(a){J(a,"ng-binding")}:x;K.$$addScopeInfo=m?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:x;K.$$addScopeClass=m?function(a,b){J(a,b?"ng-isolate-scope":"ng-scope")}:x;return K}]}function va(a){return fb(a.replace(Vc,
+""))}function Yc(a,b){var d="",c=a.split(/\s+/),e=b.split(/\s+/),f=0;a:for(;f<c.length;f++){for(var g=c[f],h=0;h<e.length;h++)if(g==e[h])continue a;d+=(0<d.length?" ":"")+g}return d}function Xc(a){a=B(a);var b=a.length;if(1>=b)return a;for(;b--;)8===a[b].nodeType&&Pf.call(a,b,1);return a}function Xe(){var a={},b=!1;this.register=function(b,c){Ra(b,"controller");H(b)?M(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector","$window",function(d,c){function e(a,b,c,d){if(!a||!H(a.$scope))throw G("$controller")("noscp",
+d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,r;h=!0===h;k&&E(k)&&(r=k);if(E(f)){k=f.match(Uc);if(!k)throw Qf("ctrlfmt",f);m=k[1];r=r||k[3];f=a.hasOwnProperty(m)?a[m]:Bc(g.$scope,m,!0)||(b?Bc(c,m,!0):u);Qa(f,m,!0)}if(h)return h=(I(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),r&&e(g,r,l,m||f.name),M(function(){var a=d.invoke(f,l,g,m);a!==l&&(H(a)||z(a))&&(l=a,r&&e(g,r,l,m||f.name));return l},{instance:l,identifier:r});l=d.instantiate(f,g,m);r&&e(g,r,l,m||f.name);return l}}]}function Ye(){this.$get=
+["$window",function(a){return B(a.document)}]}function Ze(){this.$get=["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function Zb(a){return H(a)?da(a)?a.toISOString():db(a):a}function df(){this.$get=function(){return function(a){if(!a)return"";var b=[];oc(a,function(a,c){null===a||q(a)||(I(a)?n(a,function(a,d){b.push(ja(c)+"="+ja(Zb(a)))}):b.push(ja(c)+"="+ja(Zb(a))))});return b.join("&")}}}function ef(){this.$get=function(){return function(a){function b(a,e,f){null===a||q(a)||
+(I(a)?n(a,function(a,c){b(a,e+"["+(H(a)?c:"")+"]")}):H(a)&&!da(a)?oc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ja(e)+"="+ja(Zb(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function $b(a,b){if(E(a)){var d=a.replace(Rf,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf($c))||(c=(c=d.match(Sf))&&Tf[c[0]].test(d));c&&(a=uc(d))}}return a}function ad(a){var b=$(),d;E(a)?n(a.split("\n"),function(a){d=a.indexOf(":");var e=F(U(a.substr(0,d)));a=U(a.substr(d+1));e&&
+(b[e]=b[e]?b[e]+", "+a:a)}):H(a)&&n(a,function(a,d){var f=F(d),g=U(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function bd(a){var b;return function(d){b||(b=ad(a));return d?(d=b[F(d)],void 0===d&&(d=null),d):b}}function cd(a,b,d,c){if(z(c))return c(a,b,d);n(c,function(c){a=c(a,b,d)});return a}function cf(){var a=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},
+post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return y(a)?(b=!!a,this):b};var d=!0;this.useLegacyPromiseExtensions=function(a){return y(a)?(d=!!a,this):d};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(e,f,g,h,k,l){function m(b){function c(a){var b=M({},a);b.data=cd(a.data,a.headers,a.status,f.transformResponse);
+a=a.status;return 200<=a&&300>a?b:k.reject(b)}function e(a,b){var c,d={};n(a,function(a,e){z(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}if(!fa.isObject(b))throw G("$http")("badreq",b);var f=M({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},b);f.headers=function(b){var c=a.headers,d=M({},b.headers),f,g,h,c=M({},c.common,c[F(b.method)]);a:for(f in c){g=F(f);for(h in d)if(F(h)===g)continue a;d[f]=c[f]}return e(d,ia(b))}(b);
+f.method=sb(f.method);f.paramSerializer=E(f.paramSerializer)?l.get(f.paramSerializer):f.paramSerializer;var g=[function(b){var d=b.headers,e=cd(b.data,bd(d),u,b.transformRequest);q(e)&&n(d,function(a,b){"content-type"===F(b)&&delete d[b]});q(b.withCredentials)&&!q(a.withCredentials)&&(b.withCredentials=a.withCredentials);return r(b,e).then(c,c)},u],h=k.when(f);for(n(v,function(a){(a.request||a.requestError)&&g.unshift(a.request,a.requestError);(a.response||a.responseError)&&g.push(a.response,a.responseError)});g.length;){b=
+g.shift();var m=g.shift(),h=h.then(b,m)}d?(h.success=function(a){Qa(a,"fn");h.then(function(b){a(b.data,b.status,b.headers,f)});return h},h.error=function(a){Qa(a,"fn");h.then(null,function(b){a(b.data,b.status,b.headers,f)});return h}):(h.success=dd("success"),h.error=dd("error"));return h}function r(c,d){function g(a,c,d,e){function f(){l(c,a,d,e)}J&&(200<=a&&300>a?J.put(R,[a,c,ad(d),e]):J.remove(R));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function l(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?n.resolve:
+n.reject)({data:a,status:b,headers:bd(d),config:c,statusText:e})}function r(a){l(a.data,a.status,ia(a.headers()),a.statusText)}function v(){var a=m.pendingRequests.indexOf(c);-1!==a&&m.pendingRequests.splice(a,1)}var n=k.defer(),D=n.promise,J,K,O=c.headers,R=t(c.url,c.paramSerializer(c.params));m.pendingRequests.push(c);D.then(v,v);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(J=H(c.cache)?c.cache:H(a.cache)?a.cache:A);J&&(K=J.get(R),y(K)?K&&z(K.then)?K.then(r,r):I(K)?l(K[1],
+K[0],ia(K[2]),K[3]):l(K,200,{},"OK"):J.put(R,D));q(K)&&((K=ed(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:u)&&(O[c.xsrfHeaderName||a.xsrfHeaderName]=K),e(c.method,R,d,g,O,c.timeout,c.withCredentials,c.responseType));return D}function t(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);return a}var A=g("$http");a.paramSerializer=E(a.paramSerializer)?l.get(a.paramSerializer):a.paramSerializer;var v=[];n(c,function(a){v.unshift(E(a)?l.get(a):l.invoke(a))});m.pendingRequests=[];(function(a){n(arguments,
+function(a){m[a]=function(b,c){return m(M({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){n(arguments,function(a){m[a]=function(b,c,d){return m(M({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");m.defaults=a;return m}]}function gf(){this.$get=function(){return function(){return new S.XMLHttpRequest}}}function ff(){this.$get=["$browser","$window","$document","$xhrFactory",function(a,b,d,c){return Uf(a,c,a.defer,b.angular.callbacks,d[0])}]}function Uf(a,b,d,
+c,e){function f(a,b,d){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,A="unknown";a&&("load"!==a.type||c[b].called||(a={type:"error"}),A=a.type,g="error"===a.type?404:200);d&&d(g,A)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,k,l,m,r,t,A){function v(){C&&C();w&&w.abort()}
+function T(b,c,e,f,g){y(L)&&d.cancel(L);C=w=null;b(c,e,f,g);a.$$completeOutstandingRequest(x)}a.$$incOutstandingRequestCount();h=h||a.url();if("jsonp"==F(e)){var p="_"+(c.counter++).toString(36);c[p]=function(a){c[p].data=a;c[p].called=!0};var C=f(h.replace("JSON_CALLBACK","angular.callbacks."+p),p,function(a,b){T(l,a,c[p].data,"",b);c[p]=x})}else{var w=b(e,h);w.open(e,h,!0);n(m,function(a,b){y(a)&&w.setRequestHeader(b,a)});w.onload=function(){var a=w.statusText||"",b="response"in w?w.response:w.responseText,
+c=1223===w.status?204:w.status;0===c&&(c=b?200:"file"==wa(h).protocol?404:0);T(l,c,b,w.getAllResponseHeaders(),a)};e=function(){T(l,-1,null,null,"")};w.onerror=e;w.onabort=e;t&&(w.withCredentials=!0);if(A)try{w.responseType=A}catch(ga){if("json"!==A)throw ga;}w.send(q(k)?null:k)}if(0<r)var L=d(v,r);else r&&z(r.then)&&r.then(v)}}function af(){var a="{{",b="}}";this.startSymbol=function(b){return b?(a=b,this):a};this.endSymbol=function(a){return a?(b=a,this):b};this.$get=["$parse","$exceptionHandler",
+"$sce",function(d,c,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(m,a).replace(r,b)}function h(f,h,m,r){function p(a){try{var b=a;a=m?e.getTrusted(m,b):e.valueOf(b);var d;if(r&&!y(a))d=a;else if(null==a)d="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=db(a)}d=a}return d}catch(g){c(Ja.interr(f,g))}}r=!!r;for(var C,w,n=0,L=[],s=[],D=f.length,J=[],K=[];n<D;)if(-1!=(C=f.indexOf(a,n))&&-1!=(w=f.indexOf(b,C+k)))n!==C&&J.push(g(f.substring(n,C))),n=f.substring(C+
+k,w),L.push(n),s.push(d(n,p)),n=w+l,K.push(J.length),J.push("");else{n!==D&&J.push(g(f.substring(n)));break}m&&1<J.length&&Ja.throwNoconcat(f);if(!h||L.length){var O=function(a){for(var b=0,c=L.length;b<c;b++){if(r&&q(a[b]))return;J[K[b]]=a[b]}return J.join("")};return M(function(a){var b=0,d=L.length,e=Array(d);try{for(;b<d;b++)e[b]=s[b](a);return O(e)}catch(g){c(Ja.interr(f,g))}},{exp:f,expressions:L,$$watchDelegate:function(a,b){var c;return a.$watchGroup(s,function(d,e){var f=O(d);z(b)&&b.call(this,
+f,d!==e?c:f,a);c=f})}})}}var k=a.length,l=b.length,m=new RegExp(a.replace(/./g,f),"g"),r=new RegExp(b.replace(/./g,f),"g");h.startSymbol=function(){return a};h.endSymbol=function(){return b};return h}]}function bf(){this.$get=["$rootScope","$window","$q","$$q",function(a,b,d,c){function e(e,h,k,l){var m=4<arguments.length,r=m?ra.call(arguments,4):[],t=b.setInterval,A=b.clearInterval,v=0,n=y(l)&&!l,p=(n?c:d).defer(),C=p.promise;k=y(k)?k:0;C.then(null,null,m?function(){e.apply(null,r)}:e);C.$$intervalId=
+t(function(){p.notify(v++);0<k&&v>=k&&(p.resolve(v),A(C.$$intervalId),delete f[C.$$intervalId]);n||a.$apply()},h);f[C.$$intervalId]=p;return C}var f={};e.cancel=function(a){return a&&a.$$intervalId in f?(f[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete f[a.$$intervalId],!0):!1};return e}]}function bc(a){a=a.split("/");for(var b=a.length;b--;)a[b]=ob(a[b]);return a.join("/")}function fd(a,b){var d=wa(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=ea(d.port)||Vf[d.protocol]||
+null}function gd(a,b){var d="/"!==a.charAt(0);d&&(a="/"+a);var c=wa(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=xc(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function pa(a,b){if(0===b.indexOf(a))return b.substr(a.length)}function Fa(a){var b=a.indexOf("#");return-1==b?a:a.substr(0,b)}function ib(a){return a.replace(/(#.+)|#$/,"$1")}function cc(a,b,d){this.$$html5=!0;d=d||"";
+fd(a,this);this.$$parse=function(a){var d=pa(b,a);if(!E(d))throw Db("ipthprfx",a,b);gd(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),d=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+d;this.$$absUrl=b+this.$$url.substr(1)};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;y(f=pa(a,c))?(g=f,g=y(f=pa(d,f))?b+(pa("/",f)||f):a+g):y(f=pa(b,c))?g=b+f:b==c+"/"&&(g=b);g&&this.$$parse(g);
+return!!g}}function dc(a,b,d){fd(a,this);this.$$parse=function(c){var e=pa(a,c)||pa(b,c),f;q(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",q(e)&&(a=c,this.replace())):(f=pa(d,e),q(f)&&(f=e));gd(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?
+d+this.$$url:"")};this.$$parseLinkUrl=function(b,d){return Fa(a)==Fa(b)?(this.$$parse(b),!0):!1}}function hd(a,b,d){this.$$html5=!0;dc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a==Fa(c)?f=c:(g=pa(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url}}function Eb(a){return function(){return this[a]}}
+function id(a,b){return function(d){if(q(d))return this[a];this[a]=b(d);this.$$compose();return this}}function hf(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return y(b)?(a=b,this):a};this.html5Mode=function(a){return $a(a)?(b.enabled=a,this):H(a)?($a(a.enabled)&&(b.enabled=a.enabled),$a(a.requireBase)&&(b.requireBase=a.requireBase),$a(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",
+function(d,c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state=f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,b)}var l,m;m=c.baseHref();var r=c.url(),t;if(b.enabled){if(!m&&b.requireBase)throw Db("nobase");t=r.substring(0,r.indexOf("/",r.indexOf("//")+2))+(m||"/");m=e.history?cc:hd}else t=Fa(r),m=dc;var A=t.substr(0,Fa(t).lastIndexOf("/")+1);l=new m(t,A,"#"+a);l.$$parseLinkUrl(r,r);l.$$state=
+c.state();var v=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=B(a.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),k=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=wa(h.animVal).href);v.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(h,k)||(a.preventDefault(),l.absUrl()!=c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=
+!0))}});ib(l.absUrl())!=ib(r)&&c.url(l.absUrl(),!0);var n=!0;c.onUrlChange(function(a,b){q(pa(A,a))?g.location.href=a:(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=ib(a);l.$$parse(a);l.$$state=b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=e,h(c,!1,e)):(n=!1,k(c,e)))}),d.$$phase||d.$digest())});d.$watch(function(){var a=ib(c.url()),b=ib(l.absUrl()),f=c.state(),g=l.$$replace,m=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(n||
+m)n=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(m&&h(b,g,f===l.$$state?null:l.$$state),k(a,f)))});l.$$replace=!1});return l}]}function jf(){var a=!0,b=this;this.debugEnabled=function(b){return y(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&
+(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||x;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];n(arguments,function(b){a.push(c(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Va(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===
+a||"__proto__"===a)throw ba("isecfld",b);return a}function jd(a,b){a+="";if(!E(a))throw ba("iseccst",b);return a}function xa(a,b){if(a){if(a.constructor===a)throw ba("isecfn",b);if(a.window===a)throw ba("isecwindow",b);if(a.children&&(a.nodeName||a.prop&&a.attr&&a.find))throw ba("isecdom",b);if(a===Object)throw ba("isecobj",b);}return a}function kd(a,b){if(a){if(a.constructor===a)throw ba("isecfn",b);if(a===Wf||a===Xf||a===Yf)throw ba("isecff",b);}}function ld(a,b){if(a&&(a===(0).constructor||a===
+(!1).constructor||a==="".constructor||a==={}.constructor||a===[].constructor||a===Function.constructor))throw ba("isecaf",b);}function Zf(a,b){return"undefined"!==typeof a?a:b}function md(a,b){return"undefined"===typeof a?b:"undefined"===typeof b?a:a+b}function W(a,b){var d,c;switch(a.type){case s.Program:d=!0;n(a.body,function(a){W(a.expression,b);d=d&&a.expression.constant});a.constant=d;break;case s.Literal:a.constant=!0;a.toWatch=[];break;case s.UnaryExpression:W(a.argument,b);a.constant=a.argument.constant;
+a.toWatch=a.argument.toWatch;break;case s.BinaryExpression:W(a.left,b);W(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case s.LogicalExpression:W(a.left,b);W(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case s.ConditionalExpression:W(a.test,b);W(a.alternate,b);W(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case s.Identifier:a.constant=
+!1;a.toWatch=[a];break;case s.MemberExpression:W(a.object,b);a.computed&&W(a.property,b);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=[a];break;case s.CallExpression:d=a.filter?!b(a.callee.name).$stateful:!1;c=[];n(a.arguments,function(a){W(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=a.filter&&!b(a.callee.name).$stateful?c:[a];break;case s.AssignmentExpression:W(a.left,b);W(a.right,b);a.constant=a.left.constant&&a.right.constant;
+a.toWatch=[a];break;case s.ArrayExpression:d=!0;c=[];n(a.elements,function(a){W(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=c;break;case s.ObjectExpression:d=!0;c=[];n(a.properties,function(a){W(a.value,b);d=d&&a.value.constant;a.value.constant||c.push.apply(c,a.value.toWatch)});a.constant=d;a.toWatch=c;break;case s.ThisExpression:a.constant=!1,a.toWatch=[]}}function nd(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:u}}
+function od(a){return a.type===s.Identifier||a.type===s.MemberExpression}function pd(a){if(1===a.body.length&&od(a.body[0].expression))return{type:s.AssignmentExpression,left:a.body[0].expression,right:{type:s.NGValueParameter},operator:"="}}function qd(a){return 0===a.body.length||1===a.body.length&&(a.body[0].expression.type===s.Literal||a.body[0].expression.type===s.ArrayExpression||a.body[0].expression.type===s.ObjectExpression)}function rd(a,b){this.astBuilder=a;this.$filter=b}function sd(a,
+b){this.astBuilder=a;this.$filter=b}function Fb(a){return"constructor"==a}function ec(a){return z(a.valueOf)?a.valueOf():$f.call(a)}function kf(){var a=$(),b=$();this.$get=["$filter",function(d){function c(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=ec(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function e(a,b,d,e,f){var g=e.inputs,h;if(1===g.length){var k=c,g=g[0];return a.$watch(function(a){var b=g(a);c(b,k)||(h=e(a,u,u,[b]),k=b&&ec(b));return h},b,d,f)}for(var l=[],m=[],r=0,n=
+g.length;r<n;r++)l[r]=c,m[r]=null;return a.$watch(function(a){for(var b=!1,d=0,f=g.length;d<f;d++){var k=g[d](a);if(b||(b=!c(k,l[d])))m[d]=k,l[d]=k&&ec(k)}b&&(h=e(a,u,u,m));return h},b,d,f)}function f(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function g(a,b,c,d){function e(a){var b=!0;n(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,
+c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function h(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function k(a,b){if(!b)return a;var c=a.$$watchDelegate,d=!1,c=c!==g&&c!==f?function(c,e,f,g){f=d&&g?g[0]:a(c,e,f,g);return b(f,c,e)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return y(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==e?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=
+e,d=!a.inputs,c.inputs=a.inputs?a.inputs:[a]);return c}var l=Ba().noUnsafeEval,m={csp:l,expensiveChecks:!1},r={csp:l,expensiveChecks:!0};return function(c,l,v){var n,p,q;switch(typeof c){case "string":q=c=c.trim();var w=v?b:a;n=w[q];n||(":"===c.charAt(0)&&":"===c.charAt(1)&&(p=!0,c=c.substring(2)),v=v?r:m,n=new fc(v),n=(new gc(n,d,v)).parse(c),n.constant?n.$$watchDelegate=h:p?n.$$watchDelegate=n.literal?g:f:n.inputs&&(n.$$watchDelegate=e),w[q]=n);return k(n,l);case "function":return k(c,l);default:return x}}}]}
+function mf(){this.$get=["$rootScope","$exceptionHandler",function(a,b){return td(function(b){a.$evalAsync(b)},b)}]}function nf(){this.$get=["$browser","$exceptionHandler",function(a,b){return td(function(b){a.defer(b)},b)}]}function td(a,b){function d(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function c(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,a(function(){var a,
+d,e;e=c.pending;c.processScheduled=!1;c.pending=u;for(var f=0,g=e.length;f<g;++f){d=e[f][0];a=e[f][c.status];try{z(a)?d.resolve(a(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),b(h)}}}))}function g(){this.promise=new c;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=G("$q",TypeError);M(c.prototype,{then:function(a,b,c){if(q(a)&&q(b)&&q(c))return this;var d=new g;this.$$state.pending=this.$$state.pending||[];
+this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return l(b,!0,a)},function(b){return l(b,!1,a)},b)}});M(g.prototype,{resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(a){var c,e;e=d(this,this.$$resolve,this.$$reject);try{if(H(a)||z(a))c=a&&a.then;z(c)?(this.promise.$$state.status=
+-1,c.call(a,e[0],e[1],this.notify)):(this.promise.$$state.value=a,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),b(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;f<g;f++){e=d[f][0];a=d[f][3];try{e.notify(z(a)?
+a(c):c)}catch(h){b(h)}}})}});var k=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},l=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return k(e,!1)}return d&&z(d.then)?d.then(function(){return k(a,b)},function(a){return k(a,!1)}):k(a,b)},m=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},r=function A(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof A))return new A(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
+r.defer=function(){return new g};r.reject=function(a){var b=new g;b.reject(a);return b.promise};r.when=m;r.resolve=m;r.all=function(a){var b=new g,c=0,d=I(a)?[]:{};n(a,function(a,e){c++;m(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return r}function wf(){this.$get=["$window","$timeout",function(a,b){var d=a.requestAnimationFrame||a.webkitRequestAnimationFrame,c=a.cancelAnimationFrame||a.webkitCancelAnimationFrame||
+a.webkitCancelRequestAnimationFrame,e=!!d,f=e?function(a){var b=d(a);return function(){c(b)}}:function(a){var c=b(a,16.66,!1);return function(){b.cancel(c)}};f.supported=e;return f}]}function lf(){function a(a){function b(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++nb;this.$$ChildScope=null}b.prototype=a;return b}var b=10,d=G("$rootScope"),c=null,e=null;this.digestTtl=function(a){arguments.length&&
+(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,k){function l(a){a.currentScope.$$destroyed=!0}function m(a){9===Ha&&(a.$$childHead&&m(a.$$childHead),a.$$nextSibling&&m(a.$$nextSibling));a.$parent=a.$$nextSibling=a.$$prevSibling=a.$$childHead=a.$$childTail=a.$root=a.$$watchers=null}function r(){this.$id=++nb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=
+!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function t(a){if(w.$$phase)throw d("inprog",w.$$phase);w.$$phase=a}function A(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function v(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function s(){}function p(){for(;aa.length;)try{aa.shift()()}catch(a){g(a)}e=null}function C(){null===e&&(e=k.defer(function(){w.$apply(p)}))}r.prototype={constructor:r,
+$new:function(b,c){var d;c=c||this;b?(d=new r,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=a(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(b||c!=this)&&d.$on("$destroy",l);return d},$watch:function(a,b,d,e){var f=h(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,d,f,a);var g=this,k=g.$$watchers,l={fn:b,last:s,get:f,exp:e||a,eq:!!d};c=null;z(b)||(l.fn=x);k||
+(k=g.$$watchers=[]);k.unshift(l);A(this,1);return function(){0<=ab(k,l)&&A(g,-1);c=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});n(a,function(a,b){var k=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},
+$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!q(e)){if(H(e))if(za(e))for(f!==r&&(f=r,n=f.length=0,l++),a=e.length,n!==a&&(l++,f.length=n=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==t&&(f=t={},n=0,l++);a=0;for(b in e)qa.call(e,b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(n++,f[b]=g,l++));if(n>a)for(b in l++,f)qa.call(e,b)||(n--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1<b.length,l=0,m=
+h(a,c),r=[],t={},p=!0,n=0;return this.$watch(m,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(k)if(H(e))if(za(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)qa.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var a,f,h,l,m,r,n=b,A,q=[],v,C;t("$digest");k.$$checkUrlChange();this===w&&null!==e&&(k.defer.cancel(e),p());c=null;do{r=!1;for(A=this;u.length;){try{C=u.shift(),C.scope.$eval(C.expression,C.locals)}catch(aa){g(aa)}c=null}a:do{if(l=A.$$watchers)for(m=l.length;m--;)try{if(a=
+l[m])if((f=a.get(A))!==(h=a.last)&&!(a.eq?ma(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))r=!0,c=a,a.last=a.eq?bb(f,null):f,a.fn(f,h===s?f:h,A),5>n&&(v=4-n,q[v]||(q[v]=[]),q[v].push({msg:z(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:f,oldVal:h}));else if(a===c){r=!1;break a}}catch(y){g(y)}if(!(l=A.$$watchersCount&&A.$$childHead||A!==this&&A.$$nextSibling))for(;A!==this&&!(l=A.$$nextSibling);)A=A.$parent}while(A=l);if((r||u.length)&&!n--)throw w.$$phase=null,d("infdig",
+b,q);}while(r||u.length);for(w.$$phase=null;L.length;)try{L.shift()()}catch(x){g(x)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===w&&k.$$applicationDestroyed();A(this,-this.$$watchersCount);for(var b in this.$$listenerCount)v(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=
+this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=x;this.$on=this.$watch=this.$watchGroup=function(){return x};this.$$listeners={};this.$$nextSibling=null;m(this)}},$eval:function(a,b){return h(a)(this,b)},$evalAsync:function(a,b){w.$$phase||u.length||k.defer(function(){u.length&&w.$digest()});u.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){L.push(a)},$apply:function(a){try{t("$apply");
+try{return this.$eval(a)}finally{w.$$phase=null}}catch(b){g(b)}finally{try{w.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&aa.push(b);C()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,v(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h=
+{name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,k)}catch(r){g(r)}else d.splice(l,1),l--,m--;if(f)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};
+if(!this.$$listenerCount[a])return e;for(var f=cb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,f)}catch(l){g(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var w=new r,u=w.$$asyncQueue=[],L=w.$$postDigestQueue=[],aa=w.$$applyAsyncQueue=[];return w}]}function ge(){var a=/^\s*(https?|ftp|mailto|tel|file):/,
+b=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.imgSrcSanitizationWhitelist=function(a){return y(a)?(b=a,this):b};this.$get=function(){return function(d,c){var e=c?b:a,f;f=wa(d).href;return""===f||f.match(e)?d:"unsafe:"+f}}}function ag(a){if("self"===a)return a;if(E(a)){if(-1<a.indexOf("***"))throw ya("iwcard",a);a=ud(a).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+a+"$")}if(Ma(a))return new RegExp("^"+
+a.source+"$");throw ya("imatcher");}function vd(a){var b=[];y(a)&&n(a,function(a){b.push(ag(a))});return b}function pf(){this.SCE_CONTEXTS=la;var a=["self"],b=[];this.resourceUrlWhitelist=function(b){arguments.length&&(a=vd(b));return a};this.resourceUrlBlacklist=function(a){arguments.length&&(b=vd(a));return b};this.$get=["$injector",function(d){function c(a,b){return"self"===a?ed(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=
+new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw ya("unsafe");};d.has("$sanitize")&&(f=d.get("$sanitize"));var g=e(),h={};h[la.HTML]=e(g);h[la.CSS]=e(g);h[la.URL]=e(g);h[la.JS]=e(g);h[la.RESOURCE_URL]=e(h[la.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw ya("icontext",a,b);if(null===b||q(b)||""===b)return b;if("string"!==typeof b)throw ya("itype",
+a);return new c(b)},getTrusted:function(d,e){if(null===e||q(e)||""===e)return e;var g=h.hasOwnProperty(d)?h[d]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(d===la.RESOURCE_URL){var g=wa(e.toString()),r,t,n=!1;r=0;for(t=a.length;r<t;r++)if(c(a[r],g)){n=!0;break}if(n)for(r=0,t=b.length;r<t;r++)if(c(b[r],g)){n=!1;break}if(n)return e;throw ya("insecurl",e.toString());}if(d===la.HTML)return f(e);throw ya("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}
+function of(){var a=!0;this.enabled=function(b){arguments.length&&(a=!!b);return a};this.$get=["$parse","$sceDelegate",function(b,d){if(a&&8>Ha)throw ya("iequirks");var c=ia(la);c.isEnabled=function(){return a};c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=Ya);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs,f=c.getTrusted,g=c.trustAs;n(la,function(a,
+b){var d=F(b);c[fb("parse_as_"+d)]=function(b){return e(a,b)};c[fb("get_trusted_"+d)]=function(b){return f(a,b)};c[fb("trust_as_"+d)]=function(b){return g(a,b)}});return c}]}function qf(){this.$get=["$window","$document",function(a,b){var d={},c=ea((/android (\d+)/.exec(F((a.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((a.navigator||{}).userAgent),f=b[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,k=f.body&&f.body.style,l=!1,m=!1;if(k){for(var r in k)if(l=h.exec(r)){g=l[0];g=g.substr(0,1).toUpperCase()+
+g.substr(1);break}g||(g="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||g+"Transition"in k);m=!!("animation"in k||g+"Animation"in k);!c||l&&m||(l=E(k.webkitTransition),m=E(k.webkitAnimation))}return{history:!(!a.history||!a.history.pushState||4>c||e),hasEvent:function(a){if("input"===a&&11>=Ha)return!1;if(q(d[a])){var b=f.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ba(),vendorPrefix:g,transitions:l,animations:m,android:c}}]}function sf(){this.$get=["$templateCache","$http","$q","$sce",
+function(a,b,d,c){function e(f,g){e.totalPendingRequests++;E(f)&&a.get(f)||(f=c.getTrustedResourceUrl(f));var h=b.defaults&&b.defaults.transformResponse;I(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return b.get(f,{cache:a,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(b){a.put(f,b.data);return b.data},function(a){if(!g)throw ha("tpload",f,a.status,a.statusText);return d.reject(a)})}e.totalPendingRequests=0;return e}]}function tf(){this.$get=["$rootScope",
+"$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];n(a,function(a){var c=fa.element(a).data("$binding");c&&n(c,function(c){d?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!=c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var k=a.querySelectorAll("["+g[h]+"model"+(d?"=":"*=")+'"'+b+'"]');if(k.length)return k}},getLocation:function(){return d.url()},
+setLocation:function(b){b!==d.url()&&(d.url(b),a.$digest())},whenStable:function(a){b.notifyWhenNoOutstandingRequests(a)}}}]}function uf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(a,b,d,c,e){function f(f,k,l){z(f)||(l=k,k=f,f=x);var m=ra.call(arguments,3),r=y(l)&&!l,t=(r?c:d).defer(),n=t.promise,q;q=b.defer(function(){try{t.resolve(f.apply(null,m))}catch(b){t.reject(b),e(b)}finally{delete g[n.$$timeoutId]}r||a.$apply()},k);n.$$timeoutId=q;g[q]=t;return n}var g={};
+f.cancel=function(a){return a&&a.$$timeoutId in g?(g[a.$$timeoutId].reject("canceled"),delete g[a.$$timeoutId],b.defer.cancel(a.$$timeoutId)):!1};return f}]}function wa(a){Ha&&(Y.setAttribute("href",a),a=Y.href);Y.setAttribute("href",a);return{href:Y.href,protocol:Y.protocol?Y.protocol.replace(/:$/,""):"",host:Y.host,search:Y.search?Y.search.replace(/^\?/,""):"",hash:Y.hash?Y.hash.replace(/^#/,""):"",hostname:Y.hostname,port:Y.port,pathname:"/"===Y.pathname.charAt(0)?Y.pathname:"/"+Y.pathname}}function ed(a){a=
+E(a)?wa(a):a;return a.protocol===wd.protocol&&a.host===wd.host}function vf(){this.$get=na(S)}function xd(a){function b(a){try{return decodeURIComponent(a)}catch(b){return a}}var d=a[0]||{},c={},e="";return function(){var a,g,h,k,l;a=d.cookie||"";if(a!==e)for(e=a,a=e.split("; "),c={},h=0;h<a.length;h++)g=a[h],k=g.indexOf("="),0<k&&(l=b(g.substring(0,k)),q(c[l])&&(c[l]=b(g.substring(k+1))));return c}}function zf(){this.$get=xd}function Jc(a){function b(d,c){if(H(d)){var e={};n(d,function(a,c){e[c]=
+b(c,a)});return e}return a.factory(d+"Filter",c)}this.register=b;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];b("currency",yd);b("date",zd);b("filter",bg);b("json",cg);b("limitTo",dg);b("lowercase",eg);b("number",Ad);b("orderBy",Bd);b("uppercase",fg)}function bg(){return function(a,b,d){if(!za(a)){if(null==a)return a;throw G("filter")("notarray",a);}var c;switch(hc(b)){case "function":break;case "boolean":case "null":case "number":case "string":c=!0;case "object":b=
+gg(b,d,c);break;default:return a}return Array.prototype.filter.call(a,b)}}function gg(a,b,d){var c=H(a)&&"$"in a;!0===b?b=ma:z(b)||(b=function(a,b){if(q(a))return!1;if(null===a||null===b)return a===b;if(H(b)||H(a)&&!qc(a))return!1;a=F(""+a);b=F(""+b);return-1!==a.indexOf(b)});return function(e){return c&&!H(e)?Ka(e,a.$,b,!1):Ka(e,a,b,d)}}function Ka(a,b,d,c,e){var f=hc(a),g=hc(b);if("string"===g&&"!"===b.charAt(0))return!Ka(a,b.substring(1),d,c);if(I(a))return a.some(function(a){return Ka(a,b,d,c)});
+switch(f){case "object":var h;if(c){for(h in a)if("$"!==h.charAt(0)&&Ka(a[h],b,d,!0))return!0;return e?!1:Ka(a,b,d,!1)}if("object"===g){for(h in b)if(e=b[h],!z(e)&&!q(e)&&(f="$"===h,!Ka(f?a:a[h],e,d,f,f)))return!1;return!0}return d(a,b);case "function":return!1;default:return d(a,b)}}function hc(a){return null===a?"null":typeof a}function yd(a){var b=a.NUMBER_FORMATS;return function(a,c,e){q(c)&&(c=b.CURRENCY_SYM);q(e)&&(e=b.PATTERNS[1].maxFrac);return null==a?a:Cd(a,b.PATTERNS[1],b.GROUP_SEP,b.DECIMAL_SEP,
+e).replace(/\u00A4/g,c)}}function Ad(a){var b=a.NUMBER_FORMATS;return function(a,c){return null==a?a:Cd(a,b.PATTERNS[0],b.GROUP_SEP,b.DECIMAL_SEP,c)}}function Cd(a,b,d,c,e){if(H(a))return"";var f=0>a;a=Math.abs(a);var g=Infinity===a;if(!g&&!isFinite(a))return"";var h=a+"",k="",l=!1,m=[];g&&(k="\u221e");if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?a=0:(k=h,l=!0)}if(g||l)0<e&&1>a&&(k=a.toFixed(e),a=parseFloat(k),k=k.replace(ic,c));else{g=(h.split(ic)[1]||"").length;
+q(e)&&(e=Math.min(Math.max(b.minFrac,g),b.maxFrac));a=+(Math.round(+(a.toString()+"e"+e)).toString()+"e"+-e);var g=(""+a).split(ic),h=g[0],g=g[1]||"",r=0,t=b.lgSize,n=b.gSize;if(h.length>=t+n)for(r=h.length-t,l=0;l<r;l++)0===(r-l)%n&&0!==l&&(k+=d),k+=h.charAt(l);for(l=r;l<h.length;l++)0===(h.length-l)%t&&0!==l&&(k+=d),k+=h.charAt(l);for(;g.length<e;)g+="0";e&&"0"!==e&&(k+=c+g.substr(0,e))}0===a&&(f=!1);m.push(f?b.negPre:b.posPre,k,f?b.negSuf:b.posSuf);return m.join("")}function Gb(a,b,d){var c="";
+0>a&&(c="-",a=-a);for(a=""+a;a.length<b;)a="0"+a;d&&(a=a.substr(a.length-b));return c+a}function ca(a,b,d,c){d=d||0;return function(e){e=e["get"+a]();if(0<d||e>-d)e+=d;0===e&&-12==d&&(e=12);return Gb(e,b,c)}}function Hb(a,b){return function(d,c){var e=d["get"+a](),f=sb(b?"SHORT"+a:a);return c[f][e]}}function Dd(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Ed(a){return function(b){var d=Dd(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-
++d;b=1+Math.round(b/6048E5);return Gb(b,a)}}function jc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function zd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=ea(b[9]+b[10]),g=ea(b[9]+b[11]));h.call(a,ea(b[1]),ea(b[2])-1,ea(b[3]));f=ea(b[4]||0)-f;g=ea(b[5]||0)-g;h=ea(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
+return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;E(c)&&(c=hg.test(c)?ea(c):b(c));Q(c)&&(c=new Date(c));if(!da(c)||!isFinite(c.getTime()))return c;for(;d;)(l=ig.exec(d))?(h=cb(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=vc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));n(h,function(b){k=jg[b];g+=k?k(c,a.DATETIME_FORMATS,m):b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function cg(){return function(a,b){q(b)&&(b=2);return db(a,b)}}function dg(){return function(a,
+b,d){b=Infinity===Math.abs(Number(b))?Number(b):ea(b);if(isNaN(b))return a;Q(a)&&(a=a.toString());if(!I(a)&&!E(a))return a;d=!d||isNaN(d)?0:ea(d);d=0>d?Math.max(0,a.length+d):d;return 0<=b?a.slice(d,d+b):0===d?a.slice(b,a.length):a.slice(Math.max(0,d+b),d)}}function Bd(a){function b(b,d){d=d?-1:1;return b.map(function(b){var c=1,h=Ya;if(z(b))h=b;else if(E(b)){if("+"==b.charAt(0)||"-"==b.charAt(0))c="-"==b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(h=a(b),h.constant))var k=h(),h=function(a){return a[k]}}return{get:h,
+descending:c*d}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(a,e,f){if(!za(a))return a;I(e)||(e=[e]);0===e.length&&(e=["+"]);var g=b(e,f);g.push({get:function(){return{}},descending:f?-1:1});a=Array.prototype.map.call(a,function(a,b){return{value:a,predicateValues:g.map(function(c){var e=c.get(a);c=typeof e;if(null===e)c="string",e="null";else if("string"===c)e=e.toLowerCase();else if("object"===c)a:{if("function"===typeof e.valueOf&&
+(e=e.valueOf(),d(e)))break a;if(qc(e)&&(e=e.toString(),d(e)))break a;e=b}return{value:e,type:c}})}});a.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],f=b.predicateValues[d],n=0;c.type===f.type?c.value!==f.value&&(n=c.value<f.value?-1:1):n=c.type<f.type?-1:1;if(c=n*g[d].descending)break}return c});return a=a.map(function(a){return a.value})}}function La(a){z(a)&&(a={link:a});a.restrict=a.restrict||"AC";return na(a)}function Fd(a,b,d,c,e){var f=this,g=[];f.$error=
+{};f.$$success={};f.$pending=u;f.$name=e(b.name||b.ngForm||"")(d);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;f.$$parentForm=Ib;f.$rollbackViewValue=function(){n(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){n(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a);a.$$parentForm=f};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&
+f[a.$name]===a&&delete f[a.$name];n(f.$pending,function(b,c){f.$setValidity(c,null,a)});n(f.$error,function(b,c){f.$setValidity(c,null,a)});n(f.$$success,function(b,c){f.$setValidity(c,null,a)});ab(g,a);a.$$parentForm=Ib};Gd({ctrl:this,$element:a,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(ab(d,c),0===d.length&&delete a[b])},$animate:c});f.$setDirty=function(){c.removeClass(a,Wa);c.addClass(a,Jb);f.$dirty=!0;f.$pristine=!1;f.$$parentForm.$setDirty()};
+f.$setPristine=function(){c.setClass(a,Wa,Jb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;n(g,function(a){a.$setPristine()})};f.$setUntouched=function(){n(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){c.addClass(a,"ng-submitted");f.$submitted=!0;f.$$parentForm.$setSubmitted()}}function kc(a){a.$formatters.push(function(b){return a.$isEmpty(b)?b:b.toString()})}function jb(a,b,d,c,e,f){var g=F(b[0].type);if(!e.android){var h=!1;b.on("compositionstart",function(a){h=!0});
+b.on("compositionend",function(){h=!1;k()})}var k=function(a){l&&(f.defer.cancel(l),l=null);if(!h){var e=b.val();a=a&&a.type;"password"===g||d.ngTrim&&"false"===d.ngTrim||(e=U(e));(c.$viewValue!==e||""===e&&c.$$hasNativeValidators)&&c.$setViewValue(e,a)}};if(e.hasEvent("input"))b.on("input",k);else{var l,m=function(a,b,c){l||(l=f.defer(function(){l=null;b&&b.value===c||k(a)}))};b.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",
+m)}b.on("change",k);c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Kb(a,b){return function(d,c){var e,f;if(da(d))return d;if(E(d)){'"'==d.charAt(0)&&'"'==d.charAt(d.length-1)&&(d=d.substring(1,d.length-1));if(kg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,
+mm:0,ss:0,sss:0},n(e,function(a,c){c<b.length&&(f[b[c]]=+a)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function kb(a,b,d,c){return function(e,f,g,h,k,l,m){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function n(a){return y(a)&&!da(a)?d(a)||u:a}Hd(e,f,g,h);jb(e,f,g,h,k,l);var A=h&&h.$options&&h.$options.timezone,v;h.$$parserName=a;h.$parsers.push(function(a){return h.$isEmpty(a)?null:b.test(a)?(a=d(a,v),A&&(a=Pb(a,A)),a):u});h.$formatters.push(function(a){if(a&&
+!da(a))throw lb("datefmt",a);if(r(a))return(v=a)&&A&&(v=Pb(v,A,!0)),m("date")(a,c,A);v=null;return""});if(y(g.min)||g.ngMin){var s;h.$validators.min=function(a){return!r(a)||q(s)||d(a)>=s};g.$observe("min",function(a){s=n(a);h.$validate()})}if(y(g.max)||g.ngMax){var p;h.$validators.max=function(a){return!r(a)||q(p)||d(a)<=p};g.$observe("max",function(a){p=n(a);h.$validate()})}}}function Hd(a,b,d,c){(c.$$hasNativeValidators=H(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};
+return c.badInput&&!c.typeMismatch?u:a})}function Id(a,b,d,c,e){if(y(c)){a=a(c);if(!a.constant)throw lb("constexpr",d,c);return a(b)}return e}function lc(a,b){a="ngClass"+a;return["$animate",function(d){function c(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){var b=[];return I(a)?(n(a,function(a){b=b.concat(e(a))}),b):E(a)?a.split(" "):H(a)?(n(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",
+link:function(f,g,h){function k(a,b){var c=g.data("$classCounts")||$(),d=[];n(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function l(a){if(!0===b||f.$index%2===b){var l=e(a||[]);if(!m){var n=k(l,1);h.$addClass(n)}else if(!ma(a,m)){var q=e(m),n=c(l,q),l=c(q,l),n=k(n,1),l=k(l,-1);n&&n.length&&d.addClass(g,n);l&&l.length&&d.removeClass(g,l)}}m=ia(a)}var m;f.$watch(h[a],l,!0);h.$observe("class",function(b){l(f.$eval(h[a]))});"ngClass"!==
+a&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var l=e(f.$eval(h[a]));g===b?(g=k(l,1),h.$addClass(g)):(g=k(l,-1),h.$removeClass(g))}})}}}]}function Gd(a){function b(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function d(a,c){a=a?"-"+zc(a,"-"):"";b(mb+a,!0===c);b(Jd+a,!1===c)}var c=a.ctrl,e=a.$element,f={},g=a.set,h=a.unset,k=a.$animate;f[Jd]=!(f[mb]=e.hasClass(mb));c.$setValidity=function(a,e,f){q(e)?(c.$pending||(c.$pending={}),g(c.$pending,a,f)):(c.$pending&&
+h(c.$pending,a,f),Kd(c.$pending)&&(c.$pending=u));$a(e)?e?(h(c.$error,a,f),g(c.$$success,a,f)):(g(c.$error,a,f),h(c.$$success,a,f)):(h(c.$error,a,f),h(c.$$success,a,f));c.$pending?(b(Ld,!0),c.$valid=c.$invalid=u,d("",null)):(b(Ld,!1),c.$valid=Kd(c.$error),c.$invalid=!c.$valid,d("",c.$valid));e=c.$pending&&c.$pending[a]?u:c.$error[a]?!1:c.$$success[a]?!0:null;d(a,e);c.$$parentForm.$setValidity(a,e,c)}}function Kd(a){if(a)for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}var lg=/^\/(.+)\/([a-z]*)$/,
+F=function(a){return E(a)?a.toLowerCase():a},qa=Object.prototype.hasOwnProperty,sb=function(a){return E(a)?a.toUpperCase():a},Ha,B,oa,ra=[].slice,Pf=[].splice,mg=[].push,sa=Object.prototype.toString,rc=Object.getPrototypeOf,Aa=G("ng"),fa=S.angular||(S.angular={}),Sb,nb=0;Ha=X.documentMode;x.$inject=[];Ya.$inject=[];var I=Array.isArray,Vd=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,U=function(a){return E(a)?a.trim():a},ud=function(a){return a.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,
+"\\$1").replace(/\x08/g,"\\x08")},Ba=function(){if(!y(Ba.rules)){var a=X.querySelector("[ng-csp]")||X.querySelector("[data-ng-csp]");if(a){var b=a.getAttribute("ng-csp")||a.getAttribute("data-ng-csp");Ba.rules={noUnsafeEval:!b||-1!==b.indexOf("no-unsafe-eval"),noInlineStyle:!b||-1!==b.indexOf("no-inline-style")}}else{a=Ba;try{new Function(""),b=!1}catch(d){b=!0}a.rules={noUnsafeEval:b,noInlineStyle:!1}}}return Ba.rules},pb=function(){if(y(pb.name_))return pb.name_;var a,b,d=Oa.length,c,e;for(b=0;b<
+d;++b)if(c=Oa[b],a=X.querySelector("["+c.replace(":","\\:")+"jq]")){e=a.getAttribute(c+"jq");break}return pb.name_=e},Oa=["ng-","data-ng-","ng:","x-ng-"],be=/[A-Z]/g,Ac=!1,Rb,Na=3,fe={full:"1.4.8",major:1,minor:4,dot:8,codeName:"ice-manipulation"};N.expando="ng339";var gb=N.cache={},Ff=1;N._data=function(a){return this.cache[a[this.expando]]||{}};var Af=/([\:\-\_]+(.))/g,Bf=/^moz([A-Z])/,xb={mouseleave:"mouseout",mouseenter:"mouseover"},Ub=G("jqLite"),Ef=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,
+Cf=/<([\w:-]+)/,Df=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,ka={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option;ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead;ka.th=ka.td;var Kf=Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&
+16)},Pa=N.prototype={ready:function(a){function b(){d||(d=!0,a())}var d=!1;"complete"===X.readyState?setTimeout(b):(this.on("DOMContentLoaded",b),N(S).on("load",b))},toString:function(){var a=[];n(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?B(this[a]):B(this[this.length+a])},length:0,push:mg,sort:[].sort,splice:[].splice},Cb={};n("multiple selected checked disabled readOnly required open".split(" "),function(a){Cb[F(a)]=a});var Rc={};n("input select option textarea button form details".split(" "),
+function(a){Rc[a]=!0});var Zc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};n({data:Wb,removeData:vb,hasData:function(a){for(var b in gb[a.ng339])return!0;return!1}},function(a,b){N[b]=a});n({data:Wb,inheritedData:Bb,scope:function(a){return B.data(a,"$scope")||Bb(a.parentNode||a,["$isolateScope","$scope"])},isolateScope:function(a){return B.data(a,"$isolateScope")||B.data(a,"$isolateScopeNoTemplate")},controller:Oc,injector:function(a){return Bb(a,
+"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:yb,css:function(a,b,d){b=fb(b);if(y(d))a.style[b]=d;else return a.style[b]},attr:function(a,b,d){var c=a.nodeType;if(c!==Na&&2!==c&&8!==c)if(c=F(b),Cb[c])if(y(d))d?(a[b]=!0,a.setAttribute(b,c)):(a[b]=!1,a.removeAttribute(c));else return a[b]||(a.attributes.getNamedItem(b)||x).specified?c:u;else if(y(d))a.setAttribute(b,d);else if(a.getAttribute)return a=a.getAttribute(b,2),null===a?u:a},prop:function(a,b,d){if(y(d))a[b]=d;else return a[b]},
+text:function(){function a(a,d){if(q(d)){var c=a.nodeType;return 1===c||c===Na?a.textContent:""}a.textContent=d}a.$dv="";return a}(),val:function(a,b){if(q(b)){if(a.multiple&&"select"===ta(a)){var d=[];n(a.options,function(a){a.selected&&d.push(a.value||a.text)});return 0===d.length?null:d}return a.value}a.value=b},html:function(a,b){if(q(b))return a.innerHTML;ub(a,!0);a.innerHTML=b},empty:Pc},function(a,b){N.prototype[b]=function(b,c){var e,f,g=this.length;if(a!==Pc&&q(2==a.length&&a!==yb&&a!==Oc?
+b:c)){if(H(b)){for(e=0;e<g;e++)if(a===Wb)a(this[e],b);else for(f in b)a(this[e],f,b[f]);return this}e=a.$dv;g=q(e)?Math.min(g,1):g;for(f=0;f<g;f++){var h=a(this[f],b,c);e=e?e+h:h}return e}for(e=0;e<g;e++)a(this[e],b,c);return this}});n({removeData:vb,on:function(a,b,d,c){if(y(c))throw Ub("onargs");if(Kc(a)){c=wb(a,!0);var e=c.events,f=c.handle;f||(f=c.handle=Hf(a,e));c=0<=b.indexOf(" ")?b.split(" "):[b];for(var g=c.length,h=function(b,c,g){var h=e[b];h||(h=e[b]=[],h.specialHandlerWrapper=c,"$destroy"===
+b||g||a.addEventListener(b,f,!1));h.push(d)};g--;)b=c[g],xb[b]?(h(xb[b],Jf),h(b,u,!0)):h(b)}},off:Nc,one:function(a,b,d){a=B(a);a.on(b,function e(){a.off(b,d);a.off(b,e)});a.on(b,d)},replaceWith:function(a,b){var d,c=a.parentNode;ub(a);n(new N(b),function(b){d?c.insertBefore(b,d.nextSibling):c.replaceChild(b,a);d=b})},children:function(a){var b=[];n(a.childNodes,function(a){1===a.nodeType&&b.push(a)});return b},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,b){var d=
+a.nodeType;if(1===d||11===d){b=new N(b);for(var d=0,c=b.length;d<c;d++)a.appendChild(b[d])}},prepend:function(a,b){if(1===a.nodeType){var d=a.firstChild;n(new N(b),function(b){a.insertBefore(b,d)})}},wrap:function(a,b){b=B(b).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(b,a);b.appendChild(a)},remove:Xb,detach:function(a){Xb(a,!0)},after:function(a,b){var d=a,c=a.parentNode;b=new N(b);for(var e=0,f=b.length;e<f;e++){var g=b[e];c.insertBefore(g,d.nextSibling);d=g}},addClass:Ab,removeClass:zb,
+toggleClass:function(a,b,d){b&&n(b.split(" "),function(b){var e=d;q(e)&&(e=!yb(a,b));(e?Ab:zb)(a,b)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,b){return a.getElementsByTagName?a.getElementsByTagName(b):[]},clone:Vb,triggerHandler:function(a,b,d){var c,e,f=b.type||b,g=wb(a);if(g=(g=g&&g.events)&&g[f])c={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},
+stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:x,type:f,target:a},b.type&&(c=M(c,b)),b=ia(g),e=d?[c].concat(d):[c],n(b,function(b){c.isImmediatePropagationStopped()||b.apply(a,e)})}},function(a,b){N.prototype[b]=function(b,c,e){for(var f,g=0,h=this.length;g<h;g++)q(f)?(f=a(this[g],b,c,e),y(f)&&(f=B(f))):Mc(f,a(this[g],b,c,e));return y(f)?f:this};N.prototype.bind=N.prototype.on;
+N.prototype.unbind=N.prototype.off});Sa.prototype={put:function(a,b){this[Ca(a,this.nextUid)]=b},get:function(a){return this[Ca(a,this.nextUid)]},remove:function(a){var b=this[a=Ca(a,this.nextUid)];delete this[a];return b}};var yf=[function(){this.$get=[function(){return Sa}]}],Tc=/^[^\(]*\(\s*([^\)]*)\)/m,ng=/,/,og=/^\s*(_?)(\S+?)\1\s*$/,Sc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Da=G("$injector");eb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw E(d)&&
+d||(d=a.name||Lf(a)),Da("strictdi",d);b=a.toString().replace(Sc,"");b=b.match(Tc);n(b[1].split(ng),function(a){a.replace(og,function(a,b,d){c.push(d)})})}a.$inject=c}}else I(a)?(b=a.length-1,Qa(a[b],"fn"),c=a.slice(0,b)):Qa(a,"fn",!0);return c};var Md=G("$animate"),Ue=function(){this.$get=["$q","$$rAF",function(a,b){function d(){}d.all=x;d.chain=x;d.prototype={end:x,cancel:x,resume:x,pause:x,complete:x,then:function(c,d){return a(function(a){b(function(){a()})}).then(c,d)}};return d}]},Te=function(){var a=
+new Sa,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=E(b)?b.split(" "):I(b)?b:[],n(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){n(b,function(b){var c=a.get(b);if(c){var d=Mf(b.attr("class")),e="",f="";n(c,function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});n(b,function(a){e&&Ab(a,e);f&&zb(a,f)});a.remove(b)}});b.length=0}return{enabled:x,on:x,off:x,pin:x,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);
+k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.put(g,k),b.push(g),1===b.length&&c.$$postDigest(f);return new d}}}]},Re=["$provide",function(a){var b=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,c){if(d&&"."!==d.charAt(0))throw Md("notcsel",d);var e=d+"-animation";b.$$registeredAnimations[d.substr(1)]=e;a.factory(e,c)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=
+a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Md("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var h;a:{for(h=0;h<d.length;h++){var k=d[h];if(1===k.nodeType){h=k;break a}}h=void 0}!h||h.parentNode||h.previousElementSibling||(d=null)}d?d.after(a):c.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(e,f,g,h){f=
+f&&B(f);g=g&&B(g);f=f||g.parent();b(e,f,g);return a.push(e,"enter",Ea(h))},move:function(e,f,g,h){f=f&&B(f);g=g&&B(g);f=f||g.parent();b(e,f,g);return a.push(e,"move",Ea(h))},leave:function(b,c){return a.push(b,"leave",Ea(c),function(){b.remove()})},addClass:function(b,c,g){g=Ea(g);g.addClass=hb(g.addclass,c);return a.push(b,"addClass",g)},removeClass:function(b,c,g){g=Ea(g);g.removeClass=hb(g.removeClass,c);return a.push(b,"removeClass",g)},setClass:function(b,c,g,h){h=Ea(h);h.addClass=hb(h.addClass,
+c);h.removeClass=hb(h.removeClass,g);return a.push(b,"setClass",h)},animate:function(b,c,g,h,k){k=Ea(k);k.from=k.from?M(k.from,c):c;k.to=k.to?M(k.to,g):g;k.tempClasses=hb(k.tempClasses,h||"ng-inline-animate");return a.push(b,"animate",k)}}}]}],Se=function(){this.$get=["$$rAF","$q",function(a,b){var d=function(){};d.prototype={done:function(a){this.defer&&this.defer[!0===a?"reject":"resolve"]()},end:function(){this.done()},cancel:function(){this.done(!0)},getPromise:function(){this.defer||(this.defer=
+b.defer());return this.defer.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)}};return function(b,e){function f(){a(function(){e.addClass&&(b.addClass(e.addClass),e.addClass=null);e.removeClass&&(b.removeClass(e.removeClass),e.removeClass=null);e.to&&(b.css(e.to),e.to=null);g||h.done();g=!0});return h}e.cleanupStyles&&(e.from=e.to=null);e.from&&(b.css(e.from),e.from=
+null);var g,h=new d;return{start:f,end:f}}}]},ha=G("$compile");Cc.$inject=["$provide","$$sanitizeUriProvider"];var Vc=/^((?:x|data)[\:\-_])/i,Qf=G("$controller"),Uc=/^(\S+)(\s+as\s+(\w+))?$/,$e=function(){this.$get=["$document",function(a){return function(b){b?!b.nodeType&&b instanceof B&&(b=b[0]):b=a[0].body;return b.offsetWidth+1}}]},$c="application/json",ac={"Content-Type":$c+";charset=utf-8"},Sf=/^\[|^\{(?!\{)/,Tf={"[":/]$/,"{":/}$/},Rf=/^\)\]\}',?\n/,pg=G("$http"),dd=function(a){return function(){throw pg("legacy",
+a);}},Ja=fa.$interpolateMinErr=G("$interpolate");Ja.throwNoconcat=function(a){throw Ja("noconcat",a);};Ja.interr=function(a,b){return Ja("interr",a,b.toString())};var qg=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,Vf={http:80,https:443,ftp:21},Db=G("$location"),rg={$$html5:!1,$$replace:!1,absUrl:Eb("$$absUrl"),url:function(a){if(q(a))return this.$$url;var b=qg.exec(a);(b[1]||""===a)&&this.path(decodeURIComponent(b[1]));(b[2]||b[1]||""===a)&&this.search(b[3]||"");this.hash(b[5]||"");return this},protocol:Eb("$$protocol"),
+host:Eb("$$host"),port:Eb("$$port"),path:id("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,b){switch(arguments.length){case 0:return this.$$search;case 1:if(E(a)||Q(a))a=a.toString(),this.$$search=xc(a);else if(H(a))a=bb(a,{}),n(a,function(b,c){null==b&&delete a[c]}),this.$$search=a;else throw Db("isrcharg");break;default:q(b)||null===b?delete this.$$search[a]:this.$$search[a]=b}this.$$compose();return this},hash:id("$$hash",function(a){return null!==
+a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};n([hd,dc,cc],function(a){a.prototype=Object.create(rg);a.prototype.state=function(b){if(!arguments.length)return this.$$state;if(a!==cc||!this.$$html5)throw Db("nostate");this.$$state=q(b)?null:b;return this}});var ba=G("$parse"),Wf=Function.prototype.call,Xf=Function.prototype.apply,Yf=Function.prototype.bind,Lb=$();n("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Lb[a]=!0});var sg={n:"\n",f:"\f",r:"\r",
+t:"\t",v:"\v","'":"'",'"':'"'},fc=function(a){this.options=a};fc.prototype={constructor:fc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;
+else{var b=a+this.peek(),d=b+this.peek(2),c=Lb[b],e=Lb[d];Lb[a]||c||e?(a=e?d:c?b:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,b){return-1!==b.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||
+"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=y(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw ba("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index<this.text.length;){var d=F(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var c=this.peek();
+if("e"==d&&this.isExpOperator(c))a+=d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||c&&this.isNumber(c)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var b=this.text.charAt(this.index);if(!this.isIdent(b)&&!this.isNumber(b))break;this.index++}this.tokens.push({index:a,
+text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;for(var d="",c=a,e=!1;this.index<this.text.length;){var f=this.text.charAt(this.index),c=c+f;if(e)"u"===f?(e=this.text.substring(this.index+1,this.index+5),e.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+e+"]"),this.index+=4,d+=String.fromCharCode(parseInt(e,16))):d+=sg[f]||f,e=!1;else if("\\"===f)e=!0;else{if(f===a){this.index++;this.tokens.push({index:b,text:c,constant:!0,
+value:d});return}d+=f}this.index++}this.throwError("Unterminated quote",b)}};var s=function(a,b){this.lexer=a;this.options=b};s.Program="Program";s.ExpressionStatement="ExpressionStatement";s.AssignmentExpression="AssignmentExpression";s.ConditionalExpression="ConditionalExpression";s.LogicalExpression="LogicalExpression";s.BinaryExpression="BinaryExpression";s.UnaryExpression="UnaryExpression";s.CallExpression="CallExpression";s.MemberExpression="MemberExpression";s.Identifier="Identifier";s.Literal=
+"Literal";s.ArrayExpression="ArrayExpression";s.Property="Property";s.ObjectExpression="ObjectExpression";s.ThisExpression="ThisExpression";s.NGValueParameter="NGValueParameter";s.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:s.Program,
+body:a}},expressionStatement:function(){return{type:s.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:s.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),b,d;return this.expect("?")&&(b=this.expression(),this.consume(":"))?
+(d=this.expression(),{type:s.ConditionalExpression,test:a,alternate:b,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:s.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:s.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),b;b=this.expect("==","!=","===","!==");)a={type:s.BinaryExpression,
+operator:b.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),b;b=this.expect("<",">","<=",">=");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:s.BinaryExpression,operator:b.text,
+left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:s.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=bb(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():
+this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:s.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===b.text?(a={type:s.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:s.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:s.CallExpression,callee:this.identifier(),
+arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:s.Identifier,name:a.text}},constant:function(){return{type:s.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;
+a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:s.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;b={type:s.Property,kind:"init"};this.peek().constant?b.key=this.constant():this.peek().identifier?b.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");b.value=this.expression();a.push(b)}while(this.expect(","))}this.consume("}");return{type:s.ObjectExpression,properties:a}},
+throwError:function(a,b){throw ba("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw ba("ueoe",this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw ba("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>a){a=this.tokens[a];
+var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},constants:{"true":{type:s.Literal,value:!0},"false":{type:s.Literal,value:!1},"null":{type:s.Literal,value:null},undefined:{type:s.Literal,value:u},"this":{type:s.ThisExpression}}};rd.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],
+body:[],own:{}},inputs:[]};W(c,d.$filter);var e="",f;this.stage="assign";if(f=pd(c))this.state.computing="assign",e=this.nextId(),this.recurse(f,e),this.return_(e),e="fn.assign="+this.generateFunction("assign","s,v,l");f=nd(c.body);d.stage="inputs";n(f,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}};d.state.computing=c;var e=d.nextId();d.recurse(a,e);d.return_(e);d.state.inputs.push(c);a.watchId=b});this.state.computing="fn";this.stage="main";this.recurse(c);e='"'+this.USE+" "+this.STRICT+
+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+e+this.watchFns()+"return fn;";e=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",e))(this.$filter,Va,xa,kd,jd,ld,Zf,md,a);this.state=this.stage=u;e.literal=qd(c);e.constant=c.constant;return e},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;n(b,function(b){a.push("var "+b+"="+d.generateFunction(b,
+"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];");return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;n(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,
+d,c,e,f){var g,h,k=this,l,m;c=c||x;if(!f&&y(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case s.Program:n(a.body,function(b,c){k.recurse(b.expression,u,u,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case s.Literal:m=this.escape(a.value);this.assign(b,m);c(m);break;case s.UnaryExpression:this.recurse(a.argument,u,u,function(a){h=a});m=a.operator+"("+this.ifDefined(h,
+0)+")";this.assign(b,m);c(m);break;case s.BinaryExpression:this.recurse(a.left,u,u,function(a){g=a});this.recurse(a.right,u,u,function(a){h=a});m="+"===a.operator?this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case s.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right,b));c(b);break;case s.ConditionalExpression:b=b||this.nextId();k.recurse(a.test,
+b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case s.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Va(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s",
+a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(b);c(b);break;case s.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,u,function(){k.if_(k.notNull(g),function(){if(a.computed)h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),k.addEnsureSafeMemberName(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g,h),"{}")),m=k.ensureSafeObject(k.computedMember(g,
+h)),k.assign(b,m),d&&(d.computed=!0,d.name=h);else{Va(a.property.name);e&&1!==e&&k.if_(k.not(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}"));m=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))m=k.ensureSafeObject(m);k.assign(b,m);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(b,"undefined")});c(b)},!!e);break;case s.CallExpression:b=b||this.nextId();a.filter?(h=k.filter(a.callee.name),l=[],n(a.arguments,
+function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+l.join(",")+")",k.assign(b,m),c(b)):(h=k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){k.addEnsureSafeFunction(h);n(a.arguments,function(a){k.recurse(a,k.nextId(),u,function(a){l.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),m=k.member(g.context,g.name,g.computed)+"("+l.join(",")+")"):m=h+"("+l.join(",")+")";m=k.ensureSafeObject(m);k.assign(b,m)},
+function(){k.assign(b,"undefined")});c(b)}));break;case s.AssignmentExpression:h=this.nextId();g={};if(!od(a.left))throw ba("lval");this.recurse(a.left,u,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);m=k.member(g.context,g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case s.ArrayExpression:l=[];n(a.elements,function(a){k.recurse(a,k.nextId(),u,function(a){l.push(a)})});
+m="["+l.join(",")+"]";this.assign(b,m);c(m);break;case s.ObjectExpression:l=[];n(a.properties,function(a){k.recurse(a.value,k.nextId(),u,function(b){l.push(k.escape(a.key.type===s.Identifier?a.key.name:""+a.key.value)+":"+b)})});m="{"+l.join(",")+"}";this.assign(b,m);c(m);break;case s.ThisExpression:this.assign(b,"s");c("s");break;case s.NGValueParameter:this.assign(b,"v"),c("v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+
+this.escape(b)+" in "+a+")"));return c[d]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,
+"){");b();c.push("}");d&&(c.push("else{"),d(),c.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){return a+"."+b},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},
+addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+",text)")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+
+a+",text)"},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(E(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(Q(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===
+typeof a)return"undefined";throw ba("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=b;W(c,d.$filter);var e,f;if(e=pd(c))f=this.recurse(e);e=nd(c.body);var g;e&&(g=[],n(e,function(a,b){var c=d.recurse(a);a.input=c;g.push(c);a.watchId=b}));var h=[];n(c.body,function(a){h.push(d.recurse(a.expression))});
+e=0===c.body.length?function(){}:1===c.body.length?h[0]:function(a,b){var c;n(h,function(d){c=d(a,b)});return c};f&&(e.assign=function(a,b,c){return f(a,c,b)});g&&(e.inputs=g);e.literal=qd(c);e.constant=c.constant;return e},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case s.Literal:return this.value(a.value,b);case s.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case s.BinaryExpression:return c=this.recurse(a.left),
+e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case s.Identifier:return Va(a.name,f.expression),f.identifier(a.name,f.expensiveChecks||Fb(a.name),b,d,f.expression);case s.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(Va(a.property.name,
+f.expression),e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d,f.expression):this.nonComputedMember(c,e,f.expensiveChecks,b,d,f.expression);case s.CallExpression:return g=[],n(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var r=[],n=0;n<g.length;++n)r.push(g[n](a,c,d,f));a=e.apply(u,r,f);return b?{context:u,name:u,value:a}:a}:function(a,
+c,d,m){var r=e(a,c,d,m),n;if(null!=r.value){xa(r.context,f.expression);kd(r.value,f.expression);n=[];for(var q=0;q<g.length;++q)n.push(xa(g[q](a,c,d,m),f.expression));n=xa(r.value.apply(r.context,n),f.expression)}return b?{value:n}:n};case s.AssignmentExpression:return c=this.recurse(a.left,!0,1),e=this.recurse(a.right),function(a,d,g,m){var n=c(a,d,g,m);a=e(a,d,g,m);xa(n.value,f.expression);ld(n.context);n.context[n.name]=a;return b?{value:a}:a};case s.ArrayExpression:return g=[],n(a.elements,function(a){g.push(f.recurse(a))}),
+function(a,c,d,e){for(var f=[],n=0;n<g.length;++n)f.push(g[n](a,c,d,e));return b?{value:f}:f};case s.ObjectExpression:return g=[],n(a.properties,function(a){g.push({key:a.key.type===s.Identifier?a.key.name:""+a.key.value,value:f.recurse(a.value)})}),function(a,c,d,e){for(var f={},n=0;n<g.length;++n)f[g[n].key]=g[n].value(a,c,d,e);return b?{value:f}:f};case s.ThisExpression:return function(a){return b?{value:a}:a};case s.NGValueParameter:return function(a,c,d,e){return b?{value:d}:d}}},"unary+":function(a,
+b){return function(d,c,e,f){d=a(d,c,e,f);d=y(d)?+d:0;return b?{value:d}:d}},"unary-":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=y(d)?-d:0;return b?{value:d}:d}},"unary!":function(a,b){return function(d,c,e,f){d=!a(d,c,e,f);return b?{value:d}:d}},"binary+":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=md(h,c);return d?{value:h}:h}},"binary-":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=(y(h)?h:0)-(y(c)?c:0);return d?{value:h}:h}},"binary*":function(a,
+b,d){return function(c,e,f,g){c=a(c,e,f,g)*b(c,e,f,g);return d?{value:c}:c}},"binary/":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)/b(c,e,f,g);return d?{value:c}:c}},"binary%":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)%b(c,e,f,g);return d?{value:c}:c}},"binary===":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)===b(c,e,f,g);return d?{value:c}:c}},"binary!==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!==b(c,e,f,g);return d?{value:c}:c}},"binary==":function(a,b,
+d){return function(c,e,f,g){c=a(c,e,f,g)==b(c,e,f,g);return d?{value:c}:c}},"binary!=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!=b(c,e,f,g);return d?{value:c}:c}},"binary<":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<b(c,e,f,g);return d?{value:c}:c}},"binary>":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,
+e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:u,name:u,value:a}:a}},identifier:function(a,b,d,c,e){return function(f,g,h,k){f=
+g&&a in g?g:f;c&&1!==c&&f&&!f[a]&&(f[a]={});g=f?f[a]:u;b&&xa(g,e);return d?{context:f,name:a,value:g}:g}},computedMember:function(a,b,d,c,e){return function(f,g,h,k){var l=a(f,g,h,k),m,n;null!=l&&(m=b(f,g,h,k),m=jd(m),Va(m,e),c&&1!==c&&l&&!l[m]&&(l[m]={}),n=l[m],xa(n,e));return d?{context:l,name:m,value:n}:n}},nonComputedMember:function(a,b,d,c,e,f){return function(g,h,k,l){g=a(g,h,k,l);e&&1!==e&&g&&!g[b]&&(g[b]={});h=null!=g?g[b]:u;(d||Fb(b))&&xa(h,f);return c?{context:g,name:b,value:h}:h}},inputs:function(a,
+b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};var gc=function(a,b,d){this.lexer=a;this.$filter=b;this.options=d;this.ast=new s(this.lexer);this.astCompiler=d.csp?new sd(this.ast,b):new rd(this.ast,b)};gc.prototype={constructor:gc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};$();$();var $f=Object.prototype.valueOf,ya=G("$sce"),la={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ha=G("$compile"),Y=X.createElement("a"),wd=wa(S.location.href);
+xd.$inject=["$document"];Jc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var ic=".",jg={yyyy:ca("FullYear",4),yy:ca("FullYear",2,0,!0),y:ca("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:ca("Month",2,1),M:ca("Month",1,1),dd:ca("Date",2),d:ca("Date",1),HH:ca("Hours",2),H:ca("Hours",1),hh:ca("Hours",2,-12),h:ca("Hours",1,-12),mm:ca("Minutes",2),m:ca("Minutes",1),ss:ca("Seconds",2),s:ca("Seconds",1),sss:ca("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,b){return 12>
+a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0<a?"floor":"ceil"](a/60),2)+Gb(Math.abs(a%60),2))},ww:Ed(2),w:Ed(1),G:jc,GG:jc,GGG:jc,GGGG:function(a,b){return 0>=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},ig=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,hg=/^\-?\d+$/;zd.$inject=["$locale"];var eg=na(F),fg=na(sb);Bd.$inject=["$parse"];var he=na({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,
+b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===sa.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),tb={};n(Cb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!=a){var c=va("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,e)});tb[c]=function(){return{restrict:"A",priority:100,link:e}}}});n(Zc,function(a,b){tb[b]=function(){return{priority:100,link:function(a,
+c,e){if("ngPattern"===b&&"/"==e.ngPattern.charAt(0)&&(c=e.ngPattern.match(lg))){e.$set("ngPattern",new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});n(["src","srcset","href"],function(a){var b=va("ng-"+a);tb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(c.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),Ha&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});
+var Ib={$addControl:x,$$renameControl:function(a,b){a.$name=b},$removeControl:x,$setValidity:x,$setDirty:x,$setPristine:x,$setSubmitted:x};Fd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Nd=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||x}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Fd,compile:function(d,f){d.addClass(Wa).addClass(mb);var g=f.name?"name":a&&f.ngForm?"ngForm":
+!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var q=function(b){a.$apply(function(){n.$commitViewValue();n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",q,!1);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",q,!1)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var s=g?c(n.$name):x;g&&(s(a,n),e.$observe(g,function(b){n.$name!==b&&(s(a,u),n.$$parentForm.$$renameControl(n,b),s=c(n.$name),s(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);
+s(a,u);M(n,Ib)})}}}}}]},ie=Nd(),ve=Nd(!0),kg=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,tg=/^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/,ug=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,vg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Od=/^(\d{4})-(\d{2})-(\d{2})$/,Pd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Qd=/^(\d{4})-(\d\d)$/,
+Rd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Sd={text:function(a,b,d,c,e,f){jb(a,b,d,c,e,f);kc(c)},date:kb("date",Od,Kb(Od,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":kb("datetimelocal",Pd,Kb(Pd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:kb("time",Rd,Kb(Rd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:kb("week",mc,function(a,b){if(da(a))return a;if(E(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Dd(c),e=7*(e-1);b&&(d=b.getHours(),f=
+b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:kb("month",Qd,Kb(Qd,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Hd(a,b,d,c);jb(a,b,d,c,e,f);c.$$parserName="number";c.$parsers.push(function(a){return c.$isEmpty(a)?null:vg.test(a)?parseFloat(a):u});c.$formatters.push(function(a){if(!c.$isEmpty(a)){if(!Q(a))throw lb("numfmt",a);a=a.toString()}return a});if(y(d.min)||d.ngMin){var g;c.$validators.min=function(a){return c.$isEmpty(a)||
+q(g)||a>=g};d.$observe("min",function(a){y(a)&&!Q(a)&&(a=parseFloat(a,10));g=Q(a)&&!isNaN(a)?a:u;c.$validate()})}if(y(d.max)||d.ngMax){var h;c.$validators.max=function(a){return c.$isEmpty(a)||q(h)||a<=h};d.$observe("max",function(a){y(a)&&!Q(a)&&(a=parseFloat(a,10));h=Q(a)&&!isNaN(a)?a:u;c.$validate()})}},url:function(a,b,d,c,e,f){jb(a,b,d,c,e,f);kc(c);c.$$parserName="url";c.$validators.url=function(a,b){var d=a||b;return c.$isEmpty(d)||tg.test(d)}},email:function(a,b,d,c,e,f){jb(a,b,d,c,e,f);kc(c);
+c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||ug.test(d)}},radio:function(a,b,d,c){q(d.name)&&b.attr("name",++nb);b.on("click",function(a){b[0].checked&&c.$setViewValue(d.value,a&&a.type)});c.$render=function(){b[0].checked=d.value==c.$viewValue};d.$observe("value",c.$render)},checkbox:function(a,b,d,c,e,f,g,h){var k=Id(h,a,"ngTrueValue",d.ngTrueValue,!0),l=Id(h,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&
+a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return ma(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:x,button:x,submit:x,reset:x,file:x},Dc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Sd[F(g.type)]||Sd.text)(e,f,g,h[0],b,a,d,c)}}}}],wg=/^(true|false|\d+)$/,Ne=function(){return{restrict:"A",priority:100,compile:function(a,
+b){return wg.test(b.ngValue)?function(a,b,e){e.$set("value",a.$eval(e.ngValue))}:function(a,b,e){a.$watch(e.ngValue,function(a){e.$set("value",a)})}}}},ne=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=q(a)?"":a})}}}}],pe=["$interpolate","$compile",function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));
+b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=q(a)?"":a})}}}}],oe=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){c.html(a.getTrustedHtml(f(b))||"")})}}}}],Me=na({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
+qe=lc("",!0),se=lc("Odd",0),re=lc("Even",1),te=La({compile:function(a,b){b.$set("ngCloak",u);a.removeClass("ng-cloak")}}),ue=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Ic={},xg={blur:!0,focus:!0};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var b=va("ng-"+a);Ic[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=
+d(f[b],null,!0);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};xg[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var xe=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(b,d,c,e,f){var g,h,k;b.$watch(c.ngIf,function(b){b?h||f(function(b,e){h=e;b[b.length++]=X.createComment(" end ngIf: "+c.ngIf+" ");g={clone:b};a.enter(b,d.parent(),d)}):(k&&(k.remove(),k=null),h&&(h.$destroy(),h=null),g&&(k=
+rb(g.clone),a.leave(k).then(function(){k=null}),g=null))})}}}],ye=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:fa.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,q){var s=0,v,u,p,C=function(){u&&(u.remove(),u=null);v&&(v.$destroy(),v=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};c.$watch(f,function(f){var m=function(){!y(h)||h&&!c.$eval(h)||
+b()},u=++s;f?(a(f,!0).then(function(a){if(u===s){var b=c.$new();n.template=a;a=q(b,function(a){C();d.enter(a,null,e).then(m)});v=b;p=a;v.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){u===s&&(C(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(C(),n.template=null)})}}}}],Pe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(b,d,c,e){/SVG/.test(d[0].toString())?(d.empty(),a(Lc(e.template,X).childNodes)(b,function(a){d.append(a)},
+{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],ze=La({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),Le=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=b.attr(d.$attr.ngList)||", ",f="false"!==d.ngTrim,g=f?U(e):e;c.$parsers.push(function(a){if(!q(a)){var b=[];a&&n(a.split(g),function(a){a&&b.push(f?U(a):a)});return b}});c.$formatters.push(function(a){return I(a)?a.join(e):u});c.$isEmpty=function(a){return!a||
+!a.length}}}},mb="ng-valid",Jd="ng-invalid",Wa="ng-pristine",Jb="ng-dirty",Ld="ng-pending",lb=G("ngModel"),yg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,c,e,f,g,h,k,l){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=u;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;
+this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=u;this.$name=l(d.name||"",!1)(a);this.$$parentForm=Ib;var m=e(d.ngModel),r=m.assign,t=m,s=r,v=null,B,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var b=e(d.ngModel+"()"),f=e(d.ngModel+"($$$p)");t=function(a){var c=m(a);z(c)&&(c=b(a));return c};s=function(a,b){z(m(a))?f(a,{$$$p:p.$modelValue}):r(a,p.$modelValue)}}else if(!m.assign)throw lb("nonassign",d.ngModel,ua(c));};this.$render=x;this.$isEmpty=
+function(a){return q(a)||""===a||null===a||a!==a};var C=0;Gd({ctrl:this,$element:c,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:f});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;f.removeClass(c,Jb);f.addClass(c,Wa)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;f.removeClass(c,Wa);f.addClass(c,Jb);p.$$parentForm.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;f.setClass(c,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=
+!0;p.$untouched=!1;f.setClass(c,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){g.cancel(v);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!Q(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,b=p.$valid,c=p.$modelValue,d=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(e){d||b===e||(p.$modelValue=e?a:u,p.$modelValue!==c&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,b,c){function d(){var c=
+!0;n(p.$validators,function(d,e){var g=d(a,b);c=c&&g;f(e,g)});return c?!0:(n(p.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;n(p.$asyncValidators,function(e,g){var h=e(a,b);if(!h||!z(h.then))throw lb("$asyncValidators",h);f(g,u);c.push(h.then(function(){f(g,!0)},function(a){d=!1;f(g,!1)}))});c.length?k.all(c).then(function(){g(d)},x):g(!0)}function f(a,b){h===C&&p.$setValidity(a,b)}function g(a){h===C&&c(a)}C++;var h=C;(function(){var a=p.$$parserName||"parse";if(q(B))f(a,
+null);else return B||(n(p.$validators,function(a,b){f(b,null)}),n(p.$asyncValidators,function(a,b){f(b,null)})),f(a,B),B;return!0})()?d()?e():g(!1):g(!1)};this.$commitViewValue=function(){var a=p.$viewValue;g.cancel(v);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var b=p.$$lastCommittedViewValue;if(B=q(b)?u:!0)for(var c=0;c<p.$parsers.length;c++)if(b=p.$parsers[c](b),
+q(b)){B=!1;break}Q(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=t(a));var d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=b;e&&(p.$modelValue=b,p.$modelValue!==d&&p.$$writeModelToScope());p.$$runValidators(b,p.$$lastCommittedViewValue,function(a){e||(p.$modelValue=a?b:u,p.$modelValue!==d&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){s(a,p.$modelValue);n(p.$viewChangeListeners,function(a){try{a()}catch(c){b(c)}})};this.$setViewValue=function(a,b){p.$viewValue=
+a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(b)};this.$$debounceViewValueCommit=function(b){var c=0,d=p.$options;d&&y(d.debounce)&&(d=d.debounce,Q(d)?c=d:Q(d[b])?c=d[b]:Q(d["default"])&&(c=d["default"]));g.cancel(v);c?v=g(function(){p.$commitViewValue()},c):h.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var b=t(a);if(b!==p.$modelValue&&(p.$modelValue===p.$modelValue||b===b)){p.$modelValue=p.$$rawModelValue=b;B=u;for(var c=p.$formatters,
+d=c.length,e=b;d--;)e=c[d](e);p.$viewValue!==e&&(p.$viewValue=p.$$lastCommittedViewValue=e,p.$render(),p.$$runValidators(b,e,x))}return b})}],Ke=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:yg,priority:1,compile:function(b){b.addClass(Wa).addClass("ng-untouched").addClass(mb);return{pre:function(a,b,e,f){var g=f[0];b=f[1]||g.$$parentForm;g.$$setOptions(f[2]&&f[2].$options);b.$addControl(g);e.$observe("name",function(a){g.$name!==a&&g.$$parentForm.$$renameControl(g,
+a)});a.$on("$destroy",function(){g.$$parentForm.$removeControl(g)})},post:function(b,c,e,f){var g=f[0];if(g.$options&&g.$options.updateOn)c.on(g.$options.updateOn,function(a){g.$$debounceViewValueCommit(a&&a.type)});c.on("blur",function(c){g.$touched||(a.$$phase?b.$evalAsync(g.$setTouched):b.$apply(g.$setTouched))})}}}}}],zg=/(\s+|^)default(\s+|$)/,Oe=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,b){var d=this;this.$options=bb(a.$eval(b.ngModelOptions));y(this.$options.updateOn)?
+(this.$options.updateOnDefault=!1,this.$options.updateOn=U(this.$options.updateOn.replace(zg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Ae=La({terminal:!0,priority:1E3}),Ag=G("ngOptions"),Bg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,Ie=["$compile","$parse",function(a,
+b){function d(a,c,d){function e(a,b,c,d,f){this.selectValue=a;this.viewValue=b;this.label=c;this.group=d;this.disabled=f}function l(a){var b;if(!q&&za(a))b=a;else{b=[];for(var c in a)a.hasOwnProperty(c)&&"$"!==c.charAt(0)&&b.push(c)}return b}var m=a.match(Bg);if(!m)throw Ag("iexp",a,ua(c));var n=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var s=m[9];c=b(m[2]?m[1]:n);var v=a&&b(a)||c,u=s&&b(s),p=s?function(a,b){return u(d,b)}:function(a){return Ca(a)},C=function(a,b){return p(a,z(a,b))},w=b(m[2]||
+m[1]),y=b(m[3]||""),B=b(m[4]||""),x=b(m[8]),D={},z=q?function(a,b){D[q]=b;D[n]=a;return D}:function(a){D[n]=a;return D};return{trackBy:s,getTrackByValue:C,getWatchables:b(x,function(a){var b=[];a=a||[];for(var c=l(a),e=c.length,f=0;f<e;f++){var g=a===c?f:c[f],k=z(a[g],g),g=p(a[g],k);b.push(g);if(m[2]||m[1])g=w(d,k),b.push(g);m[4]&&(k=B(d,k),b.push(k))}return b}),getOptions:function(){for(var a=[],b={},c=x(d)||[],f=l(c),g=f.length,m=0;m<g;m++){var n=c===f?m:f[m],r=z(c[n],n),q=v(d,r),n=p(q,r),t=w(d,
+r),u=y(d,r),r=B(d,r),q=new e(n,q,t,u,r);a.push(q);b[n]=q}return{items:a,selectValueMap:b,getOptionFromViewValue:function(a){return b[C(a)]},getViewValueFromOption:function(a){return s?fa.copy(a.viewValue):a.viewValue}}}}}var c=X.createElement("option"),e=X.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","?ngModel"],link:{pre:function(a,b,c,d){d[0].registerOption=x},post:function(b,g,h,k){function l(a,b){a.element=b;b.disabled=a.disabled;a.label!==b.label&&(b.label=a.label,
+b.textContent=a.label);a.value!==b.value&&(b.value=a.selectValue)}function m(a,b,c,d){b&&F(b.nodeName)===c?c=b:(c=d.cloneNode(!1),b?a.insertBefore(c,b):a.appendChild(c));return c}function r(a){for(var b;a;)b=a.nextSibling,Xb(a),a=b}function q(a){var b=p&&p[0],c=z&&z[0];if(b||c)for(;a&&(a===b||a===c||8===a.nodeType||""===a.value);)a=a.nextSibling;return a}function s(){var a=D&&u.readValue();D=E.getOptions();var b={},d=g[0].firstChild;x&&g.prepend(p);d=q(d);D.items.forEach(function(a){var f,h;a.group?
+(f=b[a.group],f||(f=m(g[0],d,"optgroup",e),d=f.nextSibling,f.label=a.group,f=b[a.group]={groupElement:f,currentOptionElement:f.firstChild}),h=m(f.groupElement,f.currentOptionElement,"option",c),l(a,h),f.currentOptionElement=h.nextSibling):(h=m(g[0],d,"option",c),l(a,h),d=h.nextSibling)});Object.keys(b).forEach(function(a){r(b[a].currentOptionElement)});r(d);v.$render();if(!v.$isEmpty(a)){var f=u.readValue();(E.trackBy?ma(a,f):a===f)||(v.$setViewValue(f),v.$render())}}var v=k[1];if(v){var u=k[0];k=
+h.multiple;for(var p,C=0,w=g.children(),y=w.length;C<y;C++)if(""===w[C].value){p=w.eq(C);break}var x=!!p,z=B(c.cloneNode(!1));z.val("?");var D,E=d(h.ngOptions,g,b);k?(v.$isEmpty=function(a){return!a||0===a.length},u.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},u.readValue=function(){var a=g.val()||[],b=[];n(a,function(a){(a=D.selectValueMap[a])&&!a.disabled&&b.push(D.getViewValueFromOption(a))});
+return b},E.trackBy&&b.$watchCollection(function(){if(I(v.$viewValue))return v.$viewValue.map(function(a){return E.getTrackByValue(a)})},function(){v.$render()})):(u.writeValue=function(a){var b=D.getOptionFromViewValue(a);b&&!b.disabled?g[0].value!==b.selectValue&&(z.remove(),x||p.remove(),g[0].value=b.selectValue,b.element.selected=!0,b.element.setAttribute("selected","selected")):null===a||x?(z.remove(),x||g.prepend(p),g.val(""),p.prop("selected",!0),p.attr("selected",!0)):(x||p.remove(),g.prepend(z),
+g.val("?"),z.prop("selected",!0),z.attr("selected",!0))},u.readValue=function(){var a=D.selectValueMap[g.val()];return a&&!a.disabled?(x||p.remove(),z.remove(),D.getViewValueFromOption(a)):null},E.trackBy&&b.$watch(function(){return E.getTrackByValue(v.$viewValue)},function(){v.$render()}));x?(p.remove(),a(p)(b),p.removeClass("ng-scope")):p=B(c.cloneNode(!1));s();b.$watchCollection(E.getWatchables,s)}}}}}],Be=["$locale","$interpolate","$log",function(a,b,d){var c=/{}/g,e=/^when(Minus)?(.+)$/;return{link:function(f,
+g,h){function k(a){g.text(a||"")}var l=h.count,m=h.$attr.when&&g.attr(h.$attr.when),r=h.offset||0,s=f.$eval(m)||{},u={},v=b.startSymbol(),y=b.endSymbol(),p=v+l+"-"+r+y,C=fa.noop,w;n(h,function(a,b){var c=e.exec(b);c&&(c=(c[1]?"-":"")+F(c[2]),s[c]=g.attr(h.$attr[b]))});n(s,function(a,d){u[d]=b(a.replace(c,p))});f.$watch(l,function(b){var c=parseFloat(b),e=isNaN(c);e||c in s||(c=a.pluralCat(c-r));c===w||e&&Q(w)&&isNaN(w)||(C(),e=u[c],q(e)?(null!=b&&d.debug("ngPluralize: no rule defined for '"+c+"' in "+
+m),C=x,k()):C=f.$watch(e,k),w=c)})}}}],Ce=["$parse","$animate",function(a,b){var d=G("ngRepeat"),c=function(a,b,c,d,k,l,m){a[c]=d;k&&(a[k]=l);a.$index=b;a.$first=0===b;a.$last=b===m-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(b&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(e,f){var g=f.ngRepeat,h=X.createComment(" end ngRepeat: "+g+" "),k=g.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+if(!k)throw d("iexp",g);var l=k[1],m=k[2],r=k[3],q=k[4],k=l.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",l);var s=k[3]||k[1],v=k[2];if(r&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(r)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(r)))throw d("badident",r);var x,p,y,w,z={$id:Ca};q?x=a(q):(y=function(a,b){return Ca(b)},w=function(a){return a});return function(a,e,f,k,l){x&&(p=function(b,c,d){v&&(z[v]=b);z[s]=c;z.$index=
+d;return x(a,z)});var q=$();a.$watchCollection(m,function(f){var k,m,t=e[0],x,z=$(),D,E,H,F,I,G,J;r&&(a[r]=f);if(za(f))I=f,m=p||y;else for(J in m=p||w,I=[],f)qa.call(f,J)&&"$"!==J.charAt(0)&&I.push(J);D=I.length;J=Array(D);for(k=0;k<D;k++)if(E=f===I?k:I[k],H=f[E],F=m(E,H,k),q[F])G=q[F],delete q[F],z[F]=G,J[k]=G;else{if(z[F])throw n(J,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",g,F,H);J[k]={id:F,scope:u,clone:u};z[F]=!0}for(x in q){G=q[x];F=rb(G.clone);b.leave(F);if(F[0].parentNode)for(k=0,m=F.length;k<
+m;k++)F[k].$$NG_REMOVED=!0;G.scope.$destroy()}for(k=0;k<D;k++)if(E=f===I?k:I[k],H=f[E],G=J[k],G.scope){x=t;do x=x.nextSibling;while(x&&x.$$NG_REMOVED);G.clone[0]!=x&&b.move(rb(G.clone),null,B(t));t=G.clone[G.clone.length-1];c(G.scope,k,s,H,v,E,D)}else l(function(a,d){G.scope=d;var e=h.cloneNode(!1);a[a.length++]=e;b.enter(a,null,B(t));t=e;G.clone=a;z[G.id]=G;c(G.scope,k,s,H,v,E,D)});q=z})}}}}],De=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngShow,function(b){a[b?
+"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],we=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngHide,function(b){a[b?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Ee=La(function(a,b,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&n(d,function(a,c){b.css(c,"")});a&&b.css(a)},!0)}),Fe=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(b,
+d,c,e){var f=[],g=[],h=[],k=[],l=function(a,b){return function(){a.splice(b,1)}};b.$watch(c.ngSwitch||c.on,function(b){var c,d;c=0;for(d=h.length;c<d;++c)a.cancel(h[c]);c=h.length=0;for(d=k.length;c<d;++c){var q=rb(g[c].clone);k[c].$destroy();(h[c]=a.leave(q)).then(l(h,c))}g.length=0;k.length=0;(f=e.cases["!"+b]||e.cases["?"])&&n(f,function(b){b.transclude(function(c,d){k.push(d);var e=b.element;c[c.length++]=X.createComment(" end ngSwitchWhen: ");g.push({clone:c});a.enter(c,e.parent(),e)})})})}}}],
+Ge=La({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["!"+d.ngSwitchWhen]=c.cases["!"+d.ngSwitchWhen]||[];c.cases["!"+d.ngSwitchWhen].push({transclude:e,element:b})}}),He=La({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["?"]=c.cases["?"]||[];c.cases["?"].push({transclude:e,element:b})}}),Je=La({restrict:"EAC",link:function(a,b,d,c,e){if(!e)throw G("ngTransclude")("orphan",ua(b));e(function(a){b.empty();
+b.append(a)})}}),je=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(b,d){"text/ng-template"==d.type&&a.put(d.id,b[0].text)}}}],Cg={$setViewValue:x,$render:x},Dg=["$element","$scope","$attrs",function(a,b,d){var c=this,e=new Sa;c.ngModelCtrl=Cg;c.unknownOption=B(X.createElement("option"));c.renderUnknownOption=function(b){b="? "+Ca(b)+" ?";c.unknownOption.val(b);a.prepend(c.unknownOption);a.val(b)};b.$on("$destroy",function(){c.renderUnknownOption=x});c.removeUnknownOption=
+function(){c.unknownOption.parent()&&c.unknownOption.remove()};c.readValue=function(){c.removeUnknownOption();return a.val()};c.writeValue=function(b){c.hasOption(b)?(c.removeUnknownOption(),a.val(b),""===b&&c.emptyOption.prop("selected",!0)):null==b&&c.emptyOption?(c.removeUnknownOption(),a.val("")):c.renderUnknownOption(b)};c.addOption=function(a,b){Ra(a,'"option value"');""===a&&(c.emptyOption=b);var d=e.get(a)||0;e.put(a,d+1);c.ngModelCtrl.$render();b[0].hasAttribute("selected")&&(b[0].selected=
+!0)};c.removeOption=function(a){var b=e.get(a);b&&(1===b?(e.remove(a),""===a&&(c.emptyOption=u)):e.put(a,b-1))};c.hasOption=function(a){return!!e.get(a)};c.registerOption=function(a,b,d,e,l){if(e){var m;d.$observe("value",function(a){y(m)&&c.removeOption(m);m=a;c.addOption(a,b)})}else l?a.$watch(l,function(a,e){d.$set("value",a);e!==a&&c.removeOption(e);c.addOption(a,b)}):c.addOption(d.value,b);b.on("$destroy",function(){c.removeOption(d.value);c.ngModelCtrl.$render()})}}],ke=function(){return{restrict:"E",
+require:["select","?ngModel"],controller:Dg,priority:1,link:{pre:function(a,b,d,c){var e=c[1];if(e){var f=c[0];f.ngModelCtrl=e;e.$render=function(){f.writeValue(e.$viewValue)};b.on("change",function(){a.$apply(function(){e.$setViewValue(f.readValue())})});if(d.multiple){f.readValue=function(){var a=[];n(b.find("option"),function(b){b.selected&&a.push(b.value)});return a};f.writeValue=function(a){var c=new Sa(a);n(b.find("option"),function(a){a.selected=y(c.get(a.value))})};var g,h=NaN;a.$watch(function(){h!==
+e.$viewValue||ma(g,e.$viewValue)||(g=ia(e.$viewValue),e.$render());h=e.$viewValue});e.$isEmpty=function(a){return!a||0===a.length}}}}}}},me=["$interpolate",function(a){return{restrict:"E",priority:100,compile:function(b,d){if(y(d.value))var c=a(d.value,!0);else{var e=a(b.text(),!0);e||d.$set("value",b.text())}return function(a,b,d){var k=b.parent();(k=k.data("$selectController")||k.parent().data("$selectController"))&&k.registerOption(a,b,d,c,e)}}}}],le=na({restrict:"E",terminal:!1}),Fc=function(){return{restrict:"A",
+require:"?ngModel",link:function(a,b,d,c){c&&(d.required=!0,c.$validators.required=function(a,b){return!d.required||!c.$isEmpty(b)},d.$observe("required",function(){c.$validate()}))}}},Ec=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e,f=d.ngPattern||d.pattern;d.$observe("pattern",function(a){E(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw G("ngPattern")("noregexp",f,a,ua(b));e=a||u;c.$validate()});c.$validators.pattern=function(a,b){return c.$isEmpty(b)||
+q(e)||e.test(b)}}}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=-1;d.$observe("maxlength",function(a){a=ea(a);e=isNaN(a)?-1:a;c.$validate()});c.$validators.maxlength=function(a,b){return 0>e||c.$isEmpty(b)||b.length<=e}}}}},Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=ea(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};S.angular.bootstrap?
+console.log("WARNING: Tried to load angular more than once."):(ce(),ee(fa),fa.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),
+SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",
+negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",pluralCat:function(a,c){var e=a|0,f=c;u===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),B(X).ready(function(){Zd(X,yc)}))})(window,document);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
+//# sourceMappingURL=angular.min.js.map
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js.map
new file mode 100644
index 00000000..fbb9d467
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/angular.min.js.map
@@ -0,0 +1,8 @@
+{
+"version":3,
+"file":"angular.min.js",
+"lineCount":294,
+"mappings":"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",
+"sources":["angular.js"],
+"names":["window","document","undefined","minErr","isArrayLike","obj","isWindow","isArray","isString","jqLite","length","Object","isNumber","item","forEach","iterator","context","key","isFunction","hasOwnProperty","call","isPrimitive","isBlankObject","forEachSorted","keys","sort","i","reverseParams","iteratorFn","value","nextUid","uid","baseExtend","dst","objs","deep","h","$$hashKey","ii","isObject","j","jj","src","isDate","Date","valueOf","isRegExp","RegExp","nodeName","cloneNode","isElement","clone","extend","slice","arguments","merge","toInt","str","parseInt","inherit","parent","extra","create","noop","identity","$","valueFn","hasCustomToString","toString","isUndefined","isDefined","getPrototypeOf","isScope","$evalAsync","$watch","isBoolean","isTypedArray","TYPED_ARRAY_REGEXP","test","node","prop","attr","find","makeMap","items","split","nodeName_","element","lowercase","arrayRemove","array","index","indexOf","splice","copy","source","destination","copyRecurse","push","copyElement","stackSource","stackDest","ngMinErr","needsRecurse","constructor","getTime","match","lastIndex","shallowCopy","charAt","equals","o1","o2","t1","t2","keySet","createMap","concat","array1","array2","bind","self","fn","curryArgs","startIndex","apply","toJsonReplacer","val","toJson","pretty","JSON","stringify","fromJson","json","parse","timezoneToOffset","timezone","fallback","requestedTimezoneOffset","isNaN","convertTimezoneToLocal","date","reverse","timezoneOffset","getTimezoneOffset","setMinutes","getMinutes","minutes","startingTag","empty","e","elemHtml","append","html","nodeType","NODE_TYPE_TEXT","replace","tryDecodeURIComponent","decodeURIComponent","parseKeyValue","keyValue","splitPoint","substring","toKeyValue","parts","arrayValue","encodeUriQuery","join","encodeUriSegment","pctEncodeSpaces","encodeURIComponent","getNgAttribute","ngAttr","ngAttrPrefixes","getAttribute","angularInit","bootstrap","appElement","module","config","prefix","name","hasAttribute","candidate","querySelector","strictDi","modules","defaultConfig","doBootstrap","injector","tag","unshift","$provide","debugInfoEnabled","$compileProvider","createInjector","invoke","bootstrapApply","scope","compile","$apply","data","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","angular","resumeBootstrap","angular.resumeBootstrap","extraModules","resumeDeferredBootstrap","reloadWithDebugInfo","location","reload","getTestability","rootElement","get","snake_case","separator","SNAKE_CASE_REGEXP","letter","pos","toLowerCase","bindJQuery","originalCleanData","bindJQueryFired","jqName","jq","jQuery","on","JQLitePrototype","isolateScope","controller","inheritedData","cleanData","jQuery.cleanData","elems","events","skipDestroyOnNextJQueryCleanData","elem","_data","$destroy","triggerHandler","JQLite","assertArg","arg","reason","assertArgFn","acceptArrayAnnotation","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","nextSibling","setupModuleLoader","ensure","factory","$injectorMinErr","$$minErr","requires","configFn","invokeLater","provider","method","insertMethod","queue","invokeQueue","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","configBlocks","runBlocks","_invokeQueue","_configBlocks","_runBlocks","service","constant","decorator","animation","filter","directive","run","block","publishExternalAPI","version","uppercase","counter","csp","angularModule","ngModule","$$sanitizeUri","$$SanitizeUriProvider","$CompileProvider","a","htmlAnchorDirective","input","inputDirective","textarea","form","formDirective","script","scriptDirective","select","selectDirective","style","styleDirective","option","optionDirective","ngBind","ngBindDirective","ngBindHtml","ngBindHtmlDirective","ngBindTemplate","ngBindTemplateDirective","ngClass","ngClassDirective","ngClassEven","ngClassEvenDirective","ngClassOdd","ngClassOddDirective","ngCloak","ngCloakDirective","ngController","ngControllerDirective","ngForm","ngFormDirective","ngHide","ngHideDirective","ngIf","ngIfDirective","ngInclude","ngIncludeDirective","ngInit","ngInitDirective","ngNonBindable","ngNonBindableDirective","ngPluralize","ngPluralizeDirective","ngRepeat","ngRepeatDirective","ngShow","ngShowDirective","ngStyle","ngStyleDirective","ngSwitch","ngSwitchDirective","ngSwitchWhen","ngSwitchWhenDirective","ngSwitchDefault","ngSwitchDefaultDirective","ngOptions","ngOptionsDirective","ngTransclude","ngTranscludeDirective","ngModel","ngModelDirective","ngList","ngListDirective","ngChange","ngChangeDirective","pattern","patternDirective","ngPattern","required","requiredDirective","ngRequired","minlength","minlengthDirective","ngMinlength","maxlength","maxlengthDirective","ngMaxlength","ngValue","ngValueDirective","ngModelOptions","ngModelOptionsDirective","ngIncludeFillContentDirective","ngAttributeAliasDirectives","ngEventDirectives","$anchorScroll","$AnchorScrollProvider","$animate","$AnimateProvider","$animateCss","$CoreAnimateCssProvider","$$animateQueue","$$CoreAnimateQueueProvider","$$AnimateRunner","$$CoreAnimateRunnerProvider","$browser","$BrowserProvider","$cacheFactory","$CacheFactoryProvider","$controller","$ControllerProvider","$document","$DocumentProvider","$exceptionHandler","$ExceptionHandlerProvider","$filter","$FilterProvider","$$forceReflow","$$ForceReflowProvider","$interpolate","$InterpolateProvider","$interval","$IntervalProvider","$http","$HttpProvider","$httpParamSerializer","$HttpParamSerializerProvider","$httpParamSerializerJQLike","$HttpParamSerializerJQLikeProvider","$httpBackend","$HttpBackendProvider","$xhrFactory","$xhrFactoryProvider","$location","$LocationProvider","$log","$LogProvider","$parse","$ParseProvider","$rootScope","$RootScopeProvider","$q","$QProvider","$$q","$$QProvider","$sce","$SceProvider","$sceDelegate","$SceDelegateProvider","$sniffer","$SnifferProvider","$templateCache","$TemplateCacheProvider","$templateRequest","$TemplateRequestProvider","$$testability","$$TestabilityProvider","$timeout","$TimeoutProvider","$window","$WindowProvider","$$rAF","$$RAFProvider","$$jqLite","$$jqLiteProvider","$$HashMap","$$HashMapProvider","$$cookieReader","$$CookieReaderProvider","camelCase","SPECIAL_CHARS_REGEXP","_","offset","toUpperCase","MOZ_HACK_REGEXP","jqLiteAcceptsData","NODE_TYPE_ELEMENT","NODE_TYPE_DOCUMENT","jqLiteBuildFragment","tmp","fragment","createDocumentFragment","HTML_REGEXP","appendChild","createElement","TAG_NAME_REGEXP","exec","wrap","wrapMap","_default","innerHTML","XHTML_TAG_REGEXP","lastChild","childNodes","firstChild","textContent","createTextNode","argIsString","trim","jqLiteMinErr","parsed","SINGLE_TAG_REGEXP","jqLiteAddNodes","jqLiteClone","jqLiteDealoc","onlyDescendants","jqLiteRemoveData","querySelectorAll","descendants","l","jqLiteOff","type","unsupported","expandoStore","jqLiteExpandoStore","handle","removeHandler","listenerFns","removeEventListener","MOUSE_EVENT_MAP","expandoId","ng339","jqCache","createIfNecessary","jqId","jqLiteData","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","setAttribute","cssClass","jqLiteAddClass","existingClasses","root","elements","jqLiteController","jqLiteInheritedData","documentElement","names","parentNode","NODE_TYPE_DOCUMENT_FRAGMENT","host","jqLiteEmpty","removeChild","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","readyState","setTimeout","getBooleanAttrName","booleanAttr","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","createEventHandler","eventHandler","event","isDefaultPrevented","event.isDefaultPrevented","defaultPrevented","eventFns","eventFnsLength","immediatePropagationStopped","originalStopImmediatePropagation","stopImmediatePropagation","event.stopImmediatePropagation","stopPropagation","isImmediatePropagationStopped","event.isImmediatePropagationStopped","handlerWrapper","specialHandlerWrapper","defaultHandlerWrapper","handler","specialMouseHandlerWrapper","target","related","relatedTarget","jqLiteContains","$get","this.$get","hasClass","classes","addClass","removeClass","hashKey","nextUidFn","objType","HashMap","isolatedUid","this.nextUid","put","anonFn","args","fnText","STRIP_COMMENTS","FN_ARGS","modulesToLoad","supportObject","delegate","provider_","providerInjector","instantiate","providerCache","providerSuffix","enforceReturnValue","enforcedReturnValue","result","instanceInjector","factoryFn","enforce","loadModules","moduleFn","runInvokeQueue","invokeArgs","loadedModules","message","stack","createInternalInjector","cache","getService","serviceName","caller","INSTANTIATING","err","shift","locals","$inject","$$annotate","Type","instance","prototype","returnedValue","annotate","has","$injector","instanceCache","decorFn","origProvider","orig$get","origProvider.$get","origInstance","$delegate","autoScrollingEnabled","disableAutoScrolling","this.disableAutoScrolling","getFirstAnchor","list","Array","some","scrollTo","scrollIntoView","scroll","yOffset","getComputedStyle","position","getBoundingClientRect","bottom","elemTop","top","scrollBy","hash","elm","getElementById","getElementsByName","autoScrollWatch","autoScrollWatchAction","newVal","oldVal","mergeClasses","b","splitClasses","klass","prepareAnimateOptions","options","Browser","completeOutstandingRequest","outstandingRequestCount","outstandingRequestCallbacks","pop","error","cacheStateAndFireUrlChange","pendingLocation","cacheState","fireUrlChange","history","state","cachedState","lastCachedState","lastBrowserUrl","url","lastHistoryState","urlChangeListeners","listener","clearTimeout","pendingDeferIds","isMock","$$completeOutstandingRequest","$$incOutstandingRequestCount","self.$$incOutstandingRequestCount","notifyWhenNoOutstandingRequests","self.notifyWhenNoOutstandingRequests","callback","href","baseElement","self.url","sameState","sameBase","stripHash","substr","self.state","urlChangeInit","onUrlChange","self.onUrlChange","$$applicationDestroyed","self.$$applicationDestroyed","off","$$checkUrlChange","baseHref","self.baseHref","defer","self.defer","delay","timeoutId","cancel","self.defer.cancel","deferId","cacheFactory","cacheId","refresh","entry","freshEnd","staleEnd","n","link","p","nextEntry","prevEntry","caches","size","stats","id","capacity","Number","MAX_VALUE","lruHash","lruEntry","remove","removeAll","destroy","info","cacheFactory.info","cacheFactory.get","$$sanitizeUriProvider","parseIsolateBindings","directiveName","isController","LOCAL_REGEXP","bindings","definition","scopeName","$compileMinErr","mode","collection","optional","attrName","assertValidDirectiveName","hasDirectives","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","REQUIRE_PREFIX_REGEXP","EVENT_HANDLER_ATTR_REGEXP","this.directive","registerDirective","directiveFactory","Suffix","directives","priority","require","restrict","bindToController","controllerAs","CNTRL_REG","$$bindings","$$isolateBindings","aHrefSanitizationWhitelist","this.aHrefSanitizationWhitelist","regexp","imgSrcSanitizationWhitelist","this.imgSrcSanitizationWhitelist","this.debugInfoEnabled","enabled","safeAddClass","$element","className","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","nodeValue","compositeLinkFn","compileNodes","$$addScopeClass","namespace","publicLinkFn","cloneConnectFn","needsNewScope","$parent","$new","parentBoundTranscludeFn","transcludeControllers","futureParentElement","$$boundTransclude","$linkNode","wrapTemplate","controllerName","$$addScopeInfo","nodeList","$rootElement","childLinkFn","childScope","childBoundTranscludeFn","stableNodeList","nodeLinkFnFound","linkFns","idx","nodeLinkFn","transcludeOnThisElement","createBoundTranscludeFn","transclude","templateOnThisElement","attrs","linkFnFound","Attributes","collectDirectives","applyDirectivesToNode","$$element","terminal","previousBoundTranscludeFn","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","$$transcluded","attrsMap","$attr","addDirective","directiveNormalize","isNgAttr","nAttrs","attributes","attrStartName","attrEndName","ngAttrName","NG_ATTR_BINDING","PREFIX_REGEXP","multiElementMatch","MULTI_ELEMENT_DIR_RE","directiveIsMultiElement","nName","addAttrInterpolateDirective","animVal","msie","addTextInterpolateDirective","NODE_TYPE_COMMENT","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","addLinkFns","pre","post","newIsolateScopeDirective","$$isolateScope","cloneAndAnnotateFn","getControllers","elementControllers","inheritType","dataName","setupControllers","controllerDirectives","controllerKey","$scope","$attrs","$transclude","controllerInstance","hasElementTranscludeDirective","linkNode","controllersBoundTransclude","cloneAttachFn","scopeToChild","controllerScope","removeScopeBindingWatches","newScopeDirective","templateDirective","$$originalDirective","initializeDirectiveBindings","$on","controllerDirective","identifier","removeControllerBindingWatches","controllerResult","invokeLinkFn","template","templateUrl","terminalPriority","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","$compileNode","$template","childTranscludeFn","$$start","$$end","directiveValue","assertNoDuplicate","$$tlb","createComment","replaceWith","replaceDirective","contents","$$newScope","denormalizeTemplate","removeComments","templateNamespace","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectiveScope","mergeTemplateAttributes","compileTemplateUrl","Math","max","newScope","tDirectives","startAttrName","endAttrName","multiElement","srcAttr","dstAttr","$set","tAttrs","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","then","content","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","$$destroyed","oldClasses","delayedNodeLinkFn","ignoreChildLinkFn","diff","what","previousDirective","wrapModuleNameIfDefined","moduleName","text","interpolateFn","textInterpolateCompileFn","templateNode","templateNodeParent","hasCompileParent","$$addBindingClass","textInterpolateLinkFn","$$addBindingInfo","expressions","interpolateFnWatchAction","wrapper","getTrustedContext","attrNormalizedName","HTML","RESOURCE_URL","allOrNothing","trustedContext","attrInterpolatePreLinkFn","$$observers","newValue","$$inter","$$scope","oldValue","$updateClass","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","replaceChild","hasData","expando","k","kk","annotation","removeWatchCollection","lastValue","parentGet","parentSet","compare","$observe","literal","assign","parentValueWatch","parentValue","$stateful","removeWatch","$watchCollection","removeWatches","attributesToCopy","$normalize","$addClass","classVal","$removeClass","newClasses","toAdd","tokenDifference","toRemove","writeAttr","booleanKey","aliasedKey","ALIASED_ATTR","observer","trimmedSrcset","srcPattern","rawUris","nbrUrisWith2parts","floor","innerIdx","lastTuple","removeAttr","listeners","startSymbol","endSymbol","binding","isolated","noTemplate","str1","str2","values","tokens1","tokens2","token","jqNodes","globals","register","this.register","allowGlobals","this.allowGlobals","addIdentifier","expression","later","ident","$controllerMinErr","controllerPrototype","exception","cause","serializeValue","v","toISOString","ngParamSerializer","params","jQueryLikeParamSerializer","serialize","toSerialize","topLevel","defaultHttpResponseTransform","headers","tempData","JSON_PROTECTION_PREFIX","contentType","jsonStart","JSON_START","JSON_ENDS","parseHeaders","line","headerVal","headerKey","headersGetter","headersObj","transformData","status","fns","defaults","transformResponse","transformRequest","d","common","CONTENT_TYPE_APPLICATION_JSON","patch","xsrfCookieName","xsrfHeaderName","paramSerializer","useApplyAsync","this.useApplyAsync","useLegacyPromise","useLegacyPromiseExtensions","this.useLegacyPromiseExtensions","interceptorFactories","interceptors","requestConfig","response","resp","reject","executeHeaderFns","headerContent","processedHeaders","headerFn","header","mergeHeaders","defHeaders","reqHeaders","defHeaderName","lowercaseDefHeaderName","reqHeaderName","chain","serverRequest","reqData","withCredentials","sendReq","promise","when","reversedInterceptors","interceptor","request","requestError","responseError","thenFn","rejectFn","success","promise.success","promise.error","$httpMinErrLegacyFn","done","headersString","statusText","resolveHttpPromise","resolvePromise","$applyAsync","$$phase","deferred","resolve","resolvePromiseWithResult","removePendingReq","pendingRequests","cachedResp","buildUrl","defaultCache","xsrfValue","urlIsSameOrigin","timeout","responseType","serializedParams","interceptorFactory","createShortMethods","createShortMethodsWithData","createXhr","XMLHttpRequest","createHttpBackend","callbacks","$browserDefer","rawDocument","jsonpReq","callbackId","async","body","called","addEventListener","timeoutRequest","jsonpDone","xhr","abort","completeRequest","open","setRequestHeader","onload","xhr.onload","responseText","urlResolve","protocol","getAllResponseHeaders","onerror","onabort","send","this.startSymbol","this.endSymbol","escape","ch","unescapeText","escapedStartRegexp","escapedEndRegexp","mustHaveExpression","parseStringifyInterceptor","getTrusted","$interpolateMinErr","interr","endIndex","parseFns","textLength","expressionPositions","startSymbolLength","exp","endSymbolLength","throwNoconcat","compute","interpolationFn","$$watchDelegate","$watchGroup","interpolateFnWatcher","oldValues","currValue","$interpolate.startSymbol","$interpolate.endSymbol","interval","count","invokeApply","hasParams","setInterval","clearInterval","iteration","skipApply","$$intervalId","tick","notify","intervals","interval.cancel","encodePath","segments","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","$$protocol","$$host","hostname","$$port","port","DEFAULT_PORTS","parseAppUrl","relativeUrl","prefixed","$$path","pathname","$$search","search","$$hash","beginsWith","begin","whole","trimEmptyHash","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","$$html5","$$parse","this.$$parse","pathUrl","$locationMinErr","$$compose","this.$$compose","$$url","$$absUrl","$$parseLinkUrl","this.$$parseLinkUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","windowsFilePathExp","base","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationGetter","property","locationGetterSetter","preprocess","html5Mode","requireBase","rewriteLinks","this.hashPrefix","this.html5Mode","setBrowserUrlWithFallback","oldUrl","oldState","$$state","afterLocationChange","$broadcast","absUrl","LocationMode","initialUrl","lastIndexOf","IGNORE_URI_REGEXP","ctrlKey","metaKey","shiftKey","which","button","absHref","preventDefault","initializing","newUrl","newState","$digest","$locationWatch","currentReplace","$$replace","urlOrStateChanged","debug","debugEnabled","this.debugEnabled","flag","formatError","Error","sourceURL","consoleLog","console","logFn","log","hasApply","arg1","arg2","warn","ensureSafeMemberName","fullExpression","$parseMinErr","getStringValue","ensureSafeObject","children","ensureSafeFunction","CALL","APPLY","BIND","ensureSafeAssignContext","Function","ifDefined","plusFn","r","findConstantAndWatchExpressions","ast","allConstants","argsToWatch","AST","Program","expr","Literal","toWatch","UnaryExpression","argument","BinaryExpression","left","right","LogicalExpression","ConditionalExpression","alternate","consequent","Identifier","MemberExpression","object","computed","CallExpression","callee","AssignmentExpression","ArrayExpression","ObjectExpression","properties","ThisExpression","getInputs","lastExpression","isAssignable","assignableAST","NGValueParameter","operator","isLiteral","ASTCompiler","astBuilder","ASTInterpreter","isPossiblyDangerousMemberName","getValueOf","objectValueOf","cacheDefault","cacheExpensive","expressionInputDirtyCheck","oldValueOfValue","inputsWatchDelegate","objectEquality","parsedExpression","prettyPrintExpression","inputExpressions","inputs","lastResult","oldInputValueOf","expressionInputWatch","newInputValue","oldInputValueOfValues","oldInputValues","expressionInputsWatch","changed","oneTimeWatchDelegate","unwatch","oneTimeWatch","oneTimeListener","old","$$postDigest","oneTimeLiteralWatchDelegate","isAllDefined","allDefined","constantWatchDelegate","constantWatch","constantListener","addInterceptor","interceptorFn","watchDelegate","useInputs","regularInterceptedExpression","oneTimeInterceptedExpression","noUnsafeEval","$parseOptions","expensiveChecks","$parseOptionsExpensive","oneTime","cacheKey","parseOptions","lexer","Lexer","parser","Parser","qFactory","nextTick","exceptionHandler","callOnce","resolveFn","Promise","simpleBind","scheduleProcessQueue","processScheduled","pending","Deferred","$qMinErr","TypeError","onFulfilled","onRejected","progressBack","catch","finally","handleCallback","$$reject","$$resolve","progress","makePromise","resolved","isResolved","callbackOutput","errback","$Q","Q","resolver","all","promises","results","requestAnimationFrame","webkitRequestAnimationFrame","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","rafSupported","raf","timer","supported","createChildScopeClass","ChildScope","$$watchers","$$nextSibling","$$childHead","$$childTail","$$listeners","$$listenerCount","$$watchersCount","$id","$$ChildScope","TTL","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","digestTtl","this.digestTtl","destroyChildScope","$event","currentScope","cleanUpScope","$$prevSibling","$root","Scope","beginPhase","phase","incrementWatchersCount","current","decrementListenerCount","initWatchVal","flushApplyAsync","applyAsyncQueue","scheduleApplyAsync","isolate","child","watchExp","watcher","last","eq","deregisterWatch","watchExpressions","watchGroupAction","changeReactionScheduled","firstRun","newValues","deregisterFns","shouldCall","deregisterWatchGroup","unwatchFn","watchGroupSubAction","$watchCollectionInterceptor","_value","bothNaN","newItem","oldItem","internalArray","oldLength","changeDetected","newLength","internalObject","veryOldValue","trackVeryOldValue","changeDetector","initRun","$watchCollectionAction","watch","watchers","dirty","ttl","watchLog","logIdx","asyncTask","asyncQueue","$eval","msg","next","postDigestQueue","eventName","this.$watchGroup","$applyAsyncExpression","namedListeners","indexOfListener","$emit","targetScope","listenerArgs","$$asyncQueue","$$postDigestQueue","$$applyAsyncQueue","sanitizeUri","uri","isImage","regex","normalizedVal","adjustMatcher","matcher","$sceMinErr","escapeForRegexp","adjustMatchers","matchers","adjustedMatchers","SCE_CONTEXTS","resourceUrlWhitelist","resourceUrlBlacklist","this.resourceUrlWhitelist","this.resourceUrlBlacklist","matchUrl","generateHolderType","Base","holderType","trustedValue","$$unwrapTrustedValue","this.$$unwrapTrustedValue","holderType.prototype.valueOf","holderType.prototype.toString","htmlSanitizer","trustedValueHolderBase","byType","CSS","URL","JS","trustAs","Constructor","maybeTrusted","allowed","this.enabled","sce","isEnabled","sce.isEnabled","sce.getTrusted","parseAs","sce.parseAs","enumValue","lName","eventSupport","android","userAgent","navigator","boxee","vendorPrefix","vendorRegex","bodyStyle","transitions","animations","webkitTransition","webkitAnimation","pushState","hasEvent","divElm","handleRequestFn","tpl","ignoreRequestError","totalPendingRequests","getTrustedResourceUrl","transformer","httpOptions","handleError","testability","testability.findBindings","opt_exactMatch","getElementsByClassName","matches","dataBinding","bindingName","testability.findModels","prefixes","attributeEquals","testability.getLocation","testability.setLocation","testability.whenStable","deferreds","$$timeoutId","timeout.cancel","urlParsingNode","requestUrl","originUrl","$$CookieReader","safeDecodeURIComponent","lastCookies","lastCookieString","cookieArray","cookie","currentCookieString","filters","suffix","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","matchAgainstAnyProp","getTypeForFilter","expressionType","predicateFn","createPredicateFn","shouldMatchPrimitives","actual","expected","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","$locale","formats","NUMBER_FORMATS","amount","currencySymbol","fractionSize","CURRENCY_SYM","PATTERNS","maxFrac","formatNumber","GROUP_SEP","DECIMAL_SEP","number","groupSep","decimalSep","isNegative","abs","isInfinity","Infinity","isFinite","numStr","formatedText","hasExponent","toFixed","parseFloat","fractionLen","min","minFrac","round","fraction","lgroup","lgSize","group","gSize","negPre","posPre","negSuf","posSuf","padNumber","num","digits","neg","dateGetter","dateStrGetter","shortForm","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getDay","weekGetter","firstThurs","getFullYear","thisThurs","getMonth","getDate","eraGetter","ERAS","jsonStringToDate","string","R_ISO8601_STR","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","m","s","ms","format","DATETIME_FORMATS","NUMBER_STRING","DATE_FORMATS_SPLIT","dateTimezoneOffset","DATE_FORMATS","spacing","limit","processPredicates","sortPredicate","reverseOrder","map","predicate","descending","predicates","compareValues","getComparisonObject","predicateValues","doComparison","v1","v2","ngDirective","FormController","controls","$error","$$success","$pending","$name","$dirty","$pristine","$valid","$invalid","$submitted","$$parentForm","nullFormCtrl","$rollbackViewValue","form.$rollbackViewValue","control","$commitViewValue","form.$commitViewValue","$addControl","form.$addControl","$$renameControl","form.$$renameControl","newName","oldName","$removeControl","form.$removeControl","$setValidity","addSetValidityMethod","ctrl","set","unset","$setDirty","form.$setDirty","PRISTINE_CLASS","DIRTY_CLASS","$setPristine","form.$setPristine","setClass","SUBMITTED_CLASS","$setUntouched","form.$setUntouched","$setSubmitted","form.$setSubmitted","stringBasedInputType","$formatters","$isEmpty","baseInputType","composing","ev","ngTrim","$viewValue","$$hasNativeValidators","$setViewValue","deferListener","origValue","keyCode","$render","ctrl.$render","createDateParser","mapping","iso","ISO_DATE_REGEXP","yyyy","MM","dd","HH","getHours","mm","ss","getSeconds","sss","getMilliseconds","part","NaN","createDateInputType","parseDate","dynamicDateInputType","isValidDate","parseObservedDateValue","badInputChecker","$options","previousDate","$$parserName","$parsers","parsedDate","ngModelMinErr","ngMin","minVal","$validators","ctrl.$validators.min","$validate","ngMax","maxVal","ctrl.$validators.max","validity","VALIDITY_STATE_PROPERTY","badInput","typeMismatch","parseConstantExpr","parseFn","classDirective","arrayDifference","arrayClasses","digestClassCounts","classCounts","classesToUpdate","ngClassWatchAction","$index","old$index","mod","cachedToggleClass","switchValue","classCache","toggleValidationCss","validationErrorKey","isValid","VALID_CLASS","INVALID_CLASS","setValidity","isObjectEmpty","PENDING_CLASS","combinedState","REGEX_STRING_REGEXP","documentMode","rules","ngCspElement","ngCspAttribute","noInlineStyle","name_","el","full","major","minor","dot","codeName","JQLite._data","mouseleave","mouseenter","optgroup","tbody","tfoot","colgroup","caption","thead","th","td","Node","contains","compareDocumentPosition","ready","trigger","fired","removeData","jqLiteHasData","removeAttribute","css","NODE_TYPE_ATTRIBUTE","lowercasedName","specified","getNamedItem","ret","getText","$dv","multiple","selected","nodeCount","jqLiteOn","types","addHandler","noEventListener","one","onFn","replaceNode","insertBefore","contentDocument","prepend","wrapNode","detach","after","newElement","toggleClass","condition","classCondition","nextElementSibling","getElementsByTagName","extraParameters","dummyEvent","handlerArgs","eventFnsCopy","arg3","unbind","FN_ARG_SPLIT","FN_ARG","argDecl","underscore","$animateMinErr","AnimateRunner","end","resume","pause","complete","pass","fail","postDigestElements","updateData","handleCSSClassChanges","existing","pin","domOperation","from","to","classesAdded","add","classesRemoved","$$registeredAnimations","classNameFilter","this.classNameFilter","$$classNameFilter","reservedRegex","NG_ANIMATE_CLASSNAME","domInsert","parentElement","afterElement","afterNode","ELEMENT_NODE","previousElementSibling","runner","enter","move","leave","addclass","animate","tempClasses","RAFPromise","getPromise","f1","f2","closed","cleanupStyles","start","domNode","offsetWidth","APPLICATION_JSON","$httpMinErr","$interpolateMinErr.throwNoconcat","$interpolateMinErr.interr","PATH_MATCH","locationPrototype","paramValue","Location","Location.prototype.state","OPERATORS","ESCAPE","lex","tokens","readString","peek","readNumber","isIdent","readIdent","is","isWhitespace","ch2","ch3","op2","op3","op1","throwError","chars","isExpOperator","colStr","peekCh","quote","rawString","hex","String","fromCharCode","rep","ExpressionStatement","Property","program","expressionStatement","expect","filterChain","assignment","ternary","logicalOR","consume","logicalAND","equality","relational","additive","multiplicative","unary","primary","arrayDeclaration","constants","parseArguments","baseExpression","peekToken","kind","e1","e2","e3","e4","peekAhead","t","nextId","vars","own","assignable","stage","computing","recurse","return_","generateFunction","fnKey","intoId","watchId","fnString","USE","STRICT","filterPrefix","watchFns","varsPrefix","section","nameId","recursionFn","skipWatchIdCheck","if_","lazyAssign","computedMember","lazyRecurse","plus","not","getHasOwnProperty","nonComputedMember","addEnsureSafeObject","notNull","addEnsureSafeMemberName","addEnsureSafeFunction","member","addEnsureSafeAssignContext","filterName","defaultValue","stringEscapeRegex","stringEscapeFn","c","charCodeAt","skip","init","fn.assign","rhs","lhs","unary+","unary-","unary!","binary+","binary-","binary*","binary/","binary%","binary===","binary!==","binary==","binary!=","binary<","binary>","binary<=","binary>=","binary&&","binary||","ternary?:","astCompiler","yy","y","MMMM","MMM","M","H","hh","EEEE","EEE","ampmGetter","AMPMS","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","ERANAMES","xlinkHref","propName","defaultLinkFn","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","getSetter","ngFormCompile","formElement","nameAttr","ngFormPreLink","ctrls","handleFormSubmission","setter","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","tElement","ngBindHtmlGetter","ngBindHtmlWatch","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","that","ngOptionsMinErr","NG_OPTIONS_REGEXP","parseOptionsExpression","optionsExp","selectElement","Option","selectValue","label","disabled","getOptionValuesKeys","optionValues","optionValuesKeys","keyName","itemKey","valueName","selectAs","trackBy","viewValueFn","trackByFn","getTrackByValueFn","getHashOfValue","getTrackByValue","getLocals","displayFn","groupByFn","disableWhenFn","valuesFn","getWatchables","watchedArray","optionValuesLength","disableWhen","getOptions","optionItems","selectValueMap","optionItem","getOptionFromViewValue","getViewValueFromOption","optionTemplate","optGroupTemplate","ngOptionsPreLink","registerOption","ngOptionsPostLink","updateOptionElement","addOrReuseElement","removeExcessElements","skipEmptyAndUnknownOptions","emptyOption_","emptyOption","unknownOption_","unknownOption","updateOptions","previousValue","selectCtrl","readValue","groupMap","providedEmptyOption","updateOption","optionElement","groupElement","currentOptionElement","ngModelCtrl","nextValue","ngModelCtrl.$isEmpty","writeValue","selectCtrl.writeValue","selectCtrl.readValue","selectedValues","selections","selectedOption","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","pluralCat","whenExpFn","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","noopNgModelController","SelectController","optionsMap","renderUnknownOption","self.renderUnknownOption","unknownVal","removeUnknownOption","self.removeUnknownOption","self.readValue","self.writeValue","hasOption","addOption","self.addOption","removeOption","self.removeOption","self.hasOption","self.registerOption","optionScope","optionAttrs","interpolateValueFn","interpolateTextFn","valueAttributeObserveAction","interpolateWatchAction","selectPreLink","ngModelCtrl.$render","lastView","lastViewRef","selectMultipleWatch","selectCtrlName","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","getDecimals","opt_precision","pow","ONE","OTHER","$$csp","head"]
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/errors.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/errors.json
new file mode 100644
index 00000000..954d1d9f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/errors.json
@@ -0,0 +1 @@
+{"id":"ng","generated":"Fri Nov 20 2015 00:03:11 GMT-0800 (PST)","errors":{"ng":{"areq":"Argument '{0}' is {1}","cpta":"Can't copy! TypedArray destination cannot be mutated.","test":"no injector found for element argument to getTestability","cpws":"Can't copy! Making copies of Window or Scope instances is not supported.","btstrpd":"App Already Bootstrapped with this Element '{0}'","cpi":"Can't copy! Source and destination are identical.","badname":"hasOwnProperty is not a valid {0} name"},"$http":{"legacy":"The method `{0}` on the promise returned from `$http` has been disabled.","badreq":"Http request configuration must be an object. Received: {0}"},"ngRepeat":{"badident":"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.","iexp":"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.","dupes":"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}","iidexp":"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'."},"$sce":{"imatcher":"Matchers may only be \"self\", string patterns or RegExp objects","icontext":"Attempted to trust a value in invalid context. Context: {0}; Value: {1}","iwcard":"Illegal sequence *** in string matcher. String: {0}","insecurl":"Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}","iequirks":"Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks mode. You can fix this by adding the text <!doctype html> to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.","unsafe":"Attempting to use an unsafe value in a safe context.","itype":"Attempted to trust a non-string value in a content requiring a string: Context: {0}"},"ngPattern":{"noregexp":"Expected {0} to be a RegExp but was {1}. Element: {2}"},"$controller":{"ctrlfmt":"Badly formed controller string '{0}'. Must match `__name__ as __id__` or `__name__`.","noscp":"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`."},"$parse":{"isecfn":"Referencing Function in Angular expressions is disallowed! Expression: {0}","isecobj":"Referencing Object in Angular expressions is disallowed! Expression: {0}","lval":"Trying to assing a value to a non l-value","isecwindow":"Referencing the Window in Angular expressions is disallowed! Expression: {0}","ueoe":"Unexpected end of expression: {0}","isecdom":"Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}","lexerr":"Lexer Error: {0} at column{1} in expression [{2}].","esc":"IMPOSSIBLE","iseccst":"Cannot convert object to primitive value! Expression: {0}","isecff":"Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}","syntax":"Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].","isecaf":"Assigning to a constructor is disallowed! Expression: {0}","isecfld":"Attempting to access a disallowed field in Angular expressions! Expression: {0}"},"jqLite":{"offargs":"jqLite#off() does not support the `selector` argument","onargs":"jqLite#on() does not support the `selector` or `eventData` parameters","nosel":"Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"},"$animate":{"notcsel":"Expecting class selector starting with '.' got '{0}'.","nongcls":"$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the \"{0}\" CSS class."},"$q":{"norslvr":"Expected resolverFn, got '{0}'","qcycle":"Expected promise to be resolved with value other than itself '{0}'"},"$injector":{"pget":"Provider '{0}' must define $get factory method.","cdep":"Circular dependency found: {0}","nomod":"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.","strictdi":"{0} is not using explicit annotation and cannot be invoked in strict mode","modulerr":"Failed to instantiate module {0} due to:\n{1}","undef":"Provider '{0}' must return a value from $get factory method.","unpr":"Unknown provider: {0}","itkn":"Incorrect injection token! Expected service name as string, got {0}"},"filter":{"notarray":"Expected array but received: {0}"},"ngTransclude":{"orphan":"Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: {0}"},"ngModel":{"nonassign":"Expression '{0}' is non-assignable. Element: {1}","datefmt":"Expected `{0}` to be a date","$asyncValidators":"Expected asynchronous validator to return a promise but got '{0}' instead.","constexpr":"Expected constant expression for `{0}`, but saw `{1}`.","numfmt":"Expected `{0}` to be a number"},"$location":{"nostate":"History API state support is available only in HTML5 mode and only in browsers supporting HTML5 History API","ipthprfx":"Invalid url \"{0}\", missing path prefix \"{1}\".","isrcharg":"The first argument of the `$location#search()` call must be a string or an object.","nobase":"$location in HTML5 mode requires a <base> tag to be present!"},"$cacheFactory":{"iid":"CacheId '{0}' is already taken!"},"$interpolate":{"noconcat":"Error while interpolating: {0}\nStrict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce","interr":"Can't interpolate: {0}\n{1}","nochgmustache":"angular-message-format.js currently does not allow you to use custom start and end symbols for interpolation.","reqcomma":"Expected a comma after the keyword “{0}†at line {1}, column {2} of text “{3}â€","untermstr":"The string beginning at line {0}, column {1} is unterminated in text “{2}â€","badexpr":"Unexpected operator “{0}†at line {1}, column {2} in text. Was expecting “{3}â€. Text: “{4}â€","dupvalue":"The choice “{0}†is specified more than once. Duplicate key is at line {1}, column {2} in text “{3}â€","unsafe":"Use of select/plural MessageFormat syntax is currently disallowed in a secure context ({0}). At line {1}, column {2} of text “{3}â€","reqother":"“other†is a required option.","reqendinterp":"Expecting end of interpolation symbol, “{0}â€, at line {1}, column {2} in text “{3}â€","reqarg":"Expected one of “plural†or “select†at line {0}, column {1} of text “{2}â€","wantstring":"Expected the beginning of a string at line {0}, column {1} in text “{2}â€","logicbug":"The messageformat parser has encountered an internal error. Please file a github issue against the AngularJS project and provide this message text that triggers the bug. Text: “{0}â€","reqopenbrace":"The plural choice “{0}†must be followed by a message in braces at line {1}, column {2} in text “{3}â€","unknarg":"Unsupported keyword “{0}†at line {0}, column {1}. Only “plural†and “select†are currently supported. Text: “{3}â€","reqendbrace":"The plural/select choice “{0}†message starting at line {1}, column {2} does not have an ending closing brace. Text “{3}â€"},"ngOptions":{"iexp":"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}"},"$rootScope":{"inprog":"{0} already in progress","infdig":"{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}"},"$compile":{"noident":"Cannot bind to controller without identifier for directive '{0}'.","selmulti":"Binding to the 'multiple' attribute is not supported. Element: {0}","nodomevents":"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.","ctreq":"Controller '{0}', required by directive '{1}', can't be found!","nonassign":"Expression '{0}' used with directive '{1}' is non-assignable!","tplrt":"Template for directive '{0}' must have exactly one root element. {1}","iscp":"Invalid {3} for directive '{0}'. Definition: {... {1}: '{2}' ...}","baddir":"Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces","noctrl":"Cannot bind to controller without directive '{0}'s controller.","multidir":"Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}","tpload":"Failed to load template: {0} (HTTP status: {1} {2})","uterdir":"Unterminated attribute, found '{0}' but no matching '{1}' found."},"$resource":{"badargs":"Expected up to 4 arguments [params, data, success, error], got {0} arguments","badmember":"Dotted member path \"@{0}\" is invalid.","badname":"hasOwnProperty is not a valid parameter name.","badcfg":"Error in resource configuration for action `{0}`. Expected response to contain an {1} but got an {2} (Request: {3} {4})"},"$route":{"norout":"Tried updating route when with no current route"},"$sanitize":{"badparse":"The sanitizer was unable to parse the following block of html: {0}"}}} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-dj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-dj.js
new file mode 100644
index 00000000..2fe0c303
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-dj.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Acaada",
+ "Etleeni",
+ "Talaata",
+ "Arbaqa",
+ "Kamiisi",
+ "Gumqata",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Leqeeni",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Aca",
+ "Etl",
+ "Tal",
+ "Arb",
+ "Kam",
+ "Gum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Fdj",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "aa-dj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-er.js
new file mode 100644
index 00000000..48c1e7c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-er.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Acaada",
+ "Etleeni",
+ "Talaata",
+ "Arbaqa",
+ "Kamiisi",
+ "Gumqata",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Liiqen",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Aca",
+ "Etl",
+ "Tal",
+ "Arb",
+ "Kam",
+ "Gum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "aa-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-et.js
new file mode 100644
index 00000000..03b62551
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa-et.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Acaada",
+ "Etleeni",
+ "Talaata",
+ "Arbaqa",
+ "Kamiisi",
+ "Gumqata",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Liiqen",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Aca",
+ "Etl",
+ "Tal",
+ "Arb",
+ "Kam",
+ "Gum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "aa-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa.js
new file mode 100644
index 00000000..661fa2e1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_aa.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Acaada",
+ "Etleeni",
+ "Talaata",
+ "Arbaqa",
+ "Kamiisi",
+ "Gumqata",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Liiqen",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Aca",
+ "Etl",
+ "Tal",
+ "Arb",
+ "Kam",
+ "Gum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "aa",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-na.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-na.js
new file mode 100644
index 00000000..4647a92b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-na.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vm.",
+ "nm."
+ ],
+ "DAY": [
+ "Sondag",
+ "Maandag",
+ "Dinsdag",
+ "Woensdag",
+ "Donderdag",
+ "Vrydag",
+ "Saterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.C.",
+ "n.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januarie",
+ "Februarie",
+ "Maart",
+ "April",
+ "Mei",
+ "Junie",
+ "Julie",
+ "Augustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "So",
+ "Ma",
+ "Di",
+ "Wo",
+ "Do",
+ "Vr",
+ "Sa"
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "Mrt.",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "af-na",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-za.js
new file mode 100644
index 00000000..38c2217c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af-za.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vm.",
+ "nm."
+ ],
+ "DAY": [
+ "Sondag",
+ "Maandag",
+ "Dinsdag",
+ "Woensdag",
+ "Donderdag",
+ "Vrydag",
+ "Saterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.C.",
+ "n.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januarie",
+ "Februarie",
+ "Maart",
+ "April",
+ "Mei",
+ "Junie",
+ "Julie",
+ "Augustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "So",
+ "Ma",
+ "Di",
+ "Wo",
+ "Do",
+ "Vr",
+ "Sa"
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "Mrt.",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y-MM-dd h:mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "af-za",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af.js
new file mode 100644
index 00000000..9ed43d14
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_af.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vm.",
+ "nm."
+ ],
+ "DAY": [
+ "Sondag",
+ "Maandag",
+ "Dinsdag",
+ "Woensdag",
+ "Donderdag",
+ "Vrydag",
+ "Saterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.C.",
+ "n.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januarie",
+ "Februarie",
+ "Maart",
+ "April",
+ "Mei",
+ "Junie",
+ "Julie",
+ "Augustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "So",
+ "Ma",
+ "Di",
+ "Wo",
+ "Do",
+ "Vr",
+ "Sa"
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "Mrt.",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y-MM-dd h:mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "af",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq-cm.js
new file mode 100644
index 00000000..9d3f9e9c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.g",
+ "a.k"
+ ],
+ "DAY": [
+ "tsu\u0294nts\u0268",
+ "tsu\u0294ukp\u00e0",
+ "tsu\u0294ugh\u0254e",
+ "tsu\u0294ut\u0254\u0300ml\u00f2",
+ "tsu\u0294um\u00e8",
+ "tsu\u0294ugh\u0268\u0302m",
+ "tsu\u0294ndz\u0268k\u0254\u0294\u0254"
+ ],
+ "ERANAMES": [
+ "S\u011be K\u0268\u0300lesto",
+ "B\u01cea K\u0268\u0300lesto"
+ ],
+ "ERAS": [
+ "SK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
+ "ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300d\u0289\u0300gh\u00e0",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u01ceaf\u0289\u0304gh\u0101",
+ "ndz\u0254\u0300\u014b\u00e8s\u00e8e",
+ "ndz\u0254\u0300\u014b\u0254\u0300nz\u00f9gh\u00f2",
+ "ndz\u0254\u0300\u014b\u0254\u0300d\u00f9mlo",
+ "ndz\u0254\u0300\u014b\u0254\u0300kw\u00eef\u0254\u0300e",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300f\u0289\u0300gh\u00e0dzugh\u00f9",
+ "ndz\u0254\u0300\u014b\u0254\u0300gh\u01d4uwel\u0254\u0300m",
+ "ndz\u0254\u0300\u014b\u0254\u0300chwa\u0294\u00e0kaa wo",
+ "ndz\u0254\u0300\u014b\u00e8fw\u00f2o"
+ ],
+ "SHORTDAY": [
+ "nts",
+ "kpa",
+ "gh\u0254",
+ "t\u0254m",
+ "ume",
+ "gh\u0268",
+ "dzk"
+ ],
+ "SHORTMONTH": [
+ "n\u00f9m",
+ "k\u0268z",
+ "t\u0268d",
+ "taa",
+ "see",
+ "nzu",
+ "dum",
+ "f\u0254e",
+ "dzu",
+ "l\u0254m",
+ "kaa",
+ "fwo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "agq-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq.js
new file mode 100644
index 00000000..2bd28260
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_agq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.g",
+ "a.k"
+ ],
+ "DAY": [
+ "tsu\u0294nts\u0268",
+ "tsu\u0294ukp\u00e0",
+ "tsu\u0294ugh\u0254e",
+ "tsu\u0294ut\u0254\u0300ml\u00f2",
+ "tsu\u0294um\u00e8",
+ "tsu\u0294ugh\u0268\u0302m",
+ "tsu\u0294ndz\u0268k\u0254\u0294\u0254"
+ ],
+ "ERANAMES": [
+ "S\u011be K\u0268\u0300lesto",
+ "B\u01cea K\u0268\u0300lesto"
+ ],
+ "ERAS": [
+ "SK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ndz\u0254\u0300\u014b\u0254\u0300n\u00f9m",
+ "ndz\u0254\u0300\u014b\u0254\u0300k\u0197\u0300z\u00f9\u0294",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300d\u0289\u0300gh\u00e0",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u01ceaf\u0289\u0304gh\u0101",
+ "ndz\u0254\u0300\u014b\u00e8s\u00e8e",
+ "ndz\u0254\u0300\u014b\u0254\u0300nz\u00f9gh\u00f2",
+ "ndz\u0254\u0300\u014b\u0254\u0300d\u00f9mlo",
+ "ndz\u0254\u0300\u014b\u0254\u0300kw\u00eef\u0254\u0300e",
+ "ndz\u0254\u0300\u014b\u0254\u0300t\u0197\u0300f\u0289\u0300gh\u00e0dzugh\u00f9",
+ "ndz\u0254\u0300\u014b\u0254\u0300gh\u01d4uwel\u0254\u0300m",
+ "ndz\u0254\u0300\u014b\u0254\u0300chwa\u0294\u00e0kaa wo",
+ "ndz\u0254\u0300\u014b\u00e8fw\u00f2o"
+ ],
+ "SHORTDAY": [
+ "nts",
+ "kpa",
+ "gh\u0254",
+ "t\u0254m",
+ "ume",
+ "gh\u0268",
+ "dzk"
+ ],
+ "SHORTMONTH": [
+ "n\u00f9m",
+ "k\u0268z",
+ "t\u0268d",
+ "taa",
+ "see",
+ "nzu",
+ "dum",
+ "f\u0254e",
+ "dzu",
+ "l\u0254m",
+ "kaa",
+ "fwo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "agq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak-gh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak-gh.js
new file mode 100644
index 00000000..8407b96f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak-gh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AN",
+ "EW"
+ ],
+ "DAY": [
+ "Kwesida",
+ "Dwowda",
+ "Benada",
+ "Wukuda",
+ "Yawda",
+ "Fida",
+ "Memeneda"
+ ],
+ "ERANAMES": [
+ "Ansa Kristo",
+ "Kristo Ekyiri"
+ ],
+ "ERAS": [
+ "AK",
+ "KE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Sanda-\u0186p\u025bp\u0254n",
+ "Kwakwar-\u0186gyefuo",
+ "Eb\u0254w-\u0186benem",
+ "Eb\u0254bira-Oforisuo",
+ "Esusow Aketseaba-K\u0254t\u0254nimba",
+ "Obirade-Ay\u025bwohomumu",
+ "Ay\u025bwoho-Kitawonsa",
+ "Difuu-\u0186sandaa",
+ "Fankwa-\u0190b\u0254",
+ "\u0186b\u025bs\u025b-Ahinime",
+ "\u0186ber\u025bf\u025bw-Obubuo",
+ "Mumu-\u0186p\u025bnimba"
+ ],
+ "SHORTDAY": [
+ "Kwe",
+ "Dwo",
+ "Ben",
+ "Wuk",
+ "Yaw",
+ "Fia",
+ "Mem"
+ ],
+ "SHORTMONTH": [
+ "S-\u0186",
+ "K-\u0186",
+ "E-\u0186",
+ "E-O",
+ "E-K",
+ "O-A",
+ "A-K",
+ "D-\u0186",
+ "F-\u0190",
+ "\u0186-A",
+ "\u0186-O",
+ "M-\u0186"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ak-gh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak.js
new file mode 100644
index 00000000..9117b354
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ak.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AN",
+ "EW"
+ ],
+ "DAY": [
+ "Kwesida",
+ "Dwowda",
+ "Benada",
+ "Wukuda",
+ "Yawda",
+ "Fida",
+ "Memeneda"
+ ],
+ "ERANAMES": [
+ "Ansa Kristo",
+ "Kristo Ekyiri"
+ ],
+ "ERAS": [
+ "AK",
+ "KE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Sanda-\u0186p\u025bp\u0254n",
+ "Kwakwar-\u0186gyefuo",
+ "Eb\u0254w-\u0186benem",
+ "Eb\u0254bira-Oforisuo",
+ "Esusow Aketseaba-K\u0254t\u0254nimba",
+ "Obirade-Ay\u025bwohomumu",
+ "Ay\u025bwoho-Kitawonsa",
+ "Difuu-\u0186sandaa",
+ "Fankwa-\u0190b\u0254",
+ "\u0186b\u025bs\u025b-Ahinime",
+ "\u0186ber\u025bf\u025bw-Obubuo",
+ "Mumu-\u0186p\u025bnimba"
+ ],
+ "SHORTDAY": [
+ "Kwe",
+ "Dwo",
+ "Ben",
+ "Wuk",
+ "Yaw",
+ "Fia",
+ "Mem"
+ ],
+ "SHORTMONTH": [
+ "S-\u0186",
+ "K-\u0186",
+ "E-\u0186",
+ "E-O",
+ "E-K",
+ "O-A",
+ "A-K",
+ "D-\u0186",
+ "F-\u0190",
+ "\u0186-A",
+ "\u0186-O",
+ "M-\u0186"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ak",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am-et.js
new file mode 100644
index 00000000..77b38ff8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am-et.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1325\u12cb\u1275",
+ "\u12a8\u1230\u12d3\u1275"
+ ],
+ "DAY": [
+ "\u12a5\u1211\u12f5",
+ "\u1230\u129e",
+ "\u121b\u12ad\u1230\u129e",
+ "\u1228\u1261\u12d5",
+ "\u1210\u1219\u1235",
+ "\u12d3\u122d\u1265",
+ "\u1245\u12f3\u121c"
+ ],
+ "ERANAMES": [
+ "\u12d3\u1218\u1270 \u12d3\u1208\u121d",
+ "\u12d3\u1218\u1270 \u121d\u1215\u1228\u1275"
+ ],
+ "ERAS": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u122a\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1276\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u12a5\u1211\u12f5",
+ "\u1230\u129e",
+ "\u121b\u12ad\u1230",
+ "\u1228\u1261\u12d5",
+ "\u1210\u1219\u1235",
+ "\u12d3\u122d\u1265",
+ "\u1245\u12f3\u121c"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u122a",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1276",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "am-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am.js
new file mode 100644
index 00000000..03146492
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_am.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1325\u12cb\u1275",
+ "\u12a8\u1230\u12d3\u1275"
+ ],
+ "DAY": [
+ "\u12a5\u1211\u12f5",
+ "\u1230\u129e",
+ "\u121b\u12ad\u1230\u129e",
+ "\u1228\u1261\u12d5",
+ "\u1210\u1219\u1235",
+ "\u12d3\u122d\u1265",
+ "\u1245\u12f3\u121c"
+ ],
+ "ERANAMES": [
+ "\u12d3\u1218\u1270 \u12d3\u1208\u121d",
+ "\u12d3\u1218\u1270 \u121d\u1215\u1228\u1275"
+ ],
+ "ERAS": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u122a\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1276\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u12a5\u1211\u12f5",
+ "\u1230\u129e",
+ "\u121b\u12ad\u1230",
+ "\u1228\u1261\u12d5",
+ "\u1210\u1219\u1235",
+ "\u12d3\u122d\u1265",
+ "\u1245\u12f3\u121c"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u122a",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1276",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "am",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-001.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-001.js
new file mode 100644
index 00000000..a9a7875a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-001.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-001",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ae.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ae.js
new file mode 100644
index 00000000..6b335da1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ae.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ae",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-bh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-bh.js
new file mode 100644
index 00000000..361f8ab9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-bh.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-bh",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dj.js
new file mode 100644
index 00000000..d44bbce0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dj.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Fdj",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-dj",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dz.js
new file mode 100644
index 00000000..871d2ce4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-dz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0627\u0646\u0641\u064a",
+ "\u0641\u064a\u0641\u0631\u064a",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0641\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u062c\u0648\u0627\u0646",
+ "\u062c\u0648\u064a\u0644\u064a\u0629",
+ "\u0623\u0648\u062a",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0627\u0646\u0641\u064a",
+ "\u0641\u064a\u0641\u0631\u064a",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0641\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u062c\u0648\u0627\u0646",
+ "\u062c\u0648\u064a\u0644\u064a\u0629",
+ "\u0623\u0648\u062a",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-dz",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eg.js
new file mode 100644
index 00000000..734c629a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-eg",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eh.js
new file mode 100644
index 00000000..f9c2666a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-eh.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-eh",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-er.js
new file mode 100644
index 00000000..0510d70b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-er.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-er",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-il.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-il.js
new file mode 100644
index 00000000..ea6e8932
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-il.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20aa",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-il",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-iq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-iq.js
new file mode 100644
index 00000000..9f08ac2f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-iq.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-iq",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-jo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-jo.js
new file mode 100644
index 00000000..793b3534
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-jo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-jo",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-km.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-km.js
new file mode 100644
index 00000000..6f9031de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-km.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CF",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-km",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-kw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-kw.js
new file mode 100644
index 00000000..b0b55a7b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-kw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-kw",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-lb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-lb.js
new file mode 100644
index 00000000..b2eb263a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-lb.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "L\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-lb",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ly.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ly.js
new file mode 100644
index 00000000..0a9dbf62
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ly.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ly",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ma.js
new file mode 100644
index 00000000..589e258a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ma.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648\u0632",
+ "\u063a\u0634\u062a",
+ "\u0634\u062a\u0646\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0646\u0628\u0631",
+ "\u062f\u062c\u0646\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648\u0632",
+ "\u063a\u0634\u062a",
+ "\u0634\u062a\u0646\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0646\u0628\u0631",
+ "\u062f\u062c\u0646\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ma",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-mr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-mr.js
new file mode 100644
index 00000000..6fbc49a5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-mr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0625\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0634\u062a",
+ "\u0634\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u062c\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0625\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0634\u062a",
+ "\u0634\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u062c\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MRO",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-mr",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-om.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-om.js
new file mode 100644
index 00000000..b12fc576
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-om.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-om",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ps.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ps.js
new file mode 100644
index 00000000..0e5a8aec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ps.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20aa",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ps",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-qa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-qa.js
new file mode 100644
index 00000000..0007850d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-qa.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-qa",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sa.js
new file mode 100644
index 00000000..dcaa4a68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sa.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-sa",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sd.js
new file mode 100644
index 00000000..769ce9bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sd.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SDG",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-sd",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-so.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-so.js
new file mode 100644
index 00000000..4aea4a8e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-so.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SOS",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-so",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ss.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ss.js
new file mode 100644
index 00000000..23338b3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ss.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ss",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sy.js
new file mode 100644
index 00000000..80f4b5ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-sy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0634\u0628\u0627\u0637",
+ "\u0622\u0630\u0627\u0631",
+ "\u0646\u064a\u0633\u0627\u0646",
+ "\u0623\u064a\u0627\u0631",
+ "\u062d\u0632\u064a\u0631\u0627\u0646",
+ "\u062a\u0645\u0648\u0632",
+ "\u0622\u0628",
+ "\u0623\u064a\u0644\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644",
+ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a",
+ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-sy",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-td.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-td.js
new file mode 100644
index 00000000..408e9393
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-td.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-td",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-tn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-tn.js
new file mode 100644
index 00000000..2784ed5f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-tn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0627\u0646\u0641\u064a",
+ "\u0641\u064a\u0641\u0631\u064a",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0641\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u062c\u0648\u0627\u0646",
+ "\u062c\u0648\u064a\u0644\u064a\u0629",
+ "\u0623\u0648\u062a",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0627\u0646\u0641\u064a",
+ "\u0641\u064a\u0641\u0631\u064a",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0641\u0631\u064a\u0644",
+ "\u0645\u0627\u064a",
+ "\u062c\u0648\u0627\u0646",
+ "\u062c\u0648\u064a\u0644\u064a\u0629",
+ "\u0623\u0648\u062a",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-tn",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ye.js
new file mode 100644
index 00000000..700b4aef
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar-ye.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar-ye",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar.js
new file mode 100644
index 00000000..dd58093d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ar.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0635",
+ "\u0645"
+ ],
+ "DAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0644\u0645\u064a\u0644\u0627\u062f",
+ "\u0645\u064a\u0644\u0627\u062f\u064a"
+ ],
+ "ERAS": [
+ "\u0642.\u0645",
+ "\u0645"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u0644\u0623\u062d\u062f",
+ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
+ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
+ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
+ "\u0627\u0644\u062e\u0645\u064a\u0633",
+ "\u0627\u0644\u062c\u0645\u0639\u0629",
+ "\u0627\u0644\u0633\u0628\u062a"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0646\u0627\u064a\u0631",
+ "\u0641\u0628\u0631\u0627\u064a\u0631",
+ "\u0645\u0627\u0631\u0633",
+ "\u0623\u0628\u0631\u064a\u0644",
+ "\u0645\u0627\u064a\u0648",
+ "\u064a\u0648\u0646\u064a\u0648",
+ "\u064a\u0648\u0644\u064a\u0648",
+ "\u0623\u063a\u0633\u0637\u0633",
+ "\u0633\u0628\u062a\u0645\u0628\u0631",
+ "\u0623\u0643\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0641\u0645\u0628\u0631",
+ "\u062f\u064a\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "dd\u200f/MM\u200f/y h:mm:ss a",
+ "mediumDate": "dd\u200f/MM\u200f/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d\u200f/M\u200f/y h:mm a",
+ "shortDate": "d\u200f/M\u200f/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ar",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as-in.js
new file mode 100644
index 00000000..27f59242
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u09aa\u09c2\u09f0\u09cd\u09ac\u09be\u09b9\u09cd\u09a3",
+ "\u0985\u09aa\u09f0\u09be\u09b9\u09cd\u09a3"
+ ],
+ "DAY": [
+ "\u09a6\u09c7\u0993\u09ac\u09be\u09f0",
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09f0",
+ "\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09f0",
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09f0",
+ "\u09ac\u09c3\u09b9\u09b7\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09f0",
+ "\u09b6\u09c1\u0995\u09cd\u09f0\u09ac\u09be\u09f0",
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09f0"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09f1\u09be\u09f0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09f0\u09c1\u09f1\u09be\u09f0\u09c0",
+ "\u09ae\u09be\u09f0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09f0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b7\u09cd\u099f",
+ "\u099b\u09c7\u09aa\u09cd\u09a4\u09c7\u09ae\u09cd\u09ac\u09f0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09f0",
+ "\u09a8\u09f1\u09c7\u09ae\u09cd\u09ac\u09f0",
+ "\u09a1\u09bf\u099a\u09c7\u09ae\u09cd\u09ac\u09f0"
+ ],
+ "SHORTDAY": [
+ "\u09f0\u09ac\u09bf",
+ "\u09b8\u09cb\u09ae",
+ "\u09ae\u0999\u09cd\u0997\u09b2",
+ "\u09ac\u09c1\u09a7",
+ "\u09ac\u09c3\u09b9\u09b7\u09cd\u09aa\u09a4\u09bf",
+ "\u09b6\u09c1\u0995\u09cd\u09f0",
+ "\u09b6\u09a8\u09bf"
+ ],
+ "SHORTMONTH": [
+ "\u099c\u09be\u09a8\u09c1",
+ "\u09ab\u09c7\u09ac\u09cd\u09f0\u09c1",
+ "\u09ae\u09be\u09f0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09f0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997",
+ "\u09b8\u09c7\u09aa\u09cd\u099f",
+ "\u0985\u0995\u09cd\u099f\u09cb",
+ "\u09a8\u09ad\u09c7",
+ "\u09a1\u09bf\u09b8\u09c7"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "dd-MM-y h.mm.ss a",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "h.mm.ss a",
+ "short": "d-M-y h.mm. a",
+ "shortDate": "d-M-y",
+ "shortTime": "h.mm. a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "as-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as.js
new file mode 100644
index 00000000..5172d54c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_as.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u09aa\u09c2\u09f0\u09cd\u09ac\u09be\u09b9\u09cd\u09a3",
+ "\u0985\u09aa\u09f0\u09be\u09b9\u09cd\u09a3"
+ ],
+ "DAY": [
+ "\u09a6\u09c7\u0993\u09ac\u09be\u09f0",
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09f0",
+ "\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09f0",
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09f0",
+ "\u09ac\u09c3\u09b9\u09b7\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09f0",
+ "\u09b6\u09c1\u0995\u09cd\u09f0\u09ac\u09be\u09f0",
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09f0"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09f1\u09be\u09f0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09f0\u09c1\u09f1\u09be\u09f0\u09c0",
+ "\u09ae\u09be\u09f0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09f0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b7\u09cd\u099f",
+ "\u099b\u09c7\u09aa\u09cd\u09a4\u09c7\u09ae\u09cd\u09ac\u09f0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09f0",
+ "\u09a8\u09f1\u09c7\u09ae\u09cd\u09ac\u09f0",
+ "\u09a1\u09bf\u099a\u09c7\u09ae\u09cd\u09ac\u09f0"
+ ],
+ "SHORTDAY": [
+ "\u09f0\u09ac\u09bf",
+ "\u09b8\u09cb\u09ae",
+ "\u09ae\u0999\u09cd\u0997\u09b2",
+ "\u09ac\u09c1\u09a7",
+ "\u09ac\u09c3\u09b9\u09b7\u09cd\u09aa\u09a4\u09bf",
+ "\u09b6\u09c1\u0995\u09cd\u09f0",
+ "\u09b6\u09a8\u09bf"
+ ],
+ "SHORTMONTH": [
+ "\u099c\u09be\u09a8\u09c1",
+ "\u09ab\u09c7\u09ac\u09cd\u09f0\u09c1",
+ "\u09ae\u09be\u09f0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09f0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997",
+ "\u09b8\u09c7\u09aa\u09cd\u099f",
+ "\u0985\u0995\u09cd\u099f\u09cb",
+ "\u09a8\u09ad\u09c7",
+ "\u09a1\u09bf\u09b8\u09c7"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "dd-MM-y h.mm.ss a",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "h.mm.ss a",
+ "short": "d-M-y h.mm. a",
+ "shortDate": "d-M-y",
+ "shortTime": "h.mm. a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "as",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa-tz.js
new file mode 100644
index 00000000..5add04ff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "icheheavo",
+ "ichamthi"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla yakwe Yethu",
+ "Baada yakwe Yethu"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Ijm",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "asa-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa.js
new file mode 100644
index 00000000..05e1f0bc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_asa.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "icheheavo",
+ "ichamthi"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla yakwe Yethu",
+ "Baada yakwe Yethu"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Ijm",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "asa",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast-es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast-es.js
new file mode 100644
index 00000000..af513b1a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast-es.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domingu",
+ "llunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "xueves",
+ "vienres",
+ "s\u00e1badu"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de xineru",
+ "de febreru",
+ "de marzu",
+ "d\u2019abril",
+ "de mayu",
+ "de xunu",
+ "de xunetu",
+ "d\u2019agostu",
+ "de setiembre",
+ "d\u2019ochobre",
+ "de payares",
+ "d\u2019avientu"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "llu",
+ "mar",
+ "mie",
+ "xue",
+ "vie",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "xin",
+ "feb",
+ "mar",
+ "abr",
+ "may",
+ "xun",
+ "xnt",
+ "ago",
+ "set",
+ "och",
+ "pay",
+ "avi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ast-es",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast.js
new file mode 100644
index 00000000..2fc061ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ast.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domingu",
+ "llunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "xueves",
+ "vienres",
+ "s\u00e1badu"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de xineru",
+ "de febreru",
+ "de marzu",
+ "d\u2019abril",
+ "de mayu",
+ "de xunu",
+ "de xunetu",
+ "d\u2019agostu",
+ "de setiembre",
+ "d\u2019ochobre",
+ "de payares",
+ "d\u2019avientu"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "llu",
+ "mar",
+ "mie",
+ "xue",
+ "vie",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "xin",
+ "feb",
+ "mar",
+ "abr",
+ "may",
+ "xun",
+ "xnt",
+ "ago",
+ "set",
+ "och",
+ "pay",
+ "avi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ast",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl-az.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl-az.js
new file mode 100644
index 00000000..1b9a6ad9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl-az.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0431\u0430\u0437\u0430\u0440",
+ "\u0431\u0430\u0437\u0430\u0440 \u0435\u0440\u0442\u04d9\u0441\u0438",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9",
+ "\u04b9\u04af\u043c\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u04b9\u04af\u043c\u04d9",
+ "\u0448\u04d9\u043d\u0431\u04d9"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0432\u0430\u0440",
+ "\u0444\u0435\u0432\u0440\u0430\u043b",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b",
+ "\u043c\u0430\u0439",
+ "\u0438\u0458\u0443\u043d",
+ "\u0438\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u0458\u0430\u0431\u0440",
+ "\u043e\u043a\u0442\u0458\u0430\u0431\u0440",
+ "\u043d\u043e\u0458\u0430\u0431\u0440",
+ "\u0434\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u0431\u0430\u0437\u0430\u0440",
+ "\u0431\u0430\u0437\u0430\u0440 \u0435\u0440\u0442\u04d9\u0441\u0438",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9",
+ "\u04b9\u04af\u043c\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u04b9\u04af\u043c\u04d9",
+ "\u0448\u04d9\u043d\u0431\u04d9"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d\u0432\u0430\u0440",
+ "\u0444\u0435\u0432\u0440\u0430\u043b",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b",
+ "\u043c\u0430\u0439",
+ "\u0438\u0458\u0443\u043d",
+ "\u0438\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u0458\u0430\u0431\u0440",
+ "\u043e\u043a\u0442\u0458\u0430\u0431\u0440",
+ "\u043d\u043e\u0458\u0430\u0431\u0440",
+ "\u0434\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d, MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "man.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "az-cyrl-az",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl.js
new file mode 100644
index 00000000..d9f52819
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-cyrl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0431\u0430\u0437\u0430\u0440",
+ "\u0431\u0430\u0437\u0430\u0440 \u0435\u0440\u0442\u04d9\u0441\u0438",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9",
+ "\u04b9\u04af\u043c\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u04b9\u04af\u043c\u04d9",
+ "\u0448\u04d9\u043d\u0431\u04d9"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0432\u0430\u0440",
+ "\u0444\u0435\u0432\u0440\u0430\u043b",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b",
+ "\u043c\u0430\u0439",
+ "\u0438\u0458\u0443\u043d",
+ "\u0438\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u0458\u0430\u0431\u0440",
+ "\u043e\u043a\u0442\u0458\u0430\u0431\u0440",
+ "\u043d\u043e\u0458\u0430\u0431\u0440",
+ "\u0434\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u0431\u0430\u0437\u0430\u0440",
+ "\u0431\u0430\u0437\u0430\u0440 \u0435\u0440\u0442\u04d9\u0441\u0438",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u0447\u04d9\u0440\u0448\u04d9\u043d\u0431\u04d9",
+ "\u04b9\u04af\u043c\u04d9 \u0430\u0445\u0448\u0430\u043c\u044b",
+ "\u04b9\u04af\u043c\u04d9",
+ "\u0448\u04d9\u043d\u0431\u04d9"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d\u0432\u0430\u0440",
+ "\u0444\u0435\u0432\u0440\u0430\u043b",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b",
+ "\u043c\u0430\u0439",
+ "\u0438\u0458\u0443\u043d",
+ "\u0438\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u0458\u0430\u0431\u0440",
+ "\u043e\u043a\u0442\u0458\u0430\u0431\u0440",
+ "\u043d\u043e\u0458\u0430\u0431\u0440",
+ "\u0434\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d, MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "man.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "az-cyrl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn-az.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn-az.js
new file mode 100644
index 00000000..72ff9e80
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn-az.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "bazar",
+ "bazar ert\u0259si",
+ "\u00e7\u0259r\u015f\u0259nb\u0259 ax\u015fam\u0131",
+ "\u00e7\u0259r\u015f\u0259nb\u0259",
+ "c\u00fcm\u0259 ax\u015fam\u0131",
+ "c\u00fcm\u0259",
+ "\u015f\u0259nb\u0259"
+ ],
+ "ERANAMES": [
+ "eram\u0131zdan \u0259vv\u0259l",
+ "bizim eram\u0131z\u0131n"
+ ],
+ "ERAS": [
+ "e.\u0259.",
+ "b.e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "yanvar",
+ "fevral",
+ "mart",
+ "aprel",
+ "may",
+ "iyun",
+ "iyul",
+ "avqust",
+ "sentyabr",
+ "oktyabr",
+ "noyabr",
+ "dekabr"
+ ],
+ "SHORTDAY": [
+ "B.",
+ "B.E.",
+ "\u00c7.A.",
+ "\u00c7.",
+ "C.A.",
+ "C.",
+ "\u015e."
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fev",
+ "mar",
+ "apr",
+ "may",
+ "iyn",
+ "iyl",
+ "avq",
+ "sen",
+ "okt",
+ "noy",
+ "dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y, EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "man.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "az-latn-az",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn.js
new file mode 100644
index 00000000..c01135c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az-latn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "bazar",
+ "bazar ert\u0259si",
+ "\u00e7\u0259r\u015f\u0259nb\u0259 ax\u015fam\u0131",
+ "\u00e7\u0259r\u015f\u0259nb\u0259",
+ "c\u00fcm\u0259 ax\u015fam\u0131",
+ "c\u00fcm\u0259",
+ "\u015f\u0259nb\u0259"
+ ],
+ "ERANAMES": [
+ "eram\u0131zdan \u0259vv\u0259l",
+ "bizim eram\u0131z\u0131n"
+ ],
+ "ERAS": [
+ "e.\u0259.",
+ "b.e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "yanvar",
+ "fevral",
+ "mart",
+ "aprel",
+ "may",
+ "iyun",
+ "iyul",
+ "avqust",
+ "sentyabr",
+ "oktyabr",
+ "noyabr",
+ "dekabr"
+ ],
+ "SHORTDAY": [
+ "B.",
+ "B.E.",
+ "\u00c7.A.",
+ "\u00c7.",
+ "C.A.",
+ "C.",
+ "\u015e."
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fev",
+ "mar",
+ "apr",
+ "may",
+ "iyn",
+ "iyl",
+ "avq",
+ "sen",
+ "okt",
+ "noy",
+ "dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y, EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "man.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "az-latn",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az.js
new file mode 100644
index 00000000..df1dd9e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_az.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "bazar",
+ "bazar ert\u0259si",
+ "\u00e7\u0259r\u015f\u0259nb\u0259 ax\u015fam\u0131",
+ "\u00e7\u0259r\u015f\u0259nb\u0259",
+ "c\u00fcm\u0259 ax\u015fam\u0131",
+ "c\u00fcm\u0259",
+ "\u015f\u0259nb\u0259"
+ ],
+ "ERANAMES": [
+ "eram\u0131zdan \u0259vv\u0259l",
+ "bizim eram\u0131z\u0131n"
+ ],
+ "ERAS": [
+ "e.\u0259.",
+ "b.e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "yanvar",
+ "fevral",
+ "mart",
+ "aprel",
+ "may",
+ "iyun",
+ "iyul",
+ "avqust",
+ "sentyabr",
+ "oktyabr",
+ "noyabr",
+ "dekabr"
+ ],
+ "SHORTDAY": [
+ "B.",
+ "B.E.",
+ "\u00c7.A.",
+ "\u00c7.",
+ "C.A.",
+ "C.",
+ "\u015e."
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fev",
+ "mar",
+ "apr",
+ "may",
+ "iyn",
+ "iyl",
+ "avq",
+ "sen",
+ "okt",
+ "noy",
+ "dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y, EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "man.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "az",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas-cm.js
new file mode 100644
index 00000000..ccc7ea07
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "I bik\u025b\u0302gl\u00e0",
+ "I \u0253ugaj\u0254p"
+ ],
+ "DAY": [
+ "\u014bgw\u00e0 n\u0254\u0302y",
+ "\u014bgw\u00e0 nja\u014bgumba",
+ "\u014bgw\u00e0 \u00fbm",
+ "\u014bgw\u00e0 \u014bg\u00ea",
+ "\u014bgw\u00e0 mb\u0254k",
+ "\u014bgw\u00e0 k\u0254\u0254",
+ "\u014bgw\u00e0 j\u00f4n"
+ ],
+ "ERANAMES": [
+ "bis\u016b bi Yes\u00f9 Kr\u01d0st\u00f2",
+ "i mb\u016bs Yes\u00f9 Kr\u01d0st\u00f2"
+ ],
+ "ERAS": [
+ "b.Y.K",
+ "m.Y.K"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "K\u0254nd\u0254\u014b",
+ "M\u00e0c\u025b\u0302l",
+ "M\u00e0t\u00f9mb",
+ "M\u00e0top",
+ "M\u0300puy\u025b",
+ "H\u00ecl\u00f2nd\u025b\u0300",
+ "Nj\u00e8b\u00e0",
+ "H\u00ecka\u014b",
+ "D\u00ecp\u0254\u0300s",
+ "B\u00ec\u00f2\u00f4m",
+ "M\u00e0y\u025bs\u00e8p",
+ "L\u00ecbuy li \u0144y\u00e8e"
+ ],
+ "SHORTDAY": [
+ "n\u0254y",
+ "nja",
+ "uum",
+ "\u014bge",
+ "mb\u0254",
+ "k\u0254\u0254",
+ "jon"
+ ],
+ "SHORTMONTH": [
+ "k\u0254n",
+ "mac",
+ "mat",
+ "mto",
+ "mpu",
+ "hil",
+ "nje",
+ "hik",
+ "dip",
+ "bio",
+ "may",
+ "li\u0253"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bas-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas.js
new file mode 100644
index 00000000..e32cc420
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bas.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "I bik\u025b\u0302gl\u00e0",
+ "I \u0253ugaj\u0254p"
+ ],
+ "DAY": [
+ "\u014bgw\u00e0 n\u0254\u0302y",
+ "\u014bgw\u00e0 nja\u014bgumba",
+ "\u014bgw\u00e0 \u00fbm",
+ "\u014bgw\u00e0 \u014bg\u00ea",
+ "\u014bgw\u00e0 mb\u0254k",
+ "\u014bgw\u00e0 k\u0254\u0254",
+ "\u014bgw\u00e0 j\u00f4n"
+ ],
+ "ERANAMES": [
+ "bis\u016b bi Yes\u00f9 Kr\u01d0st\u00f2",
+ "i mb\u016bs Yes\u00f9 Kr\u01d0st\u00f2"
+ ],
+ "ERAS": [
+ "b.Y.K",
+ "m.Y.K"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "K\u0254nd\u0254\u014b",
+ "M\u00e0c\u025b\u0302l",
+ "M\u00e0t\u00f9mb",
+ "M\u00e0top",
+ "M\u0300puy\u025b",
+ "H\u00ecl\u00f2nd\u025b\u0300",
+ "Nj\u00e8b\u00e0",
+ "H\u00ecka\u014b",
+ "D\u00ecp\u0254\u0300s",
+ "B\u00ec\u00f2\u00f4m",
+ "M\u00e0y\u025bs\u00e8p",
+ "L\u00ecbuy li \u0144y\u00e8e"
+ ],
+ "SHORTDAY": [
+ "n\u0254y",
+ "nja",
+ "uum",
+ "\u014bge",
+ "mb\u0254",
+ "k\u0254\u0254",
+ "jon"
+ ],
+ "SHORTMONTH": [
+ "k\u0254n",
+ "mac",
+ "mat",
+ "mto",
+ "mpu",
+ "hil",
+ "nje",
+ "hik",
+ "dip",
+ "bio",
+ "may",
+ "li\u0253"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bas",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be-by.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be-by.js
new file mode 100644
index 00000000..87fb319b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be-by.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0434\u0430 \u043f\u0430\u043b\u0443\u0434\u043d\u044f",
+ "\u043f\u0430\u0441\u043b\u044f \u043f\u0430\u043b\u0443\u0434\u043d\u044f"
+ ],
+ "DAY": [
+ "\u043d\u044f\u0434\u0437\u0435\u043b\u044f",
+ "\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a",
+ "\u0430\u045e\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0435\u0440\u0430\u0434\u0430",
+ "\u0447\u0430\u0446\u0432\u0435\u0440",
+ "\u043f\u044f\u0442\u043d\u0456\u0446\u0430",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u0430 \u043d.\u044d.",
+ "\u043d.\u044d."
+ ],
+ "ERAS": [
+ "\u0434\u0430 \u043d.\u044d.",
+ "\u043d.\u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f",
+ "\u043b\u044e\u0442\u0430\u0433\u0430",
+ "\u0441\u0430\u043a\u0430\u0432\u0456\u043a\u0430",
+ "\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a\u0430",
+ "\u043c\u0430\u044f",
+ "\u0447\u044d\u0440\u0432\u0435\u043d\u044f",
+ "\u043b\u0456\u043f\u0435\u043d\u044f",
+ "\u0436\u043d\u0456\u045e\u043d\u044f",
+ "\u0432\u0435\u0440\u0430\u0441\u043d\u044f",
+ "\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430",
+ "\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430",
+ "\u0441\u043d\u0435\u0436\u043d\u044f"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0434",
+ "\u043f\u043d",
+ "\u0430\u045e",
+ "\u0441\u0440",
+ "\u0447\u0446",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0441\u0442\u0443",
+ "\u043b\u044e\u0442",
+ "\u0441\u0430\u043a",
+ "\u043a\u0440\u0430",
+ "\u043c\u0430\u044f",
+ "\u0447\u044d\u0440",
+ "\u043b\u0456\u043f",
+ "\u0436\u043d\u0456",
+ "\u0432\u0435\u0440",
+ "\u043a\u0430\u0441",
+ "\u043b\u0456\u0441",
+ "\u0441\u043d\u0435"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d.M.y HH.mm.ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy HH.mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "BYR",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "be-by",
+ "pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be.js
new file mode 100644
index 00000000..8baa3ced
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_be.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0434\u0430 \u043f\u0430\u043b\u0443\u0434\u043d\u044f",
+ "\u043f\u0430\u0441\u043b\u044f \u043f\u0430\u043b\u0443\u0434\u043d\u044f"
+ ],
+ "DAY": [
+ "\u043d\u044f\u0434\u0437\u0435\u043b\u044f",
+ "\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a",
+ "\u0430\u045e\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0435\u0440\u0430\u0434\u0430",
+ "\u0447\u0430\u0446\u0432\u0435\u0440",
+ "\u043f\u044f\u0442\u043d\u0456\u0446\u0430",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u0430 \u043d.\u044d.",
+ "\u043d.\u044d."
+ ],
+ "ERAS": [
+ "\u0434\u0430 \u043d.\u044d.",
+ "\u043d.\u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f",
+ "\u043b\u044e\u0442\u0430\u0433\u0430",
+ "\u0441\u0430\u043a\u0430\u0432\u0456\u043a\u0430",
+ "\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a\u0430",
+ "\u043c\u0430\u044f",
+ "\u0447\u044d\u0440\u0432\u0435\u043d\u044f",
+ "\u043b\u0456\u043f\u0435\u043d\u044f",
+ "\u0436\u043d\u0456\u045e\u043d\u044f",
+ "\u0432\u0435\u0440\u0430\u0441\u043d\u044f",
+ "\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430",
+ "\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430",
+ "\u0441\u043d\u0435\u0436\u043d\u044f"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0434",
+ "\u043f\u043d",
+ "\u0430\u045e",
+ "\u0441\u0440",
+ "\u0447\u0446",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0441\u0442\u0443",
+ "\u043b\u044e\u0442",
+ "\u0441\u0430\u043a",
+ "\u043a\u0440\u0430",
+ "\u043c\u0430\u044f",
+ "\u0447\u044d\u0440",
+ "\u043b\u0456\u043f",
+ "\u0436\u043d\u0456",
+ "\u0432\u0435\u0440",
+ "\u043a\u0430\u0441",
+ "\u043b\u0456\u0441",
+ "\u0441\u043d\u0435"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d.M.y HH.mm.ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy HH.mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "BYR",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "be",
+ "pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem-zm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem-zm.js
new file mode 100644
index 00000000..307347a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem-zm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "uluchelo",
+ "akasuba"
+ ],
+ "DAY": [
+ "Pa Mulungu",
+ "Palichimo",
+ "Palichibuli",
+ "Palichitatu",
+ "Palichine",
+ "Palichisano",
+ "Pachibelushi"
+ ],
+ "ERANAMES": [
+ "Before Yesu",
+ "After Yesu"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Epreo",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Ogasti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Pa Mulungu",
+ "Palichimo",
+ "Palichibuli",
+ "Palichitatu",
+ "Palichine",
+ "Palichisano",
+ "Pachibelushi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Epr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Oga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "ZMW",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bem-zm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem.js
new file mode 100644
index 00000000..99778938
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bem.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "uluchelo",
+ "akasuba"
+ ],
+ "DAY": [
+ "Pa Mulungu",
+ "Palichimo",
+ "Palichibuli",
+ "Palichitatu",
+ "Palichine",
+ "Palichisano",
+ "Pachibelushi"
+ ],
+ "ERANAMES": [
+ "Before Yesu",
+ "After Yesu"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Epreo",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Ogasti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Pa Mulungu",
+ "Palichimo",
+ "Palichibuli",
+ "Palichitatu",
+ "Palichine",
+ "Palichisano",
+ "Pachibelushi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Epr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Oga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "ZMW",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bem",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez-tz.js
new file mode 100644
index 00000000..d8d80a1b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pamilau",
+ "pamunyi"
+ ],
+ "DAY": [
+ "pa mulungu",
+ "pa shahuviluha",
+ "pa hivili",
+ "pa hidatu",
+ "pa hitayi",
+ "pa hihanu",
+ "pa shahulembela"
+ ],
+ "ERANAMES": [
+ "Kabla ya Mtwaa",
+ "Baada ya Mtwaa"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pa mwedzi gwa hutala",
+ "pa mwedzi gwa wuvili",
+ "pa mwedzi gwa wudatu",
+ "pa mwedzi gwa wutai",
+ "pa mwedzi gwa wuhanu",
+ "pa mwedzi gwa sita",
+ "pa mwedzi gwa saba",
+ "pa mwedzi gwa nane",
+ "pa mwedzi gwa tisa",
+ "pa mwedzi gwa kumi",
+ "pa mwedzi gwa kumi na moja",
+ "pa mwedzi gwa kumi na mbili"
+ ],
+ "SHORTDAY": [
+ "Mul",
+ "Vil",
+ "Hiv",
+ "Hid",
+ "Hit",
+ "Hih",
+ "Lem"
+ ],
+ "SHORTMONTH": [
+ "Hut",
+ "Vil",
+ "Dat",
+ "Tai",
+ "Han",
+ "Sit",
+ "Sab",
+ "Nan",
+ "Tis",
+ "Kum",
+ "Kmj",
+ "Kmb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "bez-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez.js
new file mode 100644
index 00000000..a240ee9b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bez.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pamilau",
+ "pamunyi"
+ ],
+ "DAY": [
+ "pa mulungu",
+ "pa shahuviluha",
+ "pa hivili",
+ "pa hidatu",
+ "pa hitayi",
+ "pa hihanu",
+ "pa shahulembela"
+ ],
+ "ERANAMES": [
+ "Kabla ya Mtwaa",
+ "Baada ya Mtwaa"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pa mwedzi gwa hutala",
+ "pa mwedzi gwa wuvili",
+ "pa mwedzi gwa wudatu",
+ "pa mwedzi gwa wutai",
+ "pa mwedzi gwa wuhanu",
+ "pa mwedzi gwa sita",
+ "pa mwedzi gwa saba",
+ "pa mwedzi gwa nane",
+ "pa mwedzi gwa tisa",
+ "pa mwedzi gwa kumi",
+ "pa mwedzi gwa kumi na moja",
+ "pa mwedzi gwa kumi na mbili"
+ ],
+ "SHORTDAY": [
+ "Mul",
+ "Vil",
+ "Hiv",
+ "Hid",
+ "Hit",
+ "Hih",
+ "Lem"
+ ],
+ "SHORTMONTH": [
+ "Hut",
+ "Vil",
+ "Dat",
+ "Tai",
+ "Han",
+ "Sit",
+ "Sab",
+ "Nan",
+ "Tis",
+ "Kum",
+ "Kmj",
+ "Kmb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "bez",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg-bg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg-bg.js
new file mode 100644
index 00000000..984801da
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg-bg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440.\u043e\u0431.",
+ "\u0441\u043b.\u043e\u0431."
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u043b\u044f",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u044f\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a",
+ "\u043f\u0435\u0442\u044a\u043a",
+ "\u0441\u044a\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u043f\u0440\u0435\u0434\u0438 \u0425\u0440\u0438\u0441\u0442\u0430",
+ "\u0441\u043b\u0435\u0434 \u0425\u0440\u0438\u0441\u0442\u0430"
+ ],
+ "ERAS": [
+ "\u043f\u0440.\u0425\u0440.",
+ "\u0441\u043b.\u0425\u0440."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0443\u0430\u0440\u0438",
+ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0439",
+ "\u044e\u043d\u0438",
+ "\u044e\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438",
+ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
+ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
+ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0434",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0439",
+ "\u044e\u043d\u0438",
+ "\u044e\u043b\u0438",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043f\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u0435\u043c.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d.MM.y '\u0433'. H:mm:ss",
+ "mediumDate": "d.MM.y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "d.MM.yy '\u0433'. H:mm",
+ "shortDate": "d.MM.yy '\u0433'.",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "lev",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bg-bg",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg.js
new file mode 100644
index 00000000..1bfb1328
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440.\u043e\u0431.",
+ "\u0441\u043b.\u043e\u0431."
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u043b\u044f",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u044f\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a",
+ "\u043f\u0435\u0442\u044a\u043a",
+ "\u0441\u044a\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u043f\u0440\u0435\u0434\u0438 \u0425\u0440\u0438\u0441\u0442\u0430",
+ "\u0441\u043b\u0435\u0434 \u0425\u0440\u0438\u0441\u0442\u0430"
+ ],
+ "ERAS": [
+ "\u043f\u0440.\u0425\u0440.",
+ "\u0441\u043b.\u0425\u0440."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0443\u0430\u0440\u0438",
+ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0439",
+ "\u044e\u043d\u0438",
+ "\u044e\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438",
+ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
+ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
+ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0434",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0439",
+ "\u044e\u043d\u0438",
+ "\u044e\u043b\u0438",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043f\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u0435\u043c.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d.MM.y '\u0433'. H:mm:ss",
+ "mediumDate": "d.MM.y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "d.MM.yy '\u0433'. H:mm",
+ "shortDate": "d.MM.yy '\u0433'.",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "lev",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bg",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn-ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn-ml.js
new file mode 100644
index 00000000..6a0b184a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn-ml.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "kari",
+ "nt\u025bn\u025b",
+ "tarata",
+ "araba",
+ "alamisa",
+ "juma",
+ "sibiri"
+ ],
+ "ERANAMES": [
+ "jezu krisiti \u0272\u025b",
+ "jezu krisiti mink\u025b"
+ ],
+ "ERAS": [
+ "J.-C. \u0272\u025b",
+ "ni J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "zanwuye",
+ "feburuye",
+ "marisi",
+ "awirili",
+ "m\u025b",
+ "zuw\u025bn",
+ "zuluye",
+ "uti",
+ "s\u025btanburu",
+ "\u0254kut\u0254buru",
+ "nowanburu",
+ "desanburu"
+ ],
+ "SHORTDAY": [
+ "kar",
+ "nt\u025b",
+ "tar",
+ "ara",
+ "ala",
+ "jum",
+ "sib"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "feb",
+ "mar",
+ "awi",
+ "m\u025b",
+ "zuw",
+ "zul",
+ "uti",
+ "s\u025bt",
+ "\u0254ku",
+ "now",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bm-latn-ml",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn.js
new file mode 100644
index 00000000..686fcf15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "kari",
+ "nt\u025bn\u025b",
+ "tarata",
+ "araba",
+ "alamisa",
+ "juma",
+ "sibiri"
+ ],
+ "ERANAMES": [
+ "jezu krisiti \u0272\u025b",
+ "jezu krisiti mink\u025b"
+ ],
+ "ERAS": [
+ "J.-C. \u0272\u025b",
+ "ni J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "zanwuye",
+ "feburuye",
+ "marisi",
+ "awirili",
+ "m\u025b",
+ "zuw\u025bn",
+ "zuluye",
+ "uti",
+ "s\u025btanburu",
+ "\u0254kut\u0254buru",
+ "nowanburu",
+ "desanburu"
+ ],
+ "SHORTDAY": [
+ "kar",
+ "nt\u025b",
+ "tar",
+ "ara",
+ "ala",
+ "jum",
+ "sib"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "feb",
+ "mar",
+ "awi",
+ "m\u025b",
+ "zuw",
+ "zul",
+ "uti",
+ "s\u025bt",
+ "\u0254ku",
+ "now",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bm-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-ml.js
new file mode 100644
index 00000000..1fd18527
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm-ml.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "kari",
+ "nt\u025bn\u025b",
+ "tarata",
+ "araba",
+ "alamisa",
+ "juma",
+ "sibiri"
+ ],
+ "MONTH": [
+ "zanwuye",
+ "feburuye",
+ "marisi",
+ "awirili",
+ "m\u025b",
+ "zuw\u025bn",
+ "zuluye",
+ "uti",
+ "s\u025btanburu",
+ "\u0254kut\u0254buru",
+ "nowanburu",
+ "desanburu"
+ ],
+ "SHORTDAY": [
+ "kar",
+ "nt\u025b",
+ "tar",
+ "ara",
+ "ala",
+ "jum",
+ "sib"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "feb",
+ "mar",
+ "awi",
+ "m\u025b",
+ "zuw",
+ "zul",
+ "uti",
+ "s\u025bt",
+ "\u0254ku",
+ "now",
+ "des"
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bm-ml",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm.js
new file mode 100644
index 00000000..30c2cf0b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "kari",
+ "nt\u025bn\u025b",
+ "tarata",
+ "araba",
+ "alamisa",
+ "juma",
+ "sibiri"
+ ],
+ "ERANAMES": [
+ "jezu krisiti \u0272\u025b",
+ "jezu krisiti mink\u025b"
+ ],
+ "ERAS": [
+ "J.-C. \u0272\u025b",
+ "ni J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "zanwuye",
+ "feburuye",
+ "marisi",
+ "awirili",
+ "m\u025b",
+ "zuw\u025bn",
+ "zuluye",
+ "uti",
+ "s\u025btanburu",
+ "\u0254kut\u0254buru",
+ "nowanburu",
+ "desanburu"
+ ],
+ "SHORTDAY": [
+ "kar",
+ "nt\u025b",
+ "tar",
+ "ara",
+ "ala",
+ "jum",
+ "sib"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "feb",
+ "mar",
+ "awi",
+ "m\u025b",
+ "zuw",
+ "zul",
+ "uti",
+ "s\u025bt",
+ "\u0254ku",
+ "now",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-bd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-bd.js
new file mode 100644
index 00000000..24fb37ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-bd.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u09b0\u09ac\u09bf\u09ac\u09be\u09b0",
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09b0",
+ "\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09b0",
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09b0",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0",
+ "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0",
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0"
+ ],
+ "ERANAMES": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "ERAS": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "FIRSTDAYOFWEEK": 4,
+ "MONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "SHORTDAY": [
+ "\u09b0\u09ac\u09bf",
+ "\u09b8\u09cb\u09ae",
+ "\u09ae\u0999\u09cd\u0997\u09b2",
+ "\u09ac\u09c1\u09a7",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf",
+ "\u09b6\u09c1\u0995\u09cd\u09b0",
+ "\u09b6\u09a8\u09bf"
+ ],
+ "SHORTMONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u09f3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "bn-bd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-in.js
new file mode 100644
index 00000000..63a3c3e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u09b0\u09ac\u09bf\u09ac\u09be\u09b0",
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09b0",
+ "\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09b0",
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09b0",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0",
+ "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0",
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0"
+ ],
+ "ERANAMES": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "ERAS": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "SHORTDAY": [
+ "\u09b0\u09ac\u09bf",
+ "\u09b8\u09cb\u09ae",
+ "\u09ae\u0999\u09cd\u0997\u09b2",
+ "\u09ac\u09c1\u09a7",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf",
+ "\u09b6\u09c1\u0995\u09cd\u09b0",
+ "\u09b6\u09a8\u09bf"
+ ],
+ "SHORTMONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "bn-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn.js
new file mode 100644
index 00000000..022ce931
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u09b0\u09ac\u09bf\u09ac\u09be\u09b0",
+ "\u09b8\u09cb\u09ae\u09ac\u09be\u09b0",
+ "\u09ae\u0999\u09cd\u0997\u09b2\u09ac\u09be\u09b0",
+ "\u09ac\u09c1\u09a7\u09ac\u09be\u09b0",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0",
+ "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0",
+ "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0"
+ ],
+ "ERANAMES": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "ERAS": [
+ "\u0996\u09cd\u09b0\u09bf\u09b8\u09cd\u099f\u09aa\u09c2\u09b0\u09cd\u09ac",
+ "\u0996\u09c3\u09b7\u09cd\u099f\u09be\u09ac\u09cd\u09a6"
+ ],
+ "FIRSTDAYOFWEEK": 4,
+ "MONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "SHORTDAY": [
+ "\u09b0\u09ac\u09bf",
+ "\u09b8\u09cb\u09ae",
+ "\u09ae\u0999\u09cd\u0997\u09b2",
+ "\u09ac\u09c1\u09a7",
+ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf",
+ "\u09b6\u09c1\u0995\u09cd\u09b0",
+ "\u09b6\u09a8\u09bf"
+ ],
+ "SHORTMONTH": [
+ "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09c0",
+ "\u09ae\u09be\u09b0\u09cd\u099a",
+ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2",
+ "\u09ae\u09c7",
+ "\u099c\u09c1\u09a8",
+ "\u099c\u09c1\u09b2\u09be\u0987",
+ "\u0986\u0997\u09b8\u09cd\u099f",
+ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
+ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
+ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u09f3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "bn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-cn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-cn.js
new file mode 100644
index 00000000..ea070697
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-cn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0f66\u0f94\u0f0b\u0f51\u0fb2\u0f7c\u0f0b",
+ "\u0f55\u0fb1\u0f72\u0f0b\u0f51\u0fb2\u0f7c\u0f0b"
+ ],
+ "DAY": [
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "ERANAMES": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "ERAS": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTDAY": [
+ "\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTMONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f22",
+ "\u0f5f\u0fb3\u0f0b\u0f23",
+ "\u0f5f\u0fb3\u0f0b\u0f24",
+ "\u0f5f\u0fb3\u0f0b\u0f25",
+ "\u0f5f\u0fb3\u0f0b\u0f26",
+ "\u0f5f\u0fb3\u0f0b\u0f27",
+ "\u0f5f\u0fb3\u0f0b\u0f28",
+ "\u0f5f\u0fb3\u0f0b\u0f29",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f20",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f22"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM\u0f60\u0f72\u0f0b\u0f59\u0f7a\u0f66\u0f0bd\u0f51",
+ "medium": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd HH:mm:ss",
+ "mediumDate": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bo-cn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-in.js
new file mode 100644
index 00000000..89738d38
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0f66\u0f94\u0f0b\u0f51\u0fb2\u0f7c\u0f0b",
+ "\u0f55\u0fb1\u0f72\u0f0b\u0f51\u0fb2\u0f7c\u0f0b"
+ ],
+ "DAY": [
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "ERANAMES": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "ERAS": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTDAY": [
+ "\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTMONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f22",
+ "\u0f5f\u0fb3\u0f0b\u0f23",
+ "\u0f5f\u0fb3\u0f0b\u0f24",
+ "\u0f5f\u0fb3\u0f0b\u0f25",
+ "\u0f5f\u0fb3\u0f0b\u0f26",
+ "\u0f5f\u0fb3\u0f0b\u0f27",
+ "\u0f5f\u0fb3\u0f0b\u0f28",
+ "\u0f5f\u0fb3\u0f0b\u0f29",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f20",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f22"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM\u0f60\u0f72\u0f0b\u0f59\u0f7a\u0f66\u0f0bd\u0f51",
+ "medium": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd HH:mm:ss",
+ "mediumDate": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bo-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo.js
new file mode 100644
index 00000000..117e4d6a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0f66\u0f94\u0f0b\u0f51\u0fb2\u0f7c\u0f0b",
+ "\u0f55\u0fb1\u0f72\u0f0b\u0f51\u0fb2\u0f7c\u0f0b"
+ ],
+ "DAY": [
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "ERANAMES": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "ERAS": [
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0b\u0f66\u0f94\u0f7c\u0f53\u0f0d",
+ "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTDAY": [
+ "\u0f49\u0f72\u0f0b\u0f58\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTMONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f22",
+ "\u0f5f\u0fb3\u0f0b\u0f23",
+ "\u0f5f\u0fb3\u0f0b\u0f24",
+ "\u0f5f\u0fb3\u0f0b\u0f25",
+ "\u0f5f\u0fb3\u0f0b\u0f26",
+ "\u0f5f\u0fb3\u0f0b\u0f27",
+ "\u0f5f\u0fb3\u0f0b\u0f28",
+ "\u0f5f\u0fb3\u0f0b\u0f29",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f20",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f21",
+ "\u0f5f\u0fb3\u0f0b\u0f21\u0f22"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM\u0f60\u0f72\u0f0b\u0f59\u0f7a\u0f66\u0f0bd\u0f51",
+ "medium": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd HH:mm:ss",
+ "mediumDate": "y \u0f63\u0f7c\u0f0b\u0f60\u0f72\u0f0bMMM\u0f59\u0f7a\u0f66\u0f0bd",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "bo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br-fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br-fr.js
new file mode 100644
index 00000000..111b19cf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br-fr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "A.M.",
+ "G.M."
+ ],
+ "DAY": [
+ "Sul",
+ "Lun",
+ "Meurzh",
+ "Merc\u02bcher",
+ "Yaou",
+ "Gwener",
+ "Sadorn"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Genver",
+ "C\u02bchwevrer",
+ "Meurzh",
+ "Ebrel",
+ "Mae",
+ "Mezheven",
+ "Gouere",
+ "Eost",
+ "Gwengolo",
+ "Here",
+ "Du",
+ "Kerzu"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Lun",
+ "Meu.",
+ "Mer.",
+ "Yaou",
+ "Gwe.",
+ "Sad."
+ ],
+ "SHORTMONTH": [
+ "Gen",
+ "C\u02bchwe",
+ "Meur",
+ "Ebr",
+ "Mae",
+ "Mezh",
+ "Goue",
+ "Eost",
+ "Gwen",
+ "Here",
+ "Du",
+ "Ker"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "br-fr",
+ "pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11 && n % 100 != 71 && n % 100 != 91) { return PLURAL_CATEGORY.ONE; } if (n % 10 == 2 && n % 100 != 12 && n % 100 != 72 && n % 100 != 92) { return PLURAL_CATEGORY.TWO; } if ((n % 10 >= 3 && n % 10 <= 4 || n % 10 == 9) && (n % 100 < 10 || n % 100 > 19) && (n % 100 < 70 || n % 100 > 79) && (n % 100 < 90 || n % 100 > 99)) { return PLURAL_CATEGORY.FEW; } if (n != 0 && n % 1000000 == 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br.js
new file mode 100644
index 00000000..2fbf8714
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_br.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "A.M.",
+ "G.M."
+ ],
+ "DAY": [
+ "Sul",
+ "Lun",
+ "Meurzh",
+ "Merc\u02bcher",
+ "Yaou",
+ "Gwener",
+ "Sadorn"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Genver",
+ "C\u02bchwevrer",
+ "Meurzh",
+ "Ebrel",
+ "Mae",
+ "Mezheven",
+ "Gouere",
+ "Eost",
+ "Gwengolo",
+ "Here",
+ "Du",
+ "Kerzu"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Lun",
+ "Meu.",
+ "Mer.",
+ "Yaou",
+ "Gwe.",
+ "Sad."
+ ],
+ "SHORTMONTH": [
+ "Gen",
+ "C\u02bchwe",
+ "Meur",
+ "Ebr",
+ "Mae",
+ "Mezh",
+ "Goue",
+ "Eost",
+ "Gwen",
+ "Here",
+ "Du",
+ "Ker"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "br",
+ "pluralCat": function(n, opt_precision) { if (n % 10 == 1 && n % 100 != 11 && n % 100 != 71 && n % 100 != 91) { return PLURAL_CATEGORY.ONE; } if (n % 10 == 2 && n % 100 != 12 && n % 100 != 72 && n % 100 != 92) { return PLURAL_CATEGORY.TWO; } if ((n % 10 >= 3 && n % 10 <= 4 || n % 10 == 9) && (n % 100 < 10 || n % 100 > 19) && (n % 100 < 70 || n % 100 > 79) && (n % 100 < 90 || n % 100 > 99)) { return PLURAL_CATEGORY.FEW; } if (n != 0 && n % 1000000 == 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx-in.js
new file mode 100644
index 00000000..2d6ad847
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092b\u0941\u0902",
+ "\u092c\u0947\u0932\u093e\u0938\u0947"
+ ],
+ "DAY": [
+ "\u0930\u092c\u093f\u092c\u093e\u0930",
+ "\u0938\u092e\u092c\u093e\u0930",
+ "\u092e\u0902\u0917\u0932\u092c\u093e\u0930",
+ "\u092c\u0941\u0926\u092c\u093e\u0930",
+ "\u092c\u093f\u0938\u0925\u093f\u092c\u093e\u0930",
+ "\u0938\u0941\u0916\u0941\u0930\u092c\u093e\u0930",
+ "\u0938\u0941\u0928\u093f\u092c\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u0938",
+ "\u090f\u092b\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0907",
+ "\u0906\u0917\u0938\u094d\u0925",
+ "\u0938\u0947\u092c\u0925\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0905\u0916\u0925\u092c\u0930",
+ "\u0928\u092c\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0926\u093f\u0938\u0947\u091c\u094d\u092c\u093c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u092c\u093f",
+ "\u0938\u092e",
+ "\u092e\u0902\u0917\u0932",
+ "\u092c\u0941\u0926",
+ "\u092c\u093f\u0938\u0925\u093f",
+ "\u0938\u0941\u0916\u0941\u0930",
+ "\u0938\u0941\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u0938",
+ "\u090f\u092b\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0907",
+ "\u0906\u0917\u0938\u094d\u0925",
+ "\u0938\u0947\u092c\u0925\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0905\u0916\u0925\u092c\u0930",
+ "\u0928\u092c\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0926\u093f\u0938\u0947\u091c\u094d\u092c\u093c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "brx-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx.js
new file mode 100644
index 00000000..85aa1d7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_brx.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092b\u0941\u0902",
+ "\u092c\u0947\u0932\u093e\u0938\u0947"
+ ],
+ "DAY": [
+ "\u0930\u092c\u093f\u092c\u093e\u0930",
+ "\u0938\u092e\u092c\u093e\u0930",
+ "\u092e\u0902\u0917\u0932\u092c\u093e\u0930",
+ "\u092c\u0941\u0926\u092c\u093e\u0930",
+ "\u092c\u093f\u0938\u0925\u093f\u092c\u093e\u0930",
+ "\u0938\u0941\u0916\u0941\u0930\u092c\u093e\u0930",
+ "\u0938\u0941\u0928\u093f\u092c\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e.\u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u0938",
+ "\u090f\u092b\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0907",
+ "\u0906\u0917\u0938\u094d\u0925",
+ "\u0938\u0947\u092c\u0925\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0905\u0916\u0925\u092c\u0930",
+ "\u0928\u092c\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0926\u093f\u0938\u0947\u091c\u094d\u092c\u093c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u092c\u093f",
+ "\u0938\u092e",
+ "\u092e\u0902\u0917\u0932",
+ "\u092c\u0941\u0926",
+ "\u092c\u093f\u0938\u0925\u093f",
+ "\u0938\u0941\u0916\u0941\u0930",
+ "\u0938\u0941\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0941\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u0938",
+ "\u090f\u092b\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0907",
+ "\u0906\u0917\u0938\u094d\u0925",
+ "\u0938\u0947\u092c\u0925\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0905\u0916\u0925\u092c\u0930",
+ "\u0928\u092c\u0947\u091c\u094d\u092c\u093c\u0930",
+ "\u0926\u093f\u0938\u0947\u091c\u094d\u092c\u093c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "brx",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl-ba.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl-ba.js
new file mode 100644
index 00000000..24322a44
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl-ba.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e\u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0438\u0458\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d\u0438",
+ "\u0458\u0443\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0438",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH:mm:ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy. HH:mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bs-cyrl-ba",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl.js
new file mode 100644
index 00000000..63e52e07
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-cyrl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e\u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0438\u0458\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d\u0438",
+ "\u0458\u0443\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0438",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH:mm:ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy. HH:mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bs-cyrl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn-ba.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn-ba.js
new file mode 100644
index 00000000..32c933ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn-ba.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "prije podne",
+ "popodne"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd. MMM. y. HH:mm:ss",
+ "mediumDate": "dd. MMM. y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy. HH:mm",
+ "shortDate": "dd.MM.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bs-latn-ba",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn.js
new file mode 100644
index 00000000..b5e5f925
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "prije podne",
+ "popodne"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd. MMM. y. HH:mm:ss",
+ "mediumDate": "dd. MMM. y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy. HH:mm",
+ "shortDate": "dd.MM.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bs-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs.js
new file mode 100644
index 00000000..c9cf4634
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_bs.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "prije podne",
+ "popodne"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd. MMM. y. HH:mm:ss",
+ "mediumDate": "dd. MMM. y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy. HH:mm",
+ "shortDate": "dd.MM.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "bs",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn-er.js
new file mode 100644
index 00000000..f6ee233b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn-er.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u134b\u12f1\u1235 \u1303\u1265",
+ "\u134b\u12f1\u1235 \u12f0\u121d\u1262"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u122d \u1245\u12f3\u12c5",
+ "\u1230\u1291",
+ "\u1230\u120a\u131d",
+ "\u1208\u1313 \u12c8\u122a \u1208\u1265\u12cb",
+ "\u12a3\u121d\u12f5",
+ "\u12a3\u122d\u1265",
+ "\u1230\u1295\u1260\u122d \u123d\u1313\u12c5"
+ ],
+ "MONTH": [
+ "\u120d\u12f0\u1275\u122a",
+ "\u12ab\u1265\u12bd\u1265\u1272",
+ "\u12ad\u1265\u120b",
+ "\u134b\u1305\u12ba\u122a",
+ "\u12ad\u1262\u1245\u122a",
+ "\u121d\u12aa\u12a4\u120d \u1275\u131f\u1292\u122a",
+ "\u12b0\u122d\u12a9",
+ "\u121b\u122d\u12eb\u121d \u1275\u122a",
+ "\u12eb\u12b8\u1292 \u1218\u1233\u1245\u1208\u122a",
+ "\u1218\u1270\u1209",
+ "\u121d\u12aa\u12a4\u120d \u1218\u123d\u12c8\u122a",
+ "\u1270\u1215\u1233\u1235\u122a"
+ ],
+ "SHORTDAY": [
+ "\u1230/\u1245",
+ "\u1230\u1291",
+ "\u1230\u120a\u131d",
+ "\u1208\u1313",
+ "\u12a3\u121d\u12f5",
+ "\u12a3\u122d\u1265",
+ "\u1230/\u123d"
+ ],
+ "SHORTMONTH": [
+ "\u120d\u12f0\u1275",
+ "\u12ab\u1265\u12bd",
+ "\u12ad\u1265\u120b",
+ "\u134b\u1305\u12ba",
+ "\u12ad\u1262\u1245",
+ "\u121d/\u1275",
+ "\u12b0\u122d",
+ "\u121b\u122d\u12eb",
+ "\u12eb\u12b8\u1292",
+ "\u1218\u1270\u1209",
+ "\u121d/\u121d",
+ "\u1270\u1215\u1233"
+ ],
+ "fullDate": "EEEE\u1361 dd MMMM \u130d\u122d\u130b y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "byn-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn.js
new file mode 100644
index 00000000..578ce6dd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_byn.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u134b\u12f1\u1235 \u1303\u1265",
+ "\u134b\u12f1\u1235 \u12f0\u121d\u1262"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u122d \u1245\u12f3\u12c5",
+ "\u1230\u1291",
+ "\u1230\u120a\u131d",
+ "\u1208\u1313 \u12c8\u122a \u1208\u1265\u12cb",
+ "\u12a3\u121d\u12f5",
+ "\u12a3\u122d\u1265",
+ "\u1230\u1295\u1260\u122d \u123d\u1313\u12c5"
+ ],
+ "MONTH": [
+ "\u120d\u12f0\u1275\u122a",
+ "\u12ab\u1265\u12bd\u1265\u1272",
+ "\u12ad\u1265\u120b",
+ "\u134b\u1305\u12ba\u122a",
+ "\u12ad\u1262\u1245\u122a",
+ "\u121d\u12aa\u12a4\u120d \u1275\u131f\u1292\u122a",
+ "\u12b0\u122d\u12a9",
+ "\u121b\u122d\u12eb\u121d \u1275\u122a",
+ "\u12eb\u12b8\u1292 \u1218\u1233\u1245\u1208\u122a",
+ "\u1218\u1270\u1209",
+ "\u121d\u12aa\u12a4\u120d \u1218\u123d\u12c8\u122a",
+ "\u1270\u1215\u1233\u1235\u122a"
+ ],
+ "SHORTDAY": [
+ "\u1230/\u1245",
+ "\u1230\u1291",
+ "\u1230\u120a\u131d",
+ "\u1208\u1313",
+ "\u12a3\u121d\u12f5",
+ "\u12a3\u122d\u1265",
+ "\u1230/\u123d"
+ ],
+ "SHORTMONTH": [
+ "\u120d\u12f0\u1275",
+ "\u12ab\u1265\u12bd",
+ "\u12ad\u1265\u120b",
+ "\u134b\u1305\u12ba",
+ "\u12ad\u1262\u1245",
+ "\u121d/\u1275",
+ "\u12b0\u122d",
+ "\u121b\u122d\u12eb",
+ "\u12eb\u12b8\u1292",
+ "\u1218\u1270\u1209",
+ "\u121d/\u121d",
+ "\u1270\u1215\u1233"
+ ],
+ "fullDate": "EEEE\u1361 dd MMMM \u130d\u122d\u130b y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "byn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-ad.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-ad.js
new file mode 100644
index 00000000..44830645
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-ad.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca-ad",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es-valencia.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es-valencia.js
new file mode 100644
index 00000000..725478c4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es-valencia.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca-es-valencia",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es.js
new file mode 100644
index 00000000..427201b6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-es.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca-es",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-fr.js
new file mode 100644
index 00000000..22f1f7b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-fr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca-fr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-it.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-it.js
new file mode 100644
index 00000000..8bb952cf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca-it.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca-it",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca.js
new file mode 100644
index 00000000..9f1a6069
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ca.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "diumenge",
+ "dilluns",
+ "dimarts",
+ "dimecres",
+ "dijous",
+ "divendres",
+ "dissabte"
+ ],
+ "ERANAMES": [
+ "abans de Crist",
+ "despr\u00e9s de Crist"
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "de gener",
+ "de febrer",
+ "de mar\u00e7",
+ "d\u2019abril",
+ "de maig",
+ "de juny",
+ "de juliol",
+ "d\u2019agost",
+ "de setembre",
+ "d\u2019octubre",
+ "de novembre",
+ "de desembre"
+ ],
+ "SHORTDAY": [
+ "dg.",
+ "dl.",
+ "dt.",
+ "dc.",
+ "dj.",
+ "dv.",
+ "ds."
+ ],
+ "SHORTMONTH": [
+ "gen.",
+ "febr.",
+ "mar\u00e7",
+ "abr.",
+ "maig",
+ "juny",
+ "jul.",
+ "ag.",
+ "set.",
+ "oct.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM 'de' y",
+ "longDate": "d MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ca",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg-ug.js
new file mode 100644
index 00000000..544346c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sande",
+ "Orwokubanza",
+ "Orwakabiri",
+ "Orwakashatu",
+ "Orwakana",
+ "Orwakataano",
+ "Orwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kurisito Atakaijire",
+ "Kurisito Yaijire"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Okwokubanza",
+ "Okwakabiri",
+ "Okwakashatu",
+ "Okwakana",
+ "Okwakataana",
+ "Okwamukaaga",
+ "Okwamushanju",
+ "Okwamunaana",
+ "Okwamwenda",
+ "Okwaikumi",
+ "Okwaikumi na kumwe",
+ "Okwaikumi na ibiri"
+ ],
+ "SHORTDAY": [
+ "SAN",
+ "ORK",
+ "OKB",
+ "OKS",
+ "OKN",
+ "OKT",
+ "OMK"
+ ],
+ "SHORTMONTH": [
+ "KBZ",
+ "KBR",
+ "KST",
+ "KKN",
+ "KTN",
+ "KMK",
+ "KMS",
+ "KMN",
+ "KMW",
+ "KKM",
+ "KNK",
+ "KNB"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "cgg-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg.js
new file mode 100644
index 00000000..7068c522
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cgg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sande",
+ "Orwokubanza",
+ "Orwakabiri",
+ "Orwakashatu",
+ "Orwakana",
+ "Orwakataano",
+ "Orwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kurisito Atakaijire",
+ "Kurisito Yaijire"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Okwokubanza",
+ "Okwakabiri",
+ "Okwakashatu",
+ "Okwakana",
+ "Okwakataana",
+ "Okwamukaaga",
+ "Okwamushanju",
+ "Okwamunaana",
+ "Okwamwenda",
+ "Okwaikumi",
+ "Okwaikumi na kumwe",
+ "Okwaikumi na ibiri"
+ ],
+ "SHORTDAY": [
+ "SAN",
+ "ORK",
+ "OKB",
+ "OKS",
+ "OKN",
+ "OKT",
+ "OMK"
+ ],
+ "SHORTMONTH": [
+ "KBZ",
+ "KBR",
+ "KST",
+ "KKN",
+ "KTN",
+ "KMK",
+ "KMS",
+ "KMN",
+ "KMW",
+ "KKM",
+ "KNK",
+ "KNB"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "cgg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr-us.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr-us.js
new file mode 100644
index 00000000..bc9e9220
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr-us.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u13cc\u13be\u13b4",
+ "\u13d2\u13af\u13f1\u13a2\u13d7\u13e2"
+ ],
+ "DAY": [
+ "\u13a4\u13be\u13d9\u13d3\u13c6\u13cd\u13ac",
+ "\u13a4\u13be\u13d9\u13d3\u13c9\u13c5\u13af",
+ "\u13d4\u13b5\u13c1\u13a2\u13a6",
+ "\u13e6\u13a2\u13c1\u13a2\u13a6",
+ "\u13c5\u13a9\u13c1\u13a2\u13a6",
+ "\u13e7\u13be\u13a9\u13b6\u13cd\u13d7",
+ "\u13a4\u13be\u13d9\u13d3\u13c8\u13d5\u13be"
+ ],
+ "ERANAMES": [
+ "\u13cf \u13e5\u13cc \u13be\u13d5\u13b2\u13cd\u13ac\u13be",
+ "\u13a0\u13a9\u13c3\u13ae\u13b5\u13d3\u13cd\u13d7\u13f1 \u13a0\u13d5\u13d8\u13f1\u13cd\u13ac \u13f1\u13b0\u13e9 \u13e7\u13d3\u13c2\u13b8\u13a2\u13cd\u13d7"
+ ],
+ "ERAS": [
+ "\u13a4\u13d3\u13b7\u13b8",
+ "\u13a4\u13b6\u13d0\u13c5"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u13a4\u13c3\u13b8\u13d4\u13c5",
+ "\u13a7\u13a6\u13b5",
+ "\u13a0\u13c5\u13f1",
+ "\u13a7\u13ec\u13c2",
+ "\u13a0\u13c2\u13cd\u13ac\u13d8",
+ "\u13d5\u13ad\u13b7\u13f1",
+ "\u13ab\u13f0\u13c9\u13c2",
+ "\u13a6\u13b6\u13c2",
+ "\u13da\u13b5\u13cd\u13d7",
+ "\u13da\u13c2\u13c5\u13d7",
+ "\u13c5\u13d3\u13d5\u13c6",
+ "\u13a5\u13cd\u13a9\u13f1"
+ ],
+ "SHORTDAY": [
+ "\u13c6\u13cd\u13ac",
+ "\u13c9\u13c5\u13af",
+ "\u13d4\u13b5\u13c1",
+ "\u13e6\u13a2\u13c1",
+ "\u13c5\u13a9\u13c1",
+ "\u13e7\u13be\u13a9",
+ "\u13c8\u13d5\u13be"
+ ],
+ "SHORTMONTH": [
+ "\u13a4\u13c3",
+ "\u13a7\u13a6",
+ "\u13a0\u13c5",
+ "\u13a7\u13ec",
+ "\u13a0\u13c2",
+ "\u13d5\u13ad",
+ "\u13ab\u13f0",
+ "\u13a6\u13b6",
+ "\u13da\u13b5",
+ "\u13da\u13c2",
+ "\u13c5\u13d3",
+ "\u13a5\u13cd"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "chr-us",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr.js
new file mode 100644
index 00000000..589816f9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_chr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u13cc\u13be\u13b4",
+ "\u13d2\u13af\u13f1\u13a2\u13d7\u13e2"
+ ],
+ "DAY": [
+ "\u13a4\u13be\u13d9\u13d3\u13c6\u13cd\u13ac",
+ "\u13a4\u13be\u13d9\u13d3\u13c9\u13c5\u13af",
+ "\u13d4\u13b5\u13c1\u13a2\u13a6",
+ "\u13e6\u13a2\u13c1\u13a2\u13a6",
+ "\u13c5\u13a9\u13c1\u13a2\u13a6",
+ "\u13e7\u13be\u13a9\u13b6\u13cd\u13d7",
+ "\u13a4\u13be\u13d9\u13d3\u13c8\u13d5\u13be"
+ ],
+ "ERANAMES": [
+ "\u13cf \u13e5\u13cc \u13be\u13d5\u13b2\u13cd\u13ac\u13be",
+ "\u13a0\u13a9\u13c3\u13ae\u13b5\u13d3\u13cd\u13d7\u13f1 \u13a0\u13d5\u13d8\u13f1\u13cd\u13ac \u13f1\u13b0\u13e9 \u13e7\u13d3\u13c2\u13b8\u13a2\u13cd\u13d7"
+ ],
+ "ERAS": [
+ "\u13a4\u13d3\u13b7\u13b8",
+ "\u13a4\u13b6\u13d0\u13c5"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u13a4\u13c3\u13b8\u13d4\u13c5",
+ "\u13a7\u13a6\u13b5",
+ "\u13a0\u13c5\u13f1",
+ "\u13a7\u13ec\u13c2",
+ "\u13a0\u13c2\u13cd\u13ac\u13d8",
+ "\u13d5\u13ad\u13b7\u13f1",
+ "\u13ab\u13f0\u13c9\u13c2",
+ "\u13a6\u13b6\u13c2",
+ "\u13da\u13b5\u13cd\u13d7",
+ "\u13da\u13c2\u13c5\u13d7",
+ "\u13c5\u13d3\u13d5\u13c6",
+ "\u13a5\u13cd\u13a9\u13f1"
+ ],
+ "SHORTDAY": [
+ "\u13c6\u13cd\u13ac",
+ "\u13c9\u13c5\u13af",
+ "\u13d4\u13b5\u13c1",
+ "\u13e6\u13a2\u13c1",
+ "\u13c5\u13a9\u13c1",
+ "\u13e7\u13be\u13a9",
+ "\u13c8\u13d5\u13be"
+ ],
+ "SHORTMONTH": [
+ "\u13a4\u13c3",
+ "\u13a7\u13a6",
+ "\u13a0\u13c5",
+ "\u13a7\u13ec",
+ "\u13a0\u13c2",
+ "\u13d5\u13ad",
+ "\u13ab\u13f0",
+ "\u13a6\u13b6",
+ "\u13da\u13b5",
+ "\u13da\u13c2",
+ "\u13c5\u13d3",
+ "\u13a5\u13cd"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "chr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-iq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-iq.js
new file mode 100644
index 00000000..083bf182
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-iq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-arab-iq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-ir.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-ir.js
new file mode 100644
index 00000000..cc23f51e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab-ir.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-arab-ir",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab.js
new file mode 100644
index 00000000..8f1fd700
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-arab.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-arab",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-iq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-iq.js
new file mode 100644
index 00000000..2786ebd7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-iq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-iq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-ir.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-ir.js
new file mode 100644
index 00000000..fb0bd006
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-ir.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-ir",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn-iq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn-iq.js
new file mode 100644
index 00000000..4e3c8b79
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn-iq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-latn-iq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn.js
new file mode 100644
index 00000000..e2a333fd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb.js
new file mode 100644
index 00000000..e0321122
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ckb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0628.\u0646",
+ "\u062f.\u0646"
+ ],
+ "DAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "ERANAMES": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u0646",
+ "\u0632\u0627\u06cc\u06cc\u0646\u06cc"
+ ],
+ "ERAS": [
+ "\u067e\u06ce\u0634 \u0632\u0627\u06cc\u06cc\u06cc\u0646",
+ "\u0632"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06d5\u06a9\u0634\u06d5\u0645\u0645\u06d5",
+ "\u062f\u0648\u0648\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0633\u06ce\u0634\u06d5\u0645\u0645\u06d5",
+ "\u0686\u0648\u0627\u0631\u0634\u06d5\u0645\u0645\u06d5",
+ "\u067e\u06ce\u0646\u062c\u0634\u06d5\u0645\u0645\u06d5",
+ "\u06be\u06d5\u06cc\u0646\u06cc",
+ "\u0634\u06d5\u0645\u0645\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u06a9\u0627\u0646\u0648\u0648\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u0634\u0648\u0628\u0627\u062a",
+ "\u0626\u0627\u0632\u0627\u0631",
+ "\u0646\u06cc\u0633\u0627\u0646",
+ "\u0626\u0627\u06cc\u0627\u0631",
+ "\u062d\u0648\u0632\u06d5\u06cc\u0631\u0627\u0646",
+ "\u062a\u06d5\u0645\u0648\u0648\u0632",
+ "\u0626\u0627\u0628",
+ "\u0626\u06d5\u06cc\u0644\u0648\u0648\u0644",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645",
+ "\u062a\u0634\u0631\u06cc\u0646\u06cc \u062f\u0648\u0648\u06d5\u0645",
+ "\u06a9\u0627\u0646\u0648\u0646\u06cc \u06cc\u06d5\u06a9\u06d5\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "d\u06cc MMMM\u06cc y",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ckb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs-cz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs-cz.js
new file mode 100644
index 00000000..d260d8de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs-cz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopoledne",
+ "odpoledne"
+ ],
+ "DAY": [
+ "ned\u011ble",
+ "pond\u011bl\u00ed",
+ "\u00fater\u00fd",
+ "st\u0159eda",
+ "\u010dtvrtek",
+ "p\u00e1tek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u0159. n. l.",
+ "n. l."
+ ],
+ "ERAS": [
+ "p\u0159. n. l.",
+ "n. l."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ledna",
+ "\u00fanora",
+ "b\u0159ezna",
+ "dubna",
+ "kv\u011btna",
+ "\u010dervna",
+ "\u010dervence",
+ "srpna",
+ "z\u00e1\u0159\u00ed",
+ "\u0159\u00edjna",
+ "listopadu",
+ "prosince"
+ ],
+ "SHORTDAY": [
+ "ne",
+ "po",
+ "\u00fat",
+ "st",
+ "\u010dt",
+ "p\u00e1",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "led",
+ "\u00fano",
+ "b\u0159e",
+ "dub",
+ "kv\u011b",
+ "\u010dvn",
+ "\u010dvc",
+ "srp",
+ "z\u00e1\u0159",
+ "\u0159\u00edj",
+ "lis",
+ "pro"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. M. y H:mm:ss",
+ "mediumDate": "d. M. y",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "K\u010d",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "cs-cz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i >= 2 && i <= 4 && vf.v == 0) { return PLURAL_CATEGORY.FEW; } if (vf.v != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs.js
new file mode 100644
index 00000000..3f9cb70e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cs.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopoledne",
+ "odpoledne"
+ ],
+ "DAY": [
+ "ned\u011ble",
+ "pond\u011bl\u00ed",
+ "\u00fater\u00fd",
+ "st\u0159eda",
+ "\u010dtvrtek",
+ "p\u00e1tek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u0159. n. l.",
+ "n. l."
+ ],
+ "ERAS": [
+ "p\u0159. n. l.",
+ "n. l."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ledna",
+ "\u00fanora",
+ "b\u0159ezna",
+ "dubna",
+ "kv\u011btna",
+ "\u010dervna",
+ "\u010dervence",
+ "srpna",
+ "z\u00e1\u0159\u00ed",
+ "\u0159\u00edjna",
+ "listopadu",
+ "prosince"
+ ],
+ "SHORTDAY": [
+ "ne",
+ "po",
+ "\u00fat",
+ "st",
+ "\u010dt",
+ "p\u00e1",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "led",
+ "\u00fano",
+ "b\u0159e",
+ "dub",
+ "kv\u011b",
+ "\u010dvn",
+ "\u010dvc",
+ "srp",
+ "z\u00e1\u0159",
+ "\u0159\u00edj",
+ "lis",
+ "pro"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. M. y H:mm:ss",
+ "mediumDate": "d. M. y",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "K\u010d",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "cs",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i >= 2 && i <= 4 && vf.v == 0) { return PLURAL_CATEGORY.FEW; } if (vf.v != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy-gb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy-gb.js
new file mode 100644
index 00000000..d6a9b5d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy-gb.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dydd Sul",
+ "Dydd Llun",
+ "Dydd Mawrth",
+ "Dydd Mercher",
+ "Dydd Iau",
+ "Dydd Gwener",
+ "Dydd Sadwrn"
+ ],
+ "ERANAMES": [
+ "Cyn Crist",
+ "Oed Crist"
+ ],
+ "ERAS": [
+ "CC",
+ "OC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ionawr",
+ "Chwefror",
+ "Mawrth",
+ "Ebrill",
+ "Mai",
+ "Mehefin",
+ "Gorffennaf",
+ "Awst",
+ "Medi",
+ "Hydref",
+ "Tachwedd",
+ "Rhagfyr"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Llun",
+ "Maw",
+ "Mer",
+ "Iau",
+ "Gwen",
+ "Sad"
+ ],
+ "SHORTMONTH": [
+ "Ion",
+ "Chwef",
+ "Mawrth",
+ "Ebrill",
+ "Mai",
+ "Meh",
+ "Gorff",
+ "Awst",
+ "Medi",
+ "Hyd",
+ "Tach",
+ "Rhag"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "cy-gb",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == 3) { return PLURAL_CATEGORY.FEW; } if (n == 6) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy.js
new file mode 100644
index 00000000..057a5278
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_cy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dydd Sul",
+ "Dydd Llun",
+ "Dydd Mawrth",
+ "Dydd Mercher",
+ "Dydd Iau",
+ "Dydd Gwener",
+ "Dydd Sadwrn"
+ ],
+ "ERANAMES": [
+ "Cyn Crist",
+ "Oed Crist"
+ ],
+ "ERAS": [
+ "CC",
+ "OC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ionawr",
+ "Chwefror",
+ "Mawrth",
+ "Ebrill",
+ "Mai",
+ "Mehefin",
+ "Gorffennaf",
+ "Awst",
+ "Medi",
+ "Hydref",
+ "Tachwedd",
+ "Rhagfyr"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Llun",
+ "Maw",
+ "Mer",
+ "Iau",
+ "Gwen",
+ "Sad"
+ ],
+ "SHORTMONTH": [
+ "Ion",
+ "Chwef",
+ "Mawrth",
+ "Ebrill",
+ "Mai",
+ "Meh",
+ "Gorff",
+ "Awst",
+ "Medi",
+ "Hyd",
+ "Tach",
+ "Rhag"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "cy",
+ "pluralCat": function(n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == 3) { return PLURAL_CATEGORY.FEW; } if (n == 6) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-dk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-dk.js
new file mode 100644
index 00000000..fe2f432a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-dk.js
@@ -0,0 +1,141 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+function getWT(v, f) {
+ if (f === 0) {
+ return {w: 0, t: 0};
+ }
+
+ while ((f % 10) === 0) {
+ f /= 10;
+ v--;
+ }
+
+ return {w: v, t: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "marts",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "maj",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE 'den' d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/y HH.mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "da-dk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); var wt = getWT(vf.v, vf.f); if (n == 1 || wt.t != 0 && (i == 0 || i == 1)) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-gl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-gl.js
new file mode 100644
index 00000000..9714d083
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da-gl.js
@@ -0,0 +1,141 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+function getWT(v, f) {
+ if (f === 0) {
+ return {w: 0, t: 0};
+ }
+
+ while ((f % 10) === 0) {
+ f /= 10;
+ v--;
+ }
+
+ return {w: v, t: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "marts",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "maj",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE 'den' d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/y HH.mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "da-gl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); var wt = getWT(vf.v, vf.f); if (n == 1 || wt.t != 0 && (i == 0 || i == 1)) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da.js
new file mode 100644
index 00000000..7e263cf9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_da.js
@@ -0,0 +1,141 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+function getWT(v, f) {
+ if (f === 0) {
+ return {w: 0, t: 0};
+ }
+
+ while ((f % 10) === 0) {
+ f /= 10;
+ v--;
+ }
+
+ return {w: v, t: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "marts",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "maj",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE 'den' d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/y HH.mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "da",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); var wt = getWT(vf.v, vf.f); if (n == 1 || wt.t != 0 && (i == 0 || i == 1)) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav-ke.js
new file mode 100644
index 00000000..4a689b50
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Luma lwa K",
+ "luma lwa p"
+ ],
+ "DAY": [
+ "Ituku ja jumwa",
+ "Kuramuka jimweri",
+ "Kuramuka kawi",
+ "Kuramuka kadadu",
+ "Kuramuka kana",
+ "Kuramuka kasanu",
+ "Kifula nguwo"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mori ghwa imbiri",
+ "Mori ghwa kawi",
+ "Mori ghwa kadadu",
+ "Mori ghwa kana",
+ "Mori ghwa kasanu",
+ "Mori ghwa karandadu",
+ "Mori ghwa mfungade",
+ "Mori ghwa wunyanya",
+ "Mori ghwa ikenda",
+ "Mori ghwa ikumi",
+ "Mori ghwa ikumi na imweri",
+ "Mori ghwa ikumi na iwi"
+ ],
+ "SHORTDAY": [
+ "Jum",
+ "Jim",
+ "Kaw",
+ "Kad",
+ "Kan",
+ "Kas",
+ "Ngu"
+ ],
+ "SHORTMONTH": [
+ "Imb",
+ "Kaw",
+ "Kad",
+ "Kan",
+ "Kas",
+ "Kar",
+ "Mfu",
+ "Wun",
+ "Ike",
+ "Iku",
+ "Imw",
+ "Iwi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "dav-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav.js
new file mode 100644
index 00000000..946c59f4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dav.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Luma lwa K",
+ "luma lwa p"
+ ],
+ "DAY": [
+ "Ituku ja jumwa",
+ "Kuramuka jimweri",
+ "Kuramuka kawi",
+ "Kuramuka kadadu",
+ "Kuramuka kana",
+ "Kuramuka kasanu",
+ "Kifula nguwo"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mori ghwa imbiri",
+ "Mori ghwa kawi",
+ "Mori ghwa kadadu",
+ "Mori ghwa kana",
+ "Mori ghwa kasanu",
+ "Mori ghwa karandadu",
+ "Mori ghwa mfungade",
+ "Mori ghwa wunyanya",
+ "Mori ghwa ikenda",
+ "Mori ghwa ikumi",
+ "Mori ghwa ikumi na imweri",
+ "Mori ghwa ikumi na iwi"
+ ],
+ "SHORTDAY": [
+ "Jum",
+ "Jim",
+ "Kaw",
+ "Kad",
+ "Kan",
+ "Kas",
+ "Ngu"
+ ],
+ "SHORTMONTH": [
+ "Imb",
+ "Kaw",
+ "Kad",
+ "Kan",
+ "Kas",
+ "Kar",
+ "Mfu",
+ "Wun",
+ "Ike",
+ "Iku",
+ "Imw",
+ "Iwi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "dav",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-at.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-at.js
new file mode 100644
index 00000000..b3ee8e15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-at.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "J\u00e4nner",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "J\u00e4n.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "de-at",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-be.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-be.js
new file mode 100644
index 00000000..61390da4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-be.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "de-be",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-ch.js
new file mode 100644
index 00000000..cdb75cac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-ch.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "'",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "de-ch",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-de.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-de.js
new file mode 100644
index 00000000..b69252f5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-de.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "de-de",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-li.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-li.js
new file mode 100644
index 00000000..867e08d9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-li.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "'",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "de-li",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-lu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-lu.js
new file mode 100644
index 00000000..f141217c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de-lu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "de-lu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de.js
new file mode 100644
index 00000000..cbc6643f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_de.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nachm."
+ ],
+ "DAY": [
+ "Sonntag",
+ "Montag",
+ "Dienstag",
+ "Mittwoch",
+ "Donnerstag",
+ "Freitag",
+ "Samstag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "So.",
+ "Mo.",
+ "Di.",
+ "Mi.",
+ "Do.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4rz",
+ "Apr.",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "de",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje-ne.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje-ne.js
new file mode 100644
index 00000000..a5f24033
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje-ne.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Subbaahi",
+ "Zaarikay b"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamisi",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "dje-ne",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje.js
new file mode 100644
index 00000000..630c9f4a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dje.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Subbaahi",
+ "Zaarikay b"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamisi",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "dje",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb-de.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb-de.js
new file mode 100644
index 00000000..8d7ca9f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb-de.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopo\u0142dnja",
+ "w\u00f3tpo\u0142dnja"
+ ],
+ "DAY": [
+ "nje\u017aela",
+ "p\u00f3nje\u017aele",
+ "wa\u0142tora",
+ "srjoda",
+ "stw\u00f3rtk",
+ "p\u011btk",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u015bed Kristusowym naro\u017aenim",
+ "p\u00f3 Kristusowem naro\u017aenju"
+ ],
+ "ERAS": [
+ "p\u015b.Chr.n.",
+ "p\u00f3 Chr.n."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januara",
+ "februara",
+ "m\u011brca",
+ "apryla",
+ "maja",
+ "junija",
+ "julija",
+ "awgusta",
+ "septembra",
+ "oktobra",
+ "nowembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "nje",
+ "p\u00f3n",
+ "wa\u0142",
+ "srj",
+ "stw",
+ "p\u011bt",
+ "sob"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "m\u011br.",
+ "apr.",
+ "maj.",
+ "jun.",
+ "jul.",
+ "awg.",
+ "sep.",
+ "okt.",
+ "now.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H:mm:ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.yy H:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dsb-de",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb.js
new file mode 100644
index 00000000..f774a75b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dsb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopo\u0142dnja",
+ "w\u00f3tpo\u0142dnja"
+ ],
+ "DAY": [
+ "nje\u017aela",
+ "p\u00f3nje\u017aele",
+ "wa\u0142tora",
+ "srjoda",
+ "stw\u00f3rtk",
+ "p\u011btk",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u015bed Kristusowym naro\u017aenim",
+ "p\u00f3 Kristusowem naro\u017aenju"
+ ],
+ "ERAS": [
+ "p\u015b.Chr.n.",
+ "p\u00f3 Chr.n."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januara",
+ "februara",
+ "m\u011brca",
+ "apryla",
+ "maja",
+ "junija",
+ "julija",
+ "awgusta",
+ "septembra",
+ "oktobra",
+ "nowembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "nje",
+ "p\u00f3n",
+ "wa\u0142",
+ "srj",
+ "stw",
+ "p\u011bt",
+ "sob"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "m\u011br.",
+ "apr.",
+ "maj.",
+ "jun.",
+ "jul.",
+ "awg.",
+ "sep.",
+ "okt.",
+ "now.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H:mm:ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.yy H:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dsb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua-cm.js
new file mode 100644
index 00000000..84d78017
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "idi\u0253a",
+ "eby\u00e1mu"
+ ],
+ "DAY": [
+ "\u00e9ti",
+ "m\u0254\u0301s\u00fa",
+ "kwas\u00fa",
+ "muk\u0254\u0301s\u00fa",
+ "\u014bgis\u00fa",
+ "\u0257\u00f3n\u025bs\u00fa",
+ "esa\u0253as\u00fa"
+ ],
+ "ERANAMES": [
+ "\u0253oso \u0253w\u00e1 y\u00e1\u0253e l\u00e1",
+ "mb\u00fasa kw\u00e9di a Y\u00e9s"
+ ],
+ "ERAS": [
+ "\u0253.Ys",
+ "mb.Ys"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dim\u0254\u0301di",
+ "\u014bg\u0254nd\u025b",
+ "s\u0254\u014b\u025b",
+ "di\u0253\u00e1\u0253\u00e1",
+ "emiasele",
+ "es\u0254p\u025bs\u0254p\u025b",
+ "madi\u0253\u025b\u0301d\u00ed\u0253\u025b\u0301",
+ "di\u014bgindi",
+ "ny\u025bt\u025bki",
+ "may\u00e9s\u025b\u0301",
+ "tin\u00edn\u00ed",
+ "el\u00e1\u014bg\u025b\u0301"
+ ],
+ "SHORTDAY": [
+ "\u00e9t",
+ "m\u0254\u0301s",
+ "kwa",
+ "muk",
+ "\u014bgi",
+ "\u0257\u00f3n",
+ "esa"
+ ],
+ "SHORTMONTH": [
+ "di",
+ "\u014bg\u0254n",
+ "s\u0254\u014b",
+ "di\u0253",
+ "emi",
+ "es\u0254",
+ "mad",
+ "di\u014b",
+ "ny\u025bt",
+ "may",
+ "tin",
+ "el\u00e1"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dua-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua.js
new file mode 100644
index 00000000..c2ffe945
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dua.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "idi\u0253a",
+ "eby\u00e1mu"
+ ],
+ "DAY": [
+ "\u00e9ti",
+ "m\u0254\u0301s\u00fa",
+ "kwas\u00fa",
+ "muk\u0254\u0301s\u00fa",
+ "\u014bgis\u00fa",
+ "\u0257\u00f3n\u025bs\u00fa",
+ "esa\u0253as\u00fa"
+ ],
+ "ERANAMES": [
+ "\u0253oso \u0253w\u00e1 y\u00e1\u0253e l\u00e1",
+ "mb\u00fasa kw\u00e9di a Y\u00e9s"
+ ],
+ "ERAS": [
+ "\u0253.Ys",
+ "mb.Ys"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dim\u0254\u0301di",
+ "\u014bg\u0254nd\u025b",
+ "s\u0254\u014b\u025b",
+ "di\u0253\u00e1\u0253\u00e1",
+ "emiasele",
+ "es\u0254p\u025bs\u0254p\u025b",
+ "madi\u0253\u025b\u0301d\u00ed\u0253\u025b\u0301",
+ "di\u014bgindi",
+ "ny\u025bt\u025bki",
+ "may\u00e9s\u025b\u0301",
+ "tin\u00edn\u00ed",
+ "el\u00e1\u014bg\u025b\u0301"
+ ],
+ "SHORTDAY": [
+ "\u00e9t",
+ "m\u0254\u0301s",
+ "kwa",
+ "muk",
+ "\u014bgi",
+ "\u0257\u00f3n",
+ "esa"
+ ],
+ "SHORTMONTH": [
+ "di",
+ "\u014bg\u0254n",
+ "s\u0254\u014b",
+ "di\u0253",
+ "emi",
+ "es\u0254",
+ "mad",
+ "di\u014b",
+ "ny\u025bt",
+ "may",
+ "tin",
+ "el\u00e1"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dua",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo-sn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo-sn.js
new file mode 100644
index 00000000..e8fadc71
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo-sn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dimas",
+ "Tene\u014b",
+ "Talata",
+ "Alarbay",
+ "Aramisay",
+ "Arjuma",
+ "Sibiti"
+ ],
+ "ERANAMES": [
+ "Ari\u014buu Yeesu",
+ "Atoo\u014be Yeesu"
+ ],
+ "ERAS": [
+ "ArY",
+ "AtY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Sanvie",
+ "F\u00e9birie",
+ "Mars",
+ "Aburil",
+ "Mee",
+ "Sue\u014b",
+ "S\u00fauyee",
+ "Ut",
+ "Settembar",
+ "Oktobar",
+ "Novembar",
+ "Disambar"
+ ],
+ "SHORTDAY": [
+ "Dim",
+ "Ten",
+ "Tal",
+ "Ala",
+ "Ara",
+ "Arj",
+ "Sib"
+ ],
+ "SHORTMONTH": [
+ "Sa",
+ "Fe",
+ "Ma",
+ "Ab",
+ "Me",
+ "Su",
+ "S\u00fa",
+ "Ut",
+ "Se",
+ "Ok",
+ "No",
+ "De"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dyo-sn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo.js
new file mode 100644
index 00000000..5699f4a2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dyo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dimas",
+ "Tene\u014b",
+ "Talata",
+ "Alarbay",
+ "Aramisay",
+ "Arjuma",
+ "Sibiti"
+ ],
+ "ERANAMES": [
+ "Ari\u014buu Yeesu",
+ "Atoo\u014be Yeesu"
+ ],
+ "ERAS": [
+ "ArY",
+ "AtY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Sanvie",
+ "F\u00e9birie",
+ "Mars",
+ "Aburil",
+ "Mee",
+ "Sue\u014b",
+ "S\u00fauyee",
+ "Ut",
+ "Settembar",
+ "Oktobar",
+ "Novembar",
+ "Disambar"
+ ],
+ "SHORTDAY": [
+ "Dim",
+ "Ten",
+ "Tal",
+ "Ala",
+ "Ara",
+ "Arj",
+ "Sib"
+ ],
+ "SHORTMONTH": [
+ "Sa",
+ "Fe",
+ "Ma",
+ "Ab",
+ "Me",
+ "Su",
+ "S\u00fa",
+ "Ut",
+ "Se",
+ "Ok",
+ "No",
+ "De"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "dyo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz-bt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz-bt.js
new file mode 100644
index 00000000..c82e0508
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz-bt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0f66\u0f94\u0f0b\u0f46\u0f0b",
+ "\u0f55\u0fb1\u0f72\u0f0b\u0f46\u0f0b"
+ ],
+ "DAY": [
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0f44\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTDAY": [
+ "\u0f5f\u0fb3\u0f0b",
+ "\u0f58\u0f72\u0f62\u0f0b",
+ "\u0f63\u0fb7\u0f42\u0f0b",
+ "\u0f55\u0f74\u0f62\u0f0b",
+ "\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f66\u0fa4\u0f7a\u0f53\u0f0b",
+ "\u0f49\u0f72\u0f0b"
+ ],
+ "SHORTMONTH": [
+ "\u0f21",
+ "\u0f22",
+ "\u0f23",
+ "\u0f24",
+ "\u0f25",
+ "\u0f26",
+ "\u0f27",
+ "\u0f28",
+ "\u0f29",
+ "\u0f21\u0f20",
+ "\u0f21\u0f21",
+ "12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, \u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM \u0f5a\u0f7a\u0f66\u0f0bdd",
+ "longDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM \u0f5a\u0f7a\u0f66\u0f0b dd",
+ "medium": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by \u0f5f\u0fb3\u0f0bMMM \u0f5a\u0f7a\u0f66\u0f0bdd \u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0bh:mm:ss a",
+ "mediumDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by \u0f5f\u0fb3\u0f0bMMM \u0f5a\u0f7a\u0f66\u0f0bdd",
+ "mediumTime": "\u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0bh:mm:ss a",
+ "short": "y-MM-dd \u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0b h \u0f66\u0f90\u0f62\u0f0b\u0f58\u0f0b mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "\u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0b h \u0f66\u0f90\u0f62\u0f0b\u0f58\u0f0b mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nu.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "dz-bt",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz.js
new file mode 100644
index 00000000..3ef63d10
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_dz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0f66\u0f94\u0f0b\u0f46\u0f0b",
+ "\u0f55\u0fb1\u0f72\u0f0b\u0f46\u0f0b"
+ ],
+ "DAY": [
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f58\u0f72\u0f42\u0f0b\u0f51\u0f58\u0f62\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f63\u0fb7\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f55\u0f74\u0f62\u0f0b\u0f56\u0f74\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f54\u0f0b\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f66\u0fa4\u0f7a\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f42\u0f5f\u0f60\u0f0b\u0f49\u0f72\u0f0b\u0f58\u0f0b"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0f44\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
+ "\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b"
+ ],
+ "SHORTDAY": [
+ "\u0f5f\u0fb3\u0f0b",
+ "\u0f58\u0f72\u0f62\u0f0b",
+ "\u0f63\u0fb7\u0f42\u0f0b",
+ "\u0f55\u0f74\u0f62\u0f0b",
+ "\u0f66\u0f44\u0f66\u0f0b",
+ "\u0f66\u0fa4\u0f7a\u0f53\u0f0b",
+ "\u0f49\u0f72\u0f0b"
+ ],
+ "SHORTMONTH": [
+ "\u0f21",
+ "\u0f22",
+ "\u0f23",
+ "\u0f24",
+ "\u0f25",
+ "\u0f26",
+ "\u0f27",
+ "\u0f28",
+ "\u0f29",
+ "\u0f21\u0f20",
+ "\u0f21\u0f21",
+ "12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, \u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM \u0f5a\u0f7a\u0f66\u0f0bdd",
+ "longDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by MMMM \u0f5a\u0f7a\u0f66\u0f0b dd",
+ "medium": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by \u0f5f\u0fb3\u0f0bMMM \u0f5a\u0f7a\u0f66\u0f0bdd \u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0bh:mm:ss a",
+ "mediumDate": "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f63\u0f7c\u0f0by \u0f5f\u0fb3\u0f0bMMM \u0f5a\u0f7a\u0f66\u0f0bdd",
+ "mediumTime": "\u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0bh:mm:ss a",
+ "short": "y-MM-dd \u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0b h \u0f66\u0f90\u0f62\u0f0b\u0f58\u0f0b mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "\u0f46\u0f74\u0f0b\u0f5a\u0f7c\u0f51\u0f0b h \u0f66\u0f90\u0f62\u0f0b\u0f58\u0f0b mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nu.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "dz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu-ke.js
new file mode 100644
index 00000000..6f6761f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "KI",
+ "UT"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Njumatatu",
+ "Njumaine",
+ "Njumatano",
+ "Aramithi",
+ "Njumaa",
+ "NJumamothii"
+ ],
+ "ERANAMES": [
+ "Mbere ya Kristo",
+ "Thutha wa Kristo"
+ ],
+ "ERAS": [
+ "MK",
+ "TK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wa mbere",
+ "Mweri wa ka\u0129ri",
+ "Mweri wa kathat\u0169",
+ "Mweri wa kana",
+ "Mweri wa gatano",
+ "Mweri wa gatantat\u0169",
+ "Mweri wa m\u0169gwanja",
+ "Mweri wa kanana",
+ "Mweri wa kenda",
+ "Mweri wa ik\u0169mi",
+ "Mweri wa ik\u0169mi na \u0169mwe",
+ "Mweri wa ik\u0169mi na Ka\u0129r\u0129"
+ ],
+ "SHORTDAY": [
+ "Kma",
+ "Tat",
+ "Ine",
+ "Tan",
+ "Arm",
+ "Maa",
+ "NMM"
+ ],
+ "SHORTMONTH": [
+ "Mbe",
+ "Kai",
+ "Kat",
+ "Kan",
+ "Gat",
+ "Gan",
+ "Mug",
+ "Knn",
+ "Ken",
+ "Iku",
+ "Imw",
+ "Igi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ebu-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu.js
new file mode 100644
index 00000000..d92a16d2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ebu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "KI",
+ "UT"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Njumatatu",
+ "Njumaine",
+ "Njumatano",
+ "Aramithi",
+ "Njumaa",
+ "NJumamothii"
+ ],
+ "ERANAMES": [
+ "Mbere ya Kristo",
+ "Thutha wa Kristo"
+ ],
+ "ERAS": [
+ "MK",
+ "TK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wa mbere",
+ "Mweri wa ka\u0129ri",
+ "Mweri wa kathat\u0169",
+ "Mweri wa kana",
+ "Mweri wa gatano",
+ "Mweri wa gatantat\u0169",
+ "Mweri wa m\u0169gwanja",
+ "Mweri wa kanana",
+ "Mweri wa kenda",
+ "Mweri wa ik\u0169mi",
+ "Mweri wa ik\u0169mi na \u0169mwe",
+ "Mweri wa ik\u0169mi na Ka\u0129r\u0129"
+ ],
+ "SHORTDAY": [
+ "Kma",
+ "Tat",
+ "Ine",
+ "Tan",
+ "Arm",
+ "Maa",
+ "NMM"
+ ],
+ "SHORTMONTH": [
+ "Mbe",
+ "Kai",
+ "Kat",
+ "Kan",
+ "Gat",
+ "Gan",
+ "Mug",
+ "Knn",
+ "Ken",
+ "Iku",
+ "Imw",
+ "Igi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ebu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-gh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-gh.js
new file mode 100644
index 00000000..16848bab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-gh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u014bdi",
+ "\u0263etr\u0254"
+ ],
+ "DAY": [
+ "k\u0254si\u0256a",
+ "dzo\u0256a",
+ "bla\u0256a",
+ "ku\u0256a",
+ "yawo\u0256a",
+ "fi\u0256a",
+ "memle\u0256a"
+ ],
+ "ERANAMES": [
+ "Hafi Yesu Va Do \u014bg\u0254",
+ "Yesu \u014a\u0254li"
+ ],
+ "ERAS": [
+ "hY",
+ "Y\u014b"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dzove",
+ "dzodze",
+ "tedoxe",
+ "af\u0254f\u0129e",
+ "dama",
+ "masa",
+ "siaml\u0254m",
+ "deasiamime",
+ "any\u0254ny\u0254",
+ "kele",
+ "ade\u025bmekp\u0254xe",
+ "dzome"
+ ],
+ "SHORTDAY": [
+ "k\u0254s",
+ "dzo",
+ "bla",
+ "ku\u0256",
+ "yaw",
+ "fi\u0256",
+ "mem"
+ ],
+ "SHORTMONTH": [
+ "dzv",
+ "dzd",
+ "ted",
+ "af\u0254",
+ "dam",
+ "mas",
+ "sia",
+ "dea",
+ "any",
+ "kel",
+ "ade",
+ "dzm"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d 'lia' y",
+ "longDate": "MMMM d 'lia' y",
+ "medium": "MMM d 'lia', y a 'ga' h:mm:ss",
+ "mediumDate": "MMM d 'lia', y",
+ "mediumTime": "a 'ga' h:mm:ss",
+ "short": "M/d/yy a 'ga' h:mm",
+ "shortDate": "M/d/yy",
+ "shortTime": "a 'ga' h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ee-gh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-tg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-tg.js
new file mode 100644
index 00000000..de48746a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee-tg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u014bdi",
+ "\u0263etr\u0254"
+ ],
+ "DAY": [
+ "k\u0254si\u0256a",
+ "dzo\u0256a",
+ "bla\u0256a",
+ "ku\u0256a",
+ "yawo\u0256a",
+ "fi\u0256a",
+ "memle\u0256a"
+ ],
+ "ERANAMES": [
+ "Hafi Yesu Va Do \u014bg\u0254",
+ "Yesu \u014a\u0254li"
+ ],
+ "ERAS": [
+ "hY",
+ "Y\u014b"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dzove",
+ "dzodze",
+ "tedoxe",
+ "af\u0254f\u0129e",
+ "dama",
+ "masa",
+ "siaml\u0254m",
+ "deasiamime",
+ "any\u0254ny\u0254",
+ "kele",
+ "ade\u025bmekp\u0254xe",
+ "dzome"
+ ],
+ "SHORTDAY": [
+ "k\u0254s",
+ "dzo",
+ "bla",
+ "ku\u0256",
+ "yaw",
+ "fi\u0256",
+ "mem"
+ ],
+ "SHORTMONTH": [
+ "dzv",
+ "dzd",
+ "ted",
+ "af\u0254",
+ "dam",
+ "mas",
+ "sia",
+ "dea",
+ "any",
+ "kel",
+ "ade",
+ "dzm"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d 'lia' y",
+ "longDate": "MMMM d 'lia' y",
+ "medium": "MMM d 'lia', y a 'ga' h:mm:ss",
+ "mediumDate": "MMM d 'lia', y",
+ "mediumTime": "a 'ga' h:mm:ss",
+ "short": "M/d/yy a 'ga' h:mm",
+ "shortDate": "M/d/yy",
+ "shortTime": "a 'ga' h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ee-tg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee.js
new file mode 100644
index 00000000..fdc03beb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ee.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u014bdi",
+ "\u0263etr\u0254"
+ ],
+ "DAY": [
+ "k\u0254si\u0256a",
+ "dzo\u0256a",
+ "bla\u0256a",
+ "ku\u0256a",
+ "yawo\u0256a",
+ "fi\u0256a",
+ "memle\u0256a"
+ ],
+ "ERANAMES": [
+ "Hafi Yesu Va Do \u014bg\u0254",
+ "Yesu \u014a\u0254li"
+ ],
+ "ERAS": [
+ "hY",
+ "Y\u014b"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dzove",
+ "dzodze",
+ "tedoxe",
+ "af\u0254f\u0129e",
+ "dama",
+ "masa",
+ "siaml\u0254m",
+ "deasiamime",
+ "any\u0254ny\u0254",
+ "kele",
+ "ade\u025bmekp\u0254xe",
+ "dzome"
+ ],
+ "SHORTDAY": [
+ "k\u0254s",
+ "dzo",
+ "bla",
+ "ku\u0256",
+ "yaw",
+ "fi\u0256",
+ "mem"
+ ],
+ "SHORTMONTH": [
+ "dzv",
+ "dzd",
+ "ted",
+ "af\u0254",
+ "dam",
+ "mas",
+ "sia",
+ "dea",
+ "any",
+ "kel",
+ "ade",
+ "dzm"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d 'lia' y",
+ "longDate": "MMMM d 'lia' y",
+ "medium": "MMM d 'lia', y a 'ga' h:mm:ss",
+ "mediumDate": "MMM d 'lia', y",
+ "mediumTime": "a 'ga' h:mm:ss",
+ "short": "M/d/yy a 'ga' h:mm",
+ "shortDate": "M/d/yy",
+ "shortTime": "a 'ga' h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ee",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-cy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-cy.js
new file mode 100644
index 00000000..5637d3fb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-cy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u03c0.\u03bc.",
+ "\u03bc.\u03bc."
+ ],
+ "DAY": [
+ "\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae",
+ "\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1",
+ "\u03a4\u03c1\u03af\u03c4\u03b7",
+ "\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7",
+ "\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7",
+ "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae",
+ "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"
+ ],
+ "ERANAMES": [
+ "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd",
+ "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd"
+ ],
+ "ERAS": [
+ "\u03c0.\u03a7.",
+ "\u03bc.\u03a7."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5",
+ "\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u0390\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5",
+ "\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5",
+ "\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5"
+ ],
+ "SHORTDAY": [
+ "\u039a\u03c5\u03c1",
+ "\u0394\u03b5\u03c5",
+ "\u03a4\u03c1\u03af",
+ "\u03a4\u03b5\u03c4",
+ "\u03a0\u03ad\u03bc",
+ "\u03a0\u03b1\u03c1",
+ "\u03a3\u03ac\u03b2"
+ ],
+ "SHORTMONTH": [
+ "\u0399\u03b1\u03bd",
+ "\u03a6\u03b5\u03b2",
+ "\u039c\u03b1\u03c1",
+ "\u0391\u03c0\u03c1",
+ "\u039c\u03b1\u0390",
+ "\u0399\u03bf\u03c5\u03bd",
+ "\u0399\u03bf\u03c5\u03bb",
+ "\u0391\u03c5\u03b3",
+ "\u03a3\u03b5\u03c0",
+ "\u039f\u03ba\u03c4",
+ "\u039d\u03bf\u03b5",
+ "\u0394\u03b5\u03ba"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "el-cy",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-gr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-gr.js
new file mode 100644
index 00000000..72c8b719
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el-gr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u03c0.\u03bc.",
+ "\u03bc.\u03bc."
+ ],
+ "DAY": [
+ "\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae",
+ "\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1",
+ "\u03a4\u03c1\u03af\u03c4\u03b7",
+ "\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7",
+ "\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7",
+ "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae",
+ "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"
+ ],
+ "ERANAMES": [
+ "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd",
+ "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd"
+ ],
+ "ERAS": [
+ "\u03c0.\u03a7.",
+ "\u03bc.\u03a7."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5",
+ "\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u0390\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5",
+ "\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5",
+ "\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5"
+ ],
+ "SHORTDAY": [
+ "\u039a\u03c5\u03c1",
+ "\u0394\u03b5\u03c5",
+ "\u03a4\u03c1\u03af",
+ "\u03a4\u03b5\u03c4",
+ "\u03a0\u03ad\u03bc",
+ "\u03a0\u03b1\u03c1",
+ "\u03a3\u03ac\u03b2"
+ ],
+ "SHORTMONTH": [
+ "\u0399\u03b1\u03bd",
+ "\u03a6\u03b5\u03b2",
+ "\u039c\u03b1\u03c1",
+ "\u0391\u03c0\u03c1",
+ "\u039c\u03b1\u0390",
+ "\u0399\u03bf\u03c5\u03bd",
+ "\u0399\u03bf\u03c5\u03bb",
+ "\u0391\u03c5\u03b3",
+ "\u03a3\u03b5\u03c0",
+ "\u039f\u03ba\u03c4",
+ "\u039d\u03bf\u03b5",
+ "\u0394\u03b5\u03ba"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "el-gr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el.js
new file mode 100644
index 00000000..216542b8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_el.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u03c0.\u03bc.",
+ "\u03bc.\u03bc."
+ ],
+ "DAY": [
+ "\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae",
+ "\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1",
+ "\u03a4\u03c1\u03af\u03c4\u03b7",
+ "\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7",
+ "\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7",
+ "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae",
+ "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"
+ ],
+ "ERANAMES": [
+ "\u03c0\u03c1\u03bf \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03cd",
+ "\u03bc\u03b5\u03c4\u03ac \u03a7\u03c1\u03b9\u03c3\u03c4\u03cc\u03bd"
+ ],
+ "ERAS": [
+ "\u03c0.\u03a7.",
+ "\u03bc.\u03a7."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5",
+ "\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5",
+ "\u039c\u03b1\u0390\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5",
+ "\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5",
+ "\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5",
+ "\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
+ "\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5"
+ ],
+ "SHORTDAY": [
+ "\u039a\u03c5\u03c1",
+ "\u0394\u03b5\u03c5",
+ "\u03a4\u03c1\u03af",
+ "\u03a4\u03b5\u03c4",
+ "\u03a0\u03ad\u03bc",
+ "\u03a0\u03b1\u03c1",
+ "\u03a3\u03ac\u03b2"
+ ],
+ "SHORTMONTH": [
+ "\u0399\u03b1\u03bd",
+ "\u03a6\u03b5\u03b2",
+ "\u039c\u03b1\u03c1",
+ "\u0391\u03c0\u03c1",
+ "\u039c\u03b1\u0390",
+ "\u0399\u03bf\u03c5\u03bd",
+ "\u0399\u03bf\u03c5\u03bb",
+ "\u0391\u03c5\u03b3",
+ "\u03a3\u03b5\u03c0",
+ "\u039f\u03ba\u03c4",
+ "\u039d\u03bf\u03b5",
+ "\u0394\u03b5\u03ba"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "el",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-001.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-001.js
new file mode 100644
index 00000000..49c98073
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-001.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-001",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-150.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-150.js
new file mode 100644
index 00000000..88468dad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-150.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "en-150",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ag.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ag.js
new file mode 100644
index 00000000..effeae65
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ag.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ag",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ai.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ai.js
new file mode 100644
index 00000000..29a39cb3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ai.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ai",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-as.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-as.js
new file mode 100644
index 00000000..b121ecba
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-as.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-as",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-au.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-au.js
new file mode 100644
index 00000000..a1ea9d76
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-au.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/y h:mm a",
+ "shortDate": "d/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-au",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bb.js
new file mode 100644
index 00000000..a183bab2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-bb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-be.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-be.js
new file mode 100644
index 00000000..8a79877f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-be.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "en-be",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bm.js
new file mode 100644
index 00000000..217c162f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-bm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bs.js
new file mode 100644
index 00000000..dfcf301e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bs.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-bs",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bw.js
new file mode 100644
index 00000000..9433a32d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "P",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-bw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bz.js
new file mode 100644
index 00000000..50b70783
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-bz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y HH:mm:ss",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-bz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ca.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ca.js
new file mode 100644
index 00000000..5ca0d1d3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ca.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y-MM-dd h:mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ca",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cc.js
new file mode 100644
index 00000000..e840c699
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-cc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ck.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ck.js
new file mode 100644
index 00000000..5cdb9138
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ck.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ck",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cm.js
new file mode 100644
index 00000000..06821311
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cx.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cx.js
new file mode 100644
index 00000000..e6c4f106
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-cx.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-cx",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dg.js
new file mode 100644
index 00000000..6c2c605f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-dg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dm.js
new file mode 100644
index 00000000..7225a1dd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-dm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-dm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-er.js
new file mode 100644
index 00000000..85232a6a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-er.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fj.js
new file mode 100644
index 00000000..a7dfbe68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fj.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-fj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fk.js
new file mode 100644
index 00000000..5da1bcb8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-fk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fm.js
new file mode 100644
index 00000000..19cfa055
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-fm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-fm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gb.js
new file mode 100644
index 00000000..3eb37db2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gd.js
new file mode 100644
index 00000000..4fbcd1c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gg.js
new file mode 100644
index 00000000..8da65cc0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gh.js
new file mode 100644
index 00000000..bcaa1bcc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gi.js
new file mode 100644
index 00000000..926bacd0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gm.js
new file mode 100644
index 00000000..fec1b604
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GMD",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gu.js
new file mode 100644
index 00000000..68d66d51
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gy.js
new file mode 100644
index 00000000..405cfc39
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-gy.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-gy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-hk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-hk.js
new file mode 100644
index 00000000..6efd6924
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-hk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/y h:mm a",
+ "shortDate": "d/M/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-hk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ie.js
new file mode 100644
index 00000000..d6eb9505
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ie.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ie",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-im.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-im.js
new file mode 100644
index 00000000..b9d1717c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-im.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-im",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-in.js
new file mode 100644
index 00000000..050ef178
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-io.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-io.js
new file mode 100644
index 00000000..3e0cc47f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-io.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-io",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-iso.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-iso.js
new file mode 100644
index 00000000..4e1ba795
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-iso.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yyyy-MM-dd HH:mm",
+ "shortDate": "yyyy-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-iso",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-je.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-je.js
new file mode 100644
index 00000000..6883396c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-je.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-je",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-jm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-jm.js
new file mode 100644
index 00000000..080daec1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-jm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-jm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ke.js
new file mode 100644
index 00000000..e0e16af6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ki.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ki.js
new file mode 100644
index 00000000..de6c4ff5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ki.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ki",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-kn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-kn.js
new file mode 100644
index 00000000..88f8d651
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-kn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-kn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ky.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ky.js
new file mode 100644
index 00000000..f19fdb76
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ky.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ky",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lc.js
new file mode 100644
index 00000000..cf95b831
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-lc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lr.js
new file mode 100644
index 00000000..87c7c8c5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-lr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-lr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ls.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ls.js
new file mode 100644
index 00000000..08575f9e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ls.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ls",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mg.js
new file mode 100644
index 00000000..10c070ab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ar",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mh.js
new file mode 100644
index 00000000..3ec0b3d4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mo.js
new file mode 100644
index 00000000..e56ec63c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MOP",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mp.js
new file mode 100644
index 00000000..1d830bf7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mp.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mp",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ms.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ms.js
new file mode 100644
index 00000000..599a03fe
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ms.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ms",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mt.js
new file mode 100644
index 00000000..05818a8b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mt",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mu.js
new file mode 100644
index 00000000..37e64915
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MURs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mw.js
new file mode 100644
index 00000000..d850392c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-mw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MWK",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-mw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-my.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-my.js
new file mode 100644
index 00000000..f02af281
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-my.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RM",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-my",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-na.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-na.js
new file mode 100644
index 00000000..13dc95aa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-na.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-na",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nf.js
new file mode 100644
index 00000000..72154ecb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nf.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-nf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ng.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ng.js
new file mode 100644
index 00000000..3f506f47
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ng.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ng",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nr.js
new file mode 100644
index 00000000..fb7e1319
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-nr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nu.js
new file mode 100644
index 00000000..3ff530dd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-nu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nz.js
new file mode 100644
index 00000000..b0c2ce07
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-nz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d/MM/y h:mm:ss a",
+ "mediumDate": "d/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-nz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pg.js
new file mode 100644
index 00000000..e4379057
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "PGK",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-pg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ph.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ph.js
new file mode 100644
index 00000000..a1ae7ea8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ph.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b1",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ph",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pk.js
new file mode 100644
index 00000000..4d99a3e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-pk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pn.js
new file mode 100644
index 00000000..460e76ab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-pn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pr.js
new file mode 100644
index 00000000..5a2e9ef5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-pr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pw.js
new file mode 100644
index 00000000..5be68581
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-pw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-pw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-rw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-rw.js
new file mode 100644
index 00000000..477fe01e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-rw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-rw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sb.js
new file mode 100644
index 00000000..4f195c03
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sc.js
new file mode 100644
index 00000000..c77368e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SCR",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sd.js
new file mode 100644
index 00000000..642fed13
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SDG",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sg.js
new file mode 100644
index 00000000..9a573044
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sh.js
new file mode 100644
index 00000000..f44ca8a1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sl.js
new file mode 100644
index 00000000..c66cc354
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SLL",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ss.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ss.js
new file mode 100644
index 00000000..8c0e6947
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ss.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ss",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sx.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sx.js
new file mode 100644
index 00000000..b84c964f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sx.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NAf.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sx",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sz.js
new file mode 100644
index 00000000..5dc361c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-sz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SZL",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-sz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tc.js
new file mode 100644
index 00000000..d075f25c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-tc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tk.js
new file mode 100644
index 00000000..048c9256
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-tk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-to.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-to.js
new file mode 100644
index 00000000..a208e521
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-to.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "T$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-to",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tt.js
new file mode 100644
index 00000000..c10e2eea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-tt",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tv.js
new file mode 100644
index 00000000..32c7a2c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-tv",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tz.js
new file mode 100644
index 00000000..488954d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ug.js
new file mode 100644
index 00000000..9cde496b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-um.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-um.js
new file mode 100644
index 00000000..827b56c1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-um.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-um",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-us.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-us.js
new file mode 100644
index 00000000..9a9bfe82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-us.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-us",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vc.js
new file mode 100644
index 00000000..f9c1ab9b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-vc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vg.js
new file mode 100644
index 00000000..74fabbf8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-vg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vi.js
new file mode 100644
index 00000000..3d02ce57
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-vi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vu.js
new file mode 100644
index 00000000..a9f6a6ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-vu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "VUV",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-vu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ws.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ws.js
new file mode 100644
index 00000000..49d0931e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-ws.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "WST",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-ws",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-za.js
new file mode 100644
index 00000000..56283c80
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM y h:mm:ss a",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y/MM/dd h:mm a",
+ "shortDate": "y/MM/dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zm.js
new file mode 100644
index 00000000..78a5cd99
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "ZMW",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-zm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zw.js
new file mode 100644
index 00000000..84125681
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en-zw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd MMM,y h:mm:ss a",
+ "mediumDate": "dd MMM,y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/y h:mm a",
+ "shortDate": "d/M/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en-zw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en.js
new file mode 100644
index 00000000..55076c84
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_en.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "ERANAMES": [
+ "Before Christ",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "en",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo-001.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo-001.js
new file mode 100644
index 00000000..4a153257
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo-001.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "atm",
+ "ptm"
+ ],
+ "DAY": [
+ "diman\u0109o",
+ "lundo",
+ "mardo",
+ "merkredo",
+ "\u0135a\u016ddo",
+ "vendredo",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "aK",
+ "pK"
+ ],
+ "ERAS": [
+ "aK",
+ "pK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januaro",
+ "februaro",
+ "marto",
+ "aprilo",
+ "majo",
+ "junio",
+ "julio",
+ "a\u016dgusto",
+ "septembro",
+ "oktobro",
+ "novembro",
+ "decembro"
+ ],
+ "SHORTDAY": [
+ "di",
+ "lu",
+ "ma",
+ "me",
+ "\u0135a",
+ "ve",
+ "sa"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "a\u016dg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d-'a' 'de' MMMM y",
+ "longDate": "y-MMMM-dd",
+ "medium": "y-MMM-dd HH:mm:ss",
+ "mediumDate": "y-MMM-dd",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy-MM-dd HH:mm",
+ "shortDate": "yy-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "eo-001",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo.js
new file mode 100644
index 00000000..b70d7a05
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "atm",
+ "ptm"
+ ],
+ "DAY": [
+ "diman\u0109o",
+ "lundo",
+ "mardo",
+ "merkredo",
+ "\u0135a\u016ddo",
+ "vendredo",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "aK",
+ "pK"
+ ],
+ "ERAS": [
+ "aK",
+ "pK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januaro",
+ "februaro",
+ "marto",
+ "aprilo",
+ "majo",
+ "junio",
+ "julio",
+ "a\u016dgusto",
+ "septembro",
+ "oktobro",
+ "novembro",
+ "decembro"
+ ],
+ "SHORTDAY": [
+ "di",
+ "lu",
+ "ma",
+ "me",
+ "\u0135a",
+ "ve",
+ "sa"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "a\u016dg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d-'a' 'de' MMMM y",
+ "longDate": "y-MMMM-dd",
+ "medium": "y-MMM-dd HH:mm:ss",
+ "mediumDate": "y-MMM-dd",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy-MM-dd HH:mm",
+ "shortDate": "yy-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "eo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-419.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-419.js
new file mode 100644
index 00000000..00dcab26
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-419.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-419",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ar.js
new file mode 100644
index 00000000..155dfad9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ar.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-ar",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-bo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-bo.js
new file mode 100644
index 00000000..b7aa597b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-bo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Bs",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-bo",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cl.js
new file mode 100644
index 00000000..2b4a8a5a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd-MM-y h:mm:ss a",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd-MM-yy h:mm a",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-cl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-co.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-co.js
new file mode 100644
index 00000000..46b4d6bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-co.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d/MM/y h:mm:ss a",
+ "mediumDate": "d/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-co",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cr.js
new file mode 100644
index 00000000..42927de9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a1",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-cr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cu.js
new file mode 100644
index 00000000..ec16c71b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-cu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-cu",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-do.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-do.js
new file mode 100644
index 00000000..beedf8a3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-do.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-do",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ea.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ea.js
new file mode 100644
index 00000000..ffefb9d1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ea.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "es-ea",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ec.js
new file mode 100644
index 00000000..10949c12
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ec.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-ec",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-es.js
new file mode 100644
index 00000000..9d0eb656
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-es.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "es-es",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gq.js
new file mode 100644
index 00000000..d8fcd4b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gq.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-gq",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gt.js
new file mode 100644
index 00000000..e9b27cc0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-gt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d/MM/y h:mm:ss a",
+ "mediumDate": "d/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Q",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-gt",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-hn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-hn.js
new file mode 100644
index 00000000..1fc839e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-hn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd 'de' MMMM 'de' y",
+ "longDate": "dd 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "L",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-hn",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ic.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ic.js
new file mode 100644
index 00000000..10987395
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ic.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "es-ic",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-mx.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-mx.js
new file mode 100644
index 00000000..95eb1456
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-mx.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene",
+ "feb",
+ "mar",
+ "abr",
+ "may",
+ "jun",
+ "jul",
+ "ago",
+ "sep",
+ "oct",
+ "nov",
+ "dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y h:mm:ss a",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-mx",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ni.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ni.js
new file mode 100644
index 00000000..775fb5fd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ni.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "C$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-ni",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pa.js
new file mode 100644
index 00000000..141605ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pa.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "MM/dd/y h:mm:ss a",
+ "mediumDate": "MM/dd/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "MM/dd/yy h:mm a",
+ "shortDate": "MM/dd/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "B/.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-pa",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pe.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pe.js
new file mode 100644
index 00000000..ea7dfd22
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pe.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "setiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "set.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "S/.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-pe",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ph.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ph.js
new file mode 100644
index 00000000..0d7bc983
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ph.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b1",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "es-ph",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pr.js
new file mode 100644
index 00000000..0ac3ff95
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-pr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "MM/dd/y h:mm:ss a",
+ "mediumDate": "MM/dd/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "MM/dd/yy h:mm a",
+ "shortDate": "MM/dd/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-pr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-py.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-py.js
new file mode 100644
index 00000000..3dd2301b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-py.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Gs",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-py",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-sv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-sv.js
new file mode 100644
index 00000000..9a7574f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-sv.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-sv",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-us.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-us.js
new file mode 100644
index 00000000..bb8e3ccc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-us.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-us",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-uy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-uy.js
new file mode 100644
index 00000000..adfccd9f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-uy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "setiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "set.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-uy",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ve.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ve.js
new file mode 100644
index 00000000..ed2093cf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es-ve.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Bs",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "es-ve",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es.js
new file mode 100644
index 00000000..929ab026
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_es.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a. m.",
+ "p. m."
+ ],
+ "DAY": [
+ "domingo",
+ "lunes",
+ "martes",
+ "mi\u00e9rcoles",
+ "jueves",
+ "viernes",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despu\u00e9s de Cristo"
+ ],
+ "ERAS": [
+ "a. C.",
+ "d. C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "enero",
+ "febrero",
+ "marzo",
+ "abril",
+ "mayo",
+ "junio",
+ "julio",
+ "agosto",
+ "septiembre",
+ "octubre",
+ "noviembre",
+ "diciembre"
+ ],
+ "SHORTDAY": [
+ "dom.",
+ "lun.",
+ "mar.",
+ "mi\u00e9.",
+ "jue.",
+ "vie.",
+ "s\u00e1b."
+ ],
+ "SHORTMONTH": [
+ "ene.",
+ "feb.",
+ "mar.",
+ "abr.",
+ "may.",
+ "jun.",
+ "jul.",
+ "ago.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dic."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/yy H:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "es",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et-ee.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et-ee.js
new file mode 100644
index 00000000..3b900ae3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et-ee.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "p\u00fchap\u00e4ev",
+ "esmasp\u00e4ev",
+ "teisip\u00e4ev",
+ "kolmap\u00e4ev",
+ "neljap\u00e4ev",
+ "reede",
+ "laup\u00e4ev"
+ ],
+ "ERANAMES": [
+ "enne meie aega",
+ "meie aja j\u00e4rgi"
+ ],
+ "ERAS": [
+ "e.m.a.",
+ "m.a.j."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jaanuar",
+ "veebruar",
+ "m\u00e4rts",
+ "aprill",
+ "mai",
+ "juuni",
+ "juuli",
+ "august",
+ "september",
+ "oktoober",
+ "november",
+ "detsember"
+ ],
+ "SHORTDAY": [
+ "P",
+ "E",
+ "T",
+ "K",
+ "N",
+ "R",
+ "L"
+ ],
+ "SHORTMONTH": [
+ "jaan",
+ "veebr",
+ "m\u00e4rts",
+ "apr",
+ "mai",
+ "juuni",
+ "juuli",
+ "aug",
+ "sept",
+ "okt",
+ "nov",
+ "dets"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y H:mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "H:mm.ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "et-ee",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et.js
new file mode 100644
index 00000000..d10ad68a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_et.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "p\u00fchap\u00e4ev",
+ "esmasp\u00e4ev",
+ "teisip\u00e4ev",
+ "kolmap\u00e4ev",
+ "neljap\u00e4ev",
+ "reede",
+ "laup\u00e4ev"
+ ],
+ "ERANAMES": [
+ "enne meie aega",
+ "meie aja j\u00e4rgi"
+ ],
+ "ERAS": [
+ "e.m.a.",
+ "m.a.j."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jaanuar",
+ "veebruar",
+ "m\u00e4rts",
+ "aprill",
+ "mai",
+ "juuni",
+ "juuli",
+ "august",
+ "september",
+ "oktoober",
+ "november",
+ "detsember"
+ ],
+ "SHORTDAY": [
+ "P",
+ "E",
+ "T",
+ "K",
+ "N",
+ "R",
+ "L"
+ ],
+ "SHORTMONTH": [
+ "jaan",
+ "veebr",
+ "m\u00e4rts",
+ "apr",
+ "mai",
+ "juuni",
+ "juuli",
+ "aug",
+ "sept",
+ "okt",
+ "nov",
+ "dets"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y H:mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "H:mm.ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu-es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu-es.js
new file mode 100644
index 00000000..3a38161c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu-es.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "igandea",
+ "astelehena",
+ "asteartea",
+ "asteazkena",
+ "osteguna",
+ "ostirala",
+ "larunbata"
+ ],
+ "ERANAMES": [
+ "K.a.",
+ "K.o."
+ ],
+ "ERAS": [
+ "K.a.",
+ "K.o."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "urtarrilak",
+ "otsailak",
+ "martxoak",
+ "apirilak",
+ "maiatzak",
+ "ekainak",
+ "uztailak",
+ "abuztuak",
+ "irailak",
+ "urriak",
+ "azaroak",
+ "abenduak"
+ ],
+ "SHORTDAY": [
+ "ig.",
+ "al.",
+ "ar.",
+ "az.",
+ "og.",
+ "or.",
+ "lr."
+ ],
+ "SHORTMONTH": [
+ "urt.",
+ "ots.",
+ "mar.",
+ "api.",
+ "mai.",
+ "eka.",
+ "uzt.",
+ "abu.",
+ "ira.",
+ "urr.",
+ "aza.",
+ "abe."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y('e')'ko' MMMM d, EEEE",
+ "longDate": "y('e')'ko' MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y/MM/dd HH:mm",
+ "shortDate": "y/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "eu-es",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu.js
new file mode 100644
index 00000000..47e84711
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_eu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "igandea",
+ "astelehena",
+ "asteartea",
+ "asteazkena",
+ "osteguna",
+ "ostirala",
+ "larunbata"
+ ],
+ "ERANAMES": [
+ "K.a.",
+ "K.o."
+ ],
+ "ERAS": [
+ "K.a.",
+ "K.o."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "urtarrilak",
+ "otsailak",
+ "martxoak",
+ "apirilak",
+ "maiatzak",
+ "ekainak",
+ "uztailak",
+ "abuztuak",
+ "irailak",
+ "urriak",
+ "azaroak",
+ "abenduak"
+ ],
+ "SHORTDAY": [
+ "ig.",
+ "al.",
+ "ar.",
+ "az.",
+ "og.",
+ "or.",
+ "lr."
+ ],
+ "SHORTMONTH": [
+ "urt.",
+ "ots.",
+ "mar.",
+ "api.",
+ "mai.",
+ "eka.",
+ "uzt.",
+ "abu.",
+ "ira.",
+ "urr.",
+ "aza.",
+ "abe."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y('e')'ko' MMMM d, EEEE",
+ "longDate": "y('e')'ko' MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y/MM/dd HH:mm",
+ "shortDate": "y/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "eu",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo-cm.js
new file mode 100644
index 00000000..0acddea8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "k\u00edk\u00edr\u00edg",
+ "ng\u0259g\u00f3g\u0259le"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u0254",
+ "m\u0254\u0301ndi",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301b\u025b\u030c",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301l\u025b\u0301",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301nyi",
+ "f\u00falad\u00e9",
+ "s\u00e9rad\u00e9"
+ ],
+ "ERANAMES": [
+ "os\u00fas\u00faa Y\u00e9sus kiri",
+ "\u00e1mvus Y\u00e9sus Kir\u00eds"
+ ],
+ "ERAS": [
+ "oyk",
+ "ayk"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ng\u0254n os\u00fa",
+ "ng\u0254n b\u025b\u030c",
+ "ng\u0254n l\u00e1la",
+ "ng\u0254n nyina",
+ "ng\u0254n t\u00e1na",
+ "ng\u0254n sam\u0259na",
+ "ng\u0254n zamgb\u00e1la",
+ "ng\u0254n mwom",
+ "ng\u0254n ebul\u00fa",
+ "ng\u0254n aw\u00f3m",
+ "ng\u0254n aw\u00f3m ai dzi\u00e1",
+ "ng\u0254n aw\u00f3m ai b\u025b\u030c"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "m\u0254\u0301n",
+ "smb",
+ "sml",
+ "smn",
+ "f\u00fal",
+ "s\u00e9r"
+ ],
+ "SHORTMONTH": [
+ "ngo",
+ "ngb",
+ "ngl",
+ "ngn",
+ "ngt",
+ "ngs",
+ "ngz",
+ "ngm",
+ "nge",
+ "nga",
+ "ngad",
+ "ngab"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ewo-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo.js
new file mode 100644
index 00000000..dbef8cde
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ewo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "k\u00edk\u00edr\u00edg",
+ "ng\u0259g\u00f3g\u0259le"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u0254",
+ "m\u0254\u0301ndi",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301b\u025b\u030c",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301l\u025b\u0301",
+ "s\u0254\u0301nd\u0254 m\u0259l\u00fa m\u0259\u0301nyi",
+ "f\u00falad\u00e9",
+ "s\u00e9rad\u00e9"
+ ],
+ "ERANAMES": [
+ "os\u00fas\u00faa Y\u00e9sus kiri",
+ "\u00e1mvus Y\u00e9sus Kir\u00eds"
+ ],
+ "ERAS": [
+ "oyk",
+ "ayk"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ng\u0254n os\u00fa",
+ "ng\u0254n b\u025b\u030c",
+ "ng\u0254n l\u00e1la",
+ "ng\u0254n nyina",
+ "ng\u0254n t\u00e1na",
+ "ng\u0254n sam\u0259na",
+ "ng\u0254n zamgb\u00e1la",
+ "ng\u0254n mwom",
+ "ng\u0254n ebul\u00fa",
+ "ng\u0254n aw\u00f3m",
+ "ng\u0254n aw\u00f3m ai dzi\u00e1",
+ "ng\u0254n aw\u00f3m ai b\u025b\u030c"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "m\u0254\u0301n",
+ "smb",
+ "sml",
+ "smn",
+ "f\u00fal",
+ "s\u00e9r"
+ ],
+ "SHORTMONTH": [
+ "ngo",
+ "ngb",
+ "ngl",
+ "ngn",
+ "ngt",
+ "ngs",
+ "ngz",
+ "ngm",
+ "nge",
+ "nga",
+ "ngad",
+ "ngab"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ewo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-af.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-af.js
new file mode 100644
index 00000000..e3fccd39
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-af.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644\u200c\u0627\u0632\u0638\u0647\u0631",
+ "\u0628\u0639\u062f\u0627\u0632\u0638\u0647\u0631"
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f",
+ "\u0645\u06cc\u0644\u0627\u062f\u06cc"
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0628\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648",
+ "\u0641\u0648\u0631\u06cc\u0647\u0654",
+ "\u0645\u0627\u0631\u0633",
+ "\u0622\u0648\u0631\u06cc\u0644",
+ "\u0645\u0640\u06cc",
+ "\u0698\u0648\u0626\u0646",
+ "\u062c\u0648\u0644",
+ "\u0627\u0648\u062a",
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0628\u0631",
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
+ "\u062f\u0633\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 3,
+ 4
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Af.",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u200e\u00a4",
+ "negSuf": "",
+ "posPre": "\u200e\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fa-af",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-ir.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-ir.js
new file mode 100644
index 00000000..44a72b74
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa-ir.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644\u200c\u0627\u0632\u0638\u0647\u0631",
+ "\u0628\u0639\u062f\u0627\u0632\u0638\u0647\u0631"
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f",
+ "\u0645\u06cc\u0644\u0627\u062f\u06cc"
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654",
+ "\u0641\u0648\u0631\u06cc\u0647\u0654",
+ "\u0645\u0627\u0631\u0633",
+ "\u0622\u0648\u0631\u06cc\u0644",
+ "\u0645\u0647\u0654",
+ "\u0698\u0648\u0626\u0646",
+ "\u0698\u0648\u0626\u06cc\u0647\u0654",
+ "\u0627\u0648\u062a",
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0628\u0631",
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
+ "\u062f\u0633\u0627\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "SHORTMONTH": [
+ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654",
+ "\u0641\u0648\u0631\u06cc\u0647\u0654",
+ "\u0645\u0627\u0631\u0633",
+ "\u0622\u0648\u0631\u06cc\u0644",
+ "\u0645\u0647\u0654",
+ "\u0698\u0648\u0626\u0646",
+ "\u0698\u0648\u0626\u06cc\u0647\u0654",
+ "\u0627\u0648\u062a",
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0628\u0631",
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
+ "\u062f\u0633\u0627\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 4
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u200e\u00a4",
+ "negSuf": "",
+ "posPre": "\u200e\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fa-ir",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa.js
new file mode 100644
index 00000000..48eb5dd0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fa.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644\u200c\u0627\u0632\u0638\u0647\u0631",
+ "\u0628\u0639\u062f\u0627\u0632\u0638\u0647\u0631"
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0627\u0632 \u0645\u06cc\u0644\u0627\u062f",
+ "\u0645\u06cc\u0644\u0627\u062f\u06cc"
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654",
+ "\u0641\u0648\u0631\u06cc\u0647\u0654",
+ "\u0645\u0627\u0631\u0633",
+ "\u0622\u0648\u0631\u06cc\u0644",
+ "\u0645\u0647\u0654",
+ "\u0698\u0648\u0626\u0646",
+ "\u0698\u0648\u0626\u06cc\u0647\u0654",
+ "\u0627\u0648\u062a",
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0628\u0631",
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
+ "\u062f\u0633\u0627\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "SHORTMONTH": [
+ "\u0698\u0627\u0646\u0648\u06cc\u0647\u0654",
+ "\u0641\u0648\u0631\u06cc\u0647\u0654",
+ "\u0645\u0627\u0631\u0633",
+ "\u0622\u0648\u0631\u06cc\u0644",
+ "\u0645\u0647\u0654",
+ "\u0698\u0648\u0626\u0646",
+ "\u0698\u0648\u0626\u06cc\u0647\u0654",
+ "\u0627\u0648\u062a",
+ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0628\u0631",
+ "\u0646\u0648\u0627\u0645\u0628\u0631",
+ "\u062f\u0633\u0627\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 4
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rial",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u200e\u00a4",
+ "negSuf": "",
+ "posPre": "\u200e\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fa",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-cm.js
new file mode 100644
index 00000000..87589cf1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "subaka",
+ "kikii\u0257e"
+ ],
+ "DAY": [
+ "dewo",
+ "aa\u0253nde",
+ "mawbaare",
+ "njeslaare",
+ "naasaande",
+ "mawnde",
+ "hoore-biir"
+ ],
+ "ERANAMES": [
+ "Hade Iisa",
+ "Caggal Iisa"
+ ],
+ "ERAS": [
+ "H-I",
+ "C-I"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "siilo",
+ "colte",
+ "mbooy",
+ "see\u0257to",
+ "duujal",
+ "korse",
+ "morso",
+ "juko",
+ "siilto",
+ "yarkomaa",
+ "jolal",
+ "bowte"
+ ],
+ "SHORTDAY": [
+ "dew",
+ "aa\u0253",
+ "maw",
+ "nje",
+ "naa",
+ "mwd",
+ "hbi"
+ ],
+ "SHORTMONTH": [
+ "sii",
+ "col",
+ "mbo",
+ "see",
+ "duu",
+ "kor",
+ "mor",
+ "juk",
+ "slt",
+ "yar",
+ "jol",
+ "bow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ff-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-gn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-gn.js
new file mode 100644
index 00000000..a7678f02
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-gn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "subaka",
+ "kikii\u0257e"
+ ],
+ "DAY": [
+ "dewo",
+ "aa\u0253nde",
+ "mawbaare",
+ "njeslaare",
+ "naasaande",
+ "mawnde",
+ "hoore-biir"
+ ],
+ "ERANAMES": [
+ "Hade Iisa",
+ "Caggal Iisa"
+ ],
+ "ERAS": [
+ "H-I",
+ "C-I"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "siilo",
+ "colte",
+ "mbooy",
+ "see\u0257to",
+ "duujal",
+ "korse",
+ "morso",
+ "juko",
+ "siilto",
+ "yarkomaa",
+ "jolal",
+ "bowte"
+ ],
+ "SHORTDAY": [
+ "dew",
+ "aa\u0253",
+ "maw",
+ "nje",
+ "naa",
+ "mwd",
+ "hbi"
+ ],
+ "SHORTMONTH": [
+ "sii",
+ "col",
+ "mbo",
+ "see",
+ "duu",
+ "kor",
+ "mor",
+ "juk",
+ "slt",
+ "yar",
+ "jol",
+ "bow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FG",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ff-gn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-mr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-mr.js
new file mode 100644
index 00000000..c36b8a25
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-mr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "subaka",
+ "kikii\u0257e"
+ ],
+ "DAY": [
+ "dewo",
+ "aa\u0253nde",
+ "mawbaare",
+ "njeslaare",
+ "naasaande",
+ "mawnde",
+ "hoore-biir"
+ ],
+ "ERANAMES": [
+ "Hade Iisa",
+ "Caggal Iisa"
+ ],
+ "ERAS": [
+ "H-I",
+ "C-I"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "siilo",
+ "colte",
+ "mbooy",
+ "see\u0257to",
+ "duujal",
+ "korse",
+ "morso",
+ "juko",
+ "siilto",
+ "yarkomaa",
+ "jolal",
+ "bowte"
+ ],
+ "SHORTDAY": [
+ "dew",
+ "aa\u0253",
+ "maw",
+ "nje",
+ "naa",
+ "mwd",
+ "hbi"
+ ],
+ "SHORTMONTH": [
+ "sii",
+ "col",
+ "mbo",
+ "see",
+ "duu",
+ "kor",
+ "mor",
+ "juk",
+ "slt",
+ "yar",
+ "jol",
+ "bow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MRO",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ff-mr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-sn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-sn.js
new file mode 100644
index 00000000..e71e7b62
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff-sn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "subaka",
+ "kikii\u0257e"
+ ],
+ "DAY": [
+ "dewo",
+ "aa\u0253nde",
+ "mawbaare",
+ "njeslaare",
+ "naasaande",
+ "mawnde",
+ "hoore-biir"
+ ],
+ "ERANAMES": [
+ "Hade Iisa",
+ "Caggal Iisa"
+ ],
+ "ERAS": [
+ "H-I",
+ "C-I"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "siilo",
+ "colte",
+ "mbooy",
+ "see\u0257to",
+ "duujal",
+ "korse",
+ "morso",
+ "juko",
+ "siilto",
+ "yarkomaa",
+ "jolal",
+ "bowte"
+ ],
+ "SHORTDAY": [
+ "dew",
+ "aa\u0253",
+ "maw",
+ "nje",
+ "naa",
+ "mwd",
+ "hbi"
+ ],
+ "SHORTMONTH": [
+ "sii",
+ "col",
+ "mbo",
+ "see",
+ "duu",
+ "kor",
+ "mor",
+ "juk",
+ "slt",
+ "yar",
+ "jol",
+ "bow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ff-sn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff.js
new file mode 100644
index 00000000..9ce7b830
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ff.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "subaka",
+ "kikii\u0257e"
+ ],
+ "DAY": [
+ "dewo",
+ "aa\u0253nde",
+ "mawbaare",
+ "njeslaare",
+ "naasaande",
+ "mawnde",
+ "hoore-biir"
+ ],
+ "ERANAMES": [
+ "Hade Iisa",
+ "Caggal Iisa"
+ ],
+ "ERAS": [
+ "H-I",
+ "C-I"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "siilo",
+ "colte",
+ "mbooy",
+ "see\u0257to",
+ "duujal",
+ "korse",
+ "morso",
+ "juko",
+ "siilto",
+ "yarkomaa",
+ "jolal",
+ "bowte"
+ ],
+ "SHORTDAY": [
+ "dew",
+ "aa\u0253",
+ "maw",
+ "nje",
+ "naa",
+ "mwd",
+ "hbi"
+ ],
+ "SHORTMONTH": [
+ "sii",
+ "col",
+ "mbo",
+ "see",
+ "duu",
+ "kor",
+ "mor",
+ "juk",
+ "slt",
+ "yar",
+ "jol",
+ "bow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ff",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi-fi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi-fi.js
new file mode 100644
index 00000000..44bd4120
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi-fi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ap.",
+ "ip."
+ ],
+ "DAY": [
+ "sunnuntaina",
+ "maanantaina",
+ "tiistaina",
+ "keskiviikkona",
+ "torstaina",
+ "perjantaina",
+ "lauantaina"
+ ],
+ "ERANAMES": [
+ "ennen Kristuksen syntym\u00e4\u00e4",
+ "j\u00e4lkeen Kristuksen syntym\u00e4n"
+ ],
+ "ERAS": [
+ "eKr.",
+ "jKr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "tammikuuta",
+ "helmikuuta",
+ "maaliskuuta",
+ "huhtikuuta",
+ "toukokuuta",
+ "kes\u00e4kuuta",
+ "hein\u00e4kuuta",
+ "elokuuta",
+ "syyskuuta",
+ "lokakuuta",
+ "marraskuuta",
+ "joulukuuta"
+ ],
+ "SHORTDAY": [
+ "su",
+ "ma",
+ "ti",
+ "ke",
+ "to",
+ "pe",
+ "la"
+ ],
+ "SHORTMONTH": [
+ "tammikuuta",
+ "helmikuuta",
+ "maaliskuuta",
+ "huhtikuuta",
+ "toukokuuta",
+ "kes\u00e4kuuta",
+ "hein\u00e4kuuta",
+ "elokuuta",
+ "syyskuuta",
+ "lokakuuta",
+ "marraskuuta",
+ "joulukuuta"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "cccc d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H.mm.ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H.mm.ss",
+ "short": "d.M.y H.mm",
+ "shortDate": "d.M.y",
+ "shortTime": "H.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fi-fi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi.js
new file mode 100644
index 00000000..ade16564
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ap.",
+ "ip."
+ ],
+ "DAY": [
+ "sunnuntaina",
+ "maanantaina",
+ "tiistaina",
+ "keskiviikkona",
+ "torstaina",
+ "perjantaina",
+ "lauantaina"
+ ],
+ "ERANAMES": [
+ "ennen Kristuksen syntym\u00e4\u00e4",
+ "j\u00e4lkeen Kristuksen syntym\u00e4n"
+ ],
+ "ERAS": [
+ "eKr.",
+ "jKr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "tammikuuta",
+ "helmikuuta",
+ "maaliskuuta",
+ "huhtikuuta",
+ "toukokuuta",
+ "kes\u00e4kuuta",
+ "hein\u00e4kuuta",
+ "elokuuta",
+ "syyskuuta",
+ "lokakuuta",
+ "marraskuuta",
+ "joulukuuta"
+ ],
+ "SHORTDAY": [
+ "su",
+ "ma",
+ "ti",
+ "ke",
+ "to",
+ "pe",
+ "la"
+ ],
+ "SHORTMONTH": [
+ "tammikuuta",
+ "helmikuuta",
+ "maaliskuuta",
+ "huhtikuuta",
+ "toukokuuta",
+ "kes\u00e4kuuta",
+ "hein\u00e4kuuta",
+ "elokuuta",
+ "syyskuuta",
+ "lokakuuta",
+ "marraskuuta",
+ "joulukuuta"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "cccc d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H.mm.ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H.mm.ss",
+ "short": "d.M.y H.mm",
+ "shortDate": "d.M.y",
+ "shortTime": "H.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil-ph.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil-ph.js
new file mode 100644
index 00000000..541d3cde
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil-ph.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Linggo",
+ "Lunes",
+ "Martes",
+ "Miyerkules",
+ "Huwebes",
+ "Biyernes",
+ "Sabado"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Enero",
+ "Pebrero",
+ "Marso",
+ "Abril",
+ "Mayo",
+ "Hunyo",
+ "Hulyo",
+ "Agosto",
+ "Setyembre",
+ "Oktubre",
+ "Nobyembre",
+ "Disyembre"
+ ],
+ "SHORTDAY": [
+ "Lin",
+ "Lun",
+ "Mar",
+ "Miy",
+ "Huw",
+ "Biy",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Ene",
+ "Peb",
+ "Mar",
+ "Abr",
+ "May",
+ "Hun",
+ "Hul",
+ "Ago",
+ "Set",
+ "Okt",
+ "Nob",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b1",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fil-ph",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && (i == 1 || i == 2 || i == 3) || vf.v == 0 && i % 10 != 4 && i % 10 != 6 && i % 10 != 9 || vf.v != 0 && vf.f % 10 != 4 && vf.f % 10 != 6 && vf.f % 10 != 9) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil.js
new file mode 100644
index 00000000..5cded550
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fil.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Linggo",
+ "Lunes",
+ "Martes",
+ "Miyerkules",
+ "Huwebes",
+ "Biyernes",
+ "Sabado"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Enero",
+ "Pebrero",
+ "Marso",
+ "Abril",
+ "Mayo",
+ "Hunyo",
+ "Hulyo",
+ "Agosto",
+ "Setyembre",
+ "Oktubre",
+ "Nobyembre",
+ "Disyembre"
+ ],
+ "SHORTDAY": [
+ "Lin",
+ "Lun",
+ "Mar",
+ "Miy",
+ "Huw",
+ "Biy",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Ene",
+ "Peb",
+ "Mar",
+ "Abr",
+ "May",
+ "Hun",
+ "Hul",
+ "Ago",
+ "Set",
+ "Okt",
+ "Nob",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b1",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fil",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && (i == 1 || i == 2 || i == 3) || vf.v == 0 && i % 10 != 4 && i % 10 != 6 && i % 10 != 9 || vf.v != 0 && vf.f % 10 != 4 && vf.f % 10 != 6 && vf.f % 10 != 9) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo-fo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo-fo.js
new file mode 100644
index 00000000..a861d8c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo-fo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "um fyrrapartur",
+ "um seinnapartur"
+ ],
+ "DAY": [
+ "sunnudagur",
+ "m\u00e1nadagur",
+ "t\u00fdsdagur",
+ "mikudagur",
+ "h\u00f3sdagur",
+ "fr\u00edggjadagur",
+ "leygardagur"
+ ],
+ "ERANAMES": [
+ "fyrir Krist",
+ "eftir Krist"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "apr\u00edl",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "sun",
+ "m\u00e1n",
+ "t\u00fds",
+ "mik",
+ "h\u00f3s",
+ "fr\u00ed",
+ "ley"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "mai",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "d. MMM y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fo-fo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo.js
new file mode 100644
index 00000000..aa33cd32
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "um fyrrapartur",
+ "um seinnapartur"
+ ],
+ "DAY": [
+ "sunnudagur",
+ "m\u00e1nadagur",
+ "t\u00fdsdagur",
+ "mikudagur",
+ "h\u00f3sdagur",
+ "fr\u00edggjadagur",
+ "leygardagur"
+ ],
+ "ERANAMES": [
+ "fyrir Krist",
+ "eftir Krist"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "apr\u00edl",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "sun",
+ "m\u00e1n",
+ "t\u00fds",
+ "mik",
+ "h\u00f3s",
+ "fr\u00ed",
+ "ley"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "mai",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "d. MMM y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-be.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-be.js
new file mode 100644
index 00000000..acec9a42
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-be.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/MM/yy HH:mm",
+ "shortDate": "d/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-be",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bf.js
new file mode 100644
index 00000000..bd30d550
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-bf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bi.js
new file mode 100644
index 00000000..39d3b329
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bi.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FBu",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-bi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bj.js
new file mode 100644
index 00000000..6753f020
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bj.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-bj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bl.js
new file mode 100644
index 00000000..2f15f5a3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-bl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-bl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ca.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ca.js
new file mode 100644
index 00000000..6f5f703b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ca.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy-MM-dd HH:mm",
+ "shortDate": "yy-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ca",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cd.js
new file mode 100644
index 00000000..1e1d1cc3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cd.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-cd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cf.js
new file mode 100644
index 00000000..bf605538
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-cf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cg.js
new file mode 100644
index 00000000..c4417732
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-cg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ch.js
new file mode 100644
index 00000000..e69d2fe3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ch.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fr-ch",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ci.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ci.js
new file mode 100644
index 00000000..2954b103
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ci.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ci",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cm.js
new file mode 100644
index 00000000..d8f03d2e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-cm.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dj.js
new file mode 100644
index 00000000..9c850c29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dj.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Fdj",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-dj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dz.js
new file mode 100644
index 00000000..ae1e1c67
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-dz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-dz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-fr.js
new file mode 100644
index 00000000..bdef4eff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-fr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-fr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ga.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ga.js
new file mode 100644
index 00000000..6268c777
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ga.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ga",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gf.js
new file mode 100644
index 00000000..a7d37a0f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-gf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gn.js
new file mode 100644
index 00000000..34f4b101
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FG",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-gn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gp.js
new file mode 100644
index 00000000..9db67089
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gp.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-gp",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gq.js
new file mode 100644
index 00000000..02bbba29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-gq.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-gq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ht.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ht.js
new file mode 100644
index 00000000..116e0da6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ht.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "HTG",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ht",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-km.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-km.js
new file mode 100644
index 00000000..e178c7f3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-km.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-km",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-lu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-lu.js
new file mode 100644
index 00000000..bb236277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-lu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-lu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ma.js
new file mode 100644
index 00000000..92edf74b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ma.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ma",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mc.js
new file mode 100644
index 00000000..85e0233e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mc.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mf.js
new file mode 100644
index 00000000..2abced5c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mg.js
new file mode 100644
index 00000000..02d27478
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ar",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ml.js
new file mode 100644
index 00000000..e4549e2b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ml.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ml",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mq.js
new file mode 100644
index 00000000..3973b32e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mq.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mr.js
new file mode 100644
index 00000000..5b993c6d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MRO",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mu.js
new file mode 100644
index 00000000..7b09bd2e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-mu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MURs",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-mu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-nc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-nc.js
new file mode 100644
index 00000000..a0694a9f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-nc.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFP",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-nc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ne.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ne.js
new file mode 100644
index 00000000..7fd04821
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-ne.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-ne",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pf.js
new file mode 100644
index 00000000..d5d023a3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFP",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-pf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pm.js
new file mode 100644
index 00000000..2ed15ec9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-pm.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-pm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-re.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-re.js
new file mode 100644
index 00000000..1c1e849e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-re.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-re",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-rw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-rw.js
new file mode 100644
index 00000000..8966b7a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-rw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-rw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sc.js
new file mode 100644
index 00000000..80410913
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sc.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SCR",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-sc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sn.js
new file mode 100644
index 00000000..100a1025
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-sn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sy.js
new file mode 100644
index 00000000..8bcfaf1a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-sy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-sy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-td.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-td.js
new file mode 100644
index 00000000..2341ef76
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-td.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-td",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tg.js
new file mode 100644
index 00000000..a7c21313
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-tg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tn.js
new file mode 100644
index 00000000..14a31151
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-tn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-tn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-vu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-vu.js
new file mode 100644
index 00000000..d23d528c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-vu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "VUV",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-vu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-wf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-wf.js
new file mode 100644
index 00000000..bf5a357b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-wf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFP",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-wf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-yt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-yt.js
new file mode 100644
index 00000000..265a0324
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr-yt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr-yt",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr.js
new file mode 100644
index 00000000..f4d89ba2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimanche",
+ "lundi",
+ "mardi",
+ "mercredi",
+ "jeudi",
+ "vendredi",
+ "samedi"
+ ],
+ "ERANAMES": [
+ "avant J\u00e9sus-Christ",
+ "apr\u00e8s J\u00e9sus-Christ"
+ ],
+ "ERAS": [
+ "av. J.-C.",
+ "ap. J.-C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janvier",
+ "f\u00e9vrier",
+ "mars",
+ "avril",
+ "mai",
+ "juin",
+ "juillet",
+ "ao\u00fbt",
+ "septembre",
+ "octobre",
+ "novembre",
+ "d\u00e9cembre"
+ ],
+ "SHORTDAY": [
+ "dim.",
+ "lun.",
+ "mar.",
+ "mer.",
+ "jeu.",
+ "ven.",
+ "sam."
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "f\u00e9vr.",
+ "mars",
+ "avr.",
+ "mai",
+ "juin",
+ "juil.",
+ "ao\u00fbt",
+ "sept.",
+ "oct.",
+ "nov.",
+ "d\u00e9c."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "fr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur-it.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur-it.js
new file mode 100644
index 00000000..8f1e80b9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur-it.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.",
+ "p."
+ ],
+ "DAY": [
+ "domenie",
+ "lunis",
+ "martars",
+ "miercus",
+ "joibe",
+ "vinars",
+ "sabide"
+ ],
+ "ERANAMES": [
+ "pdC",
+ "ddC"
+ ],
+ "ERAS": [
+ "pdC",
+ "ddC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Zen\u00e2r",
+ "Fevr\u00e2r",
+ "Mar\u00e7",
+ "Avr\u00eel",
+ "Mai",
+ "Jugn",
+ "Lui",
+ "Avost",
+ "Setembar",
+ "Otubar",
+ "Novembar",
+ "Dicembar"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mie",
+ "joi",
+ "vin",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "Zen",
+ "Fev",
+ "Mar",
+ "Avr",
+ "Mai",
+ "Jug",
+ "Lui",
+ "Avo",
+ "Set",
+ "Otu",
+ "Nov",
+ "Dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d 'di' MMMM 'dal' y",
+ "longDate": "d 'di' MMMM 'dal' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fur-it",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur.js
new file mode 100644
index 00000000..ccb73300
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fur.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.",
+ "p."
+ ],
+ "DAY": [
+ "domenie",
+ "lunis",
+ "martars",
+ "miercus",
+ "joibe",
+ "vinars",
+ "sabide"
+ ],
+ "ERANAMES": [
+ "pdC",
+ "ddC"
+ ],
+ "ERAS": [
+ "pdC",
+ "ddC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Zen\u00e2r",
+ "Fevr\u00e2r",
+ "Mar\u00e7",
+ "Avr\u00eel",
+ "Mai",
+ "Jugn",
+ "Lui",
+ "Avost",
+ "Setembar",
+ "Otubar",
+ "Novembar",
+ "Dicembar"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mie",
+ "joi",
+ "vin",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "Zen",
+ "Fev",
+ "Mar",
+ "Avr",
+ "Mai",
+ "Jug",
+ "Lui",
+ "Avo",
+ "Set",
+ "Otu",
+ "Nov",
+ "Dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d 'di' MMMM 'dal' y",
+ "longDate": "d 'di' MMMM 'dal' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fur",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy-nl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy-nl.js
new file mode 100644
index 00000000..234e983b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy-nl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "snein",
+ "moandei",
+ "tiisdei",
+ "woansdei",
+ "tongersdei",
+ "freed",
+ "sneon"
+ ],
+ "ERANAMES": [
+ "Foar Kristus",
+ "nei Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "n.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jannewaris",
+ "febrewaris",
+ "maart",
+ "april",
+ "maaie",
+ "juny",
+ "july",
+ "augustus",
+ "septimber",
+ "oktober",
+ "novimber",
+ "desimber"
+ ],
+ "SHORTDAY": [
+ "si",
+ "mo",
+ "ti",
+ "wo",
+ "to",
+ "fr",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0",
+ "negSuf": "-",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fy-nl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy.js
new file mode 100644
index 00000000..6bf7ba6b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_fy.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "snein",
+ "moandei",
+ "tiisdei",
+ "woansdei",
+ "tongersdei",
+ "freed",
+ "sneon"
+ ],
+ "ERANAMES": [
+ "Foar Kristus",
+ "nei Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "n.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jannewaris",
+ "febrewaris",
+ "maart",
+ "april",
+ "maaie",
+ "juny",
+ "july",
+ "augustus",
+ "septimber",
+ "oktober",
+ "novimber",
+ "desimber"
+ ],
+ "SHORTDAY": [
+ "si",
+ "mo",
+ "ti",
+ "wo",
+ "to",
+ "fr",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0",
+ "negSuf": "-",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "fy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga-ie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga-ie.js
new file mode 100644
index 00000000..5740a197
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga-ie.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "D\u00e9 Domhnaigh",
+ "D\u00e9 Luain",
+ "D\u00e9 M\u00e1irt",
+ "D\u00e9 C\u00e9adaoin",
+ "D\u00e9ardaoin",
+ "D\u00e9 hAoine",
+ "D\u00e9 Sathairn"
+ ],
+ "ERANAMES": [
+ "Roimh Chr\u00edost",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ean\u00e1ir",
+ "Feabhra",
+ "M\u00e1rta",
+ "Aibre\u00e1n",
+ "Bealtaine",
+ "Meitheamh",
+ "I\u00fail",
+ "L\u00fanasa",
+ "Me\u00e1n F\u00f3mhair",
+ "Deireadh F\u00f3mhair",
+ "Samhain",
+ "Nollaig"
+ ],
+ "SHORTDAY": [
+ "Domh",
+ "Luan",
+ "M\u00e1irt",
+ "C\u00e9ad",
+ "D\u00e9ar",
+ "Aoine",
+ "Sath"
+ ],
+ "SHORTMONTH": [
+ "Ean",
+ "Feabh",
+ "M\u00e1rta",
+ "Aib",
+ "Beal",
+ "Meith",
+ "I\u00fail",
+ "L\u00fan",
+ "MF\u00f3mh",
+ "DF\u00f3mh",
+ "Samh",
+ "Noll"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ga-ie",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n >= 3 && n <= 6) { return PLURAL_CATEGORY.FEW; } if (n >= 7 && n <= 10) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga.js
new file mode 100644
index 00000000..76f0d145
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ga.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "D\u00e9 Domhnaigh",
+ "D\u00e9 Luain",
+ "D\u00e9 M\u00e1irt",
+ "D\u00e9 C\u00e9adaoin",
+ "D\u00e9ardaoin",
+ "D\u00e9 hAoine",
+ "D\u00e9 Sathairn"
+ ],
+ "ERANAMES": [
+ "Roimh Chr\u00edost",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ean\u00e1ir",
+ "Feabhra",
+ "M\u00e1rta",
+ "Aibre\u00e1n",
+ "Bealtaine",
+ "Meitheamh",
+ "I\u00fail",
+ "L\u00fanasa",
+ "Me\u00e1n F\u00f3mhair",
+ "Deireadh F\u00f3mhair",
+ "Samhain",
+ "Nollaig"
+ ],
+ "SHORTDAY": [
+ "Domh",
+ "Luan",
+ "M\u00e1irt",
+ "C\u00e9ad",
+ "D\u00e9ar",
+ "Aoine",
+ "Sath"
+ ],
+ "SHORTMONTH": [
+ "Ean",
+ "Feabh",
+ "M\u00e1rta",
+ "Aib",
+ "Beal",
+ "Meith",
+ "I\u00fail",
+ "L\u00fan",
+ "MF\u00f3mh",
+ "DF\u00f3mh",
+ "Samh",
+ "Noll"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ga",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n >= 3 && n <= 6) { return PLURAL_CATEGORY.FEW; } if (n >= 7 && n <= 10) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd-gb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd-gb.js
new file mode 100644
index 00000000..c245bc5d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd-gb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "m",
+ "f"
+ ],
+ "DAY": [
+ "DiD\u00f2mhnaich",
+ "DiLuain",
+ "DiM\u00e0irt",
+ "DiCiadain",
+ "DiarDaoin",
+ "DihAoine",
+ "DiSathairne"
+ ],
+ "ERANAMES": [
+ "Ro Chr\u00ecosta",
+ "An d\u00e8idh Chr\u00ecosta"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dhen Fhaoilleach",
+ "dhen Ghearran",
+ "dhen Mh\u00e0rt",
+ "dhen Ghiblean",
+ "dhen Ch\u00e8itean",
+ "dhen \u00d2gmhios",
+ "dhen Iuchar",
+ "dhen L\u00f9nastal",
+ "dhen t-Sultain",
+ "dhen D\u00e0mhair",
+ "dhen t-Samhain",
+ "dhen D\u00f9bhlachd"
+ ],
+ "SHORTDAY": [
+ "DiD",
+ "DiL",
+ "DiM",
+ "DiC",
+ "Dia",
+ "Dih",
+ "DiS"
+ ],
+ "SHORTMONTH": [
+ "Faoi",
+ "Gearr",
+ "M\u00e0rt",
+ "Gibl",
+ "C\u00e8it",
+ "\u00d2gmh",
+ "Iuch",
+ "L\u00f9na",
+ "Sult",
+ "D\u00e0mh",
+ "Samh",
+ "D\u00f9bh"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d'mh' MMMM y",
+ "longDate": "d'mh' MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gd-gb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd.js
new file mode 100644
index 00000000..9fe0c4d8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "m",
+ "f"
+ ],
+ "DAY": [
+ "DiD\u00f2mhnaich",
+ "DiLuain",
+ "DiM\u00e0irt",
+ "DiCiadain",
+ "DiarDaoin",
+ "DihAoine",
+ "DiSathairne"
+ ],
+ "ERANAMES": [
+ "Ro Chr\u00ecosta",
+ "An d\u00e8idh Chr\u00ecosta"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "dhen Fhaoilleach",
+ "dhen Ghearran",
+ "dhen Mh\u00e0rt",
+ "dhen Ghiblean",
+ "dhen Ch\u00e8itean",
+ "dhen \u00d2gmhios",
+ "dhen Iuchar",
+ "dhen L\u00f9nastal",
+ "dhen t-Sultain",
+ "dhen D\u00e0mhair",
+ "dhen t-Samhain",
+ "dhen D\u00f9bhlachd"
+ ],
+ "SHORTDAY": [
+ "DiD",
+ "DiL",
+ "DiM",
+ "DiC",
+ "Dia",
+ "Dih",
+ "DiS"
+ ],
+ "SHORTMONTH": [
+ "Faoi",
+ "Gearr",
+ "M\u00e0rt",
+ "Gibl",
+ "C\u00e8it",
+ "\u00d2gmh",
+ "Iuch",
+ "L\u00f9na",
+ "Sult",
+ "D\u00e0mh",
+ "Samh",
+ "D\u00f9bh"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d'mh' MMMM y",
+ "longDate": "d'mh' MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl-es.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl-es.js
new file mode 100644
index 00000000..fff9928c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl-es.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "domingo",
+ "luns",
+ "martes",
+ "m\u00e9rcores",
+ "xoves",
+ "venres",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "xaneiro",
+ "febreiro",
+ "marzo",
+ "abril",
+ "maio",
+ "xu\u00f1o",
+ "xullo",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "decembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "m\u00e9r",
+ "xov",
+ "ven",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "xan",
+ "feb",
+ "mar",
+ "abr",
+ "mai",
+ "xu\u00f1",
+ "xul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gl-es",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl.js
new file mode 100644
index 00000000..9223c276
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "domingo",
+ "luns",
+ "martes",
+ "m\u00e9rcores",
+ "xoves",
+ "venres",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "despois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "xaneiro",
+ "febreiro",
+ "marzo",
+ "abril",
+ "maio",
+ "xu\u00f1o",
+ "xullo",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "decembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "m\u00e9r",
+ "xov",
+ "ven",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "xan",
+ "feb",
+ "mar",
+ "abr",
+ "mai",
+ "xu\u00f1",
+ "xul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-ch.js
new file mode 100644
index 00000000..54278de0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-ch.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nam."
+ ],
+ "DAY": [
+ "Sunntig",
+ "M\u00e4\u00e4ntig",
+ "Ziischtig",
+ "Mittwuch",
+ "Dunschtig",
+ "Friitig",
+ "Samschtig"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Auguscht",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "M\u00e4.",
+ "Zi.",
+ "Mi.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "M\u00e4r",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "gsw-ch",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-fr.js
new file mode 100644
index 00000000..979ced7a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-fr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nam."
+ ],
+ "DAY": [
+ "Sunntig",
+ "M\u00e4\u00e4ntig",
+ "Ziischtig",
+ "Mittwuch",
+ "Dunschtig",
+ "Friitig",
+ "Samschtig"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Auguscht",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "M\u00e4.",
+ "Zi.",
+ "Mi.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "M\u00e4r",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "gsw-fr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-li.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-li.js
new file mode 100644
index 00000000..c1a5aebc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw-li.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nam."
+ ],
+ "DAY": [
+ "Sunntig",
+ "M\u00e4\u00e4ntig",
+ "Ziischtig",
+ "Mittwuch",
+ "Dunschtig",
+ "Friitig",
+ "Samschtig"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Auguscht",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "M\u00e4.",
+ "Zi.",
+ "Mi.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "M\u00e4r",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "gsw-li",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw.js
new file mode 100644
index 00000000..93ef2cd0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gsw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "vorm.",
+ "nam."
+ ],
+ "DAY": [
+ "Sunntig",
+ "M\u00e4\u00e4ntig",
+ "Ziischtig",
+ "Mittwuch",
+ "Dunschtig",
+ "Friitig",
+ "Samschtig"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4rz",
+ "April",
+ "Mai",
+ "Juni",
+ "Juli",
+ "Auguscht",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "M\u00e4.",
+ "Zi.",
+ "Mi.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "M\u00e4r",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "gsw",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu-in.js
new file mode 100644
index 00000000..db7daba8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0ab0\u0ab5\u0abf\u0ab5\u0abe\u0ab0",
+ "\u0ab8\u0acb\u0aae\u0ab5\u0abe\u0ab0",
+ "\u0aae\u0a82\u0a97\u0ab3\u0ab5\u0abe\u0ab0",
+ "\u0aac\u0ac1\u0aa7\u0ab5\u0abe\u0ab0",
+ "\u0a97\u0ac1\u0ab0\u0ac1\u0ab5\u0abe\u0ab0",
+ "\u0ab6\u0ac1\u0a95\u0acd\u0ab0\u0ab5\u0abe\u0ab0",
+ "\u0ab6\u0aa8\u0abf\u0ab5\u0abe\u0ab0"
+ ],
+ "ERANAMES": [
+ "\u0a88\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8 \u0aaa\u0ac2\u0ab0\u0acd\u0ab5\u0ac7",
+ "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8"
+ ],
+ "ERAS": [
+ "\u0a88\u0ab8\u0ac1\u0aa8\u0abe \u0a9c\u0aa8\u0acd\u0aae \u0aaa\u0ab9\u0ac7\u0ab2\u0abe",
+ "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1\u0a86\u0ab0\u0ac0",
+ "\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1\u0a86\u0ab0\u0ac0",
+ "\u0aae\u0abe\u0ab0\u0acd\u0a9a",
+ "\u0a8f\u0aaa\u0acd\u0ab0\u0abf\u0ab2",
+ "\u0aae\u0ac7",
+ "\u0a9c\u0ac2\u0aa8",
+ "\u0a9c\u0ac1\u0ab2\u0abe\u0a88",
+ "\u0a91\u0a97\u0ab8\u0acd\u0a9f",
+ "\u0ab8\u0aaa\u0acd\u0a9f\u0ac7\u0aae\u0acd\u0aac\u0ab0",
+ "\u0a91\u0a95\u0acd\u0a9f\u0acb\u0aac\u0ab0",
+ "\u0aa8\u0ab5\u0ac7\u0aae\u0acd\u0aac\u0ab0",
+ "\u0aa1\u0abf\u0ab8\u0ac7\u0aae\u0acd\u0aac\u0ab0"
+ ],
+ "SHORTDAY": [
+ "\u0ab0\u0ab5\u0abf",
+ "\u0ab8\u0acb\u0aae",
+ "\u0aae\u0a82\u0a97\u0ab3",
+ "\u0aac\u0ac1\u0aa7",
+ "\u0a97\u0ac1\u0ab0\u0ac1",
+ "\u0ab6\u0ac1\u0a95\u0acd\u0ab0",
+ "\u0ab6\u0aa8\u0abf"
+ ],
+ "SHORTMONTH": [
+ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1",
+ "\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1",
+ "\u0aae\u0abe\u0ab0\u0acd\u0a9a",
+ "\u0a8f\u0aaa\u0acd\u0ab0\u0abf\u0ab2",
+ "\u0aae\u0ac7",
+ "\u0a9c\u0ac2\u0aa8",
+ "\u0a9c\u0ac1\u0ab2\u0abe\u0a88",
+ "\u0a91\u0a97",
+ "\u0ab8\u0aaa\u0acd\u0a9f\u0ac7",
+ "\u0a91\u0a95\u0acd\u0a9f\u0acb",
+ "\u0aa8\u0ab5\u0ac7",
+ "\u0aa1\u0abf\u0ab8\u0ac7"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y hh:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "hh:mm:ss a",
+ "short": "d/M/yy hh:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gu-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu.js
new file mode 100644
index 00000000..a66e2b54
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0ab0\u0ab5\u0abf\u0ab5\u0abe\u0ab0",
+ "\u0ab8\u0acb\u0aae\u0ab5\u0abe\u0ab0",
+ "\u0aae\u0a82\u0a97\u0ab3\u0ab5\u0abe\u0ab0",
+ "\u0aac\u0ac1\u0aa7\u0ab5\u0abe\u0ab0",
+ "\u0a97\u0ac1\u0ab0\u0ac1\u0ab5\u0abe\u0ab0",
+ "\u0ab6\u0ac1\u0a95\u0acd\u0ab0\u0ab5\u0abe\u0ab0",
+ "\u0ab6\u0aa8\u0abf\u0ab5\u0abe\u0ab0"
+ ],
+ "ERANAMES": [
+ "\u0a88\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8 \u0aaa\u0ac2\u0ab0\u0acd\u0ab5\u0ac7",
+ "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8"
+ ],
+ "ERAS": [
+ "\u0a88\u0ab8\u0ac1\u0aa8\u0abe \u0a9c\u0aa8\u0acd\u0aae \u0aaa\u0ab9\u0ac7\u0ab2\u0abe",
+ "\u0a87\u0ab8\u0ab5\u0ac0\u0ab8\u0aa8"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1\u0a86\u0ab0\u0ac0",
+ "\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1\u0a86\u0ab0\u0ac0",
+ "\u0aae\u0abe\u0ab0\u0acd\u0a9a",
+ "\u0a8f\u0aaa\u0acd\u0ab0\u0abf\u0ab2",
+ "\u0aae\u0ac7",
+ "\u0a9c\u0ac2\u0aa8",
+ "\u0a9c\u0ac1\u0ab2\u0abe\u0a88",
+ "\u0a91\u0a97\u0ab8\u0acd\u0a9f",
+ "\u0ab8\u0aaa\u0acd\u0a9f\u0ac7\u0aae\u0acd\u0aac\u0ab0",
+ "\u0a91\u0a95\u0acd\u0a9f\u0acb\u0aac\u0ab0",
+ "\u0aa8\u0ab5\u0ac7\u0aae\u0acd\u0aac\u0ab0",
+ "\u0aa1\u0abf\u0ab8\u0ac7\u0aae\u0acd\u0aac\u0ab0"
+ ],
+ "SHORTDAY": [
+ "\u0ab0\u0ab5\u0abf",
+ "\u0ab8\u0acb\u0aae",
+ "\u0aae\u0a82\u0a97\u0ab3",
+ "\u0aac\u0ac1\u0aa7",
+ "\u0a97\u0ac1\u0ab0\u0ac1",
+ "\u0ab6\u0ac1\u0a95\u0acd\u0ab0",
+ "\u0ab6\u0aa8\u0abf"
+ ],
+ "SHORTMONTH": [
+ "\u0a9c\u0abe\u0aa8\u0acd\u0aaf\u0ac1",
+ "\u0aab\u0ac7\u0aac\u0acd\u0ab0\u0ac1",
+ "\u0aae\u0abe\u0ab0\u0acd\u0a9a",
+ "\u0a8f\u0aaa\u0acd\u0ab0\u0abf\u0ab2",
+ "\u0aae\u0ac7",
+ "\u0a9c\u0ac2\u0aa8",
+ "\u0a9c\u0ac1\u0ab2\u0abe\u0a88",
+ "\u0a91\u0a97",
+ "\u0ab8\u0aaa\u0acd\u0a9f\u0ac7",
+ "\u0a91\u0a95\u0acd\u0a9f\u0acb",
+ "\u0aa8\u0ab5\u0ac7",
+ "\u0aa1\u0abf\u0ab8\u0ac7"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y hh:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "hh:mm:ss a",
+ "short": "d/M/yy hh:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz-ke.js
new file mode 100644
index 00000000..675efe95
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Ma/Mo",
+ "Mambia/Mog"
+ ],
+ "DAY": [
+ "Chumapiri",
+ "Chumatato",
+ "Chumaine",
+ "Chumatano",
+ "Aramisi",
+ "Ichuma",
+ "Esabato"
+ ],
+ "ERANAMES": [
+ "Yeso ataiborwa",
+ "Yeso kaiboirwe"
+ ],
+ "ERAS": [
+ "YA",
+ "YK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Chanuari",
+ "Feburari",
+ "Machi",
+ "Apiriri",
+ "Mei",
+ "Juni",
+ "Chulai",
+ "Agosti",
+ "Septemba",
+ "Okitoba",
+ "Nobemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Cpr",
+ "Ctt",
+ "Cmn",
+ "Cmt",
+ "Ars",
+ "Icm",
+ "Est"
+ ],
+ "SHORTMONTH": [
+ "Can",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Cul",
+ "Agt",
+ "Sep",
+ "Okt",
+ "Nob",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "guz-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz.js
new file mode 100644
index 00000000..9ce1ce3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_guz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Ma/Mo",
+ "Mambia/Mog"
+ ],
+ "DAY": [
+ "Chumapiri",
+ "Chumatato",
+ "Chumaine",
+ "Chumatano",
+ "Aramisi",
+ "Ichuma",
+ "Esabato"
+ ],
+ "ERANAMES": [
+ "Yeso ataiborwa",
+ "Yeso kaiboirwe"
+ ],
+ "ERAS": [
+ "YA",
+ "YK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Chanuari",
+ "Feburari",
+ "Machi",
+ "Apiriri",
+ "Mei",
+ "Juni",
+ "Chulai",
+ "Agosti",
+ "Septemba",
+ "Okitoba",
+ "Nobemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Cpr",
+ "Ctt",
+ "Cmn",
+ "Cmt",
+ "Ars",
+ "Icm",
+ "Est"
+ ],
+ "SHORTMONTH": [
+ "Can",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Cul",
+ "Agt",
+ "Sep",
+ "Okt",
+ "Nob",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "guz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv-im.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv-im.js
new file mode 100644
index 00000000..aca51df1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv-im.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Jedoonee",
+ "Jelhein",
+ "Jemayrt",
+ "Jercean",
+ "Jerdein",
+ "Jeheiney",
+ "Jesarn"
+ ],
+ "ERANAMES": [
+ "RC",
+ "AD"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jerrey-geuree",
+ "Toshiaght-arree",
+ "Mayrnt",
+ "Averil",
+ "Boaldyn",
+ "Mean-souree",
+ "Jerrey-souree",
+ "Luanistyn",
+ "Mean-fouyir",
+ "Jerrey-fouyir",
+ "Mee Houney",
+ "Mee ny Nollick"
+ ],
+ "SHORTDAY": [
+ "Jed",
+ "Jel",
+ "Jem",
+ "Jerc",
+ "Jerd",
+ "Jeh",
+ "Jes"
+ ],
+ "SHORTMONTH": [
+ "J-guer",
+ "T-arree",
+ "Mayrnt",
+ "Avrril",
+ "Boaldyn",
+ "M-souree",
+ "J-souree",
+ "Luanistyn",
+ "M-fouyir",
+ "J-fouyir",
+ "M.Houney",
+ "M.Nollick"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "MMM dd, y HH:mm:ss",
+ "mediumDate": "MMM dd, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gv-im",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv.js
new file mode 100644
index 00000000..0f99b6a4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_gv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Jedoonee",
+ "Jelhein",
+ "Jemayrt",
+ "Jercean",
+ "Jerdein",
+ "Jeheiney",
+ "Jesarn"
+ ],
+ "ERANAMES": [
+ "RC",
+ "AD"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jerrey-geuree",
+ "Toshiaght-arree",
+ "Mayrnt",
+ "Averil",
+ "Boaldyn",
+ "Mean-souree",
+ "Jerrey-souree",
+ "Luanistyn",
+ "Mean-fouyir",
+ "Jerrey-fouyir",
+ "Mee Houney",
+ "Mee ny Nollick"
+ ],
+ "SHORTDAY": [
+ "Jed",
+ "Jel",
+ "Jem",
+ "Jerc",
+ "Jerd",
+ "Jeh",
+ "Jes"
+ ],
+ "SHORTMONTH": [
+ "J-guer",
+ "T-arree",
+ "Mayrnt",
+ "Avrril",
+ "Boaldyn",
+ "M-souree",
+ "J-souree",
+ "Luanistyn",
+ "M-fouyir",
+ "J-fouyir",
+ "M.Houney",
+ "M.Nollick"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "MMM dd, y HH:mm:ss",
+ "mediumDate": "MMM dd, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "gv",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-gh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-gh.js
new file mode 100644
index 00000000..c5209311
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-gh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lahadi",
+ "Litinin",
+ "Talata",
+ "Laraba",
+ "Alhamis",
+ "Jumma\u02bca",
+ "Asabar"
+ ],
+ "ERANAMES": [
+ "Kafin haihuwar annab",
+ "Bayan haihuwar annab"
+ ],
+ "ERAS": [
+ "KHAI",
+ "BHAI"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janairu",
+ "Faburairu",
+ "Maris",
+ "Afirilu",
+ "Mayu",
+ "Yuni",
+ "Yuli",
+ "Agusta",
+ "Satumba",
+ "Oktoba",
+ "Nuwamba",
+ "Disamba"
+ ],
+ "SHORTDAY": [
+ "Lh",
+ "Li",
+ "Ta",
+ "Lr",
+ "Al",
+ "Ju",
+ "As"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fab",
+ "Mar",
+ "Afi",
+ "May",
+ "Yun",
+ "Yul",
+ "Agu",
+ "Sat",
+ "Okt",
+ "Nuw",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GHS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ha-latn-gh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ne.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ne.js
new file mode 100644
index 00000000..f4b280c5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ne.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lahadi",
+ "Litinin",
+ "Talata",
+ "Laraba",
+ "Alhamis",
+ "Jumma\u02bca",
+ "Asabar"
+ ],
+ "ERANAMES": [
+ "Kafin haihuwar annab",
+ "Bayan haihuwar annab"
+ ],
+ "ERAS": [
+ "KHAI",
+ "BHAI"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janairu",
+ "Faburairu",
+ "Maris",
+ "Afirilu",
+ "Mayu",
+ "Yuni",
+ "Yuli",
+ "Agusta",
+ "Satumba",
+ "Oktoba",
+ "Nuwamba",
+ "Disamba"
+ ],
+ "SHORTDAY": [
+ "Lh",
+ "Li",
+ "Ta",
+ "Lr",
+ "Al",
+ "Ju",
+ "As"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fab",
+ "Mar",
+ "Afi",
+ "May",
+ "Yun",
+ "Yul",
+ "Agu",
+ "Sat",
+ "Okt",
+ "Nuw",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ha-latn-ne",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ng.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ng.js
new file mode 100644
index 00000000..81af53eb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn-ng.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lahadi",
+ "Litinin",
+ "Talata",
+ "Laraba",
+ "Alhamis",
+ "Jumma\u02bca",
+ "Asabar"
+ ],
+ "ERANAMES": [
+ "Kafin haihuwar annab",
+ "Bayan haihuwar annab"
+ ],
+ "ERAS": [
+ "KHAI",
+ "BHAI"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janairu",
+ "Faburairu",
+ "Maris",
+ "Afirilu",
+ "Mayu",
+ "Yuni",
+ "Yuli",
+ "Agusta",
+ "Satumba",
+ "Oktoba",
+ "Nuwamba",
+ "Disamba"
+ ],
+ "SHORTDAY": [
+ "Lh",
+ "Li",
+ "Ta",
+ "Lr",
+ "Al",
+ "Ju",
+ "As"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fab",
+ "Mar",
+ "Afi",
+ "May",
+ "Yun",
+ "Yul",
+ "Agu",
+ "Sat",
+ "Okt",
+ "Nuw",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ha-latn-ng",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn.js
new file mode 100644
index 00000000..615939cd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lahadi",
+ "Litinin",
+ "Talata",
+ "Laraba",
+ "Alhamis",
+ "Jumma\u02bca",
+ "Asabar"
+ ],
+ "ERANAMES": [
+ "Kafin haihuwar annab",
+ "Bayan haihuwar annab"
+ ],
+ "ERAS": [
+ "KHAI",
+ "BHAI"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janairu",
+ "Faburairu",
+ "Maris",
+ "Afirilu",
+ "Mayu",
+ "Yuni",
+ "Yuli",
+ "Agusta",
+ "Satumba",
+ "Oktoba",
+ "Nuwamba",
+ "Disamba"
+ ],
+ "SHORTDAY": [
+ "Lh",
+ "Li",
+ "Ta",
+ "Lr",
+ "Al",
+ "Ju",
+ "As"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fab",
+ "Mar",
+ "Afi",
+ "May",
+ "Yun",
+ "Yul",
+ "Agu",
+ "Sat",
+ "Okt",
+ "Nuw",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ha-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha.js
new file mode 100644
index 00000000..0f36507e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ha.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lahadi",
+ "Litinin",
+ "Talata",
+ "Laraba",
+ "Alhamis",
+ "Jumma\u02bca",
+ "Asabar"
+ ],
+ "ERANAMES": [
+ "Kafin haihuwar annab",
+ "Bayan haihuwar annab"
+ ],
+ "ERAS": [
+ "KHAI",
+ "BHAI"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janairu",
+ "Faburairu",
+ "Maris",
+ "Afirilu",
+ "Mayu",
+ "Yuni",
+ "Yuli",
+ "Agusta",
+ "Satumba",
+ "Oktoba",
+ "Nuwamba",
+ "Disamba"
+ ],
+ "SHORTDAY": [
+ "Lh",
+ "Li",
+ "Ta",
+ "Lr",
+ "Al",
+ "Ju",
+ "As"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fab",
+ "Mar",
+ "Afi",
+ "May",
+ "Yun",
+ "Yul",
+ "Agu",
+ "Sat",
+ "Okt",
+ "Nuw",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ha",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw-us.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw-us.js
new file mode 100644
index 00000000..4091590e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw-us.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "L\u0101pule",
+ "Po\u02bbakahi",
+ "Po\u02bbalua",
+ "Po\u02bbakolu",
+ "Po\u02bbah\u0101",
+ "Po\u02bbalima",
+ "Po\u02bbaono"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ianuali",
+ "Pepeluali",
+ "Malaki",
+ "\u02bbApelila",
+ "Mei",
+ "Iune",
+ "Iulai",
+ "\u02bbAukake",
+ "Kepakemapa",
+ "\u02bbOkakopa",
+ "Nowemapa",
+ "Kekemapa"
+ ],
+ "SHORTDAY": [
+ "LP",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "P5",
+ "P6"
+ ],
+ "SHORTMONTH": [
+ "Ian.",
+ "Pep.",
+ "Mal.",
+ "\u02bbAp.",
+ "Mei",
+ "Iun.",
+ "Iul.",
+ "\u02bbAu.",
+ "Kep.",
+ "\u02bbOk.",
+ "Now.",
+ "Kek."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "haw-us",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw.js
new file mode 100644
index 00000000..a1253a4a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_haw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "L\u0101pule",
+ "Po\u02bbakahi",
+ "Po\u02bbalua",
+ "Po\u02bbakolu",
+ "Po\u02bbah\u0101",
+ "Po\u02bbalima",
+ "Po\u02bbaono"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ianuali",
+ "Pepeluali",
+ "Malaki",
+ "\u02bbApelila",
+ "Mei",
+ "Iune",
+ "Iulai",
+ "\u02bbAukake",
+ "Kepakemapa",
+ "\u02bbOkakopa",
+ "Nowemapa",
+ "Kekemapa"
+ ],
+ "SHORTDAY": [
+ "LP",
+ "P1",
+ "P2",
+ "P3",
+ "P4",
+ "P5",
+ "P6"
+ ],
+ "SHORTMONTH": [
+ "Ian.",
+ "Pep.",
+ "Mal.",
+ "\u02bbAp.",
+ "Mei",
+ "Iun.",
+ "Iul.",
+ "\u02bbAu.",
+ "Kep.",
+ "\u02bbOk.",
+ "Now.",
+ "Kek."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "haw",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he-il.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he-il.js
new file mode 100644
index 00000000..7a05b986
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he-il.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e6",
+ "\u05d0\u05d7\u05d4\u05f4\u05e6"
+ ],
+ "DAY": [
+ "\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df",
+ "\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9",
+ "\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea"
+ ],
+ "ERANAMES": [
+ "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "ERAS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u05d9\u05e0\u05d5\u05d0\u05e8",
+ "\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05d9\u05dc",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e4\u05d8\u05de\u05d1\u05e8",
+ "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8",
+ "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8",
+ "\u05d3\u05e6\u05de\u05d1\u05e8"
+ ],
+ "SHORTDAY": [
+ "\u05d9\u05d5\u05dd \u05d0\u05f3",
+ "\u05d9\u05d5\u05dd \u05d1\u05f3",
+ "\u05d9\u05d5\u05dd \u05d2\u05f3",
+ "\u05d9\u05d5\u05dd \u05d3\u05f3",
+ "\u05d9\u05d5\u05dd \u05d4\u05f3",
+ "\u05d9\u05d5\u05dd \u05d5\u05f3",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "SHORTMONTH": [
+ "\u05d9\u05e0\u05d5\u05f3",
+ "\u05e4\u05d1\u05e8\u05f3",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05f3",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05f3",
+ "\u05e1\u05e4\u05d8\u05f3",
+ "\u05d0\u05d5\u05e7\u05f3",
+ "\u05e0\u05d5\u05d1\u05f3",
+ "\u05d3\u05e6\u05de\u05f3"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d \u05d1MMMM y",
+ "longDate": "d \u05d1MMMM y",
+ "medium": "d \u05d1MMM y H:mm:ss",
+ "mediumDate": "d \u05d1MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.y H:mm",
+ "shortDate": "d.M.y",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20aa",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "he-il",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i == 2 && vf.v == 0) { return PLURAL_CATEGORY.TWO; } if (vf.v == 0 && (n < 0 || n > 10) && n % 10 == 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he.js
new file mode 100644
index 00000000..2ef1d3c2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_he.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e6",
+ "\u05d0\u05d7\u05d4\u05f4\u05e6"
+ ],
+ "DAY": [
+ "\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df",
+ "\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9",
+ "\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea"
+ ],
+ "ERANAMES": [
+ "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "ERAS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u05d9\u05e0\u05d5\u05d0\u05e8",
+ "\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05d9\u05dc",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e4\u05d8\u05de\u05d1\u05e8",
+ "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8",
+ "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8",
+ "\u05d3\u05e6\u05de\u05d1\u05e8"
+ ],
+ "SHORTDAY": [
+ "\u05d9\u05d5\u05dd \u05d0\u05f3",
+ "\u05d9\u05d5\u05dd \u05d1\u05f3",
+ "\u05d9\u05d5\u05dd \u05d2\u05f3",
+ "\u05d9\u05d5\u05dd \u05d3\u05f3",
+ "\u05d9\u05d5\u05dd \u05d4\u05f3",
+ "\u05d9\u05d5\u05dd \u05d5\u05f3",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "SHORTMONTH": [
+ "\u05d9\u05e0\u05d5\u05f3",
+ "\u05e4\u05d1\u05e8\u05f3",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05f3",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05f3",
+ "\u05e1\u05e4\u05d8\u05f3",
+ "\u05d0\u05d5\u05e7\u05f3",
+ "\u05e0\u05d5\u05d1\u05f3",
+ "\u05d3\u05e6\u05de\u05f3"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d \u05d1MMMM y",
+ "longDate": "d \u05d1MMMM y",
+ "medium": "d \u05d1MMM y H:mm:ss",
+ "mediumDate": "d \u05d1MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.y H:mm",
+ "shortDate": "d.M.y",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20aa",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "he",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i == 2 && vf.v == 0) { return PLURAL_CATEGORY.TWO; } if (vf.v == 0 && (n < 0 || n > 10) && n % 10 == 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi-in.js
new file mode 100644
index 00000000..febae399
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u0930\u0935\u093f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0932\u0935\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u0935\u0940 \u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u094d\u0935\u0940"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u093c\u0930\u0935\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u0948\u0932",
+ "\u092e\u0908",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u0924",
+ "\u0938\u093f\u0924\u0902\u092c\u0930",
+ "\u0905\u0915\u094d\u0924\u0942\u092c\u0930",
+ "\u0928\u0935\u0902\u092c\u0930",
+ "\u0926\u093f\u0938\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0932",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u0928\u0970",
+ "\u092b\u093c\u0930\u0970",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u0948\u0932",
+ "\u092e\u0908",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0970",
+ "\u0905\u0917\u0970",
+ "\u0938\u093f\u0924\u0970",
+ "\u0905\u0915\u094d\u0924\u0942\u0970",
+ "\u0928\u0935\u0970",
+ "\u0926\u093f\u0938\u0970"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd/MM/y h:mm:ss a",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "hi-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi.js
new file mode 100644
index 00000000..e5c34123
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hi.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u0930\u0935\u093f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0932\u0935\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u0935\u0940 \u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e-\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u094d\u0935\u0940"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u093c\u0930\u0935\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u0948\u0932",
+ "\u092e\u0908",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u0924",
+ "\u0938\u093f\u0924\u0902\u092c\u0930",
+ "\u0905\u0915\u094d\u0924\u0942\u092c\u0930",
+ "\u0928\u0935\u0902\u092c\u0930",
+ "\u0926\u093f\u0938\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0932",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u0928\u0970",
+ "\u092b\u093c\u0930\u0970",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u0948\u0932",
+ "\u092e\u0908",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0970",
+ "\u0905\u0917\u0970",
+ "\u0938\u093f\u0924\u0970",
+ "\u0905\u0915\u094d\u0924\u0942\u0970",
+ "\u0928\u0935\u0970",
+ "\u0926\u093f\u0938\u0970"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd/MM/y h:mm:ss a",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "hi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-ba.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-ba.js
new file mode 100644
index 00000000..cb70c76e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-ba.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije Krista",
+ "Poslije Krista"
+ ],
+ "ERAS": [
+ "pr. Kr.",
+ "p. Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sije\u010dnja",
+ "velja\u010de",
+ "o\u017eujka",
+ "travnja",
+ "svibnja",
+ "lipnja",
+ "srpnja",
+ "kolovoza",
+ "rujna",
+ "listopada",
+ "studenoga",
+ "prosinca"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "sij",
+ "velj",
+ "o\u017eu",
+ "tra",
+ "svi",
+ "lip",
+ "srp",
+ "kol",
+ "ruj",
+ "lis",
+ "stu",
+ "pro"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y.",
+ "longDate": "d. MMMM y.",
+ "medium": "d. MMM y. HH:mm:ss",
+ "mediumDate": "d. MMM y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y. HH:mm",
+ "shortDate": "dd.MM.y.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hr-ba",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-hr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-hr.js
new file mode 100644
index 00000000..248734f6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr-hr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije Krista",
+ "Poslije Krista"
+ ],
+ "ERAS": [
+ "pr. Kr.",
+ "p. Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sije\u010dnja",
+ "velja\u010de",
+ "o\u017eujka",
+ "travnja",
+ "svibnja",
+ "lipnja",
+ "srpnja",
+ "kolovoza",
+ "rujna",
+ "listopada",
+ "studenoga",
+ "prosinca"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "sij",
+ "velj",
+ "o\u017eu",
+ "tra",
+ "svi",
+ "lip",
+ "srp",
+ "kol",
+ "ruj",
+ "lis",
+ "stu",
+ "pro"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y.",
+ "longDate": "d. MMMM y.",
+ "medium": "d. MMM y. HH:mm:ss",
+ "mediumDate": "d. MMM y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y. HH:mm",
+ "shortDate": "dd.MM.y.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hr-hr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr.js
new file mode 100644
index 00000000..4f6f1c14
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "nedjelja",
+ "ponedjeljak",
+ "utorak",
+ "srijeda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Prije Krista",
+ "Poslije Krista"
+ ],
+ "ERAS": [
+ "pr. Kr.",
+ "p. Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sije\u010dnja",
+ "velja\u010de",
+ "o\u017eujka",
+ "travnja",
+ "svibnja",
+ "lipnja",
+ "srpnja",
+ "kolovoza",
+ "rujna",
+ "listopada",
+ "studenoga",
+ "prosinca"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sri",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "sij",
+ "velj",
+ "o\u017eu",
+ "tra",
+ "svi",
+ "lip",
+ "srp",
+ "kol",
+ "ruj",
+ "lis",
+ "stu",
+ "pro"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y.",
+ "longDate": "d. MMMM y.",
+ "medium": "d. MMM y. HH:mm:ss",
+ "mediumDate": "d. MMM y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y. HH:mm",
+ "shortDate": "dd.MM.y.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb-de.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb-de.js
new file mode 100644
index 00000000..f432ed94
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb-de.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopo\u0142dnja",
+ "popo\u0142dnju"
+ ],
+ "DAY": [
+ "njed\u017aela",
+ "p\u00f3nd\u017aela",
+ "wutora",
+ "srjeda",
+ "\u0161tw\u00f3rtk",
+ "pjatk",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u0159ed Chrystowym narod\u017aenjom",
+ "po Chrystowym narod\u017aenju"
+ ],
+ "ERAS": [
+ "p\u0159.Chr.n.",
+ "po Chr.n."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januara",
+ "februara",
+ "m\u011brca",
+ "apryla",
+ "meje",
+ "junija",
+ "julija",
+ "awgusta",
+ "septembra",
+ "oktobra",
+ "nowembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "nje",
+ "p\u00f3n",
+ "wut",
+ "srj",
+ "\u0161tw",
+ "pja",
+ "sob"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "m\u011br.",
+ "apr.",
+ "mej.",
+ "jun.",
+ "jul.",
+ "awg.",
+ "sep.",
+ "okt.",
+ "now.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H:mm:ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.yy H:mm 'hod\u017a'.",
+ "shortDate": "d.M.yy",
+ "shortTime": "H:mm 'hod\u017a'."
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hsb-de",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb.js
new file mode 100644
index 00000000..c11ebc78
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hsb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopo\u0142dnja",
+ "popo\u0142dnju"
+ ],
+ "DAY": [
+ "njed\u017aela",
+ "p\u00f3nd\u017aela",
+ "wutora",
+ "srjeda",
+ "\u0161tw\u00f3rtk",
+ "pjatk",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p\u0159ed Chrystowym narod\u017aenjom",
+ "po Chrystowym narod\u017aenju"
+ ],
+ "ERAS": [
+ "p\u0159.Chr.n.",
+ "po Chr.n."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januara",
+ "februara",
+ "m\u011brca",
+ "apryla",
+ "meje",
+ "junija",
+ "julija",
+ "awgusta",
+ "septembra",
+ "oktobra",
+ "nowembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "nje",
+ "p\u00f3n",
+ "wut",
+ "srj",
+ "\u0161tw",
+ "pja",
+ "sob"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "m\u011br.",
+ "apr.",
+ "mej.",
+ "jun.",
+ "jul.",
+ "awg.",
+ "sep.",
+ "okt.",
+ "now.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d.M.y H:mm:ss",
+ "mediumDate": "d.M.y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.yy H:mm 'hod\u017a'.",
+ "shortDate": "d.M.yy",
+ "shortTime": "H:mm 'hod\u017a'."
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hsb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu-hu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu-hu.js
new file mode 100644
index 00000000..10a3bbc5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu-hu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "de.",
+ "du."
+ ],
+ "DAY": [
+ "vas\u00e1rnap",
+ "h\u00e9tf\u0151",
+ "kedd",
+ "szerda",
+ "cs\u00fct\u00f6rt\u00f6k",
+ "p\u00e9ntek",
+ "szombat"
+ ],
+ "ERANAMES": [
+ "id\u0151sz\u00e1m\u00edt\u00e1sunk el\u0151tt",
+ "id\u0151sz\u00e1m\u00edt\u00e1sunk szerint"
+ ],
+ "ERAS": [
+ "i. e.",
+ "i. sz."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janu\u00e1r",
+ "febru\u00e1r",
+ "m\u00e1rcius",
+ "\u00e1prilis",
+ "m\u00e1jus",
+ "j\u00fanius",
+ "j\u00falius",
+ "augusztus",
+ "szeptember",
+ "okt\u00f3ber",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "V",
+ "H",
+ "K",
+ "Sze",
+ "Cs",
+ "P",
+ "Szo"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "febr.",
+ "m\u00e1rc.",
+ "\u00e1pr.",
+ "m\u00e1j.",
+ "j\u00fan.",
+ "j\u00fal.",
+ "aug.",
+ "szept.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y. MMMM d., EEEE",
+ "longDate": "y. MMMM d.",
+ "medium": "y. MMM d. H:mm:ss",
+ "mediumDate": "y. MMM d.",
+ "mediumTime": "H:mm:ss",
+ "short": "y. MM. dd. H:mm",
+ "shortDate": "y. MM. dd.",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ft",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hu-hu",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu.js
new file mode 100644
index 00000000..1e61f045
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "de.",
+ "du."
+ ],
+ "DAY": [
+ "vas\u00e1rnap",
+ "h\u00e9tf\u0151",
+ "kedd",
+ "szerda",
+ "cs\u00fct\u00f6rt\u00f6k",
+ "p\u00e9ntek",
+ "szombat"
+ ],
+ "ERANAMES": [
+ "id\u0151sz\u00e1m\u00edt\u00e1sunk el\u0151tt",
+ "id\u0151sz\u00e1m\u00edt\u00e1sunk szerint"
+ ],
+ "ERAS": [
+ "i. e.",
+ "i. sz."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janu\u00e1r",
+ "febru\u00e1r",
+ "m\u00e1rcius",
+ "\u00e1prilis",
+ "m\u00e1jus",
+ "j\u00fanius",
+ "j\u00falius",
+ "augusztus",
+ "szeptember",
+ "okt\u00f3ber",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "V",
+ "H",
+ "K",
+ "Sze",
+ "Cs",
+ "P",
+ "Szo"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "febr.",
+ "m\u00e1rc.",
+ "\u00e1pr.",
+ "m\u00e1j.",
+ "j\u00fan.",
+ "j\u00fal.",
+ "aug.",
+ "szept.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y. MMMM d., EEEE",
+ "longDate": "y. MMMM d.",
+ "medium": "y. MMM d. H:mm:ss",
+ "mediumDate": "y. MMM d.",
+ "mediumTime": "H:mm:ss",
+ "short": "y. MM. dd. H:mm",
+ "shortDate": "y. MM. dd.",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ft",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hu",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy-am.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy-am.js
new file mode 100644
index 00000000..17afd276
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy-am.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u056f\u0565\u057d\u0585\u0580\u056b\u0581 \u0561\u057c\u0561\u057b",
+ "\u056f\u0565\u057d\u0585\u0580\u056b\u0581 \u0570\u0565\u057f\u0578"
+ ],
+ "DAY": [
+ "\u056f\u056b\u0580\u0561\u056f\u056b",
+ "\u0565\u0580\u056f\u0578\u0582\u0577\u0561\u0562\u0569\u056b",
+ "\u0565\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b",
+ "\u0579\u0578\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b",
+ "\u0570\u056b\u0576\u0563\u0577\u0561\u0562\u0569\u056b",
+ "\u0578\u0582\u0580\u0562\u0561\u0569",
+ "\u0577\u0561\u0562\u0561\u0569"
+ ],
+ "ERANAMES": [
+ "\u0574.\u0569.\u0561.",
+ "\u0574.\u0569."
+ ],
+ "ERAS": [
+ "\u0574.\u0569.\u0561.",
+ "\u0574.\u0569."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0570\u0578\u0582\u0576\u057e\u0561\u0580\u056b",
+ "\u0583\u0565\u057f\u0580\u057e\u0561\u0580\u056b",
+ "\u0574\u0561\u0580\u057f\u056b",
+ "\u0561\u057a\u0580\u056b\u056c\u056b",
+ "\u0574\u0561\u0575\u056b\u057d\u056b",
+ "\u0570\u0578\u0582\u0576\u056b\u057d\u056b",
+ "\u0570\u0578\u0582\u056c\u056b\u057d\u056b",
+ "\u0585\u0563\u0578\u057d\u057f\u0578\u057d\u056b",
+ "\u057d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0570\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0576\u0578\u0575\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0564\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b"
+ ],
+ "SHORTDAY": [
+ "\u056f\u056b\u0580",
+ "\u0565\u0580\u056f",
+ "\u0565\u0580\u0584",
+ "\u0579\u0580\u0584",
+ "\u0570\u0576\u0563",
+ "\u0578\u0582\u0580",
+ "\u0577\u0562\u0569"
+ ],
+ "SHORTMONTH": [
+ "\u0570\u0576\u057e",
+ "\u0583\u057f\u057e",
+ "\u0574\u0580\u057f",
+ "\u0561\u057a\u0580",
+ "\u0574\u0575\u057d",
+ "\u0570\u0576\u057d",
+ "\u0570\u056c\u057d",
+ "\u0585\u0563\u057d",
+ "\u057d\u0565\u057a",
+ "\u0570\u0578\u056f",
+ "\u0576\u0578\u0575",
+ "\u0564\u0565\u056f"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u0569. MMMM d, EEEE",
+ "longDate": "dd MMMM, y\u0569.",
+ "medium": "dd MMM, y\u0569. H:mm:ss",
+ "mediumDate": "dd MMM, y\u0569.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Dram",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hy-am",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy.js
new file mode 100644
index 00000000..c54fe770
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_hy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u056f\u0565\u057d\u0585\u0580\u056b\u0581 \u0561\u057c\u0561\u057b",
+ "\u056f\u0565\u057d\u0585\u0580\u056b\u0581 \u0570\u0565\u057f\u0578"
+ ],
+ "DAY": [
+ "\u056f\u056b\u0580\u0561\u056f\u056b",
+ "\u0565\u0580\u056f\u0578\u0582\u0577\u0561\u0562\u0569\u056b",
+ "\u0565\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b",
+ "\u0579\u0578\u0580\u0565\u0584\u0577\u0561\u0562\u0569\u056b",
+ "\u0570\u056b\u0576\u0563\u0577\u0561\u0562\u0569\u056b",
+ "\u0578\u0582\u0580\u0562\u0561\u0569",
+ "\u0577\u0561\u0562\u0561\u0569"
+ ],
+ "ERANAMES": [
+ "\u0574.\u0569.\u0561.",
+ "\u0574.\u0569."
+ ],
+ "ERAS": [
+ "\u0574.\u0569.\u0561.",
+ "\u0574.\u0569."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0570\u0578\u0582\u0576\u057e\u0561\u0580\u056b",
+ "\u0583\u0565\u057f\u0580\u057e\u0561\u0580\u056b",
+ "\u0574\u0561\u0580\u057f\u056b",
+ "\u0561\u057a\u0580\u056b\u056c\u056b",
+ "\u0574\u0561\u0575\u056b\u057d\u056b",
+ "\u0570\u0578\u0582\u0576\u056b\u057d\u056b",
+ "\u0570\u0578\u0582\u056c\u056b\u057d\u056b",
+ "\u0585\u0563\u0578\u057d\u057f\u0578\u057d\u056b",
+ "\u057d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0570\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0576\u0578\u0575\u0565\u0574\u0562\u0565\u0580\u056b",
+ "\u0564\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580\u056b"
+ ],
+ "SHORTDAY": [
+ "\u056f\u056b\u0580",
+ "\u0565\u0580\u056f",
+ "\u0565\u0580\u0584",
+ "\u0579\u0580\u0584",
+ "\u0570\u0576\u0563",
+ "\u0578\u0582\u0580",
+ "\u0577\u0562\u0569"
+ ],
+ "SHORTMONTH": [
+ "\u0570\u0576\u057e",
+ "\u0583\u057f\u057e",
+ "\u0574\u0580\u057f",
+ "\u0561\u057a\u0580",
+ "\u0574\u0575\u057d",
+ "\u0570\u0576\u057d",
+ "\u0570\u056c\u057d",
+ "\u0585\u0563\u057d",
+ "\u057d\u0565\u057a",
+ "\u0570\u0578\u056f",
+ "\u0576\u0578\u0575",
+ "\u0564\u0565\u056f"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u0569. MMMM d, EEEE",
+ "longDate": "dd MMMM, y\u0569.",
+ "medium": "dd MMM, y\u0569. H:mm:ss",
+ "mediumDate": "dd MMM, y\u0569.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Dram",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "hy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || i == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia-fr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia-fr.js
new file mode 100644
index 00000000..f7b636b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia-fr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "dominica",
+ "lunedi",
+ "martedi",
+ "mercuridi",
+ "jovedi",
+ "venerdi",
+ "sabbato"
+ ],
+ "ERANAMES": [
+ "ante Christo",
+ "post Christo"
+ ],
+ "ERAS": [
+ "a.Chr.",
+ "p.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januario",
+ "februario",
+ "martio",
+ "april",
+ "maio",
+ "junio",
+ "julio",
+ "augusto",
+ "septembre",
+ "octobre",
+ "novembre",
+ "decembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "jov",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "mai",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "oct",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ia-fr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia.js
new file mode 100644
index 00000000..38ead226
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ia.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "dominica",
+ "lunedi",
+ "martedi",
+ "mercuridi",
+ "jovedi",
+ "venerdi",
+ "sabbato"
+ ],
+ "ERANAMES": [
+ "ante Christo",
+ "post Christo"
+ ],
+ "ERAS": [
+ "a.Chr.",
+ "p.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januario",
+ "februario",
+ "martio",
+ "april",
+ "maio",
+ "junio",
+ "julio",
+ "augusto",
+ "septembre",
+ "octobre",
+ "novembre",
+ "decembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "jov",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "mai",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "oct",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ia",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id-id.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id-id.js
new file mode 100644
index 00000000..8324dce6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id-id.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Minggu",
+ "Senin",
+ "Selasa",
+ "Rabu",
+ "Kamis",
+ "Jumat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "Sebelum Masehi",
+ "M"
+ ],
+ "ERAS": [
+ "SM",
+ "M"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Maret",
+ "April",
+ "Mei",
+ "Juni",
+ "Juli",
+ "Agustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "Min",
+ "Sen",
+ "Sel",
+ "Rab",
+ "Kam",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Agt",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH.mm.ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/yy HH.mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rp",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "id-id",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id.js
new file mode 100644
index 00000000..b91f32dd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_id.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Minggu",
+ "Senin",
+ "Selasa",
+ "Rabu",
+ "Kamis",
+ "Jumat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "Sebelum Masehi",
+ "M"
+ ],
+ "ERAS": [
+ "SM",
+ "M"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Maret",
+ "April",
+ "Mei",
+ "Juni",
+ "Juli",
+ "Agustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "Min",
+ "Sen",
+ "Sel",
+ "Rab",
+ "Kam",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Agt",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH.mm.ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/yy HH.mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rp",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "id",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig-ng.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig-ng.js
new file mode 100644
index 00000000..0515635b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig-ng.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "A.M.",
+ "P.M."
+ ],
+ "DAY": [
+ "Mb\u1ecds\u1ecb \u1ee4ka",
+ "M\u1ecdnde",
+ "Tiuzdee",
+ "Wenezdee",
+ "T\u1ecd\u1ecdzdee",
+ "Fra\u1ecbdee",
+ "Sat\u1ecddee"
+ ],
+ "ERANAMES": [
+ "Tupu Kristi",
+ "Af\u1ecd Kristi"
+ ],
+ "ERAS": [
+ "T.K.",
+ "A.K."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jen\u1ee5war\u1ecb",
+ "Febr\u1ee5war\u1ecb",
+ "Maach\u1ecb",
+ "Eprel",
+ "Mee",
+ "Juun",
+ "Jula\u1ecb",
+ "\u1eccg\u1ecd\u1ecdst",
+ "Septemba",
+ "\u1eccktoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "\u1ee4ka",
+ "M\u1ecdn",
+ "Tiu",
+ "Wen",
+ "T\u1ecd\u1ecd",
+ "Fra\u1ecb",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jen",
+ "Feb",
+ "Maa",
+ "Epr",
+ "Mee",
+ "Juu",
+ "Jul",
+ "\u1eccg\u1ecd",
+ "Sep",
+ "\u1ecckt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ig-ng",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig.js
new file mode 100644
index 00000000..2c9cfe40
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ig.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "A.M.",
+ "P.M."
+ ],
+ "DAY": [
+ "Mb\u1ecds\u1ecb \u1ee4ka",
+ "M\u1ecdnde",
+ "Tiuzdee",
+ "Wenezdee",
+ "T\u1ecd\u1ecdzdee",
+ "Fra\u1ecbdee",
+ "Sat\u1ecddee"
+ ],
+ "ERANAMES": [
+ "Tupu Kristi",
+ "Af\u1ecd Kristi"
+ ],
+ "ERAS": [
+ "T.K.",
+ "A.K."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jen\u1ee5war\u1ecb",
+ "Febr\u1ee5war\u1ecb",
+ "Maach\u1ecb",
+ "Eprel",
+ "Mee",
+ "Juun",
+ "Jula\u1ecb",
+ "\u1eccg\u1ecd\u1ecdst",
+ "Septemba",
+ "\u1eccktoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "\u1ee4ka",
+ "M\u1ecdn",
+ "Tiu",
+ "Wen",
+ "T\u1ecd\u1ecd",
+ "Fra\u1ecb",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jen",
+ "Feb",
+ "Maa",
+ "Epr",
+ "Mee",
+ "Juu",
+ "Jul",
+ "\u1eccg\u1ecd",
+ "Sep",
+ "\u1ecckt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ig",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii-cn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii-cn.js
new file mode 100644
index 00000000..5cddd202
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii-cn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\ua3b8\ua111",
+ "\ua06f\ua2d2"
+ ],
+ "DAY": [
+ "\ua46d\ua18f\ua44d",
+ "\ua18f\ua282\ua2cd",
+ "\ua18f\ua282\ua44d",
+ "\ua18f\ua282\ua315",
+ "\ua18f\ua282\ua1d6",
+ "\ua18f\ua282\ua26c",
+ "\ua18f\ua282\ua0d8"
+ ],
+ "ERANAMES": [
+ "\ua0c5\ua2ca\ua0bf",
+ "\ua0c5\ua2ca\ua282"
+ ],
+ "ERAS": [
+ "\ua0c5\ua2ca\ua0bf",
+ "\ua0c5\ua2ca\ua282"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\ua2cd\ua1aa",
+ "\ua44d\ua1aa",
+ "\ua315\ua1aa",
+ "\ua1d6\ua1aa",
+ "\ua26c\ua1aa",
+ "\ua0d8\ua1aa",
+ "\ua3c3\ua1aa",
+ "\ua246\ua1aa",
+ "\ua22c\ua1aa",
+ "\ua2b0\ua1aa",
+ "\ua2b0\ua2aa\ua1aa",
+ "\ua2b0\ua44b\ua1aa"
+ ],
+ "SHORTDAY": [
+ "\ua46d\ua18f",
+ "\ua18f\ua2cd",
+ "\ua18f\ua44d",
+ "\ua18f\ua315",
+ "\ua18f\ua1d6",
+ "\ua18f\ua26c",
+ "\ua18f\ua0d8"
+ ],
+ "SHORTMONTH": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ii-cn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii.js
new file mode 100644
index 00000000..2b4f22f8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ii.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\ua3b8\ua111",
+ "\ua06f\ua2d2"
+ ],
+ "DAY": [
+ "\ua46d\ua18f\ua44d",
+ "\ua18f\ua282\ua2cd",
+ "\ua18f\ua282\ua44d",
+ "\ua18f\ua282\ua315",
+ "\ua18f\ua282\ua1d6",
+ "\ua18f\ua282\ua26c",
+ "\ua18f\ua282\ua0d8"
+ ],
+ "ERANAMES": [
+ "\ua0c5\ua2ca\ua0bf",
+ "\ua0c5\ua2ca\ua282"
+ ],
+ "ERAS": [
+ "\ua0c5\ua2ca\ua0bf",
+ "\ua0c5\ua2ca\ua282"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\ua2cd\ua1aa",
+ "\ua44d\ua1aa",
+ "\ua315\ua1aa",
+ "\ua1d6\ua1aa",
+ "\ua26c\ua1aa",
+ "\ua0d8\ua1aa",
+ "\ua3c3\ua1aa",
+ "\ua246\ua1aa",
+ "\ua22c\ua1aa",
+ "\ua2b0\ua1aa",
+ "\ua2b0\ua2aa\ua1aa",
+ "\ua2b0\ua44b\ua1aa"
+ ],
+ "SHORTDAY": [
+ "\ua46d\ua18f",
+ "\ua18f\ua2cd",
+ "\ua18f\ua44d",
+ "\ua18f\ua315",
+ "\ua18f\ua1d6",
+ "\ua18f\ua26c",
+ "\ua18f\ua0d8"
+ ],
+ "SHORTMONTH": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ii",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_in.js
new file mode 100644
index 00000000..f9d523ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Minggu",
+ "Senin",
+ "Selasa",
+ "Rabu",
+ "Kamis",
+ "Jumat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "Sebelum Masehi",
+ "M"
+ ],
+ "ERAS": [
+ "SM",
+ "M"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Maret",
+ "April",
+ "Mei",
+ "Juni",
+ "Juli",
+ "Agustus",
+ "September",
+ "Oktober",
+ "November",
+ "Desember"
+ ],
+ "SHORTDAY": [
+ "Min",
+ "Sen",
+ "Sel",
+ "Rab",
+ "Kam",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Agt",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH.mm.ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd/MM/yy HH.mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rp",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "in",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is-is.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is-is.js
new file mode 100644
index 00000000..b38bd19f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is-is.js
@@ -0,0 +1,141 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+function getWT(v, f) {
+ if (f === 0) {
+ return {w: 0, t: 0};
+ }
+
+ while ((f % 10) === 0) {
+ f /= 10;
+ v--;
+ }
+
+ return {w: v, t: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "f.h.",
+ "e.h."
+ ],
+ "DAY": [
+ "sunnudagur",
+ "m\u00e1nudagur",
+ "\u00feri\u00f0judagur",
+ "mi\u00f0vikudagur",
+ "fimmtudagur",
+ "f\u00f6studagur",
+ "laugardagur"
+ ],
+ "ERANAMES": [
+ "fyrir Krist",
+ "eftir Krist"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jan\u00faar",
+ "febr\u00faar",
+ "mars",
+ "apr\u00edl",
+ "ma\u00ed",
+ "j\u00fan\u00ed",
+ "j\u00fal\u00ed",
+ "\u00e1g\u00fast",
+ "september",
+ "okt\u00f3ber",
+ "n\u00f3vember",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "sun.",
+ "m\u00e1n.",
+ "\u00feri.",
+ "mi\u00f0.",
+ "fim.",
+ "f\u00f6s.",
+ "lau."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "ma\u00ed",
+ "j\u00fan.",
+ "j\u00fal.",
+ "\u00e1g\u00fa.",
+ "sep.",
+ "okt.",
+ "n\u00f3v.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.y HH:mm",
+ "shortDate": "d.M.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "is-is",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); var wt = getWT(vf.v, vf.f); if (wt.t == 0 && i % 10 == 1 && i % 100 != 11 || wt.t != 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is.js
new file mode 100644
index 00000000..5b3ad431
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_is.js
@@ -0,0 +1,141 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+function getWT(v, f) {
+ if (f === 0) {
+ return {w: 0, t: 0};
+ }
+
+ while ((f % 10) === 0) {
+ f /= 10;
+ v--;
+ }
+
+ return {w: v, t: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "f.h.",
+ "e.h."
+ ],
+ "DAY": [
+ "sunnudagur",
+ "m\u00e1nudagur",
+ "\u00feri\u00f0judagur",
+ "mi\u00f0vikudagur",
+ "fimmtudagur",
+ "f\u00f6studagur",
+ "laugardagur"
+ ],
+ "ERANAMES": [
+ "fyrir Krist",
+ "eftir Krist"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "jan\u00faar",
+ "febr\u00faar",
+ "mars",
+ "apr\u00edl",
+ "ma\u00ed",
+ "j\u00fan\u00ed",
+ "j\u00fal\u00ed",
+ "\u00e1g\u00fast",
+ "september",
+ "okt\u00f3ber",
+ "n\u00f3vember",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "sun.",
+ "m\u00e1n.",
+ "\u00feri.",
+ "mi\u00f0.",
+ "fim.",
+ "f\u00f6s.",
+ "lau."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "ma\u00ed",
+ "j\u00fan.",
+ "j\u00fal.",
+ "\u00e1g\u00fa.",
+ "sep.",
+ "okt.",
+ "n\u00f3v.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.y HH:mm",
+ "shortDate": "d.M.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "is",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); var wt = getWT(vf.v, vf.f); if (wt.t == 0 && i % 10 == 1 && i % 100 != 11 || wt.t != 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-ch.js
new file mode 100644
index 00000000..1adbbe48
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-ch.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domenica",
+ "luned\u00ec",
+ "marted\u00ec",
+ "mercoled\u00ec",
+ "gioved\u00ec",
+ "venerd\u00ec",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "gennaio",
+ "febbraio",
+ "marzo",
+ "aprile",
+ "maggio",
+ "giugno",
+ "luglio",
+ "agosto",
+ "settembre",
+ "ottobre",
+ "novembre",
+ "dicembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "gio",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "gen",
+ "feb",
+ "mar",
+ "apr",
+ "mag",
+ "giu",
+ "lug",
+ "ago",
+ "set",
+ "ott",
+ "nov",
+ "dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d-MMM-y HH:mm:ss",
+ "mediumDate": "d-MMM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "'",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "it-ch",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-it.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-it.js
new file mode 100644
index 00000000..f02cc459
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-it.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domenica",
+ "luned\u00ec",
+ "marted\u00ec",
+ "mercoled\u00ec",
+ "gioved\u00ec",
+ "venerd\u00ec",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "gennaio",
+ "febbraio",
+ "marzo",
+ "aprile",
+ "maggio",
+ "giugno",
+ "luglio",
+ "agosto",
+ "settembre",
+ "ottobre",
+ "novembre",
+ "dicembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "gio",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "gen",
+ "feb",
+ "mar",
+ "apr",
+ "mag",
+ "giu",
+ "lug",
+ "ago",
+ "set",
+ "ott",
+ "nov",
+ "dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd MMM y HH:mm:ss",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "it-it",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-sm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-sm.js
new file mode 100644
index 00000000..5ee2ce18
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it-sm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domenica",
+ "luned\u00ec",
+ "marted\u00ec",
+ "mercoled\u00ec",
+ "gioved\u00ec",
+ "venerd\u00ec",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "gennaio",
+ "febbraio",
+ "marzo",
+ "aprile",
+ "maggio",
+ "giugno",
+ "luglio",
+ "agosto",
+ "settembre",
+ "ottobre",
+ "novembre",
+ "dicembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "gio",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "gen",
+ "feb",
+ "mar",
+ "apr",
+ "mag",
+ "giu",
+ "lug",
+ "ago",
+ "set",
+ "ott",
+ "nov",
+ "dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd MMM y HH:mm:ss",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "it-sm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it.js
new file mode 100644
index 00000000..b4b5e4e5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_it.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domenica",
+ "luned\u00ec",
+ "marted\u00ec",
+ "mercoled\u00ec",
+ "gioved\u00ec",
+ "venerd\u00ec",
+ "sabato"
+ ],
+ "ERANAMES": [
+ "a.C.",
+ "d.C."
+ ],
+ "ERAS": [
+ "aC",
+ "dC"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "gennaio",
+ "febbraio",
+ "marzo",
+ "aprile",
+ "maggio",
+ "giugno",
+ "luglio",
+ "agosto",
+ "settembre",
+ "ottobre",
+ "novembre",
+ "dicembre"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "lun",
+ "mar",
+ "mer",
+ "gio",
+ "ven",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "gen",
+ "feb",
+ "mar",
+ "apr",
+ "mag",
+ "giu",
+ "lug",
+ "ago",
+ "set",
+ "ott",
+ "nov",
+ "dic"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd MMM y HH:mm:ss",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "it",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_iw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_iw.js
new file mode 100644
index 00000000..02622c14
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_iw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e6",
+ "\u05d0\u05d7\u05d4\u05f4\u05e6"
+ ],
+ "DAY": [
+ "\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df",
+ "\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9",
+ "\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9",
+ "\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea"
+ ],
+ "ERANAMES": [
+ "\u05dc\u05e4\u05e0\u05d9 \u05d4\u05e1\u05e4\u05d9\u05e8\u05d4",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "ERAS": [
+ "\u05dc\u05e4\u05e0\u05d4\u05f4\u05e1",
+ "\u05dc\u05e1\u05e4\u05d9\u05e8\u05d4"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u05d9\u05e0\u05d5\u05d0\u05e8",
+ "\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05d9\u05dc",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e4\u05d8\u05de\u05d1\u05e8",
+ "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8",
+ "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8",
+ "\u05d3\u05e6\u05de\u05d1\u05e8"
+ ],
+ "SHORTDAY": [
+ "\u05d9\u05d5\u05dd \u05d0\u05f3",
+ "\u05d9\u05d5\u05dd \u05d1\u05f3",
+ "\u05d9\u05d5\u05dd \u05d2\u05f3",
+ "\u05d9\u05d5\u05dd \u05d3\u05f3",
+ "\u05d9\u05d5\u05dd \u05d4\u05f3",
+ "\u05d9\u05d5\u05dd \u05d5\u05f3",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "SHORTMONTH": [
+ "\u05d9\u05e0\u05d5\u05f3",
+ "\u05e4\u05d1\u05e8\u05f3",
+ "\u05de\u05e8\u05e5",
+ "\u05d0\u05e4\u05e8\u05f3",
+ "\u05de\u05d0\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d2\u05f3",
+ "\u05e1\u05e4\u05d8\u05f3",
+ "\u05d0\u05d5\u05e7\u05f3",
+ "\u05e0\u05d5\u05d1\u05f3",
+ "\u05d3\u05e6\u05de\u05f3"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d \u05d1MMMM y",
+ "longDate": "d \u05d1MMMM y",
+ "medium": "d \u05d1MMM y H:mm:ss",
+ "mediumDate": "d \u05d1MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d.M.y H:mm",
+ "shortDate": "d.M.y",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20aa",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "iw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i == 2 && vf.v == 0) { return PLURAL_CATEGORY.TWO; } if (vf.v == 0 && (n < 0 || n > 10) && n % 10 == 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja-jp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja-jp.js
new file mode 100644
index 00000000..78cd0694
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja-jp.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u5348\u524d",
+ "\u5348\u5f8c"
+ ],
+ "DAY": [
+ "\u65e5\u66dc\u65e5",
+ "\u6708\u66dc\u65e5",
+ "\u706b\u66dc\u65e5",
+ "\u6c34\u66dc\u65e5",
+ "\u6728\u66dc\u65e5",
+ "\u91d1\u66dc\u65e5",
+ "\u571f\u66dc\u65e5"
+ ],
+ "ERANAMES": [
+ "\u7d00\u5143\u524d",
+ "\u897f\u66a6"
+ ],
+ "ERAS": [
+ "\u7d00\u5143\u524d",
+ "\u897f\u66a6"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u65e5",
+ "\u6708",
+ "\u706b",
+ "\u6c34",
+ "\u6728",
+ "\u91d1",
+ "\u571f"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y/MM/dd H:mm:ss",
+ "mediumDate": "y/MM/dd",
+ "mediumTime": "H:mm:ss",
+ "short": "y/MM/dd H:mm",
+ "shortDate": "y/MM/dd",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ja-jp",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja.js
new file mode 100644
index 00000000..0011b5cc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ja.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u5348\u524d",
+ "\u5348\u5f8c"
+ ],
+ "DAY": [
+ "\u65e5\u66dc\u65e5",
+ "\u6708\u66dc\u65e5",
+ "\u706b\u66dc\u65e5",
+ "\u6c34\u66dc\u65e5",
+ "\u6728\u66dc\u65e5",
+ "\u91d1\u66dc\u65e5",
+ "\u571f\u66dc\u65e5"
+ ],
+ "ERANAMES": [
+ "\u7d00\u5143\u524d",
+ "\u897f\u66a6"
+ ],
+ "ERAS": [
+ "\u7d00\u5143\u524d",
+ "\u897f\u66a6"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u65e5",
+ "\u6708",
+ "\u706b",
+ "\u6c34",
+ "\u6728",
+ "\u91d1",
+ "\u571f"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y/MM/dd H:mm:ss",
+ "mediumDate": "y/MM/dd",
+ "mediumTime": "H:mm:ss",
+ "short": "y/MM/dd H:mm",
+ "shortDate": "y/MM/dd",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ja",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo-cm.js
new file mode 100644
index 00000000..ae05a5a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "mba\ua78cmba\ua78c",
+ "\u014bka mb\u0254\u0301t nji"
+ ],
+ "DAY": [
+ "S\u0254\u0301ndi",
+ "M\u0254\u0301ndi",
+ "\u00c1pta M\u0254\u0301ndi",
+ "W\u025b\u0301n\u025bs\u025bd\u025b",
+ "T\u0254\u0301s\u025bd\u025b",
+ "F\u025bl\u00e2y\u025bd\u025b",
+ "S\u00e1sid\u025b"
+ ],
+ "ERANAMES": [
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301",
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301"
+ ],
+ "ERAS": [
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301",
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ndu\u014bmbi Sa\u014b",
+ "P\u025bsa\u014b P\u025b\u0301p\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301t\u00e1t",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301kwa",
+ "P\u025bsa\u014b Pataa",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301nt\u00fak\u00fa",
+ "P\u025bsa\u014b Saamb\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301f\u0254m",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301pf\u00fa\ua78b\u00fa",
+ "P\u025bsa\u014b N\u025bg\u025b\u0301m",
+ "P\u025bsa\u014b Nts\u0254\u030cpm\u0254\u0301",
+ "P\u025bsa\u014b Nts\u0254\u030cpp\u00e1"
+ ],
+ "SHORTDAY": [
+ "S\u0254\u0301ndi",
+ "M\u0254\u0301ndi",
+ "\u00c1pta M\u0254\u0301ndi",
+ "W\u025b\u0301n\u025bs\u025bd\u025b",
+ "T\u0254\u0301s\u025bd\u025b",
+ "F\u025bl\u00e2y\u025bd\u025b",
+ "S\u00e1sid\u025b"
+ ],
+ "SHORTMONTH": [
+ "Ndu\u014bmbi Sa\u014b",
+ "P\u025bsa\u014b P\u025b\u0301p\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301t\u00e1t",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301kwa",
+ "P\u025bsa\u014b Pataa",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301nt\u00fak\u00fa",
+ "P\u025bsa\u014b Saamb\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301f\u0254m",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301pf\u00fa\ua78b\u00fa",
+ "P\u025bsa\u014b N\u025bg\u025b\u0301m",
+ "P\u025bsa\u014b Nts\u0254\u030cpm\u0254\u0301",
+ "P\u025bsa\u014b Nts\u0254\u030cpp\u00e1"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "jgo-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo.js
new file mode 100644
index 00000000..f27c22c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jgo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "mba\ua78cmba\ua78c",
+ "\u014bka mb\u0254\u0301t nji"
+ ],
+ "DAY": [
+ "S\u0254\u0301ndi",
+ "M\u0254\u0301ndi",
+ "\u00c1pta M\u0254\u0301ndi",
+ "W\u025b\u0301n\u025bs\u025bd\u025b",
+ "T\u0254\u0301s\u025bd\u025b",
+ "F\u025bl\u00e2y\u025bd\u025b",
+ "S\u00e1sid\u025b"
+ ],
+ "ERANAMES": [
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301",
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301"
+ ],
+ "ERAS": [
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 l\u025b\u025bn\u025b K\u025bl\u00eds\u025bt\u0254 g\u0254 \u0144\u0254\u0301",
+ "ts\u025btts\u025bt m\u025b\u014bgu\ua78c mi \u025b\u0301 f\u00fan\u025b K\u025bl\u00eds\u025bt\u0254 t\u0254\u0301 m\u0254\u0301"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ndu\u014bmbi Sa\u014b",
+ "P\u025bsa\u014b P\u025b\u0301p\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301t\u00e1t",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301kwa",
+ "P\u025bsa\u014b Pataa",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301nt\u00fak\u00fa",
+ "P\u025bsa\u014b Saamb\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301f\u0254m",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301pf\u00fa\ua78b\u00fa",
+ "P\u025bsa\u014b N\u025bg\u025b\u0301m",
+ "P\u025bsa\u014b Nts\u0254\u030cpm\u0254\u0301",
+ "P\u025bsa\u014b Nts\u0254\u030cpp\u00e1"
+ ],
+ "SHORTDAY": [
+ "S\u0254\u0301ndi",
+ "M\u0254\u0301ndi",
+ "\u00c1pta M\u0254\u0301ndi",
+ "W\u025b\u0301n\u025bs\u025bd\u025b",
+ "T\u0254\u0301s\u025bd\u025b",
+ "F\u025bl\u00e2y\u025bd\u025b",
+ "S\u00e1sid\u025b"
+ ],
+ "SHORTMONTH": [
+ "Ndu\u014bmbi Sa\u014b",
+ "P\u025bsa\u014b P\u025b\u0301p\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301t\u00e1t",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301kwa",
+ "P\u025bsa\u014b Pataa",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301nt\u00fak\u00fa",
+ "P\u025bsa\u014b Saamb\u00e1",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301f\u0254m",
+ "P\u025bsa\u014b P\u025b\u0301n\u025b\u0301pf\u00fa\ua78b\u00fa",
+ "P\u025bsa\u014b N\u025bg\u025b\u0301m",
+ "P\u025bsa\u014b Nts\u0254\u030cpm\u0254\u0301",
+ "P\u025bsa\u014b Nts\u0254\u030cpp\u00e1"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "jgo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc-tz.js
new file mode 100644
index 00000000..8eff91df
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "jmc-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc.js
new file mode 100644
index 00000000..dd754e93
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_jmc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "jmc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka-ge.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka-ge.js
new file mode 100644
index 00000000..4383940a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka-ge.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u10d9\u10d5\u10d8\u10e0\u10d0",
+ "\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8",
+ "\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8"
+ ],
+ "ERANAMES": [
+ "\u10eb\u10d5\u10d4\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7",
+ "\u10d0\u10ee\u10d0\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7"
+ ],
+ "ERAS": [
+ "\u10eb\u10d5. \u10ec.",
+ "\u10d0\u10ee. \u10ec."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8",
+ "\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10d8",
+ "\u10db\u10d0\u10e0\u10e2\u10d8",
+ "\u10d0\u10de\u10e0\u10d8\u10da\u10d8",
+ "\u10db\u10d0\u10d8\u10e1\u10d8",
+ "\u10d8\u10d5\u10dc\u10d8\u10e1\u10d8",
+ "\u10d8\u10d5\u10da\u10d8\u10e1\u10d8",
+ "\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10dd",
+ "\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10d8"
+ ],
+ "SHORTDAY": [
+ "\u10d9\u10d5\u10d8",
+ "\u10dd\u10e0\u10e8",
+ "\u10e1\u10d0\u10db",
+ "\u10dd\u10d7\u10ee",
+ "\u10ee\u10e3\u10d7",
+ "\u10de\u10d0\u10e0",
+ "\u10e8\u10d0\u10d1"
+ ],
+ "SHORTMONTH": [
+ "\u10d8\u10d0\u10dc",
+ "\u10d7\u10d4\u10d1",
+ "\u10db\u10d0\u10e0",
+ "\u10d0\u10de\u10e0",
+ "\u10db\u10d0\u10d8",
+ "\u10d8\u10d5\u10dc",
+ "\u10d8\u10d5\u10da",
+ "\u10d0\u10d2\u10d5",
+ "\u10e1\u10d4\u10e5",
+ "\u10dd\u10e5\u10e2",
+ "\u10dc\u10dd\u10d4",
+ "\u10d3\u10d4\u10d9"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GEL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ka-ge",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka.js
new file mode 100644
index 00000000..fc846cae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ka.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u10d9\u10d5\u10d8\u10e0\u10d0",
+ "\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8",
+ "\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8",
+ "\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8"
+ ],
+ "ERANAMES": [
+ "\u10eb\u10d5\u10d4\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7",
+ "\u10d0\u10ee\u10d0\u10da\u10d8 \u10ec\u10d4\u10da\u10d7\u10d0\u10e6\u10e0\u10d8\u10ea\u10ee\u10d5\u10d8\u10d7"
+ ],
+ "ERAS": [
+ "\u10eb\u10d5. \u10ec.",
+ "\u10d0\u10ee. \u10ec."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8",
+ "\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10d8",
+ "\u10db\u10d0\u10e0\u10e2\u10d8",
+ "\u10d0\u10de\u10e0\u10d8\u10da\u10d8",
+ "\u10db\u10d0\u10d8\u10e1\u10d8",
+ "\u10d8\u10d5\u10dc\u10d8\u10e1\u10d8",
+ "\u10d8\u10d5\u10da\u10d8\u10e1\u10d8",
+ "\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10dd",
+ "\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10d8",
+ "\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10d8"
+ ],
+ "SHORTDAY": [
+ "\u10d9\u10d5\u10d8",
+ "\u10dd\u10e0\u10e8",
+ "\u10e1\u10d0\u10db",
+ "\u10dd\u10d7\u10ee",
+ "\u10ee\u10e3\u10d7",
+ "\u10de\u10d0\u10e0",
+ "\u10e8\u10d0\u10d1"
+ ],
+ "SHORTMONTH": [
+ "\u10d8\u10d0\u10dc",
+ "\u10d7\u10d4\u10d1",
+ "\u10db\u10d0\u10e0",
+ "\u10d0\u10de\u10e0",
+ "\u10db\u10d0\u10d8",
+ "\u10d8\u10d5\u10dc",
+ "\u10d8\u10d5\u10da",
+ "\u10d0\u10d2\u10d5",
+ "\u10e1\u10d4\u10e5",
+ "\u10dd\u10e5\u10e2",
+ "\u10dc\u10dd\u10d4",
+ "\u10d3\u10d4\u10d9"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GEL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ka",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab-dz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab-dz.js
new file mode 100644
index 00000000..6063c588
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab-dz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "n tufat",
+ "n tmeddit"
+ ],
+ "DAY": [
+ "Yanass",
+ "Sanass",
+ "Kra\u1e0dass",
+ "Ku\u1e93ass",
+ "Samass",
+ "S\u1e0disass",
+ "Sayass"
+ ],
+ "ERANAMES": [
+ "send talalit n \u0190isa",
+ "seld talalit n \u0190isa"
+ ],
+ "ERAS": [
+ "snd. T.\u0190",
+ "sld. T.\u0190"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Yennayer",
+ "Fu\u1e5bar",
+ "Me\u0263res",
+ "Yebrir",
+ "Mayyu",
+ "Yunyu",
+ "Yulyu",
+ "\u0194uct",
+ "Ctembe\u1e5b",
+ "Tube\u1e5b",
+ "Nunembe\u1e5b",
+ "Du\u01e7embe\u1e5b"
+ ],
+ "SHORTDAY": [
+ "Yan",
+ "San",
+ "Kra\u1e0d",
+ "Ku\u1e93",
+ "Sam",
+ "S\u1e0dis",
+ "Say"
+ ],
+ "SHORTMONTH": [
+ "Yen",
+ "Fur",
+ "Me\u0263",
+ "Yeb",
+ "May",
+ "Yun",
+ "Yul",
+ "\u0194uc",
+ "Cte",
+ "Tub",
+ "Nun",
+ "Du\u01e7"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "kab-dz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab.js
new file mode 100644
index 00000000..d7b82a94
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kab.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "n tufat",
+ "n tmeddit"
+ ],
+ "DAY": [
+ "Yanass",
+ "Sanass",
+ "Kra\u1e0dass",
+ "Ku\u1e93ass",
+ "Samass",
+ "S\u1e0disass",
+ "Sayass"
+ ],
+ "ERANAMES": [
+ "send talalit n \u0190isa",
+ "seld talalit n \u0190isa"
+ ],
+ "ERAS": [
+ "snd. T.\u0190",
+ "sld. T.\u0190"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Yennayer",
+ "Fu\u1e5bar",
+ "Me\u0263res",
+ "Yebrir",
+ "Mayyu",
+ "Yunyu",
+ "Yulyu",
+ "\u0194uct",
+ "Ctembe\u1e5b",
+ "Tube\u1e5b",
+ "Nunembe\u1e5b",
+ "Du\u01e7embe\u1e5b"
+ ],
+ "SHORTDAY": [
+ "Yan",
+ "San",
+ "Kra\u1e0d",
+ "Ku\u1e93",
+ "Sam",
+ "S\u1e0dis",
+ "Say"
+ ],
+ "SHORTMONTH": [
+ "Yen",
+ "Fur",
+ "Me\u0263",
+ "Yeb",
+ "May",
+ "Yun",
+ "Yul",
+ "\u0194uc",
+ "Cte",
+ "Tub",
+ "Nun",
+ "Du\u01e7"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "kab",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam-ke.js
new file mode 100644
index 00000000..669f17f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0128yakwakya",
+ "\u0128yaw\u0129oo"
+ ],
+ "DAY": [
+ "Wa kyumwa",
+ "Wa kwamb\u0129l\u0129lya",
+ "Wa kel\u0129",
+ "Wa katat\u0169",
+ "Wa kana",
+ "Wa katano",
+ "Wa thanthat\u0169"
+ ],
+ "ERANAMES": [
+ "Mbee wa Yes\u0169",
+ "\u0128tina wa Yes\u0169"
+ ],
+ "ERAS": [
+ "MY",
+ "IY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mwai wa mbee",
+ "Mwai wa kel\u0129",
+ "Mwai wa katat\u0169",
+ "Mwai wa kana",
+ "Mwai wa katano",
+ "Mwai wa thanthat\u0169",
+ "Mwai wa muonza",
+ "Mwai wa nyaanya",
+ "Mwai wa kenda",
+ "Mwai wa \u0129kumi",
+ "Mwai wa \u0129kumi na \u0129mwe",
+ "Mwai wa \u0129kumi na il\u0129"
+ ],
+ "SHORTDAY": [
+ "Wky",
+ "Wkw",
+ "Wkl",
+ "Wt\u0169",
+ "Wkn",
+ "Wtn",
+ "Wth"
+ ],
+ "SHORTMONTH": [
+ "Mbe",
+ "Kel",
+ "Kt\u0169",
+ "Kan",
+ "Ktn",
+ "Tha",
+ "Moo",
+ "Nya",
+ "Knd",
+ "\u0128ku",
+ "\u0128km",
+ "\u0128kl"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kam-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam.js
new file mode 100644
index 00000000..f0998400
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kam.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0128yakwakya",
+ "\u0128yaw\u0129oo"
+ ],
+ "DAY": [
+ "Wa kyumwa",
+ "Wa kwamb\u0129l\u0129lya",
+ "Wa kel\u0129",
+ "Wa katat\u0169",
+ "Wa kana",
+ "Wa katano",
+ "Wa thanthat\u0169"
+ ],
+ "ERANAMES": [
+ "Mbee wa Yes\u0169",
+ "\u0128tina wa Yes\u0169"
+ ],
+ "ERAS": [
+ "MY",
+ "IY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mwai wa mbee",
+ "Mwai wa kel\u0129",
+ "Mwai wa katat\u0169",
+ "Mwai wa kana",
+ "Mwai wa katano",
+ "Mwai wa thanthat\u0169",
+ "Mwai wa muonza",
+ "Mwai wa nyaanya",
+ "Mwai wa kenda",
+ "Mwai wa \u0129kumi",
+ "Mwai wa \u0129kumi na \u0129mwe",
+ "Mwai wa \u0129kumi na il\u0129"
+ ],
+ "SHORTDAY": [
+ "Wky",
+ "Wkw",
+ "Wkl",
+ "Wt\u0169",
+ "Wkn",
+ "Wtn",
+ "Wth"
+ ],
+ "SHORTMONTH": [
+ "Mbe",
+ "Kel",
+ "Kt\u0169",
+ "Kan",
+ "Ktn",
+ "Tha",
+ "Moo",
+ "Nya",
+ "Knd",
+ "\u0128ku",
+ "\u0128km",
+ "\u0128kl"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kam",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde-tz.js
new file mode 100644
index 00000000..0363929f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Muhi",
+ "Chilo"
+ ],
+ "DAY": [
+ "Liduva lyapili",
+ "Liduva lyatatu",
+ "Liduva lyanchechi",
+ "Liduva lyannyano",
+ "Liduva lyannyano na linji",
+ "Liduva lyannyano na mavili",
+ "Liduva litandi"
+ ],
+ "ERANAMES": [
+ "Akanapawa Yesu",
+ "Nankuida Yesu"
+ ],
+ "ERAS": [
+ "AY",
+ "NY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mwedi Ntandi",
+ "Mwedi wa Pili",
+ "Mwedi wa Tatu",
+ "Mwedi wa Nchechi",
+ "Mwedi wa Nnyano",
+ "Mwedi wa Nnyano na Umo",
+ "Mwedi wa Nnyano na Mivili",
+ "Mwedi wa Nnyano na Mitatu",
+ "Mwedi wa Nnyano na Nchechi",
+ "Mwedi wa Nnyano na Nnyano",
+ "Mwedi wa Nnyano na Nnyano na U",
+ "Mwedi wa Nnyano na Nnyano na M"
+ ],
+ "SHORTDAY": [
+ "Ll2",
+ "Ll3",
+ "Ll4",
+ "Ll5",
+ "Ll6",
+ "Ll7",
+ "Ll1"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kde-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde.js
new file mode 100644
index 00000000..6dcc55eb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kde.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Muhi",
+ "Chilo"
+ ],
+ "DAY": [
+ "Liduva lyapili",
+ "Liduva lyatatu",
+ "Liduva lyanchechi",
+ "Liduva lyannyano",
+ "Liduva lyannyano na linji",
+ "Liduva lyannyano na mavili",
+ "Liduva litandi"
+ ],
+ "ERANAMES": [
+ "Akanapawa Yesu",
+ "Nankuida Yesu"
+ ],
+ "ERAS": [
+ "AY",
+ "NY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mwedi Ntandi",
+ "Mwedi wa Pili",
+ "Mwedi wa Tatu",
+ "Mwedi wa Nchechi",
+ "Mwedi wa Nnyano",
+ "Mwedi wa Nnyano na Umo",
+ "Mwedi wa Nnyano na Mivili",
+ "Mwedi wa Nnyano na Mitatu",
+ "Mwedi wa Nnyano na Nchechi",
+ "Mwedi wa Nnyano na Nnyano",
+ "Mwedi wa Nnyano na Nnyano na U",
+ "Mwedi wa Nnyano na Nnyano na M"
+ ],
+ "SHORTDAY": [
+ "Ll2",
+ "Ll3",
+ "Ll4",
+ "Ll5",
+ "Ll6",
+ "Ll7",
+ "Ll1"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kde",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea-cv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea-cv.js
new file mode 100644
index 00000000..1fc8d8e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea-cv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "dumingu",
+ "sigunda-fera",
+ "tersa-fera",
+ "kuarta-fera",
+ "kinta-fera",
+ "sesta-fera",
+ "sabadu"
+ ],
+ "ERANAMES": [
+ "Antis di Kristu",
+ "Dispos di Kristu"
+ ],
+ "ERAS": [
+ "AK",
+ "DK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janeru",
+ "Febreru",
+ "Marsu",
+ "Abril",
+ "Maiu",
+ "Junhu",
+ "Julhu",
+ "Agostu",
+ "Setenbru",
+ "Otubru",
+ "Nuvenbru",
+ "Dizenbru"
+ ],
+ "SHORTDAY": [
+ "dum",
+ "sig",
+ "ter",
+ "kua",
+ "kin",
+ "ses",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Abr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Set",
+ "Otu",
+ "Nuv",
+ "Diz"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'di' MMMM 'di' y",
+ "longDate": "d 'di' MMMM 'di' y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CVE",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "kea-cv",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea.js
new file mode 100644
index 00000000..0bab114d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kea.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "dumingu",
+ "sigunda-fera",
+ "tersa-fera",
+ "kuarta-fera",
+ "kinta-fera",
+ "sesta-fera",
+ "sabadu"
+ ],
+ "ERANAMES": [
+ "Antis di Kristu",
+ "Dispos di Kristu"
+ ],
+ "ERAS": [
+ "AK",
+ "DK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janeru",
+ "Febreru",
+ "Marsu",
+ "Abril",
+ "Maiu",
+ "Junhu",
+ "Julhu",
+ "Agostu",
+ "Setenbru",
+ "Otubru",
+ "Nuvenbru",
+ "Dizenbru"
+ ],
+ "SHORTDAY": [
+ "dum",
+ "sig",
+ "ter",
+ "kua",
+ "kin",
+ "ses",
+ "sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Abr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Set",
+ "Otu",
+ "Nuv",
+ "Diz"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'di' MMMM 'di' y",
+ "longDate": "d 'di' MMMM 'di' y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CVE",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "kea",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq-ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq-ml.js
new file mode 100644
index 00000000..328809e1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq-ml.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Adduha",
+ "Aluula"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atini",
+ "Atalata",
+ "Alarba",
+ "Alhamiisa",
+ "Aljuma",
+ "Assabdu"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa jamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alj",
+ "Ass"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "khq-ml",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq.js
new file mode 100644
index 00000000..90fa7e6b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_khq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Adduha",
+ "Aluula"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atini",
+ "Atalata",
+ "Alarba",
+ "Alhamiisa",
+ "Aljuma",
+ "Assabdu"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa jamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alj",
+ "Ass"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "khq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki-ke.js
new file mode 100644
index 00000000..c8d312b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Kiroko",
+ "Hwa\u0129-in\u0129"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Njumatat\u0169",
+ "Njumaine",
+ "Njumatana",
+ "Aramithi",
+ "Njumaa",
+ "Njumamothi"
+ ],
+ "ERANAMES": [
+ "Mbere ya Kristo",
+ "Thutha wa Kristo"
+ ],
+ "ERAS": [
+ "MK",
+ "TK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Njenuar\u0129",
+ "Mwere wa ker\u0129",
+ "Mwere wa gatat\u0169",
+ "Mwere wa kana",
+ "Mwere wa gatano",
+ "Mwere wa gatandat\u0169",
+ "Mwere wa m\u0169gwanja",
+ "Mwere wa kanana",
+ "Mwere wa kenda",
+ "Mwere wa ik\u0169mi",
+ "Mwere wa ik\u0169mi na \u0169mwe",
+ "Ndithemba"
+ ],
+ "SHORTDAY": [
+ "KMA",
+ "NTT",
+ "NMN",
+ "NMT",
+ "ART",
+ "NMA",
+ "NMM"
+ ],
+ "SHORTMONTH": [
+ "JEN",
+ "WKR",
+ "WGT",
+ "WKN",
+ "WTN",
+ "WTD",
+ "WMJ",
+ "WNN",
+ "WKD",
+ "WIK",
+ "WMW",
+ "DIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ki-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki.js
new file mode 100644
index 00000000..b21103da
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ki.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Kiroko",
+ "Hwa\u0129-in\u0129"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Njumatat\u0169",
+ "Njumaine",
+ "Njumatana",
+ "Aramithi",
+ "Njumaa",
+ "Njumamothi"
+ ],
+ "ERANAMES": [
+ "Mbere ya Kristo",
+ "Thutha wa Kristo"
+ ],
+ "ERAS": [
+ "MK",
+ "TK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Njenuar\u0129",
+ "Mwere wa ker\u0129",
+ "Mwere wa gatat\u0169",
+ "Mwere wa kana",
+ "Mwere wa gatano",
+ "Mwere wa gatandat\u0169",
+ "Mwere wa m\u0169gwanja",
+ "Mwere wa kanana",
+ "Mwere wa kenda",
+ "Mwere wa ik\u0169mi",
+ "Mwere wa ik\u0169mi na \u0169mwe",
+ "Ndithemba"
+ ],
+ "SHORTDAY": [
+ "KMA",
+ "NTT",
+ "NMN",
+ "NMT",
+ "ART",
+ "NMA",
+ "NMM"
+ ],
+ "SHORTMONTH": [
+ "JEN",
+ "WKR",
+ "WGT",
+ "WKN",
+ "WTN",
+ "WTD",
+ "WMJ",
+ "WNN",
+ "WKD",
+ "WIK",
+ "WMW",
+ "DIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ki",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl-kz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl-kz.js
new file mode 100644
index 00000000..828abbf4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl-kz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u0435\u0440\u0442\u0435\u04a3\u0433\u0456",
+ "\u0442\u04af\u0441\u0442\u0435\u043d \u043a\u0435\u0439\u0456\u043d\u0433\u0456"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0441\u0435\u043d\u0431\u0456",
+ "\u0434\u04af\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u04d9\u0440\u0441\u0435\u043d\u0431\u0456",
+ "\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d\u0431\u0456"
+ ],
+ "ERANAMES": [
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d",
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0434.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u049b\u0430\u04a3\u0442\u0430\u0440",
+ "\u0430\u049b\u043f\u0430\u043d",
+ "\u043d\u0430\u0443\u0440\u044b\u0437",
+ "\u0441\u04d9\u0443\u0456\u0440",
+ "\u043c\u0430\u043c\u044b\u0440",
+ "\u043c\u0430\u0443\u0441\u044b\u043c",
+ "\u0448\u0456\u043b\u0434\u0435",
+ "\u0442\u0430\u043c\u044b\u0437",
+ "\u049b\u044b\u0440\u043a\u04af\u0439\u0435\u043a",
+ "\u049b\u0430\u0437\u0430\u043d",
+ "\u049b\u0430\u0440\u0430\u0448\u0430",
+ "\u0436\u0435\u043b\u0442\u043e\u049b\u0441\u0430\u043d"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a",
+ "\u0434\u04af\u0439",
+ "\u0441\u0435\u0439",
+ "\u0441\u04d9\u0440",
+ "\u0431\u0435\u0439",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d"
+ ],
+ "SHORTMONTH": [
+ "\u049b\u0430\u04a3.",
+ "\u0430\u049b\u043f.",
+ "\u043d\u0430\u0443.",
+ "\u0441\u04d9\u0443.",
+ "\u043c\u0430\u043c.",
+ "\u043c\u0430\u0443.",
+ "\u0448\u0456\u043b.",
+ "\u0442\u0430\u043c.",
+ "\u049b\u044b\u0440.",
+ "\u049b\u0430\u0437.",
+ "\u049b\u0430\u0440.",
+ "\u0436\u0435\u043b\u0442."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "y, dd-MMM HH:mm:ss",
+ "mediumDate": "y, dd-MMM",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b8",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "kk-cyrl-kz",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl.js
new file mode 100644
index 00000000..321fad88
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk-cyrl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u0435\u0440\u0442\u0435\u04a3\u0433\u0456",
+ "\u0442\u04af\u0441\u0442\u0435\u043d \u043a\u0435\u0439\u0456\u043d\u0433\u0456"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0441\u0435\u043d\u0431\u0456",
+ "\u0434\u04af\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u04d9\u0440\u0441\u0435\u043d\u0431\u0456",
+ "\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d\u0431\u0456"
+ ],
+ "ERANAMES": [
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d",
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0434.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u049b\u0430\u04a3\u0442\u0430\u0440",
+ "\u0430\u049b\u043f\u0430\u043d",
+ "\u043d\u0430\u0443\u0440\u044b\u0437",
+ "\u0441\u04d9\u0443\u0456\u0440",
+ "\u043c\u0430\u043c\u044b\u0440",
+ "\u043c\u0430\u0443\u0441\u044b\u043c",
+ "\u0448\u0456\u043b\u0434\u0435",
+ "\u0442\u0430\u043c\u044b\u0437",
+ "\u049b\u044b\u0440\u043a\u04af\u0439\u0435\u043a",
+ "\u049b\u0430\u0437\u0430\u043d",
+ "\u049b\u0430\u0440\u0430\u0448\u0430",
+ "\u0436\u0435\u043b\u0442\u043e\u049b\u0441\u0430\u043d"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a",
+ "\u0434\u04af\u0439",
+ "\u0441\u0435\u0439",
+ "\u0441\u04d9\u0440",
+ "\u0431\u0435\u0439",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d"
+ ],
+ "SHORTMONTH": [
+ "\u049b\u0430\u04a3.",
+ "\u0430\u049b\u043f.",
+ "\u043d\u0430\u0443.",
+ "\u0441\u04d9\u0443.",
+ "\u043c\u0430\u043c.",
+ "\u043c\u0430\u0443.",
+ "\u0448\u0456\u043b.",
+ "\u0442\u0430\u043c.",
+ "\u049b\u044b\u0440.",
+ "\u049b\u0430\u0437.",
+ "\u049b\u0430\u0440.",
+ "\u0436\u0435\u043b\u0442."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "y, dd-MMM HH:mm:ss",
+ "mediumDate": "y, dd-MMM",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b8",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "kk-cyrl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk.js
new file mode 100644
index 00000000..3d4a44e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u0435\u0440\u0442\u0435\u04a3\u0433\u0456",
+ "\u0442\u04af\u0441\u0442\u0435\u043d \u043a\u0435\u0439\u0456\u043d\u0433\u0456"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0441\u0435\u043d\u0431\u0456",
+ "\u0434\u04af\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0441\u04d9\u0440\u0441\u0435\u043d\u0431\u0456",
+ "\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d\u0431\u0456"
+ ],
+ "ERANAMES": [
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437\u0493\u0430 \u0434\u0435\u0439\u0456\u043d",
+ "\u0411\u0456\u0437\u0434\u0456\u04a3 \u0437\u0430\u043c\u0430\u043d\u044b\u043c\u044b\u0437"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0434.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u049b\u0430\u04a3\u0442\u0430\u0440",
+ "\u0430\u049b\u043f\u0430\u043d",
+ "\u043d\u0430\u0443\u0440\u044b\u0437",
+ "\u0441\u04d9\u0443\u0456\u0440",
+ "\u043c\u0430\u043c\u044b\u0440",
+ "\u043c\u0430\u0443\u0441\u044b\u043c",
+ "\u0448\u0456\u043b\u0434\u0435",
+ "\u0442\u0430\u043c\u044b\u0437",
+ "\u049b\u044b\u0440\u043a\u04af\u0439\u0435\u043a",
+ "\u049b\u0430\u0437\u0430\u043d",
+ "\u049b\u0430\u0440\u0430\u0448\u0430",
+ "\u0436\u0435\u043b\u0442\u043e\u049b\u0441\u0430\u043d"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a",
+ "\u0434\u04af\u0439",
+ "\u0441\u0435\u0439",
+ "\u0441\u04d9\u0440",
+ "\u0431\u0435\u0439",
+ "\u0436\u04b1\u043c\u0430",
+ "\u0441\u0435\u043d"
+ ],
+ "SHORTMONTH": [
+ "\u049b\u0430\u04a3.",
+ "\u0430\u049b\u043f.",
+ "\u043d\u0430\u0443.",
+ "\u0441\u04d9\u0443.",
+ "\u043c\u0430\u043c.",
+ "\u043c\u0430\u0443.",
+ "\u0448\u0456\u043b.",
+ "\u0442\u0430\u043c.",
+ "\u049b\u044b\u0440.",
+ "\u049b\u0430\u0437.",
+ "\u049b\u0430\u0440.",
+ "\u0436\u0435\u043b\u0442."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "y, dd-MMM HH:mm:ss",
+ "mediumDate": "y, dd-MMM",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b8",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "kk",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj-cm.js
new file mode 100644
index 00000000..8b2a2538
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "s\u0254ndi",
+ "lundi",
+ "mardi",
+ "m\u025brk\u025br\u025bdi",
+ "yedi",
+ "va\u014bd\u025br\u025bdi",
+ "m\u0254n\u0254 s\u0254ndi"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pamba",
+ "wanja",
+ "mbiy\u0254 m\u025bndo\u014bg\u0254",
+ "Ny\u0254l\u0254mb\u0254\u014bg\u0254",
+ "M\u0254n\u0254 \u014bgbanja",
+ "Nya\u014bgw\u025b \u014bgbanja",
+ "ku\u014bgw\u025b",
+ "f\u025b",
+ "njapi",
+ "nyukul",
+ "11",
+ "\u0253ul\u0253us\u025b"
+ ],
+ "SHORTDAY": [
+ "s\u0254ndi",
+ "lundi",
+ "mardi",
+ "m\u025brk\u025br\u025bdi",
+ "yedi",
+ "va\u014bd\u025br\u025bdi",
+ "m\u0254n\u0254 s\u0254ndi"
+ ],
+ "SHORTMONTH": [
+ "pamba",
+ "wanja",
+ "mbiy\u0254 m\u025bndo\u014bg\u0254",
+ "Ny\u0254l\u0254mb\u0254\u014bg\u0254",
+ "M\u0254n\u0254 \u014bgbanja",
+ "Nya\u014bgw\u025b \u014bgbanja",
+ "ku\u014bgw\u025b",
+ "f\u025b",
+ "njapi",
+ "nyukul",
+ "11",
+ "\u0253ul\u0253us\u025b"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM y HH:mm",
+ "shortDate": "dd/MM y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kkj-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj.js
new file mode 100644
index 00000000..dc0b25ad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kkj.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "s\u0254ndi",
+ "lundi",
+ "mardi",
+ "m\u025brk\u025br\u025bdi",
+ "yedi",
+ "va\u014bd\u025br\u025bdi",
+ "m\u0254n\u0254 s\u0254ndi"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pamba",
+ "wanja",
+ "mbiy\u0254 m\u025bndo\u014bg\u0254",
+ "Ny\u0254l\u0254mb\u0254\u014bg\u0254",
+ "M\u0254n\u0254 \u014bgbanja",
+ "Nya\u014bgw\u025b \u014bgbanja",
+ "ku\u014bgw\u025b",
+ "f\u025b",
+ "njapi",
+ "nyukul",
+ "11",
+ "\u0253ul\u0253us\u025b"
+ ],
+ "SHORTDAY": [
+ "s\u0254ndi",
+ "lundi",
+ "mardi",
+ "m\u025brk\u025br\u025bdi",
+ "yedi",
+ "va\u014bd\u025br\u025bdi",
+ "m\u0254n\u0254 s\u0254ndi"
+ ],
+ "SHORTMONTH": [
+ "pamba",
+ "wanja",
+ "mbiy\u0254 m\u025bndo\u014bg\u0254",
+ "Ny\u0254l\u0254mb\u0254\u014bg\u0254",
+ "M\u0254n\u0254 \u014bgbanja",
+ "Nya\u014bgw\u025b \u014bgbanja",
+ "ku\u014bgw\u025b",
+ "f\u025b",
+ "njapi",
+ "nyukul",
+ "11",
+ "\u0253ul\u0253us\u025b"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM y HH:mm",
+ "shortDate": "dd/MM y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kkj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl-gl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl-gl.js
new file mode 100644
index 00000000..3b3e77d0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl-gl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ulloqeqqata-tungaa",
+ "ulloqeqqata-kingorna"
+ ],
+ "DAY": [
+ "sabaat",
+ "ataasinngorneq",
+ "marlunngorneq",
+ "pingasunngorneq",
+ "sisamanngorneq",
+ "tallimanngorneq",
+ "arfininngorneq"
+ ],
+ "ERANAMES": [
+ "Kristusip inunngornerata siornagut",
+ "Kristusip inunngornerata kingornagut"
+ ],
+ "ERAS": [
+ "Kr.in.si.",
+ "Kr.in.king."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "martsi",
+ "aprili",
+ "maji",
+ "juni",
+ "juli",
+ "augustusi",
+ "septemberi",
+ "oktoberi",
+ "novemberi",
+ "decemberi"
+ ],
+ "SHORTDAY": [
+ "sab",
+ "ata",
+ "mar",
+ "pin",
+ "sis",
+ "tal",
+ "arf"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "MMM dd, y h:mm:ss a",
+ "mediumDate": "MMM dd, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y-MM-dd h:mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kl-gl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl.js
new file mode 100644
index 00000000..a20a1950
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ulloqeqqata-tungaa",
+ "ulloqeqqata-kingorna"
+ ],
+ "DAY": [
+ "sabaat",
+ "ataasinngorneq",
+ "marlunngorneq",
+ "pingasunngorneq",
+ "sisamanngorneq",
+ "tallimanngorneq",
+ "arfininngorneq"
+ ],
+ "ERANAMES": [
+ "Kristusip inunngornerata siornagut",
+ "Kristusip inunngornerata kingornagut"
+ ],
+ "ERAS": [
+ "Kr.in.si.",
+ "Kr.in.king."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "martsi",
+ "aprili",
+ "maji",
+ "juni",
+ "juli",
+ "augustusi",
+ "septemberi",
+ "oktoberi",
+ "novemberi",
+ "decemberi"
+ ],
+ "SHORTDAY": [
+ "sab",
+ "ata",
+ "mar",
+ "pin",
+ "sis",
+ "tal",
+ "arf"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "MMM dd, y h:mm:ss a",
+ "mediumDate": "MMM dd, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "y-MM-dd h:mm a",
+ "shortDate": "y-MM-dd",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln-ke.js
new file mode 100644
index 00000000..41e74050
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "karoon",
+ "kooskoliny"
+ ],
+ "DAY": [
+ "Kotisap",
+ "Kotaai",
+ "Koaeng\u2019",
+ "Kosomok",
+ "Koang\u2019wan",
+ "Komuut",
+ "Kolo"
+ ],
+ "ERANAMES": [
+ "Amait kesich Jesu",
+ "Kokakesich Jesu"
+ ],
+ "ERAS": [
+ "AM",
+ "KO"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mulgul",
+ "Ng\u2019atyaato",
+ "Kiptaamo",
+ "Iwootkuut",
+ "Mamuut",
+ "Paagi",
+ "Ng\u2019eiyeet",
+ "Rooptui",
+ "Bureet",
+ "Epeeso",
+ "Kipsuunde ne taai",
+ "Kipsuunde nebo aeng\u2019"
+ ],
+ "SHORTDAY": [
+ "Kts",
+ "Kot",
+ "Koo",
+ "Kos",
+ "Koa",
+ "Kom",
+ "Kol"
+ ],
+ "SHORTMONTH": [
+ "Mul",
+ "Ngat",
+ "Taa",
+ "Iwo",
+ "Mam",
+ "Paa",
+ "Nge",
+ "Roo",
+ "Bur",
+ "Epe",
+ "Kpt",
+ "Kpa"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kln-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln.js
new file mode 100644
index 00000000..973b711f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kln.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "karoon",
+ "kooskoliny"
+ ],
+ "DAY": [
+ "Kotisap",
+ "Kotaai",
+ "Koaeng\u2019",
+ "Kosomok",
+ "Koang\u2019wan",
+ "Komuut",
+ "Kolo"
+ ],
+ "ERANAMES": [
+ "Amait kesich Jesu",
+ "Kokakesich Jesu"
+ ],
+ "ERAS": [
+ "AM",
+ "KO"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mulgul",
+ "Ng\u2019atyaato",
+ "Kiptaamo",
+ "Iwootkuut",
+ "Mamuut",
+ "Paagi",
+ "Ng\u2019eiyeet",
+ "Rooptui",
+ "Bureet",
+ "Epeeso",
+ "Kipsuunde ne taai",
+ "Kipsuunde nebo aeng\u2019"
+ ],
+ "SHORTDAY": [
+ "Kts",
+ "Kot",
+ "Koo",
+ "Kos",
+ "Koa",
+ "Kom",
+ "Kol"
+ ],
+ "SHORTMONTH": [
+ "Mul",
+ "Ngat",
+ "Taa",
+ "Iwo",
+ "Mam",
+ "Paa",
+ "Nge",
+ "Roo",
+ "Bur",
+ "Epe",
+ "Kpt",
+ "Kpa"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kln",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km-kh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km-kh.js
new file mode 100644
index 00000000..43649cd6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km-kh.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1796\u17d2\u179a\u17b9\u1780",
+ "\u179b\u17d2\u1784\u17b6\u1785"
+ ],
+ "DAY": [
+ "\u17a2\u17b6\u1791\u17b7\u178f\u17d2\u1799",
+ "\u1785\u1793\u17d2\u1791",
+ "\u17a2\u1784\u17d2\u1782\u17b6\u179a",
+ "\u1796\u17bb\u1792",
+ "\u1796\u17d2\u179a\u17a0\u179f\u17d2\u1794\u178f\u17b7\u17cd",
+ "\u179f\u17bb\u1780\u17d2\u179a",
+ "\u179f\u17c5\u179a\u17cd"
+ ],
+ "ERANAMES": [
+ "\u1798\u17bb\u1793\u200b\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787",
+ "\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787"
+ ],
+ "ERAS": [
+ "\u1798\u17bb\u1793 \u1782.\u179f.",
+ "\u1782.\u179f."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1798\u1780\u179a\u17b6",
+ "\u1780\u17bb\u1798\u17d2\u1797\u17c8",
+ "\u1798\u17b8\u1793\u17b6",
+ "\u1798\u17c1\u179f\u17b6",
+ "\u17a7\u179f\u1797\u17b6",
+ "\u1798\u17b7\u1790\u17bb\u1793\u17b6",
+ "\u1780\u1780\u17d2\u1780\u178a\u17b6",
+ "\u179f\u17b8\u17a0\u17b6",
+ "\u1780\u1789\u17d2\u1789\u17b6",
+ "\u178f\u17bb\u179b\u17b6",
+ "\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6",
+ "\u1792\u17d2\u1793\u17bc"
+ ],
+ "SHORTDAY": [
+ "\u17a2\u17b6\u1791\u17b7\u178f\u17d2\u1799",
+ "\u1785\u1793\u17d2\u1791",
+ "\u17a2\u1784\u17d2\u1782\u17b6\u179a",
+ "\u1796\u17bb\u1792",
+ "\u1796\u17d2\u179a\u17a0\u179f\u17d2\u1794\u178f\u17b7\u17cd",
+ "\u179f\u17bb\u1780\u17d2\u179a",
+ "\u179f\u17c5\u179a\u17cd"
+ ],
+ "SHORTMONTH": [
+ "\u1798\u1780\u179a\u17b6",
+ "\u1780\u17bb\u1798\u17d2\u1797\u17c8",
+ "\u1798\u17b8\u1793\u17b6",
+ "\u1798\u17c1\u179f\u17b6",
+ "\u17a7\u179f\u1797\u17b6",
+ "\u1798\u17b7\u1790\u17bb\u1793\u17b6",
+ "\u1780\u1780\u17d2\u1780\u178a\u17b6",
+ "\u179f\u17b8\u17a0\u17b6",
+ "\u1780\u1789\u17d2\u1789\u17b6",
+ "\u178f\u17bb\u179b\u17b6",
+ "\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6",
+ "\u1792\u17d2\u1793\u17bc"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Riel",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "km-kh",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km.js
new file mode 100644
index 00000000..ee21ccc1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_km.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1796\u17d2\u179a\u17b9\u1780",
+ "\u179b\u17d2\u1784\u17b6\u1785"
+ ],
+ "DAY": [
+ "\u17a2\u17b6\u1791\u17b7\u178f\u17d2\u1799",
+ "\u1785\u1793\u17d2\u1791",
+ "\u17a2\u1784\u17d2\u1782\u17b6\u179a",
+ "\u1796\u17bb\u1792",
+ "\u1796\u17d2\u179a\u17a0\u179f\u17d2\u1794\u178f\u17b7\u17cd",
+ "\u179f\u17bb\u1780\u17d2\u179a",
+ "\u179f\u17c5\u179a\u17cd"
+ ],
+ "ERANAMES": [
+ "\u1798\u17bb\u1793\u200b\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787",
+ "\u1782\u17d2\u179a\u17b7\u179f\u17d2\u178f\u179f\u1780\u179a\u17b6\u1787"
+ ],
+ "ERAS": [
+ "\u1798\u17bb\u1793 \u1782.\u179f.",
+ "\u1782.\u179f."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1798\u1780\u179a\u17b6",
+ "\u1780\u17bb\u1798\u17d2\u1797\u17c8",
+ "\u1798\u17b8\u1793\u17b6",
+ "\u1798\u17c1\u179f\u17b6",
+ "\u17a7\u179f\u1797\u17b6",
+ "\u1798\u17b7\u1790\u17bb\u1793\u17b6",
+ "\u1780\u1780\u17d2\u1780\u178a\u17b6",
+ "\u179f\u17b8\u17a0\u17b6",
+ "\u1780\u1789\u17d2\u1789\u17b6",
+ "\u178f\u17bb\u179b\u17b6",
+ "\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6",
+ "\u1792\u17d2\u1793\u17bc"
+ ],
+ "SHORTDAY": [
+ "\u17a2\u17b6\u1791\u17b7\u178f\u17d2\u1799",
+ "\u1785\u1793\u17d2\u1791",
+ "\u17a2\u1784\u17d2\u1782\u17b6\u179a",
+ "\u1796\u17bb\u1792",
+ "\u1796\u17d2\u179a\u17a0\u179f\u17d2\u1794\u178f\u17b7\u17cd",
+ "\u179f\u17bb\u1780\u17d2\u179a",
+ "\u179f\u17c5\u179a\u17cd"
+ ],
+ "SHORTMONTH": [
+ "\u1798\u1780\u179a\u17b6",
+ "\u1780\u17bb\u1798\u17d2\u1797\u17c8",
+ "\u1798\u17b8\u1793\u17b6",
+ "\u1798\u17c1\u179f\u17b6",
+ "\u17a7\u179f\u1797\u17b6",
+ "\u1798\u17b7\u1790\u17bb\u1793\u17b6",
+ "\u1780\u1780\u17d2\u1780\u178a\u17b6",
+ "\u179f\u17b8\u17a0\u17b6",
+ "\u1780\u1789\u17d2\u1789\u17b6",
+ "\u178f\u17bb\u179b\u17b6",
+ "\u179c\u17b7\u1785\u17d2\u1786\u17b7\u1780\u17b6",
+ "\u1792\u17d2\u1793\u17bc"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Riel",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "km",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn-in.js
new file mode 100644
index 00000000..59f60a75
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0caa\u0cc2\u0cb0\u0ccd\u0cb5\u0cbe\u0cb9\u0ccd\u0ca8",
+ "\u0c85\u0caa\u0cb0\u0cbe\u0cb9\u0ccd\u0ca8"
+ ],
+ "DAY": [
+ "\u0cad\u0cbe\u0ca8\u0cc1\u0cb5\u0cbe\u0cb0",
+ "\u0cb8\u0ccb\u0cae\u0cb5\u0cbe\u0cb0",
+ "\u0cae\u0c82\u0c97\u0cb3\u0cb5\u0cbe\u0cb0",
+ "\u0cac\u0cc1\u0ca7\u0cb5\u0cbe\u0cb0",
+ "\u0c97\u0cc1\u0cb0\u0cc1\u0cb5\u0cbe\u0cb0",
+ "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0\u0cb5\u0cbe\u0cb0",
+ "\u0cb6\u0ca8\u0cbf\u0cb5\u0cbe\u0cb0"
+ ],
+ "ERANAMES": [
+ "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0caa\u0cc2\u0cb0\u0ccd\u0cb5",
+ "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0cb6\u0c95"
+ ],
+ "ERAS": [
+ "\u0c95\u0ccd\u0cb0\u0cbf.\u0caa\u0cc2",
+ "\u0c95\u0ccd\u0cb0\u0cbf.\u0cb6"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0c9c\u0ca8\u0cb5\u0cb0\u0cbf",
+ "\u0cab\u0cc6\u0cac\u0ccd\u0cb0\u0cb5\u0cb0\u0cbf",
+ "\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd",
+ "\u0c8f\u0caa\u0ccd\u0cb0\u0cbf\u0cb2\u0ccd",
+ "\u0cae\u0cc7",
+ "\u0c9c\u0cc2\u0ca8\u0ccd",
+ "\u0c9c\u0cc1\u0cb2\u0cc8",
+ "\u0c86\u0c97\u0cb8\u0ccd\u0c9f\u0ccd",
+ "\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82\u0cac\u0cb0\u0ccd",
+ "\u0c85\u0c95\u0ccd\u0c9f\u0ccb\u0cac\u0cb0\u0ccd",
+ "\u0ca8\u0cb5\u0cc6\u0c82\u0cac\u0cb0\u0ccd",
+ "\u0ca1\u0cbf\u0cb8\u0cc6\u0c82\u0cac\u0cb0\u0ccd"
+ ],
+ "SHORTDAY": [
+ "\u0cad\u0cbe\u0ca8\u0cc1",
+ "\u0cb8\u0ccb\u0cae",
+ "\u0cae\u0c82\u0c97\u0cb3",
+ "\u0cac\u0cc1\u0ca7",
+ "\u0c97\u0cc1\u0cb0\u0cc1",
+ "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0",
+ "\u0cb6\u0ca8\u0cbf"
+ ],
+ "SHORTMONTH": [
+ "\u0c9c\u0ca8",
+ "\u0cab\u0cc6\u0cac\u0ccd\u0cb0",
+ "\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd",
+ "\u0c8f\u0caa\u0ccd\u0cb0\u0cbf",
+ "\u0cae\u0cc7",
+ "\u0c9c\u0cc2\u0ca8\u0ccd",
+ "\u0c9c\u0cc1\u0cb2\u0cc8",
+ "\u0c86\u0c97",
+ "\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82",
+ "\u0c85\u0c95\u0ccd\u0c9f\u0ccb",
+ "\u0ca8\u0cb5\u0cc6\u0c82",
+ "\u0ca1\u0cbf\u0cb8\u0cc6\u0c82"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y hh:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "hh:mm:ss a",
+ "short": "M/d/yy hh:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kn-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn.js
new file mode 100644
index 00000000..4dcebb61
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0caa\u0cc2\u0cb0\u0ccd\u0cb5\u0cbe\u0cb9\u0ccd\u0ca8",
+ "\u0c85\u0caa\u0cb0\u0cbe\u0cb9\u0ccd\u0ca8"
+ ],
+ "DAY": [
+ "\u0cad\u0cbe\u0ca8\u0cc1\u0cb5\u0cbe\u0cb0",
+ "\u0cb8\u0ccb\u0cae\u0cb5\u0cbe\u0cb0",
+ "\u0cae\u0c82\u0c97\u0cb3\u0cb5\u0cbe\u0cb0",
+ "\u0cac\u0cc1\u0ca7\u0cb5\u0cbe\u0cb0",
+ "\u0c97\u0cc1\u0cb0\u0cc1\u0cb5\u0cbe\u0cb0",
+ "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0\u0cb5\u0cbe\u0cb0",
+ "\u0cb6\u0ca8\u0cbf\u0cb5\u0cbe\u0cb0"
+ ],
+ "ERANAMES": [
+ "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0caa\u0cc2\u0cb0\u0ccd\u0cb5",
+ "\u0c95\u0ccd\u0cb0\u0cbf\u0cb8\u0ccd\u0ca4 \u0cb6\u0c95"
+ ],
+ "ERAS": [
+ "\u0c95\u0ccd\u0cb0\u0cbf.\u0caa\u0cc2",
+ "\u0c95\u0ccd\u0cb0\u0cbf.\u0cb6"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0c9c\u0ca8\u0cb5\u0cb0\u0cbf",
+ "\u0cab\u0cc6\u0cac\u0ccd\u0cb0\u0cb5\u0cb0\u0cbf",
+ "\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd",
+ "\u0c8f\u0caa\u0ccd\u0cb0\u0cbf\u0cb2\u0ccd",
+ "\u0cae\u0cc7",
+ "\u0c9c\u0cc2\u0ca8\u0ccd",
+ "\u0c9c\u0cc1\u0cb2\u0cc8",
+ "\u0c86\u0c97\u0cb8\u0ccd\u0c9f\u0ccd",
+ "\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82\u0cac\u0cb0\u0ccd",
+ "\u0c85\u0c95\u0ccd\u0c9f\u0ccb\u0cac\u0cb0\u0ccd",
+ "\u0ca8\u0cb5\u0cc6\u0c82\u0cac\u0cb0\u0ccd",
+ "\u0ca1\u0cbf\u0cb8\u0cc6\u0c82\u0cac\u0cb0\u0ccd"
+ ],
+ "SHORTDAY": [
+ "\u0cad\u0cbe\u0ca8\u0cc1",
+ "\u0cb8\u0ccb\u0cae",
+ "\u0cae\u0c82\u0c97\u0cb3",
+ "\u0cac\u0cc1\u0ca7",
+ "\u0c97\u0cc1\u0cb0\u0cc1",
+ "\u0cb6\u0cc1\u0c95\u0ccd\u0cb0",
+ "\u0cb6\u0ca8\u0cbf"
+ ],
+ "SHORTMONTH": [
+ "\u0c9c\u0ca8",
+ "\u0cab\u0cc6\u0cac\u0ccd\u0cb0",
+ "\u0cae\u0cbe\u0cb0\u0ccd\u0c9a\u0ccd",
+ "\u0c8f\u0caa\u0ccd\u0cb0\u0cbf",
+ "\u0cae\u0cc7",
+ "\u0c9c\u0cc2\u0ca8\u0ccd",
+ "\u0c9c\u0cc1\u0cb2\u0cc8",
+ "\u0c86\u0c97",
+ "\u0cb8\u0cc6\u0caa\u0ccd\u0c9f\u0cc6\u0c82",
+ "\u0c85\u0c95\u0ccd\u0c9f\u0ccb",
+ "\u0ca8\u0cb5\u0cc6\u0c82",
+ "\u0ca1\u0cbf\u0cb8\u0cc6\u0c82"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y hh:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "hh:mm:ss a",
+ "short": "M/d/yy hh:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kp.js
new file mode 100644
index 00000000..61ae2b1b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kp.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\uc624\uc804",
+ "\uc624\ud6c4"
+ ],
+ "DAY": [
+ "\uc77c\uc694\uc77c",
+ "\uc6d4\uc694\uc77c",
+ "\ud654\uc694\uc77c",
+ "\uc218\uc694\uc77c",
+ "\ubaa9\uc694\uc77c",
+ "\uae08\uc694\uc77c",
+ "\ud1a0\uc694\uc77c"
+ ],
+ "ERANAMES": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "ERAS": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "SHORTDAY": [
+ "\uc77c",
+ "\uc6d4",
+ "\ud654",
+ "\uc218",
+ "\ubaa9",
+ "\uae08",
+ "\ud1a0"
+ ],
+ "SHORTMONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\ub144 M\uc6d4 d\uc77c EEEE",
+ "longDate": "y\ub144 M\uc6d4 d\uc77c",
+ "medium": "y. M. d. a h:mm:ss",
+ "mediumDate": "y. M. d.",
+ "mediumTime": "a h:mm:ss",
+ "short": "yy. M. d. a h:mm",
+ "shortDate": "yy. M. d.",
+ "shortTime": "a h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a9KP",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ko-kp",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kr.js
new file mode 100644
index 00000000..004a2d8d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko-kr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\uc624\uc804",
+ "\uc624\ud6c4"
+ ],
+ "DAY": [
+ "\uc77c\uc694\uc77c",
+ "\uc6d4\uc694\uc77c",
+ "\ud654\uc694\uc77c",
+ "\uc218\uc694\uc77c",
+ "\ubaa9\uc694\uc77c",
+ "\uae08\uc694\uc77c",
+ "\ud1a0\uc694\uc77c"
+ ],
+ "ERANAMES": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "ERAS": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "SHORTDAY": [
+ "\uc77c",
+ "\uc6d4",
+ "\ud654",
+ "\uc218",
+ "\ubaa9",
+ "\uae08",
+ "\ud1a0"
+ ],
+ "SHORTMONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\ub144 M\uc6d4 d\uc77c EEEE",
+ "longDate": "y\ub144 M\uc6d4 d\uc77c",
+ "medium": "y. M. d. a h:mm:ss",
+ "mediumDate": "y. M. d.",
+ "mediumTime": "a h:mm:ss",
+ "short": "yy. M. d. a h:mm",
+ "shortDate": "yy. M. d.",
+ "shortTime": "a h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ko-kr",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko.js
new file mode 100644
index 00000000..b9c6fea3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ko.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\uc624\uc804",
+ "\uc624\ud6c4"
+ ],
+ "DAY": [
+ "\uc77c\uc694\uc77c",
+ "\uc6d4\uc694\uc77c",
+ "\ud654\uc694\uc77c",
+ "\uc218\uc694\uc77c",
+ "\ubaa9\uc694\uc77c",
+ "\uae08\uc694\uc77c",
+ "\ud1a0\uc694\uc77c"
+ ],
+ "ERANAMES": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "ERAS": [
+ "\uae30\uc6d0\uc804",
+ "\uc11c\uae30"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "SHORTDAY": [
+ "\uc77c",
+ "\uc6d4",
+ "\ud654",
+ "\uc218",
+ "\ubaa9",
+ "\uae08",
+ "\ud1a0"
+ ],
+ "SHORTMONTH": [
+ "1\uc6d4",
+ "2\uc6d4",
+ "3\uc6d4",
+ "4\uc6d4",
+ "5\uc6d4",
+ "6\uc6d4",
+ "7\uc6d4",
+ "8\uc6d4",
+ "9\uc6d4",
+ "10\uc6d4",
+ "11\uc6d4",
+ "12\uc6d4"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\ub144 M\uc6d4 d\uc77c EEEE",
+ "longDate": "y\ub144 M\uc6d4 d\uc77c",
+ "medium": "y. M. d. a h:mm:ss",
+ "mediumDate": "y. M. d.",
+ "mediumTime": "a h:mm:ss",
+ "short": "yy. M. d. a h:mm",
+ "shortDate": "yy. M. d.",
+ "shortTime": "a h:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ko",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok-in.js
new file mode 100644
index 00000000..fde838b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092e.\u092a\u0942.",
+ "\u092e.\u0928\u0902."
+ ],
+ "DAY": [
+ "\u0906\u0926\u093f\u0924\u094d\u092f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0933\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935",
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e"
+ ],
+ "ERAS": [
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935",
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0913\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0933",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0913\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd-MM-y h:mm:ss a",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kok-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok.js
new file mode 100644
index 00000000..701c8f7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kok.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092e.\u092a\u0942.",
+ "\u092e.\u0928\u0902."
+ ],
+ "DAY": [
+ "\u0906\u0926\u093f\u0924\u094d\u092f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0933\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935",
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e"
+ ],
+ "ERAS": [
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935",
+ "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0913\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0933",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0913\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd-MM-y h:mm:ss a",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kok",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab-in.js
new file mode 100644
index 00000000..3f2caf1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0627\u064e\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0631\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d",
+ "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655"
+ ],
+ "ERAS": [
+ "\u0628\u06cc \u0633\u06cc",
+ "\u0627\u06d2 \u0688\u06cc"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0622\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ks-arab-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab.js
new file mode 100644
index 00000000..364703ca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks-arab.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0627\u064e\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0631\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d",
+ "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655"
+ ],
+ "ERAS": [
+ "\u0628\u06cc \u0633\u06cc",
+ "\u0627\u06d2 \u0688\u06cc"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0622\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ks-arab",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks.js
new file mode 100644
index 00000000..d5d58c66
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ks.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0627\u064e\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0631\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0655\u0644 \u0645\u0633\u06cc\u0656\u062d",
+ "\u0639\u06cc\u0656\u0633\u0648\u06cc \u0633\u0646\u06c1\u0655"
+ ],
+ "ERAS": [
+ "\u0628\u06cc \u0633\u06cc",
+ "\u0627\u06d2 \u0688\u06cc"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0622\u062a\u06be\u0648\u0627\u0631",
+ "\u0698\u0654\u0646\u065b\u062f\u0655\u0631\u0648\u0627\u0631",
+ "\u0628\u0648\u065a\u0645\u0648\u0627\u0631",
+ "\u0628\u0648\u062f\u0648\u0627\u0631",
+ "\u0628\u0631\u065b\u066e\u06ea\u0633\u0648\u0627\u0631",
+ "\u062c\u064f\u0645\u06c1",
+ "\u0628\u0679\u0648\u0627\u0631"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0624\u0631\u06cc",
+ "\u0641\u0631\u0624\u0631\u06cc",
+ "\u0645\u0627\u0631\u0655\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc\u0654",
+ "\u062c\u0648\u0657\u0646",
+ "\u062c\u0648\u0657\u0644\u0627\u06cc\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0657\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ks",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb-tz.js
new file mode 100644
index 00000000..f52a6f36
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "makeo",
+ "nyiaghuo"
+ ],
+ "DAY": [
+ "Jumaapii",
+ "Jumaatatu",
+ "Jumaane",
+ "Jumaatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumaamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Klisto",
+ "Baada ya Klisto"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januali",
+ "Febluali",
+ "Machi",
+ "Aplili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jmn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "ksb-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb.js
new file mode 100644
index 00000000..14528926
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "makeo",
+ "nyiaghuo"
+ ],
+ "DAY": [
+ "Jumaapii",
+ "Jumaatatu",
+ "Jumaane",
+ "Jumaatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumaamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Klisto",
+ "Baada ya Klisto"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januali",
+ "Febluali",
+ "Machi",
+ "Aplili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jmn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "ksb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf-cm.js
new file mode 100644
index 00000000..a3f69547
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "s\u00e1r\u00faw\u00e1",
+ "c\u025b\u025b\u0301nko"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u01dd",
+ "l\u01ddnd\u00ed",
+ "maad\u00ed",
+ "m\u025bkr\u025bd\u00ed",
+ "j\u01dd\u01ddd\u00ed",
+ "j\u00famb\u00e1",
+ "samd\u00ed"
+ ],
+ "ERANAMES": [
+ "di Y\u025b\u0301sus ak\u00e1 y\u00e1l\u025b",
+ "c\u00e1m\u025b\u025bn k\u01dd k\u01ddb\u0254pka Y"
+ ],
+ "ERAS": [
+ "d.Y.",
+ "k.Y."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u014bw\u00ed\u00ed a nt\u0254\u0301nt\u0254",
+ "\u014bw\u00ed\u00ed ak\u01dd b\u025b\u0301\u025b",
+ "\u014bw\u00ed\u00ed ak\u01dd r\u00e1\u00e1",
+ "\u014bw\u00ed\u00ed ak\u01dd nin",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1an",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1af\u0254k",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1ab\u025b\u025b",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1araa",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1anin",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk di b\u0254\u0301k",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk di b\u025b\u0301\u025b"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "l\u01ddn",
+ "maa",
+ "m\u025bk",
+ "j\u01dd\u01dd",
+ "j\u00fam",
+ "sam"
+ ],
+ "SHORTMONTH": [
+ "\u014b1",
+ "\u014b2",
+ "\u014b3",
+ "\u014b4",
+ "\u014b5",
+ "\u014b6",
+ "\u014b7",
+ "\u014b8",
+ "\u014b9",
+ "\u014b10",
+ "\u014b11",
+ "\u014b12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ksf-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf.js
new file mode 100644
index 00000000..dfd65a2e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksf.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "s\u00e1r\u00faw\u00e1",
+ "c\u025b\u025b\u0301nko"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u01dd",
+ "l\u01ddnd\u00ed",
+ "maad\u00ed",
+ "m\u025bkr\u025bd\u00ed",
+ "j\u01dd\u01ddd\u00ed",
+ "j\u00famb\u00e1",
+ "samd\u00ed"
+ ],
+ "ERANAMES": [
+ "di Y\u025b\u0301sus ak\u00e1 y\u00e1l\u025b",
+ "c\u00e1m\u025b\u025bn k\u01dd k\u01ddb\u0254pka Y"
+ ],
+ "ERAS": [
+ "d.Y.",
+ "k.Y."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u014bw\u00ed\u00ed a nt\u0254\u0301nt\u0254",
+ "\u014bw\u00ed\u00ed ak\u01dd b\u025b\u0301\u025b",
+ "\u014bw\u00ed\u00ed ak\u01dd r\u00e1\u00e1",
+ "\u014bw\u00ed\u00ed ak\u01dd nin",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1an",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1af\u0254k",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1ab\u025b\u025b",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1araa",
+ "\u014bw\u00ed\u00ed ak\u01dd t\u00e1anin",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk di b\u0254\u0301k",
+ "\u014bw\u00ed\u00ed ak\u01dd nt\u025bk di b\u025b\u0301\u025b"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "l\u01ddn",
+ "maa",
+ "m\u025bk",
+ "j\u01dd\u01dd",
+ "j\u00fam",
+ "sam"
+ ],
+ "SHORTMONTH": [
+ "\u014b1",
+ "\u014b2",
+ "\u014b3",
+ "\u014b4",
+ "\u014b5",
+ "\u014b6",
+ "\u014b7",
+ "\u014b8",
+ "\u014b9",
+ "\u014b10",
+ "\u014b11",
+ "\u014b12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ksf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh-de.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh-de.js
new file mode 100644
index 00000000..c69f40d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh-de.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Uhr v\u00f6rmiddaachs",
+ "Uhr nommendaachs"
+ ],
+ "DAY": [
+ "Sunndaach",
+ "Moondaach",
+ "Dinnsdaach",
+ "Metwoch",
+ "Dunnersdaach",
+ "Friidaach",
+ "Samsdaach"
+ ],
+ "ERANAMES": [
+ "v\u00fcr Chrestus",
+ "noh Chrestus"
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jannewa",
+ "F\u00e4browa",
+ "M\u00e4\u00e4z",
+ "Aprell",
+ "M\u00e4i",
+ "Juuni",
+ "Juuli",
+ "Oujo\u00df",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "Mo.",
+ "Di.",
+ "Me.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "F\u00e4b",
+ "M\u00e4z",
+ "Apr",
+ "M\u00e4i",
+ "Jun",
+ "Jul",
+ "Ouj",
+ "S\u00e4p",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'd\u00e4' d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM. y HH:mm:ss",
+ "mediumDate": "d. MMM. y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d. M. y HH:mm",
+ "shortDate": "d. M. y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ksh-de",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh.js
new file mode 100644
index 00000000..cb166982
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ksh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Uhr v\u00f6rmiddaachs",
+ "Uhr nommendaachs"
+ ],
+ "DAY": [
+ "Sunndaach",
+ "Moondaach",
+ "Dinnsdaach",
+ "Metwoch",
+ "Dunnersdaach",
+ "Friidaach",
+ "Samsdaach"
+ ],
+ "ERANAMES": [
+ "v\u00fcr Chrestus",
+ "noh Chrestus"
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jannewa",
+ "F\u00e4browa",
+ "M\u00e4\u00e4z",
+ "Aprell",
+ "M\u00e4i",
+ "Juuni",
+ "Juuli",
+ "Oujo\u00df",
+ "Sept\u00e4mber",
+ "Oktoober",
+ "Nov\u00e4mber",
+ "Dez\u00e4mber"
+ ],
+ "SHORTDAY": [
+ "Su.",
+ "Mo.",
+ "Di.",
+ "Me.",
+ "Du.",
+ "Fr.",
+ "Sa."
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "F\u00e4b",
+ "M\u00e4z",
+ "Apr",
+ "M\u00e4i",
+ "Jun",
+ "Jul",
+ "Ouj",
+ "S\u00e4p",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'd\u00e4' d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM. y HH:mm:ss",
+ "mediumDate": "d. MMM. y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d. M. y HH:mm",
+ "shortDate": "d. M. y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ksh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw-gb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw-gb.js
new file mode 100644
index 00000000..45be1507
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw-gb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "dy Sul",
+ "dy Lun",
+ "dy Meurth",
+ "dy Merher",
+ "dy Yow",
+ "dy Gwener",
+ "dy Sadorn"
+ ],
+ "ERANAMES": [
+ "RC",
+ "AD"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "mis Genver",
+ "mis Hwevrer",
+ "mis Meurth",
+ "mis Ebrel",
+ "mis Me",
+ "mis Metheven",
+ "mis Gortheren",
+ "mis Est",
+ "mis Gwynngala",
+ "mis Hedra",
+ "mis Du",
+ "mis Kevardhu"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Lun",
+ "Mth",
+ "Mhr",
+ "Yow",
+ "Gwe",
+ "Sad"
+ ],
+ "SHORTMONTH": [
+ "Gen",
+ "Hwe",
+ "Meu",
+ "Ebr",
+ "Me",
+ "Met",
+ "Gor",
+ "Est",
+ "Gwn",
+ "Hed",
+ "Du",
+ "Kev"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kw-gb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw.js
new file mode 100644
index 00000000..b1349d6a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_kw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "dy Sul",
+ "dy Lun",
+ "dy Meurth",
+ "dy Merher",
+ "dy Yow",
+ "dy Gwener",
+ "dy Sadorn"
+ ],
+ "ERANAMES": [
+ "RC",
+ "AD"
+ ],
+ "ERAS": [
+ "RC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "mis Genver",
+ "mis Hwevrer",
+ "mis Meurth",
+ "mis Ebrel",
+ "mis Me",
+ "mis Metheven",
+ "mis Gortheren",
+ "mis Est",
+ "mis Gwynngala",
+ "mis Hedra",
+ "mis Du",
+ "mis Kevardhu"
+ ],
+ "SHORTDAY": [
+ "Sul",
+ "Lun",
+ "Mth",
+ "Mhr",
+ "Yow",
+ "Gwe",
+ "Sad"
+ ],
+ "SHORTMONTH": [
+ "Gen",
+ "Hwe",
+ "Meu",
+ "Ebr",
+ "Me",
+ "Met",
+ "Gor",
+ "Est",
+ "Gwn",
+ "Hed",
+ "Du",
+ "Kev"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a3",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "kw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl-kg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl-kg.js
new file mode 100644
index 00000000..75a59471
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl-kg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u043a\u044b",
+ "\u0442\u04af\u0448\u0442\u04e9\u043d \u043a\u0438\u0439\u0438\u043d"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0448\u0435\u043c\u0431\u0438",
+ "\u0434\u04af\u0439\u0448\u04e9\u043c\u0431\u04af",
+ "\u0448\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0448\u0430\u0440\u0448\u0435\u043c\u0431\u0438",
+ "\u0431\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u0435\u043c\u0431\u0438"
+ ],
+ "ERANAMES": [
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d",
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0447.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044c",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044c",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b\u044c",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d\u044c",
+ "\u0438\u044e\u043b\u044c",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
+ "\u043d\u043e\u044f\u0431\u0440\u044c",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a.",
+ "\u0434\u04af\u0439.",
+ "\u0448\u0435\u0439\u0448.",
+ "\u0448\u0430\u0440\u0448.",
+ "\u0431\u0435\u0439\u0448.",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u043c."
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d.",
+ "\u0438\u044e\u043b.",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d-MMMM, y-'\u0436'.",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KGS",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ky-cyrl-kg",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl.js
new file mode 100644
index 00000000..7c5a5778
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky-cyrl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u043a\u044b",
+ "\u0442\u04af\u0448\u0442\u04e9\u043d \u043a\u0438\u0439\u0438\u043d"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0448\u0435\u043c\u0431\u0438",
+ "\u0434\u04af\u0439\u0448\u04e9\u043c\u0431\u04af",
+ "\u0448\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0448\u0430\u0440\u0448\u0435\u043c\u0431\u0438",
+ "\u0431\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u0435\u043c\u0431\u0438"
+ ],
+ "ERANAMES": [
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d",
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0447.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044c",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044c",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b\u044c",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d\u044c",
+ "\u0438\u044e\u043b\u044c",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
+ "\u043d\u043e\u044f\u0431\u0440\u044c",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a.",
+ "\u0434\u04af\u0439.",
+ "\u0448\u0435\u0439\u0448.",
+ "\u0448\u0430\u0440\u0448.",
+ "\u0431\u0435\u0439\u0448.",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u043c."
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d.",
+ "\u0438\u044e\u043b.",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d-MMMM, y-'\u0436'.",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KGS",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ky-cyrl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky.js
new file mode 100644
index 00000000..b7fe2635
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ky.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0442\u0430\u04a3\u043a\u044b",
+ "\u0442\u04af\u0448\u0442\u04e9\u043d \u043a\u0438\u0439\u0438\u043d"
+ ],
+ "DAY": [
+ "\u0436\u0435\u043a\u0448\u0435\u043c\u0431\u0438",
+ "\u0434\u04af\u0439\u0448\u04e9\u043c\u0431\u04af",
+ "\u0448\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0448\u0430\u0440\u0448\u0435\u043c\u0431\u0438",
+ "\u0431\u0435\u0439\u0448\u0435\u043c\u0431\u0438",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u0435\u043c\u0431\u0438"
+ ],
+ "ERANAMES": [
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d\u0433\u0430 \u0447\u0435\u0439\u0438\u043d",
+ "\u0431\u0438\u0437\u0434\u0438\u043d \u0437\u0430\u043c\u0430\u043d"
+ ],
+ "ERAS": [
+ "\u0431.\u0437.\u0447.",
+ "\u0431.\u0437."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044c",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044c",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0435\u043b\u044c",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d\u044c",
+ "\u0438\u044e\u043b\u044c",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
+ "\u043d\u043e\u044f\u0431\u0440\u044c",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"
+ ],
+ "SHORTDAY": [
+ "\u0436\u0435\u043a.",
+ "\u0434\u04af\u0439.",
+ "\u0448\u0435\u0439\u0448.",
+ "\u0448\u0430\u0440\u0448.",
+ "\u0431\u0435\u0439\u0448.",
+ "\u0436\u0443\u043c\u0430",
+ "\u0438\u0448\u043c."
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0439",
+ "\u0438\u044e\u043d.",
+ "\u0438\u044e\u043b.",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d-MMMM, y-'\u0436'.",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KGS",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ky",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag-tz.js
new file mode 100644
index 00000000..a76e7696
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "TOO",
+ "MUU"
+ ],
+ "DAY": [
+ "Jumap\u00ediri",
+ "Jumat\u00e1tu",
+ "Juma\u00edne",
+ "Jumat\u00e1ano",
+ "Alam\u00edisi",
+ "Ijum\u00e1a",
+ "Jumam\u00f3osi"
+ ],
+ "ERANAMES": [
+ "K\u0268r\u0268sit\u0289 s\u0268 anavyaal",
+ "K\u0268r\u0268sit\u0289 akavyaalwe"
+ ],
+ "ERAS": [
+ "KSA",
+ "KA"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "K\u0289f\u00fangat\u0268",
+ "K\u0289naan\u0268",
+ "K\u0289keenda",
+ "Kwiikumi",
+ "Kwiinyamb\u00e1la",
+ "Kwiidwaata",
+ "K\u0289m\u0289\u0289nch\u0268",
+ "K\u0289v\u0268\u0268r\u0268",
+ "K\u0289saat\u0289",
+ "Kwiinyi",
+ "K\u0289saano",
+ "K\u0289sasat\u0289"
+ ],
+ "SHORTDAY": [
+ "P\u00edili",
+ "T\u00e1atu",
+ "\u00cdne",
+ "T\u00e1ano",
+ "Alh",
+ "Ijm",
+ "M\u00f3osi"
+ ],
+ "SHORTMONTH": [
+ "F\u00fangat\u0268",
+ "Naan\u0268",
+ "Keenda",
+ "Ik\u00fami",
+ "Inyambala",
+ "Idwaata",
+ "M\u0289\u0289nch\u0268",
+ "V\u0268\u0268r\u0268",
+ "Saat\u0289",
+ "Inyi",
+ "Saano",
+ "Sasat\u0289"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lag-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag.js
new file mode 100644
index 00000000..6fb2f6e5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lag.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "TOO",
+ "MUU"
+ ],
+ "DAY": [
+ "Jumap\u00ediri",
+ "Jumat\u00e1tu",
+ "Juma\u00edne",
+ "Jumat\u00e1ano",
+ "Alam\u00edisi",
+ "Ijum\u00e1a",
+ "Jumam\u00f3osi"
+ ],
+ "ERANAMES": [
+ "K\u0268r\u0268sit\u0289 s\u0268 anavyaal",
+ "K\u0268r\u0268sit\u0289 akavyaalwe"
+ ],
+ "ERAS": [
+ "KSA",
+ "KA"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "K\u0289f\u00fangat\u0268",
+ "K\u0289naan\u0268",
+ "K\u0289keenda",
+ "Kwiikumi",
+ "Kwiinyamb\u00e1la",
+ "Kwiidwaata",
+ "K\u0289m\u0289\u0289nch\u0268",
+ "K\u0289v\u0268\u0268r\u0268",
+ "K\u0289saat\u0289",
+ "Kwiinyi",
+ "K\u0289saano",
+ "K\u0289sasat\u0289"
+ ],
+ "SHORTDAY": [
+ "P\u00edili",
+ "T\u00e1atu",
+ "\u00cdne",
+ "T\u00e1ano",
+ "Alh",
+ "Ijm",
+ "M\u00f3osi"
+ ],
+ "SHORTMONTH": [
+ "F\u00fangat\u0268",
+ "Naan\u0268",
+ "Keenda",
+ "Ik\u00fami",
+ "Inyambala",
+ "Idwaata",
+ "M\u0289\u0289nch\u0268",
+ "V\u0268\u0268r\u0268",
+ "Saat\u0289",
+ "Inyi",
+ "Saano",
+ "Sasat\u0289"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lag",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb-lu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb-lu.js
new file mode 100644
index 00000000..64ef9776
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb-lu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "moies",
+ "nom\u00ebttes"
+ ],
+ "DAY": [
+ "Sonndeg",
+ "M\u00e9indeg",
+ "D\u00ebnschdeg",
+ "M\u00ebttwoch",
+ "Donneschdeg",
+ "Freideg",
+ "Samschdeg"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4erz",
+ "Abr\u00ebll",
+ "Mee",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "Son.",
+ "M\u00e9i.",
+ "D\u00ebn.",
+ "M\u00ebt.",
+ "Don.",
+ "Fre.",
+ "Sam."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4e.",
+ "Abr.",
+ "Mee",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "lb-lu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb.js
new file mode 100644
index 00000000..dd721993
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lb.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "moies",
+ "nom\u00ebttes"
+ ],
+ "DAY": [
+ "Sonndeg",
+ "M\u00e9indeg",
+ "D\u00ebnschdeg",
+ "M\u00ebttwoch",
+ "Donneschdeg",
+ "Freideg",
+ "Samschdeg"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar",
+ "Februar",
+ "M\u00e4erz",
+ "Abr\u00ebll",
+ "Mee",
+ "Juni",
+ "Juli",
+ "August",
+ "September",
+ "Oktober",
+ "November",
+ "Dezember"
+ ],
+ "SHORTDAY": [
+ "Son.",
+ "M\u00e9i.",
+ "D\u00ebn.",
+ "M\u00ebt.",
+ "Don.",
+ "Fre.",
+ "Sam."
+ ],
+ "SHORTMONTH": [
+ "Jan.",
+ "Feb.",
+ "M\u00e4e.",
+ "Abr.",
+ "Mee",
+ "Juni",
+ "Juli",
+ "Aug.",
+ "Sep.",
+ "Okt.",
+ "Nov.",
+ "Dez."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "lb",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg-ug.js
new file mode 100644
index 00000000..78d1c9f0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sabbiiti",
+ "Balaza",
+ "Lwakubiri",
+ "Lwakusatu",
+ "Lwakuna",
+ "Lwakutaano",
+ "Lwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kulisito nga tannaza",
+ "Bukya Kulisito Azaal"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janwaliyo",
+ "Febwaliyo",
+ "Marisi",
+ "Apuli",
+ "Maayi",
+ "Juuni",
+ "Julaayi",
+ "Agusito",
+ "Sebuttemba",
+ "Okitobba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Sab",
+ "Bal",
+ "Lw2",
+ "Lw3",
+ "Lw4",
+ "Lw5",
+ "Lw6"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apu",
+ "Maa",
+ "Juu",
+ "Jul",
+ "Agu",
+ "Seb",
+ "Oki",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "lg-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg.js
new file mode 100644
index 00000000..e0bbf02f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sabbiiti",
+ "Balaza",
+ "Lwakubiri",
+ "Lwakusatu",
+ "Lwakuna",
+ "Lwakutaano",
+ "Lwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kulisito nga tannaza",
+ "Bukya Kulisito Azaal"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janwaliyo",
+ "Febwaliyo",
+ "Marisi",
+ "Apuli",
+ "Maayi",
+ "Juuni",
+ "Julaayi",
+ "Agusito",
+ "Sebuttemba",
+ "Okitobba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Sab",
+ "Bal",
+ "Lw2",
+ "Lw3",
+ "Lw4",
+ "Lw5",
+ "Lw6"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apu",
+ "Maa",
+ "Juu",
+ "Jul",
+ "Agu",
+ "Seb",
+ "Oki",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "lg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt-us.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt-us.js
new file mode 100644
index 00000000..e5b488b8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt-us.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "A\u014bp\u00e9tuwak\u021fa\u014b",
+ "A\u014bp\u00e9tuwa\u014b\u017ei",
+ "A\u014bp\u00e9tunu\u014bpa",
+ "A\u014bp\u00e9tuyamni",
+ "A\u014bp\u00e9tutopa",
+ "A\u014bp\u00e9tuzapta\u014b",
+ "Ow\u00e1\u014bgyu\u017ea\u017eapi"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Wi\u00f3the\u021fika W\u00ed",
+ "Thiy\u00f3\u021feyu\u014bka W\u00ed",
+ "I\u0161t\u00e1wi\u010dhayaza\u014b W\u00ed",
+ "P\u021fe\u017e\u00edt\u021fo W\u00ed",
+ "\u010cha\u014bw\u00e1pet\u021fo W\u00ed",
+ "W\u00edpazuk\u021fa-wa\u0161t\u00e9 W\u00ed",
+ "\u010cha\u014bp\u021f\u00e1sapa W\u00ed",
+ "Was\u00fat\u021fu\u014b W\u00ed",
+ "\u010cha\u014bw\u00e1pe\u01e7i W\u00ed",
+ "\u010cha\u014bw\u00e1pe-kasn\u00e1 W\u00ed",
+ "Wan\u00edyetu W\u00ed",
+ "T\u021fah\u00e9kap\u0161u\u014b W\u00ed"
+ ],
+ "SHORTDAY": [
+ "A\u014bp\u00e9tuwak\u021fa\u014b",
+ "A\u014bp\u00e9tuwa\u014b\u017ei",
+ "A\u014bp\u00e9tunu\u014bpa",
+ "A\u014bp\u00e9tuyamni",
+ "A\u014bp\u00e9tutopa",
+ "A\u014bp\u00e9tuzapta\u014b",
+ "Ow\u00e1\u014bgyu\u017ea\u017eapi"
+ ],
+ "SHORTMONTH": [
+ "Wi\u00f3the\u021fika W\u00ed",
+ "Thiy\u00f3\u021feyu\u014bka W\u00ed",
+ "I\u0161t\u00e1wi\u010dhayaza\u014b W\u00ed",
+ "P\u021fe\u017e\u00edt\u021fo W\u00ed",
+ "\u010cha\u014bw\u00e1pet\u021fo W\u00ed",
+ "W\u00edpazuk\u021fa-wa\u0161t\u00e9 W\u00ed",
+ "\u010cha\u014bp\u021f\u00e1sapa W\u00ed",
+ "Was\u00fat\u021fu\u014b W\u00ed",
+ "\u010cha\u014bw\u00e1pe\u01e7i W\u00ed",
+ "\u010cha\u014bw\u00e1pe-kasn\u00e1 W\u00ed",
+ "Wan\u00edyetu W\u00ed",
+ "T\u021fah\u00e9kap\u0161u\u014b W\u00ed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lkt-us",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt.js
new file mode 100644
index 00000000..57398cb3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lkt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "A\u014bp\u00e9tuwak\u021fa\u014b",
+ "A\u014bp\u00e9tuwa\u014b\u017ei",
+ "A\u014bp\u00e9tunu\u014bpa",
+ "A\u014bp\u00e9tuyamni",
+ "A\u014bp\u00e9tutopa",
+ "A\u014bp\u00e9tuzapta\u014b",
+ "Ow\u00e1\u014bgyu\u017ea\u017eapi"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Wi\u00f3the\u021fika W\u00ed",
+ "Thiy\u00f3\u021feyu\u014bka W\u00ed",
+ "I\u0161t\u00e1wi\u010dhayaza\u014b W\u00ed",
+ "P\u021fe\u017e\u00edt\u021fo W\u00ed",
+ "\u010cha\u014bw\u00e1pet\u021fo W\u00ed",
+ "W\u00edpazuk\u021fa-wa\u0161t\u00e9 W\u00ed",
+ "\u010cha\u014bp\u021f\u00e1sapa W\u00ed",
+ "Was\u00fat\u021fu\u014b W\u00ed",
+ "\u010cha\u014bw\u00e1pe\u01e7i W\u00ed",
+ "\u010cha\u014bw\u00e1pe-kasn\u00e1 W\u00ed",
+ "Wan\u00edyetu W\u00ed",
+ "T\u021fah\u00e9kap\u0161u\u014b W\u00ed"
+ ],
+ "SHORTDAY": [
+ "A\u014bp\u00e9tuwak\u021fa\u014b",
+ "A\u014bp\u00e9tuwa\u014b\u017ei",
+ "A\u014bp\u00e9tunu\u014bpa",
+ "A\u014bp\u00e9tuyamni",
+ "A\u014bp\u00e9tutopa",
+ "A\u014bp\u00e9tuzapta\u014b",
+ "Ow\u00e1\u014bgyu\u017ea\u017eapi"
+ ],
+ "SHORTMONTH": [
+ "Wi\u00f3the\u021fika W\u00ed",
+ "Thiy\u00f3\u021feyu\u014bka W\u00ed",
+ "I\u0161t\u00e1wi\u010dhayaza\u014b W\u00ed",
+ "P\u021fe\u017e\u00edt\u021fo W\u00ed",
+ "\u010cha\u014bw\u00e1pet\u021fo W\u00ed",
+ "W\u00edpazuk\u021fa-wa\u0161t\u00e9 W\u00ed",
+ "\u010cha\u014bp\u021f\u00e1sapa W\u00ed",
+ "Was\u00fat\u021fu\u014b W\u00ed",
+ "\u010cha\u014bw\u00e1pe\u01e7i W\u00ed",
+ "\u010cha\u014bw\u00e1pe-kasn\u00e1 W\u00ed",
+ "Wan\u00edyetu W\u00ed",
+ "T\u021fah\u00e9kap\u0161u\u014b W\u00ed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lkt",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-ao.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-ao.js
new file mode 100644
index 00000000..8a88e889
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-ao.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "nt\u0254\u0301ng\u0254\u0301",
+ "mp\u00f3kwa"
+ ],
+ "DAY": [
+ "eyenga",
+ "mok\u0254l\u0254 mwa yambo",
+ "mok\u0254l\u0254 mwa m\u00edbal\u00e9",
+ "mok\u0254l\u0254 mwa m\u00eds\u00e1to",
+ "mok\u0254l\u0254 ya m\u00edn\u00e9i",
+ "mok\u0254l\u0254 ya m\u00edt\u00e1no",
+ "mp\u0254\u0301s\u0254"
+ ],
+ "ERANAMES": [
+ "Yambo ya Y\u00e9zu Kr\u00eds",
+ "Nsima ya Y\u00e9zu Kr\u00eds"
+ ],
+ "ERAS": [
+ "lib\u00f3so ya",
+ "nsima ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "s\u00e1nz\u00e1 ya yambo",
+ "s\u00e1nz\u00e1 ya m\u00edbal\u00e9",
+ "s\u00e1nz\u00e1 ya m\u00eds\u00e1to",
+ "s\u00e1nz\u00e1 ya m\u00ednei",
+ "s\u00e1nz\u00e1 ya m\u00edt\u00e1no",
+ "s\u00e1nz\u00e1 ya mot\u00f3b\u00e1",
+ "s\u00e1nz\u00e1 ya nsambo",
+ "s\u00e1nz\u00e1 ya mwambe",
+ "s\u00e1nz\u00e1 ya libwa",
+ "s\u00e1nz\u00e1 ya z\u00f3mi",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u0254\u030ck\u0254\u0301",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u00edbal\u00e9"
+ ],
+ "SHORTDAY": [
+ "eye",
+ "ybo",
+ "mbl",
+ "mst",
+ "min",
+ "mtn",
+ "mps"
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fbl",
+ "msi",
+ "apl",
+ "mai",
+ "yun",
+ "yul",
+ "agt",
+ "stb",
+ "\u0254tb",
+ "nvb",
+ "dsb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Kz",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ln-ao",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cd.js
new file mode 100644
index 00000000..f08e4f4f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cd.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "nt\u0254\u0301ng\u0254\u0301",
+ "mp\u00f3kwa"
+ ],
+ "DAY": [
+ "eyenga",
+ "mok\u0254l\u0254 mwa yambo",
+ "mok\u0254l\u0254 mwa m\u00edbal\u00e9",
+ "mok\u0254l\u0254 mwa m\u00eds\u00e1to",
+ "mok\u0254l\u0254 ya m\u00edn\u00e9i",
+ "mok\u0254l\u0254 ya m\u00edt\u00e1no",
+ "mp\u0254\u0301s\u0254"
+ ],
+ "ERANAMES": [
+ "Yambo ya Y\u00e9zu Kr\u00eds",
+ "Nsima ya Y\u00e9zu Kr\u00eds"
+ ],
+ "ERAS": [
+ "lib\u00f3so ya",
+ "nsima ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "s\u00e1nz\u00e1 ya yambo",
+ "s\u00e1nz\u00e1 ya m\u00edbal\u00e9",
+ "s\u00e1nz\u00e1 ya m\u00eds\u00e1to",
+ "s\u00e1nz\u00e1 ya m\u00ednei",
+ "s\u00e1nz\u00e1 ya m\u00edt\u00e1no",
+ "s\u00e1nz\u00e1 ya mot\u00f3b\u00e1",
+ "s\u00e1nz\u00e1 ya nsambo",
+ "s\u00e1nz\u00e1 ya mwambe",
+ "s\u00e1nz\u00e1 ya libwa",
+ "s\u00e1nz\u00e1 ya z\u00f3mi",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u0254\u030ck\u0254\u0301",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u00edbal\u00e9"
+ ],
+ "SHORTDAY": [
+ "eye",
+ "ybo",
+ "mbl",
+ "mst",
+ "min",
+ "mtn",
+ "mps"
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fbl",
+ "msi",
+ "apl",
+ "mai",
+ "yun",
+ "yul",
+ "agt",
+ "stb",
+ "\u0254tb",
+ "nvb",
+ "dsb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ln-cd",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cf.js
new file mode 100644
index 00000000..7af86d5a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cf.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "nt\u0254\u0301ng\u0254\u0301",
+ "mp\u00f3kwa"
+ ],
+ "DAY": [
+ "eyenga",
+ "mok\u0254l\u0254 mwa yambo",
+ "mok\u0254l\u0254 mwa m\u00edbal\u00e9",
+ "mok\u0254l\u0254 mwa m\u00eds\u00e1to",
+ "mok\u0254l\u0254 ya m\u00edn\u00e9i",
+ "mok\u0254l\u0254 ya m\u00edt\u00e1no",
+ "mp\u0254\u0301s\u0254"
+ ],
+ "ERANAMES": [
+ "Yambo ya Y\u00e9zu Kr\u00eds",
+ "Nsima ya Y\u00e9zu Kr\u00eds"
+ ],
+ "ERAS": [
+ "lib\u00f3so ya",
+ "nsima ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "s\u00e1nz\u00e1 ya yambo",
+ "s\u00e1nz\u00e1 ya m\u00edbal\u00e9",
+ "s\u00e1nz\u00e1 ya m\u00eds\u00e1to",
+ "s\u00e1nz\u00e1 ya m\u00ednei",
+ "s\u00e1nz\u00e1 ya m\u00edt\u00e1no",
+ "s\u00e1nz\u00e1 ya mot\u00f3b\u00e1",
+ "s\u00e1nz\u00e1 ya nsambo",
+ "s\u00e1nz\u00e1 ya mwambe",
+ "s\u00e1nz\u00e1 ya libwa",
+ "s\u00e1nz\u00e1 ya z\u00f3mi",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u0254\u030ck\u0254\u0301",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u00edbal\u00e9"
+ ],
+ "SHORTDAY": [
+ "eye",
+ "ybo",
+ "mbl",
+ "mst",
+ "min",
+ "mtn",
+ "mps"
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fbl",
+ "msi",
+ "apl",
+ "mai",
+ "yun",
+ "yul",
+ "agt",
+ "stb",
+ "\u0254tb",
+ "nvb",
+ "dsb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ln-cf",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cg.js
new file mode 100644
index 00000000..5c8e41cd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln-cg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "nt\u0254\u0301ng\u0254\u0301",
+ "mp\u00f3kwa"
+ ],
+ "DAY": [
+ "eyenga",
+ "mok\u0254l\u0254 mwa yambo",
+ "mok\u0254l\u0254 mwa m\u00edbal\u00e9",
+ "mok\u0254l\u0254 mwa m\u00eds\u00e1to",
+ "mok\u0254l\u0254 ya m\u00edn\u00e9i",
+ "mok\u0254l\u0254 ya m\u00edt\u00e1no",
+ "mp\u0254\u0301s\u0254"
+ ],
+ "ERANAMES": [
+ "Yambo ya Y\u00e9zu Kr\u00eds",
+ "Nsima ya Y\u00e9zu Kr\u00eds"
+ ],
+ "ERAS": [
+ "lib\u00f3so ya",
+ "nsima ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "s\u00e1nz\u00e1 ya yambo",
+ "s\u00e1nz\u00e1 ya m\u00edbal\u00e9",
+ "s\u00e1nz\u00e1 ya m\u00eds\u00e1to",
+ "s\u00e1nz\u00e1 ya m\u00ednei",
+ "s\u00e1nz\u00e1 ya m\u00edt\u00e1no",
+ "s\u00e1nz\u00e1 ya mot\u00f3b\u00e1",
+ "s\u00e1nz\u00e1 ya nsambo",
+ "s\u00e1nz\u00e1 ya mwambe",
+ "s\u00e1nz\u00e1 ya libwa",
+ "s\u00e1nz\u00e1 ya z\u00f3mi",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u0254\u030ck\u0254\u0301",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u00edbal\u00e9"
+ ],
+ "SHORTDAY": [
+ "eye",
+ "ybo",
+ "mbl",
+ "mst",
+ "min",
+ "mtn",
+ "mps"
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fbl",
+ "msi",
+ "apl",
+ "mai",
+ "yun",
+ "yul",
+ "agt",
+ "stb",
+ "\u0254tb",
+ "nvb",
+ "dsb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ln-cg",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln.js
new file mode 100644
index 00000000..300de98e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ln.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "nt\u0254\u0301ng\u0254\u0301",
+ "mp\u00f3kwa"
+ ],
+ "DAY": [
+ "eyenga",
+ "mok\u0254l\u0254 mwa yambo",
+ "mok\u0254l\u0254 mwa m\u00edbal\u00e9",
+ "mok\u0254l\u0254 mwa m\u00eds\u00e1to",
+ "mok\u0254l\u0254 ya m\u00edn\u00e9i",
+ "mok\u0254l\u0254 ya m\u00edt\u00e1no",
+ "mp\u0254\u0301s\u0254"
+ ],
+ "ERANAMES": [
+ "Yambo ya Y\u00e9zu Kr\u00eds",
+ "Nsima ya Y\u00e9zu Kr\u00eds"
+ ],
+ "ERAS": [
+ "lib\u00f3so ya",
+ "nsima ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "s\u00e1nz\u00e1 ya yambo",
+ "s\u00e1nz\u00e1 ya m\u00edbal\u00e9",
+ "s\u00e1nz\u00e1 ya m\u00eds\u00e1to",
+ "s\u00e1nz\u00e1 ya m\u00ednei",
+ "s\u00e1nz\u00e1 ya m\u00edt\u00e1no",
+ "s\u00e1nz\u00e1 ya mot\u00f3b\u00e1",
+ "s\u00e1nz\u00e1 ya nsambo",
+ "s\u00e1nz\u00e1 ya mwambe",
+ "s\u00e1nz\u00e1 ya libwa",
+ "s\u00e1nz\u00e1 ya z\u00f3mi",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u0254\u030ck\u0254\u0301",
+ "s\u00e1nz\u00e1 ya z\u00f3mi na m\u00edbal\u00e9"
+ ],
+ "SHORTDAY": [
+ "eye",
+ "ybo",
+ "mbl",
+ "mst",
+ "min",
+ "mtn",
+ "mps"
+ ],
+ "SHORTMONTH": [
+ "yan",
+ "fbl",
+ "msi",
+ "apl",
+ "mai",
+ "yun",
+ "yul",
+ "agt",
+ "stb",
+ "\u0254tb",
+ "nvb",
+ "dsb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ln",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo-la.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo-la.js
new file mode 100644
index 00000000..f6bf34f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo-la.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0e81\u0ec8\u0ead\u0e99\u0e97\u0ec8\u0ebd\u0e87",
+ "\u0eab\u0ebc\u0eb1\u0e87\u0e97\u0ec8\u0ebd\u0e87"
+ ],
+ "DAY": [
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb2\u0e97\u0eb4\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e88\u0eb1\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb8\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb0\u0eab\u0eb1\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81",
+ "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2"
+ ],
+ "ERANAMES": [
+ "\u0e81\u0ec8\u0ead\u0e99\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94",
+ "\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94"
+ ],
+ "ERAS": [
+ "\u0e81\u0ec8\u0ead\u0e99 \u0e84.\u0eaa.",
+ "\u0e84.\u0eaa."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99",
+ "\u0e81\u0eb8\u0ea1\u0e9e\u0eb2",
+ "\u0ea1\u0eb5\u0e99\u0eb2",
+ "\u0ec0\u0ea1\u0eaa\u0eb2",
+ "\u0e9e\u0eb6\u0e94\u0eaa\u0eb0\u0e9e\u0eb2",
+ "\u0ea1\u0eb4\u0e96\u0eb8\u0e99\u0eb2",
+ "\u0e81\u0ecd\u0ea5\u0eb0\u0e81\u0ebb\u0e94",
+ "\u0eaa\u0eb4\u0e87\u0eab\u0eb2",
+ "\u0e81\u0eb1\u0e99\u0e8d\u0eb2",
+ "\u0e95\u0eb8\u0ea5\u0eb2",
+ "\u0e9e\u0eb0\u0e88\u0eb4\u0e81",
+ "\u0e97\u0eb1\u0e99\u0ea7\u0eb2"
+ ],
+ "SHORTDAY": [
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb2\u0e97\u0eb4\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e88\u0eb1\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb8\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb0\u0eab\u0eb1\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81",
+ "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2"
+ ],
+ "SHORTMONTH": [
+ "\u0ea1.\u0e81.",
+ "\u0e81.\u0e9e.",
+ "\u0ea1.\u0e99.",
+ "\u0ea1.\u0eaa.",
+ "\u0e9e.\u0e9e.",
+ "\u0ea1\u0eb4.\u0e96.",
+ "\u0e81.\u0ea5.",
+ "\u0eaa.\u0eab.",
+ "\u0e81.\u0e8d.",
+ "\u0e95.\u0ea5.",
+ "\u0e9e.\u0e88.",
+ "\u0e97.\u0ea7."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE \u0e97\u0eb5 d MMMM G y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/y H:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ad",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lo-la",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo.js
new file mode 100644
index 00000000..76d51754
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0e81\u0ec8\u0ead\u0e99\u0e97\u0ec8\u0ebd\u0e87",
+ "\u0eab\u0ebc\u0eb1\u0e87\u0e97\u0ec8\u0ebd\u0e87"
+ ],
+ "DAY": [
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb2\u0e97\u0eb4\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e88\u0eb1\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb8\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb0\u0eab\u0eb1\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81",
+ "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2"
+ ],
+ "ERANAMES": [
+ "\u0e81\u0ec8\u0ead\u0e99\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94",
+ "\u0e84\u0ea3\u0eb4\u0e94\u0eaa\u0eb1\u0e81\u0e81\u0eb0\u0ea5\u0eb2\u0e94"
+ ],
+ "ERAS": [
+ "\u0e81\u0ec8\u0ead\u0e99 \u0e84.\u0eaa.",
+ "\u0e84.\u0eaa."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0ea1\u0eb1\u0e87\u0e81\u0ead\u0e99",
+ "\u0e81\u0eb8\u0ea1\u0e9e\u0eb2",
+ "\u0ea1\u0eb5\u0e99\u0eb2",
+ "\u0ec0\u0ea1\u0eaa\u0eb2",
+ "\u0e9e\u0eb6\u0e94\u0eaa\u0eb0\u0e9e\u0eb2",
+ "\u0ea1\u0eb4\u0e96\u0eb8\u0e99\u0eb2",
+ "\u0e81\u0ecd\u0ea5\u0eb0\u0e81\u0ebb\u0e94",
+ "\u0eaa\u0eb4\u0e87\u0eab\u0eb2",
+ "\u0e81\u0eb1\u0e99\u0e8d\u0eb2",
+ "\u0e95\u0eb8\u0ea5\u0eb2",
+ "\u0e9e\u0eb0\u0e88\u0eb4\u0e81",
+ "\u0e97\u0eb1\u0e99\u0ea7\u0eb2"
+ ],
+ "SHORTDAY": [
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb2\u0e97\u0eb4\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e88\u0eb1\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0ead\u0eb1\u0e87\u0e84\u0eb2\u0e99",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb8\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0e9e\u0eb0\u0eab\u0eb1\u0e94",
+ "\u0ea7\u0eb1\u0e99\u0eaa\u0eb8\u0e81",
+ "\u0ea7\u0eb1\u0e99\u0ec0\u0eaa\u0ebb\u0eb2"
+ ],
+ "SHORTMONTH": [
+ "\u0ea1.\u0e81.",
+ "\u0e81.\u0e9e.",
+ "\u0ea1.\u0e99.",
+ "\u0ea1.\u0eaa.",
+ "\u0e9e.\u0e9e.",
+ "\u0ea1\u0eb4.\u0e96.",
+ "\u0e81.\u0ea5.",
+ "\u0eaa.\u0eab.",
+ "\u0e81.\u0e8d.",
+ "\u0e95.\u0ea5.",
+ "\u0e9e.\u0e88.",
+ "\u0e97.\u0ea7."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE \u0e97\u0eb5 d MMMM G y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "d/M/y H:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ad",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lo",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt-lt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt-lt.js
new file mode 100644
index 00000000..34e16f9d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt-lt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "prie\u0161piet",
+ "popiet"
+ ],
+ "DAY": [
+ "sekmadienis",
+ "pirmadienis",
+ "antradienis",
+ "tre\u010diadienis",
+ "ketvirtadienis",
+ "penktadienis",
+ "\u0161e\u0161tadienis"
+ ],
+ "ERANAMES": [
+ "prie\u0161 Krist\u0173",
+ "po Kristaus"
+ ],
+ "ERAS": [
+ "pr. Kr.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sausio",
+ "vasario",
+ "kovo",
+ "baland\u017eio",
+ "gegu\u017e\u0117s",
+ "bir\u017eelio",
+ "liepos",
+ "rugpj\u016b\u010dio",
+ "rugs\u0117jo",
+ "spalio",
+ "lapkri\u010dio",
+ "gruod\u017eio"
+ ],
+ "SHORTDAY": [
+ "sk",
+ "pr",
+ "an",
+ "tr",
+ "kt",
+ "pn",
+ "\u0161t"
+ ],
+ "SHORTMONTH": [
+ "saus.",
+ "vas.",
+ "kov.",
+ "bal.",
+ "geg.",
+ "bir\u017e.",
+ "liep.",
+ "rugp.",
+ "rugs.",
+ "spal.",
+ "lapkr.",
+ "gruod."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y 'm'. MMMM d 'd'., EEEE",
+ "longDate": "y 'm'. MMMM d 'd'.",
+ "medium": "y-MM-dd HH:mm:ss",
+ "mediumDate": "y-MM-dd",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "lt-lt",
+ "pluralCat": function(n, opt_precision) { var vf = getVF(n, opt_precision); if (n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) { return PLURAL_CATEGORY.FEW; } if (vf.f != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt.js
new file mode 100644
index 00000000..b8f7a9b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lt.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "prie\u0161piet",
+ "popiet"
+ ],
+ "DAY": [
+ "sekmadienis",
+ "pirmadienis",
+ "antradienis",
+ "tre\u010diadienis",
+ "ketvirtadienis",
+ "penktadienis",
+ "\u0161e\u0161tadienis"
+ ],
+ "ERANAMES": [
+ "prie\u0161 Krist\u0173",
+ "po Kristaus"
+ ],
+ "ERAS": [
+ "pr. Kr.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sausio",
+ "vasario",
+ "kovo",
+ "baland\u017eio",
+ "gegu\u017e\u0117s",
+ "bir\u017eelio",
+ "liepos",
+ "rugpj\u016b\u010dio",
+ "rugs\u0117jo",
+ "spalio",
+ "lapkri\u010dio",
+ "gruod\u017eio"
+ ],
+ "SHORTDAY": [
+ "sk",
+ "pr",
+ "an",
+ "tr",
+ "kt",
+ "pn",
+ "\u0161t"
+ ],
+ "SHORTMONTH": [
+ "saus.",
+ "vas.",
+ "kov.",
+ "bal.",
+ "geg.",
+ "bir\u017e.",
+ "liep.",
+ "rugp.",
+ "rugs.",
+ "spal.",
+ "lapkr.",
+ "gruod."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y 'm'. MMMM d 'd'., EEEE",
+ "longDate": "y 'm'. MMMM d 'd'.",
+ "medium": "y-MM-dd HH:mm:ss",
+ "mediumDate": "y-MM-dd",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "lt",
+ "pluralCat": function(n, opt_precision) { var vf = getVF(n, opt_precision); if (n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) { return PLURAL_CATEGORY.ONE; } if (n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) { return PLURAL_CATEGORY.FEW; } if (vf.f != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu-cd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu-cd.js
new file mode 100644
index 00000000..05533233
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu-cd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Dinda",
+ "Dilolo"
+ ],
+ "DAY": [
+ "Lumingu",
+ "Nkodya",
+ "Nd\u00e0ay\u00e0",
+ "Ndang\u00f9",
+ "Nj\u00f2wa",
+ "Ng\u00f2vya",
+ "Lubingu"
+ ],
+ "ERANAMES": [
+ "Kumpala kwa Yezu Kli",
+ "Kunyima kwa Yezu Kli"
+ ],
+ "ERAS": [
+ "kmp. Y.K.",
+ "kny. Y. K."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ciongo",
+ "L\u00f9ishi",
+ "Lus\u00f2lo",
+ "M\u00f9uy\u00e0",
+ "Lum\u00f9ng\u00f9l\u00f9",
+ "Lufuimi",
+ "Kab\u00e0l\u00e0sh\u00ecp\u00f9",
+ "L\u00f9sh\u00eck\u00e0",
+ "Lutongolo",
+ "Lung\u00f9di",
+ "Kasw\u00e8k\u00e8s\u00e8",
+ "Cisw\u00e0"
+ ],
+ "SHORTDAY": [
+ "Lum",
+ "Nko",
+ "Ndy",
+ "Ndg",
+ "Njw",
+ "Ngv",
+ "Lub"
+ ],
+ "SHORTMONTH": [
+ "Cio",
+ "Lui",
+ "Lus",
+ "Muu",
+ "Lum",
+ "Luf",
+ "Kab",
+ "Lush",
+ "Lut",
+ "Lun",
+ "Kas",
+ "Cis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "lu-cd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu.js
new file mode 100644
index 00000000..9cddb8fa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Dinda",
+ "Dilolo"
+ ],
+ "DAY": [
+ "Lumingu",
+ "Nkodya",
+ "Nd\u00e0ay\u00e0",
+ "Ndang\u00f9",
+ "Nj\u00f2wa",
+ "Ng\u00f2vya",
+ "Lubingu"
+ ],
+ "ERANAMES": [
+ "Kumpala kwa Yezu Kli",
+ "Kunyima kwa Yezu Kli"
+ ],
+ "ERAS": [
+ "kmp. Y.K.",
+ "kny. Y. K."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ciongo",
+ "L\u00f9ishi",
+ "Lus\u00f2lo",
+ "M\u00f9uy\u00e0",
+ "Lum\u00f9ng\u00f9l\u00f9",
+ "Lufuimi",
+ "Kab\u00e0l\u00e0sh\u00ecp\u00f9",
+ "L\u00f9sh\u00eck\u00e0",
+ "Lutongolo",
+ "Lung\u00f9di",
+ "Kasw\u00e8k\u00e8s\u00e8",
+ "Cisw\u00e0"
+ ],
+ "SHORTDAY": [
+ "Lum",
+ "Nko",
+ "Ndy",
+ "Ndg",
+ "Njw",
+ "Ngv",
+ "Lub"
+ ],
+ "SHORTMONTH": [
+ "Cio",
+ "Lui",
+ "Lus",
+ "Muu",
+ "Lum",
+ "Luf",
+ "Kab",
+ "Lush",
+ "Lut",
+ "Lun",
+ "Kas",
+ "Cis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "lu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo-ke.js
new file mode 100644
index 00000000..0f85ee6b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "OD",
+ "OT"
+ ],
+ "DAY": [
+ "Jumapil",
+ "Wuok Tich",
+ "Tich Ariyo",
+ "Tich Adek",
+ "Tich Ang\u2019wen",
+ "Tich Abich",
+ "Ngeso"
+ ],
+ "ERANAMES": [
+ "Kapok Kristo obiro",
+ "Ka Kristo osebiro"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Dwe mar Achiel",
+ "Dwe mar Ariyo",
+ "Dwe mar Adek",
+ "Dwe mar Ang\u2019wen",
+ "Dwe mar Abich",
+ "Dwe mar Auchiel",
+ "Dwe mar Abiriyo",
+ "Dwe mar Aboro",
+ "Dwe mar Ochiko",
+ "Dwe mar Apar",
+ "Dwe mar gi achiel",
+ "Dwe mar Apar gi ariyo"
+ ],
+ "SHORTDAY": [
+ "JMP",
+ "WUT",
+ "TAR",
+ "TAD",
+ "TAN",
+ "TAB",
+ "NGS"
+ ],
+ "SHORTMONTH": [
+ "DAC",
+ "DAR",
+ "DAD",
+ "DAN",
+ "DAH",
+ "DAU",
+ "DAO",
+ "DAB",
+ "DOC",
+ "DAP",
+ "DGI",
+ "DAG"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "luo-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo.js
new file mode 100644
index 00000000..0067d1f4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "OD",
+ "OT"
+ ],
+ "DAY": [
+ "Jumapil",
+ "Wuok Tich",
+ "Tich Ariyo",
+ "Tich Adek",
+ "Tich Ang\u2019wen",
+ "Tich Abich",
+ "Ngeso"
+ ],
+ "ERANAMES": [
+ "Kapok Kristo obiro",
+ "Ka Kristo osebiro"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Dwe mar Achiel",
+ "Dwe mar Ariyo",
+ "Dwe mar Adek",
+ "Dwe mar Ang\u2019wen",
+ "Dwe mar Abich",
+ "Dwe mar Auchiel",
+ "Dwe mar Abiriyo",
+ "Dwe mar Aboro",
+ "Dwe mar Ochiko",
+ "Dwe mar Apar",
+ "Dwe mar gi achiel",
+ "Dwe mar Apar gi ariyo"
+ ],
+ "SHORTDAY": [
+ "JMP",
+ "WUT",
+ "TAR",
+ "TAD",
+ "TAN",
+ "TAB",
+ "NGS"
+ ],
+ "SHORTMONTH": [
+ "DAC",
+ "DAR",
+ "DAD",
+ "DAN",
+ "DAH",
+ "DAU",
+ "DAO",
+ "DAB",
+ "DOC",
+ "DAP",
+ "DGI",
+ "DAG"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "luo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy-ke.js
new file mode 100644
index 00000000..301f5bf8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Jumapiri",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Murwa wa Kanne",
+ "Murwa wa Katano",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Imberi ya Kuuza Kwa",
+ "Muhiga Kuvita Kuuza"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "J2",
+ "J3",
+ "J4",
+ "J5",
+ "Al",
+ "Ij",
+ "J1"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "luy-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy.js
new file mode 100644
index 00000000..01f683a5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_luy.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Jumapiri",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Murwa wa Kanne",
+ "Murwa wa Katano",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Imberi ya Kuuza Kwa",
+ "Muhiga Kuvita Kuuza"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "J2",
+ "J3",
+ "J4",
+ "J5",
+ "Al",
+ "Ij",
+ "J1"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "luy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv-lv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv-lv.js
new file mode 100644
index 00000000..e892fd43
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv-lv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "priek\u0161pusdien\u0101",
+ "p\u0113cpusdien\u0101"
+ ],
+ "DAY": [
+ "sv\u0113tdiena",
+ "pirmdiena",
+ "otrdiena",
+ "tre\u0161diena",
+ "ceturtdiena",
+ "piektdiena",
+ "sestdiena"
+ ],
+ "ERANAMES": [
+ "pirms m\u016bsu \u0113ras",
+ "m\u016bsu \u0113r\u0101"
+ ],
+ "ERAS": [
+ "p.m.\u0113.",
+ "m.\u0113."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janv\u0101ris",
+ "febru\u0101ris",
+ "marts",
+ "apr\u012blis",
+ "maijs",
+ "j\u016bnijs",
+ "j\u016blijs",
+ "augusts",
+ "septembris",
+ "oktobris",
+ "novembris",
+ "decembris"
+ ],
+ "SHORTDAY": [
+ "Sv",
+ "Pr",
+ "Ot",
+ "Tr",
+ "Ce",
+ "Pk",
+ "Se"
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "febr.",
+ "marts",
+ "apr.",
+ "maijs",
+ "j\u016bn.",
+ "j\u016bl.",
+ "aug.",
+ "sept.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y. 'gada' d. MMMM",
+ "longDate": "y. 'gada' d. MMMM",
+ "medium": "y. 'gada' d. MMM HH:mm:ss",
+ "mediumDate": "y. 'gada' d. MMM",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lv-lv",
+ "pluralCat": function(n, opt_precision) { var vf = getVF(n, opt_precision); if (n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 || vf.v == 2 && vf.f % 100 >= 11 && vf.f % 100 <= 19) { return PLURAL_CATEGORY.ZERO; } if (n % 10 == 1 && n % 100 != 11 || vf.v == 2 && vf.f % 10 == 1 && vf.f % 100 != 11 || vf.v != 2 && vf.f % 10 == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv.js
new file mode 100644
index 00000000..c22256cb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_lv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "priek\u0161pusdien\u0101",
+ "p\u0113cpusdien\u0101"
+ ],
+ "DAY": [
+ "sv\u0113tdiena",
+ "pirmdiena",
+ "otrdiena",
+ "tre\u0161diena",
+ "ceturtdiena",
+ "piektdiena",
+ "sestdiena"
+ ],
+ "ERANAMES": [
+ "pirms m\u016bsu \u0113ras",
+ "m\u016bsu \u0113r\u0101"
+ ],
+ "ERAS": [
+ "p.m.\u0113.",
+ "m.\u0113."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janv\u0101ris",
+ "febru\u0101ris",
+ "marts",
+ "apr\u012blis",
+ "maijs",
+ "j\u016bnijs",
+ "j\u016blijs",
+ "augusts",
+ "septembris",
+ "oktobris",
+ "novembris",
+ "decembris"
+ ],
+ "SHORTDAY": [
+ "Sv",
+ "Pr",
+ "Ot",
+ "Tr",
+ "Ce",
+ "Pk",
+ "Se"
+ ],
+ "SHORTMONTH": [
+ "janv.",
+ "febr.",
+ "marts",
+ "apr.",
+ "maijs",
+ "j\u016bn.",
+ "j\u016bl.",
+ "aug.",
+ "sept.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y. 'gada' d. MMMM",
+ "longDate": "y. 'gada' d. MMMM",
+ "medium": "y. 'gada' d. MMM HH:mm:ss",
+ "mediumDate": "y. 'gada' d. MMM",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 0,
+ "lgSize": 0,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "lv",
+ "pluralCat": function(n, opt_precision) { var vf = getVF(n, opt_precision); if (n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 || vf.v == 2 && vf.f % 100 >= 11 && vf.f % 100 <= 19) { return PLURAL_CATEGORY.ZERO; } if (n % 10 == 1 && n % 100 != 11 || vf.v == 2 && vf.f % 10 == 1 && vf.f % 100 != 11 || vf.v != 2 && vf.f % 10 == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-ke.js
new file mode 100644
index 00000000..74bf268b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0190nkak\u025bny\u00e1",
+ "\u0190nd\u00e1m\u00e2"
+ ],
+ "DAY": [
+ "Jumap\u00edl\u00ed",
+ "Jumat\u00e1tu",
+ "Jumane",
+ "Jumat\u00e1n\u0254",
+ "Ala\u00e1misi",
+ "Jum\u00e1a",
+ "Jumam\u00f3si"
+ ],
+ "ERANAMES": [
+ "Me\u00edn\u014d Y\u025b\u0301s\u0289",
+ "E\u00edn\u014d Y\u025b\u0301s\u0289"
+ ],
+ "ERAS": [
+ "MY",
+ "EY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Oladal\u0289\u0301",
+ "Ar\u00e1t",
+ "\u0186\u025bn\u0268\u0301\u0254\u0268\u014b\u0254k",
+ "Olodoy\u00ed\u00f3r\u00ed\u00ea ink\u00f3k\u00fa\u00e2",
+ "Oloil\u00e9p\u016bny\u012b\u0113 ink\u00f3k\u00fa\u00e2",
+ "K\u00faj\u00fa\u0254r\u0254k",
+ "M\u00f3rus\u00e1sin",
+ "\u0186l\u0254\u0301\u0268\u0301b\u0254\u0301r\u00e1r\u025b",
+ "K\u00fash\u00een",
+ "Olg\u00edsan",
+ "P\u0289sh\u0289\u0301ka",
+ "Nt\u0289\u0301\u014b\u0289\u0301s"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Dal",
+ "Ar\u00e1",
+ "\u0186\u025bn",
+ "Doy",
+ "L\u00e9p",
+ "Rok",
+ "S\u00e1s",
+ "B\u0254\u0301r",
+ "K\u00fas",
+ "G\u00eds",
+ "Sh\u0289\u0301",
+ "Nt\u0289\u0301"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mas-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-tz.js
new file mode 100644
index 00000000..0a81920b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0190nkak\u025bny\u00e1",
+ "\u0190nd\u00e1m\u00e2"
+ ],
+ "DAY": [
+ "Jumap\u00edl\u00ed",
+ "Jumat\u00e1tu",
+ "Jumane",
+ "Jumat\u00e1n\u0254",
+ "Ala\u00e1misi",
+ "Jum\u00e1a",
+ "Jumam\u00f3si"
+ ],
+ "ERANAMES": [
+ "Me\u00edn\u014d Y\u025b\u0301s\u0289",
+ "E\u00edn\u014d Y\u025b\u0301s\u0289"
+ ],
+ "ERAS": [
+ "MY",
+ "EY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Oladal\u0289\u0301",
+ "Ar\u00e1t",
+ "\u0186\u025bn\u0268\u0301\u0254\u0268\u014b\u0254k",
+ "Olodoy\u00ed\u00f3r\u00ed\u00ea ink\u00f3k\u00fa\u00e2",
+ "Oloil\u00e9p\u016bny\u012b\u0113 ink\u00f3k\u00fa\u00e2",
+ "K\u00faj\u00fa\u0254r\u0254k",
+ "M\u00f3rus\u00e1sin",
+ "\u0186l\u0254\u0301\u0268\u0301b\u0254\u0301r\u00e1r\u025b",
+ "K\u00fash\u00een",
+ "Olg\u00edsan",
+ "P\u0289sh\u0289\u0301ka",
+ "Nt\u0289\u0301\u014b\u0289\u0301s"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Dal",
+ "Ar\u00e1",
+ "\u0186\u025bn",
+ "Doy",
+ "L\u00e9p",
+ "Rok",
+ "S\u00e1s",
+ "B\u0254\u0301r",
+ "K\u00fas",
+ "G\u00eds",
+ "Sh\u0289\u0301",
+ "Nt\u0289\u0301"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mas-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas.js
new file mode 100644
index 00000000..16938f98
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mas.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0190nkak\u025bny\u00e1",
+ "\u0190nd\u00e1m\u00e2"
+ ],
+ "DAY": [
+ "Jumap\u00edl\u00ed",
+ "Jumat\u00e1tu",
+ "Jumane",
+ "Jumat\u00e1n\u0254",
+ "Ala\u00e1misi",
+ "Jum\u00e1a",
+ "Jumam\u00f3si"
+ ],
+ "ERANAMES": [
+ "Me\u00edn\u014d Y\u025b\u0301s\u0289",
+ "E\u00edn\u014d Y\u025b\u0301s\u0289"
+ ],
+ "ERAS": [
+ "MY",
+ "EY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Oladal\u0289\u0301",
+ "Ar\u00e1t",
+ "\u0186\u025bn\u0268\u0301\u0254\u0268\u014b\u0254k",
+ "Olodoy\u00ed\u00f3r\u00ed\u00ea ink\u00f3k\u00fa\u00e2",
+ "Oloil\u00e9p\u016bny\u012b\u0113 ink\u00f3k\u00fa\u00e2",
+ "K\u00faj\u00fa\u0254r\u0254k",
+ "M\u00f3rus\u00e1sin",
+ "\u0186l\u0254\u0301\u0268\u0301b\u0254\u0301r\u00e1r\u025b",
+ "K\u00fash\u00een",
+ "Olg\u00edsan",
+ "P\u0289sh\u0289\u0301ka",
+ "Nt\u0289\u0301\u014b\u0289\u0301s"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Dal",
+ "Ar\u00e1",
+ "\u0186\u025bn",
+ "Doy",
+ "L\u00e9p",
+ "Rok",
+ "S\u00e1s",
+ "B\u0254\u0301r",
+ "K\u00fas",
+ "G\u00eds",
+ "Sh\u0289\u0301",
+ "Nt\u0289\u0301"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mas",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer-ke.js
new file mode 100644
index 00000000..da3e57d0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "R\u0168",
+ "\u0168G"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Muramuko",
+ "Wairi",
+ "Wethatu",
+ "Wena",
+ "Wetano",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Mbere ya Krist\u0169",
+ "Nyuma ya Krist\u0169"
+ ],
+ "ERAS": [
+ "MK",
+ "NK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar\u0129",
+ "Feburuar\u0129",
+ "Machi",
+ "\u0128pur\u0169",
+ "M\u0129\u0129",
+ "Njuni",
+ "Njura\u0129",
+ "Agasti",
+ "Septemba",
+ "Okt\u0169ba",
+ "Novemba",
+ "Dicemba"
+ ],
+ "SHORTDAY": [
+ "KIU",
+ "MRA",
+ "WAI",
+ "WET",
+ "WEN",
+ "WTN",
+ "JUM"
+ ],
+ "SHORTMONTH": [
+ "JAN",
+ "FEB",
+ "MAC",
+ "\u0128PU",
+ "M\u0128\u0128",
+ "NJU",
+ "NJR",
+ "AGA",
+ "SPT",
+ "OKT",
+ "NOV",
+ "DEC"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mer-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer.js
new file mode 100644
index 00000000..8c359f30
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mer.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "R\u0168",
+ "\u0168G"
+ ],
+ "DAY": [
+ "Kiumia",
+ "Muramuko",
+ "Wairi",
+ "Wethatu",
+ "Wena",
+ "Wetano",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Mbere ya Krist\u0169",
+ "Nyuma ya Krist\u0169"
+ ],
+ "ERAS": [
+ "MK",
+ "NK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januar\u0129",
+ "Feburuar\u0129",
+ "Machi",
+ "\u0128pur\u0169",
+ "M\u0129\u0129",
+ "Njuni",
+ "Njura\u0129",
+ "Agasti",
+ "Septemba",
+ "Okt\u0169ba",
+ "Novemba",
+ "Dicemba"
+ ],
+ "SHORTDAY": [
+ "KIU",
+ "MRA",
+ "WAI",
+ "WET",
+ "WEN",
+ "WTN",
+ "JUM"
+ ],
+ "SHORTMONTH": [
+ "JAN",
+ "FEB",
+ "MAC",
+ "\u0128PU",
+ "M\u0128\u0128",
+ "NJU",
+ "NJR",
+ "AGA",
+ "SPT",
+ "OKT",
+ "NOV",
+ "DEC"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mer",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe-mu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe-mu.js
new file mode 100644
index 00000000..1222582e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe-mu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimans",
+ "lindi",
+ "mardi",
+ "merkredi",
+ "zedi",
+ "vandredi",
+ "samdi"
+ ],
+ "ERANAMES": [
+ "avan Zezi-Krist",
+ "apre Zezi-Krist"
+ ],
+ "ERAS": [
+ "av. Z-K",
+ "ap. Z-K"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "zanvie",
+ "fevriye",
+ "mars",
+ "avril",
+ "me",
+ "zin",
+ "zilye",
+ "out",
+ "septam",
+ "oktob",
+ "novam",
+ "desam"
+ ],
+ "SHORTDAY": [
+ "dim",
+ "lin",
+ "mar",
+ "mer",
+ "ze",
+ "van",
+ "sam"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "fev",
+ "mar",
+ "avr",
+ "me",
+ "zin",
+ "zil",
+ "out",
+ "sep",
+ "okt",
+ "nov",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MURs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mfe-mu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe.js
new file mode 100644
index 00000000..56029318
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mfe.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "dimans",
+ "lindi",
+ "mardi",
+ "merkredi",
+ "zedi",
+ "vandredi",
+ "samdi"
+ ],
+ "ERANAMES": [
+ "avan Zezi-Krist",
+ "apre Zezi-Krist"
+ ],
+ "ERAS": [
+ "av. Z-K",
+ "ap. Z-K"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "zanvie",
+ "fevriye",
+ "mars",
+ "avril",
+ "me",
+ "zin",
+ "zilye",
+ "out",
+ "septam",
+ "oktob",
+ "novam",
+ "desam"
+ ],
+ "SHORTDAY": [
+ "dim",
+ "lin",
+ "mar",
+ "mer",
+ "ze",
+ "van",
+ "sam"
+ ],
+ "SHORTMONTH": [
+ "zan",
+ "fev",
+ "mar",
+ "avr",
+ "me",
+ "zin",
+ "zil",
+ "out",
+ "sep",
+ "okt",
+ "nov",
+ "des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MURs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mfe",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg-mg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg-mg.js
new file mode 100644
index 00000000..7d649917
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg-mg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Alahady",
+ "Alatsinainy",
+ "Talata",
+ "Alarobia",
+ "Alakamisy",
+ "Zoma",
+ "Asabotsy"
+ ],
+ "ERANAMES": [
+ "Alohan\u2019i JK",
+ "Aorian\u2019i JK"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janoary",
+ "Febroary",
+ "Martsa",
+ "Aprily",
+ "Mey",
+ "Jona",
+ "Jolay",
+ "Aogositra",
+ "Septambra",
+ "Oktobra",
+ "Novambra",
+ "Desambra"
+ ],
+ "SHORTDAY": [
+ "Alah",
+ "Alats",
+ "Tal",
+ "Alar",
+ "Alak",
+ "Zom",
+ "Asab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mey",
+ "Jon",
+ "Jol",
+ "Aog",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ar",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mg-mg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg.js
new file mode 100644
index 00000000..7b4b8716
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Alahady",
+ "Alatsinainy",
+ "Talata",
+ "Alarobia",
+ "Alakamisy",
+ "Zoma",
+ "Asabotsy"
+ ],
+ "ERANAMES": [
+ "Alohan\u2019i JK",
+ "Aorian\u2019i JK"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janoary",
+ "Febroary",
+ "Martsa",
+ "Aprily",
+ "Mey",
+ "Jona",
+ "Jolay",
+ "Aogositra",
+ "Septambra",
+ "Oktobra",
+ "Novambra",
+ "Desambra"
+ ],
+ "SHORTDAY": [
+ "Alah",
+ "Alats",
+ "Tal",
+ "Alar",
+ "Alak",
+ "Zom",
+ "Asab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "Mey",
+ "Jon",
+ "Jol",
+ "Aog",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ar",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh-mz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh-mz.js
new file mode 100644
index 00000000..3a96657c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh-mz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "wichishu",
+ "mchochil\u2019l"
+ ],
+ "DAY": [
+ "Sabato",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Arahamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Hinapiya yesu",
+ "Yopia yesu"
+ ],
+ "ERAS": [
+ "HY",
+ "YY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wo kwanza",
+ "Mweri wo unayeli",
+ "Mweri wo uneraru",
+ "Mweri wo unecheshe",
+ "Mweri wo unethanu",
+ "Mweri wo thanu na mocha",
+ "Mweri wo saba",
+ "Mweri wo nane",
+ "Mweri wo tisa",
+ "Mweri wo kumi",
+ "Mweri wo kumi na moja",
+ "Mweri wo kumi na yel\u2019li"
+ ],
+ "SHORTDAY": [
+ "Sab",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Ara",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Kwa",
+ "Una",
+ "Rar",
+ "Che",
+ "Tha",
+ "Moc",
+ "Sab",
+ "Nan",
+ "Tis",
+ "Kum",
+ "Moj",
+ "Yel"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MTn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mgh-mz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh.js
new file mode 100644
index 00000000..8b52d094
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "wichishu",
+ "mchochil\u2019l"
+ ],
+ "DAY": [
+ "Sabato",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Arahamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Hinapiya yesu",
+ "Yopia yesu"
+ ],
+ "ERAS": [
+ "HY",
+ "YY"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wo kwanza",
+ "Mweri wo unayeli",
+ "Mweri wo uneraru",
+ "Mweri wo unecheshe",
+ "Mweri wo unethanu",
+ "Mweri wo thanu na mocha",
+ "Mweri wo saba",
+ "Mweri wo nane",
+ "Mweri wo tisa",
+ "Mweri wo kumi",
+ "Mweri wo kumi na moja",
+ "Mweri wo kumi na yel\u2019li"
+ ],
+ "SHORTDAY": [
+ "Sab",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Ara",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Kwa",
+ "Una",
+ "Rar",
+ "Che",
+ "Tha",
+ "Moc",
+ "Sab",
+ "Nan",
+ "Tis",
+ "Kum",
+ "Moj",
+ "Yel"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MTn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mgh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo-cm.js
new file mode 100644
index 00000000..da0baa9d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Aneg 1",
+ "Aneg 2",
+ "Aneg 3",
+ "Aneg 4",
+ "Aneg 5",
+ "Aneg 6",
+ "Aneg 7"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "im\u0259g mbegtug",
+ "imeg \u00e0b\u00f9b\u00ec",
+ "imeg mb\u0259\u014bchubi",
+ "im\u0259g ngw\u0259\u0300t",
+ "im\u0259g fog",
+ "im\u0259g ichiib\u0254d",
+ "im\u0259g \u00e0d\u00f9mb\u0259\u0300\u014b",
+ "im\u0259g ichika",
+ "im\u0259g kud",
+ "im\u0259g t\u00e8si\u02bce",
+ "im\u0259g z\u00f2",
+ "im\u0259g krizmed"
+ ],
+ "SHORTDAY": [
+ "Aneg 1",
+ "Aneg 2",
+ "Aneg 3",
+ "Aneg 4",
+ "Aneg 5",
+ "Aneg 6",
+ "Aneg 7"
+ ],
+ "SHORTMONTH": [
+ "mbegtug",
+ "imeg \u00e0b\u00f9b\u00ec",
+ "imeg mb\u0259\u014bchubi",
+ "im\u0259g ngw\u0259\u0300t",
+ "im\u0259g fog",
+ "im\u0259g ichiib\u0254d",
+ "im\u0259g \u00e0d\u00f9mb\u0259\u0300\u014b",
+ "im\u0259g ichika",
+ "im\u0259g kud",
+ "im\u0259g t\u00e8si\u02bce",
+ "im\u0259g z\u00f2",
+ "im\u0259g krizmed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mgo-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo.js
new file mode 100644
index 00000000..74bc53ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mgo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Aneg 1",
+ "Aneg 2",
+ "Aneg 3",
+ "Aneg 4",
+ "Aneg 5",
+ "Aneg 6",
+ "Aneg 7"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "im\u0259g mbegtug",
+ "imeg \u00e0b\u00f9b\u00ec",
+ "imeg mb\u0259\u014bchubi",
+ "im\u0259g ngw\u0259\u0300t",
+ "im\u0259g fog",
+ "im\u0259g ichiib\u0254d",
+ "im\u0259g \u00e0d\u00f9mb\u0259\u0300\u014b",
+ "im\u0259g ichika",
+ "im\u0259g kud",
+ "im\u0259g t\u00e8si\u02bce",
+ "im\u0259g z\u00f2",
+ "im\u0259g krizmed"
+ ],
+ "SHORTDAY": [
+ "Aneg 1",
+ "Aneg 2",
+ "Aneg 3",
+ "Aneg 4",
+ "Aneg 5",
+ "Aneg 6",
+ "Aneg 7"
+ ],
+ "SHORTMONTH": [
+ "mbegtug",
+ "imeg \u00e0b\u00f9b\u00ec",
+ "imeg mb\u0259\u014bchubi",
+ "im\u0259g ngw\u0259\u0300t",
+ "im\u0259g fog",
+ "im\u0259g ichiib\u0254d",
+ "im\u0259g \u00e0d\u00f9mb\u0259\u0300\u014b",
+ "im\u0259g ichika",
+ "im\u0259g kud",
+ "im\u0259g t\u00e8si\u02bce",
+ "im\u0259g z\u00f2",
+ "im\u0259g krizmed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mgo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk-mk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk-mk.js
new file mode 100644
index 00000000..bd775d86
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk-mk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435\u0442\u043f\u043b\u0430\u0434\u043d\u0435",
+ "\u043f\u043e\u043f\u043b\u0430\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u043b\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u043e\u043a",
+ "\u043f\u0435\u0442\u043e\u043a",
+ "\u0441\u0430\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u043f\u0440\u0435\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430",
+ "\u043e\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430"
+ ],
+ "ERAS": [
+ "\u043f\u0440.\u043d.\u0435.",
+ "\u043d.\u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438",
+ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d\u0438",
+ "\u0458\u0443\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438",
+ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
+ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
+ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434.",
+ "\u043f\u043e\u043d.",
+ "\u0432\u0442.",
+ "\u0441\u0440\u0435.",
+ "\u0447\u0435\u0442.",
+ "\u043f\u0435\u0442.",
+ "\u0441\u0430\u0431."
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d.",
+ "\u0458\u0443\u043b.",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043f\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u0435\u043c.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd.M.y HH:mm:ss",
+ "mediumDate": "dd.M.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.M.yy HH:mm",
+ "shortDate": "dd.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mk-mk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 || vf.f % 10 == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk.js
new file mode 100644
index 00000000..b456dc6e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435\u0442\u043f\u043b\u0430\u0434\u043d\u0435",
+ "\u043f\u043e\u043f\u043b\u0430\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u043b\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u043e\u043a",
+ "\u043f\u0435\u0442\u043e\u043a",
+ "\u0441\u0430\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u043f\u0440\u0435\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430",
+ "\u043e\u0434 \u043d\u0430\u0448\u0430\u0442\u0430 \u0435\u0440\u0430"
+ ],
+ "ERAS": [
+ "\u043f\u0440.\u043d.\u0435.",
+ "\u043d.\u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438",
+ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d\u0438",
+ "\u0458\u0443\u043b\u0438",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438",
+ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
+ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
+ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434.",
+ "\u043f\u043e\u043d.",
+ "\u0432\u0442.",
+ "\u0441\u0440\u0435.",
+ "\u0447\u0435\u0442.",
+ "\u043f\u0435\u0442.",
+ "\u0441\u0430\u0431."
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d.",
+ "\u0458\u0443\u043b.",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043f\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u0435\u043c.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "dd MMMM y",
+ "medium": "dd.M.y HH:mm:ss",
+ "mediumDate": "dd.M.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.M.yy HH:mm",
+ "shortDate": "dd.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 || vf.f % 10 == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml-in.js
new file mode 100644
index 00000000..c3d012ff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0d1e\u0d3e\u0d2f\u0d31\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d33\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d1a\u0d4a\u0d35\u0d4d\u0d35\u0d3e\u0d34\u0d4d\u0d1a",
+ "\u0d2c\u0d41\u0d27\u0d28\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d36\u0d28\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a"
+ ],
+ "ERANAMES": [
+ "\u0d15\u0d4d\u0d30\u0d3f\u0d38\u0d4d\u200c\u0d24\u0d41\u0d35\u0d3f\u0d28\u0d4d \u0d2e\u0d41\u0d2e\u0d4d\u0d2a\u0d4d",
+ "\u0d06\u0d28\u0d4d\u0d28\u0d4b \u0d21\u0d4a\u0d2e\u0d3f\u0d28\u0d3f"
+ ],
+ "ERAS": [
+ "\u0d15\u0d4d\u0d30\u0d3f.\u0d2e\u0d41.",
+ "\u0d0e\u0d21\u0d3f"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f",
+ "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41\u0d35\u0d30\u0d3f",
+ "\u0d2e\u0d3e\u0d7c\u0d1a\u0d4d\u0d1a\u0d4d",
+ "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f\u0d7d",
+ "\u0d2e\u0d47\u0d2f\u0d4d",
+ "\u0d1c\u0d42\u0d7a",
+ "\u0d1c\u0d42\u0d32\u0d48",
+ "\u0d06\u0d17\u0d38\u0d4d\u0d31\u0d4d\u0d31\u0d4d",
+ "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02\u0d2c\u0d7c",
+ "\u0d12\u0d15\u0d4d\u200c\u0d1f\u0d4b\u0d2c\u0d7c",
+ "\u0d28\u0d35\u0d02\u0d2c\u0d7c",
+ "\u0d21\u0d3f\u0d38\u0d02\u0d2c\u0d7c"
+ ],
+ "SHORTDAY": [
+ "\u0d1e\u0d3e\u0d2f\u0d7c",
+ "\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d7e",
+ "\u0d1a\u0d4a\u0d35\u0d4d\u0d35",
+ "\u0d2c\u0d41\u0d27\u0d7b",
+ "\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d02",
+ "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f",
+ "\u0d36\u0d28\u0d3f"
+ ],
+ "SHORTMONTH": [
+ "\u0d1c\u0d28\u0d41",
+ "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41",
+ "\u0d2e\u0d3e\u0d7c",
+ "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f",
+ "\u0d2e\u0d47\u0d2f\u0d4d",
+ "\u0d1c\u0d42\u0d7a",
+ "\u0d1c\u0d42\u0d32\u0d48",
+ "\u0d13\u0d17",
+ "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02",
+ "\u0d12\u0d15\u0d4d\u0d1f\u0d4b",
+ "\u0d28\u0d35\u0d02",
+ "\u0d21\u0d3f\u0d38\u0d02"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "y, MMMM d, EEEE",
+ "longDate": "y, MMMM d",
+ "medium": "y, MMM d h:mm:ss a",
+ "mediumDate": "y, MMM d",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ml-in",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml.js
new file mode 100644
index 00000000..8d50656e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ml.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0d1e\u0d3e\u0d2f\u0d31\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d33\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d1a\u0d4a\u0d35\u0d4d\u0d35\u0d3e\u0d34\u0d4d\u0d1a",
+ "\u0d2c\u0d41\u0d27\u0d28\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a",
+ "\u0d36\u0d28\u0d3f\u0d2f\u0d3e\u0d34\u0d4d\u200c\u0d1a"
+ ],
+ "ERANAMES": [
+ "\u0d15\u0d4d\u0d30\u0d3f\u0d38\u0d4d\u200c\u0d24\u0d41\u0d35\u0d3f\u0d28\u0d4d \u0d2e\u0d41\u0d2e\u0d4d\u0d2a\u0d4d",
+ "\u0d06\u0d28\u0d4d\u0d28\u0d4b \u0d21\u0d4a\u0d2e\u0d3f\u0d28\u0d3f"
+ ],
+ "ERAS": [
+ "\u0d15\u0d4d\u0d30\u0d3f.\u0d2e\u0d41.",
+ "\u0d0e\u0d21\u0d3f"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f",
+ "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41\u0d35\u0d30\u0d3f",
+ "\u0d2e\u0d3e\u0d7c\u0d1a\u0d4d\u0d1a\u0d4d",
+ "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f\u0d7d",
+ "\u0d2e\u0d47\u0d2f\u0d4d",
+ "\u0d1c\u0d42\u0d7a",
+ "\u0d1c\u0d42\u0d32\u0d48",
+ "\u0d06\u0d17\u0d38\u0d4d\u0d31\u0d4d\u0d31\u0d4d",
+ "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02\u0d2c\u0d7c",
+ "\u0d12\u0d15\u0d4d\u200c\u0d1f\u0d4b\u0d2c\u0d7c",
+ "\u0d28\u0d35\u0d02\u0d2c\u0d7c",
+ "\u0d21\u0d3f\u0d38\u0d02\u0d2c\u0d7c"
+ ],
+ "SHORTDAY": [
+ "\u0d1e\u0d3e\u0d2f\u0d7c",
+ "\u0d24\u0d3f\u0d19\u0d4d\u0d15\u0d7e",
+ "\u0d1a\u0d4a\u0d35\u0d4d\u0d35",
+ "\u0d2c\u0d41\u0d27\u0d7b",
+ "\u0d35\u0d4d\u0d2f\u0d3e\u0d34\u0d02",
+ "\u0d35\u0d46\u0d33\u0d4d\u0d33\u0d3f",
+ "\u0d36\u0d28\u0d3f"
+ ],
+ "SHORTMONTH": [
+ "\u0d1c\u0d28\u0d41",
+ "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41",
+ "\u0d2e\u0d3e\u0d7c",
+ "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f",
+ "\u0d2e\u0d47\u0d2f\u0d4d",
+ "\u0d1c\u0d42\u0d7a",
+ "\u0d1c\u0d42\u0d32\u0d48",
+ "\u0d13\u0d17",
+ "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02",
+ "\u0d12\u0d15\u0d4d\u0d1f\u0d4b",
+ "\u0d28\u0d35\u0d02",
+ "\u0d21\u0d3f\u0d38\u0d02"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "y, MMMM d, EEEE",
+ "longDate": "y, MMMM d",
+ "medium": "y, MMM d h:mm:ss a",
+ "mediumDate": "y, MMM d",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ml",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl-mn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl-mn.js
new file mode 100644
index 00000000..961fdd2c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl-mn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04ae\u04e8",
+ "\u04ae\u0425"
+ ],
+ "DAY": [
+ "\u043d\u044f\u043c",
+ "\u0434\u0430\u0432\u0430\u0430",
+ "\u043c\u044f\u0433\u043c\u0430\u0440",
+ "\u043b\u0445\u0430\u0433\u0432\u0430",
+ "\u043f\u04af\u0440\u044d\u0432",
+ "\u0431\u0430\u0430\u0441\u0430\u043d",
+ "\u0431\u044f\u043c\u0431\u0430"
+ ],
+ "ERANAMES": [
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445",
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439"
+ ],
+ "ERAS": [
+ "\u041c\u042d\u04e8",
+ "\u041c\u042d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0425\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0413\u0443\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u04e9\u0440\u04e9\u0432\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0422\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0417\u0443\u0440\u0433\u0430\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u043e\u043b\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u041d\u0430\u0439\u043c\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0415\u0441\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u043d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u0445\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u041d\u044f",
+ "\u0414\u0430",
+ "\u041c\u044f",
+ "\u041b\u0445",
+ "\u041f\u04af",
+ "\u0411\u0430",
+ "\u0411\u044f"
+ ],
+ "SHORTMONTH": [
+ "1-\u0440 \u0441\u0430\u0440",
+ "2-\u0440 \u0441\u0430\u0440",
+ "3-\u0440 \u0441\u0430\u0440",
+ "4-\u0440 \u0441\u0430\u0440",
+ "5-\u0440 \u0441\u0430\u0440",
+ "6-\u0440 \u0441\u0430\u0440",
+ "7-\u0440 \u0441\u0430\u0440",
+ "8-\u0440 \u0441\u0430\u0440",
+ "9-\u0440 \u0441\u0430\u0440",
+ "10-\u0440 \u0441\u0430\u0440",
+ "11-\u0440 \u0441\u0430\u0440",
+ "12-\u0440 \u0441\u0430\u0440"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "longDate": "y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ae",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mn-cyrl-mn",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl.js
new file mode 100644
index 00000000..c69a40d3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn-cyrl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04ae\u04e8",
+ "\u04ae\u0425"
+ ],
+ "DAY": [
+ "\u043d\u044f\u043c",
+ "\u0434\u0430\u0432\u0430\u0430",
+ "\u043c\u044f\u0433\u043c\u0430\u0440",
+ "\u043b\u0445\u0430\u0433\u0432\u0430",
+ "\u043f\u04af\u0440\u044d\u0432",
+ "\u0431\u0430\u0430\u0441\u0430\u043d",
+ "\u0431\u044f\u043c\u0431\u0430"
+ ],
+ "ERANAMES": [
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445",
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439"
+ ],
+ "ERAS": [
+ "\u041c\u042d\u04e8",
+ "\u041c\u042d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0425\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0413\u0443\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u04e9\u0440\u04e9\u0432\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0422\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0417\u0443\u0440\u0433\u0430\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u043e\u043b\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u041d\u0430\u0439\u043c\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0415\u0441\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u043d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u0445\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u041d\u044f",
+ "\u0414\u0430",
+ "\u041c\u044f",
+ "\u041b\u0445",
+ "\u041f\u04af",
+ "\u0411\u0430",
+ "\u0411\u044f"
+ ],
+ "SHORTMONTH": [
+ "1-\u0440 \u0441\u0430\u0440",
+ "2-\u0440 \u0441\u0430\u0440",
+ "3-\u0440 \u0441\u0430\u0440",
+ "4-\u0440 \u0441\u0430\u0440",
+ "5-\u0440 \u0441\u0430\u0440",
+ "6-\u0440 \u0441\u0430\u0440",
+ "7-\u0440 \u0441\u0430\u0440",
+ "8-\u0440 \u0441\u0430\u0440",
+ "9-\u0440 \u0441\u0430\u0440",
+ "10-\u0440 \u0441\u0430\u0440",
+ "11-\u0440 \u0441\u0430\u0440",
+ "12-\u0440 \u0441\u0430\u0440"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "longDate": "y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ae",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mn-cyrl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn.js
new file mode 100644
index 00000000..0b424093
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04ae\u04e8",
+ "\u04ae\u0425"
+ ],
+ "DAY": [
+ "\u043d\u044f\u043c",
+ "\u0434\u0430\u0432\u0430\u0430",
+ "\u043c\u044f\u0433\u043c\u0430\u0440",
+ "\u043b\u0445\u0430\u0433\u0432\u0430",
+ "\u043f\u04af\u0440\u044d\u0432",
+ "\u0431\u0430\u0430\u0441\u0430\u043d",
+ "\u0431\u044f\u043c\u0431\u0430"
+ ],
+ "ERANAMES": [
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439 \u04e9\u043c\u043d\u04e9\u0445",
+ "\u043c\u0430\u043d\u0430\u0439 \u044d\u0440\u0438\u043d\u0438\u0439"
+ ],
+ "ERAS": [
+ "\u041c\u042d\u04e8",
+ "\u041c\u042d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u041d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0425\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0413\u0443\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u04e9\u0440\u04e9\u0432\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0422\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0417\u0443\u0440\u0433\u0430\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0414\u043e\u043b\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u041d\u0430\u0439\u043c\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0415\u0441\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0430\u0432\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u043d\u044d\u0433\u0434\u04af\u0433\u044d\u044d\u0440 \u0441\u0430\u0440",
+ "\u0410\u0440\u0432\u0430\u043d \u0445\u043e\u0451\u0440\u0434\u0443\u0433\u0430\u0430\u0440 \u0441\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u041d\u044f",
+ "\u0414\u0430",
+ "\u041c\u044f",
+ "\u041b\u0445",
+ "\u041f\u04af",
+ "\u0411\u0430",
+ "\u0411\u044f"
+ ],
+ "SHORTMONTH": [
+ "1-\u0440 \u0441\u0430\u0440",
+ "2-\u0440 \u0441\u0430\u0440",
+ "3-\u0440 \u0441\u0430\u0440",
+ "4-\u0440 \u0441\u0430\u0440",
+ "5-\u0440 \u0441\u0430\u0440",
+ "6-\u0440 \u0441\u0430\u0440",
+ "7-\u0440 \u0441\u0430\u0440",
+ "8-\u0440 \u0441\u0430\u0440",
+ "9-\u0440 \u0441\u0430\u0440",
+ "10-\u0440 \u0441\u0430\u0440",
+ "11-\u0440 \u0441\u0430\u0440",
+ "12-\u0440 \u0441\u0430\u0440"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "longDate": "y '\u043e\u043d\u044b' MM '\u0441\u0430\u0440\u044b\u043d' d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ae",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mn",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr-in.js
new file mode 100644
index 00000000..b040d89d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092e.\u092a\u0942.",
+ "\u092e.\u0909."
+ ],
+ "DAY": [
+ "\u0930\u0935\u093f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u0935\u0940\u0938\u0928\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u0935\u0940\u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0907. \u0938. \u092a\u0942.",
+ "\u0907. \u0938."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0911\u0917\u0938\u094d\u091f",
+ "\u0938\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0911\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0933",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0947",
+ "\u092b\u0947\u092c\u094d\u0930\u0941",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0911\u0917",
+ "\u0938\u092a\u094d\u091f\u0947\u0902",
+ "\u0911\u0915\u094d\u091f\u094b",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902",
+ "\u0921\u093f\u0938\u0947\u0902"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mr-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr.js
new file mode 100644
index 00000000..5f5847df
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092e.\u092a\u0942.",
+ "\u092e.\u0909."
+ ],
+ "DAY": [
+ "\u0930\u0935\u093f\u0935\u093e\u0930",
+ "\u0938\u094b\u092e\u0935\u093e\u0930",
+ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930",
+ "\u092c\u0941\u0927\u0935\u093e\u0930",
+ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930",
+ "\u0936\u0928\u093f\u0935\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u0935\u0940\u0938\u0928\u092a\u0942\u0930\u094d\u0935",
+ "\u0908\u0938\u0935\u0940\u0938\u0928"
+ ],
+ "ERAS": [
+ "\u0907. \u0938. \u092a\u0942.",
+ "\u0907. \u0938."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0911\u0917\u0938\u094d\u091f",
+ "\u0938\u092a\u094d\u091f\u0947\u0902\u092c\u0930",
+ "\u0911\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0930\u0935\u093f",
+ "\u0938\u094b\u092e",
+ "\u092e\u0902\u0917\u0933",
+ "\u092c\u0941\u0927",
+ "\u0917\u0941\u0930\u0941",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u093e\u0928\u0947",
+ "\u092b\u0947\u092c\u094d\u0930\u0941",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u090f\u092a\u094d\u0930\u093f",
+ "\u092e\u0947",
+ "\u091c\u0942\u0928",
+ "\u091c\u0941\u0932\u0948",
+ "\u0911\u0917",
+ "\u0938\u092a\u094d\u091f\u0947\u0902",
+ "\u0911\u0915\u094d\u091f\u094b",
+ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902",
+ "\u0921\u093f\u0938\u0947\u0902"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-bn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-bn.js
new file mode 100644
index 00000000..1bc9d07c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-bn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "PG",
+ "PTG"
+ ],
+ "DAY": [
+ "Ahad",
+ "Isnin",
+ "Selasa",
+ "Rabu",
+ "Khamis",
+ "Jumaat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "S.M.",
+ "TM"
+ ],
+ "ERAS": [
+ "S.M.",
+ "TM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Mac",
+ "April",
+ "Mei",
+ "Jun",
+ "Julai",
+ "Ogos",
+ "September",
+ "Oktober",
+ "November",
+ "Disember"
+ ],
+ "SHORTDAY": [
+ "Ahd",
+ "Isn",
+ "Sel",
+ "Rab",
+ "Kha",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ogo",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ms-latn-bn",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-my.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-my.js
new file mode 100644
index 00000000..5177e15f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-my.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "PG",
+ "PTG"
+ ],
+ "DAY": [
+ "Ahad",
+ "Isnin",
+ "Selasa",
+ "Rabu",
+ "Khamis",
+ "Jumaat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "S.M.",
+ "TM"
+ ],
+ "ERAS": [
+ "S.M.",
+ "TM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Mac",
+ "April",
+ "Mei",
+ "Jun",
+ "Julai",
+ "Ogos",
+ "September",
+ "Oktober",
+ "November",
+ "Disember"
+ ],
+ "SHORTDAY": [
+ "Ahd",
+ "Isn",
+ "Sel",
+ "Rab",
+ "Kha",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ogo",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RM",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ms-latn-my",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-sg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-sg.js
new file mode 100644
index 00000000..ebd3bd4c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn-sg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "PG",
+ "PTG"
+ ],
+ "DAY": [
+ "Ahad",
+ "Isnin",
+ "Selasa",
+ "Rabu",
+ "Khamis",
+ "Jumaat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "S.M.",
+ "TM"
+ ],
+ "ERAS": [
+ "S.M.",
+ "TM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Mac",
+ "April",
+ "Mei",
+ "Jun",
+ "Julai",
+ "Ogos",
+ "September",
+ "Oktober",
+ "November",
+ "Disember"
+ ],
+ "SHORTDAY": [
+ "Ahd",
+ "Isn",
+ "Sel",
+ "Rab",
+ "Kha",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ogo",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ms-latn-sg",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn.js
new file mode 100644
index 00000000..2d4c07a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms-latn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "PG",
+ "PTG"
+ ],
+ "DAY": [
+ "Ahad",
+ "Isnin",
+ "Selasa",
+ "Rabu",
+ "Khamis",
+ "Jumaat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "S.M.",
+ "TM"
+ ],
+ "ERAS": [
+ "S.M.",
+ "TM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Mac",
+ "April",
+ "Mei",
+ "Jun",
+ "Julai",
+ "Ogos",
+ "September",
+ "Oktober",
+ "November",
+ "Disember"
+ ],
+ "SHORTDAY": [
+ "Ahd",
+ "Isn",
+ "Sel",
+ "Rab",
+ "Kha",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ogo",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RM",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ms-latn",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms.js
new file mode 100644
index 00000000..0549f85b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ms.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "PG",
+ "PTG"
+ ],
+ "DAY": [
+ "Ahad",
+ "Isnin",
+ "Selasa",
+ "Rabu",
+ "Khamis",
+ "Jumaat",
+ "Sabtu"
+ ],
+ "ERANAMES": [
+ "S.M.",
+ "TM"
+ ],
+ "ERAS": [
+ "S.M.",
+ "TM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Mac",
+ "April",
+ "Mei",
+ "Jun",
+ "Julai",
+ "Ogos",
+ "September",
+ "Oktober",
+ "November",
+ "Disember"
+ ],
+ "SHORTDAY": [
+ "Ahd",
+ "Isn",
+ "Sel",
+ "Rab",
+ "Kha",
+ "Jum",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ogo",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/yy h:mm a",
+ "shortDate": "d/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RM",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ms",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt-mt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt-mt.js
new file mode 100644
index 00000000..20170a1a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt-mt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Il-\u0126add",
+ "It-Tnejn",
+ "It-Tlieta",
+ "L-Erbg\u0127a",
+ "Il-\u0126amis",
+ "Il-\u0120img\u0127a",
+ "Is-Sibt"
+ ],
+ "ERANAMES": [
+ "Qabel Kristu",
+ "Wara Kristu"
+ ],
+ "ERAS": [
+ "QK",
+ "WK"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Jannar",
+ "Frar",
+ "Marzu",
+ "April",
+ "Mejju",
+ "\u0120unju",
+ "Lulju",
+ "Awwissu",
+ "Settembru",
+ "Ottubru",
+ "Novembru",
+ "Di\u010bembru"
+ ],
+ "SHORTDAY": [
+ "\u0126ad",
+ "Tne",
+ "Tli",
+ "Erb",
+ "\u0126am",
+ "\u0120im",
+ "Sib"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fra",
+ "Mar",
+ "Apr",
+ "Mej",
+ "\u0120un",
+ "Lul",
+ "Aww",
+ "Set",
+ "Ott",
+ "Nov",
+ "Di\u010b"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'ta'\u2019 MMMM y",
+ "longDate": "d 'ta'\u2019 MMMM y",
+ "medium": "dd MMM y HH:mm:ss",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mt-mt",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 0 || n % 100 >= 2 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 19) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt.js
new file mode 100644
index 00000000..94902b19
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Il-\u0126add",
+ "It-Tnejn",
+ "It-Tlieta",
+ "L-Erbg\u0127a",
+ "Il-\u0126amis",
+ "Il-\u0120img\u0127a",
+ "Is-Sibt"
+ ],
+ "ERANAMES": [
+ "Qabel Kristu",
+ "Wara Kristu"
+ ],
+ "ERAS": [
+ "QK",
+ "WK"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Jannar",
+ "Frar",
+ "Marzu",
+ "April",
+ "Mejju",
+ "\u0120unju",
+ "Lulju",
+ "Awwissu",
+ "Settembru",
+ "Ottubru",
+ "Novembru",
+ "Di\u010bembru"
+ ],
+ "SHORTDAY": [
+ "\u0126ad",
+ "Tne",
+ "Tli",
+ "Erb",
+ "\u0126am",
+ "\u0120im",
+ "Sib"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fra",
+ "Mar",
+ "Apr",
+ "Mej",
+ "\u0120un",
+ "Lul",
+ "Aww",
+ "Set",
+ "Ott",
+ "Nov",
+ "Di\u010b"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'ta'\u2019 MMMM y",
+ "longDate": "d 'ta'\u2019 MMMM y",
+ "medium": "dd MMM y HH:mm:ss",
+ "mediumDate": "dd MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mt",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 0 || n % 100 >= 2 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 19) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua-cm.js
new file mode 100644
index 00000000..49c1012d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "comme",
+ "lilli"
+ ],
+ "DAY": [
+ "Com\u2019yakke",
+ "Comlaa\u0257ii",
+ "Comzyii\u0257ii",
+ "Comkolle",
+ "Comkald\u01dd\u0253lii",
+ "Comgaisuu",
+ "Comzye\u0253suu"
+ ],
+ "ERANAMES": [
+ "K\u01ddPel Kristu",
+ "Pel Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "PK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "F\u0129i Loo",
+ "Cokcwakla\u014bne",
+ "Cokcwaklii",
+ "F\u0129i Marfoo",
+ "Mad\u01dd\u01dduut\u01ddbija\u014b",
+ "Mam\u01dd\u014bgw\u00e3afahbii",
+ "Mam\u01dd\u014bgw\u00e3alii",
+ "Mad\u01ddmbii",
+ "F\u0129i D\u01dd\u0253lii",
+ "F\u0129i Munda\u014b",
+ "F\u0129i Gwahlle",
+ "F\u0129i Yuru"
+ ],
+ "SHORTDAY": [
+ "Cya",
+ "Cla",
+ "Czi",
+ "Cko",
+ "Cka",
+ "Cga",
+ "Cze"
+ ],
+ "SHORTMONTH": [
+ "FLO",
+ "CLA",
+ "CKI",
+ "FMF",
+ "MAD",
+ "MBI",
+ "MLI",
+ "MAM",
+ "FDE",
+ "FMU",
+ "FGW",
+ "FYU"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mua-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua.js
new file mode 100644
index 00000000..c5f30a2f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_mua.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "comme",
+ "lilli"
+ ],
+ "DAY": [
+ "Com\u2019yakke",
+ "Comlaa\u0257ii",
+ "Comzyii\u0257ii",
+ "Comkolle",
+ "Comkald\u01dd\u0253lii",
+ "Comgaisuu",
+ "Comzye\u0253suu"
+ ],
+ "ERANAMES": [
+ "K\u01ddPel Kristu",
+ "Pel Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "PK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "F\u0129i Loo",
+ "Cokcwakla\u014bne",
+ "Cokcwaklii",
+ "F\u0129i Marfoo",
+ "Mad\u01dd\u01dduut\u01ddbija\u014b",
+ "Mam\u01dd\u014bgw\u00e3afahbii",
+ "Mam\u01dd\u014bgw\u00e3alii",
+ "Mad\u01ddmbii",
+ "F\u0129i D\u01dd\u0253lii",
+ "F\u0129i Munda\u014b",
+ "F\u0129i Gwahlle",
+ "F\u0129i Yuru"
+ ],
+ "SHORTDAY": [
+ "Cya",
+ "Cla",
+ "Czi",
+ "Cko",
+ "Cka",
+ "Cga",
+ "Cze"
+ ],
+ "SHORTMONTH": [
+ "FLO",
+ "CLA",
+ "CKI",
+ "FMF",
+ "MAD",
+ "MBI",
+ "MLI",
+ "MAM",
+ "FDE",
+ "FMU",
+ "FGW",
+ "FYU"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "mua",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my-mm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my-mm.js
new file mode 100644
index 00000000..d658ac96
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my-mm.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1014\u1036\u1014\u1000\u103a",
+ "\u100a\u1014\u1031"
+ ],
+ "DAY": [
+ "\u1010\u1014\u1004\u103a\u1039\u1002\u1014\u103d\u1031",
+ "\u1010\u1014\u1004\u103a\u1039\u101c\u102c",
+ "\u1021\u1004\u103a\u1039\u1002\u102b",
+ "\u1017\u102f\u1012\u1039\u1013\u101f\u1030\u1038",
+ "\u1000\u103c\u102c\u101e\u1015\u1010\u1031\u1038",
+ "\u101e\u1031\u102c\u1000\u103c\u102c",
+ "\u1005\u1014\u1031"
+ ],
+ "ERANAMES": [
+ "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1019\u1015\u1031\u102b\u103a\u1019\u102e\u1000\u102c\u101c",
+ "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1015\u1031\u102b\u103a\u1011\u103d\u1014\u103a\u1038\u1015\u103c\u102e\u1038\u1000\u102c\u101c"
+ ],
+ "ERAS": [
+ "\u1018\u102e\u1005\u102e",
+ "\u1021\u1031\u1012\u102e"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1007\u1014\u103a\u1014\u101d\u102b\u101b\u102e",
+ "\u1016\u1031\u1016\u1031\u102c\u103a\u101d\u102b\u101b\u102e",
+ "\u1019\u1010\u103a",
+ "\u1027\u1015\u103c\u102e",
+ "\u1019\u1031",
+ "\u1007\u103d\u1014\u103a",
+ "\u1007\u1030\u101c\u102d\u102f\u1004\u103a",
+ "\u1029\u1002\u102f\u1010\u103a",
+ "\u1005\u1000\u103a\u1010\u1004\u103a\u1018\u102c",
+ "\u1021\u1031\u102c\u1000\u103a\u1010\u102d\u102f\u1018\u102c",
+ "\u1014\u102d\u102f\u101d\u1004\u103a\u1018\u102c",
+ "\u1012\u102e\u1007\u1004\u103a\u1018\u102c"
+ ],
+ "SHORTDAY": [
+ "\u1010\u1014\u1004\u103a\u1039\u1002\u1014\u103d\u1031",
+ "\u1010\u1014\u1004\u103a\u1039\u101c\u102c",
+ "\u1021\u1004\u103a\u1039\u1002\u102b",
+ "\u1017\u102f\u1012\u1039\u1013\u101f\u1030\u1038",
+ "\u1000\u103c\u102c\u101e\u1015\u1010\u1031\u1038",
+ "\u101e\u1031\u102c\u1000\u103c\u102c",
+ "\u1005\u1014\u1031"
+ ],
+ "SHORTMONTH": [
+ "\u1007\u1014\u103a",
+ "\u1016\u1031",
+ "\u1019\u1010\u103a",
+ "\u1027\u1015\u103c\u102e",
+ "\u1019\u1031",
+ "\u1007\u103d\u1014\u103a",
+ "\u1007\u1030",
+ "\u1029",
+ "\u1005\u1000\u103a",
+ "\u1021\u1031\u102c\u1000\u103a",
+ "\u1014\u102d\u102f",
+ "\u1012\u102e"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u104a dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "K",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "my-mm",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my.js
new file mode 100644
index 00000000..7a6c02b4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_my.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1014\u1036\u1014\u1000\u103a",
+ "\u100a\u1014\u1031"
+ ],
+ "DAY": [
+ "\u1010\u1014\u1004\u103a\u1039\u1002\u1014\u103d\u1031",
+ "\u1010\u1014\u1004\u103a\u1039\u101c\u102c",
+ "\u1021\u1004\u103a\u1039\u1002\u102b",
+ "\u1017\u102f\u1012\u1039\u1013\u101f\u1030\u1038",
+ "\u1000\u103c\u102c\u101e\u1015\u1010\u1031\u1038",
+ "\u101e\u1031\u102c\u1000\u103c\u102c",
+ "\u1005\u1014\u1031"
+ ],
+ "ERANAMES": [
+ "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1019\u1015\u1031\u102b\u103a\u1019\u102e\u1000\u102c\u101c",
+ "\u1001\u101b\u1005\u103a\u1010\u1031\u102c\u103a \u1015\u1031\u102b\u103a\u1011\u103d\u1014\u103a\u1038\u1015\u103c\u102e\u1038\u1000\u102c\u101c"
+ ],
+ "ERAS": [
+ "\u1018\u102e\u1005\u102e",
+ "\u1021\u1031\u1012\u102e"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u1007\u1014\u103a\u1014\u101d\u102b\u101b\u102e",
+ "\u1016\u1031\u1016\u1031\u102c\u103a\u101d\u102b\u101b\u102e",
+ "\u1019\u1010\u103a",
+ "\u1027\u1015\u103c\u102e",
+ "\u1019\u1031",
+ "\u1007\u103d\u1014\u103a",
+ "\u1007\u1030\u101c\u102d\u102f\u1004\u103a",
+ "\u1029\u1002\u102f\u1010\u103a",
+ "\u1005\u1000\u103a\u1010\u1004\u103a\u1018\u102c",
+ "\u1021\u1031\u102c\u1000\u103a\u1010\u102d\u102f\u1018\u102c",
+ "\u1014\u102d\u102f\u101d\u1004\u103a\u1018\u102c",
+ "\u1012\u102e\u1007\u1004\u103a\u1018\u102c"
+ ],
+ "SHORTDAY": [
+ "\u1010\u1014\u1004\u103a\u1039\u1002\u1014\u103d\u1031",
+ "\u1010\u1014\u1004\u103a\u1039\u101c\u102c",
+ "\u1021\u1004\u103a\u1039\u1002\u102b",
+ "\u1017\u102f\u1012\u1039\u1013\u101f\u1030\u1038",
+ "\u1000\u103c\u102c\u101e\u1015\u1010\u1031\u1038",
+ "\u101e\u1031\u102c\u1000\u103c\u102c",
+ "\u1005\u1014\u1031"
+ ],
+ "SHORTMONTH": [
+ "\u1007\u1014\u103a",
+ "\u1016\u1031",
+ "\u1019\u1010\u103a",
+ "\u1027\u1015\u103c\u102e",
+ "\u1019\u1031",
+ "\u1007\u103d\u1014\u103a",
+ "\u1007\u1030",
+ "\u1029",
+ "\u1005\u1000\u103a",
+ "\u1021\u1031\u102c\u1000\u103a",
+ "\u1014\u102d\u102f",
+ "\u1012\u102e"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u104a dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "K",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "my",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq-na.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq-na.js
new file mode 100644
index 00000000..699ab621
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq-na.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u01c1goagas",
+ "\u01c3uias"
+ ],
+ "DAY": [
+ "Sontaxtsees",
+ "Mantaxtsees",
+ "Denstaxtsees",
+ "Wunstaxtsees",
+ "Dondertaxtsees",
+ "Fraitaxtsees",
+ "Satertaxtsees"
+ ],
+ "ERANAMES": [
+ "Xristub ai\u01c3\u00e2",
+ "Xristub khao\u01c3g\u00e2"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u01c3Khanni",
+ "\u01c3Khan\u01c0g\u00f4ab",
+ "\u01c0Khuu\u01c1kh\u00e2b",
+ "\u01c3H\u00f4a\u01c2khaib",
+ "\u01c3Khaits\u00e2b",
+ "Gama\u01c0aeb",
+ "\u01c2Khoesaob",
+ "Ao\u01c1khuum\u00fb\u01c1kh\u00e2b",
+ "Tara\u01c0khuum\u00fb\u01c1kh\u00e2b",
+ "\u01c2N\u00fb\u01c1n\u00e2iseb",
+ "\u01c0Hoo\u01c2gaeb",
+ "H\u00f4asore\u01c1kh\u00e2b"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Ma",
+ "De",
+ "Wu",
+ "Do",
+ "Fr",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "naq-na",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq.js
new file mode 100644
index 00000000..3c376cdb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_naq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u01c1goagas",
+ "\u01c3uias"
+ ],
+ "DAY": [
+ "Sontaxtsees",
+ "Mantaxtsees",
+ "Denstaxtsees",
+ "Wunstaxtsees",
+ "Dondertaxtsees",
+ "Fraitaxtsees",
+ "Satertaxtsees"
+ ],
+ "ERANAMES": [
+ "Xristub ai\u01c3\u00e2",
+ "Xristub khao\u01c3g\u00e2"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u01c3Khanni",
+ "\u01c3Khan\u01c0g\u00f4ab",
+ "\u01c0Khuu\u01c1kh\u00e2b",
+ "\u01c3H\u00f4a\u01c2khaib",
+ "\u01c3Khaits\u00e2b",
+ "Gama\u01c0aeb",
+ "\u01c2Khoesaob",
+ "Ao\u01c1khuum\u00fb\u01c1kh\u00e2b",
+ "Tara\u01c0khuum\u00fb\u01c1kh\u00e2b",
+ "\u01c2N\u00fb\u01c1n\u00e2iseb",
+ "\u01c0Hoo\u01c2gaeb",
+ "H\u00f4asore\u01c1kh\u00e2b"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Ma",
+ "De",
+ "Wu",
+ "Do",
+ "Fr",
+ "Sat"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "naq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-no.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-no.js
new file mode 100644
index 00000000..931bf639
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-no.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd.MM.y HH.mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nb-no",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-sj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-sj.js
new file mode 100644
index 00000000..487815bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb-sj.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd.MM.y HH.mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nb-sj",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb.js
new file mode 100644
index 00000000..61106d82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nb.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd.MM.y HH.mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nb",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd-zw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd-zw.js
new file mode 100644
index 00000000..b9ac5814
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd-zw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sonto",
+ "Mvulo",
+ "Sibili",
+ "Sithathu",
+ "Sine",
+ "Sihlanu",
+ "Mgqibelo"
+ ],
+ "ERANAMES": [
+ "UKristo angakabuyi",
+ "Ukristo ebuyile"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Zibandlela",
+ "Nhlolanja",
+ "Mbimbitho",
+ "Mabasa",
+ "Nkwenkwezi",
+ "Nhlangula",
+ "Ntulikazi",
+ "Ncwabakazi",
+ "Mpandula",
+ "Mfumfu",
+ "Lwezi",
+ "Mpalakazi"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mvu",
+ "Sib",
+ "Sit",
+ "Sin",
+ "Sih",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Zib",
+ "Nhlo",
+ "Mbi",
+ "Mab",
+ "Nkw",
+ "Nhla",
+ "Ntu",
+ "Ncw",
+ "Mpan",
+ "Mfu",
+ "Lwe",
+ "Mpal"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nd-zw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd.js
new file mode 100644
index 00000000..96d113bd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sonto",
+ "Mvulo",
+ "Sibili",
+ "Sithathu",
+ "Sine",
+ "Sihlanu",
+ "Mgqibelo"
+ ],
+ "ERANAMES": [
+ "UKristo angakabuyi",
+ "Ukristo ebuyile"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Zibandlela",
+ "Nhlolanja",
+ "Mbimbitho",
+ "Mabasa",
+ "Nkwenkwezi",
+ "Nhlangula",
+ "Ntulikazi",
+ "Ncwabakazi",
+ "Mpandula",
+ "Mfumfu",
+ "Lwezi",
+ "Mpalakazi"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mvu",
+ "Sib",
+ "Sit",
+ "Sin",
+ "Sih",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Zib",
+ "Nhlo",
+ "Mbi",
+ "Mab",
+ "Nkw",
+ "Nhla",
+ "Ntu",
+ "Ncw",
+ "Mpan",
+ "Mfu",
+ "Lwe",
+ "Mpal"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-in.js
new file mode 100644
index 00000000..283c8ca2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092a\u0942\u0930\u094d\u0935\u093e\u0939\u094d\u0928",
+ "\u0905\u092a\u0930\u093e\u0939\u094d\u0928"
+ ],
+ "DAY": [
+ "\u0906\u0907\u0924\u092c\u093e\u0930",
+ "\u0938\u094b\u092e\u092c\u093e\u0930",
+ "\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930",
+ "\u092c\u0941\u0927\u092c\u093e\u0930",
+ "\u092c\u093f\u0939\u093f\u092c\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930",
+ "\u0936\u0928\u093f\u092c\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0908",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0906\u0907\u0924",
+ "\u0938\u094b\u092e",
+ "\u092e\u0919\u094d\u0917\u0932",
+ "\u092c\u0941\u0927",
+ "\u092c\u093f\u0939\u0940",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ne-in",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-np.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-np.js
new file mode 100644
index 00000000..d8e52d08
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne-np.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092a\u0942\u0930\u094d\u0935\u093e\u0939\u094d\u0928",
+ "\u0905\u092a\u0930\u093e\u0939\u094d\u0928"
+ ],
+ "DAY": [
+ "\u0906\u0907\u0924\u092c\u093e\u0930",
+ "\u0938\u094b\u092e\u092c\u093e\u0930",
+ "\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930",
+ "\u092c\u0941\u0927\u092c\u093e\u0930",
+ "\u092c\u093f\u0939\u093f\u092c\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930",
+ "\u0936\u0928\u093f\u092c\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0908",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0906\u0907\u0924",
+ "\u0938\u094b\u092e",
+ "\u092e\u0919\u094d\u0917\u0932",
+ "\u092c\u0941\u0927",
+ "\u092c\u093f\u0939\u0940",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ne-np",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne.js
new file mode 100644
index 00000000..cff99fec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ne.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u092a\u0942\u0930\u094d\u0935\u093e\u0939\u094d\u0928",
+ "\u0905\u092a\u0930\u093e\u0939\u094d\u0928"
+ ],
+ "DAY": [
+ "\u0906\u0907\u0924\u092c\u093e\u0930",
+ "\u0938\u094b\u092e\u092c\u093e\u0930",
+ "\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930",
+ "\u092c\u0941\u0927\u092c\u093e\u0930",
+ "\u092c\u093f\u0939\u093f\u092c\u093e\u0930",
+ "\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930",
+ "\u0936\u0928\u093f\u092c\u093e\u0930"
+ ],
+ "ERANAMES": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "ERAS": [
+ "\u0908\u0938\u093e \u092a\u0942\u0930\u094d\u0935",
+ "\u0938\u0928\u094d"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0908",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "SHORTDAY": [
+ "\u0906\u0907\u0924",
+ "\u0938\u094b\u092e",
+ "\u092e\u0919\u094d\u0917\u0932",
+ "\u092c\u0941\u0927",
+ "\u092c\u093f\u0939\u0940",
+ "\u0936\u0941\u0915\u094d\u0930",
+ "\u0936\u0928\u093f"
+ ],
+ "SHORTMONTH": [
+ "\u091c\u0928\u0935\u0930\u0940",
+ "\u092b\u0947\u092c\u094d\u0930\u0941\u0905\u0930\u0940",
+ "\u092e\u093e\u0930\u094d\u091a",
+ "\u0905\u092a\u094d\u0930\u093f\u0932",
+ "\u092e\u0947",
+ "\u091c\u0941\u0928",
+ "\u091c\u0941\u0932\u093e\u0908",
+ "\u0905\u0917\u0938\u094d\u091f",
+ "\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930",
+ "\u0905\u0915\u094d\u091f\u094b\u092c\u0930",
+ "\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930",
+ "\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ne",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-aw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-aw.js
new file mode 100644
index 00000000..3e22477d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-aw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Afl.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-aw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-be.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-be.js
new file mode 100644
index 00000000..38ba3ab8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-be.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/MM/yy HH:mm",
+ "shortDate": "d/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "nl-be",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-bq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-bq.js
new file mode 100644
index 00000000..87c008a2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-bq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-bq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-cw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-cw.js
new file mode 100644
index 00000000..7475f6ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-cw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NAf.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-cw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-nl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-nl.js
new file mode 100644
index 00000000..3b7bd150
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-nl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-nl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sr.js
new file mode 100644
index 00000000..06875a81
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-sr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sx.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sx.js
new file mode 100644
index 00000000..c59dfb5a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl-sx.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NAf.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl-sx",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl.js
new file mode 100644
index 00000000..79428d98
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "zondag",
+ "maandag",
+ "dinsdag",
+ "woensdag",
+ "donderdag",
+ "vrijdag",
+ "zaterdag"
+ ],
+ "ERANAMES": [
+ "voor Christus",
+ "na Christus"
+ ],
+ "ERAS": [
+ "v.Chr.",
+ "n.Chr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "maart",
+ "april",
+ "mei",
+ "juni",
+ "juli",
+ "augustus",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "zo",
+ "ma",
+ "di",
+ "wo",
+ "do",
+ "vr",
+ "za"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mrt.",
+ "apr.",
+ "mei",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg-cm.js
new file mode 100644
index 00000000..24594190
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "man\u00e1",
+ "kug\u00fa"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u0254",
+ "m\u0254\u0301nd\u0254",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1ba",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1lal",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1na",
+ "mab\u00e1g\u00e1 m\u00e1 sukul",
+ "s\u00e1sadi"
+ ],
+ "ERANAMES": [
+ "B\u00f3 Lahl\u025b\u0304",
+ "Pfi\u025b Bur\u012b"
+ ],
+ "ERAS": [
+ "BL",
+ "PB"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ngw\u025bn mat\u00e1hra",
+ "ngw\u025bn \u0144mba",
+ "ngw\u025bn \u0144lal",
+ "ngw\u025bn \u0144na",
+ "ngw\u025bn \u0144tan",
+ "ngw\u025bn \u0144tu\u00f3",
+ "ngw\u025bn h\u025bmbu\u025br\u00ed",
+ "ngw\u025bn l\u0254mbi",
+ "ngw\u025bn r\u025bbvu\u00e2",
+ "ngw\u025bn wum",
+ "ngw\u025bn wum nav\u01d4r",
+ "kr\u00edsimin"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "m\u0254\u0301n",
+ "smb",
+ "sml",
+ "smn",
+ "mbs",
+ "sas"
+ ],
+ "SHORTMONTH": [
+ "ng1",
+ "ng2",
+ "ng3",
+ "ng4",
+ "ng5",
+ "ng6",
+ "ng7",
+ "ng8",
+ "ng9",
+ "ng10",
+ "ng11",
+ "kris"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "nmg-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg.js
new file mode 100644
index 00000000..98f5073e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nmg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "man\u00e1",
+ "kug\u00fa"
+ ],
+ "DAY": [
+ "s\u0254\u0301nd\u0254",
+ "m\u0254\u0301nd\u0254",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1ba",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1lal",
+ "s\u0254\u0301nd\u0254 maf\u00fa m\u00e1na",
+ "mab\u00e1g\u00e1 m\u00e1 sukul",
+ "s\u00e1sadi"
+ ],
+ "ERANAMES": [
+ "B\u00f3 Lahl\u025b\u0304",
+ "Pfi\u025b Bur\u012b"
+ ],
+ "ERAS": [
+ "BL",
+ "PB"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ngw\u025bn mat\u00e1hra",
+ "ngw\u025bn \u0144mba",
+ "ngw\u025bn \u0144lal",
+ "ngw\u025bn \u0144na",
+ "ngw\u025bn \u0144tan",
+ "ngw\u025bn \u0144tu\u00f3",
+ "ngw\u025bn h\u025bmbu\u025br\u00ed",
+ "ngw\u025bn l\u0254mbi",
+ "ngw\u025bn r\u025bbvu\u00e2",
+ "ngw\u025bn wum",
+ "ngw\u025bn wum nav\u01d4r",
+ "kr\u00edsimin"
+ ],
+ "SHORTDAY": [
+ "s\u0254\u0301n",
+ "m\u0254\u0301n",
+ "smb",
+ "sml",
+ "smn",
+ "mbs",
+ "sas"
+ ],
+ "SHORTMONTH": [
+ "ng1",
+ "ng2",
+ "ng3",
+ "ng4",
+ "ng5",
+ "ng6",
+ "ng7",
+ "ng8",
+ "ng9",
+ "ng10",
+ "ng11",
+ "kris"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "nmg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn-no.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn-no.js
new file mode 100644
index 00000000..c303718b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn-no.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "formiddag",
+ "ettermiddag"
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "m\u00e5ndag",
+ "tysdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "laurdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8.",
+ "m\u00e5.",
+ "ty.",
+ "on.",
+ "to.",
+ "fr.",
+ "la."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "mai",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "nn-no",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn.js
new file mode 100644
index 00000000..6d2f0370
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "formiddag",
+ "ettermiddag"
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "m\u00e5ndag",
+ "tysdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "laurdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8.",
+ "m\u00e5.",
+ "ty.",
+ "on.",
+ "to.",
+ "fr.",
+ "la."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "mai",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "nn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh-cm.js
new file mode 100644
index 00000000..92eef3bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "mba\u02bc\u00e1mba\u02bc",
+ "ncw\u00f2nz\u00e9m"
+ ],
+ "DAY": [
+ "ly\u025b\u02bc\u025b\u0301 s\u1e85\u00ed\u014bt\u00e8",
+ "mvf\u00f2 ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 mvf\u00f2 ly\u025b\u030c\u02bc",
+ "ts\u00e8ts\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 tsets\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc",
+ "m\u00e0ga ly\u025b\u030c\u02bc"
+ ],
+ "ERANAMES": [
+ "m\u00e9 zy\u00e9 Y\u011bs\u00f4",
+ "m\u00e9 g\u00ffo \u0144zy\u00e9 Y\u011bs\u00f4"
+ ],
+ "ERAS": [
+ "m.z.Y.",
+ "m.g.n.Y."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m",
+ "sa\u014b k\u00e0g ngw\u00f3\u014b",
+ "sa\u014b lepy\u00e8 sh\u00fam",
+ "sa\u014b c\u00ff\u00f3",
+ "sa\u014b ts\u025b\u0300\u025b c\u00ff\u00f3",
+ "sa\u014b nj\u00ffol\u00e1\u02bc",
+ "sa\u014b ty\u025b\u0300b ty\u025b\u0300b mb\u0289\u0300",
+ "sa\u014b mb\u0289\u0300\u014b",
+ "sa\u014b ngw\u0254\u0300\u02bc mb\u00ff\u025b",
+ "sa\u014b t\u00e0\u014ba tsets\u00e1\u02bc",
+ "sa\u014b mejwo\u014b\u00f3",
+ "sa\u014b l\u00f9m"
+ ],
+ "SHORTDAY": [
+ "ly\u025b\u02bc\u025b\u0301 s\u1e85\u00ed\u014bt\u00e8",
+ "mvf\u00f2 ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 mvf\u00f2 ly\u025b\u030c\u02bc",
+ "ts\u00e8ts\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 tsets\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc",
+ "m\u00e0ga ly\u025b\u030c\u02bc"
+ ],
+ "SHORTMONTH": [
+ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m",
+ "sa\u014b k\u00e0g ngw\u00f3\u014b",
+ "sa\u014b lepy\u00e8 sh\u00fam",
+ "sa\u014b c\u00ff\u00f3",
+ "sa\u014b ts\u025b\u0300\u025b c\u00ff\u00f3",
+ "sa\u014b nj\u00ffol\u00e1\u02bc",
+ "sa\u014b ty\u025b\u0300b ty\u025b\u0300b mb\u0289\u0300",
+ "sa\u014b mb\u0289\u0300\u014b",
+ "sa\u014b ngw\u0254\u0300\u02bc mb\u00ff\u025b",
+ "sa\u014b t\u00e0\u014ba tsets\u00e1\u02bc",
+ "sa\u014b mejwo\u014b\u00f3",
+ "sa\u014b l\u00f9m"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE , 'ly\u025b'\u030c\u02bc d 'na' MMMM, y",
+ "longDate": "'ly\u025b'\u030c\u02bc d 'na' MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nnh-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh.js
new file mode 100644
index 00000000..b8745d19
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nnh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "mba\u02bc\u00e1mba\u02bc",
+ "ncw\u00f2nz\u00e9m"
+ ],
+ "DAY": [
+ "ly\u025b\u02bc\u025b\u0301 s\u1e85\u00ed\u014bt\u00e8",
+ "mvf\u00f2 ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 mvf\u00f2 ly\u025b\u030c\u02bc",
+ "ts\u00e8ts\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 tsets\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc",
+ "m\u00e0ga ly\u025b\u030c\u02bc"
+ ],
+ "ERANAMES": [
+ "m\u00e9 zy\u00e9 Y\u011bs\u00f4",
+ "m\u00e9 g\u00ffo \u0144zy\u00e9 Y\u011bs\u00f4"
+ ],
+ "ERAS": [
+ "m.z.Y.",
+ "m.g.n.Y."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m",
+ "sa\u014b k\u00e0g ngw\u00f3\u014b",
+ "sa\u014b lepy\u00e8 sh\u00fam",
+ "sa\u014b c\u00ff\u00f3",
+ "sa\u014b ts\u025b\u0300\u025b c\u00ff\u00f3",
+ "sa\u014b nj\u00ffol\u00e1\u02bc",
+ "sa\u014b ty\u025b\u0300b ty\u025b\u0300b mb\u0289\u0300",
+ "sa\u014b mb\u0289\u0300\u014b",
+ "sa\u014b ngw\u0254\u0300\u02bc mb\u00ff\u025b",
+ "sa\u014b t\u00e0\u014ba tsets\u00e1\u02bc",
+ "sa\u014b mejwo\u014b\u00f3",
+ "sa\u014b l\u00f9m"
+ ],
+ "SHORTDAY": [
+ "ly\u025b\u02bc\u025b\u0301 s\u1e85\u00ed\u014bt\u00e8",
+ "mvf\u00f2 ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 mvf\u00f2 ly\u025b\u030c\u02bc",
+ "ts\u00e8ts\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mb\u0254\u0301\u0254nt\u00e8 tsets\u025b\u0300\u025b ly\u025b\u030c\u02bc",
+ "mvf\u00f2 m\u00e0ga ly\u025b\u030c\u02bc",
+ "m\u00e0ga ly\u025b\u030c\u02bc"
+ ],
+ "SHORTMONTH": [
+ "sa\u014b tsets\u025b\u0300\u025b l\u00f9m",
+ "sa\u014b k\u00e0g ngw\u00f3\u014b",
+ "sa\u014b lepy\u00e8 sh\u00fam",
+ "sa\u014b c\u00ff\u00f3",
+ "sa\u014b ts\u025b\u0300\u025b c\u00ff\u00f3",
+ "sa\u014b nj\u00ffol\u00e1\u02bc",
+ "sa\u014b ty\u025b\u0300b ty\u025b\u0300b mb\u0289\u0300",
+ "sa\u014b mb\u0289\u0300\u014b",
+ "sa\u014b ngw\u0254\u0300\u02bc mb\u00ff\u025b",
+ "sa\u014b t\u00e0\u014ba tsets\u00e1\u02bc",
+ "sa\u014b mejwo\u014b\u00f3",
+ "sa\u014b l\u00f9m"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE , 'ly\u025b'\u030c\u02bc d 'na' MMMM, y",
+ "longDate": "'ly\u025b'\u030c\u02bc d 'na' MMMM, y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nnh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no-no.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no-no.js
new file mode 100644
index 00000000..dc93791c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no-no.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd.MM.y HH.mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "no-no",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no.js
new file mode 100644
index 00000000..b0b2fec1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_no.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "s\u00f8ndag",
+ "mandag",
+ "tirsdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f8rdag"
+ ],
+ "ERANAMES": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mars",
+ "april",
+ "mai",
+ "juni",
+ "juli",
+ "august",
+ "september",
+ "oktober",
+ "november",
+ "desember"
+ ],
+ "SHORTDAY": [
+ "s\u00f8n.",
+ "man.",
+ "tir.",
+ "ons.",
+ "tor.",
+ "fre.",
+ "l\u00f8r."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "jun.",
+ "jul.",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "des."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH.mm.ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH.mm.ss",
+ "short": "dd.MM.y HH.mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "no",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr-za.js
new file mode 100644
index 00000000..60a2745f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "uSonto",
+ "uMvulo",
+ "uLesibili",
+ "Lesithathu",
+ "uLesine",
+ "ngoLesihlanu",
+ "umGqibelo"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Janabari",
+ "uFeberbari",
+ "uMatjhi",
+ "u-Apreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Arhostosi",
+ "Septemba",
+ "Oktoba",
+ "Usinyikhaba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mvu",
+ "Bil",
+ "Tha",
+ "Ne",
+ "Hla",
+ "Gqi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Apr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Arh",
+ "Sep",
+ "Okt",
+ "Usi",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nr-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr.js
new file mode 100644
index 00000000..daa76c0a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "uSonto",
+ "uMvulo",
+ "uLesibili",
+ "Lesithathu",
+ "uLesine",
+ "ngoLesihlanu",
+ "umGqibelo"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Janabari",
+ "uFeberbari",
+ "uMatjhi",
+ "u-Apreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Arhostosi",
+ "Septemba",
+ "Oktoba",
+ "Usinyikhaba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mvu",
+ "Bil",
+ "Tha",
+ "Ne",
+ "Hla",
+ "Gqi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Apr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Arh",
+ "Sep",
+ "Okt",
+ "Usi",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso-za.js
new file mode 100644
index 00000000..493ec38e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sontaga",
+ "Mosupalogo",
+ "Labobedi",
+ "Laboraro",
+ "Labone",
+ "Labohlano",
+ "Mokibelo"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Janaware",
+ "Feberware",
+ "Mat\u0161he",
+ "Aporele",
+ "Mei",
+ "June",
+ "Julae",
+ "Agostose",
+ "Setemere",
+ "Oktobore",
+ "Nofemere",
+ "Disemere"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mos",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Hla",
+ "Mok"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Apo",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Set",
+ "Okt",
+ "Nof",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nso-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso.js
new file mode 100644
index 00000000..50d5663a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nso.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sontaga",
+ "Mosupalogo",
+ "Labobedi",
+ "Laboraro",
+ "Labone",
+ "Labohlano",
+ "Mokibelo"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Janaware",
+ "Feberware",
+ "Mat\u0161he",
+ "Aporele",
+ "Mei",
+ "June",
+ "Julae",
+ "Agostose",
+ "Setemere",
+ "Oktobore",
+ "Nofemere",
+ "Disemere"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mos",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Hla",
+ "Mok"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Apo",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Set",
+ "Okt",
+ "Nof",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nso",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus-sd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus-sd.js
new file mode 100644
index 00000000..a46aee48
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus-sd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "RW",
+ "T\u014a"
+ ],
+ "DAY": [
+ "C\u00e4\u014b ku\u0254th",
+ "Jiec la\u0331t",
+ "R\u025bw l\u00e4tni",
+ "Di\u0254\u0331k l\u00e4tni",
+ "\u014auaan l\u00e4tni",
+ "Dhieec l\u00e4tni",
+ "B\u00e4k\u025bl l\u00e4tni"
+ ],
+ "ERANAMES": [
+ "A ka\u0331n Yecu ni dap",
+ "\u0190 ca Yecu dap"
+ ],
+ "ERAS": [
+ "AY",
+ "\u0190Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Tiop thar p\u025bt",
+ "P\u025bt",
+ "Du\u0254\u0331\u0254\u0331\u014b",
+ "Guak",
+ "Du\u00e4t",
+ "Kornyoot",
+ "Pay yie\u0331tni",
+ "Tho\u0331o\u0331r",
+ "T\u025b\u025br",
+ "Laath",
+ "Kur",
+ "Tio\u0331p in di\u0331i\u0331t"
+ ],
+ "SHORTDAY": [
+ "C\u00e4\u014b",
+ "Jiec",
+ "R\u025bw",
+ "Di\u0254\u0331k",
+ "\u014auaan",
+ "Dhieec",
+ "B\u00e4k\u025bl"
+ ],
+ "SHORTMONTH": [
+ "Tiop",
+ "P\u025bt",
+ "Du\u0254\u0331\u0254\u0331",
+ "Guak",
+ "Du\u00e4",
+ "Kor",
+ "Pay",
+ "Thoo",
+ "T\u025b\u025b",
+ "Laa",
+ "Kur",
+ "Tid"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/y h:mm a",
+ "shortDate": "d/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SDG",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nus-sd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus.js
new file mode 100644
index 00000000..8d201498
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nus.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "RW",
+ "T\u014a"
+ ],
+ "DAY": [
+ "C\u00e4\u014b ku\u0254th",
+ "Jiec la\u0331t",
+ "R\u025bw l\u00e4tni",
+ "Di\u0254\u0331k l\u00e4tni",
+ "\u014auaan l\u00e4tni",
+ "Dhieec l\u00e4tni",
+ "B\u00e4k\u025bl l\u00e4tni"
+ ],
+ "ERANAMES": [
+ "A ka\u0331n Yecu ni dap",
+ "\u0190 ca Yecu dap"
+ ],
+ "ERAS": [
+ "AY",
+ "\u0190Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Tiop thar p\u025bt",
+ "P\u025bt",
+ "Du\u0254\u0331\u0254\u0331\u014b",
+ "Guak",
+ "Du\u00e4t",
+ "Kornyoot",
+ "Pay yie\u0331tni",
+ "Tho\u0331o\u0331r",
+ "T\u025b\u025br",
+ "Laath",
+ "Kur",
+ "Tio\u0331p in di\u0331i\u0331t"
+ ],
+ "SHORTDAY": [
+ "C\u00e4\u014b",
+ "Jiec",
+ "R\u025bw",
+ "Di\u0254\u0331k",
+ "\u014auaan",
+ "Dhieec",
+ "B\u00e4k\u025bl"
+ ],
+ "SHORTMONTH": [
+ "Tiop",
+ "P\u025bt",
+ "Du\u0254\u0331\u0254\u0331",
+ "Guak",
+ "Du\u00e4",
+ "Kor",
+ "Pay",
+ "Thoo",
+ "T\u025b\u025b",
+ "Laa",
+ "Kur",
+ "Tid"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/MM/y h:mm a",
+ "shortDate": "d/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SDG",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nus",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn-ug.js
new file mode 100644
index 00000000..bc15a7dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sande",
+ "Orwokubanza",
+ "Orwakabiri",
+ "Orwakashatu",
+ "Orwakana",
+ "Orwakataano",
+ "Orwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kurisito Atakaijire",
+ "Kurisito Yaijire"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Okwokubanza",
+ "Okwakabiri",
+ "Okwakashatu",
+ "Okwakana",
+ "Okwakataana",
+ "Okwamukaaga",
+ "Okwamushanju",
+ "Okwamunaana",
+ "Okwamwenda",
+ "Okwaikumi",
+ "Okwaikumi na kumwe",
+ "Okwaikumi na ibiri"
+ ],
+ "SHORTDAY": [
+ "SAN",
+ "ORK",
+ "OKB",
+ "OKS",
+ "OKN",
+ "OKT",
+ "OMK"
+ ],
+ "SHORTMONTH": [
+ "KBZ",
+ "KBR",
+ "KST",
+ "KKN",
+ "KTN",
+ "KMK",
+ "KMS",
+ "KMN",
+ "KMW",
+ "KKM",
+ "KNK",
+ "KNB"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nyn-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn.js
new file mode 100644
index 00000000..ecc65b9b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_nyn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sande",
+ "Orwokubanza",
+ "Orwakabiri",
+ "Orwakashatu",
+ "Orwakana",
+ "Orwakataano",
+ "Orwamukaaga"
+ ],
+ "ERANAMES": [
+ "Kurisito Atakaijire",
+ "Kurisito Yaijire"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Okwokubanza",
+ "Okwakabiri",
+ "Okwakashatu",
+ "Okwakana",
+ "Okwakataana",
+ "Okwamukaaga",
+ "Okwamushanju",
+ "Okwamunaana",
+ "Okwamwenda",
+ "Okwaikumi",
+ "Okwaikumi na kumwe",
+ "Okwaikumi na ibiri"
+ ],
+ "SHORTDAY": [
+ "SAN",
+ "ORK",
+ "OKB",
+ "OKS",
+ "OKN",
+ "OKT",
+ "OMK"
+ ],
+ "SHORTMONTH": [
+ "KBZ",
+ "KBR",
+ "KST",
+ "KKN",
+ "KTN",
+ "KMK",
+ "KMS",
+ "KMN",
+ "KMW",
+ "KKM",
+ "KNK",
+ "KNB"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "nyn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-et.js
new file mode 100644
index 00000000..3857abd0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-et.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "WD",
+ "WB"
+ ],
+ "DAY": [
+ "Dilbata",
+ "Wiixata",
+ "Qibxata",
+ "Roobii",
+ "Kamiisa",
+ "Jimaata",
+ "Sanbata"
+ ],
+ "ERANAMES": [
+ "KD",
+ "KB"
+ ],
+ "ERAS": [
+ "KD",
+ "KB"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Amajjii",
+ "Guraandhala",
+ "Bitooteessa",
+ "Elba",
+ "Caamsa",
+ "Waxabajjii",
+ "Adooleessa",
+ "Hagayya",
+ "Fuulbana",
+ "Onkololeessa",
+ "Sadaasa",
+ "Muddee"
+ ],
+ "SHORTDAY": [
+ "Dil",
+ "Wix",
+ "Qib",
+ "Rob",
+ "Kam",
+ "Jim",
+ "San"
+ ],
+ "SHORTMONTH": [
+ "Ama",
+ "Gur",
+ "Bit",
+ "Elb",
+ "Cam",
+ "Wax",
+ "Ado",
+ "Hag",
+ "Ful",
+ "Onk",
+ "Sad",
+ "Mud"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "om-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-ke.js
new file mode 100644
index 00000000..dba7fd1f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "WD",
+ "WB"
+ ],
+ "DAY": [
+ "Dilbata",
+ "Wiixata",
+ "Qibxata",
+ "Roobii",
+ "Kamiisa",
+ "Jimaata",
+ "Sanbata"
+ ],
+ "ERANAMES": [
+ "KD",
+ "KB"
+ ],
+ "ERAS": [
+ "KD",
+ "KB"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Amajjii",
+ "Guraandhala",
+ "Bitooteessa",
+ "Elba",
+ "Caamsa",
+ "Waxabajjii",
+ "Adooleessa",
+ "Hagayya",
+ "Fuulbana",
+ "Onkololeessa",
+ "Sadaasa",
+ "Muddee"
+ ],
+ "SHORTDAY": [
+ "Dil",
+ "Wix",
+ "Qib",
+ "Rob",
+ "Kam",
+ "Jim",
+ "San"
+ ],
+ "SHORTMONTH": [
+ "Ama",
+ "Gur",
+ "Bit",
+ "Elb",
+ "Cam",
+ "Wax",
+ "Ado",
+ "Hag",
+ "Ful",
+ "Onk",
+ "Sad",
+ "Mud"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "om-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om.js
new file mode 100644
index 00000000..c41c2772
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_om.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "WD",
+ "WB"
+ ],
+ "DAY": [
+ "Dilbata",
+ "Wiixata",
+ "Qibxata",
+ "Roobii",
+ "Kamiisa",
+ "Jimaata",
+ "Sanbata"
+ ],
+ "ERANAMES": [
+ "KD",
+ "KB"
+ ],
+ "ERAS": [
+ "KD",
+ "KB"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Amajjii",
+ "Guraandhala",
+ "Bitooteessa",
+ "Elba",
+ "Caamsa",
+ "Waxabajjii",
+ "Adooleessa",
+ "Hagayya",
+ "Fuulbana",
+ "Onkololeessa",
+ "Sadaasa",
+ "Muddee"
+ ],
+ "SHORTDAY": [
+ "Dil",
+ "Wix",
+ "Qib",
+ "Rob",
+ "Kam",
+ "Jim",
+ "San"
+ ],
+ "SHORTMONTH": [
+ "Ama",
+ "Gur",
+ "Bit",
+ "Elb",
+ "Cam",
+ "Wax",
+ "Ado",
+ "Hag",
+ "Ful",
+ "Onk",
+ "Sad",
+ "Mud"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "om",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or-in.js
new file mode 100644
index 00000000..5f1da84c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u0b30\u0b2c\u0b3f\u0b2c\u0b3e\u0b30",
+ "\u0b38\u0b4b\u0b2e\u0b2c\u0b3e\u0b30",
+ "\u0b2e\u0b19\u0b4d\u0b17\u0b33\u0b2c\u0b3e\u0b30",
+ "\u0b2c\u0b41\u0b27\u0b2c\u0b3e\u0b30",
+ "\u0b17\u0b41\u0b30\u0b41\u0b2c\u0b3e\u0b30",
+ "\u0b36\u0b41\u0b15\u0b4d\u0b30\u0b2c\u0b3e\u0b30",
+ "\u0b36\u0b28\u0b3f\u0b2c\u0b3e\u0b30"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40",
+ "\u0b2b\u0b47\u0b2c\u0b43\u0b06\u0b30\u0b40",
+ "\u0b2e\u0b3e\u0b30\u0b4d\u0b1a\u0b4d\u0b1a",
+ "\u0b05\u0b2a\u0b4d\u0b30\u0b47\u0b32",
+ "\u0b2e\u0b07",
+ "\u0b1c\u0b41\u0b28",
+ "\u0b1c\u0b41\u0b32\u0b3e\u0b07",
+ "\u0b05\u0b17\u0b37\u0b4d\u0b1f",
+ "\u0b38\u0b47\u0b2a\u0b4d\u0b1f\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b05\u0b15\u0b4d\u0b1f\u0b4b\u0b2c\u0b30",
+ "\u0b28\u0b2d\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b21\u0b3f\u0b38\u0b47\u0b2e\u0b4d\u0b2c\u0b30"
+ ],
+ "SHORTDAY": [
+ "\u0b30\u0b2c\u0b3f",
+ "\u0b38\u0b4b\u0b2e",
+ "\u0b2e\u0b19\u0b4d\u0b17\u0b33",
+ "\u0b2c\u0b41\u0b27",
+ "\u0b17\u0b41\u0b30\u0b41",
+ "\u0b36\u0b41\u0b15\u0b4d\u0b30",
+ "\u0b36\u0b28\u0b3f"
+ ],
+ "SHORTMONTH": [
+ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40",
+ "\u0b2b\u0b47\u0b2c\u0b43\u0b06\u0b30\u0b40",
+ "\u0b2e\u0b3e\u0b30\u0b4d\u0b1a\u0b4d\u0b1a",
+ "\u0b05\u0b2a\u0b4d\u0b30\u0b47\u0b32",
+ "\u0b2e\u0b07",
+ "\u0b1c\u0b41\u0b28",
+ "\u0b1c\u0b41\u0b32\u0b3e\u0b07",
+ "\u0b05\u0b17\u0b37\u0b4d\u0b1f",
+ "\u0b38\u0b47\u0b2a\u0b4d\u0b1f\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b05\u0b15\u0b4d\u0b1f\u0b4b\u0b2c\u0b30",
+ "\u0b28\u0b2d\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b21\u0b3f\u0b38\u0b47\u0b2e\u0b4d\u0b2c\u0b30"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "or-in",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or.js
new file mode 100644
index 00000000..43c4fd3a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_or.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "pm"
+ ],
+ "DAY": [
+ "\u0b30\u0b2c\u0b3f\u0b2c\u0b3e\u0b30",
+ "\u0b38\u0b4b\u0b2e\u0b2c\u0b3e\u0b30",
+ "\u0b2e\u0b19\u0b4d\u0b17\u0b33\u0b2c\u0b3e\u0b30",
+ "\u0b2c\u0b41\u0b27\u0b2c\u0b3e\u0b30",
+ "\u0b17\u0b41\u0b30\u0b41\u0b2c\u0b3e\u0b30",
+ "\u0b36\u0b41\u0b15\u0b4d\u0b30\u0b2c\u0b3e\u0b30",
+ "\u0b36\u0b28\u0b3f\u0b2c\u0b3e\u0b30"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40",
+ "\u0b2b\u0b47\u0b2c\u0b43\u0b06\u0b30\u0b40",
+ "\u0b2e\u0b3e\u0b30\u0b4d\u0b1a\u0b4d\u0b1a",
+ "\u0b05\u0b2a\u0b4d\u0b30\u0b47\u0b32",
+ "\u0b2e\u0b07",
+ "\u0b1c\u0b41\u0b28",
+ "\u0b1c\u0b41\u0b32\u0b3e\u0b07",
+ "\u0b05\u0b17\u0b37\u0b4d\u0b1f",
+ "\u0b38\u0b47\u0b2a\u0b4d\u0b1f\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b05\u0b15\u0b4d\u0b1f\u0b4b\u0b2c\u0b30",
+ "\u0b28\u0b2d\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b21\u0b3f\u0b38\u0b47\u0b2e\u0b4d\u0b2c\u0b30"
+ ],
+ "SHORTDAY": [
+ "\u0b30\u0b2c\u0b3f",
+ "\u0b38\u0b4b\u0b2e",
+ "\u0b2e\u0b19\u0b4d\u0b17\u0b33",
+ "\u0b2c\u0b41\u0b27",
+ "\u0b17\u0b41\u0b30\u0b41",
+ "\u0b36\u0b41\u0b15\u0b4d\u0b30",
+ "\u0b36\u0b28\u0b3f"
+ ],
+ "SHORTMONTH": [
+ "\u0b1c\u0b3e\u0b28\u0b41\u0b06\u0b30\u0b40",
+ "\u0b2b\u0b47\u0b2c\u0b43\u0b06\u0b30\u0b40",
+ "\u0b2e\u0b3e\u0b30\u0b4d\u0b1a\u0b4d\u0b1a",
+ "\u0b05\u0b2a\u0b4d\u0b30\u0b47\u0b32",
+ "\u0b2e\u0b07",
+ "\u0b1c\u0b41\u0b28",
+ "\u0b1c\u0b41\u0b32\u0b3e\u0b07",
+ "\u0b05\u0b17\u0b37\u0b4d\u0b1f",
+ "\u0b38\u0b47\u0b2a\u0b4d\u0b1f\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b05\u0b15\u0b4d\u0b1f\u0b4b\u0b2c\u0b30",
+ "\u0b28\u0b2d\u0b47\u0b2e\u0b4d\u0b2c\u0b30",
+ "\u0b21\u0b3f\u0b38\u0b47\u0b2e\u0b4d\u0b2c\u0b30"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "or",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ge.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ge.js
new file mode 100644
index 00000000..3516f726
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ge.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0440\u0430\u0437\u043c\u04d5",
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0444\u04d5\u0441\u0442\u04d5"
+ ],
+ "DAY": [
+ "\u0445\u0443\u044b\u0446\u0430\u0443\u0431\u043e\u043d",
+ "\u043a\u044a\u0443\u044b\u0440\u0438\u0441\u04d5\u0440",
+ "\u0434\u044b\u0446\u0446\u04d5\u0433",
+ "\u04d5\u0440\u0442\u044b\u0446\u0446\u04d5\u0433",
+ "\u0446\u044b\u043f\u043f\u04d5\u0440\u04d5\u043c",
+ "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d",
+ "\u0441\u0430\u0431\u0430\u0442"
+ ],
+ "ERANAMES": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "ERAS": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044b",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044b",
+ "\u043c\u0430\u0440\u0442\u044a\u0438\u0439\u044b",
+ "\u0430\u043f\u0440\u0435\u043b\u044b",
+ "\u043c\u0430\u0439\u044b",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u044b",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044b",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044b",
+ "\u043d\u043e\u044f\u0431\u0440\u044b",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044b"
+ ],
+ "SHORTDAY": [
+ "\u0445\u0446\u0431",
+ "\u043a\u0440\u0441",
+ "\u0434\u0446\u0433",
+ "\u04d5\u0440\u0442",
+ "\u0446\u043f\u0440",
+ "\u043c\u0440\u0431",
+ "\u0441\u0431\u0442"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y '\u0430\u0437'",
+ "longDate": "d MMMM, y '\u0430\u0437'",
+ "medium": "dd MMM y '\u0430\u0437' HH:mm:ss",
+ "mediumDate": "dd MMM y '\u0430\u0437'",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GEL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "os-ge",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ru.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ru.js
new file mode 100644
index 00000000..d740670b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os-ru.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0440\u0430\u0437\u043c\u04d5",
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0444\u04d5\u0441\u0442\u04d5"
+ ],
+ "DAY": [
+ "\u0445\u0443\u044b\u0446\u0430\u0443\u0431\u043e\u043d",
+ "\u043a\u044a\u0443\u044b\u0440\u0438\u0441\u04d5\u0440",
+ "\u0434\u044b\u0446\u0446\u04d5\u0433",
+ "\u04d5\u0440\u0442\u044b\u0446\u0446\u04d5\u0433",
+ "\u0446\u044b\u043f\u043f\u04d5\u0440\u04d5\u043c",
+ "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d",
+ "\u0441\u0430\u0431\u0430\u0442"
+ ],
+ "ERANAMES": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "ERAS": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044b",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044b",
+ "\u043c\u0430\u0440\u0442\u044a\u0438\u0439\u044b",
+ "\u0430\u043f\u0440\u0435\u043b\u044b",
+ "\u043c\u0430\u0439\u044b",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u044b",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044b",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044b",
+ "\u043d\u043e\u044f\u0431\u0440\u044b",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044b"
+ ],
+ "SHORTDAY": [
+ "\u0445\u0446\u0431",
+ "\u043a\u0440\u0441",
+ "\u0434\u0446\u0433",
+ "\u04d5\u0440\u0442",
+ "\u0446\u043f\u0440",
+ "\u043c\u0440\u0431",
+ "\u0441\u0431\u0442"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y '\u0430\u0437'",
+ "longDate": "d MMMM, y '\u0430\u0437'",
+ "medium": "dd MMM y '\u0430\u0437' HH:mm:ss",
+ "mediumDate": "dd MMM y '\u0430\u0437'",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0440\u0443\u0431.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "os-ru",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os.js
new file mode 100644
index 00000000..a643a330
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_os.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0440\u0430\u0437\u043c\u04d5",
+ "\u04d5\u043c\u0431\u0438\u0441\u0431\u043e\u043d\u044b \u0444\u04d5\u0441\u0442\u04d5"
+ ],
+ "DAY": [
+ "\u0445\u0443\u044b\u0446\u0430\u0443\u0431\u043e\u043d",
+ "\u043a\u044a\u0443\u044b\u0440\u0438\u0441\u04d5\u0440",
+ "\u0434\u044b\u0446\u0446\u04d5\u0433",
+ "\u04d5\u0440\u0442\u044b\u0446\u0446\u04d5\u0433",
+ "\u0446\u044b\u043f\u043f\u04d5\u0440\u04d5\u043c",
+ "\u043c\u0430\u0439\u0440\u04d5\u043c\u0431\u043e\u043d",
+ "\u0441\u0430\u0431\u0430\u0442"
+ ],
+ "ERANAMES": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "ERAS": [
+ "\u043d.\u0434.\u0430.",
+ "\u043d.\u0434."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044b",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044b",
+ "\u043c\u0430\u0440\u0442\u044a\u0438\u0439\u044b",
+ "\u0430\u043f\u0440\u0435\u043b\u044b",
+ "\u043c\u0430\u0439\u044b",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u044b",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044b",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044b",
+ "\u043d\u043e\u044f\u0431\u0440\u044b",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044b"
+ ],
+ "SHORTDAY": [
+ "\u0445\u0446\u0431",
+ "\u043a\u0440\u0441",
+ "\u0434\u0446\u0433",
+ "\u04d5\u0440\u0442",
+ "\u0446\u043f\u0440",
+ "\u043c\u0440\u0431",
+ "\u0441\u0431\u0442"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432.",
+ "\u043c\u0430\u0440.",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044b",
+ "\u0438\u044e\u043b\u044b",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y '\u0430\u0437'",
+ "longDate": "d MMMM, y '\u0430\u0437'",
+ "medium": "dd MMM y '\u0430\u0437' HH:mm:ss",
+ "mediumDate": "dd MMM y '\u0430\u0437'",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "GEL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "os",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab-pk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab-pk.js
new file mode 100644
index 00000000..90f60579
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab-pk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u067e\u06cc\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u064f\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "ERANAMES": [
+ "\u0627\u064a\u0633\u0627\u067e\u0648\u0631\u0648",
+ "\u0633\u06ba"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u067e\u06cc\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u064f\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pa-arab-pk",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab.js
new file mode 100644
index 00000000..184a60c7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-arab.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u067e\u06cc\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u064f\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "ERANAMES": [
+ "\u0627\u064a\u0633\u0627\u067e\u0648\u0631\u0648",
+ "\u0633\u06ba"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u067e\u06cc\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u064f\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pa-arab",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru-in.js
new file mode 100644
index 00000000..3572f992
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0a2a\u0a42.\u0a26\u0a41.",
+ "\u0a2c\u0a3e.\u0a26\u0a41."
+ ],
+ "DAY": [
+ "\u0a10\u0a24\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a4b\u0a2e\u0a35\u0a3e\u0a30",
+ "\u0a2e\u0a70\u0a17\u0a32\u0a35\u0a3e\u0a30",
+ "\u0a2c\u0a41\u0a71\u0a27\u0a35\u0a3e\u0a30",
+ "\u0a35\u0a40\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30"
+ ],
+ "ERANAMES": [
+ "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35",
+ "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28"
+ ],
+ "ERAS": [
+ "\u0a08. \u0a2a\u0a42.",
+ "\u0a38\u0a70\u0a28"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0a1c\u0a28\u0a35\u0a30\u0a40",
+ "\u0a2b\u0a3c\u0a30\u0a35\u0a30\u0a40",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48\u0a32",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e\u0a08",
+ "\u0a05\u0a17\u0a38\u0a24",
+ "\u0a38\u0a24\u0a70\u0a2c\u0a30",
+ "\u0a05\u0a15\u0a24\u0a42\u0a2c\u0a30",
+ "\u0a28\u0a35\u0a70\u0a2c\u0a30",
+ "\u0a26\u0a38\u0a70\u0a2c\u0a30"
+ ],
+ "SHORTDAY": [
+ "\u0a10\u0a24",
+ "\u0a38\u0a4b\u0a2e",
+ "\u0a2e\u0a70\u0a17\u0a32",
+ "\u0a2c\u0a41\u0a71\u0a27",
+ "\u0a35\u0a40\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30"
+ ],
+ "SHORTMONTH": [
+ "\u0a1c\u0a28",
+ "\u0a2b\u0a3c\u0a30",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e",
+ "\u0a05\u0a17",
+ "\u0a38\u0a24\u0a70",
+ "\u0a05\u0a15\u0a24\u0a42",
+ "\u0a28\u0a35\u0a70",
+ "\u0a26\u0a38\u0a70"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pa-guru-in",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru.js
new file mode 100644
index 00000000..18c8431c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa-guru.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0a2a\u0a42.\u0a26\u0a41.",
+ "\u0a2c\u0a3e.\u0a26\u0a41."
+ ],
+ "DAY": [
+ "\u0a10\u0a24\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a4b\u0a2e\u0a35\u0a3e\u0a30",
+ "\u0a2e\u0a70\u0a17\u0a32\u0a35\u0a3e\u0a30",
+ "\u0a2c\u0a41\u0a71\u0a27\u0a35\u0a3e\u0a30",
+ "\u0a35\u0a40\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30"
+ ],
+ "ERANAMES": [
+ "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35",
+ "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28"
+ ],
+ "ERAS": [
+ "\u0a08. \u0a2a\u0a42.",
+ "\u0a38\u0a70\u0a28"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0a1c\u0a28\u0a35\u0a30\u0a40",
+ "\u0a2b\u0a3c\u0a30\u0a35\u0a30\u0a40",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48\u0a32",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e\u0a08",
+ "\u0a05\u0a17\u0a38\u0a24",
+ "\u0a38\u0a24\u0a70\u0a2c\u0a30",
+ "\u0a05\u0a15\u0a24\u0a42\u0a2c\u0a30",
+ "\u0a28\u0a35\u0a70\u0a2c\u0a30",
+ "\u0a26\u0a38\u0a70\u0a2c\u0a30"
+ ],
+ "SHORTDAY": [
+ "\u0a10\u0a24",
+ "\u0a38\u0a4b\u0a2e",
+ "\u0a2e\u0a70\u0a17\u0a32",
+ "\u0a2c\u0a41\u0a71\u0a27",
+ "\u0a35\u0a40\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30"
+ ],
+ "SHORTMONTH": [
+ "\u0a1c\u0a28",
+ "\u0a2b\u0a3c\u0a30",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e",
+ "\u0a05\u0a17",
+ "\u0a38\u0a24\u0a70",
+ "\u0a05\u0a15\u0a24\u0a42",
+ "\u0a28\u0a35\u0a70",
+ "\u0a26\u0a38\u0a70"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pa-guru",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa.js
new file mode 100644
index 00000000..6f6dc995
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pa.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0a2a\u0a42.\u0a26\u0a41.",
+ "\u0a2c\u0a3e.\u0a26\u0a41."
+ ],
+ "DAY": [
+ "\u0a10\u0a24\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a4b\u0a2e\u0a35\u0a3e\u0a30",
+ "\u0a2e\u0a70\u0a17\u0a32\u0a35\u0a3e\u0a30",
+ "\u0a2c\u0a41\u0a71\u0a27\u0a35\u0a3e\u0a30",
+ "\u0a35\u0a40\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30\u0a35\u0a3e\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30\u0a35\u0a3e\u0a30"
+ ],
+ "ERANAMES": [
+ "\u0a08\u0a38\u0a35\u0a40 \u0a2a\u0a42\u0a30\u0a35",
+ "\u0a08\u0a38\u0a35\u0a40 \u0a38\u0a70\u0a28"
+ ],
+ "ERAS": [
+ "\u0a08. \u0a2a\u0a42.",
+ "\u0a38\u0a70\u0a28"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0a1c\u0a28\u0a35\u0a30\u0a40",
+ "\u0a2b\u0a3c\u0a30\u0a35\u0a30\u0a40",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48\u0a32",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e\u0a08",
+ "\u0a05\u0a17\u0a38\u0a24",
+ "\u0a38\u0a24\u0a70\u0a2c\u0a30",
+ "\u0a05\u0a15\u0a24\u0a42\u0a2c\u0a30",
+ "\u0a28\u0a35\u0a70\u0a2c\u0a30",
+ "\u0a26\u0a38\u0a70\u0a2c\u0a30"
+ ],
+ "SHORTDAY": [
+ "\u0a10\u0a24",
+ "\u0a38\u0a4b\u0a2e",
+ "\u0a2e\u0a70\u0a17\u0a32",
+ "\u0a2c\u0a41\u0a71\u0a27",
+ "\u0a35\u0a40\u0a30",
+ "\u0a38\u0a3c\u0a41\u0a71\u0a15\u0a30",
+ "\u0a38\u0a3c\u0a28\u0a3f\u0a71\u0a1a\u0a30"
+ ],
+ "SHORTMONTH": [
+ "\u0a1c\u0a28",
+ "\u0a2b\u0a3c\u0a30",
+ "\u0a2e\u0a3e\u0a30\u0a1a",
+ "\u0a05\u0a2a\u0a4d\u0a30\u0a48",
+ "\u0a2e\u0a08",
+ "\u0a1c\u0a42\u0a28",
+ "\u0a1c\u0a41\u0a32\u0a3e",
+ "\u0a05\u0a17",
+ "\u0a38\u0a24\u0a70",
+ "\u0a05\u0a15\u0a24\u0a42",
+ "\u0a28\u0a35\u0a70",
+ "\u0a26\u0a38\u0a70"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pa",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl-pl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl-pl.js
new file mode 100644
index 00000000..fae20c89
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl-pl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "niedziela",
+ "poniedzia\u0142ek",
+ "wtorek",
+ "\u015broda",
+ "czwartek",
+ "pi\u0105tek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p.n.e.",
+ "n.e."
+ ],
+ "ERAS": [
+ "p.n.e.",
+ "n.e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "stycznia",
+ "lutego",
+ "marca",
+ "kwietnia",
+ "maja",
+ "czerwca",
+ "lipca",
+ "sierpnia",
+ "wrze\u015bnia",
+ "pa\u017adziernika",
+ "listopada",
+ "grudnia"
+ ],
+ "SHORTDAY": [
+ "niedz.",
+ "pon.",
+ "wt.",
+ "\u015br.",
+ "czw.",
+ "pt.",
+ "sob."
+ ],
+ "SHORTMONTH": [
+ "sty",
+ "lut",
+ "mar",
+ "kwi",
+ "maj",
+ "cze",
+ "lip",
+ "sie",
+ "wrz",
+ "pa\u017a",
+ "lis",
+ "gru"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "z\u0142",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pl-pl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i != 1 && i % 10 >= 0 && i % 10 <= 1 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 12 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl.js
new file mode 100644
index 00000000..a37a284f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "niedziela",
+ "poniedzia\u0142ek",
+ "wtorek",
+ "\u015broda",
+ "czwartek",
+ "pi\u0105tek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "p.n.e.",
+ "n.e."
+ ],
+ "ERAS": [
+ "p.n.e.",
+ "n.e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "stycznia",
+ "lutego",
+ "marca",
+ "kwietnia",
+ "maja",
+ "czerwca",
+ "lipca",
+ "sierpnia",
+ "wrze\u015bnia",
+ "pa\u017adziernika",
+ "listopada",
+ "grudnia"
+ ],
+ "SHORTDAY": [
+ "niedz.",
+ "pon.",
+ "wt.",
+ "\u015br.",
+ "czw.",
+ "pt.",
+ "sob."
+ ],
+ "SHORTMONTH": [
+ "sty",
+ "lut",
+ "mar",
+ "kwi",
+ "maj",
+ "cze",
+ "lip",
+ "sie",
+ "wrz",
+ "pa\u017a",
+ "lis",
+ "gru"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "dd.MM.y HH:mm:ss",
+ "mediumDate": "dd.MM.y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "z\u0142",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i != 1 && i % 10 >= 0 && i % 10 <= 1 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 12 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps-af.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps-af.js
new file mode 100644
index 00000000..d6d40775
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps-af.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u063a.\u0645.",
+ "\u063a.\u0648."
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u064a",
+ "\u0641\u0628\u0631\u0648\u0631\u064a",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06ab\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u064a",
+ "\u0641\u0628\u0631\u0648\u0631\u064a",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06ab\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 3,
+ 4
+ ],
+ "fullDate": "EEEE \u062f y \u062f MMMM d",
+ "longDate": "\u062f y \u062f MMMM d",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Af.",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ps-af",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps.js
new file mode 100644
index 00000000..4bbe5111
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ps.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u063a.\u0645.",
+ "\u063a.\u0648."
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u064a",
+ "\u0641\u0628\u0631\u0648\u0631\u064a",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06ab\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u064a",
+ "\u0641\u0628\u0631\u0648\u0631\u064a",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06ab\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 3,
+ 4
+ ],
+ "fullDate": "EEEE \u062f y \u062f MMMM d",
+ "longDate": "\u062f y \u062f MMMM d",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Af.",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ps",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-ao.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-ao.js
new file mode 100644
index 00000000..dcc91dab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-ao.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Kz",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-ao",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-br.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-br.js
new file mode 100644
index 00000000..146aad33
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-br.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "Antes de Cristo",
+ "Ano do Senhor"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d 'de' MMM 'de' y HH:mm:ss",
+ "mediumDate": "d 'de' MMM 'de' y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pt-br",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-cv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-cv.js
new file mode 100644
index 00000000..d9beaa1d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-cv.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CVE",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-cv",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-gw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-gw.js
new file mode 100644
index 00000000..801f3e72
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-gw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-gw",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mo.js
new file mode 100644
index 00000000..fecce7cb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MOP",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-mo",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mz.js
new file mode 100644
index 00000000..e7450a21
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-mz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MTn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-mz",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-pt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-pt.js
new file mode 100644
index 00000000..6718f9dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-pt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-pt",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-st.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-st.js
new file mode 100644
index 00000000..a6ff9cd7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-st.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Db",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-st",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-tl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-tl.js
new file mode 100644
index 00000000..bb36d6dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt-tl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "da manh\u00e3",
+ "da tarde"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "antes de Cristo",
+ "depois de Cristo"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "dd/MM/y HH:mm:ss",
+ "mediumDate": "dd/MM/y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "pt-tl",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt.js
new file mode 100644
index 00000000..4c80611e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_pt.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "domingo",
+ "segunda-feira",
+ "ter\u00e7a-feira",
+ "quarta-feira",
+ "quinta-feira",
+ "sexta-feira",
+ "s\u00e1bado"
+ ],
+ "ERANAMES": [
+ "Antes de Cristo",
+ "Ano do Senhor"
+ ],
+ "ERAS": [
+ "a.C.",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "janeiro",
+ "fevereiro",
+ "mar\u00e7o",
+ "abril",
+ "maio",
+ "junho",
+ "julho",
+ "agosto",
+ "setembro",
+ "outubro",
+ "novembro",
+ "dezembro"
+ ],
+ "SHORTDAY": [
+ "dom",
+ "seg",
+ "ter",
+ "qua",
+ "qui",
+ "sex",
+ "s\u00e1b"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "fev",
+ "mar",
+ "abr",
+ "mai",
+ "jun",
+ "jul",
+ "ago",
+ "set",
+ "out",
+ "nov",
+ "dez"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d 'de' MMM 'de' y HH:mm:ss",
+ "mediumDate": "d 'de' MMM 'de' y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R$",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "pt",
+ "pluralCat": function(n, opt_precision) { if (n >= 0 && n <= 2 && n != 2) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-bo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-bo.js
new file mode 100644
index 00000000..cb05d91a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-bo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Mi\u00e9rcoles",
+ "Jueves",
+ "Viernes",
+ "S\u00e1bado"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "d.C."
+ ],
+ "ERAS": [
+ "BCE",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Qulla puquy",
+ "Hatun puquy",
+ "Pauqar waray",
+ "Ayriwa",
+ "Aymuray",
+ "Inti raymi",
+ "Anta Sitwa",
+ "Qhapaq Sitwa",
+ "Uma raymi",
+ "Kantaray",
+ "Ayamarq\u02bca",
+ "Kapaq Raymi"
+ ],
+ "SHORTDAY": [
+ "Dom",
+ "Lun",
+ "Mar",
+ "Mi\u00e9",
+ "Jue",
+ "Vie",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qul",
+ "Hat",
+ "Pau",
+ "Ayr",
+ "Aym",
+ "Int",
+ "Ant",
+ "Qha",
+ "Uma",
+ "Kan",
+ "Aya",
+ "Kap"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d hh:mm:ss a",
+ "mediumDate": "y MMM d",
+ "mediumTime": "hh:mm:ss a",
+ "short": "dd/MM/y hh:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Bs",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "qu-bo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-ec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-ec.js
new file mode 100644
index 00000000..9978c4a3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-ec.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Mi\u00e9rcoles",
+ "Jueves",
+ "Viernes",
+ "S\u00e1bado"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "d.C."
+ ],
+ "ERAS": [
+ "BCE",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Qulla puquy",
+ "Hatun puquy",
+ "Pauqar waray",
+ "Ayriwa",
+ "Aymuray",
+ "Inti raymi",
+ "Anta Sitwa",
+ "Qhapaq Sitwa",
+ "Uma raymi",
+ "Kantaray",
+ "Ayamarq\u02bca",
+ "Kapaq Raymi"
+ ],
+ "SHORTDAY": [
+ "Dom",
+ "Lun",
+ "Mar",
+ "Mi\u00e9",
+ "Jue",
+ "Vie",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qul",
+ "Hat",
+ "Pau",
+ "Ayr",
+ "Aym",
+ "Int",
+ "Ant",
+ "Qha",
+ "Uma",
+ "Kan",
+ "Aya",
+ "Kap"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d hh:mm:ss a",
+ "mediumDate": "y MMM d",
+ "mediumTime": "hh:mm:ss a",
+ "short": "dd/MM/y hh:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "qu-ec",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-pe.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-pe.js
new file mode 100644
index 00000000..942275b6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu-pe.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Mi\u00e9rcoles",
+ "Jueves",
+ "Viernes",
+ "S\u00e1bado"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "d.C."
+ ],
+ "ERAS": [
+ "BCE",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Qulla puquy",
+ "Hatun puquy",
+ "Pauqar waray",
+ "Ayriwa",
+ "Aymuray",
+ "Inti raymi",
+ "Anta Sitwa",
+ "Qhapaq Sitwa",
+ "Uma raymi",
+ "Kantaray",
+ "Ayamarq\u02bca",
+ "Kapaq Raymi"
+ ],
+ "SHORTDAY": [
+ "Dom",
+ "Lun",
+ "Mar",
+ "Mi\u00e9",
+ "Jue",
+ "Vie",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qul",
+ "Hat",
+ "Pau",
+ "Ayr",
+ "Aym",
+ "Int",
+ "Ant",
+ "Qha",
+ "Uma",
+ "Kan",
+ "Aya",
+ "Kap"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d hh:mm:ss a",
+ "mediumDate": "y MMM d",
+ "mediumTime": "hh:mm:ss a",
+ "short": "dd/MM/y hh:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "S/.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "qu-pe",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu.js
new file mode 100644
index 00000000..e2b56e6d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_qu.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Mi\u00e9rcoles",
+ "Jueves",
+ "Viernes",
+ "S\u00e1bado"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "d.C."
+ ],
+ "ERAS": [
+ "BCE",
+ "d.C."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Qulla puquy",
+ "Hatun puquy",
+ "Pauqar waray",
+ "Ayriwa",
+ "Aymuray",
+ "Inti raymi",
+ "Anta Sitwa",
+ "Qhapaq Sitwa",
+ "Uma raymi",
+ "Kantaray",
+ "Ayamarq\u02bca",
+ "Kapaq Raymi"
+ ],
+ "SHORTDAY": [
+ "Dom",
+ "Lun",
+ "Mar",
+ "Mi\u00e9",
+ "Jue",
+ "Vie",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Qul",
+ "Hat",
+ "Pau",
+ "Ayr",
+ "Aym",
+ "Int",
+ "Ant",
+ "Qha",
+ "Uma",
+ "Kan",
+ "Aya",
+ "Kap"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d hh:mm:ss a",
+ "mediumDate": "y MMM d",
+ "mediumTime": "hh:mm:ss a",
+ "short": "dd/MM/y hh:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "hh:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "S/.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "qu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm-ch.js
new file mode 100644
index 00000000..091c0827
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm-ch.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "sm"
+ ],
+ "DAY": [
+ "dumengia",
+ "glindesdi",
+ "mardi",
+ "mesemna",
+ "gievgia",
+ "venderdi",
+ "sonda"
+ ],
+ "ERANAMES": [
+ "avant Cristus",
+ "suenter Cristus"
+ ],
+ "ERAS": [
+ "av. Cr.",
+ "s. Cr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "schaner",
+ "favrer",
+ "mars",
+ "avrigl",
+ "matg",
+ "zercladur",
+ "fanadur",
+ "avust",
+ "settember",
+ "october",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "du",
+ "gli",
+ "ma",
+ "me",
+ "gie",
+ "ve",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "schan.",
+ "favr.",
+ "mars",
+ "avr.",
+ "matg",
+ "zercl.",
+ "fan.",
+ "avust",
+ "sett.",
+ "oct.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'ils' d 'da' MMMM y",
+ "longDate": "d 'da' MMMM y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "rm-ch",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm.js
new file mode 100644
index 00000000..7bddcf97
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "am",
+ "sm"
+ ],
+ "DAY": [
+ "dumengia",
+ "glindesdi",
+ "mardi",
+ "mesemna",
+ "gievgia",
+ "venderdi",
+ "sonda"
+ ],
+ "ERANAMES": [
+ "avant Cristus",
+ "suenter Cristus"
+ ],
+ "ERAS": [
+ "av. Cr.",
+ "s. Cr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "schaner",
+ "favrer",
+ "mars",
+ "avrigl",
+ "matg",
+ "zercladur",
+ "fanadur",
+ "avust",
+ "settember",
+ "october",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "du",
+ "gli",
+ "ma",
+ "me",
+ "gie",
+ "ve",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "schan.",
+ "favr.",
+ "mars",
+ "avr.",
+ "matg",
+ "zercl.",
+ "fan.",
+ "avust",
+ "sett.",
+ "oct.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'ils' d 'da' MMMM y",
+ "longDate": "d 'da' MMMM y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-yy HH:mm",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "rm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn-bi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn-bi.js
new file mode 100644
index 00000000..cd61a1d4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn-bi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Z.MU.",
+ "Z.MW."
+ ],
+ "DAY": [
+ "Ku w\u2019indwi",
+ "Ku wa mbere",
+ "Ku wa kabiri",
+ "Ku wa gatatu",
+ "Ku wa kane",
+ "Ku wa gatanu",
+ "Ku wa gatandatu"
+ ],
+ "ERANAMES": [
+ "Mbere ya Yezu",
+ "Nyuma ya Yezu"
+ ],
+ "ERAS": [
+ "Mb.Y.",
+ "Ny.Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Nzero",
+ "Ruhuhuma",
+ "Ntwarante",
+ "Ndamukiza",
+ "Rusama",
+ "Ruheshi",
+ "Mukakaro",
+ "Nyandagaro",
+ "Nyakanga",
+ "Gitugutu",
+ "Munyonyo",
+ "Kigarama"
+ ],
+ "SHORTDAY": [
+ "cu.",
+ "mbe.",
+ "kab.",
+ "gtu.",
+ "kan.",
+ "gnu.",
+ "gnd."
+ ],
+ "SHORTMONTH": [
+ "Mut.",
+ "Gas.",
+ "Wer.",
+ "Mat.",
+ "Gic.",
+ "Kam.",
+ "Nya.",
+ "Kan.",
+ "Nze.",
+ "Ukw.",
+ "Ugu.",
+ "Uku."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FBu",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "rn-bi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn.js
new file mode 100644
index 00000000..0a2a5e8e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Z.MU.",
+ "Z.MW."
+ ],
+ "DAY": [
+ "Ku w\u2019indwi",
+ "Ku wa mbere",
+ "Ku wa kabiri",
+ "Ku wa gatatu",
+ "Ku wa kane",
+ "Ku wa gatanu",
+ "Ku wa gatandatu"
+ ],
+ "ERANAMES": [
+ "Mbere ya Yezu",
+ "Nyuma ya Yezu"
+ ],
+ "ERAS": [
+ "Mb.Y.",
+ "Ny.Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Nzero",
+ "Ruhuhuma",
+ "Ntwarante",
+ "Ndamukiza",
+ "Rusama",
+ "Ruheshi",
+ "Mukakaro",
+ "Nyandagaro",
+ "Nyakanga",
+ "Gitugutu",
+ "Munyonyo",
+ "Kigarama"
+ ],
+ "SHORTDAY": [
+ "cu.",
+ "mbe.",
+ "kab.",
+ "gtu.",
+ "kan.",
+ "gnu.",
+ "gnd."
+ ],
+ "SHORTMONTH": [
+ "Mut.",
+ "Gas.",
+ "Wer.",
+ "Mat.",
+ "Gic.",
+ "Kam.",
+ "Nya.",
+ "Kan.",
+ "Nze.",
+ "Ukw.",
+ "Ugu.",
+ "Uku."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FBu",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "rn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-md.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-md.js
new file mode 100644
index 00000000..b3630470
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-md.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "duminic\u0103",
+ "luni",
+ "mar\u021bi",
+ "miercuri",
+ "joi",
+ "vineri",
+ "s\u00e2mb\u0103t\u0103"
+ ],
+ "ERANAMES": [
+ "\u00eenainte de Hristos",
+ "dup\u0103 Hristos"
+ ],
+ "ERAS": [
+ "\u00ee.Hr.",
+ "d.Hr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ianuarie",
+ "februarie",
+ "martie",
+ "aprilie",
+ "mai",
+ "iunie",
+ "iulie",
+ "august",
+ "septembrie",
+ "octombrie",
+ "noiembrie",
+ "decembrie"
+ ],
+ "SHORTDAY": [
+ "Dum",
+ "Lun",
+ "Mar",
+ "Mie",
+ "Joi",
+ "Vin",
+ "S\u00e2m"
+ ],
+ "SHORTMONTH": [
+ "ian.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "iun.",
+ "iul.",
+ "aug.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MDL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ro-md",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (vf.v != 0 || n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-ro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-ro.js
new file mode 100644
index 00000000..d8792260
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro-ro.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "duminic\u0103",
+ "luni",
+ "mar\u021bi",
+ "miercuri",
+ "joi",
+ "vineri",
+ "s\u00e2mb\u0103t\u0103"
+ ],
+ "ERANAMES": [
+ "\u00eenainte de Hristos",
+ "dup\u0103 Hristos"
+ ],
+ "ERAS": [
+ "\u00ee.Hr.",
+ "d.Hr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ianuarie",
+ "februarie",
+ "martie",
+ "aprilie",
+ "mai",
+ "iunie",
+ "iulie",
+ "august",
+ "septembrie",
+ "octombrie",
+ "noiembrie",
+ "decembrie"
+ ],
+ "SHORTDAY": [
+ "Dum",
+ "Lun",
+ "Mar",
+ "Mie",
+ "Joi",
+ "Vin",
+ "S\u00e2m"
+ ],
+ "SHORTMONTH": [
+ "ian.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "iun.",
+ "iul.",
+ "aug.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RON",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ro-ro",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (vf.v != 0 || n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro.js
new file mode 100644
index 00000000..3c52dd2a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ro.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "a.m.",
+ "p.m."
+ ],
+ "DAY": [
+ "duminic\u0103",
+ "luni",
+ "mar\u021bi",
+ "miercuri",
+ "joi",
+ "vineri",
+ "s\u00e2mb\u0103t\u0103"
+ ],
+ "ERANAMES": [
+ "\u00eenainte de Hristos",
+ "dup\u0103 Hristos"
+ ],
+ "ERAS": [
+ "\u00ee.Hr.",
+ "d.Hr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "ianuarie",
+ "februarie",
+ "martie",
+ "aprilie",
+ "mai",
+ "iunie",
+ "iulie",
+ "august",
+ "septembrie",
+ "octombrie",
+ "noiembrie",
+ "decembrie"
+ ],
+ "SHORTDAY": [
+ "Dum",
+ "Lun",
+ "Mar",
+ "Mie",
+ "Joi",
+ "Vin",
+ "S\u00e2m"
+ ],
+ "SHORTMONTH": [
+ "ian.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "mai",
+ "iun.",
+ "iul.",
+ "aug.",
+ "sept.",
+ "oct.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.y HH:mm",
+ "shortDate": "dd.MM.y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RON",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ro",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (vf.v != 0 || n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof-tz.js
new file mode 100644
index 00000000..8458d5ca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "kang\u2019ama",
+ "kingoto"
+ ],
+ "DAY": [
+ "Ijumapili",
+ "Ijumatatu",
+ "Ijumanne",
+ "Ijumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Ijumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Mayesu",
+ "Baada ya Mayesu"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wa kwanza",
+ "Mweri wa kaili",
+ "Mweri wa katatu",
+ "Mweri wa kaana",
+ "Mweri wa tanu",
+ "Mweri wa sita",
+ "Mweri wa saba",
+ "Mweri wa nane",
+ "Mweri wa tisa",
+ "Mweri wa ikumi",
+ "Mweri wa ikumi na moja",
+ "Mweri wa ikumi na mbili"
+ ],
+ "SHORTDAY": [
+ "Ijp",
+ "Ijt",
+ "Ijn",
+ "Ijtn",
+ "Alh",
+ "Iju",
+ "Ijm"
+ ],
+ "SHORTMONTH": [
+ "M1",
+ "M2",
+ "M3",
+ "M4",
+ "M5",
+ "M6",
+ "M7",
+ "M8",
+ "M9",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "rof-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof.js
new file mode 100644
index 00000000..a233d6ca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rof.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "kang\u2019ama",
+ "kingoto"
+ ],
+ "DAY": [
+ "Ijumapili",
+ "Ijumatatu",
+ "Ijumanne",
+ "Ijumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Ijumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Mayesu",
+ "Baada ya Mayesu"
+ ],
+ "ERAS": [
+ "KM",
+ "BM"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mweri wa kwanza",
+ "Mweri wa kaili",
+ "Mweri wa katatu",
+ "Mweri wa kaana",
+ "Mweri wa tanu",
+ "Mweri wa sita",
+ "Mweri wa saba",
+ "Mweri wa nane",
+ "Mweri wa tisa",
+ "Mweri wa ikumi",
+ "Mweri wa ikumi na moja",
+ "Mweri wa ikumi na mbili"
+ ],
+ "SHORTDAY": [
+ "Ijp",
+ "Ijt",
+ "Ijn",
+ "Ijtn",
+ "Alh",
+ "Iju",
+ "Ijm"
+ ],
+ "SHORTMONTH": [
+ "M1",
+ "M2",
+ "M3",
+ "M4",
+ "M5",
+ "M6",
+ "M7",
+ "M8",
+ "M9",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "rof",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-by.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-by.js
new file mode 100644
index 00000000..f735266c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-by.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "BYR",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-by",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kg.js
new file mode 100644
index 00000000..b1d9db98
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KGS",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-kg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kz.js
new file mode 100644
index 00000000..a1c93672
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-kz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b8",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-kz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-md.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-md.js
new file mode 100644
index 00000000..de3f0498
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-md.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MDL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-md",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ru.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ru.js
new file mode 100644
index 00000000..e9337210
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ru.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0440\u0443\u0431.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-ru",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ua.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ua.js
new file mode 100644
index 00000000..f6dfc507
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru-ua.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. HH:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b4",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru-ua",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru.js
new file mode 100644
index 00000000..553360f0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ru.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
+ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
+ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
+ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d. \u044d.",
+ "\u043d. \u044d."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u044f\u043d\u0432\u0430\u0440\u044f",
+ "\u0444\u0435\u0432\u0440\u0430\u043b\u044f",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440\u0435\u043b\u044f",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433\u0443\u0441\u0442\u0430",
+ "\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f",
+ "\u043e\u043a\u0442\u044f\u0431\u0440\u044f",
+ "\u043d\u043e\u044f\u0431\u0440\u044f",
+ "\u0434\u0435\u043a\u0430\u0431\u0440\u044f"
+ ],
+ "SHORTDAY": [
+ "\u0432\u0441",
+ "\u043f\u043d",
+ "\u0432\u0442",
+ "\u0441\u0440",
+ "\u0447\u0442",
+ "\u043f\u0442",
+ "\u0441\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u044f\u043d\u0432.",
+ "\u0444\u0435\u0432\u0440.",
+ "\u043c\u0430\u0440\u0442\u0430",
+ "\u0430\u043f\u0440.",
+ "\u043c\u0430\u044f",
+ "\u0438\u044e\u043d\u044f",
+ "\u0438\u044e\u043b\u044f",
+ "\u0430\u0432\u0433.",
+ "\u0441\u0435\u043d\u0442.",
+ "\u043e\u043a\u0442.",
+ "\u043d\u043e\u044f\u0431.",
+ "\u0434\u0435\u043a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0433'.",
+ "longDate": "d MMMM y '\u0433'.",
+ "medium": "d MMM y '\u0433'. H:mm:ss",
+ "mediumDate": "d MMM y '\u0433'.",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0440\u0443\u0431.",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "ru",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw-rw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw-rw.js
new file mode 100644
index 00000000..7e679df6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw-rw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Ku cyumweru",
+ "Kuwa mbere",
+ "Kuwa kabiri",
+ "Kuwa gatatu",
+ "Kuwa kane",
+ "Kuwa gatanu",
+ "Kuwa gatandatu"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mutarama",
+ "Gashyantare",
+ "Werurwe",
+ "Mata",
+ "Gicuransi",
+ "Kamena",
+ "Nyakanga",
+ "Kanama",
+ "Nzeli",
+ "Ukwakira",
+ "Ugushyingo",
+ "Ukuboza"
+ ],
+ "SHORTDAY": [
+ "cyu.",
+ "mbe.",
+ "kab.",
+ "gtu.",
+ "kan.",
+ "gnu.",
+ "gnd."
+ ],
+ "SHORTMONTH": [
+ "mut.",
+ "gas.",
+ "wer.",
+ "mat.",
+ "gic.",
+ "kam.",
+ "nya.",
+ "kan.",
+ "nze.",
+ "ukw.",
+ "ugu.",
+ "uku."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "rw-rw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw.js
new file mode 100644
index 00000000..2e5db17a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Ku cyumweru",
+ "Kuwa mbere",
+ "Kuwa kabiri",
+ "Kuwa gatatu",
+ "Kuwa kane",
+ "Kuwa gatanu",
+ "Kuwa gatandatu"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mutarama",
+ "Gashyantare",
+ "Werurwe",
+ "Mata",
+ "Gicuransi",
+ "Kamena",
+ "Nyakanga",
+ "Kanama",
+ "Nzeli",
+ "Ukwakira",
+ "Ugushyingo",
+ "Ukuboza"
+ ],
+ "SHORTDAY": [
+ "cyu.",
+ "mbe.",
+ "kab.",
+ "gtu.",
+ "kan.",
+ "gnu.",
+ "gnd."
+ ],
+ "SHORTMONTH": [
+ "mut.",
+ "gas.",
+ "wer.",
+ "mat.",
+ "gic.",
+ "kam.",
+ "nya.",
+ "kan.",
+ "nze.",
+ "ukw.",
+ "ugu.",
+ "uku."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "rw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk-tz.js
new file mode 100644
index 00000000..3dcb29ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "rwk-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk.js
new file mode 100644
index 00000000..726ed59a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_rwk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "rwk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah-ru.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah-ru.js
new file mode 100644
index 00000000..85b3776f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah-ru.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u042d\u0418",
+ "\u042d\u041a"
+ ],
+ "DAY": [
+ "\u0411\u0430\u0441\u043a\u044b\u04bb\u044b\u0430\u043d\u043d\u044c\u0430",
+ "\u0411\u044d\u043d\u0438\u0434\u0438\u044d\u043b\u0438\u043d\u043d\u044c\u0438\u043a",
+ "\u041e\u043f\u0442\u0443\u043e\u0440\u0443\u043d\u043d\u044c\u0443\u043a",
+ "\u0421\u044d\u0440\u044d\u0434\u044d",
+ "\u0427\u044d\u043f\u043f\u0438\u044d\u0440",
+ "\u0411\u044d\u044d\u0442\u0438\u04a5\u0441\u044d",
+ "\u0421\u0443\u0431\u0443\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0431. \u044d. \u0438.",
+ "\u0431. \u044d"
+ ],
+ "ERAS": [
+ "\u0431. \u044d. \u0438.",
+ "\u0431. \u044d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0422\u043e\u0445\u0441\u0443\u043d\u043d\u044c\u0443",
+ "\u041e\u043b\u0443\u043d\u043d\u044c\u0443",
+ "\u041a\u0443\u043b\u0443\u043d \u0442\u0443\u0442\u0430\u0440",
+ "\u041c\u0443\u0443\u0441 \u0443\u0441\u0442\u0430\u0440",
+ "\u042b\u0430\u043c \u044b\u0439\u044b\u043d",
+ "\u0411\u044d\u0441 \u044b\u0439\u044b\u043d",
+ "\u041e\u0442 \u044b\u0439\u044b\u043d",
+ "\u0410\u0442\u044b\u0440\u0434\u044c\u044b\u0445 \u044b\u0439\u044b\u043d",
+ "\u0411\u0430\u043b\u0430\u0495\u0430\u043d \u044b\u0439\u044b\u043d",
+ "\u0410\u043b\u0442\u044b\u043d\u043d\u044c\u044b",
+ "\u0421\u044d\u0442\u0438\u043d\u043d\u044c\u0438",
+ "\u0410\u0445\u0441\u044b\u043d\u043d\u044c\u044b"
+ ],
+ "SHORTDAY": [
+ "\u0411\u0441",
+ "\u0411\u043d",
+ "\u041e\u043f",
+ "\u0421\u044d",
+ "\u0427\u043f",
+ "\u0411\u044d",
+ "\u0421\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0422\u043e\u0445\u0441",
+ "\u041e\u043b\u0443\u043d",
+ "\u041a\u043b\u043d_\u0442\u0442\u0440",
+ "\u041c\u0443\u0441_\u0443\u0441\u0442",
+ "\u042b\u0430\u043c_\u0439\u043d",
+ "\u0411\u044d\u0441_\u0439\u043d",
+ "\u041e\u0442_\u0439\u043d",
+ "\u0410\u0442\u0440\u0434\u044c_\u0439\u043d",
+ "\u0411\u043b\u0495\u043d_\u0439\u043d",
+ "\u0410\u043b\u0442",
+ "\u0421\u044d\u0442",
+ "\u0410\u0445\u0441"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y '\u0441\u044b\u043b' MMMM d '\u043a\u04af\u043d\u044d', EEEE",
+ "longDate": "y, MMMM d",
+ "medium": "y, MMM d HH:mm:ss",
+ "mediumDate": "y, MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/M/d HH:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0440\u0443\u0431.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sah-ru",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah.js
new file mode 100644
index 00000000..23bd88ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sah.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u042d\u0418",
+ "\u042d\u041a"
+ ],
+ "DAY": [
+ "\u0411\u0430\u0441\u043a\u044b\u04bb\u044b\u0430\u043d\u043d\u044c\u0430",
+ "\u0411\u044d\u043d\u0438\u0434\u0438\u044d\u043b\u0438\u043d\u043d\u044c\u0438\u043a",
+ "\u041e\u043f\u0442\u0443\u043e\u0440\u0443\u043d\u043d\u044c\u0443\u043a",
+ "\u0421\u044d\u0440\u044d\u0434\u044d",
+ "\u0427\u044d\u043f\u043f\u0438\u044d\u0440",
+ "\u0411\u044d\u044d\u0442\u0438\u04a5\u0441\u044d",
+ "\u0421\u0443\u0431\u0443\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0431. \u044d. \u0438.",
+ "\u0431. \u044d"
+ ],
+ "ERAS": [
+ "\u0431. \u044d. \u0438.",
+ "\u0431. \u044d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0422\u043e\u0445\u0441\u0443\u043d\u043d\u044c\u0443",
+ "\u041e\u043b\u0443\u043d\u043d\u044c\u0443",
+ "\u041a\u0443\u043b\u0443\u043d \u0442\u0443\u0442\u0430\u0440",
+ "\u041c\u0443\u0443\u0441 \u0443\u0441\u0442\u0430\u0440",
+ "\u042b\u0430\u043c \u044b\u0439\u044b\u043d",
+ "\u0411\u044d\u0441 \u044b\u0439\u044b\u043d",
+ "\u041e\u0442 \u044b\u0439\u044b\u043d",
+ "\u0410\u0442\u044b\u0440\u0434\u044c\u044b\u0445 \u044b\u0439\u044b\u043d",
+ "\u0411\u0430\u043b\u0430\u0495\u0430\u043d \u044b\u0439\u044b\u043d",
+ "\u0410\u043b\u0442\u044b\u043d\u043d\u044c\u044b",
+ "\u0421\u044d\u0442\u0438\u043d\u043d\u044c\u0438",
+ "\u0410\u0445\u0441\u044b\u043d\u043d\u044c\u044b"
+ ],
+ "SHORTDAY": [
+ "\u0411\u0441",
+ "\u0411\u043d",
+ "\u041e\u043f",
+ "\u0421\u044d",
+ "\u0427\u043f",
+ "\u0411\u044d",
+ "\u0421\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0422\u043e\u0445\u0441",
+ "\u041e\u043b\u0443\u043d",
+ "\u041a\u043b\u043d_\u0442\u0442\u0440",
+ "\u041c\u0443\u0441_\u0443\u0441\u0442",
+ "\u042b\u0430\u043c_\u0439\u043d",
+ "\u0411\u044d\u0441_\u0439\u043d",
+ "\u041e\u0442_\u0439\u043d",
+ "\u0410\u0442\u0440\u0434\u044c_\u0439\u043d",
+ "\u0411\u043b\u0495\u043d_\u0439\u043d",
+ "\u0410\u043b\u0442",
+ "\u0421\u044d\u0442",
+ "\u0410\u0445\u0441"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y '\u0441\u044b\u043b' MMMM d '\u043a\u04af\u043d\u044d', EEEE",
+ "longDate": "y, MMMM d",
+ "medium": "y, MMM d HH:mm:ss",
+ "mediumDate": "y, MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/M/d HH:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0440\u0443\u0431.",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sah",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq-ke.js
new file mode 100644
index 00000000..a7f89980
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Tesiran",
+ "Teipa"
+ ],
+ "DAY": [
+ "Mderot ee are",
+ "Mderot ee kuni",
+ "Mderot ee ong\u2019wan",
+ "Mderot ee inet",
+ "Mderot ee ile",
+ "Mderot ee sapa",
+ "Mderot ee kwe"
+ ],
+ "ERANAMES": [
+ "Kabla ya Christo",
+ "Baada ya Christo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Lapa le obo",
+ "Lapa le waare",
+ "Lapa le okuni",
+ "Lapa le ong\u2019wan",
+ "Lapa le imet",
+ "Lapa le ile",
+ "Lapa le sapa",
+ "Lapa le isiet",
+ "Lapa le saal",
+ "Lapa le tomon",
+ "Lapa le tomon obo",
+ "Lapa le tomon waare"
+ ],
+ "SHORTDAY": [
+ "Are",
+ "Kun",
+ "Ong",
+ "Ine",
+ "Ile",
+ "Sap",
+ "Kwe"
+ ],
+ "SHORTMONTH": [
+ "Obo",
+ "Waa",
+ "Oku",
+ "Ong",
+ "Ime",
+ "Ile",
+ "Sap",
+ "Isi",
+ "Saa",
+ "Tom",
+ "Tob",
+ "Tow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "saq-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq.js
new file mode 100644
index 00000000..b515603a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_saq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Tesiran",
+ "Teipa"
+ ],
+ "DAY": [
+ "Mderot ee are",
+ "Mderot ee kuni",
+ "Mderot ee ong\u2019wan",
+ "Mderot ee inet",
+ "Mderot ee ile",
+ "Mderot ee sapa",
+ "Mderot ee kwe"
+ ],
+ "ERANAMES": [
+ "Kabla ya Christo",
+ "Baada ya Christo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Lapa le obo",
+ "Lapa le waare",
+ "Lapa le okuni",
+ "Lapa le ong\u2019wan",
+ "Lapa le imet",
+ "Lapa le ile",
+ "Lapa le sapa",
+ "Lapa le isiet",
+ "Lapa le saal",
+ "Lapa le tomon",
+ "Lapa le tomon obo",
+ "Lapa le tomon waare"
+ ],
+ "SHORTDAY": [
+ "Are",
+ "Kun",
+ "Ong",
+ "Ine",
+ "Ile",
+ "Sap",
+ "Kwe"
+ ],
+ "SHORTMONTH": [
+ "Obo",
+ "Waa",
+ "Oku",
+ "Ong",
+ "Ime",
+ "Ile",
+ "Sap",
+ "Isi",
+ "Saa",
+ "Tom",
+ "Tob",
+ "Tow"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "saq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp-tz.js
new file mode 100644
index 00000000..1e5a0e82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Lwamilawu",
+ "Pashamihe"
+ ],
+ "DAY": [
+ "Mulungu",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alahamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Ashanali uKilisito",
+ "Pamwandi ya Kilisto"
+ ],
+ "ERAS": [
+ "AK",
+ "PK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mupalangulwa",
+ "Mwitope",
+ "Mushende",
+ "Munyi",
+ "Mushende Magali",
+ "Mujimbi",
+ "Mushipepo",
+ "Mupuguto",
+ "Munyense",
+ "Mokhu",
+ "Musongandembwe",
+ "Muhaano"
+ ],
+ "SHORTDAY": [
+ "Mul",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Mup",
+ "Mwi",
+ "Msh",
+ "Mun",
+ "Mag",
+ "Muj",
+ "Msp",
+ "Mpg",
+ "Mye",
+ "Mok",
+ "Mus",
+ "Muh"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "sbp-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp.js
new file mode 100644
index 00000000..da6106a6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sbp.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Lwamilawu",
+ "Pashamihe"
+ ],
+ "DAY": [
+ "Mulungu",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alahamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Ashanali uKilisito",
+ "Pamwandi ya Kilisto"
+ ],
+ "ERAS": [
+ "AK",
+ "PK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Mupalangulwa",
+ "Mwitope",
+ "Mushende",
+ "Munyi",
+ "Mushende Magali",
+ "Mujimbi",
+ "Mushipepo",
+ "Mupuguto",
+ "Munyense",
+ "Mokhu",
+ "Musongandembwe",
+ "Muhaano"
+ ],
+ "SHORTDAY": [
+ "Mul",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Mup",
+ "Mwi",
+ "Msh",
+ "Mun",
+ "Mag",
+ "Muj",
+ "Msp",
+ "Mpg",
+ "Mye",
+ "Mok",
+ "Mus",
+ "Muh"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "sbp",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-fi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-fi.js
new file mode 100644
index 00000000..62de6b1a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-fi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "i\u0111itbeaivet",
+ "eahketbeaivet"
+ ],
+ "DAY": [
+ "aejlege",
+ "m\u00e5anta",
+ "d\u00e4jsta",
+ "gaskevahkoe",
+ "d\u00e5arsta",
+ "bearjadahke",
+ "laavadahke"
+ ],
+ "ERANAMES": [
+ "ovdal Kristtusa",
+ "ma\u014b\u014bel Kristtusa"
+ ],
+ "ERAS": [
+ "o.Kr.",
+ "m.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "o\u0111\u0111ajagem\u00e1nnu",
+ "guovvam\u00e1nnu",
+ "njuk\u010dam\u00e1nnu",
+ "cuo\u014bom\u00e1nnu",
+ "miessem\u00e1nnu",
+ "geassem\u00e1nnu",
+ "suoidnem\u00e1nnu",
+ "borgem\u00e1nnu",
+ "\u010dak\u010dam\u00e1nnu",
+ "golggotm\u00e1nnu",
+ "sk\u00e1bmam\u00e1nnu",
+ "juovlam\u00e1nnu"
+ ],
+ "SHORTDAY": [
+ "sotn",
+ "vuos",
+ "ma\u014b",
+ "gask",
+ "duor",
+ "bear",
+ "l\u00e1v"
+ ],
+ "SHORTMONTH": [
+ "o\u0111\u0111ajage",
+ "guovva",
+ "njuk\u010da",
+ "cuo\u014bo",
+ "miesse",
+ "geasse",
+ "suoidne",
+ "borge",
+ "\u010dak\u010da",
+ "golggot",
+ "sk\u00e1bma",
+ "juovla"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "se-fi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-no.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-no.js
new file mode 100644
index 00000000..b2e24ae6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-no.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "i\u0111itbeaivet",
+ "eahketbeaivet"
+ ],
+ "DAY": [
+ "sotnabeaivi",
+ "vuoss\u00e1rga",
+ "ma\u014b\u014beb\u00e1rga",
+ "gaskavahkku",
+ "duorasdat",
+ "bearjadat",
+ "l\u00e1vvardat"
+ ],
+ "ERANAMES": [
+ "ovdal Kristtusa",
+ "ma\u014b\u014bel Kristtusa"
+ ],
+ "ERAS": [
+ "o.Kr.",
+ "m.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "o\u0111\u0111ajagem\u00e1nnu",
+ "guovvam\u00e1nnu",
+ "njuk\u010dam\u00e1nnu",
+ "cuo\u014bom\u00e1nnu",
+ "miessem\u00e1nnu",
+ "geassem\u00e1nnu",
+ "suoidnem\u00e1nnu",
+ "borgem\u00e1nnu",
+ "\u010dak\u010dam\u00e1nnu",
+ "golggotm\u00e1nnu",
+ "sk\u00e1bmam\u00e1nnu",
+ "juovlam\u00e1nnu"
+ ],
+ "SHORTDAY": [
+ "sotn",
+ "vuos",
+ "ma\u014b",
+ "gask",
+ "duor",
+ "bear",
+ "l\u00e1v"
+ ],
+ "SHORTMONTH": [
+ "o\u0111\u0111j",
+ "guov",
+ "njuk",
+ "cuo",
+ "mies",
+ "geas",
+ "suoi",
+ "borg",
+ "\u010dak\u010d",
+ "golg",
+ "sk\u00e1b",
+ "juov"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "se-no",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-se.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-se.js
new file mode 100644
index 00000000..7915d431
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se-se.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "i\u0111itbeaivet",
+ "eahketbeaivet"
+ ],
+ "DAY": [
+ "sotnabeaivi",
+ "vuoss\u00e1rga",
+ "ma\u014b\u014beb\u00e1rga",
+ "gaskavahkku",
+ "duorasdat",
+ "bearjadat",
+ "l\u00e1vvardat"
+ ],
+ "ERANAMES": [
+ "ovdal Kristtusa",
+ "ma\u014b\u014bel Kristtusa"
+ ],
+ "ERAS": [
+ "o.Kr.",
+ "m.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "o\u0111\u0111ajagem\u00e1nnu",
+ "guovvam\u00e1nnu",
+ "njuk\u010dam\u00e1nnu",
+ "cuo\u014bom\u00e1nnu",
+ "miessem\u00e1nnu",
+ "geassem\u00e1nnu",
+ "suoidnem\u00e1nnu",
+ "borgem\u00e1nnu",
+ "\u010dak\u010dam\u00e1nnu",
+ "golggotm\u00e1nnu",
+ "sk\u00e1bmam\u00e1nnu",
+ "juovlam\u00e1nnu"
+ ],
+ "SHORTDAY": [
+ "sotn",
+ "vuos",
+ "ma\u014b",
+ "gask",
+ "duor",
+ "bear",
+ "l\u00e1v"
+ ],
+ "SHORTMONTH": [
+ "o\u0111\u0111j",
+ "guov",
+ "njuk",
+ "cuo",
+ "mies",
+ "geas",
+ "suoi",
+ "borg",
+ "\u010dak\u010d",
+ "golg",
+ "sk\u00e1b",
+ "juov"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "se-se",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se.js
new file mode 100644
index 00000000..0a6d7d66
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_se.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "i\u0111itbeaivet",
+ "eahketbeaivet"
+ ],
+ "DAY": [
+ "sotnabeaivi",
+ "vuoss\u00e1rga",
+ "ma\u014b\u014beb\u00e1rga",
+ "gaskavahkku",
+ "duorasdat",
+ "bearjadat",
+ "l\u00e1vvardat"
+ ],
+ "ERANAMES": [
+ "ovdal Kristtusa",
+ "ma\u014b\u014bel Kristtusa"
+ ],
+ "ERAS": [
+ "o.Kr.",
+ "m.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "o\u0111\u0111ajagem\u00e1nnu",
+ "guovvam\u00e1nnu",
+ "njuk\u010dam\u00e1nnu",
+ "cuo\u014bom\u00e1nnu",
+ "miessem\u00e1nnu",
+ "geassem\u00e1nnu",
+ "suoidnem\u00e1nnu",
+ "borgem\u00e1nnu",
+ "\u010dak\u010dam\u00e1nnu",
+ "golggotm\u00e1nnu",
+ "sk\u00e1bmam\u00e1nnu",
+ "juovlam\u00e1nnu"
+ ],
+ "SHORTDAY": [
+ "sotn",
+ "vuos",
+ "ma\u014b",
+ "gask",
+ "duor",
+ "bear",
+ "l\u00e1v"
+ ],
+ "SHORTMONTH": [
+ "o\u0111\u0111j",
+ "guov",
+ "njuk",
+ "cuo",
+ "mies",
+ "geas",
+ "suoi",
+ "borg",
+ "\u010dak\u010d",
+ "golg",
+ "sk\u00e1b",
+ "juov"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "se",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh-mz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh-mz.js
new file mode 100644
index 00000000..f723c867
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh-mz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dimingu",
+ "Chiposi",
+ "Chipiri",
+ "Chitatu",
+ "Chinai",
+ "Chishanu",
+ "Sabudu"
+ ],
+ "ERANAMES": [
+ "Antes de Cristo",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "AC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janeiro",
+ "Fevreiro",
+ "Marco",
+ "Abril",
+ "Maio",
+ "Junho",
+ "Julho",
+ "Augusto",
+ "Setembro",
+ "Otubro",
+ "Novembro",
+ "Decembro"
+ ],
+ "SHORTDAY": [
+ "Dim",
+ "Pos",
+ "Pir",
+ "Tat",
+ "Nai",
+ "Sha",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fev",
+ "Mar",
+ "Abr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Set",
+ "Otu",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d 'de' MMM 'de' y HH:mm:ss",
+ "mediumDate": "d 'de' MMM 'de' y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MTn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "seh-mz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh.js
new file mode 100644
index 00000000..d9c55eec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_seh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Dimingu",
+ "Chiposi",
+ "Chipiri",
+ "Chitatu",
+ "Chinai",
+ "Chishanu",
+ "Sabudu"
+ ],
+ "ERANAMES": [
+ "Antes de Cristo",
+ "Anno Domini"
+ ],
+ "ERAS": [
+ "AC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janeiro",
+ "Fevreiro",
+ "Marco",
+ "Abril",
+ "Maio",
+ "Junho",
+ "Julho",
+ "Augusto",
+ "Setembro",
+ "Otubro",
+ "Novembro",
+ "Decembro"
+ ],
+ "SHORTDAY": [
+ "Dim",
+ "Pos",
+ "Pir",
+ "Tat",
+ "Nai",
+ "Sha",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Fev",
+ "Mar",
+ "Abr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Set",
+ "Otu",
+ "Nov",
+ "Dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d 'de' MMMM 'de' y",
+ "longDate": "d 'de' MMMM 'de' y",
+ "medium": "d 'de' MMM 'de' y HH:mm:ss",
+ "mediumDate": "d 'de' MMM 'de' y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MTn",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "seh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses-ml.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses-ml.js
new file mode 100644
index 00000000..596dfe43
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses-ml.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Adduha",
+ "Aluula"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamiisa",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "ses-ml",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses.js
new file mode 100644
index 00000000..e150d779
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ses.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Adduha",
+ "Aluula"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamiisa",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "ses",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg-cf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg-cf.js
new file mode 100644
index 00000000..fb6d2f76
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg-cf.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ND",
+ "LK"
+ ],
+ "DAY": [
+ "Bikua-\u00f4ko",
+ "B\u00efkua-\u00fbse",
+ "B\u00efkua-pt\u00e2",
+ "B\u00efkua-us\u00ef\u00f6",
+ "B\u00efkua-ok\u00fc",
+ "L\u00e2p\u00f4s\u00f6",
+ "L\u00e2yenga"
+ ],
+ "ERANAMES": [
+ "K\u00f4zo na Kr\u00eestu",
+ "Na pek\u00f4 t\u00ee Kr\u00eestu"
+ ],
+ "ERAS": [
+ "KnK",
+ "NpK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Nyenye",
+ "Fulund\u00efgi",
+ "Mb\u00e4ng\u00fc",
+ "Ngub\u00f9e",
+ "B\u00eal\u00e4w\u00fc",
+ "F\u00f6ndo",
+ "Lengua",
+ "K\u00fck\u00fcr\u00fc",
+ "Mvuka",
+ "Ngberere",
+ "Nab\u00e4nd\u00fcru",
+ "Kakauka"
+ ],
+ "SHORTDAY": [
+ "Bk1",
+ "Bk2",
+ "Bk3",
+ "Bk4",
+ "Bk5",
+ "L\u00e2p",
+ "L\u00e2y"
+ ],
+ "SHORTMONTH": [
+ "Nye",
+ "Ful",
+ "Mb\u00e4",
+ "Ngu",
+ "B\u00eal",
+ "F\u00f6n",
+ "Len",
+ "K\u00fck",
+ "Mvu",
+ "Ngb",
+ "Nab",
+ "Kak"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sg-cf",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg.js
new file mode 100644
index 00000000..3b671dae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sg.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ND",
+ "LK"
+ ],
+ "DAY": [
+ "Bikua-\u00f4ko",
+ "B\u00efkua-\u00fbse",
+ "B\u00efkua-pt\u00e2",
+ "B\u00efkua-us\u00ef\u00f6",
+ "B\u00efkua-ok\u00fc",
+ "L\u00e2p\u00f4s\u00f6",
+ "L\u00e2yenga"
+ ],
+ "ERANAMES": [
+ "K\u00f4zo na Kr\u00eestu",
+ "Na pek\u00f4 t\u00ee Kr\u00eestu"
+ ],
+ "ERAS": [
+ "KnK",
+ "NpK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Nyenye",
+ "Fulund\u00efgi",
+ "Mb\u00e4ng\u00fc",
+ "Ngub\u00f9e",
+ "B\u00eal\u00e4w\u00fc",
+ "F\u00f6ndo",
+ "Lengua",
+ "K\u00fck\u00fcr\u00fc",
+ "Mvuka",
+ "Ngberere",
+ "Nab\u00e4nd\u00fcru",
+ "Kakauka"
+ ],
+ "SHORTDAY": [
+ "Bk1",
+ "Bk2",
+ "Bk3",
+ "Bk4",
+ "Bk5",
+ "L\u00e2p",
+ "L\u00e2y"
+ ],
+ "SHORTMONTH": [
+ "Nye",
+ "Ful",
+ "Mb\u00e4",
+ "Ngu",
+ "B\u00eal",
+ "F\u00f6n",
+ "Len",
+ "K\u00fck",
+ "Mvu",
+ "Ngb",
+ "Nab",
+ "Kak"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn-ma.js
new file mode 100644
index 00000000..02156c69
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn-ma.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "tifawt",
+ "tadgg\u02b7at"
+ ],
+ "DAY": [
+ "asamas",
+ "aynas",
+ "asinas",
+ "ak\u1e5bas",
+ "akwas",
+ "asimwas",
+ "asi\u1e0dyas"
+ ],
+ "ERANAMES": [
+ "dat n \u025bisa",
+ "dffir n \u025bisa"
+ ],
+ "ERAS": [
+ "da\u025b",
+ "df\u025b"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "innayr",
+ "b\u1e5bay\u1e5b",
+ "ma\u1e5b\u1e63",
+ "ibrir",
+ "mayyu",
+ "yunyu",
+ "yulyuz",
+ "\u0263uct",
+ "cutanbir",
+ "ktubr",
+ "nuwanbir",
+ "dujanbir"
+ ],
+ "SHORTDAY": [
+ "asa",
+ "ayn",
+ "asi",
+ "ak\u1e5b",
+ "akw",
+ "asim",
+ "asi\u1e0d"
+ ],
+ "SHORTMONTH": [
+ "inn",
+ "b\u1e5ba",
+ "ma\u1e5b",
+ "ibr",
+ "may",
+ "yun",
+ "yul",
+ "\u0263uc",
+ "cut",
+ "ktu",
+ "nuw",
+ "duj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "shi-latn-ma",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn.js
new file mode 100644
index 00000000..6b8b6f70
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "tifawt",
+ "tadgg\u02b7at"
+ ],
+ "DAY": [
+ "asamas",
+ "aynas",
+ "asinas",
+ "ak\u1e5bas",
+ "akwas",
+ "asimwas",
+ "asi\u1e0dyas"
+ ],
+ "ERANAMES": [
+ "dat n \u025bisa",
+ "dffir n \u025bisa"
+ ],
+ "ERAS": [
+ "da\u025b",
+ "df\u025b"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "innayr",
+ "b\u1e5bay\u1e5b",
+ "ma\u1e5b\u1e63",
+ "ibrir",
+ "mayyu",
+ "yunyu",
+ "yulyuz",
+ "\u0263uct",
+ "cutanbir",
+ "ktubr",
+ "nuwanbir",
+ "dujanbir"
+ ],
+ "SHORTDAY": [
+ "asa",
+ "ayn",
+ "asi",
+ "ak\u1e5b",
+ "akw",
+ "asim",
+ "asi\u1e0d"
+ ],
+ "SHORTMONTH": [
+ "inn",
+ "b\u1e5ba",
+ "ma\u1e5b",
+ "ibr",
+ "may",
+ "yun",
+ "yul",
+ "\u0263uc",
+ "cut",
+ "ktu",
+ "nuw",
+ "duj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "shi-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng-ma.js
new file mode 100644
index 00000000..998d17a2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng-ma.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u2d5c\u2d49\u2d3c\u2d30\u2d61\u2d5c",
+ "\u2d5c\u2d30\u2d37\u2d33\u2d33\u2d6f\u2d30\u2d5c"
+ ],
+ "DAY": [
+ "\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59",
+ "\u2d30\u2d62\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d55\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d61\u2d30\u2d59",
+ "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59"
+ ],
+ "ERANAMES": [
+ "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30",
+ "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30"
+ ],
+ "ERAS": [
+ "\u2d37\u2d30\u2d44",
+ "\u2d37\u2d3c\u2d44"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54",
+ "\u2d31\u2d55\u2d30\u2d62\u2d55",
+ "\u2d4e\u2d30\u2d55\u2d5a",
+ "\u2d49\u2d31\u2d54\u2d49\u2d54",
+ "\u2d4e\u2d30\u2d62\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4f\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63",
+ "\u2d56\u2d53\u2d5b\u2d5c",
+ "\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d3d\u2d5c\u2d53\u2d31\u2d54",
+ "\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d37\u2d53\u2d4a\u2d30\u2d4f\u2d31\u2d49\u2d54"
+ ],
+ "SHORTDAY": [
+ "\u2d30\u2d59\u2d30",
+ "\u2d30\u2d62\u2d4f",
+ "\u2d30\u2d59\u2d49",
+ "\u2d30\u2d3d\u2d55",
+ "\u2d30\u2d3d\u2d61",
+ "\u2d30\u2d59\u2d49\u2d4e",
+ "\u2d30\u2d59\u2d49\u2d39"
+ ],
+ "SHORTMONTH": [
+ "\u2d49\u2d4f\u2d4f",
+ "\u2d31\u2d55\u2d30",
+ "\u2d4e\u2d30\u2d55",
+ "\u2d49\u2d31\u2d54",
+ "\u2d4e\u2d30\u2d62",
+ "\u2d62\u2d53\u2d4f",
+ "\u2d62\u2d53\u2d4d",
+ "\u2d56\u2d53\u2d5b",
+ "\u2d5b\u2d53\u2d5c",
+ "\u2d3d\u2d5c\u2d53",
+ "\u2d4f\u2d53\u2d61",
+ "\u2d37\u2d53\u2d4a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "shi-tfng-ma",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng.js
new file mode 100644
index 00000000..a2d825b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi-tfng.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u2d5c\u2d49\u2d3c\u2d30\u2d61\u2d5c",
+ "\u2d5c\u2d30\u2d37\u2d33\u2d33\u2d6f\u2d30\u2d5c"
+ ],
+ "DAY": [
+ "\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59",
+ "\u2d30\u2d62\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d55\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d61\u2d30\u2d59",
+ "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59"
+ ],
+ "ERANAMES": [
+ "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30",
+ "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30"
+ ],
+ "ERAS": [
+ "\u2d37\u2d30\u2d44",
+ "\u2d37\u2d3c\u2d44"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54",
+ "\u2d31\u2d55\u2d30\u2d62\u2d55",
+ "\u2d4e\u2d30\u2d55\u2d5a",
+ "\u2d49\u2d31\u2d54\u2d49\u2d54",
+ "\u2d4e\u2d30\u2d62\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4f\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63",
+ "\u2d56\u2d53\u2d5b\u2d5c",
+ "\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d3d\u2d5c\u2d53\u2d31\u2d54",
+ "\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d37\u2d53\u2d4a\u2d30\u2d4f\u2d31\u2d49\u2d54"
+ ],
+ "SHORTDAY": [
+ "\u2d30\u2d59\u2d30",
+ "\u2d30\u2d62\u2d4f",
+ "\u2d30\u2d59\u2d49",
+ "\u2d30\u2d3d\u2d55",
+ "\u2d30\u2d3d\u2d61",
+ "\u2d30\u2d59\u2d49\u2d4e",
+ "\u2d30\u2d59\u2d49\u2d39"
+ ],
+ "SHORTMONTH": [
+ "\u2d49\u2d4f\u2d4f",
+ "\u2d31\u2d55\u2d30",
+ "\u2d4e\u2d30\u2d55",
+ "\u2d49\u2d31\u2d54",
+ "\u2d4e\u2d30\u2d62",
+ "\u2d62\u2d53\u2d4f",
+ "\u2d62\u2d53\u2d4d",
+ "\u2d56\u2d53\u2d5b",
+ "\u2d5b\u2d53\u2d5c",
+ "\u2d3d\u2d5c\u2d53",
+ "\u2d4f\u2d53\u2d61",
+ "\u2d37\u2d53\u2d4a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "shi-tfng",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi.js
new file mode 100644
index 00000000..5f2fe453
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_shi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u2d5c\u2d49\u2d3c\u2d30\u2d61\u2d5c",
+ "\u2d5c\u2d30\u2d37\u2d33\u2d33\u2d6f\u2d30\u2d5c"
+ ],
+ "DAY": [
+ "\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59",
+ "\u2d30\u2d62\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d55\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d61\u2d30\u2d59",
+ "\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59"
+ ],
+ "ERANAMES": [
+ "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30",
+ "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30"
+ ],
+ "ERAS": [
+ "\u2d37\u2d30\u2d44",
+ "\u2d37\u2d3c\u2d44"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54",
+ "\u2d31\u2d55\u2d30\u2d62\u2d55",
+ "\u2d4e\u2d30\u2d55\u2d5a",
+ "\u2d49\u2d31\u2d54\u2d49\u2d54",
+ "\u2d4e\u2d30\u2d62\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4f\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63",
+ "\u2d56\u2d53\u2d5b\u2d5c",
+ "\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d3d\u2d5c\u2d53\u2d31\u2d54",
+ "\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d37\u2d53\u2d4a\u2d30\u2d4f\u2d31\u2d49\u2d54"
+ ],
+ "SHORTDAY": [
+ "\u2d30\u2d59\u2d30",
+ "\u2d30\u2d62\u2d4f",
+ "\u2d30\u2d59\u2d49",
+ "\u2d30\u2d3d\u2d55",
+ "\u2d30\u2d3d\u2d61",
+ "\u2d30\u2d59\u2d49\u2d4e",
+ "\u2d30\u2d59\u2d49\u2d39"
+ ],
+ "SHORTMONTH": [
+ "\u2d49\u2d4f\u2d4f",
+ "\u2d31\u2d55\u2d30",
+ "\u2d4e\u2d30\u2d55",
+ "\u2d49\u2d31\u2d54",
+ "\u2d4e\u2d30\u2d62",
+ "\u2d62\u2d53\u2d4f",
+ "\u2d62\u2d53\u2d4d",
+ "\u2d56\u2d53\u2d5b",
+ "\u2d5b\u2d53\u2d5c",
+ "\u2d3d\u2d5c\u2d53",
+ "\u2d4f\u2d53\u2d61",
+ "\u2d37\u2d53\u2d4a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "shi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si-lk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si-lk.js
new file mode 100644
index 00000000..c216c753
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si-lk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0db4\u0dd9.\u0dc0.",
+ "\u0db4.\u0dc0."
+ ],
+ "DAY": [
+ "\u0d89\u0dbb\u0dd2\u0daf\u0dcf",
+ "\u0dc3\u0db3\u0dd4\u0daf\u0dcf",
+ "\u0d85\u0d9f\u0dc4\u0dbb\u0dd4\u0dc0\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0daf\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0dca\u200d\u0dbb\u0dc4\u0dc3\u0dca\u0db4\u0dad\u0dd2\u0db1\u0dca\u0daf\u0dcf",
+ "\u0dc3\u0dd2\u0d9a\u0dd4\u0dbb\u0dcf\u0daf\u0dcf",
+ "\u0dc3\u0dd9\u0db1\u0dc3\u0dd4\u0dbb\u0dcf\u0daf\u0dcf"
+ ],
+ "ERANAMES": [
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0db4\u0dd6\u0dbb\u0dca\u200d\u0dc0",
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0dc0\u0dbb\u0dca\u200d\u0dc2"
+ ],
+ "ERAS": [
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0db4\u0dd6.",
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0dc0."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0da2\u0db1\u0dc0\u0dcf\u0dbb\u0dd2",
+ "\u0db4\u0dd9\u0db6\u0dbb\u0dc0\u0dcf\u0dbb\u0dd2",
+ "\u0db8\u0dcf\u0dbb\u0dca\u0dad\u0dd4",
+ "\u0d85\u0db4\u0dca\u200d\u0dbb\u0dda\u0dbd\u0dca",
+ "\u0db8\u0dd0\u0dba\u0dd2",
+ "\u0da2\u0dd6\u0db1\u0dd2",
+ "\u0da2\u0dd6\u0dbd\u0dd2",
+ "\u0d85\u0d9c\u0ddd\u0dc3\u0dca\u0dad\u0dd4",
+ "\u0dc3\u0dd0\u0db4\u0dca\u0dad\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca",
+ "\u0d94\u0d9a\u0dca\u0dad\u0ddd\u0db6\u0dbb\u0dca",
+ "\u0db1\u0ddc\u0dc0\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca",
+ "\u0daf\u0dd9\u0dc3\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca"
+ ],
+ "SHORTDAY": [
+ "\u0d89\u0dbb\u0dd2\u0daf\u0dcf",
+ "\u0dc3\u0db3\u0dd4\u0daf\u0dcf",
+ "\u0d85\u0d9f\u0dc4",
+ "\u0db6\u0daf\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0dca\u200d\u0dbb\u0dc4\u0dc3\u0dca",
+ "\u0dc3\u0dd2\u0d9a\u0dd4",
+ "\u0dc3\u0dd9\u0db1"
+ ],
+ "SHORTMONTH": [
+ "\u0da2\u0db1",
+ "\u0db4\u0dd9\u0db6",
+ "\u0db8\u0dcf\u0dbb\u0dca\u0dad\u0dd4",
+ "\u0d85\u0db4\u0dca\u200d\u0dbb\u0dda\u0dbd\u0dca",
+ "\u0db8\u0dd0\u0dba\u0dd2",
+ "\u0da2\u0dd6\u0db1\u0dd2",
+ "\u0da2\u0dd6\u0dbd\u0dd2",
+ "\u0d85\u0d9c\u0ddd",
+ "\u0dc3\u0dd0\u0db4\u0dca",
+ "\u0d94\u0d9a\u0dca",
+ "\u0db1\u0ddc\u0dc0\u0dd0",
+ "\u0daf\u0dd9\u0dc3\u0dd0"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d a h.mm.ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "a h.mm.ss",
+ "short": "y-MM-dd a h.mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "a h.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "si-lk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if ((n == 0 || n == 1) || i == 0 && vf.f == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si.js
new file mode 100644
index 00000000..bfcdd628
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_si.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0db4\u0dd9.\u0dc0.",
+ "\u0db4.\u0dc0."
+ ],
+ "DAY": [
+ "\u0d89\u0dbb\u0dd2\u0daf\u0dcf",
+ "\u0dc3\u0db3\u0dd4\u0daf\u0dcf",
+ "\u0d85\u0d9f\u0dc4\u0dbb\u0dd4\u0dc0\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0daf\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0dca\u200d\u0dbb\u0dc4\u0dc3\u0dca\u0db4\u0dad\u0dd2\u0db1\u0dca\u0daf\u0dcf",
+ "\u0dc3\u0dd2\u0d9a\u0dd4\u0dbb\u0dcf\u0daf\u0dcf",
+ "\u0dc3\u0dd9\u0db1\u0dc3\u0dd4\u0dbb\u0dcf\u0daf\u0dcf"
+ ],
+ "ERANAMES": [
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0db4\u0dd6\u0dbb\u0dca\u200d\u0dc0",
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2\u0dc3\u0dca\u0dad\u0dd4 \u0dc0\u0dbb\u0dca\u200d\u0dc2"
+ ],
+ "ERAS": [
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0db4\u0dd6.",
+ "\u0d9a\u0dca\u200d\u0dbb\u0dd2.\u0dc0."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0da2\u0db1\u0dc0\u0dcf\u0dbb\u0dd2",
+ "\u0db4\u0dd9\u0db6\u0dbb\u0dc0\u0dcf\u0dbb\u0dd2",
+ "\u0db8\u0dcf\u0dbb\u0dca\u0dad\u0dd4",
+ "\u0d85\u0db4\u0dca\u200d\u0dbb\u0dda\u0dbd\u0dca",
+ "\u0db8\u0dd0\u0dba\u0dd2",
+ "\u0da2\u0dd6\u0db1\u0dd2",
+ "\u0da2\u0dd6\u0dbd\u0dd2",
+ "\u0d85\u0d9c\u0ddd\u0dc3\u0dca\u0dad\u0dd4",
+ "\u0dc3\u0dd0\u0db4\u0dca\u0dad\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca",
+ "\u0d94\u0d9a\u0dca\u0dad\u0ddd\u0db6\u0dbb\u0dca",
+ "\u0db1\u0ddc\u0dc0\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca",
+ "\u0daf\u0dd9\u0dc3\u0dd0\u0db8\u0dca\u0db6\u0dbb\u0dca"
+ ],
+ "SHORTDAY": [
+ "\u0d89\u0dbb\u0dd2\u0daf\u0dcf",
+ "\u0dc3\u0db3\u0dd4\u0daf\u0dcf",
+ "\u0d85\u0d9f\u0dc4",
+ "\u0db6\u0daf\u0dcf\u0daf\u0dcf",
+ "\u0db6\u0dca\u200d\u0dbb\u0dc4\u0dc3\u0dca",
+ "\u0dc3\u0dd2\u0d9a\u0dd4",
+ "\u0dc3\u0dd9\u0db1"
+ ],
+ "SHORTMONTH": [
+ "\u0da2\u0db1",
+ "\u0db4\u0dd9\u0db6",
+ "\u0db8\u0dcf\u0dbb\u0dca\u0dad\u0dd4",
+ "\u0d85\u0db4\u0dca\u200d\u0dbb\u0dda\u0dbd\u0dca",
+ "\u0db8\u0dd0\u0dba\u0dd2",
+ "\u0da2\u0dd6\u0db1\u0dd2",
+ "\u0da2\u0dd6\u0dbd\u0dd2",
+ "\u0d85\u0d9c\u0ddd",
+ "\u0dc3\u0dd0\u0db4\u0dca",
+ "\u0d94\u0d9a\u0dca",
+ "\u0db1\u0ddc\u0dc0\u0dd0",
+ "\u0daf\u0dd9\u0dc3\u0dd0"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d a h.mm.ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "a h.mm.ss",
+ "short": "y-MM-dd a h.mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "a h.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "si",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if ((n == 0 || n == 1) || i == 0 && vf.f == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk-sk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk-sk.js
new file mode 100644
index 00000000..01f0f0cb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk-sk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopoludnia",
+ "odpoludnia"
+ ],
+ "DAY": [
+ "nede\u013ea",
+ "pondelok",
+ "utorok",
+ "streda",
+ "\u0161tvrtok",
+ "piatok",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "pred Kristom",
+ "po Kristovi"
+ ],
+ "ERAS": [
+ "pred Kr.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janu\u00e1ra",
+ "febru\u00e1ra",
+ "marca",
+ "apr\u00edla",
+ "m\u00e1ja",
+ "j\u00fana",
+ "j\u00fala",
+ "augusta",
+ "septembra",
+ "okt\u00f3bra",
+ "novembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "ne",
+ "po",
+ "ut",
+ "st",
+ "\u0161t",
+ "pi",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "m\u00e1j",
+ "j\u00fan",
+ "j\u00fal",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. M. y H:mm:ss",
+ "mediumDate": "d. M. y",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sk-sk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i >= 2 && i <= 4 && vf.v == 0) { return PLURAL_CATEGORY.FEW; } if (vf.v != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk.js
new file mode 100644
index 00000000..7618fe38
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dopoludnia",
+ "odpoludnia"
+ ],
+ "DAY": [
+ "nede\u013ea",
+ "pondelok",
+ "utorok",
+ "streda",
+ "\u0161tvrtok",
+ "piatok",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "pred Kristom",
+ "po Kristovi"
+ ],
+ "ERAS": [
+ "pred Kr.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janu\u00e1ra",
+ "febru\u00e1ra",
+ "marca",
+ "apr\u00edla",
+ "m\u00e1ja",
+ "j\u00fana",
+ "j\u00fala",
+ "augusta",
+ "septembra",
+ "okt\u00f3bra",
+ "novembra",
+ "decembra"
+ ],
+ "SHORTDAY": [
+ "ne",
+ "po",
+ "ut",
+ "st",
+ "\u0161t",
+ "pi",
+ "so"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "m\u00e1j",
+ "j\u00fan",
+ "j\u00fal",
+ "aug",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. M. y H:mm:ss",
+ "mediumDate": "d. M. y",
+ "mediumTime": "H:mm:ss",
+ "short": "dd.MM.yy H:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } if (i >= 2 && i <= 4 && vf.v == 0) { return PLURAL_CATEGORY.FEW; } if (vf.v != 0) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl-si.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl-si.js
new file mode 100644
index 00000000..f480b789
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl-si.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dop.",
+ "pop."
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljek",
+ "torek",
+ "sreda",
+ "\u010detrtek",
+ "petek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "pred na\u0161im \u0161tetjem",
+ "na\u0161e \u0161tetje"
+ ],
+ "ERAS": [
+ "pr. n. \u0161t.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "marec",
+ "april",
+ "maj",
+ "junij",
+ "julij",
+ "avgust",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "ned.",
+ "pon.",
+ "tor.",
+ "sre.",
+ "\u010det.",
+ "pet.",
+ "sob."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "maj",
+ "jun.",
+ "jul.",
+ "avg.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y",
+ "longDate": "dd. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d. MM. yy HH:mm",
+ "shortDate": "d. MM. yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sl-si",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 100 == 1) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 100 == 2) { return PLURAL_CATEGORY.TWO; } if (vf.v == 0 && i % 100 >= 3 && i % 100 <= 4 || vf.v != 0) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl.js
new file mode 100644
index 00000000..24d4a779
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "dop.",
+ "pop."
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljek",
+ "torek",
+ "sreda",
+ "\u010detrtek",
+ "petek",
+ "sobota"
+ ],
+ "ERANAMES": [
+ "pred na\u0161im \u0161tetjem",
+ "na\u0161e \u0161tetje"
+ ],
+ "ERAS": [
+ "pr. n. \u0161t.",
+ "po Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "marec",
+ "april",
+ "maj",
+ "junij",
+ "julij",
+ "avgust",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "ned.",
+ "pon.",
+ "tor.",
+ "sre.",
+ "\u010det.",
+ "pet.",
+ "sob."
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mar.",
+ "apr.",
+ "maj",
+ "jun.",
+ "jul.",
+ "avg.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y",
+ "longDate": "dd. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d. MM. yy HH:mm",
+ "shortDate": "d. MM. yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 100 == 1) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 100 == 2) { return PLURAL_CATEGORY.TWO; } if (vf.v == 0 && i % 100 >= 3 && i % 100 <= 4 || vf.v != 0) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn-fi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn-fi.js
new file mode 100644
index 00000000..027b0a2c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn-fi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "pasepeeivi",
+ "vuossaarg\u00e2",
+ "majebaarg\u00e2",
+ "koskoho",
+ "tuor\u00e2stuv",
+ "v\u00e1stuppeeivi",
+ "l\u00e1vurduv"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "M01",
+ "M02",
+ "M03",
+ "M04",
+ "M05",
+ "M06",
+ "M07",
+ "M08",
+ "M09",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "SHORTDAY": [
+ "pa",
+ "vu",
+ "ma",
+ "ko",
+ "tu",
+ "v\u00e1",
+ "l\u00e1"
+ ],
+ "SHORTMONTH": [
+ "M01",
+ "M02",
+ "M03",
+ "M04",
+ "M05",
+ "M06",
+ "M07",
+ "M08",
+ "M09",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "smn-fi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn.js
new file mode 100644
index 00000000..68c71cfa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_smn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "pasepeeivi",
+ "vuossaarg\u00e2",
+ "majebaarg\u00e2",
+ "koskoho",
+ "tuor\u00e2stuv",
+ "v\u00e1stuppeeivi",
+ "l\u00e1vurduv"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "M01",
+ "M02",
+ "M03",
+ "M04",
+ "M05",
+ "M06",
+ "M07",
+ "M08",
+ "M09",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "SHORTDAY": [
+ "pa",
+ "vu",
+ "ma",
+ "ko",
+ "tu",
+ "v\u00e1",
+ "l\u00e1"
+ ],
+ "SHORTMONTH": [
+ "M01",
+ "M02",
+ "M03",
+ "M04",
+ "M05",
+ "M06",
+ "M07",
+ "M08",
+ "M09",
+ "M10",
+ "M11",
+ "M12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "smn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn-zw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn-zw.js
new file mode 100644
index 00000000..1d8cd0ff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn-zw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Svondo",
+ "Muvhuro",
+ "Chipiri",
+ "Chitatu",
+ "China",
+ "Chishanu",
+ "Mugovera"
+ ],
+ "ERANAMES": [
+ "Kristo asati auya",
+ "Kristo ashaya"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ndira",
+ "Kukadzi",
+ "Kurume",
+ "Kubvumbi",
+ "Chivabvu",
+ "Chikumi",
+ "Chikunguru",
+ "Nyamavhuvhu",
+ "Gunyana",
+ "Gumiguru",
+ "Mbudzi",
+ "Zvita"
+ ],
+ "SHORTDAY": [
+ "Svo",
+ "Muv",
+ "Chip",
+ "Chit",
+ "Chin",
+ "Chis",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Ndi",
+ "Kuk",
+ "Kur",
+ "Kub",
+ "Chv",
+ "Chk",
+ "Chg",
+ "Nya",
+ "Gun",
+ "Gum",
+ "Mb",
+ "Zvi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sn-zw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn.js
new file mode 100644
index 00000000..7b16b4dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Svondo",
+ "Muvhuro",
+ "Chipiri",
+ "Chitatu",
+ "China",
+ "Chishanu",
+ "Mugovera"
+ ],
+ "ERANAMES": [
+ "Kristo asati auya",
+ "Kristo ashaya"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ndira",
+ "Kukadzi",
+ "Kurume",
+ "Kubvumbi",
+ "Chivabvu",
+ "Chikumi",
+ "Chikunguru",
+ "Nyamavhuvhu",
+ "Gunyana",
+ "Gumiguru",
+ "Mbudzi",
+ "Zvita"
+ ],
+ "SHORTDAY": [
+ "Svo",
+ "Muv",
+ "Chip",
+ "Chit",
+ "Chin",
+ "Chis",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Ndi",
+ "Kuk",
+ "Kur",
+ "Kub",
+ "Chv",
+ "Chk",
+ "Chg",
+ "Nya",
+ "Gun",
+ "Gum",
+ "Mb",
+ "Zvi"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-dj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-dj.js
new file mode 100644
index 00000000..d8307cbd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-dj.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "sn.",
+ "gn."
+ ],
+ "DAY": [
+ "Axad",
+ "Isniin",
+ "Talaado",
+ "Arbaco",
+ "Khamiis",
+ "Jimco",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Ciise ka hor (CS)",
+ "Ciise ka dib (CS)"
+ ],
+ "ERAS": [
+ "CK",
+ "CD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Bisha Koobaad",
+ "Bisha Labaad",
+ "Bisha Saddexaad",
+ "Bisha Afraad",
+ "Bisha Shanaad",
+ "Bisha Lixaad",
+ "Bisha Todobaad",
+ "Bisha Sideedaad",
+ "Bisha Sagaalaad",
+ "Bisha Tobnaad",
+ "Bisha Kow iyo Tobnaad",
+ "Bisha Laba iyo Tobnaad"
+ ],
+ "SHORTDAY": [
+ "Axd",
+ "Isn",
+ "Tal",
+ "Arb",
+ "Kha",
+ "Jim",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Kob",
+ "Lab",
+ "Sad",
+ "Afr",
+ "Sha",
+ "Lix",
+ "Tod",
+ "Sid",
+ "Sag",
+ "Tob",
+ "KIT",
+ "LIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Fdj",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "so-dj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-et.js
new file mode 100644
index 00000000..ef34ea2c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-et.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "sn.",
+ "gn."
+ ],
+ "DAY": [
+ "Axad",
+ "Isniin",
+ "Talaado",
+ "Arbaco",
+ "Khamiis",
+ "Jimco",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Ciise ka hor (CS)",
+ "Ciise ka dib (CS)"
+ ],
+ "ERAS": [
+ "CK",
+ "CD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Bisha Koobaad",
+ "Bisha Labaad",
+ "Bisha Saddexaad",
+ "Bisha Afraad",
+ "Bisha Shanaad",
+ "Bisha Lixaad",
+ "Bisha Todobaad",
+ "Bisha Sideedaad",
+ "Bisha Sagaalaad",
+ "Bisha Tobnaad",
+ "Bisha Kow iyo Tobnaad",
+ "Bisha Laba iyo Tobnaad"
+ ],
+ "SHORTDAY": [
+ "Axd",
+ "Isn",
+ "Tal",
+ "Arb",
+ "Kha",
+ "Jim",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Kob",
+ "Lab",
+ "Sad",
+ "Afr",
+ "Sha",
+ "Lix",
+ "Tod",
+ "Sid",
+ "Sag",
+ "Tob",
+ "KIT",
+ "LIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "so-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-ke.js
new file mode 100644
index 00000000..67fc74e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "sn.",
+ "gn."
+ ],
+ "DAY": [
+ "Axad",
+ "Isniin",
+ "Talaado",
+ "Arbaco",
+ "Khamiis",
+ "Jimco",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Ciise ka hor (CS)",
+ "Ciise ka dib (CS)"
+ ],
+ "ERAS": [
+ "CK",
+ "CD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Bisha Koobaad",
+ "Bisha Labaad",
+ "Bisha Saddexaad",
+ "Bisha Afraad",
+ "Bisha Shanaad",
+ "Bisha Lixaad",
+ "Bisha Todobaad",
+ "Bisha Sideedaad",
+ "Bisha Sagaalaad",
+ "Bisha Tobnaad",
+ "Bisha Kow iyo Tobnaad",
+ "Bisha Laba iyo Tobnaad"
+ ],
+ "SHORTDAY": [
+ "Axd",
+ "Isn",
+ "Tal",
+ "Arb",
+ "Kha",
+ "Jim",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Kob",
+ "Lab",
+ "Sad",
+ "Afr",
+ "Sha",
+ "Lix",
+ "Tod",
+ "Sid",
+ "Sag",
+ "Tob",
+ "KIT",
+ "LIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "so-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-so.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-so.js
new file mode 100644
index 00000000..c91a4235
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so-so.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "sn.",
+ "gn."
+ ],
+ "DAY": [
+ "Axad",
+ "Isniin",
+ "Talaado",
+ "Arbaco",
+ "Khamiis",
+ "Jimco",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Ciise ka hor (CS)",
+ "Ciise ka dib (CS)"
+ ],
+ "ERAS": [
+ "CK",
+ "CD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Bisha Koobaad",
+ "Bisha Labaad",
+ "Bisha Saddexaad",
+ "Bisha Afraad",
+ "Bisha Shanaad",
+ "Bisha Lixaad",
+ "Bisha Todobaad",
+ "Bisha Sideedaad",
+ "Bisha Sagaalaad",
+ "Bisha Tobnaad",
+ "Bisha Kow iyo Tobnaad",
+ "Bisha Laba iyo Tobnaad"
+ ],
+ "SHORTDAY": [
+ "Axd",
+ "Isn",
+ "Tal",
+ "Arb",
+ "Kha",
+ "Jim",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Kob",
+ "Lab",
+ "Sad",
+ "Afr",
+ "Sha",
+ "Lix",
+ "Tod",
+ "Sid",
+ "Sag",
+ "Tob",
+ "KIT",
+ "LIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SOS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "so-so",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so.js
new file mode 100644
index 00000000..743a24ba
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_so.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "sn.",
+ "gn."
+ ],
+ "DAY": [
+ "Axad",
+ "Isniin",
+ "Talaado",
+ "Arbaco",
+ "Khamiis",
+ "Jimco",
+ "Sabti"
+ ],
+ "ERANAMES": [
+ "Ciise ka hor (CS)",
+ "Ciise ka dib (CS)"
+ ],
+ "ERAS": [
+ "CK",
+ "CD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Bisha Koobaad",
+ "Bisha Labaad",
+ "Bisha Saddexaad",
+ "Bisha Afraad",
+ "Bisha Shanaad",
+ "Bisha Lixaad",
+ "Bisha Todobaad",
+ "Bisha Sideedaad",
+ "Bisha Sagaalaad",
+ "Bisha Tobnaad",
+ "Bisha Kow iyo Tobnaad",
+ "Bisha Laba iyo Tobnaad"
+ ],
+ "SHORTDAY": [
+ "Axd",
+ "Isn",
+ "Tal",
+ "Arb",
+ "Kha",
+ "Jim",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Kob",
+ "Lab",
+ "Sad",
+ "Afr",
+ "Sha",
+ "Lix",
+ "Tod",
+ "Sid",
+ "Sag",
+ "Tob",
+ "KIT",
+ "LIT"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SOS",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "so",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-al.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-al.js
new file mode 100644
index 00000000..6dac5e79
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-al.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "paradite",
+ "pasdite"
+ ],
+ "DAY": [
+ "e diel",
+ "e h\u00ebn\u00eb",
+ "e mart\u00eb",
+ "e m\u00ebrkur\u00eb",
+ "e enjte",
+ "e premte",
+ "e shtun\u00eb"
+ ],
+ "ERANAMES": [
+ "para er\u00ebs s\u00eb re",
+ "er\u00ebs s\u00eb re"
+ ],
+ "ERAS": [
+ "p.e.r.",
+ "e.r."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janar",
+ "shkurt",
+ "mars",
+ "prill",
+ "maj",
+ "qershor",
+ "korrik",
+ "gusht",
+ "shtator",
+ "tetor",
+ "n\u00ebntor",
+ "dhjetor"
+ ],
+ "SHORTDAY": [
+ "Die",
+ "H\u00ebn",
+ "Mar",
+ "M\u00ebr",
+ "Enj",
+ "Pre",
+ "Sht"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Shk",
+ "Mar",
+ "Pri",
+ "Maj",
+ "Qer",
+ "Kor",
+ "Gsh",
+ "Sht",
+ "Tet",
+ "N\u00ebn",
+ "Dhj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy HH:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Lek",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sq-al",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-mk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-mk.js
new file mode 100644
index 00000000..e7f5c31e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-mk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "paradite",
+ "pasdite"
+ ],
+ "DAY": [
+ "e diel",
+ "e h\u00ebn\u00eb",
+ "e mart\u00eb",
+ "e m\u00ebrkur\u00eb",
+ "e enjte",
+ "e premte",
+ "e shtun\u00eb"
+ ],
+ "ERANAMES": [
+ "para er\u00ebs s\u00eb re",
+ "er\u00ebs s\u00eb re"
+ ],
+ "ERAS": [
+ "p.e.r.",
+ "e.r."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janar",
+ "shkurt",
+ "mars",
+ "prill",
+ "maj",
+ "qershor",
+ "korrik",
+ "gusht",
+ "shtator",
+ "tetor",
+ "n\u00ebntor",
+ "dhjetor"
+ ],
+ "SHORTDAY": [
+ "Die",
+ "H\u00ebn",
+ "Mar",
+ "M\u00ebr",
+ "Enj",
+ "Pre",
+ "Sht"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Shk",
+ "Mar",
+ "Pri",
+ "Maj",
+ "Qer",
+ "Kor",
+ "Gsh",
+ "Sht",
+ "Tet",
+ "N\u00ebn",
+ "Dhj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy HH:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sq-mk",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-xk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-xk.js
new file mode 100644
index 00000000..ccdf61f5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq-xk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "paradite",
+ "pasdite"
+ ],
+ "DAY": [
+ "e diel",
+ "e h\u00ebn\u00eb",
+ "e mart\u00eb",
+ "e m\u00ebrkur\u00eb",
+ "e enjte",
+ "e premte",
+ "e shtun\u00eb"
+ ],
+ "ERANAMES": [
+ "para er\u00ebs s\u00eb re",
+ "er\u00ebs s\u00eb re"
+ ],
+ "ERAS": [
+ "p.e.r.",
+ "e.r."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janar",
+ "shkurt",
+ "mars",
+ "prill",
+ "maj",
+ "qershor",
+ "korrik",
+ "gusht",
+ "shtator",
+ "tetor",
+ "n\u00ebntor",
+ "dhjetor"
+ ],
+ "SHORTDAY": [
+ "Die",
+ "H\u00ebn",
+ "Mar",
+ "M\u00ebr",
+ "Enj",
+ "Pre",
+ "Sht"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Shk",
+ "Mar",
+ "Pri",
+ "Maj",
+ "Qer",
+ "Kor",
+ "Gsh",
+ "Sht",
+ "Tet",
+ "N\u00ebn",
+ "Dhj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy HH:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sq-xk",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq.js
new file mode 100644
index 00000000..bc614eed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sq.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "paradite",
+ "pasdite"
+ ],
+ "DAY": [
+ "e diel",
+ "e h\u00ebn\u00eb",
+ "e mart\u00eb",
+ "e m\u00ebrkur\u00eb",
+ "e enjte",
+ "e premte",
+ "e shtun\u00eb"
+ ],
+ "ERANAMES": [
+ "para er\u00ebs s\u00eb re",
+ "er\u00ebs s\u00eb re"
+ ],
+ "ERAS": [
+ "p.e.r.",
+ "e.r."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janar",
+ "shkurt",
+ "mars",
+ "prill",
+ "maj",
+ "qershor",
+ "korrik",
+ "gusht",
+ "shtator",
+ "tetor",
+ "n\u00ebntor",
+ "dhjetor"
+ ],
+ "SHORTDAY": [
+ "Die",
+ "H\u00ebn",
+ "Mar",
+ "M\u00ebr",
+ "Enj",
+ "Pre",
+ "Sht"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Shk",
+ "Mar",
+ "Pri",
+ "Maj",
+ "Qer",
+ "Kor",
+ "Gsh",
+ "Sht",
+ "Tet",
+ "N\u00ebn",
+ "Dhj"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy HH:mm",
+ "shortDate": "d.M.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Lek",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sq",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-ba.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-ba.js
new file mode 100644
index 00000000..e3843b15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-ba.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH:mm:ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy. HH:mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-cyrl-ba",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-me.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-me.js
new file mode 100644
index 00000000..3bf9c2cc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-me.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-cyrl-me",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-rs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-rs.js
new file mode 100644
index 00000000..0f883f0b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-rs.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-cyrl-rs",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-xk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-xk.js
new file mode 100644
index 00000000..cf7c3e2f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl-xk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-cyrl-xk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl.js
new file mode 100644
index 00000000..a917cf7f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-cyrl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-cyrl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-ba.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-ba.js
new file mode 100644
index 00000000..54d8cd0e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-ba.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pre podne",
+ "po podne"
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljak",
+ "utorak",
+ "sreda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Pre nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "jun",
+ "jul",
+ "avgust",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sre",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "avg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH:mm:ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH:mm:ss",
+ "short": "d.M.yy. HH:mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "KM",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-latn-ba",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-me.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-me.js
new file mode 100644
index 00000000..cc0607a1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-me.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pre podne",
+ "po podne"
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljak",
+ "utorak",
+ "sreda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Pre nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "jun",
+ "jul",
+ "avgust",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sre",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "avg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-latn-me",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-rs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-rs.js
new file mode 100644
index 00000000..517e8eab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-rs.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pre podne",
+ "po podne"
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljak",
+ "utorak",
+ "sreda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Pre nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "jun",
+ "jul",
+ "avgust",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sre",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "avg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-latn-rs",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-xk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-xk.js
new file mode 100644
index 00000000..1cb50a73
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn-xk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pre podne",
+ "po podne"
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljak",
+ "utorak",
+ "sreda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Pre nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "jun",
+ "jul",
+ "avgust",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sre",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "avg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-latn-xk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn.js
new file mode 100644
index 00000000..040041da
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "pre podne",
+ "po podne"
+ ],
+ "DAY": [
+ "nedelja",
+ "ponedeljak",
+ "utorak",
+ "sreda",
+ "\u010detvrtak",
+ "petak",
+ "subota"
+ ],
+ "ERANAMES": [
+ "Pre nove ere",
+ "Nove ere"
+ ],
+ "ERAS": [
+ "p. n. e.",
+ "n. e."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januar",
+ "februar",
+ "mart",
+ "april",
+ "maj",
+ "jun",
+ "jul",
+ "avgust",
+ "septembar",
+ "oktobar",
+ "novembar",
+ "decembar"
+ ],
+ "SHORTDAY": [
+ "ned",
+ "pon",
+ "uto",
+ "sre",
+ "\u010det",
+ "pet",
+ "sub"
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "maj",
+ "jun",
+ "jul",
+ "avg",
+ "sep",
+ "okt",
+ "nov",
+ "dec"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr.js
new file mode 100644
index 00000000..15f2f1de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0440\u0435 \u043f\u043e\u0434\u043d\u0435",
+ "\u043f\u043e \u043f\u043e\u0434\u043d\u0435"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0435\u0459\u0430",
+ "\u043f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a",
+ "\u0443\u0442\u043e\u0440\u0430\u043a",
+ "\u0441\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0440\u0442\u0430\u043a",
+ "\u043f\u0435\u0442\u0430\u043a",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u041f\u0440\u0435 \u043d\u043e\u0432\u0435 \u0435\u0440\u0435",
+ "\u041d\u043e\u0432\u0435 \u0435\u0440\u0435"
+ ],
+ "ERAS": [
+ "\u043f. \u043d. \u0435.",
+ "\u043d. \u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0458\u0430\u043d\u0443\u0430\u0440",
+ "\u0444\u0435\u0431\u0440\u0443\u0430\u0440",
+ "\u043c\u0430\u0440\u0442",
+ "\u0430\u043f\u0440\u0438\u043b",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433\u0443\u0441\u0442",
+ "\u0441\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440",
+ "\u043e\u043a\u0442\u043e\u0431\u0430\u0440",
+ "\u043d\u043e\u0432\u0435\u043c\u0431\u0430\u0440",
+ "\u0434\u0435\u0446\u0435\u043c\u0431\u0430\u0440"
+ ],
+ "SHORTDAY": [
+ "\u043d\u0435\u0434",
+ "\u043f\u043e\u043d",
+ "\u0443\u0442\u043e",
+ "\u0441\u0440\u0435",
+ "\u0447\u0435\u0442",
+ "\u043f\u0435\u0442",
+ "\u0441\u0443\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0458\u0430\u043d",
+ "\u0444\u0435\u0431",
+ "\u043c\u0430\u0440",
+ "\u0430\u043f\u0440",
+ "\u043c\u0430\u0458",
+ "\u0458\u0443\u043d",
+ "\u0458\u0443\u043b",
+ "\u0430\u0432\u0433",
+ "\u0441\u0435\u043f",
+ "\u043e\u043a\u0442",
+ "\u043d\u043e\u0432",
+ "\u0434\u0435\u0446"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, dd. MMMM y.",
+ "longDate": "dd. MMMM y.",
+ "medium": "dd.MM.y. HH.mm.ss",
+ "mediumDate": "dd.MM.y.",
+ "mediumTime": "HH.mm.ss",
+ "short": "d.M.yy. HH.mm",
+ "shortDate": "d.M.yy.",
+ "shortTime": "HH.mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "din",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) { return PLURAL_CATEGORY.FEW; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-sz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-sz.js
new file mode 100644
index 00000000..ae1fdd5f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-sz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lisontfo",
+ "uMsombuluko",
+ "Lesibili",
+ "Lesitsatfu",
+ "Lesine",
+ "Lesihlanu",
+ "uMgcibelo"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Bhimbidvwane",
+ "iNdlovana",
+ "iNdlovu-lenkhulu",
+ "Mabasa",
+ "iNkhwekhweti",
+ "iNhlaba",
+ "Kholwane",
+ "iNgci",
+ "iNyoni",
+ "iMphala",
+ "Lweti",
+ "iNgongoni"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mso",
+ "Bil",
+ "Tsa",
+ "Ne",
+ "Hla",
+ "Mgc"
+ ],
+ "SHORTMONTH": [
+ "Bhi",
+ "Van",
+ "Vol",
+ "Mab",
+ "Nkh",
+ "Nhl",
+ "Kho",
+ "Ngc",
+ "Nyo",
+ "Mph",
+ "Lwe",
+ "Ngo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "SZL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ss-sz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-za.js
new file mode 100644
index 00000000..afb5b99b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lisontfo",
+ "uMsombuluko",
+ "Lesibili",
+ "Lesitsatfu",
+ "Lesine",
+ "Lesihlanu",
+ "uMgcibelo"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Bhimbidvwane",
+ "iNdlovana",
+ "iNdlovu-lenkhulu",
+ "Mabasa",
+ "iNkhwekhweti",
+ "iNhlaba",
+ "Kholwane",
+ "iNgci",
+ "iNyoni",
+ "iMphala",
+ "Lweti",
+ "iNgongoni"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mso",
+ "Bil",
+ "Tsa",
+ "Ne",
+ "Hla",
+ "Mgc"
+ ],
+ "SHORTMONTH": [
+ "Bhi",
+ "Van",
+ "Vol",
+ "Mab",
+ "Nkh",
+ "Nhl",
+ "Kho",
+ "Ngc",
+ "Nyo",
+ "Mph",
+ "Lwe",
+ "Ngo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ss-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss.js
new file mode 100644
index 00000000..3ff88460
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ss.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Lisontfo",
+ "uMsombuluko",
+ "Lesibili",
+ "Lesitsatfu",
+ "Lesine",
+ "Lesihlanu",
+ "uMgcibelo"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Bhimbidvwane",
+ "iNdlovana",
+ "iNdlovu-lenkhulu",
+ "Mabasa",
+ "iNkhwekhweti",
+ "iNhlaba",
+ "Kholwane",
+ "iNgci",
+ "iNyoni",
+ "iMphala",
+ "Lweti",
+ "iNgongoni"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mso",
+ "Bil",
+ "Tsa",
+ "Ne",
+ "Hla",
+ "Mgc"
+ ],
+ "SHORTMONTH": [
+ "Bhi",
+ "Van",
+ "Vol",
+ "Mab",
+ "Nkh",
+ "Nhl",
+ "Kho",
+ "Ngc",
+ "Nyo",
+ "Mph",
+ "Lwe",
+ "Ngo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ss",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy-er.js
new file mode 100644
index 00000000..d4cb8e5d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy-er.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Naba Sambat",
+ "Sani",
+ "Salus",
+ "Rabuq",
+ "Camus",
+ "Jumqata",
+ "Qunxa Sambat"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Liiqen",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Nab",
+ "San",
+ "Sal",
+ "Rab",
+ "Cam",
+ "Jum",
+ "Qun"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ssy-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy.js
new file mode 100644
index 00000000..93c0eba0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ssy.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "saaku",
+ "carra"
+ ],
+ "DAY": [
+ "Naba Sambat",
+ "Sani",
+ "Salus",
+ "Rabuq",
+ "Camus",
+ "Jumqata",
+ "Qunxa Sambat"
+ ],
+ "ERANAMES": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "ERAS": [
+ "Yaasuusuk Duma",
+ "Yaasuusuk Wadir"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Qunxa Garablu",
+ "Kudo",
+ "Ciggilta Kudo",
+ "Agda Baxis",
+ "Caxah Alsa",
+ "Qasa Dirri",
+ "Qado Dirri",
+ "Liiqen",
+ "Waysu",
+ "Diteli",
+ "Ximoli",
+ "Kaxxa Garablu"
+ ],
+ "SHORTDAY": [
+ "Nab",
+ "San",
+ "Sal",
+ "Rab",
+ "Cam",
+ "Jum",
+ "Qun"
+ ],
+ "SHORTMONTH": [
+ "Qun",
+ "Nah",
+ "Cig",
+ "Agd",
+ "Cax",
+ "Qas",
+ "Qad",
+ "Leq",
+ "Way",
+ "Dit",
+ "Xim",
+ "Kax"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM dd, y",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ssy",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-ls.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-ls.js
new file mode 100644
index 00000000..c17e6a3c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-ls.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sontaha",
+ "Mmantaha",
+ "Labobedi",
+ "Laboraru",
+ "Labone",
+ "Labohlane",
+ "Moqebelo"
+ ],
+ "MONTH": [
+ "Phesekgong",
+ "Hlakola",
+ "Hlakubele",
+ "Mmese",
+ "Motsheanong",
+ "Phupjane",
+ "Phupu",
+ "Phata",
+ "Leotshe",
+ "Mphalane",
+ "Pundungwane",
+ "Tshitwe"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mma",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Hla",
+ "Moq"
+ ],
+ "SHORTMONTH": [
+ "Phe",
+ "Kol",
+ "Ube",
+ "Mme",
+ "Mot",
+ "Jan",
+ "Upu",
+ "Pha",
+ "Leo",
+ "Mph",
+ "Pun",
+ "Tsh"
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "st-ls",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-za.js
new file mode 100644
index 00000000..ed1ac9cd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st-za.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sontaha",
+ "Mmantaha",
+ "Labobedi",
+ "Laboraru",
+ "Labone",
+ "Labohlane",
+ "Moqebelo"
+ ],
+ "MONTH": [
+ "Phesekgong",
+ "Hlakola",
+ "Hlakubele",
+ "Mmese",
+ "Motsheanong",
+ "Phupjane",
+ "Phupu",
+ "Phata",
+ "Leotshe",
+ "Mphalane",
+ "Pundungwane",
+ "Tshitwe"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mma",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Hla",
+ "Moq"
+ ],
+ "SHORTMONTH": [
+ "Phe",
+ "Kol",
+ "Ube",
+ "Mme",
+ "Mot",
+ "Jan",
+ "Upu",
+ "Pha",
+ "Leo",
+ "Mph",
+ "Pun",
+ "Tsh"
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "st-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st.js
new file mode 100644
index 00000000..64d95b6b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_st.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sontaha",
+ "Mmantaha",
+ "Labobedi",
+ "Laboraru",
+ "Labone",
+ "Labohlane",
+ "Moqebelo"
+ ],
+ "MONTH": [
+ "Phesekgong",
+ "Hlakola",
+ "Hlakubele",
+ "Mmese",
+ "Motsheanong",
+ "Phupjane",
+ "Phupu",
+ "Phata",
+ "Leotshe",
+ "Mphalane",
+ "Pundungwane",
+ "Tshitwe"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mma",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Hla",
+ "Moq"
+ ],
+ "SHORTMONTH": [
+ "Phe",
+ "Kol",
+ "Ube",
+ "Mme",
+ "Mot",
+ "Jan",
+ "Upu",
+ "Pha",
+ "Leo",
+ "Mph",
+ "Pun",
+ "Tsh"
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "st",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-ax.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-ax.js
new file mode 100644
index 00000000..3c2e1f0d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-ax.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "fm",
+ "em"
+ ],
+ "DAY": [
+ "s\u00f6ndag",
+ "m\u00e5ndag",
+ "tisdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f6rdag"
+ ],
+ "ERANAMES": [
+ "f\u00f6re Kristus",
+ "efter Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "mars",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "augusti",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f6n",
+ "m\u00e5n",
+ "tis",
+ "ons",
+ "tors",
+ "fre",
+ "l\u00f6r"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "maj",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sv-ax",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-fi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-fi.js
new file mode 100644
index 00000000..2d62ce66
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-fi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "fm",
+ "em"
+ ],
+ "DAY": [
+ "s\u00f6ndag",
+ "m\u00e5ndag",
+ "tisdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f6rdag"
+ ],
+ "ERANAMES": [
+ "f\u00f6re Kristus",
+ "efter Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "mars",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "augusti",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f6n",
+ "m\u00e5n",
+ "tis",
+ "ons",
+ "tors",
+ "fre",
+ "l\u00f6r"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "maj",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd-MM-y HH:mm",
+ "shortDate": "dd-MM-y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sv-fi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-se.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-se.js
new file mode 100644
index 00000000..124285db
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv-se.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "fm",
+ "em"
+ ],
+ "DAY": [
+ "s\u00f6ndag",
+ "m\u00e5ndag",
+ "tisdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f6rdag"
+ ],
+ "ERANAMES": [
+ "f\u00f6re Kristus",
+ "efter Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "mars",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "augusti",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f6n",
+ "m\u00e5n",
+ "tis",
+ "ons",
+ "tors",
+ "fre",
+ "l\u00f6r"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "maj",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sv-se",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv.js
new file mode 100644
index 00000000..dfd1aa78
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sv.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "fm",
+ "em"
+ ],
+ "DAY": [
+ "s\u00f6ndag",
+ "m\u00e5ndag",
+ "tisdag",
+ "onsdag",
+ "torsdag",
+ "fredag",
+ "l\u00f6rdag"
+ ],
+ "ERANAMES": [
+ "f\u00f6re Kristus",
+ "efter Kristus"
+ ],
+ "ERAS": [
+ "f.Kr.",
+ "e.Kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "januari",
+ "februari",
+ "mars",
+ "april",
+ "maj",
+ "juni",
+ "juli",
+ "augusti",
+ "september",
+ "oktober",
+ "november",
+ "december"
+ ],
+ "SHORTDAY": [
+ "s\u00f6n",
+ "m\u00e5n",
+ "tis",
+ "ons",
+ "tors",
+ "fre",
+ "l\u00f6r"
+ ],
+ "SHORTMONTH": [
+ "jan.",
+ "feb.",
+ "mars",
+ "apr.",
+ "maj",
+ "juni",
+ "juli",
+ "aug.",
+ "sep.",
+ "okt.",
+ "nov.",
+ "dec."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "kr",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "sv",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-cd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-cd.js
new file mode 100644
index 00000000..b41d77c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-cd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ya asubuyi",
+ "ya muchana"
+ ],
+ "DAY": [
+ "siku ya yenga",
+ "siku ya kwanza",
+ "siku ya pili",
+ "siku ya tatu",
+ "siku ya ine",
+ "siku ya tanu",
+ "siku ya sita"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "mwezi ya kwanja",
+ "mwezi ya pili",
+ "mwezi ya tatu",
+ "mwezi ya ine",
+ "mwezi ya tanu",
+ "mwezi ya sita",
+ "mwezi ya saba",
+ "mwezi ya munane",
+ "mwezi ya tisa",
+ "mwezi ya kumi",
+ "mwezi ya kumi na moya",
+ "mwezi ya kumi ya mbili"
+ ],
+ "SHORTDAY": [
+ "yen",
+ "kwa",
+ "pil",
+ "tat",
+ "ine",
+ "tan",
+ "sit"
+ ],
+ "SHORTMONTH": [
+ "mkw",
+ "mpi",
+ "mtu",
+ "min",
+ "mtn",
+ "mst",
+ "msb",
+ "mun",
+ "mts",
+ "mku",
+ "mkm",
+ "mkb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sw-cd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ke.js
new file mode 100644
index 00000000..6230e7c9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sw-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-tz.js
new file mode 100644
index 00000000..3f1cc2d2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sw-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ug.js
new file mode 100644
index 00000000..f2d03120
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sw-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw.js
new file mode 100644
index 00000000..e6dd8fe8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_sw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristo",
+ "Baada ya Kristo"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprili",
+ "Mei",
+ "Juni",
+ "Julai",
+ "Agosti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jumapili",
+ "Jumatatu",
+ "Jumanne",
+ "Jumatano",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "sw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc-cd.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc-cd.js
new file mode 100644
index 00000000..4e51c156
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc-cd.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ya asubuyi",
+ "ya muchana"
+ ],
+ "DAY": [
+ "siku ya yenga",
+ "siku ya kwanza",
+ "siku ya pili",
+ "siku ya tatu",
+ "siku ya ine",
+ "siku ya tanu",
+ "siku ya sita"
+ ],
+ "ERANAMES": [
+ "mbele ya Yezu Kristo",
+ "kisha ya Yezu Kristo"
+ ],
+ "ERAS": [
+ "mbele ya Y",
+ "kisha ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "mwezi ya kwanja",
+ "mwezi ya pili",
+ "mwezi ya tatu",
+ "mwezi ya ine",
+ "mwezi ya tanu",
+ "mwezi ya sita",
+ "mwezi ya saba",
+ "mwezi ya munane",
+ "mwezi ya tisa",
+ "mwezi ya kumi",
+ "mwezi ya kumi na moya",
+ "mwezi ya kumi ya mbili"
+ ],
+ "SHORTDAY": [
+ "yen",
+ "kwa",
+ "pil",
+ "tat",
+ "ine",
+ "tan",
+ "sit"
+ ],
+ "SHORTMONTH": [
+ "mkw",
+ "mpi",
+ "mtu",
+ "min",
+ "mtn",
+ "mst",
+ "msb",
+ "mun",
+ "mts",
+ "mku",
+ "mkm",
+ "mkb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "swc-cd",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc.js
new file mode 100644
index 00000000..5390f3bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_swc.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ya asubuyi",
+ "ya muchana"
+ ],
+ "DAY": [
+ "siku ya yenga",
+ "siku ya kwanza",
+ "siku ya pili",
+ "siku ya tatu",
+ "siku ya ine",
+ "siku ya tanu",
+ "siku ya sita"
+ ],
+ "ERANAMES": [
+ "mbele ya Yezu Kristo",
+ "kisha ya Yezu Kristo"
+ ],
+ "ERAS": [
+ "mbele ya Y",
+ "kisha ya Y"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "mwezi ya kwanja",
+ "mwezi ya pili",
+ "mwezi ya tatu",
+ "mwezi ya ine",
+ "mwezi ya tanu",
+ "mwezi ya sita",
+ "mwezi ya saba",
+ "mwezi ya munane",
+ "mwezi ya tisa",
+ "mwezi ya kumi",
+ "mwezi ya kumi na moya",
+ "mwezi ya kumi ya mbili"
+ ],
+ "SHORTDAY": [
+ "yen",
+ "kwa",
+ "pil",
+ "tat",
+ "ine",
+ "tan",
+ "sit"
+ ],
+ "SHORTMONTH": [
+ "mkw",
+ "mpi",
+ "mtu",
+ "min",
+ "mtn",
+ "mst",
+ "msb",
+ "mun",
+ "mts",
+ "mku",
+ "mkm",
+ "mkb"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FrCD",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "swc",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-in.js
new file mode 100644
index 00000000..8ef2205a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
+ "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
+ ],
+ "DAY": [
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
+ "\u0b9a\u0ba9\u0bbf"
+ ],
+ "ERANAMES": [
+ "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
+ "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
+ ],
+ "ERAS": [
+ "\u0b95\u0bbf.\u0bae\u0bc1.",
+ "\u0b95\u0bbf.\u0baa\u0bbf."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
+ "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
+ ],
+ "SHORTDAY": [
+ "\u0b9e\u0bbe",
+ "\u0ba4\u0bbf",
+ "\u0b9a\u0bc6",
+ "\u0baa\u0bc1",
+ "\u0bb5\u0bbf",
+ "\u0bb5\u0bc6",
+ "\u0b9a"
+ ],
+ "SHORTMONTH": [
+ "\u0b9c\u0ba9.",
+ "\u0baa\u0bbf\u0baa\u0bcd.",
+ "\u0bae\u0bbe\u0bb0\u0bcd.",
+ "\u0b8f\u0baa\u0bcd.",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95.",
+ "\u0b9a\u0bc6\u0baa\u0bcd.",
+ "\u0b85\u0b95\u0bcd.",
+ "\u0ba8\u0bb5.",
+ "\u0b9f\u0bbf\u0b9a."
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ta-in",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-lk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-lk.js
new file mode 100644
index 00000000..ffb0e7ca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-lk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
+ "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
+ ],
+ "DAY": [
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
+ "\u0b9a\u0ba9\u0bbf"
+ ],
+ "ERANAMES": [
+ "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
+ "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
+ ],
+ "ERAS": [
+ "\u0b95\u0bbf.\u0bae\u0bc1.",
+ "\u0b95\u0bbf.\u0baa\u0bbf."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
+ "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
+ ],
+ "SHORTDAY": [
+ "\u0b9e\u0bbe",
+ "\u0ba4\u0bbf",
+ "\u0b9a\u0bc6",
+ "\u0baa\u0bc1",
+ "\u0bb5\u0bbf",
+ "\u0bb5\u0bc6",
+ "\u0b9a"
+ ],
+ "SHORTMONTH": [
+ "\u0b9c\u0ba9.",
+ "\u0baa\u0bbf\u0baa\u0bcd.",
+ "\u0bae\u0bbe\u0bb0\u0bcd.",
+ "\u0b8f\u0baa\u0bcd.",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95.",
+ "\u0b9a\u0bc6\u0baa\u0bcd.",
+ "\u0b85\u0b95\u0bcd.",
+ "\u0ba8\u0bb5.",
+ "\u0b9f\u0bbf\u0b9a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ta-lk",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-my.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-my.js
new file mode 100644
index 00000000..3a9287a6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-my.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
+ "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
+ ],
+ "DAY": [
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
+ "\u0b9a\u0ba9\u0bbf"
+ ],
+ "ERANAMES": [
+ "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
+ "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
+ ],
+ "ERAS": [
+ "\u0b95\u0bbf.\u0bae\u0bc1.",
+ "\u0b95\u0bbf.\u0baa\u0bbf."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
+ "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
+ ],
+ "SHORTDAY": [
+ "\u0b9e\u0bbe",
+ "\u0ba4\u0bbf",
+ "\u0b9a\u0bc6",
+ "\u0baa\u0bc1",
+ "\u0bb5\u0bbf",
+ "\u0bb5\u0bc6",
+ "\u0b9a"
+ ],
+ "SHORTMONTH": [
+ "\u0b9c\u0ba9.",
+ "\u0baa\u0bbf\u0baa\u0bcd.",
+ "\u0bae\u0bbe\u0bb0\u0bcd.",
+ "\u0b8f\u0baa\u0bcd.",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95.",
+ "\u0b9a\u0bc6\u0baa\u0bcd.",
+ "\u0b85\u0b95\u0bcd.",
+ "\u0ba8\u0bb5.",
+ "\u0b9f\u0bbf\u0b9a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "RM",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ta-my",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-sg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-sg.js
new file mode 100644
index 00000000..fc6a77d8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta-sg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
+ "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
+ ],
+ "DAY": [
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
+ "\u0b9a\u0ba9\u0bbf"
+ ],
+ "ERANAMES": [
+ "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
+ "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
+ ],
+ "ERAS": [
+ "\u0b95\u0bbf.\u0bae\u0bc1.",
+ "\u0b95\u0bbf.\u0baa\u0bbf."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
+ "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
+ ],
+ "SHORTDAY": [
+ "\u0b9e\u0bbe",
+ "\u0ba4\u0bbf",
+ "\u0b9a\u0bc6",
+ "\u0baa\u0bc1",
+ "\u0bb5\u0bbf",
+ "\u0bb5\u0bc6",
+ "\u0b9a"
+ ],
+ "SHORTMONTH": [
+ "\u0b9c\u0ba9.",
+ "\u0baa\u0bbf\u0baa\u0bcd.",
+ "\u0bae\u0bbe\u0bb0\u0bcd.",
+ "\u0b8f\u0baa\u0bcd.",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95.",
+ "\u0b9a\u0bc6\u0baa\u0bcd.",
+ "\u0b85\u0b95\u0bcd.",
+ "\u0ba8\u0bb5.",
+ "\u0b9f\u0bbf\u0b9a."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ta-sg",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta.js
new file mode 100644
index 00000000..62726246
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ta.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
+ "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
+ ],
+ "DAY": [
+ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
+ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
+ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
+ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
+ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
+ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
+ "\u0b9a\u0ba9\u0bbf"
+ ],
+ "ERANAMES": [
+ "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
+ "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
+ ],
+ "ERAS": [
+ "\u0b95\u0bbf.\u0bae\u0bc1.",
+ "\u0b95\u0bbf.\u0baa\u0bbf."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
+ "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
+ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
+ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
+ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
+ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
+ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
+ ],
+ "SHORTDAY": [
+ "\u0b9e\u0bbe",
+ "\u0ba4\u0bbf",
+ "\u0b9a\u0bc6",
+ "\u0baa\u0bc1",
+ "\u0bb5\u0bbf",
+ "\u0bb5\u0bc6",
+ "\u0b9a"
+ ],
+ "SHORTMONTH": [
+ "\u0b9c\u0ba9.",
+ "\u0baa\u0bbf\u0baa\u0bcd.",
+ "\u0bae\u0bbe\u0bb0\u0bcd.",
+ "\u0b8f\u0baa\u0bcd.",
+ "\u0bae\u0bc7",
+ "\u0b9c\u0bc2\u0ba9\u0bcd",
+ "\u0b9c\u0bc2\u0bb2\u0bc8",
+ "\u0b86\u0b95.",
+ "\u0b9a\u0bc6\u0baa\u0bcd.",
+ "\u0b85\u0b95\u0bcd.",
+ "\u0ba8\u0bb5.",
+ "\u0b9f\u0bbf\u0b9a."
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM, y",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d-M-yy h:mm a",
+ "shortDate": "d-M-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ta",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te-in.js
new file mode 100644
index 00000000..fccdcfe8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te-in.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "[AM]",
+ "[PM]"
+ ],
+ "DAY": [
+ "\u0c06\u0c26\u0c3f\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c38\u0c4b\u0c2e\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c2e\u0c02\u0c17\u0c33\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c2c\u0c41\u0c27\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c17\u0c41\u0c30\u0c41\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02"
+ ],
+ "ERANAMES": [
+ "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c02",
+ "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c36\u0c15\u0c02"
+ ],
+ "ERAS": [
+ "\u0c15\u0c4d\u0c30\u0c40\u0c2a\u0c42",
+ "\u0c15\u0c4d\u0c30\u0c40\u0c36"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0c1c\u0c28\u0c35\u0c30\u0c3f",
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f",
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f",
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d",
+ "\u0c2e\u0c47",
+ "\u0c1c\u0c42\u0c28\u0c4d",
+ "\u0c1c\u0c41\u0c32\u0c48",
+ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41",
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d",
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d",
+ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d",
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"
+ ],
+ "SHORTDAY": [
+ "\u0c06\u0c26\u0c3f",
+ "\u0c38\u0c4b\u0c2e",
+ "\u0c2e\u0c02\u0c17\u0c33",
+ "\u0c2c\u0c41\u0c27",
+ "\u0c17\u0c41\u0c30\u0c41",
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30",
+ "\u0c36\u0c28\u0c3f"
+ ],
+ "SHORTMONTH": [
+ "\u0c1c\u0c28",
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30",
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f",
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f",
+ "\u0c2e\u0c47",
+ "\u0c1c\u0c42\u0c28\u0c4d",
+ "\u0c1c\u0c41\u0c32\u0c48",
+ "\u0c06\u0c17",
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02",
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b",
+ "\u0c28\u0c35\u0c02",
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "d, MMMM y, EEEE",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd-MM-yy h:mm a",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "te-in",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te.js
new file mode 100644
index 00000000..a3c493fc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_te.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "[AM]",
+ "[PM]"
+ ],
+ "DAY": [
+ "\u0c06\u0c26\u0c3f\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c38\u0c4b\u0c2e\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c2e\u0c02\u0c17\u0c33\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c2c\u0c41\u0c27\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c17\u0c41\u0c30\u0c41\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02",
+ "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02"
+ ],
+ "ERANAMES": [
+ "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c02",
+ "\u0c15\u0c4d\u0c30\u0c40\u0c38\u0c4d\u0c24\u0c41 \u0c36\u0c15\u0c02"
+ ],
+ "ERAS": [
+ "\u0c15\u0c4d\u0c30\u0c40\u0c2a\u0c42",
+ "\u0c15\u0c4d\u0c30\u0c40\u0c36"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0c1c\u0c28\u0c35\u0c30\u0c3f",
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f",
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f",
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d",
+ "\u0c2e\u0c47",
+ "\u0c1c\u0c42\u0c28\u0c4d",
+ "\u0c1c\u0c41\u0c32\u0c48",
+ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41",
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d",
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d",
+ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d",
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"
+ ],
+ "SHORTDAY": [
+ "\u0c06\u0c26\u0c3f",
+ "\u0c38\u0c4b\u0c2e",
+ "\u0c2e\u0c02\u0c17\u0c33",
+ "\u0c2c\u0c41\u0c27",
+ "\u0c17\u0c41\u0c30\u0c41",
+ "\u0c36\u0c41\u0c15\u0c4d\u0c30",
+ "\u0c36\u0c28\u0c3f"
+ ],
+ "SHORTMONTH": [
+ "\u0c1c\u0c28",
+ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30",
+ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f",
+ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f",
+ "\u0c2e\u0c47",
+ "\u0c1c\u0c42\u0c28\u0c4d",
+ "\u0c1c\u0c41\u0c32\u0c48",
+ "\u0c06\u0c17",
+ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02",
+ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b",
+ "\u0c28\u0c35\u0c02",
+ "\u0c21\u0c3f\u0c38\u0c46\u0c02"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "d, MMMM y, EEEE",
+ "longDate": "d MMMM, y",
+ "medium": "d MMM, y h:mm:ss a",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd-MM-yy h:mm a",
+ "shortDate": "dd-MM-yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "te",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ke.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ke.js
new file mode 100644
index 00000000..04178e1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ke.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Taparachu",
+ "Ebongi"
+ ],
+ "DAY": [
+ "Nakaejuma",
+ "Nakaebarasa",
+ "Nakaare",
+ "Nakauni",
+ "Nakaung\u2019on",
+ "Nakakany",
+ "Nakasabiti"
+ ],
+ "ERANAMES": [
+ "Kabla ya Christo",
+ "Baada ya Christo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Orara",
+ "Omuk",
+ "Okwamg\u2019",
+ "Odung\u2019el",
+ "Omaruk",
+ "Omodok\u2019king\u2019ol",
+ "Ojola",
+ "Opedel",
+ "Osokosokoma",
+ "Otibar",
+ "Olabor",
+ "Opoo"
+ ],
+ "SHORTDAY": [
+ "Jum",
+ "Bar",
+ "Aar",
+ "Uni",
+ "Ung",
+ "Kan",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Rar",
+ "Muk",
+ "Kwa",
+ "Dun",
+ "Mar",
+ "Mod",
+ "Jol",
+ "Ped",
+ "Sok",
+ "Tib",
+ "Lab",
+ "Poo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Ksh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "teo-ke",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ug.js
new file mode 100644
index 00000000..8a6e1a78
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Taparachu",
+ "Ebongi"
+ ],
+ "DAY": [
+ "Nakaejuma",
+ "Nakaebarasa",
+ "Nakaare",
+ "Nakauni",
+ "Nakaung\u2019on",
+ "Nakakany",
+ "Nakasabiti"
+ ],
+ "ERANAMES": [
+ "Kabla ya Christo",
+ "Baada ya Christo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Orara",
+ "Omuk",
+ "Okwamg\u2019",
+ "Odung\u2019el",
+ "Omaruk",
+ "Omodok\u2019king\u2019ol",
+ "Ojola",
+ "Opedel",
+ "Osokosokoma",
+ "Otibar",
+ "Olabor",
+ "Opoo"
+ ],
+ "SHORTDAY": [
+ "Jum",
+ "Bar",
+ "Aar",
+ "Uni",
+ "Ung",
+ "Kan",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Rar",
+ "Muk",
+ "Kwa",
+ "Dun",
+ "Mar",
+ "Mod",
+ "Jol",
+ "Ped",
+ "Sok",
+ "Tib",
+ "Lab",
+ "Poo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "teo-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo.js
new file mode 100644
index 00000000..b3a750c6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_teo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Taparachu",
+ "Ebongi"
+ ],
+ "DAY": [
+ "Nakaejuma",
+ "Nakaebarasa",
+ "Nakaare",
+ "Nakauni",
+ "Nakaung\u2019on",
+ "Nakakany",
+ "Nakasabiti"
+ ],
+ "ERANAMES": [
+ "Kabla ya Christo",
+ "Baada ya Christo"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Orara",
+ "Omuk",
+ "Okwamg\u2019",
+ "Odung\u2019el",
+ "Omaruk",
+ "Omodok\u2019king\u2019ol",
+ "Ojola",
+ "Opedel",
+ "Osokosokoma",
+ "Otibar",
+ "Olabor",
+ "Opoo"
+ ],
+ "SHORTDAY": [
+ "Jum",
+ "Bar",
+ "Aar",
+ "Uni",
+ "Ung",
+ "Kan",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Rar",
+ "Muk",
+ "Kwa",
+ "Dun",
+ "Mar",
+ "Mod",
+ "Jol",
+ "Ped",
+ "Sok",
+ "Tib",
+ "Lab",
+ "Poo"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "teo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl-tj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl-tj.js
new file mode 100644
index 00000000..c25e8f70
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl-tj.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0435. \u0447\u043e.",
+ "\u043f\u0430. \u0447\u043e."
+ ],
+ "DAY": [
+ "\u042f\u043a\u0448\u0430\u043d\u0431\u0435",
+ "\u0414\u0443\u0448\u0430\u043d\u0431\u0435",
+ "\u0421\u0435\u0448\u0430\u043d\u0431\u0435",
+ "\u0427\u043e\u0440\u0448\u0430\u043d\u0431\u0435",
+ "\u041f\u0430\u043d\u04b7\u0448\u0430\u043d\u0431\u0435",
+ "\u04b6\u0443\u043c\u044a\u0430",
+ "\u0428\u0430\u043d\u0431\u0435"
+ ],
+ "MONTH": [
+ "\u042f\u043d\u0432\u0430\u0440",
+ "\u0424\u0435\u0432\u0440\u0430\u043b",
+ "\u041c\u0430\u0440\u0442",
+ "\u0410\u043f\u0440\u0435\u043b",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440",
+ "\u041e\u043a\u0442\u044f\u0431\u0440",
+ "\u041d\u043e\u044f\u0431\u0440",
+ "\u0414\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u042f\u0448\u0431",
+ "\u0414\u0448\u0431",
+ "\u0421\u0448\u0431",
+ "\u0427\u0448\u0431",
+ "\u041f\u0448\u0431",
+ "\u04b6\u043c\u044a",
+ "\u0428\u043d\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u042f\u043d\u0432",
+ "\u0424\u0435\u0432",
+ "\u041c\u0430\u0440",
+ "\u0410\u043f\u0440",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433",
+ "\u0421\u0435\u043d",
+ "\u041e\u043a\u0442",
+ "\u041d\u043e\u044f",
+ "\u0414\u0435\u043a"
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Som",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tg-cyrl-tj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl.js
new file mode 100644
index 00000000..7c0b60f6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg-cyrl.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0435. \u0447\u043e.",
+ "\u043f\u0430. \u0447\u043e."
+ ],
+ "DAY": [
+ "\u042f\u043a\u0448\u0430\u043d\u0431\u0435",
+ "\u0414\u0443\u0448\u0430\u043d\u0431\u0435",
+ "\u0421\u0435\u0448\u0430\u043d\u0431\u0435",
+ "\u0427\u043e\u0440\u0448\u0430\u043d\u0431\u0435",
+ "\u041f\u0430\u043d\u04b7\u0448\u0430\u043d\u0431\u0435",
+ "\u04b6\u0443\u043c\u044a\u0430",
+ "\u0428\u0430\u043d\u0431\u0435"
+ ],
+ "MONTH": [
+ "\u042f\u043d\u0432\u0430\u0440",
+ "\u0424\u0435\u0432\u0440\u0430\u043b",
+ "\u041c\u0430\u0440\u0442",
+ "\u0410\u043f\u0440\u0435\u043b",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440",
+ "\u041e\u043a\u0442\u044f\u0431\u0440",
+ "\u041d\u043e\u044f\u0431\u0440",
+ "\u0414\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u042f\u0448\u0431",
+ "\u0414\u0448\u0431",
+ "\u0421\u0448\u0431",
+ "\u0427\u0448\u0431",
+ "\u041f\u0448\u0431",
+ "\u04b6\u043c\u044a",
+ "\u0428\u043d\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u042f\u043d\u0432",
+ "\u0424\u0435\u0432",
+ "\u041c\u0430\u0440",
+ "\u0410\u043f\u0440",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433",
+ "\u0421\u0435\u043d",
+ "\u041e\u043a\u0442",
+ "\u041d\u043e\u044f",
+ "\u0414\u0435\u043a"
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tg-cyrl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg.js
new file mode 100644
index 00000000..6a15c5c6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tg.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u043f\u0435. \u0447\u043e.",
+ "\u043f\u0430. \u0447\u043e."
+ ],
+ "DAY": [
+ "\u042f\u043a\u0448\u0430\u043d\u0431\u0435",
+ "\u0414\u0443\u0448\u0430\u043d\u0431\u0435",
+ "\u0421\u0435\u0448\u0430\u043d\u0431\u0435",
+ "\u0427\u043e\u0440\u0448\u0430\u043d\u0431\u0435",
+ "\u041f\u0430\u043d\u04b7\u0448\u0430\u043d\u0431\u0435",
+ "\u04b6\u0443\u043c\u044a\u0430",
+ "\u0428\u0430\u043d\u0431\u0435"
+ ],
+ "MONTH": [
+ "\u042f\u043d\u0432\u0430\u0440",
+ "\u0424\u0435\u0432\u0440\u0430\u043b",
+ "\u041c\u0430\u0440\u0442",
+ "\u0410\u043f\u0440\u0435\u043b",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440",
+ "\u041e\u043a\u0442\u044f\u0431\u0440",
+ "\u041d\u043e\u044f\u0431\u0440",
+ "\u0414\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u042f\u0448\u0431",
+ "\u0414\u0448\u0431",
+ "\u0421\u0448\u0431",
+ "\u0427\u0448\u0431",
+ "\u041f\u0448\u0431",
+ "\u04b6\u043c\u044a",
+ "\u0428\u043d\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u042f\u043d\u0432",
+ "\u0424\u0435\u0432",
+ "\u041c\u0430\u0440",
+ "\u0410\u043f\u0440",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433",
+ "\u0421\u0435\u043d",
+ "\u041e\u043a\u0442",
+ "\u041d\u043e\u044f",
+ "\u0414\u0435\u043a"
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Som",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tg",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th-th.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th-th.js
new file mode 100644
index 00000000..93c1cce8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th-th.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07",
+ "\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"
+ ],
+ "DAY": [
+ "\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23",
+ "\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18",
+ "\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35",
+ "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"
+ ],
+ "ERANAMES": [
+ "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a",
+ "\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a"
+ ],
+ "ERAS": [
+ "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19 \u0e04.\u0e28.",
+ "\u0e04.\u0e28."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21",
+ "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c",
+ "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21",
+ "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19",
+ "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21",
+ "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19",
+ "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21",
+ "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21",
+ "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19",
+ "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21",
+ "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19",
+ "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"
+ ],
+ "SHORTDAY": [
+ "\u0e2d\u0e32.",
+ "\u0e08.",
+ "\u0e2d.",
+ "\u0e1e.",
+ "\u0e1e\u0e24.",
+ "\u0e28.",
+ "\u0e2a."
+ ],
+ "SHORTMONTH": [
+ "\u0e21.\u0e04.",
+ "\u0e01.\u0e1e.",
+ "\u0e21\u0e35.\u0e04.",
+ "\u0e40\u0e21.\u0e22.",
+ "\u0e1e.\u0e04.",
+ "\u0e21\u0e34.\u0e22.",
+ "\u0e01.\u0e04.",
+ "\u0e2a.\u0e04.",
+ "\u0e01.\u0e22.",
+ "\u0e15.\u0e04.",
+ "\u0e1e.\u0e22.",
+ "\u0e18.\u0e04."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u0e17\u0e35\u0e48 d MMMM G y",
+ "longDate": "d MMMM G y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0e3f",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "th-th",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th.js
new file mode 100644
index 00000000..d9c21b28
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_th.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07",
+ "\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"
+ ],
+ "DAY": [
+ "\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23",
+ "\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18",
+ "\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35",
+ "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c",
+ "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"
+ ],
+ "ERANAMES": [
+ "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a",
+ "\u0e04\u0e23\u0e34\u0e2a\u0e15\u0e4c\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a"
+ ],
+ "ERAS": [
+ "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19 \u0e04.\u0e28.",
+ "\u0e04.\u0e28."
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21",
+ "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c",
+ "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21",
+ "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19",
+ "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21",
+ "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19",
+ "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21",
+ "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21",
+ "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19",
+ "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21",
+ "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19",
+ "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"
+ ],
+ "SHORTDAY": [
+ "\u0e2d\u0e32.",
+ "\u0e08.",
+ "\u0e2d.",
+ "\u0e1e.",
+ "\u0e1e\u0e24.",
+ "\u0e28.",
+ "\u0e2a."
+ ],
+ "SHORTMONTH": [
+ "\u0e21.\u0e04.",
+ "\u0e01.\u0e1e.",
+ "\u0e21\u0e35.\u0e04.",
+ "\u0e40\u0e21.\u0e22.",
+ "\u0e1e.\u0e04.",
+ "\u0e21\u0e34.\u0e22.",
+ "\u0e01.\u0e04.",
+ "\u0e2a.\u0e04.",
+ "\u0e01.\u0e22.",
+ "\u0e15.\u0e04.",
+ "\u0e1e.\u0e22.",
+ "\u0e18.\u0e04."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u0e17\u0e35\u0e48 d MMMM G y",
+ "longDate": "d MMMM G y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/yy HH:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u0e3f",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "th",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-er.js
new file mode 100644
index 00000000..26948d7c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-er.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1295\u1309\u1206 \u1230\u12d3\u1270",
+ "\u12f5\u1215\u122d \u1230\u12d3\u1275"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1230\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1213\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "ERANAMES": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "ERAS": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u1325\u122a",
+ "\u1208\u12ab\u1272\u1275",
+ "\u1218\u130b\u1262\u1275",
+ "\u121a\u12eb\u12dd\u12eb",
+ "\u130d\u1295\u1266\u1275",
+ "\u1230\u1290",
+ "\u1213\u121d\u1208",
+ "\u1290\u1213\u1230",
+ "\u1218\u1235\u12a8\u1228\u121d",
+ "\u1325\u1245\u121d\u1272",
+ "\u1215\u12f3\u122d",
+ "\u1273\u1215\u1233\u1235"
+ ],
+ "SHORTDAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1230\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1213\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "SHORTMONTH": [
+ "\u1325\u122a",
+ "\u1208\u12ab\u1272",
+ "\u1218\u130b\u1262",
+ "\u121a\u12eb\u12dd",
+ "\u130d\u1295\u1266",
+ "\u1230\u1290",
+ "\u1213\u121d\u1208",
+ "\u1290\u1213\u1230",
+ "\u1218\u1235\u12a8",
+ "\u1325\u1245\u121d",
+ "\u1215\u12f3\u122d",
+ "\u1273\u1215\u1233"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u1361 dd MMMM \u1218\u12d3\u120d\u1272 y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ti-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-et.js
new file mode 100644
index 00000000..1be479a0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti-et.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1295\u1309\u1206 \u1230\u12d3\u1270",
+ "\u12f5\u1215\u122d \u1230\u12d3\u1275"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1220\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1283\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "ERANAMES": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "ERAS": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1220\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1283\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u1363 dd MMMM \u1218\u12d3\u120d\u1272 y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ti-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti.js
new file mode 100644
index 00000000..872204c4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ti.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1295\u1309\u1206 \u1230\u12d3\u1270",
+ "\u12f5\u1215\u122d \u1230\u12d3\u1275"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1220\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1283\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "ERANAMES": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "ERAS": [
+ "\u12d3/\u12d3",
+ "\u12d3/\u121d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u1230\u1295\u1260\u1275",
+ "\u1230\u1291\u12ed",
+ "\u1220\u1209\u1235",
+ "\u1228\u1261\u12d5",
+ "\u1283\u1219\u1235",
+ "\u12d3\u122d\u1262",
+ "\u1240\u12f3\u121d"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u1363 dd MMMM \u1218\u12d3\u120d\u1272 y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ti",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig-er.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig-er.js
new file mode 100644
index 00000000..0f137e05
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig-er.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1240\u12f0\u121d \u1230\u122d\u121d\u12d5\u120d",
+ "\u1213\u1246 \u1235\u122d\u121d\u12d5\u120d"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u1275 \u12d3\u1263\u12ed",
+ "\u1230\u1296",
+ "\u1273\u120b\u1238\u1296",
+ "\u12a3\u1228\u122d\u1263\u12d3",
+ "\u12a8\u121a\u123d",
+ "\u1305\u121d\u12d3\u1275",
+ "\u1230\u1295\u1260\u1275 \u1295\u12a2\u123d"
+ ],
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u1230/\u12d3",
+ "\u1230\u1296",
+ "\u1273\u120b\u1238",
+ "\u12a3\u1228\u122d",
+ "\u12a8\u121a\u123d",
+ "\u1305\u121d\u12d3",
+ "\u1230/\u1295"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "fullDate": "EEEE\u1361 dd MMMM \u12ee\u121d y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tig-er",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig.js
new file mode 100644
index 00000000..493fd396
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tig.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u1240\u12f0\u121d \u1230\u122d\u121d\u12d5\u120d",
+ "\u1213\u1246 \u1235\u122d\u121d\u12d5\u120d"
+ ],
+ "DAY": [
+ "\u1230\u1295\u1260\u1275 \u12d3\u1263\u12ed",
+ "\u1230\u1296",
+ "\u1273\u120b\u1238\u1296",
+ "\u12a3\u1228\u122d\u1263\u12d3",
+ "\u12a8\u121a\u123d",
+ "\u1305\u121d\u12d3\u1275",
+ "\u1230\u1295\u1260\u1275 \u1295\u12a2\u123d"
+ ],
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u1230/\u12d3",
+ "\u1230\u1296",
+ "\u1273\u120b\u1238",
+ "\u12a3\u1228\u122d",
+ "\u12a8\u121a\u123d",
+ "\u1305\u121d\u12d3",
+ "\u1230/\u1295"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "fullDate": "EEEE\u1361 dd MMMM \u12ee\u121d y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Nfk",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tig",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tl.js
new file mode 100644
index 00000000..59b7a10d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tl.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Linggo",
+ "Lunes",
+ "Martes",
+ "Miyerkules",
+ "Huwebes",
+ "Biyernes",
+ "Sabado"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Enero",
+ "Pebrero",
+ "Marso",
+ "Abril",
+ "Mayo",
+ "Hunyo",
+ "Hulyo",
+ "Agosto",
+ "Setyembre",
+ "Oktubre",
+ "Nobyembre",
+ "Disyembre"
+ ],
+ "SHORTDAY": [
+ "Lin",
+ "Lun",
+ "Mar",
+ "Miy",
+ "Huw",
+ "Biy",
+ "Sab"
+ ],
+ "SHORTMONTH": [
+ "Ene",
+ "Peb",
+ "Mar",
+ "Abr",
+ "May",
+ "Hun",
+ "Hul",
+ "Ago",
+ "Set",
+ "Okt",
+ "Nob",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b1",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tl",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && (i == 1 || i == 2 || i == 3) || vf.v == 0 && i % 10 != 4 && i % 10 != 6 && i % 10 != 9 || vf.v != 0 && vf.f % 10 != 4 && vf.f % 10 != 6 && vf.f % 10 != 9) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-bw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-bw.js
new file mode 100644
index 00000000..bc05b8e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-bw.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Tshipi",
+ "Mosopulogo",
+ "Labobedi",
+ "Laboraro",
+ "Labone",
+ "Labotlhano",
+ "Matlhatso"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ferikgong",
+ "Tlhakole",
+ "Mopitlo",
+ "Moranang",
+ "Motsheganang",
+ "Seetebosigo",
+ "Phukwi",
+ "Phatwe",
+ "Lwetse",
+ "Diphalane",
+ "Ngwanatsele",
+ "Sedimonthole"
+ ],
+ "SHORTDAY": [
+ "Tsh",
+ "Mos",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Tla",
+ "Mat"
+ ],
+ "SHORTMONTH": [
+ "Fer",
+ "Tlh",
+ "Mop",
+ "Mor",
+ "Mot",
+ "See",
+ "Phu",
+ "Pha",
+ "Lwe",
+ "Dip",
+ "Ngw",
+ "Sed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "P",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tn-bw",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-za.js
new file mode 100644
index 00000000..cecb7eeb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Tshipi",
+ "Mosopulogo",
+ "Labobedi",
+ "Laboraro",
+ "Labone",
+ "Labotlhano",
+ "Matlhatso"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ferikgong",
+ "Tlhakole",
+ "Mopitlo",
+ "Moranang",
+ "Motsheganang",
+ "Seetebosigo",
+ "Phukwi",
+ "Phatwe",
+ "Lwetse",
+ "Diphalane",
+ "Ngwanatsele",
+ "Sedimonthole"
+ ],
+ "SHORTDAY": [
+ "Tsh",
+ "Mos",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Tla",
+ "Mat"
+ ],
+ "SHORTMONTH": [
+ "Fer",
+ "Tlh",
+ "Mop",
+ "Mor",
+ "Mot",
+ "See",
+ "Phu",
+ "Pha",
+ "Lwe",
+ "Dip",
+ "Ngw",
+ "Sed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tn-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn.js
new file mode 100644
index 00000000..f2495560
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Tshipi",
+ "Mosopulogo",
+ "Labobedi",
+ "Laboraro",
+ "Labone",
+ "Labotlhano",
+ "Matlhatso"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Ferikgong",
+ "Tlhakole",
+ "Mopitlo",
+ "Moranang",
+ "Motsheganang",
+ "Seetebosigo",
+ "Phukwi",
+ "Phatwe",
+ "Lwetse",
+ "Diphalane",
+ "Ngwanatsele",
+ "Sedimonthole"
+ ],
+ "SHORTDAY": [
+ "Tsh",
+ "Mos",
+ "Bed",
+ "Rar",
+ "Ne",
+ "Tla",
+ "Mat"
+ ],
+ "SHORTMONTH": [
+ "Fer",
+ "Tlh",
+ "Mop",
+ "Mor",
+ "Mot",
+ "See",
+ "Phu",
+ "Pha",
+ "Lwe",
+ "Dip",
+ "Ngw",
+ "Sed"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "tn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to-to.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to-to.js
new file mode 100644
index 00000000..568ba879
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to-to.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "S\u0101pate",
+ "M\u014dnite",
+ "T\u016bsite",
+ "Pulelulu",
+ "Tu\u02bbapulelulu",
+ "Falaite",
+ "Tokonaki"
+ ],
+ "ERANAMES": [
+ "ki mu\u02bba",
+ "ta\u02bbu \u02bbo S\u012bs\u016b"
+ ],
+ "ERAS": [
+ "KM",
+ "TS"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "S\u0101nuali",
+ "F\u0113pueli",
+ "Ma\u02bbasi",
+ "\u02bbEpeleli",
+ "M\u0113",
+ "Sune",
+ "Siulai",
+ "\u02bbAokosi",
+ "Sepitema",
+ "\u02bbOkatopa",
+ "N\u014dvema",
+ "T\u012bsema"
+ ],
+ "SHORTDAY": [
+ "S\u0101p",
+ "M\u014dn",
+ "T\u016bs",
+ "Pul",
+ "Tu\u02bba",
+ "Fal",
+ "Tok"
+ ],
+ "SHORTMONTH": [
+ "S\u0101n",
+ "F\u0113p",
+ "Ma\u02bba",
+ "\u02bbEpe",
+ "M\u0113",
+ "Sun",
+ "Siu",
+ "\u02bbAok",
+ "Sep",
+ "\u02bbOka",
+ "N\u014dv",
+ "T\u012bs"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "T$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "to-to",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to.js
new file mode 100644
index 00000000..81ee5758
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_to.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "S\u0101pate",
+ "M\u014dnite",
+ "T\u016bsite",
+ "Pulelulu",
+ "Tu\u02bbapulelulu",
+ "Falaite",
+ "Tokonaki"
+ ],
+ "ERANAMES": [
+ "ki mu\u02bba",
+ "ta\u02bbu \u02bbo S\u012bs\u016b"
+ ],
+ "ERAS": [
+ "KM",
+ "TS"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "S\u0101nuali",
+ "F\u0113pueli",
+ "Ma\u02bbasi",
+ "\u02bbEpeleli",
+ "M\u0113",
+ "Sune",
+ "Siulai",
+ "\u02bbAokosi",
+ "Sepitema",
+ "\u02bbOkatopa",
+ "N\u014dvema",
+ "T\u012bsema"
+ ],
+ "SHORTDAY": [
+ "S\u0101p",
+ "M\u014dn",
+ "T\u016bs",
+ "Pul",
+ "Tu\u02bba",
+ "Fal",
+ "Tok"
+ ],
+ "SHORTMONTH": [
+ "S\u0101n",
+ "F\u0113p",
+ "Ma\u02bba",
+ "\u02bbEpe",
+ "M\u0113",
+ "Sun",
+ "Siu",
+ "\u02bbAok",
+ "Sep",
+ "\u02bbOka",
+ "N\u014dv",
+ "T\u012bs"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "T$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "to",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-cy.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-cy.js
new file mode 100644
index 00000000..ea484759
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-cy.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00d6\u00d6",
+ "\u00d6S"
+ ],
+ "DAY": [
+ "Pazar",
+ "Pazartesi",
+ "Sal\u0131",
+ "\u00c7ar\u015famba",
+ "Per\u015fembe",
+ "Cuma",
+ "Cumartesi"
+ ],
+ "ERANAMES": [
+ "Milattan \u00d6nce",
+ "Milattan Sonra"
+ ],
+ "ERAS": [
+ "M\u00d6",
+ "MS"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ocak",
+ "\u015eubat",
+ "Mart",
+ "Nisan",
+ "May\u0131s",
+ "Haziran",
+ "Temmuz",
+ "A\u011fustos",
+ "Eyl\u00fcl",
+ "Ekim",
+ "Kas\u0131m",
+ "Aral\u0131k"
+ ],
+ "SHORTDAY": [
+ "Paz",
+ "Pzt",
+ "Sal",
+ "\u00c7ar",
+ "Per",
+ "Cum",
+ "Cmt"
+ ],
+ "SHORTMONTH": [
+ "Oca",
+ "\u015eub",
+ "Mar",
+ "Nis",
+ "May",
+ "Haz",
+ "Tem",
+ "A\u011fu",
+ "Eyl",
+ "Eki",
+ "Kas",
+ "Ara"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d MM y HH:mm",
+ "shortDate": "d MM y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ac",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tr-cy",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-tr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-tr.js
new file mode 100644
index 00000000..e9575d34
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr-tr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00d6\u00d6",
+ "\u00d6S"
+ ],
+ "DAY": [
+ "Pazar",
+ "Pazartesi",
+ "Sal\u0131",
+ "\u00c7ar\u015famba",
+ "Per\u015fembe",
+ "Cuma",
+ "Cumartesi"
+ ],
+ "ERANAMES": [
+ "Milattan \u00d6nce",
+ "Milattan Sonra"
+ ],
+ "ERAS": [
+ "M\u00d6",
+ "MS"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ocak",
+ "\u015eubat",
+ "Mart",
+ "Nisan",
+ "May\u0131s",
+ "Haziran",
+ "Temmuz",
+ "A\u011fustos",
+ "Eyl\u00fcl",
+ "Ekim",
+ "Kas\u0131m",
+ "Aral\u0131k"
+ ],
+ "SHORTDAY": [
+ "Paz",
+ "Pzt",
+ "Sal",
+ "\u00c7ar",
+ "Per",
+ "Cum",
+ "Cmt"
+ ],
+ "SHORTMONTH": [
+ "Oca",
+ "\u015eub",
+ "Mar",
+ "Nis",
+ "May",
+ "Haz",
+ "Tem",
+ "A\u011fu",
+ "Eyl",
+ "Eki",
+ "Kas",
+ "Ara"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d MM y HH:mm",
+ "shortDate": "d MM y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tr-tr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr.js
new file mode 100644
index 00000000..e3521251
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tr.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00d6\u00d6",
+ "\u00d6S"
+ ],
+ "DAY": [
+ "Pazar",
+ "Pazartesi",
+ "Sal\u0131",
+ "\u00c7ar\u015famba",
+ "Per\u015fembe",
+ "Cuma",
+ "Cumartesi"
+ ],
+ "ERANAMES": [
+ "Milattan \u00d6nce",
+ "Milattan Sonra"
+ ],
+ "ERAS": [
+ "M\u00d6",
+ "MS"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Ocak",
+ "\u015eubat",
+ "Mart",
+ "Nisan",
+ "May\u0131s",
+ "Haziran",
+ "Temmuz",
+ "A\u011fustos",
+ "Eyl\u00fcl",
+ "Ekim",
+ "Kas\u0131m",
+ "Aral\u0131k"
+ ],
+ "SHORTDAY": [
+ "Paz",
+ "Pzt",
+ "Sal",
+ "\u00c7ar",
+ "Per",
+ "Cum",
+ "Cmt"
+ ],
+ "SHORTMONTH": [
+ "Oca",
+ "\u015eub",
+ "Mar",
+ "Nis",
+ "May",
+ "Haz",
+ "Tem",
+ "A\u011fu",
+ "Eyl",
+ "Eki",
+ "Kas",
+ "Ara"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "d MMMM y EEEE",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d MM y HH:mm",
+ "shortDate": "d MM y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TL",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tr",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts-za.js
new file mode 100644
index 00000000..077c4a58
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sonto",
+ "Musumbhunuku",
+ "Ravumbirhi",
+ "Ravunharhu",
+ "Ravumune",
+ "Ravuntlhanu",
+ "Mugqivela"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Sunguti",
+ "Nyenyenyani",
+ "Nyenyankulu",
+ "Dzivamisoko",
+ "Mudyaxihi",
+ "Khotavuxika",
+ "Mawuwani",
+ "Mhawuri",
+ "Ndzhati",
+ "Nhlangula",
+ "Hukuri",
+ "N\u2019wendzamhala"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mus",
+ "Bir",
+ "Har",
+ "Ne",
+ "Tlh",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Sun",
+ "Yan",
+ "Kul",
+ "Dzi",
+ "Mud",
+ "Kho",
+ "Maw",
+ "Mha",
+ "Ndz",
+ "Nhl",
+ "Huk",
+ "N\u2019w"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ts-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts.js
new file mode 100644
index 00000000..e5299089
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ts.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sonto",
+ "Musumbhunuku",
+ "Ravumbirhi",
+ "Ravunharhu",
+ "Ravumune",
+ "Ravuntlhanu",
+ "Mugqivela"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Sunguti",
+ "Nyenyenyani",
+ "Nyenyankulu",
+ "Dzivamisoko",
+ "Mudyaxihi",
+ "Khotavuxika",
+ "Mawuwani",
+ "Mhawuri",
+ "Ndzhati",
+ "Nhlangula",
+ "Hukuri",
+ "N\u2019wendzamhala"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mus",
+ "Bir",
+ "Har",
+ "Ne",
+ "Tlh",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Sun",
+ "Yan",
+ "Kul",
+ "Dzi",
+ "Mud",
+ "Kho",
+ "Maw",
+ "Mha",
+ "Ndz",
+ "Nhl",
+ "Huk",
+ "N\u2019w"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ts",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq-ne.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq-ne.js
new file mode 100644
index 00000000..6213c47e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq-ne.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Subbaahi",
+ "Zaarikay b"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamiisa",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "twq-ne",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq.js
new file mode 100644
index 00000000..b477674a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_twq.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Subbaahi",
+ "Zaarikay b"
+ ],
+ "DAY": [
+ "Alhadi",
+ "Atinni",
+ "Atalaata",
+ "Alarba",
+ "Alhamiisa",
+ "Alzuma",
+ "Asibti"
+ ],
+ "ERANAMES": [
+ "Isaa jine",
+ "Isaa zamanoo"
+ ],
+ "ERAS": [
+ "IJ",
+ "IZ"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u017danwiye",
+ "Feewiriye",
+ "Marsi",
+ "Awiril",
+ "Me",
+ "\u017duwe\u014b",
+ "\u017duyye",
+ "Ut",
+ "Sektanbur",
+ "Oktoobur",
+ "Noowanbur",
+ "Deesanbur"
+ ],
+ "SHORTDAY": [
+ "Alh",
+ "Ati",
+ "Ata",
+ "Ala",
+ "Alm",
+ "Alz",
+ "Asi"
+ ],
+ "SHORTMONTH": [
+ "\u017dan",
+ "Fee",
+ "Mar",
+ "Awi",
+ "Me",
+ "\u017duw",
+ "\u017duy",
+ "Ut",
+ "Sek",
+ "Okt",
+ "Noo",
+ "Dee"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "twq",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn-ma.js
new file mode 100644
index 00000000..bbfe0a7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn-ma.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Zdat azal",
+ "\u1e0ceffir aza"
+ ],
+ "DAY": [
+ "Asamas",
+ "Aynas",
+ "Asinas",
+ "Akras",
+ "Akwas",
+ "Asimwas",
+ "Asi\u1e0dyas"
+ ],
+ "ERANAMES": [
+ "Zdat \u0190isa (TA\u0194)",
+ "\u1e0ceffir \u0190isa (TA\u0194)"
+ ],
+ "ERAS": [
+ "Z\u0190",
+ "\u1e0c\u0190"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "Yennayer",
+ "Yebrayer",
+ "Mars",
+ "Ibrir",
+ "Mayyu",
+ "Yunyu",
+ "Yulyuz",
+ "\u0194uct",
+ "Cutanbir",
+ "K\u1e6duber",
+ "Nwanbir",
+ "Dujanbir"
+ ],
+ "SHORTDAY": [
+ "Asa",
+ "Ayn",
+ "Asn",
+ "Akr",
+ "Akw",
+ "Asm",
+ "As\u1e0d"
+ ],
+ "SHORTMONTH": [
+ "Yen",
+ "Yeb",
+ "Mar",
+ "Ibr",
+ "May",
+ "Yun",
+ "Yul",
+ "\u0194uc",
+ "Cut",
+ "K\u1e6du",
+ "Nwa",
+ "Duj"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tzm-latn-ma",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn.js
new file mode 100644
index 00000000..b17a71dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Zdat azal",
+ "\u1e0ceffir aza"
+ ],
+ "DAY": [
+ "Asamas",
+ "Aynas",
+ "Asinas",
+ "Akras",
+ "Akwas",
+ "Asimwas",
+ "Asi\u1e0dyas"
+ ],
+ "ERANAMES": [
+ "Zdat \u0190isa (TA\u0194)",
+ "\u1e0ceffir \u0190isa (TA\u0194)"
+ ],
+ "ERAS": [
+ "Z\u0190",
+ "\u1e0c\u0190"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "Yennayer",
+ "Yebrayer",
+ "Mars",
+ "Ibrir",
+ "Mayyu",
+ "Yunyu",
+ "Yulyuz",
+ "\u0194uct",
+ "Cutanbir",
+ "K\u1e6duber",
+ "Nwanbir",
+ "Dujanbir"
+ ],
+ "SHORTDAY": [
+ "Asa",
+ "Ayn",
+ "Asn",
+ "Akr",
+ "Akw",
+ "Asm",
+ "As\u1e0d"
+ ],
+ "SHORTMONTH": [
+ "Yen",
+ "Yeb",
+ "Mar",
+ "Ibr",
+ "May",
+ "Yun",
+ "Yul",
+ "\u0194uc",
+ "Cut",
+ "K\u1e6du",
+ "Nwa",
+ "Duj"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tzm-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm.js
new file mode 100644
index 00000000..a2f34ff5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_tzm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Zdat azal",
+ "\u1e0ceffir aza"
+ ],
+ "DAY": [
+ "Asamas",
+ "Aynas",
+ "Asinas",
+ "Akras",
+ "Akwas",
+ "Asimwas",
+ "Asi\u1e0dyas"
+ ],
+ "ERANAMES": [
+ "Zdat \u0190isa (TA\u0194)",
+ "\u1e0ceffir \u0190isa (TA\u0194)"
+ ],
+ "ERAS": [
+ "Z\u0190",
+ "\u1e0c\u0190"
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "Yennayer",
+ "Yebrayer",
+ "Mars",
+ "Ibrir",
+ "Mayyu",
+ "Yunyu",
+ "Yulyuz",
+ "\u0194uct",
+ "Cutanbir",
+ "K\u1e6duber",
+ "Nwanbir",
+ "Dujanbir"
+ ],
+ "SHORTDAY": [
+ "Asa",
+ "Ayn",
+ "Asn",
+ "Akr",
+ "Akw",
+ "Asm",
+ "As\u1e0d"
+ ],
+ "SHORTMONTH": [
+ "Yen",
+ "Yeb",
+ "Mar",
+ "Ibr",
+ "May",
+ "Yun",
+ "Yul",
+ "\u0194uc",
+ "Cut",
+ "K\u1e6du",
+ "Nwa",
+ "Duj"
+ ],
+ "WEEKENDRANGE": [
+ 4,
+ 5
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "tzm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab-cn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab-cn.js
new file mode 100644
index 00000000..67092f1e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab-cn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646"
+ ],
+ "DAY": [
+ "\u064a\u06d5\u0643\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062f\u06c8\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0633\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0686\u0627\u0631\u0634\u06d5\u0646\u0628\u06d5",
+ "\u067e\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062c\u06c8\u0645\u06d5",
+ "\u0634\u06d5\u0646\u0628\u06d5"
+ ],
+ "ERANAMES": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "ERAS": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0628\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "SHORTDAY": [
+ "\u064a\u06d5",
+ "\u062f\u06c8",
+ "\u0633\u06d5",
+ "\u0686\u0627",
+ "\u067e\u06d5",
+ "\u0686\u06c8",
+ "\u0634\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0646\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c MMMM d\u060c y",
+ "longDate": "MMMM d\u060c y",
+ "medium": "MMM d\u060c y h:mm:ss a",
+ "mediumDate": "MMM d\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ug-arab-cn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab.js
new file mode 100644
index 00000000..bd9ae4ab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug-arab.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646"
+ ],
+ "DAY": [
+ "\u064a\u06d5\u0643\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062f\u06c8\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0633\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0686\u0627\u0631\u0634\u06d5\u0646\u0628\u06d5",
+ "\u067e\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062c\u06c8\u0645\u06d5",
+ "\u0634\u06d5\u0646\u0628\u06d5"
+ ],
+ "ERANAMES": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "ERAS": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0628\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "SHORTDAY": [
+ "\u064a\u06d5",
+ "\u062f\u06c8",
+ "\u0633\u06d5",
+ "\u0686\u0627",
+ "\u067e\u06d5",
+ "\u0686\u06c8",
+ "\u0634\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0646\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c MMMM d\u060c y",
+ "longDate": "MMMM d\u060c y",
+ "medium": "MMM d\u060c y h:mm:ss a",
+ "mediumDate": "MMM d\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ug-arab",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug.js
new file mode 100644
index 00000000..2ed49abc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0686\u06c8\u0634\u062a\u0649\u0646 \u0643\u06d0\u064a\u0649\u0646"
+ ],
+ "DAY": [
+ "\u064a\u06d5\u0643\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062f\u06c8\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0633\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u0686\u0627\u0631\u0634\u06d5\u0646\u0628\u06d5",
+ "\u067e\u06d5\u064a\u0634\u06d5\u0646\u0628\u06d5",
+ "\u062c\u06c8\u0645\u06d5",
+ "\u0634\u06d5\u0646\u0628\u06d5"
+ ],
+ "ERANAMES": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "ERAS": [
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5\u062f\u0649\u0646 \u0628\u06c7\u0631\u06c7\u0646",
+ "\u0645\u0649\u0644\u0627\u062f\u0649\u064a\u06d5"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0628\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "SHORTDAY": [
+ "\u064a\u06d5",
+ "\u062f\u06c8",
+ "\u0633\u06d5",
+ "\u0686\u0627",
+ "\u067e\u06d5",
+ "\u0686\u06c8",
+ "\u0634\u06d5"
+ ],
+ "SHORTMONTH": [
+ "\u064a\u0627\u0646\u06cb\u0627\u0631",
+ "\u0641\u06d0\u06cb\u0631\u0627\u0644",
+ "\u0645\u0627\u0631\u062a",
+ "\u0626\u0627\u067e\u0631\u06d0\u0644",
+ "\u0645\u0627\u064a",
+ "\u0626\u0649\u064a\u06c7\u0646",
+ "\u0626\u0649\u064a\u06c7\u0644",
+ "\u0626\u0627\u06cb\u063a\u06c7\u0633\u062a",
+ "\u0633\u06d0\u0646\u062a\u06d5\u0628\u0649\u0631",
+ "\u0626\u06c6\u0643\u062a\u06d5\u0628\u0649\u0631",
+ "\u0646\u0648\u064a\u0627\u0628\u0649\u0631",
+ "\u062f\u06d0\u0643\u0627\u0628\u0649\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c MMMM d\u060c y",
+ "longDate": "MMMM d\u060c y",
+ "medium": "MMM d\u060c y h:mm:ss a",
+ "mediumDate": "MMM d\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk-ua.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk-ua.js
new file mode 100644
index 00000000..1fca063b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk-ua.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0434\u043f",
+ "\u043f\u043f"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0456\u043b\u044f",
+ "\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a",
+ "\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a",
+ "\u0441\u0435\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440",
+ "\u043f\u02bc\u044f\u0442\u043d\u0438\u0446\u044f",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438",
+ "\u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438"
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d.\u0435.",
+ "\u043d.\u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0441\u0456\u0447\u043d\u044f",
+ "\u043b\u044e\u0442\u043e\u0433\u043e",
+ "\u0431\u0435\u0440\u0435\u0437\u043d\u044f",
+ "\u043a\u0432\u0456\u0442\u043d\u044f",
+ "\u0442\u0440\u0430\u0432\u043d\u044f",
+ "\u0447\u0435\u0440\u0432\u043d\u044f",
+ "\u043b\u0438\u043f\u043d\u044f",
+ "\u0441\u0435\u0440\u043f\u043d\u044f",
+ "\u0432\u0435\u0440\u0435\u0441\u043d\u044f",
+ "\u0436\u043e\u0432\u0442\u043d\u044f",
+ "\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430",
+ "\u0433\u0440\u0443\u0434\u043d\u044f"
+ ],
+ "SHORTDAY": [
+ "\u041d\u0434",
+ "\u041f\u043d",
+ "\u0412\u0442",
+ "\u0421\u0440",
+ "\u0427\u0442",
+ "\u041f\u0442",
+ "\u0421\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0441\u0456\u0447.",
+ "\u043b\u044e\u0442.",
+ "\u0431\u0435\u0440.",
+ "\u043a\u0432\u0456\u0442.",
+ "\u0442\u0440\u0430\u0432.",
+ "\u0447\u0435\u0440\u0432.",
+ "\u043b\u0438\u043f.",
+ "\u0441\u0435\u0440\u043f.",
+ "\u0432\u0435\u0440.",
+ "\u0436\u043e\u0432\u0442.",
+ "\u043b\u0438\u0441\u0442.",
+ "\u0433\u0440\u0443\u0434."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0440'.",
+ "longDate": "d MMMM y '\u0440'.",
+ "medium": "d MMM y '\u0440'. HH:mm:ss",
+ "mediumDate": "d MMM y '\u0440'.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b4",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "uk-ua",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk.js
new file mode 100644
index 00000000..9519ad86
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0434\u043f",
+ "\u043f\u043f"
+ ],
+ "DAY": [
+ "\u043d\u0435\u0434\u0456\u043b\u044f",
+ "\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a",
+ "\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a",
+ "\u0441\u0435\u0440\u0435\u0434\u0430",
+ "\u0447\u0435\u0442\u0432\u0435\u0440",
+ "\u043f\u02bc\u044f\u0442\u043d\u0438\u0446\u044f",
+ "\u0441\u0443\u0431\u043e\u0442\u0430"
+ ],
+ "ERANAMES": [
+ "\u0434\u043e \u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438",
+ "\u043d\u0430\u0448\u043e\u0457 \u0435\u0440\u0438"
+ ],
+ "ERAS": [
+ "\u0434\u043e \u043d.\u0435.",
+ "\u043d.\u0435."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u0441\u0456\u0447\u043d\u044f",
+ "\u043b\u044e\u0442\u043e\u0433\u043e",
+ "\u0431\u0435\u0440\u0435\u0437\u043d\u044f",
+ "\u043a\u0432\u0456\u0442\u043d\u044f",
+ "\u0442\u0440\u0430\u0432\u043d\u044f",
+ "\u0447\u0435\u0440\u0432\u043d\u044f",
+ "\u043b\u0438\u043f\u043d\u044f",
+ "\u0441\u0435\u0440\u043f\u043d\u044f",
+ "\u0432\u0435\u0440\u0435\u0441\u043d\u044f",
+ "\u0436\u043e\u0432\u0442\u043d\u044f",
+ "\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430",
+ "\u0433\u0440\u0443\u0434\u043d\u044f"
+ ],
+ "SHORTDAY": [
+ "\u041d\u0434",
+ "\u041f\u043d",
+ "\u0412\u0442",
+ "\u0421\u0440",
+ "\u0427\u0442",
+ "\u041f\u0442",
+ "\u0421\u0431"
+ ],
+ "SHORTMONTH": [
+ "\u0441\u0456\u0447.",
+ "\u043b\u044e\u0442.",
+ "\u0431\u0435\u0440.",
+ "\u043a\u0432\u0456\u0442.",
+ "\u0442\u0440\u0430\u0432.",
+ "\u0447\u0435\u0440\u0432.",
+ "\u043b\u0438\u043f.",
+ "\u0441\u0435\u0440\u043f.",
+ "\u0432\u0435\u0440.",
+ "\u0436\u043e\u0432\u0442.",
+ "\u043b\u0438\u0441\u0442.",
+ "\u0433\u0440\u0443\u0434."
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y '\u0440'.",
+ "longDate": "d MMMM y '\u0440'.",
+ "medium": "d MMM y '\u0440'. HH:mm:ss",
+ "mediumDate": "d MMM y '\u0440'.",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd.MM.yy HH:mm",
+ "shortDate": "dd.MM.yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b4",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "uk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-in.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-in.js
new file mode 100644
index 00000000..c81b2df1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-in.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644 \u062f\u0648\u067e\u06c1\u0631",
+ "\u0628\u0639\u062f \u062f\u0648\u067e\u06c1\u0631"
+ ],
+ "DAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d",
+ "\u0639\u06cc\u0633\u0648\u06cc"
+ ],
+ "ERAS": [
+ "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d",
+ "\u0639\u06cc\u0633\u0648\u06cc"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 6,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "d MMM\u060c y h:mm:ss a",
+ "mediumDate": "d MMM\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20b9",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ur-in",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-pk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-pk.js
new file mode 100644
index 00000000..f64e8f60
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur-pk.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644 \u062f\u0648\u067e\u06c1\u0631",
+ "\u0628\u0639\u062f \u062f\u0648\u067e\u06c1\u0631"
+ ],
+ "DAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d",
+ "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646"
+ ],
+ "ERAS": [
+ "\u0642 \u0645",
+ "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "d MMM\u060c y h:mm:ss a",
+ "mediumDate": "d MMM\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ur-pk",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur.js
new file mode 100644
index 00000000..79bf686c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ur.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u0642\u0628\u0644 \u062f\u0648\u067e\u06c1\u0631",
+ "\u0628\u0639\u062f \u062f\u0648\u067e\u06c1\u0631"
+ ],
+ "DAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "ERANAMES": [
+ "\u0642\u0628\u0644 \u0645\u0633\u06cc\u062d",
+ "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646"
+ ],
+ "ERAS": [
+ "\u0642 \u0645",
+ "\u0639\u06cc\u0633\u0648\u06cc \u0633\u0646"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u0627\u062a\u0648\u0627\u0631",
+ "\u0633\u0648\u0645\u0648\u0627\u0631",
+ "\u0645\u0646\u06af\u0644",
+ "\u0628\u062f\u06be",
+ "\u062c\u0645\u0639\u0631\u0627\u062a",
+ "\u062c\u0645\u0639\u06c1",
+ "\u06c1\u0641\u062a\u06c1"
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u0626\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u0626\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE\u060c d MMMM\u060c y",
+ "longDate": "d MMMM\u060c y",
+ "medium": "d MMM\u060c y h:mm:ss a",
+ "mediumDate": "d MMM\u060c y",
+ "mediumTime": "h:mm:ss a",
+ "short": "d/M/yy h:mm a",
+ "shortDate": "d/M/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Rs",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 2,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ur",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab-af.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab-af.js
new file mode 100644
index 00000000..118132ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab-af.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0628\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc.",
+ "\u062f.",
+ "\u0633.",
+ "\u0686.",
+ "\u067e.",
+ "\u062c.",
+ "\u0634."
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648",
+ "\u0641\u0628\u0631",
+ "\u0645\u0627\u0631",
+ "\u0627\u067e\u0631",
+ "\u0645\u0640\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644",
+ "\u0627\u06af\u0633",
+ "\u0633\u067e\u062a",
+ "\u0627\u06a9\u062a",
+ "\u0646\u0648\u0645",
+ "\u062f\u0633\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 3,
+ 4
+ ],
+ "fullDate": "y \u0646\u0686\u06cc \u06cc\u06cc\u0644 d \u0646\u0686\u06cc MMMM EEEE \u06a9\u0648\u0646\u06cc",
+ "longDate": "d \u0646\u0686\u06cc MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Af.",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "uz-arab-af",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab.js
new file mode 100644
index 00000000..3f1a20da
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-arab.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u06cc\u06a9\u0634\u0646\u0628\u0647",
+ "\u062f\u0648\u0634\u0646\u0628\u0647",
+ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647",
+ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647",
+ "\u067e\u0646\u062c\u0634\u0646\u0628\u0647",
+ "\u062c\u0645\u0639\u0647",
+ "\u0634\u0646\u0628\u0647"
+ ],
+ "ERANAMES": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "ERAS": [
+ "\u0642.\u0645.",
+ "\u0645."
+ ],
+ "FIRSTDAYOFWEEK": 5,
+ "MONTH": [
+ "\u062c\u0646\u0648\u0631\u06cc",
+ "\u0641\u0628\u0631\u0648\u0631\u06cc",
+ "\u0645\u0627\u0631\u0686",
+ "\u0627\u067e\u0631\u06cc\u0644",
+ "\u0645\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644\u0627\u06cc",
+ "\u0627\u06af\u0633\u062a",
+ "\u0633\u067e\u062a\u0645\u0628\u0631",
+ "\u0627\u06a9\u062a\u0648\u0628\u0631",
+ "\u0646\u0648\u0645\u0628\u0631",
+ "\u062f\u0633\u0645\u0628\u0631"
+ ],
+ "SHORTDAY": [
+ "\u06cc.",
+ "\u062f.",
+ "\u0633.",
+ "\u0686.",
+ "\u067e.",
+ "\u062c.",
+ "\u0634."
+ ],
+ "SHORTMONTH": [
+ "\u062c\u0646\u0648",
+ "\u0641\u0628\u0631",
+ "\u0645\u0627\u0631",
+ "\u0627\u067e\u0631",
+ "\u0645\u0640\u06cc",
+ "\u062c\u0648\u0646",
+ "\u062c\u0648\u0644",
+ "\u0627\u06af\u0633",
+ "\u0633\u067e\u062a",
+ "\u0627\u06a9\u062a",
+ "\u0646\u0648\u0645",
+ "\u062f\u0633\u0645"
+ ],
+ "WEEKENDRANGE": [
+ 3,
+ 4
+ ],
+ "fullDate": "y \u0646\u0686\u06cc \u06cc\u06cc\u0644 d \u0646\u0686\u06cc MMMM EEEE \u06a9\u0648\u0646\u06cc",
+ "longDate": "d \u0646\u0686\u06cc MMMM y",
+ "medium": "d MMM y H:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "H:mm:ss",
+ "short": "y/M/d H:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "H:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Af.",
+ "DECIMAL_SEP": "\u066b",
+ "GROUP_SEP": "\u066c",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "uz-arab",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl-uz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl-uz.js
new file mode 100644
index 00000000..03e74ba6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl-uz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u044f\u043a\u0448\u0430\u043d\u0431\u0430",
+ "\u0434\u0443\u0448\u0430\u043d\u0431\u0430",
+ "\u0441\u0435\u0448\u0430\u043d\u0431\u0430",
+ "\u0447\u043e\u0440\u0448\u0430\u043d\u0431\u0430",
+ "\u043f\u0430\u0439\u0448\u0430\u043d\u0431\u0430",
+ "\u0436\u0443\u043c\u0430",
+ "\u0448\u0430\u043d\u0431\u0430"
+ ],
+ "ERANAMES": [
+ "\u041c.\u0410.",
+ "\u042d"
+ ],
+ "ERAS": [
+ "\u041c.\u0410.",
+ "\u042d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u042f\u043d\u0432\u0430\u0440",
+ "\u0424\u0435\u0432\u0440\u0430\u043b",
+ "\u041c\u0430\u0440\u0442",
+ "\u0410\u043f\u0440\u0435\u043b",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440",
+ "\u041e\u043a\u0442\u044f\u0431\u0440",
+ "\u041d\u043e\u044f\u0431\u0440",
+ "\u0414\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u042f\u043a\u0448",
+ "\u0414\u0443\u0448",
+ "\u0421\u0435\u0448",
+ "\u0427\u043e\u0440",
+ "\u041f\u0430\u0439",
+ "\u0416\u0443\u043c",
+ "\u0428\u0430\u043d"
+ ],
+ "SHORTMONTH": [
+ "\u042f\u043d\u0432",
+ "\u0424\u0435\u0432",
+ "\u041c\u0430\u0440",
+ "\u0410\u043f\u0440",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433",
+ "\u0421\u0435\u043d",
+ "\u041e\u043a\u0442",
+ "\u041d\u043e\u044f",
+ "\u0414\u0435\u043a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "so\u02bcm",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "uz-cyrl-uz",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl.js
new file mode 100644
index 00000000..d284657c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-cyrl.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\u044f\u043a\u0448\u0430\u043d\u0431\u0430",
+ "\u0434\u0443\u0448\u0430\u043d\u0431\u0430",
+ "\u0441\u0435\u0448\u0430\u043d\u0431\u0430",
+ "\u0447\u043e\u0440\u0448\u0430\u043d\u0431\u0430",
+ "\u043f\u0430\u0439\u0448\u0430\u043d\u0431\u0430",
+ "\u0436\u0443\u043c\u0430",
+ "\u0448\u0430\u043d\u0431\u0430"
+ ],
+ "ERANAMES": [
+ "\u041c.\u0410.",
+ "\u042d"
+ ],
+ "ERAS": [
+ "\u041c.\u0410.",
+ "\u042d"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u042f\u043d\u0432\u0430\u0440",
+ "\u0424\u0435\u0432\u0440\u0430\u043b",
+ "\u041c\u0430\u0440\u0442",
+ "\u0410\u043f\u0440\u0435\u043b",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
+ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440",
+ "\u041e\u043a\u0442\u044f\u0431\u0440",
+ "\u041d\u043e\u044f\u0431\u0440",
+ "\u0414\u0435\u043a\u0430\u0431\u0440"
+ ],
+ "SHORTDAY": [
+ "\u042f\u043a\u0448",
+ "\u0414\u0443\u0448",
+ "\u0421\u0435\u0448",
+ "\u0427\u043e\u0440",
+ "\u041f\u0430\u0439",
+ "\u0416\u0443\u043c",
+ "\u0428\u0430\u043d"
+ ],
+ "SHORTMONTH": [
+ "\u042f\u043d\u0432",
+ "\u0424\u0435\u0432",
+ "\u041c\u0430\u0440",
+ "\u0410\u043f\u0440",
+ "\u041c\u0430\u0439",
+ "\u0418\u044e\u043d",
+ "\u0418\u044e\u043b",
+ "\u0410\u0432\u0433",
+ "\u0421\u0435\u043d",
+ "\u041e\u043a\u0442",
+ "\u041d\u043e\u044f",
+ "\u0414\u0435\u043a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "so\u02bcm",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "uz-cyrl",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn-uz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn-uz.js
new file mode 100644
index 00000000..d7b41bd0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn-uz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "TO",
+ "TK"
+ ],
+ "DAY": [
+ "yakshanba",
+ "dushanba",
+ "seshanba",
+ "chorshanba",
+ "payshanba",
+ "juma",
+ "shanba"
+ ],
+ "ERANAMES": [
+ "M.A.",
+ "E"
+ ],
+ "ERAS": [
+ "M.A.",
+ "E"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Yanvar",
+ "Fevral",
+ "Mart",
+ "Aprel",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avgust",
+ "Sentabr",
+ "Oktabr",
+ "Noyabr",
+ "Dekabr"
+ ],
+ "SHORTDAY": [
+ "Yaksh",
+ "Dush",
+ "Sesh",
+ "Chor",
+ "Pay",
+ "Jum",
+ "Shan"
+ ],
+ "SHORTMONTH": [
+ "Yanv",
+ "Fev",
+ "Mar",
+ "Apr",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avg",
+ "Sen",
+ "Okt",
+ "Noya",
+ "Dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "so\u02bcm",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "uz-latn-uz",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn.js
new file mode 100644
index 00000000..a0262271
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz-latn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "TO",
+ "TK"
+ ],
+ "DAY": [
+ "yakshanba",
+ "dushanba",
+ "seshanba",
+ "chorshanba",
+ "payshanba",
+ "juma",
+ "shanba"
+ ],
+ "ERANAMES": [
+ "M.A.",
+ "E"
+ ],
+ "ERAS": [
+ "M.A.",
+ "E"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Yanvar",
+ "Fevral",
+ "Mart",
+ "Aprel",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avgust",
+ "Sentabr",
+ "Oktabr",
+ "Noyabr",
+ "Dekabr"
+ ],
+ "SHORTDAY": [
+ "Yaksh",
+ "Dush",
+ "Sesh",
+ "Chor",
+ "Pay",
+ "Jum",
+ "Shan"
+ ],
+ "SHORTMONTH": [
+ "Yanv",
+ "Fev",
+ "Mar",
+ "Apr",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avg",
+ "Sen",
+ "Okt",
+ "Noya",
+ "Dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "so\u02bcm",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "uz-latn",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz.js
new file mode 100644
index 00000000..1bf9a645
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_uz.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "TO",
+ "TK"
+ ],
+ "DAY": [
+ "yakshanba",
+ "dushanba",
+ "seshanba",
+ "chorshanba",
+ "payshanba",
+ "juma",
+ "shanba"
+ ],
+ "ERANAMES": [
+ "M.A.",
+ "E"
+ ],
+ "ERAS": [
+ "M.A.",
+ "E"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Yanvar",
+ "Fevral",
+ "Mart",
+ "Aprel",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avgust",
+ "Sentabr",
+ "Oktabr",
+ "Noyabr",
+ "Dekabr"
+ ],
+ "SHORTDAY": [
+ "Yaksh",
+ "Dush",
+ "Sesh",
+ "Chor",
+ "Pay",
+ "Jum",
+ "Shan"
+ ],
+ "SHORTMONTH": [
+ "Yanv",
+ "Fev",
+ "Mar",
+ "Apr",
+ "May",
+ "Iyun",
+ "Iyul",
+ "Avg",
+ "Sen",
+ "Okt",
+ "Noya",
+ "Dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, y MMMM dd",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "yy/MM/dd HH:mm",
+ "shortDate": "yy/MM/dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "so\u02bcm",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "uz",
+ "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn-lr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn-lr.js
new file mode 100644
index 00000000..a3d63c35
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn-lr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "lahadi",
+ "t\u025b\u025bn\u025b\u025b",
+ "talata",
+ "alaba",
+ "aimisa",
+ "aijima",
+ "si\u0253iti"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "luukao kem\u00e3",
+ "\u0253anda\u0253u",
+ "v\u0254\u0254",
+ "fulu",
+ "goo",
+ "6",
+ "7",
+ "k\u0254nde",
+ "saah",
+ "galo",
+ "kenpkato \u0253olol\u0254",
+ "luukao l\u0254ma"
+ ],
+ "SHORTDAY": [
+ "lahadi",
+ "t\u025b\u025bn\u025b\u025b",
+ "talata",
+ "alaba",
+ "aimisa",
+ "aijima",
+ "si\u0253iti"
+ ],
+ "SHORTMONTH": [
+ "luukao kem\u00e3",
+ "\u0253anda\u0253u",
+ "v\u0254\u0254",
+ "fulu",
+ "goo",
+ "6",
+ "7",
+ "k\u0254nde",
+ "saah",
+ "galo",
+ "kenpkato \u0253olol\u0254",
+ "luukao l\u0254ma"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vai-latn-lr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn.js
new file mode 100644
index 00000000..3afe6629
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-latn.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "lahadi",
+ "t\u025b\u025bn\u025b\u025b",
+ "talata",
+ "alaba",
+ "aimisa",
+ "aijima",
+ "si\u0253iti"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "luukao kem\u00e3",
+ "\u0253anda\u0253u",
+ "v\u0254\u0254",
+ "fulu",
+ "goo",
+ "6",
+ "7",
+ "k\u0254nde",
+ "saah",
+ "galo",
+ "kenpkato \u0253olol\u0254",
+ "luukao l\u0254ma"
+ ],
+ "SHORTDAY": [
+ "lahadi",
+ "t\u025b\u025bn\u025b\u025b",
+ "talata",
+ "alaba",
+ "aimisa",
+ "aijima",
+ "si\u0253iti"
+ ],
+ "SHORTMONTH": [
+ "luukao kem\u00e3",
+ "\u0253anda\u0253u",
+ "v\u0254\u0254",
+ "fulu",
+ "goo",
+ "6",
+ "7",
+ "k\u0254nde",
+ "saah",
+ "galo",
+ "kenpkato \u0253olol\u0254",
+ "luukao l\u0254ma"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vai-latn",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii-lr.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii-lr.js
new file mode 100644
index 00000000..66666949
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii-lr.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "SHORTDAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "SHORTMONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vai-vaii-lr",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii.js
new file mode 100644
index 00000000..fc172f82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai-vaii.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "SHORTDAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "SHORTMONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vai-vaii",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai.js
new file mode 100644
index 00000000..bdf3393a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vai.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "SHORTDAY": [
+ "\ua55e\ua54c\ua535",
+ "\ua5f3\ua5e1\ua609",
+ "\ua55a\ua55e\ua55a",
+ "\ua549\ua55e\ua552",
+ "\ua549\ua524\ua546\ua562",
+ "\ua549\ua524\ua540\ua56e",
+ "\ua53b\ua52c\ua533"
+ ],
+ "SHORTMONTH": [
+ "\ua5a8\ua56a\ua583 \ua51e\ua56e",
+ "\ua552\ua561\ua59d\ua595",
+ "\ua57e\ua5ba",
+ "\ua5a2\ua595",
+ "\ua591\ua571",
+ "6",
+ "7",
+ "\ua5db\ua515",
+ "\ua562\ua54c",
+ "\ua56d\ua583",
+ "\ua51e\ua60b\ua554\ua57f \ua578\ua583\ua5cf",
+ "\ua5a8\ua56a\ua571 \ua5cf\ua56e"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vai",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve-za.js
new file mode 100644
index 00000000..eb526307
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve-za.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Swondaha",
+ "Musumbuluwo",
+ "\u1e3cavhuvhili",
+ "\u1e3cavhuraru",
+ "\u1e3cavhu\u1e4ba",
+ "\u1e3cavhu\u1e71anu",
+ "Mugivhela"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Phando",
+ "Luhuhi",
+ "\u1e70hafamuhwe",
+ "Lambamai",
+ "Shundunthule",
+ "Fulwi",
+ "Fulwana",
+ "\u1e70hangule",
+ "Khubvumedzi",
+ "Tshimedzi",
+ "\u1e3cara",
+ "Nyendavhusiku"
+ ],
+ "SHORTDAY": [
+ "Swo",
+ "Mus",
+ "Vhi",
+ "Rar",
+ "\u1e4aa",
+ "\u1e70an",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Pha",
+ "Luh",
+ "\u1e70hf",
+ "Lam",
+ "Shu",
+ "Lwi",
+ "Lwa",
+ "\u1e70ha",
+ "Khu",
+ "Tsh",
+ "\u1e3car",
+ "Nye"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ve-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve.js
new file mode 100644
index 00000000..0acd86f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_ve.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Swondaha",
+ "Musumbuluwo",
+ "\u1e3cavhuvhili",
+ "\u1e3cavhuraru",
+ "\u1e3cavhu\u1e4ba",
+ "\u1e3cavhu\u1e71anu",
+ "Mugivhela"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Phando",
+ "Luhuhi",
+ "\u1e70hafamuhwe",
+ "Lambamai",
+ "Shundunthule",
+ "Fulwi",
+ "Fulwana",
+ "\u1e70hangule",
+ "Khubvumedzi",
+ "Tshimedzi",
+ "\u1e3cara",
+ "Nyendavhusiku"
+ ],
+ "SHORTDAY": [
+ "Swo",
+ "Mus",
+ "Vhi",
+ "Rar",
+ "\u1e4aa",
+ "\u1e70an",
+ "Mug"
+ ],
+ "SHORTMONTH": [
+ "Pha",
+ "Luh",
+ "\u1e70hf",
+ "Lam",
+ "Shu",
+ "Lwi",
+ "Lwa",
+ "\u1e70ha",
+ "Khu",
+ "Tsh",
+ "\u1e3car",
+ "Nye"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "ve",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi-vn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi-vn.js
new file mode 100644
index 00000000..112e96ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi-vn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "SA",
+ "CH"
+ ],
+ "DAY": [
+ "Ch\u1ee7 Nh\u1eadt",
+ "Th\u1ee9 Hai",
+ "Th\u1ee9 Ba",
+ "Th\u1ee9 T\u01b0",
+ "Th\u1ee9 N\u0103m",
+ "Th\u1ee9 S\u00e1u",
+ "Th\u1ee9 B\u1ea3y"
+ ],
+ "ERANAMES": [
+ "tr. CN",
+ "sau CN"
+ ],
+ "ERAS": [
+ "tr. CN",
+ "sau CN"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "th\u00e1ng 1",
+ "th\u00e1ng 2",
+ "th\u00e1ng 3",
+ "th\u00e1ng 4",
+ "th\u00e1ng 5",
+ "th\u00e1ng 6",
+ "th\u00e1ng 7",
+ "th\u00e1ng 8",
+ "th\u00e1ng 9",
+ "th\u00e1ng 10",
+ "th\u00e1ng 11",
+ "th\u00e1ng 12"
+ ],
+ "SHORTDAY": [
+ "CN",
+ "Th 2",
+ "Th 3",
+ "Th 4",
+ "Th 5",
+ "Th 6",
+ "Th 7"
+ ],
+ "SHORTMONTH": [
+ "thg 1",
+ "thg 2",
+ "thg 3",
+ "thg 4",
+ "thg 5",
+ "thg 6",
+ "thg 7",
+ "thg 8",
+ "thg 9",
+ "thg 10",
+ "thg 11",
+ "thg 12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'ng\u00e0y' dd MMMM 'n\u0103m' y",
+ "longDate": "'Ng\u00e0y' dd 'th\u00e1ng' MM 'n\u0103m' y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ab",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "vi-vn",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi.js
new file mode 100644
index 00000000..be70bd8e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vi.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "SA",
+ "CH"
+ ],
+ "DAY": [
+ "Ch\u1ee7 Nh\u1eadt",
+ "Th\u1ee9 Hai",
+ "Th\u1ee9 Ba",
+ "Th\u1ee9 T\u01b0",
+ "Th\u1ee9 N\u0103m",
+ "Th\u1ee9 S\u00e1u",
+ "Th\u1ee9 B\u1ea3y"
+ ],
+ "ERANAMES": [
+ "tr. CN",
+ "sau CN"
+ ],
+ "ERAS": [
+ "tr. CN",
+ "sau CN"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "th\u00e1ng 1",
+ "th\u00e1ng 2",
+ "th\u00e1ng 3",
+ "th\u00e1ng 4",
+ "th\u00e1ng 5",
+ "th\u00e1ng 6",
+ "th\u00e1ng 7",
+ "th\u00e1ng 8",
+ "th\u00e1ng 9",
+ "th\u00e1ng 10",
+ "th\u00e1ng 11",
+ "th\u00e1ng 12"
+ ],
+ "SHORTDAY": [
+ "CN",
+ "Th 2",
+ "Th 3",
+ "Th 4",
+ "Th 5",
+ "Th 6",
+ "Th 7"
+ ],
+ "SHORTMONTH": [
+ "thg 1",
+ "thg 2",
+ "thg 3",
+ "thg 4",
+ "thg 5",
+ "thg 6",
+ "thg 7",
+ "thg 8",
+ "thg 9",
+ "thg 10",
+ "thg 11",
+ "thg 12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, 'ng\u00e0y' dd MMMM 'n\u0103m' y",
+ "longDate": "'Ng\u00e0y' dd 'th\u00e1ng' MM 'n\u0103m' y",
+ "medium": "dd-MM-y HH:mm:ss",
+ "mediumDate": "dd-MM-y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/y HH:mm",
+ "shortDate": "dd/MM/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20ab",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": ".",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "vi",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo-001.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo-001.js
new file mode 100644
index 00000000..a17a26da
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo-001.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "posz.",
+ "b\u00fcz."
+ ],
+ "DAY": [
+ "sudel",
+ "mudel",
+ "tudel",
+ "vedel",
+ "d\u00f6del",
+ "fridel",
+ "z\u00e4del"
+ ],
+ "ERANAMES": [
+ "b. t. kr.",
+ "p. t. kr."
+ ],
+ "ERAS": [
+ "b. t. kr.",
+ "p. t. kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janul",
+ "febul",
+ "m\u00e4zil",
+ "prilul",
+ "mayul",
+ "yunul",
+ "yulul",
+ "gustul",
+ "setul",
+ "tobul",
+ "novul",
+ "dekul"
+ ],
+ "SHORTDAY": [
+ "su.",
+ "mu.",
+ "tu.",
+ "ve.",
+ "d\u00f6.",
+ "fr.",
+ "z\u00e4."
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "m\u00e4z",
+ "prl",
+ "may",
+ "yun",
+ "yul",
+ "gst",
+ "set",
+ "ton",
+ "nov",
+ "dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMMa 'd'. d'id'",
+ "longDate": "y MMMM d",
+ "medium": "y MMM. d HH:mm:ss",
+ "mediumDate": "y MMM. d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vo-001",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo.js
new file mode 100644
index 00000000..f8507993
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "posz.",
+ "b\u00fcz."
+ ],
+ "DAY": [
+ "sudel",
+ "mudel",
+ "tudel",
+ "vedel",
+ "d\u00f6del",
+ "fridel",
+ "z\u00e4del"
+ ],
+ "ERANAMES": [
+ "b. t. kr.",
+ "p. t. kr."
+ ],
+ "ERAS": [
+ "b. t. kr.",
+ "p. t. kr."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "janul",
+ "febul",
+ "m\u00e4zil",
+ "prilul",
+ "mayul",
+ "yunul",
+ "yulul",
+ "gustul",
+ "setul",
+ "tobul",
+ "novul",
+ "dekul"
+ ],
+ "SHORTDAY": [
+ "su.",
+ "mu.",
+ "tu.",
+ "ve.",
+ "d\u00f6.",
+ "fr.",
+ "z\u00e4."
+ ],
+ "SHORTMONTH": [
+ "jan",
+ "feb",
+ "m\u00e4z",
+ "prl",
+ "may",
+ "yun",
+ "yul",
+ "gst",
+ "set",
+ "ton",
+ "nov",
+ "dek"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y MMMMa 'd'. d'id'",
+ "longDate": "y MMMM d",
+ "medium": "y MMM. d HH:mm:ss",
+ "mediumDate": "y MMM. d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4\u00a0-",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun-tz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun-tz.js
new file mode 100644
index 00000000..52b0670e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun-tz.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vun-tz",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun.js
new file mode 100644
index 00000000..4efacdf0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_vun.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "utuko",
+ "kyiukonyi"
+ ],
+ "DAY": [
+ "Jumapilyi",
+ "Jumatatuu",
+ "Jumanne",
+ "Jumatanu",
+ "Alhamisi",
+ "Ijumaa",
+ "Jumamosi"
+ ],
+ "ERANAMES": [
+ "Kabla ya Kristu",
+ "Baada ya Kristu"
+ ],
+ "ERAS": [
+ "KK",
+ "BK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Januari",
+ "Februari",
+ "Machi",
+ "Aprilyi",
+ "Mei",
+ "Junyi",
+ "Julyai",
+ "Agusti",
+ "Septemba",
+ "Oktoba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Jpi",
+ "Jtt",
+ "Jnn",
+ "Jtn",
+ "Alh",
+ "Iju",
+ "Jmo"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mac",
+ "Apr",
+ "Mei",
+ "Jun",
+ "Jul",
+ "Ago",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "TSh",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "vun",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae-ch.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae-ch.js
new file mode 100644
index 00000000..fba5d6ff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae-ch.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunntag",
+ "M\u00e4ntag",
+ "Zi\u0161tag",
+ "Mittwu\u010d",
+ "Fr\u00f3ntag",
+ "Fritag",
+ "Sam\u0161tag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr"
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jenner",
+ "Hornig",
+ "M\u00e4rze",
+ "Abrille",
+ "Meije",
+ "Br\u00e1\u010det",
+ "Heiwet",
+ "\u00d6ig\u0161te",
+ "Herb\u0161tm\u00e1net",
+ "W\u00edm\u00e1net",
+ "Winterm\u00e1net",
+ "Chri\u0161tm\u00e1net"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "M\u00e4n",
+ "Zi\u0161",
+ "Mit",
+ "Fr\u00f3",
+ "Fri",
+ "Sam"
+ ],
+ "SHORTMONTH": [
+ "Jen",
+ "Hor",
+ "M\u00e4r",
+ "Abr",
+ "Mei",
+ "Br\u00e1",
+ "Hei",
+ "\u00d6ig",
+ "Her",
+ "W\u00edm",
+ "Win",
+ "Chr"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "wae-ch",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae.js
new file mode 100644
index 00000000..0e16d916
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wae.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Sunntag",
+ "M\u00e4ntag",
+ "Zi\u0161tag",
+ "Mittwu\u010d",
+ "Fr\u00f3ntag",
+ "Fritag",
+ "Sam\u0161tag"
+ ],
+ "ERANAMES": [
+ "v. Chr.",
+ "n. Chr"
+ ],
+ "ERAS": [
+ "v. Chr.",
+ "n. Chr"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Jenner",
+ "Hornig",
+ "M\u00e4rze",
+ "Abrille",
+ "Meije",
+ "Br\u00e1\u010det",
+ "Heiwet",
+ "\u00d6ig\u0161te",
+ "Herb\u0161tm\u00e1net",
+ "W\u00edm\u00e1net",
+ "Winterm\u00e1net",
+ "Chri\u0161tm\u00e1net"
+ ],
+ "SHORTDAY": [
+ "Sun",
+ "M\u00e4n",
+ "Zi\u0161",
+ "Mit",
+ "Fr\u00f3",
+ "Fri",
+ "Sam"
+ ],
+ "SHORTMONTH": [
+ "Jen",
+ "Hor",
+ "M\u00e4r",
+ "Abr",
+ "Mei",
+ "Br\u00e1",
+ "Hei",
+ "\u00d6ig",
+ "Her",
+ "W\u00edm",
+ "Win",
+ "Chr"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d. MMMM y",
+ "longDate": "d. MMMM y",
+ "medium": "d. MMM y HH:mm:ss",
+ "mediumDate": "d. MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CHF",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "wae",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal-et.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal-et.js
new file mode 100644
index 00000000..16a842ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal-et.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u121b\u1208\u12f6",
+ "\u1243\u121b"
+ ],
+ "DAY": [
+ "\u12c8\u130b",
+ "\u1233\u12ed\u1296",
+ "\u121b\u1246\u1233\u129b",
+ "\u12a0\u1229\u12cb",
+ "\u1203\u1219\u1233",
+ "\u12a0\u122d\u1263",
+ "\u1244\u122b"
+ ],
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u12c8\u130b",
+ "\u1233\u12ed\u1296",
+ "\u121b\u1246\u1233\u129b",
+ "\u12a0\u1229\u12cb",
+ "\u1203\u1219\u1233",
+ "\u12a0\u122d\u1263",
+ "\u1244\u122b"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "fullDate": "EEEE\u1365 dd MMMM \u130b\u120b\u1233 y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "wal-et",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal.js
new file mode 100644
index 00000000..795c02d2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_wal.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u121b\u1208\u12f6",
+ "\u1243\u121b"
+ ],
+ "DAY": [
+ "\u12c8\u130b",
+ "\u1233\u12ed\u1296",
+ "\u121b\u1246\u1233\u129b",
+ "\u12a0\u1229\u12cb",
+ "\u1203\u1219\u1233",
+ "\u12a0\u122d\u1263",
+ "\u1244\u122b"
+ ],
+ "MONTH": [
+ "\u1303\u1295\u12e9\u12c8\u122a",
+ "\u134c\u1265\u1229\u12c8\u122a",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228\u120d",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235\u1275",
+ "\u1234\u1355\u1274\u121d\u1260\u122d",
+ "\u12a6\u12ad\u1270\u12cd\u1260\u122d",
+ "\u1296\u126c\u121d\u1260\u122d",
+ "\u12f2\u1234\u121d\u1260\u122d"
+ ],
+ "SHORTDAY": [
+ "\u12c8\u130b",
+ "\u1233\u12ed\u1296",
+ "\u121b\u1246\u1233\u129b",
+ "\u12a0\u1229\u12cb",
+ "\u1203\u1219\u1233",
+ "\u12a0\u122d\u1263",
+ "\u1244\u122b"
+ ],
+ "SHORTMONTH": [
+ "\u1303\u1295\u12e9",
+ "\u134c\u1265\u1229",
+ "\u121b\u122d\u127d",
+ "\u12a4\u1355\u1228",
+ "\u121c\u12ed",
+ "\u1301\u1295",
+ "\u1301\u120b\u12ed",
+ "\u12a6\u1308\u1235",
+ "\u1234\u1355\u1274",
+ "\u12a6\u12ad\u1270",
+ "\u1296\u126c\u121d",
+ "\u12f2\u1234\u121d"
+ ],
+ "fullDate": "EEEE\u1365 dd MMMM \u130b\u120b\u1233 y G",
+ "longDate": "dd MMMM y",
+ "medium": "dd-MMM-y h:mm:ss a",
+ "mediumDate": "dd-MMM-y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/yy h:mm a",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "Birr",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": "\u2019",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "wal",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh-za.js
new file mode 100644
index 00000000..5eeb809a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh-za.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Cawe",
+ "Mvulo",
+ "Lwesibini",
+ "Lwesithathu",
+ "Lwesine",
+ "Lwesihlanu",
+ "Mgqibelo"
+ ],
+ "MONTH": [
+ "Janyuwari",
+ "Februwari",
+ "Matshi",
+ "Epreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Agasti",
+ "Septemba",
+ "Okthoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Caw",
+ "Mvu",
+ "Bin",
+ "Tha",
+ "Sin",
+ "Hla",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Epr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Aga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "xh-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh.js
new file mode 100644
index 00000000..756a9f77
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xh.js
@@ -0,0 +1,115 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "AM",
+ "PM"
+ ],
+ "DAY": [
+ "Cawe",
+ "Mvulo",
+ "Lwesibini",
+ "Lwesithathu",
+ "Lwesine",
+ "Lwesihlanu",
+ "Mgqibelo"
+ ],
+ "MONTH": [
+ "Janyuwari",
+ "Februwari",
+ "Matshi",
+ "Epreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Agasti",
+ "Septemba",
+ "Okthoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Caw",
+ "Mvu",
+ "Bin",
+ "Tha",
+ "Sin",
+ "Hla",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mat",
+ "Epr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Aga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "fullDate": "y MMMM d, EEEE",
+ "longDate": "y MMMM d",
+ "medium": "y MMM d HH:mm:ss",
+ "mediumDate": "y MMM d",
+ "mediumTime": "HH:mm:ss",
+ "short": "y-MM-dd HH:mm",
+ "shortDate": "y-MM-dd",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "\u00a4-",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "xh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog-ug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog-ug.js
new file mode 100644
index 00000000..0288518e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog-ug.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Munkyo",
+ "Eigulo"
+ ],
+ "DAY": [
+ "Sabiiti",
+ "Balaza",
+ "Owokubili",
+ "Owokusatu",
+ "Olokuna",
+ "Olokutaanu",
+ "Olomukaaga"
+ ],
+ "ERANAMES": [
+ "Kulisto nga azilawo",
+ "Kulisto nga affile"
+ ],
+ "ERAS": [
+ "AZ",
+ "AF"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janwaliyo",
+ "Febwaliyo",
+ "Marisi",
+ "Apuli",
+ "Maayi",
+ "Juuni",
+ "Julaayi",
+ "Agusito",
+ "Sebuttemba",
+ "Okitobba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Sabi",
+ "Bala",
+ "Kubi",
+ "Kusa",
+ "Kuna",
+ "Kuta",
+ "Muka"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apu",
+ "Maa",
+ "Juu",
+ "Jul",
+ "Agu",
+ "Seb",
+ "Oki",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "xog-ug",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog.js
new file mode 100644
index 00000000..1a42ccf0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_xog.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Munkyo",
+ "Eigulo"
+ ],
+ "DAY": [
+ "Sabiiti",
+ "Balaza",
+ "Owokubili",
+ "Owokusatu",
+ "Olokuna",
+ "Olokutaanu",
+ "Olomukaaga"
+ ],
+ "ERANAMES": [
+ "Kulisto nga azilawo",
+ "Kulisto nga affile"
+ ],
+ "ERAS": [
+ "AZ",
+ "AF"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Janwaliyo",
+ "Febwaliyo",
+ "Marisi",
+ "Apuli",
+ "Maayi",
+ "Juuni",
+ "Julaayi",
+ "Agusito",
+ "Sebuttemba",
+ "Okitobba",
+ "Novemba",
+ "Desemba"
+ ],
+ "SHORTDAY": [
+ "Sabi",
+ "Bala",
+ "Kubi",
+ "Kusa",
+ "Kuna",
+ "Kuta",
+ "Muka"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apu",
+ "Maa",
+ "Juu",
+ "Jul",
+ "Agu",
+ "Seb",
+ "Oki",
+ "Nov",
+ "Des"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "UGX",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "xog",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav-cm.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav-cm.js
new file mode 100644
index 00000000..142164fc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav-cm.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ki\u025bm\u025b\u0301\u025bm",
+ "kis\u025b\u0301nd\u025b"
+ ],
+ "DAY": [
+ "s\u0254\u0301ndi\u025b",
+ "m\u00f3ndie",
+ "mu\u00e1ny\u00e1\u014bm\u00f3ndie",
+ "met\u00fakp\u00ed\u00e1p\u025b",
+ "k\u00fap\u00e9limet\u00fakpiap\u025b",
+ "fel\u00e9te",
+ "s\u00e9sel\u00e9"
+ ],
+ "ERANAMES": [
+ "katikup\u00eden Y\u00e9suse",
+ "\u00e9k\u00e9l\u00e9mk\u00fanup\u00ed\u00e9n n"
+ ],
+ "ERAS": [
+ "k.Y.",
+ "+J.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pik\u00edt\u00edk\u00edtie, o\u00f3l\u00ed \u00fa kut\u00faan",
+ "si\u025by\u025b\u0301, o\u00f3li \u00fa k\u00e1nd\u00ed\u025b",
+ "\u0254ns\u00famb\u0254l, o\u00f3li \u00fa k\u00e1t\u00e1t\u00fa\u025b",
+ "mesi\u014b, o\u00f3li \u00fa k\u00e9nie",
+ "ensil, o\u00f3li \u00fa k\u00e1t\u00e1nu\u025b",
+ "\u0254s\u0254n",
+ "efute",
+ "pisuy\u00fa",
+ "im\u025b\u014b i pu\u0254s",
+ "im\u025b\u014b i put\u00fak,o\u00f3li \u00fa k\u00e1t\u00ed\u025b",
+ "makandik\u025b",
+ "pil\u0254nd\u0254\u0301"
+ ],
+ "SHORTDAY": [
+ "sd",
+ "md",
+ "mw",
+ "et",
+ "kl",
+ "fl",
+ "ss"
+ ],
+ "SHORTMONTH": [
+ "o.1",
+ "o.2",
+ "o.3",
+ "o.4",
+ "o.5",
+ "o.6",
+ "o.7",
+ "o.8",
+ "o.9",
+ "o.10",
+ "o.11",
+ "o.12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "yav-cm",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav.js
new file mode 100644
index 00000000..01781a0d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yav.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "ki\u025bm\u025b\u0301\u025bm",
+ "kis\u025b\u0301nd\u025b"
+ ],
+ "DAY": [
+ "s\u0254\u0301ndi\u025b",
+ "m\u00f3ndie",
+ "mu\u00e1ny\u00e1\u014bm\u00f3ndie",
+ "met\u00fakp\u00ed\u00e1p\u025b",
+ "k\u00fap\u00e9limet\u00fakpiap\u025b",
+ "fel\u00e9te",
+ "s\u00e9sel\u00e9"
+ ],
+ "ERANAMES": [
+ "katikup\u00eden Y\u00e9suse",
+ "\u00e9k\u00e9l\u00e9mk\u00fanup\u00ed\u00e9n n"
+ ],
+ "ERAS": [
+ "k.Y.",
+ "+J.C."
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "pik\u00edt\u00edk\u00edtie, o\u00f3l\u00ed \u00fa kut\u00faan",
+ "si\u025by\u025b\u0301, o\u00f3li \u00fa k\u00e1nd\u00ed\u025b",
+ "\u0254ns\u00famb\u0254l, o\u00f3li \u00fa k\u00e1t\u00e1t\u00fa\u025b",
+ "mesi\u014b, o\u00f3li \u00fa k\u00e9nie",
+ "ensil, o\u00f3li \u00fa k\u00e1t\u00e1nu\u025b",
+ "\u0254s\u0254n",
+ "efute",
+ "pisuy\u00fa",
+ "im\u025b\u014b i pu\u0254s",
+ "im\u025b\u014b i put\u00fak,o\u00f3li \u00fa k\u00e1t\u00ed\u025b",
+ "makandik\u025b",
+ "pil\u0254nd\u0254\u0301"
+ ],
+ "SHORTDAY": [
+ "sd",
+ "md",
+ "mw",
+ "et",
+ "kl",
+ "fl",
+ "ss"
+ ],
+ "SHORTMONTH": [
+ "o.1",
+ "o.2",
+ "o.3",
+ "o.4",
+ "o.5",
+ "o.6",
+ "o.7",
+ "o.8",
+ "o.9",
+ "o.10",
+ "o.11",
+ "o.12"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y HH:mm:ss",
+ "mediumDate": "d MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "FCFA",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a0\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a0\u00a4"
+ }
+ ]
+ },
+ "id": "yav",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi-001.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi-001.js
new file mode 100644
index 00000000..0ba2042d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi-001.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u05e4\u05d0\u05e8\u05de\u05d9\u05d8\u05d0\u05d2",
+ "\u05e0\u05d0\u05db\u05de\u05d9\u05d8\u05d0\u05d2"
+ ],
+ "DAY": [
+ "\u05d6\u05d5\u05e0\u05d8\u05d9\u05e7",
+ "\u05de\u05d0\u05b8\u05e0\u05d8\u05d9\u05e7",
+ "\u05d3\u05d9\u05e0\u05e1\u05d8\u05d9\u05e7",
+ "\u05de\u05d9\u05d8\u05d5\u05d5\u05d0\u05da",
+ "\u05d3\u05d0\u05e0\u05e2\u05e8\u05e9\u05d8\u05d9\u05e7",
+ "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8",
+ "\u05e4\u05bf\u05e2\u05d1\u05e8\u05d5\u05d0\u05b7\u05e8",
+ "\u05de\u05e2\u05e8\u05e5",
+ "\u05d0\u05b7\u05e4\u05bc\u05e8\u05d9\u05dc",
+ "\u05de\u05d9\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d9\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e2\u05e4\u05bc\u05d8\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d0\u05e7\u05d8\u05d0\u05d1\u05e2\u05e8",
+ "\u05e0\u05d0\u05d5\u05d5\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d3\u05e2\u05e6\u05e2\u05de\u05d1\u05e2\u05e8"
+ ],
+ "SHORTDAY": [
+ "\u05d6\u05d5\u05e0\u05d8\u05d9\u05e7",
+ "\u05de\u05d0\u05b8\u05e0\u05d8\u05d9\u05e7",
+ "\u05d3\u05d9\u05e0\u05e1\u05d8\u05d9\u05e7",
+ "\u05de\u05d9\u05d8\u05d5\u05d5\u05d0\u05da",
+ "\u05d3\u05d0\u05e0\u05e2\u05e8\u05e9\u05d8\u05d9\u05e7",
+ "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "SHORTMONTH": [
+ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8",
+ "\u05e4\u05bf\u05e2\u05d1\u05e8\u05d5\u05d0\u05b7\u05e8",
+ "\u05de\u05e2\u05e8\u05e5",
+ "\u05d0\u05b7\u05e4\u05bc\u05e8\u05d9\u05dc",
+ "\u05de\u05d9\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d9\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e2\u05e4\u05bc\u05d8\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d0\u05e7\u05d8\u05d0\u05d1\u05e2\u05e8",
+ "\u05e0\u05d0\u05d5\u05d5\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d3\u05e2\u05e6\u05e2\u05de\u05d1\u05e2\u05e8"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d\u05d8\u05df MMMM y",
+ "longDate": "d\u05d8\u05df MMMM y",
+ "medium": "d\u05d8\u05df MMM y HH:mm:ss",
+ "mediumDate": "d\u05d8\u05df MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "yi-001",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi.js
new file mode 100644
index 00000000..57fb4a9d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yi.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u05e4\u05d0\u05e8\u05de\u05d9\u05d8\u05d0\u05d2",
+ "\u05e0\u05d0\u05db\u05de\u05d9\u05d8\u05d0\u05d2"
+ ],
+ "DAY": [
+ "\u05d6\u05d5\u05e0\u05d8\u05d9\u05e7",
+ "\u05de\u05d0\u05b8\u05e0\u05d8\u05d9\u05e7",
+ "\u05d3\u05d9\u05e0\u05e1\u05d8\u05d9\u05e7",
+ "\u05de\u05d9\u05d8\u05d5\u05d5\u05d0\u05da",
+ "\u05d3\u05d0\u05e0\u05e2\u05e8\u05e9\u05d8\u05d9\u05e7",
+ "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "ERANAMES": [
+ "BCE",
+ "CE"
+ ],
+ "ERAS": [
+ "BCE",
+ "CE"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8",
+ "\u05e4\u05bf\u05e2\u05d1\u05e8\u05d5\u05d0\u05b7\u05e8",
+ "\u05de\u05e2\u05e8\u05e5",
+ "\u05d0\u05b7\u05e4\u05bc\u05e8\u05d9\u05dc",
+ "\u05de\u05d9\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d9\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e2\u05e4\u05bc\u05d8\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d0\u05e7\u05d8\u05d0\u05d1\u05e2\u05e8",
+ "\u05e0\u05d0\u05d5\u05d5\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d3\u05e2\u05e6\u05e2\u05de\u05d1\u05e2\u05e8"
+ ],
+ "SHORTDAY": [
+ "\u05d6\u05d5\u05e0\u05d8\u05d9\u05e7",
+ "\u05de\u05d0\u05b8\u05e0\u05d8\u05d9\u05e7",
+ "\u05d3\u05d9\u05e0\u05e1\u05d8\u05d9\u05e7",
+ "\u05de\u05d9\u05d8\u05d5\u05d5\u05d0\u05da",
+ "\u05d3\u05d0\u05e0\u05e2\u05e8\u05e9\u05d8\u05d9\u05e7",
+ "\u05e4\u05bf\u05e8\u05f2\u05b7\u05d8\u05d9\u05e7",
+ "\u05e9\u05d1\u05ea"
+ ],
+ "SHORTMONTH": [
+ "\u05d9\u05d0\u05b7\u05e0\u05d5\u05d0\u05b7\u05e8",
+ "\u05e4\u05bf\u05e2\u05d1\u05e8\u05d5\u05d0\u05b7\u05e8",
+ "\u05de\u05e2\u05e8\u05e5",
+ "\u05d0\u05b7\u05e4\u05bc\u05e8\u05d9\u05dc",
+ "\u05de\u05d9\u05d9",
+ "\u05d9\u05d5\u05e0\u05d9",
+ "\u05d9\u05d5\u05dc\u05d9",
+ "\u05d0\u05d5\u05d9\u05d2\u05d5\u05e1\u05d8",
+ "\u05e1\u05e2\u05e4\u05bc\u05d8\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d0\u05e7\u05d8\u05d0\u05d1\u05e2\u05e8",
+ "\u05e0\u05d0\u05d5\u05d5\u05e2\u05de\u05d1\u05e2\u05e8",
+ "\u05d3\u05e2\u05e6\u05e2\u05de\u05d1\u05e2\u05e8"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d\u05d8\u05df MMMM y",
+ "longDate": "d\u05d8\u05df MMMM y",
+ "medium": "d\u05d8\u05df MMM y HH:mm:ss",
+ "mediumDate": "d\u05d8\u05df MMM y",
+ "mediumTime": "HH:mm:ss",
+ "short": "dd/MM/yy HH:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "yi",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-bj.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-bj.js
new file mode 100644
index 00000000..afc112c3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-bj.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00c0\u00e1r\u0254\u0300",
+ "\u0186\u0300s\u00e1n"
+ ],
+ "DAY": [
+ "\u0186j\u0254\u0301 \u00c0\u00eck\u00fa",
+ "\u0186j\u0254\u0301 Aj\u00e9",
+ "\u0186j\u0254\u0301 \u00ccs\u025b\u0301gun",
+ "\u0186j\u0254\u0301r\u00fa",
+ "\u0186j\u0254\u0301b\u0254",
+ "\u0186j\u0254\u0301 \u0190t\u00ec",
+ "\u0186j\u0254\u0301 \u00c0b\u00e1m\u025b\u0301ta"
+ ],
+ "ERANAMES": [
+ "Saju Kristi",
+ "Lehin Kristi"
+ ],
+ "ERAS": [
+ "SK",
+ "LK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "Osh\u00f9 Sh\u025b\u0301r\u025b\u0301",
+ "Osh\u00f9 \u00c8r\u00e8l\u00e8",
+ "Osh\u00f9 \u0190r\u025b\u0300n\u00e0",
+ "Osh\u00f9 \u00ccgb\u00e9",
+ "Osh\u00f9 \u0190\u0300bibi",
+ "Osh\u00f9 \u00d2k\u00fadu",
+ "Osh\u00f9 Ag\u025bm\u0254",
+ "Osh\u00f9 \u00d2g\u00fan",
+ "Osh\u00f9 Owewe",
+ "Osh\u00f9 \u0186\u0300w\u00e0r\u00e0",
+ "Osh\u00f9 B\u00e9l\u00fa",
+ "Osh\u00f9 \u0186\u0300p\u025b\u0300"
+ ],
+ "SHORTDAY": [
+ "\u00c0\u00eck\u00fa",
+ "Aj\u00e9",
+ "\u00ccs\u025b\u0301gun",
+ "\u0186j\u0254\u0301r\u00fa",
+ "\u0186j\u0254\u0301b\u0254",
+ "\u0190t\u00ec",
+ "\u00c0b\u00e1m\u025b\u0301ta"
+ ],
+ "SHORTMONTH": [
+ "Sh\u025b\u0301r\u025b\u0301",
+ "\u00c8r\u00e8l\u00e8",
+ "\u0190r\u025b\u0300n\u00e0",
+ "\u00ccgb\u00e9",
+ "\u0190\u0300bibi",
+ "\u00d2k\u00fadu",
+ "Ag\u025bm\u0254",
+ "\u00d2g\u00fan",
+ "Owewe",
+ "\u0186\u0300w\u00e0r\u00e0",
+ "B\u00e9l\u00fa",
+ "\u0186\u0300p\u025b\u0300"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "CFA",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "yo-bj",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-ng.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-ng.js
new file mode 100644
index 00000000..37b44503
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo-ng.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00c0\u00e1r\u1ecd\u0300",
+ "\u1ecc\u0300s\u00e1n"
+ ],
+ "DAY": [
+ "\u1eccj\u1ecd\u0301 \u00c0\u00eck\u00fa",
+ "\u1eccj\u1ecd\u0301 Aj\u00e9",
+ "\u1eccj\u1ecd\u0301 \u00ccs\u1eb9\u0301gun",
+ "\u1eccj\u1ecd\u0301r\u00fa",
+ "\u1eccj\u1ecd\u0301b\u1ecd",
+ "\u1eccj\u1ecd\u0301 \u1eb8t\u00ec",
+ "\u1eccj\u1ecd\u0301 \u00c0b\u00e1m\u1eb9\u0301ta"
+ ],
+ "ERANAMES": [
+ "Saju Kristi",
+ "Lehin Kristi"
+ ],
+ "ERAS": [
+ "SK",
+ "LK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "O\u1e63\u00f9 \u1e62\u1eb9\u0301r\u1eb9\u0301",
+ "O\u1e63\u00f9 \u00c8r\u00e8l\u00e8",
+ "O\u1e63\u00f9 \u1eb8r\u1eb9\u0300n\u00e0",
+ "O\u1e63\u00f9 \u00ccgb\u00e9",
+ "O\u1e63\u00f9 \u1eb8\u0300bibi",
+ "O\u1e63\u00f9 \u00d2k\u00fadu",
+ "O\u1e63\u00f9 Ag\u1eb9m\u1ecd",
+ "O\u1e63\u00f9 \u00d2g\u00fan",
+ "O\u1e63\u00f9 Owewe",
+ "O\u1e63\u00f9 \u1ecc\u0300w\u00e0r\u00e0",
+ "O\u1e63\u00f9 B\u00e9l\u00fa",
+ "O\u1e63\u00f9 \u1ecc\u0300p\u1eb9\u0300"
+ ],
+ "SHORTDAY": [
+ "\u00c0\u00eck\u00fa",
+ "Aj\u00e9",
+ "\u00ccs\u1eb9\u0301gun",
+ "\u1eccj\u1ecd\u0301r\u00fa",
+ "\u1eccj\u1ecd\u0301b\u1ecd",
+ "\u1eb8t\u00ec",
+ "\u00c0b\u00e1m\u1eb9\u0301ta"
+ ],
+ "SHORTMONTH": [
+ "\u1e62\u1eb9\u0301r\u1eb9\u0301",
+ "\u00c8r\u00e8l\u00e8",
+ "\u1eb8r\u1eb9\u0300n\u00e0",
+ "\u00ccgb\u00e9",
+ "\u1eb8\u0300bibi",
+ "\u00d2k\u00fadu",
+ "Ag\u1eb9m\u1ecd",
+ "\u00d2g\u00fan",
+ "Owewe",
+ "\u1ecc\u0300w\u00e0r\u00e0",
+ "B\u00e9l\u00fa",
+ "\u1ecc\u0300p\u1eb9\u0300"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "yo-ng",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo.js
new file mode 100644
index 00000000..49d87d4f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_yo.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u00c0\u00e1r\u1ecd\u0300",
+ "\u1ecc\u0300s\u00e1n"
+ ],
+ "DAY": [
+ "\u1eccj\u1ecd\u0301 \u00c0\u00eck\u00fa",
+ "\u1eccj\u1ecd\u0301 Aj\u00e9",
+ "\u1eccj\u1ecd\u0301 \u00ccs\u1eb9\u0301gun",
+ "\u1eccj\u1ecd\u0301r\u00fa",
+ "\u1eccj\u1ecd\u0301b\u1ecd",
+ "\u1eccj\u1ecd\u0301 \u1eb8t\u00ec",
+ "\u1eccj\u1ecd\u0301 \u00c0b\u00e1m\u1eb9\u0301ta"
+ ],
+ "ERANAMES": [
+ "Saju Kristi",
+ "Lehin Kristi"
+ ],
+ "ERAS": [
+ "SK",
+ "LK"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "O\u1e63\u00f9 \u1e62\u1eb9\u0301r\u1eb9\u0301",
+ "O\u1e63\u00f9 \u00c8r\u00e8l\u00e8",
+ "O\u1e63\u00f9 \u1eb8r\u1eb9\u0300n\u00e0",
+ "O\u1e63\u00f9 \u00ccgb\u00e9",
+ "O\u1e63\u00f9 \u1eb8\u0300bibi",
+ "O\u1e63\u00f9 \u00d2k\u00fadu",
+ "O\u1e63\u00f9 Ag\u1eb9m\u1ecd",
+ "O\u1e63\u00f9 \u00d2g\u00fan",
+ "O\u1e63\u00f9 Owewe",
+ "O\u1e63\u00f9 \u1ecc\u0300w\u00e0r\u00e0",
+ "O\u1e63\u00f9 B\u00e9l\u00fa",
+ "O\u1e63\u00f9 \u1ecc\u0300p\u1eb9\u0300"
+ ],
+ "SHORTDAY": [
+ "\u00c0\u00eck\u00fa",
+ "Aj\u00e9",
+ "\u00ccs\u1eb9\u0301gun",
+ "\u1eccj\u1ecd\u0301r\u00fa",
+ "\u1eccj\u1ecd\u0301b\u1ecd",
+ "\u1eb8t\u00ec",
+ "\u00c0b\u00e1m\u1eb9\u0301ta"
+ ],
+ "SHORTMONTH": [
+ "\u1e62\u1eb9\u0301r\u1eb9\u0301",
+ "\u00c8r\u00e8l\u00e8",
+ "\u1eb8r\u1eb9\u0300n\u00e0",
+ "\u00ccgb\u00e9",
+ "\u1eb8\u0300bibi",
+ "\u00d2k\u00fadu",
+ "Ag\u1eb9m\u1ecd",
+ "\u00d2g\u00fan",
+ "Owewe",
+ "\u1ecc\u0300w\u00e0r\u00e0",
+ "B\u00e9l\u00fa",
+ "\u1ecc\u0300p\u1eb9\u0300"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM y h:mm:ss a",
+ "mediumDate": "d MMM y",
+ "mediumTime": "h:mm:ss a",
+ "short": "dd/MM/y h:mm a",
+ "shortDate": "dd/MM/y",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u20a6",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "yo",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh-ma.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh-ma.js
new file mode 100644
index 00000000..ec0c86b1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh-ma.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u2d5c\u2d49\u2d3c\u2d30\u2d61\u2d5c",
+ "\u2d5c\u2d30\u2d37\u2d33\u2d33\u2d6f\u2d30\u2d5c"
+ ],
+ "DAY": [
+ "\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59",
+ "\u2d30\u2d62\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d55\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59"
+ ],
+ "ERANAMES": [
+ "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30",
+ "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30"
+ ],
+ "ERAS": [
+ "\u2d37\u2d30\u2d44",
+ "\u2d37\u2d3c\u2d44"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54",
+ "\u2d31\u2d55\u2d30\u2d62\u2d55",
+ "\u2d4e\u2d30\u2d55\u2d5a",
+ "\u2d49\u2d31\u2d54\u2d49\u2d54",
+ "\u2d4e\u2d30\u2d62\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4f\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63",
+ "\u2d56\u2d53\u2d5b\u2d5c",
+ "\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d3d\u2d5c\u2d53\u2d31\u2d54",
+ "\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d37\u2d53\u2d4a\u2d30\u2d4f\u2d31\u2d49\u2d54"
+ ],
+ "SHORTDAY": [
+ "\u2d30\u2d59\u2d30",
+ "\u2d30\u2d62\u2d4f",
+ "\u2d30\u2d59\u2d49",
+ "\u2d30\u2d3d\u2d55",
+ "\u2d30\u2d3d\u2d61",
+ "\u2d30\u2d59\u2d49\u2d4e",
+ "\u2d30\u2d59\u2d49\u2d39"
+ ],
+ "SHORTMONTH": [
+ "\u2d49\u2d4f\u2d4f",
+ "\u2d31\u2d55\u2d30",
+ "\u2d4e\u2d30\u2d55",
+ "\u2d49\u2d31\u2d54",
+ "\u2d4e\u2d30\u2d62",
+ "\u2d62\u2d53\u2d4f",
+ "\u2d62\u2d53\u2d4d",
+ "\u2d56\u2d53\u2d5b",
+ "\u2d5b\u2d53\u2d5c",
+ "\u2d3d\u2d5c\u2d53",
+ "\u2d4f\u2d53\u2d61",
+ "\u2d37\u2d53\u2d4a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "zgh-ma",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh.js
new file mode 100644
index 00000000..c4c7a64e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zgh.js
@@ -0,0 +1,128 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+function getDecimals(n) {
+ n = n + '';
+ var i = n.indexOf('.');
+ return (i == -1) ? 0 : n.length - i - 1;
+}
+
+function getVF(n, opt_precision) {
+ var v = opt_precision;
+
+ if (undefined === v) {
+ v = Math.min(getDecimals(n), 3);
+ }
+
+ var base = Math.pow(10, v);
+ var f = ((n * base) | 0) % base;
+ return {v: v, f: f};
+}
+
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u2d5c\u2d49\u2d3c\u2d30\u2d61\u2d5c",
+ "\u2d5c\u2d30\u2d37\u2d33\u2d33\u2d6f\u2d30\u2d5c"
+ ],
+ "DAY": [
+ "\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59",
+ "\u2d30\u2d62\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d55\u2d30\u2d59",
+ "\u2d30\u2d3d\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59",
+ "\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59"
+ ],
+ "ERANAMES": [
+ "\u2d37\u2d30\u2d5c \u2d4f \u2d44\u2d49\u2d59\u2d30",
+ "\u2d37\u2d3c\u2d3c\u2d49\u2d54 \u2d4f \u2d44\u2d49\u2d59\u2d30"
+ ],
+ "ERAS": [
+ "\u2d37\u2d30\u2d44",
+ "\u2d37\u2d3c\u2d44"
+ ],
+ "FIRSTDAYOFWEEK": 0,
+ "MONTH": [
+ "\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54",
+ "\u2d31\u2d55\u2d30\u2d62\u2d55",
+ "\u2d4e\u2d30\u2d55\u2d5a",
+ "\u2d49\u2d31\u2d54\u2d49\u2d54",
+ "\u2d4e\u2d30\u2d62\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4f\u2d62\u2d53",
+ "\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63",
+ "\u2d56\u2d53\u2d5b\u2d5c",
+ "\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d3d\u2d5c\u2d53\u2d31\u2d54",
+ "\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54",
+ "\u2d37\u2d53\u2d4a\u2d30\u2d4f\u2d31\u2d49\u2d54"
+ ],
+ "SHORTDAY": [
+ "\u2d30\u2d59\u2d30",
+ "\u2d30\u2d62\u2d4f",
+ "\u2d30\u2d59\u2d49",
+ "\u2d30\u2d3d\u2d55",
+ "\u2d30\u2d3d\u2d61",
+ "\u2d30\u2d59\u2d49\u2d4e",
+ "\u2d30\u2d59\u2d49\u2d39"
+ ],
+ "SHORTMONTH": [
+ "\u2d49\u2d4f\u2d4f",
+ "\u2d31\u2d55\u2d30",
+ "\u2d4e\u2d30\u2d55",
+ "\u2d49\u2d31\u2d54",
+ "\u2d4e\u2d30\u2d62",
+ "\u2d62\u2d53\u2d4f",
+ "\u2d62\u2d53\u2d4d",
+ "\u2d56\u2d53\u2d5b",
+ "\u2d5b\u2d53\u2d5c",
+ "\u2d3d\u2d5c\u2d53",
+ "\u2d4f\u2d53\u2d61",
+ "\u2d37\u2d53\u2d4a"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE d MMMM y",
+ "longDate": "d MMMM y",
+ "medium": "d MMM, y HH:mm:ss",
+ "mediumDate": "d MMM, y",
+ "mediumTime": "HH:mm:ss",
+ "short": "d/M/y HH:mm",
+ "shortDate": "d/M/y",
+ "shortTime": "HH:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "dh",
+ "DECIMAL_SEP": ",",
+ "GROUP_SEP": "\u00a0",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "\u00a4",
+ "posPre": "",
+ "posSuf": "\u00a4"
+ }
+ ]
+ },
+ "id": "zgh",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-cn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-cn.js
new file mode 100644
index 00000000..d15cdd61
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-cn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "yy/M/d ah:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-cn",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-cn.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-cn.js
new file mode 100644
index 00000000..120aa830
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-cn.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "yy/M/d ah:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hans-cn",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-hk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-hk.js
new file mode 100644
index 00000000..d47c48b1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-hk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "d/M/yy ah:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hans-hk",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-mo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-mo.js
new file mode 100644
index 00000000..750fd374
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-mo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "d/M/yy ah:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MOP",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hans-mo",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-sg.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-sg.js
new file mode 100644
index 00000000..329df2df
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans-sg.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "dd/MM/yy ah:mm",
+ "shortDate": "dd/MM/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hans-sg",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans.js
new file mode 100644
index 00000000..920d39d0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hans.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "yy/M/d ah:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hans",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-hk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-hk.js
new file mode 100644
index 00000000..23d60d7c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-hk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "d/M/yy ah:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hant-hk",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-mo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-mo.js
new file mode 100644
index 00000000..a6e4a328
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-mo.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "d/M/yy ah:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "MOP",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hant-mo",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-tw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-tw.js
new file mode 100644
index 00000000..7caaa086
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant-tw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "ERAS": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5 EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "y/M/d ah:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NT$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hant-tw",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant.js
new file mode 100644
index 00000000..99b7e43d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hant.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "ERAS": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5 EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "y/M/d ah:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NT$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hant",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hk.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hk.js
new file mode 100644
index 00000000..6c8fefb3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-hk.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "d/M/yy ah:mm",
+ "shortDate": "d/M/yy",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-hk",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-tw.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-tw.js
new file mode 100644
index 00000000..b834a617
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh-tw.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "ERAS": [
+ "\u897f\u5143\u524d",
+ "\u897f\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "SHORTDAY": [
+ "\u9031\u65e5",
+ "\u9031\u4e00",
+ "\u9031\u4e8c",
+ "\u9031\u4e09",
+ "\u9031\u56db",
+ "\u9031\u4e94",
+ "\u9031\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5 EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "y/M/d ah:mm",
+ "shortDate": "y/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "NT$",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh-tw",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh.js
new file mode 100644
index 00000000..8c764a76
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zh.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "\u4e0a\u5348",
+ "\u4e0b\u5348"
+ ],
+ "DAY": [
+ "\u661f\u671f\u65e5",
+ "\u661f\u671f\u4e00",
+ "\u661f\u671f\u4e8c",
+ "\u661f\u671f\u4e09",
+ "\u661f\u671f\u56db",
+ "\u661f\u671f\u4e94",
+ "\u661f\u671f\u516d"
+ ],
+ "ERANAMES": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "ERAS": [
+ "\u516c\u5143\u524d",
+ "\u516c\u5143"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708"
+ ],
+ "SHORTDAY": [
+ "\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d"
+ ],
+ "SHORTMONTH": [
+ "1\u6708",
+ "2\u6708",
+ "3\u6708",
+ "4\u6708",
+ "5\u6708",
+ "6\u6708",
+ "7\u6708",
+ "8\u6708",
+ "9\u6708",
+ "10\u6708",
+ "11\u6708",
+ "12\u6708"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "y\u5e74M\u6708d\u65e5EEEE",
+ "longDate": "y\u5e74M\u6708d\u65e5",
+ "medium": "y\u5e74M\u6708d\u65e5 ah:mm:ss",
+ "mediumDate": "y\u5e74M\u6708d\u65e5",
+ "mediumTime": "ah:mm:ss",
+ "short": "yy/M/d ah:mm",
+ "shortDate": "yy/M/d",
+ "shortTime": "ah:mm"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "\u00a5",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4\u00a0",
+ "negSuf": "",
+ "posPre": "\u00a4\u00a0",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zh",
+ "pluralCat": function(n, opt_precision) { return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu-za.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu-za.js
new file mode 100644
index 00000000..4f48a9fd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu-za.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Ekuseni",
+ "Ntambama"
+ ],
+ "DAY": [
+ "Sonto",
+ "Msombuluko",
+ "Lwesibili",
+ "Lwesithathu",
+ "Lwesine",
+ "Lwesihlanu",
+ "Mgqibelo"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januwari",
+ "Februwari",
+ "Mashi",
+ "Apreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Agasti",
+ "Septhemba",
+ "Okthoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mso",
+ "Bil",
+ "Tha",
+ "Sin",
+ "Hla",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mas",
+ "Apr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Aga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zu-za",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu.js
new file mode 100644
index 00000000..bd4d00ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/i18n/angular-locale_zu.js
@@ -0,0 +1,110 @@
+'use strict';
+angular.module("ngLocale", [], ["$provide", function($provide) {
+var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
+$provide.value("$locale", {
+ "DATETIME_FORMATS": {
+ "AMPMS": [
+ "Ekuseni",
+ "Ntambama"
+ ],
+ "DAY": [
+ "Sonto",
+ "Msombuluko",
+ "Lwesibili",
+ "Lwesithathu",
+ "Lwesine",
+ "Lwesihlanu",
+ "Mgqibelo"
+ ],
+ "ERANAMES": [
+ "BC",
+ "AD"
+ ],
+ "ERAS": [
+ "BC",
+ "AD"
+ ],
+ "FIRSTDAYOFWEEK": 6,
+ "MONTH": [
+ "Januwari",
+ "Februwari",
+ "Mashi",
+ "Apreli",
+ "Meyi",
+ "Juni",
+ "Julayi",
+ "Agasti",
+ "Septhemba",
+ "Okthoba",
+ "Novemba",
+ "Disemba"
+ ],
+ "SHORTDAY": [
+ "Son",
+ "Mso",
+ "Bil",
+ "Tha",
+ "Sin",
+ "Hla",
+ "Mgq"
+ ],
+ "SHORTMONTH": [
+ "Jan",
+ "Feb",
+ "Mas",
+ "Apr",
+ "Mey",
+ "Jun",
+ "Jul",
+ "Aga",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dis"
+ ],
+ "WEEKENDRANGE": [
+ 5,
+ 6
+ ],
+ "fullDate": "EEEE, MMMM d, y",
+ "longDate": "MMMM d, y",
+ "medium": "MMM d, y h:mm:ss a",
+ "mediumDate": "MMM d, y",
+ "mediumTime": "h:mm:ss a",
+ "short": "M/d/yy h:mm a",
+ "shortDate": "M/d/yy",
+ "shortTime": "h:mm a"
+ },
+ "NUMBER_FORMATS": {
+ "CURRENCY_SYM": "R",
+ "DECIMAL_SEP": ".",
+ "GROUP_SEP": ",",
+ "PATTERNS": [
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 3,
+ "minFrac": 0,
+ "minInt": 1,
+ "negPre": "-",
+ "negSuf": "",
+ "posPre": "",
+ "posSuf": ""
+ },
+ {
+ "gSize": 3,
+ "lgSize": 3,
+ "maxFrac": 2,
+ "minFrac": 2,
+ "minInt": 1,
+ "negPre": "-\u00a4",
+ "negSuf": "",
+ "posPre": "\u00a4",
+ "posSuf": ""
+ }
+ ]
+ },
+ "id": "zu",
+ "pluralCat": function(n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
+});
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.json
new file mode 100644
index 00000000..f58f0b59
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.json
@@ -0,0 +1 @@
+{"raw":"v1.4.8","major":1,"minor":4,"patch":8,"prerelease":[],"build":[],"version":"1.4.8","codeName":"ice-manipulation","full":"1.4.8","branch":"v1.4.x","cdn":{"raw":"v1.4.7","major":1,"minor":4,"patch":7,"prerelease":[],"build":[],"version":"1.4.7","docsUrl":"http://code.angularjs.org/1.4.7/docs"}} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.txt
new file mode 100644
index 00000000..721b9931
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-1.4.8/version.txt
@@ -0,0 +1 @@
+1.4.8 \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/index.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/index.js
new file mode 100644
index 00000000..a174f26d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/index.js
@@ -0,0 +1,2 @@
+require('./ui-bootstrap-tpls');
+module.exports = 'ui.bootstrap';
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css
new file mode 100644
index 00000000..3b69cf64
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css
@@ -0,0 +1,115 @@
+/* Include this file in your html if you are using the CSP mode. */
+
+.ng-animate.item:not(.left):not(.right) {
+ -webkit-transition: 0s ease-in-out left;
+ transition: 0s ease-in-out left
+}
+.uib-datepicker .uib-title {
+ width: 100%;
+}
+
+.uib-day button, .uib-month button, .uib-year button {
+ min-width: 100%;
+}
+
+.uib-left, .uib-right {
+ width: 100%
+}
+
+.uib-position-measure {
+ display: block !important;
+ visibility: hidden !important;
+ position: absolute !important;
+ top: -9999px !important;
+ left: -9999px !important;
+}
+
+.uib-position-scrollbar-measure {
+ position: absolute !important;
+ top: -9999px !important;
+ width: 50px !important;
+ height: 50px !important;
+ overflow: scroll !important;
+}
+
+.uib-position-body-scrollbar-measure {
+ overflow: scroll !important;
+}
+.uib-datepicker-popup.dropdown-menu {
+ display: block;
+ float: none;
+ margin: 0;
+}
+
+.uib-button-bar {
+ padding: 10px 9px 2px;
+}
+
+[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,
+[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,
+[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,
+[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,
+[uib-popover-popup].popover.top-left > .arrow,
+[uib-popover-popup].popover.top-right > .arrow,
+[uib-popover-popup].popover.bottom-left > .arrow,
+[uib-popover-popup].popover.bottom-right > .arrow,
+[uib-popover-popup].popover.left-top > .arrow,
+[uib-popover-popup].popover.left-bottom > .arrow,
+[uib-popover-popup].popover.right-top > .arrow,
+[uib-popover-popup].popover.right-bottom > .arrow,
+[uib-popover-html-popup].popover.top-left > .arrow,
+[uib-popover-html-popup].popover.top-right > .arrow,
+[uib-popover-html-popup].popover.bottom-left > .arrow,
+[uib-popover-html-popup].popover.bottom-right > .arrow,
+[uib-popover-html-popup].popover.left-top > .arrow,
+[uib-popover-html-popup].popover.left-bottom > .arrow,
+[uib-popover-html-popup].popover.right-top > .arrow,
+[uib-popover-html-popup].popover.right-bottom > .arrow,
+[uib-popover-template-popup].popover.top-left > .arrow,
+[uib-popover-template-popup].popover.top-right > .arrow,
+[uib-popover-template-popup].popover.bottom-left > .arrow,
+[uib-popover-template-popup].popover.bottom-right > .arrow,
+[uib-popover-template-popup].popover.left-top > .arrow,
+[uib-popover-template-popup].popover.left-bottom > .arrow,
+[uib-popover-template-popup].popover.right-top > .arrow,
+[uib-popover-template-popup].popover.right-bottom > .arrow {
+ top: auto;
+ bottom: auto;
+ left: auto;
+ right: auto;
+ margin: 0;
+}
+
+[uib-popover-popup].popover,
+[uib-popover-html-popup].popover,
+[uib-popover-template-popup].popover {
+ display: block !important;
+}
+
+.uib-time input {
+ width: 50px;
+}
+
+[uib-typeahead-popup].dropdown-menu {
+ display: block;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.js
new file mode 100644
index 00000000..67838936
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.js
@@ -0,0 +1,7776 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 2.5.0 - 2017-01-28
+ * License: MIT
+ */angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
+angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]);
+angular.module('ui.bootstrap.collapse', [])
+
+ .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) {
+ var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
+ return {
+ link: function(scope, element, attrs) {
+ var expandingExpr = $parse(attrs.expanding),
+ expandedExpr = $parse(attrs.expanded),
+ collapsingExpr = $parse(attrs.collapsing),
+ collapsedExpr = $parse(attrs.collapsed),
+ horizontal = false,
+ css = {},
+ cssTo = {};
+
+ init();
+
+ function init() {
+ horizontal = !!('horizontal' in attrs);
+ if (horizontal) {
+ css = {
+ width: ''
+ };
+ cssTo = {width: '0'};
+ } else {
+ css = {
+ height: ''
+ };
+ cssTo = {height: '0'};
+ }
+ if (!scope.$eval(attrs.uibCollapse)) {
+ element.addClass('in')
+ .addClass('collapse')
+ .attr('aria-expanded', true)
+ .attr('aria-hidden', false)
+ .css(css);
+ }
+ }
+
+ function getScrollFromElement(element) {
+ if (horizontal) {
+ return {width: element.scrollWidth + 'px'};
+ }
+ return {height: element.scrollHeight + 'px'};
+ }
+
+ function expand() {
+ if (element.hasClass('collapse') && element.hasClass('in')) {
+ return;
+ }
+
+ $q.resolve(expandingExpr(scope))
+ .then(function() {
+ element.removeClass('collapse')
+ .addClass('collapsing')
+ .attr('aria-expanded', true)
+ .attr('aria-hidden', false);
+
+ if ($animateCss) {
+ $animateCss(element, {
+ addClass: 'in',
+ easing: 'ease',
+ css: {
+ overflow: 'hidden'
+ },
+ to: getScrollFromElement(element[0])
+ }).start()['finally'](expandDone);
+ } else {
+ $animate.addClass(element, 'in', {
+ css: {
+ overflow: 'hidden'
+ },
+ to: getScrollFromElement(element[0])
+ }).then(expandDone);
+ }
+ }, angular.noop);
+ }
+
+ function expandDone() {
+ element.removeClass('collapsing')
+ .addClass('collapse')
+ .css(css);
+ expandedExpr(scope);
+ }
+
+ function collapse() {
+ if (!element.hasClass('collapse') && !element.hasClass('in')) {
+ return collapseDone();
+ }
+
+ $q.resolve(collapsingExpr(scope))
+ .then(function() {
+ element
+ // IMPORTANT: The width must be set before adding "collapsing" class.
+ // Otherwise, the browser attempts to animate from width 0 (in
+ // collapsing class) to the given width here.
+ .css(getScrollFromElement(element[0]))
+ // initially all panel collapse have the collapse class, this removal
+ // prevents the animation from jumping to collapsed state
+ .removeClass('collapse')
+ .addClass('collapsing')
+ .attr('aria-expanded', false)
+ .attr('aria-hidden', true);
+
+ if ($animateCss) {
+ $animateCss(element, {
+ removeClass: 'in',
+ to: cssTo
+ }).start()['finally'](collapseDone);
+ } else {
+ $animate.removeClass(element, 'in', {
+ to: cssTo
+ }).then(collapseDone);
+ }
+ }, angular.noop);
+ }
+
+ function collapseDone() {
+ element.css(cssTo); // Required so that collapse works when animation is disabled
+ element.removeClass('collapsing')
+ .addClass('collapse');
+ collapsedExpr(scope);
+ }
+
+ scope.$watch(attrs.uibCollapse, function(shouldCollapse) {
+ if (shouldCollapse) {
+ collapse();
+ } else {
+ expand();
+ }
+ });
+ }
+ };
+ }]);
+
+angular.module('ui.bootstrap.tabindex', [])
+
+.directive('uibTabindexToggle', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, elem, attrs) {
+ attrs.$observe('disabled', function(disabled) {
+ attrs.$set('tabindex', disabled ? -1 : null);
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])
+
+.constant('uibAccordionConfig', {
+ closeOthers: true
+})
+
+.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {
+ // This array keeps track of the accordion groups
+ this.groups = [];
+
+ // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
+ this.closeOthers = function(openGroup) {
+ var closeOthers = angular.isDefined($attrs.closeOthers) ?
+ $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
+ if (closeOthers) {
+ angular.forEach(this.groups, function(group) {
+ if (group !== openGroup) {
+ group.isOpen = false;
+ }
+ });
+ }
+ };
+
+ // This is called from the accordion-group directive to add itself to the accordion
+ this.addGroup = function(groupScope) {
+ var that = this;
+ this.groups.push(groupScope);
+
+ groupScope.$on('$destroy', function(event) {
+ that.removeGroup(groupScope);
+ });
+ };
+
+ // This is called from the accordion-group directive when to remove itself
+ this.removeGroup = function(group) {
+ var index = this.groups.indexOf(group);
+ if (index !== -1) {
+ this.groups.splice(index, 1);
+ }
+ };
+}])
+
+// The accordion directive simply sets up the directive controller
+// and adds an accordion CSS class to itself element.
+.directive('uibAccordion', function() {
+ return {
+ controller: 'UibAccordionController',
+ controllerAs: 'accordion',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/accordion/accordion.html';
+ }
+ };
+})
+
+// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
+.directive('uibAccordionGroup', function() {
+ return {
+ require: '^uibAccordion', // We need this directive to be inside an accordion
+ transclude: true, // It transcludes the contents of the directive into the template
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
+ },
+ scope: {
+ heading: '@', // Interpolate the heading attribute onto this scope
+ panelClass: '@?', // Ditto with panelClass
+ isOpen: '=?',
+ isDisabled: '=?'
+ },
+ controller: function() {
+ this.setHeading = function(element) {
+ this.heading = element;
+ };
+ },
+ link: function(scope, element, attrs, accordionCtrl) {
+ element.addClass('panel');
+ accordionCtrl.addGroup(scope);
+
+ scope.openClass = attrs.openClass || 'panel-open';
+ scope.panelClass = attrs.panelClass || 'panel-default';
+ scope.$watch('isOpen', function(value) {
+ element.toggleClass(scope.openClass, !!value);
+ if (value) {
+ accordionCtrl.closeOthers(scope);
+ }
+ });
+
+ scope.toggleOpen = function($event) {
+ if (!scope.isDisabled) {
+ if (!$event || $event.which === 32) {
+ scope.isOpen = !scope.isOpen;
+ }
+ }
+ };
+
+ var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
+ scope.headingId = id + '-tab';
+ scope.panelId = id + '-panel';
+ }
+ };
+})
+
+// Use accordion-heading below an accordion-group to provide a heading containing HTML
+.directive('uibAccordionHeading', function() {
+ return {
+ transclude: true, // Grab the contents to be used as the heading
+ template: '', // In effect remove this element!
+ replace: true,
+ require: '^uibAccordionGroup',
+ link: function(scope, element, attrs, accordionGroupCtrl, transclude) {
+ // Pass the heading to the accordion-group controller
+ // so that it can be transcluded into the right place in the template
+ // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
+ accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
+ }
+ };
+})
+
+// Use in the accordion-group template to indicate where you want the heading to be transcluded
+// You must provide the property on the accordion-group controller that will hold the transcluded element
+.directive('uibAccordionTransclude', function() {
+ return {
+ require: '^uibAccordionGroup',
+ link: function(scope, element, attrs, controller) {
+ scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {
+ if (heading) {
+ var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
+ elem.html('');
+ elem.append(heading);
+ }
+ });
+ }
+ };
+
+ function getHeaderSelectors() {
+ return 'uib-accordion-header,' +
+ 'data-uib-accordion-header,' +
+ 'x-uib-accordion-header,' +
+ 'uib\\:accordion-header,' +
+ '[uib-accordion-header],' +
+ '[data-uib-accordion-header],' +
+ '[x-uib-accordion-header]';
+ }
+});
+
+angular.module('ui.bootstrap.alert', [])
+
+.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) {
+ $scope.closeable = !!$attrs.close;
+ $element.addClass('alert');
+ $attrs.$set('role', 'alert');
+ if ($scope.closeable) {
+ $element.addClass('alert-dismissible');
+ }
+
+ var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
+ $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;
+
+ if (dismissOnTimeout) {
+ $timeout(function() {
+ $scope.close();
+ }, parseInt(dismissOnTimeout, 10));
+ }
+}])
+
+.directive('uibAlert', function() {
+ return {
+ controller: 'UibAlertController',
+ controllerAs: 'alert',
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/alert/alert.html';
+ },
+ transclude: true,
+ scope: {
+ close: '&'
+ }
+ };
+});
+
+angular.module('ui.bootstrap.buttons', [])
+
+.constant('uibButtonConfig', {
+ activeClass: 'active',
+ toggleEvent: 'click'
+})
+
+.controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {
+ this.activeClass = buttonConfig.activeClass || 'active';
+ this.toggleEvent = buttonConfig.toggleEvent || 'click';
+}])
+
+.directive('uibBtnRadio', ['$parse', function($parse) {
+ return {
+ require: ['uibBtnRadio', 'ngModel'],
+ controller: 'UibButtonsController',
+ controllerAs: 'buttons',
+ link: function(scope, element, attrs, ctrls) {
+ var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+ var uncheckableExpr = $parse(attrs.uibUncheckable);
+
+ element.find('input').css({display: 'none'});
+
+ //model -> UI
+ ngModelCtrl.$render = function() {
+ element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
+ };
+
+ //ui->model
+ element.on(buttonsCtrl.toggleEvent, function() {
+ if (attrs.disabled) {
+ return;
+ }
+
+ var isActive = element.hasClass(buttonsCtrl.activeClass);
+
+ if (!isActive || angular.isDefined(attrs.uncheckable)) {
+ scope.$apply(function() {
+ ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
+ ngModelCtrl.$render();
+ });
+ }
+ });
+
+ if (attrs.uibUncheckable) {
+ scope.$watch(uncheckableExpr, function(uncheckable) {
+ attrs.$set('uncheckable', uncheckable ? '' : undefined);
+ });
+ }
+ }
+ };
+}])
+
+.directive('uibBtnCheckbox', function() {
+ return {
+ require: ['uibBtnCheckbox', 'ngModel'],
+ controller: 'UibButtonsController',
+ controllerAs: 'button',
+ link: function(scope, element, attrs, ctrls) {
+ var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ element.find('input').css({display: 'none'});
+
+ function getTrueValue() {
+ return getCheckboxValue(attrs.btnCheckboxTrue, true);
+ }
+
+ function getFalseValue() {
+ return getCheckboxValue(attrs.btnCheckboxFalse, false);
+ }
+
+ function getCheckboxValue(attribute, defaultValue) {
+ return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
+ }
+
+ //model -> UI
+ ngModelCtrl.$render = function() {
+ element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
+ };
+
+ //ui->model
+ element.on(buttonsCtrl.toggleEvent, function() {
+ if (attrs.disabled) {
+ return;
+ }
+
+ scope.$apply(function() {
+ ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
+ ngModelCtrl.$render();
+ });
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.carousel', [])
+
+.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) {
+ var self = this,
+ slides = self.slides = $scope.slides = [],
+ SLIDE_DIRECTION = 'uib-slideDirection',
+ currentIndex = $scope.active,
+ currentInterval, isPlaying;
+
+ var destroyed = false;
+ $element.addClass('carousel');
+
+ self.addSlide = function(slide, element) {
+ slides.push({
+ slide: slide,
+ element: element
+ });
+ slides.sort(function(a, b) {
+ return +a.slide.index - +b.slide.index;
+ });
+ //if this is the first slide or the slide is set to active, select it
+ if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
+ if ($scope.$currentTransition) {
+ $scope.$currentTransition = null;
+ }
+
+ currentIndex = slide.index;
+ $scope.active = slide.index;
+ setActive(currentIndex);
+ self.select(slides[findSlideIndex(slide)]);
+ if (slides.length === 1) {
+ $scope.play();
+ }
+ }
+ };
+
+ self.getCurrentIndex = function() {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide.index === currentIndex) {
+ return i;
+ }
+ }
+ };
+
+ self.next = $scope.next = function() {
+ var newIndex = (self.getCurrentIndex() + 1) % slides.length;
+
+ if (newIndex === 0 && $scope.noWrap()) {
+ $scope.pause();
+ return;
+ }
+
+ return self.select(slides[newIndex], 'next');
+ };
+
+ self.prev = $scope.prev = function() {
+ var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
+
+ if ($scope.noWrap() && newIndex === slides.length - 1) {
+ $scope.pause();
+ return;
+ }
+
+ return self.select(slides[newIndex], 'prev');
+ };
+
+ self.removeSlide = function(slide) {
+ var index = findSlideIndex(slide);
+
+ //get the index of the slide inside the carousel
+ slides.splice(index, 1);
+ if (slides.length > 0 && currentIndex === index) {
+ if (index >= slides.length) {
+ currentIndex = slides.length - 1;
+ $scope.active = currentIndex;
+ setActive(currentIndex);
+ self.select(slides[slides.length - 1]);
+ } else {
+ currentIndex = index;
+ $scope.active = currentIndex;
+ setActive(currentIndex);
+ self.select(slides[index]);
+ }
+ } else if (currentIndex > index) {
+ currentIndex--;
+ $scope.active = currentIndex;
+ }
+
+ //clean the active value when no more slide
+ if (slides.length === 0) {
+ currentIndex = null;
+ $scope.active = null;
+ }
+ };
+
+ /* direction: "prev" or "next" */
+ self.select = $scope.select = function(nextSlide, direction) {
+ var nextIndex = findSlideIndex(nextSlide.slide);
+ //Decide direction if it's not given
+ if (direction === undefined) {
+ direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
+ }
+ //Prevent this user-triggered transition from occurring if there is already one in progress
+ if (nextSlide.slide.index !== currentIndex &&
+ !$scope.$currentTransition) {
+ goNext(nextSlide.slide, nextIndex, direction);
+ }
+ };
+
+ /* Allow outside people to call indexOf on slides array */
+ $scope.indexOfSlide = function(slide) {
+ return +slide.slide.index;
+ };
+
+ $scope.isActive = function(slide) {
+ return $scope.active === slide.slide.index;
+ };
+
+ $scope.isPrevDisabled = function() {
+ return $scope.active === 0 && $scope.noWrap();
+ };
+
+ $scope.isNextDisabled = function() {
+ return $scope.active === slides.length - 1 && $scope.noWrap();
+ };
+
+ $scope.pause = function() {
+ if (!$scope.noPause) {
+ isPlaying = false;
+ resetTimer();
+ }
+ };
+
+ $scope.play = function() {
+ if (!isPlaying) {
+ isPlaying = true;
+ restartTimer();
+ }
+ };
+
+ $element.on('mouseenter', $scope.pause);
+ $element.on('mouseleave', $scope.play);
+
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ resetTimer();
+ });
+
+ $scope.$watch('noTransition', function(noTransition) {
+ $animate.enabled($element, !noTransition);
+ });
+
+ $scope.$watch('interval', restartTimer);
+
+ $scope.$watchCollection('slides', resetTransition);
+
+ $scope.$watch('active', function(index) {
+ if (angular.isNumber(index) && currentIndex !== index) {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide.index === index) {
+ index = i;
+ break;
+ }
+ }
+
+ var slide = slides[index];
+ if (slide) {
+ setActive(index);
+ self.select(slides[index]);
+ currentIndex = index;
+ }
+ }
+ });
+
+ function getSlideByIndex(index) {
+ for (var i = 0, l = slides.length; i < l; ++i) {
+ if (slides[i].index === index) {
+ return slides[i];
+ }
+ }
+ }
+
+ function setActive(index) {
+ for (var i = 0; i < slides.length; i++) {
+ slides[i].slide.active = i === index;
+ }
+ }
+
+ function goNext(slide, index, direction) {
+ if (destroyed) {
+ return;
+ }
+
+ angular.extend(slide, {direction: direction});
+ angular.extend(slides[currentIndex].slide || {}, {direction: direction});
+ if ($animate.enabled($element) && !$scope.$currentTransition &&
+ slides[index].element && self.slides.length > 1) {
+ slides[index].element.data(SLIDE_DIRECTION, slide.direction);
+ var currentIdx = self.getCurrentIndex();
+
+ if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
+ slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
+ }
+
+ $scope.$currentTransition = true;
+ $animate.on('addClass', slides[index].element, function(element, phase) {
+ if (phase === 'close') {
+ $scope.$currentTransition = null;
+ $animate.off('addClass', element);
+ }
+ });
+ }
+
+ $scope.active = slide.index;
+ currentIndex = slide.index;
+ setActive(index);
+
+ //every time you change slides, reset the timer
+ restartTimer();
+ }
+
+ function findSlideIndex(slide) {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide === slide) {
+ return i;
+ }
+ }
+ }
+
+ function resetTimer() {
+ if (currentInterval) {
+ $interval.cancel(currentInterval);
+ currentInterval = null;
+ }
+ }
+
+ function resetTransition(slides) {
+ if (!slides.length) {
+ $scope.$currentTransition = null;
+ }
+ }
+
+ function restartTimer() {
+ resetTimer();
+ var interval = +$scope.interval;
+ if (!isNaN(interval) && interval > 0) {
+ currentInterval = $interval(timerFn, interval);
+ }
+ }
+
+ function timerFn() {
+ var interval = +$scope.interval;
+ if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
+ $scope.next();
+ } else {
+ $scope.pause();
+ }
+ }
+}])
+
+.directive('uibCarousel', function() {
+ return {
+ transclude: true,
+ controller: 'UibCarouselController',
+ controllerAs: 'carousel',
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/carousel/carousel.html';
+ },
+ scope: {
+ active: '=',
+ interval: '=',
+ noTransition: '=',
+ noPause: '=',
+ noWrap: '&'
+ }
+ };
+})
+
+.directive('uibSlide', ['$animate', function($animate) {
+ return {
+ require: '^uibCarousel',
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/carousel/slide.html';
+ },
+ scope: {
+ actual: '=?',
+ index: '=?'
+ },
+ link: function (scope, element, attrs, carouselCtrl) {
+ element.addClass('item');
+ carouselCtrl.addSlide(scope, element);
+ //when the scope is destroyed then remove the slide from the current slides array
+ scope.$on('$destroy', function() {
+ carouselCtrl.removeSlide(scope);
+ });
+
+ scope.$watch('active', function(active) {
+ $animate[active ? 'addClass' : 'removeClass'](element, 'active');
+ });
+ }
+ };
+}])
+
+.animation('.item', ['$animateCss',
+function($animateCss) {
+ var SLIDE_DIRECTION = 'uib-slideDirection';
+
+ function removeClass(element, className, callback) {
+ element.removeClass(className);
+ if (callback) {
+ callback();
+ }
+ }
+
+ return {
+ beforeAddClass: function(element, className, done) {
+ if (className === 'active') {
+ var stopped = false;
+ var direction = element.data(SLIDE_DIRECTION);
+ var directionClass = direction === 'next' ? 'left' : 'right';
+ var removeClassFn = removeClass.bind(this, element,
+ directionClass + ' ' + direction, done);
+ element.addClass(direction);
+
+ $animateCss(element, {addClass: directionClass})
+ .start()
+ .done(removeClassFn);
+
+ return function() {
+ stopped = true;
+ };
+ }
+ done();
+ },
+ beforeRemoveClass: function (element, className, done) {
+ if (className === 'active') {
+ var stopped = false;
+ var direction = element.data(SLIDE_DIRECTION);
+ var directionClass = direction === 'next' ? 'left' : 'right';
+ var removeClassFn = removeClass.bind(this, element, directionClass, done);
+
+ $animateCss(element, {addClass: directionClass})
+ .start()
+ .done(removeClassFn);
+
+ return function() {
+ stopped = true;
+ };
+ }
+ done();
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.dateparser', [])
+
+.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', 'filterFilter', function($log, $locale, dateFilter, orderByFilter, filterFilter) {
+ // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
+ var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+
+ var localeId;
+ var formatCodeToRegex;
+
+ this.init = function() {
+ localeId = $locale.id;
+
+ this.parsers = {};
+ this.formatters = {};
+
+ formatCodeToRegex = [
+ {
+ key: 'yyyy',
+ regex: '\\d{4}',
+ apply: function(value) { this.year = +value; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'yyyy');
+ }
+ },
+ {
+ key: 'yy',
+ regex: '\\d{2}',
+ apply: function(value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'yy');
+ }
+ },
+ {
+ key: 'y',
+ regex: '\\d{1,4}',
+ apply: function(value) { this.year = +value; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'y');
+ }
+ },
+ {
+ key: 'M!',
+ regex: '0?[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) {
+ var value = date.getMonth();
+ if (/^[0-9]$/.test(value)) {
+ return dateFilter(date, 'MM');
+ }
+
+ return dateFilter(date, 'M');
+ }
+ },
+ {
+ key: 'MMMM',
+ regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'MMMM'); }
+ },
+ {
+ key: 'MMM',
+ regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'MMM'); }
+ },
+ {
+ key: 'MM',
+ regex: '0[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) { return dateFilter(date, 'MM'); }
+ },
+ {
+ key: 'M',
+ regex: '[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) { return dateFilter(date, 'M'); }
+ },
+ {
+ key: 'd!',
+ regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) {
+ var value = date.getDate();
+ if (/^[1-9]$/.test(value)) {
+ return dateFilter(date, 'dd');
+ }
+
+ return dateFilter(date, 'd');
+ }
+ },
+ {
+ key: 'dd',
+ regex: '[0-2][0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) { return dateFilter(date, 'dd'); }
+ },
+ {
+ key: 'd',
+ regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) { return dateFilter(date, 'd'); }
+ },
+ {
+ key: 'EEEE',
+ regex: $locale.DATETIME_FORMATS.DAY.join('|'),
+ formatter: function(date) { return dateFilter(date, 'EEEE'); }
+ },
+ {
+ key: 'EEE',
+ regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
+ formatter: function(date) { return dateFilter(date, 'EEE'); }
+ },
+ {
+ key: 'HH',
+ regex: '(?:0|1)[0-9]|2[0-3]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'HH'); }
+ },
+ {
+ key: 'hh',
+ regex: '0[0-9]|1[0-2]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'hh'); }
+ },
+ {
+ key: 'H',
+ regex: '1?[0-9]|2[0-3]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'H'); }
+ },
+ {
+ key: 'h',
+ regex: '[0-9]|1[0-2]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'h'); }
+ },
+ {
+ key: 'mm',
+ regex: '[0-5][0-9]',
+ apply: function(value) { this.minutes = +value; },
+ formatter: function(date) { return dateFilter(date, 'mm'); }
+ },
+ {
+ key: 'm',
+ regex: '[0-9]|[1-5][0-9]',
+ apply: function(value) { this.minutes = +value; },
+ formatter: function(date) { return dateFilter(date, 'm'); }
+ },
+ {
+ key: 'sss',
+ regex: '[0-9][0-9][0-9]',
+ apply: function(value) { this.milliseconds = +value; },
+ formatter: function(date) { return dateFilter(date, 'sss'); }
+ },
+ {
+ key: 'ss',
+ regex: '[0-5][0-9]',
+ apply: function(value) { this.seconds = +value; },
+ formatter: function(date) { return dateFilter(date, 'ss'); }
+ },
+ {
+ key: 's',
+ regex: '[0-9]|[1-5][0-9]',
+ apply: function(value) { this.seconds = +value; },
+ formatter: function(date) { return dateFilter(date, 's'); }
+ },
+ {
+ key: 'a',
+ regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
+ apply: function(value) {
+ if (this.hours === 12) {
+ this.hours = 0;
+ }
+
+ if (value === 'PM') {
+ this.hours += 12;
+ }
+ },
+ formatter: function(date) { return dateFilter(date, 'a'); }
+ },
+ {
+ key: 'Z',
+ regex: '[+-]\\d{4}',
+ apply: function(value) {
+ var matches = value.match(/([+-])(\d{2})(\d{2})/),
+ sign = matches[1],
+ hours = matches[2],
+ minutes = matches[3];
+ this.hours += toInt(sign + hours);
+ this.minutes += toInt(sign + minutes);
+ },
+ formatter: function(date) {
+ return dateFilter(date, 'Z');
+ }
+ },
+ {
+ key: 'ww',
+ regex: '[0-4][0-9]|5[0-3]',
+ formatter: function(date) { return dateFilter(date, 'ww'); }
+ },
+ {
+ key: 'w',
+ regex: '[0-9]|[1-4][0-9]|5[0-3]',
+ formatter: function(date) { return dateFilter(date, 'w'); }
+ },
+ {
+ key: 'GGGG',
+ regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
+ formatter: function(date) { return dateFilter(date, 'GGGG'); }
+ },
+ {
+ key: 'GGG',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'GGG'); }
+ },
+ {
+ key: 'GG',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'GG'); }
+ },
+ {
+ key: 'G',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'G'); }
+ }
+ ];
+
+ if (angular.version.major >= 1 && angular.version.minor > 4) {
+ formatCodeToRegex.push({
+ key: 'LLLL',
+ regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'LLLL'); }
+ });
+ }
+ };
+
+ this.init();
+
+ function getFormatCodeToRegex(key) {
+ return filterFilter(formatCodeToRegex, {key: key}, true)[0];
+ }
+
+ this.getParser = function (key) {
+ var f = getFormatCodeToRegex(key);
+ return f && f.apply || null;
+ };
+
+ this.overrideParser = function (key, parser) {
+ var f = getFormatCodeToRegex(key);
+ if (f && angular.isFunction(parser)) {
+ this.parsers = {};
+ f.apply = parser;
+ }
+ }.bind(this);
+
+ function createParser(format) {
+ var map = [], regex = format.split('');
+
+ // check for literal values
+ var quoteIndex = format.indexOf('\'');
+ if (quoteIndex > -1) {
+ var inLiteral = false;
+ format = format.split('');
+ for (var i = quoteIndex; i < format.length; i++) {
+ if (inLiteral) {
+ if (format[i] === '\'') {
+ if (i + 1 < format.length && format[i+1] === '\'') { // escaped single quote
+ format[i+1] = '$';
+ regex[i+1] = '';
+ } else { // end of literal
+ regex[i] = '';
+ inLiteral = false;
+ }
+ }
+ format[i] = '$';
+ } else {
+ if (format[i] === '\'') { // start of literal
+ format[i] = '$';
+ regex[i] = '';
+ inLiteral = true;
+ }
+ }
+ }
+
+ format = format.join('');
+ }
+
+ angular.forEach(formatCodeToRegex, function(data) {
+ var index = format.indexOf(data.key);
+
+ if (index > -1) {
+ format = format.split('');
+
+ regex[index] = '(' + data.regex + ')';
+ format[index] = '$'; // Custom symbol to define consumed part of format
+ for (var i = index + 1, n = index + data.key.length; i < n; i++) {
+ regex[i] = '';
+ format[i] = '$';
+ }
+ format = format.join('');
+
+ map.push({
+ index: index,
+ key: data.key,
+ apply: data.apply,
+ matcher: data.regex
+ });
+ }
+ });
+
+ return {
+ regex: new RegExp('^' + regex.join('') + '$'),
+ map: orderByFilter(map, 'index')
+ };
+ }
+
+ function createFormatter(format) {
+ var formatters = [];
+ var i = 0;
+ var formatter, literalIdx;
+ while (i < format.length) {
+ if (angular.isNumber(literalIdx)) {
+ if (format.charAt(i) === '\'') {
+ if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
+ formatters.push(constructLiteralFormatter(format, literalIdx, i));
+ literalIdx = null;
+ }
+ } else if (i === format.length) {
+ while (literalIdx < format.length) {
+ formatter = constructFormatterFromIdx(format, literalIdx);
+ formatters.push(formatter);
+ literalIdx = formatter.endIdx;
+ }
+ }
+
+ i++;
+ continue;
+ }
+
+ if (format.charAt(i) === '\'') {
+ literalIdx = i;
+ i++;
+ continue;
+ }
+
+ formatter = constructFormatterFromIdx(format, i);
+
+ formatters.push(formatter.parser);
+ i = formatter.endIdx;
+ }
+
+ return formatters;
+ }
+
+ function constructLiteralFormatter(format, literalIdx, endIdx) {
+ return function() {
+ return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
+ };
+ }
+
+ function constructFormatterFromIdx(format, i) {
+ var currentPosStr = format.substr(i);
+ for (var j = 0; j < formatCodeToRegex.length; j++) {
+ if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
+ var data = formatCodeToRegex[j];
+ return {
+ endIdx: i + data.key.length,
+ parser: data.formatter
+ };
+ }
+ }
+
+ return {
+ endIdx: i + 1,
+ parser: function() {
+ return currentPosStr.charAt(0);
+ }
+ };
+ }
+
+ this.filter = function(date, format) {
+ if (!angular.isDate(date) || isNaN(date) || !format) {
+ return '';
+ }
+
+ format = $locale.DATETIME_FORMATS[format] || format;
+
+ if ($locale.id !== localeId) {
+ this.init();
+ }
+
+ if (!this.formatters[format]) {
+ this.formatters[format] = createFormatter(format);
+ }
+
+ var formatters = this.formatters[format];
+
+ return formatters.reduce(function(str, formatter) {
+ return str + formatter(date);
+ }, '');
+ };
+
+ this.parse = function(input, format, baseDate) {
+ if (!angular.isString(input) || !format) {
+ return input;
+ }
+
+ format = $locale.DATETIME_FORMATS[format] || format;
+ format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');
+
+ if ($locale.id !== localeId) {
+ this.init();
+ }
+
+ if (!this.parsers[format]) {
+ this.parsers[format] = createParser(format, 'apply');
+ }
+
+ var parser = this.parsers[format],
+ regex = parser.regex,
+ map = parser.map,
+ results = input.match(regex),
+ tzOffset = false;
+ if (results && results.length) {
+ var fields, dt;
+ if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
+ fields = {
+ year: baseDate.getFullYear(),
+ month: baseDate.getMonth(),
+ date: baseDate.getDate(),
+ hours: baseDate.getHours(),
+ minutes: baseDate.getMinutes(),
+ seconds: baseDate.getSeconds(),
+ milliseconds: baseDate.getMilliseconds()
+ };
+ } else {
+ if (baseDate) {
+ $log.warn('dateparser:', 'baseDate is not a valid date');
+ }
+ fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
+ }
+
+ for (var i = 1, n = results.length; i < n; i++) {
+ var mapper = map[i - 1];
+ if (mapper.matcher === 'Z') {
+ tzOffset = true;
+ }
+
+ if (mapper.apply) {
+ mapper.apply.call(fields, results[i]);
+ }
+ }
+
+ var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
+ Date.prototype.setFullYear;
+ var timesetter = tzOffset ? Date.prototype.setUTCHours :
+ Date.prototype.setHours;
+
+ if (isValid(fields.year, fields.month, fields.date)) {
+ if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
+ dt = new Date(baseDate);
+ datesetter.call(dt, fields.year, fields.month, fields.date);
+ timesetter.call(dt, fields.hours, fields.minutes,
+ fields.seconds, fields.milliseconds);
+ } else {
+ dt = new Date(0);
+ datesetter.call(dt, fields.year, fields.month, fields.date);
+ timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
+ fields.seconds || 0, fields.milliseconds || 0);
+ }
+ }
+
+ return dt;
+ }
+ };
+
+ // Check if date is valid for specific month (and year for February).
+ // Month: 0 = Jan, 1 = Feb, etc
+ function isValid(year, month, date) {
+ if (date < 1) {
+ return false;
+ }
+
+ if (month === 1 && date > 28) {
+ return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
+ }
+
+ if (month === 3 || month === 5 || month === 8 || month === 10) {
+ return date < 31;
+ }
+
+ return true;
+ }
+
+ function toInt(str) {
+ return parseInt(str, 10);
+ }
+
+ this.toTimezone = toTimezone;
+ this.fromTimezone = fromTimezone;
+ this.timezoneToOffset = timezoneToOffset;
+ this.addDateMinutes = addDateMinutes;
+ this.convertTimezoneToLocal = convertTimezoneToLocal;
+
+ function toTimezone(date, timezone) {
+ return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
+ }
+
+ function fromTimezone(date, timezone) {
+ return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
+ }
+
+ //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
+ function timezoneToOffset(timezone, fallback) {
+ timezone = timezone.replace(/:/g, '');
+ var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
+ return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
+ }
+
+ function addDateMinutes(date, minutes) {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + minutes);
+ return date;
+ }
+
+ function convertTimezoneToLocal(date, timezone, reverse) {
+ reverse = reverse ? -1 : 1;
+ var dateTimezoneOffset = date.getTimezoneOffset();
+ var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
+ return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
+ }
+}]);
+
+// Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to
+// at most one element.
+angular.module('ui.bootstrap.isClass', [])
+.directive('uibIsClass', [
+ '$animate',
+function ($animate) {
+ // 11111111 22222222
+ var ON_REGEXP = /^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/;
+ // 11111111 22222222
+ var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;
+
+ var dataPerTracked = {};
+
+ return {
+ restrict: 'A',
+ compile: function(tElement, tAttrs) {
+ var linkedScopes = [];
+ var instances = [];
+ var expToData = {};
+ var lastActivated = null;
+ var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);
+ var onExp = onExpMatches[2];
+ var expsStr = onExpMatches[1];
+ var exps = expsStr.split(',');
+
+ return linkFn;
+
+ function linkFn(scope, element, attrs) {
+ linkedScopes.push(scope);
+ instances.push({
+ scope: scope,
+ element: element
+ });
+
+ exps.forEach(function(exp, k) {
+ addForExp(exp, scope);
+ });
+
+ scope.$on('$destroy', removeScope);
+ }
+
+ function addForExp(exp, scope) {
+ var matches = exp.match(IS_REGEXP);
+ var clazz = scope.$eval(matches[1]);
+ var compareWithExp = matches[2];
+ var data = expToData[exp];
+ if (!data) {
+ var watchFn = function(compareWithVal) {
+ var newActivated = null;
+ instances.some(function(instance) {
+ var thisVal = instance.scope.$eval(onExp);
+ if (thisVal === compareWithVal) {
+ newActivated = instance;
+ return true;
+ }
+ });
+ if (data.lastActivated !== newActivated) {
+ if (data.lastActivated) {
+ $animate.removeClass(data.lastActivated.element, clazz);
+ }
+ if (newActivated) {
+ $animate.addClass(newActivated.element, clazz);
+ }
+ data.lastActivated = newActivated;
+ }
+ };
+ expToData[exp] = data = {
+ lastActivated: null,
+ scope: scope,
+ watchFn: watchFn,
+ compareWithExp: compareWithExp,
+ watcher: scope.$watch(compareWithExp, watchFn)
+ };
+ }
+ data.watchFn(scope.$eval(compareWithExp));
+ }
+
+ function removeScope(e) {
+ var removedScope = e.targetScope;
+ var index = linkedScopes.indexOf(removedScope);
+ linkedScopes.splice(index, 1);
+ instances.splice(index, 1);
+ if (linkedScopes.length) {
+ var newWatchScope = linkedScopes[0];
+ angular.forEach(expToData, function(data) {
+ if (data.scope === removedScope) {
+ data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);
+ data.scope = newWatchScope;
+ }
+ });
+ } else {
+ expToData = {};
+ }
+ }
+ }
+ };
+}]);
+angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])
+
+.value('$datepickerSuppressError', false)
+
+.value('$datepickerLiteralWarning', true)
+
+.constant('uibDatepickerConfig', {
+ datepickerMode: 'day',
+ formatDay: 'dd',
+ formatMonth: 'MMMM',
+ formatYear: 'yyyy',
+ formatDayHeader: 'EEE',
+ formatDayTitle: 'MMMM yyyy',
+ formatMonthTitle: 'yyyy',
+ maxDate: null,
+ maxMode: 'year',
+ minDate: null,
+ minMode: 'day',
+ monthColumns: 3,
+ ngModelOptions: {},
+ shortcutPropagation: false,
+ showWeeks: true,
+ yearColumns: 5,
+ yearRows: 4
+})
+
+.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
+ function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
+ var self = this,
+ ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
+ ngModelOptions = {},
+ watchListeners = [];
+
+ $element.addClass('uib-datepicker');
+ $attrs.$set('role', 'application');
+
+ if (!$scope.datepickerOptions) {
+ $scope.datepickerOptions = {};
+ }
+
+ // Modes chain
+ this.modes = ['day', 'month', 'year'];
+
+ [
+ 'customClass',
+ 'dateDisabled',
+ 'datepickerMode',
+ 'formatDay',
+ 'formatDayHeader',
+ 'formatDayTitle',
+ 'formatMonth',
+ 'formatMonthTitle',
+ 'formatYear',
+ 'maxDate',
+ 'maxMode',
+ 'minDate',
+ 'minMode',
+ 'monthColumns',
+ 'showWeeks',
+ 'shortcutPropagation',
+ 'startingDay',
+ 'yearColumns',
+ 'yearRows'
+ ].forEach(function(key) {
+ switch (key) {
+ case 'customClass':
+ case 'dateDisabled':
+ $scope[key] = $scope.datepickerOptions[key] || angular.noop;
+ break;
+ case 'datepickerMode':
+ $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
+ $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
+ break;
+ case 'formatDay':
+ case 'formatDayHeader':
+ case 'formatDayTitle':
+ case 'formatMonth':
+ case 'formatMonthTitle':
+ case 'formatYear':
+ self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
+ $interpolate($scope.datepickerOptions[key])($scope.$parent) :
+ datepickerConfig[key];
+ break;
+ case 'monthColumns':
+ case 'showWeeks':
+ case 'shortcutPropagation':
+ case 'yearColumns':
+ case 'yearRows':
+ self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
+ $scope.datepickerOptions[key] : datepickerConfig[key];
+ break;
+ case 'startingDay':
+ if (angular.isDefined($scope.datepickerOptions.startingDay)) {
+ self.startingDay = $scope.datepickerOptions.startingDay;
+ } else if (angular.isNumber(datepickerConfig.startingDay)) {
+ self.startingDay = datepickerConfig.startingDay;
+ } else {
+ self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
+ }
+
+ break;
+ case 'maxDate':
+ case 'minDate':
+ $scope.$watch('datepickerOptions.' + key, function(value) {
+ if (value) {
+ if (angular.isDate(value)) {
+ self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone'));
+ } else {
+ if ($datepickerLiteralWarning) {
+ $log.warn('Literal date support has been deprecated, please switch to date object usage');
+ }
+
+ self[key] = new Date(dateFilter(value, 'medium'));
+ }
+ } else {
+ self[key] = datepickerConfig[key] ?
+ dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) :
+ null;
+ }
+
+ self.refreshView();
+ });
+
+ break;
+ case 'maxMode':
+ case 'minMode':
+ if ($scope.datepickerOptions[key]) {
+ $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
+ self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
+ if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
+ key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
+ $scope.datepickerMode = self[key];
+ $scope.datepickerOptions.datepickerMode = self[key];
+ }
+ });
+ } else {
+ self[key] = $scope[key] = datepickerConfig[key] || null;
+ }
+
+ break;
+ }
+ });
+
+ $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
+
+ $scope.disabled = angular.isDefined($attrs.disabled) || false;
+ if (angular.isDefined($attrs.ngDisabled)) {
+ watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
+ $scope.disabled = disabled;
+ self.refreshView();
+ }));
+ }
+
+ $scope.isActive = function(dateObject) {
+ if (self.compare(dateObject.date, self.activeDate) === 0) {
+ $scope.activeDateId = dateObject.uid;
+ return true;
+ }
+ return false;
+ };
+
+ this.init = function(ngModelCtrl_) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelOptions = extractOptions(ngModelCtrl);
+
+ if ($scope.datepickerOptions.initDate) {
+ self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date();
+ $scope.$watch('datepickerOptions.initDate', function(initDate) {
+ if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
+ self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone'));
+ self.refreshView();
+ }
+ });
+ } else {
+ self.activeDate = new Date();
+ }
+
+ var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
+ this.activeDate = !isNaN(date) ?
+ dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) :
+ dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
+
+ ngModelCtrl.$render = function() {
+ self.render();
+ };
+ };
+
+ this.render = function() {
+ if (ngModelCtrl.$viewValue) {
+ var date = new Date(ngModelCtrl.$viewValue),
+ isValid = !isNaN(date);
+
+ if (isValid) {
+ this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
+ } else if (!$datepickerSuppressError) {
+ $log.error('Datepicker directive: "ng-model" value must be a Date object');
+ }
+ }
+ this.refreshView();
+ };
+
+ this.refreshView = function() {
+ if (this.element) {
+ $scope.selectedDt = null;
+ this._refreshView();
+ if ($scope.activeDt) {
+ $scope.activeDateId = $scope.activeDt.uid;
+ }
+
+ var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
+ date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
+ ngModelCtrl.$setValidity('dateDisabled', !date ||
+ this.element && !this.isDisabled(date));
+ }
+ };
+
+ this.createDateObject = function(date, format) {
+ var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
+ model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone'));
+ var today = new Date();
+ today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
+ var time = this.compare(date, today);
+ var dt = {
+ date: date,
+ label: dateParser.filter(date, format),
+ selected: model && this.compare(date, model) === 0,
+ disabled: this.isDisabled(date),
+ past: time < 0,
+ current: time === 0,
+ future: time > 0,
+ customClass: this.customClass(date) || null
+ };
+
+ if (model && this.compare(date, model) === 0) {
+ $scope.selectedDt = dt;
+ }
+
+ if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
+ $scope.activeDt = dt;
+ }
+
+ return dt;
+ };
+
+ this.isDisabled = function(date) {
+ return $scope.disabled ||
+ this.minDate && this.compare(date, this.minDate) < 0 ||
+ this.maxDate && this.compare(date, this.maxDate) > 0 ||
+ $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});
+ };
+
+ this.customClass = function(date) {
+ return $scope.customClass({date: date, mode: $scope.datepickerMode});
+ };
+
+ // Split array into smaller arrays
+ this.split = function(arr, size) {
+ var arrays = [];
+ while (arr.length > 0) {
+ arrays.push(arr.splice(0, size));
+ }
+ return arrays;
+ };
+
+ $scope.select = function(date) {
+ if ($scope.datepickerMode === self.minMode) {
+ var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);
+ dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+ dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));
+ ngModelCtrl.$setViewValue(dt);
+ ngModelCtrl.$render();
+ } else {
+ self.activeDate = date;
+ setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
+
+ $scope.$emit('uib:datepicker.mode');
+ }
+
+ $scope.$broadcast('uib:datepicker.focus');
+ };
+
+ $scope.move = function(direction) {
+ var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
+ month = self.activeDate.getMonth() + direction * (self.step.months || 0);
+ self.activeDate.setFullYear(year, month, 1);
+ self.refreshView();
+ };
+
+ $scope.toggleMode = function(direction) {
+ direction = direction || 1;
+
+ if ($scope.datepickerMode === self.maxMode && direction === 1 ||
+ $scope.datepickerMode === self.minMode && direction === -1) {
+ return;
+ }
+
+ setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);
+
+ $scope.$emit('uib:datepicker.mode');
+ };
+
+ // Key event mapper
+ $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };
+
+ var focusElement = function() {
+ self.element[0].focus();
+ };
+
+ // Listen for focus requests from popup directive
+ $scope.$on('uib:datepicker.focus', focusElement);
+
+ $scope.keydown = function(evt) {
+ var key = $scope.keys[evt.which];
+
+ if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
+ return;
+ }
+
+ evt.preventDefault();
+ if (!self.shortcutPropagation) {
+ evt.stopPropagation();
+ }
+
+ if (key === 'enter' || key === 'space') {
+ if (self.isDisabled(self.activeDate)) {
+ return; // do nothing
+ }
+ $scope.select(self.activeDate);
+ } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
+ $scope.toggleMode(key === 'up' ? 1 : -1);
+ } else {
+ self.handleKeyDown(key, evt);
+ self.refreshView();
+ }
+ };
+
+ $element.on('keydown', function(evt) {
+ $scope.$apply(function() {
+ $scope.keydown(evt);
+ });
+ });
+
+ $scope.$on('$destroy', function() {
+ //Clear all watch listeners on destroy
+ while (watchListeners.length) {
+ watchListeners.shift()();
+ }
+ });
+
+ function setMode(mode) {
+ $scope.datepickerMode = mode;
+ $scope.datepickerOptions.datepickerMode = mode;
+ }
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = ngModelCtrl.$options ||
+ $scope.datepickerOptions.ngModelOptions ||
+ datepickerConfig.ngModelOptions ||
+ {};
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ // ng-model-options defaults timezone to null; don't let its precedence squash a non-null value
+ var timezone = ngModelCtrl.$options.getOption('timezone') ||
+ ($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) ||
+ (datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null);
+
+ // values passed to createChild override existing values
+ ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance
+ .createChild(datepickerConfig.ngModelOptions) // lowest precedence
+ .createChild($scope.datepickerOptions.ngModelOptions)
+ .createChild(ngModelCtrl.$options) // highest precedence
+ .createChild({timezone: timezone}); // to keep from squashing a non-null value
+ }
+
+ return ngModelOptions;
+ }
+}])
+
+.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+ this.step = { months: 1 };
+ this.element = $element;
+ function getDaysInMonth(year, month) {
+ return month === 1 && year % 4 === 0 &&
+ (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
+ }
+
+ this.init = function(ctrl) {
+ angular.extend(ctrl, this);
+ scope.showWeeks = ctrl.showWeeks;
+ ctrl.refreshView();
+ };
+
+ this.getDates = function(startDate, n) {
+ var dates = new Array(n), current = new Date(startDate), i = 0, date;
+ while (i < n) {
+ date = new Date(current);
+ dates[i++] = date;
+ current.setDate(current.getDate() + 1);
+ }
+ return dates;
+ };
+
+ this._refreshView = function() {
+ var year = this.activeDate.getFullYear(),
+ month = this.activeDate.getMonth(),
+ firstDayOfMonth = new Date(this.activeDate);
+
+ firstDayOfMonth.setFullYear(year, month, 1);
+
+ var difference = this.startingDay - firstDayOfMonth.getDay(),
+ numDisplayedFromPreviousMonth = difference > 0 ?
+ 7 - difference : - difference,
+ firstDate = new Date(firstDayOfMonth);
+
+ if (numDisplayedFromPreviousMonth > 0) {
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
+ }
+
+ // 42 is the number of days on a six-week calendar
+ var days = this.getDates(firstDate, 42);
+ for (var i = 0; i < 42; i ++) {
+ days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
+ secondary: days[i].getMonth() !== month,
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.labels = new Array(7);
+ for (var j = 0; j < 7; j++) {
+ scope.labels[j] = {
+ abbr: dateFilter(days[j].date, this.formatDayHeader),
+ full: dateFilter(days[j].date, 'EEEE')
+ };
+ }
+
+ scope.title = dateFilter(this.activeDate, this.formatDayTitle);
+ scope.rows = this.split(days, 7);
+
+ if (scope.showWeeks) {
+ scope.weekNumbers = [];
+ var thursdayIndex = (4 + 7 - this.startingDay) % 7,
+ numWeeks = scope.rows.length;
+ for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
+ scope.weekNumbers.push(
+ getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
+ }
+ }
+ };
+
+ this.compare = function(date1, date2) {
+ var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
+ var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
+ _date1.setFullYear(date1.getFullYear());
+ _date2.setFullYear(date2.getFullYear());
+ return _date1 - _date2;
+ };
+
+ function getISO8601WeekNumber(date) {
+ var checkDate = new Date(date);
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
+ var time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+ }
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getDate();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - 7;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + 7;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);
+ this.activeDate.setMonth(month, 1);
+ date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
+ } else if (key === 'home') {
+ date = 1;
+ } else if (key === 'end') {
+ date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
+ }
+ this.activeDate.setDate(date);
+ };
+}])
+
+.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ this.step = { years: 1 };
+ this.element = $element;
+
+ this.init = function(ctrl) {
+ angular.extend(ctrl, this);
+ ctrl.refreshView();
+ };
+
+ this._refreshView = function() {
+ var months = new Array(12),
+ year = this.activeDate.getFullYear(),
+ date;
+
+ for (var i = 0; i < 12; i++) {
+ date = new Date(this.activeDate);
+ date.setFullYear(year, i, 1);
+ months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
+ scope.rows = this.split(months, this.monthColumns);
+ scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
+ };
+
+ this.compare = function(date1, date2) {
+ var _date1 = new Date(date1.getFullYear(), date1.getMonth());
+ var _date2 = new Date(date2.getFullYear(), date2.getMonth());
+ _date1.setFullYear(date1.getFullYear());
+ _date2.setFullYear(date2.getFullYear());
+ return _date1 - _date2;
+ };
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getMonth();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - this.monthColumns;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + this.monthColumns;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
+ this.activeDate.setFullYear(year);
+ } else if (key === 'home') {
+ date = 0;
+ } else if (key === 'end') {
+ date = 11;
+ }
+ this.activeDate.setMonth(date);
+ };
+}])
+
+.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ var columns, range;
+ this.element = $element;
+
+ function getStartingYear(year) {
+ return parseInt((year - 1) / range, 10) * range + 1;
+ }
+
+ this.yearpickerInit = function() {
+ columns = this.yearColumns;
+ range = this.yearRows * columns;
+ this.step = { years: range };
+ };
+
+ this._refreshView = function() {
+ var years = new Array(range), date;
+
+ for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {
+ date = new Date(this.activeDate);
+ date.setFullYear(start + i, 0, 1);
+ years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.title = [years[0].label, years[range - 1].label].join(' - ');
+ scope.rows = this.split(years, columns);
+ scope.columns = columns;
+ };
+
+ this.compare = function(date1, date2) {
+ return date1.getFullYear() - date2.getFullYear();
+ };
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getFullYear();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - columns;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + columns;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ date += (key === 'pageup' ? - 1 : 1) * range;
+ } else if (key === 'home') {
+ date = getStartingYear(this.activeDate.getFullYear());
+ } else if (key === 'end') {
+ date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
+ }
+ this.activeDate.setFullYear(date);
+ };
+}])
+
+.directive('uibDatepicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
+ },
+ scope: {
+ datepickerOptions: '=?'
+ },
+ require: ['uibDatepicker', '^ngModel'],
+ restrict: 'A',
+ controller: 'UibDatepickerController',
+ controllerAs: 'datepicker',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ datepickerCtrl.init(ngModelCtrl);
+ }
+ };
+})
+
+.directive('uibDaypicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/day.html';
+ },
+ require: ['^uibDatepicker', 'uibDaypicker'],
+ restrict: 'A',
+ controller: 'UibDaypickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0],
+ daypickerCtrl = ctrls[1];
+
+ daypickerCtrl.init(datepickerCtrl);
+ }
+ };
+})
+
+.directive('uibMonthpicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/month.html';
+ },
+ require: ['^uibDatepicker', 'uibMonthpicker'],
+ restrict: 'A',
+ controller: 'UibMonthpickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0],
+ monthpickerCtrl = ctrls[1];
+
+ monthpickerCtrl.init(datepickerCtrl);
+ }
+ };
+})
+
+.directive('uibYearpicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/year.html';
+ },
+ require: ['^uibDatepicker', 'uibYearpicker'],
+ restrict: 'A',
+ controller: 'UibYearpickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var ctrl = ctrls[0];
+ angular.extend(ctrl, ctrls[1]);
+ ctrl.yearpickerInit();
+
+ ctrl.refreshView();
+ }
+ };
+});
+
+angular.module('ui.bootstrap.position', [])
+
+/**
+ * A set of utility methods for working with the DOM.
+ * It is meant to be used where we need to absolute-position elements in
+ * relation to another element (this is the case for tooltips, popovers,
+ * typeahead suggestions etc.).
+ */
+ .factory('$uibPosition', ['$document', '$window', function($document, $window) {
+ /**
+ * Used by scrollbarWidth() function to cache scrollbar's width.
+ * Do not access this variable directly, use scrollbarWidth() instead.
+ */
+ var SCROLLBAR_WIDTH;
+ /**
+ * scrollbar on body and html element in IE and Edge overlay
+ * content and should be considered 0 width.
+ */
+ var BODY_SCROLLBAR_WIDTH;
+ var OVERFLOW_REGEX = {
+ normal: /(auto|scroll)/,
+ hidden: /(auto|scroll|hidden)/
+ };
+ var PLACEMENT_REGEX = {
+ auto: /\s?auto?\s?/i,
+ primary: /^(top|bottom|left|right)$/,
+ secondary: /^(top|bottom|left|right|center)$/,
+ vertical: /^(top|bottom)$/
+ };
+ var BODY_REGEX = /(HTML|BODY)/;
+
+ return {
+
+ /**
+ * Provides a raw DOM element from a jQuery/jQLite element.
+ *
+ * @param {element} elem - The element to convert.
+ *
+ * @returns {element} A HTML element.
+ */
+ getRawNode: function(elem) {
+ return elem.nodeName ? elem : elem[0] || elem;
+ },
+
+ /**
+ * Provides a parsed number for a style property. Strips
+ * units and casts invalid numbers to 0.
+ *
+ * @param {string} value - The style value to parse.
+ *
+ * @returns {number} A valid number.
+ */
+ parseStyle: function(value) {
+ value = parseFloat(value);
+ return isFinite(value) ? value : 0;
+ },
+
+ /**
+ * Provides the closest positioned ancestor.
+ *
+ * @param {element} element - The element to get the offest parent for.
+ *
+ * @returns {element} The closest positioned ancestor.
+ */
+ offsetParent: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var offsetParent = elem.offsetParent || $document[0].documentElement;
+
+ function isStaticPositioned(el) {
+ return ($window.getComputedStyle(el).position || 'static') === 'static';
+ }
+
+ while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || $document[0].documentElement;
+ },
+
+ /**
+ * Provides the scrollbar width, concept from TWBS measureScrollbar()
+ * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
+ * In IE and Edge, scollbar on body and html element overlay and should
+ * return a width of 0.
+ *
+ * @returns {number} The width of the browser scollbar.
+ */
+ scrollbarWidth: function(isBody) {
+ if (isBody) {
+ if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
+ var bodyElem = $document.find('body');
+ bodyElem.addClass('uib-position-body-scrollbar-measure');
+ BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
+ BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
+ bodyElem.removeClass('uib-position-body-scrollbar-measure');
+ }
+ return BODY_SCROLLBAR_WIDTH;
+ }
+
+ if (angular.isUndefined(SCROLLBAR_WIDTH)) {
+ var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
+ $document.find('body').append(scrollElem);
+ SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
+ SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
+ scrollElem.remove();
+ }
+
+ return SCROLLBAR_WIDTH;
+ },
+
+ /**
+ * Provides the padding required on an element to replace the scrollbar.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**scrollbarWidth**: the width of the scrollbar</li>
+ * <li>**widthOverflow**: whether the the width is overflowing</li>
+ * <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
+ * <li>**rightOriginal**: the amount of right padding currently on the element</li>
+ * <li>**heightOverflow**: whether the the height is overflowing</li>
+ * <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
+ * <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
+ * </ul>
+ */
+ scrollbarPadding: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemStyle = $window.getComputedStyle(elem);
+ var paddingRight = this.parseStyle(elemStyle.paddingRight);
+ var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
+ var scrollParent = this.scrollParent(elem, false, true);
+ var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));
+
+ return {
+ scrollbarWidth: scrollbarWidth,
+ widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
+ right: paddingRight + scrollbarWidth,
+ originalRight: paddingRight,
+ heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
+ bottom: paddingBottom + scrollbarWidth,
+ originalBottom: paddingBottom
+ };
+ },
+
+ /**
+ * Checks to see if the element is scrollable.
+ *
+ * @param {element} elem - The element to check.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ *
+ * @returns {boolean} Whether the element is scrollable.
+ */
+ isScrollable: function(elem, includeHidden) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var elemStyle = $window.getComputedStyle(elem);
+ return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
+ },
+
+ /**
+ * Provides the closest scrollable ancestor.
+ * A port of the jQuery UI scrollParent method:
+ * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
+ *
+ * @param {element} elem - The element to find the scroll parent of.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ * @param {boolean=} [includeSelf=false] - Should the element being passed be
+ * included in the scrollable llokup.
+ *
+ * @returns {element} A HTML element.
+ */
+ scrollParent: function(elem, includeHidden, includeSelf) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var documentEl = $document[0].documentElement;
+ var elemStyle = $window.getComputedStyle(elem);
+ if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
+ return elem;
+ }
+ var excludeStatic = elemStyle.position === 'absolute';
+ var scrollParent = elem.parentElement || documentEl;
+
+ if (scrollParent === documentEl || elemStyle.position === 'fixed') {
+ return documentEl;
+ }
+
+ while (scrollParent.parentElement && scrollParent !== documentEl) {
+ var spStyle = $window.getComputedStyle(scrollParent);
+ if (excludeStatic && spStyle.position !== 'static') {
+ excludeStatic = false;
+ }
+
+ if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
+ break;
+ }
+ scrollParent = scrollParent.parentElement;
+ }
+
+ return scrollParent;
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's position function:
+ * http://api.jquery.com/position/ - distance to closest positioned
+ * ancestor. Does not account for margins by default like jQuery position.
+ *
+ * @param {element} elem - The element to caclulate the position on.
+ * @param {boolean=} [includeMargins=false] - Should margins be accounted
+ * for, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**width**: the width of the element</li>
+ * <li>**height**: the height of the element</li>
+ * <li>**top**: distance to top edge of offset parent</li>
+ * <li>**left**: distance to left edge of offset parent</li>
+ * </ul>
+ */
+ position: function(elem, includeMagins) {
+ elem = this.getRawNode(elem);
+
+ var elemOffset = this.offset(elem);
+ if (includeMagins) {
+ var elemStyle = $window.getComputedStyle(elem);
+ elemOffset.top -= this.parseStyle(elemStyle.marginTop);
+ elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
+ }
+ var parent = this.offsetParent(elem);
+ var parentOffset = {top: 0, left: 0};
+
+ if (parent !== $document[0].documentElement) {
+ parentOffset = this.offset(parent);
+ parentOffset.top += parent.clientTop - parent.scrollTop;
+ parentOffset.left += parent.clientLeft - parent.scrollLeft;
+ }
+
+ return {
+ width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
+ top: Math.round(elemOffset.top - parentOffset.top),
+ left: Math.round(elemOffset.left - parentOffset.left)
+ };
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's offset function:
+ * http://api.jquery.com/offset/ - distance to viewport. Does
+ * not account for borders, margins, or padding on the body
+ * element.
+ *
+ * @param {element} elem - The element to calculate the offset on.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**width**: the width of the element</li>
+ * <li>**height**: the height of the element</li>
+ * <li>**top**: distance to top edge of viewport</li>
+ * <li>**right**: distance to bottom edge of viewport</li>
+ * </ul>
+ */
+ offset: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemBCR = elem.getBoundingClientRect();
+ return {
+ width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
+ top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
+ left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
+ };
+ },
+
+ /**
+ * Provides offset distance to the closest scrollable ancestor
+ * or viewport. Accounts for border and scrollbar width.
+ *
+ * Right and bottom dimensions represent the distance to the
+ * respective edge of the viewport element. If the element
+ * edge extends beyond the viewport, a negative value will be
+ * reported.
+ *
+ * @param {element} elem - The element to get the viewport offset for.
+ * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
+ * of the first scrollable element, default is false.
+ * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
+ * be accounted for, default is true.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**top**: distance to the top content edge of viewport element</li>
+ * <li>**bottom**: distance to the bottom content edge of viewport element</li>
+ * <li>**left**: distance to the left content edge of viewport element</li>
+ * <li>**right**: distance to the right content edge of viewport element</li>
+ * </ul>
+ */
+ viewportOffset: function(elem, useDocument, includePadding) {
+ elem = this.getRawNode(elem);
+ includePadding = includePadding !== false ? true : false;
+
+ var elemBCR = elem.getBoundingClientRect();
+ var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
+
+ var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
+ var offsetParentBCR = offsetParent.getBoundingClientRect();
+
+ offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
+ offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
+ if (offsetParent === $document[0].documentElement) {
+ offsetBCR.top += $window.pageYOffset;
+ offsetBCR.left += $window.pageXOffset;
+ }
+ offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
+ offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
+
+ if (includePadding) {
+ var offsetParentStyle = $window.getComputedStyle(offsetParent);
+ offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
+ offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
+ offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
+ offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
+ }
+
+ return {
+ top: Math.round(elemBCR.top - offsetBCR.top),
+ bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
+ left: Math.round(elemBCR.left - offsetBCR.left),
+ right: Math.round(offsetBCR.right - elemBCR.right)
+ };
+ },
+
+ /**
+ * Provides an array of placement values parsed from a placement string.
+ * Along with the 'auto' indicator, supported placement strings are:
+ * <ul>
+ * <li>top: element on top, horizontally centered on host element.</li>
+ * <li>top-left: element on top, left edge aligned with host element left edge.</li>
+ * <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
+ * <li>bottom: element on bottom, horizontally centered on host element.</li>
+ * <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
+ * <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
+ * <li>left: element on left, vertically centered on host element.</li>
+ * <li>left-top: element on left, top edge aligned with host element top edge.</li>
+ * <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
+ * <li>right: element on right, vertically centered on host element.</li>
+ * <li>right-top: element on right, top edge aligned with host element top edge.</li>
+ * <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
+ * </ul>
+ * A placement string with an 'auto' indicator is expected to be
+ * space separated from the placement, i.e: 'auto bottom-left' If
+ * the primary and secondary placement values do not match 'top,
+ * bottom, left, right' then 'top' will be the primary placement and
+ * 'center' will be the secondary placement. If 'auto' is passed, true
+ * will be returned as the 3rd value of the array.
+ *
+ * @param {string} placement - The placement string to parse.
+ *
+ * @returns {array} An array with the following values
+ * <ul>
+ * <li>**[0]**: The primary placement.</li>
+ * <li>**[1]**: The secondary placement.</li>
+ * <li>**[2]**: If auto is passed: true, else undefined.</li>
+ * </ul>
+ */
+ parsePlacement: function(placement) {
+ var autoPlace = PLACEMENT_REGEX.auto.test(placement);
+ if (autoPlace) {
+ placement = placement.replace(PLACEMENT_REGEX.auto, '');
+ }
+
+ placement = placement.split('-');
+
+ placement[0] = placement[0] || 'top';
+ if (!PLACEMENT_REGEX.primary.test(placement[0])) {
+ placement[0] = 'top';
+ }
+
+ placement[1] = placement[1] || 'center';
+ if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
+ placement[1] = 'center';
+ }
+
+ if (autoPlace) {
+ placement[2] = true;
+ } else {
+ placement[2] = false;
+ }
+
+ return placement;
+ },
+
+ /**
+ * Provides coordinates for an element to be positioned relative to
+ * another element. Passing 'auto' as part of the placement parameter
+ * will enable smart placement - where the element fits. i.e:
+ * 'auto left-top' will check to see if there is enough space to the left
+ * of the hostElem to fit the targetElem, if not place right (same for secondary
+ * top placement). Available space is calculated using the viewportOffset
+ * function.
+ *
+ * @param {element} hostElem - The element to position against.
+ * @param {element} targetElem - The element to position.
+ * @param {string=} [placement=top] - The placement for the targetElem,
+ * default is 'top'. 'center' is assumed as secondary placement for
+ * 'top', 'left', 'right', and 'bottom' placements. Available placements are:
+ * <ul>
+ * <li>top</li>
+ * <li>top-right</li>
+ * <li>top-left</li>
+ * <li>bottom</li>
+ * <li>bottom-left</li>
+ * <li>bottom-right</li>
+ * <li>left</li>
+ * <li>left-top</li>
+ * <li>left-bottom</li>
+ * <li>right</li>
+ * <li>right-top</li>
+ * <li>right-bottom</li>
+ * </ul>
+ * @param {boolean=} [appendToBody=false] - Should the top and left values returned
+ * be calculated from the body element, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**top**: Value for targetElem top.</li>
+ * <li>**left**: Value for targetElem left.</li>
+ * <li>**placement**: The resolved placement.</li>
+ * </ul>
+ */
+ positionElements: function(hostElem, targetElem, placement, appendToBody) {
+ hostElem = this.getRawNode(hostElem);
+ targetElem = this.getRawNode(targetElem);
+
+ // need to read from prop to support tests.
+ var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
+ var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
+
+ placement = this.parsePlacement(placement);
+
+ var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
+ var targetElemPos = {top: 0, left: 0, placement: ''};
+
+ if (placement[2]) {
+ var viewportOffset = this.viewportOffset(hostElem, appendToBody);
+
+ var targetElemStyle = $window.getComputedStyle(targetElem);
+ var adjustedSize = {
+ width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
+ height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
+ };
+
+ placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
+ placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
+ placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
+ placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
+ placement[0];
+
+ placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
+ placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
+ placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
+ placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
+ placement[1];
+
+ if (placement[1] === 'center') {
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
+ if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
+ placement[1] = 'left';
+ } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
+ placement[1] = 'right';
+ }
+ } else {
+ var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
+ if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
+ placement[1] = 'top';
+ } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
+ placement[1] = 'bottom';
+ }
+ }
+ }
+ }
+
+ switch (placement[0]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top - targetHeight;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left - targetWidth;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width;
+ break;
+ }
+
+ switch (placement[1]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
+ break;
+ case 'center':
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
+ } else {
+ targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
+ }
+ break;
+ }
+
+ targetElemPos.top = Math.round(targetElemPos.top);
+ targetElemPos.left = Math.round(targetElemPos.left);
+ targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
+
+ return targetElemPos;
+ },
+
+ /**
+ * Provides a way to adjust the top positioning after first
+ * render to correctly align element to top after content
+ * rendering causes resized element height
+ *
+ * @param {array} placementClasses - The array of strings of classes
+ * element should have.
+ * @param {object} containerPosition - The object with container
+ * position information
+ * @param {number} initialHeight - The initial height for the elem.
+ * @param {number} currentHeight - The current height for the elem.
+ */
+ adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) {
+ if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {
+ return {
+ top: containerPosition.top - currentHeight + 'px'
+ };
+ }
+ },
+
+ /**
+ * Provides a way for positioning tooltip & dropdown
+ * arrows when using placement options beyond the standard
+ * left, right, top, or bottom.
+ *
+ * @param {element} elem - The tooltip/dropdown element.
+ * @param {string} placement - The placement for the elem.
+ */
+ positionArrow: function(elem, placement) {
+ elem = this.getRawNode(elem);
+
+ var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
+ if (!innerElem) {
+ return;
+ }
+
+ var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
+
+ var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
+ if (!arrowElem) {
+ return;
+ }
+
+ var arrowCss = {
+ top: '',
+ bottom: '',
+ left: '',
+ right: ''
+ };
+
+ placement = this.parsePlacement(placement);
+ if (placement[1] === 'center') {
+ // no adjustment necessary - just reset styles
+ angular.element(arrowElem).css(arrowCss);
+ return;
+ }
+
+ var borderProp = 'border-' + placement[0] + '-width';
+ var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
+
+ var borderRadiusProp = 'border-';
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ borderRadiusProp += placement[0] + '-' + placement[1];
+ } else {
+ borderRadiusProp += placement[1] + '-' + placement[0];
+ }
+ borderRadiusProp += '-radius';
+ var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
+
+ switch (placement[0]) {
+ case 'top':
+ arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'bottom':
+ arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'left':
+ arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'right':
+ arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ }
+
+ arrowCss[placement[1]] = borderRadius;
+
+ angular.element(arrowElem).css(arrowCss);
+ }
+ };
+ }]);
+
+angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])
+
+.value('$datepickerPopupLiteralWarning', true)
+
+.constant('uibDatepickerPopupConfig', {
+ altInputFormats: [],
+ appendToBody: false,
+ clearText: 'Clear',
+ closeOnDateSelection: true,
+ closeText: 'Done',
+ currentText: 'Today',
+ datepickerPopup: 'yyyy-MM-dd',
+ datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
+ datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
+ html5Types: {
+ date: 'yyyy-MM-dd',
+ 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
+ 'month': 'yyyy-MM'
+ },
+ onOpenFocus: true,
+ showButtonBar: true,
+ placement: 'auto bottom-left'
+})
+
+.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
+function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
+ var cache = {},
+ isHtml5DateInput = false;
+ var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
+ datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
+ ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];
+
+ this.init = function(_ngModel_) {
+ ngModel = _ngModel_;
+ ngModelOptions = extractOptions(ngModel);
+ closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
+ $scope.$parent.$eval($attrs.closeOnDateSelection) :
+ datepickerPopupConfig.closeOnDateSelection;
+ appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
+ $scope.$parent.$eval($attrs.datepickerAppendToBody) :
+ datepickerPopupConfig.appendToBody;
+ onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
+ $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
+ datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
+ $attrs.datepickerPopupTemplateUrl :
+ datepickerPopupConfig.datepickerPopupTemplateUrl;
+ datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
+ $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
+ altInputFormats = angular.isDefined($attrs.altInputFormats) ?
+ $scope.$parent.$eval($attrs.altInputFormats) :
+ datepickerPopupConfig.altInputFormats;
+
+ $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
+ $scope.$parent.$eval($attrs.showButtonBar) :
+ datepickerPopupConfig.showButtonBar;
+
+ if (datepickerPopupConfig.html5Types[$attrs.type]) {
+ dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
+ isHtml5DateInput = true;
+ } else {
+ dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
+ $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
+ var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
+ // Invalidate the $modelValue to ensure that formatters re-run
+ // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
+ if (newDateFormat !== dateFormat) {
+ dateFormat = newDateFormat;
+ ngModel.$modelValue = null;
+
+ if (!dateFormat) {
+ throw new Error('uibDatepickerPopup must have a date format specified.');
+ }
+ }
+ });
+ }
+
+ if (!dateFormat) {
+ throw new Error('uibDatepickerPopup must have a date format specified.');
+ }
+
+ if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
+ throw new Error('HTML5 date input types do not support custom formats.');
+ }
+
+ // popup element used to display calendar
+ popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
+
+ popupEl.attr({
+ 'ng-model': 'date',
+ 'ng-change': 'dateSelection(date)',
+ 'template-url': datepickerPopupTemplateUrl
+ });
+
+ // datepicker element
+ datepickerEl = angular.element(popupEl.children()[0]);
+ datepickerEl.attr('template-url', datepickerTemplateUrl);
+
+ if (!$scope.datepickerOptions) {
+ $scope.datepickerOptions = {};
+ }
+
+ if (isHtml5DateInput) {
+ if ($attrs.type === 'month') {
+ $scope.datepickerOptions.datepickerMode = 'month';
+ $scope.datepickerOptions.minMode = 'month';
+ }
+ }
+
+ datepickerEl.attr('datepicker-options', 'datepickerOptions');
+
+ if (!isHtml5DateInput) {
+ // Internal API to maintain the correct ng-invalid-[key] class
+ ngModel.$$parserName = 'date';
+ ngModel.$validators.date = validator;
+ ngModel.$parsers.unshift(parseDate);
+ ngModel.$formatters.push(function(value) {
+ if (ngModel.$isEmpty(value)) {
+ $scope.date = value;
+ return value;
+ }
+
+ if (angular.isNumber(value)) {
+ value = new Date(value);
+ }
+
+ $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
+
+ return dateParser.filter($scope.date, dateFormat);
+ });
+ } else {
+ ngModel.$formatters.push(function(value) {
+ $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
+ return value;
+ });
+ }
+
+ // Detect changes in the view from the text box
+ ngModel.$viewChangeListeners.push(function() {
+ $scope.date = parseDateString(ngModel.$viewValue);
+ });
+
+ $element.on('keydown', inputKeydownBind);
+
+ $popup = $compile(popupEl)($scope);
+ // Prevent jQuery cache memory leak (template is now redundant after linking)
+ popupEl.remove();
+
+ if (appendToBody) {
+ $document.find('body').append($popup);
+ } else {
+ $element.after($popup);
+ }
+
+ $scope.$on('$destroy', function() {
+ if ($scope.isOpen === true) {
+ if (!$rootScope.$$phase) {
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ }
+ }
+
+ $popup.remove();
+ $element.off('keydown', inputKeydownBind);
+ $document.off('click', documentClickBind);
+ if (scrollParentEl) {
+ scrollParentEl.off('scroll', positionPopup);
+ }
+ angular.element($window).off('resize', positionPopup);
+
+ //Clear all watch listeners on destroy
+ while (watchListeners.length) {
+ watchListeners.shift()();
+ }
+ });
+ };
+
+ $scope.getText = function(key) {
+ return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
+ };
+
+ $scope.isDisabled = function(date) {
+ if (date === 'today') {
+ date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
+ }
+
+ var dates = {};
+ angular.forEach(['minDate', 'maxDate'], function(key) {
+ if (!$scope.datepickerOptions[key]) {
+ dates[key] = null;
+ } else if (angular.isDate($scope.datepickerOptions[key])) {
+ dates[key] = new Date($scope.datepickerOptions[key]);
+ } else {
+ if ($datepickerPopupLiteralWarning) {
+ $log.warn('Literal date support has been deprecated, please switch to date object usage');
+ }
+
+ dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
+ }
+ });
+
+ return $scope.datepickerOptions &&
+ dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
+ dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
+ };
+
+ $scope.compare = function(date1, date2) {
+ return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
+ };
+
+ // Inner change
+ $scope.dateSelection = function(dt) {
+ $scope.date = dt;
+ var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
+ $element.val(date);
+ ngModel.$setViewValue(date);
+
+ if (closeOnDateSelection) {
+ $scope.isOpen = false;
+ $element[0].focus();
+ }
+ };
+
+ $scope.keydown = function(evt) {
+ if (evt.which === 27) {
+ evt.stopPropagation();
+ $scope.isOpen = false;
+ $element[0].focus();
+ }
+ };
+
+ $scope.select = function(date, evt) {
+ evt.stopPropagation();
+
+ if (date === 'today') {
+ var today = new Date();
+ if (angular.isDate($scope.date)) {
+ date = new Date($scope.date);
+ date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
+ } else {
+ date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
+ date.setHours(0, 0, 0, 0);
+ }
+ }
+ $scope.dateSelection(date);
+ };
+
+ $scope.close = function(evt) {
+ evt.stopPropagation();
+
+ $scope.isOpen = false;
+ $element[0].focus();
+ };
+
+ $scope.disabled = angular.isDefined($attrs.disabled) || false;
+ if ($attrs.ngDisabled) {
+ watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
+ $scope.disabled = disabled;
+ }));
+ }
+
+ $scope.$watch('isOpen', function(value) {
+ if (value) {
+ if (!$scope.disabled) {
+ $timeout(function() {
+ positionPopup();
+
+ if (onOpenFocus) {
+ $scope.$broadcast('uib:datepicker.focus');
+ }
+
+ $document.on('click', documentClickBind);
+
+ var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
+ if (appendToBody || $position.parsePlacement(placement)[2]) {
+ scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
+ if (scrollParentEl) {
+ scrollParentEl.on('scroll', positionPopup);
+ }
+ } else {
+ scrollParentEl = null;
+ }
+
+ angular.element($window).on('resize', positionPopup);
+ }, 0, false);
+ } else {
+ $scope.isOpen = false;
+ }
+ } else {
+ $document.off('click', documentClickBind);
+ if (scrollParentEl) {
+ scrollParentEl.off('scroll', positionPopup);
+ }
+ angular.element($window).off('resize', positionPopup);
+ }
+ });
+
+ function cameltoDash(string) {
+ return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
+ }
+
+ function parseDateString(viewValue) {
+ var date = dateParser.parse(viewValue, dateFormat, $scope.date);
+ if (isNaN(date)) {
+ for (var i = 0; i < altInputFormats.length; i++) {
+ date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
+ if (!isNaN(date)) {
+ return date;
+ }
+ }
+ }
+ return date;
+ }
+
+ function parseDate(viewValue) {
+ if (angular.isNumber(viewValue)) {
+ // presumably timestamp to date object
+ viewValue = new Date(viewValue);
+ }
+
+ if (!viewValue) {
+ return null;
+ }
+
+ if (angular.isDate(viewValue) && !isNaN(viewValue)) {
+ return viewValue;
+ }
+
+ if (angular.isString(viewValue)) {
+ var date = parseDateString(viewValue);
+ if (!isNaN(date)) {
+ return dateParser.toTimezone(date, ngModelOptions.getOption('timezone'));
+ }
+ }
+
+ return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined;
+ }
+
+ function validator(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+
+ if (!$attrs.ngRequired && !value) {
+ return true;
+ }
+
+ if (angular.isNumber(value)) {
+ value = new Date(value);
+ }
+
+ if (!value) {
+ return true;
+ }
+
+ if (angular.isDate(value) && !isNaN(value)) {
+ return true;
+ }
+
+ if (angular.isString(value)) {
+ return !isNaN(parseDateString(value));
+ }
+
+ return false;
+ }
+
+ function documentClickBind(event) {
+ if (!$scope.isOpen && $scope.disabled) {
+ return;
+ }
+
+ var popup = $popup[0];
+ var dpContainsTarget = $element[0].contains(event.target);
+ // The popup node may not be an element node
+ // In some browsers (IE) only element nodes have the 'contains' function
+ var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
+ if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ }
+ }
+
+ function inputKeydownBind(evt) {
+ if (evt.which === 27 && $scope.isOpen) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ $element[0].focus();
+ } else if (evt.which === 40 && !$scope.isOpen) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.$apply(function() {
+ $scope.isOpen = true;
+ });
+ }
+ }
+
+ function positionPopup() {
+ if ($scope.isOpen) {
+ var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
+ var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
+ var position = $position.positionElements($element, dpElement, placement, appendToBody);
+ dpElement.css({top: position.top + 'px', left: position.left + 'px'});
+ if (dpElement.hasClass('uib-position-measure')) {
+ dpElement.removeClass('uib-position-measure');
+ }
+ }
+ }
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = angular.isObject(ngModelCtrl.$options) ?
+ ngModelCtrl.$options :
+ {
+ timezone: null
+ };
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ ngModelOptions = ngModelCtrl.$options;
+ }
+
+ return ngModelOptions;
+ }
+
+ $scope.$on('uib:datepicker.mode', function() {
+ $timeout(positionPopup, 0, false);
+ });
+}])
+
+.directive('uibDatepickerPopup', function() {
+ return {
+ require: ['ngModel', 'uibDatepickerPopup'],
+ controller: 'UibDatepickerPopupController',
+ scope: {
+ datepickerOptions: '=?',
+ isOpen: '=?',
+ currentText: '@',
+ clearText: '@',
+ closeText: '@'
+ },
+ link: function(scope, element, attrs, ctrls) {
+ var ngModel = ctrls[0],
+ ctrl = ctrls[1];
+
+ ctrl.init(ngModel);
+ }
+ };
+})
+
+.directive('uibDatepickerPopupWrap', function() {
+ return {
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
+ }
+ };
+});
+
+angular.module('ui.bootstrap.debounce', [])
+/**
+ * A helper, internal service that debounces a function
+ */
+ .factory('$$debounce', ['$timeout', function($timeout) {
+ return function(callback, debounceTime) {
+ var timeoutPromise;
+
+ return function() {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments);
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+
+ timeoutPromise = $timeout(function() {
+ callback.apply(self, args);
+ }, debounceTime);
+ };
+ };
+ }]);
+
+angular.module('ui.bootstrap.multiMap', [])
+/**
+ * A helper, internal data structure that stores all references attached to key
+ */
+ .factory('$$multiMap', function() {
+ return {
+ createNew: function() {
+ var map = {};
+
+ return {
+ entries: function() {
+ return Object.keys(map).map(function(key) {
+ return {
+ key: key,
+ value: map[key]
+ };
+ });
+ },
+ get: function(key) {
+ return map[key];
+ },
+ hasKey: function(key) {
+ return !!map[key];
+ },
+ keys: function() {
+ return Object.keys(map);
+ },
+ put: function(key, value) {
+ if (!map[key]) {
+ map[key] = [];
+ }
+
+ map[key].push(value);
+ },
+ remove: function(key, value) {
+ var values = map[key];
+
+ if (!values) {
+ return;
+ }
+
+ var idx = values.indexOf(value);
+
+ if (idx !== -1) {
+ values.splice(idx, 1);
+ }
+
+ if (!values.length) {
+ delete map[key];
+ }
+ }
+ };
+ }
+ };
+ });
+
+angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.multiMap', 'ui.bootstrap.position'])
+
+.constant('uibDropdownConfig', {
+ appendToOpenClass: 'uib-dropdown-open',
+ openClass: 'open'
+})
+
+.service('uibDropdownService', ['$document', '$rootScope', '$$multiMap', function($document, $rootScope, $$multiMap) {
+ var openScope = null;
+ var openedContainers = $$multiMap.createNew();
+
+ this.isOnlyOpen = function(dropdownScope, appendTo) {
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var openDropdown = openedDropdowns.reduce(function(toClose, dropdown) {
+ if (dropdown.scope === dropdownScope) {
+ return dropdown;
+ }
+
+ return toClose;
+ }, {});
+ if (openDropdown) {
+ return openedDropdowns.length === 1;
+ }
+ }
+
+ return false;
+ };
+
+ this.open = function(dropdownScope, element, appendTo) {
+ if (!openScope) {
+ $document.on('click', closeDropdown);
+ }
+
+ if (openScope && openScope !== dropdownScope) {
+ openScope.isOpen = false;
+ }
+
+ openScope = dropdownScope;
+
+ if (!appendTo) {
+ return;
+ }
+
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var openedScopes = openedDropdowns.map(function(dropdown) {
+ return dropdown.scope;
+ });
+ if (openedScopes.indexOf(dropdownScope) === -1) {
+ openedContainers.put(appendTo, {
+ scope: dropdownScope
+ });
+ }
+ } else {
+ openedContainers.put(appendTo, {
+ scope: dropdownScope
+ });
+ }
+ };
+
+ this.close = function(dropdownScope, element, appendTo) {
+ if (openScope === dropdownScope) {
+ $document.off('click', closeDropdown);
+ $document.off('keydown', this.keybindFilter);
+ openScope = null;
+ }
+
+ if (!appendTo) {
+ return;
+ }
+
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var dropdownToClose = openedDropdowns.reduce(function(toClose, dropdown) {
+ if (dropdown.scope === dropdownScope) {
+ return dropdown;
+ }
+
+ return toClose;
+ }, {});
+ if (dropdownToClose) {
+ openedContainers.remove(appendTo, dropdownToClose);
+ }
+ }
+ };
+
+ var closeDropdown = function(evt) {
+ // This method may still be called during the same mouse event that
+ // unbound this event handler. So check openScope before proceeding.
+ if (!openScope || !openScope.isOpen) { return; }
+
+ if (evt && openScope.getAutoClose() === 'disabled') { return; }
+
+ if (evt && evt.which === 3) { return; }
+
+ var toggleElement = openScope.getToggleElement();
+ if (evt && toggleElement && toggleElement[0].contains(evt.target)) {
+ return;
+ }
+
+ var dropdownElement = openScope.getDropdownElement();
+ if (evt && openScope.getAutoClose() === 'outsideClick' &&
+ dropdownElement && dropdownElement[0].contains(evt.target)) {
+ return;
+ }
+
+ openScope.focusToggleElement();
+ openScope.isOpen = false;
+
+ if (!$rootScope.$$phase) {
+ openScope.$apply();
+ }
+ };
+
+ this.keybindFilter = function(evt) {
+ if (!openScope) {
+ // see this.close as ESC could have been pressed which kills the scope so we can not proceed
+ return;
+ }
+
+ var dropdownElement = openScope.getDropdownElement();
+ var toggleElement = openScope.getToggleElement();
+ var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
+ var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);
+ if (evt.which === 27) {
+ evt.stopPropagation();
+ openScope.focusToggleElement();
+ closeDropdown();
+ } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ openScope.focusDropdownEntry(evt.which);
+ }
+ };
+}])
+
+.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {
+ var self = this,
+ scope = $scope.$new(), // create a child scope so we are not polluting original one
+ templateScope,
+ appendToOpenClass = dropdownConfig.appendToOpenClass,
+ openClass = dropdownConfig.openClass,
+ getIsOpen,
+ setIsOpen = angular.noop,
+ toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
+ keynavEnabled = false,
+ selectedOption = null,
+ body = $document.find('body');
+
+ $element.addClass('dropdown');
+
+ this.init = function() {
+ if ($attrs.isOpen) {
+ getIsOpen = $parse($attrs.isOpen);
+ setIsOpen = getIsOpen.assign;
+
+ $scope.$watch(getIsOpen, function(value) {
+ scope.isOpen = !!value;
+ });
+ }
+
+ keynavEnabled = angular.isDefined($attrs.keyboardNav);
+ };
+
+ this.toggle = function(open) {
+ scope.isOpen = arguments.length ? !!open : !scope.isOpen;
+ if (angular.isFunction(setIsOpen)) {
+ setIsOpen(scope, scope.isOpen);
+ }
+
+ return scope.isOpen;
+ };
+
+ // Allow other directives to watch status
+ this.isOpen = function() {
+ return scope.isOpen;
+ };
+
+ scope.getToggleElement = function() {
+ return self.toggleElement;
+ };
+
+ scope.getAutoClose = function() {
+ return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
+ };
+
+ scope.getElement = function() {
+ return $element;
+ };
+
+ scope.isKeynavEnabled = function() {
+ return keynavEnabled;
+ };
+
+ scope.focusDropdownEntry = function(keyCode) {
+ var elems = self.dropdownMenu ? //If append to body is used.
+ angular.element(self.dropdownMenu).find('a') :
+ $element.find('ul').eq(0).find('a');
+
+ switch (keyCode) {
+ case 40: {
+ if (!angular.isNumber(self.selectedOption)) {
+ self.selectedOption = 0;
+ } else {
+ self.selectedOption = self.selectedOption === elems.length - 1 ?
+ self.selectedOption :
+ self.selectedOption + 1;
+ }
+ break;
+ }
+ case 38: {
+ if (!angular.isNumber(self.selectedOption)) {
+ self.selectedOption = elems.length - 1;
+ } else {
+ self.selectedOption = self.selectedOption === 0 ?
+ 0 : self.selectedOption - 1;
+ }
+ break;
+ }
+ }
+ elems[self.selectedOption].focus();
+ };
+
+ scope.getDropdownElement = function() {
+ return self.dropdownMenu;
+ };
+
+ scope.focusToggleElement = function() {
+ if (self.toggleElement) {
+ self.toggleElement[0].focus();
+ }
+ };
+
+ function removeDropdownMenu() {
+ $element.append(self.dropdownMenu);
+ }
+
+ scope.$watch('isOpen', function(isOpen, wasOpen) {
+ var appendTo = null,
+ appendToBody = false;
+
+ if (angular.isDefined($attrs.dropdownAppendTo)) {
+ var appendToEl = $parse($attrs.dropdownAppendTo)(scope);
+ if (appendToEl) {
+ appendTo = angular.element(appendToEl);
+ }
+ }
+
+ if (angular.isDefined($attrs.dropdownAppendToBody)) {
+ var appendToBodyValue = $parse($attrs.dropdownAppendToBody)(scope);
+ if (appendToBodyValue !== false) {
+ appendToBody = true;
+ }
+ }
+
+ if (appendToBody && !appendTo) {
+ appendTo = body;
+ }
+
+ if (appendTo && self.dropdownMenu) {
+ if (isOpen) {
+ appendTo.append(self.dropdownMenu);
+ $element.on('$destroy', removeDropdownMenu);
+ } else {
+ $element.off('$destroy', removeDropdownMenu);
+ removeDropdownMenu();
+ }
+ }
+
+ if (appendTo && self.dropdownMenu) {
+ var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
+ css,
+ rightalign,
+ scrollbarPadding,
+ scrollbarWidth = 0;
+
+ css = {
+ top: pos.top + 'px',
+ display: isOpen ? 'block' : 'none'
+ };
+
+ rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
+ if (!rightalign) {
+ css.left = pos.left + 'px';
+ css.right = 'auto';
+ } else {
+ css.left = 'auto';
+ scrollbarPadding = $position.scrollbarPadding(appendTo);
+
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ scrollbarWidth = scrollbarPadding.scrollbarWidth;
+ }
+
+ css.right = window.innerWidth - scrollbarWidth -
+ (pos.left + $element.prop('offsetWidth')) + 'px';
+ }
+
+ // Need to adjust our positioning to be relative to the appendTo container
+ // if it's not the body element
+ if (!appendToBody) {
+ var appendOffset = $position.offset(appendTo);
+
+ css.top = pos.top - appendOffset.top + 'px';
+
+ if (!rightalign) {
+ css.left = pos.left - appendOffset.left + 'px';
+ } else {
+ css.right = window.innerWidth -
+ (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';
+ }
+ }
+
+ self.dropdownMenu.css(css);
+ }
+
+ var openContainer = appendTo ? appendTo : $element;
+ var dropdownOpenClass = appendTo ? appendToOpenClass : openClass;
+ var hasOpenClass = openContainer.hasClass(dropdownOpenClass);
+ var isOnlyOpen = uibDropdownService.isOnlyOpen($scope, appendTo);
+
+ if (hasOpenClass === !isOpen) {
+ var toggleClass;
+ if (appendTo) {
+ toggleClass = !isOnlyOpen ? 'addClass' : 'removeClass';
+ } else {
+ toggleClass = isOpen ? 'addClass' : 'removeClass';
+ }
+ $animate[toggleClass](openContainer, dropdownOpenClass).then(function() {
+ if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
+ toggleInvoker($scope, { open: !!isOpen });
+ }
+ });
+ }
+
+ if (isOpen) {
+ if (self.dropdownMenuTemplateUrl) {
+ $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {
+ templateScope = scope.$new();
+ $compile(tplContent.trim())(templateScope, function(dropdownElement) {
+ var newEl = dropdownElement;
+ self.dropdownMenu.replaceWith(newEl);
+ self.dropdownMenu = newEl;
+ $document.on('keydown', uibDropdownService.keybindFilter);
+ });
+ });
+ } else {
+ $document.on('keydown', uibDropdownService.keybindFilter);
+ }
+
+ scope.focusToggleElement();
+ uibDropdownService.open(scope, $element, appendTo);
+ } else {
+ uibDropdownService.close(scope, $element, appendTo);
+ if (self.dropdownMenuTemplateUrl) {
+ if (templateScope) {
+ templateScope.$destroy();
+ }
+ var newEl = angular.element('<ul class="dropdown-menu"></ul>');
+ self.dropdownMenu.replaceWith(newEl);
+ self.dropdownMenu = newEl;
+ }
+
+ self.selectedOption = null;
+ }
+
+ if (angular.isFunction(setIsOpen)) {
+ setIsOpen($scope, isOpen);
+ }
+ });
+}])
+
+.directive('uibDropdown', function() {
+ return {
+ controller: 'UibDropdownController',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ dropdownCtrl.init();
+ }
+ };
+})
+
+.directive('uibDropdownMenu', function() {
+ return {
+ restrict: 'A',
+ require: '?^uibDropdown',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {
+ return;
+ }
+
+ element.addClass('dropdown-menu');
+
+ var tplUrl = attrs.templateUrl;
+ if (tplUrl) {
+ dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
+ }
+
+ if (!dropdownCtrl.dropdownMenu) {
+ dropdownCtrl.dropdownMenu = element;
+ }
+ }
+ };
+})
+
+.directive('uibDropdownToggle', function() {
+ return {
+ require: '?^uibDropdown',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ if (!dropdownCtrl) {
+ return;
+ }
+
+ element.addClass('dropdown-toggle');
+
+ dropdownCtrl.toggleElement = element;
+
+ var toggleDropdown = function(event) {
+ event.preventDefault();
+
+ if (!element.hasClass('disabled') && !attrs.disabled) {
+ scope.$apply(function() {
+ dropdownCtrl.toggle();
+ });
+ }
+ };
+
+ element.on('click', toggleDropdown);
+
+ // WAI-ARIA
+ element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
+ scope.$watch(dropdownCtrl.isOpen, function(isOpen) {
+ element.attr('aria-expanded', !!isOpen);
+ });
+
+ scope.$on('$destroy', function() {
+ element.off('click', toggleDropdown);
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.stackedMap', [])
+/**
+ * A helper, internal data structure that acts as a map but also allows getting / removing
+ * elements in the LIFO order
+ */
+ .factory('$$stackedMap', function() {
+ return {
+ createNew: function() {
+ var stack = [];
+
+ return {
+ add: function(key, value) {
+ stack.push({
+ key: key,
+ value: value
+ });
+ },
+ get: function(key) {
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ return stack[i];
+ }
+ }
+ },
+ keys: function() {
+ var keys = [];
+ for (var i = 0; i < stack.length; i++) {
+ keys.push(stack[i].key);
+ }
+ return keys;
+ },
+ top: function() {
+ return stack[stack.length - 1];
+ },
+ remove: function(key) {
+ var idx = -1;
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ idx = i;
+ break;
+ }
+ }
+ return stack.splice(idx, 1)[0];
+ },
+ removeTop: function() {
+ return stack.pop();
+ },
+ length: function() {
+ return stack.length;
+ }
+ };
+ }
+ };
+ });
+angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
+/**
+ * Pluggable resolve mechanism for the modal resolve resolution
+ * Supports UI Router's $resolve service
+ */
+ .provider('$uibResolve', function() {
+ var resolve = this;
+ this.resolver = null;
+
+ this.setResolver = function(resolver) {
+ this.resolver = resolver;
+ };
+
+ this.$get = ['$injector', '$q', function($injector, $q) {
+ var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
+ return {
+ resolve: function(invocables, locals, parent, self) {
+ if (resolver) {
+ return resolver.resolve(invocables, locals, parent, self);
+ }
+
+ var promises = [];
+
+ angular.forEach(invocables, function(value) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promises.push($q.resolve($injector.invoke(value)));
+ } else if (angular.isString(value)) {
+ promises.push($q.resolve($injector.get(value)));
+ } else {
+ promises.push($q.resolve(value));
+ }
+ });
+
+ return $q.all(promises).then(function(resolves) {
+ var resolveObj = {};
+ var resolveIter = 0;
+ angular.forEach(invocables, function(value, key) {
+ resolveObj[key] = resolves[resolveIter++];
+ });
+
+ return resolveObj;
+ });
+ }
+ };
+ }];
+ })
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+ .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
+ function($animate, $injector, $modalStack) {
+ return {
+ restrict: 'A',
+ compile: function(tElement, tAttrs) {
+ tElement.addClass(tAttrs.backdropClass);
+ return linkFn;
+ }
+ };
+
+ function linkFn(scope, element, attrs) {
+ if (attrs.modalInClass) {
+ $animate.addClass(element, attrs.modalInClass);
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ if (scope.modalOptions.animation) {
+ $animate.removeClass(element, attrs.modalInClass).then(done);
+ } else {
+ done();
+ }
+ });
+ }
+ }
+ }])
+
+ .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
+ function($modalStack, $q, $animateCss, $document) {
+ return {
+ scope: {
+ index: '@'
+ },
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(tElement, tAttrs) {
+ return tAttrs.templateUrl || 'uib/template/modal/window.html';
+ },
+ link: function(scope, element, attrs) {
+ element.addClass(attrs.windowTopClass || '');
+ scope.size = attrs.size;
+
+ scope.close = function(evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop &&
+ modal.value.backdrop !== 'static' &&
+ evt.target === evt.currentTarget) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+
+ // moved from template to fix issue #2280
+ element.on('click', scope.close);
+
+ // This property is only added to the scope for the purpose of detecting when this directive is rendered.
+ // We can detect that by using this property in the template associated with this directive and then use
+ // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
+ scope.$isRendered = true;
+
+ // Deferred object that will be resolved when this modal is rendered.
+ var modalRenderDeferObj = $q.defer();
+ // Resolve render promise post-digest
+ scope.$$postDigest(function() {
+ modalRenderDeferObj.resolve();
+ });
+
+ modalRenderDeferObj.promise.then(function() {
+ var animationPromise = null;
+
+ if (attrs.modalInClass) {
+ animationPromise = $animateCss(element, {
+ addClass: attrs.modalInClass
+ }).start();
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ $animateCss(element, {
+ removeClass: attrs.modalInClass
+ }).start().then(done);
+ });
+ }
+
+
+ $q.when(animationPromise).then(function() {
+ // Notify {@link $modalStack} that modal is rendered.
+ var modal = $modalStack.getTop();
+ if (modal) {
+ $modalStack.modalRendered(modal.key);
+ }
+
+ /**
+ * If something within the freshly-opened modal already has focus (perhaps via a
+ * directive that causes focus) then there's no need to try to focus anything.
+ */
+ if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
+ var inputWithAutofocus = element[0].querySelector('[autofocus]');
+ /**
+ * Auto-focusing of a freshly-opened modal element causes any child elements
+ * with the autofocus attribute to lose focus. This is an issue on touch
+ * based devices which will show and then hide the onscreen keyboard.
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
+ * the modal element if the modal does not contain an autofocus element.
+ */
+ if (inputWithAutofocus) {
+ inputWithAutofocus.focus();
+ } else {
+ element[0].focus();
+ }
+ }
+ });
+ });
+ }
+ };
+ }])
+
+ .directive('uibModalAnimationClass', function() {
+ return {
+ compile: function(tElement, tAttrs) {
+ if (tAttrs.modalAnimation) {
+ tElement.addClass(tAttrs.uibModalAnimationClass);
+ }
+ }
+ };
+ })
+
+ .directive('uibModalTransclude', ['$animate', function($animate) {
+ return {
+ link: function(scope, element, attrs, controller, transclude) {
+ transclude(scope.$parent, function(clone) {
+ element.empty();
+ $animate.enter(clone, element);
+ });
+ }
+ };
+ }])
+
+ .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
+ '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
+ function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
+ var OPENED_MODAL_CLASS = 'modal-open';
+
+ var backdropDomEl, backdropScope;
+ var openedWindows = $$stackedMap.createNew();
+ var openedClasses = $$multiMap.createNew();
+ var $modalStack = {
+ NOW_CLOSING_EVENT: 'modal.stack.now-closing'
+ };
+ var topModalIndex = 0;
+ var previousTopOpenedModal = null;
+ var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';
+
+ //Modal focus behavior
+ var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
+ 'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' +
+ 'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]';
+ var scrollbarPadding;
+ var SNAKE_CASE_REGEXP = /[A-Z]/g;
+
+ // TODO: extract into common dependency with tooltip
+ function snake_case(name) {
+ var separator = '-';
+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ function isVisible(element) {
+ return !!(element.offsetWidth ||
+ element.offsetHeight ||
+ element.getClientRects().length);
+ }
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+
+ // If any backdrop exist, ensure that it's index is always
+ // right below the top modal
+ if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
+ topBackdropIndex = topModalIndex;
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
+ if (backdropScope) {
+ backdropScope.index = newBackdropIndex;
+ }
+ });
+
+ function removeModalWindow(modalInstance, elementToReceiveFocus) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ var appendToElement = modalWindow.appendTo;
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+ previousTopOpenedModal = openedWindows.top();
+ if (previousTopOpenedModal) {
+ topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
+ }
+
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
+ var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
+ openedClasses.remove(modalBodyClass, modalInstance);
+ var areAnyOpen = openedClasses.hasKey(modalBodyClass);
+ appendToElement.toggleClass(modalBodyClass, areAnyOpen);
+ if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ if (scrollbarPadding.originalRight) {
+ appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});
+ } else {
+ appendToElement.css({paddingRight: ''});
+ }
+ scrollbarPadding = null;
+ }
+ toggleTopWindowClass(true);
+ }, modalWindow.closedDeferred);
+ checkRemoveBackdrop();
+
+ //move focus to specified element if available, or else to body
+ if (elementToReceiveFocus && elementToReceiveFocus.focus) {
+ elementToReceiveFocus.focus();
+ } else if (appendToElement.focus) {
+ appendToElement.focus();
+ }
+ }
+
+ // Add or remove "windowTopClass" from the top window in the stack
+ function toggleTopWindowClass(toggleSwitch) {
+ var modalWindow;
+
+ if (openedWindows.length() > 0) {
+ modalWindow = openedWindows.top().value;
+ modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
+ }
+ }
+
+ function checkRemoveBackdrop() {
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() === -1) {
+ var backdropScopeRef = backdropScope;
+ removeAfterAnimate(backdropDomEl, backdropScope, function() {
+ backdropScopeRef = null;
+ });
+ backdropDomEl = undefined;
+ backdropScope = undefined;
+ }
+ }
+
+ function removeAfterAnimate(domEl, scope, done, closedDeferred) {
+ var asyncDeferred;
+ var asyncPromise = null;
+ var setIsAsync = function() {
+ if (!asyncDeferred) {
+ asyncDeferred = $q.defer();
+ asyncPromise = asyncDeferred.promise;
+ }
+
+ return function asyncDone() {
+ asyncDeferred.resolve();
+ };
+ };
+ scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
+
+ // Note that it's intentional that asyncPromise might be null.
+ // That's when setIsAsync has not been called during the
+ // NOW_CLOSING_EVENT broadcast.
+ return $q.when(asyncPromise).then(afterAnimating);
+
+ function afterAnimating() {
+ if (afterAnimating.done) {
+ return;
+ }
+ afterAnimating.done = true;
+
+ $animate.leave(domEl).then(function() {
+ if (done) {
+ done();
+ }
+
+ domEl.remove();
+ if (closedDeferred) {
+ closedDeferred.resolve();
+ }
+ });
+
+ scope.$destroy();
+ }
+ }
+
+ $document.on('keydown', keydownListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keydown', keydownListener);
+ });
+
+ function keydownListener(evt) {
+ if (evt.isDefaultPrevented()) {
+ return evt;
+ }
+
+ var modal = openedWindows.top();
+ if (modal) {
+ switch (evt.which) {
+ case 27: {
+ if (modal.value.keyboard) {
+ evt.preventDefault();
+ $rootScope.$apply(function() {
+ $modalStack.dismiss(modal.key, 'escape key press');
+ });
+ }
+ break;
+ }
+ case 9: {
+ var list = $modalStack.loadFocusElementList(modal);
+ var focusChanged = false;
+ if (evt.shiftKey) {
+ if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
+ focusChanged = $modalStack.focusLastFocusableElement(list);
+ }
+ } else {
+ if ($modalStack.isFocusInLastItem(evt, list)) {
+ focusChanged = $modalStack.focusFirstFocusableElement(list);
+ }
+ }
+
+ if (focusChanged) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ $modalStack.open = function(modalInstance, modal) {
+ var modalOpener = $document[0].activeElement,
+ modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
+
+ toggleTopWindowClass(false);
+
+ // Store the current top first, to determine what index we ought to use
+ // for the current top modal
+ previousTopOpenedModal = openedWindows.top();
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ renderDeferred: modal.renderDeferred,
+ closedDeferred: modal.closedDeferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard,
+ openedClass: modal.openedClass,
+ windowTopClass: modal.windowTopClass,
+ animation: modal.animation,
+ appendTo: modal.appendTo
+ });
+
+ openedClasses.put(modalBodyClass, modalInstance);
+
+ var appendToElement = modal.appendTo,
+ currBackdropIndex = backdropIndex();
+
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
+ backdropScope = $rootScope.$new(true);
+ backdropScope.modalOptions = modal;
+ backdropScope.index = currBackdropIndex;
+ backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
+ backdropDomEl.attr({
+ 'class': 'modal-backdrop',
+ 'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}',
+ 'uib-modal-animation-class': 'fade',
+ 'modal-in-class': 'in'
+ });
+ if (modal.backdropClass) {
+ backdropDomEl.addClass(modal.backdropClass);
+ }
+
+ if (modal.animation) {
+ backdropDomEl.attr('modal-animation', 'true');
+ }
+ $compile(backdropDomEl)(backdropScope);
+ $animate.enter(backdropDomEl, appendToElement);
+ if ($uibPosition.isScrollable(appendToElement)) {
+ scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
+ }
+ }
+ }
+
+ var content;
+ if (modal.component) {
+ content = document.createElement(snake_case(modal.component.name));
+ content = angular.element(content);
+ content.attr({
+ resolve: '$resolve',
+ 'modal-instance': '$uibModalInstance',
+ close: '$close($value)',
+ dismiss: '$dismiss($value)'
+ });
+ } else {
+ content = modal.content;
+ }
+
+ // Set the top modal index based on the index of the previous top modal
+ topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
+ var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
+ angularDomEl.attr({
+ 'class': 'modal',
+ 'template-url': modal.windowTemplateUrl,
+ 'window-top-class': modal.windowTopClass,
+ 'role': 'dialog',
+ 'aria-labelledby': modal.ariaLabelledBy,
+ 'aria-describedby': modal.ariaDescribedBy,
+ 'size': modal.size,
+ 'index': topModalIndex,
+ 'animate': 'animate',
+ 'ng-style': '{\'z-index\': 1050 + $$topModalIndex*10, display: \'block\'}',
+ 'tabindex': -1,
+ 'uib-modal-animation-class': 'fade',
+ 'modal-in-class': 'in'
+ }).append(content);
+ if (modal.windowClass) {
+ angularDomEl.addClass(modal.windowClass);
+ }
+
+ if (modal.animation) {
+ angularDomEl.attr('modal-animation', 'true');
+ }
+
+ appendToElement.addClass(modalBodyClass);
+ if (modal.scope) {
+ // we need to explicitly add the modal index to the modal scope
+ // because it is needed by ngStyle to compute the zIndex property.
+ modal.scope.$$topModalIndex = topModalIndex;
+ }
+ $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
+
+ openedWindows.top().value.modalDomEl = angularDomEl;
+ openedWindows.top().value.modalOpener = modalOpener;
+
+ applyAriaHidden(angularDomEl);
+
+ function applyAriaHidden(el) {
+ if (!el || el[0].tagName === 'BODY') {
+ return;
+ }
+
+ getSiblings(el).forEach(function(sibling) {
+ var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
+ ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);
+
+ if (!ariaHiddenCount) {
+ ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
+ }
+
+ sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
+ sibling.setAttribute('aria-hidden', 'true');
+ });
+
+ return applyAriaHidden(el.parent());
+
+ function getSiblings(el) {
+ var children = el.parent() ? el.parent().children() : [];
+
+ return Array.prototype.filter.call(children, function(child) {
+ return child !== el[0];
+ });
+ }
+ }
+ };
+
+ function broadcastClosing(modalWindow, resultOrReason, closing) {
+ return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
+ }
+
+ function unhideBackgroundElements() {
+ Array.prototype.forEach.call(
+ document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
+ function(hiddenEl) {
+ var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
+ newHiddenCount = ariaHiddenCount - 1;
+ hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);
+
+ if (!newHiddenCount) {
+ hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
+ hiddenEl.removeAttribute('aria-hidden');
+ }
+ }
+ );
+ }
+
+ $modalStack.close = function(modalInstance, result) {
+ var modalWindow = openedWindows.get(modalInstance);
+ unhideBackgroundElements();
+ if (modalWindow && broadcastClosing(modalWindow, result, true)) {
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.resolve(result);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+
+ return !modalWindow;
+ };
+
+ $modalStack.dismiss = function(modalInstance, reason) {
+ var modalWindow = openedWindows.get(modalInstance);
+ unhideBackgroundElements();
+ if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.reject(reason);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+ return !modalWindow;
+ };
+
+ $modalStack.dismissAll = function(reason) {
+ var topModal = this.getTop();
+ while (topModal && this.dismiss(topModal.key, reason)) {
+ topModal = this.getTop();
+ }
+ };
+
+ $modalStack.getTop = function() {
+ return openedWindows.top();
+ };
+
+ $modalStack.modalRendered = function(modalInstance) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow) {
+ modalWindow.value.renderDeferred.resolve();
+ }
+ };
+
+ $modalStack.focusFirstFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[0].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.focusLastFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[list.length - 1].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.isModalFocused = function(evt, modalWindow) {
+ if (evt && modalWindow) {
+ var modalDomEl = modalWindow.value.modalDomEl;
+ if (modalDomEl && modalDomEl.length) {
+ return (evt.target || evt.srcElement) === modalDomEl[0];
+ }
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInFirstItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[0];
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInLastItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[list.length - 1];
+ }
+ return false;
+ };
+
+ $modalStack.loadFocusElementList = function(modalWindow) {
+ if (modalWindow) {
+ var modalDomE1 = modalWindow.value.modalDomEl;
+ if (modalDomE1 && modalDomE1.length) {
+ var elements = modalDomE1[0].querySelectorAll(tabbableSelector);
+ return elements ?
+ Array.prototype.filter.call(elements, function(element) {
+ return isVisible(element);
+ }) : elements;
+ }
+ }
+ };
+
+ return $modalStack;
+ }])
+
+ .provider('$uibModal', function() {
+ var $modalProvider = {
+ options: {
+ animation: true,
+ backdrop: true, //can also be false or 'static'
+ keyboard: true
+ },
+ $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
+ function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $templateRequest(angular.isFunction(options.templateUrl) ?
+ options.templateUrl() : options.templateUrl);
+ }
+
+ var promiseChain = null;
+ $modal.getPromiseChain = function() {
+ return promiseChain;
+ };
+
+ $modal.open = function(modalOptions) {
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+ var modalClosedDeferred = $q.defer();
+ var modalRenderDeferred = $q.defer();
+
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ closed: modalClosedDeferred.promise,
+ rendered: modalRenderDeferred.promise,
+ close: function (result) {
+ return $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ return $modalStack.dismiss(modalInstance, reason);
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+ modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
+
+ if (!modalOptions.appendTo.length) {
+ throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
+ }
+
+ //verify options
+ if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of component or template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise;
+ if (modalOptions.component) {
+ templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null));
+ } else {
+ templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
+ }
+
+ function resolveWithTemplate() {
+ return templateAndResolvePromise;
+ }
+
+ // Wait for the resolution of the existing promise chain.
+ // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
+ // Then add to $modalStack and resolve opened.
+ // Finally clean up the chain variable if no subsequent modal has overwritten it.
+ var samePromise;
+ samePromise = promiseChain = $q.all([promiseChain])
+ .then(resolveWithTemplate, resolveWithTemplate)
+ .then(function resolveSuccess(tplAndVars) {
+ var providedScope = modalOptions.scope || $rootScope;
+
+ var modalScope = providedScope.$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ modalScope.$on('$destroy', function() {
+ if (!modalScope.$$uibDestructionScheduled) {
+ modalScope.$dismiss('$uibUnscheduledDestruction');
+ }
+ });
+
+ var modal = {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ renderDeferred: modalRenderDeferred,
+ closedDeferred: modalClosedDeferred,
+ animation: modalOptions.animation,
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ backdropClass: modalOptions.backdropClass,
+ windowTopClass: modalOptions.windowTopClass,
+ windowClass: modalOptions.windowClass,
+ windowTemplateUrl: modalOptions.windowTemplateUrl,
+ ariaLabelledBy: modalOptions.ariaLabelledBy,
+ ariaDescribedBy: modalOptions.ariaDescribedBy,
+ size: modalOptions.size,
+ openedClass: modalOptions.openedClass,
+ appendTo: modalOptions.appendTo
+ };
+
+ var component = {};
+ var ctrlInstance, ctrlInstantiate, ctrlLocals = {};
+
+ if (modalOptions.component) {
+ constructLocals(component, false, true, false);
+ component.name = modalOptions.component;
+ modal.component = component;
+ } else if (modalOptions.controller) {
+ constructLocals(ctrlLocals, true, false, true);
+
+ // the third param will make the controller instantiate later,private api
+ // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
+ ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
+ if (modalOptions.controllerAs && modalOptions.bindToController) {
+ ctrlInstance = ctrlInstantiate.instance;
+ ctrlInstance.$close = modalScope.$close;
+ ctrlInstance.$dismiss = modalScope.$dismiss;
+ angular.extend(ctrlInstance, {
+ $resolve: ctrlLocals.$scope.$resolve
+ }, providedScope);
+ }
+
+ ctrlInstance = ctrlInstantiate();
+
+ if (angular.isFunction(ctrlInstance.$onInit)) {
+ ctrlInstance.$onInit();
+ }
+ }
+
+ if (!modalOptions.component) {
+ modal.content = tplAndVars[0];
+ }
+
+ $modalStack.open(modalInstance, modal);
+ modalOpenedDeferred.resolve(true);
+
+ function constructLocals(obj, template, instanceOnScope, injectable) {
+ obj.$scope = modalScope;
+ obj.$scope.$resolve = {};
+ if (instanceOnScope) {
+ obj.$scope.$uibModalInstance = modalInstance;
+ } else {
+ obj.$uibModalInstance = modalInstance;
+ }
+
+ var resolves = template ? tplAndVars[1] : tplAndVars;
+ angular.forEach(resolves, function(value, key) {
+ if (injectable) {
+ obj[key] = value;
+ }
+
+ obj.$scope.$resolve[key] = value;
+ });
+ }
+ }, function resolveError(reason) {
+ modalOpenedDeferred.reject(reason);
+ modalResultDeferred.reject(reason);
+ })['finally'](function() {
+ if (promiseChain === samePromise) {
+ promiseChain = null;
+ }
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }
+ ]
+ };
+
+ return $modalProvider;
+ });
+
+angular.module('ui.bootstrap.paging', [])
+/**
+ * Helper internal service for generating common controller code between the
+ * pager and pagination components
+ */
+.factory('uibPaging', ['$parse', function($parse) {
+ return {
+ create: function(ctrl, $scope, $attrs) {
+ ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
+ ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl
+ ctrl._watchers = [];
+
+ ctrl.init = function(ngModelCtrl, config) {
+ ctrl.ngModelCtrl = ngModelCtrl;
+ ctrl.config = config;
+
+ ngModelCtrl.$render = function() {
+ ctrl.render();
+ };
+
+ if ($attrs.itemsPerPage) {
+ ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function(value) {
+ ctrl.itemsPerPage = parseInt(value, 10);
+ $scope.totalPages = ctrl.calculateTotalPages();
+ ctrl.updatePage();
+ }));
+ } else {
+ ctrl.itemsPerPage = config.itemsPerPage;
+ }
+
+ $scope.$watch('totalItems', function(newTotal, oldTotal) {
+ if (angular.isDefined(newTotal) || newTotal !== oldTotal) {
+ $scope.totalPages = ctrl.calculateTotalPages();
+ ctrl.updatePage();
+ }
+ });
+ };
+
+ ctrl.calculateTotalPages = function() {
+ var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);
+ return Math.max(totalPages || 0, 1);
+ };
+
+ ctrl.render = function() {
+ $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;
+ };
+
+ $scope.selectPage = function(page, evt) {
+ if (evt) {
+ evt.preventDefault();
+ }
+
+ var clickAllowed = !$scope.ngDisabled || !evt;
+ if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {
+ if (evt && evt.target) {
+ evt.target.blur();
+ }
+ ctrl.ngModelCtrl.$setViewValue(page);
+ ctrl.ngModelCtrl.$render();
+ }
+ };
+
+ $scope.getText = function(key) {
+ return $scope[key + 'Text'] || ctrl.config[key + 'Text'];
+ };
+
+ $scope.noPrevious = function() {
+ return $scope.page === 1;
+ };
+
+ $scope.noNext = function() {
+ return $scope.page === $scope.totalPages;
+ };
+
+ ctrl.updatePage = function() {
+ ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable
+
+ if ($scope.page > $scope.totalPages) {
+ $scope.selectPage($scope.totalPages);
+ } else {
+ ctrl.ngModelCtrl.$render();
+ }
+ };
+
+ $scope.$on('$destroy', function() {
+ while (ctrl._watchers.length) {
+ ctrl._watchers.shift()();
+ }
+ });
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
+
+.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) {
+ $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;
+
+ uibPaging.create(this, $scope, $attrs);
+}])
+
+.constant('uibPagerConfig', {
+ itemsPerPage: 10,
+ previousText: '« Previous',
+ nextText: 'Next »',
+ align: true
+})
+
+.directive('uibPager', ['uibPagerConfig', function(uibPagerConfig) {
+ return {
+ scope: {
+ totalItems: '=',
+ previousText: '@',
+ nextText: '@',
+ ngDisabled: '='
+ },
+ require: ['uibPager', '?ngModel'],
+ restrict: 'A',
+ controller: 'UibPagerController',
+ controllerAs: 'pager',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/pager/pager.html';
+ },
+ link: function(scope, element, attrs, ctrls) {
+ element.addClass('pager');
+ var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (!ngModelCtrl) {
+ return; // do nothing if no ng-model
+ }
+
+ paginationCtrl.init(ngModelCtrl, uibPagerConfig);
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
+.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
+ var ctrl = this;
+ // Setup configuration parameters
+ var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
+ rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
+ forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
+ boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,
+ pageLabel = angular.isDefined($attrs.pageLabel) ? function(idx) { return $scope.$parent.$eval($attrs.pageLabel, {$page: idx}); } : angular.identity;
+ $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
+ $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;
+ $attrs.$set('role', 'menu');
+
+ uibPaging.create(this, $scope, $attrs);
+
+ if ($attrs.maxSize) {
+ ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function(value) {
+ maxSize = parseInt(value, 10);
+ ctrl.render();
+ }));
+ }
+
+ // Create page object used in template
+ function makePage(number, text, isActive) {
+ return {
+ number: number,
+ text: text,
+ active: isActive
+ };
+ }
+
+ function getPages(currentPage, totalPages) {
+ var pages = [];
+
+ // Default page limits
+ var startPage = 1, endPage = totalPages;
+ var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;
+
+ // recompute if maxSize
+ if (isMaxSized) {
+ if (rotate) {
+ // Current page is displayed in the middle of the visible ones
+ startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
+ endPage = startPage + maxSize - 1;
+
+ // Adjust if limit is exceeded
+ if (endPage > totalPages) {
+ endPage = totalPages;
+ startPage = endPage - maxSize + 1;
+ }
+ } else {
+ // Visible pages are paginated with maxSize
+ startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;
+
+ // Adjust last page if limit is exceeded
+ endPage = Math.min(startPage + maxSize - 1, totalPages);
+ }
+ }
+
+ // Add page number links
+ for (var number = startPage; number <= endPage; number++) {
+ var page = makePage(number, pageLabel(number), number === currentPage);
+ pages.push(page);
+ }
+
+ // Add links to move between page sets
+ if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
+ if (startPage > 1) {
+ if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
+ var previousPageSet = makePage(startPage - 1, '...', false);
+ pages.unshift(previousPageSet);
+ }
+ if (boundaryLinkNumbers) {
+ if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
+ var secondPageLink = makePage(2, '2', false);
+ pages.unshift(secondPageLink);
+ }
+ //add the first page
+ var firstPageLink = makePage(1, '1', false);
+ pages.unshift(firstPageLink);
+ }
+ }
+
+ if (endPage < totalPages) {
+ if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
+ var nextPageSet = makePage(endPage + 1, '...', false);
+ pages.push(nextPageSet);
+ }
+ if (boundaryLinkNumbers) {
+ if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
+ var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
+ pages.push(secondToLastPageLink);
+ }
+ //add the last page
+ var lastPageLink = makePage(totalPages, totalPages, false);
+ pages.push(lastPageLink);
+ }
+ }
+ }
+ return pages;
+ }
+
+ var originalRender = this.render;
+ this.render = function() {
+ originalRender();
+ if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
+ $scope.pages = getPages($scope.page, $scope.totalPages);
+ }
+ };
+}])
+
+.constant('uibPaginationConfig', {
+ itemsPerPage: 10,
+ boundaryLinks: false,
+ boundaryLinkNumbers: false,
+ directionLinks: true,
+ firstText: 'First',
+ previousText: 'Previous',
+ nextText: 'Next',
+ lastText: 'Last',
+ rotate: true,
+ forceEllipses: false
+})
+
+.directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, uibPaginationConfig) {
+ return {
+ scope: {
+ totalItems: '=',
+ firstText: '@',
+ previousText: '@',
+ nextText: '@',
+ lastText: '@',
+ ngDisabled:'='
+ },
+ require: ['uibPagination', '?ngModel'],
+ restrict: 'A',
+ controller: 'UibPaginationController',
+ controllerAs: 'pagination',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/pagination/pagination.html';
+ },
+ link: function(scope, element, attrs, ctrls) {
+ element.addClass('pagination');
+ var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (!ngModelCtrl) {
+ return; // do nothing if no ng-model
+ }
+
+ paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
+ }
+ };
+}]);
+
+/**
+ * The following features are still outstanding: animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, html tooltips, and selector delegation.
+ */
+angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
+
+/**
+ * The $tooltip service creates tooltip- and popover-like directives as well as
+ * houses global options for them.
+ */
+.provider('$uibTooltip', function() {
+ // The default options tooltip and popover.
+ var defaultOptions = {
+ placement: 'top',
+ placementClassPrefix: '',
+ animation: true,
+ popupDelay: 0,
+ popupCloseDelay: 0,
+ useContentExp: false
+ };
+
+ // Default hide triggers for each show trigger
+ var triggerMap = {
+ 'mouseenter': 'mouseleave',
+ 'click': 'click',
+ 'outsideClick': 'outsideClick',
+ 'focus': 'blur',
+ 'none': ''
+ };
+
+ // The options specified to the provider globally.
+ var globalOptions = {};
+
+ /**
+ * `options({})` allows global configuration of all tooltips in the
+ * application.
+ *
+ * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
+ * // place tooltips left instead of top by default
+ * $tooltipProvider.options( { placement: 'left' } );
+ * });
+ */
+ this.options = function(value) {
+ angular.extend(globalOptions, value);
+ };
+
+ /**
+ * This allows you to extend the set of trigger mappings available. E.g.:
+ *
+ * $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
+ */
+ this.setTriggers = function setTriggers(triggers) {
+ angular.extend(triggerMap, triggers);
+ };
+
+ /**
+ * This is a helper function for translating camel-case to snake_case.
+ */
+ function snake_case(name) {
+ var regexp = /[A-Z]/g;
+ var separator = '-';
+ return name.replace(regexp, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ /**
+ * Returns the actual instance of the $tooltip service.
+ * TODO support multiple triggers
+ */
+ this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
+ var openedTooltips = $$stackedMap.createNew();
+ $document.on('keyup', keypressListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keyup', keypressListener);
+ });
+
+ function keypressListener(e) {
+ if (e.which === 27) {
+ var last = openedTooltips.top();
+ if (last) {
+ last.value.close();
+ last = null;
+ }
+ }
+ }
+
+ return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
+ options = angular.extend({}, defaultOptions, globalOptions, options);
+
+ /**
+ * Returns an object of show and hide triggers.
+ *
+ * If a trigger is supplied,
+ * it is used to show the tooltip; otherwise, it will use the `trigger`
+ * option passed to the `$tooltipProvider.options` method; else it will
+ * default to the trigger supplied to this directive factory.
+ *
+ * The hide trigger is based on the show trigger. If the `trigger` option
+ * was passed to the `$tooltipProvider.options` method, it will use the
+ * mapped trigger from `triggerMap` or the passed trigger if the map is
+ * undefined; otherwise, it uses the `triggerMap` value of the show
+ * trigger; else it will just use the show trigger.
+ */
+ function getTriggers(trigger) {
+ var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
+ var hide = show.map(function(trigger) {
+ return triggerMap[trigger] || trigger;
+ });
+ return {
+ show: show,
+ hide: hide
+ };
+ }
+
+ var directiveName = snake_case(ttType);
+
+ var startSym = $interpolate.startSymbol();
+ var endSym = $interpolate.endSymbol();
+ var template =
+ '<div '+ directiveName + '-popup ' +
+ 'uib-title="' + startSym + 'title' + endSym + '" ' +
+ (options.useContentExp ?
+ 'content-exp="contentExp()" ' :
+ 'content="' + startSym + 'content' + endSym + '" ') +
+ 'origin-scope="origScope" ' +
+ 'class="uib-position-measure ' + prefix + '" ' +
+ 'tooltip-animation-class="fade"' +
+ 'uib-tooltip-classes ' +
+ 'ng-class="{ in: isOpen }" ' +
+ '>' +
+ '</div>';
+
+ return {
+ compile: function(tElem, tAttrs) {
+ var tooltipLinker = $compile(template);
+
+ return function link(scope, element, attrs, tooltipCtrl) {
+ var tooltip;
+ var tooltipLinkedScope;
+ var transitionTimeout;
+ var showTimeout;
+ var hideTimeout;
+ var positionTimeout;
+ var adjustmentTimeout;
+ var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
+ var triggers = getTriggers(undefined);
+ var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
+ var ttScope = scope.$new(true);
+ var repositionScheduled = false;
+ var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
+ var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
+ var observers = [];
+ var lastPlacement;
+
+ var positionTooltip = function() {
+ // check if tooltip exists and is not empty
+ if (!tooltip || !tooltip.html()) { return; }
+
+ if (!positionTimeout) {
+ positionTimeout = $timeout(function() {
+ var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
+ var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
+ var elementPos = appendToBody ? $position.offset(element) : $position.position(element);
+ tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
+ var placementClasses = ttPosition.placement.split('-');
+
+ if (!tooltip.hasClass(placementClasses[0])) {
+ tooltip.removeClass(lastPlacement.split('-')[0]);
+ tooltip.addClass(placementClasses[0]);
+ }
+
+ if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
+ tooltip.removeClass(options.placementClassPrefix + lastPlacement);
+ tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
+ }
+
+ adjustmentTimeout = $timeout(function() {
+ var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
+ var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
+ if (adjustment) {
+ tooltip.css(adjustment);
+ }
+ adjustmentTimeout = null;
+ }, 0, false);
+
+ // first time through tt element will have the
+ // uib-position-measure class or if the placement
+ // has changed we need to position the arrow.
+ if (tooltip.hasClass('uib-position-measure')) {
+ $position.positionArrow(tooltip, ttPosition.placement);
+ tooltip.removeClass('uib-position-measure');
+ } else if (lastPlacement !== ttPosition.placement) {
+ $position.positionArrow(tooltip, ttPosition.placement);
+ }
+ lastPlacement = ttPosition.placement;
+
+ positionTimeout = null;
+ }, 0, false);
+ }
+ };
+
+ // Set up the correct scope to allow transclusion later
+ ttScope.origScope = scope;
+
+ // By default, the tooltip is not open.
+ // TODO add ability to start tooltip opened
+ ttScope.isOpen = false;
+
+ function toggleTooltipBind() {
+ if (!ttScope.isOpen) {
+ showTooltipBind();
+ } else {
+ hideTooltipBind();
+ }
+ }
+
+ // Show the tooltip with delay if specified, otherwise show it immediately
+ function showTooltipBind() {
+ if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
+ return;
+ }
+
+ cancelHide();
+ prepareTooltip();
+
+ if (ttScope.popupDelay) {
+ // Do nothing if the tooltip was already scheduled to pop-up.
+ // This happens if show is triggered multiple times before any hide is triggered.
+ if (!showTimeout) {
+ showTimeout = $timeout(show, ttScope.popupDelay, false);
+ }
+ } else {
+ show();
+ }
+ }
+
+ function hideTooltipBind() {
+ cancelShow();
+
+ if (ttScope.popupCloseDelay) {
+ if (!hideTimeout) {
+ hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
+ }
+ } else {
+ hide();
+ }
+ }
+
+ // Show the tooltip popup element.
+ function show() {
+ cancelShow();
+ cancelHide();
+
+ // Don't show empty tooltips.
+ if (!ttScope.content) {
+ return angular.noop;
+ }
+
+ createTooltip();
+
+ // And show the tooltip.
+ ttScope.$evalAsync(function() {
+ ttScope.isOpen = true;
+ assignIsOpen(true);
+ positionTooltip();
+ });
+ }
+
+ function cancelShow() {
+ if (showTimeout) {
+ $timeout.cancel(showTimeout);
+ showTimeout = null;
+ }
+
+ if (positionTimeout) {
+ $timeout.cancel(positionTimeout);
+ positionTimeout = null;
+ }
+ }
+
+ // Hide the tooltip popup element.
+ function hide() {
+ if (!ttScope) {
+ return;
+ }
+
+ // First things first: we don't show it anymore.
+ ttScope.$evalAsync(function() {
+ if (ttScope) {
+ ttScope.isOpen = false;
+ assignIsOpen(false);
+ // And now we remove it from the DOM. However, if we have animation, we
+ // need to wait for it to expire beforehand.
+ // FIXME: this is a placeholder for a port of the transitions library.
+ // The fade transition in TWBS is 150ms.
+ if (ttScope.animation) {
+ if (!transitionTimeout) {
+ transitionTimeout = $timeout(removeTooltip, 150, false);
+ }
+ } else {
+ removeTooltip();
+ }
+ }
+ });
+ }
+
+ function cancelHide() {
+ if (hideTimeout) {
+ $timeout.cancel(hideTimeout);
+ hideTimeout = null;
+ }
+
+ if (transitionTimeout) {
+ $timeout.cancel(transitionTimeout);
+ transitionTimeout = null;
+ }
+ }
+
+ function createTooltip() {
+ // There can only be one tooltip element per directive shown at once.
+ if (tooltip) {
+ return;
+ }
+
+ tooltipLinkedScope = ttScope.$new();
+ tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {
+ if (appendToBody) {
+ $document.find('body').append(tooltip);
+ } else {
+ element.after(tooltip);
+ }
+ });
+
+ openedTooltips.add(ttScope, {
+ close: hide
+ });
+
+ prepObservers();
+ }
+
+ function removeTooltip() {
+ cancelShow();
+ cancelHide();
+ unregisterObservers();
+
+ if (tooltip) {
+ tooltip.remove();
+
+ tooltip = null;
+ if (adjustmentTimeout) {
+ $timeout.cancel(adjustmentTimeout);
+ }
+ }
+
+ openedTooltips.remove(ttScope);
+
+ if (tooltipLinkedScope) {
+ tooltipLinkedScope.$destroy();
+ tooltipLinkedScope = null;
+ }
+ }
+
+ /**
+ * Set the initial scope values. Once
+ * the tooltip is created, the observers
+ * will be added to keep things in sync.
+ */
+ function prepareTooltip() {
+ ttScope.title = attrs[prefix + 'Title'];
+ if (contentParse) {
+ ttScope.content = contentParse(scope);
+ } else {
+ ttScope.content = attrs[ttType];
+ }
+
+ ttScope.popupClass = attrs[prefix + 'Class'];
+ ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
+ var placement = $position.parsePlacement(ttScope.placement);
+ lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];
+
+ var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
+ var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
+ ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
+ ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
+ }
+
+ function assignIsOpen(isOpen) {
+ if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
+ isOpenParse.assign(scope, isOpen);
+ }
+ }
+
+ ttScope.contentExp = function() {
+ return ttScope.content;
+ };
+
+ /**
+ * Observe the relevant attributes.
+ */
+ attrs.$observe('disabled', function(val) {
+ if (val) {
+ cancelShow();
+ }
+
+ if (val && ttScope.isOpen) {
+ hide();
+ }
+ });
+
+ if (isOpenParse) {
+ scope.$watch(isOpenParse, function(val) {
+ if (ttScope && !val === ttScope.isOpen) {
+ toggleTooltipBind();
+ }
+ });
+ }
+
+ function prepObservers() {
+ observers.length = 0;
+
+ if (contentParse) {
+ observers.push(
+ scope.$watch(contentParse, function(val) {
+ ttScope.content = val;
+ if (!val && ttScope.isOpen) {
+ hide();
+ }
+ })
+ );
+
+ observers.push(
+ tooltipLinkedScope.$watch(function() {
+ if (!repositionScheduled) {
+ repositionScheduled = true;
+ tooltipLinkedScope.$$postDigest(function() {
+ repositionScheduled = false;
+ if (ttScope && ttScope.isOpen) {
+ positionTooltip();
+ }
+ });
+ }
+ })
+ );
+ } else {
+ observers.push(
+ attrs.$observe(ttType, function(val) {
+ ttScope.content = val;
+ if (!val && ttScope.isOpen) {
+ hide();
+ } else {
+ positionTooltip();
+ }
+ })
+ );
+ }
+
+ observers.push(
+ attrs.$observe(prefix + 'Title', function(val) {
+ ttScope.title = val;
+ if (ttScope.isOpen) {
+ positionTooltip();
+ }
+ })
+ );
+
+ observers.push(
+ attrs.$observe(prefix + 'Placement', function(val) {
+ ttScope.placement = val ? val : options.placement;
+ if (ttScope.isOpen) {
+ positionTooltip();
+ }
+ })
+ );
+ }
+
+ function unregisterObservers() {
+ if (observers.length) {
+ angular.forEach(observers, function(observer) {
+ observer();
+ });
+ observers.length = 0;
+ }
+ }
+
+ // hide tooltips/popovers for outsideClick trigger
+ function bodyHideTooltipBind(e) {
+ if (!ttScope || !ttScope.isOpen || !tooltip) {
+ return;
+ }
+ // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
+ if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
+ hideTooltipBind();
+ }
+ }
+
+ // KeyboardEvent handler to hide the tooltip on Escape key press
+ function hideOnEscapeKey(e) {
+ if (e.which === 27) {
+ hideTooltipBind();
+ }
+ }
+
+ var unregisterTriggers = function() {
+ triggers.show.forEach(function(trigger) {
+ if (trigger === 'outsideClick') {
+ element.off('click', toggleTooltipBind);
+ } else {
+ element.off(trigger, showTooltipBind);
+ element.off(trigger, toggleTooltipBind);
+ }
+ element.off('keypress', hideOnEscapeKey);
+ });
+ triggers.hide.forEach(function(trigger) {
+ if (trigger === 'outsideClick') {
+ $document.off('click', bodyHideTooltipBind);
+ } else {
+ element.off(trigger, hideTooltipBind);
+ }
+ });
+ };
+
+ function prepTriggers() {
+ var showTriggers = [], hideTriggers = [];
+ var val = scope.$eval(attrs[prefix + 'Trigger']);
+ unregisterTriggers();
+
+ if (angular.isObject(val)) {
+ Object.keys(val).forEach(function(key) {
+ showTriggers.push(key);
+ hideTriggers.push(val[key]);
+ });
+ triggers = {
+ show: showTriggers,
+ hide: hideTriggers
+ };
+ } else {
+ triggers = getTriggers(val);
+ }
+
+ if (triggers.show !== 'none') {
+ triggers.show.forEach(function(trigger, idx) {
+ if (trigger === 'outsideClick') {
+ element.on('click', toggleTooltipBind);
+ $document.on('click', bodyHideTooltipBind);
+ } else if (trigger === triggers.hide[idx]) {
+ element.on(trigger, toggleTooltipBind);
+ } else if (trigger) {
+ element.on(trigger, showTooltipBind);
+ element.on(triggers.hide[idx], hideTooltipBind);
+ }
+ element.on('keypress', hideOnEscapeKey);
+ });
+ }
+ }
+
+ prepTriggers();
+
+ var animation = scope.$eval(attrs[prefix + 'Animation']);
+ ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;
+
+ var appendToBodyVal;
+ var appendKey = prefix + 'AppendToBody';
+ if (appendKey in attrs && attrs[appendKey] === undefined) {
+ appendToBodyVal = true;
+ } else {
+ appendToBodyVal = scope.$eval(attrs[appendKey]);
+ }
+
+ appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;
+
+ // Make sure tooltip is destroyed and removed.
+ scope.$on('$destroy', function onDestroyTooltip() {
+ unregisterTriggers();
+ removeTooltip();
+ ttScope = null;
+ });
+ };
+ }
+ };
+ };
+ }];
+})
+
+// This is mostly ngInclude code but with a custom scope
+.directive('uibTooltipTemplateTransclude', [
+ '$animate', '$sce', '$compile', '$templateRequest',
+function ($animate, $sce, $compile, $templateRequest) {
+ return {
+ link: function(scope, elem, attrs) {
+ var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);
+
+ var changeCounter = 0,
+ currentScope,
+ previousElement,
+ currentElement;
+
+ var cleanupLastIncludeContent = function() {
+ if (previousElement) {
+ previousElement.remove();
+ previousElement = null;
+ }
+
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+
+ if (currentElement) {
+ $animate.leave(currentElement).then(function() {
+ previousElement = null;
+ });
+ previousElement = currentElement;
+ currentElement = null;
+ }
+ };
+
+ scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {
+ var thisChangeId = ++changeCounter;
+
+ if (src) {
+ //set the 2nd param to true to ignore the template request error so that the inner
+ //contents and scope can be cleaned up.
+ $templateRequest(src, true).then(function(response) {
+ if (thisChangeId !== changeCounter) { return; }
+ var newScope = origScope.$new();
+ var template = response;
+
+ var clone = $compile(template)(newScope, function(clone) {
+ cleanupLastIncludeContent();
+ $animate.enter(clone, elem);
+ });
+
+ currentScope = newScope;
+ currentElement = clone;
+
+ currentScope.$emit('$includeContentLoaded', src);
+ }, function() {
+ if (thisChangeId === changeCounter) {
+ cleanupLastIncludeContent();
+ scope.$emit('$includeContentError', src);
+ }
+ });
+ scope.$emit('$includeContentRequested', src);
+ } else {
+ cleanupLastIncludeContent();
+ }
+ });
+
+ scope.$on('$destroy', cleanupLastIncludeContent);
+ }
+ };
+}])
+
+/**
+ * Note that it's intentional that these classes are *not* applied through $animate.
+ * They must not be animated as they're expected to be present on the tooltip on
+ * initialization.
+ */
+.directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ // need to set the primary position so the
+ // arrow has space during position measure.
+ // tooltip.positionTooltip()
+ if (scope.placement) {
+ // // There are no top-left etc... classes
+ // // in TWBS, so we need the primary position.
+ var position = $uibPosition.parsePlacement(scope.placement);
+ element.addClass(position[0]);
+ }
+
+ if (scope.popupClass) {
+ element.addClass(scope.popupClass);
+ }
+
+ if (scope.animation) {
+ element.addClass(attrs.tooltipAnimationClass);
+ }
+ }
+ };
+}])
+
+.directive('uibTooltipPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { content: '@' },
+ templateUrl: 'uib/template/tooltip/tooltip-popup.html'
+ };
+})
+
+.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
+}])
+
+.directive('uibTooltipTemplatePopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&', originScope: '&' },
+ templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
+ };
+})
+
+.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibTooltipHtmlPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&' },
+ templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
+ };
+})
+
+.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
+ useContentExp: true
+ });
+}]);
+
+/**
+ * The following features are still outstanding: popup delay, animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, and selector delegatation.
+ */
+angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
+
+.directive('uibPopoverTemplatePopup', function() {
+ return {
+ restrict: 'A',
+ scope: { uibTitle: '@', contentExp: '&', originScope: '&' },
+ templateUrl: 'uib/template/popover/popover-template.html'
+ };
+})
+
+.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibPopoverHtmlPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&', uibTitle: '@' },
+ templateUrl: 'uib/template/popover/popover-html.html'
+ };
+})
+
+.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibPopoverPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { uibTitle: '@', content: '@' },
+ templateUrl: 'uib/template/popover/popover.html'
+ };
+})
+
+.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopover', 'popover', 'click');
+}]);
+
+angular.module('ui.bootstrap.progressbar', [])
+
+.constant('uibProgressConfig', {
+ animate: true,
+ max: 100
+})
+
+.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {
+ var self = this,
+ animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
+
+ this.bars = [];
+ $scope.max = getMaxOrDefault();
+
+ this.addBar = function(bar, element, attrs) {
+ if (!animate) {
+ element.css({'transition': 'none'});
+ }
+
+ this.bars.push(bar);
+
+ bar.max = getMaxOrDefault();
+ bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';
+
+ bar.$watch('value', function(value) {
+ bar.recalculatePercentage();
+ });
+
+ bar.recalculatePercentage = function() {
+ var totalPercentage = self.bars.reduce(function(total, bar) {
+ bar.percent = +(100 * bar.value / bar.max).toFixed(2);
+ return total + bar.percent;
+ }, 0);
+
+ if (totalPercentage > 100) {
+ bar.percent -= totalPercentage - 100;
+ }
+ };
+
+ bar.$on('$destroy', function() {
+ element = null;
+ self.removeBar(bar);
+ });
+ };
+
+ this.removeBar = function(bar) {
+ this.bars.splice(this.bars.indexOf(bar), 1);
+ this.bars.forEach(function (bar) {
+ bar.recalculatePercentage();
+ });
+ };
+
+ //$attrs.$observe('maxParam', function(maxParam) {
+ $scope.$watch('maxParam', function(maxParam) {
+ self.bars.forEach(function(bar) {
+ bar.max = getMaxOrDefault();
+ bar.recalculatePercentage();
+ });
+ });
+
+ function getMaxOrDefault () {
+ return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;
+ }
+}])
+
+.directive('uibProgress', function() {
+ return {
+ replace: true,
+ transclude: true,
+ controller: 'UibProgressController',
+ require: 'uibProgress',
+ scope: {
+ maxParam: '=?max'
+ },
+ templateUrl: 'uib/template/progressbar/progress.html'
+ };
+})
+
+.directive('uibBar', function() {
+ return {
+ replace: true,
+ transclude: true,
+ require: '^uibProgress',
+ scope: {
+ value: '=',
+ type: '@'
+ },
+ templateUrl: 'uib/template/progressbar/bar.html',
+ link: function(scope, element, attrs, progressCtrl) {
+ progressCtrl.addBar(scope, element, attrs);
+ }
+ };
+})
+
+.directive('uibProgressbar', function() {
+ return {
+ replace: true,
+ transclude: true,
+ controller: 'UibProgressController',
+ scope: {
+ value: '=',
+ maxParam: '=?max',
+ type: '@'
+ },
+ templateUrl: 'uib/template/progressbar/progressbar.html',
+ link: function(scope, element, attrs, progressCtrl) {
+ progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
+ }
+ };
+});
+
+angular.module('ui.bootstrap.rating', [])
+
+.constant('uibRatingConfig', {
+ max: 5,
+ stateOn: null,
+ stateOff: null,
+ enableReset: true,
+ titles: ['one', 'two', 'three', 'four', 'five']
+})
+
+.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {
+ var ngModelCtrl = { $setViewValue: angular.noop },
+ self = this;
+
+ this.init = function(ngModelCtrl_) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelCtrl.$render = this.render;
+
+ ngModelCtrl.$formatters.push(function(value) {
+ if (angular.isNumber(value) && value << 0 !== value) {
+ value = Math.round(value);
+ }
+
+ return value;
+ });
+
+ this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
+ this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
+ this.enableReset = angular.isDefined($attrs.enableReset) ?
+ $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;
+ var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;
+ this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
+ tmpTitles : ratingConfig.titles;
+
+ var ratingStates = angular.isDefined($attrs.ratingStates) ?
+ $scope.$parent.$eval($attrs.ratingStates) :
+ new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);
+ $scope.range = this.buildTemplateObjects(ratingStates);
+ };
+
+ this.buildTemplateObjects = function(states) {
+ for (var i = 0, n = states.length; i < n; i++) {
+ states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
+ }
+ return states;
+ };
+
+ this.getTitle = function(index) {
+ if (index >= this.titles.length) {
+ return index + 1;
+ }
+
+ return this.titles[index];
+ };
+
+ $scope.rate = function(value) {
+ if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
+ var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;
+ ngModelCtrl.$setViewValue(newViewValue);
+ ngModelCtrl.$render();
+ }
+ };
+
+ $scope.enter = function(value) {
+ if (!$scope.readonly) {
+ $scope.value = value;
+ }
+ $scope.onHover({value: value});
+ };
+
+ $scope.reset = function() {
+ $scope.value = ngModelCtrl.$viewValue;
+ $scope.onLeave();
+ };
+
+ $scope.onKeydown = function(evt) {
+ if (/(37|38|39|40)/.test(evt.which)) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
+ }
+ };
+
+ this.render = function() {
+ $scope.value = ngModelCtrl.$viewValue;
+ $scope.title = self.getTitle($scope.value - 1);
+ };
+}])
+
+.directive('uibRating', function() {
+ return {
+ require: ['uibRating', 'ngModel'],
+ restrict: 'A',
+ scope: {
+ readonly: '=?readOnly',
+ onHover: '&',
+ onLeave: '&'
+ },
+ controller: 'UibRatingController',
+ templateUrl: 'uib/template/rating/rating.html',
+ link: function(scope, element, attrs, ctrls) {
+ var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+ ratingCtrl.init(ngModelCtrl);
+ }
+ };
+});
+
+angular.module('ui.bootstrap.tabs', [])
+
+.controller('UibTabsetController', ['$scope', function ($scope) {
+ var ctrl = this,
+ oldIndex;
+ ctrl.tabs = [];
+
+ ctrl.select = function(index, evt) {
+ if (!destroyed) {
+ var previousIndex = findTabIndex(oldIndex);
+ var previousSelected = ctrl.tabs[previousIndex];
+ if (previousSelected) {
+ previousSelected.tab.onDeselect({
+ $event: evt,
+ $selectedIndex: index
+ });
+ if (evt && evt.isDefaultPrevented()) {
+ return;
+ }
+ previousSelected.tab.active = false;
+ }
+
+ var selected = ctrl.tabs[index];
+ if (selected) {
+ selected.tab.onSelect({
+ $event: evt
+ });
+ selected.tab.active = true;
+ ctrl.active = selected.index;
+ oldIndex = selected.index;
+ } else if (!selected && angular.isDefined(oldIndex)) {
+ ctrl.active = null;
+ oldIndex = null;
+ }
+ }
+ };
+
+ ctrl.addTab = function addTab(tab) {
+ ctrl.tabs.push({
+ tab: tab,
+ index: tab.index
+ });
+ ctrl.tabs.sort(function(t1, t2) {
+ if (t1.index > t2.index) {
+ return 1;
+ }
+
+ if (t1.index < t2.index) {
+ return -1;
+ }
+
+ return 0;
+ });
+
+ if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
+ var newActiveIndex = findTabIndex(tab.index);
+ ctrl.select(newActiveIndex);
+ }
+ };
+
+ ctrl.removeTab = function removeTab(tab) {
+ var index;
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].tab === tab) {
+ index = i;
+ break;
+ }
+ }
+
+ if (ctrl.tabs[index].index === ctrl.active) {
+ var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
+ index - 1 : index + 1 % ctrl.tabs.length;
+ ctrl.select(newActiveTabIndex);
+ }
+
+ ctrl.tabs.splice(index, 1);
+ };
+
+ $scope.$watch('tabset.active', function(val) {
+ if (angular.isDefined(val) && val !== oldIndex) {
+ ctrl.select(findTabIndex(val));
+ }
+ });
+
+ var destroyed;
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ });
+
+ function findTabIndex(index) {
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].index === index) {
+ return i;
+ }
+ }
+ }
+}])
+
+.directive('uibTabset', function() {
+ return {
+ transclude: true,
+ replace: true,
+ scope: {},
+ bindToController: {
+ active: '=?',
+ type: '@'
+ },
+ controller: 'UibTabsetController',
+ controllerAs: 'tabset',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tabset.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.vertical = angular.isDefined(attrs.vertical) ?
+ scope.$parent.$eval(attrs.vertical) : false;
+ scope.justified = angular.isDefined(attrs.justified) ?
+ scope.$parent.$eval(attrs.justified) : false;
+ }
+ };
+})
+
+.directive('uibTab', ['$parse', function($parse) {
+ return {
+ require: '^uibTabset',
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tab.html';
+ },
+ transclude: true,
+ scope: {
+ heading: '@',
+ index: '=?',
+ classes: '@?',
+ onSelect: '&select', //This callback is called in contentHeadingTransclude
+ //once it inserts the tab's content into the dom
+ onDeselect: '&deselect'
+ },
+ controller: function() {
+ //Empty controller so other directives can require being 'under' a tab
+ },
+ controllerAs: 'tab',
+ link: function(scope, elm, attrs, tabsetCtrl, transclude) {
+ scope.disabled = false;
+ if (attrs.disable) {
+ scope.$parent.$watch($parse(attrs.disable), function(value) {
+ scope.disabled = !! value;
+ });
+ }
+
+ if (angular.isUndefined(attrs.index)) {
+ if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
+ scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;
+ } else {
+ scope.index = 0;
+ }
+ }
+
+ if (angular.isUndefined(attrs.classes)) {
+ scope.classes = '';
+ }
+
+ scope.select = function(evt) {
+ if (!scope.disabled) {
+ var index;
+ for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
+ if (tabsetCtrl.tabs[i].tab === scope) {
+ index = i;
+ break;
+ }
+ }
+
+ tabsetCtrl.select(index, evt);
+ }
+ };
+
+ tabsetCtrl.addTab(scope);
+ scope.$on('$destroy', function() {
+ tabsetCtrl.removeTab(scope);
+ });
+
+ //We need to transclude later, once the content container is ready.
+ //when this link happens, we're inside a tab heading.
+ scope.$transcludeFn = transclude;
+ }
+ };
+}])
+
+.directive('uibTabHeadingTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTab',
+ link: function(scope, elm) {
+ scope.$watch('headingElement', function updateHeadingElement(heading) {
+ if (heading) {
+ elm.html('');
+ elm.append(heading);
+ }
+ });
+ }
+ };
+})
+
+.directive('uibTabContentTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTabset',
+ link: function(scope, elm, attrs) {
+ var tab = scope.$eval(attrs.uibTabContentTransclude).tab;
+
+ //Now our tab is ready to be transcluded: both the tab heading area
+ //and the tab content area are loaded. Transclude 'em both.
+ tab.$transcludeFn(tab.$parent, function(contents) {
+ angular.forEach(contents, function(node) {
+ if (isTabHeading(node)) {
+ //Let tabHeadingTransclude know.
+ tab.headingElement = node;
+ } else {
+ elm.append(node);
+ }
+ });
+ });
+ }
+ };
+
+ function isTabHeading(node) {
+ return node.tagName && (
+ node.hasAttribute('uib-tab-heading') ||
+ node.hasAttribute('data-uib-tab-heading') ||
+ node.hasAttribute('x-uib-tab-heading') ||
+ node.tagName.toLowerCase() === 'uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'uib:tab-heading'
+ );
+ }
+});
+
+angular.module('ui.bootstrap.timepicker', [])
+
+.constant('uibTimepickerConfig', {
+ hourStep: 1,
+ minuteStep: 1,
+ secondStep: 1,
+ showMeridian: true,
+ showSeconds: false,
+ meridians: null,
+ readonlyInput: false,
+ mousewheel: true,
+ arrowkeys: true,
+ showSpinners: true,
+ templateUrl: 'uib/template/timepicker/timepicker.html'
+})
+
+.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
+ var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
+ var selected = new Date(),
+ watchers = [],
+ ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
+ meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,
+ padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;
+
+ $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
+ $element.removeAttr('tabindex');
+
+ this.init = function(ngModelCtrl_, inputs) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelCtrl.$render = this.render;
+
+ ngModelCtrl.$formatters.unshift(function(modelValue) {
+ return modelValue ? new Date(modelValue) : null;
+ });
+
+ var hoursInputEl = inputs.eq(0),
+ minutesInputEl = inputs.eq(1),
+ secondsInputEl = inputs.eq(2);
+
+ hoursModelCtrl = hoursInputEl.controller('ngModel');
+ minutesModelCtrl = minutesInputEl.controller('ngModel');
+ secondsModelCtrl = secondsInputEl.controller('ngModel');
+
+ var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
+
+ if (mousewheel) {
+ this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ }
+
+ var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
+ if (arrowkeys) {
+ this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ }
+
+ $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
+ this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ };
+
+ var hourStep = timepickerConfig.hourStep;
+ if ($attrs.hourStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function(value) {
+ hourStep = +value;
+ }));
+ }
+
+ var minuteStep = timepickerConfig.minuteStep;
+ if ($attrs.minuteStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
+ minuteStep = +value;
+ }));
+ }
+
+ var min;
+ watchers.push($scope.$parent.$watch($parse($attrs.min), function(value) {
+ var dt = new Date(value);
+ min = isNaN(dt) ? undefined : dt;
+ }));
+
+ var max;
+ watchers.push($scope.$parent.$watch($parse($attrs.max), function(value) {
+ var dt = new Date(value);
+ max = isNaN(dt) ? undefined : dt;
+ }));
+
+ var disabled = false;
+ if ($attrs.ngDisabled) {
+ watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
+ disabled = value;
+ }));
+ }
+
+ $scope.noIncrementHours = function() {
+ var incrementedSelected = addMinutes(selected, hourStep * 60);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementHours = function() {
+ var decrementedSelected = addMinutes(selected, -hourStep * 60);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noIncrementMinutes = function() {
+ var incrementedSelected = addMinutes(selected, minuteStep);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementMinutes = function() {
+ var decrementedSelected = addMinutes(selected, -minuteStep);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noIncrementSeconds = function() {
+ var incrementedSelected = addSeconds(selected, secondStep);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementSeconds = function() {
+ var decrementedSelected = addSeconds(selected, -secondStep);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noToggleMeridian = function() {
+ if (selected.getHours() < 12) {
+ return disabled || addMinutes(selected, 12 * 60) > max;
+ }
+
+ return disabled || addMinutes(selected, -12 * 60) < min;
+ };
+
+ var secondStep = timepickerConfig.secondStep;
+ if ($attrs.secondStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function(value) {
+ secondStep = +value;
+ }));
+ }
+
+ $scope.showSeconds = timepickerConfig.showSeconds;
+ if ($attrs.showSeconds) {
+ watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
+ $scope.showSeconds = !!value;
+ }));
+ }
+
+ // 12H / 24H mode
+ $scope.showMeridian = timepickerConfig.showMeridian;
+ if ($attrs.showMeridian) {
+ watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
+ $scope.showMeridian = !!value;
+
+ if (ngModelCtrl.$error.time) {
+ // Evaluate from template
+ var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
+ if (angular.isDefined(hours) && angular.isDefined(minutes)) {
+ selected.setHours(hours);
+ refresh();
+ }
+ } else {
+ updateTemplate();
+ }
+ }));
+ }
+
+ // Get $scope.hours in 24H mode if valid
+ function getHoursFromTemplate() {
+ var hours = +$scope.hours;
+ var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
+ hours >= 0 && hours < 24;
+ if (!valid || $scope.hours === '') {
+ return undefined;
+ }
+
+ if ($scope.showMeridian) {
+ if (hours === 12) {
+ hours = 0;
+ }
+ if ($scope.meridian === meridians[1]) {
+ hours = hours + 12;
+ }
+ }
+ return hours;
+ }
+
+ function getMinutesFromTemplate() {
+ var minutes = +$scope.minutes;
+ var valid = minutes >= 0 && minutes < 60;
+ if (!valid || $scope.minutes === '') {
+ return undefined;
+ }
+ return minutes;
+ }
+
+ function getSecondsFromTemplate() {
+ var seconds = +$scope.seconds;
+ return seconds >= 0 && seconds < 60 ? seconds : undefined;
+ }
+
+ function pad(value, noPad) {
+ if (value === null) {
+ return '';
+ }
+
+ return angular.isDefined(value) && value.toString().length < 2 && !noPad ?
+ '0' + value : value.toString();
+ }
+
+ // Respond on mousewheel spin
+ this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ var isScrollingUp = function(e) {
+ if (e.originalEvent) {
+ e = e.originalEvent;
+ }
+ //pick correct delta variable depending on event
+ var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;
+ return e.detail || delta > 0;
+ };
+
+ hoursInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
+ }
+ e.preventDefault();
+ });
+
+ minutesInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
+ }
+ e.preventDefault();
+ });
+
+ secondsInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
+ }
+ e.preventDefault();
+ });
+ };
+
+ // Respond on up/down arrowkeys
+ this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ hoursInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementHours();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementHours();
+ $scope.$apply();
+ }
+ }
+ });
+
+ minutesInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementMinutes();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementMinutes();
+ $scope.$apply();
+ }
+ }
+ });
+
+ secondsInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementSeconds();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementSeconds();
+ $scope.$apply();
+ }
+ }
+ });
+ };
+
+ this.setupInputEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ if ($scope.readonlyInput) {
+ $scope.updateHours = angular.noop;
+ $scope.updateMinutes = angular.noop;
+ $scope.updateSeconds = angular.noop;
+ return;
+ }
+
+ var invalidate = function(invalidHours, invalidMinutes, invalidSeconds) {
+ ngModelCtrl.$setViewValue(null);
+ ngModelCtrl.$setValidity('time', false);
+ if (angular.isDefined(invalidHours)) {
+ $scope.invalidHours = invalidHours;
+ if (hoursModelCtrl) {
+ hoursModelCtrl.$setValidity('hours', false);
+ }
+ }
+
+ if (angular.isDefined(invalidMinutes)) {
+ $scope.invalidMinutes = invalidMinutes;
+ if (minutesModelCtrl) {
+ minutesModelCtrl.$setValidity('minutes', false);
+ }
+ }
+
+ if (angular.isDefined(invalidSeconds)) {
+ $scope.invalidSeconds = invalidSeconds;
+ if (secondsModelCtrl) {
+ secondsModelCtrl.$setValidity('seconds', false);
+ }
+ }
+ };
+
+ $scope.updateHours = function() {
+ var hours = getHoursFromTemplate(),
+ minutes = getMinutesFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(hours) && angular.isDefined(minutes)) {
+ selected.setHours(hours);
+ selected.setMinutes(minutes);
+ if (selected < min || selected > max) {
+ invalidate(true);
+ } else {
+ refresh('h');
+ }
+ } else {
+ invalidate(true);
+ }
+ };
+
+ hoursInputEl.on('blur', function(e) {
+ ngModelCtrl.$setTouched();
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if ($scope.hours === null || $scope.hours === '') {
+ invalidate(true);
+ } else if (!$scope.invalidHours && $scope.hours < 10) {
+ $scope.$apply(function() {
+ $scope.hours = pad($scope.hours, !padHours);
+ });
+ }
+ });
+
+ $scope.updateMinutes = function() {
+ var minutes = getMinutesFromTemplate(),
+ hours = getHoursFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(minutes) && angular.isDefined(hours)) {
+ selected.setHours(hours);
+ selected.setMinutes(minutes);
+ if (selected < min || selected > max) {
+ invalidate(undefined, true);
+ } else {
+ refresh('m');
+ }
+ } else {
+ invalidate(undefined, true);
+ }
+ };
+
+ minutesInputEl.on('blur', function(e) {
+ ngModelCtrl.$setTouched();
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if ($scope.minutes === null) {
+ invalidate(undefined, true);
+ } else if (!$scope.invalidMinutes && $scope.minutes < 10) {
+ $scope.$apply(function() {
+ $scope.minutes = pad($scope.minutes);
+ });
+ }
+ });
+
+ $scope.updateSeconds = function() {
+ var seconds = getSecondsFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(seconds)) {
+ selected.setSeconds(seconds);
+ refresh('s');
+ } else {
+ invalidate(undefined, undefined, true);
+ }
+ };
+
+ secondsInputEl.on('blur', function(e) {
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if (!$scope.invalidSeconds && $scope.seconds < 10) {
+ $scope.$apply( function() {
+ $scope.seconds = pad($scope.seconds);
+ });
+ }
+ });
+
+ };
+
+ this.render = function() {
+ var date = ngModelCtrl.$viewValue;
+
+ if (isNaN(date)) {
+ ngModelCtrl.$setValidity('time', false);
+ $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
+ } else {
+ if (date) {
+ selected = date;
+ }
+
+ if (selected < min || selected > max) {
+ ngModelCtrl.$setValidity('time', false);
+ $scope.invalidHours = true;
+ $scope.invalidMinutes = true;
+ } else {
+ makeValid();
+ }
+ updateTemplate();
+ }
+ };
+
+ // Call internally when we know that model is valid.
+ function refresh(keyboardChange) {
+ makeValid();
+ ngModelCtrl.$setViewValue(new Date(selected));
+ updateTemplate(keyboardChange);
+ }
+
+ function makeValid() {
+ if (hoursModelCtrl) {
+ hoursModelCtrl.$setValidity('hours', true);
+ }
+
+ if (minutesModelCtrl) {
+ minutesModelCtrl.$setValidity('minutes', true);
+ }
+
+ if (secondsModelCtrl) {
+ secondsModelCtrl.$setValidity('seconds', true);
+ }
+
+ ngModelCtrl.$setValidity('time', true);
+ $scope.invalidHours = false;
+ $scope.invalidMinutes = false;
+ $scope.invalidSeconds = false;
+ }
+
+ function updateTemplate(keyboardChange) {
+ if (!ngModelCtrl.$modelValue) {
+ $scope.hours = null;
+ $scope.minutes = null;
+ $scope.seconds = null;
+ $scope.meridian = meridians[0];
+ } else {
+ var hours = selected.getHours(),
+ minutes = selected.getMinutes(),
+ seconds = selected.getSeconds();
+
+ if ($scope.showMeridian) {
+ hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system
+ }
+
+ $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);
+ if (keyboardChange !== 'm') {
+ $scope.minutes = pad(minutes);
+ }
+ $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
+
+ if (keyboardChange !== 's') {
+ $scope.seconds = pad(seconds);
+ }
+ $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
+ }
+ }
+
+ function addSecondsToSelected(seconds) {
+ selected = addSeconds(selected, seconds);
+ refresh();
+ }
+
+ function addMinutes(selected, minutes) {
+ return addSeconds(selected, minutes*60);
+ }
+
+ function addSeconds(date, seconds) {
+ var dt = new Date(date.getTime() + seconds * 1000);
+ var newDate = new Date(date);
+ newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());
+ return newDate;
+ }
+
+ function modelIsEmpty() {
+ return ($scope.hours === null || $scope.hours === '') &&
+ ($scope.minutes === null || $scope.minutes === '') &&
+ (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));
+ }
+
+ $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
+ $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;
+
+ $scope.incrementHours = function() {
+ if (!$scope.noIncrementHours()) {
+ addSecondsToSelected(hourStep * 60 * 60);
+ }
+ };
+
+ $scope.decrementHours = function() {
+ if (!$scope.noDecrementHours()) {
+ addSecondsToSelected(-hourStep * 60 * 60);
+ }
+ };
+
+ $scope.incrementMinutes = function() {
+ if (!$scope.noIncrementMinutes()) {
+ addSecondsToSelected(minuteStep * 60);
+ }
+ };
+
+ $scope.decrementMinutes = function() {
+ if (!$scope.noDecrementMinutes()) {
+ addSecondsToSelected(-minuteStep * 60);
+ }
+ };
+
+ $scope.incrementSeconds = function() {
+ if (!$scope.noIncrementSeconds()) {
+ addSecondsToSelected(secondStep);
+ }
+ };
+
+ $scope.decrementSeconds = function() {
+ if (!$scope.noDecrementSeconds()) {
+ addSecondsToSelected(-secondStep);
+ }
+ };
+
+ $scope.toggleMeridian = function() {
+ var minutes = getMinutesFromTemplate(),
+ hours = getHoursFromTemplate();
+
+ if (!$scope.noToggleMeridian()) {
+ if (angular.isDefined(minutes) && angular.isDefined(hours)) {
+ addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));
+ } else {
+ $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];
+ }
+ }
+ };
+
+ $scope.blur = function() {
+ ngModelCtrl.$setTouched();
+ };
+
+ $scope.$on('$destroy', function() {
+ while (watchers.length) {
+ watchers.shift()();
+ }
+ });
+}])
+
+.directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {
+ return {
+ require: ['uibTimepicker', '?^ngModel'],
+ restrict: 'A',
+ controller: 'UibTimepickerController',
+ controllerAs: 'timepicker',
+ scope: {},
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || uibTimepickerConfig.templateUrl;
+ },
+ link: function(scope, element, attrs, ctrls) {
+ var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (ngModelCtrl) {
+ timepickerCtrl.init(ngModelCtrl, element.find('input'));
+ }
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])
+
+/**
+ * A helper service that can parse typeahead's syntax (string provided by users)
+ * Extracted to a separate service for ease of unit testing
+ */
+ .factory('uibTypeaheadParser', ['$parse', function($parse) {
+ // 000001111111100000000000002222222200000000000000003333333333333330000000000044444444000
+ var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
+ return {
+ parse: function(input) {
+ var match = input.match(TYPEAHEAD_REGEXP);
+ if (!match) {
+ throw new Error(
+ 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
+ ' but got "' + input + '".');
+ }
+
+ return {
+ itemName: match[3],
+ source: $parse(match[4]),
+ viewMapper: $parse(match[2] || match[1]),
+ modelMapper: $parse(match[1])
+ };
+ }
+ };
+ }])
+
+ .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',
+ function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {
+ var HOT_KEYS = [9, 13, 27, 38, 40];
+ var eventDebounceTime = 200;
+ var modelCtrl, ngModelOptions;
+ //SUPPORTED ATTRIBUTES (OPTIONS)
+
+ //minimal no of characters that needs to be entered before typeahead kicks-in
+ var minLength = originalScope.$eval(attrs.typeaheadMinLength);
+ if (!minLength && minLength !== 0) {
+ minLength = 1;
+ }
+
+ originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
+ minLength = !newVal && newVal !== 0 ? 1 : newVal;
+ });
+
+ //minimal wait time after last character typed before typeahead kicks-in
+ var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
+
+ //should it restrict model values to the ones selected from the popup only?
+ var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
+ originalScope.$watch(attrs.typeaheadEditable, function (newVal) {
+ isEditable = newVal !== false;
+ });
+
+ //binding to a variable that indicates if matches are being retrieved asynchronously
+ var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
+
+ //a function to determine if an event should cause selection
+ var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function(scope, vals) {
+ var evt = vals.$event;
+ return evt.which === 13 || evt.which === 9;
+ };
+
+ //a callback executed when a match is selected
+ var onSelectCallback = $parse(attrs.typeaheadOnSelect);
+
+ //should it select highlighted popup value when losing focus?
+ var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;
+
+ //binding to a variable that indicates if there were no results after the query is completed
+ var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;
+
+ var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
+
+ var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;
+
+ var appendTo = attrs.typeaheadAppendTo ?
+ originalScope.$eval(attrs.typeaheadAppendTo) : null;
+
+ var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;
+
+ //If input matches an item of the list exactly, select it automatically
+ var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;
+
+ //binding to a variable that indicates if dropdown is open
+ var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;
+
+ var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;
+
+ //INTERNAL VARIABLES
+
+ //model setter executed upon match selection
+ var parsedModel = $parse(attrs.ngModel);
+ var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');
+ var $setModelValue = function(scope, newValue) {
+ if (angular.isFunction(parsedModel(originalScope)) &&
+ ngModelOptions.getOption('getterSetter')) {
+ return invokeModelSetter(scope, {$$$p: newValue});
+ }
+
+ return parsedModel.assign(scope, newValue);
+ };
+
+ //expressions used by typeahead
+ var parserResult = typeaheadParser.parse(attrs.uibTypeahead);
+
+ var hasFocus;
+
+ //Used to avoid bug in iOS webview where iOS keyboard does not fire
+ //mousedown & mouseup events
+ //Issue #3699
+ var selected;
+
+ //create a child scope for the typeahead directive so we are not polluting original scope
+ //with typeahead-specific data (matches, query etc.)
+ var scope = originalScope.$new();
+ var offDestroy = originalScope.$on('$destroy', function() {
+ scope.$destroy();
+ });
+ scope.$on('$destroy', offDestroy);
+
+ // WAI-ARIA
+ var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
+ element.attr({
+ 'aria-autocomplete': 'list',
+ 'aria-expanded': false,
+ 'aria-owns': popupId
+ });
+
+ var inputsContainer, hintInputElem;
+ //add read-only input to show hint
+ if (showHint) {
+ inputsContainer = angular.element('<div></div>');
+ inputsContainer.css('position', 'relative');
+ element.after(inputsContainer);
+ hintInputElem = element.clone();
+ hintInputElem.attr('placeholder', '');
+ hintInputElem.attr('tabindex', '-1');
+ hintInputElem.val('');
+ hintInputElem.css({
+ 'position': 'absolute',
+ 'top': '0px',
+ 'left': '0px',
+ 'border-color': 'transparent',
+ 'box-shadow': 'none',
+ 'opacity': 1,
+ 'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',
+ 'color': '#999'
+ });
+ element.css({
+ 'position': 'relative',
+ 'vertical-align': 'top',
+ 'background-color': 'transparent'
+ });
+
+ if (hintInputElem.attr('id')) {
+ hintInputElem.removeAttr('id'); // remove duplicate id if present.
+ }
+ inputsContainer.append(hintInputElem);
+ hintInputElem.after(element);
+ }
+
+ //pop-up element used to display matches
+ var popUpEl = angular.element('<div uib-typeahead-popup></div>');
+ popUpEl.attr({
+ id: popupId,
+ matches: 'matches',
+ active: 'activeIdx',
+ select: 'select(activeIdx, evt)',
+ 'move-in-progress': 'moveInProgress',
+ query: 'query',
+ position: 'position',
+ 'assign-is-open': 'assignIsOpen(isOpen)',
+ debounce: 'debounceUpdate'
+ });
+ //custom item template
+ if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
+ popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
+ }
+
+ if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {
+ popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);
+ }
+
+ var resetHint = function() {
+ if (showHint) {
+ hintInputElem.val('');
+ }
+ };
+
+ var resetMatches = function() {
+ scope.matches = [];
+ scope.activeIdx = -1;
+ element.attr('aria-expanded', false);
+ resetHint();
+ };
+
+ var getMatchId = function(index) {
+ return popupId + '-option-' + index;
+ };
+
+ // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
+ // This attribute is added or removed automatically when the `activeIdx` changes.
+ scope.$watch('activeIdx', function(index) {
+ if (index < 0) {
+ element.removeAttr('aria-activedescendant');
+ } else {
+ element.attr('aria-activedescendant', getMatchId(index));
+ }
+ });
+
+ var inputIsExactMatch = function(inputValue, index) {
+ if (scope.matches.length > index && inputValue) {
+ return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
+ }
+
+ return false;
+ };
+
+ var getMatchesAsync = function(inputValue, evt) {
+ var locals = {$viewValue: inputValue};
+ isLoadingSetter(originalScope, true);
+ isNoResultsSetter(originalScope, false);
+ $q.when(parserResult.source(originalScope, locals)).then(function(matches) {
+ //it might happen that several async queries were in progress if a user were typing fast
+ //but we are interested only in responses that correspond to the current view value
+ var onCurrentRequest = inputValue === modelCtrl.$viewValue;
+ if (onCurrentRequest && hasFocus) {
+ if (matches && matches.length > 0) {
+ scope.activeIdx = focusFirst ? 0 : -1;
+ isNoResultsSetter(originalScope, false);
+ scope.matches.length = 0;
+
+ //transform labels
+ for (var i = 0; i < matches.length; i++) {
+ locals[parserResult.itemName] = matches[i];
+ scope.matches.push({
+ id: getMatchId(i),
+ label: parserResult.viewMapper(scope, locals),
+ model: matches[i]
+ });
+ }
+
+ scope.query = inputValue;
+ //position pop-up with matches - we need to re-calculate its position each time we are opening a window
+ //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
+ //due to other elements being rendered
+ recalculatePosition();
+
+ element.attr('aria-expanded', true);
+
+ //Select the single remaining option if user input matches
+ if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {
+ if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
+ $$debounce(function() {
+ scope.select(0, evt);
+ }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
+ } else {
+ scope.select(0, evt);
+ }
+ }
+
+ if (showHint) {
+ var firstLabel = scope.matches[0].label;
+ if (angular.isString(inputValue) &&
+ inputValue.length > 0 &&
+ firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
+ hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
+ } else {
+ hintInputElem.val('');
+ }
+ }
+ } else {
+ resetMatches();
+ isNoResultsSetter(originalScope, true);
+ }
+ }
+ if (onCurrentRequest) {
+ isLoadingSetter(originalScope, false);
+ }
+ }, function() {
+ resetMatches();
+ isLoadingSetter(originalScope, false);
+ isNoResultsSetter(originalScope, true);
+ });
+ };
+
+ // bind events only if appendToBody params exist - performance feature
+ if (appendToBody) {
+ angular.element($window).on('resize', fireRecalculating);
+ $document.find('body').on('scroll', fireRecalculating);
+ }
+
+ // Declare the debounced function outside recalculating for
+ // proper debouncing
+ var debouncedRecalculate = $$debounce(function() {
+ // if popup is visible
+ if (scope.matches.length) {
+ recalculatePosition();
+ }
+
+ scope.moveInProgress = false;
+ }, eventDebounceTime);
+
+ // Default progress type
+ scope.moveInProgress = false;
+
+ function fireRecalculating() {
+ if (!scope.moveInProgress) {
+ scope.moveInProgress = true;
+ scope.$digest();
+ }
+
+ debouncedRecalculate();
+ }
+
+ // recalculate actual position and set new values to scope
+ // after digest loop is popup in right position
+ function recalculatePosition() {
+ scope.position = appendToBody ? $position.offset(element) : $position.position(element);
+ scope.position.top += element.prop('offsetHeight');
+ }
+
+ //we need to propagate user's query so we can higlight matches
+ scope.query = undefined;
+
+ //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
+ var timeoutPromise;
+
+ var scheduleSearchWithTimeout = function(inputValue) {
+ timeoutPromise = $timeout(function() {
+ getMatchesAsync(inputValue);
+ }, waitTime);
+ };
+
+ var cancelPreviousTimeout = function() {
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+ };
+
+ resetMatches();
+
+ scope.assignIsOpen = function (isOpen) {
+ isOpenSetter(originalScope, isOpen);
+ };
+
+ scope.select = function(activeIdx, evt) {
+ //called from within the $digest() cycle
+ var locals = {};
+ var model, item;
+
+ selected = true;
+ locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
+ model = parserResult.modelMapper(originalScope, locals);
+ $setModelValue(originalScope, model);
+ modelCtrl.$setValidity('editable', true);
+ modelCtrl.$setValidity('parse', true);
+
+ onSelectCallback(originalScope, {
+ $item: item,
+ $model: model,
+ $label: parserResult.viewMapper(originalScope, locals),
+ $event: evt
+ });
+
+ resetMatches();
+
+ //return focus to the input element if a match was selected via a mouse click event
+ // use timeout to avoid $rootScope:inprog error
+ if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
+ $timeout(function() { element[0].focus(); }, 0, false);
+ }
+ };
+
+ //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
+ element.on('keydown', function(evt) {
+ //typeahead is open and an "interesting" key was pressed
+ if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
+ return;
+ }
+
+ var shouldSelect = isSelectEvent(originalScope, {$event: evt});
+
+ /**
+ * if there's nothing selected (i.e. focusFirst) and enter or tab is hit
+ * or
+ * shift + tab is pressed to bring focus to the previous element
+ * then clear the results
+ */
+ if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
+ resetMatches();
+ scope.$digest();
+ return;
+ }
+
+ evt.preventDefault();
+ var target;
+ switch (evt.which) {
+ case 27: // escape
+ evt.stopPropagation();
+
+ resetMatches();
+ originalScope.$digest();
+ break;
+ case 38: // up arrow
+ scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
+ scope.$digest();
+ target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
+ target.parentNode.scrollTop = target.offsetTop;
+ break;
+ case 40: // down arrow
+ scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
+ scope.$digest();
+ target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
+ target.parentNode.scrollTop = target.offsetTop;
+ break;
+ default:
+ if (shouldSelect) {
+ scope.$apply(function() {
+ if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
+ $$debounce(function() {
+ scope.select(scope.activeIdx, evt);
+ }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
+ } else {
+ scope.select(scope.activeIdx, evt);
+ }
+ });
+ }
+ }
+ });
+
+ element.on('focus', function (evt) {
+ hasFocus = true;
+ if (minLength === 0 && !modelCtrl.$viewValue) {
+ $timeout(function() {
+ getMatchesAsync(modelCtrl.$viewValue, evt);
+ }, 0);
+ }
+ });
+
+ element.on('blur', function(evt) {
+ if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
+ selected = true;
+ scope.$apply(function() {
+ if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {
+ $$debounce(function() {
+ scope.select(scope.activeIdx, evt);
+ }, scope.debounceUpdate.blur);
+ } else {
+ scope.select(scope.activeIdx, evt);
+ }
+ });
+ }
+ if (!isEditable && modelCtrl.$error.editable) {
+ modelCtrl.$setViewValue();
+ scope.$apply(function() {
+ // Reset validity as we are clearing
+ modelCtrl.$setValidity('editable', true);
+ modelCtrl.$setValidity('parse', true);
+ });
+ element.val('');
+ }
+ hasFocus = false;
+ selected = false;
+ });
+
+ // Keep reference to click handler to unbind it.
+ var dismissClickHandler = function(evt) {
+ // Issue #3973
+ // Firefox treats right click as a click on document
+ if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {
+ resetMatches();
+ if (!$rootScope.$$phase) {
+ originalScope.$digest();
+ }
+ }
+ };
+
+ $document.on('click', dismissClickHandler);
+
+ originalScope.$on('$destroy', function() {
+ $document.off('click', dismissClickHandler);
+ if (appendToBody || appendTo) {
+ $popup.remove();
+ }
+
+ if (appendToBody) {
+ angular.element($window).off('resize', fireRecalculating);
+ $document.find('body').off('scroll', fireRecalculating);
+ }
+ // Prevent jQuery cache memory leak
+ popUpEl.remove();
+
+ if (showHint) {
+ inputsContainer.remove();
+ }
+ });
+
+ var $popup = $compile(popUpEl)(scope);
+
+ if (appendToBody) {
+ $document.find('body').append($popup);
+ } else if (appendTo) {
+ angular.element(appendTo).eq(0).append($popup);
+ } else {
+ element.after($popup);
+ }
+
+ this.init = function(_modelCtrl) {
+ modelCtrl = _modelCtrl;
+ ngModelOptions = extractOptions(modelCtrl);
+
+ scope.debounceUpdate = $parse(ngModelOptions.getOption('debounce'))(originalScope);
+
+ //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
+ //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
+ modelCtrl.$parsers.unshift(function(inputValue) {
+ hasFocus = true;
+
+ if (minLength === 0 || inputValue && inputValue.length >= minLength) {
+ if (waitTime > 0) {
+ cancelPreviousTimeout();
+ scheduleSearchWithTimeout(inputValue);
+ } else {
+ getMatchesAsync(inputValue);
+ }
+ } else {
+ isLoadingSetter(originalScope, false);
+ cancelPreviousTimeout();
+ resetMatches();
+ }
+
+ if (isEditable) {
+ return inputValue;
+ }
+
+ if (!inputValue) {
+ // Reset in case user had typed something previously.
+ modelCtrl.$setValidity('editable', true);
+ return null;
+ }
+
+ modelCtrl.$setValidity('editable', false);
+ return undefined;
+ });
+
+ modelCtrl.$formatters.push(function(modelValue) {
+ var candidateViewValue, emptyViewValue;
+ var locals = {};
+
+ // The validity may be set to false via $parsers (see above) if
+ // the model is restricted to selected values. If the model
+ // is set manually it is considered to be valid.
+ if (!isEditable) {
+ modelCtrl.$setValidity('editable', true);
+ }
+
+ if (inputFormatter) {
+ locals.$model = modelValue;
+ return inputFormatter(originalScope, locals);
+ }
+
+ //it might happen that we don't have enough info to properly render input value
+ //we need to check for this situation and simply return model value if we can't apply custom formatting
+ locals[parserResult.itemName] = modelValue;
+ candidateViewValue = parserResult.viewMapper(originalScope, locals);
+ locals[parserResult.itemName] = undefined;
+ emptyViewValue = parserResult.viewMapper(originalScope, locals);
+
+ return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;
+ });
+ };
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = ngModelCtrl.$options || {};
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ ngModelOptions = ngModelCtrl.$options;
+ }
+
+ return ngModelOptions;
+ }
+ }])
+
+ .directive('uibTypeahead', function() {
+ return {
+ controller: 'UibTypeaheadController',
+ require: ['ngModel', 'uibTypeahead'],
+ link: function(originalScope, element, attrs, ctrls) {
+ ctrls[1].init(ctrls[0]);
+ }
+ };
+ })
+
+ .directive('uibTypeaheadPopup', ['$$debounce', function($$debounce) {
+ return {
+ scope: {
+ matches: '=',
+ query: '=',
+ active: '=',
+ position: '&',
+ moveInProgress: '=',
+ select: '&',
+ assignIsOpen: '&',
+ debounce: '&'
+ },
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.templateUrl = attrs.templateUrl;
+
+ scope.isOpen = function() {
+ var isDropdownOpen = scope.matches.length > 0;
+ scope.assignIsOpen({ isOpen: isDropdownOpen });
+ return isDropdownOpen;
+ };
+
+ scope.isActive = function(matchIdx) {
+ return scope.active === matchIdx;
+ };
+
+ scope.selectActive = function(matchIdx) {
+ scope.active = matchIdx;
+ };
+
+ scope.selectMatch = function(activeIdx, evt) {
+ var debounce = scope.debounce();
+ if (angular.isNumber(debounce) || angular.isObject(debounce)) {
+ $$debounce(function() {
+ scope.select({activeIdx: activeIdx, evt: evt});
+ }, angular.isNumber(debounce) ? debounce : debounce['default']);
+ } else {
+ scope.select({activeIdx: activeIdx, evt: evt});
+ }
+ };
+ }
+ };
+ }])
+
+ .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {
+ return {
+ scope: {
+ index: '=',
+ match: '=',
+ query: '='
+ },
+ link: function(scope, element, attrs) {
+ var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
+ $templateRequest(tplUrl).then(function(tplContent) {
+ var tplEl = angular.element(tplContent.trim());
+ element.replaceWith(tplEl);
+ $compile(tplEl)(scope);
+ });
+ }
+ };
+ }])
+
+ .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {
+ var isSanitizePresent;
+ isSanitizePresent = $injector.has('$sanitize');
+
+ function escapeRegexp(queryToEscape) {
+ // Regex: capture the whole query string and replace it with the string that will be used to match
+ // the results, for example if the capture is "a" the result will be \a
+ return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
+ }
+
+ function containsHtml(matchItem) {
+ return /<.*>/g.test(matchItem);
+ }
+
+ return function(matchItem, query) {
+ if (!isSanitizePresent && containsHtml(matchItem)) {
+ $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
+ }
+ matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
+ if (!isSanitizePresent) {
+ matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
+ }
+ return matchItem;
+ };
+ }]);
+
+angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/accordion/accordion-group.html",
+ "<div role=\"tab\" id=\"{{::headingId}}\" aria-selected=\"{{isOpen}}\" class=\"panel-heading\" ng-keypress=\"toggleOpen($event)\">\n" +
+ " <h4 class=\"panel-title\">\n" +
+ " <a role=\"button\" data-toggle=\"collapse\" href aria-expanded=\"{{isOpen}}\" aria-controls=\"{{::panelId}}\" tabindex=\"0\" class=\"accordion-toggle\" ng-click=\"toggleOpen()\" uib-accordion-transclude=\"heading\" ng-disabled=\"isDisabled\" uib-tabindex-toggle><span uib-accordion-header ng-class=\"{'text-muted': isDisabled}\">{{heading}}</span></a>\n" +
+ " </h4>\n" +
+ "</div>\n" +
+ "<div id=\"{{::panelId}}\" aria-labelledby=\"{{::headingId}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" class=\"panel-collapse collapse\" uib-collapse=\"!isOpen\">\n" +
+ " <div class=\"panel-body\" ng-transclude></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/accordion/accordion.html",
+ "<div role=\"tablist\" class=\"panel-group\" ng-transclude></div>");
+}]);
+
+angular.module("uib/template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/alert/alert.html",
+ "<button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close({$event: $event})\">\n" +
+ " <span aria-hidden=\"true\">&times;</span>\n" +
+ " <span class=\"sr-only\">Close</span>\n" +
+ "</button>\n" +
+ "<div ng-transclude></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/carousel/carousel.html",
+ "<div class=\"carousel-inner\" ng-transclude></div>\n" +
+ "<a role=\"button\" href class=\"left carousel-control\" ng-click=\"prev()\" ng-class=\"{ disabled: isPrevDisabled() }\" ng-show=\"slides.length > 1\">\n" +
+ " <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></span>\n" +
+ " <span class=\"sr-only\">previous</span>\n" +
+ "</a>\n" +
+ "<a role=\"button\" href class=\"right carousel-control\" ng-click=\"next()\" ng-class=\"{ disabled: isNextDisabled() }\" ng-show=\"slides.length > 1\">\n" +
+ " <span aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></span>\n" +
+ " <span class=\"sr-only\">next</span>\n" +
+ "</a>\n" +
+ "<ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
+ " <li ng-repeat=\"slide in slides | orderBy:indexOfSlide track by $index\" ng-class=\"{ active: isActive(slide) }\" ng-click=\"select(slide)\">\n" +
+ " <span class=\"sr-only\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\"isActive(slide)\">, currently active</span></span>\n" +
+ " </li>\n" +
+ "</ol>\n" +
+ "");
+}]);
+
+angular.module("uib/template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/carousel/slide.html",
+ "<div class=\"text-center\" ng-transclude></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/datepicker.html",
+ "<div ng-switch=\"datepickerMode\">\n" +
+ " <div uib-daypicker ng-switch-when=\"day\" tabindex=\"0\" class=\"uib-daypicker\"></div>\n" +
+ " <div uib-monthpicker ng-switch-when=\"month\" tabindex=\"0\" class=\"uib-monthpicker\"></div>\n" +
+ " <div uib-yearpicker ng-switch-when=\"year\" tabindex=\"0\" class=\"uib-yearpicker\"></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/day.html",
+ "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
+ " <thead>\n" +
+ " <tr>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
+ " <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></button></th>\n" +
+ " </tr>\n" +
+ " <tr>\n" +
+ " <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
+ " <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{::label.abbr}}</small></th>\n" +
+ " </tr>\n" +
+ " </thead>\n" +
+ " <tbody>\n" +
+ " <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
+ " <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
+ " <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
+ " id=\"{{::dt.uid}}\"\n" +
+ " ng-class=\"::dt.customClass\">\n" +
+ " <button type=\"button\" class=\"btn btn-default btn-sm\"\n" +
+ " uib-is-class=\"\n" +
+ " 'btn-info' for selectedDt,\n" +
+ " 'active' for activeDt\n" +
+ " on dt\"\n" +
+ " ng-click=\"select(dt.date)\"\n" +
+ " ng-disabled=\"::dt.disabled\"\n" +
+ " tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
+ " </td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ "</table>\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/month.html",
+ "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
+ " <thead>\n" +
+ " <tr>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
+ " <th colspan=\"{{::yearHeaderColspan}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></i></button></th>\n" +
+ " </tr>\n" +
+ " </thead>\n" +
+ " <tbody>\n" +
+ " <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
+ " <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
+ " id=\"{{::dt.uid}}\"\n" +
+ " ng-class=\"::dt.customClass\">\n" +
+ " <button type=\"button\" class=\"btn btn-default\"\n" +
+ " uib-is-class=\"\n" +
+ " 'btn-info' for selectedDt,\n" +
+ " 'active' for activeDt\n" +
+ " on dt\"\n" +
+ " ng-click=\"select(dt.date)\"\n" +
+ " ng-disabled=\"::dt.disabled\"\n" +
+ " tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
+ " </td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ "</table>\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepicker/year.html",
+ "<table role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
+ " <thead>\n" +
+ " <tr>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-left\"></i><span class=\"sr-only\">previous</span></button></th>\n" +
+ " <th colspan=\"{{::columns - 2}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
+ " <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i aria-hidden=\"true\" class=\"glyphicon glyphicon-chevron-right\"></i><span class=\"sr-only\">next</span></button></th>\n" +
+ " </tr>\n" +
+ " </thead>\n" +
+ " <tbody>\n" +
+ " <tr class=\"uib-years\" ng-repeat=\"row in rows track by $index\" role=\"row\">\n" +
+ " <td ng-repeat=\"dt in row\" class=\"uib-year text-center\" role=\"gridcell\"\n" +
+ " id=\"{{::dt.uid}}\"\n" +
+ " ng-class=\"::dt.customClass\">\n" +
+ " <button type=\"button\" class=\"btn btn-default\"\n" +
+ " uib-is-class=\"\n" +
+ " 'btn-info' for selectedDt,\n" +
+ " 'active' for activeDt\n" +
+ " on dt\"\n" +
+ " ng-click=\"select(dt.date)\"\n" +
+ " ng-disabled=\"::dt.disabled\"\n" +
+ " tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
+ " </td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ "</table>\n" +
+ "");
+}]);
+
+angular.module("uib/template/datepickerPopup/popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/datepickerPopup/popup.html",
+ "<ul role=\"presentation\" class=\"uib-datepicker-popup dropdown-menu uib-position-measure\" dropdown-nested ng-if=\"isOpen\" ng-keydown=\"keydown($event)\" ng-click=\"$event.stopPropagation()\">\n" +
+ " <li ng-transclude></li>\n" +
+ " <li ng-if=\"showButtonBar\" class=\"uib-button-bar\">\n" +
+ " <span class=\"btn-group pull-left\">\n" +
+ " <button type=\"button\" class=\"btn btn-sm btn-info uib-datepicker-current\" ng-click=\"select('today', $event)\" ng-disabled=\"isDisabled('today')\">{{ getText('current') }}</button>\n" +
+ " <button type=\"button\" class=\"btn btn-sm btn-danger uib-clear\" ng-click=\"select(null, $event)\">{{ getText('clear') }}</button>\n" +
+ " </span>\n" +
+ " <button type=\"button\" class=\"btn btn-sm btn-success pull-right uib-close\" ng-click=\"close($event)\">{{ getText('close') }}</button>\n" +
+ " </li>\n" +
+ "</ul>\n" +
+ "");
+}]);
+
+angular.module("uib/template/modal/window.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/modal/window.html",
+ "<div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/pager/pager.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/pager/pager.html",
+ "<li ng-class=\"{disabled: noPrevious()||ngDisabled, previous: align}\"><a href ng-click=\"selectPage(page - 1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\n" +
+ "<li ng-class=\"{disabled: noNext()||ngDisabled, next: align}\"><a href ng-click=\"selectPage(page + 1, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\n" +
+ "");
+}]);
+
+angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/pagination/pagination.html",
+ "<li role=\"menuitem\" ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-first\"><a href ng-click=\"selectPage(1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('first')}}</a></li>\n" +
+ "<li role=\"menuitem\" ng-if=\"::directionLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-prev\"><a href ng-click=\"selectPage(page - 1, $event)\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\n" +
+ "<li role=\"menuitem\" ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active,disabled: ngDisabled&&!page.active}\" class=\"pagination-page\"><a href ng-click=\"selectPage(page.number, $event)\" ng-disabled=\"ngDisabled&&!page.active\" uib-tabindex-toggle>{{page.text}}</a></li>\n" +
+ "<li role=\"menuitem\" ng-if=\"::directionLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-next\"><a href ng-click=\"selectPage(page + 1, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\n" +
+ "<li role=\"menuitem\" ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-last\"><a href ng-click=\"selectPage(totalPages, $event)\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('last')}}</a></li>\n" +
+ "");
+}]);
+
+angular.module("uib/template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/tooltip/tooltip-html-popup.html",
+ "<div class=\"tooltip-arrow\"></div>\n" +
+ "<div class=\"tooltip-inner\" ng-bind-html=\"contentExp()\"></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/tooltip/tooltip-popup.html",
+ "<div class=\"tooltip-arrow\"></div>\n" +
+ "<div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/tooltip/tooltip-template-popup.html",
+ "<div class=\"tooltip-arrow\"></div>\n" +
+ "<div class=\"tooltip-inner\"\n" +
+ " uib-tooltip-template-transclude=\"contentExp()\"\n" +
+ " tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/popover/popover-html.html",
+ "<div class=\"arrow\"></div>\n" +
+ "\n" +
+ "<div class=\"popover-inner\">\n" +
+ " <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
+ " <div class=\"popover-content\" ng-bind-html=\"contentExp()\"></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/popover/popover-template.html",
+ "<div class=\"arrow\"></div>\n" +
+ "\n" +
+ "<div class=\"popover-inner\">\n" +
+ " <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
+ " <div class=\"popover-content\"\n" +
+ " uib-tooltip-template-transclude=\"contentExp()\"\n" +
+ " tooltip-template-transclude-scope=\"originScope()\"></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/popover/popover.html",
+ "<div class=\"arrow\"></div>\n" +
+ "\n" +
+ "<div class=\"popover-inner\">\n" +
+ " <h3 class=\"popover-title\" ng-bind=\"uibTitle\" ng-if=\"uibTitle\"></h3>\n" +
+ " <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/progressbar/bar.html",
+ "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/progressbar/progress.html",
+ "<div class=\"progress\" ng-transclude aria-labelledby=\"{{::title}}\"></div>");
+}]);
+
+angular.module("uib/template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/progressbar/progressbar.html",
+ "<div class=\"progress\">\n" +
+ " <div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: (percent < 100 ? percent : 100) + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" aria-labelledby=\"{{::title}}\" ng-transclude></div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/rating/rating.html",
+ "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\" aria-valuetext=\"{{title}}\">\n" +
+ " <span ng-repeat-start=\"r in range track by $index\" class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
+ " <i ng-repeat-end ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\" ng-attr-title=\"{{r.title}}\"></i>\n" +
+ "</span>\n" +
+ "");
+}]);
+
+angular.module("uib/template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/tabs/tab.html",
+ "<li ng-class=\"[{active: active, disabled: disabled}, classes]\" class=\"uib-tab nav-item\">\n" +
+ " <a href ng-click=\"select($event)\" class=\"nav-link\" uib-tab-heading-transclude>{{heading}}</a>\n" +
+ "</li>\n" +
+ "");
+}]);
+
+angular.module("uib/template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/tabs/tabset.html",
+ "<div>\n" +
+ " <ul class=\"nav nav-{{tabset.type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
+ " <div class=\"tab-content\">\n" +
+ " <div class=\"tab-pane\"\n" +
+ " ng-repeat=\"tab in tabset.tabs\"\n" +
+ " ng-class=\"{active: tabset.active === tab.index}\"\n" +
+ " uib-tab-content-transclude=\"tab\">\n" +
+ " </div>\n" +
+ " </div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/timepicker/timepicker.html",
+ "<table class=\"uib-timepicker\">\n" +
+ " <tbody>\n" +
+ " <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
+ " <td class=\"uib-increment hours\"><a ng-click=\"incrementHours()\" ng-class=\"{disabled: noIncrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementHours()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
+ " <td>&nbsp;</td>\n" +
+ " <td class=\"uib-increment minutes\"><a ng-click=\"incrementMinutes()\" ng-class=\"{disabled: noIncrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementMinutes()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
+ " <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
+ " <td ng-show=\"showSeconds\" class=\"uib-increment seconds\"><a ng-click=\"incrementSeconds()\" ng-class=\"{disabled: noIncrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noIncrementSeconds()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
+ " <td ng-show=\"showMeridian\"></td>\n" +
+ " </tr>\n" +
+ " <tr>\n" +
+ " <td class=\"form-group uib-time hours\" ng-class=\"{'has-error': invalidHours}\">\n" +
+ " <input type=\"text\" placeholder=\"HH\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementHours()\" ng-blur=\"blur()\">\n" +
+ " </td>\n" +
+ " <td class=\"uib-separator\">:</td>\n" +
+ " <td class=\"form-group uib-time minutes\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
+ " <input type=\"text\" placeholder=\"MM\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"::readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementMinutes()\" ng-blur=\"blur()\">\n" +
+ " </td>\n" +
+ " <td ng-show=\"showSeconds\" class=\"uib-separator\">:</td>\n" +
+ " <td class=\"form-group uib-time seconds\" ng-class=\"{'has-error': invalidSeconds}\" ng-show=\"showSeconds\">\n" +
+ " <input type=\"text\" placeholder=\"SS\" ng-model=\"seconds\" ng-change=\"updateSeconds()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\" tabindex=\"{{::tabindex}}\" ng-disabled=\"noIncrementSeconds()\" ng-blur=\"blur()\">\n" +
+ " </td>\n" +
+ " <td ng-show=\"showMeridian\" class=\"uib-time am-pm\"><button type=\"button\" ng-class=\"{disabled: noToggleMeridian()}\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\" ng-disabled=\"noToggleMeridian()\" tabindex=\"{{::tabindex}}\">{{meridian}}</button></td>\n" +
+ " </tr>\n" +
+ " <tr class=\"text-center\" ng-show=\"::showSpinners\">\n" +
+ " <td class=\"uib-decrement hours\"><a ng-click=\"decrementHours()\" ng-class=\"{disabled: noDecrementHours()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementHours()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
+ " <td>&nbsp;</td>\n" +
+ " <td class=\"uib-decrement minutes\"><a ng-click=\"decrementMinutes()\" ng-class=\"{disabled: noDecrementMinutes()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementMinutes()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
+ " <td ng-show=\"showSeconds\">&nbsp;</td>\n" +
+ " <td ng-show=\"showSeconds\" class=\"uib-decrement seconds\"><a ng-click=\"decrementSeconds()\" ng-class=\"{disabled: noDecrementSeconds()}\" class=\"btn btn-link\" ng-disabled=\"noDecrementSeconds()\" tabindex=\"-1\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
+ " <td ng-show=\"showMeridian\"></td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ "</table>\n" +
+ "");
+}]);
+
+angular.module("uib/template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/typeahead/typeahead-match.html",
+ "<a href\n" +
+ " tabindex=\"-1\"\n" +
+ " ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"\n" +
+ " ng-attr-title=\"{{match.label}}\"></a>\n" +
+ "");
+}]);
+
+angular.module("uib/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("uib/template/typeahead/typeahead-popup.html",
+ "<ul class=\"dropdown-menu\" ng-show=\"isOpen() && !moveInProgress\" ng-style=\"{top: position().top+'px', left: position().left+'px'}\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
+ " <li class=\"uib-typeahead-match\" ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index, $event)\" role=\"option\" id=\"{{::match.id}}\">\n" +
+ " <div uib-typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
+ " </li>\n" +
+ "</ul>\n" +
+ "");
+}]);
+angular.module('ui.bootstrap.carousel').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });
+angular.module('ui.bootstrap.datepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });
+angular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });
+angular.module('ui.bootstrap.datepickerPopup').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
+angular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
+angular.module('ui.bootstrap.timepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
+angular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js
new file mode 100644
index 00000000..0b1fc7f0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js
@@ -0,0 +1,10 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 2.5.0 - 2017-01-28
+ * License: MIT
+ */angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$q","$parse","$injector",function(a,b,c,d){var e=d.has("$animateCss")?d.get("$animateCss"):null;return{link:function(d,f,g){function h(){r=!!("horizontal"in g),r?(s={width:""},t={width:"0"}):(s={height:""},t={height:"0"}),d.$eval(g.uibCollapse)||f.addClass("in").addClass("collapse").attr("aria-expanded",!0).attr("aria-hidden",!1).css(s)}function i(a){return r?{width:a.scrollWidth+"px"}:{height:a.scrollHeight+"px"}}function j(){f.hasClass("collapse")&&f.hasClass("in")||b.resolve(n(d)).then(function(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"in",easing:"ease",css:{overflow:"hidden"},to:i(f[0])}).start()["finally"](k):a.addClass(f,"in",{css:{overflow:"hidden"},to:i(f[0])}).then(k)},angular.noop)}function k(){f.removeClass("collapsing").addClass("collapse").css(s),o(d)}function l(){return f.hasClass("collapse")||f.hasClass("in")?void b.resolve(p(d)).then(function(){f.css(i(f[0])).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),e?e(f,{removeClass:"in",to:t}).start()["finally"](m):a.removeClass(f,"in",{to:t}).then(m)},angular.noop):m()}function m(){f.css(t),f.removeClass("collapsing").addClass("collapse"),q(d)}var n=c(g.expanding),o=c(g.expanded),p=c(g.collapsing),q=c(g.collapsed),r=!1,s={},t={};h(),d.$watch(g.uibCollapse,function(a){a?l():j()})}}}]),angular.module("ui.bootstrap.tabindex",[]).directive("uibTabindexToggle",function(){return{restrict:"A",link:function(a,b,c){c.$observe("disabled",function(a){c.$set("tabindex",a?-1:null)})}}}),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse","ui.bootstrap.tabindex"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion-group.html"},scope:{heading:"@",panelClass:"@?",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){b.addClass("panel"),d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass||"panel-default",a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)};var e="accordiongroup-"+a.$id+"-"+Math.floor(1e4*Math.random());a.headingId=e+"-tab",a.panelId=e+"-panel"}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){function a(){return"uib-accordion-header,data-uib-accordion-header,x-uib-accordion-header,uib\\:accordion-header,[uib-accordion-header],[data-uib-accordion-header],[x-uib-accordion-header]"}return{require:"^uibAccordionGroup",link:function(b,c,d,e){b.$watch(function(){return e[d.uibAccordionTransclude]},function(b){if(b){var d=angular.element(c[0].querySelector(a()));d.html(""),d.append(b)}})}}}),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$element","$attrs","$interpolate","$timeout",function(a,b,c,d,e){a.closeable=!!c.close,b.addClass("alert"),c.$set("role","alert"),a.closeable&&b.addClass("alert-dismissible");var f=angular.isDefined(c.dismissOnTimeout)?d(c.dismissOnTimeout)(a.$parent):null;f&&e(function(){a.close()},parseInt(f,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/alert/alert.html"},transclude:!0,scope:{close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",["$parse",function(a){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(b,c,d,e){var f=e[0],g=e[1],h=a(d.uibUncheckable);c.find("input").css({display:"none"}),g.$render=function(){c.toggleClass(f.activeClass,angular.equals(g.$modelValue,b.$eval(d.uibBtnRadio)))},c.on(f.toggleEvent,function(){if(!d.disabled){var a=c.hasClass(f.activeClass);a&&!angular.isDefined(d.uncheckable)||b.$apply(function(){g.$setViewValue(a?null:b.$eval(d.uibBtnRadio)),g.$render()})}}),d.uibUncheckable&&b.$watch(h,function(a){d.$set("uncheckable",a?"":void 0)})}}}]).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$timeout","$animate",function(a,b,c,d,e){function f(a){for(var b=0;b<p.length;b++)p[b].slide.active=b===a}function g(c,d,g){if(!s){if(angular.extend(c,{direction:g}),angular.extend(p[r].slide||{},{direction:g}),e.enabled(b)&&!a.$currentTransition&&p[d].element&&o.slides.length>1){p[d].element.data(q,c.direction);var h=o.getCurrentIndex();angular.isNumber(h)&&p[h].element&&p[h].element.data(q,c.direction),a.$currentTransition=!0,e.on("addClass",p[d].element,function(b,c){"close"===c&&(a.$currentTransition=null,e.off("addClass",b))})}a.active=c.index,r=c.index,f(d),k()}}function h(a){for(var b=0;b<p.length;b++)if(p[b].slide===a)return b}function i(){m&&(c.cancel(m),m=null)}function j(b){b.length||(a.$currentTransition=null)}function k(){i();var b=+a.interval;!isNaN(b)&&b>0&&(m=c(l,b))}function l(){var b=+a.interval;n&&!isNaN(b)&&b>0&&p.length?a.next():a.pause()}var m,n,o=this,p=o.slides=a.slides=[],q="uib-slideDirection",r=a.active,s=!1;b.addClass("carousel"),o.addSlide=function(b,c){p.push({slide:b,element:c}),p.sort(function(a,b){return+a.slide.index-+b.slide.index}),(b.index===a.active||1===p.length&&!angular.isNumber(a.active))&&(a.$currentTransition&&(a.$currentTransition=null),r=b.index,a.active=b.index,f(r),o.select(p[h(b)]),1===p.length&&a.play())},o.getCurrentIndex=function(){for(var a=0;a<p.length;a++)if(p[a].slide.index===r)return a},o.next=a.next=function(){var b=(o.getCurrentIndex()+1)%p.length;return 0===b&&a.noWrap()?void a.pause():o.select(p[b],"next")},o.prev=a.prev=function(){var b=o.getCurrentIndex()-1<0?p.length-1:o.getCurrentIndex()-1;return a.noWrap()&&b===p.length-1?void a.pause():o.select(p[b],"prev")},o.removeSlide=function(b){var c=h(b);p.splice(c,1),p.length>0&&r===c?c>=p.length?(r=p.length-1,a.active=r,f(r),o.select(p[p.length-1])):(r=c,a.active=r,f(r),o.select(p[c])):r>c&&(r--,a.active=r),0===p.length&&(r=null,a.active=null)},o.select=a.select=function(b,c){var d=h(b.slide);void 0===c&&(c=d>o.getCurrentIndex()?"next":"prev"),b.slide.index===r||a.$currentTransition||g(b.slide,d,c)},a.indexOfSlide=function(a){return+a.slide.index},a.isActive=function(b){return a.active===b.slide.index},a.isPrevDisabled=function(){return 0===a.active&&a.noWrap()},a.isNextDisabled=function(){return a.active===p.length-1&&a.noWrap()},a.pause=function(){a.noPause||(n=!1,i())},a.play=function(){n||(n=!0,k())},b.on("mouseenter",a.pause),b.on("mouseleave",a.play),a.$on("$destroy",function(){s=!0,i()}),a.$watch("noTransition",function(a){e.enabled(b,!a)}),a.$watch("interval",k),a.$watchCollection("slides",j),a.$watch("active",function(a){if(angular.isNumber(a)&&r!==a){for(var b=0;b<p.length;b++)if(p[b].slide.index===a){a=b;break}var c=p[a];c&&(f(a),o.select(p[a]),r=a)}})}]).directive("uibCarousel",function(){return{transclude:!0,controller:"UibCarouselController",controllerAs:"carousel",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/carousel.html"},scope:{active:"=",interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}).directive("uibSlide",["$animate",function(a){return{require:"^uibCarousel",restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/slide.html"},scope:{actual:"=?",index:"=?"},link:function(b,c,d,e){c.addClass("item"),e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(b){a[b?"addClass":"removeClass"](c,"active")})}}}]).animation(".item",["$animateCss",function(a){function b(a,b,c){a.removeClass(b),c&&c()}var c="uib-slideDirection";return{beforeAddClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i+" "+h,f);return d.addClass(h),a(d,{addClass:i}).start().done(j),function(){g=!0}}f()},beforeRemoveClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i,f);return a(d,{addClass:i}).start().done(j),function(){g=!0}}f()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","dateFilter","orderByFilter","filterFilter",function(a,b,c,d,e){function f(a){return e(s,{key:a},!0)[0]}function g(a){var b=[],c=a.split(""),e=a.indexOf("'");if(e>-1){var f=!1;a=a.split("");for(var g=e;g<a.length;g++)f?("'"===a[g]&&(g+1<a.length&&"'"===a[g+1]?(a[g+1]="$",c[g+1]=""):(c[g]="",f=!1)),a[g]="$"):"'"===a[g]&&(a[g]="$",c[g]="",f=!0);a=a.join("")}return angular.forEach(s,function(d){var e=a.indexOf(d.key);if(e>-1){a=a.split(""),c[e]="("+d.regex+")",a[e]="$";for(var f=e+1,g=e+d.key.length;g>f;f++)c[f]="",a[f]="$";a=a.join(""),b.push({index:e,key:d.key,apply:d.apply,matcher:d.regex})}}),{regex:new RegExp("^"+c.join("")+"$"),map:d(b,"index")}}function h(a){for(var b,c,d=[],e=0;e<a.length;)if(angular.isNumber(c)){if("'"===a.charAt(e))(e+1>=a.length||"'"!==a.charAt(e+1))&&(d.push(i(a,c,e)),c=null);else if(e===a.length)for(;c<a.length;)b=j(a,c),d.push(b),c=b.endIdx;e++}else"'"!==a.charAt(e)?(b=j(a,e),d.push(b.parser),e=b.endIdx):(c=e,e++);return d}function i(a,b,c){return function(){return a.substr(b+1,c-b-1)}}function j(a,b){for(var c=a.substr(b),d=0;d<s.length;d++)if(new RegExp("^"+s[d].key).test(c)){var e=s[d];return{endIdx:b+e.key.length,parser:e.formatter}}return{endIdx:b+1,parser:function(){return c.charAt(0)}}}function k(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}function l(a){return parseInt(a,10)}function m(a,b){return a&&b?q(a,b):a}function n(a,b){return a&&b?q(a,b,!0):a}function o(a,b){a=a.replace(/:/g,"");var c=Date.parse("Jan 01, 1970 00:00:00 "+a)/6e4;return isNaN(c)?b:c}function p(a,b){return a=new Date(a.getTime()),a.setMinutes(a.getMinutes()+b),a}function q(a,b,c){c=c?-1:1;var d=a.getTimezoneOffset(),e=o(b,d);return p(a,c*(e-d))}var r,s,t=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){r=b.id,this.parsers={},this.formatters={},s=[{key:"yyyy",regex:"\\d{4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yyyy")}},{key:"yy",regex:"\\d{2}",apply:function(a){a=+a,this.year=69>a?a+2e3:a+1900},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yy")}},{key:"y",regex:"\\d{1,4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"y")}},{key:"M!",regex:"0?[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){var b=a.getMonth();return/^[0-9]$/.test(b)?c(a,"MM"):c(a,"M")}},{key:"MMMM",regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)},formatter:function(a){return c(a,"MMMM")}},{key:"MMM",regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)},formatter:function(a){return c(a,"MMM")}},{key:"MM",regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"MM")}},{key:"M",regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"M")}},{key:"d!",regex:"[0-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){var b=a.getDate();return/^[1-9]$/.test(b)?c(a,"dd"):c(a,"d")}},{key:"dd",regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"dd")}},{key:"d",regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"d")}},{key:"EEEE",regex:b.DATETIME_FORMATS.DAY.join("|"),formatter:function(a){return c(a,"EEEE")}},{key:"EEE",regex:b.DATETIME_FORMATS.SHORTDAY.join("|"),formatter:function(a){return c(a,"EEE")}},{key:"HH",regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"HH")}},{key:"hh",regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"hh")}},{key:"H",regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"H")}},{key:"h",regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"h")}},{key:"mm",regex:"[0-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"mm")}},{key:"m",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"m")}},{key:"sss",regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a},formatter:function(a){return c(a,"sss")}},{key:"ss",regex:"[0-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"ss")}},{key:"s",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"s")}},{key:"a",regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)},formatter:function(a){return c(a,"a")}},{key:"Z",regex:"[+-]\\d{4}",apply:function(a){var b=a.match(/([+-])(\d{2})(\d{2})/),c=b[1],d=b[2],e=b[3];this.hours+=l(c+d),this.minutes+=l(c+e)},formatter:function(a){return c(a,"Z")}},{key:"ww",regex:"[0-4][0-9]|5[0-3]",formatter:function(a){return c(a,"ww")}},{key:"w",regex:"[0-9]|[1-4][0-9]|5[0-3]",formatter:function(a){return c(a,"w")}},{key:"GGGG",regex:b.DATETIME_FORMATS.ERANAMES.join("|").replace(/\s/g,"\\s"),formatter:function(a){return c(a,"GGGG")}},{key:"GGG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GGG")}},{key:"GG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GG")}},{key:"G",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"G")}}],angular.version.major>=1&&angular.version.minor>4&&s.push({key:"LLLL",regex:b.DATETIME_FORMATS.STANDALONEMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.STANDALONEMONTH.indexOf(a)},formatter:function(a){return c(a,"LLLL")}})},this.init(),this.getParser=function(a){var b=f(a);return b&&b.apply||null},this.overrideParser=function(a,b){var c=f(a);c&&angular.isFunction(b)&&(this.parsers={},c.apply=b)}.bind(this),this.filter=function(a,c){if(!angular.isDate(a)||isNaN(a)||!c)return"";c=b.DATETIME_FORMATS[c]||c,b.id!==r&&this.init(),this.formatters[c]||(this.formatters[c]=h(c));var d=this.formatters[c];return d.reduce(function(b,c){return b+c(a)},"")},this.parse=function(c,d,e){if(!angular.isString(c)||!d)return c;d=b.DATETIME_FORMATS[d]||d,d=d.replace(t,"\\$&"),b.id!==r&&this.init(),this.parsers[d]||(this.parsers[d]=g(d,"apply"));var f=this.parsers[d],h=f.regex,i=f.map,j=c.match(h),l=!1;if(j&&j.length){var m,n;angular.isDate(e)&&!isNaN(e.getTime())?m={year:e.getFullYear(),month:e.getMonth(),date:e.getDate(),hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds(),milliseconds:e.getMilliseconds()}:(e&&a.warn("dateparser:","baseDate is not a valid date"),m={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var o=1,p=j.length;p>o;o++){var q=i[o-1];"Z"===q.matcher&&(l=!0),q.apply&&q.apply.call(m,j[o])}var s=l?Date.prototype.setUTCFullYear:Date.prototype.setFullYear,u=l?Date.prototype.setUTCHours:Date.prototype.setHours;return k(m.year,m.month,m.date)&&(!angular.isDate(e)||isNaN(e.getTime())||l?(n=new Date(0),s.call(n,m.year,m.month,m.date),u.call(n,m.hours||0,m.minutes||0,m.seconds||0,m.milliseconds||0)):(n=new Date(e),s.call(n,m.year,m.month,m.date),u.call(n,m.hours,m.minutes,m.seconds,m.milliseconds))),n}},this.toTimezone=m,this.fromTimezone=n,this.timezoneToOffset=o,this.addDateMinutes=p,this.convertTimezoneToLocal=q}]),angular.module("ui.bootstrap.isClass",[]).directive("uibIsClass",["$animate",function(a){var b=/^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/,c=/^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;return{restrict:"A",compile:function(d,e){function f(a,b,c){i.push(a),j.push({scope:a,element:b}),o.forEach(function(b,c){g(b,a)}),a.$on("$destroy",h)}function g(b,d){var e=b.match(c),f=d.$eval(e[1]),g=e[2],h=k[b];if(!h){var i=function(b){var c=null;j.some(function(a){var d=a.scope.$eval(m);return d===b?(c=a,!0):void 0}),h.lastActivated!==c&&(h.lastActivated&&a.removeClass(h.lastActivated.element,f),c&&a.addClass(c.element,f),h.lastActivated=c)};k[b]=h={lastActivated:null,scope:d,watchFn:i,compareWithExp:g,watcher:d.$watch(g,i)}}h.watchFn(d.$eval(g))}function h(a){var b=a.targetScope,c=i.indexOf(b);if(i.splice(c,1),j.splice(c,1),i.length){var d=i[0];angular.forEach(k,function(a){a.scope===b&&(a.watcher=d.$watch(a.compareWithExp,a.watchFn),a.scope=d)})}else k={}}var i=[],j=[],k={},l=e.uibIsClass.match(b),m=l[2],n=l[1],o=n.split(",");return f}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.isClass"]).value("$datepickerSuppressError",!1).value("$datepickerLiteralWarning",!0).constant("uibDatepickerConfig",{datepickerMode:"day",formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",maxDate:null,maxMode:"year",minDate:null,minMode:"day",monthColumns:3,ngModelOptions:{},shortcutPropagation:!1,showWeeks:!0,yearColumns:5,yearRows:4}).controller("UibDatepickerController",["$scope","$element","$attrs","$parse","$interpolate","$locale","$log","dateFilter","uibDatepickerConfig","$datepickerLiteralWarning","$datepickerSuppressError","uibDateParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(b){a.datepickerMode=b,a.datepickerOptions.datepickerMode=b}function n(b){var c;if(angular.version.minor<6)c=b.$options||a.datepickerOptions.ngModelOptions||i.ngModelOptions||{},c.getOption=function(a){return c[a]};else{var d=b.$options.getOption("timezone")||(a.datepickerOptions.ngModelOptions?a.datepickerOptions.ngModelOptions.timezone:null)||(i.ngModelOptions?i.ngModelOptions.timezone:null);c=b.$options.createChild(i.ngModelOptions).createChild(a.datepickerOptions.ngModelOptions).createChild(b.$options).createChild({timezone:d})}return c}var o=this,p={$setViewValue:angular.noop},q={},r=[];b.addClass("uib-datepicker"),c.$set("role","application"),a.datepickerOptions||(a.datepickerOptions={}),this.modes=["day","month","year"],["customClass","dateDisabled","datepickerMode","formatDay","formatDayHeader","formatDayTitle","formatMonth","formatMonthTitle","formatYear","maxDate","maxMode","minDate","minMode","monthColumns","showWeeks","shortcutPropagation","startingDay","yearColumns","yearRows"].forEach(function(b){switch(b){case"customClass":case"dateDisabled":a[b]=a.datepickerOptions[b]||angular.noop;break;case"datepickerMode":a.datepickerMode=angular.isDefined(a.datepickerOptions.datepickerMode)?a.datepickerOptions.datepickerMode:i.datepickerMode;break;case"formatDay":case"formatDayHeader":case"formatDayTitle":case"formatMonth":case"formatMonthTitle":case"formatYear":o[b]=angular.isDefined(a.datepickerOptions[b])?e(a.datepickerOptions[b])(a.$parent):i[b];break;case"monthColumns":case"showWeeks":case"shortcutPropagation":case"yearColumns":case"yearRows":o[b]=angular.isDefined(a.datepickerOptions[b])?a.datepickerOptions[b]:i[b];break;case"startingDay":angular.isDefined(a.datepickerOptions.startingDay)?o.startingDay=a.datepickerOptions.startingDay:angular.isNumber(i.startingDay)?o.startingDay=i.startingDay:o.startingDay=(f.DATETIME_FORMATS.FIRSTDAYOFWEEK+8)%7;break;case"maxDate":case"minDate":a.$watch("datepickerOptions."+b,function(a){a?angular.isDate(a)?o[b]=l.fromTimezone(new Date(a),q.getOption("timezone")):(j&&g.warn("Literal date support has been deprecated, please switch to date object usage"),o[b]=new Date(h(a,"medium"))):o[b]=i[b]?l.fromTimezone(new Date(i[b]),q.getOption("timezone")):null,o.refreshView()});break;case"maxMode":case"minMode":a.datepickerOptions[b]?a.$watch(function(){return a.datepickerOptions[b]},function(c){o[b]=a[b]=angular.isDefined(c)?c:a.datepickerOptions[b],("minMode"===b&&o.modes.indexOf(a.datepickerOptions.datepickerMode)<o.modes.indexOf(o[b])||"maxMode"===b&&o.modes.indexOf(a.datepickerOptions.datepickerMode)>o.modes.indexOf(o[b]))&&(a.datepickerMode=o[b],a.datepickerOptions.datepickerMode=o[b])}):o[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&r.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,o.refreshView()})),a.isActive=function(b){return 0===o.compare(b.date,o.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(b){p=b,q=n(p),a.datepickerOptions.initDate?(o.activeDate=l.fromTimezone(a.datepickerOptions.initDate,q.getOption("timezone"))||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(p.$isEmpty(p.$modelValue)||p.$invalid)&&(o.activeDate=l.fromTimezone(a,q.getOption("timezone")),o.refreshView())})):o.activeDate=new Date;var c=p.$modelValue?new Date(p.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,q.getOption("timezone")):l.fromTimezone(c,q.getOption("timezone")),p.$render=function(){o.render()}},this.render=function(){if(p.$viewValue){var a=new Date(p.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,q.getOption("timezone")):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=p.$viewValue?new Date(p.$viewValue):null;b=l.fromTimezone(b,q.getOption("timezone")),p.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=p.$viewValue?new Date(p.$viewValue):null;d=l.fromTimezone(d,q.getOption("timezone"));var e=new Date;e=l.fromTimezone(e,q.getOption("timezone"));var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:0>f,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),o.activeDate&&0===this.compare(g.date,o.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===o.minMode){var c=p.$viewValue?l.fromTimezone(new Date(p.$viewValue),q.getOption("timezone")):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,q.getOption("timezone")),p.$setViewValue(c),p.$render()}else o.activeDate=b,m(o.modes[o.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=o.activeDate.getFullYear()+a*(o.step.years||0),c=o.activeDate.getMonth()+a*(o.step.months||0);o.activeDate.setFullYear(b,c,1),o.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===o.maxMode&&1===b||a.datepickerMode===o.minMode&&-1===b||(m(o.modes[o.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var s=function(){o.element[0].focus()};a.$on("uib:datepicker.focus",s),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),o.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(o.isDisabled(o.activeDate))return;a.select(o.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(o.handleKeyDown(c,b),o.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;r.length;)r.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(this.activeDate);f.setFullYear(b,d,1);var g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate()),d=new Date(b.getFullYear(),b.getMonth(),b.getDate());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(this.activeDate),b.setFullYear(e,f,1),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,this.monthColumns),a.yearHeaderColspan=this.monthColumns>3?this.monthColumns-2:1},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth()),d=new Date(b.getFullYear(),b.getMonth());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=this.monthColumns;else if("right"===a)c+=1;else if("down"===a)c+=this.monthColumns;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/f,10)*f+1}var e,f;this.element=b,this.yearpickerInit=function(){e=this.yearColumns,f=this.yearRows*e,this.step={years:f}},this._refreshView=function(){for(var b,c=new Array(f),g=0,h=d(this.activeDate.getFullYear());f>g;g++)b=new Date(this.activeDate),b.setFullYear(h+g,0,1),c[g]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+g});a.title=[c[0].label,c[f-1].label].join(" - "),a.rows=this.split(c,e),a.columns=e},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=e:"right"===a?c+=1:"down"===a?c+=e:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*f:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+f-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/datepicker.html"},scope:{datepickerOptions:"=?"},require:["uibDatepicker","^ngModel"],restrict:"A",controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/day.html"},
+require:["^uibDatepicker","uibDaypicker"],restrict:"A",controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/month.html"},require:["^uibDatepicker","uibMonthpicker"],restrict:"A",controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/year.html"},require:["^uibDatepicker","uibYearpicker"],restrict:"A",controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){var c,d,e={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},f={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},g=/(HTML|BODY)/;return{getRawNode:function(a){return a.nodeName?a:a[0]||a},parseStyle:function(a){return a=parseFloat(a),isFinite(a)?a:0},offsetParent:function(c){function d(a){return"static"===(b.getComputedStyle(a).position||"static")}c=this.getRawNode(c);for(var e=c.offsetParent||a[0].documentElement;e&&e!==a[0].documentElement&&d(e);)e=e.offsetParent;return e||a[0].documentElement},scrollbarWidth:function(e){if(e){if(angular.isUndefined(d)){var f=a.find("body");f.addClass("uib-position-body-scrollbar-measure"),d=b.innerWidth-f[0].clientWidth,d=isFinite(d)?d:0,f.removeClass("uib-position-body-scrollbar-measure")}return d}if(angular.isUndefined(c)){var g=angular.element('<div class="uib-position-scrollbar-measure"></div>');a.find("body").append(g),c=g[0].offsetWidth-g[0].clientWidth,c=isFinite(c)?c:0,g.remove()}return c},scrollbarPadding:function(a){a=this.getRawNode(a);var c=b.getComputedStyle(a),d=this.parseStyle(c.paddingRight),e=this.parseStyle(c.paddingBottom),f=this.scrollParent(a,!1,!0),h=this.scrollbarWidth(g.test(f.tagName));return{scrollbarWidth:h,widthOverflow:f.scrollWidth>f.clientWidth,right:d+h,originalRight:d,heightOverflow:f.scrollHeight>f.clientHeight,bottom:e+h,originalBottom:e}},isScrollable:function(a,c){a=this.getRawNode(a);var d=c?e.hidden:e.normal,f=b.getComputedStyle(a);return d.test(f.overflow+f.overflowY+f.overflowX)},scrollParent:function(c,d,f){c=this.getRawNode(c);var g=d?e.hidden:e.normal,h=a[0].documentElement,i=b.getComputedStyle(c);if(f&&g.test(i.overflow+i.overflowY+i.overflowX))return c;var j="absolute"===i.position,k=c.parentElement||h;if(k===h||"fixed"===i.position)return h;for(;k.parentElement&&k!==h;){var l=b.getComputedStyle(k);if(j&&"static"!==l.position&&(j=!1),!j&&g.test(l.overflow+l.overflowY+l.overflowX))break;k=k.parentElement}return k},position:function(c,d){c=this.getRawNode(c);var e=this.offset(c);if(d){var f=b.getComputedStyle(c);e.top-=this.parseStyle(f.marginTop),e.left-=this.parseStyle(f.marginLeft)}var g=this.offsetParent(c),h={top:0,left:0};return g!==a[0].documentElement&&(h=this.offset(g),h.top+=g.clientTop-g.scrollTop,h.left+=g.clientLeft-g.scrollLeft),{width:Math.round(angular.isNumber(e.width)?e.width:c.offsetWidth),height:Math.round(angular.isNumber(e.height)?e.height:c.offsetHeight),top:Math.round(e.top-h.top),left:Math.round(e.left-h.left)}},offset:function(c){c=this.getRawNode(c);var d=c.getBoundingClientRect();return{width:Math.round(angular.isNumber(d.width)?d.width:c.offsetWidth),height:Math.round(angular.isNumber(d.height)?d.height:c.offsetHeight),top:Math.round(d.top+(b.pageYOffset||a[0].documentElement.scrollTop)),left:Math.round(d.left+(b.pageXOffset||a[0].documentElement.scrollLeft))}},viewportOffset:function(c,d,e){c=this.getRawNode(c),e=e!==!1;var f=c.getBoundingClientRect(),g={top:0,left:0,bottom:0,right:0},h=d?a[0].documentElement:this.scrollParent(c),i=h.getBoundingClientRect();if(g.top=i.top+h.clientTop,g.left=i.left+h.clientLeft,h===a[0].documentElement&&(g.top+=b.pageYOffset,g.left+=b.pageXOffset),g.bottom=g.top+h.clientHeight,g.right=g.left+h.clientWidth,e){var j=b.getComputedStyle(h);g.top+=this.parseStyle(j.paddingTop),g.bottom-=this.parseStyle(j.paddingBottom),g.left+=this.parseStyle(j.paddingLeft),g.right-=this.parseStyle(j.paddingRight)}return{top:Math.round(f.top-g.top),bottom:Math.round(g.bottom-f.bottom),left:Math.round(f.left-g.left),right:Math.round(g.right-f.right)}},parsePlacement:function(a){var b=f.auto.test(a);return b&&(a=a.replace(f.auto,"")),a=a.split("-"),a[0]=a[0]||"top",f.primary.test(a[0])||(a[0]="top"),a[1]=a[1]||"center",f.secondary.test(a[1])||(a[1]="center"),b?a[2]=!0:a[2]=!1,a},positionElements:function(a,c,d,e){a=this.getRawNode(a),c=this.getRawNode(c);var g=angular.isDefined(c.offsetWidth)?c.offsetWidth:c.prop("offsetWidth"),h=angular.isDefined(c.offsetHeight)?c.offsetHeight:c.prop("offsetHeight");d=this.parsePlacement(d);var i=e?this.offset(a):this.position(a),j={top:0,left:0,placement:""};if(d[2]){var k=this.viewportOffset(a,e),l=b.getComputedStyle(c),m={width:g+Math.round(Math.abs(this.parseStyle(l.marginLeft)+this.parseStyle(l.marginRight))),height:h+Math.round(Math.abs(this.parseStyle(l.marginTop)+this.parseStyle(l.marginBottom)))};if(d[0]="top"===d[0]&&m.height>k.top&&m.height<=k.bottom?"bottom":"bottom"===d[0]&&m.height>k.bottom&&m.height<=k.top?"top":"left"===d[0]&&m.width>k.left&&m.width<=k.right?"right":"right"===d[0]&&m.width>k.right&&m.width<=k.left?"left":d[0],d[1]="top"===d[1]&&m.height-i.height>k.bottom&&m.height-i.height<=k.top?"bottom":"bottom"===d[1]&&m.height-i.height>k.top&&m.height-i.height<=k.bottom?"top":"left"===d[1]&&m.width-i.width>k.right&&m.width-i.width<=k.left?"right":"right"===d[1]&&m.width-i.width>k.left&&m.width-i.width<=k.right?"left":d[1],"center"===d[1])if(f.vertical.test(d[0])){var n=i.width/2-g/2;k.left+n<0&&m.width-i.width<=k.right?d[1]="left":k.right+n<0&&m.width-i.width<=k.left&&(d[1]="right")}else{var o=i.height/2-m.height/2;k.top+o<0&&m.height-i.height<=k.bottom?d[1]="top":k.bottom+o<0&&m.height-i.height<=k.top&&(d[1]="bottom")}}switch(d[0]){case"top":j.top=i.top-h;break;case"bottom":j.top=i.top+i.height;break;case"left":j.left=i.left-g;break;case"right":j.left=i.left+i.width}switch(d[1]){case"top":j.top=i.top;break;case"bottom":j.top=i.top+i.height-h;break;case"left":j.left=i.left;break;case"right":j.left=i.left+i.width-g;break;case"center":f.vertical.test(d[0])?j.left=i.left+i.width/2-g/2:j.top=i.top+i.height/2-h/2}return j.top=Math.round(j.top),j.left=Math.round(j.left),j.placement="center"===d[1]?d[0]:d[0]+"-"+d[1],j},adjustTop:function(a,b,c,d){return-1!==a.indexOf("top")&&c!==d?{top:b.top-d+"px"}:void 0},positionArrow:function(a,c){a=this.getRawNode(a);var d=a.querySelector(".tooltip-inner, .popover-inner");if(d){var e=angular.element(d).hasClass("tooltip-inner"),g=e?a.querySelector(".tooltip-arrow"):a.querySelector(".arrow");if(g){var h={top:"",bottom:"",left:"",right:""};if(c=this.parsePlacement(c),"center"===c[1])return void angular.element(g).css(h);var i="border-"+c[0]+"-width",j=b.getComputedStyle(g)[i],k="border-";k+=f.vertical.test(c[0])?c[0]+"-"+c[1]:c[1]+"-"+c[0],k+="-radius";var l=b.getComputedStyle(e?d:a)[k];switch(c[0]){case"top":h.bottom=e?"0":"-"+j;break;case"bottom":h.top=e?"0":"-"+j;break;case"left":h.right=e?"0":"-"+j;break;case"right":h.left=e?"0":"-"+j}h[c[1]]=l,angular.element(g).css(h)}}}}}]),angular.module("ui.bootstrap.datepickerPopup",["ui.bootstrap.datepicker","ui.bootstrap.position"]).value("$datepickerPopupLiteralWarning",!0).constant("uibDatepickerPopupConfig",{altInputFormats:[],appendToBody:!1,clearText:"Clear",closeOnDateSelection:!0,closeText:"Done",currentText:"Today",datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"uib/template/datepickerPopup/popup.html",datepickerTemplateUrl:"uib/template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},onOpenFocus:!0,showButtonBar:!0,placement:"auto bottom-left"}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$log","$parse","$window","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout","uibDatepickerConfig","$datepickerPopupLiteralWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(b){var c=l.parse(b,x,a.date);if(isNaN(c))for(var d=0;d<J.length;d++)if(c=l.parse(b,J[d],a.date),!isNaN(c))return c;return c}function r(a){if(angular.isNumber(a)&&(a=new Date(a)),!a)return null;if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=q(a);if(!isNaN(b))return l.toTimezone(b,H.getOption("timezone"))}return H.getOption("allowInvalid")?a:void 0}function s(a,b){var d=a||b;return c.ngRequired||d?(angular.isNumber(d)&&(d=new Date(d)),d?angular.isDate(d)&&!isNaN(d)?!0:angular.isString(d)?!isNaN(q(d)):!1:!0):!0}function t(c){if(a.isOpen||!a.disabled){var d=I[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}}function u(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}function v(){if(a.isOpen){var d=angular.element(I[0].querySelector(".uib-datepicker-popup")),e=c.popupPlacement?c.popupPlacement:m.placement,f=j.positionElements(b,d,e,z);d.css({top:f.top+"px",left:f.left+"px"}),d.hasClass("uib-position-measure")&&d.removeClass("uib-position-measure")}}function w(a){var b;return angular.version.minor<6?(b=angular.isObject(a.$options)?a.$options:{timezone:null},b.getOption=function(a){return b[a]}):b=a.$options,b}var x,y,z,A,B,C,D,E,F,G,H,I,J,K=!1,L=[];this.init=function(e){if(G=e,H=w(G),y=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):m.closeOnDateSelection,z=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):m.appendToBody,A=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):m.onOpenFocus,B=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:m.datepickerPopupTemplateUrl,C=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:m.datepickerTemplateUrl,J=angular.isDefined(c.altInputFormats)?a.$parent.$eval(c.altInputFormats):m.altInputFormats,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):m.showButtonBar,m.html5Types[c.type]?(x=m.html5Types[c.type],K=!0):(x=c.uibDatepickerPopup||m.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||m.datepickerPopup;if(c!==x&&(x=c,G.$modelValue=null,!x))throw new Error("uibDatepickerPopup must have a date format specified.")})),!x)throw new Error("uibDatepickerPopup must have a date format specified.");if(K&&c.uibDatepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");D=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),D.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":B}),E=angular.element(D.children()[0]),E.attr("template-url",C),a.datepickerOptions||(a.datepickerOptions={}),K&&"month"===c.type&&(a.datepickerOptions.datepickerMode="month",a.datepickerOptions.minMode="month"),E.attr("datepicker-options","datepickerOptions"),K?G.$formatters.push(function(b){return a.date=l.fromTimezone(b,H.getOption("timezone")),b}):(G.$$parserName="date",G.$validators.date=s,G.$parsers.unshift(r),G.$formatters.push(function(b){return G.$isEmpty(b)?(a.date=b,b):(angular.isNumber(b)&&(b=new Date(b)),a.date=l.fromTimezone(b,H.getOption("timezone")),l.filter(a.date,x))})),G.$viewChangeListeners.push(function(){a.date=q(G.$viewValue)}),b.on("keydown",u),I=d(D)(a),D.remove(),z?h.find("body").append(I):b.after(I),a.$on("$destroy",function(){for(a.isOpen===!0&&(i.$$phase||a.$apply(function(){a.isOpen=!1})),I.remove(),b.off("keydown",u),h.off("click",t),F&&F.off("scroll",v),angular.element(g).off("resize",v);L.length;)L.shift()()})},a.getText=function(b){return a[b+"Text"]||m[b+"Text"]},a.isDisabled=function(b){"today"===b&&(b=l.fromTimezone(new Date,H.getOption("timezone")));var c={};return angular.forEach(["minDate","maxDate"],function(b){a.datepickerOptions[b]?angular.isDate(a.datepickerOptions[b])?c[b]=new Date(a.datepickerOptions[b]):(p&&e.warn("Literal date support has been deprecated, please switch to date object usage"),c[b]=new Date(k(a.datepickerOptions[b],"medium"))):c[b]=null}),a.datepickerOptions&&c.minDate&&a.compare(b,c.minDate)<0||c.maxDate&&a.compare(b,c.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){a.date=c;var d=a.date?l.filter(a.date,x):null;b.val(d),G.$setViewValue(d),y&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(c.stopPropagation(),a.isOpen=!1,b[0].focus())},a.select=function(b,c){if(c.stopPropagation(),"today"===b){var d=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(d.getFullYear(),d.getMonth(),d.getDate())):(b=l.fromTimezone(d,H.getOption("timezone")),b.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(c){c.stopPropagation(),a.isOpen=!1,b[0].focus()},a.disabled=angular.isDefined(c.disabled)||!1,c.ngDisabled&&L.push(a.$parent.$watch(f(c.ngDisabled),function(b){a.disabled=b})),a.$watch("isOpen",function(d){d?a.disabled?a.isOpen=!1:n(function(){v(),A&&a.$broadcast("uib:datepicker.focus"),h.on("click",t);var d=c.popupPlacement?c.popupPlacement:m.placement;z||j.parsePlacement(d)[2]?(F=F||angular.element(j.scrollParent(b)),F&&F.on("scroll",v)):F=null,angular.element(g).on("resize",v)},0,!1):(h.off("click",t),F&&F.off("scroll",v),angular.element(g).off("resize",v))}),a.$on("uib:datepicker.mode",function(){n(v,0,!1)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{datepickerOptions:"=?",isOpen:"=?",currentText:"@",clearText:"@",closeText:"@"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/datepickerPopup/popup.html"}}}),angular.module("ui.bootstrap.debounce",[]).factory("$$debounce",["$timeout",function(a){return function(b,c){var d;return function(){var e=this,f=Array.prototype.slice.call(arguments);d&&a.cancel(d),d=a(function(){b.apply(e,f)},c)}}}]),angular.module("ui.bootstrap.multiMap",[]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.multiMap","ui.bootstrap.position"]).constant("uibDropdownConfig",{appendToOpenClass:"uib-dropdown-open",openClass:"open"}).service("uibDropdownService",["$document","$rootScope","$$multiMap",function(a,b,c){var d=null,e=c.createNew();this.isOnlyOpen=function(a,b){var c=e.get(b);if(c){var d=c.reduce(function(b,c){return c.scope===a?c:b},{});if(d)return 1===c.length}return!1},this.open=function(b,c,g){if(d||a.on("click",f),d&&d!==b&&(d.isOpen=!1),d=b,g){var h=e.get(g);if(h){var i=h.map(function(a){return a.scope});-1===i.indexOf(b)&&e.put(g,{scope:b})}else e.put(g,{scope:b})}},this.close=function(b,c,g){if(d===b&&(a.off("click",f),a.off("keydown",this.keybindFilter),d=null),g){var h=e.get(g);if(h){var i=h.reduce(function(a,c){return c.scope===b?c:a},{});i&&e.remove(g,i)}}};var f=function(a){if(d&&d.isOpen&&!(a&&"disabled"===d.getAutoClose()||a&&3===a.which)){var c=d.getToggleElement();if(!(a&&c&&c[0].contains(a.target))){var e=d.getDropdownElement();a&&"outsideClick"===d.getAutoClose()&&e&&e[0].contains(a.target)||(d.focusToggleElement(),d.isOpen=!1,b.$$phase||d.$apply())}}};this.keybindFilter=function(a){if(d){var b=d.getDropdownElement(),c=d.getToggleElement(),e=b&&b[0].contains(a.target),g=c&&c[0].contains(a.target);27===a.which?(a.stopPropagation(),d.focusToggleElement(),f()):d.isKeynavEnabled()&&-1!==[38,40].indexOf(a.which)&&d.isOpen&&(e||g)&&(a.preventDefault(),a.stopPropagation(),d.focusDropdownEntry(a.which))}}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){function l(){b.append(o.dropdownMenu)}var m,n,o=this,p=a.$new(),q=e.appendToOpenClass,r=e.openClass,s=angular.noop,t=c.onToggle?d(c.onToggle):angular.noop,u=!1,v=i.find("body");b.addClass("dropdown"),this.init=function(){c.isOpen&&(n=d(c.isOpen),s=n.assign,a.$watch(n,function(a){p.isOpen=!!a})),u=angular.isDefined(c.keyboardNav)},this.toggle=function(a){return p.isOpen=arguments.length?!!a:!p.isOpen,angular.isFunction(s)&&s(p,p.isOpen),p.isOpen},this.isOpen=function(){return p.isOpen},p.getToggleElement=function(){return o.toggleElement},p.getAutoClose=function(){return c.autoClose||"always"},p.getElement=function(){return b},p.isKeynavEnabled=function(){return u},p.focusDropdownEntry=function(a){var c=o.dropdownMenu?angular.element(o.dropdownMenu).find("a"):b.find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(o.selectedOption)?o.selectedOption=o.selectedOption===c.length-1?o.selectedOption:o.selectedOption+1:o.selectedOption=0;break;case 38:angular.isNumber(o.selectedOption)?o.selectedOption=0===o.selectedOption?0:o.selectedOption-1:o.selectedOption=c.length-1}c[o.selectedOption].focus()},p.getDropdownElement=function(){return o.dropdownMenu},p.focusToggleElement=function(){o.toggleElement&&o.toggleElement[0].focus()},p.$watch("isOpen",function(e,n){var u=null,w=!1;if(angular.isDefined(c.dropdownAppendTo)){var x=d(c.dropdownAppendTo)(p);x&&(u=angular.element(x))}if(angular.isDefined(c.dropdownAppendToBody)){var y=d(c.dropdownAppendToBody)(p);y!==!1&&(w=!0)}if(w&&!u&&(u=v),u&&o.dropdownMenu&&(e?(u.append(o.dropdownMenu),b.on("$destroy",l)):(b.off("$destroy",l),l())),u&&o.dropdownMenu){var z,A,B,C=h.positionElements(b,o.dropdownMenu,"bottom-left",!0),D=0;if(z={top:C.top+"px",display:e?"block":"none"},A=o.dropdownMenu.hasClass("dropdown-menu-right"),A?(z.left="auto",B=h.scrollbarPadding(u),B.heightOverflow&&B.scrollbarWidth&&(D=B.scrollbarWidth),z.right=window.innerWidth-D-(C.left+b.prop("offsetWidth"))+"px"):(z.left=C.left+"px",z.right="auto"),!w){var E=h.offset(u);z.top=C.top-E.top+"px",A?z.right=window.innerWidth-(C.left-E.left+b.prop("offsetWidth"))+"px":z.left=C.left-E.left+"px"}o.dropdownMenu.css(z)}var F=u?u:b,G=u?q:r,H=F.hasClass(G),I=f.isOnlyOpen(a,u);if(H===!e){var J;J=u?I?"removeClass":"addClass":e?"addClass":"removeClass",g[J](F,G).then(function(){angular.isDefined(e)&&e!==n&&t(a,{open:!!e})})}if(e)o.dropdownMenuTemplateUrl?k(o.dropdownMenuTemplateUrl).then(function(a){m=p.$new(),j(a.trim())(m,function(a){var b=a;o.dropdownMenu.replaceWith(b),o.dropdownMenu=b,i.on("keydown",f.keybindFilter)})}):i.on("keydown",f.keybindFilter),p.focusToggleElement(),f.open(p,b,u);else{if(f.close(p,b,u),o.dropdownMenuTemplateUrl){m&&m.$destroy();var K=angular.element('<ul class="dropdown-menu"></ul>');o.dropdownMenu.replaceWith(K),o.dropdownMenu=K}o.selectedOption=null}angular.isFunction(s)&&s(a,e)})}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.on("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.off("click",e)})}}}}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b===a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b===a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.pop()},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.multiMap","ui.bootstrap.stackedMap","ui.bootstrap.position"]).provider("$uibResolve",function(){var a=this;this.resolver=null,this.setResolver=function(a){this.resolver=a},this.$get=["$injector","$q",function(b,c){var d=a.resolver?b.get(a.resolver):null;return{resolve:function(a,e,f,g){if(d)return d.resolve(a,e,f,g);var h=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?h.push(c.resolve(b.invoke(a))):angular.isString(a)?h.push(c.resolve(b.get(a))):h.push(c.resolve(a))}),c.all(h).then(function(b){var c={},d=0;return angular.forEach(a,function(a,e){c[e]=b[d++]}),c})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,e){e.modalInClass&&(a.addClass(d,e.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(c,f){var g=f();b.modalOptions.animation?a.removeClass(d,e.modalInClass).then(g):g()}))}return{restrict:"A",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(a,b,c,d){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/modal/window.html"},link:function(e,f,g){f.addClass(g.windowTopClass||""),e.size=g.size,e.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",e.close),e.$isRendered=!0;var h=b.defer();e.$$postDigest(function(){h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=c(f,{addClass:g.modalInClass}).start(),e.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();c(f,{removeClass:g.modalInClass}).start().then(d)})),b.when(h).then(function(){var b=a.getTop();if(b&&a.modalRendered(b.key),!d[0].activeElement||!f[0].contains(d[0].activeElement)){var c=f[0].querySelector("[autofocus]");c?c.focus():f[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(a){return{link:function(b,c,d,e,f){f(b.$parent,function(b){c.empty(),a.enter(b,c)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(a,b,c,d,e,f,g,h,i){function j(a){var b="-";return a.replace(E,function(a,c){return(c?b:"")+a.toLowerCase()})}function k(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)}function l(){for(var a=-1,b=x.keys(),c=0;c<b.length;c++)x.get(b[c]).value.backdrop&&(a=c);return a>-1&&A>a&&(a=A),a}function m(a,b){var c=x.get(a).value,d=c.appendTo;x.remove(a),B=x.top(),B&&(A=parseInt(B.value.modalDomEl.attr("index"),10)),p(c.modalDomEl,c.modalScope,function(){var b=c.openedClass||w;y.remove(b,a);var e=y.hasKey(b);d.toggleClass(b,e),!e&&v&&v.heightOverflow&&v.scrollbarWidth&&(v.originalRight?d.css({paddingRight:v.originalRight+"px"}):d.css({paddingRight:""}),v=null),n(!0)},c.closedDeferred),o(),b&&b.focus?b.focus():d.focus&&d.focus()}function n(a){var b;x.length()>0&&(b=x.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function o(){if(t&&-1===l()){var a=u;p(t,u,function(){a=null}),t=void 0,u=void 0}}function p(b,c,d,e){function g(){g.done||(g.done=!0,a.leave(b).then(function(){d&&d(),b.remove(),e&&e.resolve()}),c.$destroy())}var h,i=null,j=function(){return h||(h=f.defer(),i=h.promise),function(){h.resolve()}};return c.$broadcast(z.NOW_CLOSING_EVENT,j),f.when(i).then(g)}function q(a){if(a.isDefaultPrevented())return a;var b=x.top();if(b)switch(a.which){case 27:b.value.keyboard&&(a.preventDefault(),e.$apply(function(){z.dismiss(b.key,"escape key press")}));break;case 9:var c=z.loadFocusElementList(b),d=!1;a.shiftKey?(z.isFocusInFirstItem(a,c)||z.isModalFocused(a,b))&&(d=z.focusLastFocusableElement(c)):z.isFocusInLastItem(a,c)&&(d=z.focusFirstFocusableElement(c)),d&&(a.preventDefault(),a.stopPropagation())}}function r(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}function s(){Array.prototype.forEach.call(document.querySelectorAll("["+C+"]"),function(a){var b=parseInt(a.getAttribute(C),10),c=b-1;a.setAttribute(C,c),c||(a.removeAttribute(C),a.removeAttribute("aria-hidden"))})}var t,u,v,w="modal-open",x=h.createNew(),y=g.createNew(),z={NOW_CLOSING_EVENT:"modal.stack.now-closing"},A=0,B=null,C="data-bootstrap-modal-aria-hidden-count",D="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",E=/[A-Z]/g;return e.$watch(l,function(a){u&&(u.index=a)}),c.on("keydown",q),e.$on("$destroy",function(){c.off("keydown",q)}),z.open=function(b,f){function g(a){function b(a){var b=a.parent()?a.parent().children():[];return Array.prototype.filter.call(b,function(b){return b!==a[0]})}if(a&&"BODY"!==a[0].tagName)return b(a).forEach(function(a){var b="true"===a.getAttribute("aria-hidden"),c=parseInt(a.getAttribute(C),10);c||(c=b?1:0),a.setAttribute(C,c+1),a.setAttribute("aria-hidden","true")}),g(a.parent())}var h=c[0].activeElement,k=f.openedClass||w;n(!1),B=x.top(),x.add(b,{deferred:f.deferred,renderDeferred:f.renderDeferred,closedDeferred:f.closedDeferred,modalScope:f.scope,backdrop:f.backdrop,keyboard:f.keyboard,openedClass:f.openedClass,windowTopClass:f.windowTopClass,animation:f.animation,appendTo:f.appendTo}),y.put(k,b);var m=f.appendTo,o=l();o>=0&&!t&&(u=e.$new(!0),u.modalOptions=f,u.index=o,t=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),t.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),f.backdropClass&&t.addClass(f.backdropClass),f.animation&&t.attr("modal-animation","true"),d(t)(u),a.enter(t,m),i.isScrollable(m)&&(v=i.scrollbarPadding(m),v.heightOverflow&&v.scrollbarWidth&&m.css({paddingRight:v.right+"px"})));var p;f.component?(p=document.createElement(j(f.component.name)),p=angular.element(p),p.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):p=f.content,A=B?parseInt(B.value.modalDomEl.attr("index"),10)+1:0;var q=angular.element('<div uib-modal-window="modal-window"></div>');q.attr({"class":"modal","template-url":f.windowTemplateUrl,"window-top-class":f.windowTopClass,role:"dialog","aria-labelledby":f.ariaLabelledBy,"aria-describedby":f.ariaDescribedBy,size:f.size,index:A,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(p),f.windowClass&&q.addClass(f.windowClass),f.animation&&q.attr("modal-animation","true"),m.addClass(k),f.scope&&(f.scope.$$topModalIndex=A),a.enter(d(q)(f.scope),m),x.top().value.modalDomEl=q,x.top().value.modalOpener=h,g(q)},z.close=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),m(a,c.value.modalOpener),!0):!c},z.dismiss=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),m(a,c.value.modalOpener),!0):!c},z.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},z.getTop=function(){return x.top()},z.modalRendered=function(a){var b=x.get(a);b&&b.value.renderDeferred.resolve()},z.focusFirstFocusableElement=function(a){return a.length>0?(a[0].focus(),!0):!1},z.focusLastFocusableElement=function(a){return a.length>0?(a[a.length-1].focus(),!0):!1},z.isModalFocused=function(a,b){if(a&&b){var c=b.value.modalDomEl;if(c&&c.length)return(a.target||a.srcElement)===c[0]}return!1},z.isFocusInFirstItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[0]:!1},z.isFocusInLastItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[b.length-1]:!1},z.loadFocusElementList=function(a){if(a){var b=a.value.modalDomEl;if(b&&b.length){var c=b[0].querySelectorAll(D);return c?Array.prototype.filter.call(c,function(a){return k(a)}):c}}},z}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?c.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}var j={},k=null;return j.getPromiseChain=function(){return k},j.open=function(e){function j(){return q}var l=c.defer(),m=c.defer(),n=c.defer(),o=c.defer(),p={result:l.promise,opened:m.promise,closed:n.promise,rendered:o.promise,close:function(a){return h.close(p,a)},dismiss:function(a){return h.dismiss(p,a)}};if(e=angular.extend({},a.options,e),e.resolve=e.resolve||{},e.appendTo=e.appendTo||d.find("body").eq(0),!e.appendTo.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");if(!e.component&&!e.template&&!e.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var q;q=e.component?c.when(g.resolve(e.resolve,{},null,null)):c.all([i(e),g.resolve(e.resolve,{},null,null)]);var r;return r=k=c.all([k]).then(j,j).then(function(a){function c(b,c,d,e){b.$scope=g,b.$scope.$resolve={},d?b.$scope.$uibModalInstance=p:b.$uibModalInstance=p;var f=c?a[1]:a;angular.forEach(f,function(a,c){e&&(b[c]=a),b.$scope.$resolve[c]=a})}var d=e.scope||b,g=d.$new();g.$close=p.close,g.$dismiss=p.dismiss,g.$on("$destroy",function(){g.$$uibDestructionScheduled||g.$dismiss("$uibUnscheduledDestruction")});var i,j,k={scope:g,deferred:l,renderDeferred:o,closedDeferred:n,animation:e.animation,backdrop:e.backdrop,keyboard:e.keyboard,backdropClass:e.backdropClass,windowTopClass:e.windowTopClass,windowClass:e.windowClass,windowTemplateUrl:e.windowTemplateUrl,ariaLabelledBy:e.ariaLabelledBy,ariaDescribedBy:e.ariaDescribedBy,size:e.size,openedClass:e.openedClass,appendTo:e.appendTo},q={},r={};e.component?(c(q,!1,!0,!1),q.name=e.component,k.component=q):e.controller&&(c(r,!0,!1,!0),j=f(e.controller,r,!0,e.controllerAs),e.controllerAs&&e.bindToController&&(i=j.instance,i.$close=g.$close,i.$dismiss=g.$dismiss,angular.extend(i,{$resolve:r.$scope.$resolve},d)),i=j(),angular.isFunction(i.$onInit)&&i.$onInit()),e.component||(k.content=a[0]),h.open(p,k),m.resolve(!0)},function(a){m.reject(a),l.reject(a)})["finally"](function(){k===r&&(k=null)}),p},j}]};return a}),angular.module("ui.bootstrap.paging",[]).factory("uibPaging",["$parse",function(a){return{create:function(b,c,d){b.setNumPages=d.numPages?a(d.numPages).assign:angular.noop,b.ngModelCtrl={$setViewValue:angular.noop},b._watchers=[],b.init=function(a,e){b.ngModelCtrl=a,b.config=e,a.$render=function(){b.render()},d.itemsPerPage?b._watchers.push(c.$parent.$watch(d.itemsPerPage,function(a){
+b.itemsPerPage=parseInt(a,10),c.totalPages=b.calculateTotalPages(),b.updatePage()})):b.itemsPerPage=e.itemsPerPage,c.$watch("totalItems",function(a,d){(angular.isDefined(a)||a!==d)&&(c.totalPages=b.calculateTotalPages(),b.updatePage())})},b.calculateTotalPages=function(){var a=b.itemsPerPage<1?1:Math.ceil(c.totalItems/b.itemsPerPage);return Math.max(a||0,1)},b.render=function(){c.page=parseInt(b.ngModelCtrl.$viewValue,10)||1},c.selectPage=function(a,d){d&&d.preventDefault();var e=!c.ngDisabled||!d;e&&c.page!==a&&a>0&&a<=c.totalPages&&(d&&d.target&&d.target.blur(),b.ngModelCtrl.$setViewValue(a),b.ngModelCtrl.$render())},c.getText=function(a){return c[a+"Text"]||b.config[a+"Text"]},c.noPrevious=function(){return 1===c.page},c.noNext=function(){return c.page===c.totalPages},b.updatePage=function(){b.setNumPages(c.$parent,c.totalPages),c.page>c.totalPages?c.selectPage(c.totalPages):b.ngModelCtrl.$render()},c.$on("$destroy",function(){for(;b._watchers.length;)b._watchers.shift()()})}}}]),angular.module("ui.bootstrap.pager",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPagerController",["$scope","$attrs","uibPaging","uibPagerConfig",function(a,b,c,d){a.align=angular.isDefined(b.align)?a.$parent.$eval(b.align):d.align,c.create(this,a,b)}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],restrict:"A",controller:"UibPagerController",controllerAs:"pager",templateUrl:function(a,b){return b.templateUrl||"uib/template/pager/pager.html"},link:function(b,c,d,e){c.addClass("pager");var f=e[0],g=e[1];g&&f.init(g,a)}}}]),angular.module("ui.bootstrap.pagination",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPaginationController",["$scope","$attrs","$parse","uibPaging","uibPaginationConfig",function(a,b,c,d,e){function f(a,b,c){return{number:a,text:b,active:c}}function g(a,b){var c=[],d=1,e=b,g=angular.isDefined(i)&&b>i;g&&(j?(d=Math.max(a-Math.floor(i/2),1),e=d+i-1,e>b&&(e=b,d=e-i+1)):(d=(Math.ceil(a/i)-1)*i+1,e=Math.min(d+i-1,b)));for(var h=d;e>=h;h++){var n=f(h,m(h),h===a);c.push(n)}if(g&&i>0&&(!j||k||l)){if(d>1){if(!l||d>3){var o=f(d-1,"...",!1);c.unshift(o)}if(l){if(3===d){var p=f(2,"2",!1);c.unshift(p)}var q=f(1,"1",!1);c.unshift(q)}}if(b>e){if(!l||b-2>e){var r=f(e+1,"...",!1);c.push(r)}if(l){if(e===b-2){var s=f(b-1,b-1,!1);c.push(s)}var t=f(b,b,!1);c.push(t)}}}return c}var h=this,i=angular.isDefined(b.maxSize)?a.$parent.$eval(b.maxSize):e.maxSize,j=angular.isDefined(b.rotate)?a.$parent.$eval(b.rotate):e.rotate,k=angular.isDefined(b.forceEllipses)?a.$parent.$eval(b.forceEllipses):e.forceEllipses,l=angular.isDefined(b.boundaryLinkNumbers)?a.$parent.$eval(b.boundaryLinkNumbers):e.boundaryLinkNumbers,m=angular.isDefined(b.pageLabel)?function(c){return a.$parent.$eval(b.pageLabel,{$page:c})}:angular.identity;a.boundaryLinks=angular.isDefined(b.boundaryLinks)?a.$parent.$eval(b.boundaryLinks):e.boundaryLinks,a.directionLinks=angular.isDefined(b.directionLinks)?a.$parent.$eval(b.directionLinks):e.directionLinks,b.$set("role","menu"),d.create(this,a,b),b.maxSize&&h._watchers.push(a.$parent.$watch(c(b.maxSize),function(a){i=parseInt(a,10),h.render()}));var n=this.render;this.render=function(){n(),a.page>0&&a.page<=a.totalPages&&(a.pages=g(a.page,a.totalPages))}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],restrict:"A",controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"uib/template/pagination/pagination.html"},link:function(a,c,d,e){c.addClass("pagination");var f=e[0],g=e[1];g&&f.init(g,b)}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",placementClassPrefix:"",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",outsideClick:"outsideClick",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){function n(a){if(27===a.which){var b=o.top();b&&(b.value.close(),b=null)}}var o=m.createNew();return h.on("keyup",n),k.$on("$destroy",function(){h.off("keyup",n)}),function(e,k,m,n){function p(a){var b=(a||n.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}n=angular.extend({},b,d,n);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup uib-title="'+r+"title"+s+'" '+(n.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'origin-scope="origScope" class="uib-position-measure '+k+'" tooltip-animation-class="fade"uib-tooltip-classes ng-class="{ in: isOpen }" ></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){P.isOpen?q():m()}function m(){O&&!a.$eval(d[k+"Enable"])||(u(),x(),P.popupDelay?H||(H=g(r,P.popupDelay,!1)):r())}function q(){s(),P.popupCloseDelay?I||(I=g(t,P.popupCloseDelay,!1)):t()}function r(){return s(),u(),P.content?(v(),void P.$evalAsync(function(){P.isOpen=!0,y(!0),U()})):angular.noop}function s(){H&&(g.cancel(H),H=null),J&&(g.cancel(J),J=null)}function t(){P&&P.$evalAsync(function(){P&&(P.isOpen=!1,y(!1),P.animation?G||(G=g(w,150,!1)):w())})}function u(){I&&(g.cancel(I),I=null),G&&(g.cancel(G),G=null)}function v(){E||(F=P.$new(),E=c(F,function(a){M?h.find("body").append(a):b.after(a)}),o.add(P,{close:t}),z())}function w(){s(),u(),A(),E&&(E.remove(),E=null,K&&g.cancel(K)),o.remove(P),F&&(F.$destroy(),F=null)}function x(){P.title=d[k+"Title"],S?P.content=S(a):P.content=d[e],P.popupClass=d[k+"Class"],P.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:n.placement;var b=i.parsePlacement(P.placement);L=b[1]?b[0]+"-"+b[1]:b[0];var c=parseInt(d[k+"PopupDelay"],10),f=parseInt(d[k+"PopupCloseDelay"],10);P.popupDelay=isNaN(c)?n.popupDelay:c,P.popupCloseDelay=isNaN(f)?n.popupCloseDelay:f}function y(b){R&&angular.isFunction(R.assign)&&R.assign(a,b)}function z(){T.length=0,S?(T.push(a.$watch(S,function(a){P.content=a,!a&&P.isOpen&&t()})),T.push(F.$watch(function(){Q||(Q=!0,F.$$postDigest(function(){Q=!1,P&&P.isOpen&&U()}))}))):T.push(d.$observe(e,function(a){P.content=a,!a&&P.isOpen?t():U()})),T.push(d.$observe(k+"Title",function(a){P.title=a,P.isOpen&&U()})),T.push(d.$observe(k+"Placement",function(a){P.placement=a?a:n.placement,P.isOpen&&U()}))}function A(){T.length&&(angular.forEach(T,function(a){a()}),T.length=0)}function B(a){P&&P.isOpen&&E&&(b[0].contains(a.target)||E[0].contains(a.target)||q())}function C(a){27===a.which&&q()}function D(){var c=[],e=[],f=a.$eval(d[k+"Trigger"]);V(),angular.isObject(f)?(Object.keys(f).forEach(function(a){c.push(a),e.push(f[a])}),N={show:c,hide:e}):N=p(f),"none"!==N.show&&N.show.forEach(function(a,c){"outsideClick"===a?(b.on("click",j),h.on("click",B)):a===N.hide[c]?b.on(a,j):a&&(b.on(a,m),b.on(N.hide[c],q)),b.on("keypress",C)})}var E,F,G,H,I,J,K,L,M=angular.isDefined(n.appendToBody)?n.appendToBody:!1,N=p(void 0),O=angular.isDefined(d[k+"Enable"]),P=a.$new(!0),Q=!1,R=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,S=n.useContentExp?l(d[e]):!1,T=[],U=function(){E&&E.html()&&(J||(J=g(function(){var a=i.positionElements(b,E,P.placement,M),c=angular.isDefined(E.offsetHeight)?E.offsetHeight:E.prop("offsetHeight"),d=M?i.offset(b):i.position(b);E.css({top:a.top+"px",left:a.left+"px"});var e=a.placement.split("-");E.hasClass(e[0])||(E.removeClass(L.split("-")[0]),E.addClass(e[0])),E.hasClass(n.placementClassPrefix+a.placement)||(E.removeClass(n.placementClassPrefix+L),E.addClass(n.placementClassPrefix+a.placement)),K=g(function(){var a=angular.isDefined(E.offsetHeight)?E.offsetHeight:E.prop("offsetHeight"),b=i.adjustTop(e,d,c,a);b&&E.css(b),K=null},0,!1),E.hasClass("uib-position-measure")?(i.positionArrow(E,a.placement),E.removeClass("uib-position-measure")):L!==a.placement&&i.positionArrow(E,a.placement),L=a.placement,J=null},0,!1)))};P.origScope=a,P.isOpen=!1,P.contentExp=function(){return P.content},d.$observe("disabled",function(a){a&&s(),a&&P.isOpen&&t()}),R&&a.$watch(R,function(a){P&&!a===P.isOpen&&j()});var V=function(){N.show.forEach(function(a){"outsideClick"===a?b.off("click",j):(b.off(a,m),b.off(a,j)),b.off("keypress",C)}),N.hide.forEach(function(a){"outsideClick"===a?h.off("click",B):b.off(a,q)})};D();var W=a.$eval(d[k+"Animation"]);P.animation=angular.isDefined(W)?!!W:n.animation;var X,Y=k+"AppendToBody";X=Y in d&&void 0===d[Y]?!0:a.$eval(d[Y]),M=angular.isDefined(X)?X:M,a.$on("$destroy",function(){V(),w(),P=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",["$uibPosition",function(a){return{restrict:"A",link:function(b,c,d){if(b.placement){var e=a.parsePlacement(b.placement);c.addClass(e[0])}b.popupClass&&c.addClass(b.popupClass),b.animation&&c.addClass(d.tooltipAnimationClass)}}}]).directive("uibTooltipPopup",function(){return{restrict:"A",scope:{content:"@"},templateUrl:"uib/template/tooltip/tooltip-popup.html"}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{restrict:"A",scope:{contentExp:"&",originScope:"&"},templateUrl:"uib/template/tooltip/tooltip-template-popup.html"}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&"},templateUrl:"uib/template/tooltip/tooltip-html-popup.html"}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{restrict:"A",scope:{uibTitle:"@",contentExp:"&",originScope:"&"},templateUrl:"uib/template/popover/popover-template.html"}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&",uibTitle:"@"},templateUrl:"uib/template/popover/popover-html.html"}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{restrict:"A",scope:{uibTitle:"@",content:"@"},templateUrl:"uib/template/popover/popover.html"}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){function d(){return angular.isDefined(a.maxParam)?a.maxParam:c.max}var e=this,f=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=d(),this.addBar=function(a,b,c){f||b.css({transition:"none"}),this.bars.push(a),a.max=d(),a.title=c&&angular.isDefined(c.title)?c.title:"progressbar",a.$watch("value",function(b){a.recalculatePercentage()}),a.recalculatePercentage=function(){var b=e.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);b>100&&(a.percent-=b-100)},a.$on("$destroy",function(){b=null,e.removeBar(a)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("maxParam",function(a){e.bars.forEach(function(a){a.max=d(),a.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{maxParam:"=?max"},templateUrl:"uib/template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"uib/template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",maxParam:"=?max",type:"@"},templateUrl:"uib/template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,enableReset:!0,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop},e=this;this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff,this.enableReset=angular.isDefined(b.enableReset)?a.$parent.$eval(b.enableReset):c.enableReset;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){if(!a.readonly&&b>=0&&b<=a.range.length){var c=e.enableReset&&d.$viewValue===b?0:b;d.$setViewValue(c),d.$render()}},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue,a.title=e.getTitle(a.value-1)}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],restrict:"A",scope:{readonly:"=?readOnly",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"uib/template/rating/rating.html",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){function b(a){for(var b=0;b<d.tabs.length;b++)if(d.tabs[b].index===a)return b}var c,d=this;d.tabs=[],d.select=function(a,f){if(!e){var g=b(c),h=d.tabs[g];if(h){if(h.tab.onDeselect({$event:f,$selectedIndex:a}),f&&f.isDefaultPrevented())return;h.tab.active=!1}var i=d.tabs[a];i?(i.tab.onSelect({$event:f}),i.tab.active=!0,d.active=i.index,c=i.index):!i&&angular.isDefined(c)&&(d.active=null,c=null)}},d.addTab=function(a){if(d.tabs.push({tab:a,index:a.index}),d.tabs.sort(function(a,b){return a.index>b.index?1:a.index<b.index?-1:0}),a.index===d.active||!angular.isDefined(d.active)&&1===d.tabs.length){var c=b(a.index);d.select(c)}},d.removeTab=function(a){for(var b,c=0;c<d.tabs.length;c++)if(d.tabs[c].tab===a){b=c;break}if(d.tabs[b].index===d.active){var e=b===d.tabs.length-1?b-1:b+1%d.tabs.length;d.select(e)}d.tabs.splice(b,1)},a.$watch("tabset.active",function(a){angular.isDefined(a)&&a!==c&&d.select(b(a))});var e;a.$on("$destroy",function(){e=!0})}]).directive("uibTabset",function(){return{transclude:!0,replace:!0,scope:{},bindToController:{active:"=?",type:"@"},controller:"UibTabsetController",controllerAs:"tabset",templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tabset.html"},link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",replace:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tab.html"},transclude:!0,scope:{heading:"@",index:"=?",classes:"@?",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},controllerAs:"tab",link:function(b,c,d,e,f){b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),angular.isUndefined(d.index)&&(e.tabs&&e.tabs.length?b.index=Math.max.apply(null,e.tabs.map(function(a){return a.index}))+1:b.index=0),angular.isUndefined(d.classes)&&(b.classes=""),b.select=function(a){if(!b.disabled){for(var c,d=0;d<e.tabs.length;d++)if(e.tabs[d].tab===b){c=d;break}e.select(c,a)}},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:"^uibTab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase()||"uib:tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^uibTabset",link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude).tab;e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,secondStep:1,showMeridian:!0,showSeconds:!1,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0,templateUrl:"uib/template/timepicker/timepicker.html"}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=+a.hours,c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c&&""!==a.hours?(a.showMeridian&&(12===b&&(b=0),a.meridian===y[1]&&(b+=12)),b):void 0}function i(){var b=+a.minutes,c=b>=0&&60>b;return c&&""!==a.minutes?b:void 0}function j(){var b=+a.seconds;return b>=0&&60>b?b:void 0}function k(a,b){return null===a?"":angular.isDefined(a)&&a.toString().length<2&&!b?"0"+a:a.toString()}function l(a){m(),x.$setViewValue(new Date(v)),n(a)}function m(){s&&s.$setValidity("hours",!0),t&&t.$setValidity("minutes",!0),u&&u.$setValidity("seconds",!0),x.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1,a.invalidSeconds=!1}function n(b){if(x.$modelValue){var c=v.getHours(),d=v.getMinutes(),e=v.getSeconds();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:k(c,!z),"m"!==b&&(a.minutes=k(d)),a.meridian=v.getHours()<12?y[0]:y[1],"s"!==b&&(a.seconds=k(e)),a.meridian=v.getHours()<12?y[0]:y[1]}else a.hours=null,a.minutes=null,a.seconds=null,a.meridian=y[0]}function o(a){v=q(v,a),l()}function p(a,b){return q(a,60*b)}function q(a,b){var c=new Date(a.getTime()+1e3*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes(),c.getSeconds()),d}function r(){return(null===a.hours||""===a.hours)&&(null===a.minutes||""===a.minutes)&&(!a.showSeconds||a.showSeconds&&(null===a.seconds||""===a.seconds))}var s,t,u,v=new Date,w=[],x={$setViewValue:angular.noop},y=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS,z=angular.isDefined(c.padHours)?a.$parent.$eval(c.padHours):!0;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){x=b,x.$render=this.render,x.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=d.eq(2);s=e.controller("ngModel"),t=f.controller("ngModel"),u=h.controller("ngModel");var i=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;i&&this.setupMousewheelEvents(e,f,h);var j=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;j&&this.setupArrowkeyEvents(e,f,h),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f,h)};var A=g.hourStep;c.hourStep&&w.push(a.$parent.$watch(d(c.hourStep),function(a){A=+a}));var B=g.minuteStep;c.minuteStep&&w.push(a.$parent.$watch(d(c.minuteStep),function(a){B=+a}));var C;w.push(a.$parent.$watch(d(c.min),function(a){var b=new Date(a);C=isNaN(b)?void 0:b}));var D;w.push(a.$parent.$watch(d(c.max),function(a){var b=new Date(a);D=isNaN(b)?void 0:b}));var E=!1;c.ngDisabled&&w.push(a.$parent.$watch(d(c.ngDisabled),function(a){E=a})),a.noIncrementHours=function(){var a=p(v,60*A);return E||a>D||v>a&&C>a},a.noDecrementHours=function(){var a=p(v,60*-A);return E||C>a||a>v&&a>D},a.noIncrementMinutes=function(){var a=p(v,B);return E||a>D||v>a&&C>a},a.noDecrementMinutes=function(){var a=p(v,-B);return E||C>a||a>v&&a>D},a.noIncrementSeconds=function(){var a=q(v,F);return E||a>D||v>a&&C>a},a.noDecrementSeconds=function(){var a=q(v,-F);return E||C>a||a>v&&a>D},a.noToggleMeridian=function(){return v.getHours()<12?E||p(v,720)>D:E||p(v,-720)<C};var F=g.secondStep;c.secondStep&&w.push(a.$parent.$watch(d(c.secondStep),function(a){F=+a})),a.showSeconds=g.showSeconds,c.showSeconds&&w.push(a.$parent.$watch(d(c.showSeconds),function(b){a.showSeconds=!!b})),a.showMeridian=g.showMeridian,c.showMeridian&&w.push(a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,x.$error.time){var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(v.setHours(c),l())}else n()})),this.setupMousewheelEvents=function(b,c,d){var e=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()}),d.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementSeconds():a.decrementSeconds()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c,d){b.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply()))}),c.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply()))}),d.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementSeconds(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementSeconds(),a.$apply()))})},this.setupInputEvents=function(b,c,d){if(a.readonlyInput)return a.updateHours=angular.noop,a.updateMinutes=angular.noop,void(a.updateSeconds=angular.noop);var e=function(b,c,d){x.$setViewValue(null),x.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b,s&&s.$setValidity("hours",!1)),angular.isDefined(c)&&(a.invalidMinutes=c,t&&t.$setValidity("minutes",!1)),angular.isDefined(d)&&(a.invalidSeconds=d,u&&u.$setValidity("seconds",!1))};a.updateHours=function(){var a=h(),b=i();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(a),v.setMinutes(b),C>v||v>D?e(!0):l("h")):e(!0)},b.on("blur",function(b){x.$setTouched(),r()?m():null===a.hours||""===a.hours?e(!0):!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=k(a.hours,!z)})}),a.updateMinutes=function(){var a=i(),b=h();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(b),v.setMinutes(a),C>v||v>D?e(void 0,!0):l("m")):e(void 0,!0)},c.on("blur",function(b){x.$setTouched(),r()?m():null===a.minutes?e(void 0,!0):!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=k(a.minutes)})}),a.updateSeconds=function(){var a=j();x.$setDirty(),angular.isDefined(a)?(v.setSeconds(a),l("s")):e(void 0,void 0,!0)},d.on("blur",function(b){r()?m():!a.invalidSeconds&&a.seconds<10&&a.$apply(function(){a.seconds=k(a.seconds)})})},this.render=function(){var b=x.$viewValue;isNaN(b)?(x.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(v=b),C>v||v>D?(x.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):m(),n())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*A*60)},a.decrementHours=function(){a.noDecrementHours()||o(60*-A*60)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(60*B)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(60*-B)},a.incrementSeconds=function(){a.noIncrementSeconds()||o(F)},a.decrementSeconds=function(){a.noDecrementSeconds()||o(-F)},a.toggleMeridian=function(){var b=i(),c=h();a.noToggleMeridian()||(angular.isDefined(b)&&angular.isDefined(c)?o(720*(v.getHours()<12?60:-60)):a.meridian=a.meridian===y[0]?y[1]:y[0])},a.blur=function(){x.$setTouched()},a.$on("$destroy",function(){for(;w.length;)w.shift()()})}]).directive("uibTimepicker",["uibTimepickerConfig",function(a){return{require:["uibTimepicker","?^ngModel"],restrict:"A",controller:"UibTimepickerController",controllerAs:"timepicker",scope:{},templateUrl:function(b,c){return c.templateUrl||a.templateUrl},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.debounce","ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$$debounce","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(){P.moveInProgress||(P.moveInProgress=!0,P.$digest()),$()}function o(){P.position=F?l.offset(b):l.position(b),P.position.top+=b.prop("offsetHeight")}function p(a){var b;return angular.version.minor<6?(b=a.$options||{},b.getOption=function(a){return b[a]}):b=a.$options,b}var q,r,s=[9,13,27,38,40],t=200,u=a.$eval(c.typeaheadMinLength);u||0===u||(u=1),a.$watch(c.typeaheadMinLength,function(a){u=a||0===a?a:1});var v=a.$eval(c.typeaheadWaitMs)||0,w=a.$eval(c.typeaheadEditable)!==!1;a.$watch(c.typeaheadEditable,function(a){w=a!==!1});var x,y,z=e(c.typeaheadLoading).assign||angular.noop,A=c.typeaheadShouldSelect?e(c.typeaheadShouldSelect):function(a,b){var c=b.$event;return 13===c.which||9===c.which},B=e(c.typeaheadOnSelect),C=angular.isDefined(c.typeaheadSelectOnBlur)?a.$eval(c.typeaheadSelectOnBlur):!1,D=e(c.typeaheadNoResults).assign||angular.noop,E=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,F=c.typeaheadAppendToBody?a.$eval(c.typeaheadAppendToBody):!1,G=c.typeaheadAppendTo?a.$eval(c.typeaheadAppendTo):null,H=a.$eval(c.typeaheadFocusFirst)!==!1,I=c.typeaheadSelectOnExact?a.$eval(c.typeaheadSelectOnExact):!1,J=e(c.typeaheadIsOpen).assign||angular.noop,K=a.$eval(c.typeaheadShowHint)||!1,L=e(c.ngModel),M=e(c.ngModel+"($$$p)"),N=function(b,c){return angular.isFunction(L(a))&&r.getOption("getterSetter")?M(b,{$$$p:c}):L.assign(b,c)},O=m.parse(c.uibTypeahead),P=a.$new(),Q=a.$on("$destroy",function(){P.$destroy()});P.$on("$destroy",Q);var R="typeahead-"+P.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":R});var S,T;K&&(S=angular.element("<div></div>"),S.css("position","relative"),b.after(S),T=b.clone(),T.attr("placeholder",""),T.attr("tabindex","-1"),T.val(""),T.css({position:"absolute",top:"0px",left:"0px","border-color":"transparent","box-shadow":"none",opacity:1,background:"none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)",color:"#999"}),b.css({position:"relative","vertical-align":"top","background-color":"transparent"}),T.attr("id")&&T.removeAttr("id"),S.append(T),T.after(b));var U=angular.element("<div uib-typeahead-popup></div>");U.attr({id:R,matches:"matches",active:"activeIdx",select:"select(activeIdx, evt)","move-in-progress":"moveInProgress",query:"query",position:"position","assign-is-open":"assignIsOpen(isOpen)",debounce:"debounceUpdate"}),angular.isDefined(c.typeaheadTemplateUrl)&&U.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&U.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var V=function(){K&&T.val("")},W=function(){P.matches=[],P.activeIdx=-1,b.attr("aria-expanded",!1),V()},X=function(a){return R+"-option-"+a};P.$watch("activeIdx",function(a){0>a?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",X(a))});var Y=function(a,b){return P.matches.length>b&&a?a.toUpperCase()===P.matches[b].label.toUpperCase():!1},Z=function(c,d){var e={$viewValue:c};z(a,!0),D(a,!1),f.when(O.source(a,e)).then(function(f){var g=c===q.$viewValue;if(g&&x)if(f&&f.length>0){P.activeIdx=H?0:-1,D(a,!1),P.matches.length=0;for(var h=0;h<f.length;h++)e[O.itemName]=f[h],P.matches.push({id:X(h),label:O.viewMapper(P,e),model:f[h]});if(P.query=c,o(),b.attr("aria-expanded",!0),I&&1===P.matches.length&&Y(c,0)&&(angular.isNumber(P.debounceUpdate)||angular.isObject(P.debounceUpdate)?k(function(){P.select(0,d)},angular.isNumber(P.debounceUpdate)?P.debounceUpdate:P.debounceUpdate["default"]):P.select(0,d)),K){var i=P.matches[0].label;angular.isString(c)&&c.length>0&&i.slice(0,c.length).toUpperCase()===c.toUpperCase()?T.val(c+i.slice(c.length)):T.val("")}}else W(),D(a,!0);g&&z(a,!1)},function(){W(),z(a,!1),D(a,!0)})};F&&(angular.element(i).on("resize",n),h.find("body").on("scroll",n));var $=k(function(){P.matches.length&&o(),P.moveInProgress=!1},t);P.moveInProgress=!1,P.query=void 0;var _,aa=function(a){_=g(function(){Z(a)},v)},ba=function(){_&&g.cancel(_)};W(),P.assignIsOpen=function(b){J(a,b)},P.select=function(d,e){var f,h,i={};y=!0,i[O.itemName]=h=P.matches[d].model,f=O.modelMapper(a,i),N(a,f),q.$setValidity("editable",!0),q.$setValidity("parse",!0),B(a,{$item:h,$model:f,$label:O.viewMapper(a,i),$event:e}),W(),P.$eval(c.typeaheadFocusOnSelect)!==!1&&g(function(){b[0].focus()},0,!1)},b.on("keydown",function(b){if(0!==P.matches.length&&-1!==s.indexOf(b.which)){var c=A(a,{$event:b});if(-1===P.activeIdx&&c||9===b.which&&b.shiftKey)return W(),void P.$digest();b.preventDefault();var d;switch(b.which){case 27:b.stopPropagation(),W(),a.$digest();break;case 38:P.activeIdx=(P.activeIdx>0?P.activeIdx:P.matches.length)-1,P.$digest(),d=U[0].querySelectorAll(".uib-typeahead-match")[P.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;case 40:P.activeIdx=(P.activeIdx+1)%P.matches.length,P.$digest(),d=U[0].querySelectorAll(".uib-typeahead-match")[P.activeIdx],
+d.parentNode.scrollTop=d.offsetTop;break;default:c&&P.$apply(function(){angular.isNumber(P.debounceUpdate)||angular.isObject(P.debounceUpdate)?k(function(){P.select(P.activeIdx,b)},angular.isNumber(P.debounceUpdate)?P.debounceUpdate:P.debounceUpdate["default"]):P.select(P.activeIdx,b)})}}}),b.on("focus",function(a){x=!0,0!==u||q.$viewValue||g(function(){Z(q.$viewValue,a)},0)}),b.on("blur",function(a){C&&P.matches.length&&-1!==P.activeIdx&&!y&&(y=!0,P.$apply(function(){angular.isObject(P.debounceUpdate)&&angular.isNumber(P.debounceUpdate.blur)?k(function(){P.select(P.activeIdx,a)},P.debounceUpdate.blur):P.select(P.activeIdx,a)})),!w&&q.$error.editable&&(q.$setViewValue(),P.$apply(function(){q.$setValidity("editable",!0),q.$setValidity("parse",!0)}),b.val("")),x=!1,y=!1});var ca=function(c){b[0]!==c.target&&3!==c.which&&0!==P.matches.length&&(W(),j.$$phase||a.$digest())};h.on("click",ca),a.$on("$destroy",function(){h.off("click",ca),(F||G)&&da.remove(),F&&(angular.element(i).off("resize",n),h.find("body").off("scroll",n)),U.remove(),K&&S.remove()});var da=d(U)(P);F?h.find("body").append(da):G?angular.element(G).eq(0).append(da):b.after(da),this.init=function(b){q=b,r=p(q),P.debounceUpdate=e(r.getOption("debounce"))(a),q.$parsers.unshift(function(b){return x=!0,0===u||b&&b.length>=u?v>0?(ba(),aa(b)):Z(b):(z(a,!1),ba(),W()),w?b:b?void q.$setValidity("editable",!1):(q.$setValidity("editable",!0),null)}),q.$formatters.push(function(b){var c,d,e={};return w||q.$setValidity("editable",!0),E?(e.$model=b,E(a,e)):(e[O.itemName]=b,c=O.viewMapper(a,e),e[O.itemName]=void 0,d=O.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","uibTypeahead"],link:function(a,b,c,d){d[1].init(d[0])}}}).directive("uibTypeaheadPopup",["$$debounce",function(a){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&",assignIsOpen:"&",debounce:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"uib/template/typeahead/typeahead-popup.html"},link:function(b,c,d){b.templateUrl=d.templateUrl,b.isOpen=function(){var a=b.matches.length>0;return b.assignIsOpen({isOpen:a}),a},b.isActive=function(a){return b.active===a},b.selectActive=function(a){b.active=a},b.selectMatch=function(c,d){var e=b.debounce();angular.isNumber(e)||angular.isObject(e)?a(function(){b.select({activeIdx:c,evt:d})},angular.isNumber(e)?e:e["default"]):b.select({activeIdx:c,evt:d})}}}}]).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"uib/template/typeahead/typeahead-match.html";a(g).then(function(a){var c=angular.element(a.trim());e.replaceWith(c),b(c)(d)})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("uib/template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("uib/template/accordion/accordion-group.html",'<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">\n <h4 class="panel-title">\n <a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading" ng-disabled="isDisabled" uib-tabindex-toggle><span uib-accordion-header ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h4>\n</div>\n<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n</div>\n')}]),angular.module("uib/template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("uib/template/accordion/accordion.html",'<div role="tablist" class="panel-group" ng-transclude></div>')}]),angular.module("uib/template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("uib/template/alert/alert.html",'<button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">\n <span aria-hidden="true">&times;</span>\n <span class="sr-only">Close</span>\n</button>\n<div ng-transclude></div>\n')}]),angular.module("uib/template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/carousel.html",'<div class="carousel-inner" ng-transclude></div>\n<a role="button" href class="left carousel-control" ng-click="prev()" ng-class="{ disabled: isPrevDisabled() }" ng-show="slides.length > 1">\n <span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>\n <span class="sr-only">previous</span>\n</a>\n<a role="button" href class="right carousel-control" ng-click="next()" ng-class="{ disabled: isNextDisabled() }" ng-show="slides.length > 1">\n <span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>\n <span class="sr-only">next</span>\n</a>\n<ol class="carousel-indicators" ng-show="slides.length > 1">\n <li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">\n <span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>\n </li>\n</ol>\n')}]),angular.module("uib/template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/slide.html",'<div class="text-center" ng-transclude></div>\n')}]),angular.module("uib/template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/datepicker.html",'<div ng-switch="datepickerMode">\n <div uib-daypicker ng-switch-when="day" tabindex="0" class="uib-daypicker"></div>\n <div uib-monthpicker ng-switch-when="month" tabindex="0" class="uib-monthpicker"></div>\n <div uib-yearpicker ng-switch-when="year" tabindex="0" class="uib-yearpicker"></div>\n</div>\n')}]),angular.module("uib/template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/day.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n <th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>\n </tr>\n <tr>\n <th ng-if="showWeeks" class="text-center"></th>\n <th ng-repeat="label in ::labels track by $index" class="text-center"><small aria-label="{{::label.full}}">{{::label.abbr}}</small></th>\n </tr>\n </thead>\n <tbody>\n <tr class="uib-weeks" ng-repeat="row in rows track by $index" role="row">\n <td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n <td ng-repeat="dt in row" class="uib-day text-center" role="gridcell"\n id="{{::dt.uid}}"\n ng-class="::dt.customClass">\n <button type="button" class="btn btn-default btn-sm"\n uib-is-class="\n \'btn-info\' for selectedDt,\n \'active\' for activeDt\n on dt"\n ng-click="select(dt.date)"\n ng-disabled="::dt.disabled"\n tabindex="-1"><span ng-class="::{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("uib/template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/month.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n <th colspan="{{::yearHeaderColspan}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr class="uib-months" ng-repeat="row in rows track by $index" role="row">\n <td ng-repeat="dt in row" class="uib-month text-center" role="gridcell"\n id="{{::dt.uid}}"\n ng-class="::dt.customClass">\n <button type="button" class="btn btn-default"\n uib-is-class="\n \'btn-info\' for selectedDt,\n \'active\' for activeDt\n on dt"\n ng-click="select(dt.date)"\n ng-disabled="::dt.disabled"\n tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("uib/template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/year.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n <th colspan="{{::columns - 2}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>\n </tr>\n </thead>\n <tbody>\n <tr class="uib-years" ng-repeat="row in rows track by $index" role="row">\n <td ng-repeat="dt in row" class="uib-year text-center" role="gridcell"\n id="{{::dt.uid}}"\n ng-class="::dt.customClass">\n <button type="button" class="btn btn-default"\n uib-is-class="\n \'btn-info\' for selectedDt,\n \'active\' for activeDt\n on dt"\n ng-click="select(dt.date)"\n ng-disabled="::dt.disabled"\n tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("uib/template/datepickerPopup/popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepickerPopup/popup.html",'<ul role="presentation" class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">\n <li ng-transclude></li>\n <li ng-if="showButtonBar" class="uib-button-bar">\n <span class="btn-group pull-left">\n <button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select(\'today\', $event)" ng-disabled="isDisabled(\'today\')">{{ getText(\'current\') }}</button>\n <button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null, $event)">{{ getText(\'clear\') }}</button>\n </span>\n <button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText(\'close\') }}</button>\n </li>\n</ul>\n')}]),angular.module("uib/template/modal/window.html",[]).run(["$templateCache",function(a){a.put("uib/template/modal/window.html","<div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n")}]),angular.module("uib/template/pager/pager.html",[]).run(["$templateCache",function(a){a.put("uib/template/pager/pager.html",'<li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'previous\')}}</a></li>\n<li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'next\')}}</a></li>\n')}]),angular.module("uib/template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("uib/template/pagination/pagination.html",'<li role="menuitem" ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'first\')}}</a></li>\n<li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'previous\')}}</a></li>\n<li role="menuitem" ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)" ng-disabled="ngDisabled&&!page.active" uib-tabindex-toggle>{{page.text}}</a></li>\n<li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'next\')}}</a></li>\n<li role="menuitem" ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'last\')}}</a></li>\n')}]),angular.module("uib/template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-html-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner" ng-bind-html="contentExp()"></div>\n')}]),angular.module("uib/template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner" ng-bind="content"></div>\n')}]),angular.module("uib/template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-template-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner"\n uib-tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n')}]),angular.module("uib/template/popover/popover-html.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover-html.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n <div class="popover-content" ng-bind-html="contentExp()"></div>\n</div>\n')}]),angular.module("uib/template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover-template.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n <div class="popover-content"\n uib-tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n</div>\n')}]),angular.module("uib/template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n <div class="popover-content" ng-bind="content"></div>\n</div>\n')}]),angular.module("uib/template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" ng-transclude></div>\n')}]),angular.module("uib/template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/progress.html",'<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>')}]),angular.module("uib/template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/progressbar.html",'<div class="progress">\n <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" ng-transclude></div>\n</div>\n')}]),angular.module("uib/template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("uib/template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}" aria-valuetext="{{title}}">\n <span ng-repeat-start="r in range track by $index" class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n <i ng-repeat-end ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')" ng-attr-title="{{r.title}}"></i>\n</span>\n')}]),angular.module("uib/template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("uib/template/tabs/tab.html",'<li ng-class="[{active: active, disabled: disabled}, classes]" class="uib-tab nav-item">\n <a href ng-click="select($event)" class="nav-link" uib-tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("uib/template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("uib/template/tabs/tabset.html",'<div>\n <ul class="nav nav-{{tabset.type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n <div class="tab-content">\n <div class="tab-pane"\n ng-repeat="tab in tabset.tabs"\n ng-class="{active: tabset.active === tab.index}"\n uib-tab-content-transclude="tab">\n </div>\n </div>\n</div>\n')}]),angular.module("uib/template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/timepicker/timepicker.html",'<table class="uib-timepicker">\n <tbody>\n <tr class="text-center" ng-show="::showSpinners">\n <td class="uib-increment hours"><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td>&nbsp;</td>\n <td class="uib-increment minutes"><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td ng-show="showSeconds">&nbsp;</td>\n <td ng-show="showSeconds" class="uib-increment seconds"><a ng-click="incrementSeconds()" ng-class="{disabled: noIncrementSeconds()}" class="btn btn-link" ng-disabled="noIncrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n <tr>\n <td class="form-group uib-time hours" ng-class="{\'has-error\': invalidHours}">\n <input type="text" placeholder="HH" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementHours()" ng-blur="blur()">\n </td>\n <td class="uib-separator">:</td>\n <td class="form-group uib-time minutes" ng-class="{\'has-error\': invalidMinutes}">\n <input type="text" placeholder="MM" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementMinutes()" ng-blur="blur()">\n </td>\n <td ng-show="showSeconds" class="uib-separator">:</td>\n <td class="form-group uib-time seconds" ng-class="{\'has-error\': invalidSeconds}" ng-show="showSeconds">\n <input type="text" placeholder="SS" ng-model="seconds" ng-change="updateSeconds()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementSeconds()" ng-blur="blur()">\n </td>\n <td ng-show="showMeridian" class="uib-time am-pm"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>\n </tr>\n <tr class="text-center" ng-show="::showSpinners">\n <td class="uib-decrement hours"><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td>&nbsp;</td>\n <td class="uib-decrement minutes"><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td ng-show="showSeconds">&nbsp;</td>\n <td ng-show="showSeconds" class="uib-decrement seconds"><a ng-click="decrementSeconds()" ng-class="{disabled: noDecrementSeconds()}" class="btn btn-link" ng-disabled="noDecrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("uib/template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-match.html",'<a href\n tabindex="-1"\n ng-bind-html="match.label | uibTypeaheadHighlight:query"\n ng-attr-title="{{match.label}}"></a>\n')}]),angular.module("uib/template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+\'px\', left: position().left+\'px\'}" role="listbox" aria-hidden="{{!isOpen()}}">\n <li class="uib-typeahead-match" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="{{::match.id}}">\n <div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n </li>\n</ul>\n')}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'),angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-time input{width:50px;}</style>'),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'),angular.$$uibTypeaheadCss=!0}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.js
new file mode 100644
index 00000000..8bcf397b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.js
@@ -0,0 +1,7412 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 2.5.0 - 2017-01-28
+ * License: MIT
+ */angular.module("ui.bootstrap", ["ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]);
+angular.module('ui.bootstrap.collapse', [])
+
+ .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) {
+ var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;
+ return {
+ link: function(scope, element, attrs) {
+ var expandingExpr = $parse(attrs.expanding),
+ expandedExpr = $parse(attrs.expanded),
+ collapsingExpr = $parse(attrs.collapsing),
+ collapsedExpr = $parse(attrs.collapsed),
+ horizontal = false,
+ css = {},
+ cssTo = {};
+
+ init();
+
+ function init() {
+ horizontal = !!('horizontal' in attrs);
+ if (horizontal) {
+ css = {
+ width: ''
+ };
+ cssTo = {width: '0'};
+ } else {
+ css = {
+ height: ''
+ };
+ cssTo = {height: '0'};
+ }
+ if (!scope.$eval(attrs.uibCollapse)) {
+ element.addClass('in')
+ .addClass('collapse')
+ .attr('aria-expanded', true)
+ .attr('aria-hidden', false)
+ .css(css);
+ }
+ }
+
+ function getScrollFromElement(element) {
+ if (horizontal) {
+ return {width: element.scrollWidth + 'px'};
+ }
+ return {height: element.scrollHeight + 'px'};
+ }
+
+ function expand() {
+ if (element.hasClass('collapse') && element.hasClass('in')) {
+ return;
+ }
+
+ $q.resolve(expandingExpr(scope))
+ .then(function() {
+ element.removeClass('collapse')
+ .addClass('collapsing')
+ .attr('aria-expanded', true)
+ .attr('aria-hidden', false);
+
+ if ($animateCss) {
+ $animateCss(element, {
+ addClass: 'in',
+ easing: 'ease',
+ css: {
+ overflow: 'hidden'
+ },
+ to: getScrollFromElement(element[0])
+ }).start()['finally'](expandDone);
+ } else {
+ $animate.addClass(element, 'in', {
+ css: {
+ overflow: 'hidden'
+ },
+ to: getScrollFromElement(element[0])
+ }).then(expandDone);
+ }
+ }, angular.noop);
+ }
+
+ function expandDone() {
+ element.removeClass('collapsing')
+ .addClass('collapse')
+ .css(css);
+ expandedExpr(scope);
+ }
+
+ function collapse() {
+ if (!element.hasClass('collapse') && !element.hasClass('in')) {
+ return collapseDone();
+ }
+
+ $q.resolve(collapsingExpr(scope))
+ .then(function() {
+ element
+ // IMPORTANT: The width must be set before adding "collapsing" class.
+ // Otherwise, the browser attempts to animate from width 0 (in
+ // collapsing class) to the given width here.
+ .css(getScrollFromElement(element[0]))
+ // initially all panel collapse have the collapse class, this removal
+ // prevents the animation from jumping to collapsed state
+ .removeClass('collapse')
+ .addClass('collapsing')
+ .attr('aria-expanded', false)
+ .attr('aria-hidden', true);
+
+ if ($animateCss) {
+ $animateCss(element, {
+ removeClass: 'in',
+ to: cssTo
+ }).start()['finally'](collapseDone);
+ } else {
+ $animate.removeClass(element, 'in', {
+ to: cssTo
+ }).then(collapseDone);
+ }
+ }, angular.noop);
+ }
+
+ function collapseDone() {
+ element.css(cssTo); // Required so that collapse works when animation is disabled
+ element.removeClass('collapsing')
+ .addClass('collapse');
+ collapsedExpr(scope);
+ }
+
+ scope.$watch(attrs.uibCollapse, function(shouldCollapse) {
+ if (shouldCollapse) {
+ collapse();
+ } else {
+ expand();
+ }
+ });
+ }
+ };
+ }]);
+
+angular.module('ui.bootstrap.tabindex', [])
+
+.directive('uibTabindexToggle', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, elem, attrs) {
+ attrs.$observe('disabled', function(disabled) {
+ attrs.$set('tabindex', disabled ? -1 : null);
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])
+
+.constant('uibAccordionConfig', {
+ closeOthers: true
+})
+
+.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {
+ // This array keeps track of the accordion groups
+ this.groups = [];
+
+ // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
+ this.closeOthers = function(openGroup) {
+ var closeOthers = angular.isDefined($attrs.closeOthers) ?
+ $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
+ if (closeOthers) {
+ angular.forEach(this.groups, function(group) {
+ if (group !== openGroup) {
+ group.isOpen = false;
+ }
+ });
+ }
+ };
+
+ // This is called from the accordion-group directive to add itself to the accordion
+ this.addGroup = function(groupScope) {
+ var that = this;
+ this.groups.push(groupScope);
+
+ groupScope.$on('$destroy', function(event) {
+ that.removeGroup(groupScope);
+ });
+ };
+
+ // This is called from the accordion-group directive when to remove itself
+ this.removeGroup = function(group) {
+ var index = this.groups.indexOf(group);
+ if (index !== -1) {
+ this.groups.splice(index, 1);
+ }
+ };
+}])
+
+// The accordion directive simply sets up the directive controller
+// and adds an accordion CSS class to itself element.
+.directive('uibAccordion', function() {
+ return {
+ controller: 'UibAccordionController',
+ controllerAs: 'accordion',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/accordion/accordion.html';
+ }
+ };
+})
+
+// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
+.directive('uibAccordionGroup', function() {
+ return {
+ require: '^uibAccordion', // We need this directive to be inside an accordion
+ transclude: true, // It transcludes the contents of the directive into the template
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
+ },
+ scope: {
+ heading: '@', // Interpolate the heading attribute onto this scope
+ panelClass: '@?', // Ditto with panelClass
+ isOpen: '=?',
+ isDisabled: '=?'
+ },
+ controller: function() {
+ this.setHeading = function(element) {
+ this.heading = element;
+ };
+ },
+ link: function(scope, element, attrs, accordionCtrl) {
+ element.addClass('panel');
+ accordionCtrl.addGroup(scope);
+
+ scope.openClass = attrs.openClass || 'panel-open';
+ scope.panelClass = attrs.panelClass || 'panel-default';
+ scope.$watch('isOpen', function(value) {
+ element.toggleClass(scope.openClass, !!value);
+ if (value) {
+ accordionCtrl.closeOthers(scope);
+ }
+ });
+
+ scope.toggleOpen = function($event) {
+ if (!scope.isDisabled) {
+ if (!$event || $event.which === 32) {
+ scope.isOpen = !scope.isOpen;
+ }
+ }
+ };
+
+ var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
+ scope.headingId = id + '-tab';
+ scope.panelId = id + '-panel';
+ }
+ };
+})
+
+// Use accordion-heading below an accordion-group to provide a heading containing HTML
+.directive('uibAccordionHeading', function() {
+ return {
+ transclude: true, // Grab the contents to be used as the heading
+ template: '', // In effect remove this element!
+ replace: true,
+ require: '^uibAccordionGroup',
+ link: function(scope, element, attrs, accordionGroupCtrl, transclude) {
+ // Pass the heading to the accordion-group controller
+ // so that it can be transcluded into the right place in the template
+ // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
+ accordionGroupCtrl.setHeading(transclude(scope, angular.noop));
+ }
+ };
+})
+
+// Use in the accordion-group template to indicate where you want the heading to be transcluded
+// You must provide the property on the accordion-group controller that will hold the transcluded element
+.directive('uibAccordionTransclude', function() {
+ return {
+ require: '^uibAccordionGroup',
+ link: function(scope, element, attrs, controller) {
+ scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {
+ if (heading) {
+ var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
+ elem.html('');
+ elem.append(heading);
+ }
+ });
+ }
+ };
+
+ function getHeaderSelectors() {
+ return 'uib-accordion-header,' +
+ 'data-uib-accordion-header,' +
+ 'x-uib-accordion-header,' +
+ 'uib\\:accordion-header,' +
+ '[uib-accordion-header],' +
+ '[data-uib-accordion-header],' +
+ '[x-uib-accordion-header]';
+ }
+});
+
+angular.module('ui.bootstrap.alert', [])
+
+.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) {
+ $scope.closeable = !!$attrs.close;
+ $element.addClass('alert');
+ $attrs.$set('role', 'alert');
+ if ($scope.closeable) {
+ $element.addClass('alert-dismissible');
+ }
+
+ var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
+ $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;
+
+ if (dismissOnTimeout) {
+ $timeout(function() {
+ $scope.close();
+ }, parseInt(dismissOnTimeout, 10));
+ }
+}])
+
+.directive('uibAlert', function() {
+ return {
+ controller: 'UibAlertController',
+ controllerAs: 'alert',
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/alert/alert.html';
+ },
+ transclude: true,
+ scope: {
+ close: '&'
+ }
+ };
+});
+
+angular.module('ui.bootstrap.buttons', [])
+
+.constant('uibButtonConfig', {
+ activeClass: 'active',
+ toggleEvent: 'click'
+})
+
+.controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {
+ this.activeClass = buttonConfig.activeClass || 'active';
+ this.toggleEvent = buttonConfig.toggleEvent || 'click';
+}])
+
+.directive('uibBtnRadio', ['$parse', function($parse) {
+ return {
+ require: ['uibBtnRadio', 'ngModel'],
+ controller: 'UibButtonsController',
+ controllerAs: 'buttons',
+ link: function(scope, element, attrs, ctrls) {
+ var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+ var uncheckableExpr = $parse(attrs.uibUncheckable);
+
+ element.find('input').css({display: 'none'});
+
+ //model -> UI
+ ngModelCtrl.$render = function() {
+ element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));
+ };
+
+ //ui->model
+ element.on(buttonsCtrl.toggleEvent, function() {
+ if (attrs.disabled) {
+ return;
+ }
+
+ var isActive = element.hasClass(buttonsCtrl.activeClass);
+
+ if (!isActive || angular.isDefined(attrs.uncheckable)) {
+ scope.$apply(function() {
+ ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));
+ ngModelCtrl.$render();
+ });
+ }
+ });
+
+ if (attrs.uibUncheckable) {
+ scope.$watch(uncheckableExpr, function(uncheckable) {
+ attrs.$set('uncheckable', uncheckable ? '' : undefined);
+ });
+ }
+ }
+ };
+}])
+
+.directive('uibBtnCheckbox', function() {
+ return {
+ require: ['uibBtnCheckbox', 'ngModel'],
+ controller: 'UibButtonsController',
+ controllerAs: 'button',
+ link: function(scope, element, attrs, ctrls) {
+ var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ element.find('input').css({display: 'none'});
+
+ function getTrueValue() {
+ return getCheckboxValue(attrs.btnCheckboxTrue, true);
+ }
+
+ function getFalseValue() {
+ return getCheckboxValue(attrs.btnCheckboxFalse, false);
+ }
+
+ function getCheckboxValue(attribute, defaultValue) {
+ return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;
+ }
+
+ //model -> UI
+ ngModelCtrl.$render = function() {
+ element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
+ };
+
+ //ui->model
+ element.on(buttonsCtrl.toggleEvent, function() {
+ if (attrs.disabled) {
+ return;
+ }
+
+ scope.$apply(function() {
+ ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
+ ngModelCtrl.$render();
+ });
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.carousel', [])
+
+.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) {
+ var self = this,
+ slides = self.slides = $scope.slides = [],
+ SLIDE_DIRECTION = 'uib-slideDirection',
+ currentIndex = $scope.active,
+ currentInterval, isPlaying;
+
+ var destroyed = false;
+ $element.addClass('carousel');
+
+ self.addSlide = function(slide, element) {
+ slides.push({
+ slide: slide,
+ element: element
+ });
+ slides.sort(function(a, b) {
+ return +a.slide.index - +b.slide.index;
+ });
+ //if this is the first slide or the slide is set to active, select it
+ if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {
+ if ($scope.$currentTransition) {
+ $scope.$currentTransition = null;
+ }
+
+ currentIndex = slide.index;
+ $scope.active = slide.index;
+ setActive(currentIndex);
+ self.select(slides[findSlideIndex(slide)]);
+ if (slides.length === 1) {
+ $scope.play();
+ }
+ }
+ };
+
+ self.getCurrentIndex = function() {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide.index === currentIndex) {
+ return i;
+ }
+ }
+ };
+
+ self.next = $scope.next = function() {
+ var newIndex = (self.getCurrentIndex() + 1) % slides.length;
+
+ if (newIndex === 0 && $scope.noWrap()) {
+ $scope.pause();
+ return;
+ }
+
+ return self.select(slides[newIndex], 'next');
+ };
+
+ self.prev = $scope.prev = function() {
+ var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;
+
+ if ($scope.noWrap() && newIndex === slides.length - 1) {
+ $scope.pause();
+ return;
+ }
+
+ return self.select(slides[newIndex], 'prev');
+ };
+
+ self.removeSlide = function(slide) {
+ var index = findSlideIndex(slide);
+
+ //get the index of the slide inside the carousel
+ slides.splice(index, 1);
+ if (slides.length > 0 && currentIndex === index) {
+ if (index >= slides.length) {
+ currentIndex = slides.length - 1;
+ $scope.active = currentIndex;
+ setActive(currentIndex);
+ self.select(slides[slides.length - 1]);
+ } else {
+ currentIndex = index;
+ $scope.active = currentIndex;
+ setActive(currentIndex);
+ self.select(slides[index]);
+ }
+ } else if (currentIndex > index) {
+ currentIndex--;
+ $scope.active = currentIndex;
+ }
+
+ //clean the active value when no more slide
+ if (slides.length === 0) {
+ currentIndex = null;
+ $scope.active = null;
+ }
+ };
+
+ /* direction: "prev" or "next" */
+ self.select = $scope.select = function(nextSlide, direction) {
+ var nextIndex = findSlideIndex(nextSlide.slide);
+ //Decide direction if it's not given
+ if (direction === undefined) {
+ direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';
+ }
+ //Prevent this user-triggered transition from occurring if there is already one in progress
+ if (nextSlide.slide.index !== currentIndex &&
+ !$scope.$currentTransition) {
+ goNext(nextSlide.slide, nextIndex, direction);
+ }
+ };
+
+ /* Allow outside people to call indexOf on slides array */
+ $scope.indexOfSlide = function(slide) {
+ return +slide.slide.index;
+ };
+
+ $scope.isActive = function(slide) {
+ return $scope.active === slide.slide.index;
+ };
+
+ $scope.isPrevDisabled = function() {
+ return $scope.active === 0 && $scope.noWrap();
+ };
+
+ $scope.isNextDisabled = function() {
+ return $scope.active === slides.length - 1 && $scope.noWrap();
+ };
+
+ $scope.pause = function() {
+ if (!$scope.noPause) {
+ isPlaying = false;
+ resetTimer();
+ }
+ };
+
+ $scope.play = function() {
+ if (!isPlaying) {
+ isPlaying = true;
+ restartTimer();
+ }
+ };
+
+ $element.on('mouseenter', $scope.pause);
+ $element.on('mouseleave', $scope.play);
+
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ resetTimer();
+ });
+
+ $scope.$watch('noTransition', function(noTransition) {
+ $animate.enabled($element, !noTransition);
+ });
+
+ $scope.$watch('interval', restartTimer);
+
+ $scope.$watchCollection('slides', resetTransition);
+
+ $scope.$watch('active', function(index) {
+ if (angular.isNumber(index) && currentIndex !== index) {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide.index === index) {
+ index = i;
+ break;
+ }
+ }
+
+ var slide = slides[index];
+ if (slide) {
+ setActive(index);
+ self.select(slides[index]);
+ currentIndex = index;
+ }
+ }
+ });
+
+ function getSlideByIndex(index) {
+ for (var i = 0, l = slides.length; i < l; ++i) {
+ if (slides[i].index === index) {
+ return slides[i];
+ }
+ }
+ }
+
+ function setActive(index) {
+ for (var i = 0; i < slides.length; i++) {
+ slides[i].slide.active = i === index;
+ }
+ }
+
+ function goNext(slide, index, direction) {
+ if (destroyed) {
+ return;
+ }
+
+ angular.extend(slide, {direction: direction});
+ angular.extend(slides[currentIndex].slide || {}, {direction: direction});
+ if ($animate.enabled($element) && !$scope.$currentTransition &&
+ slides[index].element && self.slides.length > 1) {
+ slides[index].element.data(SLIDE_DIRECTION, slide.direction);
+ var currentIdx = self.getCurrentIndex();
+
+ if (angular.isNumber(currentIdx) && slides[currentIdx].element) {
+ slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);
+ }
+
+ $scope.$currentTransition = true;
+ $animate.on('addClass', slides[index].element, function(element, phase) {
+ if (phase === 'close') {
+ $scope.$currentTransition = null;
+ $animate.off('addClass', element);
+ }
+ });
+ }
+
+ $scope.active = slide.index;
+ currentIndex = slide.index;
+ setActive(index);
+
+ //every time you change slides, reset the timer
+ restartTimer();
+ }
+
+ function findSlideIndex(slide) {
+ for (var i = 0; i < slides.length; i++) {
+ if (slides[i].slide === slide) {
+ return i;
+ }
+ }
+ }
+
+ function resetTimer() {
+ if (currentInterval) {
+ $interval.cancel(currentInterval);
+ currentInterval = null;
+ }
+ }
+
+ function resetTransition(slides) {
+ if (!slides.length) {
+ $scope.$currentTransition = null;
+ }
+ }
+
+ function restartTimer() {
+ resetTimer();
+ var interval = +$scope.interval;
+ if (!isNaN(interval) && interval > 0) {
+ currentInterval = $interval(timerFn, interval);
+ }
+ }
+
+ function timerFn() {
+ var interval = +$scope.interval;
+ if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
+ $scope.next();
+ } else {
+ $scope.pause();
+ }
+ }
+}])
+
+.directive('uibCarousel', function() {
+ return {
+ transclude: true,
+ controller: 'UibCarouselController',
+ controllerAs: 'carousel',
+ restrict: 'A',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/carousel/carousel.html';
+ },
+ scope: {
+ active: '=',
+ interval: '=',
+ noTransition: '=',
+ noPause: '=',
+ noWrap: '&'
+ }
+ };
+})
+
+.directive('uibSlide', ['$animate', function($animate) {
+ return {
+ require: '^uibCarousel',
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/carousel/slide.html';
+ },
+ scope: {
+ actual: '=?',
+ index: '=?'
+ },
+ link: function (scope, element, attrs, carouselCtrl) {
+ element.addClass('item');
+ carouselCtrl.addSlide(scope, element);
+ //when the scope is destroyed then remove the slide from the current slides array
+ scope.$on('$destroy', function() {
+ carouselCtrl.removeSlide(scope);
+ });
+
+ scope.$watch('active', function(active) {
+ $animate[active ? 'addClass' : 'removeClass'](element, 'active');
+ });
+ }
+ };
+}])
+
+.animation('.item', ['$animateCss',
+function($animateCss) {
+ var SLIDE_DIRECTION = 'uib-slideDirection';
+
+ function removeClass(element, className, callback) {
+ element.removeClass(className);
+ if (callback) {
+ callback();
+ }
+ }
+
+ return {
+ beforeAddClass: function(element, className, done) {
+ if (className === 'active') {
+ var stopped = false;
+ var direction = element.data(SLIDE_DIRECTION);
+ var directionClass = direction === 'next' ? 'left' : 'right';
+ var removeClassFn = removeClass.bind(this, element,
+ directionClass + ' ' + direction, done);
+ element.addClass(direction);
+
+ $animateCss(element, {addClass: directionClass})
+ .start()
+ .done(removeClassFn);
+
+ return function() {
+ stopped = true;
+ };
+ }
+ done();
+ },
+ beforeRemoveClass: function (element, className, done) {
+ if (className === 'active') {
+ var stopped = false;
+ var direction = element.data(SLIDE_DIRECTION);
+ var directionClass = direction === 'next' ? 'left' : 'right';
+ var removeClassFn = removeClass.bind(this, element, directionClass, done);
+
+ $animateCss(element, {addClass: directionClass})
+ .start()
+ .done(removeClassFn);
+
+ return function() {
+ stopped = true;
+ };
+ }
+ done();
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.dateparser', [])
+
+.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', 'filterFilter', function($log, $locale, dateFilter, orderByFilter, filterFilter) {
+ // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js
+ var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+
+ var localeId;
+ var formatCodeToRegex;
+
+ this.init = function() {
+ localeId = $locale.id;
+
+ this.parsers = {};
+ this.formatters = {};
+
+ formatCodeToRegex = [
+ {
+ key: 'yyyy',
+ regex: '\\d{4}',
+ apply: function(value) { this.year = +value; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'yyyy');
+ }
+ },
+ {
+ key: 'yy',
+ regex: '\\d{2}',
+ apply: function(value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'yy');
+ }
+ },
+ {
+ key: 'y',
+ regex: '\\d{1,4}',
+ apply: function(value) { this.year = +value; },
+ formatter: function(date) {
+ var _date = new Date();
+ _date.setFullYear(Math.abs(date.getFullYear()));
+ return dateFilter(_date, 'y');
+ }
+ },
+ {
+ key: 'M!',
+ regex: '0?[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) {
+ var value = date.getMonth();
+ if (/^[0-9]$/.test(value)) {
+ return dateFilter(date, 'MM');
+ }
+
+ return dateFilter(date, 'M');
+ }
+ },
+ {
+ key: 'MMMM',
+ regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'MMMM'); }
+ },
+ {
+ key: 'MMM',
+ regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'MMM'); }
+ },
+ {
+ key: 'MM',
+ regex: '0[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) { return dateFilter(date, 'MM'); }
+ },
+ {
+ key: 'M',
+ regex: '[1-9]|1[0-2]',
+ apply: function(value) { this.month = value - 1; },
+ formatter: function(date) { return dateFilter(date, 'M'); }
+ },
+ {
+ key: 'd!',
+ regex: '[0-2]?[0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) {
+ var value = date.getDate();
+ if (/^[1-9]$/.test(value)) {
+ return dateFilter(date, 'dd');
+ }
+
+ return dateFilter(date, 'd');
+ }
+ },
+ {
+ key: 'dd',
+ regex: '[0-2][0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) { return dateFilter(date, 'dd'); }
+ },
+ {
+ key: 'd',
+ regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
+ apply: function(value) { this.date = +value; },
+ formatter: function(date) { return dateFilter(date, 'd'); }
+ },
+ {
+ key: 'EEEE',
+ regex: $locale.DATETIME_FORMATS.DAY.join('|'),
+ formatter: function(date) { return dateFilter(date, 'EEEE'); }
+ },
+ {
+ key: 'EEE',
+ regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
+ formatter: function(date) { return dateFilter(date, 'EEE'); }
+ },
+ {
+ key: 'HH',
+ regex: '(?:0|1)[0-9]|2[0-3]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'HH'); }
+ },
+ {
+ key: 'hh',
+ regex: '0[0-9]|1[0-2]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'hh'); }
+ },
+ {
+ key: 'H',
+ regex: '1?[0-9]|2[0-3]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'H'); }
+ },
+ {
+ key: 'h',
+ regex: '[0-9]|1[0-2]',
+ apply: function(value) { this.hours = +value; },
+ formatter: function(date) { return dateFilter(date, 'h'); }
+ },
+ {
+ key: 'mm',
+ regex: '[0-5][0-9]',
+ apply: function(value) { this.minutes = +value; },
+ formatter: function(date) { return dateFilter(date, 'mm'); }
+ },
+ {
+ key: 'm',
+ regex: '[0-9]|[1-5][0-9]',
+ apply: function(value) { this.minutes = +value; },
+ formatter: function(date) { return dateFilter(date, 'm'); }
+ },
+ {
+ key: 'sss',
+ regex: '[0-9][0-9][0-9]',
+ apply: function(value) { this.milliseconds = +value; },
+ formatter: function(date) { return dateFilter(date, 'sss'); }
+ },
+ {
+ key: 'ss',
+ regex: '[0-5][0-9]',
+ apply: function(value) { this.seconds = +value; },
+ formatter: function(date) { return dateFilter(date, 'ss'); }
+ },
+ {
+ key: 's',
+ regex: '[0-9]|[1-5][0-9]',
+ apply: function(value) { this.seconds = +value; },
+ formatter: function(date) { return dateFilter(date, 's'); }
+ },
+ {
+ key: 'a',
+ regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),
+ apply: function(value) {
+ if (this.hours === 12) {
+ this.hours = 0;
+ }
+
+ if (value === 'PM') {
+ this.hours += 12;
+ }
+ },
+ formatter: function(date) { return dateFilter(date, 'a'); }
+ },
+ {
+ key: 'Z',
+ regex: '[+-]\\d{4}',
+ apply: function(value) {
+ var matches = value.match(/([+-])(\d{2})(\d{2})/),
+ sign = matches[1],
+ hours = matches[2],
+ minutes = matches[3];
+ this.hours += toInt(sign + hours);
+ this.minutes += toInt(sign + minutes);
+ },
+ formatter: function(date) {
+ return dateFilter(date, 'Z');
+ }
+ },
+ {
+ key: 'ww',
+ regex: '[0-4][0-9]|5[0-3]',
+ formatter: function(date) { return dateFilter(date, 'ww'); }
+ },
+ {
+ key: 'w',
+ regex: '[0-9]|[1-4][0-9]|5[0-3]',
+ formatter: function(date) { return dateFilter(date, 'w'); }
+ },
+ {
+ key: 'GGGG',
+ regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\s/g, '\\s'),
+ formatter: function(date) { return dateFilter(date, 'GGGG'); }
+ },
+ {
+ key: 'GGG',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'GGG'); }
+ },
+ {
+ key: 'GG',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'GG'); }
+ },
+ {
+ key: 'G',
+ regex: $locale.DATETIME_FORMATS.ERAS.join('|'),
+ formatter: function(date) { return dateFilter(date, 'G'); }
+ }
+ ];
+
+ if (angular.version.major >= 1 && angular.version.minor > 4) {
+ formatCodeToRegex.push({
+ key: 'LLLL',
+ regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),
+ apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },
+ formatter: function(date) { return dateFilter(date, 'LLLL'); }
+ });
+ }
+ };
+
+ this.init();
+
+ function getFormatCodeToRegex(key) {
+ return filterFilter(formatCodeToRegex, {key: key}, true)[0];
+ }
+
+ this.getParser = function (key) {
+ var f = getFormatCodeToRegex(key);
+ return f && f.apply || null;
+ };
+
+ this.overrideParser = function (key, parser) {
+ var f = getFormatCodeToRegex(key);
+ if (f && angular.isFunction(parser)) {
+ this.parsers = {};
+ f.apply = parser;
+ }
+ }.bind(this);
+
+ function createParser(format) {
+ var map = [], regex = format.split('');
+
+ // check for literal values
+ var quoteIndex = format.indexOf('\'');
+ if (quoteIndex > -1) {
+ var inLiteral = false;
+ format = format.split('');
+ for (var i = quoteIndex; i < format.length; i++) {
+ if (inLiteral) {
+ if (format[i] === '\'') {
+ if (i + 1 < format.length && format[i+1] === '\'') { // escaped single quote
+ format[i+1] = '$';
+ regex[i+1] = '';
+ } else { // end of literal
+ regex[i] = '';
+ inLiteral = false;
+ }
+ }
+ format[i] = '$';
+ } else {
+ if (format[i] === '\'') { // start of literal
+ format[i] = '$';
+ regex[i] = '';
+ inLiteral = true;
+ }
+ }
+ }
+
+ format = format.join('');
+ }
+
+ angular.forEach(formatCodeToRegex, function(data) {
+ var index = format.indexOf(data.key);
+
+ if (index > -1) {
+ format = format.split('');
+
+ regex[index] = '(' + data.regex + ')';
+ format[index] = '$'; // Custom symbol to define consumed part of format
+ for (var i = index + 1, n = index + data.key.length; i < n; i++) {
+ regex[i] = '';
+ format[i] = '$';
+ }
+ format = format.join('');
+
+ map.push({
+ index: index,
+ key: data.key,
+ apply: data.apply,
+ matcher: data.regex
+ });
+ }
+ });
+
+ return {
+ regex: new RegExp('^' + regex.join('') + '$'),
+ map: orderByFilter(map, 'index')
+ };
+ }
+
+ function createFormatter(format) {
+ var formatters = [];
+ var i = 0;
+ var formatter, literalIdx;
+ while (i < format.length) {
+ if (angular.isNumber(literalIdx)) {
+ if (format.charAt(i) === '\'') {
+ if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
+ formatters.push(constructLiteralFormatter(format, literalIdx, i));
+ literalIdx = null;
+ }
+ } else if (i === format.length) {
+ while (literalIdx < format.length) {
+ formatter = constructFormatterFromIdx(format, literalIdx);
+ formatters.push(formatter);
+ literalIdx = formatter.endIdx;
+ }
+ }
+
+ i++;
+ continue;
+ }
+
+ if (format.charAt(i) === '\'') {
+ literalIdx = i;
+ i++;
+ continue;
+ }
+
+ formatter = constructFormatterFromIdx(format, i);
+
+ formatters.push(formatter.parser);
+ i = formatter.endIdx;
+ }
+
+ return formatters;
+ }
+
+ function constructLiteralFormatter(format, literalIdx, endIdx) {
+ return function() {
+ return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
+ };
+ }
+
+ function constructFormatterFromIdx(format, i) {
+ var currentPosStr = format.substr(i);
+ for (var j = 0; j < formatCodeToRegex.length; j++) {
+ if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
+ var data = formatCodeToRegex[j];
+ return {
+ endIdx: i + data.key.length,
+ parser: data.formatter
+ };
+ }
+ }
+
+ return {
+ endIdx: i + 1,
+ parser: function() {
+ return currentPosStr.charAt(0);
+ }
+ };
+ }
+
+ this.filter = function(date, format) {
+ if (!angular.isDate(date) || isNaN(date) || !format) {
+ return '';
+ }
+
+ format = $locale.DATETIME_FORMATS[format] || format;
+
+ if ($locale.id !== localeId) {
+ this.init();
+ }
+
+ if (!this.formatters[format]) {
+ this.formatters[format] = createFormatter(format);
+ }
+
+ var formatters = this.formatters[format];
+
+ return formatters.reduce(function(str, formatter) {
+ return str + formatter(date);
+ }, '');
+ };
+
+ this.parse = function(input, format, baseDate) {
+ if (!angular.isString(input) || !format) {
+ return input;
+ }
+
+ format = $locale.DATETIME_FORMATS[format] || format;
+ format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\$&');
+
+ if ($locale.id !== localeId) {
+ this.init();
+ }
+
+ if (!this.parsers[format]) {
+ this.parsers[format] = createParser(format, 'apply');
+ }
+
+ var parser = this.parsers[format],
+ regex = parser.regex,
+ map = parser.map,
+ results = input.match(regex),
+ tzOffset = false;
+ if (results && results.length) {
+ var fields, dt;
+ if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {
+ fields = {
+ year: baseDate.getFullYear(),
+ month: baseDate.getMonth(),
+ date: baseDate.getDate(),
+ hours: baseDate.getHours(),
+ minutes: baseDate.getMinutes(),
+ seconds: baseDate.getSeconds(),
+ milliseconds: baseDate.getMilliseconds()
+ };
+ } else {
+ if (baseDate) {
+ $log.warn('dateparser:', 'baseDate is not a valid date');
+ }
+ fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
+ }
+
+ for (var i = 1, n = results.length; i < n; i++) {
+ var mapper = map[i - 1];
+ if (mapper.matcher === 'Z') {
+ tzOffset = true;
+ }
+
+ if (mapper.apply) {
+ mapper.apply.call(fields, results[i]);
+ }
+ }
+
+ var datesetter = tzOffset ? Date.prototype.setUTCFullYear :
+ Date.prototype.setFullYear;
+ var timesetter = tzOffset ? Date.prototype.setUTCHours :
+ Date.prototype.setHours;
+
+ if (isValid(fields.year, fields.month, fields.date)) {
+ if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {
+ dt = new Date(baseDate);
+ datesetter.call(dt, fields.year, fields.month, fields.date);
+ timesetter.call(dt, fields.hours, fields.minutes,
+ fields.seconds, fields.milliseconds);
+ } else {
+ dt = new Date(0);
+ datesetter.call(dt, fields.year, fields.month, fields.date);
+ timesetter.call(dt, fields.hours || 0, fields.minutes || 0,
+ fields.seconds || 0, fields.milliseconds || 0);
+ }
+ }
+
+ return dt;
+ }
+ };
+
+ // Check if date is valid for specific month (and year for February).
+ // Month: 0 = Jan, 1 = Feb, etc
+ function isValid(year, month, date) {
+ if (date < 1) {
+ return false;
+ }
+
+ if (month === 1 && date > 28) {
+ return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);
+ }
+
+ if (month === 3 || month === 5 || month === 8 || month === 10) {
+ return date < 31;
+ }
+
+ return true;
+ }
+
+ function toInt(str) {
+ return parseInt(str, 10);
+ }
+
+ this.toTimezone = toTimezone;
+ this.fromTimezone = fromTimezone;
+ this.timezoneToOffset = timezoneToOffset;
+ this.addDateMinutes = addDateMinutes;
+ this.convertTimezoneToLocal = convertTimezoneToLocal;
+
+ function toTimezone(date, timezone) {
+ return date && timezone ? convertTimezoneToLocal(date, timezone) : date;
+ }
+
+ function fromTimezone(date, timezone) {
+ return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
+ }
+
+ //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
+ function timezoneToOffset(timezone, fallback) {
+ timezone = timezone.replace(/:/g, '');
+ var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
+ return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
+ }
+
+ function addDateMinutes(date, minutes) {
+ date = new Date(date.getTime());
+ date.setMinutes(date.getMinutes() + minutes);
+ return date;
+ }
+
+ function convertTimezoneToLocal(date, timezone, reverse) {
+ reverse = reverse ? -1 : 1;
+ var dateTimezoneOffset = date.getTimezoneOffset();
+ var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
+ return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
+ }
+}]);
+
+// Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to
+// at most one element.
+angular.module('ui.bootstrap.isClass', [])
+.directive('uibIsClass', [
+ '$animate',
+function ($animate) {
+ // 11111111 22222222
+ var ON_REGEXP = /^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/;
+ // 11111111 22222222
+ var IS_REGEXP = /^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;
+
+ var dataPerTracked = {};
+
+ return {
+ restrict: 'A',
+ compile: function(tElement, tAttrs) {
+ var linkedScopes = [];
+ var instances = [];
+ var expToData = {};
+ var lastActivated = null;
+ var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);
+ var onExp = onExpMatches[2];
+ var expsStr = onExpMatches[1];
+ var exps = expsStr.split(',');
+
+ return linkFn;
+
+ function linkFn(scope, element, attrs) {
+ linkedScopes.push(scope);
+ instances.push({
+ scope: scope,
+ element: element
+ });
+
+ exps.forEach(function(exp, k) {
+ addForExp(exp, scope);
+ });
+
+ scope.$on('$destroy', removeScope);
+ }
+
+ function addForExp(exp, scope) {
+ var matches = exp.match(IS_REGEXP);
+ var clazz = scope.$eval(matches[1]);
+ var compareWithExp = matches[2];
+ var data = expToData[exp];
+ if (!data) {
+ var watchFn = function(compareWithVal) {
+ var newActivated = null;
+ instances.some(function(instance) {
+ var thisVal = instance.scope.$eval(onExp);
+ if (thisVal === compareWithVal) {
+ newActivated = instance;
+ return true;
+ }
+ });
+ if (data.lastActivated !== newActivated) {
+ if (data.lastActivated) {
+ $animate.removeClass(data.lastActivated.element, clazz);
+ }
+ if (newActivated) {
+ $animate.addClass(newActivated.element, clazz);
+ }
+ data.lastActivated = newActivated;
+ }
+ };
+ expToData[exp] = data = {
+ lastActivated: null,
+ scope: scope,
+ watchFn: watchFn,
+ compareWithExp: compareWithExp,
+ watcher: scope.$watch(compareWithExp, watchFn)
+ };
+ }
+ data.watchFn(scope.$eval(compareWithExp));
+ }
+
+ function removeScope(e) {
+ var removedScope = e.targetScope;
+ var index = linkedScopes.indexOf(removedScope);
+ linkedScopes.splice(index, 1);
+ instances.splice(index, 1);
+ if (linkedScopes.length) {
+ var newWatchScope = linkedScopes[0];
+ angular.forEach(expToData, function(data) {
+ if (data.scope === removedScope) {
+ data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);
+ data.scope = newWatchScope;
+ }
+ });
+ } else {
+ expToData = {};
+ }
+ }
+ }
+ };
+}]);
+angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])
+
+.value('$datepickerSuppressError', false)
+
+.value('$datepickerLiteralWarning', true)
+
+.constant('uibDatepickerConfig', {
+ datepickerMode: 'day',
+ formatDay: 'dd',
+ formatMonth: 'MMMM',
+ formatYear: 'yyyy',
+ formatDayHeader: 'EEE',
+ formatDayTitle: 'MMMM yyyy',
+ formatMonthTitle: 'yyyy',
+ maxDate: null,
+ maxMode: 'year',
+ minDate: null,
+ minMode: 'day',
+ monthColumns: 3,
+ ngModelOptions: {},
+ shortcutPropagation: false,
+ showWeeks: true,
+ yearColumns: 5,
+ yearRows: 4
+})
+
+.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
+ function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
+ var self = this,
+ ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
+ ngModelOptions = {},
+ watchListeners = [];
+
+ $element.addClass('uib-datepicker');
+ $attrs.$set('role', 'application');
+
+ if (!$scope.datepickerOptions) {
+ $scope.datepickerOptions = {};
+ }
+
+ // Modes chain
+ this.modes = ['day', 'month', 'year'];
+
+ [
+ 'customClass',
+ 'dateDisabled',
+ 'datepickerMode',
+ 'formatDay',
+ 'formatDayHeader',
+ 'formatDayTitle',
+ 'formatMonth',
+ 'formatMonthTitle',
+ 'formatYear',
+ 'maxDate',
+ 'maxMode',
+ 'minDate',
+ 'minMode',
+ 'monthColumns',
+ 'showWeeks',
+ 'shortcutPropagation',
+ 'startingDay',
+ 'yearColumns',
+ 'yearRows'
+ ].forEach(function(key) {
+ switch (key) {
+ case 'customClass':
+ case 'dateDisabled':
+ $scope[key] = $scope.datepickerOptions[key] || angular.noop;
+ break;
+ case 'datepickerMode':
+ $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?
+ $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;
+ break;
+ case 'formatDay':
+ case 'formatDayHeader':
+ case 'formatDayTitle':
+ case 'formatMonth':
+ case 'formatMonthTitle':
+ case 'formatYear':
+ self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
+ $interpolate($scope.datepickerOptions[key])($scope.$parent) :
+ datepickerConfig[key];
+ break;
+ case 'monthColumns':
+ case 'showWeeks':
+ case 'shortcutPropagation':
+ case 'yearColumns':
+ case 'yearRows':
+ self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
+ $scope.datepickerOptions[key] : datepickerConfig[key];
+ break;
+ case 'startingDay':
+ if (angular.isDefined($scope.datepickerOptions.startingDay)) {
+ self.startingDay = $scope.datepickerOptions.startingDay;
+ } else if (angular.isNumber(datepickerConfig.startingDay)) {
+ self.startingDay = datepickerConfig.startingDay;
+ } else {
+ self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
+ }
+
+ break;
+ case 'maxDate':
+ case 'minDate':
+ $scope.$watch('datepickerOptions.' + key, function(value) {
+ if (value) {
+ if (angular.isDate(value)) {
+ self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone'));
+ } else {
+ if ($datepickerLiteralWarning) {
+ $log.warn('Literal date support has been deprecated, please switch to date object usage');
+ }
+
+ self[key] = new Date(dateFilter(value, 'medium'));
+ }
+ } else {
+ self[key] = datepickerConfig[key] ?
+ dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) :
+ null;
+ }
+
+ self.refreshView();
+ });
+
+ break;
+ case 'maxMode':
+ case 'minMode':
+ if ($scope.datepickerOptions[key]) {
+ $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
+ self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];
+ if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||
+ key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {
+ $scope.datepickerMode = self[key];
+ $scope.datepickerOptions.datepickerMode = self[key];
+ }
+ });
+ } else {
+ self[key] = $scope[key] = datepickerConfig[key] || null;
+ }
+
+ break;
+ }
+ });
+
+ $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
+
+ $scope.disabled = angular.isDefined($attrs.disabled) || false;
+ if (angular.isDefined($attrs.ngDisabled)) {
+ watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
+ $scope.disabled = disabled;
+ self.refreshView();
+ }));
+ }
+
+ $scope.isActive = function(dateObject) {
+ if (self.compare(dateObject.date, self.activeDate) === 0) {
+ $scope.activeDateId = dateObject.uid;
+ return true;
+ }
+ return false;
+ };
+
+ this.init = function(ngModelCtrl_) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelOptions = extractOptions(ngModelCtrl);
+
+ if ($scope.datepickerOptions.initDate) {
+ self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date();
+ $scope.$watch('datepickerOptions.initDate', function(initDate) {
+ if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
+ self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone'));
+ self.refreshView();
+ }
+ });
+ } else {
+ self.activeDate = new Date();
+ }
+
+ var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
+ this.activeDate = !isNaN(date) ?
+ dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) :
+ dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
+
+ ngModelCtrl.$render = function() {
+ self.render();
+ };
+ };
+
+ this.render = function() {
+ if (ngModelCtrl.$viewValue) {
+ var date = new Date(ngModelCtrl.$viewValue),
+ isValid = !isNaN(date);
+
+ if (isValid) {
+ this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
+ } else if (!$datepickerSuppressError) {
+ $log.error('Datepicker directive: "ng-model" value must be a Date object');
+ }
+ }
+ this.refreshView();
+ };
+
+ this.refreshView = function() {
+ if (this.element) {
+ $scope.selectedDt = null;
+ this._refreshView();
+ if ($scope.activeDt) {
+ $scope.activeDateId = $scope.activeDt.uid;
+ }
+
+ var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
+ date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
+ ngModelCtrl.$setValidity('dateDisabled', !date ||
+ this.element && !this.isDisabled(date));
+ }
+ };
+
+ this.createDateObject = function(date, format) {
+ var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
+ model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone'));
+ var today = new Date();
+ today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
+ var time = this.compare(date, today);
+ var dt = {
+ date: date,
+ label: dateParser.filter(date, format),
+ selected: model && this.compare(date, model) === 0,
+ disabled: this.isDisabled(date),
+ past: time < 0,
+ current: time === 0,
+ future: time > 0,
+ customClass: this.customClass(date) || null
+ };
+
+ if (model && this.compare(date, model) === 0) {
+ $scope.selectedDt = dt;
+ }
+
+ if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {
+ $scope.activeDt = dt;
+ }
+
+ return dt;
+ };
+
+ this.isDisabled = function(date) {
+ return $scope.disabled ||
+ this.minDate && this.compare(date, this.minDate) < 0 ||
+ this.maxDate && this.compare(date, this.maxDate) > 0 ||
+ $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});
+ };
+
+ this.customClass = function(date) {
+ return $scope.customClass({date: date, mode: $scope.datepickerMode});
+ };
+
+ // Split array into smaller arrays
+ this.split = function(arr, size) {
+ var arrays = [];
+ while (arr.length > 0) {
+ arrays.push(arr.splice(0, size));
+ }
+ return arrays;
+ };
+
+ $scope.select = function(date) {
+ if ($scope.datepickerMode === self.minMode) {
+ var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);
+ dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+ dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));
+ ngModelCtrl.$setViewValue(dt);
+ ngModelCtrl.$render();
+ } else {
+ self.activeDate = date;
+ setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
+
+ $scope.$emit('uib:datepicker.mode');
+ }
+
+ $scope.$broadcast('uib:datepicker.focus');
+ };
+
+ $scope.move = function(direction) {
+ var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
+ month = self.activeDate.getMonth() + direction * (self.step.months || 0);
+ self.activeDate.setFullYear(year, month, 1);
+ self.refreshView();
+ };
+
+ $scope.toggleMode = function(direction) {
+ direction = direction || 1;
+
+ if ($scope.datepickerMode === self.maxMode && direction === 1 ||
+ $scope.datepickerMode === self.minMode && direction === -1) {
+ return;
+ }
+
+ setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);
+
+ $scope.$emit('uib:datepicker.mode');
+ };
+
+ // Key event mapper
+ $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };
+
+ var focusElement = function() {
+ self.element[0].focus();
+ };
+
+ // Listen for focus requests from popup directive
+ $scope.$on('uib:datepicker.focus', focusElement);
+
+ $scope.keydown = function(evt) {
+ var key = $scope.keys[evt.which];
+
+ if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
+ return;
+ }
+
+ evt.preventDefault();
+ if (!self.shortcutPropagation) {
+ evt.stopPropagation();
+ }
+
+ if (key === 'enter' || key === 'space') {
+ if (self.isDisabled(self.activeDate)) {
+ return; // do nothing
+ }
+ $scope.select(self.activeDate);
+ } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
+ $scope.toggleMode(key === 'up' ? 1 : -1);
+ } else {
+ self.handleKeyDown(key, evt);
+ self.refreshView();
+ }
+ };
+
+ $element.on('keydown', function(evt) {
+ $scope.$apply(function() {
+ $scope.keydown(evt);
+ });
+ });
+
+ $scope.$on('$destroy', function() {
+ //Clear all watch listeners on destroy
+ while (watchListeners.length) {
+ watchListeners.shift()();
+ }
+ });
+
+ function setMode(mode) {
+ $scope.datepickerMode = mode;
+ $scope.datepickerOptions.datepickerMode = mode;
+ }
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = ngModelCtrl.$options ||
+ $scope.datepickerOptions.ngModelOptions ||
+ datepickerConfig.ngModelOptions ||
+ {};
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ // ng-model-options defaults timezone to null; don't let its precedence squash a non-null value
+ var timezone = ngModelCtrl.$options.getOption('timezone') ||
+ ($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) ||
+ (datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null);
+
+ // values passed to createChild override existing values
+ ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance
+ .createChild(datepickerConfig.ngModelOptions) // lowest precedence
+ .createChild($scope.datepickerOptions.ngModelOptions)
+ .createChild(ngModelCtrl.$options) // highest precedence
+ .createChild({timezone: timezone}); // to keep from squashing a non-null value
+ }
+
+ return ngModelOptions;
+ }
+}])
+
+.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+ this.step = { months: 1 };
+ this.element = $element;
+ function getDaysInMonth(year, month) {
+ return month === 1 && year % 4 === 0 &&
+ (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];
+ }
+
+ this.init = function(ctrl) {
+ angular.extend(ctrl, this);
+ scope.showWeeks = ctrl.showWeeks;
+ ctrl.refreshView();
+ };
+
+ this.getDates = function(startDate, n) {
+ var dates = new Array(n), current = new Date(startDate), i = 0, date;
+ while (i < n) {
+ date = new Date(current);
+ dates[i++] = date;
+ current.setDate(current.getDate() + 1);
+ }
+ return dates;
+ };
+
+ this._refreshView = function() {
+ var year = this.activeDate.getFullYear(),
+ month = this.activeDate.getMonth(),
+ firstDayOfMonth = new Date(this.activeDate);
+
+ firstDayOfMonth.setFullYear(year, month, 1);
+
+ var difference = this.startingDay - firstDayOfMonth.getDay(),
+ numDisplayedFromPreviousMonth = difference > 0 ?
+ 7 - difference : - difference,
+ firstDate = new Date(firstDayOfMonth);
+
+ if (numDisplayedFromPreviousMonth > 0) {
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
+ }
+
+ // 42 is the number of days on a six-week calendar
+ var days = this.getDates(firstDate, 42);
+ for (var i = 0; i < 42; i ++) {
+ days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {
+ secondary: days[i].getMonth() !== month,
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.labels = new Array(7);
+ for (var j = 0; j < 7; j++) {
+ scope.labels[j] = {
+ abbr: dateFilter(days[j].date, this.formatDayHeader),
+ full: dateFilter(days[j].date, 'EEEE')
+ };
+ }
+
+ scope.title = dateFilter(this.activeDate, this.formatDayTitle);
+ scope.rows = this.split(days, 7);
+
+ if (scope.showWeeks) {
+ scope.weekNumbers = [];
+ var thursdayIndex = (4 + 7 - this.startingDay) % 7,
+ numWeeks = scope.rows.length;
+ for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
+ scope.weekNumbers.push(
+ getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
+ }
+ }
+ };
+
+ this.compare = function(date1, date2) {
+ var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
+ var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
+ _date1.setFullYear(date1.getFullYear());
+ _date2.setFullYear(date2.getFullYear());
+ return _date1 - _date2;
+ };
+
+ function getISO8601WeekNumber(date) {
+ var checkDate = new Date(date);
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
+ var time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+ }
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getDate();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - 7;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + 7;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);
+ this.activeDate.setMonth(month, 1);
+ date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);
+ } else if (key === 'home') {
+ date = 1;
+ } else if (key === 'end') {
+ date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());
+ }
+ this.activeDate.setDate(date);
+ };
+}])
+
+.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ this.step = { years: 1 };
+ this.element = $element;
+
+ this.init = function(ctrl) {
+ angular.extend(ctrl, this);
+ ctrl.refreshView();
+ };
+
+ this._refreshView = function() {
+ var months = new Array(12),
+ year = this.activeDate.getFullYear(),
+ date;
+
+ for (var i = 0; i < 12; i++) {
+ date = new Date(this.activeDate);
+ date.setFullYear(year, i, 1);
+ months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
+ scope.rows = this.split(months, this.monthColumns);
+ scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
+ };
+
+ this.compare = function(date1, date2) {
+ var _date1 = new Date(date1.getFullYear(), date1.getMonth());
+ var _date2 = new Date(date2.getFullYear(), date2.getMonth());
+ _date1.setFullYear(date1.getFullYear());
+ _date2.setFullYear(date2.getFullYear());
+ return _date1 - _date2;
+ };
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getMonth();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - this.monthColumns;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + this.monthColumns;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
+ this.activeDate.setFullYear(year);
+ } else if (key === 'home') {
+ date = 0;
+ } else if (key === 'end') {
+ date = 11;
+ }
+ this.activeDate.setMonth(date);
+ };
+}])
+
+.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {
+ var columns, range;
+ this.element = $element;
+
+ function getStartingYear(year) {
+ return parseInt((year - 1) / range, 10) * range + 1;
+ }
+
+ this.yearpickerInit = function() {
+ columns = this.yearColumns;
+ range = this.yearRows * columns;
+ this.step = { years: range };
+ };
+
+ this._refreshView = function() {
+ var years = new Array(range), date;
+
+ for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {
+ date = new Date(this.activeDate);
+ date.setFullYear(start + i, 0, 1);
+ years[i] = angular.extend(this.createDateObject(date, this.formatYear), {
+ uid: scope.uniqueId + '-' + i
+ });
+ }
+
+ scope.title = [years[0].label, years[range - 1].label].join(' - ');
+ scope.rows = this.split(years, columns);
+ scope.columns = columns;
+ };
+
+ this.compare = function(date1, date2) {
+ return date1.getFullYear() - date2.getFullYear();
+ };
+
+ this.handleKeyDown = function(key, evt) {
+ var date = this.activeDate.getFullYear();
+
+ if (key === 'left') {
+ date = date - 1;
+ } else if (key === 'up') {
+ date = date - columns;
+ } else if (key === 'right') {
+ date = date + 1;
+ } else if (key === 'down') {
+ date = date + columns;
+ } else if (key === 'pageup' || key === 'pagedown') {
+ date += (key === 'pageup' ? - 1 : 1) * range;
+ } else if (key === 'home') {
+ date = getStartingYear(this.activeDate.getFullYear());
+ } else if (key === 'end') {
+ date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
+ }
+ this.activeDate.setFullYear(date);
+ };
+}])
+
+.directive('uibDatepicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
+ },
+ scope: {
+ datepickerOptions: '=?'
+ },
+ require: ['uibDatepicker', '^ngModel'],
+ restrict: 'A',
+ controller: 'UibDatepickerController',
+ controllerAs: 'datepicker',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ datepickerCtrl.init(ngModelCtrl);
+ }
+ };
+})
+
+.directive('uibDaypicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/day.html';
+ },
+ require: ['^uibDatepicker', 'uibDaypicker'],
+ restrict: 'A',
+ controller: 'UibDaypickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0],
+ daypickerCtrl = ctrls[1];
+
+ daypickerCtrl.init(datepickerCtrl);
+ }
+ };
+})
+
+.directive('uibMonthpicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/month.html';
+ },
+ require: ['^uibDatepicker', 'uibMonthpicker'],
+ restrict: 'A',
+ controller: 'UibMonthpickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0],
+ monthpickerCtrl = ctrls[1];
+
+ monthpickerCtrl.init(datepickerCtrl);
+ }
+ };
+})
+
+.directive('uibYearpicker', function() {
+ return {
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepicker/year.html';
+ },
+ require: ['^uibDatepicker', 'uibYearpicker'],
+ restrict: 'A',
+ controller: 'UibYearpickerController',
+ link: function(scope, element, attrs, ctrls) {
+ var ctrl = ctrls[0];
+ angular.extend(ctrl, ctrls[1]);
+ ctrl.yearpickerInit();
+
+ ctrl.refreshView();
+ }
+ };
+});
+
+angular.module('ui.bootstrap.position', [])
+
+/**
+ * A set of utility methods for working with the DOM.
+ * It is meant to be used where we need to absolute-position elements in
+ * relation to another element (this is the case for tooltips, popovers,
+ * typeahead suggestions etc.).
+ */
+ .factory('$uibPosition', ['$document', '$window', function($document, $window) {
+ /**
+ * Used by scrollbarWidth() function to cache scrollbar's width.
+ * Do not access this variable directly, use scrollbarWidth() instead.
+ */
+ var SCROLLBAR_WIDTH;
+ /**
+ * scrollbar on body and html element in IE and Edge overlay
+ * content and should be considered 0 width.
+ */
+ var BODY_SCROLLBAR_WIDTH;
+ var OVERFLOW_REGEX = {
+ normal: /(auto|scroll)/,
+ hidden: /(auto|scroll|hidden)/
+ };
+ var PLACEMENT_REGEX = {
+ auto: /\s?auto?\s?/i,
+ primary: /^(top|bottom|left|right)$/,
+ secondary: /^(top|bottom|left|right|center)$/,
+ vertical: /^(top|bottom)$/
+ };
+ var BODY_REGEX = /(HTML|BODY)/;
+
+ return {
+
+ /**
+ * Provides a raw DOM element from a jQuery/jQLite element.
+ *
+ * @param {element} elem - The element to convert.
+ *
+ * @returns {element} A HTML element.
+ */
+ getRawNode: function(elem) {
+ return elem.nodeName ? elem : elem[0] || elem;
+ },
+
+ /**
+ * Provides a parsed number for a style property. Strips
+ * units and casts invalid numbers to 0.
+ *
+ * @param {string} value - The style value to parse.
+ *
+ * @returns {number} A valid number.
+ */
+ parseStyle: function(value) {
+ value = parseFloat(value);
+ return isFinite(value) ? value : 0;
+ },
+
+ /**
+ * Provides the closest positioned ancestor.
+ *
+ * @param {element} element - The element to get the offest parent for.
+ *
+ * @returns {element} The closest positioned ancestor.
+ */
+ offsetParent: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var offsetParent = elem.offsetParent || $document[0].documentElement;
+
+ function isStaticPositioned(el) {
+ return ($window.getComputedStyle(el).position || 'static') === 'static';
+ }
+
+ while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || $document[0].documentElement;
+ },
+
+ /**
+ * Provides the scrollbar width, concept from TWBS measureScrollbar()
+ * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js
+ * In IE and Edge, scollbar on body and html element overlay and should
+ * return a width of 0.
+ *
+ * @returns {number} The width of the browser scollbar.
+ */
+ scrollbarWidth: function(isBody) {
+ if (isBody) {
+ if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {
+ var bodyElem = $document.find('body');
+ bodyElem.addClass('uib-position-body-scrollbar-measure');
+ BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;
+ BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;
+ bodyElem.removeClass('uib-position-body-scrollbar-measure');
+ }
+ return BODY_SCROLLBAR_WIDTH;
+ }
+
+ if (angular.isUndefined(SCROLLBAR_WIDTH)) {
+ var scrollElem = angular.element('<div class="uib-position-scrollbar-measure"></div>');
+ $document.find('body').append(scrollElem);
+ SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;
+ SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;
+ scrollElem.remove();
+ }
+
+ return SCROLLBAR_WIDTH;
+ },
+
+ /**
+ * Provides the padding required on an element to replace the scrollbar.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**scrollbarWidth**: the width of the scrollbar</li>
+ * <li>**widthOverflow**: whether the the width is overflowing</li>
+ * <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>
+ * <li>**rightOriginal**: the amount of right padding currently on the element</li>
+ * <li>**heightOverflow**: whether the the height is overflowing</li>
+ * <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>
+ * <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>
+ * </ul>
+ */
+ scrollbarPadding: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemStyle = $window.getComputedStyle(elem);
+ var paddingRight = this.parseStyle(elemStyle.paddingRight);
+ var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
+ var scrollParent = this.scrollParent(elem, false, true);
+ var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));
+
+ return {
+ scrollbarWidth: scrollbarWidth,
+ widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,
+ right: paddingRight + scrollbarWidth,
+ originalRight: paddingRight,
+ heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,
+ bottom: paddingBottom + scrollbarWidth,
+ originalBottom: paddingBottom
+ };
+ },
+
+ /**
+ * Checks to see if the element is scrollable.
+ *
+ * @param {element} elem - The element to check.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ *
+ * @returns {boolean} Whether the element is scrollable.
+ */
+ isScrollable: function(elem, includeHidden) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var elemStyle = $window.getComputedStyle(elem);
+ return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);
+ },
+
+ /**
+ * Provides the closest scrollable ancestor.
+ * A port of the jQuery UI scrollParent method:
+ * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js
+ *
+ * @param {element} elem - The element to find the scroll parent of.
+ * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,
+ * default is false.
+ * @param {boolean=} [includeSelf=false] - Should the element being passed be
+ * included in the scrollable llokup.
+ *
+ * @returns {element} A HTML element.
+ */
+ scrollParent: function(elem, includeHidden, includeSelf) {
+ elem = this.getRawNode(elem);
+
+ var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;
+ var documentEl = $document[0].documentElement;
+ var elemStyle = $window.getComputedStyle(elem);
+ if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
+ return elem;
+ }
+ var excludeStatic = elemStyle.position === 'absolute';
+ var scrollParent = elem.parentElement || documentEl;
+
+ if (scrollParent === documentEl || elemStyle.position === 'fixed') {
+ return documentEl;
+ }
+
+ while (scrollParent.parentElement && scrollParent !== documentEl) {
+ var spStyle = $window.getComputedStyle(scrollParent);
+ if (excludeStatic && spStyle.position !== 'static') {
+ excludeStatic = false;
+ }
+
+ if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
+ break;
+ }
+ scrollParent = scrollParent.parentElement;
+ }
+
+ return scrollParent;
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's position function:
+ * http://api.jquery.com/position/ - distance to closest positioned
+ * ancestor. Does not account for margins by default like jQuery position.
+ *
+ * @param {element} elem - The element to caclulate the position on.
+ * @param {boolean=} [includeMargins=false] - Should margins be accounted
+ * for, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**width**: the width of the element</li>
+ * <li>**height**: the height of the element</li>
+ * <li>**top**: distance to top edge of offset parent</li>
+ * <li>**left**: distance to left edge of offset parent</li>
+ * </ul>
+ */
+ position: function(elem, includeMagins) {
+ elem = this.getRawNode(elem);
+
+ var elemOffset = this.offset(elem);
+ if (includeMagins) {
+ var elemStyle = $window.getComputedStyle(elem);
+ elemOffset.top -= this.parseStyle(elemStyle.marginTop);
+ elemOffset.left -= this.parseStyle(elemStyle.marginLeft);
+ }
+ var parent = this.offsetParent(elem);
+ var parentOffset = {top: 0, left: 0};
+
+ if (parent !== $document[0].documentElement) {
+ parentOffset = this.offset(parent);
+ parentOffset.top += parent.clientTop - parent.scrollTop;
+ parentOffset.left += parent.clientLeft - parent.scrollLeft;
+ }
+
+ return {
+ width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),
+ top: Math.round(elemOffset.top - parentOffset.top),
+ left: Math.round(elemOffset.left - parentOffset.left)
+ };
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's offset function:
+ * http://api.jquery.com/offset/ - distance to viewport. Does
+ * not account for borders, margins, or padding on the body
+ * element.
+ *
+ * @param {element} elem - The element to calculate the offset on.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**width**: the width of the element</li>
+ * <li>**height**: the height of the element</li>
+ * <li>**top**: distance to top edge of viewport</li>
+ * <li>**right**: distance to bottom edge of viewport</li>
+ * </ul>
+ */
+ offset: function(elem) {
+ elem = this.getRawNode(elem);
+
+ var elemBCR = elem.getBoundingClientRect();
+ return {
+ width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),
+ height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),
+ top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),
+ left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))
+ };
+ },
+
+ /**
+ * Provides offset distance to the closest scrollable ancestor
+ * or viewport. Accounts for border and scrollbar width.
+ *
+ * Right and bottom dimensions represent the distance to the
+ * respective edge of the viewport element. If the element
+ * edge extends beyond the viewport, a negative value will be
+ * reported.
+ *
+ * @param {element} elem - The element to get the viewport offset for.
+ * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead
+ * of the first scrollable element, default is false.
+ * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element
+ * be accounted for, default is true.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**top**: distance to the top content edge of viewport element</li>
+ * <li>**bottom**: distance to the bottom content edge of viewport element</li>
+ * <li>**left**: distance to the left content edge of viewport element</li>
+ * <li>**right**: distance to the right content edge of viewport element</li>
+ * </ul>
+ */
+ viewportOffset: function(elem, useDocument, includePadding) {
+ elem = this.getRawNode(elem);
+ includePadding = includePadding !== false ? true : false;
+
+ var elemBCR = elem.getBoundingClientRect();
+ var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};
+
+ var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);
+ var offsetParentBCR = offsetParent.getBoundingClientRect();
+
+ offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;
+ offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;
+ if (offsetParent === $document[0].documentElement) {
+ offsetBCR.top += $window.pageYOffset;
+ offsetBCR.left += $window.pageXOffset;
+ }
+ offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;
+ offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;
+
+ if (includePadding) {
+ var offsetParentStyle = $window.getComputedStyle(offsetParent);
+ offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);
+ offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);
+ offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);
+ offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);
+ }
+
+ return {
+ top: Math.round(elemBCR.top - offsetBCR.top),
+ bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),
+ left: Math.round(elemBCR.left - offsetBCR.left),
+ right: Math.round(offsetBCR.right - elemBCR.right)
+ };
+ },
+
+ /**
+ * Provides an array of placement values parsed from a placement string.
+ * Along with the 'auto' indicator, supported placement strings are:
+ * <ul>
+ * <li>top: element on top, horizontally centered on host element.</li>
+ * <li>top-left: element on top, left edge aligned with host element left edge.</li>
+ * <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>
+ * <li>bottom: element on bottom, horizontally centered on host element.</li>
+ * <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>
+ * <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>
+ * <li>left: element on left, vertically centered on host element.</li>
+ * <li>left-top: element on left, top edge aligned with host element top edge.</li>
+ * <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>
+ * <li>right: element on right, vertically centered on host element.</li>
+ * <li>right-top: element on right, top edge aligned with host element top edge.</li>
+ * <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>
+ * </ul>
+ * A placement string with an 'auto' indicator is expected to be
+ * space separated from the placement, i.e: 'auto bottom-left' If
+ * the primary and secondary placement values do not match 'top,
+ * bottom, left, right' then 'top' will be the primary placement and
+ * 'center' will be the secondary placement. If 'auto' is passed, true
+ * will be returned as the 3rd value of the array.
+ *
+ * @param {string} placement - The placement string to parse.
+ *
+ * @returns {array} An array with the following values
+ * <ul>
+ * <li>**[0]**: The primary placement.</li>
+ * <li>**[1]**: The secondary placement.</li>
+ * <li>**[2]**: If auto is passed: true, else undefined.</li>
+ * </ul>
+ */
+ parsePlacement: function(placement) {
+ var autoPlace = PLACEMENT_REGEX.auto.test(placement);
+ if (autoPlace) {
+ placement = placement.replace(PLACEMENT_REGEX.auto, '');
+ }
+
+ placement = placement.split('-');
+
+ placement[0] = placement[0] || 'top';
+ if (!PLACEMENT_REGEX.primary.test(placement[0])) {
+ placement[0] = 'top';
+ }
+
+ placement[1] = placement[1] || 'center';
+ if (!PLACEMENT_REGEX.secondary.test(placement[1])) {
+ placement[1] = 'center';
+ }
+
+ if (autoPlace) {
+ placement[2] = true;
+ } else {
+ placement[2] = false;
+ }
+
+ return placement;
+ },
+
+ /**
+ * Provides coordinates for an element to be positioned relative to
+ * another element. Passing 'auto' as part of the placement parameter
+ * will enable smart placement - where the element fits. i.e:
+ * 'auto left-top' will check to see if there is enough space to the left
+ * of the hostElem to fit the targetElem, if not place right (same for secondary
+ * top placement). Available space is calculated using the viewportOffset
+ * function.
+ *
+ * @param {element} hostElem - The element to position against.
+ * @param {element} targetElem - The element to position.
+ * @param {string=} [placement=top] - The placement for the targetElem,
+ * default is 'top'. 'center' is assumed as secondary placement for
+ * 'top', 'left', 'right', and 'bottom' placements. Available placements are:
+ * <ul>
+ * <li>top</li>
+ * <li>top-right</li>
+ * <li>top-left</li>
+ * <li>bottom</li>
+ * <li>bottom-left</li>
+ * <li>bottom-right</li>
+ * <li>left</li>
+ * <li>left-top</li>
+ * <li>left-bottom</li>
+ * <li>right</li>
+ * <li>right-top</li>
+ * <li>right-bottom</li>
+ * </ul>
+ * @param {boolean=} [appendToBody=false] - Should the top and left values returned
+ * be calculated from the body element, default is false.
+ *
+ * @returns {object} An object with the following properties:
+ * <ul>
+ * <li>**top**: Value for targetElem top.</li>
+ * <li>**left**: Value for targetElem left.</li>
+ * <li>**placement**: The resolved placement.</li>
+ * </ul>
+ */
+ positionElements: function(hostElem, targetElem, placement, appendToBody) {
+ hostElem = this.getRawNode(hostElem);
+ targetElem = this.getRawNode(targetElem);
+
+ // need to read from prop to support tests.
+ var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');
+ var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');
+
+ placement = this.parsePlacement(placement);
+
+ var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);
+ var targetElemPos = {top: 0, left: 0, placement: ''};
+
+ if (placement[2]) {
+ var viewportOffset = this.viewportOffset(hostElem, appendToBody);
+
+ var targetElemStyle = $window.getComputedStyle(targetElem);
+ var adjustedSize = {
+ width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),
+ height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))
+ };
+
+ placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :
+ placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :
+ placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :
+ placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :
+ placement[0];
+
+ placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :
+ placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :
+ placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :
+ placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :
+ placement[1];
+
+ if (placement[1] === 'center') {
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ var xOverflow = hostElemPos.width / 2 - targetWidth / 2;
+ if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {
+ placement[1] = 'left';
+ } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {
+ placement[1] = 'right';
+ }
+ } else {
+ var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;
+ if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {
+ placement[1] = 'top';
+ } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {
+ placement[1] = 'bottom';
+ }
+ }
+ }
+ }
+
+ switch (placement[0]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top - targetHeight;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left - targetWidth;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width;
+ break;
+ }
+
+ switch (placement[1]) {
+ case 'top':
+ targetElemPos.top = hostElemPos.top;
+ break;
+ case 'bottom':
+ targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;
+ break;
+ case 'left':
+ targetElemPos.left = hostElemPos.left;
+ break;
+ case 'right':
+ targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;
+ break;
+ case 'center':
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;
+ } else {
+ targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;
+ }
+ break;
+ }
+
+ targetElemPos.top = Math.round(targetElemPos.top);
+ targetElemPos.left = Math.round(targetElemPos.left);
+ targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];
+
+ return targetElemPos;
+ },
+
+ /**
+ * Provides a way to adjust the top positioning after first
+ * render to correctly align element to top after content
+ * rendering causes resized element height
+ *
+ * @param {array} placementClasses - The array of strings of classes
+ * element should have.
+ * @param {object} containerPosition - The object with container
+ * position information
+ * @param {number} initialHeight - The initial height for the elem.
+ * @param {number} currentHeight - The current height for the elem.
+ */
+ adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) {
+ if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {
+ return {
+ top: containerPosition.top - currentHeight + 'px'
+ };
+ }
+ },
+
+ /**
+ * Provides a way for positioning tooltip & dropdown
+ * arrows when using placement options beyond the standard
+ * left, right, top, or bottom.
+ *
+ * @param {element} elem - The tooltip/dropdown element.
+ * @param {string} placement - The placement for the elem.
+ */
+ positionArrow: function(elem, placement) {
+ elem = this.getRawNode(elem);
+
+ var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');
+ if (!innerElem) {
+ return;
+ }
+
+ var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');
+
+ var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');
+ if (!arrowElem) {
+ return;
+ }
+
+ var arrowCss = {
+ top: '',
+ bottom: '',
+ left: '',
+ right: ''
+ };
+
+ placement = this.parsePlacement(placement);
+ if (placement[1] === 'center') {
+ // no adjustment necessary - just reset styles
+ angular.element(arrowElem).css(arrowCss);
+ return;
+ }
+
+ var borderProp = 'border-' + placement[0] + '-width';
+ var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];
+
+ var borderRadiusProp = 'border-';
+ if (PLACEMENT_REGEX.vertical.test(placement[0])) {
+ borderRadiusProp += placement[0] + '-' + placement[1];
+ } else {
+ borderRadiusProp += placement[1] + '-' + placement[0];
+ }
+ borderRadiusProp += '-radius';
+ var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];
+
+ switch (placement[0]) {
+ case 'top':
+ arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'bottom':
+ arrowCss.top = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'left':
+ arrowCss.right = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ case 'right':
+ arrowCss.left = isTooltip ? '0' : '-' + borderWidth;
+ break;
+ }
+
+ arrowCss[placement[1]] = borderRadius;
+
+ angular.element(arrowElem).css(arrowCss);
+ }
+ };
+ }]);
+
+angular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])
+
+.value('$datepickerPopupLiteralWarning', true)
+
+.constant('uibDatepickerPopupConfig', {
+ altInputFormats: [],
+ appendToBody: false,
+ clearText: 'Clear',
+ closeOnDateSelection: true,
+ closeText: 'Done',
+ currentText: 'Today',
+ datepickerPopup: 'yyyy-MM-dd',
+ datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',
+ datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',
+ html5Types: {
+ date: 'yyyy-MM-dd',
+ 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
+ 'month': 'yyyy-MM'
+ },
+ onOpenFocus: true,
+ showButtonBar: true,
+ placement: 'auto bottom-left'
+})
+
+.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',
+function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {
+ var cache = {},
+ isHtml5DateInput = false;
+ var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
+ datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
+ ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];
+
+ this.init = function(_ngModel_) {
+ ngModel = _ngModel_;
+ ngModelOptions = extractOptions(ngModel);
+ closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
+ $scope.$parent.$eval($attrs.closeOnDateSelection) :
+ datepickerPopupConfig.closeOnDateSelection;
+ appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?
+ $scope.$parent.$eval($attrs.datepickerAppendToBody) :
+ datepickerPopupConfig.appendToBody;
+ onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?
+ $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
+ datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?
+ $attrs.datepickerPopupTemplateUrl :
+ datepickerPopupConfig.datepickerPopupTemplateUrl;
+ datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?
+ $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
+ altInputFormats = angular.isDefined($attrs.altInputFormats) ?
+ $scope.$parent.$eval($attrs.altInputFormats) :
+ datepickerPopupConfig.altInputFormats;
+
+ $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?
+ $scope.$parent.$eval($attrs.showButtonBar) :
+ datepickerPopupConfig.showButtonBar;
+
+ if (datepickerPopupConfig.html5Types[$attrs.type]) {
+ dateFormat = datepickerPopupConfig.html5Types[$attrs.type];
+ isHtml5DateInput = true;
+ } else {
+ dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;
+ $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {
+ var newDateFormat = value || datepickerPopupConfig.datepickerPopup;
+ // Invalidate the $modelValue to ensure that formatters re-run
+ // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764
+ if (newDateFormat !== dateFormat) {
+ dateFormat = newDateFormat;
+ ngModel.$modelValue = null;
+
+ if (!dateFormat) {
+ throw new Error('uibDatepickerPopup must have a date format specified.');
+ }
+ }
+ });
+ }
+
+ if (!dateFormat) {
+ throw new Error('uibDatepickerPopup must have a date format specified.');
+ }
+
+ if (isHtml5DateInput && $attrs.uibDatepickerPopup) {
+ throw new Error('HTML5 date input types do not support custom formats.');
+ }
+
+ // popup element used to display calendar
+ popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
+
+ popupEl.attr({
+ 'ng-model': 'date',
+ 'ng-change': 'dateSelection(date)',
+ 'template-url': datepickerPopupTemplateUrl
+ });
+
+ // datepicker element
+ datepickerEl = angular.element(popupEl.children()[0]);
+ datepickerEl.attr('template-url', datepickerTemplateUrl);
+
+ if (!$scope.datepickerOptions) {
+ $scope.datepickerOptions = {};
+ }
+
+ if (isHtml5DateInput) {
+ if ($attrs.type === 'month') {
+ $scope.datepickerOptions.datepickerMode = 'month';
+ $scope.datepickerOptions.minMode = 'month';
+ }
+ }
+
+ datepickerEl.attr('datepicker-options', 'datepickerOptions');
+
+ if (!isHtml5DateInput) {
+ // Internal API to maintain the correct ng-invalid-[key] class
+ ngModel.$$parserName = 'date';
+ ngModel.$validators.date = validator;
+ ngModel.$parsers.unshift(parseDate);
+ ngModel.$formatters.push(function(value) {
+ if (ngModel.$isEmpty(value)) {
+ $scope.date = value;
+ return value;
+ }
+
+ if (angular.isNumber(value)) {
+ value = new Date(value);
+ }
+
+ $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
+
+ return dateParser.filter($scope.date, dateFormat);
+ });
+ } else {
+ ngModel.$formatters.push(function(value) {
+ $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
+ return value;
+ });
+ }
+
+ // Detect changes in the view from the text box
+ ngModel.$viewChangeListeners.push(function() {
+ $scope.date = parseDateString(ngModel.$viewValue);
+ });
+
+ $element.on('keydown', inputKeydownBind);
+
+ $popup = $compile(popupEl)($scope);
+ // Prevent jQuery cache memory leak (template is now redundant after linking)
+ popupEl.remove();
+
+ if (appendToBody) {
+ $document.find('body').append($popup);
+ } else {
+ $element.after($popup);
+ }
+
+ $scope.$on('$destroy', function() {
+ if ($scope.isOpen === true) {
+ if (!$rootScope.$$phase) {
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ }
+ }
+
+ $popup.remove();
+ $element.off('keydown', inputKeydownBind);
+ $document.off('click', documentClickBind);
+ if (scrollParentEl) {
+ scrollParentEl.off('scroll', positionPopup);
+ }
+ angular.element($window).off('resize', positionPopup);
+
+ //Clear all watch listeners on destroy
+ while (watchListeners.length) {
+ watchListeners.shift()();
+ }
+ });
+ };
+
+ $scope.getText = function(key) {
+ return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
+ };
+
+ $scope.isDisabled = function(date) {
+ if (date === 'today') {
+ date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
+ }
+
+ var dates = {};
+ angular.forEach(['minDate', 'maxDate'], function(key) {
+ if (!$scope.datepickerOptions[key]) {
+ dates[key] = null;
+ } else if (angular.isDate($scope.datepickerOptions[key])) {
+ dates[key] = new Date($scope.datepickerOptions[key]);
+ } else {
+ if ($datepickerPopupLiteralWarning) {
+ $log.warn('Literal date support has been deprecated, please switch to date object usage');
+ }
+
+ dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));
+ }
+ });
+
+ return $scope.datepickerOptions &&
+ dates.minDate && $scope.compare(date, dates.minDate) < 0 ||
+ dates.maxDate && $scope.compare(date, dates.maxDate) > 0;
+ };
+
+ $scope.compare = function(date1, date2) {
+ return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
+ };
+
+ // Inner change
+ $scope.dateSelection = function(dt) {
+ $scope.date = dt;
+ var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
+ $element.val(date);
+ ngModel.$setViewValue(date);
+
+ if (closeOnDateSelection) {
+ $scope.isOpen = false;
+ $element[0].focus();
+ }
+ };
+
+ $scope.keydown = function(evt) {
+ if (evt.which === 27) {
+ evt.stopPropagation();
+ $scope.isOpen = false;
+ $element[0].focus();
+ }
+ };
+
+ $scope.select = function(date, evt) {
+ evt.stopPropagation();
+
+ if (date === 'today') {
+ var today = new Date();
+ if (angular.isDate($scope.date)) {
+ date = new Date($scope.date);
+ date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
+ } else {
+ date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
+ date.setHours(0, 0, 0, 0);
+ }
+ }
+ $scope.dateSelection(date);
+ };
+
+ $scope.close = function(evt) {
+ evt.stopPropagation();
+
+ $scope.isOpen = false;
+ $element[0].focus();
+ };
+
+ $scope.disabled = angular.isDefined($attrs.disabled) || false;
+ if ($attrs.ngDisabled) {
+ watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
+ $scope.disabled = disabled;
+ }));
+ }
+
+ $scope.$watch('isOpen', function(value) {
+ if (value) {
+ if (!$scope.disabled) {
+ $timeout(function() {
+ positionPopup();
+
+ if (onOpenFocus) {
+ $scope.$broadcast('uib:datepicker.focus');
+ }
+
+ $document.on('click', documentClickBind);
+
+ var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
+ if (appendToBody || $position.parsePlacement(placement)[2]) {
+ scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
+ if (scrollParentEl) {
+ scrollParentEl.on('scroll', positionPopup);
+ }
+ } else {
+ scrollParentEl = null;
+ }
+
+ angular.element($window).on('resize', positionPopup);
+ }, 0, false);
+ } else {
+ $scope.isOpen = false;
+ }
+ } else {
+ $document.off('click', documentClickBind);
+ if (scrollParentEl) {
+ scrollParentEl.off('scroll', positionPopup);
+ }
+ angular.element($window).off('resize', positionPopup);
+ }
+ });
+
+ function cameltoDash(string) {
+ return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
+ }
+
+ function parseDateString(viewValue) {
+ var date = dateParser.parse(viewValue, dateFormat, $scope.date);
+ if (isNaN(date)) {
+ for (var i = 0; i < altInputFormats.length; i++) {
+ date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);
+ if (!isNaN(date)) {
+ return date;
+ }
+ }
+ }
+ return date;
+ }
+
+ function parseDate(viewValue) {
+ if (angular.isNumber(viewValue)) {
+ // presumably timestamp to date object
+ viewValue = new Date(viewValue);
+ }
+
+ if (!viewValue) {
+ return null;
+ }
+
+ if (angular.isDate(viewValue) && !isNaN(viewValue)) {
+ return viewValue;
+ }
+
+ if (angular.isString(viewValue)) {
+ var date = parseDateString(viewValue);
+ if (!isNaN(date)) {
+ return dateParser.toTimezone(date, ngModelOptions.getOption('timezone'));
+ }
+ }
+
+ return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined;
+ }
+
+ function validator(modelValue, viewValue) {
+ var value = modelValue || viewValue;
+
+ if (!$attrs.ngRequired && !value) {
+ return true;
+ }
+
+ if (angular.isNumber(value)) {
+ value = new Date(value);
+ }
+
+ if (!value) {
+ return true;
+ }
+
+ if (angular.isDate(value) && !isNaN(value)) {
+ return true;
+ }
+
+ if (angular.isString(value)) {
+ return !isNaN(parseDateString(value));
+ }
+
+ return false;
+ }
+
+ function documentClickBind(event) {
+ if (!$scope.isOpen && $scope.disabled) {
+ return;
+ }
+
+ var popup = $popup[0];
+ var dpContainsTarget = $element[0].contains(event.target);
+ // The popup node may not be an element node
+ // In some browsers (IE) only element nodes have the 'contains' function
+ var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);
+ if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ }
+ }
+
+ function inputKeydownBind(evt) {
+ if (evt.which === 27 && $scope.isOpen) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.$apply(function() {
+ $scope.isOpen = false;
+ });
+ $element[0].focus();
+ } else if (evt.which === 40 && !$scope.isOpen) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.$apply(function() {
+ $scope.isOpen = true;
+ });
+ }
+ }
+
+ function positionPopup() {
+ if ($scope.isOpen) {
+ var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));
+ var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
+ var position = $position.positionElements($element, dpElement, placement, appendToBody);
+ dpElement.css({top: position.top + 'px', left: position.left + 'px'});
+ if (dpElement.hasClass('uib-position-measure')) {
+ dpElement.removeClass('uib-position-measure');
+ }
+ }
+ }
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = angular.isObject(ngModelCtrl.$options) ?
+ ngModelCtrl.$options :
+ {
+ timezone: null
+ };
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ ngModelOptions = ngModelCtrl.$options;
+ }
+
+ return ngModelOptions;
+ }
+
+ $scope.$on('uib:datepicker.mode', function() {
+ $timeout(positionPopup, 0, false);
+ });
+}])
+
+.directive('uibDatepickerPopup', function() {
+ return {
+ require: ['ngModel', 'uibDatepickerPopup'],
+ controller: 'UibDatepickerPopupController',
+ scope: {
+ datepickerOptions: '=?',
+ isOpen: '=?',
+ currentText: '@',
+ clearText: '@',
+ closeText: '@'
+ },
+ link: function(scope, element, attrs, ctrls) {
+ var ngModel = ctrls[0],
+ ctrl = ctrls[1];
+
+ ctrl.init(ngModel);
+ }
+ };
+})
+
+.directive('uibDatepickerPopupWrap', function() {
+ return {
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
+ }
+ };
+});
+
+angular.module('ui.bootstrap.debounce', [])
+/**
+ * A helper, internal service that debounces a function
+ */
+ .factory('$$debounce', ['$timeout', function($timeout) {
+ return function(callback, debounceTime) {
+ var timeoutPromise;
+
+ return function() {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments);
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+
+ timeoutPromise = $timeout(function() {
+ callback.apply(self, args);
+ }, debounceTime);
+ };
+ };
+ }]);
+
+angular.module('ui.bootstrap.multiMap', [])
+/**
+ * A helper, internal data structure that stores all references attached to key
+ */
+ .factory('$$multiMap', function() {
+ return {
+ createNew: function() {
+ var map = {};
+
+ return {
+ entries: function() {
+ return Object.keys(map).map(function(key) {
+ return {
+ key: key,
+ value: map[key]
+ };
+ });
+ },
+ get: function(key) {
+ return map[key];
+ },
+ hasKey: function(key) {
+ return !!map[key];
+ },
+ keys: function() {
+ return Object.keys(map);
+ },
+ put: function(key, value) {
+ if (!map[key]) {
+ map[key] = [];
+ }
+
+ map[key].push(value);
+ },
+ remove: function(key, value) {
+ var values = map[key];
+
+ if (!values) {
+ return;
+ }
+
+ var idx = values.indexOf(value);
+
+ if (idx !== -1) {
+ values.splice(idx, 1);
+ }
+
+ if (!values.length) {
+ delete map[key];
+ }
+ }
+ };
+ }
+ };
+ });
+
+angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.multiMap', 'ui.bootstrap.position'])
+
+.constant('uibDropdownConfig', {
+ appendToOpenClass: 'uib-dropdown-open',
+ openClass: 'open'
+})
+
+.service('uibDropdownService', ['$document', '$rootScope', '$$multiMap', function($document, $rootScope, $$multiMap) {
+ var openScope = null;
+ var openedContainers = $$multiMap.createNew();
+
+ this.isOnlyOpen = function(dropdownScope, appendTo) {
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var openDropdown = openedDropdowns.reduce(function(toClose, dropdown) {
+ if (dropdown.scope === dropdownScope) {
+ return dropdown;
+ }
+
+ return toClose;
+ }, {});
+ if (openDropdown) {
+ return openedDropdowns.length === 1;
+ }
+ }
+
+ return false;
+ };
+
+ this.open = function(dropdownScope, element, appendTo) {
+ if (!openScope) {
+ $document.on('click', closeDropdown);
+ }
+
+ if (openScope && openScope !== dropdownScope) {
+ openScope.isOpen = false;
+ }
+
+ openScope = dropdownScope;
+
+ if (!appendTo) {
+ return;
+ }
+
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var openedScopes = openedDropdowns.map(function(dropdown) {
+ return dropdown.scope;
+ });
+ if (openedScopes.indexOf(dropdownScope) === -1) {
+ openedContainers.put(appendTo, {
+ scope: dropdownScope
+ });
+ }
+ } else {
+ openedContainers.put(appendTo, {
+ scope: dropdownScope
+ });
+ }
+ };
+
+ this.close = function(dropdownScope, element, appendTo) {
+ if (openScope === dropdownScope) {
+ $document.off('click', closeDropdown);
+ $document.off('keydown', this.keybindFilter);
+ openScope = null;
+ }
+
+ if (!appendTo) {
+ return;
+ }
+
+ var openedDropdowns = openedContainers.get(appendTo);
+ if (openedDropdowns) {
+ var dropdownToClose = openedDropdowns.reduce(function(toClose, dropdown) {
+ if (dropdown.scope === dropdownScope) {
+ return dropdown;
+ }
+
+ return toClose;
+ }, {});
+ if (dropdownToClose) {
+ openedContainers.remove(appendTo, dropdownToClose);
+ }
+ }
+ };
+
+ var closeDropdown = function(evt) {
+ // This method may still be called during the same mouse event that
+ // unbound this event handler. So check openScope before proceeding.
+ if (!openScope || !openScope.isOpen) { return; }
+
+ if (evt && openScope.getAutoClose() === 'disabled') { return; }
+
+ if (evt && evt.which === 3) { return; }
+
+ var toggleElement = openScope.getToggleElement();
+ if (evt && toggleElement && toggleElement[0].contains(evt.target)) {
+ return;
+ }
+
+ var dropdownElement = openScope.getDropdownElement();
+ if (evt && openScope.getAutoClose() === 'outsideClick' &&
+ dropdownElement && dropdownElement[0].contains(evt.target)) {
+ return;
+ }
+
+ openScope.focusToggleElement();
+ openScope.isOpen = false;
+
+ if (!$rootScope.$$phase) {
+ openScope.$apply();
+ }
+ };
+
+ this.keybindFilter = function(evt) {
+ if (!openScope) {
+ // see this.close as ESC could have been pressed which kills the scope so we can not proceed
+ return;
+ }
+
+ var dropdownElement = openScope.getDropdownElement();
+ var toggleElement = openScope.getToggleElement();
+ var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
+ var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);
+ if (evt.which === 27) {
+ evt.stopPropagation();
+ openScope.focusToggleElement();
+ closeDropdown();
+ } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ openScope.focusDropdownEntry(evt.which);
+ }
+ };
+}])
+
+.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {
+ var self = this,
+ scope = $scope.$new(), // create a child scope so we are not polluting original one
+ templateScope,
+ appendToOpenClass = dropdownConfig.appendToOpenClass,
+ openClass = dropdownConfig.openClass,
+ getIsOpen,
+ setIsOpen = angular.noop,
+ toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
+ keynavEnabled = false,
+ selectedOption = null,
+ body = $document.find('body');
+
+ $element.addClass('dropdown');
+
+ this.init = function() {
+ if ($attrs.isOpen) {
+ getIsOpen = $parse($attrs.isOpen);
+ setIsOpen = getIsOpen.assign;
+
+ $scope.$watch(getIsOpen, function(value) {
+ scope.isOpen = !!value;
+ });
+ }
+
+ keynavEnabled = angular.isDefined($attrs.keyboardNav);
+ };
+
+ this.toggle = function(open) {
+ scope.isOpen = arguments.length ? !!open : !scope.isOpen;
+ if (angular.isFunction(setIsOpen)) {
+ setIsOpen(scope, scope.isOpen);
+ }
+
+ return scope.isOpen;
+ };
+
+ // Allow other directives to watch status
+ this.isOpen = function() {
+ return scope.isOpen;
+ };
+
+ scope.getToggleElement = function() {
+ return self.toggleElement;
+ };
+
+ scope.getAutoClose = function() {
+ return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'
+ };
+
+ scope.getElement = function() {
+ return $element;
+ };
+
+ scope.isKeynavEnabled = function() {
+ return keynavEnabled;
+ };
+
+ scope.focusDropdownEntry = function(keyCode) {
+ var elems = self.dropdownMenu ? //If append to body is used.
+ angular.element(self.dropdownMenu).find('a') :
+ $element.find('ul').eq(0).find('a');
+
+ switch (keyCode) {
+ case 40: {
+ if (!angular.isNumber(self.selectedOption)) {
+ self.selectedOption = 0;
+ } else {
+ self.selectedOption = self.selectedOption === elems.length - 1 ?
+ self.selectedOption :
+ self.selectedOption + 1;
+ }
+ break;
+ }
+ case 38: {
+ if (!angular.isNumber(self.selectedOption)) {
+ self.selectedOption = elems.length - 1;
+ } else {
+ self.selectedOption = self.selectedOption === 0 ?
+ 0 : self.selectedOption - 1;
+ }
+ break;
+ }
+ }
+ elems[self.selectedOption].focus();
+ };
+
+ scope.getDropdownElement = function() {
+ return self.dropdownMenu;
+ };
+
+ scope.focusToggleElement = function() {
+ if (self.toggleElement) {
+ self.toggleElement[0].focus();
+ }
+ };
+
+ function removeDropdownMenu() {
+ $element.append(self.dropdownMenu);
+ }
+
+ scope.$watch('isOpen', function(isOpen, wasOpen) {
+ var appendTo = null,
+ appendToBody = false;
+
+ if (angular.isDefined($attrs.dropdownAppendTo)) {
+ var appendToEl = $parse($attrs.dropdownAppendTo)(scope);
+ if (appendToEl) {
+ appendTo = angular.element(appendToEl);
+ }
+ }
+
+ if (angular.isDefined($attrs.dropdownAppendToBody)) {
+ var appendToBodyValue = $parse($attrs.dropdownAppendToBody)(scope);
+ if (appendToBodyValue !== false) {
+ appendToBody = true;
+ }
+ }
+
+ if (appendToBody && !appendTo) {
+ appendTo = body;
+ }
+
+ if (appendTo && self.dropdownMenu) {
+ if (isOpen) {
+ appendTo.append(self.dropdownMenu);
+ $element.on('$destroy', removeDropdownMenu);
+ } else {
+ $element.off('$destroy', removeDropdownMenu);
+ removeDropdownMenu();
+ }
+ }
+
+ if (appendTo && self.dropdownMenu) {
+ var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
+ css,
+ rightalign,
+ scrollbarPadding,
+ scrollbarWidth = 0;
+
+ css = {
+ top: pos.top + 'px',
+ display: isOpen ? 'block' : 'none'
+ };
+
+ rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
+ if (!rightalign) {
+ css.left = pos.left + 'px';
+ css.right = 'auto';
+ } else {
+ css.left = 'auto';
+ scrollbarPadding = $position.scrollbarPadding(appendTo);
+
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ scrollbarWidth = scrollbarPadding.scrollbarWidth;
+ }
+
+ css.right = window.innerWidth - scrollbarWidth -
+ (pos.left + $element.prop('offsetWidth')) + 'px';
+ }
+
+ // Need to adjust our positioning to be relative to the appendTo container
+ // if it's not the body element
+ if (!appendToBody) {
+ var appendOffset = $position.offset(appendTo);
+
+ css.top = pos.top - appendOffset.top + 'px';
+
+ if (!rightalign) {
+ css.left = pos.left - appendOffset.left + 'px';
+ } else {
+ css.right = window.innerWidth -
+ (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';
+ }
+ }
+
+ self.dropdownMenu.css(css);
+ }
+
+ var openContainer = appendTo ? appendTo : $element;
+ var dropdownOpenClass = appendTo ? appendToOpenClass : openClass;
+ var hasOpenClass = openContainer.hasClass(dropdownOpenClass);
+ var isOnlyOpen = uibDropdownService.isOnlyOpen($scope, appendTo);
+
+ if (hasOpenClass === !isOpen) {
+ var toggleClass;
+ if (appendTo) {
+ toggleClass = !isOnlyOpen ? 'addClass' : 'removeClass';
+ } else {
+ toggleClass = isOpen ? 'addClass' : 'removeClass';
+ }
+ $animate[toggleClass](openContainer, dropdownOpenClass).then(function() {
+ if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
+ toggleInvoker($scope, { open: !!isOpen });
+ }
+ });
+ }
+
+ if (isOpen) {
+ if (self.dropdownMenuTemplateUrl) {
+ $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {
+ templateScope = scope.$new();
+ $compile(tplContent.trim())(templateScope, function(dropdownElement) {
+ var newEl = dropdownElement;
+ self.dropdownMenu.replaceWith(newEl);
+ self.dropdownMenu = newEl;
+ $document.on('keydown', uibDropdownService.keybindFilter);
+ });
+ });
+ } else {
+ $document.on('keydown', uibDropdownService.keybindFilter);
+ }
+
+ scope.focusToggleElement();
+ uibDropdownService.open(scope, $element, appendTo);
+ } else {
+ uibDropdownService.close(scope, $element, appendTo);
+ if (self.dropdownMenuTemplateUrl) {
+ if (templateScope) {
+ templateScope.$destroy();
+ }
+ var newEl = angular.element('<ul class="dropdown-menu"></ul>');
+ self.dropdownMenu.replaceWith(newEl);
+ self.dropdownMenu = newEl;
+ }
+
+ self.selectedOption = null;
+ }
+
+ if (angular.isFunction(setIsOpen)) {
+ setIsOpen($scope, isOpen);
+ }
+ });
+}])
+
+.directive('uibDropdown', function() {
+ return {
+ controller: 'UibDropdownController',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ dropdownCtrl.init();
+ }
+ };
+})
+
+.directive('uibDropdownMenu', function() {
+ return {
+ restrict: 'A',
+ require: '?^uibDropdown',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {
+ return;
+ }
+
+ element.addClass('dropdown-menu');
+
+ var tplUrl = attrs.templateUrl;
+ if (tplUrl) {
+ dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
+ }
+
+ if (!dropdownCtrl.dropdownMenu) {
+ dropdownCtrl.dropdownMenu = element;
+ }
+ }
+ };
+})
+
+.directive('uibDropdownToggle', function() {
+ return {
+ require: '?^uibDropdown',
+ link: function(scope, element, attrs, dropdownCtrl) {
+ if (!dropdownCtrl) {
+ return;
+ }
+
+ element.addClass('dropdown-toggle');
+
+ dropdownCtrl.toggleElement = element;
+
+ var toggleDropdown = function(event) {
+ event.preventDefault();
+
+ if (!element.hasClass('disabled') && !attrs.disabled) {
+ scope.$apply(function() {
+ dropdownCtrl.toggle();
+ });
+ }
+ };
+
+ element.on('click', toggleDropdown);
+
+ // WAI-ARIA
+ element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
+ scope.$watch(dropdownCtrl.isOpen, function(isOpen) {
+ element.attr('aria-expanded', !!isOpen);
+ });
+
+ scope.$on('$destroy', function() {
+ element.off('click', toggleDropdown);
+ });
+ }
+ };
+});
+
+angular.module('ui.bootstrap.stackedMap', [])
+/**
+ * A helper, internal data structure that acts as a map but also allows getting / removing
+ * elements in the LIFO order
+ */
+ .factory('$$stackedMap', function() {
+ return {
+ createNew: function() {
+ var stack = [];
+
+ return {
+ add: function(key, value) {
+ stack.push({
+ key: key,
+ value: value
+ });
+ },
+ get: function(key) {
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ return stack[i];
+ }
+ }
+ },
+ keys: function() {
+ var keys = [];
+ for (var i = 0; i < stack.length; i++) {
+ keys.push(stack[i].key);
+ }
+ return keys;
+ },
+ top: function() {
+ return stack[stack.length - 1];
+ },
+ remove: function(key) {
+ var idx = -1;
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ idx = i;
+ break;
+ }
+ }
+ return stack.splice(idx, 1)[0];
+ },
+ removeTop: function() {
+ return stack.pop();
+ },
+ length: function() {
+ return stack.length;
+ }
+ };
+ }
+ };
+ });
+angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.stackedMap', 'ui.bootstrap.position'])
+/**
+ * Pluggable resolve mechanism for the modal resolve resolution
+ * Supports UI Router's $resolve service
+ */
+ .provider('$uibResolve', function() {
+ var resolve = this;
+ this.resolver = null;
+
+ this.setResolver = function(resolver) {
+ this.resolver = resolver;
+ };
+
+ this.$get = ['$injector', '$q', function($injector, $q) {
+ var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
+ return {
+ resolve: function(invocables, locals, parent, self) {
+ if (resolver) {
+ return resolver.resolve(invocables, locals, parent, self);
+ }
+
+ var promises = [];
+
+ angular.forEach(invocables, function(value) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promises.push($q.resolve($injector.invoke(value)));
+ } else if (angular.isString(value)) {
+ promises.push($q.resolve($injector.get(value)));
+ } else {
+ promises.push($q.resolve(value));
+ }
+ });
+
+ return $q.all(promises).then(function(resolves) {
+ var resolveObj = {};
+ var resolveIter = 0;
+ angular.forEach(invocables, function(value, key) {
+ resolveObj[key] = resolves[resolveIter++];
+ });
+
+ return resolveObj;
+ });
+ }
+ };
+ }];
+ })
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+ .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
+ function($animate, $injector, $modalStack) {
+ return {
+ restrict: 'A',
+ compile: function(tElement, tAttrs) {
+ tElement.addClass(tAttrs.backdropClass);
+ return linkFn;
+ }
+ };
+
+ function linkFn(scope, element, attrs) {
+ if (attrs.modalInClass) {
+ $animate.addClass(element, attrs.modalInClass);
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ if (scope.modalOptions.animation) {
+ $animate.removeClass(element, attrs.modalInClass).then(done);
+ } else {
+ done();
+ }
+ });
+ }
+ }
+ }])
+
+ .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',
+ function($modalStack, $q, $animateCss, $document) {
+ return {
+ scope: {
+ index: '@'
+ },
+ restrict: 'A',
+ transclude: true,
+ templateUrl: function(tElement, tAttrs) {
+ return tAttrs.templateUrl || 'uib/template/modal/window.html';
+ },
+ link: function(scope, element, attrs) {
+ element.addClass(attrs.windowTopClass || '');
+ scope.size = attrs.size;
+
+ scope.close = function(evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop &&
+ modal.value.backdrop !== 'static' &&
+ evt.target === evt.currentTarget) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+
+ // moved from template to fix issue #2280
+ element.on('click', scope.close);
+
+ // This property is only added to the scope for the purpose of detecting when this directive is rendered.
+ // We can detect that by using this property in the template associated with this directive and then use
+ // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
+ scope.$isRendered = true;
+
+ // Deferred object that will be resolved when this modal is rendered.
+ var modalRenderDeferObj = $q.defer();
+ // Resolve render promise post-digest
+ scope.$$postDigest(function() {
+ modalRenderDeferObj.resolve();
+ });
+
+ modalRenderDeferObj.promise.then(function() {
+ var animationPromise = null;
+
+ if (attrs.modalInClass) {
+ animationPromise = $animateCss(element, {
+ addClass: attrs.modalInClass
+ }).start();
+
+ scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
+ var done = setIsAsync();
+ $animateCss(element, {
+ removeClass: attrs.modalInClass
+ }).start().then(done);
+ });
+ }
+
+
+ $q.when(animationPromise).then(function() {
+ // Notify {@link $modalStack} that modal is rendered.
+ var modal = $modalStack.getTop();
+ if (modal) {
+ $modalStack.modalRendered(modal.key);
+ }
+
+ /**
+ * If something within the freshly-opened modal already has focus (perhaps via a
+ * directive that causes focus) then there's no need to try to focus anything.
+ */
+ if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
+ var inputWithAutofocus = element[0].querySelector('[autofocus]');
+ /**
+ * Auto-focusing of a freshly-opened modal element causes any child elements
+ * with the autofocus attribute to lose focus. This is an issue on touch
+ * based devices which will show and then hide the onscreen keyboard.
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
+ * the modal element if the modal does not contain an autofocus element.
+ */
+ if (inputWithAutofocus) {
+ inputWithAutofocus.focus();
+ } else {
+ element[0].focus();
+ }
+ }
+ });
+ });
+ }
+ };
+ }])
+
+ .directive('uibModalAnimationClass', function() {
+ return {
+ compile: function(tElement, tAttrs) {
+ if (tAttrs.modalAnimation) {
+ tElement.addClass(tAttrs.uibModalAnimationClass);
+ }
+ }
+ };
+ })
+
+ .directive('uibModalTransclude', ['$animate', function($animate) {
+ return {
+ link: function(scope, element, attrs, controller, transclude) {
+ transclude(scope.$parent, function(clone) {
+ element.empty();
+ $animate.enter(clone, element);
+ });
+ }
+ };
+ }])
+
+ .factory('$uibModalStack', ['$animate', '$animateCss', '$document',
+ '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
+ function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {
+ var OPENED_MODAL_CLASS = 'modal-open';
+
+ var backdropDomEl, backdropScope;
+ var openedWindows = $$stackedMap.createNew();
+ var openedClasses = $$multiMap.createNew();
+ var $modalStack = {
+ NOW_CLOSING_EVENT: 'modal.stack.now-closing'
+ };
+ var topModalIndex = 0;
+ var previousTopOpenedModal = null;
+ var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';
+
+ //Modal focus behavior
+ var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
+ 'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' +
+ 'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]';
+ var scrollbarPadding;
+ var SNAKE_CASE_REGEXP = /[A-Z]/g;
+
+ // TODO: extract into common dependency with tooltip
+ function snake_case(name) {
+ var separator = '-';
+ return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ function isVisible(element) {
+ return !!(element.offsetWidth ||
+ element.offsetHeight ||
+ element.getClientRects().length);
+ }
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+
+ // If any backdrop exist, ensure that it's index is always
+ // right below the top modal
+ if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
+ topBackdropIndex = topModalIndex;
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex) {
+ if (backdropScope) {
+ backdropScope.index = newBackdropIndex;
+ }
+ });
+
+ function removeModalWindow(modalInstance, elementToReceiveFocus) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ var appendToElement = modalWindow.appendTo;
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+ previousTopOpenedModal = openedWindows.top();
+ if (previousTopOpenedModal) {
+ topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
+ }
+
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
+ var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
+ openedClasses.remove(modalBodyClass, modalInstance);
+ var areAnyOpen = openedClasses.hasKey(modalBodyClass);
+ appendToElement.toggleClass(modalBodyClass, areAnyOpen);
+ if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ if (scrollbarPadding.originalRight) {
+ appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});
+ } else {
+ appendToElement.css({paddingRight: ''});
+ }
+ scrollbarPadding = null;
+ }
+ toggleTopWindowClass(true);
+ }, modalWindow.closedDeferred);
+ checkRemoveBackdrop();
+
+ //move focus to specified element if available, or else to body
+ if (elementToReceiveFocus && elementToReceiveFocus.focus) {
+ elementToReceiveFocus.focus();
+ } else if (appendToElement.focus) {
+ appendToElement.focus();
+ }
+ }
+
+ // Add or remove "windowTopClass" from the top window in the stack
+ function toggleTopWindowClass(toggleSwitch) {
+ var modalWindow;
+
+ if (openedWindows.length() > 0) {
+ modalWindow = openedWindows.top().value;
+ modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);
+ }
+ }
+
+ function checkRemoveBackdrop() {
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() === -1) {
+ var backdropScopeRef = backdropScope;
+ removeAfterAnimate(backdropDomEl, backdropScope, function() {
+ backdropScopeRef = null;
+ });
+ backdropDomEl = undefined;
+ backdropScope = undefined;
+ }
+ }
+
+ function removeAfterAnimate(domEl, scope, done, closedDeferred) {
+ var asyncDeferred;
+ var asyncPromise = null;
+ var setIsAsync = function() {
+ if (!asyncDeferred) {
+ asyncDeferred = $q.defer();
+ asyncPromise = asyncDeferred.promise;
+ }
+
+ return function asyncDone() {
+ asyncDeferred.resolve();
+ };
+ };
+ scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);
+
+ // Note that it's intentional that asyncPromise might be null.
+ // That's when setIsAsync has not been called during the
+ // NOW_CLOSING_EVENT broadcast.
+ return $q.when(asyncPromise).then(afterAnimating);
+
+ function afterAnimating() {
+ if (afterAnimating.done) {
+ return;
+ }
+ afterAnimating.done = true;
+
+ $animate.leave(domEl).then(function() {
+ if (done) {
+ done();
+ }
+
+ domEl.remove();
+ if (closedDeferred) {
+ closedDeferred.resolve();
+ }
+ });
+
+ scope.$destroy();
+ }
+ }
+
+ $document.on('keydown', keydownListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keydown', keydownListener);
+ });
+
+ function keydownListener(evt) {
+ if (evt.isDefaultPrevented()) {
+ return evt;
+ }
+
+ var modal = openedWindows.top();
+ if (modal) {
+ switch (evt.which) {
+ case 27: {
+ if (modal.value.keyboard) {
+ evt.preventDefault();
+ $rootScope.$apply(function() {
+ $modalStack.dismiss(modal.key, 'escape key press');
+ });
+ }
+ break;
+ }
+ case 9: {
+ var list = $modalStack.loadFocusElementList(modal);
+ var focusChanged = false;
+ if (evt.shiftKey) {
+ if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {
+ focusChanged = $modalStack.focusLastFocusableElement(list);
+ }
+ } else {
+ if ($modalStack.isFocusInLastItem(evt, list)) {
+ focusChanged = $modalStack.focusFirstFocusableElement(list);
+ }
+ }
+
+ if (focusChanged) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ $modalStack.open = function(modalInstance, modal) {
+ var modalOpener = $document[0].activeElement,
+ modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
+
+ toggleTopWindowClass(false);
+
+ // Store the current top first, to determine what index we ought to use
+ // for the current top modal
+ previousTopOpenedModal = openedWindows.top();
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ renderDeferred: modal.renderDeferred,
+ closedDeferred: modal.closedDeferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard,
+ openedClass: modal.openedClass,
+ windowTopClass: modal.windowTopClass,
+ animation: modal.animation,
+ appendTo: modal.appendTo
+ });
+
+ openedClasses.put(modalBodyClass, modalInstance);
+
+ var appendToElement = modal.appendTo,
+ currBackdropIndex = backdropIndex();
+
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
+ backdropScope = $rootScope.$new(true);
+ backdropScope.modalOptions = modal;
+ backdropScope.index = currBackdropIndex;
+ backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
+ backdropDomEl.attr({
+ 'class': 'modal-backdrop',
+ 'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}',
+ 'uib-modal-animation-class': 'fade',
+ 'modal-in-class': 'in'
+ });
+ if (modal.backdropClass) {
+ backdropDomEl.addClass(modal.backdropClass);
+ }
+
+ if (modal.animation) {
+ backdropDomEl.attr('modal-animation', 'true');
+ }
+ $compile(backdropDomEl)(backdropScope);
+ $animate.enter(backdropDomEl, appendToElement);
+ if ($uibPosition.isScrollable(appendToElement)) {
+ scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
+ if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
+ appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
+ }
+ }
+ }
+
+ var content;
+ if (modal.component) {
+ content = document.createElement(snake_case(modal.component.name));
+ content = angular.element(content);
+ content.attr({
+ resolve: '$resolve',
+ 'modal-instance': '$uibModalInstance',
+ close: '$close($value)',
+ dismiss: '$dismiss($value)'
+ });
+ } else {
+ content = modal.content;
+ }
+
+ // Set the top modal index based on the index of the previous top modal
+ topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
+ var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
+ angularDomEl.attr({
+ 'class': 'modal',
+ 'template-url': modal.windowTemplateUrl,
+ 'window-top-class': modal.windowTopClass,
+ 'role': 'dialog',
+ 'aria-labelledby': modal.ariaLabelledBy,
+ 'aria-describedby': modal.ariaDescribedBy,
+ 'size': modal.size,
+ 'index': topModalIndex,
+ 'animate': 'animate',
+ 'ng-style': '{\'z-index\': 1050 + $$topModalIndex*10, display: \'block\'}',
+ 'tabindex': -1,
+ 'uib-modal-animation-class': 'fade',
+ 'modal-in-class': 'in'
+ }).append(content);
+ if (modal.windowClass) {
+ angularDomEl.addClass(modal.windowClass);
+ }
+
+ if (modal.animation) {
+ angularDomEl.attr('modal-animation', 'true');
+ }
+
+ appendToElement.addClass(modalBodyClass);
+ if (modal.scope) {
+ // we need to explicitly add the modal index to the modal scope
+ // because it is needed by ngStyle to compute the zIndex property.
+ modal.scope.$$topModalIndex = topModalIndex;
+ }
+ $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
+
+ openedWindows.top().value.modalDomEl = angularDomEl;
+ openedWindows.top().value.modalOpener = modalOpener;
+
+ applyAriaHidden(angularDomEl);
+
+ function applyAriaHidden(el) {
+ if (!el || el[0].tagName === 'BODY') {
+ return;
+ }
+
+ getSiblings(el).forEach(function(sibling) {
+ var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
+ ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);
+
+ if (!ariaHiddenCount) {
+ ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
+ }
+
+ sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
+ sibling.setAttribute('aria-hidden', 'true');
+ });
+
+ return applyAriaHidden(el.parent());
+
+ function getSiblings(el) {
+ var children = el.parent() ? el.parent().children() : [];
+
+ return Array.prototype.filter.call(children, function(child) {
+ return child !== el[0];
+ });
+ }
+ }
+ };
+
+ function broadcastClosing(modalWindow, resultOrReason, closing) {
+ return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
+ }
+
+ function unhideBackgroundElements() {
+ Array.prototype.forEach.call(
+ document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
+ function(hiddenEl) {
+ var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
+ newHiddenCount = ariaHiddenCount - 1;
+ hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);
+
+ if (!newHiddenCount) {
+ hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
+ hiddenEl.removeAttribute('aria-hidden');
+ }
+ }
+ );
+ }
+
+ $modalStack.close = function(modalInstance, result) {
+ var modalWindow = openedWindows.get(modalInstance);
+ unhideBackgroundElements();
+ if (modalWindow && broadcastClosing(modalWindow, result, true)) {
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.resolve(result);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+
+ return !modalWindow;
+ };
+
+ $modalStack.dismiss = function(modalInstance, reason) {
+ var modalWindow = openedWindows.get(modalInstance);
+ unhideBackgroundElements();
+ if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
+ modalWindow.value.modalScope.$$uibDestructionScheduled = true;
+ modalWindow.value.deferred.reject(reason);
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
+ return true;
+ }
+ return !modalWindow;
+ };
+
+ $modalStack.dismissAll = function(reason) {
+ var topModal = this.getTop();
+ while (topModal && this.dismiss(topModal.key, reason)) {
+ topModal = this.getTop();
+ }
+ };
+
+ $modalStack.getTop = function() {
+ return openedWindows.top();
+ };
+
+ $modalStack.modalRendered = function(modalInstance) {
+ var modalWindow = openedWindows.get(modalInstance);
+ if (modalWindow) {
+ modalWindow.value.renderDeferred.resolve();
+ }
+ };
+
+ $modalStack.focusFirstFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[0].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.focusLastFocusableElement = function(list) {
+ if (list.length > 0) {
+ list[list.length - 1].focus();
+ return true;
+ }
+ return false;
+ };
+
+ $modalStack.isModalFocused = function(evt, modalWindow) {
+ if (evt && modalWindow) {
+ var modalDomEl = modalWindow.value.modalDomEl;
+ if (modalDomEl && modalDomEl.length) {
+ return (evt.target || evt.srcElement) === modalDomEl[0];
+ }
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInFirstItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[0];
+ }
+ return false;
+ };
+
+ $modalStack.isFocusInLastItem = function(evt, list) {
+ if (list.length > 0) {
+ return (evt.target || evt.srcElement) === list[list.length - 1];
+ }
+ return false;
+ };
+
+ $modalStack.loadFocusElementList = function(modalWindow) {
+ if (modalWindow) {
+ var modalDomE1 = modalWindow.value.modalDomEl;
+ if (modalDomE1 && modalDomE1.length) {
+ var elements = modalDomE1[0].querySelectorAll(tabbableSelector);
+ return elements ?
+ Array.prototype.filter.call(elements, function(element) {
+ return isVisible(element);
+ }) : elements;
+ }
+ }
+ };
+
+ return $modalStack;
+ }])
+
+ .provider('$uibModal', function() {
+ var $modalProvider = {
+ options: {
+ animation: true,
+ backdrop: true, //can also be false or 'static'
+ keyboard: true
+ },
+ $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
+ function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $templateRequest(angular.isFunction(options.templateUrl) ?
+ options.templateUrl() : options.templateUrl);
+ }
+
+ var promiseChain = null;
+ $modal.getPromiseChain = function() {
+ return promiseChain;
+ };
+
+ $modal.open = function(modalOptions) {
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+ var modalClosedDeferred = $q.defer();
+ var modalRenderDeferred = $q.defer();
+
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ closed: modalClosedDeferred.promise,
+ rendered: modalRenderDeferred.promise,
+ close: function (result) {
+ return $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ return $modalStack.dismiss(modalInstance, reason);
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+ modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
+
+ if (!modalOptions.appendTo.length) {
+ throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
+ }
+
+ //verify options
+ if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of component or template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise;
+ if (modalOptions.component) {
+ templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null));
+ } else {
+ templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
+ }
+
+ function resolveWithTemplate() {
+ return templateAndResolvePromise;
+ }
+
+ // Wait for the resolution of the existing promise chain.
+ // Then switch to our own combined promise dependency (regardless of how the previous modal fared).
+ // Then add to $modalStack and resolve opened.
+ // Finally clean up the chain variable if no subsequent modal has overwritten it.
+ var samePromise;
+ samePromise = promiseChain = $q.all([promiseChain])
+ .then(resolveWithTemplate, resolveWithTemplate)
+ .then(function resolveSuccess(tplAndVars) {
+ var providedScope = modalOptions.scope || $rootScope;
+
+ var modalScope = providedScope.$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ modalScope.$on('$destroy', function() {
+ if (!modalScope.$$uibDestructionScheduled) {
+ modalScope.$dismiss('$uibUnscheduledDestruction');
+ }
+ });
+
+ var modal = {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ renderDeferred: modalRenderDeferred,
+ closedDeferred: modalClosedDeferred,
+ animation: modalOptions.animation,
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ backdropClass: modalOptions.backdropClass,
+ windowTopClass: modalOptions.windowTopClass,
+ windowClass: modalOptions.windowClass,
+ windowTemplateUrl: modalOptions.windowTemplateUrl,
+ ariaLabelledBy: modalOptions.ariaLabelledBy,
+ ariaDescribedBy: modalOptions.ariaDescribedBy,
+ size: modalOptions.size,
+ openedClass: modalOptions.openedClass,
+ appendTo: modalOptions.appendTo
+ };
+
+ var component = {};
+ var ctrlInstance, ctrlInstantiate, ctrlLocals = {};
+
+ if (modalOptions.component) {
+ constructLocals(component, false, true, false);
+ component.name = modalOptions.component;
+ modal.component = component;
+ } else if (modalOptions.controller) {
+ constructLocals(ctrlLocals, true, false, true);
+
+ // the third param will make the controller instantiate later,private api
+ // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
+ ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
+ if (modalOptions.controllerAs && modalOptions.bindToController) {
+ ctrlInstance = ctrlInstantiate.instance;
+ ctrlInstance.$close = modalScope.$close;
+ ctrlInstance.$dismiss = modalScope.$dismiss;
+ angular.extend(ctrlInstance, {
+ $resolve: ctrlLocals.$scope.$resolve
+ }, providedScope);
+ }
+
+ ctrlInstance = ctrlInstantiate();
+
+ if (angular.isFunction(ctrlInstance.$onInit)) {
+ ctrlInstance.$onInit();
+ }
+ }
+
+ if (!modalOptions.component) {
+ modal.content = tplAndVars[0];
+ }
+
+ $modalStack.open(modalInstance, modal);
+ modalOpenedDeferred.resolve(true);
+
+ function constructLocals(obj, template, instanceOnScope, injectable) {
+ obj.$scope = modalScope;
+ obj.$scope.$resolve = {};
+ if (instanceOnScope) {
+ obj.$scope.$uibModalInstance = modalInstance;
+ } else {
+ obj.$uibModalInstance = modalInstance;
+ }
+
+ var resolves = template ? tplAndVars[1] : tplAndVars;
+ angular.forEach(resolves, function(value, key) {
+ if (injectable) {
+ obj[key] = value;
+ }
+
+ obj.$scope.$resolve[key] = value;
+ });
+ }
+ }, function resolveError(reason) {
+ modalOpenedDeferred.reject(reason);
+ modalResultDeferred.reject(reason);
+ })['finally'](function() {
+ if (promiseChain === samePromise) {
+ promiseChain = null;
+ }
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }
+ ]
+ };
+
+ return $modalProvider;
+ });
+
+angular.module('ui.bootstrap.paging', [])
+/**
+ * Helper internal service for generating common controller code between the
+ * pager and pagination components
+ */
+.factory('uibPaging', ['$parse', function($parse) {
+ return {
+ create: function(ctrl, $scope, $attrs) {
+ ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
+ ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl
+ ctrl._watchers = [];
+
+ ctrl.init = function(ngModelCtrl, config) {
+ ctrl.ngModelCtrl = ngModelCtrl;
+ ctrl.config = config;
+
+ ngModelCtrl.$render = function() {
+ ctrl.render();
+ };
+
+ if ($attrs.itemsPerPage) {
+ ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function(value) {
+ ctrl.itemsPerPage = parseInt(value, 10);
+ $scope.totalPages = ctrl.calculateTotalPages();
+ ctrl.updatePage();
+ }));
+ } else {
+ ctrl.itemsPerPage = config.itemsPerPage;
+ }
+
+ $scope.$watch('totalItems', function(newTotal, oldTotal) {
+ if (angular.isDefined(newTotal) || newTotal !== oldTotal) {
+ $scope.totalPages = ctrl.calculateTotalPages();
+ ctrl.updatePage();
+ }
+ });
+ };
+
+ ctrl.calculateTotalPages = function() {
+ var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);
+ return Math.max(totalPages || 0, 1);
+ };
+
+ ctrl.render = function() {
+ $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;
+ };
+
+ $scope.selectPage = function(page, evt) {
+ if (evt) {
+ evt.preventDefault();
+ }
+
+ var clickAllowed = !$scope.ngDisabled || !evt;
+ if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {
+ if (evt && evt.target) {
+ evt.target.blur();
+ }
+ ctrl.ngModelCtrl.$setViewValue(page);
+ ctrl.ngModelCtrl.$render();
+ }
+ };
+
+ $scope.getText = function(key) {
+ return $scope[key + 'Text'] || ctrl.config[key + 'Text'];
+ };
+
+ $scope.noPrevious = function() {
+ return $scope.page === 1;
+ };
+
+ $scope.noNext = function() {
+ return $scope.page === $scope.totalPages;
+ };
+
+ ctrl.updatePage = function() {
+ ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable
+
+ if ($scope.page > $scope.totalPages) {
+ $scope.selectPage($scope.totalPages);
+ } else {
+ ctrl.ngModelCtrl.$render();
+ }
+ };
+
+ $scope.$on('$destroy', function() {
+ while (ctrl._watchers.length) {
+ ctrl._watchers.shift()();
+ }
+ });
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
+
+.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) {
+ $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;
+
+ uibPaging.create(this, $scope, $attrs);
+}])
+
+.constant('uibPagerConfig', {
+ itemsPerPage: 10,
+ previousText: '« Previous',
+ nextText: 'Next »',
+ align: true
+})
+
+.directive('uibPager', ['uibPagerConfig', function(uibPagerConfig) {
+ return {
+ scope: {
+ totalItems: '=',
+ previousText: '@',
+ nextText: '@',
+ ngDisabled: '='
+ },
+ require: ['uibPager', '?ngModel'],
+ restrict: 'A',
+ controller: 'UibPagerController',
+ controllerAs: 'pager',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/pager/pager.html';
+ },
+ link: function(scope, element, attrs, ctrls) {
+ element.addClass('pager');
+ var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (!ngModelCtrl) {
+ return; // do nothing if no ng-model
+ }
+
+ paginationCtrl.init(ngModelCtrl, uibPagerConfig);
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
+.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
+ var ctrl = this;
+ // Setup configuration parameters
+ var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,
+ rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,
+ forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,
+ boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,
+ pageLabel = angular.isDefined($attrs.pageLabel) ? function(idx) { return $scope.$parent.$eval($attrs.pageLabel, {$page: idx}); } : angular.identity;
+ $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;
+ $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;
+ $attrs.$set('role', 'menu');
+
+ uibPaging.create(this, $scope, $attrs);
+
+ if ($attrs.maxSize) {
+ ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function(value) {
+ maxSize = parseInt(value, 10);
+ ctrl.render();
+ }));
+ }
+
+ // Create page object used in template
+ function makePage(number, text, isActive) {
+ return {
+ number: number,
+ text: text,
+ active: isActive
+ };
+ }
+
+ function getPages(currentPage, totalPages) {
+ var pages = [];
+
+ // Default page limits
+ var startPage = 1, endPage = totalPages;
+ var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;
+
+ // recompute if maxSize
+ if (isMaxSized) {
+ if (rotate) {
+ // Current page is displayed in the middle of the visible ones
+ startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
+ endPage = startPage + maxSize - 1;
+
+ // Adjust if limit is exceeded
+ if (endPage > totalPages) {
+ endPage = totalPages;
+ startPage = endPage - maxSize + 1;
+ }
+ } else {
+ // Visible pages are paginated with maxSize
+ startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;
+
+ // Adjust last page if limit is exceeded
+ endPage = Math.min(startPage + maxSize - 1, totalPages);
+ }
+ }
+
+ // Add page number links
+ for (var number = startPage; number <= endPage; number++) {
+ var page = makePage(number, pageLabel(number), number === currentPage);
+ pages.push(page);
+ }
+
+ // Add links to move between page sets
+ if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {
+ if (startPage > 1) {
+ if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning
+ var previousPageSet = makePage(startPage - 1, '...', false);
+ pages.unshift(previousPageSet);
+ }
+ if (boundaryLinkNumbers) {
+ if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential
+ var secondPageLink = makePage(2, '2', false);
+ pages.unshift(secondPageLink);
+ }
+ //add the first page
+ var firstPageLink = makePage(1, '1', false);
+ pages.unshift(firstPageLink);
+ }
+ }
+
+ if (endPage < totalPages) {
+ if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end
+ var nextPageSet = makePage(endPage + 1, '...', false);
+ pages.push(nextPageSet);
+ }
+ if (boundaryLinkNumbers) {
+ if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential
+ var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);
+ pages.push(secondToLastPageLink);
+ }
+ //add the last page
+ var lastPageLink = makePage(totalPages, totalPages, false);
+ pages.push(lastPageLink);
+ }
+ }
+ }
+ return pages;
+ }
+
+ var originalRender = this.render;
+ this.render = function() {
+ originalRender();
+ if ($scope.page > 0 && $scope.page <= $scope.totalPages) {
+ $scope.pages = getPages($scope.page, $scope.totalPages);
+ }
+ };
+}])
+
+.constant('uibPaginationConfig', {
+ itemsPerPage: 10,
+ boundaryLinks: false,
+ boundaryLinkNumbers: false,
+ directionLinks: true,
+ firstText: 'First',
+ previousText: 'Previous',
+ nextText: 'Next',
+ lastText: 'Last',
+ rotate: true,
+ forceEllipses: false
+})
+
+.directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, uibPaginationConfig) {
+ return {
+ scope: {
+ totalItems: '=',
+ firstText: '@',
+ previousText: '@',
+ nextText: '@',
+ lastText: '@',
+ ngDisabled:'='
+ },
+ require: ['uibPagination', '?ngModel'],
+ restrict: 'A',
+ controller: 'UibPaginationController',
+ controllerAs: 'pagination',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/pagination/pagination.html';
+ },
+ link: function(scope, element, attrs, ctrls) {
+ element.addClass('pagination');
+ var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (!ngModelCtrl) {
+ return; // do nothing if no ng-model
+ }
+
+ paginationCtrl.init(ngModelCtrl, uibPaginationConfig);
+ }
+ };
+}]);
+
+/**
+ * The following features are still outstanding: animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, html tooltips, and selector delegation.
+ */
+angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])
+
+/**
+ * The $tooltip service creates tooltip- and popover-like directives as well as
+ * houses global options for them.
+ */
+.provider('$uibTooltip', function() {
+ // The default options tooltip and popover.
+ var defaultOptions = {
+ placement: 'top',
+ placementClassPrefix: '',
+ animation: true,
+ popupDelay: 0,
+ popupCloseDelay: 0,
+ useContentExp: false
+ };
+
+ // Default hide triggers for each show trigger
+ var triggerMap = {
+ 'mouseenter': 'mouseleave',
+ 'click': 'click',
+ 'outsideClick': 'outsideClick',
+ 'focus': 'blur',
+ 'none': ''
+ };
+
+ // The options specified to the provider globally.
+ var globalOptions = {};
+
+ /**
+ * `options({})` allows global configuration of all tooltips in the
+ * application.
+ *
+ * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
+ * // place tooltips left instead of top by default
+ * $tooltipProvider.options( { placement: 'left' } );
+ * });
+ */
+ this.options = function(value) {
+ angular.extend(globalOptions, value);
+ };
+
+ /**
+ * This allows you to extend the set of trigger mappings available. E.g.:
+ *
+ * $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );
+ */
+ this.setTriggers = function setTriggers(triggers) {
+ angular.extend(triggerMap, triggers);
+ };
+
+ /**
+ * This is a helper function for translating camel-case to snake_case.
+ */
+ function snake_case(name) {
+ var regexp = /[A-Z]/g;
+ var separator = '-';
+ return name.replace(regexp, function(letter, pos) {
+ return (pos ? separator : '') + letter.toLowerCase();
+ });
+ }
+
+ /**
+ * Returns the actual instance of the $tooltip service.
+ * TODO support multiple triggers
+ */
+ this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
+ var openedTooltips = $$stackedMap.createNew();
+ $document.on('keyup', keypressListener);
+
+ $rootScope.$on('$destroy', function() {
+ $document.off('keyup', keypressListener);
+ });
+
+ function keypressListener(e) {
+ if (e.which === 27) {
+ var last = openedTooltips.top();
+ if (last) {
+ last.value.close();
+ last = null;
+ }
+ }
+ }
+
+ return function $tooltip(ttType, prefix, defaultTriggerShow, options) {
+ options = angular.extend({}, defaultOptions, globalOptions, options);
+
+ /**
+ * Returns an object of show and hide triggers.
+ *
+ * If a trigger is supplied,
+ * it is used to show the tooltip; otherwise, it will use the `trigger`
+ * option passed to the `$tooltipProvider.options` method; else it will
+ * default to the trigger supplied to this directive factory.
+ *
+ * The hide trigger is based on the show trigger. If the `trigger` option
+ * was passed to the `$tooltipProvider.options` method, it will use the
+ * mapped trigger from `triggerMap` or the passed trigger if the map is
+ * undefined; otherwise, it uses the `triggerMap` value of the show
+ * trigger; else it will just use the show trigger.
+ */
+ function getTriggers(trigger) {
+ var show = (trigger || options.trigger || defaultTriggerShow).split(' ');
+ var hide = show.map(function(trigger) {
+ return triggerMap[trigger] || trigger;
+ });
+ return {
+ show: show,
+ hide: hide
+ };
+ }
+
+ var directiveName = snake_case(ttType);
+
+ var startSym = $interpolate.startSymbol();
+ var endSym = $interpolate.endSymbol();
+ var template =
+ '<div '+ directiveName + '-popup ' +
+ 'uib-title="' + startSym + 'title' + endSym + '" ' +
+ (options.useContentExp ?
+ 'content-exp="contentExp()" ' :
+ 'content="' + startSym + 'content' + endSym + '" ') +
+ 'origin-scope="origScope" ' +
+ 'class="uib-position-measure ' + prefix + '" ' +
+ 'tooltip-animation-class="fade"' +
+ 'uib-tooltip-classes ' +
+ 'ng-class="{ in: isOpen }" ' +
+ '>' +
+ '</div>';
+
+ return {
+ compile: function(tElem, tAttrs) {
+ var tooltipLinker = $compile(template);
+
+ return function link(scope, element, attrs, tooltipCtrl) {
+ var tooltip;
+ var tooltipLinkedScope;
+ var transitionTimeout;
+ var showTimeout;
+ var hideTimeout;
+ var positionTimeout;
+ var adjustmentTimeout;
+ var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
+ var triggers = getTriggers(undefined);
+ var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
+ var ttScope = scope.$new(true);
+ var repositionScheduled = false;
+ var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;
+ var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;
+ var observers = [];
+ var lastPlacement;
+
+ var positionTooltip = function() {
+ // check if tooltip exists and is not empty
+ if (!tooltip || !tooltip.html()) { return; }
+
+ if (!positionTimeout) {
+ positionTimeout = $timeout(function() {
+ var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
+ var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
+ var elementPos = appendToBody ? $position.offset(element) : $position.position(element);
+ tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
+ var placementClasses = ttPosition.placement.split('-');
+
+ if (!tooltip.hasClass(placementClasses[0])) {
+ tooltip.removeClass(lastPlacement.split('-')[0]);
+ tooltip.addClass(placementClasses[0]);
+ }
+
+ if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
+ tooltip.removeClass(options.placementClassPrefix + lastPlacement);
+ tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
+ }
+
+ adjustmentTimeout = $timeout(function() {
+ var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
+ var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
+ if (adjustment) {
+ tooltip.css(adjustment);
+ }
+ adjustmentTimeout = null;
+ }, 0, false);
+
+ // first time through tt element will have the
+ // uib-position-measure class or if the placement
+ // has changed we need to position the arrow.
+ if (tooltip.hasClass('uib-position-measure')) {
+ $position.positionArrow(tooltip, ttPosition.placement);
+ tooltip.removeClass('uib-position-measure');
+ } else if (lastPlacement !== ttPosition.placement) {
+ $position.positionArrow(tooltip, ttPosition.placement);
+ }
+ lastPlacement = ttPosition.placement;
+
+ positionTimeout = null;
+ }, 0, false);
+ }
+ };
+
+ // Set up the correct scope to allow transclusion later
+ ttScope.origScope = scope;
+
+ // By default, the tooltip is not open.
+ // TODO add ability to start tooltip opened
+ ttScope.isOpen = false;
+
+ function toggleTooltipBind() {
+ if (!ttScope.isOpen) {
+ showTooltipBind();
+ } else {
+ hideTooltipBind();
+ }
+ }
+
+ // Show the tooltip with delay if specified, otherwise show it immediately
+ function showTooltipBind() {
+ if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
+ return;
+ }
+
+ cancelHide();
+ prepareTooltip();
+
+ if (ttScope.popupDelay) {
+ // Do nothing if the tooltip was already scheduled to pop-up.
+ // This happens if show is triggered multiple times before any hide is triggered.
+ if (!showTimeout) {
+ showTimeout = $timeout(show, ttScope.popupDelay, false);
+ }
+ } else {
+ show();
+ }
+ }
+
+ function hideTooltipBind() {
+ cancelShow();
+
+ if (ttScope.popupCloseDelay) {
+ if (!hideTimeout) {
+ hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);
+ }
+ } else {
+ hide();
+ }
+ }
+
+ // Show the tooltip popup element.
+ function show() {
+ cancelShow();
+ cancelHide();
+
+ // Don't show empty tooltips.
+ if (!ttScope.content) {
+ return angular.noop;
+ }
+
+ createTooltip();
+
+ // And show the tooltip.
+ ttScope.$evalAsync(function() {
+ ttScope.isOpen = true;
+ assignIsOpen(true);
+ positionTooltip();
+ });
+ }
+
+ function cancelShow() {
+ if (showTimeout) {
+ $timeout.cancel(showTimeout);
+ showTimeout = null;
+ }
+
+ if (positionTimeout) {
+ $timeout.cancel(positionTimeout);
+ positionTimeout = null;
+ }
+ }
+
+ // Hide the tooltip popup element.
+ function hide() {
+ if (!ttScope) {
+ return;
+ }
+
+ // First things first: we don't show it anymore.
+ ttScope.$evalAsync(function() {
+ if (ttScope) {
+ ttScope.isOpen = false;
+ assignIsOpen(false);
+ // And now we remove it from the DOM. However, if we have animation, we
+ // need to wait for it to expire beforehand.
+ // FIXME: this is a placeholder for a port of the transitions library.
+ // The fade transition in TWBS is 150ms.
+ if (ttScope.animation) {
+ if (!transitionTimeout) {
+ transitionTimeout = $timeout(removeTooltip, 150, false);
+ }
+ } else {
+ removeTooltip();
+ }
+ }
+ });
+ }
+
+ function cancelHide() {
+ if (hideTimeout) {
+ $timeout.cancel(hideTimeout);
+ hideTimeout = null;
+ }
+
+ if (transitionTimeout) {
+ $timeout.cancel(transitionTimeout);
+ transitionTimeout = null;
+ }
+ }
+
+ function createTooltip() {
+ // There can only be one tooltip element per directive shown at once.
+ if (tooltip) {
+ return;
+ }
+
+ tooltipLinkedScope = ttScope.$new();
+ tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {
+ if (appendToBody) {
+ $document.find('body').append(tooltip);
+ } else {
+ element.after(tooltip);
+ }
+ });
+
+ openedTooltips.add(ttScope, {
+ close: hide
+ });
+
+ prepObservers();
+ }
+
+ function removeTooltip() {
+ cancelShow();
+ cancelHide();
+ unregisterObservers();
+
+ if (tooltip) {
+ tooltip.remove();
+
+ tooltip = null;
+ if (adjustmentTimeout) {
+ $timeout.cancel(adjustmentTimeout);
+ }
+ }
+
+ openedTooltips.remove(ttScope);
+
+ if (tooltipLinkedScope) {
+ tooltipLinkedScope.$destroy();
+ tooltipLinkedScope = null;
+ }
+ }
+
+ /**
+ * Set the initial scope values. Once
+ * the tooltip is created, the observers
+ * will be added to keep things in sync.
+ */
+ function prepareTooltip() {
+ ttScope.title = attrs[prefix + 'Title'];
+ if (contentParse) {
+ ttScope.content = contentParse(scope);
+ } else {
+ ttScope.content = attrs[ttType];
+ }
+
+ ttScope.popupClass = attrs[prefix + 'Class'];
+ ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;
+ var placement = $position.parsePlacement(ttScope.placement);
+ lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];
+
+ var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);
+ var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);
+ ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;
+ ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;
+ }
+
+ function assignIsOpen(isOpen) {
+ if (isOpenParse && angular.isFunction(isOpenParse.assign)) {
+ isOpenParse.assign(scope, isOpen);
+ }
+ }
+
+ ttScope.contentExp = function() {
+ return ttScope.content;
+ };
+
+ /**
+ * Observe the relevant attributes.
+ */
+ attrs.$observe('disabled', function(val) {
+ if (val) {
+ cancelShow();
+ }
+
+ if (val && ttScope.isOpen) {
+ hide();
+ }
+ });
+
+ if (isOpenParse) {
+ scope.$watch(isOpenParse, function(val) {
+ if (ttScope && !val === ttScope.isOpen) {
+ toggleTooltipBind();
+ }
+ });
+ }
+
+ function prepObservers() {
+ observers.length = 0;
+
+ if (contentParse) {
+ observers.push(
+ scope.$watch(contentParse, function(val) {
+ ttScope.content = val;
+ if (!val && ttScope.isOpen) {
+ hide();
+ }
+ })
+ );
+
+ observers.push(
+ tooltipLinkedScope.$watch(function() {
+ if (!repositionScheduled) {
+ repositionScheduled = true;
+ tooltipLinkedScope.$$postDigest(function() {
+ repositionScheduled = false;
+ if (ttScope && ttScope.isOpen) {
+ positionTooltip();
+ }
+ });
+ }
+ })
+ );
+ } else {
+ observers.push(
+ attrs.$observe(ttType, function(val) {
+ ttScope.content = val;
+ if (!val && ttScope.isOpen) {
+ hide();
+ } else {
+ positionTooltip();
+ }
+ })
+ );
+ }
+
+ observers.push(
+ attrs.$observe(prefix + 'Title', function(val) {
+ ttScope.title = val;
+ if (ttScope.isOpen) {
+ positionTooltip();
+ }
+ })
+ );
+
+ observers.push(
+ attrs.$observe(prefix + 'Placement', function(val) {
+ ttScope.placement = val ? val : options.placement;
+ if (ttScope.isOpen) {
+ positionTooltip();
+ }
+ })
+ );
+ }
+
+ function unregisterObservers() {
+ if (observers.length) {
+ angular.forEach(observers, function(observer) {
+ observer();
+ });
+ observers.length = 0;
+ }
+ }
+
+ // hide tooltips/popovers for outsideClick trigger
+ function bodyHideTooltipBind(e) {
+ if (!ttScope || !ttScope.isOpen || !tooltip) {
+ return;
+ }
+ // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
+ if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
+ hideTooltipBind();
+ }
+ }
+
+ // KeyboardEvent handler to hide the tooltip on Escape key press
+ function hideOnEscapeKey(e) {
+ if (e.which === 27) {
+ hideTooltipBind();
+ }
+ }
+
+ var unregisterTriggers = function() {
+ triggers.show.forEach(function(trigger) {
+ if (trigger === 'outsideClick') {
+ element.off('click', toggleTooltipBind);
+ } else {
+ element.off(trigger, showTooltipBind);
+ element.off(trigger, toggleTooltipBind);
+ }
+ element.off('keypress', hideOnEscapeKey);
+ });
+ triggers.hide.forEach(function(trigger) {
+ if (trigger === 'outsideClick') {
+ $document.off('click', bodyHideTooltipBind);
+ } else {
+ element.off(trigger, hideTooltipBind);
+ }
+ });
+ };
+
+ function prepTriggers() {
+ var showTriggers = [], hideTriggers = [];
+ var val = scope.$eval(attrs[prefix + 'Trigger']);
+ unregisterTriggers();
+
+ if (angular.isObject(val)) {
+ Object.keys(val).forEach(function(key) {
+ showTriggers.push(key);
+ hideTriggers.push(val[key]);
+ });
+ triggers = {
+ show: showTriggers,
+ hide: hideTriggers
+ };
+ } else {
+ triggers = getTriggers(val);
+ }
+
+ if (triggers.show !== 'none') {
+ triggers.show.forEach(function(trigger, idx) {
+ if (trigger === 'outsideClick') {
+ element.on('click', toggleTooltipBind);
+ $document.on('click', bodyHideTooltipBind);
+ } else if (trigger === triggers.hide[idx]) {
+ element.on(trigger, toggleTooltipBind);
+ } else if (trigger) {
+ element.on(trigger, showTooltipBind);
+ element.on(triggers.hide[idx], hideTooltipBind);
+ }
+ element.on('keypress', hideOnEscapeKey);
+ });
+ }
+ }
+
+ prepTriggers();
+
+ var animation = scope.$eval(attrs[prefix + 'Animation']);
+ ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;
+
+ var appendToBodyVal;
+ var appendKey = prefix + 'AppendToBody';
+ if (appendKey in attrs && attrs[appendKey] === undefined) {
+ appendToBodyVal = true;
+ } else {
+ appendToBodyVal = scope.$eval(attrs[appendKey]);
+ }
+
+ appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;
+
+ // Make sure tooltip is destroyed and removed.
+ scope.$on('$destroy', function onDestroyTooltip() {
+ unregisterTriggers();
+ removeTooltip();
+ ttScope = null;
+ });
+ };
+ }
+ };
+ };
+ }];
+})
+
+// This is mostly ngInclude code but with a custom scope
+.directive('uibTooltipTemplateTransclude', [
+ '$animate', '$sce', '$compile', '$templateRequest',
+function ($animate, $sce, $compile, $templateRequest) {
+ return {
+ link: function(scope, elem, attrs) {
+ var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);
+
+ var changeCounter = 0,
+ currentScope,
+ previousElement,
+ currentElement;
+
+ var cleanupLastIncludeContent = function() {
+ if (previousElement) {
+ previousElement.remove();
+ previousElement = null;
+ }
+
+ if (currentScope) {
+ currentScope.$destroy();
+ currentScope = null;
+ }
+
+ if (currentElement) {
+ $animate.leave(currentElement).then(function() {
+ previousElement = null;
+ });
+ previousElement = currentElement;
+ currentElement = null;
+ }
+ };
+
+ scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {
+ var thisChangeId = ++changeCounter;
+
+ if (src) {
+ //set the 2nd param to true to ignore the template request error so that the inner
+ //contents and scope can be cleaned up.
+ $templateRequest(src, true).then(function(response) {
+ if (thisChangeId !== changeCounter) { return; }
+ var newScope = origScope.$new();
+ var template = response;
+
+ var clone = $compile(template)(newScope, function(clone) {
+ cleanupLastIncludeContent();
+ $animate.enter(clone, elem);
+ });
+
+ currentScope = newScope;
+ currentElement = clone;
+
+ currentScope.$emit('$includeContentLoaded', src);
+ }, function() {
+ if (thisChangeId === changeCounter) {
+ cleanupLastIncludeContent();
+ scope.$emit('$includeContentError', src);
+ }
+ });
+ scope.$emit('$includeContentRequested', src);
+ } else {
+ cleanupLastIncludeContent();
+ }
+ });
+
+ scope.$on('$destroy', cleanupLastIncludeContent);
+ }
+ };
+}])
+
+/**
+ * Note that it's intentional that these classes are *not* applied through $animate.
+ * They must not be animated as they're expected to be present on the tooltip on
+ * initialization.
+ */
+.directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs) {
+ // need to set the primary position so the
+ // arrow has space during position measure.
+ // tooltip.positionTooltip()
+ if (scope.placement) {
+ // // There are no top-left etc... classes
+ // // in TWBS, so we need the primary position.
+ var position = $uibPosition.parsePlacement(scope.placement);
+ element.addClass(position[0]);
+ }
+
+ if (scope.popupClass) {
+ element.addClass(scope.popupClass);
+ }
+
+ if (scope.animation) {
+ element.addClass(attrs.tooltipAnimationClass);
+ }
+ }
+ };
+}])
+
+.directive('uibTooltipPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { content: '@' },
+ templateUrl: 'uib/template/tooltip/tooltip-popup.html'
+ };
+})
+
+.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');
+}])
+
+.directive('uibTooltipTemplatePopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&', originScope: '&' },
+ templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
+ };
+})
+
+.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibTooltipHtmlPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&' },
+ templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
+ };
+})
+
+.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {
+ useContentExp: true
+ });
+}]);
+
+/**
+ * The following features are still outstanding: popup delay, animation as a
+ * function, placement as a function, inside, support for more triggers than
+ * just mouse enter/leave, and selector delegatation.
+ */
+angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
+
+.directive('uibPopoverTemplatePopup', function() {
+ return {
+ restrict: 'A',
+ scope: { uibTitle: '@', contentExp: '&', originScope: '&' },
+ templateUrl: 'uib/template/popover/popover-template.html'
+ };
+})
+
+.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibPopoverHtmlPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { contentExp: '&', uibTitle: '@' },
+ templateUrl: 'uib/template/popover/popover-html.html'
+ };
+})
+
+.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopoverHtml', 'popover', 'click', {
+ useContentExp: true
+ });
+}])
+
+.directive('uibPopoverPopup', function() {
+ return {
+ restrict: 'A',
+ scope: { uibTitle: '@', content: '@' },
+ templateUrl: 'uib/template/popover/popover.html'
+ };
+})
+
+.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {
+ return $uibTooltip('uibPopover', 'popover', 'click');
+}]);
+
+angular.module('ui.bootstrap.progressbar', [])
+
+.constant('uibProgressConfig', {
+ animate: true,
+ max: 100
+})
+
+.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {
+ var self = this,
+ animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
+
+ this.bars = [];
+ $scope.max = getMaxOrDefault();
+
+ this.addBar = function(bar, element, attrs) {
+ if (!animate) {
+ element.css({'transition': 'none'});
+ }
+
+ this.bars.push(bar);
+
+ bar.max = getMaxOrDefault();
+ bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';
+
+ bar.$watch('value', function(value) {
+ bar.recalculatePercentage();
+ });
+
+ bar.recalculatePercentage = function() {
+ var totalPercentage = self.bars.reduce(function(total, bar) {
+ bar.percent = +(100 * bar.value / bar.max).toFixed(2);
+ return total + bar.percent;
+ }, 0);
+
+ if (totalPercentage > 100) {
+ bar.percent -= totalPercentage - 100;
+ }
+ };
+
+ bar.$on('$destroy', function() {
+ element = null;
+ self.removeBar(bar);
+ });
+ };
+
+ this.removeBar = function(bar) {
+ this.bars.splice(this.bars.indexOf(bar), 1);
+ this.bars.forEach(function (bar) {
+ bar.recalculatePercentage();
+ });
+ };
+
+ //$attrs.$observe('maxParam', function(maxParam) {
+ $scope.$watch('maxParam', function(maxParam) {
+ self.bars.forEach(function(bar) {
+ bar.max = getMaxOrDefault();
+ bar.recalculatePercentage();
+ });
+ });
+
+ function getMaxOrDefault () {
+ return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;
+ }
+}])
+
+.directive('uibProgress', function() {
+ return {
+ replace: true,
+ transclude: true,
+ controller: 'UibProgressController',
+ require: 'uibProgress',
+ scope: {
+ maxParam: '=?max'
+ },
+ templateUrl: 'uib/template/progressbar/progress.html'
+ };
+})
+
+.directive('uibBar', function() {
+ return {
+ replace: true,
+ transclude: true,
+ require: '^uibProgress',
+ scope: {
+ value: '=',
+ type: '@'
+ },
+ templateUrl: 'uib/template/progressbar/bar.html',
+ link: function(scope, element, attrs, progressCtrl) {
+ progressCtrl.addBar(scope, element, attrs);
+ }
+ };
+})
+
+.directive('uibProgressbar', function() {
+ return {
+ replace: true,
+ transclude: true,
+ controller: 'UibProgressController',
+ scope: {
+ value: '=',
+ maxParam: '=?max',
+ type: '@'
+ },
+ templateUrl: 'uib/template/progressbar/progressbar.html',
+ link: function(scope, element, attrs, progressCtrl) {
+ progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});
+ }
+ };
+});
+
+angular.module('ui.bootstrap.rating', [])
+
+.constant('uibRatingConfig', {
+ max: 5,
+ stateOn: null,
+ stateOff: null,
+ enableReset: true,
+ titles: ['one', 'two', 'three', 'four', 'five']
+})
+
+.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {
+ var ngModelCtrl = { $setViewValue: angular.noop },
+ self = this;
+
+ this.init = function(ngModelCtrl_) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelCtrl.$render = this.render;
+
+ ngModelCtrl.$formatters.push(function(value) {
+ if (angular.isNumber(value) && value << 0 !== value) {
+ value = Math.round(value);
+ }
+
+ return value;
+ });
+
+ this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
+ this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;
+ this.enableReset = angular.isDefined($attrs.enableReset) ?
+ $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;
+ var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;
+ this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
+ tmpTitles : ratingConfig.titles;
+
+ var ratingStates = angular.isDefined($attrs.ratingStates) ?
+ $scope.$parent.$eval($attrs.ratingStates) :
+ new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);
+ $scope.range = this.buildTemplateObjects(ratingStates);
+ };
+
+ this.buildTemplateObjects = function(states) {
+ for (var i = 0, n = states.length; i < n; i++) {
+ states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
+ }
+ return states;
+ };
+
+ this.getTitle = function(index) {
+ if (index >= this.titles.length) {
+ return index + 1;
+ }
+
+ return this.titles[index];
+ };
+
+ $scope.rate = function(value) {
+ if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
+ var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;
+ ngModelCtrl.$setViewValue(newViewValue);
+ ngModelCtrl.$render();
+ }
+ };
+
+ $scope.enter = function(value) {
+ if (!$scope.readonly) {
+ $scope.value = value;
+ }
+ $scope.onHover({value: value});
+ };
+
+ $scope.reset = function() {
+ $scope.value = ngModelCtrl.$viewValue;
+ $scope.onLeave();
+ };
+
+ $scope.onKeydown = function(evt) {
+ if (/(37|38|39|40)/.test(evt.which)) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
+ }
+ };
+
+ this.render = function() {
+ $scope.value = ngModelCtrl.$viewValue;
+ $scope.title = self.getTitle($scope.value - 1);
+ };
+}])
+
+.directive('uibRating', function() {
+ return {
+ require: ['uibRating', 'ngModel'],
+ restrict: 'A',
+ scope: {
+ readonly: '=?readOnly',
+ onHover: '&',
+ onLeave: '&'
+ },
+ controller: 'UibRatingController',
+ templateUrl: 'uib/template/rating/rating.html',
+ link: function(scope, element, attrs, ctrls) {
+ var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+ ratingCtrl.init(ngModelCtrl);
+ }
+ };
+});
+
+angular.module('ui.bootstrap.tabs', [])
+
+.controller('UibTabsetController', ['$scope', function ($scope) {
+ var ctrl = this,
+ oldIndex;
+ ctrl.tabs = [];
+
+ ctrl.select = function(index, evt) {
+ if (!destroyed) {
+ var previousIndex = findTabIndex(oldIndex);
+ var previousSelected = ctrl.tabs[previousIndex];
+ if (previousSelected) {
+ previousSelected.tab.onDeselect({
+ $event: evt,
+ $selectedIndex: index
+ });
+ if (evt && evt.isDefaultPrevented()) {
+ return;
+ }
+ previousSelected.tab.active = false;
+ }
+
+ var selected = ctrl.tabs[index];
+ if (selected) {
+ selected.tab.onSelect({
+ $event: evt
+ });
+ selected.tab.active = true;
+ ctrl.active = selected.index;
+ oldIndex = selected.index;
+ } else if (!selected && angular.isDefined(oldIndex)) {
+ ctrl.active = null;
+ oldIndex = null;
+ }
+ }
+ };
+
+ ctrl.addTab = function addTab(tab) {
+ ctrl.tabs.push({
+ tab: tab,
+ index: tab.index
+ });
+ ctrl.tabs.sort(function(t1, t2) {
+ if (t1.index > t2.index) {
+ return 1;
+ }
+
+ if (t1.index < t2.index) {
+ return -1;
+ }
+
+ return 0;
+ });
+
+ if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
+ var newActiveIndex = findTabIndex(tab.index);
+ ctrl.select(newActiveIndex);
+ }
+ };
+
+ ctrl.removeTab = function removeTab(tab) {
+ var index;
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].tab === tab) {
+ index = i;
+ break;
+ }
+ }
+
+ if (ctrl.tabs[index].index === ctrl.active) {
+ var newActiveTabIndex = index === ctrl.tabs.length - 1 ?
+ index - 1 : index + 1 % ctrl.tabs.length;
+ ctrl.select(newActiveTabIndex);
+ }
+
+ ctrl.tabs.splice(index, 1);
+ };
+
+ $scope.$watch('tabset.active', function(val) {
+ if (angular.isDefined(val) && val !== oldIndex) {
+ ctrl.select(findTabIndex(val));
+ }
+ });
+
+ var destroyed;
+ $scope.$on('$destroy', function() {
+ destroyed = true;
+ });
+
+ function findTabIndex(index) {
+ for (var i = 0; i < ctrl.tabs.length; i++) {
+ if (ctrl.tabs[i].index === index) {
+ return i;
+ }
+ }
+ }
+}])
+
+.directive('uibTabset', function() {
+ return {
+ transclude: true,
+ replace: true,
+ scope: {},
+ bindToController: {
+ active: '=?',
+ type: '@'
+ },
+ controller: 'UibTabsetController',
+ controllerAs: 'tabset',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tabset.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.vertical = angular.isDefined(attrs.vertical) ?
+ scope.$parent.$eval(attrs.vertical) : false;
+ scope.justified = angular.isDefined(attrs.justified) ?
+ scope.$parent.$eval(attrs.justified) : false;
+ }
+ };
+})
+
+.directive('uibTab', ['$parse', function($parse) {
+ return {
+ require: '^uibTabset',
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'uib/template/tabs/tab.html';
+ },
+ transclude: true,
+ scope: {
+ heading: '@',
+ index: '=?',
+ classes: '@?',
+ onSelect: '&select', //This callback is called in contentHeadingTransclude
+ //once it inserts the tab's content into the dom
+ onDeselect: '&deselect'
+ },
+ controller: function() {
+ //Empty controller so other directives can require being 'under' a tab
+ },
+ controllerAs: 'tab',
+ link: function(scope, elm, attrs, tabsetCtrl, transclude) {
+ scope.disabled = false;
+ if (attrs.disable) {
+ scope.$parent.$watch($parse(attrs.disable), function(value) {
+ scope.disabled = !! value;
+ });
+ }
+
+ if (angular.isUndefined(attrs.index)) {
+ if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {
+ scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;
+ } else {
+ scope.index = 0;
+ }
+ }
+
+ if (angular.isUndefined(attrs.classes)) {
+ scope.classes = '';
+ }
+
+ scope.select = function(evt) {
+ if (!scope.disabled) {
+ var index;
+ for (var i = 0; i < tabsetCtrl.tabs.length; i++) {
+ if (tabsetCtrl.tabs[i].tab === scope) {
+ index = i;
+ break;
+ }
+ }
+
+ tabsetCtrl.select(index, evt);
+ }
+ };
+
+ tabsetCtrl.addTab(scope);
+ scope.$on('$destroy', function() {
+ tabsetCtrl.removeTab(scope);
+ });
+
+ //We need to transclude later, once the content container is ready.
+ //when this link happens, we're inside a tab heading.
+ scope.$transcludeFn = transclude;
+ }
+ };
+}])
+
+.directive('uibTabHeadingTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTab',
+ link: function(scope, elm) {
+ scope.$watch('headingElement', function updateHeadingElement(heading) {
+ if (heading) {
+ elm.html('');
+ elm.append(heading);
+ }
+ });
+ }
+ };
+})
+
+.directive('uibTabContentTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^uibTabset',
+ link: function(scope, elm, attrs) {
+ var tab = scope.$eval(attrs.uibTabContentTransclude).tab;
+
+ //Now our tab is ready to be transcluded: both the tab heading area
+ //and the tab content area are loaded. Transclude 'em both.
+ tab.$transcludeFn(tab.$parent, function(contents) {
+ angular.forEach(contents, function(node) {
+ if (isTabHeading(node)) {
+ //Let tabHeadingTransclude know.
+ tab.headingElement = node;
+ } else {
+ elm.append(node);
+ }
+ });
+ });
+ }
+ };
+
+ function isTabHeading(node) {
+ return node.tagName && (
+ node.hasAttribute('uib-tab-heading') ||
+ node.hasAttribute('data-uib-tab-heading') ||
+ node.hasAttribute('x-uib-tab-heading') ||
+ node.tagName.toLowerCase() === 'uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'data-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'x-uib-tab-heading' ||
+ node.tagName.toLowerCase() === 'uib:tab-heading'
+ );
+ }
+});
+
+angular.module('ui.bootstrap.timepicker', [])
+
+.constant('uibTimepickerConfig', {
+ hourStep: 1,
+ minuteStep: 1,
+ secondStep: 1,
+ showMeridian: true,
+ showSeconds: false,
+ meridians: null,
+ readonlyInput: false,
+ mousewheel: true,
+ arrowkeys: true,
+ showSpinners: true,
+ templateUrl: 'uib/template/timepicker/timepicker.html'
+})
+
+.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
+ var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
+ var selected = new Date(),
+ watchers = [],
+ ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
+ meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,
+ padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;
+
+ $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
+ $element.removeAttr('tabindex');
+
+ this.init = function(ngModelCtrl_, inputs) {
+ ngModelCtrl = ngModelCtrl_;
+ ngModelCtrl.$render = this.render;
+
+ ngModelCtrl.$formatters.unshift(function(modelValue) {
+ return modelValue ? new Date(modelValue) : null;
+ });
+
+ var hoursInputEl = inputs.eq(0),
+ minutesInputEl = inputs.eq(1),
+ secondsInputEl = inputs.eq(2);
+
+ hoursModelCtrl = hoursInputEl.controller('ngModel');
+ minutesModelCtrl = minutesInputEl.controller('ngModel');
+ secondsModelCtrl = secondsInputEl.controller('ngModel');
+
+ var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
+
+ if (mousewheel) {
+ this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ }
+
+ var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;
+ if (arrowkeys) {
+ this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ }
+
+ $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
+ this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);
+ };
+
+ var hourStep = timepickerConfig.hourStep;
+ if ($attrs.hourStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function(value) {
+ hourStep = +value;
+ }));
+ }
+
+ var minuteStep = timepickerConfig.minuteStep;
+ if ($attrs.minuteStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
+ minuteStep = +value;
+ }));
+ }
+
+ var min;
+ watchers.push($scope.$parent.$watch($parse($attrs.min), function(value) {
+ var dt = new Date(value);
+ min = isNaN(dt) ? undefined : dt;
+ }));
+
+ var max;
+ watchers.push($scope.$parent.$watch($parse($attrs.max), function(value) {
+ var dt = new Date(value);
+ max = isNaN(dt) ? undefined : dt;
+ }));
+
+ var disabled = false;
+ if ($attrs.ngDisabled) {
+ watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
+ disabled = value;
+ }));
+ }
+
+ $scope.noIncrementHours = function() {
+ var incrementedSelected = addMinutes(selected, hourStep * 60);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementHours = function() {
+ var decrementedSelected = addMinutes(selected, -hourStep * 60);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noIncrementMinutes = function() {
+ var incrementedSelected = addMinutes(selected, minuteStep);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementMinutes = function() {
+ var decrementedSelected = addMinutes(selected, -minuteStep);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noIncrementSeconds = function() {
+ var incrementedSelected = addSeconds(selected, secondStep);
+ return disabled || incrementedSelected > max ||
+ incrementedSelected < selected && incrementedSelected < min;
+ };
+
+ $scope.noDecrementSeconds = function() {
+ var decrementedSelected = addSeconds(selected, -secondStep);
+ return disabled || decrementedSelected < min ||
+ decrementedSelected > selected && decrementedSelected > max;
+ };
+
+ $scope.noToggleMeridian = function() {
+ if (selected.getHours() < 12) {
+ return disabled || addMinutes(selected, 12 * 60) > max;
+ }
+
+ return disabled || addMinutes(selected, -12 * 60) < min;
+ };
+
+ var secondStep = timepickerConfig.secondStep;
+ if ($attrs.secondStep) {
+ watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function(value) {
+ secondStep = +value;
+ }));
+ }
+
+ $scope.showSeconds = timepickerConfig.showSeconds;
+ if ($attrs.showSeconds) {
+ watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
+ $scope.showSeconds = !!value;
+ }));
+ }
+
+ // 12H / 24H mode
+ $scope.showMeridian = timepickerConfig.showMeridian;
+ if ($attrs.showMeridian) {
+ watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
+ $scope.showMeridian = !!value;
+
+ if (ngModelCtrl.$error.time) {
+ // Evaluate from template
+ var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
+ if (angular.isDefined(hours) && angular.isDefined(minutes)) {
+ selected.setHours(hours);
+ refresh();
+ }
+ } else {
+ updateTemplate();
+ }
+ }));
+ }
+
+ // Get $scope.hours in 24H mode if valid
+ function getHoursFromTemplate() {
+ var hours = +$scope.hours;
+ var valid = $scope.showMeridian ? hours > 0 && hours < 13 :
+ hours >= 0 && hours < 24;
+ if (!valid || $scope.hours === '') {
+ return undefined;
+ }
+
+ if ($scope.showMeridian) {
+ if (hours === 12) {
+ hours = 0;
+ }
+ if ($scope.meridian === meridians[1]) {
+ hours = hours + 12;
+ }
+ }
+ return hours;
+ }
+
+ function getMinutesFromTemplate() {
+ var minutes = +$scope.minutes;
+ var valid = minutes >= 0 && minutes < 60;
+ if (!valid || $scope.minutes === '') {
+ return undefined;
+ }
+ return minutes;
+ }
+
+ function getSecondsFromTemplate() {
+ var seconds = +$scope.seconds;
+ return seconds >= 0 && seconds < 60 ? seconds : undefined;
+ }
+
+ function pad(value, noPad) {
+ if (value === null) {
+ return '';
+ }
+
+ return angular.isDefined(value) && value.toString().length < 2 && !noPad ?
+ '0' + value : value.toString();
+ }
+
+ // Respond on mousewheel spin
+ this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ var isScrollingUp = function(e) {
+ if (e.originalEvent) {
+ e = e.originalEvent;
+ }
+ //pick correct delta variable depending on event
+ var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;
+ return e.detail || delta > 0;
+ };
+
+ hoursInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
+ }
+ e.preventDefault();
+ });
+
+ minutesInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
+ }
+ e.preventDefault();
+ });
+
+ secondsInputEl.on('mousewheel wheel', function(e) {
+ if (!disabled) {
+ $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());
+ }
+ e.preventDefault();
+ });
+ };
+
+ // Respond on up/down arrowkeys
+ this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ hoursInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementHours();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementHours();
+ $scope.$apply();
+ }
+ }
+ });
+
+ minutesInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementMinutes();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementMinutes();
+ $scope.$apply();
+ }
+ }
+ });
+
+ secondsInputEl.on('keydown', function(e) {
+ if (!disabled) {
+ if (e.which === 38) { // up
+ e.preventDefault();
+ $scope.incrementSeconds();
+ $scope.$apply();
+ } else if (e.which === 40) { // down
+ e.preventDefault();
+ $scope.decrementSeconds();
+ $scope.$apply();
+ }
+ }
+ });
+ };
+
+ this.setupInputEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
+ if ($scope.readonlyInput) {
+ $scope.updateHours = angular.noop;
+ $scope.updateMinutes = angular.noop;
+ $scope.updateSeconds = angular.noop;
+ return;
+ }
+
+ var invalidate = function(invalidHours, invalidMinutes, invalidSeconds) {
+ ngModelCtrl.$setViewValue(null);
+ ngModelCtrl.$setValidity('time', false);
+ if (angular.isDefined(invalidHours)) {
+ $scope.invalidHours = invalidHours;
+ if (hoursModelCtrl) {
+ hoursModelCtrl.$setValidity('hours', false);
+ }
+ }
+
+ if (angular.isDefined(invalidMinutes)) {
+ $scope.invalidMinutes = invalidMinutes;
+ if (minutesModelCtrl) {
+ minutesModelCtrl.$setValidity('minutes', false);
+ }
+ }
+
+ if (angular.isDefined(invalidSeconds)) {
+ $scope.invalidSeconds = invalidSeconds;
+ if (secondsModelCtrl) {
+ secondsModelCtrl.$setValidity('seconds', false);
+ }
+ }
+ };
+
+ $scope.updateHours = function() {
+ var hours = getHoursFromTemplate(),
+ minutes = getMinutesFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(hours) && angular.isDefined(minutes)) {
+ selected.setHours(hours);
+ selected.setMinutes(minutes);
+ if (selected < min || selected > max) {
+ invalidate(true);
+ } else {
+ refresh('h');
+ }
+ } else {
+ invalidate(true);
+ }
+ };
+
+ hoursInputEl.on('blur', function(e) {
+ ngModelCtrl.$setTouched();
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if ($scope.hours === null || $scope.hours === '') {
+ invalidate(true);
+ } else if (!$scope.invalidHours && $scope.hours < 10) {
+ $scope.$apply(function() {
+ $scope.hours = pad($scope.hours, !padHours);
+ });
+ }
+ });
+
+ $scope.updateMinutes = function() {
+ var minutes = getMinutesFromTemplate(),
+ hours = getHoursFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(minutes) && angular.isDefined(hours)) {
+ selected.setHours(hours);
+ selected.setMinutes(minutes);
+ if (selected < min || selected > max) {
+ invalidate(undefined, true);
+ } else {
+ refresh('m');
+ }
+ } else {
+ invalidate(undefined, true);
+ }
+ };
+
+ minutesInputEl.on('blur', function(e) {
+ ngModelCtrl.$setTouched();
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if ($scope.minutes === null) {
+ invalidate(undefined, true);
+ } else if (!$scope.invalidMinutes && $scope.minutes < 10) {
+ $scope.$apply(function() {
+ $scope.minutes = pad($scope.minutes);
+ });
+ }
+ });
+
+ $scope.updateSeconds = function() {
+ var seconds = getSecondsFromTemplate();
+
+ ngModelCtrl.$setDirty();
+
+ if (angular.isDefined(seconds)) {
+ selected.setSeconds(seconds);
+ refresh('s');
+ } else {
+ invalidate(undefined, undefined, true);
+ }
+ };
+
+ secondsInputEl.on('blur', function(e) {
+ if (modelIsEmpty()) {
+ makeValid();
+ } else if (!$scope.invalidSeconds && $scope.seconds < 10) {
+ $scope.$apply( function() {
+ $scope.seconds = pad($scope.seconds);
+ });
+ }
+ });
+
+ };
+
+ this.render = function() {
+ var date = ngModelCtrl.$viewValue;
+
+ if (isNaN(date)) {
+ ngModelCtrl.$setValidity('time', false);
+ $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
+ } else {
+ if (date) {
+ selected = date;
+ }
+
+ if (selected < min || selected > max) {
+ ngModelCtrl.$setValidity('time', false);
+ $scope.invalidHours = true;
+ $scope.invalidMinutes = true;
+ } else {
+ makeValid();
+ }
+ updateTemplate();
+ }
+ };
+
+ // Call internally when we know that model is valid.
+ function refresh(keyboardChange) {
+ makeValid();
+ ngModelCtrl.$setViewValue(new Date(selected));
+ updateTemplate(keyboardChange);
+ }
+
+ function makeValid() {
+ if (hoursModelCtrl) {
+ hoursModelCtrl.$setValidity('hours', true);
+ }
+
+ if (minutesModelCtrl) {
+ minutesModelCtrl.$setValidity('minutes', true);
+ }
+
+ if (secondsModelCtrl) {
+ secondsModelCtrl.$setValidity('seconds', true);
+ }
+
+ ngModelCtrl.$setValidity('time', true);
+ $scope.invalidHours = false;
+ $scope.invalidMinutes = false;
+ $scope.invalidSeconds = false;
+ }
+
+ function updateTemplate(keyboardChange) {
+ if (!ngModelCtrl.$modelValue) {
+ $scope.hours = null;
+ $scope.minutes = null;
+ $scope.seconds = null;
+ $scope.meridian = meridians[0];
+ } else {
+ var hours = selected.getHours(),
+ minutes = selected.getMinutes(),
+ seconds = selected.getSeconds();
+
+ if ($scope.showMeridian) {
+ hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system
+ }
+
+ $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);
+ if (keyboardChange !== 'm') {
+ $scope.minutes = pad(minutes);
+ }
+ $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
+
+ if (keyboardChange !== 's') {
+ $scope.seconds = pad(seconds);
+ }
+ $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];
+ }
+ }
+
+ function addSecondsToSelected(seconds) {
+ selected = addSeconds(selected, seconds);
+ refresh();
+ }
+
+ function addMinutes(selected, minutes) {
+ return addSeconds(selected, minutes*60);
+ }
+
+ function addSeconds(date, seconds) {
+ var dt = new Date(date.getTime() + seconds * 1000);
+ var newDate = new Date(date);
+ newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());
+ return newDate;
+ }
+
+ function modelIsEmpty() {
+ return ($scope.hours === null || $scope.hours === '') &&
+ ($scope.minutes === null || $scope.minutes === '') &&
+ (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));
+ }
+
+ $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
+ $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;
+
+ $scope.incrementHours = function() {
+ if (!$scope.noIncrementHours()) {
+ addSecondsToSelected(hourStep * 60 * 60);
+ }
+ };
+
+ $scope.decrementHours = function() {
+ if (!$scope.noDecrementHours()) {
+ addSecondsToSelected(-hourStep * 60 * 60);
+ }
+ };
+
+ $scope.incrementMinutes = function() {
+ if (!$scope.noIncrementMinutes()) {
+ addSecondsToSelected(minuteStep * 60);
+ }
+ };
+
+ $scope.decrementMinutes = function() {
+ if (!$scope.noDecrementMinutes()) {
+ addSecondsToSelected(-minuteStep * 60);
+ }
+ };
+
+ $scope.incrementSeconds = function() {
+ if (!$scope.noIncrementSeconds()) {
+ addSecondsToSelected(secondStep);
+ }
+ };
+
+ $scope.decrementSeconds = function() {
+ if (!$scope.noDecrementSeconds()) {
+ addSecondsToSelected(-secondStep);
+ }
+ };
+
+ $scope.toggleMeridian = function() {
+ var minutes = getMinutesFromTemplate(),
+ hours = getHoursFromTemplate();
+
+ if (!$scope.noToggleMeridian()) {
+ if (angular.isDefined(minutes) && angular.isDefined(hours)) {
+ addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));
+ } else {
+ $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];
+ }
+ }
+ };
+
+ $scope.blur = function() {
+ ngModelCtrl.$setTouched();
+ };
+
+ $scope.$on('$destroy', function() {
+ while (watchers.length) {
+ watchers.shift()();
+ }
+ });
+}])
+
+.directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {
+ return {
+ require: ['uibTimepicker', '?^ngModel'],
+ restrict: 'A',
+ controller: 'UibTimepickerController',
+ controllerAs: 'timepicker',
+ scope: {},
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || uibTimepickerConfig.templateUrl;
+ },
+ link: function(scope, element, attrs, ctrls) {
+ var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
+
+ if (ngModelCtrl) {
+ timepickerCtrl.init(ngModelCtrl, element.find('input'));
+ }
+ }
+ };
+}]);
+
+angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])
+
+/**
+ * A helper service that can parse typeahead's syntax (string provided by users)
+ * Extracted to a separate service for ease of unit testing
+ */
+ .factory('uibTypeaheadParser', ['$parse', function($parse) {
+ // 000001111111100000000000002222222200000000000000003333333333333330000000000044444444000
+ var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
+ return {
+ parse: function(input) {
+ var match = input.match(TYPEAHEAD_REGEXP);
+ if (!match) {
+ throw new Error(
+ 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
+ ' but got "' + input + '".');
+ }
+
+ return {
+ itemName: match[3],
+ source: $parse(match[4]),
+ viewMapper: $parse(match[2] || match[1]),
+ modelMapper: $parse(match[1])
+ };
+ }
+ };
+ }])
+
+ .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',
+ function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {
+ var HOT_KEYS = [9, 13, 27, 38, 40];
+ var eventDebounceTime = 200;
+ var modelCtrl, ngModelOptions;
+ //SUPPORTED ATTRIBUTES (OPTIONS)
+
+ //minimal no of characters that needs to be entered before typeahead kicks-in
+ var minLength = originalScope.$eval(attrs.typeaheadMinLength);
+ if (!minLength && minLength !== 0) {
+ minLength = 1;
+ }
+
+ originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
+ minLength = !newVal && newVal !== 0 ? 1 : newVal;
+ });
+
+ //minimal wait time after last character typed before typeahead kicks-in
+ var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
+
+ //should it restrict model values to the ones selected from the popup only?
+ var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
+ originalScope.$watch(attrs.typeaheadEditable, function (newVal) {
+ isEditable = newVal !== false;
+ });
+
+ //binding to a variable that indicates if matches are being retrieved asynchronously
+ var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
+
+ //a function to determine if an event should cause selection
+ var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function(scope, vals) {
+ var evt = vals.$event;
+ return evt.which === 13 || evt.which === 9;
+ };
+
+ //a callback executed when a match is selected
+ var onSelectCallback = $parse(attrs.typeaheadOnSelect);
+
+ //should it select highlighted popup value when losing focus?
+ var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;
+
+ //binding to a variable that indicates if there were no results after the query is completed
+ var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;
+
+ var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
+
+ var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;
+
+ var appendTo = attrs.typeaheadAppendTo ?
+ originalScope.$eval(attrs.typeaheadAppendTo) : null;
+
+ var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;
+
+ //If input matches an item of the list exactly, select it automatically
+ var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;
+
+ //binding to a variable that indicates if dropdown is open
+ var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;
+
+ var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;
+
+ //INTERNAL VARIABLES
+
+ //model setter executed upon match selection
+ var parsedModel = $parse(attrs.ngModel);
+ var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');
+ var $setModelValue = function(scope, newValue) {
+ if (angular.isFunction(parsedModel(originalScope)) &&
+ ngModelOptions.getOption('getterSetter')) {
+ return invokeModelSetter(scope, {$$$p: newValue});
+ }
+
+ return parsedModel.assign(scope, newValue);
+ };
+
+ //expressions used by typeahead
+ var parserResult = typeaheadParser.parse(attrs.uibTypeahead);
+
+ var hasFocus;
+
+ //Used to avoid bug in iOS webview where iOS keyboard does not fire
+ //mousedown & mouseup events
+ //Issue #3699
+ var selected;
+
+ //create a child scope for the typeahead directive so we are not polluting original scope
+ //with typeahead-specific data (matches, query etc.)
+ var scope = originalScope.$new();
+ var offDestroy = originalScope.$on('$destroy', function() {
+ scope.$destroy();
+ });
+ scope.$on('$destroy', offDestroy);
+
+ // WAI-ARIA
+ var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
+ element.attr({
+ 'aria-autocomplete': 'list',
+ 'aria-expanded': false,
+ 'aria-owns': popupId
+ });
+
+ var inputsContainer, hintInputElem;
+ //add read-only input to show hint
+ if (showHint) {
+ inputsContainer = angular.element('<div></div>');
+ inputsContainer.css('position', 'relative');
+ element.after(inputsContainer);
+ hintInputElem = element.clone();
+ hintInputElem.attr('placeholder', '');
+ hintInputElem.attr('tabindex', '-1');
+ hintInputElem.val('');
+ hintInputElem.css({
+ 'position': 'absolute',
+ 'top': '0px',
+ 'left': '0px',
+ 'border-color': 'transparent',
+ 'box-shadow': 'none',
+ 'opacity': 1,
+ 'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',
+ 'color': '#999'
+ });
+ element.css({
+ 'position': 'relative',
+ 'vertical-align': 'top',
+ 'background-color': 'transparent'
+ });
+
+ if (hintInputElem.attr('id')) {
+ hintInputElem.removeAttr('id'); // remove duplicate id if present.
+ }
+ inputsContainer.append(hintInputElem);
+ hintInputElem.after(element);
+ }
+
+ //pop-up element used to display matches
+ var popUpEl = angular.element('<div uib-typeahead-popup></div>');
+ popUpEl.attr({
+ id: popupId,
+ matches: 'matches',
+ active: 'activeIdx',
+ select: 'select(activeIdx, evt)',
+ 'move-in-progress': 'moveInProgress',
+ query: 'query',
+ position: 'position',
+ 'assign-is-open': 'assignIsOpen(isOpen)',
+ debounce: 'debounceUpdate'
+ });
+ //custom item template
+ if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
+ popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
+ }
+
+ if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {
+ popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);
+ }
+
+ var resetHint = function() {
+ if (showHint) {
+ hintInputElem.val('');
+ }
+ };
+
+ var resetMatches = function() {
+ scope.matches = [];
+ scope.activeIdx = -1;
+ element.attr('aria-expanded', false);
+ resetHint();
+ };
+
+ var getMatchId = function(index) {
+ return popupId + '-option-' + index;
+ };
+
+ // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
+ // This attribute is added or removed automatically when the `activeIdx` changes.
+ scope.$watch('activeIdx', function(index) {
+ if (index < 0) {
+ element.removeAttr('aria-activedescendant');
+ } else {
+ element.attr('aria-activedescendant', getMatchId(index));
+ }
+ });
+
+ var inputIsExactMatch = function(inputValue, index) {
+ if (scope.matches.length > index && inputValue) {
+ return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
+ }
+
+ return false;
+ };
+
+ var getMatchesAsync = function(inputValue, evt) {
+ var locals = {$viewValue: inputValue};
+ isLoadingSetter(originalScope, true);
+ isNoResultsSetter(originalScope, false);
+ $q.when(parserResult.source(originalScope, locals)).then(function(matches) {
+ //it might happen that several async queries were in progress if a user were typing fast
+ //but we are interested only in responses that correspond to the current view value
+ var onCurrentRequest = inputValue === modelCtrl.$viewValue;
+ if (onCurrentRequest && hasFocus) {
+ if (matches && matches.length > 0) {
+ scope.activeIdx = focusFirst ? 0 : -1;
+ isNoResultsSetter(originalScope, false);
+ scope.matches.length = 0;
+
+ //transform labels
+ for (var i = 0; i < matches.length; i++) {
+ locals[parserResult.itemName] = matches[i];
+ scope.matches.push({
+ id: getMatchId(i),
+ label: parserResult.viewMapper(scope, locals),
+ model: matches[i]
+ });
+ }
+
+ scope.query = inputValue;
+ //position pop-up with matches - we need to re-calculate its position each time we are opening a window
+ //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
+ //due to other elements being rendered
+ recalculatePosition();
+
+ element.attr('aria-expanded', true);
+
+ //Select the single remaining option if user input matches
+ if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {
+ if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
+ $$debounce(function() {
+ scope.select(0, evt);
+ }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
+ } else {
+ scope.select(0, evt);
+ }
+ }
+
+ if (showHint) {
+ var firstLabel = scope.matches[0].label;
+ if (angular.isString(inputValue) &&
+ inputValue.length > 0 &&
+ firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {
+ hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));
+ } else {
+ hintInputElem.val('');
+ }
+ }
+ } else {
+ resetMatches();
+ isNoResultsSetter(originalScope, true);
+ }
+ }
+ if (onCurrentRequest) {
+ isLoadingSetter(originalScope, false);
+ }
+ }, function() {
+ resetMatches();
+ isLoadingSetter(originalScope, false);
+ isNoResultsSetter(originalScope, true);
+ });
+ };
+
+ // bind events only if appendToBody params exist - performance feature
+ if (appendToBody) {
+ angular.element($window).on('resize', fireRecalculating);
+ $document.find('body').on('scroll', fireRecalculating);
+ }
+
+ // Declare the debounced function outside recalculating for
+ // proper debouncing
+ var debouncedRecalculate = $$debounce(function() {
+ // if popup is visible
+ if (scope.matches.length) {
+ recalculatePosition();
+ }
+
+ scope.moveInProgress = false;
+ }, eventDebounceTime);
+
+ // Default progress type
+ scope.moveInProgress = false;
+
+ function fireRecalculating() {
+ if (!scope.moveInProgress) {
+ scope.moveInProgress = true;
+ scope.$digest();
+ }
+
+ debouncedRecalculate();
+ }
+
+ // recalculate actual position and set new values to scope
+ // after digest loop is popup in right position
+ function recalculatePosition() {
+ scope.position = appendToBody ? $position.offset(element) : $position.position(element);
+ scope.position.top += element.prop('offsetHeight');
+ }
+
+ //we need to propagate user's query so we can higlight matches
+ scope.query = undefined;
+
+ //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
+ var timeoutPromise;
+
+ var scheduleSearchWithTimeout = function(inputValue) {
+ timeoutPromise = $timeout(function() {
+ getMatchesAsync(inputValue);
+ }, waitTime);
+ };
+
+ var cancelPreviousTimeout = function() {
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+ };
+
+ resetMatches();
+
+ scope.assignIsOpen = function (isOpen) {
+ isOpenSetter(originalScope, isOpen);
+ };
+
+ scope.select = function(activeIdx, evt) {
+ //called from within the $digest() cycle
+ var locals = {};
+ var model, item;
+
+ selected = true;
+ locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
+ model = parserResult.modelMapper(originalScope, locals);
+ $setModelValue(originalScope, model);
+ modelCtrl.$setValidity('editable', true);
+ modelCtrl.$setValidity('parse', true);
+
+ onSelectCallback(originalScope, {
+ $item: item,
+ $model: model,
+ $label: parserResult.viewMapper(originalScope, locals),
+ $event: evt
+ });
+
+ resetMatches();
+
+ //return focus to the input element if a match was selected via a mouse click event
+ // use timeout to avoid $rootScope:inprog error
+ if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {
+ $timeout(function() { element[0].focus(); }, 0, false);
+ }
+ };
+
+ //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
+ element.on('keydown', function(evt) {
+ //typeahead is open and an "interesting" key was pressed
+ if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
+ return;
+ }
+
+ var shouldSelect = isSelectEvent(originalScope, {$event: evt});
+
+ /**
+ * if there's nothing selected (i.e. focusFirst) and enter or tab is hit
+ * or
+ * shift + tab is pressed to bring focus to the previous element
+ * then clear the results
+ */
+ if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
+ resetMatches();
+ scope.$digest();
+ return;
+ }
+
+ evt.preventDefault();
+ var target;
+ switch (evt.which) {
+ case 27: // escape
+ evt.stopPropagation();
+
+ resetMatches();
+ originalScope.$digest();
+ break;
+ case 38: // up arrow
+ scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
+ scope.$digest();
+ target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
+ target.parentNode.scrollTop = target.offsetTop;
+ break;
+ case 40: // down arrow
+ scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
+ scope.$digest();
+ target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
+ target.parentNode.scrollTop = target.offsetTop;
+ break;
+ default:
+ if (shouldSelect) {
+ scope.$apply(function() {
+ if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
+ $$debounce(function() {
+ scope.select(scope.activeIdx, evt);
+ }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
+ } else {
+ scope.select(scope.activeIdx, evt);
+ }
+ });
+ }
+ }
+ });
+
+ element.on('focus', function (evt) {
+ hasFocus = true;
+ if (minLength === 0 && !modelCtrl.$viewValue) {
+ $timeout(function() {
+ getMatchesAsync(modelCtrl.$viewValue, evt);
+ }, 0);
+ }
+ });
+
+ element.on('blur', function(evt) {
+ if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {
+ selected = true;
+ scope.$apply(function() {
+ if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {
+ $$debounce(function() {
+ scope.select(scope.activeIdx, evt);
+ }, scope.debounceUpdate.blur);
+ } else {
+ scope.select(scope.activeIdx, evt);
+ }
+ });
+ }
+ if (!isEditable && modelCtrl.$error.editable) {
+ modelCtrl.$setViewValue();
+ scope.$apply(function() {
+ // Reset validity as we are clearing
+ modelCtrl.$setValidity('editable', true);
+ modelCtrl.$setValidity('parse', true);
+ });
+ element.val('');
+ }
+ hasFocus = false;
+ selected = false;
+ });
+
+ // Keep reference to click handler to unbind it.
+ var dismissClickHandler = function(evt) {
+ // Issue #3973
+ // Firefox treats right click as a click on document
+ if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {
+ resetMatches();
+ if (!$rootScope.$$phase) {
+ originalScope.$digest();
+ }
+ }
+ };
+
+ $document.on('click', dismissClickHandler);
+
+ originalScope.$on('$destroy', function() {
+ $document.off('click', dismissClickHandler);
+ if (appendToBody || appendTo) {
+ $popup.remove();
+ }
+
+ if (appendToBody) {
+ angular.element($window).off('resize', fireRecalculating);
+ $document.find('body').off('scroll', fireRecalculating);
+ }
+ // Prevent jQuery cache memory leak
+ popUpEl.remove();
+
+ if (showHint) {
+ inputsContainer.remove();
+ }
+ });
+
+ var $popup = $compile(popUpEl)(scope);
+
+ if (appendToBody) {
+ $document.find('body').append($popup);
+ } else if (appendTo) {
+ angular.element(appendTo).eq(0).append($popup);
+ } else {
+ element.after($popup);
+ }
+
+ this.init = function(_modelCtrl) {
+ modelCtrl = _modelCtrl;
+ ngModelOptions = extractOptions(modelCtrl);
+
+ scope.debounceUpdate = $parse(ngModelOptions.getOption('debounce'))(originalScope);
+
+ //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM
+ //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue
+ modelCtrl.$parsers.unshift(function(inputValue) {
+ hasFocus = true;
+
+ if (minLength === 0 || inputValue && inputValue.length >= minLength) {
+ if (waitTime > 0) {
+ cancelPreviousTimeout();
+ scheduleSearchWithTimeout(inputValue);
+ } else {
+ getMatchesAsync(inputValue);
+ }
+ } else {
+ isLoadingSetter(originalScope, false);
+ cancelPreviousTimeout();
+ resetMatches();
+ }
+
+ if (isEditable) {
+ return inputValue;
+ }
+
+ if (!inputValue) {
+ // Reset in case user had typed something previously.
+ modelCtrl.$setValidity('editable', true);
+ return null;
+ }
+
+ modelCtrl.$setValidity('editable', false);
+ return undefined;
+ });
+
+ modelCtrl.$formatters.push(function(modelValue) {
+ var candidateViewValue, emptyViewValue;
+ var locals = {};
+
+ // The validity may be set to false via $parsers (see above) if
+ // the model is restricted to selected values. If the model
+ // is set manually it is considered to be valid.
+ if (!isEditable) {
+ modelCtrl.$setValidity('editable', true);
+ }
+
+ if (inputFormatter) {
+ locals.$model = modelValue;
+ return inputFormatter(originalScope, locals);
+ }
+
+ //it might happen that we don't have enough info to properly render input value
+ //we need to check for this situation and simply return model value if we can't apply custom formatting
+ locals[parserResult.itemName] = modelValue;
+ candidateViewValue = parserResult.viewMapper(originalScope, locals);
+ locals[parserResult.itemName] = undefined;
+ emptyViewValue = parserResult.viewMapper(originalScope, locals);
+
+ return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;
+ });
+ };
+
+ function extractOptions(ngModelCtrl) {
+ var ngModelOptions;
+
+ if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
+ // guarantee a value
+ ngModelOptions = ngModelCtrl.$options || {};
+
+ // mimic 1.6+ api
+ ngModelOptions.getOption = function (key) {
+ return ngModelOptions[key];
+ };
+ } else { // in angular >=1.6 $options is always present
+ ngModelOptions = ngModelCtrl.$options;
+ }
+
+ return ngModelOptions;
+ }
+ }])
+
+ .directive('uibTypeahead', function() {
+ return {
+ controller: 'UibTypeaheadController',
+ require: ['ngModel', 'uibTypeahead'],
+ link: function(originalScope, element, attrs, ctrls) {
+ ctrls[1].init(ctrls[0]);
+ }
+ };
+ })
+
+ .directive('uibTypeaheadPopup', ['$$debounce', function($$debounce) {
+ return {
+ scope: {
+ matches: '=',
+ query: '=',
+ active: '=',
+ position: '&',
+ moveInProgress: '=',
+ select: '&',
+ assignIsOpen: '&',
+ debounce: '&'
+ },
+ replace: true,
+ templateUrl: function(element, attrs) {
+ return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';
+ },
+ link: function(scope, element, attrs) {
+ scope.templateUrl = attrs.templateUrl;
+
+ scope.isOpen = function() {
+ var isDropdownOpen = scope.matches.length > 0;
+ scope.assignIsOpen({ isOpen: isDropdownOpen });
+ return isDropdownOpen;
+ };
+
+ scope.isActive = function(matchIdx) {
+ return scope.active === matchIdx;
+ };
+
+ scope.selectActive = function(matchIdx) {
+ scope.active = matchIdx;
+ };
+
+ scope.selectMatch = function(activeIdx, evt) {
+ var debounce = scope.debounce();
+ if (angular.isNumber(debounce) || angular.isObject(debounce)) {
+ $$debounce(function() {
+ scope.select({activeIdx: activeIdx, evt: evt});
+ }, angular.isNumber(debounce) ? debounce : debounce['default']);
+ } else {
+ scope.select({activeIdx: activeIdx, evt: evt});
+ }
+ };
+ }
+ };
+ }])
+
+ .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {
+ return {
+ scope: {
+ index: '=',
+ match: '=',
+ query: '='
+ },
+ link: function(scope, element, attrs) {
+ var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';
+ $templateRequest(tplUrl).then(function(tplContent) {
+ var tplEl = angular.element(tplContent.trim());
+ element.replaceWith(tplEl);
+ $compile(tplEl)(scope);
+ });
+ }
+ };
+ }])
+
+ .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {
+ var isSanitizePresent;
+ isSanitizePresent = $injector.has('$sanitize');
+
+ function escapeRegexp(queryToEscape) {
+ // Regex: capture the whole query string and replace it with the string that will be used to match
+ // the results, for example if the capture is "a" the result will be \a
+ return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
+ }
+
+ function containsHtml(matchItem) {
+ return /<.*>/g.test(matchItem);
+ }
+
+ return function(matchItem, query) {
+ if (!isSanitizePresent && containsHtml(matchItem)) {
+ $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger
+ }
+ matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a "strong" tag
+ if (!isSanitizePresent) {
+ matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive
+ }
+ return matchItem;
+ };
+ }]);
+angular.module('ui.bootstrap.carousel').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });
+angular.module('ui.bootstrap.datepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });
+angular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });
+angular.module('ui.bootstrap.datepickerPopup').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
+angular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
+angular.module('ui.bootstrap.timepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
+angular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.min.js
new file mode 100644
index 00000000..db7fad7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-bootstrap/ui-bootstrap.min.js
@@ -0,0 +1,10 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 2.5.0 - 2017-01-28
+ * License: MIT
+ */angular.module("ui.bootstrap",["ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$q","$parse","$injector",function(a,b,c,d){var e=d.has("$animateCss")?d.get("$animateCss"):null;return{link:function(d,f,g){function h(){r=!!("horizontal"in g),r?(s={width:""},t={width:"0"}):(s={height:""},t={height:"0"}),d.$eval(g.uibCollapse)||f.addClass("in").addClass("collapse").attr("aria-expanded",!0).attr("aria-hidden",!1).css(s)}function i(a){return r?{width:a.scrollWidth+"px"}:{height:a.scrollHeight+"px"}}function j(){f.hasClass("collapse")&&f.hasClass("in")||b.resolve(n(d)).then(function(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"in",easing:"ease",css:{overflow:"hidden"},to:i(f[0])}).start()["finally"](k):a.addClass(f,"in",{css:{overflow:"hidden"},to:i(f[0])}).then(k)},angular.noop)}function k(){f.removeClass("collapsing").addClass("collapse").css(s),o(d)}function l(){return f.hasClass("collapse")||f.hasClass("in")?void b.resolve(p(d)).then(function(){f.css(i(f[0])).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),e?e(f,{removeClass:"in",to:t}).start()["finally"](m):a.removeClass(f,"in",{to:t}).then(m)},angular.noop):m()}function m(){f.css(t),f.removeClass("collapsing").addClass("collapse"),q(d)}var n=c(g.expanding),o=c(g.expanded),p=c(g.collapsing),q=c(g.collapsed),r=!1,s={},t={};h(),d.$watch(g.uibCollapse,function(a){a?l():j()})}}}]),angular.module("ui.bootstrap.tabindex",[]).directive("uibTabindexToggle",function(){return{restrict:"A",link:function(a,b,c){c.$observe("disabled",function(a){c.$set("tabindex",a?-1:null)})}}}),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse","ui.bootstrap.tabindex"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion-group.html"},scope:{heading:"@",panelClass:"@?",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){b.addClass("panel"),d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass||"panel-default",a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)};var e="accordiongroup-"+a.$id+"-"+Math.floor(1e4*Math.random());a.headingId=e+"-tab",a.panelId=e+"-panel"}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){function a(){return"uib-accordion-header,data-uib-accordion-header,x-uib-accordion-header,uib\\:accordion-header,[uib-accordion-header],[data-uib-accordion-header],[x-uib-accordion-header]"}return{require:"^uibAccordionGroup",link:function(b,c,d,e){b.$watch(function(){return e[d.uibAccordionTransclude]},function(b){if(b){var d=angular.element(c[0].querySelector(a()));d.html(""),d.append(b)}})}}}),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$element","$attrs","$interpolate","$timeout",function(a,b,c,d,e){a.closeable=!!c.close,b.addClass("alert"),c.$set("role","alert"),a.closeable&&b.addClass("alert-dismissible");var f=angular.isDefined(c.dismissOnTimeout)?d(c.dismissOnTimeout)(a.$parent):null;f&&e(function(){a.close()},parseInt(f,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/alert/alert.html"},transclude:!0,scope:{close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",["$parse",function(a){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(b,c,d,e){var f=e[0],g=e[1],h=a(d.uibUncheckable);c.find("input").css({display:"none"}),g.$render=function(){c.toggleClass(f.activeClass,angular.equals(g.$modelValue,b.$eval(d.uibBtnRadio)))},c.on(f.toggleEvent,function(){if(!d.disabled){var a=c.hasClass(f.activeClass);a&&!angular.isDefined(d.uncheckable)||b.$apply(function(){g.$setViewValue(a?null:b.$eval(d.uibBtnRadio)),g.$render()})}}),d.uibUncheckable&&b.$watch(h,function(a){d.$set("uncheckable",a?"":void 0)})}}}]).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$timeout","$animate",function(a,b,c,d,e){function f(a){for(var b=0;b<p.length;b++)p[b].slide.active=b===a}function g(c,d,g){if(!s){if(angular.extend(c,{direction:g}),angular.extend(p[r].slide||{},{direction:g}),e.enabled(b)&&!a.$currentTransition&&p[d].element&&o.slides.length>1){p[d].element.data(q,c.direction);var h=o.getCurrentIndex();angular.isNumber(h)&&p[h].element&&p[h].element.data(q,c.direction),a.$currentTransition=!0,e.on("addClass",p[d].element,function(b,c){"close"===c&&(a.$currentTransition=null,e.off("addClass",b))})}a.active=c.index,r=c.index,f(d),k()}}function h(a){for(var b=0;b<p.length;b++)if(p[b].slide===a)return b}function i(){m&&(c.cancel(m),m=null)}function j(b){b.length||(a.$currentTransition=null)}function k(){i();var b=+a.interval;!isNaN(b)&&b>0&&(m=c(l,b))}function l(){var b=+a.interval;n&&!isNaN(b)&&b>0&&p.length?a.next():a.pause()}var m,n,o=this,p=o.slides=a.slides=[],q="uib-slideDirection",r=a.active,s=!1;b.addClass("carousel"),o.addSlide=function(b,c){p.push({slide:b,element:c}),p.sort(function(a,b){return+a.slide.index-+b.slide.index}),(b.index===a.active||1===p.length&&!angular.isNumber(a.active))&&(a.$currentTransition&&(a.$currentTransition=null),r=b.index,a.active=b.index,f(r),o.select(p[h(b)]),1===p.length&&a.play())},o.getCurrentIndex=function(){for(var a=0;a<p.length;a++)if(p[a].slide.index===r)return a},o.next=a.next=function(){var b=(o.getCurrentIndex()+1)%p.length;return 0===b&&a.noWrap()?void a.pause():o.select(p[b],"next")},o.prev=a.prev=function(){var b=o.getCurrentIndex()-1<0?p.length-1:o.getCurrentIndex()-1;return a.noWrap()&&b===p.length-1?void a.pause():o.select(p[b],"prev")},o.removeSlide=function(b){var c=h(b);p.splice(c,1),p.length>0&&r===c?c>=p.length?(r=p.length-1,a.active=r,f(r),o.select(p[p.length-1])):(r=c,a.active=r,f(r),o.select(p[c])):r>c&&(r--,a.active=r),0===p.length&&(r=null,a.active=null)},o.select=a.select=function(b,c){var d=h(b.slide);void 0===c&&(c=d>o.getCurrentIndex()?"next":"prev"),b.slide.index===r||a.$currentTransition||g(b.slide,d,c)},a.indexOfSlide=function(a){return+a.slide.index},a.isActive=function(b){return a.active===b.slide.index},a.isPrevDisabled=function(){return 0===a.active&&a.noWrap()},a.isNextDisabled=function(){return a.active===p.length-1&&a.noWrap()},a.pause=function(){a.noPause||(n=!1,i())},a.play=function(){n||(n=!0,k())},b.on("mouseenter",a.pause),b.on("mouseleave",a.play),a.$on("$destroy",function(){s=!0,i()}),a.$watch("noTransition",function(a){e.enabled(b,!a)}),a.$watch("interval",k),a.$watchCollection("slides",j),a.$watch("active",function(a){if(angular.isNumber(a)&&r!==a){for(var b=0;b<p.length;b++)if(p[b].slide.index===a){a=b;break}var c=p[a];c&&(f(a),o.select(p[a]),r=a)}})}]).directive("uibCarousel",function(){return{transclude:!0,controller:"UibCarouselController",controllerAs:"carousel",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/carousel.html"},scope:{active:"=",interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}).directive("uibSlide",["$animate",function(a){return{require:"^uibCarousel",restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/slide.html"},scope:{actual:"=?",index:"=?"},link:function(b,c,d,e){c.addClass("item"),e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(b){a[b?"addClass":"removeClass"](c,"active")})}}}]).animation(".item",["$animateCss",function(a){function b(a,b,c){a.removeClass(b),c&&c()}var c="uib-slideDirection";return{beforeAddClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i+" "+h,f);return d.addClass(h),a(d,{addClass:i}).start().done(j),function(){g=!0}}f()},beforeRemoveClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i,f);return a(d,{addClass:i}).start().done(j),function(){g=!0}}f()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","dateFilter","orderByFilter","filterFilter",function(a,b,c,d,e){function f(a){return e(s,{key:a},!0)[0]}function g(a){var b=[],c=a.split(""),e=a.indexOf("'");if(e>-1){var f=!1;a=a.split("");for(var g=e;g<a.length;g++)f?("'"===a[g]&&(g+1<a.length&&"'"===a[g+1]?(a[g+1]="$",c[g+1]=""):(c[g]="",f=!1)),a[g]="$"):"'"===a[g]&&(a[g]="$",c[g]="",f=!0);a=a.join("")}return angular.forEach(s,function(d){var e=a.indexOf(d.key);if(e>-1){a=a.split(""),c[e]="("+d.regex+")",a[e]="$";for(var f=e+1,g=e+d.key.length;g>f;f++)c[f]="",a[f]="$";a=a.join(""),b.push({index:e,key:d.key,apply:d.apply,matcher:d.regex})}}),{regex:new RegExp("^"+c.join("")+"$"),map:d(b,"index")}}function h(a){for(var b,c,d=[],e=0;e<a.length;)if(angular.isNumber(c)){if("'"===a.charAt(e))(e+1>=a.length||"'"!==a.charAt(e+1))&&(d.push(i(a,c,e)),c=null);else if(e===a.length)for(;c<a.length;)b=j(a,c),d.push(b),c=b.endIdx;e++}else"'"!==a.charAt(e)?(b=j(a,e),d.push(b.parser),e=b.endIdx):(c=e,e++);return d}function i(a,b,c){return function(){return a.substr(b+1,c-b-1)}}function j(a,b){for(var c=a.substr(b),d=0;d<s.length;d++)if(new RegExp("^"+s[d].key).test(c)){var e=s[d];return{endIdx:b+e.key.length,parser:e.formatter}}return{endIdx:b+1,parser:function(){return c.charAt(0)}}}function k(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}function l(a){return parseInt(a,10)}function m(a,b){return a&&b?q(a,b):a}function n(a,b){return a&&b?q(a,b,!0):a}function o(a,b){a=a.replace(/:/g,"");var c=Date.parse("Jan 01, 1970 00:00:00 "+a)/6e4;return isNaN(c)?b:c}function p(a,b){return a=new Date(a.getTime()),a.setMinutes(a.getMinutes()+b),a}function q(a,b,c){c=c?-1:1;var d=a.getTimezoneOffset(),e=o(b,d);return p(a,c*(e-d))}var r,s,t=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){r=b.id,this.parsers={},this.formatters={},s=[{key:"yyyy",regex:"\\d{4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yyyy")}},{key:"yy",regex:"\\d{2}",apply:function(a){a=+a,this.year=69>a?a+2e3:a+1900},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yy")}},{key:"y",regex:"\\d{1,4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"y")}},{key:"M!",regex:"0?[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){var b=a.getMonth();return/^[0-9]$/.test(b)?c(a,"MM"):c(a,"M")}},{key:"MMMM",regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)},formatter:function(a){return c(a,"MMMM")}},{key:"MMM",regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)},formatter:function(a){return c(a,"MMM")}},{key:"MM",regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"MM")}},{key:"M",regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"M")}},{key:"d!",regex:"[0-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){var b=a.getDate();return/^[1-9]$/.test(b)?c(a,"dd"):c(a,"d")}},{key:"dd",regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"dd")}},{key:"d",regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"d")}},{key:"EEEE",regex:b.DATETIME_FORMATS.DAY.join("|"),formatter:function(a){return c(a,"EEEE")}},{key:"EEE",regex:b.DATETIME_FORMATS.SHORTDAY.join("|"),formatter:function(a){return c(a,"EEE")}},{key:"HH",regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"HH")}},{key:"hh",regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"hh")}},{key:"H",regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"H")}},{key:"h",regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"h")}},{key:"mm",regex:"[0-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"mm")}},{key:"m",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"m")}},{key:"sss",regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a},formatter:function(a){return c(a,"sss")}},{key:"ss",regex:"[0-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"ss")}},{key:"s",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"s")}},{key:"a",regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)},formatter:function(a){return c(a,"a")}},{key:"Z",regex:"[+-]\\d{4}",apply:function(a){var b=a.match(/([+-])(\d{2})(\d{2})/),c=b[1],d=b[2],e=b[3];this.hours+=l(c+d),this.minutes+=l(c+e)},formatter:function(a){return c(a,"Z")}},{key:"ww",regex:"[0-4][0-9]|5[0-3]",formatter:function(a){return c(a,"ww")}},{key:"w",regex:"[0-9]|[1-4][0-9]|5[0-3]",formatter:function(a){return c(a,"w")}},{key:"GGGG",regex:b.DATETIME_FORMATS.ERANAMES.join("|").replace(/\s/g,"\\s"),formatter:function(a){return c(a,"GGGG")}},{key:"GGG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GGG")}},{key:"GG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GG")}},{key:"G",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"G")}}],angular.version.major>=1&&angular.version.minor>4&&s.push({key:"LLLL",regex:b.DATETIME_FORMATS.STANDALONEMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.STANDALONEMONTH.indexOf(a)},formatter:function(a){return c(a,"LLLL")}})},this.init(),this.getParser=function(a){var b=f(a);return b&&b.apply||null},this.overrideParser=function(a,b){var c=f(a);c&&angular.isFunction(b)&&(this.parsers={},c.apply=b)}.bind(this),this.filter=function(a,c){if(!angular.isDate(a)||isNaN(a)||!c)return"";c=b.DATETIME_FORMATS[c]||c,b.id!==r&&this.init(),this.formatters[c]||(this.formatters[c]=h(c));var d=this.formatters[c];return d.reduce(function(b,c){return b+c(a)},"")},this.parse=function(c,d,e){if(!angular.isString(c)||!d)return c;d=b.DATETIME_FORMATS[d]||d,d=d.replace(t,"\\$&"),b.id!==r&&this.init(),this.parsers[d]||(this.parsers[d]=g(d,"apply"));var f=this.parsers[d],h=f.regex,i=f.map,j=c.match(h),l=!1;if(j&&j.length){var m,n;angular.isDate(e)&&!isNaN(e.getTime())?m={year:e.getFullYear(),month:e.getMonth(),date:e.getDate(),hours:e.getHours(),minutes:e.getMinutes(),seconds:e.getSeconds(),milliseconds:e.getMilliseconds()}:(e&&a.warn("dateparser:","baseDate is not a valid date"),m={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var o=1,p=j.length;p>o;o++){var q=i[o-1];"Z"===q.matcher&&(l=!0),q.apply&&q.apply.call(m,j[o])}var s=l?Date.prototype.setUTCFullYear:Date.prototype.setFullYear,u=l?Date.prototype.setUTCHours:Date.prototype.setHours;return k(m.year,m.month,m.date)&&(!angular.isDate(e)||isNaN(e.getTime())||l?(n=new Date(0),s.call(n,m.year,m.month,m.date),u.call(n,m.hours||0,m.minutes||0,m.seconds||0,m.milliseconds||0)):(n=new Date(e),s.call(n,m.year,m.month,m.date),u.call(n,m.hours,m.minutes,m.seconds,m.milliseconds))),n}},this.toTimezone=m,this.fromTimezone=n,this.timezoneToOffset=o,this.addDateMinutes=p,this.convertTimezoneToLocal=q}]),angular.module("ui.bootstrap.isClass",[]).directive("uibIsClass",["$animate",function(a){var b=/^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/,c=/^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;return{restrict:"A",compile:function(d,e){function f(a,b,c){i.push(a),j.push({scope:a,element:b}),o.forEach(function(b,c){g(b,a)}),a.$on("$destroy",h)}function g(b,d){var e=b.match(c),f=d.$eval(e[1]),g=e[2],h=k[b];if(!h){var i=function(b){var c=null;j.some(function(a){var d=a.scope.$eval(m);return d===b?(c=a,!0):void 0}),h.lastActivated!==c&&(h.lastActivated&&a.removeClass(h.lastActivated.element,f),c&&a.addClass(c.element,f),h.lastActivated=c)};k[b]=h={lastActivated:null,scope:d,watchFn:i,compareWithExp:g,watcher:d.$watch(g,i)}}h.watchFn(d.$eval(g))}function h(a){var b=a.targetScope,c=i.indexOf(b);if(i.splice(c,1),j.splice(c,1),i.length){var d=i[0];angular.forEach(k,function(a){a.scope===b&&(a.watcher=d.$watch(a.compareWithExp,a.watchFn),a.scope=d)})}else k={}}var i=[],j=[],k={},l=e.uibIsClass.match(b),m=l[2],n=l[1],o=n.split(",");return f}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.isClass"]).value("$datepickerSuppressError",!1).value("$datepickerLiteralWarning",!0).constant("uibDatepickerConfig",{datepickerMode:"day",formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",maxDate:null,maxMode:"year",minDate:null,minMode:"day",monthColumns:3,ngModelOptions:{},shortcutPropagation:!1,showWeeks:!0,yearColumns:5,yearRows:4}).controller("UibDatepickerController",["$scope","$element","$attrs","$parse","$interpolate","$locale","$log","dateFilter","uibDatepickerConfig","$datepickerLiteralWarning","$datepickerSuppressError","uibDateParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(b){a.datepickerMode=b,a.datepickerOptions.datepickerMode=b}function n(b){var c;if(angular.version.minor<6)c=b.$options||a.datepickerOptions.ngModelOptions||i.ngModelOptions||{},c.getOption=function(a){return c[a]};else{var d=b.$options.getOption("timezone")||(a.datepickerOptions.ngModelOptions?a.datepickerOptions.ngModelOptions.timezone:null)||(i.ngModelOptions?i.ngModelOptions.timezone:null);c=b.$options.createChild(i.ngModelOptions).createChild(a.datepickerOptions.ngModelOptions).createChild(b.$options).createChild({timezone:d})}return c}var o=this,p={$setViewValue:angular.noop},q={},r=[];b.addClass("uib-datepicker"),c.$set("role","application"),a.datepickerOptions||(a.datepickerOptions={}),this.modes=["day","month","year"],["customClass","dateDisabled","datepickerMode","formatDay","formatDayHeader","formatDayTitle","formatMonth","formatMonthTitle","formatYear","maxDate","maxMode","minDate","minMode","monthColumns","showWeeks","shortcutPropagation","startingDay","yearColumns","yearRows"].forEach(function(b){switch(b){case"customClass":case"dateDisabled":a[b]=a.datepickerOptions[b]||angular.noop;break;case"datepickerMode":a.datepickerMode=angular.isDefined(a.datepickerOptions.datepickerMode)?a.datepickerOptions.datepickerMode:i.datepickerMode;break;case"formatDay":case"formatDayHeader":case"formatDayTitle":case"formatMonth":case"formatMonthTitle":case"formatYear":o[b]=angular.isDefined(a.datepickerOptions[b])?e(a.datepickerOptions[b])(a.$parent):i[b];break;case"monthColumns":case"showWeeks":case"shortcutPropagation":case"yearColumns":case"yearRows":o[b]=angular.isDefined(a.datepickerOptions[b])?a.datepickerOptions[b]:i[b];break;case"startingDay":angular.isDefined(a.datepickerOptions.startingDay)?o.startingDay=a.datepickerOptions.startingDay:angular.isNumber(i.startingDay)?o.startingDay=i.startingDay:o.startingDay=(f.DATETIME_FORMATS.FIRSTDAYOFWEEK+8)%7;break;case"maxDate":case"minDate":a.$watch("datepickerOptions."+b,function(a){a?angular.isDate(a)?o[b]=l.fromTimezone(new Date(a),q.getOption("timezone")):(j&&g.warn("Literal date support has been deprecated, please switch to date object usage"),o[b]=new Date(h(a,"medium"))):o[b]=i[b]?l.fromTimezone(new Date(i[b]),q.getOption("timezone")):null,o.refreshView()});break;case"maxMode":case"minMode":a.datepickerOptions[b]?a.$watch(function(){return a.datepickerOptions[b]},function(c){o[b]=a[b]=angular.isDefined(c)?c:a.datepickerOptions[b],("minMode"===b&&o.modes.indexOf(a.datepickerOptions.datepickerMode)<o.modes.indexOf(o[b])||"maxMode"===b&&o.modes.indexOf(a.datepickerOptions.datepickerMode)>o.modes.indexOf(o[b]))&&(a.datepickerMode=o[b],a.datepickerOptions.datepickerMode=o[b])}):o[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&r.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,o.refreshView()})),a.isActive=function(b){return 0===o.compare(b.date,o.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(b){p=b,q=n(p),a.datepickerOptions.initDate?(o.activeDate=l.fromTimezone(a.datepickerOptions.initDate,q.getOption("timezone"))||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(p.$isEmpty(p.$modelValue)||p.$invalid)&&(o.activeDate=l.fromTimezone(a,q.getOption("timezone")),o.refreshView())})):o.activeDate=new Date;var c=p.$modelValue?new Date(p.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,q.getOption("timezone")):l.fromTimezone(c,q.getOption("timezone")),p.$render=function(){o.render()}},this.render=function(){if(p.$viewValue){var a=new Date(p.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,q.getOption("timezone")):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=p.$viewValue?new Date(p.$viewValue):null;b=l.fromTimezone(b,q.getOption("timezone")),p.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=p.$viewValue?new Date(p.$viewValue):null;d=l.fromTimezone(d,q.getOption("timezone"));var e=new Date;e=l.fromTimezone(e,q.getOption("timezone"));var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:0>f,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),o.activeDate&&0===this.compare(g.date,o.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===o.minMode){var c=p.$viewValue?l.fromTimezone(new Date(p.$viewValue),q.getOption("timezone")):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,q.getOption("timezone")),p.$setViewValue(c),p.$render()}else o.activeDate=b,m(o.modes[o.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=o.activeDate.getFullYear()+a*(o.step.years||0),c=o.activeDate.getMonth()+a*(o.step.months||0);o.activeDate.setFullYear(b,c,1),o.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===o.maxMode&&1===b||a.datepickerMode===o.minMode&&-1===b||(m(o.modes[o.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var s=function(){o.element[0].focus()};a.$on("uib:datepicker.focus",s),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),o.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(o.isDisabled(o.activeDate))return;a.select(o.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(o.handleKeyDown(c,b),o.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;r.length;)r.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(this.activeDate);f.setFullYear(b,d,1);var g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate()),d=new Date(b.getFullYear(),b.getMonth(),b.getDate());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(this.activeDate),b.setFullYear(e,f,1),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,this.monthColumns),a.yearHeaderColspan=this.monthColumns>3?this.monthColumns-2:1},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth()),d=new Date(b.getFullYear(),b.getMonth());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=this.monthColumns;else if("right"===a)c+=1;else if("down"===a)c+=this.monthColumns;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/f,10)*f+1}var e,f;this.element=b,this.yearpickerInit=function(){e=this.yearColumns,f=this.yearRows*e,this.step={years:f}},this._refreshView=function(){for(var b,c=new Array(f),g=0,h=d(this.activeDate.getFullYear());f>g;g++)b=new Date(this.activeDate),b.setFullYear(h+g,0,1),c[g]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+g});a.title=[c[0].label,c[f-1].label].join(" - "),a.rows=this.split(c,e),a.columns=e},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=e:"right"===a?c+=1:"down"===a?c+=e:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*f:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+f-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/datepicker.html"},scope:{datepickerOptions:"=?"},require:["uibDatepicker","^ngModel"],restrict:"A",controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/day.html"},require:["^uibDatepicker","uibDaypicker"],restrict:"A",controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/month.html"},require:["^uibDatepicker","uibMonthpicker"],restrict:"A",controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/year.html"},require:["^uibDatepicker","uibYearpicker"],restrict:"A",controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){var c,d,e={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},f={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},g=/(HTML|BODY)/;return{getRawNode:function(a){return a.nodeName?a:a[0]||a},parseStyle:function(a){return a=parseFloat(a),
+isFinite(a)?a:0},offsetParent:function(c){function d(a){return"static"===(b.getComputedStyle(a).position||"static")}c=this.getRawNode(c);for(var e=c.offsetParent||a[0].documentElement;e&&e!==a[0].documentElement&&d(e);)e=e.offsetParent;return e||a[0].documentElement},scrollbarWidth:function(e){if(e){if(angular.isUndefined(d)){var f=a.find("body");f.addClass("uib-position-body-scrollbar-measure"),d=b.innerWidth-f[0].clientWidth,d=isFinite(d)?d:0,f.removeClass("uib-position-body-scrollbar-measure")}return d}if(angular.isUndefined(c)){var g=angular.element('<div class="uib-position-scrollbar-measure"></div>');a.find("body").append(g),c=g[0].offsetWidth-g[0].clientWidth,c=isFinite(c)?c:0,g.remove()}return c},scrollbarPadding:function(a){a=this.getRawNode(a);var c=b.getComputedStyle(a),d=this.parseStyle(c.paddingRight),e=this.parseStyle(c.paddingBottom),f=this.scrollParent(a,!1,!0),h=this.scrollbarWidth(g.test(f.tagName));return{scrollbarWidth:h,widthOverflow:f.scrollWidth>f.clientWidth,right:d+h,originalRight:d,heightOverflow:f.scrollHeight>f.clientHeight,bottom:e+h,originalBottom:e}},isScrollable:function(a,c){a=this.getRawNode(a);var d=c?e.hidden:e.normal,f=b.getComputedStyle(a);return d.test(f.overflow+f.overflowY+f.overflowX)},scrollParent:function(c,d,f){c=this.getRawNode(c);var g=d?e.hidden:e.normal,h=a[0].documentElement,i=b.getComputedStyle(c);if(f&&g.test(i.overflow+i.overflowY+i.overflowX))return c;var j="absolute"===i.position,k=c.parentElement||h;if(k===h||"fixed"===i.position)return h;for(;k.parentElement&&k!==h;){var l=b.getComputedStyle(k);if(j&&"static"!==l.position&&(j=!1),!j&&g.test(l.overflow+l.overflowY+l.overflowX))break;k=k.parentElement}return k},position:function(c,d){c=this.getRawNode(c);var e=this.offset(c);if(d){var f=b.getComputedStyle(c);e.top-=this.parseStyle(f.marginTop),e.left-=this.parseStyle(f.marginLeft)}var g=this.offsetParent(c),h={top:0,left:0};return g!==a[0].documentElement&&(h=this.offset(g),h.top+=g.clientTop-g.scrollTop,h.left+=g.clientLeft-g.scrollLeft),{width:Math.round(angular.isNumber(e.width)?e.width:c.offsetWidth),height:Math.round(angular.isNumber(e.height)?e.height:c.offsetHeight),top:Math.round(e.top-h.top),left:Math.round(e.left-h.left)}},offset:function(c){c=this.getRawNode(c);var d=c.getBoundingClientRect();return{width:Math.round(angular.isNumber(d.width)?d.width:c.offsetWidth),height:Math.round(angular.isNumber(d.height)?d.height:c.offsetHeight),top:Math.round(d.top+(b.pageYOffset||a[0].documentElement.scrollTop)),left:Math.round(d.left+(b.pageXOffset||a[0].documentElement.scrollLeft))}},viewportOffset:function(c,d,e){c=this.getRawNode(c),e=e!==!1;var f=c.getBoundingClientRect(),g={top:0,left:0,bottom:0,right:0},h=d?a[0].documentElement:this.scrollParent(c),i=h.getBoundingClientRect();if(g.top=i.top+h.clientTop,g.left=i.left+h.clientLeft,h===a[0].documentElement&&(g.top+=b.pageYOffset,g.left+=b.pageXOffset),g.bottom=g.top+h.clientHeight,g.right=g.left+h.clientWidth,e){var j=b.getComputedStyle(h);g.top+=this.parseStyle(j.paddingTop),g.bottom-=this.parseStyle(j.paddingBottom),g.left+=this.parseStyle(j.paddingLeft),g.right-=this.parseStyle(j.paddingRight)}return{top:Math.round(f.top-g.top),bottom:Math.round(g.bottom-f.bottom),left:Math.round(f.left-g.left),right:Math.round(g.right-f.right)}},parsePlacement:function(a){var b=f.auto.test(a);return b&&(a=a.replace(f.auto,"")),a=a.split("-"),a[0]=a[0]||"top",f.primary.test(a[0])||(a[0]="top"),a[1]=a[1]||"center",f.secondary.test(a[1])||(a[1]="center"),b?a[2]=!0:a[2]=!1,a},positionElements:function(a,c,d,e){a=this.getRawNode(a),c=this.getRawNode(c);var g=angular.isDefined(c.offsetWidth)?c.offsetWidth:c.prop("offsetWidth"),h=angular.isDefined(c.offsetHeight)?c.offsetHeight:c.prop("offsetHeight");d=this.parsePlacement(d);var i=e?this.offset(a):this.position(a),j={top:0,left:0,placement:""};if(d[2]){var k=this.viewportOffset(a,e),l=b.getComputedStyle(c),m={width:g+Math.round(Math.abs(this.parseStyle(l.marginLeft)+this.parseStyle(l.marginRight))),height:h+Math.round(Math.abs(this.parseStyle(l.marginTop)+this.parseStyle(l.marginBottom)))};if(d[0]="top"===d[0]&&m.height>k.top&&m.height<=k.bottom?"bottom":"bottom"===d[0]&&m.height>k.bottom&&m.height<=k.top?"top":"left"===d[0]&&m.width>k.left&&m.width<=k.right?"right":"right"===d[0]&&m.width>k.right&&m.width<=k.left?"left":d[0],d[1]="top"===d[1]&&m.height-i.height>k.bottom&&m.height-i.height<=k.top?"bottom":"bottom"===d[1]&&m.height-i.height>k.top&&m.height-i.height<=k.bottom?"top":"left"===d[1]&&m.width-i.width>k.right&&m.width-i.width<=k.left?"right":"right"===d[1]&&m.width-i.width>k.left&&m.width-i.width<=k.right?"left":d[1],"center"===d[1])if(f.vertical.test(d[0])){var n=i.width/2-g/2;k.left+n<0&&m.width-i.width<=k.right?d[1]="left":k.right+n<0&&m.width-i.width<=k.left&&(d[1]="right")}else{var o=i.height/2-m.height/2;k.top+o<0&&m.height-i.height<=k.bottom?d[1]="top":k.bottom+o<0&&m.height-i.height<=k.top&&(d[1]="bottom")}}switch(d[0]){case"top":j.top=i.top-h;break;case"bottom":j.top=i.top+i.height;break;case"left":j.left=i.left-g;break;case"right":j.left=i.left+i.width}switch(d[1]){case"top":j.top=i.top;break;case"bottom":j.top=i.top+i.height-h;break;case"left":j.left=i.left;break;case"right":j.left=i.left+i.width-g;break;case"center":f.vertical.test(d[0])?j.left=i.left+i.width/2-g/2:j.top=i.top+i.height/2-h/2}return j.top=Math.round(j.top),j.left=Math.round(j.left),j.placement="center"===d[1]?d[0]:d[0]+"-"+d[1],j},adjustTop:function(a,b,c,d){return-1!==a.indexOf("top")&&c!==d?{top:b.top-d+"px"}:void 0},positionArrow:function(a,c){a=this.getRawNode(a);var d=a.querySelector(".tooltip-inner, .popover-inner");if(d){var e=angular.element(d).hasClass("tooltip-inner"),g=e?a.querySelector(".tooltip-arrow"):a.querySelector(".arrow");if(g){var h={top:"",bottom:"",left:"",right:""};if(c=this.parsePlacement(c),"center"===c[1])return void angular.element(g).css(h);var i="border-"+c[0]+"-width",j=b.getComputedStyle(g)[i],k="border-";k+=f.vertical.test(c[0])?c[0]+"-"+c[1]:c[1]+"-"+c[0],k+="-radius";var l=b.getComputedStyle(e?d:a)[k];switch(c[0]){case"top":h.bottom=e?"0":"-"+j;break;case"bottom":h.top=e?"0":"-"+j;break;case"left":h.right=e?"0":"-"+j;break;case"right":h.left=e?"0":"-"+j}h[c[1]]=l,angular.element(g).css(h)}}}}}]),angular.module("ui.bootstrap.datepickerPopup",["ui.bootstrap.datepicker","ui.bootstrap.position"]).value("$datepickerPopupLiteralWarning",!0).constant("uibDatepickerPopupConfig",{altInputFormats:[],appendToBody:!1,clearText:"Clear",closeOnDateSelection:!0,closeText:"Done",currentText:"Today",datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"uib/template/datepickerPopup/popup.html",datepickerTemplateUrl:"uib/template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},onOpenFocus:!0,showButtonBar:!0,placement:"auto bottom-left"}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$log","$parse","$window","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout","uibDatepickerConfig","$datepickerPopupLiteralWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(b){var c=l.parse(b,x,a.date);if(isNaN(c))for(var d=0;d<J.length;d++)if(c=l.parse(b,J[d],a.date),!isNaN(c))return c;return c}function r(a){if(angular.isNumber(a)&&(a=new Date(a)),!a)return null;if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=q(a);if(!isNaN(b))return l.toTimezone(b,H.getOption("timezone"))}return H.getOption("allowInvalid")?a:void 0}function s(a,b){var d=a||b;return c.ngRequired||d?(angular.isNumber(d)&&(d=new Date(d)),d?angular.isDate(d)&&!isNaN(d)?!0:angular.isString(d)?!isNaN(q(d)):!1:!0):!0}function t(c){if(a.isOpen||!a.disabled){var d=I[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}}function u(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}function v(){if(a.isOpen){var d=angular.element(I[0].querySelector(".uib-datepicker-popup")),e=c.popupPlacement?c.popupPlacement:m.placement,f=j.positionElements(b,d,e,z);d.css({top:f.top+"px",left:f.left+"px"}),d.hasClass("uib-position-measure")&&d.removeClass("uib-position-measure")}}function w(a){var b;return angular.version.minor<6?(b=angular.isObject(a.$options)?a.$options:{timezone:null},b.getOption=function(a){return b[a]}):b=a.$options,b}var x,y,z,A,B,C,D,E,F,G,H,I,J,K=!1,L=[];this.init=function(e){if(G=e,H=w(G),y=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):m.closeOnDateSelection,z=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):m.appendToBody,A=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):m.onOpenFocus,B=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:m.datepickerPopupTemplateUrl,C=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:m.datepickerTemplateUrl,J=angular.isDefined(c.altInputFormats)?a.$parent.$eval(c.altInputFormats):m.altInputFormats,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):m.showButtonBar,m.html5Types[c.type]?(x=m.html5Types[c.type],K=!0):(x=c.uibDatepickerPopup||m.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||m.datepickerPopup;if(c!==x&&(x=c,G.$modelValue=null,!x))throw new Error("uibDatepickerPopup must have a date format specified.")})),!x)throw new Error("uibDatepickerPopup must have a date format specified.");if(K&&c.uibDatepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");D=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),D.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":B}),E=angular.element(D.children()[0]),E.attr("template-url",C),a.datepickerOptions||(a.datepickerOptions={}),K&&"month"===c.type&&(a.datepickerOptions.datepickerMode="month",a.datepickerOptions.minMode="month"),E.attr("datepicker-options","datepickerOptions"),K?G.$formatters.push(function(b){return a.date=l.fromTimezone(b,H.getOption("timezone")),b}):(G.$$parserName="date",G.$validators.date=s,G.$parsers.unshift(r),G.$formatters.push(function(b){return G.$isEmpty(b)?(a.date=b,b):(angular.isNumber(b)&&(b=new Date(b)),a.date=l.fromTimezone(b,H.getOption("timezone")),l.filter(a.date,x))})),G.$viewChangeListeners.push(function(){a.date=q(G.$viewValue)}),b.on("keydown",u),I=d(D)(a),D.remove(),z?h.find("body").append(I):b.after(I),a.$on("$destroy",function(){for(a.isOpen===!0&&(i.$$phase||a.$apply(function(){a.isOpen=!1})),I.remove(),b.off("keydown",u),h.off("click",t),F&&F.off("scroll",v),angular.element(g).off("resize",v);L.length;)L.shift()()})},a.getText=function(b){return a[b+"Text"]||m[b+"Text"]},a.isDisabled=function(b){"today"===b&&(b=l.fromTimezone(new Date,H.getOption("timezone")));var c={};return angular.forEach(["minDate","maxDate"],function(b){a.datepickerOptions[b]?angular.isDate(a.datepickerOptions[b])?c[b]=new Date(a.datepickerOptions[b]):(p&&e.warn("Literal date support has been deprecated, please switch to date object usage"),c[b]=new Date(k(a.datepickerOptions[b],"medium"))):c[b]=null}),a.datepickerOptions&&c.minDate&&a.compare(b,c.minDate)<0||c.maxDate&&a.compare(b,c.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){a.date=c;var d=a.date?l.filter(a.date,x):null;b.val(d),G.$setViewValue(d),y&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(c.stopPropagation(),a.isOpen=!1,b[0].focus())},a.select=function(b,c){if(c.stopPropagation(),"today"===b){var d=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(d.getFullYear(),d.getMonth(),d.getDate())):(b=l.fromTimezone(d,H.getOption("timezone")),b.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(c){c.stopPropagation(),a.isOpen=!1,b[0].focus()},a.disabled=angular.isDefined(c.disabled)||!1,c.ngDisabled&&L.push(a.$parent.$watch(f(c.ngDisabled),function(b){a.disabled=b})),a.$watch("isOpen",function(d){d?a.disabled?a.isOpen=!1:n(function(){v(),A&&a.$broadcast("uib:datepicker.focus"),h.on("click",t);var d=c.popupPlacement?c.popupPlacement:m.placement;z||j.parsePlacement(d)[2]?(F=F||angular.element(j.scrollParent(b)),F&&F.on("scroll",v)):F=null,angular.element(g).on("resize",v)},0,!1):(h.off("click",t),F&&F.off("scroll",v),angular.element(g).off("resize",v))}),a.$on("uib:datepicker.mode",function(){n(v,0,!1)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{datepickerOptions:"=?",isOpen:"=?",currentText:"@",clearText:"@",closeText:"@"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/datepickerPopup/popup.html"}}}),angular.module("ui.bootstrap.debounce",[]).factory("$$debounce",["$timeout",function(a){return function(b,c){var d;return function(){var e=this,f=Array.prototype.slice.call(arguments);d&&a.cancel(d),d=a(function(){b.apply(e,f)},c)}}}]),angular.module("ui.bootstrap.multiMap",[]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.multiMap","ui.bootstrap.position"]).constant("uibDropdownConfig",{appendToOpenClass:"uib-dropdown-open",openClass:"open"}).service("uibDropdownService",["$document","$rootScope","$$multiMap",function(a,b,c){var d=null,e=c.createNew();this.isOnlyOpen=function(a,b){var c=e.get(b);if(c){var d=c.reduce(function(b,c){return c.scope===a?c:b},{});if(d)return 1===c.length}return!1},this.open=function(b,c,g){if(d||a.on("click",f),d&&d!==b&&(d.isOpen=!1),d=b,g){var h=e.get(g);if(h){var i=h.map(function(a){return a.scope});-1===i.indexOf(b)&&e.put(g,{scope:b})}else e.put(g,{scope:b})}},this.close=function(b,c,g){if(d===b&&(a.off("click",f),a.off("keydown",this.keybindFilter),d=null),g){var h=e.get(g);if(h){var i=h.reduce(function(a,c){return c.scope===b?c:a},{});i&&e.remove(g,i)}}};var f=function(a){if(d&&d.isOpen&&!(a&&"disabled"===d.getAutoClose()||a&&3===a.which)){var c=d.getToggleElement();if(!(a&&c&&c[0].contains(a.target))){var e=d.getDropdownElement();a&&"outsideClick"===d.getAutoClose()&&e&&e[0].contains(a.target)||(d.focusToggleElement(),d.isOpen=!1,b.$$phase||d.$apply())}}};this.keybindFilter=function(a){if(d){var b=d.getDropdownElement(),c=d.getToggleElement(),e=b&&b[0].contains(a.target),g=c&&c[0].contains(a.target);27===a.which?(a.stopPropagation(),d.focusToggleElement(),f()):d.isKeynavEnabled()&&-1!==[38,40].indexOf(a.which)&&d.isOpen&&(e||g)&&(a.preventDefault(),a.stopPropagation(),d.focusDropdownEntry(a.which))}}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){function l(){b.append(o.dropdownMenu)}var m,n,o=this,p=a.$new(),q=e.appendToOpenClass,r=e.openClass,s=angular.noop,t=c.onToggle?d(c.onToggle):angular.noop,u=!1,v=i.find("body");b.addClass("dropdown"),this.init=function(){c.isOpen&&(n=d(c.isOpen),s=n.assign,a.$watch(n,function(a){p.isOpen=!!a})),u=angular.isDefined(c.keyboardNav)},this.toggle=function(a){return p.isOpen=arguments.length?!!a:!p.isOpen,angular.isFunction(s)&&s(p,p.isOpen),p.isOpen},this.isOpen=function(){return p.isOpen},p.getToggleElement=function(){return o.toggleElement},p.getAutoClose=function(){return c.autoClose||"always"},p.getElement=function(){return b},p.isKeynavEnabled=function(){return u},p.focusDropdownEntry=function(a){var c=o.dropdownMenu?angular.element(o.dropdownMenu).find("a"):b.find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(o.selectedOption)?o.selectedOption=o.selectedOption===c.length-1?o.selectedOption:o.selectedOption+1:o.selectedOption=0;break;case 38:angular.isNumber(o.selectedOption)?o.selectedOption=0===o.selectedOption?0:o.selectedOption-1:o.selectedOption=c.length-1}c[o.selectedOption].focus()},p.getDropdownElement=function(){return o.dropdownMenu},p.focusToggleElement=function(){o.toggleElement&&o.toggleElement[0].focus()},p.$watch("isOpen",function(e,n){var u=null,w=!1;if(angular.isDefined(c.dropdownAppendTo)){var x=d(c.dropdownAppendTo)(p);x&&(u=angular.element(x))}if(angular.isDefined(c.dropdownAppendToBody)){var y=d(c.dropdownAppendToBody)(p);y!==!1&&(w=!0)}if(w&&!u&&(u=v),u&&o.dropdownMenu&&(e?(u.append(o.dropdownMenu),b.on("$destroy",l)):(b.off("$destroy",l),l())),u&&o.dropdownMenu){var z,A,B,C=h.positionElements(b,o.dropdownMenu,"bottom-left",!0),D=0;if(z={top:C.top+"px",display:e?"block":"none"},A=o.dropdownMenu.hasClass("dropdown-menu-right"),A?(z.left="auto",B=h.scrollbarPadding(u),B.heightOverflow&&B.scrollbarWidth&&(D=B.scrollbarWidth),z.right=window.innerWidth-D-(C.left+b.prop("offsetWidth"))+"px"):(z.left=C.left+"px",z.right="auto"),!w){var E=h.offset(u);z.top=C.top-E.top+"px",A?z.right=window.innerWidth-(C.left-E.left+b.prop("offsetWidth"))+"px":z.left=C.left-E.left+"px"}o.dropdownMenu.css(z)}var F=u?u:b,G=u?q:r,H=F.hasClass(G),I=f.isOnlyOpen(a,u);if(H===!e){var J;J=u?I?"removeClass":"addClass":e?"addClass":"removeClass",g[J](F,G).then(function(){angular.isDefined(e)&&e!==n&&t(a,{open:!!e})})}if(e)o.dropdownMenuTemplateUrl?k(o.dropdownMenuTemplateUrl).then(function(a){m=p.$new(),j(a.trim())(m,function(a){var b=a;o.dropdownMenu.replaceWith(b),o.dropdownMenu=b,i.on("keydown",f.keybindFilter)})}):i.on("keydown",f.keybindFilter),p.focusToggleElement(),f.open(p,b,u);else{if(f.close(p,b,u),o.dropdownMenuTemplateUrl){m&&m.$destroy();var K=angular.element('<ul class="dropdown-menu"></ul>');o.dropdownMenu.replaceWith(K),o.dropdownMenu=K}o.selectedOption=null}angular.isFunction(s)&&s(a,e)})}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.on("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.off("click",e)})}}}}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b===a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b===a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.pop()},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.multiMap","ui.bootstrap.stackedMap","ui.bootstrap.position"]).provider("$uibResolve",function(){var a=this;this.resolver=null,this.setResolver=function(a){this.resolver=a},this.$get=["$injector","$q",function(b,c){var d=a.resolver?b.get(a.resolver):null;return{resolve:function(a,e,f,g){if(d)return d.resolve(a,e,f,g);var h=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?h.push(c.resolve(b.invoke(a))):angular.isString(a)?h.push(c.resolve(b.get(a))):h.push(c.resolve(a))}),c.all(h).then(function(b){var c={},d=0;return angular.forEach(a,function(a,e){c[e]=b[d++]}),c})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,e){e.modalInClass&&(a.addClass(d,e.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(c,f){var g=f();b.modalOptions.animation?a.removeClass(d,e.modalInClass).then(g):g()}))}return{restrict:"A",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(a,b,c,d){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/modal/window.html"},link:function(e,f,g){f.addClass(g.windowTopClass||""),e.size=g.size,e.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",e.close),e.$isRendered=!0;var h=b.defer();e.$$postDigest(function(){h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=c(f,{addClass:g.modalInClass}).start(),e.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();c(f,{removeClass:g.modalInClass}).start().then(d)})),b.when(h).then(function(){var b=a.getTop();if(b&&a.modalRendered(b.key),!d[0].activeElement||!f[0].contains(d[0].activeElement)){var c=f[0].querySelector("[autofocus]");c?c.focus():f[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(a){return{link:function(b,c,d,e,f){f(b.$parent,function(b){c.empty(),a.enter(b,c)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(a,b,c,d,e,f,g,h,i){function j(a){var b="-";return a.replace(E,function(a,c){return(c?b:"")+a.toLowerCase()})}function k(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)}function l(){for(var a=-1,b=x.keys(),c=0;c<b.length;c++)x.get(b[c]).value.backdrop&&(a=c);return a>-1&&A>a&&(a=A),a}function m(a,b){var c=x.get(a).value,d=c.appendTo;x.remove(a),B=x.top(),B&&(A=parseInt(B.value.modalDomEl.attr("index"),10)),p(c.modalDomEl,c.modalScope,function(){var b=c.openedClass||w;y.remove(b,a);var e=y.hasKey(b);d.toggleClass(b,e),!e&&v&&v.heightOverflow&&v.scrollbarWidth&&(v.originalRight?d.css({paddingRight:v.originalRight+"px"}):d.css({paddingRight:""}),v=null),n(!0)},c.closedDeferred),o(),b&&b.focus?b.focus():d.focus&&d.focus()}function n(a){var b;x.length()>0&&(b=x.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function o(){if(t&&-1===l()){var a=u;p(t,u,function(){a=null}),t=void 0,u=void 0}}function p(b,c,d,e){function g(){g.done||(g.done=!0,a.leave(b).then(function(){d&&d(),b.remove(),e&&e.resolve()}),c.$destroy())}var h,i=null,j=function(){return h||(h=f.defer(),i=h.promise),function(){h.resolve()}};return c.$broadcast(z.NOW_CLOSING_EVENT,j),f.when(i).then(g)}function q(a){if(a.isDefaultPrevented())return a;var b=x.top();if(b)switch(a.which){case 27:b.value.keyboard&&(a.preventDefault(),e.$apply(function(){z.dismiss(b.key,"escape key press")}));break;case 9:var c=z.loadFocusElementList(b),d=!1;a.shiftKey?(z.isFocusInFirstItem(a,c)||z.isModalFocused(a,b))&&(d=z.focusLastFocusableElement(c)):z.isFocusInLastItem(a,c)&&(d=z.focusFirstFocusableElement(c)),d&&(a.preventDefault(),a.stopPropagation())}}function r(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}function s(){Array.prototype.forEach.call(document.querySelectorAll("["+C+"]"),function(a){var b=parseInt(a.getAttribute(C),10),c=b-1;a.setAttribute(C,c),c||(a.removeAttribute(C),a.removeAttribute("aria-hidden"))})}var t,u,v,w="modal-open",x=h.createNew(),y=g.createNew(),z={NOW_CLOSING_EVENT:"modal.stack.now-closing"},A=0,B=null,C="data-bootstrap-modal-aria-hidden-count",D="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",E=/[A-Z]/g;return e.$watch(l,function(a){u&&(u.index=a)}),c.on("keydown",q),e.$on("$destroy",function(){c.off("keydown",q)}),z.open=function(b,f){function g(a){function b(a){var b=a.parent()?a.parent().children():[];return Array.prototype.filter.call(b,function(b){return b!==a[0]})}if(a&&"BODY"!==a[0].tagName)return b(a).forEach(function(a){var b="true"===a.getAttribute("aria-hidden"),c=parseInt(a.getAttribute(C),10);c||(c=b?1:0),a.setAttribute(C,c+1),a.setAttribute("aria-hidden","true")}),g(a.parent())}var h=c[0].activeElement,k=f.openedClass||w;n(!1),B=x.top(),x.add(b,{deferred:f.deferred,renderDeferred:f.renderDeferred,closedDeferred:f.closedDeferred,modalScope:f.scope,backdrop:f.backdrop,keyboard:f.keyboard,openedClass:f.openedClass,windowTopClass:f.windowTopClass,animation:f.animation,appendTo:f.appendTo}),y.put(k,b);var m=f.appendTo,o=l();o>=0&&!t&&(u=e.$new(!0),u.modalOptions=f,u.index=o,t=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),t.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),f.backdropClass&&t.addClass(f.backdropClass),f.animation&&t.attr("modal-animation","true"),d(t)(u),a.enter(t,m),i.isScrollable(m)&&(v=i.scrollbarPadding(m),v.heightOverflow&&v.scrollbarWidth&&m.css({paddingRight:v.right+"px"})));var p;f.component?(p=document.createElement(j(f.component.name)),p=angular.element(p),p.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):p=f.content,A=B?parseInt(B.value.modalDomEl.attr("index"),10)+1:0;var q=angular.element('<div uib-modal-window="modal-window"></div>');q.attr({"class":"modal","template-url":f.windowTemplateUrl,"window-top-class":f.windowTopClass,role:"dialog","aria-labelledby":f.ariaLabelledBy,"aria-describedby":f.ariaDescribedBy,size:f.size,index:A,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(p),f.windowClass&&q.addClass(f.windowClass),f.animation&&q.attr("modal-animation","true"),m.addClass(k),f.scope&&(f.scope.$$topModalIndex=A),a.enter(d(q)(f.scope),m),x.top().value.modalDomEl=q,x.top().value.modalOpener=h,g(q)},z.close=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),m(a,c.value.modalOpener),!0):!c},z.dismiss=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),m(a,c.value.modalOpener),!0):!c},z.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},z.getTop=function(){return x.top()},z.modalRendered=function(a){var b=x.get(a);b&&b.value.renderDeferred.resolve()},z.focusFirstFocusableElement=function(a){return a.length>0?(a[0].focus(),!0):!1},z.focusLastFocusableElement=function(a){return a.length>0?(a[a.length-1].focus(),!0):!1},z.isModalFocused=function(a,b){if(a&&b){var c=b.value.modalDomEl;if(c&&c.length)return(a.target||a.srcElement)===c[0]}return!1},z.isFocusInFirstItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[0]:!1},z.isFocusInLastItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[b.length-1]:!1},z.loadFocusElementList=function(a){if(a){var b=a.value.modalDomEl;if(b&&b.length){var c=b[0].querySelectorAll(D);return c?Array.prototype.filter.call(c,function(a){return k(a)}):c}}},z}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?c.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}var j={},k=null;return j.getPromiseChain=function(){return k},j.open=function(e){function j(){return q}var l=c.defer(),m=c.defer(),n=c.defer(),o=c.defer(),p={result:l.promise,opened:m.promise,closed:n.promise,rendered:o.promise,close:function(a){return h.close(p,a)},dismiss:function(a){return h.dismiss(p,a)}};if(e=angular.extend({},a.options,e),e.resolve=e.resolve||{},e.appendTo=e.appendTo||d.find("body").eq(0),!e.appendTo.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");if(!e.component&&!e.template&&!e.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var q;q=e.component?c.when(g.resolve(e.resolve,{},null,null)):c.all([i(e),g.resolve(e.resolve,{},null,null)]);var r;return r=k=c.all([k]).then(j,j).then(function(a){function c(b,c,d,e){b.$scope=g,b.$scope.$resolve={},d?b.$scope.$uibModalInstance=p:b.$uibModalInstance=p;var f=c?a[1]:a;angular.forEach(f,function(a,c){e&&(b[c]=a),b.$scope.$resolve[c]=a})}var d=e.scope||b,g=d.$new();g.$close=p.close,g.$dismiss=p.dismiss,g.$on("$destroy",function(){g.$$uibDestructionScheduled||g.$dismiss("$uibUnscheduledDestruction")});var i,j,k={scope:g,deferred:l,renderDeferred:o,closedDeferred:n,animation:e.animation,backdrop:e.backdrop,keyboard:e.keyboard,backdropClass:e.backdropClass,windowTopClass:e.windowTopClass,windowClass:e.windowClass,windowTemplateUrl:e.windowTemplateUrl,ariaLabelledBy:e.ariaLabelledBy,ariaDescribedBy:e.ariaDescribedBy,size:e.size,openedClass:e.openedClass,appendTo:e.appendTo},q={},r={};e.component?(c(q,!1,!0,!1),q.name=e.component,k.component=q):e.controller&&(c(r,!0,!1,!0),j=f(e.controller,r,!0,e.controllerAs),e.controllerAs&&e.bindToController&&(i=j.instance,i.$close=g.$close,i.$dismiss=g.$dismiss,angular.extend(i,{$resolve:r.$scope.$resolve},d)),i=j(),angular.isFunction(i.$onInit)&&i.$onInit()),e.component||(k.content=a[0]),h.open(p,k),m.resolve(!0)},function(a){m.reject(a),l.reject(a)})["finally"](function(){k===r&&(k=null)}),p},j}]};return a}),angular.module("ui.bootstrap.paging",[]).factory("uibPaging",["$parse",function(a){return{create:function(b,c,d){b.setNumPages=d.numPages?a(d.numPages).assign:angular.noop,b.ngModelCtrl={$setViewValue:angular.noop},b._watchers=[],b.init=function(a,e){b.ngModelCtrl=a,b.config=e,a.$render=function(){b.render()},d.itemsPerPage?b._watchers.push(c.$parent.$watch(d.itemsPerPage,function(a){b.itemsPerPage=parseInt(a,10),c.totalPages=b.calculateTotalPages(),b.updatePage()})):b.itemsPerPage=e.itemsPerPage,c.$watch("totalItems",function(a,d){(angular.isDefined(a)||a!==d)&&(c.totalPages=b.calculateTotalPages(),b.updatePage())})},b.calculateTotalPages=function(){var a=b.itemsPerPage<1?1:Math.ceil(c.totalItems/b.itemsPerPage);return Math.max(a||0,1)},b.render=function(){c.page=parseInt(b.ngModelCtrl.$viewValue,10)||1},c.selectPage=function(a,d){d&&d.preventDefault();var e=!c.ngDisabled||!d;e&&c.page!==a&&a>0&&a<=c.totalPages&&(d&&d.target&&d.target.blur(),b.ngModelCtrl.$setViewValue(a),b.ngModelCtrl.$render())},c.getText=function(a){return c[a+"Text"]||b.config[a+"Text"]},c.noPrevious=function(){return 1===c.page},c.noNext=function(){return c.page===c.totalPages},b.updatePage=function(){b.setNumPages(c.$parent,c.totalPages),c.page>c.totalPages?c.selectPage(c.totalPages):b.ngModelCtrl.$render()},c.$on("$destroy",function(){for(;b._watchers.length;)b._watchers.shift()()})}}}]),angular.module("ui.bootstrap.pager",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPagerController",["$scope","$attrs","uibPaging","uibPagerConfig",function(a,b,c,d){
+a.align=angular.isDefined(b.align)?a.$parent.$eval(b.align):d.align,c.create(this,a,b)}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],restrict:"A",controller:"UibPagerController",controllerAs:"pager",templateUrl:function(a,b){return b.templateUrl||"uib/template/pager/pager.html"},link:function(b,c,d,e){c.addClass("pager");var f=e[0],g=e[1];g&&f.init(g,a)}}}]),angular.module("ui.bootstrap.pagination",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPaginationController",["$scope","$attrs","$parse","uibPaging","uibPaginationConfig",function(a,b,c,d,e){function f(a,b,c){return{number:a,text:b,active:c}}function g(a,b){var c=[],d=1,e=b,g=angular.isDefined(i)&&b>i;g&&(j?(d=Math.max(a-Math.floor(i/2),1),e=d+i-1,e>b&&(e=b,d=e-i+1)):(d=(Math.ceil(a/i)-1)*i+1,e=Math.min(d+i-1,b)));for(var h=d;e>=h;h++){var n=f(h,m(h),h===a);c.push(n)}if(g&&i>0&&(!j||k||l)){if(d>1){if(!l||d>3){var o=f(d-1,"...",!1);c.unshift(o)}if(l){if(3===d){var p=f(2,"2",!1);c.unshift(p)}var q=f(1,"1",!1);c.unshift(q)}}if(b>e){if(!l||b-2>e){var r=f(e+1,"...",!1);c.push(r)}if(l){if(e===b-2){var s=f(b-1,b-1,!1);c.push(s)}var t=f(b,b,!1);c.push(t)}}}return c}var h=this,i=angular.isDefined(b.maxSize)?a.$parent.$eval(b.maxSize):e.maxSize,j=angular.isDefined(b.rotate)?a.$parent.$eval(b.rotate):e.rotate,k=angular.isDefined(b.forceEllipses)?a.$parent.$eval(b.forceEllipses):e.forceEllipses,l=angular.isDefined(b.boundaryLinkNumbers)?a.$parent.$eval(b.boundaryLinkNumbers):e.boundaryLinkNumbers,m=angular.isDefined(b.pageLabel)?function(c){return a.$parent.$eval(b.pageLabel,{$page:c})}:angular.identity;a.boundaryLinks=angular.isDefined(b.boundaryLinks)?a.$parent.$eval(b.boundaryLinks):e.boundaryLinks,a.directionLinks=angular.isDefined(b.directionLinks)?a.$parent.$eval(b.directionLinks):e.directionLinks,b.$set("role","menu"),d.create(this,a,b),b.maxSize&&h._watchers.push(a.$parent.$watch(c(b.maxSize),function(a){i=parseInt(a,10),h.render()}));var n=this.render;this.render=function(){n(),a.page>0&&a.page<=a.totalPages&&(a.pages=g(a.page,a.totalPages))}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],restrict:"A",controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"uib/template/pagination/pagination.html"},link:function(a,c,d,e){c.addClass("pagination");var f=e[0],g=e[1];g&&f.init(g,b)}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",placementClassPrefix:"",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",outsideClick:"outsideClick",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){function n(a){if(27===a.which){var b=o.top();b&&(b.value.close(),b=null)}}var o=m.createNew();return h.on("keyup",n),k.$on("$destroy",function(){h.off("keyup",n)}),function(e,k,m,n){function p(a){var b=(a||n.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}n=angular.extend({},b,d,n);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup uib-title="'+r+"title"+s+'" '+(n.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'origin-scope="origScope" class="uib-position-measure '+k+'" tooltip-animation-class="fade"uib-tooltip-classes ng-class="{ in: isOpen }" ></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){P.isOpen?q():m()}function m(){O&&!a.$eval(d[k+"Enable"])||(u(),x(),P.popupDelay?H||(H=g(r,P.popupDelay,!1)):r())}function q(){s(),P.popupCloseDelay?I||(I=g(t,P.popupCloseDelay,!1)):t()}function r(){return s(),u(),P.content?(v(),void P.$evalAsync(function(){P.isOpen=!0,y(!0),U()})):angular.noop}function s(){H&&(g.cancel(H),H=null),J&&(g.cancel(J),J=null)}function t(){P&&P.$evalAsync(function(){P&&(P.isOpen=!1,y(!1),P.animation?G||(G=g(w,150,!1)):w())})}function u(){I&&(g.cancel(I),I=null),G&&(g.cancel(G),G=null)}function v(){E||(F=P.$new(),E=c(F,function(a){M?h.find("body").append(a):b.after(a)}),o.add(P,{close:t}),z())}function w(){s(),u(),A(),E&&(E.remove(),E=null,K&&g.cancel(K)),o.remove(P),F&&(F.$destroy(),F=null)}function x(){P.title=d[k+"Title"],S?P.content=S(a):P.content=d[e],P.popupClass=d[k+"Class"],P.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:n.placement;var b=i.parsePlacement(P.placement);L=b[1]?b[0]+"-"+b[1]:b[0];var c=parseInt(d[k+"PopupDelay"],10),f=parseInt(d[k+"PopupCloseDelay"],10);P.popupDelay=isNaN(c)?n.popupDelay:c,P.popupCloseDelay=isNaN(f)?n.popupCloseDelay:f}function y(b){R&&angular.isFunction(R.assign)&&R.assign(a,b)}function z(){T.length=0,S?(T.push(a.$watch(S,function(a){P.content=a,!a&&P.isOpen&&t()})),T.push(F.$watch(function(){Q||(Q=!0,F.$$postDigest(function(){Q=!1,P&&P.isOpen&&U()}))}))):T.push(d.$observe(e,function(a){P.content=a,!a&&P.isOpen?t():U()})),T.push(d.$observe(k+"Title",function(a){P.title=a,P.isOpen&&U()})),T.push(d.$observe(k+"Placement",function(a){P.placement=a?a:n.placement,P.isOpen&&U()}))}function A(){T.length&&(angular.forEach(T,function(a){a()}),T.length=0)}function B(a){P&&P.isOpen&&E&&(b[0].contains(a.target)||E[0].contains(a.target)||q())}function C(a){27===a.which&&q()}function D(){var c=[],e=[],f=a.$eval(d[k+"Trigger"]);V(),angular.isObject(f)?(Object.keys(f).forEach(function(a){c.push(a),e.push(f[a])}),N={show:c,hide:e}):N=p(f),"none"!==N.show&&N.show.forEach(function(a,c){"outsideClick"===a?(b.on("click",j),h.on("click",B)):a===N.hide[c]?b.on(a,j):a&&(b.on(a,m),b.on(N.hide[c],q)),b.on("keypress",C)})}var E,F,G,H,I,J,K,L,M=angular.isDefined(n.appendToBody)?n.appendToBody:!1,N=p(void 0),O=angular.isDefined(d[k+"Enable"]),P=a.$new(!0),Q=!1,R=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,S=n.useContentExp?l(d[e]):!1,T=[],U=function(){E&&E.html()&&(J||(J=g(function(){var a=i.positionElements(b,E,P.placement,M),c=angular.isDefined(E.offsetHeight)?E.offsetHeight:E.prop("offsetHeight"),d=M?i.offset(b):i.position(b);E.css({top:a.top+"px",left:a.left+"px"});var e=a.placement.split("-");E.hasClass(e[0])||(E.removeClass(L.split("-")[0]),E.addClass(e[0])),E.hasClass(n.placementClassPrefix+a.placement)||(E.removeClass(n.placementClassPrefix+L),E.addClass(n.placementClassPrefix+a.placement)),K=g(function(){var a=angular.isDefined(E.offsetHeight)?E.offsetHeight:E.prop("offsetHeight"),b=i.adjustTop(e,d,c,a);b&&E.css(b),K=null},0,!1),E.hasClass("uib-position-measure")?(i.positionArrow(E,a.placement),E.removeClass("uib-position-measure")):L!==a.placement&&i.positionArrow(E,a.placement),L=a.placement,J=null},0,!1)))};P.origScope=a,P.isOpen=!1,P.contentExp=function(){return P.content},d.$observe("disabled",function(a){a&&s(),a&&P.isOpen&&t()}),R&&a.$watch(R,function(a){P&&!a===P.isOpen&&j()});var V=function(){N.show.forEach(function(a){"outsideClick"===a?b.off("click",j):(b.off(a,m),b.off(a,j)),b.off("keypress",C)}),N.hide.forEach(function(a){"outsideClick"===a?h.off("click",B):b.off(a,q)})};D();var W=a.$eval(d[k+"Animation"]);P.animation=angular.isDefined(W)?!!W:n.animation;var X,Y=k+"AppendToBody";X=Y in d&&void 0===d[Y]?!0:a.$eval(d[Y]),M=angular.isDefined(X)?X:M,a.$on("$destroy",function(){V(),w(),P=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",["$uibPosition",function(a){return{restrict:"A",link:function(b,c,d){if(b.placement){var e=a.parsePlacement(b.placement);c.addClass(e[0])}b.popupClass&&c.addClass(b.popupClass),b.animation&&c.addClass(d.tooltipAnimationClass)}}}]).directive("uibTooltipPopup",function(){return{restrict:"A",scope:{content:"@"},templateUrl:"uib/template/tooltip/tooltip-popup.html"}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{restrict:"A",scope:{contentExp:"&",originScope:"&"},templateUrl:"uib/template/tooltip/tooltip-template-popup.html"}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&"},templateUrl:"uib/template/tooltip/tooltip-html-popup.html"}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{restrict:"A",scope:{uibTitle:"@",contentExp:"&",originScope:"&"},templateUrl:"uib/template/popover/popover-template.html"}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&",uibTitle:"@"},templateUrl:"uib/template/popover/popover-html.html"}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{restrict:"A",scope:{uibTitle:"@",content:"@"},templateUrl:"uib/template/popover/popover.html"}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){function d(){return angular.isDefined(a.maxParam)?a.maxParam:c.max}var e=this,f=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=d(),this.addBar=function(a,b,c){f||b.css({transition:"none"}),this.bars.push(a),a.max=d(),a.title=c&&angular.isDefined(c.title)?c.title:"progressbar",a.$watch("value",function(b){a.recalculatePercentage()}),a.recalculatePercentage=function(){var b=e.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);b>100&&(a.percent-=b-100)},a.$on("$destroy",function(){b=null,e.removeBar(a)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("maxParam",function(a){e.bars.forEach(function(a){a.max=d(),a.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{maxParam:"=?max"},templateUrl:"uib/template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"uib/template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",maxParam:"=?max",type:"@"},templateUrl:"uib/template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,enableReset:!0,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop},e=this;this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff,this.enableReset=angular.isDefined(b.enableReset)?a.$parent.$eval(b.enableReset):c.enableReset;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){if(!a.readonly&&b>=0&&b<=a.range.length){var c=e.enableReset&&d.$viewValue===b?0:b;d.$setViewValue(c),d.$render()}},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue,a.title=e.getTitle(a.value-1)}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],restrict:"A",scope:{readonly:"=?readOnly",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"uib/template/rating/rating.html",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){function b(a){for(var b=0;b<d.tabs.length;b++)if(d.tabs[b].index===a)return b}var c,d=this;d.tabs=[],d.select=function(a,f){if(!e){var g=b(c),h=d.tabs[g];if(h){if(h.tab.onDeselect({$event:f,$selectedIndex:a}),f&&f.isDefaultPrevented())return;h.tab.active=!1}var i=d.tabs[a];i?(i.tab.onSelect({$event:f}),i.tab.active=!0,d.active=i.index,c=i.index):!i&&angular.isDefined(c)&&(d.active=null,c=null)}},d.addTab=function(a){if(d.tabs.push({tab:a,index:a.index}),d.tabs.sort(function(a,b){return a.index>b.index?1:a.index<b.index?-1:0}),a.index===d.active||!angular.isDefined(d.active)&&1===d.tabs.length){var c=b(a.index);d.select(c)}},d.removeTab=function(a){for(var b,c=0;c<d.tabs.length;c++)if(d.tabs[c].tab===a){b=c;break}if(d.tabs[b].index===d.active){var e=b===d.tabs.length-1?b-1:b+1%d.tabs.length;d.select(e)}d.tabs.splice(b,1)},a.$watch("tabset.active",function(a){angular.isDefined(a)&&a!==c&&d.select(b(a))});var e;a.$on("$destroy",function(){e=!0})}]).directive("uibTabset",function(){return{transclude:!0,replace:!0,scope:{},bindToController:{active:"=?",type:"@"},controller:"UibTabsetController",controllerAs:"tabset",templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tabset.html"},link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",replace:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tab.html"},transclude:!0,scope:{heading:"@",index:"=?",classes:"@?",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},controllerAs:"tab",link:function(b,c,d,e,f){b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),angular.isUndefined(d.index)&&(e.tabs&&e.tabs.length?b.index=Math.max.apply(null,e.tabs.map(function(a){return a.index}))+1:b.index=0),angular.isUndefined(d.classes)&&(b.classes=""),b.select=function(a){if(!b.disabled){for(var c,d=0;d<e.tabs.length;d++)if(e.tabs[d].tab===b){c=d;break}e.select(c,a)}},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:"^uibTab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase()||"uib:tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^uibTabset",link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude).tab;e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,secondStep:1,showMeridian:!0,showSeconds:!1,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0,templateUrl:"uib/template/timepicker/timepicker.html"}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=+a.hours,c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c&&""!==a.hours?(a.showMeridian&&(12===b&&(b=0),a.meridian===y[1]&&(b+=12)),b):void 0}function i(){var b=+a.minutes,c=b>=0&&60>b;return c&&""!==a.minutes?b:void 0}function j(){var b=+a.seconds;return b>=0&&60>b?b:void 0}function k(a,b){return null===a?"":angular.isDefined(a)&&a.toString().length<2&&!b?"0"+a:a.toString()}function l(a){m(),x.$setViewValue(new Date(v)),n(a)}function m(){s&&s.$setValidity("hours",!0),t&&t.$setValidity("minutes",!0),u&&u.$setValidity("seconds",!0),x.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1,a.invalidSeconds=!1}function n(b){if(x.$modelValue){var c=v.getHours(),d=v.getMinutes(),e=v.getSeconds();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:k(c,!z),"m"!==b&&(a.minutes=k(d)),a.meridian=v.getHours()<12?y[0]:y[1],"s"!==b&&(a.seconds=k(e)),a.meridian=v.getHours()<12?y[0]:y[1]}else a.hours=null,a.minutes=null,a.seconds=null,a.meridian=y[0]}function o(a){v=q(v,a),l()}function p(a,b){return q(a,60*b)}function q(a,b){var c=new Date(a.getTime()+1e3*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes(),c.getSeconds()),d}function r(){return(null===a.hours||""===a.hours)&&(null===a.minutes||""===a.minutes)&&(!a.showSeconds||a.showSeconds&&(null===a.seconds||""===a.seconds))}var s,t,u,v=new Date,w=[],x={$setViewValue:angular.noop},y=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS,z=angular.isDefined(c.padHours)?a.$parent.$eval(c.padHours):!0;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){x=b,x.$render=this.render,x.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=d.eq(2);s=e.controller("ngModel"),t=f.controller("ngModel"),u=h.controller("ngModel");var i=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;i&&this.setupMousewheelEvents(e,f,h);var j=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;j&&this.setupArrowkeyEvents(e,f,h),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f,h)};var A=g.hourStep;c.hourStep&&w.push(a.$parent.$watch(d(c.hourStep),function(a){A=+a}));var B=g.minuteStep;c.minuteStep&&w.push(a.$parent.$watch(d(c.minuteStep),function(a){B=+a}));var C;w.push(a.$parent.$watch(d(c.min),function(a){var b=new Date(a);C=isNaN(b)?void 0:b}));var D;w.push(a.$parent.$watch(d(c.max),function(a){var b=new Date(a);D=isNaN(b)?void 0:b}));var E=!1;c.ngDisabled&&w.push(a.$parent.$watch(d(c.ngDisabled),function(a){E=a})),a.noIncrementHours=function(){var a=p(v,60*A);return E||a>D||v>a&&C>a},a.noDecrementHours=function(){var a=p(v,60*-A);return E||C>a||a>v&&a>D},a.noIncrementMinutes=function(){var a=p(v,B);return E||a>D||v>a&&C>a},a.noDecrementMinutes=function(){var a=p(v,-B);return E||C>a||a>v&&a>D},a.noIncrementSeconds=function(){var a=q(v,F);return E||a>D||v>a&&C>a},a.noDecrementSeconds=function(){var a=q(v,-F);return E||C>a||a>v&&a>D},a.noToggleMeridian=function(){return v.getHours()<12?E||p(v,720)>D:E||p(v,-720)<C};var F=g.secondStep;c.secondStep&&w.push(a.$parent.$watch(d(c.secondStep),function(a){F=+a})),a.showSeconds=g.showSeconds,c.showSeconds&&w.push(a.$parent.$watch(d(c.showSeconds),function(b){a.showSeconds=!!b})),a.showMeridian=g.showMeridian,c.showMeridian&&w.push(a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,x.$error.time){var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(v.setHours(c),l())}else n()})),this.setupMousewheelEvents=function(b,c,d){var e=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()}),d.on("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementSeconds():a.decrementSeconds()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c,d){b.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply()))}),c.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply()))}),d.on("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementSeconds(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementSeconds(),a.$apply()))})},this.setupInputEvents=function(b,c,d){if(a.readonlyInput)return a.updateHours=angular.noop,a.updateMinutes=angular.noop,void(a.updateSeconds=angular.noop);var e=function(b,c,d){x.$setViewValue(null),x.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b,s&&s.$setValidity("hours",!1)),angular.isDefined(c)&&(a.invalidMinutes=c,t&&t.$setValidity("minutes",!1)),angular.isDefined(d)&&(a.invalidSeconds=d,u&&u.$setValidity("seconds",!1))};a.updateHours=function(){var a=h(),b=i();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(a),v.setMinutes(b),C>v||v>D?e(!0):l("h")):e(!0)},b.on("blur",function(b){x.$setTouched(),r()?m():null===a.hours||""===a.hours?e(!0):!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=k(a.hours,!z)})}),a.updateMinutes=function(){var a=i(),b=h();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(b),v.setMinutes(a),C>v||v>D?e(void 0,!0):l("m")):e(void 0,!0)},c.on("blur",function(b){x.$setTouched(),r()?m():null===a.minutes?e(void 0,!0):!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=k(a.minutes)})}),a.updateSeconds=function(){var a=j();x.$setDirty(),angular.isDefined(a)?(v.setSeconds(a),l("s")):e(void 0,void 0,!0)},d.on("blur",function(b){r()?m():!a.invalidSeconds&&a.seconds<10&&a.$apply(function(){a.seconds=k(a.seconds)})})},this.render=function(){var b=x.$viewValue;isNaN(b)?(x.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(v=b),C>v||v>D?(x.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):m(),n())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*A*60)},a.decrementHours=function(){a.noDecrementHours()||o(60*-A*60)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(60*B)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(60*-B)},a.incrementSeconds=function(){a.noIncrementSeconds()||o(F)},a.decrementSeconds=function(){a.noDecrementSeconds()||o(-F)},a.toggleMeridian=function(){var b=i(),c=h();a.noToggleMeridian()||(angular.isDefined(b)&&angular.isDefined(c)?o(720*(v.getHours()<12?60:-60)):a.meridian=a.meridian===y[0]?y[1]:y[0])},a.blur=function(){x.$setTouched()},a.$on("$destroy",function(){for(;w.length;)w.shift()()})}]).directive("uibTimepicker",["uibTimepickerConfig",function(a){return{require:["uibTimepicker","?^ngModel"],restrict:"A",controller:"UibTimepickerController",controllerAs:"timepicker",scope:{},templateUrl:function(b,c){return c.templateUrl||a.templateUrl},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.debounce","ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$$debounce","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(){P.moveInProgress||(P.moveInProgress=!0,P.$digest()),$()}function o(){P.position=F?l.offset(b):l.position(b),P.position.top+=b.prop("offsetHeight")}function p(a){var b;return angular.version.minor<6?(b=a.$options||{},b.getOption=function(a){return b[a]}):b=a.$options,b}var q,r,s=[9,13,27,38,40],t=200,u=a.$eval(c.typeaheadMinLength);u||0===u||(u=1),a.$watch(c.typeaheadMinLength,function(a){u=a||0===a?a:1});var v=a.$eval(c.typeaheadWaitMs)||0,w=a.$eval(c.typeaheadEditable)!==!1;a.$watch(c.typeaheadEditable,function(a){w=a!==!1});var x,y,z=e(c.typeaheadLoading).assign||angular.noop,A=c.typeaheadShouldSelect?e(c.typeaheadShouldSelect):function(a,b){var c=b.$event;return 13===c.which||9===c.which},B=e(c.typeaheadOnSelect),C=angular.isDefined(c.typeaheadSelectOnBlur)?a.$eval(c.typeaheadSelectOnBlur):!1,D=e(c.typeaheadNoResults).assign||angular.noop,E=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,F=c.typeaheadAppendToBody?a.$eval(c.typeaheadAppendToBody):!1,G=c.typeaheadAppendTo?a.$eval(c.typeaheadAppendTo):null,H=a.$eval(c.typeaheadFocusFirst)!==!1,I=c.typeaheadSelectOnExact?a.$eval(c.typeaheadSelectOnExact):!1,J=e(c.typeaheadIsOpen).assign||angular.noop,K=a.$eval(c.typeaheadShowHint)||!1,L=e(c.ngModel),M=e(c.ngModel+"($$$p)"),N=function(b,c){return angular.isFunction(L(a))&&r.getOption("getterSetter")?M(b,{$$$p:c}):L.assign(b,c)},O=m.parse(c.uibTypeahead),P=a.$new(),Q=a.$on("$destroy",function(){P.$destroy()});P.$on("$destroy",Q);var R="typeahead-"+P.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":R});var S,T;K&&(S=angular.element("<div></div>"),S.css("position","relative"),b.after(S),T=b.clone(),T.attr("placeholder",""),T.attr("tabindex","-1"),T.val(""),T.css({position:"absolute",top:"0px",left:"0px","border-color":"transparent","box-shadow":"none",opacity:1,background:"none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)",color:"#999"}),b.css({position:"relative","vertical-align":"top","background-color":"transparent"}),T.attr("id")&&T.removeAttr("id"),S.append(T),T.after(b));var U=angular.element("<div uib-typeahead-popup></div>");U.attr({id:R,matches:"matches",active:"activeIdx",select:"select(activeIdx, evt)","move-in-progress":"moveInProgress",query:"query",position:"position","assign-is-open":"assignIsOpen(isOpen)",debounce:"debounceUpdate"}),angular.isDefined(c.typeaheadTemplateUrl)&&U.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&U.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var V=function(){K&&T.val("")},W=function(){P.matches=[],P.activeIdx=-1,b.attr("aria-expanded",!1),V()},X=function(a){return R+"-option-"+a};P.$watch("activeIdx",function(a){0>a?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",X(a))});var Y=function(a,b){return P.matches.length>b&&a?a.toUpperCase()===P.matches[b].label.toUpperCase():!1},Z=function(c,d){var e={$viewValue:c};z(a,!0),D(a,!1),f.when(O.source(a,e)).then(function(f){var g=c===q.$viewValue;if(g&&x)if(f&&f.length>0){P.activeIdx=H?0:-1,D(a,!1),P.matches.length=0;for(var h=0;h<f.length;h++)e[O.itemName]=f[h],P.matches.push({id:X(h),label:O.viewMapper(P,e),model:f[h]});if(P.query=c,o(),b.attr("aria-expanded",!0),I&&1===P.matches.length&&Y(c,0)&&(angular.isNumber(P.debounceUpdate)||angular.isObject(P.debounceUpdate)?k(function(){P.select(0,d)},angular.isNumber(P.debounceUpdate)?P.debounceUpdate:P.debounceUpdate["default"]):P.select(0,d)),K){var i=P.matches[0].label;angular.isString(c)&&c.length>0&&i.slice(0,c.length).toUpperCase()===c.toUpperCase()?T.val(c+i.slice(c.length)):T.val("")}}else W(),D(a,!0);g&&z(a,!1)},function(){W(),z(a,!1),D(a,!0)})};F&&(angular.element(i).on("resize",n),h.find("body").on("scroll",n));var $=k(function(){P.matches.length&&o(),P.moveInProgress=!1},t);P.moveInProgress=!1,P.query=void 0;var _,aa=function(a){_=g(function(){Z(a)},v)},ba=function(){_&&g.cancel(_)};W(),P.assignIsOpen=function(b){J(a,b)},P.select=function(d,e){var f,h,i={};y=!0,i[O.itemName]=h=P.matches[d].model,f=O.modelMapper(a,i),N(a,f),q.$setValidity("editable",!0),q.$setValidity("parse",!0),B(a,{$item:h,$model:f,$label:O.viewMapper(a,i),$event:e}),W(),P.$eval(c.typeaheadFocusOnSelect)!==!1&&g(function(){b[0].focus()},0,!1)},b.on("keydown",function(b){if(0!==P.matches.length&&-1!==s.indexOf(b.which)){var c=A(a,{$event:b});if(-1===P.activeIdx&&c||9===b.which&&b.shiftKey)return W(),void P.$digest();b.preventDefault();var d;switch(b.which){case 27:b.stopPropagation(),W(),a.$digest();break;case 38:P.activeIdx=(P.activeIdx>0?P.activeIdx:P.matches.length)-1,P.$digest(),d=U[0].querySelectorAll(".uib-typeahead-match")[P.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;case 40:P.activeIdx=(P.activeIdx+1)%P.matches.length,P.$digest(),d=U[0].querySelectorAll(".uib-typeahead-match")[P.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;default:c&&P.$apply(function(){angular.isNumber(P.debounceUpdate)||angular.isObject(P.debounceUpdate)?k(function(){P.select(P.activeIdx,b)},angular.isNumber(P.debounceUpdate)?P.debounceUpdate:P.debounceUpdate["default"]):P.select(P.activeIdx,b)})}}}),b.on("focus",function(a){x=!0,0!==u||q.$viewValue||g(function(){Z(q.$viewValue,a)},0)}),b.on("blur",function(a){C&&P.matches.length&&-1!==P.activeIdx&&!y&&(y=!0,P.$apply(function(){angular.isObject(P.debounceUpdate)&&angular.isNumber(P.debounceUpdate.blur)?k(function(){P.select(P.activeIdx,a)},P.debounceUpdate.blur):P.select(P.activeIdx,a)})),!w&&q.$error.editable&&(q.$setViewValue(),P.$apply(function(){q.$setValidity("editable",!0),q.$setValidity("parse",!0)}),b.val("")),x=!1,y=!1});var ca=function(c){b[0]!==c.target&&3!==c.which&&0!==P.matches.length&&(W(),j.$$phase||a.$digest())};h.on("click",ca),a.$on("$destroy",function(){h.off("click",ca),(F||G)&&da.remove(),F&&(angular.element(i).off("resize",n),h.find("body").off("scroll",n)),U.remove(),K&&S.remove()});var da=d(U)(P);F?h.find("body").append(da):G?angular.element(G).eq(0).append(da):b.after(da),
+this.init=function(b){q=b,r=p(q),P.debounceUpdate=e(r.getOption("debounce"))(a),q.$parsers.unshift(function(b){return x=!0,0===u||b&&b.length>=u?v>0?(ba(),aa(b)):Z(b):(z(a,!1),ba(),W()),w?b:b?void q.$setValidity("editable",!1):(q.$setValidity("editable",!0),null)}),q.$formatters.push(function(b){var c,d,e={};return w||q.$setValidity("editable",!0),E?(e.$model=b,E(a,e)):(e[O.itemName]=b,c=O.viewMapper(a,e),e[O.itemName]=void 0,d=O.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","uibTypeahead"],link:function(a,b,c,d){d[1].init(d[0])}}}).directive("uibTypeaheadPopup",["$$debounce",function(a){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&",assignIsOpen:"&",debounce:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"uib/template/typeahead/typeahead-popup.html"},link:function(b,c,d){b.templateUrl=d.templateUrl,b.isOpen=function(){var a=b.matches.length>0;return b.assignIsOpen({isOpen:a}),a},b.isActive=function(a){return b.active===a},b.selectActive=function(a){b.active=a},b.selectMatch=function(c,d){var e=b.debounce();angular.isNumber(e)||angular.isObject(e)?a(function(){b.select({activeIdx:c,evt:d})},angular.isNumber(e)?e:e["default"]):b.select({activeIdx:c,evt:d})}}}}]).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"uib/template/typeahead/typeahead-match.html";a(g).then(function(a){var c=angular.element(a.trim());e.replaceWith(c),b(c)(d)})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'),angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-time input{width:50px;}</style>'),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'),angular.$$uibTypeaheadCss=!0}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.css
new file mode 100644
index 00000000..f89af3e8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.css
@@ -0,0 +1,145 @@
+/**
+ * gridster.js - v0.2.1 - 2013-10-28 * http://gridster.net
+ * Copyright (c) 2013 ducksboard; Licensed MIT
+ */
+.gridster {
+ position: relative;
+ margin: auto;
+ height: 0;
+}
+.gridster > ul {
+ margin: 0;
+ list-style: none;
+ padding: 0;
+}
+.gridster-item {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ list-style: none;
+ z-index: 2;
+ position: absolute;
+ display: none;
+}
+.gridster-loaded {
+ -webkit-transition: height .3s;
+ -moz-transition: height .3s;
+ -o-transition: height .3s;
+ transition: height .3s;
+}
+.gridster-loaded .gridster-item {
+ display: block;
+ position: absolute;
+ -webkit-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -moz-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -o-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -webkit-transition-delay: 50ms;
+ -moz-transition-delay: 50ms;
+ -o-transition-delay: 50ms;
+ transition-delay: 50ms;
+}
+.gridster-loaded .gridster-preview-holder {
+ display: none;
+ z-index: 1;
+ position: absolute;
+ background-color: #ddd;
+ border-color: #fff;
+ opacity: 0.2;
+}
+.gridster-loaded .gridster-item.gridster-item-moving,
+.gridster-loaded .gridster-preview-holder {
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+.gridster-mobile {
+ height: auto !important;
+}
+.gridster-mobile .gridster-item {
+ height: auto;
+ position: static;
+ float: none;
+}
+.gridster-item.ng-leave.ng-leave-active {
+ opacity: 0;
+}
+.gridster-item.ng-enter {
+ opacity: 1;
+}
+.gridster-item-moving {
+ z-index: 3;
+}
+/* RESIZE */
+.gridster-item-resizable-handler {
+ position: absolute;
+ font-size: 1px;
+ display: block;
+ z-index: 5;
+}
+.handle-se {
+ cursor: se-resize;
+ width: 0;
+ height: 0;
+ right: 1px;
+ bottom: 1px;
+ border-style: solid;
+ border-width: 0 0 12px 12px;
+ border-color: transparent;
+}
+.handle-ne {
+ cursor: ne-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ top: 1px;
+}
+.handle-nw {
+ cursor: nw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ top: 1px;
+}
+.handle-sw {
+ cursor: sw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ bottom: 1px;
+}
+.handle-e {
+ cursor: e-resize;
+ width: 12px;
+ bottom: 0;
+ right: 1px;
+ top: 0;
+}
+.handle-s {
+ cursor: s-resize;
+ height: 12px;
+ right: 0;
+ bottom: 1px;
+ left: 0;
+}
+.handle-n {
+ cursor: n-resize;
+ height: 12px;
+ right: 0;
+ top: 1px;
+ left: 0;
+}
+.handle-w {
+ cursor: w-resize;
+ width: 12px;
+ left: 1px;
+ top: 0;
+ bottom: 0;
+}
+.gridster .gridster-item:hover .gridster-box {
+ border: 1.5px solid #B3B2B3;
+}
+.gridster .gridster-item:hover .handle-se {
+ border-color: transparent transparent #ccc;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.css
new file mode 100644
index 00000000..1bb601d3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.css
@@ -0,0 +1 @@
+.gridster{position:relative;margin:auto;height:0}.gridster>ul{margin:0;list-style:none;padding:0}.gridster-item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;list-style:none;z-index:2;position:absolute;display:none}.gridster-loaded{-webkit-transition:height .3s;-moz-transition:height .3s;-o-transition:height .3s;transition:height .3s}.gridster-loaded .gridster-item{display:block;position:absolute;-webkit-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-moz-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-o-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-webkit-transition-delay:50ms;-moz-transition-delay:50ms;-o-transition-delay:50ms;transition-delay:50ms}.gridster-loaded .gridster-preview-holder{display:none;z-index:1;position:absolute;background-color:#ddd;border-color:#fff;opacity:.2}.gridster-loaded .gridster-item.gridster-item-moving,.gridster-loaded .gridster-preview-holder{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.gridster-mobile{height:auto !important}.gridster-mobile .gridster-item{height:auto;position:static;float:none}.gridster-item.ng-leave.ng-leave-active{opacity:0}.gridster-item.ng-enter{opacity:1}.gridster-item-moving{z-index:3}.gridster-item-resizable-handler{position:absolute;font-size:1px;display:block;z-index:5}.handle-se{cursor:se-resize;width:0;height:0;right:1px;bottom:1px;border-style:solid;border-width:0 0 12px 12px;border-color:transparent}.handle-ne{cursor:ne-resize;width:12px;height:12px;right:1px;top:1px}.handle-nw{cursor:nw-resize;width:12px;height:12px;left:1px;top:1px}.handle-sw{cursor:sw-resize;width:12px;height:12px;left:1px;bottom:1px}.handle-e{cursor:e-resize;width:12px;bottom:0;right:1px;top:0}.handle-s{cursor:s-resize;height:12px;right:0;bottom:1px;left:0}.handle-n{cursor:n-resize;height:12px;right:0;top:1px;left:0}.handle-w{cursor:w-resize;width:12px;left:1px;top:0;bottom:0}.gridster .gridster-item:hover .gridster-box{border:1.5px solid #B3B2B3}.gridster .gridster-item:hover .handle-se{border-color:transparent transparent #ccc} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.js
new file mode 100644
index 00000000..07d7c878
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/dist/angular-gridster.min.js
@@ -0,0 +1,8 @@
+/*
+ * angular-gridster
+ * http://manifestwebdesign.github.io/angular-gridster
+ *
+ * @version: 0.13.14
+ * @license: MIT
+ */
+!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";return a.module("gridster",[]).constant("gridsterConfig",{columns:6,pushing:!0,floating:!0,swapping:!1,width:"auto",colWidth:"auto",rowHeight:"match",margins:[10,10],outerMargin:!0,sparse:!1,isMobile:!1,mobileBreakPoint:600,mobileModeEnabled:!0,minColumns:1,minRows:1,maxRows:100,defaultSizeX:2,defaultSizeY:1,minSizeX:1,maxSizeX:null,minSizeY:1,maxSizeY:null,saveGridItemCalculatedHeightInMobile:!1,resizable:{enabled:!0,handles:["s","e","n","w","se","ne","sw","nw"]},draggable:{enabled:!0,scrollSensitivity:20,scrollSpeed:15}}).controller("GridsterCtrl",["gridsterConfig","$timeout",function(b,c){var d=this;a.extend(this,b),this.resizable=a.extend({},b.resizable||{}),this.draggable=a.extend({},b.draggable||{});var e=!1;this.layoutChanged=function(){e||(e=!0,c(function(){e=!1,d.loaded&&d.floatItemsUp(),d.updateHeight(d.movingItem?d.movingItem.sizeY:0)},30))},this.grid=[],this.allItems=[],this.destroy=function(){this.grid&&(this.grid=[]),this.$element=null,this.allItems&&(this.allItems.length=0,this.allItems=null)},this.setOptions=function(b){if(b)if(b=a.extend({},b),b.draggable&&(a.extend(this.draggable,b.draggable),delete b.draggable),b.resizable&&(a.extend(this.resizable,b.resizable),delete b.resizable),a.extend(this,b),this.margins&&2===this.margins.length)for(var c=0,d=this.margins.length;c<d;++c)this.margins[c]=parseInt(this.margins[c],10),isNaN(this.margins[c])&&(this.margins[c]=0);else this.margins=[0,0]},this.canItemOccupy=function(a,b,c){return b>-1&&c>-1&&a.sizeX+c<=this.columns&&a.sizeY+b<=this.maxRows},this.autoSetItemPosition=function(a){for(var b=0;b<this.maxRows;++b)for(var c=0;c<this.columns;++c){var d=this.getItems(b,c,a.sizeX,a.sizeY,a);if(0===d.length&&this.canItemOccupy(a,b,c))return void this.putItem(a,b,c)}throw new Error("Unable to place item!")},this.getItems=function(a,b,c,d,e){var f=[];c&&d||(c=d=1),!e||e instanceof Array||(e=[e]);var g;if(this.sparse===!1)for(var h=0;h<d;++h)for(var i=0;i<c;++i)g=this.getItem(a+h,b+i,e),!g||e&&e.indexOf(g)!==-1||f.indexOf(g)!==-1||f.push(g);else for(var j=a+d-1,k=b+c-1,l=0;l<this.allItems.length;++l)g=this.allItems[l],!g||e&&e.indexOf(g)!==-1||f.indexOf(g)!==-1||!this.intersect(g,b,k,a,j)||f.push(g);return f},this.getBoundingBox=function(a){if(0===a.length)return null;if(1===a.length)return{row:a[0].row,col:a[0].col,sizeY:a[0].sizeY,sizeX:a[0].sizeX};for(var b=0,c=0,d=9999,e=9999,f=0,g=a.length;f<g;++f){var h=a[f];d=Math.min(h.row,d),e=Math.min(h.col,e),b=Math.max(h.row+h.sizeY,b),c=Math.max(h.col+h.sizeX,c)}return{row:d,col:e,sizeY:b-d,sizeX:c-e}},this.intersect=function(a,b,c,d,e){return b<=a.col+a.sizeX-1&&c>=a.col&&d<=a.row+a.sizeY-1&&e>=a.row},this.removeItem=function(a){for(var b,c=0,d=this.grid.length;c<d;++c){var e=this.grid[c];if(e&&(b=e.indexOf(a),b!==-1)){e[b]=null;break}}this.sparse&&(b=this.allItems.indexOf(a),b!==-1&&this.allItems.splice(b,1)),this.layoutChanged()},this.getItem=function(a,b,c){!c||c instanceof Array||(c=[c]);for(var d=1;a>-1;){for(var e=1,f=b;f>-1;){var g=this.grid[a];if(g){var h=g[f];if(h&&(!c||c.indexOf(h)===-1)&&h.sizeX>=e&&h.sizeY>=d)return h}++e,--f}--a,++d}return null},this.putItems=function(a){for(var b=0,c=a.length;b<c;++b)this.putItem(a[b])},this.putItem=function(a,b,c,d){if(("undefined"==typeof b||null===b)&&(b=a.row,c=a.col,"undefined"==typeof b||null===b))return void this.autoSetItemPosition(a);if(this.canItemOccupy(a,b,c)||(c=Math.min(this.columns-a.sizeX,Math.max(0,c)),b=Math.min(this.maxRows-a.sizeY,Math.max(0,b))),null!==a.oldRow&&"undefined"!=typeof a.oldRow){var e=a.oldRow===b&&a.oldColumn===c,f=this.grid[b]&&this.grid[b][c]===a;if(e&&f)return a.row=b,void(a.col=c);var g=this.grid[a.oldRow];g&&g[a.oldColumn]===a&&delete g[a.oldColumn]}a.oldRow=a.row=b,a.oldColumn=a.col=c,this.moveOverlappingItems(a,d),this.grid[b]||(this.grid[b]=[]),this.grid[b][c]=a,this.sparse&&this.allItems.indexOf(a)===-1&&this.allItems.push(a),this.movingItem===a&&this.floatItemUp(a),this.layoutChanged()},this.swapItems=function(a,b){this.grid[a.row][a.col]=b,this.grid[b.row][b.col]=a;var c=a.row,d=a.col;a.row=b.row,a.col=b.col,b.row=c,b.col=d},this.moveOverlappingItems=function(a,b){b?b.indexOf(a)===-1&&(b=b.slice(0),b.push(a)):b=[a];var c=this.getItems(a.row,a.col,a.sizeX,a.sizeY,b);this.moveItemsDown(c,a.row+a.sizeY,b)},this.moveItemsDown=function(a,b,c){if(a&&0!==a.length){a.sort(function(a,b){return a.row-b.row}),c=c?c.slice(0):[];var d,e,f,g={};for(e=0,f=a.length;e<f;++e){d=a[e];var h=g[d.col];("undefined"==typeof h||d.row<h)&&(g[d.col]=d.row)}for(e=0,f=a.length;e<f;++e){d=a[e];var i=b-g[d.col];this.moveItemDown(d,d.row+i,c),c.push(d)}}},this.moveItemDown=function(a,b,c){if(!(a.row>=b)){for(;a.row<b;)++a.row,this.moveOverlappingItems(a,c);this.putItem(a,a.row,a.col,c)}},this.floatItemsUp=function(){if(this.floating!==!1)for(var a=0,b=this.grid.length;a<b;++a){var c=this.grid[a];if(c)for(var d=0,e=c.length;d<e;++d){var f=c[d];f&&this.floatItemUp(f)}}},this.floatItemUp=function(a){if(this.floating!==!1){for(var b=a.col,c=a.sizeY,d=a.sizeX,e=null,f=null,g=a.row-1;g>-1;){var h=this.getItems(g,b,d,c,a);if(0!==h.length)break;e=g,f=b,--g}null!==e&&this.putItem(a,e,f)}},this.updateHeight=function(a){var b=this.minRows;a=a||0;for(var c=this.grid.length;c>=0;--c){var d=this.grid[c];if(d)for(var e=0,f=d.length;e<f;++e)d[e]&&(b=Math.max(b,c+a+d[e].sizeY))}this.gridHeight=this.maxRows-b>0?Math.min(this.maxRows,b):Math.max(this.maxRows,b)},this.pixelsToRows=function(a,b){return this.outerMargin||(a+=this.margins[0]/2),b===!0?Math.ceil(a/this.curRowHeight):b===!1?Math.floor(a/this.curRowHeight):Math.round(a/this.curRowHeight)},this.pixelsToColumns=function(a,b){return this.outerMargin||(a+=this.margins[1]/2),b===!0?Math.ceil(a/this.curColWidth):b===!1?Math.floor(a/this.curColWidth):Math.round(a/this.curColWidth)}}]).directive("gridsterPreview",function(){return{replace:!0,scope:!0,require:"^gridster",template:'<div ng-style="previewStyle()" class="gridster-item gridster-preview-holder"></div>',link:function(a,b,c,d){a.previewStyle=function(){return d.movingItem?{display:"block",height:d.movingItem.sizeY*d.curRowHeight-d.margins[0]+"px",width:d.movingItem.sizeX*d.curColWidth-d.margins[1]+"px",top:d.movingItem.row*d.curRowHeight+(d.outerMargin?d.margins[0]:0)+"px",left:d.movingItem.col*d.curColWidth+(d.outerMargin?d.margins[1]:0)+"px"}:{display:"none"}}}}}).directive("gridster",["$timeout","$window","$rootScope","gridsterDebounce",function(b,c,d,e){return{scope:!0,restrict:"EAC",controller:"GridsterCtrl",controllerAs:"gridster",compile:function(f){return f.prepend('<div ng-if="gridster.movingItem" gridster-preview></div>'),function(f,g,h,i){function j(){g.css("height",i.gridHeight*i.curRowHeight+(i.outerMargin?i.margins[0]:-i.margins[0])+"px")}function k(a){if(i.setOptions(a),l(g[0])){"auto"===i.width?i.curWidth=g[0].offsetWidth||parseInt(g.css("width"),10):i.curWidth=i.width,"auto"===i.colWidth?i.curColWidth=(i.curWidth+(i.outerMargin?-i.margins[1]:i.margins[1]))/i.columns:i.curColWidth=i.colWidth,i.curRowHeight=i.rowHeight,"string"==typeof i.rowHeight&&("match"===i.rowHeight?i.curRowHeight=Math.round(i.curColWidth):i.rowHeight.indexOf("*")!==-1?i.curRowHeight=Math.round(i.curColWidth*i.rowHeight.replace("*","").replace(" ","")):i.rowHeight.indexOf("/")!==-1&&(i.curRowHeight=Math.round(i.curColWidth/i.rowHeight.replace("/","").replace(" ","")))),i.isMobile=i.mobileModeEnabled&&i.curWidth<=i.mobileBreakPoint;for(var b=0,c=i.grid.length;b<c;++b){var d=i.grid[b];if(d)for(var e=0,f=d.length;e<f;++e)if(d[e]){var h=d[e];h.setElementPosition(),h.setElementSizeY(),h.setElementSizeX()}}j()}}i.loaded=!1,i.$element=g,f.gridster=i,g.addClass("gridster");var l=function(a){return"hidden"!==a.style.visibility&&"none"!==a.style.display};f.$watch(function(){return i.gridHeight},j),f.$watch(function(){return i.movingItem},function(){i.updateHeight(i.movingItem?i.movingItem.sizeY:0)});var m=h.gridster;m?f.$parent.$watch(m,function(a){k(a)},!0):k({}),f.$watch(function(){return i.loaded},function(){i.loaded?(g.addClass("gridster-loaded"),d.$broadcast("gridster-loaded",i)):g.removeClass("gridster-loaded")}),f.$watch(function(){return i.isMobile},function(){i.isMobile?g.addClass("gridster-mobile").removeClass("gridster-desktop"):g.removeClass("gridster-mobile").addClass("gridster-desktop"),d.$broadcast("gridster-mobile-changed",i)}),f.$watch(function(){return i.draggable},function(){d.$broadcast("gridster-draggable-changed",i)},!0),f.$watch(function(){return i.resizable},function(){d.$broadcast("gridster-resizable-changed",i)},!0);var n=g[0].offsetWidth||parseInt(g.css("width"),10),o=function(){var a=g[0].offsetWidth||parseInt(g.css("width"),10);a&&a!==n&&!i.movingItem&&(n=a,i.loaded&&g.removeClass("gridster-loaded"),k(),i.loaded&&g.addClass("gridster-loaded"),d.$broadcast("gridster-resized",[a,g[0].offsetHeight],i))},p=e(function(){o(),b(function(){f.$apply()})},100);f.$watch(function(){return l(g[0])},p),"function"==typeof window.addResizeListener?window.addResizeListener(g[0],p):f.$watch(function(){return g[0].offsetWidth||parseInt(g.css("width"),10)},o);var q=a.element(c);q.on("resize",p),f.$on("$destroy",function(){i.destroy(),q.off("resize",p),"function"==typeof window.removeResizeListener&&window.removeResizeListener(g[0],p)}),b(function(){f.$watch("gridster.floating",function(){i.floatItemsUp()}),i.loaded=!0},100)}}}}]).controller("GridsterItemCtrl",function(){this.$element=null,this.gridster=null,this.row=null,this.col=null,this.sizeX=null,this.sizeY=null,this.minSizeX=0,this.minSizeY=0,this.maxSizeX=null,this.maxSizeY=null,this.init=function(a,b){this.$element=a,this.gridster=b,this.sizeX=b.defaultSizeX,this.sizeY=b.defaultSizeY},this.destroy=function(){this.gridster=null,this.$element=null},this.toJSON=function(){return{row:this.row,col:this.col,sizeY:this.sizeY,sizeX:this.sizeX}},this.isMoving=function(){return this.gridster.movingItem===this},this.setPosition=function(a,b){this.gridster.putItem(this,a,b),this.isMoving()||this.setElementPosition()},this.setSize=function(a,b,c){a=a.toUpperCase();var d="size"+a,e="Size"+a;if(""!==b){b=parseInt(b,10),(isNaN(b)||0===b)&&(b=this.gridster["default"+e]);var f="X"===a?this.gridster.columns:this.gridster.maxRows;this["max"+e]&&(f=Math.min(this["max"+e],f)),this.gridster["max"+e]&&(f=Math.min(this.gridster["max"+e],f)),"X"===a&&this.cols?f-=this.cols:"Y"===a&&this.rows&&(f-=this.rows);var g=0;this["min"+e]&&(g=Math.max(this["min"+e],g)),this.gridster["min"+e]&&(g=Math.max(this.gridster["min"+e],g)),b=Math.max(Math.min(b,f),g);var h=this[d]!==b||this["old"+e]&&this["old"+e]!==b;return this["old"+e]=this[d]=b,this.isMoving()||this["setElement"+e](),!c&&h&&(this.gridster.moveOverlappingItems(this),this.gridster.layoutChanged()),h}},this.setSizeY=function(a,b){return this.setSize("Y",a,b)},this.setSizeX=function(a,b){return this.setSize("X",a,b)},this.setElementPosition=function(){this.gridster.isMobile?this.$element.css({marginLeft:this.gridster.margins[0]+"px",marginRight:this.gridster.margins[0]+"px",marginTop:this.gridster.margins[1]+"px",marginBottom:this.gridster.margins[1]+"px",top:"",left:""}):this.$element.css({margin:0,top:this.row*this.gridster.curRowHeight+(this.gridster.outerMargin?this.gridster.margins[0]:0)+"px",left:this.col*this.gridster.curColWidth+(this.gridster.outerMargin?this.gridster.margins[1]:0)+"px"})},this.setElementSizeY=function(){this.gridster.isMobile&&!this.gridster.saveGridItemCalculatedHeightInMobile?this.$element.css("height",""):this.$element.css("height",this.sizeY*this.gridster.curRowHeight-this.gridster.margins[0]+"px")},this.setElementSizeX=function(){this.gridster.isMobile?this.$element.css("width",""):this.$element.css("width",this.sizeX*this.gridster.curColWidth-this.gridster.margins[1]+"px")},this.getElementSizeX=function(){return this.sizeX*this.gridster.curColWidth-this.gridster.margins[1]},this.getElementSizeY=function(){return this.sizeY*this.gridster.curRowHeight-this.gridster.margins[0]}}).factory("GridsterTouch",[function(){return function(a,b,c,d){var e,f,g={},h=function(a){if(Object.keys)return Object.keys(a).length;var b,c=0;for(b in a)++c;return c},i=function(a){for(var b=0,c=0,d=navigator.userAgent.match(/\bMSIE\b/),e=a;null!=e;e=e.offsetParent)d&&(!document.documentMode||document.documentMode<8)&&"relative"===e.currentStyle.position&&e.offsetParent&&"relative"===e.offsetParent.currentStyle.position&&e.offsetLeft===e.offsetParent.offsetLeft?c+=e.offsetTop:(b+=e.offsetLeft,c+=e.offsetTop);return{x:b,y:c}},j=i(a),k=!1,l=function(e){if("mousemove"!==e.type||0!==h(g)){for(var f=!0,m=e.changedTouches?e.changedTouches:[e],n=0;n<m.length;++n){var o=m[n],p="undefined"!=typeof o.identifier?o.identifier:"undefined"!=typeof o.pointerId?o.pointerId:1;if("undefined"==typeof o.pageX)if(o.pageX=o.offsetX+j.x,o.pageY=o.offsetY+j.y,o.srcElement.offsetParent===a&&document.documentMode&&8===document.documentMode&&"mousedown"===o.type)o.pageX+=o.srcElement.offsetLeft,o.pageY+=o.srcElement.offsetTop;else if(o.srcElement!==a&&!document.documentMode||document.documentMode<8){for(var q=-2,r=-2,s=o.srcElement;null!==s;s=s.parentNode)q+=s.scrollLeft?s.scrollLeft:0,r+=s.scrollTop?s.scrollTop:0;o.pageX=o.clientX+q,o.pageY=o.clientY+r}var t=o.pageX,u=o.pageY;e.type.match(/(start|down)$/i)?(j=i(a),g[p]&&(d&&d({target:e.target,which:e.which,pointerId:p,pageX:t,pageY:u}),delete g[p]),b&&f&&(f=b({target:e.target,which:e.which,pointerId:p,pageX:t,pageY:u})),g[p]={x:t,y:u},a.msSetPointerCapture&&f?a.msSetPointerCapture(p):"mousedown"===e.type&&1===h(g)&&(k?a.setCapture(!0):(document.addEventListener("mousemove",l,!1),document.addEventListener("mouseup",l,!1)))):e.type.match(/move$/i)?!g[p]||g[p].x===t&&g[p].y===u||(c&&f&&(f=c({target:e.target,which:e.which,pointerId:p,pageX:t,pageY:u})),g[p].x=t,g[p].y=u):g[p]&&e.type.match(/(up|end|cancel)$/i)&&(d&&f&&(f=d({target:e.target,which:e.which,pointerId:p,pageX:t,pageY:u})),delete g[p],a.msReleasePointerCapture?a.msReleasePointerCapture(p):"mouseup"===e.type&&0===h(g)&&(k?a.releaseCapture():(document.removeEventListener("mousemove",l,!1),document.removeEventListener("mouseup",l,!1))))}f&&(e.preventDefault&&e.preventDefault(),e.preventManipulation&&e.preventManipulation(),e.preventMouseEvent&&e.preventMouseEvent())}};return this.enable=function(){window.navigator.msPointerEnabled?(a.addEventListener("MSPointerDown",l,!1),a.addEventListener("MSPointerMove",l,!1),a.addEventListener("MSPointerUp",l,!1),a.addEventListener("MSPointerCancel",l,!1),"undefined"!=typeof a.style.msContentZooming&&(e=a.style.msContentZooming,a.style.msContentZooming="none"),"undefined"!=typeof a.style.msTouchAction&&(f=a.style.msTouchAction,a.style.msTouchAction="none")):a.addEventListener?(a.addEventListener("touchstart",l,!1),a.addEventListener("touchmove",l,!1),a.addEventListener("touchend",l,!1),a.addEventListener("touchcancel",l,!1),a.addEventListener("mousedown",l,!1),a.setCapture&&!window.navigator.userAgent.match(/\bGecko\b/)&&(k=!0,a.addEventListener("mousemove",l,!1),a.addEventListener("mouseup",l,!1))):a.attachEvent&&a.setCapture&&(k=!0,a.attachEvent("onmousedown",function(){return l(window.event),window.event.returnValue=!1,!1}),a.attachEvent("onmousemove",function(){return l(window.event),window.event.returnValue=!1,!1}),a.attachEvent("onmouseup",function(){return l(window.event),window.event.returnValue=!1,!1}))},this.disable=function(){window.navigator.msPointerEnabled?(a.removeEventListener("MSPointerDown",l,!1),a.removeEventListener("MSPointerMove",l,!1),a.removeEventListener("MSPointerUp",l,!1),a.removeEventListener("MSPointerCancel",l,!1),e&&(a.style.msContentZooming=e),f&&(a.style.msTouchAction=f)):a.removeEventListener?(a.removeEventListener("touchstart",l,!1),a.removeEventListener("touchmove",l,!1),a.removeEventListener("touchend",l,!1),a.removeEventListener("touchcancel",l,!1),a.removeEventListener("mousedown",l,!1),a.setCapture&&!window.navigator.userAgent.match(/\bGecko\b/)&&(k=!0,a.removeEventListener("mousemove",l,!1),a.removeEventListener("mouseup",l,!1))):a.detachEvent&&a.setCapture&&(k=!0,a.detachEvent("onmousedown"),a.detachEvent("onmousemove"),a.detachEvent("onmouseup"))},this}}]).factory("GridsterDraggable",["$document","$window","GridsterTouch",function(b,c,d){function e(e,f,g,h,i){function j(a){e.addClass("gridster-item-moving"),g.movingItem=h,g.updateHeight(h.sizeY),f.$apply(function(){g.draggable&&g.draggable.start&&g.draggable.start(a,e,i,h)})}function k(a){var b=h.row,d=h.col,j=g.draggable&&g.draggable.drag,k=g.draggable.scrollSensitivity,l=g.draggable.scrollSpeed,m=Math.min(g.pixelsToRows(q),g.maxRows-1),n=Math.min(g.pixelsToColumns(p),g.columns-1),o=g.getItems(m,n,h.sizeX,h.sizeY,h),r=0!==o.length;if(g.swapping===!0&&r){var s=g.getBoundingBox(o),t=s.sizeX===h.sizeX&&s.sizeY===h.sizeY,u=s.row===b,v=s.col===d,w=s.row===m&&s.col===n,x=u||v;if(t&&1===o.length){if(w)g.swapItems(h,o[0]);else if(x)return}else if(s.sizeX<=h.sizeX&&s.sizeY<=h.sizeY&&x)for(var y=h.row<=m?h.row:m+h.sizeY,z=h.col<=n?h.col:n+h.sizeX,A=y-s.row,B=z-s.col,C=0,E=o.length;C<E;++C){var F=o[C],G=g.getItems(F.row+A,F.col+B,F.sizeX,F.sizeY,h);0===G.length&&g.putItem(F,F.row+A,F.col+B)}}g.pushing===!1&&r||(h.row=m,h.col=n),a.pageY-D.body.scrollTop<k?D.body.scrollTop=D.body.scrollTop-l:c.innerHeight-(a.pageY-D.body.scrollTop)<k&&(D.body.scrollTop=D.body.scrollTop+l),a.pageX-D.body.scrollLeft<k?D.body.scrollLeft=D.body.scrollLeft-l:c.innerWidth-(a.pageX-D.body.scrollLeft)<k&&(D.body.scrollLeft=D.body.scrollLeft+l),(j||b!==h.row||d!==h.col)&&f.$apply(function(){j&&g.draggable.drag(a,e,i,h)})}function l(a){e.removeClass("gridster-item-moving");var b=Math.min(g.pixelsToRows(q),g.maxRows-1),c=Math.min(g.pixelsToColumns(p),g.columns-1);g.pushing===!1&&0!==g.getItems(b,c,h.sizeX,h.sizeY,h).length||(h.row=b,h.col=c),g.movingItem=null,h.setPosition(h.row,h.col),f.$apply(function(){g.draggable&&g.draggable.stop&&g.draggable.stop(a,e,i,h)})}function m(b){if(E.indexOf(b.target.nodeName.toLowerCase())!==-1)return!1;var c=a.element(b.target);if(c.hasClass("gridster-item-resizable-handler"))return!1;if(c.attr("onclick")||c.attr("ng-click"))return!1;if(c.closest&&c.closest(".gridster-no-drag").length)return!1;if(g.draggable&&g.draggable.handle){var d=a.element(e[0].querySelectorAll(g.draggable.handle)),f=!1;a:for(var i=0,k=d.length;i<k;++i){var l=d[i];if(l===b.target){f=!0;break}for(var m=b.target,n=0;n<20;++n){var o=m.parentNode;if(o===e[0]||!o)break;if(o===l){f=!0;break a}m=o}}if(!f)return!1}switch(b.which){case 1:break;case 2:case 3:return}return x=b.pageX,y=b.pageY,p=parseInt(e.css("left"),10),q=parseInt(e.css("top"),10),r=e[0].offsetWidth,s=e[0].offsetHeight,t=h.col,u=h.row,j(b),!0}function n(a){if(!e.hasClass("gridster-item-moving")||e.hasClass("gridster-item-resizing"))return!1;var b=g.curWidth-1,c=g.curRowHeight*g.maxRows-1;v=a.pageX,w=a.pageY;var d=v-x+z,f=w-y+A;z=A=0,x=v,y=w;var h=d,i=f;return p+h<C?(d=C-p,z=h-d):p+r+h>b&&(d=b-p-r,z=h-d),q+i<B?(f=B-q,A=i-f):q+s+i>c&&(f=c-q-s,A=i-f),p+=d,q+=f,e.css({top:q+"px",left:p+"px"}),k(a),!0}function o(a){return!(!e.hasClass("gridster-item-moving")||e.hasClass("gridster-item-resizing"))&&(z=A=0,l(a),!0)}var p,q,r,s,t,u,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=b[0],E=["select","option","input","textarea","button"],F=null,G=null;this.enable=function(){if(F!==!0){if(F=!0,G)return void G.enable();G=new d(e[0],m,n,o),G.enable()}},this.disable=function(){F!==!1&&(F=!1,G&&G.disable())},this.toggle=function(a){a?this.enable():this.disable()},this.destroy=function(){this.disable()}}return e}]).factory("GridsterResizable",["GridsterTouch",function(b){function c(c,d,e,f,g){function h(h){function i(a){c.addClass("gridster-item-moving"),c.addClass("gridster-item-resizing"),e.movingItem=f,f.setElementSizeX(),f.setElementSizeY(),f.setElementPosition(),e.updateHeight(1),d.$apply(function(){e.resizable&&e.resizable.start&&e.resizable.start(a,c,g,f)})}function j(a){var b=f.row,i=f.col,j=f.sizeX,k=f.sizeY,l=e.resizable&&e.resizable.resize,m=f.col;["w","nw","sw"].indexOf(h)!==-1&&(m=e.pixelsToColumns(o,!1));var n=f.row;["n","ne","nw"].indexOf(h)!==-1&&(n=e.pixelsToRows(p,!1));var s=f.sizeX;["n","s"].indexOf(h)===-1&&(s=e.pixelsToColumns(q,!0));var t=f.sizeY;["e","w"].indexOf(h)===-1&&(t=e.pixelsToRows(r,!0));var u=n>-1&&m>-1&&s+m<=e.columns&&t+n<=e.maxRows;!u||e.pushing===!1&&0!==e.getItems(n,m,s,t,f).length||(f.row=n,f.col=m,f.sizeX=s,f.sizeY=t);var v=f.row!==b||f.col!==i||f.sizeX!==j||f.sizeY!==k;(l||v)&&d.$apply(function(){l&&e.resizable.resize(a,c,g,f)})}function k(a){c.removeClass("gridster-item-moving"),c.removeClass("gridster-item-resizing"),e.movingItem=null,f.setPosition(f.row,f.col),f.setSizeY(f.sizeY),f.setSizeX(f.sizeX),d.$apply(function(){e.resizable&&e.resizable.stop&&e.resizable.stop(a,c,g,f)})}function l(a){switch(a.which){case 1:break;case 2:case 3:return}return u=e.draggable.enabled,u&&(e.draggable.enabled=!1,d.$broadcast("gridster-draggable-changed",e)),z=a.pageX,A=a.pageY,o=parseInt(c.css("left"),10),p=parseInt(c.css("top"),10),q=c[0].offsetWidth,r=c[0].offsetHeight,s=f.sizeX,t=f.sizeY,i(a),!0}function m(a){var b=e.curWidth-1;x=a.pageX,y=a.pageY;var d=x-z+B,f=y-A+C;B=C=0,z=x,A=y;var g=f,h=d;return w.indexOf("n")>=0&&(r-g<G()?(f=r-G(),C=g-f):p+g<D&&(f=D-p,C=g-f),p+=f,r-=f),w.indexOf("s")>=0&&(r+g<G()?(f=G()-r,C=g-f):p+r+g>E&&(f=E-p-r,C=g-f),r+=f),w.indexOf("w")>=0&&(q-h<H()?(d=q-H(),B=h-d):o+h<F&&(d=F-o,B=h-d),o+=d,q-=d),w.indexOf("e")>=0&&(q+h<H()?(d=H()-q,B=h-d):o+q+h>b&&(d=b-o-q,B=h-d),q+=d),c.css({top:p+"px",left:o+"px",width:q+"px",height:r+"px"}),j(a),!0}function n(a){return e.draggable.enabled!==u&&(e.draggable.enabled=u,d.$broadcast("gridster-draggable-changed",e)),B=C=0,k(a),!0}var o,p,q,r,s,t,u,v,w=h,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=9999,F=0,G=function(){return(f.minSizeY?f.minSizeY:1)*e.curRowHeight-e.margins[0]},H=function(){return(f.minSizeX?f.minSizeX:1)*e.curColWidth-e.margins[1]},I=null;this.enable=function(){I||(I=a.element('<div class="gridster-item-resizable-handler handle-'+w+'"></div>'),c.append(I)),v=new b(I[0],l,m,n),v.enable()},this.disable=function(){I&&(I.remove(),I=null),v.disable(),v=void 0},this.destroy=function(){this.disable()}}var i=[],j=e.resizable.handles;"string"==typeof j&&(j=e.resizable.handles.split(","));for(var k=!1,l=0,m=j.length;l<m;l++)i.push(new h(j[l]));this.enable=function(){if(!k){for(var a=0,b=i.length;a<b;a++)i[a].enable();k=!0}},this.disable=function(){if(k){for(var a=0,b=i.length;a<b;a++)i[a].disable();k=!1}},this.toggle=function(a){a?this.enable():this.disable()},this.destroy=function(){for(var a=0,b=i.length;a<b;a++)i[a].destroy()}}return c}]).factory("gridsterDebounce",function(){return function(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,c||a.apply(e,f)},h=c&&!d;clearTimeout(d),d=setTimeout(g,b),h&&a.apply(e,f)}}}).directive("gridsterItem",["$parse","GridsterDraggable","GridsterResizable","gridsterDebounce",function(a,b,c,d){return{scope:!0,restrict:"EA",controller:"GridsterItemCtrl",controllerAs:"gridsterItem",require:["^gridster","gridsterItem"],link:function(e,f,g,h){function i(){o.setPosition(o.row,o.col),r.row&&r.row.assign&&r.row.assign(e,o.row),r.col&&r.col.assign&&r.col.assign(e,o.col)}function j(){var a=o.setSizeX(o.sizeX,!0);a&&r.sizeX&&r.sizeX.assign&&r.sizeX.assign(e,o.sizeX);var b=o.setSizeY(o.sizeY,!0);b&&r.sizeY&&r.sizeY.assign&&r.sizeY.assign(e,o.sizeY),(a||b)&&(o.gridster.moveOverlappingItems(o),n.layoutChanged(),e.$broadcast("gridster-item-resized",o))}function k(){var a=document.createElement("div"),b={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(var c in b)if(void 0!==a.style[c])return b[c]}var l,m=g.gridsterItem,n=h[0],o=h[1];if(e.gridster=n,m){var p=a(m);l=p(e)||{},!l&&p.assign&&(l={row:o.row,col:o.col,sizeX:o.sizeX,sizeY:o.sizeY,minSizeX:0,minSizeY:0,maxSizeX:null,maxSizeY:null},p.assign(e,l))}else l=g;o.init(f,n),f.addClass("gridster-item");for(var q=["minSizeX","maxSizeX","minSizeY","maxSizeY","sizeX","sizeY","row","col"],r={},s=[],t=function(b){var c;if("string"==typeof l[b])c=l[b];else if("string"==typeof l[b.toLowerCase()])c=l[b.toLowerCase()];else{if(!m)return;c=m+"."+b}s.push('"'+b+'":'+c),r[b]=a(c);var d=r[b](e);"number"==typeof d&&(o[b]=d)},u=0,v=q.length;u<v;++u)t(q[u]);var w="{"+s.join(",")+"}";e.$watchCollection(w,function(a,b){for(var c in a){var d=a[c],e=b[c];e!==d&&(d=parseInt(d,10),isNaN(d)||(o[c]=d))}}),e.$watch(function(){return o.row+","+o.col},i),e.$watch(function(){return o.sizeY+","+o.sizeX+","+o.minSizeX+","+o.maxSizeX+","+o.minSizeY+","+o.maxSizeY},j);var x=new b(f,e,n,o,l),y=new c(f,e,n,o,l),z=function(){y.toggle(!n.isMobile&&n.resizable&&n.resizable.enabled)};z();var A=function(){x.toggle(!n.isMobile&&n.draggable&&n.draggable.enabled)};A(),e.$on("gridster-draggable-changed",A),e.$on("gridster-resizable-changed",z),e.$on("gridster-resized",z),e.$on("gridster-mobile-changed",function(){z(),A()});var B=d(function(){e.$apply(function(){e.$broadcast("gridster-item-transition-end",o)})},50);return f.on(k(),B),e.$broadcast("gridster-item-initialized",o),e.$on("$destroy",function(){try{y.destroy(),x.destroy()}catch(a){}try{n.removeItem(o)}catch(a){}try{o.destroy()}catch(a){}})}}}]).directive("gridsterNoDrag",function(){return{restrict:"A",link:function(a,b){b.addClass("gridster-no-drag")}}})}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.js
new file mode 100644
index 00000000..5fa8499f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.js
@@ -0,0 +1,2239 @@
+/*global define:true*/
+(function(root, factory) {
+
+ 'use strict';
+
+ if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(['angular'], factory);
+ } else if (typeof exports === 'object') {
+ // CommonJS
+ module.exports = factory(require('angular'));
+ } else {
+ // Browser, nothing "exported". Only registered as a module with angular.
+ factory(root.angular);
+ }
+}(this, function(angular) {
+
+ 'use strict';
+
+ // This returned angular module 'gridster' is what is exported.
+ return angular.module('gridster', [])
+
+ .constant('gridsterConfig', {
+ columns: 6, // number of columns in the grid
+ pushing: true, // whether to push other items out of the way
+ floating: true, // whether to automatically float items up so they stack
+ swapping: false, // whether or not to have items switch places instead of push down if they are the same size
+ width: 'auto', // width of the grid. "auto" will expand the grid to its parent container
+ colWidth: 'auto', // width of grid columns. "auto" will divide the width of the grid evenly among the columns
+ rowHeight: 'match', // height of grid rows. 'match' will make it the same as the column width, a numeric value will be interpreted as pixels, '/2' is half the column width, '*5' is five times the column width, etc.
+ margins: [10, 10], // margins in between grid items
+ outerMargin: true,
+ sparse: false, // "true" can increase performance of dragging and resizing for big grid (e.g. 20x50)
+ isMobile: false, // toggle mobile view
+ mobileBreakPoint: 600, // width threshold to toggle mobile mode
+ mobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint
+ minColumns: 1, // minimum amount of columns the grid can scale down to
+ minRows: 1, // minimum amount of rows to show if the grid is empty
+ maxRows: 100, // maximum amount of rows in the grid
+ defaultSizeX: 2, // default width of an item in columns
+ defaultSizeY: 1, // default height of an item in rows
+ minSizeX: 1, // minimum column width of an item
+ maxSizeX: null, // maximum column width of an item
+ minSizeY: 1, // minumum row height of an item
+ maxSizeY: null, // maximum row height of an item
+ saveGridItemCalculatedHeightInMobile: false, // grid item height in mobile display. true- to use the calculated height by sizeY given
+ resizable: { // options to pass to resizable handler
+ enabled: true,
+ handles: ['s', 'e', 'n', 'w', 'se', 'ne', 'sw', 'nw']
+ },
+ draggable: { // options to pass to draggable handler
+ enabled: true,
+ scrollSensitivity: 20, // Distance in pixels from the edge of the viewport after which the viewport should scroll, relative to pointer
+ scrollSpeed: 15 // Speed at which the window should scroll once the mouse pointer gets within scrollSensitivity distance
+ }
+ })
+
+ .controller('GridsterCtrl', ['gridsterConfig', '$timeout',
+ function(gridsterConfig, $timeout) {
+
+ var gridster = this;
+
+ /**
+ * Create options from gridsterConfig constant
+ */
+ angular.extend(this, gridsterConfig);
+
+ this.resizable = angular.extend({}, gridsterConfig.resizable || {});
+ this.draggable = angular.extend({}, gridsterConfig.draggable || {});
+
+ var flag = false;
+ this.layoutChanged = function() {
+ if (flag) {
+ return;
+ }
+ flag = true;
+ $timeout(function() {
+ flag = false;
+ if (gridster.loaded) {
+ gridster.floatItemsUp();
+ }
+ gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);
+ }, 30);
+ };
+
+ /**
+ * A positional array of the items in the grid
+ */
+ this.grid = [];
+ this.allItems = [];
+
+ /**
+ * Clean up after yourself
+ */
+ this.destroy = function() {
+ // empty the grid to cut back on the possibility
+ // of circular references
+ if (this.grid) {
+ this.grid = [];
+ }
+ this.$element = null;
+
+ if (this.allItems) {
+ this.allItems.length = 0;
+ this.allItems = null;
+ }
+ };
+
+ /**
+ * Overrides default options
+ *
+ * @param {Object} options The options to override
+ */
+ this.setOptions = function(options) {
+ if (!options) {
+ return;
+ }
+
+ options = angular.extend({}, options);
+
+ // all this to avoid using jQuery...
+ if (options.draggable) {
+ angular.extend(this.draggable, options.draggable);
+ delete(options.draggable);
+ }
+ if (options.resizable) {
+ angular.extend(this.resizable, options.resizable);
+ delete(options.resizable);
+ }
+
+ angular.extend(this, options);
+
+ if (!this.margins || this.margins.length !== 2) {
+ this.margins = [0, 0];
+ } else {
+ for (var x = 0, l = this.margins.length; x < l; ++x) {
+ this.margins[x] = parseInt(this.margins[x], 10);
+ if (isNaN(this.margins[x])) {
+ this.margins[x] = 0;
+ }
+ }
+ }
+ };
+
+ /**
+ * Check if item can occupy a specified position in the grid
+ *
+ * @param {Object} item The item in question
+ * @param {Number} row The row index
+ * @param {Number} column The column index
+ * @returns {Boolean} True if if item fits
+ */
+ this.canItemOccupy = function(item, row, column) {
+ return row > -1 && column > -1 && item.sizeX + column <= this.columns && item.sizeY + row <= this.maxRows;
+ };
+
+ /**
+ * Set the item in the first suitable position
+ *
+ * @param {Object} item The item to insert
+ */
+ this.autoSetItemPosition = function(item) {
+ // walk through each row and column looking for a place it will fit
+ for (var rowIndex = 0; rowIndex < this.maxRows; ++rowIndex) {
+ for (var colIndex = 0; colIndex < this.columns; ++colIndex) {
+ // only insert if position is not already taken and it can fit
+ var items = this.getItems(rowIndex, colIndex, item.sizeX, item.sizeY, item);
+ if (items.length === 0 && this.canItemOccupy(item, rowIndex, colIndex)) {
+ this.putItem(item, rowIndex, colIndex);
+ return;
+ }
+ }
+ }
+ throw new Error('Unable to place item!');
+ };
+
+ /**
+ * Gets items at a specific coordinate
+ *
+ * @param {Number} row
+ * @param {Number} column
+ * @param {Number} sizeX
+ * @param {Number} sizeY
+ * @param {Array} excludeItems An array of items to exclude from selection
+ * @returns {Array} Items that match the criteria
+ */
+ this.getItems = function(row, column, sizeX, sizeY, excludeItems) {
+ var items = [];
+ if (!sizeX || !sizeY) {
+ sizeX = sizeY = 1;
+ }
+ if (excludeItems && !(excludeItems instanceof Array)) {
+ excludeItems = [excludeItems];
+ }
+ var item;
+ if (this.sparse === false) { // check all cells
+ for (var h = 0; h < sizeY; ++h) {
+ for (var w = 0; w < sizeX; ++w) {
+ item = this.getItem(row + h, column + w, excludeItems);
+ if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1) {
+ items.push(item);
+ }
+ }
+ }
+ } else { // check intersection with all items
+ var bottom = row + sizeY - 1;
+ var right = column + sizeX - 1;
+ for (var i = 0; i < this.allItems.length; ++i) {
+ item = this.allItems[i];
+ if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1 && this.intersect(item, column, right, row, bottom)) {
+ items.push(item);
+ }
+ }
+ }
+ return items;
+ };
+
+ /**
+ * @param {Array} items
+ * @returns {Object} An item that represents the bounding box of the items
+ */
+ this.getBoundingBox = function(items) {
+
+ if (items.length === 0) {
+ return null;
+ }
+ if (items.length === 1) {
+ return {
+ row: items[0].row,
+ col: items[0].col,
+ sizeY: items[0].sizeY,
+ sizeX: items[0].sizeX
+ };
+ }
+
+ var maxRow = 0;
+ var maxCol = 0;
+ var minRow = 9999;
+ var minCol = 9999;
+
+ for (var i = 0, l = items.length; i < l; ++i) {
+ var item = items[i];
+ minRow = Math.min(item.row, minRow);
+ minCol = Math.min(item.col, minCol);
+ maxRow = Math.max(item.row + item.sizeY, maxRow);
+ maxCol = Math.max(item.col + item.sizeX, maxCol);
+ }
+
+ return {
+ row: minRow,
+ col: minCol,
+ sizeY: maxRow - minRow,
+ sizeX: maxCol - minCol
+ };
+ };
+
+ /**
+ * Checks if item intersects specified box
+ *
+ * @param {object} item
+ * @param {number} left
+ * @param {number} right
+ * @param {number} top
+ * @param {number} bottom
+ */
+
+ this.intersect = function(item, left, right, top, bottom) {
+ return (left <= item.col + item.sizeX - 1 &&
+ right >= item.col &&
+ top <= item.row + item.sizeY - 1 &&
+ bottom >= item.row);
+ };
+
+
+ /**
+ * Removes an item from the grid
+ *
+ * @param {Object} item
+ */
+ this.removeItem = function(item) {
+ var index;
+ for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ index = columns.indexOf(item);
+ if (index !== -1) {
+ columns[index] = null;
+ break;
+ }
+ }
+ if (this.sparse) {
+ index = this.allItems.indexOf(item);
+ if (index !== -1) {
+ this.allItems.splice(index, 1);
+ }
+ }
+ this.layoutChanged();
+ };
+
+ /**
+ * Returns the item at a specified coordinate
+ *
+ * @param {Number} row
+ * @param {Number} column
+ * @param {Array} excludeItems Items to exclude from selection
+ * @returns {Object} The matched item or null
+ */
+ this.getItem = function(row, column, excludeItems) {
+ if (excludeItems && !(excludeItems instanceof Array)) {
+ excludeItems = [excludeItems];
+ }
+ var sizeY = 1;
+ while (row > -1) {
+ var sizeX = 1,
+ col = column;
+ while (col > -1) {
+ var items = this.grid[row];
+ if (items) {
+ var item = items[col];
+ if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && item.sizeX >= sizeX && item.sizeY >= sizeY) {
+ return item;
+ }
+ }
+ ++sizeX;
+ --col;
+ }
+ --row;
+ ++sizeY;
+ }
+ return null;
+ };
+
+ /**
+ * Insert an array of items into the grid
+ *
+ * @param {Array} items An array of items to insert
+ */
+ this.putItems = function(items) {
+ for (var i = 0, l = items.length; i < l; ++i) {
+ this.putItem(items[i]);
+ }
+ };
+
+ /**
+ * Insert a single item into the grid
+ *
+ * @param {Object} item The item to insert
+ * @param {Number} row (Optional) Specifies the items row index
+ * @param {Number} column (Optional) Specifies the items column index
+ * @param {Array} ignoreItems
+ */
+ this.putItem = function(item, row, column, ignoreItems) {
+ // auto place item if no row specified
+ if (typeof row === 'undefined' || row === null) {
+ row = item.row;
+ column = item.col;
+ if (typeof row === 'undefined' || row === null) {
+ this.autoSetItemPosition(item);
+ return;
+ }
+ }
+
+ // keep item within allowed bounds
+ if (!this.canItemOccupy(item, row, column)) {
+ column = Math.min(this.columns - item.sizeX, Math.max(0, column));
+ row = Math.min(this.maxRows - item.sizeY, Math.max(0, row));
+ }
+
+ // check if item is already in grid
+ if (item.oldRow !== null && typeof item.oldRow !== 'undefined') {
+ var samePosition = item.oldRow === row && item.oldColumn === column;
+ var inGrid = this.grid[row] && this.grid[row][column] === item;
+ if (samePosition && inGrid) {
+ item.row = row;
+ item.col = column;
+ return;
+ } else {
+ // remove from old position
+ var oldRow = this.grid[item.oldRow];
+ if (oldRow && oldRow[item.oldColumn] === item) {
+ delete oldRow[item.oldColumn];
+ }
+ }
+ }
+
+ item.oldRow = item.row = row;
+ item.oldColumn = item.col = column;
+
+ this.moveOverlappingItems(item, ignoreItems);
+
+ if (!this.grid[row]) {
+ this.grid[row] = [];
+ }
+ this.grid[row][column] = item;
+
+ if (this.sparse && this.allItems.indexOf(item) === -1) {
+ this.allItems.push(item);
+ }
+
+ if (this.movingItem === item) {
+ this.floatItemUp(item);
+ }
+ this.layoutChanged();
+ };
+
+ /**
+ * Trade row and column if item1 with item2
+ *
+ * @param {Object} item1
+ * @param {Object} item2
+ */
+ this.swapItems = function(item1, item2) {
+ this.grid[item1.row][item1.col] = item2;
+ this.grid[item2.row][item2.col] = item1;
+
+ var item1Row = item1.row;
+ var item1Col = item1.col;
+ item1.row = item2.row;
+ item1.col = item2.col;
+ item2.row = item1Row;
+ item2.col = item1Col;
+ };
+
+ /**
+ * Prevents items from being overlapped
+ *
+ * @param {Object} item The item that should remain
+ * @param {Array} ignoreItems
+ */
+ this.moveOverlappingItems = function(item, ignoreItems) {
+ // don't move item, so ignore it
+ if (!ignoreItems) {
+ ignoreItems = [item];
+ } else if (ignoreItems.indexOf(item) === -1) {
+ ignoreItems = ignoreItems.slice(0);
+ ignoreItems.push(item);
+ }
+
+ // get the items in the space occupied by the item's coordinates
+ var overlappingItems = this.getItems(
+ item.row,
+ item.col,
+ item.sizeX,
+ item.sizeY,
+ ignoreItems
+ );
+ this.moveItemsDown(overlappingItems, item.row + item.sizeY, ignoreItems);
+ };
+
+ /**
+ * Moves an array of items to a specified row
+ *
+ * @param {Array} items The items to move
+ * @param {Number} newRow The target row
+ * @param {Array} ignoreItems
+ */
+ this.moveItemsDown = function(items, newRow, ignoreItems) {
+ if (!items || items.length === 0) {
+ return;
+ }
+ items.sort(function(a, b) {
+ return a.row - b.row;
+ });
+
+ ignoreItems = ignoreItems ? ignoreItems.slice(0) : [];
+ var topRows = {},
+ item, i, l;
+
+ // calculate the top rows in each column
+ for (i = 0, l = items.length; i < l; ++i) {
+ item = items[i];
+ var topRow = topRows[item.col];
+ if (typeof topRow === 'undefined' || item.row < topRow) {
+ topRows[item.col] = item.row;
+ }
+ }
+
+ // move each item down from the top row in its column to the row
+ for (i = 0, l = items.length; i < l; ++i) {
+ item = items[i];
+ var rowsToMove = newRow - topRows[item.col];
+ this.moveItemDown(item, item.row + rowsToMove, ignoreItems);
+ ignoreItems.push(item);
+ }
+ };
+
+ /**
+ * Moves an item down to a specified row
+ *
+ * @param {Object} item The item to move
+ * @param {Number} newRow The target row
+ * @param {Array} ignoreItems
+ */
+ this.moveItemDown = function(item, newRow, ignoreItems) {
+ if (item.row >= newRow) {
+ return;
+ }
+ while (item.row < newRow) {
+ ++item.row;
+ this.moveOverlappingItems(item, ignoreItems);
+ }
+ this.putItem(item, item.row, item.col, ignoreItems);
+ };
+
+ /**
+ * Moves all items up as much as possible
+ */
+ this.floatItemsUp = function() {
+ if (this.floating === false) {
+ return;
+ }
+ for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ var item = columns[colIndex];
+ if (item) {
+ this.floatItemUp(item);
+ }
+ }
+ }
+ };
+
+ /**
+ * Float an item up to the most suitable row
+ *
+ * @param {Object} item The item to move
+ */
+ this.floatItemUp = function(item) {
+ if (this.floating === false) {
+ return;
+ }
+ var colIndex = item.col,
+ sizeY = item.sizeY,
+ sizeX = item.sizeX,
+ bestRow = null,
+ bestColumn = null,
+ rowIndex = item.row - 1;
+
+ while (rowIndex > -1) {
+ var items = this.getItems(rowIndex, colIndex, sizeX, sizeY, item);
+ if (items.length !== 0) {
+ break;
+ }
+ bestRow = rowIndex;
+ bestColumn = colIndex;
+ --rowIndex;
+ }
+ if (bestRow !== null) {
+ this.putItem(item, bestRow, bestColumn);
+ }
+ };
+
+ /**
+ * Update gridsters height
+ *
+ * @param {Number} plus (Optional) Additional height to add
+ */
+ this.updateHeight = function(plus) {
+ var maxHeight = this.minRows;
+ plus = plus || 0;
+ for (var rowIndex = this.grid.length; rowIndex >= 0; --rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ if (columns[colIndex]) {
+ maxHeight = Math.max(maxHeight, rowIndex + plus + columns[colIndex].sizeY);
+ }
+ }
+ }
+ this.gridHeight = this.maxRows - maxHeight > 0 ? Math.min(this.maxRows, maxHeight) : Math.max(this.maxRows, maxHeight);
+ };
+
+ /**
+ * Returns the number of rows that will fit in given amount of pixels
+ *
+ * @param {Number} pixels
+ * @param {Boolean} ceilOrFloor (Optional) Determines rounding method
+ */
+ this.pixelsToRows = function(pixels, ceilOrFloor) {
+ if (!this.outerMargin) {
+ pixels += this.margins[0] / 2;
+ }
+
+ if (ceilOrFloor === true) {
+ return Math.ceil(pixels / this.curRowHeight);
+ } else if (ceilOrFloor === false) {
+ return Math.floor(pixels / this.curRowHeight);
+ }
+
+ return Math.round(pixels / this.curRowHeight);
+ };
+
+ /**
+ * Returns the number of columns that will fit in a given amount of pixels
+ *
+ * @param {Number} pixels
+ * @param {Boolean} ceilOrFloor (Optional) Determines rounding method
+ * @returns {Number} The number of columns
+ */
+ this.pixelsToColumns = function(pixels, ceilOrFloor) {
+ if (!this.outerMargin) {
+ pixels += this.margins[1] / 2;
+ }
+
+ if (ceilOrFloor === true) {
+ return Math.ceil(pixels / this.curColWidth);
+ } else if (ceilOrFloor === false) {
+ return Math.floor(pixels / this.curColWidth);
+ }
+
+ return Math.round(pixels / this.curColWidth);
+ };
+ }
+ ])
+
+ .directive('gridsterPreview', function() {
+ return {
+ replace: true,
+ scope: true,
+ require: '^gridster',
+ template: '<div ng-style="previewStyle()" class="gridster-item gridster-preview-holder"></div>',
+ link: function(scope, $el, attrs, gridster) {
+
+ /**
+ * @returns {Object} style object for preview element
+ */
+ scope.previewStyle = function() {
+ if (!gridster.movingItem) {
+ return {
+ display: 'none'
+ };
+ }
+
+ return {
+ display: 'block',
+ height: (gridster.movingItem.sizeY * gridster.curRowHeight - gridster.margins[0]) + 'px',
+ width: (gridster.movingItem.sizeX * gridster.curColWidth - gridster.margins[1]) + 'px',
+ top: (gridster.movingItem.row * gridster.curRowHeight + (gridster.outerMargin ? gridster.margins[0] : 0)) + 'px',
+ left: (gridster.movingItem.col * gridster.curColWidth + (gridster.outerMargin ? gridster.margins[1] : 0)) + 'px'
+ };
+ };
+ }
+ };
+ })
+
+ /**
+ * The gridster directive
+ *
+ * @param {Function} $timeout
+ * @param {Object} $window
+ * @param {Object} $rootScope
+ * @param {Function} gridsterDebounce
+ */
+ .directive('gridster', ['$timeout', '$window', '$rootScope', 'gridsterDebounce',
+ function($timeout, $window, $rootScope, gridsterDebounce) {
+ return {
+ scope: true,
+ restrict: 'EAC',
+ controller: 'GridsterCtrl',
+ controllerAs: 'gridster',
+ compile: function($tplElem) {
+
+ $tplElem.prepend('<div ng-if="gridster.movingItem" gridster-preview></div>');
+
+ return function(scope, $elem, attrs, gridster) {
+ gridster.loaded = false;
+
+ gridster.$element = $elem;
+
+ scope.gridster = gridster;
+
+ $elem.addClass('gridster');
+
+ var isVisible = function(ele) {
+ return ele.style.visibility !== 'hidden' && ele.style.display !== 'none';
+ };
+
+ function updateHeight() {
+ $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');
+ }
+
+ scope.$watch(function() {
+ return gridster.gridHeight;
+ }, updateHeight);
+
+ scope.$watch(function() {
+ return gridster.movingItem;
+ }, function() {
+ gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);
+ });
+
+ function refresh(config) {
+ gridster.setOptions(config);
+
+ if (!isVisible($elem[0])) {
+ return;
+ }
+
+ // resolve "auto" & "match" values
+ if (gridster.width === 'auto') {
+ gridster.curWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+ } else {
+ gridster.curWidth = gridster.width;
+ }
+
+ if (gridster.colWidth === 'auto') {
+ gridster.curColWidth = (gridster.curWidth + (gridster.outerMargin ? -gridster.margins[1] : gridster.margins[1])) / gridster.columns;
+ } else {
+ gridster.curColWidth = gridster.colWidth;
+ }
+
+ gridster.curRowHeight = gridster.rowHeight;
+ if (typeof gridster.rowHeight === 'string') {
+ if (gridster.rowHeight === 'match') {
+ gridster.curRowHeight = Math.round(gridster.curColWidth);
+ } else if (gridster.rowHeight.indexOf('*') !== -1) {
+ gridster.curRowHeight = Math.round(gridster.curColWidth * gridster.rowHeight.replace('*', '').replace(' ', ''));
+ } else if (gridster.rowHeight.indexOf('/') !== -1) {
+ gridster.curRowHeight = Math.round(gridster.curColWidth / gridster.rowHeight.replace('/', '').replace(' ', ''));
+ }
+ }
+
+ gridster.isMobile = gridster.mobileModeEnabled && gridster.curWidth <= gridster.mobileBreakPoint;
+
+ // loop through all items and reset their CSS
+ for (var rowIndex = 0, l = gridster.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = gridster.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ if (columns[colIndex]) {
+ var item = columns[colIndex];
+ item.setElementPosition();
+ item.setElementSizeY();
+ item.setElementSizeX();
+ }
+ }
+ }
+
+ updateHeight();
+ }
+
+ var optionsKey = attrs.gridster;
+ if (optionsKey) {
+ scope.$parent.$watch(optionsKey, function(newConfig) {
+ refresh(newConfig);
+ }, true);
+ } else {
+ refresh({});
+ }
+
+ scope.$watch(function() {
+ return gridster.loaded;
+ }, function() {
+ if (gridster.loaded) {
+ $elem.addClass('gridster-loaded');
+ $rootScope.$broadcast('gridster-loaded', gridster);
+ } else {
+ $elem.removeClass('gridster-loaded');
+ }
+ });
+
+ scope.$watch(function() {
+ return gridster.isMobile;
+ }, function() {
+ if (gridster.isMobile) {
+ $elem.addClass('gridster-mobile').removeClass('gridster-desktop');
+ } else {
+ $elem.removeClass('gridster-mobile').addClass('gridster-desktop');
+ }
+ $rootScope.$broadcast('gridster-mobile-changed', gridster);
+ });
+
+ scope.$watch(function() {
+ return gridster.draggable;
+ }, function() {
+ $rootScope.$broadcast('gridster-draggable-changed', gridster);
+ }, true);
+
+ scope.$watch(function() {
+ return gridster.resizable;
+ }, function() {
+ $rootScope.$broadcast('gridster-resizable-changed', gridster);
+ }, true);
+
+ var prevWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+
+ var resize = function() {
+ var width = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+
+ if (!width || width === prevWidth || gridster.movingItem) {
+ return;
+ }
+ prevWidth = width;
+
+ if (gridster.loaded) {
+ $elem.removeClass('gridster-loaded');
+ }
+
+ refresh();
+
+ if (gridster.loaded) {
+ $elem.addClass('gridster-loaded');
+ }
+
+ $rootScope.$broadcast('gridster-resized', [width, $elem[0].offsetHeight], gridster);
+ };
+
+ // track element width changes any way we can
+ var onResize = gridsterDebounce(function onResize() {
+ resize();
+ $timeout(function() {
+ scope.$apply();
+ });
+ }, 100);
+
+ scope.$watch(function() {
+ return isVisible($elem[0]);
+ }, onResize);
+
+ // see https://github.com/sdecima/javascript-detect-element-resize
+ if (typeof window.addResizeListener === 'function') {
+ window.addResizeListener($elem[0], onResize);
+ } else {
+ scope.$watch(function() {
+ return $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+ }, resize);
+ }
+ var $win = angular.element($window);
+ $win.on('resize', onResize);
+
+ // be sure to cleanup
+ scope.$on('$destroy', function() {
+ gridster.destroy();
+ $win.off('resize', onResize);
+ if (typeof window.removeResizeListener === 'function') {
+ window.removeResizeListener($elem[0], onResize);
+ }
+ });
+
+ // allow a little time to place items before floating up
+ $timeout(function() {
+ scope.$watch('gridster.floating', function() {
+ gridster.floatItemsUp();
+ });
+ gridster.loaded = true;
+ }, 100);
+ };
+ }
+ };
+ }
+ ])
+
+ .controller('GridsterItemCtrl', function() {
+ this.$element = null;
+ this.gridster = null;
+ this.row = null;
+ this.col = null;
+ this.sizeX = null;
+ this.sizeY = null;
+ this.minSizeX = 0;
+ this.minSizeY = 0;
+ this.maxSizeX = null;
+ this.maxSizeY = null;
+
+ this.init = function($element, gridster) {
+ this.$element = $element;
+ this.gridster = gridster;
+ this.sizeX = gridster.defaultSizeX;
+ this.sizeY = gridster.defaultSizeY;
+ };
+
+ this.destroy = function() {
+ // set these to null to avoid the possibility of circular references
+ this.gridster = null;
+ this.$element = null;
+ };
+
+ /**
+ * Returns the items most important attributes
+ */
+ this.toJSON = function() {
+ return {
+ row: this.row,
+ col: this.col,
+ sizeY: this.sizeY,
+ sizeX: this.sizeX
+ };
+ };
+
+ this.isMoving = function() {
+ return this.gridster.movingItem === this;
+ };
+
+ /**
+ * Set the items position
+ *
+ * @param {Number} row
+ * @param {Number} column
+ */
+ this.setPosition = function(row, column) {
+ this.gridster.putItem(this, row, column);
+
+ if (!this.isMoving()) {
+ this.setElementPosition();
+ }
+ };
+
+ /**
+ * Sets a specified size property
+ *
+ * @param {String} key Can be either "x" or "y"
+ * @param {Number} value The size amount
+ * @param {Boolean} preventMove
+ */
+ this.setSize = function(key, value, preventMove) {
+ key = key.toUpperCase();
+ var camelCase = 'size' + key,
+ titleCase = 'Size' + key;
+ if (value === '') {
+ return;
+ }
+ value = parseInt(value, 10);
+ if (isNaN(value) || value === 0) {
+ value = this.gridster['default' + titleCase];
+ }
+ var max = key === 'X' ? this.gridster.columns : this.gridster.maxRows;
+ if (this['max' + titleCase]) {
+ max = Math.min(this['max' + titleCase], max);
+ }
+ if (this.gridster['max' + titleCase]) {
+ max = Math.min(this.gridster['max' + titleCase], max);
+ }
+ if (key === 'X' && this.cols) {
+ max -= this.cols;
+ } else if (key === 'Y' && this.rows) {
+ max -= this.rows;
+ }
+
+ var min = 0;
+ if (this['min' + titleCase]) {
+ min = Math.max(this['min' + titleCase], min);
+ }
+ if (this.gridster['min' + titleCase]) {
+ min = Math.max(this.gridster['min' + titleCase], min);
+ }
+
+ value = Math.max(Math.min(value, max), min);
+
+ var changed = (this[camelCase] !== value || (this['old' + titleCase] && this['old' + titleCase] !== value));
+ this['old' + titleCase] = this[camelCase] = value;
+
+ if (!this.isMoving()) {
+ this['setElement' + titleCase]();
+ }
+ if (!preventMove && changed) {
+ this.gridster.moveOverlappingItems(this);
+ this.gridster.layoutChanged();
+ }
+
+ return changed;
+ };
+
+ /**
+ * Sets the items sizeY property
+ *
+ * @param {Number} rows
+ * @param {Boolean} preventMove
+ */
+ this.setSizeY = function(rows, preventMove) {
+ return this.setSize('Y', rows, preventMove);
+ };
+
+ /**
+ * Sets the items sizeX property
+ *
+ * @param {Number} columns
+ * @param {Boolean} preventMove
+ */
+ this.setSizeX = function(columns, preventMove) {
+ return this.setSize('X', columns, preventMove);
+ };
+
+ /**
+ * Sets an elements position on the page
+ */
+ this.setElementPosition = function() {
+ if (this.gridster.isMobile) {
+ this.$element.css({
+ marginLeft: this.gridster.margins[0] + 'px',
+ marginRight: this.gridster.margins[0] + 'px',
+ marginTop: this.gridster.margins[1] + 'px',
+ marginBottom: this.gridster.margins[1] + 'px',
+ top: '',
+ left: ''
+ });
+ } else {
+ this.$element.css({
+ margin: 0,
+ top: (this.row * this.gridster.curRowHeight + (this.gridster.outerMargin ? this.gridster.margins[0] : 0)) + 'px',
+ left: (this.col * this.gridster.curColWidth + (this.gridster.outerMargin ? this.gridster.margins[1] : 0)) + 'px'
+ });
+ }
+ };
+
+ /**
+ * Sets an elements height
+ */
+ this.setElementSizeY = function() {
+ if (this.gridster.isMobile && !this.gridster.saveGridItemCalculatedHeightInMobile) {
+ this.$element.css('height', '');
+ } else {
+ this.$element.css('height', (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]) + 'px');
+ }
+ };
+
+ /**
+ * Sets an elements width
+ */
+ this.setElementSizeX = function() {
+ if (this.gridster.isMobile) {
+ this.$element.css('width', '');
+ } else {
+ this.$element.css('width', (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]) + 'px');
+ }
+ };
+
+ /**
+ * Gets an element's width
+ */
+ this.getElementSizeX = function() {
+ return (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]);
+ };
+
+ /**
+ * Gets an element's height
+ */
+ this.getElementSizeY = function() {
+ return (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]);
+ };
+
+ })
+
+ .factory('GridsterTouch', [function() {
+ return function GridsterTouch(target, startEvent, moveEvent, endEvent) {
+ var lastXYById = {};
+
+ // Opera doesn't have Object.keys so we use this wrapper
+ var numberOfKeys = function(theObject) {
+ if (Object.keys) {
+ return Object.keys(theObject).length;
+ }
+
+ var n = 0,
+ key;
+ for (key in theObject) {
+ ++n;
+ }
+
+ return n;
+ };
+
+ // this calculates the delta needed to convert pageX/Y to offsetX/Y because offsetX/Y don't exist in the TouchEvent object or in Firefox's MouseEvent object
+ var computeDocumentToElementDelta = function(theElement) {
+ var elementLeft = 0;
+ var elementTop = 0;
+ var oldIEUserAgent = navigator.userAgent.match(/\bMSIE\b/);
+
+ for (var offsetElement = theElement; offsetElement != null; offsetElement = offsetElement.offsetParent) {
+ // the following is a major hack for versions of IE less than 8 to avoid an apparent problem on the IEBlog with double-counting the offsets
+ // this may not be a general solution to IE7's problem with offsetLeft/offsetParent
+ if (oldIEUserAgent &&
+ (!document.documentMode || document.documentMode < 8) &&
+ offsetElement.currentStyle.position === 'relative' && offsetElement.offsetParent && offsetElement.offsetParent.currentStyle.position === 'relative' && offsetElement.offsetLeft === offsetElement.offsetParent.offsetLeft) {
+ // add only the top
+ elementTop += offsetElement.offsetTop;
+ } else {
+ elementLeft += offsetElement.offsetLeft;
+ elementTop += offsetElement.offsetTop;
+ }
+ }
+
+ return {
+ x: elementLeft,
+ y: elementTop
+ };
+ };
+
+ // cache the delta from the document to our event target (reinitialized each mousedown/MSPointerDown/touchstart)
+ var documentToTargetDelta = computeDocumentToElementDelta(target);
+ var useSetReleaseCapture = false;
+
+ // common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events
+ var doEvent = function(theEvtObj) {
+
+ if (theEvtObj.type === 'mousemove' && numberOfKeys(lastXYById) === 0) {
+ return;
+ }
+
+ var prevent = true;
+
+ var pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];
+ for (var i = 0; i < pointerList.length; ++i) {
+ var pointerObj = pointerList[i];
+ var pointerId = (typeof pointerObj.identifier !== 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId !== 'undefined') ? pointerObj.pointerId : 1;
+
+ // use the pageX/Y coordinates to compute target-relative coordinates when we have them (in ie < 9, we need to do a little work to put them there)
+ if (typeof pointerObj.pageX === 'undefined') {
+ // initialize assuming our source element is our target
+ pointerObj.pageX = pointerObj.offsetX + documentToTargetDelta.x;
+ pointerObj.pageY = pointerObj.offsetY + documentToTargetDelta.y;
+
+ if (pointerObj.srcElement.offsetParent === target && document.documentMode && document.documentMode === 8 && pointerObj.type === 'mousedown') {
+ // source element is a child piece of VML, we're in IE8, and we've not called setCapture yet - add the origin of the source element
+ pointerObj.pageX += pointerObj.srcElement.offsetLeft;
+ pointerObj.pageY += pointerObj.srcElement.offsetTop;
+ } else if (pointerObj.srcElement !== target && !document.documentMode || document.documentMode < 8) {
+ // source element isn't the target (most likely it's a child piece of VML) and we're in a version of IE before IE8 -
+ // the offsetX/Y values are unpredictable so use the clientX/Y values and adjust by the scroll offsets of its parents
+ // to get the document-relative coordinates (the same as pageX/Y)
+ var sx = -2,
+ sy = -2; // adjust for old IE's 2-pixel border
+ for (var scrollElement = pointerObj.srcElement; scrollElement !== null; scrollElement = scrollElement.parentNode) {
+ sx += scrollElement.scrollLeft ? scrollElement.scrollLeft : 0;
+ sy += scrollElement.scrollTop ? scrollElement.scrollTop : 0;
+ }
+
+ pointerObj.pageX = pointerObj.clientX + sx;
+ pointerObj.pageY = pointerObj.clientY + sy;
+ }
+ }
+
+
+ var pageX = pointerObj.pageX;
+ var pageY = pointerObj.pageY;
+
+ if (theEvtObj.type.match(/(start|down)$/i)) {
+ // clause for processing MSPointerDown, touchstart, and mousedown
+
+ // refresh the document-to-target delta on start in case the target has moved relative to document
+ documentToTargetDelta = computeDocumentToElementDelta(target);
+
+ // protect against failing to get an up or end on this pointerId
+ if (lastXYById[pointerId]) {
+ if (endEvent) {
+ endEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ delete lastXYById[pointerId];
+ }
+
+ if (startEvent) {
+ if (prevent) {
+ prevent = startEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+ }
+
+ // init last page positions for this pointer
+ lastXYById[pointerId] = {
+ x: pageX,
+ y: pageY
+ };
+
+ // IE pointer model
+ if (target.msSetPointerCapture && prevent) {
+ target.msSetPointerCapture(pointerId);
+ } else if (theEvtObj.type === 'mousedown' && numberOfKeys(lastXYById) === 1) {
+ if (useSetReleaseCapture) {
+ target.setCapture(true);
+ } else {
+ document.addEventListener('mousemove', doEvent, false);
+ document.addEventListener('mouseup', doEvent, false);
+ }
+ }
+ } else if (theEvtObj.type.match(/move$/i)) {
+ // clause handles mousemove, MSPointerMove, and touchmove
+
+ if (lastXYById[pointerId] && !(lastXYById[pointerId].x === pageX && lastXYById[pointerId].y === pageY)) {
+ // only extend if the pointer is down and it's not the same as the last point
+
+ if (moveEvent && prevent) {
+ prevent = moveEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ // update last page positions for this pointer
+ lastXYById[pointerId].x = pageX;
+ lastXYById[pointerId].y = pageY;
+ }
+ } else if (lastXYById[pointerId] && theEvtObj.type.match(/(up|end|cancel)$/i)) {
+ // clause handles up/end/cancel
+
+ if (endEvent && prevent) {
+ prevent = endEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ // delete last page positions for this pointer
+ delete lastXYById[pointerId];
+
+ // in the Microsoft pointer model, release the capture for this pointer
+ // in the mouse model, release the capture or remove document-level event handlers if there are no down points
+ // nothing is required for the iOS touch model because capture is implied on touchstart
+ if (target.msReleasePointerCapture) {
+ target.msReleasePointerCapture(pointerId);
+ } else if (theEvtObj.type === 'mouseup' && numberOfKeys(lastXYById) === 0) {
+ if (useSetReleaseCapture) {
+ target.releaseCapture();
+ } else {
+ document.removeEventListener('mousemove', doEvent, false);
+ document.removeEventListener('mouseup', doEvent, false);
+ }
+ }
+ }
+ }
+
+ if (prevent) {
+ if (theEvtObj.preventDefault) {
+ theEvtObj.preventDefault();
+ }
+
+ if (theEvtObj.preventManipulation) {
+ theEvtObj.preventManipulation();
+ }
+
+ if (theEvtObj.preventMouseEvent) {
+ theEvtObj.preventMouseEvent();
+ }
+ }
+ };
+
+ // saving the settings for contentZooming and touchaction before activation
+ var contentZooming, msTouchAction;
+
+ this.enable = function() {
+
+ if (window.navigator.msPointerEnabled) {
+ // Microsoft pointer model
+ target.addEventListener('MSPointerDown', doEvent, false);
+ target.addEventListener('MSPointerMove', doEvent, false);
+ target.addEventListener('MSPointerUp', doEvent, false);
+ target.addEventListener('MSPointerCancel', doEvent, false);
+
+ // css way to prevent panning in our target area
+ if (typeof target.style.msContentZooming !== 'undefined') {
+ contentZooming = target.style.msContentZooming;
+ target.style.msContentZooming = 'none';
+ }
+
+ // new in Windows Consumer Preview: css way to prevent all built-in touch actions on our target
+ // without this, you cannot touch draw on the element because IE will intercept the touch events
+ if (typeof target.style.msTouchAction !== 'undefined') {
+ msTouchAction = target.style.msTouchAction;
+ target.style.msTouchAction = 'none';
+ }
+ } else if (target.addEventListener) {
+ // iOS touch model
+ target.addEventListener('touchstart', doEvent, false);
+ target.addEventListener('touchmove', doEvent, false);
+ target.addEventListener('touchend', doEvent, false);
+ target.addEventListener('touchcancel', doEvent, false);
+
+ // mouse model
+ target.addEventListener('mousedown', doEvent, false);
+
+ // mouse model with capture
+ // rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target
+ if (target.setCapture && !window.navigator.userAgent.match(/\bGecko\b/)) {
+ useSetReleaseCapture = true;
+
+ target.addEventListener('mousemove', doEvent, false);
+ target.addEventListener('mouseup', doEvent, false);
+ }
+ } else if (target.attachEvent && target.setCapture) {
+ // legacy IE mode - mouse with capture
+ useSetReleaseCapture = true;
+ target.attachEvent('onmousedown', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ target.attachEvent('onmousemove', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ target.attachEvent('onmouseup', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ }
+ };
+
+ this.disable = function() {
+ if (window.navigator.msPointerEnabled) {
+ // Microsoft pointer model
+ target.removeEventListener('MSPointerDown', doEvent, false);
+ target.removeEventListener('MSPointerMove', doEvent, false);
+ target.removeEventListener('MSPointerUp', doEvent, false);
+ target.removeEventListener('MSPointerCancel', doEvent, false);
+
+ // reset zooming to saved value
+ if (contentZooming) {
+ target.style.msContentZooming = contentZooming;
+ }
+
+ // reset touch action setting
+ if (msTouchAction) {
+ target.style.msTouchAction = msTouchAction;
+ }
+ } else if (target.removeEventListener) {
+ // iOS touch model
+ target.removeEventListener('touchstart', doEvent, false);
+ target.removeEventListener('touchmove', doEvent, false);
+ target.removeEventListener('touchend', doEvent, false);
+ target.removeEventListener('touchcancel', doEvent, false);
+
+ // mouse model
+ target.removeEventListener('mousedown', doEvent, false);
+
+ // mouse model with capture
+ // rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target
+ if (target.setCapture && !window.navigator.userAgent.match(/\bGecko\b/)) {
+ useSetReleaseCapture = true;
+
+ target.removeEventListener('mousemove', doEvent, false);
+ target.removeEventListener('mouseup', doEvent, false);
+ }
+ } else if (target.detachEvent && target.setCapture) {
+ // legacy IE mode - mouse with capture
+ useSetReleaseCapture = true;
+ target.detachEvent('onmousedown');
+ target.detachEvent('onmousemove');
+ target.detachEvent('onmouseup');
+ }
+ };
+
+ return this;
+ };
+ }])
+
+ .factory('GridsterDraggable', ['$document', '$window', 'GridsterTouch',
+ function($document, $window, GridsterTouch) {
+ function GridsterDraggable($el, scope, gridster, item, itemOptions) {
+
+ var elmX, elmY, elmW, elmH,
+
+ mouseX = 0,
+ mouseY = 0,
+ lastMouseX = 0,
+ lastMouseY = 0,
+ mOffX = 0,
+ mOffY = 0,
+
+ minTop = 0,
+ minLeft = 0,
+ realdocument = $document[0];
+
+ var originalCol, originalRow;
+ var inputTags = ['select', 'option', 'input', 'textarea', 'button'];
+
+ function dragStart(event) {
+ $el.addClass('gridster-item-moving');
+ gridster.movingItem = item;
+
+ gridster.updateHeight(item.sizeY);
+ scope.$apply(function() {
+ if (gridster.draggable && gridster.draggable.start) {
+ gridster.draggable.start(event, $el, itemOptions, item);
+ }
+ });
+ }
+
+ function drag(event) {
+ var oldRow = item.row,
+ oldCol = item.col,
+ hasCallback = gridster.draggable && gridster.draggable.drag,
+ scrollSensitivity = gridster.draggable.scrollSensitivity,
+ scrollSpeed = gridster.draggable.scrollSpeed;
+
+ var row = Math.min(gridster.pixelsToRows(elmY), gridster.maxRows - 1);
+ var col = Math.min(gridster.pixelsToColumns(elmX), gridster.columns - 1);
+
+ var itemsInTheWay = gridster.getItems(row, col, item.sizeX, item.sizeY, item);
+ var hasItemsInTheWay = itemsInTheWay.length !== 0;
+
+ if (gridster.swapping === true && hasItemsInTheWay) {
+ var boundingBoxItem = gridster.getBoundingBox(itemsInTheWay),
+ sameSize = boundingBoxItem.sizeX === item.sizeX && boundingBoxItem.sizeY === item.sizeY,
+ sameRow = boundingBoxItem.row === oldRow,
+ sameCol = boundingBoxItem.col === oldCol,
+ samePosition = boundingBoxItem.row === row && boundingBoxItem.col === col,
+ inline = sameRow || sameCol;
+
+ if (sameSize && itemsInTheWay.length === 1) {
+ if (samePosition) {
+ gridster.swapItems(item, itemsInTheWay[0]);
+ } else if (inline) {
+ return;
+ }
+ } else if (boundingBoxItem.sizeX <= item.sizeX && boundingBoxItem.sizeY <= item.sizeY && inline) {
+ var emptyRow = item.row <= row ? item.row : row + item.sizeY,
+ emptyCol = item.col <= col ? item.col : col + item.sizeX,
+ rowOffset = emptyRow - boundingBoxItem.row,
+ colOffset = emptyCol - boundingBoxItem.col;
+
+ for (var i = 0, l = itemsInTheWay.length; i < l; ++i) {
+ var itemInTheWay = itemsInTheWay[i];
+
+ var itemsInFreeSpace = gridster.getItems(
+ itemInTheWay.row + rowOffset,
+ itemInTheWay.col + colOffset,
+ itemInTheWay.sizeX,
+ itemInTheWay.sizeY,
+ item
+ );
+
+ if (itemsInFreeSpace.length === 0) {
+ gridster.putItem(itemInTheWay, itemInTheWay.row + rowOffset, itemInTheWay.col + colOffset);
+ }
+ }
+ }
+ }
+
+ if (gridster.pushing !== false || !hasItemsInTheWay) {
+ item.row = row;
+ item.col = col;
+ }
+
+ if (event.pageY - realdocument.body.scrollTop < scrollSensitivity) {
+ realdocument.body.scrollTop = realdocument.body.scrollTop - scrollSpeed;
+ } else if ($window.innerHeight - (event.pageY - realdocument.body.scrollTop) < scrollSensitivity) {
+ realdocument.body.scrollTop = realdocument.body.scrollTop + scrollSpeed;
+ }
+
+ if (event.pageX - realdocument.body.scrollLeft < scrollSensitivity) {
+ realdocument.body.scrollLeft = realdocument.body.scrollLeft - scrollSpeed;
+ } else if ($window.innerWidth - (event.pageX - realdocument.body.scrollLeft) < scrollSensitivity) {
+ realdocument.body.scrollLeft = realdocument.body.scrollLeft + scrollSpeed;
+ }
+
+ if (hasCallback || oldRow !== item.row || oldCol !== item.col) {
+ scope.$apply(function() {
+ if (hasCallback) {
+ gridster.draggable.drag(event, $el, itemOptions, item);
+ }
+ });
+ }
+ }
+
+ function dragStop(event) {
+ $el.removeClass('gridster-item-moving');
+ var row = Math.min(gridster.pixelsToRows(elmY), gridster.maxRows - 1);
+ var col = Math.min(gridster.pixelsToColumns(elmX), gridster.columns - 1);
+ if (gridster.pushing !== false || gridster.getItems(row, col, item.sizeX, item.sizeY, item).length === 0) {
+ item.row = row;
+ item.col = col;
+ }
+ gridster.movingItem = null;
+ item.setPosition(item.row, item.col);
+
+ scope.$apply(function() {
+ if (gridster.draggable && gridster.draggable.stop) {
+ gridster.draggable.stop(event, $el, itemOptions, item);
+ }
+ });
+ }
+
+ function mouseDown(e) {
+ if (inputTags.indexOf(e.target.nodeName.toLowerCase()) !== -1) {
+ return false;
+ }
+
+ var $target = angular.element(e.target);
+
+ // exit, if a resize handle was hit
+ if ($target.hasClass('gridster-item-resizable-handler')) {
+ return false;
+ }
+
+ // exit, if the target has it's own click event
+ if ($target.attr('onclick') || $target.attr('ng-click')) {
+ return false;
+ }
+
+ // only works if you have jQuery
+ if ($target.closest && $target.closest('.gridster-no-drag').length) {
+ return false;
+ }
+
+ // apply drag handle filter
+ if (gridster.draggable && gridster.draggable.handle) {
+ var $dragHandles = angular.element($el[0].querySelectorAll(gridster.draggable.handle));
+ var match = false;
+ outerloop:
+ for (var h = 0, hl = $dragHandles.length; h < hl; ++h) {
+ var handle = $dragHandles[h];
+ if (handle === e.target) {
+ match = true;
+ break;
+ }
+ var target = e.target;
+ for (var p = 0; p < 20; ++p) {
+ var parent = target.parentNode;
+ if (parent === $el[0] || !parent) {
+ break;
+ }
+ if (parent === handle) {
+ match = true;
+ break outerloop;
+ }
+ target = parent;
+ }
+ }
+ if (!match) {
+ return false;
+ }
+ }
+
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+
+ lastMouseX = e.pageX;
+ lastMouseY = e.pageY;
+
+ elmX = parseInt($el.css('left'), 10);
+ elmY = parseInt($el.css('top'), 10);
+ elmW = $el[0].offsetWidth;
+ elmH = $el[0].offsetHeight;
+
+ originalCol = item.col;
+ originalRow = item.row;
+
+ dragStart(e);
+
+ return true;
+ }
+
+ function mouseMove(e) {
+ if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {
+ return false;
+ }
+
+ var maxLeft = gridster.curWidth - 1;
+ var maxTop = gridster.curRowHeight * gridster.maxRows - 1;
+
+ // Get the current mouse position.
+ mouseX = e.pageX;
+ mouseY = e.pageY;
+
+ // Get the deltas
+ var diffX = mouseX - lastMouseX + mOffX;
+ var diffY = mouseY - lastMouseY + mOffY;
+ mOffX = mOffY = 0;
+
+ // Update last processed mouse positions.
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+
+ var dX = diffX,
+ dY = diffY;
+ if (elmX + dX < minLeft) {
+ diffX = minLeft - elmX;
+ mOffX = dX - diffX;
+ } else if (elmX + elmW + dX > maxLeft) {
+ diffX = maxLeft - elmX - elmW;
+ mOffX = dX - diffX;
+ }
+
+ if (elmY + dY < minTop) {
+ diffY = minTop - elmY;
+ mOffY = dY - diffY;
+ } else if (elmY + elmH + dY > maxTop) {
+ diffY = maxTop - elmY - elmH;
+ mOffY = dY - diffY;
+ }
+ elmX += diffX;
+ elmY += diffY;
+
+ // set new position
+ $el.css({
+ 'top': elmY + 'px',
+ 'left': elmX + 'px'
+ });
+
+ drag(e);
+
+ return true;
+ }
+
+ function mouseUp(e) {
+ if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {
+ return false;
+ }
+
+ mOffX = mOffY = 0;
+
+ dragStop(e);
+
+ return true;
+ }
+
+ var enabled = null;
+ var gridsterTouch = null;
+
+ this.enable = function() {
+ if (enabled === true) {
+ return;
+ }
+ enabled = true;
+
+ if (gridsterTouch) {
+ gridsterTouch.enable();
+ return;
+ }
+
+ gridsterTouch = new GridsterTouch($el[0], mouseDown, mouseMove, mouseUp);
+ gridsterTouch.enable();
+ };
+
+ this.disable = function() {
+ if (enabled === false) {
+ return;
+ }
+
+ enabled = false;
+ if (gridsterTouch) {
+ gridsterTouch.disable();
+ }
+ };
+
+ this.toggle = function(enabled) {
+ if (enabled) {
+ this.enable();
+ } else {
+ this.disable();
+ }
+ };
+
+ this.destroy = function() {
+ this.disable();
+ };
+ }
+
+ return GridsterDraggable;
+ }
+ ])
+
+ .factory('GridsterResizable', ['GridsterTouch', function(GridsterTouch) {
+ function GridsterResizable($el, scope, gridster, item, itemOptions) {
+
+ function ResizeHandle(handleClass) {
+
+ var hClass = handleClass;
+
+ var elmX, elmY, elmW, elmH,
+
+ mouseX = 0,
+ mouseY = 0,
+ lastMouseX = 0,
+ lastMouseY = 0,
+ mOffX = 0,
+ mOffY = 0,
+
+ minTop = 0,
+ maxTop = 9999,
+ minLeft = 0;
+
+ var getMinHeight = function() {
+ return (item.minSizeY ? item.minSizeY : 1) * gridster.curRowHeight - gridster.margins[0];
+ };
+ var getMinWidth = function() {
+ return (item.minSizeX ? item.minSizeX : 1) * gridster.curColWidth - gridster.margins[1];
+ };
+
+ var originalWidth, originalHeight;
+ var savedDraggable;
+
+ function resizeStart(e) {
+ $el.addClass('gridster-item-moving');
+ $el.addClass('gridster-item-resizing');
+
+ gridster.movingItem = item;
+
+ item.setElementSizeX();
+ item.setElementSizeY();
+ item.setElementPosition();
+ gridster.updateHeight(1);
+
+ scope.$apply(function() {
+ // callback
+ if (gridster.resizable && gridster.resizable.start) {
+ gridster.resizable.start(e, $el, itemOptions, item); // options is the item model
+ }
+ });
+ }
+
+ function resize(e) {
+ var oldRow = item.row,
+ oldCol = item.col,
+ oldSizeX = item.sizeX,
+ oldSizeY = item.sizeY,
+ hasCallback = gridster.resizable && gridster.resizable.resize;
+
+ var col = item.col;
+ // only change column if grabbing left edge
+ if (['w', 'nw', 'sw'].indexOf(handleClass) !== -1) {
+ col = gridster.pixelsToColumns(elmX, false);
+ }
+
+ var row = item.row;
+ // only change row if grabbing top edge
+ if (['n', 'ne', 'nw'].indexOf(handleClass) !== -1) {
+ row = gridster.pixelsToRows(elmY, false);
+ }
+
+ var sizeX = item.sizeX;
+ // only change row if grabbing left or right edge
+ if (['n', 's'].indexOf(handleClass) === -1) {
+ sizeX = gridster.pixelsToColumns(elmW, true);
+ }
+
+ var sizeY = item.sizeY;
+ // only change row if grabbing top or bottom edge
+ if (['e', 'w'].indexOf(handleClass) === -1) {
+ sizeY = gridster.pixelsToRows(elmH, true);
+ }
+
+
+ var canOccupy = row > -1 && col > -1 && sizeX + col <= gridster.columns && sizeY + row <= gridster.maxRows;
+ if (canOccupy && (gridster.pushing !== false || gridster.getItems(row, col, sizeX, sizeY, item).length === 0)) {
+ item.row = row;
+ item.col = col;
+ item.sizeX = sizeX;
+ item.sizeY = sizeY;
+ }
+ var isChanged = item.row !== oldRow || item.col !== oldCol || item.sizeX !== oldSizeX || item.sizeY !== oldSizeY;
+
+ if (hasCallback || isChanged) {
+ scope.$apply(function() {
+ if (hasCallback) {
+ gridster.resizable.resize(e, $el, itemOptions, item); // options is the item model
+ }
+ });
+ }
+ }
+
+ function resizeStop(e) {
+ $el.removeClass('gridster-item-moving');
+ $el.removeClass('gridster-item-resizing');
+
+ gridster.movingItem = null;
+
+ item.setPosition(item.row, item.col);
+ item.setSizeY(item.sizeY);
+ item.setSizeX(item.sizeX);
+
+ scope.$apply(function() {
+ if (gridster.resizable && gridster.resizable.stop) {
+ gridster.resizable.stop(e, $el, itemOptions, item); // options is the item model
+ }
+ });
+ }
+
+ function mouseDown(e) {
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+
+ // save the draggable setting to restore after resize
+ savedDraggable = gridster.draggable.enabled;
+ if (savedDraggable) {
+ gridster.draggable.enabled = false;
+ scope.$broadcast('gridster-draggable-changed', gridster);
+ }
+
+ // Get the current mouse position.
+ lastMouseX = e.pageX;
+ lastMouseY = e.pageY;
+
+ // Record current widget dimensions
+ elmX = parseInt($el.css('left'), 10);
+ elmY = parseInt($el.css('top'), 10);
+ elmW = $el[0].offsetWidth;
+ elmH = $el[0].offsetHeight;
+
+ originalWidth = item.sizeX;
+ originalHeight = item.sizeY;
+
+ resizeStart(e);
+
+ return true;
+ }
+
+ function mouseMove(e) {
+ var maxLeft = gridster.curWidth - 1;
+
+ // Get the current mouse position.
+ mouseX = e.pageX;
+ mouseY = e.pageY;
+
+ // Get the deltas
+ var diffX = mouseX - lastMouseX + mOffX;
+ var diffY = mouseY - lastMouseY + mOffY;
+ mOffX = mOffY = 0;
+
+ // Update last processed mouse positions.
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+
+ var dY = diffY,
+ dX = diffX;
+
+ if (hClass.indexOf('n') >= 0) {
+ if (elmH - dY < getMinHeight()) {
+ diffY = elmH - getMinHeight();
+ mOffY = dY - diffY;
+ } else if (elmY + dY < minTop) {
+ diffY = minTop - elmY;
+ mOffY = dY - diffY;
+ }
+ elmY += diffY;
+ elmH -= diffY;
+ }
+ if (hClass.indexOf('s') >= 0) {
+ if (elmH + dY < getMinHeight()) {
+ diffY = getMinHeight() - elmH;
+ mOffY = dY - diffY;
+ } else if (elmY + elmH + dY > maxTop) {
+ diffY = maxTop - elmY - elmH;
+ mOffY = dY - diffY;
+ }
+ elmH += diffY;
+ }
+ if (hClass.indexOf('w') >= 0) {
+ if (elmW - dX < getMinWidth()) {
+ diffX = elmW - getMinWidth();
+ mOffX = dX - diffX;
+ } else if (elmX + dX < minLeft) {
+ diffX = minLeft - elmX;
+ mOffX = dX - diffX;
+ }
+ elmX += diffX;
+ elmW -= diffX;
+ }
+ if (hClass.indexOf('e') >= 0) {
+ if (elmW + dX < getMinWidth()) {
+ diffX = getMinWidth() - elmW;
+ mOffX = dX - diffX;
+ } else if (elmX + elmW + dX > maxLeft) {
+ diffX = maxLeft - elmX - elmW;
+ mOffX = dX - diffX;
+ }
+ elmW += diffX;
+ }
+
+ // set new position
+ $el.css({
+ 'top': elmY + 'px',
+ 'left': elmX + 'px',
+ 'width': elmW + 'px',
+ 'height': elmH + 'px'
+ });
+
+ resize(e);
+
+ return true;
+ }
+
+ function mouseUp(e) {
+ // restore draggable setting to its original state
+ if (gridster.draggable.enabled !== savedDraggable) {
+ gridster.draggable.enabled = savedDraggable;
+ scope.$broadcast('gridster-draggable-changed', gridster);
+ }
+
+ mOffX = mOffY = 0;
+
+ resizeStop(e);
+
+ return true;
+ }
+
+ var $dragHandle = null;
+ var unifiedInput;
+
+ this.enable = function() {
+ if (!$dragHandle) {
+ $dragHandle = angular.element('<div class="gridster-item-resizable-handler handle-' + hClass + '"></div>');
+ $el.append($dragHandle);
+ }
+
+ unifiedInput = new GridsterTouch($dragHandle[0], mouseDown, mouseMove, mouseUp);
+ unifiedInput.enable();
+ };
+
+ this.disable = function() {
+ if ($dragHandle) {
+ $dragHandle.remove();
+ $dragHandle = null;
+ }
+
+ unifiedInput.disable();
+ unifiedInput = undefined;
+ };
+
+ this.destroy = function() {
+ this.disable();
+ };
+ }
+
+ var handles = [];
+ var handlesOpts = gridster.resizable.handles;
+ if (typeof handlesOpts === 'string') {
+ handlesOpts = gridster.resizable.handles.split(',');
+ }
+ var enabled = false;
+
+ for (var c = 0, l = handlesOpts.length; c < l; c++) {
+ handles.push(new ResizeHandle(handlesOpts[c]));
+ }
+
+ this.enable = function() {
+ if (enabled) {
+ return;
+ }
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].enable();
+ }
+ enabled = true;
+ };
+
+ this.disable = function() {
+ if (!enabled) {
+ return;
+ }
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].disable();
+ }
+ enabled = false;
+ };
+
+ this.toggle = function(enabled) {
+ if (enabled) {
+ this.enable();
+ } else {
+ this.disable();
+ }
+ };
+
+ this.destroy = function() {
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].destroy();
+ }
+ };
+ }
+ return GridsterResizable;
+ }])
+
+ .factory('gridsterDebounce', function() {
+ return function gridsterDebounce(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var context = this,
+ args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) {
+ func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) {
+ func.apply(context, args);
+ }
+ };
+ };
+ })
+
+ /**
+ * GridsterItem directive
+ * @param $parse
+ * @param GridsterDraggable
+ * @param GridsterResizable
+ * @param gridsterDebounce
+ */
+ .directive('gridsterItem', ['$parse', 'GridsterDraggable', 'GridsterResizable', 'gridsterDebounce',
+ function($parse, GridsterDraggable, GridsterResizable, gridsterDebounce) {
+ return {
+ scope: true,
+ restrict: 'EA',
+ controller: 'GridsterItemCtrl',
+ controllerAs: 'gridsterItem',
+ require: ['^gridster', 'gridsterItem'],
+ link: function(scope, $el, attrs, controllers) {
+ var optionsKey = attrs.gridsterItem,
+ options;
+
+ var gridster = controllers[0],
+ item = controllers[1];
+
+ scope.gridster = gridster;
+
+ // bind the item's position properties
+ // options can be an object specified by gridster-item="object"
+ // or the options can be the element html attributes object
+ if (optionsKey) {
+ var $optionsGetter = $parse(optionsKey);
+ options = $optionsGetter(scope) || {};
+ if (!options && $optionsGetter.assign) {
+ options = {
+ row: item.row,
+ col: item.col,
+ sizeX: item.sizeX,
+ sizeY: item.sizeY,
+ minSizeX: 0,
+ minSizeY: 0,
+ maxSizeX: null,
+ maxSizeY: null
+ };
+ $optionsGetter.assign(scope, options);
+ }
+ } else {
+ options = attrs;
+ }
+
+ item.init($el, gridster);
+
+ $el.addClass('gridster-item');
+
+ var aspects = ['minSizeX', 'maxSizeX', 'minSizeY', 'maxSizeY', 'sizeX', 'sizeY', 'row', 'col'],
+ $getters = {};
+
+ var expressions = [];
+ var aspectFn = function(aspect) {
+ var expression;
+ if (typeof options[aspect] === 'string') {
+ // watch the expression in the scope
+ expression = options[aspect];
+ } else if (typeof options[aspect.toLowerCase()] === 'string') {
+ // watch the expression in the scope
+ expression = options[aspect.toLowerCase()];
+ } else if (optionsKey) {
+ // watch the expression on the options object in the scope
+ expression = optionsKey + '.' + aspect;
+ } else {
+ return;
+ }
+ expressions.push('"' + aspect + '":' + expression);
+ $getters[aspect] = $parse(expression);
+
+ // initial set
+ var val = $getters[aspect](scope);
+ if (typeof val === 'number') {
+ item[aspect] = val;
+ }
+ };
+
+ for (var i = 0, l = aspects.length; i < l; ++i) {
+ aspectFn(aspects[i]);
+ }
+
+ var watchExpressions = '{' + expressions.join(',') + '}';
+ // when the value changes externally, update the internal item object
+ scope.$watchCollection(watchExpressions, function(newVals, oldVals) {
+ for (var aspect in newVals) {
+ var newVal = newVals[aspect];
+ var oldVal = oldVals[aspect];
+ if (oldVal === newVal) {
+ continue;
+ }
+ newVal = parseInt(newVal, 10);
+ if (!isNaN(newVal)) {
+ item[aspect] = newVal;
+ }
+ }
+ });
+
+ function positionChanged() {
+ // call setPosition so the element and gridster controller are updated
+ item.setPosition(item.row, item.col);
+
+ // when internal item position changes, update externally bound values
+ if ($getters.row && $getters.row.assign) {
+ $getters.row.assign(scope, item.row);
+ }
+ if ($getters.col && $getters.col.assign) {
+ $getters.col.assign(scope, item.col);
+ }
+ }
+ scope.$watch(function() {
+ return item.row + ',' + item.col;
+ }, positionChanged);
+
+ function sizeChanged() {
+ var changedX = item.setSizeX(item.sizeX, true);
+ if (changedX && $getters.sizeX && $getters.sizeX.assign) {
+ $getters.sizeX.assign(scope, item.sizeX);
+ }
+ var changedY = item.setSizeY(item.sizeY, true);
+ if (changedY && $getters.sizeY && $getters.sizeY.assign) {
+ $getters.sizeY.assign(scope, item.sizeY);
+ }
+
+ if (changedX || changedY) {
+ item.gridster.moveOverlappingItems(item);
+ gridster.layoutChanged();
+ scope.$broadcast('gridster-item-resized', item);
+ }
+ }
+
+ scope.$watch(function() {
+ return item.sizeY + ',' + item.sizeX + ',' + item.minSizeX + ',' + item.maxSizeX + ',' + item.minSizeY + ',' + item.maxSizeY;
+ }, sizeChanged);
+
+ var draggable = new GridsterDraggable($el, scope, gridster, item, options);
+ var resizable = new GridsterResizable($el, scope, gridster, item, options);
+
+ var updateResizable = function() {
+ resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);
+ };
+ updateResizable();
+
+ var updateDraggable = function() {
+ draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);
+ };
+ updateDraggable();
+
+ scope.$on('gridster-draggable-changed', updateDraggable);
+ scope.$on('gridster-resizable-changed', updateResizable);
+ scope.$on('gridster-resized', updateResizable);
+ scope.$on('gridster-mobile-changed', function() {
+ updateResizable();
+ updateDraggable();
+ });
+
+ function whichTransitionEvent() {
+ var el = document.createElement('div');
+ var transitions = {
+ 'transition': 'transitionend',
+ 'OTransition': 'oTransitionEnd',
+ 'MozTransition': 'transitionend',
+ 'WebkitTransition': 'webkitTransitionEnd'
+ };
+ for (var t in transitions) {
+ if (el.style[t] !== undefined) {
+ return transitions[t];
+ }
+ }
+ }
+
+ var debouncedTransitionEndPublisher = gridsterDebounce(function() {
+ scope.$apply(function() {
+ scope.$broadcast('gridster-item-transition-end', item);
+ });
+ }, 50);
+
+ $el.on(whichTransitionEvent(), debouncedTransitionEndPublisher);
+
+ scope.$broadcast('gridster-item-initialized', item);
+
+ return scope.$on('$destroy', function() {
+ try {
+ resizable.destroy();
+ draggable.destroy();
+ } catch (e) {}
+
+ try {
+ gridster.removeItem(item);
+ } catch (e) {}
+
+ try {
+ item.destroy();
+ } catch (e) {}
+ });
+ }
+ };
+ }
+ ])
+
+ .directive('gridsterNoDrag', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, $element) {
+ $element.addClass('gridster-no-drag');
+ }
+ };
+ })
+
+ ;
+
+}));
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.less b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.less
new file mode 100644
index 00000000..e8160dd2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-gridster/src/angular-gridster.less
@@ -0,0 +1,167 @@
+/**
+ * gridster.js - v0.2.1 - 2013-10-28 * http://gridster.net
+ * Copyright (c) 2013 ducksboard; Licensed MIT
+ */
+
+.gridster {
+ position: relative;
+ margin: auto;
+ height: 0;
+}
+
+.gridster > ul {
+ margin: 0;
+ list-style: none;
+ padding: 0;
+}
+
+.gridster-item {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ list-style: none;
+ z-index: 2;
+ position: absolute;
+ display: none;
+}
+
+.gridster-loaded {
+ -webkit-transition: height .3s;
+ -moz-transition: height .3s;
+ -o-transition: height .3s;
+ transition: height .3s;
+
+ .gridster-item {
+ display: block;
+ position: absolute;
+ -webkit-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -moz-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -o-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -webkit-transition-delay: 50ms;
+ -moz-transition-delay: 50ms;
+ -o-transition-delay: 50ms;
+ transition-delay: 50ms;
+ }
+
+ .gridster-preview-holder {
+ display: none;
+ z-index: 1;
+ position: absolute;
+ background-color: #ddd;
+ border-color: #fff;
+ opacity: 0.2;
+ }
+
+ .gridster-item.gridster-item-moving,
+ .gridster-preview-holder {
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+ }
+}
+
+.gridster-mobile {
+ height: auto !important;
+
+ .gridster-item {
+ height: auto;
+ position: static;
+ float: none;
+ }
+}
+
+.gridster-item.ng-leave.ng-leave-active {
+ opacity: 0;
+}
+.gridster-item.ng-enter {
+ opacity: 1;
+}
+
+.gridster-item-moving {
+ z-index: 3;
+}
+
+/* RESIZE */
+.gridster-item-resizable-handler {
+ position: absolute;
+ font-size: 1px;
+ display: block;
+ z-index: 5;
+}
+
+.handle-se {
+ cursor: se-resize;
+ width: 0;
+ height: 0;
+ right: 1px;
+ bottom: 1px;
+ border-style: solid;
+ border-width: 0 0 12px 12px;
+ border-color: transparent;
+}
+
+.handle-ne {
+ cursor: ne-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ top: 1px;
+}
+
+.handle-nw {
+ cursor: nw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ top: 1px;
+}
+
+.handle-sw {
+ cursor: sw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ bottom: 1px;
+}
+
+.handle-e {
+ cursor: e-resize;
+ width: 12px;
+ bottom: 0;
+ right: 1px;
+ top: 0;
+}
+
+.handle-s {
+ cursor: s-resize;
+ height: 12px;
+ right: 0;
+ bottom: 1px;
+ left: 0;
+}
+
+.handle-n {
+ cursor: n-resize;
+ height: 12px;
+ right: 0;
+ top: 1px;
+ left: 0;
+}
+
+.handle-w {
+ cursor: w-resize;
+ width: 12px;
+ left: 1px;
+ top: 0;
+ bottom: 0;
+}
+
+.gridster .gridster-item:hover .gridster-box {
+ border: 1.5px solid #B3B2B3;
+}
+
+.gridster .gridster-item:hover .handle-se {
+ border-color: transparent transparent #ccc;
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/index.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/index.js
new file mode 100644
index 00000000..99a08334
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/index.js
@@ -0,0 +1,2 @@
+require('./ui-grid');
+module.exports = 'ui.grid';
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.css
new file mode 100644
index 00000000..819592c5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.css
@@ -0,0 +1,2005 @@
+/*!
+ * ui-grid - v4.0.2 - 2016-12-30
+ * Copyright (c) 2016 ; License: MIT
+ */
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ content: " ";
+ display: table;
+}
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ clear: both;
+}
+.ui-grid {
+ border: 1px solid #d4d4d4;
+ box-sizing: content-box;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ border-radius: 0px;
+ -webkit-transform: translateZ(0);
+ -moz-transform: translateZ(0);
+ -o-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.ui-grid-vertical-bar {
+ position: absolute;
+ right: 0;
+ width: 0;
+}
+.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,
+.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
+ width: 1px;
+}
+.ui-grid-scrollbar-placeholder {
+ background-color: transparent;
+}
+.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
+ background-color: #d4d4d4;
+}
+.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
+ background-color: #d4d4d4;
+}
+.ui-grid-header-cell:last-child .ui-grid-vertical-bar {
+ right: -1px;
+ width: 1px;
+ background-color: #d4d4d4;
+}
+.ui-grid-clearfix:before,
+.ui-grid-clearfix:after {
+ content: "";
+ display: table;
+}
+.ui-grid-clearfix:after {
+ clear: both;
+}
+.ui-grid-invisible {
+ visibility: hidden;
+}
+.ui-grid-contents-wrapper {
+ position: relative;
+ height: 100%;
+ width: 100%;
+}
+.ui-grid-sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.ui-grid-top-panel-background {
+ background: #f3f3f3;
+ background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
+ background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
+ background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
+ background: -o-linear-gradient(#ffffff, #eeeeee);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+}
+.ui-grid-header {
+ border-bottom: 1px solid #d4d4d4;
+ box-sizing: border-box;
+}
+.ui-grid-top-panel {
+ position: relative;
+ overflow: hidden;
+ font-weight: bold;
+ background: #f3f3f3;
+ background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
+ background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
+ background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
+ background: -o-linear-gradient(#ffffff, #eeeeee);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+ -webkit-border-top-right-radius: -1px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: -1px;
+ -moz-border-radius-topright: -1px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: -1px;
+ border-top-right-radius: -1px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: -1px;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+.ui-grid-header-viewport {
+ overflow: hidden;
+}
+.ui-grid-header-canvas:before,
+.ui-grid-header-canvas:after {
+ content: "";
+ display: table;
+ line-height: 0;
+}
+.ui-grid-header-canvas:after {
+ clear: both;
+}
+.ui-grid-header-cell-wrapper {
+ position: relative;
+ display: table;
+ box-sizing: border-box;
+ height: 100%;
+}
+.ui-grid-header-cell-row {
+ display: table-row;
+ position: relative;
+}
+.ui-grid-header-cell {
+ position: relative;
+ box-sizing: border-box;
+ background-color: inherit;
+ border-right: 1px solid;
+ border-color: #d4d4d4;
+ display: table-cell;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ width: 0;
+}
+.ui-grid-header-cell:last-child {
+ border-right: 0;
+}
+.ui-grid-header-cell .sortable {
+ cursor: pointer;
+}
+.ui-grid-header-cell .ui-grid-sort-priority-number {
+ margin-left: -8px;
+}
+.ui-grid-header .ui-grid-vertical-bar {
+ top: 0;
+ bottom: 0;
+}
+.ui-grid-column-menu-button {
+ position: absolute;
+ right: 1px;
+ top: 0;
+}
+.ui-grid-column-menu-button .ui-grid-icon-angle-down {
+ vertical-align: sub;
+}
+.ui-grid-column-menu-button-last-col {
+ margin-right: 25px;
+}
+.ui-grid-column-menu {
+ position: absolute;
+}
+/* Slide up/down animations */
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
+ -webkit-transition: all 0.05s linear;
+ -moz-transition: all 0.05s linear;
+ -o-transition: all 0.05s linear;
+ transition: all 0.05s linear;
+ display: block !important;
+}
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
+ -webkit-transform: translateY(-100%);
+ -moz-transform: translateY(-100%);
+ -o-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+}
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
+.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateY(0);
+ -moz-transform: translateY(0);
+ -o-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+}
+/* Slide up/down animations */
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
+ -webkit-transition: all 0.05s linear;
+ -moz-transition: all 0.05s linear;
+ -o-transition: all 0.05s linear;
+ transition: all 0.05s linear;
+ display: block !important;
+}
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
+ -webkit-transform: translateY(-100%);
+ -moz-transform: translateY(-100%);
+ -o-transform: translateY(-100%);
+ -ms-transform: translateY(-100%);
+ transform: translateY(-100%);
+}
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {
+ -webkit-transform: translateY(0);
+ -moz-transform: translateY(0);
+ -o-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+}
+.ui-grid-filter-container {
+ padding: 4px 10px;
+ position: relative;
+}
+.ui-grid-filter-container .ui-grid-filter-button {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+}
+.ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"] {
+ position: absolute;
+ top: 50%;
+ line-height: 32px;
+ margin-top: -16px;
+ right: 10px;
+ opacity: 0.66;
+}
+.ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"]:hover {
+ opacity: 1;
+}
+.ui-grid-filter-container .ui-grid-filter-button-select {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+}
+.ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"] {
+ position: absolute;
+ top: 50%;
+ line-height: 32px;
+ margin-top: -16px;
+ right: 0px;
+ opacity: 0.66;
+}
+.ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"]:hover {
+ opacity: 1;
+}
+input[type="text"].ui-grid-filter-input {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ width: 100%;
+ border: 1px solid #d4d4d4;
+ -webkit-border-top-right-radius: 0px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius-topright: 0px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: 0;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+input[type="text"].ui-grid-filter-input:hover {
+ border: 1px solid #d4d4d4;
+}
+select.ui-grid-filter-select {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ width: 90%;
+ border: 1px solid #d4d4d4;
+ -webkit-border-top-right-radius: 0px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius-topright: 0px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: 0;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+select.ui-grid-filter-select:hover {
+ border: 1px solid #d4d4d4;
+}
+.ui-grid-filter-cancel-button-hidden select.ui-grid-filter-select {
+ width: 100%;
+}
+.ui-grid-render-container {
+ position: inherit;
+ -webkit-border-top-right-radius: 0;
+ -webkit-border-bottom-right-radius: 0px;
+ -webkit-border-bottom-left-radius: 0px;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius-topright: 0;
+ -moz-border-radius-bottomright: 0px;
+ -moz-border-radius-bottomleft: 0px;
+ -moz-border-radius-topleft: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0px;
+ border-bottom-left-radius: 0px;
+ border-top-left-radius: 0;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+.ui-grid-render-container:focus {
+ outline: none;
+}
+.ui-grid-viewport {
+ min-height: 20px;
+ position: relative;
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+}
+.ui-grid-viewport:focus {
+ outline: none !important;
+}
+.ui-grid-canvas {
+ position: relative;
+ padding-top: 1px;
+}
+.ui-grid-row {
+ clear: both;
+}
+.ui-grid-row:nth-child(odd) .ui-grid-cell {
+ background-color: #fdfdfd;
+}
+.ui-grid-row:nth-child(even) .ui-grid-cell {
+ background-color: #f3f3f3;
+}
+.ui-grid-row:last-child .ui-grid-cell {
+ border-bottom-color: #d4d4d4;
+ border-bottom-style: solid;
+}
+.ui-grid-no-row-overlay {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: 10%;
+ background: #f3f3f3;
+ background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
+ background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
+ background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
+ background: -o-linear-gradient(#ffffff, #eeeeee);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+ -webkit-border-top-right-radius: 0px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius-topright: 0px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: 0;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #d4d4d4;
+ font-size: 2em;
+ text-align: center;
+}
+.ui-grid-no-row-overlay > * {
+ position: absolute;
+ display: table;
+ margin: auto 0;
+ width: 100%;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ opacity: 0.66;
+}
+.ui-grid-cell {
+ overflow: hidden;
+ float: left;
+ background-color: inherit;
+ border-right: 1px solid;
+ border-color: #d4d4d4;
+ box-sizing: border-box;
+}
+.ui-grid-cell:last-child {
+ border-right: 0;
+}
+.ui-grid-cell-contents {
+ padding: 5px;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ white-space: nowrap;
+ -ms-text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ height: 100%;
+}
+.ui-grid-cell-contents-hidden {
+ visibility: hidden;
+ width: 0;
+ height: 0;
+ display: none;
+}
+.ui-grid-row .ui-grid-cell.ui-grid-row-header-cell {
+ background-color: #f0f0ee;
+ border-bottom: solid 1px #d4d4d4;
+}
+.ui-grid-footer-panel-background {
+ background: #f3f3f3;
+ background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
+ background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
+ background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
+ background: -o-linear-gradient(#ffffff, #eeeeee);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+}
+.ui-grid-footer-panel {
+ position: relative;
+ border-bottom: 1px solid #d4d4d4;
+ border-top: 1px solid #d4d4d4;
+ overflow: hidden;
+ font-weight: bold;
+ background: #f3f3f3;
+ background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
+ background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
+ background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
+ background: -o-linear-gradient(#ffffff, #eeeeee);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+ -webkit-border-top-right-radius: -1px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: -1px;
+ -moz-border-radius-topright: -1px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: -1px;
+ border-top-right-radius: -1px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: -1px;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+.ui-grid-grid-footer {
+ float: left;
+ width: 100%;
+}
+.ui-grid-footer-viewport {
+ overflow: hidden;
+}
+.ui-grid-footer-canvas {
+ position: relative;
+}
+.ui-grid-footer-canvas:before,
+.ui-grid-footer-canvas:after {
+ content: "";
+ display: table;
+ line-height: 0;
+}
+.ui-grid-footer-canvas:after {
+ clear: both;
+}
+.ui-grid-footer-cell-wrapper {
+ position: relative;
+ display: table;
+ box-sizing: border-box;
+ height: 100%;
+}
+.ui-grid-footer-cell-row {
+ display: table-row;
+}
+.ui-grid-footer-cell {
+ overflow: hidden;
+ background-color: inherit;
+ border-right: 1px solid;
+ border-color: #d4d4d4;
+ box-sizing: border-box;
+ display: table-cell;
+}
+.ui-grid-footer-cell:last-child {
+ border-right: 0;
+}
+input[type="text"].ui-grid-filter-input {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ width: 100%;
+ border: 1px solid #d4d4d4;
+ -webkit-border-top-right-radius: 0px;
+ -webkit-border-bottom-right-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -webkit-border-top-left-radius: 0;
+ -moz-border-radius-topright: 0px;
+ -moz-border-radius-bottomright: 0;
+ -moz-border-radius-bottomleft: 0;
+ -moz-border-radius-topleft: 0;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+ -moz-background-clip: padding-box;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+input[type="text"].ui-grid-filter-input:hover {
+ border: 1px solid #d4d4d4;
+}
+.ui-grid-menu-button {
+ z-index: 2;
+ position: absolute;
+ right: 0;
+ top: 0;
+ background: #f3f3f3;
+ border: 1px solid #d4d4d4;
+ cursor: pointer;
+ height: 31px;
+ font-weight: normal;
+}
+.ui-grid-menu-button .ui-grid-icon-container {
+ margin-top: 3px;
+}
+.ui-grid-menu-button .ui-grid-menu {
+ right: 0;
+}
+.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {
+ overflow: scroll;
+ border: 1px solid #d4d4d4;
+}
+.ui-grid-menu {
+ z-index: 2;
+ position: absolute;
+ padding: 0 10px 20px 10px;
+ cursor: pointer;
+ box-sizing: border-box;
+}
+.ui-grid-menu .ui-grid-menu-inner {
+ background: #f3f3f3;
+ border: 1px solid #d4d4d4;
+ position: relative;
+ white-space: nowrap;
+ -webkit-border-radius: 0px;
+ -moz-border-radius: 0px;
+ border-radius: 0px;
+ -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ padding: 1px 1px;
+ font-size: 10px;
+ line-height: 1;
+ border-radius: 2px;
+ color: transparent;
+ background-color: transparent;
+ border-color: transparent;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
+ color: #333333;
+ text-decoration: none;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active {
+ outline: 0;
+ background-image: none;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],
+fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
+ cursor: not-allowed;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,
+fieldset[disabled] a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
+ pointer-events: none;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,
+.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:hover,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:hover,
+.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,
+.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus,
+.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
+ color: transparent;
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,
+.open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
+ background-image: none;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:hover,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:hover,
+fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:focus,
+fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.focus,
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].focus,
+fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
+ background-color: transparent;
+ border-color: transparent;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button .badge {
+ color: transparent;
+ background-color: transparent;
+}
+.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button > i {
+ opacity: 0.75;
+ color: black;
+}
+.ui-grid-menu .ui-grid-menu-inner ul {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+}
+.ui-grid-menu .ui-grid-menu-inner ul li {
+ padding: 0px;
+}
+.ui-grid-menu .ui-grid-menu-inner ul li button {
+ min-width: 100%;
+ padding: 8px;
+ text-align: left;
+ background: transparent;
+ border: none;
+}
+.ui-grid-menu .ui-grid-menu-inner ul li button:hover,
+.ui-grid-menu .ui-grid-menu-inner ul li button:focus {
+ -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+}
+.ui-grid-menu .ui-grid-menu-inner ul li button.ui-grid-menu-item-active {
+ -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+ background-color: #cecece;
+}
+.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) > button {
+ border-bottom: 1px solid #d4d4d4;
+}
+.ui-grid-sortarrow {
+ right: 5px;
+ position: absolute;
+ width: 20px;
+ top: 0;
+ bottom: 0;
+ background-position: center;
+}
+.ui-grid-sortarrow.down {
+ -webkit-transform: rotate(180deg);
+ -moz-transform: rotate(180deg);
+ -o-transform: rotate(180deg);
+ -ms-transform: rotate(180deg);
+ transform: rotate(180deg);
+}
+@font-face {
+ font-family: 'ui-grid';
+ src: url('ui-grid.eot');
+ src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
+/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
+/*
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+ @font-face {
+ font-family: 'ui-grid';
+ src: url('@{font-path}ui-grid.svg?12312827#ui-grid') format('svg');
+ }
+}
+*/
+[class^="ui-grid-icon"]:before,
+[class*=" ui-grid-icon"]:before {
+ font-family: "ui-grid";
+ font-style: normal;
+ font-weight: normal;
+ speak: none;
+ display: inline-block;
+ text-decoration: inherit;
+ width: 1em;
+ margin-right: .2em;
+ text-align: center;
+ /* opacity: .8; */
+ /* For safety - reset parent styles, that can break glyph codes*/
+ font-variant: normal;
+ text-transform: none;
+ /* fix buttons height, for twitter bootstrap */
+ line-height: 1em;
+ /* Animation center compensation - margins should be symmetric */
+ /* remove if not needed */
+ margin-left: .2em;
+ /* you can be more comfortable with increased icons size */
+ /* font-size: 120%; */
+ /* Uncomment for 3D effect */
+ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
+}
+.ui-grid-icon-blank::before {
+ width: 1em;
+ content: ' ';
+}
+.ui-grid-icon-plus-squared:before {
+ content: '\c350';
+}
+.ui-grid-icon-minus-squared:before {
+ content: '\c351';
+}
+.ui-grid-icon-search:before {
+ content: '\c352';
+}
+.ui-grid-icon-cancel:before {
+ content: '\c353';
+}
+.ui-grid-icon-info-circled:before {
+ content: '\c354';
+}
+.ui-grid-icon-lock:before {
+ content: '\c355';
+}
+.ui-grid-icon-lock-open:before {
+ content: '\c356';
+}
+.ui-grid-icon-pencil:before {
+ content: '\c357';
+}
+.ui-grid-icon-down-dir:before {
+ content: '\c358';
+}
+.ui-grid-icon-up-dir:before {
+ content: '\c359';
+}
+.ui-grid-icon-left-dir:before {
+ content: '\c35a';
+}
+.ui-grid-icon-right-dir:before {
+ content: '\c35b';
+}
+.ui-grid-icon-left-open:before {
+ content: '\c35c';
+}
+.ui-grid-icon-right-open:before {
+ content: '\c35d';
+}
+.ui-grid-icon-angle-down:before {
+ content: '\c35e';
+}
+.ui-grid-icon-filter:before {
+ content: '\c35f';
+}
+.ui-grid-icon-sort-alt-up:before {
+ content: '\c360';
+}
+.ui-grid-icon-sort-alt-down:before {
+ content: '\c361';
+}
+.ui-grid-icon-ok:before {
+ content: '\c362';
+}
+.ui-grid-icon-menu:before {
+ content: '\c363';
+}
+.ui-grid-icon-indent-left:before {
+ content: '\e800';
+}
+.ui-grid-icon-indent-right:before {
+ content: '\e801';
+}
+.ui-grid-icon-spin5:before {
+ content: '\ea61';
+}
+/*
+* RTL Styles
+*/
+.ui-grid[dir=rtl] .ui-grid-header-cell,
+.ui-grid[dir=rtl] .ui-grid-footer-cell,
+.ui-grid[dir=rtl] .ui-grid-cell {
+ float: right !important;
+}
+.ui-grid[dir=rtl] .ui-grid-column-menu-button {
+ position: absolute;
+ left: 1px;
+ top: 0;
+ right: inherit;
+}
+.ui-grid[dir=rtl] .ui-grid-cell:first-child,
+.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,
+.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {
+ border-right: 0;
+}
+.ui-grid[dir=rtl] .ui-grid-cell:last-child,
+.ui-grid[dir=rtl] .ui-grid-header-cell:last-child {
+ border-right: 1px solid #d4d4d4;
+ border-left: 0;
+}
+.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,
+.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,
+.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {
+ width: 0;
+}
+.ui-grid[dir=rtl] .ui-grid-menu-button {
+ z-index: 2;
+ position: absolute;
+ left: 0;
+ right: auto;
+ background: #f3f3f3;
+ border: 1px solid #d4d4d4;
+ cursor: pointer;
+ min-height: 27px;
+ font-weight: normal;
+}
+.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {
+ left: 0;
+ right: auto;
+}
+.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {
+ right: initial;
+ left: 0;
+}
+.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"] {
+ right: initial;
+ left: 10px;
+}
+/*
+ Animation example, for spinners
+*/
+.ui-grid-animate-spin {
+ -moz-animation: ui-grid-spin 2s infinite linear;
+ -o-animation: ui-grid-spin 2s infinite linear;
+ -webkit-animation: ui-grid-spin 2s infinite linear;
+ animation: ui-grid-spin 2s infinite linear;
+ display: inline-block;
+}
+@-moz-keyframes ui-grid-spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-webkit-keyframes ui-grid-spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-o-keyframes ui-grid-spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-ms-keyframes ui-grid-spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes ui-grid-spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+/*---------------------------------------------------
+ LESS Elements 0.9
+ ---------------------------------------------------
+ A set of useful LESS mixins
+ More info at: http://lesselements.com
+ ---------------------------------------------------*/
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ content: " ";
+ display: table;
+}
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ clear: both;
+}
+.ui-grid-cell-focus {
+ outline: 0;
+ background-color: #b3c4c7;
+}
+.ui-grid-focuser {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ z-index: -1;
+ width: 100%;
+ height: 100%;
+}
+.ui-grid-focuser:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.ui-grid-offscreen {
+ display: block;
+ position: absolute;
+ left: -10000px;
+ top: -10000px;
+ clip: rect(0px, 0px, 0px, 0px);
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+div.ui-grid-cell input {
+ border-radius: inherit;
+ padding: 0;
+ width: 100%;
+ color: inherit;
+ height: auto;
+ font: inherit;
+ outline: none;
+}
+div.ui-grid-cell input:focus {
+ color: inherit;
+ outline: none;
+}
+div.ui-grid-cell input[type="checkbox"] {
+ margin: 9px 0 0 6px;
+ width: auto;
+}
+div.ui-grid-cell input.ng-invalid {
+ border: 1px solid #fc8f8f;
+}
+div.ui-grid-cell input.ng-valid {
+ border: 1px solid #d4d4d4;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-viewport .ui-grid-empty-base-layer-container {
+ position: absolute;
+ overflow: hidden;
+ pointer-events: none;
+ z-index: -1;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {
+ background-color: #fdfdfd;
+}
+.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {
+ background-color: #f3f3f3;
+}
+.ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell {
+ pointer-events: none;
+}
+.ui-grid-expandable-buttons-cell i {
+ pointer-events: all;
+}
+.scrollFiller {
+ float: left;
+ border: 1px solid #d4d4d4;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-tree-header-row {
+ font-weight: bold !important;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.movingColumn {
+ position: absolute;
+ top: 0;
+ border: 1px solid #d4d4d4;
+ box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
+}
+.movingColumn .ui-grid-icon-angle-down {
+ display: none;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/*---------------------------------------------------
+ LESS Elements 0.9
+ ---------------------------------------------------
+ A set of useful LESS mixins
+ More info at: http://lesselements.com
+ ---------------------------------------------------*/
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ content: " ";
+ display: table;
+}
+#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
+#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
+#ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
+ clear: both;
+}
+.ui-grid-pager-panel {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ padding-top: 3px;
+ padding-bottom: 3px;
+ box-sizing: content-box;
+}
+.ui-grid-pager-container {
+ float: left;
+}
+.ui-grid-pager-control {
+ margin-right: 10px;
+ margin-left: 10px;
+ min-width: 135px;
+ float: left;
+}
+.ui-grid-pager-control button {
+ height: 25px;
+ min-width: 26px;
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ color: #eeeeee;
+ background-color: #f3f3f3;
+ border-color: #cccccc;
+}
+.ui-grid-pager-control button:focus,
+.ui-grid-pager-control button:active:focus,
+.ui-grid-pager-control button.active:focus,
+.ui-grid-pager-control button.focus,
+.ui-grid-pager-control button:active.focus,
+.ui-grid-pager-control button.active.focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.ui-grid-pager-control button:hover,
+.ui-grid-pager-control button:focus,
+.ui-grid-pager-control button.focus {
+ color: #333333;
+ text-decoration: none;
+}
+.ui-grid-pager-control button:active,
+.ui-grid-pager-control button.active {
+ outline: 0;
+ background-image: none;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.ui-grid-pager-control button.disabled,
+.ui-grid-pager-control button[disabled],
+fieldset[disabled] .ui-grid-pager-control button {
+ cursor: not-allowed;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+a.ui-grid-pager-control button.disabled,
+fieldset[disabled] a.ui-grid-pager-control button {
+ pointer-events: none;
+}
+.ui-grid-pager-control button:focus,
+.ui-grid-pager-control button.focus {
+ color: #eeeeee;
+ background-color: #dadada;
+ border-color: #8c8c8c;
+}
+.ui-grid-pager-control button:hover {
+ color: #eeeeee;
+ background-color: #dadada;
+ border-color: #adadad;
+}
+.ui-grid-pager-control button:active,
+.ui-grid-pager-control button.active,
+.open > .dropdown-toggle.ui-grid-pager-control button {
+ color: #eeeeee;
+ background-color: #dadada;
+ border-color: #adadad;
+}
+.ui-grid-pager-control button:active:hover,
+.ui-grid-pager-control button.active:hover,
+.open > .dropdown-toggle.ui-grid-pager-control button:hover,
+.ui-grid-pager-control button:active:focus,
+.ui-grid-pager-control button.active:focus,
+.open > .dropdown-toggle.ui-grid-pager-control button:focus,
+.ui-grid-pager-control button:active.focus,
+.ui-grid-pager-control button.active.focus,
+.open > .dropdown-toggle.ui-grid-pager-control button.focus {
+ color: #eeeeee;
+ background-color: #c8c8c8;
+ border-color: #8c8c8c;
+}
+.ui-grid-pager-control button:active,
+.ui-grid-pager-control button.active,
+.open > .dropdown-toggle.ui-grid-pager-control button {
+ background-image: none;
+}
+.ui-grid-pager-control button.disabled:hover,
+.ui-grid-pager-control button[disabled]:hover,
+fieldset[disabled] .ui-grid-pager-control button:hover,
+.ui-grid-pager-control button.disabled:focus,
+.ui-grid-pager-control button[disabled]:focus,
+fieldset[disabled] .ui-grid-pager-control button:focus,
+.ui-grid-pager-control button.disabled.focus,
+.ui-grid-pager-control button[disabled].focus,
+fieldset[disabled] .ui-grid-pager-control button.focus {
+ background-color: #f3f3f3;
+ border-color: #cccccc;
+}
+.ui-grid-pager-control button .badge {
+ color: #f3f3f3;
+ background-color: #eeeeee;
+}
+.ui-grid-pager-control input {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555555;
+ background-color: #ffffff;
+ background-image: none;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+ display: inline;
+ height: 26px;
+ width: 50px;
+ vertical-align: top;
+}
+.ui-grid-pager-control input:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.ui-grid-pager-control input::-moz-placeholder {
+ color: #999999;
+ opacity: 1;
+}
+.ui-grid-pager-control input:-ms-input-placeholder {
+ color: #999999;
+}
+.ui-grid-pager-control input::-webkit-input-placeholder {
+ color: #999999;
+}
+.ui-grid-pager-control input::-ms-expand {
+ border: 0;
+ background-color: transparent;
+}
+.ui-grid-pager-control input[disabled],
+.ui-grid-pager-control input[readonly],
+fieldset[disabled] .ui-grid-pager-control input {
+ background-color: #eeeeee;
+ opacity: 1;
+}
+.ui-grid-pager-control input[disabled],
+fieldset[disabled] .ui-grid-pager-control input {
+ cursor: not-allowed;
+}
+textarea.ui-grid-pager-control input {
+ height: auto;
+}
+select.ui-grid-pager-control input {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.ui-grid-pager-control input,
+select[multiple].ui-grid-pager-control input {
+ height: auto;
+}
+.ui-grid-pager-control .ui-grid-pager-max-pages-number {
+ vertical-align: bottom;
+}
+.ui-grid-pager-control .ui-grid-pager-max-pages-number > * {
+ vertical-align: middle;
+}
+.ui-grid-pager-control .first-bar {
+ width: 10px;
+ border-left: 2px solid #4d4d4d;
+ margin-top: -6px;
+ height: 12px;
+ margin-left: -3px;
+}
+.ui-grid-pager-control .first-bar-rtl {
+ width: 10px;
+ border-left: 2px solid #4d4d4d;
+ margin-top: -6px;
+ height: 12px;
+ margin-right: -7px;
+}
+.ui-grid-pager-control .first-triangle {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-width: 5px 8.7px 5px 0;
+ border-color: transparent #4d4d4d transparent transparent;
+ margin-left: 2px;
+}
+.ui-grid-pager-control .next-triangle {
+ margin-left: 1px;
+}
+.ui-grid-pager-control .prev-triangle {
+ margin-left: 0;
+}
+.ui-grid-pager-control .last-triangle {
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-width: 5px 0 5px 8.7px;
+ border-color: transparent transparent transparent #4d4d4d;
+ margin-left: -1px;
+}
+.ui-grid-pager-control .last-bar {
+ width: 10px;
+ border-left: 2px solid #4d4d4d;
+ margin-top: -6px;
+ height: 12px;
+ margin-left: 1px;
+}
+.ui-grid-pager-control .last-bar-rtl {
+ width: 10px;
+ border-left: 2px solid #4d4d4d;
+ margin-top: -6px;
+ height: 12px;
+ margin-right: -11px;
+}
+.ui-grid-pager-row-count-picker {
+ float: left;
+}
+.ui-grid-pager-row-count-picker select {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555555;
+ background-color: #ffffff;
+ background-image: none;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+ height: 26px;
+ width: 67px;
+ display: inline;
+}
+.ui-grid-pager-row-count-picker select:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.ui-grid-pager-row-count-picker select::-moz-placeholder {
+ color: #999999;
+ opacity: 1;
+}
+.ui-grid-pager-row-count-picker select:-ms-input-placeholder {
+ color: #999999;
+}
+.ui-grid-pager-row-count-picker select::-webkit-input-placeholder {
+ color: #999999;
+}
+.ui-grid-pager-row-count-picker select::-ms-expand {
+ border: 0;
+ background-color: transparent;
+}
+.ui-grid-pager-row-count-picker select[disabled],
+.ui-grid-pager-row-count-picker select[readonly],
+fieldset[disabled] .ui-grid-pager-row-count-picker select {
+ background-color: #eeeeee;
+ opacity: 1;
+}
+.ui-grid-pager-row-count-picker select[disabled],
+fieldset[disabled] .ui-grid-pager-row-count-picker select {
+ cursor: not-allowed;
+}
+textarea.ui-grid-pager-row-count-picker select {
+ height: auto;
+}
+select.ui-grid-pager-row-count-picker select {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.ui-grid-pager-row-count-picker select,
+select[multiple].ui-grid-pager-row-count-picker select {
+ height: auto;
+}
+.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {
+ margin-top: 3px;
+}
+.ui-grid-pager-count-container {
+ float: right;
+ margin-top: 4px;
+ min-width: 50px;
+}
+.ui-grid-pager-count-container .ui-grid-pager-count {
+ margin-right: 10px;
+ margin-left: 10px;
+ float: right;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-pinned-container {
+ position: absolute;
+ display: inline;
+ top: 0;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left {
+ float: left;
+ left: 0;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right {
+ float: right;
+ right: 0;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {
+ box-sizing: border-box;
+ border-right: 1px solid;
+ border-width: 1px;
+ border-right-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {
+ box-sizing: border-box;
+ border-right: 1px solid;
+ border-width: 1px;
+ border-right-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,
+.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
+ width: 1px;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
+ background-color: #d4d4d4;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
+ background-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {
+ right: -1px;
+ width: 1px;
+ background-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {
+ box-sizing: border-box;
+ border-left: 1px solid;
+ border-width: 1px;
+ border-left-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {
+ box-sizing: border-box;
+ border-left: 1px solid;
+ border-width: 1px;
+ border-left-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,
+.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {
+ width: 1px;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {
+ background-color: #d4d4d4;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
+ background-color: #aeaeae;
+}
+.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {
+ left: -1px;
+ width: 1px;
+ background-color: #aeaeae;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-column-resizer {
+ top: 0;
+ bottom: 0;
+ width: 5px;
+ position: absolute;
+ cursor: col-resize;
+}
+.ui-grid-column-resizer.left {
+ left: 0;
+}
+.ui-grid-column-resizer.right {
+ right: 0;
+}
+.ui-grid-header-cell:last-child .ui-grid-column-resizer.right {
+ border-right: 1px solid #d4d4d4;
+}
+.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {
+ border-right: 0;
+}
+.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.left {
+ border-left: 1px solid #d4d4d4;
+}
+.ui-grid.column-resizing {
+ cursor: col-resize;
+}
+.ui-grid.column-resizing .ui-grid-resize-overlay {
+ position: absolute;
+ top: 0;
+ height: 100%;
+ width: 1px;
+ background-color: #aeaeae;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-row-saving .ui-grid-cell {
+ color: #848484 !important;
+}
+.ui-grid-row-dirty .ui-grid-cell {
+ color: #610b38;
+}
+.ui-grid-row-error .ui-grid-cell {
+ color: #ff0000 !important;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {
+ background-color: #c9dde1;
+}
+.ui-grid-disable-selection {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: default;
+}
+.ui-grid-selection-row-header-buttons {
+ cursor: pointer;
+ opacity: 0.1;
+}
+.ui-grid-selection-row-header-buttons.ui-grid-row-selected {
+ opacity: 1;
+}
+.ui-grid-selection-row-header-buttons.ui-grid-all-selected {
+ opacity: 1;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-tree-row-header-buttons.ui-grid-tree-header {
+ cursor: pointer;
+ opacity: 1;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+.ui-grid-tree-header-row {
+ font-weight: bold !important;
+}
+.ui-grid-tree-header-row .ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell {
+ pointer-events: all;
+}
+
+/* This file contains variable declarations (do not remove this line) */
+/*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+/**
+* @section Grid styles
+*/
+/**
+* @section Header styles
+*/
+/** @description Colors for header gradient */
+/**
+* @section Grid body styles
+*/
+/** @description Colors used for row alternation */
+/**
+* @section Sort arrow colors
+*/
+/**
+* @section Scrollbar styles
+*/
+/**
+* @section font library path
+*/
+/*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
+div.ui-grid-cell-contents.invalid {
+ border: 1px solid #fc8f8f;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.eot b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.eot
new file mode 100644
index 00000000..3b343158
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.eot
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.js
new file mode 100644
index 00000000..df03c974
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.js
@@ -0,0 +1,28935 @@
+/*!
+ * ui-grid - v4.0.2 - 2016-12-30
+ * Copyright (c) 2016 ; License: MIT
+ */
+
+(function () {
+ 'use strict';
+ angular.module('ui.grid.i18n', []);
+ angular.module('ui.grid', ['ui.grid.i18n']);
+})();
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.service:uiGridConstants
+ * @description Constants for use across many grid features
+ *
+ */
+
+
+ angular.module('ui.grid').constant('uiGridConstants', {
+ LOG_DEBUG_MESSAGES: true,
+ LOG_WARN_MESSAGES: true,
+ LOG_ERROR_MESSAGES: true,
+ CUSTOM_FILTERS: /CUSTOM_FILTERS/g,
+ COL_FIELD: /COL_FIELD/g,
+ MODEL_COL_FIELD: /MODEL_COL_FIELD/g,
+ TOOLTIP: /title=\"TOOLTIP\"/g,
+ DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,
+ TEMPLATE_REGEXP: /<.+>/,
+ FUNC_REGEXP: /(\([^)]*\))?$/,
+ DOT_REGEXP: /\./g,
+ APOS_REGEXP: /'/g,
+ BRACKET_REGEXP: /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,
+ COL_CLASS_PREFIX: 'ui-grid-col',
+ ENTITY_BINDING: '$$this',
+ events: {
+ GRID_SCROLL: 'uiGridScroll',
+ COLUMN_MENU_SHOWN: 'uiGridColMenuShown',
+ ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged
+ COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'
+ },
+ // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html
+ keymap: {
+ TAB: 9,
+ STRG: 17,
+ CAPSLOCK: 20,
+ CTRL: 17,
+ CTRLRIGHT: 18,
+ CTRLR: 18,
+ SHIFT: 16,
+ RETURN: 13,
+ ENTER: 13,
+ BACKSPACE: 8,
+ BCKSP: 8,
+ ALT: 18,
+ ALTR: 17,
+ ALTRIGHT: 17,
+ SPACE: 32,
+ WIN: 91,
+ MAC: 91,
+ FN: null,
+ PG_UP: 33,
+ PG_DOWN: 34,
+ UP: 38,
+ DOWN: 40,
+ LEFT: 37,
+ RIGHT: 39,
+ ESC: 27,
+ DEL: 46,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123
+ },
+ /**
+ * @ngdoc object
+ * @name ASC
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and
+ * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}
+ * to configure the sorting direction of the column
+ */
+ ASC: 'asc',
+ /**
+ * @ngdoc object
+ * @name DESC
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and
+ * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}
+ * to configure the sorting direction of the column
+ */
+ DESC: 'desc',
+
+
+ /**
+ * @ngdoc object
+ * @name filter
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_filter columnDef.filter}
+ * to configure filtering on the column
+ *
+ * `SELECT` and `INPUT` are used with the `type` property of the filter, the rest are used to specify
+ * one of the built-in conditions.
+ *
+ * Available `condition` options are:
+ * - `uiGridConstants.filter.STARTS_WITH`
+ * - `uiGridConstants.filter.ENDS_WITH`
+ * - `uiGridConstants.filter.CONTAINS`
+ * - `uiGridConstants.filter.GREATER_THAN`
+ * - `uiGridConstants.filter.GREATER_THAN_OR_EQUAL`
+ * - `uiGridConstants.filter.LESS_THAN`
+ * - `uiGridConstants.filter.LESS_THAN_OR_EQUAL`
+ * - `uiGridConstants.filter.NOT_EQUAL`
+ * - `uiGridConstants.filter.STARTS_WITH`
+ *
+ *
+ * Available `type` options are:
+ * - `uiGridConstants.filter.SELECT` - use a dropdown box for the cell header filter field
+ * - `uiGridConstants.filter.INPUT` - use a text box for the cell header filter field
+ */
+ filter: {
+ STARTS_WITH: 2,
+ ENDS_WITH: 4,
+ EXACT: 8,
+ CONTAINS: 16,
+ GREATER_THAN: 32,
+ GREATER_THAN_OR_EQUAL: 64,
+ LESS_THAN: 128,
+ LESS_THAN_OR_EQUAL: 256,
+ NOT_EQUAL: 512,
+ SELECT: 'select',
+ INPUT: 'input'
+ },
+
+ /**
+ * @ngdoc object
+ * @name aggregationTypes
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_aggregationType columnDef.aggregationType}
+ * to specify the type of built-in aggregation the column should use.
+ *
+ * Available options are:
+ * - `uiGridConstants.aggregationTypes.sum` - add the values in this column to produce the aggregated value
+ * - `uiGridConstants.aggregationTypes.count` - count the number of rows to produce the aggregated value
+ * - `uiGridConstants.aggregationTypes.avg` - average the values in this column to produce the aggregated value
+ * - `uiGridConstants.aggregationTypes.min` - use the minimum value in this column as the aggregated value
+ * - `uiGridConstants.aggregationTypes.max` - use the maximum value in this column as the aggregated value
+ */
+ aggregationTypes: {
+ sum: 2,
+ count: 4,
+ avg: 8,
+ min: 16,
+ max: 32
+ },
+
+ /**
+ * @ngdoc array
+ * @name CURRENCY_SYMBOLS
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description A list of all presently circulating currency symbols that was copied from
+ * https://en.wikipedia.org/wiki/Currency_symbol#List_of_presently-circulating_currency_symbols
+ *
+ * Can be used on {@link ui.grid.class:rowSorter} to create a number string regex that ignores currency symbols.
+ */
+ CURRENCY_SYMBOLS: ['¤', '؋', 'Ar', 'Ƀ', '฿', 'B/.', 'Br', 'Bs.', 'Bs.F.', 'GH₵', '¢', 'c', 'Ch.', '₡', 'C$', 'D', 'ден',
+ 'دج', '.د.ب', 'د.ع', 'JD', 'د.ك', 'ل.د', 'дин', 'د.ت', 'د.م.', 'د.إ', 'Db', '$', '₫', 'Esc', '€', 'ƒ', 'Ft', 'FBu',
+ 'FCFA', 'CFA', 'Fr', 'FRw', 'G', 'gr', '₲', 'h', 'â‚´', 'â‚­', 'KÄ', 'kr', 'kn', 'MK', 'ZK', 'Kz', 'K', 'L', 'Le', 'лв',
+ 'E', 'lp', 'M', 'KM', 'MT', '₥', 'Nfk', '₦', 'Nu.', 'UM', 'T$', 'MOP$', '₱', 'Pt.', '£', 'ج.م.', 'LL', 'LS', 'P', 'Q',
+ 'q', 'R', 'R$', 'ر.ع.', 'ر.ق', 'ر.س', '៛', 'RM', 'p', 'Rf.', '₹', '₨', 'SRe', 'Rp', '₪', 'Ksh', 'Sh.So.', 'USh', 'S/',
+ 'SDR', 'Ñом', '৳ ', 'WS$', 'â‚®', 'VT', 'â‚©', 'Â¥', 'zÅ‚'],
+
+ /**
+ * @ngdoc object
+ * @name scrollDirection
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Set on {@link ui.grid.class:Grid#properties_scrollDirection Grid.scrollDirection},
+ * to indicate the direction the grid is currently scrolling in
+ *
+ * Available options are:
+ * - `uiGridConstants.scrollDirection.UP` - set when the grid is scrolling up
+ * - `uiGridConstants.scrollDirection.DOWN` - set when the grid is scrolling down
+ * - `uiGridConstants.scrollDirection.LEFT` - set when the grid is scrolling left
+ * - `uiGridConstants.scrollDirection.RIGHT` - set when the grid is scrolling right
+ * - `uiGridConstants.scrollDirection.NONE` - set when the grid is not scrolling, this is the default
+ */
+ scrollDirection: {
+ UP: 'up',
+ DOWN: 'down',
+ LEFT: 'left',
+ RIGHT: 'right',
+ NONE: 'none'
+
+ },
+
+ /**
+ * @ngdoc object
+ * @name dataChange
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used with {@link ui.grid.core.api:PublicApi#methods_notifyDataChange PublicApi.notifyDataChange},
+ * {@link ui.grid.class:Grid#methods_callDataChangeCallbacks Grid.callDataChangeCallbacks},
+ * and {@link ui.grid.class:Grid#methods_registerDataChangeCallback Grid.registerDataChangeCallback}
+ * to specify the type of the event(s).
+ *
+ * Available options are:
+ * - `uiGridConstants.dataChange.ALL` - listeners fired on any of these events, fires listeners on all events.
+ * - `uiGridConstants.dataChange.EDIT` - fired when the data in a cell is edited
+ * - `uiGridConstants.dataChange.ROW` - fired when a row is added or removed
+ * - `uiGridConstants.dataChange.COLUMN` - fired when the column definitions are modified
+ * - `uiGridConstants.dataChange.OPTIONS` - fired when the grid options are modified
+ */
+ dataChange: {
+ ALL: 'all',
+ EDIT: 'edit',
+ ROW: 'row',
+ COLUMN: 'column',
+ OPTIONS: 'options'
+ },
+
+ /**
+ * @ngdoc object
+ * @name scrollbars
+ * @propertyOf ui.grid.service:uiGridConstants
+ * @description Used with {@link ui.grid.class:GridOptions#properties_enableHorizontalScrollbar GridOptions.enableHorizontalScrollbar}
+ * and {@link ui.grid.class:GridOptions#properties_enableVerticalScrollbar GridOptions.enableVerticalScrollbar}
+ * to specify the scrollbar policy for that direction.
+ *
+ * Available options are:
+ * - `uiGridConstants.scrollbars.NEVER` - never show scrollbars in this direction
+ * - `uiGridConstants.scrollbars.ALWAYS` - always show scrollbars in this direction
+ */
+
+ scrollbars: {
+ NEVER: 0,
+ ALWAYS: 1
+ //WHEN_NEEDED: 2
+ }
+ });
+
+})();
+
+angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {
+ var uiGridCell = {
+ priority: 0,
+ scope: false,
+ require: '?^uiGrid',
+ compile: function() {
+ return {
+ pre: function($scope, $elm, $attrs, uiGridCtrl) {
+ function compileTemplate() {
+ var compiledElementFn = $scope.col.compiledElementFn;
+
+ compiledElementFn($scope, function(clonedElement, scope) {
+ $elm.append(clonedElement);
+ });
+ }
+
+ // If the grid controller is present, use it to get the compiled cell template function
+ if (uiGridCtrl && $scope.col.compiledElementFn) {
+ compileTemplate();
+ }
+ // No controller, compile the element manually (for unit tests)
+ else {
+ if ( uiGridCtrl && !$scope.col.compiledElementFn ){
+ // gridUtil.logError('Render has been called before precompile. Please log a ui-grid issue');
+
+ $scope.col.getCompiledElementFn()
+ .then(function (compiledElementFn) {
+ compiledElementFn($scope, function(clonedElement, scope) {
+ $elm.append(clonedElement);
+ });
+ });
+ }
+ else {
+ var html = $scope.col.cellTemplate
+ .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))
+ .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var cellElement = $compile(html)($scope);
+ $elm.append(cellElement);
+ }
+ }
+ },
+ post: function($scope, $elm, $attrs, uiGridCtrl) {
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ var classAdded;
+ var updateClass = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.cellClass)) {
+ classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.cellClass;
+ }
+ contents.addClass(classAdded);
+ };
+
+ if ($scope.col.cellClass) {
+ updateClass();
+ }
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);
+
+ // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise
+ // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things
+ var cellChangeFunction = function( n, o ){
+ if ( n !== o ) {
+ if ( classAdded || $scope.col.cellClass ){
+ updateClass();
+ }
+
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ };
+
+ // TODO(c0bra): Turn this into a deep array watch
+/* shouldn't be needed any more given track by col.name
+ var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );
+*/
+ var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );
+
+
+ var deregisterFunction = function() {
+ dataChangeDereg();
+// colWatchDereg();
+ rowWatchDereg();
+ };
+
+ $scope.$on( '$destroy', deregisterFunction );
+ $elm.on( '$destroy', deregisterFunction );
+ }
+ };
+ }
+ };
+
+ return uiGridCell;
+}]);
+
+
+(function(){
+
+angular.module('ui.grid')
+.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',
+function ( i18nService, uiGridConstants, gridUtil ) {
+/**
+ * @ngdoc service
+ * @name ui.grid.service:uiGridColumnMenuService
+ *
+ * @description Services for working with column menus, factored out
+ * to make the code easier to understand
+ */
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name initialize
+ * @description Sets defaults, puts a reference to the $scope on
+ * the uiGridController
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {controller} uiGridCtrl the uiGridController for the grid
+ * we're on
+ *
+ */
+ initialize: function( $scope, uiGridCtrl ){
+ $scope.grid = uiGridCtrl.grid;
+
+ // Store a reference to this link/controller in the main uiGrid controller
+ // to allow showMenu later
+ uiGridCtrl.columnMenuScope = $scope;
+
+ // Save whether we're shown or not so the columns can check
+ $scope.menuShown = false;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name setColMenuItemWatch
+ * @description Setup a watch on $scope.col.menuItems, and update
+ * menuItems based on this. $scope.col needs to be set by the column
+ * before calling the menu.
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {controller} uiGridCtrl the uiGridController for the grid
+ * we're on
+ *
+ */
+ setColMenuItemWatch: function ( $scope ){
+ var deregFunction = $scope.$watch('col.menuItems', function (n) {
+ if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {
+ n.forEach(function (item) {
+ if (typeof(item.context) === 'undefined' || !item.context) {
+ item.context = {};
+ }
+ item.context.col = $scope.col;
+ });
+
+ $scope.menuItems = $scope.defaultMenuItems.concat(n);
+ }
+ else {
+ $scope.menuItems = $scope.defaultMenuItems;
+ }
+ });
+
+ $scope.$on( '$destroy', deregFunction );
+ },
+
+
+ /**
+ * @ngdoc boolean
+ * @name enableSorting
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) True by default. When enabled, this setting adds sort
+ * widgets to the column header, allowing sorting of the data in the individual column.
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name sortable
+ * @description determines whether this column is sortable
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ sortable: function( $scope ) {
+ if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name isActiveSort
+ * @description determines whether the requested sort direction is current active, to
+ * allow highlighting in the menu
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {string} direction the direction that we'd have selected for us to be active
+ *
+ */
+ isActiveSort: function( $scope, direction ){
+ return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&
+ typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);
+
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name suppressRemoveSort
+ * @description determines whether we should suppress the removeSort option
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ suppressRemoveSort: function( $scope ) {
+ if ($scope.col && $scope.col.suppressRemoveSort) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+
+ /**
+ * @ngdoc boolean
+ * @name enableHiding
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column
+ * using the column menu or the grid menu.
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name hideable
+ * @description determines whether a column can be hidden, by checking the enableHiding columnDef option
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ hideable: function( $scope ) {
+ if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name getDefaultMenuItems
+ * @description returns the default menu items for a column menu
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ getDefaultMenuItems: function( $scope ){
+ return [
+ {
+ title: i18nService.getSafeText('sort.ascending'),
+ icon: 'ui-grid-icon-sort-alt-up',
+ action: function($event) {
+ $event.stopPropagation();
+ $scope.sortColumn($event, uiGridConstants.ASC);
+ },
+ shown: function () {
+ return service.sortable( $scope );
+ },
+ active: function() {
+ return service.isActiveSort( $scope, uiGridConstants.ASC);
+ }
+ },
+ {
+ title: i18nService.getSafeText('sort.descending'),
+ icon: 'ui-grid-icon-sort-alt-down',
+ action: function($event) {
+ $event.stopPropagation();
+ $scope.sortColumn($event, uiGridConstants.DESC);
+ },
+ shown: function() {
+ return service.sortable( $scope );
+ },
+ active: function() {
+ return service.isActiveSort( $scope, uiGridConstants.DESC);
+ }
+ },
+ {
+ title: i18nService.getSafeText('sort.remove'),
+ icon: 'ui-grid-icon-cancel',
+ action: function ($event) {
+ $event.stopPropagation();
+ $scope.unsortColumn();
+ },
+ shown: function() {
+ return service.sortable( $scope ) &&
+ typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&
+ typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&
+ !service.suppressRemoveSort( $scope );
+ }
+ },
+ {
+ title: i18nService.getSafeText('column.hide'),
+ icon: 'ui-grid-icon-cancel',
+ shown: function() {
+ return service.hideable( $scope );
+ },
+ action: function ($event) {
+ $event.stopPropagation();
+ $scope.hideColumn();
+ }
+ }
+ ];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name getColumnElementPosition
+ * @description gets the position information needed to place the column
+ * menu below the column header
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {GridCol} column the column we want to position below
+ * @param {element} $columnElement the column element we want to position below
+ * @returns {hash} containing left, top, offset, height, width
+ *
+ */
+ getColumnElementPosition: function( $scope, column, $columnElement ){
+ var positionData = {};
+ positionData.left = $columnElement[0].offsetLeft;
+ positionData.top = $columnElement[0].offsetTop;
+ positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;
+
+ // Get the grid scrollLeft
+ positionData.offset = 0;
+ if (column.grid.options.offsetLeft) {
+ positionData.offset = column.grid.options.offsetLeft;
+ }
+
+ positionData.height = gridUtil.elementHeight($columnElement, true);
+ positionData.width = gridUtil.elementWidth($columnElement, true);
+
+ return positionData;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name repositionMenu
+ * @description Reposition the menu below the new column. If the menu has no child nodes
+ * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again
+ * later to fix it
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {GridCol} column the column we want to position below
+ * @param {hash} positionData a hash containing left, top, offset, height, width
+ * @param {element} $elm the column menu element that we want to reposition
+ * @param {element} $columnElement the column element that we want to reposition underneath
+ *
+ */
+ repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {
+ var menu = $elm[0].querySelectorAll('.ui-grid-menu');
+
+ // It's possible that the render container of the column we're attaching to is
+ // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft
+ // between the render container and the grid
+ var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');
+ var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;
+
+ var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;
+
+ // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170
+ var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);
+ var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
+
+ if ( menu.length !== 0 ){
+ var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');
+ if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {
+ myWidth = gridUtil.elementWidth(menu, true);
+ $scope.lastMenuWidth = myWidth;
+ column.lastMenuWidth = myWidth;
+
+ // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
+ // Get the column menu right padding
+ paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
+ $scope.lastMenuPaddingRight = paddingRight;
+ column.lastMenuPaddingRight = paddingRight;
+ }
+ }
+
+ var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight;
+ if (left < positionData.offset){
+ left = positionData.offset;
+ }
+
+ $elm.css('left', left + 'px');
+ $elm.css('top', (positionData.top + positionData.height) + 'px');
+ }
+
+ };
+
+ return service;
+}])
+
+
+.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',
+function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridColumnMenu
+ * @description Provides the column menu framework, leverages uiGridMenu underneath
+ *
+ */
+
+ var uiGridColumnMenu = {
+ priority: 0,
+ scope: true,
+ require: '^uiGrid',
+ templateUrl: 'ui-grid/uiGridColumnMenu',
+ replace: true,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridColumnMenuService.initialize( $scope, uiGridCtrl );
+
+ $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );
+
+ // Set the menu items for use with the column menu. The user can later add additional items via the watch
+ $scope.menuItems = $scope.defaultMenuItems;
+ uiGridColumnMenuService.setColMenuItemWatch( $scope );
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.directive:uiGridColumnMenu
+ * @name showMenu
+ * @description Shows the column menu. If the menu is already displayed it
+ * calls the menu to ask it to hide (it will animate), then it repositions the menu
+ * to the right place whilst hidden (it will make an assumption on menu width),
+ * then it asks the menu to show (it will animate), then it repositions the menu again
+ * once we can calculate it's size.
+ * @param {GridCol} column the column we want to position below
+ * @param {element} $columnElement the column element we want to position below
+ */
+ $scope.showMenu = function(column, $columnElement, event) {
+ // Swap to this column
+ $scope.col = column;
+
+ // Get the position information for the column element
+ var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
+
+ if ($scope.menuShown) {
+ // we want to hide, then reposition, then show, but we want to wait for animations
+ // we set a variable, and then rely on the menu-hidden event to call the reposition and show
+ $scope.colElement = $columnElement;
+ $scope.colElementPosition = colElementPosition;
+ $scope.hideThenShow = true;
+
+ $scope.$broadcast('hide-menu', { originalEvent: event });
+ } else {
+ $scope.menuShown = true;
+ uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
+
+ $scope.colElement = $columnElement;
+ $scope.colElementPosition = colElementPosition;
+ $scope.$broadcast('show-menu', { originalEvent: event });
+
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.directive:uiGridColumnMenu
+ * @name hideMenu
+ * @description Hides the column menu.
+ * @param {boolean} broadcastTrigger true if we were triggered by a broadcast
+ * from the menu itself - in which case don't broadcast again as we'll get
+ * an infinite loop
+ */
+ $scope.hideMenu = function( broadcastTrigger ) {
+ $scope.menuShown = false;
+ if ( !broadcastTrigger ){
+ $scope.$broadcast('hide-menu');
+ }
+ };
+
+
+ $scope.$on('menu-hidden', function() {
+ if ( $scope.hideThenShow ){
+ delete $scope.hideThenShow;
+
+ uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
+ $scope.$broadcast('show-menu');
+
+ $scope.menuShown = true;
+ } else {
+ $scope.hideMenu( true );
+
+ if ($scope.col) {
+ //Focus on the menu button
+ gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);
+ }
+ }
+ });
+
+ $scope.$on('menu-shown', function() {
+ $timeout( function() {
+ uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
+ //Focus on the first item
+ gridUtil.focus.bySelector($document, '.ui-grid-menu-items .ui-grid-menu-item', true);
+ delete $scope.colElementPosition;
+ delete $scope.columnElement;
+ }, 200);
+ });
+
+
+ /* Column methods */
+ $scope.sortColumn = function (event, dir) {
+ event.stopPropagation();
+
+ $scope.grid.sortColumn($scope.col, dir, true)
+ .then(function () {
+ $scope.grid.refresh();
+ $scope.hideMenu();
+ });
+ };
+
+ $scope.unsortColumn = function () {
+ $scope.col.unsort();
+
+ $scope.grid.refresh();
+ $scope.hideMenu();
+ };
+
+ //Since we are hiding this column the default hide action will fail so we need to focus somewhere else.
+ var setFocusOnHideColumn = function(){
+ $timeout(function(){
+ // Get the UID of the first
+ var focusToGridMenu = function(){
+ return gridUtil.focus.byId('grid-menu', $scope.grid);
+ };
+
+ var thisIndex;
+ $scope.grid.columns.some(function(element, index){
+ if (angular.equals(element, $scope.col)) {
+ thisIndex = index;
+ return true;
+ }
+ });
+
+ var previousVisibleCol;
+ // Try and find the next lower or nearest column to focus on
+ $scope.grid.columns.some(function(element, index){
+ if (!element.visible){
+ return false;
+ } // This columns index is below the current column index
+ else if ( index < thisIndex){
+ previousVisibleCol = element;
+ } // This elements index is above this column index and we haven't found one that is lower
+ else if ( index > thisIndex && !previousVisibleCol) {
+ // This is the next best thing
+ previousVisibleCol = element;
+ // We've found one so use it.
+ return true;
+ } // We've reached an element with an index above this column and the previousVisibleCol variable has been set
+ else if (index > thisIndex && previousVisibleCol) {
+ // We are done.
+ return true;
+ }
+ });
+ // If found then focus on it
+ if (previousVisibleCol){
+ var colClass = previousVisibleCol.getColClass();
+ gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason){
+ if (reason !== 'canceled'){ // If this is canceled then don't perform the action
+ //The fallback action is to focus on the grid menu
+ return focusToGridMenu();
+ }
+ });
+ } else {
+ // Fallback action to focus on the grid menu
+ focusToGridMenu();
+ }
+ });
+ };
+
+ $scope.hideColumn = function () {
+ $scope.col.colDef.visible = false;
+ $scope.col.visible = false;
+
+ $scope.grid.queueGridRefresh();
+ $scope.hideMenu();
+ $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );
+
+ // We are hiding so the default action of focusing on the button that opened this menu will fail.
+ setFocusOnHideColumn();
+ };
+ },
+
+
+
+ controller: ['$scope', function ($scope) {
+ var self = this;
+
+ $scope.$watch('menuItems', function (n) {
+ self.menuItems = n;
+ });
+ }]
+ };
+
+ return uiGridColumnMenu;
+
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {
+
+ return {
+ compile: function() {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ $scope.col.updateFilters = function( filterable ){
+ $elm.children().remove();
+ if ( filterable ){
+ var template = $scope.col.filterHeaderTemplate;
+
+ $elm.append($compile(template)($scope));
+ }
+ };
+
+ $scope.$on( '$destroy', function() {
+ delete $scope.col.updateFilters;
+ });
+ },
+ post: function ($scope, $elm, $attrs, controllers){
+ $scope.aria = i18nService.getSafeText('headerCell.aria');
+ $scope.removeFilter = function(colFilter, index){
+ colFilter.term = null;
+ //Set the focus to the filter input after the action disables the button
+ gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);
+ };
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',
+ function ($timeout, gridUtil, uiGridConstants, $compile) {
+ var uiGridFooterCell = {
+ priority: 0,
+ scope: {
+ col: '=',
+ row: '=',
+ renderIndex: '='
+ },
+ replace: true,
+ require: '^uiGrid',
+ compile: function compile(tElement, tAttrs, transclude) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var cellFooter = $compile($scope.col.footerCellTemplate)($scope);
+ $elm.append(cellFooter);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ //$elm.addClass($scope.col.getColClass(false));
+ $scope.grid = uiGridCtrl.grid;
+
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ // apply any footerCellClass
+ var classAdded;
+ var updateClass = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.footerCellClass)) {
+ classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.footerCellClass;
+ }
+ contents.addClass(classAdded);
+ };
+
+ if ($scope.col.footerCellClass) {
+ updateClass();
+ }
+
+ $scope.col.updateAggregationValue();
+
+ // Watch for column changes so we can alter the col cell class properly
+/* shouldn't be needed any more, given track by col.name
+ $scope.$watch('col', function (n, o) {
+ if (n !== o) {
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ });
+*/
+
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);
+ // listen for visible rows change and update aggregation values
+ $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );
+ $scope.grid.api.core.on.rowsRendered( $scope, updateClass );
+ $scope.$on( '$destroy', dataChangeDereg );
+ }
+ };
+ }
+ };
+
+ return uiGridFooterCell;
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ // priority: 1000,
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ containerCtrl.footer = $elm;
+
+ var footerTemplate = $scope.grid.options.footerTemplate;
+ gridUtil.getTemplate(footerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+
+ if (containerCtrl) {
+ // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
+ var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
+
+ if (footerViewport) {
+ containerCtrl.footerViewport = footerViewport;
+ }
+ }
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ // gridUtil.logDebug('ui-grid-footer link');
+
+ var grid = uiGridCtrl.grid;
+
+ // Don't animate footer cells
+ gridUtil.disableAnimations($elm);
+
+ containerCtrl.footer = $elm;
+
+ var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
+ if (footerViewport) {
+ containerCtrl.footerViewport = footerViewport;
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ // priority: 1000,
+ require: '^uiGrid',
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ $scope.grid = uiGridCtrl.grid;
+
+
+
+ var footerTemplate = $scope.grid.options.gridFooterTemplate;
+ gridUtil.getTemplate(footerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridGroupPanel', ["$compile", "uiGridConstants", "gridUtil", function($compile, uiGridConstants, gridUtil) {
+ var defaultTemplate = 'ui-grid/ui-grid-group-panel';
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ require: '?^uiGrid',
+ scope: false,
+ compile: function($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var groupPanelTemplate = $scope.grid.options.groupPanelTemplate || defaultTemplate;
+
+ gridUtil.getTemplate(groupPanelTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ $elm.bind('$destroy', function() {
+ // scrollUnbinder();
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
+ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
+ // Do stuff after mouse has been down this many ms on the header cell
+ var mousedownTimeout = 500;
+ var changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa
+
+ var uiGridHeaderCell = {
+ priority: 0,
+ scope: {
+ col: '=',
+ row: '=',
+ renderIndex: '='
+ },
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ replace: true,
+ compile: function() {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
+ $elm.append(cellHeader);
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var renderContainerCtrl = controllers[1];
+
+ $scope.i18n = {
+ headerCell: i18nService.getSafeText('headerCell'),
+ sort: i18nService.getSafeText('sort')
+ };
+ $scope.isSortPriorityVisible = function() {
+ //show sort priority if column is sorted and there is at least one other sorted column
+ return angular.isNumber($scope.col.sort.priority) && $scope.grid.columns.some(function(element, index){
+ return angular.isNumber(element.sort.priority) && element !== $scope.col;
+ });
+ };
+ $scope.getSortDirectionAriaLabel = function(){
+ var col = $scope.col;
+ //Trying to recreate this sort of thing but it was getting messy having it in the template.
+ //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
+ var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
+ var label = sortDirectionText;
+
+ if ($scope.isSortPriorityVisible()) {
+ label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority;
+ }
+ return label;
+ };
+
+ $scope.grid = uiGridCtrl.grid;
+
+ $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];
+
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ // Hide the menu by default
+ $scope.menuShown = false;
+
+ // Put asc and desc sort directions in scope
+ $scope.asc = uiGridConstants.ASC;
+ $scope.desc = uiGridConstants.DESC;
+
+ // Store a reference to menu element
+ var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );
+
+ var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
+
+
+ // apply any headerCellClass
+ var classAdded;
+ var previousMouseX;
+
+ // filter watchers
+ var filterDeregisters = [];
+
+
+ /*
+ * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
+ * Once we have a down event, we need to work out whether we have a click, a drag, or a
+ * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so
+ * we ignore it. A hold would open the menu.
+ *
+ * So, on down event, we put in place handlers for move and up events, and a timer. If the
+ * timer expires before we see a move or up, then we have a long press and hence a column menu open.
+ * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
+ * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
+ * will handle it.
+ *
+ * To deal with touch enabled devices that also have mice, we only create our handlers when
+ * we get the down event, and we create the corresponding handlers - if we're touchstart then
+ * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
+ *
+ * We also suppress the click action whilst this is happening - otherwise after the mouseup there
+ * will be a click event and that can cause the column menu to close
+ *
+ */
+
+ $scope.downFn = function( event ){
+ event.stopPropagation();
+
+ if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
+ event = event.originalEvent;
+ }
+
+ // Don't show the menu if it's not the left button
+ if (event.button && event.button !== 0) {
+ return;
+ }
+ previousMouseX = event.pageX;
+
+ $scope.mousedownStartTime = (new Date()).getTime();
+ $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);
+
+ $scope.mousedownTimeout.then(function () {
+ if ( $scope.colMenu ) {
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
+ }
+ });
+
+ uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
+
+ $scope.offAllEvents();
+ if ( event.type === 'touchstart'){
+ $document.on('touchend', $scope.upFn);
+ $document.on('touchmove', $scope.moveFn);
+ } else if ( event.type === 'mousedown' ){
+ $document.on('mouseup', $scope.upFn);
+ $document.on('mousemove', $scope.moveFn);
+ }
+ };
+
+ $scope.upFn = function( event ){
+ event.stopPropagation();
+ $timeout.cancel($scope.mousedownTimeout);
+ $scope.offAllEvents();
+ $scope.onDownEvents(event.type);
+
+ var mousedownEndTime = (new Date()).getTime();
+ var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;
+
+ if (mousedownTime > mousedownTimeout) {
+ // long click, handled above with mousedown
+ }
+ else {
+ // short click
+ if ( $scope.sortable ){
+ $scope.handleClick(event);
+ }
+ }
+ };
+
+ $scope.moveFn = function( event ){
+ // Chrome is known to fire some bogus move events.
+ var changeValue = event.pageX - previousMouseX;
+ if ( changeValue === 0 ){ return; }
+
+ // we're a move, so do nothing and leave for column move (if enabled) to take over
+ $timeout.cancel($scope.mousedownTimeout);
+ $scope.offAllEvents();
+ $scope.onDownEvents(event.type);
+ };
+
+ $scope.clickFn = function ( event ){
+ event.stopPropagation();
+ $contentsElm.off('click', $scope.clickFn);
+ };
+
+
+ $scope.offAllEvents = function(){
+ $contentsElm.off('touchstart', $scope.downFn);
+ $contentsElm.off('mousedown', $scope.downFn);
+
+ $document.off('touchend', $scope.upFn);
+ $document.off('mouseup', $scope.upFn);
+
+ $document.off('touchmove', $scope.moveFn);
+ $document.off('mousemove', $scope.moveFn);
+
+ $contentsElm.off('click', $scope.clickFn);
+ };
+
+ $scope.onDownEvents = function( type ){
+ // If there is a previous event, then wait a while before
+ // activating the other mode - i.e. if the last event was a touch event then
+ // don't enable mouse events for a wee while (500ms or so)
+ // Avoids problems with devices that emulate mouse events when you have touch events
+
+ switch (type){
+ case 'touchmove':
+ case 'touchend':
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('touchstart', $scope.downFn);
+ $timeout(function(){
+ $contentsElm.on('mousedown', $scope.downFn);
+ }, changeModeTimeout);
+ break;
+ case 'mousemove':
+ case 'mouseup':
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('mousedown', $scope.downFn);
+ $timeout(function(){
+ $contentsElm.on('touchstart', $scope.downFn);
+ }, changeModeTimeout);
+ break;
+ default:
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('touchstart', $scope.downFn);
+ $contentsElm.on('mousedown', $scope.downFn);
+ }
+ };
+
+
+ var updateHeaderOptions = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.headerCellClass)) {
+ classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.headerCellClass;
+ }
+ contents.addClass(classAdded);
+
+ $timeout(function (){
+ var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
+ $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
+ });
+
+ // Figure out whether this column is sortable or not
+ if ($scope.col.enableSorting) {
+ $scope.sortable = true;
+ }
+ else {
+ $scope.sortable = false;
+ }
+
+ // Figure out whether this column is filterable or not
+ var oldFilterable = $scope.filterable;
+ if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
+ $scope.filterable = true;
+ }
+ else {
+ $scope.filterable = false;
+ }
+
+ if ( oldFilterable !== $scope.filterable){
+ if ( typeof($scope.col.updateFilters) !== 'undefined' ){
+ $scope.col.updateFilters($scope.filterable);
+ }
+
+ // if column is filterable add a filter watcher
+ if ($scope.filterable) {
+ $scope.col.filters.forEach( function(filter, i) {
+ filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
+ if (n !== o) {
+ uiGridCtrl.grid.api.core.raise.filterChanged();
+ uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ uiGridCtrl.grid.queueGridRefresh();
+ }
+ }));
+ });
+ $scope.$on('$destroy', function() {
+ filterDeregisters.forEach( function(filterDeregister) {
+ filterDeregister();
+ });
+ });
+ } else {
+ filterDeregisters.forEach( function(filterDeregister) {
+ filterDeregister();
+ });
+ }
+
+ }
+
+ // figure out whether we support column menus
+ if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
+ $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
+ $scope.colMenu = true;
+ } else {
+ $scope.colMenu = false;
+ }
+
+ /**
+ * @ngdoc property
+ * @name enableColumnMenu
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description if column menus are enabled, controls the column menus for this specific
+ * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
+ * using this option. If gridOptions.enableColumnMenus === false then you get no column
+ * menus irrespective of the value of this option ). Defaults to true.
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name enableColumnMenus
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Override for column menus everywhere - if set to false then you get no
+ * column menus. Defaults to true.
+ *
+ */
+
+ $scope.offAllEvents();
+
+ if ($scope.sortable || $scope.colMenu) {
+ $scope.onDownEvents();
+
+ $scope.$on('$destroy', function () {
+ $scope.offAllEvents();
+ });
+ }
+ };
+
+/*
+ $scope.$watch('col', function (n, o) {
+ if (n !== o) {
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ });
+*/
+ updateHeaderOptions();
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);
+
+ $scope.$on( '$destroy', dataChangeDereg );
+
+ $scope.handleClick = function(event) {
+ // If the shift key is being held down, add this column to the sort
+ var add = false;
+ if (event.shiftKey) {
+ add = true;
+ }
+
+ // Sort this column then rebuild the grid's rows
+ uiGridCtrl.grid.sortColumn($scope.col, add)
+ .then(function () {
+ if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
+ uiGridCtrl.grid.refresh();
+ });
+ };
+
+
+ $scope.toggleMenu = function(event) {
+ event.stopPropagation();
+
+ // If the menu is already showing...
+ if (uiGridCtrl.columnMenuScope.menuShown) {
+ // ... and we're the column the menu is on...
+ if (uiGridCtrl.columnMenuScope.col === $scope.col) {
+ // ... hide it
+ uiGridCtrl.columnMenuScope.hideMenu();
+ }
+ // ... and we're NOT the column the menu is on
+ else {
+ // ... move the menu to our column
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
+ }
+ }
+ // If the menu is NOT showing
+ else {
+ // ... show it on our column
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
+ }
+ };
+ }
+ };
+ }
+ };
+
+ return uiGridHeaderCell;
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',
+ function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {
+ var defaultTemplate = 'ui-grid/ui-grid-header';
+ var emptyTemplate = 'ui-grid/ui-grid-no-header';
+
+ return {
+ restrict: 'EA',
+ // templateUrl: 'ui-grid/ui-grid-header',
+ replace: true,
+ // priority: 1000,
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: true,
+ compile: function($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ updateHeaderReferences();
+
+ var headerTemplate;
+ if (!$scope.grid.options.showHeader) {
+ headerTemplate = emptyTemplate;
+ }
+ else {
+ headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
+ }
+
+ gridUtil.getTemplate(headerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.replaceWith(newElm);
+
+ // And update $elm to be the new element
+ $elm = newElm;
+
+ updateHeaderReferences();
+
+ if (containerCtrl) {
+ // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
+ var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
+
+
+ if (headerViewport) {
+ containerCtrl.headerViewport = headerViewport;
+ angular.element(headerViewport).on('scroll', scrollHandler);
+ $scope.$on('$destroy', function () {
+ angular.element(headerViewport).off('scroll', scrollHandler);
+ });
+ }
+ }
+
+ $scope.grid.queueRefresh();
+ });
+
+ function updateHeaderReferences() {
+ containerCtrl.header = containerCtrl.colContainer.header = $elm;
+
+ var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');
+
+ if (headerCanvases.length > 0) {
+ containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
+ }
+ else {
+ containerCtrl.headerCanvas = null;
+ }
+ }
+
+ function scrollHandler(evt) {
+ if (uiGridCtrl.grid.isScrollingHorizontally) {
+ return;
+ }
+ var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);
+ var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);
+
+ var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);
+ scrollEvent.newScrollLeft = newScrollLeft;
+ if ( horizScrollPercentage > -1 ){
+ scrollEvent.x = { percentage: horizScrollPercentage };
+ }
+
+ uiGridCtrl.grid.scrollContainers(null, scrollEvent);
+ }
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ // gridUtil.logDebug('ui-grid-header link');
+
+ var grid = uiGridCtrl.grid;
+
+ // Don't animate header cells
+ gridUtil.disableAnimations($elm);
+
+ function updateColumnWidths() {
+ // this styleBuilder always runs after the renderContainer, so we can rely on the column widths
+ // already being populated correctly
+
+ var columnCache = containerCtrl.colContainer.visibleColumnCache;
+
+ // Build the CSS
+ // uiGridCtrl.grid.columns.forEach(function (column) {
+ var ret = '';
+ var canvasWidth = 0;
+ columnCache.forEach(function (column) {
+ ret = ret + column.getColClassDefinition();
+ canvasWidth += column.drawnWidth;
+ });
+
+ containerCtrl.colContainer.canvasWidth = canvasWidth;
+
+ // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
+ return ret;
+ }
+
+ containerCtrl.header = $elm;
+
+ var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
+ if (headerViewport) {
+ containerCtrl.headerViewport = headerViewport;
+ }
+
+ //todo: remove this if by injecting gridCtrl into unit tests
+ if (uiGridCtrl) {
+ uiGridCtrl.grid.registerStyleComputation({
+ priority: 15,
+ func: updateColumnWidths
+ });
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {
+ /**
+ * @ngdoc service
+ * @name ui.grid.gridMenuService
+ *
+ * @description Methods for working with the grid menu
+ */
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name initialize
+ * @description Sets up the gridMenu. Most importantly, sets our
+ * scope onto the grid object as grid.gridMenuScope, allowing us
+ * to operate when passed only the grid. Second most importantly,
+ * we register the 'addToGridMenu' and 'removeFromGridMenu' methods
+ * on the core api.
+ * @param {$scope} $scope the scope of this gridMenu
+ * @param {Grid} grid the grid to which this gridMenu is associated
+ */
+ initialize: function( $scope, grid ){
+ grid.gridMenuScope = $scope;
+ $scope.grid = grid;
+ $scope.registeredMenuItems = [];
+
+ // not certain this is needed, but would be bad to create a memory leak
+ $scope.$on('$destroy', function() {
+ if ( $scope.grid && $scope.grid.gridMenuScope ){
+ $scope.grid.gridMenuScope = null;
+ }
+ if ( $scope.grid ){
+ $scope.grid = null;
+ }
+ if ( $scope.registeredMenuItems ){
+ $scope.registeredMenuItems = null;
+ }
+ });
+
+ $scope.registeredMenuItems = [];
+
+ /**
+ * @ngdoc function
+ * @name addToGridMenu
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description add items to the grid menu. Used by features
+ * to add their menu items if they are enabled, can also be used by
+ * end users to add menu items. This method has the advantage of allowing
+ * remove again, which can simplify management of which items are included
+ * in the menu when. (Noting that in most cases the shown and active functions
+ * provide a better way to handle visibility of menu items)
+ * @param {Grid} grid the grid on which we are acting
+ * @param {array} items menu items in the format as described in the tutorial, with
+ * the added note that if you want to use remove you must also specify an `id` field,
+ * which is provided when you want to remove an item. The id should be unique.
+ *
+ */
+ grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );
+
+ /**
+ * @ngdoc function
+ * @name removeFromGridMenu
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Remove an item from the grid menu based on a provided id. Assumes
+ * that the id is unique, removes only the last instance of that id. Does nothing if
+ * the specified id is not found
+ * @param {Grid} grid the grid on which we are acting
+ * @param {string} id the id we'd like to remove from the menu
+ *
+ */
+ grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToGridMenu
+ * @propertyOf ui.grid.gridMenuService
+ * @description add items to the grid menu. Used by features
+ * to add their menu items if they are enabled, can also be used by
+ * end users to add menu items. This method has the advantage of allowing
+ * remove again, which can simplify management of which items are included
+ * in the menu when. (Noting that in most cases the shown and active functions
+ * provide a better way to handle visibility of menu items)
+ * @param {Grid} grid the grid on which we are acting
+ * @param {array} items menu items in the format as described in the tutorial, with
+ * the added note that if you want to use remove you must also specify an `id` field,
+ * which is provided when you want to remove an item. The id should be unique.
+ *
+ */
+ addToGridMenu: function( grid, menuItems ) {
+ if ( !angular.isArray( menuItems ) ) {
+ gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');
+ } else {
+ if ( grid.gridMenuScope ){
+ grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];
+ grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );
+ } else {
+ gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid');
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name removeFromGridMenu
+ * @methodOf ui.grid.gridMenuService
+ * @description Remove an item from the grid menu based on a provided id. Assumes
+ * that the id is unique, removes only the last instance of that id. Does nothing if
+ * the specified id is not found. If there is no gridMenuScope or registeredMenuItems
+ * then do nothing silently - the desired result is those menu items not be present and they
+ * aren't.
+ * @param {Grid} grid the grid on which we are acting
+ * @param {string} id the id we'd like to remove from the menu
+ *
+ */
+ removeFromGridMenu: function( grid, id ){
+ var foundIndex = -1;
+
+ if ( grid && grid.gridMenuScope ){
+ grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {
+ if ( value.id === id ){
+ if (foundIndex > -1) {
+ gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );
+ } else {
+
+ foundIndex = index;
+ }
+ }
+ });
+ }
+
+ if ( foundIndex > -1 ){
+ grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );
+ }
+ },
+
+
+ /**
+ * @ngdoc array
+ * @name gridMenuCustomItems
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) An array of menu items that should be added to
+ * the gridMenu. Follow the format documented in the tutorial for column
+ * menu customisation. The context provided to the action function will
+ * include context.grid. An alternative if working with dynamic menus is to use the
+ * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles
+ * some of the management of items for you.
+ *
+ */
+ /**
+ * @ngdoc boolean
+ * @name gridMenuShowHideColumns
+ * @propertyOf ui.grid.class:GridOptions
+ * @description true by default, whether the grid menu should allow hide/show
+ * of columns
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name getMenuItems
+ * @description Decides the menu items to show in the menu. This is a
+ * combination of:
+ *
+ * - the default menu items that are always included,
+ * - any menu items that have been provided through the addMenuItem api. These
+ * are typically added by features within the grid
+ * - any menu items included in grid.options.gridMenuCustomItems. These can be
+ * changed dynamically, as they're always recalculated whenever we show the
+ * menu
+ * @param {$scope} $scope the scope of this gridMenu, from which we can find all
+ * the information that we need
+ * @returns {array} an array of menu items that can be shown
+ */
+ getMenuItems: function( $scope ) {
+ var menuItems = [
+ // this is where we add any menu items we want to always include
+ ];
+
+ if ( $scope.grid.options.gridMenuCustomItems ){
+ if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){
+ gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');
+ } else {
+ menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );
+ }
+ }
+
+ var clearFilters = [{
+ title: i18nService.getSafeText('gridMenu.clearAllFilters'),
+ action: function ($event) {
+ $scope.grid.clearAllFilters();
+ },
+ shown: function() {
+ return $scope.grid.options.enableFiltering;
+ },
+ order: 100
+ }];
+ menuItems = menuItems.concat( clearFilters );
+
+ menuItems = menuItems.concat( $scope.registeredMenuItems );
+
+ if ( $scope.grid.options.gridMenuShowHideColumns !== false ){
+ menuItems = menuItems.concat( service.showHideColumns( $scope ) );
+ }
+
+ menuItems.sort(function(a, b){
+ return a.order - b.order;
+ });
+
+ return menuItems;
+ },
+
+
+ /**
+ * @ngdoc array
+ * @name gridMenuTitleFilter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) A function that takes a title string
+ * (usually the col.displayName), and converts it into a display value. The function
+ * must return either a string or a promise.
+ *
+ * Used for internationalization of the grid menu column names - for angular-translate
+ * you can pass $translate as the function, for i18nService you can pass getSafeText as the
+ * function
+ * @example
+ * <pre>
+ * gridOptions = {
+ * gridMenuTitleFilter: $translate
+ * }
+ * </pre>
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name showHideColumns
+ * @description Adds two menu items for each of the columns in columnDefs. One
+ * menu item for hide, one menu item for show. Each is visible when appropriate
+ * (show when column is not visible, hide when column is visible). Each toggles
+ * the visible property on the columnDef using toggleColumnVisibility
+ * @param {$scope} $scope of a gridMenu, which contains a reference to the grid
+ */
+ showHideColumns: function( $scope ){
+ var showHideColumns = [];
+ if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {
+ return showHideColumns;
+ }
+
+ // add header for columns
+ showHideColumns.push({
+ title: i18nService.getSafeText('gridMenu.columns'),
+ order: 300
+ });
+
+ $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };
+
+ $scope.grid.options.columnDefs.forEach( function( colDef, index ){
+ if ( colDef.enableHiding !== false ){
+ // add hide menu item - shows an OK icon as we only show when column is already visible
+ var menuItem = {
+ icon: 'ui-grid-icon-ok',
+ action: function($event) {
+ $event.stopPropagation();
+ service.toggleColumnVisibility( this.context.gridCol );
+ },
+ shown: function() {
+ return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;
+ },
+ context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
+ leaveOpen: true,
+ order: 301 + index * 2
+ };
+ service.setMenuItemTitle( menuItem, colDef, $scope.grid );
+ showHideColumns.push( menuItem );
+
+ // add show menu item - shows no icon as we only show when column is invisible
+ menuItem = {
+ icon: 'ui-grid-icon-cancel',
+ action: function($event) {
+ $event.stopPropagation();
+ service.toggleColumnVisibility( this.context.gridCol );
+ },
+ shown: function() {
+ return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);
+ },
+ context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
+ leaveOpen: true,
+ order: 301 + index * 2 + 1
+ };
+ service.setMenuItemTitle( menuItem, colDef, $scope.grid );
+ showHideColumns.push( menuItem );
+ }
+ });
+ return showHideColumns;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name setMenuItemTitle
+ * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu
+ * item if it returns a string, otherwise waiting for the promise to resolve or reject then
+ * putting the result into the title
+ * @param {object} menuItem the menuItem we want to put the title on
+ * @param {object} colDef the colDef from which we can get displayName, name or field
+ * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter
+ *
+ */
+ setMenuItemTitle: function( menuItem, colDef, grid ){
+ var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );
+
+ if ( typeof(title) === 'string' ){
+ menuItem.title = title;
+ } else if ( title.then ){
+ // must be a promise
+ menuItem.title = "";
+ title.then( function( successValue ) {
+ menuItem.title = successValue;
+ }, function( errorValue ) {
+ menuItem.title = errorValue;
+ });
+ } else {
+ gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');
+ menuItem.title = 'badconfig';
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name toggleColumnVisibility
+ * @description Toggles the visibility of an individual column. Expects to be
+ * provided a context that has on it a gridColumn, which is the column that
+ * we'll operate upon. We change the visibility, and refresh the grid as appropriate
+ * @param {GridCol} gridCol the column that we want to toggle
+ *
+ */
+ toggleColumnVisibility: function( gridCol ) {
+ gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );
+
+ gridCol.grid.refresh();
+ gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );
+ }
+ };
+
+ return service;
+}])
+
+
+
+.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',
+function (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {
+
+ return {
+ priority: 0,
+ scope: true,
+ require: ['^uiGrid'],
+ templateUrl: 'ui-grid/ui-grid-menu-button',
+ replace: true,
+
+ link: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+
+ // For the aria label
+ $scope.i18n = {
+ aria: i18nService.getSafeText('gridMenu.aria')
+ };
+
+ uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
+
+ $scope.shown = false;
+
+ $scope.toggleMenu = function () {
+ if ( $scope.shown ){
+ $scope.$broadcast('hide-menu');
+ $scope.shown = false;
+ } else {
+ $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
+ $scope.$broadcast('show-menu');
+ $scope.shown = true;
+ }
+ };
+
+ $scope.$on('menu-hidden', function() {
+ $scope.shown = false;
+ gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
+ });
+ }
+ };
+
+}]);
+
+})();
+
+(function(){
+
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridMenu
+ * @element style
+ * @restrict A
+ *
+ * @description
+ * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div ui-grid-menu shown="true" ></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ </doc:scenario>
+ </doc:example>
+ */
+angular.module('ui.grid')
+
+.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',
+function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {
+ var uiGridMenu = {
+ priority: 0,
+ scope: {
+ // shown: '&',
+ menuItems: '=',
+ autoHide: '=?'
+ },
+ require: '?^uiGrid',
+ templateUrl: 'ui-grid/uiGridMenu',
+ replace: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ $scope.dynamicStyles = '';
+ if (uiGridCtrl && uiGridCtrl.grid && uiGridCtrl.grid.options && uiGridCtrl.grid.options.gridMenuTemplate) {
+ var gridMenuTemplate = uiGridCtrl.grid.options.gridMenuTemplate;
+ gridUtil.getTemplate(gridMenuTemplate).then(function (contents) {
+ var template = angular.element(contents);
+ var newElm = $compile(template)($scope);
+ $elm.replaceWith(newElm);
+ });
+ }
+
+ var setupHeightStyle = function(gridHeight) {
+ //menu appears under header row, so substract that height from it's total
+ // additional 20px for general padding
+ var gridMenuMaxHeight = gridHeight - uiGridCtrl.grid.headerHeight - 20;
+ $scope.dynamicStyles = [
+ '.grid' + uiGridCtrl.grid.id + ' .ui-grid-menu-mid {',
+ 'max-height: ' + gridMenuMaxHeight + 'px;',
+ '}'
+ ].join(' ');
+ };
+
+ if (uiGridCtrl) {
+ setupHeightStyle(uiGridCtrl.grid.gridHeight);
+ uiGridCtrl.grid.api.core.on.gridDimensionChanged($scope, function(oldGridHeight, oldGridWidth, newGridHeight, newGridWidth) {
+ setupHeightStyle(newGridHeight);
+ });
+ }
+
+ $scope.i18n = {
+ close: i18nService.getSafeText('columnMenu.close')
+ };
+
+ // *** Show/Hide functions ******
+ $scope.showMenu = function(event, args) {
+ if ( !$scope.shown ){
+
+ /*
+ * In order to animate cleanly we remove the ng-if, wait a digest cycle, then
+ * animate the removal of the ng-hide. We can't successfully (so far as I can tell)
+ * animate removal of the ng-if, as the menu items aren't there yet. And we don't want
+ * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated
+ * on scroll events.
+ *
+ * Note when testing animation that animations don't run on the tutorials. When debugging it looks
+ * like they do, but angular has a default $animate provider that is just a stub, and that's what's
+ * being called. ALso don't be fooled by the fact that your browser has actually loaded the
+ * angular-translate.js, it's not using it. You need to test animations in an external application.
+ */
+ $scope.shown = true;
+
+ $timeout( function() {
+ $scope.shownMid = true;
+ $scope.$emit('menu-shown');
+ });
+ } else if ( !$scope.shownMid ) {
+ // we're probably doing a hide then show, so we don't need to wait for ng-if
+ $scope.shownMid = true;
+ $scope.$emit('menu-shown');
+ }
+
+ var docEventType = 'click';
+ if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {
+ docEventType = args.originalEvent.type;
+ }
+
+ // Turn off an existing document click handler
+ angular.element(document).off('click touchstart', applyHideMenu);
+ $elm.off('keyup', checkKeyUp);
+ $elm.off('keydown', checkKeyDown);
+
+ // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
+ $timeout(function() {
+ angular.element(document).on(docEventType, applyHideMenu);
+ $elm.on('keyup', checkKeyUp);
+ $elm.on('keydown', checkKeyDown);
+
+ });
+ //automatically set the focus to the first button element in the now open menu.
+ gridUtil.focus.bySelector($elm, 'button[type=button]', true);
+ };
+
+
+ $scope.hideMenu = function(event) {
+ if ( $scope.shown ){
+ /*
+ * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
+ * set the ng-if (shown = false) after the animation runs. In theory we can cascade off the
+ * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.
+ *
+ * The user may have clicked on the menu again whilst
+ * we're waiting, so we check that the mid isn't shown before applying the ng-if.
+ */
+ $scope.shownMid = false;
+ $timeout( function() {
+ if ( !$scope.shownMid ){
+ $scope.shown = false;
+ $scope.$emit('menu-hidden');
+ }
+ }, 200);
+ }
+
+ angular.element(document).off('click touchstart', applyHideMenu);
+ $elm.off('keyup', checkKeyUp);
+ $elm.off('keydown', checkKeyDown);
+ };
+
+ $scope.$on('hide-menu', function (event, args) {
+ $scope.hideMenu(event, args);
+ });
+
+ $scope.$on('show-menu', function (event, args) {
+ $scope.showMenu(event, args);
+ });
+
+
+ // *** Auto hide when click elsewhere ******
+ var applyHideMenu = function(){
+ if ($scope.shown) {
+ $scope.$apply(function () {
+ $scope.hideMenu();
+ });
+ }
+ };
+
+ // close menu on ESC and keep tab cyclical
+ var checkKeyUp = function(event) {
+ if (event.keyCode === 27) {
+ $scope.hideMenu();
+ }
+ };
+
+ var checkKeyDown = function(event) {
+ var setFocus = function(elm) {
+ elm.focus();
+ event.preventDefault();
+ return false;
+ };
+ if (event.keyCode === 9) {
+ var firstMenuItem, lastMenuItem;
+ var menuItemButtons = $elm[0].querySelectorAll('button:not(.ng-hide)');
+ if (menuItemButtons.length > 0) {
+ firstMenuItem = menuItemButtons[0];
+ lastMenuItem = menuItemButtons[menuItemButtons.length - 1];
+ if (event.target === lastMenuItem && !event.shiftKey) {
+ setFocus(firstMenuItem);
+ } else if (event.target === firstMenuItem && event.shiftKey) {
+ setFocus(lastMenuItem);
+ }
+ }
+ }
+ };
+
+ if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
+ $scope.autoHide = true;
+ }
+
+ if ($scope.autoHide) {
+ angular.element($window).on('resize', applyHideMenu);
+ }
+
+ $scope.$on('$destroy', function unbindEvents() {
+ angular.element($window).off('resize', applyHideMenu);
+ angular.element(document).off('click touchstart', applyHideMenu);
+ $elm.off('keyup', checkKeyUp);
+ $elm.off('keydown', checkKeyDown);
+ });
+
+ if (uiGridCtrl) {
+ $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));
+ }
+
+ $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));
+ }
+ };
+
+ return uiGridMenu;
+}])
+
+.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {
+ var uiGridMenuItem = {
+ priority: 0,
+ scope: {
+ name: '=',
+ active: '=',
+ action: '=',
+ icon: '=',
+ shown: '=',
+ context: '=',
+ templateUrl: '=',
+ leaveOpen: '=',
+ screenReaderOnly: '='
+ },
+ require: ['?^uiGrid'],
+ templateUrl: 'ui-grid/uiGridMenuItem',
+ replace: false,
+ compile: function() {
+ return {
+ pre: function ($scope, $elm) {
+ if ($scope.templateUrl) {
+ gridUtil.getTemplate($scope.templateUrl)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.replaceWith(newElm);
+ });
+ }
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+
+ // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
+ // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
+ // throw new TypeError("$scope.shown is defined but not a function");
+ // }
+ if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {
+ $scope.shown = function() { return true; };
+ }
+
+ $scope.itemShown = function () {
+ var context = {};
+ if ($scope.context) {
+ context.context = $scope.context;
+ }
+
+ if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
+ context.grid = uiGridCtrl.grid;
+ }
+
+ return $scope.shown.call(context);
+ };
+
+ $scope.itemAction = function($event,title) {
+ $event.stopPropagation();
+
+ if (typeof($scope.action) === 'function') {
+ var context = {};
+
+ if ($scope.context) {
+ context.context = $scope.context;
+ }
+
+ // Add the grid to the function call context if the uiGrid controller is present
+ if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
+ context.grid = uiGridCtrl.grid;
+ }
+
+ $scope.action.call(context, $event, title);
+
+ if ( !$scope.leaveOpen ){
+ $scope.$emit('hide-menu');
+ } else {
+ /*
+ * XXX: Fix after column refactor
+ * Ideally the focus would remain on the item.
+ * However, since there are two menu items that have their 'show' property toggled instead. This is a quick fix.
+ */
+ gridUtil.focus.bySelector(angular.element(gridUtil.closestElm($elm, ".ui-grid-menu-items")), 'button[type=button]', true);
+ }
+ }
+ };
+
+ $scope.i18n = i18nService.get();
+ }
+ };
+ }
+ };
+
+ return uiGridMenuItem;
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.directive:uiGridOneBind
+ * @summary A group of directives that provide a one time bind to a dom element.
+ * @description A group of directives that provide a one time bind to a dom element.
+ * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.
+ * This is done to reduce the number of watchers on the dom.
+ * <br/>
+ * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>
+ * <pre>
+ <div ng-init="imageName = 'myImageDir.jpg'">
+ <img ui-grid-one-bind-src="imageName"></img>
+ </div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="imageName = 'myImageDir.jpg'">
+ <img ui-grid-one-bind-src="imageName" src="myImageDir.jpg"></img>
+ </div>
+ </pre>
+ </br>
+ <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-text="text"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-text="text">Add this text</div>
+ </pre>
+ </br>
+ * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}
+ * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.
+ *
+ */
+ //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js
+ var oneBinders = angular.module('ui.grid');
+ angular.forEach([
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindSrc
+ * @memberof ui.grid.directive:uiGridOneBind
+ * @element img
+ * @restrict A
+ * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the src dom tag.
+ *
+ */
+ {tag: 'Src', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindText
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the text dom tag.
+ */
+ {tag: 'Text', method: 'text'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindHref
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Href', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindClass
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.
+ * this is to prevent the watcher from being removed before the scope is initialized.
+ * @param {Array} uiGridOneBindClass An array of classes to bind to this element.
+ * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Class', method: 'addClass'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindHtml
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Html', method: 'html'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAlt
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Alt', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindStyle
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Style', method: 'css'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindValue
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Value', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindId
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Id', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindIdGrid
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the id dom tag.
+ * <h1>Important Note!</h1>
+ * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring
+ * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.
+ * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.
+ * This is done in order to ensure uniqueness of id tags across the grid.
+ * This is to prevent two grids in the same document having duplicate id tags.
+ */
+ {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindTitle
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Title', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabel
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text" aria-label="Add this text"></div>
+ </pre>
+ */
+ {tag: 'Label', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabelledby
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId" aria-labelledby="gridID32"></div>
+ </pre>
+ */
+ {tag: 'Labelledby', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
+ * grid id to each one.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId"></div>
+ </pre>
+ * Will become ([grid.id] will be replaced by the actual grid id):
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId" aria-labelledby-Grid="[grid.id]-gridID32"></div>
+ </pre>
+ */
+ {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaDescribedby
+ * @element ANY
+ * @restrict A
+ * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId" aria-describedby="gridID32"></div>
+ </pre>
+ */
+ {tag: 'Describedby', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid
+ * @element ANY
+ * @restrict A
+ * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
+ * grid id to each one.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId"></div>
+ </pre>
+ * Will become ([grid.id] will be replaced by the actual grid id):
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId" aria-describedby="[grid.id]-gridID32"></div>
+ </pre>
+ */
+ {tag: 'Describedby', directiveName:'DescribedbyGrid', appendGridId:true, method: 'attr', aria:true}],
+ function(v){
+
+ var baseDirectiveName = 'uiGridOneBind';
+ //If it is an aria tag then append the aria label seperately
+ //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.
+ //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up.
+ var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);
+ oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){
+ return {
+ restrict: 'A',
+ require: ['?uiGrid','?^uiGrid'],
+ link: function(scope, iElement, iAttrs, controllers){
+ /* Appends the grid id to the beginnig of the value. */
+ var appendGridId = function(val){
+ var grid; //Get an instance of the grid if its available
+ //If its available in the scope then we don't need to try to find it elsewhere
+ if (scope.grid) {
+ grid = scope.grid;
+ }
+ //Another possible location to try to find the grid
+ else if (scope.col && scope.col.grid){
+ grid = scope.col.grid;
+ }
+ //Last ditch effort: Search through the provided controllers.
+ else if (!controllers.some( //Go through the controllers till one has the element we need
+ function(controller){
+ if (controller && controller.grid) {
+ grid = controller.grid;
+ return true; //We've found the grid
+ }
+ })){
+ //We tried our best to find it for you
+ gridUtil.logError("["+directiveName+"] A valid grid could not be found to bind id. Are you using this directive " +
+ "within the correct scope? Trying to generate id: [gridID]-" + val);
+ throw new Error("No valid grid could be found");
+ }
+
+ if (grid){
+ var idRegex = new RegExp(grid.id.toString());
+ //If the grid id hasn't been appended already in the template declaration
+ if (!idRegex.test(val)){
+ val = grid.id.toString() + '-' + val;
+ }
+ }
+ return val;
+ };
+
+ // The watch returns a function to remove itself.
+ var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){
+ if (newV){
+ //If we are trying to add an id element then we also apply the grid id if it isn't already there
+ if (v.appendGridId) {
+ var newIdString = null;
+ //Append the id to all of the new ids.
+ angular.forEach( newV.split(' '), function(s){
+ newIdString = (newIdString ? (newIdString + ' ') : '') + appendGridId(s);
+ });
+ newV = newIdString;
+ }
+
+ // Append this newValue to the dom element.
+ switch (v.method) {
+ case 'attr': //The attr method takes two paraams the tag and the value
+ if (v.aria) {
+ //If it is an aria element then append the aria prefix
+ iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);
+ } else {
+ iElement[v.method](v.tag.toLowerCase(),newV);
+ }
+ break;
+ case 'addClass':
+ //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js
+ if (angular.isObject(newV) && !angular.isArray(newV)) {
+ var results = [];
+ var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined
+ angular.forEach(newV, function (value, index) {
+ if (value !== null && typeof(value) !== "undefined"){
+ nonNullFound = true; //A non null value for a key was found so the object must have been initialized
+ if (value) {results.push(index);}
+ }
+ });
+ //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized
+ if (!nonNullFound){
+ return; // If not initialized then the watcher should not be removed yet.
+ }
+ newV = results;
+ }
+
+ if (newV) {
+ iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);
+ } else {
+ return;
+ }
+ break;
+ default:
+ iElement[v.method](newV);
+ break;
+ }
+
+ //Removes the watcher on itself after the bind
+ rmWatcher();
+ }
+ // True ensures that equality is determined using angular.equals instead of ===
+ }, true); //End rm watchers
+ } //End compile function
+ }; //End directive return
+ } // End directive function
+ ]); //End directive
+ }); // End angular foreach
+})();
+
+(function () {
+ 'use strict';
+
+ var module = angular.module('ui.grid');
+
+ module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',
+ function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {
+ return {
+ replace: true,
+ transclude: true,
+ templateUrl: 'ui-grid/uiGridRenderContainer',
+ require: ['^uiGrid', 'uiGridRenderContainer'],
+ scope: {
+ containerId: '=',
+ rowContainerName: '=',
+ colContainerName: '=',
+ bindScrollHorizontal: '=',
+ bindScrollVertical: '=',
+ enableVerticalScrollbar: '=',
+ enableHorizontalScrollbar: '='
+ },
+ controller: 'uiGridRenderContainer as RenderContainer',
+ compile: function () {
+ return {
+ pre: function prelink($scope, $elm, $attrs, controllers) {
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+ var grid = $scope.grid = uiGridCtrl.grid;
+
+ // Verify that the render container for this element exists
+ if (!$scope.rowContainerName) {
+ throw "No row render container name specified";
+ }
+ if (!$scope.colContainerName) {
+ throw "No column render container name specified";
+ }
+
+ if (!grid.renderContainers[$scope.rowContainerName]) {
+ throw "Row render container '" + $scope.rowContainerName + "' is not registered.";
+ }
+ if (!grid.renderContainers[$scope.colContainerName]) {
+ throw "Column render container '" + $scope.colContainerName + "' is not registered.";
+ }
+
+ var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];
+ var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];
+
+ containerCtrl.containerId = $scope.containerId;
+ containerCtrl.rowContainer = rowContainer;
+ containerCtrl.colContainer = colContainer;
+ },
+ post: function postlink($scope, $elm, $attrs, controllers) {
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ var grid = uiGridCtrl.grid;
+ var rowContainer = containerCtrl.rowContainer;
+ var colContainer = containerCtrl.colContainer;
+ var scrollTop = null;
+ var scrollLeft = null;
+
+
+ var renderContainer = grid.renderContainers[$scope.containerId];
+
+ // Put the container name on this element as a class
+ $elm.addClass('ui-grid-render-container-' + $scope.containerId);
+
+ // Scroll the render container viewport when the mousewheel is used
+ gridUtil.on.mousewheel($elm, function (event) {
+ var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);
+ if (event.deltaY !== 0) {
+ var scrollYAmount = event.deltaY * -1 * event.deltaFactor;
+
+ scrollTop = containerCtrl.viewport[0].scrollTop;
+
+ // Get the scroll percentage
+ scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();
+ var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;
+
+ // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length
+ // Viewports that have "overflow: hidden" don't let the mousewheel scroll all the way to the bottom without this check
+ if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {
+ containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;
+ }
+
+ // Keep scrollPercentage within the range 0-1.
+ if (scrollYPercentage < 0) { scrollYPercentage = 0; }
+ else if (scrollYPercentage > 1) { scrollYPercentage = 1; }
+
+ scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };
+ }
+ if (event.deltaX !== 0) {
+ var scrollXAmount = event.deltaX * event.deltaFactor;
+
+ // Get the scroll percentage
+ scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);
+ scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
+ var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;
+
+ // Keep scrollPercentage within the range 0-1.
+ if (scrollXPercentage < 0) { scrollXPercentage = 0; }
+ else if (scrollXPercentage > 1) { scrollXPercentage = 1; }
+
+ scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };
+ }
+
+ // Let the parent container scroll if the grid is already at the top/bottom
+ if ((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||
+ (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft)))) {
+ //parent controller scrolls
+ }
+ else {
+ event.preventDefault();
+ event.stopPropagation();
+ scrollEvent.fireThrottledScrollingEvent('', scrollEvent);
+ }
+
+ });
+
+ $elm.bind('$destroy', function() {
+ $elm.unbind('keydown');
+
+ ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {
+ $elm.unbind(eventName);
+ });
+ });
+
+ // TODO(c0bra): Handle resizing the inner canvas based on the number of elements
+ function update() {
+ var ret = '';
+
+ var canvasWidth = colContainer.canvasWidth;
+ var viewportWidth = colContainer.getViewportWidth();
+
+ var canvasHeight = rowContainer.getCanvasHeight();
+
+ //add additional height for scrollbar on left and right container
+ //if ($scope.containerId !== 'body') {
+ // canvasHeight -= grid.scrollbarHeight;
+ //}
+
+ var viewportHeight = rowContainer.getViewportHeight();
+ //shorten the height to make room for a scrollbar placeholder
+ if (colContainer.needsHScrollbarPlaceholder()) {
+ viewportHeight -= grid.scrollbarHeight;
+ }
+
+ var headerViewportWidth,
+ footerViewportWidth;
+ headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();
+
+ // Set canvas dimensions
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
+
+ if (renderContainer.explicitHeaderCanvasHeight) {
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
+ }
+ else {
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: inherit; }';
+ }
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';
+
+ return ret;
+ }
+
+ uiGridCtrl.grid.registerStyleComputation({
+ priority: 6,
+ func: update
+ });
+ }
+ };
+ }
+ };
+
+ }]);
+
+ module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {
+
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {
+ return {
+ replace: true,
+ // priority: 2001,
+ // templateUrl: 'ui-grid/ui-grid-row',
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: {
+ row: '=uiGridRow',
+ //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it
+ rowRenderIndex: '='
+ },
+ compile: function() {
+ return {
+ pre: function($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ var grid = uiGridCtrl.grid;
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ // Function for attaching the template to this scope
+ var clonedElement, cloneScope;
+ function compileTemplate() {
+ $scope.row.getRowTemplateFn.then(function (compiledElementFn) {
+ // var compiledElementFn = $scope.row.compiledElementFn;
+
+ // Create a new scope for the contents of this row, so we can destroy it later if need be
+ var newScope = $scope.$new();
+
+ compiledElementFn(newScope, function (newElm, scope) {
+ // If we already have a cloned element, we need to remove it and destroy its scope
+ if (clonedElement) {
+ clonedElement.remove();
+ cloneScope.$destroy();
+ }
+
+ // Empty the row and append the new element
+ $elm.empty().append(newElm);
+
+ // Save the new cloned element and scope
+ clonedElement = newElm;
+ cloneScope = newScope;
+ });
+ });
+ }
+
+ // Initially attach the compiled template to this scope
+ compileTemplate();
+
+ // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
+ $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {
+ if (newFunc !== oldFunc) {
+ compileTemplate();
+ }
+ });
+ },
+ post: function($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+// 'use strict';
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridStyle
+ * @element style
+ * @restrict A
+ *
+ * @description
+ * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.myStyle = '.blah { border: 1px solid }';
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <style ui-grid-style>{{ myStyle }}</style>
+ <span class="blah">I am in a box.</span>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ it('should apply the right class to the element', function () {
+ element(by.css('.blah')).getCssValue('border-top-width')
+ .then(function(c) {
+ expect(c).toContain('1px');
+ });
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+
+
+ angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {
+ return {
+ // restrict: 'A',
+ // priority: 1000,
+ // require: '?^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ // gridUtil.logDebug('ui-grid-style link');
+ // if (uiGridCtrl === undefined) {
+ // gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');
+ // }
+
+ var interpolateFn = $interpolate($elm.text(), true);
+
+ if (interpolateFn) {
+ $scope.$watch(interpolateFn, function(value) {
+ $elm.text(value);
+ });
+ }
+
+ // uiGridCtrl.recalcRowStyles = function() {
+ // var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);
+ // var rowHeight = scope.options.rowHeight;
+
+ // var ret = '';
+ // var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);
+ // for (var i = 1; i <= rowStyleCount; i++) {
+ // ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';
+ // offset = offset + rowHeight;
+ // }
+
+ // scope.rowStyles = ret;
+ // };
+
+ // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);
+
+ }
+ };
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants', '$log',
+ function(gridUtil, ScrollEvent, uiGridConstants, $log) {
+ return {
+ replace: true,
+ scope: {},
+ controllerAs: 'Viewport',
+ templateUrl: 'ui-grid/uiGridViewport',
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ link: function($scope, $elm, $attrs, controllers) {
+ // gridUtil.logDebug('viewport post-link');
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.containerCtrl = containerCtrl;
+
+ var rowContainer = containerCtrl.rowContainer;
+ var colContainer = containerCtrl.colContainer;
+
+ var grid = uiGridCtrl.grid;
+
+ $scope.grid = uiGridCtrl.grid;
+
+ // Put the containers in scope so we can get rows and columns from them
+ $scope.rowContainer = containerCtrl.rowContainer;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ // Register this viewport with its container
+ containerCtrl.viewport = $elm;
+
+ /**
+ * @ngdoc function
+ * @name customScroller
+ * @methodOf ui.grid.class:GridOptions
+ * @description (optional) uiGridViewport.on('scroll', scrollHandler) by default.
+ * A function that allows you to provide your own scroller function. It is particularly helpful if you want to use third party scrollers
+ * as this allows you to do that.
+ *
+ * <div class="alert alert-info" role="alert"> <strong>NOTE:</strong> It is important to remember to always pass in an event object to
+ * the scrollHandler as the grid scrolling behavior will break without it.</div>
+ * <h5>Example</h5>
+ * <pre>
+ * $scope.gridOptions = {
+ * customScroller: function myScrolling(uiGridViewport, scrollHandler) {
+ * uiGridViewport.on('scroll', function myScrollingOverride(event) {
+ * // Do something here
+ *
+ * scrollHandler(event);
+ * });
+ * }
+ * };
+ * </pre>
+ * @param {object} uiGridViewport Element being scrolled. (this gets passed in by the grid).
+ * @param {function} scrollHandler Function that needs to be called when scrolling happens. (this gets passed in by the grid).
+ */
+ if (grid && grid.options && grid.options.customScroller) {
+ grid.options.customScroller($elm, scrollHandler);
+ } else {
+ $elm.on('scroll', scrollHandler);
+ }
+
+ var ignoreScroll = false;
+
+ function scrollHandler(evt) {
+ //Leaving in this commented code in case it can someday be used
+ //It does improve performance, but because the horizontal scroll is normalized,
+ // using this code will lead to the column header getting slightly out of line with columns
+ //
+ //if (ignoreScroll && (grid.isScrollingHorizontally || grid.isScrollingHorizontally)) {
+ // //don't ask for scrollTop if we just set it
+ // ignoreScroll = false;
+ // return;
+ //}
+ //ignoreScroll = true;
+
+ var newScrollTop = $elm[0].scrollTop;
+ var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);
+
+ var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
+ var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);
+
+ var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
+ scrollEvent.newScrollLeft = newScrollLeft;
+ scrollEvent.newScrollTop = newScrollTop;
+ if ( horizScrollPercentage > -1 ){
+ scrollEvent.x = { percentage: horizScrollPercentage };
+ }
+
+ if ( vertScrollPercentage > -1 ){
+ scrollEvent.y = { percentage: vertScrollPercentage };
+ }
+
+ grid.scrollContainers($scope.$parent.containerId, scrollEvent);
+ }
+
+ if ($scope.$parent.bindScrollVertical) {
+ grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);
+ }
+
+ if ($scope.$parent.bindScrollHorizontal) {
+ grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);
+ grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);
+ grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);
+ }
+
+ function syncVerticalScroll(scrollEvent){
+ containerCtrl.prevScrollArgs = scrollEvent;
+ var newScrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);
+ $elm[0].scrollTop = newScrollTop;
+
+ }
+
+ function syncHorizontalScroll(scrollEvent){
+ containerCtrl.prevScrollArgs = scrollEvent;
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ $elm[0].scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+
+ function syncHorizontalHeader(scrollEvent){
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ if (containerCtrl.headerViewport) {
+ containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+ }
+
+ function syncHorizontalFooter(scrollEvent){
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ if (containerCtrl.footerViewport) {
+ containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+ }
+
+ $scope.$on('$destroy', function unbindEvents() {
+ $elm.off();
+ });
+ },
+ controller: ['$scope', function ($scope) {
+ this.rowStyle = function (index) {
+ var rowContainer = $scope.rowContainer;
+ var colContainer = $scope.colContainer;
+
+ var styles = {};
+
+ if (rowContainer.currentTopRow !== 0){
+ //top offset based on hidden rows count
+ var translateY = "translateY("+ (rowContainer.currentTopRow * rowContainer.grid.options.rowHeight) +"px)";
+ styles['transform'] = translateY;
+ styles['-webkit-transform'] = translateY;
+ styles['-ms-transform'] = translateY;
+ }
+
+ if (colContainer.currentFirstColumn !== 0) {
+ if (colContainer.grid.isRTL()) {
+ styles['margin-right'] = colContainer.columnOffset + 'px';
+ }
+ else {
+ styles['margin-left'] = colContainer.columnOffset + 'px';
+ }
+ }
+
+ return styles;
+ };
+ }]
+ };
+ }
+ ]);
+
+})();
+
+(function() {
+
+angular.module('ui.grid')
+.directive('uiGridVisible', function uiGridVisibleAction() {
+ return function ($scope, $elm, $attr) {
+ $scope.$watch($attr.uiGridVisible, function (visible) {
+ // $elm.css('visibility', visible ? 'visible' : 'hidden');
+ $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');
+ });
+ };
+});
+
+})();
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',
+ '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile',
+ function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,
+ $templateCache, gridClassFactory, $timeout, $parse, $compile) {
+ // gridUtil.logDebug('ui-grid controller');
+
+ var self = this;
+
+ self.grid = gridClassFactory.createGrid($scope.uiGrid);
+
+ //assign $scope.$parent if appScope not already assigned
+ self.grid.appScope = self.grid.appScope || $scope.$parent;
+
+ $elm.addClass('grid' + self.grid.id);
+ self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';
+
+
+ // angular.extend(self.grid.options, );
+
+ //all properties of grid are available on scope
+ $scope.grid = self.grid;
+
+ if ($attrs.uiGridColumns) {
+ $attrs.$observe('uiGridColumns', function(value) {
+ self.grid.options.columnDefs = value;
+ self.grid.buildColumns()
+ .then(function(){
+ self.grid.preCompileCellTemplates();
+
+ self.grid.refreshCanvas(true);
+ });
+ });
+ }
+
+
+ // if fastWatch is set we watch only the length and the reference, not every individual object
+ var deregFunctions = [];
+ if (self.grid.options.fastWatch) {
+ self.uiGrid = $scope.uiGrid;
+ if (angular.isString($scope.uiGrid.data)) {
+ deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() {
+ if ( self.grid.appScope[$scope.uiGrid.data] ){
+ return self.grid.appScope[$scope.uiGrid.data].length;
+ } else {
+ return undefined;
+ }
+ }, dataWatchFunction) );
+ } else {
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data.length; }, function(){ dataWatchFunction($scope.uiGrid.data); }) );
+ }
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs.length; }, function(){ columnDefsWatchFunction($scope.uiGrid.columnDefs); }) );
+ } else {
+ if (angular.isString($scope.uiGrid.data)) {
+ deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );
+ } else {
+ deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
+ }
+ deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
+ }
+
+
+ function columnDefsWatchFunction(n, o) {
+ if (n && n !== o) {
+ self.grid.options.columnDefs = $scope.uiGrid.columnDefs;
+ self.grid.buildColumns({ orderByColumnDefs: true })
+ .then(function(){
+
+ self.grid.preCompileCellTemplates();
+
+ self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);
+ });
+ }
+ }
+
+ var mostRecentData;
+
+ function dataWatchFunction(newData) {
+ // gridUtil.logDebug('dataWatch fired');
+ var promises = [];
+
+ if ( self.grid.options.fastWatch ){
+ if (angular.isString($scope.uiGrid.data)) {
+ newData = self.grid.appScope[$scope.uiGrid.data];
+ } else {
+ newData = $scope.uiGrid.data;
+ }
+ }
+
+ mostRecentData = newData;
+
+ if (newData) {
+ // columns length is greater than the number of row header columns, which don't count because they're created automatically
+ var hasColumns = self.grid.columns.length > (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0);
+
+ if (
+ // If we have no columns
+ !hasColumns &&
+ // ... and we don't have a ui-grid-columns attribute, which would define columns for us
+ !$attrs.uiGridColumns &&
+ // ... and we have no pre-defined columns
+ self.grid.options.columnDefs.length === 0 &&
+ // ... but we DO have data
+ newData.length > 0
+ ) {
+ // ... then build the column definitions from the data that we have
+ self.grid.buildColumnDefsFromData(newData);
+ }
+
+ // If we haven't built columns before and either have some columns defined or some data defined
+ if (!hasColumns && (self.grid.options.columnDefs.length > 0 || newData.length > 0)) {
+ // Build the column set, then pre-compile the column cell templates
+ promises.push(self.grid.buildColumns()
+ .then(function() {
+ self.grid.preCompileCellTemplates();
+ }));
+ }
+
+ $q.all(promises).then(function() {
+ // use most recent data, rather than the potentially outdated data passed into watcher handler
+ self.grid.modifyRows(mostRecentData)
+ .then(function () {
+ // if (self.viewport) {
+ self.grid.redrawInPlace(true);
+ // }
+
+ $scope.$evalAsync(function() {
+ self.grid.refreshCanvas(true);
+ self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);
+ });
+ });
+ });
+ }
+ }
+
+ var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {
+ self.grid.refreshCanvas(true);
+ });
+
+ $scope.$on('$destroy', function() {
+ deregFunctions.forEach( function( deregFn ){ deregFn(); });
+ styleWatchDereg();
+ });
+
+ self.fireEvent = function(eventName, args) {
+ // Add the grid to the event arguments if it's not there
+ if (typeof(args) === 'undefined' || args === undefined) {
+ args = {};
+ }
+
+ if (typeof(args.grid) === 'undefined' || args.grid === undefined) {
+ args.grid = self.grid;
+ }
+
+ $scope.$broadcast(eventName, args);
+ };
+
+ self.innerCompile = function innerCompile(elm) {
+ $compile(elm)($scope);
+ };
+
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGrid
+ * @element div
+ * @restrict EA
+ * @param {Object} uiGrid Options for the grid to use
+ *
+ * @description Create a very basic grid.
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data }"></div>
+ </div>
+ </file>
+ </example>
+ */
+angular.module('ui.grid').directive('uiGrid', uiGridDirective);
+
+uiGridDirective.$inject = ['$compile', '$templateCache', '$timeout', '$window', 'gridUtil', 'uiGridConstants'];
+function uiGridDirective($compile, $templateCache, $timeout, $window, gridUtil, uiGridConstants) {
+ return {
+ templateUrl: 'ui-grid/ui-grid',
+ scope: {
+ uiGrid: '='
+ },
+ replace: true,
+ transclude: true,
+ controller: 'uiGridController',
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var grid = uiGridCtrl.grid;
+ // Initialize scrollbars (TODO: move to controller??)
+ uiGridCtrl.scrollbars = [];
+ grid.element = $elm;
+
+
+ // See if the grid has a rendered width, if not, wait a bit and try again
+ var sizeCheckInterval = 100; // ms
+ var maxSizeChecks = 20; // 2 seconds total
+ var sizeChecks = 0;
+
+ // Setup (event listeners) the grid
+ setup();
+
+ // And initialize it
+ init();
+
+ // Mark rendering complete so API events can happen
+ grid.renderingComplete();
+
+ // If the grid doesn't have size currently, wait for a bit to see if it gets size
+ checkSize();
+
+ /*-- Methods --*/
+
+ function checkSize() {
+ // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds
+ if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {
+ setTimeout(checkSize, sizeCheckInterval);
+ sizeChecks++;
+ }
+ else {
+ $timeout(init);
+ }
+ }
+
+ // Setup event listeners and watchers
+ function setup() {
+ // Bind to window resize events
+ angular.element($window).on('resize', gridResize);
+
+ // Unbind from window resize events when the grid is destroyed
+ $elm.on('$destroy', function () {
+ angular.element($window).off('resize', gridResize);
+ });
+
+ // If we add a left container after render, we need to watch and react
+ $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {
+ if (newValue === oldValue) {
+ return;
+ }
+ grid.refreshCanvas(true);
+ });
+
+ // If we add a right container after render, we need to watch and react
+ $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {
+ if (newValue === oldValue) {
+ return;
+ }
+ grid.refreshCanvas(true);
+ });
+ }
+
+ // Initialize the directive
+ function init() {
+ grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
+
+ // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from
+ grid.canvasWidth = uiGridCtrl.grid.gridWidth;
+
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+
+ // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows
+ if (grid.gridHeight <= grid.options.rowHeight && grid.options.enableMinHeightCheck) {
+ autoAdjustHeight();
+ }
+
+ // Run initial canvas refresh
+ grid.refreshCanvas(true);
+ }
+
+ // Set the grid's height ourselves in the case that its height would be unusably small
+ function autoAdjustHeight() {
+ // Figure out the new height
+ var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;
+ var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;
+ var footerHeight = grid.calcFooterHeight();
+
+ var scrollbarHeight = 0;
+ if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ scrollbarHeight = gridUtil.getScrollbarWidth();
+ }
+
+ var maxNumberOfFilters = 0;
+ // Calculates the maximum number of filters in the columns
+ angular.forEach(grid.options.columnDefs, function(col) {
+ if (col.hasOwnProperty('filter')) {
+ if (maxNumberOfFilters < 1) {
+ maxNumberOfFilters = 1;
+ }
+ }
+ else if (col.hasOwnProperty('filters')) {
+ if (maxNumberOfFilters < col.filters.length) {
+ maxNumberOfFilters = col.filters.length;
+ }
+ }
+ });
+
+ if (grid.options.enableFiltering && !maxNumberOfFilters) {
+ var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.length && grid.options.columnDefs.every(function(col) {
+ return col.enableFiltering === false;
+ });
+
+ if (!allColumnsHaveFilteringTurnedOff) {
+ maxNumberOfFilters = 1;
+ }
+ }
+
+ var filterHeight = maxNumberOfFilters * headerHeight;
+
+ var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;
+
+ $elm.css('height', newHeight + 'px');
+
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+ }
+
+ // Resize the grid on window resize events
+ function gridResize($event) {
+ grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+
+ grid.refreshCanvas(true);
+ }
+ }
+ };
+ }
+ };
+}
+
+})();
+
+(function(){
+ 'use strict';
+
+ // TODO: rename this file to ui-grid-pinned-container.js
+
+ angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ template: '<div class="ui-grid-pinned-container"><div ui-grid-render-container container-id="side" row-container-name="\'body\'" col-container-name="side" bind-scroll-vertical="true" class="{{ side }} ui-grid-render-container-{{ side }}"></div></div>',
+ scope: {
+ side: '=uiGridPinnedContainer'
+ },
+ require: '^uiGrid',
+ compile: function compile() {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');
+
+ var grid = uiGridCtrl.grid;
+
+ var myWidth = 0;
+
+ $elm.addClass('ui-grid-pinned-container-' + $scope.side);
+
+ // Monkey-patch the viewport width function
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;
+ }
+
+ function monkeyPatchedGetViewportWidth() {
+ /*jshint validthis: true */
+ var self = this;
+
+ var viewportWidth = 0;
+ self.visibleColumnCache.forEach(function (column) {
+ viewportWidth += column.drawnWidth;
+ });
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewportWidth = viewportWidth + adjustment.width;
+
+ return viewportWidth;
+ }
+
+ function updateContainerWidth() {
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ var cols = grid.renderContainers[$scope.side].visibleColumnCache;
+ var width = 0;
+ for (var i = 0; i < cols.length; i++) {
+ var col = cols[i];
+ width += col.drawnWidth || col.width || 0;
+ }
+
+ return width;
+ }
+ }
+
+ function updateContainerDimensions() {
+ var ret = '';
+
+ // Column containers
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ myWidth = updateContainerWidth();
+
+ // gridUtil.logDebug('myWidth', myWidth);
+
+ // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it
+ $elm.attr('style', null);
+
+ // var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;
+
+ ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';
+ }
+
+ return ret;
+ }
+
+ grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
+ myWidth = updateContainerWidth();
+
+ // Subtract our own width
+ adjustment.width -= myWidth;
+ adjustment.side = $scope.side;
+
+ return adjustment;
+ });
+
+ // Register style computation to adjust for columns in `side`'s render container
+ grid.registerStyleComputation({
+ priority: 15,
+ func: updateContainerDimensions
+ });
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',
+ function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.core.api:PublicApi
+ * @description Public Api for the core grid features
+ *
+ */
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:Grid
+ * @description Grid is the main viewModel. Any properties or methods needed to maintain state are defined in
+ * this prototype. One instance of Grid is created per Grid directive instance.
+ * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.
+ */
+ var Grid = function Grid(options) {
+ var self = this;
+ // Get the id out of the options, then remove it
+ if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {
+ if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {
+ throw new Error("Grid id '" + options.id + '" is invalid. It must follow CSS selector syntax rules.');
+ }
+ }
+ else {
+ throw new Error('No ID provided. An ID must be given when creating a grid.');
+ }
+
+ self.id = options.id;
+ delete options.id;
+
+ // Get default options
+ self.options = GridOptions.initialize( options );
+
+ /**
+ * @ngdoc object
+ * @name appScope
+ * @propertyOf ui.grid.class:Grid
+ * @description reference to the application scope (the parent scope of the ui-grid element). Assigned in ui-grid controller
+ * <br/>
+ * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference
+ */
+ self.appScope = self.options.appScopeProvider;
+
+ self.headerHeight = self.options.headerRowHeight;
+
+
+ /**
+ * @ngdoc object
+ * @name footerHeight
+ * @propertyOf ui.grid.class:Grid
+ * @description returns the total footer height gridFooter + columnFooter
+ */
+ self.footerHeight = self.calcFooterHeight();
+
+
+ /**
+ * @ngdoc object
+ * @name columnFooterHeight
+ * @propertyOf ui.grid.class:Grid
+ * @description returns the total column footer height
+ */
+ self.columnFooterHeight = self.calcColumnFooterHeight();
+
+ self.rtl = false;
+ self.gridHeight = 0;
+ self.gridWidth = 0;
+ self.columnBuilders = [];
+ self.rowBuilders = [];
+ self.rowsProcessors = [];
+ self.columnsProcessors = [];
+ self.styleComputations = [];
+ self.viewportAdjusters = [];
+ self.rowHeaderColumns = [];
+ self.dataChangeCallbacks = {};
+ self.verticalScrollSyncCallBackFns = {};
+ self.horizontalScrollSyncCallBackFns = {};
+
+ // self.visibleRowCache = [];
+
+ // Set of 'render' containers for self grid, which can render sets of rows
+ self.renderContainers = {};
+
+ // Create a
+ self.renderContainers.body = new GridRenderContainer('body', self);
+
+ self.cellValueGetterCache = {};
+
+ // Cached function to use with custom row templates
+ self.getRowTemplateFn = null;
+
+
+ //representation of the rows on the grid.
+ //these are wrapped references to the actual data rows (options.data)
+ self.rows = [];
+
+ //represents the columns on the grid
+ self.columns = [];
+
+ /**
+ * @ngdoc boolean
+ * @name isScrollingVertically
+ * @propertyOf ui.grid.class:Grid
+ * @description set to true when Grid is scrolling vertically. Set to false via debounced method
+ */
+ self.isScrollingVertically = false;
+
+ /**
+ * @ngdoc boolean
+ * @name isScrollingHorizontally
+ * @propertyOf ui.grid.class:Grid
+ * @description set to true when Grid is scrolling horizontally. Set to false via debounced method
+ */
+ self.isScrollingHorizontally = false;
+
+ /**
+ * @ngdoc property
+ * @name scrollDirection
+ * @propertyOf ui.grid.class:Grid
+ * @description set one of the {@link ui.grid.service:uiGridConstants#properties_scrollDirection uiGridConstants.scrollDirection}
+ * values (UP, DOWN, LEFT, RIGHT, NONE), which tells us which direction we are scrolling.
+ * Set to NONE via debounced method
+ */
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+
+ //if true, grid will not respond to any scroll events
+ self.disableScrolling = false;
+
+
+ function vertical (scrollEvent) {
+ self.isScrollingVertically = false;
+ self.api.core.raise.scrollEnd(scrollEvent);
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+ }
+
+ var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);
+ var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);
+
+ function horizontal (scrollEvent) {
+ self.isScrollingHorizontally = false;
+ self.api.core.raise.scrollEnd(scrollEvent);
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+ }
+
+ var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);
+ var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);
+
+
+ /**
+ * @ngdoc function
+ * @name flagScrollingVertically
+ * @methodOf ui.grid.class:Grid
+ * @description sets isScrollingVertically to true and sets it to false in a debounced function
+ */
+ self.flagScrollingVertically = function(scrollEvent) {
+ if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
+ self.api.core.raise.scrollBegin(scrollEvent);
+ }
+ self.isScrollingVertically = true;
+ if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
+ debouncedVerticalMinDelay(scrollEvent);
+ }
+ else {
+ debouncedVertical(scrollEvent);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name flagScrollingHorizontally
+ * @methodOf ui.grid.class:Grid
+ * @description sets isScrollingHorizontally to true and sets it to false in a debounced function
+ */
+ self.flagScrollingHorizontally = function(scrollEvent) {
+ if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
+ self.api.core.raise.scrollBegin(scrollEvent);
+ }
+ self.isScrollingHorizontally = true;
+ if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
+ debouncedHorizontalMinDelay(scrollEvent);
+ }
+ else {
+ debouncedHorizontal(scrollEvent);
+ }
+ };
+
+ self.scrollbarHeight = 0;
+ self.scrollbarWidth = 0;
+ if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ self.scrollbarHeight = gridUtil.getScrollbarWidth();
+ }
+
+ if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ self.scrollbarWidth = gridUtil.getScrollbarWidth();
+ }
+
+
+
+ self.api = new GridApi(self);
+
+ /**
+ * @ngdoc function
+ * @name refresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Refresh the rendered grid on screen.
+ * The refresh method re-runs both the columnProcessors and the
+ * rowProcessors, as well as calling refreshCanvas to update all
+ * the grid sizing. In general you should prefer to use queueGridRefresh
+ * instead, which is basically a debounced version of refresh.
+ *
+ * If you only want to resize the grid, not regenerate all the rows
+ * and columns, you should consider directly calling refreshCanvas instead.
+ *
+ * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed
+ */
+ self.api.registerMethod( 'core', 'refresh', this.refresh );
+
+ /**
+ * @ngdoc function
+ * @name queueGridRefresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Request a refresh of the rendered grid on screen, if multiple
+ * calls to queueGridRefresh are made within a digest cycle only one will execute.
+ * The refresh method re-runs both the columnProcessors and the
+ * rowProcessors, as well as calling refreshCanvas to update all
+ * the grid sizing. In general you should prefer to use queueGridRefresh
+ * instead, which is basically a debounced version of refresh.
+ *
+ */
+ self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );
+
+ /**
+ * @ngdoc function
+ * @name refreshRows
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Runs only the rowProcessors, columns remain as they were.
+ * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );
+
+ /**
+ * @ngdoc function
+ * @name queueRefresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Requests execution of refreshCanvas, if multiple requests are made
+ * during a digest cycle only one will run. RefreshCanvas updates the grid sizing.
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );
+
+ /**
+ * @ngdoc function
+ * @name handleWindowResize
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Trigger a grid resize, normally this would be picked
+ * up by a watch on window size, but in some circumstances it is necessary
+ * to call this manually
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );
+
+
+ /**
+ * @ngdoc function
+ * @name addRowHeaderColumn
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description adds a row header column to the grid
+ * @param {object} column def
+ * @param {number} order Determines order of header column on grid. Lower order means header
+ * is positioned to the left of higher order headers
+ *
+ */
+ self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );
+
+ /**
+ * @ngdoc function
+ * @name scrollToIfNecessary
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Scrolls the grid to make a certain row and column combo visible,
+ * in the case that it is not completely visible on the screen already.
+ * @param {GridRow} gridRow row to make visible
+ * @param {GridCol} gridCol column to make visible
+ * @returns {promise} a promise that is resolved when scrolling is complete
+ *
+ */
+ self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );
+
+ /**
+ * @ngdoc function
+ * @name scrollTo
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Scroll the grid such that the specified
+ * row and column is in view
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible
+ * @param {object} colDef to make visible
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);} );
+
+ /**
+ * @ngdoc function
+ * @name registerRowsProcessor
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description
+ * Register a "rows processor" function. When the rows are updated,
+ * the grid calls each registered "rows processor", which has a chance
+ * to alter the set of rows (sorting, etc) as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated rows list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
+ *
+ * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,
+ * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ */
+ self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor );
+
+ /**
+ * @ngdoc function
+ * @name registerColumnsProcessor
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description
+ * Register a "columns processor" function. When the columns are updated,
+ * the grid calls each registered "columns processor", which has a chance
+ * to alter the set of columns as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated columns list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
+ *
+ * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ */
+ self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor );
+
+
+
+ /**
+ * @ngdoc function
+ * @name sortHandleNulls
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description A null handling method that can be used when building custom sort
+ * functions
+ * @example
+ * <pre>
+ * mySortFn = function(a, b) {
+ * var nulls = $scope.gridApi.core.sortHandleNulls(a, b);
+ * if ( nulls !== null ){
+ * return nulls;
+ * } else {
+ * // your code for sorting here
+ * };
+ * </pre>
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} null if there were no nulls/undefineds, otherwise returns
+ * a sort value that should be passed back from the sort function
+ *
+ */
+ self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );
+
+
+ /**
+ * @ngdoc function
+ * @name sortChanged
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description The sort criteria on one or more columns has
+ * changed. Provides as parameters the grid and the output of
+ * getColumnSorting, which is an array of gridColumns
+ * that have sorting on them, sorted in priority order.
+ *
+ * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
+ * @param {Function} callBack Will be called when the event is emited. The function passes back the grid and an array of
+ * columns with sorts on them, in priority order.
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.sortChanged( $scope, function(grid, sortColumns){
+ * // do something
+ * });
+ * </pre>
+ */
+ self.api.registerEvent( 'core', 'sortChanged' );
+
+ /**
+ * @ngdoc function
+ * @name columnVisibilityChanged
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description The visibility of a column has changed,
+ * the column itself is passed out as a parameter of the event.
+ *
+ * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
+ * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.columnVisibilityChanged( $scope, function (column) {
+ * // do something
+ * } );
+ * </pre>
+ */
+ self.api.registerEvent( 'core', 'columnVisibilityChanged' );
+
+ /**
+ * @ngdoc method
+ * @name notifyDataChange
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Notify the grid that a data or config change has occurred,
+ * where that change isn't something the grid was otherwise noticing. This
+ * might be particularly relevant where you've changed values within the data
+ * and you'd like cell classes to be re-evaluated, or changed config within
+ * the columnDef and you'd like headerCellClasses to be re-evaluated.
+ * @param {string} type one of the
+ * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
+ * values (ALL, ROW, EDIT, COLUMN), which tells us which refreshes to fire.
+ *
+ */
+ self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );
+
+ /**
+ * @ngdoc method
+ * @name clearAllFilters
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Clears all filters and optionally refreshes the visible rows.
+ * @param {object} refreshRows Defaults to true.
+ * @param {object} clearConditions Defaults to false.
+ * @param {object} clearFlags Defaults to false.
+ * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
+ */
+ self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);
+
+ self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);
+ self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);
+ self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);
+
+ self.registerStyleComputation({
+ priority: 10,
+ func: self.getFooterStyles
+ });
+ };
+
+ Grid.prototype.calcFooterHeight = function () {
+ if (!this.hasFooter()) {
+ return 0;
+ }
+
+ var height = 0;
+ if (this.options.showGridFooter) {
+ height += this.options.gridFooterHeight;
+ }
+
+ height += this.calcColumnFooterHeight();
+
+ return height;
+ };
+
+ Grid.prototype.calcColumnFooterHeight = function () {
+ var height = 0;
+
+ if (this.options.showColumnFooter) {
+ height += this.options.columnFooterHeight;
+ }
+
+ return height;
+ };
+
+ Grid.prototype.getFooterStyles = function () {
+ var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';
+ style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';
+ return style;
+ };
+
+ Grid.prototype.hasFooter = function () {
+ return this.options.showGridFooter || this.options.showColumnFooter;
+ };
+
+ /**
+ * @ngdoc function
+ * @name isRTL
+ * @methodOf ui.grid.class:Grid
+ * @description Returns true if grid is RightToLeft
+ */
+ Grid.prototype.isRTL = function () {
+ return this.rtl;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name registerColumnBuilder
+ * @methodOf ui.grid.class:Grid
+ * @description When the build creates columns from column definitions, the columnbuilders will be called to add
+ * additional properties to the column.
+ * @param {function(colDef, col, gridOptions)} columnBuilder function to be called
+ */
+ Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {
+ this.columnBuilders.push(columnBuilder);
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildColumnDefsFromData
+ * @methodOf ui.grid.class:Grid
+ * @description Populates columnDefs from the provided data
+ * @param {function(colDef, col, gridOptions)} rowBuilder function to be called
+ */
+ Grid.prototype.buildColumnDefsFromData = function (dataRows){
+ this.options.columnDefs = gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerRowBuilder
+ * @methodOf ui.grid.class:Grid
+ * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add
+ * additional properties to the row.
+ * @param {function(row, gridOptions)} rowBuilder function to be called
+ */
+ Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {
+ this.rowBuilders.push(rowBuilder);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name registerDataChangeCallback
+ * @methodOf ui.grid.class:Grid
+ * @description When a data change occurs, the data change callbacks of the specified type
+ * will be called. The rules are:
+ *
+ * - when the data watch fires, that is considered a ROW change (the data watch only notices
+ * added or removed rows)
+ * - when the api is called to inform us of a change, the declared type of that change is used
+ * - when a cell edit completes, the EDIT callbacks are triggered
+ * - when the columnDef watch fires, the COLUMN callbacks are triggered
+ * - when the options watch fires, the OPTIONS callbacks are triggered
+ *
+ * For a given event:
+ * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks
+ * - ROW calls ROW and ALL callbacks
+ * - EDIT calls EDIT and ALL callbacks
+ * - COLUMN calls COLUMN and ALL callbacks
+ * - OPTIONS calls OPTIONS and ALL callbacks
+ *
+ * @param {function(grid)} callback function to be called
+ * @param {array} types the types of data change you want to be informed of. Values from
+ * the {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
+ * values ( ALL, EDIT, ROW, COLUMN, OPTIONS ). Optional and defaults to ALL
+ * @returns {function} deregister function - a function that can be called to deregister this callback
+ */
+ Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {
+ var uid = gridUtil.nextUid();
+ if ( !types ){
+ types = [uiGridConstants.dataChange.ALL];
+ }
+ if ( !Array.isArray(types)){
+ gridUtil.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: " + types );
+ }
+ this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };
+
+ var self = this;
+ var deregisterFunction = function() {
+ delete self.dataChangeCallbacks[uid];
+ };
+ return deregisterFunction;
+ };
+
+ /**
+ * @ngdoc function
+ * @name callDataChangeCallbacks
+ * @methodOf ui.grid.class:Grid
+ * @description Calls the callbacks based on the type of data change that
+ * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the
+ * event type is matching, or if the type is ALL.
+ * @param {string} type the type of event that occurred - one of the
+ * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
+ * values (ALL, ROW, EDIT, COLUMN, OPTIONS)
+ */
+ Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {
+ angular.forEach( this.dataChangeCallbacks, function( callback, uid ){
+ if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||
+ callback.types.indexOf( type ) !== -1 ||
+ type === uiGridConstants.dataChange.ALL ) {
+ if (callback._this) {
+ callback.callback.apply(callback._this,this);
+ }
+ else {
+ callback.callback( this );
+ }
+ }
+ }, this);
+ };
+
+ /**
+ * @ngdoc function
+ * @name notifyDataChange
+ * @methodOf ui.grid.class:Grid
+ * @description Notifies us that a data change has occurred, used in the public
+ * api for users to tell us when they've changed data or some other event that
+ * our watches cannot pick up
+ * @param {string} type the type of event that occurred - one of the
+ * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)
+ */
+ Grid.prototype.notifyDataChange = function notifyDataChange(type) {
+ var constants = uiGridConstants.dataChange;
+ if ( type === constants.ALL ||
+ type === constants.COLUMN ||
+ type === constants.EDIT ||
+ type === constants.ROW ||
+ type === constants.OPTIONS ){
+ this.callDataChangeCallbacks( type );
+ } else {
+ gridUtil.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: " + type);
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name columnRefreshCallback
+ * @methodOf ui.grid.class:Grid
+ * @description refreshes the grid when a column refresh
+ * is notified, which triggers handling of the visible flag.
+ * This is called on uiGridConstants.dataChange.COLUMN, and is
+ * registered as a dataChangeCallback in grid.js
+ * @param {string} name column name
+ */
+ Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){
+ grid.buildColumns();
+ grid.queueGridRefresh();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name processRowsCallback
+ * @methodOf ui.grid.class:Grid
+ * @description calls the row processors, specifically
+ * intended to reset the sorting when an edit is called,
+ * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT
+ * @param {string} name column name
+ */
+ Grid.prototype.processRowsCallback = function processRowsCallback( grid ){
+ grid.queueGridRefresh();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name updateFooterHeightCallback
+ * @methodOf ui.grid.class:Grid
+ * @description recalculates the footer height,
+ * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS
+ * @param {string} name column name
+ */
+ Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ){
+ grid.footerHeight = grid.calcFooterHeight();
+ grid.columnFooterHeight = grid.calcColumnFooterHeight();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColumn
+ * @methodOf ui.grid.class:Grid
+ * @description returns a grid column for the column name
+ * @param {string} name column name
+ */
+ Grid.prototype.getColumn = function getColumn(name) {
+ var columns = this.columns.filter(function (column) {
+ return column.colDef.name === name;
+ });
+ return columns.length > 0 ? columns[0] : null;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getColDef
+ * @methodOf ui.grid.class:Grid
+ * @description returns a grid colDef for the column name
+ * @param {string} name column.field
+ */
+ Grid.prototype.getColDef = function getColDef(name) {
+ var colDefs = this.options.columnDefs.filter(function (colDef) {
+ return colDef.name === name;
+ });
+ return colDefs.length > 0 ? colDefs[0] : null;
+ };
+
+ /**
+ * @ngdoc function
+ * @name assignTypes
+ * @methodOf ui.grid.class:Grid
+ * @description uses the first row of data to assign colDef.type for any types not defined.
+ */
+ /**
+ * @ngdoc property
+ * @name type
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description the type of the column, used in sorting. If not provided then the
+ * grid will guess the type. Add this only if the grid guessing is not to your
+ * satisfaction. One of:
+ * - 'string'
+ * - 'boolean'
+ * - 'number'
+ * - 'date'
+ * - 'object'
+ * - 'numberStr'
+ * Note that if you choose date, your dates should be in a javascript date type
+ *
+ */
+ Grid.prototype.assignTypes = function(){
+ var self = this;
+ self.options.columnDefs.forEach(function (colDef, index) {
+
+ //Assign colDef type if not specified
+ if (!colDef.type) {
+ var col = new GridColumn(colDef, index, self);
+ var firstRow = self.rows.length > 0 ? self.rows[0] : null;
+ if (firstRow) {
+ colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));
+ }
+ else {
+ colDef.type = 'string';
+ }
+ }
+ });
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name isRowHeaderColumn
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if the column is a row Header
+ * @param {object} column column
+ */
+ Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {
+ return this.rowHeaderColumns.indexOf(column) !== -1;
+ };
+
+ /**
+ * @ngdoc function
+ * @name addRowHeaderColumn
+ * @methodOf ui.grid.class:Grid
+ * @description adds a row header column to the grid
+ * @param {object} column def
+ */
+ Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef, order) {
+ var self = this;
+
+ //default order
+ if (order === undefined) {
+ order = 0;
+ }
+
+ var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
+ rowHeaderCol.isRowHeader = true;
+ if (self.isRTL()) {
+ self.createRightContainer();
+ rowHeaderCol.renderContainer = 'right';
+ }
+ else {
+ self.createLeftContainer();
+ rowHeaderCol.renderContainer = 'left';
+ }
+
+ // relies on the default column builder being first in array, as it is instantiated
+ // as part of grid creation
+ self.columnBuilders[0](colDef,rowHeaderCol,self.options)
+ .then(function(){
+ rowHeaderCol.enableFiltering = false;
+ rowHeaderCol.enableSorting = false;
+ rowHeaderCol.enableHiding = false;
+ rowHeaderCol.headerPriority = order;
+ self.rowHeaderColumns.push(rowHeaderCol);
+ self.rowHeaderColumns = self.rowHeaderColumns.sort(function (a, b) {
+ return a.headerPriority - b.headerPriority;
+ });
+
+ self.buildColumns()
+ .then( function() {
+ self.preCompileCellTemplates();
+ self.queueGridRefresh();
+ });
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getOnlyDataColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns all columns except for rowHeader columns
+ */
+ Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {
+ var self = this;
+ var cols = [];
+ self.columns.forEach(function (col) {
+ if (self.rowHeaderColumns.indexOf(col) === -1) {
+ cols.push(col);
+ }
+ });
+ return cols;
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildColumns
+ * @methodOf ui.grid.class:Grid
+ * @description creates GridColumn objects from the columnDefinition. Calls each registered
+ * columnBuilder to further process the column
+ * @param {object} options An object contains options to use when building columns
+ *
+ * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.
+ *
+ * @returns {Promise} a promise to load any needed column resources
+ */
+ Grid.prototype.buildColumns = function buildColumns(opts) {
+ var options = {
+ orderByColumnDefs: false
+ };
+
+ angular.extend(options, opts);
+
+ // gridUtil.logDebug('buildColumns');
+ var self = this;
+ var builderPromises = [];
+ var headerOffset = self.rowHeaderColumns.length;
+ var i;
+
+ // Remove any columns for which a columnDef cannot be found
+ // Deliberately don't use forEach, as it doesn't like splice being called in the middle
+ // Also don't cache columns.length, as it will change during this operation
+ for (i = 0; i < self.columns.length; i++){
+ if (!self.getColDef(self.columns[i].name)) {
+ self.columns.splice(i, 1);
+ i--;
+ }
+ }
+
+ //add row header columns to the grid columns array _after_ columns without columnDefs have been removed
+ //rowHeaderColumns is ordered by priority so insert in reverse
+ for (var j = self.rowHeaderColumns.length - 1; j >= 0; j--) {
+ self.columns.unshift(self.rowHeaderColumns[j]);
+ }
+
+
+
+ // look at each column def, and update column properties to match. If the column def
+ // doesn't have a column, then splice in a new gridCol
+ self.options.columnDefs.forEach(function (colDef, index) {
+ self.preprocessColDef(colDef);
+ var col = self.getColumn(colDef.name);
+
+ if (!col) {
+ col = new GridColumn(colDef, gridUtil.nextUid(), self);
+ self.columns.splice(index + headerOffset, 0, col);
+ }
+ else {
+ // tell updateColumnDef that the column was pre-existing
+ col.updateColumnDef(colDef, false);
+ }
+
+ self.columnBuilders.forEach(function (builder) {
+ builderPromises.push(builder.call(self, colDef, col, self.options));
+ });
+ });
+
+ /*** Reorder columns if necessary ***/
+ if (!!options.orderByColumnDefs) {
+ // Create a shallow copy of the columns as a cache
+ var columnCache = self.columns.slice(0);
+
+ // We need to allow for the "row headers" when mapping from the column defs array to the columns array
+ // If we have a row header in columns[0] and don't account for it we'll overwrite it with the column in columnDefs[0]
+
+ // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then
+ // columns will be shorter than columnDefs. In this situation we'll avoid an error, but the user will still get an unexpected result
+ var len = Math.min(self.options.columnDefs.length, self.columns.length);
+ for (i = 0; i < len; i++) {
+ // If the column at this index has a different name than the column at the same index in the column defs...
+ if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {
+ // Replace the one in the cache with the appropriate column
+ columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);
+ }
+ else {
+ // Otherwise just copy over the one from the initial columns
+ columnCache[i + headerOffset] = self.columns[i + headerOffset];
+ }
+ }
+
+ // Empty out the columns array, non-destructively
+ self.columns.length = 0;
+
+ // And splice in the updated, ordered columns from the cache
+ Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));
+ }
+
+ return $q.all(builderPromises).then(function(){
+ if (self.rows.length > 0){
+ self.assignTypes();
+ }
+ });
+ };
+
+ Grid.prototype.preCompileCellTemplate = function(col) {
+ var self = this;
+ var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));
+ html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var compiledElementFn = $compile(html);
+ col.compiledElementFn = compiledElementFn;
+
+ if (col.compiledElementFnDefer) {
+ col.compiledElementFnDefer.resolve(col.compiledElementFn);
+ }
+ };
+
+/**
+ * @ngdoc function
+ * @name preCompileCellTemplates
+ * @methodOf ui.grid.class:Grid
+ * @description precompiles all cell templates
+ */
+ Grid.prototype.preCompileCellTemplates = function() {
+ var self = this;
+ self.columns.forEach(function (col) {
+ if ( col.cellTemplate ){
+ self.preCompileCellTemplate( col );
+ } else if ( col.cellTemplatePromise ){
+ col.cellTemplatePromise.then( function() {
+ self.preCompileCellTemplate( col );
+ });
+ }
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getGridQualifiedColField
+ * @methodOf ui.grid.class:Grid
+ * @description Returns the $parse-able accessor for a column within its $scope
+ * @param {GridColumn} col col object
+ */
+ Grid.prototype.getQualifiedColField = function (col) {
+ var base = 'row.entity';
+ if ( col.field === uiGridConstants.ENTITY_BINDING ) {
+ return base;
+ }
+ return gridUtil.preEval(base + '.' + col.field);
+ };
+
+ /**
+ * @ngdoc function
+ * @name createLeftContainer
+ * @methodOf ui.grid.class:Grid
+ * @description creates the left render container if it doesn't already exist
+ */
+ Grid.prototype.createLeftContainer = function() {
+ if (!this.hasLeftContainer()) {
+ this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name createRightContainer
+ * @methodOf ui.grid.class:Grid
+ * @description creates the right render container if it doesn't already exist
+ */
+ Grid.prototype.createRightContainer = function() {
+ if (!this.hasRightContainer()) {
+ this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasLeftContainer
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if leftContainer exists
+ */
+ Grid.prototype.hasLeftContainer = function() {
+ return this.renderContainers.left !== undefined;
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasRightContainer
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if rightContainer exists
+ */
+ Grid.prototype.hasRightContainer = function() {
+ return this.renderContainers.right !== undefined;
+ };
+
+
+ /**
+ * undocumented function
+ * @name preprocessColDef
+ * @methodOf ui.grid.class:Grid
+ * @description defaults the name property from field to maintain backwards compatibility with 2.x
+ * validates that name or field is present
+ */
+ Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {
+ var self = this;
+
+ if (!colDef.field && !colDef.name) {
+ throw new Error('colDef.name or colDef.field property is required');
+ }
+
+ //maintain backwards compatibility with 2.x
+ //field was required in 2.x. now name is required
+ if (colDef.name === undefined && colDef.field !== undefined) {
+ // See if the column name already exists:
+ var newName = colDef.field,
+ counter = 2;
+ while (self.getColumn(newName)) {
+ newName = colDef.field + counter.toString();
+ counter++;
+ }
+ colDef.name = newName;
+ }
+ };
+
+ // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters
+ Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {
+ var self = this;
+
+ var t = [];
+ for (var i = 0; i < n.length; i++) {
+ var nV = nAccessor ? n[i][nAccessor] : n[i];
+
+ var found = false;
+ for (var j = 0; j < o.length; j++) {
+ var oV = oAccessor ? o[j][oAccessor] : o[j];
+ if (self.options.rowEquality(nV, oV)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ t.push(nV);
+ }
+ }
+
+ return t;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRow
+ * @methodOf ui.grid.class:Grid
+ * @description returns the GridRow that contains the rowEntity
+ * @param {object} rowEntity the gridOptions.data array element instance
+ * @param {array} lookInRows [optional] the rows to look in - if not provided then
+ * looks in grid.rows
+ */
+ Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {
+ var self = this;
+
+ lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;
+
+ var rows = lookInRows.filter(function (row) {
+ return self.options.rowEquality(row.entity, rowEntity);
+ });
+ return rows.length > 0 ? rows[0] : null;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name modifyRows
+ * @methodOf ui.grid.class:Grid
+ * @description creates or removes GridRow objects from the newRawData array. Calls each registered
+ * rowBuilder to further process the row
+ * @param {array} newRawData Modified set of data
+ *
+ * This method aims to achieve three things:
+ * 1. the resulting rows array is in the same order as the newRawData, we'll call
+ * rowsProcessors immediately after to sort the data anyway
+ * 2. if we have row hashing available, we try to use the rowHash to find the row
+ * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected
+ *
+ * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates
+ * the newRows and newHash
+ *
+ * ```
+ * newRawData.forEach newEntity
+ * if (hashing enabled)
+ * check oldHash for newEntity
+ * else
+ * look for old row directly in oldRows
+ * if !oldRowFound // must be a new row
+ * create newRow
+ * append to the newRows and add to newHash
+ * run the processors
+ * ```
+ *
+ * Rows are identified using the hashKey if configured. If not configured, then rows
+ * are identified using the gridOptions.rowEquality function
+ *
+ * This method is useful when trying to select rows immediately after loading data without
+ * using a $timeout/$interval, e.g.:
+ *
+ * $scope.gridOptions.data = someData;
+ * $scope.gridApi.grid.modifyRows($scope.gridOptions.data);
+ * $scope.gridApi.selection.selectRow($scope.gridOptions.data[0]);
+ *
+ * OR to persist row selection after data update (e.g. rows selected, new data loaded, want
+ * originally selected rows to be re-selected))
+ */
+ Grid.prototype.modifyRows = function modifyRows(newRawData) {
+ var self = this;
+ var oldRows = self.rows.slice(0);
+ var oldRowHash = self.rowHashMap || self.createRowHashMap();
+ self.rowHashMap = self.createRowHashMap();
+ self.rows.length = 0;
+
+ newRawData.forEach( function( newEntity, i ) {
+ var newRow, oldRow;
+
+ if ( self.options.enableRowHashing ){
+ // if hashing is enabled, then this row will be in the hash if we already know about it
+ oldRow = oldRowHash.get( newEntity );
+ } else {
+ // otherwise, manually search the oldRows to see if we can find this row
+ oldRow = self.getRow(newEntity, oldRows);
+ }
+
+ // update newRow to have an entity
+ if ( oldRow ) {
+ newRow = oldRow;
+ newRow.entity = newEntity;
+ }
+
+ // if we didn't find the row, it must be new, so create it
+ if ( !newRow ){
+ newRow = self.processRowBuilders(new GridRow(newEntity, i, self));
+ }
+
+ self.rows.push( newRow );
+ self.rowHashMap.put( newEntity, newRow );
+ });
+
+ self.assignTypes();
+
+ var p1 = $q.when(self.processRowsProcessors(self.rows))
+ .then(function (renderableRows) {
+ return self.setVisibleRows(renderableRows);
+ });
+
+ var p2 = $q.when(self.processColumnsProcessors(self.columns))
+ .then(function (renderableColumns) {
+ return self.setVisibleColumns(renderableColumns);
+ });
+
+ return $q.all([p1, p2]);
+ };
+
+
+ /**
+ * Private Undocumented Method
+ * @name addRows
+ * @methodOf ui.grid.class:Grid
+ * @description adds the newRawData array of rows to the grid and calls all registered
+ * rowBuilders. this keyword will reference the grid
+ */
+ Grid.prototype.addRows = function addRows(newRawData) {
+ var self = this;
+
+ var existingRowCount = self.rows.length;
+ for (var i = 0; i < newRawData.length; i++) {
+ var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));
+
+ if (self.options.enableRowHashing) {
+ var found = self.rowHashMap.get(newRow.entity);
+ if (found) {
+ found.row = newRow;
+ }
+ }
+
+ self.rows.push(newRow);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name processRowBuilders
+ * @methodOf ui.grid.class:Grid
+ * @description processes all RowBuilders for the gridRow
+ * @param {GridRow} gridRow reference to gridRow
+ * @returns {GridRow} the gridRow with all additional behavior added
+ */
+ Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {
+ var self = this;
+
+ self.rowBuilders.forEach(function (builder) {
+ builder.call(self, gridRow, self.options);
+ });
+
+ return gridRow;
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerStyleComputation
+ * @methodOf ui.grid.class:Grid
+ * @description registered a styleComputation function
+ *
+ * If the function returns a value it will be appended into the grid's `<style>` block
+ * @param {function($scope)} styleComputation function
+ */
+ Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {
+ this.styleComputations.push(styleComputationInfo);
+ };
+
+
+ // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...
+ // Grid.prototype.registerRowFilter = function(filter) {
+ // // TODO(c0bra): validate filter?
+
+ // this.rowFilters.push(filter);
+ // };
+
+ // Grid.prototype.removeRowFilter = function(filter) {
+ // var idx = this.rowFilters.indexOf(filter);
+
+ // if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ // this.rowFilters.slice(idx, 1);
+ // }
+ // };
+
+ // Grid.prototype.processRowFilters = function(rows) {
+ // var self = this;
+ // self.rowFilters.forEach(function (filter) {
+ // filter.call(self, rows);
+ // });
+ // };
+
+
+ /**
+ * @ngdoc function
+ * @name registerRowsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @description
+ *
+ * Register a "rows processor" function. When the rows are updated,
+ * the grid calls each registered "rows processor", which has a chance
+ * to alter the set of rows (sorting, etc) as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated rows list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
+ *
+ * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ *
+ */
+ Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {
+ if (!angular.isFunction(processor)) {
+ throw 'Attempt to register non-function rows processor: ' + processor;
+ }
+
+ this.rowsProcessors.push({processor: processor, priority: priority});
+ this.rowsProcessors.sort(function sortByPriority( a, b ){
+ return a.priority - b.priority;
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name removeRowsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @param {function(renderableRows)} rows processor function
+ * @description Remove a registered rows processor
+ */
+ Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {
+ var idx = -1;
+ this.rowsProcessors.forEach(function(rowsProcessor, index){
+ if ( rowsProcessor.processor === processor ){
+ idx = index;
+ }
+ });
+
+ if ( idx !== -1 ) {
+ this.rowsProcessors.splice(idx, 1);
+ }
+ };
+
+ /**
+ * Private Undocumented Method
+ * @name processRowsProcessors
+ * @methodOf ui.grid.class:Grid
+ * @param {Array[GridRow]} The array of "renderable" rows
+ * @param {Array[GridColumn]} The array of columns
+ * @description Run all the registered rows processors on the array of renderable rows
+ */
+ Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {
+ var self = this;
+
+ // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
+ var myRenderableRows = renderableRows.slice(0);
+
+ // Return myRenderableRows with no processing if we have no rows processors
+ if (self.rowsProcessors.length === 0) {
+ return $q.when(myRenderableRows);
+ }
+
+ // Counter for iterating through rows processors
+ var i = 0;
+
+ // Promise for when we're done with all the processors
+ var finished = $q.defer();
+
+ // This function will call the processor in self.rowsProcessors at index 'i', and then
+ // when done will call the next processor in the list, using the output from the processor
+ // at i as the argument for 'renderedRowsToProcess' on the next iteration.
+ //
+ // If we're at the end of the list of processors, we resolve our 'finished' callback with
+ // the result.
+ function startProcessor(i, renderedRowsToProcess) {
+ // Get the processor at 'i'
+ var processor = self.rowsProcessors[i].processor;
+
+ // Call the processor, passing in the rows to process and the current columns
+ // (note: it's wrapped in $q.when() in case the processor does not return a promise)
+ return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )
+ .then(function handleProcessedRows(processedRows) {
+ // Check for errors
+ if (!processedRows) {
+ throw "Processor at index " + i + " did not return a set of renderable rows";
+ }
+
+ if (!angular.isArray(processedRows)) {
+ throw "Processor at index " + i + " did not return an array";
+ }
+
+ // Processor is done, increment the counter
+ i++;
+
+ // If we're not done with the processors, call the next one
+ if (i <= self.rowsProcessors.length - 1) {
+ return startProcessor(i, processedRows);
+ }
+ // We're done! Resolve the 'finished' promise
+ else {
+ finished.resolve(processedRows);
+ }
+ });
+ }
+
+ // Start on the first processor
+ startProcessor(0, myRenderableRows);
+
+ return finished.promise;
+ };
+
+ Grid.prototype.setVisibleRows = function setVisibleRows(rows) {
+ var self = this;
+
+ // Reset all the render container row caches
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ container.canvasHeightShouldUpdate = true;
+
+ if ( typeof(container.visibleRowCache) === 'undefined' ){
+ container.visibleRowCache = [];
+ } else {
+ container.visibleRowCache.length = 0;
+ }
+ }
+
+ // rows.forEach(function (row) {
+ for (var ri = 0; ri < rows.length; ri++) {
+ var row = rows[ri];
+
+ var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';
+
+ // If the row is visible
+ if (row.visible) {
+ self.renderContainers[targetContainer].visibleRowCache.push(row);
+ }
+ }
+ self.api.core.raise.rowsVisibleChanged(this.api);
+ self.api.core.raise.rowsRendered(this.api);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerColumnsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @param {function(renderedColumnsToProcess, rows)} columnProcessor column processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and
+ * which must return an updated renderedColumnsToProcess which can be passed to the next processor
+ * in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
+ *
+ * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ * @description
+
+ Register a "columns processor" function. When the columns are updated,
+ the grid calls each registered "columns processor", which has a chance
+ to alter the set of columns, as long as the count is not modified.
+ */
+ Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {
+ if (!angular.isFunction(processor)) {
+ throw 'Attempt to register non-function rows processor: ' + processor;
+ }
+
+ this.columnsProcessors.push({processor: processor, priority: priority});
+ this.columnsProcessors.sort(function sortByPriority( a, b ){
+ return a.priority - b.priority;
+ });
+ };
+
+ Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {
+ var idx = this.columnsProcessors.indexOf(processor);
+
+ if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ this.columnsProcessors.splice(idx, 1);
+ }
+ };
+
+ Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {
+ var self = this;
+
+ // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
+ var myRenderableColumns = renderableColumns.slice(0);
+
+ // Return myRenderableRows with no processing if we have no rows processors
+ if (self.columnsProcessors.length === 0) {
+ return $q.when(myRenderableColumns);
+ }
+
+ // Counter for iterating through rows processors
+ var i = 0;
+
+ // Promise for when we're done with all the processors
+ var finished = $q.defer();
+
+ // This function will call the processor in self.rowsProcessors at index 'i', and then
+ // when done will call the next processor in the list, using the output from the processor
+ // at i as the argument for 'renderedRowsToProcess' on the next iteration.
+ //
+ // If we're at the end of the list of processors, we resolve our 'finished' callback with
+ // the result.
+ function startProcessor(i, renderedColumnsToProcess) {
+ // Get the processor at 'i'
+ var processor = self.columnsProcessors[i].processor;
+
+ // Call the processor, passing in the rows to process and the current columns
+ // (note: it's wrapped in $q.when() in case the processor does not return a promise)
+ return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )
+ .then(function handleProcessedRows(processedColumns) {
+ // Check for errors
+ if (!processedColumns) {
+ throw "Processor at index " + i + " did not return a set of renderable rows";
+ }
+
+ if (!angular.isArray(processedColumns)) {
+ throw "Processor at index " + i + " did not return an array";
+ }
+
+ // Processor is done, increment the counter
+ i++;
+
+ // If we're not done with the processors, call the next one
+ if (i <= self.columnsProcessors.length - 1) {
+ return startProcessor(i, myRenderableColumns);
+ }
+ // We're done! Resolve the 'finished' promise
+ else {
+ finished.resolve(myRenderableColumns);
+ }
+ });
+ }
+
+ // Start on the first processor
+ startProcessor(0, myRenderableColumns);
+
+ return finished.promise;
+ };
+
+ Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {
+ // gridUtil.logDebug('setVisibleColumns');
+
+ var self = this;
+
+ // Reset all the render container row caches
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ container.visibleColumnCache.length = 0;
+ }
+
+ for (var ci = 0; ci < columns.length; ci++) {
+ var column = columns[ci];
+
+ // If the column is visible
+ if (column.visible) {
+ // If the column has a container specified
+ if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {
+ self.renderContainers[column.renderContainer].visibleColumnCache.push(column);
+ }
+ // If not, put it into the body container
+ else {
+ self.renderContainers.body.visibleColumnCache.push(column);
+ }
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name handleWindowResize
+ * @methodOf ui.grid.class:Grid
+ * @description Triggered when the browser window resizes; automatically resizes the grid
+ * @returns {Promise} A resolved promise once the window resize has completed.
+ */
+ Grid.prototype.handleWindowResize = function handleWindowResize($event) {
+ var self = this;
+
+ self.gridWidth = gridUtil.elementWidth(self.element);
+ self.gridHeight = gridUtil.elementHeight(self.element);
+
+ return self.queueRefresh();
+ };
+
+ /**
+ * @ngdoc function
+ * @name queueRefresh
+ * @methodOf ui.grid.class:Grid
+ * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue
+ */
+ Grid.prototype.queueRefresh = function queueRefresh() {
+ var self = this;
+
+ if (self.refreshCanceller) {
+ $timeout.cancel(self.refreshCanceller);
+ }
+
+ self.refreshCanceller = $timeout(function () {
+ self.refreshCanvas(true);
+ });
+
+ self.refreshCanceller.then(function () {
+ self.refreshCanceller = null;
+ });
+
+ return self.refreshCanceller;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name queueGridRefresh
+ * @methodOf ui.grid.class:Grid
+ * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue
+ */
+ Grid.prototype.queueGridRefresh = function queueGridRefresh() {
+ var self = this;
+
+ if (self.gridRefreshCanceller) {
+ $timeout.cancel(self.gridRefreshCanceller);
+ }
+
+ self.gridRefreshCanceller = $timeout(function () {
+ self.refresh(true);
+ });
+
+ self.gridRefreshCanceller.then(function () {
+ self.gridRefreshCanceller = null;
+ });
+
+ return self.gridRefreshCanceller;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name updateCanvasHeight
+ * @methodOf ui.grid.class:Grid
+ * @description flags all render containers to update their canvas height
+ */
+ Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {
+ var self = this;
+
+ for (var containerId in self.renderContainers) {
+ if (self.renderContainers.hasOwnProperty(containerId)) {
+ var container = self.renderContainers[containerId];
+ container.canvasHeightShouldUpdate = true;
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildStyles
+ * @methodOf ui.grid.class:Grid
+ * @description calls each styleComputation function
+ */
+ // TODO: this used to take $scope, but couldn't see that it was used
+ Grid.prototype.buildStyles = function buildStyles() {
+ // gridUtil.logDebug('buildStyles');
+
+ var self = this;
+
+ self.customStyles = '';
+
+ self.styleComputations
+ .sort(function(a, b) {
+ if (a.priority === null) { return 1; }
+ if (b.priority === null) { return -1; }
+ if (a.priority === null && b.priority === null) { return 0; }
+ return a.priority - b.priority;
+ })
+ .forEach(function (compInfo) {
+ // this used to provide $scope as a second parameter, but I couldn't find any
+ // style builders that used it, so removed it as part of moving to grid from controller
+ var ret = compInfo.func.call(self);
+
+ if (angular.isString(ret)) {
+ self.customStyles += '\n' + ret;
+ }
+ });
+ };
+
+
+ Grid.prototype.minColumnsToRender = function minColumnsToRender() {
+ var self = this;
+ var viewport = this.getViewportWidth();
+
+ var min = 0;
+ var totalWidth = 0;
+ self.columns.forEach(function(col, i) {
+ if (totalWidth < viewport) {
+ totalWidth += col.drawnWidth;
+ min++;
+ }
+ else {
+ var currWidth = 0;
+ for (var j = i; j >= i - min; j--) {
+ currWidth += self.columns[j].drawnWidth;
+ }
+ if (currWidth < viewport) {
+ min++;
+ }
+ }
+ });
+
+ return min;
+ };
+
+ Grid.prototype.getBodyHeight = function getBodyHeight() {
+ // Start with the viewportHeight
+ var bodyHeight = this.getViewportHeight();
+
+ // Add the horizontal scrollbar height if there is one
+ //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
+ // bodyHeight = bodyHeight + this.horizontalScrollbarHeight;
+ //}
+
+ return bodyHeight;
+ };
+
+ // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)
+ // TODO(c0bra): account for footer height
+ Grid.prototype.getViewportHeight = function getViewportHeight() {
+ var self = this;
+
+ var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;
+
+ // Account for native horizontal scrollbar, if present
+ //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
+ // viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;
+ //}
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortHeight = viewPortHeight + adjustment.height;
+
+ //gridUtil.logDebug('viewPortHeight', viewPortHeight);
+
+ return viewPortHeight;
+ };
+
+ Grid.prototype.getViewportWidth = function getViewportWidth() {
+ var self = this;
+
+ var viewPortWidth = this.gridWidth;
+
+ //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;
+ //}
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortWidth = viewPortWidth + adjustment.width;
+
+ //gridUtil.logDebug('getviewPortWidth', viewPortWidth);
+
+ return viewPortWidth;
+ };
+
+ Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
+ var viewPortWidth = this.getViewportWidth();
+
+ //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;
+ //}
+
+ return viewPortWidth;
+ };
+
+ Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {
+ this.verticalScrollSyncCallBackFns[containerId] = callBackFn;
+ };
+
+ Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {
+ this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;
+ };
+
+/**
+ * Scroll needed containers by calling their ScrollSyncs
+ * @param sourceContainerId the containerId that has already set it's top/left.
+ * can be empty string which means all containers need to set top/left
+ * @param scrollEvent
+ */
+ Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {
+
+ if (scrollEvent.y) {
+ //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
+ var verts = ['body','left', 'right'];
+
+ this.flagScrollingVertically(scrollEvent);
+
+ if (sourceContainerId === 'body') {
+ verts = ['left', 'right'];
+ }
+ else if (sourceContainerId === 'left') {
+ verts = ['body', 'right'];
+ }
+ else if (sourceContainerId === 'right') {
+ verts = ['body', 'left'];
+ }
+
+ for (var i = 0; i < verts.length; i++) {
+ var id = verts[i];
+ if (this.verticalScrollSyncCallBackFns[id]) {
+ this.verticalScrollSyncCallBackFns[id](scrollEvent);
+ }
+ }
+
+ }
+
+ if (scrollEvent.x) {
+ //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
+ var horizs = ['body','bodyheader', 'bodyfooter'];
+
+ this.flagScrollingHorizontally(scrollEvent);
+ if (sourceContainerId === 'body') {
+ horizs = ['bodyheader', 'bodyfooter'];
+ }
+
+ for (var j = 0; j < horizs.length; j++) {
+ var idh = horizs[j];
+ if (this.horizontalScrollSyncCallBackFns[idh]) {
+ this.horizontalScrollSyncCallBackFns[idh](scrollEvent);
+ }
+ }
+
+ }
+
+ };
+
+ Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
+ this.viewportAdjusters.push(func);
+ };
+
+ Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {
+ var idx = this.viewportAdjusters.indexOf(func);
+
+ if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ this.viewportAdjusters.splice(idx, 1);
+ }
+ };
+
+ Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {
+ var self = this;
+
+ var adjustment = { height: 0, width: 0 };
+
+ self.viewportAdjusters.forEach(function (func) {
+ adjustment = func.call(this, adjustment);
+ });
+
+ return adjustment;
+ };
+
+ Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {
+ // var count = 0;
+
+ // this.rows.forEach(function (row) {
+ // if (row.visible) {
+ // count++;
+ // }
+ // });
+
+ // return this.visibleRowCache.length;
+ return this.renderContainers.body.visibleRowCache.length;
+ };
+
+ Grid.prototype.getVisibleRows = function getVisibleRows() {
+ return this.renderContainers.body.visibleRowCache;
+ };
+
+ Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {
+ // var count = 0;
+
+ // this.rows.forEach(function (row) {
+ // if (row.visible) {
+ // count++;
+ // }
+ // });
+
+ // return this.visibleRowCache.length;
+ return this.renderContainers.body.visibleColumnCache.length;
+ };
+
+
+ Grid.prototype.searchRows = function searchRows(renderableRows) {
+ return rowSearcher.search(this, renderableRows, this.columns);
+ };
+
+ Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {
+ return rowSorter.sort(this, renderableRows, this.columns);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getCellValue
+ * @methodOf ui.grid.class:Grid
+ * @description Gets the value of a cell for a particular row and column
+ * @param {GridRow} row Row to access
+ * @param {GridColumn} col Column to access
+ */
+ Grid.prototype.getCellValue = function getCellValue(row, col){
+ if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {
+ return row.entity[ '$$' + col.uid].rendered;
+ } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ){
+ return row.entity[col.field];
+ } else {
+ if (!col.cellValueGetterCache) {
+ col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));
+ }
+
+ return col.cellValueGetterCache(row);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name getCellDisplayValue
+ * @methodOf ui.grid.class:Grid
+ * @description Gets the displayed value of a cell after applying any the `cellFilter`
+ * @param {GridRow} row Row to access
+ * @param {GridColumn} col Column to access
+ */
+ Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {
+ if ( !col.cellDisplayGetterCache ) {
+ var custom_filter = col.cellFilter ? " | " + col.cellFilter : "";
+
+ if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {
+ col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);
+ } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {
+ col.cellDisplayGetterCache = $parse(row.entity[col.field] + custom_filter);
+ } else {
+ col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);
+ }
+ }
+
+ return col.cellDisplayGetterCache(row);
+ };
+
+
+ Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {
+ var self = this,
+ p = 0;
+
+ self.columns.forEach(function (col) {
+ if (col.sort && col.sort.priority !== undefined && col.sort.priority >= p) {
+ p = col.sort.priority + 1;
+ }
+ });
+
+ return p;
+ };
+
+ /**
+ * @ngdoc function
+ * @name resetColumnSorting
+ * @methodOf ui.grid.class:Grid
+ * @description Return the columns that the grid is currently being sorted by
+ * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset
+ */
+ Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {
+ var self = this;
+
+ self.columns.forEach(function (col) {
+ if (col !== excludeCol && !col.suppressRemoveSort) {
+ col.sort = {};
+ }
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getColumnSorting
+ * @methodOf ui.grid.class:Grid
+ * @description Return the columns that the grid is currently being sorted by
+ * @returns {Array[GridColumn]} An array of GridColumn objects
+ */
+ Grid.prototype.getColumnSorting = function getColumnSorting() {
+ var self = this;
+
+ var sortedCols = [], myCols;
+
+ // Iterate through all the columns, sorted by priority
+ // Make local copy of column list, because sorting is in-place and we do not want to
+ // change the original sequence of columns
+ myCols = self.columns.slice(0);
+ myCols.sort(rowSorter.prioritySort).forEach(function (col) {
+ if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
+ sortedCols.push(col);
+ }
+ });
+
+ return sortedCols;
+ };
+
+ /**
+ * @ngdoc function
+ * @name sortColumn
+ * @methodOf ui.grid.class:Grid
+ * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.
+ * Emits the sortChanged event whenever the sort criteria are changed.
+ * @param {GridColumn} column Column to set the sorting on
+ * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.
+ * If not provided, the column will iterate through the sort directions
+ * specified in the {@link ui.grid.class:GridOptions.columnDef#sortDirectionCycle sortDirectionCycle} attribute.
+ * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort
+ * by this column only
+ * @returns {Promise} A resolved promise that supplies the column.
+ */
+
+ Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {
+ var self = this,
+ direction = null;
+
+ if (typeof(column) === 'undefined' || !column) {
+ throw new Error('No column parameter provided');
+ }
+
+ // Second argument can either be a direction or whether to add this column to the existing sort.
+ // If it's a boolean, it's an add, otherwise, it's a direction
+ if (typeof(directionOrAdd) === 'boolean') {
+ add = directionOrAdd;
+ }
+ else {
+ direction = directionOrAdd;
+ }
+
+ if (!add) {
+ self.resetColumnSorting(column);
+ column.sort.priority = undefined;
+ // Get the actual priority since there may be columns which have suppressRemoveSort set
+ column.sort.priority = self.getNextColumnSortPriority();
+ }
+ else if (column.sort.priority === undefined){
+ column.sort.priority = self.getNextColumnSortPriority();
+ }
+
+ if (!direction) {
+ // Find the current position in the cycle (or -1).
+ var i = column.sortDirectionCycle.indexOf(column.sort.direction ? column.sort.direction : null);
+ // Proceed to the next position in the cycle (or start at the beginning).
+ i = (i+1) % column.sortDirectionCycle.length;
+ // If suppressRemoveSort is set, and the next position in the cycle would
+ // remove the sort, skip it.
+ if (column.colDef && column.suppressRemoveSort && !column.sortDirectionCycle[i]) {
+ i = (i+1) % column.sortDirectionCycle.length;
+ }
+
+ if (column.sortDirectionCycle[i]) {
+ column.sort.direction = column.sortDirectionCycle[i];
+ } else {
+ removeSortOfColumn(column, self);
+ }
+ }
+ else {
+ column.sort.direction = direction;
+ }
+
+ self.api.core.raise.sortChanged( self, self.getColumnSorting() );
+
+ return $q.when(column);
+ };
+
+ var removeSortOfColumn = function removeSortOfColumn(column, grid) {
+ //Decrease priority for every col where priority is higher than the removed sort's priority.
+ grid.columns.forEach(function (col) {
+ if (col.sort && col.sort.priority !== undefined && col.sort.priority > column.sort.priority) {
+ col.sort.priority -= 1;
+ }
+ });
+
+ //Remove sort
+ column.sort = {};
+ };
+
+ /**
+ * communicate to outside world that we are done with initial rendering
+ */
+ Grid.prototype.renderingComplete = function(){
+ if (angular.isFunction(this.options.onRegisterApi)) {
+ this.options.onRegisterApi(this.api);
+ }
+ this.api.core.raise.renderingComplete( this.api );
+ };
+
+ Grid.prototype.createRowHashMap = function createRowHashMap() {
+ var self = this;
+
+ var hashMap = new RowHashMap();
+ hashMap.grid = self;
+
+ return hashMap;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name refresh
+ * @methodOf ui.grid.class:Grid
+ * @description Refresh the rendered grid on screen.
+ * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.
+ */
+ Grid.prototype.refresh = function refresh(rowsAltered) {
+ var self = this;
+
+ var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {
+ self.setVisibleRows(renderableRows);
+ });
+
+ var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {
+ self.setVisibleColumns(renderableColumns);
+ });
+
+ return $q.all([p1, p2]).then(function () {
+ self.redrawInPlace(rowsAltered);
+
+ self.refreshCanvas(true);
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name refreshRows
+ * @methodOf ui.grid.class:Grid
+ * @description Refresh the rendered rows on screen? Note: not functional at present
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ Grid.prototype.refreshRows = function refreshRows() {
+ var self = this;
+
+ return self.processRowsProcessors(self.rows)
+ .then(function (renderableRows) {
+ self.setVisibleRows(renderableRows);
+
+ self.redrawInPlace();
+
+ self.refreshCanvas( true );
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name refreshCanvas
+ * @methodOf ui.grid.class:Grid
+ * @description Builds all styles and recalculates much of the grid sizing
+ * @param {object} buildStyles optional parameter. Use TBD
+ * @returns {promise} promise that is resolved when the canvas
+ * has been refreshed
+ *
+ */
+ Grid.prototype.refreshCanvas = function(buildStyles) {
+ var self = this;
+
+ if (buildStyles) {
+ self.buildStyles();
+ }
+
+ var p = $q.defer();
+
+ // Get all the header heights
+ var containerHeadersToRecalc = [];
+ for (var containerId in self.renderContainers) {
+ if (self.renderContainers.hasOwnProperty(containerId)) {
+ var container = self.renderContainers[containerId];
+
+ // Skip containers that have no canvasWidth set yet
+ if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
+ continue;
+ }
+
+ if (container.header || container.headerCanvas) {
+ container.explicitHeaderHeight = container.explicitHeaderHeight || null;
+ container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;
+
+ containerHeadersToRecalc.push(container);
+ }
+ }
+ }
+
+ /*
+ *
+ * Here we loop through the headers, measuring each element as well as any header "canvas" it has within it.
+ *
+ * If any header is less than the largest header height, it will be resized to that so that we don't have headers
+ * with different heights, which looks like a rendering problem
+ *
+ * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas
+ * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't
+ * appear shorter than other cells.
+ *
+ */
+ if (containerHeadersToRecalc.length > 0) {
+ // Build the styles without the explicit header heights
+ if (buildStyles) {
+ self.buildStyles();
+ }
+
+ // Putting in a timeout as it's not calculating after the grid element is rendered and filled out
+ $timeout(function() {
+ // var oldHeaderHeight = self.grid.headerHeight;
+ // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);
+
+ var rebuildStyles = false;
+
+ // Get all the header heights
+ var maxHeaderHeight = 0;
+ var maxHeaderCanvasHeight = 0;
+ var i, container;
+ var getHeight = function(oldVal, newVal){
+ if ( oldVal !== newVal){
+ rebuildStyles = true;
+ }
+ return newVal;
+ };
+ for (i = 0; i < containerHeadersToRecalc.length; i++) {
+ container = containerHeadersToRecalc[i];
+
+ // Skip containers that have no canvasWidth set yet
+ if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
+ continue;
+ }
+
+ if (container.header) {
+ var headerHeight = container.headerHeight = getHeight(container.headerHeight, parseInt(gridUtil.outerElementHeight(container.header), 10));
+
+ // Get the "inner" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height
+ var topBorder = gridUtil.getBorderSize(container.header, 'top');
+ var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');
+ var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);
+
+ innerHeaderHeight = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;
+
+ container.innerHeaderHeight = innerHeaderHeight;
+
+ // If the header doesn't have an explicit height set, save the largest header height for use later
+ // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
+ if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {
+ maxHeaderHeight = innerHeaderHeight;
+ }
+ }
+
+ if (container.headerCanvas) {
+ var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));
+
+
+ // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later
+ // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
+ if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {
+ maxHeaderCanvasHeight = headerCanvasHeight;
+ }
+ }
+ }
+
+ // Go through all the headers
+ for (i = 0; i < containerHeadersToRecalc.length; i++) {
+ container = containerHeadersToRecalc[i];
+
+ /* If:
+ 1. We have a max header height
+ 2. This container has a header height defined
+ 3. And either this container has an explicit header height set, OR its header height is less than the max
+
+ then:
+
+ Give this container's header an explicit height so it will line up with the tallest header
+ */
+ if (
+ maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&
+ (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)
+ ) {
+ container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);
+ }
+
+ // Do the same as above except for the header canvas
+ if (
+ maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&
+ (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)
+ ) {
+ container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);
+ }
+ }
+
+ // Rebuild styles if the header height has changed
+ // The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available
+ if (buildStyles && rebuildStyles) {
+ self.buildStyles();
+ }
+
+ p.resolve();
+ });
+ }
+ else {
+ // Timeout still needs to be here to trigger digest after styles have been rebuilt
+ $timeout(function() {
+ p.resolve();
+ });
+ }
+
+ return p.promise;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name redrawCanvas
+ * @methodOf ui.grid.class:Grid
+ * @description Redraw the rows and columns based on our current scroll position
+ * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated
+ *
+ */
+ Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {
+ // gridUtil.logDebug('redrawInPlace');
+
+ var self = this;
+
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ // gridUtil.logDebug('redrawing container', i);
+
+ if (rowsAdded) {
+ container.adjustRows(container.prevScrollTop, null);
+ container.adjustColumns(container.prevScrollLeft, null);
+ }
+ else {
+ container.adjustRows(null, container.prevScrolltopPercentage);
+ container.adjustColumns(null, container.prevScrollleftPercentage);
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasLeftContainerColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if leftContainer has columns
+ */
+ Grid.prototype.hasLeftContainerColumns = function () {
+ return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasRightContainerColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if rightContainer has columns
+ */
+ Grid.prototype.hasRightContainerColumns = function () {
+ return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;
+ };
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:Grid
+ * @name scrollToIfNecessary
+ * @description Scrolls the grid to make a certain row and column combo visible,
+ * in the case that it is not completely visible on the screen already.
+ * @param {GridRow} gridRow row to make visible
+ * @param {GridCol} gridCol column to make visible
+ * @returns {promise} a promise that is resolved when scrolling is complete
+ */
+ Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {
+ var self = this;
+
+ var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');
+
+ // Alias the visible row and column caches
+ var visRowCache = self.renderContainers.body.visibleRowCache;
+ var visColCache = self.renderContainers.body.visibleColumnCache;
+
+ /*-- Get the top, left, right, and bottom "scrolled" edges of the grid --*/
+
+ // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards
+ var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;
+
+ // Don't the let top boundary be less than 0
+ topBound = (topBound < 0) ? 0 : topBound;
+
+ // The left boundary is the current X scroll position
+ var leftBound = self.renderContainers.body.prevScrollLeft;
+
+ // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.
+ // Basically this is the viewport height added on to the scroll position
+ var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight - self.scrollbarWidth;
+
+ // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows
+ //if (self.horizontalScrollbarHeight) {
+ // bottomBound = bottomBound - self.horizontalScrollbarHeight;
+ //}
+
+ // The right position is the current X scroll position minus the grid width
+ var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.renderContainers.body.getViewportWidth());
+
+ // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells
+ //if (self.verticalScrollbarWidth) {
+ // rightBound = rightBound - self.verticalScrollbarWidth;
+ //}
+
+ // We were given a row to scroll to
+ if (gridRow !== null) {
+ // This is the index of the row we want to scroll to, within the list of rows that can be visible
+ var seekRowIndex = visRowCache.indexOf(gridRow);
+
+ // Total vertical scroll length of the grid
+ var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());
+
+ // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
+ //if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {
+ // scrollLength = scrollLength + self.horizontalScrollbarHeight;
+ //}
+
+ // This is the minimum amount of pixels we need to scroll vertical in order to see this row.
+ var pixelsToSeeRow = (seekRowIndex * self.options.rowHeight + self.headerHeight);
+
+ // Don't let the pixels required to see the row be less than zero
+ pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;
+
+ var scrollPixels, percentage;
+
+ // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
+ if (pixelsToSeeRow < topBound) {
+ // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
+ // to get the full position we need
+ scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ percentage = scrollPixels / scrollLength;
+ scrollEvent.y = { percentage: percentage };
+ }
+ // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
+ else if (pixelsToSeeRow > bottomBound) {
+ // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
+ // to get the full position we need
+ scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ percentage = scrollPixels / scrollLength;
+ scrollEvent.y = { percentage: percentage };
+ }
+ }
+
+ // We were given a column to scroll to
+ if (gridCol !== null) {
+ // This is the index of the column we want to scroll to, within the list of columns that can be visible
+ var seekColumnIndex = visColCache.indexOf(gridCol);
+
+ // Total horizontal scroll length of the grid
+ var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());
+
+ // This is the minimum amount of pixels we need to scroll horizontal in order to see this column
+ var columnLeftEdge = 0;
+ for (var i = 0; i < seekColumnIndex; i++) {
+ var col = visColCache[i];
+ columnLeftEdge += col.drawnWidth;
+ }
+ columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;
+
+ var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;
+
+ // Don't let the pixels required to see the column be less than zero
+ columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;
+
+ var horizScrollPixels, horizPercentage;
+
+ // If the scroll position we need to see the column is LESS than the left boundary, i.e. obscured before the left of the self...
+ if (columnLeftEdge < leftBound) {
+ // Get the different between the left boundary and the required scroll position and subtract it from the current scroll position\
+ // to get the full position we need
+ horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ horizPercentage = horizScrollPixels / horizScrollLength;
+ horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
+ scrollEvent.x = { percentage: horizPercentage };
+ }
+ // Otherwise if the scroll position we need to see the column is MORE than the right boundary, i.e. obscured after the right of the self...
+ else if (columnRightEdge > rightBound) {
+ // Get the different between the right boundary and the required scroll position and add it to the current scroll position
+ // to get the full position we need
+ horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ horizPercentage = horizScrollPixels / horizScrollLength;
+ horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
+ scrollEvent.x = { percentage: horizPercentage };
+ }
+ }
+
+ var deferred = $q.defer();
+
+ // If we need to scroll on either the x or y axes, fire a scroll event
+ if (scrollEvent.y || scrollEvent.x) {
+ scrollEvent.withDelay = false;
+ self.scrollContainers('',scrollEvent);
+ var dereg = self.api.core.on.scrollEnd(null,function() {
+ deferred.resolve(scrollEvent);
+ dereg();
+ });
+ }
+ else {
+ deferred.resolve();
+ }
+
+ return deferred.promise;
+ };
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:Grid
+ * @name scrollTo
+ * @description Scroll the grid such that the specified
+ * row and column is in view
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible
+ * @param {object} colDef to make visible
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ Grid.prototype.scrollTo = function (rowEntity, colDef) {
+ var gridRow = null, gridCol = null;
+
+ if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {
+ gridRow = this.getRow(rowEntity);
+ }
+
+ if (colDef !== null && typeof(colDef) !== 'undefined' ) {
+ gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);
+ }
+ return this.scrollToIfNecessary(gridRow, gridCol);
+ };
+
+ /**
+ * @ngdoc function
+ * @name clearAllFilters
+ * @methodOf ui.grid.class:Grid
+ * @description Clears all filters and optionally refreshes the visible rows.
+ * @param {object} refreshRows Defaults to true.
+ * @param {object} clearConditions Defaults to false.
+ * @param {object} clearFlags Defaults to false.
+ * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
+ */
+ Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {
+ // Default `refreshRows` to true because it will be the most commonly desired behaviour.
+ if (refreshRows === undefined) {
+ refreshRows = true;
+ }
+ if (clearConditions === undefined) {
+ clearConditions = false;
+ }
+ if (clearFlags === undefined) {
+ clearFlags = false;
+ }
+
+ this.columns.forEach(function(column) {
+ column.filters.forEach(function(filter) {
+ filter.term = undefined;
+
+ if (clearConditions) {
+ filter.condition = undefined;
+ }
+
+ if (clearFlags) {
+ filter.flags = undefined;
+ }
+ });
+ });
+
+ if (refreshRows) {
+ return this.refreshRows();
+ }
+ };
+
+
+ // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)
+ function RowHashMap() {}
+
+ RowHashMap.prototype = {
+ /**
+ * Store key value pair
+ * @param key key to store can be any type
+ * @param value value to store can be any type
+ */
+ put: function(key, value) {
+ this[this.grid.options.rowIdentity(key)] = value;
+ },
+
+ /**
+ * @param key
+ * @returns {Object} the value for the key
+ */
+ get: function(key) {
+ return this[this.grid.options.rowIdentity(key)];
+ },
+
+ /**
+ * Remove the key/value pair
+ * @param key
+ */
+ remove: function(key) {
+ var value = this[key = this.grid.options.rowIdentity(key)];
+ delete this[key];
+ return value;
+ }
+ };
+
+
+
+ return Grid;
+
+}]);
+
+})();
+
+(function () {
+
+ angular.module('ui.grid')
+ .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',
+ function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridApi
+ * @description GridApi provides the ability to register public methods events inside the grid and allow
+ * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.
+ * <br/>
+ * To listen to events, you must add a callback to gridOptions.onRegisterApi
+ * <pre>
+ * $scope.gridOptions.onRegisterApi = function(gridApi){
+ * gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){
+ * $log.log('navigation event');
+ * });
+ * };
+ * </pre>
+ * @param {object} grid grid that owns api
+ */
+ var GridApi = function GridApi(grid) {
+ this.grid = grid;
+ this.listeners = [];
+
+ /**
+ * @ngdoc function
+ * @name renderingComplete
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Rendering is complete, called at the same
+ * time as `onRegisterApi`, but provides a way to obtain
+ * that same event within features without stopping end
+ * users from getting at the onRegisterApi method.
+ *
+ * Included in gridApi so that it's always there - otherwise
+ * there is still a timing problem with when a feature can
+ * call this.
+ *
+ * @param {GridApi} gridApi the grid api, as normally
+ * returned in the onRegisterApi method
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.renderingComplete( grid );
+ * </pre>
+ */
+ this.registerEvent( 'core', 'renderingComplete' );
+
+ /**
+ * @ngdoc event
+ * @name filterChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the filter is changed. The nature
+ * of the watch expression doesn't allow notification of what changed,
+ * so the receiver of this event will need to re-extract the filter
+ * conditions from the columns.
+ *
+ */
+ this.registerEvent( 'core', 'filterChanged' );
+
+ /**
+ * @ngdoc function
+ * @name setRowInvisible
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Sets an override on the row to make it always invisible,
+ * which will override any filtering or other visibility calculations.
+ * If the row is currently visible then sets it to invisible and calls
+ * both grid refresh and emits the rowsVisibleChanged event
+ * @param {GridRow} row the row we want to make invisible
+ */
+ this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Clears any override on visibility for the row so that it returns to
+ * using normal filtering and other visibility calculations.
+ * If the row is currently invisible then sets it to visible and calls
+ * both grid refresh and emits the rowsVisibleChanged event
+ * TODO: if a filter is active then we can't just set it to visible?
+ * @param {GridRow} row the row we want to make visible
+ */
+ this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );
+
+ /**
+ * @ngdoc function
+ * @name getVisibleRows
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Returns all visible rows
+ * @param {Grid} grid the grid you want to get visible rows from
+ * @returns {array} an array of gridRow
+ */
+ this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );
+
+ /**
+ * @ngdoc event
+ * @name rowsVisibleChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the rows that are visible
+ * change. The filtering is zero-based, so it isn't possible
+ * to say which rows changed (unlike in the selection feature).
+ * We can plausibly know which row was changed when setRowInvisible
+ * is called, but in that situation the user already knows which row
+ * they changed. When a filter runs we don't know what changed,
+ * and that is the one that would have been useful.
+ *
+ */
+ this.registerEvent( 'core', 'rowsVisibleChanged' );
+
+ /**
+ * @ngdoc event
+ * @name rowsRendered
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the cache of visible rows is changed.
+ */
+ this.registerEvent( 'core', 'rowsRendered' );
+
+
+ /**
+ * @ngdoc event
+ * @name scrollBegin
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when scroll begins. Is throttled, so won't be raised too frequently
+ */
+ this.registerEvent( 'core', 'scrollBegin' );
+
+ /**
+ * @ngdoc event
+ * @name scrollEnd
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when scroll has finished. Is throttled, so won't be raised too frequently
+ */
+ this.registerEvent( 'core', 'scrollEnd' );
+
+ /**
+ * @ngdoc event
+ * @name canvasHeightChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when the canvas height has changed
+ * <br/>
+ * arguments: oldHeight, newHeight
+ */
+ this.registerEvent( 'core', 'canvasHeightChanged');
+
+ /**
+ * @ngdoc event
+ * @name gridDimensionChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when the grid dimensions have changed (when autoResize is on)
+ * <br/>
+ * arguments: oldGridHeight, oldGridWidth, newGridHeight, newGridWidth
+ */
+ this.registerEvent( 'core', 'gridDimensionChanged');
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:suppressEvents
+ * @methodOf ui.grid.class:GridApi
+ * @description Used to execute a function while disabling the specified event listeners.
+ * Disables the listenerFunctions, executes the callbackFn, and then enables
+ * the listenerFunctions again
+ * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same
+ * functions that were used in the .on.eventName method
+ * @param {object} callBackFn function to execute
+ * @example
+ * <pre>
+ * var navigate = function (newRowCol, oldRowCol){
+ * //do something on navigate
+ * }
+ *
+ * gridApi.cellNav.on.navigate(scope,navigate);
+ *
+ *
+ * //call the scrollTo event and suppress our navigate listener
+ * //scrollTo will still raise the event for other listeners
+ * gridApi.suppressEvents(navigate, function(){
+ * gridApi.cellNav.scrollTo(aRow, aCol);
+ * });
+ *
+ * </pre>
+ */
+ GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {
+ var self = this;
+ var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];
+
+ //find all registered listeners
+ var foundListeners = self.listeners.filter(function(listener) {
+ return listeners.some(function(l) {
+ return listener.handler === l;
+ });
+ });
+
+ //deregister all the listeners
+ foundListeners.forEach(function(l){
+ l.dereg();
+ });
+
+ callBackFn();
+
+ //reregister all the listeners
+ foundListeners.forEach(function(l){
+ l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);
+ });
+
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerEvent
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers a new event for the given feature. The event will get a
+ * .raise and .on prepended to it
+ * <br>
+ * .raise.eventName() - takes no arguments
+ * <br/>
+ * <br/>
+ * .on.eventName(scope, callBackFn, _this)
+ * <br/>
+ * scope - a scope reference to add a deregister call to the scopes .$on('destroy'). Scope is optional and can be a null value,
+ * but in this case you must deregister it yourself via the returned deregister function
+ * <br/>
+ * callBackFn - The function to call
+ * <br/>
+ * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context
+ * <br/>
+ * .on.eventName returns a dereg funtion that will remove the listener. It's not necessary to use it as the listener
+ * will be removed when the scope is destroyed.
+ * @param {string} featureName name of the feature that raises the event
+ * @param {string} eventName name of the event
+ */
+ GridApi.prototype.registerEvent = function (featureName, eventName) {
+ var self = this;
+ if (!self[featureName]) {
+ self[featureName] = {};
+ }
+
+ var feature = self[featureName];
+ if (!feature.on) {
+ feature.on = {};
+ feature.raise = {};
+ }
+
+ var eventId = self.grid.id + featureName + eventName;
+
+ // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);
+ feature.raise[eventName] = function () {
+ $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));
+ };
+
+ // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);
+ feature.on[eventName] = function (scope, handler, _this) {
+ if ( scope !== null && typeof(scope.$on) === 'undefined' ){
+ gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\'t passed in the input parameters. It is legitimate to pass null, but you\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');
+ return;
+ }
+ var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);
+
+ //track our listener so we can turn off and on
+ var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};
+ self.listeners.push(listener);
+
+ var removeListener = function(){
+ listener.dereg();
+ var index = self.listeners.indexOf(listener);
+ self.listeners.splice(index,1);
+ };
+
+ //destroy tracking when scope is destroyed
+ if (scope) {
+ scope.$on('$destroy', function() {
+ removeListener();
+ });
+ }
+
+
+ return removeListener;
+ };
+ };
+
+ function registerEventWithAngular(eventId, handler, grid, _this) {
+ return $rootScope.$on(eventId, function (event) {
+ var args = Array.prototype.slice.call(arguments);
+ args.splice(0, 1); //remove evt argument
+ handler.apply(_this ? _this : grid.api, args);
+ });
+ }
+
+ /**
+ * @ngdoc function
+ * @name registerEventsFromObject
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers features and events from a simple objectMap.
+ * eventObjectMap must be in this format (multiple features allowed)
+ * <pre>
+ * {featureName:
+ * {
+ * eventNameOne:function(args){},
+ * eventNameTwo:function(args){}
+ * }
+ * }
+ * </pre>
+ * @param {object} eventObjectMap map of feature/event names
+ */
+ GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {
+ var self = this;
+ var features = [];
+ angular.forEach(eventObjectMap, function (featProp, featPropName) {
+ var feature = {name: featPropName, events: []};
+ angular.forEach(featProp, function (prop, propName) {
+ feature.events.push(propName);
+ });
+ features.push(feature);
+ });
+
+ features.forEach(function (feature) {
+ feature.events.forEach(function (event) {
+ self.registerEvent(feature.name, event);
+ });
+ });
+
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerMethod
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers a new event for the given feature
+ * @param {string} featureName name of the feature
+ * @param {string} methodName name of the method
+ * @param {object} callBackFn function to execute
+ * @param {object} _this binds callBackFn 'this' to _this. Defaults to gridApi.grid
+ */
+ GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {
+ if (!this[featureName]) {
+ this[featureName] = {};
+ }
+
+ var feature = this[featureName];
+
+ feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerMethodsFromObject
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers features and methods from a simple objectMap.
+ * eventObjectMap must be in this format (multiple features allowed)
+ * <br>
+ * {featureName:
+ * {
+ * methodNameOne:function(args){},
+ * methodNameTwo:function(args){}
+ * }
+ * @param {object} eventObjectMap map of feature/event names
+ * @param {object} _this binds this to _this for all functions. Defaults to gridApi.grid
+ */
+ GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {
+ var self = this;
+ var features = [];
+ angular.forEach(methodMap, function (featProp, featPropName) {
+ var feature = {name: featPropName, methods: []};
+ angular.forEach(featProp, function (prop, propName) {
+ feature.methods.push({name: propName, fn: prop});
+ });
+ features.push(feature);
+ });
+
+ features.forEach(function (feature) {
+ feature.methods.forEach(function (method) {
+ self.registerMethod(feature.name, method.name, method.fn, _this);
+ });
+ });
+
+ };
+
+ return GridApi;
+
+ }]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {
+
+ /**
+ * ******************************************************************************************
+ * PaulL1: Ugly hack here in documentation. These properties are clearly properties of GridColumn,
+ * and need to be noted as such for those extending and building ui-grid itself.
+ * However, from an end-developer perspective, they interact with all these through columnDefs,
+ * and they really need to be documented there. I feel like they're relatively static, and
+ * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each
+ * comment block. Ugh.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name name
+ * @propertyOf ui.grid.class:GridColumn
+ * @description (mandatory) each column should have a name, although for backward
+ * compatibility with 2.x name can be omitted if field is present
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name name
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (mandatory) each column should have a name, although for backward
+ * compatibility with 2.x name can be omitted if field is present
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name displayName
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Column name that will be shown in the header. If displayName is not
+ * provided then one is generated using the name.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name displayName
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Column name that will be shown in the header. If displayName is not
+ * provided then one is generated using the name.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name field
+ * @propertyOf ui.grid.class:GridColumn
+ * @description field must be provided if you wish to bind to a
+ * property in the data source. Should be an angular expression that evaluates against grid.options.data
+ * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.
+ * See the angular docs on binding expressions.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name field
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description field must be provided if you wish to bind to a
+ * property in the data source. Should be an angular expression that evaluates against grid.options.data
+ * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>. * See the angular docs on binding expressions. *
+ */
+
+ /**
+ * @ngdoc property
+ * @name filter
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Filter on this column.
+ *
+ * Available built-in conditions and types are listed under {@link jui.grid.service:uiGridConstants#properties_filter uiGridOptions.filter}
+ * @example
+ * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text', flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name extraStyle
+ * @propertyOf ui.grid.class:GridColumn
+ * @description additional on this column.
+ * @example
+ * <pre>{extraStyle: {display:'table-cell'}}</pre>
+ *
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridColumn
+ * @description Represents the viewModel for each column. Any state or methods needed for a Grid Column
+ * are defined on this prototype
+ * @param {ColumnDef} colDef the column def to associate with this column
+ * @param {number} uid the unique and immutable uid we'd like to allocate to this column
+ * @param {Grid} grid the grid we'd like to create this column in
+ */
+ function GridColumn(colDef, uid, grid) {
+ var self = this;
+
+ self.grid = grid;
+ self.uid = uid;
+
+ self.updateColumnDef(colDef, true);
+
+ self.aggregationValue = undefined;
+
+ // The footer cell registers to listen for the rowsRendered event, and calls this. Needed to be
+ // in something with a scope so that the dereg would get called
+ self.updateAggregationValue = function() {
+
+ // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);
+
+ /**
+ * @ngdoc property
+ * @name aggregationType
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description The aggregation that you'd like to show in the columnFooter for this
+ * column. Valid values are in
+ * {@link ui.grid.service:uiGridConstants#properties_aggregationTypes uiGridConstants.aggregationTypes},
+ * and currently include `uiGridConstants.aggregationTypes.count`,
+ * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,
+ * `uiGridConstants.aggregationTypes.max`.
+ *
+ * You can also provide a function as the aggregation type, in this case your function needs to accept the full
+ * set of visible rows, and return a value that should be shown
+ */
+ if (!self.aggregationType) {
+ self.aggregationValue = undefined;
+ return;
+ }
+
+ var result = 0;
+ var visibleRows = self.grid.getVisibleRows();
+
+ var cellValues = function(){
+ var values = [];
+ visibleRows.forEach(function (row) {
+ var cellValue = self.grid.getCellValue(row, self);
+ var cellNumber = Number(cellValue);
+ if (!isNaN(cellNumber)) {
+ values.push(cellNumber);
+ }
+ });
+ return values;
+ };
+
+ if (angular.isFunction(self.aggregationType)) {
+ self.aggregationValue = self.aggregationType(visibleRows, self);
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {
+ self.aggregationValue = self.grid.getVisibleRowCount();
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {
+ cellValues().forEach(function (value) {
+ result += value;
+ });
+ self.aggregationValue = result;
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {
+ cellValues().forEach(function (value) {
+ result += value;
+ });
+ result = result / cellValues().length;
+ self.aggregationValue = result;
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {
+ self.aggregationValue = Math.min.apply(null, cellValues());
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {
+ self.aggregationValue = Math.max.apply(null, cellValues());
+ }
+ else {
+ self.aggregationValue = '\u00A0';
+ }
+ };
+
+// var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });
+
+ /**
+ * @ngdoc function
+ * @name getAggregationValue
+ * @methodOf ui.grid.class:GridColumn
+ * @description gets the aggregation value based on the aggregation type for this column.
+ * Debounced using scrollDebounce option setting
+ */
+ this.getAggregationValue = function() {
+// if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
+// throttledUpdateAggregationValue();
+// }
+
+ return self.aggregationValue;
+ };
+ }
+
+ /**
+ * @ngdoc function
+ * @name hideColumn
+ * @methodOf ui.grid.class:GridColumn
+ * @description Hides the column by setting colDef.visible = false
+ */
+ GridColumn.prototype.hideColumn = function() {
+ this.colDef.visible = false;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:GridColumn
+ * @name setPropertyOrDefault
+ * @description Sets a property on the column using the passed in columnDef, and
+ * setting the defaultValue if the value cannot be found on the colDef
+ * @param {ColumnDef} colDef the column def to look in for the property value
+ * @param {string} propName the property name we'd like to set
+ * @param {object} defaultValue the value to use if the colDef doesn't provide the setting
+ */
+ GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {
+ var self = this;
+
+ // Use the column definition filter if we were passed it
+ if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {
+ self[propName] = colDef[propName];
+ }
+ // Otherwise use our own if it's set
+ else if (typeof(self[propName]) !== 'undefined') {
+ self[propName] = self[propName];
+ }
+ // Default to empty object for the filter
+ else {
+ self[propName] = defaultValue ? defaultValue : {};
+ }
+ };
+
+
+
+ /**
+ * @ngdoc property
+ * @name width
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the column width. Can be either
+ * a number or a percentage, or an * for auto.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},
+ * { field: 'field2', width: '20%'},
+ * { field: 'field3', width: '*' }]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name minWidth
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the minimum column width. Should be a number.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name maxWidth
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the maximum column width. Should be a number.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name visible
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets whether or not the column is visible
+ * </br>Default is true
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [
+ * { field: 'field1', visible: true},
+ * { field: 'field2', visible: false }
+ * ]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name sort
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description An object of sort information, attributes are:
+ *
+ * - direction: values are {@link ui.grid.service:uiGridConstants#properties_ASC uiGridConstants.ASC}
+ * or {@link ui.grid.service:uiGridConstants#properties_DESC uiGridConstants.DESC}
+ * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)
+ * - priority: says what order to sort the columns in (lower priority gets sorted first).
+ * @example
+ * <pre>
+ * $scope.gridOptions.columnDefs = [{
+ * field: 'field1',
+ * sort: {
+ * direction: uiGridConstants.ASC,
+ * ignoreSort: true,
+ * priority: 0
+ * }
+ * }];
+ * </pre>
+ */
+
+
+ /**
+ * @ngdoc property
+ * @name sortingAlgorithm
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters
+ * like any normal sorting function with additional 'rowA', 'rowB', and 'direction' parameters
+ * that are the row objects and the current direction of the sort respectively.
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name filters
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Specify multiple filter fields.
+ * @example
+ * <pre>$scope.gridOptions.columnDefs = [
+ * {
+ * field: 'field1', filters: [
+ * {
+ * term: 'aa',
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Filter for field1',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
+ * },
+ * {
+ * condition: uiGridConstants.filter.ENDS_WITH,
+ * placeholder: 'ends with...'
+ * }
+ * ]
+ * }
+ * ]; </pre>
+ *
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name filters
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Filters for this column. Includes 'term' property bound to filter input elements.
+ * @example
+ * <pre>[
+ * {
+ * term: 'foo', // ngModel for <input>
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Filter for foo',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
+ * },
+ * {
+ * term: 'baz',
+ * condition: uiGridConstants.filter.ENDS_WITH,
+ * placeholder: 'ends with...'
+ * }
+ * ] </pre>
+ *
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name menuItems
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description used to add menu items to a column. Refer to the tutorial on this
+ * functionality. A number of settings are supported:
+ *
+ * - title: controls the title that is displayed in the menu
+ * - icon: the icon shown alongside that title
+ * - action: the method to call when the menu is clicked
+ * - shown: a function to evaluate to determine whether or not to show the item
+ * - active: a function to evaluate to determine whether or not the item is currently selected
+ * - context: context to pass to the action function, available in this.context in your handler
+ * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [
+ * { field: 'field1', menuItems: [
+ * {
+ * title: 'Outer Scope Alert',
+ * icon: 'ui-grid-icon-info-circled',
+ * action: function($event) {
+ * this.context.blargh(); // $scope.blargh() would work too, this is just an example
+ * },
+ * shown: function() { return true; },
+ * active: function() { return true; },
+ * context: $scope
+ * },
+ * {
+ * title: 'Grid ID',
+ * action: function() {
+ * alert('Grid ID: ' + this.grid.id);
+ * }
+ * }
+ * ] }]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:GridColumn
+ * @name updateColumnDef
+ * @description Moves settings from the columnDef down onto the column,
+ * and sets properties as appropriate
+ * @param {ColumnDef} colDef the column def to look in for the property value
+ * @param {boolean} isNew whether the column is being newly created, if not
+ * we're updating an existing column, and some items such as the sort shouldn't
+ * be copied down
+ */
+ GridColumn.prototype.updateColumnDef = function(colDef, isNew) {
+ var self = this;
+
+ self.colDef = colDef;
+
+ if (colDef.name === undefined) {
+ throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));
+ }
+
+ self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
+
+ if (!angular.isNumber(self.width) || !self.hasCustomWidth || colDef.allowCustomWidthOverride) {
+ var colDefWidth = colDef.width;
+ var parseErrorMsg = "Cannot parse column width '" + colDefWidth + "' for column named '" + colDef.name + "'";
+ self.hasCustomWidth = false;
+
+ if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {
+ self.width = '*';
+ } else if (angular.isString(colDefWidth)) {
+ // See if it ends with a percent
+ if (gridUtil.endsWith(colDefWidth, '%')) {
+ // If so we should be able to parse the non-percent-sign part to a number
+ var percentStr = colDefWidth.replace(/%/g, '');
+ var percent = parseInt(percentStr, 10);
+ if (isNaN(percent)) {
+ throw new Error(parseErrorMsg);
+ }
+ self.width = colDefWidth;
+ }
+ // And see if it's a number string
+ else if (colDefWidth.match(/^(\d+)$/)) {
+ self.width = parseInt(colDefWidth.match(/^(\d+)$/)[1], 10);
+ }
+ // Otherwise it should be a string of asterisks
+ else if (colDefWidth.match(/^\*+$/)) {
+ self.width = colDefWidth;
+ }
+ // No idea, throw an Error
+ else {
+ throw new Error(parseErrorMsg);
+ }
+ }
+ // Is a number, use it as the width
+ else {
+ self.width = colDefWidth;
+ }
+ }
+
+ ['minWidth', 'maxWidth'].forEach(function (name) {
+ var minOrMaxWidth = colDef[name];
+ var parseErrorMsg = "Cannot parse column " + name + " '" + minOrMaxWidth + "' for column named '" + colDef.name + "'";
+
+ if (!angular.isString(minOrMaxWidth) && !angular.isNumber(minOrMaxWidth)) {
+ //Sets default minWidth and maxWidth values
+ self[name] = ((name === 'minWidth') ? 30 : 9000);
+ } else if (angular.isString(minOrMaxWidth)) {
+ if (minOrMaxWidth.match(/^(\d+)$/)) {
+ self[name] = parseInt(minOrMaxWidth.match(/^(\d+)$/)[1], 10);
+ } else {
+ throw new Error(parseErrorMsg);
+ }
+ } else {
+ self[name] = minOrMaxWidth;
+ }
+ });
+
+ //use field if it is defined; name if it is not
+ self.field = (colDef.field === undefined) ? colDef.name : colDef.field;
+
+ if ( typeof( self.field ) !== 'string' ){
+ gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );
+ }
+
+ self.name = colDef.name;
+
+ // Use colDef.displayName as long as it's not undefined, otherwise default to the field name
+ self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
+
+ //self.originalIndex = index;
+
+ self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;
+ self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;
+
+ /**
+ * @ngdoc property
+ * @name cellTooltip
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Whether or not to show a tooltip when a user hovers over the cell.
+ * If set to false, no tooltip. If true, the cell value is shown in the tooltip (useful
+ * if you have long values in your cells), if a function then that function is called
+ * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,
+ * if it is a static string then displays that static string.
+ *
+ * Defaults to false
+ *
+ */
+ if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {
+ self.cellTooltip = false;
+ } else if ( colDef.cellTooltip === true ){
+ self.cellTooltip = function(row, col) {
+ return self.grid.getCellValue( row, col );
+ };
+ } else if (typeof(colDef.cellTooltip) === 'function' ){
+ self.cellTooltip = colDef.cellTooltip;
+ } else {
+ self.cellTooltip = function ( row, col ){
+ return col.colDef.cellTooltip;
+ };
+ }
+
+ /**
+ * @ngdoc property
+ * @name headerTooltip
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Whether or not to show a tooltip when a user hovers over the header cell.
+ * If set to false, no tooltip. If true, the displayName is shown in the tooltip (useful
+ * if you have long values in your headers), if a function then that function is called
+ * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,
+ * if a static string then shows that static string.
+ *
+ * Defaults to false
+ *
+ */
+ if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {
+ self.headerTooltip = false;
+ } else if ( colDef.headerTooltip === true ){
+ self.headerTooltip = function(col) {
+ return col.displayName;
+ };
+ } else if (typeof(colDef.headerTooltip) === 'function' ){
+ self.headerTooltip = colDef.headerTooltip;
+ } else {
+ self.headerTooltip = function ( col ) {
+ return col.colDef.headerTooltip;
+ };
+ }
+
+
+ /**
+ * @ngdoc property
+ * @name footerCellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description footerCellClass can be a string specifying the class to append to a cell
+ * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
+ *
+ */
+ self.footerCellClass = colDef.footerCellClass;
+
+ /**
+ * @ngdoc property
+ * @name cellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description cellClass can be a string specifying the class to append to a cell
+ * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
+ *
+ */
+ self.cellClass = colDef.cellClass;
+
+ /**
+ * @ngdoc property
+ * @name headerCellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description headerCellClass can be a string specifying the class to append to a cell
+ * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
+ *
+ */
+ self.headerCellClass = colDef.headerCellClass;
+
+ /**
+ * @ngdoc property
+ * @name cellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description cellFilter is a filter to apply to the content of each cell
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].cellFilter = 'date'
+ *
+ */
+ self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
+
+ /**
+ * @ngdoc boolean
+ * @name sortCellFiltered
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
+ * sorting the data. Note that when using this option uiGrid will assume that the displayed value is
+ * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible
+ * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}
+ * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`
+ * found in the {@link ui.grid.RowSorter rowSorter} service.
+ */
+ self.sortCellFiltered = colDef.sortCellFiltered ? true : false;
+
+ /**
+ * @ngdoc boolean
+ * @name filterCellFiltered
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
+ * applying "search" `filters`.
+ */
+ self.filterCellFiltered = colDef.filterCellFiltered ? true : false;
+
+ /**
+ * @ngdoc property
+ * @name headerCellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description headerCellFilter is a filter to apply to the content of the column header
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].headerCellFilter = 'translate'
+ *
+ */
+ self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : "";
+
+ /**
+ * @ngdoc property
+ * @name footerCellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description footerCellFilter is a filter to apply to the content of the column footer
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].footerCellFilter = 'date'
+ *
+ */
+ self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : "";
+
+ self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;
+
+ self.headerClass = colDef.headerClass;
+ //self.cursor = self.sortable ? 'pointer' : 'default';
+
+ // Turn on sorting by default
+ self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : self.grid.options.enableSorting;
+ self.sortingAlgorithm = colDef.sortingAlgorithm;
+
+ /**
+ * @ngdoc property
+ * @name sortDirectionCycle
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) An array of {@link ui.grid.service:uiGridConstants#properties_ASC sort directions},
+ * specifying the order that they should cycle through as the user repeatedly clicks on the column heading.
+ * The default is `[null, uiGridConstants.ASC, uiGridConstants.DESC]`. Null
+ * refers to the unsorted state. This does not affect the initial sort
+ * direction; use the {@link ui.grid.class:GridOptions.columnDef#sort sort}
+ * property for that. If
+ * {@link ui.grid.class:GridOptions.columnDef#suppressRemoveSort suppressRemoveSort}
+ * is also set, the unsorted state will be skipped even if it is listed here.
+ * Each direction may not appear in the list more than once (e.g. `[ASC,
+ * DESC, DESC]` is not allowed), and the list may not be empty.
+ */
+ self.sortDirectionCycle = typeof(colDef.sortDirectionCycle) !== 'undefined' ?
+ colDef.sortDirectionCycle :
+ [null, uiGridConstants.ASC, uiGridConstants.DESC];
+
+ /**
+ * @ngdoc boolean
+ * @name suppressRemoveSort
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When enabled, this setting hides the removeSort option
+ * in the menu, and prevents users from manually removing the sort
+ */
+ if ( typeof(self.suppressRemoveSort) === 'undefined'){
+ self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;
+ }
+
+ /**
+ * @ngdoc property
+ * @name enableFiltering
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description turn off filtering for an individual column, where
+ * you've turned on filtering for the overall grid
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].enableFiltering = false;
+ *
+ */
+ // Turn on filtering by default (it's disabled by default at the Grid level)
+ self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;
+
+ // self.menuItems = colDef.menuItems;
+ self.setPropertyOrDefault(colDef, 'menuItems', []);
+
+ // Use the column definition sort if we were passed it, but only if this is a newly added column
+ if ( isNew ){
+ self.setPropertyOrDefault(colDef, 'sort');
+ }
+
+ // Set up default filters array for when one is not provided.
+ // In other words, this (in column def):
+ //
+ // filter: { term: 'something', flags: {}, condition: [CONDITION] }
+ //
+ // is just shorthand for this:
+ //
+ // filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]
+ //
+ var defaultFilters = [];
+ if (colDef.filter) {
+ defaultFilters.push(colDef.filter);
+ }
+ else if ( colDef.filters ){
+ defaultFilters = colDef.filters;
+ } else {
+ // Add an empty filter definition object, which will
+ // translate to a guessed condition and no pre-populated
+ // value for the filter <input>.
+ defaultFilters.push({});
+ }
+
+ /**
+ * @ngdoc property
+ * @name filter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Specify a single filter field on this column.
+ *
+ * A filter consists of a condition, a term, and a placeholder:
+ *
+ * - condition defines how rows are chosen as matching the filter term. This can be set to
+ * one of the constants in {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter},
+ * or you can supply a custom filter function
+ * that gets passed the following arguments: [searchTerm, cellValue, row, column].
+ * - term: If set, the filter field will be pre-populated
+ * with this value.
+ * - placeholder: String that will be set to the `<input>.placeholder` attribute.
+ * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.
+ * - noTerm: set this to true if you have defined a custom function in condition, and
+ * your custom function doesn't require a term (so it can run even when the term is null)
+ * - rawTerm: set this to true if you have defined a custom function in condition, and
+ * your custom function requires access to the raw unmodified search term that was entered
+ * - flags: only flag currently available is `caseSensitive`, set to false if you don't want
+ * case sensitive matching
+ * - type: defaults to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.INPUT},
+ * which gives a text box. If set to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.SELECT}
+ * then a select box will be shown with options selectOptions
+ * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`. No i18n filter is provided, you need
+ * to perform the i18n on the values before you provide them
+ * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter
+ * will not be shown.
+ * @example
+ * <pre>$scope.gridOptions.columnDefs = [
+ * {
+ * field: 'field1',
+ * filter: {
+ * term: 'xx',
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Starts with filter for field1',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],
+ * disableCancelFilterButton: true
+ * }
+ * }
+ * ]; </pre>
+ *
+ */
+
+ /*
+
+
+ /*
+
+ self.filters = [
+ {
+ term: 'search term'
+ condition: uiGridConstants.filter.CONTAINS,
+ placeholder: 'my placeholder',
+ ariaLabel: 'Starts with filter for field1',
+ flags: {
+ caseSensitive: true
+ }
+ }
+ ]
+
+ */
+
+ // Only set filter if this is a newly added column, if we're updating an existing
+ // column then we don't want to put the default filter back if the user may have already
+ // removed it.
+ // However, we do want to keep the settings if they change, just not the term
+ if ( isNew ) {
+ self.setPropertyOrDefault(colDef, 'filter');
+ self.setPropertyOrDefault(colDef, 'extraStyle');
+ self.setPropertyOrDefault(colDef, 'filters', defaultFilters);
+ } else if ( self.filters.length === defaultFilters.length ) {
+ self.filters.forEach( function( filter, index ){
+ if (typeof(defaultFilters[index].placeholder) !== 'undefined') {
+ filter.placeholder = defaultFilters[index].placeholder;
+ }
+ if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {
+ filter.ariaLabel = defaultFilters[index].ariaLabel;
+ }
+ if (typeof(defaultFilters[index].flags) !== 'undefined') {
+ filter.flags = defaultFilters[index].flags;
+ }
+ if (typeof(defaultFilters[index].type) !== 'undefined') {
+ filter.type = defaultFilters[index].type;
+ }
+ if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {
+ filter.selectOptions = defaultFilters[index].selectOptions;
+ }
+ });
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name unsort
+ * @methodOf ui.grid.class:GridColumn
+ * @description Removes column from the grid sorting
+ */
+ GridColumn.prototype.unsort = function () {
+ this.sort = {};
+ this.grid.api.core.raise.sortChanged( this.grid, this.grid.getColumnSorting() );
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColClass
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the class name for the column
+ * @param {bool} prefixDot if true, will return .className instead of className
+ */
+ GridColumn.prototype.getColClass = function (prefixDot) {
+ var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;
+
+ return prefixDot ? '.' + cls : cls;
+ };
+
+ /**
+ * @ngdoc function
+ * @name isPinnedLeft
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns true if column is in the left render container
+ */
+ GridColumn.prototype.isPinnedLeft = function () {
+ return this.renderContainer === 'left';
+ };
+
+ /**
+ * @ngdoc function
+ * @name isPinnedRight
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns true if column is in the right render container
+ */
+ GridColumn.prototype.isPinnedRight = function () {
+ return this.renderContainer === 'right';
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColClassDefinition
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the class definition for th column
+ */
+ GridColumn.prototype.getColClassDefinition = function () {
+ return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRenderContainer
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the render container object that this column belongs to.
+ *
+ * Columns will be default be in the `body` render container if they aren't allocated to one specifically.
+ */
+ GridColumn.prototype.getRenderContainer = function getRenderContainer() {
+ var self = this;
+
+ var containerId = self.renderContainer;
+
+ if (containerId === null || containerId === '' || containerId === undefined) {
+ containerId = 'body';
+ }
+
+ return self.grid.renderContainers[containerId];
+ };
+
+ /**
+ * @ngdoc function
+ * @name showColumn
+ * @methodOf ui.grid.class:GridColumn
+ * @description Makes the column visible by setting colDef.visible = true
+ */
+ GridColumn.prototype.showColumn = function() {
+ this.colDef.visible = true;
+ };
+
+
+ /**
+ * @ngdoc property
+ * @name aggregationHideLabel
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description defaults to false, if set to true hides the label text
+ * in the aggregation footer, so only the value is displayed.
+ *
+ */
+ /**
+ * @ngdoc function
+ * @name getAggregationText
+ * @methodOf ui.grid.class:GridColumn
+ * @description Gets the aggregation label from colDef.aggregationLabel if
+ * specified or by using i18n, including deciding whether or not to display
+ * based on colDef.aggregationHideLabel.
+ *
+ * @param {string} label the i18n lookup value to use for the column label
+ *
+ */
+ GridColumn.prototype.getAggregationText = function () {
+ var self = this;
+ if ( self.colDef.aggregationHideLabel ){
+ return '';
+ }
+ else if ( self.colDef.aggregationLabel ) {
+ return self.colDef.aggregationLabel;
+ }
+ else {
+ switch ( self.colDef.aggregationType ){
+ case uiGridConstants.aggregationTypes.count:
+ return i18nService.getSafeText('aggregation.count');
+ case uiGridConstants.aggregationTypes.sum:
+ return i18nService.getSafeText('aggregation.sum');
+ case uiGridConstants.aggregationTypes.avg:
+ return i18nService.getSafeText('aggregation.avg');
+ case uiGridConstants.aggregationTypes.min:
+ return i18nService.getSafeText('aggregation.min');
+ case uiGridConstants.aggregationTypes.max:
+ return i18nService.getSafeText('aggregation.max');
+ default:
+ return '';
+ }
+ }
+ };
+
+ GridColumn.prototype.getCellTemplate = function () {
+ var self = this;
+
+ return self.cellTemplatePromise;
+ };
+
+ GridColumn.prototype.getCompiledElementFn = function () {
+ var self = this;
+
+ return self.compiledElementFnDefer.promise;
+ };
+
+ return GridColumn;
+}]);
+
+})();
+
+ (function(){
+
+angular.module('ui.grid')
+.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridOptions
+ * @description Default GridOptions class. GridOptions are defined by the application developer and overlaid
+ * over this object. Setting gridOptions within your controller is the most common method for an application
+ * developer to configure the behaviour of their ui-grid
+ *
+ * @example To define your gridOptions within your controller:
+ * <pre>$scope.gridOptions = {
+ * data: $scope.myData,
+ * columnDefs: [
+ * { name: 'field1', displayName: 'pretty display name' },
+ * { name: 'field2', visible: false }
+ * ]
+ * };</pre>
+ *
+ * You can then use this within your html template, when you define your grid:
+ * <pre>&lt;div ui-grid="gridOptions"&gt;&lt;/div&gt;</pre>
+ *
+ * To provide default options for all of the grids within your application, use an angular
+ * decorator to modify the GridOptions factory.
+ * <pre>
+ * app.config(function($provide){
+ * $provide.decorator('GridOptions',function($delegate){
+ * var gridOptions;
+ * gridOptions = angular.copy($delegate);
+ * gridOptions.initialize = function(options) {
+ * var initOptions;
+ * initOptions = $delegate.initialize(options);
+ * initOptions.enableColumnMenus = false;
+ * return initOptions;
+ * };
+ * return gridOptions;
+ * });
+ * });
+ * </pre>
+ */
+ return {
+ initialize: function( baseOptions ){
+ /**
+ * @ngdoc function
+ * @name onRegisterApi
+ * @propertyOf ui.grid.class:GridOptions
+ * @description A callback that returns the gridApi once the grid is instantiated, which is
+ * then used to interact with the grid programatically.
+ *
+ * Note that the gridApi.core.renderingComplete event is identical to this
+ * callback, but has the advantage that it can be called from multiple places
+ * if needed
+ *
+ * @example
+ * <pre>
+ * $scope.gridOptions.onRegisterApi = function ( gridApi ) {
+ * $scope.gridApi = gridApi;
+ * $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );
+ * };
+ * </pre>
+ *
+ */
+ baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();
+
+ /**
+ * @ngdoc object
+ * @name data
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for
+ * the grid.
+ *
+ * Most commonly the data is an array of objects, where each object has a number of attributes.
+ * Each attribute automatically becomes a column in your grid. This array could, for example, be sourced from
+ * an angularJS $resource query request. The array can also contain complex objects, refer the binding tutorial
+ * for examples of that.
+ *
+ * The most flexible usage is to set your data on $scope:
+ *
+ * `$scope.data = data;`
+ *
+ * And then direct the grid to resolve whatever is in $scope.data:
+ *
+ * `$scope.gridOptions.data = 'data';`
+ *
+ * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without
+ * getting pointer issues.
+ *
+ * Alternatively you can directly set the data array:
+ *
+ * `$scope.gridOptions.data = [ ];`
+ * or
+ *
+ * `$http.get('/data/100.json')
+ * .success(function(data) {
+ * $scope.myData = data;
+ * $scope.gridOptions.data = $scope.myData;
+ * });`
+ *
+ * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other
+ * array, you need to update $scope.gridOptions.data to point to that new array as well.
+ *
+ */
+ baseOptions.data = baseOptions.data || [];
+
+ /**
+ * @ngdoc array
+ * @name columnDefs
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Array of columnDef objects. Only required property is name.
+ * The individual options available in columnDefs are documented in the
+ * {@link ui.grid.class:GridOptions.columnDef columnDef} section
+ * </br>_field property can be used in place of name for backwards compatibility with 2.x_
+ * @example
+ *
+ * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>
+ *
+ */
+ baseOptions.columnDefs = baseOptions.columnDefs || [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridOptions.columnDef
+ * @description Definition / configuration of an individual column, which would typically be
+ * one of many column definitions within the gridOptions.columnDefs array
+ * @example
+ * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>
+ *
+ */
+
+
+ /**
+ * @ngdoc array
+ * @name excludeProperties
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Array of property names in data to ignore when auto-generating column names. Provides the
+ * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns
+ * to exclude.
+ *
+ * If columnDefs is defined, this will be ignored.
+ *
+ * Defaults to ['$$hashKey']
+ */
+
+ baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];
+
+ /**
+ * @ngdoc boolean
+ * @name enableRowHashing
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting allows uiGrid to add
+ * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows
+ * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.
+ *
+ * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF
+ * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows
+ * and are altering the data set often.
+ */
+ baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;
+
+ /**
+ * @ngdoc function
+ * @name rowIdentity
+ * @methodOf ui.grid.class:GridOptions
+ * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).
+ *
+ * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one
+ */
+ baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {
+ return gridUtil.hashKey(row);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRowIdentity
+ * @methodOf ui.grid.class:GridOptions
+ * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.
+ *
+ * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.
+ */
+ baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {
+ return row.$$hashKey;
+ };
+
+ /**
+ * @ngdoc property
+ * @name flatEntityAccess
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.
+ * each of your columns associate directly with a property on each of the entities in your data array.
+ *
+ * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,
+ * which can provide a significant speed improvement with large data sets when filtering or sorting.
+ *
+ * By default false
+ */
+ baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;
+
+ /**
+ * @ngdoc property
+ * @name showHeader
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When set to false, this setting will replace the
+ * standard header template with '<div></div>', resulting in no header being shown.
+ */
+ baseOptions.showHeader = typeof(baseOptions.showHeader) !== "undefined" ? baseOptions.showHeader : true;
+
+ /* (NOTE): Don't show this in the docs. We only use it internally
+ * @ngdoc property
+ * @name headerRowHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the header in pixels, defaults to 30
+ *
+ */
+ if (!baseOptions.showHeader) {
+ baseOptions.headerRowHeight = 0;
+ }
+ else {
+ baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== "undefined" ? baseOptions.headerRowHeight : 30;
+ }
+
+ /**
+ * @ngdoc property
+ * @name rowHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the row in pixels, Can be passed as integer or string. defaults to 30.
+ *
+ */
+
+ if (typeof baseOptions.rowHeight === "string") {
+ baseOptions.rowHeight = parseInt(baseOptions.rowHeight) || 30;
+ }
+
+ else {
+ baseOptions.rowHeight = baseOptions.rowHeight || 30;
+ }
+
+ /**
+ * @ngdoc integer
+ * @name minRowsToShow
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to "10".
+ */
+ baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== "undefined" ? baseOptions.minRowsToShow : 10;
+
+ /**
+ * @ngdoc property
+ * @name showGridFooter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether or not to show the footer, defaults to false
+ * The footer display Total Rows and Visible Rows (filtered rows)
+ */
+ baseOptions.showGridFooter = baseOptions.showGridFooter === true;
+
+ /**
+ * @ngdoc property
+ * @name showColumnFooter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether or not to show the column footer, defaults to false
+ * The column footer displays column aggregates
+ */
+ baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;
+
+ /**
+ * @ngdoc property
+ * @name columnFooterHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the footer rows (column footer and grid footer) in pixels
+ *
+ */
+ baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== "undefined" ? baseOptions.columnFooterHeight : 30;
+ baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== "undefined" ? baseOptions.gridFooterHeight : 30;
+
+ baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== "undefined" ? baseOptions.columnWidth : 50;
+
+ /**
+ * @ngdoc property
+ * @name maxVisibleColumnCount
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 200
+ *
+ */
+ baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== "undefined" ? baseOptions.maxVisibleColumnCount : 200;
+
+ /**
+ * @ngdoc property
+ * @name virtualizationThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Turn virtualization on when number of data elements goes over this number, defaults to 20
+ */
+ baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== "undefined" ? baseOptions.virtualizationThreshold : 20;
+
+ /**
+ * @ngdoc property
+ * @name columnVirtualizationThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Turn virtualization on when number of columns goes over this number, defaults to 10
+ */
+ baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== "undefined" ? baseOptions.columnVirtualizationThreshold : 10;
+
+ /**
+ * @ngdoc property
+ * @name excessRows
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.
+ * Defaults to 4
+ */
+ baseOptions.excessRows = typeof(baseOptions.excessRows) !== "undefined" ? baseOptions.excessRows : 4;
+ /**
+ * @ngdoc property
+ * @name scrollThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 4
+ */
+ baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== "undefined" ? baseOptions.scrollThreshold : 4;
+
+ /**
+ * @ngdoc property
+ * @name excessColumns
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.
+ * Defaults to 4
+ */
+ baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== "undefined" ? baseOptions.excessColumns : 4;
+ /**
+ * @ngdoc property
+ * @name horizontalScrollThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 4
+ */
+ baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== "undefined" ? baseOptions.horizontalScrollThreshold : 2;
+
+
+ /**
+ * @ngdoc property
+ * @name aggregationCalcThrottle
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms
+ */
+ baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== "undefined" ? baseOptions.aggregationCalcThrottle : 500;
+
+ /**
+ * @ngdoc property
+ * @name wheelScrollThrottle
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms
+ */
+ baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== "undefined" ? baseOptions.wheelScrollThrottle : 70;
+
+
+ /**
+ * @ngdoc property
+ * @name scrollDebounce
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to debounce scroll events, defaults to 300ms
+ */
+ baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== "undefined" ? baseOptions.scrollDebounce : 300;
+
+ /**
+ * @ngdoc boolean
+ * @name enableSorting
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting adds sort
+ * widgets to the column headers, allowing sorting of the data for the entire grid.
+ * Sorting can then be disabled / enabled on individual columns using the columnDefs,
+ * if it set, it will override GridOptions enableSorting setting.
+ */
+ baseOptions.enableSorting = baseOptions.enableSorting !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name enableFiltering
+ * @propertyOf ui.grid.class:GridOptions
+ * @description False by default. When enabled, this setting adds filter
+ * boxes to each column header, allowing filtering within the column for the entire grid.
+ * Filtering can then be disabled on individual columns using the columnDefs.
+ */
+ baseOptions.enableFiltering = baseOptions.enableFiltering === true;
+
+ /**
+ * @ngdoc boolean
+ * @name enableColumnMenus
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting displays a column
+ * menu within each column.
+ */
+ baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name enableVerticalScrollbar
+ * @propertyOf ui.grid.class:GridOptions
+ * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.
+ * This settings controls the vertical scrollbar for the grid.
+ * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
+ */
+ baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== "undefined" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;
+
+ /**
+ * @ngdoc boolean
+ * @name enableHorizontalScrollbar
+ * @propertyOf ui.grid.class:GridOptions
+ * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.
+ * This settings controls the horizontal scrollbar for the grid.
+ * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
+ */
+ baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== "undefined" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;
+
+ /**
+ * @ngdoc boolean
+ * @name enableMinHeightCheck
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display
+ * at least one row of data. If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number
+ * of rows.
+ */
+ baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name minimumColumnSize
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Columns can't be smaller than this, defaults to 10 pixels
+ */
+ baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== "undefined" ? baseOptions.minimumColumnSize : 10;
+
+ /**
+ * @ngdoc function
+ * @name rowEquality
+ * @methodOf ui.grid.class:GridOptions
+ * @description By default, rows are compared using object equality. This option can be overridden
+ * to compare on any data item property or function
+ * @param {object} entityA First Data Item to compare
+ * @param {object} entityB Second Data Item to compare
+ */
+ baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {
+ return entityA === entityB;
+ };
+
+ /**
+ * @ngdoc string
+ * @name headerTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Null by default. When provided, this setting uses a custom header
+ * template, rather than the default template. Can be set to either the name of a template file:
+ * <pre> $scope.gridOptions.headerTemplate = 'header_template.html';</pre>
+ * inline html
+ * <pre> $scope.gridOptions.headerTemplate = '<div class="ui-grid-top-panel" style="text-align: center">I am a Custom Grid Header</div>'</pre>
+ * or the id of a precompiled template (TBD how to use this).
+ * </br>Refer to the custom header tutorial for more information.
+ * If you want no header at all, you can set to an empty div:
+ * <pre> $scope.gridOptions.headerTemplate = '<div></div>';</pre>
+ *
+ * If you want to only have a static header, then you can set to static content. If
+ * you want to tailor the existing column headers, then you should look at the
+ * current 'ui-grid-header.html' template in github as your starting point.
+ *
+ */
+ baseOptions.headerTemplate = baseOptions.headerTemplate || null;
+
+ /**
+ * @ngdoc string
+ * @name footerTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) ui-grid/ui-grid-footer by default. This footer shows the per-column
+ * aggregation totals.
+ * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html
+ * <pre>'<div class="ui-grid-bottom-panel" style="text-align: center">I am a Custom Grid Footer</div>'</pre>, or the id
+ * of a precompiled template (TBD how to use this). Refer to the custom footer tutorial for more information.
+ */
+ baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';
+
+ /**
+ * @ngdoc string
+ * @name gridFooterTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the
+ * total items at the bottom of the grid, and the selected items if selection is enabled.
+ */
+ baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';
+
+ /**
+ * @ngdoc string
+ * @name rowTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a
+ * custom row template. Can be set to either the name of a template file:
+ * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>
+ * inline html
+ * <pre> $scope.gridOptions.rowTemplate = '<div style="background-color: aquamarine" ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ui-grid-cell></div>';</pre>
+ * or the id of a precompiled template (TBD how to use this) can be provided.
+ * </br>Refer to the custom row template tutorial for more information.
+ */
+ baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';
+
+ /**
+ * @ngdoc string
+ * @name gridMenuTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description 'ui-grid/uiGridMenu' by default. When provided, this setting uses a
+ * custom grid menu template.
+ */
+ baseOptions.gridMenuTemplate = baseOptions.gridMenuTemplate || 'ui-grid/uiGridMenu';
+
+ /**
+ * @ngdoc object
+ * @name appScopeProvider
+ * @propertyOf ui.grid.class:GridOptions
+ * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope
+ * this property allows you to assign any reference you want to grid.appScope
+ */
+ baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;
+
+ return baseOptions;
+ }
+ };
+
+
+}]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridRenderContainer
+ * @description The grid has render containers, allowing the ability to have pinned columns. If the grid
+ * is right-to-left then there may be a right render container, if left-to-right then there may
+ * be a left render container. There is always a body render container.
+ * @param {string} name The name of the render container ('body', 'left', or 'right')
+ * @param {Grid} grid the grid the render container is in
+ * @param {object} options the render container options
+ */
+.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
+ function GridRenderContainer(name, grid, options) {
+ var self = this;
+
+ // if (gridUtil.type(grid) !== 'Grid') {
+ // throw new Error('Grid argument is not a Grid object');
+ // }
+
+ self.name = name;
+
+ self.grid = grid;
+
+ // self.rowCache = [];
+ // self.columnCache = [];
+
+ self.visibleRowCache = [];
+ self.visibleColumnCache = [];
+
+ self.renderedRows = [];
+ self.renderedColumns = [];
+
+ self.prevScrollTop = 0;
+ self.prevScrolltopPercentage = 0;
+ self.prevRowScrollIndex = 0;
+
+ self.prevScrollLeft = 0;
+ self.prevScrollleftPercentage = 0;
+ self.prevColumnScrollIndex = 0;
+
+ self.columnStyles = "";
+
+ self.viewportAdjusters = [];
+
+ /**
+ * @ngdoc boolean
+ * @name hasHScrollbar
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container has a horizontal scrollbar
+ */
+ self.hasHScrollbar = false;
+
+ /**
+ * @ngdoc boolean
+ * @name hasVScrollbar
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container has a vertical scrollbar
+ */
+ self.hasVScrollbar = false;
+
+ /**
+ * @ngdoc boolean
+ * @name canvasHeightShouldUpdate
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container should recalculate the canvas size
+ */
+ self.canvasHeightShouldUpdate = true;
+
+ /**
+ * @ngdoc boolean
+ * @name canvasHeight
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description last calculated canvas height value
+ */
+ self.$$canvasHeight = 0;
+
+ if (options && angular.isObject(options)) {
+ angular.extend(self, options);
+ }
+
+ grid.registerStyleComputation({
+ priority: 5,
+ func: function () {
+ self.updateColumnWidths();
+ return self.columnStyles;
+ }
+ });
+ }
+
+
+ GridRenderContainer.prototype.reset = function reset() {
+ // this.rowCache.length = 0;
+ // this.columnCache.length = 0;
+
+ this.visibleColumnCache.length = 0;
+ this.visibleRowCache.length = 0;
+
+ this.renderedRows.length = 0;
+ this.renderedColumns.length = 0;
+ };
+
+ // TODO(c0bra): calculate size?? Should this be in a stackable directive?
+
+
+ GridRenderContainer.prototype.containsColumn = function (col) {
+ return this.visibleColumnCache.indexOf(col) !== -1;
+ };
+
+ GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {
+ var self = this;
+ var minRows = 0;
+ var rowAddedHeight = 0;
+ var viewPortHeight = self.getViewportHeight();
+ for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {
+ rowAddedHeight += self.visibleRowCache[i].height;
+ minRows++;
+ }
+ return minRows;
+ };
+
+ GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {
+ var self = this;
+ var viewportWidth = this.getViewportWidth();
+
+ var min = 0;
+ var totalWidth = 0;
+ // self.columns.forEach(function(col, i) {
+ for (var i = 0; i < self.visibleColumnCache.length; i++) {
+ var col = self.visibleColumnCache[i];
+
+ if (totalWidth < viewportWidth) {
+ totalWidth += col.drawnWidth ? col.drawnWidth : 0;
+ min++;
+ }
+ else {
+ var currWidth = 0;
+ for (var j = i; j >= i - min; j--) {
+ currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;
+ }
+ if (currWidth < viewportWidth) {
+ min++;
+ }
+ }
+ }
+
+ return min;
+ };
+
+ GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {
+ return this.visibleRowCache.length;
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerViewportAdjuster
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Registers an adjuster to the render container's available width or height. Adjusters are used
+ * to tell the render container that there is something else consuming space, and to adjust it's size
+ * appropriately.
+ * @param {function} func the adjuster function we want to register
+ */
+
+ GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
+ this.viewportAdjusters.push(func);
+ };
+
+ /**
+ * @ngdoc function
+ * @name removeViewportAdjuster
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Removes an adjuster, should be used when your element is destroyed
+ * @param {function} func the adjuster function we want to remove
+ */
+ GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {
+ var idx = this.viewportAdjusters.indexOf(func);
+
+ if (idx > -1) {
+ this.viewportAdjusters.splice(idx, 1);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name getViewportAdjustment
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Gets the adjustment based on the viewportAdjusters.
+ * @returns {object} a hash of { height: x, width: y }. Usually the values will be negative
+ */
+ GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {
+ var self = this;
+
+ var adjustment = { height: 0, width: 0 };
+
+ self.viewportAdjusters.forEach(function (func) {
+ adjustment = func.call(this, adjustment);
+ });
+
+ return adjustment;
+ };
+
+ GridRenderContainer.prototype.getMargin = function getMargin(side) {
+ var self = this;
+
+ var amount = 0;
+
+ self.viewportAdjusters.forEach(function (func) {
+ var adjustment = func.call(this, { height: 0, width: 0 });
+
+ if (adjustment.side && adjustment.side === side) {
+ amount += adjustment.width * -1;
+ }
+ });
+
+ return amount;
+ };
+
+ GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {
+ var self = this;
+
+ var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;
+
+ var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;
+
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortHeight = viewPortHeight + adjustment.height;
+
+ return viewPortHeight;
+ };
+
+ GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {
+ var self = this;
+
+ var viewportWidth = self.grid.gridWidth;
+
+ //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;
+ //}
+
+ // var viewportWidth = 0;\
+ // self.visibleColumnCache.forEach(function (column) {
+ // viewportWidth += column.drawnWidth;
+ // });
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewportWidth = viewportWidth + adjustment.width;
+
+ return viewportWidth;
+ };
+
+ GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
+ var self = this;
+
+ var viewportWidth = this.getViewportWidth();
+
+ //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;
+ //}
+
+ // var adjustment = self.getViewportAdjustment();
+ // viewPortWidth = viewPortWidth + adjustment.width;
+
+ return viewportWidth;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getCanvasHeight
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Returns the total canvas height. Only recalculates if canvasHeightShouldUpdate = false
+ * @returns {number} total height of all the visible rows in the container
+ */
+ GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {
+ var self = this;
+
+ if (!self.canvasHeightShouldUpdate) {
+ return self.$$canvasHeight;
+ }
+
+ var oldCanvasHeight = self.$$canvasHeight;
+
+ self.$$canvasHeight = 0;
+
+ self.visibleRowCache.forEach(function(row){
+ self.$$canvasHeight += row.height;
+ });
+
+
+ self.canvasHeightShouldUpdate = false;
+
+ self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);
+
+ return self.$$canvasHeight;
+ };
+
+ GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {
+ return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight !== 0 ? this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight : -1;
+ };
+
+ GridRenderContainer.prototype.getHorizontalScrollLength = function getHorizontalScrollLength() {
+ return this.getCanvasWidth() - this.getViewportWidth() + this.grid.scrollbarWidth !== 0 ? this.getCanvasWidth() - this.getViewportWidth() + this.grid.scrollbarWidth : -1;
+ };
+
+ GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {
+ var self = this;
+
+ var ret = self.canvasWidth;
+
+ return ret;
+ };
+
+ GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {
+ this.renderedRows.length = newRows.length;
+ for (var i = 0; i < newRows.length; i++) {
+ this.renderedRows[i] = newRows[i];
+ }
+ };
+
+ GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {
+ var self = this;
+
+ // OLD:
+ this.renderedColumns.length = newColumns.length;
+ for (var i = 0; i < newColumns.length; i++) {
+ this.renderedColumns[i] = newColumns[i];
+ }
+
+ this.updateColumnOffset();
+ };
+
+ GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {
+ // Calculate the width of the columns on the left side that are no longer rendered.
+ // That will be the offset for the columns as we scroll horizontally.
+ var hiddenColumnsWidth = 0;
+ for (var i = 0; i < this.currentFirstColumn; i++) {
+ hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;
+ }
+
+ this.columnOffset = hiddenColumnsWidth;
+ };
+
+ GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {
+ var vertScrollPercentage = -1;
+
+ if (newScrollTop !== this.prevScrollTop) {
+ var yDiff = newScrollTop - this.prevScrollTop;
+
+ if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }
+ if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }
+
+ var vertScrollLength = this.getVerticalScrollLength();
+
+ vertScrollPercentage = newScrollTop / vertScrollLength;
+
+ // console.log('vert', vertScrollPercentage, newScrollTop, vertScrollLength);
+
+ if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }
+ if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }
+
+ this.adjustScrollVertical(newScrollTop, vertScrollPercentage);
+ return vertScrollPercentage;
+ }
+ };
+
+ GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft){
+ var horizScrollPercentage = -1;
+
+ // Handle RTL here
+
+ if (newScrollLeft !== this.prevScrollLeft) {
+ var xDiff = newScrollLeft - this.prevScrollLeft;
+
+ if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }
+ if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }
+
+ var horizScrollLength = this.getHorizontalScrollLength();
+ if (horizScrollLength !== 0) {
+ horizScrollPercentage = newScrollLeft / horizScrollLength;
+ }
+ else {
+ horizScrollPercentage = 0;
+ }
+
+ this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);
+ return horizScrollPercentage;
+ }
+ };
+
+ GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {
+ if (this.prevScrollTop === scrollTop && !force) {
+ return;
+ }
+
+ if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {
+ scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;
+ }
+
+ this.adjustRows(scrollTop, scrollPercentage, false);
+
+ this.prevScrollTop = scrollTop;
+ this.prevScrolltopPercentage = scrollPercentage;
+
+ this.grid.queueRefresh();
+ };
+
+ GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {
+ if (this.prevScrollLeft === scrollLeft && !force) {
+ return;
+ }
+
+ if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {
+ scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;
+ }
+
+ this.adjustColumns(scrollLeft, scrollPercentage);
+
+ this.prevScrollLeft = scrollLeft;
+ this.prevScrollleftPercentage = scrollPercentage;
+
+ this.grid.queueRefresh();
+ };
+
+ GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {
+ var self = this;
+
+ var minRows = self.minRowsToRender();
+
+ var rowCache = self.visibleRowCache;
+
+ var maxRowIndex = rowCache.length - minRows;
+
+ // console.log('scroll%1', scrollPercentage);
+
+ // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided
+ if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {
+ scrollPercentage = scrollTop / self.getVerticalScrollLength();
+ }
+
+ var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));
+
+ // console.log('maxRowIndex / scroll%', maxRowIndex, scrollPercentage, rowIndex);
+
+ // Define a max row index that we can't scroll past
+ if (rowIndex > maxRowIndex) {
+ rowIndex = maxRowIndex;
+ }
+
+ var newRange = [];
+ if (rowCache.length > self.grid.options.virtualizationThreshold) {
+ if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {
+ // Have we hit the threshold going down?
+ if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
+ return;
+ }
+ //Have we hit the threshold going up?
+ if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
+ return;
+ }
+ }
+ var rangeStart = {};
+ var rangeEnd = {};
+
+ rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);
+ rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);
+
+ newRange = [rangeStart, rangeEnd];
+ }
+ else {
+ var maxLen = self.visibleRowCache.length;
+ newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];
+ }
+
+ self.updateViewableRowRange(newRange);
+
+ self.prevRowScrollIndex = rowIndex;
+ };
+
+ GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {
+ var self = this;
+
+ var minCols = self.minColumnsToRender();
+
+ var columnCache = self.visibleColumnCache;
+ var maxColumnIndex = columnCache.length - minCols;
+
+ // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided
+ if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {
+ scrollPercentage = scrollLeft / self.getHorizontalScrollLength();
+ }
+
+ var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));
+
+ // Define a max row index that we can't scroll past
+ if (colIndex > maxColumnIndex) {
+ colIndex = maxColumnIndex;
+ }
+
+ var newRange = [];
+ if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {
+ /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position
+ * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it
+ // Have we hit the threshold going down?
+ if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
+ return;
+ }
+ //Have we hit the threshold going up?
+ if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
+ return;
+ }*/
+
+ var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);
+ var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);
+
+ newRange = [rangeStart, rangeEnd];
+ }
+ else {
+ var maxLen = self.visibleColumnCache.length;
+
+ newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];
+ }
+
+ self.updateViewableColumnRange(newRange);
+
+ self.prevColumnScrollIndex = colIndex;
+ };
+
+ // Method for updating the visible rows
+ GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {
+ // Slice out the range of rows from the data
+ // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);
+ var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);
+
+ // Define the top-most rendered row
+ this.currentTopRow = renderedRange[0];
+
+ this.setRenderedRows(rowArr);
+ };
+
+ // Method for updating the visible columns
+ GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {
+ // Slice out the range of rows from the data
+ // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);
+ var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);
+
+ // Define the left-most rendered columns
+ this.currentFirstColumn = renderedRange[0];
+
+ this.setRenderedColumns(columnArr);
+ };
+
+ GridRenderContainer.prototype.headerCellWrapperStyle = function () {
+ var self = this;
+
+ if (self.currentFirstColumn !== 0) {
+ var offset = self.columnOffset;
+
+ if (self.grid.isRTL()) {
+ return { 'margin-right': offset + 'px' };
+ }
+ else {
+ return { 'margin-left': offset + 'px' };
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * @ngdoc boolean
+ * @name updateColumnWidths
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description Determine the appropriate column width of each column across all render containers.
+ *
+ * Column width is easy when each column has a specified width. When columns are variable width (i.e.
+ * have an * or % of the viewport) then we try to calculate so that things fit in. The problem is that
+ * we have multiple render containers, and we don't want one render container to just take the whole viewport
+ * when it doesn't need to - we want things to balance out across the render containers.
+ *
+ * To do this, we use this method to calculate all the renderContainers, recognising that in a given render
+ * cycle it'll get called once per render container, so it needs to return the same values each time.
+ *
+ * The constraints on this method are therefore:
+ * - must return the same value when called multiple times, to do this it needs to rely on properties of the
+ * columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)
+ *
+ * The general logic of this method is:
+ * - calculate our total available width
+ * - look at all the columns across all render containers, and work out which have widths and which have
+ * constraints such as % or * or something else
+ * - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array
+ * - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max
+ * - for those with manual width (in pixels) we set the drawnWidth to the specified width
+ * - we end up with an asterisks array still to process
+ * - we look at our remaining width. If it's greater than zero, we divide it up among the asterisk columns, then process
+ * them for min and max width constraints
+ * - if it's zero or less, we set the asterisk columns to their minimum widths
+ * - we use parseInt quite a bit, as we try to make all our column widths integers
+ */
+ GridRenderContainer.prototype.updateColumnWidths = function () {
+ var self = this;
+
+ var asterisksArray = [],
+ asteriskNum = 0,
+ usedWidthSum = 0,
+ ret = '';
+
+ // Get the width of the viewport
+ var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;
+
+ // get all the columns across all render containers, we have to calculate them all or one render container
+ // could consume the whole viewport
+ var columnCache = [];
+ angular.forEach(self.grid.renderContainers, function( container, name){
+ columnCache = columnCache.concat(container.visibleColumnCache);
+ });
+
+ // look at each column, process any manual values or %, put the * into an array to look at later
+ columnCache.forEach(function(column, i) {
+ var width = 0;
+ // Skip hidden columns
+ if (!column.visible) { return; }
+
+ if (angular.isNumber(column.width)) {
+ // pixel width, set to this value
+ width = parseInt(column.width, 10);
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+
+ } else if (gridUtil.endsWith(column.width, "%")) {
+ // percentage width, set to percentage of the viewport
+ width = parseFloat(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);
+
+ if ( width > column.maxWidth ){
+ width = column.maxWidth;
+ }
+
+ if ( width < column.minWidth ){
+ width = column.minWidth;
+ }
+
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+ } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {
+ // is an asterisk column, the gridColumn already checked the string consists only of '****'
+ asteriskNum = asteriskNum + column.width.length;
+ asterisksArray.push(column);
+ }
+ });
+
+ // Get the remaining width (available width subtracted by the used widths sum)
+ var remainingWidth = availableWidth - usedWidthSum;
+
+ var i, column, colWidth;
+
+ if (asterisksArray.length > 0) {
+ // the width that each asterisk value would be assigned (this can be negative)
+ var asteriskVal = remainingWidth / asteriskNum;
+
+ asterisksArray.forEach(function( column ){
+ var width = parseInt(column.width.length * asteriskVal, 10);
+
+ if ( width > column.maxWidth ){
+ width = column.maxWidth;
+ }
+
+ if ( width < column.minWidth ){
+ width = column.minWidth;
+ }
+
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+ });
+ }
+
+ // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
+ // calculated widths would have the grid narrower than the available space,
+ // dole the remainder out one by one to make everything fit
+ var processColumnUpwards = function(column){
+ if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
+ column.drawnWidth++;
+ usedWidthSum++;
+ leftoverWidth--;
+ columnsToChange = true;
+ }
+ };
+
+ var leftoverWidth = availableWidth - usedWidthSum;
+ var columnsToChange = true;
+
+ while (leftoverWidth > 0 && columnsToChange) {
+ columnsToChange = false;
+ asterisksArray.forEach(processColumnUpwards);
+ }
+
+ // We can end up with too much width even though some columns aren't at their max width, in this situation
+ // we can trim the columns a little
+ var processColumnDownwards = function(column){
+ if ( column.drawnWidth > column.minWidth && excessWidth > 0) {
+ column.drawnWidth--;
+ usedWidthSum--;
+ excessWidth--;
+ columnsToChange = true;
+ }
+ };
+
+ var excessWidth = usedWidthSum - availableWidth;
+ columnsToChange = true;
+
+ while (excessWidth > 0 && columnsToChange) {
+ columnsToChange = false;
+ asterisksArray.forEach(processColumnDownwards);
+ }
+
+
+ // all that was across all the renderContainers, now we need to work out what that calculation decided for
+ // our renderContainer
+ var canvasWidth = 0;
+ self.visibleColumnCache.forEach(function(column){
+ if ( column.visible ){
+ canvasWidth = canvasWidth + column.drawnWidth;
+ }
+ });
+
+ // Build the CSS
+ columnCache.forEach(function (column) {
+ ret = ret + column.getColClassDefinition();
+ });
+
+ self.canvasWidth = canvasWidth;
+
+ // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
+ // return ret;
+
+ // Set this render container's column styles so they can be used in style computation
+ this.columnStyles = ret;
+ };
+
+ GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {
+ return this.grid.options.enableHorizontalScrollbar && !this.hasHScrollbar && !this.grid.disableScrolling;
+ };
+
+ GridRenderContainer.prototype.getViewportStyle = function () {
+ var self = this;
+ var styles = {};
+
+ self.hasHScrollbar = false;
+ self.hasVScrollbar = false;
+
+ if (self.grid.disableScrolling) {
+ styles['overflow-x'] = 'hidden';
+ styles['overflow-y'] = 'hidden';
+ return styles;
+ }
+
+ if (self.name === 'body') {
+ self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ if (!self.grid.isRTL()) {
+ if (!self.grid.hasRightContainerColumns()) {
+ self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ }
+ }
+ else {
+ if (!self.grid.hasLeftContainerColumns()) {
+ self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ }
+ }
+ }
+ else if (self.name === 'left') {
+ self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
+ }
+ else {
+ self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
+ }
+
+ styles['overflow-x'] = self.hasHScrollbar ? 'scroll' : 'hidden';
+ styles['overflow-y'] = self.hasVScrollbar ? 'scroll' : 'hidden';
+
+
+ return styles;
+
+
+ };
+
+ return GridRenderContainer;
+}]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('GridRow', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridRow
+ * @description GridRow is the viewModel for one logical row on the grid. A grid Row is not necessarily a one-to-one
+ * relation to gridOptions.data.
+ * @param {object} entity the array item from GridOptions.data
+ * @param {number} index the current position of the row in the array
+ * @param {Grid} reference to the parent grid
+ */
+ function GridRow(entity, index, grid) {
+
+ /**
+ * @ngdoc object
+ * @name grid
+ * @propertyOf ui.grid.class:GridRow
+ * @description A reference back to the grid
+ */
+ this.grid = grid;
+
+ /**
+ * @ngdoc object
+ * @name entity
+ * @propertyOf ui.grid.class:GridRow
+ * @description A reference to an item in gridOptions.data[]
+ */
+ this.entity = entity;
+
+ /**
+ * @ngdoc object
+ * @name uid
+ * @propertyOf ui.grid.class:GridRow
+ * @description UniqueId of row
+ */
+ this.uid = gridUtil.nextUid();
+
+ /**
+ * @ngdoc object
+ * @name visible
+ * @propertyOf ui.grid.class:GridRow
+ * @description If true, the row will be rendered
+ */
+ // Default to true
+ this.visible = true;
+
+
+ this.$$height = grid.options.rowHeight;
+
+ }
+
+ /**
+ * @ngdoc object
+ * @name height
+ * @propertyOf ui.grid.class:GridRow
+ * @description height of each individual row. changing the height will flag all
+ * row renderContainers to recalculate their canvas height
+ */
+ Object.defineProperty(GridRow.prototype, 'height', {
+ get: function() {
+ return this.$$height;
+ },
+ set: function(height) {
+ if (height !== this.$$height) {
+ this.grid.updateCanvasHeight();
+ this.$$height = height;
+ }
+ }
+ });
+
+ /**
+ * @ngdoc function
+ * @name getQualifiedColField
+ * @methodOf ui.grid.class:GridRow
+ * @description returns the qualified field name as it exists on scope
+ * ie: row.entity.fieldA
+ * @param {GridCol} col column instance
+ * @returns {string} resulting name that can be evaluated on scope
+ */
+ GridRow.prototype.getQualifiedColField = function(col) {
+ return 'row.' + this.getEntityQualifiedColField(col);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getEntityQualifiedColField
+ * @methodOf ui.grid.class:GridRow
+ * @description returns the qualified field name minus the row path
+ * ie: entity.fieldA
+ * @param {GridCol} col column instance
+ * @returns {string} resulting name that can be evaluated against a row
+ */
+ GridRow.prototype.getEntityQualifiedColField = function(col) {
+ var base = 'entity';
+ if ( col.field === uiGridConstants.ENTITY_BINDING ) {
+ return base;
+ }
+ return gridUtil.preEval(base + '.' + col.field);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Sets an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
+ *
+ * This method can be called from the api, passing in the gridRow we want
+ * altered. It should really work by calling gridRow.setRowInvisible, but that's
+ * not the way I coded it, and too late to change now. Changed to just call
+ * the internal function row.setThisRowInvisible().
+ *
+ * @param {GridRow} row the row we want to set to invisible
+ *
+ */
+ GridRow.prototype.setRowInvisible = function ( row ) {
+ if (row && row.setThisRowInvisible){
+ row.setThisRowInvisible( 'user' );
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Clears an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
+ *
+ * This method can be called from the api, passing in the gridRow we want
+ * altered. It should really work by calling gridRow.clearRowInvisible, but that's
+ * not the way I coded it, and too late to change now. Changed to just call
+ * the internal function row.clearThisRowInvisible().
+ *
+ * @param {GridRow} row the row we want to clear the invisible flag
+ *
+ */
+ GridRow.prototype.clearRowInvisible = function ( row ) {
+ if (row && row.clearThisRowInvisible){
+ row.clearThisRowInvisible( 'user' );
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setThisRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Sets an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility
+ *
+ * @param {string} reason the reason (usually the module) for the row to be invisible.
+ * E.g. grouping, user, filter
+ * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
+ */
+ GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {
+ if ( !this.invisibleReason ){
+ this.invisibleReason = {};
+ }
+ this.invisibleReason[reason] = true;
+ this.evaluateRowVisibility( fromRowsProcessor);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Clears any override on the row visibility, returning it
+ * to normal visibility calculations. Emits the rowsVisibleChanged
+ * event
+ *
+ * @param {string} reason the reason (usually the module) for the row to be invisible.
+ * E.g. grouping, user, filter
+ * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
+ */
+ GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {
+ if (typeof(this.invisibleReason) !== 'undefined' ) {
+ delete this.invisibleReason[reason];
+ }
+ this.evaluateRowVisibility( fromRowsProcessor );
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name evaluateRowVisibility
+ * @methodOf ui.grid.class:GridRow
+ * @description Determines whether the row should be visible based on invisibleReason,
+ * and if it changes the row visibility, then emits the rowsVisibleChanged event.
+ *
+ * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.
+ * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the
+ * row processor does that already
+ */
+ GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {
+ var newVisibility = true;
+ if ( typeof(this.invisibleReason) !== 'undefined' ){
+ angular.forEach(this.invisibleReason, function( value, key ){
+ if ( value ){
+ newVisibility = false;
+ }
+ });
+ }
+
+ if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ){
+ this.visible = newVisibility;
+ if ( !fromRowProcessor ){
+ this.grid.queueGridRefresh();
+ this.grid.api.core.raise.rowsVisibleChanged(this);
+ }
+ }
+ };
+
+
+ return GridRow;
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridRowColumn
+ * @param {GridRow} row The row for this pair
+ * @param {GridColumn} column The column for this pair
+ * @description A row and column pair that represents the intersection of these two entities.
+ * Must be instantiated as a constructor using the `new` keyword.
+ */
+ angular.module('ui.grid')
+ .factory('GridRowColumn', ['$parse', '$filter',
+ function GridRowColumnFactory($parse, $filter){
+ var GridRowColumn = function GridRowColumn(row, col) {
+ if ( !(this instanceof GridRowColumn)){
+ throw "Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";
+ }
+
+ /**
+ * @ngdoc object
+ * @name row
+ * @propertyOf ui.grid.class:GridRowColumn
+ * @description {@link ui.grid.class:GridRow }
+ */
+ this.row = row;
+ /**
+ * @ngdoc object
+ * @name col
+ * @propertyOf ui.grid.class:GridRowColumn
+ * @description {@link ui.grid.class:GridColumn }
+ */
+ this.col = col;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getIntersectionValueRaw
+ * @methodOf ui.grid.class:GridRowColumn
+ * @description Gets the intersection of where the row and column meet.
+ * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
+ * If the column has a cellFilter this will NOT return the filtered value.
+ */
+ GridRowColumn.prototype.getIntersectionValueRaw = function(){
+ var getter = $parse(this.row.getEntityQualifiedColField(this.col));
+ var context = this.row;
+ return getter(context);
+ };
+ return GridRowColumn;
+ }
+ ]);
+})();
+
+(function () {
+ angular.module('ui.grid')
+ .factory('ScrollEvent', ['gridUtil', function (gridUtil) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:ScrollEvent
+ * @description Model for all scrollEvents
+ * @param {Grid} grid that owns the scroll event
+ * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null
+ * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null
+ * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName
+ */
+ function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {
+ var self = this;
+ if (!grid) {
+ throw new Error("grid argument is required");
+ }
+
+ /**
+ * @ngdoc object
+ * @name grid
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description A reference back to the grid
+ */
+ self.grid = grid;
+
+
+
+ /**
+ * @ngdoc object
+ * @name source
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources
+ */
+ self.source = source;
+
+
+ /**
+ * @ngdoc object
+ * @name noDelay
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description most scroll events from the mouse or trackpad require delay to operate properly
+ * set to false to eliminate delay. Useful for scroll events that the grid causes, such as scrolling to make a row visible.
+ */
+ self.withDelay = true;
+
+ self.sourceRowContainer = sourceRowContainer;
+ self.sourceColContainer = sourceColContainer;
+
+ self.newScrollLeft = null;
+ self.newScrollTop = null;
+ self.x = null;
+ self.y = null;
+
+ self.verticalScrollLength = -9999999;
+ self.horizontalScrollLength = -999999;
+
+
+ /**
+ * @ngdoc function
+ * @name fireThrottledScrollingEvent
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description fires a throttled event using grid.api.core.raise.scrollEvent
+ */
+ self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {
+ self.grid.scrollContainers(sourceContainerId, self);
+ }, self.grid.options.wheelScrollThrottle, {trailing: true});
+
+ }
+
+
+ /**
+ * @ngdoc function
+ * @name getNewScrollLeft
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description returns newScrollLeft property if available; calculates a new value if it isn't
+ */
+ ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){
+ var self = this;
+
+ if (!self.newScrollLeft){
+ var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
+
+ var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);
+
+ var scrollXPercentage;
+ if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {
+ scrollXPercentage = self.x.percentage;
+ }
+ else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {
+ scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;
+ }
+ else {
+ throw new Error("No percentage or pixel value provided for scroll event X axis");
+ }
+
+ return Math.max(0, scrollXPercentage * scrollWidth);
+ }
+
+ return self.newScrollLeft;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getNewScrollTop
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description returns newScrollTop property if available; calculates a new value if it isn't
+ */
+ ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){
+ var self = this;
+
+
+ if (!self.newScrollTop){
+ var scrollLength = rowContainer.getVerticalScrollLength();
+
+ var oldScrollTop = viewport[0].scrollTop;
+
+ var scrollYPercentage;
+ if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {
+ scrollYPercentage = self.y.percentage;
+ }
+ else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {
+ scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;
+ }
+ else {
+ throw new Error("No percentage or pixel value provided for scroll event Y axis");
+ }
+
+ return Math.max(0, scrollYPercentage * scrollLength);
+ }
+
+ return self.newScrollTop;
+ };
+
+ ScrollEvent.prototype.atTop = function(scrollTop) {
+ return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
+ };
+
+ ScrollEvent.prototype.atBottom = function(scrollTop) {
+ return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
+ };
+
+ ScrollEvent.prototype.atLeft = function(scrollLeft) {
+ return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);
+ };
+
+ ScrollEvent.prototype.atRight = function(scrollLeft) {
+ return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);
+ };
+
+
+ ScrollEvent.Sources = {
+ ViewPortScroll: 'ViewPortScroll',
+ RenderContainerMouseWheel: 'RenderContainerMouseWheel',
+ RenderContainerTouchMove: 'RenderContainerTouchMove',
+ Other: 99
+ };
+
+ return ScrollEvent;
+ }]);
+
+
+
+})();
+
+(function () {
+ 'use strict';
+ /**
+ * @ngdoc object
+ * @name ui.grid.service:gridClassFactory
+ *
+ * @description factory to return dom specific instances of a grid
+ *
+ */
+ angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',
+ function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @name createGrid
+ * @methodOf ui.grid.service:gridClassFactory
+ * @description Creates a new grid instance. Each instance will have a unique id
+ * @param {object} options An object map of options to pass into the created grid instance.
+ * @returns {Grid} grid
+ */
+ createGrid : function(options) {
+ options = (typeof(options) !== 'undefined') ? options : {};
+ options.id = gridUtil.newId();
+ var grid = new Grid(options);
+
+ // NOTE/TODO: rowTemplate should always be defined...
+ if (grid.options.rowTemplate) {
+ var rowTemplateFnPromise = $q.defer();
+ grid.getRowTemplateFn = rowTemplateFnPromise.promise;
+
+ gridUtil.getTemplate(grid.options.rowTemplate)
+ .then(
+ function (template) {
+ var rowTemplateFn = $compile(template);
+ rowTemplateFnPromise.resolve(rowTemplateFn);
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use row template '" + grid.options.rowTemplate + "'");
+ });
+ }
+
+ grid.registerColumnBuilder(service.defaultColumnBuilder);
+
+ // Row builder for custom row templates
+ grid.registerRowBuilder(service.rowTemplateAssigner);
+
+ // Reset all rows to visible initially
+ grid.registerRowsProcessor(function allRowsVisible(rows) {
+ rows.forEach(function (row) {
+ row.evaluateRowVisibility( true );
+ }, 50);
+
+ return rows;
+ });
+
+ grid.registerColumnsProcessor(function applyColumnVisibility(columns) {
+ columns.forEach(function (column) {
+ column.visible = angular.isDefined(column.colDef.visible) ? column.colDef.visible : true;
+ });
+
+ return columns;
+ }, 50);
+
+ grid.registerRowsProcessor(grid.searchRows, 100);
+
+ // Register the default row processor, it sorts rows by selected columns
+ if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {
+ grid.registerRowsProcessor(grid.options.externalSort, 200);
+ }
+ else {
+ grid.registerRowsProcessor(grid.sortByColumn, 200);
+ }
+
+ return grid;
+ },
+
+ /**
+ * @ngdoc function
+ * @name defaultColumnBuilder
+ * @methodOf ui.grid.service:gridClassFactory
+ * @description Processes designTime column definitions and applies them to col for the
+ * core grid features
+ * @param {object} colDef reference to column definition
+ * @param {GridColumn} col reference to gridCol
+ * @param {object} gridOptions reference to grid options
+ */
+ defaultColumnBuilder: function (colDef, col, gridOptions) {
+
+ var templateGetPromises = [];
+
+ // Abstracts the standard template processing we do for every template type.
+ var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {
+ if ( !colDef[templateType] ){
+ col[providedType] = defaultTemplate;
+ } else {
+ col[providedType] = colDef[templateType];
+ }
+
+ templateGetPromises.push(gridUtil.getTemplate(col[providedType])
+ .then(
+ function (template) {
+ if ( angular.isFunction(template) ) { template = template(); }
+ var tooltipCall = ( tooltipType === 'cellTooltip' ) ? 'col.cellTooltip(row,col)' : 'col.headerTooltip(col)';
+ if ( tooltipType && col[tooltipType] === false ){
+ template = template.replace(uiGridConstants.TOOLTIP, '');
+ } else if ( tooltipType && col[tooltipType] ){
+ template = template.replace(uiGridConstants.TOOLTIP, 'title="{{' + tooltipCall + ' CUSTOM_FILTERS }}"');
+ }
+
+ if ( filterType ){
+ col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {
+ return col[filterType] ? "|" + col[filterType] : "";
+ });
+ } else {
+ col[templateType] = template;
+ }
+ },
+ function (res) {
+ throw new Error("Couldn't fetch/use colDef." + templateType + " '" + colDef[templateType] + "'");
+ })
+ );
+
+ };
+
+
+ /**
+ * @ngdoc property
+ * @name cellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for each cell in this column. The default
+ * is ui-grid/uiGridCell. If you are using the cellNav feature, this template
+ * must contain a div that can receive focus.
+ *
+ */
+ processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );
+ col.cellTemplatePromise = templateGetPromises[0];
+
+ /**
+ * @ngdoc property
+ * @name headerCellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the header for this column. The default
+ * is ui-grid/uiGridHeaderCell
+ *
+ */
+ processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );
+
+ /**
+ * @ngdoc property
+ * @name footerCellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the footer for this column. The default
+ * is ui-grid/uiGridFooterCell
+ *
+ */
+ processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );
+
+ /**
+ * @ngdoc property
+ * @name filterHeaderTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the filter input. The default is ui-grid/ui-grid-filter
+ *
+ */
+ processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );
+
+ // Create a promise for the compiled element function
+ col.compiledElementFnDefer = $q.defer();
+
+ return $q.all(templateGetPromises);
+ },
+
+
+ rowTemplateAssigner: function rowTemplateAssigner(row) {
+ var grid = this;
+
+ // Row has no template assigned to it
+ if (!row.rowTemplate) {
+ // Use the default row template from the grid
+ row.rowTemplate = grid.options.rowTemplate;
+
+ // Use the grid's function for fetching the compiled row template function
+ row.getRowTemplateFn = grid.getRowTemplateFn;
+ }
+ // Row has its own template assigned
+ else {
+ // Create a promise for the compiled row template function
+ var perRowTemplateFnPromise = $q.defer();
+ row.getRowTemplateFn = perRowTemplateFnPromise.promise;
+
+ // Get the row template
+ gridUtil.getTemplate(row.rowTemplate)
+ .then(function (template) {
+ // Compile the template
+ var rowTemplateFn = $compile(template);
+
+ // Resolve the compiled template function promise
+ perRowTemplateFnPromise.resolve(rowTemplateFn);
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use row template '" + row.rowTemplate + "'");
+ });
+ }
+
+ return row.getRowTemplateFn;
+ }
+ };
+
+ //class definitions (moved to separate factories)
+
+ return service;
+ }]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+function escapeRegExp(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+}
+
+
+/**
+ * @ngdoc service
+ * @name ui.grid.service:rowSearcher
+ *
+ * @description Service for searching/filtering rows based on column value conditions.
+ */
+module.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {
+ var defaultCondition = uiGridConstants.filter.CONTAINS;
+
+ var rowSearcher = {};
+
+ /**
+ * @ngdoc function
+ * @name getTerm
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Get the term from a filter
+ * Trims leading and trailing whitespace
+ * @param {object} filter object to use
+ * @returns {object} Parsed term
+ */
+ rowSearcher.getTerm = function getTerm(filter) {
+ if (typeof(filter.term) === 'undefined') { return filter.term; }
+
+ var term = filter.term;
+
+ // Strip leading and trailing whitespace if the term is a string
+ if (typeof(term) === 'string') {
+ term = term.trim();
+ }
+
+ return term;
+ };
+
+ /**
+ * @ngdoc function
+ * @name stripTerm
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Remove leading and trailing asterisk (*) from the filter's term
+ * @param {object} filter object to use
+ * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
+ */
+ rowSearcher.stripTerm = function stripTerm(filter) {
+ var term = rowSearcher.getTerm(filter);
+
+ if (typeof(term) === 'string') {
+ return escapeRegExp(term.replace(/(^\*|\*$)/g, ''));
+ }
+ else {
+ return term;
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name guessCondition
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Guess the condition for a filter based on its term
+ * <br>
+ * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).
+ * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).
+ * @param {object} filter object to use
+ * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
+ */
+ rowSearcher.guessCondition = function guessCondition(filter) {
+ if (typeof(filter.term) === 'undefined' || !filter.term) {
+ return defaultCondition;
+ }
+
+ var term = rowSearcher.getTerm(filter);
+
+ if (/\*/.test(term)) {
+ var regexpFlags = '';
+ if (!filter.flags || !filter.flags.caseSensitive) {
+ regexpFlags += 'i';
+ }
+
+ var reText = term.replace(/(\\)?\*/g, function ($0, $1) { return $1 ? $0 : '[\\s\\S]*?'; });
+ return new RegExp('^' + reText + '$', regexpFlags);
+ }
+ // Otherwise default to default condition
+ else {
+ return defaultCondition;
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setupFilters
+ * @methodOf ui.grid.service:rowSearcher
+ * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),
+ * do all the parsing and pre-processing and store that data into a new filters object. The object
+ * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.
+ *
+ * We could use a forEach in here, since it's much less performance sensitive, but since we're using
+ * for loops everywhere else in this module...
+ *
+ * @param {array} filters the filters from the column (col.filters or [col.filter])
+ * @returns {array} An array of parsed/preprocessed filters
+ */
+ rowSearcher.setupFilters = function setupFilters( filters ){
+ var newFilters = [];
+
+ var filtersLength = filters.length;
+ for ( var i = 0; i < filtersLength; i++ ){
+ var filter = filters[i];
+
+ if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ){
+ var newFilter = {};
+
+ var regexpFlags = '';
+ if (!filter.flags || !filter.flags.caseSensitive) {
+ regexpFlags += 'i';
+ }
+
+ if ( !gridUtil.isNullOrUndefined(filter.term) ){
+ // it is possible to have noTerm.
+ if ( filter.rawTerm ){
+ newFilter.term = filter.term;
+ } else {
+ newFilter.term = rowSearcher.stripTerm(filter);
+ }
+ }
+ newFilter.noTerm = filter.noTerm;
+
+ if ( filter.condition ){
+ newFilter.condition = filter.condition;
+ } else {
+ newFilter.condition = rowSearcher.guessCondition(filter);
+ }
+
+ newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );
+
+ if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {
+ newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {
+ newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.CONTAINS) {
+ newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.EXACT) {
+ newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);
+ }
+
+ newFilters.push(newFilter);
+ }
+ }
+ return newFilters;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name runColumnFilter
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Runs a single pre-parsed filter against a cell, returning true
+ * if the cell matches that one filter.
+ *
+ * @param {Grid} grid the grid we're working against
+ * @param {GridRow} row the row we're matching against
+ * @param {GridCol} column the column that we're working against
+ * @param {object} filter the specific, preparsed, filter that we want to test
+ * @returns {boolean} true if we match (row stays visible)
+ */
+ rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {
+ // Cache typeof condition
+ var conditionType = typeof(filter.condition);
+
+ // Term to search for.
+ var term = filter.term;
+
+ // Get the column value for this row
+ var value;
+ if ( column.filterCellFiltered ){
+ value = grid.getCellDisplayValue(row, column);
+ } else {
+ value = grid.getCellValue(row, column);
+ }
+
+
+ // If the filter's condition is a RegExp, then use it
+ if (filter.condition instanceof RegExp) {
+ return filter.condition.test(value);
+ }
+
+ // If the filter's condition is a function, run it
+ if (conditionType === 'function') {
+ return filter.condition(term, value, row, column);
+ }
+
+ if (filter.startswithRE) {
+ return filter.startswithRE.test(value);
+ }
+
+ if (filter.endswithRE) {
+ return filter.endswithRE.test(value);
+ }
+
+ if (filter.containsRE) {
+ return filter.containsRE.test(value);
+ }
+
+ if (filter.exactRE) {
+ return filter.exactRE.test(value);
+ }
+
+ if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {
+ var regex = new RegExp('^' + term + '$');
+ return !regex.exec(value);
+ }
+
+ if (typeof(value) === 'number' && typeof(term) === 'string' ){
+ // if the term has a decimal in it, it comes through as '9\.4', we need to take out the \
+ // the same for negative numbers
+ // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?
+ var tempFloat = parseFloat(term.replace(/\\\./,'.').replace(/\\\-/,'-'));
+ if (!isNaN(tempFloat)) {
+ term = tempFloat;
+ }
+ }
+
+ if (filter.flags.date === true) {
+ value = new Date(value);
+ // If the term has a dash in it, it comes through as '\-' -- we need to take out the '\'.
+ term = new Date(term.replace(/\\/g, ''));
+ }
+
+ if (filter.condition === uiGridConstants.filter.GREATER_THAN) {
+ return (value > term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {
+ return (value >= term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.LESS_THAN) {
+ return (value < term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {
+ return (value <= term);
+ }
+
+ return true;
+ };
+
+
+ /**
+ * @ngdoc boolean
+ * @name useExternalFiltering
+ * @propertyOf ui.grid.class:GridOptions
+ * @description False by default. When enabled, this setting suppresses the internal filtering.
+ * All UI logic will still operate, allowing filter conditions to be set and modified.
+ *
+ * The external filter logic can listen for the `filterChange` event, which fires whenever
+ * a filter has been adjusted.
+ */
+ /**
+ * @ngdoc function
+ * @name searchColumn
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Process provided filters on provided column against a given row. If the row meets
+ * the conditions on all the filters, return true.
+ * @param {Grid} grid Grid to search in
+ * @param {GridRow} row Row to search on
+ * @param {GridCol} column Column with the filters to use
+ * @param {array} filters array of pre-parsed/preprocessed filters to apply
+ * @returns {boolean} Whether the column matches or not.
+ */
+ rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {
+ if (grid.options.useExternalFiltering) {
+ return true;
+ }
+
+ var filtersLength = filters.length;
+ for (var i = 0; i < filtersLength; i++) {
+ var filter = filters[i];
+
+ if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){
+ var ret = rowSearcher.runColumnFilter(grid, row, column, filter);
+ if (!ret) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name search
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Run a search across the given rows and columns, marking any rows that don't
+ * match the stored col.filters or col.filter as invisible.
+ * @param {Grid} grid Grid instance to search inside
+ * @param {Array[GridRow]} rows GridRows to filter
+ * @param {Array[GridColumn]} columns GridColumns with filters to process
+ */
+ rowSearcher.search = function search(grid, rows, columns) {
+ /*
+ * Added performance optimisations into this code base, as this logic creates deeply nested
+ * loops and is therefore very performance sensitive. In particular, avoiding forEach as
+ * this impacts some browser optimisers (particularly Chrome), using iterators instead
+ */
+
+ // Don't do anything if we weren't passed any rows
+ if (!rows) {
+ return;
+ }
+
+ // don't filter if filtering currently disabled
+ if (!grid.options.enableFiltering){
+ return rows;
+ }
+
+ // Build list of filters to apply
+ var filterData = [];
+
+ var colsLength = columns.length;
+
+ var hasTerm = function( filters ) {
+ var hasTerm = false;
+
+ filters.forEach( function (filter) {
+ if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){
+ hasTerm = true;
+ }
+ });
+
+ return hasTerm;
+ };
+
+ for (var i = 0; i < colsLength; i++) {
+ var col = columns[i];
+
+ if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {
+ filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );
+ }
+ }
+
+ if (filterData.length > 0) {
+ // define functions outside the loop, performance optimisation
+ var foreachRow = function(grid, row, col, filters){
+ if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {
+ row.visible = false;
+ }
+ };
+
+ var foreachFilterCol = function(grid, filterData){
+ var rowsLength = rows.length;
+ for ( var i = 0; i < rowsLength; i++){
+ foreachRow(grid, rows[i], filterData.col, filterData.filters);
+ }
+ };
+
+ // nested loop itself - foreachFilterCol, which in turn calls foreachRow
+ var filterDataLength = filterData.length;
+ for ( var j = 0; j < filterDataLength; j++){
+ foreachFilterCol( grid, filterData[j] );
+ }
+
+ if (grid.api.core.raise.rowsVisibleChanged) {
+ grid.api.core.raise.rowsVisibleChanged();
+ }
+
+ // drop any invisible rows
+ // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter
+ // rows = rows.filter(function(row){ return row.visible; });
+
+ }
+
+ return rows;
+ };
+
+ return rowSearcher;
+}]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+/**
+ * @ngdoc object
+ * @name ui.grid.class:rowSorter
+ * @description rowSorter provides the default sorting mechanisms,
+ * including guessing column types and applying appropriate sort
+ * algorithms
+ *
+ */
+
+module.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {
+ var currencyRegexStr =
+ '(' +
+ uiGridConstants.CURRENCY_SYMBOLS
+ .map(function (a) { return '\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)
+ .join('|') + // Join all the symbols together with |s
+ ')?';
+
+ // /^[-+]?[£$¤¥]?[\d,.]+%?$/
+ var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\d,.]+' + currencyRegexStr + '%?$');
+
+ var rowSorter = {
+ // Cache of sorting functions. Once we create them, we don't want to keep re-doing it
+ // this takes a piece of data from the cell and tries to determine its type and what sorting
+ // function to use for it
+ colSortFnCache: {}
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name guessSortFn
+ * @description Assigns a sort function to use based on the itemType in the column
+ * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'. And
+ * error will be thrown for any other type.
+ * @returns {function} a sort function that will sort that type
+ */
+ rowSorter.guessSortFn = function guessSortFn(itemType) {
+ switch (itemType) {
+ case "number":
+ return rowSorter.sortNumber;
+ case "numberStr":
+ return rowSorter.sortNumberStr;
+ case "boolean":
+ return rowSorter.sortBool;
+ case "string":
+ return rowSorter.sortAlpha;
+ case "date":
+ return rowSorter.sortDate;
+ case "object":
+ return rowSorter.basicSort;
+ default:
+ throw new Error('No sorting function found for type:' + itemType);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name handleNulls
+ * @description Sorts nulls and undefined to the bottom (top when
+ * descending). Called by each of the internal sorters before
+ * attempting to sort. Note that this method is available on the core api
+ * via gridApi.core.sortHandleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} null if there were no nulls/undefineds, otherwise returns
+ * a sort value that should be passed back from the sort function
+ */
+ rowSorter.handleNulls = function handleNulls(a, b) {
+ // We want to allow zero values and false values to be evaluated in the sort function
+ if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {
+ // We want to force nulls and such to the bottom when we sort... which effectively is "greater than"
+ if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {
+ return 0;
+ }
+ else if (!a && a !== 0 && a !== false) {
+ return 1;
+ }
+ else if (!b && b !== 0 && b !== false) {
+ return -1;
+ }
+ }
+ return null;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name basicSort
+ * @description Sorts any values that provide the < method, including strings
+ * or numbers. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.basicSort = function basicSort(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (a === b) {
+ return 0;
+ }
+ if (a < b) {
+ return -1;
+ }
+ return 1;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sortNumber
+ * @description Sorts numerical values. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortNumber = function sortNumber(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ return a - b;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sortNumberStr
+ * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).
+ * Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortNumberStr = function sortNumberStr(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ var numA, // The parsed number form of 'a'
+ numB, // The parsed number form of 'b'
+ badA = false,
+ badB = false;
+
+ // Try to parse 'a' to a float
+ numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
+
+ // If 'a' couldn't be parsed to float, flag it as bad
+ if (isNaN(numA)) {
+ badA = true;
+ }
+
+ // Try to parse 'b' to a float
+ numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
+
+ // If 'b' couldn't be parsed to float, flag it as bad
+ if (isNaN(numB)) {
+ badB = true;
+ }
+
+ // We want bad ones to get pushed to the bottom... which effectively is "greater than"
+ if (badA && badB) {
+ return 0;
+ }
+
+ if (badA) {
+ return 1;
+ }
+
+ if (badB) {
+ return -1;
+ }
+
+ return numA - numB;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sortAlpha
+ * @description Sorts string values. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortAlpha = function sortAlpha(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ var strA = a.toString().toLowerCase(),
+ strB = b.toString().toLowerCase();
+
+ return strA === strB ? 0 : strA.localeCompare(strB);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sortDate
+ * @description Sorts date values. Handles nulls and undefined through calling handleNulls.
+ * Handles date strings by converting to Date object if not already an instance of Date
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortDate = function sortDate(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (!(a instanceof Date)) {
+ a = new Date(a);
+ }
+ if (!(b instanceof Date)){
+ b = new Date(b);
+ }
+ var timeA = a.getTime(),
+ timeB = b.getTime();
+
+ return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sortBool
+ * @description Sorts boolean values, true is considered larger than false.
+ * Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortBool = function sortBool(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (a && b) {
+ return 0;
+ }
+
+ if (!a && !b) {
+ return 0;
+ }
+ else {
+ return a ? 1 : -1;
+ }
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name getSortFn
+ * @description Get the sort function for the column. Looks first in
+ * rowSorter.colSortFnCache using the column name, failing that it
+ * looks at col.sortingAlgorithm (and puts it in the cache), failing that
+ * it guesses the sort algorithm based on the data type.
+ *
+ * The cache currently seems a bit pointless, as none of the work we do is
+ * processor intensive enough to need caching. Presumably in future we might
+ * inspect the row data itself to guess the sort function, and in that case
+ * it would make sense to have a cache, the infrastructure is in place to allow
+ * that.
+ *
+ * @param {Grid} grid the grid to consider
+ * @param {GridCol} col the column to find a function for
+ * @param {array} rows an array of grid rows. Currently unused, but presumably in future
+ * we might inspect the rows themselves to decide what sort of data might be there
+ * @returns {function} the sort function chosen for the column
+ */
+ rowSorter.getSortFn = function getSortFn(grid, col, rows) {
+ var sortFn, item;
+
+ // See if we already figured out what to use to sort the column and have it in the cache
+ if (rowSorter.colSortFnCache[col.colDef.name]) {
+ sortFn = rowSorter.colSortFnCache[col.colDef.name];
+ }
+ // If the column has its OWN sorting algorithm, use that
+ else if (col.sortingAlgorithm !== undefined) {
+ sortFn = col.sortingAlgorithm;
+ rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;
+ }
+ // Always default to sortAlpha when sorting after a cellFilter
+ else if ( col.sortCellFiltered && col.cellFilter ){
+ sortFn = rowSorter.sortAlpha;
+ rowSorter.colSortFnCache[col.colDef.name] = sortFn;
+ }
+ // Try and guess what sort function to use
+ else {
+ // Guess the sort function
+ sortFn = rowSorter.guessSortFn(col.colDef.type);
+
+ // If we found a sort function, cache it
+ if (sortFn) {
+ rowSorter.colSortFnCache[col.colDef.name] = sortFn;
+ }
+ else {
+ // We assign the alpha sort because anything that is null/undefined will never get passed to
+ // the actual sorting function. It will get caught in our null check and returned to be sorted
+ // down to the bottom
+ sortFn = rowSorter.sortAlpha;
+ }
+ }
+
+ return sortFn;
+ };
+
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name prioritySort
+ * @description Used where multiple columns are present in the sort criteria,
+ * we determine which column should take precedence in the sort by sorting
+ * the columns based on their sort.priority
+ *
+ * @param {gridColumn} a column a
+ * @param {gridColumn} b column b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.prioritySort = function (a, b) {
+ // Both columns have a sort priority
+ if (a.sort.priority !== undefined && b.sort.priority !== undefined) {
+ // A is higher priority
+ if (a.sort.priority < b.sort.priority) {
+ return -1;
+ }
+ // Equal
+ else if (a.sort.priority === b.sort.priority) {
+ return 0;
+ }
+ // B is higher
+ else {
+ return 1;
+ }
+ }
+ // Only A has a priority
+ else if (a.sort.priority !== undefined) {
+ return -1;
+ }
+ // Only B has a priority
+ else if (b.sort.priority !== undefined) {
+ return 1;
+ }
+ // Neither has a priority
+ else {
+ return 0;
+ }
+ };
+
+
+ /**
+ * @ngdoc object
+ * @name useExternalSorting
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Prevents the internal sorting from executing. Events will
+ * still be fired when the sort changes, and the sort information on
+ * the columns will be updated, allowing an external sorter (for example,
+ * server sorting) to be implemented. Defaults to false.
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:rowSorter
+ * @name sort
+ * @description sorts the grid
+ * @param {Object} grid the grid itself
+ * @param {array} rows the rows to be sorted
+ * @param {array} columns the columns in which to look
+ * for sort criteria
+ * @returns {array} sorted rows
+ */
+ rowSorter.sort = function rowSorterSort(grid, rows, columns) {
+ // first make sure we are even supposed to do work
+ if (!rows) {
+ return;
+ }
+
+ if (grid.options.useExternalSorting){
+ return rows;
+ }
+
+ // Build the list of columns to sort by
+ var sortCols = [];
+ columns.forEach(function (col) {
+ if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
+ sortCols.push(col);
+ }
+ });
+
+ // Sort the "sort columns" by their sort priority
+ sortCols = sortCols.sort(rowSorter.prioritySort);
+
+ // Now rows to sort by, maintain original order
+ if (sortCols.length === 0) {
+ return rows;
+ }
+
+ // Re-usable variables
+ var col, direction;
+
+ // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
+ var setIndex = function( row, idx ){
+ row.entity.$$uiGridIndex = idx;
+ };
+ rows.forEach(setIndex);
+
+ // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference
+ // var d = data.slice(0);
+ var r = rows.slice(0);
+
+ // Now actually sort the data
+ var rowSortFn = function (rowA, rowB) {
+ var tem = 0,
+ idx = 0,
+ sortFn;
+
+ while (tem === 0 && idx < sortCols.length) {
+ // grab the metadata for the rest of the logic
+ col = sortCols[idx];
+ direction = sortCols[idx].sort.direction;
+
+ sortFn = rowSorter.getSortFn(grid, col, r);
+
+ var propA, propB;
+
+ if ( col.sortCellFiltered ){
+ propA = grid.getCellDisplayValue(rowA, col);
+ propB = grid.getCellDisplayValue(rowB, col);
+ } else {
+ propA = grid.getCellValue(rowA, col);
+ propB = grid.getCellValue(rowB, col);
+ }
+
+ tem = sortFn(propA, propB, rowA, rowB, direction, col);
+
+ idx++;
+ }
+
+ // Chrome doesn't implement a stable sort function. If our sort returns 0
+ // (i.e. the items are equal), and we're at the last sort column in the list,
+ // then return the previous order using our custom
+ // index variable
+ if (tem === 0 ) {
+ return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;
+ }
+
+ // Made it this far, we don't have to worry about null & undefined
+ if (direction === uiGridConstants.ASC) {
+ return tem;
+ } else {
+ return 0 - tem;
+ }
+ };
+
+ var newRows = rows.sort(rowSortFn);
+
+ // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
+ var clearIndex = function( row, idx ){
+ delete row.entity.$$uiGridIndex;
+ };
+ rows.forEach(clearIndex);
+
+ return newRows;
+ };
+
+ return rowSorter;
+}]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+var bindPolyfill;
+if (typeof Function.prototype.bind !== "function") {
+ bindPolyfill = function() {
+ var slice = Array.prototype.slice;
+ return function(context) {
+ var fn = this,
+ args = slice.call(arguments, 1);
+ if (args.length) {
+ return function() {
+ return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);
+ };
+ }
+ return function() {
+ return arguments.length ? fn.apply(context, arguments) : fn.call(context);
+ };
+ };
+ };
+}
+
+function getStyles (elem) {
+ var e = elem;
+ if (typeof(e.length) !== 'undefined' && e.length) {
+ e = elem[0];
+ }
+
+ return e.ownerDocument.defaultView.getComputedStyle(e, null);
+}
+
+var rnumnonpx = new RegExp( "^(" + (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source + ")(?!px)[a-z%]+$", "i" ),
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" };
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? 'border' : 'content' ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === 'width' ? 1 : 0,
+
+ val = 0;
+
+ var sides = ['Top', 'Right', 'Bottom', 'Left'];
+
+ for ( ; i < 4; i += 2 ) {
+ var side = sides[i];
+ // dump('side', side);
+
+ // both box models exclude margin, so add it if we want it
+ if ( extra === 'margin' ) {
+ var marg = parseFloat(styles[extra + side]);
+ if (!isNaN(marg)) {
+ val += marg;
+ }
+ }
+ // dump('val1', val);
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === 'content' ) {
+ var padd = parseFloat(styles['padding' + side]);
+ if (!isNaN(padd)) {
+ val -= padd;
+ // dump('val2', val);
+ }
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== 'margin' ) {
+ var bordermarg = parseFloat(styles['border' + side + 'Width']);
+ if (!isNaN(bordermarg)) {
+ val -= bordermarg;
+ // dump('val3', val);
+ }
+ }
+ }
+ else {
+ // at this point, extra isn't content, so add padding
+ var nocontentPad = parseFloat(styles['padding' + side]);
+ if (!isNaN(nocontentPad)) {
+ val += nocontentPad;
+ // dump('val4', val);
+ }
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== 'padding') {
+ var nocontentnopad = parseFloat(styles['border' + side + 'Width']);
+ if (!isNaN(nocontentnopad)) {
+ val += nocontentnopad;
+ // dump('val5', val);
+ }
+ }
+ }
+ }
+
+ // dump('augVal', val);
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles(elem),
+ isBorderBox = styles['boxSizing'] === 'border-box';
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = styles[name];
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ var ret = ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ );
+
+ // dump('ret', ret, val);
+ return ret;
+}
+
+function getLineHeight(elm) {
+ elm = angular.element(elm)[0];
+ var parent = elm.parentElement;
+
+ if (!parent) {
+ parent = document.getElementsByTagName('body')[0];
+ }
+
+ return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;
+}
+
+var uid = ['0', '0', '0', '0'];
+var uidPrefix = 'uiGrid-';
+
+/**
+ * @ngdoc service
+ * @name ui.grid.service:GridUtil
+ *
+ * @description Grid utility functions
+ */
+module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',
+ function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {
+ var s = {
+
+ augmentWidthOrHeight: augmentWidthOrHeight,
+
+ getStyles: getStyles,
+
+ /**
+ * @ngdoc method
+ * @name createBoundedWrapper
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {object} Object to bind 'this' to
+ * @param {method} Method to bind
+ * @returns {Function} The wrapper that performs the binding
+ *
+ * @description
+ * Binds given method to given object.
+ *
+ * By means of a wrapper, ensures that ``method`` is always bound to
+ * ``object`` regardless of its calling environment.
+ * Iow, inside ``method``, ``this`` always points to ``object``.
+ *
+ * See http://alistapart.com/article/getoutbindingsituations
+ *
+ */
+ createBoundedWrapper: function(object, method) {
+ return function() {
+ return method.apply(object, arguments);
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name readableColumnName
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {string} columnName Column name as a string
+ * @returns {string} Column name appropriately capitalized and split apart
+ *
+ @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {
+ $scope.name = 'firstName';
+ $scope.columnName = function(name) {
+ return gridUtil.readableColumnName(name);
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <strong>Column name:</strong> <input ng-model="name" />
+ <br>
+ <strong>Output:</strong> <span ng-bind="columnName(name)"></span>
+ </div>
+ </file>
+ </example>
+ */
+ readableColumnName: function (columnName) {
+ // Convert underscores to spaces
+ if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }
+
+ if (typeof(columnName) !== 'string') {
+ columnName = String(columnName);
+ }
+
+ return columnName.replace(/_+/g, ' ')
+ // Replace a completely all-capsed word with a first-letter-capitalized version
+ .replace(/^[A-Z]+$/, function (match) {
+ return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));
+ })
+ // Capitalize the first letter of words
+ .replace(/([\w\u00C0-\u017F]+)/g, function (match) {
+ return angular.uppercase(match.charAt(0)) + match.slice(1);
+ })
+ // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')
+ // .replace(/([A-Z]|[A-Z]\w+)([A-Z])/g, "$1 $2");
+ // .replace(/(\w+?|\w)([A-Z])/g, "$1 $2");
+ .replace(/(\w+?(?=[A-Z]))/g, '$1 ');
+ },
+
+ /**
+ * @ngdoc method
+ * @name getColumnsFromData
+ * @methodOf ui.grid.service:GridUtil
+ * @description Return a list of column names, given a data set
+ *
+ * @param {string} data Data array for grid
+ * @returns {Object} Column definitions with field accessor and column name
+ *
+ * @example
+ <pre>
+ var data = [
+ { firstName: 'Bob', lastName: 'Jones' },
+ { firstName: 'Frank', lastName: 'Smith' }
+ ];
+
+ var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);
+
+ columnDefs == [
+ {
+ field: 'firstName',
+ name: 'First Name'
+ },
+ {
+ field: 'lastName',
+ name: 'Last Name'
+ }
+ ];
+ </pre>
+ */
+ getColumnsFromData: function (data, excludeProperties) {
+ var columnDefs = [];
+
+ if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }
+ if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }
+
+ var item = data[0];
+
+ angular.forEach(item,function (prop, propName) {
+ if ( excludeProperties.indexOf(propName) === -1){
+ columnDefs.push({
+ name: propName
+ });
+ }
+ });
+
+ return columnDefs;
+ },
+
+ /**
+ * @ngdoc method
+ * @name newId
+ * @methodOf ui.grid.service:GridUtil
+ * @description Return a unique ID string
+ *
+ * @returns {string} Unique string
+ *
+ * @example
+ <pre>
+ var id = GridUtil.newId();
+
+ # 1387305700482;
+ </pre>
+ */
+ newId: (function() {
+ var seedId = new Date().getTime();
+ return function() {
+ return seedId += 1;
+ };
+ })(),
+
+
+ /**
+ * @ngdoc method
+ * @name getTemplate
+ * @methodOf ui.grid.service:GridUtil
+ * @description Get's template from cache / element / url
+ *
+ * @param {string|element|promise} Either a string representing the template id, a string representing the template url,
+ * an jQuery/Angualr element, or a promise that returns the template contents to use.
+ * @returns {object} a promise resolving to template contents
+ *
+ * @example
+ <pre>
+ GridUtil.getTemplate(url).then(function (contents) {
+ alert(contents);
+ })
+ </pre>
+ */
+ getTemplate: function (template) {
+ // Try to fetch the template out of the templateCache
+ if ($templateCache.get(template)) {
+ return s.postProcessTemplate($templateCache.get(template));
+ }
+
+ // See if the template is itself a promise
+ if (angular.isFunction(template.then)) {
+ return template.then(s.postProcessTemplate);
+ }
+
+ // If the template is an element, return the element
+ try {
+ if (angular.element(template).length > 0) {
+ return $q.when(template).then(s.postProcessTemplate);
+ }
+ }
+ catch (err){
+ //do nothing; not valid html
+ }
+
+ s.logDebug('fetching url', template);
+
+ // Default to trying to fetch the template as a url with $http
+ return $http({ method: 'GET', url: template})
+ .then(
+ function (result) {
+ var templateHtml = result.data.trim();
+ //put in templateCache for next call
+ $templateCache.put(template, templateHtml);
+ return templateHtml;
+ },
+ function (err) {
+ throw new Error("Could not get template " + template + ": " + err);
+ }
+ )
+ .then(s.postProcessTemplate);
+ },
+
+ //
+ postProcessTemplate: function (template) {
+ var startSym = $interpolate.startSymbol(),
+ endSym = $interpolate.endSymbol();
+
+ // If either of the interpolation symbols have been changed, we need to alter this template
+ if (startSym !== '{{' || endSym !== '}}') {
+ template = template.replace(/\{\{/g, startSym);
+ template = template.replace(/\}\}/g, endSym);
+ }
+
+ return $q.when(template);
+ },
+
+ /**
+ * @ngdoc method
+ * @name guessType
+ * @methodOf ui.grid.service:GridUtil
+ * @description guesses the type of an argument
+ *
+ * @param {string/number/bool/object} item variable to examine
+ * @returns {string} one of the following
+ * - 'string'
+ * - 'boolean'
+ * - 'number'
+ * - 'date'
+ * - 'object'
+ */
+ guessType : function (item) {
+ var itemType = typeof(item);
+
+ // Check for numbers and booleans
+ switch (itemType) {
+ case "number":
+ case "boolean":
+ case "string":
+ return itemType;
+ default:
+ if (angular.isDate(item)) {
+ return "date";
+ }
+ return "object";
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name elementWidth
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element DOM element
+ * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
+ *
+ * @returns {number} Element width in pixels, accounting for any borders, etc.
+ */
+ elementWidth: function (elem) {
+
+ },
+
+ /**
+ * @ngdoc method
+ * @name elementHeight
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element DOM element
+ * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
+ *
+ * @returns {number} Element height in pixels, accounting for any borders, etc.
+ */
+ elementHeight: function (elem) {
+
+ },
+
+ // Thanks to http://stackoverflow.com/a/13382873/888165
+ getScrollbarWidth: function() {
+ var outer = document.createElement("div");
+ outer.style.visibility = "hidden";
+ outer.style.width = "100px";
+ outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
+
+ document.body.appendChild(outer);
+
+ var widthNoScroll = outer.offsetWidth;
+ // force scrollbars
+ outer.style.overflow = "scroll";
+
+ // add innerdiv
+ var inner = document.createElement("div");
+ inner.style.width = "100%";
+ outer.appendChild(inner);
+
+ var widthWithScroll = inner.offsetWidth;
+
+ // remove divs
+ outer.parentNode.removeChild(outer);
+
+ return widthNoScroll - widthWithScroll;
+ },
+
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ },
+
+ fakeElement: function( elem, options, callback, args ) {
+ var ret, name,
+ newElement = angular.element(elem).clone()[0];
+
+ for ( name in options ) {
+ newElement.style[ name ] = options[ name ];
+ }
+
+ angular.element(document.body).append(newElement);
+
+ ret = callback.call( newElement, newElement );
+
+ angular.element(newElement).remove();
+
+ return ret;
+ },
+
+ /**
+ * @ngdoc method
+ * @name normalizeWheelEvent
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {event} event A mouse wheel event
+ *
+ * @returns {event} A normalized event
+ *
+ * @description
+ * Given an event from this list:
+ *
+ * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`
+ *
+ * "normalize" it
+ * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)
+ */
+ normalizeWheelEvent: function (event) {
+ // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
+ // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
+ var lowestDelta, lowestDeltaXY;
+
+ var orgEvent = event || window.event,
+ args = [].slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ absDeltaXY = 0,
+ fn;
+
+ // event = $.event.fix(orgEvent);
+ // event.type = 'mousewheel';
+
+ // NOTE: jQuery masks the event and stores it in the event as originalEvent
+ if (orgEvent.originalEvent) {
+ orgEvent = orgEvent.originalEvent;
+ }
+
+ // Old school scrollwheel delta
+ if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
+ if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
+
+ // At a minimum, setup the deltaY to be delta
+ deltaY = delta;
+
+ // Firefox < 17 related to DOMMouseScroll event
+ if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
+ deltaY = 0;
+ deltaX = delta * -1;
+ }
+
+ // New school wheel delta (wheel event)
+ if ( orgEvent.deltaY ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( orgEvent.deltaX ) {
+ deltaX = orgEvent.deltaX;
+ delta = deltaX * -1;
+ }
+
+ // Webkit
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }
+
+ // Look for lowest delta to normalize the delta values
+ absDelta = Math.abs(delta);
+ if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
+ absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
+ if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
+
+ // Get a whole value for the deltas
+ fn = delta > 0 ? 'floor' : 'ceil';
+ delta = Math[fn](delta / lowestDelta);
+ deltaX = Math[fn](deltaX / lowestDeltaXY);
+ deltaY = Math[fn](deltaY / lowestDeltaXY);
+
+ return {
+ delta: delta,
+ deltaX: deltaX,
+ deltaY: deltaY
+ };
+ },
+
+ // Stolen from Modernizr
+ // TODO: make this, and everythign that flows from it, robust
+ //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
+ isTouchEnabled: function() {
+ var bool;
+
+ if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {
+ bool = true;
+ }
+
+ return bool;
+ },
+
+ isNullOrUndefined: function(obj) {
+ if (obj === undefined || obj === null) {
+ return true;
+ }
+ return false;
+ },
+
+ endsWith: function(str, suffix) {
+ if (!str || !suffix || typeof str !== "string") {
+ return false;
+ }
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ },
+
+ arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {
+ var found = false;
+ angular.forEach(array, function (object) {
+ if (object[propertyName] === propertyValue) {
+ found = true;
+ }
+ });
+ return found;
+ },
+
+ //// Shim requestAnimationFrame
+ //requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||
+ // $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||
+ // function(fn) {
+ // return $timeout(fn, 10, false);
+ // },
+
+ numericAndNullSort: function (a, b) {
+ if (a === null) { return 1; }
+ if (b === null) { return -1; }
+ if (a === null && b === null) { return 0; }
+ return a - b;
+ },
+
+ // Disable ngAnimate animations on an element
+ disableAnimations: function (element) {
+ var $animate;
+ try {
+ $animate = $injector.get('$animate');
+ // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
+ if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
+ $animate.enabled(element, false);
+ } else {
+ $animate.enabled(false, element);
+ }
+ }
+ catch (e) {}
+ },
+
+ enableAnimations: function (element) {
+ var $animate;
+ try {
+ $animate = $injector.get('$animate');
+ // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
+ if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
+ $animate.enabled(element, true);
+ } else {
+ $animate.enabled(true, element);
+ }
+ return $animate;
+ }
+ catch (e) {}
+ },
+
+ // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
+ nextUid: function nextUid() {
+ var index = uid.length;
+ var digit;
+
+ while (index) {
+ index--;
+ digit = uid[index].charCodeAt(0);
+ if (digit === 57 /*'9'*/) {
+ uid[index] = 'A';
+ return uidPrefix + uid.join('');
+ }
+ if (digit === 90 /*'Z'*/) {
+ uid[index] = '0';
+ } else {
+ uid[index] = String.fromCharCode(digit + 1);
+ return uidPrefix + uid.join('');
+ }
+ }
+ uid.unshift('0');
+
+ return uidPrefix + uid.join('');
+ },
+
+ // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
+ hashKey: function hashKey(obj) {
+ var objType = typeof obj,
+ key;
+
+ if (objType === 'object' && obj !== null) {
+ if (typeof (key = obj.$$hashKey) === 'function') {
+ // must invoke on object to keep the right this
+ key = obj.$$hashKey();
+ }
+ else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {
+ key = obj.$$hashKey;
+ }
+ else if (key === undefined) {
+ key = obj.$$hashKey = s.nextUid();
+ }
+ }
+ else {
+ key = obj;
+ }
+
+ return objType + ':' + key;
+ },
+
+ resetUids: function () {
+ uid = ['0', '0', '0'];
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logError
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true
+ * @param {string} logMessage message to be logged to the console
+ *
+ */
+ logError: function( logMessage ){
+ if ( uiGridConstants.LOG_ERROR_MESSAGES ){
+ $log.error( logMessage );
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logWarn
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true
+ * @param {string} logMessage message to be logged to the console
+ *
+ */
+ logWarn: function( logMessage ){
+ if ( uiGridConstants.LOG_WARN_MESSAGES ){
+ $log.warn( logMessage );
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logDebug
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true
+ *
+ */
+ logDebug: function() {
+ if ( uiGridConstants.LOG_DEBUG_MESSAGES ){
+ $log.debug.apply($log, arguments);
+ }
+ }
+
+ };
+
+ /**
+ * @ngdoc object
+ * @name focus
+ * @propertyOf ui.grid.service:GridUtil
+ * @description Provies a set of methods to set the document focus inside the grid.
+ * See {@link ui.grid.service:GridUtil.focus} for more information.
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.service:GridUtil.focus
+ * @description Provies a set of methods to set the document focus inside the grid.
+ * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.
+ * e.g. click events that need to run before the focus or
+ * inputs elements that are in a disabled state but are enabled when those events
+ * are triggered.
+ */
+ s.focus = {
+ queue: [],
+ //http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name byId
+ * @description Sets the focus of the document to the given id value.
+ * If provided with the grid object it will automatically append the grid id.
+ * This is done to encourage unique dom id's as it allows for multiple grids on a
+ * page.
+ * @param {String} id the id of the dom element to set the focus on
+ * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}
+ * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ byId: function (id, Grid) {
+ this._purgeQueue();
+ var promise = $timeout(function() {
+ var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;
+ var element = $window.document.getElementById(elementID);
+ if (element) {
+ element.focus();
+ } else {
+ s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');
+ }
+ });
+ this.queue.push(promise);
+ return promise;
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name byElement
+ * @description Sets the focus of the document to the given dom element.
+ * @param {(element|angular.element)} element the DOM element to set the focus on
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ byElement: function(element){
+ if (!angular.isElement(element)){
+ s.logWarn("Trying to focus on an element that isn\'t an element.");
+ return $q.reject('not-element');
+ }
+ element = angular.element(element);
+ this._purgeQueue();
+ var promise = $timeout(function(){
+ if (element){
+ element[0].focus();
+ }
+ });
+ this.queue.push(promise);
+ return promise;
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name bySelector
+ * @description Sets the focus of the document to the given dom element.
+ * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector
+ * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}
+ * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately
+ * then the focus will be called.
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ bySelector: function(parentElement, querySelector, aSync){
+ var self = this;
+ if (!angular.isElement(parentElement)){
+ throw new Error("The parent element is not an element.");
+ }
+ // Ensure that this is an angular element.
+ // It is fine if this is already an angular element.
+ parentElement = angular.element(parentElement);
+ var focusBySelector = function(){
+ var element = parentElement[0].querySelector(querySelector);
+ return self.byElement(element);
+ };
+ this._purgeQueue();
+ if (aSync){ //Do this asynchronysly
+ var promise = $timeout(focusBySelector);
+ this.queue.push($timeout(focusBySelector));
+ return promise;
+ } else {
+ return focusBySelector();
+ }
+ },
+ _purgeQueue: function(){
+ this.queue.forEach(function(element){
+ $timeout.cancel(element);
+ });
+ this.queue = [];
+ }
+ };
+
+
+ ['width', 'height'].forEach(function (name) {
+ var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);
+ s['element' + capsName] = function (elem, extra) {
+ var e = elem;
+ if (e && typeof(e.length) !== 'undefined' && e.length) {
+ e = elem[0];
+ }
+
+ if (e && e !== null) {
+ var styles = getStyles(e);
+ return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?
+ s.swap(e, cssShow, function() {
+ return getWidthOrHeight(e, name, extra );
+ }) :
+ getWidthOrHeight( e, name, extra );
+ }
+ else {
+ return null;
+ }
+ };
+
+ s['outerElement' + capsName] = function (elem, margin) {
+ return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;
+ };
+ });
+
+ // http://stackoverflow.com/a/24107550/888165
+ s.closestElm = function closestElm(el, selector) {
+ if (typeof(el.length) !== 'undefined' && el.length) {
+ el = el[0];
+ }
+
+ var matchesFn;
+
+ // find vendor prefix
+ ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
+ if (typeof document.body[fn] === 'function') {
+ matchesFn = fn;
+ return true;
+ }
+ return false;
+ });
+
+ // traverse parents
+ var parent;
+ while (el !== null) {
+ parent = el.parentElement;
+ if (parent !== null && parent[matchesFn](selector)) {
+ return parent;
+ }
+ el = parent;
+ }
+
+ return null;
+ };
+
+ s.type = function (obj) {
+ var text = Function.prototype.toString.call(obj.constructor);
+ return text.match(/function (.*?)\(/)[1];
+ };
+
+ s.getBorderSize = function getBorderSize(elem, borderType) {
+ if (typeof(elem.length) !== 'undefined' && elem.length) {
+ elem = elem[0];
+ }
+
+ var styles = getStyles(elem);
+
+ // If a specific border is supplied, like 'top', read the 'borderTop' style property
+ if (borderType) {
+ borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);
+ }
+ else {
+ borderType = 'border';
+ }
+
+ borderType += 'Width';
+
+ var val = parseInt(styles[borderType], 10);
+
+ if (isNaN(val)) {
+ return 0;
+ }
+ else {
+ return val;
+ }
+ };
+
+ // http://stackoverflow.com/a/22948274/888165
+ // TODO: Opera? Mobile?
+ s.detectBrowser = function detectBrowser() {
+ var userAgent = $window.navigator.userAgent;
+
+ var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\//i};
+
+ for (var key in browsers) {
+ if (browsers[key].test(userAgent)) {
+ return key;
+ }
+ }
+
+ return 'unknown';
+ };
+
+ // Borrowed from https://github.com/othree/jquery.rtl-scroll-type
+ // Determine the scroll "type" this browser is using for RTL
+ s.rtlScrollType = function rtlScrollType() {
+ if (rtlScrollType.type) {
+ return rtlScrollType.type;
+ }
+
+ var definer = angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],
+ type = 'reverse';
+
+ document.body.appendChild(definer);
+
+ if (definer.scrollLeft > 0) {
+ type = 'default';
+ }
+ else {
+ definer.scrollLeft = 1;
+ if (definer.scrollLeft === 0) {
+ type = 'negative';
+ }
+ }
+
+ angular.element(definer).remove();
+ rtlScrollType.type = type;
+
+ return type;
+ };
+
+ /**
+ * @ngdoc method
+ * @name normalizeScrollLeft
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element The element to get the `scrollLeft` from.
+ * @param {grid} grid - grid used to normalize (uses the rtl property)
+ *
+ * @returns {number} A normalized scrollLeft value for the current browser.
+ *
+ * @description
+ * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them
+ */
+ s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {
+ if (typeof(element.length) !== 'undefined' && element.length) {
+ element = element[0];
+ }
+
+ var scrollLeft = element.scrollLeft;
+
+ if (grid.isRTL()) {
+ switch (s.rtlScrollType()) {
+ case 'default':
+ return element.scrollWidth - scrollLeft - element.clientWidth;
+ case 'negative':
+ return Math.abs(scrollLeft);
+ case 'reverse':
+ return scrollLeft;
+ }
+ }
+
+ return scrollLeft;
+ };
+
+ /**
+ * @ngdoc method
+ * @name denormalizeScrollLeft
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element The element to normalize the `scrollLeft` value for
+ * @param {number} scrollLeft The `scrollLeft` value to denormalize.
+ * @param {grid} grid The grid that owns the scroll event.
+ *
+ * @returns {number} A normalized scrollLeft value for the current browser.
+ *
+ * @description
+ * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.
+ */
+ s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {
+ if (typeof(element.length) !== 'undefined' && element.length) {
+ element = element[0];
+ }
+
+ if (grid.isRTL()) {
+ switch (s.rtlScrollType()) {
+ case 'default':
+ // Get the max scroll for the element
+ var maxScrollLeft = element.scrollWidth - element.clientWidth;
+
+ // Subtract the current scroll amount from the max scroll
+ return maxScrollLeft - scrollLeft;
+ case 'negative':
+ return scrollLeft * -1;
+ case 'reverse':
+ return scrollLeft;
+ }
+ }
+
+ return scrollLeft;
+ };
+
+ /**
+ * @ngdoc method
+ * @name preEval
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {string} path Path to evaluate
+ *
+ * @returns {string} A path that is normalized.
+ *
+ * @description
+ * Takes a field path and converts it to bracket notation to allow for special characters in path
+ * @example
+ * <pre>
+ * gridUtil.preEval('property') == 'property'
+ * gridUtil.preEval('nested.deep.prop-erty') = "nested['deep']['prop-erty']"
+ * </pre>
+ */
+ s.preEval = function (path) {
+ var m = uiGridConstants.BRACKET_REGEXP.exec(path);
+ if (m) {
+ return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);
+ } else {
+ path = path.replace(uiGridConstants.APOS_REGEXP, '\\\'');
+ var parts = path.split(uiGridConstants.DOT_REGEXP);
+ var preparsed = [parts.shift()]; // first item must be var notation, thus skip
+ angular.forEach(parts, function (part) {
+ preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\']$1'));
+ });
+ return preparsed.join('[\'');
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name debounce
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {function} func function to debounce
+ * @param {number} wait milliseconds to delay
+ * @param {boolean} immediate execute before delay
+ *
+ * @returns {function} A function that can be executed as debounced function
+ *
+ * @description
+ * Copied from https://github.com/shahata/angular-debounce
+ * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function
+ * @example
+ * <pre>
+ * var debouncedFunc = gridUtil.debounce(function(){alert('debounced');}, 500);
+ * debouncedFunc();
+ * debouncedFunc();
+ * debouncedFunc();
+ * </pre>
+ */
+ s.debounce = function (func, wait, immediate) {
+ var timeout, args, context, result;
+ function debounce() {
+ /* jshint validthis:true */
+ context = this;
+ args = arguments;
+ var later = function () {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ if (timeout) {
+ $timeout.cancel(timeout);
+ }
+ timeout = $timeout(later, wait, false);
+ if (callNow) {
+ result = func.apply(context, args);
+ }
+ return result;
+ }
+ debounce.cancel = function () {
+ $timeout.cancel(timeout);
+ timeout = null;
+ };
+ return debounce;
+ };
+
+ /**
+ * @ngdoc method
+ * @name throttle
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {function} func function to throttle
+ * @param {number} wait milliseconds to delay after first trigger
+ * @param {Object} params to use in throttle.
+ *
+ * @returns {function} A function that can be executed as throttled function
+ *
+ * @description
+ * Adapted from debounce function (above)
+ * Potential keys for Params Object are:
+ * trailing (bool) - whether to trigger after throttle time ends if called multiple times
+ * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,
+ * but not with $timeout
+ *
+ * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function
+ * return from that call each time you need to call throttle. If you call throttle itself repeatedly, the lastCall
+ * variable will get overwritten and the throttling won't work
+ *
+ * @example
+ * <pre>
+ * var throttledFunc = gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});
+ * throttledFunc(); //=> logs throttled
+ * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)
+ * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.
+ * </pre>
+ */
+ s.throttle = function(func, wait, options){
+ options = options || {};
+ var lastCall = 0, queued = null, context, args;
+
+ function runFunc(endDate){
+ lastCall = +new Date();
+ func.apply(context, args);
+ $interval(function(){queued = null; }, 0, 1, false);
+ }
+
+ return function(){
+ /* jshint validthis:true */
+ context = this;
+ args = arguments;
+ if (queued === null){
+ var sinceLast = +new Date() - lastCall;
+ if (sinceLast > wait){
+ runFunc();
+ }
+ else if (options.trailing){
+ queued = $interval(runFunc, wait - sinceLast, 1, false);
+ }
+ }
+ };
+ };
+
+ s.on = {};
+ s.off = {};
+ s._events = {};
+
+ s.addOff = function (eventName) {
+ s.off[eventName] = function (elm, fn) {
+ var idx = s._events[eventName].indexOf(fn);
+ if (idx > 0) {
+ s._events[eventName].removeAt(idx);
+ }
+ };
+ };
+
+ var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
+ nullLowestDeltaTimeout,
+ lowestDelta;
+
+ s.on.mousewheel = function (elm, fn) {
+ if (!elm || !fn) { return; }
+
+ var $elm = angular.element(elm);
+
+ // Store the line height and page height for this particular element
+ $elm.data('mousewheel-line-height', getLineHeight($elm));
+ $elm.data('mousewheel-page-height', s.elementHeight($elm));
+ if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }
+
+ var cbs = $elm.data('mousewheel-callbacks');
+ cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);
+
+ // Bind all the mousew heel events
+ for ( var i = mouseWheeltoBind.length; i; ) {
+ $elm.on(mouseWheeltoBind[--i], cbs[fn]);
+ }
+ $elm.on('$destroy', function unbindEvents() {
+ for ( var i = mouseWheeltoBind.length; i; ) {
+ $elm.off(mouseWheeltoBind[--i], cbs[fn]);
+ }
+ });
+ };
+ s.off.mousewheel = function (elm, fn) {
+ var $elm = angular.element(elm);
+
+ var cbs = $elm.data('mousewheel-callbacks');
+ var handler = cbs[fn];
+
+ if (handler) {
+ for ( var i = mouseWheeltoBind.length; i; ) {
+ $elm.off(mouseWheeltoBind[--i], handler);
+ }
+ }
+
+ delete cbs[fn];
+
+ if (Object.keys(cbs).length === 0) {
+ $elm.removeData('mousewheel-line-height');
+ $elm.removeData('mousewheel-page-height');
+ $elm.removeData('mousewheel-callbacks');
+ }
+ };
+
+ function mousewheelHandler(fn, event) {
+ var $elm = angular.element(this);
+
+ var delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ offsetX = 0,
+ offsetY = 0;
+
+ // jQuery masks events
+ if (event.originalEvent) { event = event.originalEvent; }
+
+ if ( 'detail' in event ) { deltaY = event.detail * -1; }
+ if ( 'wheelDelta' in event ) { deltaY = event.wheelDelta; }
+ if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY; }
+ if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }
+
+ // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
+ if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
+ deltaX = deltaY * -1;
+ deltaY = 0;
+ }
+
+ // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
+ delta = deltaY === 0 ? deltaX : deltaY;
+
+ // New school wheel delta (wheel event)
+ if ( 'deltaY' in event ) {
+ deltaY = event.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( 'deltaX' in event ) {
+ deltaX = event.deltaX;
+ if ( deltaY === 0 ) { delta = deltaX * -1; }
+ }
+
+ // No change actually happened, no reason to go any further
+ if ( deltaY === 0 && deltaX === 0 ) { return; }
+
+ // Need to convert lines and pages to pixels if we aren't already in pixels
+ // There are three delta modes:
+ // * deltaMode 0 is by pixels, nothing to do
+ // * deltaMode 1 is by lines
+ // * deltaMode 2 is by pages
+ if ( event.deltaMode === 1 ) {
+ var lineHeight = $elm.data('mousewheel-line-height');
+ delta *= lineHeight;
+ deltaY *= lineHeight;
+ deltaX *= lineHeight;
+ }
+ else if ( event.deltaMode === 2 ) {
+ var pageHeight = $elm.data('mousewheel-page-height');
+ delta *= pageHeight;
+ deltaY *= pageHeight;
+ deltaX *= pageHeight;
+ }
+
+ // Store lowest absolute delta to normalize the delta values
+ absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
+
+ if ( !lowestDelta || absDelta < lowestDelta ) {
+ lowestDelta = absDelta;
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(event, absDelta) ) {
+ lowestDelta /= 40;
+ }
+ }
+
+ // Get a whole, normalized value for the deltas
+ delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
+ deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
+ deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
+
+ // Normalise offsetX and offsetY properties
+ // if ($elm[0].getBoundingClientRect ) {
+ // var boundingRect = $(elm)[0].getBoundingClientRect();
+ // offsetX = event.clientX - boundingRect.left;
+ // offsetY = event.clientY - boundingRect.top;
+ // }
+
+ // event.deltaX = deltaX;
+ // event.deltaY = deltaY;
+ // event.deltaFactor = lowestDelta;
+
+ var newEvent = {
+ originalEvent: event,
+ deltaX: deltaX,
+ deltaY: deltaY,
+ deltaFactor: lowestDelta,
+ preventDefault: function () { event.preventDefault(); },
+ stopPropagation: function () { event.stopPropagation(); }
+ };
+
+ // Clearout lowestDelta after sometime to better
+ // handle multiple device types that give
+ // a different lowestDelta
+ // Ex: trackpad = 3 and mouse wheel = 120
+ if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
+ nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
+
+ fn.call($elm[0], newEvent);
+ }
+
+ function nullLowestDelta() {
+ lowestDelta = null;
+ }
+
+ function shouldAdjustOldDeltas(orgEvent, absDelta) {
+ // If this is an older event and the delta is divisable by 120,
+ // then we are assuming that the browser is treating this as an
+ // older mouse wheel event and that we should divide the deltas
+ // by 40 to try and get a more usable deltaFactor.
+ // Side note, this actually impacts the reported scroll distance
+ // in older browsers and can cause scrolling to be slower than native.
+ // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
+ return orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
+ }
+
+ return s;
+}]);
+
+// Add 'px' to the end of a number string if it doesn't have it already
+module.filter('px', function() {
+ return function(str) {
+ if (str.match(/^[\d\.]+$/)) {
+ return str + 'px';
+ }
+ else {
+ return str;
+ }
+ };
+});
+
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ var lang = {
+ aggregate: {
+ label: 'položky'
+ },
+ groupPanel: {
+ description: 'Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce.'
+ },
+ search: {
+ placeholder: 'Hledat...',
+ showingItems: 'Zobrazuji položky:',
+ selectedItems: 'Vybrané položky:',
+ totalItems: 'Celkem položek:',
+ size: 'Velikost strany:',
+ first: 'První strana',
+ next: 'Další strana',
+ previous: 'Předchozí strana',
+ last: 'Poslední strana'
+ },
+ menu: {
+ text: 'Vyberte sloupec:'
+ },
+ sort: {
+ ascending: 'Seřadit od A-Z',
+ descending: 'Seřadit od Z-A',
+ remove: 'Odebrat seřazení'
+ },
+ column: {
+ hide: 'Schovat sloupec'
+ },
+ aggregation: {
+ count: 'celkem řádků: ',
+ sum: 'celkem: ',
+ avg: 'avg: ',
+ min: 'min.: ',
+ max: 'max.: '
+ },
+ pinning: {
+ pinLeft: 'Zamknout vlevo',
+ pinRight: 'Zamknout vpravo',
+ unpin: 'Odemknout'
+ },
+ gridMenu: {
+ columns: 'Sloupce:',
+ importerTitle: 'Importovat soubor',
+ exporterAllAsCsv: 'Exportovat všechna data do csv',
+ exporterVisibleAsCsv: 'Exportovat viditelná data do csv',
+ exporterSelectedAsCsv: 'Exportovat vybraná data do csv',
+ exporterAllAsPdf: 'Exportovat všechna data do pdf',
+ exporterVisibleAsPdf: 'Exportovat viditelná data do pdf',
+ exporterSelectedAsPdf: 'Exportovat vybraná data do pdf',
+ clearAllFilters: 'Odstranit všechny filtry'
+ },
+ importer: {
+ noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',
+ noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',
+ invalidCsv: 'Soubor nelze zpracovat, jedná se o CSV?',
+ invalidJson: 'Soubor nelze zpracovat, je to JSON?',
+ jsonNotArray: 'Soubor musí obsahovat json. UkonÄuji..'
+ },
+ pagination: {
+ sizes: 'položek na stránku',
+ totalItems: 'položek'
+ },
+ grouping: {
+ group: 'Seskupit',
+ ungroup: 'Odebrat seskupení',
+ aggregate_count: 'Agregace: Count',
+ aggregate_sum: 'Agregace: Sum',
+ aggregate_max: 'Agregace: Max',
+ aggregate_min: 'Agregace: Min',
+ aggregate_avg: 'Agregace: Avg',
+ aggregate_remove: 'Agregace: Odebrat'
+ }
+ };
+
+ // support varianty of different czech keys.
+ $delegate.add('cs', lang);
+ $delegate.add('cz', lang);
+ $delegate.add('cs-cz', lang);
+ $delegate.add('cs-CZ', lang);
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function(){
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('da', {
+ aggregate:{
+ label: 'artikler'
+ },
+ groupPanel:{
+ description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'
+ },
+ search:{
+ placeholder: 'Søg...',
+ showingItems: 'Viste rækker:',
+ selectedItems: 'Valgte rækker:',
+ totalItems: 'Rækker totalt:',
+ size: 'Side størrelse:',
+ first: 'Første side',
+ next: 'Næste side',
+ previous: 'Forrige side',
+ last: 'Sidste side'
+ },
+ menu:{
+ text: 'Vælg kolonner:'
+ },
+ sort: {
+ ascending: 'Sorter stigende',
+ descending: 'Sorter faldende',
+ none: 'Sorter ingen',
+ remove: 'Fjern sortering'
+ },
+ column: {
+ hide: 'Skjul kolonne'
+ },
+ aggregation: {
+ count: 'antal rækker: ',
+ sum: 'sum: ',
+ avg: 'gns: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Kolonner:',
+ importerTitle: 'Importer fil',
+ exporterAllAsCsv: 'Eksporter alle data som csv',
+ exporterVisibleAsCsv: 'Eksporter synlige data som csv',
+ exporterSelectedAsCsv: 'Eksporter markerede data som csv',
+ exporterAllAsPdf: 'Eksporter alle data som pdf',
+ exporterVisibleAsPdf: 'Eksporter synlige data som pdf',
+ exporterSelectedAsPdf: 'Eksporter markerede data som pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Gå til første',
+ pageBack: 'GÃ¥ tilbage',
+ pageSelected: 'Valgte side',
+ pageForward: 'GÃ¥ frem',
+ pageToLast: 'GÃ¥ til sidste'
+ },
+ sizes: 'genstande per side',
+ totalItems: 'genstande',
+ through: 'gennem',
+ of: 'af'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('de', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filter für Spalte',
+ removeFilter: 'Filter löschen',
+ columnMenuButtonLabel: 'Spaltenmenü'
+ },
+ priority: 'Priorität:',
+ filterLabel: "Filter für Spalte: "
+ },
+ aggregate: {
+ label: 'Eintrag'
+ },
+ groupPanel: {
+ description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'
+ },
+ search: {
+ placeholder: 'Suche...',
+ showingItems: 'Zeige Einträge:',
+ selectedItems: 'Ausgewählte Einträge:',
+ totalItems: 'Einträge gesamt:',
+ size: 'Einträge pro Seite:',
+ first: 'Erste Seite',
+ next: 'Nächste Seite',
+ previous: 'Vorherige Seite',
+ last: 'Letzte Seite'
+ },
+ menu: {
+ text: 'Spalten auswählen:'
+ },
+ sort: {
+ ascending: 'aufsteigend sortieren',
+ descending: 'absteigend sortieren',
+ none: 'keine Sortierung',
+ remove: 'Sortierung zurücksetzen'
+ },
+ column: {
+ hide: 'Spalte ausblenden'
+ },
+ aggregation: {
+ count: 'Zeilen insgesamt: ',
+ sum: 'gesamt: ',
+ avg: 'Durchschnitt: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Links anheften',
+ pinRight: 'Rechts anheften',
+ unpin: 'Lösen'
+ },
+ columnMenu: {
+ close: 'Schließen'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Tabellenmenü'
+ },
+ columns: 'Spalten:',
+ importerTitle: 'Datei importieren',
+ exporterAllAsCsv: 'Alle Daten als CSV exportieren',
+ exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',
+ exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',
+ exporterAllAsPdf: 'Alle Daten als PDF exportieren',
+ exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',
+ exporterSelectedAsPdf: 'markierte Daten als PDF exportieren',
+ clearAllFilters: 'Alle Filter zurücksetzen'
+ },
+ importer: {
+ noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',
+ noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',
+ invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',
+ invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',
+ jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Zum Anfang',
+ pageBack: 'Seite zurück',
+ pageSelected: 'Ausgwählte Seite',
+ pageForward: 'Seite vor',
+ pageToLast: 'Zum Ende'
+ },
+ sizes: 'Einträge pro Seite',
+ totalItems: 'Einträge',
+ through: 'bis',
+ of: 'von'
+ },
+ grouping: {
+ group: 'Gruppieren',
+ ungroup: 'Gruppierung aufheben',
+ aggregate_count: 'Agg: Anzahl',
+ aggregate_sum: 'Agg: Summe',
+ aggregate_max: 'Agg: Maximum',
+ aggregate_min: 'Agg: Minimum',
+ aggregate_avg: 'Agg: Mittelwert',
+ aggregate_remove: 'Aggregation entfernen'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('en', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filter for column',
+ removeFilter: 'Remove Filter',
+ columnMenuButtonLabel: 'Column Menu'
+ },
+ priority: 'Priority:',
+ filterLabel: "Filter for column: "
+ },
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Drag a column header here and drop it to group by that column.'
+ },
+ search: {
+ placeholder: 'Search...',
+ showingItems: 'Showing Items:',
+ selectedItems: 'Selected Items:',
+ totalItems: 'Total Items:',
+ size: 'Page Size:',
+ first: 'First Page',
+ next: 'Next Page',
+ previous: 'Previous Page',
+ last: 'Last Page'
+ },
+ menu: {
+ text: 'Choose Columns:'
+ },
+ sort: {
+ ascending: 'Sort Ascending',
+ descending: 'Sort Descending',
+ none: 'Sort None',
+ remove: 'Remove Sort'
+ },
+ column: {
+ hide: 'Hide Column'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Pin Left',
+ pinRight: 'Pin Right',
+ unpin: 'Unpin'
+ },
+ columnMenu: {
+ close: 'Close'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Grid Menu'
+ },
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Page to first',
+ pageBack: 'Page back',
+ pageSelected: 'Selected page',
+ pageForward: 'Page forward',
+ pageToLast: 'Page to last'
+ },
+ sizes: 'items per page',
+ totalItems: 'items',
+ through: 'through',
+ of: 'of'
+ },
+ grouping: {
+ group: 'Group',
+ ungroup: 'Ungroup',
+ aggregate_count: 'Agg: Count',
+ aggregate_sum: 'Agg: Sum',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Avg',
+ aggregate_remove: 'Agg: Remove'
+ },
+ validate: {
+ error: 'Error:',
+ minLength: 'Value should be at least THRESHOLD characters long.',
+ maxLength: 'Value should be at most THRESHOLD characters long.',
+ required: 'A value is needed.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('es', {
+ aggregate: {
+ label: 'Artículos'
+ },
+ groupPanel: {
+ description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'
+ },
+ search: {
+ placeholder: 'Buscar...',
+ showingItems: 'Artículos Mostrados:',
+ selectedItems: 'Artículos Seleccionados:',
+ totalItems: 'Artículos Totales:',
+ size: 'Tamaño de Página:',
+ first: 'Primera Página',
+ next: 'Página Siguiente',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Elegir columnas:'
+ },
+ sort: {
+ ascending: 'Orden Ascendente',
+ descending: 'Orden Descendente',
+ remove: 'Sin Ordenar'
+ },
+ column: {
+ hide: 'Ocultar la columna'
+ },
+ aggregation: {
+ count: 'filas totales: ',
+ sum: 'total: ',
+ avg: 'media: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fijar a la Izquierda',
+ pinRight: 'Fijar a la Derecha',
+ unpin: 'Quitar Fijación'
+ },
+ gridMenu: {
+ columns: 'Columnas:',
+ importerTitle: 'Importar archivo',
+ exporterAllAsCsv: 'Exportar todo como csv',
+ exporterVisibleAsCsv: 'Exportar vista como csv',
+ exporterSelectedAsCsv: 'Exportar selección como csv',
+ exporterAllAsPdf: 'Exportar todo como pdf',
+ exporterVisibleAsPdf: 'Exportar vista como pdf',
+ exporterSelectedAsPdf: 'Exportar selección como pdf',
+ clearAllFilters: 'Limpiar todos los filtros'
+ },
+ importer: {
+ noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',
+ noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',
+ invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',
+ invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',
+ jsonNotArray: 'El archivo json importado debe contener un array, abortando.'
+ },
+ pagination: {
+ sizes: 'registros por página',
+ totalItems: 'registros',
+ of: 'de'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Cont',
+ aggregate_sum: 'Agr: Sum',
+ aggregate_max: 'Agr: Máx',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Prom',
+ aggregate_remove: 'Agr: Quitar'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+/**
+ * Translated by: R. Salarmehr
+ * M. Hosseynzade
+ * Using Vajje.com online dictionary.
+ */
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('fa', {
+ aggregate: {
+ label: 'قلم'
+ },
+ groupPanel: {
+ description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'
+ },
+ search: {
+ placeholder: 'جستجو...',
+ showingItems: 'نمایش اقلام:',
+ selectedItems: 'قلم\u200cهای انتخاب شده:',
+ totalItems: 'مجموع اقلام:',
+ size: 'اندازه\u200cÛŒ صÙحه:',
+ first: 'اولین صÙحه',
+ next: 'صÙحه\u200cÛŒ\u200cبعدی',
+ previous: 'صÙحه\u200cÛŒ\u200c قبلی',
+ last: 'آخرین صÙحه'
+ },
+ menu: {
+ text: 'ستون\u200cهای انتخابی:'
+ },
+ sort: {
+ ascending: 'ترتیب صعودی',
+ descending: 'ترتیب نزولی',
+ remove: 'حذ٠مرتب کردن'
+ },
+ column: {
+ hide: 'پنهان\u200cکردن ستون'
+ },
+ aggregation: {
+ count: 'تعداد: ',
+ sum: 'مجموع: ',
+ avg: 'میانگین: ',
+ min: 'کمترین: ',
+ max: 'بیشترین: '
+ },
+ pinning: {
+ pinLeft: 'پین کردن سمت چپ',
+ pinRight: 'پین کردن سمت راست',
+ unpin: 'حذ٠پین'
+ },
+ gridMenu: {
+ columns: 'ستون\u200cها:',
+ importerTitle: 'وارد کردن Ùایل',
+ exporterAllAsCsv: 'خروجی تمام داده\u200cها در Ùایل csv',
+ exporterVisibleAsCsv: 'خروجی داده\u200cهای قابل مشاهده در Ùایل csv',
+ exporterSelectedAsCsv: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل csv',
+ exporterAllAsPdf: 'خروجی تمام داده\u200cها در Ùایل pdf',
+ exporterVisibleAsPdf: 'خروجی داده\u200cهای قابل مشاهده در Ùایل pdf',
+ exporterSelectedAsPdf: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل pdf',
+ clearAllFilters: 'پاک کردن تمام Ùیلتر'
+ },
+ importer: {
+ noHeaders: 'نام ستون قابل استخراج نیست. آیا Ùایل عنوان دارد؟',
+ noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\u200cها در Ùایل داده وجود دارد؟',
+ invalidCsv: 'Ùایل قابل پردازش نیست. آیا Ùرمت csv معتبر است؟',
+ invalidJson: 'Ùایل قابل پردازش نیست. آیا Ùرمت json معتبر است؟',
+ jsonNotArray: 'Ùایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'
+ },
+ pagination: {
+ sizes: 'اقلام در هر صÙحه',
+ totalItems: 'اقلام',
+ of: 'از'
+ },
+ grouping: {
+ group: 'گروه\u200cبندی',
+ ungroup: 'حذ٠گروه\u200cبندی',
+ aggregate_count: 'Agg: تعداد',
+ aggregate_sum: 'Agg: جمع',
+ aggregate_max: 'Agg: بیشینه',
+ aggregate_min: 'Agg: کمینه',
+ aggregate_avg: 'Agg: میانگین',
+ aggregate_remove: 'Agg: حذÙ'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('fi', {
+ aggregate: {
+ label: 'rivit'
+ },
+ groupPanel: {
+ description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'
+ },
+ search: {
+ placeholder: 'Hae...',
+ showingItems: 'Näytetään rivejä:',
+ selectedItems: 'Valitut rivit:',
+ totalItems: 'Rivejä yht.:',
+ size: 'Näytä:',
+ first: 'Ensimmäinen sivu',
+ next: 'Seuraava sivu',
+ previous: 'Edellinen sivu',
+ last: 'Viimeinen sivu'
+ },
+ menu: {
+ text: 'Valitse sarakkeet:'
+ },
+ sort: {
+ ascending: 'Järjestä nouseva',
+ descending: 'Järjestä laskeva',
+ remove: 'Poista järjestys'
+ },
+ column: {
+ hide: 'Piilota sarake'
+ },
+ aggregation: {
+ count: 'Rivejä yht.: ',
+ sum: 'Summa: ',
+ avg: 'K.a.: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Lukitse vasemmalle',
+ pinRight: 'Lukitse oikealle',
+ unpin: 'Poista lukitus'
+ },
+ gridMenu: {
+ columns: 'Sarakkeet:',
+ importerTitle: 'Tuo tiedosto',
+ exporterAllAsCsv: 'Vie tiedot csv-muodossa',
+ exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',
+ exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',
+ exporterAllAsPdf: 'Vie tiedot pdf-muodossa',
+ exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',
+ exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa',
+ clearAllFilters: 'Puhdista kaikki suodattimet'
+ },
+ importer: {
+ noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',
+ noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',
+ invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',
+ invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',
+ jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('fr', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filtre de la colonne',
+ removeFilter: 'Supprimer le filtre',
+ columnMenuButtonLabel: 'Menu de la colonne'
+ },
+ priority: 'Priorité:',
+ filterLabel: "Filtre de la colonne: "
+ },
+ aggregate: {
+ label: 'éléments'
+ },
+ groupPanel: {
+ description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'
+ },
+ search: {
+ placeholder: 'Recherche...',
+ showingItems: 'Affichage des éléments :',
+ selectedItems: 'Éléments sélectionnés :',
+ totalItems: 'Nombre total d\'éléments:',
+ size: 'Taille de page:',
+ first: 'Première page',
+ next: 'Page Suivante',
+ previous: 'Page précédente',
+ last: 'Dernière page'
+ },
+ menu: {
+ text: 'Choisir des colonnes :'
+ },
+ sort: {
+ ascending: 'Trier par ordre croissant',
+ descending: 'Trier par ordre décroissant',
+ none: 'Aucun tri',
+ remove: 'Enlever le tri'
+ },
+ column: {
+ hide: 'Cacher la colonne'
+ },
+ aggregation: {
+ count: 'lignes totales: ',
+ sum: 'total: ',
+ avg: 'moy: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Épingler à gauche',
+ pinRight: 'Épingler à droite',
+ unpin: 'Détacher'
+ },
+ columnMenu: {
+ close: 'Fermer'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Menu du tableau'
+ },
+ columns: 'Colonnes:',
+ importerTitle: 'Importer un fichier',
+ exporterAllAsCsv: 'Exporter toutes les données en CSV',
+ exporterVisibleAsCsv: 'Exporter les données visibles en CSV',
+ exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',
+ exporterAllAsPdf: 'Exporter toutes les données en PDF',
+ exporterVisibleAsPdf: 'Exporter les données visibles en PDF',
+ exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF',
+ clearAllFilters: 'Nettoyez tous les filtres'
+ },
+ importer: {
+ noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',
+ noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\'en-tête ?',
+ invalidCsv: 'Le fichier n\'a pas pu être traité, le CSV est-il valide ?',
+ invalidJson: 'Le fichier n\'a pas pu être traité, le JSON est-il valide ?',
+ jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Aller à la première page',
+ pageBack: 'Page précédente',
+ pageSelected: 'Page sélectionnée',
+ pageForward: 'Page suivante',
+ pageToLast: 'Aller à la dernière page'
+ },
+ sizes: 'éléments par page',
+ totalItems: 'éléments',
+ through: 'à',
+ of: 'sur'
+ },
+ grouping: {
+ group: 'Grouper',
+ ungroup: 'Dégrouper',
+ aggregate_count: 'Agg: Compter',
+ aggregate_sum: 'Agg: Somme',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Moy',
+ aggregate_remove: 'Agg: Retirer'
+ },
+ validate: {
+ error: 'Erreur:',
+ minLength: 'La valeur doit être supérieure ou égale à THRESHOLD caractères.',
+ maxLength: 'La valeur doit être inférieure ou égale à THRESHOLD caractères.',
+ required: 'Une valeur est nécéssaire.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('he', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'גרור עמודה לכ×ן ושחרר בכדי לקבץ עמודה זו.'
+ },
+ search: {
+ placeholder: 'חפש...',
+ showingItems: 'מציג:',
+ selectedItems: 'סה"כ נבחרו:',
+ totalItems: 'סה"כ רשומות:',
+ size: 'תוצ×ות בדף:',
+ first: 'דף ר×שון',
+ next: 'דף הב×',
+ previous: 'דף קוד×',
+ last: 'דף ×חרון'
+ },
+ menu: {
+ text: 'בחר עמודות:'
+ },
+ sort: {
+ ascending: 'סדר עולה',
+ descending: 'סדר יורד',
+ remove: 'בטל'
+ },
+ column: {
+ hide: 'טור הסתר'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clean all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('hy', {
+ aggregate: {
+ label: 'Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€'
+ },
+ groupPanel: {
+ description: 'Ô¸Õ½Õ¿ Õ½ÕµÕ¡Õ¶ Õ­Õ´Õ¢Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö„Õ¡Õ·Õ¥Ö„ Ö‡ Õ£ÖÕ¥Ö„ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰'
+ },
+ search: {
+ placeholder: 'Õ“Õ¶Õ¿Ö€Õ¸Ö‚Õ´...',
+ showingItems: 'Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ',
+ selectedItems: 'Ô¸Õ¶Õ¿Ö€Õ¾Õ¡Õ®:',
+ totalItems: 'Ô¸Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ',
+ size: 'ÕÕ¸Õ²Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨ Õ§Õ»Õ¸Ö‚Õ´Õ',
+ first: 'Ô±Õ¼Õ¡Õ»Õ«Õ¶ Õ§Õ»',
+ next: 'Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ§Õ»',
+ previous: 'Õ†Õ¡Õ­Õ¸Ö€Õ¤ Õ§Õ»',
+ last: 'ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ§Õ»'
+ },
+ menu: {
+ text: 'Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¥Ö€Õ¨:'
+ },
+ sort: {
+ ascending: 'Ô±Õ³Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
+ descending: 'Õ†Õ¾Õ¡Õ¦Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
+ remove: 'Õ€Õ¡Õ¶Õ¥Õ¬ '
+ },
+ column: {
+ hide: 'Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¨'
+ },
+ aggregation: {
+ count: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨ Õ¿Õ¸Õ²Õ ',
+ sum: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ ',
+ avg: 'Õ´Õ«Õ»Õ«Õ¶Õ ',
+ min: 'Õ´Õ«Õ¶Õ ',
+ max: 'Õ´Õ¡Ö„Õ½Õ '
+ },
+ pinning: {
+ pinLeft: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ±Õ¡Õ­ Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
+ pinRight: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
+ unpin: 'Ô±Ö€Õ±Õ¡Õ¯Õ¥Õ¬'
+ },
+ gridMenu: {
+ columns: 'ÕÕµÕ¸Ö‚Õ¶Õ¥Ö€:',
+ importerTitle: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ Ö†Õ¡ÕµÕ¬',
+ exporterAllAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨ CSV',
+ exporterVisibleAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
+ exporterSelectedAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
+ exporterAllAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ PDF',
+ exporterVisibleAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
+ exporterSelectedAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
+ clearAllFilters: 'Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€Õ¨'
+ },
+ importer: {
+ noHeaders: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ½ÕµÕ¡Õ¶ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¨ Õ¸Ö‚Õ¶Õ« Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Ö‰',
+ noObjects: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰',
+ invalidCsv: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ CSV Õ§Ö‰',
+ invalidJson: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ Json Õ§Ö‰',
+ jsonNotArray: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¾Õ¡Õ® json Ö†Õ¡ÕµÕ¬Õ¨ ÕºÕ¥Õ¿Ö„ Õ§ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ« Õ¦Õ¡Õ¶Õ£Õ¾Õ¡Õ®, Õ¯Õ¡Õ½Õ¥ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('it', {
+ aggregate: {
+ label: 'elementi'
+ },
+ groupPanel: {
+ description: 'Trascina un\'intestazione all\'interno del gruppo della colonna.'
+ },
+ search: {
+ placeholder: 'Ricerca...',
+ showingItems: 'Mostra:',
+ selectedItems: 'Selezionati:',
+ totalItems: 'Totali:',
+ size: 'Tot Pagine:',
+ first: 'Prima',
+ next: 'Prossima',
+ previous: 'Precedente',
+ last: 'Ultima'
+ },
+ menu: {
+ text: 'Scegli le colonne:'
+ },
+ sort: {
+ ascending: 'Asc.',
+ descending: 'Desc.',
+ remove: 'Annulla ordinamento'
+ },
+ column: {
+ hide: 'Nascondi'
+ },
+ aggregation: {
+ count: 'righe totali: ',
+ sum: 'tot: ',
+ avg: 'media: ',
+ min: 'minimo: ',
+ max: 'massimo: '
+ },
+ pinning: {
+ pinLeft: 'Blocca a sx',
+ pinRight: 'Blocca a dx',
+ unpin: 'Blocca in alto'
+ },
+ gridMenu: {
+ columns: 'Colonne:',
+ importerTitle: 'Importa',
+ exporterAllAsCsv: 'Esporta tutti i dati in CSV',
+ exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',
+ exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',
+ exporterAllAsPdf: 'Esporta tutti i dati in PDF',
+ exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',
+ exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF',
+ clearAllFilters: 'Pulire tutti i filtri'
+ },
+ importer: {
+ noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\'interno del file?',
+ noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\'interno del file?',
+ invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',
+ invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',
+ jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Prima',
+ pageBack: 'Indietro',
+ pageSelected: 'Pagina selezionata',
+ pageForward: 'Avanti',
+ pageToLast: 'Ultima'
+ },
+ sizes: 'elementi per pagina',
+ totalItems: 'elementi',
+ through: 'a',
+ of: 'di'
+ },
+ grouping: {
+ group: 'Raggruppa',
+ ungroup: 'Separa',
+ aggregate_count: 'Agg: N. Elem.',
+ aggregate_sum: 'Agg: Somma',
+ aggregate_max: 'Agg: Massimo',
+ aggregate_min: 'Agg: Minimo',
+ aggregate_avg: 'Agg: Media',
+ aggregate_remove: 'Agg: Rimuovi'
+ },
+ validate: {
+ error: 'Errore:',
+ minLength: 'Lunghezza minima pari a THRESHOLD caratteri.',
+ maxLength: 'Lunghezza massima pari a THRESHOLD caratteri.',
+ required: 'Necessario inserire un valore.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ja', {
+ aggregate: {
+ label: 'é …ç›®'
+ },
+ groupPanel: {
+ description: 'ã“ã“ã«åˆ—ヘッダをドラッグアンドドロップã—ã¦ã€ãã®åˆ—ã§ã‚°ãƒ«ãƒ¼ãƒ—化ã—ã¾ã™ã€‚'
+ },
+ search: {
+ placeholder: '検索...',
+ showingItems: '表示中ã®é …ç›®:',
+ selectedItems: 'é¸æŠžã—ãŸé …ç›®:',
+ totalItems: 'é …ç›®ã®ç·æ•°:',
+ size: 'ページサイズ:',
+ first: '最åˆã®ãƒšãƒ¼ã‚¸',
+ next: '次ã®ãƒšãƒ¼ã‚¸',
+ previous: 'å‰ã®ãƒšãƒ¼ã‚¸',
+ last: 'å‰ã®ãƒšãƒ¼ã‚¸'
+ },
+ menu: {
+ text: '列ã®é¸æŠž:'
+ },
+ sort: {
+ ascending: '昇順ã«ä¸¦ã¹æ›¿ãˆ',
+ descending: 'é™é †ã«ä¸¦ã¹æ›¿ãˆ',
+ remove: '並ã¹æ›¿ãˆã®è§£é™¤'
+ },
+ column: {
+ hide: '列ã®éžè¡¨ç¤º'
+ },
+ aggregation: {
+ count: 'åˆè¨ˆè¡Œæ•°: ',
+ sum: 'åˆè¨ˆ: ',
+ avg: 'å¹³å‡: ',
+ min: '最å°: ',
+ max: '最大: '
+ },
+ pinning: {
+ pinLeft: 'å·¦ã«å›ºå®š',
+ pinRight: 'å³ã«å›ºå®š',
+ unpin: '固定解除'
+ },
+ gridMenu: {
+ columns: '列:',
+ importerTitle: 'ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ',
+ exporterAllAsCsv: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterVisibleAsCsv: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterSelectedAsCsv: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterAllAsPdf: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterVisibleAsPdf: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterSelectedAsPdf: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ clearAllFilters: 'ã™ã¹ã¦ã®ãƒ•ã‚£ãƒ«ã‚¿ã‚’清掃ã—ã¦ãã ã•ã„'
+ },
+ importer: {
+ noHeaders: '列åã‚’å–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ noObjects: 'オブジェクトをå–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ä»¥å¤–ã®ãƒ‡ãƒ¼ã‚¿ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ invalidCsv: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªCSVå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ invalidJson: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªJSONå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ jsonNotArray: 'インãƒãƒ¼ãƒˆã—ãŸJSONファイルã«ã¯é…列ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚処ç†ã‚’中止ã—ã¾ã™ã€‚'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: '最åˆã®ãƒšãƒ¼ã‚¸',
+ pageBack: 'å‰ã®ãƒšãƒ¼ã‚¸',
+ pageSelected: 'ç¾åœ¨ã®ãƒšãƒ¼ã‚¸',
+ pageForward: '次ã®ãƒšãƒ¼ã‚¸',
+ pageToLast: '最後ã®ãƒšãƒ¼ã‚¸'
+ },
+ sizes: '項目/ページ',
+ totalItems: 'é …ç›®',
+ through: 'ã‹ã‚‰',
+ of: 'é …ç›®/å…¨'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ko', {
+ aggregate: {
+ label: 'ì•„ì´í…œ'
+ },
+ groupPanel: {
+ description: '컬럼으로 그룹핑하기 위해서는 컬럼 í—¤ë”를 ëŒì–´ 떨어뜨려 주세요.'
+ },
+ search: {
+ placeholder: '검색...',
+ showingItems: '항목 보여주기:',
+ selectedItems: 'ì„ íƒ í•­ëª©:',
+ totalItems: '전체 항목:',
+ size: '페ì´ì§€ í¬ê¸°:',
+ first: '첫번째 페ì´ì§€',
+ next: 'ë‹¤ìŒ íŽ˜ì´ì§€',
+ previous: 'ì´ì „ 페ì´ì§€',
+ last: '마지막 페ì´ì§€'
+ },
+ menu: {
+ text: 'ì»¬ëŸ¼ì„ ì„ íƒí•˜ì„¸ìš”:'
+ },
+ sort: {
+ ascending: '오름차순 정렬',
+ descending: '내림차순 정렬',
+ remove: '소팅 제거'
+ },
+ column: {
+ hide: '컬럼 제거'
+ },
+ aggregation: {
+ count: '전체 갯수: ',
+ sum: 'ì „ì²´: ',
+ avg: 'í‰ê· : ',
+ min: '최소: ',
+ max: '최대: '
+ },
+ pinning: {
+ pinLeft: '왼쪽 핀',
+ pinRight: '오른쪽 핀',
+ unpin: '핀 제거'
+ },
+ gridMenu: {
+ columns: '컬럼:',
+ importerTitle: 'íŒŒì¼ ê°€ì ¸ì˜¤ê¸°',
+ exporterAllAsCsv: 'csvë¡œ 모든 ë°ì´í„° 내보내기',
+ exporterVisibleAsCsv: 'csvë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
+ exporterSelectedAsCsv: 'csvë¡œ ì„ íƒëœ ë°ì´í„° 내보내기',
+ exporterAllAsPdf: 'pdfë¡œ 모든 ë°ì´í„° 내보내기',
+ exporterVisibleAsPdf: 'pdfë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
+ exporterSelectedAsPdf: 'pdfë¡œ ì„ íƒ ë°ì´í„° 내보내기',
+ clearAllFilters: '모든 필터를 청소'
+ },
+ importer: {
+ noHeaders: 'ì»¬ëŸ¼ëª…ì´ ì§€ì •ë˜ì–´ 있지 않습니다. 파ì¼ì— í—¤ë”ê°€ 명시ë˜ì–´ 있는지 확ì¸í•´ 주세요.',
+ noObjects: 'ë°ì´í„°ê°€ 지정ë˜ì–´ 있지 않습니다. ë°ì´í„°ê°€ 파ì¼ì— 있는지 확ì¸í•´ 주세요.',
+ invalidCsv: '파ì¼ì„ 처리할 수 없습니다. 올바른 csvì¸ì§€ 확ì¸í•´ 주세요.',
+ invalidJson: '파ì¼ì„ 처리할 수 없습니다. 올바른 jsonì¸ì§€ 확ì¸í•´ 주세요.',
+ jsonNotArray: 'json 파ì¼ì€ ë°°ì—´ì„ í¬í•¨í•´ì•¼ 합니다.'
+ },
+ pagination: {
+ sizes: '페ì´ì§€ë‹¹ 항목',
+ totalItems: '전체 항목'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('nl', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Sleep hier een kolomnaam heen om op te groeperen.'
+ },
+ search: {
+ placeholder: 'Zoeken...',
+ showingItems: 'Getoonde items:',
+ selectedItems: 'Geselecteerde items:',
+ totalItems: 'Totaal aantal items:',
+ size: 'Items per pagina:',
+ first: 'Eerste pagina',
+ next: 'Volgende pagina',
+ previous: 'Vorige pagina',
+ last: 'Laatste pagina'
+ },
+ menu: {
+ text: 'Kies kolommen:'
+ },
+ sort: {
+ ascending: 'Sorteer oplopend',
+ descending: 'Sorteer aflopend',
+ remove: 'Verwijder sortering'
+ },
+ column: {
+ hide: 'Verberg kolom'
+ },
+ aggregation: {
+ count: 'Aantal rijen: ',
+ sum: 'Som: ',
+ avg: 'Gemiddelde: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Zet links vast',
+ pinRight: 'Zet rechts vast',
+ unpin: 'Maak los'
+ },
+ gridMenu: {
+ columns: 'Kolommen:',
+ importerTitle: 'Importeer bestand',
+ exporterAllAsCsv: 'Exporteer alle data als csv',
+ exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',
+ exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',
+ exporterAllAsPdf: 'Exporteer alle data als pdf',
+ exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',
+ exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf',
+ clearAllFilters: 'Reinig alle filters'
+ },
+ importer: {
+ noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',
+ noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',
+ invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',
+ invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',
+ jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'
+ },
+ pagination: {
+ sizes: 'items per pagina',
+ totalItems: 'items',
+ of: 'van de'
+ },
+ grouping: {
+ group: 'Groepeer',
+ ungroup: 'Groepering opheffen',
+ aggregate_count: 'Agg: Aantal',
+ aggregate_sum: 'Agg: Som',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Gem',
+ aggregate_remove: 'Agg: Verwijder'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('no', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filter for column',
+ removeFilter: 'Remove Filter',
+ columnMenuButtonLabel: 'Column Menu'
+ },
+ priority: 'Priority:',
+ filterLabel: "Filter for column: "
+ },
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Drag a column header here and drop it to group by that column.'
+ },
+ search: {
+ placeholder: 'Search...',
+ showingItems: 'Showing Items:',
+ selectedItems: 'Selected Items:',
+ totalItems: 'Total Items:',
+ size: 'Page Size:',
+ first: 'First Page',
+ next: 'Next Page',
+ previous: 'Previous Page',
+ last: 'Last Page'
+ },
+ menu: {
+ text: 'Choose Columns:'
+ },
+ sort: {
+ ascending: 'Sort Ascending',
+ descending: 'Sort Descending',
+ none: 'Sort None',
+ remove: 'Remove Sort'
+ },
+ column: {
+ hide: 'Hide Column'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Pin Left',
+ pinRight: 'Pin Right',
+ unpin: 'Unpin'
+ },
+ columnMenu: {
+ close: 'Close'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Grid Menu'
+ },
+ columns: 'Kolonner:',
+ importerTitle: 'Importer fil',
+ exporterAllAsCsv: 'Eksporter alle data som csv',
+ exporterVisibleAsCsv: 'Eksporter synlige data som csv',
+ exporterSelectedAsCsv: 'Eksporter utvalgte data som csv',
+ exporterAllAsPdf: 'Eksporter alle data som pdf',
+ exporterVisibleAsPdf: 'Eksporter synlige data som pdf',
+ exporterSelectedAsPdf: 'Eksporter utvalgte data som pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Page to first',
+ pageBack: 'Page back',
+ pageSelected: 'Selected page',
+ pageForward: 'Page forward',
+ pageToLast: 'Page to last'
+ },
+ sizes: 'items per page',
+ totalItems: 'items',
+ through: 'through',
+ of: 'of'
+ },
+ grouping: {
+ group: 'Group',
+ ungroup: 'Ungroup',
+ aggregate_count: 'Agg: Count',
+ aggregate_sum: 'Agg: Sum',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Avg',
+ aggregate_remove: 'Agg: Remove'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('pl', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filtr dla kolumny',
+ removeFilter: 'Usuń filtr',
+ columnMenuButtonLabel: 'Menu kolumny'
+ },
+ priority: 'Prioritet:',
+ filterLabel: "Filtr dla kolumny: "
+ },
+ aggregate: {
+ label: 'pozycji'
+ },
+ groupPanel: {
+ description: 'Przeciągnij nagłówek kolumny tutaj, aby pogrupować według niej.'
+ },
+ search: {
+ placeholder: 'Szukaj...',
+ showingItems: 'Widoczne pozycje:',
+ selectedItems: 'Zaznaczone pozycje:',
+ totalItems: 'Wszystkich pozycji:',
+ size: 'Rozmiar strony:',
+ first: 'Pierwsza strona',
+ next: 'Następna strona',
+ previous: 'Poprzednia strona',
+ last: 'Ostatnia strona'
+ },
+ menu: {
+ text: 'Wybierz kolumny:'
+ },
+ sort: {
+ ascending: 'Sortuj rosnÄ…co',
+ descending: 'Sortuj malejÄ…co',
+ none: 'Brak sortowania',
+ remove: 'Wyłącz sortowanie'
+ },
+ column: {
+ hide: 'Ukryj kolumne'
+ },
+ aggregation: {
+ count: 'Razem pozycji: ',
+ sum: 'Razem: ',
+ avg: 'Åšrednia: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Przypnij do lewej',
+ pinRight: 'Przypnij do prawej',
+ unpin: 'Odepnij'
+ },
+ columnMenu: {
+ close: 'Zamknij'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Menu Grida'
+ },
+ columns: 'Kolumny:',
+ importerTitle: 'Importuj plik',
+ exporterAllAsCsv: 'Eksportuj wszystkie dane do csv',
+ exporterVisibleAsCsv: 'Eksportuj widoczne dane do csv',
+ exporterSelectedAsCsv: 'Eksportuj zaznaczone dane do csv',
+ exporterAllAsPdf: 'Eksportuj wszystkie dane do pdf',
+ exporterVisibleAsPdf: 'Eksportuj widoczne dane do pdf',
+ exporterSelectedAsPdf: 'Eksportuj zaznaczone dane do pdf',
+ clearAllFilters: 'Wyczyść filtry'
+ },
+ importer: {
+ noHeaders: 'Nie udało się wczytać nazw kolumn. Czy plik posiada nagłówek?',
+ noObjects: 'Nie udalo się wczytać pozycji. Czy plik zawiera dane??',
+ invalidCsv: 'Nie udało się przetworzyć pliku, jest to prawidlowy plik CSV??',
+ invalidJson: 'Nie udało się przetworzyć pliku, jest to prawidlowy plik Json?',
+ jsonNotArray: 'Importowany plik json musi zawierać tablicę, importowanie przerwane.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Pierwsza strona',
+ pageBack: 'Poprzednia strona',
+ pageSelected: 'Wybrana strona',
+ pageForward: 'Następna strona',
+ pageToLast: 'Ostatnia strona'
+ },
+ sizes: 'pozycji na stronÄ™',
+ totalItems: 'pozycji',
+ through: 'do',
+ of: 'z'
+ },
+ grouping: {
+ group: 'Grupuj',
+ ungroup: 'Rozgrupuj',
+ aggregate_count: 'Zbiorczo: Razem',
+ aggregate_sum: 'Zbiorczo: Suma',
+ aggregate_max: 'Zbiorczo: Max',
+ aggregate_min: 'Zbiorczo: Min',
+ aggregate_avg: 'Zbiorczo: Åšrednia',
+ aggregate_remove: 'Zbiorczo: Usuń'
+ },
+ validate: {
+ error: 'BÅ‚Ä…d:',
+ minLength: 'Wartość powinna składać się z co najmniej THRESHOLD znaków.',
+ maxLength: 'Wartość powinna składać się z przynajmniej THRESHOLD znaków.',
+ required: 'Wartość jest wymagana.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('pt-br', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filtro por coluna',
+ removeFilter: 'Remover filtro',
+ columnMenuButtonLabel: 'Menu coluna'
+ },
+ priority: 'Prioridade:',
+ filterLabel: "Filtro por coluna: "
+ },
+ aggregate: {
+ label: 'itens'
+ },
+ groupPanel: {
+ description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
+ },
+ search: {
+ placeholder: 'Procurar...',
+ showingItems: 'Mostrando os Itens:',
+ selectedItems: 'Items Selecionados:',
+ totalItems: 'Total de Itens:',
+ size: 'Tamanho da Página:',
+ first: 'Primeira Página',
+ next: 'Próxima Página',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Selecione as colunas:'
+ },
+ sort: {
+ ascending: 'Ordenar Ascendente',
+ descending: 'Ordenar Descendente',
+ none: 'Nenhuma Ordem',
+ remove: 'Remover Ordenação'
+ },
+ column: {
+ hide: 'Esconder coluna'
+ },
+ aggregation: {
+ count: 'total de linhas: ',
+ sum: 'total: ',
+ avg: 'med: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fixar Esquerda',
+ pinRight: 'Fixar Direita',
+ unpin: 'Desprender'
+ },
+ columnMenu: {
+ close: 'Fechar'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Menu Grid'
+ },
+ columns: 'Colunas:',
+ importerTitle: 'Importar arquivo',
+ exporterAllAsCsv: 'Exportar todos os dados como csv',
+ exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
+ exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
+ exporterAllAsPdf: 'Exportar todos os dados como pdf',
+ exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
+ exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
+ clearAllFilters: 'Limpar todos os filtros'
+ },
+ importer: {
+ noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',
+ noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',
+ invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',
+ invalidJson: 'Arquivo não pode ser processado. É um Json válido?',
+ jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Primeira página',
+ pageBack: 'Página anterior',
+ pageSelected: 'Página Selecionada',
+ pageForward: 'Proxima',
+ pageToLast: 'Anterior'
+ },
+ sizes: 'itens por página',
+ totalItems: 'itens',
+ through: 'através dos',
+ of: 'de'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Contar',
+ aggregate_sum: 'Agr: Soma',
+ aggregate_max: 'Agr: Max',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Med',
+ aggregate_remove: 'Agr: Remover'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('pt', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filtro por coluna',
+ removeFilter: 'Remover filtro',
+ columnMenuButtonLabel: 'Menu coluna'
+ },
+ priority: 'Prioridade:',
+ filterLabel: "Filtro por coluna: "
+ },
+ aggregate: {
+ label: 'itens'
+ },
+ groupPanel: {
+ description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
+ },
+ search: {
+ placeholder: 'Procurar...',
+ showingItems: 'Mostrando os Itens:',
+ selectedItems: 'Itens Selecionados:',
+ totalItems: 'Total de Itens:',
+ size: 'Tamanho da Página:',
+ first: 'Primeira Página',
+ next: 'Próxima Página',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Selecione as colunas:'
+ },
+ sort: {
+ ascending: 'Ordenar Ascendente',
+ descending: 'Ordenar Descendente',
+ none: 'Nenhuma Ordem',
+ remove: 'Remover Ordenação'
+ },
+ column: {
+ hide: 'Esconder coluna'
+ },
+ aggregation: {
+ count: 'total de linhas: ',
+ sum: 'total: ',
+ avg: 'med: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fixar Esquerda',
+ pinRight: 'Fixar Direita',
+ unpin: 'Desprender'
+ },
+ columnMenu: {
+ close: 'Fechar'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Menu Grid'
+ },
+ columns: 'Colunas:',
+ importerTitle: 'Importar ficheiro',
+ exporterAllAsCsv: 'Exportar todos os dados como csv',
+ exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
+ exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
+ exporterAllAsPdf: 'Exportar todos os dados como pdf',
+ exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
+ exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
+ clearAllFilters: 'Limpar todos os filtros'
+ },
+ importer: {
+ noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',
+ noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',
+ invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',
+ invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',
+ jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Primeira página',
+ pageBack: 'Página anterior',
+ pageSelected: 'Página Selecionada',
+ pageForward: 'Próxima',
+ pageToLast: 'Anterior'
+ },
+ sizes: 'itens por página',
+ totalItems: 'itens',
+ through: 'através dos',
+ of: 'de'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Contar',
+ aggregate_sum: 'Agr: Soma',
+ aggregate_max: 'Agr: Max',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Med',
+ aggregate_remove: 'Agr: Remover'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ro', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filtru pentru coloana',
+ removeFilter: 'Sterge filtru',
+ columnMenuButtonLabel: 'Column Menu'
+ },
+ priority: 'Prioritate:',
+ filterLabel: "Filtru pentru coloana:"
+ },
+ aggregate: {
+ label: 'Elemente'
+ },
+ groupPanel: {
+ description: 'Trage un cap de coloana aici pentru a grupa elementele dupa coloana respectiva'
+ },
+ search: {
+ placeholder: 'Cauta...',
+ showingItems: 'Arata elementele:',
+ selectedItems: 'Elementele selectate:',
+ totalItems: 'Total elemente:',
+ size: 'Marime pagina:',
+ first: 'Prima pagina',
+ next: 'Pagina urmatoare',
+ previous: 'Pagina anterioara',
+ last: 'Ultima pagina'
+ },
+ menu: {
+ text: 'Alege coloane:'
+ },
+ sort: {
+ ascending: 'Ordoneaza crescator',
+ descending: 'Ordoneaza descrescator',
+ none: 'Fara ordonare',
+ remove: 'Sterge ordonarea'
+ },
+ column: {
+ hide: 'Ascunde coloana'
+ },
+ aggregation: {
+ count: 'total linii: ',
+ sum: 'total: ',
+ avg: 'medie: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Pin la stanga',
+ pinRight: 'Pin la dreapta',
+ unpin: 'Sterge pinul'
+ },
+ columnMenu: {
+ close: 'Inchide'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Grid Menu'
+ },
+ columns: 'Coloane:',
+ importerTitle: 'Incarca fisier',
+ exporterAllAsCsv: 'Exporta toate datele ca csv',
+ exporterVisibleAsCsv: 'Exporta datele vizibile ca csv',
+ exporterSelectedAsCsv: 'Exporta datele selectate ca csv',
+ exporterAllAsPdf: 'Exporta toate datele ca pdf',
+ exporterVisibleAsPdf: 'Exporta datele vizibile ca pdf',
+ exporterSelectedAsPdf: 'Exporta datele selectate ca csv pdf',
+ clearAllFilters: 'Sterge toate filtrele'
+ },
+ importer: {
+ noHeaders: 'Numele coloanelor nu a putut fi incarcat, acest fisier are un header?',
+ noObjects: 'Datele nu au putut fi incarcate, exista date in fisier in afara numelor de coloane?',
+ invalidCsv: 'Fisierul nu a putut fi procesat, ati incarcat un CSV valid ?',
+ invalidJson: 'Fisierul nu a putut fi procesat, ati incarcat un Json valid?',
+ jsonNotArray: 'Json-ul incarcat trebuie sa contina un array, inchidere.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Prima pagina',
+ pageBack: 'O pagina inapoi',
+ pageSelected: 'Pagina selectata',
+ pageForward: 'O pagina inainte',
+ pageToLast: 'Ultima pagina'
+ },
+ sizes: 'Elemente per pagina',
+ totalItems: 'elemente',
+ through: 'prin',
+ of: 'of'
+ },
+ grouping: {
+ group: 'Grupeaza',
+ ungroup: 'Opreste gruparea',
+ aggregate_count: 'Agg: Count',
+ aggregate_sum: 'Agg: Sum',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Avg',
+ aggregate_remove: 'Agg: Remove'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ru', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Фильтр Ñтолбца',
+ removeFilter: 'Удалить фильтр',
+ columnMenuButtonLabel: 'Меню Ñтолбца'
+ },
+ priority: 'Приоритет:',
+ filterLabel: "Фильтр Ñтолбца: "
+ },
+ aggregate: {
+ label: 'Ñлементы'
+ },
+ groupPanel: {
+ description: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ по Ñтолбцу перетащите Ñюда его название.'
+ },
+ search: {
+ placeholder: 'ПоиÑк...',
+ showingItems: 'Показать Ñлементы:',
+ selectedItems: 'Выбранные Ñлементы:',
+ totalItems: 'Ð’Ñего Ñлементов:',
+ size: 'Размер Ñтраницы:',
+ first: 'ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница',
+ next: 'Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница',
+ previous: 'ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница',
+ last: 'ПоÑледнÑÑ Ñтраница'
+ },
+ menu: {
+ text: 'Выбрать Ñтолбцы:'
+ },
+ sort: {
+ ascending: 'По возраÑтанию',
+ descending: 'По убыванию',
+ none: 'Без Ñортировки',
+ remove: 'Убрать Ñортировку'
+ },
+ column: {
+ hide: 'СпрÑтать Ñтолбец'
+ },
+ aggregation: {
+ count: 'вÑего Ñтрок: ',
+ sum: 'итого: ',
+ avg: 'Ñреднее: ',
+ min: 'мин: ',
+ max: 'макÑ: '
+ },
+ pinning: {
+ pinLeft: 'Закрепить Ñлева',
+ pinRight: 'Закрепить Ñправа',
+ unpin: 'Открепить'
+ },
+ columnMenu: {
+ close: 'Закрыть'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Меню'
+ },
+ columns: 'Столбцы:',
+ importerTitle: 'Импортировать файл',
+ exporterAllAsCsv: 'ЭкÑпортировать вÑÑ‘ в CSV',
+ exporterVisibleAsCsv: 'ЭкÑпортировать видимые данные в CSV',
+ exporterSelectedAsCsv: 'ЭкÑпортировать выбранные данные в CSV',
+ exporterAllAsPdf: 'ЭкÑпортировать вÑÑ‘ в PDF',
+ exporterVisibleAsPdf: 'ЭкÑпортировать видимые данные в PDF',
+ exporterSelectedAsPdf: 'ЭкÑпортировать выбранные данные в PDF',
+ clearAllFilters: 'ОчиÑтите вÑе фильтры'
+ },
+ importer: {
+ noHeaders: 'Ðе удалоÑÑŒ получить Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñтолбцов, еÑÑ‚ÑŒ ли в файле заголовок?',
+ noObjects: 'Ðе удалоÑÑŒ получить данные, еÑÑ‚ÑŒ ли в файле Ñтроки кроме заголовка?',
+ invalidCsv: 'Ðе удалоÑÑŒ обработать файл, Ñто правильный CSV-файл?',
+ invalidJson: 'Ðе удалоÑÑŒ обработать файл, Ñто правильный JSON?',
+ jsonNotArray: 'Импортируемый JSON-файл должен Ñодержать маÑÑив, Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚Ð¼ÐµÐ½ÐµÐ½Ð°.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница',
+ pageBack: 'ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница',
+ pageSelected: 'Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ñтраница',
+ pageForward: 'Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница',
+ pageToLast: 'ПоÑледнÑÑ Ñтраница'
+ },
+ sizes: 'Ñтрок на Ñтраницу',
+ totalItems: 'Ñтрок',
+ through: 'по',
+ of: 'из'
+ },
+ grouping: {
+ group: 'Группировать',
+ ungroup: 'Разгруппировать',
+ aggregate_count: 'Группировать: Count',
+ aggregate_sum: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Сумма',
+ aggregate_max: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: МакÑимум',
+ aggregate_min: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Минимум',
+ aggregate_avg: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Среднее',
+ aggregate_remove: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: ПуÑто'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('sk', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'
+ },
+ search: {
+ placeholder: 'Hľadaj...',
+ showingItems: 'Zobrazujem položky:',
+ selectedItems: 'Vybraté položky:',
+ totalItems: 'PoÄet položiek:',
+ size: 'PoÄet:',
+ first: 'Prvá strana',
+ next: 'Ďalšia strana',
+ previous: 'Predchádzajúca strana',
+ last: 'Posledná strana'
+ },
+ menu: {
+ text: 'Vyberte stĺpce:'
+ },
+ sort: {
+ ascending: 'Zotriediť vzostupne',
+ descending: 'Zotriediť zostupne',
+ remove: 'Vymazať triedenie'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('sv', {
+ aggregate: {
+ label: 'Artiklar'
+ },
+ groupPanel: {
+ description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'
+ },
+ search: {
+ placeholder: 'Sök...',
+ showingItems: 'Visar artiklar:',
+ selectedItems: 'Valda artiklar:',
+ totalItems: 'Antal artiklar:',
+ size: 'Sidstorlek:',
+ first: 'Första sidan',
+ next: 'Nästa sida',
+ previous: 'Föregående sida',
+ last: 'Sista sidan'
+ },
+ menu: {
+ text: 'Välj kolumner:'
+ },
+ sort: {
+ ascending: 'Sortera stigande',
+ descending: 'Sortera fallande',
+ remove: 'Inaktivera sortering'
+ },
+ column: {
+ hide: 'Göm kolumn'
+ },
+ aggregation: {
+ count: 'Antal rader: ',
+ sum: 'Summa: ',
+ avg: 'Genomsnitt: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Fäst vänster',
+ pinRight: 'Fäst höger',
+ unpin: 'Lösgör'
+ },
+ gridMenu: {
+ columns: 'Kolumner:',
+ importerTitle: 'Importera fil',
+ exporterAllAsCsv: 'Exportera all data som CSV',
+ exporterVisibleAsCsv: 'Exportera synlig data som CSV',
+ exporterSelectedAsCsv: 'Exportera markerad data som CSV',
+ exporterAllAsPdf: 'Exportera all data som PDF',
+ exporterVisibleAsPdf: 'Exportera synlig data som PDF',
+ exporterSelectedAsPdf: 'Exportera markerad data som PDF',
+ clearAllFilters: 'Rengör alla filter'
+ },
+ importer: {
+ noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',
+ noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',
+ invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',
+ invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',
+ jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'
+ },
+ pagination: {
+ sizes: 'Artiklar per sida',
+ totalItems: 'Artiklar'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ta', {
+ aggregate: {
+ label: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯'
+ },
+ groupPanel: {
+ description: 'ஒர௠பதà¯à®¤à®¿à®¯à¯ˆ கà¯à®´à¯à®µà®¾à®• அமைகà¯à®• அபà¯à®ªà®¤à¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯ˆ இஙà¯à®•à¯‡ இழà¯à®¤à¯à®¤à¯ வரவà¯à®®à¯ '
+ },
+ search: {
+ placeholder: 'தேடல௠...',
+ showingItems: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ˆ காணà¯à®ªà®¿à®¤à¯à®¤à®²à¯:',
+ selectedItems: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
+ totalItems: 'மொதà¯à®¤ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
+ size: 'பகà¯à®• அளவà¯: ',
+ first: 'à®®à¯à®¤à®²à¯ பகà¯à®•à®®à¯',
+ next: 'அடà¯à®¤à¯à®¤ பகà¯à®•à®®à¯',
+ previous: 'à®®à¯à®¨à¯à®¤à¯ˆà®¯ பகà¯à®•à®®à¯ ',
+ last: 'இறà¯à®¤à®¿ பகà¯à®•à®®à¯'
+ },
+ menu: {
+ text: 'பதà¯à®¤à®¿à®•à®³à¯ˆ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯:'
+ },
+ sort: {
+ ascending: 'மேலிரà¯à®¨à¯à®¤à¯ கீழாக',
+ descending: 'கீழிரà¯à®¨à¯à®¤à¯ மேலாக',
+ remove: 'வரிசையை நீகà¯à®•à¯'
+ },
+ column: {
+ hide: 'பதà¯à®¤à®¿à®¯à¯ˆ மறைதà¯à®¤à¯ வை '
+ },
+ aggregation: {
+ count: 'மொதà¯à®¤ வரிகளà¯:',
+ sum: 'மொதà¯à®¤à®®à¯: ',
+ avg: 'சராசரி: ',
+ min: 'கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®š: ',
+ max: 'அதிகபடà¯à®š: '
+ },
+ pinning: {
+ pinLeft: 'இடதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®• ',
+ pinRight: 'வலதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®•',
+ unpin: 'பிரி'
+ },
+ gridMenu: {
+ columns: 'பதà¯à®¤à®¿à®•à®³à¯:',
+ importerTitle: 'கோபà¯à®ªà¯ : படிதà¯à®¤à®²à¯',
+ exporterAllAsCsv: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterVisibleAsCsv: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterSelectedAsCsv: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterAllAsPdf: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ exporterVisibleAsPdf: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ exporterSelectedAsPdf: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'பதà¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ பெற இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà®¿à®±à¯à®•à¯ தலைபà¯à®ªà¯ உளà¯à®³à®¤à®¾?',
+ noObjects: 'இலகà¯à®•à¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ, கோபà¯à®ªà®¿à®²à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ தவிர தரவ௠à®à®¤à¯‡à®©à¯à®®à¯ உளà¯à®³à®¤à®¾? ',
+ invalidCsv: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - csv',
+ invalidJson: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - json',
+ jsonNotArray: 'படிதà¯à®¤ கோபà¯à®ªà®¿à®²à¯ வரிசைகள௠உளà¯à®³à®¤à¯, நடைமà¯à®±à¯ˆ ரதà¯à®¤à¯ செய௠: json'
+ },
+ pagination: {
+ sizes : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ / பகà¯à®•à®®à¯',
+ totalItems : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ '
+ },
+ grouping: {
+ group : 'கà¯à®´à¯',
+ ungroup : 'பிரி',
+ aggregate_count : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : எணà¯à®£à¯',
+ aggregate_sum : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கூடà¯à®Ÿà®²à¯',
+ aggregate_max : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : அதிகபடà¯à®šà®®à¯',
+ aggregate_min : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯',
+ aggregate_avg : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : சராசரி',
+ aggregate_remove : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : நீகà¯à®•à¯'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('tr', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Sütun için filtre',
+ removeFilter: 'Filtreyi Kaldır',
+ columnMenuButtonLabel: 'Sütun Menüsü'
+ },
+ priority: 'Öncelik:',
+ filterLabel: "Sütun için filtre: "
+ },
+ aggregate: {
+ label: 'kayıtlar'
+ },
+ groupPanel: {
+ description: 'Sütuna göre gruplamak için sütun başlığını buraya sürükleyin ve bırakın.'
+ },
+ search: {
+ placeholder: 'Arama...',
+ showingItems: 'Gösterilen Kayıt:',
+ selectedItems: 'Seçili Kayıt:',
+ totalItems: 'Toplam Kayıt:',
+ size: 'Sayfa Boyutu:',
+ first: 'Ä°lk Sayfa',
+ next: 'Sonraki Sayfa',
+ previous: 'Önceki Sayfa',
+ last: 'Son Sayfa'
+ },
+ menu: {
+ text: 'Sütunları Seç:'
+ },
+ sort: {
+ ascending: 'Artan Sırada Sırala',
+ descending: 'Azalan Sırada Sırala',
+ none: 'Sıralama Yapma',
+ remove: 'Sıralamayı Kaldır'
+ },
+ column: {
+ hide: 'Sütunu Gizle'
+ },
+ aggregation: {
+ count: 'toplam satır: ',
+ sum: 'toplam: ',
+ avg: 'ort: ',
+ min: 'min: ',
+ max: 'maks: '
+ },
+ pinning: {
+ pinLeft: 'Sola Sabitle',
+ pinRight: 'SaÄŸa Sabitle',
+ unpin: 'Sabitlemeyi Kaldır'
+ },
+ columnMenu: {
+ close: 'Kapat'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Tablo Menü'
+ },
+ columns: 'Sütunlar:',
+ importerTitle: 'Dosya içeri aktar',
+ exporterAllAsCsv: 'Bütün veriyi CSV olarak dışarı aktar',
+ exporterVisibleAsCsv: 'Görünen veriyi CSV olarak dışarı aktar',
+ exporterSelectedAsCsv: 'Seçili veriyi CSV olarak dışarı aktar',
+ exporterAllAsPdf: 'Bütün veriyi PDF olarak dışarı aktar',
+ exporterVisibleAsPdf: 'Görünen veriyi PDF olarak dışarı aktar',
+ exporterSelectedAsPdf: 'Seçili veriyi PDF olarak dışarı aktar',
+ clearAllFilters: 'Bütün filtreleri kaldır'
+ },
+ importer: {
+ noHeaders: 'Sütun isimleri üretilemiyor, dosyanın bir başlığı var mı?',
+ noObjects: 'Nesneler üretilemiyor, dosyada başlıktan başka bir veri var mı?',
+ invalidCsv: 'Dosya işlenemedi, geçerli bir CSV dosyası mı?',
+ invalidJson: 'Dosya işlenemedi, geçerli bir Json dosyası mı?',
+ jsonNotArray: 'Alınan Json dosyasında bir dizi bulunmalıdır, işlem iptal ediliyor.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Ä°lk sayfaya',
+ pageBack: 'Geri git',
+ pageSelected: 'Seçili sayfa',
+ pageForward: 'Ä°leri git',
+ pageToLast: 'Sona git'
+ },
+ sizes: 'Sayfadaki nesne sayısı',
+ totalItems: 'kayıtlar',
+ through: '', //note(fsw) : turkish dont have this preposition
+ of: '' //note(fsw) : turkish dont have this preposition
+ },
+ grouping: {
+ group: 'Grupla',
+ ungroup: 'Gruplama',
+ aggregate_count: 'Yekun: Sayı',
+ aggregate_sum: 'Yekun: Toplam',
+ aggregate_max: 'Yekun: Maks',
+ aggregate_min: 'Yekun: Min',
+ aggregate_avg: 'Yekun: Ort',
+ aggregate_remove: 'Yekun: Sil'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ua', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Фільтр Ñтовпчика',
+ removeFilter: 'Видалити фільтр',
+ columnMenuButtonLabel: 'Меню Ñтвпчика'
+ },
+ priority: 'Пріоритет:',
+ filterLabel: "Фільтр Ñтовпчика: "
+ },
+ aggregate: {
+ label: 'елементи'
+ },
+ groupPanel: {
+ description: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° Ñтовпчиком перетÑгніть Ñюди його назву.'
+ },
+ search: {
+ placeholder: 'Пошук...',
+ showingItems: 'Показати елементи:',
+ selectedItems: 'Обрані елементи:',
+ totalItems: 'УÑього елементів:',
+ size: 'Розмір Ñторінки:',
+ first: 'Перша Ñторінка',
+ next: 'ÐаÑтупна Ñторінка',
+ previous: 'ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка',
+ last: 'ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка'
+ },
+ menu: {
+ text: 'Обрати Ñтвпчики:'
+ },
+ sort: {
+ ascending: 'За зроÑтаннÑм',
+ descending: 'За ÑпаданнÑм',
+ none: 'Без ÑортуваннÑ',
+ remove: 'Прибрати ÑортуваннÑ'
+ },
+ column: {
+ hide: 'Приховати Ñтовпчик'
+ },
+ aggregation: {
+ count: 'уÑього Ñ€Ñдків: ',
+ sum: 'ітого: ',
+ avg: 'Ñереднє: ',
+ min: 'мін: ',
+ max: 'макÑ: '
+ },
+ pinning: {
+ pinLeft: 'Закріпити ліворуч',
+ pinRight: 'Закріпити праворуч',
+ unpin: 'Відкріпити'
+ },
+ columnMenu: {
+ close: 'Закрити'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Меню'
+ },
+ columns: 'Стовпчики:',
+ importerTitle: 'Імпортувати файл',
+ exporterAllAsCsv: 'ЕкÑпортувати вÑе в CSV',
+ exporterVisibleAsCsv: 'ЕкÑпортувати видимі дані в CSV',
+ exporterSelectedAsCsv: 'ЕкÑпортувати обрані дані в CSV',
+ exporterAllAsPdf: 'ЕкÑпортувати вÑе в PDF',
+ exporterVisibleAsPdf: 'ЕкÑпортувати видимі дані в PDF',
+ exporterSelectedAsPdf: 'ЕкÑпортувати обрані дані в PDF',
+ clearAllFilters: 'ОчиÑтити вÑÑ– фільтри'
+ },
+ importer: {
+ noHeaders: 'Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ назви Ñтовпчиків, чи Ñ” в файлі заголовок?',
+ noObjects: 'Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ дані, чи Ñ” в файлі Ñ€Ñдки окрім заголовка?',
+ invalidCsv: 'Ðе вдалоÑÑ Ð¾Ð±Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ файл, чи це коректний CSV-файл?',
+ invalidJson: 'Ðе вдалоÑÑ Ð¾Ð±Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ файл, чи це коректний JSON?',
+ jsonNotArray: 'JSON-файл що імпортуєтьÑÑ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ міÑтити маÑив, операцію ÑкаÑовано.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Перша Ñторінка',
+ pageBack: 'ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка',
+ pageSelected: 'Обрана Ñторінка',
+ pageForward: 'ÐаÑтупна Ñторінка',
+ pageToLast: 'ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка'
+ },
+ sizes: 'Ñ€Ñдків на Ñторінку',
+ totalItems: 'Ñ€Ñдків',
+ through: 'по',
+ of: 'з'
+ },
+ grouping: {
+ group: 'Групувати',
+ ungroup: 'Розгрупувати',
+ aggregate_count: 'Групувати: КількіÑÑ‚ÑŒ',
+ aggregate_sum: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Сума',
+ aggregate_max: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: МакÑимум',
+ aggregate_min: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Мінімум',
+ aggregate_avg: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Серднє',
+ aggregate_remove: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: ПуÑто'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+/**
+ * @ngdoc overview
+ * @name ui.grid.i18n
+ * @description
+ *
+ * # ui.grid.i18n
+ * This module provides i18n functions to ui.grid and any application that wants to use it
+
+ *
+ * <div doc-module-components="ui.grid.i18n"></div>
+ */
+
+(function () {
+ var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];
+ var FILTER_ALIASES = ['t', 'uiTranslate'];
+
+ var module = angular.module('ui.grid.i18n');
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.i18n.constant:i18nConstants
+ *
+ * @description constants available in i18n module
+ */
+ module.constant('i18nConstants', {
+ MISSING: '[MISSING]',
+ UPDATE_EVENT: '$uiI18n',
+
+ LOCALE_DIRECTIVE_ALIAS: 'uiI18n',
+ // default to english
+ DEFAULT_LANG: 'en'
+ });
+
+// module.config(['$provide', function($provide) {
+// $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.i18n.service:i18nService
+ *
+ * @description Services for i18n
+ */
+ module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',
+ function ($log, i18nConstants, $rootScope) {
+
+ var langCache = {
+ _langs: {},
+ current: null,
+ get: function (lang) {
+ return this._langs[lang.toLowerCase()];
+ },
+ add: function (lang, strings) {
+ var lower = lang.toLowerCase();
+ if (!this._langs[lower]) {
+ this._langs[lower] = {};
+ }
+ angular.extend(this._langs[lower], strings);
+ },
+ getAllLangs: function () {
+ var langs = [];
+ if (!this._langs) {
+ return langs;
+ }
+
+ for (var key in this._langs) {
+ langs.push(key);
+ }
+
+ return langs;
+ },
+ setCurrent: function (lang) {
+ this.current = lang.toLowerCase();
+ },
+ getCurrentLang: function () {
+ return this.current;
+ }
+ };
+
+ var service = {
+
+ /**
+ * @ngdoc service
+ * @name add
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description Adds the languages and strings to the cache. Decorate this service to
+ * add more translation strings
+ * @param {string} lang language to add
+ * @param {object} stringMaps of strings to add grouped by property names
+ * @example
+ * <pre>
+ * i18nService.add('en', {
+ * aggregate: {
+ * label1: 'items',
+ * label2: 'some more items'
+ * }
+ * },
+ * groupPanel: {
+ * description: 'Drag a column header here and drop it to group by that column.'
+ * }
+ * }
+ * </pre>
+ */
+ add: function (langs, stringMaps) {
+ if (typeof(langs) === 'object') {
+ angular.forEach(langs, function (lang) {
+ if (lang) {
+ langCache.add(lang, stringMaps);
+ }
+ });
+ } else {
+ langCache.add(langs, stringMaps);
+ }
+ },
+
+ /**
+ * @ngdoc service
+ * @name getAllLangs
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description return all currently loaded languages
+ * @returns {array} string
+ */
+ getAllLangs: function () {
+ return langCache.getAllLangs();
+ },
+
+ /**
+ * @ngdoc service
+ * @name get
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description return all currently loaded languages
+ * @param {string} lang to return. If not specified, returns current language
+ * @returns {object} the translation string maps for the language
+ */
+ get: function (lang) {
+ var language = lang ? lang : service.getCurrentLang();
+ return langCache.get(language);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getSafeText
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description returns the text specified in the path or a Missing text if text is not found
+ * @param {string} path property path to use for retrieving text from string map
+ * @param {string} lang to return. If not specified, returns current language
+ * @returns {object} the translation for the path
+ * @example
+ * <pre>
+ * i18nService.getSafeText('sort.ascending')
+ * </pre>
+ */
+ getSafeText: function (path, lang) {
+ var language = lang ? lang : service.getCurrentLang();
+ var trans = langCache.get(language);
+
+ if (!trans) {
+ return i18nConstants.MISSING;
+ }
+
+ var paths = path.split('.');
+ var current = trans;
+
+ for (var i = 0; i < paths.length; ++i) {
+ if (current[paths[i]] === undefined || current[paths[i]] === null) {
+ return i18nConstants.MISSING;
+ } else {
+ current = current[paths[i]];
+ }
+ }
+
+ return current;
+
+ },
+
+ /**
+ * @ngdoc service
+ * @name setCurrentLang
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description sets the current language to use in the application
+ * $broadcasts the Update_Event on the $rootScope
+ * @param {string} lang to set
+ * @example
+ * <pre>
+ * i18nService.setCurrentLang('fr');
+ * </pre>
+ */
+
+ setCurrentLang: function (lang) {
+ if (lang) {
+ langCache.setCurrent(lang);
+ $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);
+ }
+ },
+
+ /**
+ * @ngdoc service
+ * @name getCurrentLang
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description returns the current language used in the application
+ */
+ getCurrentLang: function () {
+ var lang = langCache.getCurrentLang();
+ if (!lang) {
+ lang = i18nConstants.DEFAULT_LANG;
+ langCache.setCurrent(lang);
+ }
+ return lang;
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ var localeDirective = function (i18nService, i18nConstants) {
+ return {
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;
+ // check for watchable property
+ var lang = $scope.$eval($attrs[alias]);
+ if (lang) {
+ $scope.$watch($attrs[alias], function () {
+ i18nService.setCurrentLang(lang);
+ });
+ } else if ($attrs.$$observers) {
+ $attrs.$observe(alias, function () {
+ i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);
+ });
+ }
+ }
+ };
+ }
+ };
+ };
+
+ module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);
+
+ // directive syntax
+ var uitDirective = function ($parse, i18nService, i18nConstants) {
+ return {
+ restrict: 'EA',
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var alias1 = DIRECTIVE_ALIASES[0],
+ alias2 = DIRECTIVE_ALIASES[1];
+ var token = $attrs[alias1] || $attrs[alias2] || $elm.html();
+ var missing = i18nConstants.MISSING + token;
+ var observer;
+ if ($attrs.$$observers) {
+ var prop = $attrs[alias1] ? alias1 : alias2;
+ observer = $attrs.$observe(prop, function (result) {
+ if (result) {
+ $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);
+ }
+ });
+ }
+ var getter = $parse(token);
+ var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {
+ if (observer) {
+ observer($attrs[alias1] || $attrs[alias2]);
+ } else {
+ // set text based on i18n current language
+ $elm.html(getter(i18nService.get()) || missing);
+ }
+ });
+ $scope.$on('$destroy', listener);
+
+ $elm.html(getter(i18nService.get()) || missing);
+ }
+ };
+ }
+ };
+ };
+
+ angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {
+ module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );
+ } );
+
+ // optional filter syntax
+ var uitFilter = function ($parse, i18nService, i18nConstants) {
+ return function (data) {
+ var getter = $parse(data);
+ // set text based on i18n current language
+ return getter(i18nService.get()) || i18nConstants.MISSING + data;
+ };
+ };
+
+ angular.forEach( FILTER_ALIASES, function ( alias ) {
+ module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );
+ } );
+
+
+})();
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('zh-cn', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: '列过滤器',
+ removeFilter: '移除过滤器',
+ columnMenuButtonLabel: '列èœå•'
+ },
+ priority: '优先级:',
+ filterLabel: "列过滤器: "
+ },
+ aggregate: {
+ label: '行'
+ },
+ groupPanel: {
+ description: '拖曳表头到此处进行分组'
+ },
+ search: {
+ placeholder: '查找',
+ showingItems: '已显示行数:',
+ selectedItems: '已选择行数:',
+ totalItems: '总行数:',
+ size: 'æ¯é¡µæ˜¾ç¤ºè¡Œæ•°ï¼š',
+ first: '首页',
+ next: '下一页',
+ previous: '上一页',
+ last: '末页'
+ },
+ menu: {
+ text: '选择列:'
+ },
+ sort: {
+ ascending: 'å‡åº',
+ descending: 'é™åº',
+ none: 'æ— åº',
+ remove: 'å–消排åº'
+ },
+ column: {
+ hide: 'éšè—列'
+ },
+ aggregation: {
+ count: '计数:',
+ sum: '求和:',
+ avg: 'å‡å€¼ï¼š',
+ min: '最å°å€¼ï¼š',
+ max: '最大值:'
+ },
+ pinning: {
+ pinLeft: '左侧固定',
+ pinRight: 'å³ä¾§å›ºå®š',
+ unpin: 'å–消固定'
+ },
+ columnMenu: {
+ close: '关闭'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: '表格èœå•'
+ },
+ columns: '列:',
+ importerTitle: '导入文件',
+ exporterAllAsCsv: '导出全部数æ®åˆ°CSV',
+ exporterVisibleAsCsv: '导出å¯è§æ•°æ®åˆ°CSV',
+ exporterSelectedAsCsv: '导出已选数æ®åˆ°CSV',
+ exporterAllAsPdf: '导出全部数æ®åˆ°PDF',
+ exporterVisibleAsPdf: '导出å¯è§æ•°æ®åˆ°PDF',
+ exporterSelectedAsPdf: '导出已选数æ®åˆ°PDF',
+ clearAllFilters: '清除所有过滤器'
+ },
+ importer: {
+ noHeaders: '无法获å–列å,确定文件包å«è¡¨å¤´ï¼Ÿ',
+ noObjects: '无法获å–æ•°æ®ï¼Œç¡®å®šæ–‡ä»¶åŒ…å«æ•°æ®ï¼Ÿ',
+ invalidCsv: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„CSV文件?',
+ invalidJson: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„JSON文件?',
+ jsonNotArray: '导入的文件ä¸æ˜¯JSON数组ï¼'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: '第一页',
+ pageBack: '上一页',
+ pageSelected: '当å‰é¡µ',
+ pageForward: '下一页',
+ pageToLast: '最åŽä¸€é¡µ'
+ },
+ sizes: 'è¡Œæ¯é¡µ',
+ totalItems: '行',
+ through: '至',
+ of: 'å…±'
+ },
+ grouping: {
+ group: '分组',
+ ungroup: 'å–消分组',
+ aggregate_count: 'åˆè®¡: 计数',
+ aggregate_sum: 'åˆè®¡: 求和',
+ aggregate_max: 'åˆè®¡: 最大',
+ aggregate_min: 'åˆè®¡: 最å°',
+ aggregate_avg: 'åˆè®¡: å¹³å‡',
+ aggregate_remove: 'åˆè®¡: 移除'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('zh-tw', {
+ aggregate: {
+ label: '行'
+ },
+ groupPanel: {
+ description: '拖曳表頭到此處進行分組'
+ },
+ search: {
+ placeholder: '查找',
+ showingItems: '已顯示行數:',
+ selectedItems: 'å·²é¸æ“‡è¡Œæ•¸ï¼š',
+ totalItems: '總行數:',
+ size: 'æ¯é é¡¯ç¤ºè¡Œæ•¸ï¼š',
+ first: '首é ',
+ next: '下壹é ',
+ previous: '上壹é ',
+ last: '末é '
+ },
+ menu: {
+ text: 'é¸æ“‡åˆ—:'
+ },
+ sort: {
+ ascending: 'å‡åº',
+ descending: 'é™åº',
+ remove: 'å–消排åº'
+ },
+ column: {
+ hide: 'éš±è—列'
+ },
+ aggregation: {
+ count: '計數:',
+ sum: '求和:',
+ avg: 'å‡å€¼ï¼š',
+ min: '最å°å€¼ï¼š',
+ max: '最大值:'
+ },
+ pinning: {
+ pinLeft: 'å·¦å´å›ºå®š',
+ pinRight: 'å³å´å›ºå®š',
+ unpin: 'å–消固定'
+ },
+ gridMenu: {
+ columns: '列:',
+ importerTitle: '導入文件',
+ exporterAllAsCsv: '導出全部數據到CSV',
+ exporterVisibleAsCsv: '導出å¯è¦‹æ•¸æ“šåˆ°CSV',
+ exporterSelectedAsCsv: '導出已é¸æ•¸æ“šåˆ°CSV',
+ exporterAllAsPdf: '導出全部數據到PDF',
+ exporterVisibleAsPdf: '導出å¯è¦‹æ•¸æ“šåˆ°PDF',
+ exporterSelectedAsPdf: '導出已é¸æ•¸æ“šåˆ°PDF',
+ clearAllFilters: '清除所有过滤器'
+ },
+ importer: {
+ noHeaders: '無法ç²å–列å,確定文件包å«è¡¨é ­ï¼Ÿ',
+ noObjects: '無法ç²å–數據,確定文件包å«æ•¸æ“šï¼Ÿ',
+ invalidCsv: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„CSV文件?',
+ invalidJson: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„JSON文件?',
+ jsonNotArray: '導入的文件ä¸æ˜¯JSON數組ï¼'
+ },
+ pagination: {
+ sizes: 'è¡Œæ¯é ',
+ totalItems: '行'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.autoResize
+ *
+ * @description
+ *
+ * #ui.grid.autoResize
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides auto-resizing functionality to UI-Grid.
+ */
+ var module = angular.module('ui.grid.autoResize', ['ui.grid']);
+
+
+ module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {
+ return {
+ require: 'uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var prevGridWidth, prevGridHeight;
+
+ function getDimensions() {
+ prevGridHeight = gridUtil.elementHeight($elm);
+ prevGridWidth = gridUtil.elementWidth($elm);
+ }
+
+ // Initialize the dimensions
+ getDimensions();
+
+ var resizeTimeoutId;
+ function startTimeout() {
+ clearTimeout(resizeTimeoutId);
+
+ resizeTimeoutId = setTimeout(function () {
+ var newGridHeight = gridUtil.elementHeight($elm);
+ var newGridWidth = gridUtil.elementWidth($elm);
+
+ if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {
+ uiGridCtrl.grid.gridHeight = newGridHeight;
+ uiGridCtrl.grid.gridWidth = newGridWidth;
+ uiGridCtrl.grid.api.core.raise.gridDimensionChanged(prevGridHeight, prevGridWidth, newGridHeight, newGridWidth);
+
+ $scope.$apply(function () {
+ uiGridCtrl.grid.refresh()
+ .then(function () {
+ getDimensions();
+
+ startTimeout();
+ });
+ });
+ }
+ else {
+ startTimeout();
+ }
+ }, 250);
+ }
+
+ startTimeout();
+
+ $scope.$on('$destroy', function() {
+ clearTimeout(resizeTimeoutId);
+ });
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.cellNav
+ *
+ * @description
+
+ #ui.grid.cellNav
+
+ <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+
+ This module provides cell navigation functionality to UI-Grid.
+ */
+ var module = angular.module('ui.grid.cellNav', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.constant:uiGridCellNavConstants
+ *
+ * @description constants available in cellNav
+ */
+ module.constant('uiGridCellNavConstants', {
+ FEATURE_NAME: 'gridCellNav',
+ CELL_NAV_EVENT: 'cellNav',
+ direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},
+ EVENT_TYPE: {
+ KEYDOWN: 0,
+ CLICK: 1,
+ CLEAR: 2
+ }
+ });
+
+
+ module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'GridRowColumn', '$q',
+ function (gridUtil, uiGridConstants, uiGridCellNavConstants, GridRowColumn, $q) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.object:CellNav
+ * @description returns a CellNav prototype function
+ * @param {object} rowContainer container for rows
+ * @param {object} colContainer parent column container
+ * @param {object} leftColContainer column container to the left of parent
+ * @param {object} rightColContainer column container to the right of parent
+ */
+ var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {
+ this.rows = rowContainer.visibleRowCache;
+ this.columns = colContainer.visibleColumnCache;
+ this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];
+ this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];
+ this.bodyContainer = rowContainer;
+ };
+
+ /** returns focusable columns of all containers */
+ UiGridCellNav.prototype.getFocusableCols = function () {
+ var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);
+
+ return allColumns.filter(function (col) {
+ return col.colDef.allowCellFocus;
+ });
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:GridRow
+ *
+ * @description GridRow settings for cellNav feature, these are available to be
+ * set only internally (for example, by other features)
+ */
+
+ /**
+ * @ngdoc object
+ * @name allowCellFocus
+ * @propertyOf ui.grid.cellNav.api:GridRow
+ * @description Enable focus on a cell within this row. If set to false then no cells
+ * in this row can be focused - group header rows as an example would set this to false.
+ * <br/>Defaults to true
+ */
+ /** returns focusable rows */
+ UiGridCellNav.prototype.getFocusableRows = function () {
+ return this.rows.filter(function(row) {
+ return row.allowCellFocus !== false;
+ });
+ };
+
+ UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {
+ switch (direction) {
+ case uiGridCellNavConstants.direction.LEFT:
+ return this.getRowColLeft(curRow, curCol);
+ case uiGridCellNavConstants.direction.RIGHT:
+ return this.getRowColRight(curRow, curCol);
+ case uiGridCellNavConstants.direction.UP:
+ return this.getRowColUp(curRow, curCol);
+ case uiGridCellNavConstants.direction.DOWN:
+ return this.getRowColDown(curRow, curCol);
+ case uiGridCellNavConstants.direction.PG_UP:
+ return this.getRowColPageUp(curRow, curCol);
+ case uiGridCellNavConstants.direction.PG_DOWN:
+ return this.getRowColPageDown(curRow, curCol);
+ }
+
+ };
+
+ UiGridCellNav.prototype.initializeSelection = function () {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ if (focusableCols.length === 0 || focusableRows.length === 0) {
+ return null;
+ }
+
+ var curRowIndex = 0;
+ var curColIndex = 0;
+ return new GridRowColumn(focusableRows[0], focusableCols[0]); //return same row
+ };
+
+ UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 1
+ if (curColIndex === -1) {
+ curColIndex = 1;
+ }
+
+ var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;
+
+ //get column to left
+ if (nextColIndex >= curColIndex) {
+ // On the first row
+ // if (curRowIndex === 0 && curColIndex === 0) {
+ // return null;
+ // }
+ if (curRowIndex === 0) {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
+ }
+ else {
+ //up one row and far right column
+ return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);
+ }
+ }
+ else {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]);
+ }
+ };
+
+
+
+ UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+ var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;
+
+ if (nextColIndex <= curColIndex) {
+ if (curRowIndex === focusableRows.length - 1) {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
+ }
+ else {
+ //down one row and far left column
+ return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);
+ }
+ }
+ else {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ if (curRowIndex === focusableRows.length - 1) {
+ return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
+ }
+ else {
+ //down one row
+ return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ var pageSize = this.bodyContainer.minRowsToRender();
+ if (curRowIndex >= focusableRows.length - pageSize) {
+ return new GridRowColumn(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row
+ }
+ else {
+ //down one page
+ return new GridRowColumn(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ if (curRowIndex === 0) {
+ return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
+ }
+ else {
+ //up one row
+ return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ var pageSize = this.bodyContainer.minRowsToRender();
+ if (curRowIndex - pageSize < 0) {
+ return new GridRowColumn(focusableRows[0], focusableCols[curColIndex]); //return first row
+ }
+ else {
+ //up one page
+ return new GridRowColumn(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);
+ }
+ };
+ return UiGridCellNav;
+ }]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.cellNav.service:uiGridCellNavService
+ *
+ * @description Services for cell navigation features. If you don't like the key maps we use,
+ * or the direction cells navigation, override with a service decorator (see angular docs)
+ */
+ module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'GridRowColumn', 'ScrollEvent',
+ function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, GridRowColumn, ScrollEvent) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+ grid.registerColumnBuilder(service.cellNavColumnBuilder);
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav:Grid.cellNav
+ * @description cellNav properties added to grid class
+ */
+ grid.cellNav = {};
+ grid.cellNav.lastRowCol = null;
+ grid.cellNav.focusedCells = [];
+
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:PublicApi
+ *
+ * @description Public Api for cellNav feature
+ */
+ var publicApi = {
+ events: {
+ cellNav: {
+ /**
+ * @ngdoc event
+ * @name navigate
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description raised when the active cell is changed
+ * <pre>
+ * gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})
+ * </pre>
+ * @param {object} newRowCol new position
+ * @param {object} oldRowCol old position
+ */
+ navigate: function (newRowCol, oldRowCol) {},
+ /**
+ * @ngdoc event
+ * @name viewPortKeyDown
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid
+ * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
+ * event whenever you need a keydown event on a cell
+ * <br/>
+ * @param {object} event keydown event
+ * @param {object} rowCol current rowCol position
+ */
+ viewPortKeyDown: function (event, rowCol) {},
+
+ /**
+ * @ngdoc event
+ * @name viewPortKeyPress
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid
+ * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
+ * event whenever you need a keypress event on a cell
+ * <br/>
+ * @param {object} event keypress event
+ * @param {object} rowCol current rowCol position
+ */
+ viewPortKeyPress: function (event, rowCol) {}
+ }
+ },
+ methods: {
+ cellNav: {
+ /**
+ * @ngdoc function
+ * @name scrollToFocus
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description brings the specified row and column into view, and sets focus
+ * to that cell
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus
+ * @param {object} colDef to make visible and set focus
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ scrollToFocus: function (rowEntity, colDef) {
+ return service.scrollToFocus(grid, rowEntity, colDef);
+ },
+
+ /**
+ * @ngdoc function
+ * @name getFocusedCell
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns the current (or last if Grid does not have focus) focused row and column
+ * <br> value is null if no selection has occurred
+ */
+ getFocusedCell: function () {
+ return grid.cellNav.lastRowCol;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getCurrentSelection
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns an array containing the current selection
+ * <br> array is empty if no selection has occurred
+ */
+ getCurrentSelection: function () {
+ return grid.cellNav.focusedCells;
+ },
+
+ /**
+ * @ngdoc function
+ * @name rowColSelectIndex
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns the index in the order in which the GridRowColumn was selected, returns -1 if the GridRowColumn
+ * isn't selected
+ * @param {object} rowCol the rowCol to evaluate
+ */
+ rowColSelectIndex: function (rowCol) {
+ //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&
+ var index = -1;
+ for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {
+ if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&
+ grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:GridOptions
+ *
+ * @description GridOptions for cellNav feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name modifierKeysToMultiSelectCells
+ * @propertyOf ui.grid.cellNav.api:GridOptions
+ * @description Enable multiple cell selection only when using the ctrlKey or shiftKey.
+ * <br/>Defaults to false
+ */
+ gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;
+
+ /**
+ * @ngdoc array
+ * @name keyDownOverrides
+ * @propertyOf ui.grid.cellNav.api:GridOptions
+ * @description An array of event objects to override on keydown. If an event is overridden, the viewPortKeyDown event will
+ * be raised with the overridden events, allowing custom keydown behavior.
+ * <br/>Defaults to []
+ */
+ gridOptions.keyDownOverrides = gridOptions.keyDownOverrides || [];
+
+ },
+
+ /**
+ * @ngdoc service
+ * @name decorateRenderContainers
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description decorates grid renderContainers with cellNav functions
+ */
+ decorateRenderContainers: function (grid) {
+
+ var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;
+ var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;
+
+ if (leftContainer !== null) {
+ grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);
+ }
+ if (rightContainer !== null) {
+ grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);
+ }
+
+ grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getDirection
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description determines which direction to for a given keyDown event
+ * @returns {uiGridCellNavConstants.direction} direction
+ */
+ getDirection: function (evt) {
+ if (evt.keyCode === uiGridConstants.keymap.LEFT ||
+ (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {
+ return uiGridCellNavConstants.direction.LEFT;
+ }
+ if (evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.TAB) {
+ return uiGridCellNavConstants.direction.RIGHT;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.UP ||
+ (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {
+ return uiGridCellNavConstants.direction.UP;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.PG_UP){
+ return uiGridCellNavConstants.direction.PG_UP;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.DOWN ||
+ evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {
+ return uiGridCellNavConstants.direction.DOWN;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){
+ return uiGridCellNavConstants.direction.PG_DOWN;
+ }
+
+ return null;
+ },
+
+ /**
+ * @ngdoc service
+ * @name cellNavColumnBuilder
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description columnBuilder function that adds cell navigation properties to grid column
+ * @returns {promise} promise that will load any needed templates when resolved
+ */
+ cellNavColumnBuilder: function (colDef, col, gridOptions) {
+ var promises = [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:ColumnDef
+ *
+ * @description Column Definitions for cellNav feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name allowCellFocus
+ * @propertyOf ui.grid.cellNav.api:ColumnDef
+ * @description Enable focus on a cell within this column.
+ * <br/>Defaults to true
+ */
+ colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;
+
+ return $q.all(promises);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @name scrollToFocus
+ * @description Scroll the grid such that the specified
+ * row and column is in view, and set focus to the cell in that row and column
+ * @param {Grid} grid the grid you'd like to act upon, usually available
+ * from gridApi.grid
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to
+ * @param {object} colDef to make visible and set focus to
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ scrollToFocus: function (grid, rowEntity, colDef) {
+ var gridRow = null, gridCol = null;
+
+ if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {
+ gridRow = grid.getRow(rowEntity);
+ }
+
+ if (typeof(colDef) !== 'undefined' && colDef !== null) {
+ gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);
+ }
+ return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {
+ var rowCol = { row: gridRow, col: gridCol };
+
+ // Broadcast the navigation
+ if (gridRow !== null && gridCol !== null) {
+ grid.cellNav.broadcastCellNav(rowCol);
+ }
+ });
+
+
+
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @name getLeftWidth
+ * @description Get the current drawn width of the columns in the
+ * grid up to the numbered column, and add an apportionment for the
+ * column that we're on. So if we are on column 0, we want to scroll
+ * 0% (i.e. exclude this column from calc). If we're on the last column
+ * we want to scroll to 100% (i.e. include this column in the calc). So
+ * we include (thisColIndex / totalNumberCols) % of this column width
+ * @param {Grid} grid the grid you'd like to act upon, usually available
+ * from gridApi.grid
+ * @param {gridCol} upToCol the column to total up to and including
+ */
+ getLeftWidth: function (grid, upToCol) {
+ var width = 0;
+
+ if (!upToCol) {
+ return width;
+ }
+
+ var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );
+
+ // total column widths up-to but not including the passed in column
+ grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {
+ if ( index < lastIndex ){
+ width += col.drawnWidth;
+ }
+ });
+
+ // pro-rata the final column based on % of total columns.
+ var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;
+ width += upToCol.drawnWidth * percentage;
+
+ return width;
+ }
+ };
+
+ return service;
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.cellNav.directive:uiCellNav
+ * @element div
+ * @restrict EA
+ *
+ * @description Adds cell navigation features to the grid columns
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'title'}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-cellnav></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn', '$timeout', '$compile',
+ function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, GridRowColumn, $timeout, $compile) {
+ return {
+ replace: true,
+ priority: -150,
+ require: '^uiGrid',
+ scope: false,
+ controller: function () {},
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var _scope = $scope;
+
+ var grid = uiGridCtrl.grid;
+ uiGridCellNavService.initializeGrid(grid);
+
+ uiGridCtrl.cellNav = {};
+
+ //Ensure that the object has all of the methods we expect it to
+ uiGridCtrl.cellNav.makeRowCol = function (obj) {
+ if (!(obj instanceof GridRowColumn)) {
+ obj = new GridRowColumn(obj.row, obj.col);
+ }
+ return obj;
+ };
+
+ uiGridCtrl.cellNav.getActiveCell = function () {
+ var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');
+ if (elms.length > 0){
+ return elms[0];
+ }
+
+ return undefined;
+ };
+
+ uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {
+ modifierDown = !(modifierDown === undefined || !modifierDown);
+
+ newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);
+
+ uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);
+ _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);
+ };
+
+ uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {
+ grid.cellNav.focusedCells = [];
+ _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);
+ };
+
+ uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {
+ modifierDown = !(modifierDown === undefined || !modifierDown);
+
+ rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);
+
+ var row = rowCol.row,
+ col = rowCol.col;
+
+ var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
+
+ if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {
+ var newRowCol = new GridRowColumn(row, col);
+
+ if (grid.cellNav.lastRowCol === null || grid.cellNav.lastRowCol.row !== newRowCol.row || grid.cellNav.lastRowCol.col !== newRowCol.col){
+ grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol, originEvt);
+ grid.cellNav.lastRowCol = newRowCol;
+ }
+ if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {
+ grid.cellNav.focusedCells.push(rowCol);
+ } else {
+ grid.cellNav.focusedCells = [rowCol];
+ }
+ } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&
+ rowColSelectIndex >= 0) {
+
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ }
+ };
+
+ uiGridCtrl.cellNav.handleKeyDown = function (evt) {
+ var direction = uiGridCellNavService.getDirection(evt);
+ if (direction === null) {
+ return null;
+ }
+
+ var containerId = 'body';
+ if (evt.uiGridTargetRenderContainerId) {
+ containerId = evt.uiGridTargetRenderContainerId;
+ }
+
+ // Get the last-focused row+col combo
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol) {
+ // Figure out which new row+combo we're navigating to
+ var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);
+ var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();
+ var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
+ // Shift+tab on top-left cell should exit cellnav on render container
+ if (
+ // Navigating left
+ direction === uiGridCellNavConstants.direction.LEFT &&
+ // New col is last col (i.e. wrap around)
+ rowCol.col === focusableCols[focusableCols.length - 1] &&
+ // Staying on same row, which means we're at first row
+ rowCol.row === lastRowCol.row &&
+ evt.keyCode === uiGridConstants.keymap.TAB &&
+ evt.shiftKey
+ ) {
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ uiGridCtrl.cellNav.clearFocus();
+ return true;
+ }
+ // Tab on bottom-right cell should exit cellnav on render container
+ else if (
+ direction === uiGridCellNavConstants.direction.RIGHT &&
+ // New col is first col (i.e. wrap around)
+ rowCol.col === focusableCols[0] &&
+ // Staying on same row, which means we're at first row
+ rowCol.row === lastRowCol.row &&
+ evt.keyCode === uiGridConstants.keymap.TAB &&
+ !evt.shiftKey
+ ) {
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ uiGridCtrl.cellNav.clearFocus();
+ return true;
+ }
+
+ // Scroll to the new cell, if it's not completely visible within the render container's viewport
+ grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {
+ uiGridCtrl.cellNav.broadcastCellNav(rowCol, null, evt);
+ });
+
+
+ evt.stopPropagation();
+ evt.preventDefault();
+
+ return false;
+ }
+ };
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var _scope = $scope;
+ var grid = uiGridCtrl.grid;
+
+ function addAriaLiveRegion(){
+ // Thanks to google docs for the inspiration behind how to do this
+ // XXX: Why is this entire mess nessasary?
+ // Because browsers take a lot of coercing to get them to read out live regions
+ //http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
+ var ariaNotifierDomElt = '<div ' +
+ 'id="' + grid.id +'-aria-speakable" ' +
+ 'class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" ' +
+ 'aria-live="assertive" ' +
+ 'role="region" ' +
+ 'aria-atomic="true" ' +
+ 'aria-hidden="false" ' +
+ 'aria-relevant="additions" ' +
+ '>' +
+ '&nbsp;' +
+ '</div>';
+
+ var ariaNotifier = $compile(ariaNotifierDomElt)($scope);
+ $elm.prepend(ariaNotifier);
+ $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {
+ /*
+ * If the cell nav event was because of a focus event then we don't want to
+ * change the notifier text.
+ * Reasoning: Voice Over fires a focus events when moving arround the grid.
+ * If the screen reader is handing the grid nav properly then we don't need to
+ * use the alert to notify the user of the movement.
+ * In all other cases we do want a notification event.
+ */
+ if (originEvt && originEvt.type === 'focus'){return;}
+
+ function setNotifyText(text){
+ if (text === ariaNotifier.text()){return;}
+ ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';
+ /*
+ * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''
+ */
+ ariaNotifier[0].innerHTML = "";
+ ariaNotifier[0].style.visibility = 'hidden';
+ ariaNotifier[0].style.visibility = 'visible';
+ if (text !== ''){
+ ariaNotifier[0].style.clip = 'auto';
+ /*
+ * The space after the text is something that google docs does.
+ */
+ ariaNotifier[0].appendChild(document.createTextNode(text + " "));
+ ariaNotifier[0].style.visibility = 'hidden';
+ ariaNotifier[0].style.visibility = 'visible';
+ }
+ }
+
+ var values = [];
+ var currentSelection = grid.api.cellNav.getCurrentSelection();
+ for (var i = 0; i < currentSelection.length; i++) {
+ values.push(grid.getCellDisplayValue(currentSelection[i].row, currentSelection[i].col));
+ }
+ var cellText = values.toString();
+ setNotifyText(cellText);
+
+ });
+ }
+ addAriaLiveRegion();
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',
+ function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {
+ return {
+ replace: true,
+ priority: -99999, //this needs to run very last
+ require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],
+ scope: false,
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ renderContainerCtrl = controllers[1],
+ uiGridCellnavCtrl = controllers[2];
+
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = renderContainerCtrl.containerId;
+
+ var grid = uiGridCtrl.grid;
+
+ //run each time a render container is created
+ uiGridCellNavService.decorateRenderContainers(grid);
+
+ // focusser only created for body
+ if (containerId !== 'body') {
+ return;
+ }
+
+
+
+ if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells){
+ $elm.attr('aria-multiselectable', true);
+ } else {
+ $elm.attr('aria-multiselectable', false);
+ }
+
+ //add an element with no dimensions that can be used to set focus and capture keystrokes
+ var focuser = $compile('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'" aria-owns="' + grid.id + '-grid-container' + '"></div>')($scope);
+ $elm.append(focuser);
+
+ focuser.on('focus', function (evt) {
+ evt.uiGridTargetRenderContainerId = containerId;
+ var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (rowCol === null) {
+ rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);
+ if (rowCol.row && rowCol.col) {
+ uiGridCtrl.cellNav.broadcastCellNav(rowCol);
+ }
+ }
+ });
+
+ uiGridCellnavCtrl.setAriaActivedescendant = function(id){
+ $elm.attr('aria-activedescendant', id);
+ };
+
+ uiGridCellnavCtrl.removeAriaActivedescendant = function(id){
+ if ($elm.attr('aria-activedescendant') === id){
+ $elm.attr('aria-activedescendant', '');
+ }
+ };
+
+
+ uiGridCtrl.focus = function () {
+ gridUtil.focus.byElement(focuser[0]);
+ //allow for first time grid focus
+ };
+
+ var viewPortKeyDownWasRaisedForRowCol = null;
+ // Bind to keydown events in the render container
+ focuser.on('keydown', function (evt) {
+ evt.uiGridTargetRenderContainerId = containerId;
+ var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ var raiseViewPortKeyDown = uiGridCtrl.grid.options.keyDownOverrides.some(function (override) {
+ return Object.keys(override).every( function (property) {
+ return override[property] === evt[property];
+ });
+ });
+ var result = raiseViewPortKeyDown ? null : uiGridCtrl.cellNav.handleKeyDown(evt);
+ if (result === null) {
+ uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol);
+ viewPortKeyDownWasRaisedForRowCol = rowCol;
+ }
+ });
+ //Bind to keypress events in the render container
+ //keypress events are needed by edit function so the key press
+ //that initiated an edit is not lost
+ //must fire the event in a timeout so the editor can
+ //initialize and subscribe to the event on another event loop
+ focuser.on('keypress', function (evt) {
+ if (viewPortKeyDownWasRaisedForRowCol) {
+ $timeout(function () {
+ uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);
+ },4);
+
+ viewPortKeyDownWasRaisedForRowCol = null;
+ }
+ });
+
+ $scope.$on('$destroy', function(){
+ //Remove all event handlers associated with this focuser.
+ focuser.off();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridViewport', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants','$log','$compile',
+ function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants, $log, $compile) {
+ return {
+ replace: true,
+ priority: -99999, //this needs to run very last
+ require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ renderContainerCtrl = controllers[1];
+
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = renderContainerCtrl.containerId;
+ //no need to process for other containers
+ if (containerId !== 'body') {
+ return;
+ }
+
+ var grid = uiGridCtrl.grid;
+
+ grid.api.core.on.scrollBegin($scope, function (args) {
+
+ // Skip if there's no currently-focused cell
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol === null) {
+ return;
+ }
+
+ //if not in my container, move on
+ //todo: worry about horiz scroll
+ if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
+ return;
+ }
+
+ uiGridCtrl.cellNav.clearFocus();
+
+ });
+
+ grid.api.core.on.scrollEnd($scope, function (args) {
+ // Skip if there's no currently-focused cell
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol === null) {
+ return;
+ }
+
+ //if not in my container, move on
+ //todo: worry about horiz scroll
+ if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
+ return;
+ }
+
+ uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
+
+ });
+
+ grid.api.cellNav.on.navigate($scope, function () {
+ //focus again because it can be lost
+ uiGridCtrl.focus();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.cellNav.directive:uiGridCell
+ * @element div
+ * @restrict A
+ * @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
+ */
+ module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn',
+ function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, GridRowColumn) {
+ return {
+ priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
+ restrict: 'A',
+ require: ['^uiGrid', '?^uiGridCellnav'],
+ scope: false,
+ link: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ uiGridCellnavCtrl = controllers[1];
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ if (!$scope.col.colDef.allowCellFocus) {
+ return;
+ }
+
+ //Convinience local variables
+ var grid = uiGridCtrl.grid;
+ $scope.focused = false;
+
+ // Make this cell focusable but only with javascript/a mouse click
+ $elm.attr('tabindex', -1);
+
+ // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused
+ $elm.find('div').on('click', function (evt) {
+ uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);
+
+ evt.stopPropagation();
+ $scope.$apply();
+ });
+
+
+ /*
+ * XXX Hack for screen readers.
+ * This allows the grid to focus using only the screen reader cursor.
+ * Since the focus event doesn't include key press information we can't use it
+ * as our primary source of the event.
+ */
+ $elm.on('mousedown', preventMouseDown);
+
+ //turn on and off for edit events
+ if (uiGridCtrl.grid.api.edit) {
+ uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {
+ $elm.off('mousedown', preventMouseDown);
+ });
+
+ uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {
+ $elm.on('mousedown', preventMouseDown);
+ });
+
+ uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {
+ $elm.on('mousedown', preventMouseDown);
+ });
+ }
+
+ // In case we created a new row, and we are the new created row by ngRepeat
+ // then this cell content might have been selected previously
+ refreshCellFocus();
+
+ function preventMouseDown(evt) {
+ //Prevents the foucus event from firing if the click event is already going to fire.
+ //If both events fire it will cause bouncing behavior.
+ evt.preventDefault();
+ }
+
+ //You can only focus on elements with a tabindex value
+ $elm.on('focus', function (evt) {
+ uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), false, evt);
+ evt.stopPropagation();
+ $scope.$apply();
+ });
+
+ // This event is fired for all cells. If the cell matches, then focus is set
+ $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, refreshCellFocus);
+
+ // Refresh cell focus when a new row id added to the grid
+ var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
+ // Clear the focus if it's set to avoid the wrong cell getting focused during
+ // a short period of time (from now until $timeout function executed)
+ clearFocus();
+
+ $timeout(refreshCellFocus);
+ }, [uiGridConstants.dataChange.ROW]);
+
+ function refreshCellFocus() {
+ var isFocused = grid.cellNav.focusedCells.some(function (focusedRowCol, index) {
+ return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);
+ });
+ if (isFocused) {
+ setFocused();
+ } else {
+ clearFocus();
+ }
+ }
+
+ function setFocused() {
+ if (!$scope.focused){
+ var div = $elm.find('div');
+ div.addClass('ui-grid-cell-focus');
+ $elm.attr('aria-selected', true);
+ uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));
+ $scope.focused = true;
+ }
+ }
+
+ function clearFocus() {
+ if ($scope.focused){
+ var div = $elm.find('div');
+ div.removeClass('ui-grid-cell-focus');
+ $elm.attr('aria-selected', false);
+ uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));
+ $scope.focused = false;
+ }
+ }
+
+ $scope.$on('$destroy', function () {
+ dataChangeDereg();
+
+ //.off withouth paramaters removes all handlers
+ $elm.find('div').off();
+ $elm.off();
+ });
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.edit
+ * @description
+ *
+ * # ui.grid.edit
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via
+ * a keyboard.
+ * <br/>
+ * <br/>
+ * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the
+ * user to key data and then tab, arrow, or enter to the cells beside or below.
+ *
+ * <div doc-module-components="ui.grid.edit"></div>
+ */
+
+ var module = angular.module('ui.grid.edit', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.constant:uiGridEditConstants
+ *
+ * @description constants available in edit module
+ */
+ module.constant('uiGridEditConstants', {
+ EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,
+ //must be lowercase because template bulder converts to lower
+ EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,
+ events: {
+ BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',
+ END_CELL_EDIT: 'uiGridEventEndCellEdit',
+ CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.edit.service:uiGridEditService
+ *
+ * @description Services for editing features
+ */
+ module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',
+ function ($q, uiGridConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerColumnBuilder(service.editColumnBuilder);
+ grid.edit = {};
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:PublicApi
+ *
+ * @description Public Api for edit feature
+ */
+ var publicApi = {
+ events: {
+ edit: {
+ /**
+ * @ngdoc event
+ * @name afterCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing is complete
+ * <pre>
+ * gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ * @param {object} newValue new value
+ * @param {object} oldValue old value
+ */
+ afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {
+ },
+ /**
+ * @ngdoc event
+ * @name beginCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing starts on a cell
+ * <pre>
+ * gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ * @param {object} triggerEvent the event that triggered the edit. Useful to prevent losing keystrokes on some
+ * complex editors
+ */
+ beginCellEdit: function (rowEntity, colDef, triggerEvent) {
+ },
+ /**
+ * @ngdoc event
+ * @name cancelCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing is cancelled on a cell
+ * <pre>
+ * gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ */
+ cancelCellEdit: function (rowEntity, colDef) {
+ }
+ }
+ },
+ methods: {
+ edit: { }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ //grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:GridOptions
+ *
+ * @description Options for configuring the edit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If defined, sets the default value for the editable flag on each individual colDefs
+ * if their individual enableCellEdit configuration is not defined. Defaults to undefined.
+ */
+
+ /**
+ * @ngdoc object
+ * @name cellEditableCondition
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If specified, either a value or function to be used by all columns before editing.
+ * If falsy, then editing of cell is not allowed.
+ * @example
+ * <pre>
+ * function($scope){
+ * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
+ * return true;
+ * }
+ * </pre>
+ */
+ gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;
+
+ /**
+ * @ngdoc object
+ * @name editableCellTemplate
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If specified, cellTemplate to use as the editor for all columns.
+ * <br/> defaults to 'ui-grid/cellTextEditor'
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEditOnFocus
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If true, then editor is invoked as soon as cell receives focus. Default false.
+ * <br/>_requires cellNav feature and the edit feature to be enabled_
+ */
+ //enableCellEditOnFocus can only be used if cellnav module is used
+ gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;
+ },
+
+ /**
+ * @ngdoc service
+ * @name editColumnBuilder
+ * @methodOf ui.grid.edit.service:uiGridEditService
+ * @description columnBuilder function that adds edit properties to grid column
+ * @returns {promise} promise that will load any needed templates when resolved
+ */
+ editColumnBuilder: function (colDef, col, gridOptions) {
+
+ var promises = [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:ColumnDef
+ *
+ * @description Column Definition for edit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description enable editing on column
+ */
+ colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?
+ (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;
+
+ /**
+ * @ngdoc object
+ * @name cellEditableCondition
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description If specified, either a value or function evaluated before editing cell. If falsy, then editing of cell is not allowed.
+ * @example
+ * <pre>
+ * function($scope){
+ * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
+ * return true;
+ * }
+ * </pre>
+ */
+ colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition : colDef.cellEditableCondition;
+
+ /**
+ * @ngdoc object
+ * @name editableCellTemplate
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description cell template to be used when editing this column. Can be Url or text template
+ * <br/>Defaults to gridOptions.editableCellTemplate
+ */
+ if (colDef.enableCellEdit) {
+ colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';
+
+ promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)
+ .then(
+ function (template) {
+ col.editableCellTemplate = template;
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use colDef.editableCellTemplate '" + colDef.editableCellTemplate + "'");
+ }));
+ }
+
+ /**
+ * @ngdoc object
+ * @name enableCellEditOnFocus
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @requires ui.grid.cellNav
+ * @description If true, then editor is invoked as soon as cell receives focus. Default false.
+ * <br>_requires both the cellNav feature and the edit feature to be enabled_
+ */
+ //enableCellEditOnFocus can only be used if cellnav module is used
+ colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;
+
+
+ /**
+ * @ngdoc string
+ * @name editModelField
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description a bindable string value that is used when binding to edit controls instead of colDef.field
+ * <br/> example: You have a complex property on and object like state:{abbrev:'MS',name:'Mississippi'}. The
+ * grid should display state.name in the cell and sort/filter based on the state.name property but the editor
+ * requires the full state object.
+ * <br/>colDef.field = 'state.name'
+ * <br/>colDef.editModelField = 'state'
+ */
+ //colDef.editModelField
+
+ return $q.all(promises);
+ },
+
+ /**
+ * @ngdoc service
+ * @name isStartEditKey
+ * @methodOf ui.grid.edit.service:uiGridEditService
+ * @description Determines if a keypress should start editing. Decorate this service to override with your
+ * own key events. See service decorator in angular docs.
+ * @param {Event} evt keydown event
+ * @returns {boolean} true if an edit should start
+ */
+ isStartEditKey: function (evt) {
+ if (evt.metaKey ||
+ evt.keyCode === uiGridConstants.keymap.ESC ||
+ evt.keyCode === uiGridConstants.keymap.SHIFT ||
+ evt.keyCode === uiGridConstants.keymap.CTRL ||
+ evt.keyCode === uiGridConstants.keymap.ALT ||
+ evt.keyCode === uiGridConstants.keymap.WIN ||
+ evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||
+
+ evt.keyCode === uiGridConstants.keymap.LEFT ||
+ (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||
+
+ evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.TAB ||
+
+ evt.keyCode === uiGridConstants.keymap.UP ||
+ (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||
+
+ evt.keyCode === uiGridConstants.keymap.DOWN ||
+ evt.keyCode === uiGridConstants.keymap.ENTER) {
+ return false;
+
+ }
+ return true;
+ }
+
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEdit
+ * @element div
+ * @restrict A
+ *
+ * @description Adds editing features to the ui-grid directive.
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridEditService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridRenderContainer
+ * @element div
+ * @restrict A
+ *
+ * @description Adds keydown listeners to renderContainer element so we can capture when to begin edits
+ *
+ */
+ module.directive('uiGridViewport', [ 'uiGridEditConstants',
+ function ( uiGridEditConstants) {
+ return {
+ replace: true,
+ priority: -99998, //run before cellNav
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: false,
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+
+ // Skip attaching if edit and cellNav is not enabled
+ if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = controllers[1].containerId;
+ //no need to process for other containers
+ if (containerId !== 'body') {
+ return;
+ }
+
+ //refocus on the grid
+ $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
+ uiGridCtrl.focus();
+ });
+ $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
+ uiGridCtrl.focus();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell
+ * Editing Actions.
+ *
+ * Binds edit start events to the uiGridCell element. When the events fire, the gridCell element is appended
+ * with the columnDef.editableCellTemplate element ('cellEditor.html' by default).
+ *
+ * The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\_CELL\_EDIT angular event
+ * and do the initial steps needed to edit the cell (setfocus on input element, etc).
+ *
+ * When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)
+ * it should emit the uiGridEditConstants.events.END\_CELL\_EDIT event.
+ *
+ * If editableCellTemplate recognizes that the editing has been cancelled (esc key)
+ * it should emit the uiGridEditConstants.events.CANCEL\_CELL\_EDIT event. The original value
+ * will be set back on the model by the uiGridCell directive.
+ *
+ * Events that invoke editing:
+ * - dblclick
+ * - F2 keydown (when using cell selection)
+ *
+ * Events that end editing:
+ * - Dependent on the specific editableCellTemplate
+ * - Standards should be blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Dependent on the specific editableCellTemplate
+ * - Standards should be Esc keydown
+ *
+ * Grid Events that end editing:
+ * - uiGridConstants.events.GRID_SCROLL
+ *
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:GridRow
+ *
+ * @description GridRow options for edit feature, these are available to be
+ * set internally only, by other features
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:GridRow
+ * @description enable editing on row, grouping for example might disable editing on group header rows
+ */
+
+ module.directive('uiGridCell',
+ ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope', '$q',
+ function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope, $q) {
+ var touchstartTimeout = 500;
+ if ($injector.has('uiGridCellNavService')) {
+ var uiGridCellNavService = $injector.get('uiGridCellNavService');
+ }
+
+ return {
+ priority: -100, // run after default uiGridCell directive
+ restrict: 'A',
+ scope: false,
+ require: '?^uiGrid',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var html;
+ var origCellValue;
+ var inEdit = false;
+ var cellModel;
+ var cancelTouchstartTimeout;
+
+ var editCellScope;
+
+ if (!$scope.col.colDef.enableCellEdit) {
+ return;
+ }
+
+ var cellNavNavigateDereg = function() {};
+ var viewPortKeyDownDereg = function() {};
+
+
+ var setEditable = function() {
+ if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {
+ if (!$scope.beginEditEventsWired) { //prevent multiple attachments
+ registerBeginEditEvents();
+ }
+ } else {
+ if ($scope.beginEditEventsWired) {
+ cancelBeginEditEvents();
+ }
+ }
+ };
+
+ setEditable();
+
+ var rowWatchDereg = $scope.$watch('row', function (n, o) {
+ if (n !== o) {
+ setEditable();
+ }
+ });
+
+
+ $scope.$on('$destroy', function destroyEvents() {
+ rowWatchDereg();
+ // unbind all jquery events in order to avoid memory leaks
+ $elm.off();
+ });
+
+ function registerBeginEditEvents() {
+ $elm.on('dblclick', beginEdit);
+
+ // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit
+ $elm.on('touchstart', touchStart);
+
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+
+ viewPortKeyDownDereg = uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
+ if (rowCol === null) {
+ return;
+ }
+
+ if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {
+ //important to do this before scrollToIfNecessary
+ beginEditKeyDown(evt);
+ }
+ });
+
+ cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol, evt) {
+ if ($scope.col.colDef.enableCellEditOnFocus) {
+ // Don't begin edit if the cell hasn't changed
+ if ((!oldRowCol || newRowCol.row !== oldRowCol.row || newRowCol.col !== oldRowCol.col) &&
+ newRowCol.row === $scope.row && newRowCol.col === $scope.col) {
+ $timeout(function () {
+ beginEdit(evt);
+ });
+ }
+ }
+ });
+ }
+
+ $scope.beginEditEventsWired = true;
+
+ }
+
+ function touchStart(event) {
+ // jQuery masks events
+ if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
+ event = event.originalEvent;
+ }
+
+ // Bind touchend handler
+ $elm.on('touchend', touchEnd);
+
+ // Start a timeout
+ cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);
+
+ // Timeout's done! Start the edit
+ cancelTouchstartTimeout.then(function () {
+ // Use setTimeout to start the edit because beginEdit expects to be outside of $digest
+ setTimeout(beginEdit, 0);
+
+ // Undbind the touchend handler, we don't need it anymore
+ $elm.off('touchend', touchEnd);
+ });
+ }
+
+ // Cancel any touchstart timeout
+ function touchEnd(event) {
+ $timeout.cancel(cancelTouchstartTimeout);
+ $elm.off('touchend', touchEnd);
+ }
+
+ function cancelBeginEditEvents() {
+ $elm.off('dblclick', beginEdit);
+ $elm.off('keydown', beginEditKeyDown);
+ $elm.off('touchstart', touchStart);
+ cellNavNavigateDereg();
+ viewPortKeyDownDereg();
+ $scope.beginEditEventsWired = false;
+ }
+
+ function beginEditKeyDown(evt) {
+ if (uiGridEditService.isStartEditKey(evt)) {
+ beginEdit(evt);
+ }
+ }
+
+ function shouldEdit(col, row) {
+ return !row.isSaving &&
+ ( angular.isFunction(col.colDef.cellEditableCondition) ?
+ col.colDef.cellEditableCondition($scope) :
+ col.colDef.cellEditableCondition );
+ }
+
+
+ function beginEdit(triggerEvent) {
+ //we need to scroll the cell into focus before invoking the editor
+ $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)
+ .then(function () {
+ beginEditAfterScroll(triggerEvent);
+ });
+ }
+
+ /**
+ * @ngdoc property
+ * @name editDropdownOptionsArray
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description an array of values in the format
+ * [ {id: xxx, value: xxx} ], which is populated
+ * into the edit dropdown
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownIdLabel
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description the label for the "id" field
+ * in the editDropdownOptionsArray. Defaults
+ * to 'id'
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownRowEntityOptionsArrayPath
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description a path to a property on row.entity containing an
+ * array of values in the format
+ * [ {id: xxx, value: xxx} ], which will be used to populate
+ * the edit dropdown. This can be used when the dropdown values are dependent on
+ * the backing row entity.
+ * If this property is set then editDropdownOptionsArray will be ignored.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc service
+ * @name editDropdownOptionsFunction
+ * @methodOf ui.grid.edit.api:ColumnDef
+ * @description a function returning an array of values in the format
+ * [ {id: xxx, value: xxx} ], which will be used to populate
+ * the edit dropdown. This can be used when the dropdown values are dependent on
+ * the backing row entity with some kind of algorithm.
+ * If this property is set then both editDropdownOptionsArray and
+ * editDropdownRowEntityOptionsArrayPath will be ignored.
+ * @param {object} rowEntity the options.data element that the returned array refers to
+ * @param {object} colDef the column that implements this dropdown
+ * @returns {object} an array of values in the format
+ * [ {id: xxx, value: xxx} ] used to populate the edit dropdown
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsFunction: function(rowEntity, colDef) {
+ * if (rowEntity.foo === 'bar') {
+ * return [{id: 'bar1', value: 'BAR 1'},
+ * {id: 'bar2', value: 'BAR 2'},
+ * {id: 'bar3', value: 'BAR 3'}];
+ * } else {
+ * return [{id: 'foo1', value: 'FOO 1'},
+ * {id: 'foo2', value: 'FOO 2'}];
+ * }
+ * },
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownValueLabel
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description the label for the "value" field
+ * in the editDropdownOptionsArray. Defaults
+ * to 'value'
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownFilter
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description A filter that you would like to apply to the values in the options list
+ * of the dropdown. For example if you were using angular-translate you might set this
+ * to `'translate'`
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }
+ * ],
+ * </pre>
+ *
+ */
+ function beginEditAfterScroll(triggerEvent) {
+ // If we are already editing, then just skip this so we don't try editing twice...
+ if (inEdit) {
+ return;
+ }
+
+ if (!shouldEdit($scope.col, $scope.row)) {
+ return;
+ }
+
+ var modelField = $scope.row.getQualifiedColField($scope.col);
+ if ($scope.col.colDef.editModelField) {
+ modelField = gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField);
+ }
+
+ cellModel = $parse(modelField);
+
+ //get original value from the cell
+ origCellValue = cellModel($scope);
+
+ html = $scope.col.editableCellTemplate;
+ html = html.replace(uiGridConstants.MODEL_COL_FIELD, modelField);
+ html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';
+ html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);
+
+ var inputType = 'text';
+ switch ($scope.col.colDef.type){
+ case 'boolean':
+ inputType = 'checkbox';
+ break;
+ case 'number':
+ inputType = 'number';
+ break;
+ case 'date':
+ inputType = 'date';
+ break;
+ }
+ html = html.replace('INPUT_TYPE', inputType);
+
+ // In order to fill dropdown options we use:
+ // - A function/promise or
+ // - An array inside of row entity if no function exists or
+ // - A single array for the whole column if none of the previous exists.
+ var editDropdownOptionsFunction = $scope.col.colDef.editDropdownOptionsFunction;
+ if (editDropdownOptionsFunction) {
+ $q.when(editDropdownOptionsFunction($scope.row.entity, $scope.col.colDef))
+ .then(function(result) {
+ $scope.editDropdownOptionsArray = result;
+ });
+ } else {
+ var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;
+ if (editDropdownRowEntityOptionsArrayPath) {
+ $scope.editDropdownOptionsArray = resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);
+ }
+ else {
+ $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;
+ }
+ }
+ $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';
+ $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';
+
+ var cellElement;
+ var createEditor = function(){
+ inEdit = true;
+ cancelBeginEditEvents();
+ var cellElement = angular.element(html);
+ $elm.append(cellElement);
+ editCellScope = $scope.$new();
+ $compile(cellElement)(editCellScope);
+ var gridCellContentsEl = angular.element($elm.children()[0]);
+ gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');
+ };
+ if (!$rootScope.$$phase) {
+ $scope.$apply(createEditor);
+ } else {
+ createEditor();
+ }
+
+ //stop editing when grid is scrolled
+ var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {
+ if ($scope.grid.disableScrolling) {
+ return;
+ }
+ endEdit();
+ $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
+ deregOnGridScroll();
+ deregOnEndCellEdit();
+ deregOnCancelCellEdit();
+ });
+
+ //end editing
+ var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
+ endEdit();
+ $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
+ deregOnEndCellEdit();
+ deregOnGridScroll();
+ deregOnCancelCellEdit();
+ });
+
+ //cancel editing
+ var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
+ cancelEdit();
+ deregOnCancelCellEdit();
+ deregOnGridScroll();
+ deregOnEndCellEdit();
+ });
+
+ $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);
+ $timeout(function () {
+ //execute in a timeout to give any complex editor templates a cycle to completely render
+ $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);
+ });
+ }
+
+ function endEdit() {
+ $scope.grid.disableScrolling = false;
+ if (!inEdit) {
+ return;
+ }
+
+ //sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus
+ //back to grid here. The focus call needs to be before the $destroy and removal of the control,
+ //otherwise ng-model-options of UpdateOn: 'blur' will not work.
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ uiGridCtrl.focus();
+ }
+
+ var gridCellContentsEl = angular.element($elm.children()[0]);
+ //remove edit element
+ editCellScope.$destroy();
+ var children = $elm.children();
+ for (var i = 1; i < children.length; i++) {
+ angular.element(children[i]).remove();
+ }
+ gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');
+ inEdit = false;
+ registerBeginEditEvents();
+ $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );
+ }
+
+ function cancelEdit() {
+ $scope.grid.disableScrolling = false;
+ if (!inEdit) {
+ return;
+ }
+ cellModel.assign($scope, origCellValue);
+ $scope.$apply();
+
+ $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);
+ endEdit();
+ }
+
+ // resolves a string path against the given object
+ // shamelessly borrowed from
+ // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
+ function resolveObjectFromPath(object, path) {
+ path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+ path = path.replace(/^\./, ''); // strip a leading dot
+ var a = path.split('.');
+ while (a.length) {
+ var n = a.shift();
+ if (n in object) {
+ object = object[n];
+ } else {
+ return;
+ }
+ }
+ return object;
+ }
+
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditor
+ * @element div
+ * @restrict A
+ *
+ * @description input editor directive for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditor',
+ ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',
+ function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {
+ return {
+ scope: true,
+ require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl, renderContainerCtrl, ngModel;
+ if (controllers[0]) { uiGridCtrl = controllers[0]; }
+ if (controllers[1]) { renderContainerCtrl = controllers[1]; }
+ if (controllers[2]) { ngModel = controllers[2]; }
+
+ //set focus at start of edit
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function (evt,triggerEvent) {
+ $timeout(function () {
+ $elm[0].focus();
+ //only select text if it is not being replaced below in the cellNav viewPortKeyPress
+ if ($elm[0].select && ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav))) {
+ $elm[0].select();
+ }
+ else {
+ //some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...
+ //fields should not allow setSelectionRange. We ignore the error for those browsers
+ //https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796
+ try {
+ $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);
+ }
+ catch (ex) {
+ //ignore
+ }
+ }
+ });
+
+ //set the keystroke that started the edit event
+ //we must do this because the BeginEdit is done in a different event loop than the intitial
+ //keydown event
+ //fire this event for the keypress that is received
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {
+ if (uiGridEditService.isStartEditKey(evt)) {
+ ngModel.$setViewValue(String.fromCharCode( typeof evt.which === 'number' ? evt.which : evt.keyCode), evt);
+ ngModel.$render();
+ }
+ viewPortKeyDownUnregister();
+ });
+ }
+
+ // macOS will blur the checkbox when clicked in Safari and Firefox,
+ // to get around this, we disable the blur handler on mousedown,
+ // and then focus the checkbox and re-enable the blur handler after $timeout
+ $elm.on('mousedown', function(evt) {
+ if ($elm[0].type === 'checkbox') {
+ $elm.off('blur', $scope.stopEdit);
+ $timeout(function() {
+ $elm.focus();
+ $elm.on('blur', $scope.stopEdit);
+ });
+ }
+ });
+
+ $elm.on('blur', $scope.stopEdit);
+ });
+
+
+ $scope.deepEdit = false;
+
+ $scope.stopEdit = function (evt) {
+ if ($scope.inputForm && !$scope.inputForm.$valid) {
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ }
+ else {
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ }
+ $scope.deepEdit = false;
+ };
+
+
+ $elm.on('click', function (evt) {
+ if ($elm[0].type !== 'checkbox') {
+ $scope.deepEdit = true;
+ $timeout(function () {
+ $scope.grid.disableScrolling = true;
+ });
+ }
+ });
+
+ $elm.on('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ESC:
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ break;
+ }
+
+ if ($scope.deepEdit &&
+ (evt.keyCode === uiGridConstants.keymap.LEFT ||
+ evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.UP ||
+ evt.keyCode === uiGridConstants.keymap.DOWN)) {
+ evt.stopPropagation();
+ }
+ // Pass the keydown event off to the cellNav service, if it exists
+ else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
+ if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
+ $scope.stopEdit(evt);
+ }
+ }
+ else {
+ //handle enter and tab for editing not using cellNav
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
+ case uiGridConstants.keymap.TAB:
+ evt.stopPropagation();
+ evt.preventDefault();
+ $scope.stopEdit(evt);
+ break;
+ }
+ }
+
+ return true;
+ });
+
+ $scope.$on('$destroy', function unbindEvents() {
+ // unbind all jquery events in order to avoid memory leaks
+ $elm.off();
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:input
+ * @element input
+ * @restrict E
+ *
+ * @description directive to provide binding between input[date] value and ng-model for angular 1.2
+ * It is similar to input[date] directive of angular 1.3
+ *
+ * Supported date format for input is 'yyyy-MM-dd'
+ * The directive will set the $valid property of input element and the enclosing form to false if
+ * model is invalid date or value of input is entered wrong.
+ *
+ */
+ module.directive('uiGridEditor', ['$filter', function ($filter) {
+ function parseDateString(dateString) {
+ if (typeof(dateString) === 'undefined' || dateString === '') {
+ return null;
+ }
+ var parts = dateString.split('-');
+ if (parts.length !== 3) {
+ return null;
+ }
+ var year = parseInt(parts[0], 10);
+ var month = parseInt(parts[1], 10);
+ var day = parseInt(parts[2], 10);
+
+ if (month < 1 || year < 1 || day < 1) {
+ return null;
+ }
+ return new Date(year, (month - 1), day);
+ }
+ return {
+ priority: -100, // run after default uiGridEditor directive
+ require: '?ngModel',
+ link: function (scope, element, attrs, ngModel) {
+
+ if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {
+
+ ngModel.$formatters.push(function (modelValue) {
+ ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));
+ return $filter('date')(modelValue, 'yyyy-MM-dd');
+ });
+
+ ngModel.$parsers.push(function (viewValue) {
+ if (viewValue && viewValue.length > 0) {
+ var dateValue = parseDateString(viewValue);
+ ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));
+ return dateValue;
+ }
+ else {
+ ngModel.$setValidity(null, true);
+ return null;
+ }
+ });
+ }
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditDropdown
+ * @element div
+ * @restrict A
+ *
+ * @description dropdown editor for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown, and any left/right nav
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditDropdown',
+ ['uiGridConstants', 'uiGridEditConstants', '$timeout',
+ function (uiGridConstants, uiGridEditConstants, $timeout) {
+ return {
+ require: ['?^uiGrid', '?^uiGridRenderContainer'],
+ scope: true,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var renderContainerCtrl = controllers[1];
+
+ //set focus at start of edit
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
+ $timeout(function(){
+ $elm[0].focus();
+ });
+
+ $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';
+ $elm.on('blur', function (evt) {
+ $scope.stopEdit(evt);
+ });
+ });
+
+
+ $scope.stopEdit = function (evt) {
+ // no need to validate a dropdown - invalid values shouldn't be
+ // available in the list
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ };
+
+ $elm.on('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ESC:
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ break;
+ }
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
+ if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
+ $scope.stopEdit(evt);
+ }
+ }
+ else {
+ //handle enter and tab for editing not using cellNav
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
+ case uiGridConstants.keymap.TAB:
+ evt.stopPropagation();
+ evt.preventDefault();
+ $scope.stopEdit(evt);
+ break;
+ }
+ }
+ return true;
+ });
+
+ $scope.$on('$destroy', function unbindEvents() {
+ // unbind jquery events to prevent memory leaks
+ $elm.off();
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditFileChooser
+ * @element div
+ * @restrict A
+ *
+ * @description input editor directive for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditFileChooser',
+ ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout',
+ function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout) {
+ return {
+ scope: true,
+ require: ['?^uiGrid', '?^uiGridRenderContainer'],
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl, renderContainerCtrl;
+ if (controllers[0]) { uiGridCtrl = controllers[0]; }
+ if (controllers[1]) { renderContainerCtrl = controllers[1]; }
+ var grid = uiGridCtrl.grid;
+
+ var handleFileSelect = function( event ){
+ var target = event.srcElement || event.target;
+
+ if (target && target.files && target.files.length > 0) {
+ /**
+ * @ngdoc property
+ * @name editFileChooserCallback
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description A function that should be called when any files have been chosen
+ * by the user. You should use this to process the files appropriately for your
+ * application.
+ *
+ * It passes the gridCol, the gridRow (from which you can get gridRow.entity),
+ * and the files. The files are in the format as returned from the file chooser,
+ * an array of files, with each having useful information such as:
+ * - `files[0].lastModifiedDate`
+ * - `files[0].name`
+ * - `files[0].size` (appears to be in bytes)
+ * - `files[0].type` (MIME type by the looks)
+ *
+ * Typically you would do something with these files - most commonly you would
+ * use the filename or read the file itself in. The example function does both.
+ *
+ * @example
+ * <pre>
+ * editFileChooserCallBack: function(gridRow, gridCol, files ){
+ * // ignore all but the first file, it can only choose one anyway
+ * // set the filename into this column
+ * gridRow.entity.filename = file[0].name;
+ *
+ * // read the file and set it into a hidden column, which we may do stuff with later
+ * var setFile = function(fileContent){
+ * gridRow.entity.file = fileContent.currentTarget.result;
+ * };
+ * var reader = new FileReader();
+ * reader.onload = setFile;
+ * reader.readAsText( files[0] );
+ * }
+ * </pre>
+ */
+ if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {
+ $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);
+ } else {
+ gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');
+ }
+
+ target.form.reset();
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ } else {
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ }
+ };
+
+ $elm[0].addEventListener('change', handleFileSelect, false);
+
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
+ $elm[0].focus();
+ $elm[0].select();
+
+ $elm.on('blur', function (evt) {
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ });
+ });
+
+ $scope.$on('$destroy', function unbindEvents() {
+ // unbind jquery events to prevent memory leaks
+ $elm.off();
+ $elm[0].removeEventListener('change', handleFileSelect, false);
+ });
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.emptyBaseLayer
+ * @description
+ *
+ * # ui.grid.emptyBaseLayer
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides the ability to have the background of the ui-grid be empty rows, this would be displayed in the case were
+ * the grid height is greater then the amount of rows displayed.
+ *
+ * <div doc-module-components="ui.grid.emptyBaseLayer"></div>
+ */
+ var module = angular.module('ui.grid.emptyBaseLayer', ['ui.grid']);
+
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.emptyBaseLayer.service:uiGridBaseLayerService
+ *
+ * @description Services for the empty base layer grid
+ */
+ module.service('uiGridBaseLayerService', ['gridUtil', '$compile', function (gridUtil, $compile) {
+ var service = {
+ initializeGrid: function (grid, disableEmptyBaseLayer) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.emptyBaseLayer.api:GridOptions
+ *
+ * @description GridOptions for emptyBaseLayer feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ grid.baseLayer = {
+ emptyRows: []
+ };
+
+ /**
+ * @ngdoc object
+ * @name enableEmptyGridBaseLayer
+ * @propertyOf ui.grid.emptyBaseLayer.api:GridOptions
+ * @description Enable empty base layer, which shows empty rows as background on the entire grid
+ * <br/>Defaults to true, if the directive is used.
+ * <br/>Set to false either by setting this attribute or passing false to the directive.
+ */
+ //default option to true unless it was explicitly set to false
+ if (grid.options.enableEmptyGridBaseLayer !== false) {
+ grid.options.enableEmptyGridBaseLayer = !disableEmptyBaseLayer;
+ }
+ },
+
+ setNumberOfEmptyRows: function(viewportHeight, grid) {
+ var rowHeight = grid.options.rowHeight,
+ rows = Math.ceil(viewportHeight / rowHeight);
+ if (rows > 0) {
+ grid.baseLayer.emptyRows = [];
+ for (var i = 0; i < rows; i++) {
+ grid.baseLayer.emptyRows.push({});
+ }
+ }
+ }
+ };
+ return service;
+ }]);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.emptyBaseLayer.directive:uiGridEmptyBaseLayer
+ * @description Shows empty rows in the background of the ui-grid, these span
+ * the full height of the ui-grid, so that there won't be blank space below the shown rows.
+ * @example
+ * <pre>
+ * <div ui-grid="gridOptions" class="grid" ui-grid-empty-base-layer></div>
+ * </pre>
+ * Or you can enable/disable it dynamically by passing in true or false. It doesn't
+ * the value, so it would only be set on initial render.
+ * <pre>
+ * <div ui-grid="gridOptions" class="grid" ui-grid-empty-base-layer="false"></div>
+ * </pre>
+ */
+ module.directive('uiGridEmptyBaseLayer', ['gridUtil', 'uiGridBaseLayerService',
+ '$parse',
+ function (gridUtil, uiGridBaseLayerService, $parse) {
+ return {
+ require: '^uiGrid',
+ scope: false,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var disableEmptyBaseLayer = $parse($attrs.uiGridEmptyBaseLayer)($scope) === false;
+ uiGridBaseLayerService.initializeGrid(uiGridCtrl.grid, disableEmptyBaseLayer);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if (!uiGridCtrl.grid.options.enableEmptyGridBaseLayer) {
+ return;
+ }
+
+ var renderBodyContainer = uiGridCtrl.grid.renderContainers.body,
+ viewportHeight = renderBodyContainer.getViewportHeight();
+
+ function heightHasChanged() {
+ var newViewPortHeight = renderBodyContainer.getViewportHeight();
+
+ if (newViewPortHeight !== viewportHeight) {
+ viewportHeight = newViewPortHeight;
+ return true;
+ }
+ return false;
+ }
+
+ function getEmptyBaseLayerCss(viewportHeight) {
+ // Set ui-grid-empty-base-layer height
+ return '.grid' + uiGridCtrl.grid.id +
+ ' .ui-grid-render-container ' +
+ '.ui-grid-empty-base-layer-container.ui-grid-canvas ' +
+ '{ height: ' + viewportHeight + 'px; }';
+ }
+
+ uiGridCtrl.grid.registerStyleComputation({
+ func: function() {
+ if (heightHasChanged()) {
+ uiGridBaseLayerService.setNumberOfEmptyRows(viewportHeight, uiGridCtrl.grid);
+ }
+ return getEmptyBaseLayerCss(viewportHeight);
+ }
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.emptyBaseLayer.directive:uiGridViewport
+ * @description stacks on the uiGridViewport directive to append the empty grid base layer html elements to the
+ * default gridRow template
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'gridUtil', '$templateCache',
+ function ($compile, gridUtil, $templateCache) {
+ return {
+ priority: -200,
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var emptyBaseLayerContainer = $templateCache.get('ui-grid/emptyBaseLayerContainer');
+ $elm.prepend(emptyBaseLayerContainer);
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.expandable
+ * @description
+ *
+ * # ui.grid.expandable
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides the ability to create subgrids with the ability to expand a row
+ * to show the subgrid.
+ *
+ * <div doc-module-components="ui.grid.expandable"></div>
+ */
+ var module = angular.module('ui.grid.expandable', ['ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.expandable.service:uiGridExpandableService
+ *
+ * @description Services for the expandable grid
+ */
+ module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {
+ var service = {
+ initializeGrid: function (grid) {
+
+ grid.expandable = {};
+ grid.expandable.expandedAll = false;
+
+ /**
+ * @ngdoc object
+ * @name enableExpandable
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids
+ * within your application, or in specific modes on _this_ grid. Defaults to true.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * enableExpandable: false
+ * }
+ * </pre>
+ */
+ grid.options.enableExpandable = grid.options.enableExpandable !== false;
+
+ /**
+ * @ngdoc object
+ * @name expandableRowHeight
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Height in pixels of the expanded subgrid. Defaults to
+ * 150
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowHeight: 150
+ * }
+ * </pre>
+ */
+ grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;
+
+ /**
+ * @ngdoc object
+ * @name
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Width in pixels of the expandable column. Defaults to 40
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowHeaderWidth: 40
+ * }
+ * </pre>
+ */
+ grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;
+
+ /**
+ * @ngdoc object
+ * @name expandableRowTemplate
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Mandatory. The template for your expanded row
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowTemplate: 'expandableRowTemplate.html'
+ * }
+ * </pre>
+ */
+ if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){
+ gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );
+ grid.options.enableExpandable = false;
+ }
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.expandable.api:PublicApi
+ *
+ * @description Public Api for expandable feature
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.expandable.api:GridRow
+ *
+ * @description Additional properties added to GridRow when using the expandable module
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.expandable.api:GridOptions
+ *
+ * @description Options for configuring the expandable feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ var publicApi = {
+ events: {
+ expandable: {
+ /**
+ * @ngdoc event
+ * @name rowExpandedStateChanged
+ * @eventOf ui.grid.expandable.api:PublicApi
+ * @description raised when row expanded or collapsed
+ * <pre>
+ * gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})
+ * </pre>
+ * @param {GridRow} row the row that was expanded
+ */
+ rowExpandedBeforeStateChanged: function(scope,row){
+ },
+ rowExpandedStateChanged: function (scope, row) {
+ }
+ }
+ },
+
+ methods: {
+ expandable: {
+ /**
+ * @ngdoc method
+ * @name toggleRowExpansion
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Toggle a specific row
+ * <pre>
+ * gridApi.expandable.toggleRowExpansion(rowEntity);
+ * </pre>
+ * @param {object} rowEntity the data entity for the row you want to expand
+ */
+ toggleRowExpansion: function (rowEntity) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null) {
+ service.toggleRowExpansion(grid, row);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name expandAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Expand all subgrids.
+ * <pre>
+ * gridApi.expandable.expandAllRows();
+ * </pre>
+ */
+ expandAllRows: function() {
+ service.expandAllRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @name collapseAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Collapse all subgrids.
+ * <pre>
+ * gridApi.expandable.collapseAllRows();
+ * </pre>
+ */
+ collapseAllRows: function() {
+ service.collapseAllRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @name toggleAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Toggle all subgrids.
+ * <pre>
+ * gridApi.expandable.toggleAllRows();
+ * </pre>
+ */
+ toggleAllRows: function() {
+ service.toggleAllRows(grid);
+ },
+ /**
+ * @ngdoc function
+ * @name expandRow
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Expand the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ */
+ expandRow: function (rowEntity) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && !row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name collapseRow
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Collapse the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ */
+ collapseRow: function (rowEntity) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name getExpandedRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description returns all expandedRow's entity references
+ */
+ getExpandedRows: function () {
+ return service.getExpandedRows(grid).map(function (gridRow) {
+ return gridRow.entity;
+ });
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+ toggleRowExpansion: function (grid, row) {
+ // trigger the "before change" event. Can change row height dynamically this way.
+ grid.api.expandable.raise.rowExpandedBeforeStateChanged(row);
+ /**
+ * @ngdoc object
+ * @name isExpanded
+ * @propertyOf ui.grid.expandable.api:GridRow
+ * @description Whether or not the row is currently expanded.
+ * @example
+ * <pre>
+ * $scope.api.expandable.on.rowExpandedStateChanged($scope, function (row) {
+ * if (row.isExpanded) {
+ * //...
+ * }
+ * });
+ * </pre>
+ */
+ row.isExpanded = !row.isExpanded;
+ if (angular.isUndefined(row.expandedRowHeight)){
+ row.expandedRowHeight = grid.options.expandableRowHeight;
+ }
+
+ if (row.isExpanded) {
+ row.height = row.grid.options.rowHeight + row.expandedRowHeight;
+ }
+ else {
+ row.height = row.grid.options.rowHeight;
+ grid.expandable.expandedAll = false;
+ }
+ grid.api.expandable.raise.rowExpandedStateChanged(row);
+ },
+
+ expandAllRows: function(grid, $scope) {
+ grid.renderContainers.body.visibleRowCache.forEach( function(row) {
+ if (!row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ });
+ grid.expandable.expandedAll = true;
+ grid.queueGridRefresh();
+ },
+
+ collapseAllRows: function(grid) {
+ grid.renderContainers.body.visibleRowCache.forEach( function(row) {
+ if (row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ });
+ grid.expandable.expandedAll = false;
+ grid.queueGridRefresh();
+ },
+
+ toggleAllRows: function(grid) {
+ if (grid.expandable.expandedAll) {
+ service.collapseAllRows(grid);
+ }
+ else {
+ service.expandAllRows(grid);
+ }
+ },
+
+ getExpandedRows: function (grid) {
+ return grid.rows.filter(function (row) {
+ return row.isExpanded;
+ });
+ }
+ };
+ return service;
+ }]);
+
+ /**
+ * @ngdoc object
+ * @name enableExpandableRowHeader
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Show a rowHeader to provide the expandable buttons. If set to false then implies
+ * you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * enableExpandableRowHeader: false
+ * }
+ * </pre>
+ */
+ module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',
+ function (uiGridExpandableService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridExpandableService.initializeGrid(uiGridCtrl.grid);
+
+ if (!uiGridCtrl.grid.options.enableExpandable) {
+ return;
+ }
+
+ if (uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {
+ var expandableRowHeaderColDef = {
+ name: 'expandableButtons',
+ displayName: '',
+ exporterSuppressExport: true,
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40
+ };
+ expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');
+ expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');
+ uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef, -90);
+ }
+
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGrid
+ * @description stacks on the uiGrid directive to register child grid with parent row when child is created
+ */
+ module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',
+ function (uiGridExpandableService, $templateCache) {
+ return {
+ replace: true,
+ priority: 599,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {
+ //if a parent grid row is on the scope, then add the parentRow property to this childGrid
+ if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.class:Grid
+ * @description Additional Grid properties added by expandable module
+ */
+
+ /**
+ * @ngdoc object
+ * @name parentRow
+ * @propertyOf ui.grid.expandable.class:Grid
+ * @description reference to the expanded parent row that owns this grid
+ */
+ uiGridCtrl.grid.parentRow = $scope.row;
+
+ //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event
+ // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {
+ // uiGridCtrl.grid.parentRow = newHeight;
+ // });
+ }
+
+ });
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridExpandableRow
+ * @description directive to render the expandable row template
+ */
+ module.directive('uiGridExpandableRow',
+ ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',
+ function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {
+
+ return {
+ replace: false,
+ priority: 0,
+ scope: false,
+
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(
+ function (template) {
+ if ($scope.grid.options.expandableRowScope) {
+ /**
+ * @ngdoc object
+ * @name expandableRowScope
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Variables of object expandableScope will be available in the scope of the expanded subgrid
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowScope: expandableScope
+ * }
+ * </pre>
+ */
+ var expandableRowScope = $scope.grid.options.expandableRowScope;
+ for (var property in expandableRowScope) {
+ if (expandableRowScope.hasOwnProperty(property)) {
+ $scope[property] = expandableRowScope[property];
+ }
+ }
+ }
+ var expandedRowElement = angular.element(template);
+ $elm.append(expandedRowElement);
+ expandedRowElement = $compile(expandedRowElement)($scope);
+ $scope.row.expandedRendered = true;
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ $scope.$on('$destroy', function() {
+ $scope.row.expandedRendered = false;
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridRow
+ * @description stacks on the uiGridRow directive to add support for expandable rows
+ */
+ module.directive('uiGridRow',
+ ['$compile', 'gridUtil', '$templateCache',
+ function ($compile, gridUtil, $templateCache) {
+ return {
+ priority: -200,
+ scope: false,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ if (!$scope.grid.options.enableExpandable) {
+ return;
+ }
+
+ $scope.expandableRow = {};
+
+ $scope.expandableRow.shouldRenderExpand = function () {
+ var ret = $scope.colContainer.name === 'body' && $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);
+ return ret;
+ };
+
+ $scope.expandableRow.shouldRenderFiller = function () {
+ var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));
+ return ret;
+ };
+
+ /*
+ * Commented out @PaulL1. This has no purpose that I can see, and causes #2964. If this code needs to be reinstated for some
+ * reason it needs to use drawnWidth, not width, and needs to check column visibility. It should really use render container
+ * visible column cache also instead of checking column.renderContainer.
+ function updateRowContainerWidth() {
+ var grid = $scope.grid;
+ var colWidth = 0;
+ grid.columns.forEach( function (column) {
+ if (column.renderContainer === 'left') {
+ colWidth += column.width;
+ }
+ });
+ colWidth = Math.floor(colWidth);
+ return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +
+ ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +
+ ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';
+ }
+
+ if ($scope.colContainer.name === 'left') {
+ $scope.grid.registerStyleComputation({
+ priority: 15,
+ func: updateRowContainerWidth
+ });
+ }*/
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridViewport
+ * @description stacks on the uiGridViewport directive to append the expandable row html elements to the
+ * default gridRow template
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'gridUtil', '$templateCache',
+ function ($compile, gridUtil, $templateCache) {
+ return {
+ priority: -200,
+ scope: false,
+ compile: function ($elm, $attrs) {
+
+ //todo: this adds ng-if watchers to each row even if the grid is not using expandable directive
+ // or options.enableExpandable == false
+ // The alternative is to compile the template and append to each row in a uiGridRow directive
+
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+ var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');
+ var expandedRowElement = $templateCache.get('ui-grid/expandableRow');
+ rowRepeatDiv.append(expandedRowElement);
+ rowRepeatDiv.append(expandedRowFillerElement);
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+/* global console */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.exporter
+ * @description
+ *
+ * # ui.grid.exporter
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to export data from the grid.
+ *
+ * Data can be exported in a range of formats, and all data, visible
+ * data, or selected rows can be exported, with all columns or visible
+ * columns.
+ *
+ * No UI is provided, the caller should provide their own UI/buttons
+ * as appropriate, or enable the gridMenu
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.exporter"></div>
+ */
+
+ var module = angular.module('ui.grid.exporter', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.constant:uiGridExporterConstants
+ *
+ * @description constants available in exporter module
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name ALL
+ * @description export all data, including data not visible. Can
+ * be set for either rowTypes or colTypes
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name VISIBLE
+ * @description export only visible data, including data not visible. Can
+ * be set for either rowTypes or colTypes
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name SELECTED
+ * @description export all data, including data not visible. Can
+ * be set only for rowTypes, selection of only some columns is
+ * not supported
+ */
+ module.constant('uiGridExporterConstants', {
+ featureName: 'exporter',
+ ALL: 'all',
+ VISIBLE: 'visible',
+ SELECTED: 'selected',
+ CSV_CONTENT: 'CSV_CONTENT',
+ BUTTON_LABEL: 'BUTTON_LABEL',
+ FILE_NAME: 'FILE_NAME'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.exporter.service:uiGridExporterService
+ *
+ * @description Services for exporter feature
+ */
+ module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',
+ function ($q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {
+
+ var service = {
+
+ delay: 100,
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.exporter = {};
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:PublicApi
+ *
+ * @description Public Api for exporter feature
+ */
+ var publicApi = {
+ events: {
+ exporter: {
+ }
+ },
+ methods: {
+ exporter: {
+ /**
+ * @ngdoc function
+ * @name csvExport
+ * @methodOf ui.grid.exporter.api:PublicApi
+ * @description Exports rows from the grid in csv format,
+ * the data exported is selected based on the provided options
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
+ */
+ csvExport: function (rowTypes, colTypes) {
+ service.csvExport(grid, rowTypes, colTypes);
+ },
+ /**
+ * @ngdoc function
+ * @name pdfExport
+ * @methodOf ui.grid.exporter.api:PublicApi
+ * @description Exports rows from the grid in pdf format,
+ * the data exported is selected based on the provided options
+ * Note that this function has a dependency on pdfMake, all
+ * going well this has been installed for you.
+ * The resulting pdf opens in a new browser window.
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
+ */
+ pdfExport: function (rowTypes, colTypes) {
+ service.pdfExport(grid, rowTypes, colTypes);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ } else {
+ // order of registration is not guaranteed, register in a little while
+ $interval( function() {
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ }
+ }, this.delay, 1);
+ }
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:GridOptions
+ *
+ * @description GridOptions for exporter feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:ColumnDef
+ * @description ColumnDef settings for exporter
+ */
+ /**
+ * @ngdoc object
+ * @name exporterSuppressMenu
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Don't show the export menu button, implying the user
+ * will roll their own UI for calling the exporter
+ * <br/>Defaults to false
+ */
+ gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;
+ /**
+ * @ngdoc object
+ * @name exporterMenuLabel
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The text to show on the exporter menu button
+ * link
+ * <br/>Defaults to 'Export'
+ */
+ gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';
+ /**
+ * @ngdoc object
+ * @name exporterSuppressColumns
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Columns that should not be exported. The selectionRowHeader is already automatically
+ * suppressed, but if you had a button column or some other "system" column that shouldn't be shown in the
+ * output then add it in this list. You should provide an array of column names.
+ * <br/>Defaults to: []
+ * <pre>
+ * gridOptions.exporterSuppressColumns = [ 'buttons' ];
+ * </pre>
+ */
+ gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];
+ /**
+ * @ngdoc object
+ * @name exporterCsvColumnSeparator
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The character to use as column separator
+ * link
+ * <br/>Defaults to ','
+ */
+ gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';
+ /**
+ * @ngdoc object
+ * @name exporterCsvFilename
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default filename to use when saving the downloaded csv.
+ * This will only work in some browsers.
+ * <br/>Defaults to 'download.csv'
+ */
+ gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';
+ /**
+ * @ngdoc object
+ * @name exporterPdfFilename
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)
+ * <br/>Defaults to 'download.pdf'
+ */
+ gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';
+ /**
+ * @ngdoc object
+ * @name exporterOlderExcelCompatibility
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes
+ * through as  in the first column header. Setting this option to false will suppress this, at the
+ * expense of proper utf-16 handling in applications that do recognise the BOM
+ * <br/>Defaults to false
+ */
+ gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;
+ /**
+ * @ngdoc object
+ * @name exporterIsExcelCompatible
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Separator header, used to set a custom column separator in a csv file, only works on MS Excel.
+ * Used it on other programs will make csv content display unproperly. Setting this option to false won't add this header.
+ * <br/>Defaults to false
+ */
+ gridOptions.exporterIsExcelCompatible = gridOptions.exporterIsExcelCompatible === true;
+ /**
+ * @ngdoc object
+ * @name exporterMenuItemOrder
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description An option to determine the starting point for the menu items created by the exporter
+ * <br/>Defaults to 200
+ */
+ gridOptions.exporterMenuItemOrder = gridOptions.exporterMenuItemOrder ? gridOptions.exporterMenuItemOrder : 200;
+ /**
+ * @ngdoc object
+ * @name exporterPdfDefaultStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * fontSize: 11
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The table style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * margin: [0, 5, 0, 15]
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableHeaderStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The tableHeader style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * bold: true,
+ * fontSize: 12,
+ * color: 'black'
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };
+ /**
+ * @ngdoc object
+ * @name exporterPdfHeader
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The header section for pdf exports. Can be
+ * simple text:
+ * <pre>
+ * gridOptions.exporterPdfHeader = 'My Header';
+ * </pre>
+ * Can be a more complex object in pdfMake format:
+ * <pre>
+ * gridOptions.exporterPdfHeader = {
+ * columns: [
+ * 'Left part',
+ * { text: 'Right part', alignment: 'right' }
+ * ]
+ * };
+ * </pre>
+ * Or can be a function, allowing page numbers and the like
+ * <pre>
+ * gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
+ * </pre>
+ */
+ gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;
+ /**
+ * @ngdoc object
+ * @name exporterPdfFooter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The header section for pdf exports. Can be
+ * simple text:
+ * <pre>
+ * gridOptions.exporterPdfFooter = 'My Footer';
+ * </pre>
+ * Can be a more complex object in pdfMake format:
+ * <pre>
+ * gridOptions.exporterPdfFooter = {
+ * columns: [
+ * 'Left part',
+ * { text: 'Right part', alignment: 'right' }
+ * ]
+ * };
+ * </pre>
+ * Or can be a function, allowing page numbers and the like
+ * <pre>
+ * gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
+ * </pre>
+ */
+ gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;
+ /**
+ * @ngdoc object
+ * @name exporterPdfOrientation
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The orientation, should be a valid pdfMake value,
+ * 'landscape' or 'portrait'
+ * <br/>Defaults to landscape
+ */
+ gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';
+ /**
+ * @ngdoc object
+ * @name exporterPdfPageSize
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The orientation, should be a valid pdfMake
+ * paper size, usually 'A4' or 'LETTER'
+ * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}
+ * <br/>Defaults to A4
+ */
+ gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';
+ /**
+ * @ngdoc object
+ * @name exporterPdfMaxGridWidth
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The maxium grid width - the current grid width
+ * will be scaled to match this, with any fixed width columns
+ * being adjusted accordingly.
+ * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER
+ */
+ gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableLayout
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A tableLayout in pdfMake format,
+ * controls gridlines and the like. We use the default
+ * layout usually.
+ * <br/>Defaults to null, which means no layout
+ */
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuAllData
+ * @porpertyOf ui.grid.exporter.api:GridOptions
+ * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuVisibleData
+ * @porpertyOf ui.grid.exporter.api:GridOptions
+ * @description Add export visible data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuVisibleData = gridOptions.exporterMenuVisibleData !== undefined ? gridOptions.exporterMenuVisibleData : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuSelectedData
+ * @porpertyOf ui.grid.exporter.api:GridOptions
+ * @description Add export selected data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuSelectedData = gridOptions.exporterMenuSelectedData !== undefined ? gridOptions.exporterMenuSelectedData : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuCsv
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Add csv export menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuPdf
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Add pdf export menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterPdfCustomFormatter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A custom callback routine that changes the pdf document, adding any
+ * custom styling or content that is supported by pdfMake. Takes in the complete docDefinition, and
+ * must return an updated docDefinition ready for pdfMake.
+ * @example
+ * In this example we add a style to the style array, so that we can use it in our
+ * footer definition.
+ * <pre>
+ * gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {
+ * docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };
+ * return docDefinition;
+ * }
+ *
+ * gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }
+ * </pre>
+ */
+ gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };
+
+ /**
+ * @ngdoc object
+ * @name exporterHeaderFilterUseName
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.
+ * If set to true, then will pass `name` instead.
+ *
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterHeaderFilterUseName = true;
+ * </pre>
+ */
+ gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;
+
+ /**
+ * @ngdoc object
+ * @name exporterHeaderFilter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A function to apply to the header displayNames before exporting. Useful for internationalisation,
+ * for example if you were using angular-translate you'd set this to `$translate.instant`. Note that this
+ * call must be synchronous, it cannot be a call that returns a promise.
+ *
+ * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };
+ * </pre>
+ * OR
+ * <pre>
+ * gridOptions.exporterHeaderFilter = $translate.instant;
+ * </pre>
+ */
+
+ /**
+ * @ngdoc function
+ * @name exporterFieldCallback
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A function to call for each field before exporting it. Allows
+ * massaging of raw data into a display format, for example if you have applied
+ * filters to convert codes into decodes, or you require
+ * a specific date format in the exported content.
+ *
+ * The method is called once for each field exported, and provides the grid, the
+ * gridCol and the GridRow for you to use as context in massaging the data.
+ *
+ * @param {Grid} grid provides the grid in case you have need of it
+ * @param {GridRow} row the row from which the data comes
+ * @param {GridCol} col the column from which the data comes
+ * @param {object} value the value for your massaging
+ * @returns {object} you must return the massaged value ready for exporting
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterFieldCallback = function ( grid, row, col, value ){
+ * if ( col.name === 'status' ){
+ * value = decodeStatus( value );
+ * }
+ * return value;
+ * }
+ * </pre>
+ */
+ gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };
+
+ /**
+ * @ngdoc function
+ * @name exporterAllDataFn
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description This promise is needed when exporting all rows,
+ * and the data need to be provided by server side. Default is null.
+ * @returns {Promise} a promise to load all data from server
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterAllDataFn = function () {
+ * return $http.get('/data/100.json')
+ * }
+ * </pre>
+ */
+ gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;
+
+ /**
+ * @ngdoc function
+ * @name exporterAllDataPromise
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description DEPRECATED - exporterAllDataFn used to be
+ * called this, but it wasn't a promise, it was a function that returned
+ * a promise. Deprecated, but supported for backward compatibility, use
+ * exporterAllDataFn instead.
+ * @returns {Promise} a promise to load all data from server
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterAllDataFn = function () {
+ * return $http.get('/data/100.json')
+ * }
+ * </pre>
+ */
+ if ( gridOptions.exporterAllDataFn == null && gridOptions.exporterAllDataPromise ) {
+ gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToMenu
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Adds export items to the grid menu,
+ * allowing the user to select export options
+ * @param {Grid} grid the grid from which data should be exported
+ */
+ addToMenu: function ( grid ) {
+ grid.api.core.addToGridMenu( grid, [
+ {
+ title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuAllData;
+ },
+ order: grid.options.exporterMenuItemOrder
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuVisibleData;
+ },
+ order: grid.options.exporterMenuItemOrder + 1
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuSelectedData &&
+ ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
+ },
+ order: grid.options.exporterMenuItemOrder + 2
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuAllData;
+ },
+ order: grid.options.exporterMenuItemOrder + 3
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuVisibleData;
+ },
+ order: grid.options.exporterMenuItemOrder + 4
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuSelectedData &&
+ ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
+ },
+ order: grid.options.exporterMenuItemOrder + 5
+ }
+ ]);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name csvExport
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Exports rows from the grid in csv format,
+ * the data exported is selected based on the provided options
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ csvExport: function (grid, rowTypes, colTypes) {
+ var self = this;
+ this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
+ var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
+ var exportData = self.getData(grid, rowTypes, colTypes);
+ var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);
+
+ self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterCsvColumnSeparator, grid.options.exporterOlderExcelCompatibility, grid.options.exporterIsExcelCompatible);
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name loadAllDataIfNeeded
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description When using server side pagination, use exporterAllDataFn to
+ * load all data before continuing processing.
+ * When using client side pagination, return a resolved promise so processing
+ * continues immediately
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {
+ if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {
+ return grid.options.exporterAllDataFn()
+ .then(function() {
+ grid.modifyRows(grid.options.data);
+ });
+ } else {
+ var deferred = $q.defer();
+ deferred.resolve();
+ return deferred.promise;
+ }
+ },
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.api:ColumnDef
+ * @name exporterSuppressExport
+ * @description Suppresses export for this column. Used by selection and expandable.
+ */
+
+ /**
+ * @ngdoc function
+ * @name getColumnHeaders
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Gets the column headers from the grid to use
+ * as a title row for the exported file, all headers have
+ * headerCellFilters applied as appropriate.
+ *
+ * Column headers are an array of objects, each object has
+ * name, displayName, width and align attributes. Only name is
+ * used for csv, all attributes are used for pdf.
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ getColumnHeaders: function (grid, colTypes) {
+ var headers = [];
+ var columns;
+
+ if ( colTypes === uiGridExporterConstants.ALL ){
+ columns = grid.columns;
+ } else {
+ var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+
+ columns = leftColumns.concat(bodyColumns,rightColumns);
+ }
+
+ columns.forEach( function( gridCol, index ) {
+ if ( gridCol.colDef.exporterSuppressExport !== true &&
+ grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
+ headers.push({
+ name: gridCol.field,
+ displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,
+ width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,
+ align: gridCol.colDef.type === 'number' ? 'right' : 'left'
+ });
+ }
+ });
+
+ return headers;
+ },
+
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.api:ColumnDef
+ * @name exporterPdfAlign
+ * @description the alignment you'd like for this specific column when
+ * exported into a pdf. Can be 'left', 'right', 'center' or any other
+ * valid pdfMake alignment option.
+ */
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:GridRow
+ * @description GridRow settings for exporter
+ */
+ /**
+ * @ngdoc object
+ * @name exporterEnableExporting
+ * @propertyOf ui.grid.exporter.api:GridRow
+ * @description If set to false, then don't export this row, notwithstanding visible or
+ * other settings
+ * <br/>Defaults to true
+ */
+
+ /**
+ * @ngdoc function
+ * @name getData
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Gets data from the grid based on the provided options,
+ * all cells have cellFilters applied as appropriate. Any rows marked
+ * `exporterEnableExporting: false` will not be exported
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {boolean} applyCellFilters whether or not to get the display value or the raw value of the data
+ */
+ getData: function (grid, rowTypes, colTypes, applyCellFilters) {
+ var data = [];
+ var rows;
+ var columns;
+
+ switch ( rowTypes ) {
+ case uiGridExporterConstants.ALL:
+ rows = grid.rows;
+ break;
+ case uiGridExporterConstants.VISIBLE:
+ rows = grid.getVisibleRows();
+ break;
+ case uiGridExporterConstants.SELECTED:
+ if ( grid.api.selection ){
+ rows = grid.api.selection.getSelectedGridRows();
+ } else {
+ gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');
+ }
+ break;
+ }
+
+ if ( colTypes === uiGridExporterConstants.ALL ){
+ columns = grid.columns;
+ } else {
+ var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+
+ columns = leftColumns.concat(bodyColumns,rightColumns);
+ }
+
+ rows.forEach( function( row, index ) {
+
+ if (row.exporterEnableExporting !== false) {
+ var extractedRow = [];
+
+
+ columns.forEach( function( gridCol, index ) {
+ if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&
+ gridCol.colDef.exporterSuppressExport !== true &&
+ grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
+ var cellValue = applyCellFilters ? grid.getCellDisplayValue( row, gridCol ) : grid.getCellValue( row, gridCol );
+ var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, cellValue ) };
+ if ( gridCol.colDef.exporterPdfAlign ) {
+ extractedField.alignment = gridCol.colDef.exporterPdfAlign;
+ }
+ extractedRow.push(extractedField);
+ }
+ });
+
+ data.push(extractedRow);
+ }
+ });
+
+ return data;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name formatAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Formats the column headers and data as a CSV,
+ * and sends that data to the user
+ * @param {array} exportColumnHeaders an array of column headers,
+ * where each header is an object with name, width and maybe alignment
+ * @param {array} exportData an array of rows, where each row is
+ * an array of column data
+ * @param {string} separator a string that represents the separator to be used in the csv file
+ * @returns {string} csv the formatted csv as a string
+ */
+ formatAsCsv: function (exportColumnHeaders, exportData, separator) {
+ var self = this;
+
+ var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});
+
+ var csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\n') : '';
+
+ csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\n');
+
+ return csv;
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatRowAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a csv field, including
+ * quotes around the value
+ * @param {exporterService} exporter pass in exporter
+ * @param {array} row the row to be turned into a csv string
+ * @returns {string} a csv-ified version of the row
+ */
+ formatRowAsCsv: function (exporter, separator) {
+ return function (row) {
+ return row.map(exporter.formatFieldAsCsv).join(separator);
+ };
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatFieldAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a csv field, including
+ * quotes around the value
+ * @param {field} field the field to be turned into a csv string,
+ * may be of any type
+ * @returns {string} a csv-ified version of the field
+ */
+ formatFieldAsCsv: function (field) {
+ if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
+ return '';
+ }
+ if (typeof(field.value) === 'number') {
+ return field.value;
+ }
+ if (typeof(field.value) === 'boolean') {
+ return (field.value ? 'TRUE' : 'FALSE') ;
+ }
+ if (typeof(field.value) === 'string') {
+ return '"' + field.value.replace(/"/g,'""') + '"';
+ }
+
+ return JSON.stringify(field.value);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name isIE
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Checks whether current browser is IE and returns it's version if it is
+ */
+ isIE: function () {
+ var match = navigator.userAgent.search(/(?:Edge|MSIE|Trident\/.*; rv:)/);
+ var isIE = false;
+
+ if (match !== -1) {
+ isIE = true;
+ }
+
+ return isIE;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name downloadFile
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Triggers download of a csv file. Logic provided
+ * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391
+ * @param {string} fileName the filename we'd like our file to be
+ * given
+ * @param {string} csvContent the csv content that we'd like to
+ * download as a file
+ * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\uFEFF)
+ * @param {boolean} exporterIsExcelCompatible whether or not we add separator header ('sep=X')
+ */
+ downloadFile: function (fileName, csvContent, columnSeparator, exporterOlderExcelCompatibility, exporterIsExcelCompatible) {
+ var D = document;
+ var a = D.createElement('a');
+ var strMimeType = 'application/octet-stream;charset=utf-8';
+ var rawFile;
+ var ieVersion = this.isIE();
+
+ if (exporterIsExcelCompatible) {
+ csvContent = 'sep=' + columnSeparator + '\r\n' + csvContent;
+ }
+
+ // IE10+
+ if (navigator.msSaveBlob) {
+ return navigator.msSaveOrOpenBlob(
+ new Blob(
+ [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
+ { type: strMimeType } ),
+ fileName
+ );
+ }
+
+ if (ieVersion) {
+ var frame = D.createElement('iframe');
+ document.body.appendChild(frame);
+
+ frame.contentWindow.document.open('text/html', 'replace');
+ frame.contentWindow.document.write(csvContent);
+ frame.contentWindow.document.close();
+ frame.contentWindow.focus();
+ frame.contentWindow.document.execCommand('SaveAs', true, fileName);
+
+ document.body.removeChild(frame);
+ return true;
+ }
+
+ //html5 A[download]
+ if ('download' in a) {
+ var blob = new Blob(
+ [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
+ { type: strMimeType }
+ );
+ rawFile = URL.createObjectURL(blob);
+ a.setAttribute('download', fileName);
+ } else {
+ rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);
+ a.setAttribute('target', '_blank');
+ }
+
+ a.href = rawFile;
+ a.setAttribute('style', 'display:none;');
+ D.body.appendChild(a);
+ setTimeout(function() {
+ if (a.click) {
+ a.click();
+ // Workaround for Safari 5
+ } else if (document.createEvent) {
+ var eventObj = document.createEvent('MouseEvents');
+ eventObj.initEvent('click', true, true);
+ a.dispatchEvent(eventObj);
+ }
+ D.body.removeChild(a);
+
+ }, this.delay);
+ },
+
+ /**
+ * @ngdoc function
+ * @name pdfExport
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Exports rows from the grid in pdf format,
+ * the data exported is selected based on the provided options.
+ * Note that this function has a dependency on pdfMake, which must
+ * be installed. The resulting pdf opens in a new
+ * browser window.
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ pdfExport: function (grid, rowTypes, colTypes) {
+ var self = this;
+ this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {
+ var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);
+ var exportData = self.getData(grid, rowTypes, colTypes);
+ var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);
+
+ if (self.isIE() || navigator.appVersion.indexOf("Edge") !== -1) {
+ self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);
+ } else {
+ pdfMake.createPdf(docDefinition).open();
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name downloadPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Generates and retrieves the pdf as a blob, then downloads
+ * it as a file. Only used in IE, in all other browsers we use the native
+ * pdfMake.open function to just open the PDF
+ * @param {string} fileName the filename to give to the pdf, can be set
+ * through exporterPdfFilename
+ * @param {object} docDefinition a pdf docDefinition that we can generate
+ * and get a blob from
+ */
+ downloadPDF: function (fileName, docDefinition) {
+ var D = document;
+ var a = D.createElement('a');
+ var strMimeType = 'application/octet-stream;charset=utf-8';
+ var rawFile;
+ var ieVersion;
+
+ ieVersion = this.isIE(); // This is now a boolean value
+ var doc = pdfMake.createPdf(docDefinition);
+ var blob;
+
+ doc.getBuffer( function (buffer) {
+ blob = new Blob([buffer]);
+
+ // IE10+
+ if (navigator.msSaveBlob) {
+ return navigator.msSaveBlob(
+ blob, fileName
+ );
+ }
+
+ // Previously: && ieVersion < 10
+ // ieVersion now returns a boolean for the
+ // sake of sanity. We just check `msSaveBlob` first.
+ if (ieVersion) {
+ var frame = D.createElement('iframe');
+ document.body.appendChild(frame);
+
+ frame.contentWindow.document.open("text/html", "replace");
+ frame.contentWindow.document.write(blob);
+ frame.contentWindow.document.close();
+ frame.contentWindow.focus();
+ frame.contentWindow.document.execCommand('SaveAs', true, fileName);
+
+ document.body.removeChild(frame);
+ return true;
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name renderAsPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders the data into a pdf, and opens that pdf.
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {array} exportColumnHeaders an array of column headers,
+ * where each header is an object with name, width and maybe alignment
+ * @param {array} exportData an array of rows, where each row is
+ * an array of column data
+ * @returns {object} a pdfMake format document definition, ready
+ * for generation
+ */
+ prepareAsPdf: function(grid, exportColumnHeaders, exportData) {
+ var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );
+
+ var headerColumns = exportColumnHeaders.map( function( header ) {
+ return { text: header.displayName, style: 'tableHeader' };
+ });
+
+ var stringData = exportData.map(this.formatRowAsPdf(this));
+
+ var allData = [headerColumns].concat(stringData);
+
+ var docDefinition = {
+ pageOrientation: grid.options.exporterPdfOrientation,
+ pageSize: grid.options.exporterPdfPageSize,
+ content: [{
+ style: 'tableStyle',
+ table: {
+ headerRows: 1,
+ widths: headerWidths,
+ body: allData
+ }
+ }],
+ styles: {
+ tableStyle: grid.options.exporterPdfTableStyle,
+ tableHeader: grid.options.exporterPdfTableHeaderStyle
+ },
+ defaultStyle: grid.options.exporterPdfDefaultStyle
+ };
+
+ if ( grid.options.exporterPdfLayout ){
+ docDefinition.layout = grid.options.exporterPdfLayout;
+ }
+
+ if ( grid.options.exporterPdfHeader ){
+ docDefinition.header = grid.options.exporterPdfHeader;
+ }
+
+ if ( grid.options.exporterPdfFooter ){
+ docDefinition.footer = grid.options.exporterPdfFooter;
+ }
+
+ if ( grid.options.exporterPdfCustomFormatter ){
+ docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );
+ }
+ return docDefinition;
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name calculatePdfHeaderWidths
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Determines the column widths base on the
+ * widths we got from the grid. If the column is drawn
+ * then we have a drawnWidth. If the column is not visible
+ * then we have '*', 'x%' or a width. When columns are
+ * not visible they don't contribute to the overall gridWidth,
+ * so we need to adjust to allow for extra columns
+ *
+ * Our basic heuristic is to take the current gridWidth, plus
+ * numeric columns and call this the base gridwidth.
+ *
+ * To that we add 100 for any '*' column, and x% of the base gridWidth
+ * for any column that is a %
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {array} exportHeaders array of header information
+ * @returns {object} an array of header widths
+ */
+ calculatePdfHeaderWidths: function ( grid, exportHeaders ) {
+ var baseGridWidth = 0;
+ exportHeaders.forEach( function(value){
+ if (typeof(value.width) === 'number'){
+ baseGridWidth += value.width;
+ }
+ });
+
+ var extraColumns = 0;
+ exportHeaders.forEach( function(value){
+ if (value.width === '*'){
+ extraColumns += 100;
+ }
+ if (typeof(value.width) === 'string' && value.width.match(/(\d)*%/)) {
+ var percent = parseInt(value.width.match(/(\d)*%/)[0]);
+
+ value.width = baseGridWidth * percent / 100;
+ extraColumns += value.width;
+ }
+ });
+
+ var gridWidth = baseGridWidth + extraColumns;
+
+ return exportHeaders.map(function( header ) {
+ return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;
+ });
+
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatRowAsPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a row in a format consumable by PDF,
+ * mainly meaning casting everything to a string
+ * @param {exporterService} exporter pass in exporter
+ * @param {array} row the row to be turned into a csv string
+ * @returns {string} a csv-ified version of the row
+ */
+ formatRowAsPdf: function ( exporter ) {
+ return function( row ) {
+ return row.map(exporter.formatFieldAsPdfString);
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name formatFieldAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a pdf-able field, which
+ * is different from a csv field only in that strings don't have quotes
+ * around them
+ * @param {field} field the field to be turned into a pdf string,
+ * may be of any type
+ * @returns {string} a string-ified version of the field
+ */
+ formatFieldAsPdfString: function (field) {
+ var returnVal;
+ if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
+ returnVal = '';
+ } else if (typeof(field.value) === 'number') {
+ returnVal = field.value.toString();
+ } else if (typeof(field.value) === 'boolean') {
+ returnVal = (field.value ? 'TRUE' : 'FALSE') ;
+ } else if (typeof(field.value) === 'string') {
+ returnVal = field.value.replace(/"/g,'""');
+ } else {
+ returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
+ }
+
+ if (field.alignment && typeof(field.alignment) === 'string' ){
+ returnVal = { text: returnVal, alignment: field.alignment };
+ }
+
+ return returnVal;
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.exporter.directive:uiGridExporter
+ * @element div
+ * @restrict A
+ *
+ * @description Adds exporter features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.gridOptions = {
+ enableGridMenu: true,
+ exporterMenuCsv: false,
+ columnDefs: [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ],
+ data: $scope.data
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-exporter></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',
+ function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridExporterService.initializeGrid(uiGridCtrl.grid);
+ uiGridCtrl.grid.exporter.$scope = $scope;
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.grouping
+ * @description
+ *
+ * # ui.grid.grouping
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides grouping of rows based on the data in them, similar
+ * in concept to excel grouping. You can group multiple columns, resulting in
+ * nested grouping.
+ *
+ * In concept this feature is similar to sorting + grid footer/aggregation, it
+ * sorts the data based on the grouped columns, then creates group rows that
+ * reflect a break in the data. Each of those group rows can have aggregations for
+ * the data within that group.
+ *
+ * This feature leverages treeBase to provide the tree functionality itself,
+ * the key thing this feature does therefore is to set treeLevels on the rows
+ * and insert the group headers.
+ *
+ * Design information:
+ * -------------------
+ *
+ * Each column will get new menu items - group by, and aggregate by. Group by
+ * will cause this column to be sorted (if not already), and will move this column
+ * to the front of the sorted columns (i.e. grouped columns take precedence over
+ * sorted columns). It will respect the sort order already set if there is one,
+ * and it will allow the sorting logic to change that sort order, it just forces
+ * the column to the front of the sorting. You can group by multiple columns, the
+ * logic will add this column to the sorting after any already grouped columns.
+ *
+ * Once a grouping is defined, grouping logic is added to the rowsProcessors. This
+ * will process the rows, identifying a break in the data value, and inserting a grouping row.
+ * Grouping rows have specific attributes on them:
+ *
+ * - internalRow = true: tells us that this isn't a real row, so we can ignore it
+ * from any processing that it looking at core data rows. This is used by the core
+ * logic (or will be one day), as it's not grouping specific
+ * - groupHeader = true: tells us this is a groupHeader. This is used by the grouping logic
+ * to know if this is a groupHeader row or not
+ *
+ * Since the logic is baked into the rowsProcessors, it should get triggered whenever
+ * row order or filtering or anything like that is changed. In order to avoid the row instantiation
+ * time, and to preserve state across invocations, we hold a cache of the rows that we created
+ * last time, and we use them again this time if we can.
+ *
+ * By default rows are collapsed, which means all data rows have their visible property
+ * set to false, and only level 0 group rows are set to visible.
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.grouping"></div>
+ */
+
+ var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.constant:uiGridGroupingConstants
+ *
+ * @description constants available in grouping module, this includes
+ * all the constants declared in the treeBase module (these are manually copied
+ * as there isn't an easy way to include constants in another constants file, and
+ * we don't want to make users include treeBase)
+ *
+ */
+ module.constant('uiGridGroupingConstants', {
+ featureName: "grouping",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.grouping.service:uiGridGroupingService
+ *
+ * @description Services for grouping features
+ */
+ module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',
+ function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+ uiGridTreeBaseService.initializeGrid( grid, $scope );
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.grid:grouping
+ *
+ * @description Grid properties and functions added for grouping
+ */
+ grid.grouping = {};
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.grouping.grid:grouping
+ * @name groupHeaderCache
+ *
+ * @description Cache that holds the group header rows we created last time, we'll
+ * reuse these next time, not least because they hold our expanded states.
+ *
+ * We need to take care with these that they don't become a memory leak, we
+ * create a new cache each time using the values from the old cache. This works
+ * so long as we're creating group rows for invisible rows as well.
+ *
+ * The cache is a nested hash, indexed on the value we grouped by. So if we
+ * grouped by gender then age, we'd maybe have something like:
+ * ```
+ * {
+ * male: {
+ * row: <pointer to the old row>,
+ * children: {
+ * 22: { row: <pointer to the old row> },
+ * 31: { row: <pointer to the old row> }
+ * },
+ * female: {
+ * row: <pointer to the old row>,
+ * children: {
+ * 28: { row: <pointer to the old row> },
+ * 55: { row: <pointer to the old row> }
+ * }
+ * }
+ * ```
+ *
+ * We create new rows for any missing rows, this means that they come in as collapsed.
+ *
+ */
+ grid.grouping.groupHeaderCache = {};
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerRowsProcessor(service.groupRows, 400);
+
+ grid.registerColumnBuilder( service.groupingColumnBuilder);
+
+ grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:PublicApi
+ *
+ * @description Public Api for grouping feature
+ */
+ var publicApi = {
+ events: {
+ grouping: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.grouping.api:PublicApi
+ * @name aggregationChanged
+ * @description raised whenever aggregation is changed, added or removed from a column
+ *
+ * <pre>
+ * gridApi.grouping.on.aggregationChanged(scope,function(col){})
+ * </pre>
+ * @param {gridCol} col the column which on which aggregation changed. The aggregation
+ * type is available as `col.treeAggregation.type`
+ */
+ aggregationChanged: {},
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.grouping.api:PublicApi
+ * @name groupingChanged
+ * @description raised whenever the grouped columns changes
+ *
+ * <pre>
+ * gridApi.grouping.on.groupingChanged(scope,function(col){})
+ * </pre>
+ * @param {gridCol} col the column which on which grouping changed. The new grouping is
+ * available as `col.grouping`
+ */
+ groupingChanged: {}
+ }
+ },
+ methods: {
+ grouping: {
+ /**
+ * @ngdoc function
+ * @name getGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Get the grouping configuration for this grid,
+ * used by the saveState feature. Adds expandedState to the information
+ * provided by the internal getGrouping, and removes any aggregations that have a source
+ * of grouping (i.e. will be automatically reapplied when we regroup the column)
+ * Returned grouping is an object
+ * `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`
+ * where grouping contains an array of objects:
+ * `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`
+ * and aggregations contains an array of objects:
+ * `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`
+ * and expandedState is a hash of the currently expanded nodes
+ *
+ * The groupArray will be sorted by groupPriority.
+ *
+ * @param {boolean} getExpanded whether or not to return the expanded state
+ * @returns {object} grouping configuration
+ */
+ getGrouping: function ( getExpanded ) {
+ var grouping = service.getGrouping(grid);
+
+ grouping.grouping.forEach( function( group ) {
+ group.colName = group.col.name;
+ delete group.col;
+ });
+
+ grouping.aggregations.forEach( function( aggregation ) {
+ aggregation.colName = aggregation.col.name;
+ delete aggregation.col;
+ });
+
+ grouping.aggregations = grouping.aggregations.filter( function( aggregation ){
+ return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';
+ });
+
+ if ( getExpanded ){
+ grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );
+ }
+
+ return grouping;
+ },
+
+ /**
+ * @ngdoc function
+ * @name setGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Set the grouping configuration for this grid,
+ * used by the saveState feature, but can also be used by any
+ * user to specify a combined grouping and aggregation configuration
+ * @param {object} config the config you want to apply, in the format
+ * provided out by getGrouping
+ */
+ setGrouping: function ( config ) {
+ service.setGrouping(grid, config);
+ },
+
+ /**
+ * @ngdoc function
+ * @name groupColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Adds this column to the existing grouping, at the end of the priority order.
+ * If the column doesn't have a sort, adds one, by default ASC
+ *
+ * This column will move to the left of any non-group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {string} columnName the name of the column we want to group
+ */
+ groupColumn: function( columnName ) {
+ var column = grid.getColumn(columnName);
+ service.groupColumn(grid, column);
+ },
+
+ /**
+ * @ngdoc function
+ * @name ungroupColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Removes the groupPriority from this column. If the
+ * column was previously aggregated the aggregation will come back.
+ * The sort will remain.
+ *
+ * This column will move to the right of any other group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {string} columnName the name of the column we want to ungroup
+ */
+ ungroupColumn: function( columnName ) {
+ var column = grid.getColumn(columnName);
+ service.ungroupColumn(grid, column);
+ },
+
+ /**
+ * @ngdoc function
+ * @name clearGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
+ * as we don't know whether that sorting was added by grouping or was there beforehand
+ *
+ */
+ clearGrouping: function() {
+ service.clearGrouping(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name aggregateColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Sets the aggregation type on a column, if the
+ * column is currently grouped then it removes the grouping first.
+ * If the aggregationDef is null then will result in the aggregation
+ * being removed
+ *
+ * @param {string} columnName the column we want to aggregate
+ * @param {string} or {function} aggregationDef one of the recognised types
+ * from uiGridGroupingConstants or a custom aggregation function.
+ * @param {string} aggregationLabel (optional) The label to use for this aggregation.
+ */
+ aggregateColumn: function( columnName, aggregationDef, aggregationLabel){
+ var column = grid.getColumn(columnName);
+ service.aggregateColumn( grid, column, aggregationDef, aggregationLabel);
+ }
+
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ grid.api.core.on.sortChanged( $scope, service.tidyPriorities);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:GridOptions
+ *
+ * @description GridOptions for grouping feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableGrouping
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description Enable row grouping for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableGrouping = gridOptions.enableGrouping !== false;
+
+ /**
+ * @ngdoc object
+ * @name groupingShowCounts
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a
+ * sortingAlgorithm which relies on a specific format or data type, showing counts may cause that
+ * to break, since the group header rows will always be a string with groupingShowCounts enabled.
+ * <br/>Defaults to true except on columns of types 'date' and 'object'
+ */
+ gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;
+
+ /**
+ * @ngdoc object
+ * @name groupingNullLabel
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.
+ * <br/>Defaults to "Null"
+ */
+ gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;
+
+ /**
+ * @ngdoc object
+ * @name enableGroupHeaderSelection
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description Allows group header rows to be selected.
+ * <br/>Defaults to false
+ */
+ gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupingColumnBuilder
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Sets the grouping defaults based on the columnDefs
+ *
+ * @param {object} colDef columnDef we're basing on
+ * @param {GridCol} col the column we're to update
+ * @param {object} gridOptions the options we should use
+ * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
+ */
+ groupingColumnBuilder: function (colDef, col, gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:ColumnDef
+ *
+ * @description ColumnDef for grouping feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableGrouping
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Enable grouping on this column
+ * <br/>Defaults to true.
+ */
+ if (colDef.enableGrouping === false){
+ return;
+ }
+
+ /**
+ * @ngdoc object
+ * @name grouping
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Set the grouping for a column. Format is:
+ * ```
+ * {
+ * groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>
+ * }
+ * ```
+ *
+ * **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation
+ * setting in treeBase**
+ *
+ * We group in the priority order given, this will also put these columns to the high order of the sort irrespective
+ * of the sort priority given them. If there is no sort defined then we sort ascending, if there is a sort defined then
+ * we use that sort.
+ *
+ * If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the
+ * aggregation types to determine what sort of aggregation we can do. Values are in the constants file, but
+ * include SUM, COUNT, MAX, MIN
+ *
+ * groupPriorities should generally be sequential, if they're not then the next time getGrouping is called
+ * we'll renumber them to be sequential.
+ * <br/>Defaults to undefined.
+ */
+
+ if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {
+ col.grouping = angular.copy(colDef.grouping);
+ if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ){
+ col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
+ col.treeAggregationFinalizerFn = service.groupedFinalizerFn;
+ }
+ } else if (typeof(col.grouping) === 'undefined'){
+ col.grouping = {};
+ }
+
+ if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0){
+ col.suppressRemoveSort = true;
+ }
+
+ var groupColumn = {
+ name: 'ui.grid.grouping.group',
+ title: i18nService.get().grouping.group,
+ icon: 'ui-grid-icon-indent-right',
+ shown: function () {
+ return typeof(this.context.col.grouping) === 'undefined' ||
+ typeof(this.context.col.grouping.groupPriority) === 'undefined' ||
+ this.context.col.grouping.groupPriority < 0;
+ },
+ action: function () {
+ service.groupColumn( this.context.col.grid, this.context.col );
+ }
+ };
+
+ var ungroupColumn = {
+ name: 'ui.grid.grouping.ungroup',
+ title: i18nService.get().grouping.ungroup,
+ icon: 'ui-grid-icon-indent-left',
+ shown: function () {
+ return typeof(this.context.col.grouping) !== 'undefined' &&
+ typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&
+ this.context.col.grouping.groupPriority >= 0;
+ },
+ action: function () {
+ service.ungroupColumn( this.context.col.grid, this.context.col );
+ }
+ };
+
+ var aggregateRemove = {
+ name: 'ui.grid.grouping.aggregateRemove',
+ title: i18nService.get().grouping.aggregate_remove,
+ shown: function () {
+ return typeof(this.context.col.treeAggregationFn) !== 'undefined';
+ },
+ action: function () {
+ service.aggregateColumn( this.context.col.grid, this.context.col, null);
+ }
+ };
+
+ // generic adder for the aggregation menus, which follow a pattern
+ var addAggregationMenu = function(type, title){
+ title = title || i18nService.get().grouping['aggregate_' + type] || type;
+ var menuItem = {
+ name: 'ui.grid.grouping.aggregate' + type,
+ title: title,
+ shown: function () {
+ return typeof(this.context.col.treeAggregation) === 'undefined' ||
+ typeof(this.context.col.treeAggregation.type) === 'undefined' ||
+ this.context.col.treeAggregation.type !== type;
+ },
+ action: function () {
+ service.aggregateColumn( this.context.col.grid, this.context.col, type);
+ }
+ };
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {
+ col.menuItems.push(menuItem);
+ }
+ };
+
+ /**
+ * @ngdoc object
+ * @name groupingShowGroupingMenu
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Show the grouping (group and ungroup items) menu on this column
+ * <br/>Defaults to true.
+ */
+ if ( col.colDef.groupingShowGroupingMenu !== false ){
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {
+ col.menuItems.push(groupColumn);
+ }
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {
+ col.menuItems.push(ungroupColumn);
+ }
+ }
+
+
+ /**
+ * @ngdoc object
+ * @name groupingShowAggregationMenu
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Show the aggregation menu on this column
+ * <br/>Defaults to true.
+ */
+ if ( col.colDef.groupingShowAggregationMenu !== false ){
+ angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name){
+ addAggregationMenu(name);
+ });
+ angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name){
+ addAggregationMenu(name, aggregationDef.menuTitle);
+ });
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {
+ col.menuItems.push(aggregateRemove);
+ }
+ }
+ },
+
+
+
+
+ /**
+ * @ngdoc function
+ * @name groupingColumnProcessor
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Moves the columns around based on which are grouped
+ *
+ * @param {array} columns the columns to consider rendering
+ * @param {array} rows the grid rows, which we don't use but are passed to us
+ * @returns {array} updated columns array
+ */
+ groupingColumnProcessor: function( columns, rows ) {
+ var grid = this;
+
+ columns = service.moveGroupColumns(this, columns, rows);
+ return columns;
+ },
+
+ /**
+ * @ngdoc function
+ * @name groupedFinalizerFn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Used on group columns to display the rendered value and optionally
+ * display the count of rows.
+ *
+ * @param {aggregation} the aggregation entity for a grouped column
+ */
+ groupedFinalizerFn: function( aggregation ){
+ var col = this;
+
+ if ( typeof(aggregation.groupVal) !== 'undefined') {
+ aggregation.rendered = aggregation.groupVal;
+ if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' && col.colDef.type !== 'object' ){
+ aggregation.rendered += (' (' + aggregation.value + ')');
+ }
+ } else {
+ aggregation.rendered = null;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name moveGroupColumns
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Moves the column order so that the grouped columns are lined up
+ * to the left (well, unless you're RTL, then it's the right). By doing this in
+ * the columnsProcessor, we make it transient - when the column is ungrouped it'll
+ * go back to where it was.
+ *
+ * Does nothing if the option `moveGroupColumns` is set to false.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} columns the columns that we should process/move
+ * @param {array} rows the grid rows
+ * @returns {array} updated columns
+ */
+ moveGroupColumns: function( grid, columns, rows ){
+ if ( grid.options.moveGroupColumns === false){
+ return columns;
+ }
+
+ columns.forEach( function(column, index){
+ // position used to make stable sort in moveGroupColumns
+ column.groupingPosition = index;
+ });
+
+ columns.sort(function(a, b){
+ var a_group, b_group;
+ if (a.isRowHeader){
+ a_group = a.headerPriority;
+ }
+ else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0){
+ a_group = null;
+ } else {
+ a_group = a.grouping.groupPriority;
+ }
+
+ if (b.isRowHeader){
+ b_group = b.headerPriority;
+ }
+ else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0){
+ b_group = null;
+ } else {
+ b_group = b.grouping.groupPriority;
+ }
+
+ // groups get sorted to the top
+ if ( a_group !== null && b_group === null) { return -1; }
+ if ( b_group !== null && a_group === null) { return 1; }
+ if ( a_group !== null && b_group !== null) {return a_group - b_group; }
+
+ return a.groupingPosition - b.groupingPosition;
+ });
+
+ columns.forEach( function(column, index) {
+ delete column.groupingPosition;
+ });
+
+ return columns;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Adds this column to the existing grouping, at the end of the priority order.
+ * If the column doesn't have a sort, adds one, by default ASC
+ *
+ * This column will move to the left of any non-group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to group
+ */
+ groupColumn: function( grid, column){
+ if ( typeof(column.grouping) === 'undefined' ){
+ column.grouping = {};
+ }
+
+ // set the group priority to the next number in the hierarchy
+ var existingGrouping = service.getGrouping( grid );
+ column.grouping.groupPriority = existingGrouping.grouping.length;
+
+ // save sort in order to restore it when column is ungrouped
+ column.previousSort = angular.copy(column.sort);
+
+ // add sort if not present
+ if ( !column.sort ){
+ column.sort = { direction: uiGridConstants.ASC };
+ } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ){
+ column.sort.direction = uiGridConstants.ASC;
+ }
+
+ column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };
+ column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
+ column.treeAggregationFinalizerFn = service.groupedFinalizerFn;
+
+ grid.api.grouping.raise.groupingChanged(column);
+ // This indirectly calls service.tidyPriorities( grid );
+ grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name ungroupColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Removes the groupPriority from this column. If the
+ * column was previously aggregated the aggregation will come back.
+ * The sort will remain.
+ *
+ * This column will move to the right of any other group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to ungroup
+ */
+ ungroupColumn: function( grid, column){
+ if ( typeof(column.grouping) === 'undefined' ){
+ return;
+ }
+
+ delete column.grouping.groupPriority;
+ delete column.treeAggregation;
+ delete column.customTreeAggregationFinalizer;
+
+ if (column.previousSort) {
+ column.sort = column.previousSort;
+ delete column.previousSort;
+ }
+
+ service.tidyPriorities( grid );
+
+ grid.api.grouping.raise.groupingChanged(column);
+ grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
+
+ grid.queueGridRefresh();
+ },
+
+ /**
+ * @ngdoc function
+ * @name aggregateColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Sets the aggregation type on a column, if the
+ * column is currently grouped then it removes the grouping first.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to aggregate
+ * @param {string} one of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions
+ */
+ aggregateColumn: function( grid, column, aggregationType){
+
+ if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ service.ungroupColumn( grid, column );
+ }
+
+ var aggregationDef = {};
+ if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ){
+ aggregationDef = grid.options.treeCustomAggregations[aggregationType];
+ } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ){
+ aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];
+ }
+
+ column.treeAggregation = { type: aggregationType, label: i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };
+ column.treeAggregationFn = aggregationDef.aggregationFn;
+ column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;
+
+ grid.api.grouping.raise.aggregationChanged(column);
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Set the grouping based on a config object, used by the save state feature
+ * (more specifically, by the restore function in that feature )
+ *
+ * @param {Grid} grid grid object
+ * @param {object} config the config we want to set, same format as that returned by getGrouping
+ */
+ setGrouping: function ( grid, config ){
+ if ( typeof(config) === 'undefined' ){
+ return;
+ }
+
+ // first remove any existing grouping
+ service.clearGrouping(grid);
+
+ if ( config.grouping && config.grouping.length && config.grouping.length > 0 ){
+ config.grouping.forEach( function( group ) {
+ var col = grid.getColumn(group.colName);
+
+ if ( col ) {
+ service.groupColumn( grid, col );
+ }
+ });
+ }
+
+ if ( config.aggregations && config.aggregations.length ){
+ config.aggregations.forEach( function( aggregation ) {
+ var col = grid.getColumn(aggregation.colName);
+
+ if ( col ) {
+ service.aggregateColumn( grid, col, aggregation.aggregation.type );
+ }
+ });
+ }
+
+ if ( config.rowExpandedStates ){
+ service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name clearGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
+ * as we don't know whether that sorting was added by grouping or was there beforehand
+ *
+ * @param {Grid} grid grid object
+ */
+ clearGrouping: function( grid ) {
+ var currentGrouping = service.getGrouping(grid);
+
+ if ( currentGrouping.grouping.length > 0 ){
+ currentGrouping.grouping.forEach( function( group ) {
+ if (!group.col){
+ // should have a group.colName if there's no col
+ group.col = grid.getColumn(group.colName);
+ }
+ service.ungroupColumn(grid, group.col);
+ });
+ }
+
+ if ( currentGrouping.aggregations.length > 0 ){
+ currentGrouping.aggregations.forEach( function( aggregation ){
+ if (!aggregation.col){
+ // should have a group.colName if there's no col
+ aggregation.col = grid.getColumn(aggregation.colName);
+ }
+ service.aggregateColumn(grid, aggregation.col, null);
+ });
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name tidyPriorities
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Renumbers groupPriority and sortPriority such that
+ * groupPriority is contiguous, and sortPriority either matches
+ * groupPriority (for group columns), and otherwise is contiguous and
+ * higher than groupPriority.
+ *
+ * @param {Grid} grid grid object
+ */
+ tidyPriorities: function( grid ){
+ // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined
+ if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {
+ grid = this.grid;
+ }
+
+ var groupArray = [];
+ var sortArray = [];
+
+ grid.columns.forEach( function(column, index){
+ if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ groupArray.push(column);
+ } else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0){
+ sortArray.push(column);
+ }
+ });
+
+ groupArray.sort(function(a, b){ return a.grouping.groupPriority - b.grouping.groupPriority; });
+ groupArray.forEach( function(column, index){
+ column.grouping.groupPriority = index;
+ column.suppressRemoveSort = true;
+ if ( typeof(column.sort) === 'undefined'){
+ column.sort = {};
+ }
+ column.sort.priority = index;
+ });
+
+ var i = groupArray.length;
+ sortArray.sort(function(a, b){ return a.sort.priority - b.sort.priority; });
+ sortArray.forEach( function(column, index){
+ column.sort.priority = i;
+ column.suppressRemoveSort = column.colDef.suppressRemoveSort;
+ i++;
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupRows
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description The rowProcessor that creates the groupHeaders (i.e. does
+ * the actual grouping).
+ *
+ * Assumes it is always called after the sorting processor, guaranteed by the priority setting
+ *
+ * Processes all the rows in order, inserting a groupHeader row whenever there is a change
+ * in value of a grouped row, based on the sortAlgorithm used for the column. The group header row
+ * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset
+ * to {} if one is found.
+ *
+ * As it processes it maintains a `processingState` array. This records, for each level of grouping we're
+ * working with, the following information:
+ * ```
+ * {
+ * fieldName: name,
+ * col: col,
+ * initialised: boolean,
+ * currentValue: value,
+ * currentRow: gridRow,
+ * }
+ * ```
+ * We look for changes in the currentValue at any of the levels. Where we find a change we:
+ *
+ * - create a new groupHeader row in the array
+ *
+ * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
+ * @returns {array} the updated rows, including our new group rows
+ */
+ groupRows: function( renderableRows ) {
+ if (renderableRows.length === 0){
+ return renderableRows;
+ }
+
+ var grid = this;
+ grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};
+ grid.grouping.groupingHeaderCache = {};
+
+ var processingState = service.initialiseProcessingState( grid );
+
+ // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader
+ // Broken out as shouldn't create functions in a loop.
+ var updateProcessingState = function( groupFieldState, stateIndex ) {
+ var fieldValue = grid.getCellValue(row, groupFieldState.col);
+
+ // look for change of value - and insert a header
+ if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ){
+ service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );
+ i++;
+ }
+ };
+
+ // use a for loop because it's tolerant of the array length changing whilst we go - we can
+ // manipulate the iterator when we insert groupHeader rows
+ for (var i = 0; i < renderableRows.length; i++ ){
+ var row = renderableRows[i];
+
+ if ( row.visible ){
+ processingState.forEach( updateProcessingState );
+ }
+ }
+
+ delete grid.grouping.oldGroupingHeaderCache;
+ return renderableRows;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name initialiseProcessingState
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Creates the processing state array that is used
+ * for groupRows.
+ *
+ * @param {Grid} grid grid object
+ * @returns {array} an array in the format described in the groupRows method,
+ * initialised with blank values
+ */
+ initialiseProcessingState: function( grid ){
+ var processingState = [];
+ var columnSettings = service.getGrouping( grid );
+
+ columnSettings.grouping.forEach( function( groupItem, index){
+ processingState.push({
+ fieldName: groupItem.field,
+ col: groupItem.col,
+ initialised: false,
+ currentValue: null,
+ currentRow: null
+ });
+ });
+
+ return processingState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Get the grouping settings from the columns. As a side effect
+ * this always renumbers the grouping starting at 0
+ * @param {Grid} grid grid object
+ * @returns {array} an array of the group fields, in order of priority
+ */
+ getGrouping: function( grid ){
+ var groupArray = [];
+ var aggregateArray = [];
+
+ // get all the grouping
+ grid.columns.forEach( function(column, columnIndex){
+ if ( column.grouping ){
+ if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });
+ }
+ }
+ if ( column.treeAggregation && column.treeAggregation.type ){
+ aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });
+ }
+ });
+
+ // sort grouping into priority order
+ groupArray.sort( function(a, b){
+ return a.groupPriority - b.groupPriority;
+ });
+
+ // renumber the priority in case it was somewhat messed up, then remove the grouping reference
+ groupArray.forEach( function( group, index) {
+ group.grouping.groupPriority = index;
+ group.groupPriority = index;
+ delete group.grouping;
+ });
+
+ return { grouping: groupArray, aggregations: aggregateArray };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name insertGroupHeader
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Create a group header row, and link it to the various configuration
+ * items that we use.
+ *
+ * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} renderableRows the rows that we are processing
+ * @param {number} rowIndex the row we were up to processing
+ * @param {array} processingState the current processing state
+ * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -
+ * i.e. the column that we want to create a header for
+ */
+ insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {
+ // set the value that caused the end of a group into the header row and the processing state
+ var fieldName = processingState[stateIndex].fieldName;
+ var col = processingState[stateIndex].col;
+
+ var newValue = grid.getCellValue(renderableRows[rowIndex], col);
+ var newDisplayValue = newValue;
+ if ( typeof(newValue) === 'undefined' || newValue === null ) {
+ newDisplayValue = grid.options.groupingNullLabel;
+ }
+
+ var getKeyAsValueForCacheMap = function(key) {
+ if (angular.isObject(key)) {
+ return JSON.stringify(key);
+ } else {
+ return key;
+ }
+ };
+
+ var cacheItem = grid.grouping.oldGroupingHeaderCache;
+ for ( var i = 0; i < stateIndex; i++ ){
+ if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)] ){
+ cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;
+ }
+ }
+
+ var headerRow;
+ if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(newValue)]){
+ headerRow = cacheItem[getKeyAsValueForCacheMap(newValue)].row;
+ headerRow.entity = {};
+ } else {
+ headerRow = new GridRow( {}, null, grid );
+ gridClassFactory.rowTemplateAssigner.call(grid, headerRow);
+ }
+
+ headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };
+ headerRow.treeLevel = stateIndex;
+ headerRow.groupHeader = true;
+ headerRow.internalRow = true;
+ headerRow.enableCellEdit = false;
+ headerRow.enableSelection = grid.options.enableGroupHeaderSelection;
+ processingState[stateIndex].initialised = true;
+ processingState[stateIndex].currentValue = newValue;
+ processingState[stateIndex].currentRow = headerRow;
+
+ // set all processing states below this one to not be initialised - change of this state
+ // means all those need to start again
+ service.finaliseProcessingState( processingState, stateIndex + 1);
+
+ // insert our new header row
+ renderableRows.splice(rowIndex, 0, headerRow);
+
+ // add our new header row to the cache
+ cacheItem = grid.grouping.groupingHeaderCache;
+ for ( i = 0; i < stateIndex; i++ ){
+ cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;
+ }
+ cacheItem[getKeyAsValueForCacheMap(newValue)] = { row: headerRow, children: {} };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name finaliseProcessingState
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Set all processing states lower than the one that had a break in value to
+ * no longer be initialised. Render the counts into the entity ready for display.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} processingState the current processing state
+ * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all
+ * processing states after this need to be finalised
+ */
+ finaliseProcessingState: function( processingState, stateIndex ){
+ for ( var i = stateIndex; i < processingState.length; i++){
+ processingState[i].initialised = false;
+ processingState[i].currentRow = null;
+ processingState[i].currentValue = null;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getRowExpandedStates
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Extract the groupHeaderCache hash, pulling out only the states.
+ *
+ * The example below shows a grid that is grouped by gender then age
+ *
+ * <pre>
+ * {
+ * male: {
+ * state: 'expanded',
+ * children: {
+ * 22: { state: 'expanded' },
+ * 30: { state: 'collapsed' }
+ * }
+ * },
+ * female: {
+ * state: 'expanded',
+ * children: {
+ * 28: { state: 'expanded' },
+ * 55: { state: 'collapsed' }
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @param {Grid} grid grid object
+ * @returns {hash} the expanded states as a hash
+ */
+ getRowExpandedStates: function(treeChildren){
+ if ( typeof(treeChildren) === 'undefined' ){
+ return {};
+ }
+
+ var newChildren = {};
+
+ angular.forEach( treeChildren, function( value, key ){
+ newChildren[key] = { state: value.row.treeNode.state };
+ if ( value.children ){
+ newChildren[key].children = service.getRowExpandedStates( value.children );
+ } else {
+ newChildren[key].children = {};
+ }
+ });
+
+ return newChildren;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name applyRowExpandedStates
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Take a hash in the format as created by getRowExpandedStates,
+ * and apply it to the grid.grouping.groupHeaderCache.
+ *
+ * Takes a treeSubset, and applies to a treeSubset - so can be called
+ * recursively.
+ *
+ * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of
+ * the children of that hash
+ * @returns {hash} expandedStates can be the full expanded states, or children
+ * of that expanded states (which hopefully matches the subset of the groupHeaderCache)
+ */
+ applyRowExpandedStates: function( currentNode, expandedStates ){
+ if ( typeof(expandedStates) === 'undefined' ){
+ return;
+ }
+
+ angular.forEach(expandedStates, function( value, key ) {
+ if ( currentNode[key] ){
+ currentNode[key].row.treeNode.state = value.state;
+
+ if (value.children && currentNode[key].children){
+ service.applyRowExpandedStates( currentNode[key].children, value.children );
+ }
+ }
+ });
+ }
+
+
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.grouping.directive:uiGridGrouping
+ * @element div
+ * @restrict A
+ *
+ * @description Adds grouping features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+
+ $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-grouping></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService', '$templateCache',
+ function (uiGridGroupingConstants, uiGridGroupingService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if (uiGridCtrl.grid.options.enableGrouping !== false){
+ uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);
+ }
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.importer
+ * @description
+ *
+ * # ui.grid.importer
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to import data into the grid. It
+ * uses the column defs to work out which data belongs in which column,
+ * and creates entities from a configured class (typically a $resource).
+ *
+ * If the rowEdit feature is enabled, it also calls save on those newly
+ * created objects, and then displays any errors in the imported data.
+ *
+ * Currently the importer imports only CSV and json files, although provision has been
+ * made to process other file formats, and these can be added over time.
+ *
+ * For json files, the properties within each object in the json must match the column names
+ * (to put it another way, the importer doesn't process the json, it just copies the objects
+ * within the json into a new instance of the specified object type)
+ *
+ * For CSV import, the default column identification relies on each column in the
+ * header row matching a column.name or column.displayName. Optionally, a column identification
+ * callback can be used. This allows matching using other attributes, which is particularly
+ * useful if your application has internationalised column headings (i.e. the headings that
+ * the user sees don't match the column names).
+ *
+ * The importer makes use of the grid menu as the UI for requesting an
+ * import.
+ *
+ * <div ui-grid-importer></div>
+ */
+
+ var module = angular.module('ui.grid.importer', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.constant:uiGridImporterConstants
+ *
+ * @description constants available in importer module
+ */
+
+ module.constant('uiGridImporterConstants', {
+ featureName: 'importer'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.importer.service:uiGridImporterService
+ *
+ * @description Services for importer feature
+ */
+ module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',
+ function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {
+
+ var service = {
+
+ initializeGrid: function ($scope, grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.importer = {
+ $scope: $scope
+ };
+
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.api:PublicApi
+ *
+ * @description Public Api for importer feature
+ */
+ var publicApi = {
+ events: {
+ importer: {
+ }
+ },
+ methods: {
+ importer: {
+ /**
+ * @ngdoc function
+ * @name importFile
+ * @methodOf ui.grid.importer.api:PublicApi
+ * @description Imports a file into the grid using the file object
+ * provided. Bypasses the grid menu
+ * @param {File} fileObject the file we want to import, as a javascript
+ * File object
+ */
+ importFile: function ( fileObject ) {
+ service.importThisFile( grid, fileObject );
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ if ( grid.options.enableImporter && grid.options.importerShowMenu ){
+ if ( grid.api.core.addToGridMenu ){
+ service.addToMenu( grid );
+ } else {
+ // order of registration is not guaranteed, register in a little while
+ $interval( function() {
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ }
+ }, 100, 1);
+ }
+ }
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.api:GridOptions
+ *
+ * @description GridOptions for importer feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @name enableImporter
+ * @description Whether or not importer is enabled. Automatically set
+ * to false if the user's browser does not support the required fileApi.
+ * Otherwise defaults to true.
+ *
+ */
+ if (gridOptions.enableImporter || gridOptions.enableImporter === undefined) {
+ if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {
+ gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');
+ gridOptions.enableImporter = false;
+ } else {
+ gridOptions.enableImporter = true;
+ }
+ } else {
+ gridOptions.enableImporter = false;
+ }
+
+ /**
+ * @ngdoc method
+ * @name importerProcessHeaders
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that will process headers using custom
+ * logic. Set this callback function if the headers that your user will provide in their
+ * import file don't necessarily match the grid header or field names. This might commonly
+ * occur where your application is internationalised, and therefore the field names
+ * that the user recognises are in a different language than the field names that
+ * ui-grid knows about.
+ *
+ * Defaults to the internal `processHeaders` method, which seeks to match using both
+ * displayName and column.name. Any non-matching columns are discarded.
+ *
+ * Your callback routine should respond by processing the header array, and returning an array
+ * of matching column names. A null value in any given position means "don't import this column"
+ *
+ * <pre>
+ * gridOptions.importerProcessHeaders: function( headerArray ) {
+ * var myHeaderColumns = [];
+ * var thisCol;
+ * headerArray.forEach( function( value, index ) {
+ * thisCol = mySpecialLookupFunction( value );
+ * myHeaderColumns.push( thisCol.name );
+ * });
+ *
+ * return myHeaderCols;
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerArray an array of the text from the first row of the csv file,
+ * which you need to match to column.names
+ * @returns {array} array of matching column names, in the same order as the headerArray
+ *
+ */
+ gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;
+
+ /**
+ * @ngdoc method
+ * @name importerHeaderFilter
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that will filter (usually translate) a single
+ * header. Used when you want to match the passed in column names to the column
+ * displayName after the header filter.
+ *
+ * Your callback routine needs to return the filtered header value.
+ * <pre>
+ * gridOptions.importerHeaderFilter: function( displayName ) {
+ * return $translate.instant( displayName );
+ * })
+ * </pre>
+ *
+ * or:
+ * <pre>
+ * gridOptions.importerHeaderFilter: $translate.instant
+ * </pre>
+ * @param {string} displayName the displayName that we'd like to translate
+ * @returns {string} the translated name
+ *
+ */
+ gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };
+
+ /**
+ * @ngdoc method
+ * @name importerErrorCallback
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that provides custom error handling, rather
+ * than the standard grid behaviour of an alert box and a console message. You
+ * might use this to internationalise the console log messages, or to write to a
+ * custom logging routine that returned errors to the server.
+ *
+ * <pre>
+ * gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {
+ * myUserDisplayRoutine( errorKey );
+ * myLoggingRoutine( consoleMessage, context );
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages
+ * in some way
+ * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,
+ * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray
+ * @param {string} consoleMessage the English console message that importer would have written
+ * @param {object} context the context data that importer would have appended to that console message,
+ * often the file content itself or the element that is in error
+ *
+ */
+ if ( !gridOptions.importerErrorCallback || typeof(gridOptions.importerErrorCallback) !== 'function' ){
+ delete gridOptions.importerErrorCallback;
+ }
+
+ /**
+ * @ngdoc method
+ * @name importerDataAddCallback
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A mandatory callback function that adds data to the source data array. The grid
+ * generally doesn't add rows to the source data array, it is tidier to handle this through a user
+ * callback.
+ *
+ * <pre>
+ * gridOptions.importerDataAddCallback: function( grid, newObjects ) {
+ * $scope.myData = $scope.myData.concat( newObjects );
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into, may be useful in some way
+ * @param {array} newObjects an array of new objects that you should add to your data
+ *
+ */
+ if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {
+ gridUtil.logError("You have not set an importerDataAddCallback, importer is disabled");
+ gridOptions.enableImporter = false;
+ }
+
+ /**
+ * @ngdoc object
+ * @name importerNewObject
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @description An object on which we call `new` to create each new row before inserting it into
+ * the data array. Typically this would be a $resource entity, which means that if you're using
+ * the rowEdit feature, you can directly call save on this entity when the save event is triggered.
+ *
+ * Defaults to a vanilla javascript object
+ *
+ * @example
+ * <pre>
+ * gridOptions.importerNewObject = MyRes;
+ * </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @name importerShowMenu
+ * @description Whether or not to show an item in the grid menu. Defaults to true.
+ *
+ */
+ gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @name importerObjectCallback
+ * @description A callback that massages the data for each object. For example,
+ * you might have data stored as a code value, but display the decode. This callback
+ * can be used to change the decoded value back into a code. Defaults to doing nothing.
+ * @param {Grid} grid in case you need it
+ * @param {object} newObject the new object as importer has created it, modify it
+ * then return the modified version
+ * @returns {object} the modified object
+ * @example
+ * <pre>
+ * gridOptions.importerObjectCallback = function ( grid, newObject ) {
+ * switch newObject.status {
+ * case 'Active':
+ * newObject.status = 1;
+ * break;
+ * case 'Inactive':
+ * newObject.status = 2;
+ * break;
+ * }
+ * return newObject;
+ * };
+ * </pre>
+ */
+ gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToMenu
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Adds import menu item to the grid menu,
+ * allowing the user to request import of a file
+ * @param {Grid} grid the grid into which data should be imported
+ */
+ addToMenu: function ( grid ) {
+ grid.api.core.addToGridMenu( grid, [
+ {
+ title: i18nService.getSafeText('gridMenu.importerTitle'),
+ order: 150
+ },
+ {
+ templateUrl: 'ui-grid/importerMenuItemContainer',
+ action: function ($event) {
+ this.grid.api.importer.importAFile( grid );
+ },
+ order: 151
+ }
+ ]);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name importThisFile
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Imports the provided file into the grid using the file object
+ * provided. Bypasses the grid menu
+ * @param {Grid} grid the grid we're importing into
+ * @param {File} fileObject the file we want to import, as returned from the File
+ * javascript object
+ */
+ importThisFile: function ( grid, fileObject ) {
+ if (!fileObject){
+ gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');
+ return;
+ }
+
+ var reader = new FileReader();
+
+ switch ( fileObject.type ){
+ case 'application/json':
+ reader.onload = service.importJsonClosure( grid );
+ break;
+ default:
+ reader.onload = service.importCsvClosure( grid );
+ break;
+ }
+
+ reader.readAsText( fileObject );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name importJson
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Creates a function that imports a json file into the grid.
+ * The json data is imported into new objects of type `gridOptions.importerNewObject`,
+ * and if the rowEdit feature is enabled the rows are marked as dirty
+ * @param {Grid} grid the grid we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a FileObject
+ */
+ importJsonClosure: function( grid ) {
+ return function( importFile ){
+ var newObjects = [];
+ var newObject;
+
+ var importArray = service.parseJson( grid, importFile );
+ if (importArray === null){
+ return;
+ }
+ importArray.forEach( function( value, index ) {
+ newObject = service.newObject( grid );
+ angular.extend( newObject, value );
+ newObject = grid.options.importerObjectCallback( grid, newObject );
+ newObjects.push( newObject );
+ });
+
+ service.addObjects( grid, newObjects );
+
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name parseJson
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Parses a json file, returns the parsed data.
+ * Displays an error if file doesn't parse
+ * @param {Grid} grid the grid that we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a FileObject
+ * @returns {array} array of objects from the imported json
+ */
+ parseJson: function( grid, importFile ){
+ var loadedObjects;
+ try {
+ loadedObjects = JSON.parse( importFile.target.result );
+ } catch (e) {
+ service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );
+ return;
+ }
+
+ if ( !Array.isArray( loadedObjects ) ){
+ service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );
+ return [];
+ } else {
+ return loadedObjects;
+ }
+ },
+
+
+
+ /**
+ * @ngdoc function
+ * @name importCsvClosure
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Creates a function that imports a csv file into the grid
+ * (allowing it to be used in the reader.onload event)
+ * @param {Grid} grid the grid that we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a file object
+ */
+ importCsvClosure: function( grid ) {
+ return function( importFile ){
+ var importArray = service.parseCsv( importFile );
+ if ( !importArray || importArray.length < 1 ){
+ service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );
+ return;
+ }
+
+ var newObjects = service.createCsvObjects( grid, importArray );
+ if ( !newObjects || newObjects.length === 0 ){
+ service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );
+ return;
+ }
+
+ service.addObjects( grid, newObjects );
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name parseCsv
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Parses a csv file into an array of arrays, with the first
+ * array being the headers, and the remaining arrays being the data.
+ * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,
+ * which is noted as being under the MIT license. The code is modified to pass the jscs yoda condition
+ * checker
+ * @param {FileObject} importFile the file that we want to import, as a
+ * file object
+ */
+ parseCsv: function( importFile ) {
+ var csv = importFile.target.result;
+
+ // use the CSV-JS library to parse
+ return CSV.parse(csv);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createCsvObjects
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Converts an array of arrays (representing the csv file)
+ * into a set of objects. Uses the provided `gridOptions.importerNewObject`
+ * to create the objects, and maps the header row into the individual columns
+ * using either `gridOptions.importerProcessHeaders`, or by using a native method
+ * of matching to either the displayName, column name or column field of
+ * the columns in the column defs. The resulting objects will have attributes
+ * that are named based on the column.field or column.name, in that order.
+ * @param {Grid} grid the grid that we want to import into
+ * @param {Array} importArray the data that we want to import, as an array
+ */
+ createCsvObjects: function( grid, importArray ){
+ // pull off header row and turn into headers
+ var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );
+ if ( !headerMapping || headerMapping.length === 0 ){
+ service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );
+ return [];
+ }
+
+ var newObjects = [];
+ var newObject;
+ importArray.forEach( function( row, index ) {
+ newObject = service.newObject( grid );
+ if ( row !== null ){
+ row.forEach( function( field, index ){
+ if ( headerMapping[index] !== null ){
+ newObject[ headerMapping[index] ] = field;
+ }
+ });
+ }
+ newObject = grid.options.importerObjectCallback( grid, newObject );
+ newObjects.push( newObject );
+ });
+
+ return newObjects;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name processHeaders
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Determines the columns that the header row from
+ * a csv (or other) file represents.
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerRow the header row that we wish to match against
+ * the column definitions
+ * @returns {array} an array of the attribute names that should be used
+ * for that column, based on matching the headers or creating the headers
+ *
+ */
+ processHeaders: function( grid, headerRow ) {
+ var headers = [];
+ if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){
+ // we are going to create new columnDefs for all these columns, so just remove
+ // spaces from the names to create fields
+ headerRow.forEach( function( value, index ) {
+ headers.push( value.replace( /[^0-9a-zA-Z\-_]/g, '_' ) );
+ });
+ return headers;
+ } else {
+ var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );
+ headerRow.forEach( function( value, index ) {
+ if ( lookupHash[value] ) {
+ headers.push( lookupHash[value] );
+ } else if ( lookupHash[ value.toLowerCase() ] ) {
+ headers.push( lookupHash[ value.toLowerCase() ] );
+ } else {
+ headers.push( null );
+ }
+ });
+ return headers;
+ }
+ },
+
+
+ /**
+ * @name flattenColumnDefs
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Runs through the column defs and creates a hash of
+ * the displayName, name and field, and of each of those values forced to lower case,
+ * with each pointing to the field or name
+ * (whichever is present). Used to lookup column headers and decide what
+ * attribute name to give to the resulting field.
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} columnDefs the columnDefs that we should flatten
+ * @returns {hash} the flattened version of the column def information, allowing
+ * us to look up a value by `flattenedHash[ headerValue ]`
+ */
+ flattenColumnDefs: function( grid, columnDefs ){
+ var flattenedHash = {};
+ columnDefs.forEach( function( columnDef, index) {
+ if ( columnDef.name ){
+ flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.field ){
+ flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.displayName ){
+ flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.displayName && grid.options.importerHeaderFilter ){
+ flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;
+ flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+ });
+
+ return flattenedHash;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addObjects
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Inserts our new objects into the grid data, and
+ * sets the rows to dirty if the rowEdit feature is being used
+ *
+ * Does this by registering a watch on dataChanges, which essentially
+ * is waiting on the result of the grid data watch, and downstream processing.
+ *
+ * When the callback is called, it deregisters itself - we don't want to run
+ * again next time data is added.
+ *
+ * If we never get called, we deregister on destroy.
+ *
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} newObjects the objects we want to insert into the grid data
+ * @returns {object} the new object
+ */
+ addObjects: function( grid, newObjects, $scope ){
+ if ( grid.api.rowEdit ){
+ var dataChangeDereg = grid.registerDataChangeCallback( function() {
+ grid.api.rowEdit.setRowsDirty( newObjects );
+ dataChangeDereg();
+ }, [uiGridConstants.dataChange.ROW] );
+
+ grid.importer.$scope.$on( '$destroy', dataChangeDereg );
+ }
+
+ grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name newObject
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Makes a new object based on `gridOptions.importerNewObject`,
+ * or based on an empty object if not present
+ * @param {Grid} grid the grid we're importing into
+ * @returns {object} the new object
+ */
+ newObject: function( grid ){
+ if ( typeof(grid.options) !== "undefined" && typeof(grid.options.importerNewObject) !== "undefined" ){
+ return new grid.options.importerNewObject();
+ } else {
+ return {};
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name alertError
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Provides an internationalised user alert for the failure,
+ * and logs a console message including diagnostic content.
+ * Optionally, if the the `gridOptions.importerErrorCallback` routine
+ * is defined, then calls that instead, allowing user specified error routines
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerRow the header row that we wish to match against
+ * the column definitions
+ */
+ alertError: function( grid, alertI18nToken, consoleMessage, context ){
+ if ( grid.options.importerErrorCallback ){
+ grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );
+ } else {
+ $window.alert(i18nService.getSafeText( alertI18nToken ));
+ gridUtil.logError(consoleMessage + context );
+ }
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.importer.directive:uiGridImporter
+ * @element div
+ * @restrict A
+ *
+ * @description Adds importer features to grid
+ *
+ */
+ module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
+ function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);
+ }
+ };
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.importer.directive:uiGridImporterMenuItem
+ * @element div
+ * @restrict A
+ *
+ * @description Handles the processing from the importer menu item - once a file is
+ * selected
+ *
+ */
+ module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
+ function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ templateUrl: 'ui-grid/importerMenuItem',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var handleFileSelect = function( event ){
+ var target = event.srcElement || event.target;
+
+ if (target && target.files && target.files.length === 1) {
+ var fileObject = target.files[0];
+ uiGridImporterService.importThisFile( grid, fileObject );
+ target.form.reset();
+ }
+ };
+
+ var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');
+ var grid = uiGridCtrl.grid;
+
+ if ( fileChooser.length !== 1 ){
+ gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');
+ } else {
+ fileChooser[0].addEventListener('change', handleFileSelect, false); // TODO: why the false on the end? Google
+ }
+ }
+ };
+ }
+ ]);
+})();
+
+(function() {
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.infiniteScroll
+ *
+ * @description
+ *
+ * #ui.grid.infiniteScroll
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides infinite scroll functionality to ui-grid
+ *
+ */
+ var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);
+ /**
+ * @ngdoc service
+ * @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ *
+ * @description Service for infinite scroll features
+ */
+ module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $timeout, uiGridConstants, ScrollEvent, $q) {
+
+ var service = {
+
+ /**
+ * @ngdoc function
+ * @name initializeGrid
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This method register events and methods into grid public API
+ */
+
+ initializeGrid: function(grid, $scope) {
+ service.defaultGridOptions(grid.options);
+
+ if (!grid.options.enableInfiniteScroll){
+ return;
+ }
+
+ grid.infiniteScroll = { dataLoading: false };
+ service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );
+ grid.api.core.on.scrollEnd($scope, service.handleScroll);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.infiniteScroll.api:PublicAPI
+ *
+ * @description Public API for infinite scroll feature
+ */
+ var publicApi = {
+ events: {
+ infiniteScroll: {
+
+ /**
+ * @ngdoc event
+ * @name needLoadMoreData
+ * @eventOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description This event fires when scroll reaches bottom percentage of grid
+ * and needs to load data
+ */
+
+ needLoadMoreData: function ($scope, fn) {
+ },
+
+ /**
+ * @ngdoc event
+ * @name needLoadMoreDataTop
+ * @eventOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description This event fires when scroll reaches top percentage of grid
+ * and needs to load data
+ */
+
+ needLoadMoreDataTop: function ($scope, fn) {
+ }
+ }
+ },
+ methods: {
+ infiniteScroll: {
+
+ /**
+ * @ngdoc function
+ * @name dataLoaded
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Call this function when you have loaded the additional data
+ * requested. You should set scrollUp and scrollDown to indicate
+ * whether there are still more pages in each direction.
+ *
+ * If you call dataLoaded without first calling `saveScrollPercentage` then we will
+ * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll
+ * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and
+ * on variable speed internet connections. Using `saveScrollPercentage` as demonstrated in the tutorial
+ * should give a smoother scrolling experience for users.
+ *
+ * See infinite_scroll tutorial for example of usage
+ * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire
+ * any more infinite scroll events upward
+ * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't
+ * fire any more infinite scroll events downward
+ * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted. If you're
+ * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning
+ */
+ dataLoaded: function( scrollUp, scrollDown ) {
+ service.setScrollDirections(grid, scrollUp, scrollDown);
+
+ var promise = service.adjustScroll(grid).then(function() {
+ grid.infiniteScroll.dataLoading = false;
+ });
+
+ return promise;
+ },
+
+ /**
+ * @ngdoc function
+ * @name resetScroll
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Call this function when you have taken some action that makes the current
+ * scroll position invalid. For example, if you're using external sorting and you've resorted
+ * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps
+ * you've reused an existing grid for a new data set
+ *
+ * You must tell us whether there is data upwards or downwards after the reset
+ *
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ resetScroll: function( scrollUp, scrollDown ) {
+ service.setScrollDirections( grid, scrollUp, scrollDown);
+
+ service.adjustInfiniteScrollPosition(grid, 0);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveScrollPercentage
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Saves the scroll percentage and number of visible rows before you adjust the data,
+ * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`
+ */
+ saveScrollPercentage: function() {
+ grid.infiniteScroll.prevScrollTop = grid.renderContainers.body.prevScrollTop;
+ grid.infiniteScroll.previousVisibleRows = grid.getVisibleRowCount();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedTop
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the top
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedTop: function( scrollUp, scrollDown ) {
+ service.dataRemovedTop( grid, scrollUp, scrollDown );
+ },
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedBottom
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the bottom
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedBottom: function( scrollUp, scrollDown ) {
+ service.dataRemovedBottom( grid, scrollUp, scrollDown );
+ },
+
+ /**
+ * @ngdoc function
+ * @name setScrollDirections
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
+ * and also sets the grid.suppressParentScroll
+ * @param {boolean} scrollUp whether there are pages available up - defaults to false
+ * @param {boolean} scrollDown whether there are pages available down - defaults to true
+ */
+ setScrollDirections: function ( scrollUp, scrollDown ) {
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+ }
+
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.infiniteScroll.api:GridOptions
+ *
+ * @description GridOptions for infinite scroll feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableInfiniteScroll
+ * @propertyOf ui.grid.infiniteScroll.api:GridOptions
+ * @description Enable infinite scrolling for this grid
+ * <br/>Defaults to true
+ */
+ gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollRowsFromEnd
+ * @propertyOf ui.grid.class:GridOptions
+ * @description This setting controls how close to the end of the dataset a user gets before
+ * more data is requested by the infinite scroll, whether scrolling up or down. This allows you to
+ * 'prefetch' rows before the user actually runs out of scrolling.
+ *
+ * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting
+ * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll
+ * preserve that scroll position
+ *
+ * <br> Defaults to 20
+ */
+ gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollUp
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether you allow infinite scroll up, implying that the first page of data
+ * you have displayed is in the middle of your data set. If set to true then we trigger the
+ * needMoreDataTop event when the user hits the top of the scrollbar.
+ * <br> Defaults to false
+ */
+ gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollDown
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether you allow infinite scroll down, implying that the first page of data
+ * you have displayed is in the middle of your data set. If set to true then we trigger the
+ * needMoreData event when the user hits the bottom of the scrollbar.
+ * <br> Defaults to true
+ */
+ gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setScrollDirections
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
+ * and also sets the grid.suppressParentScroll
+ * @param {grid} grid the grid we're operating on
+ * @param {boolean} scrollUp whether there are pages available up - defaults to false
+ * @param {boolean} scrollDown whether there are pages available down - defaults to true
+ */
+ setScrollDirections: function ( grid, scrollUp, scrollDown ) {
+ grid.infiniteScroll.scrollUp = ( scrollUp === true );
+ grid.suppressParentScrollUp = ( scrollUp === true );
+
+ grid.infiniteScroll.scrollDown = ( scrollDown !== false);
+ grid.suppressParentScrollDown = ( scrollDown !== false);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name handleScroll
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Called whenever the grid scrolls, determines whether the scroll should
+ * trigger an infinite scroll request for more data
+ * @param {object} args the args from the event
+ */
+ handleScroll: function (args) {
+ // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function
+ if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ){
+ return;
+ }
+
+ if (args.y) {
+
+ // If the user is scrolling very quickly all the way to the top/bottom, the scroll handler can get confused
+ // about the direction. First we check if they've gone all the way, and data always is loaded in this case.
+ if (args.y.percentage === 0) {
+ args.grid.scrollDirection = uiGridConstants.scrollDirection.UP;
+ service.loadData(args.grid);
+ } else if (args.y.percentage === 1) {
+ args.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN;
+ service.loadData(args.grid);
+ } else { // Scroll position is somewhere in between top/bottom, so determine whether it's far enough to load more data.
+ var percentage;
+ var targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;
+ if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {
+ percentage = args.y.percentage;
+ if (percentage <= targetPercentage){
+ service.loadData(args.grid);
+ }
+ } else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {
+ percentage = 1 - args.y.percentage;
+ if (percentage <= targetPercentage){
+ service.loadData(args.grid);
+ }
+ }
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name loadData
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
+ * and whether there are more pages upwards or downwards. It also stores the number of rows that we had previously,
+ * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`
+ * @param {Grid} grid the grid we're working on
+ */
+ loadData: function (grid) {
+ // save number of currently visible rows to calculate new scroll position later - we know that we want
+ // to be at approximately the row we're currently at
+ grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;
+ grid.infiniteScroll.direction = grid.scrollDirection;
+ delete grid.infiniteScroll.prevScrollTop;
+
+ if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {
+ grid.infiniteScroll.dataLoading = true;
+ grid.api.infiniteScroll.raise.needLoadMoreDataTop();
+ } else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {
+ grid.infiniteScroll.dataLoading = true;
+ grid.api.infiniteScroll.raise.needLoadMoreData();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustScroll
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Once we are informed that data has been loaded, adjust the scroll position to account for that
+ * addition and to make things look clean.
+ *
+ * If we're scrolling up we scroll to the first row of the old data set -
+ * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by
+ * the time the data comes back. If we're scrolling down we scoll to the last row of the old data set - so we're
+ * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time
+ * the data comes back.
+ *
+ * Neither of these are good assumptions, but making this a smoother experience really requires
+ * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end). Even then
+ * it'd be better still to actually run into the end. But if the data takes a while to come back, they may have scrolled
+ * somewhere else in the mean-time, in which case they'll get a jump back to the new data. Anyway, this will do for
+ * now, until someone wants to do better.
+ * @param {Grid} grid the grid we're working on
+ * @returns {promise} a promise that is resolved when scrolling has finished
+ */
+ adjustScroll: function(grid){
+ var promise = $q.defer();
+ $timeout(function () {
+ var newPercentage, viewportHeight, rowHeight, newVisibleRows, oldTop, newTop;
+
+ viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight;
+ rowHeight = grid.options.rowHeight;
+
+ if ( grid.infiniteScroll.direction === undefined ){
+ // called from initialize, tweak our scroll up a little
+ service.adjustInfiniteScrollPosition(grid, 0);
+ }
+
+ newVisibleRows = grid.getVisibleRowCount();
+
+ // in case not enough data is loaded to enable scroller - load more data
+ var canvasHeight = rowHeight * newVisibleRows;
+ if (grid.infiniteScroll.scrollDown && (viewportHeight > canvasHeight)) {
+ grid.api.infiniteScroll.raise.needLoadMoreData();
+ }
+
+ if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ){
+ oldTop = grid.infiniteScroll.prevScrollTop || 0;
+ newTop = oldTop + (newVisibleRows - grid.infiniteScroll.previousVisibleRows)*rowHeight;
+ service.adjustInfiniteScrollPosition(grid, newTop);
+ $timeout( function() {
+ promise.resolve();
+ });
+ }
+
+ if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ){
+ newTop = grid.infiniteScroll.prevScrollTop || (grid.infiniteScroll.previousVisibleRows*rowHeight - viewportHeight);
+ service.adjustInfiniteScrollPosition(grid, newTop);
+ $timeout( function() {
+ promise.resolve();
+ });
+ }
+ }, 0);
+
+ return promise.promise;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustInfiniteScrollPosition
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
+ * @param {Grid} grid the grid we're working on
+ * @param {number} scrollTop the position through the grid that we want to scroll to
+ */
+ adjustInfiniteScrollPosition: function (grid, scrollTop) {
+ var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition'),
+ visibleRows = grid.getVisibleRowCount(),
+ viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight,
+ rowHeight = grid.options.rowHeight,
+ scrollHeight = visibleRows*rowHeight-viewportHeight;
+
+ //for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active
+ if (scrollTop === 0 && grid.infiniteScroll.scrollUp) {
+ // using pixels results in a relative scroll, hence we have to use percentage
+ scrollEvent.y = {percentage: 1/scrollHeight};
+ }
+ else {
+ scrollEvent.y = {percentage: scrollTop/scrollHeight};
+ }
+ grid.scrollContainers('', scrollEvent);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedTop
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the top. You should
+ * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
+ * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
+ * before you start removing data
+ * @param {Grid} grid the grid we're working on
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedTop: function( grid, scrollUp, scrollDown ) {
+ var newVisibleRows, oldTop, newTop, rowHeight;
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+
+ newVisibleRows = grid.renderContainers.body.visibleRowCache.length;
+ oldTop = grid.infiniteScroll.prevScrollTop;
+ rowHeight = grid.options.rowHeight;
+
+ // since we removed from the top, our new scroll row will be the old scroll row less the number
+ // of rows removed
+ newTop = oldTop - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows )*rowHeight;
+
+ service.adjustInfiniteScrollPosition( grid, newTop );
+ },
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedBottom
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the bottom. You should
+ * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
+ * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
+ * before you start removing data
+ * @param {Grid} grid the grid we're working on
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedBottom: function( grid, scrollUp, scrollDown ) {
+ var newTop;
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+
+ newTop = grid.infiniteScroll.prevScrollTop;
+
+ service.adjustInfiniteScrollPosition( grid, newTop );
+ }
+ };
+ return service;
+ }]);
+ /**
+ * @ngdoc directive
+ * @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll
+ * @element div
+ * @restrict A
+ *
+ * @description Adds infinite scroll features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Alex', car: 'Toyota' },
+ { name: 'Sam', car: 'Lexus' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'car'}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-infinite-scroll="20"></div>
+ </div>
+ </file>
+ </example>
+ */
+
+ module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',
+ function (uiGridInfiniteScrollService) {
+ return {
+ priority: -200,
+ scope: false,
+ require: '^uiGrid',
+ compile: function($scope, $elm, $attr){
+ return {
+ pre: function($scope, $elm, $attr, uiGridCtrl) {
+ uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);
+ },
+ post: function($scope, $elm, $attr) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.moveColumns
+ * @description
+ *
+ * # ui.grid.moveColumns
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides column moving capability to ui.grid. It enables to change the position of columns.
+ * <div doc-module-components="ui.grid.moveColumns"></div>
+ */
+ var module = angular.module('ui.grid.moveColumns', ['ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.moveColumns.service:uiGridMoveColumnService
+ * @description Service for column moving feature.
+ */
+ module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $timeout, $log, ScrollEvent, uiGridConstants, gridUtil) {
+
+ var service = {
+ initializeGrid: function (grid) {
+ var self = this;
+ this.registerPublicApi(grid);
+ this.defaultGridOptions(grid.options);
+ grid.moveColumns = {orderCache: []}; // Used to cache the order before columns are rebuilt
+ grid.registerColumnBuilder(self.movableColumnBuilder);
+ grid.registerDataChangeCallback(self.verifyColumnOrder, [uiGridConstants.dataChange.COLUMN]);
+ },
+ registerPublicApi: function (grid) {
+ var self = this;
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:PublicApi
+ * @description Public Api for column moving feature.
+ */
+ var publicApi = {
+ events: {
+ /**
+ * @ngdoc event
+ * @name columnPositionChanged
+ * @eventOf ui.grid.moveColumns.api:PublicApi
+ * @description raised when column is moved
+ * <pre>
+ * gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})
+ * </pre>
+ * @param {object} colDef the column that was moved
+ * @param {integer} originalPosition of the column
+ * @param {integer} finalPosition of the column
+ */
+ colMovable: {
+ columnPositionChanged: function (colDef, originalPosition, newPosition) {
+ }
+ }
+ },
+ methods: {
+ /**
+ * @ngdoc method
+ * @name moveColumn
+ * @methodOf ui.grid.moveColumns.api:PublicApi
+ * @description Method can be used to change column position.
+ * <pre>
+ * gridApi.colMovable.moveColumn(oldPosition, newPosition)
+ * </pre>
+ * @param {integer} originalPosition of the column
+ * @param {integer} finalPosition of the column
+ */
+ colMovable: {
+ moveColumn: function (originalPosition, finalPosition) {
+ var columns = grid.columns;
+ if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {
+ gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');
+ return;
+ }
+ var nonMovableColumns = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {
+ nonMovableColumns++;
+ }
+ }
+ if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {
+ gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');
+ return;
+ }
+ var findPositionForRenderIndex = function (index) {
+ var position = index;
+ for (var i = 0; i <= position; i++) {
+ if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
+ position++;
+ }
+ }
+ return position;
+ };
+ self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:GridOptions
+ *
+ * @description Options for configuring the move column feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name enableColumnMoving
+ * @propertyOf ui.grid.moveColumns.api:GridOptions
+ * @description If defined, sets the default value for the colMovable flag on each individual colDefs
+ * if their individual enableColumnMoving configuration is not defined. Defaults to true.
+ */
+ gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;
+ },
+ movableColumnBuilder: function (colDef, col, gridOptions) {
+ var promises = [];
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:ColumnDef
+ *
+ * @description Column Definition for move column feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+ /**
+ * @ngdoc object
+ * @name enableColumnMoving
+ * @propertyOf ui.grid.moveColumns.api:ColumnDef
+ * @description Enable column moving for the column.
+ */
+ colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving
+ : colDef.enableColumnMoving;
+ return $q.all(promises);
+ },
+ /**
+ * @ngdoc method
+ * @name updateColumnCache
+ * @methodOf ui.grid.moveColumns
+ * @description Cache the current order of columns, so we can restore them after new columnDefs are defined
+ */
+ updateColumnCache: function(grid){
+ grid.moveColumns.orderCache = grid.getOnlyDataColumns();
+ },
+ /**
+ * @ngdoc method
+ * @name verifyColumnOrder
+ * @methodOf ui.grid.moveColumns
+ * @description dataChangeCallback which uses the cached column order to restore the column order
+ * when it is reset by altering the columnDefs array.
+ */
+ verifyColumnOrder: function(grid){
+ var headerRowOffset = grid.rowHeaderColumns.length;
+ var newIndex;
+
+ angular.forEach(grid.moveColumns.orderCache, function(cacheCol, cacheIndex){
+ newIndex = grid.columns.indexOf(cacheCol);
+ if ( newIndex !== -1 && newIndex - headerRowOffset !== cacheIndex ){
+ var column = grid.columns.splice(newIndex, 1)[0];
+ grid.columns.splice(cacheIndex + headerRowOffset, 0, column);
+ }
+ });
+ },
+ redrawColumnAtPosition: function (grid, originalPosition, newPosition) {
+ var columns = grid.columns;
+
+ if (originalPosition === newPosition) {
+ return;
+ }
+
+ //check columns in between move-range to make sure they are visible columns
+ var pos = (originalPosition < newPosition) ? originalPosition + 1 : originalPosition - 1;
+ var i0 = Math.min(pos, newPosition);
+ for (i0; i0 <= Math.max(pos, newPosition); i0++) {
+ if (columns[i0].visible) {
+ break;
+ }
+ }
+ if (i0 > Math.max(pos, newPosition)) {
+ //no visible column found, column did not visibly move
+ return;
+ }
+
+ var originalColumn = columns[originalPosition];
+ if (originalColumn.colDef.enableColumnMoving) {
+ if (originalPosition > newPosition) {
+ for (var i1 = originalPosition; i1 > newPosition; i1--) {
+ columns[i1] = columns[i1 - 1];
+ }
+ }
+ else if (newPosition > originalPosition) {
+ for (var i2 = originalPosition; i2 < newPosition; i2++) {
+ columns[i2] = columns[i2 + 1];
+ }
+ }
+ columns[newPosition] = originalColumn;
+ service.updateColumnCache(grid);
+ grid.queueGridRefresh();
+ $timeout(function () {
+ grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);
+ });
+ }
+ }
+ };
+ return service;
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.moveColumns.directive:uiGridMoveColumns
+ * @element div
+ * @restrict A
+ * @description Adds column moving features to the ui-grid directive.
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO', age: 45 },
+ { name: 'Frank', title: 'Lowly Developer', age: 25 },
+ { name: 'Jenny', title: 'Highly Developer', age: 35 }
+ ];
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'title'},
+ {name: 'age'}
+ ];
+ }]);
+ </file>
+ <file name="main.css">
+ .grid {
+ width: 100%;
+ height: 150px;
+ }
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div class="grid" ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-move-columns></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.moveColumns.directive:uiGridHeaderCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.
+ *
+ * On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.
+ * In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).
+ * On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.
+ *
+ * Events that invoke cloning of header cell:
+ * - mousedown
+ *
+ * Events that invoke movement of cloned header cell:
+ * - mousemove
+ *
+ * Events that invoke repositioning of column:
+ * - mouseup
+ */
+ module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',
+ function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {
+ return {
+ priority: -10,
+ require: '^uiGrid',
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ if ($scope.col.colDef.enableColumnMoving) {
+
+ /*
+ * Our general approach to column move is that we listen to a touchstart or mousedown
+ * event over the column header. When we hear one, then we wait for a move of the same type
+ * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for
+ * a mousemove (i.e. a drag) before we decide that there's a move underway. If there's never a move,
+ * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.
+ *
+ */
+ var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
+
+ var gridLeft;
+ var previousMouseX;
+ var totalMouseMovement;
+ var rightMoveLimit;
+ var elmCloned = false;
+ var movingElm;
+ var reducedWidth;
+ var moveOccurred = false;
+
+ var downFn = function( event ){
+ //Setting some variables required for calculations.
+ gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
+ if ( $scope.grid.hasLeftContainer() ){
+ gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;
+ }
+
+ previousMouseX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);
+ totalMouseMovement = 0;
+ rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();
+
+ if ( event.type === 'mousedown' ){
+ $document.on('mousemove', moveFn);
+ $document.on('mouseup', upFn);
+ } else if ( event.type === 'touchstart' ){
+ $document.on('touchmove', moveFn);
+ $document.on('touchend', upFn);
+ }
+ };
+
+ var moveFn = function( event ) {
+ var pageX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);
+ var changeValue = pageX - previousMouseX;
+ if ( changeValue === 0 ){ return; }
+ //Disable text selection in Chrome during column move
+ document.onselectstart = function() { return false; };
+
+ moveOccurred = true;
+
+ if (!elmCloned) {
+ cloneElement();
+ }
+ else if (elmCloned) {
+ moveElement(changeValue);
+ previousMouseX = pageX;
+ }
+ };
+
+ var upFn = function( event ){
+ //Re-enable text selection after column move
+ document.onselectstart = null;
+
+ //Remove the cloned element on mouse up.
+ if (movingElm) {
+ movingElm.remove();
+ elmCloned = false;
+ }
+
+ offAllEvents();
+ onDownEvents();
+
+ if (!moveOccurred){
+ return;
+ }
+
+ var columns = $scope.grid.columns;
+ var columnIndex = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if (columns[i].colDef.name !== $scope.col.colDef.name) {
+ columnIndex++;
+ }
+ else {
+ break;
+ }
+ }
+
+ var targetIndex;
+
+ //Case where column should be moved to a position on its left
+ if (totalMouseMovement < 0) {
+ var totalColumnsLeftWidth = 0;
+ var il;
+ if ( $scope.grid.isRTL() ){
+ for (il = columnIndex + 1; il < columns.length; il++) {
+ if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
+ totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
+ if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, il - 1);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ for (il = columnIndex - 1; il >= 0; il--) {
+ if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
+ totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
+ if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, il + 1);
+ break;
+ }
+ }
+ }
+ }
+
+ //Case where column should be moved to beginning (or end in RTL) of the grid.
+ if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {
+ targetIndex = 0;
+ if ( $scope.grid.isRTL() ){
+ targetIndex = columns.length - 1;
+ }
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, targetIndex);
+ }
+ }
+
+ //Case where column should be moved to a position on its right
+ else if (totalMouseMovement > 0) {
+ var totalColumnsRightWidth = 0;
+ var ir;
+ if ( $scope.grid.isRTL() ){
+ for (ir = columnIndex - 1; ir > 0; ir--) {
+ if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
+ totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
+ if (totalColumnsRightWidth > totalMouseMovement) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, ir);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ for (ir = columnIndex + 1; ir < columns.length; ir++) {
+ if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
+ totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
+ if (totalColumnsRightWidth > totalMouseMovement) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, ir - 1);
+ break;
+ }
+ }
+ }
+ }
+
+
+ //Case where column should be moved to end (or beginning in RTL) of the grid.
+ if (totalColumnsRightWidth < totalMouseMovement) {
+ targetIndex = columns.length - 1;
+ if ( $scope.grid.isRTL() ){
+ targetIndex = 0;
+ }
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, targetIndex);
+ }
+ }
+
+
+
+ };
+
+ var onDownEvents = function(){
+ $contentsElm.on('touchstart', downFn);
+ $contentsElm.on('mousedown', downFn);
+ };
+
+ var offAllEvents = function() {
+ $contentsElm.off('touchstart', downFn);
+ $contentsElm.off('mousedown', downFn);
+
+ $document.off('mousemove', moveFn);
+ $document.off('touchmove', moveFn);
+
+ $document.off('mouseup', upFn);
+ $document.off('touchend', upFn);
+ };
+
+ onDownEvents();
+
+
+ var cloneElement = function () {
+ elmCloned = true;
+
+ //Cloning header cell and appending to current header cell.
+ movingElm = $elm.clone();
+ $elm.parent().append(movingElm);
+
+ //Left of cloned element should be aligned to original header cell.
+ movingElm.addClass('movingColumn');
+ var movingElementStyles = {};
+ movingElementStyles.left = $elm[0].offsetLeft + 'px';
+ var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
+ var elmRight = $elm[0].getBoundingClientRect().right;
+ if (elmRight > gridRight) {
+ reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
+ movingElementStyles.width = reducedWidth + 'px';
+ }
+ movingElm.css(movingElementStyles);
+ };
+
+ var moveElement = function (changeValue) {
+ //Calculate total column width
+ var columns = $scope.grid.columns;
+ var totalColumnWidth = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {
+ totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;
+ }
+ }
+
+ //Calculate new position of left of column
+ var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
+ var currentElmRight = movingElm[0].getBoundingClientRect().right;
+ var newElementLeft;
+
+ newElementLeft = currentElmLeft - gridLeft + changeValue;
+ newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;
+
+ //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
+ if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
+ movingElm.css({visibility: 'visible', 'left': (movingElm[0].offsetLeft +
+ (newElementLeft < rightMoveLimit ? changeValue : (rightMoveLimit - currentElmLeft))) + 'px'});
+ }
+ else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {
+ changeValue *= 8;
+ var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');
+ scrollEvent.x = {pixels: changeValue};
+ scrollEvent.grid.scrollContainers('',scrollEvent);
+ }
+
+ //Calculate total width of columns on the left of the moving column and the mouse movement
+ var totalColumnsLeftWidth = 0;
+ for (var il = 0; il < columns.length; il++) {
+ if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
+ if (columns[il].colDef.name !== $scope.col.colDef.name) {
+ totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if ($scope.newScrollLeft === undefined) {
+ totalMouseMovement += changeValue;
+ }
+ else {
+ totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;
+ }
+
+ //Increase width of moving column, in case the rightmost column was moved and its width was
+ //decreased because of overflow
+ if (reducedWidth < $scope.col.drawnWidth) {
+ reducedWidth += Math.abs(changeValue);
+ movingElm.css({'width': reducedWidth + 'px'});
+ }
+ };
+
+ $scope.$on('$destroy', offAllEvents);
+ }
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.pagination
+ *
+ * @description
+ *
+ * # ui.grid.pagination
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides pagination support to ui-grid
+ */
+ var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.pagination.service:uiGridPaginationService
+ *
+ * @description Service for the pagination feature
+ */
+ module.service('uiGridPaginationService', ['gridUtil',
+ function (gridUtil) {
+ var service = {
+ /**
+ * @ngdoc method
+ * @name initializeGrid
+ * @methodOf ui.grid.pagination.service:uiGridPaginationService
+ * @description Attaches the service to a certain grid
+ * @param {Grid} grid The grid we want to work with
+ */
+ initializeGrid: function (grid) {
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pagination.api:PublicAPI
+ *
+ * @description Public API for the pagination feature
+ */
+ var publicApi = {
+ events: {
+ pagination: {
+ /**
+ * @ngdoc event
+ * @name paginationChanged
+ * @eventOf ui.grid.pagination.api:PublicAPI
+ * @description This event fires when the pageSize or currentPage changes
+ * @param {int} currentPage requested page number
+ * @param {int} pageSize requested page size
+ */
+ paginationChanged: function (currentPage, pageSize) { }
+ }
+ },
+ methods: {
+ pagination: {
+ /**
+ * @ngdoc method
+ * @name getPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the number of the current page
+ */
+ getPage: function () {
+ return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;
+ },
+ /**
+ * @ngdoc method
+ * @name getFirstRowIndex
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the index of the first row of the current page.
+ */
+ getFirstRowIndex: function () {
+ if (grid.options.useCustomPagination) {
+ return grid.options.paginationPageSizes.reduce(function(result, size, index) {
+ return index < grid.options.paginationCurrentPage - 1 ? result + size : result;
+ }, 0);
+ }
+ return ((grid.options.paginationCurrentPage - 1) * grid.options.paginationPageSize);
+ },
+ /**
+ * @ngdoc method
+ * @name getLastRowIndex
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the index of the last row of the current page.
+ */
+ getLastRowIndex: function () {
+ if (grid.options.useCustomPagination) {
+ return publicApi.methods.pagination.getFirstRowIndex() + grid.options.paginationPageSizes[grid.options.paginationCurrentPage - 1];
+ }
+ return Math.min(grid.options.paginationCurrentPage * grid.options.paginationPageSize, grid.options.totalItems);
+ },
+ /**
+ * @ngdoc method
+ * @name getTotalPages
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the total number of pages
+ */
+ getTotalPages: function () {
+ if (!grid.options.enablePagination) {
+ return null;
+ }
+
+ if (grid.options.useCustomPagination) {
+ return grid.options.paginationPageSizes.length;
+ }
+
+ return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);
+ },
+ /**
+ * @ngdoc method
+ * @name nextPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the next page, if possible
+ */
+ nextPage: function () {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+
+ if (grid.options.totalItems > 0) {
+ grid.options.paginationCurrentPage = Math.min(
+ grid.options.paginationCurrentPage + 1,
+ publicApi.methods.pagination.getTotalPages()
+ );
+ } else {
+ grid.options.paginationCurrentPage++;
+ }
+ },
+ /**
+ * @ngdoc method
+ * @name previousPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the previous page, if we're not on the first page
+ */
+ previousPage: function () {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+
+ grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);
+ },
+ /**
+ * @ngdoc method
+ * @name seek
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the requested page
+ * @param {int} page The number of the page that should be displayed
+ */
+ seek: function (page) {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+ if (!angular.isNumber(page) || page < 1) {
+ throw 'Invalid page number: ' + page;
+ }
+
+ grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ var processPagination = function( renderableRows ){
+ if (grid.options.useExternalPagination || !grid.options.enablePagination) {
+ return renderableRows;
+ }
+ //client side pagination
+ var pageSize = parseInt(grid.options.paginationPageSize, 10);
+ var currentPage = parseInt(grid.options.paginationCurrentPage, 10);
+
+ var visibleRows = renderableRows.filter(function (row) { return row.visible; });
+ grid.options.totalItems = visibleRows.length;
+
+ var firstRow = publicApi.methods.pagination.getFirstRowIndex();
+ var lastRow = publicApi.methods.pagination.getLastRowIndex();
+
+ if (firstRow > visibleRows.length) {
+ currentPage = grid.options.paginationCurrentPage = 1;
+ firstRow = (currentPage - 1) * pageSize;
+ }
+ return visibleRows.slice(firstRow, lastRow);
+ };
+
+ grid.registerRowsProcessor(processPagination, 900 );
+
+ },
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.pagination.api:GridOptions
+ *
+ * @description GridOptions for the pagination feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc property
+ * @name enablePagination
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Enables pagination. Defaults to true.
+ */
+ gridOptions.enablePagination = gridOptions.enablePagination !== false;
+ /**
+ * @ngdoc property
+ * @name enablePaginationControls
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Enables the paginator at the bottom of the grid. Turn this off if you want to implement your
+ * own controls outside the grid.
+ */
+ gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;
+ /**
+ * @ngdoc property
+ * @name useExternalPagination
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Disables client side pagination. When true, handle the paginationChanged event and set data
+ * and totalItems. Defaults to `false`
+ */
+ gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;
+
+ /**
+ * @ngdoc property
+ * @name useCustomPagination
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Disables client-side pagination. When true, handle the `paginationChanged` event and set `data`,
+ * `firstRowIndex`, `lastRowIndex`, and `totalItems`. Defaults to `false`.
+ */
+ gridOptions.useCustomPagination = gridOptions.useCustomPagination === true;
+
+ /**
+ * @ngdoc property
+ * @name totalItems
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Total number of items, set automatically when using client side pagination, but needs set by user
+ * for server side pagination
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {
+ gridOptions.totalItems = 0;
+ }
+ /**
+ * @ngdoc property
+ * @name paginationPageSizes
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Array of page sizes, defaults to `[250, 500, 1000]`
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {
+ gridOptions.paginationPageSizes = [250, 500, 1000];
+ }
+ /**
+ * @ngdoc property
+ * @name paginationPageSize
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {
+ if (gridOptions.paginationPageSizes.length > 0) {
+ gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];
+ } else {
+ gridOptions.paginationPageSize = 0;
+ }
+ }
+ /**
+ * @ngdoc property
+ * @name paginationCurrentPage
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Current page number, defaults to 1
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {
+ gridOptions.paginationCurrentPage = 1;
+ }
+
+ /**
+ * @ngdoc property
+ * @name paginationTemplate
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description A custom template for the pager, defaults to `ui-grid/pagination`
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {
+ gridOptions.paginationTemplate = 'ui-grid/pagination';
+ }
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.pagination.service:uiGridPaginationService
+ * @name uiGridPaginationService
+ * @description Raises paginationChanged and calls refresh for client side pagination
+ * @param {Grid} grid the grid for which the pagination changed
+ * @param {int} currentPage requested page number
+ * @param {int} pageSize requested page size
+ */
+ onPaginationChanged: function (grid, currentPage, pageSize) {
+ grid.api.pagination.raise.paginationChanged(currentPage, pageSize);
+ if (!grid.options.useExternalPagination) {
+ grid.queueGridRefresh(); //client side pagination
+ }
+ }
+ };
+
+ return service;
+ }
+ ]);
+ /**
+ * @ngdoc directive
+ * @name ui.grid.pagination.directive:uiGridPagination
+ * @element div
+ * @restrict A
+ *
+ * @description Adds pagination features to grid
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Alex', car: 'Toyota' },
+ { name: 'Sam', car: 'Lexus' },
+ { name: 'Joe', car: 'Dodge' },
+ { name: 'Bob', car: 'Buick' },
+ { name: 'Cindy', car: 'Ford' },
+ { name: 'Brian', car: 'Audi' },
+ { name: 'Malcom', car: 'Mercedes Benz' },
+ { name: 'Dave', car: 'Ford' },
+ { name: 'Stacey', car: 'Audi' },
+ { name: 'Amy', car: 'Acura' },
+ { name: 'Scott', car: 'Toyota' },
+ { name: 'Ryan', car: 'BMW' },
+ ];
+
+ $scope.gridOptions = {
+ data: 'data',
+ paginationPageSizes: [5, 10, 25],
+ paginationPageSize: 5,
+ columnDefs: [
+ {name: 'name'},
+ {name: 'car'}
+ ]
+ }
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-pagination></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',
+ function (gridUtil, uiGridPaginationService) {
+ return {
+ priority: -200,
+ scope: false,
+ require: 'uiGrid',
+ link: {
+ pre: function ($scope, $elm, $attr, uiGridCtrl) {
+ uiGridPaginationService.initializeGrid(uiGridCtrl.grid);
+
+ gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+ $elm.append(template);
+ uiGridCtrl.innerCompile(template);
+ });
+ }
+ }
+ };
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.pagination.directive:uiGridPager
+ * @element div
+ *
+ * @description Panel for handling pagination
+ */
+ module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',
+ function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {
+ return {
+ priority: -200,
+ scope: true,
+ require: '^uiGrid',
+ link: function ($scope, $elm, $attr, uiGridCtrl) {
+ var defaultFocusElementSelector = '.ui-grid-pager-control-input';
+ $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels
+
+ $scope.paginationApi = uiGridCtrl.grid.api.pagination;
+ $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');
+ $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');
+ $scope.paginationOf = i18nService.getSafeText('pagination.of');
+ $scope.paginationThrough = i18nService.getSafeText('pagination.through');
+
+ var options = uiGridCtrl.grid.options;
+
+ uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
+ adjustment.height = adjustment.height - gridUtil.elementHeight($elm, "padding");
+ return adjustment;
+ });
+
+ var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
+ if (!grid.options.useExternalPagination) {
+ grid.options.totalItems = grid.rows.length;
+ }
+ }, [uiGridConstants.dataChange.ROW]);
+
+ $scope.$on('$destroy', dataChangeDereg);
+
+ var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {
+ if (newValues === oldValues || oldValues === undefined) {
+ return;
+ }
+
+ if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {
+ options.paginationCurrentPage = 1;
+ return;
+ }
+
+ if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {
+ options.paginationCurrentPage = $scope.paginationApi.getTotalPages();
+ return;
+ }
+
+ uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);
+ }
+ );
+
+ $scope.$on('$destroy', function() {
+ deregP();
+ });
+
+ $scope.cantPageForward = function () {
+ if ($scope.paginationApi.getTotalPages()) {
+ return $scope.cantPageToLast();
+ } else {
+ return options.data.length < 1;
+ }
+ };
+
+ $scope.cantPageToLast = function () {
+ var totalPages = $scope.paginationApi.getTotalPages();
+ return !totalPages || options.paginationCurrentPage >= totalPages;
+ };
+
+ $scope.cantPageBackward = function () {
+ return options.paginationCurrentPage <= 1;
+ };
+
+ var focusToInputIf = function(condition){
+ if (condition){
+ gridUtil.focus.bySelector($elm, defaultFocusElementSelector);
+ }
+ };
+
+ //Takes care of setting focus to the middle element when focus is lost
+ $scope.pageFirstPageClick = function () {
+ $scope.paginationApi.seek(1);
+ focusToInputIf($scope.cantPageBackward());
+ };
+
+ $scope.pagePreviousPageClick = function () {
+ $scope.paginationApi.previousPage();
+ focusToInputIf($scope.cantPageBackward());
+ };
+
+ $scope.pageNextPageClick = function () {
+ $scope.paginationApi.nextPage();
+ focusToInputIf($scope.cantPageForward());
+ };
+
+ $scope.pageLastPageClick = function () {
+ $scope.paginationApi.seek($scope.paginationApi.getTotalPages());
+ focusToInputIf($scope.cantPageToLast());
+ };
+
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.pinning
+ * @description
+ *
+ * # ui.grid.pinning
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides column pinning to the end user via menu options in the column header
+ *
+ * <div doc-module-components="ui.grid.pinning"></div>
+ */
+
+ var module = angular.module('ui.grid.pinning', ['ui.grid']);
+
+ module.constant('uiGridPinningConstants', {
+ container: {
+ LEFT: 'left',
+ RIGHT: 'right',
+ NONE: ''
+ }
+ });
+
+ module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {
+ var service = {
+
+ initializeGrid: function (grid) {
+ service.defaultGridOptions(grid.options);
+
+ // Register a column builder to add new menu items for pinning left and right
+ grid.registerColumnBuilder(service.pinningColumnBuilder);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:PublicApi
+ *
+ * @description Public Api for pinning feature
+ */
+ var publicApi = {
+ events: {
+ pinning: {
+ /**
+ * @ngdoc event
+ * @name columnPin
+ * @eventOf ui.grid.pinning.api:PublicApi
+ * @description raised when column pin state has changed
+ * <pre>
+ * gridApi.pinning.on.columnPinned(scope, function(colDef){})
+ * </pre>
+ * @param {object} colDef the column that was changed
+ * @param {string} container the render container the column is in ('left', 'right', '')
+ */
+ columnPinned: function(colDef, container) {
+ }
+ }
+ },
+ methods: {
+ pinning: {
+ /**
+ * @ngdoc function
+ * @name pinColumn
+ * @methodOf ui.grid.pinning.api:PublicApi
+ * @description pin column left, right, or none
+ * <pre>
+ * gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)
+ * </pre>
+ * @param {gridColumn} col the column being pinned
+ * @param {string} container one of the recognised types
+ * from uiGridPinningConstants
+ */
+ pinColumn: function(col, container) {
+ service.pinColumn(grid, col, container);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:GridOptions
+ *
+ * @description GridOptions for pinning feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enablePinning
+ * @propertyOf ui.grid.pinning.api:GridOptions
+ * @description Enable pinning for the entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enablePinning = gridOptions.enablePinning !== false;
+
+ },
+
+ pinningColumnBuilder: function (colDef, col, gridOptions) {
+ //default to true unless gridOptions or colDef is explicitly false
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:ColumnDef
+ *
+ * @description ColumnDef for pinning feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enablePinning
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Enable pinning for the individual column.
+ * <br/>Defaults to true
+ */
+ colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;
+
+
+ /**
+ * @ngdoc object
+ * @name pinnedLeft
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Column is pinned left when grid is rendered
+ * <br/>Defaults to false
+ */
+
+ /**
+ * @ngdoc object
+ * @name pinnedRight
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Column is pinned right when grid is rendered
+ * <br/>Defaults to false
+ */
+ if (colDef.pinnedLeft) {
+ col.renderContainer = 'left';
+ col.grid.createLeftContainer();
+ }
+ else if (colDef.pinnedRight) {
+ col.renderContainer = 'right';
+ col.grid.createRightContainer();
+ }
+
+ if (!colDef.enablePinning) {
+ return;
+ }
+
+ var pinColumnLeftAction = {
+ name: 'ui.grid.pinning.pinLeft',
+ title: i18nService.get().pinning.pinLeft,
+ icon: 'ui-grid-icon-left-open',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);
+ }
+ };
+
+ var pinColumnRightAction = {
+ name: 'ui.grid.pinning.pinRight',
+ title: i18nService.get().pinning.pinRight,
+ icon: 'ui-grid-icon-right-open',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);
+ }
+ };
+
+ var removePinAction = {
+ name: 'ui.grid.pinning.unpin',
+ title: i18nService.get().pinning.unpin,
+ icon: 'ui-grid-icon-cancel',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.NONE);
+ }
+ };
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {
+ col.menuItems.push(pinColumnLeftAction);
+ }
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {
+ col.menuItems.push(pinColumnRightAction);
+ }
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {
+ col.menuItems.push(removePinAction);
+ }
+ },
+
+ pinColumn: function(grid, col, container) {
+ if (container === uiGridPinningConstants.container.NONE) {
+ col.renderContainer = null;
+ col.colDef.pinnedLeft = col.colDef.pinnedRight = false;
+ }
+ else {
+ col.renderContainer = container;
+ if (container === uiGridPinningConstants.container.LEFT) {
+ grid.createLeftContainer();
+ }
+ else if (container === uiGridPinningConstants.container.RIGHT) {
+ grid.createRightContainer();
+ }
+ }
+
+ grid.refresh()
+ .then(function() {
+ grid.api.pinning.raise.columnPinned( col.colDef, container );
+ });
+ }
+ };
+
+ return service;
+ }]);
+
+ module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',
+ function (gridUtil, uiGridPinningService) {
+ return {
+ require: 'uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridPinningService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+
+})();
+
+(function(){
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.resizeColumns
+ * @description
+ *
+ * # ui.grid.resizeColumns
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module allows columns to be resized.
+ */
+ var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);
+
+ module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',
+ function (gridUtil, $q, $timeout) {
+
+ var service = {
+ defaultGridOptions: function(gridOptions){
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:GridOptions
+ *
+ * @description GridOptions for resizeColumns feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableColumnResizing
+ * @propertyOf ui.grid.resizeColumns.api:GridOptions
+ * @description Enable column resizing on the entire grid
+ * <br/>Defaults to true
+ */
+ gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;
+
+ //legacy support
+ //use old name if it is explicitly false
+ if (gridOptions.enableColumnResize === false){
+ gridOptions.enableColumnResizing = false;
+ }
+ },
+
+ colResizerColumnBuilder: function (colDef, col, gridOptions) {
+
+ var promises = [];
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:ColumnDef
+ *
+ * @description ColumnDef for resizeColumns feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableColumnResizing
+ * @propertyOf ui.grid.resizeColumns.api:ColumnDef
+ * @description Enable column resizing on an individual column
+ * <br/>Defaults to GridOptions.enableColumnResizing
+ */
+ //default to true unless gridOptions or colDef is explicitly false
+ colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;
+
+
+ //legacy support of old option name
+ if (colDef.enableColumnResize === false){
+ colDef.enableColumnResizing = false;
+ }
+
+ return $q.all(promises);
+ },
+
+ registerPublicApi: function (grid) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:PublicApi
+ * @description Public Api for column resize feature.
+ */
+ var publicApi = {
+ events: {
+ /**
+ * @ngdoc event
+ * @name columnSizeChanged
+ * @eventOf ui.grid.resizeColumns.api:PublicApi
+ * @description raised when column is resized
+ * <pre>
+ * gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})
+ * </pre>
+ * @param {object} colDef the column that was resized
+ * @param {integer} delta of the column size change
+ */
+ colResizable: {
+ columnSizeChanged: function (colDef, deltaChange) {
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ },
+
+ fireColumnSizeChanged: function (grid, colDef, deltaChange) {
+ $timeout(function () {
+ if ( grid.api.colResizable ){
+ grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);
+ } else {
+ gridUtil.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.");
+ }
+ });
+ },
+
+ // get either this column, or the column next to this column, to resize,
+ // returns the column we're going to resize
+ findTargetCol: function(col, position, rtlMultiplier){
+ var renderContainer = col.getRenderContainer();
+
+ if (position === 'left') {
+ // Get the column to the left of this one
+ var colIndex = renderContainer.visibleColumnCache.indexOf(col);
+ return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];
+ } else {
+ return col;
+ }
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.resizeColumns.directive:uiGridResizeColumns
+ * @element div
+ * @restrict A
+ * @description
+ * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the
+ * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.gridOpts = {
+ data: [
+ { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
+ { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
+ { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
+ { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
+ ]
+ };
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div class="testGrid" ui-grid="gridOpts" ui-grid-resize-columns ></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+
+ </doc:scenario>
+ </doc:example>
+ */
+ module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);
+ uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);
+ uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ // Extend the uiGridHeaderCell directive
+ module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {
+ return {
+ // Run after the original uiGridHeaderCell
+ priority: -10,
+ require: '^uiGrid',
+ // scope: false,
+ compile: function() {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var grid = uiGridCtrl.grid;
+
+ if (grid.options.enableColumnResizing) {
+ var columnResizerElm = $templateCache.get('ui-grid/columnResizer');
+
+ var rtlMultiplier = 1;
+ //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
+ if (grid.isRTL()) {
+ $scope.position = 'left';
+ rtlMultiplier = -1;
+ }
+
+ var displayResizers = function(){
+
+ // remove any existing resizers.
+ var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');
+ for ( var i = 0; i < resizers.length; i++ ){
+ angular.element(resizers[i]).remove();
+ }
+
+ // get the target column for the left resizer
+ var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);
+ var renderContainer = $scope.col.getRenderContainer();
+
+ // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled
+ if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {
+ var resizerLeft = angular.element(columnResizerElm).clone();
+ resizerLeft.attr('position', 'left');
+
+ $elm.prepend(resizerLeft);
+ $compile(resizerLeft)($scope);
+ }
+
+ // Don't append the right resizer if this column has resizing disabled
+ if ($scope.col.colDef.enableColumnResizing !== false) {
+ var resizerRight = angular.element(columnResizerElm).clone();
+ resizerRight.attr('position', 'right');
+
+ $elm.append(resizerRight);
+ $compile(resizerRight)($scope);
+ }
+ };
+
+ displayResizers();
+
+ var waitDisplay = function(){
+ $timeout(displayResizers);
+ };
+
+ var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );
+
+ $scope.$on( '$destroy', dataChangeDereg );
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.resizeColumns.directive:uiGridColumnResizer
+ * @element div
+ * @restrict A
+ *
+ * @description
+ * Draggable handle that controls column resizing.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.gridOpts = {
+ enableColumnResizing: true,
+ data: [
+ { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
+ { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
+ { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
+ { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
+ ]
+ };
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div class="testGrid" ui-grid="gridOpts"></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ // TODO: e2e specs?
+
+ // TODO: post-resize a horizontal scroll event should be fired
+ </doc:scenario>
+ </doc:example>
+ */
+ module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {
+ var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');
+
+ var resizer = {
+ priority: 0,
+ scope: {
+ col: '=',
+ position: '@',
+ renderIndex: '='
+ },
+ require: '?^uiGrid',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var startX = 0,
+ x = 0,
+ gridLeft = 0,
+ rtlMultiplier = 1;
+
+ //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
+ if (uiGridCtrl.grid.isRTL()) {
+ $scope.position = 'left';
+ rtlMultiplier = -1;
+ }
+
+ if ($scope.position === 'left') {
+ $elm.addClass('left');
+ }
+ else if ($scope.position === 'right') {
+ $elm.addClass('right');
+ }
+
+ // Refresh the grid canvas
+ // takes an argument representing the diff along the X-axis that the resize had
+ function refreshCanvas(xDiff) {
+ // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
+ uiGridCtrl.grid.refreshCanvas(true).then( function() {
+ uiGridCtrl.grid.queueGridRefresh();
+ });
+ }
+
+ // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
+ // Returns the new recommended with, after constraints applied
+ function constrainWidth(col, width){
+ var newWidth = width;
+
+ // If the new width would be less than the column's allowably minimum width, don't allow it
+ if (col.minWidth && newWidth < col.minWidth) {
+ newWidth = col.minWidth;
+ }
+ else if (col.maxWidth && newWidth > col.maxWidth) {
+ newWidth = col.maxWidth;
+ }
+
+ return newWidth;
+ }
+
+
+ /*
+ * Our approach to event handling aims to deal with both touch devices and mouse devices
+ * We register down handlers on both touch and mouse. When a touchstart or mousedown event
+ * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
+ *
+ * This way we can listen for both without worrying about the fact many touch devices also emulate
+ * mouse events - basically whichever one we hear first is what we'll go with.
+ */
+ function moveFunction(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.preventDefault();
+
+ x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
+
+ if (x < 0) { x = 0; }
+ else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
+ uiGridCtrl.grid.element.addClass('column-resizing');
+ }
+
+ // Get the diff along the X axis
+ var xDiff = x - startX;
+
+ // Get the width that this mouse would give the column
+ var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
+
+ // check we're not outside the allowable bounds for this column
+ x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;
+
+ resizeOverlay.css({ left: x + 'px' });
+
+ uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
+ }
+
+
+ function upFunction(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.preventDefault();
+
+ uiGridCtrl.grid.element.removeClass('column-resizing');
+
+ resizeOverlay.remove();
+
+ // Resize the column
+ x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
+ var xDiff = x - startX;
+
+ if (xDiff === 0) {
+ // no movement, so just reset event handlers, including turning back on both
+ // down events - we turned one off when this event started
+ offAllEvents();
+ onDownEvents();
+ return;
+ }
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ // Get the new width
+ var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
+
+ // check we're not outside the allowable bounds for this column
+ col.width = constrainWidth(col, newWidth);
+ col.hasCustomWidth = true;
+
+ refreshCanvas(xDiff);
+
+ uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
+
+ // stop listening of up and move events - wait for next down
+ // reset the down events - we will have turned one off when this event started
+ offAllEvents();
+ onDownEvents();
+ }
+
+
+ var downFunction = function(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.stopPropagation();
+
+ // Get the left offset of the grid
+ // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
+ gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;
+
+ // Get the starting X position, which is the X coordinate of the click minus the grid's offset
+ startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
+
+ // Append the resizer overlay
+ uiGridCtrl.grid.element.append(resizeOverlay);
+
+ // Place the resizer overlay at the start position
+ resizeOverlay.css({ left: startX });
+
+ // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
+ // we were touchdown then we listen for touchmove and touchup. Also remove the handler for the equivalent
+ // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
+ // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
+ if ( event.type === 'touchstart' ){
+ $document.on('touchend', upFunction);
+ $document.on('touchmove', moveFunction);
+ $elm.off('mousedown', downFunction);
+ } else {
+ $document.on('mouseup', upFunction);
+ $document.on('mousemove', moveFunction);
+ $elm.off('touchstart', downFunction);
+ }
+ };
+
+ var onDownEvents = function() {
+ $elm.on('mousedown', downFunction);
+ $elm.on('touchstart', downFunction);
+ };
+
+ var offAllEvents = function() {
+ $document.off('mouseup', upFunction);
+ $document.off('touchend', upFunction);
+ $document.off('mousemove', moveFunction);
+ $document.off('touchmove', moveFunction);
+ $elm.off('mousedown', downFunction);
+ $elm.off('touchstart', downFunction);
+ };
+
+ onDownEvents();
+
+
+ // On doubleclick, resize to fit all rendered cells
+ var dblClickFn = function(event, args){
+ event.stopPropagation();
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ // Go through the rendered rows and find out the max size for the data in this column
+ var maxWidth = 0;
+ var xDiff = 0;
+
+ // Get the parent render container element
+ var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');
+
+ // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present
+ var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');
+ Array.prototype.forEach.call(cells, function (cell) {
+ // Get the cell width
+ // gridUtil.logDebug('width', gridUtil.elementWidth(cell));
+
+ // Account for the menu button if it exists
+ var menuButton;
+ if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {
+ menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');
+ }
+
+ gridUtil.fakeElement(cell, {}, function(newElm) {
+ // Make the element float since it's a div and can expand to fill its container
+ var e = angular.element(newElm);
+ e.attr('style', 'float: left');
+
+ var width = gridUtil.elementWidth(e);
+
+ if (menuButton) {
+ var menuButtonWidth = gridUtil.elementWidth(menuButton);
+ width = width + menuButtonWidth;
+ }
+
+ if (width > maxWidth) {
+ maxWidth = width;
+ xDiff = maxWidth - width;
+ }
+ });
+ });
+
+ // check we're not outside the allowable bounds for this column
+ col.width = constrainWidth(col, maxWidth);
+ col.hasCustomWidth = true;
+
+ refreshCanvas(xDiff);
+
+ uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff); };
+ $elm.on('dblclick', dblClickFn);
+
+ $elm.on('$destroy', function() {
+ $elm.off('dblclick', dblClickFn);
+ offAllEvents();
+ });
+ }
+ };
+
+ return resizer;
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.rowEdit
+ * @description
+ *
+ * # ui.grid.rowEdit
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module extends the edit feature to provide tracking and saving of rows
+ * of data. The tutorial provides more information on how this feature is best
+ * used {@link tutorial/205_row_editable here}.
+ * <br/>
+ * This feature depends on usage of the ui-grid-edit feature, and also benefits
+ * from use of ui-grid-cellNav to provide the full spreadsheet-like editing
+ * experience
+ *
+ */
+
+ var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.constant:uiGridRowEditConstants
+ *
+ * @description constants available in row edit module
+ */
+ module.constant('uiGridRowEditConstants', {
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.rowEdit.service:uiGridRowEditService
+ *
+ * @description Services for row editing features
+ */
+ module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',
+ function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (scope, grid) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.api:PublicApi
+ *
+ * @description Public Api for rowEdit feature
+ */
+
+ grid.rowEdit = {};
+
+ var publicApi = {
+ events: {
+ rowEdit: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.rowEdit.api:PublicApi
+ * @name saveRow
+ * @description raised when a row is ready for saving. Once your
+ * row has saved you may need to use angular.extend to update the
+ * data entity with any changed data from your save (for example,
+ * lock version information if you're using optimistic locking,
+ * or last update time/user information).
+ *
+ * Your method should call setSavePromise somewhere in the body before
+ * returning control. The feature will then wait, with the gridRow greyed out
+ * whilst this promise is being resolved.
+ *
+ * <pre>
+ * gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})
+ * </pre>
+ * and somewhere within the event handler:
+ * <pre>
+ * gridApi.rowEdit.setSavePromise( rowEntity, savePromise)
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @returns {promise} Your saveRow method should return a promise, the
+ * promise should either be resolved (implying successful save), or
+ * rejected (implying an error).
+ */
+ saveRow: function (rowEntity) {
+ }
+ }
+ },
+ methods: {
+ rowEdit: {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setSavePromise
+ * @description Sets the promise associated with the row save, mandatory that
+ * the saveRow event handler calls this method somewhere before returning.
+ * <pre>
+ * gridApi.rowEdit.setSavePromise(rowEntity, savePromise)
+ * </pre>
+ * @param {object} rowEntity a data row from the grid for which a save has
+ * been initiated
+ * @param {promise} savePromise the promise that will be resolved when the
+ * save is successful, or rejected if the save fails
+ *
+ */
+ setSavePromise: function ( rowEntity, savePromise) {
+ service.setSavePromise(grid, rowEntity, savePromise);
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name getDirtyRows
+ * @description Returns all currently dirty rows
+ * <pre>
+ * gridApi.rowEdit.getDirtyRows(grid)
+ * </pre>
+ * @returns {array} An array of gridRows that are currently dirty
+ *
+ */
+ getDirtyRows: function () {
+ return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name getErrorRows
+ * @description Returns all currently errored rows
+ * <pre>
+ * gridApi.rowEdit.getErrorRows(grid)
+ * </pre>
+ * @returns {array} An array of gridRows that are currently in error
+ *
+ */
+ getErrorRows: function () {
+ return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name flushDirtyRows
+ * @description Triggers a save event for all currently dirty rows, could
+ * be used where user presses a save button or navigates away from the page
+ * <pre>
+ * gridApi.rowEdit.flushDirtyRows(grid)
+ * </pre>
+ * @returns {promise} a promise that represents the aggregate of all
+ * of the individual save promises - i.e. it will be resolved when all
+ * the individual save promises have been resolved.
+ *
+ */
+ flushDirtyRows: function () {
+ return service.flushDirtyRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setRowsDirty
+ * @description Sets each of the rows passed in dataRows
+ * to be dirty. note that if you have only just inserted the
+ * rows into your data you will need to wait for a $digest cycle
+ * before the gridRows are present - so often you would wrap this
+ * call in a $interval or $timeout
+ * <pre>
+ * $interval( function() {
+ * gridApi.rowEdit.setRowsDirty(myDataRows);
+ * }, 0, 1);
+ * </pre>
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set dirty.
+ *
+ */
+ setRowsDirty: function ( dataRows) {
+ service.setRowsDirty(grid, dataRows);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setRowsClean
+ * @description Sets each of the rows passed in dataRows
+ * to be clean, removing them from the dirty cache and the error cache,
+ * and clearing the error flag and the dirty flag
+ * <pre>
+ * var gridRows = $scope.gridApi.rowEdit.getDirtyRows();
+ * var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });
+ * $scope.gridApi.rowEdit.setRowsClean( dataRows );
+ * </pre>
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set clean.
+ *
+ */
+ setRowsClean: function ( dataRows) {
+ service.setRowsClean(grid, dataRows);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ grid.api.core.on.renderingComplete( scope, function ( gridApi ) {
+ grid.api.edit.on.afterCellEdit( scope, service.endEditCell );
+ grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );
+ grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );
+
+ if ( grid.api.cellNav ) {
+ grid.api.cellNav.on.navigate( scope, service.navigate );
+ }
+ });
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.api:GridOptions
+ *
+ * @description Options for configuring the rowEdit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name saveRow
+ * @description Returns a function that saves the specified row from the grid,
+ * and returns a promise
+ * @param {object} grid the grid for which dirty rows should be flushed
+ * @param {GridRow} gridRow the row that should be saved
+ * @returns {function} the saveRow function returns a function. That function
+ * in turn, when called, returns a promise relating to the save callback
+ */
+ saveRow: function ( grid, gridRow ) {
+ var self = this;
+
+ return function() {
+ gridRow.isSaving = true;
+
+ if ( gridRow.rowEditSavePromise ){
+ // don't save the row again if it's already saving - that causes stale object exceptions
+ return gridRow.rowEditSavePromise;
+ }
+
+ var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );
+
+ if ( gridRow.rowEditSavePromise ){
+ gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));
+ } else {
+ gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );
+ }
+ return promise;
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setSavePromise
+ * @description Sets the promise associated with the row save, mandatory that
+ * the saveRow event handler calls this method somewhere before returning.
+ * <pre>
+ * gridApi.rowEdit.setSavePromise(grid, rowEntity)
+ * </pre>
+ * @param {object} grid the grid for which dirty rows should be returned
+ * @param {object} rowEntity a data row from the grid for which a save has
+ * been initiated
+ * @param {promise} savePromise the promise that will be resolved when the
+ * save is successful, or rejected if the save fails
+ *
+ */
+ setSavePromise: function (grid, rowEntity, savePromise) {
+ var gridRow = grid.getRow( rowEntity );
+ gridRow.rowEditSavePromise = savePromise;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name processSuccessPromise
+ * @description Returns a function that processes the successful
+ * resolution of a save promise
+ * @param {object} grid the grid for which the promise should be processed
+ * @param {GridRow} gridRow the row that has been saved
+ * @returns {function} the success handling function
+ */
+ processSuccessPromise: function ( grid, gridRow ) {
+ var self = this;
+
+ return function() {
+ delete gridRow.isSaving;
+ delete gridRow.isDirty;
+ delete gridRow.isError;
+ delete gridRow.rowEditSaveTimer;
+ delete gridRow.rowEditSavePromise;
+ self.removeRow( grid.rowEdit.errorRows, gridRow );
+ self.removeRow( grid.rowEdit.dirtyRows, gridRow );
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name processErrorPromise
+ * @description Returns a function that processes the failed
+ * resolution of a save promise
+ * @param {object} grid the grid for which the promise should be processed
+ * @param {GridRow} gridRow the row that is now in error
+ * @returns {function} the error handling function
+ */
+ processErrorPromise: function ( grid, gridRow ) {
+ return function() {
+ delete gridRow.isSaving;
+ delete gridRow.rowEditSaveTimer;
+ delete gridRow.rowEditSavePromise;
+
+ gridRow.isError = true;
+
+ if (!grid.rowEdit.errorRows){
+ grid.rowEdit.errorRows = [];
+ }
+ if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){
+ grid.rowEdit.errorRows.push( gridRow );
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name removeRow
+ * @description Removes a row from a cache of rows - either
+ * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows. If the row
+ * is not present silently does nothing.
+ * @param {array} rowArray the array from which to remove the row
+ * @param {GridRow} gridRow the row that should be removed
+ */
+ removeRow: function( rowArray, removeGridRow ){
+ if (typeof(rowArray) === 'undefined' || rowArray === null){
+ return;
+ }
+
+ rowArray.forEach( function( gridRow, index ){
+ if ( gridRow.uid === removeGridRow.uid ){
+ rowArray.splice( index, 1);
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name isRowPresent
+ * @description Checks whether a row is already present
+ * in the given array
+ * @param {array} rowArray the array in which to look for the row
+ * @param {GridRow} gridRow the row that should be looked for
+ */
+ isRowPresent: function( rowArray, removeGridRow ){
+ var present = false;
+ rowArray.forEach( function( gridRow, index ){
+ if ( gridRow.uid === removeGridRow.uid ){
+ present = true;
+ }
+ });
+ return present;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name flushDirtyRows
+ * @description Triggers a save event for all currently dirty rows, could
+ * be used where user presses a save button or navigates away from the page
+ * <pre>
+ * gridApi.rowEdit.flushDirtyRows(grid)
+ * </pre>
+ * @param {object} grid the grid for which dirty rows should be flushed
+ * @returns {promise} a promise that represents the aggregate of all
+ * of the individual save promises - i.e. it will be resolved when all
+ * the individual save promises have been resolved.
+ *
+ */
+ flushDirtyRows: function(grid){
+ var promises = [];
+ grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ){
+ service.saveRow( grid, gridRow )();
+ promises.push( gridRow.rowEditSavePromise );
+ });
+
+ return $q.all( promises );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name endEditCell
+ * @description Receives an afterCellEdit event from the edit function,
+ * and sets flags as appropriate. Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ * @param {object} rowEntity the data entity for which the cell
+ * was edited
+ */
+ endEditCell: function( rowEntity, colDef, newValue, previousValue ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }
+
+ if ( newValue !== previousValue || gridRow.isDirty ){
+ if ( !grid.rowEdit.dirtyRows ){
+ grid.rowEdit.dirtyRows = [];
+ }
+
+ if ( !gridRow.isDirty ){
+ gridRow.isDirty = true;
+ grid.rowEdit.dirtyRows.push( gridRow );
+ }
+
+ delete gridRow.isError;
+
+ service.considerSetTimer( grid, gridRow );
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name beginEditCell
+ * @description Receives a beginCellEdit event from the edit function,
+ * and cancels any rowEditSaveTimers if present, as the user is still editing
+ * this row. Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ * @param {object} rowEntity the data entity for which the cell
+ * editing has commenced
+ */
+ beginEditCell: function( rowEntity, colDef ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }
+
+ service.cancelTimer( grid, gridRow );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name cancelEditCell
+ * @description Receives a cancelCellEdit event from the edit function,
+ * and if the row was already dirty, restarts the save timer. If the row
+ * was not already dirty, then it's not dirty now either and does nothing.
+ *
+ * Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ *
+ * @param {object} rowEntity the data entity for which the cell
+ * editing was cancelled
+ */
+ cancelEditCell: function( rowEntity, colDef ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }
+
+ service.considerSetTimer( grid, gridRow );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name navigate
+ * @description cellNav tells us that the selected cell has changed. If
+ * the new row had a timer running, then stop it similar to in a beginCellEdit
+ * call. If the old row is dirty and not the same as the new row, then
+ * start a timer on it.
+ * @param {object} newRowCol the row and column that were selected
+ * @param {object} oldRowCol the row and column that was left
+ *
+ */
+ navigate: function( newRowCol, oldRowCol ){
+ var grid = this.grid;
+ if ( newRowCol.row.rowEditSaveTimer ){
+ service.cancelTimer( grid, newRowCol.row );
+ }
+
+ if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){
+ service.considerSetTimer( grid, oldRowCol.row );
+ }
+ },
+
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.rowEdit.api:GridOptions
+ * @name rowEditWaitInterval
+ * @description How long the grid should wait for another change on this row
+ * before triggering a save (in milliseconds). If set to -1, then saves are
+ * never triggered by timer (implying that the user will call flushDirtyRows()
+ * manually)
+ *
+ * @example
+ * Setting the wait interval to 4 seconds
+ * <pre>
+ * $scope.gridOptions = { rowEditWaitInterval: 4000 }
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name considerSetTimer
+ * @description Consider setting a timer on this row (if it is dirty). if there is a timer running
+ * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is
+ * dirty and not currently saving then set a new timer
+ * @param {object} grid the grid for which we are processing
+ * @param {GridRow} gridRow the row for which the timer should be adjusted
+ *
+ */
+ considerSetTimer: function( grid, gridRow ){
+ service.cancelTimer( grid, gridRow );
+
+ if ( gridRow.isDirty && !gridRow.isSaving ){
+ if ( grid.options.rowEditWaitInterval !== -1 ){
+ var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;
+ gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name cancelTimer
+ * @description cancel the $interval for any timer running on this row
+ * then delete the timer itself
+ * @param {object} grid the grid for which we are processing
+ * @param {GridRow} gridRow the row for which the timer should be adjusted
+ *
+ */
+ cancelTimer: function( grid, gridRow ){
+ if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){
+ $interval.cancel(gridRow.rowEditSaveTimer);
+ delete gridRow.rowEditSaveTimer;
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setRowsDirty
+ * @description Sets each of the rows passed in dataRows
+ * to be dirty. note that if you have only just inserted the
+ * rows into your data you will need to wait for a $digest cycle
+ * before the gridRows are present - so often you would wrap this
+ * call in a $interval or $timeout
+ * <pre>
+ * $interval( function() {
+ * gridApi.rowEdit.setRowsDirty( myDataRows);
+ * }, 0, 1);
+ * </pre>
+ * @param {object} grid the grid for which rows should be set dirty
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set dirty.
+ *
+ */
+ setRowsDirty: function( grid, myDataRows ) {
+ var gridRow;
+ myDataRows.forEach( function( value, index ){
+ gridRow = grid.getRow( value );
+ if ( gridRow ){
+ if ( !grid.rowEdit.dirtyRows ){
+ grid.rowEdit.dirtyRows = [];
+ }
+
+ if ( !gridRow.isDirty ){
+ gridRow.isDirty = true;
+ grid.rowEdit.dirtyRows.push( gridRow );
+ }
+
+ delete gridRow.isError;
+
+ service.considerSetTimer( grid, gridRow );
+ } else {
+ gridUtil.logError( "requested row not found in rowEdit.setRowsDirty, row was: " + value );
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setRowsClean
+ * @description Sets each of the rows passed in dataRows
+ * to be clean, clearing the dirty flag and the error flag, and removing
+ * the rows from the dirty and error caches.
+ * @param {object} grid the grid for which rows should be set clean
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set clean.
+ *
+ */
+ setRowsClean: function( grid, myDataRows ) {
+ var gridRow;
+
+ myDataRows.forEach( function( value, index ){
+ gridRow = grid.getRow( value );
+ if ( gridRow ){
+ delete gridRow.isDirty;
+ service.removeRow( grid.rowEdit.dirtyRows, gridRow );
+ service.cancelTimer( grid, gridRow );
+
+ delete gridRow.isError;
+ service.removeRow( grid.rowEdit.errorRows, gridRow );
+ } else {
+ gridUtil.logError( "requested row not found in rowEdit.setRowsClean, row was: " + value );
+ }
+ });
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.rowEdit.directive:uiGridEdit
+ * @element div
+ * @restrict A
+ *
+ * @description Adds row editing features to the ui-grid-edit directive.
+ *
+ */
+ module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',
+ function (gridUtil, uiGridRowEditService, uiGridEditConstants) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.rowEdit.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
+ * for the grid row to allow coloring of saving and error rows
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
+ function ($compile, uiGridConstants, gridUtil, $parse) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
+ } else {
+ newNgClass = "{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.saveState
+ * @description
+ *
+ * # ui.grid.saveState
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to save the grid state, and restore
+ * it when the user returns to the page.
+ *
+ * No UI is provided, the caller should provide their own UI/buttons
+ * as appropriate. Usually the navigate events would be used to save
+ * the grid state and restore it.
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.save-state"></div>
+ */
+
+ var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.constant:uiGridSaveStateConstants
+ *
+ * @description constants available in save state module
+ */
+
+ module.constant('uiGridSaveStateConstants', {
+ featureName: 'saveState'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.saveState.service:uiGridSaveStateService
+ *
+ * @description Services for saveState feature
+ */
+ module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',
+ function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.saveState = {};
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.api:PublicApi
+ *
+ * @description Public Api for saveState feature
+ */
+ var publicApi = {
+ events: {
+ saveState: {
+ }
+ },
+ methods: {
+ saveState: {
+ /**
+ * @ngdoc function
+ * @name save
+ * @methodOf ui.grid.saveState.api:PublicApi
+ * @description Packages the current state of the grid into
+ * an object, and provides it to the user for saving
+ * @returns {object} the state as a javascript object that can be saved
+ */
+ save: function () {
+ return service.save(grid);
+ },
+ /**
+ * @ngdoc function
+ * @name restore
+ * @methodOf ui.grid.saveState.api:PublicApi
+ * @description Restores the provided state into the grid
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} state the state that should be restored into the grid
+ */
+ restore: function ( $scope, state) {
+ service.restore(grid, $scope, state);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.api:GridOptions
+ *
+ * @description GridOptions for saveState feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name saveWidths
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current column widths. Note that unless
+ * you've provided the user with some way to resize their columns (say
+ * the resize columns feature), then this makes little sense.
+ * <br/>Defaults to true
+ */
+ gridOptions.saveWidths = gridOptions.saveWidths !== false;
+ /**
+ * @ngdoc object
+ * @name saveOrder
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Restore the current column order. Note that unless
+ * you've provided the user with some way to reorder their columns (for
+ * example the move columns feature), this makes little sense.
+ * <br/>Defaults to true
+ */
+ gridOptions.saveOrder = gridOptions.saveOrder !== false;
+ /**
+ * @ngdoc object
+ * @name saveScroll
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current scroll position. Note that this
+ * is saved as the percentage of the grid scrolled - so if your
+ * user returns to a grid with a significantly different number of
+ * rows (perhaps some data has been deleted) then the scroll won't
+ * actually show the same rows as before. If you want to scroll to
+ * a specific row then you should instead use the saveFocus option, which
+ * is the default.
+ *
+ * Note that this element will only be saved if the cellNav feature is
+ * enabled
+ * <br/>Defaults to false
+ */
+ gridOptions.saveScroll = gridOptions.saveScroll === true;
+ /**
+ * @ngdoc object
+ * @name saveFocus
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current focused cell. On returning
+ * to this focused cell we'll also scroll. This option is
+ * preferred to the saveScroll option, so is set to true by
+ * default. If saveScroll is set to true then this option will
+ * be disabled.
+ *
+ * By default this option saves the current row number and column
+ * number, and returns to that row and column. However, if you define
+ * a saveRowIdentity function, then it will return you to the currently
+ * selected column within that row (in a business sense - so if some
+ * rows have been deleted, it will still find the same data, presuming it
+ * still exists in the list. If it isn't in the list then it will instead
+ * return to the same row number - i.e. scroll percentage)
+ *
+ * Note that this option will do nothing if the cellNav
+ * feature is not enabled.
+ *
+ * <br/>Defaults to true (unless saveScroll is true)
+ */
+ gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;
+ /**
+ * @ngdoc object
+ * @name saveRowIdentity
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description A function that can be called, passing in a rowEntity,
+ * and that will return a unique id for that row. This might simply
+ * return the `id` field from that row (if you have one), or it might
+ * concatenate some fields within the row to make a unique value.
+ *
+ * This value will be used to find the same row again and set the focus
+ * to it, if it exists when we return.
+ *
+ * <br/>Defaults to undefined
+ */
+ /**
+ * @ngdoc object
+ * @name saveVisible
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save whether or not columns are visible.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveVisible = gridOptions.saveVisible !== false;
+ /**
+ * @ngdoc object
+ * @name saveSort
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current sort state for each column
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveSort = gridOptions.saveSort !== false;
+ /**
+ * @ngdoc object
+ * @name saveFilter
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current filter state for each column
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveFilter = gridOptions.saveFilter !== false;
+ /**
+ * @ngdoc object
+ * @name saveSelection
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the currently selected rows. If the `saveRowIdentity` callback
+ * is defined, then it will save the id of the row and select that. If not, then
+ * it will attempt to select the rows by row number, which will give the wrong results
+ * if the data set has changed in the mean-time.
+ *
+ * Note that this option only does anything
+ * if the selection feature is enabled.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveSelection = gridOptions.saveSelection !== false;
+ /**
+ * @ngdoc object
+ * @name saveGrouping
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the grouping configuration. If set to true and the
+ * grouping feature is not enabled then does nothing.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveGrouping = gridOptions.saveGrouping !== false;
+ /**
+ * @ngdoc object
+ * @name saveGroupingExpandedStates
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the grouping row expanded states. If set to true and the
+ * grouping feature is not enabled then does nothing.
+ *
+ * This can be quite a bit of data, in many cases you wouldn't want to save this
+ * information.
+ *
+ * <br/>Defaults to false
+ */
+ gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;
+ /**
+ * @ngdoc object
+ * @name savePinning
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save pinning state for columns.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.savePinning = gridOptions.savePinning !== false;
+ /**
+ * @ngdoc object
+ * @name saveTreeView
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the treeView configuration. If set to true and the
+ * treeView feature is not enabled then does nothing.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveTreeView = gridOptions.saveTreeView !== false;
+ },
+
+
+
+ /**
+ * @ngdoc function
+ * @name save
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the current grid state into an object, and
+ * passes that object back to the caller
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the state ready to be saved
+ */
+ save: function (grid) {
+ var savedState = {};
+
+ savedState.columns = service.saveColumns( grid );
+ savedState.scrollFocus = service.saveScrollFocus( grid );
+ savedState.selection = service.saveSelection( grid );
+ savedState.grouping = service.saveGrouping( grid );
+ savedState.treeView = service.saveTreeView( grid );
+ savedState.pagination = service.savePagination( grid );
+
+ return savedState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restore
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Applies the provided state to the grid
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} state the state we'd like to restore
+ */
+ restore: function( grid, $scope, state ){
+ if ( state.columns ) {
+ service.restoreColumns( grid, state.columns );
+ }
+
+ if ( state.scrollFocus ){
+ service.restoreScrollFocus( grid, $scope, state.scrollFocus );
+ }
+
+ if ( state.selection ){
+ service.restoreSelection( grid, state.selection );
+ }
+
+ if ( state.grouping ){
+ service.restoreGrouping( grid, state.grouping );
+ }
+
+ if ( state.treeView ){
+ service.restoreTreeView( grid, state.treeView );
+ }
+
+ if ( state.pagination ){
+ service.restorePagination( grid, state.pagination );
+ }
+
+ grid.refresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveColumns
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the column setup, including sort, filters, ordering,
+ * pinning and column widths.
+ *
+ * Works through the current columns, storing them in order. Stores the
+ * column name, then the visible flag, width, sort and filters for each column.
+ *
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {array} the columns state ready to be saved
+ */
+ saveColumns: function( grid ) {
+ var columns = [];
+ grid.getOnlyDataColumns().forEach( function( column ) {
+ var savedColumn = {};
+ savedColumn.name = column.name;
+
+ if ( grid.options.saveVisible ){
+ savedColumn.visible = column.visible;
+ }
+
+ if ( grid.options.saveWidths ){
+ savedColumn.width = column.width;
+ }
+
+ // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state
+ if ( grid.options.saveSort ){
+ savedColumn.sort = angular.copy( column.sort );
+ }
+
+ if ( grid.options.saveFilter ){
+ savedColumn.filters = [];
+ column.filters.forEach( function( filter ){
+ var copiedFilter = {};
+ angular.forEach( filter, function( value, key) {
+ if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder'){
+ copiedFilter[key] = value;
+ }
+ });
+ savedColumn.filters.push(copiedFilter);
+ });
+ }
+
+ if ( !!grid.api.pinning && grid.options.savePinning ){
+ savedColumn.pinned = column.renderContainer ? column.renderContainer : '';
+ }
+
+ columns.push( savedColumn );
+ });
+
+ return columns;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveScrollFocus
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the currently scroll or focus.
+ *
+ * If cellNav isn't present then does nothing - we can't return
+ * to the scroll position without cellNav anyway.
+ *
+ * If the cellNav module is present, and saveFocus is true, then
+ * it saves the currently focused cell. If rowIdentity is present
+ * then saves using rowIdentity, otherwise saves visibleRowNum.
+ *
+ * If the cellNav module is not present, and saveScroll is true, then
+ * it approximates the current scroll row and column, and saves that.
+ *
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the selection state ready to be saved
+ */
+ saveScrollFocus: function( grid ){
+ if ( !grid.api.cellNav ){
+ return {};
+ }
+
+ var scrollFocus = {};
+ if ( grid.options.saveFocus ){
+ scrollFocus.focus = true;
+ var rowCol = grid.api.cellNav.getFocusedCell();
+ if ( rowCol !== null ) {
+ if ( rowCol.col !== null ){
+ scrollFocus.colName = rowCol.col.colDef.name;
+ }
+ if ( rowCol.row !== null ){
+ scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );
+ }
+ }
+ }
+
+ if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {
+ scrollFocus.focus = false;
+ if ( grid.renderContainers.body.prevRowScrollIndex ){
+ scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);
+ }
+
+ if ( grid.renderContainers.body.prevColScrollIndex ){
+ scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;
+ }
+ }
+
+ return scrollFocus;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveSelection
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the currently selected rows, if the selection feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {array} the selection state ready to be saved
+ */
+ saveSelection: function( grid ){
+ if ( !grid.api.selection || !grid.options.saveSelection ){
+ return [];
+ }
+
+ var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {
+ return service.getRowVal( grid, gridRow );
+ });
+
+ return selection;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveGrouping
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the grouping state, if the grouping feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the grouping state ready to be saved
+ */
+ saveGrouping: function( grid ){
+ if ( !grid.api.grouping || !grid.options.saveGrouping ){
+ return {};
+ }
+
+ return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name savePagination
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the pagination state, if the pagination feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the pagination state ready to be saved
+ */
+ savePagination: function( grid ) {
+ if ( !grid.api.pagination || !grid.options.paginationPageSize ){
+ return {};
+ }
+
+ return {
+ paginationCurrentPage: grid.options.paginationCurrentPage,
+ paginationPageSize: grid.options.paginationPageSize
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveTreeView
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the tree view state, if the tree feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the tree view state ready to be saved
+ */
+ saveTreeView: function( grid ){
+ if ( !grid.api.treeView || !grid.options.saveTreeView ){
+ return {};
+ }
+
+ return grid.api.treeView.getTreeView();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getRowVal
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Helper function that gets either the rowNum or
+ * the saveRowIdentity, given a gridRow
+ * @param {Grid} grid the grid the row is in
+ * @param {GridRow} gridRow the row we want the rowNum for
+ * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }
+ *
+ */
+ getRowVal: function( grid, gridRow ){
+ if ( !gridRow ) {
+ return null;
+ }
+
+ var rowVal = {};
+ if ( grid.options.saveRowIdentity ){
+ rowVal.identity = true;
+ rowVal.row = grid.options.saveRowIdentity( gridRow.entity );
+ } else {
+ rowVal.identity = false;
+ rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );
+ }
+ return rowVal;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreColumns
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the columns, including order, visible, width,
+ * pinning, sort and filters.
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} columnsState the list of columns we had before, with their state
+ */
+ restoreColumns: function( grid, columnsState ){
+ var isSortChanged = false;
+
+ columnsState.forEach( function( columnState, index ) {
+ var currentCol = grid.getColumn( columnState.name );
+
+ if ( currentCol && !grid.isRowHeaderColumn(currentCol) ){
+ if ( grid.options.saveVisible &&
+ ( currentCol.visible !== columnState.visible ||
+ currentCol.colDef.visible !== columnState.visible ) ){
+ currentCol.visible = columnState.visible;
+ currentCol.colDef.visible = columnState.visible;
+ grid.api.core.raise.columnVisibilityChanged(currentCol);
+ }
+
+ if ( grid.options.saveWidths && currentCol.width !== columnState.width){
+ currentCol.width = columnState.width;
+ currentCol.hasCustomWidth = true;
+ }
+
+ if ( grid.options.saveSort &&
+ !angular.equals(currentCol.sort, columnState.sort) &&
+ !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ){
+ currentCol.sort = angular.copy( columnState.sort );
+ isSortChanged = true;
+ }
+
+ if ( grid.options.saveFilter &&
+ !angular.equals(currentCol.filters, columnState.filters ) ){
+ columnState.filters.forEach( function( filter, index ){
+ angular.extend( currentCol.filters[index], filter );
+ if ( typeof(filter.term) === 'undefined' || filter.term === null ){
+ delete currentCol.filters[index].term;
+ }
+ });
+ grid.api.core.raise.filterChanged();
+ }
+
+ if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ){
+ grid.api.pinning.pinColumn(currentCol, columnState.pinned);
+ }
+
+ var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );
+ if (currentIndex !== -1) {
+ if (grid.options.saveOrder && currentIndex !== index) {
+ var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];
+ grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);
+ }
+ }
+ }
+ });
+
+ if ( isSortChanged ) {
+ grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreScrollFocus
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Scrolls to the position that was saved. If focus is true, then
+ * sets focus to the specified row/col. If focus is false, then scrolls to the
+ * specified row/col.
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} scrollFocusState the scroll/focus state ready to be restored
+ */
+ restoreScrollFocus: function( grid, $scope, scrollFocusState ){
+ if ( !grid.api.cellNav ){
+ return;
+ }
+
+ var colDef, row;
+ if ( scrollFocusState.colName ){
+ var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });
+ if ( colDefs.length > 0 ){
+ colDef = colDefs[0];
+ }
+ }
+
+ if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){
+ if ( scrollFocusState.rowVal.identity ){
+ row = service.findRowByIdentity( grid, scrollFocusState.rowVal );
+ } else {
+ row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];
+ }
+ }
+
+ var entity = row && row.entity ? row.entity : null ;
+
+ if ( colDef || entity ) {
+ if (scrollFocusState.focus ){
+ grid.api.cellNav.scrollToFocus( entity, colDef );
+ } else {
+ grid.scrollTo( entity, colDef );
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreSelection
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Selects the rows that are provided in the selection
+ * state. If you are using `saveRowIdentity` and more than one row matches the identity
+ * function then only the first is selected.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} selectionState the selection state ready to be restored
+ */
+ restoreSelection: function( grid, selectionState ){
+ if ( !grid.api.selection ){
+ return;
+ }
+
+ grid.api.selection.clearSelectedRows();
+
+ selectionState.forEach( function( rowVal ) {
+ if ( rowVal.identity ){
+ var foundRow = service.findRowByIdentity( grid, rowVal );
+
+ if ( foundRow ){
+ grid.api.selection.selectRow( foundRow.entity );
+ }
+
+ } else {
+ grid.api.selection.selectRowByVisibleIndex( rowVal.row );
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreGrouping
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the grouping configuration, if the grouping feature
+ * is enabled.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} groupingState the grouping state ready to be restored
+ */
+ restoreGrouping: function( grid, groupingState ){
+ if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ){
+ return;
+ }
+
+ grid.api.grouping.setGrouping( groupingState );
+ },
+
+ /**
+ * @ngdoc function
+ * @name restoreTreeView
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the tree view configuration, if the tree view feature
+ * is enabled.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} treeViewState the tree view state ready to be restored
+ */
+ restoreTreeView: function( grid, treeViewState ){
+ if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ){
+ return;
+ }
+
+ grid.api.treeView.setTreeView( treeViewState );
+ },
+
+ /**
+ * @ngdoc function
+ * @name restorePagination
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the pagination information, if pagination is enabled.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} pagination the pagination object to be restored
+ * @param {number} pagination.paginationCurrentPage the page number to restore
+ * @param {number} pagination.paginationPageSize the number of items displayed per page
+ */
+ restorePagination: function( grid, pagination ){
+ if ( !grid.api.pagination || !grid.options.paginationPageSize ){
+ return;
+ }
+
+ grid.options.paginationCurrentPage = pagination.paginationCurrentPage;
+ grid.options.paginationPageSize = pagination.paginationPageSize;
+ },
+
+ /**
+ * @ngdoc function
+ * @name findRowByIdentity
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Finds a row given it's identity value, returns the first found row
+ * if any are found, otherwise returns null if no rows are found.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} rowVal the row we'd like to find
+ * @returns {gridRow} the found row, or null if none found
+ */
+ findRowByIdentity: function( grid, rowVal ){
+ if ( !grid.options.saveRowIdentity ){
+ return null;
+ }
+
+ var filteredRows = grid.rows.filter( function( gridRow ) {
+ if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){
+ return true;
+ } else {
+ return false;
+ }
+ });
+
+ if ( filteredRows.length > 0 ){
+ return filteredRows[0];
+ } else {
+ return null;
+ }
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.saveState.directive:uiGridSaveState
+ * @element div
+ * @restrict A
+ *
+ * @description Adds saveState features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.gridOptions = {
+ columnDefs: [
+ {name: 'name'},
+ {name: 'title', enableCellEdit: true}
+ ],
+ data: $scope.data
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-save-state></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',
+ function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.selection
+ * @description
+ *
+ * # ui.grid.selection
+ * This module provides row selection
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * <div doc-module-components="ui.grid.selection"></div>
+ */
+
+ var module = angular.module('ui.grid.selection', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.constant:uiGridSelectionConstants
+ *
+ * @description constants available in selection module
+ */
+ module.constant('uiGridSelectionConstants', {
+ featureName: "selection",
+ selectionRowHeaderColName: 'selectionRowHeaderCol'
+ });
+
+ //add methods to GridRow
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('GridRow', ['$delegate', function($delegate) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:GridRow
+ *
+ * @description GridRow prototype functions added for selection
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableSelection
+ * @propertyOf ui.grid.selection.api:GridRow
+ * @description Enable row selection for this row, only settable by internal code.
+ *
+ * The grouping feature, for example, might set group header rows to not be selectable.
+ * <br/>Defaults to true
+ */
+
+ /**
+ * @ngdoc object
+ * @name isSelected
+ * @propertyOf ui.grid.selection.api:GridRow
+ * @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
+ * <br/>Defaults to false
+ */
+
+
+ /**
+ * @ngdoc function
+ * @name setSelected
+ * @methodOf ui.grid.selection.api:GridRow
+ * @description Sets the isSelected property and updates the selectedCount
+ * Changes to isSelected state should only be made via this function
+ * @param {bool} selected value to set
+ */
+ $delegate.prototype.setSelected = function(selected) {
+ if (selected !== this.isSelected) {
+ this.isSelected = selected;
+ this.grid.selection.selectedCount += selected ? 1 : -1;
+ }
+ };
+
+ return $delegate;
+ }]);
+ }]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.selection.service:uiGridSelectionService
+ *
+ * @description Services for selection features
+ */
+ module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',
+ function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.grid:selection
+ *
+ * @description Grid properties and functions added for selection
+ */
+ grid.selection = {};
+ grid.selection.lastSelectedRow = null;
+ grid.selection.selectAll = false;
+
+
+ /**
+ * @ngdoc object
+ * @name selectedCount
+ * @propertyOf ui.grid.selection.grid:selection
+ * @description Current count of selected rows
+ * @example
+ * var count = grid.selection.selectedCount
+ */
+ grid.selection.selectedCount = 0;
+
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:PublicApi
+ *
+ * @description Public Api for selection feature
+ */
+ var publicApi = {
+ events: {
+ selection: {
+ /**
+ * @ngdoc event
+ * @name rowSelectionChanged
+ * @eventOf ui.grid.selection.api:PublicApi
+ * @description is raised after the row.isSelected state is changed
+ * @param {GridRow} row the row that was selected/deselected
+ * @param {Event} event object if raised from an event
+ */
+ rowSelectionChanged: function (scope, row, evt) {
+ },
+ /**
+ * @ngdoc event
+ * @name rowSelectionChangedBatch
+ * @eventOf ui.grid.selection.api:PublicApi
+ * @description is raised after the row.isSelected state is changed
+ * in bulk, if the `enableSelectionBatchEvent` option is set to true
+ * (which it is by default). This allows more efficient processing
+ * of bulk events.
+ * @param {array} rows the rows that were selected/deselected
+ * @param {Event} event object if raised from an event
+ */
+ rowSelectionChangedBatch: function (scope, rows, evt) {
+ }
+ }
+ },
+ methods: {
+ selection: {
+ /**
+ * @ngdoc function
+ * @name toggleRowSelection
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Toggles data row as selected or unselected
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ toggleRowSelection: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectRow
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Select the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ selectRow: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && !row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectRowByVisibleIndex
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Select the specified row by visible index (i.e. if you
+ * specify row 0 you'll get the first visible row selected). In this context
+ * visible means of those rows that are theoretically visible (i.e. not filtered),
+ * rather than rows currently rendered on the screen.
+ * @param {number} index index within the rowsVisible array
+ * @param {Event} event object if raised from an event
+ */
+ selectRowByVisibleIndex: function ( rowNum, evt ) {
+ var row = grid.renderContainers.body.visibleRowCache[rowNum];
+ if (row !== null && typeof(row) !== 'undefined' && !row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name unSelectRow
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description UnSelect the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ unSelectRow: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectAllRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Selects all rows. Does nothing if multiSelect = false
+ * @param {Event} event object if raised from an event
+ */
+ selectAllRows: function (evt) {
+ if (grid.options.multiSelect === false) {
+ return;
+ }
+
+ var changedRows = [];
+ grid.rows.forEach(function (row) {
+ if ( !row.isSelected && row.enableSelection !== false ){
+ row.setSelected(true);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = true;
+ },
+ /**
+ * @ngdoc function
+ * @name selectAllVisibleRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Selects all visible rows. Does nothing if multiSelect = false
+ * @param {Event} event object if raised from an event
+ */
+ selectAllVisibleRows: function (evt) {
+ if (grid.options.multiSelect === false) {
+ return;
+ }
+
+ var changedRows = [];
+ grid.rows.forEach(function (row) {
+ if (row.visible) {
+ if (!row.isSelected && row.enableSelection !== false){
+ row.setSelected(true);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ } else {
+ if (row.isSelected){
+ row.setSelected(false);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = true;
+ },
+ /**
+ * @ngdoc function
+ * @name clearSelectedRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Unselects all rows
+ * @param {Event} event object if raised from an event
+ */
+ clearSelectedRows: function (evt) {
+ service.clearSelectedRows(grid, evt);
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description returns all selectedRow's entity references
+ */
+ getSelectedRows: function () {
+ return service.getSelectedRows(grid).map(function (gridRow) {
+ return gridRow.entity;
+ });
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedGridRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description returns all selectedRow's as gridRows
+ */
+ getSelectedGridRows: function () {
+ return service.getSelectedRows(grid);
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedCount
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description returns the number of rows selected
+ */
+ getSelectedCount: function () {
+ return grid.selection.selectedCount;
+ },
+ /**
+ * @ngdoc function
+ * @name setMultiSelect
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Sets the current gridOption.multiSelect to true or false
+ * @param {bool} multiSelect true to allow multiple rows
+ */
+ setMultiSelect: function (multiSelect) {
+ grid.options.multiSelect = multiSelect;
+ },
+ /**
+ * @ngdoc function
+ * @name setModifierKeysToMultiSelect
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false
+ * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used
+ */
+ setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {
+ grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectAllState
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Returns whether or not the selectAll checkbox is currently ticked. The
+ * grid doesn't automatically select rows when you add extra data - so when you add data
+ * you need to explicitly check whether the selectAll is set, and then call setVisible rows
+ * if it is
+ */
+ getSelectAllState: function () {
+ return grid.selection.selectAll;
+ }
+
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:GridOptions
+ *
+ * @description GridOptions for selection feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableRowSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable row selection for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;
+ /**
+ * @ngdoc object
+ * @name multiSelect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable multiple row selection for entire grid
+ * <br/>Defaults to true
+ */
+ gridOptions.multiSelect = gridOptions.multiSelect !== false;
+ /**
+ * @ngdoc object
+ * @name noUnselect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Prevent a row from being unselected. Works in conjunction
+ * with `multiselect = false` and `gridApi.selection.selectRow()` to allow
+ * you to create a single selection only grid - a row is always selected, you
+ * can only select different rows, you can't unselect the row.
+ * <br/>Defaults to false
+ */
+ gridOptions.noUnselect = gridOptions.noUnselect === true;
+ /**
+ * @ngdoc object
+ * @name modifierKeysToMultiSelect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.
+ * <br/>Defaults to false
+ */
+ gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;
+ /**
+ * @ngdoc object
+ * @name enableRowHeaderSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable a row header to be used for selection
+ * <br/>Defaults to true
+ */
+ gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;
+ /**
+ * @ngdoc object
+ * @name enableFullRowSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable selection by clicking anywhere on the row. Defaults to
+ * false if `enableRowHeaderSelection` is true, otherwise defaults to false.
+ */
+ if ( typeof(gridOptions.enableFullRowSelection) === 'undefined' ){
+ gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
+ }
+ /**
+ * @ngdoc object
+ * @name enableSelectAll
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable the select all checkbox at the top of the selectionRowHeader
+ * <br/>Defaults to true
+ */
+ gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;
+ /**
+ * @ngdoc object
+ * @name enableSelectionBatchEvent
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description If selected rows are changed in bulk, either via the API or
+ * via the selectAll checkbox, then a separate event is fired. Setting this
+ * option to false will cause the rowSelectionChanged event to be called multiple times
+ * instead
+ * <br/>Defaults to true
+ */
+ gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;
+ /**
+ * @ngdoc object
+ * @name selectionRowHeaderWidth
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description can be used to set a custom width for the row header selection column
+ * <br/>Defaults to 30px
+ */
+ gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
+
+ /**
+ * @ngdoc object
+ * @name enableFooterTotalSelected
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Shows the total number of selected items in footer if true.
+ * <br/>Defaults to true.
+ * <br/>GridOptions.showGridFooter must also be set to true.
+ */
+ gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
+
+ /**
+ * @ngdoc object
+ * @name isRowSelectable
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
+ */
+
+ gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
+ },
+
+ /**
+ * @ngdoc function
+ * @name toggleRowSelection
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Toggles row as selected or unselected
+ * @param {Grid} grid grid object
+ * @param {GridRow} row row to select or deselect
+ * @param {Event} event object if resulting from event
+ * @param {bool} multiSelect if false, only one row at time can be selected
+ * @param {bool} noUnselect if true then rows cannot be unselected
+ */
+ toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
+ var selected = row.isSelected;
+
+ if ( row.enableSelection === false && !selected ){
+ return;
+ }
+
+ var selectedRows;
+ if (!multiSelect && !selected) {
+ service.clearSelectedRows(grid, evt);
+ } else if (!multiSelect && selected) {
+ selectedRows = service.getSelectedRows(grid);
+ if (selectedRows.length > 1) {
+ selected = false; // Enable reselect of the row
+ service.clearSelectedRows(grid, evt);
+ }
+ }
+
+ if (selected && noUnselect){
+ // don't deselect the row
+ } else {
+ row.setSelected(!selected);
+ if (row.isSelected === true) {
+ grid.selection.lastSelectedRow = row;
+ }
+
+ selectedRows = service.getSelectedRows(grid);
+ grid.selection.selectAll = grid.rows.length === selectedRows.length;
+
+ grid.api.selection.raise.rowSelectionChanged(row, evt);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name shiftSelect
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description selects a group of rows from the last selected row using the shift key
+ * @param {Grid} grid grid object
+ * @param {GridRow} clicked row
+ * @param {Event} event object if raised from an event
+ * @param {bool} multiSelect if false, does nothing this is for multiSelect only
+ */
+ shiftSelect: function (grid, row, evt, multiSelect) {
+ if (!multiSelect) {
+ return;
+ }
+ var selectedRows = service.getSelectedRows(grid);
+ var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;
+ var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);
+ //reverse select direction
+ if (fromRow > toRow) {
+ var tmp = fromRow;
+ fromRow = toRow;
+ toRow = tmp;
+ }
+
+ var changedRows = [];
+ for (var i = fromRow; i <= toRow; i++) {
+ var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
+ if (rowToSelect) {
+ if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){
+ rowToSelect.setSelected(true);
+ grid.selection.lastSelectedRow = rowToSelect;
+ service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );
+ }
+ }
+ }
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedRows
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Returns all the selected rows
+ * @param {Grid} grid grid object
+ */
+ getSelectedRows: function (grid) {
+ return grid.rows.filter(function (row) {
+ return row.isSelected;
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name clearSelectedRows
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Clears all selected rows
+ * @param {Grid} grid grid object
+ * @param {Event} event object if raised from an event
+ */
+ clearSelectedRows: function (grid, evt) {
+ var changedRows = [];
+ service.getSelectedRows(grid).forEach(function (row) {
+ if ( row.isSelected ){
+ row.setSelected(false);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = false;
+ grid.selection.selectedCount = 0;
+ },
+
+ /**
+ * @ngdoc function
+ * @name decideRaiseSelectionEvent
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Decides whether to raise a single event or a batch event
+ * @param {Grid} grid grid object
+ * @param {GridRow} row row that has changed
+ * @param {array} changedRows an array to which we can append the changed
+ * @param {Event} event object if raised from an event
+ * row if we're doing batch events
+ */
+ decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){
+ if ( !grid.options.enableSelectionBatchEvent ){
+ grid.api.selection.raise.rowSelectionChanged(row, evt);
+ } else {
+ changedRows.push(row);
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name raiseSelectionEvent
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Decides whether we need to raise a batch event, and
+ * raises it if we do.
+ * @param {Grid} grid grid object
+ * @param {array} changedRows an array of changed rows, only populated
+ * @param {Event} event object if raised from an event
+ * if we're doing batch events
+ */
+ decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){
+ if ( changedRows.length > 0 ){
+ grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);
+ }
+ }
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridSelection
+ * @element div
+ * @restrict A
+ *
+ * @description Adds selection features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-selection></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache', 'uiGridConstants',
+ function (uiGridSelectionConstants, uiGridSelectionService, $templateCache, uiGridConstants) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridSelectionService.initializeGrid(uiGridCtrl.grid);
+ if (uiGridCtrl.grid.options.enableRowHeaderSelection) {
+ var selectionRowHeaderDef = {
+ name: uiGridSelectionConstants.selectionRowHeaderColName,
+ displayName: '',
+ width: uiGridCtrl.grid.options.selectionRowHeaderWidth,
+ minWidth: 10,
+ cellTemplate: 'ui-grid/selectionRowHeader',
+ headerCellTemplate: 'ui-grid/selectionHeaderCell',
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ exporterSuppressExport: true,
+ allowCellFocus: true
+ };
+
+ uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0);
+ }
+
+ var processorSet = false;
+
+ var processSelectableRows = function( rows ){
+ rows.forEach(function(row){
+ row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);
+ });
+ return rows;
+ };
+
+ var updateOptions = function(){
+ if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {
+ uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);
+ processorSet = true;
+ }
+ };
+
+ updateOptions();
+
+ var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback( updateOptions, [uiGridConstants.dataChange.OPTIONS] );
+
+ $scope.$on( '$destroy', dataChangeDereg);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',
+ function ($templateCache, uiGridSelectionService, gridUtil) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),
+ scope: true,
+ require: '^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = uiGridCtrl.grid;
+ $scope.selectButtonClick = selectButtonClick;
+
+ // On IE, prevent mousedowns on the select button from starting a selection.
+ // If this is not done and you shift+click on another row, the browser will select a big chunk of text
+ if (gridUtil.detectBrowser() === 'ie') {
+ $elm.on('mousedown', selectButtonMouseDown);
+ }
+
+
+ function selectButtonClick(row, evt) {
+ evt.stopPropagation();
+
+ if (evt.shiftKey) {
+ uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
+ }
+ else if (evt.ctrlKey || evt.metaKey) {
+ uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
+ }
+ else {
+ uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
+ }
+ }
+
+ function selectButtonMouseDown(evt) {
+ if (evt.ctrlKey || evt.shiftKey) {
+ evt.target.onselectstart = function () { return false; };
+ window.setTimeout(function () { evt.target.onselectstart = null; }, 0);
+ }
+ }
+
+ $scope.$on('$destroy', function unbindEvents() {
+ $elm.off();
+ });
+ }
+ };
+ }]);
+
+ module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',
+ function ($templateCache, uiGridSelectionService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/selectionSelectAllButtons'),
+ scope: false,
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = $scope.col.grid;
+
+ $scope.headerButtonClick = function(row, evt) {
+ if ( self.selection.selectAll ){
+ uiGridSelectionService.clearSelectedRows(self, evt);
+ if ( self.options.noUnselect ){
+ self.api.selection.selectRowByVisibleIndex(0, evt);
+ }
+ self.selection.selectAll = false;
+ } else {
+ if ( self.options.multiSelect ){
+ self.api.selection.selectAllVisibleRows(evt);
+ self.selection.selectAll = true;
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
+ * for the grid row
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',
+ function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-row-selected': row.isSelected}";
+ } else {
+ newNgClass = "{'ui-grid-row-selected': row.isSelected}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridCell to provide selection feature
+ */
+ module.directive('uiGridCell',
+ ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService', '$timeout',
+ function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService, $timeout) {
+ return {
+ priority: -200, // run after default uiGridCell directive
+ restrict: 'A',
+ require: '?^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ var touchStartTime = 0;
+ var touchTimeout = 300;
+
+ // Bind to keydown events in the render container
+ if (uiGridCtrl.grid.api.cellNav) {
+
+ uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
+ if (rowCol === null ||
+ rowCol.row !== $scope.row ||
+ rowCol.col !== $scope.col) {
+ return;
+ }
+
+ if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ $scope.$apply();
+ }
+
+ // uiGridCellNavService.scrollToIfNecessary(uiGridCtrl.grid, rowCol.row, rowCol.col);
+ });
+ }
+
+ //$elm.bind('keydown', function (evt) {
+ // if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
+ // uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ // $scope.$apply();
+ // }
+ //});
+
+ var selectCells = function(evt){
+ // if you click on expandable icon doesn't trigger selection
+ if (evt.target.className === "ui-grid-icon-minus-squared" || evt.target.className === "ui-grid-icon-plus-squared") {
+ return;
+ }
+
+ // if we get a click, then stop listening for touchend
+ $elm.off('touchend', touchEnd);
+
+ if (evt.shiftKey) {
+ uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
+ }
+ else if (evt.ctrlKey || evt.metaKey) {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
+ }
+ else {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ }
+ $scope.$apply();
+
+ // don't re-enable the touchend handler for a little while - some devices generate both, and it will
+ // take a little while to move your hand from the mouse to the screen if you have both modes of input
+ $timeout(function() {
+ $elm.on('touchend', touchEnd);
+ }, touchTimeout);
+ };
+
+ var touchStart = function(evt){
+ touchStartTime = (new Date()).getTime();
+
+ // if we get a touch event, then stop listening for click
+ $elm.off('click', selectCells);
+ };
+
+ var touchEnd = function(evt) {
+ var touchEndTime = (new Date()).getTime();
+ var touchTime = touchEndTime - touchStartTime;
+
+ if (touchTime < touchTimeout ) {
+ // short touch
+ selectCells(evt);
+ }
+
+ // don't re-enable the click handler for a little while - some devices generate both, and it will
+ // take a little while to move your hand from the screen to the mouse if you have both modes of input
+ $timeout(function() {
+ $elm.on('click', selectCells);
+ }, touchTimeout);
+ };
+
+ function registerRowSelectionEvents() {
+ if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection) {
+ $elm.addClass('ui-grid-disable-selection');
+ $elm.on('touchstart', touchStart);
+ $elm.on('touchend', touchEnd);
+ $elm.on('click', selectCells);
+
+ $scope.registered = true;
+ }
+ }
+
+ function deregisterRowSelectionEvents() {
+ if ($scope.registered){
+ $elm.removeClass('ui-grid-disable-selection');
+
+ $elm.off('touchstart', touchStart);
+ $elm.off('touchend', touchEnd);
+ $elm.off('click', selectCells);
+
+ $scope.registered = false;
+ }
+ }
+
+ registerRowSelectionEvents();
+ // register a dataChange callback so that we can change the selection configuration dynamically
+ // if the user changes the options
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {
+ if ( $scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
+ !$scope.registered ){
+ registerRowSelectionEvents();
+ } else if ( ( !$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection ) &&
+ $scope.registered ){
+ deregisterRowSelectionEvents();
+ }
+ }, [uiGridConstants.dataChange.OPTIONS] );
+
+ $elm.on( '$destroy', dataChangeDereg);
+ }
+ };
+ }]);
+
+ module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ priority: -1000,
+ require: '^uiGrid',
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ if (!uiGridCtrl.grid.options.showGridFooter) {
+ return;
+ }
+
+
+ gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+
+ angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.treeBase
+ * @description
+ *
+ * # ui.grid.treeBase
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides base tree handling functions that are shared by other features, notably grouping
+ * and treeView. It provides a tree view of the data, with nodes in that
+ * tree and leaves.
+ *
+ * Design information:
+ * -------------------
+ *
+ * The raw data that is provided must come with a $$treeLevel on any non-leaf node. Grouping will create
+ * these on all the group header rows, treeView will expect these to be set in the raw data by the user.
+ * TreeBase will run a rowsProcessor that:
+ * - builds `treeBase.tree` out of the provided rows
+ * - permits a recursive sort of the tree
+ * - maintains the expand/collapse state of each node
+ * - provides the expand/collapse all button and the expand/collapse buttons
+ * - maintains the count of children for each node
+ *
+ * Each row is updated with a link to the tree node that represents it. Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}
+ * for information.
+ *
+ * TreeBase adds information to the rows
+ * - treeLevel: if present and > -1 tells us the level (level 0 is the top level)
+ * - treeNode: pointer to the node in the grid.treeBase.tree that refers
+ * to this row, allowing us to manipulate the state
+ *
+ * Since the logic is baked into the rowsProcessors, it should get triggered whenever
+ * row order or filtering or anything like that is changed. We recall the expanded state
+ * across invocations of the rowsProcessors by the reference to the treeNode on the individual
+ * rows. We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to
+ * get the state, but we overwrite the other data in that treeNode.
+ *
+ * By default rows are collapsed, which means all data rows have their visible property
+ * set to false, and only level 0 group rows are set to visible.
+ *
+ * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into
+ * grid.treeBase.tree, then call refresh. This is because we can't easily change the visible
+ * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as
+ * well use it all the time.
+ *
+ * Tree base provides sorting (on non-grouped columns).
+ *
+ * Sorting works in two passes. The standard sorting is performed for any columns that are important to building
+ * the tree (for example, any grouped columns). Then after the tree is built, a recursive tree sort is performed
+ * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level
+ * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).
+ *
+ * To achieve this we make use of the `ignoreSort` property on the sort configuration. The parent feature (treeView or grouping)
+ * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets
+ * the `ignoreSort`on any sort that it wants to run on the tree. TreeBase will clear the ignoreSort on all sorts - so it
+ * will turn on any sorts that haven't run. It will then call a recursive sort on the tree.
+ *
+ * Tree base provides treeAggregation. It checks the treeAggregation configuration on each column, and aggregates based on
+ * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,
+ * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the
+ * treeAggregations in the column footer. Aggregation information will be collected in the format:
+ *
+ * ```
+ * {
+ * type: 'count',
+ * value: 4,
+ * label: 'count: ',
+ * rendered: 'count: 4'
+ * }
+ * ```
+ *
+ * A callback is provided to format the value once it is finalised (aka a valueFilter).
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.treeBase"></div>
+ */
+
+ var module = angular.module('ui.grid.treeBase', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.constant:uiGridTreeBaseConstants
+ *
+ * @description constants available in treeBase module.
+ *
+ * These constants are manually copied into grouping and treeView,
+ * as I haven't found a way to simply include them, and it's not worth
+ * investing time in for something that changes very infrequently.
+ *
+ */
+ module.constant('uiGridTreeBaseConstants', {
+ featureName: "treeBase",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.treeBase.service:uiGridTreeBaseService
+ *
+ * @description Services for treeBase feature
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:ColumnDef
+ *
+ * @description ColumnDef for tree feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',
+ function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.grid:treeBase
+ *
+ * @description Grid properties and functions added for treeBase
+ */
+ grid.treeBase = {};
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name numberLevels
+ *
+ * @description Total number of tree levels currently used, calculated by the rowsProcessor by
+ * retaining the highest tree level it sees
+ */
+ grid.treeBase.numberLevels = 0;
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name expandAll
+ *
+ * @description Whether or not the expandAll box is selected
+ */
+ grid.treeBase.expandAll = false;
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name tree
+ *
+ * @description Tree represented as a nested array that holds the state of each node, along with a
+ * pointer to the row. The array order is material - we will display the children in the order
+ * they are stored in the array
+ *
+ * Each node stores:
+ *
+ * - the state of this node
+ * - an array of children of this node
+ * - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)
+ * - the number of children of this node
+ * - aggregation information calculated from the nodes
+ *
+ * ```
+ * [{
+ * state: 'expanded',
+ * row: <reference to row>,
+ * parentRow: null,
+ * aggregations: [{
+ * type: 'count',
+ * col: <gridCol>,
+ * value: 2,
+ * label: 'count: ',
+ * rendered: 'count: 2'
+ * }],
+ * children: [
+ * {
+ * state: 'expanded',
+ * row: <reference to row>,
+ * parentRow: <reference to row>,
+ * aggregations: [{
+ * type: 'count',
+ * col: '<gridCol>,
+ * value: 4,
+ * label: 'count: ',
+ * rendered: 'count: 4'
+ * }],
+ * children: [
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }
+ * ]
+ * },
+ * {
+ * state: 'collapsed',
+ * row: <reference to row>,
+ * parentRow: <reference to row>,
+ * aggregations: [{
+ * type: 'count',
+ * col: <gridCol>,
+ * value: 3,
+ * label: 'count: ',
+ * rendered: 'count: 3'
+ * }],
+ * children: [
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }
+ * ]
+ * }
+ * ]
+ * }, {<another level 0 node maybe>} ]
+ * ```
+ * Missing state values are false - meaning they aren't expanded.
+ *
+ * This is used because the rowProcessors run every time the grid is refreshed, so
+ * we'd lose the expanded state every time the grid was refreshed. This instead gives
+ * us a reliable lookup that persists across rowProcessors.
+ *
+ * This tree is rebuilt every time we run the rowsProcessors. Since each row holds a pointer
+ * to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard
+ * all transient information on the tree (children, childCount) and recalculate it
+ *
+ */
+ grid.treeBase.tree = [];
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerRowsProcessor(service.treeRows, 410);
+
+ grid.registerColumnBuilder( service.treeBaseColumnBuilder );
+
+ service.createRowHeader( grid );
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:PublicApi
+ *
+ * @description Public Api for treeBase feature
+ */
+ var publicApi = {
+ events: {
+ treeBase: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.treeBase.api:PublicApi
+ * @name rowExpanded
+ * @description raised whenever a row is expanded. If you are dynamically
+ * rendering your tree you can listen to this event, and then retrieve
+ * the children of this row and load them into the grid data.
+ *
+ * When the data is loaded the grid will automatically refresh to show these new rows
+ *
+ * <pre>
+ * gridApi.treeBase.on.rowExpanded(scope,function(row){})
+ * </pre>
+ * @param {gridRow} row the row that was expanded. You can also
+ * retrieve the grid from this row with row.grid
+ */
+ rowExpanded: {},
+
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.treeBase.api:PublicApi
+ * @name rowCollapsed
+ * @description raised whenever a row is collapsed. Doesn't really have
+ * a purpose at the moment, included for symmetry
+ *
+ * <pre>
+ * gridApi.treeBase.on.rowCollapsed(scope,function(row){})
+ * </pre>
+ * @param {gridRow} row the row that was collapsed. You can also
+ * retrieve the grid from this row with row.grid
+ */
+ rowCollapsed: {}
+ }
+ },
+
+ methods: {
+ treeBase: {
+ /**
+ * @ngdoc function
+ * @name expandAllRows
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Expands all tree rows
+ */
+ expandAllRows: function () {
+ service.expandAllRows(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseAllRows
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse all tree rows
+ */
+ collapseAllRows: function () {
+ service.collapseAllRows(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name toggleRowTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description call expand if the row is collapsed, collapse if it is expanded
+ * @param {gridRow} row the row you wish to toggle
+ */
+ toggleRowTreeState: function (row) {
+ service.toggleRowTreeState(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name expandRow
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description expand the immediate children of the specified row
+ * @param {gridRow} row the row you wish to expand
+ */
+ expandRow: function (row) {
+ service.expandRow(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name expandRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description expand all children of the specified row
+ * @param {gridRow} row the row you wish to expand
+ */
+ expandRowChildren: function (row) {
+ service.expandRowChildren(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseRow
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse the specified row. When
+ * you expand the row again, all grandchildren will retain their state
+ * @param {gridRow} row the row you wish to collapse
+ */
+ collapseRow: function ( row ) {
+ service.collapseRow(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse all children of the specified row. When
+ * you expand the row again, all grandchildren will be collapsed
+ * @param {gridRow} row the row you wish to collapse children for
+ */
+ collapseRowChildren: function ( row ) {
+ service.collapseRowChildren(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name getTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Get the tree state for this grid,
+ * used by the saveState feature
+ * Returned treeState as an object
+ * `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`
+ * where expandedState is a hash of row uid and the current expanded state
+ *
+ * @returns {object} tree state
+ *
+ * TODO - this needs work - we need an identifier that persists across instantiations,
+ * not uid. This really means we need a row identity defined, but that won't work for
+ * grouping. Perhaps this needs to be moved up to treeView and grouping, rather than
+ * being in base.
+ */
+ getTreeExpandedState: function () {
+ return { expandedState: service.getTreeState(grid) };
+ },
+
+ /**
+ * @ngdoc function
+ * @name setTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Set the expanded states of the tree
+ * @param {object} config the config you want to apply, in the format
+ * provided by getTreeState
+ */
+ setTreeState: function ( config ) {
+ service.setTreeState( grid, config );
+ },
+
+ /**
+ * @ngdoc function
+ * @name getRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Get the children of the specified row
+ * @param {GridRow} row the row you want the children of
+ * @returns {Array} array of children of this row, the children
+ * are all gridRows
+ */
+ getRowChildren: function ( row ){
+ return row.treeNode.children.map( function( childNode ){
+ return childNode.row;
+ });
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:GridOptions
+ *
+ * @description GridOptions for treeBase feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name treeRowHeaderBaseWidth
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Base width of the tree header, provides for a single level of tree. This
+ * is incremented by `treeIndent` for each extra level
+ * <br/>Defaults to 30
+ */
+ gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;
+
+ /**
+ * @ngdoc object
+ * @name treeIndent
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,
+ * but will make the tree row header wider
+ * <br/>Defaults to 10
+ */
+ gridOptions.treeIndent = gridOptions.treeIndent || 10;
+
+ /**
+ * @ngdoc object
+ * @name showTreeRowHeader
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to false, don't create the row header. You'll need to programmatically control the expand
+ * states
+ * <br/>Defaults to true
+ */
+ gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;
+
+ /**
+ * @ngdoc object
+ * @name showTreeExpandNoChildren
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to true, show the expand/collapse button even if there are no
+ * children of a node. You'd use this if you're planning to dynamically load the children
+ *
+ * <br/>Defaults to true, grouping overrides to false
+ */
+ gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;
+
+ /**
+ * @ngdoc object
+ * @name treeRowHeaderAlwaysVisible
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to true, row header even if there are no tree nodes
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;
+
+ /**
+ * @ngdoc object
+ * @name treeCustomAggregations
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Define custom aggregation functions. The properties of this object will be
+ * aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.
+ * If a function defined here uses the same name as one of the native aggregations, this one will take precedence.
+ * The object format is:
+ *
+ * <pre>
+ * {
+ * aggregationName: {
+ * label: (optional) string,
+ * aggregationFn: function( aggregation, fieldValue, numValue, row ){...},
+ * finalizerFn: (optional) function( aggregation ){...}
+ * },
+ * mean: {
+ * label: 'mean',
+ * aggregationFn: function( aggregation, fieldValue, numValue ){
+ * aggregation.count = (aggregation.count || 1) + 1;
+ * aggregation.sum = (aggregation.sum || 0) + numValue;
+ * },
+ * finalizerFn: function( aggregation ){
+ * aggregation.value = aggregation.sum / aggregation.count
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to
+ * apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be
+ * rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate
+ * the label and the value.
+ *
+ * <br/>Defaults to {}
+ */
+ gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};
+
+ /**
+ * @ngdoc object
+ * @name enableExpandAll
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Enable the expand all button at the top of the row header
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.enableExpandAll = gridOptions.enableExpandAll !== false;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name treeBaseColumnBuilder
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Sets the tree defaults based on the columnDefs
+ *
+ * @param {object} colDef columnDef we're basing on
+ * @param {GridCol} col the column we're to update
+ * @param {object} gridOptions the options we should use
+ * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
+ */
+ treeBaseColumnBuilder: function (colDef, col, gridOptions) {
+
+
+ /**
+ * @ngdoc object
+ * @name customTreeAggregationFn
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom function that aggregates rows into some form of
+ * total. Aggregations run row-by-row, the function needs to be capable of
+ * creating a running total.
+ *
+ * The function will be provided the aggregation item (in which you can store running
+ * totals), the row value that is to be aggregated, and that same row value converted to
+ * a number (most aggregations work on numbers)
+ * @example
+ * <pre>
+ * customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ){
+ * // calculates the average of the squares of the values
+ * if ( typeof(aggregation.count) === 'undefined' ){
+ * aggregation.count = 0;
+ * }
+ * aggregation.count++;
+ *
+ * if ( !isNaN(numValue) ){
+ * if ( typeof(aggregation.total) === 'undefined' ){
+ * aggregation.total = 0;
+ * }
+ * aggregation.total = aggregation.total + numValue * numValue;
+ * }
+ *
+ * aggregation.value = aggregation.total / aggregation.count;
+ * }
+ * </pre>
+ * <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.
+ */
+ if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ){
+ col.treeAggregationFn = colDef.customTreeAggregationFn;
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationType
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.
+ * Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the
+ * name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.
+ *
+ * <pre>
+ * treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,
+ * }
+ * </pre>
+ *
+ * If you are using aggregations you should either:
+ *
+ * - also use grouping, in which case the aggregations are displayed in the group header, OR
+ * - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and
+ * treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`
+ * in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations
+ *
+ * <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.
+ * <br/>Defaults to undefined.
+ */
+ if ( typeof(colDef.treeAggregationType) !== 'undefined' ){
+ col.treeAggregation = { type: colDef.treeAggregationType };
+ if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ){
+ col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;
+ col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;
+ col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;
+ } else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ){
+ col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;
+ col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;
+ }
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationLabel
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom label to use for this aggregation. If provided we don't use native i18n.
+ */
+ if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ){
+ if (typeof(col.treeAggregation) === 'undefined' ){
+ col.treeAggregation = {};
+ }
+ col.treeAggregation.label = colDef.treeAggregationLabel;
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationUpdateEntity
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description Store calculated aggregations into the entity, allowing them
+ * to be displayed in the grid using a standard cellTemplate. This defaults to true,
+ * if you are using grouping then you shouldn't set it to false, as then the aggregations won't
+ * display.
+ *
+ * If you are using treeView in most cases you'll want to set this to true. This will result in
+ * getCellValue returning the aggregation rather than whatever was stored in the cell attribute on
+ * the entity. If you want to render the underlying entity value (and do something else with the aggregation)
+ * then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.
+ *
+ * <br/>Defaults to true
+ *
+ * @example
+ * <pre>
+ * gridOptions.columns = [{
+ * name: 'myCol',
+ * treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },
+ * treeAggregationUpdateEntity: true
+ * cellTemplate: '<div>{{row.entity.myCol + " " + row.treeNode.aggregations[0].rendered}}</div>'
+ * }];
+ * </pre>
+ */
+ col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;
+
+ /**
+ * @ngdoc object
+ * @name customTreeAggregationFinalizerFn
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom function that populates aggregation.rendered, this is called when
+ * a particular aggregation has been fully calculated, and we want to render the value.
+ *
+ * With the native aggregation options we just concatenate `aggregation.label` and
+ * `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label
+ * or the value, you can do so with this function. This function will be called after the
+ * the default `finalizerFn`.
+ *
+ * @example
+ * <pre>
+ * customTreeAggregationFinalizerFn = function ( aggregation ){
+ * aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';
+ * }
+ * </pre>
+ * <br/>Defaults to undefined.
+ */
+ if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ){
+ col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;
+ }
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createRowHeader
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Create the rowHeader. If treeRowHeaderAlwaysVisible then
+ * set it to visible, otherwise set it to invisible
+ *
+ * @param {Grid} grid grid object
+ */
+ createRowHeader: function( grid ){
+ var rowHeaderColumnDef = {
+ name: uiGridTreeBaseConstants.rowHeaderColName,
+ displayName: '',
+ width: grid.options.treeRowHeaderBaseWidth,
+ minWidth: 10,
+ cellTemplate: 'ui-grid/treeBaseRowHeader',
+ headerCellTemplate: 'ui-grid/treeBaseHeaderCell',
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ exporterSuppressExport: true,
+ allowCellFocus: true
+ };
+
+ rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;
+ grid.addRowHeaderColumn( rowHeaderColumnDef, -100 );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandAllRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands all nodes in the tree
+ *
+ * @param {Grid} grid grid object
+ */
+ expandAllRows: function (grid) {
+ grid.treeBase.tree.forEach( function( node ) {
+ service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);
+ });
+ grid.treeBase.expandAll = true;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseAllRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses all nodes in the tree
+ *
+ * @param {Grid} grid grid object
+ */
+ collapseAllRows: function (grid) {
+ grid.treeBase.tree.forEach( function( node ) {
+ service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);
+ });
+ grid.treeBase.expandAll = false;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setAllNodes
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Works through a subset of grid.treeBase.rowExpandedStates, setting
+ * all child nodes (and their descendents) of the provided node to the given state.
+ *
+ * Calls itself recursively on all nodes so as to achieve this.
+ *
+ * @param {Grid} grid the grid we're operating on (so we can raise events)
+ * @param {object} treeNode a node in the tree that we want to update
+ * @param {string} targetState the state we want to set it to
+ */
+ setAllNodes: function (grid, treeNode, targetState) {
+ if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ){
+ treeNode.state = targetState;
+
+ if ( targetState === uiGridTreeBaseConstants.EXPANDED ){
+ grid.api.treeBase.raise.rowExpanded(treeNode.row);
+ } else {
+ grid.api.treeBase.raise.rowCollapsed(treeNode.row);
+ }
+ }
+
+ // set all child nodes
+ if ( treeNode.children ){
+ treeNode.children.forEach(function( childNode ){
+ service.setAllNodes(grid, childNode, targetState);
+ });
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name toggleRowTreeState
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Toggles the expand or collapse state of this grouped row, if
+ * it's a parent row
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to toggle
+ */
+ toggleRowTreeState: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED){
+ service.collapseRow(grid, row);
+ } else {
+ service.expandRow(grid, row);
+ }
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandRow
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands this specific row, showing only immediate children.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to expand
+ */
+ expandRow: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ){
+ row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;
+ grid.api.treeBase.raise.rowExpanded(row);
+ grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandRowChildren
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands this specific row, showing all children.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to expand
+ */
+ expandRowChildren: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);
+ grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseRow
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses this specific row
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to collapse
+ */
+ collapseRow: function( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ){
+ row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;
+ grid.treeBase.expandAll = false;
+ grid.api.treeBase.raise.rowCollapsed(row);
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseRowChildren
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses this specific row and all children
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to collapse
+ */
+ collapseRowChildren: function( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);
+ grid.treeBase.expandAll = false;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name allExpanded
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Returns true if all rows are expanded, false
+ * if they're not. Walks the tree to determine this. Used
+ * to set the expandAll state.
+ *
+ * If the node has no children, then return true (it's immaterial
+ * whether it is expanded). If the node has children, then return
+ * false if this node is collapsed, or if any child node is not all expanded
+ *
+ * @param {object} tree the grid to check
+ * @returns {boolean} whether or not the tree is all expanded
+ */
+ allExpanded: function( tree ){
+ var allExpanded = true;
+ tree.forEach( function( node ){
+ if ( !service.allExpandedInternal( node ) ){
+ allExpanded = false;
+ }
+ });
+ return allExpanded;
+ },
+
+ allExpandedInternal: function( treeNode ){
+ if ( treeNode.children && treeNode.children.length > 0 ){
+ if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
+ return false;
+ }
+ var allExpanded = true;
+ treeNode.children.forEach( function( node ){
+ if ( !service.allExpandedInternal( node ) ){
+ allExpanded = false;
+ }
+ });
+ return allExpanded;
+ } else {
+ return true;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name treeRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description The rowProcessor that adds the nodes to the tree, and sets the visible
+ * state of each row based on it's parent state
+ *
+ * Assumes it is always called after the sorting processor, and the grouping processor if there is one.
+ * Performs any tree sorts itself after having built the tree
+ *
+ * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated
+ * entity, and setting the visible state based on the parent's state.
+ *
+ * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly
+ * sized.
+ *
+ * Aggregates if necessary along the way.
+ *
+ * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
+ * @returns {array} the updated rows
+ */
+ treeRows: function( renderableRows ) {
+ if (renderableRows.length === 0){
+ return renderableRows;
+ }
+
+ var grid = this;
+ var currentLevel = 0;
+ var currentState = uiGridTreeBaseConstants.EXPANDED;
+ var parents = [];
+
+ grid.treeBase.tree = service.createTree( grid, renderableRows );
+ service.updateRowHeaderWidth( grid );
+
+ service.sortTree( grid );
+ service.fixFilter( grid );
+
+ return service.renderTree( grid.treeBase.tree );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createOrUpdateRowHeaderWidth
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Calculates the rowHeader width.
+ *
+ * If rowHeader is always present, updates the width.
+ *
+ * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there
+ * should be one, then creates or removes it as appropriate, with the created rowHeader having the
+ * right width.
+ *
+ * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`
+ *
+ * @param {Grid} grid the grid we want to set the row header on
+ */
+ updateRowHeaderWidth: function( grid ){
+ var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName);
+
+ var newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);
+ if ( rowHeader && newWidth !== rowHeader.width ){
+ rowHeader.width = newWidth;
+ grid.queueRefresh();
+ }
+
+ var newVisibility = true;
+ if ( grid.options.showTreeRowHeader === false ){
+ newVisibility = false;
+ }
+ if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ){
+ newVisibility = false;
+ }
+ if ( rowHeader.visible !== newVisibility ) {
+ rowHeader.visible = newVisibility;
+ rowHeader.colDef.visible = newVisibility;
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name renderTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates an array of rows based on the tree, exporting only
+ * the visible nodes and leaves
+ *
+ * @param {array} nodeList the list of nodes - can be grid.treeBase.tree, or can be node.children when
+ * we're calling recursively
+ * @returns {array} renderable rows
+ */
+ renderTree: function( nodeList ){
+ var renderableRows = [];
+
+ nodeList.forEach( function ( node ){
+ if ( node.row.visible ){
+ renderableRows.push( node.row );
+ }
+ if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
+ renderableRows = renderableRows.concat( service.renderTree( node.children ) );
+ }
+ });
+ return renderableRows;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates a tree from the renderableRows
+ *
+ * @param {Grid} grid the grid
+ * @param {array} renderableRows the rows we want to create a tree from
+ * @returns {object} the tree we've build
+ */
+ createTree: function( grid, renderableRows ) {
+ var currentLevel = -1;
+ var parents = [];
+ var currentState;
+ grid.treeBase.tree = [];
+ grid.treeBase.numberLevels = 0;
+ var aggregations = service.getAggregations( grid );
+
+ var createNode = function( row ){
+ if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ){
+ row.treeLevel = row.entity.$$treeLevel;
+ }
+
+ if ( row.treeLevel <= currentLevel ){
+ // pop any levels that aren't parents of this level, formatting the aggregation at the same time
+ while ( row.treeLevel <= currentLevel ){
+ var lastParent = parents.pop();
+ service.finaliseAggregations( lastParent );
+ currentLevel--;
+ }
+
+ // reset our current state based on the new parent, set to expanded if this is a level 0 node
+ if ( parents.length > 0 ){
+ currentState = service.setCurrentState(parents);
+ } else {
+ currentState = uiGridTreeBaseConstants.EXPANDED;
+ }
+ }
+
+ // aggregate if this is a leaf node
+ if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible ){
+ service.aggregate( grid, row, parents );
+ }
+
+ // add this node to the tree
+ service.addOrUseNode(grid, row, parents, aggregations);
+
+ if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ){
+ parents.push(row);
+ currentLevel++;
+ currentState = service.setCurrentState(parents);
+ }
+
+ // update the tree number of levels, so we can set header width if we need to
+ if ( grid.treeBase.numberLevels < row.treeLevel + 1){
+ grid.treeBase.numberLevels = row.treeLevel + 1;
+ }
+ };
+
+ renderableRows.forEach( createNode );
+
+ // finalise remaining aggregations
+ while ( parents.length > 0 ){
+ var lastParent = parents.pop();
+ service.finaliseAggregations( lastParent );
+ }
+
+ return grid.treeBase.tree;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addOrUseNode
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates a tree node for this row. If this row already has a treeNode
+ * recorded against it, preserves the state, but otherwise overwrites the data.
+ *
+ * @param {grid} grid the grid we're operating on
+ * @param {gridRow} row the row we want to set
+ * @param {array} parents an array of the parents this row should have
+ * @param {array} aggregationBase empty aggregation information
+ * @returns {undefined} updates the parents array, updates the row to have a treeNode, and updates the
+ * grid.treeBase.tree
+ */
+ addOrUseNode: function( grid, row, parents, aggregationBase ){
+ var newAggregations = [];
+ aggregationBase.forEach( function(aggregation){
+ newAggregations.push(service.buildAggregationObject(aggregation.col));
+ });
+
+ var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };
+ if ( row.treeNode ){
+ newNode.state = row.treeNode.state;
+ }
+ if ( parents.length > 0 ){
+ newNode.parentRow = parents[parents.length - 1];
+ }
+ row.treeNode = newNode;
+
+ if ( parents.length === 0 ){
+ grid.treeBase.tree.push( newNode );
+ } else {
+ parents[parents.length - 1].treeNode.children.push( newNode );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setCurrentState
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Looks at the parents array to determine our current state.
+ * If any node in the hierarchy is collapsed, then return collapsed, otherwise return
+ * expanded.
+ *
+ * @param {array} parents an array of the parents this row should have
+ * @returns {string} the state we should be setting to any nodes we see
+ */
+ setCurrentState: function( parents ){
+ var currentState = uiGridTreeBaseConstants.EXPANDED;
+ parents.forEach( function(parent){
+ if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
+ currentState = uiGridTreeBaseConstants.COLLAPSED;
+ }
+ });
+ return currentState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name sortTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Performs a recursive sort on the tree nodes, sorting the
+ * children of each node and putting them back into the children array.
+ *
+ * Before doing this it turns back on all the sortIgnore - things that were previously
+ * ignored we process now. Since we're sorting within the nodes, presumably anything
+ * that was already sorted is how we derived the nodes, we can keep those sorts too.
+ *
+ * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed
+ * nodes
+ *
+ * @param {Grid} grid the grid to get the aggregation information from
+ * @returns {array} the aggregation information
+ */
+ sortTree: function( grid ){
+ grid.columns.forEach( function( column ) {
+ if ( column.sort && column.sort.ignoreSort ){
+ delete column.sort.ignoreSort;
+ }
+ });
+
+ grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );
+ },
+
+ sortInternal: function( grid, treeList ){
+ var rows = treeList.map( function( node ){
+ return node.row;
+ });
+
+ rows = rowSorter.sort( grid, rows, grid.columns );
+
+ var treeNodes = rows.map( function( row ){
+ return row.treeNode;
+ });
+
+ treeNodes.forEach( function( node ){
+ if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
+ node.children = service.sortInternal( grid, node.children );
+ }
+ });
+
+ return treeNodes;
+ },
+
+ /**
+ * @ngdoc function
+ * @name fixFilter
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description After filtering has run, we need to go back through the tree
+ * and make sure the parent rows are always visible if any of the child rows
+ * are visible (filtering may make a child visible, but the parent may not
+ * match the filter criteria)
+ *
+ * This has a risk of being computationally expensive, we do it by walking
+ * the tree and remembering whether there are any invisible nodes on the
+ * way down.
+ *
+ * @param {Grid} grid the grid to fix filters on
+ */
+ fixFilter: function( grid ){
+ var parentsVisible;
+
+ grid.treeBase.tree.forEach( function( node ){
+ if ( node.children && node.children.length > 0 ){
+ parentsVisible = node.row.visible;
+ service.fixFilterInternal( node.children, parentsVisible );
+ }
+ });
+ },
+
+ fixFilterInternal: function( nodes, parentsVisible) {
+ nodes.forEach( function( node ){
+ if ( node.row.visible && !parentsVisible ){
+ service.setParentsVisible( node );
+ parentsVisible = true;
+ }
+
+ if ( node.children && node.children.length > 0 ){
+ if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {
+ parentsVisible = true;
+ }
+ }
+ });
+
+ return parentsVisible;
+ },
+
+ setParentsVisible: function( node ){
+ while ( node.parentRow ){
+ node.parentRow.visible = true;
+ node = node.parentRow.treeNode;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name buildAggregationObject
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Build the object which is stored on the column for holding meta-data about the aggregation.
+ * This method should only be called with columns which have an aggregation.
+ *
+ * @param {Column} the column which this object relates to
+ * @returns {object} {col: Column object, label: string, type: string (optional)}
+ */
+ buildAggregationObject: function( column ){
+ var newAggregation = { col: column };
+
+ if ( column.treeAggregation && column.treeAggregation.type ){
+ newAggregation.type = column.treeAggregation.type;
+ }
+
+ if ( column.treeAggregation && column.treeAggregation.label ){
+ newAggregation.label = column.treeAggregation.label;
+ }
+
+ return newAggregation;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getAggregations
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Looks through the grid columns to find those with aggregations,
+ * and collates the aggregation information into an array, returns that array
+ *
+ * @param {Grid} grid the grid to get the aggregation information from
+ * @returns {array} the aggregation information
+ */
+ getAggregations: function( grid ){
+ var aggregateArray = [];
+
+ grid.columns.forEach( function(column){
+ if ( typeof(column.treeAggregationFn) !== 'undefined' ){
+ aggregateArray.push( service.buildAggregationObject(column) );
+
+ if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ){
+ // Add aggregation object for footer
+ column.treeFooterAggregation = service.buildAggregationObject(column);
+ column.aggregationType = service.treeFooterAggregationType;
+ }
+ }
+ });
+ return aggregateArray;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name aggregate
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Accumulate the data from this row onto the aggregations for each parent
+ *
+ * Iterate over the parents, then iterate over the aggregations for each of those parents,
+ * and perform the aggregation for each individual aggregation
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to set grouping visibility on
+ * @param {array} parents the parents that we would want to aggregate onto
+ */
+ aggregate: function( grid, row, parents ){
+ if ( parents.length === 0 && row.treeNode && row.treeNode.aggregations ){
+ row.treeNode.aggregations.forEach(function(aggregation){
+ // Calculate aggregations for footer even if there are no grouped rows
+ if ( typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ) {
+ var fieldValue = grid.getCellValue(row, aggregation.col);
+ var numValue = Number(fieldValue);
+ aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
+ }
+ });
+ }
+
+ parents.forEach( function( parent, index ){
+ if ( parent.treeNode.aggregations ){
+ parent.treeNode.aggregations.forEach( function( aggregation ){
+ var fieldValue = grid.getCellValue(row, aggregation.col);
+ var numValue = Number(fieldValue);
+ aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);
+
+ if ( index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ){
+ aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
+ }
+ });
+ }
+ });
+ },
+
+
+ // Aggregation routines - no doco needed as self evident
+ nativeAggregations: function() {
+ var nativeAggregations = {
+ count: {
+ label: i18nService.get().aggregation.count,
+ menuTitle: i18nService.get().grouping.aggregate_count,
+ aggregationFn: function (aggregation, fieldValue, numValue) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = 1;
+ } else {
+ aggregation.value++;
+ }
+ }
+ },
+
+ sum: {
+ label: i18nService.get().aggregation.sum,
+ menuTitle: i18nService.get().grouping.aggregate_sum,
+ aggregationFn: function( aggregation, fieldValue, numValue ) {
+ if (!isNaN(numValue)) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = numValue;
+ } else {
+ aggregation.value += numValue;
+ }
+ }
+ }
+ },
+
+ min: {
+ label: i18nService.get().aggregation.min,
+ menuTitle: i18nService.get().grouping.aggregate_min,
+ aggregationFn: function( aggregation, fieldValue, numValue ) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = fieldValue;
+ } else {
+ if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {
+ aggregation.value = fieldValue;
+ }
+ }
+ }
+ },
+
+ max: {
+ label: i18nService.get().aggregation.max,
+ menuTitle: i18nService.get().grouping.aggregate_max,
+ aggregationFn: function( aggregation, fieldValue, numValue ){
+ if ( typeof(aggregation.value) === 'undefined' ){
+ aggregation.value = fieldValue;
+ } else {
+ if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)){
+ aggregation.value = fieldValue;
+ }
+ }
+ }
+ },
+
+ avg: {
+ label: i18nService.get().aggregation.avg,
+ menuTitle: i18nService.get().grouping.aggregate_avg,
+ aggregationFn: function( aggregation, fieldValue, numValue ){
+ if ( typeof(aggregation.count) === 'undefined' ){
+ aggregation.count = 1;
+ } else {
+ aggregation.count++;
+ }
+
+ if ( isNaN(numValue) ){
+ return;
+ }
+
+ if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ){
+ aggregation.value = numValue;
+ aggregation.sum = numValue;
+ } else {
+ aggregation.sum += numValue;
+ aggregation.value = aggregation.sum / aggregation.count;
+ }
+ }
+ }
+ };
+ return nativeAggregations;
+ },
+
+ /**
+ * @ngdoc function
+ * @name finaliseAggregation
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Helper function used to finalize aggregation nodes and footer cells
+ *
+ * @param {gridRow} row the parent we're finalising
+ * @param {aggregation} the aggregation object manipulated by the aggregationFn
+ */
+ finaliseAggregation: function(row, aggregation){
+ if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ){
+ angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);
+ }
+
+ if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ){
+ aggregation.col.treeAggregationFinalizerFn( aggregation );
+ }
+ if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ){
+ aggregation.col.customTreeAggregationFinalizerFn( aggregation );
+ }
+ if ( typeof(aggregation.rendered) === 'undefined' ){
+ aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name finaliseAggregations
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Format the data from the aggregation into the rendered text
+ * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.
+ *
+ * As part of this we call any formatting callback routines we've been provided.
+ *
+ * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is
+ * set on the column - we don't overwrite any information that's already there, we append
+ * to it so that grouping can have set the groupVal beforehand without us overwriting it.
+ *
+ * We need to copy the data from the row.entity first before we finalise the aggregation,
+ * we need that information for the finaliserFn
+ *
+ * @param {gridRow} row the parent we're finalising
+ */
+ finaliseAggregations: function( row ){
+ if ( row == null || typeof(row.treeNode.aggregations) === 'undefined' ){
+ return;
+ }
+
+ row.treeNode.aggregations.forEach( function( aggregation ) {
+ service.finaliseAggregation(row, aggregation);
+
+ if ( aggregation.col.treeAggregationUpdateEntity ){
+ var aggregationCopy = {};
+ angular.forEach( aggregation, function( value, key ){
+ if ( aggregation.hasOwnProperty(key) && key !== 'col' ){
+ aggregationCopy[key] = value;
+ }
+ });
+
+ row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;
+ }
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name treeFooterAggregationType
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Uses the tree aggregation functions and finalizers to set the
+ * column footer aggregations.
+ *
+ * @param {rows} visible rows. not used, but accepted to match signature of GridColumn.aggregationType
+ * @param {gridColumn} the column we are finalizing
+ */
+ treeFooterAggregationType: function( rows, column ) {
+ service.finaliseAggregation(undefined, column.treeFooterAggregation);
+ if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ){
+ // The was apparently no aggregation performed (perhaps this is a grouped column
+ return '';
+ }
+ return column.treeFooterAggregation.rendered;
+ }
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons
+ * @element div
+ *
+ * @description Provides the expand/collapse button on rows
+ */
+ module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',
+ function ($templateCache, uiGridTreeBaseService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),
+ scope: true,
+ require: '^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = uiGridCtrl.grid;
+ $scope.treeButtonClick = function(row, evt) {
+ uiGridTreeBaseService.toggleRowTreeState(self, row, evt);
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons
+ * @element div
+ *
+ * @description Provides the expand/collapse all button
+ */
+ module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',
+ function ($templateCache, uiGridTreeBaseService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),
+ scope: false,
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = $scope.col.grid;
+
+ $scope.headerButtonClick = function(row, evt) {
+ if ( self.treeBase.expandAll ){
+ uiGridTreeBaseService.collapseAllRows(self, evt);
+ } else {
+ uiGridTreeBaseService.expandAllRows(self, evt);
+ }
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
+ function ($compile, uiGridConstants, gridUtil, $parse) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-tree-header-row': row.treeLevel > -1}";
+ } else {
+ newNgClass = "{'ui-grid-tree-header-row': row.treeLevel > -1}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.treeView
+ * @description
+ *
+ * # ui.grid.treeView
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides a tree view of the data that it is provided, with nodes in that
+ * tree and leaves. Unlike grouping, the tree is an inherent property of the data and must
+ * be provided with your data array.
+ *
+ * Design information:
+ * -------------------
+ *
+ * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around
+ * that logic. Most of the design information has now moved to treebase.
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.treeView"></div>
+ */
+
+ var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.constant:uiGridTreeViewConstants
+ *
+ * @description constants available in treeView module, this includes
+ * all the constants declared in the treeBase module (these are manually copied
+ * as there isn't an easy way to include constants in another constants file, and
+ * we don't want to make users include treeBase)
+ *
+ */
+ module.constant('uiGridTreeViewConstants', {
+ featureName: "treeView",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.treeView.service:uiGridTreeViewService
+ *
+ * @description Services for treeView features
+ */
+ module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',
+ function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+ uiGridTreeBaseService.initializeGrid( grid, $scope );
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.grid:treeView
+ *
+ * @description Grid properties and functions added for treeView
+ */
+ grid.treeView = {};
+
+ grid.registerRowsProcessor(service.adjustSorting, 60);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.api:PublicApi
+ *
+ * @description Public Api for treeView feature
+ */
+ var publicApi = {
+ events: {
+ treeView: {
+ }
+ },
+ methods: {
+ treeView: {
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.api:GridOptions
+ *
+ * @description GridOptions for treeView feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ *
+ * Many tree options are set on treeBase, make sure to look at that feature in
+ * conjunction with these options.
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableTreeView
+ * @propertyOf ui.grid.treeView.api:GridOptions
+ * @description Enable row tree view for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableTreeView = gridOptions.enableTreeView !== false;
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustSorting
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Trees cannot be sorted the same as flat lists of rows -
+ * trees are sorted recursively within each level - so the children of each
+ * node are sorted, but not the full set of rows.
+ *
+ * To achieve this, we suppress the normal sorting by setting ignoreSort on
+ * each of the sort columns. When the treeBase rowsProcessor runs it will then
+ * unignore these, and will perform a recursive sort against the tree that it builds.
+ *
+ * @param {array} renderableRows the rows that we need to pass on through
+ * @returns {array} renderableRows that we passed on through
+ */
+ adjustSorting: function( renderableRows ) {
+ var grid = this;
+
+ grid.columns.forEach( function( column ){
+ if ( column.sort ){
+ column.sort.ignoreSort = true;
+ }
+ });
+
+ return renderableRows;
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeView.directive:uiGridTreeView
+ * @element div
+ * @restrict A
+ *
+ * @description Adds treeView features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+
+ $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-tree-view></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',
+ function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if (uiGridCtrl.grid.options.enableTreeView !== false){
+ uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);
+ }
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.validate
+ * @description
+ *
+ * # ui.grid.validate
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides the ability to validate cells upon change.
+ *
+ * Design information:
+ * -------------------
+ *
+ * Validation is not based on angularjs validation, since it would work only when editing the field.
+ *
+ * Instead it adds custom properties to any field considered as invalid.
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.expandable"></div>
+ */
+
+ var module = angular.module('ui.grid.validate', ['ui.grid']);
+
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.validate.service:uiGridValidateService
+ *
+ * @description Services for validation features
+ */
+ module.service('uiGridValidateService', ['$sce', '$q', '$http', 'i18nService', 'uiGridConstants', function ($sce, $q, $http, i18nService, uiGridConstants) {
+
+ var service = {
+
+ /**
+ * @ngdoc object
+ * @name validatorFactories
+ * @propertyOf ui.grid.validate.service:uiGridValidateService
+ * @description object containing all the factories used to validate data.<br/>
+ * These factories will be in the form <br/>
+ * ```
+ * {
+ * validatorFactory: function(argument) {
+ * return function(newValue, oldValue, rowEntity, colDef) {
+ * return true || false || promise
+ * }
+ * },
+ * messageFunction: function(argument) {
+ * return string
+ * }
+ * }
+ * ```
+ *
+ * Promises should return true or false as result according to the result of validation.
+ */
+ validatorFactories: {},
+
+
+ /**
+ * @ngdoc service
+ * @name setExternalFactoryFunction
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Adds a way to retrieve validators from an external service
+ * <p>Validators from this external service have a higher priority than default
+ * ones
+ * @param {function} externalFactoryFunction a function that accepts name and argument to pass to a
+ * validator factory and that returns an object with the same properties as
+ * you can see in {@link ui.grid.validate.service:uiGridValidateService#properties_validatorFactories validatorFactories}
+ */
+ setExternalFactoryFunction: function(externalFactoryFunction) {
+ service.externalFactoryFunction = externalFactoryFunction;
+ },
+
+ /**
+ * @ngdoc service
+ * @name clearExternalFactory
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Removes any link to external factory from this service
+ */
+ clearExternalFactory: function() {
+ delete service.externalFactoryFunction;
+ },
+
+ /**
+ * @ngdoc service
+ * @name getValidatorFromExternalFactory
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Retrieves a validator by executing a validatorFactory
+ * stored in an external service.
+ * @param {string} name the name of the validator to retrieve
+ * @param {object} argument an argument to pass to the validator factory
+ */
+ getValidatorFromExternalFactory: function(name, argument) {
+ return service.externalFactoryFunction(name, argument).validatorFactory(argument);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getMessageFromExternalFactory
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Retrieves a message stored in an external service.
+ * @param {string} name the name of the validator
+ * @param {object} argument an argument to pass to the message function
+ */
+ getMessageFromExternalFactory: function(name, argument) {
+ return service.externalFactoryFunction(name, argument).messageFunction(argument);
+ },
+
+ /**
+ * @ngdoc service
+ * @name setValidator
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Adds a new validator to the service
+ * @param {string} name the name of the validator, must be unique
+ * @param {function} validatorFactory a factory that return a validatorFunction
+ * @param {function} messageFunction a function that return the error message
+ */
+ setValidator: function(name, validatorFactory, messageFunction) {
+ service.validatorFactories[name] = {
+ validatorFactory: validatorFactory,
+ messageFunction: messageFunction
+ };
+ },
+
+ /**
+ * @ngdoc service
+ * @name getValidator
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Returns a validator registered to the service
+ * or retrieved from the external factory
+ * @param {string} name the name of the validator to retrieve
+ * @param {object} argument an argument to pass to the validator factory
+ * @returns {object} the validator function
+ */
+ getValidator: function(name, argument) {
+ if (service.externalFactoryFunction) {
+ var validator = service.getValidatorFromExternalFactory(name, argument);
+ if (validator) {
+ return validator;
+ }
+ }
+ if (!service.validatorFactories[name]) {
+ throw ("Invalid validator name: " + name);
+ }
+ return service.validatorFactories[name].validatorFactory(argument);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getMessage
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Returns the error message related to the validator
+ * @param {string} name the name of the validator
+ * @param {object} argument an argument to pass to the message function
+ * @returns {string} the error message related to the validator
+ */
+ getMessage: function(name, argument) {
+ if (service.externalFactoryFunction) {
+ var message = service.getMessageFromExternalFactory(name, argument);
+ if (message) {
+ return message;
+ }
+ }
+ return service.validatorFactories[name].messageFunction(argument);
+ },
+
+ /**
+ * @ngdoc service
+ * @name isInvalid
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Returns true if the cell (identified by rowEntity, colDef) is invalid
+ * @param {object} rowEntity the row entity of the cell
+ * @param {object} colDef the colDef of the cell
+ * @returns {boolean} true if the cell is invalid
+ */
+ isInvalid: function (rowEntity, colDef) {
+ return rowEntity['$$invalid'+colDef.name];
+ },
+
+ /**
+ * @ngdoc service
+ * @name setInvalid
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Makes the cell invalid by adding the proper field to the entity
+ * @param {object} rowEntity the row entity of the cell
+ * @param {object} colDef the colDef of the cell
+ */
+ setInvalid: function (rowEntity, colDef) {
+ rowEntity['$$invalid'+colDef.name] = true;
+ },
+
+ /**
+ * @ngdoc service
+ * @name setValid
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Makes the cell valid by removing the proper error field from the entity
+ * @param {object} rowEntity the row entity of the cell
+ * @param {object} colDef the colDef of the cell
+ */
+ setValid: function (rowEntity, colDef) {
+ delete rowEntity['$$invalid'+colDef.name];
+ },
+
+ /**
+ * @ngdoc service
+ * @name setError
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Adds the proper error to the entity errors field
+ * @param {object} rowEntity the row entity of the cell
+ * @param {object} colDef the colDef of the cell
+ * @param {string} validatorName the name of the validator that is failing
+ */
+ setError: function(rowEntity, colDef, validatorName) {
+ if (!rowEntity['$$errors'+colDef.name]) {
+ rowEntity['$$errors'+colDef.name] = {};
+ }
+ rowEntity['$$errors'+colDef.name][validatorName] = true;
+ },
+
+ /**
+ * @ngdoc service
+ * @name clearError
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Removes the proper error from the entity errors field
+ * @param {object} rowEntity the row entity of the cell
+ * @param {object} colDef the colDef of the cell
+ * @param {string} validatorName the name of the validator that is failing
+ */
+ clearError: function(rowEntity, colDef, validatorName) {
+ if (!rowEntity['$$errors'+colDef.name]) {
+ return;
+ }
+ if (validatorName in rowEntity['$$errors'+colDef.name]) {
+ delete rowEntity['$$errors'+colDef.name][validatorName];
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name getErrorMessages
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description returns an array of i18n-ed error messages.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {array} An array of strings containing all the error messages for the cell
+ */
+ getErrorMessages: function(rowEntity, colDef) {
+ var errors = [];
+
+ if (!rowEntity['$$errors'+colDef.name] || Object.keys(rowEntity['$$errors'+colDef.name]).length === 0) {
+ return errors;
+ }
+
+ Object.keys(rowEntity['$$errors'+colDef.name]).sort().forEach(function(validatorName) {
+ errors.push(service.getMessage(validatorName, colDef.validators[validatorName]));
+ });
+
+ return errors;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getFormattedErrors
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description returns the error i18n-ed and formatted in html to be shown inside the page.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
+ * message inside the page (i.e. inside a div)
+ */
+ getFormattedErrors: function(rowEntity, colDef) {
+
+ var msgString = "";
+
+ var errors = service.getErrorMessages(rowEntity, colDef);
+
+ if (!errors.length) {
+ return;
+ }
+
+ errors.forEach(function(errorMsg) {
+ msgString += errorMsg + "<br/>";
+ });
+
+ return $sce.trustAsHtml('<p><b>' + i18nService.getSafeText('validate.error') + '</b></p>' + msgString );
+ },
+
+ /**
+ * @ngdoc function
+ * @name getTitleFormattedErrors
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html
+ * title attribute.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
+ * message inside an html title attribute
+ */
+ getTitleFormattedErrors: function(rowEntity, colDef) {
+
+ var newLine = "\n";
+
+ var msgString = "";
+
+ var errors = service.getErrorMessages(rowEntity, colDef);
+
+ if (!errors.length) {
+ return;
+ }
+
+ errors.forEach(function(errorMsg) {
+ msgString += errorMsg + newLine;
+ });
+
+ return $sce.trustAsHtml(i18nService.getSafeText('validate.error') + newLine + msgString);
+ },
+
+ /**
+ * @ngdoc function
+ * @name getTitleFormattedErrors
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description Executes all validators on a cell (identified by row entity and column definition) and sets or clears errors
+ * @param {object} rowEntity the row entity of the cell we want to run the validators on
+ * @param {object} colDef the column definition of the cell we want to run the validators on
+ * @param {object} newValue the value the user just entered
+ * @param {object} oldValue the value the field had before
+ */
+ runValidators: function(rowEntity, colDef, newValue, oldValue, grid) {
+
+ if (newValue === oldValue) {
+ // If the value has not changed we perform no validation
+ return;
+ }
+
+ if (typeof(colDef.name) === 'undefined' || !colDef.name) {
+ throw new Error('colDef.name is required to perform validation');
+ }
+
+ service.setValid(rowEntity, colDef);
+
+ var validateClosureFactory = function(rowEntity, colDef, validatorName) {
+ return function(value) {
+ if (!value) {
+ service.setInvalid(rowEntity, colDef);
+ service.setError(rowEntity, colDef, validatorName);
+ if (grid) {
+ grid.api.validate.raise.validationFailed(rowEntity, colDef, newValue, oldValue);
+ }
+ }
+ };
+ };
+
+ var promises = [];
+
+ for (var validatorName in colDef.validators) {
+ service.clearError(rowEntity, colDef, validatorName);
+ var msg;
+ var validatorFunction = service.getValidator(validatorName, colDef.validators[validatorName]);
+ // We pass the arguments as oldValue, newValue so they are in the same order
+ // as ng-model validators (modelValue, viewValue)
+ var promise = $q
+ .when(validatorFunction(oldValue, newValue, rowEntity, colDef))
+ .then(validateClosureFactory(rowEntity, colDef, validatorName));
+ promises.push(promise);
+ }
+
+ return $q.all(promises);
+ },
+
+ /**
+ * @ngdoc function
+ * @name createDefaultValidators
+ * @methodOf ui.grid.validate.service:uiGridValidateService
+ * @description adds the basic validators to the list of service validators
+ */
+ createDefaultValidators: function() {
+ service.setValidator('minLength',
+ function (argument) {
+ return function (oldValue, newValue, rowEntity, colDef) {
+ if (newValue === undefined || newValue === null || newValue === '') {
+ return true;
+ }
+ return newValue.length >= argument;
+ };
+ },
+ function(argument) {
+ return i18nService.getSafeText('validate.minLength').replace('THRESHOLD', argument);
+ });
+
+ service.setValidator('maxLength',
+ function (argument) {
+ return function (oldValue, newValue, rowEntity, colDef) {
+ if (newValue === undefined || newValue === null || newValue === '') {
+ return true;
+ }
+ return newValue.length <= argument;
+ };
+ },
+ function(threshold) {
+ return i18nService.getSafeText('validate.maxLength').replace('THRESHOLD', threshold);
+ });
+
+ service.setValidator('required',
+ function (argument) {
+ return function (oldValue, newValue, rowEntity, colDef) {
+ if (argument) {
+ return !(newValue === undefined || newValue === null || newValue === '');
+ }
+ return true;
+ };
+ },
+ function(argument) {
+ return i18nService.getSafeText('validate.required');
+ });
+ },
+
+ initializeGrid: function (scope, grid) {
+ grid.validate = {
+
+ isInvalid: service.isInvalid,
+
+ getFormattedErrors: service.getFormattedErrors,
+
+ getTitleFormattedErrors: service.getTitleFormattedErrors,
+
+ runValidators: service.runValidators
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.validate.api:PublicApi
+ *
+ * @description Public Api for validation feature
+ */
+ var publicApi = {
+ events: {
+ validate: {
+ /**
+ * @ngdoc event
+ * @name validationFailed
+ * @eventOf ui.grid.validate.api:PublicApi
+ * @description raised when one or more failure happened during validation
+ * <pre>
+ * gridApi.validate.on.validationFailed(scope, function(rowEntity, colDef, newValue, oldValue){...})
+ * </pre>
+ * @param {object} rowEntity the options.data element whose validation failed
+ * @param {object} colDef the column whose validation failed
+ * @param {object} newValue new value
+ * @param {object} oldValue old value
+ */
+ validationFailed: function (rowEntity, colDef, newValue, oldValue) {
+ }
+ }
+ },
+ methods: {
+ validate: {
+ /**
+ * @ngdoc function
+ * @name isInvalid
+ * @methodOf ui.grid.validate.api:PublicApi
+ * @description checks if a cell (identified by rowEntity, colDef) is invalid
+ * @param {object} rowEntity gridOptions.data[] array instance we want to check
+ * @param {object} colDef the column whose errors we want to check
+ * @returns {boolean} true if the cell value is not valid
+ */
+ isInvalid: function(rowEntity, colDef) {
+ return grid.validate.isInvalid(rowEntity, colDef);
+ },
+ /**
+ * @ngdoc function
+ * @name getErrorMessages
+ * @methodOf ui.grid.validate.api:PublicApi
+ * @description returns an array of i18n-ed error messages.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {array} An array of strings containing all the error messages for the cell
+ */
+ getErrorMessages: function (rowEntity, colDef) {
+ return grid.validate.getErrorMessages(rowEntity, colDef);
+ },
+ /**
+ * @ngdoc function
+ * @name getFormattedErrors
+ * @methodOf ui.grid.validate.api:PublicApi
+ * @description returns the error i18n-ed and formatted in html to be shown inside the page.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
+ * message inside the page (i.e. inside a div)
+ */
+ getFormattedErrors: function (rowEntity, colDef) {
+ return grid.validate.getFormattedErrors(rowEntity, colDef);
+ },
+ /**
+ * @ngdoc function
+ * @name getTitleFormattedErrors
+ * @methodOf ui.grid.validate.api:PublicApi
+ * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html
+ * title attribute.
+ * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
+ * @param {object} colDef the column whose errors we are looking for
+ * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
+ * message inside an html title attribute
+ */
+ getTitleFormattedErrors: function (rowEntity, colDef) {
+ return grid.validate.getTitleFormattedErrors(rowEntity, colDef);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ if (grid.edit) {
+ grid.api.edit.on.afterCellEdit(scope, function(rowEntity, colDef, newValue, oldValue) {
+ grid.validate.runValidators(rowEntity, colDef, newValue, oldValue, grid);
+ });
+ }
+
+ service.createDefaultValidators();
+ }
+
+ };
+
+ return service;
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.validate.directive:uiGridValidate
+ * @element div
+ * @restrict A
+ * @description Adds validating features to the ui-grid directive.
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.edit', 'ui.grid.validate']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true, validators: {minLength: 3, maxLength: 9}, cellTemplate: 'ui-grid/cellTitleValidator'},
+ {name: 'title', enableCellEdit: true, validators: {required: true}, cellTemplate: 'ui-grid/cellTitleValidator'}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit ui-grid-validate></div>
+ </div>
+ </file>
+ </example>
+ */
+
+ module.directive('uiGridValidate', ['gridUtil', 'uiGridValidateService', function (gridUtil, uiGridValidateService) {
+ return {
+ priority: 0,
+ replace: true,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridValidateService.initializeGrid($scope, uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+angular.module('ui.grid').run(['$templateCache', function($templateCache) {
+ 'use strict';
+
+ $templateCache.put('ui-grid/ui-grid-filter',
+ "<div class=\"ui-grid-filter-container\" ng-style=\"col.extraStyle\" ng-repeat=\"colFilter in col.filters\" ng-class=\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\"><div ng-if=\"colFilter.type !== 'select'\"><input type=\"text\" class=\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\" aria-label=\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\"><div role=\"button\" class=\"ui-grid-filter-button\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div><div ng-if=\"colFilter.type === 'select'\"><select class=\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-show=\"colFilter.selectOptions.length > 0\" ng-attr-placeholder=\"{{colFilter.placeholder || aria.defaultFilterLabel}}\" aria-label=\"{{colFilter.ariaLabel || ''}}\" ng-options=\"option.value as option.label for option in colFilter.selectOptions\"><option value=\"\"></option></select><div role=\"button\" class=\"ui-grid-filter-button-select\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term != null\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-footer',
+ "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\"><!-- tfooter --><div class=\"ui-grid-footer ui-grid-footer-viewport\"><div class=\"ui-grid-footer-canvas\"><div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-footer-cell-row\"><div ui-grid-footer-cell role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\"></div></div></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-grid-footer',
+ "<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-group-panel',
+ "<div class=\"ui-grid-group-panel\"><div ui-t=\"groupPanel.description\" class=\"description\" ng-show=\"groupings.length == 0\"></div><ul ng-show=\"groupings.length > 0\" class=\"ngGroupList\"><li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\"><span class=\"ngGroupElement\"><span class=\"ngGroupName\">{{group.displayName}} <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span></span> <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span></span></li></ul></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-header',
+ "<div role=\"rowgroup\" class=\"ui-grid-header\"><!-- theader --><div class=\"ui-grid-top-panel\"><div class=\"ui-grid-header-viewport\"><div class=\"ui-grid-header-canvas\"><div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-header-cell-row\"><div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div></div></div></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-menu-button',
+ "<div class=\"ui-grid-menu-button\"><div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-menu\" ui-grid-one-bind-aria-label=\"i18n.aria.buttonLabel\">&nbsp;</i></div><div ui-grid-menu menu-items=\"menuItems\"></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-no-header',
+ "<div class=\"ui-grid-top-panel\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-row',
+ "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid',
+ "<div ui-i18n=\"en\" class=\"ui-grid\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\n" +
+ " /* Styles for the grid */\n" +
+ " }\n" +
+ "\n" +
+ " .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n" +
+ " height: {{ grid.options.rowHeight }}px;\n" +
+ " }\n" +
+ "\n" +
+ " .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n" +
+ " border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\n" +
+ " }\n" +
+ "\n" +
+ " {{ grid.verticalScrollbarStyles }}\n" +
+ " {{ grid.horizontalScrollbarStyles }}\n" +
+ "\n" +
+ " /*\n" +
+ " .ui-grid[dir=rtl] .ui-grid-viewport {\n" +
+ " padding-left: {{ grid.verticalScrollbarWidth }}px;\n" +
+ " }\n" +
+ " */\n" +
+ "\n" +
+ " {{ grid.customStyles }}</style><div class=\"ui-grid-contents-wrapper\"><div ui-grid-menu-button ng-if=\"grid.options.enableGridMenu\"></div><div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\"></div><div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\" enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div><div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\"></div><div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\"></div><div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\"></div><div ng-transclude></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridCell',
+ "<div class=\"ui-grid-cell-contents\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridColumnMenu',
+ "<div class=\"ui-grid-column-menu\"><div ui-grid-menu menu-items=\"menuItems\"><!-- <div class=\"ui-grid-column-menu\">\n" +
+ " <div class=\"inner\" ng-show=\"menuShown\">\n" +
+ " <ul>\n" +
+ " <div ng-show=\"grid.options.enableSorting\">\n" +
+ " <li ng-click=\"sortColumn($event, asc)\" ng-class=\"{ 'selected' : col.sort.direction == asc }\"><i class=\"ui-grid-icon-sort-alt-up\"></i> Sort Ascending</li>\n" +
+ " <li ng-click=\"sortColumn($event, desc)\" ng-class=\"{ 'selected' : col.sort.direction == desc }\"><i class=\"ui-grid-icon-sort-alt-down\"></i> Sort Descending</li>\n" +
+ " <li ng-show=\"col.sort.direction\" ng-click=\"unsortColumn()\"><i class=\"ui-grid-icon-cancel\"></i> Remove Sort</li>\n" +
+ " </div>\n" +
+ " </ul>\n" +
+ " </div>\n" +
+ " </div> --></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridFooterCell',
+ "<div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridHeaderCell',
+ "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\"><div role=\"button\" tabindex=\"0\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\"><span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\"><i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}\" aria-hidden=\"true\"></i> <sub ui-grid-visible=\"isSortPriorityVisible()\" class=\"ui-grid-sort-priority-number\">{{col.sort.priority + 1}}</sub></span></div><div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i></div><div ui-grid-filter></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridMenu',
+ "<div class=\"ui-grid-menu\" ng-if=\"shown\"><style ui-grid-style>{{dynamicStyles}}</style><div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\"><div class=\"ui-grid-menu-inner\"><ul role=\"menu\" class=\"ui-grid-menu-items\"><li ng-repeat=\"item in menuItems\" role=\"menuitem\" ui-grid-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\" action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" screen-reader-only=\"item.screenReaderOnly\"></li></ul></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridMenuItem',
+ "<button type=\"button\" class=\"ui-grid-menu-item\" ng-click=\"itemAction($event, title)\" ng-show=\"itemShown()\" ng-class=\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\" aria-pressed=\"{{active()}}\" tabindex=\"0\" ng-focus=\"focus=true\" ng-blur=\"focus=false\"><i ng-class=\"icon\" aria-hidden=\"true\">&nbsp;</i> {{ name }}</button>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridRenderContainer',
+ "<div role=\"grid\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridViewport',
+ "<div role=\"rowgroup\" class=\"ui-grid-viewport\" ng-style=\"colContainer.getViewportStyle()\"><!-- tbody --><div class=\"ui-grid-canvas\"><div ng-repeat=\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\" class=\"ui-grid-row\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div role=\"row\" ui-grid-row=\"row\" row-render-index=\"rowRenderIndex\"></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/cellEditor',
+ "<div><form name=\"inputForm\"><input type=\"INPUT_TYPE\" ng-class=\"'colt' + col.uid\" ui-grid-editor ng-model=\"MODEL_COL_FIELD\"></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/dropdownEditor',
+ "<div><form name=\"inputForm\"><select ng-class=\"'colt' + col.uid\" ui-grid-edit-dropdown ng-model=\"MODEL_COL_FIELD\" ng-options=\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\"></select></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/fileChooserEditor',
+ "<div><form name=\"inputForm\"><input ng-class=\"'colt' + col.uid\" ui-grid-edit-file-chooser type=\"file\" id=\"files\" name=\"files[]\" ng-model=\"MODEL_COL_FIELD\"></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/emptyBaseLayerContainer',
+ "<div class=\"ui-grid-empty-base-layer-container ui-grid-canvas\"><div class=\"ui-grid-row\" ng-repeat=\"(rowRenderIndex, row) in grid.baseLayer.emptyRows track by $index\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div><div><div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell {{ col.getColClass(false) }}\"></div></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableRow',
+ "<div ui-grid-expandable-row ng-if=\"expandableRow.shouldRenderExpand()\" class=\"expandableRow\" style=\"float:left; margin-top: 1px; margin-bottom: 1px\" ng-style=\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: row.expandedRowHeight + 'px'}\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableRowHeader',
+ "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-if=\"!row.groupHeader==true\" ng-class=\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\" ng-click=\"grid.api.expandable.toggleRowExpansion(row.entity)\"></i></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableScrollFiller',
+ "<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\"><i class=\"ui-grid-icon-spin5 ui-grid-animate-spin\" ng-style=\"{'margin-top': ( row.expandedRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\"></i></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableTopRowHeader',
+ "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-class=\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\" ng-click=\"grid.api.expandable.toggleAllRows()\"></i></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/csvLink',
+ "<span class=\"ui-grid-exporter-csv-link-span\"><a href=\"data:text/csv;charset=UTF-8,CSV_CONTENT\" download=\"FILE_NAME\">LINK_LABEL</a></span>"
+ );
+
+
+ $templateCache.put('ui-grid/importerMenuItem',
+ "<li class=\"ui-grid-menu-item\"><form><input class=\"ui-grid-importer-file-chooser\" type=\"file\" id=\"files\" name=\"files[]\"></form></li>"
+ );
+
+
+ $templateCache.put('ui-grid/importerMenuItemContainer',
+ "<div ui-grid-importer-menu-item></div>"
+ );
+
+
+ $templateCache.put('ui-grid/pagination',
+ "<div role=\"contentinfo\" class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div role=\"menubar\" class=\"ui-grid-pager-control\"><button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div ng-class=\"grid.isRTL() ? 'last-triangle' : 'first-triangle'\"><div ng-class=\"grid.isRTL() ? 'last-bar-rtl' : 'first-bar'\"></div></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div ng-class=\"grid.isRTL() ? 'last-triangle prev-triangle' : 'first-triangle prev-triangle'\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div ng-class=\"grid.isRTL() ? 'first-triangle next-triangle' : 'last-triangle next-triangle'\"></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div ng-class=\"grid.isRTL() ? 'first-triangle' : 'last-triangle'\"><div ng-class=\"grid.isRTL() ? 'first-bar-rtl' : 'last-bar'\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{ 1 + paginationApi.getFirstRowIndex() }} <abbr ui-grid-one-bind-title=\"paginationThrough\">-</abbr> {{ 1 + paginationApi.getLastRowIndex() }} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/columnResizer',
+ "<div ui-grid-column-resizer ng-if=\"grid.options.enableColumnResizing\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/gridFooterSelectedItems',
+ "<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"search.selectedItems\" | t}} {{grid.selection.selectedCount}})</span>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionHeaderCell',
+ "<div><!-- <div class=\"ui-grid-vertical-bar\">&nbsp;</div> --><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-selection-select-all-buttons ng-if=\"grid.options.enableSelectAll\"></ui-grid-selection-select-all-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionRowHeader',
+ "<div class=\"ui-grid-disable-selection\"><div class=\"ui-grid-cell-contents\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionRowHeaderButtons',
+ "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ng-click=\"selectButtonClick(row, $event)\">&nbsp;</div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionSelectAllButtons',
+ "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-click=\"headerButtonClick($event)\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseExpandAllButtons',
+ "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-icon-minus-squared': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, 'ui-grid-icon-plus-squared': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}\" ng-click=\"headerButtonClick($event)\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseHeaderCell',
+ "<div><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-tree-base-expand-all-buttons ng-if=\"grid.options.enableExpandAll\"></ui-grid-tree-base-expand-all-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseRowHeader',
+ "<div class=\"ui-grid-cell-contents\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseRowHeaderButtons',
+ "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\" ng-click=\"treeButtonClick(row, $event)\"><i ng-class=\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\" ng-style=\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\"></i> &nbsp;</div>"
+ );
+
+
+ $templateCache.put('ui-grid/cellTitleValidator',
+ "<div class=\"ui-grid-cell-contents\" ng-class=\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\" title=\"{{grid.validate.getTitleFormattedErrors(row.entity,col.colDef)}}\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
+ );
+
+
+ $templateCache.put('ui-grid/cellTooltipValidator',
+ "<div class=\"ui-grid-cell-contents\" ng-class=\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\" tooltip-html-unsafe=\"{{grid.validate.getFormattedErrors(row.entity,col.colDef)}}\" tooltip-enable=\"grid.validate.isInvalid(row.entity,col.colDef)\" tooltip-append-to-body=\"true\" tooltip-placement=\"top\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
+ );
+
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.css
new file mode 100644
index 00000000..110aefc4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.css
@@ -0,0 +1,4 @@
+/*!
+ * ui-grid - v4.0.2 - 2016-12-30
+ * Copyright (c) 2016 ; License: MIT
+ */#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:before,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{content:" ";display:table}#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{clear:both}.ui-grid{border:1px solid #d4d4d4;box-sizing:content-box;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-o-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}.ui-grid-vertical-bar{position:absolute;right:0;width:0}.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{width:1px}.ui-grid-scrollbar-placeholder{background-color:transparent}.ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#d4d4d4}.ui-grid-clearfix:before,.ui-grid-clearfix:after{content:"";display:table}.ui-grid-clearfix:after{clear:both}.ui-grid-invisible{visibility:hidden}.ui-grid-contents-wrapper{position:relative;height:100%;width:100%}.ui-grid-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.ui-grid-top-panel-background{background:#f3f3f3;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #fff));background:-ms-linear-gradient(bottom, #eee, #fff);background:-moz-linear-gradient(center bottom, #eee 0, #fff 100%);background:-o-linear-gradient(#fff, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-header{border-bottom:1px solid #d4d4d4;box-sizing:border-box}.ui-grid-top-panel{position:relative;overflow:hidden;font-weight:bold;background:#f3f3f3;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #fff));background:-ms-linear-gradient(bottom, #eee, #fff);background:-moz-linear-gradient(center bottom, #eee 0, #fff 100%);background:-o-linear-gradient(#fff, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-top-right-radius:-1px;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:-1px;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-top-right-radius:-1px;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:-1px;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-header-viewport{overflow:hidden}.ui-grid-header-canvas:before,.ui-grid-header-canvas:after{content:"";display:table;line-height:0}.ui-grid-header-canvas:after{clear:both}.ui-grid-header-cell-wrapper{position:relative;display:table;box-sizing:border-box;height:100%}.ui-grid-header-cell-row{display:table-row;position:relative}.ui-grid-header-cell{position:relative;box-sizing:border-box;background-color:inherit;border-right:1px solid;border-color:#d4d4d4;display:table-cell;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:0}.ui-grid-header-cell:last-child{border-right:0}.ui-grid-header-cell .sortable{cursor:pointer}.ui-grid-header-cell .ui-grid-sort-priority-number{margin-left:-8px}.ui-grid-header .ui-grid-vertical-bar{top:0;bottom:0}.ui-grid-column-menu-button{position:absolute;right:1px;top:0}.ui-grid-column-menu-button .ui-grid-icon-angle-down{vertical-align:sub}.ui-grid-column-menu-button-last-col{margin-right:25px}.ui-grid-column-menu{position:absolute}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block !important}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transition:all .05s linear;-moz-transition:all .05s linear;-o-transition:all .05s linear;transition:all .05s linear;display:block !important}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%)}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active{-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.ui-grid-filter-container{padding:4px 10px;position:relative}.ui-grid-filter-container .ui-grid-filter-button{position:absolute;top:0;bottom:0;right:0}.ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"]{position:absolute;top:50%;line-height:32px;margin-top:-16px;right:10px;opacity:.66}.ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"]:hover{opacity:1}.ui-grid-filter-container .ui-grid-filter-button-select{position:absolute;top:0;bottom:0;right:0}.ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"]{position:absolute;top:50%;line-height:32px;margin-top:-16px;right:0;opacity:.66}.ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"]:hover{opacity:1}input[type="text"].ui-grid-filter-input{padding:0;margin:0;border:0;width:100%;border:1px solid #d4d4d4;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}input[type="text"].ui-grid-filter-input:hover{border:1px solid #d4d4d4}select.ui-grid-filter-select{padding:0;margin:0;border:0;width:90%;border:1px solid #d4d4d4;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}select.ui-grid-filter-select:hover{border:1px solid #d4d4d4}.ui-grid-filter-cancel-button-hidden select.ui-grid-filter-select{width:100%}.ui-grid-render-container{position:inherit;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-render-container:focus{outline:none}.ui-grid-viewport{min-height:20px;position:relative;overflow-y:scroll;-webkit-overflow-scrolling:touch}.ui-grid-viewport:focus{outline:none !important}.ui-grid-canvas{position:relative;padding-top:1px}.ui-grid-row{clear:both}.ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#fdfdfd}.ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#f3f3f3}.ui-grid-row:last-child .ui-grid-cell{border-bottom-color:#d4d4d4;border-bottom-style:solid}.ui-grid-no-row-overlay{position:absolute;top:0;bottom:0;left:0;right:0;margin:10%;background:#f3f3f3;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #fff));background:-ms-linear-gradient(bottom, #eee, #fff);background:-moz-linear-gradient(center bottom, #eee 0, #fff 100%);background:-o-linear-gradient(#fff, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #d4d4d4;font-size:2em;text-align:center}.ui-grid-no-row-overlay>*{position:absolute;display:table;margin:auto 0;width:100%;top:0;bottom:0;left:0;right:0;opacity:.66}.ui-grid-cell{overflow:hidden;float:left;background-color:inherit;border-right:1px solid;border-color:#d4d4d4;box-sizing:border-box}.ui-grid-cell:last-child{border-right:0}.ui-grid-cell-contents{padding:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;height:100%}.ui-grid-cell-contents-hidden{visibility:hidden;width:0;height:0;display:none}.ui-grid-row .ui-grid-cell.ui-grid-row-header-cell{background-color:#f0f0ee;border-bottom:solid 1px #d4d4d4}.ui-grid-footer-panel-background{background:#f3f3f3;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #fff));background:-ms-linear-gradient(bottom, #eee, #fff);background:-moz-linear-gradient(center bottom, #eee 0, #fff 100%);background:-o-linear-gradient(#fff, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.ui-grid-footer-panel{position:relative;border-bottom:1px solid #d4d4d4;border-top:1px solid #d4d4d4;overflow:hidden;font-weight:bold;background:#f3f3f3;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #fff));background:-ms-linear-gradient(bottom, #eee, #fff);background:-moz-linear-gradient(center bottom, #eee 0, #fff 100%);background:-o-linear-gradient(#fff, #eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);-webkit-border-top-right-radius:-1px;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:-1px;-moz-border-radius-topright:-1px;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:-1px;border-top-right-radius:-1px;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:-1px;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}.ui-grid-grid-footer{float:left;width:100%}.ui-grid-footer-viewport{overflow:hidden}.ui-grid-footer-canvas{position:relative}.ui-grid-footer-canvas:before,.ui-grid-footer-canvas:after{content:"";display:table;line-height:0}.ui-grid-footer-canvas:after{clear:both}.ui-grid-footer-cell-wrapper{position:relative;display:table;box-sizing:border-box;height:100%}.ui-grid-footer-cell-row{display:table-row}.ui-grid-footer-cell{overflow:hidden;background-color:inherit;border-right:1px solid;border-color:#d4d4d4;box-sizing:border-box;display:table-cell}.ui-grid-footer-cell:last-child{border-right:0}input[type="text"].ui-grid-filter-input{padding:0;margin:0;border:0;width:100%;border:1px solid #d4d4d4;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0;-moz-background-clip:padding-box;-webkit-background-clip:padding-box;background-clip:padding-box}input[type="text"].ui-grid-filter-input:hover{border:1px solid #d4d4d4}.ui-grid-menu-button{z-index:2;position:absolute;right:0;top:0;background:#f3f3f3;border:1px solid #d4d4d4;cursor:pointer;height:31px;font-weight:normal}.ui-grid-menu-button .ui-grid-icon-container{margin-top:3px}.ui-grid-menu-button .ui-grid-menu{right:0}.ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid{overflow:scroll;border:1px solid #d4d4d4}.ui-grid-menu{z-index:2;position:absolute;padding:0 10px 20px 10px;cursor:pointer;box-sizing:border-box}.ui-grid-menu .ui-grid-menu-inner{background:#f3f3f3;border:1px solid #d4d4d4;position:relative;white-space:nowrap;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);box-shadow:0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button{position:absolute;right:0;top:0;display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:1px 1px;font-size:10px;line-height:1;border-radius:2px;color:transparent;background-color:transparent;border-color:transparent}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus{color:#333;text-decoration:none}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,fieldset[disabled] a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button{pointer-events:none}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus{color:transparent;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover{color:transparent;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,.open>.dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button{color:transparent;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:hover,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:hover,.open>.dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,.open>.dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus,.open>.dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus{color:transparent;background-color:rgba(0,0,0,0);border-color:rgba(0,0,0,0)}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,.open>.dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button{background-image:none}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:hover,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:hover,fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:focus,fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.focus,.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].focus,fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus{background-color:transparent;border-color:transparent}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button .badge{color:transparent;background-color:transparent}.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button>i{opacity:.75;color:black}.ui-grid-menu .ui-grid-menu-inner ul{margin:0;padding:0;list-style-type:none}.ui-grid-menu .ui-grid-menu-inner ul li{padding:0}.ui-grid-menu .ui-grid-menu-inner ul li button{min-width:100%;padding:8px;text-align:left;background:transparent;border:none}.ui-grid-menu .ui-grid-menu-inner ul li button:hover,.ui-grid-menu .ui-grid-menu-inner ul li button:focus{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,0.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,0.2);box-shadow:inset 0 0 14px rgba(0,0,0,0.2)}.ui-grid-menu .ui-grid-menu-inner ul li button.ui-grid-menu-item-active{-webkit-box-shadow:inset 0 0 14px rgba(0,0,0,0.2);-moz-box-shadow:inset 0 0 14px rgba(0,0,0,0.2);box-shadow:inset 0 0 14px rgba(0,0,0,0.2);background-color:#cecece}.ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child)>button{border-bottom:1px solid #d4d4d4}.ui-grid-sortarrow{right:5px;position:absolute;width:20px;top:0;bottom:0;background-position:center}.ui-grid-sortarrow.down{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}@font-face{font-family:'ui-grid';src:url('ui-grid.eot');src:url('ui-grid.eot#iefix') format('embedded-opentype'),url('ui-grid.woff') format('woff'),url('ui-grid.ttf') format('truetype'),url('ui-grid.svg?#ui-grid') format('svg');font-weight:normal;font-style:normal}[class^="ui-grid-icon"]:before,[class*=" ui-grid-icon"]:before{font-family:"ui-grid";font-style:normal;font-weight:normal;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em}.ui-grid-icon-blank::before{width:1em;content:' '}.ui-grid-icon-plus-squared:before{content:'\c350'}.ui-grid-icon-minus-squared:before{content:'\c351'}.ui-grid-icon-search:before{content:'\c352'}.ui-grid-icon-cancel:before{content:'\c353'}.ui-grid-icon-info-circled:before{content:'\c354'}.ui-grid-icon-lock:before{content:'\c355'}.ui-grid-icon-lock-open:before{content:'\c356'}.ui-grid-icon-pencil:before{content:'\c357'}.ui-grid-icon-down-dir:before{content:'\c358'}.ui-grid-icon-up-dir:before{content:'\c359'}.ui-grid-icon-left-dir:before{content:'\c35a'}.ui-grid-icon-right-dir:before{content:'\c35b'}.ui-grid-icon-left-open:before{content:'\c35c'}.ui-grid-icon-right-open:before{content:'\c35d'}.ui-grid-icon-angle-down:before{content:'\c35e'}.ui-grid-icon-filter:before{content:'\c35f'}.ui-grid-icon-sort-alt-up:before{content:'\c360'}.ui-grid-icon-sort-alt-down:before{content:'\c361'}.ui-grid-icon-ok:before{content:'\c362'}.ui-grid-icon-menu:before{content:'\c363'}.ui-grid-icon-indent-left:before{content:'\e800'}.ui-grid-icon-indent-right:before{content:'\e801'}.ui-grid-icon-spin5:before{content:'\ea61'}.ui-grid[dir=rtl] .ui-grid-header-cell,.ui-grid[dir=rtl] .ui-grid-footer-cell,.ui-grid[dir=rtl] .ui-grid-cell{float:right !important}.ui-grid[dir=rtl] .ui-grid-column-menu-button{position:absolute;left:1px;top:0;right:inherit}.ui-grid[dir=rtl] .ui-grid-cell:first-child,.ui-grid[dir=rtl] .ui-grid-header-cell:first-child,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child{border-right:0}.ui-grid[dir=rtl] .ui-grid-cell:last-child,.ui-grid[dir=rtl] .ui-grid-header-cell:last-child{border-right:1px solid #d4d4d4;border-left:0}.ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,.ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar{width:0}.ui-grid[dir=rtl] .ui-grid-menu-button{z-index:2;position:absolute;left:0;right:auto;background:#f3f3f3;border:1px solid #d4d4d4;cursor:pointer;min-height:27px;font-weight:normal}.ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu{left:0;right:auto}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button{right:initial;left:0}.ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"]{right:initial;left:10px}.ui-grid-animate-spin{-moz-animation:ui-grid-spin 2s infinite linear;-o-animation:ui-grid-spin 2s infinite linear;-webkit-animation:ui-grid-spin 2s infinite linear;animation:ui-grid-spin 2s infinite linear;display:inline-block}@-moz-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-ms-keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes ui-grid-spin{0%{-moz-transform:rotate(0deg);-o-transform:rotate(0deg);-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-moz-transform:rotate(359deg);-o-transform:rotate(359deg);-webkit-transform:rotate(359deg);transform:rotate(359deg)}}#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:before,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{content:" ";display:table}#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{clear:both}.ui-grid-cell-focus{outline:0;background-color:#b3c4c7}.ui-grid-focuser{position:absolute;left:0;top:0;z-index:-1;width:100%;height:100%}.ui-grid-focuser:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.ui-grid-offscreen{display:block;position:absolute;left:-10000px;top:-10000px;clip:rect(0, 0, 0, 0)}div.ui-grid-cell input{border-radius:inherit;padding:0;width:100%;color:inherit;height:auto;font:inherit;outline:none}div.ui-grid-cell input:focus{color:inherit;outline:none}div.ui-grid-cell input[type="checkbox"]{margin:9px 0 0 6px;width:auto}div.ui-grid-cell input.ng-invalid{border:1px solid #fc8f8f}div.ui-grid-cell input.ng-valid{border:1px solid #d4d4d4}.ui-grid-viewport .ui-grid-empty-base-layer-container{position:absolute;overflow:hidden;pointer-events:none;z-index:-1}.expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell{background-color:#fdfdfd}.expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell{background-color:#f3f3f3}.ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell{pointer-events:none}.ui-grid-expandable-buttons-cell i{pointer-events:all}.scrollFiller{float:left;border:1px solid #d4d4d4}.ui-grid-tree-header-row{font-weight:bold !important}.movingColumn{position:absolute;top:0;border:1px solid #d4d4d4;box-shadow:inset 0 0 14px rgba(0,0,0,0.2)}.movingColumn .ui-grid-icon-angle-down{display:none}#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:before,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{content:" ";display:table}#ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,#ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,#ui-grid-twbs #ui-grid-twbs .btn-group-vertical>.btn-group:after{clear:both}.ui-grid-pager-panel{position:absolute;left:0;bottom:0;width:100%;padding-top:3px;padding-bottom:3px;box-sizing:content-box}.ui-grid-pager-container{float:left}.ui-grid-pager-control{margin-right:10px;margin-left:10px;min-width:135px;float:left}.ui-grid-pager-control button{height:25px;min-width:26px;display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#eee;background-color:#f3f3f3;border-color:#ccc}.ui-grid-pager-control button:focus,.ui-grid-pager-control button:active:focus,.ui-grid-pager-control button.active:focus,.ui-grid-pager-control button.focus,.ui-grid-pager-control button:active.focus,.ui-grid-pager-control button.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.ui-grid-pager-control button:hover,.ui-grid-pager-control button:focus,.ui-grid-pager-control button.focus{color:#333;text-decoration:none}.ui-grid-pager-control button:active,.ui-grid-pager-control button.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.ui-grid-pager-control button.disabled,.ui-grid-pager-control button[disabled],fieldset[disabled] .ui-grid-pager-control button{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.ui-grid-pager-control button.disabled,fieldset[disabled] a.ui-grid-pager-control button{pointer-events:none}.ui-grid-pager-control button:focus,.ui-grid-pager-control button.focus{color:#eee;background-color:#dadada;border-color:#8c8c8c}.ui-grid-pager-control button:hover{color:#eee;background-color:#dadada;border-color:#adadad}.ui-grid-pager-control button:active,.ui-grid-pager-control button.active,.open>.dropdown-toggle.ui-grid-pager-control button{color:#eee;background-color:#dadada;border-color:#adadad}.ui-grid-pager-control button:active:hover,.ui-grid-pager-control button.active:hover,.open>.dropdown-toggle.ui-grid-pager-control button:hover,.ui-grid-pager-control button:active:focus,.ui-grid-pager-control button.active:focus,.open>.dropdown-toggle.ui-grid-pager-control button:focus,.ui-grid-pager-control button:active.focus,.ui-grid-pager-control button.active.focus,.open>.dropdown-toggle.ui-grid-pager-control button.focus{color:#eee;background-color:#c8c8c8;border-color:#8c8c8c}.ui-grid-pager-control button:active,.ui-grid-pager-control button.active,.open>.dropdown-toggle.ui-grid-pager-control button{background-image:none}.ui-grid-pager-control button.disabled:hover,.ui-grid-pager-control button[disabled]:hover,fieldset[disabled] .ui-grid-pager-control button:hover,.ui-grid-pager-control button.disabled:focus,.ui-grid-pager-control button[disabled]:focus,fieldset[disabled] .ui-grid-pager-control button:focus,.ui-grid-pager-control button.disabled.focus,.ui-grid-pager-control button[disabled].focus,fieldset[disabled] .ui-grid-pager-control button.focus{background-color:#f3f3f3;border-color:#ccc}.ui-grid-pager-control button .badge{color:#f3f3f3;background-color:#eee}.ui-grid-pager-control input{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;display:inline;height:26px;width:50px;vertical-align:top}.ui-grid-pager-control input:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.ui-grid-pager-control input::-moz-placeholder{color:#999;opacity:1}.ui-grid-pager-control input:-ms-input-placeholder{color:#999}.ui-grid-pager-control input::-webkit-input-placeholder{color:#999}.ui-grid-pager-control input::-ms-expand{border:0;background-color:transparent}.ui-grid-pager-control input[disabled],.ui-grid-pager-control input[readonly],fieldset[disabled] .ui-grid-pager-control input{background-color:#eee;opacity:1}.ui-grid-pager-control input[disabled],fieldset[disabled] .ui-grid-pager-control input{cursor:not-allowed}textarea.ui-grid-pager-control input{height:auto}select.ui-grid-pager-control input{height:30px;line-height:30px}textarea.ui-grid-pager-control input,select[multiple].ui-grid-pager-control input{height:auto}.ui-grid-pager-control .ui-grid-pager-max-pages-number{vertical-align:bottom}.ui-grid-pager-control .ui-grid-pager-max-pages-number>*{vertical-align:middle}.ui-grid-pager-control .first-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:-3px}.ui-grid-pager-control .first-bar-rtl{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-right:-7px}.ui-grid-pager-control .first-triangle{width:0;height:0;border-style:solid;border-width:5px 8.7px 5px 0;border-color:transparent #4d4d4d transparent transparent;margin-left:2px}.ui-grid-pager-control .next-triangle{margin-left:1px}.ui-grid-pager-control .prev-triangle{margin-left:0}.ui-grid-pager-control .last-triangle{width:0;height:0;border-style:solid;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #4d4d4d;margin-left:-1px}.ui-grid-pager-control .last-bar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:1px}.ui-grid-pager-control .last-bar-rtl{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-right:-11px}.ui-grid-pager-row-count-picker{float:left}.ui-grid-pager-row-count-picker select{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;height:26px;width:67px;display:inline}.ui-grid-pager-row-count-picker select:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.ui-grid-pager-row-count-picker select::-moz-placeholder{color:#999;opacity:1}.ui-grid-pager-row-count-picker select:-ms-input-placeholder{color:#999}.ui-grid-pager-row-count-picker select::-webkit-input-placeholder{color:#999}.ui-grid-pager-row-count-picker select::-ms-expand{border:0;background-color:transparent}.ui-grid-pager-row-count-picker select[disabled],.ui-grid-pager-row-count-picker select[readonly],fieldset[disabled] .ui-grid-pager-row-count-picker select{background-color:#eee;opacity:1}.ui-grid-pager-row-count-picker select[disabled],fieldset[disabled] .ui-grid-pager-row-count-picker select{cursor:not-allowed}textarea.ui-grid-pager-row-count-picker select{height:auto}select.ui-grid-pager-row-count-picker select{height:30px;line-height:30px}textarea.ui-grid-pager-row-count-picker select,select[multiple].ui-grid-pager-row-count-picker select{height:auto}.ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label{margin-top:3px}.ui-grid-pager-count-container{float:right;margin-top:4px;min-width:50px}.ui-grid-pager-count-container .ui-grid-pager-count{margin-right:10px;margin-left:10px;float:right}.ui-grid-pinned-container{position:absolute;display:inline;top:0}.ui-grid-pinned-container.ui-grid-pinned-container-left{float:left;left:0}.ui-grid-pinned-container.ui-grid-pinned-container-right{float:right;right:0}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child{box-sizing:border-box;border-right:1px solid;border-width:1px;border-right-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child{box-sizing:border-box;border-right:1px solid;border-width:1px;border-right-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,.ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar{right:-1px;width:1px;background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child{box-sizing:border-box;border-left:1px solid;border-width:1px;border-left-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child{box-sizing:border-box;border-left:1px solid;border-width:1px;border-left-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,.ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar{width:1px}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar{background-color:#d4d4d4}.ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar{background-color:#aeaeae}.ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar{left:-1px;width:1px;background-color:#aeaeae}.ui-grid-column-resizer{top:0;bottom:0;width:5px;position:absolute;cursor:col-resize}.ui-grid-column-resizer.left{left:0}.ui-grid-column-resizer.right{right:0}.ui-grid-header-cell:last-child .ui-grid-column-resizer.right{border-right:1px solid #d4d4d4}.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.right{border-right:0}.ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.left{border-left:1px solid #d4d4d4}.ui-grid.column-resizing{cursor:col-resize}.ui-grid.column-resizing .ui-grid-resize-overlay{position:absolute;top:0;height:100%;width:1px;background-color:#aeaeae}.ui-grid-row-saving .ui-grid-cell{color:#848484 !important}.ui-grid-row-dirty .ui-grid-cell{color:#610b38}.ui-grid-row-error .ui-grid-cell{color:#f00 !important}.ui-grid-row.ui-grid-row-selected>[ui-grid-row]>.ui-grid-cell{background-color:#c9dde1}.ui-grid-disable-selection{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.ui-grid-selection-row-header-buttons{cursor:pointer;opacity:.1}.ui-grid-selection-row-header-buttons.ui-grid-row-selected{opacity:1}.ui-grid-selection-row-header-buttons.ui-grid-all-selected{opacity:1}.ui-grid-tree-row-header-buttons.ui-grid-tree-header{cursor:pointer;opacity:1}.ui-grid-tree-header-row{font-weight:bold !important}.ui-grid-tree-header-row .ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell{pointer-events:all}div.ui-grid-cell-contents.invalid{border:1px solid #fc8f8f} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.js
new file mode 100644
index 00000000..8d9e7ed8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.min.js
@@ -0,0 +1,15 @@
+/*!
+ * ui-grid - v4.0.2 - 2016-12-30
+ * Copyright (c) 2016 ; License: MIT
+ */
+
+!function(){"use strict";angular.module("ui.grid.i18n",[]),angular.module("ui.grid",["ui.grid.i18n"])}(),function(){"use strict";angular.module("ui.grid").constant("uiGridConstants",{LOG_DEBUG_MESSAGES:!0,LOG_WARN_MESSAGES:!0,LOG_ERROR_MESSAGES:!0,CUSTOM_FILTERS:/CUSTOM_FILTERS/g,COL_FIELD:/COL_FIELD/g,MODEL_COL_FIELD:/MODEL_COL_FIELD/g,TOOLTIP:/title=\"TOOLTIP\"/g,DISPLAY_CELL_TEMPLATE:/DISPLAY_CELL_TEMPLATE/g,TEMPLATE_REGEXP:/<.+>/,FUNC_REGEXP:/(\([^)]*\))?$/,DOT_REGEXP:/\./g,APOS_REGEXP:/'/g,BRACKET_REGEXP:/^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,COL_CLASS_PREFIX:"ui-grid-col",ENTITY_BINDING:"$$this",events:{GRID_SCROLL:"uiGridScroll",COLUMN_MENU_SHOWN:"uiGridColMenuShown",ITEM_DRAGGING:"uiGridItemDragStart",COLUMN_HEADER_CLICK:"uiGridColumnHeaderClick"},keymap:{TAB:9,STRG:17,CAPSLOCK:20,CTRL:17,CTRLRIGHT:18,CTRLR:18,SHIFT:16,RETURN:13,ENTER:13,BACKSPACE:8,BCKSP:8,ALT:18,ALTR:17,ALTRIGHT:17,SPACE:32,WIN:91,MAC:91,FN:null,PG_UP:33,PG_DOWN:34,UP:38,DOWN:40,LEFT:37,RIGHT:39,ESC:27,DEL:46,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123},ASC:"asc",DESC:"desc",filter:{STARTS_WITH:2,ENDS_WITH:4,EXACT:8,CONTAINS:16,GREATER_THAN:32,GREATER_THAN_OR_EQUAL:64,LESS_THAN:128,LESS_THAN_OR_EQUAL:256,NOT_EQUAL:512,SELECT:"select",INPUT:"input"},aggregationTypes:{sum:2,count:4,avg:8,min:16,max:32},CURRENCY_SYMBOLS:["¤","Ø‹","Ar","Ƀ","฿","B/.","Br","Bs.","Bs.F.","GH₵","¢","c","Ch.","â‚¡","C$","D","ден","دج",".د.ب","د.ع","JD","د.Ùƒ","Ù„.د","дин","د.ت","د.Ù….","د.Ø¥","Db","$","â‚«","Esc","€","Æ’","Ft","FBu","FCFA","CFA","Fr","FRw","G","gr","₲","h","â‚´","â‚­","KÄ","kr","kn","MK","ZK","Kz","K","L","Le","лв","E","lp","M","KM","MT","â‚¥","Nfk","₦","Nu.","UM","T$","MOP$","₱","Pt.","£","ج.Ù….","LL","LS","P","Q","q","R","R$","ر.ع.","ر.Ù‚","ر.س","៛","RM","p","Rf.","₹","₨","SRe","Rp","₪","Ksh","Sh.So.","USh","S/","SDR","Ñом","৳ ","WS$","â‚®","VT","â‚©","Â¥","zÅ‚"],scrollDirection:{UP:"up",DOWN:"down",LEFT:"left",RIGHT:"right",NONE:"none"},dataChange:{ALL:"all",EDIT:"edit",ROW:"row",COLUMN:"column",OPTIONS:"options"},scrollbars:{NEVER:0,ALWAYS:1}})}(),angular.module("ui.grid").directive("uiGridCell",["$compile","$parse","gridUtil","uiGridConstants",function(a,b,c,d){var e={priority:0,scope:!1,require:"?^uiGrid",compile:function(){return{pre:function(b,e,f,g){function h(){var a=b.col.compiledElementFn;a(b,function(a,b){e.append(a)})}if(g&&b.col.compiledElementFn)h();else if(g&&!b.col.compiledElementFn)b.col.getCompiledElementFn().then(function(a){a(b,function(a,b){e.append(a)})});else{var i=b.col.cellTemplate.replace(d.MODEL_COL_FIELD,"row.entity."+c.preEval(b.col.field)).replace(d.COL_FIELD,"grid.getCellValue(row, col)"),j=a(i)(b);e.append(j)}},post:function(a,b,c,e){var f=a.col.getColClass(!1);b.addClass(f);var g,h=function(c){var d=b;g&&(d.removeClass(g),g=null),g=angular.isFunction(a.col.cellClass)?a.col.cellClass(a.grid,a.row,a.col,a.rowRenderIndex,a.colRenderIndex):a.col.cellClass,d.addClass(g)};a.col.cellClass&&h();var i=a.grid.registerDataChangeCallback(h,[d.dataChange.COLUMN,d.dataChange.EDIT]),j=function(c,d){if(c!==d){(g||a.col.cellClass)&&h();var e=a.col.getColClass(!1);e!==f&&(b.removeClass(f),b.addClass(e),f=e)}},k=a.$watch("row",j),l=function(){i(),k()};a.$on("$destroy",l),b.on("$destroy",l)}}}};return e}]),function(){angular.module("ui.grid").service("uiGridColumnMenuService",["i18nService","uiGridConstants","gridUtil",function(a,b,c){var d={initialize:function(a,b){a.grid=b.grid,b.columnMenuScope=a,a.menuShown=!1},setColMenuItemWatch:function(a){var b=a.$watch("col.menuItems",function(b){"undefined"!=typeof b&&b&&angular.isArray(b)?(b.forEach(function(b){"undefined"!=typeof b.context&&b.context||(b.context={}),b.context.col=a.col}),a.menuItems=a.defaultMenuItems.concat(b)):a.menuItems=a.defaultMenuItems});a.$on("$destroy",b)},sortable:function(a){return a.grid.options.enableSorting&&"undefined"!=typeof a.col&&a.col&&a.col.enableSorting?!0:!1},isActiveSort:function(a,b){return"undefined"!=typeof a.col&&"undefined"!=typeof a.col.sort&&"undefined"!=typeof a.col.sort.direction&&a.col.sort.direction===b},suppressRemoveSort:function(a){return a.col&&a.col.suppressRemoveSort?!0:!1},hideable:function(a){return"undefined"!=typeof a.col&&a.col&&a.col.colDef&&a.col.colDef.enableHiding===!1?!1:!0},getDefaultMenuItems:function(c){return[{title:a.getSafeText("sort.ascending"),icon:"ui-grid-icon-sort-alt-up",action:function(a){a.stopPropagation(),c.sortColumn(a,b.ASC)},shown:function(){return d.sortable(c)},active:function(){return d.isActiveSort(c,b.ASC)}},{title:a.getSafeText("sort.descending"),icon:"ui-grid-icon-sort-alt-down",action:function(a){a.stopPropagation(),c.sortColumn(a,b.DESC)},shown:function(){return d.sortable(c)},active:function(){return d.isActiveSort(c,b.DESC)}},{title:a.getSafeText("sort.remove"),icon:"ui-grid-icon-cancel",action:function(a){a.stopPropagation(),c.unsortColumn()},shown:function(){return d.sortable(c)&&"undefined"!=typeof c.col&&"undefined"!=typeof c.col.sort&&"undefined"!=typeof c.col.sort.direction&&null!==c.col.sort.direction&&!d.suppressRemoveSort(c)}},{title:a.getSafeText("column.hide"),icon:"ui-grid-icon-cancel",shown:function(){return d.hideable(c)},action:function(a){a.stopPropagation(),c.hideColumn()}}]},getColumnElementPosition:function(a,b,d){var e={};return e.left=d[0].offsetLeft,e.top=d[0].offsetTop,e.parentLeft=d[0].offsetParent.offsetLeft,e.offset=0,b.grid.options.offsetLeft&&(e.offset=b.grid.options.offsetLeft),e.height=c.elementHeight(d,!0),e.width=c.elementWidth(d,!0),e},repositionMenu:function(a,b,d,e,f){var g=e[0].querySelectorAll(".ui-grid-menu"),h=c.closestElm(f,".ui-grid-render-container"),i=h.getBoundingClientRect().left-a.grid.element[0].getBoundingClientRect().left,j=h.querySelectorAll(".ui-grid-viewport")[0].scrollLeft,k=b.lastMenuWidth?b.lastMenuWidth:a.lastMenuWidth?a.lastMenuWidth:170,l=b.lastMenuPaddingRight?b.lastMenuPaddingRight:a.lastMenuPaddingRight?a.lastMenuPaddingRight:10;if(0!==g.length){var m=g[0].querySelectorAll(".ui-grid-menu-mid");0===m.length||angular.element(m).hasClass("ng-hide")||(k=c.elementWidth(g,!0),a.lastMenuWidth=k,b.lastMenuWidth=k,l=parseInt(c.getStyles(angular.element(g)[0]).paddingRight,10),a.lastMenuPaddingRight=l,b.lastMenuPaddingRight=l)}var n=d.left+i-j+d.parentLeft+d.width-k+l;n<d.offset&&(n=d.offset),e.css("left",n+"px"),e.css("top",d.top+d.height+"px")}};return d}]).directive("uiGridColumnMenu",["$timeout","gridUtil","uiGridConstants","uiGridColumnMenuService","$document",function(a,b,c,d,e){var f={priority:0,scope:!0,require:"^uiGrid",templateUrl:"ui-grid/uiGridColumnMenu",replace:!0,link:function(f,g,h,i){d.initialize(f,i),f.defaultMenuItems=d.getDefaultMenuItems(f),f.menuItems=f.defaultMenuItems,d.setColMenuItemWatch(f),f.showMenu=function(a,b,c){f.col=a;var e=d.getColumnElementPosition(f,a,b);f.menuShown?(f.colElement=b,f.colElementPosition=e,f.hideThenShow=!0,f.$broadcast("hide-menu",{originalEvent:c})):(f.menuShown=!0,d.repositionMenu(f,a,e,g,b),f.colElement=b,f.colElementPosition=e,f.$broadcast("show-menu",{originalEvent:c}))},f.hideMenu=function(a){f.menuShown=!1,a||f.$broadcast("hide-menu")},f.$on("menu-hidden",function(){f.hideThenShow?(delete f.hideThenShow,d.repositionMenu(f,f.col,f.colElementPosition,g,f.colElement),f.$broadcast("show-menu"),f.menuShown=!0):(f.hideMenu(!0),f.col&&b.focus.bySelector(e,".ui-grid-header-cell."+f.col.getColClass()+" .ui-grid-column-menu-button",f.col.grid,!1))}),f.$on("menu-shown",function(){a(function(){d.repositionMenu(f,f.col,f.colElementPosition,g,f.colElement),b.focus.bySelector(e,".ui-grid-menu-items .ui-grid-menu-item",!0),delete f.colElementPosition,delete f.columnElement},200)}),f.sortColumn=function(a,b){a.stopPropagation(),f.grid.sortColumn(f.col,b,!0).then(function(){f.grid.refresh(),f.hideMenu()})},f.unsortColumn=function(){f.col.unsort(),f.grid.refresh(),f.hideMenu()};var j=function(){a(function(){var a,c=function(){return b.focus.byId("grid-menu",f.grid)};f.grid.columns.some(function(b,c){return angular.equals(b,f.col)?(a=c,!0):void 0});var d;if(f.grid.columns.some(function(b,c){if(!b.visible)return!1;if(a>c)d=b;else{if(c>a&&!d)return d=b,!0;if(c>a&&d)return!0}}),d){var g=d.getColClass();b.focus.bySelector(e,".ui-grid-header-cell."+g+" .ui-grid-header-cell-primary-focus",!0).then(angular.noop,function(a){return"canceled"!==a?c():void 0})}else c()})};f.hideColumn=function(){f.col.colDef.visible=!1,f.col.visible=!1,f.grid.queueGridRefresh(),f.hideMenu(),f.grid.api.core.notifyDataChange(c.dataChange.COLUMN),f.grid.api.core.raise.columnVisibilityChanged(f.col),j()}},controller:["$scope",function(a){var b=this;a.$watch("menuItems",function(a){b.menuItems=a})}]};return f}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridFilter",["$compile","$templateCache","i18nService","gridUtil",function(a,b,c,d){return{compile:function(){return{pre:function(b,c,d,e){b.col.updateFilters=function(d){if(c.children().remove(),d){var e=b.col.filterHeaderTemplate;c.append(a(e)(b))}},b.$on("$destroy",function(){delete b.col.updateFilters})},post:function(a,b,e,f){a.aria=c.getSafeText("headerCell.aria"),a.removeFilter=function(a,c){a.term=null,d.focus.bySelector(b,".ui-grid-filter-input-"+c)}}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridFooterCell",["$timeout","gridUtil","uiGridConstants","$compile",function(a,b,c,d){var e={priority:0,scope:{col:"=",row:"=",renderIndex:"="},replace:!0,require:"^uiGrid",compile:function(a,b,e){return{pre:function(a,b,c,e){var f=d(a.col.footerCellTemplate)(a);b.append(f)},post:function(a,b,d,e){a.grid=e.grid;var f=a.col.getColClass(!1);b.addClass(f);var g,h=function(c){var d=b;g&&(d.removeClass(g),g=null),g=angular.isFunction(a.col.footerCellClass)?a.col.footerCellClass(a.grid,a.row,a.col,a.rowRenderIndex,a.colRenderIndex):a.col.footerCellClass,d.addClass(g)};a.col.footerCellClass&&h(),a.col.updateAggregationValue();var i=a.grid.registerDataChangeCallback(h,[c.dataChange.COLUMN]);a.grid.api.core.on.rowsRendered(a,a.col.updateAggregationValue),a.grid.api.core.on.rowsRendered(a,h),a.$on("$destroy",i)}}}};return e}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridFooter",["$templateCache","$compile","uiGridConstants","gridUtil","$timeout",function(a,b,c,d,e){return{restrict:"EA",replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:!0,compile:function(a,c){return{pre:function(a,c,e,f){var g=f[0],h=f[1];a.grid=g.grid,a.colContainer=h.colContainer,h.footer=c;var i=a.grid.options.footerTemplate;d.getTemplate(i).then(function(d){var e=angular.element(d),f=b(e)(a);if(c.append(f),h){var g=c[0].getElementsByClassName("ui-grid-footer-viewport")[0];g&&(h.footerViewport=g)}})},post:function(a,b,c,e){var f=e[0],g=e[1];f.grid;d.disableAnimations(b),g.footer=b;var h=b[0].getElementsByClassName("ui-grid-footer-viewport")[0];h&&(g.footerViewport=h)}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridGridFooter",["$templateCache","$compile","uiGridConstants","gridUtil","$timeout",function(a,b,c,d,e){return{restrict:"EA",replace:!0,require:"^uiGrid",scope:!0,compile:function(a,c){return{pre:function(a,c,e,f){a.grid=f.grid;var g=a.grid.options.gridFooterTemplate;d.getTemplate(g).then(function(d){var e=angular.element(d),f=b(e)(a);c.append(f)})},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridGroupPanel",["$compile","uiGridConstants","gridUtil",function(a,b,c){var d="ui-grid/ui-grid-group-panel";return{restrict:"EA",replace:!0,require:"?^uiGrid",scope:!1,compile:function(b,e){return{pre:function(b,e,f,g){var h=b.grid.options.groupPanelTemplate||d;c.getTemplate(h).then(function(c){var d=angular.element(c),f=a(d)(b);e.append(f)})},post:function(a,b,c,d){b.bind("$destroy",function(){})}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridHeaderCell",["$compile","$timeout","$window","$document","gridUtil","uiGridConstants","ScrollEvent","i18nService",function(a,b,c,d,e,f,g,h){var i=500,j=500,k={priority:0,scope:{col:"=",row:"=",renderIndex:"="},require:["^uiGrid","^uiGridRenderContainer"],replace:!0,compile:function(){return{pre:function(b,c,d){var e=a(b.col.headerCellTemplate)(b);c.append(e)},post:function(a,c,e,g){var k=g[0],l=g[1];a.i18n={headerCell:h.getSafeText("headerCell"),sort:h.getSafeText("sort")},a.isSortPriorityVisible=function(){return angular.isNumber(a.col.sort.priority)&&a.grid.columns.some(function(b,c){return angular.isNumber(b.sort.priority)&&b!==a.col})},a.getSortDirectionAriaLabel=function(){var b=a.col,c=b.sort.direction===f.ASC?a.i18n.sort.ascending:b.sort.direction===f.DESC?a.i18n.sort.descending:a.i18n.sort.none,d=c;return a.isSortPriorityVisible()&&(d=d+". "+a.i18n.headerCell.priority+" "+b.sort.priority),d},a.grid=k.grid,a.renderContainer=k.grid.renderContainers[l.containerId];var m=a.col.getColClass(!1);c.addClass(m),a.menuShown=!1,a.asc=f.ASC,a.desc=f.DESC;var n,o,p=(angular.element(c[0].querySelectorAll(".ui-grid-header-cell-menu")),angular.element(c[0].querySelectorAll(".ui-grid-cell-contents"))),q=[];a.downFn=function(e){e.stopPropagation(),"undefined"!=typeof e.originalEvent&&void 0!==e.originalEvent&&(e=e.originalEvent),e.button&&0!==e.button||(o=e.pageX,a.mousedownStartTime=(new Date).getTime(),a.mousedownTimeout=b(function(){},i),a.mousedownTimeout.then(function(){a.colMenu&&k.columnMenuScope.showMenu(a.col,c,e)}),k.fireEvent(f.events.COLUMN_HEADER_CLICK,{event:e,columnName:a.col.colDef.name}),a.offAllEvents(),"touchstart"===e.type?(d.on("touchend",a.upFn),d.on("touchmove",a.moveFn)):"mousedown"===e.type&&(d.on("mouseup",a.upFn),d.on("mousemove",a.moveFn)))},a.upFn=function(c){c.stopPropagation(),b.cancel(a.mousedownTimeout),a.offAllEvents(),a.onDownEvents(c.type);var d=(new Date).getTime(),e=d-a.mousedownStartTime;e>i||a.sortable&&a.handleClick(c)},a.moveFn=function(c){var d=c.pageX-o;0!==d&&(b.cancel(a.mousedownTimeout),a.offAllEvents(),a.onDownEvents(c.type))},a.clickFn=function(b){b.stopPropagation(),p.off("click",a.clickFn)},a.offAllEvents=function(){p.off("touchstart",a.downFn),p.off("mousedown",a.downFn),d.off("touchend",a.upFn),d.off("mouseup",a.upFn),d.off("touchmove",a.moveFn),d.off("mousemove",a.moveFn),p.off("click",a.clickFn)},a.onDownEvents=function(c){switch(c){case"touchmove":case"touchend":p.on("click",a.clickFn),p.on("touchstart",a.downFn),b(function(){p.on("mousedown",a.downFn)},j);break;case"mousemove":case"mouseup":p.on("click",a.clickFn),p.on("mousedown",a.downFn),b(function(){p.on("touchstart",a.downFn)},j);break;default:p.on("click",a.clickFn),p.on("touchstart",a.downFn),p.on("mousedown",a.downFn)}};var r=function(d){var e=c;n&&(e.removeClass(n),n=null),n=angular.isFunction(a.col.headerCellClass)?a.col.headerCellClass(a.grid,a.row,a.col,a.rowRenderIndex,a.colRenderIndex):a.col.headerCellClass,e.addClass(n),b(function(){var b=a.grid.renderContainers.right?a.grid.renderContainers.right:a.grid.renderContainers.body;a.isLastCol=a.col===b.visibleColumnCache[b.visibleColumnCache.length-1]}),a.col.enableSorting?a.sortable=!0:a.sortable=!1;var g=a.filterable;k.grid.options.enableFiltering&&a.col.enableFiltering?a.filterable=!0:a.filterable=!1,g!==a.filterable&&("undefined"!=typeof a.col.updateFilters&&a.col.updateFilters(a.filterable),a.filterable?(a.col.filters.forEach(function(b,c){q.push(a.$watch("col.filters["+c+"].term",function(a,b){a!==b&&(k.grid.api.core.raise.filterChanged(),k.grid.api.core.notifyDataChange(f.dataChange.COLUMN),k.grid.queueGridRefresh())}))}),a.$on("$destroy",function(){q.forEach(function(a){a()})})):q.forEach(function(a){a()})),a.col.grid.options&&a.col.grid.options.enableColumnMenus!==!1&&a.col.colDef&&a.col.colDef.enableColumnMenu!==!1?a.colMenu=!0:a.colMenu=!1,a.offAllEvents(),(a.sortable||a.colMenu)&&(a.onDownEvents(),a.$on("$destroy",function(){a.offAllEvents()}))};r();var s=a.grid.registerDataChangeCallback(r,[f.dataChange.COLUMN]);a.$on("$destroy",s),a.handleClick=function(b){var c=!1;b.shiftKey&&(c=!0),k.grid.sortColumn(a.col,c).then(function(){k.columnMenuScope&&k.columnMenuScope.hideMenu(),k.grid.refresh()})},a.toggleMenu=function(b){b.stopPropagation(),k.columnMenuScope.menuShown&&k.columnMenuScope.col===a.col?k.columnMenuScope.hideMenu():k.columnMenuScope.showMenu(a.col,c)}}}}};return k}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridHeader",["$templateCache","$compile","uiGridConstants","gridUtil","$timeout","ScrollEvent",function(a,b,c,d,e,f){var g="ui-grid/ui-grid-header",h="ui-grid/ui-grid-no-header";return{restrict:"EA",replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:!0,compile:function(a,c){return{pre:function(a,c,e,i){function j(){m.header=m.colContainer.header=c;var a=c[0].getElementsByClassName("ui-grid-header-canvas");a.length>0?m.headerCanvas=m.colContainer.headerCanvas=a[0]:m.headerCanvas=null}function k(a){if(!l.grid.isScrollingHorizontally){var b=d.normalizeScrollLeft(m.headerViewport,l.grid),c=m.colContainer.scrollHorizontal(b),e=new f(l.grid,null,m.colContainer,f.Sources.ViewPortScroll);e.newScrollLeft=b,c>-1&&(e.x={percentage:c}),l.grid.scrollContainers(null,e)}}var l=i[0],m=i[1];a.grid=l.grid,a.colContainer=m.colContainer,j();var n;n=a.grid.options.showHeader?a.grid.options.headerTemplate?a.grid.options.headerTemplate:g:h,d.getTemplate(n).then(function(d){var e=angular.element(d),f=b(e)(a);if(c.replaceWith(f),c=f,j(),m){var g=c[0].getElementsByClassName("ui-grid-header-viewport")[0];g&&(m.headerViewport=g,angular.element(g).on("scroll",k),a.$on("$destroy",function(){angular.element(g).off("scroll",k)}))}a.grid.queueRefresh()})},post:function(a,b,c,e){function f(){var a=h.colContainer.visibleColumnCache,b="",c=0;return a.forEach(function(a){b+=a.getColClassDefinition(),c+=a.drawnWidth}),h.colContainer.canvasWidth=c,b}var g=e[0],h=e[1];g.grid;d.disableAnimations(b),h.header=b;var i=b[0].getElementsByClassName("ui-grid-header-viewport")[0];i&&(h.headerViewport=i),g&&g.grid.registerStyleComputation({priority:15,func:f})}}}}}])}(),function(){angular.module("ui.grid").service("uiGridGridMenuService",["gridUtil","i18nService","uiGridConstants",function(a,b,c){var d={initialize:function(a,b){b.gridMenuScope=a,a.grid=b,a.registeredMenuItems=[],a.$on("$destroy",function(){a.grid&&a.grid.gridMenuScope&&(a.grid.gridMenuScope=null),a.grid&&(a.grid=null),a.registeredMenuItems&&(a.registeredMenuItems=null)}),a.registeredMenuItems=[],b.api.registerMethod("core","addToGridMenu",d.addToGridMenu),b.api.registerMethod("core","removeFromGridMenu",d.removeFromGridMenu)},addToGridMenu:function(b,c){angular.isArray(c)?b.gridMenuScope?(b.gridMenuScope.registeredMenuItems=b.gridMenuScope.registeredMenuItems?b.gridMenuScope.registeredMenuItems:[],b.gridMenuScope.registeredMenuItems=b.gridMenuScope.registeredMenuItems.concat(c)):a.logError("Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid"):a.logError("addToGridMenu: menuItems must be an array, and is not, not adding any items")},removeFromGridMenu:function(b,c){var d=-1;b&&b.gridMenuScope&&b.gridMenuScope.registeredMenuItems.forEach(function(b,e){b.id===c&&(d>-1?a.logError("removeFromGridMenu: found multiple items with the same id, removing only the last"):d=e)}),d>-1&&b.gridMenuScope.registeredMenuItems.splice(d,1)},getMenuItems:function(c){var e=[];c.grid.options.gridMenuCustomItems&&(angular.isArray(c.grid.options.gridMenuCustomItems)?e=e.concat(c.grid.options.gridMenuCustomItems):a.logError("gridOptions.gridMenuCustomItems must be an array, and is not"));var f=[{title:b.getSafeText("gridMenu.clearAllFilters"),action:function(a){c.grid.clearAllFilters()},shown:function(){return c.grid.options.enableFiltering},order:100}];return e=e.concat(f),e=e.concat(c.registeredMenuItems),c.grid.options.gridMenuShowHideColumns!==!1&&(e=e.concat(d.showHideColumns(c))),e.sort(function(a,b){return a.order-b.order}),e},showHideColumns:function(a){var c=[];return a.grid.options.columnDefs&&0!==a.grid.options.columnDefs.length&&0!==a.grid.columns.length?(c.push({title:b.getSafeText("gridMenu.columns"),order:300}),a.grid.options.gridMenuTitleFilter=a.grid.options.gridMenuTitleFilter?a.grid.options.gridMenuTitleFilter:function(a){return a},a.grid.options.columnDefs.forEach(function(b,e){if(b.enableHiding!==!1){var f={icon:"ui-grid-icon-ok",action:function(a){a.stopPropagation(),d.toggleColumnVisibility(this.context.gridCol)},shown:function(){return this.context.gridCol.colDef.visible===!0||void 0===this.context.gridCol.colDef.visible},context:{gridCol:a.grid.getColumn(b.name||b.field)},leaveOpen:!0,order:301+2*e};d.setMenuItemTitle(f,b,a.grid),c.push(f),f={icon:"ui-grid-icon-cancel",action:function(a){a.stopPropagation(),d.toggleColumnVisibility(this.context.gridCol)},shown:function(){return!(this.context.gridCol.colDef.visible===!0||void 0===this.context.gridCol.colDef.visible)},context:{gridCol:a.grid.getColumn(b.name||b.field)},leaveOpen:!0,order:301+2*e+1},d.setMenuItemTitle(f,b,a.grid),c.push(f)}}),c):c},setMenuItemTitle:function(b,c,d){var e=d.options.gridMenuTitleFilter(c.displayName||a.readableColumnName(c.name)||c.field);"string"==typeof e?b.title=e:e.then?(b.title="",e.then(function(a){b.title=a},function(a){b.title=a})):(a.logError("Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config"),b.title="badconfig")},toggleColumnVisibility:function(a){a.colDef.visible=!(a.colDef.visible===!0||void 0===a.colDef.visible),a.grid.refresh(),a.grid.api.core.notifyDataChange(c.dataChange.COLUMN),a.grid.api.core.raise.columnVisibilityChanged(a)}};return d}]).directive("uiGridMenuButton",["gridUtil","uiGridConstants","uiGridGridMenuService","i18nService",function(a,b,c,d){return{priority:0,scope:!0,require:["^uiGrid"],templateUrl:"ui-grid/ui-grid-menu-button",replace:!0,link:function(b,e,f,g){var h=g[0];b.i18n={aria:d.getSafeText("gridMenu.aria")},c.initialize(b,h.grid),b.shown=!1,b.toggleMenu=function(){b.shown?(b.$broadcast("hide-menu"),b.shown=!1):(b.menuItems=c.getMenuItems(b),b.$broadcast("show-menu"),b.shown=!0)},b.$on("menu-hidden",function(){b.shown=!1,a.focus.bySelector(e,".ui-grid-icon-container")})}}}])}(),function(){angular.module("ui.grid").directive("uiGridMenu",["$compile","$timeout","$window","$document","gridUtil","uiGridConstants","i18nService",function(a,b,c,d,e,f,g){var h={priority:0,scope:{menuItems:"=",autoHide:"=?"},require:"?^uiGrid",templateUrl:"ui-grid/uiGridMenu",replace:!1,link:function(d,h,i,j){if(d.dynamicStyles="",j&&j.grid&&j.grid.options&&j.grid.options.gridMenuTemplate){var k=j.grid.options.gridMenuTemplate;e.getTemplate(k).then(function(b){var c=angular.element(b),e=a(c)(d);h.replaceWith(e)})}var l=function(a){var b=a-j.grid.headerHeight-20;d.dynamicStyles=[".grid"+j.grid.id+" .ui-grid-menu-mid {","max-height: "+b+"px;","}"].join(" ")};j&&(l(j.grid.gridHeight),j.grid.api.core.on.gridDimensionChanged(d,function(a,b,c,d){l(c)})),d.i18n={close:g.getSafeText("columnMenu.close")},d.showMenu=function(a,c){d.shown?d.shownMid||(d.shownMid=!0,d.$emit("menu-shown")):(d.shown=!0,b(function(){d.shownMid=!0,d.$emit("menu-shown")}));var f="click";c&&c.originalEvent&&c.originalEvent.type&&"touchstart"===c.originalEvent.type&&(f=c.originalEvent.type),angular.element(document).off("click touchstart",m),h.off("keyup",n),h.off("keydown",o),b(function(){angular.element(document).on(f,m),h.on("keyup",n),h.on("keydown",o)}),e.focus.bySelector(h,"button[type=button]",!0)},d.hideMenu=function(a){d.shown&&(d.shownMid=!1,b(function(){d.shownMid||(d.shown=!1,d.$emit("menu-hidden"))},200)),angular.element(document).off("click touchstart",m),h.off("keyup",n),h.off("keydown",o)},d.$on("hide-menu",function(a,b){d.hideMenu(a,b)}),d.$on("show-menu",function(a,b){d.showMenu(a,b)});var m=function(){d.shown&&d.$apply(function(){d.hideMenu()})},n=function(a){27===a.keyCode&&d.hideMenu()},o=function(a){var b=function(b){return b.focus(),a.preventDefault(),!1};if(9===a.keyCode){var c,d,e=h[0].querySelectorAll("button:not(.ng-hide)");e.length>0&&(c=e[0],d=e[e.length-1],a.target!==d||a.shiftKey?a.target===c&&a.shiftKey&&b(d):b(c))}};("undefined"==typeof d.autoHide||void 0===d.autoHide)&&(d.autoHide=!0),d.autoHide&&angular.element(c).on("resize",m),d.$on("$destroy",function(){angular.element(c).off("resize",m),angular.element(document).off("click touchstart",m),h.off("keyup",n),h.off("keydown",o)}),j&&d.$on("$destroy",j.grid.api.core.on.scrollBegin(d,m)),d.$on("$destroy",d.$on(f.events.ITEM_DRAGGING,m))}};return h}]).directive("uiGridMenuItem",["gridUtil","$compile","i18nService",function(a,b,c){var d={priority:0,scope:{name:"=",active:"=",action:"=",icon:"=",shown:"=",context:"=",templateUrl:"=",leaveOpen:"=",screenReaderOnly:"="},require:["?^uiGrid"],templateUrl:"ui-grid/uiGridMenuItem",replace:!1,compile:function(){return{pre:function(c,d){c.templateUrl&&a.getTemplate(c.templateUrl).then(function(a){var e=angular.element(a),f=b(e)(c);d.replaceWith(f)})},post:function(b,d,e,f){var g=f[0];("undefined"==typeof b.shown||null===b.shown)&&(b.shown=function(){return!0}),b.itemShown=function(){var a={};return b.context&&(a.context=b.context),"undefined"!=typeof g&&g&&(a.grid=g.grid),b.shown.call(a)},b.itemAction=function(c,e){if(c.stopPropagation(),"function"==typeof b.action){var f={};b.context&&(f.context=b.context),"undefined"!=typeof g&&g&&(f.grid=g.grid),b.action.call(f,c,e),b.leaveOpen?a.focus.bySelector(angular.element(a.closestElm(d,".ui-grid-menu-items")),"button[type=button]",!0):b.$emit("hide-menu")}},b.i18n=c.get()}}}};return d}])}(),function(){"use strict";var a=angular.module("ui.grid");angular.forEach([{tag:"Src",method:"attr"},{tag:"Text",method:"text"},{tag:"Href",method:"attr"},{tag:"Class",method:"addClass"},{tag:"Html",method:"html"},{tag:"Alt",method:"attr"},{tag:"Style",method:"css"},{tag:"Value",method:"attr"},{tag:"Id",method:"attr"},{tag:"Id",directiveName:"IdGrid",method:"attr",appendGridId:!0},{tag:"Title",method:"attr"},{tag:"Label",method:"attr",aria:!0},{tag:"Labelledby",method:"attr",aria:!0},{tag:"Labelledby",directiveName:"LabelledbyGrid",appendGridId:!0,method:"attr",aria:!0},{tag:"Describedby",method:"attr",aria:!0},{tag:"Describedby",directiveName:"DescribedbyGrid",appendGridId:!0,method:"attr",aria:!0}],function(b){var c="uiGridOneBind",d=(b.aria?c+"Aria":c)+(b.directiveName?b.directiveName:b.tag);a.directive(d,["gridUtil",function(a){return{restrict:"A",require:["?uiGrid","?^uiGrid"],link:function(c,e,f,g){var h=function(b){var e;if(c.grid)e=c.grid;else if(c.col&&c.col.grid)e=c.col.grid;else if(!g.some(function(a){return a&&a.grid?(e=a.grid,!0):void 0}))throw a.logError("["+d+"] A valid grid could not be found to bind id. Are you using this directive within the correct scope? Trying to generate id: [gridID]-"+b),new Error("No valid grid could be found");if(e){var f=new RegExp(e.id.toString());f.test(b)||(b=e.id.toString()+"-"+b)}return b},i=c.$watch(f[d],function(a){if(a){if(b.appendGridId){var c=null;angular.forEach(a.split(" "),function(a){c=(c?c+" ":"")+h(a)}),a=c}switch(b.method){case"attr":b.aria?e[b.method]("aria-"+b.tag.toLowerCase(),a):e[b.method](b.tag.toLowerCase(),a);break;case"addClass":if(angular.isObject(a)&&!angular.isArray(a)){var d=[],f=!1;if(angular.forEach(a,function(a,b){null!==a&&"undefined"!=typeof a&&(f=!0,a&&d.push(b))}),!f)return;a=d}if(!a)return;e.addClass(angular.isArray(a)?a.join(" "):a);break;default:e[b.method](a)}i()}},!0)}}}])})}(),function(){"use strict";var a=angular.module("ui.grid");a.directive("uiGridRenderContainer",["$timeout","$document","uiGridConstants","gridUtil","ScrollEvent",function(a,b,c,d,e){return{replace:!0,transclude:!0,templateUrl:"ui-grid/uiGridRenderContainer",require:["^uiGrid","uiGridRenderContainer"],scope:{containerId:"=",rowContainerName:"=",colContainerName:"=",bindScrollHorizontal:"=",bindScrollVertical:"=",enableVerticalScrollbar:"=",enableHorizontalScrollbar:"="},controller:"uiGridRenderContainer as RenderContainer",compile:function(){return{pre:function(a,b,c,d){var e=d[0],f=d[1],g=a.grid=e.grid;if(!a.rowContainerName)throw"No row render container name specified";if(!a.colContainerName)throw"No column render container name specified";if(!g.renderContainers[a.rowContainerName])throw"Row render container '"+a.rowContainerName+"' is not registered.";if(!g.renderContainers[a.colContainerName])throw"Column render container '"+a.colContainerName+"' is not registered.";var h=a.rowContainer=g.renderContainers[a.rowContainerName],i=a.colContainer=g.renderContainers[a.colContainerName];f.containerId=a.containerId,f.rowContainer=h,f.colContainer=i},post:function(a,b,c,f){function g(){var b="",c=l.canvasWidth,d=l.getViewportWidth(),e=k.getCanvasHeight(),f=k.getViewportHeight();l.needsHScrollbarPlaceholder()&&(f-=j.scrollbarHeight);var g,i;return g=i=l.getHeaderViewportWidth(),b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-canvas { width: "+c+"px; height: "+e+"px; }",b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-header-canvas { width: "+(c+j.scrollbarWidth)+"px; }",b+=o.explicitHeaderCanvasHeight?"\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-header-canvas { height: "+o.explicitHeaderCanvasHeight+"px; }":"\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-header-canvas { height: inherit; }",b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-viewport { width: "+d+"px; height: "+f+"px; }",b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-header-viewport { width: "+g+"px; }",b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-footer-canvas { width: "+(c+j.scrollbarWidth)+"px; }",b+="\n .grid"+h.grid.id+" .ui-grid-render-container-"+a.containerId+" .ui-grid-footer-viewport { width: "+i+"px; }"}var h=f[0],i=f[1],j=h.grid,k=i.rowContainer,l=i.colContainer,m=null,n=null,o=j.renderContainers[a.containerId];b.addClass("ui-grid-render-container-"+a.containerId),d.on.mousewheel(b,function(a){var b=new e(j,k,l,e.Sources.RenderContainerMouseWheel);if(0!==a.deltaY){var c=-1*a.deltaY*a.deltaFactor;m=i.viewport[0].scrollTop,b.verticalScrollLength=k.getVerticalScrollLength();var f=(m+c)/b.verticalScrollLength;f>=1&&m<b.verticalScrollLength&&(i.viewport[0].scrollTop=b.verticalScrollLength),0>f?f=0:f>1&&(f=1),b.y={percentage:f,pixels:c}}if(0!==a.deltaX){var g=a.deltaX*a.deltaFactor;n=d.normalizeScrollLeft(i.viewport,j),b.horizontalScrollLength=l.getCanvasWidth()-l.getViewportWidth();var h=(n+g)/b.horizontalScrollLength;0>h?h=0:h>1&&(h=1),b.x={percentage:h,pixels:g}}0!==a.deltaY&&(b.atTop(m)||b.atBottom(m))||0!==a.deltaX&&(b.atLeft(n)||b.atRight(n))||(a.preventDefault(),a.stopPropagation(),b.fireThrottledScrollingEvent("",b))}),b.bind("$destroy",function(){b.unbind("keydown"),["touchstart","touchmove","touchend","keydown","wheel","mousewheel","DomMouseScroll","MozMousePixelScroll"].forEach(function(a){b.unbind(a)})}),h.grid.registerStyleComputation({priority:6,func:g})}}}}}]),a.controller("uiGridRenderContainer",["$scope","gridUtil",function(a,b){}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridRow",["gridUtil",function(a){return{replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:{row:"=uiGridRow",rowRenderIndex:"="},compile:function(){return{pre:function(a,b,c,d){function e(){a.row.getRowTemplateFn.then(function(c){var d=a.$new();c(d,function(a,c){h&&(h.remove(),i.$destroy()),b.empty().append(a),h=a,i=d})})}var f=d[0],g=d[1];f.grid;a.grid=f.grid,a.colContainer=g.colContainer;var h,i;e(),a.$watch("row.getRowTemplateFn",function(a,b){a!==b&&e()})},post:function(a,b,c,d){}}}}}])}(),function(){angular.module("ui.grid").directive("uiGridStyle",["gridUtil","$interpolate",function(a,b){return{link:function(a,c,d,e){var f=b(c.text(),!0);f&&a.$watch(f,function(a){c.text(a)})}}}])}(),
+function(){"use strict";angular.module("ui.grid").directive("uiGridViewport",["gridUtil","ScrollEvent","uiGridConstants","$log",function(a,b,c,d){return{replace:!0,scope:{},controllerAs:"Viewport",templateUrl:"ui-grid/uiGridViewport",require:["^uiGrid","^uiGridRenderContainer"],link:function(c,d,e,f){function g(e){var f=d[0].scrollTop,g=a.normalizeScrollLeft(d,p),h=n.scrollVertical(f),i=o.scrollHorizontal(g),j=new b(p,n,o,b.Sources.ViewPortScroll);j.newScrollLeft=g,j.newScrollTop=f,i>-1&&(j.x={percentage:i}),h>-1&&(j.y={percentage:h}),p.scrollContainers(c.$parent.containerId,j)}function h(a){m.prevScrollArgs=a;var b=a.getNewScrollTop(n,m.viewport);d[0].scrollTop=b}function i(b){m.prevScrollArgs=b;var c=b.getNewScrollLeft(o,m.viewport);d[0].scrollLeft=a.denormalizeScrollLeft(m.viewport,c,p)}function j(b){var c=b.getNewScrollLeft(o,m.viewport);m.headerViewport&&(m.headerViewport.scrollLeft=a.denormalizeScrollLeft(m.viewport,c,p))}function k(b){var c=b.getNewScrollLeft(o,m.viewport);m.footerViewport&&(m.footerViewport.scrollLeft=a.denormalizeScrollLeft(m.viewport,c,p))}var l=f[0],m=f[1];c.containerCtrl=m;var n=m.rowContainer,o=m.colContainer,p=l.grid;c.grid=l.grid,c.rowContainer=m.rowContainer,c.colContainer=m.colContainer,m.viewport=d,p&&p.options&&p.options.customScroller?p.options.customScroller(d,g):d.on("scroll",g);c.$parent.bindScrollVertical&&p.addVerticalScrollSync(c.$parent.containerId,h),c.$parent.bindScrollHorizontal&&(p.addHorizontalScrollSync(c.$parent.containerId,i),p.addHorizontalScrollSync(c.$parent.containerId+"header",j),p.addHorizontalScrollSync(c.$parent.containerId+"footer",k)),c.$on("$destroy",function(){d.off()})},controller:["$scope",function(a){this.rowStyle=function(b){var c=a.rowContainer,d=a.colContainer,e={};if(0!==c.currentTopRow){var f="translateY("+c.currentTopRow*c.grid.options.rowHeight+"px)";e.transform=f,e["-webkit-transform"]=f,e["-ms-transform"]=f}return 0!==d.currentFirstColumn&&(d.grid.isRTL()?e["margin-right"]=d.columnOffset+"px":e["margin-left"]=d.columnOffset+"px"),e}}]}}])}(),function(){angular.module("ui.grid").directive("uiGridVisible",function(){return function(a,b,c){a.$watch(c.uiGridVisible,function(a){b[a?"removeClass":"addClass"]("ui-grid-invisible")})}})}(),function(){"use strict";function a(a,b,c,d,e,f){return{templateUrl:"ui-grid/ui-grid",scope:{uiGrid:"="},replace:!0,transclude:!0,controller:"uiGridController",compile:function(){return{post:function(a,b,g,h){function i(){b[0].offsetWidth<=0&&p>q?(setTimeout(i,o),q++):c(k)}function j(){angular.element(d).on("resize",m),b.on("$destroy",function(){angular.element(d).off("resize",m)}),a.$watch(function(){return n.hasLeftContainer()},function(a,b){a!==b&&n.refreshCanvas(!0)}),a.$watch(function(){return n.hasRightContainer()},function(a,b){a!==b&&n.refreshCanvas(!0)})}function k(){n.gridWidth=a.gridWidth=e.elementWidth(b),n.canvasWidth=h.grid.gridWidth,n.gridHeight=a.gridHeight=e.elementHeight(b),n.gridHeight<=n.options.rowHeight&&n.options.enableMinHeightCheck&&l(),n.refreshCanvas(!0)}function l(){var c=n.options.minRowsToShow*n.options.rowHeight,d=n.options.showHeader?n.options.headerRowHeight:0,g=n.calcFooterHeight(),h=0;n.options.enableHorizontalScrollbar===f.scrollbars.ALWAYS&&(h=e.getScrollbarWidth());var i=0;if(angular.forEach(n.options.columnDefs,function(a){a.hasOwnProperty("filter")?1>i&&(i=1):a.hasOwnProperty("filters")&&i<a.filters.length&&(i=a.filters.length)}),n.options.enableFiltering&&!i){var j=n.options.columnDefs.length&&n.options.columnDefs.every(function(a){return a.enableFiltering===!1});j||(i=1)}var k=i*d,l=d+c+g+h+k;b.css("height",l+"px"),n.gridHeight=a.gridHeight=e.elementHeight(b)}function m(c){n.gridWidth=a.gridWidth=e.elementWidth(b),n.gridHeight=a.gridHeight=e.elementHeight(b),n.refreshCanvas(!0)}var n=h.grid;h.scrollbars=[],n.element=b;var o=100,p=20,q=0;j(),k(),n.renderingComplete(),i()}}}}}angular.module("ui.grid").controller("uiGridController",["$scope","$element","$attrs","gridUtil","$q","uiGridConstants","$templateCache","gridClassFactory","$timeout","$parse","$compile",function(a,b,c,d,e,f,g,h,i,j,k){function l(b,c){b&&b!==c&&(n.grid.options.columnDefs=a.uiGrid.columnDefs,n.grid.buildColumns({orderByColumnDefs:!0}).then(function(){n.grid.preCompileCellTemplates(),n.grid.callDataChangeCallbacks(f.dataChange.COLUMN)}))}function m(b){var d=[];if(n.grid.options.fastWatch&&(b=angular.isString(a.uiGrid.data)?n.grid.appScope[a.uiGrid.data]:a.uiGrid.data),p=b,b){var g=n.grid.columns.length>(n.grid.rowHeaderColumns?n.grid.rowHeaderColumns.length:0);!g&&!c.uiGridColumns&&0===n.grid.options.columnDefs.length&&b.length>0&&n.grid.buildColumnDefsFromData(b),!g&&(n.grid.options.columnDefs.length>0||b.length>0)&&d.push(n.grid.buildColumns().then(function(){n.grid.preCompileCellTemplates()})),e.all(d).then(function(){n.grid.modifyRows(p).then(function(){n.grid.redrawInPlace(!0),a.$evalAsync(function(){n.grid.refreshCanvas(!0),n.grid.callDataChangeCallbacks(f.dataChange.ROW)})})})}}var n=this;n.grid=h.createGrid(a.uiGrid),n.grid.appScope=n.grid.appScope||a.$parent,b.addClass("grid"+n.grid.id),n.grid.rtl="rtl"===d.getStyles(b[0]).direction,a.grid=n.grid,c.uiGridColumns&&c.$observe("uiGridColumns",function(a){n.grid.options.columnDefs=a,n.grid.buildColumns().then(function(){n.grid.preCompileCellTemplates(),n.grid.refreshCanvas(!0)})});var o=[];n.grid.options.fastWatch?(n.uiGrid=a.uiGrid,angular.isString(a.uiGrid.data)?(o.push(a.$parent.$watch(a.uiGrid.data,m)),o.push(a.$parent.$watch(function(){return n.grid.appScope[a.uiGrid.data]?n.grid.appScope[a.uiGrid.data].length:void 0},m))):(o.push(a.$parent.$watch(function(){return a.uiGrid.data},m)),o.push(a.$parent.$watch(function(){return a.uiGrid.data.length},function(){m(a.uiGrid.data)}))),o.push(a.$parent.$watch(function(){return a.uiGrid.columnDefs},l)),o.push(a.$parent.$watch(function(){return a.uiGrid.columnDefs.length},function(){l(a.uiGrid.columnDefs)}))):(angular.isString(a.uiGrid.data)?o.push(a.$parent.$watchCollection(a.uiGrid.data,m)):o.push(a.$parent.$watchCollection(function(){return a.uiGrid.data},m)),o.push(a.$parent.$watchCollection(function(){return a.uiGrid.columnDefs},l)));var p,q=a.$watch(function(){return n.grid.styleComputations},function(){n.grid.refreshCanvas(!0)});a.$on("$destroy",function(){o.forEach(function(a){a()}),q()}),n.fireEvent=function(b,c){("undefined"==typeof c||void 0===c)&&(c={}),("undefined"==typeof c.grid||void 0===c.grid)&&(c.grid=n.grid),a.$broadcast(b,c)},n.innerCompile=function(b){k(b)(a)}}]),angular.module("ui.grid").directive("uiGrid",a),a.$inject=["$compile","$templateCache","$timeout","$window","gridUtil","uiGridConstants"]}(),function(){"use strict";angular.module("ui.grid").directive("uiGridPinnedContainer",["gridUtil",function(a){return{restrict:"EA",replace:!0,template:'<div class="ui-grid-pinned-container"><div ui-grid-render-container container-id="side" row-container-name="\'body\'" col-container-name="side" bind-scroll-vertical="true" class="{{ side }} ui-grid-render-container-{{ side }}"></div></div>',scope:{side:"=uiGridPinnedContainer"},require:"^uiGrid",compile:function(){return{post:function(a,b,c,d){function e(){var a=this,b=0;a.visibleColumnCache.forEach(function(a){b+=a.drawnWidth});var c=a.getViewportAdjustment();return b+=c.width}function f(){if("left"===a.side||"right"===a.side){for(var b=h.renderContainers[a.side].visibleColumnCache,c=0,d=0;d<b.length;d++){var e=b[d];c+=e.drawnWidth||e.width||0}return c}}function g(){var c="";return("left"===a.side||"right"===a.side)&&(i=f(),b.attr("style",null),c+=".grid"+h.id+" .ui-grid-pinned-container-"+a.side+", .grid"+h.id+" .ui-grid-pinned-container-"+a.side+" .ui-grid-render-container-"+a.side+" .ui-grid-viewport { width: "+i+"px; } "),c}var h=d.grid,i=0;b.addClass("ui-grid-pinned-container-"+a.side),("left"===a.side||"right"===a.side)&&(h.renderContainers[a.side].getViewportWidth=e),h.renderContainers.body.registerViewportAdjuster(function(b){return i=f(),b.width-=i,b.side=a.side,b}),h.registerStyleComputation({priority:15,func:g})}}}}}])}(),function(){angular.module("ui.grid").factory("Grid",["$q","$compile","$parse","gridUtil","uiGridConstants","GridOptions","GridColumn","GridRow","GridApi","rowSorter","rowSearcher","GridRenderContainer","$timeout","ScrollEvent",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){function o(){}var p=function(a){function b(a){g.isScrollingVertically=!1,g.api.core.raise.scrollEnd(a),g.scrollDirection=e.scrollDirection.NONE}function c(a){g.isScrollingHorizontally=!1,g.api.core.raise.scrollEnd(a),g.scrollDirection=e.scrollDirection.NONE}var g=this;if(void 0===a||"undefined"==typeof a.id||!a.id)throw new Error("No ID provided. An ID must be given when creating a grid.");if(!/^[_a-zA-Z0-9-]+$/.test(a.id))throw new Error("Grid id '"+a.id+'" is invalid. It must follow CSS selector syntax rules.');g.id=a.id,delete a.id,g.options=f.initialize(a),g.appScope=g.options.appScopeProvider,g.headerHeight=g.options.headerRowHeight,g.footerHeight=g.calcFooterHeight(),g.columnFooterHeight=g.calcColumnFooterHeight(),g.rtl=!1,g.gridHeight=0,g.gridWidth=0,g.columnBuilders=[],g.rowBuilders=[],g.rowsProcessors=[],g.columnsProcessors=[],g.styleComputations=[],g.viewportAdjusters=[],g.rowHeaderColumns=[],g.dataChangeCallbacks={},g.verticalScrollSyncCallBackFns={},g.horizontalScrollSyncCallBackFns={},g.renderContainers={},g.renderContainers.body=new l("body",g),g.cellValueGetterCache={},g.getRowTemplateFn=null,g.rows=[],g.columns=[],g.isScrollingVertically=!1,g.isScrollingHorizontally=!1,g.scrollDirection=e.scrollDirection.NONE,g.disableScrolling=!1;var h=d.debounce(b,g.options.scrollDebounce),k=d.debounce(b,0),m=d.debounce(c,g.options.scrollDebounce),n=d.debounce(c,0);g.flagScrollingVertically=function(a){g.isScrollingVertically||g.isScrollingHorizontally||g.api.core.raise.scrollBegin(a),g.isScrollingVertically=!0,0!==g.options.scrollDebounce&&a.withDelay?h(a):k(a)},g.flagScrollingHorizontally=function(a){g.isScrollingVertically||g.isScrollingHorizontally||g.api.core.raise.scrollBegin(a),g.isScrollingHorizontally=!0,0!==g.options.scrollDebounce&&a.withDelay?m(a):n(a)},g.scrollbarHeight=0,g.scrollbarWidth=0,g.options.enableHorizontalScrollbar===e.scrollbars.ALWAYS&&(g.scrollbarHeight=d.getScrollbarWidth()),g.options.enableVerticalScrollbar===e.scrollbars.ALWAYS&&(g.scrollbarWidth=d.getScrollbarWidth()),g.api=new i(g),g.api.registerMethod("core","refresh",this.refresh),g.api.registerMethod("core","queueGridRefresh",this.queueGridRefresh),g.api.registerMethod("core","refreshRows",this.refreshRows),g.api.registerMethod("core","queueRefresh",this.queueRefresh),g.api.registerMethod("core","handleWindowResize",this.handleWindowResize),g.api.registerMethod("core","addRowHeaderColumn",this.addRowHeaderColumn),g.api.registerMethod("core","scrollToIfNecessary",function(a,b){return g.scrollToIfNecessary(a,b)}),g.api.registerMethod("core","scrollTo",function(a,b){return g.scrollTo(a,b)}),g.api.registerMethod("core","registerRowsProcessor",this.registerRowsProcessor),g.api.registerMethod("core","registerColumnsProcessor",this.registerColumnsProcessor),g.api.registerMethod("core","sortHandleNulls",j.handleNulls),g.api.registerEvent("core","sortChanged"),g.api.registerEvent("core","columnVisibilityChanged"),g.api.registerMethod("core","notifyDataChange",this.notifyDataChange),g.api.registerMethod("core","clearAllFilters",this.clearAllFilters),g.registerDataChangeCallback(g.columnRefreshCallback,[e.dataChange.COLUMN]),g.registerDataChangeCallback(g.processRowsCallback,[e.dataChange.EDIT]),g.registerDataChangeCallback(g.updateFooterHeightCallback,[e.dataChange.OPTIONS]),g.registerStyleComputation({priority:10,func:g.getFooterStyles})};p.prototype.calcFooterHeight=function(){if(!this.hasFooter())return 0;var a=0;return this.options.showGridFooter&&(a+=this.options.gridFooterHeight),a+=this.calcColumnFooterHeight()},p.prototype.calcColumnFooterHeight=function(){var a=0;return this.options.showColumnFooter&&(a+=this.options.columnFooterHeight),a},p.prototype.getFooterStyles=function(){var a=".grid"+this.id+" .ui-grid-footer-aggregates-row { height: "+this.options.columnFooterHeight+"px; }";return a+=" .grid"+this.id+" .ui-grid-footer-info { height: "+this.options.gridFooterHeight+"px; }"},p.prototype.hasFooter=function(){return this.options.showGridFooter||this.options.showColumnFooter},p.prototype.isRTL=function(){return this.rtl},p.prototype.registerColumnBuilder=function(a){this.columnBuilders.push(a)},p.prototype.buildColumnDefsFromData=function(a){this.options.columnDefs=d.getColumnsFromData(a,this.options.excludeProperties)},p.prototype.registerRowBuilder=function(a){this.rowBuilders.push(a)},p.prototype.registerDataChangeCallback=function(a,b,c){var f=d.nextUid();b||(b=[e.dataChange.ALL]),Array.isArray(b)||d.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: "+b),this.dataChangeCallbacks[f]={callback:a,types:b,_this:c};var g=this,h=function(){delete g.dataChangeCallbacks[f]};return h},p.prototype.callDataChangeCallbacks=function(a,b){angular.forEach(this.dataChangeCallbacks,function(b,c){(-1!==b.types.indexOf(e.dataChange.ALL)||-1!==b.types.indexOf(a)||a===e.dataChange.ALL)&&(b._this?b.callback.apply(b._this,this):b.callback(this))},this)},p.prototype.notifyDataChange=function(a){var b=e.dataChange;a===b.ALL||a===b.COLUMN||a===b.EDIT||a===b.ROW||a===b.OPTIONS?this.callDataChangeCallbacks(a):d.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: "+a)},p.prototype.columnRefreshCallback=function(a){a.buildColumns(),a.queueGridRefresh()},p.prototype.processRowsCallback=function(a){a.queueGridRefresh()},p.prototype.updateFooterHeightCallback=function(a){a.footerHeight=a.calcFooterHeight(),a.columnFooterHeight=a.calcColumnFooterHeight()},p.prototype.getColumn=function(a){var b=this.columns.filter(function(b){return b.colDef.name===a});return b.length>0?b[0]:null},p.prototype.getColDef=function(a){var b=this.options.columnDefs.filter(function(b){return b.name===a});return b.length>0?b[0]:null},p.prototype.assignTypes=function(){var a=this;a.options.columnDefs.forEach(function(b,c){if(!b.type){var e=new g(b,c,a),f=a.rows.length>0?a.rows[0]:null;f?b.type=d.guessType(a.getCellValue(f,e)):b.type="string"}})},p.prototype.isRowHeaderColumn=function(a){return-1!==this.rowHeaderColumns.indexOf(a)},p.prototype.addRowHeaderColumn=function(a,b){var c=this;void 0===b&&(b=0);var e=new g(a,d.nextUid(),c);e.isRowHeader=!0,c.isRTL()?(c.createRightContainer(),e.renderContainer="right"):(c.createLeftContainer(),e.renderContainer="left"),c.columnBuilders[0](a,e,c.options).then(function(){e.enableFiltering=!1,e.enableSorting=!1,e.enableHiding=!1,e.headerPriority=b,c.rowHeaderColumns.push(e),c.rowHeaderColumns=c.rowHeaderColumns.sort(function(a,b){return a.headerPriority-b.headerPriority}),c.buildColumns().then(function(){c.preCompileCellTemplates(),c.queueGridRefresh()})})},p.prototype.getOnlyDataColumns=function(){var a=this,b=[];return a.columns.forEach(function(c){-1===a.rowHeaderColumns.indexOf(c)&&b.push(c)}),b},p.prototype.buildColumns=function(b){var c={orderByColumnDefs:!1};angular.extend(c,b);var e,f=this,h=[],i=f.rowHeaderColumns.length;for(e=0;e<f.columns.length;e++)f.getColDef(f.columns[e].name)||(f.columns.splice(e,1),e--);for(var j=f.rowHeaderColumns.length-1;j>=0;j--)f.columns.unshift(f.rowHeaderColumns[j]);if(f.options.columnDefs.forEach(function(a,b){f.preprocessColDef(a);var c=f.getColumn(a.name);c?c.updateColumnDef(a,!1):(c=new g(a,d.nextUid(),f),f.columns.splice(b+i,0,c)),f.columnBuilders.forEach(function(b){h.push(b.call(f,a,c,f.options))})}),c.orderByColumnDefs){var k=f.columns.slice(0),l=Math.min(f.options.columnDefs.length,f.columns.length);for(e=0;l>e;e++)f.columns[e+i].name!==f.options.columnDefs[e].name?k[e+i]=f.getColumn(f.options.columnDefs[e].name):k[e+i]=f.columns[e+i];f.columns.length=0,Array.prototype.splice.apply(f.columns,[0,0].concat(k))}return a.all(h).then(function(){f.rows.length>0&&f.assignTypes()})},p.prototype.preCompileCellTemplate=function(a){var c=this,d=a.cellTemplate.replace(e.MODEL_COL_FIELD,c.getQualifiedColField(a));d=d.replace(e.COL_FIELD,"grid.getCellValue(row, col)");var f=b(d);a.compiledElementFn=f,a.compiledElementFnDefer&&a.compiledElementFnDefer.resolve(a.compiledElementFn)},p.prototype.preCompileCellTemplates=function(){var a=this;a.columns.forEach(function(b){b.cellTemplate?a.preCompileCellTemplate(b):b.cellTemplatePromise&&b.cellTemplatePromise.then(function(){a.preCompileCellTemplate(b)})})},p.prototype.getQualifiedColField=function(a){var b="row.entity";return a.field===e.ENTITY_BINDING?b:d.preEval(b+"."+a.field)},p.prototype.createLeftContainer=function(){this.hasLeftContainer()||(this.renderContainers.left=new l("left",this,{disableColumnOffset:!0}))},p.prototype.createRightContainer=function(){this.hasRightContainer()||(this.renderContainers.right=new l("right",this,{disableColumnOffset:!0}))},p.prototype.hasLeftContainer=function(){return void 0!==this.renderContainers.left},p.prototype.hasRightContainer=function(){return void 0!==this.renderContainers.right},p.prototype.preprocessColDef=function(a){var b=this;if(!a.field&&!a.name)throw new Error("colDef.name or colDef.field property is required");if(void 0===a.name&&void 0!==a.field){for(var c=a.field,d=2;b.getColumn(c);)c=a.field+d.toString(),d++;a.name=c}},p.prototype.newInN=function(a,b,c,d){for(var e=this,f=[],g=0;g<b.length;g++){for(var h=d?b[g][d]:b[g],i=!1,j=0;j<a.length;j++){var k=c?a[j][c]:a[j];if(e.options.rowEquality(h,k)){i=!0;break}}i||f.push(h)}return f},p.prototype.getRow=function(a,b){var c=this;b="undefined"==typeof b?c.rows:b;var d=b.filter(function(b){return c.options.rowEquality(b.entity,a)});return d.length>0?d[0]:null},p.prototype.modifyRows=function(b){var c=this,d=c.rows.slice(0),e=c.rowHashMap||c.createRowHashMap();c.rowHashMap=c.createRowHashMap(),c.rows.length=0,b.forEach(function(a,b){var f,g;g=c.options.enableRowHashing?e.get(a):c.getRow(a,d),g&&(f=g,f.entity=a),f||(f=c.processRowBuilders(new h(a,b,c))),c.rows.push(f),c.rowHashMap.put(a,f)}),c.assignTypes();var f=a.when(c.processRowsProcessors(c.rows)).then(function(a){return c.setVisibleRows(a)}),g=a.when(c.processColumnsProcessors(c.columns)).then(function(a){return c.setVisibleColumns(a)});return a.all([f,g])},p.prototype.addRows=function(a){for(var b=this,c=b.rows.length,d=0;d<a.length;d++){var e=b.processRowBuilders(new h(a[d],d+c,b));if(b.options.enableRowHashing){var f=b.rowHashMap.get(e.entity);f&&(f.row=e)}b.rows.push(e)}},p.prototype.processRowBuilders=function(a){var b=this;return b.rowBuilders.forEach(function(c){c.call(b,a,b.options)}),a},p.prototype.registerStyleComputation=function(a){this.styleComputations.push(a)},p.prototype.registerRowsProcessor=function(a,b){if(!angular.isFunction(a))throw"Attempt to register non-function rows processor: "+a;this.rowsProcessors.push({processor:a,priority:b}),this.rowsProcessors.sort(function(a,b){return a.priority-b.priority})},p.prototype.removeRowsProcessor=function(a){var b=-1;this.rowsProcessors.forEach(function(c,d){c.processor===a&&(b=d)}),-1!==b&&this.rowsProcessors.splice(b,1)},p.prototype.processRowsProcessors=function(b){function c(b,e){var g=d.rowsProcessors[b].processor;return a.when(g.call(d,e,d.columns)).then(function(a){if(!a)throw"Processor at index "+b+" did not return a set of renderable rows";if(!angular.isArray(a))throw"Processor at index "+b+" did not return an array";return b++,b<=d.rowsProcessors.length-1?c(b,a):void f.resolve(a)})}var d=this,e=b.slice(0);if(0===d.rowsProcessors.length)return a.when(e);var f=a.defer();return c(0,e),f.promise},p.prototype.setVisibleRows=function(a){var b=this;for(var c in b.renderContainers){var d=b.renderContainers[c];d.canvasHeightShouldUpdate=!0,"undefined"==typeof d.visibleRowCache?d.visibleRowCache=[]:d.visibleRowCache.length=0}for(var e=0;e<a.length;e++){var f=a[e],g="undefined"!=typeof f.renderContainer&&f.renderContainer?f.renderContainer:"body";f.visible&&b.renderContainers[g].visibleRowCache.push(f)}b.api.core.raise.rowsVisibleChanged(this.api),b.api.core.raise.rowsRendered(this.api)},p.prototype.registerColumnsProcessor=function(a,b){if(!angular.isFunction(a))throw"Attempt to register non-function rows processor: "+a;this.columnsProcessors.push({processor:a,priority:b}),this.columnsProcessors.sort(function(a,b){return a.priority-b.priority})},p.prototype.removeColumnsProcessor=function(a){var b=this.columnsProcessors.indexOf(a);"undefined"!=typeof b&&void 0!==b&&this.columnsProcessors.splice(b,1)},p.prototype.processColumnsProcessors=function(b){function c(b,g){var h=d.columnsProcessors[b].processor;return a.when(h.call(d,g,d.rows)).then(function(a){if(!a)throw"Processor at index "+b+" did not return a set of renderable rows";if(!angular.isArray(a))throw"Processor at index "+b+" did not return an array";return b++,b<=d.columnsProcessors.length-1?c(b,e):void f.resolve(e)})}var d=this,e=b.slice(0);if(0===d.columnsProcessors.length)return a.when(e);var f=a.defer();return c(0,e),f.promise},p.prototype.setVisibleColumns=function(a){var b=this;for(var c in b.renderContainers){var d=b.renderContainers[c];d.visibleColumnCache.length=0}for(var e=0;e<a.length;e++){var f=a[e];f.visible&&("undefined"!=typeof f.renderContainer&&f.renderContainer?b.renderContainers[f.renderContainer].visibleColumnCache.push(f):b.renderContainers.body.visibleColumnCache.push(f))}},p.prototype.handleWindowResize=function(a){var b=this;return b.gridWidth=d.elementWidth(b.element),b.gridHeight=d.elementHeight(b.element),b.queueRefresh()},p.prototype.queueRefresh=function(){var a=this;return a.refreshCanceller&&m.cancel(a.refreshCanceller),a.refreshCanceller=m(function(){a.refreshCanvas(!0)}),a.refreshCanceller.then(function(){a.refreshCanceller=null}),a.refreshCanceller},p.prototype.queueGridRefresh=function(){var a=this;return a.gridRefreshCanceller&&m.cancel(a.gridRefreshCanceller),a.gridRefreshCanceller=m(function(){a.refresh(!0)}),a.gridRefreshCanceller.then(function(){a.gridRefreshCanceller=null}),a.gridRefreshCanceller},p.prototype.updateCanvasHeight=function(){var a=this;for(var b in a.renderContainers)if(a.renderContainers.hasOwnProperty(b)){var c=a.renderContainers[b];c.canvasHeightShouldUpdate=!0}},p.prototype.buildStyles=function(){var a=this;a.customStyles="",a.styleComputations.sort(function(a,b){return null===a.priority?1:null===b.priority?-1:null===a.priority&&null===b.priority?0:a.priority-b.priority}).forEach(function(b){var c=b.func.call(a);angular.isString(c)&&(a.customStyles+="\n"+c)})},p.prototype.minColumnsToRender=function(){var a=this,b=this.getViewportWidth(),c=0,d=0;return a.columns.forEach(function(e,f){if(b>d)d+=e.drawnWidth,c++;else{for(var g=0,h=f;h>=f-c;h--)g+=a.columns[h].drawnWidth;b>g&&c++}}),c},p.prototype.getBodyHeight=function(){var a=this.getViewportHeight();return a},p.prototype.getViewportHeight=function(){var a=this,b=this.gridHeight-this.headerHeight-this.footerHeight,c=a.getViewportAdjustment();return b+=c.height},p.prototype.getViewportWidth=function(){var a=this,b=this.gridWidth,c=a.getViewportAdjustment();return b+=c.width},p.prototype.getHeaderViewportWidth=function(){var a=this.getViewportWidth();return a},p.prototype.addVerticalScrollSync=function(a,b){this.verticalScrollSyncCallBackFns[a]=b},p.prototype.addHorizontalScrollSync=function(a,b){this.horizontalScrollSyncCallBackFns[a]=b},p.prototype.scrollContainers=function(a,b){if(b.y){var c=["body","left","right"];this.flagScrollingVertically(b),"body"===a?c=["left","right"]:"left"===a?c=["body","right"]:"right"===a&&(c=["body","left"]);for(var d=0;d<c.length;d++){var e=c[d];this.verticalScrollSyncCallBackFns[e]&&this.verticalScrollSyncCallBackFns[e](b)}}if(b.x){var f=["body","bodyheader","bodyfooter"];this.flagScrollingHorizontally(b),"body"===a&&(f=["bodyheader","bodyfooter"]);for(var g=0;g<f.length;g++){var h=f[g];this.horizontalScrollSyncCallBackFns[h]&&this.horizontalScrollSyncCallBackFns[h](b)}}},p.prototype.registerViewportAdjuster=function(a){this.viewportAdjusters.push(a)},p.prototype.removeViewportAdjuster=function(a){var b=this.viewportAdjusters.indexOf(a);"undefined"!=typeof b&&void 0!==b&&this.viewportAdjusters.splice(b,1)},p.prototype.getViewportAdjustment=function(){var a=this,b={height:0,width:0};return a.viewportAdjusters.forEach(function(a){b=a.call(this,b)}),b},p.prototype.getVisibleRowCount=function(){return this.renderContainers.body.visibleRowCache.length},p.prototype.getVisibleRows=function(){return this.renderContainers.body.visibleRowCache},p.prototype.getVisibleColumnCount=function(){return this.renderContainers.body.visibleColumnCache.length},p.prototype.searchRows=function(a){return k.search(this,a,this.columns)},p.prototype.sortByColumn=function(a){return j.sort(this,a,this.columns)},p.prototype.getCellValue=function(a,b){return"undefined"!=typeof a.entity["$$"+b.uid]?a.entity["$$"+b.uid].rendered:this.options.flatEntityAccess&&"undefined"!=typeof b.field?a.entity[b.field]:(b.cellValueGetterCache||(b.cellValueGetterCache=c(a.getEntityQualifiedColField(b))),b.cellValueGetterCache(a))},p.prototype.getCellDisplayValue=function(a,b){if(!b.cellDisplayGetterCache){var d=b.cellFilter?" | "+b.cellFilter:"";"undefined"!=typeof a.entity["$$"+b.uid]?b.cellDisplayGetterCache=c(a.entity["$$"+b.uid].rendered+d):this.options.flatEntityAccess&&"undefined"!=typeof b.field?b.cellDisplayGetterCache=c(a.entity[b.field]+d):b.cellDisplayGetterCache=c(a.getEntityQualifiedColField(b)+d)}return b.cellDisplayGetterCache(a)},p.prototype.getNextColumnSortPriority=function(){var a=this,b=0;return a.columns.forEach(function(a){a.sort&&void 0!==a.sort.priority&&a.sort.priority>=b&&(b=a.sort.priority+1)}),b},p.prototype.resetColumnSorting=function(a){var b=this;b.columns.forEach(function(b){b===a||b.suppressRemoveSort||(b.sort={})})},p.prototype.getColumnSorting=function(){var a,b=this,c=[];return a=b.columns.slice(0),a.sort(j.prioritySort).forEach(function(a){a.sort&&"undefined"!=typeof a.sort.direction&&a.sort.direction&&(a.sort.direction===e.ASC||a.sort.direction===e.DESC)&&c.push(a)}),c},p.prototype.sortColumn=function(b,c,d){var e=this,f=null;if("undefined"==typeof b||!b)throw new Error("No column parameter provided");if("boolean"==typeof c?d=c:f=c,d?void 0===b.sort.priority&&(b.sort.priority=e.getNextColumnSortPriority()):(e.resetColumnSorting(b),b.sort.priority=void 0,b.sort.priority=e.getNextColumnSortPriority()),f)b.sort.direction=f;else{var g=b.sortDirectionCycle.indexOf(b.sort.direction?b.sort.direction:null);g=(g+1)%b.sortDirectionCycle.length,b.colDef&&b.suppressRemoveSort&&!b.sortDirectionCycle[g]&&(g=(g+1)%b.sortDirectionCycle.length),b.sortDirectionCycle[g]?b.sort.direction=b.sortDirectionCycle[g]:q(b,e)}return e.api.core.raise.sortChanged(e,e.getColumnSorting()),a.when(b)};var q=function(a,b){b.columns.forEach(function(b){b.sort&&void 0!==b.sort.priority&&b.sort.priority>a.sort.priority&&(b.sort.priority-=1)}),a.sort={}};return p.prototype.renderingComplete=function(){angular.isFunction(this.options.onRegisterApi)&&this.options.onRegisterApi(this.api),this.api.core.raise.renderingComplete(this.api)},p.prototype.createRowHashMap=function(){var a=this,b=new o;return b.grid=a,b},p.prototype.refresh=function(b){var c=this,d=c.processRowsProcessors(c.rows).then(function(a){c.setVisibleRows(a)}),e=c.processColumnsProcessors(c.columns).then(function(a){c.setVisibleColumns(a)});return a.all([d,e]).then(function(){c.redrawInPlace(b),c.refreshCanvas(!0)})},p.prototype.refreshRows=function(){var a=this;return a.processRowsProcessors(a.rows).then(function(b){a.setVisibleRows(b),a.redrawInPlace(),a.refreshCanvas(!0)})},p.prototype.refreshCanvas=function(b){var c=this;b&&c.buildStyles();var e=a.defer(),f=[];for(var g in c.renderContainers)if(c.renderContainers.hasOwnProperty(g)){var h=c.renderContainers[g];if(null===h.canvasWidth||isNaN(h.canvasWidth))continue;(h.header||h.headerCanvas)&&(h.explicitHeaderHeight=h.explicitHeaderHeight||null,h.explicitHeaderCanvasHeight=h.explicitHeaderCanvasHeight||null,f.push(h))}return f.length>0?(b&&c.buildStyles(),m(function(){var a,g,h=!1,i=0,j=0,k=function(a,b){return a!==b&&(h=!0),b};for(a=0;a<f.length;a++)if(g=f[a],null!==g.canvasWidth&&!isNaN(g.canvasWidth)){if(g.header){var l=g.headerHeight=k(g.headerHeight,parseInt(d.outerElementHeight(g.header),10)),m=d.getBorderSize(g.header,"top"),n=d.getBorderSize(g.header,"bottom"),o=parseInt(l-m-n,10);o=0>o?0:o,g.innerHeaderHeight=o,!g.explicitHeaderHeight&&o>i&&(i=o)}if(g.headerCanvas){var p=g.headerCanvasHeight=k(g.headerCanvasHeight,parseInt(d.outerElementHeight(g.headerCanvas),10));!g.explicitHeaderCanvasHeight&&p>j&&(j=p)}}for(a=0;a<f.length;a++)g=f[a],i>0&&"undefined"!=typeof g.headerHeight&&null!==g.headerHeight&&(g.explicitHeaderHeight||g.headerHeight<i)&&(g.explicitHeaderHeight=k(g.explicitHeaderHeight,i)),j>0&&"undefined"!=typeof g.headerCanvasHeight&&null!==g.headerCanvasHeight&&(g.explicitHeaderCanvasHeight||g.headerCanvasHeight<j)&&(g.explicitHeaderCanvasHeight=k(g.explicitHeaderCanvasHeight,j));b&&h&&c.buildStyles(),e.resolve()})):m(function(){e.resolve()}),e.promise},p.prototype.redrawInPlace=function(a){var b=this;for(var c in b.renderContainers){var d=b.renderContainers[c];a?(d.adjustRows(d.prevScrollTop,null),d.adjustColumns(d.prevScrollLeft,null)):(d.adjustRows(null,d.prevScrolltopPercentage),d.adjustColumns(null,d.prevScrollleftPercentage))}},p.prototype.hasLeftContainerColumns=function(){return this.hasLeftContainer()&&this.renderContainers.left.renderedColumns.length>0},p.prototype.hasRightContainerColumns=function(){return this.hasRightContainer()&&this.renderContainers.right.renderedColumns.length>0},p.prototype.scrollToIfNecessary=function(b,c){var d=this,e=new n(d,"uiGrid.scrollToIfNecessary"),f=d.renderContainers.body.visibleRowCache,g=d.renderContainers.body.visibleColumnCache,h=d.renderContainers.body.prevScrollTop+d.headerHeight;h=0>h?0:h;var i=d.renderContainers.body.prevScrollLeft,j=d.renderContainers.body.prevScrollTop+d.gridHeight-d.renderContainers.body.headerHeight-d.footerHeight-d.scrollbarWidth,k=d.renderContainers.body.prevScrollLeft+Math.ceil(d.renderContainers.body.getViewportWidth());if(null!==b){var l=f.indexOf(b),m=d.renderContainers.body.getCanvasHeight()-d.renderContainers.body.getViewportHeight(),o=l*d.options.rowHeight+d.headerHeight;o=0>o?0:o;var p,q;h>o?(p=d.renderContainers.body.prevScrollTop-(h-o),q=p/m,e.y={percentage:q}):o>j&&(p=o-j+d.renderContainers.body.prevScrollTop,q=p/m,e.y={percentage:q})}if(null!==c){for(var r=g.indexOf(c),s=d.renderContainers.body.getCanvasWidth()-d.renderContainers.body.getViewportWidth(),t=0,u=0;r>u;u++){var v=g[u];t+=v.drawnWidth}t=0>t?0:t;var w=t+c.drawnWidth;w=0>w?0:w;var x,y;i>t?(x=d.renderContainers.body.prevScrollLeft-(i-t),y=x/s,y=y>1?1:y,e.x={percentage:y}):w>k&&(x=w-k+d.renderContainers.body.prevScrollLeft,y=x/s,y=y>1?1:y,e.x={percentage:y})}var z=a.defer();if(e.y||e.x){e.withDelay=!1,d.scrollContainers("",e);var A=d.api.core.on.scrollEnd(null,function(){z.resolve(e),A()})}else z.resolve();return z.promise},p.prototype.scrollTo=function(a,b){var c=null,d=null;return null!==a&&"undefined"!=typeof a&&(c=this.getRow(a)),null!==b&&"undefined"!=typeof b&&(d=this.getColumn(b.name?b.name:b.field)),this.scrollToIfNecessary(c,d)},p.prototype.clearAllFilters=function(a,b,c){return void 0===a&&(a=!0),void 0===b&&(b=!1),void 0===c&&(c=!1),this.columns.forEach(function(a){a.filters.forEach(function(a){a.term=void 0,b&&(a.condition=void 0),c&&(a.flags=void 0)})}),a?this.refreshRows():void 0},o.prototype={put:function(a,b){this[this.grid.options.rowIdentity(a)]=b},get:function(a){return this[this.grid.options.rowIdentity(a)]},remove:function(a){var b=this[a=this.grid.options.rowIdentity(a)];return delete this[a],b}},p}])}(),function(){angular.module("ui.grid").factory("GridApi",["$q","$rootScope","gridUtil","uiGridConstants","GridRow","uiGridGridMenuService",function(a,b,c,d,e,f){
+function g(a,c,d,e){return b.$on(a,function(a){var b=Array.prototype.slice.call(arguments);b.splice(0,1),c.apply(e?e:d.api,b)})}var h=function(a){this.grid=a,this.listeners=[],this.registerEvent("core","renderingComplete"),this.registerEvent("core","filterChanged"),this.registerMethod("core","setRowInvisible",e.prototype.setRowInvisible),this.registerMethod("core","clearRowInvisible",e.prototype.clearRowInvisible),this.registerMethod("core","getVisibleRows",this.grid.getVisibleRows),this.registerEvent("core","rowsVisibleChanged"),this.registerEvent("core","rowsRendered"),this.registerEvent("core","scrollBegin"),this.registerEvent("core","scrollEnd"),this.registerEvent("core","canvasHeightChanged"),this.registerEvent("core","gridDimensionChanged")};return h.prototype.suppressEvents=function(a,b){var c=this,d=angular.isArray(a)?a:[a],e=c.listeners.filter(function(a){return d.some(function(b){return a.handler===b})});e.forEach(function(a){a.dereg()}),b(),e.forEach(function(a){a.dereg=g(a.eventId,a.handler,c.grid,a._this)})},h.prototype.registerEvent=function(a,d){var e=this;e[a]||(e[a]={});var f=e[a];f.on||(f.on={},f.raise={});var h=e.grid.id+a+d;f.raise[d]=function(){b.$emit.apply(b,[h].concat(Array.prototype.slice.call(arguments)))},f.on[d]=function(b,f,i){if(null!==b&&"undefined"==typeof b.$on)return void c.logError("asked to listen on "+a+".on."+d+" but scope wasn't passed in the input parameters. It is legitimate to pass null, but you've passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering");var j=g(h,f,e.grid,i),k={handler:f,dereg:j,eventId:h,scope:b,_this:i};e.listeners.push(k);var l=function(){k.dereg();var a=e.listeners.indexOf(k);e.listeners.splice(a,1)};return b&&b.$on("$destroy",function(){l()}),l}},h.prototype.registerEventsFromObject=function(a){var b=this,c=[];angular.forEach(a,function(a,b){var d={name:b,events:[]};angular.forEach(a,function(a,b){d.events.push(b)}),c.push(d)}),c.forEach(function(a){a.events.forEach(function(c){b.registerEvent(a.name,c)})})},h.prototype.registerMethod=function(a,b,d,e){this[a]||(this[a]={});var f=this[a];f[b]=c.createBoundedWrapper(e||this.grid,d)},h.prototype.registerMethodsFromObject=function(a,b){var c=this,d=[];angular.forEach(a,function(a,b){var c={name:b,methods:[]};angular.forEach(a,function(a,b){c.methods.push({name:b,fn:a})}),d.push(c)}),d.forEach(function(a){a.methods.forEach(function(d){c.registerMethod(a.name,d.name,d.fn,b)})})},h}])}(),function(){angular.module("ui.grid").factory("GridColumn",["gridUtil","uiGridConstants","i18nService",function(a,b,c){function d(a,c,d){var e=this;e.grid=d,e.uid=c,e.updateColumnDef(a,!0),e.aggregationValue=void 0,e.updateAggregationValue=function(){if(!e.aggregationType)return void(e.aggregationValue=void 0);var a=0,c=e.grid.getVisibleRows(),d=function(){var a=[];return c.forEach(function(b){var c=e.grid.getCellValue(b,e),d=Number(c);isNaN(d)||a.push(d)}),a};angular.isFunction(e.aggregationType)?e.aggregationValue=e.aggregationType(c,e):e.aggregationType===b.aggregationTypes.count?e.aggregationValue=e.grid.getVisibleRowCount():e.aggregationType===b.aggregationTypes.sum?(d().forEach(function(b){a+=b}),e.aggregationValue=a):e.aggregationType===b.aggregationTypes.avg?(d().forEach(function(b){a+=b}),a/=d().length,e.aggregationValue=a):e.aggregationType===b.aggregationTypes.min?e.aggregationValue=Math.min.apply(null,d()):e.aggregationType===b.aggregationTypes.max?e.aggregationValue=Math.max.apply(null,d()):e.aggregationValue=" "},this.getAggregationValue=function(){return e.aggregationValue}}return d.prototype.hideColumn=function(){this.colDef.visible=!1},d.prototype.setPropertyOrDefault=function(a,b,c){var d=this;"undefined"!=typeof a[b]&&a[b]?d[b]=a[b]:"undefined"!=typeof d[b]?d[b]=d[b]:d[b]=c?c:{}},d.prototype.updateColumnDef=function(c,d){var e=this;if(e.colDef=c,void 0===c.name)throw new Error("colDef.name is required for column at index "+e.grid.options.columnDefs.indexOf(c));if(e.displayName=void 0===c.displayName?a.readableColumnName(c.name):c.displayName,!angular.isNumber(e.width)||!e.hasCustomWidth||c.allowCustomWidthOverride){var f=c.width,g="Cannot parse column width '"+f+"' for column named '"+c.name+"'";if(e.hasCustomWidth=!1,angular.isString(f)||angular.isNumber(f))if(angular.isString(f))if(a.endsWith(f,"%")){var h=f.replace(/%/g,""),i=parseInt(h,10);if(isNaN(i))throw new Error(g);e.width=f}else if(f.match(/^(\d+)$/))e.width=parseInt(f.match(/^(\d+)$/)[1],10);else{if(!f.match(/^\*+$/))throw new Error(g);e.width=f}else e.width=f;else e.width="*"}["minWidth","maxWidth"].forEach(function(a){var b=c[a],d="Cannot parse column "+a+" '"+b+"' for column named '"+c.name+"'";if(angular.isString(b)||angular.isNumber(b))if(angular.isString(b)){if(!b.match(/^(\d+)$/))throw new Error(d);e[a]=parseInt(b.match(/^(\d+)$/)[1],10)}else e[a]=b;else e[a]="minWidth"===a?30:9e3}),e.field=void 0===c.field?c.name:c.field,"string"!=typeof e.field&&a.logError("Field is not a string, this is likely to break the code, Field is: "+e.field),e.name=c.name,e.displayName=void 0===c.displayName?a.readableColumnName(c.name):c.displayName,e.aggregationType=angular.isDefined(c.aggregationType)?c.aggregationType:null,e.footerCellTemplate=angular.isDefined(c.footerCellTemplate)?c.footerCellTemplate:null,"undefined"==typeof c.cellTooltip||c.cellTooltip===!1?e.cellTooltip=!1:c.cellTooltip===!0?e.cellTooltip=function(a,b){return e.grid.getCellValue(a,b)}:"function"==typeof c.cellTooltip?e.cellTooltip=c.cellTooltip:e.cellTooltip=function(a,b){return b.colDef.cellTooltip},"undefined"==typeof c.headerTooltip||c.headerTooltip===!1?e.headerTooltip=!1:c.headerTooltip===!0?e.headerTooltip=function(a){return a.displayName}:"function"==typeof c.headerTooltip?e.headerTooltip=c.headerTooltip:e.headerTooltip=function(a){return a.colDef.headerTooltip},e.footerCellClass=c.footerCellClass,e.cellClass=c.cellClass,e.headerCellClass=c.headerCellClass,e.cellFilter=c.cellFilter?c.cellFilter:"",e.sortCellFiltered=c.sortCellFiltered?!0:!1,e.filterCellFiltered=c.filterCellFiltered?!0:!1,e.headerCellFilter=c.headerCellFilter?c.headerCellFilter:"",e.footerCellFilter=c.footerCellFilter?c.footerCellFilter:"",e.visible=a.isNullOrUndefined(c.visible)||c.visible,e.headerClass=c.headerClass,e.enableSorting="undefined"!=typeof c.enableSorting?c.enableSorting:e.grid.options.enableSorting,e.sortingAlgorithm=c.sortingAlgorithm,e.sortDirectionCycle="undefined"!=typeof c.sortDirectionCycle?c.sortDirectionCycle:[null,b.ASC,b.DESC],"undefined"==typeof e.suppressRemoveSort&&(e.suppressRemoveSort="undefined"!=typeof c.suppressRemoveSort?c.suppressRemoveSort:!1),e.enableFiltering="undefined"!=typeof c.enableFiltering?c.enableFiltering:!0,e.setPropertyOrDefault(c,"menuItems",[]),d&&e.setPropertyOrDefault(c,"sort");var j=[];c.filter?j.push(c.filter):c.filters?j=c.filters:j.push({}),d?(e.setPropertyOrDefault(c,"filter"),e.setPropertyOrDefault(c,"extraStyle"),e.setPropertyOrDefault(c,"filters",j)):e.filters.length===j.length&&e.filters.forEach(function(a,b){"undefined"!=typeof j[b].placeholder&&(a.placeholder=j[b].placeholder),"undefined"!=typeof j[b].ariaLabel&&(a.ariaLabel=j[b].ariaLabel),"undefined"!=typeof j[b].flags&&(a.flags=j[b].flags),"undefined"!=typeof j[b].type&&(a.type=j[b].type),"undefined"!=typeof j[b].selectOptions&&(a.selectOptions=j[b].selectOptions)})},d.prototype.unsort=function(){this.sort={},this.grid.api.core.raise.sortChanged(this.grid,this.grid.getColumnSorting())},d.prototype.getColClass=function(a){var c=b.COL_CLASS_PREFIX+this.uid;return a?"."+c:c},d.prototype.isPinnedLeft=function(){return"left"===this.renderContainer},d.prototype.isPinnedRight=function(){return"right"===this.renderContainer},d.prototype.getColClassDefinition=function(){return" .grid"+this.grid.id+" "+this.getColClass(!0)+" { min-width: "+this.drawnWidth+"px; max-width: "+this.drawnWidth+"px; }"},d.prototype.getRenderContainer=function(){var a=this,b=a.renderContainer;return(null===b||""===b||void 0===b)&&(b="body"),a.grid.renderContainers[b]},d.prototype.showColumn=function(){this.colDef.visible=!0},d.prototype.getAggregationText=function(){var a=this;if(a.colDef.aggregationHideLabel)return"";if(a.colDef.aggregationLabel)return a.colDef.aggregationLabel;switch(a.colDef.aggregationType){case b.aggregationTypes.count:return c.getSafeText("aggregation.count");case b.aggregationTypes.sum:return c.getSafeText("aggregation.sum");case b.aggregationTypes.avg:return c.getSafeText("aggregation.avg");case b.aggregationTypes.min:return c.getSafeText("aggregation.min");case b.aggregationTypes.max:return c.getSafeText("aggregation.max");default:return""}},d.prototype.getCellTemplate=function(){var a=this;return a.cellTemplatePromise},d.prototype.getCompiledElementFn=function(){var a=this;return a.compiledElementFnDefer.promise},d}])}(),function(){angular.module("ui.grid").factory("GridOptions",["gridUtil","uiGridConstants",function(a,b){return{initialize:function(c){return c.onRegisterApi=c.onRegisterApi||angular.noop(),c.data=c.data||[],c.columnDefs=c.columnDefs||[],c.excludeProperties=c.excludeProperties||["$$hashKey"],c.enableRowHashing=c.enableRowHashing!==!1,c.rowIdentity=c.rowIdentity||function(b){return a.hashKey(b)},c.getRowIdentity=c.getRowIdentity||function(a){return a.$$hashKey},c.flatEntityAccess=c.flatEntityAccess===!0,c.showHeader="undefined"!=typeof c.showHeader?c.showHeader:!0,c.showHeader?c.headerRowHeight="undefined"!=typeof c.headerRowHeight?c.headerRowHeight:30:c.headerRowHeight=0,"string"==typeof c.rowHeight?c.rowHeight=parseInt(c.rowHeight)||30:c.rowHeight=c.rowHeight||30,c.minRowsToShow="undefined"!=typeof c.minRowsToShow?c.minRowsToShow:10,c.showGridFooter=c.showGridFooter===!0,c.showColumnFooter=c.showColumnFooter===!0,c.columnFooterHeight="undefined"!=typeof c.columnFooterHeight?c.columnFooterHeight:30,c.gridFooterHeight="undefined"!=typeof c.gridFooterHeight?c.gridFooterHeight:30,c.columnWidth="undefined"!=typeof c.columnWidth?c.columnWidth:50,c.maxVisibleColumnCount="undefined"!=typeof c.maxVisibleColumnCount?c.maxVisibleColumnCount:200,c.virtualizationThreshold="undefined"!=typeof c.virtualizationThreshold?c.virtualizationThreshold:20,c.columnVirtualizationThreshold="undefined"!=typeof c.columnVirtualizationThreshold?c.columnVirtualizationThreshold:10,c.excessRows="undefined"!=typeof c.excessRows?c.excessRows:4,c.scrollThreshold="undefined"!=typeof c.scrollThreshold?c.scrollThreshold:4,c.excessColumns="undefined"!=typeof c.excessColumns?c.excessColumns:4,c.horizontalScrollThreshold="undefined"!=typeof c.horizontalScrollThreshold?c.horizontalScrollThreshold:2,c.aggregationCalcThrottle="undefined"!=typeof c.aggregationCalcThrottle?c.aggregationCalcThrottle:500,c.wheelScrollThrottle="undefined"!=typeof c.wheelScrollThrottle?c.wheelScrollThrottle:70,c.scrollDebounce="undefined"!=typeof c.scrollDebounce?c.scrollDebounce:300,c.enableSorting=c.enableSorting!==!1,c.enableFiltering=c.enableFiltering===!0,c.enableColumnMenus=c.enableColumnMenus!==!1,c.enableVerticalScrollbar="undefined"!=typeof c.enableVerticalScrollbar?c.enableVerticalScrollbar:b.scrollbars.ALWAYS,c.enableHorizontalScrollbar="undefined"!=typeof c.enableHorizontalScrollbar?c.enableHorizontalScrollbar:b.scrollbars.ALWAYS,c.enableMinHeightCheck=c.enableMinHeightCheck!==!1,c.minimumColumnSize="undefined"!=typeof c.minimumColumnSize?c.minimumColumnSize:10,c.rowEquality=c.rowEquality||function(a,b){return a===b},c.headerTemplate=c.headerTemplate||null,c.footerTemplate=c.footerTemplate||"ui-grid/ui-grid-footer",c.gridFooterTemplate=c.gridFooterTemplate||"ui-grid/ui-grid-grid-footer",c.rowTemplate=c.rowTemplate||"ui-grid/ui-grid-row",c.gridMenuTemplate=c.gridMenuTemplate||"ui-grid/uiGridMenu",c.appScopeProvider=c.appScopeProvider||null,c}}}])}(),function(){angular.module("ui.grid").factory("GridRenderContainer",["gridUtil","uiGridConstants",function(a,b){function c(a,b,c){var d=this;d.name=a,d.grid=b,d.visibleRowCache=[],d.visibleColumnCache=[],d.renderedRows=[],d.renderedColumns=[],d.prevScrollTop=0,d.prevScrolltopPercentage=0,d.prevRowScrollIndex=0,d.prevScrollLeft=0,d.prevScrollleftPercentage=0,d.prevColumnScrollIndex=0,d.columnStyles="",d.viewportAdjusters=[],d.hasHScrollbar=!1,d.hasVScrollbar=!1,d.canvasHeightShouldUpdate=!0,d.$$canvasHeight=0,c&&angular.isObject(c)&&angular.extend(d,c),b.registerStyleComputation({priority:5,func:function(){return d.updateColumnWidths(),d.columnStyles}})}return c.prototype.reset=function(){this.visibleColumnCache.length=0,this.visibleRowCache.length=0,this.renderedRows.length=0,this.renderedColumns.length=0},c.prototype.containsColumn=function(a){return-1!==this.visibleColumnCache.indexOf(a)},c.prototype.minRowsToRender=function(){for(var a=this,b=0,c=0,d=a.getViewportHeight(),e=a.visibleRowCache.length-1;d>c&&e>=0;e--)c+=a.visibleRowCache[e].height,b++;return b},c.prototype.minColumnsToRender=function(){for(var a=this,b=this.getViewportWidth(),c=0,d=0,e=0;e<a.visibleColumnCache.length;e++){var f=a.visibleColumnCache[e];if(b>d)d+=f.drawnWidth?f.drawnWidth:0,c++;else{for(var g=0,h=e;h>=e-c;h--)g+=a.visibleColumnCache[h].drawnWidth?a.visibleColumnCache[h].drawnWidth:0;b>g&&c++}}return c},c.prototype.getVisibleRowCount=function(){return this.visibleRowCache.length},c.prototype.registerViewportAdjuster=function(a){this.viewportAdjusters.push(a)},c.prototype.removeViewportAdjuster=function(a){var b=this.viewportAdjusters.indexOf(a);b>-1&&this.viewportAdjusters.splice(b,1)},c.prototype.getViewportAdjustment=function(){var a=this,b={height:0,width:0};return a.viewportAdjusters.forEach(function(a){b=a.call(this,b)}),b},c.prototype.getMargin=function(a){var b=this,c=0;return b.viewportAdjusters.forEach(function(b){var d=b.call(this,{height:0,width:0});d.side&&d.side===a&&(c+=-1*d.width)}),c},c.prototype.getViewportHeight=function(){var a=this,b=a.headerHeight?a.headerHeight:a.grid.headerHeight,c=a.grid.gridHeight-b-a.grid.footerHeight,d=a.getViewportAdjustment();return c+=d.height},c.prototype.getViewportWidth=function(){var a=this,b=a.grid.gridWidth,c=a.getViewportAdjustment();return b+=c.width},c.prototype.getHeaderViewportWidth=function(){var a=this.getViewportWidth();return a},c.prototype.getCanvasHeight=function(){var a=this;if(!a.canvasHeightShouldUpdate)return a.$$canvasHeight;var b=a.$$canvasHeight;return a.$$canvasHeight=0,a.visibleRowCache.forEach(function(b){a.$$canvasHeight+=b.height}),a.canvasHeightShouldUpdate=!1,a.grid.api.core.raise.canvasHeightChanged(b,a.$$canvasHeight),a.$$canvasHeight},c.prototype.getVerticalScrollLength=function(){return this.getCanvasHeight()-this.getViewportHeight()+this.grid.scrollbarHeight!==0?this.getCanvasHeight()-this.getViewportHeight()+this.grid.scrollbarHeight:-1},c.prototype.getHorizontalScrollLength=function(){return this.getCanvasWidth()-this.getViewportWidth()+this.grid.scrollbarWidth!==0?this.getCanvasWidth()-this.getViewportWidth()+this.grid.scrollbarWidth:-1},c.prototype.getCanvasWidth=function(){var a=this,b=a.canvasWidth;return b},c.prototype.setRenderedRows=function(a){this.renderedRows.length=a.length;for(var b=0;b<a.length;b++)this.renderedRows[b]=a[b]},c.prototype.setRenderedColumns=function(a){this.renderedColumns.length=a.length;for(var b=0;b<a.length;b++)this.renderedColumns[b]=a[b];this.updateColumnOffset()},c.prototype.updateColumnOffset=function(){for(var a=0,b=0;b<this.currentFirstColumn;b++)a+=this.visibleColumnCache[b].drawnWidth;this.columnOffset=a},c.prototype.scrollVertical=function(a){var c=-1;if(a!==this.prevScrollTop){var d=a-this.prevScrollTop;d>0&&(this.grid.scrollDirection=b.scrollDirection.DOWN),0>d&&(this.grid.scrollDirection=b.scrollDirection.UP);var e=this.getVerticalScrollLength();return c=a/e,c>1&&(c=1),0>c&&(c=0),this.adjustScrollVertical(a,c),c}},c.prototype.scrollHorizontal=function(a){var c=-1;if(a!==this.prevScrollLeft){var d=a-this.prevScrollLeft;d>0&&(this.grid.scrollDirection=b.scrollDirection.RIGHT),0>d&&(this.grid.scrollDirection=b.scrollDirection.LEFT);var e=this.getHorizontalScrollLength();return c=0!==e?a/e:0,this.adjustScrollHorizontal(a,c),c}},c.prototype.adjustScrollVertical=function(a,b,c){(this.prevScrollTop!==a||c)&&(("undefined"==typeof a||void 0===a||null===a)&&(a=(this.getCanvasHeight()-this.getViewportHeight())*b),this.adjustRows(a,b,!1),this.prevScrollTop=a,this.prevScrolltopPercentage=b,this.grid.queueRefresh())},c.prototype.adjustScrollHorizontal=function(a,b,c){(this.prevScrollLeft!==a||c)&&(("undefined"==typeof a||void 0===a||null===a)&&(a=(this.getCanvasWidth()-this.getViewportWidth())*b),this.adjustColumns(a,b),this.prevScrollLeft=a,this.prevScrollleftPercentage=b,this.grid.queueRefresh())},c.prototype.adjustRows=function(a,b,c){var d=this,e=d.minRowsToRender(),f=d.visibleRowCache,g=f.length-e;"undefined"!=typeof b&&null!==b||!a||(b=a/d.getVerticalScrollLength());var h=Math.ceil(Math.min(g,g*b));h>g&&(h=g);var i=[];if(f.length>d.grid.options.virtualizationThreshold){if("undefined"!=typeof a&&null!==a){if(!d.grid.suppressParentScrollDown&&d.prevScrollTop<a&&h<d.prevRowScrollIndex+d.grid.options.scrollThreshold&&g>h)return;if(!d.grid.suppressParentScrollUp&&d.prevScrollTop>a&&h>d.prevRowScrollIndex-d.grid.options.scrollThreshold&&g>h)return}var j={},k={};j=Math.max(0,h-d.grid.options.excessRows),k=Math.min(f.length,h+e+d.grid.options.excessRows),i=[j,k]}else{var l=d.visibleRowCache.length;i=[0,Math.max(l,e+d.grid.options.excessRows)]}d.updateViewableRowRange(i),d.prevRowScrollIndex=h},c.prototype.adjustColumns=function(a,b){var c=this,d=c.minColumnsToRender(),e=c.visibleColumnCache,f=e.length-d;"undefined"!=typeof b&&null!==b||!a||(b=a/c.getHorizontalScrollLength());var g=Math.ceil(Math.min(f,f*b));g>f&&(g=f);var h=[];if(e.length>c.grid.options.columnVirtualizationThreshold&&c.getCanvasWidth()>c.getViewportWidth()){var i=Math.max(0,g-c.grid.options.excessColumns),j=Math.min(e.length,g+d+c.grid.options.excessColumns);h=[i,j]}else{var k=c.visibleColumnCache.length;h=[0,Math.max(k,d+c.grid.options.excessColumns)]}c.updateViewableColumnRange(h),c.prevColumnScrollIndex=g},c.prototype.updateViewableRowRange=function(a){var b=this.visibleRowCache.slice(a[0],a[1]);this.currentTopRow=a[0],this.setRenderedRows(b)},c.prototype.updateViewableColumnRange=function(a){var b=this.visibleColumnCache.slice(a[0],a[1]);this.currentFirstColumn=a[0],this.setRenderedColumns(b)},c.prototype.headerCellWrapperStyle=function(){var a=this;if(0!==a.currentFirstColumn){var b=a.columnOffset;return a.grid.isRTL()?{"margin-right":b+"px"}:{"margin-left":b+"px"}}return null},c.prototype.updateColumnWidths=function(){var b=this,c=[],d=0,e=0,f="",g=b.grid.getViewportWidth()-b.grid.scrollbarWidth,h=[];angular.forEach(b.grid.renderContainers,function(a,b){h=h.concat(a.visibleColumnCache)}),h.forEach(function(b,f){var h=0;b.visible&&(angular.isNumber(b.width)?(h=parseInt(b.width,10),e+=h,b.drawnWidth=h):a.endsWith(b.width,"%")?(h=parseFloat(parseInt(b.width.replace(/%/g,""),10)/100*g),h>b.maxWidth&&(h=b.maxWidth),h<b.minWidth&&(h=b.minWidth),e+=h,b.drawnWidth=h):angular.isString(b.width)&&-1!==b.width.indexOf("*")&&(d+=b.width.length,c.push(b)))});var i=g-e;if(c.length>0){var j=i/d;c.forEach(function(a){var b=parseInt(a.width.length*j,10);b>a.maxWidth&&(b=a.maxWidth),b<a.minWidth&&(b=a.minWidth),e+=b,a.drawnWidth=b})}for(var k=function(a){a.drawnWidth<a.maxWidth&&l>0&&(a.drawnWidth++,e++,l--,m=!0)},l=g-e,m=!0;l>0&&m;)m=!1,c.forEach(k);var n=function(a){a.drawnWidth>a.minWidth&&o>0&&(a.drawnWidth--,e--,o--,m=!0)},o=e-g;for(m=!0;o>0&&m;)m=!1,c.forEach(n);var p=0;b.visibleColumnCache.forEach(function(a){a.visible&&(p+=a.drawnWidth)}),h.forEach(function(a){f+=a.getColClassDefinition()}),b.canvasWidth=p,this.columnStyles=f},c.prototype.needsHScrollbarPlaceholder=function(){return this.grid.options.enableHorizontalScrollbar&&!this.hasHScrollbar&&!this.grid.disableScrolling},c.prototype.getViewportStyle=function(){var a=this,c={};return a.hasHScrollbar=!1,a.hasVScrollbar=!1,a.grid.disableScrolling?(c["overflow-x"]="hidden",c["overflow-y"]="hidden",c):("body"===a.name?(a.hasHScrollbar=a.grid.options.enableHorizontalScrollbar!==b.scrollbars.NEVER,a.grid.isRTL()?a.grid.hasLeftContainerColumns()||(a.hasVScrollbar=a.grid.options.enableVerticalScrollbar!==b.scrollbars.NEVER):a.grid.hasRightContainerColumns()||(a.hasVScrollbar=a.grid.options.enableVerticalScrollbar!==b.scrollbars.NEVER)):"left"===a.name?a.hasVScrollbar=a.grid.isRTL()?a.grid.options.enableVerticalScrollbar!==b.scrollbars.NEVER:!1:a.hasVScrollbar=a.grid.isRTL()?!1:a.grid.options.enableVerticalScrollbar!==b.scrollbars.NEVER,c["overflow-x"]=a.hasHScrollbar?"scroll":"hidden",c["overflow-y"]=a.hasVScrollbar?"scroll":"hidden",c)},c}])}(),function(){angular.module("ui.grid").factory("GridRow",["gridUtil","uiGridConstants",function(a,b){function c(b,c,d){this.grid=d,this.entity=b,this.uid=a.nextUid(),this.visible=!0,this.$$height=d.options.rowHeight}return Object.defineProperty(c.prototype,"height",{get:function(){return this.$$height},set:function(a){a!==this.$$height&&(this.grid.updateCanvasHeight(),this.$$height=a)}}),c.prototype.getQualifiedColField=function(a){return"row."+this.getEntityQualifiedColField(a)},c.prototype.getEntityQualifiedColField=function(c){var d="entity";return c.field===b.ENTITY_BINDING?d:a.preEval(d+"."+c.field)},c.prototype.setRowInvisible=function(a){a&&a.setThisRowInvisible&&a.setThisRowInvisible("user")},c.prototype.clearRowInvisible=function(a){a&&a.clearThisRowInvisible&&a.clearThisRowInvisible("user")},c.prototype.setThisRowInvisible=function(a,b){this.invisibleReason||(this.invisibleReason={}),this.invisibleReason[a]=!0,this.evaluateRowVisibility(b)},c.prototype.clearThisRowInvisible=function(a,b){"undefined"!=typeof this.invisibleReason&&delete this.invisibleReason[a],this.evaluateRowVisibility(b)},c.prototype.evaluateRowVisibility=function(a){var b=!0;"undefined"!=typeof this.invisibleReason&&angular.forEach(this.invisibleReason,function(a,c){a&&(b=!1)}),("undefined"==typeof this.visible||this.visible!==b)&&(this.visible=b,a||(this.grid.queueGridRefresh(),this.grid.api.core.raise.rowsVisibleChanged(this)))},c}])}(),function(){"use strict";angular.module("ui.grid").factory("GridRowColumn",["$parse","$filter",function(a,b){var c=function d(a,b){if(!(this instanceof d))throw"Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";this.row=a,this.col=b};return c.prototype.getIntersectionValueRaw=function(){var b=a(this.row.getEntityQualifiedColField(this.col)),c=this.row;return b(c)},c}])}(),function(){angular.module("ui.grid").factory("ScrollEvent",["gridUtil",function(a){function b(b,c,d,e){var f=this;if(!b)throw new Error("grid argument is required");f.grid=b,f.source=e,f.withDelay=!0,f.sourceRowContainer=c,f.sourceColContainer=d,f.newScrollLeft=null,f.newScrollTop=null,f.x=null,f.y=null,f.verticalScrollLength=-9999999,f.horizontalScrollLength=-999999,f.fireThrottledScrollingEvent=a.throttle(function(a){f.grid.scrollContainers(a,f)},f.grid.options.wheelScrollThrottle,{trailing:!0})}return b.prototype.getNewScrollLeft=function(b,c){var d=this;if(!d.newScrollLeft){var e,f=b.getCanvasWidth()-b.getViewportWidth(),g=a.normalizeScrollLeft(c,d.grid);if("undefined"!=typeof d.x.percentage&&void 0!==d.x.percentage)e=d.x.percentage;else{if("undefined"==typeof d.x.pixels||void 0===d.x.pixels)throw new Error("No percentage or pixel value provided for scroll event X axis");e=d.x.percentage=(g+d.x.pixels)/f}return Math.max(0,e*f)}return d.newScrollLeft},b.prototype.getNewScrollTop=function(a,b){var c=this;if(!c.newScrollTop){var d,e=a.getVerticalScrollLength(),f=b[0].scrollTop;if("undefined"!=typeof c.y.percentage&&void 0!==c.y.percentage)d=c.y.percentage;else{if("undefined"==typeof c.y.pixels||void 0===c.y.pixels)throw new Error("No percentage or pixel value provided for scroll event Y axis");d=c.y.percentage=(f+c.y.pixels)/e}return Math.max(0,d*e)}return c.newScrollTop},b.prototype.atTop=function(a){return this.y&&(0===this.y.percentage||this.verticalScrollLength<0)&&0===a},b.prototype.atBottom=function(a){return this.y&&(1===this.y.percentage||0===this.verticalScrollLength)&&a>0},b.prototype.atLeft=function(a){return this.x&&(0===this.x.percentage||this.horizontalScrollLength<0)&&0===a},b.prototype.atRight=function(a){return this.x&&(1===this.x.percentage||0===this.horizontalScrollLength)&&a>0},b.Sources={ViewPortScroll:"ViewPortScroll",RenderContainerMouseWheel:"RenderContainerMouseWheel",RenderContainerTouchMove:"RenderContainerTouchMove",Other:99},b}])}(),function(){"use strict";angular.module("ui.grid").service("gridClassFactory",["gridUtil","$q","$compile","$templateCache","uiGridConstants","Grid","GridColumn","GridRow",function(a,b,c,d,e,f,g,h){var i={createGrid:function(d){d="undefined"!=typeof d?d:{},d.id=a.newId();var e=new f(d);if(e.options.rowTemplate){var g=b.defer();e.getRowTemplateFn=g.promise,a.getTemplate(e.options.rowTemplate).then(function(a){var b=c(a);g.resolve(b)},function(a){throw new Error("Couldn't fetch/use row template '"+e.options.rowTemplate+"'")})}return e.registerColumnBuilder(i.defaultColumnBuilder),e.registerRowBuilder(i.rowTemplateAssigner),e.registerRowsProcessor(function(a){return a.forEach(function(a){a.evaluateRowVisibility(!0)},50),a}),e.registerColumnsProcessor(function(a){return a.forEach(function(a){a.visible=angular.isDefined(a.colDef.visible)?a.colDef.visible:!0}),a},50),e.registerRowsProcessor(e.searchRows,100),e.options.externalSort&&angular.isFunction(e.options.externalSort)?e.registerRowsProcessor(e.options.externalSort,200):e.registerRowsProcessor(e.sortByColumn,200),e},defaultColumnBuilder:function(c,d,f){var g=[],h=function(b,f,h,i,j){c[b]?d[f]=c[b]:d[f]=h,g.push(a.getTemplate(d[f]).then(function(a){angular.isFunction(a)&&(a=a());var c="cellTooltip"===j?"col.cellTooltip(row,col)":"col.headerTooltip(col)";j&&d[j]===!1?a=a.replace(e.TOOLTIP,""):j&&d[j]&&(a=a.replace(e.TOOLTIP,'title="{{'+c+' CUSTOM_FILTERS }}"')),i?d[b]=a.replace(e.CUSTOM_FILTERS,function(){return d[i]?"|"+d[i]:""}):d[b]=a},function(a){throw new Error("Couldn't fetch/use colDef."+b+" '"+c[b]+"'")}))};return h("cellTemplate","providedCellTemplate","ui-grid/uiGridCell","cellFilter","cellTooltip"),d.cellTemplatePromise=g[0],h("headerCellTemplate","providedHeaderCellTemplate","ui-grid/uiGridHeaderCell","headerCellFilter","headerTooltip"),h("footerCellTemplate","providedFooterCellTemplate","ui-grid/uiGridFooterCell","footerCellFilter"),h("filterHeaderTemplate","providedFilterHeaderTemplate","ui-grid/ui-grid-filter"),d.compiledElementFnDefer=b.defer(),b.all(g)},rowTemplateAssigner:function(d){var e=this;if(d.rowTemplate){var f=b.defer();d.getRowTemplateFn=f.promise,a.getTemplate(d.rowTemplate).then(function(a){var b=c(a);f.resolve(b)},function(a){throw new Error("Couldn't fetch/use row template '"+d.rowTemplate+"'")})}else d.rowTemplate=e.options.rowTemplate,d.getRowTemplateFn=e.getRowTemplateFn;return d.getRowTemplateFn}};return i}])}(),function(){function a(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}var b=angular.module("ui.grid");b.service("rowSearcher",["gridUtil","uiGridConstants",function(b,c){var d=c.filter.CONTAINS,e={};return e.getTerm=function(a){if("undefined"==typeof a.term)return a.term;var b=a.term;return"string"==typeof b&&(b=b.trim()),b},e.stripTerm=function(b){var c=e.getTerm(b);return"string"==typeof c?a(c.replace(/(^\*|\*$)/g,"")):c},e.guessCondition=function(a){if("undefined"==typeof a.term||!a.term)return d;var b=e.getTerm(a);if(/\*/.test(b)){var c="";a.flags&&a.flags.caseSensitive||(c+="i");var f=b.replace(/(\\)?\*/g,function(a,b){return b?a:"[\\s\\S]*?"});return new RegExp("^"+f+"$",c)}return d},e.setupFilters=function(a){for(var d=[],f=a.length,g=0;f>g;g++){var h=a[g];if(h.noTerm||!b.isNullOrUndefined(h.term)){var i={},j="";h.flags&&h.flags.caseSensitive||(j+="i"),b.isNullOrUndefined(h.term)||(h.rawTerm?i.term=h.term:i.term=e.stripTerm(h)),i.noTerm=h.noTerm,h.condition?i.condition=h.condition:i.condition=e.guessCondition(h),i.flags=angular.extend({caseSensitive:!1,date:!1},h.flags),i.condition===c.filter.STARTS_WITH&&(i.startswithRE=new RegExp("^"+i.term,j)),i.condition===c.filter.ENDS_WITH&&(i.endswithRE=new RegExp(i.term+"$",j)),i.condition===c.filter.CONTAINS&&(i.containsRE=new RegExp(i.term,j)),i.condition===c.filter.EXACT&&(i.exactRE=new RegExp("^"+i.term+"$",j)),d.push(i)}}return d},e.runColumnFilter=function(a,b,d,e){var f,g=typeof e.condition,h=e.term;if(f=d.filterCellFiltered?a.getCellDisplayValue(b,d):a.getCellValue(b,d),e.condition instanceof RegExp)return e.condition.test(f);if("function"===g)return e.condition(h,f,b,d);if(e.startswithRE)return e.startswithRE.test(f);if(e.endswithRE)return e.endswithRE.test(f);if(e.containsRE)return e.containsRE.test(f);if(e.exactRE)return e.exactRE.test(f);if(e.condition===c.filter.NOT_EQUAL){var i=new RegExp("^"+h+"$");return!i.exec(f)}if("number"==typeof f&&"string"==typeof h){var j=parseFloat(h.replace(/\\\./,".").replace(/\\\-/,"-"));isNaN(j)||(h=j)}return e.flags.date===!0&&(f=new Date(f),h=new Date(h.replace(/\\/g,""))),e.condition===c.filter.GREATER_THAN?f>h:e.condition===c.filter.GREATER_THAN_OR_EQUAL?f>=h:e.condition===c.filter.LESS_THAN?h>f:e.condition===c.filter.LESS_THAN_OR_EQUAL?h>=f:!0},e.searchColumn=function(a,c,d,f){if(a.options.useExternalFiltering)return!0;for(var g=f.length,h=0;g>h;h++){var i=f[h];if(!b.isNullOrUndefined(i.term)&&""!==i.term||i.noTerm){var j=e.runColumnFilter(a,c,d,i);if(!j)return!1}}return!0},e.search=function(a,c,d){if(c){if(!a.options.enableFiltering)return c;for(var f=[],g=d.length,h=function(a){var c=!1;return a.forEach(function(a){(!b.isNullOrUndefined(a.term)&&""!==a.term||a.noTerm)&&(c=!0)}),c},i=0;g>i;i++){var j=d[i];"undefined"!=typeof j.filters&&h(j.filters)&&f.push({col:j,filters:e.setupFilters(j.filters)})}if(f.length>0){for(var k=function(a,b,c,d){b.visible&&!e.searchColumn(a,b,c,d)&&(b.visible=!1)},l=function(a,b){for(var d=c.length,e=0;d>e;e++)k(a,c[e],b.col,b.filters)},m=f.length,n=0;m>n;n++)l(a,f[n]);a.api.core.raise.rowsVisibleChanged&&a.api.core.raise.rowsVisibleChanged()}return c}},e}])}(),function(){var a=angular.module("ui.grid");a.service("rowSorter",["$parse","uiGridConstants",function(a,b){var c="("+b.CURRENCY_SYMBOLS.map(function(a){return"\\"+a}).join("|")+")?",d=(new RegExp("^[-+]?"+c+"[\\d,.]+"+c+"%?$"),{colSortFnCache:{}});return d.guessSortFn=function(a){switch(a){case"number":return d.sortNumber;case"numberStr":return d.sortNumberStr;case"boolean":return d.sortBool;case"string":return d.sortAlpha;case"date":return d.sortDate;case"object":return d.basicSort;default:throw new Error("No sorting function found for type:"+a)}},d.handleNulls=function(a,b){if(!a&&0!==a&&a!==!1||!b&&0!==b&&b!==!1){if(!a&&0!==a&&a!==!1&&!b&&0!==b&&b!==!1)return 0;if(!a&&0!==a&&a!==!1)return 1;if(!b&&0!==b&&b!==!1)return-1}return null},d.basicSort=function(a,b){var c=d.handleNulls(a,b);return null!==c?c:a===b?0:b>a?-1:1},d.sortNumber=function(a,b){var c=d.handleNulls(a,b);return null!==c?c:a-b},d.sortNumberStr=function(a,b){var c=d.handleNulls(a,b);if(null!==c)return c;var e,f,g=!1,h=!1;return e=parseFloat(a.replace(/[^0-9.-]/g,"")),isNaN(e)&&(g=!0),f=parseFloat(b.replace(/[^0-9.-]/g,"")),isNaN(f)&&(h=!0),g&&h?0:g?1:h?-1:e-f},d.sortAlpha=function(a,b){var c=d.handleNulls(a,b);if(null!==c)return c;var e=a.toString().toLowerCase(),f=b.toString().toLowerCase();return e===f?0:e.localeCompare(f)},d.sortDate=function(a,b){var c=d.handleNulls(a,b);if(null!==c)return c;a instanceof Date||(a=new Date(a)),b instanceof Date||(b=new Date(b));var e=a.getTime(),f=b.getTime();return e===f?0:f>e?-1:1},d.sortBool=function(a,b){var c=d.handleNulls(a,b);return null!==c?c:a&&b?0:a||b?a?1:-1:0},d.getSortFn=function(a,b,c){var e;return d.colSortFnCache[b.colDef.name]?e=d.colSortFnCache[b.colDef.name]:void 0!==b.sortingAlgorithm?(e=b.sortingAlgorithm,d.colSortFnCache[b.colDef.name]=b.sortingAlgorithm):b.sortCellFiltered&&b.cellFilter?(e=d.sortAlpha,
+d.colSortFnCache[b.colDef.name]=e):(e=d.guessSortFn(b.colDef.type),e?d.colSortFnCache[b.colDef.name]=e:e=d.sortAlpha),e},d.prioritySort=function(a,b){return void 0!==a.sort.priority&&void 0!==b.sort.priority?a.sort.priority<b.sort.priority?-1:a.sort.priority===b.sort.priority?0:1:void 0!==a.sort.priority?-1:void 0!==b.sort.priority?1:0},d.sort=function(a,c,e){if(c){if(a.options.useExternalSorting)return c;var f=[];if(e.forEach(function(a){!a.sort||a.sort.ignoreSort||!a.sort.direction||a.sort.direction!==b.ASC&&a.sort.direction!==b.DESC||f.push(a)}),f=f.sort(d.prioritySort),0===f.length)return c;var g,h,i=function(a,b){a.entity.$$uiGridIndex=b};c.forEach(i);var j=c.slice(0),k=function(c,e){for(var i,k=0,l=0;0===k&&l<f.length;){g=f[l],h=f[l].sort.direction,i=d.getSortFn(a,g,j);var m,n;g.sortCellFiltered?(m=a.getCellDisplayValue(c,g),n=a.getCellDisplayValue(e,g)):(m=a.getCellValue(c,g),n=a.getCellValue(e,g)),k=i(m,n,c,e,h,g),l++}return 0===k?c.entity.$$uiGridIndex-e.entity.$$uiGridIndex:h===b.ASC?k:0-k},l=c.sort(k),m=function(a,b){delete a.entity.$$uiGridIndex};return c.forEach(m),l}},d}])}(),function(){function a(a){var b=a;return"undefined"!=typeof b.length&&b.length&&(b=a[0]),b.ownerDocument.defaultView.getComputedStyle(b,null)}function b(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0,h=["Top","Right","Bottom","Left"];4>f;f+=2){var i=h[f];if("margin"===c){var j=parseFloat(e[c+i]);isNaN(j)||(g+=j)}if(d){if("content"===c){var k=parseFloat(e["padding"+i]);isNaN(k)||(g-=k)}if("margin"!==c){var l=parseFloat(e["border"+i+"Width"]);isNaN(l)||(g-=l)}}else{var m=parseFloat(e["padding"+i]);if(isNaN(m)||(g+=m),"padding"!==c){var n=parseFloat(e["border"+i+"Width"]);isNaN(n)||(g+=n)}}}return g}function c(c,d,e){var f,h=!0,i=a(c),j="border-box"===i.boxSizing;if(0>=f||null==f){if(f=i[d],(0>f||null==f)&&(f=c.style[d]),g.test(f))return f;h=j&&!0,f=parseFloat(f)||0}var k=f+b(c,d,e||(j?"border":"content"),h,i);return k}function d(b){b=angular.element(b)[0];var c=b.parentElement;return c||(c=document.getElementsByTagName("body")[0]),parseInt(a(c).fontSize)||parseInt(a(b).fontSize)||16}var e,f=angular.module("ui.grid");"function"!=typeof Function.prototype.bind&&(e=function(){var a=Array.prototype.slice;return function(b){var c=this,d=a.call(arguments,1);return d.length?function(){return arguments.length?c.apply(b,d.concat(a.call(arguments))):c.apply(b,d)}:function(){return arguments.length?c.apply(b,arguments):c.call(b)}}});var g=new RegExp("^("+/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source+")(?!px)[a-z%]+$","i"),h=/^(block|none|table(?!-c[ea]).+)/,i={position:"absolute",visibility:"hidden",display:"block"},j=["0","0","0","0"],k="uiGrid-";f.service("gridUtil",["$log","$window","$document","$http","$templateCache","$timeout","$interval","$injector","$q","$interpolate","uiGridConstants",function(f,g,l,m,n,o,p,q,r,s,t){function u(a,b){var c=angular.element(this),d=0,e=0,f=0,g=0;if(b.originalEvent&&(b=b.originalEvent),"detail"in b&&(f=-1*b.detail),"wheelDelta"in b&&(f=b.wheelDelta),"wheelDeltaY"in b&&(f=b.wheelDeltaY),"wheelDeltaX"in b&&(e=-1*b.wheelDeltaX),"axis"in b&&b.axis===b.HORIZONTAL_AXIS&&(e=-1*f,f=0),d=0===f?e:f,"deltaY"in b&&(f=-1*b.deltaY,d=f),"deltaX"in b&&(e=b.deltaX,0===f&&(d=-1*e)),0!==f||0!==e){if(1===b.deltaMode){var h=c.data("mousewheel-line-height");d*=h,f*=h,e*=h}else if(2===b.deltaMode){var i=c.data("mousewheel-page-height");d*=i,f*=i,e*=i}g=Math.max(Math.abs(f),Math.abs(e)),(!z||z>g)&&(z=g,w(b,g)&&(z/=40)),d=Math[d>=1?"floor":"ceil"](d/z),e=Math[e>=1?"floor":"ceil"](e/z),f=Math[f>=1?"floor":"ceil"](f/z);var j={originalEvent:b,deltaX:e,deltaY:f,deltaFactor:z,preventDefault:function(){b.preventDefault()},stopPropagation:function(){b.stopPropagation()}};y&&clearTimeout(y),y=setTimeout(v,200),a.call(c[0],j)}}function v(){z=null}function w(a,b){return"mousewheel"===a.type&&b%120===0}var x={augmentWidthOrHeight:b,getStyles:a,createBoundedWrapper:function(a,b){return function(){return b.apply(a,arguments)}},readableColumnName:function(a){return"undefined"==typeof a||void 0===a||null===a?a:("string"!=typeof a&&(a=String(a)),a.replace(/_+/g," ").replace(/^[A-Z]+$/,function(a){return angular.lowercase(angular.uppercase(a.charAt(0))+a.slice(1))}).replace(/([\w\u00C0-\u017F]+)/g,function(a){return angular.uppercase(a.charAt(0))+a.slice(1)}).replace(/(\w+?(?=[A-Z]))/g,"$1 "))},getColumnsFromData:function(a,b){var c=[];if(!a||"undefined"==typeof a[0]||void 0===a[0])return[];angular.isUndefined(b)&&(b=[]);var d=a[0];return angular.forEach(d,function(a,d){-1===b.indexOf(d)&&c.push({name:d})}),c},newId:function(){var a=(new Date).getTime();return function(){return a+=1}}(),getTemplate:function(a){if(n.get(a))return x.postProcessTemplate(n.get(a));if(angular.isFunction(a.then))return a.then(x.postProcessTemplate);try{if(angular.element(a).length>0)return r.when(a).then(x.postProcessTemplate)}catch(b){}return x.logDebug("fetching url",a),m({method:"GET",url:a}).then(function(b){var c=b.data.trim();return n.put(a,c),c},function(b){throw new Error("Could not get template "+a+": "+b)}).then(x.postProcessTemplate)},postProcessTemplate:function(a){var b=s.startSymbol(),c=s.endSymbol();return("{{"!==b||"}}"!==c)&&(a=a.replace(/\{\{/g,b),a=a.replace(/\}\}/g,c)),r.when(a)},guessType:function(a){var b=typeof a;switch(b){case"number":case"boolean":case"string":return b;default:return angular.isDate(a)?"date":"object"}},elementWidth:function(a){},elementHeight:function(a){},getScrollbarWidth:function(){var a=document.createElement("div");a.style.visibility="hidden",a.style.width="100px",a.style.msOverflowStyle="scrollbar",document.body.appendChild(a);var b=a.offsetWidth;a.style.overflow="scroll";var c=document.createElement("div");c.style.width="100%",a.appendChild(c);var d=c.offsetWidth;return a.parentNode.removeChild(a),b-d},swap:function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},fakeElement:function(a,b,c,d){var e,f,g=angular.element(a).clone()[0];for(f in b)g.style[f]=b[f];return angular.element(document.body).append(g),e=c.call(g,g),angular.element(g).remove(),e},normalizeWheelEvent:function(a){var b,c,d,e=a||window.event,f=([].slice.call(arguments,1),0),g=0,h=0,i=0,j=0;return e.originalEvent&&(e=e.originalEvent),e.wheelDelta&&(f=e.wheelDelta),e.detail&&(f=-1*e.detail),h=f,void 0!==e.axis&&e.axis===e.HORIZONTAL_AXIS&&(h=0,g=-1*f),e.deltaY&&(h=-1*e.deltaY,f=h),e.deltaX&&(g=e.deltaX,f=-1*g),void 0!==e.wheelDeltaY&&(h=e.wheelDeltaY),void 0!==e.wheelDeltaX&&(g=e.wheelDeltaX),i=Math.abs(f),(!b||b>i)&&(b=i),j=Math.max(Math.abs(h),Math.abs(g)),(!c||c>j)&&(c=j),d=f>0?"floor":"ceil",f=Math[d](f/b),g=Math[d](g/c),h=Math[d](h/c),{delta:f,deltaX:g,deltaY:h}},isTouchEnabled:function(){var a;return("ontouchstart"in g||g.DocumentTouch&&l instanceof DocumentTouch)&&(a=!0),a},isNullOrUndefined:function(a){return void 0===a||null===a?!0:!1},endsWith:function(a,b){return a&&b&&"string"==typeof a?-1!==a.indexOf(b,a.length-b.length):!1},arrayContainsObjectWithProperty:function(a,b,c){var d=!1;return angular.forEach(a,function(a){a[b]===c&&(d=!0)}),d},numericAndNullSort:function(a,b){return null===a?1:null===b?-1:null===a&&null===b?0:a-b},disableAnimations:function(a){var b;try{b=q.get("$animate"),angular.version.major>1||1===angular.version.major&&angular.version.minor>=4?b.enabled(a,!1):b.enabled(!1,a)}catch(c){}},enableAnimations:function(a){var b;try{return b=q.get("$animate"),angular.version.major>1||1===angular.version.major&&angular.version.minor>=4?b.enabled(a,!0):b.enabled(!0,a),b}catch(c){}},nextUid:function(){for(var a,b=j.length;b;){if(b--,a=j[b].charCodeAt(0),57===a)return j[b]="A",k+j.join("");if(90!==a)return j[b]=String.fromCharCode(a+1),k+j.join("");j[b]="0"}return j.unshift("0"),k+j.join("")},hashKey:function(a){var b,c=typeof a;return"object"===c&&null!==a?"function"==typeof(b=a.$$hashKey)?b=a.$$hashKey():"undefined"!=typeof a.$$hashKey&&a.$$hashKey?b=a.$$hashKey:void 0===b&&(b=a.$$hashKey=x.nextUid()):b=a,c+":"+b},resetUids:function(){j=["0","0","0"]},logError:function(a){t.LOG_ERROR_MESSAGES&&f.error(a)},logWarn:function(a){t.LOG_WARN_MESSAGES&&f.warn(a)},logDebug:function(){t.LOG_DEBUG_MESSAGES&&f.debug.apply(f,arguments)}};x.focus={queue:[],byId:function(a,b){this._purgeQueue();var c=o(function(){var c=(b&&b.id?b.id+"-":"")+a,d=g.document.getElementById(c);d?d.focus():x.logWarn("[focus.byId] Element id "+c+" was not found.")});return this.queue.push(c),c},byElement:function(a){if(!angular.isElement(a))return x.logWarn("Trying to focus on an element that isn't an element."),r.reject("not-element");a=angular.element(a),this._purgeQueue();var b=o(function(){a&&a[0].focus()});return this.queue.push(b),b},bySelector:function(a,b,c){var d=this;if(!angular.isElement(a))throw new Error("The parent element is not an element.");a=angular.element(a);var e=function(){var c=a[0].querySelector(b);return d.byElement(c)};if(this._purgeQueue(),c){var f=o(e);return this.queue.push(o(e)),f}return e()},_purgeQueue:function(){this.queue.forEach(function(a){o.cancel(a)}),this.queue=[]}},["width","height"].forEach(function(b){var d=angular.uppercase(b.charAt(0))+b.substr(1);x["element"+d]=function(d,e){var f=d;if(f&&"undefined"!=typeof f.length&&f.length&&(f=d[0]),f&&null!==f){var g=a(f);return 0===f.offsetWidth&&h.test(g.display)?x.swap(f,i,function(){return c(f,b,e)}):c(f,b,e)}return null},x["outerElement"+d]=function(a,b){return a?x["element"+d].call(this,a,b?"margin":"border"):null}}),x.closestElm=function(a,b){"undefined"!=typeof a.length&&a.length&&(a=a[0]);var c;["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"].some(function(a){return"function"==typeof document.body[a]?(c=a,!0):!1});for(var d;null!==a;){if(d=a.parentElement,null!==d&&d[c](b))return d;a=d}return null},x.type=function(a){var b=Function.prototype.toString.call(a.constructor);return b.match(/function (.*?)\(/)[1]},x.getBorderSize=function(b,c){"undefined"!=typeof b.length&&b.length&&(b=b[0]);var d=a(b);c=c?"border"+c.charAt(0).toUpperCase()+c.slice(1):"border",c+="Width";var e=parseInt(d[c],10);return isNaN(e)?0:e},x.detectBrowser=function(){var a=g.navigator.userAgent,b={chrome:/chrome/i,safari:/safari/i,firefox:/firefox/i,ie:/internet explorer|trident\//i};for(var c in b)if(b[c].test(a))return c;return"unknown"},x.rtlScrollType=function B(){if(B.type)return B.type;var a=angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],b="reverse";return document.body.appendChild(a),a.scrollLeft>0?b="default":(a.scrollLeft=1,0===a.scrollLeft&&(b="negative")),angular.element(a).remove(),B.type=b,b},x.normalizeScrollLeft=function(a,b){"undefined"!=typeof a.length&&a.length&&(a=a[0]);var c=a.scrollLeft;if(b.isRTL())switch(x.rtlScrollType()){case"default":return a.scrollWidth-c-a.clientWidth;case"negative":return Math.abs(c);case"reverse":return c}return c},x.denormalizeScrollLeft=function(a,b,c){if("undefined"!=typeof a.length&&a.length&&(a=a[0]),c.isRTL())switch(x.rtlScrollType()){case"default":var d=a.scrollWidth-a.clientWidth;return d-b;case"negative":return-1*b;case"reverse":return b}return b},x.preEval=function(a){var b=t.BRACKET_REGEXP.exec(a);if(b)return(b[1]?x.preEval(b[1]):b[1])+b[2]+(b[3]?x.preEval(b[3]):b[3]);a=a.replace(t.APOS_REGEXP,"\\'");var c=a.split(t.DOT_REGEXP),d=[c.shift()];return angular.forEach(c,function(a){d.push(a.replace(t.FUNC_REGEXP,"']$1"))}),d.join("['")},x.debounce=function(a,b,c){function d(){g=this,f=arguments;var d=function(){e=null,c||(h=a.apply(g,f))},i=c&&!e;return e&&o.cancel(e),e=o(d,b,!1),i&&(h=a.apply(g,f)),h}var e,f,g,h;return d.cancel=function(){o.cancel(e),e=null},d},x.throttle=function(a,b,c){function d(b){g=+new Date,a.apply(e,f),p(function(){h=null},0,1,!1)}c=c||{};var e,f,g=0,h=null;return function(){if(e=this,f=arguments,null===h){var a=+new Date-g;a>b?d():c.trailing&&(h=p(d,b-a,1,!1))}}},x.on={},x.off={},x._events={},x.addOff=function(a){x.off[a]=function(b,c){var d=x._events[a].indexOf(c);d>0&&x._events[a].removeAt(d)}};var y,z,A="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"];return x.on.mousewheel=function(a,b){if(a&&b){var c=angular.element(a);c.data("mousewheel-line-height",d(c)),c.data("mousewheel-page-height",x.elementHeight(c)),c.data("mousewheel-callbacks")||c.data("mousewheel-callbacks",{});var f=c.data("mousewheel-callbacks");f[b]=(Function.prototype.bind||e).call(u,c[0],b);for(var g=A.length;g;)c.on(A[--g],f[b]);c.on("$destroy",function(){for(var a=A.length;a;)c.off(A[--a],f[b])})}},x.off.mousewheel=function(a,b){var c=angular.element(a),d=c.data("mousewheel-callbacks"),e=d[b];if(e)for(var f=A.length;f;)c.off(A[--f],e);delete d[b],0===Object.keys(d).length&&(c.removeData("mousewheel-line-height"),c.removeData("mousewheel-page-height"),c.removeData("mousewheel-callbacks"))},x}]),f.filter("px",function(){return function(a){return a.match(/^[\d\.]+$/)?a+"px":a}})}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){var b={aggregate:{label:"položky"},groupPanel:{description:"PÅ™esuňte záhlaví zde pro vytvoÅ™ení skupiny dle sloupce."},search:{placeholder:"Hledat...",showingItems:"Zobrazuji položky:",selectedItems:"Vybrané položky:",totalItems:"Celkem položek:",size:"Velikost strany:",first:"První strana",next:"Další strana",previous:"PÅ™edchozí strana",last:"Poslední strana"},menu:{text:"Vyberte sloupec:"},sort:{ascending:"SeÅ™adit od A-Z",descending:"SeÅ™adit od Z-A",remove:"Odebrat seÅ™azení"},column:{hide:"Schovat sloupec"},aggregation:{count:"celkem řádků: ",sum:"celkem: ",avg:"avg: ",min:"min.: ",max:"max.: "},pinning:{pinLeft:"Zamknout vlevo",pinRight:"Zamknout vpravo",unpin:"Odemknout"},gridMenu:{columns:"Sloupce:",importerTitle:"Importovat soubor",exporterAllAsCsv:"Exportovat vÅ¡echna data do csv",exporterVisibleAsCsv:"Exportovat viditelná data do csv",exporterSelectedAsCsv:"Exportovat vybraná data do csv",exporterAllAsPdf:"Exportovat vÅ¡echna data do pdf",exporterVisibleAsPdf:"Exportovat viditelná data do pdf",exporterSelectedAsPdf:"Exportovat vybraná data do pdf",clearAllFilters:"Odstranit vÅ¡echny filtry"},importer:{noHeaders:"Názvy sloupců se nepodaÅ™ilo získat, obsahuje soubor záhlaví?",noObjects:"Data se nepodaÅ™ilo zpracovat, obsahuje soubor řádky mimo záhlaví?",invalidCsv:"Soubor nelze zpracovat, jedná se o CSV?",invalidJson:"Soubor nelze zpracovat, je to JSON?",jsonNotArray:"Soubor musí obsahovat json. UkonÄuji.."},pagination:{sizes:"položek na stránku",totalItems:"položek"},grouping:{group:"Seskupit",ungroup:"Odebrat seskupení",aggregate_count:"Agregace: Count",aggregate_sum:"Agregace: Sum",aggregate_max:"Agregace: Max",aggregate_min:"Agregace: Min",aggregate_avg:"Agregace: Avg",aggregate_remove:"Agregace: Odebrat"}};return a.add("cs",b),a.add("cz",b),a.add("cs-cz",b),a.add("cs-CZ",b),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("da",{aggregate:{label:"artikler"},groupPanel:{description:"Grupér rækker udfra en kolonne ved at trække dens overskift hertil."},search:{placeholder:"Søg...",showingItems:"Viste rækker:",selectedItems:"Valgte rækker:",totalItems:"Rækker totalt:",size:"Side størrelse:",first:"Første side",next:"Næste side",previous:"Forrige side",last:"Sidste side"},menu:{text:"Vælg kolonner:"},sort:{ascending:"Sorter stigende",descending:"Sorter faldende",none:"Sorter ingen",remove:"Fjern sortering"},column:{hide:"Skjul kolonne"},aggregation:{count:"antal rækker: ",sum:"sum: ",avg:"gns: ",min:"min: ",max:"max: "},gridMenu:{columns:"Kolonner:",importerTitle:"Importer fil",exporterAllAsCsv:"Eksporter alle data som csv",exporterVisibleAsCsv:"Eksporter synlige data som csv",exporterSelectedAsCsv:"Eksporter markerede data som csv",exporterAllAsPdf:"Eksporter alle data som pdf",exporterVisibleAsPdf:"Eksporter synlige data som pdf",exporterSelectedAsPdf:"Eksporter markerede data som pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"GÃ¥ til første",pageBack:"GÃ¥ tilbage",pageSelected:"Valgte side",pageForward:"GÃ¥ frem",pageToLast:"GÃ¥ til sidste"},sizes:"genstande per side",totalItems:"genstande",through:"gennem",of:"af"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("de",{headerCell:{aria:{defaultFilterLabel:"Filter für Spalte",removeFilter:"Filter löschen",columnMenuButtonLabel:"Spaltenmenü"},priority:"Priorität:",filterLabel:"Filter für Spalte: "},aggregate:{label:"Eintrag"},groupPanel:{description:"Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren."},search:{placeholder:"Suche...",showingItems:"Zeige Einträge:",selectedItems:"Ausgewählte Einträge:",totalItems:"Einträge gesamt:",size:"Einträge pro Seite:",first:"Erste Seite",next:"Nächste Seite",previous:"Vorherige Seite",last:"Letzte Seite"},menu:{text:"Spalten auswählen:"},sort:{ascending:"aufsteigend sortieren",descending:"absteigend sortieren",none:"keine Sortierung",remove:"Sortierung zurücksetzen"},column:{hide:"Spalte ausblenden"},aggregation:{count:"Zeilen insgesamt: ",sum:"gesamt: ",avg:"Durchschnitt: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Links anheften",pinRight:"Rechts anheften",unpin:"Lösen"},columnMenu:{close:"Schließen"},gridMenu:{aria:{buttonLabel:"Tabellenmenü"},columns:"Spalten:",importerTitle:"Datei importieren",exporterAllAsCsv:"Alle Daten als CSV exportieren",exporterVisibleAsCsv:"sichtbare Daten als CSV exportieren",exporterSelectedAsCsv:"markierte Daten als CSV exportieren",exporterAllAsPdf:"Alle Daten als PDF exportieren",exporterVisibleAsPdf:"sichtbare Daten als PDF exportieren",exporterSelectedAsPdf:"markierte Daten als PDF exportieren",clearAllFilters:"Alle Filter zurücksetzen"},importer:{noHeaders:"Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?",noObjects:"Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?",invalidCsv:"Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?",invalidJson:"Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?",jsonNotArray:"Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab."},pagination:{aria:{pageToFirst:"Zum Anfang",pageBack:"Seite zurück",pageSelected:"Ausgwählte Seite",pageForward:"Seite vor",pageToLast:"Zum Ende"},sizes:"Einträge pro Seite",totalItems:"Einträge",through:"bis",of:"von"},grouping:{group:"Gruppieren",ungroup:"Gruppierung aufheben",aggregate_count:"Agg: Anzahl",aggregate_sum:"Agg: Summe",aggregate_max:"Agg: Maximum",aggregate_min:"Agg: Minimum",aggregate_avg:"Agg: Mittelwert",aggregate_remove:"Aggregation entfernen"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("en",{headerCell:{aria:{defaultFilterLabel:"Filter for column",removeFilter:"Remove Filter",columnMenuButtonLabel:"Column Menu"},priority:"Priority:",filterLabel:"Filter for column: "},aggregate:{label:"items"},groupPanel:{description:"Drag a column header here and drop it to group by that column."},search:{placeholder:"Search...",showingItems:"Showing Items:",selectedItems:"Selected Items:",totalItems:"Total Items:",size:"Page Size:",first:"First Page",next:"Next Page",previous:"Previous Page",last:"Last Page"},menu:{text:"Choose Columns:"},sort:{ascending:"Sort Ascending",descending:"Sort Descending",none:"Sort None",remove:"Remove Sort"},column:{hide:"Hide Column"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pin Left",pinRight:"Pin Right",unpin:"Unpin"},columnMenu:{close:"Close"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Columns:",importerTitle:"Import file",exporterAllAsCsv:"Export all data as csv",exporterVisibleAsCsv:"Export visible data as csv",exporterSelectedAsCsv:"Export selected data as csv",exporterAllAsPdf:"Export all data as pdf",exporterVisibleAsPdf:"Export visible data as pdf",exporterSelectedAsPdf:"Export selected data as pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"Page to first",pageBack:"Page back",pageSelected:"Selected page",pageForward:"Page forward",pageToLast:"Page to last"},sizes:"items per page",totalItems:"items",through:"through",of:"of"},grouping:{group:"Group",ungroup:"Ungroup",aggregate_count:"Agg: Count",aggregate_sum:"Agg: Sum",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Remove"},validate:{error:"Error:",minLength:"Value should be at least THRESHOLD characters long.",maxLength:"Value should be at most THRESHOLD characters long.",required:"A value is needed."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("es",{aggregate:{label:"Artículos"},groupPanel:{description:"Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna."},search:{placeholder:"Buscar...",showingItems:"Artículos Mostrados:",selectedItems:"Artículos Seleccionados:",totalItems:"Artículos Totales:",size:"Tamaño de Página:",first:"Primera Página",next:"Página Siguiente",previous:"Página Anterior",last:"Última Página"},menu:{text:"Elegir columnas:"},sort:{ascending:"Orden Ascendente",descending:"Orden Descendente",remove:"Sin Ordenar"},column:{hide:"Ocultar la columna"},aggregation:{count:"filas totales: ",sum:"total: ",avg:"media: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fijar a la Izquierda",pinRight:"Fijar a la Derecha",unpin:"Quitar Fijación"},gridMenu:{columns:"Columnas:",importerTitle:"Importar archivo",exporterAllAsCsv:"Exportar todo como csv",exporterVisibleAsCsv:"Exportar vista como csv",exporterSelectedAsCsv:"Exportar selección como csv",exporterAllAsPdf:"Exportar todo como pdf",exporterVisibleAsPdf:"Exportar vista como pdf",exporterSelectedAsPdf:"Exportar selección como pdf",clearAllFilters:"Limpiar todos los filtros"},importer:{noHeaders:"No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?",noObjects:"No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?",invalidCsv:"No fue posible procesar el archivo, ¿es un CSV válido?",invalidJson:"No fue posible procesar el archivo, ¿es un Json válido?",jsonNotArray:"El archivo json importado debe contener un array, abortando."},pagination:{sizes:"registros por página",totalItems:"registros",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Cont",aggregate_sum:"Agr: Sum",aggregate_max:"Agr: Máx",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Prom",aggregate_remove:"Agr: Quitar"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("fa",{aggregate:{label:"قلم"},groupPanel:{description:"عنوان یک ستون را بگیر Ùˆ به گروهی از آن ستون رها Ú©Ù†."},search:{placeholder:"جستجو...",showingItems:"نمایش اقلام:",selectedItems:"قلم‌های انتخاب شده:",totalItems:"مجموع اقلام:",size:"اندازه‌ی صÙحه:",first:"اولین صÙحه",next:"صÙحه‌ی‌بعدی",previous:"صÙحه‌ی‌ قبلی",last:"آخرین صÙحه"},menu:{text:"ستون‌های انتخابی:"},sort:{ascending:"ترتیب صعودی",descending:"ترتیب نزولی",remove:"حذ٠مرتب کردن"},column:{hide:"پنهان‌کردن ستون"},aggregation:{count:"تعداد: ",sum:"مجموع: ",avg:"میانگین: ",min:"کمترین: ",max:"بیشترین: "},pinning:{pinLeft:"پین کردن سمت Ú†Ù¾",pinRight:"پین کردن سمت راست",unpin:"حذ٠پین"},gridMenu:{columns:"ستون‌ها:",importerTitle:"وارد کردن Ùایل",exporterAllAsCsv:"خروجی تمام داده‌ها در Ùایل csv",exporterVisibleAsCsv:"خروجی داده‌های قابل مشاهده در Ùایل csv",exporterSelectedAsCsv:"خروجی داده‌های انتخاب‌شده در Ùایل csv",exporterAllAsPdf:"خروجی تمام داده‌ها در Ùایل pdf",exporterVisibleAsPdf:"خروجی داده‌های قابل مشاهده در Ùایل pdf",exporterSelectedAsPdf:"خروجی داده‌های انتخاب‌شده در Ùایل pdf",clearAllFilters:"پاک کردن تمام Ùیلتر"},importer:{noHeaders:"نام ستون قابل استخراج نیست. آیا Ùایل عنوان دارد؟",noObjects:"اشیا قابل استخراج نیستند. آیا به جز عنوان‌ها در Ùایل داده وجود دارد؟",invalidCsv:"Ùایل قابل پردازش نیست. آیا Ùرمت csv معتبر است؟",invalidJson:"Ùایل قابل پردازش نیست. آیا Ùرمت json معتبر است؟",jsonNotArray:"Ùایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد."},pagination:{sizes:"اقلام در هر صÙحه",totalItems:"اقلام",of:"از"},grouping:{group:"گروه‌بندی",ungroup:"حذ٠گروه‌بندی",aggregate_count:"Agg: تعداد",aggregate_sum:"Agg: جمع",aggregate_max:"Agg: بیشینه",aggregate_min:"Agg: کمینه",aggregate_avg:"Agg: میانگین",aggregate_remove:"Agg: حذÙ"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("fi",{aggregate:{label:"rivit"},groupPanel:{description:"Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan."},search:{placeholder:"Hae...",showingItems:"Näytetään rivejä:",selectedItems:"Valitut rivit:",totalItems:"Rivejä yht.:",size:"Näytä:",first:"Ensimmäinen sivu",next:"Seuraava sivu",previous:"Edellinen sivu",last:"Viimeinen sivu"},menu:{text:"Valitse sarakkeet:"},sort:{ascending:"Järjestä nouseva",descending:"Järjestä laskeva",remove:"Poista järjestys"},column:{hide:"Piilota sarake"},aggregation:{count:"Rivejä yht.: ",sum:"Summa: ",avg:"K.a.: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Lukitse vasemmalle",pinRight:"Lukitse oikealle",unpin:"Poista lukitus"},gridMenu:{columns:"Sarakkeet:",importerTitle:"Tuo tiedosto",exporterAllAsCsv:"Vie tiedot csv-muodossa",exporterVisibleAsCsv:"Vie näkyvä tieto csv-muodossa",exporterSelectedAsCsv:"Vie valittu tieto csv-muodossa",exporterAllAsPdf:"Vie tiedot pdf-muodossa",exporterVisibleAsPdf:"Vie näkyvä tieto pdf-muodossa",exporterSelectedAsPdf:"Vie valittu tieto pdf-muodossa",clearAllFilters:"Puhdista kaikki suodattimet"},importer:{noHeaders:"Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?",noObjects:"Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?",invalidCsv:"Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?",invalidJson:"Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?",jsonNotArray:"Tiedosto ei sisältänyt taulukkoa, lopetetaan."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("fr",{headerCell:{aria:{defaultFilterLabel:"Filtre de la colonne",removeFilter:"Supprimer le filtre",columnMenuButtonLabel:"Menu de la colonne"},priority:"Priorité:",filterLabel:"Filtre de la colonne: "},aggregate:{label:"éléments"},groupPanel:{description:"Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes."},search:{placeholder:"Recherche...",showingItems:"Affichage des éléments :",selectedItems:"Éléments sélectionnés :",totalItems:"Nombre total d'éléments:",size:"Taille de page:",first:"Première page",next:"Page Suivante",previous:"Page précédente",last:"Dernière page"},menu:{text:"Choisir des colonnes :"},sort:{ascending:"Trier par ordre croissant",descending:"Trier par ordre décroissant",none:"Aucun tri",remove:"Enlever le tri"},column:{hide:"Cacher la colonne"},aggregation:{count:"lignes totales: ",sum:"total: ",avg:"moy: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Épingler à gauche",pinRight:"Épingler à droite",unpin:"Détacher"},columnMenu:{close:"Fermer"},gridMenu:{aria:{buttonLabel:"Menu du tableau"},columns:"Colonnes:",importerTitle:"Importer un fichier",exporterAllAsCsv:"Exporter toutes les données en CSV",exporterVisibleAsCsv:"Exporter les données visibles en CSV",exporterSelectedAsCsv:"Exporter les données sélectionnées en CSV",exporterAllAsPdf:"Exporter toutes les données en PDF",exporterVisibleAsPdf:"Exporter les données visibles en PDF",exporterSelectedAsPdf:"Exporter les données sélectionnées en PDF",clearAllFilters:"Nettoyez tous les filtres"},importer:{noHeaders:"Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?",noObjects:"Aucun objet trouvé, le fichier possède-t-il des données autres que l'en-tête ?",invalidCsv:"Le fichier n'a pas pu être traité, le CSV est-il valide ?",invalidJson:"Le fichier n'a pas pu être traité, le JSON est-il valide ?",jsonNotArray:"Le fichier JSON importé doit contenir un tableau, abandon."},pagination:{aria:{pageToFirst:"Aller à la première page",pageBack:"Page précédente",pageSelected:"Page sélectionnée",pageForward:"Page suivante",pageToLast:"Aller à la dernière page"},sizes:"éléments par page",totalItems:"éléments",through:"à",of:"sur"},grouping:{group:"Grouper",ungroup:"Dégrouper",aggregate_count:"Agg: Compter",aggregate_sum:"Agg: Somme",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Moy",aggregate_remove:"Agg: Retirer"},validate:{error:"Erreur:",minLength:"La valeur doit être supérieure ou égale à THRESHOLD caractères.",maxLength:"La valeur doit être inférieure ou égale à THRESHOLD caractères.",required:"Une valeur est nécéssaire."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("he",{aggregate:{label:"items"},groupPanel:{description:"גרור עמודה לכ×ן ושחרר בכדי לקבץ עמודה זו."},search:{placeholder:"חפש...",showingItems:"מציג:",selectedItems:'סה"×› נבחרו:',totalItems:'סה"×› רשומות:',size:"תוצ×ות בדף:",first:"דף ר×שון",next:"דף הב×",previous:"דף קוד×",last:"דף ×חרון"},menu:{text:"בחר עמודות:"},sort:{ascending:"סדר עולה",descending:"סדר יורד",remove:"בטל"},column:{hide:"טור הסתר"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},gridMenu:{columns:"Columns:",importerTitle:"Import file",exporterAllAsCsv:"Export all data as csv",exporterVisibleAsCsv:"Export visible data as csv",exporterSelectedAsCsv:"Export selected data as csv",exporterAllAsPdf:"Export all data as pdf",exporterVisibleAsPdf:"Export visible data as pdf",exporterSelectedAsPdf:"Export selected data as pdf",clearAllFilters:"Clean all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("hy",{aggregate:{label:"Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€"},groupPanel:{description:"Ô¸Õ½Õ¿ Õ½ÕµÕ¡Õ¶ Õ­Õ´Õ¢Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö„Õ¡Õ·Õ¥Ö„ Ö‡ Õ£ÖÕ¥Ö„ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰"},search:{placeholder:"Õ“Õ¶Õ¿Ö€Õ¸Ö‚Õ´...",showingItems:"Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ",selectedItems:"Ô¸Õ¶Õ¿Ö€Õ¾Õ¡Õ®:",totalItems:"Ô¸Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ",size:"ÕÕ¸Õ²Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨ Õ§Õ»Õ¸Ö‚Õ´Õ",first:"Ô±Õ¼Õ¡Õ»Õ«Õ¶ Õ§Õ»",next:"Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ§Õ»",previous:"Õ†Õ¡Õ­Õ¸Ö€Õ¤ Õ§Õ»",last:"ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ§Õ»"},menu:{text:"Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¥Ö€Õ¨:"},sort:{ascending:"Ô±Õ³Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾",descending:"Õ†Õ¾Õ¡Õ¦Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾",remove:"Õ€Õ¡Õ¶Õ¥Õ¬ "},column:{hide:"Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¨"},aggregation:{count:"Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨ Õ¿Õ¸Õ²Õ ",
+sum:"Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ ",avg:"Õ´Õ«Õ»Õ«Õ¶Õ ",min:"Õ´Õ«Õ¶Õ ",max:"Õ´Õ¡Ö„Õ½Õ "},pinning:{pinLeft:"Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ±Õ¡Õ­ Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´",pinRight:"Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´",unpin:"Ô±Ö€Õ±Õ¡Õ¯Õ¥Õ¬"},gridMenu:{columns:"ÕÕµÕ¸Ö‚Õ¶Õ¥Ö€:",importerTitle:"Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ Ö†Õ¡ÕµÕ¬",exporterAllAsCsv:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨ CSV",exporterVisibleAsCsv:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV",exporterSelectedAsCsv:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV",exporterAllAsPdf:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ PDF",exporterVisibleAsPdf:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF",exporterSelectedAsPdf:"Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF",clearAllFilters:"Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€Õ¨"},importer:{noHeaders:"Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ½ÕµÕ¡Õ¶ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¨ Õ¸Ö‚Õ¶Õ« Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Ö‰",noObjects:"Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰",invalidCsv:"Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ CSV Õ§Ö‰",invalidJson:"Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ Json Õ§Ö‰",jsonNotArray:"Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¾Õ¡Õ® json Ö†Õ¡ÕµÕ¬Õ¨ ÕºÕ¥Õ¿Ö„ Õ§ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ« Õ¦Õ¡Õ¶Õ£Õ¾Õ¡Õ®, Õ¯Õ¡Õ½Õ¥ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("it",{aggregate:{label:"elementi"},groupPanel:{description:"Trascina un'intestazione all'interno del gruppo della colonna."},search:{placeholder:"Ricerca...",showingItems:"Mostra:",selectedItems:"Selezionati:",totalItems:"Totali:",size:"Tot Pagine:",first:"Prima",next:"Prossima",previous:"Precedente",last:"Ultima"},menu:{text:"Scegli le colonne:"},sort:{ascending:"Asc.",descending:"Desc.",remove:"Annulla ordinamento"},column:{hide:"Nascondi"},aggregation:{count:"righe totali: ",sum:"tot: ",avg:"media: ",min:"minimo: ",max:"massimo: "},pinning:{pinLeft:"Blocca a sx",pinRight:"Blocca a dx",unpin:"Blocca in alto"},gridMenu:{columns:"Colonne:",importerTitle:"Importa",exporterAllAsCsv:"Esporta tutti i dati in CSV",exporterVisibleAsCsv:"Esporta i dati visibili in CSV",exporterSelectedAsCsv:"Esporta i dati selezionati in CSV",exporterAllAsPdf:"Esporta tutti i dati in PDF",exporterVisibleAsPdf:"Esporta i dati visibili in PDF",exporterSelectedAsPdf:"Esporta i dati selezionati in PDF",clearAllFilters:"Pulire tutti i filtri"},importer:{noHeaders:"Impossibile reperire i nomi delle colonne, sicuro che siano indicati all'interno del file?",noObjects:"Impossibile reperire gli oggetti, sicuro che siano indicati all'interno del file?",invalidCsv:"Impossibile elaborare il file, sicuro che sia un CSV?",invalidJson:"Impossibile elaborare il file, sicuro che sia un JSON valido?",jsonNotArray:"Errore! Il file JSON da importare deve contenere un array."},pagination:{aria:{pageToFirst:"Prima",pageBack:"Indietro",pageSelected:"Pagina selezionata",pageForward:"Avanti",pageToLast:"Ultima"},sizes:"elementi per pagina",totalItems:"elementi",through:"a",of:"di"},grouping:{group:"Raggruppa",ungroup:"Separa",aggregate_count:"Agg: N. Elem.",aggregate_sum:"Agg: Somma",aggregate_max:"Agg: Massimo",aggregate_min:"Agg: Minimo",aggregate_avg:"Agg: Media",aggregate_remove:"Agg: Rimuovi"},validate:{error:"Errore:",minLength:"Lunghezza minima pari a THRESHOLD caratteri.",maxLength:"Lunghezza massima pari a THRESHOLD caratteri.",required:"Necessario inserire un valore."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ja",{aggregate:{label:"é …ç›®"},groupPanel:{description:"ã“ã“ã«åˆ—ヘッダをドラッグアンドドロップã—ã¦ã€ãã®åˆ—ã§ã‚°ãƒ«ãƒ¼ãƒ—化ã—ã¾ã™ã€‚"},search:{placeholder:"検索...",showingItems:"表示中ã®é …ç›®:",selectedItems:"é¸æŠžã—ãŸé …ç›®:",totalItems:"é …ç›®ã®ç·æ•°:",size:"ページサイズ:",first:"最åˆã®ãƒšãƒ¼ã‚¸",next:"次ã®ãƒšãƒ¼ã‚¸",previous:"å‰ã®ãƒšãƒ¼ã‚¸",last:"å‰ã®ãƒšãƒ¼ã‚¸"},menu:{text:"列ã®é¸æŠž:"},sort:{ascending:"昇順ã«ä¸¦ã¹æ›¿ãˆ",descending:"é™é †ã«ä¸¦ã¹æ›¿ãˆ",remove:"並ã¹æ›¿ãˆã®è§£é™¤"},column:{hide:"列ã®éžè¡¨ç¤º"},aggregation:{count:"åˆè¨ˆè¡Œæ•°: ",sum:"åˆè¨ˆ: ",avg:"å¹³å‡: ",min:"最å°: ",max:"最大: "},pinning:{pinLeft:"å·¦ã«å›ºå®š",pinRight:"å³ã«å›ºå®š",unpin:"固定解除"},gridMenu:{columns:"列:",importerTitle:"ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ",exporterAllAsCsv:"ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",exporterVisibleAsCsv:"表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",exporterSelectedAsCsv:"é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",exporterAllAsPdf:"ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",exporterVisibleAsPdf:"表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",exporterSelectedAsPdf:"é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ",clearAllFilters:"ã™ã¹ã¦ã®ãƒ•ã‚£ãƒ«ã‚¿ã‚’清掃ã—ã¦ãã ã•ã„"},importer:{noHeaders:"列åã‚’å–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。",noObjects:"オブジェクトをå–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ä»¥å¤–ã®ãƒ‡ãƒ¼ã‚¿ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。",invalidCsv:"ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªCSVå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。",invalidJson:"ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªJSONå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。",jsonNotArray:"インãƒãƒ¼ãƒˆã—ãŸJSONファイルã«ã¯é…列ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚処ç†ã‚’中止ã—ã¾ã™ã€‚"},pagination:{aria:{pageToFirst:"最åˆã®ãƒšãƒ¼ã‚¸",pageBack:"å‰ã®ãƒšãƒ¼ã‚¸",pageSelected:"ç¾åœ¨ã®ãƒšãƒ¼ã‚¸",pageForward:"次ã®ãƒšãƒ¼ã‚¸",pageToLast:"最後ã®ãƒšãƒ¼ã‚¸"},sizes:"é …ç›®/ページ",totalItems:"é …ç›®",through:"ã‹ã‚‰",of:"é …ç›®/å…¨"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ko",{aggregate:{label:"ì•„ì´í…œ"},groupPanel:{description:"컬럼으로 그룹핑하기 위해서는 컬럼 í—¤ë”를 ëŒì–´ 떨어뜨려 주세요."},search:{placeholder:"검색...",showingItems:"항목 보여주기:",selectedItems:"ì„ íƒ í•­ëª©:",totalItems:"ì „ì²´ 항목:",size:"페ì´ì§€ í¬ê¸°:",first:"첫번째 페ì´ì§€",next:"ë‹¤ìŒ íŽ˜ì´ì§€",previous:"ì´ì „ 페ì´ì§€",last:"마지막 페ì´ì§€"},menu:{text:"ì»¬ëŸ¼ì„ ì„ íƒí•˜ì„¸ìš”:"},sort:{ascending:"오름차순 ì •ë ¬",descending:"내림차순 ì •ë ¬",remove:"소팅 제거"},column:{hide:"컬럼 제거"},aggregation:{count:"ì „ì²´ 갯수: ",sum:"ì „ì²´: ",avg:"í‰ê· : ",min:"최소: ",max:"최대: "},pinning:{pinLeft:"왼쪽 í•€",pinRight:"오른쪽 í•€",unpin:"í•€ 제거"},gridMenu:{columns:"컬럼:",importerTitle:"íŒŒì¼ ê°€ì ¸ì˜¤ê¸°",exporterAllAsCsv:"csvë¡œ 모든 ë°ì´í„° 내보내기",exporterVisibleAsCsv:"csvë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기",exporterSelectedAsCsv:"csvë¡œ ì„ íƒëœ ë°ì´í„° 내보내기",exporterAllAsPdf:"pdfë¡œ 모든 ë°ì´í„° 내보내기",exporterVisibleAsPdf:"pdfë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기",exporterSelectedAsPdf:"pdfë¡œ ì„ íƒ ë°ì´í„° 내보내기",clearAllFilters:"모든 필터를 청소"},importer:{noHeaders:"ì»¬ëŸ¼ëª…ì´ ì§€ì •ë˜ì–´ 있지 않습니다. 파ì¼ì— í—¤ë”ê°€ 명시ë˜ì–´ 있는지 확ì¸í•´ 주세요.",noObjects:"ë°ì´í„°ê°€ 지정ë˜ì–´ 있지 않습니다. ë°ì´í„°ê°€ 파ì¼ì— 있는지 확ì¸í•´ 주세요.",invalidCsv:"파ì¼ì„ 처리할 수 없습니다. 올바른 csvì¸ì§€ 확ì¸í•´ 주세요.",invalidJson:"파ì¼ì„ 처리할 수 없습니다. 올바른 jsonì¸ì§€ 확ì¸í•´ 주세요.",jsonNotArray:"json 파ì¼ì€ ë°°ì—´ì„ í¬í•¨í•´ì•¼ 합니다."},pagination:{sizes:"페ì´ì§€ë‹¹ 항목",totalItems:"ì „ì²´ 항목"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("nl",{aggregate:{label:"items"},groupPanel:{description:"Sleep hier een kolomnaam heen om op te groeperen."},search:{placeholder:"Zoeken...",showingItems:"Getoonde items:",selectedItems:"Geselecteerde items:",totalItems:"Totaal aantal items:",size:"Items per pagina:",first:"Eerste pagina",next:"Volgende pagina",previous:"Vorige pagina",last:"Laatste pagina"},menu:{text:"Kies kolommen:"},sort:{ascending:"Sorteer oplopend",descending:"Sorteer aflopend",remove:"Verwijder sortering"},column:{hide:"Verberg kolom"},aggregation:{count:"Aantal rijen: ",sum:"Som: ",avg:"Gemiddelde: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Zet links vast",pinRight:"Zet rechts vast",unpin:"Maak los"},gridMenu:{columns:"Kolommen:",importerTitle:"Importeer bestand",exporterAllAsCsv:"Exporteer alle data als csv",exporterVisibleAsCsv:"Exporteer zichtbare data als csv",exporterSelectedAsCsv:"Exporteer geselecteerde data als csv",exporterAllAsPdf:"Exporteer alle data als pdf",exporterVisibleAsPdf:"Exporteer zichtbare data als pdf",exporterSelectedAsPdf:"Exporteer geselecteerde data als pdf",clearAllFilters:"Reinig alle filters"},importer:{noHeaders:"Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?",noObjects:"Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?",invalidCsv:"Het bestand kan niet verwerkt worden. Is het een valide csv bestand?",invalidJson:"Het bestand kan niet verwerkt worden. Is het valide json?",jsonNotArray:"Het json bestand moet een array bevatten. De actie wordt geannuleerd."},pagination:{sizes:"items per pagina",totalItems:"items",of:"van de"},grouping:{group:"Groepeer",ungroup:"Groepering opheffen",aggregate_count:"Agg: Aantal",aggregate_sum:"Agg: Som",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Gem",aggregate_remove:"Agg: Verwijder"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("no",{headerCell:{aria:{defaultFilterLabel:"Filter for column",removeFilter:"Remove Filter",columnMenuButtonLabel:"Column Menu"},priority:"Priority:",filterLabel:"Filter for column: "},aggregate:{label:"items"},groupPanel:{description:"Drag a column header here and drop it to group by that column."},search:{placeholder:"Search...",showingItems:"Showing Items:",selectedItems:"Selected Items:",totalItems:"Total Items:",size:"Page Size:",first:"First Page",next:"Next Page",previous:"Previous Page",last:"Last Page"},menu:{text:"Choose Columns:"},sort:{ascending:"Sort Ascending",descending:"Sort Descending",none:"Sort None",remove:"Remove Sort"},column:{hide:"Hide Column"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pin Left",pinRight:"Pin Right",unpin:"Unpin"},columnMenu:{close:"Close"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Kolonner:",importerTitle:"Importer fil",exporterAllAsCsv:"Eksporter alle data som csv",exporterVisibleAsCsv:"Eksporter synlige data som csv",exporterSelectedAsCsv:"Eksporter utvalgte data som csv",exporterAllAsPdf:"Eksporter alle data som pdf",exporterVisibleAsPdf:"Eksporter synlige data som pdf",exporterSelectedAsPdf:"Eksporter utvalgte data som pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"Page to first",pageBack:"Page back",pageSelected:"Selected page",pageForward:"Page forward",pageToLast:"Page to last"},sizes:"items per page",totalItems:"items",through:"through",of:"of"},grouping:{group:"Group",ungroup:"Ungroup",aggregate_count:"Agg: Count",aggregate_sum:"Agg: Sum",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Remove"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("pl",{headerCell:{aria:{defaultFilterLabel:"Filtr dla kolumny",removeFilter:"UsuÅ„ filtr",columnMenuButtonLabel:"Menu kolumny"},priority:"Prioritet:",filterLabel:"Filtr dla kolumny: "},aggregate:{label:"pozycji"},groupPanel:{description:"PrzeciÄ…gnij nagłówek kolumny tutaj, aby pogrupować wedÅ‚ug niej."},search:{placeholder:"Szukaj...",showingItems:"Widoczne pozycje:",selectedItems:"Zaznaczone pozycje:",totalItems:"Wszystkich pozycji:",size:"Rozmiar strony:",first:"Pierwsza strona",next:"NastÄ™pna strona",previous:"Poprzednia strona",last:"Ostatnia strona"},menu:{text:"Wybierz kolumny:"},sort:{ascending:"Sortuj rosnÄ…co",descending:"Sortuj malejÄ…co",none:"Brak sortowania",remove:"WyÅ‚Ä…cz sortowanie"},column:{hide:"Ukryj kolumne"},aggregation:{count:"Razem pozycji: ",sum:"Razem: ",avg:"Åšrednia: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Przypnij do lewej",pinRight:"Przypnij do prawej",unpin:"Odepnij"},columnMenu:{close:"Zamknij"},gridMenu:{aria:{buttonLabel:"Menu Grida"},columns:"Kolumny:",importerTitle:"Importuj plik",exporterAllAsCsv:"Eksportuj wszystkie dane do csv",exporterVisibleAsCsv:"Eksportuj widoczne dane do csv",exporterSelectedAsCsv:"Eksportuj zaznaczone dane do csv",exporterAllAsPdf:"Eksportuj wszystkie dane do pdf",exporterVisibleAsPdf:"Eksportuj widoczne dane do pdf",exporterSelectedAsPdf:"Eksportuj zaznaczone dane do pdf",clearAllFilters:"Wyczyść filtry"},importer:{noHeaders:"Nie udaÅ‚o siÄ™ wczytać nazw kolumn. Czy plik posiada nagłówek?",noObjects:"Nie udalo siÄ™ wczytać pozycji. Czy plik zawiera dane??",invalidCsv:"Nie udaÅ‚o siÄ™ przetworzyć pliku, jest to prawidlowy plik CSV??",invalidJson:"Nie udaÅ‚o siÄ™ przetworzyć pliku, jest to prawidlowy plik Json?",jsonNotArray:"Importowany plik json musi zawierać tablicÄ™, importowanie przerwane."},pagination:{aria:{pageToFirst:"Pierwsza strona",pageBack:"Poprzednia strona",pageSelected:"Wybrana strona",pageForward:"NastÄ™pna strona",pageToLast:"Ostatnia strona"},sizes:"pozycji na stronÄ™",totalItems:"pozycji",through:"do",of:"z"},grouping:{group:"Grupuj",ungroup:"Rozgrupuj",aggregate_count:"Zbiorczo: Razem",aggregate_sum:"Zbiorczo: Suma",aggregate_max:"Zbiorczo: Max",aggregate_min:"Zbiorczo: Min",aggregate_avg:"Zbiorczo: Åšrednia",aggregate_remove:"Zbiorczo: UsuÅ„"},validate:{error:"BÅ‚Ä…d:",minLength:"Wartość powinna skÅ‚adać siÄ™ z co najmniej THRESHOLD znaków.",maxLength:"Wartość powinna skÅ‚adać siÄ™ z przynajmniej THRESHOLD znaków.",required:"Wartość jest wymagana."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("pt-br",{headerCell:{aria:{defaultFilterLabel:"Filtro por coluna",removeFilter:"Remover filtro",columnMenuButtonLabel:"Menu coluna"},priority:"Prioridade:",filterLabel:"Filtro por coluna: "},aggregate:{label:"itens"},groupPanel:{description:"Arraste e solte uma coluna aqui para agrupar por essa coluna"},search:{placeholder:"Procurar...",showingItems:"Mostrando os Itens:",selectedItems:"Items Selecionados:",totalItems:"Total de Itens:",size:"Tamanho da Página:",first:"Primeira Página",next:"Próxima Página",previous:"Página Anterior",last:"Última Página"},menu:{text:"Selecione as colunas:"},sort:{ascending:"Ordenar Ascendente",descending:"Ordenar Descendente",none:"Nenhuma Ordem",remove:"Remover Ordenação"},column:{hide:"Esconder coluna"},aggregation:{count:"total de linhas: ",sum:"total: ",avg:"med: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fixar Esquerda",pinRight:"Fixar Direita",unpin:"Desprender"},columnMenu:{close:"Fechar"},gridMenu:{aria:{buttonLabel:"Menu Grid"},columns:"Colunas:",importerTitle:"Importar arquivo",exporterAllAsCsv:"Exportar todos os dados como csv",exporterVisibleAsCsv:"Exportar dados visíveis como csv",exporterSelectedAsCsv:"Exportar dados selecionados como csv",exporterAllAsPdf:"Exportar todos os dados como pdf",exporterVisibleAsPdf:"Exportar dados visíveis como pdf",exporterSelectedAsPdf:"Exportar dados selecionados como pdf",clearAllFilters:"Limpar todos os filtros"},importer:{noHeaders:"Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?",noObjects:"Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?",invalidCsv:"Arquivo não pode ser processado. É um CSV válido?",invalidJson:"Arquivo não pode ser processado. É um Json válido?",jsonNotArray:"Arquivo json importado tem que conter um array. Abortando."},pagination:{aria:{pageToFirst:"Primeira página",pageBack:"Página anterior",pageSelected:"Página Selecionada",pageForward:"Proxima",pageToLast:"Anterior"},sizes:"itens por página",totalItems:"itens",through:"através dos",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Contar",aggregate_sum:"Agr: Soma",aggregate_max:"Agr: Max",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Med",aggregate_remove:"Agr: Remover"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("pt",{headerCell:{aria:{defaultFilterLabel:"Filtro por coluna",removeFilter:"Remover filtro",columnMenuButtonLabel:"Menu coluna"},priority:"Prioridade:",filterLabel:"Filtro por coluna: "},aggregate:{label:"itens"},groupPanel:{description:"Arraste e solte uma coluna aqui para agrupar por essa coluna"},search:{placeholder:"Procurar...",showingItems:"Mostrando os Itens:",selectedItems:"Itens Selecionados:",totalItems:"Total de Itens:",size:"Tamanho da Página:",first:"Primeira Página",next:"Próxima Página",previous:"Página Anterior",last:"Última Página"},menu:{text:"Selecione as colunas:"},sort:{ascending:"Ordenar Ascendente",descending:"Ordenar Descendente",none:"Nenhuma Ordem",remove:"Remover Ordenação"},column:{hide:"Esconder coluna"},aggregation:{count:"total de linhas: ",sum:"total: ",avg:"med: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fixar Esquerda",pinRight:"Fixar Direita",unpin:"Desprender"},columnMenu:{close:"Fechar"},gridMenu:{aria:{buttonLabel:"Menu Grid"},columns:"Colunas:",importerTitle:"Importar ficheiro",exporterAllAsCsv:"Exportar todos os dados como csv",exporterVisibleAsCsv:"Exportar dados visíveis como csv",exporterSelectedAsCsv:"Exportar dados selecionados como csv",exporterAllAsPdf:"Exportar todos os dados como pdf",exporterVisibleAsPdf:"Exportar dados visíveis como pdf",exporterSelectedAsPdf:"Exportar dados selecionados como pdf",clearAllFilters:"Limpar todos os filtros"},importer:{noHeaders:"Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?",noObjects:"Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?",invalidCsv:"Ficheiro não pode ser processado. É um CSV válido?",invalidJson:"Ficheiro não pode ser processado. É um Json válido?",jsonNotArray:"Ficheiro json importado tem que conter um array. Interrompendo."},pagination:{aria:{pageToFirst:"Primeira página",pageBack:"Página anterior",pageSelected:"Página Selecionada",pageForward:"Próxima",pageToLast:"Anterior"},sizes:"itens por página",totalItems:"itens",through:"através dos",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Contar",aggregate_sum:"Agr: Soma",aggregate_max:"Agr: Max",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Med",aggregate_remove:"Agr: Remover"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ro",{headerCell:{aria:{defaultFilterLabel:"Filtru pentru coloana",removeFilter:"Sterge filtru",columnMenuButtonLabel:"Column Menu"},priority:"Prioritate:",filterLabel:"Filtru pentru coloana:"},aggregate:{label:"Elemente"},groupPanel:{description:"Trage un cap de coloana aici pentru a grupa elementele dupa coloana respectiva"},search:{placeholder:"Cauta...",showingItems:"Arata elementele:",selectedItems:"Elementele selectate:",totalItems:"Total elemente:",size:"Marime pagina:",first:"Prima pagina",next:"Pagina urmatoare",previous:"Pagina anterioara",last:"Ultima pagina"},menu:{text:"Alege coloane:"},sort:{ascending:"Ordoneaza crescator",descending:"Ordoneaza descrescator",none:"Fara ordonare",remove:"Sterge ordonarea"},column:{hide:"Ascunde coloana"},aggregation:{count:"total linii: ",sum:"total: ",avg:"medie: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pin la stanga",pinRight:"Pin la dreapta",unpin:"Sterge pinul"},columnMenu:{close:"Inchide"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Coloane:",importerTitle:"Incarca fisier",exporterAllAsCsv:"Exporta toate datele ca csv",exporterVisibleAsCsv:"Exporta datele vizibile ca csv",exporterSelectedAsCsv:"Exporta datele selectate ca csv",exporterAllAsPdf:"Exporta toate datele ca pdf",exporterVisibleAsPdf:"Exporta datele vizibile ca pdf",exporterSelectedAsPdf:"Exporta datele selectate ca csv pdf",clearAllFilters:"Sterge toate filtrele"},importer:{noHeaders:"Numele coloanelor nu a putut fi incarcat, acest fisier are un header?",noObjects:"Datele nu au putut fi incarcate, exista date in fisier in afara numelor de coloane?",invalidCsv:"Fisierul nu a putut fi procesat, ati incarcat un CSV valid ?",invalidJson:"Fisierul nu a putut fi procesat, ati incarcat un Json valid?",jsonNotArray:"Json-ul incarcat trebuie sa contina un array, inchidere."},pagination:{aria:{pageToFirst:"Prima pagina",pageBack:"O pagina inapoi",pageSelected:"Pagina selectata",pageForward:"O pagina inainte",pageToLast:"Ultima pagina"},sizes:"Elemente per pagina",totalItems:"elemente",through:"prin",of:"of"},grouping:{group:"Grupeaza",ungroup:"Opreste gruparea",aggregate_count:"Agg: Count",aggregate_sum:"Agg: Sum",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Remove"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ru",{headerCell:{aria:{defaultFilterLabel:"Фильтр Ñтолбца",removeFilter:"Удалить фильтр",columnMenuButtonLabel:"Меню Ñтолбца"},priority:"Приоритет:",filterLabel:"Фильтр Ñтолбца: "},aggregate:{label:"Ñлементы"},groupPanel:{description:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ по Ñтолбцу перетащите Ñюда его название."},search:{placeholder:"ПоиÑк...",showingItems:"Показать Ñлементы:",selectedItems:"Выбранные Ñлементы:",totalItems:"Ð’Ñего Ñлементов:",size:"Размер Ñтраницы:",first:"ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница",next:"Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница",previous:"ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница",last:"ПоÑледнÑÑ Ñтраница"},menu:{text:"Выбрать Ñтолбцы:"},sort:{ascending:"По возраÑтанию",descending:"По убыванию",none:"Без Ñортировки",remove:"Убрать Ñортировку"},column:{hide:"СпрÑтать Ñтолбец"},aggregation:{count:"вÑего Ñтрок: ",sum:"итого: ",avg:"Ñреднее: ",min:"мин: ",max:"макÑ: "},pinning:{pinLeft:"Закрепить Ñлева",pinRight:"Закрепить Ñправа",unpin:"Открепить"},columnMenu:{close:"Закрыть"},gridMenu:{aria:{buttonLabel:"Меню"},columns:"Столбцы:",importerTitle:"Импортировать файл",exporterAllAsCsv:"ЭкÑпортировать вÑÑ‘ в CSV",exporterVisibleAsCsv:"ЭкÑпортировать видимые данные в CSV",exporterSelectedAsCsv:"ЭкÑпортировать выбранные данные в CSV",exporterAllAsPdf:"ЭкÑпортировать вÑÑ‘ в PDF",exporterVisibleAsPdf:"ЭкÑпортировать видимые данные в PDF",exporterSelectedAsPdf:"ЭкÑпортировать выбранные данные в PDF",clearAllFilters:"ОчиÑтите вÑе фильтры"},importer:{noHeaders:"Ðе удалоÑÑŒ получить Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñтолбцов, еÑÑ‚ÑŒ ли в файле заголовок?",noObjects:"Ðе удалоÑÑŒ получить данные, еÑÑ‚ÑŒ ли в файле Ñтроки кроме заголовка?",invalidCsv:"Ðе удалоÑÑŒ обработать файл, Ñто правильный CSV-файл?",invalidJson:"Ðе удалоÑÑŒ обработать файл, Ñто правильный JSON?",jsonNotArray:"Импортируемый JSON-файл должен Ñодержать маÑÑив, Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚Ð¼ÐµÐ½ÐµÐ½Ð°."},pagination:{aria:{pageToFirst:"ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница",pageBack:"ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница",pageSelected:"Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ñтраница",pageForward:"Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница",pageToLast:"ПоÑледнÑÑ Ñтраница"},sizes:"Ñтрок на Ñтраницу",totalItems:"Ñтрок",through:"по",of:"из"},grouping:{group:"Группировать",ungroup:"Разгруппировать",aggregate_count:"Группировать: Count",aggregate_sum:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Сумма",aggregate_max:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: МакÑимум",aggregate_min:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Минимум",aggregate_avg:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: Среднее",aggregate_remove:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹: ПуÑто"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("sk",{aggregate:{label:"items"},groupPanel:{description:"Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca."},search:{placeholder:"Hľadaj...",showingItems:"Zobrazujem položky:",selectedItems:"Vybraté položky:",totalItems:"PoÄet položiek:",size:"PoÄet:",first:"Prvá strana",next:"ÄŽalÅ¡ia strana",previous:"Predchádzajúca strana",last:"Posledná strana"},menu:{text:"Vyberte stĺpce:"},sort:{ascending:"ZotriediÅ¥ vzostupne",descending:"ZotriediÅ¥ zostupne",remove:"VymazaÅ¥ triedenie"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},gridMenu:{columns:"Columns:",importerTitle:"Import file",exporterAllAsCsv:"Export all data as csv",exporterVisibleAsCsv:"Export visible data as csv",exporterSelectedAsCsv:"Export selected data as csv",exporterAllAsPdf:"Export all data as pdf",exporterVisibleAsPdf:"Export visible data as pdf",exporterSelectedAsPdf:"Export selected data as pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("sv",{aggregate:{label:"Artiklar"},groupPanel:{description:"Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen."},search:{placeholder:"Sök...",showingItems:"Visar artiklar:",selectedItems:"Valda artiklar:",totalItems:"Antal artiklar:",size:"Sidstorlek:",first:"Första sidan",next:"Nästa sida",previous:"FöregÃ¥ende sida",last:"Sista sidan"},menu:{text:"Välj kolumner:"},sort:{ascending:"Sortera stigande",descending:"Sortera fallande",remove:"Inaktivera sortering"},column:{hide:"Göm kolumn"},aggregation:{count:"Antal rader: ",sum:"Summa: ",avg:"Genomsnitt: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Fäst vänster",pinRight:"Fäst höger",unpin:"Lösgör"},gridMenu:{columns:"Kolumner:",importerTitle:"Importera fil",exporterAllAsCsv:"Exportera all data som CSV",exporterVisibleAsCsv:"Exportera synlig data som CSV",exporterSelectedAsCsv:"Exportera markerad data som CSV",exporterAllAsPdf:"Exportera all data som PDF",exporterVisibleAsPdf:"Exportera synlig data som PDF",exporterSelectedAsPdf:"Exportera markerad data som PDF",clearAllFilters:"Rengör alla filter"},importer:{noHeaders:"Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?",noObjects:"Objekt kunde inte härledas. Har filen data undantaget sidhuvud?",invalidCsv:"Filen kunde inte behandlas, är den en giltig CSV?",invalidJson:"Filen kunde inte behandlas, är den en giltig JSON?",jsonNotArray:"Importerad JSON-fil mÃ¥ste innehÃ¥lla ett fält. Import avbruten."},pagination:{sizes:"Artiklar per sida",totalItems:"Artiklar"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ta",{aggregate:{label:"உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯"},groupPanel:{description:"ஒர௠பதà¯à®¤à®¿à®¯à¯ˆ கà¯à®´à¯à®µà®¾à®• அமைகà¯à®• அபà¯à®ªà®¤à¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯ˆ இஙà¯à®•à¯‡ இழà¯à®¤à¯à®¤à¯ வரவà¯à®®à¯ "},search:{placeholder:"தேடல௠...",showingItems:"உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ˆ காணà¯à®ªà®¿à®¤à¯à®¤à®²à¯:",selectedItems:"தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:",totalItems:"மொதà¯à®¤ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:",size:"பகà¯à®• அளவà¯: ",first:"à®®à¯à®¤à®²à¯ பகà¯à®•à®®à¯",next:"அடà¯à®¤à¯à®¤ பகà¯à®•à®®à¯",previous:"à®®à¯à®¨à¯à®¤à¯ˆà®¯ பகà¯à®•à®®à¯ ",last:"இறà¯à®¤à®¿ பகà¯à®•à®®à¯"},menu:{text:"பதà¯à®¤à®¿à®•à®³à¯ˆ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯:"},sort:{ascending:"மேலிரà¯à®¨à¯à®¤à¯ கீழாக",descending:"கீழிரà¯à®¨à¯à®¤à¯ மேலாக",remove:"வரிசையை நீகà¯à®•à¯"},column:{hide:"பதà¯à®¤à®¿à®¯à¯ˆ மறைதà¯à®¤à¯ வை "},aggregation:{count:"மொதà¯à®¤ வரிகளà¯:",sum:"மொதà¯à®¤à®®à¯: ",avg:"சராசரி: ",min:"கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®š: ",max:"அதிகபடà¯à®š: "},pinning:{pinLeft:"இடதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®• ",pinRight:"வலதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®•",unpin:"பிரி"},gridMenu:{columns:"பதà¯à®¤à®¿à®•à®³à¯:",importerTitle:"கோபà¯à®ªà¯ : படிதà¯à®¤à®²à¯",exporterAllAsCsv:"எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv",exporterVisibleAsCsv:"இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv",exporterSelectedAsCsv:"தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv",exporterAllAsPdf:"எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf",exporterVisibleAsPdf:"இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf",exporterSelectedAsPdf:"தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"பதà¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ பெற இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà®¿à®±à¯à®•à¯ தலைபà¯à®ªà¯ உளà¯à®³à®¤à®¾?",noObjects:"இலகà¯à®•à¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ, கோபà¯à®ªà®¿à®²à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ தவிர தரவ௠à®à®¤à¯‡à®©à¯à®®à¯ உளà¯à®³à®¤à®¾? ",invalidCsv:"சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - csv",invalidJson:"சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - json",jsonNotArray:"படிதà¯à®¤ கோபà¯à®ªà®¿à®²à¯ வரிசைகள௠உளà¯à®³à®¤à¯, நடைமà¯à®±à¯ˆ ரதà¯à®¤à¯ செய௠: json"},pagination:{sizes:"உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ / பகà¯à®•à®®à¯",totalItems:"உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ "},grouping:{group:"கà¯à®´à¯",ungroup:"பிரி",aggregate_count:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : எணà¯à®£à¯",aggregate_sum:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கூடà¯à®Ÿà®²à¯",aggregate_max:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : அதிகபடà¯à®šà®®à¯",aggregate_min:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯",aggregate_avg:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : சராசரி",aggregate_remove:"மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : நீகà¯à®•à¯"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("tr",{headerCell:{aria:{defaultFilterLabel:"Sütun için filtre",removeFilter:"Filtreyi Kaldır",columnMenuButtonLabel:"Sütun Menüsü"},priority:"Öncelik:",filterLabel:"Sütun için filtre: "},aggregate:{label:"kayıtlar"},groupPanel:{description:"Sütuna göre gruplamak için sütun baÅŸlığını buraya sürükleyin ve bırakın."},search:{placeholder:"Arama...",showingItems:"Gösterilen Kayıt:",selectedItems:"Seçili Kayıt:",totalItems:"Toplam Kayıt:",size:"Sayfa Boyutu:",first:"Ä°lk Sayfa",next:"Sonraki Sayfa",previous:"Önceki Sayfa",last:"Son Sayfa"},menu:{text:"Sütunları Seç:"},sort:{ascending:"Artan Sırada Sırala",descending:"Azalan Sırada Sırala",none:"Sıralama Yapma",remove:"Sıralamayı Kaldır"},column:{hide:"Sütunu Gizle"},aggregation:{count:"toplam satır: ",sum:"toplam: ",avg:"ort: ",min:"min: ",max:"maks: "},pinning:{pinLeft:"Sola Sabitle",pinRight:"SaÄŸa Sabitle",unpin:"Sabitlemeyi Kaldır"},columnMenu:{close:"Kapat"},gridMenu:{aria:{buttonLabel:"Tablo Menü"},columns:"Sütunlar:",importerTitle:"Dosya içeri aktar",exporterAllAsCsv:"Bütün veriyi CSV olarak dışarı aktar",exporterVisibleAsCsv:"Görünen veriyi CSV olarak dışarı aktar",exporterSelectedAsCsv:"Seçili veriyi CSV olarak dışarı aktar",exporterAllAsPdf:"Bütün veriyi PDF olarak dışarı aktar",exporterVisibleAsPdf:"Görünen veriyi PDF olarak dışarı aktar",exporterSelectedAsPdf:"Seçili veriyi PDF olarak dışarı aktar",clearAllFilters:"Bütün filtreleri kaldır"},importer:{noHeaders:"Sütun isimleri üretilemiyor, dosyanın bir baÅŸlığı var mı?",noObjects:"Nesneler üretilemiyor, dosyada baÅŸlıktan baÅŸka bir veri var mı?",invalidCsv:"Dosya iÅŸlenemedi, geçerli bir CSV dosyası mı?",invalidJson:"Dosya iÅŸlenemedi, geçerli bir Json dosyası mı?",jsonNotArray:"Alınan Json dosyasında bir dizi bulunmalıdır, iÅŸlem iptal ediliyor."},pagination:{aria:{pageToFirst:"Ä°lk sayfaya",pageBack:"Geri git",pageSelected:"Seçili sayfa",pageForward:"Ä°leri git",pageToLast:"Sona git"},sizes:"Sayfadaki nesne sayısı",totalItems:"kayıtlar",through:"",of:""},grouping:{group:"Grupla",ungroup:"Gruplama",aggregate_count:"Yekun: Sayı",aggregate_sum:"Yekun: Toplam",aggregate_max:"Yekun: Maks",aggregate_min:"Yekun: Min",aggregate_avg:"Yekun: Ort",aggregate_remove:"Yekun: Sil"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("ua",{headerCell:{aria:{defaultFilterLabel:"Фільтр Ñтовпчика",removeFilter:"Видалити фільтр",columnMenuButtonLabel:"Меню Ñтвпчика"},priority:"Пріоритет:",filterLabel:"Фільтр Ñтовпчика: "},aggregate:{label:"елементи"},groupPanel:{description:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° Ñтовпчиком перетÑгніть Ñюди його назву."},search:{placeholder:"Пошук...",showingItems:"Показати елементи:",selectedItems:"Обрані елементи:",totalItems:"УÑього елементів:",size:"Розмір Ñторінки:",first:"Перша Ñторінка",next:"ÐаÑтупна Ñторінка",previous:"ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка",last:"ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка"},menu:{text:"Обрати Ñтвпчики:"},sort:{ascending:"За зроÑтаннÑм",descending:"За ÑпаданнÑм",none:"Без ÑортуваннÑ",remove:"Прибрати ÑортуваннÑ"},column:{hide:"Приховати Ñтовпчик"},aggregation:{count:"уÑього Ñ€Ñдків: ",sum:"ітого: ",avg:"Ñереднє: ",min:"мін: ",max:"макÑ: "},pinning:{pinLeft:"Закріпити ліворуч",pinRight:"Закріпити праворуч",unpin:"Відкріпити"},columnMenu:{close:"Закрити"},gridMenu:{aria:{buttonLabel:"Меню"},columns:"Стовпчики:",importerTitle:"Імпортувати файл",exporterAllAsCsv:"ЕкÑпортувати вÑе в CSV",exporterVisibleAsCsv:"ЕкÑпортувати видимі дані в CSV",exporterSelectedAsCsv:"ЕкÑпортувати обрані дані в CSV",exporterAllAsPdf:"ЕкÑпортувати вÑе в PDF",exporterVisibleAsPdf:"ЕкÑпортувати видимі дані в PDF",exporterSelectedAsPdf:"ЕкÑпортувати обрані дані в PDF",clearAllFilters:"ОчиÑтити вÑÑ– фільтри"},importer:{noHeaders:"Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ назви Ñтовпчиків, чи Ñ” в файлі заголовок?",noObjects:"Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ дані, чи Ñ” в файлі Ñ€Ñдки окрім заголовка?",invalidCsv:"Ðе вдалоÑÑ Ð¾Ð±Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ файл, чи це коректний CSV-файл?",invalidJson:"Ðе вдалоÑÑ Ð¾Ð±Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ файл, чи це коректний JSON?",jsonNotArray:"JSON-файл що імпортуєтьÑÑ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ міÑтити маÑив, операцію ÑкаÑовано."},pagination:{aria:{pageToFirst:"Перша Ñторінка",pageBack:"ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка",pageSelected:"Обрана Ñторінка",pageForward:"ÐаÑтупна Ñторінка",pageToLast:"ОÑÑ‚Ð°Ð½Ð½Ñ Ñторінка"},sizes:"Ñ€Ñдків на Ñторінку",totalItems:"Ñ€Ñдків",through:"по",of:"з"},grouping:{
+group:"Групувати",ungroup:"Розгрупувати",aggregate_count:"Групувати: КількіÑÑ‚ÑŒ",aggregate_sum:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Сума",aggregate_max:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: МакÑимум",aggregate_min:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Мінімум",aggregate_avg:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: Серднє",aggregate_remove:"Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸: ПуÑто"}}),a}])}])}(),function(){var a=["uiT","uiTranslate"],b=["t","uiTranslate"],c=angular.module("ui.grid.i18n");c.constant("i18nConstants",{MISSING:"[MISSING]",UPDATE_EVENT:"$uiI18n",LOCALE_DIRECTIVE_ALIAS:"uiI18n",DEFAULT_LANG:"en"}),c.service("i18nService",["$log","i18nConstants","$rootScope",function(a,b,c){var d={_langs:{},current:null,get:function(a){return this._langs[a.toLowerCase()]},add:function(a,b){var c=a.toLowerCase();this._langs[c]||(this._langs[c]={}),angular.extend(this._langs[c],b)},getAllLangs:function(){var a=[];if(!this._langs)return a;for(var b in this._langs)a.push(b);return a},setCurrent:function(a){this.current=a.toLowerCase()},getCurrentLang:function(){return this.current}},e={add:function(a,b){"object"==typeof a?angular.forEach(a,function(a){a&&d.add(a,b)}):d.add(a,b)},getAllLangs:function(){return d.getAllLangs()},get:function(a){var b=a?a:e.getCurrentLang();return d.get(b)},getSafeText:function(a,c){var f=c?c:e.getCurrentLang(),g=d.get(f);if(!g)return b.MISSING;for(var h=a.split("."),i=g,j=0;j<h.length;++j){if(void 0===i[h[j]]||null===i[h[j]])return b.MISSING;i=i[h[j]]}return i},setCurrentLang:function(a){a&&(d.setCurrent(a),c.$broadcast(b.UPDATE_EVENT))},getCurrentLang:function(){var a=d.getCurrentLang();return a||(a=b.DEFAULT_LANG,d.setCurrent(a)),a}};return e}]);var d=function(a,b){return{compile:function(){return{pre:function(c,d,e){var f=b.LOCALE_DIRECTIVE_ALIAS,g=c.$eval(e[f]);g?c.$watch(e[f],function(){a.setCurrentLang(g)}):e.$$observers&&e.$observe(f,function(){a.setCurrentLang(e[f]||b.DEFAULT_LANG)})}}}}};c.directive("uiI18n",["i18nService","i18nConstants",d]);var e=function(b,c,d){return{restrict:"EA",compile:function(){return{pre:function(e,f,g){var h,i=a[0],j=a[1],k=g[i]||g[j]||f.html(),l=d.MISSING+k;if(g.$$observers){var m=g[i]?i:j;h=g.$observe(m,function(a){a&&f.html(b(a)(c.getCurrentLang())||l)})}var n=b(k),o=e.$on(d.UPDATE_EVENT,function(a){h?h(g[i]||g[j]):f.html(n(c.get())||l)});e.$on("$destroy",o),f.html(n(c.get())||l)}}}}};angular.forEach(a,function(a){c.directive(a,["$parse","i18nService","i18nConstants",e])});var f=function(a,b,c){return function(d){var e=a(d);return e(b.get())||c.MISSING+d}};angular.forEach(b,function(a){c.filter(a,["$parse","i18nService","i18nConstants",f])})}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("zh-cn",{headerCell:{aria:{defaultFilterLabel:"列过滤器",removeFilter:"移除过滤器",columnMenuButtonLabel:"列èœå•"},priority:"优先级:",filterLabel:"列过滤器: "},aggregate:{label:"è¡Œ"},groupPanel:{description:"拖曳表头到此处进行分组"},search:{placeholder:"查找",showingItems:"已显示行数:",selectedItems:"已选择行数:",totalItems:"总行数:",size:"æ¯é¡µæ˜¾ç¤ºè¡Œæ•°ï¼š",first:"首页",next:"下一页",previous:"上一页",last:"末页"},menu:{text:"选择列:"},sort:{ascending:"å‡åº",descending:"é™åº",none:"æ— åº",remove:"å–消排åº"},column:{hide:"éšè—列"},aggregation:{count:"计数:",sum:"求和:",avg:"å‡å€¼ï¼š",min:"最å°å€¼ï¼š",max:"最大值:"},pinning:{pinLeft:"左侧固定",pinRight:"å³ä¾§å›ºå®š",unpin:"å–消固定"},columnMenu:{close:"关闭"},gridMenu:{aria:{buttonLabel:"表格èœå•"},columns:"列:",importerTitle:"导入文件",exporterAllAsCsv:"导出全部数æ®åˆ°CSV",exporterVisibleAsCsv:"导出å¯è§æ•°æ®åˆ°CSV",exporterSelectedAsCsv:"导出已选数æ®åˆ°CSV",exporterAllAsPdf:"导出全部数æ®åˆ°PDF",exporterVisibleAsPdf:"导出å¯è§æ•°æ®åˆ°PDF",exporterSelectedAsPdf:"导出已选数æ®åˆ°PDF",clearAllFilters:"清除所有过滤器"},importer:{noHeaders:"无法获å–列å,确定文件包å«è¡¨å¤´ï¼Ÿ",noObjects:"无法获å–æ•°æ®ï¼Œç¡®å®šæ–‡ä»¶åŒ…å«æ•°æ®ï¼Ÿ",invalidCsv:"无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„CSV文件?",invalidJson:"无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„JSON文件?",jsonNotArray:"导入的文件ä¸æ˜¯JSON数组ï¼"},pagination:{aria:{pageToFirst:"第一页",pageBack:"上一页",pageSelected:"当å‰é¡µ",pageForward:"下一页",pageToLast:"最åŽä¸€é¡µ"},sizes:"è¡Œæ¯é¡µ",totalItems:"è¡Œ",through:"至",of:"å…±"},grouping:{group:"分组",ungroup:"å–消分组",aggregate_count:"åˆè®¡: 计数",aggregate_sum:"åˆè®¡: 求和",aggregate_max:"åˆè®¡: 最大",aggregate_min:"åˆè®¡: 最å°",aggregate_avg:"åˆè®¡: å¹³å‡",aggregate_remove:"åˆè®¡: 移除"}}),a}])}])}(),function(){angular.module("ui.grid").config(["$provide",function(a){a.decorator("i18nService",["$delegate",function(a){return a.add("zh-tw",{aggregate:{label:"è¡Œ"},groupPanel:{description:"拖曳表頭到此處進行分組"},search:{placeholder:"查找",showingItems:"已顯示行數:",selectedItems:"å·²é¸æ“‡è¡Œæ•¸ï¼š",totalItems:"總行數:",size:"æ¯é é¡¯ç¤ºè¡Œæ•¸ï¼š",first:"首é ",next:"下壹é ",previous:"上壹é ",last:"末é "},menu:{text:"é¸æ“‡åˆ—:"},sort:{ascending:"å‡åº",descending:"é™åº",remove:"å–消排åº"},column:{hide:"éš±è—列"},aggregation:{count:"計數:",sum:"求和:",avg:"å‡å€¼ï¼š",min:"最å°å€¼ï¼š",max:"最大值:"},pinning:{pinLeft:"å·¦å´å›ºå®š",pinRight:"å³å´å›ºå®š",unpin:"å–消固定"},gridMenu:{columns:"列:",importerTitle:"導入文件",exporterAllAsCsv:"導出全部數據到CSV",exporterVisibleAsCsv:"導出å¯è¦‹æ•¸æ“šåˆ°CSV",exporterSelectedAsCsv:"導出已é¸æ•¸æ“šåˆ°CSV",exporterAllAsPdf:"導出全部數據到PDF",exporterVisibleAsPdf:"導出å¯è¦‹æ•¸æ“šåˆ°PDF",exporterSelectedAsPdf:"導出已é¸æ•¸æ“šåˆ°PDF",clearAllFilters:"清除所有过滤器"},importer:{noHeaders:"無法ç²å–列å,確定文件包å«è¡¨é ­ï¼Ÿ",noObjects:"無法ç²å–數據,確定文件包å«æ•¸æ“šï¼Ÿ",invalidCsv:"無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„CSV文件?",invalidJson:"無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„JSON文件?",jsonNotArray:"導入的文件ä¸æ˜¯JSON數組ï¼"},pagination:{sizes:"è¡Œæ¯é ",totalItems:"è¡Œ"}}),a}])}])}(),function(){"use strict";var a=angular.module("ui.grid.autoResize",["ui.grid"]);a.directive("uiGridAutoResize",["$timeout","gridUtil",function(a,b){return{require:"uiGrid",scope:!1,link:function(a,c,d,e){function f(){i=b.elementHeight(c),h=b.elementWidth(c)}function g(){clearTimeout(j),j=setTimeout(function(){var d=b.elementHeight(c),j=b.elementWidth(c);d!==i||j!==h?(e.grid.gridHeight=d,e.grid.gridWidth=j,e.grid.api.core.raise.gridDimensionChanged(i,h,d,j),a.$apply(function(){e.grid.refresh().then(function(){f(),g()})})):g()},250)}var h,i;f();var j;g(),a.$on("$destroy",function(){clearTimeout(j)})}}}])}(),function(){"use strict";var a=angular.module("ui.grid.cellNav",["ui.grid"]);a.constant("uiGridCellNavConstants",{FEATURE_NAME:"gridCellNav",CELL_NAV_EVENT:"cellNav",direction:{LEFT:0,RIGHT:1,UP:2,DOWN:3,PG_UP:4,PG_DOWN:5},EVENT_TYPE:{KEYDOWN:0,CLICK:1,CLEAR:2}}),a.factory("uiGridCellNavFactory",["gridUtil","uiGridConstants","uiGridCellNavConstants","GridRowColumn","$q",function(a,b,c,d,e){var f=function(a,b,c,d){this.rows=a.visibleRowCache,this.columns=b.visibleColumnCache,this.leftColumns=c?c.visibleColumnCache:[],this.rightColumns=d?d.visibleColumnCache:[],this.bodyContainer=a};return f.prototype.getFocusableCols=function(){var a=this.leftColumns.concat(this.columns,this.rightColumns);return a.filter(function(a){return a.colDef.allowCellFocus})},f.prototype.getFocusableRows=function(){return this.rows.filter(function(a){return a.allowCellFocus!==!1})},f.prototype.getNextRowCol=function(a,b,d){switch(a){case c.direction.LEFT:return this.getRowColLeft(b,d);case c.direction.RIGHT:return this.getRowColRight(b,d);case c.direction.UP:return this.getRowColUp(b,d);case c.direction.DOWN:return this.getRowColDown(b,d);case c.direction.PG_UP:return this.getRowColPageUp(b,d);case c.direction.PG_DOWN:return this.getRowColPageDown(b,d)}},f.prototype.initializeSelection=function(){var a=this.getFocusableCols(),b=this.getFocusableRows();if(0===a.length||0===b.length)return null;return new d(b[0],a[0])},f.prototype.getRowColLeft=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);-1===f&&(f=1);var h=0===f?c.length-1:f-1;return h>=f?0===g?new d(a,c[h]):new d(e[g-1],c[h]):new d(a,c[h])},f.prototype.getRowColRight=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);-1===f&&(f=0);var h=f===c.length-1?0:f+1;return f>=h?g===e.length-1?new d(a,c[h]):new d(e[g+1],c[h]):new d(a,c[h])},f.prototype.getRowColDown=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);return-1===f&&(f=0),g===e.length-1?new d(a,c[f]):new d(e[g+1],c[f])},f.prototype.getRowColPageDown=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);-1===f&&(f=0);var h=this.bodyContainer.minRowsToRender();return g>=e.length-h?new d(e[e.length-1],c[f]):new d(e[g+h],c[f])},f.prototype.getRowColUp=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);return-1===f&&(f=0),0===g?new d(a,c[f]):new d(e[g-1],c[f])},f.prototype.getRowColPageUp=function(a,b){var c=this.getFocusableCols(),e=this.getFocusableRows(),f=c.indexOf(b),g=e.indexOf(a);-1===f&&(f=0);var h=this.bodyContainer.minRowsToRender();return 0>g-h?new d(e[0],c[f]):new d(e[g-h],c[f])},f}]),a.service("uiGridCellNavService",["gridUtil","uiGridConstants","uiGridCellNavConstants","$q","uiGridCellNavFactory","GridRowColumn","ScrollEvent",function(a,b,c,d,e,f,g){var h={initializeGrid:function(a){a.registerColumnBuilder(h.cellNavColumnBuilder),a.cellNav={},a.cellNav.lastRowCol=null,a.cellNav.focusedCells=[],h.defaultGridOptions(a.options);var b={events:{cellNav:{navigate:function(a,b){},viewPortKeyDown:function(a,b){},viewPortKeyPress:function(a,b){}}},methods:{cellNav:{scrollToFocus:function(b,c){return h.scrollToFocus(a,b,c)},getFocusedCell:function(){return a.cellNav.lastRowCol},getCurrentSelection:function(){return a.cellNav.focusedCells},rowColSelectIndex:function(b){for(var c=-1,d=0;d<a.cellNav.focusedCells.length;d++)if(a.cellNav.focusedCells[d].col.uid===b.col.uid&&a.cellNav.focusedCells[d].row.uid===b.row.uid){c=d;break}return c}}}};a.api.registerEventsFromObject(b.events),a.api.registerMethodsFromObject(b.methods)},defaultGridOptions:function(a){a.modifierKeysToMultiSelectCells=a.modifierKeysToMultiSelectCells===!0,a.keyDownOverrides=a.keyDownOverrides||[]},decorateRenderContainers:function(a){var b=a.hasRightContainer()?a.renderContainers.right:null,c=a.hasLeftContainer()?a.renderContainers.left:null;null!==c&&(a.renderContainers.left.cellNav=new e(a.renderContainers.body,c,b,a.renderContainers.body)),null!==b&&(a.renderContainers.right.cellNav=new e(a.renderContainers.body,b,a.renderContainers.body,c)),a.renderContainers.body.cellNav=new e(a.renderContainers.body,a.renderContainers.body,c,b)},getDirection:function(a){return a.keyCode===b.keymap.LEFT||a.keyCode===b.keymap.TAB&&a.shiftKey?c.direction.LEFT:a.keyCode===b.keymap.RIGHT||a.keyCode===b.keymap.TAB?c.direction.RIGHT:a.keyCode===b.keymap.UP||a.keyCode===b.keymap.ENTER&&a.shiftKey?c.direction.UP:a.keyCode===b.keymap.PG_UP?c.direction.PG_UP:a.keyCode===b.keymap.DOWN||a.keyCode===b.keymap.ENTER&&!a.ctrlKey&&!a.altKey?c.direction.DOWN:a.keyCode===b.keymap.PG_DOWN?c.direction.PG_DOWN:null},cellNavColumnBuilder:function(a,b,c){var e=[];return a.allowCellFocus=void 0===a.allowCellFocus?!0:a.allowCellFocus,d.all(e)},scrollToFocus:function(a,b,c){var d=null,e=null;return"undefined"!=typeof b&&null!==b&&(d=a.getRow(b)),"undefined"!=typeof c&&null!==c&&(e=a.getColumn(c.name?c.name:c.field)),a.api.core.scrollToIfNecessary(d,e).then(function(){var b={row:d,col:e};null!==d&&null!==e&&a.cellNav.broadcastCellNav(b)})},getLeftWidth:function(a,b){var c=0;if(!b)return c;var d=a.renderContainers.body.visibleColumnCache.indexOf(b);a.renderContainers.body.visibleColumnCache.forEach(function(a,b){d>b&&(c+=a.drawnWidth)});var e=0===d?0:(d+1)/a.renderContainers.body.visibleColumnCache.length;return c+=b.drawnWidth*e}};return h}]),a.directive("uiGridCellnav",["gridUtil","uiGridCellNavService","uiGridCellNavConstants","uiGridConstants","GridRowColumn","$timeout","$compile",function(a,b,c,d,e,f,g){return{replace:!0,priority:-150,require:"^uiGrid",scope:!1,controller:function(){},compile:function(){return{pre:function(a,f,g,h){var i=a,j=h.grid;b.initializeGrid(j),h.cellNav={},h.cellNav.makeRowCol=function(a){return a instanceof e||(a=new e(a.row,a.col)),a},h.cellNav.getActiveCell=function(){var a=f[0].getElementsByClassName("ui-grid-cell-focus");return a.length>0?a[0]:void 0},h.cellNav.broadcastCellNav=j.cellNav.broadcastCellNav=function(a,b,d){b=!(void 0===b||!b),a=h.cellNav.makeRowCol(a),h.cellNav.broadcastFocus(a,b,d),i.$broadcast(c.CELL_NAV_EVENT,a,b,d)},h.cellNav.clearFocus=j.cellNav.clearFocus=function(){j.cellNav.focusedCells=[],i.$broadcast(c.CELL_NAV_EVENT)},h.cellNav.broadcastFocus=function(a,b,c){b=!(void 0===b||!b),a=h.cellNav.makeRowCol(a);var d=a.row,f=a.col,g=h.grid.api.cellNav.rowColSelectIndex(a);if(null===j.cellNav.lastRowCol||-1===g){var i=new e(d,f);(null===j.cellNav.lastRowCol||j.cellNav.lastRowCol.row!==i.row||j.cellNav.lastRowCol.col!==i.col)&&(j.api.cellNav.raise.navigate(i,j.cellNav.lastRowCol,c),j.cellNav.lastRowCol=i),h.grid.options.modifierKeysToMultiSelectCells&&b?j.cellNav.focusedCells.push(a):j.cellNav.focusedCells=[a]}else j.options.modifierKeysToMultiSelectCells&&b&&g>=0&&j.cellNav.focusedCells.splice(g,1)},h.cellNav.handleKeyDown=function(a){var e=b.getDirection(a);if(null===e)return null;var f="body";a.uiGridTargetRenderContainerId&&(f=a.uiGridTargetRenderContainerId);var g=h.grid.api.cellNav.getFocusedCell();if(g){var i=h.grid.renderContainers[f].cellNav.getNextRowCol(e,g.row,g.col),k=h.grid.renderContainers[f].cellNav.getFocusableCols(),l=h.grid.api.cellNav.rowColSelectIndex(i);return e===c.direction.LEFT&&i.col===k[k.length-1]&&i.row===g.row&&a.keyCode===d.keymap.TAB&&a.shiftKey?(j.cellNav.focusedCells.splice(l,1),h.cellNav.clearFocus(),!0):e!==c.direction.RIGHT||i.col!==k[0]||i.row!==g.row||a.keyCode!==d.keymap.TAB||a.shiftKey?(j.scrollToIfNecessary(i.row,i.col).then(function(){h.cellNav.broadcastCellNav(i,null,a)}),a.stopPropagation(),a.preventDefault(),!1):(j.cellNav.focusedCells.splice(l,1),h.cellNav.clearFocus(),!0)}}},post:function(a,b,d,e){function f(){var d='<div id="'+h.id+'-aria-speakable" class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" aria-live="assertive" role="region" aria-atomic="true" aria-hidden="false" aria-relevant="additions" >&nbsp;</div>',e=g(d)(a);b.prepend(e),a.$on(c.CELL_NAV_EVENT,function(a,b,c,d){function f(a){a!==e.text()&&(e[0].style.clip="rect(0px,0px,0px,0px)",e[0].innerHTML="",e[0].style.visibility="hidden",e[0].style.visibility="visible",""!==a&&(e[0].style.clip="auto",e[0].appendChild(document.createTextNode(a+" ")),e[0].style.visibility="hidden",e[0].style.visibility="visible"))}if(!d||"focus"!==d.type){for(var g=[],i=h.api.cellNav.getCurrentSelection(),j=0;j<i.length;j++)g.push(h.getCellDisplayValue(i[j].row,i[j].col));var k=g.toString();f(k)}})}var h=e.grid;f()}}}}}]),a.directive("uiGridRenderContainer",["$timeout","$document","gridUtil","uiGridConstants","uiGridCellNavService","$compile","uiGridCellNavConstants",function(a,b,c,d,e,f,g){return{replace:!0,priority:-99999,require:["^uiGrid","uiGridRenderContainer","?^uiGridCellnav"],scope:!1,compile:function(){return{post:function(b,d,h,i){var j=i[0],k=i[1],l=i[2];if(j.grid.api.cellNav){var m=k.containerId,n=j.grid;if(e.decorateRenderContainers(n),"body"===m){j.grid.options.modifierKeysToMultiSelectCells?d.attr("aria-multiselectable",!0):d.attr("aria-multiselectable",!1);var o=f('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="'+n.id+"-aria-speakable "+n.id+'-grid-container" aria-owns="'+n.id+'-grid-container"></div>')(b);d.append(o),o.on("focus",function(a){a.uiGridTargetRenderContainerId=m;var b=j.grid.api.cellNav.getFocusedCell();null===b&&(b=j.grid.renderContainers[m].cellNav.getNextRowCol(g.direction.DOWN,null,null),b.row&&b.col&&j.cellNav.broadcastCellNav(b))}),l.setAriaActivedescendant=function(a){d.attr("aria-activedescendant",a)},l.removeAriaActivedescendant=function(a){d.attr("aria-activedescendant")===a&&d.attr("aria-activedescendant","")},j.focus=function(){c.focus.byElement(o[0])};var p=null;o.on("keydown",function(a){a.uiGridTargetRenderContainerId=m;var b=j.grid.api.cellNav.getFocusedCell(),c=j.grid.options.keyDownOverrides.some(function(b){return Object.keys(b).every(function(c){return b[c]===a[c]})}),d=c?null:j.cellNav.handleKeyDown(a);null===d&&(j.grid.api.cellNav.raise.viewPortKeyDown(a,b),p=b)}),o.on("keypress",function(b){p&&(a(function(){j.grid.api.cellNav.raise.viewPortKeyPress(b,p)},4),p=null)}),b.$on("$destroy",function(){o.off()})}}}}}}}]),a.directive("uiGridViewport",["$timeout","$document","gridUtil","uiGridConstants","uiGridCellNavService","uiGridCellNavConstants","$log","$compile",function(a,b,c,d,e,f,g,h){return{replace:!0,priority:-99999,require:["^uiGrid","^uiGridRenderContainer","?^uiGridCellnav"],scope:!1,compile:function(){return{pre:function(a,b,c,d){},post:function(a,b,c,d){var e=d[0],f=d[1];if(e.grid.api.cellNav){var g=f.containerId;if("body"===g){var h=e.grid;h.api.core.on.scrollBegin(a,function(a){var b=e.grid.api.cellNav.getFocusedCell();null!==b&&f.colContainer.containsColumn(b.col)&&e.cellNav.clearFocus()}),h.api.core.on.scrollEnd(a,function(a){var b=e.grid.api.cellNav.getFocusedCell();null!==b&&f.colContainer.containsColumn(b.col)&&e.cellNav.broadcastCellNav(b)}),h.api.cellNav.on.navigate(a,function(){e.focus()})}}}}}}}]),a.directive("uiGridCell",["$timeout","$document","uiGridCellNavService","gridUtil","uiGridCellNavConstants","uiGridConstants","GridRowColumn",function(a,b,c,d,e,f,g){return{priority:-150,restrict:"A",require:["^uiGrid","?^uiGridCellnav"],scope:!1,link:function(b,c,d,h){function i(a){a.preventDefault()}function j(){var a=o.cellNav.focusedCells.some(function(a,c){return a.row===b.row&&a.col===b.col});a?k():l()}function k(){if(!b.focused){var a=c.find("div");a.addClass("ui-grid-cell-focus"),c.attr("aria-selected",!0),n.setAriaActivedescendant(c.attr("id")),b.focused=!0}}function l(){if(b.focused){var a=c.find("div");a.removeClass("ui-grid-cell-focus"),c.attr("aria-selected",!1),n.removeAriaActivedescendant(c.attr("id")),b.focused=!1}}var m=h[0],n=h[1];if(m.grid.api.cellNav&&b.col.colDef.allowCellFocus){var o=m.grid;b.focused=!1,c.attr("tabindex",-1),c.find("div").on("click",function(a){m.cellNav.broadcastCellNav(new g(b.row,b.col),a.ctrlKey||a.metaKey,a),a.stopPropagation(),b.$apply()}),c.on("mousedown",i),m.grid.api.edit&&(m.grid.api.edit.on.beginCellEdit(b,function(){c.off("mousedown",i)}),m.grid.api.edit.on.afterCellEdit(b,function(){c.on("mousedown",i)}),m.grid.api.edit.on.cancelCellEdit(b,function(){c.on("mousedown",i)})),j(),c.on("focus",function(a){m.cellNav.broadcastCellNav(new g(b.row,b.col),!1,a),a.stopPropagation(),b.$apply()}),b.$on(e.CELL_NAV_EVENT,j);var p=m.grid.registerDataChangeCallback(function(b){l(),a(j)},[f.dataChange.ROW]);b.$on("$destroy",function(){p(),c.find("div").off(),c.off()})}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.edit",["ui.grid"]);a.constant("uiGridEditConstants",{EDITABLE_CELL_TEMPLATE:/EDITABLE_CELL_TEMPLATE/g,EDITABLE_CELL_DIRECTIVE:/editable_cell_directive/g,events:{BEGIN_CELL_EDIT:"uiGridEventBeginCellEdit",END_CELL_EDIT:"uiGridEventEndCellEdit",CANCEL_CELL_EDIT:"uiGridEventCancelCellEdit"}}),a.service("uiGridEditService",["$q","uiGridConstants","gridUtil",function(a,b,c){var d={initializeGrid:function(a){d.defaultGridOptions(a.options),a.registerColumnBuilder(d.editColumnBuilder),a.edit={};var b={events:{edit:{afterCellEdit:function(a,b,c,d){},beginCellEdit:function(a,b,c){},cancelCellEdit:function(a,b){}}},methods:{edit:{}}};a.api.registerEventsFromObject(b.events)},defaultGridOptions:function(a){a.cellEditableCondition=void 0===a.cellEditableCondition?!0:a.cellEditableCondition,a.enableCellEditOnFocus=void 0===a.enableCellEditOnFocus?!1:a.enableCellEditOnFocus},editColumnBuilder:function(b,d,e){var f=[];return b.enableCellEdit=void 0===b.enableCellEdit?void 0===e.enableCellEdit?"object"!==b.type:e.enableCellEdit:b.enableCellEdit,b.cellEditableCondition=void 0===b.cellEditableCondition?e.cellEditableCondition:b.cellEditableCondition,b.enableCellEdit&&(b.editableCellTemplate=b.editableCellTemplate||e.editableCellTemplate||"ui-grid/cellEditor",f.push(c.getTemplate(b.editableCellTemplate).then(function(a){d.editableCellTemplate=a},function(a){throw new Error("Couldn't fetch/use colDef.editableCellTemplate '"+b.editableCellTemplate+"'")}))),b.enableCellEditOnFocus=void 0===b.enableCellEditOnFocus?e.enableCellEditOnFocus:b.enableCellEditOnFocus,a.all(f)},isStartEditKey:function(a){return a.metaKey||a.keyCode===b.keymap.ESC||a.keyCode===b.keymap.SHIFT||a.keyCode===b.keymap.CTRL||a.keyCode===b.keymap.ALT||a.keyCode===b.keymap.WIN||a.keyCode===b.keymap.CAPSLOCK||a.keyCode===b.keymap.LEFT||a.keyCode===b.keymap.TAB&&a.shiftKey||a.keyCode===b.keymap.RIGHT||a.keyCode===b.keymap.TAB||a.keyCode===b.keymap.UP||a.keyCode===b.keymap.ENTER&&a.shiftKey||a.keyCode===b.keymap.DOWN||a.keyCode===b.keymap.ENTER?!1:!0}};return d}]),a.directive("uiGridEdit",["gridUtil","uiGridEditService",function(a,b){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){b.initializeGrid(e.grid)},post:function(a,b,c,d){}}}}}]),a.directive("uiGridViewport",["uiGridEditConstants",function(a){return{replace:!0,priority:-99998,require:["^uiGrid","^uiGridRenderContainer"],scope:!1,compile:function(){return{post:function(b,c,d,e){var f=e[0];if(f.grid.api.edit&&f.grid.api.cellNav){var g=e[1].containerId;"body"===g&&(b.$on(a.events.CANCEL_CELL_EDIT,function(){f.focus()}),b.$on(a.events.END_CELL_EDIT,function(){f.focus()}))}}}}}}]),a.directive("uiGridCell",["$compile","$injector","$timeout","uiGridConstants","uiGridEditConstants","gridUtil","$parse","uiGridEditService","$rootScope","$q",function(a,b,c,d,e,f,g,h,i,j){var k=500;if(b.has("uiGridCellNavService")){b.get("uiGridCellNavService")}return{priority:-100,restrict:"A",scope:!1,require:"?^uiGrid",link:function(b,l,m,n){function o(){l.on("dblclick",u),l.on("touchstart",p),n&&n.grid.api.cellNav&&(G=n.grid.api.cellNav.on.viewPortKeyDown(b,function(a,c){null!==c&&(c.row!==b.row||c.col!==b.col||b.col.colDef.enableCellEditOnFocus||s(a))}),F=n.grid.api.cellNav.on.navigate(b,function(a,d,e){b.col.colDef.enableCellEditOnFocus&&(d&&a.row===d.row&&a.col===d.col||a.row!==b.row||a.col!==b.col||c(function(){u(e)}))})),b.beginEditEventsWired=!0}function p(a){"undefined"!=typeof a.originalEvent&&void 0!==a.originalEvent&&(a=a.originalEvent),l.on("touchend",q),C=c(function(){},k),C.then(function(){setTimeout(u,0),l.off("touchend",q)})}function q(a){c.cancel(C),l.off("touchend",q)}function r(){l.off("dblclick",u),l.off("keydown",s),l.off("touchstart",p),F(),G(),b.beginEditEventsWired=!1}function s(a){h.isStartEditKey(a)&&u(a)}function t(a,c){return!c.isSaving&&(angular.isFunction(a.colDef.cellEditableCondition)?a.colDef.cellEditableCondition(b):a.colDef.cellEditableCondition)}function u(a){b.grid.api.core.scrollToIfNecessary(b.row,b.col).then(function(){v(a)})}function v(h){if(!E&&t(b.col,b.row)){var k=b.row.getQualifiedColField(b.col);b.col.colDef.editModelField&&(k=f.preEval("row.entity."+b.col.colDef.editModelField)),B=g(k),A=B(b),z=b.col.editableCellTemplate,z=z.replace(d.MODEL_COL_FIELD,k),z=z.replace(d.COL_FIELD,"grid.getCellValue(row, col)");var m=b.col.colDef.editDropdownFilter?"|"+b.col.colDef.editDropdownFilter:"";z=z.replace(d.CUSTOM_FILTERS,m);var n="text";switch(b.col.colDef.type){case"boolean":n="checkbox";break;case"number":n="number";break;case"date":n="date"}z=z.replace("INPUT_TYPE",n);var o=b.col.colDef.editDropdownOptionsFunction;if(o)j.when(o(b.row.entity,b.col.colDef)).then(function(a){b.editDropdownOptionsArray=a});else{var p=b.col.colDef.editDropdownRowEntityOptionsArrayPath;p?b.editDropdownOptionsArray=y(b.row.entity,p):b.editDropdownOptionsArray=b.col.colDef.editDropdownOptionsArray}b.editDropdownIdLabel=b.col.colDef.editDropdownIdLabel?b.col.colDef.editDropdownIdLabel:"id",b.editDropdownValueLabel=b.col.colDef.editDropdownValueLabel?b.col.colDef.editDropdownValueLabel:"value";var q=function(){E=!0,r();var c=angular.element(z);l.append(c),D=b.$new(),a(c)(D);var d=angular.element(l.children()[0]);d.addClass("ui-grid-cell-contents-hidden")};i.$$phase?q():b.$apply(q);var s=b.col.grid.api.core.on.scrollBegin(b,function(){b.grid.disableScrolling||(w(),b.grid.api.edit.raise.afterCellEdit(b.row.entity,b.col.colDef,B(b),A),s(),u(),v())}),u=b.$on(e.events.END_CELL_EDIT,function(){w(),b.grid.api.edit.raise.afterCellEdit(b.row.entity,b.col.colDef,B(b),A),u(),s(),v()}),v=b.$on(e.events.CANCEL_CELL_EDIT,function(){x(),v(),s(),u()});b.$broadcast(e.events.BEGIN_CELL_EDIT,h),c(function(){b.grid.api.edit.raise.beginCellEdit(b.row.entity,b.col.colDef,h)})}}function w(){if(b.grid.disableScrolling=!1,E){n&&n.grid.api.cellNav&&n.focus();var a=angular.element(l.children()[0]);D.$destroy();for(var c=l.children(),e=1;e<c.length;e++)angular.element(c[e]).remove();a.removeClass("ui-grid-cell-contents-hidden"),E=!1,o(),b.grid.api.core.notifyDataChange(d.dataChange.EDIT)}}function x(){b.grid.disableScrolling=!1,E&&(B.assign(b,A),b.$apply(),b.grid.api.edit.raise.cancelCellEdit(b.row.entity,b.col.colDef),w())}function y(a,b){b=b.replace(/\[(\w+)\]/g,".$1"),b=b.replace(/^\./,"");for(var c=b.split(".");c.length;){var d=c.shift();if(!(d in a))return;a=a[d]}return a}var z,A,B,C,D,E=!1;if(b.col.colDef.enableCellEdit){var F=function(){},G=function(){},H=function(){b.col.colDef.enableCellEdit&&b.row.enableCellEdit!==!1?b.beginEditEventsWired||o():b.beginEditEventsWired&&r()};H();var I=b.$watch("row",function(a,b){a!==b&&H()});b.$on("$destroy",function(){I(),l.off()})}}}}]),a.directive("uiGridEditor",["gridUtil","uiGridConstants","uiGridEditConstants","$timeout","uiGridEditService",function(a,b,c,d,e){return{scope:!0,require:["?^uiGrid","?^uiGridRenderContainer","ngModel"],compile:function(){return{pre:function(a,b,c){},post:function(a,f,g,h){var i,j,k;h[0]&&(i=h[0]),h[1]&&(j=h[1]),h[2]&&(k=h[2]),a.$on(c.events.BEGIN_CELL_EDIT,function(b,c){if(d(function(){if(f[0].focus(),!f[0].select||!a.col.colDef.enableCellEditOnFocus&&i&&i.grid.api.cellNav)try{f[0].setSelectionRange(f[0].value.length,f[0].value.length)}catch(b){}else f[0].select()}),i&&i.grid.api.cellNav)var g=i.grid.api.cellNav.on.viewPortKeyPress(a,function(a,b){e.isStartEditKey(a)&&(k.$setViewValue(String.fromCharCode("number"==typeof a.which?a.which:a.keyCode),a),k.$render()),g()});f.on("mousedown",function(b){"checkbox"===f[0].type&&(f.off("blur",a.stopEdit),d(function(){f.focus(),f.on("blur",a.stopEdit)}))}),f.on("blur",a.stopEdit)}),a.deepEdit=!1,a.stopEdit=function(b){a.inputForm&&!a.inputForm.$valid?(b.stopPropagation(),a.$emit(c.events.CANCEL_CELL_EDIT)):a.$emit(c.events.END_CELL_EDIT),a.deepEdit=!1},f.on("click",function(b){"checkbox"!==f[0].type&&(a.deepEdit=!0,d(function(){a.grid.disableScrolling=!0}))}),f.on("keydown",function(d){switch(d.keyCode){case b.keymap.ESC:d.stopPropagation(),a.$emit(c.events.CANCEL_CELL_EDIT)}if(!a.deepEdit||d.keyCode!==b.keymap.LEFT&&d.keyCode!==b.keymap.RIGHT&&d.keyCode!==b.keymap.UP&&d.keyCode!==b.keymap.DOWN)if(i&&i.grid.api.cellNav)d.uiGridTargetRenderContainerId=j.containerId,null!==i.cellNav.handleKeyDown(d)&&a.stopEdit(d);else switch(d.keyCode){case b.keymap.ENTER:case b.keymap.TAB:d.stopPropagation(),d.preventDefault(),a.stopEdit(d)}else d.stopPropagation();return!0}),a.$on("$destroy",function(){f.off()})}}}}}]),a.directive("uiGridEditor",["$filter",function(a){function b(a){if("undefined"==typeof a||""===a)return null;var b=a.split("-");if(3!==b.length)return null;var c=parseInt(b[0],10),d=parseInt(b[1],10),e=parseInt(b[2],10);return 1>d||1>c||1>e?null:new Date(c,d-1,e)}return{priority:-100,require:"?ngModel",link:function(c,d,e,f){2===angular.version.minor&&e.type&&"date"===e.type&&f&&(f.$formatters.push(function(b){return f.$setValidity(null,!b||!isNaN(b.getTime())),a("date")(b,"yyyy-MM-dd")}),f.$parsers.push(function(a){if(a&&a.length>0){var c=b(a);return f.$setValidity(null,c&&!isNaN(c.getTime())),c}return f.$setValidity(null,!0),null}))}}}]),a.directive("uiGridEditDropdown",["uiGridConstants","uiGridEditConstants","$timeout",function(a,b,c){return{require:["?^uiGrid","?^uiGridRenderContainer"],scope:!0,compile:function(){return{pre:function(a,b,c){},post:function(d,e,f,g){var h=g[0],i=g[1];d.$on(b.events.BEGIN_CELL_EDIT,function(){c(function(){e[0].focus()}),e[0].style.width=e[0].parentElement.offsetWidth-1+"px",e.on("blur",function(a){d.stopEdit(a)})}),d.stopEdit=function(a){d.$emit(b.events.END_CELL_EDIT)},e.on("keydown",function(c){switch(c.keyCode){case a.keymap.ESC:c.stopPropagation(),d.$emit(b.events.CANCEL_CELL_EDIT)}if(h&&h.grid.api.cellNav)c.uiGridTargetRenderContainerId=i.containerId,null!==h.cellNav.handleKeyDown(c)&&d.stopEdit(c);else switch(c.keyCode){case a.keymap.ENTER:case a.keymap.TAB:c.stopPropagation(),c.preventDefault(),d.stopEdit(c)}return!0}),d.$on("$destroy",function(){e.off()})}}}}}]),a.directive("uiGridEditFileChooser",["gridUtil","uiGridConstants","uiGridEditConstants","$timeout",function(a,b,c,d){return{scope:!0,require:["?^uiGrid","?^uiGridRenderContainer"],compile:function(){return{pre:function(a,b,c){},post:function(b,d,e,f){var g,h;f[0]&&(g=f[0]),f[1]&&(h=f[1]);var i=(g.grid,function(d){var e=d.srcElement||d.target;e&&e.files&&e.files.length>0?("function"==typeof b.col.colDef.editFileChooserCallback?b.col.colDef.editFileChooserCallback(b.row,b.col,e.files):a.logError("You need to set colDef.editFileChooserCallback to use the file chooser"),e.form.reset(),b.$emit(c.events.END_CELL_EDIT)):b.$emit(c.events.CANCEL_CELL_EDIT)});d[0].addEventListener("change",i,!1),b.$on(c.events.BEGIN_CELL_EDIT,function(){d[0].focus(),d[0].select(),d.on("blur",function(a){b.$emit(c.events.END_CELL_EDIT)})}),b.$on("$destroy",function(){d.off(),d[0].removeEventListener("change",i,!1)})}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.emptyBaseLayer",["ui.grid"]);a.service("uiGridBaseLayerService",["gridUtil","$compile",function(a,b){var c={initializeGrid:function(a,b){a.baseLayer={emptyRows:[]},a.options.enableEmptyGridBaseLayer!==!1&&(a.options.enableEmptyGridBaseLayer=!b)},setNumberOfEmptyRows:function(a,b){var c=b.options.rowHeight,d=Math.ceil(a/c);if(d>0){b.baseLayer.emptyRows=[];for(var e=0;d>e;e++)b.baseLayer.emptyRows.push({})}}};return c}]),a.directive("uiGridEmptyBaseLayer",["gridUtil","uiGridBaseLayerService","$parse",function(a,b,c){return{require:"^uiGrid",scope:!1,compile:function(a,d){return{pre:function(a,d,e,f){var g=c(e.uiGridEmptyBaseLayer)(a)===!1;b.initializeGrid(f.grid,g)},post:function(a,c,d,e){function f(){var a=h.getViewportHeight();return a!==i?(i=a,!0):!1}function g(a){return".grid"+e.grid.id+" .ui-grid-render-container .ui-grid-empty-base-layer-container.ui-grid-canvas { height: "+a+"px; }"}if(e.grid.options.enableEmptyGridBaseLayer){var h=e.grid.renderContainers.body,i=h.getViewportHeight();e.grid.registerStyleComputation({func:function(){return f()&&b.setNumberOfEmptyRows(i,e.grid),g(i)}})}}}}}}]),a.directive("uiGridViewport",["$compile","gridUtil","$templateCache",function(a,b,c){return{priority:-200,scope:!1,compile:function(a,b){var d=c.get("ui-grid/emptyBaseLayerContainer");return a.prepend(d),{pre:function(a,b,c,d){},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.expandable",["ui.grid"]);a.service("uiGridExpandableService",["gridUtil","$compile",function(a,b){var c={initializeGrid:function(b){b.expandable={},b.expandable.expandedAll=!1,b.options.enableExpandable=b.options.enableExpandable!==!1,b.options.expandableRowHeight=b.options.expandableRowHeight||150,b.options.expandableRowHeaderWidth=b.options.expandableRowHeaderWidth||40,b.options.enableExpandable&&!b.options.expandableRowTemplate&&(a.logError("You have not set the expandableRowTemplate, disabling expandable module"),b.options.enableExpandable=!1);var d={events:{expandable:{rowExpandedBeforeStateChanged:function(a,b){},rowExpandedStateChanged:function(a,b){}}},methods:{expandable:{toggleRowExpansion:function(a){var d=b.getRow(a);null!==d&&c.toggleRowExpansion(b,d)},expandAllRows:function(){c.expandAllRows(b)},collapseAllRows:function(){c.collapseAllRows(b)},toggleAllRows:function(){c.toggleAllRows(b)},expandRow:function(a){var d=b.getRow(a);null===d||d.isExpanded||c.toggleRowExpansion(b,d)},collapseRow:function(a){var d=b.getRow(a);null!==d&&d.isExpanded&&c.toggleRowExpansion(b,d)},getExpandedRows:function(){
+return c.getExpandedRows(b).map(function(a){return a.entity})}}}};b.api.registerEventsFromObject(d.events),b.api.registerMethodsFromObject(d.methods)},toggleRowExpansion:function(a,b){a.api.expandable.raise.rowExpandedBeforeStateChanged(b),b.isExpanded=!b.isExpanded,angular.isUndefined(b.expandedRowHeight)&&(b.expandedRowHeight=a.options.expandableRowHeight),b.isExpanded?b.height=b.grid.options.rowHeight+b.expandedRowHeight:(b.height=b.grid.options.rowHeight,a.expandable.expandedAll=!1),a.api.expandable.raise.rowExpandedStateChanged(b)},expandAllRows:function(a,b){a.renderContainers.body.visibleRowCache.forEach(function(b){b.isExpanded||c.toggleRowExpansion(a,b)}),a.expandable.expandedAll=!0,a.queueGridRefresh()},collapseAllRows:function(a){a.renderContainers.body.visibleRowCache.forEach(function(b){b.isExpanded&&c.toggleRowExpansion(a,b)}),a.expandable.expandedAll=!1,a.queueGridRefresh()},toggleAllRows:function(a){a.expandable.expandedAll?c.collapseAllRows(a):c.expandAllRows(a)},getExpandedRows:function(a){return a.rows.filter(function(a){return a.isExpanded})}};return c}]),a.directive("uiGridExpandable",["uiGridExpandableService","$templateCache",function(a,b){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(c,d,e,f){if(a.initializeGrid(f.grid),f.grid.options.enableExpandable&&f.grid.options.enableExpandableRowHeader!==!1){var g={name:"expandableButtons",displayName:"",exporterSuppressExport:!0,enableColumnResizing:!1,enableColumnMenu:!1,width:f.grid.options.expandableRowHeaderWidth||40};g.cellTemplate=b.get("ui-grid/expandableRowHeader"),g.headerCellTemplate=b.get("ui-grid/expandableTopRowHeader"),f.grid.addRowHeaderColumn(g,-90)}},post:function(a,b,c,d){}}}}}]),a.directive("uiGrid",["uiGridExpandableService","$templateCache",function(a,b){return{replace:!0,priority:599,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,b,c,d){d.grid.api.core.on.renderingComplete(a,function(){a.row&&a.row.grid&&a.row.grid.options&&a.row.grid.options.enableExpandable&&(d.grid.parentRow=a.row)})},post:function(a,b,c,d){}}}}}]),a.directive("uiGridExpandableRow",["uiGridExpandableService","$timeout","$compile","uiGridConstants","gridUtil","$interval","$log",function(a,b,c,d,e,f,g){return{replace:!1,priority:0,scope:!1,compile:function(){return{pre:function(a,b,d,f){e.getTemplate(a.grid.options.expandableRowTemplate).then(function(d){if(a.grid.options.expandableRowScope){var e=a.grid.options.expandableRowScope;for(var f in e)e.hasOwnProperty(f)&&(a[f]=e[f])}var g=angular.element(d);b.append(g),g=c(g)(a),a.row.expandedRendered=!0})},post:function(a,b,c,d){a.$on("$destroy",function(){a.row.expandedRendered=!1})}}}}}]),a.directive("uiGridRow",["$compile","gridUtil","$templateCache",function(a,b,c){return{priority:-200,scope:!1,compile:function(a,b){return{pre:function(a,b,c,d){a.grid.options.enableExpandable&&(a.expandableRow={},a.expandableRow.shouldRenderExpand=function(){var b="body"===a.colContainer.name&&a.grid.options.enableExpandable!==!1&&a.row.isExpanded&&(!a.grid.isScrollingVertically||a.row.expandedRendered);return b},a.expandableRow.shouldRenderFiller=function(){var b=a.row.isExpanded&&("body"!==a.colContainer.name||a.grid.isScrollingVertically&&!a.row.expandedRendered);return b})},post:function(a,b,c,d){}}}}}]),a.directive("uiGridViewport",["$compile","gridUtil","$templateCache",function(a,b,c){return{priority:-200,scope:!1,compile:function(a,b){var d=angular.element(a.children().children()[0]),e=c.get("ui-grid/expandableScrollFiller"),f=c.get("ui-grid/expandableRow");return d.append(f),d.append(e),{pre:function(a,b,c,d){},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.exporter",["ui.grid"]);a.constant("uiGridExporterConstants",{featureName:"exporter",ALL:"all",VISIBLE:"visible",SELECTED:"selected",CSV_CONTENT:"CSV_CONTENT",BUTTON_LABEL:"BUTTON_LABEL",FILE_NAME:"FILE_NAME"}),a.service("uiGridExporterService",["$q","uiGridExporterConstants","gridUtil","$compile","$interval","i18nService",function(a,b,c,d,e,f){var g={delay:100,initializeGrid:function(a){a.exporter={},this.defaultGridOptions(a.options);var b={events:{exporter:{}},methods:{exporter:{csvExport:function(b,c){g.csvExport(a,b,c)},pdfExport:function(b,c){g.pdfExport(a,b,c)}}}};a.api.registerEventsFromObject(b.events),a.api.registerMethodsFromObject(b.methods),a.api.core.addToGridMenu?g.addToMenu(a):e(function(){a.api.core.addToGridMenu&&g.addToMenu(a)},this.delay,1)},defaultGridOptions:function(a){a.exporterSuppressMenu=a.exporterSuppressMenu===!0,a.exporterMenuLabel=a.exporterMenuLabel?a.exporterMenuLabel:"Export",a.exporterSuppressColumns=a.exporterSuppressColumns?a.exporterSuppressColumns:[],a.exporterCsvColumnSeparator=a.exporterCsvColumnSeparator?a.exporterCsvColumnSeparator:",",a.exporterCsvFilename=a.exporterCsvFilename?a.exporterCsvFilename:"download.csv",a.exporterPdfFilename=a.exporterPdfFilename?a.exporterPdfFilename:"download.pdf",a.exporterOlderExcelCompatibility=a.exporterOlderExcelCompatibility===!0,a.exporterIsExcelCompatible=a.exporterIsExcelCompatible===!0,a.exporterMenuItemOrder=a.exporterMenuItemOrder?a.exporterMenuItemOrder:200,a.exporterPdfDefaultStyle=a.exporterPdfDefaultStyle?a.exporterPdfDefaultStyle:{fontSize:11},a.exporterPdfTableStyle=a.exporterPdfTableStyle?a.exporterPdfTableStyle:{margin:[0,5,0,15]},a.exporterPdfTableHeaderStyle=a.exporterPdfTableHeaderStyle?a.exporterPdfTableHeaderStyle:{bold:!0,fontSize:12,color:"black"},a.exporterPdfHeader=a.exporterPdfHeader?a.exporterPdfHeader:null,a.exporterPdfFooter=a.exporterPdfFooter?a.exporterPdfFooter:null,a.exporterPdfOrientation=a.exporterPdfOrientation?a.exporterPdfOrientation:"landscape",a.exporterPdfPageSize=a.exporterPdfPageSize?a.exporterPdfPageSize:"A4",a.exporterPdfMaxGridWidth=a.exporterPdfMaxGridWidth?a.exporterPdfMaxGridWidth:720,a.exporterMenuAllData=void 0!==a.exporterMenuAllData?a.exporterMenuAllData:!0,a.exporterMenuVisibleData=void 0!==a.exporterMenuVisibleData?a.exporterMenuVisibleData:!0,a.exporterMenuSelectedData=void 0!==a.exporterMenuSelectedData?a.exporterMenuSelectedData:!0,a.exporterMenuCsv=void 0!==a.exporterMenuCsv?a.exporterMenuCsv:!0,a.exporterMenuPdf=void 0!==a.exporterMenuPdf?a.exporterMenuPdf:!0,a.exporterPdfCustomFormatter=a.exporterPdfCustomFormatter&&"function"==typeof a.exporterPdfCustomFormatter?a.exporterPdfCustomFormatter:function(a){return a},a.exporterHeaderFilterUseName=a.exporterHeaderFilterUseName===!0,a.exporterFieldCallback=a.exporterFieldCallback?a.exporterFieldCallback:function(a,b,c,d){return d},a.exporterAllDataFn=a.exporterAllDataFn?a.exporterAllDataFn:null,null==a.exporterAllDataFn&&a.exporterAllDataPromise&&(a.exporterAllDataFn=a.exporterAllDataPromise)},addToMenu:function(a){a.api.core.addToGridMenu(a,[{title:f.getSafeText("gridMenu.exporterAllAsCsv"),action:function(a){this.grid.api.exporter.csvExport(b.ALL,b.ALL)},shown:function(){return this.grid.options.exporterMenuCsv&&this.grid.options.exporterMenuAllData},order:a.options.exporterMenuItemOrder},{title:f.getSafeText("gridMenu.exporterVisibleAsCsv"),action:function(a){this.grid.api.exporter.csvExport(b.VISIBLE,b.VISIBLE)},shown:function(){return this.grid.options.exporterMenuCsv&&this.grid.options.exporterMenuVisibleData},order:a.options.exporterMenuItemOrder+1},{title:f.getSafeText("gridMenu.exporterSelectedAsCsv"),action:function(a){this.grid.api.exporter.csvExport(b.SELECTED,b.VISIBLE)},shown:function(){return this.grid.options.exporterMenuCsv&&this.grid.options.exporterMenuSelectedData&&this.grid.api.selection&&this.grid.api.selection.getSelectedRows().length>0},order:a.options.exporterMenuItemOrder+2},{title:f.getSafeText("gridMenu.exporterAllAsPdf"),action:function(a){this.grid.api.exporter.pdfExport(b.ALL,b.ALL)},shown:function(){return this.grid.options.exporterMenuPdf&&this.grid.options.exporterMenuAllData},order:a.options.exporterMenuItemOrder+3},{title:f.getSafeText("gridMenu.exporterVisibleAsPdf"),action:function(a){this.grid.api.exporter.pdfExport(b.VISIBLE,b.VISIBLE)},shown:function(){return this.grid.options.exporterMenuPdf&&this.grid.options.exporterMenuVisibleData},order:a.options.exporterMenuItemOrder+4},{title:f.getSafeText("gridMenu.exporterSelectedAsPdf"),action:function(a){this.grid.api.exporter.pdfExport(b.SELECTED,b.VISIBLE)},shown:function(){return this.grid.options.exporterMenuPdf&&this.grid.options.exporterMenuSelectedData&&this.grid.api.selection&&this.grid.api.selection.getSelectedRows().length>0},order:a.options.exporterMenuItemOrder+5}])},csvExport:function(a,b,c){var d=this;this.loadAllDataIfNeeded(a,b,c).then(function(){var e=a.options.showHeader?d.getColumnHeaders(a,c):[],f=d.getData(a,b,c),g=d.formatAsCsv(e,f,a.options.exporterCsvColumnSeparator);d.downloadFile(a.options.exporterCsvFilename,g,a.options.exporterCsvColumnSeparator,a.options.exporterOlderExcelCompatibility,a.options.exporterIsExcelCompatible)})},loadAllDataIfNeeded:function(c,d,e){if(d===b.ALL&&c.rows.length!==c.options.totalItems&&c.options.exporterAllDataFn)return c.options.exporterAllDataFn().then(function(){c.modifyRows(c.options.data)});var f=a.defer();return f.resolve(),f.promise},getColumnHeaders:function(a,c){var d,e=[];if(c===b.ALL)d=a.columns;else{var f=a.renderContainers.left?a.renderContainers.left.visibleColumnCache.filter(function(a){return a.visible}):[],g=a.renderContainers.body?a.renderContainers.body.visibleColumnCache.filter(function(a){return a.visible}):[],h=a.renderContainers.right?a.renderContainers.right.visibleColumnCache.filter(function(a){return a.visible}):[];d=f.concat(g,h)}return d.forEach(function(b,c){b.colDef.exporterSuppressExport!==!0&&-1===a.options.exporterSuppressColumns.indexOf(b.name)&&e.push({name:b.field,displayName:a.options.exporterHeaderFilter?a.options.exporterHeaderFilterUseName?a.options.exporterHeaderFilter(b.name):a.options.exporterHeaderFilter(b.displayName):b.displayName,width:b.drawnWidth?b.drawnWidth:b.width,align:"number"===b.colDef.type?"right":"left"})}),e},getData:function(a,d,e,f){var g,h,i=[];switch(d){case b.ALL:g=a.rows;break;case b.VISIBLE:g=a.getVisibleRows();break;case b.SELECTED:a.api.selection?g=a.api.selection.getSelectedGridRows():c.logError("selection feature must be enabled to allow selected rows to be exported")}if(e===b.ALL)h=a.columns;else{var j=a.renderContainers.left?a.renderContainers.left.visibleColumnCache.filter(function(a){return a.visible}):[],k=a.renderContainers.body?a.renderContainers.body.visibleColumnCache.filter(function(a){return a.visible}):[],l=a.renderContainers.right?a.renderContainers.right.visibleColumnCache.filter(function(a){return a.visible}):[];h=j.concat(k,l)}return g.forEach(function(c,d){if(c.exporterEnableExporting!==!1){var g=[];h.forEach(function(d,h){if((d.visible||e===b.ALL)&&d.colDef.exporterSuppressExport!==!0&&-1===a.options.exporterSuppressColumns.indexOf(d.name)){var i=f?a.getCellDisplayValue(c,d):a.getCellValue(c,d),j={value:a.options.exporterFieldCallback(a,c,d,i)};d.colDef.exporterPdfAlign&&(j.alignment=d.colDef.exporterPdfAlign),g.push(j)}}),i.push(g)}}),i},formatAsCsv:function(a,b,c){var d=this,e=a.map(function(a){return{value:a.displayName}}),f=e.length>0?d.formatRowAsCsv(this,c)(e)+"\n":"";return f+=b.map(this.formatRowAsCsv(this,c)).join("\n")},formatRowAsCsv:function(a,b){return function(c){return c.map(a.formatFieldAsCsv).join(b)}},formatFieldAsCsv:function(a){return null==a.value?"":"number"==typeof a.value?a.value:"boolean"==typeof a.value?a.value?"TRUE":"FALSE":"string"==typeof a.value?'"'+a.value.replace(/"/g,'""')+'"':JSON.stringify(a.value)},isIE:function(){var a=navigator.userAgent.search(/(?:Edge|MSIE|Trident\/.*; rv:)/),b=!1;return-1!==a&&(b=!0),b},downloadFile:function(a,b,c,d,e){var f,g=document,h=g.createElement("a"),i="application/octet-stream;charset=utf-8",j=this.isIE();if(e&&(b="sep="+c+"\r\n"+b),navigator.msSaveBlob)return navigator.msSaveOrOpenBlob(new Blob([d?"\ufeff":"",b],{type:i}),a);if(j){var k=g.createElement("iframe");return document.body.appendChild(k),k.contentWindow.document.open("text/html","replace"),k.contentWindow.document.write(b),k.contentWindow.document.close(),k.contentWindow.focus(),k.contentWindow.document.execCommand("SaveAs",!0,a),document.body.removeChild(k),!0}if("download"in h){var l=new Blob([d?"\ufeff":"",b],{type:i});f=URL.createObjectURL(l),h.setAttribute("download",a)}else f="data:"+i+","+encodeURIComponent(b),h.setAttribute("target","_blank");h.href=f,h.setAttribute("style","display:none;"),g.body.appendChild(h),setTimeout(function(){if(h.click)h.click();else if(document.createEvent){var a=document.createEvent("MouseEvents");a.initEvent("click",!0,!0),h.dispatchEvent(a)}g.body.removeChild(h)},this.delay)},pdfExport:function(a,b,c){var d=this;this.loadAllDataIfNeeded(a,b,c).then(function(){var e=d.getColumnHeaders(a,c),f=d.getData(a,b,c),g=d.prepareAsPdf(a,e,f);d.isIE()||-1!==navigator.appVersion.indexOf("Edge")?d.downloadPDF(a.options.exporterPdfFilename,g):pdfMake.createPdf(g).open()})},downloadPDF:function(a,b){var c,d=document;d.createElement("a");c=this.isIE();var e,f=pdfMake.createPdf(b);f.getBuffer(function(b){if(e=new Blob([b]),navigator.msSaveBlob)return navigator.msSaveBlob(e,a);if(c){var f=d.createElement("iframe");return document.body.appendChild(f),f.contentWindow.document.open("text/html","replace"),f.contentWindow.document.write(e),f.contentWindow.document.close(),f.contentWindow.focus(),f.contentWindow.document.execCommand("SaveAs",!0,a),document.body.removeChild(f),!0}})},prepareAsPdf:function(a,b,c){var d=this.calculatePdfHeaderWidths(a,b),e=b.map(function(a){return{text:a.displayName,style:"tableHeader"}}),f=c.map(this.formatRowAsPdf(this)),g=[e].concat(f),h={pageOrientation:a.options.exporterPdfOrientation,pageSize:a.options.exporterPdfPageSize,content:[{style:"tableStyle",table:{headerRows:1,widths:d,body:g}}],styles:{tableStyle:a.options.exporterPdfTableStyle,tableHeader:a.options.exporterPdfTableHeaderStyle},defaultStyle:a.options.exporterPdfDefaultStyle};return a.options.exporterPdfLayout&&(h.layout=a.options.exporterPdfLayout),a.options.exporterPdfHeader&&(h.header=a.options.exporterPdfHeader),a.options.exporterPdfFooter&&(h.footer=a.options.exporterPdfFooter),a.options.exporterPdfCustomFormatter&&(h=a.options.exporterPdfCustomFormatter(h)),h},calculatePdfHeaderWidths:function(a,b){var c=0;b.forEach(function(a){"number"==typeof a.width&&(c+=a.width)});var d=0;b.forEach(function(a){if("*"===a.width&&(d+=100),"string"==typeof a.width&&a.width.match(/(\d)*%/)){var b=parseInt(a.width.match(/(\d)*%/)[0]);a.width=c*b/100,d+=a.width}});var e=c+d;return b.map(function(b){return"*"===b.width?b.width:b.width*a.options.exporterPdfMaxGridWidth/e})},formatRowAsPdf:function(a){return function(b){return b.map(a.formatFieldAsPdfString)}},formatFieldAsPdfString:function(a){var b;return b=null==a.value?"":"number"==typeof a.value?a.value.toString():"boolean"==typeof a.value?a.value?"TRUE":"FALSE":"string"==typeof a.value?a.value.replace(/"/g,'""'):JSON.stringify(a.value).replace(/^"/,"").replace(/"$/,""),a.alignment&&"string"==typeof a.alignment&&(b={text:b,alignment:a.alignment}),b}};return g}]),a.directive("uiGridExporter",["uiGridExporterConstants","uiGridExporterService","gridUtil","$compile",function(a,b,c,d){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(a,c,d,e){b.initializeGrid(e.grid),e.grid.exporter.$scope=a}}}])}(),function(){"use strict";var a=angular.module("ui.grid.grouping",["ui.grid","ui.grid.treeBase"]);a.constant("uiGridGroupingConstants",{featureName:"grouping",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),a.service("uiGridGroupingService",["$q","uiGridGroupingConstants","gridUtil","rowSorter","GridRow","gridClassFactory","i18nService","uiGridConstants","uiGridTreeBaseService",function(a,b,c,d,e,f,g,h,i){var j={initializeGrid:function(a,b){i.initializeGrid(a,b),a.grouping={},a.grouping.groupHeaderCache={},j.defaultGridOptions(a.options),a.registerRowsProcessor(j.groupRows,400),a.registerColumnBuilder(j.groupingColumnBuilder),a.registerColumnsProcessor(j.groupingColumnProcessor,400);var c={events:{grouping:{aggregationChanged:{},groupingChanged:{}}},methods:{grouping:{getGrouping:function(b){var c=j.getGrouping(a);return c.grouping.forEach(function(a){a.colName=a.col.name,delete a.col}),c.aggregations.forEach(function(a){a.colName=a.col.name,delete a.col}),c.aggregations=c.aggregations.filter(function(a){return!a.aggregation.source||"grouping"!==a.aggregation.source}),b&&(c.rowExpandedStates=j.getRowExpandedStates(a.grouping.groupingHeaderCache)),c},setGrouping:function(b){j.setGrouping(a,b)},groupColumn:function(b){var c=a.getColumn(b);j.groupColumn(a,c)},ungroupColumn:function(b){var c=a.getColumn(b);j.ungroupColumn(a,c)},clearGrouping:function(){j.clearGrouping(a)},aggregateColumn:function(b,c,d){var e=a.getColumn(b);j.aggregateColumn(a,e,c,d)}}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods),a.api.core.on.sortChanged(b,j.tidyPriorities)},defaultGridOptions:function(a){a.enableGrouping=a.enableGrouping!==!1,a.groupingShowCounts=a.groupingShowCounts!==!1,a.groupingNullLabel="undefined"==typeof a.groupingNullLabel?"Null":a.groupingNullLabel,a.enableGroupHeaderSelection=a.enableGroupHeaderSelection===!0},groupingColumnBuilder:function(a,d,e){if(a.enableGrouping!==!1){"undefined"==typeof d.grouping&&"undefined"!=typeof a.grouping?(d.grouping=angular.copy(a.grouping),"undefined"!=typeof d.grouping.groupPriority&&d.grouping.groupPriority>-1&&(d.treeAggregationFn=i.nativeAggregations()[b.aggregation.COUNT].aggregationFn,d.treeAggregationFinalizerFn=j.groupedFinalizerFn)):"undefined"==typeof d.grouping&&(d.grouping={}),"undefined"!=typeof d.grouping&&"undefined"!=typeof d.grouping.groupPriority&&d.grouping.groupPriority>=0&&(d.suppressRemoveSort=!0);var f={name:"ui.grid.grouping.group",title:g.get().grouping.group,icon:"ui-grid-icon-indent-right",shown:function(){return"undefined"==typeof this.context.col.grouping||"undefined"==typeof this.context.col.grouping.groupPriority||this.context.col.grouping.groupPriority<0},action:function(){j.groupColumn(this.context.col.grid,this.context.col)}},h={name:"ui.grid.grouping.ungroup",title:g.get().grouping.ungroup,icon:"ui-grid-icon-indent-left",shown:function(){return"undefined"!=typeof this.context.col.grouping&&"undefined"!=typeof this.context.col.grouping.groupPriority&&this.context.col.grouping.groupPriority>=0},action:function(){j.ungroupColumn(this.context.col.grid,this.context.col)}},k={name:"ui.grid.grouping.aggregateRemove",title:g.get().grouping.aggregate_remove,shown:function(){return"undefined"!=typeof this.context.col.treeAggregationFn},action:function(){j.aggregateColumn(this.context.col.grid,this.context.col,null)}},l=function(a,b){b=b||g.get().grouping["aggregate_"+a]||a;var e={name:"ui.grid.grouping.aggregate"+a,title:b,shown:function(){return"undefined"==typeof this.context.col.treeAggregation||"undefined"==typeof this.context.col.treeAggregation.type||this.context.col.treeAggregation.type!==a},action:function(){j.aggregateColumn(this.context.col.grid,this.context.col,a)}};c.arrayContainsObjectWithProperty(d.menuItems,"name","ui.grid.grouping.aggregate"+a)||d.menuItems.push(e)};d.colDef.groupingShowGroupingMenu!==!1&&(c.arrayContainsObjectWithProperty(d.menuItems,"name","ui.grid.grouping.group")||d.menuItems.push(f),c.arrayContainsObjectWithProperty(d.menuItems,"name","ui.grid.grouping.ungroup")||d.menuItems.push(h)),d.colDef.groupingShowAggregationMenu!==!1&&(angular.forEach(i.nativeAggregations(),function(a,b){l(b)}),angular.forEach(e.treeCustomAggregations,function(a,b){l(b,a.menuTitle)}),c.arrayContainsObjectWithProperty(d.menuItems,"name","ui.grid.grouping.aggregateRemove")||d.menuItems.push(k))}},groupingColumnProcessor:function(a,b){return a=j.moveGroupColumns(this,a,b)},groupedFinalizerFn:function(a){var b=this;"undefined"!=typeof a.groupVal?(a.rendered=a.groupVal,b.grid.options.groupingShowCounts&&"date"!==b.colDef.type&&"object"!==b.colDef.type&&(a.rendered+=" ("+a.value+")")):a.rendered=null},moveGroupColumns:function(a,b,c){return a.options.moveGroupColumns===!1?b:(b.forEach(function(a,b){a.groupingPosition=b}),b.sort(function(a,b){var c,d;return c=a.isRowHeader?a.headerPriority:"undefined"==typeof a.grouping||"undefined"==typeof a.grouping.groupPriority||a.grouping.groupPriority<0?null:a.grouping.groupPriority,d=b.isRowHeader?b.headerPriority:"undefined"==typeof b.grouping||"undefined"==typeof b.grouping.groupPriority||b.grouping.groupPriority<0?null:b.grouping.groupPriority,null!==c&&null===d?-1:null!==d&&null===c?1:null!==c&&null!==d?c-d:a.groupingPosition-b.groupingPosition}),b.forEach(function(a,b){delete a.groupingPosition}),b)},groupColumn:function(a,c){"undefined"==typeof c.grouping&&(c.grouping={});var d=j.getGrouping(a);c.grouping.groupPriority=d.grouping.length,c.previousSort=angular.copy(c.sort),c.sort?("undefined"==typeof c.sort.direction||null===c.sort.direction)&&(c.sort.direction=h.ASC):c.sort={direction:h.ASC},c.treeAggregation={type:b.aggregation.COUNT,source:"grouping"},c.treeAggregationFn=i.nativeAggregations()[b.aggregation.COUNT].aggregationFn,c.treeAggregationFinalizerFn=j.groupedFinalizerFn,a.api.grouping.raise.groupingChanged(c),a.api.core.raise.sortChanged(a,a.getColumnSorting()),a.queueGridRefresh()},ungroupColumn:function(a,b){"undefined"!=typeof b.grouping&&(delete b.grouping.groupPriority,delete b.treeAggregation,delete b.customTreeAggregationFinalizer,b.previousSort&&(b.sort=b.previousSort,delete b.previousSort),j.tidyPriorities(a),a.api.grouping.raise.groupingChanged(b),a.api.core.raise.sortChanged(a,a.getColumnSorting()),a.queueGridRefresh())},aggregateColumn:function(a,b,c){"undefined"!=typeof b.grouping&&"undefined"!=typeof b.grouping.groupPriority&&b.grouping.groupPriority>=0&&j.ungroupColumn(a,b);var d={};"undefined"!=typeof a.options.treeCustomAggregations[c]?d=a.options.treeCustomAggregations[c]:"undefined"!=typeof i.nativeAggregations()[c]&&(d=i.nativeAggregations()[c]),b.treeAggregation={type:c,label:g.get().aggregation[d.label]||d.label},b.treeAggregationFn=d.aggregationFn,b.treeAggregationFinalizerFn=d.finalizerFn,a.api.grouping.raise.aggregationChanged(b),a.queueGridRefresh()},setGrouping:function(a,b){"undefined"!=typeof b&&(j.clearGrouping(a),b.grouping&&b.grouping.length&&b.grouping.length>0&&b.grouping.forEach(function(b){var c=a.getColumn(b.colName);c&&j.groupColumn(a,c)}),b.aggregations&&b.aggregations.length&&b.aggregations.forEach(function(b){var c=a.getColumn(b.colName);c&&j.aggregateColumn(a,c,b.aggregation.type)}),b.rowExpandedStates&&j.applyRowExpandedStates(a.grouping.groupingHeaderCache,b.rowExpandedStates))},clearGrouping:function(a){var b=j.getGrouping(a);b.grouping.length>0&&b.grouping.forEach(function(b){b.col||(b.col=a.getColumn(b.colName)),j.ungroupColumn(a,b.col)}),b.aggregations.length>0&&b.aggregations.forEach(function(b){b.col||(b.col=a.getColumn(b.colName)),j.aggregateColumn(a,b.col,null)})},tidyPriorities:function(a){"undefined"!=typeof a&&"undefined"==typeof a.grid||"undefined"==typeof this.grid||(a=this.grid);var b=[],c=[];a.columns.forEach(function(a,d){"undefined"!=typeof a.grouping&&"undefined"!=typeof a.grouping.groupPriority&&a.grouping.groupPriority>=0?b.push(a):"undefined"!=typeof a.sort&&"undefined"!=typeof a.sort.priority&&a.sort.priority>=0&&c.push(a)}),b.sort(function(a,b){return a.grouping.groupPriority-b.grouping.groupPriority}),b.forEach(function(a,b){a.grouping.groupPriority=b,a.suppressRemoveSort=!0,"undefined"==typeof a.sort&&(a.sort={}),a.sort.priority=b});var d=b.length;c.sort(function(a,b){return a.sort.priority-b.sort.priority}),c.forEach(function(a,b){a.sort.priority=d,a.suppressRemoveSort=a.colDef.suppressRemoveSort,d++})},groupRows:function(a){if(0===a.length)return a;var b=this;b.grouping.oldGroupingHeaderCache=b.grouping.groupingHeaderCache||{},b.grouping.groupingHeaderCache={};for(var c=j.initialiseProcessingState(b),e=function(e,h){var i=b.getCellValue(g,e.col);e.initialised&&0===d.getSortFn(b,e.col,a)(i,e.currentValue)||(j.insertGroupHeader(b,a,f,c,h),f++)},f=0;f<a.length;f++){var g=a[f];g.visible&&c.forEach(e)}return delete b.grouping.oldGroupingHeaderCache,a},initialiseProcessingState:function(a){var b=[],c=j.getGrouping(a);return c.grouping.forEach(function(a,c){b.push({fieldName:a.field,col:a.col,initialised:!1,currentValue:null,currentRow:null})}),b},getGrouping:function(a){var b=[],c=[];return a.columns.forEach(function(a,d){a.grouping&&"undefined"!=typeof a.grouping.groupPriority&&a.grouping.groupPriority>=0&&b.push({field:a.field,col:a,groupPriority:a.grouping.groupPriority,grouping:a.grouping}),a.treeAggregation&&a.treeAggregation.type&&c.push({field:a.field,col:a,aggregation:a.treeAggregation})}),b.sort(function(a,b){return a.groupPriority-b.groupPriority}),b.forEach(function(a,b){a.grouping.groupPriority=b,a.groupPriority=b,delete a.grouping}),{grouping:b,aggregations:c}},insertGroupHeader:function(a,b,c,d,g){var h=(d[g].fieldName,d[g].col),i=a.getCellValue(b[c],h),k=i;("undefined"==typeof i||null===i)&&(k=a.options.groupingNullLabel);for(var l=function(a){return angular.isObject(a)?JSON.stringify(a):a},m=a.grouping.oldGroupingHeaderCache,n=0;g>n;n++)m&&m[l(d[n].currentValue)]&&(m=m[l(d[n].currentValue)].children);var o;for(m&&m[l(i)]?(o=m[l(i)].row,o.entity={}):(o=new e({},null,a),f.rowTemplateAssigner.call(a,o)),o.entity["$$"+d[g].col.uid]={groupVal:k},o.treeLevel=g,o.groupHeader=!0,o.internalRow=!0,o.enableCellEdit=!1,o.enableSelection=a.options.enableGroupHeaderSelection,d[g].initialised=!0,d[g].currentValue=i,d[g].currentRow=o,j.finaliseProcessingState(d,g+1),b.splice(c,0,o),m=a.grouping.groupingHeaderCache,n=0;g>n;n++)m=m[l(d[n].currentValue)].children;m[l(i)]={row:o,children:{}}},finaliseProcessingState:function(a,b){for(var c=b;c<a.length;c++)a[c].initialised=!1,a[c].currentRow=null,a[c].currentValue=null},getRowExpandedStates:function(a){if("undefined"==typeof a)return{};var b={};return angular.forEach(a,function(a,c){b[c]={state:a.row.treeNode.state},a.children?b[c].children=j.getRowExpandedStates(a.children):b[c].children={}}),b},applyRowExpandedStates:function(a,b){"undefined"!=typeof b&&angular.forEach(b,function(b,c){a[c]&&(a[c].row.treeNode.state=b.state,b.children&&a[c].children&&j.applyRowExpandedStates(a[c].children,b.children))})}};return j}]),a.directive("uiGridGrouping",["uiGridGroupingConstants","uiGridGroupingService","$templateCache",function(a,b,c){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){e.grid.options.enableGrouping!==!1&&b.initializeGrid(e.grid,a)},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.importer",["ui.grid"]);a.constant("uiGridImporterConstants",{featureName:"importer"}),a.service("uiGridImporterService",["$q","uiGridConstants","uiGridImporterConstants","gridUtil","$compile","$interval","i18nService","$window",function(a,b,c,d,e,f,g,h){var i={initializeGrid:function(a,b){b.importer={$scope:a},this.defaultGridOptions(b.options);var c={events:{importer:{}},methods:{importer:{importFile:function(a){i.importThisFile(b,a)}}}};b.api.registerEventsFromObject(c.events),b.api.registerMethodsFromObject(c.methods),b.options.enableImporter&&b.options.importerShowMenu&&(b.api.core.addToGridMenu?i.addToMenu(b):f(function(){b.api.core.addToGridMenu&&i.addToMenu(b)},100,1))},defaultGridOptions:function(a){a.enableImporter||void 0===a.enableImporter?h.hasOwnProperty("File")&&h.hasOwnProperty("FileReader")&&h.hasOwnProperty("FileList")&&h.hasOwnProperty("Blob")?a.enableImporter=!0:(d.logError("The File APIs are not fully supported in this browser, grid importer cannot be used."),a.enableImporter=!1):a.enableImporter=!1,a.importerProcessHeaders=a.importerProcessHeaders||i.processHeaders,a.importerHeaderFilter=a.importerHeaderFilter||function(a){return a},a.importerErrorCallback&&"function"==typeof a.importerErrorCallback||delete a.importerErrorCallback,a.enableImporter!==!0||a.importerDataAddCallback||(d.logError("You have not set an importerDataAddCallback, importer is disabled"),a.enableImporter=!1),a.importerShowMenu=a.importerShowMenu!==!1,a.importerObjectCallback=a.importerObjectCallback||function(a,b){return b}},addToMenu:function(a){a.api.core.addToGridMenu(a,[{title:g.getSafeText("gridMenu.importerTitle"),order:150},{templateUrl:"ui-grid/importerMenuItemContainer",action:function(b){this.grid.api.importer.importAFile(a)},order:151}])},importThisFile:function(a,b){if(!b)return void d.logError("No file object provided to importThisFile, should be impossible, aborting");var c=new FileReader;switch(b.type){case"application/json":c.onload=i.importJsonClosure(a);break;default:c.onload=i.importCsvClosure(a)}c.readAsText(b)},importJsonClosure:function(a){return function(b){var c,d=[],e=i.parseJson(a,b);null!==e&&(e.forEach(function(b,e){c=i.newObject(a),angular.extend(c,b),c=a.options.importerObjectCallback(a,c),d.push(c)}),i.addObjects(a,d))}},parseJson:function(a,b){var c;try{c=JSON.parse(b.target.result)}catch(d){return void i.alertError(a,"importer.invalidJson","File could not be processed, is it valid json? Content was: ",b.target.result)}return Array.isArray(c)?c:(i.alertError(a,"importer.jsonNotarray","Import failed, file is not an array, file was: ",b.target.result),[])},importCsvClosure:function(a){return function(b){var c=i.parseCsv(b);if(!c||c.length<1)return void i.alertError(a,"importer.invalidCsv","File could not be processed, is it valid csv? Content was: ",b.target.result);var d=i.createCsvObjects(a,c);return d&&0!==d.length?void i.addObjects(a,d):void i.alertError(a,"importer.noObjects","Objects were not able to be derived, content was: ",b.target.result)}},parseCsv:function(a){var b=a.target.result;return CSV.parse(b)},createCsvObjects:function(a,b){var c=a.options.importerProcessHeaders(a,b.shift());if(!c||0===c.length)return i.alertError(a,"importer.noHeaders","Column names could not be derived, content was: ",b),[];var d,e=[];return b.forEach(function(b,f){d=i.newObject(a),null!==b&&b.forEach(function(a,b){null!==c[b]&&(d[c[b]]=a)}),d=a.options.importerObjectCallback(a,d),e.push(d)}),e},processHeaders:function(a,b){var c=[];if(a.options.columnDefs&&0!==a.options.columnDefs.length){var d=i.flattenColumnDefs(a,a.options.columnDefs);return b.forEach(function(a,b){d[a]?c.push(d[a]):d[a.toLowerCase()]?c.push(d[a.toLowerCase()]):c.push(null)}),c}return b.forEach(function(a,b){c.push(a.replace(/[^0-9a-zA-Z\-_]/g,"_"))}),c},flattenColumnDefs:function(a,b){var c={};return b.forEach(function(b,d){b.name&&(c[b.name]=b.field||b.name,c[b.name.toLowerCase()]=b.field||b.name),b.field&&(c[b.field]=b.field||b.name,c[b.field.toLowerCase()]=b.field||b.name),b.displayName&&(c[b.displayName]=b.field||b.name,c[b.displayName.toLowerCase()]=b.field||b.name),b.displayName&&a.options.importerHeaderFilter&&(c[a.options.importerHeaderFilter(b.displayName)]=b.field||b.name,c[a.options.importerHeaderFilter(b.displayName).toLowerCase()]=b.field||b.name)}),c},addObjects:function(a,c,d){if(a.api.rowEdit){var e=a.registerDataChangeCallback(function(){a.api.rowEdit.setRowsDirty(c),e()},[b.dataChange.ROW]);a.importer.$scope.$on("$destroy",e)}a.importer.$scope.$apply(a.options.importerDataAddCallback(a,c))},newObject:function(a){return"undefined"!=typeof a.options&&"undefined"!=typeof a.options.importerNewObject?new a.options.importerNewObject:{}},alertError:function(a,b,c,e){a.options.importerErrorCallback?a.options.importerErrorCallback(a,b,c,e):(h.alert(g.getSafeText(b)),d.logError(c+e))}};return i}]),a.directive("uiGridImporter",["uiGridImporterConstants","uiGridImporterService","gridUtil","$compile",function(a,b,c,d){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(a,c,d,e){b.initializeGrid(a,e.grid);
+}}}]),a.directive("uiGridImporterMenuItem",["uiGridImporterConstants","uiGridImporterService","gridUtil","$compile",function(a,b,c,d){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,templateUrl:"ui-grid/importerMenuItem",link:function(a,d,e,f){var g=function(a){var c=a.srcElement||a.target;if(c&&c.files&&1===c.files.length){var d=c.files[0];b.importThisFile(i,d),c.form.reset()}},h=d[0].querySelectorAll(".ui-grid-importer-file-chooser"),i=f.grid;1!==h.length?c.logError("Found > 1 or < 1 file choosers within the menu item, error, cannot continue"):h[0].addEventListener("change",g,!1)}}}])}(),function(){"use strict";var a=angular.module("ui.grid.infiniteScroll",["ui.grid"]);a.service("uiGridInfiniteScrollService",["gridUtil","$compile","$timeout","uiGridConstants","ScrollEvent","$q",function(a,b,c,d,e,f){var g={initializeGrid:function(a,b){if(g.defaultGridOptions(a.options),a.options.enableInfiniteScroll){a.infiniteScroll={dataLoading:!1},g.setScrollDirections(a,a.options.infiniteScrollUp,a.options.infiniteScrollDown),a.api.core.on.scrollEnd(b,g.handleScroll);var c={events:{infiniteScroll:{needLoadMoreData:function(a,b){},needLoadMoreDataTop:function(a,b){}}},methods:{infiniteScroll:{dataLoaded:function(b,c){g.setScrollDirections(a,b,c);var d=g.adjustScroll(a).then(function(){a.infiniteScroll.dataLoading=!1});return d},resetScroll:function(b,c){g.setScrollDirections(a,b,c),g.adjustInfiniteScrollPosition(a,0)},saveScrollPercentage:function(){a.infiniteScroll.prevScrollTop=a.renderContainers.body.prevScrollTop,a.infiniteScroll.previousVisibleRows=a.getVisibleRowCount()},dataRemovedTop:function(b,c){g.dataRemovedTop(a,b,c)},dataRemovedBottom:function(b,c){g.dataRemovedBottom(a,b,c)},setScrollDirections:function(b,c){g.setScrollDirections(a,b,c)}}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods)}},defaultGridOptions:function(a){a.enableInfiniteScroll=a.enableInfiniteScroll!==!1,a.infiniteScrollRowsFromEnd=a.infiniteScrollRowsFromEnd||20,a.infiniteScrollUp=a.infiniteScrollUp===!0,a.infiniteScrollDown=a.infiniteScrollDown!==!1},setScrollDirections:function(a,b,c){a.infiniteScroll.scrollUp=b===!0,a.suppressParentScrollUp=b===!0,a.infiniteScroll.scrollDown=c!==!1,a.suppressParentScrollDown=c!==!1},handleScroll:function(a){if(!(a.grid.infiniteScroll&&a.grid.infiniteScroll.dataLoading||"ui.grid.adjustInfiniteScrollPosition"===a.source)&&a.y)if(0===a.y.percentage)a.grid.scrollDirection=d.scrollDirection.UP,g.loadData(a.grid);else if(1===a.y.percentage)a.grid.scrollDirection=d.scrollDirection.DOWN,g.loadData(a.grid);else{var b,c=a.grid.options.infiniteScrollRowsFromEnd/a.grid.renderContainers.body.visibleRowCache.length;a.grid.scrollDirection===d.scrollDirection.UP?(b=a.y.percentage,c>=b&&g.loadData(a.grid)):a.grid.scrollDirection===d.scrollDirection.DOWN&&(b=1-a.y.percentage,c>=b&&g.loadData(a.grid))}},loadData:function(a){a.infiniteScroll.previousVisibleRows=a.renderContainers.body.visibleRowCache.length,a.infiniteScroll.direction=a.scrollDirection,delete a.infiniteScroll.prevScrollTop,a.scrollDirection===d.scrollDirection.UP&&a.infiniteScroll.scrollUp?(a.infiniteScroll.dataLoading=!0,a.api.infiniteScroll.raise.needLoadMoreDataTop()):a.scrollDirection===d.scrollDirection.DOWN&&a.infiniteScroll.scrollDown&&(a.infiniteScroll.dataLoading=!0,a.api.infiniteScroll.raise.needLoadMoreData())},adjustScroll:function(a){var b=f.defer();return c(function(){var e,f,h,i,j;e=a.getViewportHeight()+a.headerHeight-a.renderContainers.body.headerHeight-a.scrollbarHeight,f=a.options.rowHeight,void 0===a.infiniteScroll.direction&&g.adjustInfiniteScrollPosition(a,0),h=a.getVisibleRowCount();var k=f*h;a.infiniteScroll.scrollDown&&e>k&&a.api.infiniteScroll.raise.needLoadMoreData(),a.infiniteScroll.direction===d.scrollDirection.UP&&(i=a.infiniteScroll.prevScrollTop||0,j=i+(h-a.infiniteScroll.previousVisibleRows)*f,g.adjustInfiniteScrollPosition(a,j),c(function(){b.resolve()})),a.infiniteScroll.direction===d.scrollDirection.DOWN&&(j=a.infiniteScroll.prevScrollTop||a.infiniteScroll.previousVisibleRows*f-e,g.adjustInfiniteScrollPosition(a,j),c(function(){b.resolve()}))},0),b.promise},adjustInfiniteScrollPosition:function(a,b){var c=new e(a,null,null,"ui.grid.adjustInfiniteScrollPosition"),d=a.getVisibleRowCount(),f=a.getViewportHeight()+a.headerHeight-a.renderContainers.body.headerHeight-a.scrollbarHeight,g=a.options.rowHeight,h=d*g-f;0===b&&a.infiniteScroll.scrollUp?c.y={percentage:1/h}:c.y={percentage:b/h},a.scrollContainers("",c)},dataRemovedTop:function(a,b,c){var d,e,f,h;g.setScrollDirections(a,b,c),d=a.renderContainers.body.visibleRowCache.length,e=a.infiniteScroll.prevScrollTop,h=a.options.rowHeight,f=e-(a.infiniteScroll.previousVisibleRows-d)*h,g.adjustInfiniteScrollPosition(a,f)},dataRemovedBottom:function(a,b,c){var d;g.setScrollDirections(a,b,c),d=a.infiniteScroll.prevScrollTop,g.adjustInfiniteScrollPosition(a,d)}};return g}]),a.directive("uiGridInfiniteScroll",["uiGridInfiniteScrollService",function(a){return{priority:-200,scope:!1,require:"^uiGrid",compile:function(b,c,d){return{pre:function(b,c,d,e){a.initializeGrid(e.grid,b)},post:function(a,b,c){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.moveColumns",["ui.grid"]);a.service("uiGridMoveColumnService",["$q","$timeout","$log","ScrollEvent","uiGridConstants","gridUtil",function(a,b,c,d,e,f){var g={initializeGrid:function(a){var b=this;this.registerPublicApi(a),this.defaultGridOptions(a.options),a.moveColumns={orderCache:[]},a.registerColumnBuilder(b.movableColumnBuilder),a.registerDataChangeCallback(b.verifyColumnOrder,[e.dataChange.COLUMN])},registerPublicApi:function(a){var b=this,c={events:{colMovable:{columnPositionChanged:function(a,b,c){}}},methods:{colMovable:{moveColumn:function(c,d){var e=a.columns;if(!angular.isNumber(c)||!angular.isNumber(d))return void f.logError("MoveColumn: Please provide valid values for originalPosition and finalPosition");for(var g=0,h=0;h<e.length;h++)(angular.isDefined(e[h].colDef.visible)&&e[h].colDef.visible===!1||e[h].isRowHeader===!0)&&g++;if(c>=e.length-g||d>=e.length-g)return void f.logError("MoveColumn: Invalid values for originalPosition, finalPosition");var i=function(a){for(var b=a,c=0;b>=c;c++)angular.isDefined(e[c])&&(angular.isDefined(e[c].colDef.visible)&&e[c].colDef.visible===!1||e[c].isRowHeader===!0)&&b++;return b};b.redrawColumnAtPosition(a,i(c),i(d))}}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods)},defaultGridOptions:function(a){a.enableColumnMoving=a.enableColumnMoving!==!1},movableColumnBuilder:function(b,c,d){var e=[];return b.enableColumnMoving=void 0===b.enableColumnMoving?d.enableColumnMoving:b.enableColumnMoving,a.all(e)},updateColumnCache:function(a){a.moveColumns.orderCache=a.getOnlyDataColumns()},verifyColumnOrder:function(a){var b,c=a.rowHeaderColumns.length;angular.forEach(a.moveColumns.orderCache,function(d,e){if(b=a.columns.indexOf(d),-1!==b&&b-c!==e){var f=a.columns.splice(b,1)[0];a.columns.splice(e+c,0,f)}})},redrawColumnAtPosition:function(a,c,d){var f=a.columns;if(c!==d){var h=d>c?c+1:c-1,i=Math.min(h,d);for(i;i<=Math.max(h,d)&&!f[i].visible;i++);if(!(i>Math.max(h,d))){var j=f[c];if(j.colDef.enableColumnMoving){if(c>d)for(var k=c;k>d;k--)f[k]=f[k-1];else if(d>c)for(var l=c;d>l;l++)f[l]=f[l+1];f[d]=j,g.updateColumnCache(a),a.queueGridRefresh(),b(function(){a.api.core.notifyDataChange(e.dataChange.COLUMN),a.api.colMovable.raise.columnPositionChanged(j.colDef,c,d)})}}}}};return g}]),a.directive("uiGridMoveColumns",["uiGridMoveColumnService",function(a){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(b,c,d,e){a.initializeGrid(e.grid)},post:function(a,b,c,d){}}}}}]),a.directive("uiGridHeaderCell",["$q","gridUtil","uiGridMoveColumnService","$document","$log","uiGridConstants","ScrollEvent",function(a,b,c,d,e,f,g){return{priority:-10,require:"^uiGrid",compile:function(){return{post:function(a,b,e,f){if(a.col.colDef.enableColumnMoving){var h,i,j,k,l,m,n=angular.element(b[0].querySelectorAll(".ui-grid-cell-contents")),o=!1,p=!1,q=function(b){h=a.grid.element[0].getBoundingClientRect().left,a.grid.hasLeftContainer()&&(h+=a.grid.renderContainers.left.header[0].getBoundingClientRect().width),i=b.pageX||(b.originalEvent?b.originalEvent.pageX:0),j=0,k=h+a.grid.getViewportWidth(),"mousedown"===b.type?(d.on("mousemove",r),d.on("mouseup",s)):"touchstart"===b.type&&(d.on("touchmove",r),d.on("touchend",s))},r=function(a){var b=a.pageX||(a.originalEvent?a.originalEvent.pageX:0),c=b-i;0!==c&&(document.onselectstart=function(){return!1},p=!0,o?o&&(w(c),i=b):v())},s=function(b){if(document.onselectstart=null,l&&(l.remove(),o=!1),u(),t(),p){for(var d=a.grid.columns,e=0,f=0;f<d.length&&d[f].colDef.name!==a.col.colDef.name;f++)e++;var g;if(0>j){var h,i=0;if(a.grid.isRTL()){for(h=e+1;h<d.length;h++)if((angular.isUndefined(d[h].colDef.visible)||d[h].colDef.visible===!0)&&(i+=d[h].drawnWidth||d[h].width||d[h].colDef.width,i>Math.abs(j))){c.redrawColumnAtPosition(a.grid,e,h-1);break}}else for(h=e-1;h>=0;h--)if((angular.isUndefined(d[h].colDef.visible)||d[h].colDef.visible===!0)&&(i+=d[h].drawnWidth||d[h].width||d[h].colDef.width,i>Math.abs(j))){c.redrawColumnAtPosition(a.grid,e,h+1);break}i<Math.abs(j)&&(g=0,a.grid.isRTL()&&(g=d.length-1),c.redrawColumnAtPosition(a.grid,e,g))}else if(j>0){var k,m=0;if(a.grid.isRTL()){for(k=e-1;k>0;k--)if((angular.isUndefined(d[k].colDef.visible)||d[k].colDef.visible===!0)&&(m+=d[k].drawnWidth||d[k].width||d[k].colDef.width,m>j)){c.redrawColumnAtPosition(a.grid,e,k);break}}else for(k=e+1;k<d.length;k++)if((angular.isUndefined(d[k].colDef.visible)||d[k].colDef.visible===!0)&&(m+=d[k].drawnWidth||d[k].width||d[k].colDef.width,m>j)){c.redrawColumnAtPosition(a.grid,e,k-1);break}j>m&&(g=d.length-1,a.grid.isRTL()&&(g=0),c.redrawColumnAtPosition(a.grid,e,g))}}},t=function(){n.on("touchstart",q),n.on("mousedown",q)},u=function(){n.off("touchstart",q),n.off("mousedown",q),d.off("mousemove",r),d.off("touchmove",r),d.off("mouseup",s),d.off("touchend",s)};t();var v=function(){o=!0,l=b.clone(),b.parent().append(l),l.addClass("movingColumn");var c={};c.left=b[0].offsetLeft+"px";var d=a.grid.element[0].getBoundingClientRect().right,e=b[0].getBoundingClientRect().right;e>d&&(m=a.col.drawnWidth+(d-e),c.width=m+"px"),l.css(c)},w=function(b){for(var c=a.grid.columns,d=0,e=0;e<c.length;e++)(angular.isUndefined(c[e].colDef.visible)||c[e].colDef.visible===!0)&&(d+=c[e].drawnWidth||c[e].width||c[e].colDef.width);var i,n=l[0].getBoundingClientRect().left-1,o=l[0].getBoundingClientRect().right;if(i=n-h+b,i=k>i?i:k,(n>=h||b>0)&&(k>=o||0>b))l.css({visibility:"visible",left:l[0].offsetLeft+(k>i?b:k-n)+"px"});else if(d>Math.ceil(f.grid.gridWidth)){b*=8;var p=new g(a.col.grid,null,null,"uiGridHeaderCell.moveElement");p.x={pixels:b},p.grid.scrollContainers("",p)}for(var q=0,r=0;r<c.length;r++)if(angular.isUndefined(c[r].colDef.visible)||c[r].colDef.visible===!0){if(c[r].colDef.name===a.col.colDef.name)break;q+=c[r].drawnWidth||c[r].width||c[r].colDef.width}void 0===a.newScrollLeft?j+=b:j=a.newScrollLeft+i-q,m<a.col.drawnWidth&&(m+=Math.abs(b),l.css({width:m+"px"}))};a.$on("$destroy",u)}}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.pagination",["ng","ui.grid"]);a.service("uiGridPaginationService",["gridUtil",function(a){var b={initializeGrid:function(a){b.defaultGridOptions(a.options);var c={events:{pagination:{paginationChanged:function(a,b){}}},methods:{pagination:{getPage:function(){return a.options.enablePagination?a.options.paginationCurrentPage:null},getFirstRowIndex:function(){return a.options.useCustomPagination?a.options.paginationPageSizes.reduce(function(b,c,d){return d<a.options.paginationCurrentPage-1?b+c:b},0):(a.options.paginationCurrentPage-1)*a.options.paginationPageSize},getLastRowIndex:function(){return a.options.useCustomPagination?c.methods.pagination.getFirstRowIndex()+a.options.paginationPageSizes[a.options.paginationCurrentPage-1]:Math.min(a.options.paginationCurrentPage*a.options.paginationPageSize,a.options.totalItems)},getTotalPages:function(){return a.options.enablePagination?a.options.useCustomPagination?a.options.paginationPageSizes.length:0===a.options.totalItems?1:Math.ceil(a.options.totalItems/a.options.paginationPageSize):null},nextPage:function(){a.options.enablePagination&&(a.options.totalItems>0?a.options.paginationCurrentPage=Math.min(a.options.paginationCurrentPage+1,c.methods.pagination.getTotalPages()):a.options.paginationCurrentPage++)},previousPage:function(){a.options.enablePagination&&(a.options.paginationCurrentPage=Math.max(a.options.paginationCurrentPage-1,1))},seek:function(b){if(a.options.enablePagination){if(!angular.isNumber(b)||1>b)throw"Invalid page number: "+b;a.options.paginationCurrentPage=Math.min(b,c.methods.pagination.getTotalPages())}}}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods);var d=function(b){if(a.options.useExternalPagination||!a.options.enablePagination)return b;var d=parseInt(a.options.paginationPageSize,10),e=parseInt(a.options.paginationCurrentPage,10),f=b.filter(function(a){return a.visible});a.options.totalItems=f.length;var g=c.methods.pagination.getFirstRowIndex(),h=c.methods.pagination.getLastRowIndex();return g>f.length&&(e=a.options.paginationCurrentPage=1,g=(e-1)*d),f.slice(g,h)};a.registerRowsProcessor(d,900)},defaultGridOptions:function(b){b.enablePagination=b.enablePagination!==!1,b.enablePaginationControls=b.enablePaginationControls!==!1,b.useExternalPagination=b.useExternalPagination===!0,b.useCustomPagination=b.useCustomPagination===!0,a.isNullOrUndefined(b.totalItems)&&(b.totalItems=0),a.isNullOrUndefined(b.paginationPageSizes)&&(b.paginationPageSizes=[250,500,1e3]),a.isNullOrUndefined(b.paginationPageSize)&&(b.paginationPageSizes.length>0?b.paginationPageSize=b.paginationPageSizes[0]:b.paginationPageSize=0),a.isNullOrUndefined(b.paginationCurrentPage)&&(b.paginationCurrentPage=1),a.isNullOrUndefined(b.paginationTemplate)&&(b.paginationTemplate="ui-grid/pagination")},onPaginationChanged:function(a,b,c){a.api.pagination.raise.paginationChanged(b,c),a.options.useExternalPagination||a.queueGridRefresh()}};return b}]),a.directive("uiGridPagination",["gridUtil","uiGridPaginationService",function(a,b){return{priority:-200,scope:!1,require:"uiGrid",link:{pre:function(c,d,e,f){b.initializeGrid(f.grid),a.getTemplate(f.grid.options.paginationTemplate).then(function(a){var b=angular.element(a);d.append(b),f.innerCompile(b)})}}}}]),a.directive("uiGridPager",["uiGridPaginationService","uiGridConstants","gridUtil","i18nService",function(a,b,c,d){return{priority:-200,scope:!0,require:"^uiGrid",link:function(e,f,g,h){var i=".ui-grid-pager-control-input";e.aria=d.getSafeText("pagination.aria"),e.paginationApi=h.grid.api.pagination,e.sizesLabel=d.getSafeText("pagination.sizes"),e.totalItemsLabel=d.getSafeText("pagination.totalItems"),e.paginationOf=d.getSafeText("pagination.of"),e.paginationThrough=d.getSafeText("pagination.through");var j=h.grid.options;h.grid.renderContainers.body.registerViewportAdjuster(function(a){return a.height=a.height-c.elementHeight(f,"padding"),a});var k=h.grid.registerDataChangeCallback(function(a){a.options.useExternalPagination||(a.options.totalItems=a.rows.length)},[b.dataChange.ROW]);e.$on("$destroy",k);var l=e.$watch("grid.options.paginationCurrentPage + grid.options.paginationPageSize",function(b,c){return b!==c&&void 0!==c?!angular.isNumber(j.paginationCurrentPage)||j.paginationCurrentPage<1?void(j.paginationCurrentPage=1):j.totalItems>0&&j.paginationCurrentPage>e.paginationApi.getTotalPages()?void(j.paginationCurrentPage=e.paginationApi.getTotalPages()):void a.onPaginationChanged(e.grid,j.paginationCurrentPage,j.paginationPageSize):void 0});e.$on("$destroy",function(){l()}),e.cantPageForward=function(){return e.paginationApi.getTotalPages()?e.cantPageToLast():j.data.length<1},e.cantPageToLast=function(){var a=e.paginationApi.getTotalPages();return!a||j.paginationCurrentPage>=a},e.cantPageBackward=function(){return j.paginationCurrentPage<=1};var m=function(a){a&&c.focus.bySelector(f,i)};e.pageFirstPageClick=function(){e.paginationApi.seek(1),m(e.cantPageBackward())},e.pagePreviousPageClick=function(){e.paginationApi.previousPage(),m(e.cantPageBackward())},e.pageNextPageClick=function(){e.paginationApi.nextPage(),m(e.cantPageForward())},e.pageLastPageClick=function(){e.paginationApi.seek(e.paginationApi.getTotalPages()),m(e.cantPageToLast())}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.pinning",["ui.grid"]);a.constant("uiGridPinningConstants",{container:{LEFT:"left",RIGHT:"right",NONE:""}}),a.service("uiGridPinningService",["gridUtil","GridRenderContainer","i18nService","uiGridPinningConstants",function(a,b,c,d){var e={initializeGrid:function(a){e.defaultGridOptions(a.options),a.registerColumnBuilder(e.pinningColumnBuilder);var b={events:{pinning:{columnPinned:function(a,b){}}},methods:{pinning:{pinColumn:function(b,c){e.pinColumn(a,b,c)}}}};a.api.registerEventsFromObject(b.events),a.api.registerMethodsFromObject(b.methods)},defaultGridOptions:function(a){a.enablePinning=a.enablePinning!==!1},pinningColumnBuilder:function(b,f,g){if(b.enablePinning=void 0===b.enablePinning?g.enablePinning:b.enablePinning,b.pinnedLeft?(f.renderContainer="left",f.grid.createLeftContainer()):b.pinnedRight&&(f.renderContainer="right",f.grid.createRightContainer()),b.enablePinning){var h={name:"ui.grid.pinning.pinLeft",title:c.get().pinning.pinLeft,icon:"ui-grid-icon-left-open",shown:function(){return"undefined"==typeof this.context.col.renderContainer||!this.context.col.renderContainer||"left"!==this.context.col.renderContainer},action:function(){e.pinColumn(this.context.col.grid,this.context.col,d.container.LEFT)}},i={name:"ui.grid.pinning.pinRight",title:c.get().pinning.pinRight,icon:"ui-grid-icon-right-open",shown:function(){return"undefined"==typeof this.context.col.renderContainer||!this.context.col.renderContainer||"right"!==this.context.col.renderContainer},action:function(){e.pinColumn(this.context.col.grid,this.context.col,d.container.RIGHT)}},j={name:"ui.grid.pinning.unpin",title:c.get().pinning.unpin,icon:"ui-grid-icon-cancel",shown:function(){return"undefined"!=typeof this.context.col.renderContainer&&null!==this.context.col.renderContainer&&"body"!==this.context.col.renderContainer},action:function(){e.pinColumn(this.context.col.grid,this.context.col,d.container.NONE)}};a.arrayContainsObjectWithProperty(f.menuItems,"name","ui.grid.pinning.pinLeft")||f.menuItems.push(h),a.arrayContainsObjectWithProperty(f.menuItems,"name","ui.grid.pinning.pinRight")||f.menuItems.push(i),a.arrayContainsObjectWithProperty(f.menuItems,"name","ui.grid.pinning.unpin")||f.menuItems.push(j)}},pinColumn:function(a,b,c){c===d.container.NONE?(b.renderContainer=null,b.colDef.pinnedLeft=b.colDef.pinnedRight=!1):(b.renderContainer=c,c===d.container.LEFT?a.createLeftContainer():c===d.container.RIGHT&&a.createRightContainer()),a.refresh().then(function(){a.api.pinning.raise.columnPinned(b.colDef,c)})}};return e}]),a.directive("uiGridPinning",["gridUtil","uiGridPinningService",function(a,b){return{require:"uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){b.initializeGrid(e.grid)},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.resizeColumns",["ui.grid"]);a.service("uiGridResizeColumnsService",["gridUtil","$q","$timeout",function(a,b,c){var d={defaultGridOptions:function(a){a.enableColumnResizing=a.enableColumnResizing!==!1,a.enableColumnResize===!1&&(a.enableColumnResizing=!1)},colResizerColumnBuilder:function(a,c,d){var e=[];return a.enableColumnResizing=void 0===a.enableColumnResizing?d.enableColumnResizing:a.enableColumnResizing,a.enableColumnResize===!1&&(a.enableColumnResizing=!1),b.all(e)},registerPublicApi:function(a){var b={events:{colResizable:{columnSizeChanged:function(a,b){}}}};a.api.registerEventsFromObject(b.events)},fireColumnSizeChanged:function(b,d,e){c(function(){b.api.colResizable?b.api.colResizable.raise.columnSizeChanged(d,e):a.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.")})},findTargetCol:function(a,b,c){var d=a.getRenderContainer();if("left"===b){var e=d.visibleColumnCache.indexOf(a);return d.visibleColumnCache[e-1*c]}return a}};return d}]),a.directive("uiGridResizeColumns",["gridUtil","uiGridResizeColumnsService",function(a,b){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){b.defaultGridOptions(e.grid.options),e.grid.registerColumnBuilder(b.colResizerColumnBuilder),b.registerPublicApi(e.grid)},post:function(a,b,c,d){}}}}}]),a.directive("uiGridHeaderCell",["gridUtil","$templateCache","$compile","$q","uiGridResizeColumnsService","uiGridConstants","$timeout",function(a,b,c,d,e,f,g){return{priority:-10,require:"^uiGrid",compile:function(){return{post:function(a,d,h,i){var j=i.grid;if(j.options.enableColumnResizing){var k=b.get("ui-grid/columnResizer"),l=1;j.isRTL()&&(a.position="left",l=-1);var m=function(){for(var b=d[0].getElementsByClassName("ui-grid-column-resizer"),f=0;f<b.length;f++)angular.element(b[f]).remove();var g=e.findTargetCol(a.col,"left",l),h=a.col.getRenderContainer();if(g&&0!==h.visibleColumnCache.indexOf(a.col)&&g.colDef.enableColumnResizing!==!1){var i=angular.element(k).clone();i.attr("position","left"),d.prepend(i),c(i)(a)}if(a.col.colDef.enableColumnResizing!==!1){var j=angular.element(k).clone();j.attr("position","right"),d.append(j),c(j)(a)}};m();var n=function(){g(m)},o=j.registerDataChangeCallback(n,[f.dataChange.COLUMN]);a.$on("$destroy",o)}}}}}}]),a.directive("uiGridColumnResizer",["$document","gridUtil","uiGridConstants","uiGridResizeColumnsService",function(a,b,c,d){var e=angular.element('<div class="ui-grid-resize-overlay"></div>'),f={priority:0,scope:{col:"=",position:"@",renderIndex:"="},require:"?^uiGrid",link:function(f,g,h,i){function j(a){i.grid.refreshCanvas(!0).then(function(){i.grid.queueGridRefresh()})}function k(a,b){var c=b;return a.minWidth&&c<a.minWidth?c=a.minWidth:a.maxWidth&&c>a.maxWidth&&(c=a.maxWidth),c}function l(a,b){a.originalEvent&&(a=a.originalEvent),a.preventDefault(),o=(a.targetTouches?a.targetTouches[0]:a).clientX-p,0>o?o=0:o>i.grid.gridWidth&&(o=i.grid.gridWidth);var g=d.findTargetCol(f.col,f.position,q);if(g.colDef.enableColumnResizing!==!1){i.grid.element.hasClass("column-resizing")||i.grid.element.addClass("column-resizing");var h=o-n,j=parseInt(g.drawnWidth+h*q,10);o+=(k(g,j)-j)*q,e.css({left:o+"px"}),i.fireEvent(c.events.ITEM_DRAGGING)}}function m(a,b){a.originalEvent&&(a=a.originalEvent),a.preventDefault(),i.grid.element.removeClass("column-resizing"),e.remove(),o=(a.changedTouches?a.changedTouches[0]:a).clientX-p;var c=o-n;if(0===c)return t(),void s();var g=d.findTargetCol(f.col,f.position,q);if(g.colDef.enableColumnResizing!==!1){var h=parseInt(g.drawnWidth+c*q,10);g.width=k(g,h),g.hasCustomWidth=!0,j(c),d.fireColumnSizeChanged(i.grid,g.colDef,c),t(),s()}}var n=0,o=0,p=0,q=1;i.grid.isRTL()&&(f.position="left",q=-1),"left"===f.position?g.addClass("left"):"right"===f.position&&g.addClass("right");var r=function(b,c){b.originalEvent&&(b=b.originalEvent),b.stopPropagation(),p=i.grid.element[0].getBoundingClientRect().left,n=(b.targetTouches?b.targetTouches[0]:b).clientX-p,i.grid.element.append(e),e.css({left:n}),"touchstart"===b.type?(a.on("touchend",m),a.on("touchmove",l),g.off("mousedown",r)):(a.on("mouseup",m),a.on("mousemove",l),g.off("touchstart",r))},s=function(){g.on("mousedown",r),g.on("touchstart",r)},t=function(){a.off("mouseup",m),a.off("touchend",m),a.off("mousemove",l),a.off("touchmove",l),g.off("mousedown",r),g.off("touchstart",r)};s();var u=function(a,e){a.stopPropagation();var h=d.findTargetCol(f.col,f.position,q);if(h.colDef.enableColumnResizing!==!1){var l=0,m=0,n=b.closestElm(g,".ui-grid-render-container"),o=n.querySelectorAll("."+c.COL_CLASS_PREFIX+h.uid+" .ui-grid-cell-contents");Array.prototype.forEach.call(o,function(a){var c;angular.element(a).parent().hasClass("ui-grid-header-cell")&&(c=angular.element(a).parent()[0].querySelectorAll(".ui-grid-column-menu-button")),b.fakeElement(a,{},function(a){var d=angular.element(a);d.attr("style","float: left");var e=b.elementWidth(d);if(c){var f=b.elementWidth(c);e+=f}e>l&&(l=e,m=l-e)})}),h.width=k(h,l),h.hasCustomWidth=!0,j(m),d.fireColumnSizeChanged(i.grid,h.colDef,m)}};g.on("dblclick",u),g.on("$destroy",function(){g.off("dblclick",u),t()})}};return f}])}(),function(){"use strict";var a=angular.module("ui.grid.rowEdit",["ui.grid","ui.grid.edit","ui.grid.cellNav"]);a.constant("uiGridRowEditConstants",{}),a.service("uiGridRowEditService",["$interval","$q","uiGridConstants","uiGridRowEditConstants","gridUtil",function(a,b,c,d,e){var f={initializeGrid:function(a,b){b.rowEdit={};var c={events:{rowEdit:{saveRow:function(a){}}},methods:{rowEdit:{setSavePromise:function(a,c){f.setSavePromise(b,a,c)},getDirtyRows:function(){return b.rowEdit.dirtyRows?b.rowEdit.dirtyRows:[]},getErrorRows:function(){return b.rowEdit.errorRows?b.rowEdit.errorRows:[]},flushDirtyRows:function(){return f.flushDirtyRows(b)},setRowsDirty:function(a){f.setRowsDirty(b,a)},setRowsClean:function(a){f.setRowsClean(b,a)}}}};b.api.registerEventsFromObject(c.events),b.api.registerMethodsFromObject(c.methods),b.api.core.on.renderingComplete(a,function(c){b.api.edit.on.afterCellEdit(a,f.endEditCell),b.api.edit.on.beginCellEdit(a,f.beginEditCell),b.api.edit.on.cancelCellEdit(a,f.cancelEditCell),b.api.cellNav&&b.api.cellNav.on.navigate(a,f.navigate)})},defaultGridOptions:function(a){},saveRow:function(a,b){var c=this;return function(){if(b.isSaving=!0,b.rowEditSavePromise)return b.rowEditSavePromise;var d=a.api.rowEdit.raise.saveRow(b.entity);return b.rowEditSavePromise?b.rowEditSavePromise.then(c.processSuccessPromise(a,b),c.processErrorPromise(a,b)):e.logError("A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise"),d}},setSavePromise:function(a,b,c){var d=a.getRow(b);d.rowEditSavePromise=c},processSuccessPromise:function(a,b){var c=this;return function(){delete b.isSaving,delete b.isDirty,delete b.isError,delete b.rowEditSaveTimer,delete b.rowEditSavePromise,c.removeRow(a.rowEdit.errorRows,b),c.removeRow(a.rowEdit.dirtyRows,b)}},processErrorPromise:function(a,b){return function(){delete b.isSaving,delete b.rowEditSaveTimer,delete b.rowEditSavePromise,b.isError=!0,a.rowEdit.errorRows||(a.rowEdit.errorRows=[]),f.isRowPresent(a.rowEdit.errorRows,b)||a.rowEdit.errorRows.push(b)}},removeRow:function(a,b){"undefined"!=typeof a&&null!==a&&a.forEach(function(c,d){c.uid===b.uid&&a.splice(d,1)})},isRowPresent:function(a,b){var c=!1;return a.forEach(function(a,d){a.uid===b.uid&&(c=!0)}),c},flushDirtyRows:function(a){var c=[];return a.api.rowEdit.getDirtyRows().forEach(function(b){f.saveRow(a,b)(),c.push(b.rowEditSavePromise)}),b.all(c)},endEditCell:function(a,b,c,d){var g=this.grid,h=g.getRow(a);return h?void((c!==d||h.isDirty)&&(g.rowEdit.dirtyRows||(g.rowEdit.dirtyRows=[]),h.isDirty||(h.isDirty=!0,g.rowEdit.dirtyRows.push(h)),delete h.isError,f.considerSetTimer(g,h))):void e.logError("Unable to find rowEntity in grid data, dirty flag cannot be set")},beginEditCell:function(a,b){var c=this.grid,d=c.getRow(a);return d?void f.cancelTimer(c,d):void e.logError("Unable to find rowEntity in grid data, timer cannot be cancelled")},cancelEditCell:function(a,b){var c=this.grid,d=c.getRow(a);return d?void f.considerSetTimer(c,d):void e.logError("Unable to find rowEntity in grid data, timer cannot be set")},navigate:function(a,b){var c=this.grid;a.row.rowEditSaveTimer&&f.cancelTimer(c,a.row),b&&b.row&&b.row!==a.row&&f.considerSetTimer(c,b.row)},considerSetTimer:function(b,c){if(f.cancelTimer(b,c),c.isDirty&&!c.isSaving&&-1!==b.options.rowEditWaitInterval){var d=b.options.rowEditWaitInterval?b.options.rowEditWaitInterval:2e3;c.rowEditSaveTimer=a(f.saveRow(b,c),d,1)}},cancelTimer:function(b,c){c.rowEditSaveTimer&&!c.isSaving&&(a.cancel(c.rowEditSaveTimer),delete c.rowEditSaveTimer)},setRowsDirty:function(a,b){var c;b.forEach(function(b,d){c=a.getRow(b),c?(a.rowEdit.dirtyRows||(a.rowEdit.dirtyRows=[]),c.isDirty||(c.isDirty=!0,a.rowEdit.dirtyRows.push(c)),delete c.isError,f.considerSetTimer(a,c)):e.logError("requested row not found in rowEdit.setRowsDirty, row was: "+b)})},setRowsClean:function(a,b){var c;b.forEach(function(b,d){c=a.getRow(b),c?(delete c.isDirty,f.removeRow(a.rowEdit.dirtyRows,c),f.cancelTimer(a,c),delete c.isError,f.removeRow(a.rowEdit.errorRows,c)):e.logError("requested row not found in rowEdit.setRowsClean, row was: "+b)})}};return f}]),a.directive("uiGridRowEdit",["gridUtil","uiGridRowEditService","uiGridEditConstants",function(a,b,c){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){b.initializeGrid(a,e.grid)},post:function(a,b,c,d){}}}}}]),a.directive("uiGridViewport",["$compile","uiGridConstants","gridUtil","$parse",function(a,b,c,d){return{priority:-200,scope:!1,compile:function(a,b){var c=angular.element(a.children().children()[0]),d=c.attr("ng-class"),e="";return e=d?d.slice(0,-1)+", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}":"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}",c.attr("ng-class",e),{pre:function(a,b,c,d){},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.saveState",["ui.grid","ui.grid.selection","ui.grid.cellNav","ui.grid.grouping","ui.grid.pinning","ui.grid.treeView"]);a.constant("uiGridSaveStateConstants",{featureName:"saveState"}),a.service("uiGridSaveStateService",["$q","uiGridSaveStateConstants","gridUtil","$compile","$interval","uiGridConstants",function(a,b,c,d,e,f){var g={initializeGrid:function(a){a.saveState={},this.defaultGridOptions(a.options);var b={events:{saveState:{}},methods:{saveState:{save:function(){return g.save(a)},restore:function(b,c){g.restore(a,b,c)}}}};a.api.registerEventsFromObject(b.events),a.api.registerMethodsFromObject(b.methods)},defaultGridOptions:function(a){a.saveWidths=a.saveWidths!==!1,a.saveOrder=a.saveOrder!==!1,a.saveScroll=a.saveScroll===!0,a.saveFocus=a.saveScroll!==!0&&a.saveFocus!==!1,a.saveVisible=a.saveVisible!==!1,a.saveSort=a.saveSort!==!1,a.saveFilter=a.saveFilter!==!1,a.saveSelection=a.saveSelection!==!1,a.saveGrouping=a.saveGrouping!==!1,a.saveGroupingExpandedStates=a.saveGroupingExpandedStates===!0,a.savePinning=a.savePinning!==!1,a.saveTreeView=a.saveTreeView!==!1},save:function(a){var b={};return b.columns=g.saveColumns(a),b.scrollFocus=g.saveScrollFocus(a),b.selection=g.saveSelection(a),b.grouping=g.saveGrouping(a),b.treeView=g.saveTreeView(a),b.pagination=g.savePagination(a),b},restore:function(a,b,c){c.columns&&g.restoreColumns(a,c.columns),c.scrollFocus&&g.restoreScrollFocus(a,b,c.scrollFocus),c.selection&&g.restoreSelection(a,c.selection),c.grouping&&g.restoreGrouping(a,c.grouping),c.treeView&&g.restoreTreeView(a,c.treeView),c.pagination&&g.restorePagination(a,c.pagination),a.refresh()},saveColumns:function(a){var b=[];return a.getOnlyDataColumns().forEach(function(c){var d={};d.name=c.name,a.options.saveVisible&&(d.visible=c.visible),a.options.saveWidths&&(d.width=c.width),a.options.saveSort&&(d.sort=angular.copy(c.sort)),a.options.saveFilter&&(d.filters=[],c.filters.forEach(function(a){var b={};angular.forEach(a,function(a,c){"condition"!==c&&"$$hashKey"!==c&&"placeholder"!==c&&(b[c]=a)}),d.filters.push(b)})),a.api.pinning&&a.options.savePinning&&(d.pinned=c.renderContainer?c.renderContainer:""),b.push(d)}),b},saveScrollFocus:function(a){if(!a.api.cellNav)return{};var b={};if(a.options.saveFocus){
+b.focus=!0;var c=a.api.cellNav.getFocusedCell();null!==c&&(null!==c.col&&(b.colName=c.col.colDef.name),null!==c.row&&(b.rowVal=g.getRowVal(a,c.row)))}return(a.options.saveScroll||a.options.saveFocus&&!b.colName&&!b.rowVal)&&(b.focus=!1,a.renderContainers.body.prevRowScrollIndex&&(b.rowVal=g.getRowVal(a,a.renderContainers.body.visibleRowCache[a.renderContainers.body.prevRowScrollIndex])),a.renderContainers.body.prevColScrollIndex&&(b.colName=a.renderContainers.body.visibleColumnCache[a.renderContainers.body.prevColScrollIndex].name)),b},saveSelection:function(a){if(!a.api.selection||!a.options.saveSelection)return[];var b=a.api.selection.getSelectedGridRows().map(function(b){return g.getRowVal(a,b)});return b},saveGrouping:function(a){return a.api.grouping&&a.options.saveGrouping?a.api.grouping.getGrouping(a.options.saveGroupingExpandedStates):{}},savePagination:function(a){return a.api.pagination&&a.options.paginationPageSize?{paginationCurrentPage:a.options.paginationCurrentPage,paginationPageSize:a.options.paginationPageSize}:{}},saveTreeView:function(a){return a.api.treeView&&a.options.saveTreeView?a.api.treeView.getTreeView():{}},getRowVal:function(a,b){if(!b)return null;var c={};return a.options.saveRowIdentity?(c.identity=!0,c.row=a.options.saveRowIdentity(b.entity)):(c.identity=!1,c.row=a.renderContainers.body.visibleRowCache.indexOf(b)),c},restoreColumns:function(a,b){var c=!1;b.forEach(function(b,d){var e=a.getColumn(b.name);if(e&&!a.isRowHeaderColumn(e)){!a.options.saveVisible||e.visible===b.visible&&e.colDef.visible===b.visible||(e.visible=b.visible,e.colDef.visible=b.visible,a.api.core.raise.columnVisibilityChanged(e)),a.options.saveWidths&&e.width!==b.width&&(e.width=b.width,e.hasCustomWidth=!0),!a.options.saveSort||angular.equals(e.sort,b.sort)||void 0===e.sort&&angular.isEmpty(b.sort)||(e.sort=angular.copy(b.sort),c=!0),a.options.saveFilter&&!angular.equals(e.filters,b.filters)&&(b.filters.forEach(function(a,b){angular.extend(e.filters[b],a),("undefined"==typeof a.term||null===a.term)&&delete e.filters[b].term}),a.api.core.raise.filterChanged()),a.api.pinning&&a.options.savePinning&&e.renderContainer!==b.pinned&&a.api.pinning.pinColumn(e,b.pinned);var f=a.getOnlyDataColumns().indexOf(e);if(-1!==f&&a.options.saveOrder&&f!==d){var g=a.columns.splice(f+a.rowHeaderColumns.length,1)[0];a.columns.splice(d+a.rowHeaderColumns.length,0,g)}}}),c&&a.api.core.raise.sortChanged(a,a.getColumnSorting())},restoreScrollFocus:function(a,b,c){if(a.api.cellNav){var d,e;if(c.colName){var f=a.options.columnDefs.filter(function(a){return a.name===c.colName});f.length>0&&(d=f[0])}c.rowVal&&c.rowVal.row&&(e=c.rowVal.identity?g.findRowByIdentity(a,c.rowVal):a.renderContainers.body.visibleRowCache[c.rowVal.row]);var h=e&&e.entity?e.entity:null;(d||h)&&(c.focus?a.api.cellNav.scrollToFocus(h,d):a.scrollTo(h,d))}},restoreSelection:function(a,b){a.api.selection&&(a.api.selection.clearSelectedRows(),b.forEach(function(b){if(b.identity){var c=g.findRowByIdentity(a,b);c&&a.api.selection.selectRow(c.entity)}else a.api.selection.selectRowByVisibleIndex(b.row)}))},restoreGrouping:function(a,b){a.api.grouping&&"undefined"!=typeof b&&null!==b&&!angular.equals(b,{})&&a.api.grouping.setGrouping(b)},restoreTreeView:function(a,b){a.api.treeView&&"undefined"!=typeof b&&null!==b&&!angular.equals(b,{})&&a.api.treeView.setTreeView(b)},restorePagination:function(a,b){a.api.pagination&&a.options.paginationPageSize&&(a.options.paginationCurrentPage=b.paginationCurrentPage,a.options.paginationPageSize=b.paginationPageSize)},findRowByIdentity:function(a,b){if(!a.options.saveRowIdentity)return null;var c=a.rows.filter(function(c){return a.options.saveRowIdentity(c.entity)===b.row?!0:!1});return c.length>0?c[0]:null}};return g}]),a.directive("uiGridSaveState",["uiGridSaveStateConstants","uiGridSaveStateService","gridUtil","$compile",function(a,b,c,d){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(a,c,d,e){b.initializeGrid(e.grid)}}}])}(),function(){"use strict";var a=angular.module("ui.grid.selection",["ui.grid"]);a.constant("uiGridSelectionConstants",{featureName:"selection",selectionRowHeaderColName:"selectionRowHeaderCol"}),angular.module("ui.grid").config(["$provide",function(a){a.decorator("GridRow",["$delegate",function(a){return a.prototype.setSelected=function(a){a!==this.isSelected&&(this.isSelected=a,this.grid.selection.selectedCount+=a?1:-1)},a}])}]),a.service("uiGridSelectionService",["$q","$templateCache","uiGridSelectionConstants","gridUtil",function(a,b,c,d){var e={initializeGrid:function(a){a.selection={},a.selection.lastSelectedRow=null,a.selection.selectAll=!1,a.selection.selectedCount=0,e.defaultGridOptions(a.options);var b={events:{selection:{rowSelectionChanged:function(a,b,c){},rowSelectionChangedBatch:function(a,b,c){}}},methods:{selection:{toggleRowSelection:function(b,c){var d=a.getRow(b);null!==d&&e.toggleRowSelection(a,d,c,a.options.multiSelect,a.options.noUnselect)},selectRow:function(b,c){var d=a.getRow(b);null===d||d.isSelected||e.toggleRowSelection(a,d,c,a.options.multiSelect,a.options.noUnselect)},selectRowByVisibleIndex:function(b,c){var d=a.renderContainers.body.visibleRowCache[b];null===d||"undefined"==typeof d||d.isSelected||e.toggleRowSelection(a,d,c,a.options.multiSelect,a.options.noUnselect)},unSelectRow:function(b,c){var d=a.getRow(b);null!==d&&d.isSelected&&e.toggleRowSelection(a,d,c,a.options.multiSelect,a.options.noUnselect)},selectAllRows:function(b){if(a.options.multiSelect!==!1){var c=[];a.rows.forEach(function(d){d.isSelected||d.enableSelection===!1||(d.setSelected(!0),e.decideRaiseSelectionEvent(a,d,c,b))}),e.decideRaiseSelectionBatchEvent(a,c,b),a.selection.selectAll=!0}},selectAllVisibleRows:function(b){if(a.options.multiSelect!==!1){var c=[];a.rows.forEach(function(d){d.visible?d.isSelected||d.enableSelection===!1||(d.setSelected(!0),e.decideRaiseSelectionEvent(a,d,c,b)):d.isSelected&&(d.setSelected(!1),e.decideRaiseSelectionEvent(a,d,c,b))}),e.decideRaiseSelectionBatchEvent(a,c,b),a.selection.selectAll=!0}},clearSelectedRows:function(b){e.clearSelectedRows(a,b)},getSelectedRows:function(){return e.getSelectedRows(a).map(function(a){return a.entity})},getSelectedGridRows:function(){return e.getSelectedRows(a)},getSelectedCount:function(){return a.selection.selectedCount},setMultiSelect:function(b){a.options.multiSelect=b},setModifierKeysToMultiSelect:function(b){a.options.modifierKeysToMultiSelect=b},getSelectAllState:function(){return a.selection.selectAll}}}};a.api.registerEventsFromObject(b.events),a.api.registerMethodsFromObject(b.methods)},defaultGridOptions:function(a){a.enableRowSelection=a.enableRowSelection!==!1,a.multiSelect=a.multiSelect!==!1,a.noUnselect=a.noUnselect===!0,a.modifierKeysToMultiSelect=a.modifierKeysToMultiSelect===!0,a.enableRowHeaderSelection=a.enableRowHeaderSelection!==!1,"undefined"==typeof a.enableFullRowSelection&&(a.enableFullRowSelection=!a.enableRowHeaderSelection),a.enableSelectAll=a.enableSelectAll!==!1,a.enableSelectionBatchEvent=a.enableSelectionBatchEvent!==!1,a.selectionRowHeaderWidth=angular.isDefined(a.selectionRowHeaderWidth)?a.selectionRowHeaderWidth:30,a.enableFooterTotalSelected=a.enableFooterTotalSelected!==!1,a.isRowSelectable=angular.isDefined(a.isRowSelectable)?a.isRowSelectable:angular.noop},toggleRowSelection:function(a,b,c,d,f){var g=b.isSelected;if(b.enableSelection!==!1||g){var h;d||g?!d&&g&&(h=e.getSelectedRows(a),h.length>1&&(g=!1,e.clearSelectedRows(a,c))):e.clearSelectedRows(a,c),g&&f||(b.setSelected(!g),b.isSelected===!0&&(a.selection.lastSelectedRow=b),h=e.getSelectedRows(a),a.selection.selectAll=a.rows.length===h.length,a.api.selection.raise.rowSelectionChanged(b,c))}},shiftSelect:function(a,b,c,d){if(d){var f=e.getSelectedRows(a),g=f.length>0?a.renderContainers.body.visibleRowCache.indexOf(a.selection.lastSelectedRow):0,h=a.renderContainers.body.visibleRowCache.indexOf(b);if(g>h){var i=g;g=h,h=i}for(var j=[],k=g;h>=k;k++){var l=a.renderContainers.body.visibleRowCache[k];l&&(l.isSelected||l.enableSelection===!1||(l.setSelected(!0),a.selection.lastSelectedRow=l,e.decideRaiseSelectionEvent(a,l,j,c)))}e.decideRaiseSelectionBatchEvent(a,j,c)}},getSelectedRows:function(a){return a.rows.filter(function(a){return a.isSelected})},clearSelectedRows:function(a,b){var c=[];e.getSelectedRows(a).forEach(function(d){d.isSelected&&(d.setSelected(!1),e.decideRaiseSelectionEvent(a,d,c,b))}),e.decideRaiseSelectionBatchEvent(a,c,b),a.selection.selectAll=!1,a.selection.selectedCount=0},decideRaiseSelectionEvent:function(a,b,c,d){a.options.enableSelectionBatchEvent?c.push(b):a.api.selection.raise.rowSelectionChanged(b,d)},decideRaiseSelectionBatchEvent:function(a,b,c){b.length>0&&a.api.selection.raise.rowSelectionChangedBatch(b,c)}};return e}]),a.directive("uiGridSelection",["uiGridSelectionConstants","uiGridSelectionService","$templateCache","uiGridConstants",function(a,b,c,d){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(c,e,f,g){if(b.initializeGrid(g.grid),g.grid.options.enableRowHeaderSelection){var h={name:a.selectionRowHeaderColName,displayName:"",width:g.grid.options.selectionRowHeaderWidth,minWidth:10,cellTemplate:"ui-grid/selectionRowHeader",headerCellTemplate:"ui-grid/selectionHeaderCell",enableColumnResizing:!1,enableColumnMenu:!1,exporterSuppressExport:!0,allowCellFocus:!0};g.grid.addRowHeaderColumn(h,0)}var i=!1,j=function(a){return a.forEach(function(a){a.enableSelection=g.grid.options.isRowSelectable(a)}),a},k=function(){g.grid.options.isRowSelectable!==angular.noop&&i!==!0&&(g.grid.registerRowsProcessor(j,500),i=!0)};k();var l=g.grid.registerDataChangeCallback(k,[d.dataChange.OPTIONS]);c.$on("$destroy",l)},post:function(a,b,c,d){}}}}}]),a.directive("uiGridSelectionRowHeaderButtons",["$templateCache","uiGridSelectionService","gridUtil",function(a,b,c){return{replace:!0,restrict:"E",template:a.get("ui-grid/selectionRowHeaderButtons"),scope:!0,require:"^uiGrid",link:function(a,d,e,f){function g(a,c){c.stopPropagation(),c.shiftKey?b.shiftSelect(i,a,c,i.options.multiSelect):c.ctrlKey||c.metaKey?b.toggleRowSelection(i,a,c,i.options.multiSelect,i.options.noUnselect):b.toggleRowSelection(i,a,c,i.options.multiSelect&&!i.options.modifierKeysToMultiSelect,i.options.noUnselect)}function h(a){(a.ctrlKey||a.shiftKey)&&(a.target.onselectstart=function(){return!1},window.setTimeout(function(){a.target.onselectstart=null},0))}var i=f.grid;a.selectButtonClick=g,"ie"===c.detectBrowser()&&d.on("mousedown",h),a.$on("$destroy",function(){d.off()})}}}]),a.directive("uiGridSelectionSelectAllButtons",["$templateCache","uiGridSelectionService",function(a,b){return{replace:!0,restrict:"E",template:a.get("ui-grid/selectionSelectAllButtons"),scope:!1,link:function(a,c,d,e){var f=a.col.grid;a.headerButtonClick=function(a,c){f.selection.selectAll?(b.clearSelectedRows(f,c),f.options.noUnselect&&f.api.selection.selectRowByVisibleIndex(0,c),f.selection.selectAll=!1):f.options.multiSelect&&(f.api.selection.selectAllVisibleRows(c),f.selection.selectAll=!0)}}}}]),a.directive("uiGridViewport",["$compile","uiGridConstants","uiGridSelectionConstants","gridUtil","$parse","uiGridSelectionService",function(a,b,c,d,e,f){return{priority:-200,scope:!1,compile:function(a,b){var c=angular.element(a.children().children()[0]),d=c.attr("ng-class"),e="";return e=d?d.slice(0,-1)+",'ui-grid-row-selected': row.isSelected}":"{'ui-grid-row-selected': row.isSelected}",c.attr("ng-class",e),{pre:function(a,b,c,d){},post:function(a,b,c,d){}}}}}]),a.directive("uiGridCell",["$compile","uiGridConstants","uiGridSelectionConstants","gridUtil","$parse","uiGridSelectionService","$timeout",function(a,b,c,d,e,f,g){return{priority:-200,restrict:"A",require:"?^uiGrid",scope:!1,link:function(a,c,d,e){function h(){a.grid.options.enableRowSelection&&a.grid.options.enableFullRowSelection&&(c.addClass("ui-grid-disable-selection"),c.on("touchstart",m),c.on("touchend",n),c.on("click",l),a.registered=!0)}function i(){a.registered&&(c.removeClass("ui-grid-disable-selection"),c.off("touchstart",m),c.off("touchend",n),c.off("click",l),a.registered=!1)}var j=0,k=300;e.grid.api.cellNav&&e.grid.api.cellNav.on.viewPortKeyDown(a,function(b,c){null!==c&&c.row===a.row&&c.col===a.col&&32===b.keyCode&&"selectionRowHeaderCol"===a.col.colDef.name&&(f.toggleRowSelection(a.grid,a.row,b,a.grid.options.multiSelect&&!a.grid.options.modifierKeysToMultiSelect,a.grid.options.noUnselect),a.$apply())});var l=function(b){"ui-grid-icon-minus-squared"!==b.target.className&&"ui-grid-icon-plus-squared"!==b.target.className&&(c.off("touchend",n),b.shiftKey?f.shiftSelect(a.grid,a.row,b,a.grid.options.multiSelect):b.ctrlKey||b.metaKey?f.toggleRowSelection(a.grid,a.row,b,a.grid.options.multiSelect,a.grid.options.noUnselect):f.toggleRowSelection(a.grid,a.row,b,a.grid.options.multiSelect&&!a.grid.options.modifierKeysToMultiSelect,a.grid.options.noUnselect),a.$apply(),g(function(){c.on("touchend",n)},k))},m=function(a){j=(new Date).getTime(),c.off("click",l)},n=function(a){var b=(new Date).getTime(),d=b-j;k>d&&l(a),g(function(){c.on("click",l)},k)};h();var o=a.grid.registerDataChangeCallback(function(){a.grid.options.enableRowSelection&&a.grid.options.enableFullRowSelection&&!a.registered?h():a.grid.options.enableRowSelection&&a.grid.options.enableFullRowSelection||!a.registered||i()},[b.dataChange.OPTIONS]);c.on("$destroy",o)}}}]),a.directive("uiGridGridFooter",["$compile","uiGridConstants","gridUtil",function(a,b,c){return{restrict:"EA",replace:!0,priority:-1e3,require:"^uiGrid",scope:!0,compile:function(b,d){return{pre:function(b,d,e,f){f.grid.options.showGridFooter&&c.getTemplate("ui-grid/gridFooterSelectedItems").then(function(c){var e=angular.element(c),f=a(e)(b);angular.element(d[0].getElementsByClassName("ui-grid-grid-footer")[0]).append(f)})},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.treeBase",["ui.grid"]);a.constant("uiGridTreeBaseConstants",{featureName:"treeBase",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),a.service("uiGridTreeBaseService",["$q","uiGridTreeBaseConstants","gridUtil","GridRow","gridClassFactory","i18nService","uiGridConstants","rowSorter",function(a,b,c,d,e,f,g,h){var i={initializeGrid:function(a,b){a.treeBase={},a.treeBase.numberLevels=0,a.treeBase.expandAll=!1,a.treeBase.tree=[],i.defaultGridOptions(a.options),a.registerRowsProcessor(i.treeRows,410),a.registerColumnBuilder(i.treeBaseColumnBuilder),i.createRowHeader(a);var c={events:{treeBase:{rowExpanded:{},rowCollapsed:{}}},methods:{treeBase:{expandAllRows:function(){i.expandAllRows(a)},collapseAllRows:function(){i.collapseAllRows(a)},toggleRowTreeState:function(b){i.toggleRowTreeState(a,b)},expandRow:function(b){i.expandRow(a,b)},expandRowChildren:function(b){i.expandRowChildren(a,b)},collapseRow:function(b){i.collapseRow(a,b)},collapseRowChildren:function(b){i.collapseRowChildren(a,b)},getTreeExpandedState:function(){return{expandedState:i.getTreeState(a)}},setTreeState:function(b){i.setTreeState(a,b)},getRowChildren:function(a){return a.treeNode.children.map(function(a){return a.row})}}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods)},defaultGridOptions:function(a){a.treeRowHeaderBaseWidth=a.treeRowHeaderBaseWidth||30,a.treeIndent=a.treeIndent||10,a.showTreeRowHeader=a.showTreeRowHeader!==!1,a.showTreeExpandNoChildren=a.showTreeExpandNoChildren!==!1,a.treeRowHeaderAlwaysVisible=a.treeRowHeaderAlwaysVisible!==!1,a.treeCustomAggregations=a.treeCustomAggregations||{},a.enableExpandAll=a.enableExpandAll!==!1},treeBaseColumnBuilder:function(a,b,c){"undefined"!=typeof a.customTreeAggregationFn&&(b.treeAggregationFn=a.customTreeAggregationFn),"undefined"!=typeof a.treeAggregationType&&(b.treeAggregation={type:a.treeAggregationType},"undefined"!=typeof c.treeCustomAggregations[a.treeAggregationType]?(b.treeAggregationFn=c.treeCustomAggregations[a.treeAggregationType].aggregationFn,b.treeAggregationFinalizerFn=c.treeCustomAggregations[a.treeAggregationType].finalizerFn,b.treeAggregation.label=c.treeCustomAggregations[a.treeAggregationType].label):"undefined"!=typeof i.nativeAggregations()[a.treeAggregationType]&&(b.treeAggregationFn=i.nativeAggregations()[a.treeAggregationType].aggregationFn,b.treeAggregation.label=i.nativeAggregations()[a.treeAggregationType].label)),"undefined"!=typeof a.treeAggregationLabel&&("undefined"==typeof b.treeAggregation&&(b.treeAggregation={}),b.treeAggregation.label=a.treeAggregationLabel),b.treeAggregationUpdateEntity=a.treeAggregationUpdateEntity!==!1,"undefined"==typeof b.customTreeAggregationFinalizerFn&&(b.customTreeAggregationFinalizerFn=a.customTreeAggregationFinalizerFn)},createRowHeader:function(a){var c={name:b.rowHeaderColName,displayName:"",width:a.options.treeRowHeaderBaseWidth,minWidth:10,cellTemplate:"ui-grid/treeBaseRowHeader",headerCellTemplate:"ui-grid/treeBaseHeaderCell",enableColumnResizing:!1,enableColumnMenu:!1,exporterSuppressExport:!0,allowCellFocus:!0};c.visible=a.options.treeRowHeaderAlwaysVisible,a.addRowHeaderColumn(c,-100)},expandAllRows:function(a){a.treeBase.tree.forEach(function(c){i.setAllNodes(a,c,b.EXPANDED)}),a.treeBase.expandAll=!0,a.queueGridRefresh()},collapseAllRows:function(a){a.treeBase.tree.forEach(function(c){i.setAllNodes(a,c,b.COLLAPSED)}),a.treeBase.expandAll=!1,a.queueGridRefresh()},setAllNodes:function(a,c,d){"undefined"!=typeof c.state&&c.state!==d&&(c.state=d,d===b.EXPANDED?a.api.treeBase.raise.rowExpanded(c.row):a.api.treeBase.raise.rowCollapsed(c.row)),c.children&&c.children.forEach(function(b){i.setAllNodes(a,b,d)})},toggleRowTreeState:function(a,c){"undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0||(c.treeNode.state===b.EXPANDED?i.collapseRow(a,c):i.expandRow(a,c),a.queueGridRefresh())},expandRow:function(a,c){"undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0||c.treeNode.state!==b.EXPANDED&&(c.treeNode.state=b.EXPANDED,a.api.treeBase.raise.rowExpanded(c),a.treeBase.expandAll=i.allExpanded(a.treeBase.tree),a.queueGridRefresh())},expandRowChildren:function(a,c){"undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0||(i.setAllNodes(a,c.treeNode,b.EXPANDED),a.treeBase.expandAll=i.allExpanded(a.treeBase.tree),a.queueGridRefresh())},collapseRow:function(a,c){"undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0||c.treeNode.state!==b.COLLAPSED&&(c.treeNode.state=b.COLLAPSED,a.treeBase.expandAll=!1,a.api.treeBase.raise.rowCollapsed(c),a.queueGridRefresh())},collapseRowChildren:function(a,c){"undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0||(i.setAllNodes(a,c.treeNode,b.COLLAPSED),a.treeBase.expandAll=!1,a.queueGridRefresh())},allExpanded:function(a){var b=!0;return a.forEach(function(a){i.allExpandedInternal(a)||(b=!1)}),b},allExpandedInternal:function(a){if(a.children&&a.children.length>0){if(a.state===b.COLLAPSED)return!1;var c=!0;return a.children.forEach(function(a){i.allExpandedInternal(a)||(c=!1)}),c}return!0},treeRows:function(a){if(0===a.length)return a;var c=this;b.EXPANDED;return c.treeBase.tree=i.createTree(c,a),i.updateRowHeaderWidth(c),i.sortTree(c),i.fixFilter(c),i.renderTree(c.treeBase.tree)},updateRowHeaderWidth:function(a){var c=a.getColumn(b.rowHeaderColName),d=a.options.treeRowHeaderBaseWidth+a.options.treeIndent*Math.max(a.treeBase.numberLevels-1,0);c&&d!==c.width&&(c.width=d,a.queueRefresh());var e=!0;a.options.showTreeRowHeader===!1&&(e=!1),a.options.treeRowHeaderAlwaysVisible===!1&&a.treeBase.numberLevels<=0&&(e=!1),c.visible!==e&&(c.visible=e,c.colDef.visible=e,a.queueGridRefresh())},renderTree:function(a){var c=[];return a.forEach(function(a){a.row.visible&&c.push(a.row),a.state===b.EXPANDED&&a.children&&a.children.length>0&&(c=c.concat(i.renderTree(a.children)))}),c},createTree:function(a,c){var d,e=-1,f=[];a.treeBase.tree=[],a.treeBase.numberLevels=0;var g=i.getAggregations(a),h=function(c){if("undefined"!=typeof c.entity.$$treeLevel&&c.treeLevel!==c.entity.$$treeLevel&&(c.treeLevel=c.entity.$$treeLevel),c.treeLevel<=e){for(;c.treeLevel<=e;){var h=f.pop();i.finaliseAggregations(h),e--}d=f.length>0?i.setCurrentState(f):b.EXPANDED}("undefined"==typeof c.treeLevel||null===c.treeLevel||c.treeLevel<0)&&c.visible&&i.aggregate(a,c,f),i.addOrUseNode(a,c,f,g),"undefined"!=typeof c.treeLevel&&null!==c.treeLevel&&c.treeLevel>=0&&(f.push(c),e++,d=i.setCurrentState(f)),a.treeBase.numberLevels<c.treeLevel+1&&(a.treeBase.numberLevels=c.treeLevel+1)};for(c.forEach(h);f.length>0;){var j=f.pop();i.finaliseAggregations(j)}return a.treeBase.tree},addOrUseNode:function(a,c,d,e){var f=[];e.forEach(function(a){f.push(i.buildAggregationObject(a.col))});var g={state:b.COLLAPSED,row:c,parentRow:null,aggregations:f,children:[]};c.treeNode&&(g.state=c.treeNode.state),d.length>0&&(g.parentRow=d[d.length-1]),c.treeNode=g,0===d.length?a.treeBase.tree.push(g):d[d.length-1].treeNode.children.push(g)},setCurrentState:function(a){var c=b.EXPANDED;return a.forEach(function(a){a.treeNode.state===b.COLLAPSED&&(c=b.COLLAPSED)}),c},sortTree:function(a){a.columns.forEach(function(a){a.sort&&a.sort.ignoreSort&&delete a.sort.ignoreSort}),a.treeBase.tree=i.sortInternal(a,a.treeBase.tree)},sortInternal:function(a,c){var d=c.map(function(a){return a.row});d=h.sort(a,d,a.columns);var e=d.map(function(a){return a.treeNode});return e.forEach(function(c){c.state===b.EXPANDED&&c.children&&c.children.length>0&&(c.children=i.sortInternal(a,c.children))}),e},fixFilter:function(a){var b;a.treeBase.tree.forEach(function(a){a.children&&a.children.length>0&&(b=a.row.visible,i.fixFilterInternal(a.children,b))})},fixFilterInternal:function(a,b){return a.forEach(function(a){a.row.visible&&!b&&(i.setParentsVisible(a),b=!0),a.children&&a.children.length>0&&i.fixFilterInternal(a.children,b&&a.row.visible)&&(b=!0)}),b},setParentsVisible:function(a){for(;a.parentRow;)a.parentRow.visible=!0,a=a.parentRow.treeNode},buildAggregationObject:function(a){var b={col:a};return a.treeAggregation&&a.treeAggregation.type&&(b.type=a.treeAggregation.type),a.treeAggregation&&a.treeAggregation.label&&(b.label=a.treeAggregation.label),b},getAggregations:function(a){var b=[];return a.columns.forEach(function(c){"undefined"!=typeof c.treeAggregationFn&&(b.push(i.buildAggregationObject(c)),a.options.showColumnFooter&&"undefined"==typeof c.colDef.aggregationType&&c.treeAggregation&&(c.treeFooterAggregation=i.buildAggregationObject(c),c.aggregationType=i.treeFooterAggregationType))}),b},aggregate:function(a,b,c){0===c.length&&b.treeNode&&b.treeNode.aggregations&&b.treeNode.aggregations.forEach(function(c){if("undefined"!=typeof c.col.treeFooterAggregation){var d=a.getCellValue(b,c.col),e=Number(d);c.col.treeAggregationFn(c.col.treeFooterAggregation,d,e,b)}}),c.forEach(function(c,d){c.treeNode.aggregations&&c.treeNode.aggregations.forEach(function(c){var e=a.getCellValue(b,c.col),f=Number(e);c.col.treeAggregationFn(c,e,f,b),0===d&&"undefined"!=typeof c.col.treeFooterAggregation&&c.col.treeAggregationFn(c.col.treeFooterAggregation,e,f,b)})})},nativeAggregations:function(){var a={count:{label:f.get().aggregation.count,menuTitle:f.get().grouping.aggregate_count,aggregationFn:function(a,b,c){"undefined"==typeof a.value?a.value=1:a.value++}},sum:{label:f.get().aggregation.sum,menuTitle:f.get().grouping.aggregate_sum,aggregationFn:function(a,b,c){isNaN(c)||("undefined"==typeof a.value?a.value=c:a.value+=c)}},min:{label:f.get().aggregation.min,menuTitle:f.get().grouping.aggregate_min,aggregationFn:function(a,b,c){"undefined"==typeof a.value?a.value=b:"undefined"!=typeof b&&null!==b&&(b<a.value||null===a.value)&&(a.value=b)}},max:{label:f.get().aggregation.max,menuTitle:f.get().grouping.aggregate_max,aggregationFn:function(a,b,c){"undefined"==typeof a.value?a.value=b:"undefined"!=typeof b&&null!==b&&(b>a.value||null===a.value)&&(a.value=b)}},avg:{label:f.get().aggregation.avg,menuTitle:f.get().grouping.aggregate_avg,aggregationFn:function(a,b,c){"undefined"==typeof a.count?a.count=1:a.count++,isNaN(c)||("undefined"==typeof a.value||"undefined"==typeof a.sum?(a.value=c,a.sum=c):(a.sum+=c,a.value=a.sum/a.count))}}};return a},finaliseAggregation:function(a,b){b.col.treeAggregationUpdateEntity&&"undefined"!=typeof a&&"undefined"!=typeof a.entity["$$"+b.col.uid]&&angular.extend(b,a.entity["$$"+b.col.uid]),"function"==typeof b.col.treeAggregationFinalizerFn&&b.col.treeAggregationFinalizerFn(b),"function"==typeof b.col.customTreeAggregationFinalizerFn&&b.col.customTreeAggregationFinalizerFn(b),"undefined"==typeof b.rendered&&(b.rendered=b.label?b.label+b.value:b.value)},finaliseAggregations:function(a){null!=a&&"undefined"!=typeof a.treeNode.aggregations&&a.treeNode.aggregations.forEach(function(b){if(i.finaliseAggregation(a,b),b.col.treeAggregationUpdateEntity){var c={};angular.forEach(b,function(a,d){b.hasOwnProperty(d)&&"col"!==d&&(c[d]=a)}),a.entity["$$"+b.col.uid]=c}})},treeFooterAggregationType:function(a,b){return i.finaliseAggregation(void 0,b.treeFooterAggregation),"undefined"==typeof b.treeFooterAggregation.value||null===b.treeFooterAggregation.rendered?"":b.treeFooterAggregation.rendered}};return i}]),a.directive("uiGridTreeBaseRowHeaderButtons",["$templateCache","uiGridTreeBaseService",function(a,b){return{replace:!0,restrict:"E",template:a.get("ui-grid/treeBaseRowHeaderButtons"),scope:!0,require:"^uiGrid",link:function(a,c,d,e){var f=e.grid;a.treeButtonClick=function(a,c){b.toggleRowTreeState(f,a,c)}}}}]),a.directive("uiGridTreeBaseExpandAllButtons",["$templateCache","uiGridTreeBaseService",function(a,b){return{replace:!0,restrict:"E",template:a.get("ui-grid/treeBaseExpandAllButtons"),scope:!1,link:function(a,c,d,e){var f=a.col.grid;a.headerButtonClick=function(a,c){f.treeBase.expandAll?b.collapseAllRows(f,c):b.expandAllRows(f,c)}}}}]),a.directive("uiGridViewport",["$compile","uiGridConstants","gridUtil","$parse",function(a,b,c,d){return{priority:-200,scope:!1,compile:function(a,b){var c=angular.element(a.children().children()[0]),d=c.attr("ng-class"),e="";return e=d?d.slice(0,-1)+",'ui-grid-tree-header-row': row.treeLevel > -1}":"{'ui-grid-tree-header-row': row.treeLevel > -1}",c.attr("ng-class",e),{pre:function(a,b,c,d){},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.treeView",["ui.grid","ui.grid.treeBase"]);a.constant("uiGridTreeViewConstants",{featureName:"treeView",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),a.service("uiGridTreeViewService",["$q","uiGridTreeViewConstants","uiGridTreeBaseConstants","uiGridTreeBaseService","gridUtil","GridRow","gridClassFactory","i18nService","uiGridConstants",function(a,b,c,d,e,f,g,h,i){var j={initializeGrid:function(a,b){d.initializeGrid(a,b),a.treeView={},a.registerRowsProcessor(j.adjustSorting,60);var c={events:{treeView:{}},methods:{treeView:{}}};a.api.registerEventsFromObject(c.events),a.api.registerMethodsFromObject(c.methods)},defaultGridOptions:function(a){a.enableTreeView=a.enableTreeView!==!1},adjustSorting:function(a){var b=this;return b.columns.forEach(function(a){a.sort&&(a.sort.ignoreSort=!0)}),a}};return j}]),a.directive("uiGridTreeView",["uiGridTreeViewConstants","uiGridTreeViewService","$templateCache",function(a,b,c){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){e.grid.options.enableTreeView!==!1&&b.initializeGrid(e.grid,a)},post:function(a,b,c,d){}}}}}])}(),function(){"use strict";var a=angular.module("ui.grid.validate",["ui.grid"]);a.service("uiGridValidateService",["$sce","$q","$http","i18nService","uiGridConstants",function(a,b,c,d,e){var f={validatorFactories:{},setExternalFactoryFunction:function(a){f.externalFactoryFunction=a},clearExternalFactory:function(){delete f.externalFactoryFunction},getValidatorFromExternalFactory:function(a,b){return f.externalFactoryFunction(a,b).validatorFactory(b)},getMessageFromExternalFactory:function(a,b){return f.externalFactoryFunction(a,b).messageFunction(b)},setValidator:function(a,b,c){f.validatorFactories[a]={validatorFactory:b,messageFunction:c}},getValidator:function(a,b){if(f.externalFactoryFunction){var c=f.getValidatorFromExternalFactory(a,b);if(c)return c}if(!f.validatorFactories[a])throw"Invalid validator name: "+a;return f.validatorFactories[a].validatorFactory(b)},getMessage:function(a,b){if(f.externalFactoryFunction){var c=f.getMessageFromExternalFactory(a,b);if(c)return c}return f.validatorFactories[a].messageFunction(b)},isInvalid:function(a,b){return a["$$invalid"+b.name]},setInvalid:function(a,b){a["$$invalid"+b.name]=!0},setValid:function(a,b){delete a["$$invalid"+b.name]},setError:function(a,b,c){a["$$errors"+b.name]||(a["$$errors"+b.name]={}),a["$$errors"+b.name][c]=!0},clearError:function(a,b,c){a["$$errors"+b.name]&&c in a["$$errors"+b.name]&&delete a["$$errors"+b.name][c]},getErrorMessages:function(a,b){var c=[];return a["$$errors"+b.name]&&0!==Object.keys(a["$$errors"+b.name]).length?(Object.keys(a["$$errors"+b.name]).sort().forEach(function(a){c.push(f.getMessage(a,b.validators[a]))}),c):c},getFormattedErrors:function(b,c){var e="",g=f.getErrorMessages(b,c);return g.length?(g.forEach(function(a){e+=a+"<br/>"}),a.trustAsHtml("<p><b>"+d.getSafeText("validate.error")+"</b></p>"+e)):void 0},getTitleFormattedErrors:function(b,c){var e="\n",g="",h=f.getErrorMessages(b,c);return h.length?(h.forEach(function(a){g+=a+e}),a.trustAsHtml(d.getSafeText("validate.error")+e+g)):void 0},runValidators:function(a,c,d,e,g){if(d!==e){if("undefined"==typeof c.name||!c.name)throw new Error("colDef.name is required to perform validation");f.setValid(a,c);var h=function(a,b,c){return function(h){h||(f.setInvalid(a,b),f.setError(a,b,c),g&&g.api.validate.raise.validationFailed(a,b,d,e))}},i=[];for(var j in c.validators){f.clearError(a,c,j);var k=f.getValidator(j,c.validators[j]),l=b.when(k(e,d,a,c)).then(h(a,c,j));i.push(l)}return b.all(i)}},createDefaultValidators:function(){f.setValidator("minLength",function(a){return function(b,c,d,e){return void 0===c||null===c||""===c?!0:c.length>=a}},function(a){return d.getSafeText("validate.minLength").replace("THRESHOLD",a)}),f.setValidator("maxLength",function(a){return function(b,c,d,e){return void 0===c||null===c||""===c?!0:c.length<=a}},function(a){return d.getSafeText("validate.maxLength").replace("THRESHOLD",a)}),f.setValidator("required",function(a){return function(b,c,d,e){return a?!(void 0===c||null===c||""===c):!0}},function(a){return d.getSafeText("validate.required")})},initializeGrid:function(a,b){b.validate={isInvalid:f.isInvalid,getFormattedErrors:f.getFormattedErrors,getTitleFormattedErrors:f.getTitleFormattedErrors,runValidators:f.runValidators};var c={events:{validate:{validationFailed:function(a,b,c,d){}}},methods:{validate:{isInvalid:function(a,c){return b.validate.isInvalid(a,c)},getErrorMessages:function(a,c){return b.validate.getErrorMessages(a,c)},getFormattedErrors:function(a,c){return b.validate.getFormattedErrors(a,c)},getTitleFormattedErrors:function(a,c){return b.validate.getTitleFormattedErrors(a,c)}}}};b.api.registerEventsFromObject(c.events),b.api.registerMethodsFromObject(c.methods),b.edit&&b.api.edit.on.afterCellEdit(a,function(a,c,d,e){b.validate.runValidators(a,c,d,e,b)}),f.createDefaultValidators()}};return f}]),a.directive("uiGridValidate",["gridUtil","uiGridValidateService",function(a,b){return{priority:0,replace:!0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(a,c,d,e){b.initializeGrid(a,e.grid)},post:function(a,b,c,d){}}}}}])}(),angular.module("ui.grid").run(["$templateCache",function(a){"use strict";a.put("ui-grid/ui-grid-filter",'<div class="ui-grid-filter-container" ng-style="col.extraStyle" ng-repeat="colFilter in col.filters" ng-class="{\'ui-grid-filter-cancel-button-hidden\' : colFilter.disableCancelFilterButton === true }"><div ng-if="colFilter.type !== \'select\'"><input type="text" class="ui-grid-filter-input ui-grid-filter-input-{{$index}}" ng-model="colFilter.term" ng-attr-placeholder="{{colFilter.placeholder || \'\'}}" aria-label="{{colFilter.ariaLabel || aria.defaultFilterLabel}}"><div role="button" class="ui-grid-filter-button" ng-click="removeFilter(colFilter, $index)" ng-if="!colFilter.disableCancelFilterButton" ng-disabled="colFilter.term === undefined || colFilter.term === null || colFilter.term === \'\'" ng-show="colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== \'\'"><i class="ui-grid-icon-cancel" ui-grid-one-bind-aria-label="aria.removeFilter">&nbsp;</i></div></div><div ng-if="colFilter.type === \'select\'"><select class="ui-grid-filter-select ui-grid-filter-input-{{$index}}" ng-model="colFilter.term" ng-show="colFilter.selectOptions.length > 0" ng-attr-placeholder="{{colFilter.placeholder || aria.defaultFilterLabel}}" aria-label="{{colFilter.ariaLabel || \'\'}}" ng-options="option.value as option.label for option in colFilter.selectOptions"><option value=""></option></select><div role="button" class="ui-grid-filter-button-select" ng-click="removeFilter(colFilter, $index)" ng-if="!colFilter.disableCancelFilterButton" ng-disabled="colFilter.term === undefined || colFilter.term === null || colFilter.term === \'\'" ng-show="colFilter.term !== undefined && colFilter.term != null"><i class="ui-grid-icon-cancel" ui-grid-one-bind-aria-label="aria.removeFilter">&nbsp;</i></div></div></div>'),
+a.put("ui-grid/ui-grid-footer",'<div class="ui-grid-footer-panel ui-grid-footer-aggregates-row"><!-- tfooter --><div class="ui-grid-footer ui-grid-footer-viewport"><div class="ui-grid-footer-canvas"><div class="ui-grid-footer-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()"><div role="row" class="ui-grid-footer-cell-row"><div ui-grid-footer-cell role="gridcell" ng-repeat="col in colContainer.renderedColumns track by col.uid" col="col" render-index="$index" class="ui-grid-footer-cell ui-grid-clearfix"></div></div></div></div></div></div>'),a.put("ui-grid/ui-grid-grid-footer",'<div class="ui-grid-footer-info ui-grid-grid-footer"><span>{{\'search.totalItems\' | t}} {{grid.rows.length}}</span> <span ng-if="grid.renderContainers.body.visibleRowCache.length !== grid.rows.length" class="ngLabel">({{"search.showingItems" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>'),a.put("ui-grid/ui-grid-group-panel",'<div class="ui-grid-group-panel"><div ui-t="groupPanel.description" class="description" ng-show="groupings.length == 0"></div><ul ng-show="groupings.length > 0" class="ngGroupList"><li class="ngGroupItem" ng-repeat="group in configGroups"><span class="ngGroupElement"><span class="ngGroupName">{{group.displayName}} <span ng-click="removeGroup($index)" class="ngRemoveGroup">x</span></span> <span ng-hide="$last" class="ngGroupArrow"></span></span></li></ul></div>'),a.put("ui-grid/ui-grid-header",'<div role="rowgroup" class="ui-grid-header"><!-- theader --><div class="ui-grid-top-panel"><div class="ui-grid-header-viewport"><div class="ui-grid-header-canvas"><div class="ui-grid-header-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()"><div role="row" class="ui-grid-header-cell-row"><div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns track by col.uid" ui-grid-header-cell col="col" render-index="$index"></div></div></div></div></div></div></div>'),a.put("ui-grid/ui-grid-menu-button",'<div class="ui-grid-menu-button"><div role="button" ui-grid-one-bind-id-grid="\'grid-menu\'" class="ui-grid-icon-container" ng-click="toggleMenu()" aria-haspopup="true"><i class="ui-grid-icon-menu" ui-grid-one-bind-aria-label="i18n.aria.buttonLabel">&nbsp;</i></div><div ui-grid-menu menu-items="menuItems"></div></div>'),a.put("ui-grid/ui-grid-no-header",'<div class="ui-grid-top-panel"></div>'),a.put("ui-grid/ui-grid-row","<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"),a.put("ui-grid/ui-grid",'<div ui-i18n="en" class="ui-grid"><!-- TODO (c0bra): add "scoped" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\n /* Styles for the grid */\n }\n\n .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n height: {{ grid.options.rowHeight }}px;\n }\n\n .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && \'1\') || \'0\' }}px;\n }\n\n {{ grid.verticalScrollbarStyles }}\n {{ grid.horizontalScrollbarStyles }}\n\n /*\n .ui-grid[dir=rtl] .ui-grid-viewport {\n padding-left: {{ grid.verticalScrollbarWidth }}px;\n }\n */\n\n {{ grid.customStyles }}</style><div class="ui-grid-contents-wrapper"><div ui-grid-menu-button ng-if="grid.options.enableGridMenu"></div><div ng-if="grid.hasLeftContainer()" style="width: 0" ui-grid-pinned-container="\'left\'"></div><div ui-grid-render-container container-id="\'body\'" col-container-name="\'body\'" row-container-name="\'body\'" bind-scroll-horizontal="true" bind-scroll-vertical="true" enable-horizontal-scrollbar="grid.options.enableHorizontalScrollbar" enable-vertical-scrollbar="grid.options.enableVerticalScrollbar"></div><div ng-if="grid.hasRightContainer()" style="width: 0" ui-grid-pinned-container="\'right\'"></div><div ui-grid-grid-footer ng-if="grid.options.showGridFooter"></div><div ui-grid-column-menu ng-if="grid.options.enableColumnMenus"></div><div ng-transclude></div></div></div>'),a.put("ui-grid/uiGridCell",'<div class="ui-grid-cell-contents" title="TOOLTIP">{{COL_FIELD CUSTOM_FILTERS}}</div>'),a.put("ui-grid/uiGridColumnMenu",'<div class="ui-grid-column-menu"><div ui-grid-menu menu-items="menuItems"><!-- <div class="ui-grid-column-menu">\n <div class="inner" ng-show="menuShown">\n <ul>\n <div ng-show="grid.options.enableSorting">\n <li ng-click="sortColumn($event, asc)" ng-class="{ \'selected\' : col.sort.direction == asc }"><i class="ui-grid-icon-sort-alt-up"></i> Sort Ascending</li>\n <li ng-click="sortColumn($event, desc)" ng-class="{ \'selected\' : col.sort.direction == desc }"><i class="ui-grid-icon-sort-alt-down"></i> Sort Descending</li>\n <li ng-show="col.sort.direction" ng-click="unsortColumn()"><i class="ui-grid-icon-cancel"></i> Remove Sort</li>\n </div>\n </ul>\n </div>\n </div> --></div></div>'),a.put("ui-grid/uiGridFooterCell",'<div class="ui-grid-cell-contents" col-index="renderIndex"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>'),a.put("ui-grid/uiGridHeaderCell",'<div role="columnheader" ng-class="{ \'sortable\': sortable }" ui-grid-one-bind-aria-labelledby-grid="col.uid + \'-header-text \' + col.uid + \'-sortdir-text\'" aria-sort="{{col.sort.direction == asc ? \'ascending\' : ( col.sort.direction == desc ? \'descending\' : (!col.sort.direction ? \'none\' : \'other\'))}}"><div role="button" tabindex="0" class="ui-grid-cell-contents ui-grid-header-cell-primary-focus" col-index="renderIndex" title="TOOLTIP"><span class="ui-grid-header-cell-label" ui-grid-one-bind-id-grid="col.uid + \'-header-text\'">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid="col.uid + \'-sortdir-text\'" ui-grid-visible="col.sort.direction" aria-label="{{getSortDirectionAriaLabel()}}"><i ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }" title="{{isSortPriorityVisible() ? i18n.headerCell.priority + \' \' + ( col.sort.priority + 1 ) : null}}" aria-hidden="true"></i> <sub ui-grid-visible="isSortPriorityVisible()" class="ui-grid-sort-priority-number">{{col.sort.priority + 1}}</sub></span></div><div role="button" tabindex="0" ui-grid-one-bind-id-grid="col.uid + \'-menu-button\'" class="ui-grid-column-menu-button" ng-if="grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false" ng-click="toggleMenu($event)" ng-class="{\'ui-grid-column-menu-button-last-col\': isLastCol}" ui-grid-one-bind-aria-label="i18n.headerCell.aria.columnMenuButtonLabel" aria-haspopup="true"><i class="ui-grid-icon-angle-down" aria-hidden="true">&nbsp;</i></div><div ui-grid-filter></div></div>'),a.put("ui-grid/uiGridMenu",'<div class="ui-grid-menu" ng-if="shown"><style ui-grid-style>{{dynamicStyles}}</style><div class="ui-grid-menu-mid" ng-show="shownMid"><div class="ui-grid-menu-inner"><ul role="menu" class="ui-grid-menu-items"><li ng-repeat="item in menuItems" role="menuitem" ui-grid-menu-item ui-grid-one-bind-id="\'menuitem-\'+$index" action="item.action" name="item.title" active="item.active" icon="item.icon" shown="item.shown" context="item.context" template-url="item.templateUrl" leave-open="item.leaveOpen" screen-reader-only="item.screenReaderOnly"></li></ul></div></div></div>'),a.put("ui-grid/uiGridMenuItem",'<button type="button" class="ui-grid-menu-item" ng-click="itemAction($event, title)" ng-show="itemShown()" ng-class="{ \'ui-grid-menu-item-active\': active(), \'ui-grid-sr-only\': (!focus && screenReaderOnly) }" aria-pressed="{{active()}}" tabindex="0" ng-focus="focus=true" ng-blur="focus=false"><i ng-class="icon" aria-hidden="true">&nbsp;</i> {{ name }}</button>'),a.put("ui-grid/uiGridRenderContainer","<div role=\"grid\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"),a.put("ui-grid/uiGridViewport",'<div role="rowgroup" class="ui-grid-viewport" ng-style="colContainer.getViewportStyle()"><!-- tbody --><div class="ui-grid-canvas"><div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="Viewport.rowStyle(rowRenderIndex)"><div role="row" ui-grid-row="row" row-render-index="rowRenderIndex"></div></div></div></div>'),a.put("ui-grid/cellEditor",'<div><form name="inputForm"><input type="INPUT_TYPE" ng-class="\'colt\' + col.uid" ui-grid-editor ng-model="MODEL_COL_FIELD"></form></div>'),a.put("ui-grid/dropdownEditor",'<div><form name="inputForm"><select ng-class="\'colt\' + col.uid" ui-grid-edit-dropdown ng-model="MODEL_COL_FIELD" ng-options="field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray"></select></form></div>'),a.put("ui-grid/fileChooserEditor",'<div><form name="inputForm"><input ng-class="\'colt\' + col.uid" ui-grid-edit-file-chooser type="file" id="files" name="files[]" ng-model="MODEL_COL_FIELD"></form></div>'),a.put("ui-grid/emptyBaseLayerContainer",'<div class="ui-grid-empty-base-layer-container ui-grid-canvas"><div class="ui-grid-row" ng-repeat="(rowRenderIndex, row) in grid.baseLayer.emptyRows track by $index" ng-style="Viewport.rowStyle(rowRenderIndex)"><div><div><div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell {{ col.getColClass(false) }}"></div></div></div></div></div>'),a.put("ui-grid/expandableRow",'<div ui-grid-expandable-row ng-if="expandableRow.shouldRenderExpand()" class="expandableRow" style="float:left; margin-top: 1px; margin-bottom: 1px" ng-style="{width: (grid.renderContainers.body.getCanvasWidth()) + \'px\', height: row.expandedRowHeight + \'px\'}"></div>'),a.put("ui-grid/expandableRowHeader",'<div class="ui-grid-row-header-cell ui-grid-expandable-buttons-cell"><div class="ui-grid-cell-contents"><i ng-if="!row.groupHeader==true" ng-class="{ \'ui-grid-icon-plus-squared\' : !row.isExpanded, \'ui-grid-icon-minus-squared\' : row.isExpanded }" ng-click="grid.api.expandable.toggleRowExpansion(row.entity)"></i></div></div>'),a.put("ui-grid/expandableScrollFiller","<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\"><i class=\"ui-grid-icon-spin5 ui-grid-animate-spin\" ng-style=\"{'margin-top': ( row.expandedRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\"></i></div>"),a.put("ui-grid/expandableTopRowHeader",'<div class="ui-grid-row-header-cell ui-grid-expandable-buttons-cell"><div class="ui-grid-cell-contents"><i ng-class="{ \'ui-grid-icon-plus-squared\' : !grid.expandable.expandedAll, \'ui-grid-icon-minus-squared\' : grid.expandable.expandedAll }" ng-click="grid.api.expandable.toggleAllRows()"></i></div></div>'),a.put("ui-grid/csvLink",'<span class="ui-grid-exporter-csv-link-span"><a href="data:text/csv;charset=UTF-8,CSV_CONTENT" download="FILE_NAME">LINK_LABEL</a></span>'),a.put("ui-grid/importerMenuItem",'<li class="ui-grid-menu-item"><form><input class="ui-grid-importer-file-chooser" type="file" id="files" name="files[]"></form></li>'),a.put("ui-grid/importerMenuItemContainer","<div ui-grid-importer-menu-item></div>"),a.put("ui-grid/pagination",'<div role="contentinfo" class="ui-grid-pager-panel" ui-grid-pager ng-show="grid.options.enablePaginationControls"><div role="navigation" class="ui-grid-pager-container"><div role="menubar" class="ui-grid-pager-control"><button type="button" role="menuitem" class="ui-grid-pager-first" ui-grid-one-bind-title="aria.pageToFirst" ui-grid-one-bind-aria-label="aria.pageToFirst" ng-click="pageFirstPageClick()" ng-disabled="cantPageBackward()"><div ng-class="grid.isRTL() ? \'last-triangle\' : \'first-triangle\'"><div ng-class="grid.isRTL() ? \'last-bar-rtl\' : \'first-bar\'"></div></div></button> <button type="button" role="menuitem" class="ui-grid-pager-previous" ui-grid-one-bind-title="aria.pageBack" ui-grid-one-bind-aria-label="aria.pageBack" ng-click="pagePreviousPageClick()" ng-disabled="cantPageBackward()"><div ng-class="grid.isRTL() ? \'last-triangle prev-triangle\' : \'first-triangle prev-triangle\'"></div></button> <input type="number" ui-grid-one-bind-title="aria.pageSelected" ui-grid-one-bind-aria-label="aria.pageSelected" class="ui-grid-pager-control-input" ng-model="grid.options.paginationCurrentPage" min="1" max="{{ paginationApi.getTotalPages() }}" required> <span class="ui-grid-pager-max-pages-number" ng-show="paginationApi.getTotalPages() > 0"><abbr ui-grid-one-bind-title="paginationOf">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type="button" role="menuitem" class="ui-grid-pager-next" ui-grid-one-bind-title="aria.pageForward" ui-grid-one-bind-aria-label="aria.pageForward" ng-click="pageNextPageClick()" ng-disabled="cantPageForward()"><div ng-class="grid.isRTL() ? \'first-triangle next-triangle\' : \'last-triangle next-triangle\'"></div></button> <button type="button" role="menuitem" class="ui-grid-pager-last" ui-grid-one-bind-title="aria.pageToLast" ui-grid-one-bind-aria-label="aria.pageToLast" ng-click="pageLastPageClick()" ng-disabled="cantPageToLast()"><div ng-class="grid.isRTL() ? \'first-triangle\' : \'last-triangle\'"><div ng-class="grid.isRTL() ? \'first-bar-rtl\' : \'last-bar\'"></div></div></button></div><div class="ui-grid-pager-row-count-picker" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination"><select ui-grid-one-bind-aria-labelledby-grid="\'items-per-page-label\'" ng-model="grid.options.paginationPageSize" ng-options="o as o for o in grid.options.paginationPageSizes"></select><span ui-grid-one-bind-id-grid="\'items-per-page-label\'" class="ui-grid-pager-row-count-label">&nbsp;{{sizesLabel}}</span></div><span ng-if="grid.options.paginationPageSizes.length <= 1" class="ui-grid-pager-row-count-label">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class="ui-grid-pager-count-container"><div class="ui-grid-pager-count"><span ng-show="grid.options.totalItems > 0">{{ 1 + paginationApi.getFirstRowIndex() }} <abbr ui-grid-one-bind-title="paginationThrough">-</abbr> {{ 1 + paginationApi.getLastRowIndex() }} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>'),a.put("ui-grid/columnResizer",'<div ui-grid-column-resizer ng-if="grid.options.enableColumnResizing" class="ui-grid-column-resizer" col="col" position="right" render-index="renderIndex" unselectable="on"></div>'),a.put("ui-grid/gridFooterSelectedItems",'<span ng-if="grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected">({{"search.selectedItems" | t}} {{grid.selection.selectedCount}})</span>'),a.put("ui-grid/selectionHeaderCell",'<div><!-- <div class="ui-grid-vertical-bar">&nbsp;</div> --><div class="ui-grid-cell-contents" col-index="renderIndex"><ui-grid-selection-select-all-buttons ng-if="grid.options.enableSelectAll"></ui-grid-selection-select-all-buttons></div></div>'),a.put("ui-grid/selectionRowHeader",'<div class="ui-grid-disable-selection"><div class="ui-grid-cell-contents"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>'),a.put("ui-grid/selectionRowHeaderButtons",'<div class="ui-grid-selection-row-header-buttons ui-grid-icon-ok" ng-class="{\'ui-grid-row-selected\': row.isSelected}" ng-click="selectButtonClick(row, $event)">&nbsp;</div>'),a.put("ui-grid/selectionSelectAllButtons",'<div class="ui-grid-selection-row-header-buttons ui-grid-icon-ok" ng-class="{\'ui-grid-all-selected\': grid.selection.selectAll}" ng-click="headerButtonClick($event)"></div>'),a.put("ui-grid/treeBaseExpandAllButtons",'<div class="ui-grid-tree-base-row-header-buttons" ng-class="{\'ui-grid-icon-minus-squared\': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, \'ui-grid-icon-plus-squared\': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}" ng-click="headerButtonClick($event)"></div>'),a.put("ui-grid/treeBaseHeaderCell",'<div><div class="ui-grid-cell-contents" col-index="renderIndex"><ui-grid-tree-base-expand-all-buttons ng-if="grid.options.enableExpandAll"></ui-grid-tree-base-expand-all-buttons></div></div>'),a.put("ui-grid/treeBaseRowHeader",'<div class="ui-grid-cell-contents"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>'),a.put("ui-grid/treeBaseRowHeaderButtons","<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\" ng-click=\"treeButtonClick(row, $event)\"><i ng-class=\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\" ng-style=\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\"></i> &nbsp;</div>"),a.put("ui-grid/cellTitleValidator",'<div class="ui-grid-cell-contents" ng-class="{invalid:grid.validate.isInvalid(row.entity,col.colDef)}" title="{{grid.validate.getTitleFormattedErrors(row.entity,col.colDef)}}">{{COL_FIELD CUSTOM_FILTERS}}</div>'),a.put("ui-grid/cellTooltipValidator",'<div class="ui-grid-cell-contents" ng-class="{invalid:grid.validate.isInvalid(row.entity,col.colDef)}" tooltip-html-unsafe="{{grid.validate.getFormattedErrors(row.entity,col.colDef)}}" tooltip-enable="grid.validate.isInvalid(row.entity,col.colDef)" tooltip-append-to-body="true" tooltip-placement="top" title="TOOLTIP">{{COL_FIELD CUSTOM_FILTERS}}</div>')}]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.svg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.svg
new file mode 100644
index 00000000..9d2e03c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata>
+<defs>
+<font id="ui-grid" horiz-adv-x="1000" >
+<font-face font-family="ui-grid" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
+<missing-glyph horiz-adv-x="1000" />
+<glyph glyph-name="plus-squared" unicode="&#xc350;" d="M714 314v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="minus-squared" unicode="&#xc351;" d="M714 314v72q0 14-10 25t-25 10h-500q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h500q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="search" unicode="&#xc352;" d="M643 386q0 103-73 176t-177 74-177-74-73-176 73-177 177-73 177 73 73 177z m286-465q0-29-22-50t-50-21q-30 0-50 21l-191 191q-100-69-223-69-80 0-153 31t-125 84-84 125-31 153 31 152 84 126 125 84 153 31 153-31 125-84 84-126 31-152q0-123-69-223l191-191q21-21 21-51z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="cancel" unicode="&#xc353;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="info-circled" unicode="&#xc354;" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="lock" unicode="&#xc355;" d="M179 421h285v108q0 59-42 101t-101 41-101-41-41-101v-108z m464-53v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h17v108q0 102 74 176t176 74 177-74 73-176v-108h18q23 0 38-15t16-38z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="lock-open" unicode="&#xc356;" d="M929 529v-143q0-15-11-25t-25-11h-36q-14 0-25 11t-11 25v143q0 59-41 101t-101 41-101-41-42-101v-108h53q23 0 38-15t16-38v-322q0-22-16-37t-38-16h-535q-23 0-38 16t-16 37v322q0 22 16 38t38 15h375v108q0 103 73 176t177 74 176-74 74-176z" horiz-adv-x="928.6" />
+
+<glyph glyph-name="pencil" unicode="&#xc357;" d="M203-7l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="down-dir" unicode="&#xc358;" d="M571 457q0-14-10-25l-250-250q-11-11-25-11t-25 11l-250 250q-11 11-11 25t11 25 25 11h500q14 0 25-11t10-25z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="up-dir" unicode="&#xc359;" d="M571 171q0-14-10-25t-25-10h-500q-15 0-25 10t-11 25 11 26l250 250q10 10 25 10t25-10l250-250q10-11 10-26z" horiz-adv-x="571.4" />
+
+<glyph glyph-name="left-dir" unicode="&#xc35a;" d="M357 600v-500q0-14-10-25t-26-11-25 11l-250 250q-10 11-10 25t10 25l250 250q11 11 25 11t26-11 10-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="right-dir" unicode="&#xc35b;" d="M321 350q0-14-10-25l-250-250q-11-11-25-11t-25 11-11 25v500q0 15 11 25t25 11 25-11l250-250q10-10 10-25z" horiz-adv-x="357.1" />
+
+<glyph glyph-name="left-open" unicode="&#xc35c;" d="M654 682l-297-296 297-297q10-10 10-25t-10-25l-93-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 11 25 11t25-11l93-93q10-10 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="right-open" unicode="&#xc35d;" d="M618 361l-414-415q-11-10-25-10t-25 10l-93 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l93 93q10 11 25 11t25-11l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
+
+<glyph glyph-name="angle-down" unicode="&#xc35e;" d="M600 439q0-7-6-12l-260-261q-5-5-13-5t-12 5l-260 261q-6 5-6 12t6 13l28 28q5 6 12 6t13-6l219-219 220 219q5 6 13 6t12-6l28-28q6-5 6-13z" horiz-adv-x="642.9" />
+
+<glyph glyph-name="filter" unicode="&#xc35f;" d="M783 685q9-22-8-39l-275-275v-414q0-23-22-33-7-3-14-3-15 0-25 11l-143 143q-10 11-10 25v271l-275 275q-18 17-8 39 9 22 33 22h714q23 0 33-22z" horiz-adv-x="785.7" />
+
+<glyph glyph-name="sort-alt-up" unicode="&#xc360;" d="M411 46q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m589-71v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-357q-8 0-13 5t-5 13v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m-107 285v-107q0-7-5-12t-13-6h-250q-8 0-13 6t-5 12v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m-107 286v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="sort-alt-down" unicode="&#xc361;" d="M679-25v-107q0-8-5-13t-13-5h-143q-8 0-13 5t-5 13v107q0 8 5 13t13 5h143q8 0 13-5t5-13z m-268 71q0-6-6-13l-178-178q-5-5-13-5-6 0-12 5l-179 179q-8 9-4 19 4 11 17 11h107v768q0 8 5 13t13 5h107q8 0 13-5t5-13v-768h107q8 0 13-5t5-13z m375 215v-107q0-8-5-13t-13-5h-250q-8 0-13 5t-5 13v107q0 8 5 13t13 5h250q8 0 13-5t5-13z m107 285v-107q0-7-5-12t-13-6h-357q-8 0-13 6t-5 12v107q0 8 5 13t13 5h357q8 0 13-5t5-13z m107 286v-107q0-8-5-13t-13-5h-464q-8 0-13 5t-5 13v107q0 8 5 13t13 5h464q8 0 13-5t5-13z" horiz-adv-x="1000" />
+
+<glyph glyph-name="ok" unicode="&#xc362;" d="M933 534q0-22-16-38l-404-404-76-76q-16-15-38-15t-38 15l-76 76-202 202q-15 16-15 38t15 38l76 76q16 16 38 16t38-16l164-165 366 367q16 16 38 16t38-16l76-76q16-15 16-38z" horiz-adv-x="1000" />
+
+<glyph glyph-name="menu" unicode="&#xc363;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
+
+<glyph glyph-name="indent-left" unicode="&#xe800;" d="M214 546v-321q0-7-5-13t-13-5q-7 0-12 5l-161 161q-5 5-5 13t5 13l161 160q5 5 12 5 8 0 13-5t5-13z m786-428v-107q0-7-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z m0 214v-107q0-7-5-13t-13-5h-607q-7 0-13 5t-5 13v107q0 7 5 13t13 5h607q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-607q-7 0-13 6t-5 12v107q0 8 5 13t13 5h607q7 0 13-5t5-13z m0 215v-107q0-8-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="indent-right" unicode="&#xe801;" d="M196 386q0-8-5-13l-160-161q-5-5-13-5-7 0-13 5t-5 13v321q0 8 5 13t13 5q8 0 13-5l160-160q5-5 5-13z m804-268v-107q0-7-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z m0 214v-107q0-7-5-13t-13-5h-607q-7 0-13 5t-5 13v107q0 7 5 13t13 5h607q7 0 13-5t5-13z m0 214v-107q0-7-5-12t-13-6h-607q-7 0-13 6t-5 12v107q0 8 5 13t13 5h607q7 0 13-5t5-13z m0 215v-107q0-8-5-13t-13-5h-964q-7 0-13 5t-5 13v107q0 7 5 12t13 6h964q7 0 13-6t5-12z" horiz-adv-x="1000" />
+
+<glyph glyph-name="spin5" unicode="&#xea61;" d="M462 850c-6 0-11-5-11-11l0-183 0 0c0-6 5-11 11-11l69 0c1 0 1 0 1 0 7 0 12 5 12 11l0 183 0 0c0 6-5 11-12 11l-69 0c0 0 0 0-1 0z m250-47c-4 1-8-2-10-5l-91-158 0 0c-4-6-2-13 4-16l60-34c0-1 0-1 0-1 6-3 13-1 16 4l91 158c3 6 2 13-4 16l-61 35c-1 1-3 1-5 1z m-428-2c-2 0-4-1-6-2l-61-35c-5-3-7-10-4-16l91-157c0 0 0 0 0 0 3-6 10-8 16-5l61 35c5 4 7 11 4 16l-91 157c0 1 0 1 0 1-2 4-6 6-10 6z m620-163c-2 0-4 0-6-1l-157-91c0 0 0 0 0 0-6-3-8-10-5-16l35-61c4-5 11-7 16-4l157 91c1 0 1 0 1 0 6 3 7 11 4 16l-35 61c-2 4-6 6-10 5z m-810-4c-5 0-9-2-11-6l-35-61c-3-5-1-12 4-15l158-91 0 0c6-4 13-2 16 4l35 60c0 0 0 0 0 0 3 6 1 13-4 16l-158 91c-2 1-4 2-5 2z m712-235l0 0c-6 0-11-5-11-11l0-69c0-1 0-1 0-1 0-7 5-12 11-12l183 0 0 0c6 0 11 5 11 12l0 69c0 0 0 0 0 1 0 6-5 11-11 11l-183 0z m-794-5l0 0c-7 0-12-5-12-12l0-69c0 0 0 0 0-1 0-6 5-11 12-11l182 0 0 0c6 0 11 5 11 11l0 69c0 1 0 1 0 1 0 7-5 12-11 12l-182 0z m772-153c-4 0-8-2-10-6l-34-60c-1 0-1 0-1 0-3-6-1-13 4-16l158-91c6-3 13-1 16 4l35 61c3 5 1 12-4 15l-158 92 0 0c-2 1-4 1-6 1z m-566-5c-1 0-3 0-5-1l-157-91c0 0-1 0-1 0-5-3-7-10-4-16l35-61c3-5 10-7 16-4l157 91c0 0 0 0 0 0 6 3 8 10 5 16l-35 61c-3 3-7 6-11 5z m468-121c-2 0-4 0-6-1l-61-35c-5-4-7-11-4-16l91-157c0-1 0-1 0-1 3-6 11-7 16-4l61 35c5 3 7 10 4 16l-91 157c0 0 0 0 0 0-2 4-6 6-10 6z m-367-2c-4 0-8-2-10-6l-91-158c-3-6-1-13 4-16l61-35c5-3 12-1 15 4l92 158 0 0c3 6 1 13-5 16l-60 35c0 0 0 0 0 0-2 1-4 1-6 2z m149-58c-7 0-12-5-12-11l0-183 0 0c0-6 5-11 12-11l69 0c0 0 0 0 1 0 6 0 11 5 11 11l0 183 0 0c0 6-5 11-11 11l-69 0c-1 0-1 0-1 0z" horiz-adv-x="1000" />
+</font>
+</defs>
+</svg> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.ttf b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.ttf
new file mode 100644
index 00000000..f33fd255
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.ttf
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.woff b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.woff
new file mode 100644
index 00000000..426c6115
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui-grid/ui-grid.woff
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js
index b09fe5b7..b09fe5b7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js
index 0eab2963..0eab2963 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-sortable/v0.13.4/sortable.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-sortable/v0.13.4/sortable.min.js
new file mode 100644
index 00000000..af538bcf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/angular-ui/ui-sortable/v0.13.4/sortable.min.js
@@ -0,0 +1,8 @@
+/**
+ * angular-ui-sortable - This directive allows you to jQueryUI Sortable.
+ * @version v0.13.4 - 2015-06-07
+ * @link http://angular-ui.github.com
+ * @license MIT
+ */
+
+!function(a,b,c){"use strict";b.module("ui.sortable",[]).value("uiSortableConfig",{}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(a,d,e){return{require:"?ngModel",scope:{ngModel:"=",uiSortable:"="},link:function(f,g,h,i){function j(a,b){return b&&"function"==typeof b?function(){a.apply(this,arguments),b.apply(this,arguments)}:a}function k(a){var b=a.data("ui-sortable");return b&&"object"==typeof b&&"ui-sortable"===b.widgetFullName?b:null}function l(a,b){var c=a.sortable("option","helper");return"clone"===c||"function"==typeof c&&b.item.sortable.isCustomHelperUsed()}function m(a){return/left|right/.test(a.css("float"))||/inline|table-cell/.test(a.css("display"))}function n(a,b){for(var c=null,d=0;d<a.length;d++){var e=a[d];if(e.element[0]===b[0]){c=e.scope;break}}return c}function o(a,b){b.item.sortable._destroy()}var p,q={},r={"ui-floating":c},s={receive:null,remove:null,start:null,stop:null,update:null},t={helper:null};return b.extend(q,r,a,f.uiSortable),b.element.fn&&b.element.fn.jquery?(i?(f.$watch("ngModel.length",function(){d(function(){k(g)&&g.sortable("refresh")},0,!1)}),s.start=function(a,d){if("auto"===q["ui-floating"]){var e=d.item.siblings(),f=k(b.element(a.target));f.floating=m(e)}d.item.sortable={model:i.$modelValue[d.item.index()],index:d.item.index(),source:d.item.parent(),sourceModel:i.$modelValue,cancel:function(){d.item.sortable._isCanceled=!0},isCanceled:function(){return d.item.sortable._isCanceled},isCustomHelperUsed:function(){return!!d.item.sortable._isCustomHelperUsed},_isCanceled:!1,_isCustomHelperUsed:d.item.sortable._isCustomHelperUsed,_destroy:function(){b.forEach(d.item.sortable,function(a,b){d.item.sortable[b]=c})}}},s.activate=function(a,c){p=g.contents();var d=g.sortable("option","placeholder");if(d&&d.element&&"function"==typeof d.element){var e=d.element();e=b.element(e);var h=g.find('[class="'+e.attr("class")+'"]:not([ng-repeat], [data-ng-repeat])');p=p.not(h)}var i=c.item.sortable._connectedSortables||[];i.push({element:g,scope:f}),c.item.sortable._connectedSortables=i},s.update=function(a,b){if(!b.item.sortable.received){b.item.sortable.dropindex=b.item.index();var c=b.item.parent();b.item.sortable.droptarget=c;var d=n(b.item.sortable._connectedSortables,c);b.item.sortable.droptargetModel=d.ngModel,g.sortable("cancel")}l(g,b)&&!b.item.sortable.received&&"parent"===g.sortable("option","appendTo")&&(p=p.not(p.last())),p.appendTo(g),b.item.sortable.received&&(p=null),b.item.sortable.received&&!b.item.sortable.isCanceled()&&f.$apply(function(){i.$modelValue.splice(b.item.sortable.dropindex,0,b.item.sortable.moved)})},s.stop=function(a,b){!b.item.sortable.received&&"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()?f.$apply(function(){i.$modelValue.splice(b.item.sortable.dropindex,0,i.$modelValue.splice(b.item.sortable.index,1)[0])}):"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()||l(g,b)||p.appendTo(g),p=null},s.receive=function(a,b){b.item.sortable.received=!0},s.remove=function(a,b){"dropindex"in b.item.sortable||(g.sortable("cancel"),b.item.sortable.cancel()),b.item.sortable.isCanceled()||f.$apply(function(){b.item.sortable.moved=i.$modelValue.splice(b.item.sortable.index,1)[0]})},t.helper=function(a){return a&&"function"==typeof a?function(b,c){var d=a.apply(this,arguments);return c.sortable._isCustomHelperUsed=c!==d,d}:a},f.$watch("uiSortable",function(a){var c=k(g);c&&b.forEach(a,function(a,b){return b in r?("ui-floating"!==b||a!==!1&&a!==!0||(c.floating=a),void(q[b]=a)):(s[b]?("stop"===b&&(a=j(a,function(){f.$apply()}),a=j(a,o)),a=j(s[b],a)):t[b]&&(a=t[b](a)),q[b]=a,void g.sortable("option",b,a))})},!0),b.forEach(s,function(a,b){q[b]=j(a,q[b]),"stop"===b&&(q[b]=j(q[b],o))})):e.info("ui.sortable: ngModel not provided!",g),void g.sortable(q)):void e.error("ui.sortable: jQuery should be included before AngularJS!")}}}])}(window,window.angular);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/README.md b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/README.md
new file mode 100644
index 00000000..493b9e85
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/README.md
@@ -0,0 +1,26 @@
+# B2B Library Area
+
+## Overview
+
+This is a README document to track changes made by ECOMP Portal team to the b2b library.
+
+## Release Notes
+
+All of the release notes in the b2b area apply here.
+
+--
+
+9 Mar 2017
+Modified b2b-library.min.js for ECOMP left menu feature, toggle menu icon, hide plus sign if there is no child menus:
+
+- scope.toggleNav = function (val) {
+- if(val == 0){ /*ECOMP portal change assuming the first item is home page.*/
+- location.href = "welcome.htm";
+- }else{
++ scope.toggleNav = function (val,link) {
++ /**Added for ECOMP: make parent menu a link if no child menus.**/
++ if(link!=null && link!=''){
++ location.href = link;
++ return;
++ }
++ /**Ended**/
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/b2b-angular.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/b2b-angular.css
new file mode 100644
index 00000000..d1246179
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/b2b-angular.css
@@ -0,0 +1,11827 @@
+/*! b2b-angular-library - v1.0.1 - Last updated: 2017-03-02. Copyright (c) 2016 AT&T Services, Inc. */
+.b2b-horizontal-table {
+ border: 1px solid;
+ width: 651px; }
+ .b2b-horizontal-table ::-webkit-scrollbar {
+ height: 10px; }
+ .b2b-horizontal-table ::-webkit-scrollbar-thumb {
+ background: #666666;
+ border-radius: 5px; }
+ .b2b-horizontal-table .b2b-horizontal-table-inner-container {
+ width: 650px;
+ padding-left: 150px;
+ overflow-x: scroll; }
+ .b2b-horizontal-table th:first-child {
+ background-color: #FFFFFF; }
+ .b2b-horizontal-table td:first-child {
+ background-color: #FFFFFF;
+ border-top: 1px solid #cccccc;
+ border-right: 1px solid #cccccc;
+ margin-top: -0.5px; }
+ .b2b-horizontal-table tr th:nth-child(2), .b2b-horizontal-table tr td:nth-child(2) {
+ border-left: none; }
+ .b2b-horizontal-table .b2b-horizontal-table-column-info {
+ padding-top: 16px;
+ text-align: center; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .btn-arrow:hover, .b2b-horizontal-table .b2b-horizontal-table-arrows .btn-arrow:focus {
+ text-decoration: none; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .left {
+ float: left;
+ margin: 10px;
+ color: #0568ae; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .left[disabled] {
+ color: #767676;
+ cursor: not-allowed; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .right {
+ float: right;
+ clear: right;
+ margin: 10px;
+ color: #0568ae; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .right[disabled] {
+ color: #767676;
+ cursor: not-allowed; }
+ .b2b-horizontal-table .b2b-horizontal-table-arrows .right.btn-arrow .btn {
+ margin-right: 0;
+ margin-left: 10px; }
+
+@-moz-document url-prefix() {
+ .b2b-horizontal-table td:first-child {
+ border-top: none; } }
+* {
+ box-sizing: border-box; }
+
+:root {
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ overflow-y: scroll;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+ box-sizing: border-box;
+ font: 0.625pc/1.5 sans-serif;
+ text-rendering: optimizeLegibility; }
+
+html {
+ overflow-y: scroll;
+ -webkit-overflow-scrolling: touch;
+ height: 100%;
+ position: relative; }
+
+h1,
+h2,
+h3,
+h4,
+h5,
+p,
+blockquote,
+figure,
+ol,
+ul {
+ margin: 0;
+ padding: 0; }
+
+/* a:focus {
+ outline: thin dotted #191919;
+} */
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: top; }
+
+sup {
+ top: .75em;
+ display: inline-block; }
+
+sub {
+ bottom: -0.25em; }
+
+img {
+ max-width: 100%;
+ height: auto;
+ vertical-align: middle;
+ border: 0;
+ -ms-interpolation-mode: bicubic; }
+
+.img-no-rwd {
+ max-width: inherit !important; }
+
+svg {
+ display: inline-block; }
+
+.responsive-img {
+ width: 100%;
+ height: auto; }
+
+button,
+input,
+select,
+textarea {
+ margin: 0;
+ font-size: 100%;
+ vertical-align: middle; }
+
+::-moz-focus-inner {
+ padding: 0;
+ border: 0; }
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ appearance: button;
+ cursor: pointer; }
+
+label,
+select,
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+input[type="radio"],
+input[type="checkbox"] {
+ cursor: pointer; }
+
+input[type=search] {
+ -webkit-appearance: textfield; }
+
+input[type=search]:-webkit-search-cancel-button,
+input[type=search]:-webkit-search-decoration {
+ -webkit-appearance: none; }
+
+textarea {
+ overflow: auto;
+ vertical-align: top;
+ resize: none; }
+
+select {
+ -moz-appearance: none;
+ -webkit-appearance: none; }
+
+[aria-busy=true] {
+ cursor: progress; }
+
+[aria-controls] {
+ cursor: pointer; }
+
+body {
+ background-color: #ffffff;
+ color: #191919;
+ font-family: "Omnes-ECOMP-W02", Arial;
+/* font-size: 1.6rem;
+ line-height: 2rem;*/
+ margin: 0;
+ position: relative;
+ width: 100%;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased; }
+
+small {
+ font-size: 1.6rem; }
+
+.container {
+ margin: 0 auto;
+ padding: 0; }
+
+.tooltip {
+ display: inline-block;
+ height: 20px;
+ margin: 1px 0 0 7px;
+ vertical-align: middle; }
+
+.tooltip-wrapper {
+ display: none; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02";
+ src: url("fonts/Omnes_ATTW02.eot");
+ src: url("fonts/Omnes_ATTW02.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02.woff") format("woff"), url("fonts/Omnes_ATTW02.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Medium";
+ src: url("fonts/Omnes_ATTW02Medium.eot");
+ src: url("fonts/Omnes_ATTW02Medium.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Medium.woff") format("woff"), url("fonts/Omnes_ATTW02Medium.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Italic";
+ src: url("fonts/Omnes_ATTW02Italic.eot");
+ src: url("fonts/Omnes_ATTW02Italic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Italic.woff") format("woff"), url("fonts/Omnes_ATTW02Italic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Light";
+ src: url("fonts/Omnes_ATTW02Light.eot");
+ src: url("fonts/Omnes_ATTW02Light.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Light.woff") format("woff"), url("fonts/Omnes_ATTW02Light.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Bold";
+ src: url("fonts/Omnes_ATTW02Bold.eot");
+ src: url("fonts/Omnes_ATTW02Bold.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Bold.woff") format("woff"), url("fonts/Omnes_ATTW02Bold.woff2") format("woff2"), url("fonts/Omnes_ATTW02Bold.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Light-Italic";
+ src: url("fonts/Omnes_ATTW02LightItalic.eot");
+ src: url("fonts/Omnes_ATTW02LightItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02LightItalic.woff") format("woff"), url("fonts/Omnes_ATTW02LightItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02LightItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Medium-Italic";
+ src: url("fonts/Omnes_ATTW02MediumItalic.eot");
+ src: url("fonts/Omnes_ATTW02MediumItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02MediumItalic.woff") format("woff"), url("fonts/Omnes_ATTW02MediumItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02MediumItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Bold-Italic";
+ src: url("fonts/Omnes_ATTW02BoldItalic.eot");
+ src: url("fonts/Omnes_ATTW02BoldItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02BoldItalic.woff") format("woff"), url("fonts/Omnes_ATTW02BoldItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02BoldItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+/* TODO: Build a reference page for these classes */
+.font-regular {
+ font-family: "Omnes-ECOMP-W02", Arial !important; }
+
+.font-light {
+ font-family: "Omnes-ECOMP-W02-Light", Arial !important; }
+
+.font-italic {
+ font-family: "Omnes-ECOMP-W02-Italic", Arial !important; }
+
+.font-light-italic {
+ font-family: "Omnes-ECOMP-W02-Light-Italic", Arial !important; }
+
+.font-medium {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial !important; }
+
+.font-medium-italic {
+ font-family: "Omnes-ECOMP-W02-Medium-Italic", Arial !important; }
+
+.font-reset {
+ font-style: normal;
+ font-variant: normal;
+ font-weight: normal;
+ text-transform: none; }
+
+.visible-phone {
+ display: none !important; }
+
+.visible-tablet {
+ display: none !important; }
+
+.hidden-desktop {
+ display: none !important; }
+
+.visible-desktop {
+ display: inherit !important; }
+
+.row,
+.row-nowrap {
+ margin-left: 0; }
+
+.row:before,
+.row-nowrap:before,
+.row:after,
+.row-nowrap:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.row:after,
+.row-nowrap:after {
+ clear: both; }
+
+.row:before,
+.row-nowrap:before,
+.row:after,
+.row-nowrap:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.row:after,
+.row-nowrap:after {
+ clear: both; }
+
+.row,
+.row-nowrap {
+ display: flex; }
+
+.row > [class*="span"],
+.row-nowrap > [class*="span"] {
+ float: left;
+ margin-right: 14px;
+ margin-right: 1.40845%\9; }
+
+.row > [class*="span"]:last-child,
+.row-nowrap > [class*="span"]:last-child {
+ margin-right: 0; }
+
+.row > [class*="span"].centered,
+.row-nowrap > [class*="span"].centered {
+ margin-left: auto !important;
+ margin-right: auto !important; }
+
+.row.no-flex,
+.row-nowrap.no-flex {
+ display: block; }
+
+.row.no-flex > [class*="span"],
+.row-nowrap.no-flex > [class*="span"] {
+ margin-right: 1.408450704225352%; }
+
+.row.no-flex > [class*="span"]:last-child,
+.row-nowrap.no-flex > [class*="span"]:last-child {
+ margin-right: 0; }
+
+.row.flex-justify,
+.row-nowrap.flex-justify {
+ justify-content: space-between; }
+
+.row.flex-justify > [class*="span"],
+.row-nowrap.flex-justify > [class*="span"] {
+ flex: 1 1 0; }
+
+.row.flex-justify > .flex-col,
+.row-nowrap.flex-justify > .flex-col {
+ margin-right: 14px;
+ margin-right: 1.40845%\9; }
+
+.row.flex-wrap,
+.row-nowrap.flex-wrap {
+ flex-wrap: wrap; }
+
+.align-items-top {
+ align-items: flex-start; }
+
+.align-items-center {
+ align-items: center; }
+
+.align-items-bottom {
+ align-items: flex-end; }
+
+.align-self-top {
+ align-self: flex-start; }
+
+.align-self-center {
+ align-self: center; }
+
+.align-self-bottom {
+ align-self: flex-end; }
+
+.row .fixed-230 {
+ flex: 0;
+ display: block;
+ width: 230px;
+ vertical-align: top;
+ min-width: 230px;
+ background-color: #efefef; }
+
+.row .fluid-space {
+ flex: 1 1 0;
+ display: block;
+ vertical-align: top;
+ padding-left: 0;
+ padding-right: 20px;
+ width: 100%; }
+
+.row .fixed-230 + .fluid-space {
+ padding-left: 20px;
+ padding-right: 20px; }
+
+.row .fluid-space:last-child {
+ padding-right: 0; }
+
+.span1 {
+ width: 7.042253521126761%; }
+
+.span2 {
+ width: 15.49295774647887%; }
+
+.span3 {
+ width: 23.94366197183099%; }
+
+.span4 {
+ width: 32.3943661971831%; }
+
+.span5 {
+ width: 40.84507042253521%; }
+
+.span6 {
+ width: 49.29577464788733%; }
+
+.span7 {
+ width: 57.74647887323944%; }
+
+.span8 {
+ width: 66.19718309859155%; }
+
+.span9 {
+ width: 74.64788732394367%; }
+
+.span10 {
+ width: 83.09859154929578%; }
+
+.span11 {
+ width: 91.54929577464789%; }
+
+.span12 {
+ width: 100%; }
+
+.offset1 {
+ margin-left: 8.450704225352113%; }
+
+.offset2 {
+ margin-left: 16.90140845070423%; }
+
+.offset3 {
+ margin-left: 25.35211267605634%; }
+
+.offset4 {
+ margin-left: 33.8028169%; }
+
+.offset5 {
+ margin-left: 42.25352113%; }
+
+.offset6 {
+ margin-left: 50.70422535%; }
+
+.offset7 {
+ margin-left: 59.15492958%; }
+
+.offset8 {
+ margin-left: 67.6056338%; }
+
+.offset9 {
+ margin-left: 76.05633803%; }
+
+.offset10 {
+ margin-left: 84.50704225%; }
+
+.offset11 {
+ margin-left: 92.95774648%; }
+
+.align-center {
+ margin: 0 auto;
+ text-align: center; }
+
+[class*="span"].align-center {
+ margin: 0 auto !important;
+ float: none; }
+
+.align-left .container {
+ padding-left: 0 !important;
+ margin: 0 !important; }
+
+/* BEGIN RESPONSIVE-4.LESS ************** */
+@media (min-width: 1025px) {
+ .row > [class*="span"],
+ .row-nowrap > [class*="span"] {
+ margin-right: 20px;
+ margin-right: 1.487301587301587%\9; }
+ .container {
+ padding-left: 20px;
+ padding-right: 20px;
+ max-width: 1260px; }
+ /* 1col = 6.878306878306879 */
+ /* 1colgutter = 1.587301587301587 */
+ .span0 {
+ display: none; }
+ .span1 {
+ width: 6.878306878306879%; }
+ .span2 {
+ width: 15.34391534391534%; }
+ .span3 {
+ width: 23.80952380952381%; }
+ .span4 {
+ width: 32.27513227513228%; }
+ .span5 {
+ width: 40.74074074074074%; }
+ .span6 {
+ width: 49.20634920634921%; }
+ .span7 {
+ width: 57.67195767195767%; }
+ .span8 {
+ width: 66.13756613756614%; }
+ .span9 {
+ width: 74.60317460317461%; }
+ .span10 {
+ width: 83.06878306878308%; }
+ .span11 {
+ width: 91.53439153439154%; }
+ .span12 {
+ width: 100%; }
+ .offset1 {
+ margin-left: 8.465608465608466%; }
+ .offset2 {
+ margin-left: 16.93121693121693%; }
+ .offset3 {
+ margin-left: 25.3968253968254%; }
+ .offset4 {
+ margin-left: 33.86243386%; }
+ .offset5 {
+ margin-left: 42.32804233%; }
+ .offset6 {
+ margin-left: 50.79365079%; }
+ .offset7 {
+ margin-left: 59.25925926%; }
+ .offset8 {
+ margin-left: 67.72486772%; }
+ .offset9 {
+ margin-left: 76.19047619%; }
+ .offset10 {
+ margin-left: 84.65608466%; }
+ .offset11 {
+ margin-left: 93.12169312%; }
+ .tooltip-size-control {
+ position: relative;
+ width: 400px; }
+ .thumbnails > li {
+ margin-left: 1.40845070422535%; }
+ .row .thumbnails {
+ margin-left: 0; } }
+
+/* END RESPONSIVE-4.LESS ****************** */
+/* BEGIN RESPONSIVE-3.LESS ******************* */
+@media (min-width: 768px) and (max-width: 1024px) {
+ .hidden-desktop {
+ display: inherit !important; }
+ .visible-desktop {
+ display: none !important; }
+ .visible-tablet {
+ display: inherit !important; }
+ .hidden-tablet {
+ display: none !important; }
+ .container {
+ width: 100%;
+ margin: 0 auto;
+ padding-left: 20px;
+ padding-right: 20px; }
+ .span0-md {
+ display: none; }
+ .span1-md {
+ width: 7.042253521126761%; }
+ .span2-md {
+ width: 15.49295774647887%; }
+ .span3-md {
+ width: 23.94366197183099%; }
+ .span4-md {
+ width: 32.3943661971831%; }
+ .span5-md {
+ width: 40.84507042253521%; }
+ .span6-md {
+ width: 49.29577464788733%; }
+ .span7-md {
+ width: 57.74647887323944%; }
+ .span8-md {
+ width: 66.19718309859155%; }
+ .span9-md {
+ width: 74.64788732394367%; }
+ .span10-md {
+ width: 83.09859154929578%; }
+ .span11-md {
+ width: 91.54929577464789%; }
+ .span12-md {
+ width: 100%; }
+ .offset1-md {
+ margin-left: 8.450704225352113%; }
+ .offset2-md {
+ margin-left: 16.90140845070423%; }
+ .offset3-md {
+ margin-left: 25.35211267605634%; }
+ .offset4-md {
+ margin-left: 33.8028169%; }
+ .offset5-md {
+ margin-left: 42.25352113%; }
+ .offset6-md {
+ margin-left: 50.70422535%; }
+ .offset7-md {
+ margin-left: 59.15492958%; }
+ .offset8-md {
+ margin-left: 67.6056338%; }
+ .offset9-md {
+ margin-left: 76.05633803%; }
+ .offset10-md {
+ margin-left: 84.50704225%; }
+ .offset11-md {
+ margin-left: 92.95774648%; }
+ .tooltip-size-control {
+ position: relative;
+ width: 300px; } }
+
+/* END RESPONSIVE-3.LESS ******************* */
+/* BEGIN RESPONSIVE-2.LESS *************** */
+@media (max-width: 767px) {
+ .hidden-desktop {
+ display: inherit !important; }
+ .visible-desktop {
+ display: none !important; }
+ .visible-phone {
+ display: inherit !important; }
+ .visible-tablet {
+ display: inherit !important; }
+ .hidden-phone {
+ display: none !important; }
+ .hidden-tablet {
+ display: none !important; }
+ .container {
+ width: auto;
+ padding-left: 15px;
+ padding-right: 15px; }
+ /*.row{ display:block; }*/
+ .row > [class*="span"] {
+ float: none;
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%; }
+ .row {
+ display: block; }
+ .row.flex > .flex-col,
+ .row-nowrap.flex > .flex-col {
+ margin-right: 0; }
+ .row .fixed-230 {
+ display: block;
+ width: 100%; }
+ .row .fluid-space {
+ display: block;
+ padding-left: 0;
+ padding-right: 0;
+ width: auto; }
+ .row .fluid-space + .fixed-230 {
+ padding-left: 0; }
+ .row .fluid-space:last-child {
+ padding-right: 0; }
+ .span0-sm {
+ display: none; }
+ .span1-sm {
+ width: 7.042253521126761%; }
+ .span2-sm {
+ width: 15.49295774647887%; }
+ .span3-sm {
+ width: 23.94366197183099%; }
+ .span4-sm {
+ width: 32.3943661971831%; }
+ .span5-sm {
+ width: 40.84507042253521%; }
+ .span6-sm {
+ width: 49.29577464788733%; }
+ .span7-sm {
+ width: 57.74647887323944%; }
+ .span8-sm {
+ width: 66.19718309859155%; }
+ .span9-sm {
+ width: 74.64788732394367%; }
+ .span10-sm {
+ width: 83.09859154929578%; }
+ .span11-sm {
+ width: 91.54929577464789%; }
+ .span12-sm {
+ width: 100%; }
+ .offset1-sm {
+ margin-left: 8.450704225352113%; }
+ .offset2-sm {
+ margin-left: 16.90140845070423%; }
+ .offset3-sm {
+ margin-left: 25.35211267605634%; }
+ .offset4-sm {
+ margin-left: 33.8028169%; }
+ .offset5-sm {
+ margin-left: 42.25352113%; }
+ .offset6-sm {
+ margin-left: 50.70422535%; }
+ .offset7-sm {
+ margin-left: 59.15492958%; }
+ .offset8-sm {
+ margin-left: 67.6056338%; }
+ .offset9-sm {
+ margin-left: 76.05633803%; }
+ .offset10-sm {
+ margin-left: 84.50704225%; }
+ .offset11-sm {
+ margin-left: 92.95774648%; }
+ input {
+ padding: 8px 15px 8px 15px; }
+ .field-group input.input-emphasized[type="search"] + .reset-field:after {
+ top: 14px; }
+ .field-group input.input-emphasized[type="search"] + .reset-field {
+ height: 46px;
+ top: 1px; }
+ .marquee {
+ margin-bottom: 30px; }
+ .marquee .blur-overlay {
+ border-radius: 0;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ margin: 0;
+ padding: 34px 15px 30px; }
+ .marquee + div {
+ margin-top: 30px; }
+ .marquee h1 {
+ font-size: 1.8rem;
+ letter-spacing: -0.035px; }
+ .marquee .lead {
+ font-size: 3.0rem;
+ line-height: 3.6rem;
+ margin-bottom: 0; }
+ .marquee p:not(.lead) {
+ font-family: "Omnes-ECOMP-W02-Light", Arial;
+ font-size: 1.8rem;
+ margin-bottom: 0; }
+ .marquee .btn-fullwidth {
+ margin-top: 10px;
+ width: 100%;
+ float: none; }
+ .tooltip-size-control {
+ width: 100%; }
+ .table-wrapper,
+ .accordion-table-layout {
+ margin-left: -15px;
+ margin-right: -15px; }
+ .table-wrapper caption {
+ padding-left: 15px; } }
+
+@media (max-width: 480px) {
+ .span1-xsm {
+ width: 7.042253521126761%; }
+ .span2-xsm {
+ width: 15.49295774647887%; }
+ .span3-xsm {
+ width: 23.94366197183099%; }
+ .span4-xsm {
+ width: 32.3943661971831%; }
+ .span5-xsm {
+ width: 40.84507042253521%; }
+ .span6-xsm {
+ width: 49.29577464788733%; }
+ .span7-xsm {
+ width: 57.74647887323944%; }
+ .span8-xsm {
+ width: 66.19718309859155%; }
+ .span9-xsm {
+ width: 74.64788732394367%; }
+ .span10-xsm {
+ width: 83.09859154929578%; }
+ .span11-xsm {
+ width: 91.54929577464789%; }
+ .span12-xsm {
+ width: 100%; }
+ .offset1-xsm {
+ margin-left: 8.450704225352113%; }
+ .offset2-xsm {
+ margin-left: 16.90140845070423%; }
+ .offset3-xsm {
+ margin-left: 25.35211267605634%; }
+ .offset4-xsm {
+ margin-left: 33.8028169%; }
+ .offset5-xsm {
+ margin-left: 42.25352113%; }
+ .offset6-xsm {
+ margin-left: 50.70422535%; }
+ .offset7-xsm {
+ margin-left: 59.15492958%; }
+ .offset8-xsm {
+ margin-left: 67.6056338%; }
+ .offset9-xsm {
+ margin-left: 76.05633803%; }
+ .offset10-xsm {
+ margin-left: 84.50704225%; }
+ .offset11-xsm {
+ margin-left: 92.95774648%; } }
+
+/* END RESPONSIVE-2.LESS ******************* */
+/* BEGIN RESPONSIVE-1.LESS ************** */
+.xxxxxxxx-begin-responsive-480px.less {
+ /* placeholder */ }
+
+@media (max-width: 480px) {
+ .hidden-desktop {
+ display: inherit !important; }
+ .hidden-tablet {
+ display: inherit !important; }
+ .hidden-phone {
+ display: none !important; }
+ .visible-desktop {
+ display: none !important; }
+ .visible-tablet {
+ display: none !important; }
+ .visible-phone {
+ display: inherit !important; }
+ .container {
+ width: auto;
+ padding-left: 15px;
+ padding-right: 15px; } }
+
+@font-face {
+ font-family: 'icoPrimary';
+ src: url("fonts/icons/icoPrimary.eot?timestamp=@@timestamp");
+ src: url("fonts/icons/icoPrimary.eot?timestamp=@@timestamp#iefix") format("embedded-opentype"), url("data:font/woff2; charset=utf-8;base64,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") format("woff2"), url("data:application/font-woff; charset=utf-8;base64,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") format("woff"), url("fonts/icons/icoPrimary.ttf?timestamp=@@timestamp") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+[class*="icon-primary-"],
+.nav-links a:after,
+.bellyband-link a:after,
+.breadcrumb > li:after,
+.checkbox input:checked + .skin:after,
+.checkbox input.indeterminate + .skin:after,
+.checkbox input:indeterminate + .skin:after,
+.selectWrap.large:before,
+.form-row.error .error-msg:before,
+.close:before,
+.reset-field:before,
+.cssIcon-globe:before,
+.selectWrap:after {
+ color: #0568ae;
+ display: inline-block;
+ font-family: 'icoPrimary' !important;
+ font-style: normal;
+ font-size: 20px;
+ font-weight: normal;
+ font-variant: normal;
+ height: 1em;
+ margin-right: 7px;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ position: relative;
+ speak: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ vertical-align: middle;
+ width: 1em; }
+
+[class*="icon-primary-"]:before,
+[class*="icon-primary-"]:after {
+ box-sizing: border-box;
+ display: inline-block;
+ font-size: 1em;
+ height: 1em;
+ position: relative;
+ top: 0;
+ left: 0;
+ vertical-align: middle;
+ width: 1em; }
+
+.icon-primary-att-globe:before,
+.cssIcon-globe:before {
+ content: "\e900";
+ color: #44c7f5; }
+
+.icon-primary-hamburger:before {
+ content: "\e903"; }
+
+.icon-primary-secure:before {
+ content: "\e918"; }
+
+.icon-primary-secureL:before {
+ content: "\e919"; }
+
+.icon-primary-padlockopen:before {
+ content: "\e916"; }
+
+.icon-primary-padlockopenL:before {
+ content: "\e917"; }
+
+.icon-primary-shoppingcart:before {
+ content: "\e914"; }
+
+.icon-primary-shoppingcartL:before {
+ content: "\e915"; }
+
+.icon-primary-print:before {
+ content: "\e921"; }
+
+.icon-primary-printL:before {
+ content: "\e922"; }
+
+.icon-primary-mobilesmartphone:before {
+ content: "\e908"; }
+
+.icon-primary-mobilesmartphoneL:before {
+ content: "\e90c"; }
+
+.icon-primary-tablet:before {
+ content: "\e904"; }
+
+.icon-primary-tabletL:before {
+ content: "\e905"; }
+
+.icon-primary-tv:before {
+ content: "\e906"; }
+
+.icon-primary-tvL:before {
+ content: "\e907"; }
+
+.icon-primary-calendar {
+ width: 100% !important; }
+
+.icon-primary-calendar:before {
+ content: "\e91a";
+ z-index: 1; }
+
+.icon-primary-calendarL:before {
+ content: "\e91b"; }
+
+.icon-primary-star:before {
+ content: "\e96c"; }
+
+.icon-primary-close:before,
+.close:before,
+.reset-field:before {
+ content: "\e910"; }
+
+.icon-primary-down:before {
+ content: "\ea3c"; }
+
+.checkbox input.indeterminate + .skin:after,
+.icon-primary-subtractminimize:before {
+ content: "\e920"; }
+
+.icon-primary-add-maximize:before {
+ content: "\e91f"; }
+
+.icon-primary-check:before,
+.checkbox input:checked + .skin:after {
+ content: "\e912"; }
+
+.icon-primary-questionmark:before {
+ content: "\e90f"; }
+
+.icon-primary-badgealert:before,
+.form-row.error .error-msg:before {
+ content: "\e90e"; }
+
+.icon-primary-approval:before {
+ content: "\e925"; }
+
+.icon-primary-flat-info:before {
+ content: "\e927"; }
+
+.icon-primary-alert:before {
+ content: "\e913"; }
+
+.icon-primary-tooltip:before,
+.icon-primary-flat-faq:before {
+ content: "\e90d"; }
+
+.icon-primary-tooltip {
+ font-size: 20px; }
+
+.nav-links a:after,
+.bellyband-link a:after,
+.breadcrumb > li:after,
+.icon-primary-right:before {
+ content: "\ea3c";
+ transform: rotate(-90deg); }
+
+.icon-primary-left:before {
+ content: "\ea3c";
+ transform: rotate(90deg); }
+
+.icon-primary-accordion-plus:after,
+.icon-primary-collapsed:after,
+.icon-primary-accordion-minus:after,
+.icon-primary-expanded:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ z-index: 1; }
+
+.icon-primary-accordion-minus,
+.icon-primary-expanded,
+.icon-primary-accordion-plus,
+.icon-primary-collapsed {
+ font-size: 20px !important; }
+
+:not(.ds2-no-colors) .icon-primary-accordion-minus:before,
+:not(.ds2-no-colors) .icon-primary-expanded:before {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2021%2021%22%3E%3Cpath%20fill%3D%22%230568ae%22%20d%3D%22M15.1%2011.3H5.9c-.4%200-.8-.3-.8-.8s.3-.8.8-.8h9.3c.4%200%20.8.3.8.8s-.4.8-.9.8z%22%2F%3E%3Cpath%20fill%3D%22%23d2d2d2%22%20d%3D%22M10.5%2021C4.7%2021%200%2016.3%200%2010.5S4.7%200%2010.5%200%2021%204.7%2021%2010.5%2016.3%2021%2010.5%2021zm0-20C5.3%201%201%205.3%201%2010.5S5.3%2020%2010.5%2020s9.5-4.3%209.5-9.5S15.7%201%2010.5%201z%22%2F%3E%3C%2Fsvg%3E");
+ content: ""; }
+
+:not(.ds2-no-colors) .icon-primary-accordion-plus:before,
+:not(.ds2-no-colors) .icon-primary-collapsed:before {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2021%2021%22%3E%3Cpath%20fill%3D%22%230568ae%22%20d%3D%22M10.5%2015.9c-.4%200-.8-.3-.8-.8V5.9c0-.4.3-.8.8-.8s.8.3.8.8v9.3c0%20.4-.4.7-.8.7z%22%2F%3E%3Cpath%20fill%3D%22%230568ae%22%20d%3D%22M15.1%2011.3H5.9c-.4%200-.8-.3-.8-.8s.3-.8.8-.8h9.3c.4%200%20.8.3.8.8s-.4.8-.9.8z%22%2F%3E%3Cpath%20fill%3D%22%23d2d2d2%22%20d%3D%22M10.5%2021C4.7%2021%200%2016.3%200%2010.5S4.7%200%2010.5%200%2021%204.7%2021%2010.5%2016.3%2021%2010.5%2021zm0-20C5.3%201%201%205.3%201%2010.5S5.3%2020%2010.5%2020s9.5-4.3%209.5-9.5S15.7%201%2010.5%201z%22%2F%3E%3C%2Fsvg%3E");
+ content: ""; }
+
+.ds2-no-colors .icon-primary-accordion-minus:before,
+.ds2-no-colors .icon-primary-expanded:before {
+ background-image: none;
+ content: "\e901"; }
+
+.ds2-no-colors .icon-primary-accordion-minus:after,
+.ds2-no-colors .icon-primary-expanded:after {
+ content: "\e902"; }
+
+.ds2-no-colors .icon-primary-accordion-plus:before,
+.ds2-no-colors .icon-primary-collapsed:before {
+ background-image: none;
+ content: "\e90b"; }
+
+.ds2-no-colors .icon-primary-accordion-plus:after,
+.ds2-no-colors .icon-primary-collapsed:after {
+ content: "\e911"; }
+
+.icon-primary-circle-arrow {
+ outline: 1px solid transparent;
+ border-radius: 50%;
+ font-size: 20px !important;
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
+ margin-right: 7px; }
+
+.icon-primary-circle-arrow:after {
+ background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2036%2036%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20baseProfile%3D%22tiny%22%3E%3Ccircle%20r%3D%2217%22%20cy%3D%2218%22%20cx%3D%2218%22%20stroke-width%3D%221%22%20fill%3D%22transparent%22%20stroke%3D%22%23ccc%22%2F%3E%3C%2Fsvg%3E");
+ content: "";
+ position: absolute;
+ top: 0;
+ z-index: 2; }
+
+.icon-primary-circle-arrow:before {
+ border-radius: 50%;
+ content: "\ea3c";
+ font-size: 12px;
+ top: 0;
+ position: absolute;
+ transform: rotate(-90deg);
+ width: 20px;
+ z-index: 1; }
+
+[class*="icon-primary-"] [class*="icon-primary-"] {
+ display: inline-block;
+ float: left;
+ font-size: 1em;
+ margin-left: -1em;
+ position: absolute; }
+
+[class*="icon-primary-"].white {
+ color: #fff; }
+
+[class*="icon-primary-"].black {
+ color: #000; }
+
+[class*="icon-primary-"].blue {
+ color: #0568ae; }
+
+[class*="icon-primary-"].green {
+ color: #007a3e; }
+
+@-webkit-viewport {
+ width: device-width; }
+
+@-moz-viewport {
+ width: device-width; }
+
+@-ms-viewport {
+ width: device-width; }
+
+@-o-viewport {
+ width: device-width; }
+
+@viewport {
+ width: device-width; }
+
+.clearfix:before,
+.clearfix:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.clearfix:after {
+ clear: both; }
+
+.pull-right {
+ float: right !important; }
+
+.pull-left {
+ float: left !important; }
+
+.float-children-left:before,
+.float-children-left:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.float-children-left:after {
+ clear: both; }
+
+.float-children-left > div {
+ float: left;
+ white-space: nowrap; }
+
+.block {
+ display: block !important; }
+
+.inline {
+ display: inline !important; }
+
+.inline-block {
+ display: inline-block !important; }
+
+.table-cell {
+ display: table-cell !important;
+ width: 1%;
+ vertical-align: middle; }
+
+@media (max-width: 767px) {
+ .full-bleed {
+ width: auto;
+ margin-left: -15px;
+ margin-right: -15px;
+ padding: 15px; } }
+
+@media (min-width: 768px) {
+ .full-bleed {
+ width: auto;
+ margin-left: -20px;
+ margin-right: -20px;
+ padding: 20px; } }
+
+@media (max-width: 480px) {
+ .full-bleed {
+ width: auto;
+ margin-left: -15px;
+ margin-right: -15px;
+ padding: 0 15px; } }
+
+.fade {
+ opacity: 0;
+ filter: alpha(opacity=0);
+ transition: opacity .15s linear; }
+
+.fade.in {
+ opacity: 1;
+ filter: alpha(opacity=100); }
+
+.b2bCollapse {
+ display: none; }
+
+.collapse.in {
+ height: auto; }
+
+.nowrap {
+ white-space: nowrap; }
+
+.pre {
+ white-space: pre; }
+
+.hidden-spoken {
+ border: 0 none !important;
+ clip: rect(0px, 0px, 0px, 0px) !important;
+ height: 1px !important;
+ letter-spacing: 0;
+ line-height: 0;
+ overflow: hidden !important;
+ margin-top: -1px;
+ padding: 0 !important;
+ position: absolute !important;
+ width: 1px !important; }
+
+[data-sr-text].hidden-spoken:before {
+ border: 0 none !important;
+ content: attr(data-sr-text);
+ clip: rect(0px, 0px, 0px, 0px) !important;
+ height: 1px !important;
+ letter-spacing: 0;
+ line-height: 0;
+ overflow: hidden !important;
+ padding: 0 !important;
+ position: absolute !important;
+ width: 100% !important;
+ z-index: -1; }
+
+[data-sr-text].hidden-spoken {
+ position: relative !important;
+ width: auto !important; }
+
+[data-show-between] {
+ display: none;
+ visibility: hidden; }
+
+.noscroll-y {
+ overflow-y: hidden !important; }
+
+.invisible {
+ visibility: hidden !important;
+ opacity: 0 !important; }
+
+.transparent {
+ background-color: rgba(255, 255, 255, 0) !important; }
+
+.hide {
+ display: none !important; }
+
+.show {
+ display: block !important; }
+
+.rel {
+ position: relative !important; }
+
+.legend-pad {
+ padding: 0 15px; }
+
+.border-top {
+ border-top-width: 1px !important; }
+
+.border-left {
+ border-left-width: 1px !important; }
+
+.border-right {
+ border-right-width: 1px !important; }
+
+.border-bottom {
+ border-bottom-width: 1px !important; }
+
+.border-dark {
+ border-color: #000; }
+
+.border-light {
+ border-color: #fff; }
+
+.no-border-top {
+ border-top-width: 0 !important; }
+
+.no-border-left {
+ border-left-width: 0 !important; }
+
+.no-border-right {
+ border-right-width: 0 !important; }
+
+.no-border-bottom {
+ border-bottom-width: 0 !important; }
+
+.align-middle {
+ margin: 0 auto !important; }
+
+.align-top {
+ position: absolute;
+ top: 0; }
+
+.align-bottom {
+ position: absolute;
+ bottom: 0; }
+
+.valign-top {
+ vertical-align: top !important; }
+
+.valign-middle {
+ vertical-align: middle !important; }
+
+.valign-bottom {
+ vertical-align: bottom !important; }
+
+.align-children-middle > * {
+ margin: 0 auto; }
+
+[class*="valign-children-"] {
+ display: table; }
+
+[class*="valign-children-"] > * {
+ display: table-cell; }
+
+.valign-children-top > * {
+ vertical-align: top; }
+
+.valign-children-middle > * {
+ vertical-align: middle; }
+
+.valign-children-bottom > * {
+ vertical-align: bottom; }
+
+.no-pad {
+ padding: 0 !important; }
+
+.top-space {
+ margin-top: 60px !important; }
+
+.bottom-space {
+ margin-bottom: 60px !important; }
+
+.top-pad {
+ padding-top: 60px !important; }
+
+.bottom-pad {
+ padding-bottom: 60px !important; }
+
+@media (max-width: 767px) {
+ .top-space {
+ margin-top: 30px !important; }
+ .bottom-space {
+ margin-bottom: 30px !important; }
+ .top-pad {
+ padding-top: 30px !important; }
+ .bottom-pad {
+ padding-bottom: 30px !important; } }
+
+.affix {
+ position: fixed; }
+
+.img-landscape,
+.img-portrait {
+ position: relative; }
+
+@media (orientation: landscape) {
+ .img-landscape {
+ display: block; }
+ .img-portrait {
+ display: none !important; } }
+
+@media (orientation: portrait) {
+ .img-landscape {
+ display: none !important; }
+ .img-portrait {
+ display: block; } }
+
+.dark-bg {
+ background-color: #222222; }
+
+/* ... JAVASCRIPT HOOKS .................
+ ... used by javascript ............... */
+.autoSize,
+.autoSize-this {
+ position: relative; }
+
+.truncate {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis; }
+
+.placeholdersjs {
+ color: #5a5a5a !important; }
+
+.jshook-return-focus-here {
+ display: block; }
+
+.visible-print {
+ display: none !important; }
+
+.hidden-print {
+ display: inherit !important; }
+
+@media print {
+ .visible-print {
+ display: inherit !important; }
+ .hidden-print {
+ display: none !important; }
+ * {
+ color: #000 !important;
+ background: transparent !important;
+ box-shadow: none !important; }
+ a,
+ a:visited {
+ text-decoration: underline; }
+ pre,
+ blockquote {
+ border: 1px solid #000;
+ page-break-inside: avoid; }
+ thead {
+ display: table-header-group; }
+ tr,
+ img {
+ page-break-inside: avoid; }
+ img {
+ max-width: 100% !important; }
+ @page {
+ margin: 0.5cm; }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3; }
+ h2,
+ h3 {
+ page-break-after: avoid; } }
+
+.mar-top-0 {
+ margin-top: 0px; }
+
+.mar-top-30 {
+ margin-top: 30px; }
+
+a:focus {
+ outline: thin dotted #191919; }
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-weight: normal;
+ text-rendering: optimizeLegibility;
+ margin: 0;
+ line-height: 1; }
+
+.heading-page {
+ font-size: 3.8rem !important;
+ font-family: "Omnes-ECOMP-W02-Light", Arial;
+ margin-bottom: 40px; }
+
+.heading-major-section {
+ font-size: 3rem !important;
+ font-family: "Omnes-ECOMP-W02-Light", Arial;
+ margin-bottom: 40px !important; }
+
+.heading-sub-section {
+ font-size: 2.4rem !important;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 40px; }
+
+.heading-group {
+ font-size: 2rem !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #ea7400;
+ margin-bottom: 20px !important; }
+
+.heading-medium {
+ font-size: 2rem !important;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px; }
+
+.heading-medium-emphasis {
+ font-size: 2rem !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ margin-bottom: 20px; }
+
+.heading-small {
+ font-size: 1.8rem !important;
+ font-family: "Omnes-ECOMP-W02";
+ margin-bottom: 20px; }
+
+.heading-small-emphasis {
+ font-size: 1.8rem !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ margin-bottom: 20px; }
+
+.heading-micro {
+ font-size: 1.3rem !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial
+ text-transform: uppercase;
+ color: #da0081;
+ margin-bottom: 10px; }
+
+* + .heading-major-section {
+ margin-top: 60px; }
+
+* + .heading-sub-section {
+ margin-top: 60px; }
+
+* + .heading-group {
+ margin-top: 40px !important; }
+
+* + .heading-medium {
+ margin-top: 40px; }
+
+* + .heading-medium-emphasis {
+ margin-top: 40px; }
+
+* + .heading-small {
+ margin-top: 40px; }
+
+* + .heading-small-emphasis {
+ margin-top: 40px; }
+
+* + .heading-micro {
+ margin-top: 20px; }
+
+.lead {
+ color: #666;
+ font-family: "Omnes-ECOMP-W02-Light-Italic", Arial
+ font-size: 2.4rem;
+ line-height: 2.8rem;
+ margin-top: 10px;
+ letter-spacing: -0.024rem; }
+
+.eyebrow {
+ text-transform: uppercase;
+ line-height: .65 !important; }
+
+.eyebrow,
+.subheading {
+ font-size: 1.4rem !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial
+ color: #666; }
+
+.eyebrow + .heading-major-section,
+.eyebrow + .heading-sub-section {
+ margin-top: 4px; }
+
+.subheading {
+ margin-top: 10px; }
+
+@media (max-width: 767px) {
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ .heading-page {
+ font-size: 2rem;
+ font-family: "Omnes-ECOMP-W02", Arial
+ margin-bottom: 30px; }
+ .heading-major-section {
+ font-size: 2rem;
+ font-family: "Omnes-ECOMP-W02", Arial
+ margin-bottom: 30px; }
+ .heading-sub-section {
+ font-size: 2rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px; }
+ .heading-medium {
+ font-size: 2rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px; }
+ .heading-medium-emphasis {
+ font-size: 2rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px; }
+ .heading-small {
+ font-size: 1.6rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 10px; }
+ .heading-small-emphasis {
+ font-size: 1.6rem;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ margin-bottom: 5px; }
+ * + .heading-major-section {
+ margin-top: 30px; }
+ * + .heading-sub-section {
+ margin-top: 30px; }
+ * + .heading-group {
+ margin-top: 20px; }
+ * + .heading-medium {
+ margin-top: 20px; }
+ * + .heading-medium-emphasis {
+ margin-top: 20px; }
+ * + .heading-small {
+ margin-top: 20px; }
+ * + .heading-small-emphasis {
+ margin-top: 20px; }
+ * + .heading-micro {
+ margin-top: 10px; } }
+
+/* Standard Type styles */
+.zeromargin {
+ margin: 0 !important; }
+
+a {
+ color: #0568ae;
+ text-decoration: none; }
+
+a:hover,
+a:focus {
+ text-decoration: underline; }
+
+a:active {
+ color: #0568ae; }
+
+.a-min {
+ font-size: 12px; }
+
+.a-small {
+ font-size: 14px; }
+
+.a-max {
+ font-size: 18px; }
+
+a.show-qualifier {
+ margin-right: 25px;
+ position: relative; }
+
+a.show-qualifier:after {
+ color: #333333;
+ display: inline-block;
+ white-space: pre !important; }
+
+a[href$="pdf"].show-qualifier:after,
+a.show-qualifier.pdf:after {
+ content: " (PDF)"; }
+
+a[href$="psd"].show-qualifier:after,
+a.show-qualifier.psd:after {
+ content: " (PSD)"; }
+
+.standalone-link {
+ display: flex; }
+
+/* 20px for the icon, 10px left of icon */
+.standalone-link.small {
+ font-size: 1.4rem; }
+
+.standalone-link.small i[class*="icon-primary-"] {
+ font-size: 16px;
+ top: 2px; }
+
+.standalone-link.large {
+ font-size: 1.8rem; }
+
+.standalone-link.large i[class*="icon-primary-"] {
+ font-size: 24px;
+ top: -1px; }
+
+p {
+ margin: 0 0 12px 0;
+ line-height: 2rem; }
+
+.p-small {
+ font-size: 1.4rem;
+ line-height: 1.8rem; }
+
+p + .p-small {
+ margin: 10px 0 0; }
+
+.p-micro {
+ font-size: 1.2rem;
+ line-height: 1.5rem; }
+
+p + .p-micro {
+ margin: 10px 0 0; }
+
+.p-max {
+ font-size: 1.8rem; }
+
+p + .p-max {
+ margin: 10px 0 0; }
+
+b,
+strong {
+ font-family: "Omnes-ECOMP-W02-Medium";
+ font-weight: normal; }
+
+i,
+em {
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ font-style: normal; }
+
+.strike {
+ text-decoration: line-through; }
+
+sup {
+ display: inline-block;
+ font-style: normal;
+ height: 1em;
+ position: relative;
+ vertical-align: text-top;
+ width: auto; }
+
+.text-legal {
+ color: #5a5a5a;
+ font-size: 1.1rem;
+ line-height: 1.5rem;
+ margin: 0 0 10px; }
+
+.text-legal.legal-module {
+ line-height: 1.3rem;
+ margin: 0 0 12px; }
+
+.text-legal b,
+.text-legal strong {
+ font-weight: bold; }
+
+.text-legal a {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.text-left {
+ text-align: left !important; }
+
+.text-right {
+ text-align: right !important; }
+
+.text-center {
+ text-align: center !important; }
+
+.text-justified {
+ text-align: justify !important; }
+
+ul {
+ padding: 0;
+ margin: 0;
+ list-style: none; }
+
+ul.bullet,
+ul.no-bullet,
+ul.lower-alpha,
+ul.lower-roman,
+ol {
+ padding: 0;
+ margin: 12px 0 0 20px; }
+
+ul.bullet li,
+ul.no-bullet li,
+ul.lower-alpha li,
+ul.lower-roman li,
+ol li {
+ padding-left: 15px;
+ line-height: 20px;
+ position: relative; }
+
+ul.bullet li + li,
+ul.no-bullet li + li,
+ul.lower-alpha li + li,
+ul.lower-roman li + li,
+ol li + li {
+ margin-top: 12px; }
+
+ul.bullet > li:before,
+ul.no-bullet > li:before,
+ul.lower-alpha > li:before,
+ul.lower-roman > li:before,
+ol > li:before {
+ background-color: #333333;
+ border: 2px solid #333333;
+ border-radius: 100%;
+ content: " ";
+ display: block;
+ height: 1px;
+ left: 0;
+ position: absolute;
+ top: 8px;
+ width: 1px; }
+
+ul.bullet ul,
+ul.no-bullet ul,
+ul.lower-alpha ul,
+ul.lower-roman ul,
+ol ul,
+ul.bullet ol,
+ul.no-bullet ol,
+ul.lower-alpha ol,
+ul.lower-roman ol,
+ol ol {
+ margin-top: 12px; }
+
+ul + *,
+ol + * {
+ margin-top: 20px; }
+
+ul.no-bullet,
+ul.lower-alpha,
+ul.lower-roman {
+ margin: 0; }
+
+ul.no-bullet > li,
+ul.lower-alpha > li,
+ul.lower-roman > li {
+ padding-left: 0; }
+
+ul.no-bullet > li:before,
+ul.lower-alpha > li:before,
+ul.lower-roman > li:before {
+ display: none !important; }
+
+ol {
+ margin: 20px 0 0 32px; }
+
+ol li {
+ padding-left: 3px; }
+
+ol li:before {
+ display: none; }
+
+ol ol {
+ margin-left: 25px; }
+
+ol ul {
+ margin-left: -5px; }
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin-top: 0; }
+
+ul.lower-roman {
+ list-style-type: lower-roman;
+ margin-top: 12px;
+ margin-left: 35px;
+ margin-bottom: 0; }
+
+ul.lower-alpha {
+ list-style-type: lower-alpha;
+ margin-top: 12px;
+ margin-left: 35px;
+ margin-bottom: 0; }
+
+dl {
+ display: table;
+ margin: 0 0 20px;
+ width: 100%; }
+
+dt,
+dd {
+ display: table-cell; }
+
+.btn {
+ background-color: transparent;
+ background-clip: padding-box;
+ border: 1px solid transparent;
+ border-radius: 8px;
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
+ cursor: pointer;
+ display: inline-block;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 1.9rem;
+ font-weight: normal;
+ line-height: 1;
+ margin: 0 7px 10px 0;
+ max-width: 470px;
+ min-width: 70px;
+ padding: 14px 19px 11px 18px;
+ position: relative;
+ text-align: center;
+ vertical-align: middle;
+ white-space: nowrap;
+ overflow: hidden; }
+ .btn:focus {
+ outline: 1px dotted #000;
+ outline-offset: -5px; }
+ .btn:last-child {
+ margin-right: 0; }
+ .btn::-moz-focus-inner {
+ padding: 0;
+ border: 0; }
+ .btn i[class*="icon-primary-"].icon-primary-small {
+ font-size: 24px;
+ top: -2px; }
+ .btn i[class*="icon-primary-"].icon-primary-medium {
+ font-size: 30px;
+ top: -2px; }
+ .btn i[class*="icon-primary-"].icon-primary-large {
+ font-size: 36px;
+ top: -2px; }
+
+a.btn {
+ vertical-align: middle; }
+ a.btn:hover {
+ text-decoration: none; }
+
+.field-group + .btn {
+ margin-left: 20px; }
+
+.btn-primary {
+ border-color: #ea7400 transparent #d16500;
+ background-color: #ea7400 transparent #d16500;
+ background: linear-gradient(to bottom, #ea7400 0%, #d16500 100%);
+ color: #ffffff;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-weight: bold; }
+ .btn-primary:hover {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+ .btn-primary:focus {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+ .btn-primary:active {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+
+.btn-arrow {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.6rem;
+ font-weight: normal;
+ background-color: transparent;
+ border: none;
+ padding: 5px 0 0;
+ top: -4px;
+ color: #333333;
+ position: relative; }
+ .btn-arrow:hover {
+ text-decoration: underline; }
+ .btn-arrow:hover .btn-primary {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+ .btn-arrow:hover .btn-secondary {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+ .btn-arrow:hover .btn-alt {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%); }
+ .btn-arrow:hover .btn-specialty {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+ .btn-arrow:focus {
+ text-decoration: underline;
+ outline: 1px dotted #666; }
+ .btn-arrow:focus .btn-primary {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+ .btn-arrow:focus .btn-secondary {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+ .btn-arrow:focus .btn-alt {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%); }
+ .btn-arrow:focus .btn-specialty {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+ .btn-arrow:active .btn-primary {
+ text-decoration: none;
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #d16500 0%, #ea7400 100%); }
+ .btn-arrow:active .btn-secondary {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+ .btn-arrow:active .btn-alt {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%); }
+ .btn-arrow:active .btn-specialty {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+ .btn-arrow .btn-alt {
+ border-color: #087ac2 transparent #0568ae;
+ background-color: #0568ae;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%);
+ color: #ffffff; }
+ .btn-arrow .btn-alt:hover {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+ .btn-arrow .btn-alt:focus {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+ .btn-arrow .btn-alt:active {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+ .btn-arrow::-moz-focus-inner {
+ padding: 0;
+ border: 0; }
+ .btn-arrow .btn {
+ border: 1px solid transparent;
+ border-radius: 100%;
+ height: 36px;
+ margin-bottom: 0;
+ margin-right: 7px;
+ max-width: 36px;
+ min-width: 20px;
+ padding: 0;
+ margin-top: -4px;
+ vertical-align: middle;
+ width: 36px; }
+ .btn-arrow .btn .icon-primary-left {
+ bottom: 0;
+ display: block;
+ height: 100%;
+ left: 0;
+ line-height: 0;
+ position: absolute;
+ right: 0;
+ text-indent: 0;
+ top: 0; }
+ .btn-arrow .btn .icon-primary-left:before {
+ position: absolute;
+ font-size: 1.6rem;
+ left: 1px;
+ top: 9px; }
+ .btn-arrow .btn .icon-primary-right {
+ bottom: 0;
+ display: block;
+ height: 100%;
+ left: 0;
+ line-height: 0;
+ position: absolute;
+ right: 0;
+ text-indent: 0;
+ top: 0;
+ color: #ffffff; }
+ .btn-arrow .btn .icon-primary-right:before {
+ position: absolute;
+ font-size: 1.6rem;
+ left: 17px;
+ top: 9px; }
+ .btn-arrow .btn.btn-primary .icon-primary-left {
+ color: #fff; }
+ .btn-arrow .btn.btn-primary .icon-primary-right {
+ color: #fff; }
+ .btn-arrow .btn.btn-alt .icon-primary-left {
+ color: #fff; }
+ .btn-arrow .btn.btn-alt .icon-primary-right {
+ color: #fff; }
+ .btn-arrow .btn.btn-secondary {
+ border: 1px solid #d2d2d2; }
+ .btn-arrow .btn.btn-secondary .icon-primary-left {
+ color: #0568ae; }
+ .btn-arrow .btn.btn-secondary .icon-primary-right {
+ color: #0568ae; }
+ .btn-arrow .btn.btn-small {
+ height: 20px;
+ max-width: 20px;
+ min-width: 20px;
+ width: 20px;
+ top: -1px; }
+ .btn-arrow .btn.btn-small .icon-primary-left:before {
+ font-size: 10px;
+ top: 4px;
+ left: 0; }
+ .btn-arrow .btn.btn-small .icon-primary-right:before {
+ font-size: 10px;
+ top: 4px;
+ left: 10px; }
+ .btn-arrow .btn.btn-large .icon-primary-left:before {
+ font-size: 112%;
+ top: 12px;
+ left: 23px; }
+ .btn-arrow .btn.btn-large .icon-primary-right:before {
+ font-size: 112%;
+ top: 12px;
+ left: 23px; }
+
+.btn-secondary {
+ border: 1px solid #d2d2d2;
+ background-color: #f2f2f2;
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ color: #0568ae;
+ box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.15);
+ padding: 14px 18px 11px 17px; }
+ .btn-secondary:hover {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+ .btn-secondary:focus {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+ .btn-secondary:active {
+ color: #0568ae;
+ outline-color: #000000 !important;
+ background: linear-gradient(to bottom, #f2f2f2 0%, #fcfcfc 100%); }
+
+.btn-alt {
+ border-color: #087ac2 transparent #0568ae;
+ background-color: #0568ae;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%);
+ color: #ffffff; }
+ .btn-alt:hover {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+ .btn-alt:focus {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+ .btn-alt:active {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #0568ae 0%, #087ac2 100%); }
+
+.btn-specialty {
+ border-color: #008744 transparent #007a3e;
+ background-color: #007a3e;
+ background: linear-gradient(to bottom, #008744 0%, #007a3e 100%);
+ color: #ffffff; }
+ .btn-specialty:hover {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+ .btn-specialty:focus {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+ .btn-specialty:active {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: linear-gradient(to bottom, #007a3e 0%, #008744 100%); }
+
+.btn-clear {
+ background: transparent !important;
+ border-color: transparent !important;
+ font-weight: normal;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ box-shadow: none;
+ text-decoration: none;
+ color: #0568ae; }
+ .btn-clear:focus {
+ text-decoration: underline; }
+ .btn-clear:hover {
+ text-decoration: underline; }
+
+.isIE .btn:focus {
+ outline: none !important;
+ text-decoration: none !important; }
+ .isIE .btn:focus:after {
+ display: block;
+ content: "";
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ right: 4px;
+ bottom: 4px;
+ border: 1px dotted #000; }
+
+.isIE .btn:active {
+ outline: none !important;
+ text-decoration: none !important; }
+ .isIE .btn:active:after {
+ display: block;
+ content: "";
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ right: 4px;
+ bottom: 4px;
+ border: 1px dotted #000; }
+
+.isIE .btn.active {
+ outline: none !important;
+ text-decoration: none !important; }
+ .isIE .btn.active:not(:focus):after {
+ border: 1px solid #000; }
+ .isIE .btn.active:after {
+ display: block;
+ content: "";
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ right: 4px;
+ bottom: 4px;
+ border: 1px dotted #000; }
+
+.isIE .btn.btn-primary:focus:after {
+ border: 2px dashed #fff; }
+
+.isIE .btn.btn-specialty:focus:after {
+ border: 2px dashed #fff; }
+
+.isIE .btn.btn-alt:focus:after {
+ border: 2px dashed #fff; }
+
+.btn.disabled {
+ background-image: none;
+ background-color: #767676;
+ box-shadow: none;
+ cursor: not-allowed;
+ color: #ffffff;
+ border-color: transparent;
+ outline: 0 !important; }
+ .btn.disabled:hover {
+ color: #f2f2f2;
+ outline: none !important; }
+ .btn.disabled:focus {
+ color: #f2f2f2;
+ outline: none !important; }
+
+.btn[disabled] {
+ background-image: none;
+ background-color: #767676;
+ box-shadow: none;
+ cursor: not-allowed;
+ color: #ffffff;
+ border-color: transparent;
+ outline: 0 !important; }
+ .btn[disabled]:hover {
+ color: #f2f2f2;
+ outline: none !important; }
+ .btn[disabled]:focus {
+ color: #f2f2f2;
+ outline: none !important; }
+
+.btn[disabled="disabled"] {
+ background-image: none;
+ background-color: #767676;
+ box-shadow: none;
+ cursor: not-allowed;
+ color: #ffffff;
+ border-color: transparent;
+ outline: 0 !important; }
+ .btn[disabled="disabled"]:hover {
+ color: #f2f2f2;
+ outline: none !important; }
+ .btn[disabled="disabled"]:focus {
+ color: #f2f2f2;
+ outline: none !important; }
+
+.btn-arrow[disabled] .btn {
+ background-image: none;
+ background-color: #767676;
+ box-shadow: none;
+ cursor: not-allowed;
+ color: #ffffff;
+ border-color: transparent;
+ outline: 0 !important; }
+ .btn-arrow[disabled] .btn:hover {
+ color: #f2f2f2;
+ outline: none !important; }
+ .btn-arrow[disabled] .btn:focus {
+ color: #f2f2f2;
+ outline: none !important; }
+
+.btn-arrow[disabled] .icon-primary-left {
+ color: #fff !important; }
+
+.btn-arrow[disabled] .icon-primary-right {
+ color: #fff !important; }
+
+.btn-arrow.disabled .btn {
+ background-image: none;
+ background-color: #767676;
+ box-shadow: none;
+ cursor: not-allowed;
+ color: #ffffff;
+ border-color: transparent;
+ outline: 0 !important; }
+ .btn-arrow.disabled .btn:hover {
+ color: #f2f2f2;
+ outline: none !important; }
+ .btn-arrow.disabled .btn:focus {
+ color: #f2f2f2;
+ outline: none !important; }
+
+.btn-arrow.disabled .icon-primary-left {
+ color: #fff !important; }
+
+.btn-arrow.disabled .icon-primary-right {
+ color: #fff !important; }
+
+.btn-medium {
+ padding: 12px 19px 11px 18px;
+ font-size: 1.7rem; }
+
+.btn-small {
+ padding: 10px 19px 9px 18px;
+ font-size: 1.5rem;
+ border-radius: 8px; }
+
+.btn-fullwidth {
+ width: 100%; }
+
+*:not(.btn-arrow) > .btn > i[class*="icon-primary-"] {
+ margin-top: -20px;
+ margin-bottom: -20px; }
+
+.enhanced-cta-group {
+ display: -ms-flexbox;
+ display: flex;
+ -ms-flex-direction: row-reverse;
+ flex-direction: row-reverse;
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3A%23959595%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E") !important;
+ background-position: 0 -1px;
+ background-repeat: repeat-x; }
+ .enhanced-cta-group > .cta-button-group {
+ border-top: 0;
+ background-image: none !important; }
+ .enhanced-cta-group > .cta-button-group + .cta-button-group a {
+ font-size: 1.4rem;
+ line-height: 1em; }
+ .enhanced-cta-group > .cta-button-group + .cta-button-group a a {
+ margin-right: 0; }
+ .enhanced-cta-group > .cta-button-group hr {
+ min-height: 14px; }
+ .enhanced-cta-group > .cta-button-group + .cta-button-group {
+ -ms-flex-align: center;
+ -ms-grid-row-align: center;
+ align-items: center;
+ -ms-flex-direction: row;
+ flex-direction: row;
+ padding: 10px 0; }
+
+.cta-button-group {
+ text-align: right;
+ -ms-flex-align: baseline;
+ align-items: baseline;
+ padding: 20px 0 10px;
+ width: 100%; }
+ .cta-button-group.nodots {
+ background-image: none !important; }
+ .cta-button-group .hidden-phone {
+ margin-right: 14px; }
+ .cta-button-group .btn + .btn {
+ margin-right: 20px !important; }
+ .cta-button-group .btn:not(.hidden-phone):not(.visible-phone) {
+ margin-right: 0; }
+
+.isMobile .btn-arrow .btn.btn-small .icon-primary-left:before {
+ left: -1px; }
+
+.isMobile .btn-arrow .btn.btn-large .icon-primary-left:before {
+ left: 24px; }
+
+.isMobile .btn-arrow .btn.btn-large .icon-primary-right:before {
+ left: 24px; }
+
+@media (max-width: 1024px) {
+ .field-group + .btn {
+ margin-left: 15px; } }
+
+@media (max-width: 767px) {
+ .cta-button-group {
+ text-align: center; }
+ .cta-button-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ margin-left: auto !important;
+ margin-right: auto !important; } }
+
+.btn-group {
+ border-radius: 8px;
+ box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.15);
+ display: -ms-flexbox;
+ display: flex;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ margin-bottom: 10px;
+ max-width: 470px;
+ min-width: 290px;
+ position: relative;
+ vertical-align: middle;
+ width: 100%; }
+ .btn-group > .btn {
+ box-shadow: none;
+ -ms-flex: 1;
+ flex: 1;
+ position: relative;
+ float: left;
+ margin-right: -1px;
+ margin-bottom: 0;
+ padding-left: 0;
+ padding-right: 0;
+ text-align: center; }
+ .btn-group:not([data-select-color]) .btn.active:not(:first-child) {
+ margin-right: -1px;
+ border-left: 1px solid #d2d2d2 !important; }
+ .btn-group:not([data-select-color]) .btn[disabled]:not(:first-child) {
+ border-left: 1px solid #d2d2d2 !important; }
+ .btn-group:not([data-select-color]) .btn[disabled] + .btn[disabled] {
+ border-left: 1px solid #ebebeb !important; }
+ .btn-group:not([data-select-color]) > .btn.active {
+ border-color: #087ac2 transparent #0568ae;
+ background-color: #0568ae;
+ background: linear-gradient(to bottom, #087ac2 0%, #0568ae 100%);
+ color: #ffffff; }
+ .btn-group:not([data-select-color]) > .btn.active:hover {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: #0563a6;
+ border-color: #0563a6; }
+ .btn-group:not([data-select-color]) > .btn.active:focus {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: #0563a6;
+ border-color: #0563a6; }
+ .btn-group:not([data-select-color]) > .btn.active:active {
+ color: #ffffff;
+ outline-color: #ffffff !important;
+ background: #0563a6;
+ border-color: #0563a6; }
+ .btn-group:not([data-select-color]) > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0; }
+ .btn-group:not([data-select-color]) > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0; }
+ .btn-group:not([data-select-color]) > .btn:last-child:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0; }
+ .btn-group:not([data-select-color]) > .dropdown-toggle:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0; }
+ .btn-group > .active {
+ text-decoration: none;
+ outline: 1px dotted transparent; }
+ .btn-group > .active:focus {
+ outline: 1px dotted #ffffff; }
+
+.btn-group.btn-fullwidth > .btn {
+ -ms-flex: 1;
+ flex: 1; }
+
+.btn-group[data-select-color] {
+ margin-top: 5px;
+ box-shadow: none;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -ms-flex-wrap: wrap;
+ flex-wrap: wrap; }
+ .btn-group[data-select-color] .btn {
+ border: 1px solid #959595;
+ border-radius: 4px;
+ box-shadow: 0 5px 5px -5px rgba(0, 0, 0, 0.15);
+ margin-right: 10px;
+ margin-bottom: 10px;
+ height: 40px;
+ font-size: 16px;
+ color: #333333;
+ max-width: 60px;
+ min-width: 60px;
+ -ms-flex: 0;
+ flex: 0; }
+ .btn-group[data-select-color] > .btn.active:focus {
+ outline: 1px dotted #191919;
+ outline-offset: 4px; }
+
+button .btn-fill {
+ background-clip: padding-box;
+ border: 0;
+ border-radius: 4px;
+ bottom: 0;
+ display: block;
+ height: auto;
+ left: 0;
+ margin: 5px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: auto; }
+
+button .btn-fill[style*="#fff"] {
+ border: 1px solid #d2d2d2; }
+
+[data-select-color] .btn.active {
+ background: none !important;
+ outline: 0;
+ margin-right: 10px;
+ border-width: 3px;
+ color: #333333;
+ line-height: 12px; }
+ [data-select-color] .btn.active > .btn-fill {
+ margin: 3px; }
+ [data-select-color] .btn.active:hover {
+ color: #333333; }
+
+[data-select-color] .btn:active {
+ background: none !important;
+ outline: 0;
+ margin-right: 10px;
+ border-width: 3px;
+ color: #333333;
+ line-height: 12px; }
+ [data-select-color] .btn:active > .btn-fill {
+ margin: 3px; }
+ [data-select-color] .btn:active:hover {
+ color: #333333; }
+
+.btn-group[data-select-color="orange"] > .btn.active {
+ border-color: #ea7400; }
+
+.btn-group[data-select-color="blue"] > .btn.active {
+ border-color: #0568ae; }
+
+.btn-group[data-select-color="green"] > .btn.active {
+ border-color: #007a3e; }
+
+.btn-spinbutton-toggle.btn-group {
+ display: block !important;
+ height: 40px !important;
+ margin-top: 5px;
+ max-width: 138px;
+ min-width: 138px;
+ white-space: nowrap; }
+
+.btn-spinbutton-toggle .btn {
+ border-radius: 6px;
+ font-weight: normal;
+ -ms-flex: unset;
+ flex: unset;
+ height: 40px;
+ letter-spacing: normal;
+ min-width: auto;
+ padding: 3px 0 0;
+ text-align: center;
+ min-width: 46px;
+ width: 46px; }
+
+.btn-spinbutton-toggle .btn[data-max-value] {
+ border-bottom: 1px solid #d2d2d2;
+ border-top: 1px solid #d2d2d2;
+ box-shadow: 0 3px 2px -2px rgba(0, 0, 0, 0.08) inset;
+ background-color: #fff;
+ cursor: text;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 2rem;
+ font-weight: normal;
+ padding: 4px 0 0;
+ text-align: center;
+ min-width: 46px !important;
+ width: 46px; }
+ .btn-spinbutton-toggle .btn[data-max-value]:focus {
+ border-color: #0568ae;
+ outline: none; }
+ .btn-spinbutton-toggle .btn[data-max-value]:focus + .btn {
+ border-left: 1px solid #0568ae;
+ transition: border 0.3s linear 0s; }
+
+.btn-spinbutton-toggle .icon-primary-subtractminimize {
+ font-size: 30px !important;
+ color: #0568ae !important; }
+
+.btn-spinbutton-toggle .icon-primary-add-maximize {
+ font-size: 30px !important;
+ color: #0568ae !important; }
+
+.btn-spinbutton-toggle .btn[disabled].icon-primary-subtractminimize {
+ background-color: #d2d2d2;
+ color: #767676 !important; }
+
+.btn-spinbutton-toggle .btn[disabled].icon-primary-add-maximize {
+ background-color: #d2d2d2;
+ color: #767676 !important; }
+
+.btn-spinbutton-toggle input.btn[disabled] {
+ background-color: #d2d2d2;
+ color: #5a5a5a;
+ cursor: not-allowed; }
+
+.btn-group.btn-spinbutton-toggle .btn[disabled] + .btn[disabled] {
+ border-left: 1px solid #f0f0f0 !important; }
+
+.btn-group.btn-spinbutton-toggle .btn[data-max-value]:focus + .btn:not(:first-child) {
+ border-left: 1px solid #0568ae !important; }
+
+@media (max-width: 480px) {
+ .btn-group:not([data-select-color]) > .btn {
+ font-size: 1.3rem;
+ min-width: auto; } }
+
+.reset-field,
+.close {
+ float: right;
+ background: none;
+ width: 34px;
+ height: 34px;
+ padding: 0;
+ overflow: hidden;
+ display: inline-block; }
+
+.reset-field {
+ display: none; }
+
+.reset-field:before {
+ font-size: 22px;
+ color: #5a5a5a; }
+
+.input-emphasized + .reset-field:before {
+ font-size: 29px;
+ color: #5a5a5a; }
+
+.reset-field:active,
+.reset-field:hover,
+.reset-field:focus {
+ display: block !important; }
+
+button.close {
+ border: 0;
+ appearance: none; }
+
+.corner-button {
+ box-shadow: 0 -50px 0 0 #f2f2f2 inset;
+ height: 69px;
+ /*overflow: hidden;*/
+ position: absolute;
+ right: -35px;
+ top: -35px;
+ transform: rotate(45deg);
+ width: 69px; }
+
+.corner-button .close:before {
+ bottom: -7px;
+ color: #0568ae;
+ display: block;
+ font-size: 20px;
+ height: 50px;
+ left: -11px;
+ position: absolute;
+ width: 50px; }
+
+.corner-button .close {
+ float: none;
+ height: 45px;
+ margin: 0;
+ position: absolute;
+ right: 12px;
+ top: 45px;
+ transform: rotate(45deg);
+ width: 45px; }
+
+.corner-button .close:focus {
+ outline: 1px dotted black; }
+
+.ds2-no-colors .corner-button .close {
+ border: 1px solid black; }
+
+.field-group input + .reset-field {
+ background: none;
+ height: 36px;
+ width: 45px;
+ display: none;
+ padding: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ box-shadow: none;
+ border: none;
+ content: " "; }
+
+.field-group input[type="search"] + .reset-field,
+.field-group input[type="search"] + .btn-search + .reset-field,
+.tooltip-onclick input + .reset-field,
+.tooltip-onclick input + .icon-primary-tooltip + .reset-field,
+.tooltip-onclick textarea + .reset-field,
+.tooltip-onclick textarea + .icon-primary-tooltip + .reset-field {
+ right: 45px; }
+
+.field-group input[type="search"] + .reset-field:after,
+.field-group input[type="search"] + .btn-search + .reset-field:after,
+.tooltip-onclick input + .reset-field:after,
+.tooltip-onclick input + .icon-primary-tooltip + .reset-field:after,
+.tooltip-onclick textarea + .reset-field:after,
+.tooltip-onclick textarea + .icon-primary-tooltip + .reset-field:after {
+ background-color: #d2d2d2;
+ content: "";
+ display: block;
+ height: 20px;
+ position: absolute;
+ right: 0;
+ top: 8px;
+ width: 1px; }
+
+.tooltip-onclick input + .reset-field,
+.tooltip-onclick input + .icon-primary-tooltip + .reset-field {
+ right: 50px !important; }
+
+.tooltip-onclick textarea + .reset-field,
+.tooltip-onclick textarea + .icon-primary-tooltip + .reset-field {
+ right: 45px !important;
+ width: 40px; }
+
+.field-group input.input-emphasized + .reset-field {
+ width: 45px;
+ height: 46px;
+ right: 6px; }
+
+.field-group input.input-emphasized + .reset-field:after {
+ top: 14px; }
+
+.field-group [disabled] + .reset-field {
+ display: none; }
+
+.ds2_touchevents .field-group input + .reset-field:focus,
+.ds2_touchevents .field-group input:focus + .reset-field,
+.ds2_touchevents textarea:focus + .reset-field,
+.ds2_touchevents textarea + .reset-field:focus {
+ display: block;
+ position: absolute;
+ right: 0px;
+ top: 0;
+ border: none; }
+
+.ds2_touchevents .field-group input {
+ padding: 8px 55px 8px 15px;
+ -webkit-appearance: none; }
+
+.ds2_touchevents textarea:focus {
+ padding: 15px 55px 15px 15px; }
+
+.ds2_touchevents textarea:focus + .reset-field {
+ border: none;
+ position: absolute;
+ right: 6px;
+ top: 5px; }
+
+.ds2_touchevents textarea.hasScrollbar:focus {
+ padding: 15px 35px 15px 15px; }
+
+.ds2_touchevents textarea.hasScrollbar:focus + .reset-field {
+ right: 22px; }
+
+.form-row.error .error-msg {
+ display: block;
+ font-size: 14px;
+ line-height: 14px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ position: relative;
+ padding-left: 18px; }
+
+.form-row.error .error-msg:before {
+ color: #cf2a2a;
+ font-size: 14px;
+ left: 0;
+ line-height: 14px;
+ position: absolute;
+ vertical-align: middle; }
+
+.form-row.error label,
+.form-row.error .error-msg,
+.form-row.error button.awd-select,
+.form-row.error select.awd-select + span,
+.form-row.error .checkbox,
+.form-row.error .radio,
+.form-row.error legend.error,
+.form-row.error input {
+ color: #cf2a2a; }
+
+.form-row.error .btn-group > .btn,
+.form-row.error button.awd-select,
+.form-row.error .awd-select-list,
+.form-row.error select.awd-select + span,
+.form-row.error textarea,
+.form-row.error input,
+.form-row.error .checkbox .skin,
+.form-row.error .radio .skin {
+ border-color: #cf2a2a !important; }
+
+.form-row.error .checkbox input:checked:not(:disabled) + .skin {
+ background-color: #cf2a2a; }
+
+.form-row.error .radio input:checked + .skin:after {
+ background-color: #cf2a2a; }
+
+.error .tooltip-onclick .icon-primary-tooltip.active + .error-msg {
+ margin-top: -11px;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+
+.error .tooltip-onclick .icon-primary-tooltip.active + .error-msg + .helpertext {
+ margin: 0 0 10px; }
+
+.error .tooltip-onclick .icon-primary-tooltip.active + .error-msg + .helpertext:before,
+.error .tooltip-onclick .icon-primary-tooltip.active + .error-msg + .helpertext:after {
+ display: none; }
+
+.error .helpertext {
+ border-color: #cf2a2a;
+ /*border-radius:0;*/ }
+
+.error .helpertext:before {
+ border-top-color: #cf2a2a; }
+
+.error .tooltip-onfocus .helpertext {
+ margin: 14px 0 10px 0; }
+
+.error [class*="price"],
+.error [class*="pricing-"] {
+ color: #cf2a2a; }
+
+input:-ms-clear {
+ display: none; }
+
+input[type]::-webkit-inner-spin-button,
+input[type]::-webkit-outer-spin-button {
+ -webkit-appearance: none; }
+
+input[type] {
+ -moz-appearance: textfield; }
+
+form {
+ margin: 0; }
+
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0; }
+
+label,
+legend {
+ display: inline-block;
+ font-size: 1.4rem;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+legend {
+ display: block; }
+
+.error-msg {
+ display: none; }
+
+select,
+textarea,
+input {
+ border-radius: 6px;
+ color: #5a5a5a;
+ display: inline-block;
+ font-size: 1.6rem;
+ margin: 0px;
+ padding: 0 15px 0 15px;
+ vertical-align: middle;
+ line-height: normal; }
+
+select::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder,
+input::-webkit-input-placeholder {
+ color: #5a5a5a;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ font-style: normal;
+ opacity: 1; }
+
+select:-moz-placeholder,
+textarea:-moz-placeholder,
+input:-moz-placeholder {
+ color: #5a5a5a;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ font-style: normal;
+ opacity: 1; }
+
+select::-moz-placeholder,
+textarea::-moz-placeholder,
+input::-moz-placeholder {
+ color: #5a5a5a;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ font-style: normal;
+ opacity: 1; }
+
+select:-ms-input-placeholder,
+textarea:-ms-input-placeholder,
+input:-ms-input-placeholder {
+ color: #5a5a5a;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ transition: none;
+ opacity: 1; }
+
+select:placeholder,
+textarea:placeholder,
+input:placeholder {
+ color: #5a5a5a;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial;
+ font-style: normal;
+ opacity: 1; }
+
+select:last-child,
+textarea:last-child,
+input:last-child {
+ margin-right: 0; }
+
+input:not([type="button"]) {
+ height: 36px; }
+
+input.input-emphasized {
+ font-size: 1.8rem;
+ height: 48px;
+ padding: 13px 20px 13px; }
+
+input[type="search"]:focus {
+ padding-right: 88px; }
+
+input[type="search"] {
+ padding-right: 40px;
+ -webkit-appearance: none !important; }
+
+input[type="search"].input-emphasized {
+ padding-right: 45px; }
+
+.btn-search[class*="btn"] {
+ background-color: transparent;
+ background-position: 50% 50%;
+ background-size: 20px;
+ background-repeat: no-repeat;
+ border: none;
+ height: 100%;
+ margin-left: 0;
+ margin-top: 0;
+ min-width: 45px !important;
+ outline-offset: 0;
+ padding: 0 !important;
+ position: absolute;
+ right: 0;
+ top: 0;
+ border-radius: 0 5px 5px 0;
+ min-width: 44px;
+ width: 44px; }
+
+.input-emphasized + .btn-search[class*="btn"],
+.input-emphasized + .reset-field + .btn-search[class*="btn"] {
+ background-size: 26px;
+ height: 46px;
+ top: 1px;
+ outline-offset: -3px;
+ margin-bottom: 0;
+ border-radius: 0 5px 5px 0; }
+
+input[type="search"].input-emphasized + .reset-field {
+ right: 45px !important; }
+
+.search-suggestion-wrapper {
+ position: relative;
+ margin-bottom: 15px; }
+
+/*styles from dropdown*/
+.search-suggestion-list {
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.15);
+ border-radius: 0 0 6px 6px;
+ position: relative;
+ border: 1px solid #0568ae;
+ border-top: 0;
+ padding: 15px 0;
+ background-color: #f2f2f2;
+ z-index: 1000;
+ width: 100%;
+ max-height: 400px;
+ overflow-y: auto; }
+
+.search-suggestion-list:empty {
+ display: none; }
+
+.search-suggestion-item {
+ position: relative;
+ z-index: -1;
+ padding: 0 15px;
+ line-height: 4.0rem;
+ color: #5a5a5a; }
+
+.search-suggestion-item a {
+ text-decoration: none;
+ color: #5a5a5a; }
+
+.search-suggestion-item:hover,
+.search-suggestion-item:focus {
+ cursor: pointer;
+ background-color: #d2d2d2; }
+
+input[data-provide="datepicker"],
+[data-provide="datepicker"]:-moz-placeholder,
+[data-provide="datepicker"]:-ms-input-placeholder,
+[data-provide="datepicker"]:-webkit-input-placeholder {
+ color: #0568ae !important;
+ opacity: 1;
+ filter: alpha(opacity=100); }
+
+input[disabled],
+input[readonly],
+select[disabled],
+select[readonly],
+textarea[disabled],
+textarea[readonly],
+span.icon-primary-calendar.disabled,
+span.icon-primary-calendar.readonly {
+ cursor: not-allowed;
+ background-color: #f2f2f2;
+ box-shadow: none; }
+
+span.icon-primary-calendar.disabled input,
+span.icon-primary-calendar.readonly input {
+ color: #959595 !important; }
+
+textarea {
+ display: block;
+ width: 100%;
+ max-width: 100%;
+ padding: 15px; }
+
+textarea.small {
+ line-height: 20px; }
+
+textarea + .reset-field {
+ display: none; }
+
+textarea::-webkit-input-placeholder {
+ line-height: .99; }
+
+textarea:-moz-placeholder {
+ line-height: .99; }
+
+textarea::-moz-placeholder {
+ line-height: .99; }
+
+textarea:-ms-input-placeholder {
+ line-height: .99; }
+
+textarea:placeholder {
+ line-height: .99; }
+
+textarea,
+input {
+ background-color: #ffffff;
+ border: 1px solid #d2d2d2;
+ -webkit-appearance: none;
+ box-shadow: 2px 3px 2px -2px rgba(0, 0, 0, 0.08) inset;
+ transition: border .3s linear 0s;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+textarea:focus,
+input:focus {
+ outline: 0;
+ border-color: #0568ae; }
+
+.input-append {
+ display: table; }
+
+.input-append > div {
+ display: table-cell;
+ width: 1%; }
+
+.input-append > .field-group {
+ width: 100%; }
+
+.row .field-group input[class*="span"] {
+ float: none; }
+
+.field-group {
+ position: relative;
+ display: inline-block; }
+
+label + .field-group,
+label + .input-append,
+label + .row,
+label + .row-nowrap,
+label + .form-row {
+ margin-top: 5px; }
+
+.field-group {
+ position: relative;
+ display: block; }
+
+.field-group input:not([type="button"])[disabled] {
+ padding-right: 15px; }
+
+input:invalid,
+textarea:invalid,
+select:invalid {
+ outline: none !important; }
+
+.form-row {
+ margin-top: 20px; }
+
+.form-row.nomar {
+ margin: 0; }
+
+.row-nowrap.no-flex.form-row > label + br {
+ margin-bottom: 5px; }
+
+span.form-row {
+ display: inline-block; }
+
+legend + .form-row {
+ margin-top: 20px; }
+
+.tooltip-onclick input {
+ padding-right: 45px; }
+
+.ds2_touchevents .tooltip-onclick input:focus {
+ padding-right: 95px; }
+
+span.icon-primary-calendar {
+ display: block;
+ position: relative;
+ background-color: #fff;
+ border-radius: 4px;
+ overflow: hidden;
+ height: 36px; }
+
+span.icon-primary-calendar:before {
+ position: absolute;
+ top: 7px;
+ left: 13px;
+ color: #0568ae; }
+
+span.icon-primary-calendar.disabled {
+ background-color: #f2f2f2; }
+
+span.icon-primary-calendar.disabled:before {
+ color: #959595; }
+
+span.icon-primary-calendar input {
+ padding-left: 35px;
+ color: #0568ae;
+ transition: border-color 0.3s linear 0s;
+ box-shadow: 2px 3px 2px -2px rgba(0, 0, 0, 0.08) inset;
+ position: absolute;
+ top: 0;
+ left: 0; }
+
+.faux-input + input.datepicker-input:not([disabled]) {
+ cursor: pointer;
+ margin-left: 0;
+ background-color: #fff;
+ position: absolute;
+ left: 0;
+ top: 0;
+ z-index: 0; }
+
+.faux-input {
+ background-color: transparent !important;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ font-size: 1.6rem;
+ height: 35px;
+ left: 0;
+ line-height: 35px;
+ margin-bottom: 10px;
+ margin-right: 6px;
+ padding: 0 0 0 35px;
+ position: relative;
+ text-align: left;
+ top: 0;
+ vertical-align: middle;
+ width: 100%;
+ z-index: 1; }
+
+.faux-input:disabled {
+ cursor: not-allowed; }
+
+.faux-input:focus + .datepicker-input,
+[data-calendar-state="opened"] + .datepicker-input {
+ border-color: #0568ae;
+ box-shadow: 2px 3px 2px -2px rgba(5, 116, 172, 0.35) inset;
+ outline: 0 none; }
+
+.form-row.error .error-msg {
+ display: block;
+ font-size: 14px;
+ line-height: 14px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ position: relative;
+ padding-left: 18px;
+ margin-top: 10px; }
+
+.form-row.error .error-msg > .icon-primary-badgealert {
+ height: 14px;
+ width: 14px;
+ position: absolute;
+ left: 0;
+ margin-right: 0; }
+
+.form-row.error .error-msg > .icon-primary-badgealert:before {
+ color: #cf2a2a;
+ font-size: 14px;
+ left: 0;
+ line-height: 14px;
+ position: absolute;
+ vertical-align: middle; }
+
+.form-row.error label,
+.form-row.error .error-msg,
+.form-row.error button.awd-select,
+.form-row.error select.awd-select + span,
+.form-row.error .checkbox,
+.form-row.error .radio,
+.form-row.error legend.error,
+.form-row.error input,
+.form-row.error textarea {
+ color: #cf2a2a; }
+
+.form-row.error .btn-group > .btn,
+.form-row.error button.awd-select,
+.form-row.error .awd-select-list,
+.form-row.error select.awd-select + span,
+.form-row.error textarea,
+.form-row.error input,
+.form-row.error .checkbox .skin,
+.form-row.error .radio .skin {
+ border-color: #cf2a2a !important; }
+
+.form-row.error .checkbox input:checked:not(:disabled) + .skin {
+ background-color: #cf2a2a; }
+
+.form-row.error .radio input:checked + .skin:after {
+ background-color: #cf2a2a; }
+
+.error [class*="price"],
+.error [class*="pricing-"] {
+ color: #cf2a2a; }
+
+hr,
+.hr-or {
+ display: block;
+ height: 1px;
+ margin: 15px 0;
+ border: none;
+ background-repeat: repeat-x;
+ background-color: #959595;
+ position: relative; }
+
+hr.dark {
+ background-color: #959595; }
+
+hr.lite {
+ background-color: #d2d2d2; }
+
+.hr-or:before {
+ background-color: #fff;
+ color: #666;
+ content: " OR ";
+ display: block;
+ font-size: 1.4rem;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ height: 16px;
+ left: 50%;
+ line-height: 1.6rem;
+ margin-left: -15px;
+ margin-top: -8px;
+ position: absolute;
+ text-align: center;
+ top: 50%;
+ width: 30px;
+ z-index: 1111; }
+
+hr.hr-dotted.dark {
+ background-color: transparent;
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(153%2C153%2C153%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E");
+ background-position: bottom;
+ background-repeat: repeat-x;
+ background-size: 4px 1px;
+ width: 100%; }
+
+hr.hr-dotted.lite {
+ background-color: transparent;
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(204%2C204%2C204%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E"); }
+
+hr.is-vertical.dark,
+hr.hr-or.dark,
+hr.is-vertical.lite,
+hr.hr-or.lite {
+ display: inline-block;
+ height: auto;
+ margin: 0 15px;
+ min-height: 20px;
+ width: 1px; }
+
+hr.is-vertical.dark,
+hr.hr-or.dark {
+ background-color: #959595; }
+
+hr.is-vertical.lite,
+hr.hr-or.lite {
+ background-color: #d2d2d2; }
+
+.hr-dotted.is-vertical.dark,
+.hr-dotted.is-vertical.lite {
+ background-color: transparent;
+ background-repeat: repeat-y;
+ background-size: 1px 4px;
+ height: auto;
+ min-height: 20px;
+ width: 1px; }
+
+.hr-dotted.is-vertical.dark {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A1px%3B%20height%3A100%25%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(153%2C153%2C153%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%22100%25%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%221%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E"); }
+
+.hr-dotted.is-vertical.lite {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A1px%3B%20height%3A100%25%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(204%2C204%2C204%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%22100%25%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%221%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E"); }
+
+.row-nowrap > .span + hr.is-vertical,
+.row > .span + hr.is-vertical {
+ margin: 0 0 0 -20px; }
+
+@media (max-width: 767px) {
+ hr,
+ .hr-or {
+ margin: 30px 0; }
+ hr.full {
+ margin-left: -15px;
+ margin-right: -15px; }
+ .hr-or.is-vertical {
+ min-height: 1px;
+ height: 1px;
+ width: 100%; }
+ .row-nowrap > .span + hr.is-vertical {
+ margin: 0 0 0 -15px; }
+ .row > .span + hr.is-vertical {
+ min-height: 1px;
+ height: 1px;
+ width: 100%;
+ margin: 0;
+ display: block; }
+ .row > .span + hr.is-vertical.lite {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(204%2C204%2C204%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E") !important;
+ background-size: 4px 1px;
+ background-repeat: repeat-x; }
+ .row > .span + hr.is-vertical.dark {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(153%2C153%2C153%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E") !important;
+ background-size: 4px 1px;
+ background-repeat: repeat-x; } }
+
+hr.bottom-space-only {
+ margin-top: 0; }
+
+.hr-nomargin {
+ margin: 0; }
+
+.radio {
+ position: relative;
+ min-height: 24px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.6rem;
+ margin-bottom: 5px; }
+ .radio input {
+ -webkit-tap-highlight-color: transparent;
+ height: 10px;
+ margin: 6px;
+ opacity: 0;
+ outline: none;
+ position: absolute;
+ left: 1px;
+ top: 1px;
+ width: 10px; }
+ .radio input:focus + .skin {
+ border-color: #0568ae; }
+ .radio input:focus + .skin:before {
+ content: "";
+ height: 34px;
+ left: -6px;
+ top: -6px;
+ outline: 1px dotted #000000;
+ position: absolute;
+ width: 34px; }
+ .radio input + .skin {
+ border-radius: 100%; }
+ .radio input:checked + .skin:after {
+ background-color: #0568ae;
+ border-radius: 100%;
+ border: 3px solid #FFFFFF;
+ content: "";
+ display: block;
+ height: 16px;
+ position: absolute;
+ width: 16px; }
+ .radio input:disabled + .skin {
+ cursor: not-allowed;
+ background-color: #d2d2d2;
+ border-color: #d2d2d2;
+ color: #666666; }
+ .radio input:disabled + .skin + span {
+ cursor: not-allowed;
+ color: #666666; }
+ .radio input:disabled:checked + .skin:after {
+ background-color: #666666; }
+ .radio input:invalid + .skin {
+ border: solid 1px #cf2a2a; }
+ .radio .skin {
+ background-color: #FFFFFF;
+ border: 1px solid #d2d2d2;
+ border-radius: 3px;
+ display: inline-block;
+ height: 24px;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 24px; }
+ .radio span {
+ display: inline-block;
+ margin-left: 34px;
+ margin-top: 0;
+ position: relative;
+ top: 3px; }
+ .radio label {
+ font-size: 1.6rem;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+.radio.inline {
+ display: inline-block;
+ margin-bottom: 10px;
+ vertical-align: middle;
+ margin-right: 10px; }
+ .radio.inline:last-child {
+ margin-right: 0; }
+
+.radio-box {
+ border: 1px solid #d2d2d2;
+ border-radius: 8px; }
+ .radio-box > [role="radio"] label {
+ padding: 15px 15px 20px 15px;
+ display: block;
+ width: 100%; }
+ .radio-box > [role="radio"] label .skin + span {
+ top: 2px; }
+ .radio-box > [role="radio"] + div {
+ padding: 0 15px 15px 47px; }
+ .radio-box > [aria-checked="false"] label > input {
+ top: 15px;
+ left: 15px; }
+ .radio-box > [aria-checked="false"] label .skin {
+ top: 15px;
+ left: 15px; }
+ .radio-box > [aria-checked="true"] label > input {
+ top: 13px;
+ left: 13px; }
+ .radio-box > [aria-checked="true"] label .skin {
+ top: 13px;
+ left: 13px; }
+
+.radio-box.active {
+ border: 3px solid #0568ae; }
+ .radio-box.active > [role="radio"] label {
+ padding: 13px 14px 19px 13px; }
+
+.checkbox {
+ position: relative;
+ min-height: 24px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.6rem;
+ margin-bottom: 5px; }
+ .checkbox input {
+ -webkit-tap-highlight-color: transparent;
+ height: 10px;
+ margin: 6px;
+ opacity: 0;
+ outline: none;
+ position: absolute;
+ left: 1px;
+ top: 1px;
+ width: 10px; }
+ .checkbox input:focus + .skin {
+ border-color: #0568ae; }
+ .checkbox input:focus + .skin:before {
+ content: "";
+ height: 34px;
+ left: -6px;
+ top: -6px;
+ outline: 1px dotted #000000;
+ position: absolute;
+ width: 34px; }
+ .checkbox input:checked:not(:disabled) + .skin {
+ background-color: #0568ae;
+ border-color: #0568ae; }
+ .checkbox input:checked:disabled + .skin:after {
+ color: #5A5A5A; }
+ .checkbox input:checked + .skin:after {
+ height: 24px;
+ width: 24px;
+ background-color: transparent;
+ font-size: 23.4px;
+ color: #FFFFFF;
+ line-height: 21px; }
+ .checkbox input:disabled + .skin {
+ cursor: not-allowed;
+ background-color: #d2d2d2;
+ border-color: #d2d2d2;
+ color: #666666; }
+ .checkbox input:disabled + .skin + span {
+ cursor: not-allowed;
+ color: #666666; }
+ .checkbox input:invalid + .skin {
+ border: solid 1px #cf2a2a; }
+ .checkbox input:indeterminate + .skin:after {
+ background-color: transparent;
+ font-size: 25px;
+ color: #0574ac;
+ content: "\e920"; }
+ .checkbox .skin {
+ background-color: #fff;
+ border: 1px solid #d2d2d2;
+ border-radius: 3px;
+ display: inline-block;
+ height: 24px;
+ width: 24px;
+ position: absolute;
+ left: 0;
+ top: 0; }
+ .checkbox span {
+ display: inline-block;
+ margin-left: 34px;
+ margin-top: 0;
+ position: relative;
+ top: 3px; }
+ .checkbox label {
+ font-size: 1.6rem;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+ .checkbox input {
+ z-index: 9999; }
+ .checkbox input.indeterminate + .skin:after {
+ font-size: 22px;
+ color: #0568ae; }
+
+.checkbox.inline {
+ display: inline-block;
+ margin-bottom: 10px;
+ vertical-align: middle;
+ margin-right: 10px; }
+ .checkbox.inline:last-child {
+ margin-right: 0; }
+
+.checkbox.checkbox-selectall {
+ margin: 20px 0 0 24px; }
+
+.terms-after-checkbox {
+ margin-top: 15px; }
+
+.indeterminate-margin {
+ padding-left: 24px; }
+
+.tiny-accordion {
+ border-bottom: 1px solid #d2d2d2; }
+
+.toggle-header,
+.inactive-toggle-header {
+ border-color: #fff;
+ color: #0568ae;
+ cursor: pointer;
+ display: block;
+ font-size: 2.0rem;
+ line-height: 2.2rem;
+ min-height: 41px;
+ position: relative;
+ padding: 16px 55px 16px 15px; }
+
+.toggle-header.opened {
+ color: #333333; }
+
+.tiny-accordion .toggle-header,
+.tiny-accordion .inactive-toggle-header {
+ padding: 16px 55px 16px 15px;
+ border-top: 1px solid #d2d2d2; }
+
+.tiny-accordion .toggle-header:focus {
+ text-decoration: underline; }
+
+.tiny-accordion.iconleft .toggle-header,
+.tiny-accordion.iconleft .inactive-toggle-header {
+ padding: 15px 15px 15px 50px; }
+
+.accordion-content {
+ font-size: 1.4rem; }
+
+.accordion-content .toggle-header:first-child {
+ margin-top: 16px; }
+
+.tiny-accordion .toggle-header + .accordion-content {
+ padding: 0 50px 15px 15px; }
+
+.tiny-accordion.iconleft .toggle-header + .accordion-content {
+ padding: 0 15px 15px 50px; }
+
+.toggle-header .icon-primary-accordion-plus,
+.toggle-header .icon-primary-accordion-minus {
+ display: inline-block;
+ font-size: 20px;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ right: 15px;
+ vertical-align: middle;
+ top: 16px;
+ font-weight: bold; }
+
+.tiny-accordion.iconleft .toggle-header .icon-primary-accordion-plus,
+.tiny-accordion.iconleft .toggle-header .icon-primary-accordion-minus {
+ left: 15px; }
+
+.inactive-toggle-header:hover {
+ cursor: inherit; }
+
+.tiny-accordion-to-tabs,
+.tiny-tabs {
+ position: relative;
+ width: 100%;
+ margin: 0px;
+ padding: 0px; }
+
+.tiny-tabs [class*="icon-primary-accordion-"] {
+ display: none !important; }
+
+.tiny-accordion-to-tabs:before,
+.tiny-accordion-to-tabs:after,
+.tiny-tabs:before,
+.tiny-tabs:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.tiny-accordion-to-tabs:after,
+.tiny-tabs:after {
+ clear: both; }
+
+.tiny-accordion-to-tabs:before,
+.tiny-accordion-to-tabs:after,
+.tiny-tabs:before,
+.tiny-tabs:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.tiny-accordion-to-tabs:after,
+.tiny-tabs:after {
+ clear: both; }
+
+.tiny-tabs > .toggle-header {
+ display: inline-block;
+ float: left;
+ border-top: none;
+ overflow: hidden;
+ height: 70px;
+ text-align: center;
+ background-color: #fff;
+ border-radius: 0px;
+ padding: 26px 20px 25px 20px !important;
+ border-top: 1px solid #fff;
+ -webkit-filter: none;
+ filter: none;
+ background-clip: padding-box;
+ border-bottom: 1px solid #d2d2d2;
+ font-weight: normal;
+ border-right: 1px solid #d2d2d2;
+ white-space: nowrap; }
+
+.tiny-tabs .toggle-header + div {
+ left: 0px;
+ position: absolute;
+ top: 69px;
+ border-top: 1px solid #d2d2d2;
+ padding: 0;
+ display: block;
+ border-bottom: none;
+ width: 100%; }
+
+.accordion-pad {
+ padding-top: 30px;
+ padding-bottom: 30px; }
+
+.tiny-tabs .opened {
+ color: #333333;
+ border-top: 5px solid #0568ae !important;
+ padding-top: 22px !important;
+ border-bottom: none;
+ background-color: #fff;
+ -webkit-filter: none;
+ filter: none;
+ cursor: default;
+ z-index: 999; }
+
+.tiny-tabs .toggle-header:focus {
+ text-decoration: underline;
+ outline: thin dotted #666;
+ outline-offset: 0; }
+
+.tiny-tabs .toggle-header:first-child {
+ border-left: none;
+ margin-left: 0; }
+
+.tiny-tabs .toggle-header:first-child {
+ border-left: 1px solid #fff; }
+
+.tiny-tabs .opened:first-child {
+ border-left: 1px solid #d2d2d2; }
+
+.tiny-tabs .toggle-header:nth-last-of-type(2) {
+ border-right-color: #fff; }
+
+.tiny-tabs .opened:nth-last-of-type(2) {
+ border-right: 1px solid #d2d2d2; }
+
+@media (max-width: 767px) {
+ .tiny-accordion,
+ .tiny-accordion-to-tabs {
+ margin-left: -15px;
+ margin-right: -15px;
+ width: auto; }
+ .tiny-accordion-to-tabs {
+ display: block;
+ border-bottom: 1px solid #d2d2d2; }
+ .tiny-accordion-to-tabs .toggle-header {
+ display: block;
+ min-height: 41px;
+ padding: 16px 50px 16px 15px;
+ border-top: 1px solid #d2d2d2; }
+ .tiny-accordion-to-tabs .toggle-header:focus {
+ text-decoration: underline; }
+ .tiny-accordion-to-tabs .toggle-header + .accordion-content {
+ padding: 0 50px 15px 15px; } }
+
+@media (min-width: 768px) {
+ .tiny-accordion-to-tabs [class*="icon-primary-accordion-"] {
+ display: none !important; }
+ .tiny-accordion-to-tabs > .toggle-header {
+ display: inline-block;
+ float: left;
+ border-top: none;
+ /*overflow: hidden;*/
+ height: 70px;
+ text-align: center;
+ background-color: #fff;
+ border-radius: 0px;
+ padding: 26px 20px 25px 20px !important;
+ border-top: 1px solid #fff;
+ -webkit-filter: none;
+ filter: none;
+ background-clip: padding-box;
+ border-bottom: 1px solid #d2d2d2;
+ font-weight: normal;
+ border-right: 1px solid #d2d2d2;
+ white-space: nowrap; }
+ .tiny-accordion-to-tabs .toggle-header + div {
+ left: 0px;
+ position: absolute;
+ top: 69px;
+ border-top: 1px solid #d2d2d2;
+ padding-top: 30px;
+ padding-left: 20px;
+ display: block;
+ border-bottom: none;
+ width: 100%; }
+ .tiny-accordion-to-tabs .opened {
+ color: #333333;
+ border-top: 5px solid #0568ae !important;
+ padding-top: 22px !important;
+ border-bottom: none;
+ background-color: #fff;
+ -webkit-filter: none;
+ filter: none;
+ cursor: default;
+ text-decoration: none;
+ z-index: 999; }
+ .tiny-accordion-to-tabs .toggle-header:focus {
+ text-decoration: underline;
+ outline: thin dotted #666;
+ outline-offset: 0px; }
+ .tiny-accordion-to-tabs .toggle-header:nth-last-of-type(2) {
+ border-right: none; }
+ .tiny-accordion-to-tabs .toggle-header:first-child {
+ border-left: none;
+ margin-left: 0; }
+ .tiny-accordion-to-tabs .toggle-header:first-child {
+ border-left: 1px solid #fff; }
+ .tiny-accordion-to-tabs .opened:first-child {
+ border-left: 1px solid #d2d2d2; }
+ .tiny-accordion-to-tabs .opened:nth-last-of-type(2) {
+ border-right: 1px solid #d2d2d2; } }
+
+.toggle-header .tooltip .icon-primary-tooltip {
+ margin-top: -5px; }
+
+.accordion-content {
+ transition: all 0.8s linear; }
+
+.opaque-content {
+ opacity: 0; }
+
+.tiny-tabs .toggle-header {
+ display: inline-block;
+ float: left;
+ border-top: none;
+ overflow: hidden;
+ height: 70px;
+ text-align: center;
+ background-color: #fff;
+ border-radius: 0px;
+ padding: 22px 20px 25px 20px !important;
+ border-top: 5px solid #fff;
+ -webkit-filter: none;
+ filter: none;
+ background-clip: padding-box;
+ border-bottom: 1px solid #ccc;
+ font-weight: normal;
+ border-right: 1px solid #ccc;
+ white-space: nowrap; }
+
+.tiny-tabs .toggle-header:first-child {
+ margin-left: 0; }
+
+.tiny-tabs div:first-child .toggle-header {
+ margin-left: 30px; }
+
+.tiny-tabs > div .toggle-header.opened {
+ border-bottom: 0 !important; }
+
+.tiny-accordion-to-tabs > div > div.toggle-header {
+ background-clip: padding-box;
+ background-color: #fff;
+ border-bottom: 1px solid #ccc;
+ border-radius: 0;
+ border-top: 5px solid #fff;
+ display: inline-block;
+ filter: none;
+ float: left;
+ font-weight: normal;
+ overflow: hidden;
+ padding: 22px 20px 21px !important;
+ text-align: center;
+ white-space: nowrap; }
+
+.tiny-accordion-to-tabs .toggle-header:first-child {
+ margin-left: 0; }
+
+.tiny-accordion-to-tabs div:first-child .toggle-header {
+ margin-left: 30px;
+ border-bottom: 0 !important; }
+
+.tiny-accordion-to-tabs > div .toggle-header.opened {
+ border-bottom: 0 !important; }
+
+@media (max-width: 767px) {
+ .tiny-accordion-to-tabs {
+ display: block !important;
+ border-bottom: 1px solid #ccc !important; }
+ .tiny-accordion-to-tabs > div > div.toggle-header {
+ display: block !important;
+ float: none;
+ text-align: left;
+ min-height: 41px !important;
+ padding: 15px 50px 15px 15px !important;
+ border-top: 1px solid #ccc; }
+ .tiny-accordion-to-tabs > div > div.toggle-header:first-child {
+ margin-left: 0 !important; }
+ .tiny-accordion-to-tabs > div > div.toggle-header + .accordion-content {
+ padding: 0 50px 15px 15px; }
+ .tiny-accordion-to-tabs > div > div.toggle-header .icon-primary-accordion-plus {
+ background-position: 0 0;
+ background-size: 20px 40px; }
+ .tiny-accordion-to-tabs > div > div.toggle-header .icon-primary-accordion-minus {
+ background-position: 0 -20px;
+ background-size: 20px 40px; }
+ .tiny-accordion-to-tabs > div > div.toggle-header .icon-primary-accordion-plus,
+ .tiny-accordion-to-tabs > div > div.toggle-header .icon-primary-accordion-minus {
+ display: inline-block;
+ height: 20px;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ right: 15px;
+ vertical-align: middle;
+ width: 20px; } }
+
+.alert {
+ background-color: #5a5a5a;
+ border-radius: 8px;
+ color: #fff;
+ margin-top: 15px;
+ padding: 0;
+ position: relative;
+ border: 0; }
+
+.alert h3,
+.alert h4 {
+ color: #fff;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 1.6rem;
+ margin: 0 20px 5px 0; }
+
+.alert div {
+ padding: 15px 20px; }
+
+.alert div:first-child {
+ border-radius: 8px 0 0 8px;
+ width: 1%; }
+
+.alert div:first-child + div {
+ border: 1px solid transparent;
+ border-left: none;
+ border-radius: 0 8px 8px 0; }
+
+.alert-error {
+ background-color: #cf2a2a;
+ border: 1px solid #cf2a2a; }
+
+.alert-info {
+ background-color: #44c8f5;
+ border: 1px solid #44c8f5; }
+
+.alert-success {
+ background-color: #c5d63d;
+ border: 1px solid #c5d63d; }
+
+.alert [class*="icon-primary-"] {
+ color: #fff;
+ font-size: 30px;
+ margin-right: 0; }
+
+.alert .close {
+ height: 30px;
+ position: absolute;
+ right: 1px;
+ top: 1px;
+ width: 30px; }
+
+.alert .close:before {
+ color: #fff;
+ margin-right: 0;
+ position: absolute;
+ right: 9px;
+ top: 9px; }
+
+.alert a {
+ color: #fff;
+ text-decoration: underline; }
+
+.alert .close:focus {
+ outline: 1px dotted #666; }
+
+.alert p {
+ font-size: 1.4rem; }
+
+.alert p:last-child {
+ margin-bottom: 0; }
+
+.alert .standalone-link i[class*="icon-primary-"] {
+ font-size: 20px;
+ margin-right: 5px; }
+
+@media (max-width: 767px) {
+ .alert {
+ border-radius: 0;
+ margin: 0 -15px; }
+ .alert + .alert {
+ margin-top: 4px; }
+ .alert div {
+ padding: 15px 10px; }
+ .alert div:first-child {
+ border-radius: 0;
+ padding: 15px; }
+ .alert h3,
+ .alert h4 {
+ font-size: 1.4rem; }
+ .alert p {
+ font-size: 1.2rem; }
+ .alert .close {
+ right: 5px;
+ top: 5px; }
+ .alert .standalone-link i[class*="icon-primary-"] {
+ font-size: 16px; } }
+
+.alert h3 {
+ margin: 0;
+ font-size: 16px; }
+
+.alert p {
+ font-size: 14px; }
+
+.alert p a {
+ color: #FFFFFF;
+ text-decoration: underline; }
+
+.alert div:first-child + div {
+ padding-right: 25px; }
+
+.alert div:last-child {
+ padding-right: 20px !important; }
+
+.alert p [class*="icon-primary-"] {
+ color: #fff;
+ font-size: 20px;
+ margin-right: 0; }
+
+@media (max-width: 767px) {
+ .alert h3 {
+ font-size: 14px; }
+ .alert div:first-child + div {
+ padding-right: 20px; }
+ .alert div:last-child {
+ padding-right: 15px !important; }
+ .alert div:first-child {
+ padding: 15px; }
+ .alert p {
+ font-size: 12px; }
+ .alert p [class*="icon-primary-"] {
+ font-size: 16px; } }
+
+.b2b-audio {
+ width: auto;
+ margin: 10px auto;
+ height: 35px; }
+ .b2b-audio .controls-wrapper {
+ display: inline-block;
+ font-size: 25px;
+ cursor: pointer; }
+ .b2b-audio .controls-wrapper i {
+ font-size: 25px;
+ margin-right: 0px;
+ color: #444; }
+ .b2b-audio .controls-wrapper i:hover {
+ color: #0574AC; }
+ .b2b-audio .seek-bar-container-wrapper {
+ display: inline-block;
+ outline: 0;
+ min-width: 180px;
+ margin-right: 10px;
+ margin-left: 10px;
+ height: 14px;
+ padding-top: 5px; }
+ .b2b-audio .seek-bar-container-wrapper .timing-container {
+ padding-top: 13px;
+ color: #333;
+ font-size: 12px; }
+ .b2b-audio .seek-bar-container-wrapper .timing-container .timing-container-left {
+ float: left;
+ line-height: 100%; }
+ .b2b-audio .seek-bar-container-wrapper .timing-container .timing-container-right {
+ float: right;
+ line-height: 100%; }
+ .b2b-audio .seek-bar-container-wrapper .timing-container .timing-container-spacer {
+ clear: both; }
+ .b2b-audio .seek-bar-tooltip {
+ text-align: center;
+ min-width: 76px; }
+
+.b2b-audio-popover {
+ width: 22px; }
+ .b2b-audio-popover .volume-popover {
+ height: 100px !important;
+ width: 6px !important;
+ margin: 7px auto; }
+ .b2b-audio-popover .min-label {
+ margin-top: 5px; }
+
+.b2b-audio-native {
+ width: auto;
+ height: auto; }
+
+.b2b-audio-recorder {
+ border: 1px solid #ccc;
+ box-shadow: 0px 1px 2px 0 rgba(0, 0, 0, 0.15);
+ height: 63px;
+ min-height: 63px;
+ min-width: 347px; }
+ .b2b-audio-recorder .b2b-elapsed-time {
+ margin: 23px 0 24px 15px;
+ font-size: 16px;
+ font-style: italic;
+ color: #767676; }
+ .b2b-audio-recorder .b2b-controls {
+ width: 68px;
+ cursor: pointer; }
+ .b2b-audio-recorder .b2b-controls i.icoControls-record {
+ font-size: 64px;
+ color: black;
+ float: right;
+ margin-right: 10px; }
+ .b2b-audio-recorder .b2b-controls i.icoControls-record:focus, .b2b-audio-recorder .b2b-controls i.icoControls-record:hover {
+ color: #0568ae; }
+ .b2b-audio-recorder .b2b-controls i.icoControls-stop {
+ font-size: 36px;
+ color: black;
+ float: right;
+ margin-right: 20px;
+ margin-top: 12px; }
+ .b2b-audio-recorder .b2b-controls i.icoControls-stop:focus, .b2b-audio-recorder .b2b-controls i.icoControls-stop:hover {
+ color: #0568ae; }
+
+.b2b-top-btn {
+ height: 36px;
+ width: 36px;
+ border-radius: 7px; }
+
+.b2b-top-btn > i {
+ position: absolute;
+ top: 13px;
+ left: 9px;
+ width: 11px;
+ height: 18px; }
+
+.b2b-badge {
+ font-family: "Omnes-ECOMP-W02-Medium";
+ background-color: #5A5A5A;
+ border-radius: 12px;
+ color: #FFFFFF;
+ display: inline-block;
+ font-size: 1.5rem;
+ font-weight: normal;
+ height: 20px;
+ line-height: 0;
+ margin-top: 0;
+ min-width: 20px;
+ padding: 0 5px;
+ text-align: center;
+ vertical-align: baseline; }
+ .b2b-badge:empty {
+ display: none; }
+
+* + .b2b-heading-micro {
+ margin-top: 20px !important; }
+
+.b2b-heading-micro {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-weight: normal;
+ text-rendering: optimizeLegibility;
+ font-size: 1.2rem !important;
+ text-transform: uppercase !important;
+ margin-bottom: 20px !important;
+ line-height: 1.2 !important; }
+
+.b2b-no-colors .b2b-badge {
+ border: 1px solid transparent; }
+
+.btn > .b2b-badge {
+ margin-right: 5px; }
+
+a > .b2b-badge {
+ margin-right: 6px;
+ padding-top: 10px; }
+
+.b2b-badge-urgent {
+ background-color: #cf2a2a; }
+
+.bellyband-container {
+ margin: 0 -15px; }
+
+.bellyband-group {
+ width: auto; }
+
+.bellyband-link {
+ border-top: 1px solid #d2d2d2; }
+
+.bellyband-link a {
+ display: block;
+ height: 40px;
+ line-height: 40px;
+ padding: 0 15px;
+ position: relative;
+ text-decoration: none; }
+
+.bellyband-link a:hover > div span,
+.bellyband-link a:focus > div span {
+ text-decoration: underline; }
+
+.bellyband-link a:after {
+ color: #666;
+ font-size: 2.3rem;
+ height: 20px;
+ position: absolute;
+ right: 5px;
+ top: 12px;
+ width: 18px; }
+
+.dark-bg .bellyband-link a:after {
+ color: white; }
+
+.bellyband-link img[src$="svg"].hidden-desktop,
+.bellyband-link [class*="icon-primary-"].hidden-desktop {
+ display: inline-block !important;
+ float: left;
+ font-size: 24px;
+ height: 24px;
+ margin-right: 5px;
+ margin-top: 8px;
+ width: 24px; }
+
+.dark-bg .bellyband-link [class*="icon-primary-"].hidden-desktop,
+.dark-bg .bellyband-link [class*="icon-primary-"].visible-desktop {
+ color: #fff; }
+
+.bellyband-link img[src$="svg"].visible-desktop {
+ display: none !important; }
+
+.bellyband-link p {
+ margin-top: -10px;
+ margin-left: 29px;
+ font-size: 1.4rem;
+ color: #666; }
+
+@media (min-width: 481px) and (max-width: 767px) {
+ .bellyband-container {
+ display: flex;
+ margin: 0; }
+ .bellyband-group {
+ align-content: flex-start;
+ align-items: stretch;
+ display: inline-flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ margin-top: 1px;
+ width: 100%; }
+ .bellyband-group .row {
+ display: flex !important; }
+ .bellyband-link {
+ padding-top: 0;
+ position: relative;
+ border-top: none;
+ margin-bottom: 20px;
+ width: 50%; }
+ .bellyband-link a {
+ height: inherit;
+ line-height: inherit;
+ display: flex;
+ padding: 0; }
+ .bellyband-link a:after {
+ display: none; }
+ .bellyband-link a span {
+ display: block;
+ padding-top: 10px; }
+ .bellyband-link p {
+ display: block;
+ padding: 0 15px 0 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ margin-top: 0; }
+ .bellyband-link a:focus p {
+ text-decoration: none; } }
+
+@media (min-width: 768px) {
+ .bellyband-group {
+ margin: 0;
+ max-width: 100%;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center; }
+ .bellyband-group .row {
+ display: block; }
+ .bellyband-group .row .span {
+ float: none;
+ margin-right: 0;
+ margin-bottom: 30px;
+ display: flex;
+ justify-content: space-between; }
+ .bellyband-link {
+ border-top: none;
+ flex: 0 0 auto;
+ margin-right: 0;
+ margin-bottom: 30px; }
+ .bellyband-link:last-child {
+ margin-right: 0; }
+ .bellyband-link a {
+ height: auto;
+ line-height: 1;
+ text-align: center; }
+ .bellyband-link a:after {
+ display: none; }
+ .bellyband-link img[src$="svg"].hidden-desktop,
+ .bellyband-link [class*="icon-primary-"].hidden-desktop {
+ display: none !important; }
+ .bellyband-link img[src$="svg"].visible-desktop,
+ .bellyband-link [class*="icon-primary-"].visible-desktop {
+ display: block !important;
+ font-size: 50px;
+ height: 50px;
+ margin-right: 0;
+ margin-top: 0;
+ margin-left: auto;
+ margin-right: auto;
+ width: auto; }
+ .bellyband-link a span {
+ display: block;
+ margin-top: 12px;
+ line-height: 2rem; }
+ .bellyband-link p {
+ display: block;
+ text-align: center;
+ margin-top: 6px;
+ margin-left: 0;
+ padding-left: 0 !important;
+ color: #666;
+ line-height: 1.8rem; } }
+
+@media (max-width: 480px) {
+ .bellyband-link-tall a {
+ height: auto;
+ padding: 0 40px 10px 15px; }
+ .bellyband-link-tall p {
+ line-height: 1.8rem;
+ margin-bottom: 0; }
+ .bellyband-link-tall > a:after {
+ margin-top: -8px;
+ top: 50%; } }
+
+.b2b-boardstrip {
+ display: inline-block;
+ width: 100%;
+ border-bottom: 1px solid #9d9d9d;
+ position: relative;
+ padding-top: 15px; }
+ .b2b-boardstrip .boardstrip-reel {
+ margin-bottom: 15px; }
+ .b2b-boardstrip .boardstrip-item--add {
+ border: 1px dashed #ccc;
+ background: #FFFFFF;
+ color: #0574ac;
+ width: 140px;
+ height: 80px;
+ font-size: 14px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ position: absolute;
+ left: 29px;
+ top: 15px; }
+ .b2b-boardstrip .boardstrip-item--add:hover, .b2b-boardstrip .boardstrip-item--add:focus {
+ border: 2px solid #007A3E;
+ cursor: pointer; }
+ .b2b-boardstrip .boardstrip-item--add i {
+ font-size: 14px;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: initial; }
+ .b2b-boardstrip .boardstrip-item--add .centered {
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 27px;
+ margin-bottom: 35px;
+ display: block; }
+ .b2b-boardstrip .board-viewport {
+ float: left;
+ margin-left: 210px;
+ max-height: 95px;
+ position: relative;
+ height: 95px;
+ overflow: hidden;
+ width: 0px; }
+ .b2b-boardstrip .board-viewport .boardstrip-container {
+ width: 0px;
+ margin-left: 0;
+ left: 0px;
+ position: absolute;
+ list-style: none;
+ -webkit-transition: left 1000ms;
+ transition: left 1000ms; }
+ .b2b-boardstrip .board-viewport .board-item {
+ width: 140px;
+ height: 80px;
+ border: 1px solid #ccc;
+ margin: 0 15px 15px 0;
+ background-color: #FFFFFF;
+ border-radius: 3px;
+ float: left;
+ overflow: hidden; }
+ .b2b-boardstrip .board-viewport .board-item:hover, .b2b-boardstrip .board-viewport .board-item:focus {
+ border: 2px solid #007A3E;
+ background-color: white;
+ cursor: pointer; }
+ .b2b-boardstrip .board-viewport .board-item .board-img {
+ width: 61px;
+ height: 40px;
+ margin: 0 auto; }
+ .b2b-boardstrip .board-viewport .board-item .board-img img {
+ max-width: 100%; }
+ .b2b-boardstrip .board-viewport .board-item .title {
+ text-align: center;
+ line-height: 16px;
+ color: #666;
+ font-size: 14px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ padding: 10px 0; }
+ .b2b-boardstrip .board-viewport .board-item.selected {
+ background-color: #FFFFFF;
+ border: 2px solid #0574ac; }
+ .b2b-boardstrip .board-viewport .board-item .board-caret {
+ cursor: default;
+ outline: 0;
+ position: absolute;
+ bottom: 7px; }
+ .b2b-boardstrip .board-viewport .board-item .board-caret .board-caret-indicator {
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ border-bottom: 8px solid #999;
+ width: 0px;
+ height: 0px;
+ position: absolute;
+ left: 61px;
+ bottom: -7px; }
+ .b2b-boardstrip .board-viewport .board-item .board-caret .board-caret-arrow-up {
+ width: 0px;
+ height: 0px;
+ border-style: solid;
+ border-width: 0 8px 8px 8px;
+ border-color: transparent transparent #FFFFFF transparent;
+ left: 61px;
+ position: absolute; }
+ .b2b-boardstrip .arrow {
+ font-size: 14px;
+ cursor: pointer;
+ color: #0574ac; }
+ .b2b-boardstrip .arrow:hover {
+ color: #0574ac; }
+ .b2b-boardstrip .arrow.disabled {
+ color: #767676 !important;
+ cursor: not-allowed; }
+ .b2b-boardstrip .prev-items {
+ display: inline-block;
+ margin-top: auto;
+ margin-bottom: auto;
+ margin-right: 15px;
+ position: absolute;
+ left: 0;
+ top: 45px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none; }
+ .b2b-boardstrip .next-items {
+ display: inline-block;
+ margin-top: 30px;
+ margin-bottom: auto;
+ margin-left: 10px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none; }
+ .b2b-boardstrip .centered {
+ display: table-cell;
+ text-align: center;
+ vertical-align: middle; }
+
+.breadcrumb {
+ padding: 10px 15px;
+ height: 40px;
+ list-style: none;
+ border-bottom: 1px solid #d2d2d2;
+ font-size: 1.2rem;
+ width: 100%;
+ z-index: 1000; }
+
+.breadcrumb > li {
+ position: relative;
+ display: inline-block;
+ margin-right: 15px; }
+
+.breadcrumb > li:after {
+ font-size: 8px;
+ margin-right: 0;
+ right: -8px;
+ color: #333333; }
+
+.breadcrumb > li:last-child {
+ color: #333333; }
+
+.breadcrumb > li:last-child:after {
+ content: ""; }
+
+.breadcrumb li > * {
+ float: none !important;
+ margin: 0; }
+
+.breadcrumb {
+ padding: 10px 15px !important; }
+
+/* ARROW */
+/* spanish */
+.datepicker {
+ background-color: #FFFFFF;
+ padding: 0;
+ border-radius: 5px;
+ direction: ltr; }
+ .datepicker > div {
+ display: none; }
+ .datepicker table {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ margin: 0 0 0 0; }
+ .datepicker td {
+ text-align: center;
+ display: block;
+ width: 30px;
+ height: 30px;
+ border: none; }
+ .datepicker td span {
+ display: block;
+ width: 23%;
+ height: 54px;
+ line-height: 54px;
+ float: left;
+ margin: 1%;
+ cursor: pointer;
+ border-radius: 4px; }
+ .datepicker td span:hover {
+ background: #eeeeee; }
+ .datepicker td span.disabled {
+ background: none;
+ color: #5A5A5A;
+ cursor: default; }
+ .datepicker td span.disabled:hover {
+ background: none;
+ color: #5A5A5A;
+ cursor: default; }
+ .datepicker td span.active {
+ color: #FFFFFF;
+ background-color: #0568ae;
+ border-color: #357ebd; }
+ .datepicker td span.active:hover {
+ color: #FFFFFF;
+ background-color: #0568ae;
+ border-color: #357ebd; }
+ .datepicker td span.active.disabled {
+ color: #FFFFFF;
+ background-color: #0568ae;
+ border-color: #357ebd; }
+ .datepicker th {
+ text-align: center;
+ display: block;
+ width: 30px;
+ height: 30px;
+ border: none; }
+ .datepicker tbody:focus {
+ outline: none; }
+ .datepicker td.day {
+ background-color: transparent;
+ color: #0568ae;
+ cursor: pointer;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 16px;
+ height: 34px;
+ line-height: 30rem;
+ margin: -2px -1px 0 0;
+ overflow: hidden;
+ text-align: center;
+ width: 42px; }
+ .datepicker:focus {
+ outline: 1px dotted #191919;
+ outline-offset: -2px; }
+ .datepicker th[tabindex]:focus {
+ outline-offset: -15px; }
+ .datepicker td.day.focused {
+ background: #ededed;
+ cursor: pointer; }
+ .datepicker td.day.focused.active {
+ background-color: #ededed;
+ color: #0568ae; }
+ .datepicker td.disabled {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5A5A5A;
+ cursor: default; }
+ .datepicker td.disabled:hover {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5A5A5A;
+ cursor: default; }
+ .datepicker td.disabled:hover .show-date {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5A5A5A; }
+ .datepicker td.disabled .show-date {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5A5A5A; }
+ .datepicker td.today {
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today:hover {
+ color: #FFFFFF;
+ background-color: #0568ae;
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today:active {
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today:focus {
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today.disabled {
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today.active {
+ color: #FFFFFF;
+ background-color: #0568ae; }
+ .datepicker td.today.active:hover {
+ color: #FFFFFF; }
+ .datepicker td.selected {
+ color: #FFFFFF;
+ background-color: #959595; }
+ .datepicker td.selected:hover {
+ color: #FFFFFF;
+ background-color: #959595; }
+ .datepicker td.selected.disabled {
+ color: #FFFFFF;
+ background-color: #959595; }
+ .datepicker td.active:not(.new) {
+ color: #FFFFFF;
+ border-color: #357ebd; }
+ .datepicker td.active:not(.new) .show-date {
+ color: #0568ae;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+ .datepicker td.active:hover:not(.new) {
+ color: #FFFFFF;
+ border-color: #357ebd; }
+ .datepicker td.active:hover:not(.new) .show-date {
+ color: #0568ae;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+ .datepicker .start-date .show-date {
+ background-color: #0568ae;
+ color: #FFFFFF !important;
+ border-radius: 5px 0 0 5px;
+ z-index: 1; }
+ .datepicker .start-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: 20px;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+ .datepicker .between-date .show-date {
+ background-color: #0568ae;
+ color: #FFFFFF !important; }
+ .datepicker .between-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: 0;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+ .datepicker .between-date:first-child .show-date:before {
+ background-color: #FFFFFF;
+ content: "";
+ height: 26px;
+ position: absolute;
+ left: 0;
+ width: 8px; }
+ .datepicker .end-date .show-date {
+ background-color: #0568ae;
+ color: #FFFFFF !important;
+ border-radius: 0 5px 5px 0; }
+ .datepicker .end-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: -20px;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+ .datepicker .end-date:first-child .show-date:after {
+ background-color: #FFFFFF;
+ content: "";
+ height: 26px;
+ position: absolute;
+ left: 0;
+ width: 8px; }
+ .datepicker .end-date:first-child .show-date::before {
+ background-color: #FFFFFF; }
+ .datepicker tr td.start-date:last-child .show-date:after {
+ background-color: #FFFFFF;
+ content: "";
+ height: 26px;
+ position: absolute;
+ right: 0;
+ width: 8px; }
+ .datepicker tr td.start-date:last-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker tr td.start-date:first-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker tr td.between-date:last-child .show-date:after {
+ background-color: #FFFFFF;
+ content: "";
+ height: 26px;
+ position: absolute;
+ right: 0;
+ width: 8px; }
+ .datepicker tr td.between-date:last-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker tr td.between-date:first-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker tr td.end-date:last-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker tr td.end-date:first-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+ .datepicker th.datepicker-switch {
+ width: 198px;
+ font-size: 20px;
+ font-weight: normal;
+ cursor: default !important; }
+ .datepicker thead tr:first-child th {
+ cursor: pointer;
+ height: 60px;
+ line-height: 60px; }
+ .datepicker thead tr:first-child th.cw {
+ cursor: default;
+ background-color: transparent; }
+ .datepicker tfoot tr th {
+ cursor: pointer;
+ height: 60px;
+ line-height: 60px;
+ height: auto;
+ line-height: normal; }
+ .datepicker tfoot tr th li {
+ margin-bottom: 5px; }
+ .datepicker .prev {
+ color: transparent;
+ font-size: 0;
+ margin: 0 -1px -1px 0;
+ width: 46px; }
+ .datepicker .prev i {
+ color: #0568ae;
+ position: absolute;
+ font-size: 27px;
+ margin: 0;
+ top: 15px;
+ left: 8px; }
+ .datepicker .next {
+ color: transparent;
+ font-size: 0;
+ margin: 0 -1px -1px 0;
+ width: 46px; }
+ .datepicker .next i {
+ color: #0568ae;
+ position: absolute;
+ font-size: 27px;
+ margin: 0;
+ top: 15px;
+ right: 8px; }
+ .datepicker .cw {
+ font-size: 10px;
+ width: 12px;
+ padding: 0 2px 0 5px;
+ vertical-align: middle; }
+ .datepicker .due-date .show-date {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ background-color: #cf2a2a;
+ border-radius: 5px;
+ color: #FFFFFF !important; }
+ .datepicker .day.active .show-date:after {
+ border: 2px solid #0568ae;
+ border-radius: 7px;
+ content: "";
+ display: block;
+ height: 30px;
+ left: 4px;
+ position: absolute;
+ top: 0;
+ width: 30px; }
+ .datepicker .day:focus .show-date:after {
+ border: 2px solid #0568ae;
+ border-radius: 7px;
+ content: "";
+ display: block;
+ height: 30px;
+ left: 4px;
+ position: absolute;
+ top: 0;
+ width: 30px;
+ height: 30px;
+ left: 4px;
+ top: 0;
+ width: 30px; }
+ .datepicker .due-date.disabled .show-date:after {
+ border: 2px solid #0568ae;
+ border-radius: 7px;
+ content: "";
+ display: block;
+ height: 30px;
+ left: 4px;
+ position: absolute;
+ top: 0;
+ width: 30px; }
+ .datepicker .day.due-date:focus .show-date:after {
+ height: 30px;
+ left: 4px;
+ top: 0;
+ width: 30px; }
+ .datepicker .due-date.old:after {
+ visibility: hidden; }
+ .datepicker .due-date.new:after {
+ visibility: hidden; }
+ .datepicker .due-date.active:after {
+ border-color: #FFFFFF; }
+ .datepicker .due-date.active.focused {
+ color: #0568ae !important; }
+ .datepicker .due-date.active.focused:after {
+ border-color: #cf2a2a !important; }
+ .datepicker .dow {
+ height: 24px;
+ width: 42px;
+ font-weight: normal;
+ position: relative;
+ overflow: hidden;
+ color: transparent;
+ letter-spacing: -6px;
+ margin: 0 -1px -1px 0; }
+ .datepicker .dow span[aria-hidden="true"] {
+ bottom: 0;
+ color: #5A5A5A;
+ display: block;
+ left: 1px;
+ letter-spacing: 0;
+ line-height: .9;
+ margin: 0 auto;
+ padding: 0;
+ position: relative;
+ width: 22px; }
+ .datepicker .calendar-legend {
+ margin-top: 3px;
+ margin-bottom: 20px; }
+ .datepicker .calendar-legend li {
+ font-size: 1.4rem;
+ font-weight: normal;
+ margin-bottom: 5px;
+ padding-left: 10px;
+ padding-top: 5px;
+ position: relative; }
+ .datepicker i.legend-due-date {
+ background-color: #cf2a2a;
+ border-radius: 5px;
+ height: 18px;
+ width: 18px;
+ margin-right: 8px;
+ vertical-align: middle;
+ display: inline-block; }
+ .datepicker i.legend-selected-date {
+ background-color: #FFFFFF;
+ border: 2px solid #0568ae;
+ border-radius: 5px;
+ height: 18px;
+ width: 18px;
+ margin-right: 8px;
+ vertical-align: middle;
+ display: inline-block; }
+ .datepicker i.legend-selectedisdue {
+ background-color: #FFFFFF;
+ border: 2px solid #0568ae;
+ border-radius: 5px;
+ display: inline-block;
+ height: 18px;
+ margin-right: 8px;
+ position: relative;
+ vertical-align: middle;
+ width: 18px; }
+ .datepicker i.legend-selectedisdue:after {
+ background-color: #cf2a2a;
+ border-radius: 3px;
+ content: "";
+ display: block;
+ height: 10px;
+ left: 2px;
+ position: absolute;
+ top: 2px;
+ width: 10px; }
+ .datepicker .text-left {
+ width: 100%; }
+ .datepicker .active.old {
+ background-color: #ededed !important;
+ color: #ededed !important; }
+
+.datepicker-inline {
+ width: 220px; }
+
+.datepicker.datepicker-rtl {
+ direction: rtl; }
+ .datepicker.datepicker-rtl td span {
+ float: right; }
+
+.datepicker-dropdown {
+ top: 0;
+ left: 0; }
+ .datepicker-dropdown:before {
+ content: " ";
+ display: inline-block;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 10px solid #d2d2d2;
+ border-top: 0;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ position: absolute; }
+ .datepicker-dropdown:after {
+ content: " ";
+ display: inline-block;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 10px solid #fff;
+ border-top: 0;
+ position: absolute; }
+
+.datepicker-dropdown.datepicker-orient-left:before {
+ left: 16px; }
+
+.datepicker-dropdown.datepicker-orient-left:after {
+ left: 16px; }
+
+.datepicker-dropdown.datepicker-orient-right:before {
+ right: 16px; }
+
+.datepicker-dropdown.datepicker-orient-right:after {
+ right: 16px; }
+
+.datepicker-dropdown.datepicker-orient-top:before {
+ top: -10px; }
+
+.datepicker-dropdown.datepicker-orient-top:after {
+ top: -9px; }
+
+.datepicker-dropdown.datepicker-orient-bottom:before {
+ bottom: -7px;
+ border-bottom: 0;
+ border-top: 7px solid #959595; }
+
+.datepicker-dropdown.datepicker-orient-bottom:after {
+ bottom: -6px;
+ border-bottom: 0;
+ border-top: 6px solid #fff; }
+
+.datepicker.days div.datepicker-days {
+ display: block; }
+
+.datepicker.months div.datepicker-months {
+ display: block; }
+
+.datepicker.years div.datepicker-years {
+ display: block; }
+
+.show-date {
+ font-family: "Omnes-ECOMP-W02-Medium";
+ color: #0568ae;
+ height: 26px;
+ line-height: 26px;
+ margin: 4px auto 0;
+ width: 26px; }
+
+.input-group.date .input-group-addon i {
+ cursor: pointer;
+ width: 16px;
+ height: 16px; }
+
+.datepicker.dropdown-menu {
+ box-shadow: 0 10px 15px -10px rgba(0, 0, 0, 0.7);
+ position: absolute;
+ top: 100%;
+ left: 0;
+ float: left;
+ display: none;
+ margin-top: 13px;
+ width: 290px;
+ list-style: none;
+ background-color: #FFFFFF;
+ border: 1px solid #d2d2d2;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ color: #333333;
+ font-size: 13px;
+ line-height: 1.428571429;
+ z-index: 1050; }
+ .datepicker.dropdown-menu th {
+ display: block;
+ float: left;
+ padding: 0;
+ position: relative; }
+ .datepicker.dropdown-menu td {
+ display: block;
+ float: left;
+ padding: 0;
+ position: relative; }
+
+.s {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: -62px 0; }
+
+.m {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: -5px 0; }
+
+.t {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: -19px 0; }
+
+.w {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: -34px 0; }
+
+.f {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: -49px 0; }
+
+.d {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: 0 0; }
+
+.l {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: 0 0; }
+
+.v {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: 0 0; }
+
+.j {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: #FFFFFF;
+ background-repeat: no-repeat;
+ background-position: 0 0; }
+
+.b2b-coachmark-label {
+ z-index: 1060;
+ opacity: 1;
+ cursor: not-allowed;
+ position: relative; }
+
+.b2b-coachmark-highlight {
+ border: 1px solid #d3d3d3;
+ cursor: default;
+ z-index: 1045;
+ opacity: 1;
+ background-color: #ffffff;
+ border-radius: 10px;
+ position: relative;
+ box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.25);
+ padding: 10px;
+ position: absolute; }
+
+.b2b-coachmark-highlight-mask {
+ z-index: 1100;
+ opacity: .1; }
+
+.b2b-coachmark-container {
+ border: 1px solid #cccccc;
+ width: 316px;
+ pointer-events: auto;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 16px;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ background: #fff;
+ border-radius: 20px;
+ box-shadow: 0 6px 6px 0 rgba(0, 0, 0, 0.15);
+ color: #333;
+ line-height: 20px;
+ position: absolute;
+ top: 50px;
+ left: -97px;
+ display: block;
+ background-color: #ffffff;
+ z-index: 1050;
+ opacity: 1; }
+ .b2b-coachmark-container i.b2b-coachmark-caret {
+ position: absolute;
+ top: -12px;
+ left: 47%;
+ opacity: 1;
+ z-index: 1050; }
+ .b2b-coachmark-container i.b2b-coachmark-caret:before {
+ content: "";
+ border-left: 12px solid transparent;
+ border-right: 12px solid transparent;
+ border-bottom: 12px solid #d3d3d3;
+ position: absolute;
+ top: -1px; }
+ .b2b-coachmark-container i.b2b-coachmark-caret:after {
+ content: "";
+ border-left: 12px solid transparent;
+ border-right: 12px solid transparent;
+ border-bottom: 12px solid #fff;
+ position: absolute; }
+ .b2b-coachmark-container .b2b-coachmark-header {
+ position: relative;
+ height: 47px;
+ overflow: hidden; }
+ .b2b-coachmark-container .b2b-coachmark-header .corner-button {
+ box-shadow: 0 -24px 0 0 #f2f2f2 inset;
+ height: 69px;
+ position: absolute;
+ right: -33px;
+ top: -38px;
+ transform: rotate(45deg);
+ width: 69px; }
+ .b2b-coachmark-container .b2b-coachmark-countlabel {
+ font-size: 12px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #333333;
+ margin-left: 20px;
+ margin-top: 20px; }
+ .b2b-coachmark-container .b2b-coachmark-content {
+ padding: 0px 20px 20px 20px;
+ float: left; }
+ .b2b-coachmark-container .b2b-coachmark-content .icon-misc-dimmer {
+ font-size: 32px;
+ float: left;
+ margin-right: 10px;
+ width: 32px; }
+ .b2b-coachmark-container .b2b-coachmark-content .offscreen-text {
+ position: absolute;
+ left: -10000px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden; }
+ .b2b-coachmark-container .b2b-coachmark-content .b2b-coachmark-content-header {
+ font-size: 16px;
+ color: #333333;
+ line-height: 18px;
+ float: left;
+ width: 220px; }
+ .b2b-coachmark-container .b2b-coachmark-content .b2b-coachmark-description {
+ font-size: 14px;
+ line-height: 18px;
+ color: #333333;
+ width: 100%;
+ float: left;
+ margin-top: 15px; }
+ .b2b-coachmark-container .b2b-coachmark-content .b2b-coachmark-btn-group {
+ margin-top: 20px;
+ float: left;
+ text-align: right;
+ width: 100%; }
+ .b2b-coachmark-container .b2b-coachmark-content .b2b-coachmark-btn-group .b2b-coachmark-link {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 15px;
+ color: #0574ac;
+ line-height: 18px;
+ margin-right: 20px; }
+ .b2b-coachmark-container .b2b-coachmark-content .b2b-coachmark-btn-group button {
+ font-size: 15px;
+ margin: 0px; }
+
+.datepicker {
+ background-color: #fff;
+ padding: 0;
+ border-radius: 5px;
+ direction: ltr; }
+
+.datepicker-inline {
+ width: 220px; }
+
+.datepicker.datepicker-rtl {
+ direction: rtl; }
+
+.datepicker.datepicker-rtl td span {
+ float: right; }
+
+.datepicker-dropdown {
+ top: 0;
+ left: 0; }
+
+/* ARROW */
+.datepicker-dropdown:before {
+ content: " ";
+ display: inline-block;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 10px solid #d2d2d2;
+ border-top: 0;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ position: absolute; }
+
+.datepicker-dropdown:after {
+ content: " ";
+ display: inline-block;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 10px solid #fff;
+ border-top: 0;
+ position: absolute; }
+
+.datepicker-dropdown.datepicker-orient-left:before,
+.datepicker-dropdown.datepicker-orient-left:after {
+ left: 16px; }
+
+.datepicker-dropdown.datepicker-orient-right:before,
+.datepicker-dropdown.datepicker-orient-right:after {
+ right: 16px; }
+
+.datepicker-dropdown.datepicker-orient-top:before {
+ top: -10px; }
+
+.datepicker-dropdown.datepicker-orient-top:after {
+ top: -9px; }
+
+.datepicker-dropdown.datepicker-orient-bottom:before {
+ bottom: -7px;
+ border-bottom: 0;
+ border-top: 7px solid #959595; }
+
+.datepicker-dropdown.datepicker-orient-bottom:after {
+ bottom: -6px;
+ border-bottom: 0;
+ border-top: 6px solid #fff; }
+
+.datepicker > div {
+ display: none; }
+
+.datepicker.days div.datepicker-days {
+ display: block; }
+
+.datepicker.months div.datepicker-months {
+ display: block; }
+
+.datepicker.years div.datepicker-years {
+ display: block; }
+
+.datepicker table {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ margin: 0 0 0 0; }
+
+.datepicker td,
+.datepicker th {
+ text-align: center;
+ display: block;
+ width: 30px;
+ height: 30px;
+ border: none; }
+
+.datepicker tbody :focus {
+ outline: none; }
+
+.datepicker td.day {
+ background-color: transparent;
+ color: #0568ae;
+ cursor: pointer;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 16px;
+ height: 34px;
+ line-height: 30rem;
+ margin: -2px -1px 0 0;
+ overflow: hidden;
+ text-align: center;
+ width: 42px; }
+
+.datepicker :focus {
+ outline: 1px dotted #000;
+ outline-offset: -2px; }
+
+.datepicker td.day.focused {
+ background: #ededed;
+ cursor: pointer; }
+
+.datepicker td.day.focused.active {
+ background-color: #ededed;
+ color: #0568ae; }
+
+.datepicker td.disabled,
+.datepicker td.disabled:hover {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5a5a5a;
+ cursor: default; }
+
+.datepicker td.today,
+.datepicker td.today:hover,
+.datepicker td.today.disabled {
+ color: #fff;
+ background-color: #0568ae; }
+
+.datepicker td.today.active,
+.datepicker td.today:active,
+.datepicker td.today:hover,
+.datepicker td.today:focus {
+ color: #fff;
+ background-color: #0568ae; }
+
+.datepicker td.today.active:hover {
+ color: #fff; }
+
+.datepicker td.selected,
+.datepicker td.selected:hover,
+.datepicker td.selected.disabled {
+ color: #ffffff;
+ background-color: #959595; }
+
+.datepicker td.active:not(.new),
+.datepicker td.active:hover:not(.new) {
+ color: #ffffff;
+ border-color: #357ebd; }
+
+.show-date {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #0568ae;
+ height: 26px;
+ line-height: 26px;
+ margin: 4px auto 0;
+ width: 26px; }
+
+.datepicker .start-date .show-date,
+.datepicker .between-date .show-date,
+.datepicker .end-date .show-date {
+ background-color: #0568ae;
+ color: #fff !important; }
+
+.datepicker .start-date .show-date {
+ border-radius: 5px 0 0 5px;
+ z-index: 1; }
+
+.datepicker .start-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: 20px;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+
+.datepicker .between-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: 0;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+
+.datepicker .end-date .show-date {
+ border-radius: 0 5px 5px 0; }
+
+.datepicker .end-date .show-date:before {
+ background-color: #0568ae;
+ content: "";
+ display: block;
+ height: 26px;
+ left: -20px;
+ position: absolute;
+ width: 100%;
+ z-index: -1; }
+
+.datepicker .between-date:first-child .show-date:before {
+ background-color: #fff;
+ content: "";
+ height: 26px;
+ position: absolute;
+ left: 0;
+ width: 8px; }
+
+.datepicker .end-date:first-child .show-date:after {
+ background-color: #fff;
+ content: "";
+ height: 26px;
+ position: absolute;
+ left: 0;
+ width: 8px; }
+
+.datepicker .end-date:first-child .show-date::before {
+ background-color: #fff; }
+
+.datepicker tr td.start-date:last-child .show-date:after,
+.datepicker tr td.between-date:last-child .show-date:after {
+ background-color: #fff;
+ content: "";
+ height: 26px;
+ position: absolute;
+ right: 0;
+ width: 8px; }
+
+.datepicker tr td.start-date:last-child:focus .show-date:after,
+.datepicker tr td.end-date:last-child:focus .show-date:after,
+.datepicker tr td.between-date:last-child:focus .show-date:after,
+.datepicker tr td.start-date:first-child:focus .show-date:after,
+.datepicker tr td.end-date:first-child:focus .show-date:after,
+.datepicker tr td.between-date:first-child:focus .show-date:after {
+ height: 30px;
+ width: 30px;
+ background-color: transparent; }
+
+.datepicker td.active:not(.new) .show-date,
+.datepicker td.active:hover:not(.new) .show-date {
+ color: #0568ae;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.datepicker td.disabled .show-date,
+.datepicker td.disabled:hover .show-date {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5a5a5a; }
+
+.datepicker td span {
+ display: block;
+ width: 23%;
+ height: 54px;
+ line-height: 54px;
+ float: left;
+ margin: 1%;
+ cursor: pointer;
+ border-radius: 4px; }
+
+.datepicker td span:hover {
+ background: #eeeeee; }
+
+.datepicker td span.disabled,
+.datepicker td span.disabled:hover {
+ background: none;
+ color: #5a5a5a;
+ cursor: default; }
+
+.datepicker td span.active,
+.datepicker td span.active:hover,
+.datepicker td span.active.disabled {
+ color: #ffffff;
+ background-color: #0568ae;
+ border-color: #357ebd; }
+
+.datepicker th.datepicker-switch {
+ width: 198px;
+ font-size: 20px;
+ font-weight: normal;
+ cursor: default !important; }
+
+.datepicker thead tr:first-child th,
+.datepicker tfoot tr th {
+ cursor: pointer;
+ height: 60px;
+ line-height: 60px; }
+
+.datepicker tfoot tr th {
+ height: auto;
+ line-height: normal; }
+
+.datepicker tfoot tr th li {
+ margin-bottom: 5px; }
+
+.datepicker .prev,
+.datepicker .next {
+ color: transparent;
+ font-size: 0;
+ margin: 0 -1px -1px 0;
+ width: 46px; }
+
+.datepicker .prev i,
+.datepicker .next i {
+ color: #0568ae;
+ position: absolute;
+ font-size: 27px;
+ margin: 0;
+ top: 15px; }
+
+.datepicker .prev i {
+ left: 8px; }
+
+.datepicker .next i {
+ right: 8px; }
+
+.datepicker .cw {
+ font-size: 10px;
+ width: 12px;
+ padding: 0 2px 0 5px;
+ vertical-align: middle; }
+
+.datepicker thead tr:first-child th.cw {
+ cursor: default;
+ background-color: transparent; }
+
+.input-group.date .input-group-addon i {
+ cursor: pointer;
+ width: 16px;
+ height: 16px; }
+
+.datepicker.dropdown-menu {
+ box-shadow: 0 10px 15px -10px rgba(0, 0, 0, 0.7);
+ position: absolute;
+ top: 100%;
+ left: 0;
+ float: left;
+ display: none;
+ margin-top: 13px;
+ width: 290px;
+ list-style: none;
+ background-color: #ffffff;
+ border: 1px solid #d2d2d2;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ color: #333333;
+ font-size: 13px;
+ line-height: 1.428571429;
+ z-index: 1050; }
+
+.datepicker.dropdown-menu th,
+.datepicker.dropdown-menu td {
+ display: block;
+ float: left;
+ padding: 0;
+ position: relative; }
+
+.datepicker .due-date .show-date {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ background-color: #cf2a2a;
+ border-radius: 5px;
+ color: #fff !important; }
+
+.datepicker .day.active .show-date:after,
+.datepicker .day:focus .show-date:after,
+.datepicker .due-date.disabled .show-date:after {
+ border: 2px solid #0568ae;
+ border-radius: 7px;
+ content: "";
+ display: block;
+ height: 30px;
+ left: 4px;
+ position: absolute;
+ top: 0;
+ width: 30px; }
+
+.datepicker .day:focus .show-date:after {
+ height: 30px;
+ left: 4px;
+ top: 0;
+ width: 30px; }
+
+.datepicker .day.due-date:focus .show-date:after {
+ height: 30px;
+ left: 4px;
+ top: 0;
+ width: 30px; }
+
+.datepicker .due-date.old:after,
+.datepicker .due-date.new:after {
+ visibility: hidden; }
+
+.datepicker .due-date.active:after {
+ border-color: #fff; }
+
+.datepicker .due-date.active.focused {
+ color: #0568ae !important; }
+
+.datepicker .due-date.active.focused:after {
+ border-color: #cf2a2a !important; }
+
+.datepicker .dow {
+ height: 24px;
+ width: 42px;
+ font-weight: normal;
+ position: relative;
+ overflow: hidden;
+ color: transparent;
+ letter-spacing: -6px;
+ margin: 0 -1px -1px 0; }
+
+.datepicker .dow span[aria-hidden="true"] {
+ bottom: 0;
+ color: #5a5a5a;
+ display: block;
+ left: 1px;
+ letter-spacing: 0;
+ line-height: .9;
+ margin: 0 auto;
+ padding: 0;
+ position: relative;
+ width: 22px; }
+
+.datepicker .calendar-legend {
+ margin-top: 3px;
+ margin-bottom: 20px; }
+
+.datepicker .calendar-legend li {
+ font-size: 1.4rem;
+ font-weight: normal;
+ margin-bottom: 5px;
+ padding-left: 10px;
+ padding-top: 5px;
+ position: relative; }
+
+.datepicker i.legend-due-date {
+ background-color: #cf2a2a;
+ border-radius: 5px;
+ height: 18px;
+ width: 18px;
+ margin-right: 8px;
+ vertical-align: middle;
+ display: inline-block; }
+
+.datepicker i.legend-selected-date {
+ background-color: #fff;
+ border: 2px solid #0568ae;
+ border-radius: 5px;
+ height: 18px;
+ width: 18px;
+ margin-right: 8px;
+ vertical-align: middle;
+ display: inline-block; }
+
+.datepicker i.legend-selectedisdue {
+ background-color: #fff;
+ border: 2px solid #0568ae;
+ border-radius: 5px;
+ display: inline-block;
+ height: 18px;
+ margin-right: 8px;
+ position: relative;
+ vertical-align: middle;
+ width: 18px; }
+
+.datepicker i.legend-selectedisdue:after {
+ background-color: #cf2a2a;
+ border-radius: 3px;
+ content: "";
+ display: block;
+ height: 10px;
+ left: 2px;
+ position: absolute;
+ top: 2px;
+ width: 10px; }
+
+.datepicker .text-left {
+ width: 100%; }
+
+.datepicker .active.old {
+ background-color: #ededed !important;
+ color: #ededed !important; }
+
+.s,
+.m,
+.t,
+.w,
+.f,
+.d,
+.l,
+.v,
+.j {
+ display: block;
+ height: 20px;
+ width: 12px;
+ margin: 0 auto;
+ background-color: white;
+ background-repeat: no-repeat; }
+
+.s {
+ background-position: -62px 0; }
+
+.m {
+ background-position: -5px 0; }
+
+.t {
+ background-position: -19px 0; }
+
+.w {
+ background-position: -34px 0; }
+
+.f {
+ background-position: -49px 0; }
+
+/* spanish */
+.d {
+ background-position: 0 0; }
+
+.l {
+ background-position: 0 0; }
+
+.v {
+ background-position: 0 0; }
+
+.j {
+ background-position: 0 0; }
+
+/* remove focus outline when dropdown is opened */
+/*resolve blue focus outline over dropdown with error*/
+select {
+ margin-right: -1;
+ max-width: 100%;
+ height: 36px;
+ line-height: 25px;
+ width: auto;
+ background-color: #FFFFFF; }
+
+.selectWrap.disabled .icon-primary-down {
+ color: #767676; }
+
+.selectWrap.disabled input.awd-select {
+ z-index: 0;
+ padding: 10px 45px 10px 15px;
+ text-indent: 0; }
+
+.selectWrap.disabled button.awd-select {
+ z-index: 0;
+ text-indent: 15; }
+
+.selectWrap.disabled:after {
+ color: #5A5A5A;
+ cursor: not-allowed; }
+
+input.awd-select {
+ background-color: transparent;
+ border: 1px solid #d2d2d2;
+ border-radius: 6px;
+ box-shadow: 1px 5px 2px -5px rgba(0, 0, 0, 0.15);
+ color: #333333;
+ display: block;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ /*font-size: 1.6rem;*/
+ height: 36px;
+ line-height: 0;
+ margin-bottom: 0;
+ padding: 12px 45px 8px 0;
+ position: relative;
+ text-align: left;
+ top: 0;
+ width: 100%;
+ z-index: 10;
+ padding: 12px 45px 8px 15px;
+ user-select: none; }
+ input.awd-select:focus {
+ border-color: #0568ae !important; }
+
+button.awd-select {
+ background-color: transparent;
+ border: 1px solid #d2d2d2;
+ border-radius: 6px;
+ box-shadow: 1px 5px 2px -5px rgba(0, 0, 0, 0.15);
+ color: #333333;
+ display: block;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ /*font-size: 1.6rem;*/
+ height: 36px;
+ line-height: 36px;
+ margin-bottom: 0;
+ /*padding-right: 41px;*/
+ position: relative;
+ text-align: left;
+ top: 0;
+ width: 100%;
+ z-index: 10; }
+ button.awd-select:not(.large) {
+ text-indent: 15px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: clip;
+ text-overflow: ellipsis; }
+ button.awd-select img {
+ height: 26px;
+ margin-right: 7px;
+ margin-top: -10px;
+ position: relative;
+ top: 2px;
+ vertical-align: text-bottom; }
+ button.awd-select:focus {
+ border-color: #0568ae !important; }
+ button.awd-select i {
+ font-size: 23px;
+ position: absolute;
+ right: 33px;
+ top: 5px;
+ z-index: 1000; }
+
+button.awd-select.large {
+ align-items: center;
+ display: flex;
+ height: 60px;
+ line-height: 20px;
+ overflow: hidden;
+ padding-left: 70px;
+ vertical-align: middle; }
+ button.awd-select.large img {
+ height: 40px;
+ left: 20px;
+ position: absolute;
+ top: 20px;
+ width: 40px; }
+
+.selectWrap.large {
+ height: 60px; }
+ .selectWrap.large .awd-select-list-item {
+ align-items: center;
+ display: flex;
+ height: 60px;
+ line-height: 20px;
+ overflow: hidden;
+ padding-left: 70px;
+ vertical-align: middle; }
+ .selectWrap.large .awd-select-list-item img {
+ height: 40px;
+ left: 20px;
+ position: absolute;
+ top: 20px;
+ width: 40px;
+ top: 10px; }
+
+button.awd-select.active {
+ border-radius: 6px 6px 0 0; }
+ button.awd-select.active:focus {
+ border-color: #d2d2d2 !important; }
+
+input.awd-select.active {
+ border-radius: 6px 6px 0 0; }
+ input.awd-select.active:focus {
+ border-color: #d2d2d2 !important; }
+
+.selectWrapper {
+ position: relative; }
+
+span.selectWrap input[readonly]:focus {
+ color: transparent;
+ text-shadow: 0 0 0 #000; }
+
+.isIE.ds2-no-colors .awd-select:focus {
+ outline: 1px dashed transparent; }
+
+.awd-select-list {
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.15);
+ border-radius: 0 0 6px 6px;
+ position: absolute;
+ border: 1px solid #d2d2d2;
+ border-top: 0;
+ padding: 0;
+ background-color: #f2f2f2;
+ z-index: 1000;
+ width: 100%;
+ max-height: 320px;
+ overflow-y: auto; }
+
+.awd-select-list-item {
+ cursor: pointer;
+ height: 100%;
+ min-height: 36px;
+ line-height: 38px;
+ overflow: hidden;
+ padding: 0 15px;
+ position: relative;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ z-index: 1000; }
+ .awd-select-list-item:hover {
+ cursor: pointer;
+ background-color: #d2d2d2;
+ outline: 1px dashed transparent; }
+ .awd-select-list-item:focus {
+ cursor: pointer;
+ background-color: #d2d2d2;
+ outline: 1px dashed transparent; }
+ .awd-select-list-item img {
+ margin-top: 0;
+ margin-right: 7px;
+ height: 26px;
+ width: 26px; }
+
+.selectWrap {
+ border-radius: 6px;
+ position: relative;
+ height: 36px;
+ line-height: 28px;
+ display: block;
+ margin: 0;
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="@att-gray-highlight", endColorstr="@att-functional-bg-gray", GradientType=0); }
+ .selectWrap:not(.large) .awd-select-list-item:first-child {
+ margin-top: 15px; }
+ .selectWrap:not(.large) .awd-select-list-item:last-child {
+ margin-bottom: 15px; }
+ .selectWrap .icon-primary-down {
+ font-size: 23px;
+ margin-top: -11px;
+ position: absolute;
+ right: 4px;
+ top: 50%; }
+ .selectWrap + [aria-expanded="true"] {
+ padding-bottom: 9px;
+ padding-top: 20px; }
+
+.awd-select-list-item[aria-selected="true"] {
+ background-color: #d2d2d2; }
+
+span input.awd-select {
+ width: 100%;
+ cursor: pointer;
+ text-overflow: ellipsis;
+ padding-right: 45px; }
+
+li.optgroup-wrapper {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ cursor: default !important;
+ padding: 0px 15px; }
+ li.optgroup-wrapper:first-child {
+ padding-top: 10px; }
+ li.optgroup-wrapper:hover {
+ background-color: #f2f2f2; }
+
+ul.optgroup {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ cursor: pointer !important;
+ margin: 0 -15px; }
+ ul.optgroup li {
+ padding: 0 0 0 33px; }
+
+label + .selectWrap {
+ margin-top: 4px; }
+
+.selectorModule {
+ border-radius: 6px;
+ position: relative;
+ height: 36px;
+ line-height: 28px;
+ display: block;
+ margin: 0;
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="@att-gray-highlight", endColorstr="@att-functional-bg-gray", GradientType=0); }
+
+.group .selectWrap {
+ margin: 0 0 10px 0; }
+
+select.awd-select {
+ position: relative;
+ top: 0;
+ left: 0;
+ font-size: 16px;
+ z-index: 1010;
+ height: 33px;
+ min-width: 100%;
+ opacity: 0.01; }
+ select.awd-select > optgroup {
+ padding-left: 8px;
+ font-style: normal;
+ margin-top: 10px; }
+ select.awd-select > optgroup:first-child {
+ margin-top: 0; }
+ select.awd-select > optgroup > option {
+ padding-left: 8px; }
+ select.awd-select > option {
+ padding-left: 8px; }
+ select.awd-select + span {
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="@att-gray-highlight", endColorstr="@att-functional-bg-gray", GradientType=0);
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ display: block;
+ border: 1px solid #d2d2d2;
+ border-radius: 6px;
+ height: 35px;
+ line-height: 0;
+ padding: 18px 45px 15px 15px;
+ width: 100%;
+ font-size: 1.6rem;
+ padding-right: 45px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis; }
+ select.awd-select + span > i {
+ font-size: 23px;
+ position: absolute;
+ right: 33px;
+ top: 5px;
+ z-index: 1000; }
+ select.awd-select + span > i:before {
+ left: 1px;
+ position: absolute;
+ top: -1px; }
+ select.awd-select:focus + span {
+ border-color: #0568ae; }
+
+.isIE select.awd-select + span {
+ line-height: 1; }
+
+[data-default-option="true"] {
+ color: #767676 !important;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial; }
+
+.placeholdercolor {
+ color: #767676 !important;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial; }
+
+.filterTank button.awd-select {
+ border-color: #d2d2d2;
+ background-color: #333333;
+ color: #FFFFFF;
+ color: #333333; }
+ .filterTank button.awd-select:after {
+ background-color: #FFFFFF !important;
+ border-color: #d2d2d2; }
+
+.utility-bg button.awd-select {
+ border-color: #d2d2d2;
+ background-color: #333333;
+ color: #FFFFFF;
+ color: #333333; }
+ .utility-bg button.awd-select:after {
+ background-color: #FFFFFF !important;
+ border-color: #d2d2d2; }
+
+.utility-bg select.awd-select + span {
+ border-color: #d2d2d2;
+ border-color: #d2d2d2;
+ background-color: #333333;
+ background-color: #333333;
+ color: #FFFFFF;
+ color: #FFFFFF; }
+ .utility-bg select.awd-select + span:after {
+ background-color: #FFFFFF !important;
+ background-color: #FFFFFF !important;
+ border-color: #d2d2d2;
+ border-color: #d2d2d2; }
+
+.utility-bg select.awd-select:focus + span {
+ border-color: #d2d2d2;
+ border-color: #d2d2d2;
+ background-color: #333333;
+ background-color: #333333;
+ color: #FFFFFF;
+ color: #FFFFFF; }
+ .utility-bg select.awd-select:focus + span:after {
+ background-color: #FFFFFF !important;
+ background-color: #FFFFFF !important;
+ border-color: #d2d2d2;
+ border-color: #d2d2d2; }
+
+.utility-bg select.awd-select:hover + span {
+ border-color: #d2d2d2;
+ border-color: #d2d2d2;
+ background-color: #333333;
+ background-color: #333333;
+ color: #FFFFFF;
+ color: #FFFFFF; }
+ .utility-bg select.awd-select:hover + span:after {
+ background-color: #FFFFFF !important;
+ background-color: #FFFFFF !important;
+ border-color: #d2d2d2;
+ border-color: #d2d2d2; }
+
+input.awd-select[disabled] {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ input.awd-select[disabled] + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+
+button.awd-select[disabled] {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ button.awd-select[disabled]:after {
+ background-color: #d2d2d2 !important;
+ border-color: #d2d2d2; }
+
+select.awd-select[disabled] + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ select.awd-select[disabled] + span:after {
+ background-color: #d2d2d2 !important;
+ border-color: #d2d2d2; }
+
+select.awd-select[disabled]:focus + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+
+select.awd-select[disabled]:hover + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+
+input.awd-select[disabled="disabled"] {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ input.awd-select[disabled="disabled"] + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+
+select.awd-select[disabled="disabled"] + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ select.awd-select[disabled="disabled"] + span:after {
+ background-color: #d2d2d2 !important;
+ border-color: #d2d2d2; }
+
+select.awd-select[disabled="disabled"]:focus + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ select.awd-select[disabled="disabled"]:focus + span:after {
+ background-color: #d2d2d2 !important;
+ border-color: #d2d2d2; }
+
+select.awd-select[disabled="disabled"]:hover + span {
+ cursor: not-allowed;
+ border-color: #d2d2d2;
+ background-color: #d2d2d2;
+ background-image: none;
+ color: #5A5A5A; }
+ select.awd-select[disabled="disabled"]:hover + span:after {
+ background-color: #d2d2d2 !important;
+ border-color: #d2d2d2; }
+
+.ddexpand-wrapper > h2 {
+ margin-bottom: 11px; }
+ .ddexpand-wrapper > h2 + p {
+ margin-bottom: 4px; }
+
+.ddexpand-wrapper .selectWrap + [aria-expanded="true"] .form-row {
+ margin-top: 11px; }
+
+.ddexpand-wrapper .selectWrap + [aria-expanded="true"] .row + .row .form-row {
+ margin-top: 14px; }
+
+.modal .awd-select-list {
+ z-index: 1060 !important; }
+
+.form-row.error button.awd-select.active:focus {
+ border-color: #cf2a2a !important; }
+
+.form-row.error input.awd-select.active:focus {
+ border-color: #cf2a2a !important; }
+
+.awd-module-list .module-list-item[aria-selected="true"] {
+ background-color: #f2f2f2; }
+
+li.module-list-item[aria-selected="true"]:before {
+ color: #0568ae;
+ display: inline-block;
+ font-family: "icoControls" !important;
+ font-style: normal;
+ font-size: 20px;
+ font-weight: normal;
+ font-variant: normal;
+ height: 1em;
+ margin-right: 7px;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ position: relative;
+ speak: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ vertical-align: middle;
+ width: 1em;
+ content: "\e907";
+ box-sizing: border-box;
+ display: inline-block;
+ font-size: 2em;
+ height: 1em;
+ position: absolute;
+ top: 20px;
+ right: 0px;
+ vertical-align: middle;
+ width: 1em;
+ color: #007a3e; }
+
+@media (min-width: 768px) {
+ span[class*="large"] {
+ max-width: 370px; }
+ .large {
+ max-width: 370px; } }
+
+@media (max-width: 767px) {
+ .selectWrap.large:after {
+ right: 5px; }
+ .selectWrap.large .awd-select-list-item {
+ padding-right: 41px; }
+ .selectWrap + div > h4 {
+ margin-bottom: 0;
+ font-size: 16px; } }
+
+/**********************Dropdown Chrome scrolling fix start ********************/
+input.awd-select {
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ -ms-user-select: text;
+ user-select: text; }
+
+input.awd-select.focused {
+ -webkit-user-select: none !important;
+ -moz-user-select: none !important;
+ -ms-user-select: none !important;
+ user-select: none !important; }
+
+/**********************Dropdown Chrome scrolling fix end ********************/
+.mpc-expanders {
+ border-bottom: 1px solid #e4e4e4;
+ border-top: 1px solid #e4e4e4; }
+
+.mpc-expanders + .mpc-expanders {
+ border-top: 0px; }
+
+.mpc-expanders .heading-medium {
+ margin-bottom: 10px; }
+
+.mpc-expanders .p-small {
+ margin-top: 5px; }
+
+.mpc-expander-body {
+ border-top: 1px solid #e4e4e4; }
+
+.mpc-expander-body .mpc-expanders {
+ border-bottom: 1px solid #e4e4e4;
+ border-top: 0; }
+
+.mpc-expander-body .mpc-expanders:last-child {
+ border-bottom: 0px; }
+
+.ddh-blue {
+ color: #0574ac; }
+
+.b2b-dragdrop {
+ border: 1px dashed #bbb;
+ border-radius: 5px;
+ padding: 0;
+ text-align: center;
+ color: #bbb;
+ position: relative; }
+
+.b2b-dragdrop-over {
+ background: #0091d9;
+ color: #006496; }
+ .b2b-dragdrop-over:after {
+ content: "Drop the file";
+ color: #fff;
+ width: 80px;
+ height: 20px;
+ overflow: hidden;
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0; }
+
+.b2b-file-container {
+ position: relative;
+ overflow: hidden;
+ display: inline-table;
+ font-weight: 400; }
+ .b2b-file-container [type=file] {
+ position: absolute;
+ cursor: inherit;
+ display: block;
+ font-size: 0;
+ opacity: 0;
+ height: 0;
+ width: 0;
+ left: 0;
+ top: 0;
+ -ms-filter: "alpha(Opacity=0)"; }
+
+.b2b-upload-link {
+ color: #0568ae; }
+
+.b2b-flyout {
+ position: relative;
+ display: inline-block;
+ cursor: default; }
+
+.b2b-flyout-icon {
+ cursor: pointer; }
+ .b2b-flyout-icon:focus {
+ outline: thin dotted #666;
+ outline-offset: -1px; }
+
+.b2b-flyout .b2b-flyout-container {
+ border: 1px solid #d3d3d3;
+ width: 300px;
+ padding: 20px;
+ pointer-events: auto;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 16px;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ background: #fff;
+ border-radius: 6px;
+ box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.25);
+ color: #333;
+ line-height: 20px;
+ position: absolute;
+ top: 35px;
+ opacity: 0;
+ z-index: 1010;
+ display: none; }
+ .b2b-flyout .b2b-flyout-container.open-flyout {
+ opacity: 1;
+ display: block; }
+
+.b2b-flyout i.b2b-flyout-caret {
+ position: absolute;
+ top: -8px;
+ left: 50%;
+ opacity: 0;
+ z-index: 1011;
+ display: none; }
+ .b2b-flyout i.b2b-flyout-caret.open-flyout {
+ opacity: 1;
+ display: block; }
+ .b2b-flyout i.b2b-flyout-caret:before {
+ content: "";
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ border-bottom: 8px solid #d3d3d3;
+ position: absolute;
+ top: -1px; }
+ .b2b-flyout i.b2b-flyout-caret:after {
+ content: "";
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ border-bottom: 8px solid #fff;
+ position: absolute; }
+
+.b2b-flyout .b2b-flyout-container.b2b-flyout-left i.b2b-flyout-caret {
+ left: 16px !important; }
+
+.b2b-flyout .b2b-flyout-container.b2b-flyout-right i.b2b-flyout-caret {
+ left: inherit !important;
+ right: 30px !important; }
+
+.b2b-flyout .b2b-flyout-container.b2b-flyout-above {
+ box-shadow: 0 -5px 6px 0 rgba(0, 0, 0, 0.25); }
+ .b2b-flyout .b2b-flyout-container.b2b-flyout-above i.b2b-flyout-caret {
+ top: auto;
+ bottom: 0px; }
+ .b2b-flyout .b2b-flyout-container.b2b-flyout-above i.b2b-flyout-caret:before {
+ top: auto;
+ bottom: -9px;
+ border-top: 8px solid #d3d3d3;
+ border-bottom: none; }
+ .b2b-flyout .b2b-flyout-container.b2b-flyout-above i.b2b-flyout-caret:after {
+ border-top: 8px solid #fff;
+ border-bottom: none; }
+
+.b2b-flyout .b2b-flyout-container.b2b-flyout-centerLeft i.b2b-flyout-caret {
+ left: inherit !important;
+ right: -7px !important;
+ top: 8px;
+ transform: rotate(90deg); }
+
+.b2b-flyout .b2b-flyout-container.b2b-flyout-centerRight i.b2b-flyout-caret {
+ left: -8px !important;
+ top: 296px;
+ transform: rotate(-90deg); }
+
+.b2b-flyout .buttons-group {
+ margin-top: 20px; }
+ .b2b-flyout .buttons-group .cta-button-group {
+ width: 100%;
+ border-top: 1px solid #ccc;
+ padding: 20px 0 0; }
+ .b2b-flyout .buttons-group .cta-button-group button {
+ margin-bottom: 0; }
+
+.b2b-flyout .heading {
+ font-size: 20px;
+ margin-bottom: 10px; }
+
+.b2b-flyout .body-text {
+ font-size: 14px;
+ margin-bottom: 30px; }
+
+.b2b-footer-wrapper {
+ width: 100%;
+ background-color: #222; }
+
+.b2b-footer-container {
+ width: 980px;
+ margin: 0 auto;
+ padding-top: 15px; }
+ .b2b-footer-container .footer-columns {
+ display: inline-block;
+ text-align: left;
+ vertical-align: top; }
+ .b2b-footer-container .footer-columns.three-column, .b2b-footer-container .footer-columns.four-column, .b2b-footer-container .footer-columns.five-column {
+ padding-top: 30px; }
+ .b2b-footer-container .footer-columns.three-column {
+ width: 33.3%;
+ padding-left: 75px; }
+ .b2b-footer-container .footer-columns.four-column {
+ width: 25%;
+ padding-left: 75px; }
+ .b2b-footer-container .footer-columns.five-column {
+ width: 20%; }
+ .b2b-footer-container .footer-columns .b2b-footer-header {
+ color: #009fdb;
+ font-size: 18px;
+ font-style: normal;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ line-height: 23.9px;
+ margin: 0; }
+ .b2b-footer-container .footer-columns li {
+ padding: 7.5px 0; }
+ .b2b-footer-container .footer-columns ul li:first-child {
+ padding-top: 15px; }
+ .b2b-footer-container .footer-columns li a {
+ color: #fff;
+ font-size: 16px;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+ .b2b-footer-container .footer-nav-content {
+ padding-bottom: 10px; }
+ .b2b-footer-container .footer-nav-content li {
+ display: inline;
+ font-size: 14px;
+ color: #fff;
+ vertical-align: middle; }
+ .b2b-footer-container .footer-nav-content li a {
+ color: #fff;
+ font-size: 14px;
+ vertical-align: middle;
+ margin-right: 5px;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+.b2b-footer-wrapper .b2b-footer-container hr {
+ background: #d2d2d2;
+ margin-top: 50px; }
+
+.b2b-footer-wrapper .divider-bottom-footer {
+ padding: 45px 0 50px 0; }
+
+.b2b-footer-wrapper .footerLogo {
+ margin: 10px 0 0 0px;
+ vertical-align: top; }
+ .b2b-footer-wrapper .footerLogo div {
+ display: inline-block; }
+ .b2b-footer-wrapper .footerLogo .icon-primary-att-globe {
+ font-size: 40px; }
+ .b2b-footer-wrapper .footerLogo .logo-title {
+ color: #fff;
+ margin-left: 10px;
+ display: inline-block;
+ font-size: 26px;
+ margin-top: 0px; }
+
+.b2b-footer-wrapper .copyright-text {
+ color: #fff;
+ font-size: 11px;
+ text-align: left;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+ .b2b-footer-wrapper .copyright-text a {
+ color: #fff;
+ text-decoration: underline;
+ display: inline-block; }
+ .b2b-footer-wrapper .copyright-text a:hover {
+ text-decoration: none; }
+
+@media (max-width: 768px) {
+ .b2b-footer-wrapper {
+ padding: 0 15px; }
+ .b2b-footer-container {
+ width: 100%; }
+ .b2b-footer-container .footer-columns.three-column, .b2b-footer-container .footer-columns.four-column, .b2b-footer-container .footer-columns.five-column {
+ width: 50%; }
+ .b2b-footer-wrapper .divider-bottom-footer {
+ padding-top: 15px; }
+ .b2b-footer-wrapper .divider-bottom-footer .footer-links {
+ width: 100%; }
+ .b2b-footer-wrapper .footerLogo {
+ margin: 30px 0 0 0; }
+ .b2b-footer-wrapper .footerLogo .footer-logo {
+ margin: 0;
+ padding-left: 10px; } }
+
+.b2b-header-tabs {
+ background-color: #222;
+ width: 100%;
+ position: relative;
+ height: 45px; }
+ .b2b-header-tabs .icon-primary-att-globe {
+ color: #0568ae; }
+ .b2b-header-tabs a:focus {
+ border: 1px solid white; }
+ .b2b-header-tabs .header__items {
+ width: 980px;
+ margin: 0 auto;
+ display: block;
+ list-style: none;
+ padding: 6px 0px 0px 0px;
+ border-spacing: 30px 0; }
+ .b2b-header-tabs .header__item {
+ display: inline-block;
+ text-align: left;
+ width: auto;
+ font-size: 16px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ cursor: pointer;
+ padding: 5px 15px;
+ color: #fff; }
+ .b2b-header-tabs .header__item.b2b-headermenu {
+ padding: 0; }
+ .b2b-header-tabs .header__item.b2b-headermenu:last-child {
+ background: none; }
+ .b2b-header-tabs .header__item.b2b-headermenu a.menu__item {
+ color: #fff;
+ text-decoration: none;
+ display: inline-block;
+ padding: 5px 15px; }
+ .b2b-header-tabs .header__item.active {
+ background-color: #fff;
+ border-radius: 2px;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+ .b2b-header-tabs .header__item.active a.menu__item {
+ color: #0578ae; }
+ .b2b-header-tabs li:focus {
+ outline: 2px solid #0578ae; }
+ .b2b-header-tabs .header__item .header-secondary-wrapper, .b2b-header-tabs .header__item .header-tertiary-wrapper {
+ background-color: #fff;
+ position: absolute;
+ width: 100%;
+ left: 0;
+ top: 42px;
+ border-bottom: solid 1px #ccc;
+ -webkit-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ -moz-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ display: none;
+ z-index: 111; }
+ .b2b-header-tabs .header-secondary, .b2b-header-tabs .header-tertiary {
+ background-color: #fff;
+ width: 980px;
+ margin: 0 auto; }
+ .b2b-header-tabs .header__item.active .header-secondary-wrapper {
+ display: block; }
+ .b2b-header-tabs .header-secondary .header-subitem {
+ display: inline-block;
+ width: auto;
+ margin: 0 15px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active .header-tertiary-wrapper {
+ display: block; }
+ .b2b-header-tabs .header-secondary .header-subitem a.menu__item {
+ display: inline-block;
+ padding: 15px 0;
+ color: #333; }
+ .b2b-header-tabs .header-secondary .header-subitem a.menu__item:hover, .b2b-header-tabs .header-secondary .header-subitem a.menu__item:focus {
+ color: #0578ae; }
+
+/** Secondary Menu **/
+.b2b-labelhide {
+ position: absolute;
+ clip: rect(1px, 1px, 1px, 1px); }
+
+/** Tertiary Level Menu **/
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret {
+ position: absolute;
+ z-index: 111;
+ top: 25px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:after, .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:before {
+ content: '';
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ position: absolute;
+ -webkit-transition: left .2s ease-out;
+ -moz-transition: left .2s ease-out;
+ transition: left .2s ease-out; }
+ .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:after {
+ border-bottom: 8px solid #fff;
+ top: 10px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:before {
+ border-bottom: 8px solid #ccc;
+ top: 9px; }
+
+.b2b-header-tabs .header-secondary .header-subitem.active .header-tertiary {
+ border-top: solid 1px #ccc; }
+
+.b2b-header-tabs .header-tertiary:after {
+ content: '';
+ clear: both;
+ display: block; }
+
+.b2b-header-tabs .header-tertiary li {
+ display: inline-block;
+ padding: 0;
+ float: left; }
+ .b2b-header-tabs .header-tertiary li a {
+ color: #333;
+ display: block;
+ padding: 10px 15px; }
+ .b2b-header-tabs .header-tertiary li label {
+ text-align: left;
+ display: block;
+ font-size: 16px;
+ font-weight: bold;
+ color: #857B7B;
+ padding: 15px 0 0 15px; }
+
+.b2b-header-tabs .header__item.skip {
+ padding: 0;
+ display: inline-block;
+ cursor: default !important; }
+ .b2b-header-tabs .header__item.skip a {
+ color: transparent;
+ font-size: 12px;
+ line-height: 15px;
+ text-decoration: none; }
+ .b2b-header-tabs .header__item.skip a:focus {
+ color: #fff;
+ outline: 2px solid #0578ae; }
+
+.b2b-header-tabs .selectWrap {
+ min-width: 150px; }
+ .b2b-header-tabs .selectWrap button.awd-select {
+ height: 30px;
+ line-height: 31px;
+ font-size: 1rem;
+ display: inline-block; }
+ .b2b-header-tabs .selectWrap .awd-select-list {
+ background-color: #fff;
+ color: #333;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176); }
+
+@media (max-width: 768px) {
+ .b2b-header-tabs {
+ padding: 0 15px; }
+ .b2b-header-tabs .header__items, .b2b-header-tabs .header-secondary, .b2b-header-tabs .header-tertiary {
+ width: 100%; }
+ .b2b-header-tabs .header__item {
+ padding: 5px 0; }
+ .b2b-header-tabs .globe-text {
+ display: none; }
+ .b2b-header-tabs .header__item.b2b-headermenu a.menu__item {
+ padding: 5px 7px 9px 7px; }
+ .b2b-header-tabs .header__item .header-tertiary-wrapper {
+ top: 30px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret {
+ top: 14px; }
+ .b2b-header-tabs .header__item .header-secondary-wrapper {
+ top: 45px; }
+ .b2b-header-tabs .header__item.profile {
+ padding-left: 15px;
+ float: none; } }
+
+/************* Header - Start *************/
+.b2b-header-tabs {
+ background-color: #222;
+ width: 100%;
+ position: relative;
+ height: 45px; }
+
+.b2b-header-tabs .icon-primary-primary-att-globe {
+ color: #0568ae;
+ font-size: 34px;
+ bottom: 1px; }
+
+/*
+ *TODO: delete below .icon-primary-att-globel will not be used
+ *instead the one above, icon-primary-primary-att-globe not available here
+ */
+.b2b-header-tabs .icon-primary-att-globe {
+ color: #0568ae;
+ font-size: 34px; }
+
+.b2b-header-tabs .globe-text {
+ margin-left: 20px;
+ font-size: 2rem; }
+
+.b2b-header-tabs .header__items {
+ width: 980px;
+ margin: 0 auto;
+ display: block;
+ list-style: none;
+ border-spacing: 30px 0;
+ padding: 3px 0px 0px 0px; }
+
+.b2b-header-tabs .header__item {
+ display: inline-block;
+ text-align: left;
+ width: auto;
+ font-size: 14px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ cursor: pointer;
+ padding: 0 15px 4px 15px;
+ /*margin-top:-3px;*/
+ color: #fff; }
+
+.b2b-header-tabs .header__item.b2b-headermenu {
+ padding: 0; }
+
+.b2b-header-tabs .header__item.b2b-headermenu a.menu__item {
+ color: #fff;
+ text-decoration: none;
+ display: inline-block;
+ padding: 8px 15px 12px 15px;
+ font-size: 16px; }
+
+.b2b-header-tabs .header__item.active {
+ background-color: #fff;
+ border-radius: 2px;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+
+.b2b-header-tabs .header__item.active a.menu__item {
+ color: #0578ae; }
+
+.b2b-header-tabs li:focus {
+ outline: 2px solid #0578ae; }
+
+/** profile pop Over **/
+.b2b-header-tabs .header__item.profile {
+ position: relative;
+ float: right; }
+
+/** Secondary Menu **/
+.b2b-header-tabs .header__item .header-secondary-wrapper, .b2b-header-tabs .header__item .header-tertiary-wrapper {
+ background-color: #fff;
+ position: absolute;
+ width: 100%;
+ left: 0;
+ top: 42px;
+ border-bottom: solid 1px #ccc;
+ -webkit-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ -moz-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.16);
+ display: none;
+ z-index: 111; }
+
+.b2b-header-tabs .header-secondary, .b2b-header-tabs .header-tertiary {
+ background-color: #fff;
+ width: 980px;
+ margin: 0 auto; }
+
+.b2b-header-tabs .header__item.active .header-secondary-wrapper,
+.b2b-header-tabs .header-secondary .header-subitem.active .header-tertiary-wrapper {
+ display: block; }
+
+.b2b-header-tabs .header-secondary .header-subitem {
+ display: inline-block;
+ width: auto;
+ margin: 0 15px; }
+
+.b2b-header-tabs .header-secondary .header-subitem a.menu__item {
+ display: inline-block;
+ padding: 15px 0;
+ color: #333;
+ font-size: 14px; }
+
+.b2b-header-tabs .header-secondary .header-subitem a.menu__item:hover, .b2b-header-tabs .header-secondary .header-subitem a.menu__item:focus {
+ color: #0578ae; }
+
+.b2b-label-hide {
+ position: absolute;
+ clip: rect(1px, 1px, 1px, 1px); }
+
+/** Tertiary Level Menu **/
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:after,
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:before {
+ content: '';
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ position: absolute;
+ -webkit-transition: left .2s ease-out;
+ -moz-transition: left .2s ease-out;
+ transition: left .2s ease-out; }
+
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret {
+ position: absolute;
+ z-index: 111;
+ top: 25px; }
+
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:after {
+ border-bottom: 8px solid #fff;
+ top: 10px; }
+
+.b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret:before {
+ border-bottom: 8px solid #ccc;
+ top: 9px; }
+
+/** Tertiary Level Menu **/
+.b2b-header-tabs .header-secondary .header-subitem.active .header-tertiary {
+ border-top: solid 1px #ccc; }
+
+.b2b-header-tabs .header-tertiary:after {
+ content: '';
+ clear: both;
+ display: block; }
+
+.b2b-header-tabs .header-tertiary li {
+ display: inline-block;
+ padding: 0;
+ float: left; }
+
+.b2b-header-tabs .header-tertiary li a {
+ color: #333;
+ display: block;
+ padding: 7px 15px;
+ max-width: 228px; }
+
+.b2b-header-tabs .header-tertiary li label {
+ text-align: left;
+ display: block;
+ font-size: 14px !important;
+ font-weight: bold;
+ color: #857B7B;
+ padding: 15px 0 0 15px; }
+
+/** Quarternary Level Menu **/
+.b2b-header-tabs .header-quarternary {
+ width: 100%;
+ float: left; }
+
+.b2b-header-tabs .header-quarternary li {
+ padding-left: 15px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ display: none; }
+
+.b2b-header-tabs .header-quarternary li.active {
+ display: block; }
+
+.b2b-header-tabs .header-quarternary li a {
+ color: #666666;
+ font-size: 14px;
+ padding: 0px 10px 10px 10px; }
+
+/** Skip Navigation**/
+.b2b-header-tabs .header__item.skip {
+ padding: 0;
+ display: inline-block;
+ cursor: default !important; }
+
+.b2b-header-tabs .header__item.skip a {
+ color: transparent;
+ font-size: 12px;
+ line-height: 15px;
+ text-decoration: none; }
+
+.b2b-header-tabs .header__item.skip a:focus {
+ color: #fff;
+ outline: 2px solid #0578ae; }
+
+/** Dropdown css inside Header ****/
+.b2b-header-tabs .selectWrap {
+ min-width: 150px; }
+
+.b2b-header-tabs .selectWrap button.awd-select, .b2b-header-tabs .selectWrap input.awd-select {
+ height: 36px;
+ line-height: 8px;
+ font-size: 1rem;
+ display: inline-block; }
+
+.b2b-header-tabs .selectWrap .awd-select-list {
+ background-color: #fff;
+ color: #333;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176); }
+
+/*
+ * responsive header media queries
+ */
+@media screen and (max-width: 1100px) {
+ .b2b-header-tabs .globe-text {
+ display: none; }
+ .b2b-header-tabs .header__item.profile {
+ padding-left: 15px;
+ float: none; }
+ .b2b-header-tabs .header__items {
+ padding-top: 0px; } }
+
+@media screen and (max-width: 950px) {
+ .header__item.profile {
+ top: 20px; }
+ .b2b-header-tabs {
+ height: 90px; }
+ .selectWrap {
+ bottom: 15px; }
+ .b2b-header-tabs .header__items {
+ padding-top: 25px; }
+ .b2b-header-tabs .header__item .header-secondary-wrapper, .b2b-header-tabs .header__item .header-tertiary-wrapper {
+ top: 80px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active i.menuCaret {
+ top: 35px; }
+ .b2b-header-tabs .header__item.b2b-headermenu a.menu__item {
+ padding-bottom: 30px; }
+ .b2b-header-tabs .header-secondary .header-subitem.active .header-tertiary {
+ margin-top: -28px; } }
+
+/*************** Header - END ******************/
+.hp-container {
+ display: block;
+ max-width: 408px; }
+ .hp-container i:focus {
+ outline: thin dotted #666; }
+ .hp-container .icon-misc-pen {
+ cursor: pointer; }
+ .hp-container .icon-misc-trash {
+ cursor: pointer; }
+
+.hp-selected {
+ border-bottom: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ margin-bottom: 16px;
+ padding-bottom: 16px; }
+ .hp-selected .selected-days {
+ padding-bottom: 16px; }
+ .hp-selected .selected-days .day {
+ padding-top: 10px;
+ float: left; }
+
+.hp-checkbox {
+ padding-top: 20px;
+ margin: 16px auto 0 auto; }
+ .hp-checkbox label {
+ position: relative;
+ width: 20px;
+ margin-right: 34px; }
+ .hp-checkbox label span {
+ position: absolute;
+ top: -20px;
+ left: 0px;
+ margin-left: 0px; }
+
+.hp-dropdowns {
+ margin-top: 15px;
+ display: flex;
+ display: -webkit-flex;
+ display: -ms-flexbox; }
+
+.hp-buttons {
+ margin-top: 20px;
+ display: flex;
+ display: -webkit-flex;
+ display: -ms-flexbox; }
+
+.hp-dropdowns .radio-buttons {
+ margin-top: 30px; }
+ .hp-dropdowns .radio-buttons .radio {
+ margin-right: 15px; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02";
+ src: url("fonts/Omnes_ATTW02.eot");
+ src: url("fonts/Omnes_ATTW02.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02.woff") format("woff"), url("fonts/Omnes_ATTW02.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Medium";
+ src: url("fonts/Omnes_ATTW02Medium.eot");
+ src: url("fonts/Omnes_ATTW02Medium.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Medium.woff") format("woff"), url("fonts/Omnes_ATTW02Medium.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Italic";
+ src: url("fonts/Omnes_ATTW02Italic.eot");
+ src: url("fonts/Omnes_ATTW02Italic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Italic.woff") format("woff"), url("fonts/Omnes_ATTW02Italic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Light";
+ src: url("fonts/Omnes_ATTW02Light.eot");
+ src: url("fonts/Omnes_ATTW02Light.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Light.woff") format("woff"), url("fonts/Omnes_ATTW02Light.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Bold";
+ src: url("fonts/Omnes_ATTW02Bold.eot");
+ src: url("fonts/Omnes_ATTW02Bold.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02Bold.woff") format("woff"), url("fonts/Omnes_ATTW02Bold.woff2") format("woff2"), url("fonts/Omnes_ATTW02Bold.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Light-Italic";
+ src: url("fonts/Omnes_ATTW02LightItalic.eot");
+ src: url("fonts/Omnes_ATTW02LightItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02LightItalic.woff") format("woff"), url("fonts/Omnes_ATTW02LightItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02LightItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Medium-Italic";
+ src: url("fonts/Omnes_ATTW02MediumItalic.eot");
+ src: url("fonts/Omnes_ATTW02MediumItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02MediumItalic.woff") format("woff"), url("fonts/Omnes_ATTW02MediumItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02MediumItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+@font-face {
+ font-family: "Omnes-ECOMP-W02-Bold-Italic";
+ src: url("fonts/Omnes_ATTW02BoldItalic.eot");
+ src: url("fonts/Omnes_ATTW02BoldItalic.eot?#iefix") format("embedded-opentype"), url("fonts/Omnes_ATTW02BoldItalic.woff") format("woff"), url("fonts/Omnes_ATTW02BoldItalic.woff2") format("woff2"), url("fonts/Omnes_ATTW02BoldItalic.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal; }
+
+/* TODO: Build a reference page for these classes */
+.font-regular {
+ font-family: "Omnes-ECOMP-W02" !important; }
+
+.font-light {
+ font-family: "Omnes-ECOMP-W02-Light" !important; }
+
+.font-italic {
+ font-family: "Omnes-ECOMP-W02-Italic" !important; }
+
+.font-light-italic {
+ font-family: "Omnes-ECOMP-W02-Light-Italic" !important; }
+
+.font-medium {
+ font-family: "Omnes-ECOMP-W02-Medium" !important; }
+
+.font-medium-italic {
+ font-family: "Omnes-ECOMP-W02-Medium-Italic" !important; }
+
+.font-reset {
+ font-style: normal;
+ font-variant: normal;
+ font-weight: normal;
+ text-transform: none; }
+
+.b2b-nav-menu {
+ background-color: #efefef;
+ border: 1px solid #efefef;
+ width: 230px;
+ font-size: 1.4rem; }
+
+.b2b-subnav-container > ul {
+ padding: 0px; }
+
+.b2b-subnav-content {
+ margin: 0;
+ margin-bottom: 10px; }
+
+.b2b-subnav-content > li {
+ border-bottom: 1px solid #999999;
+ position: relative;
+ cursor: pointer; }
+
+.b2b-subnav-content > li > a {
+ text-decoration: none;
+ line-height: 18px;
+ display: block;
+ padding: 10px; }
+
+.b2b-subnav-content > li > a.expand {
+ color: #333; }
+
+.b2b-subnav-content > li ul {
+ overflow: hidden;
+ max-height: 0;
+ transition-duration: 0.5s;
+ transition-timing-function: cubic-bezier(0, 1, 0.5, 1); }
+
+.b2b-subnav-content > li ul.expand {
+ transition-duration: 0.7s;
+ transition-timing-function: ease-in-out;
+ max-height: 1000px;
+ overflow: hidden; }
+
+.b2b-subnav-content > li > a:focus, .b2b-subnav-content > li ul > li > a:focus {
+ outline: thin dotted #666; }
+
+.b2b-subnav-content > li ul > li > a {
+ line-height: 18px;
+ padding: 8px 0;
+ display: block;
+ outline-offset: -4px;
+ padding-left: 10px; }
+
+.b2b-icon-primary-plus-minus {
+ display: inline-block;
+ height: 20px;
+ margin-right: 10px;
+ padding: 0;
+ position: absolute;
+ right: 0px;
+ top: 10px;
+ vertical-align: middle;
+ width: 20px; }
+
+@media (min-width: 320px) and (max-width: 767px) {
+ .b2b-nav-menu {
+ background-color: #fff;
+ border: 1px solid white;
+ width: 100%; }
+ .b2b-subnav-content > li {
+ padding-left: 10px; }
+ .b2b-subnav-container > ul:first-child {
+ border-top: 1px solid #999; }
+ .b2b-icon-primary-plus-minus {
+ right: 10px; }
+ .b2b-subnav-content > li li > a.active {
+ color: #0574ac;
+ text-decoration: none;
+ font-family: "Omnes-ECOMP-W02", Arial; } }
+
+.b2b-list-box-item {
+ white-space: nowrap;
+ margin: 1px;
+ border: 1px solid transparent;
+ outline: none;
+ visibility: inherit;
+ display: inherit;
+ text-align: left;
+ overflow: hidden;
+ cursor: pointer;
+ padding: 5px 0 5px;
+ padding-left: 15px;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none; }
+ .b2b-list-box-item:focus {
+ border: 2px solid #5e8cb3; }
+
+.b2b-list-box-item--selected {
+ background-color: #cfdde9; }
+
+.btn.disabled[ddh-load-button] {
+ line-height: 46px;
+ padding: 0 19px 0 18px; }
+
+.btn.disabled[ddh-load-button] {
+ color: #666666; }
+
+.icon-primary-spinner-ddh.large {
+ height: 50px;
+ width: 50px; }
+
+.icon-primary-spinner-ddh.small {
+ height: 30px;
+ width: 30px; }
+
+.icon-primary-spinner-ddh {
+ -webkit-animation: 1s linear infinite spinner;
+ animation: 1s linear infinite spinner;
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNiAzNiIgaWQ9InN2Zy1zcGlubmVyIiB4PSIwcHgiIHk9IjBweCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgIDxwYXRoIGZpbGw9IiNGNUY1RjUiIGQ9Ik0xOCAzNkM4LjEgMzYgMCAyNy45IDAgMThTOC4xIDAgMTggMHMxOCA4LjEgMTggMTgtOC4xIDE4LTE4IDE4em0wLTMxLjVjLTcuNSAwLTEzLjUgNi0xMy41IDEzLjVTMTAuNiAzMS41IDE4IDMxLjVjNy41IDAgMTMuNS02LjEgMTMuNS0xMy41IDAtNy41LTYtMTMuNS0xMy41LTEzLjV6Ii8+CiAgIDxwYXRoIGZpbGw9IiMwNTY4QUUiIGlkPSJzcGlubmVyIiBkPSJNMzAuNyA1LjNsLTMuMSAzLjJjMi40IDIuNCAzLjkgNS44IDMuOSA5LjUgMCA3LjQtNi4xIDEzLjUtMTMuNSAxMy41UzQuNSAyNS40IDQuNSAxOCAxMC42IDQuNSAxOCA0LjVWMEM4LjEgMCAwIDguMSAwIDE4czguMSAxOCAxOCAxOCAxOC04LjEgMTgtMThjMC01LTItOS41LTUuMy0xMi43eiIgdHJhbnNmb3JtPSIiPiAgICAgIAogICA8L3BhdGg+Cjwvc3ZnPg==); }
+
+.btn-small .icon-primary-spinner-ddh {
+ height: 30px !important;
+ width: 30px !important; }
+
+.btn-small .icon-primary-spinner {
+ height: 30px;
+ width: 30px; }
+
+.load-backdrop {
+ position: absolute;
+ top: 50%;
+ left: 50%; }
+
+.body.styled-by-modal {
+ position: fixed; }
+
+.b2b-modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: -1; }
+
+.b2b-modal-backdrop.fade {
+ background-color: #000;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ transition: all 0.3s linear 0s; }
+
+.b2b-modal-backdrop.fade.in {
+ z-index: 1040;
+ opacity: 0.7;
+ filter: alpha(opacity=70);
+ background-color: #000;
+ transition: opacity 0.3s linear 0s; }
+
+.modalwrapper {
+ height: 100%;
+ width: 100%;
+ left: 0;
+ overflow-y: hidden;
+ position: absolute;
+ right: 0;
+ padding: 20px;
+ top: 0;
+ z-index: -1; }
+
+.modalwrapper.active {
+ z-index: 1050;
+ overflow-y: auto; }
+
+.modal {
+ background-clip: padding-box;
+ background-color: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ box-shadow: 0 3px 5px 1px rgba(0, 0, 0, 0.4);
+ margin: 0 auto;
+ /*margin-bottom:10%;*/
+ outline: medium none;
+ /*position: absolute;*/
+ height: 0;
+ min-height: 150px;
+ overflow: hidden;
+ /*top: 10%;*/
+ width: 100%;
+ z-index: -1; }
+
+.modalwrapper.modal-docked .modal {
+ max-height: 80%;
+ height: 80%;
+ overflow: hidden;
+ top: 0; }
+
+.modal.fade.in {
+ position: relative;
+ height: auto;
+ overflow: auto;
+ top: 10%;
+ z-index: 1060;
+ transition: opacity .5s linear 0s; }
+
+.modal.fade.in.modal-landscape {
+ overflow-y: auto; }
+
+.modal.fade {
+ transition: opacity .5s linear 0s; }
+
+.fade.in {
+ opacity: 1; }
+
+.fade {
+ opacity: 0; }
+
+.b2b-modal-header {
+ align-items: center;
+ border-radius: 8px 8px 0 0;
+ display: flex;
+ min-height: 60px;
+ overflow: hidden;
+ padding: 30px 46px 30px 30px;
+ position: relative; }
+
+.b2b-modal-header > h2 {
+ line-height: 1;
+ margin: 0;
+ padding: 0; }
+
+.modal-header-portrait {
+ -webkit-overflow-scrolling: auto; }
+
+.modal-header-landscape {
+ -webkit-overflow-scrolling: auto; }
+
+.b2b-modal-body {
+ -webkit-overflow-scrolling: touch;
+ padding: 0 30px 20px;
+ position: relative;
+ width: auto; }
+
+.b2b-modal-body:focus {
+ outline: 1px dotted #333333; }
+
+.modal-form {
+ margin-bottom: 0; }
+
+.b2b-modal-footer {
+ background-color: #fff;
+ width: 100%;
+ padding: 0 30px;
+ border-radius: 0;
+ position: absolute;
+ bottom: 0; }
+
+:not(.modal-docked) .b2b-modal-footer {
+ position: relative; }
+
+.modal-docked .b2b-modal-footer {
+ border-top: 1px solid #d2d2d2; }
+
+.modal-landscape .b2b-modal-footer {
+ position: relative; }
+
+.b2b-modal-footer .cta-button-group {
+ display: flex;
+ justify-content: flex-end;
+ padding: 20px 0 5px;
+ width: 100%; }
+
+.b2b-modal-footer .cta-button-group .btn {
+ margin-left: auto;
+ margin-right: auto;
+ float: right;
+ margin-left: 10px; }
+
+.b2b-modal-footer .cta-button-group .btn + .btn {
+ margin-right: 0 !important; }
+
+[class*="modal-"] {
+ width: 100%; }
+
+.modal-small {
+ max-width: 420px; }
+
+.modal-medium {
+ max-width: 620px; }
+
+.modal-large {
+ max-width: 720px; }
+
+.modal-xlarge {
+ max-width: 860px; }
+
+.modal-jumbo {
+ max-width: 1000px; }
+
+.modalwrapper.modal-docked {
+ height: 100%;
+ display: flex;
+ align-items: center; }
+
+.modalwrapper.modal-docked .b2b-modal-body {
+ height: 80%;
+ overflow-y: scroll;
+ padding-bottom: 60px; }
+
+.modalwrapper.modal-docked .modal {
+ max-height: 80%;
+ height: 80%;
+ overflow: hidden;
+ top: 0; }
+
+.modalwrapper.modal-docked .b2b-modal-body > *:last-child {
+ margin-bottom: 60px; }
+
+@media (max-width: 767px) {
+ .modalwrapper {
+ padding: 15px;
+ overflow-x: hidden; }
+ .modal.fade.in {
+ top: 0;
+ right: 0;
+ left: 0;
+ margin-bottom: 15px;
+ border: none; }
+ .b2b-modal-header {
+ padding: 20px 46px 20px 15px; }
+ .b2b-modal-body {
+ width: 100%;
+ padding: 0 15px 15px; }
+ .modalwrapper.modal-docked {
+ position: absolute;
+ height: 100%;
+ padding: 0; }
+ .modalwrapper.modal-docked .modal.fade.in {
+ margin-bottom: 0;
+ width: 100% !important;
+ max-height: 100%;
+ height: 100%;
+ border-radius: 0; }
+ .modalwrapper.modal-docked .b2b-modal-body {
+ overflow-y: scroll;
+ height: 100%; }
+ .modalwrapper.modal-docked.modal-landscape {
+ overflow-y: hidden;
+ position: fixed; }
+ .modalwrapper.modal-docked.modal-landscape .modal {
+ overflow-y: scroll;
+ max-width: 100%; }
+ .modalwrapper.modal-docked.modal-landscape .b2b-modal-body {
+ height: auto;
+ overflow-y: hidden; }
+ .b2b-modal-footer {
+ padding: 0 15px; }
+ .b2b-modal-footer .cta-button-group {
+ display: block;
+ padding: 15px 0; }
+ .b2b-modal-footer .cta-button-group .btn {
+ float: none; }
+ .b2b-modal-footer .cta-button-group .btn + .btn {
+ margin-bottom: 0; }
+ .b2b-modal-footer .cta-button-group a.visible-phone {
+ align-items: center;
+ display: flex !important;
+ height: 42px;
+ justify-content: center; } }
+
+.b2b-modal-footer > .cta-button-group {
+ line-height: 40px; }
+
+.ajaxed,
+.modal.fade.in .b2b-modal-header,
+.modal.fade.in .b2b-modal-body,
+.modal.fade.in .b2b-modal-footer {
+ animation-duration: 0.01s;
+ -o-animation-duration: 0.01s;
+ -ms-animation-duration: 0.01s;
+ -moz-animation-duration: 0.01s;
+ -webkit-animation-duration: 0.01s;
+ animation-name: DOMinsertion;
+ -o-animation-name: DOMinsertion;
+ -ms-animation-name: DOMinsertion;
+ -moz-animation-name: DOMinsertion;
+ -webkit-animation-name: DOMinsertion; }
+
+.monthselector thead tr th {
+ min-width: 46px; }
+
+.monthselector thead tr:after {
+ content: "";
+ position: absolute;
+ left: 20px;
+ top: 52px;
+ height: 1px;
+ width: 85%;
+ border-bottom: 1px solid #ccc; }
+
+.monthselector tbody tr:last-child {
+ height: 50px; }
+
+.monthselector td.day {
+ margin: 1px 4px !important;
+ width: 64px !important; }
+
+.monthselector .datepicker-switch {
+ width: 195px !important; }
+
+.monthselector .show-date {
+ width: 30px !important; }
+
+.monthselector button.faux-input {
+ width: 100%; }
+ .monthselector button.faux-input:focus {
+ border: 1px solid #0574ac; }
+ .monthselector button.faux-input:disabled {
+ cursor: not-allowed; }
+
+.monthselector .cta-button-group {
+ padding: 0 20px; }
+ .monthselector .cta-button-group a {
+ margin-right: 20px; }
+
+.monthselector .day.active .show-date:after, .monthselector .day:focus .show-date:after, .monthselector .due-date.disabled .show-date:after {
+ height: 30px;
+ left: 9px !important;
+ top: 0;
+ width: 42px !important; }
+
+.monthselector .disabled.day:focus .show-date:after {
+ border: none; }
+
+.monthselector .icon-primary-calendar {
+ display: block; }
+
+.b2b-ml-nav {
+ padding: 0 10px 0 10px;
+ width: 320px; }
+
+.b2b-ml-nav ul {
+ list-style: none;
+ list-style-type: none; }
+
+.b2b-ml-nav a {
+ display: block;
+ padding: 0 0 5px 30px;
+ line-height: 22px;
+ margin-left: -10px;
+ color: #333;
+ font-size: 1.4rem; }
+
+.b2b-ml-nav a:focus {
+ outline-offset: 1px; }
+
+.b2b-ml-nav li:focus {
+ outline: none; }
+
+.b2b-ml-nav li:focus > a {
+ outline: thin dotted #666;
+ outline-offset: 1px; }
+
+.b2b-ml-nav ul li {
+ border-left: 1px solid #ccc; }
+
+.b2b-ml-nav ul ul {
+ padding: 0 0 0 20px; }
+
+.b2b-ml-nav ul > li {
+ position: relative;
+ line-height: 18px; }
+
+.b2b-ml-nav a > span {
+ background-color: #FFF;
+ display: inline;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ left: -11px;
+ top: 0; }
+
+.b2b-ml-nav a > span > i {
+ font-size: 20px; }
+
+.b2b-ml-nav a:only-child {
+ color: #0574ac; }
+
+.b2b-ml-nav a:only-child > span {
+ left: -6px;
+ border-radius: 50%;
+ line-height: 7px;
+ top: 5px; }
+
+.b2b-ml-nav a:only-child > span > i {
+ background-color: inherit;
+ background: #fff;
+ font-size: 10px; }
+
+.b2b-ml-nav ul li:first-child > a:only-child > span {
+ left: -6px;
+ border-radius: 50%;
+ line-height: 12px;
+ top: 0px; }
+
+.b2b-ml-nav li a + ul {
+ display: none; }
+
+.b2b-ml-nav li a.active + ul {
+ display: block; }
+
+/*to overide ng-doc inline property for library demo - TODO: Move to docs.css*/
+.b2b-ml-nav a [class^="icon-primary-"], a [class*=" icon-primary-"], a [class^="icon-primary-"]:before, a [class*=" icon-primary-"]:before {
+ display: inline-block; }
+
+.b2b-alerts-messages {
+ background-color: #fff;
+ border-radius: 8px;
+ height: auto; }
+ .b2b-alerts-messages h3 {
+ color: #333 !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ margin-bottom: 0 !important; }
+ .b2b-alerts-messages h4 {
+ color: #333 !important;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ margin-bottom: 0 !important; }
+ .b2b-alerts-messages .alert-info {
+ background-color: #0574ac;
+ border: 0; }
+ .b2b-alerts-messages .alert-error {
+ background-color: #cf2a2a;
+ border: 0; }
+ .b2b-alerts-messages .alert-success {
+ background-color: #1b7e28;
+ border: 0; }
+ .b2b-alerts-messages div:nth-child(2) {
+ padding: 0 0 15px 10px;
+ vertical-align: baseline; }
+ .b2b-alerts-messages .close:before {
+ color: #767676; }
+ .b2b-alerts-messages p {
+ font-size: 14px;
+ color: #333;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+ .b2b-alerts-messages p a {
+ color: #333; }
+ .b2b-alerts-messages .btn-small {
+ margin-bottom: 0px; }
+
+.b2b-alerts-success {
+ border: 1px solid #1b7e28; }
+
+.b2b-alerts-error {
+ border: 1px solid #cf2a2a; }
+
+.b2b-alerts-info {
+ border: 1px solid #0574ac; }
+
+/* TODO: Rearange this and move to patches if needed */
+.b2b-breadcrumb-css-override > li {
+ margin-right: 24px; }
+
+.b2b-breadcrumb-css-override li > * {
+ float: left !important; }
+
+.b2b-css-override ul.nav-tabs {
+ margin-bottom: 0; }
+
+.b2b-css-override div.tab-content {
+ margin-top: 0;
+ border-top: none; }
+
+.b2b-css-override .tab-content .prettyprint, .b2b-css-override .usage .prettyprint {
+ max-height: 500px;
+ overflow-y: auto; }
+
+.b2b-top-nav-buttons-css-override {
+ margin-bottom: 0;
+ margin-top: 2px; }
+
+.b2b-auto-width {
+ width: auto !important; }
+
+.b2b-toggle-header-active {
+ color: #0568ae; }
+
+.b2b-toggle-header-inactive {
+ color: #333333; }
+
+.b2b-toggle-header-icon {
+ cursor: pointer; }
+
+.tab-content > .tab-pane {
+ display: none; }
+
+.tab-content > .active {
+ display: block; }
+
+.icon-primary-circle:before {
+ background-image: url("data:image/svg+xml,%3Csvg%20baseProfile%3D%22tiny%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%3E%3Ccircle%20fill%3D%22transparent%22%20stroke%3D%22%23666%22%20stroke-miterlimit%3D%2210%22%20cx%3D%2218%22%20cy%3D%2218%22%20r%3D%2216%22%2F%3E%3C%2Fsvg%3E");
+ content: "";
+ position: absolute;
+ top: 0;
+ z-index: 1; }
+
+.ds2-no-colors .icon-primary-circle:before {
+ background-image: none;
+ content: "\e902"; }
+
+i:focus {
+ outline: thin dotted #666; }
+
+.p-col-md-12 {
+ width: 50%; }
+
+.pager__item {
+ border-radius: 0;
+ cursor: default;
+ display: inline-block;
+ margin: 5px;
+ width: 22px;
+ height: 23px;
+ /*transition: all 0.3s ease-out 0s;*/
+ vertical-align: baseline; }
+
+.pager {
+ padding-top: 10px;
+ padding-bottom: 20px;
+ text-align: center;
+ margin: 0 auto; }
+
+.pager__item--input {
+ color: #067ab4;
+ max-height: 32px;
+ max-width: 40px;
+ padding-left: 0;
+ padding-right: 0;
+ text-align: center;
+ margin-left: 10px; }
+
+.row.section-row {
+ margin-bottom: 20px; }
+
+.pager__item--active {
+ border-bottom: 2px solid #0574ac;
+ border-radius: 0;
+ color: #333333; }
+
+.pager a.pager__item--active:hover {
+ cursor: default; }
+
+.pager a:hover, .pager a:focus {
+ text-decoration: none;
+ color: #333333;
+ cursor: pointer; }
+
+.pager a.disabled:hover, .pager a.disabled:focus {
+ cursor: not-allowed; }
+
+.row.section-row.b2b-page {
+ display: block; }
+
+a.pager__item--next:focus, a.pager__item--prev:focus {
+ text-decoration: none;
+ border: 0; }
+
+.pager__item--next, .pager__item--prev {
+ margin: 5px;
+ padding: 1.5px 6px 1.5px 6px; }
+
+.pager .disabled i {
+ pointer-events: none;
+ cursor: default;
+ color: #c4c4c4; }
+
+.fieldLabel {
+ color: #666666; }
+
+.fieldLabel input {
+ color: #666666; }
+
+.pSelect {
+ float: right;
+ width: 150px; }
+
+.numericResult {
+ margin-bottom: 20px;
+ font-size: 1.6rem;
+ margin-top: 20px;
+ display: inline-block;
+ font-family: "Omnes-ECOMP-w02-medium", Arial; }
+
+.mobile-view > .pager__item {
+ margin: 5px 10px;
+ width: 24px;
+ height: 34px;
+ vertical-align: middle;
+ line-height: 34px; }
+
+.fade1, .fadel {
+ opacity: 0.4; }
+
+.fade2, .fadesl {
+ opacity: 0.6; }
+
+h4#pagination-truncated {
+ margin-top: 50px; }
+
+h4#pagination-large-count {
+ margin-top: 50px; }
+
+.p-col-md-12 input {
+ margin-left: 20px; }
+
+.pager a .icon-primary-right:before {
+ display: inline-block; }
+
+.pager a .icon-primary-left:before {
+ display: inline-block; }
+
+.page-heading {
+ background: white none repeat scroll 0 0;
+ margin-bottom: -12px;
+ padding-left: 10px;
+ padding-right: 10px;
+ position: relative; }
+
+.numericResult:focus {
+ outline: 1px dotted #0574ac; }
+
+.page-heading-group {
+ color: #ef6f00;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.pager > div > span.fieldLabel {
+ margin-left: 18px; }
+
+.pager .fieldLabel .btn-arrow {
+ top: 0;
+ left: 10px; }
+
+.b2b-p-col-md-12 {
+ width: 50%; }
+ .b2b-p-col-md-12 input {
+ margin-left: 20px; }
+
+.b2b-pager__item {
+ border-radius: 0;
+ cursor: default;
+ display: inline-block;
+ margin: 5px;
+ min-width: 23px;
+ height: 23px;
+ vertical-align: baseline; }
+
+.b2b-pager__item--noclick {
+ pointer-events: none !important;
+ cursor: default !important; }
+
+.b2b-pager {
+ padding-top: 10px;
+ padding-bottom: 20px;
+ text-align: center;
+ margin: 0 auto; }
+ .b2b-pager a:hover {
+ text-decoration: none;
+ color: #333333;
+ cursor: pointer; }
+ .b2b-pager a:focus {
+ text-decoration: none;
+ color: #333333;
+ cursor: pointer; }
+ .b2b-pager a .icon-primary-right:before {
+ display: inline-block; }
+ .b2b-pager a .icon-primary-left:before {
+ display: inline-block; }
+ .b2b-pager .disabled i {
+ pointer-events: none;
+ cursor: default;
+ color: #c4c4c4; }
+
+.b2b-pager__item--input {
+ color: #067ab4;
+ max-height: 32px;
+ max-width: 60px;
+ padding-left: 0;
+ padding-right: 0;
+ text-align: center;
+ margin-left: 10px; }
+
+.row.section-row {
+ margin-bottom: 20px; }
+
+.b2b-pager__item--active {
+ border-bottom: 2px solid #0574ac;
+ border-radius: 0;
+ color: #333333; }
+
+.row.section-row.b2b-page {
+ display: block; }
+
+a.b2b-pager__item--next:focus {
+ text-decoration: none;
+ border: 0; }
+
+a.b2b-pager__item--next-disabled {
+ outline: 0; }
+
+a.b2b-pager__item--next-disabled > [class^="icon-primary-"] {
+ color: #cccccc;
+ cursor: not-allowed;
+ outline: 0; }
+
+a.b2b-pager__item--prev:focus {
+ text-decoration: none;
+ border: 0; }
+
+a.b2b-pager__item--prev-disabled {
+ outline: 0; }
+
+a.b2b-pager__item--prev-disabled > [class^="icon-primary-"] {
+ color: #cccccc;
+ cursor: not-allowed; }
+
+.b2b-pager__item--next {
+ margin: 5px;
+ padding: 1.5px 6px 1.5px 6px; }
+
+.b2b-pager__item--prev {
+ margin: 5px;
+ padding: 1.5px 6px 1.5px 6px; }
+
+.fieldLabel {
+ color: #666666; }
+ .fieldLabel input {
+ color: #666666; }
+ .fieldLabel .btn-arrow {
+ top: 0;
+ left: 10px; }
+
+.b2b-pSelect {
+ float: right;
+ width: 150px; }
+
+.b2b-numericResult {
+ margin-bottom: 20px;
+ font-size: 1.6rem;
+ margin-top: 20px; }
+
+.b2b-mobile-view > .b2b-pager__item {
+ margin: 5px 10px;
+ min-width: 23px;
+ height: 34px;
+ vertical-align: middle;
+ line-height: 34px; }
+
+.b2b-fade1 {
+ opacity: 0.4; }
+
+.b2b-fade2 {
+ opacity: 0.6; }
+
+.b2b-fadesl {
+ opacity: 0.6; }
+
+h4#b2b-pagination-truncated {
+ margin-top: 50px; }
+
+h4#b2b-pagination-large-count {
+ margin-top: 50px; }
+
+.b2b-page-heading {
+ background: white none repeat scroll 0 0;
+ margin-bottom: -12px;
+ padding-left: 10px;
+ padding-right: 10px;
+ position: relative; }
+
+.b2b-numericResult:focus {
+ outline: 1px dotted #0574ac; }
+
+.b2b-page-heading-group {
+ color: #ef6f00;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.b2b-pager > div > span.fieldLabel {
+ margin-left: 18px; }
+
+input.b2b-phone-mask-input {
+ padding-right: 15px; }
+ input.b2b-phone-mask-input:hover, input.b2b-phone-mask-input:focus {
+ padding-right: 15px; }
+
+/************************** Start - Should be removed after the styling in global is fixed *******************/
+input::-ms-clear {
+ display: none; }
+
+/************************** End - Should be removed after the styling in global is fixed *******************/
+@media (max-width: 767px) {
+ input::-ms-clear {
+ display: block; } }
+
+.pivot-link-group {
+ background-color: #5a5a5a;
+ border-top: 1px solid #959595; }
+
+.pivot-links > li {
+ border-bottom: 1px solid #959595; }
+
+.pivot-links > li > a {
+ color: #fff;
+ display: block;
+ padding: 12px 15px 10px;
+ line-height: normal; }
+
+.b2b-profile-block-container {
+ min-height: 200px;
+ height: auto;
+ background-color: #fff;
+ border-radius: 8px;
+ border: 1px solid #ccc;
+ box-shadow: 0px 1px 1px 1px #ccc;
+ display: inline-table;
+ margin: 15px 15px; }
+
+.b2b-profile-block-details p, .b2b-profile-block-details div {
+ padding: 2px 7px;
+ font-size: 1.4rem; }
+
+.b2b-profile-block-details .radio-label, .b2b-profile-block-details a {
+ font-size: 1.4rem; }
+
+.b2b-profile-block-details p label, .b2b-profile-block-details p span {
+ padding-left: 10px; }
+
+.b2b-profile-block-footer {
+ margin-bottom: 12px;
+ margin-top: 5px;
+ height: 35px; }
+
+.b2b-profile-block-details p {
+ word-wrap: break-word;
+ height: 61px; }
+ .b2b-profile-block-details p:first-child {
+ margin-top: 10px; }
+ .b2b-profile-block-details p:after {
+ content: ' ';
+ display: block;
+ border: 0.2px solid #ccc;
+ margin-top: 12px; }
+
+.b2b-profile-block-details .radio {
+ margin-left: 15px;
+ height: 30px; }
+
+.b2b-approval-icon {
+ color: #1b7e28;
+ float: right;
+ position: relative;
+ left: 10px; }
+ .b2b-approval-icon i {
+ color: #1b7e28;
+ float: right; }
+
+.b2b-profile-link {
+ float: right;
+ position: relative;
+ left: -4px; }
+
+a.link-profile {
+ position: relative;
+ left: -5px;
+ float: right;
+ margin-bottom: 16px; }
+
+.b2b-profile-block-radio {
+ position: relative;
+ top: -5px; }
+
+.b2b-profile-card {
+ min-width: 229px;
+ min-height: 354px;
+ margin: 10px;
+ border: solid 1px #CCC;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ display: inline-block;
+ vertical-align: top; }
+ .b2b-profile-card .top-block {
+ padding: 15px 20px;
+ background-color: #e4e4e4;
+ max-height: 153px; }
+ .b2b-profile-card .bottom-block {
+ padding: 15px 20px 15px 20px;
+ background-color: #fff; }
+ .b2b-profile-card .profile-image {
+ background: #e4e4e4;
+ margin-bottom: 15px;
+ text-align: center; }
+ .b2b-profile-card .profile-image .default-img {
+ display: inline-block;
+ width: 60px;
+ height: 60px;
+ margin-bottom: 10px;
+ border: 6px solid #fff;
+ border-radius: 99em;
+ -webkit-border-radius: 99em;
+ -moz-border-radius: 99em;
+ /* background-color: #eee; */ }
+
+.profile-image img {
+ display: inline-block;
+ width: 60px;
+ height: 60px;
+ margin-bottom: 10px;
+ border: 6px solid #fff;
+ border-radius: 99em;
+ -webkit-border-radius: 99em;
+ -moz-border-radius: 99em;
+ /* background-color: #eee; */ }
+
+.b2b-profile-card .profile-image .default-img {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #333;
+ background-color: #fff;
+ font-size: 32px;
+ line-height: 22px;
+ padding: 5px;
+ padding-top: 13px;
+ width: 60px;
+ height: 60px;
+ text-transform: uppercase; }
+
+.b2b-profile-card .profile-image .name {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 16px;
+ color: #333;
+ text-align: center;
+ margin-bottom: 5px;
+ margin-top: 5px;
+ overflow: hidden;
+ word-break: break-word;
+ white-space: normal;
+ text-transform: capitalize; }
+
+.b2b-profile-card .profile-image .status-icon {
+ border-radius: 10px;
+ border: 1px solid #fff;
+ margin: 0 3px 0 0;
+ width: 10px;
+ height: 10px;
+ display: inline-block;
+ vertical-align: middle; }
+
+.b2b-profile-card .profile-image .status {
+ font-size: 12px;
+ line-height: 15px;
+ text-align: center;
+ margin: 0 15px 0 0;
+ color: #444; }
+
+.b2b-profile-card .status .circle {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ margin: 30px 6px 0px 20px;
+ text-align: center;
+ background-color: #444; }
+
+.b2b-profile-card .profile-image .status-green {
+ background-color: #0c0; }
+
+.b2b-profile-card .profile-image .status-red {
+ background-color: red; }
+
+.b2b-profile-card .profile-image .status-blue {
+ background-color: #00f; }
+
+.b2b-profile-card .profile-image .status-yellow {
+ background-color: #ff0; }
+
+.b2b-profile-card .profile-image .status .status-badge {
+ margin-left: 5px;
+ border: dotted 1px #444;
+ background-color: transparent;
+ font-weight: 400;
+ color: #444;
+ height: 17px;
+ padding: 0 5px;
+ font-size: 11px;
+ padding-left: 5px;
+ padding-right: 5px; }
+
+.b2b-profile-card .profile-details {
+ background: #fff; }
+ .b2b-profile-card .profile-details label {
+ display: block;
+ cursor: text;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-weight: bolder;
+ font-size: 14px;
+ color: #333;
+ padding: 0;
+ margin: 0; }
+ .b2b-profile-card .profile-details div {
+ margin: 0;
+ font-size: 14px;
+ color: #333;
+ padding-bottom: 6.5px; }
+
+.b2b-profile-card .b2b-add-user {
+ background: white;
+ border-style: dotted;
+ font-size: 16px;
+ color: #333;
+ position: relative; }
+ .b2b-profile-card .b2b-add-user i {
+ font-size: 30px;
+ padding-bottom: 15px; }
+
+.b2b-profile-card .atcenter {
+ cursor: pointer;
+ margin-top: 60%;
+ vertical-align: middle;
+ text-align: center; }
+
+.b2b-profile-card .tooltip {
+ cursor: pointer; }
+ .b2b-profile-card .tooltip .helpertext {
+ position: relative;
+ color: white; }
+
+.b2b-profile-card .tooltip-wrapper {
+ position: relative; }
+
+/* Overrides for tooltip absolute positioning */
+@media (min-width: 1025px) {
+ .b2b-profile-card .tooltip-size-control {
+ width: 100% !important; } }
+
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 0 0; }
+ to {
+ background-position: 80px 0; } }
+
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 0 0; }
+ to {
+ background-position: 80px 0; } }
+
+.progress {
+ background-color: #e4e4e4;
+ border-radius: 4px;
+ height: 14px;
+ margin-bottom: 20px;
+ min-width: 250px;
+ overflow: hidden;
+ padding: 0;
+ position: relative; }
+
+a .progress {
+ margin-bottom: 0; }
+
+.progress .bar {
+ background-color: #666;
+ border-radius: 4px;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ height: 100%;
+ width: 0; }
+
+.progress-arrow {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-justify-content: flex-end;
+ -ms-flex-pack: end;
+ justify-content: flex-end; }
+
+.progress-link + .usage-bar {
+ margin-top: 5px; }
+
+.progress-success .bar, .progress .bar-success {
+ background-color: #1b7e28; }
+
+.progress-warning .bar, .progress .bar-warning {
+ background-color: #ef6f00; }
+
+.progress-danger .bar, .progress .bar-danger {
+ background-color: #cf2a2a; }
+
+.progress.increment {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex; }
+
+.progress.increment .bar:first-child:not(:last-child) {
+ border-right: none;
+ border-radius: 4px 0 0 4px; }
+
+.progress.increment .bar:last-child:not(:first-child) {
+ border-left: none;
+ border-radius: 0 4px 4px 0; }
+
+.progress.increment .bar + .bar:not(:last-child) {
+ border-left: none;
+ border-right: none;
+ border-radius: 0; }
+
+.progress.increment .bar:not(:first-child) {
+ border-left: 1px solid white !important; }
+
+.usage-bar {
+ display: table;
+ float: none;
+ width: 100%;
+ margin-bottom: 1px; }
+
+.usage-bar > .usage-text {
+ display: table-cell;
+ width: 1%; }
+
+.progress + .usage-bar {
+ margin-top: -15px; }
+
+.usage-bar .usage-text {
+ font-size: 1.4rem; }
+
+.usage-bar .usage-text:first-child {
+ white-space: nowrap; }
+
+.usage-bar .usage-text.text-right {
+ vertical-align: top;
+ font-size: 1.4rem;
+ width: auto !important; }
+
+.usage-bar .usage-text.text-right:before {
+ content: "";
+ display: table;
+ height: .1em; }
+
+.usage-bar.billing-cycle .usage-text {
+ font-size: 1.4rem; }
+
+.usage-bar.billing-cycle .usage-text.text-right {
+ vertical-align: bottom; }
+
+.progress.autocolor [data-percentage="1"], .progress.autocolor [data-percentage="2"], .progress.autocolor [data-percentage="3"], .progress.autocolor [data-percentage="4"], .progress.autocolor [data-percentage="5"], .progress.autocolor [data-percentage="6"], .progress.autocolor [data-percentage="7"], .progress.autocolor [data-percentage="8"], .progress.autocolor [data-percentage="9"], .progress.autocolor [data-percentage="10"] .progress.autocolor [data-percentage^="2"], .progress.autocolor [data-percentage^="3"], .progress.autocolor [data-percentage^="4"], .progress.autocolor [data-percentage^="5"], .progress.autocolor [data-percentage="60"], .progress.autocolor [data-percentage="61"], .progress.autocolor [data-percentage="62"], .progress.autocolor [data-percentage="63"], .progress.autocolor [data-percentage="64"] {
+ background-color: #1b7e28; }
+
+.progress.autocolor [data-percentage="65"], .progress.autocolor [data-percentage="66"], .progress.autocolor [data-percentage="67"], .progress.autocolor [data-percentage="68"], .progress.autocolor [data-percentage="69"], .progress.autocolor [data-percentage^="7"], .progress.autocolor [data-percentage^="8"] {
+ background-color: #ef6f00; }
+
+.progress.autocolor [data-percentage^="9"], .progress.autocolor [data-percentage="100"] {
+ background-color: #cf2a2a; }
+
+.b2b-seek-bar-container {
+ position: relative; }
+ .b2b-seek-bar-container div {
+ position: absolute; }
+ .b2b-seek-bar-container .b2b-seek-bar-track-container {
+ width: 100%; }
+ .b2b-seek-bar-container .b2b-seek-bar-track {
+ width: 100%;
+ height: 6px;
+ background-color: #cccccc;
+ border-radius: 10px; }
+ .b2b-seek-bar-container .b2b-seek-bar-track-fill {
+ width: 100%;
+ height: 6px;
+ background-color: #cccccc;
+ border-radius: 10px;
+ width: 0;
+ background-color: #157BB2;
+ transition: width 0s linear; }
+
+.seek-bar-container .seek-bar-knob-container {
+ transition: left 0s linear; }
+
+.b2b-seek-bar-container .b2b-seek-bar-knob {
+ width: 14px;
+ height: 14px;
+ border-radius: 10px;
+ top: -4px;
+ left: -8px;
+ border: 1px solid #cccccc;
+ background: white;
+ cursor: pointer; }
+
+.b2b-seek-bar-container .b2b-seek-bar-knob:focus {
+ outline: thin dotted #666; }
+
+.b2b-seek-bar-container.vertical {
+ width: 100%;
+ height: 100%;
+ margin: 0 auto;
+ position: relative;
+ border-radius: 10px; }
+ .b2b-seek-bar-container.vertical .b2b-seek-bar-track-container {
+ position: relative;
+ height: 100%; }
+ .b2b-seek-bar-container.vertical .b2b-seek-bar-track {
+ position: absolute;
+ height: 100%; }
+ .b2b-seek-bar-container.vertical .b2b-seek-bar-track-fill {
+ position: absolute;
+ bottom: 0;
+ height: 0;
+ width: 100%; }
+ .b2b-seek-bar-container.vertical .b2b-seek-bar-knob-container {
+ transition: bottom .01s linear;
+ position: relative;
+ bottom: 0; }
+ .b2b-seek-bar-container.vertical .b2b-seek-bar-knob {
+ position: absolute;
+ border-radius: 10px;
+ top: -7px;
+ left: -4px; }
+
+.form-search .search-query {
+ width: 100% !important; }
+
+.form-search .well {
+ margin-top: 0; }
+
+.form-search > ul.nav > li.section {
+ min-height: 20px !important; }
+
+input.b2b-search-input-field {
+ margin-bottom: 0px; }
+
+.search-suggestion-list {
+ background-color: #FFFFFF;
+ border: 1px solid #ccc;
+ border-radius: 0 0 6px 6px;
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.15);
+ margin-top: -5px;
+ max-height: 400px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 15px 0;
+ position: absolute;
+ width: 100%;
+ z-index: 1000; }
+ .search-suggestion-list > li.active {
+ background-color: #cccccc; }
+ .search-suggestion-list:empty {
+ display: none; }
+
+.b2b-search-hightlight {
+ font-weight: bold; }
+
+input[type="text"]::-moz-placeholder {
+ color: #767676;
+ font-family: "Omnes-ECOMP-W02-Italic", Arial; }
+
+input[type="text"]:focus {
+ z-index: 1000; }
+
+input[type="text"] + .reset-field {
+ background-color: #FFFFFF;
+ height: 90%;
+ top: 5%; }
+
+.btn-search:focus {
+ outline: 1px dotted #0574ac; }
+
+.field-group input:not([type="button"])[disabled] ~ .btn-search {
+ background-color: #eee; }
+
+.btn-search[class*="btn"] {
+ background-color: #FFFFFF;
+ background-size: 20px 20px;
+ border-radius: 0 1.5rem 1.5rem 0;
+ height: 3rem;
+ min-width: 4.4rem !important;
+ right: 0.15rem;
+ top: 0.15rem;
+ width: 4.4rem; }
+
+.search-suggestion-wrapper {
+ margin-bottom: 15px;
+ position: relative; }
+ .search-suggestion-wrapper .no-result {
+ padding: 0px 15px; }
+
+.search-suggestion-item {
+ color: #333333;
+ line-height: 4rem;
+ padding: 0 15px;
+ position: relative;
+ z-index: 1000; }
+ .search-suggestion-item:hover {
+ background-color: #e4e4e4;
+ cursor: pointer; }
+ .search-suggestion-item:focus {
+ background-color: #e4e4e4;
+ cursor: pointer; }
+ .search-suggestion-item a {
+ color: #333333;
+ text-decoration: none; }
+
+.btn-search i {
+ color: #767676; }
+
+input.b2b-search-input-field:focus ~ .btn-search > i, .btn-search:focus > i {
+ color: #0568ae; }
+
+button.btn-search[disabled] {
+ cursor: not-allowed; }
+ button.btn-search[disabled] i {
+ color: #767676; }
+
+.linkSelectorModule {
+ position: relative;
+ height: 32px;
+ line-height: 20px;
+ border: 0px;
+ width: auto;
+ display: block; }
+ .linkSelectorModule .icon-primary-down {
+ font-size: 23px;
+ margin-top: -10px;
+ position: absolute;
+ top: 50%;
+ margin-left: -30px; }
+ .linkSelectorModule .selectModule {
+ background-color: transparent;
+ border: none;
+ color: #0568ae;
+ cursor: pointer;
+ border: 1px solid transparent;
+ box-shadow: none;
+ padding-right: 35px;
+ position: relative;
+ user-select: none;
+ font-size: 1.6rem; }
+ .linkSelectorModule .selectModule:focus {
+ border: 1px dotted #ccc;
+ box-shadow: none;
+ -moz-user-select: none; }
+ .linkSelectorModule .selectModule:hover {
+ text-decoration: underline; }
+ .linkSelectorModule .active + .moduleWrapper:before {
+ background-color: #FFFFFF;
+ border-color: #d2d2d2;
+ border-style: solid;
+ border-width: 1px 1px 0 0;
+ content: "";
+ display: block;
+ height: 15px;
+ right: 122px;
+ margin: 0;
+ position: absolute;
+ top: -8px;
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ width: 15px; }
+ .linkSelectorModule .moduleWrapper {
+ top: 40px; }
+ .linkSelectorModule ul.awd-module-list {
+ border-radius: 6px 6px 0px 0px; }
+
+.selectorModule .icon-primary-down {
+ font-size: 23px;
+ margin-top: -11px;
+ position: absolute;
+ right: 4px;
+ top: 50%; }
+
+.selectorModule .selectModule {
+ border: 1px solid #d2d2d2;
+ border-radius: 6px;
+ box-shadow: 1px 5px 2px -5px rgba(0, 0, 0, 0.15);
+ display: block;
+ width: 100%;
+ padding-left: 15px;
+ background-color: transparent;
+ cursor: pointer; }
+ .selectorModule .selectModule:focus {
+ border: 1px solid #0568ae;
+ -moz-user-select: none; }
+ .selectorModule .selectModule span.module-data {
+ position: absolute;
+ bottom: 6px;
+ line-height: 20px; }
+ .selectorModule .selectModule img + span.module-data {
+ padding-left: 45px; }
+
+.selectorModule .selectModule.active {
+ border-bottom-right-radius: 0px;
+ border-bottom-left-radius: 0px; }
+
+.selectorModule .moduleWrapper {
+ position: absolute;
+ width: 100% !important;
+ border-top: none; }
+
+.selectorModule ul.awd-module-list {
+ border-radius: 0px 0px 6px 6px; }
+
+.selectorModule .large > img {
+ height: 30px;
+ position: absolute;
+ width: 30px;
+ top: 20px;
+ left: 15px; }
+
+.selectModule {
+ background-color: transparent;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #333333;
+ font-size: 1.6rem;
+ height: 36px;
+ line-height: 35px;
+ margin-bottom: 0;
+ position: relative;
+ text-align: left;
+ top: 0;
+ z-index: 10;
+ padding: 0px;
+ margin: 0px;
+ cursor: pointer; }
+
+.moduleWrapper {
+ background-color: #FFFFFF;
+ position: absolute;
+ color: #191919;
+ z-index: 9999;
+ box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.15);
+ border-radius: 0px 0px 6px 6px; }
+ .moduleWrapper .module-list-item img {
+ height: 30px;
+ position: absolute;
+ width: 30px;
+ top: 30px;
+ left: 15px;
+ align-self: center; }
+ .moduleWrapper span {
+ display: block;
+ white-space: nowrap;
+ font-size: 1.5rem; }
+
+.awd-module-list {
+ overflow-y: auto;
+ z-index: 9999;
+ max-height: 360px;
+ border: 1px solid #d2d2d2; }
+ .awd-module-list .module-list-item > .module-data {
+ overflow: ellipsis;
+ white-space: nowrap;
+ line-height: 20px;
+ font-size: 1.6rem;
+ border-bottom: 1px dotted #959595;
+ margin: 0px 15px 0px 15px;
+ padding-right: 50px;
+ padding-bottom: 14px;
+ padding-top: 14px;
+ align-self: center;
+ width: 100%; }
+ .awd-module-list .module-list-item:hover {
+ background-color: #f2f2f2; }
+ .awd-module-list .module-list-item:active {
+ background-color: #f2f2f2; }
+ .awd-module-list .module-list-item[aria-selected="true"] {
+ background-color: #f2f2f2; }
+
+.module-list-item {
+ cursor: pointer;
+ overflow: hidden;
+ position: relative;
+ overflow: ellipsis;
+ white-space: nowrap;
+ z-index: 1000;
+ color: #191919;
+ display: flex; }
+ .module-list-item:last-of-type .module-data {
+ border-bottom: none; }
+ .module-list-item img + span.module-data {
+ padding-left: 45px; }
+
+.module-groups:first-of-type .module-list-item:last-of-type .module-data {
+ border-bottom: 1px solid #959595; }
+
+.module-groupitem {
+ padding-bottom: 4px; }
+
+.selectorModule.large {
+ height: 72px;
+ vertical-align: middle;
+ text-align: left; }
+ .selectorModule.large .moduleWrapper {
+ top: 71px; }
+ .selectorModule.large input {
+ height: 72px;
+ vertical-align: middle;
+ text-align: left; }
+ .selectorModule.large button {
+ height: 72px;
+ vertical-align: middle;
+ text-align: left; }
+ .selectorModule.large .selectModule img {
+ left: 15px;
+ top: 21px; }
+
+ul.module-groupitem li {
+ margin: 0 -15px 0 -15px; }
+
+span.module-data span {
+ display: block;
+ line-height: 20px;
+ font-size: 1.5rem; }
+
+li.module-groups {
+ cursor: default !important;
+ padding: 18px 15px 0px 15px; }
+
+li.module-list-item[selected]:before {
+ box-sizing: border-box;
+ display: inline-block;
+ font-size: 2em;
+ height: 1em;
+ position: absolute;
+ top: 20px;
+ right: 0px;
+ vertical-align: middle;
+ width: 1em;
+ color: #007a3e; }
+
+ul.module-optinalcta {
+ position: relative;
+ height: 44px;
+ margin-top: 0px;
+ border-bottom: 1px solid #d2d2d2;
+ border-left: 1px solid #d2d2d2;
+ border-right: 1px solid #d2d2d2;
+ border-radius: 0px 0px 6px 6px; }
+ ul.module-optinalcta li {
+ position: absolute;
+ bottom: 10px; }
+ ul.module-optinalcta a {
+ text-indent: 15px;
+ padding: 15px; }
+
+.b2b-slider-container {
+ position: relative; }
+ .b2b-slider-container.slider-disabled {
+ cursor: not-allowed !important; }
+ .b2b-slider-container div {
+ position: absolute; }
+ .b2b-slider-container .slider-track-container {
+ width: 100%;
+ cursor: pointer; }
+ .b2b-slider-container .slider-track {
+ width: 100%;
+ height: 6px;
+ background-color: #cccccc;
+ border-radius: 10px; }
+ .b2b-slider-container .slider-track-fill {
+ width: 100%;
+ height: 6px;
+ background-color: #cccccc;
+ border-radius: 10px;
+ width: 0;
+ background-color: #157BB2;
+ transition: width 0s linear; }
+ .b2b-slider-container .slider-knob-container {
+ transition: left 0s linear; }
+ .b2b-slider-container .slider-knob-container.slider-knob-hidden {
+ display: none !important; }
+ .b2b-slider-container .slider-knob {
+ width: 14px;
+ height: 14px;
+ border-radius: 10px;
+ top: -4px;
+ left: -8px;
+ border: 1px solid #cccccc;
+ background: white;
+ cursor: pointer; }
+ .b2b-slider-container .slider-knob:focus {
+ outline: thin dotted #666; }
+
+.b2b-slider-endpoints-container {
+ margin-top: 13px;
+ color: #333;
+ font-size: 12px; }
+ .b2b-slider-endpoints-container .b2b-slider-endpoints-left {
+ float: left;
+ line-height: 100%; }
+ .b2b-slider-endpoints-container .b2b-slider-endpoints-right {
+ float: right;
+ line-height: 100%; }
+ .b2b-slider-endpoints-container::after {
+ clear: both;
+ content: "";
+ display: block; }
+
+.b2b-slider-container.vertical {
+ width: 100%;
+ height: 100%;
+ margin: 0 auto;
+ position: relative;
+ border-radius: 10px; }
+ .b2b-slider-container.vertical .slider-track-container {
+ position: relative;
+ height: 100%; }
+ .b2b-slider-container.vertical .slider-track {
+ position: absolute;
+ height: 100%; }
+ .b2b-slider-container.vertical .slider-track-fill {
+ position: absolute;
+ bottom: 0;
+ height: 0;
+ width: 100%; }
+ .b2b-slider-container.vertical .slider-knob-container {
+ transition: bottom 0s linear;
+ position: relative;
+ bottom: 0; }
+ .b2b-slider-container.vertical .slider-knob-container.slider-knob-hidden {
+ display: none !important; }
+ .b2b-slider-container.vertical .slider-knob {
+ position: absolute;
+ border-radius: 10px;
+ top: -7px;
+ left: -4px; }
+
+.icon-primary-spinner {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%20id%3D%22svg-spinner%22%20x%3D%220px%22%20y%3D%220px%22%20xml%3Aspace%3D%22preserve%22%3E%0A%20%20%20%3Cpath%20fill%3D%22%23F5F5F5%22%20d%3D%22M18%2036C8.1%2036%200%2027.9%200%2018S8.1%200%2018%200s18%208.1%2018%2018-8.1%2018-18%2018zm0-31.5c-7.5%200-13.5%206-13.5%2013.5S10.6%2031.5%2018%2031.5c7.5%200%2013.5-6.1%2013.5-13.5%200-7.5-6-13.5-13.5-13.5z%22%2F%3E%0A%20%20%20%3Cpath%20fill%3D%22%230568AE%22%20id%3D%22spinner%22%20d%3D%22M30.7%205.3l-3.1%203.2c2.4%202.4%203.9%205.8%203.9%209.5%200%207.4-6.1%2013.5-13.5%2013.5S4.5%2025.4%204.5%2018%2010.6%204.5%2018%204.5V0C8.1%200%200%208.1%200%2018s8.1%2018%2018%2018%2018-8.1%2018-18c0-5-2-9.5-5.3-12.7z%22%3E%0A%20%20%20%20%20%20%3CanimateTransform%20%0A%20%20%20%20%20%20%20%20%20attributeType%3D%22xml%22%0A%20%20%20%20%20%20%20%20%20attributeName%3D%22transform%22%0A%20%20%20%20%20%20%20%20%20type%3D%22rotate%22%0A%20%20%20%20%20%20%20%20%20from%3D%220%2018%2018%22%0A%20%20%20%20%20%20%20%20%20to%3D%22360%2018%2018%22%0A%20%20%20%20%20%20%20%20%20dur%3D%221.0s%22%0A%20%20%20%20%20%20%20%20%20repeatCount%3D%22indefinite%22%0A%20%20%20%20%20%20%2F%3E%0A%20%20%20%3C%2Fpath%3E%0A%3C%2Fsvg%3E");
+ height: 50px;
+ width: 50px; }
+
+.icon-primary-spinner.small {
+ margin-right: 5px;
+ height: 30px !important;
+ width: 30px !important; }
+
+.isIE .icon-primary-spinner,
+.isIE .icon-primary-spinner.small {
+ animation: spinner 1s linear infinite; }
+
+.ds2-no-colors .icon-primary-spinner {
+ animation: spinner 1s linear infinite;
+ border: 5px dotted transparent;
+ border-radius: 50%; }
+
+@keyframes spinner {
+ 0% {
+ transform: rotate(0deg); }
+ 100% {
+ transform: rotate(359deg); } }
+
+.b2b-status-tracker > .btn-arrow:nth-of-type(1) {
+ margin-right: 10px; }
+
+.b2b-status-tracker > .btn-arrow:nth-of-type(2) {
+ margin-left: 20px; }
+
+.b2b-status-tracker > .btn-arrow {
+ height: 20px;
+ margin-top: 25px;
+ overflow: visible; }
+ .b2b-status-tracker > .btn-arrow > .btn-secondary > .icon-primary-left {
+ margin-right: 5px;
+ color: #0574ac; }
+ .b2b-status-tracker > .btn-arrow > .btn-secondary > .icon-primary-right {
+ color: #0574ac; }
+
+.b2b-status-tracker > .b2b-status-tracker-step {
+ padding: 0;
+ position: relative; }
+
+.b2b-status-tracker-step {
+ margin-left: 5px; }
+
+.b2b-status-tracker > .b2b-status-tracker-step .b2b-status-tracker-heading {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ color: #767676;
+ margin-bottom: 10px; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.complete > .b2b-status-tracker-heading {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #1b7e28; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.complete > .progress > .progress-bar {
+ width: 100%;
+ background-color: #1b7e28; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.complete > .b2b-status-tracker-estimate {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #333333; }
+ .b2b-status-tracker > .b2b-status-tracker-step.complete > .b2b-status-tracker-estimate > .icoControls-approval {
+ color: #1b7e28; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.current > .b2b-status-tracker-heading {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #333333; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.current > .progress > .progress-bar {
+ width: 100%;
+ background-color: #333333; }
+
+.b2b-status-tracker > .b2b-status-tracker-step.current > .b2b-status-tracker-estimate > .icon-misc-time {
+ color: #333333; }
+
+.b2b-status-tracker > .b2b-status-tracker-step > .progress {
+ position: relative;
+ border-radius: 1.5px;
+ height: 3px;
+ margin-bottom: 10px;
+ background-color: #c5c5c5; }
+ .b2b-status-tracker > .b2b-status-tracker-step > .progress > .progress-bar {
+ width: 0;
+ height: 3px; }
+
+.b2b-status-tracker > .b2b-status-tracker-step > .b2b-status-tracker-estimate {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ color: #767676;
+ margin-bottom: 10px; }
+ .b2b-status-tracker > .b2b-status-tracker-step > .b2b-status-tracker-estimate > .icon-misc-time {
+ color: #767676; }
+
+.b2b-status-tracker > .b2b-status-tracker-step > .b2b-status-tracker-description {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 12px;
+ color: #767676;
+ padding-right: 15px; }
+
+.step-indicator {
+ height: auto;
+ padding: 40px 0; }
+
+.step-heading {
+ color: #333333;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 3.8rem;
+ line-height: 0.8; }
+
+.steps {
+ display: flex;
+ height: 5px;
+ margin-top: 60px;
+ position: relative; }
+
+.steps li {
+ color: #5a5a5a;
+ flex: 1;
+ margin-right: 5px;
+ background-color: #c4c4c4;
+ outline: 1px solid transparent; }
+
+.steps li:first-child {
+ border-radius: 4px 0 0 4px; }
+
+.steps li:last-child {
+ margin-right: 0;
+ border-radius: 0 4px 4px 0; }
+
+.steps li.step-on,
+.steps li.step-done {
+ background-color: #007a3e;
+ color: #007a3e;
+ border: 1px solid transparent; }
+
+.step-text {
+ bottom: 29px;
+ display: inline-block;
+ font-size: 1.8rem;
+ margin-top: 0;
+ position: relative;
+ white-space: nowrap; }
+
+.step-on .step-text {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.steps li .step-text[data-large-text]:before {
+ content: attr(data-large-text) " "; }
+
+.step-confirmation {
+ color: #007a3e;
+ margin-bottom: 30px; }
+
+.step-confirmation > div {
+ display: flex; }
+
+.step-confirmation > div i {
+ color: #007a3e;
+ font-size: 50px;
+ margin-right: 10px; }
+
+.step-confirmation.centered > div i {
+ margin-left: -60px; }
+
+.step-confirmation > div h3 {
+ font-size: 2.4rem;
+ margin: 26px 0 20px; }
+
+.step-confirmation > p {
+ margin: 0; }
+
+@media (max-width: 1024px) {
+ .step-indicator {
+ padding: 25px 0; }
+ .steps {
+ margin-top: 0; }
+ .step-heading {
+ font-size: 2.4rem;
+ margin-bottom: 11px; }
+ .step-text {
+ display: none; }
+ .step-on .step-text {
+ bottom: 6px;
+ display: block;
+ font-size: 1.2rem;
+ left: 0;
+ line-height: 1;
+ margin-top: 10px;
+ position: absolute;
+ top: 4px; }
+ .steps li .step-text[data-sm-text]:before {
+ content: attr(data-sm-text) " ";
+ color: #333333; }
+ .step-confirmation {
+ margin-top: 30px !important; } }
+
+@media (max-width: 767px) {
+ .step-confirmation.centered > div i {
+ margin-left: 0; }
+ .step-confirmation.centered > p {
+ margin-left: 40px; }
+ .step-confirmation > div h3 {
+ font-size: 1.8rem;
+ margin: 13px 0 10px; }
+ .step-confirmation > div i {
+ font-size: 30px;
+ margin-right: 10px; } }
+
+.step-indicator.vertical {
+ height: auto; }
+
+.vertical .step-heading {
+ font-size: 24px; }
+
+.vertical .steps {
+ display: block;
+ height: inherit;
+ width: 100%; }
+
+.vertical .steps li {
+ align-items: center;
+ background-color: transparent;
+ display: flex;
+ height: 60px;
+ margin: 0 0 4px;
+ padding: 0 0 0 20px;
+ position: relative; }
+
+.vertical .steps li .step-text {
+ align-self: center;
+ color: #0568ae;
+ display: block;
+ margin: 0;
+ position: relative;
+ font-size: 14px;
+ top: 0; }
+
+.vertical .steps li .step-text[data-large-text]:before {
+ content: attr(data-large-text) " "; }
+
+.vertical .steps li:after {
+ background-color: transparent;
+ border-left: 4px solid #d2d2d2;
+ content: "";
+ height: 60px;
+ left: 0;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ top: 0;
+ width: 4px; }
+
+.vertical .steps li.step-on:after,
+.vertical .steps li.step-done:after {
+ border-color: #0568ae; }
+
+.b2b-step-tracker {
+ height: auto;
+ padding: 0px 0px 0px 0px; }
+ .b2b-step-tracker .btn.btn-left {
+ margin-right: 10px; }
+ .b2b-step-tracker .btn.btn-right {
+ margin-left: 5px; }
+ .b2b-step-tracker .b2b-left-arrow {
+ float: left;
+ margin-top: -5px; }
+ .b2b-step-tracker .b2b-right-arrow {
+ float: right;
+ margin-top: -5px; }
+ .b2b-step-tracker .b2b-steps {
+ display: flex;
+ height: 5px;
+ margin-top: 30px;
+ position: relative; }
+ .b2b-step-tracker .b2b-steps li {
+ color: #767676;
+ flex: 1;
+ margin-right: 5px;
+ background-color: #767676;
+ outline: 1px solid transparent;
+ height: 3px; }
+ .b2b-step-tracker .b2b-steps li.b2b-step-done {
+ background-color: #1b7e28;
+ color: #007a3e;
+ height: 3px; }
+ .b2b-step-tracker .b2b-steps li.b2b-step-on {
+ background-color: #333333;
+ color: #333333;
+ height: 3px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+ .b2b-step-tracker .b2b-steps li .b2b-step-text {
+ bottom: 29px;
+ display: inline-block;
+ font-size: 14px;
+ margin-top: 0;
+ position: relative;
+ white-space: nowrap; }
+ .b2b-step-tracker .b2b-steps li .b2b-step-text[data-large-text]:before {
+ content: attr(data-large-text) " "; }
+ .b2b-step-tracker .b2b-steps li:first-child {
+ border-radius: 2px 0 0 2px; }
+ .b2b-step-tracker .b2b-steps li:last-child {
+ margin-right: 0;
+ border-radius: 0 2px 2px 0; }
+
+@media (max-width: 1024px) {
+ .b2b-step-tracker {
+ padding: 25px 0; }
+ .b2b-step-tracker .b2b-steps {
+ margin-top: 0; }
+ .b2b-step-tracker .b2b-steps li .b2b-step-text {
+ display: none; }
+ .b2b-step-tracker .b2b-steps li .b2b-step-text[data-sm-text]:before {
+ content: attr(data-sm-text) " ";
+ color: #333333; }
+ .b2b-step-tracker .b2b-steps li.b2b-step-on .b2b-step-text {
+ bottom: 6px;
+ display: block;
+ font-size: 10px;
+ left: 0;
+ line-height: 1;
+ margin-top: 10px;
+ position: absolute;
+ top: 4px; } }
+
+.strength-meter-container {
+ height: 26px;
+ max-width: 450px; }
+
+.strength-meter-gauge {
+ border-radius: 2px;
+ background-color: #d2d2d2;
+ height: 5px;
+ display: block;
+ position: relative;
+ outline: 1px solid transparent; }
+
+.strength-meter-gauge-fill {
+ height: 100%;
+ display: block;
+ border-radius: 2px;
+ text-indent: -9999px;
+ width: 0%;
+ border: 2px solid transparent; }
+
+.strength-meter-gauge-fill.strength-meter-animate {
+ transition: width 0.5s linear, background-color 0.5s linear; }
+
+.strength-meter-animate[style*="20"] {
+ background-color: #cf2a2a; }
+
+.strength-meter-animate[style*="20"] + .strength-meter-divider + .strength-meter-content:after {
+ content: "Unacceptable"; }
+
+.strength-meter-animate[style*="40"] {
+ background-color: #ea7400; }
+
+.strength-meter-animate[style*="40"] + .strength-meter-divider + .strength-meter-content:after {
+ content: "Weak"; }
+
+.strength-meter-animate[style*="60"] {
+ background-color: #ea7400; }
+
+.strength-meter-animate[style*="60"] + .strength-meter-divider + .strength-meter-content:after {
+ content: "Fair"; }
+
+.strength-meter-animate[style*="80"] {
+ background-color: #007a3e; }
+
+.strength-meter-animate[style*="80"] + .strength-meter-divider + .strength-meter-content:after {
+ content: "Good"; }
+
+.strength-meter-animate[style*="100"] {
+ background-color: #007a3e; }
+
+.strength-meter-animate[style*="100"] + .strength-meter-divider + .strength-meter-content:after {
+ content: "Excellent"; }
+
+.strength-meter-divider {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ overflow: hidden; }
+
+.strength-meter-divider span {
+ background: transparent;
+ display: block;
+ flex-grow: 1;
+ border-right: solid 1px #fff; }
+
+.strength-meter-divider span:first-child {
+ border-radius: 2px 0 0 2px; }
+
+.strength-meter-divider span + .strength-meter-divider span {
+ border-radius: 0; }
+
+.strength-meter-divider span:last-child {
+ border-radius: 0 2px 2px 0;
+ border-right: 0; }
+
+.strength-meter-content {
+ font-size: 14px;
+ line-height: 1;
+ padding-top: 7px;
+ position: absolute; }
+
+.strength-meter-content:before {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ content: "Password strength: "; }
+
+.strength-meter-content:after {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.strength-meter-container {
+ height: 26px;
+ min-width: 290px;
+ max-width: 450px; }
+
+.strength-meter-container .strength-meter-gauge {
+ border-radius: 2px;
+ background-color: #cccccc;
+ box-shadow: 0 1px 1px -1px #333 inset;
+ height: 5px;
+ display: block;
+ overflow: hidden;
+ position: relative; }
+
+.strength-meter-container > .strength-meter-gauge > .strength-meter-gauge-fill {
+ height: 100%;
+ box-shadow: 0 1px 1px -1px #999 inset;
+ display: block;
+ text-indent: -9999px;
+ width: 0%; }
+
+.strength-meter-container > .strength-meter-gauge > .strength-meter-gauge-fill.strength-meter-animate {
+ transition: width 0ms ease-out, background-color 0ms ease-in; }
+
+.strength-meter-container > .strength-meter-gauge > .strength-meter-divider {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex; }
+
+.strength-meter-container > .strength-meter-gauge > .strength-meter-divider span {
+ background: transparent;
+ display: block;
+ flex-grow: 1;
+ border-right: solid 1px #fff; }
+
+.strength-meter-container > .strength-meter-gauge > .strength-meter-divider span:last-child {
+ border-right: 0; }
+
+.strength-meter-container > .strength-meter-content {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ line-height: 1;
+ padding-top: 7px; }
+
+.strength-meter-container > .strength-meter-content:before {
+ content: none; }
+
+.strength-meter-container > .strength-meter-content > .strength-meter-content-state {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial; }
+
+.btn-switch-label {
+ display: flex;
+ align-items: center; }
+ .btn-switch-label:focus .btn-switch {
+ outline: 1px dotted #666;
+ outline-offset: 5px; }
+ .btn-switch-label input:focus .btn-switch {
+ outline: 1px dotted #666;
+ outline-offset: 5px; }
+ .btn-switch-label > span {
+ flex: 1; }
+
+.btn-switch {
+ background-color: #fff;
+ border: 1px solid #d2d2d2;
+ border-radius: 16px;
+ box-shadow: 0 4px 5px -5px rgba(0, 0, 0, 0.15) inset, 0 5px 5px -5px rgba(0, 0, 0, 0.15);
+ height: 32px;
+ overflow: hidden;
+ position: relative;
+ width: 80px;
+ user-select: none; }
+ .btn-switch input[type="checkbox"] {
+ left: 0;
+ margin: 0;
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ transition: none; }
+ .btn-switch input[type="checkbox"] + .switch-overlay .btn-slider-on .activo {
+ font: 0px/0 "Omnes-ECOMP-W02", Arial; }
+ .btn-switch input[type="checkbox"] + .switch-overlay .btn-slider-on + .btn + .btn-slider-off .inactivo {
+ font: 0px/0 "Omnes-ECOMP-W02", Arial; }
+ .btn-switch input:checked + .switch-overlay {
+ left: 0;
+ transition: all .3s linear .0s; }
+ .btn-switch input:checked + .switch-overlay .switch-handle {
+ background-color: #007a3e;
+ background: linear-gradient(to bottom, #008744 0%, #007a3e 100%);
+ transition: background-color 0.3s linear 0s;
+ border: 1px solid transparent; }
+ .btn-switch input + .switch-overlay {
+ left: -48px;
+ transition: all .3s linear .0s; }
+ .btn-switch input + .switch-overlay .switch-handle {
+ background-color: #f2f2f2;
+ background: linear-gradient(to bottom, #fcfcfc 0%, #f2f2f2 100%);
+ transition: background-color 0.3s linear 0s;
+ border: 1px solid #d2d2d2; }
+ .btn-switch input[disabled] + .switch-overlay {
+ left: 0;
+ width: 100% !important;
+ background-color: #d2d2d2;
+ color: #959595;
+ cursor: not-allowed !important; }
+ .btn-switch input[disabled] + .switch-overlay .btn-slider-on {
+ display: none; }
+ .btn-switch input[disabled] + .switch-overlay .activo {
+ display: none; }
+ .btn-switch input[disabled] + .switch-overlay .switch-handle {
+ display: none; }
+ .btn-switch input[disabled] + .switch-overlay .btn-slider-off {
+ left: 0;
+ text-align: center;
+ padding: 0; }
+ .btn-switch input[disabled]:checked + .switch-overlay {
+ left: 0;
+ width: 100% !important;
+ background-color: #fff; }
+ .btn-switch input[disabled]:checked + .switch-overlay .btn-slider-off {
+ display: none; }
+ .btn-switch input[disabled]:checked + .switch-overlay .btn-slider-off + .inactivo {
+ display: none; }
+ .btn-switch input[disabled]:checked + .switch-overlay .switch-handle {
+ display: none; }
+ .btn-switch input[disabled]:checked + .switch-overlay .btn-slider-on {
+ display: block;
+ text-align: center;
+ padding: 0;
+ color: #007a3e !important;
+ font-weight: bold; }
+ .btn-switch input[disabled]:checked + .switch-overlay .activo {
+ display: block;
+ text-align: center;
+ padding: 0;
+ color: #007a3e !important;
+ font-weight: bold; }
+ .btn-switch input[disabled]:checked + .btn-slider-on {
+ display: block; }
+ .btn-switch input[disabled] + .btn-slider-on + .switch-handle {
+ width: 100%;
+ margin: 0; }
+ .btn-switch input[disabled] + .btn-slider-on + .switch-handle + .btn-slider-off {
+ display: block; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on {
+ display: none; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on .activo {
+ border: medium none;
+ color: #666;
+ font: 16px/32px "Omnes-ECOMP-W02", Arial;
+ height: auto;
+ margin: 0 auto;
+ width: auto; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on .activo:before {
+ display: none; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on + .switch-handle + .btn-slider-off {
+ display: block;
+ padding: 0;
+ text-align: center;
+ color: #333333; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on + .switch-handle + .btn-slider-off .inactivo {
+ border: medium none;
+ color: #666;
+ font: 16px/32px "Omnes-ECOMP-W02", Arial;
+ height: auto;
+ margin: 0 auto;
+ width: auto; }
+ .btn-switch input[type="checkbox"][disabled] + .switch-overlay .btn-slider-on + .switch-handle + .btn-slider-off .inactivo:before {
+ display: none; }
+ .btn-switch input[type="checkbox"][disabled]:checked + .switch-overlay .btn-slider-on {
+ display: block;
+ padding: 0;
+ text-align: center;
+ color: #007a3e; }
+ .btn-switch input[type="checkbox"][disabled]:checked + .switch-overlay .btn-slider-on + .switch-handle + .btn-slider-off {
+ display: none; }
+ .btn-switch input[type="checkbox"][disabled]:checked + .switch-overlay .activo {
+ color: #007a3e;
+ font-weight: bold; }
+
+.switch-overlay {
+ border-radius: 16px;
+ color: black !important;
+ font-size: 1.6rem;
+ height: 32px;
+ left: 0;
+ position: absolute;
+ top: -1px;
+ width: 126px;
+ overflow: hidden; }
+
+.btn-slider-on {
+ left: -1px;
+ text-align: left;
+ padding-left: 12px;
+ display: inline-block;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ height: 32px;
+ line-height: 32px;
+ position: absolute;
+ top: 1px;
+ width: 80px; }
+
+.btn-slider-off {
+ display: inline-block;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ height: 32px;
+ line-height: 32px;
+ position: absolute;
+ top: 1px;
+ width: 80px;
+ right: 1px;
+ text-align: right;
+ padding-right: 11px; }
+
+.switch-handle {
+ border-radius: 50%;
+ display: inline-block;
+ height: 26px;
+ left: 50px;
+ position: absolute;
+ top: 3px;
+ width: 26px; }
+
+.activo {
+ display: block;
+ font-size: 0.1px;
+ line-height: 40px;
+ overflow: hidden; }
+ .activo:before {
+ background-image: none;
+ border-left: 3px solid #007a3e;
+ content: " ";
+ height: 18px;
+ left: 22px;
+ margin: 2px auto;
+ position: absolute;
+ top: 5px;
+ width: 0; }
+
+.inactivo {
+ font-size: 0.1px;
+ line-height: 40px; }
+ .inactivo:before {
+ background-image: none;
+ border: 3px solid #959595;
+ border-radius: 100%;
+ content: " ";
+ display: block;
+ position: absolute;
+ top: 4px;
+ right: 3px;
+ height: 16px;
+ width: 16px; }
+
+table {
+ max-width: 100%;
+ background-color: transparent;
+ border-collapse: collapse;
+ border-spacing: 0;
+ width: 100%;
+ margin-bottom: 20px; }
+
+table caption {
+ text-align: left; }
+
+table thead th {
+ vertical-align: bottom; }
+
+table th,
+table td {
+ padding: 19px 20px;
+ line-height: 1;
+ font-size: 1.4rem;
+ text-align: left;
+ vertical-align: top;
+ word-wrap: break-word; }
+
+table th {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 1.6rem;
+ font-weight: normal;
+ color: #333333;
+ padding: 13px 20px; }
+
+table tbody td {
+ border-left: 1px solid #d2d2d2;
+ border-top: 1px solid #d2d2d2; }
+
+table tbody td:first-child {
+ border-left: none; }
+
+.tiny-accordion.iconleft.accordion-table-layout .toggle-header,
+.tiny-accordion.iconleft.accordion-table-layout .toggle-header + .accordion-content,
+.tiny-accordion.iconleft.accordion-table-layout .inactive-toggle-header {
+ padding: 0 0 0 50px; }
+
+.faux-table-cell,
+.inactive-toggle-header .faux-table-cell {
+ display: table-cell;
+ width: 100%;
+ padding: 13px 0 10px 0;
+ font-size: 16px;
+ color: #333333; }
+
+.accordion-content .faux-table-cell {
+ display: table-cell;
+ width: 100%;
+ padding: 0 0 10px 0; }
+
+.faux-table-cell:last-child {
+ text-align: right;
+ min-width: 100px;
+ max-width: 150px;
+ width: 1%;
+ background-color: #f2f2f2;
+ color: #333333;
+ font-size: 14px;
+ border-left: 1px solid #d2d2d2;
+ padding: 0 20px 0 10px; }
+
+.tiny-accordion.iconleft.accordion-table-layout .toggle-header.opened .hide-when-expanded {
+ opacity: 1; }
+
+.tiny-accordion.iconleft.accordion-table-layout .toggle-header.opened .hide-when-expanded {
+ opacity: 0;
+ transition: opacity .3s linear .2s; }
+
+@media (max-width: 767px) {
+ table th,
+ table td {
+ padding: 19px 10px; }
+ table th:first-child,
+ table td:first-child {
+ padding: 19px 15px; } }
+
+.data-row-list ul > li {
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20viewport%3D%220%200%201%201%22%20style%3D%22width%3A100%25%3B%20height%3A1px%3B%22%3E%3Cstyle%3Eline%7Bstroke%3Argba(153%2C153%2C153%2C1)%3Bstroke-width%3A2%3B%7D%3C%2Fstyle%3E%3Cline%20y2%3D%221%22%20y1%3D%221%22%20x1%3D%221%22%20x2%3D%22100%25%22%20stroke-dasharray%3D%221%2C%203%22%2F%3E%3C%2Fsvg%3E") !important; }
+
+table {
+ border-bottom: 1px solid #d2d2d2; }
+
+table th,
+table td {
+ padding: 15px 15px 10px; }
+
+.data-row .col-1 {
+ white-space: nowrap;
+ padding: 15px 15px 0 15px;
+ position: relative;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.4rem;
+ border-top: 1px solid #d2d2d2; }
+
+.data-row.has-button .col-1 {
+ padding: 0; }
+
+.complex-table .data-row .col-1 {
+ color: #0568ae;
+ cursor: pointer; }
+
+.data-row.opened {
+ box-shadow: 0 -2px 0 0 #d2d2d2; }
+
+.data-row.opened td,
+.data-row.opened th {
+ border-left: 1px solid transparent;
+ border-bottom: 1px solid transparent; }
+
+.data-row.opened + .data-row-list {
+ box-shadow: 0 1px 0 0 #d2d2d2; }
+
+.data-row.opened + .data-row-list > td {
+ padding-top: 0; }
+
+.data-row.opened + .data-row-list + .data-row.opened {
+ box-shadow: 0 -1px 0 0 #d2d2d2; }
+
+.data-row button {
+ background-color: transparent;
+ border: medium none;
+ border-radius: 0;
+ color: #0568ae;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.4rem;
+ left: 0;
+ margin: 0;
+ padding: 12px 15px 7px;
+ position: relative;
+ text-align: left;
+ top: 0;
+ vertical-align: middle; }
+
+.data-row button:focus {
+ outline: 1px dotted black; }
+
+.data-row .col-1 i {
+ top: -1px;
+ margin-right: 10px;
+ display: inline-block !important; }
+
+.data-row-list th:first-child {
+ background-color: inherit !important;
+ border-top: none;
+ padding: 0 15px 15px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.4rem; }
+
+.data-row-list ul {
+ margin: 0 0 0 30px; }
+
+.data-row-list ul > li:before {
+ display: none; }
+
+.data-row-list ul > li {
+ /* background-image in tables.less */
+ background-position: left 13px;
+ background-repeat: repeat-x;
+ background-size: 4px 1px;
+ display: table;
+ padding-left: 0;
+ width: 100%; }
+
+.data-row-list li div {
+ display: table-cell;
+ background-color: white;
+ float: left;
+ text-align: left;
+ padding-left: 0;
+ padding-right: 7px; }
+
+.data-row-list li div + div {
+ float: right;
+ text-align: right;
+ padding-right: 0;
+ padding-left: 7px; }
+
+.complex-table td:nth-child(1),
+.complex-table td:nth-child(2),
+.complex-table td:nth-child(3),
+.complex-table td:nth-child(4),
+.complex-table td:nth-child(5),
+.complex-table td:nth-child(6),
+.complex-table td:nth-child(7),
+.complex-table td:nth-child(8),
+.complex-table td:nth-child(9) {
+ white-space: nowrap; }
+
+th:nth-child(8) {
+ word-wrap: break-word;
+ word-spacing: 0; }
+
+.align-col-right {
+ text-align: right; }
+
+.complex-table th:not(:first-child),
+.complex-table td:not(:first-child) {
+ text-align: right; }
+
+.striped tbody > tr td {
+ background-color: transparent !important; }
+
+.striped tbody > tr.data-row.odd,
+.striped tbody > tr.data-row.odd + .data-row-list,
+.striped tbody > tr.data-row.odd + .data-row-list li div {
+ background-color: #f2f2f2 !important; }
+
+.striped tbody > tr:not('.data-row'):nth-child(even) {
+ background-color: #f2f2f2; }
+
+.b2b-table-div .selectWrap {
+ width: 290px;
+ position: relative;
+ left: 10px;
+ display: inline-table;
+ margin-bottom: 0px; }
+
+.b2b-external-sort-div {
+ float: right;
+ padding-bottom: 25px; }
+
+.b2b-external-sort-div .sortButton {
+ font-size: 36px;
+ border: 1px solid #ccc;
+ background: #FFF;
+ border-radius: 6px; }
+
+.b2b-external-sort-label {
+ padding-bottom: 10px; }
+
+.b2b-external-sort-div a:hover {
+ cursor: pointer; }
+
+.b2b-external-sort-div a:hover, .b2b-external-sort-div a:focus {
+ text-decoration: none; }
+
+.b2b-external-sort-label label {
+ position: relative;
+ left: 10px; }
+
+.tablesorter-default .tablesorter-header.sorter-false .tablesorter-header-inner {
+ background: 0 0;
+ cursor: default; }
+
+.tablesorter-default .tablesorter-header .tablesorter-header-inner {
+ /* background-image: url(images/tables/upanddown.png);*/
+ background-position: center right;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ white-space: normal;
+ display: inline-block;
+ vertical-align: baseline;
+ zoom: 1;
+ *display: inline;
+ *vertical-align: auto;
+ /* padding: 0 24px 0 0;*/ }
+
+.tablesorter-default .tablesorter-header.sorter-false .tablesorter-header-inner {
+ padding: 0; }
+
+.tablesorter-default .tablesorter-header.tablesort-sortable .tablesorter-header-inner span {
+ margin-right: 24px;
+ display: inline-block; }
+
+/*
+.tablesorter-default thead .headerSortUp .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerAsc .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerSortUp .tablesorter-header-inner {
+ background-image: url(images/tables/up.png);
+}
+
+.tablesorter-default thead .headerSortDown .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerDesc .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerSortDown .tablesorter-header-inner {
+ background-image: url(images/tables/down.png);
+}
+*/
+.tablesorter-default thead .headerSortUp .tablesorter-header-inner,
+.tablesorter-default thead .tablesorter-headerAsc .tablesorter-header-inner,
+.tablesorter-default thead .tablesorter-headerSortUp .tablesorter-header-inner,
+.tablesorter-default thead .headerSortDown .tablesorter-header-inner,
+.tablesorter-default thead .tablesorter-headerDesc .tablesorter-header-inner,
+.tablesorter-default thead .tablesorter-headerSortDown .tablesorter-header-inner {
+ padding-right: 0;
+ line-height: 16px; }
+
+.tablesorter-default thead .headerSortUp .tablesorter-header-inner:after,
+.tablesorter-default thead .tablesorter-headerAsc .tablesorter-header-inner:after,
+.tablesorter-default thead .tablesorter-headerSortUp .tablesorter-header-inner:after {
+ font-family: 'icoPrimary' !important;
+ speak: none;
+ font-style: normal;
+ font-size: 24px;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 14px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ content: "\ea3c";
+ /* position: relative;*/
+ position: absolute;
+ text-decoration: inherit;
+ display: inline-block;
+ transform: rotate(180deg);
+ margin-left: -22px;
+ margin-top: 2px; }
+
+.tablesorter-default thead .headerSortDown .tablesorter-header-inner:after,
+.tablesorter-default thead .tablesorter-headerDesc .tablesorter-header-inner:after,
+.tablesorter-default thead .tablesorter-headerSortDown .tablesorter-header-inner:after {
+ font-family: 'icoPrimary' !important;
+ speak: none;
+ font-style: normal;
+ font-size: 24px;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 14px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ content: "\ea3c";
+ /* position: relative;*/
+ position: absolute;
+ text-decoration: inherit;
+ display: inline-block;
+ margin-left: -22px;
+ margin-top: 2px; }
+
+.tablesorter-search-highlight {
+ font-weight: 700; }
+
+.tablesorter-headerRow th:focus {
+ outline: thin dotted #666;
+ outline-offset: -1px; }
+
+.b2b-table-message {
+ font-family: "Omnes-ECOMP-W02", Arial; }
+ .b2b-table-message .b2b-magnify-glass {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%20enable-background%3D%22new%200%200%2036%2036%22%3E%3Cpath%20d%3D%22M27.847%208.26c-1.805-1.803-4.202-2.795-6.751-2.795-2.548%200-4.945.993-6.749%202.796-1.803%201.803-2.796%204.2-2.796%206.75%200%201.879.543%203.681%201.576%205.242l-7.059%207.059c-.357.356-.554.831-.554%201.336-.001.505.196.98.554%201.337.357.356.832.552%201.336.552.503%200%20.977-.196%201.336-.553l7.047-7.048c1.576%201.062%203.402%201.622%205.309%201.622%202.55%200%204.948-.993%206.751-2.796%201.803-1.804%202.796-4.201%202.796-6.751%200-2.549-.993-4.947-2.796-6.751zm-6.761.96c3.186%200%205.778%202.592%205.778%205.778%200%203.186-2.592%205.778-5.778%205.778-3.186%200-5.778-2.592-5.778-5.778%200-3.185%202.592-5.778%205.778-5.778z%22%20fill%3D%22%23767676%22%2F%3E%3C%2Fsvg%3E");
+ background-repeat: no-repeat;
+ background-position: center;
+ height: 50px; }
+ .b2b-table-message .b2b-alert {
+ font-size: 50px; }
+ .b2b-table-message .b2b-loading-dots {
+ font-size: 50px;
+ margin-bottom: 20px; }
+ .b2b-table-message .b2b-message {
+ text-align: center;
+ padding-bottom: 45px;
+ padding-top: 40px;
+ border-style: solid;
+ border-width: 1px;
+ border-top: none;
+ padding-bottom: 45px;
+ border-color: #d2d2d2;
+ width: 100%;
+ min-height: 220px; }
+ .b2b-table-message .b2b-error-title {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #444444;
+ line-height: 26px;
+ margin-top: 10px; }
+ .b2b-table-message .b2b-message-title {
+ color: #444;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+.b2b-table-scrollbar {
+ border: 1px solid;
+ width: 651px; }
+ .b2b-table-scrollbar .b2b-table-inner-container {
+ width: 650px;
+ padding-left: 150px;
+ overflow-x: scroll; }
+ .b2b-table-scrollbar th:first-child {
+ background-color: #FFFFFF; }
+ .b2b-table-scrollbar td:first-child {
+ background-color: #FFFFFF;
+ border-top: 1px solid #cccccc;
+ border-right: 1px solid #cccccc;
+ margin-top: -0.5px; }
+ .b2b-table-scrollbar tr {
+ th: nth-child(2), td; }
+ .b2b-table-scrollbar tr :nth-child(2) {
+ border-left: none; }
+ .b2b-table-scrollbar tr:last-child > td:first-child {
+ border-bottom: 1px solid #cccccc; }
+
+.b2b-scrollbar-arrow-left {
+ float: left;
+ margin: 10px; }
+
+.b2b-scrollbar-arrow-right {
+ float: right;
+ clear: right;
+ margin: 10px; }
+ .b2b-scrollbar-arrow-right.btn-arrow .btn {
+ margin-right: 0; }
+
+.b2b-table-scrollbar ::-webkit-scrollbar {
+ height: 10px; }
+
+.b2b-table-scrollbar ::-webkit-scrollbar-thumb {
+ background: #666666;
+ border-radius: 5px; }
+
+.tabs {
+ margin-left: 0;
+ margin-bottom: 20px;
+ list-style: none; }
+
+.tabs > li > a {
+ display: block; }
+
+.tabs > li > a:hover,
+.tabs > li > a:focus {
+ text-decoration: none;
+ background-color: #d2d2d2; }
+
+.tabs > .pull-right {
+ float: right; }
+
+.tabs:before,
+.tabs:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.tabs:after {
+ clear: both; }
+
+.tabs > li {
+ float: left; }
+
+.tabs > li > a {
+ padding-right: 20px;
+ padding-left: 20px;
+ margin-right: 3px;
+ line-height: 16px; }
+
+.tabs {
+ margin: 0; }
+
+.tabs > li {
+ margin-bottom: -1px; }
+
+.tabs > li:first-child {
+ margin-left: 20px; }
+
+.tabs > li > a {
+ padding: 12px 20px;
+ border: 1px solid #d2d2d2;
+ border-radius: 6px 6px 0 0;
+ background-color: #f2f2f2;
+ color: #5a5a5a;
+ border-color: #d2d2d2; }
+
+.tabs > li > a {
+ margin-right: 6px; }
+
+.tabs > li > a,
+.tabs > li > a:hover,
+.tabs > li > a:focus {
+ background-image: none;
+ background-color: #ffffff;
+ color: #5a5a5a;
+ border-color: #d2d2d2;
+ border-bottom: 1px solid transparent;
+ cursor: pointer; }
+
+.tabs.tabs-justified,
+.tabs.promo-tabs {
+ width: 100%;
+ border-bottom: 0;
+ margin-bottom: -1px; }
+
+.tabs.tabs-justified > li,
+.tabs.promo-tabs > li {
+ display: table-cell;
+ float: none;
+ width: 1%;
+ border-left: 1px solid #d2d2d2; }
+
+.tabs.tabs-justified > li.active,
+.tabs.promo-tabs > li.active {
+ position: relative;
+ z-index: 1000; }
+
+.tabs.tabs-justified > li > a {
+ padding-right: 5px;
+ padding-left: 5px; }
+
+.tabs.tabs-justified > li > a,
+.tabs.promo-tabs > li > a {
+ text-align: center; }
+
+.tabs.promo-tabs > li > a {
+ padding: 0;
+ margin: 0;
+ border-radius: 0;
+ border: none;
+ color: #0568ae;
+ font-size: 1.2rem;
+ text-align: center;
+ padding: 6px 10px 10px;
+ border-top: 4px solid #e6e6e6;
+ filter: none;
+ border-bottom: 1px solid #d2d2d2;
+ background-color: #f9f9f9; }
+
+.tabs > li:last-child > a {
+ margin-right: 0; }
+
+.tabs.promo-tabs > li.active > a {
+ color: #333333;
+ border-top: 4px solid #ea7400;
+ border-bottom-color: white;
+ background-color: #fff !important;
+ filter: none;
+ cursor: default; }
+
+.tabs.promo-tabs > li:first-child {
+ border-left: none; }
+
+.tabs.promo-tabs > li > a img {
+ max-width: inherit;
+ max-height: 39px;
+ margin: 0 auto 5px auto;
+ display: block; }
+
+.tabbable:before,
+.tabbable:after {
+ display: table;
+ content: "";
+ line-height: 0; }
+
+.tabbable:after {
+ clear: both; }
+
+.tab-content {
+ overflow: auto;
+ border: 1px solid #e6e6e6; }
+
+.tabs.promo-tabs + .tab-content {
+ border: none;
+ border-bottom: 1px solid #e6e6e6; }
+
+.tab-content > .tab-pane {
+ padding: 10px 15px; }
+
+.tab-content.noborder {
+ border: none; }
+
+.tab-content.noborder > .tab-pane {
+ padding: 0; }
+
+.tab-content > .tab-pane {
+ display: none; }
+
+.tab-content > .active {
+ display: block; }
+
+.tabs.promo-tabs > li > a {
+ font-size: 2.0rem;
+ height: 70px;
+ padding: 20px 20px 24px;
+ background-color: #FFFFFF;
+ border-top: 5px solid #FFFFFF;
+ white-space: nowrap; }
+
+.tabs.promo-tabs > li.active > a {
+ border-top: 5px solid #0574ac; }
+
+.tabs.promo-tabs > li > a:hover {
+ color: #333333; }
+
+.tabs.promo-tabs > li {
+ width: auto; }
+
+.tabs > li[disabled="disabled"] > a:hover {
+ cursor: not-allowed; }
+
+.b2b-tags {
+ background-color: #f2f2f2;
+ -webkit-transition: all .3s ease-out;
+ -moz-transition: all .3s ease-out;
+ transition: all .3s ease-out;
+ margin: 3px 5px 3px 0;
+ padding: 2px 15px;
+ border-radius: 6px;
+ border: 1px solid #c9c9c9;
+ display: inline-block; }
+ .b2b-tags .tags__item {
+ font-size: 14px;
+ vertical-align: baseline;
+ zoom: 1;
+ color: #333; }
+ .b2b-tags .tags__item i {
+ color: #0574ac;
+ font-size: 14px;
+ font-weight: bold;
+ margin-left: 10px; }
+ .b2b-tags .tags__item i:hover {
+ cursor: pointer; }
+ .b2b-tags .tags__item i:focus {
+ outline: thin dotted #666; }
+ .b2b-tags .tags__item:last-child {
+ margin-right: 0; }
+ .b2b-tags .tags__item:hover {
+ text-decoration: none; }
+ .b2b-tags .tags__item:focus {
+ outline: 1px dotted #666; }
+
+.tooltip-size-control {
+ display: block; }
+
+.tooltip {
+ display: inline-block;
+ height: 20px;
+ vertical-align: middle;
+ margin: 1px 0 0 7px; }
+
+p .tooltip {
+ margin: -3px 7px 0 0; }
+
+label .tooltip {
+ margin: 1px 0 0 7px; }
+
+.tooltip .icon-primary-tooltip {
+ background: none;
+ border: none;
+ display: inline-block;
+ font-size: 20px;
+ height: 20px;
+ margin: 0;
+ position: relative;
+ width: 20px; }
+
+.tooltip .icon-primary-tooltip:before {
+ top: 0; }
+
+.tooltip .icon-primary-tooltip:focus {
+ text-decoration: none;
+ outline: 1px dotted black; }
+
+.tooltip.active .icon-primary-tooltip:focus {
+ outline: none; }
+
+.tooltip .arrow {
+ display: none;
+ border-color: transparent;
+ border-style: solid;
+ background-color: #0568ae;
+ height: 20px;
+ width: 20px;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ opacity: 0;
+ transform: rotate(45deg); }
+
+.tooltip.active .icon-primary-tooltip[data-placement="top"] .arrow {
+ display: block;
+ bottom: 32px;
+ top: auto;
+ border-width: 0 1px 1px 0; }
+
+.tooltip.active .icon-primary-tooltip[data-placement="bottom"] .arrow {
+ border-width: 1px 0 0 1px;
+ display: block;
+ bottom: -33px;
+ top: auto; }
+
+.tooltip.active .arrow {
+ opacity: 1; }
+
+.tooltip .closingtooltip {
+ display: block; }
+
+.tooltip.active .closingtooltip {
+ display: none; }
+
+.tooltip-wrapper {
+ position: absolute;
+ margin-top: 20px;
+ left: 15px;
+ right: 15px;
+ display: none;
+ opacity: 0;
+ z-index: 1010;
+ text-align: left; }
+
+.helpertext {
+ background-color: #0568ae;
+ border: 1px solid transparent;
+ border-radius: 6px;
+ color: #fff;
+ display: none;
+ margin: 0;
+ padding: 25px;
+ position: relative;
+ text-align: left;
+ width: 100%;
+ top: 0;
+ z-index: 1009; }
+
+.tooltip .helpertext {
+ position: absolute; }
+
+.tooltip.active .icon-primary-tooltip[data-placement="bottom"] + .tooltip-wrapper .helpertext {
+ bottom: inherit;
+ top: 19px; }
+
+.tooltip.active .icon-primary-tooltip[data-placement="top"] + .tooltip-wrapper .helpertext {
+ top: inherit;
+ bottom: 38px; }
+
+.tooltip.active .tooltip-wrapper {
+ opacity: 1;
+ display: block;
+ margin-top: 0; }
+
+.tooltip.active .tooltip-wrapper .helpertext {
+ display: block; }
+
+.tooltip-onclick .btn.icon-primary-tooltip {
+ border: medium none;
+ box-shadow: none;
+ color: #0568ae;
+ font-size: 20px;
+ height: 34px;
+ line-height: 36px;
+ margin: 0;
+ min-width: 50px;
+ padding: 0;
+ position: absolute;
+ right: 0;
+ top: 0; }
+
+.tooltip-onclick .icon-primary-tooltip:before {
+ display: inline;
+ position: relative; }
+
+.tooltip-onclick textarea + .reset-field + .icon-primary-tooltip {
+ top: 4px;
+ right: 5px;
+ min-width: 40px; }
+
+.tooltip-onclick.active .helpertext:before,
+.tooltip-onfocus.active .helpertext:before {
+ background-color: #0568ae;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 1px 1px 0 0;
+ content: "";
+ display: block;
+ height: 15px;
+ left: 17px;
+ margin: 0;
+ position: absolute;
+ top: -7px;
+ transform: rotate(-45deg);
+ width: 15px; }
+
+.tooltip-onclick.active .helpertext {
+ display: block;
+ opacity: 1;
+ margin: 14px 0 0; }
+
+.tooltip-onclick.active .helpertext:before {
+ left: inherit;
+ right: 18px; }
+
+.tooltip-onclick .reset-field {
+ right: 37px; }
+
+.tooltip-onclick .reset-field:before {
+ position: relative;
+ top: -1px; }
+
+.tooltip-onfocus.active .helpertext {
+ display: block;
+ margin: 14px 0 10px 0; }
+
+.popover-title {
+ display: block;
+ font-size: 14px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-weight: bold;
+ margin-bottom: 8px;
+ white-space: normal; }
+
+.popover-content {
+ display: block;
+ font-size: 12px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ line-height: 1.5rem;
+ white-space: normal; }
+
+.popover-content span,
+.popover-content p {
+ line-height: 1.5rem; }
+
+.popover-content p:last-child {
+ margin-bottom: 0; }
+
+.tooltip .tooltip-element {
+ position: relative; }
+
+.tooltip .icon-primary-tooltip:hover {
+ text-decoration: none; }
+
+.tooltip.active .tooltip-element[data-placement="top"] .arrow {
+ display: block;
+ bottom: 32px;
+ top: auto; }
+
+.tooltip.active .tooltip-element[data-placement="bottom"] .arrow {
+ display: block;
+ border-color: transparent transparent #0574ac;
+ bottom: -33px;
+ top: auto; }
+
+.tooltip.active .tooltip-element[data-placement="bottom"] + .tooltip-wrapper .helpertext {
+ bottom: inherit;
+ top: 19px; }
+
+.tooltip.active .tooltip-element[data-placement="top"] + .tooltip-wrapper .helpertext {
+ top: inherit;
+ bottom: 38px; }
+
+.b2b-tree {
+ padding: 0 10px 0 10px;
+ width: 320px; }
+ .b2b-tree ul {
+ list-style: none;
+ list-style-type: none; }
+ .b2b-tree a {
+ display: block;
+ padding: 0 0 5px 30px;
+ line-height: 22px;
+ margin-left: -10px;
+ font-size: 1.4rem;
+ outline-offset: -1px; }
+ .b2b-tree li:focus {
+ outline: none; }
+ .b2b-tree li:focus > a {
+ outline: thin dotted #666;
+ outline-offset: -1px; }
+ .b2b-tree ul li {
+ border-left: 1px solid #ccc; }
+ .b2b-tree ul li.bg > a {
+ color: #333;
+ background-image: url("../style/images/treebg.png"); }
+ .b2b-tree ul li .b2b-tree-tooltip {
+ display: none;
+ position: absolute;
+ top: -25px;
+ left: 100%;
+ white-space: nowrap;
+ margin-left: 10px;
+ z-index: 1010;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 12px; }
+ .b2b-tree ul li .b2b-tree-tooltip-content {
+ background-color: #0568ae;
+ margin-left: 9px;
+ border-radius: 6px;
+ color: #fff;
+ padding: 25px; }
+ .b2b-tree ul li .b2b-tree-arrow-left {
+ width: 0;
+ height: 0;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ border-right: 10px solid #0568ae;
+ position: absolute;
+ top: 25px; }
+ .b2b-tree ul li.activeTooltip > a .b2b-tree-tooltip {
+ display: block; }
+ .b2b-tree ul ul {
+ padding: 0 0 0 20px; }
+ .b2b-tree ul > li {
+ position: relative;
+ line-height: 18px; }
+ .b2b-tree a > span.b2b-tree-node-icon {
+ background-color: #FFF;
+ display: inline;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ left: -11px;
+ top: 0;
+ line-height: 14px;
+ width: 11px; }
+ .b2b-tree a > span.b2b-tree-node-icon > i {
+ font-size: 20px; }
+ .b2b-tree a:only-child {
+ color: #0574ac; }
+ .b2b-tree a:only-child > span.b2b-tree-node-icon {
+ left: -11px;
+ border-radius: 50%;
+ line-height: 7px;
+ top: 0; }
+ .b2b-tree a:only-child > span.b2b-tree-node-icon > i {
+ background-color: inherit;
+ background: #fff; }
+ .b2b-tree a > span.b2b-tree-node-icon > i.icon-primary-circle {
+ background-color: inherit;
+ background: #fff;
+ font-size: 10px; }
+ .b2b-tree a.b2b-locked-node:after {
+ content: "\ec58";
+ float: right;
+ font-family: 'icoSecurityalerts' !important; }
+ .b2b-tree a:hover .b2b-locked-node:after {
+ text-decoration: none; }
+ .b2b-tree ul li:first-child > a:only-child > span.b2b-tree-node-icon {
+ left: -11px;
+ border-radius: 50%;
+ line-height: 12px; }
+ .b2b-tree ul li:last-child > a:only-child > span.b2b-tree-node-icon {
+ height: 27px;
+ background-color: #fff; }
+ .b2b-tree li a + ul {
+ height: 0;
+ overflow: hidden; }
+ .b2b-tree li a.active + ul {
+ height: auto;
+ overflow: visible; }
+ .b2b-tree li a.grp {
+ font-family: "Omnes-ECOMP-W02-Italic", Arial; }
+ .b2b-tree li a.grp.active {
+ color: #333; }
+ .b2b-tree span.end {
+ left: -6px !important;
+ top: 5px !important; }
+ .b2b-tree span.first-link {
+ width: 3px !important;
+ height: 15px !important;
+ top: 0px !important;
+ left: -2px !important;
+ background: #fff; }
+
+.b2b-tree-checkbox {
+ padding: 0 10px 0 10px;
+ width: 320px; }
+ .b2b-tree-checkbox ul {
+ list-style: none;
+ list-style-type: none; }
+ .b2b-tree-checkbox a {
+ display: block;
+ padding: 0 0 5px 30px;
+ line-height: 22px;
+ margin-left: -10px;
+ font-size: 14px;
+ outline-offset: -1px; }
+ .b2b-tree-checkbox li:focus {
+ outline: none; }
+ .b2b-tree-checkbox li:focus > a {
+ outline: thin dotted #666;
+ outline-offset: -1px; }
+ .b2b-tree-checkbox ul li {
+ border-left: 1px solid #ccc; }
+ .b2b-tree-checkbox ul ul {
+ padding: 0 0 0 20px; }
+ .b2b-tree-checkbox ul > li {
+ position: relative;
+ line-height: 18px; }
+ .b2b-tree-checkbox a > span.nodeIcon {
+ background-color: #FFF;
+ display: inline;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ left: -11px;
+ top: 0;
+ line-height: 14px;
+ width: 11px; }
+ .b2b-tree-checkbox a > span.nodeIcon > i {
+ font-size: 20px; }
+ .b2b-tree-checkbox a > span.nodeIcon.end {
+ margin-top: 10px; }
+ .b2b-tree-checkbox a:only-child {
+ color: #0574ac; }
+ .b2b-tree-checkbox a:only-child > span.nodeIcon {
+ left: -11px;
+ border-radius: 50%;
+ line-height: 7px;
+ top: 0; }
+ .b2b-tree-checkbox a:only-child > span.nodeIcon > i {
+ background-color: inherit;
+ background: #fff; }
+ .b2b-tree-checkbox a > span.nodeIcon > i.icon-primary-circle {
+ background-color: inherit;
+ background: #fff;
+ font-size: 10px; }
+ .b2b-tree-checkbox ul li:first-child > a:only-child > span {
+ left: -11px;
+ border-radius: 50%;
+ line-height: 12px;
+ top: 0px; }
+ .b2b-tree-checkbox ul li:first-child > a:only-child > span.end {
+ margin-top: 0px; }
+ .b2b-tree-checkbox ul li:first-child > a:only-child > span i.icon-primary-circle {
+ top: 8px; }
+ .b2b-tree-checkbox ul li:last-child > a:only-child > span {
+ height: 34px;
+ background-color: #fff; }
+ .b2b-tree-checkbox li a + ul {
+ height: 0;
+ overflow: hidden; }
+ .b2b-tree-checkbox li a.active + ul {
+ height: auto; }
+ .b2b-tree-checkbox li a.grp {
+ font-family: "Omnes-ECOMP-W02-Italic", Arial; }
+ .b2b-tree-checkbox span.end {
+ left: -6px !important; }
+ .b2b-tree-checkbox .checkbox {
+ margin-bottom: 0px;
+ margin-top: 2px;
+ font-size: 14px; }
+ .b2b-tree-checkbox .checkbox input:indeterminate + .skin:after {
+ content: "\2014";
+ padding-left: 2px;
+ font-family: inherit !important;
+ line-height: inherit !important; }
+ .b2b-tree-checkbox span.first-link {
+ width: 3px !important;
+ height: 15px !important;
+ top: 0px !important;
+ left: -2px !important;
+ background: #fff; }
+
+.b2b-widget-window {
+ width: 147px;
+ right: 5px;
+ top: 60px;
+ position: absolute;
+ border: 1px solid #ccc;
+ background-color: #fff;
+ border-radius: 8px;
+ z-index: 1000; }
+ .b2b-widget-window li {
+ margin: 15px; }
+
+.b2b-widget-container {
+ background-color: #fff;
+ border-radius: 8px;
+ border: 1px solid #ccc;
+ position: relative; }
+ .b2b-widget-container .b2b-widget-header {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #333;
+ height: 55px;
+ padding-left: 15px;
+ padding-top: 19px; }
+ .b2b-widget-container .b2b-widget-header .header {
+ font-size: 18px; }
+ .b2b-widget-container .b2b-widget-header-icons {
+ font-size: 16px;
+ color: #0574ac; }
+
+.b2b-widget-header-icons button {
+ border: none;
+ background: transparent;
+ color: #0574ac; }
+ .b2b-widget-header-icons button:focus {
+ outline-style: solid;
+ outline-width: 1px;
+ outline-color: #0574ac; }
+ .b2b-widget-header-icons button:first-child {
+ margin-right: 0px; }
+
+.b2b-widget-container .b2b-widget-content {
+ height: 325px;
+ margin: 0;
+ padding: 20px;
+ position: relative;
+ border-top: 1px solid #ccc; }
+
+.b2b-widget-content .form-row:first-child {
+ margin-top: 0; }
+
+.b2b-widget-header-icons button.icoControls-gear:focus, .b2b-widget-header-icons button.icon-primary-close:focus {
+ outline: thin dotted #666; }
+
+.b2b-widget-header .icon-primary-close:before {
+ content: '-';
+ display: inline-block;
+ margin: 0;
+ padding: 0;
+ outline: none; }
+
+.b2b-widget-window .arrow_box {
+ background: #fff;
+ border: 1px solid #ccc; }
+
+.b2b-widget-window.arrow_box:after, .b2b-widget-window.arrow_box:before {
+ bottom: 100%;
+ left: 75%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none; }
+
+.b2b-widget-window.arrow_box:after {
+ border-color: rgba(255, 255, 255, 0);
+ border-bottom-color: #fff;
+ border-width: 10px;
+ margin-left: 1px; }
+
+.b2b-widget-window.arrow_box:before {
+ border-color: rgba(204, 204, 204, 0);
+ border-bottom-color: #ccc;
+ border-width: 11px;
+ margin-left: 0px; }
+
+/************************** Overrides for Filters ***************************/
+.filter-container .filter-header h2 {
+ line-height: 1 !important;
+ margin: 0 !important; }
+
+.filter-container .icon-primary-spinner:before {
+ content: none; }
+
+.filter-container .fixed-230-subnav {
+ margin: 10px !important;
+ width: inherit !important; }
+
+.filter-container .unlinked:focus {
+ outline: thin dotted #666 !important; }
+
+.filter-container .unlinked.active {
+ color: inherit !important; }
+
+.filter-container .fixed-230-subnav a > i {
+ background: none; }
+
+.filter-container .fixed-230-subnav ul {
+ margin: 0 0 10px 10px; }
+
+/************************** Overrides for Filters ***************************/
+.row .filter-container {
+ background-color: #fff; }
+
+.filter-header {
+ overflow: hidden;
+ padding: 20px 0;
+ position: relative; }
+
+.filter-header h2 {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 2.4rem;
+ margin-bottom: 0; }
+
+.filter-selected {
+ border-top: 1px solid #ccc;
+ padding-top: 20px; }
+
+.filter-selected > span {
+ font-size: 1.3rem;
+ text-transform: uppercase; }
+
+.filter-selected > a.clear-all-filters {
+ float: right;
+ font-size: 1.4rem; }
+
+.filter-selected > span,
+.filter-selected > a.clear-all-filters {
+ font-family: Omnes-ECOMP-W02-Medium; }
+
+.filter-selected-group {
+ padding-top: 15px; }
+
+.filter-selected-badge {
+ background-color: #f2f2f2;
+ border-radius: 15px;
+ display: inline-block;
+ font-size: 1.4rem;
+ margin-bottom: 10px;
+ padding: 0 0 0 12px; }
+
+.filter-selected-badge .icoControls-optionsoff {
+ background: transparent none repeat scroll 0 0;
+ border: medium none;
+ font-size: 2.5em;
+ margin: 0;
+ padding: 0; }
+
+.filters .fixed-230-subnav > ng-transclude > div:first-child {
+ border-top: 1px solid #ccc; }
+
+.filters .fixed-230-subnav > ng-transclude > div {
+ border-bottom: 1px solid #ccc; }
+
+.filter-results {
+ align-items: center;
+ border-bottom: 1px solid #ccc;
+ display: flex;
+ flex-wrap: wrap;
+ height: 50px;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between; }
+
+.filter-results-sortby > span {
+ text-transform: uppercase; }
+
+.filter-results-view .icon-primary-content-gridguide {
+ font-size: 2em;
+ margin-right: 0; }
+
+.filter-container .fixed-230-subnav > ng-transclude > div > a {
+ font-size: 1.8rem;
+ margin: 0;
+ padding: 15px 20px 15px 0;
+ color: #0574ac !important;
+ cursor: pointer !important;
+ font-family: "Omnes-ECOMP-W02" !important;
+ outline-offset: inherit !important;
+ position: relative;
+ height: auto;
+ width: auto; }
+
+.filter-container .fixed-230-subnav a > i {
+ right: 0;
+ top: 15px; }
+
+.filter-container .fixed-230-subnav .icon-primary-collapsed:before, .filter-container .fixed-230-subnav .icon-primary-expanded:before {
+ float: right; }
+
+.filter-container .fixed-230-subnav ul.collapse {
+ position: inherit;
+ transition: height 0.5s ease;
+ height: 0;
+ overflow: hidden; }
+
+.filter-container .checkbox .icon-primary-spinner {
+ height: 24px;
+ position: absolute;
+ width: 24px; }
+
+.fixed-230-subnav.affix {
+ margin: -28px 0 0; }
+
+#nav-menu .b2b-menu,
+#nav-menu .fixed-230-subnav {
+ margin: 0; }
+
+.b2b-menu > li,
+.fixed-230-subnav > div {
+ border-bottom: 1px solid #ccc;
+ line-height: 4.0rem; }
+
+.b2b-menu > li:first-child,
+.fixed-230-subnav > li:first-child {
+ border-top: 1px solid #ccc; }
+
+.b2b-menu div > a,
+.fixed-230-subnav div > a {
+ color: #0574ac;
+ cursor: pointer;
+ display: block;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 1.4rem;
+ margin: 0;
+ outline-offset: -1px;
+ padding: 0 10px;
+ position: relative; }
+
+.fixed-230-subnav div > a.live {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ color: #666; }
+
+.fixed-230-subnav > ng-transclude > div li > a {
+ display: block;
+ font-size: 1.4rem;
+ line-height: 20px; }
+
+.fixed-230-subnav > ng-transclude > div li > a.active {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ text-decoration: none;
+ color: #666; }
+
+#nav-menu .fixed-230-subnav a > i {
+ top: 10px; }
+
+.fixed-230-subnav > li > a.active > i:after {
+ display: none; }
+
+.b2b-menu ul,
+.fixed-230-subnav ul {
+ margin: 0 0 10px 0; }
+
+.b2b-menu ul div a,
+.fixed-230-subnav ul div a {
+ padding: 0 10px; }
+
+.unlinked {
+ outline: medium none !important;
+ text-decoration: none !important; }
+
+@media (max-width: 1024px) {
+ .filter-container .fixed-230-subnav {
+ margin: 0 20px;
+ width: auto; }
+ .filter-container .fixed-230-subnav > li {
+ margin: 0; }
+ .row .filter-container {
+ display: none;
+ height: 100%;
+ left: 0;
+ position: fixed;
+ overflow: auto;
+ top: 0;
+ transition: all 0.5s ease 0s;
+ width: 285px;
+ z-index: 9999; }
+ .filter-header {
+ padding-left: 20px; }
+ .filter-selected {
+ margin: 0 20px 10px; } }
+
+.b2b-pane-selector-wrapper {
+ width: 100%;
+ display: block;
+ border-top: solid 1px #ccc;
+ border-bottom: solid 1px #ccc; }
+ .b2b-pane-selector-wrapper .side-nav {
+ width: 20% !important;
+ display: inline-block;
+ float: left; }
+ .b2b-pane-selector-wrapper .pane-container {
+ width: 80%;
+ vertical-align: top;
+ margin: 0;
+ padding-top: 30px;
+ border-left: solid 1px #ccc;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ display: none; }
+ .b2b-pane-selector-wrapper .pane-container.active {
+ display: inline-block; }
+ .b2b-pane-selector-wrapper .pane-container .pane-container-top {
+ padding-left: 15px; }
+ .b2b-pane-selector-wrapper .pane-container .panes {
+ display: -webkit-flex;
+ display: flex;
+ border-top: solid 1px #ccc;
+ margin-top: 30px; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block {
+ height: inherit;
+ overflow-y: auto;
+ border-right: solid 1px #ccc;
+ position: relative;
+ flex: 1;
+ -webkit-flex: 1;
+ /* Safari 6.1+ */
+ -ms-flex: 1;
+ /* IE 10 */ }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block:focus {
+ outline: dotted 1px #333333; }
+ .b2b-pane-selector-wrapper .pane-container .search-block {
+ position: relative;
+ float: right; }
+ .b2b-pane-selector-wrapper .pane-container .search-block input[type="search"]:focus {
+ padding-right: 40px; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row p {
+ margin-top: 15px; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block div {
+ border-bottom: solid 1px #ccc; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row {
+ display: block;
+ padding: 19px 14px 19px 14px;
+ margin-top: 0px;
+ border: dotted 1px transparent;
+ border-bottom: solid 1px #ccc; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row:focus {
+ border: dotted 1px #333333 !important; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row:last-child {
+ border-bottom: none; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block > .no-content {
+ text-align: center;
+ border-bottom: none;
+ display: block;
+ position: absolute;
+ top: 45%;
+ left: 0;
+ right: 0; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block div:last-child {
+ border-bottom: none; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row span.margin-chk {
+ margin: 15px 15px 0px 15px;
+ float: left; }
+ .b2b-pane-selector-wrapper .pane-container .panes div.pane-block .form-row .checkbox-selectall {
+ margin: 0px 0 0 24px !important; }
+ .b2b-pane-selector-wrapper .side-nav li {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ border: none;
+ border-top: solid 1px #ccc;
+ display: block !important;
+ width: auto !important;
+ margin-left: 0px !important; }
+ .b2b-pane-selector-wrapper .side-nav li.active {
+ background-color: #f6f6f6;
+ position: inherit !important; }
+ .b2b-pane-selector-wrapper .side-nav li.active > a {
+ font-size: 16px;
+ color: #333;
+ text-decoration: none;
+ border: none;
+ background-color: transparent;
+ padding: 20px 15px;
+ display: block;
+ height: auto;
+ border-left: 4px solid #0574ac; }
+ .b2b-pane-selector-wrapper .side-nav li > a {
+ font-size: 16px;
+ color: #333;
+ text-decoration: none;
+ border: none;
+ background-color: transparent;
+ padding: 20px 15px;
+ display: block;
+ height: auto;
+ text-align: left; }
+ .b2b-pane-selector-wrapper .side-nav li > a:focus {
+ border-right: dotted 1px #333333; }
+ .b2b-pane-selector-wrapper .side-nav li:first-child {
+ border-top: none;
+ margin-left: none !important; }
+/********************* Utility CSS Starts **********************/
+.offscreen-text {
+ position: absolute;
+ left: -10000px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden; }
+
+/********************* Utility CSS Ends **********************/
+/* Fix for alignment issue on Cancel link inside modal */
+.b2b-modal-footer > .cta-button-group {
+ line-height: 40px; }
+
+/* .att-dark-green { // Not used
+ color: #007a3e;
+} */
+.colors-off-msg {
+ display: none; }
+
+button .colors-off-msg {
+ position: relative; }
+
+.ds2-no-colors .colors-off-msg {
+ display: block; }
+
+.ds2-no-colors [data-colordatatext] button .colors-off-msg {
+ font-size: 1.1rem;
+ line-height: normal;
+ padding: 5px 0;
+ position: absolute;
+ top: 0;
+ white-space: normal;
+ width: 60px; }
+
+/* Not used
+.make-all-white * {
+ color: #fff;
+}
+.make-all-white a {
+ text-decoration: underline;
+} */
+.loader > span {
+ display: block;
+ padding-top: 20px; }
+
+.modal > .loader {
+ left: 50%;
+ margin-left: -25px;
+ margin-top: -25px;
+ position: absolute;
+ top: 50%; }
+
+#pageLevelLoader.modal {
+ background-color: transparent;
+ border: none;
+ box-shadow: none;
+ top: 40%; }
+
+.modal.fade .loader {
+ display: none; }
+
+.modal.fade.in .loader {
+ display: block; }
+
+.btn.disabled[data-loading-text] {
+ padding: 0 19px 0 18px;
+ line-height: 46px; }
+
+.btn.disabled[data-loading-text] img {
+ position: relative;
+ top: 2px; }
+
+/* Seems to already be in docs.css
+.fixed-230.leftnav {
+ position: relative;
+}
+.fixed-230-subnav {
+ margin: 10px;
+}
+.fixed-230-subnav > li:first-child {
+ border-top: none;
+}
+.fixed-230-subnav > li {
+ border-bottom: 1px solid #d2d2d2;
+}
+.fixed-230-subnav > li > a {
+ display: block;
+ font-size: 1.4rem;
+ line-height: normal;
+ margin: 0 -9px;
+ padding: 11px 35px 12px 9px;
+ outline-offset: 0;
+ position: relative;
+}
+.fixed-230-subnav > li > a.live {
+ color: #333333;
+ font-family: "Omnes-ECOMP-W02-Medium";
+}
+.fixed-230-subnav a > i {
+ right: 10px;
+ margin: 0;
+ position: absolute;
+ top: 10px;
+}
+.fixed-230-subnav a > i:after {
+ display: none;
+}
+.fixed-230-subnav > li li > a {
+ display: block;
+ font-size: 1.4rem;
+ line-height: 18px;
+}
+.fixed-230-subnav > li li > a.active {
+ color: #333333;
+ font-family: "Omnes-ECOMP-W02-Medium";
+ text-decoration: none;
+}
+.fixed-230-subnav ul {
+ margin: 0 0 10px;
+} */
+.unlinked {
+ color: #0568ae !important;
+ font-family: "Omnes-ECOMP-W02" !important; }
+
+.unlinked.active {
+ color: inherit !important; }
+
+/* @media (max-width: 767px) {
+ .row.has-leftnav {
+ flex-wrap: wrap;
+ }
+ .row.has-leftnav .fluid-space {
+ padding-right: 0;
+ }
+ .row .fixed-230 {
+ background-color: #fff;
+ width: auto;
+ }
+ .row .leftnav {
+ background-color: #fff !important;
+ display: block !important;
+ }
+ .fixed-230-subnav {
+ margin: 10px 0 0;
+ width: 100%;
+ }
+ .fixed-230-subnav > li {
+ margin-left: -15px;
+ margin-right: -15px;
+ }
+ .fixed-230-subnav > li:first-child {
+ border-top: 1px solid #d2d2d2;
+ }
+ .fixed-230-subnav > li > a {
+ margin: 0;
+ }
+ .fixed-230-subnav a:hover,
+ .fixed-230-subnav a:focus {
+ text-decoration: none !important;
+ }
+ .fixed-230-subnav > li li > a {
+ padding: 5px 10px;
+ }
+ .fixed-230-subnav > li li > a.active {
+ color: inherit;
+ font-family: "Omnes-ECOMP-W02-Medium";
+ }
+} */
+@keyframes DOMinsertion {
+ from {
+ outline-color: transparent; }
+ to {
+ outline-color: transparent; } }
+
+@-moz-keyframes DOMinsertion {
+ from {
+ outline-color: transparent; }
+ to {
+ outline-color: transparent; } }
+
+@-webkit-keyframes DOMinsertion {
+ from {
+ outline-color: transparent; }
+ to {
+ outline-color: transparent; } }
+
+@-ms-keyframes DOMinsertion {
+ from {
+ outline-color: transparent; }
+ to {
+ outline-color: transparent; } }
+
+@-o-keyframes DOMinsertion {
+ from {
+ outline-color: transparent; }
+ to {
+ outline-color: transparent; } }
+
+.ajaxed,
+.modal.fade.in .b2b-modal-header,
+.modal.fade.in .b2b-modal-body,
+.modal.fade.in .b2b-modal-footer {
+ animation-duration: 0.01s;
+ -o-animation-duration: 0.01s;
+ -ms-animation-duration: 0.01s;
+ -moz-animation-duration: 0.01s;
+ -webkit-animation-duration: 0.01s;
+ animation-name: DOMinsertion;
+ -o-animation-name: DOMinsertion;
+ -ms-animation-name: DOMinsertion;
+ -moz-animation-name: DOMinsertion;
+ -webkit-animation-name: DOMinsertion; }
+
+.dda-css-override ul.nav-tabs {
+ margin-bottom: 0; }
+
+.dda-css-override div.tab-content {
+ margin-top: 0;
+ border-top: none; }
+
+.dda-css-override .tab-content .prettyprint, .dda-css-override .usage .prettyprint {
+ max-height: 500px;
+ overflow-y: auto; }
+
+.formsWithinProcessButton {
+ margin-right: 0px; }
+
+.heading-sub-section-form {
+ font-size: 2.4rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px;
+ margin-top: 10px; }
+
+.heading-small-form {
+ font-size: 1.6rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-top: 0px; }
+
+.icon-primary-form-sizeL {
+ font-size: 50px; }
+
+.icon-primary-form-size {
+ font-size: 30px; }
+
+.spanformfix {
+ margin-right: 15px !important; }
+
+@media (max-width: 767px) {
+ .heading-sub-section-form {
+ font-size: 1.8rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-bottom: 20px;
+ padding-top: 10px;
+ margin-top: 30px; }
+ .heading-small-form {
+ font-size: 1.4rem;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ margin-top: 0px; } }
+
+@media (max-width: 479px) {
+ .icon-primary-form-resizeL {
+ display: none; }
+ .icon-primary-form-resize {
+ display: none; }
+ .heading-center-form {
+ margin-left: 20px; } }
+
+@media (min-width: 480px) {
+ .icon-primary-form-resizeL {
+ display: none; }
+ .icon-primary-form-resize {
+ display: inherit; }
+ .icon-primary-center-min {
+ margin-top: 30px; } }
+
+@media (min-width: 768px) {
+ .icon-primary-form-resizeL {
+ display: inherit;
+ margin-top: 30px; }
+ .icon-primary-form-resize {
+ display: none; }
+ .center-form-align {
+ margin-top: 35px; } }
+
+@media (min-width: 1024px) {
+ .icon-primary-form-resizeL {
+ display: inherit;
+ margin-top: 0px; }
+ .icon-primary-form-resize {
+ display: none; }
+ .center-form-align {
+ margin-top: 5px; } }
+
+.data-row.has-button td.col-1 {
+ padding: 0; }
+
+.tab-content > .tab-pane {
+ display: none; }
+
+.tab-content > .active {
+ display: block; }
+
+.icon-primary-circle:before {
+ background-image: url("data:image/svg+xml,%3Csvg%20baseProfile%3D%22tiny%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%3E%3Ccircle%20fill%3D%22transparent%22%20stroke%3D%22%23666%22%20stroke-miterlimit%3D%2210%22%20cx%3D%2218%22%20cy%3D%2218%22%20r%3D%2216%22%2F%3E%3C%2Fsvg%3E");
+ content: "";
+ position: absolute;
+ top: 0;
+ z-index: 1; }
+
+.icon-primary-primary-circle:before {
+ background-image: url("data:image/svg+xml,%3Csvg%20baseProfile%3D%22tiny%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%3E%3Ccircle%20fill%3D%22transparent%22%20stroke%3D%22%23666%22%20stroke-miterlimit%3D%2210%22%20cx%3D%2218%22%20cy%3D%2218%22%20r%3D%2216%22%2F%3E%3C%2Fsvg%3E");
+ content: "";
+ position: absolute;
+ top: 0;
+ z-index: 1; }
+/* Flyout inputs color is not aligned */
+textarea, input {
+ color: #333; }
+
+.isIE .btn-primary.btn:focus::after,
+.isIE .btn-specialty.btn:focus::after,
+.isIE .btn-alt.btn:focus::after {
+ border: 1px dashed #fff !important; }
+.b2b-config-section-container {
+ height: auto;
+ min-height: 330px;
+ width: 815px;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ display: inline-table;
+ border-radius: 6px; }
+
+.b2b-config-section-first-div {
+ border-right: 1px solid #ccc;
+ height: auto;
+ min-height: 330px; }
+
+.b2b-config-section-icon-primary-font {
+ font-size: 50px;
+ height: 31px;
+ line-height: 31px; }
+
+.b2b-config-section-padding {
+ padding: 20px 20px 15px 15px;
+ height: auto; }
+
+.b2b-config-sec-flyout {
+ position: relative;
+ left: 10px;
+ float: right;
+ color: #0574ac;
+ font-size: 16px;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+.b2b-config-sec-divider {
+ border-bottom: 1px solid #ccc; }
+
+.b2b-confi-sec-span-border {
+ border-right: 1px solid;
+ height: auto; }
+
+.b2b-config-sec-speed-div {
+ text-align: center;
+ margin-top: 20px; }
+
+.b2b-config-sec-label-font {
+ font-size: 16px; }
+
+.b2b-config-sec-expander-main {
+ padding: 0 5px 0px 15px; }
+
+.b2b-config-sec-expander-body .b2b-config-vlan-padding {
+ padding: 5px 15px 10px 0px; }
+
+.b2b-conif-sec-row-height {
+ height: 110px; }
+
+.b2b-config-sec-expander-body {
+ font-size: 14px; }
+ .b2b-config-sec-expander-body .b2b-config-vlan-data {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ padding-left: 15px; }
+
+.b2b-config-sec-expander-body-first-div {
+ border-top: 1px solid #ccc; }
+
+.b2b-config-sec-expander-body .tooltip {
+ position: static;
+ opacity: 1; }
+
+.b2b-config-section-container .row > [class*="span"] {
+ margin-right: 0px; }
+
+.b2b-config-vlan-icons {
+ font-size: 16px;
+ float: right;
+ margin-right: 0px; }
+
+.b2b-config-section-container .span6 {
+ width: 50%; }
+
+.b2b-config-sec-data-link-style {
+ position: relative;
+ left: 95%;
+ top: 30px;
+ border-radius: 50%;
+ width: 23px;
+ height: 23px;
+ background: #fff;
+ border: 1px solid #ccc;
+ color: #666666; }
+
+.b2b-config-sec-text-align {
+ text-align: center;
+ margin-top: 15px;
+ margin-bottom: 35px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 14px;
+ color: #333333; }
+
+.b2b-config-port-text-align {
+ text-align: center;
+ margin-top: 15px;
+ margin-bottom: 8px;
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 14px;
+ color: #333333; }
+
+.b2b-config-port-text-label {
+ margin-top: 6px;
+ margin-bottom: 8px;
+ font-size: 14px;
+ text-align: center; }
+
+.b2b-confi-sec-last-div p {
+ font-size: 14px;
+ padding: 10px 15px 0 15px; }
+
+.b2b-confi-sec-router-label {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 16px;
+ color: #333333;
+ float: left;
+ width: 100%;
+ margin-bottom: 7px; }
+
+.b2b-config-vlan-label {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 14px;
+ color: #333333;
+ margin-top: 1px;
+ margin-bottom: 9px; }
+
+.b2b-config-vlan-info {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ color: #333333;
+ margin-bottom: 1px; }
+ .b2b-config-vlan-info .icon-misc-pen {
+ padding-left: 7px; }
+
+.b2b-confi-sec-model-label {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ color: #333333; }
+
+.b2b-confi-sec-router-info {
+ float: left;
+ width: 62%; }
+
+.b2b-config-sec-speed-sec {
+ border-right: 1px solid #ccc; }
+
+.b2b-config-sec-speed-label {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 20px;
+ color: #333333;
+ text-align: center; }
+ .b2b-config-sec-speed-label i {
+ margin-left: 15px;
+ font-size: 16px; }
+
+.b2b-config-sec-yellow-flag-div {
+ width: 1.6%;
+ background-color: #ffb18c; }
+
+.b2b-config-sec-expander-icons {
+ margin-top: 6px; }
+ .b2b-config-sec-expander-icons .icon-misc-trash {
+ margin-right: 10px; }
+
+.b2b-config-sec-yellow-flag .b2b-config-sec-expander-icons {
+ left: 40px; }
+
+.b2b-config-sec-expander-body-icons .icon-misc-pen {
+ position: relative;
+ left: 18px; }
+.b2b-directory-listing .listBox {
+ height: 310px;
+ width: 450px;
+ padding-left: 1px;
+ padding-right: 1px;
+ font-family: "Omnes-ECOMP-W02", Arial; }
+
+.b2b-directory-listing .listBox:focus {
+ outline: thin dotted #666; }
+
+.b2b-directory-listing .b2b-directory-listing-no-results {
+ font-weight: bold; }
+
+.b2b-directory-listing .b2b-directory-listing-list {
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #5a5a5a;
+ overflow-x: hidden;
+ position: relative;
+ height: 300px;
+ border: 1px solid #333;
+ border-radius: 6px;
+ margin-bottom: 10px; }
+
+.b2b-directory-listing .b2b-directory-listing-item {
+ margin: 1px;
+ border: 1px solid transparent;
+ outline: none;
+ text-align: left;
+ overflow: hidden;
+ cursor: pointer;
+ padding-top: 13px;
+ padding-bottom: 7px;
+ padding-left: 15px;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ word-wrap: break-word; }
+ .b2b-directory-listing .b2b-directory-listing-item:focus {
+ border: 1px #3399FF solid; }
+
+.b2b-directory-listing .b2b-directory-listing-item-selected {
+ color: #fff;
+ background-color: #3399FF; }
+
+.b2b-directory-listing input[type="text"] {
+ padding-right: 30px; }
+ .b2b-directory-listing input[type="text"]:focus, .b2b-directory-listing input[type="text"]:hover {
+ padding-right: 30px; }
+
+.b2b-directory-listing .row .btns {
+ margin-right: 90px;
+ margin-left: -115px;
+ margin-top: 100px; }
+
+.b2b-directory-listing .btn-right {
+ margin-bottom: 15px !important; }
+ .b2b-directory-listing .btn-right:after {
+ content: " \27A1"; }
+
+.b2b-directory-listing .btn-left {
+ margin-top: 10px !important; }
+
+.b2b-directory-listing .btn-remove {
+ margin-right: auto !important;
+ margin-bottom: 15px; }
+
+.b2b-directory-listing .btn-remove-all {
+ margin-top: 0;
+ margin-bottom: 61px !important;
+ /* need to be removed */
+ margin-right: auto !important; }
+
+.b2b-directory-listing .btn-add-all {
+ margin-top: 0;
+ margin-bottom: 61px !important; }
+
+.b2b-directory-listing .btn-left:before {
+ content: "\2B05 "; }
+
+.b2b-directory-listing .btn-search[class*="btn"] {
+ right: 0.09rem; }
+
+.b2b-directory-listing .btn {
+ width: 130px; }
+
+.b2b-directory-listing-disabled {
+ cursor: not-allowed; }
+
+.b2b-directory-listing-label-heading {
+ margin-top: 24px;
+ padding-bottom: 5px; }
+
+.b2b-dl-list-box option {
+ padding-top: 13px;
+ padding-bottom: 7px;
+ padding-left: 15px; }
+
+.b2b-dl-modal-button-div {
+ padding-top: 110px;
+ text-align: center; }
+.b2b-tmpl-notification-card {
+ border-radius: 6px;
+ height: auto;
+ width: 420px;
+ background-color: #ffffff;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ overflow: hidden; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-header {
+ padding-left: 30px;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ color: #333333;
+ font-size: 24px;
+ margin-top: 2px;
+ display: inline-block;
+ min-height: 60px;
+ position: relative; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-body {
+ padding: 0 30px 20px;
+ position: relative; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-header-title {
+ margin-top: 10px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-corner-button {
+ box-shadow: 0 -50px 0 0 #f2f2f2 inset;
+ height: 69px;
+ position: absolute;
+ border-color: #f2f2f2 #f2f2f2 transparent transparent;
+ border-style: solid;
+ border-width: 35px;
+ height: 0;
+ right: -295px;
+ top: -4px;
+ width: 69px;
+ /*Old properties */
+ box-shadow: none;
+ transform: none; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-corner-button .close {
+ height: 48px;
+ right: -40px;
+ top: -40px;
+ width: 48px;
+ position: relative;
+ /*Old properties */
+ transform: none; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-corner-button .close:before {
+ color: #0568ae;
+ display: block;
+ font-size: 20px;
+ height: auto;
+ right: -4px;
+ top: 4px;
+ width: auto;
+ /*Old properties */
+ left: auto;
+ height: auto;
+ bottom: auto; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-corner-button .close:focus {
+ outline: 1px dotted black; }
+ .b2b-tmpl-notification-card button.close {
+ -webkit-appearance: none;
+ moz-appearance: none;
+ appearance: none; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-icon-primary-cirlce {
+ width: 30px;
+ height: 30px;
+ border-radius: 50%; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-outer-cirlce {
+ background: #f0f5f5;
+ border-radius: 50%;
+ height: 16px;
+ width: 16px;
+ vertical-align: middle; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-inner-cirlce {
+ background: #fff;
+ width: 22px;
+ height: 22px;
+ position: relative;
+ border-radius: 50%;
+ display: block;
+ left: 4px;
+ top: 4px;
+ border: 1px solid #767676; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-row {
+ padding-top: 10px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-sub-header {
+ margin-top: 0px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-favourite-view-item {
+ background-color: #fff;
+ margin-top: 25px;
+ border-top: 1px solid #ccc; }
+ .b2b-tmpl-notification-card .b2b-tmpl-favourite-view-item .cta-button-group {
+ line-height: 40px;
+ padding-top: 20px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-edit-section .cta-button-group {
+ line-height: 40px;
+ padding-top: 15px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-add-item-container {
+ padding-top: 30px; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-link-active {
+ pointer-events: none;
+ cursor: default;
+ color: #ccc; }
+ .b2b-tmpl-notification-card .b2b-tmpl-card-cursor:hover {
+ cursor: pointer; }
+.b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-icon {
+ text-align: center;
+ margin-top: 91px; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-icon i {
+ font-size: 99px;
+ color: #1b7e28; }
+
+.b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-heading {
+ color: #333333;
+ text-align: center;
+ margin-top: 20px; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-heading h1 {
+ font-size: 38px; }
+
+.b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-sub-heading {
+ color: #333333;
+ text-align: center; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-sub-heading h5 {
+ font-size: 18px; }
+
+.b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-info {
+ padding-left: 18%;
+ font-size: 16px;
+ margin-top: 20px; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-info ul {
+ list-style-type: disc;
+ list-style-position: inside; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-info li {
+ padding-top: 5px; }
+
+.b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-link-section {
+ font-size: 15px;
+ color: #0574ac;
+ margin-top: 20px;
+ text-align: center;
+ margin-bottom: 55px; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-link-section .b2b-tmpl-order-confirmation-link {
+ margin-right: 8%; }
+ .b2b-tmpl-order-confirmation .b2b-tmpl-order-confirmation-link-section a {
+ cursor: pointer; }
+.b2b-tmpl-profile-block-container {
+ min-height: 200px;
+ height: auto;
+ background-color: #fff;
+ border-radius: 8px;
+ border: 1px solid #ccc;
+ box-shadow: 0px 1px 1px 1px #ccc;
+ display: inline-table;
+ margin: 15px 15px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-title {
+ font-weight: bold; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-footer {
+ margin-bottom: 12px;
+ margin-top: 5px;
+ height: 35px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p {
+ word-wrap: break-word;
+ height: 61px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p:first-child {
+ margin-top: 10px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p:after {
+ content: ' ';
+ display: block;
+ border: 0.2px solid #ccc;
+ margin-top: 12px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details .radio {
+ margin-left: 15px;
+ height: 30px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p, .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details div {
+ padding: 2px 7px;
+ font-size: 14px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details .radio-label, .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details a {
+ font-size: 14px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p label, .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-details p span {
+ padding-left: 10px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-approval-icon {
+ color: #1b7e28;
+ float: right;
+ position: relative;
+ left: 10px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-approval-icon i {
+ color: #1b7e28;
+ float: right; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-link {
+ float: right;
+ position: relative;
+ left: -4px; }
+ .b2b-tmpl-profile-block-container a.link-profile {
+ position: relative;
+ left: -5px;
+ float: right;
+ margin-bottom: 16px; }
+ .b2b-tmpl-profile-block-container .b2b-tmpl-profile-block-radio {
+ position: relative;
+ top: -5px; }
+.b2b-static-route-container {
+ padding-left: 32px;
+ display: inline-block; }
+
+.b2b-static-route-label-heading {
+ font-family: "Omnes-ECOMP-W02-Medium", Arial;
+ font-size: 16px !important;
+ color: #333333;
+ font-style: normal;
+ text-align: left; }
+
+label.b2b-static-route-label-heading {
+ margin-bottom: 12px;
+ margin-top: 15px;
+ display: block; }
+
+#b2b-static-route-input {
+ margin: 5px 0 5px; }
+
+.b2b-static-route-list {
+ margin-bottom: 30px;
+ width: 216px;
+ float: left;
+ margin-right: 20px;
+ max-height: 540px;
+ overflow-y: auto; }
+ .b2b-static-route-list .status-text {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ outline: 0; }
+
+.b2b-static-route-list-item {
+ border: 1px #cccccc solid;
+ font-family: "Omnes-ECOMP-W02", Arial;
+ font-size: 14px;
+ display: flex;
+ cursor: pointer; }
+ .b2b-static-route-list-item > .status-bar {
+ padding: 20px 0 20px;
+ background-color: #ea7400;
+ border-radius: 0;
+ width: 10px;
+ display: inline-block;
+ margin-right: 20px;
+ height: 100%;
+ float: left; }
+ .b2b-static-route-list-item > .status-bar:after {
+ content: '.';
+ visibility: hidden; }
+ .b2b-static-route-list-item > .status-bar-unedited {
+ padding: 20px 0 20px;
+ background-color: #ffb81c;
+ border-radius: 0;
+ width: 10px;
+ display: inline-block;
+ margin-right: 20px;
+ height: 100%;
+ float: left;
+ background-color: transparent; }
+ .b2b-static-route-list-item > .status-bar-unedited:after {
+ content: '.';
+ visibility: hidden; }
+
+.b2b-static-route-list-item:focus {
+ outline: 1px dashed #00f; }
+
+.b2b-static-route-list-item--selected {
+ background: #f2f2f2; }
+
+.b2b-static-route-content {
+ display: inline-block; }
+
+
+/*
+To Remove later
+*/
+
+.selectWrap::after {
+ align-items: center;
+ background-position: 7px 7px;
+ background-repeat: no-repeat;
+ background-size: auto 23px;
+ border-left: 1px solid transparent;
+ color: #0568ae;
+ display: flex;
+ font-size: 23px;
+ height: 36px;
+ margin-right: 0;
+ overflow: hidden;
+ position: absolute;
+ right: 0;
+ text-indent: 7px;
+ top: 0;
+ user-select: none;
+ width: 41px;
+ z-index: 0;
+ position: absolute !important;
+ display: flex !important;
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/horse_shoe.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/horse_shoe.jpg
new file mode 100644
index 00000000..a53eb4ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/horse_shoe.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/icon-flyout.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/icon-flyout.png
new file mode 100644
index 00000000..88e10332
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/icon-flyout.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/treebg.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/treebg.png
new file mode 100644
index 00000000..32ed1b7c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/treebg.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/widget-thumbnail.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/widget-thumbnail.png
new file mode 100644
index 00000000..5fbf93c2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/css/b2b-angular/style/images/widget-thumbnail.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js
new file mode 100644
index 00000000..0e62a349
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js
@@ -0,0 +1,22054 @@
+/*! b2b-angular-library - v1.0.1 - Last updated: 2017-03-02. Copyright (c) 2016 AT&T Services, Inc. */
+angular.module("b2b.att.tpls", ['b2bTemplate/audioPlayer/audioPlayer.html', 'b2bTemplate/audioRecorder/audioRecorder.html', 'b2bTemplate/backToTop/backToTop.html', 'b2bTemplate/boardstrip/b2bAddBoard.html', 'b2bTemplate/boardstrip/b2bBoard.html', 'b2bTemplate/boardstrip/b2bBoardstrip.html', 'b2bTemplate/calendar/datepicker-popup.html', 'b2bTemplate/calendar/datepicker.html', 'b2bTemplate/coachmark/coachmark.html', 'b2bTemplate/dropdowns/b2bDropdownDesktop.html', 'b2bTemplate/dropdowns/b2bDropdownGroupDesktop.html', 'b2bTemplate/dropdowns/b2bDropdownListDesktop.html', 'b2bTemplate/fileUpload/fileUpload.html', 'b2bTemplate/flyout/flyout.html', 'b2bTemplate/flyout/flyoutContent.html', 'b2bTemplate/footer/footer_column_switch_tpl.html', 'b2bTemplate/horizontalTable/horizontalTable.html', 'b2bTemplate/hourPicker/b2bHourpicker.html', 'b2bTemplate/hourPicker/b2bHourpickerPanel.html', 'b2bTemplate/hourPicker/b2bHourpickerValue.html', 'b2bTemplate/leftNavigation/leftNavigation.html', 'b2bTemplate/listbox/listbox.html', 'b2bTemplate/modalsAndAlerts/b2b-backdrop.html', 'b2bTemplate/modalsAndAlerts/b2b-window.html', 'b2bTemplate/monthSelector/monthSelector-popup.html', 'b2bTemplate/monthSelector/monthSelector.html', 'b2bTemplate/monthSelector/monthSelectorLink.html', 'b2bTemplate/pagination/b2b-pagination.html', 'b2bTemplate/paneSelector/paneSelector.html', 'b2bTemplate/paneSelector/paneSelectorPane.html', 'b2bTemplate/profileCard/profileCard-addUser.html', 'b2bTemplate/profileCard/profileCard.html', 'b2bTemplate/searchField/searchField.html', 'b2bTemplate/seekBar/seekBar.html', 'b2bTemplate/slider/slider.html', 'b2bTemplate/spinButton/spinButton.html', 'b2bTemplate/statusTracker/statusTracker.html', 'b2bTemplate/stepTracker/stepTracker.html', 'b2bTemplate/switches/switches-spanish.html', 'b2bTemplate/switches/switches.html', 'b2bTemplate/tableMessages/tableMessage.html', 'b2bTemplate/tables/b2bTable.html', 'b2bTemplate/tables/b2bTableBody.html', 'b2bTemplate/tables/b2bTableHeaderSortable.html', 'b2bTemplate/tables/b2bTableHeaderUnsortable.html', 'b2bTemplate/tableScrollbar/tableScrollbar.html', 'b2bTemplate/tabs/b2bTab.html', 'b2bTemplate/tabs/b2bTabset.html', 'b2bTemplate/treeNav/groupedTree.html', 'b2bTemplate/treeNav/treeMember.html', 'b2bTemplate/treeNav/ungroupedTree.html', 'b2bTemplate/treeNodeCheckbox/groupedTree.html', 'b2bTemplate/treeNodeCheckbox/treeMember.html', 'b2bTemplate/treeNodeCheckbox/ungroupedTree.html']);angular.module("b2b.att", ["b2b.att.tpls", 'b2b.att.addressInputTemplate','b2b.att.arrows','b2b.att.audioPlayer','b2b.att.audioRecorder','b2b.att.backToTop','b2b.att.badgesForAlerts','b2b.att.boardstrip','b2b.att.breadcrumbs','b2b.att.buttonGroups','b2b.att.buttons','b2b.att.calendar','b2b.att.checkboxes','b2b.att.coachmark','b2b.att.configurationSection','b2b.att.directoryListingTemplate','b2b.att.dropdowns','b2b.att.fileUpload','b2b.att.filters','b2b.att.flyout','b2b.att.footer','b2b.att.header','b2b.att.headings','b2b.att.horizontalTable','b2b.att.hourPicker','b2b.att.inputTemplate','b2b.att.leftNavigation','b2b.att.links','b2b.att.listbox','b2b.att.loaderAnimation','b2b.att.messageWrapper','b2b.att.modalsAndAlerts','b2b.att.monthSelector','b2b.att.multiLevelNavigation','b2b.att.multipurposeExpander','b2b.att.notesMessagesAndErrors','b2b.att.notificationCardTemplate','b2b.att.orderConfirmationTemplate','b2b.att.pagination','b2b.att.paneSelector','b2b.att.phoneNumberInput','b2b.att.profileBlockTemplate','b2b.att.profileCard','b2b.att.radios','b2b.att.searchField','b2b.att.seekBar','b2b.att.selectorModule','b2b.att.separators','b2b.att.slider','b2b.att.spinButton','b2b.att.staticRouteTemplate','b2b.att.statusTracker','b2b.att.stepTracker','b2b.att.switches','b2b.att.tableMessages','b2b.att.tables','b2b.att.tableScrollbar','b2b.att.tabs','b2b.att.tagBadges','b2b.att.textArea','b2b.att.tooltipsForForms','b2b.att.treeNav','b2b.att.treeNodeCheckbox','b2b.att.utilities']);/**
+ * @ngdoc directive
+ * @name Template.att:Address Input
+ *
+ * @description
+ * <file src="src/addressInputTemplate/docs/readme.md" />
+ *
+ * @usage
+
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/addressInputTemplate/docs/demo.html" />
+ <file src="src/addressInputTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.addressInputTemplate', ['ngMessages']);
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:arrows
+ *
+ * @description
+ * <file src="src/arrows/docs/readme.md" />
+ *
+ * @usage
+ * Please refer demo.html tab in Example section below.
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/arrows/docs/demo.html" />
+ <file src="src/arrows/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.arrows', []);
+/**
+ * @ngdoc directive
+ * @name Videos, audio & animation.att:Audio Player
+ * @scope
+ * @param {string} audioSrcUrl - MP3 audio source URL or Blob URL
+ * @description
+ * <file src="src/audioPlayer/docs/readme.md" />
+ *
+ * @usage
+ *
+ <div b2b-audio audio-src-url='audioSrcUrl'></div>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/audioPlayer/docs/demo.html" />
+ <file src="src/audioPlayer/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.audioPlayer', ['b2b.att.utilities', 'b2b.att.seekBar'])
+ .constant('AudioPlayerConfig', {
+ 'defaultVolume': 50,
+ 'timeShiftInSeconds': 5
+ })
+ .filter('trustedAudioUrl', ['$sce', function ($sce) {
+ return function (audioFileFullPath) {
+ return audioFileFullPath ? $sce.trustAsResourceUrl(audioFileFullPath) : 'undefined';
+ };
+ }])
+ .directive('b2bAudio', ['$log', '$timeout', 'AudioPlayerConfig', '$compile', 'events', function ($log, $timeout, AudioPlayerConfig, $compile, events) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ scope: {
+ audioSrcUrl: '='
+ },
+ templateUrl: 'b2bTemplate/audioPlayer/audioPlayer.html',
+ controller: function ($scope) {
+
+ $scope.audio = {};
+
+ if (!angular.isDefined($scope.audioSrcUrl)) {
+ $log.warn('b2b-audio : audio-src-url undefined');
+ $scope.audioSrcUrl = undefined;
+ $scope.audio.mp3 = undefined;
+ }
+
+ },
+ link: function (scope, element) {
+ var audioElement = angular.element(element[0].querySelector('audio'))[0];
+ scope.audio.audioElement = audioElement;
+
+ function setAttributes(element, attributes) {
+ Object.keys(attributes).forEach(function (name) {
+ element.setAttribute(name, attributes[name]);
+ });
+ }
+
+ $timeout(function () {
+ // TODO: Replace with DDA Tooltip
+ var seekBarKnob = element[0].querySelector('.b2b-seek-bar-knob');
+ var tooltipObject = {
+ 'tooltip': '{{timeFormatter(audio.currentTime)}}',
+ 'tooltip-placement': 'above',
+ 'tooltip-style': 'blue',
+ 'tooltip-trigger': 'mousedown',
+ 'tooltip-append-to-body': 'false',
+ 'tooltip-offset': '-10',
+ 'refer-by': 'seek-bar-tooltip'
+ };
+ setAttributes(seekBarKnob, tooltipObject);
+ $compile(seekBarKnob)(scope);
+ });
+
+ if (angular.isDefined(scope.audioSrcUrl)) {
+ scope.audio.mp3 = scope.audioSrcUrl;
+ }
+
+ scope.audio.currentTime = 0;
+ scope.audio.currentVolume = AudioPlayerConfig.defaultVolume;
+ scope.audio.timeShiftInSeconds = AudioPlayerConfig.timeShiftInSeconds;
+ scope.isPlayInProgress = false;
+ scope.isReady = false;
+ scope.isAudioDragging = false;
+
+ $timeout(function () {
+ audioElement.load();
+ audioElement.volume = scope.audio.currentVolume / 100;
+ });
+
+ scope.$watch('audioSrcUrl', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ if (!newVal) {
+ $log.warn('b2b-audio : audio-src-url undefined. Please provide a valid URL');
+ }
+
+ scope.audio.mp3 = newVal;
+ $timeout(function () {
+ audioElement.load();
+ });
+ }
+ });
+
+ scope.playAudio = function () {
+ if (scope.isReady) {
+ audioElement.play();
+ }
+ };
+
+ audioElement.onplay = function () {
+ scope.isPlayInProgress = true;
+ scope.$digest();
+ };
+
+ scope.pauseAudio = function () {
+ audioElement.pause();
+ };
+
+ audioElement.onpause = function () {
+ scope.isPlayInProgress = false;
+ scope.$digest();
+ };
+
+ scope.toggleAudio = function () {
+ if (audioElement.paused) {
+ scope.playAudio();
+ } else {
+ scope.pauseAudio();
+ }
+ };
+
+ scope.volumeUp = function (delta) {
+ if (!delta) {
+ delta = 0.1;
+ } else {
+ delta = delta / 100;
+ }
+ audioElement.muted = false;
+ if (audioElement.volume < 1) {
+ audioElement.volume = Math.min((Math.round((audioElement.volume + delta) * 100) / 100), 1);
+ }
+ scope.audio.currentVolume = audioElement.volume * 100;
+ return audioElement.volume;
+ };
+
+ scope.volumeDown = function (delta) {
+ if (!delta) {
+ delta = 0.1;
+ } else {
+ delta = delta / 100;
+ }
+ audioElement.muted = false;
+ if (audioElement.volume > 0) {
+ audioElement.volume = Math.max((Math.round((audioElement.volume - delta) * 100) / 100), 0);
+ }
+ scope.audio.currentVolume = audioElement.volume * 100;
+ return audioElement.volume;
+ };
+
+ var volumeHandler = function (e) {
+ events.preventDefault(e);
+ if ((e.wheelDelta && e.wheelDelta > 0) || (e.detail && e.detail < 0)) {
+ scope.volumeUp();
+ } else {
+ scope.volumeDown();
+ }
+ scope.$digest();
+ };
+
+
+
+ scope.$watch('audio.currentVolume', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ audioElement.volume = newVal / 100;
+ }
+ });
+
+ scope.setCurrentTime = function (timeInSec) {
+ audioElement.currentTime = timeInSec;
+ };
+
+ scope.setAudioPosition = function (val) {
+ if (scope.isReady) {
+ scope.setCurrentTime(val);
+ scope.isAudioDragging = false;
+ }
+ };
+
+ function getTimestampArray(timestamp) {
+ var d = Math.abs(timestamp) / 1000; // delta
+ var r = {}; // result
+ var s = { // structure
+ day: 86400,
+ hour: 3600,
+ minute: 60,
+ second: 1
+ };
+
+ Object.keys(s).forEach(function (key) {
+ r[key] = Math.floor(d / s[key]);
+ d -= r[key] * s[key];
+ });
+
+ return r;
+ };
+
+ scope.timeFormatter = function (timeInSec) {
+ var formattedTime = '00:00';
+
+ if (!timeInSec || timeInSec < 1) {
+ return formattedTime;
+ }
+
+ if (typeof timeInSec === 'string') {
+ return timeInSec;
+ }
+
+ var dateArray = getTimestampArray(timeInSec * 1000);
+ Object.keys(dateArray).forEach(function (key) {
+ if (dateArray[key] === 0) {
+ dateArray[key] = '00';
+ } else if (dateArray[key] < 10) {
+ dateArray[key] = '0' + dateArray[key];
+ }
+ });
+
+ formattedTime = dateArray['minute'] + ':' + dateArray['second'];
+
+ if (dateArray['hour'] !== '00') {
+ formattedTime = dateArray['hour'] + ':' + formattedTime;
+ }
+
+ if (dateArray['day'] !== '00') {
+ formattedTime = dateArray['day'] + ':' + formattedTime;
+ }
+
+ return formattedTime;
+ };
+
+ audioElement.onloadedmetadata = function () {
+ scope.audio.duration = audioElement.duration;
+ scope.$digest();
+ };
+
+ audioElement.ontimeupdate = function () {
+ if (!scope.isAudioDragging) {
+ scope.audio.currentTime = audioElement.currentTime;
+ scope.$digest();
+ }
+ };
+
+ audioElement.onended = function () {
+ scope.setCurrentTime(0);
+ scope.audio.currentTime = 0;
+ if (!audioElement.paused) {
+ scope.pauseAudio();
+ }
+ scope.$digest();
+ };
+
+ audioElement.oncanplay = function () {
+ scope.isReady = true;
+ scope.isPlayInProgress = !audioElement.paused;
+ scope.$digest();
+ };
+
+ var onloadstart = function () {
+ scope.isReady = false;
+ scope.isPlayInProgress = !audioElement.paused;
+ scope.audio.currentTime = 0;
+ scope.audio.duration = 0;
+ scope.$digest();
+ };
+ audioElement.addEventListener("loadstart", onloadstart);
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Videos, audio & animation.att:Audio Recorder
+ * @scope
+ * @param {function} callback - A callback to handle the WAV blob
+ * @param {object} config - A config object with properties startRecordingMessage & whileRecordingMessage
+ * @description
+ * <file src="src/audioRecorder/docs/readme.md" />
+ *
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/audioRecorder/docs/demo.html" />
+ <file src="src/audioRecorder/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.audioRecorder', ['b2b.att.utilities'])
+ .constant('AudioRecorderConfig', {
+ 'startRecordingMessage': 'Click on REC icon to being recording',
+ 'whileRecordingMessage': 'Recording...'
+ })
+ .directive('b2bAudioRecorder', ['$interval', 'AudioRecorderConfig', 'b2bUserAgent', 'b2bRecorder', function($interval, AudioRecorderConfig, b2bUserAgent, b2bRecorder) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ scope: {
+ callback: '&'
+ },
+ templateUrl: 'b2bTemplate/audioRecorder/audioRecorder.html',
+ controller: function($scope) {
+
+ function hasGetUserMedia() {
+ return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
+ navigator.mozGetUserMedia || navigator.msGetUserMedia);
+ }
+
+ if (!hasGetUserMedia()) {
+ throw new Error('Your broswer does not support MediaRecorder API');
+ }
+
+ if (!(b2bUserAgent.isFF() || b2bUserAgent.isChrome())) {
+ throw new Error('b2bAudioRecorder does not support this browser!');
+ }
+
+ },
+ link: function(scope, element) {
+ scope.elapsedTime = 0;
+ scope.isRecording = false;
+ scope.config = {};
+ scope.config.startRecordingMessage = AudioRecorderConfig.startRecordingMessage;
+ scope.config.whileRecordingMessage = AudioRecorderConfig.whileRecordingMessage;
+
+
+ var timer = undefined; // Interval promise
+ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+ var stream;
+ var audio = angular.element(element[0].querySelector('audio'))[0];
+ var recorder = undefined;
+
+ function startRecording() {
+ scope.isRecording = true;
+ navigator.mediaDevices.getUserMedia({
+ audio: true
+ }).then(function(stream) {
+ //create the MediaStreamAudioSourceNode
+ context = new AudioContext();
+ source = context.createMediaStreamSource(stream);
+ recorder = new b2bRecorder(source);
+ recorder.record();
+
+ timer = $interval(function() {
+ scope.elapsedTime += 1;
+ }, 1000, 0);
+ }).catch(function(err) {
+ angular.noop();
+ });
+
+ };
+
+ function stopRecording() {
+ scope.isRecording = false;
+ recorder.stop();
+ var audio = {};
+ recorder.exportWAV(function(s) {
+ audio.src = window.URL.createObjectURL(s);
+ context.close().then(function() {
+ if (timer) {
+ $interval.cancel(timer);
+ }
+ scope.elapsedTime = 0;
+
+ recorder.clear();
+ recorder = undefined;
+ });
+ if (angular.isFunction(scope.callback)){
+ scope.callback({'data': audio});
+ }
+ });
+
+
+ }
+
+ scope.toggleRecording = function() {
+ if (scope.isRecording) {
+ stopRecording();
+ } else {
+ startRecording();
+ }
+ };
+
+
+
+ //TODO: Move this into utilities
+ function getTimestampArray(timestamp) {
+ var d = Math.abs(timestamp) / 1000; // delta
+ var r = {}; // result
+ var s = { // structure
+ day: 86400,
+ hour: 3600,
+ minute: 60,
+ second: 1
+ };
+
+ Object.keys(s).forEach(function(key) {
+ r[key] = Math.floor(d / s[key]);
+ d -= r[key] * s[key];
+ });
+
+ return r;
+ };
+ scope.timeFormatter = function(timeInSec) {
+ var formattedTime = '00:00';
+
+ if (!timeInSec || timeInSec < 1) {
+ return formattedTime;
+ }
+
+ if (typeof timeInSec === 'string') {
+ return timeInSec;
+ }
+
+ var dateArray = getTimestampArray(timeInSec * 1000);
+ Object.keys(dateArray).forEach(function(key) {
+ if (dateArray[key] === 0) {
+ dateArray[key] = '00';
+ } else if (dateArray[key] < 10) {
+ dateArray[key] = '0' + dateArray[key];
+ }
+ });
+
+ formattedTime = dateArray['minute'] + ':' + dateArray['second'];
+
+ if (dateArray['hour'] !== '00') {
+ formattedTime = dateArray['hour'] + ':' + formattedTime;
+ }
+
+ if (dateArray['day'] !== '00') {
+ formattedTime = dateArray['day'] + ':' + formattedTime;
+ }
+
+ return formattedTime;
+ };
+
+ scope.$on('$destroy', function() {
+ if (timer) {
+ $interval.cancel(timer);
+ }
+ });
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Navigation.att:Back To Top
+ * @scope
+ * @description
+ * <file src="src/backToTop/docs/readme.md" />
+ * @param {integer} scrollSpeed - Scroll speed in seconds, default is 1
+*
+ * @usage
+ *
+ <div ng-controller="backToTopController">
+ <div b2b-backtotop></div>
+ </div>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/backToTop/docs/demo.html" />
+ <file src="src/backToTop/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.backToTop', ['b2b.att.utilities','b2b.att.position'])
+ .directive('b2bBacktotopButton', [function () {
+ return {
+ restrict: 'EA',
+ replace: true,
+ templateUrl: 'b2bTemplate/backToTop/backToTop.html',
+ link: function (scope, elem, attr) {
+ elem.bind('click', function(evt) {
+ var scrollSpeed = parseInt(attr.scrollSpeed) || 1;
+ TweenLite.to(window, scrollSpeed, {scrollTo:{x: 0, y: 0}});
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:badgesForAlerts
+ *
+ * @description
+ * <file src="src/badgesForAlerts/docs/readme.md" />
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/badgesForAlerts/docs/demo.html" />
+ <file src="src/badgesForAlerts/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.badgesForAlerts', []);
+/**
+ * @ngdoc directive
+ * @name Misc.att:boardstrip
+ *
+ * @description
+ * <file src="src/boardstrip/docs/readme.md" />
+ *
+ * @usage
+ * See demo section
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/boardstrip/docs/demo.html" />
+ <file src="src/boardstrip/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.boardstrip', ['b2b.att.utilities'])
+ .constant('BoardStripConfig', {
+ 'maxVisibleBoards': 4,
+ 'boardsToScroll': 1,
+ /* These parameters are non-configurable and remain unaltered, until there is a change in corresponding CSS */
+ 'boardLength': 140,
+ 'boardMargin': 15
+ })
+ .directive('b2bBoard', [function () {
+ return {
+ restrict: 'AE',
+ replace: true,
+ transclude: true,
+ require: '^b2bBoardStrip',
+ scope: {
+ boardIndex: '=',
+ boardLabel: '='
+ },
+ templateUrl: 'b2bTemplate/boardstrip/b2bBoard.html',
+ link: function (scope, element, attrs, ctrls) {
+
+ var parentCtrl = ctrls;
+
+ scope.getCurrentIndex = function () {
+ return parentCtrl.getCurrentIndex();
+ };
+ scope.selectBoard = function (boardIndex) {
+ if (!isNaN(boardIndex)) {
+ parentCtrl.setCurrentIndex(boardIndex);
+ }
+ };
+ }
+ };
+ }])
+ .directive('b2bBoardStrip', ['BoardStripConfig', '$timeout', function (BoardStripConfig, $timeout) {
+ return {
+ restrict: 'AE',
+ replace: true,
+ transclude: true,
+ require: ['?ngModel', 'b2bBoardStrip'],
+ scope: {
+ boardsMasterArray: '=',
+ onAddBoard: '&?'
+ },
+ templateUrl: 'b2bTemplate/boardstrip/b2bBoardstrip.html',
+ controller: function ($scope) {
+ if (!angular.isDefined($scope.boardsMasterArray)) {
+ $scope.boardsMasterArray = [];
+ }
+
+ this.rectifyMaxVisibleBoards = function () {
+ if (this.maxVisibleIndex >= $scope.boardsMasterArray.length) {
+ this.maxVisibleIndex = $scope.boardsMasterArray.length - 1;
+ }
+
+ if (this.maxVisibleIndex < 0) {
+ this.maxVisibleIndex = 0;
+ }
+ };
+
+ this.resetBoardStrip = function () {
+ $scope.currentIndex = 0;
+
+ this.maxVisibleIndex = BoardStripConfig.maxVisibleBoards - 1;
+ this.minVisibleIndex = 0;
+
+ this.rectifyMaxVisibleBoards();
+ };
+
+ this.getCurrentIndex = function () {
+ return $scope.currentIndex;
+ };
+ this.setCurrentIndex = function (indx) {
+ $scope.currentIndex = indx;
+ };
+
+ this.getBoardsMasterArrayLength = function () {
+ return $scope.boardsMasterArray.length;
+ };
+
+ $scope.addBoardPressedFlag = false;
+ this.getAddBoardPressedFlag = function () {
+ return $scope.addBoardPressedFlag;
+ };
+ this.setAddBoardPressedFlag = function (booleanValue) {
+ $scope.addBoardPressedFlag = booleanValue;
+ };
+
+ },
+ link: function (scope, element, attrs, ctrls) {
+
+ var ngModelCtrl = ctrls[0];
+ var ctrl = ctrls[1];
+
+ var oldTimeout;
+ var animationTimeout = 1000;
+
+ var getBoardViewportWidth = function (numberOfVisibleBoards) {
+ return numberOfVisibleBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
+ };
+ if (element[0].querySelector(".board-viewport")) {
+ angular.element(element[0].querySelector(".board-viewport")).css({
+ "width": getBoardViewportWidth(BoardStripConfig.maxVisibleBoards) + "px"
+ });
+ }
+
+ var getBoardstripContainerWidth = function (totalNumberOfBoards) {
+ return totalNumberOfBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
+ };
+ if (element[0].querySelector(".boardstrip-container")) {
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"
+ });
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "left": "0px"
+ });
+ }
+
+ var calculateAndGetBoardstripContainerAdjustment = function () {
+
+ var calculatedAdjustmentValue;
+
+ if (ctrl.getBoardsMasterArrayLength() <= BoardStripConfig.maxVisibleBoards) {
+ calculatedAdjustmentValue = 0;
+ } else {
+ calculatedAdjustmentValue = (ctrl.minVisibleIndex * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin)) * -1;
+ }
+
+ return calculatedAdjustmentValue;
+ };
+
+ var animateBoardstripContainerAdjustment = function (elementToFocusAfterAnimation) {
+ var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
+ var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
+ if (oldContainerAdjustment !== containerAdjustment + 'px') {
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "left": containerAdjustment + "px"
+ });
+
+ $timeout.cancel(oldTimeout);
+ oldTimeout = $timeout(function () {
+ elementToFocusAfterAnimation.focus();
+ }, animationTimeout);
+ } else {
+ elementToFocusAfterAnimation.focus();
+ }
+ };
+
+ var updateBoardsTabIndex = function (boardArray, minViewIndex, maxViewIndex) {
+ for (var i = 0; i < boardArray.length; i++) {
+ angular.element(boardArray[i]).attr('tabindex', '-1');
+ }
+ for (var j = minViewIndex; j <= maxViewIndex; j++) {
+ angular.element(boardArray[j]).attr('tabindex', '0');
+ }
+ };
+
+ $timeout(function () {
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+
+ scope.$watchCollection('boardsMasterArray', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ /* When a board is removed */
+ if (newVal.length < oldVal.length) {
+ ctrl.resetBoardStrip();
+ $timeout(function () {
+
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ if (currentBoardArray.length !== 0) {
+ animateBoardstripContainerAdjustment(currentBoardArray[0]);
+ } else {
+ element[0].querySelector('div.boardstrip-item--add').focus();
+ }
+
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"
+ });
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+ }
+ /* When a board is added */
+ else {
+ if (ctrl.getAddBoardPressedFlag()) {
+ ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength() - 1;
+ ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
+
+ ctrl.setCurrentIndex(ctrl.maxVisibleIndex);
+
+ $timeout(function () {
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"
+ });
+
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ animateBoardstripContainerAdjustment(currentBoardArray[currentBoardArray.length - 1]);
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+ } else {
+ if (ctrl.minVisibleIndex === 0 && ctrl.getBoardsMasterArrayLength() < BoardStripConfig.maxVisibleBoards + 1) {
+ ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength() - 1;
+ ctrl.rectifyMaxVisibleBoards();
+ }
+
+ $timeout(function () {
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"
+ });
+
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+ }
+
+ ctrl.setAddBoardPressedFlag(false);
+ }
+ }
+ });
+
+ scope.nextBoard = function () {
+ ctrl.maxVisibleIndex += BoardStripConfig.boardsToScroll;
+ ctrl.rectifyMaxVisibleBoards();
+ ctrl.minVisibleIndex = ctrl.maxVisibleIndex - (BoardStripConfig.maxVisibleBoards - 1);
+
+ $timeout.cancel(oldTimeout);
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "left": calculateAndGetBoardstripContainerAdjustment() + "px"
+ });
+
+ $timeout(function () {
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+
+ /* Remove tabindex from non-visible boards */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+
+ if (!(scope.isNextBoard())) {
+ try {
+ currentBoardArray[currentBoardArray.length - 1].focus();
+ } catch (e) { /* IE8 may throw exception */ }
+ }
+ }, animationTimeout);
+ };
+ scope.prevBoard = function () {
+
+ ctrl.minVisibleIndex -= BoardStripConfig.boardsToScroll;
+ if (ctrl.minVisibleIndex < 0) {
+ ctrl.minVisibleIndex = 0;
+ }
+
+ ctrl.maxVisibleIndex = ctrl.minVisibleIndex + BoardStripConfig.maxVisibleBoards - 1;
+ ctrl.rectifyMaxVisibleBoards();
+
+ $timeout.cancel(oldTimeout);
+ angular.element(element[0].querySelector(".boardstrip-container")).css({
+ "left": calculateAndGetBoardstripContainerAdjustment() + "px"
+ });
+
+ $timeout(function () {
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+
+ /* Remove tabindex from non-visible boards */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+
+ if (ctrl.minVisibleIndex === 0) {
+ try {
+ element[0].querySelector('div.boardstrip-item--add').focus();
+ } catch (e) { /* IE8 may throw exception */ }
+ }
+ });
+ };
+
+ scope.isPrevBoard = function () {
+ return (ctrl.minVisibleIndex > 0);
+ };
+ scope.isNextBoard = function () {
+ return (ctrl.getBoardsMasterArrayLength() - 1 > ctrl.maxVisibleIndex);
+ };
+
+ ngModelCtrl.$render = function () {
+ if (ngModelCtrl.$viewValue || ngModelCtrl.$viewValue === 0) {
+ var newCurrentIndex = ngModelCtrl.$viewValue;
+
+ if (!(newCurrentIndex = parseInt(newCurrentIndex, 10))) {
+ newCurrentIndex = 0;
+ }
+
+ if (newCurrentIndex <= 0) {
+ ctrl.resetBoardStrip();
+ newCurrentIndex = 0;
+
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ if (currentBoardArray.length !== 0) {
+ animateBoardstripContainerAdjustment(currentBoardArray[0]);
+ } else {
+ element[0].querySelector('div.boardstrip-item--add').focus();
+ }
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ } else if (newCurrentIndex >= ctrl.getBoardsMasterArrayLength()) {
+ ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength() - 1;
+ ctrl.rectifyMaxVisibleBoards();
+ ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
+
+ newCurrentIndex = ctrl.maxVisibleIndex;
+
+ $timeout(function () {
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ animateBoardstripContainerAdjustment(currentBoardArray[newCurrentIndex]);
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+ } else {
+
+ if (!(newCurrentIndex >= ctrl.minVisibleIndex && newCurrentIndex <= ctrl.maxVisibleIndex)) {
+ ctrl.minVisibleIndex = newCurrentIndex;
+ ctrl.maxVisibleIndex = ctrl.minVisibleIndex + BoardStripConfig.maxVisibleBoards - 1;
+ ctrl.rectifyMaxVisibleBoards();
+
+ if (ctrl.getBoardsMasterArrayLength() < BoardStripConfig.maxVisibleBoards) {
+ ctrl.minVisibleIndex = 0;
+ } else {
+ ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
+ }
+
+ $timeout(function () {
+ var currentBoardArray = element[0].querySelectorAll('[b2b-board]');
+ animateBoardstripContainerAdjustment(currentBoardArray[newCurrentIndex]);
+ /* Update tabindecies to ensure keyboard navigation behaves correctly */
+ updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
+ });
+ }
+ }
+ scope.currentIndex = newCurrentIndex;
+ ngModelCtrl.$setViewValue(newCurrentIndex);
+ } else {
+ ctrl.resetBoardStrip();
+ ngModelCtrl.$setViewValue(0);
+ }
+ };
+
+ scope.$watch('currentIndex', function (newVal, oldVal) {
+ if (newVal !== oldVal && ngModelCtrl && ngModelCtrl.$viewValue !== newVal) {
+ ngModelCtrl.$setViewValue(newVal);
+ }
+ });
+ }
+ };
+ }])
+ .directive('b2bAddBoard', ['BoardStripConfig', '$parse', function (BoardStripConfig, $parse) {
+ return {
+ restrict: 'AE',
+ replace: true,
+ require: '^b2bBoardStrip',
+ scope: {
+ onAddBoard: '&?'
+ },
+ templateUrl: 'b2bTemplate/boardstrip/b2bAddBoard.html',
+ link: function (scope, element, attrs, ctrl) {
+ scope.addBoard = function () {
+ if (attrs['onAddBoard']) {
+ scope.onAddBoard = $parse(scope.onAddBoard);
+ scope.onAddBoard();
+ ctrl.setAddBoardPressedFlag(true);
+ }
+ };
+ }
+ };
+ }])
+ .directive('b2bBoardNavigation', ['keymap', 'events', function (keymap, events) {
+ return {
+ restrict: 'AE',
+ link: function (scope, elem) {
+
+ var prevElem = keymap.KEY.LEFT;
+ var nextElem = keymap.KEY.RIGHT;
+
+ elem.bind('keydown', function (ev) {
+
+ if (!(ev.keyCode)) {
+ ev.keyCode = ev.which;
+ }
+
+ switch (ev.keyCode) {
+ case nextElem:
+ events.preventDefault(ev);
+ events.stopPropagation(ev);
+
+ if (elem[0].nextElementSibling && parseInt(angular.element(elem[0].nextElementSibling).attr('tabindex')) >= 0) {
+ angular.element(elem[0])[0].nextElementSibling.focus();
+ } else {
+ /* IE8 fix */
+ var el = angular.element(elem[0])[0];
+ do {
+ if (el.nextSibling) {
+ el = el.nextSibling;
+ } else {
+ break;
+ }
+ } while (el && el.tagName !== 'LI');
+
+ if (el.tagName && el.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0) {
+ el.focus();
+ }
+ }
+
+ break;
+ case prevElem:
+ events.preventDefault(ev);
+ events.stopPropagation(ev);
+
+ if (elem[0].previousElementSibling && parseInt(angular.element(elem[0].previousElementSibling).attr('tabindex')) >= 0) {
+ angular.element(elem[0])[0].previousElementSibling.focus();
+ } else {
+ /* IE8 fix */
+ var el1 = angular.element(elem[0])[0];
+ do {
+ if (el1.previousSibling) {
+ el1 = el1.previousSibling;
+ } else {
+ break;
+ }
+ } while (el1 && el1.tagName !== 'LI');
+
+ if (el1.tagName && el1.tagName === 'LI' && parseInt(angular.element(el1).attr('tabindex')) >= 0) {
+ el1.focus();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:breadcrumbs
+ *
+ * @description
+ * <file src="src/breadcrumbs/docs/readme.md" />
+ * @usage
+ <ul class="breadcrumb">
+ <li ng-repeat="link in breadCrumbsLink"><a tabindex="{{(idx==$index)?-1:0}}" href='javascript:void(0)' ng-click="clickActive($index)" ng-class="{'active':idx==$index, '': idx!=$index}">{{link.title}}</a></li>
+ </ul>
+ * @example
+ <example module="b2b.att">
+ <file src="src/breadcrumbs/docs/demo.html" />
+ <file src="src/breadcrumbs/docs/demo.js" />
+ </example>
+ */
+angular.module('b2b.att.breadcrumbs',[])
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:buttonGroups
+ *
+ * @description
+ * <file src="src/buttonGroups/docs/readme.md" />
+ *
+ * @usage
+<h2>Radio Aproach</h2>
+<div class="btn-group" b2b-key prev="37,38" next="39,40" circular-traversal role="radiogroup">
+ <button type="button" class="btn btn-secondary" b2b-key-item ng-focus="radioModel='Button 1'" ng-model="radioModel" b2b-btn-radio="'Button 1'" tabindex="{{(!radioModel || 'Button 1'===radioModel)?0:-1}}">Button 1</button>
+ <button type="button" class="btn btn-secondary" b2b-key-item ng-focus="radioModel='Button 2'" ng-model="radioModel" b2b-btn-radio="'Button 2'" tabindex="{{(!radioModel || 'Button 2'===radioModel)?0:-1}}">Button 2</button>
+ <button type="button" class="btn btn-secondary" b2b-key-item ng-focus="radioModel='Button 3'" ng-model="radioModel" b2b-btn-radio="'Button 3'" tabindex="{{(!radioModel || 'Button 3'===radioModel)?0:-1}}">Button 3</button>
+</div>
+
+<h2>Checkbox Aproach</h2>
+<span b2b-button-group class="btn-group btn-fullwidth" role="group" max-select="3" ng-model="checkModel1">
+ <button type="button" class="btn btn-secondary" ng-model="checkModel1.Button1" b2b-btn-checkbox>Button1</button>
+ <button type="button" class="btn btn-secondary" ng-model="checkModel1.Button2" b2b-btn-checkbox>Button2</button>
+ <button type="button" class="btn btn-secondary" ng-model="checkModel1.Button3" b2b-btn-checkbox>Button3</button>
+ <button type="button" class="btn btn-secondary" ng-model="checkModel1.Button4" b2b-btn-checkbox>Button4</button>
+ <button type="button" class="btn btn-secondary" ng-model="checkModel1.Button5" b2b-btn-checkbox>Button5</button>
+</span>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/buttonGroups/docs/demo.html" />
+ <file src="src/buttonGroups/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.buttonGroups', ['b2b.att.utilities'])
+ .constant('buttonConfig', {
+ activeClass: 'active',
+ toggleEvent: 'click'
+ })
+ .directive('b2bBtnRadio', ['buttonConfig', function (buttonConfig) {
+ var activeClass = buttonConfig.activeClass || 'active';
+ var toggleEvent = buttonConfig.toggleEvent || 'click';
+
+ return {
+ require: 'ngModel',
+ link: function (scope, element, attrs, ngModelCtrl) {
+ var notMobile = !/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+
+ if (notMobile) {
+ element.bind('focus', function () {
+ scope.$apply(function () {
+ ngModelCtrl.$setViewValue(scope.$eval(attrs.b2bBtnRadio));
+ ngModelCtrl.$render();
+ });
+ });
+ }
+
+ element.attr('role', 'radio');
+
+ //model -> UI
+ ngModelCtrl.$render = function () {
+ element.toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.b2bBtnRadio)));
+ if (angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.b2bBtnRadio))) {
+ element.attr("aria-checked", true);
+ } else {
+ element.attr("aria-checked", false);
+ }
+ };
+
+ //ui->model
+ element.bind(toggleEvent, function () {
+ if (!element.hasClass(activeClass)) {
+ scope.$apply(function () {
+ ngModelCtrl.$setViewValue(scope.$eval(attrs.b2bBtnRadio));
+ ngModelCtrl.$render();
+ });
+ }
+ });
+ }
+ };
+ }])
+ .directive('b2bBtnCheckbox', ['buttonConfig', function (buttonConfig) {
+ var activeClass = buttonConfig.activeClass || 'active';
+ var toggleEvent = buttonConfig.toggleEvent || 'click';
+
+ return {
+ require: ['ngModel', '^^b2bButtonGroup'],
+ link: function (scope, element, attrs, ctrls) {
+
+ var ngModelCtrl = ctrls[0];
+ var parentCtrl = ctrls[1];
+
+ element.attr('role', 'checkbox');
+ element.attr('aria-describedby', parentCtrl.getStateDescriptionElemId());
+
+ function getTrueValue() {
+ var trueValue = scope.$eval(attrs.b2bBtnCheckboxTrue);
+ return angular.isDefined(trueValue) ? trueValue : true;
+ }
+
+ function getFalseValue() {
+ var falseValue = scope.$eval(attrs.b2bBtnCheckboxFalse);
+ return angular.isDefined(falseValue) ? falseValue : false;
+ }
+
+ //model -> UI
+ ngModelCtrl.$render = function () {
+ element.toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
+ if ((angular.equals(ngModelCtrl.$modelValue, getTrueValue()))) {
+ element.attr("aria-checked", true);
+ } else {
+ element.attr("aria-checked", false);
+ }
+ };
+
+ //ui->model
+ element.bind(toggleEvent, function () {
+ scope.$apply(function () {
+ ngModelCtrl.$setViewValue(element.hasClass(activeClass) ? getFalseValue() : getTrueValue());
+ ngModelCtrl.$render();
+ });
+ });
+ }
+ };
+ }])
+ .directive('b2bButtonGroup', ['$timeout', '$compile', function ($timeout, $compile) {
+ return {
+ restrict: 'A',
+ scope: {
+ maxSelect: "=",
+ ngModelButtonState: '=ngModel'
+ },
+ controller: ['$scope', '$element', function ($scope, $element) {
+ $scope.nSel = 0;
+
+ var stateDescriptionElem = angular.element('<span id="b2b_button_group_' + $scope.$id + '" class="hide" aria-hidden="true">{{nSel}} of {{maxSelect}} options selected.</span>');
+ $compile(stateDescriptionElem)($scope);
+ $element.after(stateDescriptionElem);
+
+ this.getStateDescriptionElemId = function () {
+ return stateDescriptionElem.attr('id');
+ };
+ }],
+ link: function (scope, element) {
+
+
+ var executeFxn = function () {
+ scope.nSel = 0;
+ angular.forEach(scope.ngModelButtonState, function (value, key) {
+ if (value === true) {
+ scope.nSel += 1;
+ }
+ });
+
+ if (scope.nSel >= scope.maxSelect) {
+ angular.forEach(element.children(), function (chd) {
+ if (chd.className.indexOf('active') < 0) {
+ chd.disabled = true;
+ chd.setAttribute('aria-disabled', true);
+ }
+ });
+ } else {
+ angular.forEach(element.children(), function (chd) {
+ chd.disabled = false;
+ chd.setAttribute('aria-disabled', false);
+ });
+ }
+ scope.$digest();
+ };
+
+ $timeout(function () {
+ executeFxn();
+ });
+ element.bind('click', executeFxn);
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:buttons
+ * @element input
+ * @function
+ *
+ * @description
+ * <file src="src/buttons/docs/readme.md" />
+ * @usage
+ *
+Button shape
+<button class="btn" type="button">Button</button> button.btn (button shape only)
+<button aria-label="Custom aria label" class="btn" type="button">Button</button> button.btn (button shape only) with custom aria label
+<button aria-label="Click on button/Press enter" class="btn" type="button" onclick="javascript:alert('It works!');">Click on button/Press enter</button> button.btn with click functionality
+<a b2b-keyup-click="32" href="javascript:void(0)" class="btn" role="button">Button</a> a.btn (button shape only)
+<button class="btn btn-primary">Button</button> .btn-primary
+<a b2b-keyup-click="32" href="javascript:void(0)" class="btn btn-primary" role="button">Button</a> a.btn-primary
+
+5 Button colors
+<button class="btn btn-secondary">Button</button> .btn-secondary
+<a b2b-keyup-click="32" href="javascript:void(0)" class="btn btn-secondary" role="button">Button</a> a.btn-secondary
+<button class="btn btn-alt">Button</button> .btn-alt
+<a b2b-keyup-click="32" href="javascript:void(0)" class="btn btn-alt" role="button">Button</a> a.btn-alt
+<button class="btn btn-specialty">Button</button> .btn-specialty
+<a b2b-keyup-click="32" href="javascript:void(0)" class="btn btn-specialty" role="button">Button</a> a.btn-specialty
+<button class="btn btn-specialty" disabled="">Button</button> disabled="disabled"
+<a b2b-keyup-click="32" aria-disabled="true" href="javascript:void(0)" class="btn btn-primary disabled" role="button">Button</a> a.disabled
+
+3 button heights
+<button class="btn btn-secondary">Button</button> .btn is default and 46px height
+<button class="btn btn-secondary btn-medium">Button</button> .btn-medium is 42px
+<button class="btn btn-secondary btn-small">Button</button> .btn-small is 36px
+
+.row-nowrap 2 up buttons
+<div class="row-nowrap">
+ <button class="btn btn-secondary btn-fullwidth" type="button">Cancel</button>
+ <button class="btn btn-primary btn-fullwidth" type="button">Continue</button>
+</div>
+
+.row 2 up buttons (desktop) stacked (mobile) (different order)
+<div class="row cta-button-group">
+ <button class="span btn btn-secondary btn-fullwidth hidden-phone" type="button">Cancel</button>
+ <button class="span btn btn-primary btn-fullwidth" type="button">Continue</button>
+ <button class="span btn btn-secondary btn-fullwidth visible-phone" type="button">Cancel</button>
+</div>
+
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ * <example module="b2b.att">
+ * <file src="src/buttons/docs/demo.html" />
+ <file src="src/buttons/docs/demo.js" />
+ * </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.buttons', ['b2b.att.utilities']);
+/**
+ * @ngdoc directive
+ * @name Forms.att:calendar
+ *
+ * @description
+ * <file src="src/calendar/docs/readme.md" />
+ * @usage
+ * <input type="text" ng-model="dt" b2b-datepicker>
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/calendar/docs/demo.html" />
+ <file src="src/calendar/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.calendar', ['b2b.att.position', 'b2b.att.utilities'])
+
+.constant('b2bDatepickerConfig', {
+ dateFormat: 'MM/dd/yyyy',
+ dayFormat: 'd',
+ monthFormat: 'MMMM',
+ yearFormat: 'yyyy',
+ dayHeaderFormat: 'EEEE',
+ dayTitleFormat: 'MMMM yyyy',
+ disableWeekend: false,
+ disableSunday: false,
+ disableDates: null,
+ onSelectClose: null,
+ startingDay: 0,
+ minDate: null,
+ maxDate: null,
+ dueDate: null,
+ fromDate: null,
+ legendIcon: null,
+ legendMessage: null,
+ calendarDisabled: false,
+ collapseWait: 0,
+ orientation: 'left',
+ inline: false,
+ helperText: 'The date you selected is $date. In case of mobile double tap to open calendar. Select a date to close the calendar.',
+ datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'collapseWait', 'orientation'],
+ datepickerWatchAttributes: ['min', 'max', 'due', 'from', 'legendIcon', 'legendMessage', 'ngDisabled'],
+ datepickerFunctionAttributes: ['disableDates', 'onSelectClose']
+})
+
+.factory('b2bDatepickerService', ['b2bDatepickerConfig', 'dateFilter', function (b2bDatepickerConfig, dateFilter) {
+ var setAttributes = function (attr, elem) {
+ if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
+ var attributes = b2bDatepickerConfig.datepickerEvalAttributes.concat(b2bDatepickerConfig.datepickerWatchAttributes, b2bDatepickerConfig.datepickerFunctionAttributes);
+ for (var key in attr) {
+ var val = attr[key];
+ if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ elem.attr(key.toSnakeCase(), key);
+ }
+ }
+ }
+ };
+
+ var bindScope = function (attr, scope) {
+ if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
+ var evalFunction = function (key, val) {
+ scope[key] = scope.$parent.$eval(val);
+ };
+
+ var watchFunction = function (key, val) {
+ scope.$parent.$watch(val, function (value) {
+ scope[key] = value;
+ });
+ scope.$watch(key, function (value) {
+ scope.$parent[val] = value;
+ });
+ };
+
+ var evalAttributes = b2bDatepickerConfig.datepickerEvalAttributes;
+ var watchAttributes = b2bDatepickerConfig.datepickerWatchAttributes;
+ for (var key in attr) {
+ var val = attr[key];
+ if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ evalFunction(key, val);
+ } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ watchFunction(key, val);
+ }
+ }
+ }
+ };
+
+ return {
+ setAttributes: setAttributes,
+ bindScope: bindScope
+ };
+}])
+
+.controller('b2bDatepickerController', ['$scope', '$attrs', 'dateFilter', '$element', '$position', 'b2bDatepickerConfig', function ($scope, $attrs, dateFilter, $element, $position, dtConfig) {
+ var format = {
+ date: getValue($attrs.dateFormat, dtConfig.dateFormat),
+ day: getValue($attrs.dayFormat, dtConfig.dayFormat),
+ month: getValue($attrs.monthFormat, dtConfig.monthFormat),
+ year: getValue($attrs.yearFormat, dtConfig.yearFormat),
+ dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
+ dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
+ disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
+ disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday),
+ disableDates: getValue($attrs.disableDates, dtConfig.disableDates)
+ },
+ startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
+
+ $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
+ $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
+ $scope.dueDate = dtConfig.dueDate ? $scope.resetTime(dtConfig.dueDate) : null;
+ $scope.fromDate = dtConfig.fromDate ? $scope.resetTime(dtConfig.fromDate) : null;
+ $scope.legendIcon = dtConfig.legendIcon ? dtConfig.legendIcon : null;
+ $scope.legendMessage = dtConfig.legendMessage ? dtConfig.legendMessage : null;
+ $scope.ngDisabled = dtConfig.calendarDisabled ? dtConfig.calendarDisabled : null;
+ $scope.collapseWait = getValue($attrs.collapseWait, dtConfig.collapseWait);
+ $scope.orientation = getValue($attrs.orientation, dtConfig.orientation);
+ $scope.onSelectClose = getValue($attrs.onSelectClose, dtConfig.onSelectClose);
+
+ $scope.inline = $attrs.inline === 'true' ? true : dtConfig.inline;
+
+ function getValue(value, defaultValue) {
+ return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
+ }
+
+ function getDaysInMonth(year, month) {
+ return new Date(year, month, 0).getDate();
+ }
+
+ function getDates(startDate, n) {
+ var dates = new Array(n);
+ var current = startDate,
+ i = 0;
+ while (i < n) {
+ dates[i++] = new Date(current);
+ current.setDate(current.getDate() + 1);
+ }
+ return dates;
+ }
+
+ this.updatePosition = function (b2bDatepickerPopupTemplate) {
+ $scope.position = $position.offset($element);
+ $scope.position.top = $scope.position.top + $element.find('input').prop('offsetHeight');
+ if ($scope.orientation === 'right') {
+ $scope.position.left = $scope.position.left - (((b2bDatepickerPopupTemplate && b2bDatepickerPopupTemplate.prop('offsetWidth')) || 290) - $element.find('input').prop('offsetWidth'));
+ }
+ };
+
+ function isSelected(dt) {
+ if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isFromDate(dt) {
+ if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isDateRange(dt) {
+ if (dt && $scope.fromDate && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
+ return true;
+ } else if (dt && $scope.fromDate && compare(dt, $scope.fromDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isOld(date, currentMonthDate) {
+ if (date && currentMonthDate && (new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0).getTime() < new Date(currentMonthDate.getFullYear(), currentMonthDate.getMonth(), 1, 0, 0, 0).getTime())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function isNew(date, currentMonthDate) {
+ if (date && currentMonthDate && (new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0).getTime() > new Date(currentMonthDate.getFullYear(), currentMonthDate.getMonth(), 1, 0, 0, 0).getTime())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function isPastDue(dt) {
+ if ($scope.dueDate) {
+ return (dt > $scope.dueDate);
+ }
+ return false;
+ }
+
+ function isDueDate(dt) {
+ if ($scope.dueDate) {
+ return (dt.getTime() === $scope.dueDate.getTime());
+ }
+ return false;
+ }
+
+ var isDisabled = function (date, currentMonthDate) {
+ if ($attrs.from && !angular.isDate($scope.fromDate)) {
+ return true;
+ }
+ if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ if (isOld(date, currentMonthDate) || isNew(date, currentMonthDate)) {
+ return true;
+ }
+ return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0) || (format.disableDates && format.disableDates({
+ date: date
+ })));
+ };
+
+ var compare = function (date1, date2) {
+ return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
+ };
+
+ function isMinDateAvailable(startDate, endDate) {
+ if (($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime())) {
+ $scope.disablePrev = true;
+ $scope.visibilityPrev = "hidden";
+ } else {
+ $scope.disablePrev = false;
+ $scope.visibilityPrev = "visible";
+ }
+ }
+
+ function isMaxDateAvailable(startDate, endDate) {
+ if (($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime())) {
+ $scope.disableNext = true;
+ $scope.visibilityNext = "hidden";
+ } else {
+ $scope.disableNext = false;
+ $scope.visibilityNext = "visible";
+ }
+ }
+
+ function getLabel(label) {
+ if (label) {
+ var labelObj = {
+ pre: label.substr(0, 1).toUpperCase(),
+ post: label
+ };
+ return labelObj;
+ }
+ return;
+ }
+
+ function makeDate(date, dayFormat, dayHeaderFormat, isSelected, isFromDate, isDateRange, isOld, isNew, isDisabled, dueDate, pastDue) {
+ return {
+ date: date,
+ label: dateFilter(date, dayFormat),
+ header: dateFilter(date, dayHeaderFormat),
+ selected: !!isSelected,
+ fromDate: !!isFromDate,
+ dateRange: !!isDateRange,
+ oldMonth: !!isOld,
+ nextMonth: !!isNew,
+ disabled: !!isDisabled,
+ dueDate: !!dueDate,
+ pastDue: !!pastDue,
+ focusable: !((isDisabled && !(isSelected || isDateRange)) || (isOld || isNew))
+ };
+ }
+
+ this.modes = [
+ {
+ name: 'day',
+ getVisibleDates: function (date) {
+ var year = date.getFullYear(),
+ month = date.getMonth(),
+ firstDayOfMonth = new Date(year, month, 1),
+ lastDayOfMonth = new Date(year, month + 1, 0);
+ var difference = startingDay - firstDayOfMonth.getDay(),
+ numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
+ firstDate = new Date(firstDayOfMonth),
+ numDates = 0;
+
+ if (numDisplayedFromPreviousMonth > 0) {
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
+ numDates += numDisplayedFromPreviousMonth; // Previous
+ }
+ numDates += getDaysInMonth(year, month + 1); // Current
+ numDates += (7 - numDates % 7) % 7; // Next
+
+ var days = getDates(firstDate, numDates),
+ labels = new Array(7);
+ for (var i = 0; i < numDates; i++) {
+ var dt = new Date(days[i]);
+ days[i] = makeDate(dt,
+ format.day,
+ format.dayHeader,
+ isSelected(dt),
+ isFromDate(dt),
+ isDateRange(dt),
+ isOld(dt, date),
+ isNew(dt, date),
+ isDisabled(dt, date),
+ isDueDate(dt),
+ isPastDue(dt));
+ }
+ for (var j = 0; j < 7; j++) {
+ labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
+ }
+ isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
+ isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
+ return {
+ objects: days,
+ title: dateFilter(date, format.dayTitle),
+ labels: labels
+ };
+ },
+ split: 7,
+ step: {
+ months: 1
+ }
+ }
+ ];
+}])
+
+.directive('b2bDatepickerPopup', ['$parse', '$log', '$timeout', '$document', '$documentBind', '$isElement', '$templateCache', '$compile', 'trapFocusInElement', '$position', '$window', function ($parse, $log, $timeout, $document, $documentBind, $isElement, $templateCache, $compile, trapFocusInElement, $position, $window) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ transclude: true,
+ templateUrl: function (elem, attr) {
+ if (attr.inline === 'true') {
+ return 'b2bTemplate/calendar/datepicker-popup.html';
+ } else {
+ return 'b2bTemplate/calendar/datepicker.html';
+ }
+ },
+ scope: {},
+ require: ['b2bDatepickerPopup', 'ngModel', '?^b2bDatepickerGroup'],
+ controller: 'b2bDatepickerController',
+ link: function (scope, element, attrs, ctrls) {
+ var datepickerCtrl = ctrls[0],
+ ngModel = ctrls[1],
+ b2bDatepickerGroupCtrl = ctrls[2];
+ var b2bDatepickerPopupTemplate;
+
+ if (!ngModel) {
+ $log.error("ng-model is required.");
+ return; // do nothing if no ng-model
+ }
+
+ // Configuration parameters
+ var mode = 0,
+ selected;
+ scope.isOpen = false;
+
+ scope.headers = [];
+ scope.footers = [];
+
+ if (b2bDatepickerGroupCtrl) {
+ b2bDatepickerGroupCtrl.registerDatepickerScope(scope);
+ }
+
+ element.find('button').bind('click', function () {
+ element.find('input')[0].click();
+ });
+
+ element.find('input').bind('click', function () {
+ if (!scope.ngDisabled) {
+ scope.isOpen = !scope.isOpen;
+ toggleCalendar(scope.isOpen);
+ scope.$apply();
+ datepickerCtrl.updatePosition(b2bDatepickerPopupTemplate);
+ $timeout(function () {
+ angular.element(element[0].querySelector('.datepicker-input')).scrollTop=0;
+ },10);
+ }
+ });
+ var toggleCalendar = function (flag) {
+ if (!scope.inline) {
+ if (flag) {
+ b2bDatepickerPopupTemplate = angular.element($templateCache.get('b2bTemplate/calendar/datepicker-popup.html'));
+ b2bDatepickerPopupTemplate = $compile(b2bDatepickerPopupTemplate)(scope);
+ $document.find('body').append(b2bDatepickerPopupTemplate);
+ b2bDatepickerPopupTemplate.bind('keydown', keyPress);
+ $timeout(function () {
+ scope.getFocus = true;
+ trapFocusInElement(flag, b2bDatepickerPopupTemplate);
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ }, 100);
+ });
+ } else {
+ b2bDatepickerPopupTemplate.unbind('keydown', keyPress);
+ b2bDatepickerPopupTemplate.remove();
+ element.find('button')[0].focus();
+ scope.getFocus = false;
+ trapFocusInElement(flag, b2bDatepickerPopupTemplate);
+ }
+ }
+ };
+
+ var outsideClick = function (e) {
+ var isElement = $isElement(angular.element(e.target), element, $document);
+ var isb2bDatepickerPopupTemplate = $isElement(angular.element(e.target), b2bDatepickerPopupTemplate, $document);
+ if (!(isElement || isb2bDatepickerPopupTemplate)) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ scope.$apply();
+ }
+ };
+
+ var keyPress = function (ev) {
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if (ev.keyCode) {
+ if (ev.keyCode === 27) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === 33) {
+ !scope.disablePrev && scope.move(-1);
+ $timeout(function () {
+ scope.getFocus = true;
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ }, 100);
+ });
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === 34) {
+ !scope.disableNext && scope.move(1);
+ $timeout(function () {
+ scope.getFocus = true;
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ }, 100);
+ });
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ scope.$apply();
+ }
+ };
+
+ $documentBind.click('isOpen', outsideClick, scope);
+
+ var modalContainer = angular.element(document.querySelector('.modalwrapper'));
+ var modalBodyContainer = angular.element(document.querySelector('.modal-body'));
+ if (modalContainer) {
+ modalContainer.bind('scroll', function () {
+ if (b2bDatepickerPopupTemplate) {
+ datepickerCtrl.updatePosition(b2bDatepickerPopupTemplate);
+ scope.$apply();
+ }
+ });
+ }
+ if (modalBodyContainer) {
+ modalBodyContainer.bind('scroll', function () {
+ if (b2bDatepickerPopupTemplate) {
+ datepickerCtrl.updatePosition(b2bDatepickerPopupTemplate);
+ var datepickerTextfield = $position.offset(element.find('input'));
+ var modalBodyPosition = $position.offset(modalBodyContainer);
+
+ if (((datepickerTextfield.top + datepickerTextfield.height) < modalBodyPosition.top || datepickerTextfield.top > (modalBodyPosition.top + modalBodyPosition.height)) && scope.isOpen) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }
+ scope.$apply();
+ }
+ });
+ }
+ var window = angular.element($window);
+ window.bind('resize', function () {
+ if (b2bDatepickerPopupTemplate) {
+ datepickerCtrl.updatePosition(b2bDatepickerPopupTemplate);
+ scope.$apply();
+ }
+ });
+
+ scope.$on('$destroy', function () {
+ if (scope.isOpen) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }
+ });
+
+ scope.resetTime = function (date) {
+ if (typeof date === 'string') {
+ date = date + 'T12:00:00';
+ }
+ var dt;
+ if (!isNaN(new Date(date))) {
+ dt = new Date(date);
+ } else {
+ return null;
+ }
+ return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
+ };
+
+ if (attrs.min) {
+ scope.$parent.$watch($parse(attrs.min), function (value) {
+ scope.minDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.max) {
+ scope.$parent.$watch($parse(attrs.max), function (value) {
+ scope.maxDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.due) {
+ scope.$parent.$watch($parse(attrs.due), function (value) {
+ scope.dueDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.from) {
+ scope.$parent.$watch($parse(attrs.from), function (value) {
+ scope.fromDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+
+ if (attrs.legendIcon) {
+ scope.$parent.$watch(attrs.legendIcon, function (value) {
+ scope.legendIcon = value ? value : null;
+ refill();
+ });
+ }
+ if (attrs.legendMessage) {
+ scope.$parent.$watch(attrs.legendMessage, function (value) {
+ scope.legendMessage = value ? value : null;
+ refill();
+ });
+ }
+ if (attrs.ngDisabled) {
+ scope.$parent.$watch(attrs.ngDisabled, function (value) {
+ scope.ngDisabled = value ? value : null;
+ });
+ }
+
+ // Split array into smaller arrays
+ function split(arr, size) {
+ var arrays = [];
+ while (arr.length > 0) {
+ arrays.push(arr.splice(0, size));
+ }
+ return arrays;
+ }
+
+ function refill(date) {
+ if (angular.isDate(date) && !isNaN(date)) {
+ selected = new Date(date);
+ } else {
+ if (!selected) {
+ selected = new Date();
+ }
+ }
+
+ if (selected) {
+ var currentMode = datepickerCtrl.modes[mode],
+ data = currentMode.getVisibleDates(selected);
+ scope.rows = split(data.objects, currentMode.split);
+ var flag = false;
+ var startFlag = false;
+ var firstSelected = false;
+ for (var i = 0; i < scope.rows.length; i++) {
+ for (var j = 0; j < scope.rows[i].length; j++) {
+
+ if (scope.rows[i][j].label === "1" && !firstSelected) {
+ firstSelected = true;
+ var firstDay = scope.rows[i][j];
+ }
+
+ if (scope.rows[i][j].selected === true) {
+ flag = true;
+ break;
+ }
+ }
+ if (flag) {
+ break;
+ }
+ }
+ if (!flag) {
+ firstDay.firstFocus = true;
+ }
+
+ scope.labels = data.labels || [];
+ scope.title = data.title;
+
+ datepickerCtrl.updatePosition(b2bDatepickerPopupTemplate);
+ }
+ }
+
+ scope.select = function (date) {
+ var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
+ if (!scope.onSelectClose || (scope.onSelectClose && scope.onSelectClose({
+ date: dt
+ }) !== false)) {
+ scope.currentDate = dt;
+ if (angular.isNumber(scope.collapseWait)) {
+ $timeout(function () {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }, scope.collapseWait);
+ } else {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }
+ }
+ };
+
+ scope.move = function (direction,$event) {
+ var step = datepickerCtrl.modes[mode].step;
+ selected.setDate(1);
+ selected.setMonth(selected.getMonth() + direction * (step.months || 0));
+ selected.setFullYear(selected.getFullYear() + direction * (step.years || 0));
+ refill();
+
+ $timeout(function () {
+ trapFocusInElement();
+ }, 100);
+
+ $event.preventDefault();
+ $event.stopPropagation();
+ };
+
+ scope.trapFocus = function () {
+ $timeout(function () {
+ trapFocusInElement();
+ }, 100);
+ };
+
+ scope.$watch('currentDate', function (value) {
+ if (angular.isDefined(value) && value !== null) {
+ refill(value);
+ } else {
+ refill();
+ }
+ ngModel.$setViewValue(value);
+ });
+
+ ngModel.$render = function () {
+ scope.currentDate = ngModel.$viewValue;
+ };
+
+ var stringToDate = function (value) {
+ if (!isNaN(new Date(value))) {
+ value = new Date(value);
+ }
+ return value;
+ };
+ ngModel.$formatters.unshift(stringToDate);
+ }
+ };
+}])
+
+.directive('b2bDatepicker', ['$compile', '$log', 'b2bDatepickerConfig', 'b2bDatepickerService', function ($compile, $log, b2bDatepickerConfig, b2bDatepickerService) {
+ return {
+ restrict: 'A',
+ scope: {
+ disableDates: '&',
+ onSelectClose: '&'
+ },
+ require: 'ngModel',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : b2bDatepickerConfig.dateFormat;
+ var helperText = angular.isDefined(attr.helperText) ? scope.$parent.$eval(attr.helperText) : b2bDatepickerConfig.helperText;
+ helperText = helperText.replace('$date', '{{dt | date : \'' + dateFormatString + '\'}}');
+
+ var inline = false;
+ if (elem.prop('nodeName') !== 'INPUT') {
+ inline = true;
+ }
+
+ var calendarIcon = '<i class="icon-primary-calendar" aria-hidden="true"></i>'
+ var selectedDateMessage = '<button id="' + attr.btnId + '" type="button" class="span12 faux-input" ng-disabled="ngDisabled"><span class="hidden-spoken">' + helperText + '</span></button>';
+
+ elem.removeAttr('b2b-datepicker');
+ elem.removeAttr('ng-model');
+ elem.removeAttr('ng-disabled');
+ elem.addClass('datepicker-input');
+ elem.attr('ng-model', 'dt');
+ elem.attr('aria-describedby', 'datepicker');
+ elem.attr('aria-hidden', 'true');
+ elem.attr('tabindex', '-1');
+ elem.attr('readonly', 'true');
+ elem.attr('ng-disabled', 'ngDisabled');
+ elem.attr('b2b-format-date', dateFormatString);
+
+ var wrapperElement = angular.element('<div></div>');
+ wrapperElement.attr('b2b-datepicker-popup', '');
+ wrapperElement.attr('ng-model', 'dt');
+ if (inline) {
+ wrapperElement.attr('inline', inline);
+ }
+
+ b2bDatepickerService.setAttributes(attr, wrapperElement);
+ b2bDatepickerService.bindScope(attr, scope);
+
+ wrapperElement.html('');
+ wrapperElement.append(calendarIcon);
+ wrapperElement.append(selectedDateMessage);
+ wrapperElement.append(elem.prop('outerHTML'));
+
+ var elm = wrapperElement.prop('outerHTML');
+ elm = $compile(elm)(scope);
+ elem.replaceWith(elm);
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ if (!ctrl) {
+ $log.error("ng-model is required.");
+ return; // do nothing if no ng-model
+ }
+
+ scope.$watch('dt', function (value) {
+ ctrl.$setViewValue(value);
+ });
+ ctrl.$render = function () {
+ scope.dt = ctrl.$viewValue;
+ };
+ }
+ };
+}])
+
+.directive('b2bDatepickerGroup', [function () {
+ return {
+ restrict: 'EA',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ this.$$headers = [];
+ this.$$footers = [];
+ this.registerDatepickerScope = function (datepickerScope) {
+ datepickerScope.headers = this.$$headers;
+ datepickerScope.footers = this.$$footers;
+ };
+ }],
+ link: function (scope, elem, attr, ctrl) {}
+ };
+}])
+
+.directive('b2bFormatDate', ['dateFilter', function (dateFilter) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ var b2bFormatDate = "";
+ attr.$observe('b2bFormatDate', function (value) {
+ b2bFormatDate = value;
+ });
+ var dateToString = function (value) {
+ if (!isNaN(new Date(value))) {
+ return dateFilter(new Date(value), b2bFormatDate);
+ }
+ return value;
+ };
+ ctrl.$formatters.unshift(dateToString);
+ }
+ };
+}])
+
+.directive('b2bDatepickerHeader', [function () {
+ return {
+ restrict: 'EA',
+ require: '^b2bDatepickerGroup',
+ transclude: true,
+ replace: true,
+ template: '',
+ compile: function (elem, attr, transclude) {
+ return function link(scope, elem, attr, ctrl) {
+ if (ctrl) {
+ ctrl.$$headers.push(transclude(scope, function () {}));
+ }
+ elem.remove();
+ };
+ }
+ };
+}])
+
+.directive('b2bDatepickerFooter', [function () {
+ return {
+ restrict: 'EA',
+ require: '^b2bDatepickerGroup',
+ transclude: true,
+ replace: true,
+ template: '',
+ compile: function (elem, attr, transclude) {
+ return function link(scope, elem, attr, ctrl) {
+ if (ctrl) {
+ ctrl.$$footers.push(transclude(scope, function () {}));
+ }
+ elem.remove();
+ };
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:checkboxes
+ *
+ * @description
+ * <file src="src/checkboxes/docs/readme.md" />
+ * @usage
+ * See demo section
+ * @example
+ <example module="b2b.att">
+ <file src="src/checkboxes/docs/demo.html" />
+ <file src="src/checkboxes/docs/demo.js" />
+ </example>
+ */
+angular.module('b2b.att.checkboxes', ['b2b.att.utilities'])
+.directive('b2bSelectGroup', [function (){
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ scope: {
+ checkboxes: "="
+ },
+ link: function (scope, elem, attr, ctrl) {
+ elem.bind('change', function () {
+ var isChecked = elem.prop('checked');
+ angular.forEach(scope.checkboxes, function (item) {
+ item.isSelected = isChecked;
+ });
+ scope.$apply();
+ });
+ scope.$watch('checkboxes', function () {
+ var setBoxes = 0;
+ if(scope.checkboxes === undefined) {
+ return;
+ }
+ angular.forEach(scope.checkboxes, function (item) {
+ if (item.isSelected) {
+ setBoxes++;
+ }
+ });
+ elem.prop('indeterminate', false);
+ if ( scope.checkboxes !==undefined && setBoxes === scope.checkboxes.length && scope.checkboxes.length > 0) {
+ ctrl.$setViewValue(true);
+ elem.removeClass('indeterminate');
+ } else if (setBoxes === 0) {
+ ctrl.$setViewValue(false);
+ elem.removeClass('indeterminate');
+ } else {
+ ctrl.$setViewValue(false);
+ elem.addClass('indeterminate');
+ elem.prop('indeterminate', true);
+ }
+ ctrl.$render();
+ }, true);
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Misc.att:coachmark
+ *
+ * @description
+ * <file src="src/coachmark/docs/readme.md" />
+ *
+ * @usage
+ *
+<button b2b-coachmark start-coachmark-callback="startCoachmark()" end-coachmark-callback="endCoachmark()" action-coachmark-callback="actionCoachmark(action)" coachmark-index="coachmarkIndex" coachmarks="coachmarkElements" id="coachmark0" class="btn btn-alt">Initiate tour</button>
+
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/coachmark/docs/demo.html" />
+ <file src="src/coachmark/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.coachmark', ['b2b.att.utilities','b2b.att.position'])
+
+ .directive('b2bCoachmark', ['$document', '$compile', '$position', '$timeout', function($document, $compile, $position, $timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ coachmarks: '=',
+ coachmarkIndex: '=',
+ startCoachmarkCallback: '&',
+ endCoachmarkCallback: '&',
+ actionCoachmarkCallback: '&'
+ },
+ link: function (scope, element, attrs, ctrl) {
+ var coachmarkItems = scope.coachmarks;
+ var body = $document.find('body').eq(0);
+ var coackmarkJqContainer;
+ var coackmarkContainer;
+ var coachMarkElement;
+ var backdropjqLiteEl;
+ var coachmarkHighlight;
+ var initaitedCoachmark = false;
+ scope.coackmarkElPos ={
+ 'top':'',
+ 'left':''
+ };
+
+ scope.currentCoachmark = {};
+
+
+ var coachmarkBackdrop = function(){
+ backdropjqLiteEl = angular.element('<div class="b2b-modal-backdrop fade in hidden-by-modal"></div>');
+ body.append(backdropjqLiteEl);
+
+ backdropjqLiteEl.bind('click', function() {
+ scope.closeCoachmark();
+ scope.$apply();
+ });
+ };
+
+
+ scope.closeButtonFocus = function(){
+ if(document.getElementsByClassName('b2b-coachmark-header').length >0){
+ document.getElementsByClassName('b2b-coachmark-header')[0].scrollLeft = 0;
+ document.getElementsByClassName('b2b-coachmark-header')[0].scrollTop = 0;
+ }
+ }
+
+ scope.actionCoachmark = function(action){
+ scope.actionCoachmarkCallback({
+ 'action':action
+ })
+ };
+
+ scope.closeCoachmark = function(){
+ initaitedCoachmark = false;
+ backdropjqLiteEl.remove();
+ coackmarkContainer.remove();
+ coachmarkHighlight.remove();
+ if(coachMarkElement !== undefined && coachMarkElement !==""){
+ coachMarkElement.removeClass('b2b-coachmark-label')
+ }
+ if (angular.isFunction(scope.endCoachmarkCallback)){
+ scope.endCoachmarkCallback();
+ }
+ element[0].focus();
+ }
+
+ function showCoachmark(targetElement) {
+ scope.currentCoachmark = targetElement;
+ if(coachMarkElement !== undefined && coachMarkElement !==""){
+ coachMarkElement.removeClass('b2b-coachmark-label')
+ coackmarkContainer.remove();
+ coachmarkHighlight.remove();
+ }
+ coachMarkElement = angular.element(document.querySelector(targetElement.elementId));
+ coachMarkElement.addClass('b2b-coachmark-label');
+ var elementPosition = $position.offset(coachMarkElement);
+
+ coachmarkHighlight = angular.element('<div class="b2b-coachmark-highlight"></div><div class="b2b-coachmark-highlight b2b-coachmark-highlight-mask"></div>');
+ coachmarkHighlight.css({
+ 'width': (elementPosition.width + 20) +'px',
+ 'top': (elementPosition.top -10) + 'px',
+ 'left': (elementPosition.left - 10) + 'px',
+ 'height': (elementPosition.height + 20) +'px'
+ });
+ body.append(coachmarkHighlight);
+
+ scope.coackmarkElPos.top = (elementPosition.top + elementPosition.height + 32) + 'px';
+ scope.coackmarkElPos.left = (elementPosition.left - 158 + elementPosition.width / 2 ) + 'px';
+ coackmarkJqContainer = angular.element('<div b2b-coachmark-container b2b-trap-focus-inside-element="true"></div>');
+ coackmarkContainer = $compile(coackmarkJqContainer)(scope);
+ body.append(coackmarkContainer);
+
+ $timeout(function () {
+ var currentCoachmarkContainer = document.getElementsByClassName('b2b-coachmark-container')[0];
+ currentCoachmarkContainer.focus();
+ var coachmarkHeight = window.getComputedStyle(currentCoachmarkContainer).height.split('px')[0];
+ var newOffsetHeight = (Math.round(elementPosition.top) - Math.round(coachmarkHeight));
+
+ // We need a slight offset to show the lightboxed item
+ TweenLite.to(window, 2, {scrollTo:{x: (scope.coackmarkElPos.left.split('px')[0]-100), y: newOffsetHeight}});
+ }, 200);
+ }
+
+ element.bind('click', function (e) {
+ initaitedCoachmark = true;
+ if(scope.coachmarkIndex === -1 || scope.coachmarkIndex >= coachmarkItems.length ){
+ scope.coachmarkIndex = 0;
+ }
+ scope.$watch('coachmarkIndex', function () {
+ if(initaitedCoachmark === true){
+ if(scope.coachmarkIndex === -1 || scope.coachmarkIndex >= coachmarkItems.length ){
+ scope.closeCoachmark();
+ }else{
+ showCoachmark(coachmarkItems[scope.coachmarkIndex]);
+ }
+ }
+ });
+ coachmarkBackdrop();
+ showCoachmark(coachmarkItems[scope.coachmarkIndex]);
+ if (angular.isFunction(scope.startCoachmarkCallback)){
+ scope.startCoachmarkCallback();
+ }
+ $document.bind('keydown', function (evt) {
+ if (evt.which === 27 && initaitedCoachmark) {
+ scope.closeCoachmark();
+ scope.$apply();
+ }
+ });
+ });
+
+ }
+ };
+ }])
+ .directive('b2bCoachmarkContainer', ['$document', '$position', function($document, $position) {
+ return {
+ restrict: 'A',
+ transclude: true,
+ replace: true,
+ templateUrl: 'b2bTemplate/coachmark/coachmark.html',
+ link: function (scope, element, attrs, ctrl) {
+
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Template.att:Configuration Section
+ *
+ * @description
+ * <file src="src/configurationSection/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/configurationSection/docs/demo.html" />
+ <file src="src/configurationSection/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.configurationSection', [])
+
+/**
+ * @ngdoc directive
+ * @name Template.att:Directory Listing
+ *
+ * @description
+ * <file src="src/directoryListingTemplate/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/directoryListingTemplate/docs/demo.html" />
+ <file src="src/directoryListingTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.directoryListingTemplate', [])
+
+/**
+ * @ngdoc directive
+ * @name Forms.att:dropdowns
+ *
+ * @description
+ * <file src="src/dropdowns/docs/readme.md" />
+ * @usage
+ *
+ * @example
+ <section id="code">
+ <example module="b2b.att">
+ <file src="src/dropdowns/docs/demo.html" />
+ <file src="src/dropdowns/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.dropdowns', ['b2b.att.utilities', 'b2b.att.position', 'ngSanitize'])
+
+.constant('b2bDropdownConfig', {
+ prev: '37,38',
+ next: '39,40',
+ menuKeyword: 'menu',
+ linkMenuKeyword: 'link-menu',
+ largeKeyword: 'large',
+ smallKeyword: 'small'
+})
+
+.directive("b2bDropdown", ['$timeout', '$compile', '$templateCache', 'b2bUserAgent', 'b2bDropdownConfig', '$position', function ($timeout, $compile, $templateCache, b2bUserAgent, b2bDropdownConfig, $position) {
+ return {
+ restrict: 'A',
+ scope: true,
+ require: 'ngModel',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ scope.isInputDropdown = true;
+ scope.placeHoldertext = attr.placeholderText;
+ if (attr.type) {
+ if (attr.type.indexOf(b2bDropdownConfig.menuKeyword) > -1 || attr.type.indexOf(b2bDropdownConfig.linkMenuKeyword) > -1) {
+ scope.isInputDropdown = false;
+ if (attr.type.indexOf(b2bDropdownConfig.linkMenuKeyword) > -1) {
+ scope.dropdownType = b2bDropdownConfig.linkMenuKeyword;
+ } else if (attr.type.indexOf(b2bDropdownConfig.menuKeyword) > -1) {
+ scope.dropdownType = b2bDropdownConfig.menuKeyword;
+ }
+ }
+ if (attr.type.indexOf(b2bDropdownConfig.largeKeyword) > -1) {
+ scope.dropdownSize = b2bDropdownConfig.largeKeyword;
+ } else if (attr.type.indexOf(b2bDropdownConfig.smallKeyword) > -1) {
+ scope.dropdownSize = b2bDropdownConfig.smallKeyword;
+ }
+ }
+
+ scope.labelText = attr.labelText;
+
+ scope.setBlur = function () {
+ scope.setTouched();
+ };
+
+ if ((scope.isInputDropdown && b2bUserAgent.notMobile()) || (!scope.isInputDropdown)) {
+ var formCtrl = elem.controller('form');
+ scope.setNgModelController = function (name, ngModelCtrl) {
+ if (name && formCtrl && ngModelCtrl) {
+ formCtrl[name] = ngModelCtrl;
+ }
+ };
+ scope.setOptionalCta = function (optionalCta) {
+ scope.optionalCta = optionalCta;
+ };
+ var innerHtml = angular.element('<div></div>').append(elem.html());
+ innerHtml = ($compile(innerHtml)(scope)).html();
+ var template = angular.element($templateCache.get('b2bTemplate/dropdowns/b2bDropdownDesktop.html'));
+ template.find('ul').eq(0).append(innerHtml);
+ template = $compile(template)(scope);
+ elem.replaceWith(template);
+ } else if (scope.isInputDropdown && b2bUserAgent.isMobile()) {
+ elem.css({
+ 'opacity': '0',
+ 'filter': 'alpha(opacity=0)'
+ });
+ elem.addClass('awd-select isWrapped');
+ elem.wrap('<span class="selectWrap"></span>');
+ var cover = angular.element('<span aria-hidden="true"><i class="icon-primary-down" aria-hidden="true"></i></span>');
+ elem.parent().append(cover);
+ elem.parent().append('<i class="icon-primary-down" aria-hidden="true"></i>');
+ var set = function () {
+ var sel = elem[0] ? elem[0] : elem;
+ var selectedText = "";
+ var selIndex = sel.selectedIndex;
+ if (typeof selIndex !== 'undefined') {
+ selectedText = sel.options[selIndex].text;
+ }
+ cover.text(selectedText).append('<i class="icon-primary-down" aria-hidden="true"></i>');
+ };
+ var update = function (value) {
+ $timeout(set, 100);
+ };
+
+ if (attr.ngModel) {
+ scope.$watch(attr.ngModel, function (newVal, oldVal) {
+ update();
+ });
+ }
+ elem.bind('keyup', function (ev) {
+ if (ev.keyCode === keymap.KEY.TAB || ev.keyCode === keymap.KEY.ESC) {
+ return;
+ }
+ set();
+ });
+ }
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ if ((scope.isInputDropdown && b2bUserAgent.notMobile()) || (!scope.isInputDropdown)) {
+ scope.updateModel = function () {
+ if (ctrl.$dirty) {
+ debugger;
+ }
+ ctrl.$setViewValue(scope.currentSelected.value);
+ if (scope.dropdownRequired && scope.currentSelected.value === '') {
+ scope.setRequired(false);
+ } else {
+ scope.setRequired(true);
+ }
+
+ if (scope.dropdownType === b2bDropdownConfig.linkMenuKeyword) {
+ $timeout(function () {
+ scope.appendCaretPositionStyle();
+ }, 100);
+ }
+ };
+ ctrl.$render = function () {
+// if(ctrl.$dirty || ctrl.$pristine) {
+ $timeout(function () {
+
+ if ((angular.isUndefined(ctrl.$viewValue) || ctrl.$viewValue == '') && (angular.isUndefined(scope.placeHoldertext) || scope.placeHoldertext == '')) {
+ scope.dropdownLists[ctrl.$viewValue] && scope.dropdownLists[ctrl.$viewValue][0].updateDropdownValue();
+ } else if ((angular.isUndefined(scope.placeHoldertext) || scope.placeHoldertext == '') && ctrl.$viewValue !== '' ) {
+ scope.dropdownLists[ctrl.$viewValue] && scope.dropdownLists[ctrl.$viewValue][0].updateDropdownValue();
+ } else if ((angular.isUndefined(ctrl.$viewValue) || ctrl.$viewValue == '') && scope.placeHoldertext !== '' ) {
+ scope.currentSelected.text = scope.placeHoldertext;
+ } else {
+ scope.dropdownLists[ctrl.$viewValue] && scope.dropdownLists[ctrl.$viewValue][0].updateDropdownValue();
+ }
+
+ }, 100);
+ };
+// }
+ scope.disabled = false;
+ scope.dropdownName = attr.name;
+ scope.dropdownId = attr.id;
+ scope.labelId = attr.ariaLabelledby;
+ scope.dropdownDescribedBy = attr.ariaDescribedby;
+ if (attr.required) {
+ scope.dropdownRequired = true;
+ } else {
+ scope.dropdownRequired = false;
+ }
+ elem.removeAttr('name');
+ elem.removeAttr('id');
+ scope.$parent.$watch(attr.ngDisabled, function (val) {
+ scope.disabled = val;
+ });
+ }
+ }
+ };
+}])
+
+.directive("b2bDropdownToggle", ['$document', '$documentBind', '$isElement', 'b2bDropdownConfig', 'keymap', 'b2bUtilitiesConfig', '$timeout', '$position', function ($document, $documentBind, $isElement, b2bDropdownConfig, keymap, b2bUtilitiesConfig, $timeout, $position) {
+ return {
+ restrict: 'A',
+ require: '?^b2bKey',
+ link: function (scope, elem, attr, ctrl) {
+ scope.appendCaretPositionStyle = function () {
+ while (document.querySelector('style.b2bDropdownCaret')) {
+ document.querySelector('style.b2bDropdownCaret').remove();
+ };
+ var caretPosition = $position.position(elem).width - 26;
+ if (scope.dropdownType === b2bDropdownConfig.linkMenuKeyword) {
+ var template = angular.element('<style class="b2bDropdownCaret" type="text/css">.linkSelectorModule .active+.moduleWrapper:before {left: ' + caretPosition + 'px;}</style>');
+ $document.find('head').append(template);
+ }
+ };
+
+ if (scope.isInputDropdown && (scope.labelText !== undefined)) {
+ elem.attr('aria-label', scope.labelText);
+ }
+
+ scope.toggleFlag = false;
+ scope.dropdownLists = {};
+ scope.dropdownListValues = [];
+ scope.dropdown = {
+ totalIndex: -1
+ };
+ scope.currentSelected = {
+ value: '',
+ text: '',
+ label: '',
+ index: -1
+ };
+ var searchString = '';
+ var searchElement = function (searchExp) {
+ var regex = new RegExp("\\b" + searchExp, "gi");
+ var position = scope.dropdownListValues.regexIndexOf(regex, scope.currentSelected.index + 1, true);
+ if (position > -1) {
+ return position;
+ }
+ return undefined;
+ };
+ var startTimer = function (time) {
+ if (searchString === '') {
+ $timeout(function () {
+ searchString = '';
+ }, time);
+ }
+ };
+ scope.toggleDropdown = function (toggleFlag) {
+ if (!scope.disabled) {
+ if (angular.isDefined(toggleFlag)) {
+ scope.toggleFlag = toggleFlag;
+ } else {
+ scope.toggleFlag = !scope.toggleFlag;
+ }
+ if (!scope.toggleFlag) {
+ if (scope.isInputDropdown) {
+ elem.parent().find('input')[0].focus();
+ } else {
+ elem.parent().find('button')[0].focus();
+ }
+ } else {
+ scope.dropdown.highlightedValue = scope.currentSelected.value;
+ if (ctrl && ctrl.enableSearch) {
+ if (angular.isDefined(scope.dropdownLists[scope.currentSelected.value])) {
+ ctrl.resetCounter(scope.dropdownLists[scope.currentSelected.value][2]);
+ }
+ }
+ if (scope.dropdownType === b2bDropdownConfig.linkMenuKeyword) {
+ scope.appendCaretPositionStyle();
+ }
+ }
+ }
+ };
+
+ elem.bind('keydown', function (ev) {
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if (!scope.toggleFlag) {
+ if (ev.keyCode) {
+ var currentIndex = scope.currentSelected.index;
+ if (ev.altKey === true && ev.keyCode === keymap.KEY.DOWN) {
+ scope.toggleDropdown(true);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (b2bDropdownConfig.prev.split(',').indexOf(ev.keyCode.toString()) > -1) {
+ angular.isDefined(scope.dropdownListValues[currentIndex - 1]) ? scope.dropdownLists[scope.dropdownListValues[currentIndex - 1]][0].updateDropdownValue() : angular.noop();
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (b2bDropdownConfig.next.split(',').indexOf(ev.keyCode.toString()) > -1) {
+ angular.isDefined(scope.dropdownListValues[currentIndex + 1]) ? scope.dropdownLists[scope.dropdownListValues[currentIndex + 1]][0].updateDropdownValue() : angular.noop();
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode >= 48 && ev.keyCode <= 105) {
+ startTimer(b2bUtilitiesConfig.searchTimer);
+ searchString = searchString + (keymap.MAP[ev.keyCode] || '');
+ var position = searchElement(searchString);
+ angular.isDefined(scope.dropdownListValues[position]) ? scope.dropdownLists[scope.dropdownListValues[position]][0].updateDropdownValue() : angular.noop();
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ }
+ } else {
+ if (ev.altKey === true && ev.keyCode === keymap.KEY.UP) {
+ scope.toggleDropdown(false);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === keymap.KEY.TAB || ev.keyCode === keymap.KEY.ESC) {
+ scope.toggleDropdown(false);
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ }
+ scope.$apply(); // TODO: Move this into each block to avoid expensive digest cycles
+ });
+ var outsideClick = function (e) {
+ var isElement = $isElement(angular.element(e.target), elem.parent(), $document);
+ if (!isElement) {
+ scope.toggleDropdown(false);
+ scope.$apply();
+ }
+ };
+ $documentBind.click('toggleFlag', outsideClick, scope);
+ }
+ };
+}])
+
+.directive("b2bDropdownGroup", ['$compile', '$templateCache', 'b2bUserAgent', function ($compile, $templateCache, b2bUserAgent) {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ if ((scope.isInputDropdown && b2bUserAgent.notMobile()) || (!scope.isInputDropdown)) {
+ var innerHtml = angular.element('<div></div>').append(elem.html());
+ innerHtml = ($compile(innerHtml)(scope)).html();
+ var template = angular.element($templateCache.get('b2bTemplate/dropdowns/b2bDropdownGroupDesktop.html'));
+ template.attr('ng-repeat', attr.optGroupRepeat);
+ template.attr('label', elem.attr('label'));
+ template.find('ul').append(innerHtml);
+ elem.replaceWith(template);
+ } else if (scope.isInputDropdown && b2bUserAgent.isMobile()) {
+ var template = angular.element(elem.prop('outerHTML'));
+ template.attr('ng-repeat', attr.optGroupRepeat);
+ template.removeAttr('b2b-dropdown-group');
+ template.removeAttr('opt-group-repeat');
+ template = $compile(template)(scope);
+ elem.replaceWith(template);
+ }
+ }]
+ };
+}])
+
+.directive("b2bDropdownGroupDesktop", [function () {
+ return {
+ restrict: 'A',
+ scope: true,
+ link: function (scope, elem, attr, ctrl) {
+ scope.groupHeader = attr.label;
+ }
+ };
+}])
+
+.directive("b2bDropdownList", ['$compile', '$templateCache', 'b2bUserAgent', function ($compile, $templateCache, b2bUserAgent) {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ if ((scope.isInputDropdown && b2bUserAgent.notMobile()) || (!scope.isInputDropdown)) {
+ var innerHtml = angular.element('<div></div>').append(elem.html());
+ innerHtml = ($compile(innerHtml)(scope)).html();
+ var template = angular.element($templateCache.get('b2bTemplate/dropdowns/b2bDropdownListDesktop.html'));
+ template.attr('ng-repeat', attr.optionRepeat);
+ template.attr('value', elem.attr('value'));
+ template.attr('search-key', elem.attr('value'));
+ if (elem.attr('aria-describedby')){
+ template.attr('aria-describedby', attr.ariaDescribedby);
+ }
+ if (elem.attr('imgsrc')) {
+ if (elem.attr('imgalt')) {
+ template.append('<img role="presentation" ng-src="' + elem.attr('imgsrc') + '" alt="' + elem.attr('imgalt') + '"/>');
+ } else {
+ template.append('<img role="presentation" ng-src="' + elem.attr('imgsrc') + '" alt=""/>');
+ }
+ }
+ template.append(innerHtml);
+ elem.replaceWith(template);
+ } else if (scope.isInputDropdown && b2bUserAgent.isMobile()) {
+ var template = angular.element(elem.prop('outerHTML'));
+ template.attr('ng-repeat', attr.optionRepeat);
+ if (elem.attr('aria-describedby')){
+ template.attr('aria-describedby', attr.ariaDescribedby);
+ }
+ template.removeAttr('b2b-dropdown-list');
+ template.removeAttr('option-repeat');
+ template = $compile(template)(scope);
+ elem.replaceWith(template);
+ }
+ }]
+ };
+}])
+
+.directive("b2bDropdownListDesktop", ['$sce', 'keymap', 'b2bDropdownConfig', function ($sce, keymap, b2bDropdownConfig) {
+ return {
+ restrict: 'A',
+ scope: true,
+ link: function (scope, elem, attr, ctrl) {
+ var dropdownListValue = scope.dropdownListValue = attr.value;
+ scope.dropdown.totalIndex++;
+ var dropdownListIndex = scope.dropdown.totalIndex;
+ scope.dropdownListValues.push(dropdownListValue);
+ scope.dropdownLists[dropdownListValue] = [];
+ scope.dropdownLists[dropdownListValue][0] = scope;
+ scope.dropdownLists[dropdownListValue][1] = elem;
+ scope.dropdownLists[dropdownListValue][2] = dropdownListIndex;
+ scope.updateDropdownValue = function () {
+ scope.currentSelected.value = dropdownListValue;
+ if (scope.isInputDropdown) {
+ scope.currentSelected.text = elem.text();
+ } else if ((scope.dropdownType === b2bDropdownConfig.linkMenuKeyword) || (scope.dropdownType === b2bDropdownConfig.menuKeyword && scope.dropdownSize === b2bDropdownConfig.smallKeyword)) {
+ scope.currentSelected.text = dropdownListValue;
+ } else if (scope.dropdownType === b2bDropdownConfig.menuKeyword) {
+ scope.currentSelected.text = $sce.trustAsHtml(elem.html());
+ }
+ if (scope.isInputDropdown) {
+ scope.currentSelected.label = elem.text();
+ } else if (scope.dropdownType === b2bDropdownConfig.linkMenuKeyword) {
+ scope.currentSelected.label = dropdownListValue;
+ } else if (scope.dropdownType === b2bDropdownConfig.menuKeyword) {
+ scope.currentSelected.label = elem.text();
+ }
+ scope.currentSelected.index = dropdownListIndex;
+ scope.updateModel();
+ };
+ scope.selectDropdownItem = function () {
+ scope.setDirty();
+ scope.updateDropdownValue();
+ scope.toggleDropdown(false);
+ };
+ scope.highlightDropdown = function () {
+ scope.dropdown.highlightedValue = dropdownListValue;
+ };
+ elem.bind('mouseover', function (ev) {
+ elem[0].focus();
+ });
+ elem.bind('keydown', function (ev) {
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if (ev.altKey === true && ev.keyCode === keymap.KEY.UP) {
+ scope.toggleDropdown(false);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === keymap.KEY.TAB || ev.keyCode === keymap.KEY.ESC) {
+ scope.toggleDropdown(false);
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ scope.$apply();
+ });
+ }
+ };
+}])
+
+.directive("b2bDropdownRepeat", ['$compile', 'b2bUserAgent', function ($compile, b2bUserAgent) {
+ return {
+ restrict: 'A',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ if ((scope.isInputDropdown && b2bUserAgent.notMobile()) || (!scope.isInputDropdown)) {
+ var innerHtml = angular.element('<div></div>').append(elem.html());
+ innerHtml = ($compile(innerHtml)(scope)).html();
+ var template = angular.element('<div></div>');
+ template.attr('ng-repeat', attr.b2bDropdownRepeat);
+ template.append(innerHtml);
+ elem.replaceWith(template);
+ } else if (scope.isInputDropdown && b2bUserAgent.isMobile()) {
+ angular.noop();
+ }
+ }]
+ };
+}])
+
+.directive("b2bDropdownValidation", ['$timeout', function ($timeout) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ $timeout(function () {
+ scope.setNgModelController(attr.name, ctrl);
+ }, 100);
+ scope.setDirty = function () {
+ if (ctrl.$dirty === false) {
+ ctrl.$dirty = true;
+ ctrl.$pristine = false;
+ }
+ };
+ scope.setTouched = function () {
+ if (ctrl.$touched === false) {
+ ctrl.$touched = true;
+ ctrl.$pristine = false;
+ }
+ };
+ scope.setRequired = function (flag) {
+ ctrl.$setValidity('required', flag);
+ };
+ }
+ };
+}])
+
+.directive('b2bDropdownOptionalCta', [function () {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ template: '',
+ compile: function (elem, attr, transclude) {
+ return function link(scope, elem, attr, ctrl) {
+ if (scope.setOptionalCta) {
+ scope.setOptionalCta(transclude(scope, function () {}));
+ }
+ elem.remove();
+ };
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:File Upload
+ *
+ * @description
+ * <file src="src/fileUpload/docs/readme.md" />
+ *
+ * @usage
+ *
+<form id="dragDropFile">
+ <div b2b-file-drop file-model="fileModel" on-drop="triggerFileUpload()" align="center">
+ <p>
+ <br>To upload a file, drag & drop it here or
+ <span b2b-file-link file-model="fileModel" on-file-select="triggerFileUpload()" >
+ click here to select from your computer.
+ </span><br>
+ </p>
+ </div>
+</form>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/fileUpload/docs/demo.html" />
+ <file src="src/fileUpload/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.fileUpload', ['b2b.att.utilities'])
+ .directive('b2bFileDrop', [function() {
+ return {
+ restrict: 'EA',
+ scope: {
+ fileModel: '=',
+ onDrop: '&'
+ },
+ controller: ['$scope', '$attrs', function($scope, $attrs) {
+ this.onDrop = $scope.onDrop;
+ }],
+ link: function(scope, element) {
+ element.addClass('b2b-dragdrop');
+ element.bind(
+ 'dragover',
+ function(e) {
+ if (e.originalEvent) {
+ e.dataTransfer = e.originalEvent.dataTransfer;
+ }
+ e.dataTransfer.dropEffect = 'move';
+ // allows us to drop
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ element.addClass('b2b-dragdrop-over');
+ return false;
+ }
+ );
+ element.bind(
+ 'dragenter',
+ function(e) {
+ // allows us to drop
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ element.addClass('b2b-dragdrop-over');
+ return false;
+ }
+ );
+ element.bind(
+ 'dragleave',
+ function() {
+ element.removeClass('b2b-dragdrop-over');
+ return false;
+ }
+ );
+ element.bind(
+ 'drop',
+ function(e) {
+ // Stops some browsers from redirecting.
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation) {
+ e.stopPropagation();
+ }
+ if (e.originalEvent) {
+ e.dataTransfer = e.originalEvent.dataTransfer;
+ }
+ element.removeClass('b2b-dragdrop-over');
+ if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
+ scope.fileModel = e.dataTransfer.files[0];
+ scope.$apply();
+ if (angular.isFunction(scope.onDrop)) {
+ scope.onDrop();
+ }
+ }
+ return false;
+ }
+ );
+ }
+ };
+ }])
+ .directive('b2bFileLink', [function() {
+ return {
+ restrict: 'EA',
+ require: '^?b2bFileDrop',
+ replace: true,
+ transclude: true,
+ templateUrl: 'b2bTemplate/fileUpload/fileUpload.html',
+ scope: {
+ fileModel: '=?',
+ onFileSelect: '&'
+ },
+ controller: ['$scope', function($scope) {
+ this.setFileModel = function(fileModel) {
+ if ($scope.takeFileModelFromParent) {
+ $scope.$parent.fileModel = fileModel;
+ $scope.$parent.$apply();
+ } else {
+ $scope.fileModel = fileModel;
+ $scope.$apply();
+ }
+ };
+ this.callbackFunction = function() {
+ if (angular.isFunction($scope.onFileSelect)) {
+ $scope.onFileSelect();
+ }
+ };
+
+ }],
+ link: function(scope, element, attr, b2bFileDropCtrl) {
+ scope.takeFileModelFromParent = false;
+ if (!(attr.fileModel) && b2bFileDropCtrl) {
+ scope.takeFileModelFromParent = true;
+ }
+ if (!(attr.onFileSelect) && b2bFileDropCtrl) {
+ scope.onFileSelect = b2bFileDropCtrl.onDrop;
+ }
+ }
+ };
+ }])
+ .directive('b2bFileChange', ['$log', '$rootScope', function($log, $rootScope) {
+ return {
+ restrict: 'A',
+ require: '^b2bFileLink',
+ link: function(scope, element, attr, b2bFileLinkCtrl) {
+ element.bind('change', changeFileModel);
+
+ function changeFileModel(e) {
+ if (e.target.files && e.target.files.length > 0) {
+ b2bFileLinkCtrl.setFileModel(e.target.files[0]);
+ b2bFileLinkCtrl.callbackFunction();
+ } else {
+ var strFileName = e.target.value;
+ try {
+ var objFSO = new ActiveXObject("Scripting.FileSystemObject");
+ b2bFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
+ b2bFileLinkCtrl.callbackFunction();
+ } catch (e) {
+ var errMsg = "There was an issue uploading " + strFileName + ". Please try again.";
+ $log.error(errMsg);
+ $rootScope.$broadcast('b2b-file-link-failure', errMsg);
+ }
+ }
+ }
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:filters
+ *
+ * @description
+ * <file src="src/filters/docs/readme.md" />
+ *
+ * @usage
+ * <div b2b-filters></div>
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/filters/docs/demo.html" />
+ <file src="src/filters/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.filters', ['b2b.att.utilities', 'b2b.att.multipurposeExpander'])
+ .filter('filtersSelectedItemsFilter', [function () {
+ return function (listOfItemsArray) {
+
+ if (!listOfItemsArray) {
+ listOfItemsArray = [];
+ }
+
+ var returnArray = [];
+
+ for (var i = 0; i < listOfItemsArray.length; i++) {
+ for (var j = 0; j < listOfItemsArray[i].filterTypeItems.length; j++) {
+ if (listOfItemsArray[i].filterTypeItems[j].selected && !listOfItemsArray[i].filterTypeItems[j].inProgress) {
+ returnArray.push(listOfItemsArray[i].filterTypeItems[j]);
+ }
+ }
+ }
+
+ return returnArray;
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:flyout
+ *
+ * @description
+ * <file src="src/flyout/docs/readme.md" />
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/flyout/docs/demo.html" />
+ <file src="src/flyout/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.flyout', ['b2b.att.utilities', 'b2b.att.position'])
+ .directive('b2bFlyout', ['$timeout', 'b2bDOMHelper', 'keymap', 'events', function ($timeout, b2bDOMHelper, keymap, events) {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ templateUrl: 'b2bTemplate/flyout/flyout.html',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ scope.flyoutOpened = false;
+ var contentScope = '';
+ var togglerScope = '';
+ this.registerContentScope = function (scp) {
+ contentScope = scp;
+ };
+ this.registerTogglerScope = function (scp) {
+ togglerScope = scp;
+ };
+
+ this.toggleFlyoutState = function () {
+ if (contentScope) {
+ contentScope.toggleFlyout();
+ }
+ };
+ this.getTogglerDimensions = function () {
+ return togglerScope.getTogglerDimensions();
+ }
+ this.setTogglerFocus = function () {
+ return togglerScope.setTogglerFocus();
+ }
+
+ this.closeFlyout = function (e) {
+ contentScope.closeFromChild(e);
+ };
+ this.gotFocus = function () {
+ contentScope.gotFocus();
+ };
+
+ this.updateAriaModel = function (val) {
+ scope.flyoutOpened = val;
+ };
+
+ var firstTabableElement = undefined,
+ lastTabableElement = undefined;
+
+ var firstTabableElementKeyhandler = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+ if (e.keyCode === keymap.KEY.TAB && e.shiftKey && scope.flyoutOpened) {
+ contentScope.gotFocus();
+ events.preventDefault(e);
+ events.stopPropagation(e);
+ }
+ };
+
+ var lastTabableElementKeyhandler = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+ if (e.keyCode === keymap.KEY.TAB && !e.shiftKey) {
+ contentScope.gotFocus();
+ events.preventDefault(e);
+ events.stopPropagation(e);
+ }
+ };
+ this.associateTabEvent = function(){
+ $timeout(function () {
+ var element = elem[0].getElementsByClassName('b2b-flyout-container')[0];
+ firstTabableElement = b2bDOMHelper.firstTabableElement(element);
+ lastTabableElement = b2bDOMHelper.lastTabableElement(element);
+ if(angular.isUndefined(firstTabableElement)){
+ angular.element(element).css('display','block');
+ firstTabableElement = b2bDOMHelper.firstTabableElement(element);
+ lastTabableElement = b2bDOMHelper.lastTabableElement(element);
+ angular.element(element).css('display','none');
+ }
+ angular.element(firstTabableElement).bind('keydown', firstTabableElementKeyhandler);
+ angular.element(lastTabableElement).bind('keydown', lastTabableElementKeyhandler);
+ });
+ }
+ this.updateTabbableElements = function(){
+ $timeout(function () {
+ var element = elem[0].getElementsByClassName('b2b-flyout-container')[0];
+ angular.element(element).css('display','block');
+ firstTabableElement = b2bDOMHelper.firstTabableElement(element);
+ lastTabableElement = b2bDOMHelper.lastTabableElement(element);
+ angular.element(firstTabableElement).bind('keydown', firstTabableElementKeyhandler);
+ angular.element(lastTabableElement).bind('keydown', lastTabableElementKeyhandler);
+ angular.element(element).css('display','none');
+ });
+ }
+ this.unbindTabbaleEvents = function(){
+ if(angular.isDefined(firstTabableElement)){
+ angular.element(firstTabableElement).unbind('keydown', firstTabableElementKeyhandler);
+ }
+
+ if(angular.isDefined(lastTabableElement)){
+ angular.element(lastTabableElement).unbind('keydown', lastTabableElementKeyhandler);
+ }
+ }
+ }],
+ link: function (scope, element, attrs, ctrl) {
+
+ }
+ };
+ }])
+ .directive('b2bFlyoutToggler', [function () {
+ return {
+ restrict: 'A',
+ require: '^b2bFlyout',
+ link: function (scope, element, attrs, ctrl) {
+ element.bind('click', function (e) {
+ ctrl.toggleFlyoutState();
+ });
+
+ scope.getTogglerDimensions = function () {
+ return element[0].getBoundingClientRect();
+ }
+
+ scope.setTogglerFocus = function () {
+ element[0].focus();
+ }
+
+ ctrl.registerTogglerScope(scope);
+ }
+ };
+ }])
+ .directive('b2bFlyoutContent', ['$position', '$timeout', '$documentBind', '$isElement', '$document', function ($position, $timeout, $documentBind, $isElement, $document) {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ require: '^b2bFlyout',
+ scope: {
+ horizontalPlacement: '@',
+ verticalPlacement: '@',
+ flyoutStyle: '@',
+ flyoutTitle: '@',
+ contentUpdated: "=?"
+ },
+ templateUrl: 'b2bTemplate/flyout/flyoutContent.html',
+ link: function (scope, element, attrs, ctrl) {
+ var flyoutStyleArray, eachCssProperty, cssPropertyKey, cssPropertyVal, temp;
+ scope.openFlyout = false;
+ if (!scope.horizontalPlacement) {
+ scope.horizontalPlacement = 'center';
+ }
+ if (!scope.verticalPlacement) {
+ scope.verticalPlacement = 'below';
+ }
+
+ scope.toggleFlyout = function () {
+
+ scope.openFlyout = !scope.openFlyout;
+
+ if (scope.openFlyout) {
+
+ if (angular.isDefined(scope.flyoutStyle) && scope.flyoutStyle != "") {
+ flyoutStyleArray = scope.flyoutStyle.split(";");
+ for (i = 0; i < flyoutStyleArray.length; i++) {
+ eachCssProperty = flyoutStyleArray[i].split(":");
+ if (eachCssProperty.length == 2) {
+ cssPropertyKey = eachCssProperty[0].trim();
+ cssPropertyVal = eachCssProperty[1].trim();
+ angular.element(element[0])[0].style[cssPropertyKey] = cssPropertyVal;
+ }
+ }
+ }
+
+ angular.element(element[0]).css({
+ 'opacity': 0,
+ 'display': 'block'
+ });
+
+ var flyoutIcons = angular.element(document.querySelectorAll(".b2b-flyout-icon"));
+ angular.forEach(flyoutIcons, function (elm) {
+ angular.element(elm)[0].blur();
+ });
+
+ $timeout(function () {
+ ctrl.setTogglerFocus();
+
+ var togglerDimensions = ctrl.getTogglerDimensions();
+ var flyoutDimensions = element[0].getBoundingClientRect();
+
+ switch (scope.horizontalPlacement) {
+ case "left":
+ angular.element(element[0]).css({
+ 'left': ((togglerDimensions.width / 2) - 26) + 'px'
+ });
+ break;
+ case "right":
+ angular.element(element[0]).css({
+ 'right': ((togglerDimensions.width / 2) - 23) + 'px'
+ });
+ break;
+
+ case "centerLeft":
+ var marginLeft = 10-(flyoutDimensions.width)-20;
+ angular.element(element[0]).css({
+ 'margin-left': marginLeft + 'px'
+ });
+ break;
+ case "centerRight":
+ angular.element(element[0]).css({
+ 'left': ((togglerDimensions.width + 9 )) + 'px'
+ });
+ break;
+
+ default:
+ var marginLeft = (togglerDimensions.width / 2) - (flyoutDimensions.width / 2) - 8;
+ angular.element(element[0]).css({
+ 'margin-left': marginLeft + 'px'
+ });
+ }
+
+ switch (scope.verticalPlacement) {
+ case "above":
+ angular.element(element[0]).css({
+ 'top': -(flyoutDimensions.height + 13) + 'px'
+ });
+ break;
+ case "centerLeft":
+ angular.element(element[0]).css({
+ 'top': -((togglerDimensions.height-13))+ 'px'
+ });
+ break;
+ case "centerRight":
+ angular.element(element[0]).css({
+ 'top': -(flyoutDimensions.height - 23)+ 'px'
+ });
+ break;
+ default:
+ angular.element(element[0]).css({
+ 'top': (togglerDimensions.height + 13) + 'px'
+ });
+ }
+
+ angular.element(element[0]).css({
+ 'opacity': 1
+ });
+ }, 100);
+ } else {
+ scope.hideFlyout();
+ }
+ };
+
+ scope.gotFocus = function () {
+ scope.openFlyout = false;
+ scope.hideFlyout();
+ ctrl.setTogglerFocus();
+ scope.$apply();
+ };
+
+ scope.closeFromChild = function (e) {
+ scope.openFlyout = false;
+ scope.hideFlyout();
+ ctrl.setTogglerFocus();
+ scope.$apply();
+ };
+
+ scope.hideFlyout = function () {
+ angular.element(element[0]).css({
+ 'opacity': 0,
+ 'display': 'none'
+ });
+ };
+
+ scope.closeFlyout = function (e) {
+ var isElement = $isElement(angular.element(e.target), element, $document);
+ if ((e.type === "keydown" && e.which === 27) || ((e.type === "click" || e.type==="touchend") && !isElement)) {
+ scope.openFlyout = false;
+ scope.hideFlyout();
+ ctrl.setTogglerFocus();
+ scope.$apply();
+ }
+ };
+
+ scope.$watch('openFlyout', function () {
+ ctrl.updateAriaModel(scope.openFlyout);
+ });
+
+ $documentBind.click('openFlyout', scope.closeFlyout, scope);
+ $documentBind.event('keydown', 'openFlyout', scope.closeFlyout, scope);
+ $documentBind.event('touchend', 'openFlyout', scope.closeFlyout, scope);
+ ctrl.registerContentScope(scope);
+
+ if (angular.isDefined(scope.contentUpdated) && scope.contentUpdated !== null) {
+ scope.$watch('contentUpdated', function (newVal, oldVal) {
+ if(newVal){
+ if (newVal !== oldVal) {
+ ctrl.unbindTabbaleEvents();
+ ctrl.associateTabEvent();
+ }
+ scope.contentUpdated = false;
+ }
+ });
+ }
+
+ }
+ };
+ }])
+ .directive('b2bCloseFlyout', [function () {
+ return {
+ restrict: 'A',
+ require: '^b2bFlyout',
+ scope: {
+ closeFlyout: '&'
+ },
+ link: function (scope, element, attrs, ctrl) {
+ element.bind('click', function (e) {
+ scope.closeFlyout(e);
+ ctrl.closeFlyout(e);
+ });
+ }
+ };
+ }])
+ .directive('b2bFlyoutTrapFocusInside', [function () {
+ return {
+ restrict: 'A',
+ transclude: false,
+ require: '^b2bFlyout',
+ link: function (scope, elem, attr, ctrl) {
+ /* Before opening modal, find the focused element */
+ ctrl.updateTabbableElements();
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Layouts.att:footer
+ *
+ * @description
+ * <file src="src/footer/docs/readme.md" />
+ *
+ * @usage
+ *
+ <footer class="b2b-footer-wrapper" role="contentinfo" aria-label="footer">
+ <div class="b2b-footer-container" b2b-column-switch-footer footer-link-items='footerItems'>
+ <hr>
+ <div class="divider-bottom-footer">
+ <div class="span2 dispalyInline">&nbsp;</div>
+ <div class="span6 dispalyInline">
+ <ul class="footer-nav-content">
+ <li><a href="Terms_of_use.html" title="Terms of use" id="foot0">Terms of use</a>|</li>
+ <li><a href="Privacy_policy.html" title="Privacy policy" id="foot1" class="active">Privacy policy</a>|</li>
+ <li><a href="Tollfree_directory_assistance.html" title="Tollfree directory assistance" id="foot2">Tollfree directory assistance</a>|</li>
+ <li><a href="compliance.html" title="Accessibility" id="foot3">Accessibility</a></li>
+
+ </ul>
+ <p><a href="//www.att.com/gen/privacy-policy?pid=2587" target="_blank">© <span class="copyright">2016</span> AT&amp;T Intellectual Property</a>. All rights reserved. AT&amp;T,the AT&amp;T Globe logo and all other AT&amp;T marks contained herein are tardemarks of AT&amp;T intellectual property and/or AT&amp;T affiliated companines.
+
+ </p>
+ </div>
+ <div class="span3 footerLogo dispalyInline">
+ <a href="index.html" class="footer-logo">
+ <i class="icon-primary-att-globe"><span class="hidden-spoken">A T &amp; T</span></i>
+ <h2 class="logo-title">AT&amp;T</h2>
+ </a>
+ </div>
+ </div>
+
+ </div>
+ </footer>
+
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/footer/docs/demo.html" />
+ <file src="src/footer/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.footer', ['b2b.att.utilities']).
+ directive('b2bColumnSwitchFooter', [function() {
+ return {
+ restrict: 'A',
+ transclude: true,
+ scope: {
+ footerLinkItems: "="
+ },
+ templateUrl: 'b2bTemplate/footer/footer_column_switch_tpl.html',
+ link: function(scope) {
+ var tempFooterColumns = scope.footerLinkItems.length;
+ scope.footerColumns = 3;
+ if ( (tempFooterColumns === 5) || (tempFooterColumns === 4) ) {
+ scope.footerColumns = tempFooterColumns;
+ }
+ }
+
+ };
+
+ }]);
+
+
+/**
+ * @ngdoc directive
+ * @name Layouts.att:header
+ *
+ * @description
+ * <file src="src/header/docs/readme.md" />
+ *
+ * @usage
+ * <li b2b-header-menu class="header__item b2b-headermenu" ng-repeat="item in tabItems" role="presentation">
+ <a href="#" class="menu__item" role="menuitem">{{item.title}}</a>
+ <div class="header-secondary-wrapper">
+ <ul class="header-secondary" role="menu">
+ <li class="header-subitem" b2b-header-submenu ng-repeat="i in item.subitems" role="presentation">
+ <a href="#" class="menu__item" aria-haspopup="true" role="menuitem">{{i.value}}</a>
+ <div class="header-tertiary-wrapper" ng-if="i.links">
+ <ul class="header-tertiary" role="menu">
+ <li b2b-header-tertiarymenu ng-repeat="link in i.links" role="presentation">
+ <label>{{link.title}}</label>
+ <div b2b-tertiary-link ng-repeat="title in link.value">
+ <a href="{{link.href}}" class="header-tertiaryitem" ng-if="!title.subitems" aria-haspopup="false" role="menuitem"><span class="b2b-label-hide">{{link.title}}</span>{{title.title}}</a>
+ <a href="{{link.href}}" class="header-tertiaryitem" b2b-header-togglemenu ng-if="title.subitems" aria-haspopup="true" role="menuitem"><span class="b2b-label-hide">{{link.title}}</span>{{title.title}}</a>
+ <ul class="header-quarternary" role="menu" ng-if="title.subitems">
+ <li b2b-header-quarternarymenu role="presentation">
+ <a href="{{nav.href}}" ng-repeat="nav in title.subitems" role="menuitem" aria-haspopup="true">{{nav.title}}</a>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </li>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att.header">
+ <file src="src/header/docs/demo.html" />
+ <file src="src/header/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.header', ['b2b.att.dropdowns','b2b.att.utilities'])
+ .directive('b2bHeaderMenu', ['keymap', '$documentBind', '$timeout', '$isElement', '$document', function (keymap, $documentBind, $timeout, $isElement, $document) {
+ return {
+ restrict: 'A',
+ controller:['$scope',function($scope){
+ this.nextSiblingFocus = function (elObj,flag) {
+ if (elObj.nextElementSibling) {
+ if(flag){
+ var nextmenuItem = this.getFirstElement(elObj.nextElementSibling,'a');
+ nextmenuItem.focus();
+ }else{
+ elObj.nextElementSibling.focus();
+ }
+ }
+ };
+
+ this.previousSiblingFocus = function (elObj,flag) {
+ if (elObj.previousElementSibling) {
+ if(flag){
+ var prevmenuItem = this.getFirstElement(elObj.previousElementSibling,'a');
+ prevmenuItem.focus();
+ }else{
+ elObj.previousElementSibling.focus();
+ }
+ }
+ };
+
+ this.getFirstElement = function(elmObj,selector){
+ return elmObj.querySelector(selector);
+ };
+ }],
+ link: function (scope, elem,attr,ctrl) {
+ scope.showMenu = false;
+ var activeElm, subMenu, tertiaryMenu, el= angular.element(elem)[0],
+ menuItem = angular.element(elem[0].children[0]);
+ menuItem.bind('click', function () {
+ elem.parent().children().removeClass('active');
+ elem.addClass('active');
+ var elems= this.parentElement.parentElement.querySelectorAll('li[b2b-header-menu]>a');
+ for (var i=0; i<elems.length; i++) {
+ elems[i].setAttribute("aria-expanded",false);
+ }
+ scope.showMenu = true;
+ var elmTofocus = ctrl.getFirstElement(this.parentElement,'li[b2b-header-submenu]');
+ elmTofocus.firstElementChild.focus();
+ this.setAttribute('aria-expanded',true);
+ scope.$apply();
+ });
+
+ elem.bind('keydown', function (evt) {
+ activeElm = document.activeElement;
+ subMenu = ctrl.getFirstElement(activeElm.parentElement,'li[b2b-header-submenu]');
+ tertiaryMenu = ctrl.getFirstElement(activeElm.parentElement,'li[b2b-header-tertiarymenu]');
+ switch (evt.keyCode) {
+ case keymap.KEY.ENTER:
+ case keymap.KEY.SPACE:
+ elem[0].click();
+ break;
+ case keymap.KEY.UP:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if (activeElm.parentElement.hasAttribute('b2b-header-submenu')) {
+ menuItem[0].focus();
+ }
+ break;
+ case keymap.KEY.DOWN:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if (subMenu) {
+ subMenu.firstElementChild.focus();
+ } else if (tertiaryMenu) {
+ var firstSubitem = ctrl.getFirstElement(tertiaryMenu,'a.header-tertiaryitem');
+ firstSubitem.focus();
+ }
+ break;
+ case keymap.KEY.RIGHT:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if (activeElm.parentElement.hasAttribute('b2b-header-submenu')) {
+ var elm = angular.element(activeElm.parentElement)[0];
+ ctrl.nextSiblingFocus(elm,true);
+ } else if (activeElm.parentElement.parentElement.hasAttribute('b2b-header-tertiarymenu')) {
+ var tertiaryLI = angular.element(activeElm.parentElement.parentElement)[0];
+ if (tertiaryLI.nextElementSibling) {
+ var nextElm = ctrl.getFirstElement(tertiaryLI.nextElementSibling,"a.header-tertiaryitem");
+ nextElm.focus();
+ }
+ }
+ else if(activeElm.parentElement.hasAttribute('b2b-header-menu')){
+ ctrl.nextSiblingFocus(el,true);
+ }
+ break;
+ case keymap.KEY.LEFT:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if (activeElm.parentElement.hasAttribute('b2b-header-submenu')) {
+ var previousElm = angular.element(activeElm.parentElement)[0];
+ ctrl.previousSiblingFocus(previousElm,true);
+ } else if (activeElm.parentElement.parentElement.hasAttribute('b2b-header-tertiarymenu')) {
+ var tertiaryLI = angular.element(activeElm.parentElement.parentElement)[0];
+ if (tertiaryLI.previousElementSibling) {
+ var prevElm = ctrl.getFirstElement(tertiaryLI.previousElementSibling,"a.header-tertiaryitem");
+ prevElm.focus();
+ }
+ }
+ else if(activeElm.parentElement.hasAttribute('b2b-header-menu')) {
+ ctrl.previousSiblingFocus(el,true);
+ }
+ break;
+ case keymap.KEY.ESC:
+ evt.stopPropagation();
+ evt.preventDefault();
+ scope.showMenu = false;
+ elem.removeClass('active');
+ menuItem.attr('aria-expanded',false);
+ $timeout(function(){
+ menuItem[0].focus();
+ },100);
+ scope.$apply();
+ break;
+ default:
+ break;
+ }
+ });
+ var outsideClick = function (e) {
+ var isElement = $isElement(angular.element(e.target), elem, $document);
+ if (!isElement) {
+ scope.showMenu = false;
+ elem.removeClass('active');
+ scope.$apply();
+ }
+ };
+ $documentBind.click('showMenu', outsideClick, scope);
+ }
+ };
+ }]).directive('b2bHeaderSubmenu', ['$timeout',function ($timeout) {
+ return{
+ restrict: 'A',
+ link: function (scope, elem) {
+ var caretSign = angular.element("<i class='menuCaret'></i>");
+ $timeout(function(){
+ var menuItem = angular.element(elem[0].children[0]);
+ menuItem.bind('focus mouseenter', function () {
+ elem.parent().children().removeClass('active');
+ elem.addClass('active');
+ if(elem[0].childElementCount > 1){ // > 1 has third level menu
+ menuItem.attr('aria-expanded',true);
+ menuItem.attr('aria-haspopup',true);
+ }
+ var caretLeft = (elem[0].offsetLeft + elem[0].offsetWidth/2) - 10;
+ caretSign.css({left: caretLeft + 'px'});
+ angular.element(caretSign);
+ var tertiaryItems = elem[0].querySelectorAll('[b2b-header-tertiarymenu]');
+ if(tertiaryItems.length >=1){
+ elem.append(caretSign);
+ }
+ });
+ menuItem.bind('blur', function () {
+ $timeout(function () {
+ var parentElm = document.activeElement.parentElement.parentElement;
+ if(parentElm){
+ if (!(parentElm.hasAttribute('b2b-header-tertiarymenu'))) {
+ elem.removeClass('active');
+ if(elem[0].childElementCount > 1){ // > 1 has third level menu
+ menuItem.attr('aria-expanded',false);
+ }
+ var caret = elem[0].querySelector('.menuCaret');
+ if(caret){
+ caret.remove();
+ }
+ }
+ }
+ });
+ });
+ });
+ }
+ };
+ }]).directive('b2bHeaderTertiarymenu', ['$timeout','keymap', function ($timeout,keymap){
+ return{
+ restrict: 'A',
+ require:'^b2bHeaderMenu',
+ link: function (scope, elem,attr,ctrl) {
+
+ elem.bind('keydown', function (evt) {
+ var activeElm = document.activeElement;
+ var activeParentElm = activeElm.parentElement;
+ var activeParentObj = angular.element(activeParentElm)[0];
+
+ if(activeParentElm.hasAttribute('b2b-tertiary-link')){
+ var quarterNav = angular.element(activeParentElm)[0].querySelector('li[b2b-header-quarternarymenu]');
+ if(quarterNav){
+ var links = ctrl.getFirstElement(angular.element(quarterNav)[0],'a');
+ }
+ }
+ var tertiaryMenu = activeElm.parentElement.parentElement.parentElement;
+ var tertiaryMenuFlag = tertiaryMenu.hasAttribute('b2b-tertiary-link');
+
+ switch (evt.keyCode) {
+ case keymap.KEY.DOWN:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if (activeParentElm.hasAttribute('b2b-tertiary-link')) {
+ if(angular.element(quarterNav).hasClass('active')){
+ links.focus();
+ }else if(activeParentObj.nextElementSibling){
+ ctrl.nextSiblingFocus(activeParentObj,true);
+ }
+ }
+ else if(angular.element(activeParentElm).hasClass('active')){
+ ctrl.nextSiblingFocus(activeElm);
+ }
+ break;
+ case keymap.KEY.UP:
+ evt.stopPropagation();
+ evt.preventDefault();
+ if(activeParentElm.hasAttribute('b2b-tertiary-link')){
+ if(activeParentObj.previousElementSibling.hasAttribute('b2b-tertiary-link')){
+ ctrl.previousSiblingFocus(activeParentObj,true);
+ }else{
+ var elm = angular.element(activeElm.parentElement.parentElement.parentElement.parentElement.parentElement)[0];
+ ctrl.getFirstElement(elm,"a").focus();
+ }
+ }else if(angular.element(activeParentElm).hasClass('active')){
+ if (activeElm.previousElementSibling) {
+ ctrl.previousSiblingFocus(activeElm);
+ }else if (tertiaryMenuFlag) {
+ var elm = angular.element(tertiaryMenu)[0];
+ ctrl.getFirstElement(elm,"a.header-tertiaryitem").focus();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ };
+ }]).directive('b2bHeaderTogglemenu', ['$timeout', 'keymap', function ($timeout, keymap) {
+ return{
+ restrict: 'A',
+ require: '^b2bHeaderMenu',
+ link: function (scope, elem, attrs, ctrl) {
+ var quarterNav;
+ $timeout(function () {
+ quarterNav = angular.element(elem.parent())[0].querySelector('li[b2b-header-quarternarymenu]');
+ elem.bind('click', function () {
+ angular.element(quarterNav).toggleClass('active');
+ });
+ });
+ }
+ };
+ }]).directive('b2bHeaderResponsive', ['$timeout',function ($timeout) {
+ return{
+ restrict: 'A',
+ controller: function($scope){
+ this.applyMediaQueries = function(value){
+ document.querySelector('style').textContent +=
+ "@media screen and (max-width:950px) { \
+ .header__item.profile { right: " + value + "px; } \
+ }";
+ };
+ this.arrangeResponsiveHeader = function(children){
+ /*
+ * clientWidth of 1090 === max-width of 1100px
+ * clientWidth of 920 === max-width of 950px
+ * see b2b-angular.css for rest of responsive header CSS
+ */
+ if (document.documentElement.clientWidth <= 920) {
+ switch(children){
+ case 1:
+ this.applyMediaQueries(200);
+ break;
+ case 2:
+ this.applyMediaQueries(200);
+ break;
+ default: // anthing above 3, however, should not have more than 3 to date
+ this.applyMediaQueries(200);
+ }
+ }
+ }
+ },
+ link: function (scope, elem, attrs, ctrl) {
+ var children;
+ var profile;
+
+ // onload of page
+ $timeout(function(){
+ profile = document.querySelector('li.header__item.profile');
+ children = angular.element(profile).children().length;
+
+ ctrl.arrangeResponsiveHeader(children); // shift right-side icon flyovers
+ });
+
+ // on screen resize
+ window.addEventListener('resize', function(event){ // caret adjustmet
+ var activeSubmenu = elem[0].querySelector('[b2b-header-menu] [b2b-header-submenu].active');
+ var activeSubmenuEl = angular.element(activeSubmenu);
+ if(activeSubmenu){
+ var caretSign = activeSubmenu.querySelector('i.menuCaret');
+ if(caretSign){
+ var caretSignEl = angular.element(caretSign);
+ var caretLeft = (activeSubmenu.offsetLeft + activeSubmenu.offsetWidth/2) - 10;
+ caretSignEl.css({left: caretLeft + 'px'});
+ }
+ }
+
+ ctrl.arrangeResponsiveHeader(children); // shift right-side icon flyovers
+ });
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Layouts.att:headings
+ *
+ * @description
+ * <file src="src/headings/docs/readme.md" />
+ *
+ * @usage
+ <h1 class="heading-page">38px page heading</h1>
+ <h2 class="heading-major-section">30px major section heading</h2>
+ <h3 class="heading-sub-section">24px sub-section heading</h3>
+ <h2 class="heading-medium">20px medium heading</h2>
+ <h2 class="heading-medium-emphasis">20px medium emphasis heading</h2>
+ <h3 class="heading-small">18px small heading</h3>
+ <h3 class="heading-small-emphasis">18px small emphasis heading</h3>
+ <h3 class="heading-micro">13px micro heading</h3>
+
+ <h2 class="heading-group">Lead</h2>
+ <h1 class="heading-page">This is 38px heading</h1>
+ <h2 class="lead">This is lead text...The next big thing since the last big thing we announced.</h2>
+ <h2 class="heading-group">Eyebrow</h2>
+ <h3 class="eyebrow">EYEBROW TEXT</h3>
+ <h2 class="heading-major-section">This is a 30px heading</h2>
+ <h3 class="eyebrow">EYEBROW TEXT</h3>
+ <h3 class="heading-sub-section">24px sub-section heading</h3>
+ <h2 class="heading-group">Subheading</h2>
+ <h2 class="heading-major-section">This is a 30px heading</h2>
+ <h3 class="subheading">A subheading here to support what was said above</h3>
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/headings/docs/demo.html" />
+</example>
+</section>
+ */
+
+var b2bLegalCopy = angular.module('b2b.att.headings', []);
+/**
+ * @ngdoc directive
+ * @name Tabs, tables & accordions.att:horizontalTable
+ *
+ * @description
+ * <file src="src/horizontalTable/docs/readme.md" />
+ *
+ * @usage
+ * @param {int} sticky - Number of sticky columns to have. Maximum of 3.
+ * @param {boolean} refresh - A boolean that when set to true will force a re-render of table. Only use when using 'bulk mode'
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/horizontalTable/docs/demo.html" />
+ <file src="src/horizontalTable/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.horizontalTable', [])
+ .constant('b2bHorizontalTableConfig', {
+ 'maxStickyColumns': 3
+ })
+ .directive('b2bHorizontalTable', ['$timeout', 'b2bHorizontalTableConfig', 'b2bDOMHelper', function ($timeout, b2bHorizontalTableConfig, b2bDOMHelper) {
+ return {
+ restrict: 'EA',
+ scope: true,
+ transclude: true,
+ scope: {
+ numOfStickyCols: '=?sticky',
+ refresh: '=?'
+
+ },
+ templateUrl: 'b2bTemplate/horizontalTable/horizontalTable.html',
+ link: function (scope, element, attrs, ctrl) {
+ scope.numOfStickyCols = scope.numOfStickyCols || 1;
+ scope.viewportIndex = scope.numOfStickyCols;
+
+ // JM520E: This is a temporary hack until I solve the ngRepeat issue
+ function hack() {
+ if (element.find('th').length < scope.numOfStickyCols) {
+ // DOM ngRepeat is not ready, let's check back in 10 ms
+ console.info('THs are not ready, trying again in 10ms');
+ $timeout(hack, 10, false);
+ } else {
+ init();
+ }
+ }
+ hack();
+
+ if (attrs.refresh !== undefined && attrs.refresh !== '') {
+ scope.$watch('refresh', function(oldVal, newVal) {
+ if (scope.refresh) {
+ // From testing it takes about 30 ms before ngRepeat executes, so let's set initial timeout
+ // NOTE: May need to expose timeout to developers. Application is known to have digest cycle of 3-5k watches.
+ $timeout(init, 100, false);
+ scope.refresh = false;
+ }
+ });
+ }
+
+ var tableElement = element.find('table');
+ var thElements = element.find('th');
+ var innerContainer = angular.element(element[0].querySelector('.b2b-horizontal-table-inner-container'));
+ var outerContainer = angular.element(element[0].querySelector('.b2b-horizontal-table'));
+
+ var tableColumns = [];
+ var tableRows = element.find('tr');
+
+ var maxWidth = 0,
+ maxHeight = 0;
+ var totalWidth = element.children()[0].offsetWidth;
+ var lastVisibleColumn = 0;
+ var collectiveColumnWidth = [];
+ var collectiveRowHeight = [];
+ var columnSets = [];
+ var setIndex = 0;
+ var stickyPixels = 0;
+
+ var displayNoneCSS = {'display': 'none'};
+ var displayBlockCSS = {'display': 'table-cell'};
+
+ function calculateVisibleColumns(startingPoint) {
+ var usedWidth = 0,
+ visibleColumns = startingPoint || scope.numOfStickyCols;
+
+ while(usedWidth < stickyPixels && visibleColumns < collectiveColumnWidth.length) {
+ if (usedWidth+collectiveColumnWidth[visibleColumns] > stickyPixels) {
+ if (startingPoint === visibleColumns) {
+ return visibleColumns; // The next cell is too large to fit, it should be only thing to fit
+ }
+ visibleColumns--;
+ return visibleColumns;
+ }
+ usedWidth += collectiveColumnWidth[visibleColumns];
+ visibleColumns++;
+ }
+
+ if (usedWidth > stickyPixels) {
+ return --visibleColumns;
+ }
+ return visibleColumns;
+ }
+
+ function updateCellDisplay(set) {
+ for (var i = scope.numOfStickyCols; i < tableColumns.length; i++) {
+ angular.element(tableColumns[i]).css(displayNoneCSS);
+ }
+
+ for (var i = set[0]; i <= set[1]; i++) {
+ angular.element(tableColumns[i]).css(displayBlockCSS);
+ }
+ }
+
+ function forceDigest() {
+ if (!scope.$$phase) {
+ scope.$digest();
+ }
+ }
+
+ function findMax(arr, prop) {
+ var max = 0;
+ var localVal = 0;
+ var prevDisplay;
+ var item;
+ for (var i = 0; i < arr.length; i++) {
+ item = arr[i];
+ prevDisplay = angular.element(item).css('display');
+ if (scope.$$phase) {
+ scope.$digest();
+ }
+ if (prop === 'width') {
+ localVal = Math.ceil(parseInt(window.getComputedStyle(item).width.split('px')[0], 10)) + 30; // 30 px is padding
+ } else if (prop === 'offsetWidth') {
+ localVal = item.offsetWidth;
+ } else if (prop === 'height') {
+ localVal = item.offsetHeight;
+ }
+
+ if (localVal >= max) {
+ max = localVal;
+ }
+ }
+
+ return max;
+ }
+
+ function init() {
+ // Reset this from a previous execution
+ tableColumns = [];
+ collectiveColumnWidth = [];
+ collectiveRowHeight = [];
+ maxWidth = 0;
+ maxHeight = 0;
+ lastVisibleColumn = 0;
+ columnSets = [];
+ setIndex = 0;
+ visibleColumns = [];
+ stickyPixels = 0;
+
+ tableElement = element.find('table');
+ thElements = element.find('th');
+ innerContainer = angular.element(element[0].querySelector('.b2b-horizontal-table-inner-container'));
+ outerContainer = angular.element(element[0].querySelector('.b2b-horizontal-table'));
+ totalWidth = element.children()[0].offsetWidth;
+
+
+ tableRows = element.find('tr');
+ totalWidth = element.children()[0].offsetWidth;
+
+ scope.disableLeft = true;
+ scope.disableRight = false;
+
+ if (scope.numOfStickyCols > b2bHorizontalTableConfig.maxStickyColumns) {
+ throw new Error("Table can only support 3 sticky columns.");
+ }
+
+ angular.forEach(tableRows, function(row, rowIndex) {
+ collectiveRowHeight.push(findMax(row.children, 'height'));
+ for(var j = 0; j < row.children.length; j++) {
+ if (tableColumns[j] === undefined) {
+ tableColumns[j] = [];
+ }
+ tableColumns[j].push(row.children[j]);
+ }
+ });
+
+ // We need to reset all the displayNones from previous runs, if applicable
+ if (attrs.refresh !== undefined && attrs.refresh !== '') {
+ for (var i = scope.numOfStickyCols+1; i < tableColumns.length; i++) {
+ angular.element(tableColumns[i]).css(displayBlockCSS);
+ }
+ }
+
+ for (var i = 0; i < tableColumns.length; i++) {
+ collectiveColumnWidth.push(findMax(tableColumns[i], 'width')); //offsetWidth doesn't take into account custom css inside
+ }
+ for(var i = 0; i < scope.numOfStickyCols; i++) {
+ maxWidth += collectiveColumnWidth[i];
+ }
+
+ stickyPixels = totalWidth-maxWidth;
+
+
+ // At this point, for each tr, I need to set the properties (height) and each numOfStickyCols children
+ // should be set with sticky properties (margin-left and width)
+ var width = maxWidth;
+ for(var i = 0; i < scope.numOfStickyCols; i++) {
+ for (var j = 0; j < tableRows.length; j++) {
+ trObject = angular.element(tableRows[j].children[i]);
+
+ angular.element(trObject).css({
+ 'margin-left': -(width + 2) + 'px',
+ 'width': (collectiveColumnWidth[i] + 3) + 'px', // instead of taking the max width, grab max width for that column
+ 'height': collectiveRowHeight[j] + 'px',
+ 'position': 'absolute',
+ 'background-color': 'lightgrey'
+ });
+ }
+
+
+ width -= collectiveColumnWidth[i];
+ }
+
+ innerContainer.css({
+ 'padding-left': (maxWidth + 2) + 'px'
+ });
+
+
+ // Let's precompute all the (set) combinations beforehand
+ columnSets = [];
+ for (var i = scope.numOfStickyCols; i < tableColumns.length;) {
+ visibleColumns = calculateVisibleColumns(i);
+ columnSets.push([i, visibleColumns]);
+ i = visibleColumns + 1;
+ }
+
+ updateCellDisplay(columnSets[setIndex]);
+ checkScrollArrows();
+
+ scope.numOfCols = tableColumns.length;
+
+ console.log('Bulk Mode is ' + (attrs.bulkMode ? 'enabled': 'disabled'));
+ console.log('tableColumns', tableColumns);
+ console.log('collectiveColumnWidth: ', collectiveColumnWidth);
+ console.log('maxWidth: ', maxWidth);
+ }
+
+ function checkScrollArrows() {
+ scope.disableLeft = (setIndex === 0);
+ scope.disableRight = !(setIndex < columnSets.length-1);
+ }
+
+
+ scope.moveViewportLeft = function () {
+ setIndex--;
+ updateCellDisplay(columnSets[setIndex]);
+ checkScrollArrows();
+
+ if (scope.disableLeft) {
+ element.find('span')[0].focus();
+ }
+ };
+
+ scope.moveViewportRight = function () {
+ setIndex++;
+ updateCellDisplay(columnSets[setIndex]);
+ checkScrollArrows();
+
+ if (scope.disableRight) {
+ element.find('span')[0].focus();
+ }
+ };
+
+ scope.getColumnSet = function () {
+ return columnSets[setIndex];
+ };
+
+ innerContainer.bind('scroll', function () {
+ $timeout(function () {
+ checkScrollArrows();
+ }, 1);
+ });
+
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:hourPicker
+ *
+ * @description
+ * <file src="src/hourPicker/docs/readme.md" />
+ *
+ * @usage
+ * <div b2b-hourpicker ng-model="hourpickerValue.value"></div>
+
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/hourPicker/docs/demo.html" />
+ <file src="src/hourPicker/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.hourPicker', ['b2b.att.utilities'])
+
+.constant('b2bHourpickerConfig', {
+ dayOptions: [{
+ title: 'sunday',
+ caption: 'Sun',
+ label: 'S',
+ disabled: false
+ }, {
+ title: 'monday',
+ caption: 'Mon',
+ label: 'M',
+ disabled: false
+ }, {
+ title: 'tuesday',
+ caption: 'Tues',
+ label: 'T',
+ disabled: false
+ }, {
+ title: 'wednesday',
+ caption: 'Wed',
+ label: 'W',
+ disabled: false
+ }, {
+ title: 'thursday',
+ caption: 'Thu',
+ label: 'T',
+ disabled: false
+ }, {
+ title: 'friday',
+ caption: 'Fri',
+ label: 'F',
+ disabled: false
+ }, {
+ title: 'saturday',
+ caption: 'Sat',
+ label: 'S',
+ disabled: false
+ }],
+ startTimeOptions: ['1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:00', '11:00', '12:00'],
+ startTimeDefaultOptionIndex: -1,
+ startTimeDefaultMeridiem: "am",
+ endTimeOptions: ['1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:00', '11:00', '12:00'],
+ endTimeDefaultOptionIndex: -1,
+ endTimeDefaultMeridiem: "pm",
+ sameDayOption: true
+})
+
+.factory('b2bNormalizeHourpickerValues', [function () {
+ var _normalize = function (hourpickerValues) {
+ if (angular.isDefined(hourpickerValues) && hourpickerValues != null) {
+ var finalHourpickerValues = [];
+ var hourpickerValue = {};
+ var days = {};
+ for (var i = 0; i < hourpickerValues.length; i++) {
+ days = hourpickerValues[i].days ? hourpickerValues[i].days : {};
+ hourpickerValue.startTime = hourpickerValues[i].startTime ? hourpickerValues[i].startTime : '';
+ hourpickerValue.startMeridiem = hourpickerValues[i].startMeridiem ? hourpickerValues[i].startMeridiem : '';
+ hourpickerValue.endTime = hourpickerValues[i].endTime ? hourpickerValues[i].endTime : '';
+ hourpickerValue.endMeridiem = hourpickerValues[i].endMeridiem ? hourpickerValues[i].endMeridiem : '';
+ hourpickerValue.days = [];
+
+ var retrieveDaysText = function (daysDetails) {
+ var daysTexts = [];
+ var first = -1;
+ var last = -1;
+ var index = -1;
+ for (var i in days) {
+ if (days[i].value) {
+ daysTexts.push(i);
+ }
+ }
+
+ first = daysTexts[0];
+ last = daysTexts[0];
+ index = 0;
+ hourpickerValue.days[index] = days[first].caption;
+ if (daysTexts.length > 1) {
+ for (var i = 1; i < daysTexts.length; i++) {
+ if (daysTexts[i] - last === 1) {
+ last = daysTexts[i];
+ hourpickerValue.days[index] = days[first].caption + ' - ' + days[last].caption;
+ } else {
+ index++;
+ first = last = daysTexts[i];
+ hourpickerValue.days[index] = days[first].caption;
+ }
+ }
+ }
+ };
+ retrieveDaysText();
+
+ finalHourpickerValues.push(angular.copy(hourpickerValue));
+ }
+
+ return angular.copy(finalHourpickerValues);
+ }
+ };
+
+ return {
+ normalize: _normalize
+ };
+}])
+
+.directive('b2bHourpicker', ['b2bHourpickerConfig', 'b2bNormalizeHourpickerValues', function (b2bHourpickerConfig, b2bNormalizeHourpickerValues) {
+ return {
+ restrict: 'EA',
+ replace: false,
+ scope: true,
+ require: 'ngModel',
+ templateUrl: 'b2bTemplate/hourPicker/b2bHourpicker.html',
+ controller: ['$scope', function (scope) {
+
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ scope.hourpicker = {};
+ scope.hourpicker.dayOptions = attr.dayOptions ? scope.$parent.$eval(attr.dayOptions) : b2bHourpickerConfig.dayOptions;
+ scope.hourpicker.startTimeOptions = attr.startTimeOptions ? scope.$parent.$eval(attr.startTimeOptions) : b2bHourpickerConfig.startTimeOptions;
+ scope.hourpicker.endTimeOptions = attr.endTimeOptions ? scope.$parent.$eval(attr.endTimeOptions) : b2bHourpickerConfig.endTimeOptions;
+ scope.hourpicker.startTimeDefaultOptionIndex = attr.startTimeDefaultOptionIndex ? scope.$parent.$eval(attr.startTimeDefaultOptionIndex) : b2bHourpickerConfig.startTimeDefaultOptionIndex;
+ scope.hourpicker.endTimeDefaultOptionIndex = attr.endTimeDefaultOptionIndex ? scope.$parent.$eval(attr.endTimeDefaultOptionIndex) : b2bHourpickerConfig.endTimeDefaultOptionIndex;
+ scope.hourpicker.startTimeDefaultMeridiem = attr.startTimeDefaultMeridiem ? scope.$parent.$eval(attr.startTimeDefaultMeridiem) : b2bHourpickerConfig.startTimeDefaultMeridiem;
+ scope.hourpicker.endTimeDefaultMeridiem = attr.endTimeDefaultMeridiem ? scope.$parent.$eval(attr.endTimeDefaultMeridiem) : b2bHourpickerConfig.endTimeDefaultMeridiem;
+ scope.hourpicker.sameDayOption = attr.sameDayOption ? scope.$parent.$eval(attr.sameDayOption) : b2bHourpickerConfig.sameDayOption;
+ scope.hourpicker.editMode = -1;
+
+ scope.hourpickerValues = [];
+ scope.finalHourpickerValues = [];
+ scope.addHourpickerValue = function (hourpickerPanelValue) {
+ if (hourpickerPanelValue) {
+ if (scope.hourpicker.editMode > -1) {
+ scope.hourpickerValues[scope.hourpicker.editMode] = hourpickerPanelValue;
+ scope.hourpicker.editMode = -1;
+ } else {
+ scope.hourpickerValues.push(hourpickerPanelValue);
+ }
+ }
+ scope.finalHourpickerValues = b2bNormalizeHourpickerValues.normalize(angular.copy(scope.hourpickerValues));
+ ctrl.$setViewValue(angular.copy(scope.hourpickerValues));
+ };
+ ctrl.$render = function () {
+ if (angular.isDefined(ctrl.$modelValue)) {
+ scope.hourpickerValues = angular.copy(ctrl.$modelValue);
+ scope.finalHourpickerValues = b2bNormalizeHourpickerValues.normalize(angular.copy(scope.hourpickerValues));
+ }
+ };
+ scope.editHourpickerValue = function (index) {
+ scope.hourpickerPanelValue = angular.copy(scope.hourpickerValues[index]);
+ scope.hourpicker.editMode = index;
+ };
+ scope.deleteHourpickerValue = function (index) {
+ scope.hourpickerValues.splice(index, 1);
+ scope.resetHourpickerPanelValue();
+ scope.addHourpickerValue();
+ };
+
+ scope.setValidity = function (errorType, errorValue) {
+ ctrl.$setValidity(errorType, errorValue);
+ }
+ }
+ }
+}])
+
+.directive('b2bHourpickerPanel', [function () {
+ return {
+ restrict: 'EA',
+ replace: false,
+ templateUrl: 'b2bTemplate/hourPicker/b2bHourpickerPanel.html',
+ controller: ['$scope', function (scope) {
+
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ var hourpickerPanelValueTemplate = {
+ days: {},
+ startTime: '',
+ startMeridiem: 'am',
+ endTime: '',
+ endMeridiem: 'pm'
+ };
+ for (var i = 0; i < scope.hourpicker.dayOptions.length; i++) {
+ hourpickerPanelValueTemplate.days[i] = {
+ value: false,
+ title: scope.hourpicker.dayOptions[i].title,
+ caption: scope.hourpicker.dayOptions[i].caption
+ };
+ }
+ scope.hourpickerPanelValue = {};
+ scope.disableAddBtn = true;
+
+ scope.$watch('hourpickerPanelValue.days', function(){
+ for(var i in scope.hourpickerPanelValue.days)
+ {
+ if(scope.hourpickerPanelValue.days[i].value)
+ {
+ scope.disableAddBtn = false;
+ break;
+ }
+ scope.disableAddBtn = true;
+ }
+ }, true);
+
+ scope.resetHourpickerPanelValue = function () {
+ scope.hourpickerPanelValue = angular.copy(hourpickerPanelValueTemplate);
+ if (scope.hourpicker.startTimeDefaultOptionIndex > -1) {
+ scope.hourpickerPanelValue.startTime = scope.hourpicker.startTimeOptions[scope.hourpicker.startTimeDefaultOptionIndex];
+ }
+ if (scope.hourpicker.endTimeDefaultOptionIndex > -1) {
+ scope.hourpickerPanelValue.endTime = scope.hourpicker.endTimeOptions[scope.hourpicker.endTimeDefaultOptionIndex];
+ }
+ scope.hourpickerPanelValue.startMeridiem = scope.hourpicker.startTimeDefaultMeridiem;
+ scope.hourpickerPanelValue.endMeridiem = scope.hourpicker.endTimeDefaultMeridiem;
+ scope.hourpicker.editMode = -1;
+ scope.setValidity('invalidHourpickerData', true);
+ scope.setValidity('invalidHourpickerTimeRange', true);
+ };
+ scope.resetHourpickerPanelValue();
+ scope.updateHourpickerValue = function () {
+ if (scope.isFormValid() && !scope.isTimeOverlap()) {
+ scope.addHourpickerValue(angular.copy(scope.hourpickerPanelValue));
+ scope.resetHourpickerPanelValue();
+ }
+ };
+
+ scope.isFormValid = function () {
+ var isStartTimeAvailable = scope.hourpickerPanelValue.startTime ? true : false;
+ var isStartMeridiemAvailable = scope.hourpickerPanelValue.startMeridiem ? true : false;
+ var isEndTimeAvailable = scope.hourpickerPanelValue.endTime ? true : false;
+ var isEndMeridiemAvailable = scope.hourpickerPanelValue.endMeridiem ? true : false;
+ var currentStartTime = getTime(scope.hourpickerPanelValue.startTime, scope.hourpickerPanelValue.startMeridiem);
+ var currentEndTime = getTime(scope.hourpickerPanelValue.endTime, scope.hourpickerPanelValue.endMeridiem);
+ var isTimeInProperSequence = currentEndTime > currentStartTime;
+ var isDayChecked = false;
+ for (var i in scope.hourpickerPanelValue.days) {
+ if (scope.hourpickerPanelValue.days[i].value) {
+ isDayChecked = true;
+ break;
+ }
+ }
+
+ if (isStartTimeAvailable && isStartMeridiemAvailable && isEndTimeAvailable && isEndMeridiemAvailable && isTimeInProperSequence && isDayChecked) {
+ scope.setValidity('invalidHourpickerData', true);
+ return true;
+ } else {
+ scope.setValidity('invalidHourpickerData', false);
+ return false;
+ }
+ };
+ scope.isTimeOverlap = function () {
+ var selectedDays = [];
+ for (var i in scope.hourpickerPanelValue.days) {
+ if (scope.hourpickerPanelValue.days[i].value) {
+ selectedDays.push(i);
+ }
+ }
+
+ var currentStartTime, currentEndTime, existingStartTime, existingEndTime;
+ currentStartTime = getTime(scope.hourpickerPanelValue.startTime, scope.hourpickerPanelValue.startMeridiem);
+ currentEndTime = getTime(scope.hourpickerPanelValue.endTime, scope.hourpickerPanelValue.endMeridiem);
+ for (var i = 0; i < scope.hourpickerValues.length; i++) {
+
+ if (i === scope.hourpicker.editMode) {
+ continue;
+ }
+
+ for (var j = 0; j < selectedDays.length; j++) {
+ existingStartTime = getTime(scope.hourpickerValues[i].startTime, scope.hourpickerValues[i].startMeridiem);
+ existingEndTime = getTime(scope.hourpickerValues[i].endTime, scope.hourpickerValues[i].endMeridiem);
+ if (scope.hourpickerValues[i].days[selectedDays[j]].value) {
+ if(!scope.hourpicker.sameDayOption){
+ scope.setValidity('dayAlreadySelected', false);
+ return true;
+ } else if ((currentStartTime > existingStartTime && currentStartTime < existingEndTime) || (currentEndTime > existingStartTime && currentEndTime < existingEndTime)) {
+ scope.setValidity('invalidHourpickerTimeRange', false);
+ return true;
+ } else if ((existingStartTime > currentStartTime && existingStartTime < currentEndTime) || (existingEndTime > currentStartTime && existingEndTime < currentEndTime)) {
+ scope.setValidity('invalidHourpickerTimeRange', false);
+ return true;
+ } else if ((currentStartTime === existingStartTime) && (currentEndTime === existingEndTime)) {
+ scope.setValidity('invalidHourpickerTimeRange', false);
+ return true;
+ }
+ }
+ }
+ }
+
+ scope.setValidity('dayAlreadySelected', true);
+ scope.setValidity('invalidHourpickerTimeRange', true);
+ return false;
+ };
+ var getTime = function (timeString, meridiem) {
+ var tempDate = new Date();
+ if (timeString && meridiem) {
+ var timeSplit = timeString.split(':');
+ var hour = ((meridiem === 'PM' || meridiem === 'pm') && timeSplit[0] !== '12') ? parseInt(timeSplit[0], 10) + 12 : parseInt(timeSplit[0], 10);
+ tempDate.setHours(hour, parseInt(timeSplit[1], 10), 0, 0);
+ }
+
+ return tempDate.getTime();
+ };
+ }
+ }
+}])
+
+.directive('b2bHourpickerValue', [function () {
+ return {
+ restrict: 'EA',
+ replace: false,
+ templateUrl: 'b2bTemplate/hourPicker/b2bHourpickerValue.html',
+ controller: ['$scope', function (scope) {
+
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ scope.hourpickerValue = {};
+ scope.hourpickerValue.startTime = attr.startTime ? scope.$eval(attr.startTime) : '';
+ scope.hourpickerValue.startMeridiem = attr.startMeridiem ? scope.$eval(attr.startMeridiem) : '';
+ scope.hourpickerValue.endTime = attr.endTime ? scope.$eval(attr.endTime) : '';
+ scope.hourpickerValue.endMeridiem = attr.endMeridiem ? scope.$eval(attr.endMeridiem) : '';
+ scope.hourpickerValue.days = attr.days ? scope.$eval(attr.days).join(', ') : '';
+ scope.hourpickerValue.index = attr.b2bHourpickerValue ? scope.$eval(attr.b2bHourpickerValue) : -1;
+ }
+ }
+}]);
+/**
+ * @ngdoc directive
+ * @name Template.att:inputTemplate
+ *
+ * @description
+ * <file src="src/inputTemplate/docs/readme.md" />
+ *
+ * @usage
+ * <input type="text" id="fieldId" placeholder="placholder text here" class="span12 input-enhanced" name="fieldName">
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/inputTemplate/docs/demo.html" />
+ <file src="src/inputTemplate/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.inputTemplate', []);
+
+/**
+ * @ngdoc directive
+ * @name Navigation.att:leftNavigation
+ *
+ * @description
+ * <file src="src/leftNavigation/docs/readme.md" />
+ *
+ * @usage
+ * <b2b-left-navigation data-menu="menuData"></b2b-left-navigation>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/leftNavigation/docs/demo.html" />
+ <file src="src/leftNavigation/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.leftNavigation', [])
+ .directive('b2bLeftNavigation', [function () {
+ return {
+ restrict: 'EA',
+ templateUrl: 'b2bTemplate/leftNavigation/leftNavigation.html',
+ scope: {
+ menuData: '='
+ },
+ link: function (scope, element, attrs, ctrl) {
+ scope.idx = -1;
+ scope.itemIdx = -1;
+ scope.navIdx = -1;
+ scope.toggleNav = function (val,link) {
+ /**Added for ECOMP: make parent menu a link if no child menus.**/
+ if(link!=null && link!=''){
+ location.href = link;
+ return;
+ }
+ /**Ended**/
+ if (val === scope.idx) {
+ scope.idx = -1;
+ return;
+ }
+ scope.idx = val;
+ };
+ /*New function for ECOMP*/
+ scope.toggleDrawer = function(showmenu){
+ scope.idx=-1; /*hide the sunmenus*/
+ if(showmenu){
+ //scope.openList.length=0;
+ document.getElementById('page-content').style.marginLeft = "50px";
+ }
+ else
+ document.getElementById('page-content').style.marginLeft = "250px";
+ };
+ scope.liveLink = function (evt, val1, val2) {
+ scope.itemIdx = val1;
+ scope.navIdx = val2;
+ evt.stopPropagation();
+ };
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:links
+ *
+ * @description
+ * <file src="src/links/docs/readme.md" />
+ * @usage
+ * <!-- See below examples for link implementation -->
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/links/docs/demo.html" />
+ <file src="src/links/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.links', []);
+/**
+ * @ngdoc directive
+ * @name Misc.att:listbox
+ *
+ * @description
+ * <file src="src/listbox/docs/readme.md" />
+ *
+ * @param {int} currentIndex - Current index of selected listbox item. Is not supported on multiselect listbox
+ * @param {Array} listboxData - Data of listbox items. Should include full data regardless if HTML will be filtered.
+
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/listbox/docs/demo.html" />
+ <file src="src/listbox/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.listbox', ['b2b.att.utilities'])
+.directive('b2bListBox', ['keymap', 'b2bDOMHelper', '$rootScope', function(keymap, b2bDOMHelper, $rootScope) {
+ return {
+ restrict: 'AE',
+ transclude: true,
+ replace: true,
+ scope: {
+ currentIndex: '=',
+ listboxData: '='
+ },
+ templateUrl: 'b2bTemplate/listbox/listbox.html',
+ link: function(scope, elem, attr) {
+
+ if (attr.ariaMultiselectable !== undefined || attr.ariaMultiselectable === 'true') {
+ scope.multiselectable = true;
+ } else {
+ scope.multiselectable = false;
+ }
+
+ var shiftKey = false;
+ var elements = [];
+ var prevDirection = undefined; // previous direction is used for an edge case when shifting
+ var shiftKeyPressed = false; // Used to handle shift clicking
+ var ctrlKeyPressed = false;
+
+ var currentIndexSet = {
+ 'elementIndex': 0,
+ 'listboxDataIndex': 0
+ };
+
+ /*scope.$watch('currentIndex', function(oldVal, newVal) {
+ if (angular.equals(oldVal, newVal)) return;
+ if (!scope.multiselectable) {
+ // This doesn't garuntee anything. index will update on focus based on rules
+ currentIndexSet.listboxDataIndex = scope.currentIndex;
+ // Should this occur?
+ //scope.listboxData[currentIndexSet.listboxDataIndex].selected = true;
+
+ // Update elementIndex
+ elements = elem.children();
+ var indecies = Array.prototype.map.call(elements, function(item) {
+ return parseInt(angular.element(item).attr('data-index'), 10);
+ }).filter(function(item) {
+ return item === scope.currentIndex;
+ });
+ currentIndex.elementIndex = indecies[0];
+ //focusOnElement(currentIndexSet.elementIndex); // This isn't shifting focus
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+ }
+ });*/
+
+ function isTrue(item) {
+ if (item.selected === true) {
+ return true;
+ }
+ }
+
+ function incrementIndex(elem) {
+ $rootScope.$apply();
+
+ var nextElem = elem.next();
+ if (!angular.isDefined(nextElem) || nextElem.length === 0) {
+ return;
+ }
+
+ currentIndexSet.elementIndex += 1;
+ currentIndexSet.listboxDataIndex = parseInt(nextElem.attr('data-index'), 10);
+ scope.currentIndex = currentIndexSet.listboxDataIndex;
+
+ if (currentIndexSet.elementIndex >= elements.length - 1) {
+ currentIndexSet.elementIndex = elements.length-1;
+ }
+ }
+
+ function decrementIndex(elem) {
+ $rootScope.$apply();
+ var prevElem = angular.element(b2bDOMHelper.previousElement(elem));
+ if (!angular.isDefined(prevElem) || prevElem.length === 0) {
+ return;
+ }
+
+ currentIndexSet.elementIndex -= 1;
+ currentIndexSet.listboxDataIndex = parseInt(prevElem.attr('data-index'), 10);
+ scope.currentIndex = currentIndexSet.listboxDataIndex;
+
+ if (currentIndexSet.elementIndex <= 0) {
+ currentIndexSet.elementIndex = 0;
+ }
+ }
+
+ var focusOnElement = function(index) {
+ try {
+ elements[index].focus();
+ } catch (e) {};
+ }
+
+ function selectItems(startIndex, endIndex, forceValue) {
+ for (var i = startIndex; i < endIndex; i++) {
+ if (forceValue === undefined) {
+ // We will flip the value
+ scope.listboxData[i].selected = !scope.listboxData[i].selected;
+ } else {
+ scope.listboxData[i].selected = forceValue;
+ }
+ }
+
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+ }
+
+ elem.bind('focus', function(evt) {
+ // If multiselectable or not and nothing is selected, put focus on first element
+ // If multiselectable and a range is set, put focus on first element of range
+ // If not multiselectable and something selected, put focus on element
+ elements = elem.children();
+ var selectedItems = scope.listboxData.filter(isTrue);
+ var elementsIndies = Array.prototype.map.call(elements, function(item) {
+ return parseInt(angular.element(item).attr('data-index'), 10);
+ });
+
+ if (selectedItems.length == 0) {
+ focusOnElement(0);
+ currentIndexSet.listboxDataIndex = 0;
+ } else if (attr.ariaMultiselectable) {
+ var index = scope.listboxData.indexOf(selectedItems[0]);
+ var indies = elementsIndies.filter(function(item) {
+ return (item === index);
+ });
+
+ if (indies.length === 0 || indies[0] != index) {
+ // Set focused on 0
+ currentIndexSet.elementIndex = elementsIndies[0];
+ currentIndexSet.listboxDataIndex = 0;
+ focusOnElement(currentIndexSet.elementIndex);
+ } else {
+ focusOnElement(indies[0]);
+ currentIndexSet.elementIndex = indies[0];
+ currentIndexSet.listboxDataIndex = index;
+ }
+ } else {
+ focusOnElement(currentIndexSet.elementIndex);
+ }
+ scope.currentIndex = currentIndexSet.listboxDataIndex;
+
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+ });
+ elem.bind('keyup', function(evt) {
+ if (evt.keyCode === keymap.KEY.SHIFT) {
+ shiftKeyPressed = false;
+ } else if (evt.keyCode === keymap.KEY.CTRL) {
+ ctrlKeyPressed = false;
+ }
+ });
+
+ elem.bind('keydown', function(evt) {
+ var keyCode = evt.keyCode;
+ elements = elem.children();
+ if (keyCode === keymap.KEY.SHIFT) {
+ shiftKeyPressed = true;
+ } else if (evt.keyCode === keymap.KEY.CTRL) {
+ ctrlKeyPressed = true;
+ }
+
+ switch(keyCode) {
+ case 65: // A key
+ {
+ if (scope.multiselectable && evt.ctrlKey) {
+ var arr = scope.listboxData.filter(isTrue);
+ var elementsIndies = Array.prototype.map.call(elements, function(item) {
+ return parseInt(angular.element(item).attr('data-index'), 10);
+ });
+ var val = !(arr.length === scope.listboxData.length);
+ for (var i = 0; i < elementsIndies.length; i++) {
+ scope.listboxData[elementsIndies[i]].selected = val;
+ }
+
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+ break;
+ }
+ case keymap.KEY.END:
+ {
+ if (scope.multiselectable && evt.ctrlKey && evt.shiftKey) {
+ var elementsIndies = Array.prototype.map.call(elements, function(item) {
+ return parseInt(angular.element(item).attr('data-index'), 10);
+ }).filter(function(item) {
+ return (item >= currentIndexSet.listboxDataIndex);
+ });
+ for (var i = 0; i < elementsIndies.length; i++) {
+ scope.listboxData[elementsIndies[i]].selected = true;
+ }
+ evt.preventDefault();
+ evt.stopPropagation();
+
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+ }
+ break;
+ }
+ case keymap.KEY.HOME:
+ {
+ if (scope.multiselectable && evt.ctrlKey && evt.shiftKey) {
+ selectItems(0, currentIndexSet.listboxDataIndex+1, true); // currentIndex+1 is what is being focused on
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+ break;
+ }
+ case keymap.KEY.LEFT:
+ case keymap.KEY.UP:
+ {
+ if (currentIndexSet.listboxDataIndex === 0) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ return;
+ }
+
+ decrementIndex(elements.eq(currentIndexSet.elementIndex));
+ if (scope.multiselectable && (evt.shiftKey || evt.ctrlKey)) {
+ if (evt.shiftKey) {
+ if (prevDirection === 'DOWN') {
+ scope.listboxData[currentIndexSet.listboxDataIndex+1].selected = !scope.listboxData[currentIndexSet.listboxDataIndex+1].selected;
+ }
+ scope.listboxData[currentIndexSet.listboxDataIndex].selected = !scope.listboxData[currentIndexSet.listboxDataIndex].selected;
+ }
+ prevDirection = 'UP';
+ } else {
+ // If no modifier keys are selected, all other items need to be unselected.
+ prevDirection = undefined;
+ selectItems(0, scope.listboxData.length, false);
+ scope.listboxData[currentIndexSet.listboxDataIndex].selected = true;
+ }
+ focusOnElement(currentIndexSet.elementIndex);
+ if(!scope.$$phase) {
+ scope.$apply();
+ }
+ evt.preventDefault();
+ evt.stopPropagation();
+ break;
+ }
+ case keymap.KEY.RIGHT:
+ case keymap.KEY.DOWN:
+ {
+ if (currentIndexSet.listboxDataIndex === scope.listboxData.length-1) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ return;
+ }
+
+ incrementIndex(elements.eq(currentIndexSet.elementIndex));
+
+ if (scope.multiselectable && (evt.shiftKey || evt.ctrlKey)) {
+ if (evt.shiftKey) {
+ if (prevDirection === 'UP') {
+ scope.listboxData[currentIndexSet.listboxDataIndex-1].selected = !scope.listboxData[currentIndexSet.listboxDataIndex-1].selected;
+ }
+
+ scope.listboxData[currentIndexSet.listboxDataIndex].selected = !scope.listboxData[currentIndexSet.listboxDataIndex].selected;
+ }
+ prevDirection = 'DOWN';
+ } else {
+ // If no modifier keys are selected, all other items need to be unselected.
+ prevDirection = undefined;
+ selectItems(0, scope.listboxData.length, false);
+ scope.listboxData[currentIndexSet.listboxDataIndex].selected = true;
+ }
+
+ focusOnElement(currentIndexSet.elementIndex);
+ if(!scope.$$phase) {
+ scope.$apply();
+ }
+ evt.preventDefault();
+ evt.stopPropagation();
+ break;
+ }
+ case keymap.KEY.TAB:
+ if(evt.shiftKey) {
+ var previousElement = b2bDOMHelper.previousElement(elem.parent().parent(), true);
+ evt.preventDefault();
+ previousElement.focus();
+ }
+ break;
+ default:
+ break;
+ }
+ });
+
+ elem.bind('click', function(evt) {
+ var index = parseInt(evt.target.dataset.index, 10);
+ if (index === undefined || isNaN(index)) {
+ return;
+ }
+ if (scope.multiselectable && currentIndexSet.listboxDataIndex !== undefined) {
+ if (shiftKeyPressed) {
+ var min = Math.min(index, currentIndexSet.listboxDataIndex);
+ var max = Math.max(index, currentIndexSet.listboxDataIndex);
+
+ if (index === min) { // clicking up
+ var firstIndex = scope.listboxData.findIndex(function(item) { return item.selected === true;});
+ // Given the firstIndex, let's find the matching element to get proper element match
+ elements = elem.children();
+ elements.eq(firstIndex)
+ var elementsThatMatch = Array.prototype.filter.call(elements, function(item) {
+ if (parseInt(angular.element(item).attr('data-index'), 10) === firstIndex) {
+ return true;
+ }
+ });
+ firstIndex = parseInt(angular.element(elementsThatMatch).attr('data-index'), 10);
+
+ if (index <= firstIndex && scope.listboxData.filter(isTrue).length > 1) {
+ // Break the selection into 2
+ selectItems(firstIndex + 1, max + 1, undefined); // + 1 needed because selectItems only selects up to MAX
+ selectItems(min, firstIndex, undefined);
+ } else if (scope.listboxData.filter(isTrue).length == 1){
+ selectItems(min, max, undefined);
+ } else {
+ selectItems(min + 1, max + 1, undefined);
+ }
+ } else { // clicking down
+ selectItems(min + 1, max + 1, scope.listboxData[min].selected);
+ }
+ } else if (ctrlKeyPressed) {
+ scope.listboxData[index].selected = !scope.listboxData[index].selected;
+ } else {
+ selectItems(0, scope.listboxData.length, false);
+ scope.listboxData[index].selected = !scope.listboxData[index].selected;
+ }
+ } else {
+ selectItems(0, scope.listboxData.length, false);
+ scope.listboxData[index].selected = !scope.listboxData[index].selected;
+ }
+ currentIndexSet.elementIndex = index;
+ currentIndexSet.listboxDataIndex = index;
+ scope.currentIndex = currentIndexSet.listboxDataIndex;
+ if (!scope.$$phase) {
+ scope.$apply();
+ }
+ focusOnElement(index);
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Videos, audio & animation.att:loaderAnimation
+ *
+ * @description
+ * <file src="src/loaderAnimation/docs/readme.md" />
+ *
+ * @usage
+ * <!-- Below demo js shows-->
+ * Angular library uses Global.css's icon-primary-spinner.
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/loaderAnimation/docs/demo.html" />
+ <file src="src/loaderAnimation/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.loaderAnimation', [])
+ .constant('b2bSpinnerConfig', {
+ loadingText: 'Loading...',
+ startEvent: 'startButtonSpinner',
+ stopEvent: 'stopButtonSpinner'
+ })
+ .constant("progressTrackerConfig", {
+ loadingText: 'Loading...',
+ minDuration: "",
+ activationDelay: "",
+ minDurationPromise: "",
+ activationDelayPromise: ""
+ })
+
+.provider('progressTracker', function () {
+ this.$get = ['$q', '$timeout', function ($q, $timeout) {
+ function cancelTimeout(promise) {
+ if (promise) {
+ $timeout.cancel(promise);
+ }
+ }
+ return function ProgressTracker(options) {
+ //do new if user doesn't
+ if (!(this instanceof ProgressTracker)) {
+ return new ProgressTracker(options);
+ }
+
+ options = options || {};
+ //Array of promises being tracked
+ var tracked = [];
+ var self = this;
+ //Allow an optional "minimum duration" that the tracker has to stay active for.
+ var minDuration = options.minDuration;
+ //Allow a delay that will stop the tracker from activating until that time is reached
+ var activationDelay = options.activationDelay;
+ var minDurationPromise;
+ var activationDelayPromise;
+ self.active = function () {
+ //Even if we have a promise in our tracker, we aren't active until delay is elapsed
+ if (activationDelayPromise) {
+ return false;
+ }
+ return tracked.length > 0;
+ };
+ self.tracking = function () {
+ //Even if we aren't active, we could still have a promise in our tracker
+ return tracked.length > 0;
+ };
+ self.destroy = self.cancel = function () {
+ minDurationPromise = cancelTimeout(minDurationPromise);
+ activationDelayPromise = cancelTimeout(activationDelayPromise);
+ for (var i = tracked.length - 1; i >= 0; i--) {
+ tracked[i].resolve();
+ }
+ tracked.length = 0;
+ };
+ //Create a promise that will make our tracker active until it is resolved.
+ // @return deferred - our deferred object that is being tracked
+ self.createPromise = function () {
+ var deferred = $q.defer();
+ tracked.push(deferred);
+ //If the tracker was just inactive and this the first in the list of promises, we reset our delay and minDuration again.
+ if (tracked.length === 1) {
+ if (activationDelay) {
+ activationDelayPromise = $timeout(function () {
+ activationDelayPromise = cancelTimeout(activationDelayPromise);
+ startMinDuration();
+ }, activationDelay);
+ } else {
+ startMinDuration();
+ }
+ }
+ deferred.promise.then(onDone(false), onDone(true));
+ return deferred;
+
+ function startMinDuration() {
+ if (minDuration) {
+ minDurationPromise = $timeout(angular.noop, minDuration);
+ }
+ }
+ //Create a callback for when this promise is done. It will remove our tracked promise from the array if once minDuration is complete
+ function onDone() {
+ return function () {
+ (minDurationPromise || $q.when()).then(function () {
+ var index = tracked.indexOf(deferred);
+ tracked.splice(index, 1);
+ //If this is the last promise, cleanup the timeouts for activationDelay
+ if (tracked.length === 0) {
+ activationDelayPromise = cancelTimeout(activationDelayPromise);
+ }
+ });
+ };
+ }
+ };
+ self.addPromise = function (promise) {
+
+// we cannot assign then function in other var and then add the resolve and reject
+ var thenFxn = promise && (promise.then || promise.$then || (promise.$promise && promise.$promise.then));
+ if (!thenFxn) {
+ throw new Error("progressTracker expects a promise object :: Not found");
+ }
+ var deferred = self.createPromise();
+ //When given promise is done, resolve our created promise
+ //Allow $then for angular-resource objects
+
+ promise.then(function (value) {
+ deferred.resolve(value);
+ return value;
+ }, function (value) {
+ deferred.reject(value);
+ return $q.reject(value);
+ }
+ );
+ return deferred;
+ };
+ };
+ }];
+})
+
+.config(['$httpProvider', function ($httpProvider) {
+ $httpProvider.interceptors.push(['$q', 'progressTracker', function ($q) {
+ return {
+ request: function (config) {
+ if (config.tracker) {
+ if (!angular.isArray(config.tracker)) {
+ config.tracker = [config.tracker];
+ }
+ config.$promiseTrackerDeferred = config.$promiseTrackerDeferred || [];
+
+ angular.forEach(config.tracker, function (tracker) {
+ var deferred = tracker.createPromise();
+ config.$promiseTrackerDeferred.push(deferred);
+ });
+ }
+ return $q.when(config);
+ },
+ response: function (response) {
+ if (response.config && response.config.$promiseTrackerDeferred) {
+ angular.forEach(response.config.$promiseTrackerDeferred, function (deferred) {
+ deferred.resolve(response);
+ });
+ }
+ return $q.when(response);
+ },
+ responseError: function (response) {
+ if (response.config && response.config.$promiseTrackerDeferred) {
+ angular.forEach(response.config.$promiseTrackerDeferred, function (deferred) {
+ deferred.reject(response);
+ });
+ }
+ return $q.reject(response);
+ }
+ };
+ }]);
+}])
+
+.directive('b2bClickSpin', ['$timeout', '$parse', '$rootScope', 'progressTracker', function ($timeout, $parse, $rootScope, progressTracker) {
+ return {
+ restrict: 'A',
+ link: function (scope, elm, attrs) {
+ var fn = $parse(attrs.b2bClickSpin);
+ elm.on('click', function (event) {
+ var promise = $timeout(function () {console.log("inside Promise")}, 5000);
+ scope.$apply(function () {
+ fn(scope, {
+ $event: event
+ });
+ });
+ //comment this line if not running unit test
+ $rootScope.loadingTracker = progressTracker({
+ minDuration: 750
+ });
+ $rootScope.loadingTracker.addPromise(promise);
+ angular.forEach("$routeChangeSuccess $viewContentLoaded $locationChangeSuccess".split(" "), function (event) {
+ $rootScope.$on(event, function () {
+
+ $timeout.cancel(promise);
+ });
+ });
+ });
+ }
+ };
+}])
+
+.directive('b2bProgressTracker', ['progressTrackerConfig', function (ptc) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ template: '<div><div ng-show="loadingTracker.active()" style="width:100%; text-align:center"><i class=\"icon-primary-spinner\"></i></div><div ng-show="loadingTracker.active()" style="width:100%;margin-top:10px; text-align:center">'+ ptc.loadingText+'</div></div>'
+ };
+}])
+
+.directive('b2bLoadButton', ['b2bSpinnerConfig', '$timeout', function (spinnerConfig, $timeout) {
+ var spinButton = function (state, element, data) {
+
+ var attr = element.html() ? 'html' : 'val';
+ state = state + 'Text';
+ if (state === 'loadingText') {
+ element[attr](data[state]);
+ element.attr("disabled",'disabled');
+ element.addClass('disabled');
+ } else if (state === 'resetText') {
+ element[attr](data[state]);
+ element.removeAttr("disabled");
+ element.removeClass('disabled');
+ }
+ };
+
+ return {
+ restrict: 'A',
+ replace: false,
+ scope: {
+ promise: '=promise',
+ startEvent: '@startEvent',
+ stopEvent: '@stopEvent'
+ },
+ link: function (scope, element, attr) {
+ var validAttr = element.html() ? 'html' : 'val';
+ var data = {
+ loadingText: '',
+ resetText: ''
+ };
+
+ var updateLoadingText = function (val) {
+ var loadingText = val;
+ if (!angular.isDefined(loadingText) || loadingText === "") {
+ loadingText = spinnerConfig.loadingText;
+ }
+ data.loadingText = validAttr === 'html' ? "<i class=\"icon-primary-spinner small\"></i>" + loadingText : loadingText;
+ };
+ var updateResetText = function (val) {
+ data.resetText = val;
+ };
+
+ attr.$observe('b2bLoadButton', function (val) {
+ updateLoadingText(val);
+ });
+ $timeout(function () {
+ updateResetText(element[validAttr]());
+ }, 500);
+
+ if (!angular.isDefined(scope.startEvent) || scope.startEvent === "") {
+ scope.startEvent = spinnerConfig.startEvent;
+ }
+
+ if (!angular.isDefined(scope.stopEvent) || scope.stopEvent === "") {
+ scope.stopEvent = spinnerConfig.stopEvent;
+ }
+
+ scope.$watch('promise', function () {
+ if (angular.isDefined(scope.promise) && angular.isFunction(scope.promise.then)) {
+ spinButton('loading', element, data);
+ scope.promise.then(function () {
+ spinButton('reset', element, data);
+ }, function () {
+ spinButton('reset', element, data);
+ });
+ }
+ });
+
+ scope.$on(scope.startEvent, function () {
+ spinButton('loading', element, data);
+ scope.$on(scope.stopEvent, function () {
+ spinButton('reset', element, data);
+ });
+ });
+ }
+ };
+}])
+
+
+;
+ /**
+ * @ngdoc directive
+ * @name Misc.att:messageWrapper
+ * @scope
+ * @param {boolean} trigger - A boolean that triggers directive to switch focus
+ * @param {integer} delay - Extra delay added to trigger code to allow for DOM to be ready. Default is 10ms.
+ * @param {string} noFocus - Attribute-based API to trigger whether first focusable element receives focus on trigger or whole message (assumes tabindex="-1" set on first child)
+ * @param {string} trapFocus - Attribute-based API to trap focus within the message. This should be enabled by default on all toast messages.
+ * @description
+ * <file src="src/messageWrapper/docs/readme.md" />
+ * @usage
+ * <b2b-message-wrapper>Code that contains at least one focusable element and will be shown/hidden on some logic. This must have tabindex="-1".</b2b-message-wrapper>
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/messageWrapper/docs/demo.html" />
+ <file src="src/messageWrapper/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.messageWrapper', ['b2b.att.utilities'])
+.directive('b2bMessageWrapper', ['b2bDOMHelper', '$compile', '$timeout', '$log', function(b2bDOMHelper, $compile, $timeout, $log) {
+ return {
+ restrict: 'AE',
+ scope: {
+ trigger: '=',
+ delay: '=?'
+ },
+ transclude: true,
+ replace: true,
+ template: '<div ng-transclude></div>',
+ link: function(scope, elem, attrs) {
+ scope.delay = scope.delay || 10;
+
+ if (attrs.trapFocus != undefined && !elem.children().eq(0).attr('b2b-trap-focus-inside-element')) {
+ // Append b2bTrapFocusInsideElement onto first child and recompile
+ elem.children().eq(0).attr('b2b-trap-focus-inside-element', 'false');
+ elem.children().eq(0).attr('trigger', scope.trigger);
+ $compile(elem.contents())(scope);
+ }
+
+ var firstElement = undefined,
+ launchingElement = undefined;
+
+ scope.$watch('trigger', function(oldVal, newVal) {
+ if (oldVal === newVal) return;
+ if (!angular.isDefined(launchingElement)) {
+ launchingElement = document.activeElement;
+ }
+ $timeout(function() {
+ if (scope.trigger) {
+
+ if (attrs.noFocus === true || attrs.noFocus === "") {
+ elem.children()[0].focus();
+ } else {
+ firstElement = b2bDOMHelper.firstTabableElement(elem);
+
+ if (angular.isDefined(firstElement)) {
+ firstElement.focus();
+ }
+ }
+
+ } else {
+ if (angular.isDefined(launchingElement) && launchingElement.nodeName !== 'BODY') {
+ if (launchingElement === document.activeElement) {
+ return;
+ }
+
+ if (b2bDOMHelper.isInDOM(launchingElement) && b2bDOMHelper.isTabable(launchingElement)) {
+ // At this point, launchingElement is still a valid element, but focus will fail and
+ // activeElement will become body, hence we want to apply custom logic and find previousElement
+ var prevLaunchingElement = launchingElement;
+ launchingElement.focus();
+
+ if (document.activeElement !== launchingElement || document.activeElement.nodeName === 'BODY') {
+ launchingElement = b2bDOMHelper.previousElement(angular.element(prevLaunchingElement), true);
+ launchingElement.focus();
+ }
+ } else {
+ launchingElement = b2bDOMHelper.previousElement(launchingElement, true);
+ launchingElement.focus();
+ }
+ }
+ }
+ }, scope.delay);
+ });
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:modalsAndAlerts
+ *
+ * @description
+ * <file src="src/modalsAndAlerts/docs/readme.md" />
+ *
+ * @usage
+ * <button class="btn" b2b-modal="b2bTemplate/modalsAndAlerts/demo_modal.html" modal-ok="ok()" modal-cancel="cancel()">Launch demo modal</button>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/modalsAndAlerts/docs/demo.html" />
+ <file src="src/modalsAndAlerts/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.modalsAndAlerts', ['b2b.att.position', 'b2b.att.transition', 'b2b.att.utilities'])
+
+/**
+ * A helper, internal data structure that acts as a map but also allows getting / removing
+ * elements in the LIFO order
+ */
+.factory('$$stackedMap', function () {
+ return {
+ createNew: function () {
+ var stack = [];
+
+ return {
+ add: function (key, value) {
+ stack.push({
+ key: key,
+ value: value
+ });
+ },
+ get: function (key) {
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ return stack[i];
+ }
+ }
+ },
+ keys: function () {
+ var keys = [];
+ for (var i = 0; i < stack.length; i++) {
+ keys.push(stack[i].key);
+ }
+ return keys;
+ },
+ top: function () {
+ return stack[stack.length - 1];
+ },
+ remove: function (key) {
+ var idx = -1;
+ for (var i = 0; i < stack.length; i++) {
+ if (key === stack[i].key) {
+ idx = i;
+ break;
+ }
+ }
+ return stack.splice(idx, 1)[0];
+ },
+ removeTop: function () {
+ return stack.splice(stack.length - 1, 1)[0];
+ },
+ length: function () {
+ return stack.length;
+ }
+ };
+ }
+ };
+}).factory('trapFocusInElement', ['$document', '$isElement', 'DOMHelper', 'keymap', function ($document, $isElement, DOMHelper, keymap) {
+ var elementStack = [];
+ var stackHead = undefined;
+ var firstTabableElement, lastTabableElement;
+
+ var trapKeyboardFocusInFirstElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === true && e.keyCode === keymap.KEY.TAB) {
+ lastTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+
+ };
+
+ var trapKeyboardFocusInLastElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === false && e.keyCode === keymap.KEY.TAB) {
+ firstTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+ };
+
+ var trapFocusInElement = function (flag, firstTabableElementParam, lastTabableElementParam) {
+ var bodyElements = $document.find('body').children();
+
+ firstTabableElement = firstTabableElementParam ? firstTabableElementParam : angular.element(DOMHelper.firstTabableElement(stackHead));
+ lastTabableElement = lastTabableElementParam ? lastTabableElementParam : angular.element(DOMHelper.lastTabableElement(stackHead));
+
+ if (flag) {
+ for (var i = 0; i < bodyElements.length; i++) {
+ if (bodyElements[i] !== stackHead[0]) {
+ bodyElements.eq(i).attr('aria-hidden', true);
+ }
+ }
+ firstTabableElement.bind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.bind('keydown', trapKeyboardFocusInLastElement);
+ } else {
+ for (var j = 0; j < bodyElements.length; j++) {
+ if (bodyElements[j] !== stackHead[0]) {
+ bodyElements.eq(j).removeAttr('aria-hidden');
+ }
+ }
+ firstTabableElement.unbind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.unbind('keydown', trapKeyboardFocusInLastElement);
+ }
+ };
+ var toggleTrapFocusInElement = function (flag, element) {
+ if (angular.isDefined(flag) && angular.isDefined(element)) {
+ if (angular.isUndefined(stackHead)) {
+ stackHead = element;
+ trapFocusInElement(flag);
+ } else {
+ if (flag) {
+ trapFocusInElement(false);
+ elementStack.push(stackHead);
+ stackHead = element;
+ trapFocusInElement(true);
+ } else {
+ if (stackHead.prop('$$hashKey') === element.prop('$$hashKey')) {
+ trapFocusInElement(false);
+ stackHead = elementStack.pop();
+ if (angular.isDefined(stackHead)) {
+ trapFocusInElement(true);
+ }
+ }
+ }
+ }
+ }else {
+ if (angular.isDefined(stackHead)) {
+ trapFocusInElement(false, firstTabableElement, lastTabableElement);
+ trapFocusInElement(true);
+ }
+ }
+ };
+
+ return toggleTrapFocusInElement;
+}])
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+.directive('b2bModalBackdrop', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ templateUrl: 'b2bTemplate/modalsAndAlerts/b2b-backdrop.html',
+ link: function (scope, element, attrs) {
+ scope.close = function (evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop && modal.value.backdrop !== 'static') {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+ }
+ };
+}])
+
+.directive('b2bModalWindow', ['$timeout', 'windowOrientation', '$window', function ($timeout, windowOrientation, $window) {
+ return {
+ restrict: 'EA',
+ scope: {
+ index: '@'
+ },
+ replace: true,
+ transclude: true,
+ templateUrl: 'b2bTemplate/modalsAndAlerts/b2b-window.html',
+ controller: ['$scope', '$element', '$attrs', function (scope, element, attrs) {
+ scope.windowClass = attrs.windowClass || '';
+ scope.sizeClass = attrs.sizeClass || '';
+ scope.isNotifDialog = false;
+
+ this.setTitle = function (title) {
+ scope.title = title;
+ };
+ this.setContent = function (content) {
+ scope.content = content;
+ scope.isNotifDialog = true;
+ };
+ this.isDockedModal = scope.windowClass.indexOf('modal-docked') > -1;
+ }],
+ link: function (scope, element, attrs, ctrl) {
+ if (ctrl.isDockedModal) {
+ scope.isModalLandscape = false;
+
+ var window = angular.element($window);
+ scope.updateCss = function () {
+ if (windowOrientation.isPotrait()) { // Potrait Mode
+ scope.isModalLandscape = false;
+ } else if (windowOrientation.isLandscape()) { // Landscape Mode
+ scope.isModalLandscape = true;
+ }
+ };
+
+ $timeout(function () {
+ scope.updateCss();
+ scope.$apply();
+ }, 100);
+ window.bind('orientationchange', function () {
+ scope.updateCss();
+ scope.$apply();
+ });
+ window.bind('resize', function () {
+ scope.updateCss();
+ scope.$apply();
+ });
+ }else {
+ angular.element(element[0].querySelectorAll(".awd-select-list")).css({
+ "max-height": "200px"
+ });
+ }
+
+ var isIE = /msie|trident/i.test(navigator.userAgent);
+ if (isIE) {
+ if(angular.element(element[0].querySelector('.corner-button button.close')).length > 0){
+ angular.element(element[0].querySelector('.corner-button button.close')).bind('focus', function () {
+ angular.element(element[0].querySelector('.b2b-modal-header'))[0].scrollLeft = 0;
+ angular.element(element[0].querySelector('.b2b-modal-header'))[0].scrollTop = 0;
+ });
+ }
+ }
+
+ }
+ };
+}])
+
+.directive('b2bModalTitle', [function () {
+ return {
+ restrict: 'A',
+ require: '^b2bModalWindow',
+ link: function (scope, elem, attr, ctrl) {
+ ctrl.setTitle(attr.id);
+ }
+ };
+}])
+
+.directive('b2bModalContent', [function () {
+ return {
+ restrict: 'A',
+ require: '^b2bModalWindow',
+ link: function (scope, elem, attr, ctrl) {
+ ctrl.setContent(attr.id);
+ }
+ };
+}])
+
+
+.directive('b2bModalBody', ['$timeout', '$position', '$document', '$window', 'windowOrientation', 'b2bAwdBreakpoints', function ($timeout, $position, $document, $window, windowOrientation, b2bAwdBreakpoints) {
+ return {
+ restrict: 'AC',
+ scope: {
+ index: '@'
+ },
+ require: '^b2bModalWindow',
+ link: function (scope, element, attrs, ctrl) {
+ var window = angular.element($window);
+ var body = $document.find('body').eq(0);
+ scope.setModalHeight = function () {
+ var modalHeaderHeight, modalFooterHeight, modalBodyHeight, windowHeight, windowWidth, modalHeight;
+ modalHeaderHeight = 0;
+ modalFooterHeight = 0;
+ windowHeight = $window.innerHeight;
+ windowWidth = $window.innerWidth;
+ body.css({
+ 'height': windowHeight + 'px'
+ });
+
+ if (ctrl.isDockedModal) {
+ var modalElements = element.parent().children();
+ for (var i = 0; i < modalElements.length; i++) {
+ if (modalElements.eq(i).hasClass('b2b-modal-header')) {
+ modalHeaderHeight = $position.position(modalElements.eq(i)).height;
+ } else if (modalElements.eq(i).hasClass('b2b-modal-footer')) {
+ modalFooterHeight = $position.position(modalElements.eq(i)).height;
+ }
+ }
+
+ modalHeight = $position.position(element.parent()).height;
+
+ modalBodyHeight = modalHeight - (modalHeaderHeight + modalFooterHeight) + 'px';
+
+ if (windowOrientation.isPotrait()) { // Potrait Mode
+ element.removeAttr('style').css({
+ height: modalBodyHeight
+ });
+ } else if (windowOrientation.isLandscape() && windowWidth < b2bAwdBreakpoints.breakpoints.mobile.max) { // Landscape Mode Mobile
+ element.removeAttr('style');
+ } else if (windowOrientation.isLandscape() && windowWidth >= b2bAwdBreakpoints.breakpoints.mobile.max) { // Landscape Mode Non-Mobile
+ element.removeAttr('style').css({
+ height: modalBodyHeight
+ });
+ }
+ }
+ };
+
+ $timeout(function () {
+ scope.setModalHeight();
+ scope.$apply();
+ }, 100);
+ window.bind('orientationchange', function () {
+ scope.setModalHeight();
+ scope.$apply();
+ });
+ window.bind('resize', function () {
+ scope.setModalHeight();
+ scope.$apply();
+ });
+ }
+ };
+}])
+
+.directive('b2bModalFooter', ['windowOrientation', '$window', function (windowOrientation, $window) {
+ return {
+ restrict: 'AC',
+ scope: {
+ index: '@'
+ },
+ link: function (scope, element, attrs) {
+
+ }
+ };
+}])
+
+.factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', '$log', '$timeout', 'trapFocusInElement', function ($document, $compile, $rootScope, $$stackedMap, $log, $timeout, trapFocusInElement) {
+ var backdropjqLiteEl, backdropDomEl;
+ var backdropScope = $rootScope.$new(true);
+ var body = $document.find('body').eq(0);
+ var html = $document.find('html').eq(0);
+ var openedWindows = $$stackedMap.createNew();
+ var $modalStack = {};
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function (newBackdropIndex) {
+ backdropScope.index = newBackdropIndex;
+ });
+
+ function removeModalWindow(modalInstance) {
+ //background scroll fix
+ html.removeAttr('style');
+ body.removeAttr('style');
+ body.removeClass('styled-by-modal');
+
+ var modalWindow = openedWindows.get(modalInstance).value;
+ trapFocusInElement(false, modalWindow.modalDomEl);
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+
+ //remove window DOM element
+ modalWindow.modalDomEl.remove();
+
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() === -1) {
+ backdropDomEl.remove();
+ backdropDomEl = undefined;
+ }
+
+ //destroy scope
+ modalWindow.modalScope.$destroy();
+ }
+
+ $document.bind('keydown', function (evt) {
+ var modal;
+
+ if (evt.which === 27) {
+ modal = openedWindows.top();
+ if (modal && modal.value.keyboard) {
+ $rootScope.$apply(function () {
+ $modalStack.dismiss(modal.key);
+ });
+ }
+ }
+ });
+
+ $modalStack.open = function (modalInstance, modal) {
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard
+ });
+
+ var angularDomEl = angular.element('<div b2b-modal-window></div>');
+ angularDomEl.attr('window-class', modal.windowClass);
+ angularDomEl.attr('size-class', modal.sizeClass);
+ angularDomEl.attr('index', openedWindows.length() - 1);
+ angularDomEl.html(modal.content);
+
+ var modalDomEl = $compile(angularDomEl)(modal.scope);
+ openedWindows.top().value.modalDomEl = modalDomEl;
+ //background page scroll fix
+ html.css({
+ 'overflow-y': 'hidden'
+ });
+ body.css({
+ 'overflow-y': 'hidden',
+ 'width': '100%',
+ 'height': window.innerHeight + 'px'
+ });
+ body.addClass('styled-by-modal');
+ body.append(modalDomEl);
+
+ if (backdropIndex() >= 0 && !backdropDomEl) {
+ backdropjqLiteEl = angular.element('<div b2b-modal-backdrop></div>');
+ backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
+ body.append(backdropDomEl);
+ }
+
+ $timeout(function () {
+
+ if (modal.scope.$$childHead.isNotifDialog) {
+ angular.element(modalDomEl).find('button')[0].focus();
+ } else {
+ angular.element(modalDomEl)[0].focus();
+ }
+ trapFocusInElement(true, angular.element(modalDomEl).eq(0));
+ }, 200);
+ };
+
+ $modalStack.close = function (modalInstance, result) {
+ var modal = openedWindows.get(modalInstance);
+ if (modal) {
+ modal.value.deferred.resolve(result);
+ removeModalWindow(modalInstance);
+ }
+ };
+
+ $modalStack.dismiss = function (modalInstance, reason) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ if (modalWindow) {
+ modalWindow.deferred.reject(reason);
+ removeModalWindow(modalInstance);
+ }
+ };
+
+ $modalStack.getTop = function () {
+ return openedWindows.top();
+ };
+
+ return $modalStack;
+}])
+
+.provider('$modal', function () {
+ var $modalProvider = {
+ options: {
+ backdrop: true, //can be also false or 'static'
+ keyboard: true
+ },
+ $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $http.get(options.templateUrl, {
+ cache: $templateCache
+ }).then(function (result) {
+ return result.data;
+ });
+ }
+
+ function getResolvePromises(resolves) {
+ var promisesArr = [];
+ angular.forEach(resolves, function (value, key) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promisesArr.push($q.when($injector.invoke(value)));
+ }
+ });
+ return promisesArr;
+ }
+
+ $modal.open = function (modalOptions) {
+
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ close: function (result) {
+ $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ $modalStack.dismiss(modalInstance, reason);
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+
+ //verify options
+ if (!modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
+
+
+ templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {
+
+ var modalScope = (modalOptions.scope || $rootScope).$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ var ctrlInstance, ctrlLocals = {};
+ var resolveIter = 1;
+
+ //controllers
+ if (modalOptions.controller) {
+ ctrlLocals.$scope = modalScope;
+ ctrlLocals.$modalInstance = modalInstance;
+ angular.forEach(modalOptions.resolve, function (value, key) {
+ ctrlLocals[key] = tplAndVars[resolveIter++];
+ });
+
+ ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
+ }
+
+ $modalStack.open(modalInstance, {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ content: tplAndVars[0],
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ windowClass: modalOptions.windowClass,
+ sizeClass: modalOptions.sizeClass
+ });
+
+ }, function resolveError(reason) {
+ modalResultDeferred.reject(reason);
+ });
+
+ templateAndResolvePromise.then(function () {
+ modalOpenedDeferred.resolve(true);
+ }, function () {
+ modalOpenedDeferred.reject(false);
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }]
+ };
+
+ return $modalProvider;
+})
+
+.directive("b2bModal", ["$modal", "$log", '$scrollTo', function ($modal, $log, $scrollTo) {
+ return {
+ restrict: 'A',
+ scope: {
+ b2bModal: '@',
+ modalController: '@',
+ modalOk: '&',
+ modalCancel: '&',
+ windowClass: '@',
+ sizeClass: '@'
+ },
+ link: function (scope, elm, attr) {
+ elm.bind('click', function (ev) {
+ var currentPosition = ev.pageY - ev.clientY;
+ ev.preventDefault();
+ if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
+ scope.b2bModal = elm.attr("href");
+ }
+ $modal.open({
+ templateUrl: scope.b2bModal,
+ controller: scope.modalController,
+ windowClass: scope.windowClass,
+ sizeClass: scope.sizeClass
+ }).result.then(function (value) {
+ scope.modalOk({
+ value: value
+ });
+ elm[0].focus();
+ }, function (value) {
+ scope.modalCancel({
+ value: value
+ });
+ elm[0].focus();
+ });
+ });
+ }
+ };
+}])
+
+.directive("utilityFilter", ["$modal", "$log", '$scrollTo', function ($modal, $log, $scrollTo) {
+ return {
+ restrict: 'EA',
+ scope: {
+ utilityFilter: '@'
+ },
+ require: 'ngModel',
+ templateUrl: 'b2bTemplate/modal/u-filter.html',
+ link: function (scope, element, attribute, ctrl) {
+ //controller to be passed to $modal service
+ scope.options = angular.copy(scope.$parent.$eval(attribute.ngModel));
+ scope.$parent.$watch(attribute.ngModel, function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ scope.options = newVal;
+ }
+ });
+ var modalCtrl = function ($scope, options) {
+ $scope.options = angular.copy(options);
+ };
+
+ if (angular.isDefined(scope.utilityFilter)) {
+ scope.templateUrl = scope.utilityFilter;
+ } else {
+ scope.templateUrl = 'b2bTemplate/modal/u-filter-window.html';
+ }
+ element.bind('click', function (ev) {
+ var currentPosition = ev.pageY - ev.clientY;
+ $modal.open({
+ templateUrl: scope.templateUrl,
+ controller: modalCtrl,
+ resolve: {
+ options: function () {
+ return scope.options;
+ }
+ }
+ }).result.then(function (value) {
+ ctrl.$setViewValue(value);
+ element[0].focus();
+ $scrollTo(0, currentPosition, 0);
+ }, function () {
+ element[0].focus();
+ $scrollTo(0, currentPosition, 0);
+ });
+ });
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:monthSelector
+ *
+ * @description
+ * <file src="src/monthSelector/docs/readme.md" />
+ *
+ * @usage
+ * <div b2b-monthpicker ng-model="dt" min="minDate" max="maxDate" mode="monthpicker"></div>
+
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/monthSelector/docs/demo.html" />
+ <file src="src/monthSelector/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.monthSelector', ['b2b.att.position', 'b2b.att.utilities'])
+
+.constant('b2bMonthpickerConfig', {
+ dateFormat: 'MM/dd/yyyy',
+ dayFormat: 'd',
+ monthFormat: 'MMMM',
+ yearFormat: 'yyyy',
+ dayHeaderFormat: 'EEEE',
+ dayTitleFormat: 'MMMM yyyy',
+ disableWeekend: false,
+ disableSunday: false,
+ disableDates: null,
+ onSelectClose: null,
+ startingDay: 0,
+ minDate: null,
+ maxDate: null,
+ dueDate: null,
+ fromDate: null,
+ legendIcon: null,
+ legendMessage: null,
+ calendarDisabled: false,
+ collapseWait: 0,
+ orientation: 'left',
+ inline: false,
+ mode:0,
+ helperText: 'The date you selected is $date. Double tap to open calendar. Select a date to close the calendar.',
+ descriptionText: 'Use tab to navigate between previous button, next button and month. Use arrow keys to navigate between months. Use space or enter to select a month.',
+ MonthpickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'collapseWait', 'orientation','mode','id'],
+ MonthpickerWatchAttributes: ['min', 'max', 'due', 'from', 'legendIcon', 'legendMessage', 'ngDisabled'],
+ MonthpickerFunctionAttributes: ['disableDates', 'onSelectClose']
+})
+
+.factory('b2bMonthpickerService', ['b2bMonthpickerConfig', 'dateFilter', function (b2bMonthpickerConfig, dateFilter) {
+ var setAttributes = function (attr, elem) {
+ if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
+ var attributes = b2bMonthpickerConfig.MonthpickerEvalAttributes.concat(b2bMonthpickerConfig.MonthpickerWatchAttributes, b2bMonthpickerConfig.MonthpickerFunctionAttributes);
+ for (var key in attr) {
+ var val = attr[key];
+ if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ elem.attr(key.toSnakeCase(), key);
+ }
+ }
+ }
+ };
+
+ var bindScope = function (attr, scope) {
+ if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
+ var evalFunction = function (key, val) {
+ scope[key] = scope.$parent.$eval(val);
+ };
+
+ var watchFunction = function (key, val) {
+ scope.$parent.$watch(val, function (value) {
+ scope[key] = value;
+ });
+ scope.$watch(key, function (value) {
+ scope.$parent[val] = value;
+ });
+ };
+
+ var evalAttributes = b2bMonthpickerConfig.MonthpickerEvalAttributes;
+ var watchAttributes = b2bMonthpickerConfig.MonthpickerWatchAttributes;
+ for (var key in attr) {
+ var val = attr[key];
+ if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ evalFunction(key, val);
+ } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
+ watchFunction(key, val);
+ }
+ }
+ }
+ };
+
+ return {
+ setAttributes: setAttributes,
+ bindScope: bindScope
+ };
+}])
+
+.controller('b2bMonthpickerController', ['$scope', '$attrs', 'dateFilter', '$element', '$position', 'b2bMonthpickerConfig', function ($scope, $attrs, dateFilter, $element, $position, dtConfig) {
+ var format = {
+ date: getValue($attrs.dateFormat, dtConfig.dateFormat),
+ day: getValue($attrs.dayFormat, dtConfig.dayFormat),
+ month: getValue($attrs.monthFormat, dtConfig.monthFormat),
+ year: getValue($attrs.yearFormat, dtConfig.yearFormat),
+ dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
+ dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
+ disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
+ disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday),
+ disableDates: getValue($attrs.disableDates, dtConfig.disableDates)
+ },
+ startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
+
+ $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
+ $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
+ $scope.dueDate = dtConfig.dueDate ? $scope.resetTime(dtConfig.dueDate) : null;
+ $scope.fromDate = dtConfig.fromDate ? $scope.resetTime(dtConfig.fromDate) : null;
+ $scope.legendIcon = dtConfig.legendIcon ? dtConfig.legendIcon : null;
+ $scope.legendMessage = dtConfig.legendMessage ? dtConfig.legendMessage : null;
+ $scope.ngDisabled = dtConfig.calendarDisabled ? dtConfig.calendarDisabled : null;
+ $scope.collapseWait = getValue($attrs.collapseWait, dtConfig.collapseWait);
+ $scope.orientation = getValue($attrs.orientation, dtConfig.orientation);
+ $scope.onSelectClose = getValue($attrs.onSelectClose, dtConfig.onSelectClose);
+ $scope.mode = getValue($attrs.mode, dtConfig.mode);
+
+ $scope.inline = $attrs.inline === 'true' ? true : dtConfig.inline;
+
+ function getValue(value, defaultValue) {
+ return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
+ }
+
+ function getDaysInMonth(year, month) {
+ return new Date(year, month, 0).getDate();
+ }
+
+ function getDates(startDate, n) {
+ var dates = new Array(n);
+ var current = startDate,
+ i = 0;
+ while (i < n) {
+ dates[i++] = new Date(current);
+ current.setDate(current.getDate() + 1);
+ }
+ return dates;
+ }
+
+ this.updatePosition = function (b2bMonthpickerPopupTemplate) {
+ $scope.position = $position.offset($element);
+ if($element.find('input').length > 0 ){
+ $scope.position.top += $element.find('input').prop('offsetHeight');
+ }else{
+ $scope.position.top += $element.find('a').prop('offsetHeight');
+ }
+
+ if ($scope.orientation === 'right') {
+ $scope.position.left -= (((b2bMonthpickerPopupTemplate && b2bMonthpickerPopupTemplate.prop('offsetWidth')) || 290) - $element.find('input').prop('offsetWidth'));
+ }
+ };
+
+ function isSelected(dt) {
+ if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isFromDate(dt) {
+ if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isDateRange(dt) {
+ if (dt && $scope.fromDate && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
+ return true;
+ } else if (dt && $scope.fromDate && compare(dt, $scope.fromDate) === 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isOld(date, currentMonthDate) {
+ if (date && currentMonthDate && (new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0).getTime() < new Date(currentMonthDate.getFullYear(), currentMonthDate.getMonth(), 1, 0, 0, 0).getTime())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function isNew(date, currentMonthDate) {
+ if (date && currentMonthDate && (new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0).getTime() > new Date(currentMonthDate.getFullYear(), currentMonthDate.getMonth(), 1, 0, 0, 0).getTime())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function isPastDue(dt) {
+ if ($scope.dueDate) {
+ return (dt > $scope.dueDate);
+ }
+ return false;
+ }
+
+ function isDueDate(dt) {
+ if ($scope.dueDate) {
+ return (dt.getTime() === $scope.dueDate.getTime());
+ }
+ return false;
+ }
+
+ var isDisabled = function (date, currentMonthDate) {
+ if ($attrs.from && !angular.isDate($scope.fromDate)) {
+ return true;
+ }
+ if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ if (isOld(date, currentMonthDate) || isNew(date, currentMonthDate)) {
+ return true;
+ }
+ return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0) || (format.disableDates && format.disableDates({
+ date: date
+ })));
+ };
+
+ var isDisabledMonth = function (date, currentMonthDate) {
+ if ($attrs.from && !angular.isDate($scope.fromDate)) {
+ return true;
+ }
+ if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
+ return true;
+ }
+ return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0) || (format.disableDates && format.disableDates({
+ date: date
+ })));
+ };
+
+ var compare = function (date1, date2) {
+ return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
+ };
+
+ function isMinDateAvailable(startDate, endDate) {
+ if (($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime())) {
+ $scope.disablePrev = true;
+ $scope.visibilityPrev = "hidden";
+ } else {
+ $scope.disablePrev = false;
+ $scope.visibilityPrev = "visible";
+ }
+ }
+
+ function isMaxDateAvailable(startDate, endDate) {
+ if (($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime())) {
+ $scope.disableNext = true;
+ $scope.visibilityNext = "hidden";
+ } else {
+ $scope.disableNext = false;
+ $scope.visibilityNext = "visible";
+ }
+ }
+
+ function isYearInRange(currentYear) {
+
+ if ($scope.minDate && currentYear === $scope.minDate.getFullYear()) {
+ $scope.disablePrev = true;
+ $scope.visibilityPrev = "hidden";
+ } else {
+ $scope.disablePrev = false;
+ $scope.visibilityPrev = "visible";
+ }
+
+ if ($scope.maxDate && currentYear === $scope.maxDate.getFullYear()) {
+ $scope.disableNext = true;
+ $scope.visibilityNext = "hidden";
+ } else {
+ $scope.disableNext = false;
+ $scope.visibilityNext = "visible";
+ }
+
+ }
+
+ this.focusNextPrev = function(b2bMonthpickerPopupTemplate,init){
+ if(init){
+ if (!$scope.disablePrev){
+ b2bMonthpickerPopupTemplate[0].querySelector('th.prev').focus();
+ }else if (!$scope.disableNext){
+ b2bMonthpickerPopupTemplate[0].querySelector('th.next').focus();
+ }else{
+ b2bMonthpickerPopupTemplate[0].querySelector('th.b2b-monthSelector-label').focus();
+ }
+ }else{
+ if ($scope.disableNext || $scope.disablePrev){
+ b2bMonthpickerPopupTemplate[0].querySelector('th.b2b-monthSelector-label').focus();
+ }
+ }
+ };
+
+ function getLabel(label) {
+ if (label) {
+ var labelObj = {
+ pre: label.substr(0, 1).toUpperCase(),
+ post: label
+ };
+ return labelObj;
+ }
+ return;
+ }
+
+ function makeDate(date, dayFormat, dayHeaderFormat, isSelected, isFromDate, isDateRange, isOld, isNew, isDisabled, dueDate, pastDue) {
+ return {
+ date: date,
+ label: dateFilter(date, dayFormat),
+ header: dateFilter(date, dayHeaderFormat),
+ selected: !!isSelected,
+ fromDate: !!isFromDate,
+ dateRange: !!isDateRange,
+ oldMonth: !!isOld,
+ nextMonth: !!isNew,
+ disabled: !!isDisabled,
+ dueDate: !!dueDate,
+ pastDue: !!pastDue,
+ focusable: !((isDisabled && !(isSelected || isDateRange)) || (isOld || isNew))
+ };
+ }
+
+ this.modes = [
+ {
+ name: 'day',
+ getVisibleDates: function (date) {
+ var year = date.getFullYear(),
+ month = date.getMonth(),
+ firstDayOfMonth = new Date(year, month, 1),
+ lastDayOfMonth = new Date(year, month + 1, 0);
+ var difference = startingDay - firstDayOfMonth.getDay(),
+ numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
+ firstDate = new Date(firstDayOfMonth),
+ numDates = 0;
+
+ if (numDisplayedFromPreviousMonth > 0) {
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
+ numDates += numDisplayedFromPreviousMonth; // Previous
+ }
+ numDates += getDaysInMonth(year, month + 1); // Current
+ numDates += (7 - numDates % 7) % 7; // Next
+
+ var days = getDates(firstDate, numDates),
+ labels = new Array(7);
+ for (var i = 0; i < numDates; i++) {
+ var dt = new Date(days[i]);
+ days[i] = makeDate(dt,
+ format.day,
+ format.dayHeader,
+ isSelected(dt),
+ isFromDate(dt),
+ isDateRange(dt),
+ isOld(dt, date),
+ isNew(dt, date),
+ isDisabled(dt, date),
+ isDueDate(dt),
+ isPastDue(dt));
+ }
+ for (var j = 0; j < 7; j++) {
+ labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
+ }
+ isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
+ isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
+ return {
+ objects: days,
+ title: dateFilter(date, format.dayTitle),
+ labels: labels
+ };
+ },
+ split: 7,
+ step: {
+ months: 1
+ }
+ },
+ {
+ name: 'month',
+ getVisibleDates: function(date) {
+ var months = [],
+ labels = [],
+ year = date.getFullYear();
+ for (var i = 0; i < 12; i++) {
+ var dt = new Date(year,i,1);
+ months[i] = makeDate(dt,
+ format.month,
+ format.dayHeader,
+ isSelected(dt),
+ isFromDate(dt),
+ isDateRange(dt),
+ false,
+ false,
+ isDisabledMonth(dt, date),
+ isDueDate(dt),
+ isPastDue(dt));
+ }
+ isYearInRange(year);
+ return {objects: months, title: dateFilter(date, format.year), labels: labels};
+ },
+ split:4,
+ step: {years: 1}
+ }
+ ];
+}])
+
+.directive('b2bMonthpickerPopup', ['$parse', '$log', '$timeout', '$document', '$documentBind', '$isElement', '$templateCache', '$compile','$interval', 'trapFocusInElement', 'keymap', function ($parse, $log, $timeout, $document, $documentBind, $isElement, $templateCache, $compile, $interval,trapFocusInElement, keymap) {
+ return {
+ restrict: 'EA',
+ scope: {
+ trigger: '='
+ },
+ replace: true,
+ transclude: true,
+ templateUrl: function (elem, attr) {
+ if (attr.inline === 'true') {
+ return 'b2bTemplate/monthSelector/monthSelector-popup.html';
+ }else if (attr.link === 'true') {
+ return 'b2bTemplate/monthSelector/monthSelectorLink.html';
+ }else {
+ return 'b2bTemplate/monthSelector/monthSelector.html';
+ }
+ },
+ scope: {},
+ require: ['b2bMonthpickerPopup', 'ngModel', '?^b2bMonthpickerGroup'],
+ controller: 'b2bMonthpickerController',
+ link: function (scope, element, attrs, ctrls) {
+ var MonthpickerCtrl = ctrls[0],
+ ngModel = ctrls[1],
+ b2bMonthpickerGroupCtrl = ctrls[2];
+ var b2bMonthpickerPopupTemplate;
+
+ if (!ngModel) {
+ $log.error("ng-model is required.");
+ return; // do nothing if no ng-model
+ }
+
+ // Configuration parameters
+ var mode = scope.mode,
+ selected;
+ scope.isOpen = false;
+
+ scope.headers = [];
+ scope.footers = [];
+ scope.triggerInterval=undefined;
+
+
+ if (b2bMonthpickerGroupCtrl) {
+ b2bMonthpickerGroupCtrl.registerMonthpickerScope(scope);
+ }
+
+ element.bind('keydown', function (ev) {
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if(ev.keyCode === keymap.KEY.ESC)
+ {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ scope.$apply();
+ }
+ });
+
+ element.find('button').bind('click', function () {
+ onClicked();
+ });
+
+ element.find('a').bind('click', function () {
+ onClicked();
+ });
+
+
+ element.find('input').bind('click', function () {
+ onClicked();
+ });
+
+ var onClicked = function() {
+ if (!scope.ngDisabled) {
+ scope.isOpen = !scope.isOpen;
+ toggleCalendar(scope.isOpen);
+ MonthpickerCtrl.updatePosition(b2bMonthpickerPopupTemplate);
+ scope.$apply();
+ }
+ };
+
+ var toggleCalendar = function (flag) {
+ if (!scope.inline) {
+ if (flag) {
+ b2bMonthpickerPopupTemplate = angular.element($templateCache.get('b2bTemplate/monthSelector/monthSelector-popup.html'));
+ b2bMonthpickerPopupTemplate.attr('b2b-trap-focus-inside-element', 'false');
+ b2bMonthpickerPopupTemplate.attr('trigger', 'true');
+ b2bMonthpickerPopupTemplate = $compile(b2bMonthpickerPopupTemplate)(scope);
+ $document.find('body').append(b2bMonthpickerPopupTemplate);
+ b2bMonthpickerPopupTemplate.bind('keydown', escPress);
+ $timeout(function () {
+ scope.getFocus = true;
+ scope.trigger=0;
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ MonthpickerCtrl.focusNextPrev(b2bMonthpickerPopupTemplate,true);
+ }, 100);
+ });
+ scope.triggerInterval = $interval(function () {
+ //This value is updated to trigger init() function of directive on year change.
+ scope.trigger=(scope.trigger === 0 ? 1 : 0);
+ }, 200);
+
+ } else {
+ b2bMonthpickerPopupTemplate.unbind('keydown', escPress);
+ if(scope.triggerInterval)
+ {
+ $interval.cancel(scope.triggerInterval);
+ scope.triggerInterval=undefined;
+ }
+ b2bMonthpickerPopupTemplate.remove();
+ if(element.find('button').length > 0){
+ element.find('button')[0].focus();
+ }else{
+ element.find('a')[0].focus();
+ }
+
+ scope.getFocus = false;
+ }
+ }
+ };
+
+ var outsideClick = function (e) {
+ var isElement = $isElement(angular.element(e.target), element, $document);
+ var isb2bMonthpickerPopupTemplate = $isElement(angular.element(e.target), b2bMonthpickerPopupTemplate, $document);
+ if (!(isElement || isb2bMonthpickerPopupTemplate)) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ scope.$apply();
+ }
+ };
+
+ var escPress = function (ev) {
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if (ev.keyCode) {
+ if (ev.keyCode === keymap.KEY.ESC) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === 33) {
+ !scope.disablePrev && scope.move(-1);
+ $timeout(function () {
+ scope.getFocus = true;
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ }, 100);
+ });
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === 34) {
+ !scope.disableNext && scope.move(1);
+ $timeout(function () {
+ scope.getFocus = true;
+ scope.$apply();
+ $timeout(function () {
+ scope.getFocus = false;
+ scope.$apply();
+ }, 100);
+ });
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ scope.$apply();
+ }
+ };
+
+ $documentBind.click('isOpen', outsideClick, scope);
+
+ scope.$on('$destroy', function () {
+ if (scope.isOpen) {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }
+ });
+
+ scope.resetTime = function (date) {
+ if (typeof date === 'string') {
+ date = date + 'T12:00:00';
+ }
+ var dt;
+ if (!isNaN(new Date(date))) {
+ dt = new Date(date);
+ if(scope.mode === 1){
+ dt = new Date(dt.getFullYear(), dt.getMonth());
+ }else{
+ dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
+ }
+ } else {
+ return null;
+ }
+ return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
+ };
+
+ if (attrs.min) {
+ scope.$parent.$watch($parse(attrs.min), function (value) {
+ scope.minDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.max) {
+ scope.$parent.$watch($parse(attrs.max), function (value) {
+ scope.maxDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.due) {
+ scope.$parent.$watch($parse(attrs.due), function (value) {
+ scope.dueDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+ if (attrs.from) {
+ scope.$parent.$watch($parse(attrs.from), function (value) {
+ scope.fromDate = value ? scope.resetTime(value) : null;
+ refill();
+ });
+ }
+
+ if (attrs.legendIcon) {
+ scope.$parent.$watch(attrs.legendIcon, function (value) {
+ scope.legendIcon = value ? value : null;
+ refill();
+ });
+ }
+ if (attrs.legendMessage) {
+ scope.$parent.$watch(attrs.legendMessage, function (value) {
+ scope.legendMessage = value ? value : null;
+ refill();
+ });
+ }
+ if (attrs.ngDisabled) {
+ scope.$parent.$watch(attrs.ngDisabled, function (value) {
+ scope.ngDisabled = value ? value : null;
+ });
+ }
+
+
+ // Split array into smaller arrays
+ function split(arr, size) {
+ var arrays = [];
+ while (arr.length > 0) {
+ arrays.push(arr.splice(0, size));
+ }
+ return arrays;
+ }
+
+ var moveMonth = function(selectedDate, direction) {
+ var step = MonthpickerCtrl.modes[scope.mode].step;
+ selectedDate.setDate(1);
+ selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
+ selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
+
+ return selectedDate;
+ };
+
+ function refill(date) {
+ if (angular.isDate(date) && !isNaN(date)) {
+ selected = new Date(date);
+ } else {
+ if (!selected) {
+ selected = new Date();
+ }
+ }
+
+ if (selected) {
+ var selectedCalendar;
+ if(scope.mode === 1){
+ if(!angular.isDate(selected))
+ {
+ selected = new Date();
+ }
+ selectedCalendar = moveMonth(angular.copy(selected), -1);
+ } else {
+ selectedCalendar = angular.copy(selected);
+ }
+
+ var currentMode = MonthpickerCtrl.modes[mode],
+ data = currentMode.getVisibleDates(selected);
+
+ scope.rows = split(data.objects, currentMode.split);
+
+ var flag=false;
+ var startFlag=false;
+ var firstSelected = false;
+ for(var i=0; i<scope.rows.length; i++)
+ {
+ for(var j=0; j<scope.rows[i].length; j++)
+ {
+ if(!scope.rows[i][j].disabled && !firstSelected)
+ {
+ firstSelected=true;
+ var firstDay = scope.rows[i][j];
+ }
+
+ if(scope.rows[i][j].selected)
+ {
+ flag=true;
+ break;
+ }
+ }
+ if(flag)
+ {
+ break;
+ }
+ }
+ if(!flag && firstSelected)
+ {
+ firstDay.firstFocus=true;
+ }
+
+ scope.labels = data.labels || [];
+ scope.title = data.title;
+ }
+ }
+
+ scope.select = function (date,$event) {
+ var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
+ scope.currentDate = dt;
+ if (!scope.onSelectClose || (scope.onSelectClose && scope.onSelectClose({
+ date: dt
+ }) !== false)) {
+ if (angular.isNumber(scope.collapseWait)) {
+ $timeout(function () {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }, scope.collapseWait);
+ } else {
+ scope.isOpen = false;
+ toggleCalendar(scope.isOpen);
+ }
+ }
+ };
+
+ scope.move = function (direction,$event) {
+ var step = MonthpickerCtrl.modes[mode].step;
+ selected.setDate(1);
+ selected.setMonth(selected.getMonth() + direction * (step.months || 0));
+ selected.setFullYear(selected.getFullYear() + direction * (step.years || 0));
+ refill();
+ scope.getFocus = true;
+ $timeout(function () {
+ if (attrs.inline === 'true') {
+ MonthpickerCtrl.focusNextPrev(element,false);
+ }else{
+ MonthpickerCtrl.focusNextPrev(b2bMonthpickerPopupTemplate,false);
+ }
+ },100);
+ $event.preventDefault();
+ $event.stopPropagation();
+ };
+
+ scope.$watch('currentDate', function (value) {
+ if (angular.isDefined(value) && value !== null) {
+ refill(value);
+ } else {
+ refill();
+ }
+ ngModel.$setViewValue(value);
+ });
+
+ ngModel.$render = function () {
+ scope.currentDate = ngModel.$viewValue;
+ };
+
+ var stringToDate = function (value) {
+ if (!isNaN(new Date(value))) {
+ value = new Date(value);
+ }
+ return value;
+ };
+ ngModel.$formatters.unshift(stringToDate);
+ }
+ };
+}])
+
+.directive('b2bMonthpicker', ['$compile', '$log', 'b2bMonthpickerConfig', 'b2bMonthpickerService', function ($compile, $log, b2bMonthpickerConfig, b2bMonthpickerService) {
+ return {
+ restrict: 'A',
+ scope: {
+ disableDates: '&',
+ onSelectClose: '&'
+ },
+ require: 'ngModel',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : b2bMonthpickerConfig.dateFormat;
+ var helperText = angular.isDefined(attr.helperText) ? scope.$parent.$eval(attr.helperText) : b2bMonthpickerConfig.helperText;
+ helperText = helperText.replace('$date', '{{dt | date : \'' + dateFormatString + '\'}}');
+
+ var descriptionText = angular.isDefined(attr.descriptionText) ? scope.$parent.$eval(attr.descriptionText) : b2bMonthpickerConfig.descriptionText;
+
+
+ var inline = false;
+ if (elem.prop('nodeName') !== 'INPUT' && elem.prop('nodeName') !== 'A') {
+ inline = true;
+ }
+
+ var selectedDateMessage = "";
+
+ if (elem.prop('nodeName') !== 'A'){
+ selectedDateMessage = '<button type="button" class="span12 faux-input" ng-disabled="ngDisabled" aria-describedby="monthpicker-description'+scope.$id+'"><span class="hidden-spoken" aria-live="assertive" aria-atomic="false">' + helperText + '</span></button>';
+ elem.attr('tabindex', '-1');
+ elem.attr('aria-hidden', 'true');
+ elem.attr('readonly', 'true');
+ }else{
+ selectedDateMessage = ''
+ elem.attr('aria-label', helperText);
+ }
+
+ var descriptionTextSpan = '<span class="offscreen-text" id="monthpicker-description'+scope.$id+'">'+descriptionText+'</span>';
+ elem.removeAttr('b2b-Monthpicker');
+ elem.removeAttr('ng-model');
+ elem.removeAttr('ng-disabled');
+ elem.addClass('Monthpicker-input');
+ elem.attr('ng-model', 'dt');
+ elem.attr('aria-describedby', 'monthpicker-description'+scope.$id);
+
+
+
+ elem.attr('ng-disabled', 'ngDisabled');
+ elem.attr('b2b-format-date', dateFormatString);
+
+ var wrapperElement = angular.element('<div></div>');
+ wrapperElement.attr('b2b-Monthpicker-popup', '');
+ wrapperElement.attr('ng-model', 'dt');
+ if (inline) {
+ wrapperElement.attr('inline', inline);
+ }
+ if (elem.prop('nodeName') === 'A'){
+ wrapperElement.attr('link', true);
+ }
+ b2bMonthpickerService.setAttributes(attr, wrapperElement);
+ b2bMonthpickerService.bindScope(attr, scope);
+
+ wrapperElement.html('');
+ wrapperElement.append(selectedDateMessage);
+ wrapperElement.append('');
+ wrapperElement.append(descriptionTextSpan);
+ wrapperElement.append('');
+ wrapperElement.append(elem.prop('outerHTML'));
+
+ var elm = wrapperElement.prop('outerHTML');
+ elm = $compile(elm)(scope);
+ elem.replaceWith(elm);
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ if (!ctrl) {
+ $log.error("ng-model is required.");
+ return; // do nothing if no ng-model
+ }
+
+ scope.$watch('dt', function (value) {
+ ctrl.$setViewValue(value);
+ });
+ ctrl.$render = function () {
+ scope.dt = ctrl.$viewValue;
+ };
+ }
+ };
+}])
+
+.directive('b2bMonthpickerGroup', [function () {
+ return {
+ restrict: 'EA',
+ controller: ['$scope', '$element', '$attrs', function (scope, elem, attr) {
+ this.$$headers = [];
+ this.$$footers = [];
+ this.registerMonthpickerScope = function (MonthpickerScope) {
+ MonthpickerScope.headers = this.$$headers;
+ MonthpickerScope.footers = this.$$footers;
+ };
+ }],
+ link: function (scope, elem, attr, ctrl) {}
+ };
+}])
+
+.directive('b2bFormatDate', ['dateFilter', function (dateFilter) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ var b2bFormatDate = "";
+ attr.$observe('b2bFormatDate', function (value) {
+ b2bFormatDate = value;
+ });
+ var dateToString = function (value) {
+ if (!isNaN(new Date(value))) {
+ return dateFilter(new Date(value), b2bFormatDate);
+ }
+ return value;
+ };
+ ctrl.$formatters.unshift(dateToString);
+ }
+ };
+}])
+
+.directive('b2bMonthpickerHeader', [function () {
+ return {
+ restrict: 'EA',
+ require: '^b2bMonthpickerGroup',
+ transclude: true,
+ replace: true,
+ template: '',
+ compile: function (elem, attr, transclude) {
+ return function link(scope, elem, attr, ctrl) {
+ if (ctrl) {
+ ctrl.$$headers.push(transclude(scope, function () {}));
+ }
+ elem.remove();
+ };
+ }
+ };
+}])
+
+.directive('b2bMonthpickerFooter', [function () {
+ return {
+ restrict: 'EA',
+ require: '^b2bMonthpickerGroup',
+ transclude: true,
+ replace: true,
+ template: '',
+ compile: function (elem, attr, transclude) {
+ return function link(scope, elem, attr, ctrl) {
+ if (ctrl) {
+ ctrl.$$footers.push(transclude(scope, function () {}));
+ }
+ elem.remove();
+ };
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:multiLevelNavigation
+ *
+ * @description
+ * <file src="src/multiLevelNavigation/docs/readme.md" />
+ *
+ * @usage
+ * <div class="b2b-ml-nav">
+ * <ul role="tree">
+ * <li aria-label="{{child.name}}" tabindex="-1" b2b-ml-nav="{{child.type}}" role="treeitem" ng-repeat="child in treeStructure">
+ * <a tabindex="-1" href="javascript:void(0);" title="{{child.name}}">{{child.name}}<span><i class="{{child.type=='endNode'?'icon-primary-circle':'icon-primary-collapsed'}}"></i></span></a>
+ * <!-- Below UL tag is RECURSIVE to generate n-childs -->
+ * <ul role="group" ng-if="child.child">
+ * <li aria-label="{{child.name}}" b2b-ml-nav="{{child.type}}" tabindex="-1" role="treeitem" ng-repeat="child in child.child">
+ * <a tabindex="-1" href="javascript:void(0);" title="{{child.name}}">{{child.name}}<span><i class="{{child.type=='endNode'?'icon-primary-circle':'icon-primary-collapsed'}}"></i></span></a>
+ * <!-- RECURSIVE UL tag goes here -->
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </div>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/multiLevelNavigation/docs/demo.html" />
+ <file src="src/multiLevelNavigation/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.multiLevelNavigation', ['b2b.att.utilities'])
+ //directive b2bMlNav Test coverage 100% on 5/13
+ .directive('b2bMlNav', ['keymap', function (keymap) {
+ return {
+ restrict: 'EA',
+ link: function (scope, element) {
+ var rootE, parentE, upE, downE, lastE, homeE, endE;
+ //default root tree element tabindex set zero
+ if (element.parent().parent().hasClass('b2b-ml-nav') && (element[0].previousElementSibling === null)) {
+ element.attr('tabindex', 0);
+ }
+ //check root via class
+ var isRoot = function (elem) {
+ if (elem.parent().parent().eq(0).hasClass('b2b-ml-nav')) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+ //for any expandable tree item on click
+ var toggleState = function (e) {
+ if (angular.element(e.target).attr("b2b-ml-nav") !== "endNode") {
+ var eLink = element.find('a').eq(0);
+ if (eLink.hasClass('active')) {
+ eLink.removeClass('active');
+ eLink.parent().attr("aria-expanded", "false");
+ eLink.find('i').eq(0).removeClass('icon-primary-expanded');
+ eLink.find('i').eq(0).addClass('icon-primary-collapsed');
+ } else {
+ eLink.addClass('active');
+ eLink.parent().attr("aria-expanded", "true");
+ eLink.find('i').eq(0).removeClass('icon-primary-collapsed');
+ eLink.find('i').eq(0).addClass('icon-primary-expanded');
+ }
+ }
+ };
+ //function finds the main root-item from particular tree-group
+ var findRoot = function (elem) {
+ if (isRoot(elem)) {
+ rootE = elem;
+ return;
+ }
+ if (elem.attr("b2b-ml-nav") === "middleNode" || elem.attr("b2b-ml-nav") === "endNode") {
+ parentE = elem.parent().parent();
+ } else {
+ parentE = elem;
+ }
+ if (parentE.attr("b2b-ml-nav") === "rootNode") {
+ rootE = parentE;
+ } else {
+ findRoot(parentE);
+ }
+ };
+ //finds the last visible node of the previous tree-group
+ var findPreActive = function (elem) {
+ if (!(elem.hasClass("active"))) {
+ return;
+ } else {
+ var childElems = angular.element(elem[0].nextElementSibling.children);
+ lastE = angular.element(childElems[childElems.length - 1]);
+ if (lastE.attr("b2b-ml-nav") === "middleNode" && lastE.find('a').eq(0).hasClass('active')) {
+ findPreActive(lastE.find('a').eq(0));
+ }
+ upE = lastE;
+ }
+ };
+ //find above visible link
+ var findUp = function (elem) {
+ if (elem[0].previousElementSibling !== null) {
+ upE = angular.element(elem[0].previousElementSibling);
+ } else {
+ upE = elem.parent().parent();
+ }
+ if (isRoot(elem) || (upE.attr('b2b-ml-nav') === "middleNode" && upE[0] !== elem.parent().parent()[0])) {
+ findPreActive(upE.find('a').eq(0));
+ }
+ };
+ //find below visible link
+ var findDown = function (elem) {
+ if (elem.hasClass('active')) {
+ downE = elem.next().find('li').eq(0);
+ } else {
+ if (elem.parent().next().length !== 0) {
+ downE = elem.parent().next().eq(0);
+ } else {
+ if (elem.parent().parent().parent().next().length !== 0) {
+ downE = elem.parent().parent().parent().next().eq(0);
+ return;
+ }
+ downE = elem.parent().eq(0);
+ }
+ }
+ };
+ //finds last root-group element of the tree
+ var findEnd = function (elem) {
+ findRoot(elem);
+ endE = angular.element(rootE.parent()[0].children[rootE.parent()[0].children.length - 1]);
+ };
+ //finds first root element of tree
+ var findHome = function (elem) {
+ findRoot(elem);
+ homeE = angular.element(rootE.parent()[0].children[0]);
+ };
+ element.bind('click', function (e) {
+ if(element.attr("b2b-ml-nav") !== "endNode") {
+ toggleState(e);
+ }
+ e.stopPropagation();
+ });
+ element.bind('focus', function (e) {
+ if(element.attr("b2b-ml-nav") !== "endNode") {
+ if(element.find('a').eq(0).hasClass('active')) {
+ element.attr("aria-expanded", true);
+ }
+ else {
+ element.attr("aria-expanded", false);
+ }
+
+ }
+ })
+ //Keyboard functionality approach:
+ //find keycode
+ //set set tabindex -1 on the current focus element
+ //find the next element to be focussed, set tabindex 0 and throw focus
+ element.bind('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case keymap.KEY.ENTER:
+ case keymap.KEY.SPACE:
+ element.triggerHandler('click');
+ evt.stopPropagation();
+ evt.preventDefault();
+ break;
+ case keymap.KEY.END:
+ evt.preventDefault();
+ element.attr('tabindex', -1);
+ findEnd(element);
+ endE.eq(0).attr('tabindex', 0);
+ endE[0].focus();
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.HOME:
+ evt.preventDefault();
+ element.attr('tabindex', -1);
+ findHome(element);
+ homeE.eq(0).attr('tabindex', 0);
+ homeE[0].focus();
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.LEFT:
+ evt.preventDefault();
+ if (!isRoot(element)) {
+ element.attr('tabindex', -1);
+ parentE = element.parent().parent();
+ parentE.eq(0).attr('tabindex', 0);
+ parentE[0].focus();
+ parentE.eq(0).triggerHandler('click');
+ } else {
+ if (element.find('a').eq(0).hasClass('active')) {
+ element.triggerHandler('click');
+ }
+ }
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.UP:
+ evt.preventDefault();
+ if (!(isRoot(element) && element[0].previousElementSibling === null)) {
+ element.attr('tabindex', -1);
+ findUp(element);
+ upE.eq(0).attr('tabindex', 0);
+ upE[0].focus();
+ }
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.RIGHT:
+ evt.preventDefault();
+ if (element.attr("b2b-ml-nav") !== "endNode") {
+ if (!element.find('a').eq(0).hasClass('active')) {
+ element.triggerHandler('click');
+ }
+ element.attr('tabindex', -1);
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ }
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.DOWN:
+ evt.preventDefault();
+ element.attr('tabindex', -1);
+ if (!(element.attr("b2b-ml-nav") === "middleNode" && element.find('a').eq(0).hasClass('active')) && (element.next().length === 0)) {
+ if(element.parent().parent().attr("b2b-ml-nav") !== "rootNode" && element.parent().parent()[0].nextElementSibling !== null)
+ {
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ evt.stopPropagation();
+ break;
+ }
+ findRoot(element);
+ if (!(rootE.next().length === 0)) {
+ rootE.next().eq(0).attr('tabindex', 0);
+ rootE.next()[0].focus();
+ } else {
+ rootE.eq(0).attr('tabindex', 0);
+ rootE[0].focus();
+ }
+ evt.stopPropagation();
+ break;
+ }
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ evt.stopPropagation();
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Tabs, tables & accordions.att:multipurposeExpander
+ *
+ * @description
+ * <file src="src/multipurposeExpander/docs/readme.md" />
+ *
+ * @usage
+ * <!--With Close Other -->
+ * <b2b-expander-group close-others="true">
+ * <b2b-expanders class="mpc-expanders" is-open="testmpc">
+ * <b2b-expander-heading ng-class=" { 'b2b-toggle-header-active': !testmpc, 'b2b-toggle-header-inactive': testmpc } ">Heading content goes here</b2b-expander-heading>
+ * <b2b-expander-body>
+ <p>body content goes here</p>
+ </b2b-expander-body>
+ * </b2b-expanders>
+ * </b2b-expander-group>
+ *
+ * <!-- Without Close Other -->
+ * <b2b-expanders class="mpc-expanders" is-open="testmpc2">
+ * <b2b-expander-heading ng-class=" { 'b2b-toggle-header-active': !testmpc2, 'b2b-toggle-header-inactive': testmpc2 } ">Heading content goes here</b2b-expander-heading>
+ * <b2b-expander-body>
+ <p>body content goes here</p>
+ </b2b-expander-body>
+ * </b2b-expanders>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att.multipurposeExpander">
+ <file src="src/multipurposeExpander/docs/demo.html" />
+ <file src="src/multipurposeExpander/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.multipurposeExpander', ['b2b.att', 'b2b.att.collapse'])
+.directive('b2bExpanderGroup', function () {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ template: "<ng-transclude></ng-transclude>",
+ controller:['$scope','$attrs', function($scope,$attrs){
+ this.groups = [];
+ this.index = -1;
+ this.scope = $scope;
+
+ this.addGroup = function (groupScope) {
+ var that = this;
+ groupScope.index = this.groups.length;
+ this.groups.push(groupScope);
+ if(this.groups.length > 0){
+ this.index = 0;
+ }
+ groupScope.$on('$destroy', function () {
+ that.removeGroup(groupScope);
+ });
+ };
+
+ this.closeOthers = function (openGroup) {
+ var closeOthers = angular.isDefined($attrs.closeOthers);
+ if (closeOthers && !$scope.forceExpand) {
+ angular.forEach(this.groups, function (group) {
+ if (group !== openGroup) {
+ group.isOpen = false;
+ }
+ });
+ }
+ if (this.groups.indexOf(openGroup) === (this.groups.length - 1) && $scope.forceExpand) {
+ $scope.forceExpand = false;
+ }
+ };
+ this.removeGroup = function (group) {
+ var index = this.groups.indexOf(group);
+ if (index !== -1) {
+ this.groups.splice(this.groups.indexOf(group), 1);
+ }
+ };
+ }]
+
+ };
+
+})
+.directive('b2bExpanders', function () {
+ return{
+ restrict: 'EA',
+ replace: true,
+ require:['b2bExpanders','?^b2bExpanderGroup'],
+ transclude: true,
+ scope:{isOpen:'=?'},
+ template: "<div ng-transclude></div>",
+ controller: ['$scope', function ($scope){
+ var bodyScope = null;
+ var expanderScope = null;
+ this.isOpened = function(){
+ if($scope.isOpen)
+ {
+ return true;
+ }else
+ {
+ return false;
+ }
+ };
+ this.setScope = function (scope) {
+ bodyScope = scope;
+ bodyScope.isOpen = $scope.isOpen;
+ };
+ this.setExpanderScope = function (scope) {
+ expanderScope = scope;
+ };
+ this.toggle = function () {
+ $scope.isOpen = bodyScope.isOpen = !bodyScope.isOpen;
+ return bodyScope.isOpen;
+
+ };
+ this.watchToggle = function(io){
+ bodyScope.isOpen = io;
+ expanderScope.updateIcons(io);
+ };
+ }],
+ link: function (scope, elem, attr, myCtrl)
+ {
+ //scope.isOpen = false;
+ if(myCtrl[1]){
+ myCtrl[1].addGroup(scope);
+ }
+ scope.$watch('isOpen', function(val){
+ myCtrl[0].watchToggle(scope.isOpen);
+ if(val && myCtrl[1]){
+ myCtrl[1].closeOthers(scope);
+ }
+ });
+ }
+ };
+})
+
+.directive('b2bExpanderHeading', function () {
+ return{
+ require: "^b2bExpanders",
+ restrict: 'EA',
+ replace: true,
+ transclude: true,
+ scope: true,
+ template: "<div style='padding:10px 10px 10px 0 !important' ng-transclude></div>"
+ };
+})
+
+.directive('b2bExpanderBody', function () {
+ return{
+ restrict: 'EA',
+ require: "^b2bExpanders",
+ replace: true,
+ transclude: true,
+ scope: {},
+ template: "<div b2b-collapse='!isOpen' ><div ng-transclude></div></div>",
+ link: function (scope, elem, attr, myCtrl) {
+ scope.isOpen = false;
+ myCtrl.setScope(scope);
+ }
+ };
+})
+
+.directive('b2bExpanderToggle', function () {
+ return{
+ restrict: 'EA',
+ require: "^b2bExpanders",
+ scope: {
+ expandIcon: '@',
+ collapseIcon: '@'
+ },
+
+ link: function (scope, element, attr, myCtrl)
+ {
+ myCtrl.setExpanderScope(scope);
+ var isOpen = myCtrl.isOpened();
+
+ scope.setIcon = function () {
+ element.attr("role", "tab");
+
+ if (scope.expandIcon && scope.collapseIcon)
+ {
+ if (isOpen) {
+ element.removeClass(scope.expandIcon);
+ element.addClass(scope.collapseIcon);
+
+ element.attr("aria-expanded", "true");
+ }
+ else {
+ element.removeClass(scope.collapseIcon);
+ element.addClass(scope.expandIcon);
+
+ element.attr("aria-expanded", "false");
+ }
+ }
+ };
+
+ element.bind('click', function (){
+ scope.toggleit();
+ });
+ scope.updateIcons = function(nStat){
+ isOpen = nStat;
+ scope.setIcon();
+ };
+ scope.toggleit = function (){
+ isOpen = myCtrl.toggle();
+ scope.setIcon();
+ scope.$apply();
+ };
+ scope.setIcon();
+ }
+ };
+});
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:notesMessagesAndErrors
+ *
+ * @description
+ * <file src="src/notesMessagesAndErrors/docs/readme.md" />
+ *
+ * @usage
+ * See Demo
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/notesMessagesAndErrors/docs/demo.html" />
+ <file src="src/notesMessagesAndErrors/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.notesMessagesAndErrors', []);
+/**
+ * @ngdoc directive
+ * @name Template.att:Notification Card
+ *
+ * @description
+ * <file src="src/notificationCardTemplate/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/notificationCardTemplate/docs/demo.html" />
+ <file src="src/notificationCardTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.notificationCardTemplate', [])
+
+/**
+ * @ngdoc directive
+ * @name Template.att:Order Confirmation Template
+ *
+ * @description
+ * <file src="src/orderConfirmationTemplate/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/orderConfirmationTemplate/docs/demo.html" />
+ <file src="src/orderConfirmationTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.orderConfirmationTemplate', []);
+
+/**
+ * @ngdoc directive
+ * @name Navigation.att:pagination
+ *
+ * @description
+ * <file src="src/pagination/docs/readme.md" />
+ *
+ * @usage
+ * <div b2b-pagination="" input-id="goto-page-2" total-pages="totalPages1" current-page="currentPage1" click-handler="customHandler" show-input="showInput"></div>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/pagination/docs/demo.html" />
+ <file src="src/pagination/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.pagination', ['b2b.att.utilities', 'ngTouch'])
+ .directive('b2bPagination', ['b2bUserAgent', 'keymap', '$window', '$timeout', function (b2bUserAgent, keymap, $window, $timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ totalPages: '=',
+ currentPage: '=',
+ showInput: '=',
+ clickHandler: '=?',
+ inputId: '='
+ },
+ replace: true,
+ templateUrl: 'b2bTemplate/pagination/b2b-pagination.html',
+ link: function (scope, elem) {
+ scope.isMobile = b2bUserAgent.isMobile();
+ scope.notMobile = b2bUserAgent.notMobile();
+ scope.focusedPage;
+ scope.meanVal = 3;
+ scope.$watch('totalPages', function (value) {
+ if (angular.isDefined(value) && value !== null) {
+ scope.pages = [];
+ if (value < 1) {
+ scope.totalPages = 1;
+ return;
+ }
+ if (value <= 10) {
+ for (var i = 1; i <= value; i++) {
+ scope.pages.push(i);
+ }
+ } else if (value > 10) {
+ var midVal = Math.ceil(value / 2);
+ scope.pages = [midVal - 2, midVal - 1, midVal, midVal + 1, midVal + 2];
+ }
+ if(scope.currentPage === undefined || scope.currentPage === 1)
+ {
+ currentPageChanged(1);
+ }
+ }
+ });
+ scope.$watch('currentPage', function (value) {
+ currentPageChanged(value);
+ callbackHandler(value);
+ });
+ var callbackHandler = function (num) {
+ if (angular.isFunction(scope.clickHandler)) {
+ scope.clickHandler(num);
+ }
+ };
+
+ function currentPageChanged(value) {
+ if (angular.isDefined(value) && value !== null) {
+ if (!value || value < 1) {
+ value = 1;
+ }
+ if (value > scope.totalPages) {
+ value = scope.totalPages;
+ }
+ if (scope.currentPage !== value) {
+ scope.currentPage = value;
+ callbackHandler(scope.currentPage);
+ }
+ if (scope.totalPages > 10) {
+ var val = parseInt(value);
+ if (val <= 6) {
+ scope.pages = [1, 2, 3, 4, 5, 6, 7, 8];
+ } else if (val > 6 && val <= scope.totalPages - 5) {
+ scope.pages = [val - 1, val, val + 1];
+ } else if (val >= scope.totalPages - 5) {
+ scope.pages = [scope.totalPages - 7, scope.totalPages - 6, scope.totalPages - 5, scope.totalPages - 4, scope.totalPages - 3, scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
+ }
+ }
+ if (scope.isMobile) {
+ var inWidth = $window.innerWidth;
+ var viewLimit = 7;
+ if (inWidth <= 400) {
+ viewLimit = 7;
+ } else if (inWidth > 400 && inWidth < 500) {
+ viewLimit = 9;
+ } else if (inWidth >= 500 && inWidth < 600) {
+ viewLimit = 11;
+ } else if (inWidth >= 600 && inWidth < 700) {
+ viewLimit = 13;
+ } else if (inWidth >= 700 && inWidth < 800) {
+ viewLimit = 15;
+ }
+
+ var val = parseInt(value);
+
+ scope.meanVal = Math.floor(viewLimit / 2);
+ var lowerLimit = (val - scope.meanVal) < 1 ? 1 : val - scope.meanVal;
+ var upperLimit = (lowerLimit + viewLimit - 1) > scope.totalPages ? scope.totalPages : lowerLimit + viewLimit - 1;
+ scope.pages = [];
+ for (var i = lowerLimit; i <= upperLimit; i++) {
+ scope.pages.push(i);
+ }
+ }
+ }
+ }
+ scope.gotoKeyClick = function (keyEvent) {
+ if (keyEvent.which === keymap.KEY.ENTER) {
+ scope.gotoBtnClick()
+ }
+ }
+ scope.gotoBtnClick = function () {
+ currentPageChanged(parseInt(scope.gotoPage));
+ callbackHandler(scope.currentPage);
+ var qResult = elem[0].querySelector('button');
+ angular.element(qResult).attr('disabled','true');
+ $timeout(function(){
+ elem[0].querySelector('.b2b-pager__item--active').focus();
+ }, 50);
+ scope.gotoPage = null;
+ }
+ scope.onfocusIn = function(evt)
+ {
+ var qResult = elem[0].querySelector('button');
+ angular.element(qResult).removeAttr('disabled');
+ }
+ scope.onfocusOut = function(evt)
+ {
+ if(evt.target.value === "")
+ {
+ var qResult = elem[0].querySelector('button');
+ angular.element(qResult).attr('disabled','true');
+ }
+ }
+ scope.next = function (event) {
+ if (event != undefined) {
+ event.preventDefault();
+ }
+ if (scope.currentPage < scope.totalPages) {
+ scope.currentPage += 1;
+ callbackHandler(scope.currentPage);
+ }
+ };
+ scope.prev = function (event) {
+ if (event != undefined) {
+ event.preventDefault();
+ }
+ if (scope.currentPage > 1) {
+ scope.currentPage -= 1;
+ callbackHandler(scope.currentPage);
+ }
+ };
+ scope.selectPage = function (value, event) {
+ event.preventDefault();
+ scope.currentPage = value;
+ scope.focusedPage = value;
+ callbackHandler(scope.currentPage);
+ };
+ scope.checkSelectedPage = function (value) {
+ if (scope.currentPage === value) {
+ return true;
+ }
+ return false;
+ };
+ scope.isFocused = function (page) {
+ return scope.focusedPage === page;
+ };
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:paneSelector
+ *
+ * @description
+ * <file src="src/paneSelector/docs/readme.md" />
+ *
+ * @usage
+ * Please refer demo.html tab in Example section below.
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/paneSelector/docs/demo.html" />
+ <file src="src/paneSelector/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.paneSelector', ['b2b.att.tabs', 'b2b.att.utilities'])
+
+.filter('paneSelectorSelectedItemsFilter', [function () {
+ return function (listOfItemsArray) {
+
+ if (!listOfItemsArray) {
+ listOfItemsArray = [];
+ }
+
+ var returnArray = [];
+
+ for (var i = 0; i < listOfItemsArray.length; i++) {
+ if (listOfItemsArray[i].isSelected) {
+ returnArray.push(listOfItemsArray[i]);
+ }
+ }
+
+ return returnArray;
+ };
+}])
+
+.filter('paneSelectorFetchChildItemsFilter', [function () {
+ return function (listOfItemsArray) {
+
+ if (!listOfItemsArray) {
+ listOfItemsArray = [];
+ }
+
+ var returnArray = [];
+
+ for (var i = 0; i < listOfItemsArray.length; i++) {
+ for (var j = 0; j < listOfItemsArray[i].childItems.length; j++) {
+ returnArray.push(listOfItemsArray[i].childItems[j]);
+ }
+ }
+
+ return returnArray;
+ };
+}])
+
+.directive('b2bPaneSelector', [function () {
+ return {
+ restrict: 'AE',
+ replace: true,
+ templateUrl: 'b2bTemplate/paneSelector/paneSelector.html',
+ transclude: true,
+ scope: {}
+ };
+}])
+
+.directive('b2bPaneSelectorPane', [ function () {
+ return {
+ restrict: 'AE',
+ replace: true,
+ templateUrl: 'b2bTemplate/paneSelector/paneSelectorPane.html',
+ transclude: true,
+ scope: {}
+ };
+}])
+
+.directive('b2bTabVertical', ['$timeout', 'keymap', function ($timeout, keymap) {
+ return {
+ restrict: 'A',
+ require: '^b2bTab',
+ link: function (scope, element, attr, b2bTabCtrl) {
+
+ if (!b2bTabCtrl) {
+ return;
+ }
+
+ // retreive the isolateScope
+ var iScope = angular.element(element).isolateScope();
+
+ $timeout(function () {
+ angular.element(element[0].querySelector('a')).unbind('keydown');
+ angular.element(element[0].querySelector('a')).bind('keydown', function (evt) {
+
+ if (!(evt.keyCode)) {
+ evt.keyCode = evt.which;
+ }
+
+ switch (evt.keyCode) {
+ case keymap.KEY.DOWN:
+ evt.preventDefault();
+ iScope.nextKey();
+ break;
+
+ case keymap.KEY.UP:
+ evt.preventDefault();
+ iScope.previousKey();
+ break;
+
+ default:;
+ }
+ });
+ });
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:phoneNumberInput
+ *
+ * @description
+ * <file src="src/phoneNumberInput/docs/readme.md" />
+ *
+ * @usage
+<form name="userForm1">
+ <div class="form-row" ng-class="{'error':!userForm1.text.$valid && userForm1.text.$dirty}">
+ <label>Phone Mask<span style="color:red">*</span>: (npa) nxx-line &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Model Value: {{mask.text}}</label>
+ <div>
+ <input b2b-phone-mask="phoneMask" name="text" ng-model="mask.text" type="text" placeholder="e.g. (123) 456-7890" title="Phone Number" class="b2b-phone-mask-input" required />
+ <div ng-messages="userForm1.text.$error" class="error-msg" aria-live="polite" aria-atomic="true">
+ <span ng-message="required" role="alert">This field is mandatory!</span>
+ <span ng-message="invalidPhoneNumber" role="alert">Please enter valid phone number!</span>
+ <span ng-message="mask" role="alert">Please enter valid phone number!</span>
+ </div>
+ </div>
+ </div>
+</form>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/phoneNumberInput/docs/demo.html" />
+ <file src="src/phoneNumberInput/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.phoneNumberInput', ['ngMessages', 'b2b.att.utilities'])
+ .constant("CoreFormsUiConfig", {
+ phoneMask: '(___) ___-____',
+ phoneMaskDot: '___.___.____',
+ phoneMaskHyphen: '___-___-____'
+ })
+ .directive('b2bPhoneMask', ['$parse', 'CoreFormsUiConfig', 'keymap', function ($parse, CoreFormsUiConfig, keymap) {
+ return {
+ require: 'ngModel',
+ scope: {
+ ngModel: '='
+ },
+ link: function (scope, iElement, iAttrs, ctrl) {
+ var navigatorAgent = navigator.userAgent.toLowerCase(),
+ isAndroid = navigatorAgent.indexOf("android") > -1,
+ oldIE = navigatorAgent.indexOf('msie 8.0') !== -1;
+ var mask = '';
+ var validPhoneNumber = false;
+ var currentKey = '';
+ if (isAndroid) {
+ mask = "__________";
+ } else {
+ switch (iAttrs.b2bPhoneMask) {
+ case "phoneMask":
+ mask = CoreFormsUiConfig.phoneMask;
+ break;
+ case "phoneMaskDot":
+ mask = CoreFormsUiConfig.phoneMaskDot;
+ break;
+ case "phoneMaskHyphen":
+ mask = CoreFormsUiConfig.phoneMaskHyphen;
+ break;
+ default:
+ mask = CoreFormsUiConfig.phoneMask;
+ }
+ }
+ iElement.attr("maxlength", mask.length);
+ var checkValidity = function (unmaskedValue, rawValue) {
+ var valid = false;
+ if (angular.isUndefined(rawValue) || rawValue === '') {
+ valid = true;
+ } else if (unmaskedValue) {
+ valid = (unmaskedValue.length === 10);
+ }
+ ctrl.$setValidity('invalidPhoneNumber', validPhoneNumber);
+ ctrl.$setValidity('mask', valid);
+ return valid;
+ };
+ var handleKeyup = function (evt) {
+
+ if (evt && evt.keyCode === keymap.KEY.SHIFT) {
+ return;
+ }
+
+ var index, formattedNumber;
+ if (ctrl.$modelValue) {
+ formattedNumber = ctrl.$modelValue;
+ } else {
+ formattedNumber = iElement.val();
+ }
+ if (!formattedNumber.length && currentKey === '') {
+ return;
+ }
+ var maskLength, inputNumbers, maskArray, tempArray, maskArrayLength;
+ tempArray = [];
+ maskArray = mask.split("");
+ maskArrayLength = maskArray.length;
+ maskLength = formattedNumber.substring(0, mask.length);
+ inputNumbers = formattedNumber.replace(/[^0-9]/g, "").split("");
+ for (index = 0; index < maskArrayLength; index++) {
+ tempArray.push(maskArray[index] === "_" ? inputNumbers.shift() : maskArray[index]);
+ if (inputNumbers.length === 0) {
+ break;
+ }
+ }
+ formattedNumber = tempArray.join("");
+ if (formattedNumber === '(') {
+ formattedNumber = '';
+ }
+
+ if ( (angular.isDefined(evt) && evt.which) && currentKey !== '') {
+ if (maskArray[0] === currentKey && formattedNumber === '') {
+ formattedNumber = '(';
+ } else if (evt.which === keymap.KEY.SPACE && currentKey === ' ') {
+ formattedNumber = formattedNumber + ') ';
+ } else if (maskArray[0] === currentKey && formattedNumber === '') {
+ formattedNumber = formattedNumber + currentKey;
+ } else if (maskArray[formattedNumber.length] === currentKey) {
+ formattedNumber = formattedNumber + currentKey;
+ }
+ currentKey = '';
+ }
+
+ ctrl.$setViewValue(formattedNumber);
+ ctrl.$render();
+ return formattedNumber;
+ };
+
+
+ // since we are only allowing 0-9, why even let the keypress go forward?
+ // also added in delete... in case they want to delete :)
+ var handlePress = function (e) {
+ if (e.which) {
+ if ((e.which < 48 || e.which > 57) && (e.which < 96 || e.which > 105)) {
+ if (e.which !== keymap.KEY.BACKSPACE && e.which !== keymap.KEY.TAB && e.which !== keymap.KEY.DELETE && e.which !== keymap.KEY.ENTER && e.which !== keymap.KEY.LEFT && e.which !== keymap.KEY.RIGHT &&
+ // Allow: Ctrl+V/v
+ (!(e.ctrlKey) && (e.which !== '118' || e.which !== '86')) &&
+ // Allow: Ctrl+C/c
+ (!(e.ctrlKey) && (e.which !== '99' || e.which !== '67')) &&
+ // Allow: Ctrl+X/x
+ (!(e.ctrlKey) && (e.which !== '120' || e.which !== '88'))) {
+ e.preventDefault ? e.preventDefault() : e.returnValue = false;
+ iElement.attr("aria-label", "Only numbers are allowed");
+ validPhoneNumber = false;
+ }
+ } else {
+ iElement.removeAttr("aria-label");
+ validPhoneNumber = true;
+ }
+
+ setCurrentKey(e);
+ }
+ scope.$apply();
+ };
+ // i moved this out because i thought i might need focus as well..
+ // to handle setting the model as the view changes
+ var parser = function (fromViewValue) {
+ var letters = /^[A-Za-z]+$/;
+ var numbers = /^[0-9]+$/;
+ if (angular.isUndefined(fromViewValue) || fromViewValue === '') {
+ validPhoneNumber = true;
+ } else {
+ if (fromViewValue.match(letters)) {
+ validPhoneNumber = false;
+ }
+ if (fromViewValue.match(numbers)) {
+ validPhoneNumber = true;
+ }
+ }
+ var clean = "";
+ if (fromViewValue && fromViewValue.length > 0) {
+ clean = fromViewValue.replace(/[^0-9]/g, '');
+ }
+ checkValidity(clean, fromViewValue);
+ return clean;
+ };
+
+ //to handle reading the model and formatting it
+ var formatter = function (fromModelView) {
+ var input = '';
+ checkValidity(fromModelView);
+ if (fromModelView) {
+ input = handleKeyup();
+ }
+ return input;
+ };
+
+ var setCurrentKey = function (e) {
+ switch (e.which) {
+ case 189:
+ case 109:
+ currentKey = '-';
+ break;
+ case 190:
+ case 110:
+ currentKey = '.';
+ break;
+ case 57:
+ if (e.shiftKey === true) {
+ currentKey = '(';
+ }
+ break;
+ case 48:
+ if (e.shiftKey === true) {
+ currentKey = ')';
+ }
+ break;
+ case 32:
+ currentKey = ' ';
+ break;
+ }
+ };
+
+ if (angular.isDefined(scope.ngModel)) {
+ parser(scope.ngModel);
+ }
+
+ ctrl.$parsers.push(parser);
+ ctrl.$formatters.push(formatter);
+ iElement.bind('keyup', handleKeyup);
+ iElement.bind('keydown', handlePress);
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Template.att:Profile Blocks
+ *
+ * @description
+ * <file src="src/profileBlockTemplate/docs/readme.md" />
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/profileBlockTemplate/docs/demo.html" />
+ <file src="src/profileBlockTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.profileBlockTemplate', [])
+
+
+
+/**
+ * @ngdoc directive
+ * @name Layouts.att:profileCard
+ *
+ * @description
+ * <file src="src/profileCard/docs/readme.md" />
+ *
+ * @usage
+ * <b2b-profile-card></b2b-profile-card>
+ *
+ * @example
+ <section id="code">
+ <example module="b2b.att">
+ <file src="src/profileCard/docs/demo.html" />
+ <file src="src/profileCard/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.profileCard', ['b2b.att'])
+.constant('profileStatus',{
+ status: {
+ ACTIVE: {
+ status: "Active",
+ color: "green"
+ },
+ DEACTIVATED: {
+ status: "Deactivated",
+ color: "red"
+ },
+ LOCKED: {
+ status: "Locked",
+ color: "red"
+ },
+ IDLE: {
+ status: "Idle",
+ color: "yellow"
+ },
+ PENDING: {
+ status: "Pending",
+ color: "blue"
+ }
+ },
+ role: "COMPANY ADMINISTRATOR"
+
+})
+.directive('b2bProfileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
+ return {
+ restrict: 'EA',
+ replace: 'true',
+ templateUrl: function(element, attrs){
+ if(!attrs.addUser){
+ return 'b2bTemplate/profileCard/profileCard.html';
+ }
+ else{
+ return 'b2bTemplate/profileCard/profileCard-addUser.html';
+ }
+ },
+ scope: {
+ profile:'=',
+ characterLimit: '@'
+ },
+ link: function(scope, elem, attr){
+ scope.characterLimit = parseInt(attr.characterLimit, 10) || 25;
+ scope.shouldClip = function(str) {
+ return str.length > scope.characterLimit;
+ };
+
+ scope.showEmailTooltip = false;
+
+ scope.image=true;
+ function isImage(src) {
+ var deferred = $q.defer();
+ var image = new Image();
+ image.onerror = function() {
+ deferred.reject(false);
+ };
+ image.onload = function() {
+ deferred.resolve(true);
+ };
+ if(src !== undefined && src.length>0 ){
+ image.src = src;
+ } else {
+ deferred.reject(false);
+ }
+ return deferred.promise;
+ }
+ if(!attr.addUser){
+ scope.image=false;
+ isImage(scope.profile.img).then(function(img) {
+ scope.image=img;
+ });
+ var splitName=(scope.profile.name).split(' ');
+ scope.initials='';
+ for(var i=0;i<splitName.length;i++){
+ scope.initials += splitName[i][0];
+ }
+ if(scope.profile.role.toUpperCase() === profileStatus.role){
+ scope.badge=true;
+ }
+ var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
+ if(profileState) {
+ scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
+ scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
+ if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
+ scope.profile.lastLogin=scope.profile.state;
+ }
+ }
+ var today=new Date().getTime();
+ var lastlogin=new Date(scope.profile.lastLogin).getTime();
+ var diff=(today-lastlogin)/(1000*60*60*24);
+ if(diff<=1){
+ scope.profile.lastLogin="Today";
+ }
+ else if(diff<=2){
+ scope.profile.lastLogin="Yesterday";
+ }
+ }
+ }
+};
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:radios
+ *
+ * @description
+ * <file src="src/radios/docs/readme.md" />
+ *
+ * @usage
+ * See demo section
+ *
+ * @param {boolean} refreshRadioGroup - A trigger that recalculates and updates the accessibility roles on radios in a group.
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/radios/docs/demo.html" />
+ <file src="src/radios/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.radios', ['b2b.att.utilities'])
+.directive('b2bRadioGroupAccessibility', ['$timeout', 'b2bUserAgent', function($timeout, b2bUserAgent) {
+ return {
+ restrict: "A",
+ scope: {
+ refreshRadioGroup: "=",
+ },
+ link: function(scope, ele, attr) {
+
+ var roleRadioElement, radioProductSelectElement, radioInputTypeElement;
+
+ $timeout(calculateNumberOfRadio);
+
+ scope.$watch('refreshRadioGroup', function(value) {
+ if (value === true) {
+ addingRoleAttribute();
+ $timeout(calculateNumberOfRadio);
+ scope.refreshRadioGroup = false;
+ } else {
+ return;
+ }
+ })
+
+
+ function calculateNumberOfRadio() {
+ roleRadioElement = ele[0].querySelectorAll('[role="radio"]');
+
+ radioProductSelectElement = ele[0].querySelectorAll('[role="radiogroup"] li.radio-box');
+
+ radioInputTypeElement = ele[0].querySelectorAll('input[type="radio"]');
+
+ for (var i = 0; i < radioInputTypeElement.length; i++) {
+ var isChecked = radioInputTypeElement[i].checked ? 'true' : 'false';
+ var isDisabled = radioInputTypeElement[i].disabled ? 'true' : 'false';
+ var numOfx = i + 1 + ' of ' + radioInputTypeElement.length;
+ angular.element(roleRadioElement[i]).attr({
+ 'aria-checked': isChecked,
+ 'aria-disabled': isDisabled,
+ 'data-opNum': numOfx
+ });
+ if (b2bUserAgent.notMobile()) {
+ angular.element(roleRadioElement[i]).removeAttr("role");
+ }
+
+ if (radioProductSelectElement.length) {
+ isChecked === 'true' ? angular.element(radioProductSelectElement[i]).addClass('active') : angular.element(radioProductSelectElement[i]).removeClass('active');
+ }
+
+ if (/Android/i.test(navigator.userAgent)) {
+ angular.element(roleRadioElement[i]).append('<span class="hidden-spoken">. ' + numOfx + '.</span>');
+ }
+
+
+ angular.element(radioInputTypeElement[i]).bind('click', radioStateChangeonClick);
+
+ }
+ }
+
+ function addingRoleAttribute() {
+ for (var i = 0; i < radioInputTypeElement.length; i++) {
+ if (b2bUserAgent.notMobile()) {
+ angular.element(roleRadioElement[i]).attr("role", "radio");
+ }
+ }
+ }
+
+ function radioStateChangeonClick() {
+ for (var i = 0; i < radioInputTypeElement.length; i++) {
+ var isChecked = radioInputTypeElement[i].checked ? 'true' : 'false';
+ var isDisabled = radioInputTypeElement[i].disabled ? 'true' : 'false';
+ if (radioProductSelectElement.length) {
+ isChecked === 'true' ? angular.element(radioProductSelectElement[i]).addClass('active') : angular.element(radioProductSelectElement[i]).removeClass('active');
+ }
+ angular.element(roleRadioElement[i]).attr({
+ 'aria-checked': isChecked,
+ 'aria-disabled': isDisabled
+ });
+ }
+
+ }
+ }
+ }
+
+}]);
+
+/**
+ * @ngdoc directive
+ * @name Forms.att:searchField
+ *
+ * @description
+ * <file src="src/searchField/docs/readme.md" />
+ *
+ * @usage
+ * <div b2b-search-field dropdown-list="listdata" on-click-callback="clickFn(value)" class="span12" input-model='typedString' config-obj='keyConfigObj'></div>
+ *
+ * @example
+ <section id="code">
+ <example module="b2b.att">
+ <file src="src/searchField/docs/demo.html" />
+ <file src="src/searchField/docs/demo.js" />
+ </example>
+</section>
+ */
+
+angular.module('b2b.att.searchField', ['b2b.att.utilities', 'b2b.att.position'])
+ .filter('b2bFilterInput', [function() {
+ return function(list, str, keyArray, displayListKey, isContainsSearch, searchSeperator) {
+ var res = [];
+ var searchLabel;
+ var searchCondition;
+ var conditionCheck = function(searchSeperator, listItem, displayListKey, splitString) {
+ var displayTitle = null;
+ if (splitString) {
+ for (var i = 0; i < displayListKey.length; i++) {
+ if (i <= 0) {
+ displayTitle = listItem[displayListKey[i]].toLowerCase().indexOf(splitString[i].toLowerCase()) > -1;
+ } else {
+ displayTitle = (splitString[i]) ? displayTitle && listItem[displayListKey[i]].toLowerCase().indexOf(splitString[i].toLowerCase().trim()) > -1 : displayTitle;
+ }
+ }
+ } else {
+ angular.forEach(displayListKey, function(value) {
+ if (!displayTitle) {
+ displayTitle = listItem[value];
+ } else {
+ displayTitle = displayTitle + (listItem[value] ? searchSeperator + ' ' + listItem[value] : '');
+ }
+ });
+ }
+ return displayTitle;
+ }
+ angular.forEach(list, function(listItem) {
+ var splitString = str.indexOf(searchSeperator) > -1 ? str.split(searchSeperator) : false;
+ var displayList = conditionCheck(searchSeperator, listItem, displayListKey, splitString)
+ for (var i = 0; i < keyArray.length; i++) {
+ searchLabel = keyArray[i];
+ if (listItem[searchLabel]) {
+ if (isContainsSearch) {
+ var displaySearchList = listItem[searchLabel].toLowerCase().indexOf(str.toLowerCase()) > -1;
+ if (splitString.length > 1) {
+ displaySearchList = (splitString.length <= keyArray.length) ? displayList : false;
+ }
+ searchCondition = displaySearchList;
+ } else {
+ searchCondition = listItem[searchLabel].match(new RegExp('^' + str, 'gi'));
+ }
+ if (searchCondition) {
+ res.push({
+ 'title': conditionCheck(searchSeperator, listItem, displayListKey),
+ 'valueObj': listItem
+ });
+ break;
+ }
+ }
+ }
+ });
+ return res;
+ };
+ }]).directive('b2bSearchField', ['$filter', 'b2bFilterInputFilter', 'keymap', '$documentBind', '$isElement', '$document', 'events', '$timeout', function($filter, b2bFilterInput, keymap, $documentBind, $isElement, $document, events, $timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ dataList: '=dropdownList',
+ onClickCallback: '&',
+ inputModel: '=',
+ configObj: '=',
+ objModel: '=',
+ inputDeny: '=?',
+ disabled: '=?'
+ },
+ replace: true,
+ templateUrl: 'b2bTemplate/searchField/searchField.html',
+ controller: ['$scope', function($scope) {
+ this.searchKeyArray = [];
+ if ($scope.configObj.searchKeys) {
+ this.searchKeyArray = $scope.configObj.searchKeys;
+ }
+ if (angular.isUndefined($scope.disabled)) {
+ $scope.disabled = false;
+ }
+ this.triggerInput = function(searchString) {
+ $scope.originalInputModel = searchString;
+ if (searchString === '') {
+ $scope.currentIndex = -1;
+ $scope.filterList = [];
+ $scope.showListFlag = false;
+ } else if (searchString !== '' && !$scope.isFilterEnabled) {
+ $scope.filterList = $filter('b2bFilterInput')($scope.dataList, searchString, this.searchKeyArray, $scope.configObj.displayListDataKey, $scope.configObj.isContainsSearch, $scope.configObj.searchSeperator);
+ $scope.showListFlag = true;
+ }
+ };
+ this.denyRegex = function() {
+ return $scope.inputDeny;
+ };
+ }],
+ link: function(scope, elem) {
+ scope.isFilterEnabled = false;
+ scope.showListFlag = false;
+ scope.currentIndex = -1;
+ scope.setCurrentIdx = function(idx) {
+ scope.currentIndex = idx;
+ if (idx > -1) {
+ scope.inputModel = scope.filterList[idx].title;
+ scope.objModel = scope.filterList[idx];
+ }
+ };
+ scope.isActive = function(index, dropdownLength) {
+ scope.dropdownLength = dropdownLength;
+ return scope.currentIndex === index;
+ };
+ scope.selectItem = function(idx) {
+ scope.setCurrentIdx(idx);
+ scope.onClickCallback({
+ value: scope.inputModel,
+ objValue: scope.objModel
+ });
+ scope.showListFlag = false;
+ $timeout(function() {
+ elem.find('div').find('input')[0].focus();
+ }, 150);
+ };
+ scope.startSearch = function() {
+ scope.onClickCallback({
+ value: scope.inputModel,
+ objValue: scope.objModel
+ });
+ };
+ scope.selectPrev = function() {
+ if (scope.currentIndex > 0 && scope.filterList.length > 0) {
+ scope.currentIndex = scope.currentIndex - 1;
+ scope.setCurrentIdx(scope.currentIndex);
+ } else if (scope.currentIndex === 0) {
+ scope.currentIndex = scope.currentIndex - 1;
+ scope.inputModel = scope.originalInputModel;
+ scope.isFilterEnabled = true;
+ }
+ };
+ scope.selectNext = function() {
+ if (scope.currentIndex < scope.configObj.noOfItemsDisplay - 1) {
+ if (scope.currentIndex < scope.filterList.length - 1) {
+ scope.currentIndex = scope.currentIndex + 1;
+ scope.setCurrentIdx(scope.currentIndex);
+ }
+ }
+ };
+ scope.selectCurrent = function() {
+ scope.selectItem(scope.currentIndex);
+ };
+ scope.selectionIndex = function(e) {
+ switch (e.keyCode) {
+ case keymap.KEY.DOWN:
+ events.preventDefault(e);
+ scope.isFilterEnabled = true;
+ scope.selectNext();
+ break;
+ case keymap.KEY.UP:
+ events.preventDefault(e);
+ scope.isFilterEnabled = true;
+ scope.selectPrev();
+ break;
+ case keymap.KEY.ENTER:
+ events.preventDefault(e);
+ scope.isFilterEnabled = true;
+ scope.selectCurrent();
+ break;
+ case keymap.KEY.ESC:
+ events.preventDefault(e);
+ scope.isFilterEnabled = false;
+ scope.showListFlag = false;
+ scope.inputModel = '';
+ break;
+ default:
+ scope.isFilterEnabled = false;
+ break;
+ }
+ if (elem[0].querySelector('.filtercontainer')) {
+ elem[0].querySelector('.filtercontainer').scrollTop = (scope.currentIndex - 1) * 35;
+ }
+ };
+ scope.$watch('filterList', function(newVal, oldVal) {
+ if (newVal !== oldVal) {
+ scope.currentIndex = -1;
+ }
+ });
+ scope.blurInput = function() {
+ $timeout(function() {
+ scope.showListFlag = false;
+ }, 150);
+ };
+ var outsideClick = function(e) {
+ var isElement = $isElement(angular.element(e.target), elem.find('ul').eq(0), $document);
+ if (!isElement && document.activeElement.tagName.toLowerCase() !== 'input') {
+ scope.showListFlag = false;
+ scope.$apply();
+ }
+ };
+ $documentBind.click('showListFlag', outsideClick, scope);
+ }
+ };
+ }])
+ .directive('b2bSearchInput', [function() {
+ return {
+ restrict: 'A',
+ require: ['ngModel', '^b2bSearchField'],
+ link: function(scope, elem, attr, ctrl) {
+ var ngModelCtrl = ctrl[0];
+ var attSearchBarCtrl = ctrl[1];
+ var REGEX = ctrl[1].denyRegex();
+ var parser = function(viewValue) {
+ attSearchBarCtrl.triggerInput(viewValue);
+ return viewValue;
+ };
+ ngModelCtrl.$parsers.push(parser);
+
+ if (REGEX !== undefined || REGEX !== '') {
+ elem.bind('input', function() {
+ var inputString = ngModelCtrl.$viewValue && ngModelCtrl.$viewValue.replace(REGEX, '');
+ if (inputString !== ngModelCtrl.$viewValue) {
+ ngModelCtrl.$setViewValue(inputString);
+ ngModelCtrl.$render();
+ scope.$apply();
+ }
+ });
+ }
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:Seek bar
+ *
+ * @description
+ * <file src="src/seekBar/docs/readme.md" />
+ *
+ * @usage
+ * Horizontal Seek Bar
+ * <b2b-seek-bar min="0" max="400" step="1" skip-interval="1" data-ng-model="horizontalSeekBarVal" style="width:180px; margin: auto;" on-drag-end="onDragEnd()" on-drag-init="onDragStart()"></b2b-seek-bar>
+
+ * Vertical Seek Bar
+ * <b2b-seek-bar min="0" max="1" step="0.01" skip-interval="0.1" vertical data-ng-model="verticalSeekBarVal" style=" width: 6px; height: 180px; margin: auto;"></b2b-seek-bar>
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/seekBar/docs/demo.html" />
+ <file src="src/seekBar/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.seekBar', ['b2b.att.utilities','b2b.att.position'])
+ .constant('b2bSeekBarConfig', {
+ 'min': 0,
+ 'max': 100,
+ 'step': 1,
+ 'skipInterval': 1
+ })
+ .directive('b2bSeekBar', ['$documentBind', 'events', 'b2bSeekBarConfig', 'keymap', '$compile', function($documentBind, events, b2bSeekBarConfig, keymap, $compile) {
+ return {
+ restrict: 'AE',
+ replace: true,
+ require: 'ngModel',
+ templateUrl: 'b2bTemplate/seekBar/seekBar.html',
+ scope: {
+ onDragEnd: '&?',
+ onDragInit: '&?'
+ },
+ link: function(scope, elm, attr, ngModelCtrl) {
+ scope.isDragging = false;
+ scope.verticalSeekBar = false;
+ var min;
+ var max;
+ var step = b2bSeekBarConfig.step;
+ var skipInterval = b2bSeekBarConfig.skipInterval;
+ var knob = angular.element(elm[0].querySelector('.b2b-seek-bar-knob-container'));
+ var seekBarKnob = angular.element(knob[0].querySelector('.b2b-seek-bar-knob'));
+ var trackContainer = angular.element(elm[0].querySelector('.b2b-seek-bar-track-container'));
+ var trackFill = angular.element(elm[0].querySelector('.b2b-seek-bar-track-fill'));
+ var trackContainerRect = {};
+ var axisPosition;
+ var trackFillOrderPositioning;
+
+ if (angular.isDefined(attr.vertical)) {
+ scope.verticalSeekBar = true;
+ axisPosition = "clientY";
+ }
+ else {
+ scope.verticalSeekBar = false;
+ axisPosition = "clientX";
+ }
+ var getValidStep = function(val) {
+ val = parseFloat(val);
+ // in case $modelValue came in string number
+ if (angular.isNumber(val)) {
+ val = Math.round((val - min) / step) * step + min;
+ return Math.round(val * 1000) / 1000;
+ }
+ };
+
+ var getPositionToPercent = function(x) {
+ if (scope.verticalSeekBar) {
+ return Math.max(0, Math.min(1, (trackContainerRect.bottom - x) / (trackFillOrderPositioning)));
+ }
+ else {
+ return Math.max(0, Math.min(1, (x - trackContainerRect.left) / (trackFillOrderPositioning)));
+ }
+ };
+
+ var getPercentToValue = function(percent) {
+ return (min + percent * (max - min));
+ };
+
+ var getValueToPercent = function(val) {
+ return (val - min) / (max - min);
+ };
+
+ var getValidMinMax = function(val) {
+ return Math.max(min, Math.min(max, val));
+ };
+
+ var updateTrackContainerRect = function() {
+ trackContainerRect = trackContainer[0].getBoundingClientRect();
+ if (scope.verticalSeekBar) {
+ if (!trackContainerRect.height) {
+ trackFillOrderPositioning = trackContainer[0].scrollHeight;
+ } else {
+ trackFillOrderPositioning = trackContainerRect.height;
+ }
+ }
+ else {
+ if (!trackContainerRect.width) {
+ trackFillOrderPositioning = trackContainer[0].scrollWidth;
+ } else {
+ trackFillOrderPositioning = trackContainerRect.width;
+ }
+
+ }
+
+ };
+
+ var updateKnobPosition = function(percent) {
+ var percentStr = (percent * 100) + '%';
+ if (scope.verticalSeekBar) {
+ knob.css('bottom', percentStr);
+ trackFill.css('height', percentStr);
+ }
+ else {
+ knob.css('left', percentStr);
+ trackFill.css('width', percentStr);
+ }
+ };
+
+ var modelRenderer = function() {
+ if (isNaN(ngModelCtrl.$viewValue)) {
+ ngModelCtrl.$viewValue = ngModelCtrl.$modelValue || min;
+ }
+
+ var viewVal = ngModelCtrl.$viewValue;
+ scope.currentModelValue = viewVal;
+
+ //wait for min, max and step to be set then only update UI to avoid NaN on percent calculation
+ if ((min || min === 0) && max && step) {
+ updateKnobPosition(getValueToPercent(viewVal));
+ }
+ };
+
+ var setModelValue = function(val) {
+ scope.currentModelValue = getValidMinMax(getValidStep(val));
+ ngModelCtrl.$setViewValue(scope.currentModelValue);
+ };
+
+ var updateMin = function(val) {
+ min = parseFloat(val);
+ if(isNaN(min)){
+ min = b2bSeekBarConfig.min;
+ }
+ modelRenderer();
+ };
+
+ var updateMax = function(val) {
+ max = parseFloat(val);
+ if(isNaN(max)){
+ max = b2bSeekBarConfig.max;
+ }
+ modelRenderer();
+ };
+
+ var updateStep = function(val) {
+ step = parseFloat(val);
+ if (!attr['skipInterval']) {
+ skipInterval = step;
+ }
+ };
+
+ var updateSkipInterval = function(val) {
+ skipInterval = step * Math.ceil(val / (step!==0?step:1));
+ };
+
+ angular.isDefined(attr.min) ? attr.$observe('min', updateMin) : updateMin(b2bSeekBarConfig.min);
+ angular.isDefined(attr.max) ? attr.$observe('max', updateMax) : updateMax(b2bSeekBarConfig.max);
+ if (angular.isDefined(attr.step)) {
+ attr.$observe('step', updateStep);
+ }
+ if (angular.isDefined(attr.skipInterval)) {
+ attr.$observe('skipInterval', updateSkipInterval);
+ }
+ scope.currentModelValue = getValidMinMax(getValidStep(min));
+ var onMouseDown = function(e) {
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+ ;
+
+ scope.isDragging = true;
+ seekBarKnob[0].focus();
+ updateTrackContainerRect();
+ if (attr['onDragInit']) {
+ scope.onDragInit();
+ }
+ events.stopPropagation(e);
+ events.preventDefault(e);
+ scope.$apply(function() {
+ setModelValue(getPercentToValue(getPositionToPercent(e[axisPosition])));
+ });
+ };
+
+ var onMouseUp = function() {
+
+ if (attr['onDragEnd']) {
+ scope.onDragEnd();
+ }
+ scope.isDragging = false;
+ scope.$digest();
+ };
+
+ var onMouseMove = function(e) {
+ if (scope.isDragging) {
+ events.stopPropagation(e);
+ events.preventDefault(e);
+
+ scope.$apply(function() {
+ setModelValue(getPercentToValue(getPositionToPercent(e[axisPosition])));
+ });
+ }
+ };
+
+ function onKeyDown(e) {
+ if (!(e.keyCode)) {
+ e.keyCode = e.which;
+ }
+ var updateStep;
+ switch (e.keyCode) {
+ case keymap.KEY.LEFT:
+ if (!scope.verticalSeekBar) {
+ updateStep = -skipInterval;
+ }
+ break;
+ case keymap.KEY.RIGHT:
+ if (!scope.verticalSeekBar) {
+ updateStep = skipInterval;
+ }
+ break;
+ case keymap.KEY.UP:
+ if (scope.verticalSeekBar) {
+ updateStep = skipInterval;
+ }
+ break;
+ case keymap.KEY.DOWN:
+ if (scope.verticalSeekBar) {
+ updateStep = -skipInterval;
+ }
+ break;
+ default:
+ return;
+ }
+
+ if (updateStep) {
+ events.stopPropagation(e);
+ events.preventDefault(e);
+ scope.$apply(function() {
+ setModelValue(ngModelCtrl.$viewValue + updateStep);
+ });
+ if (attr['onDragEnd']) {
+ scope.onDragEnd();
+ }
+ }
+ }
+
+ elm.on('keydown', onKeyDown);
+ elm.on('mousedown', onMouseDown);
+
+ $documentBind.event('mousemove', 'isDragging', onMouseMove, scope, true, 0);
+ $documentBind.event('mouseup', 'isDragging', onMouseUp, scope, true, 0);
+
+ ngModelCtrl.$render = function() {
+ if (!scope.isDragging) {
+ modelRenderer();
+ }
+ };
+ ngModelCtrl.$viewChangeListeners.push(modelRenderer);
+ ngModelCtrl.$formatters.push(getValidMinMax);
+ ngModelCtrl.$formatters.push(getValidStep);
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:selectorModule
+ *
+ * @description
+ * <file src="src/selectorModule/docs/readme.md" />
+ *
+ * @usage
+ * <select name="myNameBig" type="large" b2b-dropdown ng-model="Controller Variable here">
+ * <option b2b-dropdown-list option-repeat="option data here" imgsrc="image path" value="value">List Text</option>
+ * </select>
+ *
+ * <select name="myNameBig" type="large" b2b-dropdown ng-model="Controller Variable here">
+ * <option b2b-dropdown-list option-repeat="option data here" imgsrc="image path" value="value">List Text</option>
+ * </select>
+ *
+ * <select name="myNameBig" b2b-dropdown ng-model="Controller Variable here">
+ * <optgroup b2b-dropdown-group label="Group Label here">
+ * <option b2b-dropdown-list option-repeat="option data here" imgsrc="image path" value="value">List Text</option>
+ * </optgroup>
+ * </select>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/selectorModule/docs/demo.html" />
+ <file src="src/selectorModule/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.selectorModule', ['b2b.att.dropdowns']);
+/**
+ * @ngdoc directive
+ * @name Layouts.att:separators
+ *
+ * @description
+ * <file src="src/separators/docs/readme.md" />
+ *
+ * @usage
+
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/separators/docs/demo.html" />
+ <file src="src/separators/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.separators', []);
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:slider
+ *
+ * @description
+ * <file src="src/slider/docs/readme.md" />
+ *
+ * @usage
+ * <b2b-slider min="0" max="400" step="1" no-aria-label skip-interval="1" ng-model="horizontalSliderVal" style="width:180px; margin: auto;" on-drag-end="onDragEnd()" on-drag-init="onDragStart()" label-id="slider-label" post-aria-label="postAriaLabel"></b2b-slider>
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/slider/docs/demo.html" />
+ <file src="src/slider/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.slider', ['b2b.att.utilities'])
+ .constant('SliderConfig', {
+ 'min': 0,
+ 'max': 100,
+ 'step': 1,
+ 'skipInterval': 1
+ })
+ .directive('b2bSlider', ['$documentBind', 'SliderConfig', 'keymap', '$compile', '$log', function($documentBind, SliderConfig, keymap, $compile, $log) {
+ return {
+ restrict: 'AE',
+ replace: true,
+ require: 'ngModel',
+ templateUrl: 'b2bTemplate/slider/slider.html',
+ scope: {
+ onDragEnd: '&?',
+ onDragInit: '&?',
+ trackFillColor: '=?',
+ preAriaLabel: '=?',
+ postAriaLabel: '=?',
+ onRenderEnd: '&?',
+ sliderSnapPoints: '=?',
+ customAriaLabel: '=?',
+ labelId: '@?'
+ },
+ link: function(scope, elm, attr, ngModelCtrl) {
+ scope.isDragging = false;
+ scope.verticalSlider = false;
+ var min;
+ var max;
+ var step = SliderConfig.step;
+ var skipInterval = SliderConfig.skipInterval;
+ var knob = angular.element(elm[0].querySelector('.slider-knob-container'));
+ var sliderKnob = angular.element(knob[0].querySelector('.slider-knob'));
+ var trackContainer = angular.element(elm[0].querySelector('.slider-track-container'));
+ var trackFill = angular.element(elm[0].querySelector('.slider-track-fill'));
+ var trackContainerRect = {};
+ var axisPosition = "clientX";
+ var trackFillOrderPositioning;
+
+ //Forcefully disabling the vertical Slider code.
+ if (angular.isDefined(attr.vertical)) {
+ scope.verticalSlider = true;
+ axisPosition = "clientY";
+ }
+
+ if (angular.isDefined(scope.noAriaLabel) && scope.noAriaLabel !== '') {
+ $log.warn('no-aria-label has been deprecated. This will be removed in v0.6.0.');
+ }
+ if (angular.isDefined(scope.preAriaLabel) && scope.preAriaLabel !== '') {
+ $log.warn('pre-aria-label has been deprecated. Please use label-id instead. This will be removed in v0.6.0.');
+ }
+ if (angular.isDefined(scope.customAriaLabel) && scope.customAriaLabel !== '') {
+ $log.warn('custom-aria-label has been deprecated. Please use label-id and post-aria-label instead. This will be removed in v0.6.0.');
+ }
+
+ var binarySearchNearest = function (num, arr) {
+ var mid;
+ var lo = 0;
+ var hi = arr.length - 1;
+
+ while (hi - lo > 1) {
+ mid = Math.floor((lo + hi) / 2);
+ if (arr[mid] < num) {
+ lo = mid;
+ } else {
+ hi = mid;
+ }
+ }
+ if (num - arr[lo] < arr[hi] - num) {
+ return arr[lo];
+ }
+ return arr[hi];
+ };
+
+ var getValidStep = function(val) {
+ val = parseFloat(val);
+ // in case $modelValue came in string number
+ if (!isNaN(val)) {
+
+ if(attr['sliderSnapPoints'] && scope.sliderSnapPoints.length > 0) {
+ val = binarySearchNearest(val, scope.sliderSnapPoints);
+ }
+ else {
+ val = Math.round((val - min) / step) * step + min;
+ }
+
+ return Math.round(val * 1000) / 1000;
+ }
+ };
+
+ var getPositionToPercent = function(x) {
+ if (scope.verticalSlider) {
+ return Math.max(0, Math.min(1, (trackContainerRect.bottom - x) / (trackFillOrderPositioning)));
+ }
+ else {
+ return Math.max(0, Math.min(1, (x - trackContainerRect.left) / (trackFillOrderPositioning)));
+ }
+ };
+
+ var getPercentToValue = function(percent) {
+ return (min + percent * (max - min));
+ };
+
+ var getValueToPercent = function(val) {
+ return (val - min) / (max - min);
+ };
+
+ var getValidMinMax = function(val) {
+ return Math.max(min, Math.min(max, val));
+ };
+
+ var updateTrackContainerRect = function() {
+ trackContainerRect = trackContainer[0].getBoundingClientRect();
+ if (scope.verticalSlider) {
+ if (!trackContainerRect.height) {
+ trackFillOrderPositioning = trackContainer[0].scrollHeight;
+ } else {
+ trackFillOrderPositioning = trackContainerRect.height;
+ }
+ }
+ else {
+ if (!trackContainerRect.width) {
+ trackFillOrderPositioning = trackContainer[0].scrollWidth;
+ } else {
+ trackFillOrderPositioning = trackContainerRect.width;
+ }
+
+ }
+
+ };
+
+ var updateKnobPosition = function(percent) {
+ var percentStr = (percent * 100) + '%';
+ if (scope.verticalSlider) {
+ knob.css('bottom', percentStr);
+ trackFill.css('height', percentStr);
+ }
+ else {
+ knob.css('left', percentStr);
+ trackFill.css('width', percentStr);
+ }
+ };
+
+ var modelRenderer = function() {
+
+ if(attr['disabled']){
+ return;
+ }
+
+ if (isNaN(ngModelCtrl.$viewValue)) {
+ ngModelCtrl.$viewValue = ngModelCtrl.$modelValue || min;
+ }
+
+ var viewVal = ngModelCtrl.$viewValue;
+ scope.currentModelValue = viewVal;
+
+ //wait for min, max and step to be set then only update UI to avoid NaN on percent calculation
+ if ((min || min === 0) && max && step) {
+ updateKnobPosition(getValueToPercent(viewVal));
+ }
+ };
+
+ var setModelValue = function(val) {
+ scope.currentModelValue = getValidMinMax(getValidStep(val));
+ ngModelCtrl.$setViewValue(scope.currentModelValue);
+ };
+
+ var updateMin = function(val) {
+ min = parseFloat(val);
+ if(isNaN(min)){
+ min = SliderConfig.min;
+ }
+ scope.min = min;
+ modelRenderer();
+ };
+
+ var updateMax = function(val) {
+ max = parseFloat(val);
+ if(isNaN(max)){
+ max = SliderConfig.max;
+ }
+ scope.max = max;
+ modelRenderer();
+ };
+
+ var updateStep = function(val) {
+ step = parseFloat(val);
+ if (!attr['skipInterval']) {
+ skipInterval = step;
+ }
+ };
+
+ var updateSkipInterval = function(val) {
+ skipInterval = step * Math.ceil(val / (step!==0?step:1));
+ };
+
+ angular.isDefined(attr.min) ? attr.$observe('min', updateMin) : updateMin(SliderConfig.min);
+ angular.isDefined(attr.max) ? attr.$observe('max', updateMax) : updateMax(SliderConfig.max);
+ if (angular.isDefined(attr.step)) {
+ attr.$observe('step', updateStep);
+ }
+ if (angular.isDefined(attr.skipInterval)) {
+ attr.$observe('skipInterval', updateSkipInterval);
+ }
+ scope.currentModelValue = getValidMinMax(getValidStep(min));
+ var onMouseDown = function(e) {
+
+ if(attr['disabled']){
+ return;
+ }
+
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+
+ scope.isDragging = true;
+ sliderKnob[0].focus();
+ updateTrackContainerRect();
+ if (attr['onDragInit']) {
+ scope.onDragInit();
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ scope.$apply(function() {
+ setModelValue(getPercentToValue(getPositionToPercent(e[axisPosition])));
+ });
+ };
+
+ var onMouseUp = function() {
+
+ if (attr['onDragEnd']) {
+ scope.onDragEnd();
+ }
+ scope.isDragging = false;
+ scope.$digest();
+ };
+
+ var onMouseMove = function(e) {
+ if (scope.isDragging) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ scope.$apply(function() {
+ setModelValue(getPercentToValue(getPositionToPercent(e[axisPosition])));
+ });
+ }
+ };
+
+ function onKeyDown(e) {
+ if (!(e.keyCode)) {
+ e.keyCode = e.which;
+ }
+ var updateStep;
+ switch (e.keyCode) {
+ case keymap.KEY.DOWN:
+ case keymap.KEY.LEFT:
+ if(attr['sliderSnapPoints'] && scope.sliderSnapPoints.length > 0) {
+ var currentIndex = scope.sliderSnapPoints.indexOf(ngModelCtrl.$viewValue);
+ if (currentIndex > 0) {
+ currentIndex--;
+ }
+ updateStep = scope.sliderSnapPoints[currentIndex];
+ }
+ else {
+ updateStep = ngModelCtrl.$viewValue - skipInterval;
+ }
+ break;
+ case keymap.KEY.UP:
+ case keymap.KEY.RIGHT:
+ if(attr['sliderSnapPoints'] && scope.sliderSnapPoints.length > 0) {
+ var currentIndex = scope.sliderSnapPoints.indexOf(ngModelCtrl.$viewValue);
+ if (currentIndex < scope.sliderSnapPoints.length-1) {
+ currentIndex++;
+ }
+ updateStep = scope.sliderSnapPoints[currentIndex];
+ }
+ else {
+ updateStep = ngModelCtrl.$viewValue + skipInterval;
+ }
+ break;
+ case keymap.KEY.END:
+ if(attr['sliderSnapPoints'] && scope.sliderSnapPoints.length > 0) {
+ currentIndex = scope.sliderSnapPoints.length-1;
+ updateStep = scope.sliderSnapPoints[currentIndex];
+ } else {
+ setModelValue(scope.max);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ break;
+ case keymap.KEY.HOME:
+ if(attr['sliderSnapPoints'] && scope.sliderSnapPoints.length > 0) {
+ currentIndex = 0;
+ updateStep = scope.sliderSnapPoints[currentIndex];
+ } else {
+ setModelValue(scope.min);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ break;
+ default:
+ return;
+ }
+
+ if (angular.isNumber(updateStep) && !attr['disabled']) {
+ e.stopPropagation();
+ e.preventDefault();
+ scope.$apply(function() {
+ setModelValue(updateStep);
+ });
+ if (attr['onDragEnd']) {
+ scope.onDragEnd();
+ }
+ }
+ }
+
+ elm.on('keydown', onKeyDown);
+ elm.on('mousedown', onMouseDown);
+
+ $documentBind.event('mousemove', 'isDragging', onMouseMove, scope, true, 0);
+ $documentBind.event('mouseup', 'isDragging', onMouseUp, scope, true, 0);
+
+ attr.$observe('disabled', function (disabled) {
+ if (disabled) {
+ sliderKnob.removeAttr('tabindex');
+ } else {
+ sliderKnob.attr('tabindex', '0');
+ disabled = false;
+ }
+
+ elm.toggleClass("slider-disabled", disabled);
+
+ if (angular.isDefined(attr.hideDisabledKnob)) {
+ scope.hideKnob = disabled;
+ }
+ });
+
+ ngModelCtrl.$render = function() {
+ if (!scope.isDragging) {
+ modelRenderer();
+ if (attr['onRenderEnd'] && !attr['disabled']) {
+ scope.onRenderEnd({currentModelValue: scope.currentModelValue});
+ }
+ }
+ };
+ ngModelCtrl.$viewChangeListeners.push(modelRenderer);
+ ngModelCtrl.$formatters.push(getValidMinMax);
+ ngModelCtrl.$formatters.push(getValidStep);
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:spinButton
+ *
+ * @param {String} spin-button-id - An ID for the input field
+ * @param {Integer} min - Minimum value for the input
+ * @param {Integer} max - Maximum value for the input
+ * @param {Integer} step - Value by which input field increments or decrements on up/down arrow keys
+ * @param {Integer} page-step - Value by which input field increments or decrements on page up/down keys
+ * @param {boolean} input-model-key - Default value for input field
+ * @param {boolean} disabled-flag - A boolean that triggers directive once the min or max value has reached
+ *
+ * @description
+ * <file src="src/spinButton/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/spinButton/docs/demo.html" />
+ <file src="src/spinButton/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.spinButton', ['b2b.att.utilities'])
+ .constant('b2bSpinButtonConfig', {
+ min: 1,
+ max: 10,
+ step: 1,
+ pageStep: 10,
+ inputModelKey: 'value',
+ disabledFlag: false
+ })
+ .directive('b2bSpinButton', ['keymap', 'b2bSpinButtonConfig', 'b2bUserAgent', function (keymap, b2bSpinButtonConfig, userAgent) {
+ return {
+ restrict: 'EA',
+ require: '?ngModel',
+ transclude: false,
+ replace: true,
+ scope: {
+ min: '=min',
+ max: '=max',
+ step: '=step',
+ pageStep: '=pageStep',
+ spinButtonId: '@',
+ inputValue: '=ngModel',
+ inputModelKey: '@',
+ disabledFlag: "=?"
+ },
+ templateUrl: 'b2bTemplate/spinButton/spinButton.html',
+ controller: ['$scope', '$element', '$attrs', function (scope, element, attrs) {
+
+ scope.isMobile = userAgent.isMobile();
+ scope.notMobile = userAgent.notMobile();
+
+ scope.min = attrs.min ? scope.min : b2bSpinButtonConfig.min;
+ scope.max = attrs.max ? scope.max : b2bSpinButtonConfig.max;
+ scope.step = attrs.step ? scope.step : b2bSpinButtonConfig.step;
+ scope.pageStep = attrs.pageStep ? scope.pageStep : b2bSpinButtonConfig.pageStep;
+ scope.inputModelKey = attrs.inputModelKey ? scope.inputModelKey : b2bSpinButtonConfig.inputModelKey;
+ scope.disabledFlag = attrs.disabledFlag ? scope.disabledFlag : b2bSpinButtonConfig.disabledFlag;
+
+ if (scope.min < 0) {
+ scope.min = 0;
+ }
+ if (scope.max > 999) {
+ scope.max = 999;
+ }
+
+ scope.isPlusDisabled = function () {
+ return (scope.disabledFlag || scope.inputValue[scope.inputModelKey] >= scope.max);
+ };
+ scope.isMinusDisabled = function () {
+ return (scope.disabledFlag || scope.inputValue[scope.inputModelKey] <= scope.min);
+ };
+
+ scope.getValidateInputValue = function (value) {
+ if (value <= scope.min) {
+ return scope.min;
+ } else if (value >= scope.max) {
+ return scope.max;
+ } else {
+ return value;
+ }
+ };
+
+ scope.plus = function () {
+ scope.inputValue[scope.inputModelKey] = scope.getValidateInputValue(parseInt(scope.inputValue[scope.inputModelKey], 10) + scope.step);
+ };
+ scope.minus = function () {
+ scope.inputValue[scope.inputModelKey] = scope.getValidateInputValue(parseInt(scope.inputValue[scope.inputModelKey], 10) - scope.step);
+ };
+ scope.pagePlus = function () {
+ scope.inputValue[scope.inputModelKey] = scope.getValidateInputValue(parseInt(scope.inputValue[scope.inputModelKey], 10) + scope.pageStep);
+ };
+ scope.pageMinus = function () {
+ scope.inputValue[scope.inputModelKey] = scope.getValidateInputValue(parseInt(scope.inputValue[scope.inputModelKey], 10) - scope.pageStep);
+ };
+
+ }],
+ link: function (scope, elem) {
+
+ if (scope.notMobile) {
+ angular.element(elem).find('input').attr('aria-live', 'off');
+ angular.element(elem).find('input').attr('role', 'spinbutton');
+ }
+
+ elem.find('input').bind('keydown', function (e) {
+ if (e.keyCode === keymap.KEY.UP) {
+ scope.plus();
+ } else if (e.keyCode === keymap.KEY.DOWN){
+ scope.minus();
+ } else if (e.keyCode === keymap.KEY.HOME) {
+ scope.inputValue[scope.inputModelKey] = parseInt(scope.min);
+ } else if (e.keyCode === keymap.KEY.END) {
+ scope.inputValue[scope.inputModelKey] = parseInt(scope.max);
+ } else if (e.keyCode === keymap.KEY.PAGE_UP) {
+ scope.pagePlus();
+ } else if (e.keyCode === keymap.KEY.PAGE_DOWN) {
+ scope.pageMinus();
+ }
+ scope.$apply();
+ });
+
+ elem.find('input').bind('keyup', function () {
+ if (scope.inputValue[scope.inputModelKey] === null ||
+ scope.inputValue[scope.inputModelKey] === '' ||
+ scope.inputValue[scope.inputModelKey] < scope.min) {
+ scope.inputValue[scope.inputModelKey] = scope.min;
+ scope.$apply();
+ } else if (angular.isUndefined(scope.inputValue[scope.inputModelKey]) ||
+ scope.inputValue[scope.inputModelKey] > scope.max) {
+ scope.inputValue[scope.inputModelKey] = scope.max;
+ scope.$apply();
+ }
+ });
+
+ scope.focusInputSpinButton = function (evt) {
+ evt.preventDefault();
+ if (scope.notMobile) {
+ elem[0].querySelector('input').focus();
+ }
+ };
+
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Template.att:Static Route
+ *
+ * @description
+ * <file src="src/staticRouteTemplate/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/staticRouteTemplate/docs/demo.html" />
+ <file src="src/staticRouteTemplate/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.staticRouteTemplate', ['b2b.att.utilities'])
+
+/**
+ * @ngdoc directive
+ * @name Progress & usage indicators.att:statusTracker
+ *
+ * @scope
+ * @param {array} statuses - An array of status objects
+ * @description
+ * <file src="src/statusTracker/docs/readme.md" />
+ *
+ * @usage
+ *
+<div ng-controller="statusTrackerController">
+ <b2b-status-tracker statuses="statusObject"></b2b-status-tracker>
+</div>
+
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/statusTracker/docs/demo.html" />
+ <file src="src/statusTracker/docs/demo.js" />
+ </example>
+ </section>
+ */
+
+angular.module('b2b.att.statusTracker', ['b2b.att.utilities'])
+.constant('b2bStatusTrackerConfig', {
+ 'maxViewItems': 3
+})
+.directive('b2bStatusTracker', ['b2bStatusTrackerConfig', function(b2bStatusTrackerConfig) {
+ return {
+ restrict: 'EA',
+ transclude: false,
+ replace: true,
+ scope:{
+ statuses: '='
+ },
+ templateUrl: function(scope) {
+ return 'b2bTemplate/statusTracker/statusTracker.html';
+ },
+ link: function(scope, element, attr) {
+ scope.currentViewIndex = 0;
+ scope.b2bStatusTrackerConfig = b2bStatusTrackerConfig;
+
+ scope.nextStatus = function() {
+ if (scope.currentViewIndex+1 <= scope.statuses.length) {
+ scope.currentViewIndex++;
+ }
+ };
+ scope.previousStatus = function() {
+ if (scope.currentViewIndex-1 >= 0) {
+ scope.currentViewIndex--;
+ }
+ };
+ scope.isInViewport = function(index) {
+ return (index < scope.currentViewIndex+3 && index >= scope.currentViewIndex); // && index > scope.currentViewIndex-2
+ };
+ scope.currentStatus = function(index) {
+ if(index != undefined){
+ if(!scope.statuses[index].complete) {
+ if(index > 0 && scope.statuses[index-1].complete) {
+ return true;
+ } else if(index == 0 && !scope.statuses[index].complete){
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ };
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Progress & usage indicators.att:stepTracker
+ *
+ * @scope
+ * @param {array} stepsItemsObject - An array of step objects
+ * @param {Integer} currenIindex - This indicates the current running step
+ * @param {Integer} viewportIndex - This is optional. This can used to start the view port rather than 1 item.
+ * @description
+ * <file src="src/stepTracker/docs/readme.md" />
+ *
+ * @usage
+ *
+ * <b2b-step-tracker steps-items-object="stepsObject" current-index="currentStepIndex" step-indicator-heading="stepHeading"></b2b-step-tracker>
+ *
+
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/stepTracker/docs/demo.html" />
+ <file src="src/stepTracker/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.stepTracker', ['b2b.att.utilities'])
+ .constant('b2bStepTrackerConfig', {
+ 'maxViewItems': 5
+ })
+ .directive('b2bStepTracker', ['b2bStepTrackerConfig', function(b2bStepTrackerConfig) {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ scope:{
+ stepsItemsObject:"=",
+ currentIndex:"=",
+ viewportIndex:"=?"
+ },
+ templateUrl: 'b2bTemplate/stepTracker/stepTracker.html',
+ link: function(scope, ele, attr) {
+ if (angular.isDefined(scope.viewportIndex)) {
+ scope.currentViewIndex = scope.viewportIndex - 1;
+ }else{
+ scope.currentViewIndex = 0;
+ }
+
+ scope.b2bStepTrackerConfig = b2bStepTrackerConfig;
+ scope.nextStatus = function() {
+ if (scope.currentViewIndex+1 <= scope.stepsItemsObject.length) {
+ scope.currentViewIndex++;
+ }
+ };
+ scope.previousStatus = function() {
+ if (scope.currentViewIndex-1 >= 0) {
+ scope.currentViewIndex--;
+ }
+ };
+ scope.isInViewport = function(index) {
+ return (index < scope.currentViewIndex+b2bStepTrackerConfig.maxViewItems && index >= scope.currentViewIndex);
+ };
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Buttons, links & UI controls.att:switches
+ *
+ * @description
+ * <file src="src/switches/docs/readme.md" />
+ *
+ * @usage
+ *
+ * <!-- On / Off Toggle switch -->
+ * <label for="switch1" class="controlled-text-wrap"> This is ON
+ * <input type="checkbox" role="checkbox" b2b-switches id="switch1" ng-model="switch1.value">
+ * </label>
+ *
+ * <!-- On / Off Toggle switch and DISABLED -->
+ * <label for="switch2" class="controlled-text-wrap"> This is ON (disabled)
+ * <input type="checkbox" role="checkbox" b2b-switches id="switch2" ng-model="switch1.value" ng-disabled="true" >
+ * </label>
+ *
+ *
+ * @example
+ * <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/switches/docs/demo.js" />
+ <file src="src/switches/docs/demo.html" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.switches', ['b2b.att.utilities'])
+ .directive('b2bSwitches', ['$compile', '$templateCache', 'keymap', 'events', function ($compile, $templateCache, keymap, events) {
+ return {
+ restrict: 'EA',
+ require: ['ngModel'],
+ link: function (scope, element, attrs, ctrl) {
+ var ngModelController = ctrl[0];
+
+ element.parent().bind("keydown", function (e) {
+ if (!attrs.disabled && (e.keyCode === keymap.KEY.ENTER || e.keyCode === keymap.KEY.SPACE)) {
+ events.preventDefault(e);
+ ngModelController.$setViewValue(!ngModelController.$viewValue);
+ element.prop("checked", ngModelController.$viewValue);
+ }
+ });
+
+ element.wrap('<div class="btn-switch">');
+ //element.attr("tabindex", -1);
+ if (navigator.userAgent.match(/iphone/i)){
+ element.attr("aria-live", "polite");
+ }
+ else {
+ element.removeAttr('aria-live');
+ }
+
+ var templateSwitch = angular.element($templateCache.get("b2bTemplate/switches/switches.html"));
+ if (angular.isDefined(attrs.typeSpanish)) {
+ templateSwitch = angular.element($templateCache.get("b2bTemplate/switches/switches-spanish.html"));
+ }
+
+ templateSwitch = $compile(templateSwitch)(scope);
+ element.parent().append(templateSwitch);
+
+ element.bind("focus", function (e) {
+ element.parent().addClass('focused');
+ });
+
+ element.bind("blur", function (e) {
+ element.parent().removeClass('focused');
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:tableMessages
+ *
+ * @description
+ * <file src="src/tableMessages/docs/readme.md" />
+ *
+ * @usage
+ <!-- no matching results -->
+ <b2b-table-message msg-type="'noMatchingResults'">
+ <p>No Matching Results</p>
+ </b2b-table-message>
+
+ <!-- info could not load -->
+ <b2b-table-message msg-type="'infoCouldNotLoad'" on-refresh-click="refreshClicked()">
+ </b2b-table-message>
+
+ <!-- magnify search -->
+ <b2b-table-message msg-type="'magnifySearch'">
+ </b2b-table-message>
+
+ <!-- loading data -->
+ <b2b-table-message msg-type="'loadingTable'">
+ <!-- custom html -->
+ <p>The data is currently loading...</p>
+ </b2b-table-message>
+
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/tableMessages/docs/demo.html" />
+ <file src="src/tableMessages/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.tableMessages', [])
+ .directive('b2bTableMessage', [function() {
+ return {
+ restrict: 'AE',
+ replace: true,
+ transclude: true,
+ scope: {
+ msgType: '=',
+ onRefreshClick: '&'
+ },
+ templateUrl: 'b2bTemplate/tableMessages/tableMessage.html',
+ link: function(scope) {
+ scope.refreshAction = function(evt) {
+ scope.onRefreshClick(evt);
+ };
+ }
+ };
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name Tabs, tables & accordions.att:tableScrollbar
+ *
+ * @description
+ * <file src="src/tableScrollbar/docs/readme.md" />
+ *
+ * @usage
+ *
+<b2b-table-scrollbar>
+ <table>
+ <thead type="header">
+ <tr>
+ <th role="columnheader" scope="col" key="Id" id="col1">Id</th>
+ .....
+ </tr>
+ </thead>
+ <tbody type="body">
+ <tr>
+ <td id="rowheader0" headers="col1">1002</td>
+ .....
+ </tr>
+ </tbody>
+ </table>
+</b2b-table-scrollbar>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/tableScrollbar/docs/demo.html" />
+ <file src="src/tableScrollbar/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.tableScrollbar', [])
+ .directive('b2bTableScrollbar', ['$timeout', function ($timeout) {
+ return {
+ restrict: 'E',
+ scope: true,
+ transclude: true,
+ templateUrl: 'b2bTemplate/tableScrollbar/tableScrollbar.html',
+ link: function (scope, element, attrs, ctrl) {
+ var firstThWidth, firstTdWidth, firstColumnWidth, firstColumnHeight, trHeight = 0;
+ var pxToScroll = '';
+ var tableElement = element.find('table');
+ var thElements = element.find('th');
+ var tdElements = element.find('td');
+ var innerContainer = angular.element(element[0].querySelector('.b2b-table-inner-container'));
+ var outerContainer = angular.element(element[0].querySelector('.b2b-table-scrollbar'));
+
+ scope.disableLeft = true;
+ scope.disableRight = false;
+
+ if (angular.isDefined(thElements[0])) {
+ firstThWidth = thElements[0].offsetWidth;
+ }
+ if (angular.isDefined(tdElements[0])) {
+ firstTdWidth = tdElements[0].offsetWidth;
+ }
+ firstColumnWidth = (firstThWidth > firstTdWidth) ? firstThWidth : firstTdWidth;
+
+ innerContainer.css({
+ 'padding-left': (firstColumnWidth + 2) + 'px'
+ });
+
+ angular.forEach(element.find('tr'), function (eachTr, index) {
+ trObject = angular.element(eachTr);
+ firstColumn = angular.element(trObject.children()[0]);
+
+ angular.element(firstColumn).css({
+ 'margin-left': -(firstColumnWidth + 2) + 'px',
+ 'width': (firstColumnWidth + 2) + 'px',
+ 'position': 'absolute'
+ });
+
+ trHeight = trObject[0].offsetHeight;
+ firstColumnHeight = firstColumn[0].offsetHeight;
+ if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
+ firstColumnHeight += 1;
+ }
+
+ if (trHeight !== firstColumnHeight - 1) {
+ if (trHeight > firstColumnHeight) {
+ if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
+ trHeight -= 1;
+ }
+ angular.element(firstColumn).css({
+ 'height': (trHeight + 1) + 'px'
+ });
+ } else {
+ angular.element(trObject).css({
+ 'height': (firstColumnHeight - 1) + 'px'
+ });
+ }
+ }
+
+ });
+
+ pxToScroll = outerContainer[0].offsetWidth - firstColumnWidth;
+
+ scope.scrollLeft = function () {
+ innerContainer[0].scrollLeft = innerContainer[0].scrollLeft + 20 - pxToScroll;
+ };
+
+ scope.scrollRight = function () {
+ innerContainer[0].scrollLeft = innerContainer[0].scrollLeft + pxToScroll - 20;
+ };
+
+ scope.checkScrollArrows = function () {
+ if (innerContainer[0].scrollLeft == 0) {
+ scope.disableLeft = true;
+ } else {
+ scope.disableLeft = false;
+ }
+
+ if (((innerContainer[0].offsetWidth - firstColumnWidth) + innerContainer[0].scrollLeft) >= tableElement[0].offsetWidth) {
+ scope.disableRight = true;
+ } else {
+ scope.disableRight = false;
+ }
+ };
+
+ innerContainer.bind('scroll', function () {
+ $timeout(function () {
+ scope.checkScrollArrows();
+ }, 1);
+ });
+
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Tabs, tables & accordions.att:tables
+ *
+ * @description
+ * <file src="src/tables/docs/readme.md" />
+ *
+ * @usage
+ *
+ Table
+ <table b2b-table table-data="tableData" search-string="searchString">
+ <thead b2b-table-row type="header">
+ <tr>
+ <th b2b-table-header key="requestId" default-sort="a" id="col1">Header 1</th>
+ <th b2b-table-header key="requestType" sortable="false" id="col2">Header 2</th>
+ </tr>
+ </thead>
+ <tbody b2b-table-row type="body" row-repeat="rowData in tableData">
+ <tr>
+ <td b2b-table-body id="rowheader{{$index}}" headers="col1" ng-bind="rowData['requestId']"> </td>
+ <td b2b-table-body ng-bind="rowData['requestType']"></td>
+ </tr>
+ </tbody>
+ </table>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/tables/docs/demo.html" />
+ <file src="src/tables/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.tables', ['b2b.att.utilities'])
+ .constant('b2bTableConfig', {
+ defaultSortPattern: false, // true for descending & false for ascending
+ highlightSearchStringClass: 'tablesorter-search-highlight',
+ zebraStripCutOff: 6, // > zebraStripCutOff
+ tableBreakpoints: [ // breakpoints are >= min and < max
+ {
+ min: 0,
+ max: 480,
+ columns: 2
+ },
+ {
+ min: 480,
+ max: 768,
+ columns: 3
+ },
+ {
+ min: 768,
+ max: 1025,
+ columns: 5
+ },
+ {
+ min: 1025,
+ max: 1920,
+ columns: 7
+ }
+ ]
+ })
+ .directive('b2bTable', ['$filter', '$window', 'b2bTableConfig', '$timeout', function ($filter, $window, b2bTableConfig, $timeout) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ transclude: true,
+ scope: {
+ tableData: "=",
+ viewPerPage: "=",
+ currentPage: "=",
+ totalPage: "=",
+ searchCategory: "=",
+ searchString: "=",
+ nextSort: '='
+ },
+ require: 'b2bTable',
+ templateUrl: 'b2bTemplate/tables/b2bTable.html',
+ controller: ['$scope', '$attrs', function ($scope, $attrs) {
+ this.headers = [];
+ this.currentSortIndex = null;
+ this.responsive = $scope.responsive = $attrs.responsive;
+ this.maxTableColumns = -1;
+ this.totalTableColums = 0;
+ this.active = $scope.active = false;
+ this.responsiveRowScopes = [];
+ this.hideColumnPriority = [];
+ this.hiddenColumn = [];
+ this.setIndex = function (headerScope, priority) {
+ this.headers.push(headerScope);
+ if (this.responsive) {
+ this.totalTableColums++;
+ if (!isNaN(priority)) {
+ this.hideColumnPriority[priority] = this.totalTableColums - 1;
+ } else {
+ this.hideColumnPriority[this.totalTableColums - 1] = this.totalTableColums - 1;
+ }
+ }
+ return this.totalTableColums - 1;
+ };
+ this.getIndex = function (headerName) {
+ for (var i = 0; i < this.headers.length; i++) {
+ if (this.headers[i].headerName === headerName) {
+ return this.headers[i].index;
+ }
+ }
+ return null;
+ };
+ this.setResponsiveRow = function (responsiveRowScope) {
+ this.responsiveRowScopes.push(responsiveRowScope);
+ }
+ $scope.nextSort = '';
+ this.sortData = function (columnIndex, reverse, externalSort) {
+ if ($scope.$parent && $scope.$parent !== undefined) {
+ $scope.$parent.columnIndex = columnIndex;
+ $scope.$parent.reverse = reverse;
+ }
+ this.currentSortIndex = columnIndex;
+ if (externalSort === true) {
+ if (!reverse) {
+ $scope.nextSort = 'd'
+ } else {
+ $scope.nextSort = 'a'
+ }
+ }
+ $scope.currentPage = 1;
+ this.resetSortPattern();
+ };
+ this.getSearchString = function () {
+ return $scope.searchString;
+ };
+ this.resetSortPattern = function () {
+ for (var i = 0; i < this.headers.length; i++) {
+ var currentScope = this.headers[i];
+ if (currentScope.index !== this.currentSortIndex) {
+ currentScope.resetSortPattern();
+ }
+ }
+ };
+
+ $scope.$watch('nextSort', function (val) {
+ if ($scope.$parent && $scope.$parent !== undefined) {
+ $scope.$parent.nextSort = val;
+ }
+
+ });
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ scope.searchCriteria = {};
+ scope.tableBreakpoints = attr.tableConfig ? scope.$parent.$eval(attr.tableConfig) : angular.copy(b2bTableConfig.tableBreakpoints);
+ scope.$watchCollection('tableData', function (value) {
+ if (value && !isNaN(value.length)) {
+ scope.totalRows = value.length;
+ }
+ });
+ scope.$watch('currentPage', function (val) {
+ if (scope.$parent && scope.$parent !== undefined) {
+ scope.$parent.currentPage = val;
+ }
+
+ });
+ scope.$watch('viewPerPage', function (val) {
+ if (scope.$parent && scope.$parent !== undefined) {
+ scope.$parent.viewPerPage = val;
+ }
+ });
+ scope.$watch('totalRows', function (val) {
+ if (scope.$parent && scope.$parent !== undefined) {
+ if (val > b2bTableConfig.zebraStripCutOff) {
+ scope.$parent.zebraStripFlag = true;
+ } else {
+ scope.$parent.zebraStripFlag = false;
+ }
+ }
+ });
+ scope.$watch(function () {
+ return scope.totalRows / scope.viewPerPage;
+ }, function (value) {
+ if (!isNaN(value)) {
+ scope.totalPage = Math.ceil(value);
+ scope.currentPage = 1;
+ }
+ });
+ var searchValCheck = function (val) {
+ if (angular.isDefined(val) && val !== null && val !== "") {
+ return true;
+ }
+ };
+ var setSearchCriteria = function (v1, v2) {
+ if (searchValCheck(v1) && searchValCheck(v2)) {
+ var index = ctrl.getIndex(v2);
+ scope.searchCriteria = {};
+ if (index !== null) {
+ scope.searchCriteria[index] = v1;
+ }
+ } else if (searchValCheck(v1) && (!angular.isDefined(v2) || v2 === null || v2 === "")) {
+ scope.searchCriteria = {
+ $: v1
+ };
+ } else {
+ scope.searchCriteria = {};
+ }
+ };
+ scope.$watch('searchCategory', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ setSearchCriteria(scope.searchString, newVal);
+ }
+ });
+ scope.$watch('searchString', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ setSearchCriteria(newVal, scope.searchCategory);
+ }
+ });
+ scope.$watchCollection('searchCriteria', function (val) {
+ if (scope.$parent && scope.$parent !== undefined) {
+ scope.$parent.searchCriteria = val;
+ }
+ scope.totalRows = scope.tableData && ($filter('filter')(scope.tableData, val, false)).length || 0;
+ scope.currentPage = 1;
+ });
+ var window = angular.element($window);
+ var findMaxTableColumns = function () {
+ var windowWidth;
+ windowWidth = $window.innerWidth;
+ ctrl.maxTableColumns = -1;
+ for (var i in scope.tableBreakpoints) {
+ if (windowWidth >= scope.tableBreakpoints[i].min && windowWidth < scope.tableBreakpoints[i].max) {
+ ctrl.maxTableColumns = scope.tableBreakpoints[i].columns;
+ break;
+ }
+ }
+ if (ctrl.maxTableColumns > -1 && ctrl.totalTableColums > ctrl.maxTableColumns) {
+ ctrl.active = true;
+ } else {
+ ctrl.active = false;
+ }
+ for (var i in ctrl.responsiveRowScopes) {
+ ctrl.responsiveRowScopes[i].setActive(ctrl.active);
+ }
+ };
+ var findHiddenColumn = function () {
+ var columnDiffenence = ctrl.maxTableColumns > -1 ? ctrl.totalTableColums - ctrl.maxTableColumns : 0;
+ ctrl.hiddenColumn = [];
+ if (columnDiffenence > 0) {
+ var tempHideColumnPriority = angular.copy(ctrl.hideColumnPriority);
+ for (var i = 0; i < columnDiffenence; i++) {
+ ctrl.hiddenColumn.push(tempHideColumnPriority.pop());
+ }
+ }
+ };
+ var resizeListener = function () {
+ findMaxTableColumns();
+ findHiddenColumn();
+ };
+ if (ctrl.responsive) {
+ window.bind('resize', function () {
+ resizeListener();
+ scope.$apply();
+ });
+ $timeout(function () {
+ resizeListener();
+ }, 100);
+ }
+ }
+ };
+ }])
+ .directive('b2bTableRow', [function () {
+ return {
+ restrict: 'EA',
+ compile: function (elem, attr) {
+ if (attr.type === 'header') {
+ angular.noop();
+ } else if (attr.type === 'body') {
+ var html = elem.children();
+ if (attr.rowRepeat) {
+ html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false "));
+ }
+ html.attr('ng-class', "{'odd': $odd && zebraStripFlag}");
+ html.attr('class', 'data-row');
+ html.attr('b2b-responsive-row', '{{$index}}');
+ elem.append(html);
+ }
+ }
+ };
+ }])
+ .directive('b2bTableHeader', ['b2bTableConfig', function (b2bTableConfig) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ transclude: true,
+ scope: {
+ sortable: '@',
+ defaultSort: '@',
+ index: '@key'
+ },
+ require: '^b2bTable',
+ templateUrl: function (elem, attr) {
+ if (attr.sortable === 'false') {
+ return 'b2bTemplate/tables/b2bTableHeaderUnsortable.html';
+ } else {
+ return 'b2bTemplate/tables/b2bTableHeaderSortable.html';
+ }
+ },
+ link: function (scope, elem, attr, ctrl) {
+ var reverse = b2bTableConfig.defaultSortPattern;
+ scope.headerName = elem.text();
+ scope.headerId = elem.attr('id');
+ scope.sortPattern = null;
+ var priority = parseInt(attr.priority, 10);
+ scope.columnIndex = ctrl.setIndex(scope, priority);
+
+ scope.isHidden = function () {
+ return (ctrl.hiddenColumn.indexOf(scope.columnIndex) > -1);
+ };
+
+ scope.$watch(function () {
+ return elem.text();
+ }, function (value) {
+ scope.headerName = value;
+ });
+ scope.sort = function (sortType) {
+ if (typeof sortType === 'boolean') {
+ reverse = sortType;
+ }
+ ctrl.sortData(scope.index, reverse, false);
+ scope.sortPattern = reverse ? 'descending' : 'ascending';
+ reverse = !reverse;
+ };
+ scope.$watch(function () {
+ return ctrl.currentSortIndex;
+ }, function (value) {
+ if (value !== scope.index) {
+ scope.sortPattern = null;
+ }
+ });
+
+ if (scope.sortable === undefined || scope.sortable === 'true' || scope.sortable === true) {
+ scope.sortable = 'true';
+ } else if (scope.sortable === false || scope.sortable === 'false') {
+ scope.sortable = 'false';
+ }
+
+ if (scope.sortable !== 'false') {
+ if (scope.defaultSort === 'A' || scope.defaultSort === 'a') {
+ scope.sort(false);
+ } else if (scope.defaultSort === 'D' || scope.defaultSort === 'd') {
+ scope.sort(true);
+ }
+ }
+ scope.resetSortPattern = function () {
+ reverse = b2bTableConfig.defaultSortPattern;
+ };
+ }
+ };
+ }])
+ .directive('b2bResponsiveRow', ['$templateCache', '$timeout', '$compile', function ($templateCache, $timeout, $compile) {
+ return {
+ restrict: 'EA',
+ require: '^b2bTable',
+ controller: ['$scope', function ($scope) {
+ this.rowValues = $scope.rowValues = [];
+ this.setRowValues = function (rowValue) {
+ this.rowValues.push(rowValue);
+ };
+ var columnIndexCounter = -1;
+ this.getIndex = function () {
+ columnIndexCounter++;
+ return columnIndexCounter;
+ };
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ if (ctrl.responsive) {
+ scope.rowIndex = attr.b2bResponsiveRow;
+ scope.active = false;
+ scope.expandFlag = false;
+ scope.headerValues = ctrl.headers;
+ ctrl.setResponsiveRow(scope);
+ var firstTd = elem.find('td').eq(0);
+ scope.setActive = function (activeFlag) {
+ scope.active = activeFlag;
+ if (scope.active) {
+ elem.addClass('has-button');
+ firstTd.attr('role', 'rowheader');
+ firstTd.parent().attr('role', 'row');
+ } else {
+ elem.removeClass('has-button');
+ firstTd.removeAttr('role');
+ firstTd.parent().removeAttr('role');
+ }
+ };
+ scope.toggleExpandFlag = function (expandFlag) {
+ if (angular.isDefined(expandFlag)) {
+ scope.expandFlag = expandFlag;
+ } else {
+ scope.expandFlag = !scope.expandFlag;
+ }
+ if (scope.expandFlag) {
+ elem.addClass('opened');
+ } else {
+ elem.removeClass('opened');
+ }
+ };
+
+ firstTd.attr('scope', 'row');
+ firstTd.addClass('col-1');
+ scope.$on('$destroy', function () {
+ elem.next().remove();
+ });
+ $timeout(function () {
+ scope.firstTdId = firstTd.attr('id');
+ var firstTdContent = firstTd.html();
+ var toggleButtonTemplate = '<span ng-show="!active">' + firstTdContent + '</span><button type="button" aria-describedby="sup-actNum{{$id}}" aria-expanded="{{expandFlag}}" ng-show="active" ng-click="toggleExpandFlag()"><i ng-class="{\'icon-primary-accordion-plus\': !expandFlag, \'icon-primary-accordion-minus\': expandFlag}" aria-hidden="true"></i>' + firstTdContent + '</button><span id="sup-actNum{{$id}}" style="display:none">{{expandFlag && "Hide row below." || "Show row below."}}</span>';
+ toggleButtonTemplate = $compile(toggleButtonTemplate)(scope);
+ firstTd.html('');
+ firstTd.prepend(toggleButtonTemplate);
+
+ var template = $templateCache.get('b2bTemplate/tables/b2bResponsiveRow.html');
+ template = $compile(template)(scope);
+ elem.after(template);
+ }, 100);
+ }
+ }
+ };
+ }])
+ .directive('b2bResponsiveList', ['$templateCache', '$timeout', '$compile', function ($templateCache, $timeout, $compile) {
+ return {
+ restrict: 'EA',
+ require: '^b2bTable',
+ link: function (scope, elem, attr, ctrl) {
+ scope.columnIndex = parseInt(attr.b2bResponsiveList, 10);
+ scope.isVisible = function () {
+ return (ctrl.hiddenColumn.indexOf(scope.columnIndex) > -1);
+ };
+ }
+ };
+ }])
+ .directive('b2bTableBody', ['$filter', '$timeout', 'b2bTableConfig', function ($filter, $timeout, b2bTableConfig) {
+ return {
+ restrict: 'EA',
+ require: ['^b2bTable', '?^b2bResponsiveRow'],
+ scope: true,
+ replace: true,
+ transclude: true,
+ templateUrl: 'b2bTemplate/tables/b2bTableBody.html',
+ link: function (scope, elem, attr, ctrl) {
+ var b2bTableCtrl = ctrl[0];
+ var b2bResponsiveRowCtrl = ctrl[1];
+ var highlightSearchStringClass = b2bTableConfig.highlightSearchStringClass;
+ var searchString = "";
+ var wrapElement = function (elem) {
+ var text = elem.text();
+ elem.html($filter('b2bHighlight')(text, searchString, highlightSearchStringClass));
+ };
+ var traverse = function (elem) {
+ var innerHtml = elem.children();
+ if (innerHtml.length > 0) {
+ for (var i = 0; i < innerHtml.length; i++) {
+ traverse(innerHtml.eq(i));
+ }
+ } else {
+ wrapElement(elem);
+ return;
+ }
+ };
+ var clearWrap = function (elem) {
+ var elems = elem.find('*');
+ for (var i = 0; i < elems.length; i++) {
+ if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
+ var text = elems.eq(i).text();
+ elems.eq(i).replaceWith(text);
+ }
+ }
+ };
+ if (b2bResponsiveRowCtrl) {
+ scope.columnIndex = b2bResponsiveRowCtrl.getIndex();
+ scope.isHidden = function () {
+ return (b2bTableCtrl.hiddenColumn.indexOf(scope.columnIndex) > -1);
+ };
+ }
+ $timeout(function () {
+ var actualHtml = elem.children();
+ scope.$watch(function () {
+ return b2bTableCtrl.getSearchString();
+ }, function (val) {
+ searchString = val;
+ clearWrap(elem);
+ if (actualHtml.length > 0) {
+ traverse(elem);
+ } else {
+ wrapElement(elem);
+ }
+ });
+ if (b2bResponsiveRowCtrl) {
+ b2bResponsiveRowCtrl.setRowValues(elem.html());
+ }
+ }, 50);
+ }
+ };
+ }])
+ .directive('b2bTableSort', ['b2bTableConfig','$timeout', function (b2bTableConfig,$timeout) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ require: '^b2bTable',
+ link: function (scope, elem, attr, ctrl) {
+ var initialSort = '',
+ nextSort = '',
+ tempsort = '';
+ initialSort = attr.initialSort;
+
+ scope.sortTable = function (msg) {
+ $timeout(function(){
+ if (nextSort.length > 0) {
+
+ if (nextSort === 'd' || nextSort === 'D') {
+ tempsort = nextSort
+ ctrl.sortData(msg, true, true);
+ nextSort = 'a';
+ $timeout(function(){
+ if(!angular.isUndefined(elem[0].querySelector('.sortButton')) || elem[0].querySelector('.sortButton') !== null ){
+ angular.element(elem[0].querySelector('.sortButton'))[0].focus();
+ }
+ },100);
+
+ } else {
+ tempsort = nextSort
+ ctrl.sortData(msg, false, true);
+ nextSort = 'd';
+ $timeout(function(){
+ if(!angular.isUndefined(elem[0].querySelector('.sortButton')) || elem[0].querySelector('.sortButton') !== null ){
+ angular.element(elem[0].querySelector('.sortButton'))[0].focus();
+ }
+ },100);
+ }
+ } else if (initialSort.length > 0) {
+
+ if (initialSort === 'd' || initialSort === 'D') {
+ tempsort = nextSort
+ ctrl.sortData(msg, true, true);
+ nextSort = 'a';
+ $timeout(function(){
+ if(!angular.isUndefined(elem[0].querySelector('.sortButton')) || elem[0].querySelector('.sortButton') !== null ){
+ angular.element(elem[0].querySelector('.sortButton'))[0].focus();
+ }
+ },100);
+
+ } else {
+ tempsort = nextSort
+ ctrl.sortData(msg, false, true);
+ nextSort = 'd';
+ $timeout(function(){
+ if(!angular.isUndefined(elem[0].querySelector('.sortButton')) || elem[0].querySelector('.sortButton') !== null ){
+ angular.element(elem[0].querySelector('.sortButton'))[0].focus();
+ }
+ },100);
+
+
+ }
+ }
+ },10)
+
+ };
+
+ scope.sortDropdown = function(msg) {
+
+ if(tempsort==='') {
+
+ tempsort='a'
+ }
+ if(tempsort === 'd' || tempsort === 'D' ) {
+ ctrl.sortData(msg, true, false);
+ } else {
+ ctrl.sortData(msg, false, false);
+ }
+
+ };
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Tabs, tables & accordions.att:tabs
+ *
+ * @description
+ * <file src="src/tabs/docs/readme.md" />
+ *
+ * @usage
+ * <b2b-tabset tab-id-selected="activeTabsId">
+ <b2b-tab ng-repeat="tab in gTabs" tab-item="tab"
+ id="{{tab.uniqueId}}" aria-controls="{{tab.tabPanelId}}"
+ ng-disabled="tab.disabled">
+ {{tab.title}}
+ </b2b-tab>
+ </b2b-tabset>
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/tabs/docs/demo.html" />
+ <file src="src/tabs/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+
+angular.module('b2b.att.tabs', ['b2b.att.utilities'])
+ .directive('b2bTabset', function () {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ scope: {
+ tabIdSelected: '='
+ },
+ templateUrl: 'b2bTemplate/tabs/b2bTabset.html',
+ controller: ['$scope', function ($scope) {
+
+ this.setTabIdSelected = function (tab) {
+ $scope.tabIdSelected = tab.id;
+ };
+
+ this.getTabIdSelected = function () {
+ return $scope.tabIdSelected;
+ };
+ }]
+ };
+ })
+ .directive('b2bTab', ['keymap', function (keymap) {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ require: '^b2bTabset',
+ scope: {
+ tabItem: "="
+ },
+ templateUrl: 'b2bTemplate/tabs/b2bTab.html',
+ controller: [function(){}],
+ link: function (scope, element, attr, b2bTabsetCtrl) {
+
+ if (scope.tabItem && !scope.tabItem.disabled) {
+ scope.tabItem.disabled = false;
+ }
+
+ scope.isTabActive = function () {
+ return (scope.tabItem.id === b2bTabsetCtrl.getTabIdSelected());
+ };
+
+ scope.clickTab = function () {
+ if (attr.disabled) {
+ return;
+ }
+ b2bTabsetCtrl.setTabIdSelected(scope.tabItem);
+ };
+
+ scope.nextKey = function () {
+ var el = angular.element(element[0])[0];
+ var elementToFocus = null;
+ while (el && el.nextElementSibling) {
+ el = el.nextElementSibling;
+ if (!el.querySelector('a').disabled) {
+ elementToFocus = el.querySelector('a');
+ break;
+ }
+ }
+
+ if (!elementToFocus) {
+ var childTabs = element.parent().children();
+ for (var i = 0; i < childTabs.length; i++) {
+ if (!childTabs[i].querySelector('a').disabled) {
+ elementToFocus = childTabs[i].querySelector('a');
+ break;
+ }
+ }
+ }
+
+ if (elementToFocus) {
+ elementToFocus.focus();
+ }
+ };
+
+ scope.previousKey = function () {
+ var el = angular.element(element[0])[0];
+ var elementToFocus = null;
+
+ while (el && el.previousElementSibling) {
+ el = el.previousElementSibling;
+ if (!el.querySelector('a').disabled) {
+ elementToFocus = el.querySelector('a');
+ break;
+ }
+ }
+
+ if (!elementToFocus) {
+ var childTabs = element.parent().children();
+ for (var i = childTabs.length - 1; i > 0; i--) {
+ if (!childTabs[i].querySelector('a').disabled) {
+ elementToFocus = childTabs[i].querySelector('a');
+ break;
+ }
+ }
+ }
+
+ if (elementToFocus) {
+ elementToFocus.focus();
+ }
+ };
+
+ angular.element(element[0].querySelector('a')).bind('keydown', function (evt) {
+
+ if (!(evt.keyCode)) {
+ evt.keyCode = evt.which;
+ }
+
+ switch (evt.keyCode) {
+ case keymap.KEY.RIGHT:
+ evt.preventDefault();
+ scope.nextKey();
+ break;
+
+ case keymap.KEY.LEFT:
+ evt.preventDefault();
+ scope.previousKey();
+ break;
+
+ default:;
+ }
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Messages, modals & alerts.att:tagBadges
+ *
+ * @description
+ * <file src="src/tagBadges/docs/readme.md" />
+ *
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/tagBadges/docs/demo.html" />
+ <file src="src/tagBadges/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.tagBadges', ['b2b.att.utilities'])
+ .directive('b2bTagBadge',['$timeout',function($timeout){
+ return{
+ restrict: 'EA',
+ link: function(scope,elem,attr,ctrl){
+ elem.addClass('b2b-tags');
+ if(angular.element(elem[0].querySelector('.icon-primary-close')).length>0) {
+ var item = angular.element(elem[0].querySelector('.icon-primary-close'));
+ item.bind('click',function(){
+ elem.css({'height':'0','width':'0','padding':'0','border':'0'});
+ elem.attr('tabindex','0');
+ elem[0].focus();
+ item.parent().remove();
+ elem[0].bind('blur',function(){
+ elem[0].remove();
+ });
+ });
+ }
+
+
+
+
+ }
+ };
+}]);
+/**
+ * @ngdoc directive
+ * @name Forms.att:textArea
+ *
+ * @description
+ * <file src="src/textArea/docs/readme.md" />
+ *
+ * @usage
+ * <textarea b2b-reset b2b-reset-textarea ng-model="textAreaModel" ng-disabled="disabled" ng-trim="false" placeholder="{{placeholderText}}" rows="{{textAreaRows}}" maxlength="{{textAreaMaxlength}}" role="textarea"></textarea>
+ *
+ * @example
+ <section id="code">
+ <b>HTML + AngularJS</b>
+ <example module="b2b.att">
+ <file src="src/textArea/docs/demo.html" />
+ <file src="src/textArea/docs/demo.js" />
+ </example>
+ </section>
+ */
+angular.module('b2b.att.textArea', ['b2b.att.utilities'])
+
+.directive('b2bResetTextarea', [ function () {
+ return {
+ restrict: 'A',
+ require: 'b2bReset',
+ link: function (scope, element, attrs, ctrl) {
+
+ var resetButton = ctrl.getResetButton();
+
+ var computeScrollbarAndAddClass = function () {
+ if (element.prop('scrollHeight') > element[0].clientHeight) {
+ element.addClass('hasScrollbar');
+ } else {
+ element.removeClass('hasScrollbar');
+ }
+ };
+
+ computeScrollbarAndAddClass();
+
+ element.on('focus keyup', function(){
+ computeScrollbarAndAddClass();
+ });
+ }
+ };
+}]);
+
+/**
+ * @ngdoc directive
+ * @name Forms.att:tooltipsForForms
+ *
+ * @description
+ * <file src="src/tooltipsForForms/docs/readme.md" />
+ *
+ * @example
+ <example module="b2b.att">
+ <file src="src/tooltipsForForms/docs/demo.html" />
+ <file src="src/tooltipsForForms/docs/demo.js" />
+ </example>
+ */
+angular.module('b2b.att.tooltipsForForms', ['b2b.att.utilities'])
+ .directive('b2bTooltip', ['$document', '$window', '$isElement', function ($document, $window, $isElement) {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr, ctrl) {
+ var icon = elem[0].querySelector('a.tooltip-element');
+ var btnIcon = elem[0].querySelector('.btn.tooltip-element');
+ var tooltipText = elem[0].querySelector('.helpertext');
+ var tooltipWrapper = elem[0].querySelector('.tooltip-size-control');
+ if (elem.hasClass('tooltip-onfocus')) {
+ var inputElm = angular.element(elem[0].querySelector("input"));
+ var textAreaElm = angular.element(elem[0].querySelector("textarea"));
+ }
+ angular.element(icon).attr({'aria-expanded': false});
+ angular.element(btnIcon).attr({'aria-expanded': false});
+ var calcTooltip = function () {
+ if (!elem.hasClass('tooltip active')) {
+ if (elem.hasClass('tooltip-onfocus')) {
+ angular.element(elem[0].querySelector("input")).triggerHandler('focusout');
+ }
+ if (elem.hasClass('tooltip-onclick')) {
+ return false;
+ }
+ angular.element(icon).removeClass('active');
+ angular.element(icon).attr({'aria-expanded': true});
+ angular.element(icon).attr({'aria-describedby': angular.element(tooltipText).attr('id')});
+ angular.element(tooltipText).attr({'aria-hidden': false});
+ elem.addClass('active');
+
+ var tooltipIconPos = angular.element(icon).prop('offsetLeft'),
+ tooltipPosition = angular.element(tooltipText).prop('offsetWidth') / 2,
+ tipOffset = (tooltipIconPos - 30) - tooltipPosition,
+ maxRightPos = (($window.innerWidth - 72) - (tooltipPosition * 2)) - 14.5;
+
+ if ($window.innerWidth >= '768') {
+ if (tipOffset < 0) {// if icon on far left side of page
+ tipOffset = 15;
+ }
+ else if (tooltipIconPos > maxRightPos) {// if icon is far right side of page
+ tipOffset = maxRightPos;
+ }
+ else {// if tooltip in the middle somewhere
+ tipOffset = tipOffset;
+ }
+ angular.element(tooltipWrapper).css({left: tipOffset + 'px'});
+ }
+ }
+ };
+
+ // TOOLTIP LINK ONCLICK AND FOCUS
+ angular.element(icon).on('click mouseover mouseout focus blur', function (e) {
+ if (e.type == 'mouseover') {
+ calcTooltip();
+ }
+ else if (e.type == 'mouseout' && elem.hasClass('active')) {
+ if (!elem.hasClass('activeClick')) {
+ angular.element(tooltipText).attr({
+ 'aria-hidden': true,
+ 'tabindex': '-1'
+ });
+ elem.removeClass('active');
+ } else if (elem.hasClass('activeClick') && navigator.userAgent.match(/iphone/i)) {
+ elem.removeClass('active activeClick');
+ }
+ }
+
+ else {
+ if (elem.hasClass('activeClick')) {
+ angular.element(icon).attr({'aria-expanded': false});
+ angular.element(tooltipText).attr({'aria-hidden': true});
+ angular.element(icon).removeAttr('aria-describedby');
+ elem.removeClass('activeClick active');
+ e.preventDefault();
+ }
+ else if (e.type == 'click') {
+ elem.addClass('activeClick');
+ calcTooltip();
+ e.preventDefault();
+ }
+ else {
+ angular.element(icon).on('keydown', function (e) {
+ if (e.keyCode == '32') {
+ (elem.hasClass('active')) ? elem.removeClass('active') : elem.addClass('value');
+ angular.element(icon).triggerHandler('click');
+ e.preventDefault();
+ } else if (e.keyCode == '27') {
+ (elem.hasClass('active')) ? elem.removeClass('active activeClick') : elem.addClass('value');
+ }
+ });
+ e.preventDefault();
+ }
+ }
+ e.preventDefault();
+ });
+
+ // TOOLTIP BUTTON INSIDE A TEXT FIELD
+ angular.element(btnIcon).on('click', function (e) {
+ var $this = angular.element(this);
+ if ($this.hasClass('active') && elem.hasClass('tooltip-onclick')) {
+ elem.removeClass('active');
+ $this.removeClass('active');
+ angular.element(tooltipText).removeAttr('aria-live');
+ $this.attr({'aria-expanded': 'false'});
+ $this.removeAttr('aria-describedby');
+ } else {
+ elem.addClass('active');
+ $this.addClass('active');
+ $this.attr({'aria-expanded': 'true', 'aria-describedby': angular.element(tooltipText).attr('id')});
+ angular.element(tooltipText).attr({'aria-live': 'polite'});
+ }
+ });
+
+ angular.element(btnIcon).on('blur', function (e) {
+ var $this = angular.element(this);
+ if ($this.hasClass('active') && elem.hasClass('tooltip-onclick')) {
+ elem.removeClass('active');
+ $this.removeClass('active');
+ angular.element(tooltipText).removeAttr('aria-live');
+ $this.attr({'aria-expanded': 'false'});
+ $this.removeAttr('aria-describedby');
+ }
+ });
+
+ angular.element(btnIcon).on('keydown', function (e) {
+ var $this = angular.element(this);
+ if (e.keyCode == '27') {
+ var $this = angular.element(this);
+ if ($this.hasClass('active') && elem.hasClass('tooltip-onclick')) {
+ elem.removeClass('active');
+ $this.removeClass('active');
+ angular.element(tooltipText).removeAttr('aria-live');
+ $this.attr({'aria-expanded': 'false'});
+ $this.removeAttr('aria-describedby');
+ }
+ }
+ });
+
+ // close all tooltips if clicking something else
+ $document.bind('click', function (e) {
+ var isElement = $isElement(angular.element(e.target), elem, $document);
+ if (!isElement) {
+ elem.removeClass('active');
+ angular.element(elem[0].querySelector('.tooltip-element')).removeClass('active');
+ angular.element(tooltipText).removeAttr('aria-live');
+ angular.element(elem[0].querySelector('.tooltip-element')).attr({'aria-expanded': 'false'});
+ angular.element(elem[0].querySelector('.tooltip-element')).removeAttr('aria-describedby');
+ };
+ });
+
+ angular.element(inputElm).on('keydown', function (e) {
+ if (e.keyCode == '27'){
+ elem.removeClass('active');
+ angular.element(tooltipText).css('display', 'none');
+ angular.element(tooltipText).removeAttr('aria-live');
+
+ if (angular.element(this).attr('aria-describedby') === undefined){
+
+ }
+
+ else if ((spaceIndex = angular.element(this).attr('aria-describedby').lastIndexOf(' ')) >= 0){
+
+ var describedByValue = angular.element(this).attr('aria-describedby').slice(0, spaceIndex);
+
+ angular.element(this).attr('aria-describedby', describedByValue);
+
+ }
+ else {
+ angular.element(this).removeAttr('aria-describedby');
+ }
+ }
+ });
+
+ angular.element(textAreaElm).on('keydown', function (e) {
+ if (e.keyCode == '27'){
+ elem.removeClass('active');
+ angular.element(tooltipText).css('display', 'none');
+ angular.element(tooltipText).removeAttr('aria-live');
+ if (angular.element(this).attr('aria-describedby') === undefined){
+
+ }
+
+ else if ((spaceIndex = angular.element(this).attr('aria-describedby').lastIndexOf(' ')) >= 0){
+
+ var describedByValue = angular.element(this).attr('aria-describedby').slice(0, spaceIndex);
+
+ angular.element(this).attr('aria-describedby', describedByValue);
+
+ }
+ else {
+ angular.element(this).removeAttr('aria-describedby');
+ }
+ }
+ });
+
+ // TOOLTIP TRIGGERED AUTOMATICALLY INSIDE A TEXT FIELD
+ angular.element(inputElm).on('focus', function (e) {
+ var allTooltip = $document[0].querySelectorAll('[class*="tooltip"]');
+ for (var i = 0; i < allTooltip.length; i++) {
+ if (angular.element(allTooltip[i]).hasClass('active')) {
+ angular.element(allTooltip[i]).triggerHandler('click');
+ }
+ };
+ angular.element(this).attr({'aria-describedby': angular.element(tooltipText).attr('id')});
+ angular.element(tooltipText).css('display', 'block');
+ angular.element(tooltipText).attr({'aria-live': 'polite'});
+ elem.addClass('active');
+ });
+ angular.element(inputElm).on('blur', function (e) {
+ elem.removeClass('active');
+ angular.element(tooltipText).css('display', 'none');
+ angular.element(tooltipText).removeAttr('aria-live');
+ angular.element(this).removeAttr('aria-describedby');
+ });
+
+ // TOOLTIP TRIGGERED AUTOMATICALLY INSIDE A TEXTAREA
+ angular.element(textAreaElm).on('focus', function (e) {
+ var allTooltip = $document[0].querySelectorAll('[class*="tooltip"]');
+ for (var i = 0; i < allTooltip.length; i++) {
+ if (angular.element(allTooltip[i]).hasClass('active')) {
+ angular.element(allTooltip[i]).triggerHandler('click');
+ }
+ };
+ elem.addClass('active');
+ angular.element(tooltipText).css('display', 'block');
+ angular.element(tooltipText).attr({'aria-live': 'polite'});
+ angular.element(this).attr({'aria-describedby': angular.element(tooltipText).attr('id')});
+ });
+ angular.element(textAreaElm).on('blur', function (e) {
+ elem.removeClass('active');
+ angular.element(tooltipText).css('display', 'none');
+ angular.element(tooltipText).removeAttr('aria-live');
+ angular.element(this).removeAttr('aria-describedby');
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:TreeNavigation
+ *
+ *
+ * @scope
+ * @param {String} setRole - This value needs to be "tree". This is required to incorporate CATO requirements.
+ * @param {Boolean} groupIt - This value needs to be "false" for top-level tree rendered.
+ *
+ * @description
+ * <file src="src/treeNav/docs/readme.md" />
+ *
+ * @usage
+ * <div class="b2b-tree">
+ * <b2b-tree-nav collection="treeStructure" set-role="tree" group-it="false"></b2b-tree-nav>
+ * </div>
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/treeNav/docs/demo.html" />
+ <file src="src/treeNav/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.treeNav', ['b2b.att.utilities'])
+ .directive('b2bTreeNav', function () {
+ return {
+ restrict: "E",
+ replace: true,
+ scope: {
+ collection: '=',
+ groupIt: '=',
+ setRole: '@'
+ },
+ templateUrl: function (element, attrs) {
+ if (attrs.groupIt === 'true') {
+ return "b2bTemplate/treeNav/groupedTree.html";
+ } else {
+ return "b2bTemplate/treeNav/ungroupedTree.html";
+ }
+ },
+ link: function (scope) {
+ if (!(scope.setRole === 'tree')) {
+ scope.setRole = 'group';
+ }
+ }
+ }
+ })
+ .directive('b2bMember', ['$compile', '$timeout', 'keymap', function ($compile, $timeout, keymap) {
+ return {
+ restrict: "E",
+ replace: true,
+ scope: {
+ member: '=',
+ groupIt: '='
+ },
+ templateUrl: 'b2bTemplate/treeNav/treeMember.html',
+ link: function (scope, element, attrs) {
+ scope.elemArr = [];
+ var removeRootTabIndex = function (elem) {
+ if (elem.parent().parent().eq(0).hasClass('b2b-tree')) {
+ elem.attr('tabindex', -1);
+ return;
+ }
+ removeRootTabIndex(elem.parent());
+ };
+ scope.$watch('member.child', function(newVal, oldVal){
+ if(newVal !== oldVal){
+ scope.showChild();
+ };
+ });
+ scope.showChild = function () {
+ if (!element.hasClass('grouped')) {
+ if (angular.isArray(scope.member.child) && scope.member.child.length > 0 && (scope.member.divide === undefined || scope.member.child.length < scope.member.divide)) {
+ scope.groupIt = false;
+ element.addClass('grouped');
+ element.append("<b2b-tree-nav collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-nav>");
+ $compile(element.contents())(scope);
+ if(scope.member.active && scope.member.active === true){
+ element.find('i').eq(0).removeClass('icon-primary-collapsed');
+ };
+ if(scope.member.selected && scope.member.selected === true){
+ element.attr('aria-selected', true);
+ element.attr('tabindex', 0);
+ removeRootTabIndex(element);
+ };
+ if(scope.member.active && scope.member.active == undefined){
+ element.find('i').eq(0).addClass('icon-primary-collapsed');
+ };
+ } else if (scope.member.child && scope.member.divide && scope.member.child.length > scope.member.divide) {
+ element.addClass('grouped');
+ scope.groupIt = true;
+ // FILTER - GROUPBY - APPROACH
+ var j = 0;
+ var grpName = '';
+ if(scope.member.child[0].groupName !== undefined){
+ grpName = scope.member.child[0].groupName;
+ }
+ else{
+ var toSlice = scope.member.child[0].name.search(' ');
+ grpName = scope.member.child[0].name.slice(0, toSlice);
+ }
+
+ for (i = 0; i < scope.member.child.length; i += scope.member.divide) {
+ j = 0;
+ for (j = j + i; j < (i + scope.member.divide); j++) {
+ if (j === scope.member.child.length) {
+ scope.member.child[j - 1].grpChild = grpName + ' ' + (i + 1) + ' - ' + (scope.member.child.length);
+ break;
+
+ if(scope.member.child[j-1].active && scope.member.child[j-1].active===true){
+ scope.member.child[j-1].activeGrp = true;
+ };
+
+ }
+ if (i + scope.member.divide > scope.member.child.length) {
+ scope.member.child[j].grpChild = grpName + ' ' + (i + 1) + ' - ' + (scope.member.child.length);
+ if(scope.member.child[j].active && scope.member.child[j].active===true){
+ scope.member.child[j].activeGrp = true;
+ };
+
+ } else {
+ scope.member.child[j].grpChild = grpName + ' ' + (i + 1) + ' - ' + (i + scope.member.divide);
+ if(scope.member.child[j].active && scope.member.child[j].active===true){
+ scope.member.child[j].activeGrp = true;
+ };
+ }
+ }
+ }
+ if(scope.member.divide){
+ element.append("<b2b-tree-nav collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-nav>");
+ } else {
+ element.append("<b2b-tree-nav collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-nav>");
+ }
+ $compile(element.contents())(scope);
+ if(scope.member.active && scope.member.active === true){
+ element.find('i').eq(0).removeClass('icon-primary-collapsed');
+ };
+ if(scope.member.selected && scope.member.selected === true){
+ element.attr('aria-selected', true);
+ };
+ if( scope.member.active && scope.member.active == undefined){
+ element.find('i').eq(0).addClass('icon-primary-collapsed');
+ };
+ }
+ }
+ };
+ //Below condition opens node for opening on json load.
+ if(scope.member.active && scope.member.active == true){
+ scope.showChild();
+ };
+ if(scope.member.active == undefined && !element.find('a').eq(0).hasClass('active') && scope.member.child !== undefined){
+ element.find('i').eq(0).addClass('icon-primary-collapsed');
+ }
+ else if(scope.member.child == undefined){
+ element.find('i').eq(0).addClass('icon-primary-circle');
+ };
+ element.bind('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case keymap.KEY.ENTER:
+ if (element.hasClass('bg') && scope.member.onSelect !== undefined) {
+ scope.member.onSelect(scope.member);
+ }
+ evt.stopPropagation();
+ break;
+ default:
+ break;
+ }
+
+ });
+ //else getting true in every case .. so better use switch case .. that makes more sense you dumb.
+ element.bind('click', function (evt) {
+ scope.showChild();
+ var expandFunc = scope.member.onExpand;
+
+ //onSelect
+ if (element.hasClass('bg') && scope.member.onSelect !== undefined) {
+ scope.member.onSelect(scope.member);
+ }
+ if (element.find('a').eq(0).hasClass('active') && scope.member.onExpand !== undefined) {
+ var eValue = scope.member.onExpand(scope.member);
+ }
+ if (!element.find('a').eq(0).hasClass('active') && scope.member.onCollapse !== undefined) {
+ scope.member.onCollapse(scope.member);
+ }
+ });
+ }
+ }
+}])
+ .directive('b2bTreeLink', ['keymap', '$timeout', function (keymap, $timeout) {
+ return {
+ restrict: 'A',
+ link: function (scope, element, attr, ctrl) {
+ var rootE, parentE, upE, downE;
+ var closeOthersUp = function (elem,isKeyPress,passiveClose) {
+ //For accordion functionality on sibling nodes
+ if (elem.find('a').eq(0).hasClass('active')) {
+ activeToggle(elem,isKeyPress,passiveClose);
+ return;
+ }
+ if (elem.hasClass('bg') && !isKeyPress) {
+ elem.removeClass('bg');
+ if (elem.attr('aria-selected')) {
+ elem.attr('aria-selected', 'false');
+ }
+ }
+ if (elem[0].previousElementSibling !== null) {
+ closeOthersUp(angular.element(elem[0].previousElementSibling),isKeyPress);
+ }
+ };
+ var closeOthersDown = function (elem,isKeyPress,passiveClose) {
+ //For accordion functionality on sibling nodes
+ if (elem.find('a').eq(0).hasClass('active')) {
+ activeToggle(elem,isKeyPress,passiveClose);
+ return;
+ }
+ if (elem.hasClass('bg') && !isKeyPress) {
+ elem.removeClass('bg');
+ if (elem.attr('aria-selected')) {
+ elem.attr('aria-selected', 'false');
+ }
+ }
+ if (elem[0].nextElementSibling !== null) {
+ closeOthersDown(angular.element(elem[0].nextElementSibling),isKeyPress);
+ }
+ };
+
+
+ var removeBackground = function(elem){
+
+ if(elem.hasClass('b2b-tree')){
+ angular.element(elem[0].getElementsByClassName('bg')).removeClass('bg');
+ return;
+ }else{
+ removeBackground(elem.parent().parent());
+ }
+
+ };
+
+/**
+* These two functions used for setting heights on parent nodes as the child node closes
+* Retaining this code for future reference
+
+ var addParentHeight = function(e, h) {
+ var parentLi = e.parent().parent();
+ var parentUl = e.parent();
+ if(!parentLi.hasClass('b2b-tree')) {
+ var addHeight = parentUl[0].offsetHeight + h;
+ parentLi.find('ul').eq(0).css({
+ height: addHeight+'px'
+ })
+ addParentHeight(parentLi, h);
+ }
+ };
+
+ var removeParentHeight = function(e, h) {
+ var parentLi = e.parent().parent();
+ var parentUl = e.parent();
+ if(!parentLi.hasClass('b2b-tree')) {
+ var addHeight = parentUl[0].offsetHeight - h;
+ parentLi.find('ul').eq(0).css({
+ height: addHeight+'px'
+ })
+ removeParentHeight(parentLi, h);
+ }
+ };
+*/
+
+ // isKeyPress - to notify that the function is called by Right Key press
+ // passiveClose - prevents firing of oncollapse events during the action
+ // of expand function(check the function definition)
+
+ var activeToggle = function (elem,isKeyPress,passiveClose) {
+ var element = elem.find('a').eq(0);
+ if (element.hasClass('active')) {
+ if(!isKeyPress){
+ elem.removeClass('bg');
+ }
+
+ if (elem.attr('aria-selected') && !isKeyPress) {
+ elem.attr('aria-selected', 'false');
+ }
+ if (!element.find('i').eq(0).hasClass('icon-primary-circle')) {
+ if(isKeyPress && scope.member){
+ if (scope.member.onCollapse !== undefined && !passiveClose) {
+ scope.member.onCollapse(scope.member);
+ }
+ }
+ element.removeClass('active');
+ elem.attr('aria-expanded', 'false');
+ element.find('i').eq(0).removeClass('icon-primary-expanded');
+ element.find('i').eq(0).addClass('icon-primary-collapsed');
+ //For Animation: below commented code is used to manually set height of UL to zero
+ //retaining code for future reference
+ /*
+ var totalHeight = elem.find('ul')[0].scrollHeight;
+ removeParentHeight(elem, totalHeight);
+ elem.find('ul').eq(0).css({
+ height: null
+ });*/
+ }
+ } else {
+ if(!isKeyPress){
+ elem.addClass('bg');
+ elem.attr('aria-selected', 'true');
+ }
+
+ if (!element.find('i').eq(0).hasClass('icon-primary-circle')) {
+ if(isKeyPress){
+ if(typeof scope.showChild === 'function' ){
+ scope.showChild();
+ }
+ if(scope.member){
+ if (scope.member.onExpand !== undefined) {
+ scope.member.onExpand(scope.member);
+ }
+ }
+ }
+ element.addClass('active');
+ elem.attr('aria-expanded', 'true');
+ element.find('i').eq(0).removeClass('icon-primary-collapsed');
+ element.find('i').eq(0).addClass('icon-primary-expanded');
+ //For Animation: below commented code is used to manually set height of the ul generatedon the click of parent LI.
+ //retaining code for future reference
+ /*
+ var totalHeight = elem.find('ul')[0].scrollHeight;
+ addParentHeight(elem, totalHeight);
+ elem.find('ul').eq(0).css({
+ height: totalHeight+'px'
+ });*/
+
+ }
+ }
+ };
+ element.bind('click', function (evt) {
+ //first we close others and then we open the clicked element
+ if (element[0].previousElementSibling) {
+ closeOthersUp(angular.element(element[0].previousElementSibling));
+ }
+ if (element[0].nextElementSibling) {
+ closeOthersDown(angular.element(element[0].nextElementSibling));
+ }
+ removeBackground(element);
+ activeToggle(element);
+
+ evt.stopPropagation();
+ });
+ //default root tree element tabindex set zero
+ if (element.parent().parent().hasClass('b2b-tree') && (element.parent()[0].previousElementSibling === null)) {
+ element.attr('tabindex', 0);
+ }
+ //check root via class
+ var isRoot = function (elem) {
+ if (elem.parent().parent().eq(0).hasClass('b2b-tree')) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ var findRoot = function (elem) {
+ if (isRoot(elem)) {
+ rootE = elem;
+ return;
+ }
+ findRoot(elem.parent());
+ };
+
+ var findPreActive = function (elem) {
+
+ if (!(elem.hasClass("active"))) {
+ return;
+ } else {
+ var childElems = angular.element(elem[0].nextElementSibling.children);
+ lastE = angular.element(childElems[childElems.length - 1]);
+ if (lastE.find('a').eq(0).hasClass('active')) {
+ findPreActive(lastE.find('a').eq(0));
+ }
+ upE = lastE;
+ }
+ };
+
+ var findUp = function (elem) {
+ if (isRoot(elem)) {
+ upE = elem;
+ return;
+ }
+ if (elem[0].previousElementSibling !== null && !angular.element(elem[0].previousElementSibling).hasClass('tree-hide')) {
+ upE = angular.element(elem[0].previousElementSibling);
+ if (upE.find('a').eq(0).hasClass('active')) {
+ findPreActive(upE.find('a').eq(0));
+ }
+ } else {
+ upE = elem.parent().parent();
+ }
+ };
+
+ var downElement = function (elem) {
+ if (elem.next().hasClass('tree-hide')) {
+ downElement(elem.next());
+ } else {
+ downE = elem.next();
+ }
+ }
+ var isBottomElem = false;
+ var downParent = function(liElem){
+ if(liElem.eq(0).parent().parent().eq(0).hasClass('b2b-tree')){
+ isBottomElem = true;
+ return;
+ }
+ if(liElem.next().length !== 0){
+ downE = liElem.next().eq(0);
+ return;
+ }
+ else {
+ downParent(liElem.parent().parent());
+ }
+ }
+
+ var findDown = function (elem) {
+ if (isRoot(elem.parent()) && !elem.hasClass('active')) {
+ downE = elem.parent();
+ return;
+ }
+ if (elem.hasClass('active')) {
+ downE = elem.next().find('li').eq(0);
+ if (downE.hasClass('tree-hide')) {
+ downElement(downE);
+ }
+
+ } else {
+ downParent(elem.parent());
+ if(isBottomElem === true){
+ downE = elem.parent();
+ isBottomElem = false;
+ }
+ }
+ };
+
+
+ var resetTabPosition = function(element){
+ findRoot(element);
+ angular.element(rootE.parent().parent()[0].querySelector("li[tabindex='0']")).attr('tabindex','-1');
+ var elemToFocus = rootE.parent().parent()[0].querySelector(".bg")|| rootE;
+
+ angular.element(elemToFocus).attr('tabindex','0');
+ };
+ // Function to control the expansion of nodes when the user tabs into the tree and
+ // the slected node is not visible
+ var expand = function(elemArr){
+ var elem= elemArr.pop();
+ var element = elem.find('a').eq(0);
+ var selectedNode = elem.parent().parent()[0].querySelector(".bg");
+ if(selectedNode != null){
+ while(elem){
+ element = elem.find('a').eq(0);
+ if(!element.hasClass('active') ){
+
+
+ if (elem[0].previousElementSibling) {
+ closeOthersUp(angular.element(elem[0].previousElementSibling),true,true);
+ }
+ if (elem[0].nextElementSibling) {
+ closeOthersDown(angular.element(elem[0].nextElementSibling),true,true);
+ }
+
+ if (!element.find('i').eq(0).hasClass('icon-primary-circle')) {
+ if(typeof scope.showChild === 'function' ){
+ scope.showChild();
+ }
+ element.addClass('active');
+ elem.attr('aria-expanded', 'true');
+ element.find('i').eq(0).removeClass('icon-primary-collapsed');
+ element.find('i').eq(0).addClass('icon-primary-expanded');
+ }
+
+ }
+ elem = elemArr.pop();
+ }
+
+ }else{
+ return;
+ }
+ };
+
+ element.find('a').eq(0).bind('mouseenter', function (evt) {
+ angular.forEach(document.querySelectorAll('.activeTooltip'), function(value, key) {
+ angular.element(value).removeClass('activeTooltip')
+ });
+ element.addClass('activeTooltip');
+ });
+ element.find('a').eq(0).bind('mouseleave', function (evt) {
+ element.removeClass('activeTooltip');
+ });
+ element.bind('focus', function (evt) {
+ angular.forEach(document.querySelectorAll('.activeTooltip'), function(value, key) {
+ angular.element(value).removeClass('activeTooltip')
+ });
+ element.addClass('activeTooltip');
+ });
+ element.bind('blur', function (evt) {
+ element.removeClass('activeTooltip');
+ });
+ element.bind('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case keymap.KEY.HOME:
+ evt.preventDefault();
+ evt.stopPropagation();
+ element.attr('tabindex', -1);
+ findRoot(element);
+ rootE.eq(0).attr('tabindex', 0);
+ rootE[0].focus();
+ break;
+ case keymap.KEY.LEFT:
+ evt.preventDefault();
+ evt.stopPropagation();
+
+ if(element.find('a').eq(0).hasClass('active')){
+ if (element[0].previousElementSibling) {
+ closeOthersUp(angular.element(element[0].previousElementSibling),true);
+ }
+ if (element[0].nextElementSibling) {
+ closeOthersDown(angular.element(element[0].nextElementSibling),true);
+ }
+ activeToggle(element,true);
+ return;
+ }
+ element.attr('tabindex', -1);
+ parentE = element.parent().parent();
+ parentE.attr('tabindex', 0);
+ parentE[0].focus();
+ break;
+ case keymap.KEY.UP:
+ evt.preventDefault();
+ evt.stopPropagation();
+ element.attr('tabindex', -1);
+ findUp(element);
+ upE.eq(0).attr('tabindex', 0);
+ upE[0].focus();
+ break;
+ case keymap.KEY.RIGHT:
+ evt.preventDefault();
+ evt.stopPropagation();
+ if(element.find('i').eq(0).hasClass('icon-primary-circle')){
+ break;
+ }
+ if (!element.find('a').eq(0).hasClass('active')) {
+ if (element[0].previousElementSibling) {
+ closeOthersUp(angular.element(element[0].previousElementSibling),true);
+ }
+ if (element[0].nextElementSibling) {
+ closeOthersDown(angular.element(element[0].nextElementSibling),true);
+ }
+ activeToggle(element,true);
+
+ }
+ else {
+ element.attr('tabindex', -1);
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ }
+ break;
+ case keymap.KEY.DOWN:
+ evt.preventDefault();
+ element.attr('tabindex', -1);
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.ENTER:
+ var isSelectedElem = element.hasClass('bg');
+ var enterFunc = function(element){
+ if (isSelectedElem) {
+ element.removeClass('bg');
+ if (element.attr('aria-selected')) {
+ element.attr('aria-selected', 'false');
+ }
+ }
+ else {
+ element.addClass('bg');
+ element.attr('aria-selected', 'true');
+ }
+ };
+ if (element[0].previousElementSibling) {
+ closeOthersUp(angular.element(element[0].previousElementSibling));
+ }
+ if (element[0].nextElementSibling) {
+ closeOthersDown(angular.element(element[0].nextElementSibling));
+ }
+
+ removeBackground(element);
+ enterFunc(element);
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.TAB:
+ $timeout(function(){
+ resetTabPosition(element);
+ },0);
+ evt.stopPropagation();
+
+ break;
+ default:
+ break;
+ }
+ });
+ element.bind('keyup',function(evt){
+ if(evt.keyCode === keymap.KEY.TAB){
+
+ var tempElem = element;
+ var elemArr = [];
+ while(!tempElem.hasClass('b2b-tree')){
+ elemArr.push(tempElem);
+ tempElem = tempElem.parent().parent();
+ }
+ elemArr.push(tempElem);
+
+ expand(elemArr);
+ }
+ evt.stopPropagation();
+ });
+ }
+ };
+ }]);
+/**
+ * @ngdoc directive
+ * @name Navigation.att:Tree nodes with checkboxes
+ *
+ * @param {String} setRole - The value needs to be "tree". This is required to incorporate CATO requirements.
+ * @param {boolean} groupIt - The value needs to be "false" for top-level tree rendered.
+ * @param {Object} collection - The JSON object of tree to be rendered.
+ * @description
+ * <file src="src/treeNodeCheckbox/docs/readme.md" />
+ *
+ * @usage
+ * <div class="b2b-tree-checkbox">
+ * <b2b-tree-node-checkbox collection="treeStructure" set-role="tree" group-it="false"></b2b-tree-node-checkbox>
+ * </div>
+ * @example
+ * <section id="code">
+ <example module="b2b.att">
+ <file src="src/treeNodeCheckbox/docs/demo.html" />
+ <file src="src/treeNodeCheckbox/docs/demo.js" />
+ </example>
+ </section>
+ *
+ */
+angular.module('b2b.att.treeNodeCheckbox', ['b2b.att.utilities'])
+ .directive('b2bTreeNodeCheckbox', function () {
+ return {
+ restrict: "E",
+ replace: true,
+ scope: {
+ collection: '=',
+ groupIt: '=',
+ setRole: '@'
+ },
+ templateUrl: function (element, attrs) {
+ if (attrs.groupIt === 'true') {
+ return "b2bTemplate/treeNodeCheckbox/groupedTree.html";
+ } else {
+ return "b2bTemplate/treeNodeCheckbox/ungroupedTree.html";
+ }
+ },
+ link: function (scope) {
+ if (!(scope.setRole === 'tree')) {
+ scope.setRole = 'group';
+ }
+ }
+ }
+ })
+ .directive('b2bTreeMember', ['$compile', '$timeout', 'keymap', function ($compile, $timeout, keymap) {
+ return {
+ restrict: "E",
+ replace: true,
+ scope: {
+ member: '=',
+ groupIt: '='
+ },
+ templateUrl: 'b2bTemplate/treeNodeCheckbox/treeMember.html',
+ link: function (scope, element, attrs) {
+ scope.elemArr = [];
+ var removeRootTabIndex = function (elem) {
+ if (elem.parent().parent().eq(0).hasClass('b2b-tree-checkbox')) {
+ elem.attr('tabindex', -1);
+ return;
+ }
+ removeRootTabIndex(elem.parent());
+ };
+ scope.$watch('member.child', function(newVal, oldVal){
+ if(newVal !== oldVal){
+ scope.showChild();
+ };
+ });
+
+ var checkedCount = 0;
+ var nonCheckedCount = 0;
+ var checkBoxesCount = 0;
+
+ if(element.find('a').eq(0).find('input')){
+ if(scope.member.indeterminate){
+ element.find('a').eq(0).find('input').prop('indeterminate', true);
+ element.attr('aria-checked',"mixed");
+ }
+ element.attr('aria-checked',scope.member.isSelected);
+ }
+
+ element.find('a').eq(0).find('input').bind('change',function(){
+ scope.member.indeterminate = false;
+ downwardModalUpdate(scope.member);
+ downwardSelection(element);
+ upwardSelection(element);
+ element.attr('aria-checked',scope.member.isSelected);
+ if (scope.member.onSelect !== undefined) {
+ scope.member.onSelect(scope.member);
+ }
+ });
+
+ element.find('a').eq(0).find('input').bind('click',function(){
+ var elem = angular.element(this);
+ if(scope.member.indeterminate){
+ scope.member.indeterminate = false;
+ scope.member.isSelected = true;
+ elem.prop('indeterminate', false);
+ elem.prop('checked', true);
+ elem.triggerHandler('change');
+ }
+ });
+
+ var groupNode = false;
+ var checkedTreeNode = false;
+
+ var isCheckboxSelected = function(elem){
+ checkedTreeNode = false;
+ checkedTreeNode = angular.element(angular.element(elem).find('a').eq(0))[0].querySelector('input.treeCheckBox').checked;
+ }
+
+ var findCheckbox = function(elem){
+ return angular.element(angular.element(elem).find('a').eq(0))[0].querySelector('input.treeCheckBox');
+ }
+
+ var updateGrpNodeCheckboxes = function(elem, checked){
+ angular.element(angular.element(elem).find('a').eq(0))[0].querySelector('input.treeCheckBox').checked = checked;
+ }
+
+
+ var isGroupNode = function(elem){
+ groupNode = false;
+ if(angular.element(angular.element(elem).find('a').eq(0))[0].querySelector('input.grpTreeCheckbox')){
+ groupNode = true;
+ }
+ }
+
+ var downwardModalUpdate = function(curMember){
+ angular.forEach(curMember.child, function(childMember, key) {
+ childMember.isSelected = curMember.isSelected;
+ childMember.indeterminate = false;
+ if(angular.isArray(childMember.child) && scope.member.child.length > 0){
+ downwardModalUpdate(childMember);
+ }
+ });
+ }
+
+ var downwardSelection = function(elem){
+ if(findCheckbox(elem)){
+ isCheckboxSelected(elem)
+ }
+ if(angular.element(elem).find('ul').length > 0){
+ var childNodes = angular.element(elem).find('ul').eq(0).children('li');
+ for(var i=0; i<childNodes.length; i++){
+ if(findCheckbox(childNodes[i])){
+ isGroupNode(childNodes[i]);
+ angular.element(findCheckbox(childNodes[i])).prop('indeterminate', false);
+ angular.element(childNodes[i]).attr('aria-checked',checkedTreeNode);
+ if(groupNode){
+ updateGrpNodeCheckboxes(childNodes[i],checkedTreeNode);
+ }else{
+ angular.element(childNodes[i]).scope().member.isSelected = checkedTreeNode;
+ angular.element(childNodes[i]).scope().member.indeterminate = false
+ angular.element(childNodes[i]).scope().$apply();
+ }
+ downwardSelection(childNodes[i]);
+ }
+ }
+
+ }
+ }
+ var upwardSelection = function(elem){
+ var childNodes = elem.parent().parent().find('ul').eq(0).children('li');
+ checkedCount = 0;
+ nonCheckedCount = 0;
+ checkBoxesCount = 0;
+ for(i=0; i<childNodes.length; i++){
+ if(findCheckbox(childNodes[i])){
+ isGroupNode(childNodes[i]);
+ isCheckboxSelected(childNodes[i]);
+ checkBoxesCount++;
+ if(checkedTreeNode){
+ checkedCount++;
+ }else if(!angular.element(angular.element(angular.element(childNodes[i]).find('a').eq(0))[0].querySelector('input.treeCheckBox')).prop('indeterminate')){
+ nonCheckedCount++;
+ }
+ }
+ }
+ var parentNodeScope;
+ parentNodeScope = angular.element(elem.parent().parent()).scope();
+ if(findCheckbox(elem.parent().parent())){
+ if(nonCheckedCount == checkBoxesCount){
+ angular.element(findCheckbox(elem.parent().parent())).prop('indeterminate', false);
+ if(parentNodeScope && parentNodeScope.member){
+ parentNodeScope.member.isSelected = false;
+ parentNodeScope.member.indeterminate = false;
+ }else{
+ updateGrpNodeCheckboxes(elem.parent().parent(),false);
+ }
+ angular.element(elem.parent().parent()).attr('aria-checked',false);
+ }else if(checkedCount == checkBoxesCount){
+ angular.element(findCheckbox(elem.parent().parent())).prop('indeterminate', false);
+ if(parentNodeScope && parentNodeScope.member){
+ parentNodeScope.member.isSelected = true;
+ parentNodeScope.member.indeterminate = false;
+ }else{
+ updateGrpNodeCheckboxes(elem.parent().parent(),true);
+ }
+ angular.element(elem.parent().parent()).attr('aria-checked',true);
+ }else{
+ angular.element(findCheckbox(elem.parent().parent())).prop('indeterminate', true);
+ if(parentNodeScope && parentNodeScope.member){
+ parentNodeScope.member.isSelected = false;
+ parentNodeScope.member.indeterminate = true;
+ }else{
+ updateGrpNodeCheckboxes(elem.parent().parent(),false);
+ }
+ angular.element(elem.parent().parent()).attr('aria-checked',"mixed");
+ }
+ if(parentNodeScope && parentNodeScope.member){
+ parentNodeScope.$apply();
+ }
+ }
+
+
+
+ if(elem.parent().parent().attr('role') == "treeitem"){
+ upwardSelection(elem.parent().parent());
+ }
+ }
+
+ scope.showChild = function () {
+ if (!element.hasClass('grouped')) {
+ if (angular.isArray(scope.member.child) && scope.member.child.length > 0 && (scope.member.divide === undefined || scope.member.child.length < scope.member.divide)) {
+ scope.groupIt = false;
+ element.addClass('grouped');
+ element.append("<b2b-tree-node-checkbox collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-node-checkbox>");
+ $compile(element.contents())(scope);
+ if(scope.member.active && scope.member.active === true){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).removeClass('icon-primary-collapsed');
+ };
+ if(scope.member.selected && scope.member.selected === true){
+ element.attr('tabindex', 0);
+ removeRootTabIndex(element);
+ };
+ if(scope.member.active && scope.member.active == undefined){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-collapsed');
+ };
+ } else if (scope.member.child && scope.member.divide && scope.member.child.length > scope.member.divide) {
+ element.addClass('grouped');
+ scope.groupIt = true;
+ var j = 0;
+ var grpName = '';
+ if(scope.member.child[0].groupName !== undefined){
+ grpName = scope.member.child[0].groupName;
+ }
+ else{
+ var toSlice = scope.member.child[0].name.search(' ');
+ grpName = scope.member.child[0].name.slice(0, toSlice);
+ }
+
+ for (i = 0; i < scope.member.child.length; i += scope.member.divide) {
+ j = 0;
+ for (j = j + i; j < (i + scope.member.divide); j++) {
+ if (j === scope.member.child.length) {
+ scope.member.child[j - 1].grpChild = grpName + ' ' + (i + 1) + ' - ' + (scope.member.child.length);
+ break;
+
+ if(scope.member.child[j-1].active && scope.member.child[j-1].active===true){
+ scope.member.child[j-1].activeGrp = true;
+ };
+
+ }
+ if (i + scope.member.divide > scope.member.child.length) {
+ scope.member.child[j].grpChild = grpName + ' ' + (i + 1) + ' - ' + (scope.member.child.length);
+ if(scope.member.child[j].active && scope.member.child[j].active===true){
+ scope.member.child[j].activeGrp = true;
+ };
+
+ } else {
+ scope.member.child[j].grpChild = grpName + ' ' + (i + 1) + ' - ' + (i + scope.member.divide);
+ if(scope.member.child[j].active && scope.member.child[j].active===true){
+ scope.member.child[j].activeGrp = true;
+ };
+ }
+ }
+ }
+ if(scope.member.divide){
+ element.append("<b2b-tree-node-checkbox collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-node-checkbox>");
+ } else {
+ element.append("<b2b-tree-node-checkbox collection='member.child' group-it='" + scope.groupIt + "'></b2b-tree-node-checkbox>");
+ }
+ $compile(element.contents())(scope);
+ if(scope.member.active && scope.member.active === true){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).removeClass('icon-primary-collapsed');
+ };
+
+ if( scope.member.active && scope.member.active == undefined){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-collapsed');
+ };
+ }
+ }
+ $timeout(function () {
+ if(!scope.member.indeterminate){
+ downwardSelection(element);
+ }
+ });
+
+ };
+
+ if(scope.member.active && scope.member.active == true){
+ scope.showChild();
+ };
+ if(scope.member.active == undefined && !element.find('a').eq(0).hasClass('active') && scope.member.child !== undefined){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-collapsed');
+ }
+ else if(scope.member.child == undefined){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-circle');
+ if(scope.$parent.$index === 0) {
+ element.find('a').eq(0).append('<span class="first-link"></span>');
+ };
+ };
+
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).bind('click', function (evt) {
+ scope.showChild();
+ var expandFunc = scope.member.onExpand;
+ if (element.find('a').eq(0).hasClass('active') && scope.member.onExpand !== undefined) {
+ var eValue = scope.member.onExpand(scope.member);
+ }
+ if (!element.find('a').eq(0).hasClass('active') && scope.member.onCollapse !== undefined) {
+ scope.member.onCollapse(scope.member);
+ }
+ });
+
+ angular.element(element[0].querySelectorAll('.treeNodeName')).eq(0).bind('click', function (evt) {
+
+ });
+
+ }
+ }
+}])
+ .directive('b2bTreeNodeLink', ['keymap', '$timeout', function (keymap, $timeout) {
+ return {
+ restrict: 'A',
+ link: function (scope, element, attr, ctrl) {
+ var rootE, parentE, upE, downE;
+ var closeOthersUp = function (elem) {
+
+ if (elem.find('a').eq(0).hasClass('active')) {
+ activeToggle(elem);
+ return;
+ }
+ if (elem.hasClass('bg')) {
+ elem.removeClass('bg');
+ }
+ if (elem[0].previousElementSibling !== null) {
+ closeOthersUp(angular.element(elem[0].previousElementSibling));
+ }
+ };
+ var closeOthersDown = function (elem) {
+
+ if (elem.find('a').eq(0).hasClass('active')) {
+ activeToggle(elem);
+ return;
+ }
+ if (elem.hasClass('bg')) {
+ elem.removeClass('bg');
+ }
+ if (elem[0].nextElementSibling !== null) {
+ closeOthersDown(angular.element(elem[0].nextElementSibling));
+ }
+ };
+
+ var removeBackgroundUp = function (elem) {
+
+ if (elem.hasClass('b2b-tree-checkbox')) {
+ return;
+ } else {
+ elem.parent().parent().removeClass('bg');
+ removeBackgroundUp(elem.parent().parent());
+ }
+ };
+
+ var removeBackgroundDown = function (elem) {
+
+ angular.element(elem[0].querySelector('.bg')).removeClass('bg');
+ };
+
+
+
+ var activeToggle = function (elem) {
+ var element = elem.find('a').eq(0);
+ if (element.hasClass('active')) {
+ elem.removeClass('bg');
+ if (!angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).hasClass('icon-primary-circle')) {
+ element.removeClass('active');
+ elem.attr('aria-expanded', 'false');
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).removeClass('icon-primary-expanded');
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-collapsed');
+ }
+ } else {
+ elem.addClass('bg');
+ if (!angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).hasClass('icon-primary-circle')) {
+ element.addClass('active');
+ elem.attr('aria-expanded', 'true');
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).removeClass('icon-primary-collapsed');
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).addClass('icon-primary-expanded');
+ }
+ }
+ };
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).bind('click', function (evt) {
+
+ if (element[0].previousElementSibling) {
+ closeOthersUp(angular.element(element[0].previousElementSibling));
+ }
+ if (element[0].nextElementSibling) {
+ closeOthersDown(angular.element(element[0].nextElementSibling));
+ }
+
+ activeToggle(element);
+
+ removeBackgroundDown(element);
+ removeBackgroundUp(element);
+ evt.stopPropagation();
+ });
+
+ if (element.parent().parent().hasClass('b2b-tree-checkbox') && (element.parent()[0].previousElementSibling === null)) {
+ element.attr('tabindex', 0);
+ }
+
+ var isRoot = function (elem) {
+ if (elem.parent().parent().eq(0).hasClass('b2b-tree-checkbox')) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ var findRoot = function (elem) {
+ if (isRoot(elem)) {
+ rootE = elem;
+ return;
+ }
+ findRoot(elem.parent());
+ };
+
+ var findPreActive = function (elem) {
+
+ if (!(elem.hasClass("active"))) {
+ return;
+ } else {
+ var childElems = angular.element(elem[0].nextElementSibling.children);
+ lastE = angular.element(childElems[childElems.length - 1]);
+ if (lastE.find('a').eq(0).hasClass('active')) {
+ findPreActive(lastE.find('a').eq(0));
+ }
+ upE = lastE;
+ }
+ };
+
+ var findUp = function (elem) {
+ if (isRoot(elem)) {
+ upE = elem;
+ return;
+ }
+ if (elem[0].previousElementSibling !== null && !angular.element(elem[0].previousElementSibling).hasClass('tree-hide')) {
+ upE = angular.element(elem[0].previousElementSibling);
+ if (upE.find('a').eq(0).hasClass('active')) {
+ findPreActive(upE.find('a').eq(0));
+ }
+ } else {
+ upE = elem.parent().parent();
+ }
+ };
+
+ var downElement = function (elem) {
+ if (elem.next().hasClass('tree-hide')) {
+ downElement(elem.next());
+ } else {
+ downE = elem.next();
+ }
+ }
+ var isBottomElem = false;
+ var downParent = function(liElem){
+ if(liElem.eq(0).parent().parent().eq(0).hasClass('b2b-tree-checkbox')){
+ isBottomElem = true;
+ return;
+ }
+ if(liElem.next().length !== 0){
+ downE = liElem.next().eq(0);
+ return;
+ }
+ else {
+ downParent(liElem.parent().parent());
+ }
+ }
+
+ var findDown = function (elem) {
+ if (isRoot(elem.parent()) && !elem.hasClass('active')) {
+ downE = elem.parent();
+ return;
+ }
+ if (elem.hasClass('active')) {
+ downE = elem.next().find('li').eq(0);
+ if (downE.hasClass('tree-hide')) {
+ downElement(downE);
+ }
+
+ } else {
+ downParent(elem.parent());
+ if(isBottomElem === true){
+ downE = elem.parent();
+ isBottomElem = false;
+ }
+ }
+ };
+ element.bind('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case keymap.KEY.HOME:
+ evt.preventDefault();
+ evt.stopPropagation();
+ element.attr('tabindex', -1);
+ findRoot(element);
+ rootE.eq(0).attr('tabindex', 0);
+ rootE[0].focus();
+ break;
+ case keymap.KEY.LEFT:
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (!isRoot(element)) {
+ if(element.find('a').eq(0).hasClass('active')){
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).triggerHandler('click');
+ return;
+ }
+ element.attr('tabindex', -1);
+ parentE = element.parent().parent();
+ parentE.attr('tabindex', 0);
+ parentE[0].focus();
+ } else {
+ if (element.find('a').eq(0).hasClass('active')) {
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).triggerHandler('click');
+ }
+ };
+ break;
+ case keymap.KEY.UP:
+ evt.preventDefault();
+ evt.stopPropagation();
+ element.attr('tabindex', -1);
+ findUp(element);
+ upE.eq(0).attr('tabindex', 0);
+ upE[0].focus();
+ break;
+ case keymap.KEY.RIGHT:
+ evt.preventDefault();
+ evt.stopPropagation();
+ if(angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).hasClass('icon-primary-circle')){
+ break;
+ }
+ if (!element.find('a').eq(0).hasClass('active')) {
+ angular.element(element[0].querySelectorAll('i.expandCollapseIcon')).eq(0).triggerHandler('click');
+ }
+ else {
+ element.attr('tabindex', -1);
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ }
+ break;
+ case keymap.KEY.DOWN:
+ evt.preventDefault();
+ element.attr('tabindex', -1);
+ findDown(element.find('a').eq(0));
+ downE.eq(0).attr('tabindex', 0);
+ downE[0].focus();
+ evt.stopPropagation();
+ break;
+ case keymap.KEY.SPACE:
+ case keymap.KEY.ENTER:
+ evt.preventDefault();
+ evt.stopPropagation();
+ if(angular.isDefined(element.scope().member.isSelected)){
+ element.scope().member.isSelected = !element.scope().member.isSelected;
+ element.scope().member.indeterminate = false;
+ element.scope().$apply();
+ element.find('a').eq(0).find('input').prop('indeterminate', false);
+ element.find('a').eq(0).find('input').triggerHandler('change');
+ }
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ };
+ }]);
+/*!
+ * VERSION: 1.7.3
+ * DATE: 2014-01-14
+ * UPDATES AND DOCS AT: http://www.greensock.com
+ *
+ * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
+ * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
+ * Club GreenSock members, the software agreement that was issued with your membership.
+ *
+ * @author: Jack Doyle, jack@greensock.com
+ **/
+(window._gsQueue || (window._gsQueue = [])).push( function() {
+
+ "use strict";
+
+ var _doc = document.documentElement,
+ _window = window,
+ _max = function(element, axis) {
+ var dim = (axis === "x") ? "Width" : "Height",
+ scroll = "scroll" + dim,
+ client = "client" + dim,
+ body = document.body;
+ return (element === _window || element === _doc || element === body) ? Math.max(_doc[scroll], body[scroll]) - (_window["inner" + dim] || Math.max(_doc[client], body[client])) : element[scroll] - element["offset" + dim];
+ },
+
+ ScrollToPlugin = window._gsDefine.plugin({
+ propName: "scrollTo",
+ API: 2,
+ version:"1.7.3",
+
+ //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
+ init: function(target, value, tween) {
+ this._wdw = (target === _window);
+ this._target = target;
+ this._tween = tween;
+ if (typeof(value) !== "object") {
+ value = {y:value}; //if we don't receive an object as the parameter, assume the user intends "y".
+ }
+ this._autoKill = (value.autoKill !== false);
+ this.x = this.xPrev = this.getX();
+ this.y = this.yPrev = this.getY();
+ if (value.x != null) {
+ this._addTween(this, "x", this.x, (value.x === "max") ? _max(target, "x") : value.x, "scrollTo_x", true);
+ this._overwriteProps.push("scrollTo_x");
+ } else {
+ this.skipX = true;
+ }
+ if (value.y != null) {
+ this._addTween(this, "y", this.y, (value.y === "max") ? _max(target, "y") : value.y, "scrollTo_y", true);
+ this._overwriteProps.push("scrollTo_y");
+ } else {
+ this.skipY = true;
+ }
+ return true;
+ },
+
+ //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
+ set: function(v) {
+ this._super.setRatio.call(this, v);
+
+ var x = (this._wdw || !this.skipX) ? this.getX() : this.xPrev,
+ y = (this._wdw || !this.skipY) ? this.getY() : this.yPrev,
+ yDif = y - this.yPrev,
+ xDif = x - this.xPrev;
+
+ if (this._autoKill) {
+ //note: iOS has a bug that throws off the scroll by several pixels, so we need to check if it's within 7 pixels of the previous one that we set instead of just looking for an exact match.
+ if (!this.skipX && (xDif > 7 || xDif < -7) && x < _max(this._target, "x")) {
+ this.skipX = true; //if the user scrolls separately, we should stop tweening!
+ }
+ if (!this.skipY && (yDif > 7 || yDif < -7) && y < _max(this._target, "y")) {
+ this.skipY = true; //if the user scrolls separately, we should stop tweening!
+ }
+ if (this.skipX && this.skipY) {
+ this._tween.kill();
+ }
+ }
+ if (this._wdw) {
+ _window.scrollTo((!this.skipX) ? this.x : x, (!this.skipY) ? this.y : y);
+ } else {
+ if (!this.skipY) {
+ this._target.scrollTop = this.y;
+ }
+ if (!this.skipX) {
+ this._target.scrollLeft = this.x;
+ }
+ }
+ this.xPrev = this.x;
+ this.yPrev = this.y;
+ }
+
+ }),
+ p = ScrollToPlugin.prototype;
+
+ ScrollToPlugin.max = _max;
+
+ p.getX = function() {
+ return (!this._wdw) ? this._target.scrollLeft : (_window.pageXOffset != null) ? _window.pageXOffset : (_doc.scrollLeft != null) ? _doc.scrollLeft : document.body.scrollLeft;
+ };
+
+ p.getY = function() {
+ return (!this._wdw) ? this._target.scrollTop : (_window.pageYOffset != null) ? _window.pageYOffset : (_doc.scrollTop != null) ? _doc.scrollTop : document.body.scrollTop;
+ };
+
+ p._kill = function(lookup) {
+ if (lookup.scrollTo_x) {
+ this.skipX = true;
+ }
+ if (lookup.scrollTo_y) {
+ this.skipY = true;
+ }
+ return this._super._kill.call(this, lookup);
+ };
+
+}); if (window._gsDefine) { window._gsQueue.pop()(); }
+/*!
+ * VERSION: 1.12.1
+ * DATE: 2014-06-26
+ * UPDATES AND DOCS AT: http://www.greensock.com
+ *
+ * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
+ *
+ * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
+ * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
+ * Club GreenSock members, the software agreement that was issued with your membership.
+ *
+ * @author: Jack Doyle, jack@greensock.com
+ **/
+
+(window._gsQueue || (window._gsQueue = [])).push( function() {
+
+ "use strict";
+
+ window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
+
+ var _slice = [].slice,
+ TweenMax = function(target, duration, vars) {
+ TweenLite.call(this, target, duration, vars);
+ this._cycle = 0;
+ this._yoyo = (this.vars.yoyo === true);
+ this._repeat = this.vars.repeat || 0;
+ this._repeatDelay = this.vars.repeatDelay || 0;
+ this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
+ this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
+ },
+ _tinyNum = 0.0000000001,
+ TweenLiteInternals = TweenLite._internals,
+ _isSelector = TweenLiteInternals.isSelector,
+ _isArray = TweenLiteInternals.isArray,
+ p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
+ _blankArray = [];
+
+ TweenMax.version = "1.12.1";
+ p.constructor = TweenMax;
+ p.kill()._gc = false;
+ TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
+ TweenMax.getTweensOf = TweenLite.getTweensOf;
+ TweenMax.lagSmoothing = TweenLite.lagSmoothing;
+ TweenMax.ticker = TweenLite.ticker;
+ TweenMax.render = TweenLite.render;
+
+ p.invalidate = function() {
+ this._yoyo = (this.vars.yoyo === true);
+ this._repeat = this.vars.repeat || 0;
+ this._repeatDelay = this.vars.repeatDelay || 0;
+ this._uncache(true);
+ return TweenLite.prototype.invalidate.call(this);
+ };
+
+ p.updateTo = function(vars, resetDuration) {
+ var curRatio = this.ratio, p;
+ if (resetDuration && this._startTime < this._timeline._time) {
+ this._startTime = this._timeline._time;
+ this._uncache(false);
+ if (this._gc) {
+ this._enabled(true, false);
+ } else {
+ this._timeline.insert(this, this._startTime - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
+ }
+ }
+ for (p in vars) {
+ this.vars[p] = vars[p];
+ }
+ if (this._initted) {
+ if (resetDuration) {
+ this._initted = false;
+ } else {
+ if (this._gc) {
+ this._enabled(true, false);
+ }
+ if (this._notifyPluginsOfEnabled && this._firstPT) {
+ TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks
+ }
+ if (this._time / this._duration > 0.998) { //if the tween has finished (or come extremely close to finishing), we just need to rewind it to 0 and then render it again at the end which forces it to re-initialize (parsing the new vars). We allow tweens that are close to finishing (but haven't quite finished) to work this way too because otherwise, the values are so small when determining where to project the starting values that binary math issues creep in and can make the tween appear to render incorrectly when run backwards.
+ var prevTime = this._time;
+ this.render(0, true, false);
+ this._initted = false;
+ this.render(prevTime, true, false);
+ } else if (this._time > 0) {
+ this._initted = false;
+ this._init();
+ var inv = 1 / (1 - curRatio),
+ pt = this._firstPT, endValue;
+ while (pt) {
+ endValue = pt.s + pt.c;
+ pt.c *= inv;
+ pt.s = endValue - pt.c;
+ pt = pt._next;
+ }
+ }
+ }
+ }
+ return this;
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ if (!this._initted) if (this._duration === 0 && this.vars.repeat) { //zero duration tweens that render immediately have render() called from TweenLite's constructor, before TweenMax's constructor has finished setting _repeat, _repeatDelay, and _yoyo which are critical in determining totalDuration() so we need to call invalidate() which is a low-kb way to get those set properly.
+ this.invalidate();
+ }
+ var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
+ prevTime = this._time,
+ prevTotalTime = this._totalTime,
+ prevCycle = this._cycle,
+ duration = this._duration,
+ prevRawPrevTime = this._rawPrevTime,
+ isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
+ if (time >= totalDur) {
+ this._totalTime = totalDur;
+ this._cycle = this._repeat;
+ if (this._yoyo && (this._cycle & 1) !== 0) {
+ this._time = 0;
+ this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
+ } else {
+ this._time = duration;
+ this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
+ }
+ if (!this._reversed) {
+ isComplete = true;
+ callback = "onComplete";
+ }
+ if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
+ time = 0;
+ }
+ if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
+ force = true;
+ if (prevRawPrevTime > _tinyNum) {
+ callback = "onReverseComplete";
+ }
+ }
+ this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ }
+
+ } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
+ this._totalTime = this._time = this._cycle = 0;
+ this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
+ if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
+ callback = "onReverseComplete";
+ isComplete = this._reversed;
+ }
+ if (time < 0) {
+ this._active = false;
+ if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ if (prevRawPrevTime >= 0) {
+ force = true;
+ }
+ this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ }
+ } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
+ force = true;
+ }
+ } else {
+ this._totalTime = this._time = time;
+
+ if (this._repeat !== 0) {
+ cycleDuration = duration + this._repeatDelay;
+ this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but Flash reports it as 0.79999999!)
+ if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
+ this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
+ }
+ this._time = this._totalTime - (this._cycle * cycleDuration);
+ if (this._yoyo) if ((this._cycle & 1) !== 0) {
+ this._time = duration - this._time;
+ }
+ if (this._time > duration) {
+ this._time = duration;
+ } else if (this._time < 0) {
+ this._time = 0;
+ }
+ }
+
+ if (this._easeType) {
+ r = this._time / duration;
+ type = this._easeType;
+ pow = this._easePower;
+ if (type === 1 || (type === 3 && r >= 0.5)) {
+ r = 1 - r;
+ }
+ if (type === 3) {
+ r *= 2;
+ }
+ if (pow === 1) {
+ r *= r;
+ } else if (pow === 2) {
+ r *= r * r;
+ } else if (pow === 3) {
+ r *= r * r * r;
+ } else if (pow === 4) {
+ r *= r * r * r * r;
+ }
+
+ if (type === 1) {
+ this.ratio = 1 - r;
+ } else if (type === 2) {
+ this.ratio = r;
+ } else if (this._time / duration < 0.5) {
+ this.ratio = r / 2;
+ } else {
+ this.ratio = 1 - (r / 2);
+ }
+
+ } else {
+ this.ratio = this._ease.getRatio(this._time / duration);
+ }
+
+ }
+
+ if (prevTime === this._time && !force && prevCycle === this._cycle) {
+ if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+ return;
+ } else if (!this._initted) {
+ this._init();
+ if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
+ return;
+ } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) { //we stick it in the queue for rendering at the very end of the tick - this is a performance optimization because browsers invalidate styles and force a recalculation if you read, write, and then read style data (so it's better to read/read/read/write/write/write than read/write/read/write/read/write). The down side, of course, is that usually you WANT things to render immediately because you may have code running right after that which depends on the change. Like imagine running TweenLite.set(...) and then immediately after that, creating a nother tween that animates the same property to another value; the starting values of that 2nd tween wouldn't be accurate if lazy is true.
+ this._time = prevTime;
+ this._totalTime = prevTotalTime;
+ this._rawPrevTime = prevRawPrevTime;
+ this._cycle = prevCycle;
+ TweenLiteInternals.lazyTweens.push(this);
+ this._lazy = time;
+ return;
+ }
+ //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
+ if (this._time && !isComplete) {
+ this.ratio = this._ease.getRatio(this._time / duration);
+ } else if (isComplete && this._ease._calcEnd) {
+ this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
+ }
+ }
+ if (this._lazy !== false) {
+ this._lazy = false;
+ }
+
+ if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
+ this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
+ }
+ if (prevTotalTime === 0) {
+ if (this._initted === 2 && time > 0) {
+ //this.invalidate();
+ this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
+ }
+ if (this._startAt) {
+ if (time >= 0) {
+ this._startAt.render(time, suppressEvents, force);
+ } else if (!callback) {
+ callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
+ }
+ }
+ if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
+ this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
+ }
+ }
+
+ pt = this._firstPT;
+ while (pt) {
+ if (pt.f) {
+ pt.t[pt.p](pt.c * this.ratio + pt.s);
+ } else {
+ pt.t[pt.p] = pt.c * this.ratio + pt.s;
+ }
+ pt = pt._next;
+ }
+
+ if (this._onUpdate) {
+ if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
+ this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
+ }
+ if (!suppressEvents) if (this._totalTime !== prevTotalTime || isComplete) {
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+ }
+ if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
+ this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
+ }
+ if (callback) if (!this._gc) { //check gc because there's a chance that kill() could be called in an onUpdate
+ if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
+ this._startAt.render(time, suppressEvents, force);
+ }
+ if (isComplete) {
+ if (this._timeline.autoRemoveChildren) {
+ this._enabled(false, false);
+ }
+ this._active = false;
+ }
+ if (!suppressEvents && this.vars[callback]) {
+ this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
+ }
+ if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
+ this._rawPrevTime = 0;
+ }
+ }
+ };
+
+//---- STATIC FUNCTIONS -----------------------------------------------------------------------------------------------------------
+
+ TweenMax.to = function(target, duration, vars) {
+ return new TweenMax(target, duration, vars);
+ };
+
+ TweenMax.from = function(target, duration, vars) {
+ vars.runBackwards = true;
+ vars.immediateRender = (vars.immediateRender != false);
+ return new TweenMax(target, duration, vars);
+ };
+
+ TweenMax.fromTo = function(target, duration, fromVars, toVars) {
+ toVars.startAt = fromVars;
+ toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
+ return new TweenMax(target, duration, toVars);
+ };
+
+ TweenMax.staggerTo = TweenMax.allTo = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ stagger = stagger || 0;
+ var delay = vars.delay || 0,
+ a = [],
+ finalComplete = function() {
+ if (vars.onComplete) {
+ vars.onComplete.apply(vars.onCompleteScope || this, arguments);
+ }
+ onCompleteAll.apply(onCompleteAllScope || this, onCompleteAllParams || _blankArray);
+ },
+ l, copy, i, p;
+ if (!_isArray(targets)) {
+ if (typeof(targets) === "string") {
+ targets = TweenLite.selector(targets) || targets;
+ }
+ if (_isSelector(targets)) {
+ targets = _slice.call(targets, 0);
+ }
+ }
+ l = targets.length;
+ for (i = 0; i < l; i++) {
+ copy = {};
+ for (p in vars) {
+ copy[p] = vars[p];
+ }
+ copy.delay = delay;
+ if (i === l - 1 && onCompleteAll) {
+ copy.onComplete = finalComplete;
+ }
+ a[i] = new TweenMax(targets[i], duration, copy);
+ delay += stagger;
+ }
+ return a;
+ };
+
+ TweenMax.staggerFrom = TweenMax.allFrom = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ vars.runBackwards = true;
+ vars.immediateRender = (vars.immediateRender != false);
+ return TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
+ };
+
+ TweenMax.staggerFromTo = TweenMax.allFromTo = function(targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ toVars.startAt = fromVars;
+ toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
+ return TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
+ };
+
+ TweenMax.delayedCall = function(delay, callback, params, scope, useFrames) {
+ return new TweenMax(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
+ };
+
+ TweenMax.set = function(target, vars) {
+ return new TweenMax(target, 0, vars);
+ };
+
+ TweenMax.isTweening = function(target) {
+ return (TweenLite.getTweensOf(target, true).length > 0);
+ };
+
+ var _getChildrenOf = function(timeline, includeTimelines) {
+ var a = [],
+ cnt = 0,
+ tween = timeline._first;
+ while (tween) {
+ if (tween instanceof TweenLite) {
+ a[cnt++] = tween;
+ } else {
+ if (includeTimelines) {
+ a[cnt++] = tween;
+ }
+ a = a.concat(_getChildrenOf(tween, includeTimelines));
+ cnt = a.length;
+ }
+ tween = tween._next;
+ }
+ return a;
+ },
+ getAllTweens = TweenMax.getAllTweens = function(includeTimelines) {
+ return _getChildrenOf(Animation._rootTimeline, includeTimelines).concat( _getChildrenOf(Animation._rootFramesTimeline, includeTimelines) );
+ };
+
+ TweenMax.killAll = function(complete, tweens, delayedCalls, timelines) {
+ if (tweens == null) {
+ tweens = true;
+ }
+ if (delayedCalls == null) {
+ delayedCalls = true;
+ }
+ var a = getAllTweens((timelines != false)),
+ l = a.length,
+ allTrue = (tweens && delayedCalls && timelines),
+ isDC, tween, i;
+ for (i = 0; i < l; i++) {
+ tween = a[i];
+ if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
+ if (complete) {
+ tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
+ } else {
+ tween._enabled(false, false);
+ }
+ }
+ }
+ };
+
+ TweenMax.killChildTweensOf = function(parent, complete) {
+ if (parent == null) {
+ return;
+ }
+ var tl = TweenLiteInternals.tweenLookup,
+ a, curParent, p, i, l;
+ if (typeof(parent) === "string") {
+ parent = TweenLite.selector(parent) || parent;
+ }
+ if (_isSelector(parent)) {
+ parent = _slice.call(parent, 0);
+ }
+ if (_isArray(parent)) {
+ i = parent.length;
+ while (--i > -1) {
+ TweenMax.killChildTweensOf(parent[i], complete);
+ }
+ return;
+ }
+ a = [];
+ for (p in tl) {
+ curParent = tl[p].target.parentNode;
+ while (curParent) {
+ if (curParent === parent) {
+ a = a.concat(tl[p].tweens);
+ }
+ curParent = curParent.parentNode;
+ }
+ }
+ l = a.length;
+ for (i = 0; i < l; i++) {
+ if (complete) {
+ a[i].totalTime(a[i].totalDuration());
+ }
+ a[i]._enabled(false, false);
+ }
+ };
+
+ var _changePause = function(pause, tweens, delayedCalls, timelines) {
+ tweens = (tweens !== false);
+ delayedCalls = (delayedCalls !== false);
+ timelines = (timelines !== false);
+ var a = getAllTweens(timelines),
+ allTrue = (tweens && delayedCalls && timelines),
+ i = a.length,
+ isDC, tween;
+ while (--i > -1) {
+ tween = a[i];
+ if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
+ tween.paused(pause);
+ }
+ }
+ };
+
+ TweenMax.pauseAll = function(tweens, delayedCalls, timelines) {
+ _changePause(true, tweens, delayedCalls, timelines);
+ };
+
+ TweenMax.resumeAll = function(tweens, delayedCalls, timelines) {
+ _changePause(false, tweens, delayedCalls, timelines);
+ };
+
+ TweenMax.globalTimeScale = function(value) {
+ var tl = Animation._rootTimeline,
+ t = TweenLite.ticker.time;
+ if (!arguments.length) {
+ return tl._timeScale;
+ }
+ value = value || _tinyNum; //can't allow zero because it'll throw the math off
+ tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
+ tl = Animation._rootFramesTimeline;
+ t = TweenLite.ticker.frame;
+ tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
+ tl._timeScale = Animation._rootTimeline._timeScale = value;
+ return value;
+ };
+
+
+//---- GETTERS / SETTERS ----------------------------------------------------------------------------------------------------------
+
+ p.progress = function(value) {
+ return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
+ };
+
+ p.totalProgress = function(value) {
+ return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
+ };
+
+ p.time = function(value, suppressEvents) {
+ if (!arguments.length) {
+ return this._time;
+ }
+ if (this._dirty) {
+ this.totalDuration();
+ }
+ if (value > this._duration) {
+ value = this._duration;
+ }
+ if (this._yoyo && (this._cycle & 1) !== 0) {
+ value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
+ } else if (this._repeat !== 0) {
+ value += this._cycle * (this._duration + this._repeatDelay);
+ }
+ return this.totalTime(value, suppressEvents);
+ };
+
+ p.duration = function(value) {
+ if (!arguments.length) {
+ return this._duration; //don't set _dirty = false because there could be repeats that haven't been factored into the _totalDuration yet. Otherwise, if you create a repeated TweenMax and then immediately check its duration(), it would cache the value and the totalDuration would not be correct, thus repeats wouldn't take effect.
+ }
+ return Animation.prototype.duration.call(this, value);
+ };
+
+ p.totalDuration = function(value) {
+ if (!arguments.length) {
+ if (this._dirty) {
+ //instead of Infinity, we use 999999999999 so that we can accommodate reverses
+ this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
+ this._dirty = false;
+ }
+ return this._totalDuration;
+ }
+ return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
+ };
+
+ p.repeat = function(value) {
+ if (!arguments.length) {
+ return this._repeat;
+ }
+ this._repeat = value;
+ return this._uncache(true);
+ };
+
+ p.repeatDelay = function(value) {
+ if (!arguments.length) {
+ return this._repeatDelay;
+ }
+ this._repeatDelay = value;
+ return this._uncache(true);
+ };
+
+ p.yoyo = function(value) {
+ if (!arguments.length) {
+ return this._yoyo;
+ }
+ this._yoyo = value;
+ return this;
+ };
+
+
+ return TweenMax;
+
+ }, true);
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * TimelineLite
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
+
+ var TimelineLite = function(vars) {
+ SimpleTimeline.call(this, vars);
+ this._labels = {};
+ this.autoRemoveChildren = (this.vars.autoRemoveChildren === true);
+ this.smoothChildTiming = (this.vars.smoothChildTiming === true);
+ this._sortChildren = true;
+ this._onUpdate = this.vars.onUpdate;
+ var v = this.vars,
+ val, p;
+ for (p in v) {
+ val = v[p];
+ if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) {
+ v[p] = this._swapSelfInParams(val);
+ }
+ }
+ if (_isArray(v.tweens)) {
+ this.add(v.tweens, 0, v.align, v.stagger);
+ }
+ },
+ _tinyNum = 0.0000000001,
+ _isSelector = TweenLite._internals.isSelector,
+ _isArray = TweenLite._internals.isArray,
+ _blankArray = [],
+ _globals = window._gsDefine.globals,
+ _copy = function(vars) {
+ var copy = {}, p;
+ for (p in vars) {
+ copy[p] = vars[p];
+ }
+ return copy;
+ },
+ _pauseCallback = function(tween, callback, params, scope) {
+ tween._timeline.pause(tween._startTime);
+ if (callback) {
+ callback.apply(scope || tween._timeline, params || _blankArray);
+ }
+ },
+ _slice = _blankArray.slice,
+ p = TimelineLite.prototype = new SimpleTimeline();
+
+ TimelineLite.version = "1.12.1";
+ p.constructor = TimelineLite;
+ p.kill()._gc = false;
+
+ p.to = function(target, duration, vars, position) {
+ var Engine = (vars.repeat && _globals.TweenMax) || TweenLite;
+ return duration ? this.add( new Engine(target, duration, vars), position) : this.set(target, vars, position);
+ };
+
+ p.from = function(target, duration, vars, position) {
+ return this.add( ((vars.repeat && _globals.TweenMax) || TweenLite).from(target, duration, vars), position);
+ };
+
+ p.fromTo = function(target, duration, fromVars, toVars, position) {
+ var Engine = (toVars.repeat && _globals.TweenMax) || TweenLite;
+ return duration ? this.add( Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position);
+ };
+
+ p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope, smoothChildTiming:this.smoothChildTiming}),
+ i;
+ if (typeof(targets) === "string") {
+ targets = TweenLite.selector(targets) || targets;
+ }
+ if (_isSelector(targets)) { //senses if the targets object is a selector. If it is, we should translate it into an array.
+ targets = _slice.call(targets, 0);
+ }
+ stagger = stagger || 0;
+ for (i = 0; i < targets.length; i++) {
+ if (vars.startAt) {
+ vars.startAt = _copy(vars.startAt);
+ }
+ tl.to(targets[i], duration, _copy(vars), i * stagger);
+ }
+ return this.add(tl, position);
+ };
+
+ p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ vars.immediateRender = (vars.immediateRender != false);
+ vars.runBackwards = true;
+ return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
+ };
+
+ p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
+ toVars.startAt = fromVars;
+ toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
+ return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
+ };
+
+ p.call = function(callback, params, scope, position) {
+ return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
+ };
+
+ p.set = function(target, vars, position) {
+ position = this._parseTimeOrLabel(position, 0, true);
+ if (vars.immediateRender == null) {
+ vars.immediateRender = (position === this._time && !this._paused);
+ }
+ return this.add( new TweenLite(target, 0, vars), position);
+ };
+
+ TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) {
+ vars = vars || {};
+ if (vars.smoothChildTiming == null) {
+ vars.smoothChildTiming = true;
+ }
+ var tl = new TimelineLite(vars),
+ root = tl._timeline,
+ tween, next;
+ if (ignoreDelayedCalls == null) {
+ ignoreDelayedCalls = true;
+ }
+ root._remove(tl, true);
+ tl._startTime = 0;
+ tl._rawPrevTime = tl._time = tl._totalTime = root._time;
+ tween = root._first;
+ while (tween) {
+ next = tween._next;
+ if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
+ tl.add(tween, tween._startTime - tween._delay);
+ }
+ tween = next;
+ }
+ root.add(tl, 0);
+ return tl;
+ };
+
+ p.add = function(value, position, align, stagger) {
+ var curTime, l, i, child, tl, beforeRawTime;
+ if (typeof(position) !== "number") {
+ position = this._parseTimeOrLabel(position, 0, true, value);
+ }
+ if (!(value instanceof Animation)) {
+ if ((value instanceof Array) || (value && value.push && _isArray(value))) {
+ align = align || "normal";
+ stagger = stagger || 0;
+ curTime = position;
+ l = value.length;
+ for (i = 0; i < l; i++) {
+ if (_isArray(child = value[i])) {
+ child = new TimelineLite({tweens:child});
+ }
+ this.add(child, curTime);
+ if (typeof(child) !== "string" && typeof(child) !== "function") {
+ if (align === "sequence") {
+ curTime = child._startTime + (child.totalDuration() / child._timeScale);
+ } else if (align === "start") {
+ child._startTime -= child.delay();
+ }
+ }
+ curTime += stagger;
+ }
+ return this._uncache(true);
+ } else if (typeof(value) === "string") {
+ return this.addLabel(value, position);
+ } else if (typeof(value) === "function") {
+ value = TweenLite.delayedCall(0, value);
+ } else {
+ throw("Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string.");
+ }
+ }
+
+ SimpleTimeline.prototype.add.call(this, value, position);
+
+ //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. We should also align the playhead with the parent timeline's when appropriate.
+ if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) {
+ //in case any of the ancestors had completed but should now be enabled...
+ tl = this;
+ beforeRawTime = (tl.rawTime() > value._startTime); //if the tween is placed on the timeline so that it starts BEFORE the current rawTime, we should align the playhead (move the timeline). This is because sometimes users will create a timeline, let it finish, and much later append a tween and expect it to run instead of jumping to its end state. While technically one could argue that it should jump to its end state, that's not what users intuitively expect.
+ while (tl._timeline) {
+ if (beforeRawTime && tl._timeline.smoothChildTiming) {
+ tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it.
+ } else if (tl._gc) {
+ tl._enabled(true, false);
+ }
+ tl = tl._timeline;
+ }
+ }
+
+ return this;
+ };
+
+ p.remove = function(value) {
+ if (value instanceof Animation) {
+ return this._remove(value, false);
+ } else if (value instanceof Array || (value && value.push && _isArray(value))) {
+ var i = value.length;
+ while (--i > -1) {
+ this.remove(value[i]);
+ }
+ return this;
+ } else if (typeof(value) === "string") {
+ return this.removeLabel(value);
+ }
+ return this.kill(null, value);
+ };
+
+ p._remove = function(tween, skipDisable) {
+ SimpleTimeline.prototype._remove.call(this, tween, skipDisable);
+ var last = this._last;
+ if (!last) {
+ this._time = this._totalTime = this._duration = this._totalDuration = 0;
+ } else if (this._time > last._startTime + last._totalDuration / last._timeScale) {
+ this._time = this.duration();
+ this._totalTime = this._totalDuration;
+ }
+ return this;
+ };
+
+ p.append = function(value, offsetOrLabel) {
+ return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value));
+ };
+
+ p.insert = p.insertMultiple = function(value, position, align, stagger) {
+ return this.add(value, position || 0, align, stagger);
+ };
+
+ p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) {
+ return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger);
+ };
+
+ p.addLabel = function(label, position) {
+ this._labels[label] = this._parseTimeOrLabel(position);
+ return this;
+ };
+
+ p.addPause = function(position, callback, params, scope) {
+ return this.call(_pauseCallback, ["{self}", callback, params, scope], this, position);
+ };
+
+ p.removeLabel = function(label) {
+ delete this._labels[label];
+ return this;
+ };
+
+ p.getLabelTime = function(label) {
+ return (this._labels[label] != null) ? this._labels[label] : -1;
+ };
+
+ p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) {
+ var i;
+ //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration().
+ if (ignore instanceof Animation && ignore.timeline === this) {
+ this.remove(ignore);
+ } else if (ignore && ((ignore instanceof Array) || (ignore.push && _isArray(ignore)))) {
+ i = ignore.length;
+ while (--i > -1) {
+ if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
+ this.remove(ignore[i]);
+ }
+ }
+ }
+ if (typeof(offsetOrLabel) === "string") {
+ return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent);
+ }
+ offsetOrLabel = offsetOrLabel || 0;
+ if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value).
+ i = timeOrLabel.indexOf("=");
+ if (i === -1) {
+ if (this._labels[timeOrLabel] == null) {
+ return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel;
+ }
+ return this._labels[timeOrLabel] + offsetOrLabel;
+ }
+ offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1));
+ timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration();
+ } else if (timeOrLabel == null) {
+ timeOrLabel = this.duration();
+ }
+ return Number(timeOrLabel) + offsetOrLabel;
+ };
+
+ p.seek = function(position, suppressEvents) {
+ return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false));
+ };
+
+ p.stop = function() {
+ return this.paused(true);
+ };
+
+ p.gotoAndPlay = function(position, suppressEvents) {
+ return this.play(position, suppressEvents);
+ };
+
+ p.gotoAndStop = function(position, suppressEvents) {
+ return this.pause(position, suppressEvents);
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ if (this._gc) {
+ this._enabled(true, false);
+ }
+ var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
+ prevTime = this._time,
+ prevStart = this._startTime,
+ prevTimeScale = this._timeScale,
+ prevPaused = this._paused,
+ tween, isComplete, next, callback, internalForce;
+ if (time >= totalDur) {
+ this._totalTime = this._time = totalDur;
+ if (!this._reversed) if (!this._hasPausedChild()) {
+ isComplete = true;
+ callback = "onComplete";
+ if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) {
+ internalForce = true;
+ if (this._rawPrevTime > _tinyNum) {
+ callback = "onReverseComplete";
+ }
+ }
+ }
+ this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ time = totalDur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7.
+
+ } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
+ this._totalTime = this._time = 0;
+ if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || (time < 0 && this._rawPrevTime >= 0)))) {
+ callback = "onReverseComplete";
+ isComplete = this._reversed;
+ }
+ if (time < 0) {
+ this._active = false;
+ if (this._duration === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ internalForce = true;
+ }
+ this._rawPrevTime = time;
+ } else {
+ this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+
+ time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
+ if (!this._initted) {
+ internalForce = true;
+ }
+ }
+
+ } else {
+ this._totalTime = this._time = this._rawPrevTime = time;
+ }
+ if ((this._time === prevTime || !this._first) && !force && !internalForce) {
+ return;
+ } else if (!this._initted) {
+ this._initted = true;
+ }
+
+ if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) {
+ this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
+ }
+
+ if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) {
+ this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
+ }
+
+ if (this._time >= prevTime) {
+ tween = this._first;
+ while (tween) {
+ next = tween._next; //record it here because the value could change after rendering...
+ if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
+ break;
+ } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
+ if (!tween._reversed) {
+ tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
+ } else {
+ tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
+ }
+ }
+ tween = next;
+ }
+ } else {
+ tween = this._last;
+ while (tween) {
+ next = tween._prev; //record it here because the value could change after rendering...
+ if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
+ break;
+ } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
+ if (!tween._reversed) {
+ tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
+ } else {
+ tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
+ }
+ }
+ tween = next;
+ }
+ }
+
+ if (this._onUpdate) if (!suppressEvents) {
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+
+ if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
+ if (isComplete) {
+ if (this._timeline.autoRemoveChildren) {
+ this._enabled(false, false);
+ }
+ this._active = false;
+ }
+ if (!suppressEvents && this.vars[callback]) {
+ this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
+ }
+ }
+ };
+
+ p._hasPausedChild = function() {
+ var tween = this._first;
+ while (tween) {
+ if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) {
+ return true;
+ }
+ tween = tween._next;
+ }
+ return false;
+ };
+
+ p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) {
+ ignoreBeforeTime = ignoreBeforeTime || -9999999999;
+ var a = [],
+ tween = this._first,
+ cnt = 0;
+ while (tween) {
+ if (tween._startTime < ignoreBeforeTime) {
+ //do nothing
+ } else if (tween instanceof TweenLite) {
+ if (tweens !== false) {
+ a[cnt++] = tween;
+ }
+ } else {
+ if (timelines !== false) {
+ a[cnt++] = tween;
+ }
+ if (nested !== false) {
+ a = a.concat(tween.getChildren(true, tweens, timelines));
+ cnt = a.length;
+ }
+ }
+ tween = tween._next;
+ }
+ return a;
+ };
+
+ p.getTweensOf = function(target, nested) {
+ var disabled = this._gc,
+ a = [],
+ cnt = 0,
+ tweens, i;
+ if (disabled) {
+ this._enabled(true, true); //getTweensOf() filters out disabled tweens, and we have to mark them as _gc = true when the timeline completes in order to allow clean garbage collection, so temporarily re-enable the timeline here.
+ }
+ tweens = TweenLite.getTweensOf(target);
+ i = tweens.length;
+ while (--i > -1) {
+ if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
+ a[cnt++] = tweens[i];
+ }
+ }
+ if (disabled) {
+ this._enabled(false, true);
+ }
+ return a;
+ };
+
+ p._contains = function(tween) {
+ var tl = tween.timeline;
+ while (tl) {
+ if (tl === this) {
+ return true;
+ }
+ tl = tl.timeline;
+ }
+ return false;
+ };
+
+ p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) {
+ ignoreBeforeTime = ignoreBeforeTime || 0;
+ var tween = this._first,
+ labels = this._labels,
+ p;
+ while (tween) {
+ if (tween._startTime >= ignoreBeforeTime) {
+ tween._startTime += amount;
+ }
+ tween = tween._next;
+ }
+ if (adjustLabels) {
+ for (p in labels) {
+ if (labels[p] >= ignoreBeforeTime) {
+ labels[p] += amount;
+ }
+ }
+ }
+ return this._uncache(true);
+ };
+
+ p._kill = function(vars, target) {
+ if (!vars && !target) {
+ return this._enabled(false, false);
+ }
+ var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target),
+ i = tweens.length,
+ changed = false;
+ while (--i > -1) {
+ if (tweens[i]._kill(vars, target)) {
+ changed = true;
+ }
+ }
+ return changed;
+ };
+
+ p.clear = function(labels) {
+ var tweens = this.getChildren(false, true, true),
+ i = tweens.length;
+ this._time = this._totalTime = 0;
+ while (--i > -1) {
+ tweens[i]._enabled(false, false);
+ }
+ if (labels !== false) {
+ this._labels = {};
+ }
+ return this._uncache(true);
+ };
+
+ p.invalidate = function() {
+ var tween = this._first;
+ while (tween) {
+ tween.invalidate();
+ tween = tween._next;
+ }
+ return this;
+ };
+
+ p._enabled = function(enabled, ignoreTimeline) {
+ if (enabled === this._gc) {
+ var tween = this._first;
+ while (tween) {
+ tween._enabled(enabled, true);
+ tween = tween._next;
+ }
+ }
+ return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline);
+ };
+
+ p.duration = function(value) {
+ if (!arguments.length) {
+ if (this._dirty) {
+ this.totalDuration(); //just triggers recalculation
+ }
+ return this._duration;
+ }
+ if (this.duration() !== 0 && value !== 0) {
+ this.timeScale(this._duration / value);
+ }
+ return this;
+ };
+
+ p.totalDuration = function(value) {
+ if (!arguments.length) {
+ if (this._dirty) {
+ var max = 0,
+ tween = this._last,
+ prevStart = 999999999999,
+ prev, end;
+ while (tween) {
+ prev = tween._prev; //record it here in case the tween changes position in the sequence...
+ if (tween._dirty) {
+ tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
+ }
+ if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence
+ this.add(tween, tween._startTime - tween._delay);
+ } else {
+ prevStart = tween._startTime;
+ }
+ if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found.
+ max -= tween._startTime;
+ if (this._timeline.smoothChildTiming) {
+ this._startTime += tween._startTime / this._timeScale;
+ }
+ this.shiftChildren(-tween._startTime, false, -9999999999);
+ prevStart = 0;
+ }
+ end = tween._startTime + (tween._totalDuration / tween._timeScale);
+ if (end > max) {
+ max = end;
+ }
+ tween = prev;
+ }
+ this._duration = this._totalDuration = max;
+ this._dirty = false;
+ }
+ return this._totalDuration;
+ }
+ if (this.totalDuration() !== 0) if (value !== 0) {
+ this.timeScale(this._totalDuration / value);
+ }
+ return this;
+ };
+
+ p.usesFrames = function() {
+ var tl = this._timeline;
+ while (tl._timeline) {
+ tl = tl._timeline;
+ }
+ return (tl === Animation._rootFramesTimeline);
+ };
+
+ p.rawTime = function() {
+ return this._paused ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale;
+ };
+
+ return TimelineLite;
+
+ }, true);
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * TimelineMax
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) {
+
+ var TimelineMax = function(vars) {
+ TimelineLite.call(this, vars);
+ this._repeat = this.vars.repeat || 0;
+ this._repeatDelay = this.vars.repeatDelay || 0;
+ this._cycle = 0;
+ this._yoyo = (this.vars.yoyo === true);
+ this._dirty = true;
+ },
+ _tinyNum = 0.0000000001,
+ _blankArray = [],
+ _easeNone = new Ease(null, null, 1, 0),
+ p = TimelineMax.prototype = new TimelineLite();
+
+ p.constructor = TimelineMax;
+ p.kill()._gc = false;
+ TimelineMax.version = "1.12.1";
+
+ p.invalidate = function() {
+ this._yoyo = (this.vars.yoyo === true);
+ this._repeat = this.vars.repeat || 0;
+ this._repeatDelay = this.vars.repeatDelay || 0;
+ this._uncache(true);
+ return TimelineLite.prototype.invalidate.call(this);
+ };
+
+ p.addCallback = function(callback, position, params, scope) {
+ return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
+ };
+
+ p.removeCallback = function(callback, position) {
+ if (callback) {
+ if (position == null) {
+ this._kill(null, callback);
+ } else {
+ var a = this.getTweensOf(callback, false),
+ i = a.length,
+ time = this._parseTimeOrLabel(position);
+ while (--i > -1) {
+ if (a[i]._startTime === time) {
+ a[i]._enabled(false, false);
+ }
+ }
+ }
+ }
+ return this;
+ };
+
+ p.tweenTo = function(position, vars) {
+ vars = vars || {};
+ var copy = {ease:_easeNone, overwrite:(vars.delay ? 2 : 1), useFrames:this.usesFrames(), immediateRender:false},//note: set overwrite to 1 (true/all) by default unless there's a delay so that we avoid a racing situation that could happen if, for example, an onmousemove creates the same tweenTo() over and over again.
+ duration, p, t;
+ for (p in vars) {
+ copy[p] = vars[p];
+ }
+ copy.time = this._parseTimeOrLabel(position);
+ duration = (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001;
+ t = new TweenLite(this, duration, copy);
+ copy.onStart = function() {
+ t.target.paused(true);
+ if (t.vars.time !== t.target.time() && duration === t.duration()) { //don't make the duration zero - if it's supposed to be zero, don't worry because it's already initting the tween and will complete immediately, effectively making the duration zero anyway. If we make duration zero, the tween won't run at all.
+ t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale );
+ }
+ if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it.
+ vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray);
+ }
+ };
+ return t;
+ };
+
+ p.tweenFromTo = function(fromPosition, toPosition, vars) {
+ vars = vars || {};
+ fromPosition = this._parseTimeOrLabel(fromPosition);
+ vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this};
+ vars.immediateRender = (vars.immediateRender !== false);
+ var t = this.tweenTo(toPosition, vars);
+ return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001);
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ if (this._gc) {
+ this._enabled(true, false);
+ }
+ var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
+ dur = this._duration,
+ prevTime = this._time,
+ prevTotalTime = this._totalTime,
+ prevStart = this._startTime,
+ prevTimeScale = this._timeScale,
+ prevRawPrevTime = this._rawPrevTime,
+ prevPaused = this._paused,
+ prevCycle = this._cycle,
+ tween, isComplete, next, callback, internalForce, cycleDuration;
+ if (time >= totalDur) {
+ if (!this._locked) {
+ this._totalTime = totalDur;
+ this._cycle = this._repeat;
+ }
+ if (!this._reversed) if (!this._hasPausedChild()) {
+ isComplete = true;
+ callback = "onComplete";
+ if (this._duration === 0) if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) {
+ internalForce = true;
+ if (prevRawPrevTime > _tinyNum) {
+ callback = "onReverseComplete";
+ }
+ }
+ }
+ this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ if (this._yoyo && (this._cycle & 1) !== 0) {
+ this._time = time = 0;
+ } else {
+ this._time = dur;
+ time = dur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7. We cannot do less then 0.0001 because the same issue can occur when the duration is extremely large like 999999999999 in which case adding 0.00000001, for example, causes it to act like nothing was added.
+ }
+
+ } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
+ if (!this._locked) {
+ this._totalTime = this._cycle = 0;
+ }
+ this._time = 0;
+ if (prevTime !== 0 || (dur === 0 && prevRawPrevTime !== _tinyNum && (prevRawPrevTime > 0 || (time < 0 && prevRawPrevTime >= 0)) && !this._locked)) { //edge case for checking time < 0 && prevRawPrevTime >= 0: a zero-duration fromTo() tween inside a zero-duration timeline (yeah, very rare)
+ callback = "onReverseComplete";
+ isComplete = this._reversed;
+ }
+ if (time < 0) {
+ this._active = false;
+ if (dur === 0) if (prevRawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ internalForce = true;
+ }
+ this._rawPrevTime = time;
+ } else {
+ this._rawPrevTime = (dur || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
+ if (!this._initted) {
+ internalForce = true;
+ }
+ }
+
+ } else {
+ if (dur === 0 && prevRawPrevTime < 0) { //without this, zero-duration repeating timelines (like with a simple callback nested at the very beginning and a repeatDelay) wouldn't render the first time through.
+ internalForce = true;
+ }
+ this._time = this._rawPrevTime = time;
+ if (!this._locked) {
+ this._totalTime = time;
+ if (this._repeat !== 0) {
+ cycleDuration = dur + this._repeatDelay;
+ this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but it gets reported as 0.79999999!)
+ if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
+ this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
+ }
+ this._time = this._totalTime - (this._cycle * cycleDuration);
+ if (this._yoyo) if ((this._cycle & 1) !== 0) {
+ this._time = dur - this._time;
+ }
+ if (this._time > dur) {
+ this._time = dur;
+ time = dur + 0.0001; //to avoid occasional floating point rounding error
+ } else if (this._time < 0) {
+ this._time = time = 0;
+ } else {
+ time = this._time;
+ }
+ }
+ }
+ }
+
+ if (this._cycle !== prevCycle) if (!this._locked) {
+ /*
+ make sure children at the end/beginning of the timeline are rendered properly. If, for example,
+ a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
+ would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there
+ could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So
+ we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must
+ ensure that zero-duration tweens at the very beginning or end of the TimelineMax work.
+ */
+ var backwards = (this._yoyo && (prevCycle & 1) !== 0),
+ wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)),
+ recTotalTime = this._totalTime,
+ recCycle = this._cycle,
+ recRawPrevTime = this._rawPrevTime,
+ recTime = this._time;
+
+ this._totalTime = prevCycle * dur;
+ if (this._cycle < prevCycle) {
+ backwards = !backwards;
+ } else {
+ this._totalTime += dur;
+ }
+ this._time = prevTime; //temporarily revert _time so that render() renders the children in the correct order. Without this, tweens won't rewind correctly. We could arhictect things in a "cleaner" way by splitting out the rendering queue into a separate method but for performance reasons, we kept it all inside this method.
+
+ this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.0001 : prevRawPrevTime;
+ this._cycle = prevCycle;
+ this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render()
+ prevTime = (backwards) ? 0 : dur;
+ this.render(prevTime, suppressEvents, (dur === 0));
+ if (!suppressEvents) if (!this._gc) {
+ if (this.vars.onRepeat) {
+ this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
+ }
+ }
+ if (wrap) {
+ prevTime = (backwards) ? dur + 0.0001 : -0.0001;
+ this.render(prevTime, true, false);
+ }
+ this._locked = false;
+ if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible)
+ return;
+ }
+ this._time = recTime;
+ this._totalTime = recTotalTime;
+ this._cycle = recCycle;
+ this._rawPrevTime = recRawPrevTime;
+ }
+
+ if ((this._time === prevTime || !this._first) && !force && !internalForce) {
+ if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+ return;
+ } else if (!this._initted) {
+ this._initted = true;
+ }
+
+ if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) {
+ this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
+ }
+
+ if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) {
+ this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
+ }
+
+ if (this._time >= prevTime) {
+ tween = this._first;
+ while (tween) {
+ next = tween._next; //record it here because the value could change after rendering...
+ if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
+ break;
+ } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
+ if (!tween._reversed) {
+ tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
+ } else {
+ tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
+ }
+
+ }
+ tween = next;
+ }
+ } else {
+ tween = this._last;
+ while (tween) {
+ next = tween._prev; //record it here because the value could change after rendering...
+ if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
+ break;
+ } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
+ if (!tween._reversed) {
+ tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
+ } else {
+ tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
+ }
+ }
+ tween = next;
+ }
+ }
+
+ if (this._onUpdate) if (!suppressEvents) {
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+ if (callback) if (!this._locked) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
+ if (isComplete) {
+ if (this._timeline.autoRemoveChildren) {
+ this._enabled(false, false);
+ }
+ this._active = false;
+ }
+ if (!suppressEvents && this.vars[callback]) {
+ this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
+ }
+ }
+ };
+
+ p.getActive = function(nested, tweens, timelines) {
+ if (nested == null) {
+ nested = true;
+ }
+ if (tweens == null) {
+ tweens = true;
+ }
+ if (timelines == null) {
+ timelines = false;
+ }
+ var a = [],
+ all = this.getChildren(nested, tweens, timelines),
+ cnt = 0,
+ l = all.length,
+ i, tween;
+ for (i = 0; i < l; i++) {
+ tween = all[i];
+ if (tween.isActive()) {
+ a[cnt++] = tween;
+ }
+ }
+ return a;
+ };
+
+
+ p.getLabelAfter = function(time) {
+ if (!time) if (time !== 0) { //faster than isNan()
+ time = this._time;
+ }
+ var labels = this.getLabelsArray(),
+ l = labels.length,
+ i;
+ for (i = 0; i < l; i++) {
+ if (labels[i].time > time) {
+ return labels[i].name;
+ }
+ }
+ return null;
+ };
+
+ p.getLabelBefore = function(time) {
+ if (time == null) {
+ time = this._time;
+ }
+ var labels = this.getLabelsArray(),
+ i = labels.length;
+ while (--i > -1) {
+ if (labels[i].time < time) {
+ return labels[i].name;
+ }
+ }
+ return null;
+ };
+
+ p.getLabelsArray = function() {
+ var a = [],
+ cnt = 0,
+ p;
+ for (p in this._labels) {
+ a[cnt++] = {time:this._labels[p], name:p};
+ }
+ a.sort(function(a,b) {
+ return a.time - b.time;
+ });
+ return a;
+ };
+
+
+//---- GETTERS / SETTERS -------------------------------------------------------------------------------------------------------
+
+ p.progress = function(value) {
+ return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
+ };
+
+ p.totalProgress = function(value) {
+ return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
+ };
+
+ p.totalDuration = function(value) {
+ if (!arguments.length) {
+ if (this._dirty) {
+ TimelineLite.prototype.totalDuration.call(this); //just forces refresh
+ //Instead of Infinity, we use 999999999999 so that we can accommodate reverses.
+ this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
+ }
+ return this._totalDuration;
+ }
+ return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
+ };
+
+ p.time = function(value, suppressEvents) {
+ if (!arguments.length) {
+ return this._time;
+ }
+ if (this._dirty) {
+ this.totalDuration();
+ }
+ if (value > this._duration) {
+ value = this._duration;
+ }
+ if (this._yoyo && (this._cycle & 1) !== 0) {
+ value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
+ } else if (this._repeat !== 0) {
+ value += this._cycle * (this._duration + this._repeatDelay);
+ }
+ return this.totalTime(value, suppressEvents);
+ };
+
+ p.repeat = function(value) {
+ if (!arguments.length) {
+ return this._repeat;
+ }
+ this._repeat = value;
+ return this._uncache(true);
+ };
+
+ p.repeatDelay = function(value) {
+ if (!arguments.length) {
+ return this._repeatDelay;
+ }
+ this._repeatDelay = value;
+ return this._uncache(true);
+ };
+
+ p.yoyo = function(value) {
+ if (!arguments.length) {
+ return this._yoyo;
+ }
+ this._yoyo = value;
+ return this;
+ };
+
+ p.currentLabel = function(value) {
+ if (!arguments.length) {
+ return this.getLabelBefore(this._time + 0.00000001);
+ }
+ return this.seek(value, true);
+ };
+
+ return TimelineMax;
+
+ }, true);
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * BezierPlugin
+ * ----------------------------------------------------------------
+ */
+ (function() {
+
+ var _RAD2DEG = 180 / Math.PI,
+ _r1 = [],
+ _r2 = [],
+ _r3 = [],
+ _corProps = {},
+ Segment = function(a, b, c, d) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ this.da = d - a;
+ this.ca = c - a;
+ this.ba = b - a;
+ },
+ _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",
+ cubicToQuadratic = function(a, b, c, d) {
+ var q1 = {a:a},
+ q2 = {},
+ q3 = {},
+ q4 = {c:d},
+ mab = (a + b) / 2,
+ mbc = (b + c) / 2,
+ mcd = (c + d) / 2,
+ mabc = (mab + mbc) / 2,
+ mbcd = (mbc + mcd) / 2,
+ m8 = (mbcd - mabc) / 8;
+ q1.b = mab + (a - mab) / 4;
+ q2.b = mabc + m8;
+ q1.c = q2.a = (q1.b + q2.b) / 2;
+ q2.c = q3.a = (mabc + mbcd) / 2;
+ q3.b = mbcd - m8;
+ q4.b = mcd + (d - mcd) / 4;
+ q3.c = q4.a = (q3.b + q4.b) / 2;
+ return [q1, q2, q3, q4];
+ },
+ _calculateControlPoints = function(a, curviness, quad, basic, correlate) {
+ var l = a.length - 1,
+ ii = 0,
+ cp1 = a[0].a,
+ i, p1, p2, p3, seg, m1, m2, mm, cp2, qb, r1, r2, tl;
+ for (i = 0; i < l; i++) {
+ seg = a[ii];
+ p1 = seg.a;
+ p2 = seg.d;
+ p3 = a[ii+1].d;
+
+ if (correlate) {
+ r1 = _r1[i];
+ r2 = _r2[i];
+ tl = ((r2 + r1) * curviness * 0.25) / (basic ? 0.5 : _r3[i] || 0.5);
+ m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : (r1 !== 0 ? tl / r1 : 0));
+ m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : (r2 !== 0 ? tl / r2 : 0));
+ mm = p2 - (m1 + (((m2 - m1) * ((r1 * 3 / (r1 + r2)) + 0.5) / 4) || 0));
+ } else {
+ m1 = p2 - (p2 - p1) * curviness * 0.5;
+ m2 = p2 + (p3 - p2) * curviness * 0.5;
+ mm = p2 - (m1 + m2) / 2;
+ }
+ m1 += mm;
+ m2 += mm;
+
+ seg.c = cp2 = m1;
+ if (i !== 0) {
+ seg.b = cp1;
+ } else {
+ seg.b = cp1 = seg.a + (seg.c - seg.a) * 0.6; //instead of placing b on a exactly, we move it inline with c so that if the user specifies an ease like Back.easeIn or Elastic.easeIn which goes BEYOND the beginning, it will do so smoothly.
+ }
+
+ seg.da = p2 - p1;
+ seg.ca = cp2 - p1;
+ seg.ba = cp1 - p1;
+
+ if (quad) {
+ qb = cubicToQuadratic(p1, cp1, cp2, p2);
+ a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
+ ii += 4;
+ } else {
+ ii++;
+ }
+
+ cp1 = m2;
+ }
+ seg = a[ii];
+ seg.b = cp1;
+ seg.c = cp1 + (seg.d - cp1) * 0.4; //instead of placing c on d exactly, we move it inline with b so that if the user specifies an ease like Back.easeOut or Elastic.easeOut which goes BEYOND the end, it will do so smoothly.
+ seg.da = seg.d - seg.a;
+ seg.ca = seg.c - seg.a;
+ seg.ba = cp1 - seg.a;
+ if (quad) {
+ qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
+ a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
+ }
+ },
+ _parseAnchors = function(values, p, correlate, prepend) {
+ var a = [],
+ l, i, p1, p2, p3, tmp;
+ if (prepend) {
+ values = [prepend].concat(values);
+ i = values.length;
+ while (--i > -1) {
+ if (typeof( (tmp = values[i][p]) ) === "string") if (tmp.charAt(1) === "=") {
+ values[i][p] = prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)); //accommodate relative values. Do it inline instead of breaking it out into a function for speed reasons
+ }
+ }
+ }
+ l = values.length - 2;
+ if (l < 0) {
+ a[0] = new Segment(values[0][p], 0, 0, values[(l < -1) ? 0 : 1][p]);
+ return a;
+ }
+ for (i = 0; i < l; i++) {
+ p1 = values[i][p];
+ p2 = values[i+1][p];
+ a[i] = new Segment(p1, 0, 0, p2);
+ if (correlate) {
+ p3 = values[i+2][p];
+ _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
+ _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
+ }
+ }
+ a[i] = new Segment(values[i][p], 0, 0, values[i+1][p]);
+ return a;
+ },
+ bezierThrough = function(values, curviness, quadratic, basic, correlate, prepend) {
+ var obj = {},
+ props = [],
+ first = prepend || values[0],
+ i, p, a, j, r, l, seamless, last;
+ correlate = (typeof(correlate) === "string") ? ","+correlate+"," : _correlate;
+ if (curviness == null) {
+ curviness = 1;
+ }
+ for (p in values[0]) {
+ props.push(p);
+ }
+ //check to see if the last and first values are identical (well, within 0.05). If so, make seamless by appending the second element to the very end of the values array and the 2nd-to-last element to the very beginning (we'll remove those segments later)
+ if (values.length > 1) {
+ last = values[values.length - 1];
+ seamless = true;
+ i = props.length;
+ while (--i > -1) {
+ p = props[i];
+ if (Math.abs(first[p] - last[p]) > 0.05) { //build in a tolerance of +/-0.05 to accommodate rounding errors. For example, if you set an object's position to 4.945, Flash will make it 4.9
+ seamless = false;
+ break;
+ }
+ }
+ if (seamless) {
+ values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens
+ if (prepend) {
+ values.unshift(prepend);
+ }
+ values.push(values[1]);
+ prepend = values[values.length - 3];
+ }
+ }
+ _r1.length = _r2.length = _r3.length = 0;
+ i = props.length;
+ while (--i > -1) {
+ p = props[i];
+ _corProps[p] = (correlate.indexOf(","+p+",") !== -1);
+ obj[p] = _parseAnchors(values, p, _corProps[p], prepend);
+ }
+ i = _r1.length;
+ while (--i > -1) {
+ _r1[i] = Math.sqrt(_r1[i]);
+ _r2[i] = Math.sqrt(_r2[i]);
+ }
+ if (!basic) {
+ i = props.length;
+ while (--i > -1) {
+ if (_corProps[p]) {
+ a = obj[props[i]];
+ l = a.length - 1;
+ for (j = 0; j < l; j++) {
+ r = a[j+1].da / _r2[j] + a[j].da / _r1[j];
+ _r3[j] = (_r3[j] || 0) + r * r;
+ }
+ }
+ }
+ i = _r3.length;
+ while (--i > -1) {
+ _r3[i] = Math.sqrt(_r3[i]);
+ }
+ }
+ i = props.length;
+ j = quadratic ? 4 : 1;
+ while (--i > -1) {
+ p = props[i];
+ a = obj[p];
+ _calculateControlPoints(a, curviness, quadratic, basic, _corProps[p]); //this method requires that _parseAnchors() and _setSegmentRatios() ran first so that _r1, _r2, and _r3 values are populated for all properties
+ if (seamless) {
+ a.splice(0, j);
+ a.splice(a.length - j, j);
+ }
+ }
+ return obj;
+ },
+ _parseBezierData = function(values, type, prepend) {
+ type = type || "soft";
+ var obj = {},
+ inc = (type === "cubic") ? 3 : 2,
+ soft = (type === "soft"),
+ props = [],
+ a, b, c, d, cur, i, j, l, p, cnt, tmp;
+ if (soft && prepend) {
+ values = [prepend].concat(values);
+ }
+ if (values == null || values.length < inc + 1) { throw "invalid Bezier data"; }
+ for (p in values[0]) {
+ props.push(p);
+ }
+ i = props.length;
+ while (--i > -1) {
+ p = props[i];
+ obj[p] = cur = [];
+ cnt = 0;
+ l = values.length;
+ for (j = 0; j < l; j++) {
+ a = (prepend == null) ? values[j][p] : (typeof( (tmp = values[j][p]) ) === "string" && tmp.charAt(1) === "=") ? prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)) : Number(tmp);
+ if (soft) if (j > 1) if (j < l - 1) {
+ cur[cnt++] = (a + cur[cnt-2]) / 2;
+ }
+ cur[cnt++] = a;
+ }
+ l = cnt - inc + 1;
+ cnt = 0;
+ for (j = 0; j < l; j += inc) {
+ a = cur[j];
+ b = cur[j+1];
+ c = cur[j+2];
+ d = (inc === 2) ? 0 : cur[j+3];
+ cur[cnt++] = tmp = (inc === 3) ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
+ }
+ cur.length = cnt;
+ }
+ return obj;
+ },
+ _addCubicLengths = function(a, steps, resolution) {
+ var inc = 1 / resolution,
+ j = a.length,
+ d, d1, s, da, ca, ba, p, i, inv, bez, index;
+ while (--j > -1) {
+ bez = a[j];
+ s = bez.a;
+ da = bez.d - s;
+ ca = bez.c - s;
+ ba = bez.b - s;
+ d = d1 = 0;
+ for (i = 1; i <= resolution; i++) {
+ p = inc * i;
+ inv = 1 - p;
+ d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
+ index = j * resolution + i - 1;
+ steps[index] = (steps[index] || 0) + d * d;
+ }
+ }
+ },
+ _parseLengthData = function(obj, resolution) {
+ resolution = resolution >> 0 || 6;
+ var a = [],
+ lengths = [],
+ d = 0,
+ total = 0,
+ threshold = resolution - 1,
+ segments = [],
+ curLS = [], //current length segments array
+ p, i, l, index;
+ for (p in obj) {
+ _addCubicLengths(obj[p], a, resolution);
+ }
+ l = a.length;
+ for (i = 0; i < l; i++) {
+ d += Math.sqrt(a[i]);
+ index = i % resolution;
+ curLS[index] = d;
+ if (index === threshold) {
+ total += d;
+ index = (i / resolution) >> 0;
+ segments[index] = curLS;
+ lengths[index] = total;
+ d = 0;
+ curLS = [];
+ }
+ }
+ return {length:total, lengths:lengths, segments:segments};
+ },
+
+
+
+ BezierPlugin = window._gsDefine.plugin({
+ propName: "bezier",
+ priority: -1,
+ version: "1.3.2",
+ API: 2,
+ global:true,
+
+ //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
+ init: function(target, vars, tween) {
+ this._target = target;
+ if (vars instanceof Array) {
+ vars = {values:vars};
+ }
+ this._func = {};
+ this._round = {};
+ this._props = [];
+ this._timeRes = (vars.timeResolution == null) ? 6 : parseInt(vars.timeResolution, 10);
+ var values = vars.values || [],
+ first = {},
+ second = values[0],
+ autoRotate = vars.autoRotate || tween.vars.orientToBezier,
+ p, isFunc, i, j, prepend;
+
+ this._autoRotate = autoRotate ? (autoRotate instanceof Array) ? autoRotate : [["x","y","rotation",((autoRotate === true) ? 0 : Number(autoRotate) || 0)]] : null;
+ for (p in second) {
+ this._props.push(p);
+ }
+
+ i = this._props.length;
+ while (--i > -1) {
+ p = this._props[i];
+
+ this._overwriteProps.push(p);
+ isFunc = this._func[p] = (typeof(target[p]) === "function");
+ first[p] = (!isFunc) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
+ if (!prepend) if (first[p] !== values[0][p]) {
+ prepend = first;
+ }
+ }
+ this._beziers = (vars.type !== "cubic" && vars.type !== "quadratic" && vars.type !== "soft") ? bezierThrough(values, isNaN(vars.curviness) ? 1 : vars.curviness, false, (vars.type === "thruBasic"), vars.correlate, prepend) : _parseBezierData(values, vars.type, first);
+ this._segCount = this._beziers[p].length;
+
+ if (this._timeRes) {
+ var ld = _parseLengthData(this._beziers, this._timeRes);
+ this._length = ld.length;
+ this._lengths = ld.lengths;
+ this._segments = ld.segments;
+ this._l1 = this._li = this._s1 = this._si = 0;
+ this._l2 = this._lengths[0];
+ this._curSeg = this._segments[0];
+ this._s2 = this._curSeg[0];
+ this._prec = 1 / this._curSeg.length;
+ }
+
+ if ((autoRotate = this._autoRotate)) {
+ this._initialRotations = [];
+ if (!(autoRotate[0] instanceof Array)) {
+ this._autoRotate = autoRotate = [autoRotate];
+ }
+ i = autoRotate.length;
+ while (--i > -1) {
+ for (j = 0; j < 3; j++) {
+ p = autoRotate[i][j];
+ this._func[p] = (typeof(target[p]) === "function") ? target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ] : false;
+ }
+ p = autoRotate[i][2];
+ this._initialRotations[i] = this._func[p] ? this._func[p].call(this._target) : this._target[p];
+ }
+ }
+ this._startRatio = tween.vars.runBackwards ? 1 : 0; //we determine the starting ratio when the tween inits which is always 0 unless the tween has runBackwards:true (indicating it's a from() tween) in which case it's 1.
+ return true;
+ },
+
+ //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
+ set: function(v) {
+ var segments = this._segCount,
+ func = this._func,
+ target = this._target,
+ notStart = (v !== this._startRatio),
+ curIndex, inv, i, p, b, t, val, l, lengths, curSeg;
+ if (!this._timeRes) {
+ curIndex = (v < 0) ? 0 : (v >= 1) ? segments - 1 : (segments * v) >> 0;
+ t = (v - (curIndex * (1 / segments))) * segments;
+ } else {
+ lengths = this._lengths;
+ curSeg = this._curSeg;
+ v *= this._length;
+ i = this._li;
+ //find the appropriate segment (if the currently cached one isn't correct)
+ if (v > this._l2 && i < segments - 1) {
+ l = segments - 1;
+ while (i < l && (this._l2 = lengths[++i]) <= v) { }
+ this._l1 = lengths[i-1];
+ this._li = i;
+ this._curSeg = curSeg = this._segments[i];
+ this._s2 = curSeg[(this._s1 = this._si = 0)];
+ } else if (v < this._l1 && i > 0) {
+ while (i > 0 && (this._l1 = lengths[--i]) >= v) { }
+ if (i === 0 && v < this._l1) {
+ this._l1 = 0;
+ } else {
+ i++;
+ }
+ this._l2 = lengths[i];
+ this._li = i;
+ this._curSeg = curSeg = this._segments[i];
+ this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
+ this._s2 = curSeg[this._si];
+ }
+ curIndex = i;
+ //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one)
+ v -= this._l1;
+ i = this._si;
+ if (v > this._s2 && i < curSeg.length - 1) {
+ l = curSeg.length - 1;
+ while (i < l && (this._s2 = curSeg[++i]) <= v) { }
+ this._s1 = curSeg[i-1];
+ this._si = i;
+ } else if (v < this._s1 && i > 0) {
+ while (i > 0 && (this._s1 = curSeg[--i]) >= v) { }
+ if (i === 0 && v < this._s1) {
+ this._s1 = 0;
+ } else {
+ i++;
+ }
+ this._s2 = curSeg[i];
+ this._si = i;
+ }
+ t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec;
+ }
+ inv = 1 - t;
+
+ i = this._props.length;
+ while (--i > -1) {
+ p = this._props[i];
+ b = this._beziers[p][curIndex];
+ val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
+ if (this._round[p]) {
+ val = Math.round(val);
+ }
+ if (func[p]) {
+ target[p](val);
+ } else {
+ target[p] = val;
+ }
+ }
+
+ if (this._autoRotate) {
+ var ar = this._autoRotate,
+ b2, x1, y1, x2, y2, add, conv;
+ i = ar.length;
+ while (--i > -1) {
+ p = ar[i][2];
+ add = ar[i][3] || 0;
+ conv = (ar[i][4] === true) ? 1 : _RAD2DEG;
+ b = this._beziers[ar[i][0]];
+ b2 = this._beziers[ar[i][1]];
+
+ if (b && b2) { //in case one of the properties got overwritten.
+ b = b[curIndex];
+ b2 = b2[curIndex];
+
+ x1 = b.a + (b.b - b.a) * t;
+ x2 = b.b + (b.c - b.b) * t;
+ x1 += (x2 - x1) * t;
+ x2 += ((b.c + (b.d - b.c) * t) - x2) * t;
+
+ y1 = b2.a + (b2.b - b2.a) * t;
+ y2 = b2.b + (b2.c - b2.b) * t;
+ y1 += (y2 - y1) * t;
+ y2 += ((b2.c + (b2.d - b2.c) * t) - y2) * t;
+
+ val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i];
+
+ if (func[p]) {
+ target[p](val);
+ } else {
+ target[p] = val;
+ }
+ }
+ }
+ }
+ }
+ }),
+ p = BezierPlugin.prototype;
+
+
+ BezierPlugin.bezierThrough = bezierThrough;
+ BezierPlugin.cubicToQuadratic = cubicToQuadratic;
+ BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite
+ BezierPlugin.quadraticToCubic = function(a, b, c) {
+ return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
+ };
+
+ BezierPlugin._cssRegister = function() {
+ var CSSPlugin = window._gsDefine.globals.CSSPlugin;
+ if (!CSSPlugin) {
+ return;
+ }
+ var _internals = CSSPlugin._internals,
+ _parseToProxy = _internals._parseToProxy,
+ _setPluginRatio = _internals._setPluginRatio,
+ CSSPropTween = _internals.CSSPropTween;
+ _internals._registerComplexSpecialProp("bezier", {parser:function(t, e, prop, cssp, pt, plugin) {
+ if (e instanceof Array) {
+ e = {values:e};
+ }
+ plugin = new BezierPlugin();
+ var values = e.values,
+ l = values.length - 1,
+ pluginValues = [],
+ v = {},
+ i, p, data;
+ if (l < 0) {
+ return pt;
+ }
+ for (i = 0; i <= l; i++) {
+ data = _parseToProxy(t, values[i], cssp, pt, plugin, (l !== i));
+ pluginValues[i] = data.end;
+ }
+ for (p in e) {
+ v[p] = e[p]; //duplicate the vars object because we need to alter some things which would cause problems if the user plans to reuse the same vars object for another tween.
+ }
+ v.values = pluginValues;
+ pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2);
+ pt.data = data;
+ pt.plugin = plugin;
+ pt.setRatio = _setPluginRatio;
+ if (v.autoRotate === 0) {
+ v.autoRotate = true;
+ }
+ if (v.autoRotate && !(v.autoRotate instanceof Array)) {
+ i = (v.autoRotate === true) ? 0 : Number(v.autoRotate);
+ v.autoRotate = (data.end.left != null) ? [["left","top","rotation",i,false]] : (data.end.x != null) ? [["x","y","rotation",i,false]] : false;
+ }
+ if (v.autoRotate) {
+ if (!cssp._transform) {
+ cssp._enableTransforms(false);
+ }
+ data.autoRotate = cssp._target._gsTransform;
+ }
+ plugin._onInitTween(data.proxy, v, cssp._tween);
+ return pt;
+ }});
+ };
+
+ p._roundProps = function(lookup, value) {
+ var op = this._overwriteProps,
+ i = op.length;
+ while (--i > -1) {
+ if (lookup[op[i]] || lookup.bezier || lookup.bezierThrough) {
+ this._round[op[i]] = value;
+ }
+ }
+ };
+
+ p._kill = function(lookup) {
+ var a = this._props,
+ p, i;
+ for (p in this._beziers) {
+ if (p in lookup) {
+ delete this._beziers[p];
+ delete this._func[p];
+ i = a.length;
+ while (--i > -1) {
+ if (a[i] === p) {
+ a.splice(i, 1);
+ }
+ }
+ }
+ }
+ return this._super._kill.call(this, lookup);
+ };
+
+ }());
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * CSSPlugin
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin","TweenLite"], function(TweenPlugin, TweenLite) {
+
+ /** @constructor **/
+ var CSSPlugin = function() {
+ TweenPlugin.call(this, "css");
+ this._overwriteProps.length = 0;
+ this.setRatio = CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method)
+ },
+ _hasPriority, //turns true whenever a CSSPropTween instance is created that has a priority other than 0. This helps us discern whether or not we should spend the time organizing the linked list or not after a CSSPlugin's _onInitTween() method is called.
+ _suffixMap, //we set this in _onInitTween() each time as a way to have a persistent variable we can use in other methods like _parse() without having to pass it around as a parameter and we keep _parse() decoupled from a particular CSSPlugin instance
+ _cs, //computed style (we store this in a shared variable to conserve memory and make minification tighter
+ _overwriteProps, //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification.
+ _specialProps = {},
+ p = CSSPlugin.prototype = new TweenPlugin("css");
+
+ p.constructor = CSSPlugin;
+ CSSPlugin.version = "1.12.1";
+ CSSPlugin.API = 2;
+ CSSPlugin.defaultTransformPerspective = 0;
+ CSSPlugin.defaultSkewType = "compensated";
+ p = "px"; //we'll reuse the "p" variable to keep file size down
+ CSSPlugin.suffixMap = {top:p, right:p, bottom:p, left:p, width:p, height:p, fontSize:p, padding:p, margin:p, perspective:p, lineHeight:""};
+
+
+ var _numExp = /(?:\d|\-\d|\.\d|\-\.\d)+/g,
+ _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
+ _valuesExp = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, //finds all the values that begin with numbers or += or -= and then a number. Includes suffixes. We use this to split complex values apart like "1px 5px 20px rgb(255,102,51)"
+ _NaNExp = /[^\d\-\.]/g,
+ _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
+ _opacityExp = /opacity *= *([^)]*)/i,
+ _opacityValExp = /opacity:([^;]*)/i,
+ _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
+ _rgbhslExp = /^(rgb|hsl)/,
+ _capsExp = /([A-Z])/g,
+ _camelExp = /-([a-z])/gi,
+ _urlExp = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, //for pulling out urls from url(...) or url("...") strings (some browsers wrap urls in quotes, some don't when reporting things like backgroundImage)
+ _camelFunc = function(s, g) { return g.toUpperCase(); },
+ _horizExp = /(?:Left|Right|Width)/i,
+ _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi,
+ _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,
+ _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, //finds any commas that are not within parenthesis
+ _DEG2RAD = Math.PI / 180,
+ _RAD2DEG = 180 / Math.PI,
+ _forcePT = {},
+ _doc = document,
+ _tempDiv = _doc.createElement("div"),
+ _tempImg = _doc.createElement("img"),
+ _internals = CSSPlugin._internals = {_specialProps:_specialProps}, //provides a hook to a few internal methods that we need to access from inside other plugins
+ _agent = navigator.userAgent,
+ _autoRound,
+ _reqSafariFix, //we won't apply the Safari transform fix until we actually come across a tween that affects a transform property (to maintain best performance).
+
+ _isSafari,
+ _isFirefox, //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element.
+ _isSafariLT6, //Safari (and Android 4 which uses a flavor of Safari) has a bug that prevents changes to "top" and "left" properties from rendering properly if changed on the same frame as a transform UNLESS we set the element's WebkitBackfaceVisibility to hidden (weird, I know). Doing this for Android 3 and earlier seems to actually cause other problems, though (fun!)
+ _ieVers,
+ _supportsOpacity = (function() { //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version.
+ var i = _agent.indexOf("Android"),
+ d = _doc.createElement("div"), a;
+
+ _isSafari = (_agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || Number(_agent.substr(i+8, 1)) > 3));
+ _isSafariLT6 = (_isSafari && (Number(_agent.substr(_agent.indexOf("Version/")+8, 1)) < 6));
+ _isFirefox = (_agent.indexOf("Firefox") !== -1);
+
+ if ((/MSIE ([0-9]{1,}[\.0-9]{0,})/).exec(_agent)) {
+ _ieVers = parseFloat( RegExp.$1 );
+ }
+
+ d.innerHTML = "<a title='' style='top:1px;opacity:.55;'>a</a>";
+ a = d.getElementsByTagName("a")[0];
+ return a ? /^0.55/.test(a.style.opacity) : false;
+ }()),
+ _getIEOpacity = function(v) {
+ return (_opacityExp.test( ((typeof(v) === "string") ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ) ? ( parseFloat( RegExp.$1 ) / 100 ) : 1);
+ },
+ _log = function(s) {//for logging messages, but in a way that won't throw errors in old versions of IE.
+ if (window.console) {
+ //console.log(s);
+ }
+ },
+ _prefixCSS = "", //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-"
+ _prefix = "", //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz".
+
+ // @private feed in a camelCase property name like "transform" and it will check to see if it is valid as-is or if it needs a vendor prefix. It returns the corrected camelCase property name (i.e. "WebkitTransform" or "MozTransform" or "transform" or null if no such property is found, like if the browser is IE8 or before, "transform" won't be found at all)
+ _checkPropPrefix = function(p, e) {
+ e = e || _tempDiv;
+ var s = e.style,
+ a, i;
+ if (s[p] !== undefined) {
+ return p;
+ }
+ p = p.charAt(0).toUpperCase() + p.substr(1);
+ a = ["O","Moz","ms","Ms","Webkit"];
+ i = 5;
+ while (--i > -1 && s[a[i]+p] === undefined) { }
+ if (i >= 0) {
+ _prefix = (i === 3) ? "ms" : a[i];
+ _prefixCSS = "-" + _prefix.toLowerCase() + "-";
+ return _prefix + p;
+ }
+ return null;
+ },
+
+ _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function() {},
+
+ /**
+ * @private Returns the css style for a particular property of an element. For example, to get whatever the current "left" css value for an element with an ID of "myElement", you could do:
+ * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left");
+ *
+ * @param {!Object} t Target element whose style property you want to query
+ * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.)
+ * @param {Object=} cs Computed style object. This just provides a way to speed processing if you're going to get several properties on the same element in quick succession - you can reuse the result of the getComputedStyle() call.
+ * @param {boolean=} calc If true, the value will not be read directly from the element's "style" property (if it exists there), but instead the getComputedStyle() result will be used. This can be useful when you want to ensure that the browser itself is interpreting the value.
+ * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto".
+ * @return {?string} The current property value
+ */
+ _getStyle = CSSPlugin.getStyle = function(t, p, cs, calc, dflt) {
+ var rv;
+ if (!_supportsOpacity) if (p === "opacity") { //several versions of IE don't use the standard "opacity" property - they use things like filter:alpha(opacity=50), so we parse that here.
+ return _getIEOpacity(t);
+ }
+ if (!calc && t.style[p]) {
+ rv = t.style[p];
+ } else if ((cs = cs || _getComputedStyle(t))) {
+ rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
+ } else if (t.currentStyle) {
+ rv = t.currentStyle[p];
+ }
+ return (dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto")) ? dflt : rv;
+ },
+
+ /**
+ * @private Pass the target element, the property name, the numeric value, and the suffix (like "%", "em", "px", etc.) and it will spit back the equivalent pixel number.
+ * @param {!Object} t Target element
+ * @param {!string} p Property name (like "left", "top", "marginLeft", etc.)
+ * @param {!number} v Value
+ * @param {string=} sfx Suffix (like "px" or "%" or "em")
+ * @param {boolean=} recurse If true, the call is a recursive one. In some browsers (like IE7/8), occasionally the value isn't accurately reported initially, but if we run the function again it will take effect.
+ * @return {number} value in pixels
+ */
+ _convertToPixels = _internals.convertToPixels = function(t, p, v, sfx, recurse) {
+ if (sfx === "px" || !sfx) { return v; }
+ if (sfx === "auto" || !v) { return 0; }
+ var horiz = _horizExp.test(p),
+ node = t,
+ style = _tempDiv.style,
+ neg = (v < 0),
+ pix, cache, time;
+ if (neg) {
+ v = -v;
+ }
+ if (sfx === "%" && p.indexOf("border") !== -1) {
+ pix = (v / 100) * (horiz ? t.clientWidth : t.clientHeight);
+ } else {
+ style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;";
+ if (sfx === "%" || !node.appendChild) {
+ node = t.parentNode || _doc.body;
+ cache = node._gsCache;
+ time = TweenLite.ticker.frame;
+ if (cache && horiz && cache.time === time) { //performance optimization: we record the width of elements along with the ticker frame so that we can quickly get it again on the same tick (seems relatively safe to assume it wouldn't change on the same tick)
+ return cache.width * v / 100;
+ }
+ style[(horiz ? "width" : "height")] = v + sfx;
+ } else {
+ style[(horiz ? "borderLeftWidth" : "borderTopWidth")] = v + sfx;
+ }
+ node.appendChild(_tempDiv);
+ pix = parseFloat(_tempDiv[(horiz ? "offsetWidth" : "offsetHeight")]);
+ node.removeChild(_tempDiv);
+ if (horiz && sfx === "%" && CSSPlugin.cacheWidths !== false) {
+ cache = node._gsCache = node._gsCache || {};
+ cache.time = time;
+ cache.width = pix / v * 100;
+ }
+ if (pix === 0 && !recurse) {
+ pix = _convertToPixels(t, p, v, sfx, true);
+ }
+ }
+ return neg ? -pix : pix;
+ },
+ _calculateOffset = _internals.calculateOffset = function(t, p, cs) { //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop
+ if (_getStyle(t, "position", cs) !== "absolute") { return 0; }
+ var dim = ((p === "left") ? "Left" : "Top"),
+ v = _getStyle(t, "margin" + dim, cs);
+ return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0);
+ },
+
+ // @private returns at object containing ALL of the style properties in camelCase and their associated values.
+ _getAllStyles = function(t, cs) {
+ var s = {},
+ i, tr;
+ if ((cs = cs || _getComputedStyle(t, null))) {
+ if ((i = cs.length)) {
+ while (--i > -1) {
+ s[cs[i].replace(_camelExp, _camelFunc)] = cs.getPropertyValue(cs[i]);
+ }
+ } else { //Opera behaves differently - cs.length is always 0, so we must do a for...in loop.
+ for (i in cs) {
+ s[i] = cs[i];
+ }
+ }
+ } else if ((cs = t.currentStyle || t.style)) {
+ for (i in cs) {
+ if (typeof(i) === "string" && s[i] === undefined) {
+ s[i.replace(_camelExp, _camelFunc)] = cs[i];
+ }
+ }
+ }
+ if (!_supportsOpacity) {
+ s.opacity = _getIEOpacity(t);
+ }
+ tr = _getTransform(t, cs, false);
+ s.rotation = tr.rotation;
+ s.skewX = tr.skewX;
+ s.scaleX = tr.scaleX;
+ s.scaleY = tr.scaleY;
+ s.x = tr.x;
+ s.y = tr.y;
+ if (_supports3D) {
+ s.z = tr.z;
+ s.rotationX = tr.rotationX;
+ s.rotationY = tr.rotationY;
+ s.scaleZ = tr.scaleZ;
+ }
+ if (s.filters) {
+ delete s.filters;
+ }
+ return s;
+ },
+
+ // @private analyzes two style objects (as returned by _getAllStyles()) and only looks for differences between them that contain tweenable values (like a number or color). It returns an object with a "difs" property which refers to an object containing only those isolated properties and values for tweening, and a "firstMPT" property which refers to the first MiniPropTween instance in a linked list that recorded all the starting values of the different properties so that we can revert to them at the end or beginning of the tween - we don't want the cascading to get messed up. The forceLookup parameter is an optional generic object with properties that should be forced into the results - this is necessary for className tweens that are overwriting others because imagine a scenario where a rollover/rollout adds/removes a class and the user swipes the mouse over the target SUPER fast, thus nothing actually changed yet and the subsequent comparison of the properties would indicate they match (especially when px rounding is taken into consideration), thus no tweening is necessary even though it SHOULD tween and remove those properties after the tween (otherwise the inline styles will contaminate things). See the className SpecialProp code for details.
+ _cssDif = function(t, s1, s2, vars, forceLookup) {
+ var difs = {},
+ style = t.style,
+ val, p, mpt;
+ for (p in s2) {
+ if (p !== "cssText") if (p !== "length") if (isNaN(p)) if (s1[p] !== (val = s2[p]) || (forceLookup && forceLookup[p])) if (p.indexOf("Origin") === -1) if (typeof(val) === "number" || typeof(val) === "string") {
+ difs[p] = (val === "auto" && (p === "left" || p === "top")) ? _calculateOffset(t, p) : ((val === "" || val === "auto" || val === "none") && typeof(s1[p]) === "string" && s1[p].replace(_NaNExp, "") !== "") ? 0 : val; //if the ending value is defaulting ("" or "auto"), we check the starting value and if it can be parsed into a number (a string which could have a suffix too, like 700px), then we swap in 0 for "" or "auto" so that things actually tween.
+ if (style[p] !== undefined) { //for className tweens, we must remember which properties already existed inline - the ones that didn't should be removed when the tween isn't in progress because they were only introduced to facilitate the transition between classes.
+ mpt = new MiniPropTween(style, p, style[p], mpt);
+ }
+ }
+ }
+ if (vars) {
+ for (p in vars) { //copy properties (except className)
+ if (p !== "className") {
+ difs[p] = vars[p];
+ }
+ }
+ }
+ return {difs:difs, firstMPT:mpt};
+ },
+ _dimensions = {width:["Left","Right"], height:["Top","Bottom"]},
+ _margins = ["marginLeft","marginRight","marginTop","marginBottom"],
+
+ /**
+ * @private Gets the width or height of an element
+ * @param {!Object} t Target element
+ * @param {!string} p Property name ("width" or "height")
+ * @param {Object=} cs Computed style object (if one exists). Just a speed optimization.
+ * @return {number} Dimension (in pixels)
+ */
+ _getDimension = function(t, p, cs) {
+ var v = parseFloat((p === "width") ? t.offsetWidth : t.offsetHeight),
+ a = _dimensions[p],
+ i = a.length;
+ cs = cs || _getComputedStyle(t, null);
+ while (--i > -1) {
+ v -= parseFloat( _getStyle(t, "padding" + a[i], cs, true) ) || 0;
+ v -= parseFloat( _getStyle(t, "border" + a[i] + "Width", cs, true) ) || 0;
+ }
+ return v;
+ },
+
+ // @private Parses position-related complex strings like "top left" or "50px 10px" or "70% 20%", etc. which are used for things like transformOrigin or backgroundPosition. Optionally decorates a supplied object (recObj) with the following properties: "ox" (offsetX), "oy" (offsetY), "oxp" (if true, "ox" is a percentage not a pixel value), and "oxy" (if true, "oy" is a percentage not a pixel value)
+ _parsePosition = function(v, recObj) {
+ if (v == null || v === "" || v === "auto" || v === "auto auto") { //note: Firefox uses "auto auto" as default whereas Chrome uses "auto".
+ v = "0 0";
+ }
+ var a = v.split(" "),
+ x = (v.indexOf("left") !== -1) ? "0%" : (v.indexOf("right") !== -1) ? "100%" : a[0],
+ y = (v.indexOf("top") !== -1) ? "0%" : (v.indexOf("bottom") !== -1) ? "100%" : a[1];
+ if (y == null) {
+ y = "0";
+ } else if (y === "center") {
+ y = "50%";
+ }
+ if (x === "center" || (isNaN(parseFloat(x)) && (x + "").indexOf("=") === -1)) { //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it could be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative.
+ x = "50%";
+ }
+ if (recObj) {
+ recObj.oxp = (x.indexOf("%") !== -1);
+ recObj.oyp = (y.indexOf("%") !== -1);
+ recObj.oxr = (x.charAt(1) === "=");
+ recObj.oyr = (y.charAt(1) === "=");
+ recObj.ox = parseFloat(x.replace(_NaNExp, ""));
+ recObj.oy = parseFloat(y.replace(_NaNExp, ""));
+ }
+ return x + " " + y + ((a.length > 2) ? " " + a[2] : "");
+ },
+
+ /**
+ * @private Takes an ending value (typically a string, but can be a number) and a starting value and returns the change between the two, looking for relative value indicators like += and -= and it also ignores suffixes (but make sure the ending value starts with a number or +=/-= and that the starting value is a NUMBER!)
+ * @param {(number|string)} e End value which is typically a string, but could be a number
+ * @param {(number|string)} b Beginning value which is typically a string but could be a number
+ * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized)
+ */
+ _parseChange = function(e, b) {
+ return (typeof(e) === "string" && e.charAt(1) === "=") ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b);
+ },
+
+ /**
+ * @private Takes a value and a default number, checks if the value is relative, null, or numeric and spits back a normalized number accordingly. Primarily used in the _parseTransform() function.
+ * @param {Object} v Value to be parsed
+ * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
+ * @return {number} Parsed value
+ */
+ _parseVal = function(v, d) {
+ return (v == null) ? d : (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) + d : parseFloat(v);
+ },
+
+ /**
+ * @private Translates strings like "40deg" or "40" or 40rad" or "+=40deg" or "270_short" or "-90_cw" or "+=45_ccw" to a numeric radian angle. Of course a starting/default value must be fed in too so that relative values can be calculated properly.
+ * @param {Object} v Value to be parsed
+ * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
+ * @param {string=} p property name for directionalEnd (optional - only used when the parsed value is directional ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation). Property name would be "rotation", "rotationX", or "rotationY"
+ * @param {Object=} directionalEnd An object that will store the raw end values for directional angles ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation.
+ * @return {number} parsed angle in radians
+ */
+ _parseAngle = function(v, d, p, directionalEnd) {
+ var min = 0.000001,
+ cap, split, dif, result;
+ if (v == null) {
+ result = d;
+ } else if (typeof(v) === "number") {
+ result = v;
+ } else {
+ cap = 360;
+ split = v.split("_");
+ dif = Number(split[0].replace(_NaNExp, "")) * ((v.indexOf("rad") === -1) ? 1 : _RAD2DEG) - ((v.charAt(1) === "=") ? 0 : d);
+ if (split.length) {
+ if (directionalEnd) {
+ directionalEnd[p] = d + dif;
+ }
+ if (v.indexOf("short") !== -1) {
+ dif = dif % cap;
+ if (dif !== dif % (cap / 2)) {
+ dif = (dif < 0) ? dif + cap : dif - cap;
+ }
+ }
+ if (v.indexOf("_cw") !== -1 && dif < 0) {
+ dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
+ } else if (v.indexOf("ccw") !== -1 && dif > 0) {
+ dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
+ }
+ }
+ result = d + dif;
+ }
+ if (result < min && result > -min) {
+ result = 0;
+ }
+ return result;
+ },
+
+ _colorLookup = {aqua:[0,255,255],
+ lime:[0,255,0],
+ silver:[192,192,192],
+ black:[0,0,0],
+ maroon:[128,0,0],
+ teal:[0,128,128],
+ blue:[0,0,255],
+ navy:[0,0,128],
+ white:[255,255,255],
+ fuchsia:[255,0,255],
+ olive:[128,128,0],
+ yellow:[255,255,0],
+ orange:[255,165,0],
+ gray:[128,128,128],
+ purple:[128,0,128],
+ green:[0,128,0],
+ red:[255,0,0],
+ pink:[255,192,203],
+ cyan:[0,255,255],
+ transparent:[255,255,255,0]},
+
+ _hue = function(h, m1, m2) {
+ h = (h < 0) ? h + 1 : (h > 1) ? h - 1 : h;
+ return ((((h * 6 < 1) ? m1 + (m2 - m1) * h * 6 : (h < 0.5) ? m2 : (h * 3 < 2) ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * 255) + 0.5) | 0;
+ },
+
+ /**
+ * @private Parses a color (like #9F0, #FF9900, or rgb(255,51,153)) into an array with 3 elements for red, green, and blue. Also handles rgba() values (splits into array of 4 elements of course)
+ * @param {(string|number)} v The value the should be parsed which could be a string like #9F0 or rgb(255,102,51) or rgba(255,0,0,0.5) or it could be a number like 0xFF00CC or even a named color like red, blue, purple, etc.
+ * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order.
+ */
+ _parseColor = function(v) {
+ var c1, c2, c3, h, s, l;
+ if (!v || v === "") {
+ return _colorLookup.black;
+ }
+ if (typeof(v) === "number") {
+ return [v >> 16, (v >> 8) & 255, v & 255];
+ }
+ if (v.charAt(v.length - 1) === ",") { //sometimes a trailing commma is included and we should chop it off (typically from a comma-delimited list of values like a textShadow:"2px 2px 2px blue, 5px 5px 5px rgb(255,0,0)" - in this example "blue," has a trailing comma. We could strip it out inside parseComplex() but we'd need to do it to the beginning and ending values plus it wouldn't provide protection from other potential scenarios like if the user passes in a similar value.
+ v = v.substr(0, v.length - 1);
+ }
+ if (_colorLookup[v]) {
+ return _colorLookup[v];
+ }
+ if (v.charAt(0) === "#") {
+ if (v.length === 4) { //for shorthand like #9F0
+ c1 = v.charAt(1),
+ c2 = v.charAt(2),
+ c3 = v.charAt(3);
+ v = "#" + c1 + c1 + c2 + c2 + c3 + c3;
+ }
+ v = parseInt(v.substr(1), 16);
+ return [v >> 16, (v >> 8) & 255, v & 255];
+ }
+ if (v.substr(0, 3) === "hsl") {
+ v = v.match(_numExp);
+ h = (Number(v[0]) % 360) / 360;
+ s = Number(v[1]) / 100;
+ l = Number(v[2]) / 100;
+ c2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
+ c1 = l * 2 - c2;
+ if (v.length > 3) {
+ v[3] = Number(v[3]);
+ }
+ v[0] = _hue(h + 1 / 3, c1, c2);
+ v[1] = _hue(h, c1, c2);
+ v[2] = _hue(h - 1 / 3, c1, c2);
+ return v;
+ }
+ v = v.match(_numExp) || _colorLookup.transparent;
+ v[0] = Number(v[0]);
+ v[1] = Number(v[1]);
+ v[2] = Number(v[2]);
+ if (v.length > 3) {
+ v[3] = Number(v[3]);
+ }
+ return v;
+ },
+ _colorExp = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#.+?\\b"; //we'll dynamically build this Regular Expression to conserve file size. After building it, it will be able to find rgb(), rgba(), # (hexadecimal), and named color values like red, blue, purple, etc.
+
+ for (p in _colorLookup) {
+ _colorExp += "|" + p + "\\b";
+ }
+ _colorExp = new RegExp(_colorExp+")", "gi");
+
+ /**
+ * @private Returns a formatter function that handles taking a string (or number in some cases) and returning a consistently formatted one in terms of delimiters, quantity of values, etc. For example, we may get boxShadow values defined as "0px red" or "0px 0px 10px rgb(255,0,0)" or "0px 0px 20px 20px #F00" and we need to ensure that what we get back is described with 4 numbers and a color. This allows us to feed it into the _parseComplex() method and split the values up appropriately. The neat thing about this _getFormatter() function is that the dflt defines a pattern as well as a default, so for example, _getFormatter("0px 0px 0px 0px #777", true) not only sets the default as 0px for all distances and #777 for the color, but also sets the pattern such that 4 numbers and a color will always get returned.
+ * @param {!string} dflt The default value and pattern to follow. So "0px 0px 0px 0px #777" will ensure that 4 numbers and a color will always get returned.
+ * @param {boolean=} clr If true, the values should be searched for color-related data. For example, boxShadow values typically contain a color whereas borderRadius don't.
+ * @param {boolean=} collapsible If true, the value is a top/left/right/bottom style one that acts like margin or padding, where if only one value is received, it's used for all 4; if 2 are received, the first is duplicated for 3rd (bottom) and the 2nd is duplicated for the 4th spot (left), etc.
+ * @return {Function} formatter function
+ */
+ var _getFormatter = function(dflt, clr, collapsible, multi) {
+ if (dflt == null) {
+ return function(v) {return v;};
+ }
+ var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "",
+ dVals = dflt.split(dColor).join("").match(_valuesExp) || [],
+ pfx = dflt.substr(0, dflt.indexOf(dVals[0])),
+ sfx = (dflt.charAt(dflt.length - 1) === ")") ? ")" : "",
+ delim = (dflt.indexOf(" ") !== -1) ? " " : ",",
+ numVals = dVals.length,
+ dSfx = (numVals > 0) ? dVals[0].replace(_numExp, "") : "",
+ formatter;
+ if (!numVals) {
+ return function(v) {return v;};
+ }
+ if (clr) {
+ formatter = function(v) {
+ var color, vals, i, a;
+ if (typeof(v) === "number") {
+ v += dSfx;
+ } else if (multi && _commasOutsideParenExp.test(v)) {
+ a = v.replace(_commasOutsideParenExp, "|").split("|");
+ for (i = 0; i < a.length; i++) {
+ a[i] = formatter(a[i]);
+ }
+ return a.join(",");
+ }
+ color = (v.match(_colorExp) || [dColor])[0];
+ vals = v.split(color).join("").match(_valuesExp) || [];
+ i = vals.length;
+ if (numVals > i--) {
+ while (++i < numVals) {
+ vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
+ }
+ }
+ return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : "");
+ };
+ return formatter;
+
+ }
+ formatter = function(v) {
+ var vals, a, i;
+ if (typeof(v) === "number") {
+ v += dSfx;
+ } else if (multi && _commasOutsideParenExp.test(v)) {
+ a = v.replace(_commasOutsideParenExp, "|").split("|");
+ for (i = 0; i < a.length; i++) {
+ a[i] = formatter(a[i]);
+ }
+ return a.join(",");
+ }
+ vals = v.match(_valuesExp) || [];
+ i = vals.length;
+ if (numVals > i--) {
+ while (++i < numVals) {
+ vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
+ }
+ }
+ return pfx + vals.join(delim) + sfx;
+ };
+ return formatter;
+ },
+
+ /**
+ * @private returns a formatter function that's used for edge-related values like marginTop, marginLeft, paddingBottom, paddingRight, etc. Just pass a comma-delimited list of property names related to the edges.
+ * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft"
+ * @return {Function} a formatter function
+ */
+ _getEdgeParser = function(props) {
+ props = props.split(",");
+ return function(t, e, p, cssp, pt, plugin, vars) {
+ var a = (e + "").split(" "),
+ i;
+ vars = {};
+ for (i = 0; i < 4; i++) {
+ vars[props[i]] = a[i] = a[i] || a[(((i - 1) / 2) >> 0)];
+ }
+ return cssp.parse(t, vars, pt, plugin);
+ };
+ },
+
+ // @private used when other plugins must tween values first, like BezierPlugin or ThrowPropsPlugin, etc. That plugin's setRatio() gets called first so that the values are updated, and then we loop through the MiniPropTweens which handle copying the values into their appropriate slots so that they can then be applied correctly in the main CSSPlugin setRatio() method. Remember, we typically create a proxy object that has a bunch of uniquely-named properties that we feed to the sub-plugin and it does its magic normally, and then we must interpret those values and apply them to the css because often numbers must get combined/concatenated, suffixes added, etc. to work with css, like boxShadow could have 4 values plus a color.
+ _setPluginRatio = _internals._setPluginRatio = function(v) {
+ this.plugin.setRatio(v);
+ var d = this.data,
+ proxy = d.proxy,
+ mpt = d.firstMPT,
+ min = 0.000001,
+ val, pt, i, str;
+ while (mpt) {
+ val = proxy[mpt.v];
+ if (mpt.r) {
+ val = Math.round(val);
+ } else if (val < min && val > -min) {
+ val = 0;
+ }
+ mpt.t[mpt.p] = val;
+ mpt = mpt._next;
+ }
+ if (d.autoRotate) {
+ d.autoRotate.rotation = proxy.rotation;
+ }
+ //at the end, we must set the CSSPropTween's "e" (end) value dynamically here because that's what is used in the final setRatio() method.
+ if (v === 1) {
+ mpt = d.firstMPT;
+ while (mpt) {
+ pt = mpt.t;
+ if (!pt.type) {
+ pt.e = pt.s + pt.xs0;
+ } else if (pt.type === 1) {
+ str = pt.xs0 + pt.s + pt.xs1;
+ for (i = 1; i < pt.l; i++) {
+ str += pt["xn"+i] + pt["xs"+(i+1)];
+ }
+ pt.e = str;
+ }
+ mpt = mpt._next;
+ }
+ }
+ },
+
+ /**
+ * @private @constructor Used by a few SpecialProps to hold important values for proxies. For example, _parseToProxy() creates a MiniPropTween instance for each property that must get tweened on the proxy, and we record the original property name as well as the unique one we create for the proxy, plus whether or not the value needs to be rounded plus the original value.
+ * @param {!Object} t target object whose property we're tweening (often a CSSPropTween)
+ * @param {!string} p property name
+ * @param {(number|string|object)} v value
+ * @param {MiniPropTween=} next next MiniPropTween in the linked list
+ * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer
+ */
+ MiniPropTween = function(t, p, v, next, r) {
+ this.t = t;
+ this.p = p;
+ this.v = v;
+ this.r = r;
+ if (next) {
+ next._prev = this;
+ this._next = next;
+ }
+ },
+
+ /**
+ * @private Most other plugins (like BezierPlugin and ThrowPropsPlugin and others) can only tween numeric values, but CSSPlugin must accommodate special values that have a bunch of extra data (like a suffix or strings between numeric values, etc.). For example, boxShadow has values like "10px 10px 20px 30px rgb(255,0,0)" which would utterly confuse other plugins. This method allows us to split that data apart and grab only the numeric data and attach it to uniquely-named properties of a generic proxy object ({}) so that we can feed that to virtually any plugin to have the numbers tweened. However, we must also keep track of which properties from the proxy go with which CSSPropTween values and instances. So we create a linked list of MiniPropTweens. Each one records a target (the original CSSPropTween), property (like "s" or "xn1" or "xn2") that we're tweening and the unique property name that was used for the proxy (like "boxShadow_xn1" and "boxShadow_xn2") and whether or not they need to be rounded. That way, in the _setPluginRatio() method we can simply copy the values over from the proxy to the CSSPropTween instance(s). Then, when the main CSSPlugin setRatio() method runs and applies the CSSPropTween values accordingly, they're updated nicely. So the external plugin tweens the numbers, _setPluginRatio() copies them over, and setRatio() acts normally, applying css-specific values to the element.
+ * This method returns an object that has the following properties:
+ * - proxy: a generic object containing the starting values for all the properties that will be tweened by the external plugin. This is what we feed to the external _onInitTween() as the target
+ * - end: a generic object containing the ending values for all the properties that will be tweened by the external plugin. This is what we feed to the external plugin's _onInitTween() as the destination values
+ * - firstMPT: the first MiniPropTween in the linked list
+ * - pt: the first CSSPropTween in the linked list that was created when parsing. If shallow is true, this linked list will NOT attach to the one passed into the _parseToProxy() as the "pt" (4th) parameter.
+ * @param {!Object} t target object to be tweened
+ * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed
+ * @param {!CSSPlugin} cssp The CSSPlugin instance
+ * @param {CSSPropTween=} pt the next CSSPropTween in the linked list
+ * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values
+ * @param {boolean=} shallow if true, the resulting linked list from the parse will NOT be attached to the CSSPropTween that was passed in as the "pt" (4th) parameter.
+ * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions)
+ */
+ _parseToProxy = _internals._parseToProxy = function(t, vars, cssp, pt, plugin, shallow) {
+ var bpt = pt,
+ start = {},
+ end = {},
+ transform = cssp._transform,
+ oldForce = _forcePT,
+ i, p, xp, mpt, firstPT;
+ cssp._transform = null;
+ _forcePT = vars;
+ pt = firstPT = cssp.parse(t, vars, pt, plugin);
+ _forcePT = oldForce;
+ //break off from the linked list so the new ones are isolated.
+ if (shallow) {
+ cssp._transform = transform;
+ if (bpt) {
+ bpt._prev = null;
+ if (bpt._prev) {
+ bpt._prev._next = null;
+ }
+ }
+ }
+ while (pt && pt !== bpt) {
+ if (pt.type <= 1) {
+ p = pt.p;
+ end[p] = pt.s + pt.c;
+ start[p] = pt.s;
+ if (!shallow) {
+ mpt = new MiniPropTween(pt, "s", p, mpt, pt.r);
+ pt.c = 0;
+ }
+ if (pt.type === 1) {
+ i = pt.l;
+ while (--i > 0) {
+ xp = "xn" + i;
+ p = pt.p + "_" + xp;
+ end[p] = pt.data[xp];
+ start[p] = pt[xp];
+ if (!shallow) {
+ mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]);
+ }
+ }
+ }
+ }
+ pt = pt._next;
+ }
+ return {proxy:start, end:end, firstMPT:mpt, pt:firstPT};
+ },
+
+
+
+ /**
+ * @constructor Each property that is tweened has at least one CSSPropTween associated with it. These instances store important information like the target, property, starting value, amount of change, etc. They can also optionally have a number of "extra" strings and numeric values named xs1, xn1, xs2, xn2, xs3, xn3, etc. where "s" indicates string and "n" indicates number. These can be pieced together in a complex-value tween (type:1) that has alternating types of data like a string, number, string, number, etc. For example, boxShadow could be "5px 5px 8px rgb(102, 102, 51)". In that value, there are 6 numbers that may need to tween and then pieced back together into a string again with spaces, suffixes, etc. xs0 is special in that it stores the suffix for standard (type:0) tweens, -OR- the first string (prefix) in a complex-value (type:1) CSSPropTween -OR- it can be the non-tweening value in a type:-1 CSSPropTween. We do this to conserve memory.
+ * CSSPropTweens have the following optional properties as well (not defined through the constructor):
+ * - l: Length in terms of the number of extra properties that the CSSPropTween has (default: 0). For example, for a boxShadow we may need to tween 5 numbers in which case l would be 5; Keep in mind that the start/end values for the first number that's tweened are always stored in the s and c properties to conserve memory. All additional values thereafter are stored in xn1, xn2, etc.
+ * - xfirst: The first instance of any sub-CSSPropTweens that are tweening properties of this instance. For example, we may split up a boxShadow tween so that there's a main CSSPropTween of type:1 that has various xs* and xn* values associated with the h-shadow, v-shadow, blur, color, etc. Then we spawn a CSSPropTween for each of those that has a higher priority and runs BEFORE the main CSSPropTween so that the values are all set by the time it needs to re-assemble them. The xfirst gives us an easy way to identify the first one in that chain which typically ends at the main one (because they're all prepende to the linked list)
+ * - plugin: The TweenPlugin instance that will handle the tweening of any complex values. For example, sometimes we don't want to use normal subtweens (like xfirst refers to) to tween the values - we might want ThrowPropsPlugin or BezierPlugin some other plugin to do the actual tweening, so we create a plugin instance and store a reference here. We need this reference so that if we get a request to round values or disable a tween, we can pass along that request.
+ * - data: Arbitrary data that needs to be stored with the CSSPropTween. Typically if we're going to have a plugin handle the tweening of a complex-value tween, we create a generic object that stores the END values that we're tweening to and the CSSPropTween's xs1, xs2, etc. have the starting values. We store that object as data. That way, we can simply pass that object to the plugin and use the CSSPropTween as the target.
+ * - setRatio: Only used for type:2 tweens that require custom functionality. In this case, we call the CSSPropTween's setRatio() method and pass the ratio each time the tween updates. This isn't quite as efficient as doing things directly in the CSSPlugin's setRatio() method, but it's very convenient and flexible.
+ * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything.
+ * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width".
+ * @param {number} s Starting numeric value
+ * @param {number} c Change in numeric value over the course of the entire tween. For example, if element.width starts at 5 and should end at 100, c would be 95.
+ * @param {CSSPropTween=} next The next CSSPropTween in the linked list. If one is defined, we will define its _prev as the new instance, and the new instance's _next will be pointed at it.
+ * @param {number=} type The type of CSSPropTween where -1 = a non-tweening value, 0 = a standard simple tween, 1 = a complex value (like one that has multiple numbers in a comma- or space-delimited string like border:"1px solid red"), and 2 = one that uses a custom setRatio function that does all of the work of applying the values on each update.
+ * @param {string=} n Name of the property that should be used for overwriting purposes which is typically the same as p but not always. For example, we may need to create a subtween for the 2nd part of a "clip:rect(...)" tween in which case "p" might be xs1 but "n" is still "clip"
+ * @param {boolean=} r If true, the value(s) should be rounded
+ * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0.
+ * @param {string=} b Beginning value. We store this to ensure that it is EXACTLY what it was when the tween began without any risk of interpretation issues.
+ * @param {string=} e Ending value. We store this to ensure that it is EXACTLY what the user defined at the end of the tween without any risk of interpretation issues.
+ */
+ CSSPropTween = _internals.CSSPropTween = function(t, p, s, c, next, type, n, r, pr, b, e) {
+ this.t = t; //target
+ this.p = p; //property
+ this.s = s; //starting value
+ this.c = c; //change value
+ this.n = n || p; //name that this CSSPropTween should be associated to (usually the same as p, but not always - n is what overwriting looks at)
+ if (!(t instanceof CSSPropTween)) {
+ _overwriteProps.push(this.n);
+ }
+ this.r = r; //round (boolean)
+ this.type = type || 0; //0 = normal tween, -1 = non-tweening (in which case xs0 will be applied to the target's property, like tp.t[tp.p] = tp.xs0), 1 = complex-value SpecialProp, 2 = custom setRatio() that does all the work
+ if (pr) {
+ this.pr = pr;
+ _hasPriority = true;
+ }
+ this.b = (b === undefined) ? s : b;
+ this.e = (e === undefined) ? s + c : e;
+ if (next) {
+ this._next = next;
+ next._prev = this;
+ }
+ },
+
+ /**
+ * Takes a target, the beginning value and ending value (as strings) and parses them into a CSSPropTween (possibly with child CSSPropTweens) that accommodates multiple numbers, colors, comma-delimited values, etc. For example:
+ * sp.parseComplex(element, "boxShadow", "5px 10px 20px rgb(255,102,51)", "0px 0px 0px red", true, "0px 0px 0px rgb(0,0,0,0)", pt);
+ * It will walk through the beginning and ending values (which should be in the same format with the same number and type of values) and figure out which parts are numbers, what strings separate the numeric/tweenable values, and then create the CSSPropTweens accordingly. If a plugin is defined, no child CSSPropTweens will be created. Instead, the ending values will be stored in the "data" property of the returned CSSPropTween like: {s:-5, xn1:-10, xn2:-20, xn3:255, xn4:0, xn5:0} so that it can be fed to any other plugin and it'll be plain numeric tweens but the recomposition of the complex value will be handled inside CSSPlugin's setRatio().
+ * If a setRatio is defined, the type of the CSSPropTween will be set to 2 and recomposition of the values will be the responsibility of that method.
+ *
+ * @param {!Object} t Target whose property will be tweened
+ * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow")
+ * @param {string} b Beginning value
+ * @param {string} e Ending value
+ * @param {boolean} clrs If true, the value could contain a color value like "rgb(255,0,0)" or "#F00" or "red". The default is false, so no colors will be recognized (a performance optimization)
+ * @param {(string|number|Object)} dflt The default beginning value that should be used if no valid beginning value is defined or if the number of values inside the complex beginning and ending values don't match
+ * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this).
+ * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0.
+ * @param {TweenPlugin=} plugin If a plugin should handle the tweening of extra properties, pass the plugin instance here. If one is defined, then NO subtweens will be created for any extra properties (the properties will be created - just not additional CSSPropTween instances to tween them) because the plugin is expected to do so. However, the end values WILL be populated in the "data" property, like {s:100, xn1:50, xn2:300}
+ * @param {function(number)=} setRatio If values should be set in a custom function instead of being pieced together in a type:1 (complex-value) CSSPropTween, define that custom function here.
+ * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call.
+ */
+ _parseComplex = CSSPlugin.parseComplex = function(t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) {
+ //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e);
+ b = b || dflt || "";
+ pt = new CSSPropTween(t, p, 0, 0, pt, (setRatio ? 2 : 1), null, false, pr, b, e);
+ e += ""; //ensures it's a string
+ var ba = b.split(", ").join(",").split(" "), //beginning array
+ ea = e.split(", ").join(",").split(" "), //ending array
+ l = ba.length,
+ autoRound = (_autoRound !== false),
+ i, xi, ni, bv, ev, bnums, enums, bn, rgba, temp, cv, str;
+ if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
+ ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
+ ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
+ l = ba.length;
+ }
+ if (l !== ea.length) {
+ //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
+ ba = (dflt || "").split(" ");
+ l = ba.length;
+ }
+ pt.plugin = plugin;
+ pt.setRatio = setRatio;
+ for (i = 0; i < l; i++) {
+ bv = ba[i];
+ ev = ea[i];
+ bn = parseFloat(bv);
+
+ //if the value begins with a number (most common). It's fine if it has a suffix like px
+ if (bn || bn === 0) {
+ pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), (autoRound && ev.indexOf("px") !== -1), true);
+
+ //if the value is a color
+ } else if (clrs && (bv.charAt(0) === "#" || _colorLookup[bv] || _rgbhslExp.test(bv))) {
+ str = ev.charAt(ev.length - 1) === "," ? ")," : ")"; //if there's a comma at the end, retain it.
+ bv = _parseColor(bv);
+ ev = _parseColor(ev);
+ rgba = (bv.length + ev.length > 6);
+ if (rgba && !_supportsOpacity && ev[3] === 0) { //older versions of IE don't support rgba(), so if the destination alpha is 0, just use "transparent" for the end color
+ pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
+ pt.e = pt.e.split(ea[i]).join("transparent");
+ } else {
+ if (!_supportsOpacity) { //old versions of IE don't support rgba().
+ rgba = false;
+ }
+ pt.appendXtra((rgba ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true)
+ .appendXtra("", bv[1], ev[1] - bv[1], ",", true)
+ .appendXtra("", bv[2], ev[2] - bv[2], (rgba ? "," : str), true);
+ if (rgba) {
+ bv = (bv.length < 4) ? 1 : bv[3];
+ pt.appendXtra("", bv, ((ev.length < 4) ? 1 : ev[3]) - bv, str, false);
+ }
+ }
+
+ } else {
+ bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array
+
+ //if no number is found, treat it as a non-tweening value and just append the string to the current xs.
+ if (!bnums) {
+ pt["xs" + pt.l] += pt.l ? " " + bv : bv;
+
+ //loop through all the numbers that are found and construct the extra values on the pt.
+ } else {
+ enums = ev.match(_relNumExp); //get each group of numbers in the end value string and drop them into an array. We allow relative values too, like +=50 or -=.5
+ if (!enums || enums.length !== bnums.length) {
+ //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
+ return pt;
+ }
+ ni = 0;
+ for (xi = 0; xi < bnums.length; xi++) {
+ cv = bnums[xi];
+ temp = bv.indexOf(cv, ni);
+ pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", (autoRound && bv.substr(temp + cv.length, 2) === "px"), (xi === 0));
+ ni = temp + cv.length;
+ }
+ pt["xs" + pt.l] += bv.substr(ni);
+ }
+ }
+ }
+ //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly.
+ if (e.indexOf("=") !== -1) if (pt.data) {
+ str = pt.xs0 + pt.data.s;
+ for (i = 1; i < pt.l; i++) {
+ str += pt["xs" + i] + pt.data["xn" + i];
+ }
+ pt.e = str + pt["xs" + i];
+ }
+ if (!pt.l) {
+ pt.type = -1;
+ pt.xs0 = pt.e;
+ }
+ return pt.xfirst || pt;
+ },
+ i = 9;
+
+
+ p = CSSPropTween.prototype;
+ p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc.
+ while (--i > 0) {
+ p["xn" + i] = 0;
+ p["xs" + i] = "";
+ }
+ p.xs0 = "";
+ p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null;
+
+
+ /**
+ * Appends and extra tweening value to a CSSPropTween and automatically manages any prefix and suffix strings. The first extra value is stored in the s and c of the main CSSPropTween instance, but thereafter any extras are stored in the xn1, xn2, xn3, etc. The prefixes and suffixes are stored in the xs0, xs1, xs2, etc. properties. For example, if I walk through a clip value like "rect(10px, 5px, 0px, 20px)", the values would be stored like this:
+ * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)"
+ * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method).
+ * @param {string=} pfx Prefix (if any)
+ * @param {!number} s Starting value
+ * @param {!number} c Change in numeric value over the course of the entire tween. For example, if the start is 5 and the end is 100, the change would be 95.
+ * @param {string=} sfx Suffix (if any)
+ * @param {boolean=} r Round (if true).
+ * @param {boolean=} pad If true, this extra value should be separated by the previous one by a space. If there is no previous extra and pad is true, it will automatically drop the space.
+ * @return {CSSPropTween} returns itself so that multiple methods can be chained together.
+ */
+ p.appendXtra = function(pfx, s, c, sfx, r, pad) {
+ var pt = this,
+ l = pt.l;
+ pt["xs" + l] += (pad && l) ? " " + pfx : pfx || "";
+ if (!c) if (l !== 0 && !pt.plugin) { //typically we'll combine non-changing values right into the xs to optimize performance, but we don't combine them when there's a plugin that will be tweening the values because it may depend on the values being split apart, like for a bezier, if a value doesn't change between the first and second iteration but then it does on the 3rd, we'll run into trouble because there's no xn slot for that value!
+ pt["xs" + l] += s + (sfx || "");
+ return pt;
+ }
+ pt.l++;
+ pt.type = pt.setRatio ? 2 : 1;
+ pt["xs" + pt.l] = sfx || "";
+ if (l > 0) {
+ pt.data["xn" + l] = s + c;
+ pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method)
+ pt["xn" + l] = s;
+ if (!pt.plugin) {
+ pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr);
+ pt.xfirst.xs0 = 0; //just to ensure that the property stays numeric which helps modern browsers speed up processing. Remember, in the setRatio() method, we do pt.t[pt.p] = val + pt.xs0 so if pt.xs0 is "" (the default), it'll cast the end value as a string. When a property is a number sometimes and a string sometimes, it prevents the compiler from locking in the data type, slowing things down slightly.
+ }
+ return pt;
+ }
+ pt.data = {s:s + c};
+ pt.rxp = {};
+ pt.s = s;
+ pt.c = c;
+ pt.r = r;
+ return pt;
+ };
+
+ /**
+ * @constructor A SpecialProp is basically a css property that needs to be treated in a non-standard way, like if it may contain a complex value like boxShadow:"5px 10px 15px rgb(255, 102, 51)" or if it is associated with another plugin like ThrowPropsPlugin or BezierPlugin. Every SpecialProp is associated with a particular property name like "boxShadow" or "throwProps" or "bezier" and it will intercept those values in the vars object that's passed to the CSSPlugin and handle them accordingly.
+ * @param {!string} p Property name (like "boxShadow" or "throwProps")
+ * @param {Object=} options An object containing any of the following configuration options:
+ * - defaultValue: the default value
+ * - parser: A function that should be called when the associated property name is found in the vars. This function should return a CSSPropTween instance and it should ensure that it is properly inserted into the linked list. It will receive 4 paramters: 1) The target, 2) The value defined in the vars, 3) The CSSPlugin instance (whose _firstPT should be used for the linked list), and 4) A computed style object if one was calculated (this is a speed optimization that allows retrieval of starting values quicker)
+ * - formatter: a function that formats any value received for this special property (for example, boxShadow could take "5px 5px red" and format it to "5px 5px 0px 0px red" so that both the beginning and ending values have a common order and quantity of values.)
+ * - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O)
+ * - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc.
+ * - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0.
+ * - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out.
+ * - collapsible: if true, the formatter should treat the value like it's a top/right/bottom/left value that could be collapsed, like "5px" would apply to all, "5px, 10px" would use 5px for top/bottom and 10px for right/left, etc.
+ * - keyword: a special keyword that can [optionally] be found inside the value (like "inset" for boxShadow). This allows us to validate beginning/ending values to make sure they match (if the keyword is found in one, it'll be added to the other for consistency by default).
+ */
+ var SpecialProp = function(p, options) {
+ options = options || {};
+ this.p = options.prefix ? _checkPropPrefix(p) || p : p;
+ _specialProps[p] = _specialProps[this.p] = this;
+ this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi);
+ if (options.parser) {
+ this.parse = options.parser;
+ }
+ this.clrs = options.color;
+ this.multi = options.multi;
+ this.keyword = options.keyword;
+ this.dflt = options.defaultValue;
+ this.pr = options.priority || 0;
+ },
+
+ //shortcut for creating a new SpecialProp that can accept multiple properties as a comma-delimited list (helps minification). dflt can be an array for multiple values (we don't do a comma-delimited list because the default value may contain commas, like rect(0px,0px,0px,0px)). We attach this method to the SpecialProp class/object instead of using a private _createSpecialProp() method so that we can tap into it externally if necessary, like from another plugin.
+ _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function(p, options, defaults) {
+ if (typeof(options) !== "object") {
+ options = {parser:defaults}; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin
+ }
+ var a = p.split(","),
+ d = options.defaultValue,
+ i, temp;
+ defaults = defaults || [d];
+ for (i = 0; i < a.length; i++) {
+ options.prefix = (i === 0 && options.prefix);
+ options.defaultValue = defaults[i] || d;
+ temp = new SpecialProp(a[i], options);
+ }
+ },
+
+ //creates a placeholder special prop for a plugin so that the property gets caught the first time a tween of it is attempted, and at that time it makes the plugin register itself, thus taking over for all future tweens of that property. This allows us to not mandate that things load in a particular order and it also allows us to log() an error that informs the user when they attempt to tween an external plugin-related property without loading its .js file.
+ _registerPluginProp = function(p) {
+ if (!_specialProps[p]) {
+ var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin";
+ _registerComplexSpecialProp(p, {parser:function(t, e, p, cssp, pt, plugin, vars) {
+ var pluginClass = (window.GreenSockGlobals || window).com.greensock.plugins[pluginName];
+ if (!pluginClass) {
+ _log("Error: " + pluginName + " js file not loaded.");
+ return pt;
+ }
+ pluginClass._cssRegister();
+ return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars);
+ }});
+ }
+ };
+
+
+ p = SpecialProp.prototype;
+
+ /**
+ * Alias for _parseComplex() that automatically plugs in certain values for this SpecialProp, like its property name, whether or not colors should be sensed, the default value, and priority. It also looks for any keyword that the SpecialProp defines (like "inset" for boxShadow) and ensures that the beginning and ending values have the same number of values for SpecialProps where multi is true (like boxShadow and textShadow can have a comma-delimited list)
+ * @param {!Object} t target element
+ * @param {(string|number|object)} b beginning value
+ * @param {(string|number|object)} e ending (destination) value
+ * @param {CSSPropTween=} pt next CSSPropTween in the linked list
+ * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here.
+ * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here.
+ * @return {CSSPropTween=} First CSSPropTween in the linked list
+ */
+ p.parseComplex = function(t, b, e, pt, plugin, setRatio) {
+ var kwd = this.keyword,
+ i, ba, ea, l, bi, ei;
+ //if this SpecialProp's value can contain a comma-delimited list of values (like boxShadow or textShadow), we must parse them in a special way, and look for a keyword (like "inset" for boxShadow) and ensure that the beginning and ending BOTH have it if the end defines it as such. We also must ensure that there are an equal number of values specified (we can't tween 1 boxShadow to 3 for example)
+ if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) {
+ ba = b.replace(_commasOutsideParenExp, "|").split("|");
+ ea = e.replace(_commasOutsideParenExp, "|").split("|");
+ } else if (kwd) {
+ ba = [b];
+ ea = [e];
+ }
+ if (ea) {
+ l = (ea.length > ba.length) ? ea.length : ba.length;
+ for (i = 0; i < l; i++) {
+ b = ba[i] = ba[i] || this.dflt;
+ e = ea[i] = ea[i] || this.dflt;
+ if (kwd) {
+ bi = b.indexOf(kwd);
+ ei = e.indexOf(kwd);
+ if (bi !== ei) {
+ e = (ei === -1) ? ea : ba;
+ e[i] += " " + kwd;
+ }
+ }
+ }
+ b = ba.join(", ");
+ e = ea.join(", ");
+ }
+ return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio);
+ };
+
+ /**
+ * Accepts a target and end value and spits back a CSSPropTween that has been inserted into the CSSPlugin's linked list and conforms with all the conventions we use internally, like type:-1, 0, 1, or 2, setting up any extra property tweens, priority, etc. For example, if we have a boxShadow SpecialProp and call:
+ * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this);
+ * It should figure out the starting value of the element's boxShadow, compare it to the provided end value and create all the necessary CSSPropTweens of the appropriate types to tween the boxShadow. The CSSPropTween that gets spit back should already be inserted into the linked list (the 4th parameter is the current head, so prepend to that).
+ * @param {!Object} t Target object whose property is being tweened
+ * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object).
+ * @param {!string} p Property name
+ * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween.
+ * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it)
+ * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance.
+ * @param {Object=} vars Original vars object that contains the data for parsing.
+ * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call.
+ */
+ p.parse = function(t, e, p, cssp, pt, plugin, vars) {
+ return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin);
+ };
+
+ /**
+ * Registers a special property that should be intercepted from any "css" objects defined in tweens. This allows you to handle them however you want without CSSPlugin doing it for you. The 2nd parameter should be a function that accepts 3 parameters:
+ * 1) Target object whose property should be tweened (typically a DOM element)
+ * 2) The end/destination value (could be a string, number, object, or whatever you want)
+ * 3) The tween instance (you probably don't need to worry about this, but it can be useful for looking up information like the duration)
+ *
+ * Then, your function should return a function which will be called each time the tween gets rendered, passing a numeric "ratio" parameter to your function that indicates the change factor (usually between 0 and 1). For example:
+ *
+ * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) {
+ * var start = target.style.width;
+ * return function(ratio) {
+ * target.style.width = (start + value * ratio) + "px";
+ * console.log("set width to " + target.style.width);
+ * }
+ * }, 0);
+ *
+ * Then, when I do this tween, it will trigger my special property:
+ *
+ * TweenLite.to(element, 1, {css:{myCustomProp:100}});
+ *
+ * In the example, of course, we're just changing the width, but you can do anything you want.
+ *
+ * @param {!string} name Property name (or comma-delimited list of property names) that should be intercepted and handled by your function. For example, if I define "myCustomProp", then it would handle that portion of the following tween: TweenLite.to(element, 1, {css:{myCustomProp:100}})
+ * @param {!function(Object, Object, Object, string):function(number)} onInitTween The function that will be called when a tween of this special property is performed. The function will receive 4 parameters: 1) Target object that should be tweened, 2) Value that was passed to the tween, 3) The tween instance itself (rarely used), and 4) The property name that's being tweened. Your function should return a function that should be called on every update of the tween. That function will receive a single parameter that is a "change factor" value (typically between 0 and 1) indicating the amount of change as a ratio. You can use this to determine how to set the values appropriately in your function.
+ * @param {number=} priority Priority that helps the engine determine the order in which to set the properties (default: 0). Higher priority properties will be updated before lower priority ones.
+ */
+ CSSPlugin.registerSpecialProp = function(name, onInitTween, priority) {
+ _registerComplexSpecialProp(name, {parser:function(t, e, p, cssp, pt, plugin, vars) {
+ var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority);
+ rv.plugin = plugin;
+ rv.setRatio = onInitTween(t, e, cssp._tween, p);
+ return rv;
+ }, priority:priority});
+ };
+
+
+
+
+
+
+
+
+ //transform-related methods and properties
+ var _transformProps = ("scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective").split(","),
+ _transformProp = _checkPropPrefix("transform"), //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform.
+ _transformPropCSS = _prefixCSS + "transform",
+ _transformOriginProp = _checkPropPrefix("transformOrigin"),
+ _supports3D = (_checkPropPrefix("perspective") !== null),
+ Transform = _internals.Transform = function() {
+ this.skewY = 0;
+ },
+
+ /**
+ * Parses the transform values for an element, returning an object with x, y, z, scaleX, scaleY, scaleZ, rotation, rotationX, rotationY, skewX, and skewY properties. Note: by default (for performance reasons), all skewing is combined into skewX and rotation but skewY still has a place in the transform object so that we can record how much of the skew is attributed to skewX vs skewY. Remember, a skewY of 10 looks the same as a rotation of 10 and skewX of -10.
+ * @param {!Object} t target element
+ * @param {Object=} cs computed style object (optional)
+ * @param {boolean=} rec if true, the transform values will be recorded to the target element's _gsTransform object, like target._gsTransform = {x:0, y:0, z:0, scaleX:1...}
+ * @param {boolean=} parse if true, we'll ignore any _gsTransform values that already exist on the element, and force a reparsing of the css (calculated style)
+ * @return {object} object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...}
+ */
+ _getTransform = _internals.getTransform = function(t, cs, rec, parse) {
+ if (t._gsTransform && rec && !parse) {
+ return t._gsTransform; //if the element already has a _gsTransform, use that. Note: some browsers don't accurately return the calculated style for the transform (particularly for SVG), so it's almost always safest to just use the values we've already applied rather than re-parsing things.
+ }
+ var tm = rec ? t._gsTransform || new Transform() : new Transform(),
+ invX = (tm.scaleX < 0), //in order to interpret things properly, we need to know if the user applied a negative scaleX previously so that we can adjust the rotation and skewX accordingly. Otherwise, if we always interpret a flipped matrix as affecting scaleY and the user only wants to tween the scaleX on multiple sequential tweens, it would keep the negative scaleY without that being the user's intent.
+ min = 0.00002,
+ rnd = 100000,
+ minAngle = 179.99,
+ minPI = minAngle * _DEG2RAD,
+ zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin || 0 : 0,
+ s, m, i, n, dec, scaleX, scaleY, rotation, skewX, difX, difY, difR, difS;
+ if (_transformProp) {
+ s = _getStyle(t, _transformPropCSS, cs, true);
+ } else if (t.currentStyle) {
+ //for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix.
+ s = t.currentStyle.filter.match(_ieGetMatrixExp);
+ s = (s && s.length === 4) ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), (tm.x || 0), (tm.y || 0)].join(",") : "";
+ }
+ //split the matrix values out into an array (m for matrix)
+ m = (s || "").match(/(?:\-|\b)[\d\-\.e]+\b/gi) || [];
+ i = m.length;
+ while (--i > -1) {
+ n = Number(m[i]);
+ m[i] = (dec = n - (n |= 0)) ? ((dec * rnd + (dec < 0 ? -0.5 : 0.5)) | 0) / rnd + n : n; //convert strings to Numbers and round to 5 decimal places to avoid issues with tiny numbers. Roughly 20x faster than Number.toFixed(). We also must make sure to round before dividing so that values like 0.9999999999 become 1 to avoid glitches in browser rendering and interpretation of flipped/rotated 3D matrices. And don't just multiply the number by rnd, floor it, and then divide by rnd because the bitwise operations max out at a 32-bit signed integer, thus it could get clipped at a relatively low value (like 22,000.00000 for example).
+ }
+ if (m.length === 16) {
+
+ //we'll only look at these position-related 6 variables first because if x/y/z all match, it's relatively safe to assume we don't need to re-parse everything which risks losing important rotational information (like rotationX:180 plus rotationY:180 would look the same as rotation:180 - there's no way to know for sure which direction was taken based solely on the matrix3d() values)
+ var a13 = m[8], a23 = m[9], a33 = m[10],
+ a14 = m[12], a24 = m[13], a34 = m[14];
+
+ //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari
+ if (tm.zOrigin) {
+ a34 = -tm.zOrigin;
+ a14 = a13*a34-m[12];
+ a24 = a23*a34-m[13];
+ a34 = a33*a34+tm.zOrigin-m[14];
+ }
+
+ //only parse from the matrix if we MUST because not only is it usually unnecessary due to the fact that we store the values in the _gsTransform object, but also because it's impossible to accurately interpret rotationX, rotationY, rotationZ, scaleX, and scaleY if all are applied, so it's much better to rely on what we store. However, we must parse the first time that an object is tweened. We also assume that if the position has changed, the user must have done some styling changes outside of CSSPlugin, thus we force a parse in that scenario.
+ if (!rec || parse || tm.rotationX == null) {
+ var a11 = m[0], a21 = m[1], a31 = m[2], a41 = m[3],
+ a12 = m[4], a22 = m[5], a32 = m[6], a42 = m[7],
+ a43 = m[11],
+ angle = Math.atan2(a32, a33),
+ xFlip = (angle < -minPI || angle > minPI),
+ t1, t2, t3, cos, sin, yFlip, zFlip;
+ tm.rotationX = angle * _RAD2DEG;
+ //rotationX
+ if (angle) {
+ cos = Math.cos(-angle);
+ sin = Math.sin(-angle);
+ t1 = a12*cos+a13*sin;
+ t2 = a22*cos+a23*sin;
+ t3 = a32*cos+a33*sin;
+ a13 = a12*-sin+a13*cos;
+ a23 = a22*-sin+a23*cos;
+ a33 = a32*-sin+a33*cos;
+ a43 = a42*-sin+a43*cos;
+ a12 = t1;
+ a22 = t2;
+ a32 = t3;
+ }
+ //rotationY
+ angle = Math.atan2(a13, a11);
+ tm.rotationY = angle * _RAD2DEG;
+ if (angle) {
+ yFlip = (angle < -minPI || angle > minPI);
+ cos = Math.cos(-angle);
+ sin = Math.sin(-angle);
+ t1 = a11*cos-a13*sin;
+ t2 = a21*cos-a23*sin;
+ t3 = a31*cos-a33*sin;
+ a23 = a21*sin+a23*cos;
+ a33 = a31*sin+a33*cos;
+ a43 = a41*sin+a43*cos;
+ a11 = t1;
+ a21 = t2;
+ a31 = t3;
+ }
+ //rotationZ
+ angle = Math.atan2(a21, a22);
+ tm.rotation = angle * _RAD2DEG;
+ if (angle) {
+ zFlip = (angle < -minPI || angle > minPI);
+ cos = Math.cos(-angle);
+ sin = Math.sin(-angle);
+ a11 = a11*cos+a12*sin;
+ t2 = a21*cos+a22*sin;
+ a22 = a21*-sin+a22*cos;
+ a32 = a31*-sin+a32*cos;
+ a21 = t2;
+ }
+
+ if (zFlip && xFlip) {
+ tm.rotation = tm.rotationX = 0;
+ } else if (zFlip && yFlip) {
+ tm.rotation = tm.rotationY = 0;
+ } else if (yFlip && xFlip) {
+ tm.rotationY = tm.rotationX = 0;
+ }
+
+ tm.scaleX = ((Math.sqrt(a11 * a11 + a21 * a21) * rnd + 0.5) | 0) / rnd;
+ tm.scaleY = ((Math.sqrt(a22 * a22 + a23 * a23) * rnd + 0.5) | 0) / rnd;
+ tm.scaleZ = ((Math.sqrt(a32 * a32 + a33 * a33) * rnd + 0.5) | 0) / rnd;
+ tm.skewX = 0;
+ tm.perspective = a43 ? 1 / ((a43 < 0) ? -a43 : a43) : 0;
+ tm.x = a14;
+ tm.y = a24;
+ tm.z = a34;
+ }
+
+ } else if ((!_supports3D || parse || !m.length || tm.x !== m[4] || tm.y !== m[5] || (!tm.rotationX && !tm.rotationY)) && !(tm.x !== undefined && _getStyle(t, "display", cs) === "none")) { //sometimes a 6-element matrix is returned even when we performed 3D transforms, like if rotationX and rotationY are 180. In cases like this, we still need to honor the 3D transforms. If we just rely on the 2D info, it could affect how the data is interpreted, like scaleY might get set to -1 or rotation could get offset by 180 degrees. For example, do a TweenLite.to(element, 1, {css:{rotationX:180, rotationY:180}}) and then later, TweenLite.to(element, 1, {css:{rotationX:0}}) and without this conditional logic in place, it'd jump to a state of being unrotated when the 2nd tween starts. Then again, we need to honor the fact that the user COULD alter the transforms outside of CSSPlugin, like by manually applying new css, so we try to sense that by looking at x and y because if those changed, we know the changes were made outside CSSPlugin and we force a reinterpretation of the matrix values. Also, in Webkit browsers, if the element's "display" is "none", its calculated style value will always return empty, so if we've already recorded the values in the _gsTransform object, we'll just rely on those.
+ var k = (m.length >= 6),
+ a = k ? m[0] : 1,
+ b = m[1] || 0,
+ c = m[2] || 0,
+ d = k ? m[3] : 1;
+ tm.x = m[4] || 0;
+ tm.y = m[5] || 0;
+ scaleX = Math.sqrt(a * a + b * b);
+ scaleY = Math.sqrt(d * d + c * c);
+ rotation = (a || b) ? Math.atan2(b, a) * _RAD2DEG : tm.rotation || 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist).
+ skewX = (c || d) ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0;
+ difX = scaleX - Math.abs(tm.scaleX || 0);
+ difY = scaleY - Math.abs(tm.scaleY || 0);
+ if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
+ if (invX) {
+ scaleX *= -1;
+ skewX += (rotation <= 0) ? 180 : -180;
+ rotation += (rotation <= 0) ? 180 : -180;
+ } else {
+ scaleY *= -1;
+ skewX += (skewX <= 0) ? 180 : -180;
+ }
+ }
+ difR = (rotation - tm.rotation) % 180; //note: matching ranges would be very small (+/-0.0001) or very close to 180.
+ difS = (skewX - tm.skewX) % 180;
+ //if there's already a recorded _gsTransform in place for the target, we should leave those values in place unless we know things changed for sure (beyond a super small amount). This gets around ambiguous interpretations, like if scaleX and scaleY are both -1, the matrix would be the same as if the rotation was 180 with normal scaleX/scaleY. If the user tweened to particular values, those must be prioritized to ensure animation is consistent.
+ if (tm.skewX === undefined || difX > min || difX < -min || difY > min || difY < -min || (difR > -minAngle && difR < minAngle && (difR * rnd) | 0 !== 0) || (difS > -minAngle && difS < minAngle && (difS * rnd) | 0 !== 0)) {
+ tm.scaleX = scaleX;
+ tm.scaleY = scaleY;
+ tm.rotation = rotation;
+ tm.skewX = skewX;
+ }
+ if (_supports3D) {
+ tm.rotationX = tm.rotationY = tm.z = 0;
+ tm.perspective = parseFloat(CSSPlugin.defaultTransformPerspective) || 0;
+ tm.scaleZ = 1;
+ }
+ }
+ tm.zOrigin = zOrigin;
+
+ //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 0 in these cases. The conditional logic here is faster than calling Math.abs(). Also, browsers tend to render a SLIGHTLY rotated object in a fuzzy way, so we need to snap to exactly 0 when appropriate.
+ for (i in tm) {
+ if (tm[i] < min) if (tm[i] > -min) {
+ tm[i] = 0;
+ }
+ }
+ //DEBUG: _log("parsed rotation: "+(tm.rotationX)+", "+(tm.rotationY)+", "+(tm.rotation)+", scale: "+tm.scaleX+", "+tm.scaleY+", "+tm.scaleZ+", position: "+tm.x+", "+tm.y+", "+tm.z+", perspective: "+tm.perspective);
+ if (rec) {
+ t._gsTransform = tm; //record to the object's _gsTransform which we use so that tweens can control individual properties independently (we need all the properties to accurately recompose the matrix in the setRatio() method)
+ }
+ return tm;
+ },
+
+ //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms)
+ _setIETransformRatio = function(v) {
+ var t = this.data, //refers to the element's _gsTransform object
+ ang = -t.rotation * _DEG2RAD,
+ skew = ang + t.skewX * _DEG2RAD,
+ rnd = 100000,
+ a = ((Math.cos(ang) * t.scaleX * rnd) | 0) / rnd,
+ b = ((Math.sin(ang) * t.scaleX * rnd) | 0) / rnd,
+ c = ((Math.sin(skew) * -t.scaleY * rnd) | 0) / rnd,
+ d = ((Math.cos(skew) * t.scaleY * rnd) | 0) / rnd,
+ style = this.t.style,
+ cs = this.t.currentStyle,
+ filters, val;
+ if (!cs) {
+ return;
+ }
+ val = b; //just for swapping the variables an inverting them (reused "val" to avoid creating another variable in memory). IE's filter matrix uses a non-standard matrix configuration (angle goes the opposite way, and b and c are reversed and inverted)
+ b = -c;
+ c = -val;
+ filters = cs.filter;
+ style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight
+ var w = this.t.offsetWidth,
+ h = this.t.offsetHeight,
+ clip = (cs.position !== "absolute"),
+ m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d,
+ ox = t.x,
+ oy = t.y,
+ dx, dy;
+
+ //if transformOrigin is being used, adjust the offset x and y
+ if (t.ox != null) {
+ dx = ((t.oxp) ? w * t.ox * 0.01 : t.ox) - w / 2;
+ dy = ((t.oyp) ? h * t.oy * 0.01 : t.oy) - h / 2;
+ ox += dx - (dx * a + dy * b);
+ oy += dy - (dx * c + dy * d);
+ }
+
+ if (!clip) {
+ m += ", sizingMethod='auto expand')";
+ } else {
+ dx = (w / 2);
+ dy = (h / 2);
+ //translate to ensure that transformations occur around the correct origin (default is center).
+ m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")";
+ }
+ if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
+ style.filter = filters.replace(_ieSetMatrixExp, m);
+ } else {
+ style.filter = m + " " + filters; //we must always put the transform/matrix FIRST (before alpha(opacity=xx)) to avoid an IE bug that slices part of the object when rotation is applied with alpha.
+ }
+
+ //at the end or beginning of the tween, if the matrix is normal (1, 0, 0, 1) and opacity is 100 (or doesn't exist), remove the filter to improve browser performance.
+ if (v === 0 || v === 1) if (a === 1) if (b === 0) if (c === 0) if (d === 1) if (!clip || m.indexOf("Dx=0, Dy=0") !== -1) if (!_opacityExp.test(filters) || parseFloat(RegExp.$1) === 100) if (filters.indexOf("gradient(" && filters.indexOf("Alpha")) === -1) {
+ style.removeAttribute("filter");
+ }
+
+ //we must set the margins AFTER applying the filter in order to avoid some bugs in IE8 that could (in rare scenarios) cause them to be ignored intermittently (vibration).
+ if (!clip) {
+ var mult = (_ieVers < 8) ? 1 : -1, //in Internet Explorer 7 and before, the box model is broken, causing the browser to treat the width/height of the actual rotated filtered image as the width/height of the box itself, but Microsoft corrected that in IE8. We must use a negative offset in IE8 on the right/bottom
+ marg, prop, dif;
+ dx = t.ieOffsetX || 0;
+ dy = t.ieOffsetY || 0;
+ t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox);
+ t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy);
+ for (i = 0; i < 4; i++) {
+ prop = _margins[i];
+ marg = cs[prop];
+ //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes)
+ val = (marg.indexOf("px") !== -1) ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0;
+ if (val !== t[prop]) {
+ dif = (i < 2) ? -t.ieOffsetX : -t.ieOffsetY; //if another tween is controlling a margin, we cannot only apply the difference in the ieOffsets, so we essentially zero-out the dx and dy here in that case. We record the margin(s) later so that we can keep comparing them, making this code very flexible.
+ } else {
+ dif = (i < 2) ? dx - t.ieOffsetX : dy - t.ieOffsetY;
+ }
+ style[prop] = (t[prop] = Math.round( val - dif * ((i === 0 || i === 2) ? 1 : mult) )) + "px";
+ }
+ }
+ },
+
+ _set3DTransformRatio = _internals.set3DTransformRatio = function(v) {
+ var t = this.data, //refers to the element's _gsTransform object
+ style = this.t.style,
+ angle = t.rotation * _DEG2RAD,
+ sx = t.scaleX,
+ sy = t.scaleY,
+ sz = t.scaleZ,
+ perspective = t.perspective,
+ a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
+ zOrigin, rnd, cos, sin, t1, t2, t3, t4;
+ if (v === 1 || v === 0) if (t.force3D === "auto") if (!t.rotationY && !t.rotationX && sz === 1 && !perspective && !t.z) { //on the final render (which could be 0 for a from tween), if there are no 3D aspects, render in 2D to free up memory and improve performance especially on mobile devices
+ _set2DTransformRatio.call(this, v);
+ return;
+ }
+ if (_isFirefox) {
+ var n = 0.0001;
+ if (sx < n && sx > -n) { //Firefox has a bug (at least in v25) that causes it to render the transparent part of 32-bit PNG images as black when displayed inside an iframe and the 3D scale is very small and doesn't change sufficiently enough between renders (like if you use a Power4.easeInOut to scale from 0 to 1 where the beginning values only change a tiny amount to begin the tween before accelerating). In this case, we force the scale to be 0.00002 instead which is visually the same but works around the Firefox issue.
+ sx = sz = 0.00002;
+ }
+ if (sy < n && sy > -n) {
+ sy = sz = 0.00002;
+ }
+ if (perspective && !t.z && !t.rotationX && !t.rotationY) { //Firefox has a bug that causes elements to have an odd super-thin, broken/dotted black border on elements that have a perspective set but aren't utilizing 3D space (no rotationX, rotationY, or z).
+ perspective = 0;
+ }
+ }
+ if (angle || t.skewX) {
+ cos = Math.cos(angle);
+ sin = Math.sin(angle);
+ a11 = cos;
+ a21 = sin;
+ if (t.skewX) {
+ angle -= t.skewX * _DEG2RAD;
+ cos = Math.cos(angle);
+ sin = Math.sin(angle);
+ if (t.skewType === "simple") { //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does
+ t1 = Math.tan(t.skewX * _DEG2RAD);
+ t1 = Math.sqrt(1 + t1 * t1);
+ cos *= t1;
+ sin *= t1;
+ }
+ }
+ a12 = -sin;
+ a22 = cos;
+
+ } else if (!t.rotationY && !t.rotationX && sz === 1 && !perspective) { //if we're only translating and/or 2D scaling, this is faster...
+ style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");
+ return;
+ } else {
+ a11 = a22 = 1;
+ a12 = a21 = 0;
+ }
+ a33 = 1;
+ a13 = a14 = a23 = a24 = a31 = a32 = a34 = a41 = a42 = 0;
+ a43 = (perspective) ? -1 / perspective : 0;
+ zOrigin = t.zOrigin;
+ rnd = 100000;
+ angle = t.rotationY * _DEG2RAD;
+ if (angle) {
+ cos = Math.cos(angle);
+ sin = Math.sin(angle);
+ a31 = a33*-sin;
+ a41 = a43*-sin;
+ a13 = a11*sin;
+ a23 = a21*sin;
+ a33 *= cos;
+ a43 *= cos;
+ a11 *= cos;
+ a21 *= cos;
+ }
+ angle = t.rotationX * _DEG2RAD;
+ if (angle) {
+ cos = Math.cos(angle);
+ sin = Math.sin(angle);
+ t1 = a12*cos+a13*sin;
+ t2 = a22*cos+a23*sin;
+ t3 = a32*cos+a33*sin;
+ t4 = a42*cos+a43*sin;
+ a13 = a12*-sin+a13*cos;
+ a23 = a22*-sin+a23*cos;
+ a33 = a32*-sin+a33*cos;
+ a43 = a42*-sin+a43*cos;
+ a12 = t1;
+ a22 = t2;
+ a32 = t3;
+ a42 = t4;
+ }
+ if (sz !== 1) {
+ a13*=sz;
+ a23*=sz;
+ a33*=sz;
+ a43*=sz;
+ }
+ if (sy !== 1) {
+ a12*=sy;
+ a22*=sy;
+ a32*=sy;
+ a42*=sy;
+ }
+ if (sx !== 1) {
+ a11*=sx;
+ a21*=sx;
+ a31*=sx;
+ a41*=sx;
+ }
+ if (zOrigin) {
+ a34 -= zOrigin;
+ a14 = a13*a34;
+ a24 = a23*a34;
+ a34 = a33*a34+zOrigin;
+ }
+ //we round the x, y, and z slightly differently to allow even larger values.
+ a14 = (t1 = (a14 += t.x) - (a14 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a14 : a14;
+ a24 = (t1 = (a24 += t.y) - (a24 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a24 : a24;
+ a34 = (t1 = (a34 += t.z) - (a34 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a34 : a34;
+ style[_transformProp] = "matrix3d(" + [ (((a11 * rnd) | 0) / rnd), (((a21 * rnd) | 0) / rnd), (((a31 * rnd) | 0) / rnd), (((a41 * rnd) | 0) / rnd), (((a12 * rnd) | 0) / rnd), (((a22 * rnd) | 0) / rnd), (((a32 * rnd) | 0) / rnd), (((a42 * rnd) | 0) / rnd), (((a13 * rnd) | 0) / rnd), (((a23 * rnd) | 0) / rnd), (((a33 * rnd) | 0) / rnd), (((a43 * rnd) | 0) / rnd), a14, a24, a34, (perspective ? (1 + (-a34 / perspective)) : 1) ].join(",") + ")";
+ },
+
+ _set2DTransformRatio = _internals.set2DTransformRatio = function(v) {
+ var t = this.data, //refers to the element's _gsTransform object
+ targ = this.t,
+ style = targ.style,
+ ang, skew, rnd, sx, sy;
+ if (t.rotationX || t.rotationY || t.z || t.force3D === true || (t.force3D === "auto" && v !== 1 && v !== 0)) { //if a 3D tween begins while a 2D one is running, we need to kick the rendering over to the 3D method. For example, imagine a yoyo-ing, infinitely repeating scale tween running, and then the object gets rotated in 3D space with a different tween.
+ this.setRatio = _set3DTransformRatio;
+ _set3DTransformRatio.call(this, v);
+ return;
+ }
+ if (!t.rotation && !t.skewX) {
+ style[_transformProp] = "matrix(" + t.scaleX + ",0,0," + t.scaleY + "," + t.x + "," + t.y + ")";
+ } else {
+ ang = t.rotation * _DEG2RAD;
+ skew = ang - t.skewX * _DEG2RAD;
+ rnd = 100000;
+ sx = t.scaleX * rnd;
+ sy = t.scaleY * rnd;
+ //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 5 decimal places.
+ style[_transformProp] = "matrix(" + (((Math.cos(ang) * sx) | 0) / rnd) + "," + (((Math.sin(ang) * sx) | 0) / rnd) + "," + (((Math.sin(skew) * -sy) | 0) / rnd) + "," + (((Math.cos(skew) * sy) | 0) / rnd) + "," + t.x + "," + t.y + ")";
+ }
+ };
+
+ _registerComplexSpecialProp("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType", {parser:function(t, e, p, cssp, pt, plugin, vars) {
+ if (cssp._transform) { return pt; } //only need to parse the transform once, and only if the browser supports it.
+ var m1 = cssp._transform = _getTransform(t, _cs, true, vars.parseTransform),
+ style = t.style,
+ min = 0.000001,
+ i = _transformProps.length,
+ v = vars,
+ endRotations = {},
+ m2, skewY, copy, orig, has3D, hasChange, dr;
+ if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
+ copy = _tempDiv.style; //don't use the original target because it might be SVG in which case some browsers don't report computed style correctly.
+ copy[_transformProp] = v.transform;
+ copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
+ copy.position = "absolute";
+ _doc.body.appendChild(_tempDiv);
+ m2 = _getTransform(_tempDiv, null, false);
+ _doc.body.removeChild(_tempDiv);
+ } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
+ m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
+ scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
+ scaleZ:_parseVal(v.scaleZ, m1.scaleZ),
+ x:_parseVal(v.x, m1.x),
+ y:_parseVal(v.y, m1.y),
+ z:_parseVal(v.z, m1.z),
+ perspective:_parseVal(v.transformPerspective, m1.perspective)};
+ dr = v.directionalRotation;
+ if (dr != null) {
+ if (typeof(dr) === "object") {
+ for (copy in dr) {
+ v[copy] = dr[copy];
+ }
+ } else {
+ v.rotation = dr;
+ }
+ }
+ m2.rotation = _parseAngle(("rotation" in v) ? v.rotation : ("shortRotation" in v) ? v.shortRotation + "_short" : ("rotationZ" in v) ? v.rotationZ : m1.rotation, m1.rotation, "rotation", endRotations);
+ if (_supports3D) {
+ m2.rotationX = _parseAngle(("rotationX" in v) ? v.rotationX : ("shortRotationX" in v) ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations);
+ m2.rotationY = _parseAngle(("rotationY" in v) ? v.rotationY : ("shortRotationY" in v) ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations);
+ }
+ m2.skewX = (v.skewX == null) ? m1.skewX : _parseAngle(v.skewX, m1.skewX);
+
+ //note: for performance reasons, we combine all skewing into the skewX and rotation values, ignoring skewY but we must still record it so that we can discern how much of the overall skew is attributed to skewX vs. skewY. Otherwise, if the skewY would always act relative (tween skewY to 10deg, for example, multiple times and if we always combine things into skewX, we can't remember that skewY was 10 from last time). Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of -10 degrees.
+ m2.skewY = (v.skewY == null) ? m1.skewY : _parseAngle(v.skewY, m1.skewY);
+ if ((skewY = m2.skewY - m1.skewY)) {
+ m2.skewX += skewY;
+ m2.rotation += skewY;
+ }
+ }
+
+ if (_supports3D && v.force3D != null) {
+ m1.force3D = v.force3D;
+ hasChange = true;
+ }
+
+ m1.skewType = v.skewType || m1.skewType || CSSPlugin.defaultSkewType;
+
+ has3D = (m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective);
+ if (!has3D && v.scale != null) {
+ m2.scaleZ = 1; //no need to tween scaleZ.
+ }
+
+ while (--i > -1) {
+ p = _transformProps[i];
+ orig = m2[p] - m1[p];
+ if (orig > min || orig < -min || _forcePT[p] != null) {
+ hasChange = true;
+ pt = new CSSPropTween(m1, p, m1[p], orig, pt);
+ if (p in endRotations) {
+ pt.e = endRotations[p]; //directional rotations typically have compensated values during the tween, but we need to make sure they end at exactly what the user requested
+ }
+ pt.xs0 = 0; //ensures the value stays numeric in setRatio()
+ pt.plugin = plugin;
+ cssp._overwriteProps.push(pt.n);
+ }
+ }
+
+ orig = v.transformOrigin;
+ if (orig || (_supports3D && has3D && m1.zOrigin)) { //if anything 3D is happening and there's a transformOrigin with a z component that's non-zero, we must ensure that the transformOrigin's z-component is set to 0 so that we can manually do those calculations to get around Safari bugs. Even if the user didn't specifically define a "transformOrigin" in this particular tween (maybe they did it via css directly).
+ if (_transformProp) {
+ hasChange = true;
+ p = _transformOriginProp;
+ orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors
+ pt = new CSSPropTween(style, p, 0, 0, pt, -1, "transformOrigin");
+ pt.b = style[p];
+ pt.plugin = plugin;
+ if (_supports3D) {
+ copy = m1.zOrigin;
+ orig = orig.split(" ");
+ m1.zOrigin = ((orig.length > 2 && !(copy !== 0 && orig[2] === "0px")) ? parseFloat(orig[2]) : copy) || 0; //Safari doesn't handle the z part of transformOrigin correctly, so we'll manually handle it in the _set3DTransformRatio() method.
+ pt.xs0 = pt.e = orig[0] + " " + (orig[1] || "50%") + " 0px"; //we must define a z value of 0px specifically otherwise iOS 5 Safari will stick with the old one (if one was defined)!
+ pt = new CSSPropTween(m1, "zOrigin", 0, 0, pt, -1, pt.n); //we must create a CSSPropTween for the _gsTransform.zOrigin so that it gets reset properly at the beginning if the tween runs backward (as opposed to just setting m1.zOrigin here)
+ pt.b = copy;
+ pt.xs0 = pt.e = m1.zOrigin;
+ } else {
+ pt.xs0 = pt.e = orig;
+ }
+
+ //for older versions of IE (6-8), we need to manually calculate things inside the setRatio() function. We record origin x and y (ox and oy) and whether or not the values are percentages (oxp and oyp).
+ } else {
+ _parsePosition(orig + "", m1);
+ }
+ }
+
+ if (hasChange) {
+ cssp._transformType = (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms();
+ }
+ return pt;
+ }, prefix:true});
+
+ _registerComplexSpecialProp("boxShadow", {defaultValue:"0px 0px 0px 0px #999", prefix:true, color:true, multi:true, keyword:"inset"});
+
+ _registerComplexSpecialProp("borderRadius", {defaultValue:"0px", parser:function(t, e, p, cssp, pt, plugin) {
+ e = this.format(e);
+ var props = ["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],
+ style = t.style,
+ ea1, i, es2, bs2, bs, es, bn, en, w, h, esfx, bsfx, rel, hn, vn, em;
+ w = parseFloat(t.offsetWidth);
+ h = parseFloat(t.offsetHeight);
+ ea1 = e.split(" ");
+ for (i = 0; i < props.length; i++) { //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis!
+ if (this.p.indexOf("border")) { //older browsers used a prefix
+ props[i] = _checkPropPrefix(props[i]);
+ }
+ bs = bs2 = _getStyle(t, props[i], _cs, false, "0px");
+ if (bs.indexOf(" ") !== -1) {
+ bs2 = bs.split(" ");
+ bs = bs2[0];
+ bs2 = bs2[1];
+ }
+ es = es2 = ea1[i];
+ bn = parseFloat(bs);
+ bsfx = bs.substr((bn + "").length);
+ rel = (es.charAt(1) === "=");
+ if (rel) {
+ en = parseInt(es.charAt(0)+"1", 10);
+ es = es.substr(2);
+ en *= parseFloat(es);
+ esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || "";
+ } else {
+ en = parseFloat(es);
+ esfx = es.substr((en + "").length);
+ }
+ if (esfx === "") {
+ esfx = _suffixMap[p] || bsfx;
+ }
+ if (esfx !== bsfx) {
+ hn = _convertToPixels(t, "borderLeft", bn, bsfx); //horizontal number (we use a bogus "borderLeft" property just because the _convertToPixels() method searches for the keywords "Left", "Right", "Top", and "Bottom" to determine of it's a horizontal or vertical property, and we need "border" in the name so that it knows it should measure relative to the element itself, not its parent.
+ vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number
+ if (esfx === "%") {
+ bs = (hn / w * 100) + "%";
+ bs2 = (vn / h * 100) + "%";
+ } else if (esfx === "em") {
+ em = _convertToPixels(t, "borderLeft", 1, "em");
+ bs = (hn / em) + "em";
+ bs2 = (vn / em) + "em";
+ } else {
+ bs = hn + "px";
+ bs2 = vn + "px";
+ }
+ if (rel) {
+ es = (parseFloat(bs) + en) + esfx;
+ es2 = (parseFloat(bs2) + en) + esfx;
+ }
+ }
+ pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt);
+ }
+ return pt;
+ }, prefix:true, formatter:_getFormatter("0px 0px 0px 0px", false, true)});
+ _registerComplexSpecialProp("backgroundPosition", {defaultValue:"0 0", parser:function(t, e, p, cssp, pt, plugin) {
+ var bp = "background-position",
+ cs = (_cs || _getComputedStyle(t, null)),
+ bs = this.format( ((cs) ? _ieVers ? cs.getPropertyValue(bp + "-x") + " " + cs.getPropertyValue(bp + "-y") : cs.getPropertyValue(bp) : t.currentStyle.backgroundPositionX + " " + t.currentStyle.backgroundPositionY) || "0 0"), //Internet Explorer doesn't report background-position correctly - we must query background-position-x and background-position-y and combine them (even in IE10). Before IE9, we must do the same with the currentStyle object and use camelCase
+ es = this.format(e),
+ ba, ea, i, pct, overlap, src;
+ if ((bs.indexOf("%") !== -1) !== (es.indexOf("%") !== -1)) {
+ src = _getStyle(t, "backgroundImage").replace(_urlExp, "");
+ if (src && src !== "none") {
+ ba = bs.split(" ");
+ ea = es.split(" ");
+ _tempImg.setAttribute("src", src); //set the temp <img>'s src to the background-image so that we can measure its width/height
+ i = 2;
+ while (--i > -1) {
+ bs = ba[i];
+ pct = (bs.indexOf("%") !== -1);
+ if (pct !== (ea[i].indexOf("%") !== -1)) {
+ overlap = (i === 0) ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height;
+ ba[i] = pct ? (parseFloat(bs) / 100 * overlap) + "px" : (parseFloat(bs) / overlap * 100) + "%";
+ }
+ }
+ bs = ba.join(" ");
+ }
+ }
+ return this.parseComplex(t.style, bs, es, pt, plugin);
+ }, formatter:_parsePosition});
+ _registerComplexSpecialProp("backgroundSize", {defaultValue:"0 0", formatter:_parsePosition});
+ _registerComplexSpecialProp("perspective", {defaultValue:"0px", prefix:true});
+ _registerComplexSpecialProp("perspectiveOrigin", {defaultValue:"50% 50%", prefix:true});
+ _registerComplexSpecialProp("transformStyle", {prefix:true});
+ _registerComplexSpecialProp("backfaceVisibility", {prefix:true});
+ _registerComplexSpecialProp("userSelect", {prefix:true});
+ _registerComplexSpecialProp("margin", {parser:_getEdgeParser("marginTop,marginRight,marginBottom,marginLeft")});
+ _registerComplexSpecialProp("padding", {parser:_getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft")});
+ _registerComplexSpecialProp("clip", {defaultValue:"rect(0px,0px,0px,0px)", parser:function(t, e, p, cssp, pt, plugin){
+ var b, cs, delim;
+ if (_ieVers < 9) { //IE8 and earlier don't report a "clip" value in the currentStyle - instead, the values are split apart into clipTop, clipRight, clipBottom, and clipLeft. Also, in IE7 and earlier, the values inside rect() are space-delimited, not comma-delimited.
+ cs = t.currentStyle;
+ delim = _ieVers < 8 ? " " : ",";
+ b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")";
+ e = this.format(e).split(",").join(delim);
+ } else {
+ b = this.format(_getStyle(t, this.p, _cs, false, this.dflt));
+ e = this.format(e);
+ }
+ return this.parseComplex(t.style, b, e, pt, plugin);
+ }});
+ _registerComplexSpecialProp("textShadow", {defaultValue:"0px 0px 0px #999", color:true, multi:true});
+ _registerComplexSpecialProp("autoRound,strictUnits", {parser:function(t, e, p, cssp, pt) {return pt;}}); //just so that we can ignore these properties (not tween them)
+ _registerComplexSpecialProp("border", {defaultValue:"0px solid #000", parser:function(t, e, p, cssp, pt, plugin) {
+ return this.parseComplex(t.style, this.format(_getStyle(t, "borderTopWidth", _cs, false, "0px") + " " + _getStyle(t, "borderTopStyle", _cs, false, "solid") + " " + _getStyle(t, "borderTopColor", _cs, false, "#000")), this.format(e), pt, plugin);
+ }, color:true, formatter:function(v) {
+ var a = v.split(" ");
+ return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0];
+ }});
+ _registerComplexSpecialProp("borderWidth", {parser:_getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}); //Firefox doesn't pick up on borderWidth set in style sheets (only inline).
+ _registerComplexSpecialProp("float,cssFloat,styleFloat", {parser:function(t, e, p, cssp, pt, plugin) {
+ var s = t.style,
+ prop = ("cssFloat" in s) ? "cssFloat" : "styleFloat";
+ return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e);
+ }});
+
+ //opacity-related
+ var _setIEOpacityRatio = function(v) {
+ var t = this.t, //refers to the element's style property
+ filters = t.filter || _getStyle(this.data, "filter"),
+ val = (this.s + this.c * v) | 0,
+ skip;
+ if (val === 100) { //for older versions of IE that need to use a filter to apply opacity, we should remove the filter if opacity hits 1 in order to improve performance, but make sure there isn't a transform (matrix) or gradient in the filters.
+ if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) {
+ t.removeAttribute("filter");
+ skip = (!_getStyle(this.data, "filter")); //if a class is applied that has an alpha filter, it will take effect (we don't want that), so re-apply our alpha filter in that case. We must first remove it and then check.
+ } else {
+ t.filter = filters.replace(_alphaFilterExp, "");
+ skip = true;
+ }
+ }
+ if (!skip) {
+ if (this.xn1) {
+ t.filter = filters = filters || ("alpha(opacity=" + val + ")"); //works around bug in IE7/8 that prevents changes to "visibility" from being applied properly if the filter is changed to a different alpha on the same frame.
+ }
+ if (filters.indexOf("pacity") === -1) { //only used if browser doesn't support the standard opacity style property (IE 7 and 8). We omit the "O" to avoid case-sensitivity issues
+ if (val !== 0 || !this.xn1) { //bugs in IE7/8 won't render the filter properly if opacity is ADDED on the same frame/render as "visibility" changes (this.xn1 is 1 if this tween is an "autoAlpha" tween)
+ t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
+ }
+ } else {
+ t.filter = filters.replace(_opacityExp, "opacity=" + val);
+ }
+ }
+ };
+ _registerComplexSpecialProp("opacity,alpha,autoAlpha", {defaultValue:"1", parser:function(t, e, p, cssp, pt, plugin) {
+ var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")),
+ style = t.style,
+ isAutoAlpha = (p === "autoAlpha");
+ if (typeof(e) === "string" && e.charAt(1) === "=") {
+ e = ((e.charAt(0) === "-") ? -1 : 1) * parseFloat(e.substr(2)) + b;
+ }
+ if (isAutoAlpha && b === 1 && _getStyle(t, "visibility", _cs) === "hidden" && e !== 0) { //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience)
+ b = 0;
+ }
+ if (_supportsOpacity) {
+ pt = new CSSPropTween(style, "opacity", b, e - b, pt);
+ } else {
+ pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt);
+ pt.xn1 = isAutoAlpha ? 1 : 0; //we need to record whether or not this is an autoAlpha so that in the setRatio(), we know to duplicate the setting of the alpha in order to work around a bug in IE7 and IE8 that prevents changes to "visibility" from taking effect if the filter is changed to a different alpha(opacity) at the same time. Setting it to the SAME value first, then the new value works around the IE7/8 bug.
+ style.zoom = 1; //helps correct an IE issue.
+ pt.type = 2;
+ pt.b = "alpha(opacity=" + pt.s + ")";
+ pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")";
+ pt.data = t;
+ pt.plugin = plugin;
+ pt.setRatio = _setIEOpacityRatio;
+ }
+ if (isAutoAlpha) { //we have to create the "visibility" PropTween after the opacity one in the linked list so that they run in the order that works properly in IE8 and earlier
+ pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, ((b !== 0) ? "inherit" : "hidden"), ((e === 0) ? "hidden" : "inherit"));
+ pt.xs0 = "inherit";
+ cssp._overwriteProps.push(pt.n);
+ cssp._overwriteProps.push(p);
+ }
+ return pt;
+ }});
+
+
+ var _removeProp = function(s, p) {
+ if (p) {
+ if (s.removeProperty) {
+ if (p.substr(0,2) === "ms") { //Microsoft browsers don't conform to the standard of capping the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example)
+ p = "M" + p.substr(1);
+ }
+ s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
+ } else { //note: old versions of IE use "removeAttribute()" instead of "removeProperty()"
+ s.removeAttribute(p);
+ }
+ }
+ },
+ _setClassNameRatio = function(v) {
+ this.t._gsClassPT = this;
+ if (v === 1 || v === 0) {
+ this.t.setAttribute("class", (v === 0) ? this.b : this.e);
+ var mpt = this.data, //first MiniPropTween
+ s = this.t.style;
+ while (mpt) {
+ if (!mpt.v) {
+ _removeProp(s, mpt.p);
+ } else {
+ s[mpt.p] = mpt.v;
+ }
+ mpt = mpt._next;
+ }
+ if (v === 1 && this.t._gsClassPT === this) {
+ this.t._gsClassPT = null;
+ }
+ } else if (this.t.getAttribute("class") !== this.e) {
+ this.t.setAttribute("class", this.e);
+ }
+ };
+ _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
+ var b = t.getAttribute("class") || "", //don't use t.className because it doesn't work consistently on SVG elements; getAttribute("class") and setAttribute("class", value") is more reliable.
+ cssText = t.style.cssText,
+ difData, bs, cnpt, cnptLookup, mpt;
+ pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
+ pt.setRatio = _setClassNameRatio;
+ pt.pr = -11;
+ _hasPriority = true;
+ pt.b = b;
+ bs = _getAllStyles(t, _cs);
+ //if there's a className tween already operating on the target, force it to its end so that the necessary inline styles are removed and the class name is applied before we determine the end state (we don't want inline styles interfering that were there just for class-specific values)
+ cnpt = t._gsClassPT;
+ if (cnpt) {
+ cnptLookup = {};
+ mpt = cnpt.data; //first MiniPropTween which stores the inline styles - we need to force these so that the inline styles don't contaminate things. Otherwise, there's a small chance that a tween could start and the inline values match the destination values and they never get cleaned.
+ while (mpt) {
+ cnptLookup[mpt.p] = 1;
+ mpt = mpt._next;
+ }
+ cnpt.setRatio(1);
+ }
+ t._gsClassPT = pt;
+ pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
+ if (cssp._tween._duration) { //if it's a zero-duration tween, there's no need to tween anything or parse the data. In fact, if we switch classes temporarily (which we must do for proper parsing) and the class has a transition applied, it could cause a quick flash to the end state and back again initially in some browsers.
+ t.setAttribute("class", pt.e);
+ difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
+ t.setAttribute("class", b);
+ pt.data = difData.firstMPT;
+ t.style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity).
+ pt = pt.xfirst = cssp.parse(t, difData.difs, pt, plugin); //we record the CSSPropTween as the xfirst so that we can handle overwriting propertly (if "className" gets overwritten, we must kill all the properties associated with the className part of the tween, so we can loop through from xfirst to the pt itself)
+ }
+ return pt;
+ }});
+
+
+ var _setClearPropsRatio = function(v) {
+ if (v === 1 || v === 0) if (this.data._totalTime === this.data._totalDuration && this.data.data !== "isFromStart") { //this.data refers to the tween. Only clear at the END of the tween (remember, from() tweens make the ratio go from 1 to 0, so we can't just check that and if the tween is the zero-duration one that's created internally to render the starting values in a from() tween, ignore that because otherwise, for example, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in).
+ var s = this.t.style,
+ transformParse = _specialProps.transform.parse,
+ a, p, i, clearTransform;
+ if (this.e === "all") {
+ s.cssText = "";
+ clearTransform = true;
+ } else {
+ a = this.e.split(",");
+ i = a.length;
+ while (--i > -1) {
+ p = a[i];
+ if (_specialProps[p]) {
+ if (_specialProps[p].parse === transformParse) {
+ clearTransform = true;
+ } else {
+ p = (p === "transformOrigin") ? _transformOriginProp : _specialProps[p].p; //ensures that special properties use the proper browser-specific property name, like "scaleX" might be "-webkit-transform" or "boxShadow" might be "-moz-box-shadow"
+ }
+ }
+ _removeProp(s, p);
+ }
+ }
+ if (clearTransform) {
+ _removeProp(s, _transformProp);
+ if (this.t._gsTransform) {
+ delete this.t._gsTransform;
+ }
+ }
+
+ }
+ };
+ _registerComplexSpecialProp("clearProps", {parser:function(t, e, p, cssp, pt) {
+ pt = new CSSPropTween(t, p, 0, 0, pt, 2);
+ pt.setRatio = _setClearPropsRatio;
+ pt.e = e;
+ pt.pr = -10;
+ pt.data = cssp._tween;
+ _hasPriority = true;
+ return pt;
+ }});
+
+ p = "bezier,throwProps,physicsProps,physics2D".split(",");
+ i = p.length;
+ while (i--) {
+ _registerPluginProp(p[i]);
+ }
+
+
+
+
+
+
+
+
+ p = CSSPlugin.prototype;
+ p._firstPT = null;
+
+ //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc.
+ p._onInitTween = function(target, vars, tween) {
+ if (!target.nodeType) { //css is only for dom elements
+ return false;
+ }
+ this._target = target;
+ this._tween = tween;
+ this._vars = vars;
+ _autoRound = vars.autoRound;
+ _hasPriority = false;
+ _suffixMap = vars.suffixMap || CSSPlugin.suffixMap;
+ _cs = _getComputedStyle(target, "");
+ _overwriteProps = this._overwriteProps;
+ var style = target.style,
+ v, pt, pt2, first, last, next, zIndex, tpt, threeD;
+ if (_reqSafariFix) if (style.zIndex === "") {
+ v = _getStyle(target, "zIndex", _cs);
+ if (v === "auto" || v === "") {
+ //corrects a bug in [non-Android] Safari that prevents it from repainting elements in their new positions if they don't have a zIndex set. We also can't just apply this inside _parseTransform() because anything that's moved in any way (like using "left" or "top" instead of transforms like "x" and "y") can be affected, so it is best to ensure that anything that's tweening has a z-index. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. Plus zIndex is less memory-intensive.
+ this._addLazySet(style, "zIndex", 0);
+ }
+ }
+
+ if (typeof(vars) === "string") {
+ first = style.cssText;
+ v = _getAllStyles(target, _cs);
+ style.cssText = first + ";" + vars;
+ v = _cssDif(target, v, _getAllStyles(target)).difs;
+ if (!_supportsOpacity && _opacityValExp.test(vars)) {
+ v.opacity = parseFloat( RegExp.$1 );
+ }
+ vars = v;
+ style.cssText = first;
+ }
+ this._firstPT = pt = this.parse(target, vars, null);
+
+ if (this._transformType) {
+ threeD = (this._transformType === 3);
+ if (!_transformProp) {
+ style.zoom = 1; //helps correct an IE issue.
+ } else if (_isSafari) {
+ _reqSafariFix = true;
+ //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random).
+ if (style.zIndex === "") {
+ zIndex = _getStyle(target, "zIndex", _cs);
+ if (zIndex === "auto" || zIndex === "") {
+ this._addLazySet(style, "zIndex", 0);
+ }
+ }
+ //Setting WebkitBackfaceVisibility corrects 3 bugs:
+ // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update.
+ // 2) iOS Safari sometimes neglects to repaint elements in their new positions. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly.
+ // 3) Safari sometimes displayed odd artifacts when tweening the transform (or WebkitTransform) property, like ghosts of the edges of the element remained. Definitely a browser bug.
+ //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
+ if (_isSafariLT6) {
+ this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
+ }
+ }
+ pt2 = pt;
+ while (pt2 && pt2._next) {
+ pt2 = pt2._next;
+ }
+ tpt = new CSSPropTween(target, "transform", 0, 0, null, 2);
+ this._linkCSSP(tpt, null, pt2);
+ tpt.setRatio = (threeD && _supports3D) ? _set3DTransformRatio : _transformProp ? _set2DTransformRatio : _setIETransformRatio;
+ tpt.data = this._transform || _getTransform(target, _cs, true);
+ _overwriteProps.pop(); //we don't want to force the overwrite of all "transform" tweens of the target - we only care about individual transform properties like scaleX, rotation, etc. The CSSPropTween constructor automatically adds the property to _overwriteProps which is why we need to pop() here.
+ }
+
+ if (_hasPriority) {
+ //reorders the linked list in order of pr (priority)
+ while (pt) {
+ next = pt._next;
+ pt2 = first;
+ while (pt2 && pt2.pr > pt.pr) {
+ pt2 = pt2._next;
+ }
+ if ((pt._prev = pt2 ? pt2._prev : last)) {
+ pt._prev._next = pt;
+ } else {
+ first = pt;
+ }
+ if ((pt._next = pt2)) {
+ pt2._prev = pt;
+ } else {
+ last = pt;
+ }
+ pt = next;
+ }
+ this._firstPT = first;
+ }
+ return true;
+ };
+
+
+ p.parse = function(target, vars, pt, plugin) {
+ var style = target.style,
+ p, sp, bn, en, bs, es, bsfx, esfx, isStr, rel;
+ for (p in vars) {
+ es = vars[p]; //ending value string
+ sp = _specialProps[p]; //SpecialProp lookup.
+ if (sp) {
+ pt = sp.parse(target, es, p, this, pt, plugin, vars);
+
+ } else {
+ bs = _getStyle(target, p, _cs) + "";
+ isStr = (typeof(es) === "string");
+ if (p === "color" || p === "fill" || p === "stroke" || p.indexOf("Color") !== -1 || (isStr && _rgbhslExp.test(es))) { //Opera uses background: to define color sometimes in addition to backgroundColor:
+ if (!isStr) {
+ es = _parseColor(es);
+ es = ((es.length > 3) ? "rgba(" : "rgb(") + es.join(",") + ")";
+ }
+ pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin);
+
+ } else if (isStr && (es.indexOf(" ") !== -1 || es.indexOf(",") !== -1)) {
+ pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin);
+
+ } else {
+ bn = parseFloat(bs);
+ bsfx = (bn || bn === 0) ? bs.substr((bn + "").length) : ""; //remember, bs could be non-numeric like "normal" for fontWeight, so we should default to a blank suffix in that case.
+
+ if (bs === "" || bs === "auto") {
+ if (p === "width" || p === "height") {
+ bn = _getDimension(target, p, _cs);
+ bsfx = "px";
+ } else if (p === "left" || p === "top") {
+ bn = _calculateOffset(target, p, _cs);
+ bsfx = "px";
+ } else {
+ bn = (p !== "opacity") ? 0 : 1;
+ bsfx = "";
+ }
+ }
+
+ rel = (isStr && es.charAt(1) === "=");
+ if (rel) {
+ en = parseInt(es.charAt(0) + "1", 10);
+ es = es.substr(2);
+ en *= parseFloat(es);
+ esfx = es.replace(_suffixExp, "");
+ } else {
+ en = parseFloat(es);
+ esfx = isStr ? es.substr((en + "").length) || "" : "";
+ }
+
+ if (esfx === "") {
+ esfx = (p in _suffixMap) ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix.
+ }
+
+ es = (en || en === 0) ? (rel ? en + bn : en) + esfx : vars[p]; //ensures that any += or -= prefixes are taken care of. Record the end value before normalizing the suffix because we always want to end the tween on exactly what they intended even if it doesn't match the beginning value's suffix.
+
+ //if the beginning/ending suffixes don't match, normalize them...
+ if (bsfx !== esfx) if (esfx !== "") if (en || en === 0) if (bn) { //note: if the beginning value (bn) is 0, we don't need to convert units!
+ bn = _convertToPixels(target, p, bn, bsfx);
+ if (esfx === "%") {
+ bn /= _convertToPixels(target, p, 100, "%") / 100;
+ if (vars.strictUnits !== true) { //some browsers report only "px" values instead of allowing "%" with getComputedStyle(), so we assume that if we're tweening to a %, we should start there too unless strictUnits:true is defined. This approach is particularly useful for responsive designs that use from() tweens.
+ bs = bn + "%";
+ }
+
+ } else if (esfx === "em") {
+ bn /= _convertToPixels(target, p, 1, "em");
+
+ //otherwise convert to pixels.
+ } else if (esfx !== "px") {
+ en = _convertToPixels(target, p, en, esfx);
+ esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too.
+ }
+ if (rel) if (en || en === 0) {
+ es = (en + bn) + esfx; //the changes we made affect relative calculations, so adjust the end value here.
+ }
+ }
+
+ if (rel) {
+ en += bn;
+ }
+
+ if ((bn || bn === 0) && (en || en === 0)) { //faster than isNaN(). Also, previously we required en !== bn but that doesn't really gain much performance and it prevents _parseToProxy() from working properly if beginning and ending values match but need to get tweened by an external plugin anyway. For example, a bezier tween where the target starts at left:0 and has these points: [{left:50},{left:0}] wouldn't work properly because when parsing the last point, it'd match the first (current) one and a non-tweening CSSPropTween would be recorded when we actually need a normal tween (type:0) so that things get updated during the tween properly.
+ pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, (_autoRound !== false && (esfx === "px" || p === "zIndex")), 0, bs, es);
+ pt.xs0 = esfx;
+ //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0);
+ } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) {
+ _log("invalid " + p + " tween value: " + vars[p]);
+ } else {
+ pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es);
+ pt.xs0 = (es === "none" && (p === "display" || p.indexOf("Style") !== -1)) ? bs : es; //intermediate value should typically be set immediately (end value) except for "display" or things like borderTopStyle, borderBottomStyle, etc. which should use the beginning value during the tween.
+ //DEBUG: _log("non-tweening value "+p+": "+pt.xs0);
+ }
+ }
+ }
+ if (plugin) if (pt && !pt.plugin) {
+ pt.plugin = plugin;
+ }
+ }
+ return pt;
+ };
+
+
+ //gets called every time the tween updates, passing the new ratio (typically a value between 0 and 1, but not always (for example, if an Elastic.easeOut is used, the value can jump above 1 mid-tween). It will always start and 0 and end at 1.
+ p.setRatio = function(v) {
+ var pt = this._firstPT,
+ min = 0.000001,
+ val, str, i;
+
+ //at the end of the tween, we set the values to exactly what we received in order to make sure non-tweening values (like "position" or "float" or whatever) are set and so that if the beginning/ending suffixes (units) didn't match and we normalized to px, the value that the user passed in is used here. We check to see if the tween is at its beginning in case it's a from() tween in which case the ratio will actually go from 1 to 0 over the course of the tween (backwards).
+ if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) {
+ while (pt) {
+ if (pt.type !== 2) {
+ pt.t[pt.p] = pt.e;
+ } else {
+ pt.setRatio(v);
+ }
+ pt = pt._next;
+ }
+
+ } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) {
+ while (pt) {
+ val = pt.c * v + pt.s;
+ if (pt.r) {
+ val = Math.round(val);
+ } else if (val < min) if (val > -min) {
+ val = 0;
+ }
+ if (!pt.type) {
+ pt.t[pt.p] = val + pt.xs0;
+ } else if (pt.type === 1) { //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)"
+ i = pt.l;
+ if (i === 2) {
+ pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2;
+ } else if (i === 3) {
+ pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3;
+ } else if (i === 4) {
+ pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4;
+ } else if (i === 5) {
+ pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4 + pt.xn4 + pt.xs5;
+ } else {
+ str = pt.xs0 + val + pt.xs1;
+ for (i = 1; i < pt.l; i++) {
+ str += pt["xn"+i] + pt["xs"+(i+1)];
+ }
+ pt.t[pt.p] = str;
+ }
+
+ } else if (pt.type === -1) { //non-tweening value
+ pt.t[pt.p] = pt.xs0;
+
+ } else if (pt.setRatio) { //custom setRatio() for things like SpecialProps, external plugins, etc.
+ pt.setRatio(v);
+ }
+ pt = pt._next;
+ }
+
+ //if the tween is reversed all the way back to the beginning, we need to restore the original values which may have different units (like % instead of px or em or whatever).
+ } else {
+ while (pt) {
+ if (pt.type !== 2) {
+ pt.t[pt.p] = pt.b;
+ } else {
+ pt.setRatio(v);
+ }
+ pt = pt._next;
+ }
+ }
+ };
+
+ /**
+ * @private
+ * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called.
+ * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked
+ * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call
+ * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin
+ * doesn't have any transform-related properties of its own. You can call this method as many times as you
+ * want and it won't create duplicate CSSPropTweens.
+ *
+ * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster)
+ */
+ p._enableTransforms = function(threeD) {
+ this._transformType = (threeD || this._transformType === 3) ? 3 : 2;
+ this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
+ };
+
+ var lazySet = function(v) {
+ this.t[this.p] = this.e;
+ this.data._linkCSSP(this, this._next, null, true); //we purposefully keep this._next even though it'd make sense to null it, but this is a performance optimization, as this happens during the while (pt) {} loop in setRatio() at the bottom of which it sets pt = pt._next, so if we null it, the linked list will be broken in that loop.
+ };
+ /** @private Gives us a way to set a value on the first render (and only the first render). **/
+ p._addLazySet = function(t, p, v) {
+ var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
+ pt.e = v;
+ pt.setRatio = lazySet;
+ pt.data = this;
+ };
+
+ /** @private **/
+ p._linkCSSP = function(pt, next, prev, remove) {
+ if (pt) {
+ if (next) {
+ next._prev = pt;
+ }
+ if (pt._next) {
+ pt._next._prev = pt._prev;
+ }
+ if (pt._prev) {
+ pt._prev._next = pt._next;
+ } else if (this._firstPT === pt) {
+ this._firstPT = pt._next;
+ remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed)
+ }
+ if (prev) {
+ prev._next = pt;
+ } else if (!remove && this._firstPT === null) {
+ this._firstPT = pt;
+ }
+ pt._next = next;
+ pt._prev = prev;
+ }
+ return pt;
+ };
+
+ //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property.
+ p._kill = function(lookup) {
+ var copy = lookup,
+ pt, p, xfirst;
+ if (lookup.autoAlpha || lookup.alpha) {
+ copy = {};
+ for (p in lookup) { //copy the lookup so that we're not changing the original which may be passed elsewhere.
+ copy[p] = lookup[p];
+ }
+ copy.opacity = 1;
+ if (copy.autoAlpha) {
+ copy.visibility = 1;
+ }
+ }
+ if (lookup.className && (pt = this._classNamePT)) { //for className tweens, we need to kill any associated CSSPropTweens too; a linked list starts at the className's "xfirst".
+ xfirst = pt.xfirst;
+ if (xfirst && xfirst._prev) {
+ this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev
+ } else if (xfirst === this._firstPT) {
+ this._firstPT = pt._next;
+ }
+ if (pt._next) {
+ this._linkCSSP(pt._next, pt._next._next, xfirst._prev);
+ }
+ this._classNamePT = null;
+ }
+ return TweenPlugin.prototype._kill.call(this, copy);
+ };
+
+
+
+ //used by cascadeTo() for gathering all the style properties of each child element into an array for comparison.
+ var _getChildStyles = function(e, props, targets) {
+ var children, i, child, type;
+ if (e.slice) {
+ i = e.length;
+ while (--i > -1) {
+ _getChildStyles(e[i], props, targets);
+ }
+ return;
+ }
+ children = e.childNodes;
+ i = children.length;
+ while (--i > -1) {
+ child = children[i];
+ type = child.type;
+ if (child.style) {
+ props.push(_getAllStyles(child));
+ if (targets) {
+ targets.push(child);
+ }
+ }
+ if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) {
+ _getChildStyles(child, props, targets);
+ }
+ }
+ };
+
+ /**
+ * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite
+ * and then compares the style properties of all the target's child elements at the tween's start and end, and
+ * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting
+ * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is
+ * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens
+ * is because it creates entirely new tweens that may have completely different targets than the original tween,
+ * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API
+ * and it would create other problems. For example:
+ * - If I create a tween of elementA, that tween instance may suddenly change its target to include 50 other elements (unintuitive if I specifically defined the target I wanted)
+ * - We can't just create new independent tweens because otherwise, what happens if the original/parent tween is reversed or pause or dropped into a TimelineLite for tight control? You'd expect that tween's behavior to affect all the others.
+ * - Analyzing every style property of every child before and after the tween is an expensive operation when there are many children, so this behavior shouldn't be imposed on all className tweens by default, especially since it's probably rare that this extra functionality is needed.
+ *
+ * @param {Object} target object to be tweened
+ * @param {number} Duration in seconds (or frames for frames-based tweens)
+ * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone}
+ * @return {Array} An array of TweenLite instances
+ */
+ CSSPlugin.cascadeTo = function(target, duration, vars) {
+ var tween = TweenLite.to(target, duration, vars),
+ results = [tween],
+ b = [],
+ e = [],
+ targets = [],
+ _reservedProps = TweenLite._internals.reservedProps,
+ i, difs, p;
+ target = tween._targets || tween.target;
+ _getChildStyles(target, b, targets);
+ tween.render(duration, true);
+ _getChildStyles(target, e);
+ tween.render(0, true);
+ tween._enabled(true);
+ i = targets.length;
+ while (--i > -1) {
+ difs = _cssDif(targets[i], b[i], e[i]);
+ if (difs.firstMPT) {
+ difs = difs.difs;
+ for (p in vars) {
+ if (_reservedProps[p]) {
+ difs[p] = vars[p];
+ }
+ }
+ results.push( TweenLite.to(targets[i], duration, difs) );
+ }
+ }
+ return results;
+ };
+
+ TweenPlugin.activate([CSSPlugin]);
+ return CSSPlugin;
+
+ }, true);
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * RoundPropsPlugin
+ * ----------------------------------------------------------------
+ */
+ (function() {
+
+ var RoundPropsPlugin = window._gsDefine.plugin({
+ propName: "roundProps",
+ priority: -1,
+ API: 2,
+
+ //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
+ init: function(target, value, tween) {
+ this._tween = tween;
+ return true;
+ }
+
+ }),
+ p = RoundPropsPlugin.prototype;
+
+ p._onInitAllProps = function() {
+ var tween = this._tween,
+ rp = (tween.vars.roundProps instanceof Array) ? tween.vars.roundProps : tween.vars.roundProps.split(","),
+ i = rp.length,
+ lookup = {},
+ rpt = tween._propLookup.roundProps,
+ prop, pt, next;
+ while (--i > -1) {
+ lookup[rp[i]] = 1;
+ }
+ i = rp.length;
+ while (--i > -1) {
+ prop = rp[i];
+ pt = tween._firstPT;
+ while (pt) {
+ next = pt._next; //record here, because it may get removed
+ if (pt.pg) {
+ pt.t._roundProps(lookup, true);
+ } else if (pt.n === prop) {
+ this._add(pt.t, prop, pt.s, pt.c);
+ //remove from linked list
+ if (next) {
+ next._prev = pt._prev;
+ }
+ if (pt._prev) {
+ pt._prev._next = next;
+ } else if (tween._firstPT === pt) {
+ tween._firstPT = next;
+ }
+ pt._next = pt._prev = null;
+ tween._propLookup[prop] = rpt;
+ }
+ pt = next;
+ }
+ }
+ return false;
+ };
+
+ p._add = function(target, p, s, c) {
+ this._addTween(target, p, s, s + c, p, true);
+ this._overwriteProps.push(p);
+ };
+
+ }());
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * AttrPlugin
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine.plugin({
+ propName: "attr",
+ API: 2,
+ version: "0.3.2",
+
+ //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
+ init: function(target, value, tween) {
+ var p, start, end;
+ if (typeof(target.setAttribute) !== "function") {
+ return false;
+ }
+ this._target = target;
+ this._proxy = {};
+ this._start = {}; // we record start and end values exactly as they are in case they're strings (not numbers) - we need to be able to revert to them cleanly.
+ this._end = {};
+ for (p in value) {
+ this._start[p] = this._proxy[p] = start = target.getAttribute(p);
+ end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
+ this._end[p] = end ? end.s + end.c : value[p];
+ this._overwriteProps.push(p);
+ }
+ return true;
+ },
+
+ //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
+ set: function(ratio) {
+ this._super.setRatio.call(this, ratio);
+ var props = this._overwriteProps,
+ i = props.length,
+ lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
+ p;
+ while (--i > -1) {
+ p = props[i];
+ this._target.setAttribute(p, lookup[p] + "");
+ }
+ }
+
+ });
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * DirectionalRotationPlugin
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine.plugin({
+ propName: "directionalRotation",
+ API: 2,
+ version: "0.2.0",
+
+ //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
+ init: function(target, value, tween) {
+ if (typeof(value) !== "object") {
+ value = {rotation:value};
+ }
+ this.finals = {};
+ var cap = (value.useRadians === true) ? Math.PI * 2 : 360,
+ min = 0.000001,
+ p, v, start, end, dif, split;
+ for (p in value) {
+ if (p !== "useRadians") {
+ split = (value[p] + "").split("_");
+ v = split[0];
+ start = parseFloat( (typeof(target[p]) !== "function") ? target[p] : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]() );
+ end = this.finals[p] = (typeof(v) === "string" && v.charAt(1) === "=") ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0;
+ dif = end - start;
+ if (split.length) {
+ v = split.join("_");
+ if (v.indexOf("short") !== -1) {
+ dif = dif % cap;
+ if (dif !== dif % (cap / 2)) {
+ dif = (dif < 0) ? dif + cap : dif - cap;
+ }
+ }
+ if (v.indexOf("_cw") !== -1 && dif < 0) {
+ dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
+ } else if (v.indexOf("ccw") !== -1 && dif > 0) {
+ dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
+ }
+ }
+ if (dif > min || dif < -min) {
+ this._addTween(target, p, start, start + dif, p);
+ this._overwriteProps.push(p);
+ }
+ }
+ }
+ return true;
+ },
+
+ //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
+ set: function(ratio) {
+ var pt;
+ if (ratio !== 1) {
+ this._super.setRatio.call(this, ratio);
+ } else {
+ pt = this._firstPT;
+ while (pt) {
+ if (pt.f) {
+ pt.t[pt.p](this.finals[pt.p]);
+ } else {
+ pt.t[pt.p] = this.finals[pt.p];
+ }
+ pt = pt._next;
+ }
+ }
+ }
+
+ })._autoCSS = true;
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * EasePack
+ * ----------------------------------------------------------------
+ */
+ window._gsDefine("easing.Back", ["easing.Ease"], function(Ease) {
+
+ var w = (window.GreenSockGlobals || window),
+ gs = w.com.greensock,
+ _2PI = Math.PI * 2,
+ _HALF_PI = Math.PI / 2,
+ _class = gs._class,
+ _create = function(n, f) {
+ var C = _class("easing." + n, function(){}, true),
+ p = C.prototype = new Ease();
+ p.constructor = C;
+ p.getRatio = f;
+ return C;
+ },
+ _easeReg = Ease.register || function(){}, //put an empty function in place just as a safety measure in case someone loads an OLD version of TweenLite.js where Ease.register doesn't exist.
+ _wrap = function(name, EaseOut, EaseIn, EaseInOut, aliases) {
+ var C = _class("easing."+name, {
+ easeOut:new EaseOut(),
+ easeIn:new EaseIn(),
+ easeInOut:new EaseInOut()
+ }, true);
+ _easeReg(C, name);
+ return C;
+ },
+ EasePoint = function(time, value, next) {
+ this.t = time;
+ this.v = value;
+ if (next) {
+ this.next = next;
+ next.prev = this;
+ this.c = next.v - value;
+ this.gap = next.t - time;
+ }
+ },
+
+ //Back
+ _createBack = function(n, f) {
+ var C = _class("easing." + n, function(overshoot) {
+ this._p1 = (overshoot || overshoot === 0) ? overshoot : 1.70158;
+ this._p2 = this._p1 * 1.525;
+ }, true),
+ p = C.prototype = new Ease();
+ p.constructor = C;
+ p.getRatio = f;
+ p.config = function(overshoot) {
+ return new C(overshoot);
+ };
+ return C;
+ },
+
+ Back = _wrap("Back",
+ _createBack("BackOut", function(p) {
+ return ((p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1);
+ }),
+ _createBack("BackIn", function(p) {
+ return p * p * ((this._p1 + 1) * p - this._p1);
+ }),
+ _createBack("BackInOut", function(p) {
+ return ((p *= 2) < 1) ? 0.5 * p * p * ((this._p2 + 1) * p - this._p2) : 0.5 * ((p -= 2) * p * ((this._p2 + 1) * p + this._p2) + 2);
+ })
+ ),
+
+
+ //SlowMo
+ SlowMo = _class("easing.SlowMo", function(linearRatio, power, yoyoMode) {
+ power = (power || power === 0) ? power : 0.7;
+ if (linearRatio == null) {
+ linearRatio = 0.7;
+ } else if (linearRatio > 1) {
+ linearRatio = 1;
+ }
+ this._p = (linearRatio !== 1) ? power : 0;
+ this._p1 = (1 - linearRatio) / 2;
+ this._p2 = linearRatio;
+ this._p3 = this._p1 + this._p2;
+ this._calcEnd = (yoyoMode === true);
+ }, true),
+ p = SlowMo.prototype = new Ease(),
+ SteppedEase, RoughEase, _createElastic;
+
+ p.constructor = SlowMo;
+ p.getRatio = function(p) {
+ var r = p + (0.5 - p) * this._p;
+ if (p < this._p1) {
+ return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
+ } else if (p > this._p3) {
+ return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
+ }
+ return this._calcEnd ? 1 : r;
+ };
+ SlowMo.ease = new SlowMo(0.7, 0.7);
+
+ p.config = SlowMo.config = function(linearRatio, power, yoyoMode) {
+ return new SlowMo(linearRatio, power, yoyoMode);
+ };
+
+
+ //SteppedEase
+ SteppedEase = _class("easing.SteppedEase", function(steps) {
+ steps = steps || 1;
+ this._p1 = 1 / steps;
+ this._p2 = steps + 1;
+ }, true);
+ p = SteppedEase.prototype = new Ease();
+ p.constructor = SteppedEase;
+ p.getRatio = function(p) {
+ if (p < 0) {
+ p = 0;
+ } else if (p >= 1) {
+ p = 0.999999999;
+ }
+ return ((this._p2 * p) >> 0) * this._p1;
+ };
+ p.config = SteppedEase.config = function(steps) {
+ return new SteppedEase(steps);
+ };
+
+
+ //RoughEase
+ RoughEase = _class("easing.RoughEase", function(vars) {
+ vars = vars || {};
+ var taper = vars.taper || "none",
+ a = [],
+ cnt = 0,
+ points = (vars.points || 20) | 0,
+ i = points,
+ randomize = (vars.randomize !== false),
+ clamp = (vars.clamp === true),
+ template = (vars.template instanceof Ease) ? vars.template : null,
+ strength = (typeof(vars.strength) === "number") ? vars.strength * 0.4 : 0.4,
+ x, y, bump, invX, obj, pnt;
+ while (--i > -1) {
+ x = randomize ? Math.random() : (1 / points) * i;
+ y = template ? template.getRatio(x) : x;
+ if (taper === "none") {
+ bump = strength;
+ } else if (taper === "out") {
+ invX = 1 - x;
+ bump = invX * invX * strength;
+ } else if (taper === "in") {
+ bump = x * x * strength;
+ } else if (x < 0.5) { //"both" (start)
+ invX = x * 2;
+ bump = invX * invX * 0.5 * strength;
+ } else { //"both" (end)
+ invX = (1 - x) * 2;
+ bump = invX * invX * 0.5 * strength;
+ }
+ if (randomize) {
+ y += (Math.random() * bump) - (bump * 0.5);
+ } else if (i % 2) {
+ y += bump * 0.5;
+ } else {
+ y -= bump * 0.5;
+ }
+ if (clamp) {
+ if (y > 1) {
+ y = 1;
+ } else if (y < 0) {
+ y = 0;
+ }
+ }
+ a[cnt++] = {x:x, y:y};
+ }
+ a.sort(function(a, b) {
+ return a.x - b.x;
+ });
+
+ pnt = new EasePoint(1, 1, null);
+ i = points;
+ while (--i > -1) {
+ obj = a[i];
+ pnt = new EasePoint(obj.x, obj.y, pnt);
+ }
+
+ this._prev = new EasePoint(0, 0, (pnt.t !== 0) ? pnt : pnt.next);
+ }, true);
+ p = RoughEase.prototype = new Ease();
+ p.constructor = RoughEase;
+ p.getRatio = function(p) {
+ var pnt = this._prev;
+ if (p > pnt.t) {
+ while (pnt.next && p >= pnt.t) {
+ pnt = pnt.next;
+ }
+ pnt = pnt.prev;
+ } else {
+ while (pnt.prev && p <= pnt.t) {
+ pnt = pnt.prev;
+ }
+ }
+ this._prev = pnt;
+ return (pnt.v + ((p - pnt.t) / pnt.gap) * pnt.c);
+ };
+ p.config = function(vars) {
+ return new RoughEase(vars);
+ };
+ RoughEase.ease = new RoughEase();
+
+
+ //Bounce
+ _wrap("Bounce",
+ _create("BounceOut", function(p) {
+ if (p < 1 / 2.75) {
+ return 7.5625 * p * p;
+ } else if (p < 2 / 2.75) {
+ return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
+ } else if (p < 2.5 / 2.75) {
+ return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
+ }
+ return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
+ }),
+ _create("BounceIn", function(p) {
+ if ((p = 1 - p) < 1 / 2.75) {
+ return 1 - (7.5625 * p * p);
+ } else if (p < 2 / 2.75) {
+ return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);
+ } else if (p < 2.5 / 2.75) {
+ return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);
+ }
+ return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);
+ }),
+ _create("BounceInOut", function(p) {
+ var invert = (p < 0.5);
+ if (invert) {
+ p = 1 - (p * 2);
+ } else {
+ p = (p * 2) - 1;
+ }
+ if (p < 1 / 2.75) {
+ p = 7.5625 * p * p;
+ } else if (p < 2 / 2.75) {
+ p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
+ } else if (p < 2.5 / 2.75) {
+ p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
+ } else {
+ p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
+ }
+ return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5;
+ })
+ );
+
+
+ //CIRC
+ _wrap("Circ",
+ _create("CircOut", function(p) {
+ return Math.sqrt(1 - (p = p - 1) * p);
+ }),
+ _create("CircIn", function(p) {
+ return -(Math.sqrt(1 - (p * p)) - 1);
+ }),
+ _create("CircInOut", function(p) {
+ return ((p*=2) < 1) ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1);
+ })
+ );
+
+
+ //Elastic
+ _createElastic = function(n, f, def) {
+ var C = _class("easing." + n, function(amplitude, period) {
+ this._p1 = amplitude || 1;
+ this._p2 = period || def;
+ this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0);
+ }, true),
+ p = C.prototype = new Ease();
+ p.constructor = C;
+ p.getRatio = f;
+ p.config = function(amplitude, period) {
+ return new C(amplitude, period);
+ };
+ return C;
+ };
+ _wrap("Elastic",
+ _createElastic("ElasticOut", function(p) {
+ return this._p1 * Math.pow(2, -10 * p) * Math.sin( (p - this._p3) * _2PI / this._p2 ) + 1;
+ }, 0.3),
+ _createElastic("ElasticIn", function(p) {
+ return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ));
+ }, 0.3),
+ _createElastic("ElasticInOut", function(p) {
+ return ((p *= 2) < 1) ? -0.5 * (this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2)) : this._p1 * Math.pow(2, -10 *(p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ) *0.5 + 1;
+ }, 0.45)
+ );
+
+
+ //Expo
+ _wrap("Expo",
+ _create("ExpoOut", function(p) {
+ return 1 - Math.pow(2, -10 * p);
+ }),
+ _create("ExpoIn", function(p) {
+ return Math.pow(2, 10 * (p - 1)) - 0.001;
+ }),
+ _create("ExpoInOut", function(p) {
+ return ((p *= 2) < 1) ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
+ })
+ );
+
+
+ //Sine
+ _wrap("Sine",
+ _create("SineOut", function(p) {
+ return Math.sin(p * _HALF_PI);
+ }),
+ _create("SineIn", function(p) {
+ return -Math.cos(p * _HALF_PI) + 1;
+ }),
+ _create("SineInOut", function(p) {
+ return -0.5 * (Math.cos(Math.PI * p) - 1);
+ })
+ );
+
+ _class("easing.EaseLookup", {
+ find:function(s) {
+ return Ease.map[s];
+ }
+ }, true);
+
+ //register the non-standard eases
+ _easeReg(w.SlowMo, "SlowMo", "ease,");
+ _easeReg(RoughEase, "RoughEase", "ease,");
+ _easeReg(SteppedEase, "SteppedEase", "ease,");
+
+ return Back;
+
+ }, true);
+
+
+});
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc.
+ * ----------------------------------------------------------------
+ */
+(function(window) {
+
+ "use strict";
+ var _globals = window.GreenSockGlobals || window;
+ if (_globals.TweenLite) {
+ return; //in case the core set of classes is already loaded, don't instantiate twice.
+ }
+ var _namespace = function(ns) {
+ var a = ns.split("."),
+ p = _globals, i;
+ for (i = 0; i < a.length; i++) {
+ p[a[i]] = p = p[a[i]] || {};
+ }
+ return p;
+ },
+ gs = _namespace("com.greensock"),
+ _tinyNum = 0.0000000001,
+ _slice = [].slice,
+ _emptyFunc = function() {},
+ _isArray = (function() { //works around issues in iframe environments where the Array global isn't shared, thus if the object originates in a different window/iframe, "(obj instanceof Array)" will evaluate false. We added some speed optimizations to avoid Object.prototype.toString.call() unless it's absolutely necessary because it's VERY slow (like 20x slower)
+ var toString = Object.prototype.toString,
+ array = toString.call([]);
+ return function(obj) {
+ return obj != null && (obj instanceof Array || (typeof(obj) === "object" && !!obj.push && toString.call(obj) === array));
+ };
+ }()),
+ a, i, p, _ticker, _tickerActive,
+ _defLookup = {},
+
+ /**
+ * @constructor
+ * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition.
+ * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is
+ * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin
+ * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally.
+ *
+ * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found,
+ * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere,
+ * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so
+ * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything
+ * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock
+ * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could
+ * sandbox the banner one like:
+ *
+ * <script>
+ * var gs = window.GreenSockGlobals = {}; //the newer version we're about to load could now be referenced in a "gs" object, like gs.TweenLite.to(...). Use whatever alias you want as long as it's unique, "gs" or "banner" or whatever.
+ * </script>
+ * <script src="js/greensock/v1.7/TweenMax.js"></script>
+ * <script>
+ * window.GreenSockGlobals = null; //reset it back to null so that the next load of TweenMax affects the window and we can reference things directly like TweenLite.to(...)
+ * </script>
+ * <script src="js/greensock/v1.6/TweenMax.js"></script>
+ * <script>
+ * gs.TweenLite.to(...); //would use v1.7
+ * TweenLite.to(...); //would use v1.6
+ * </script>
+ *
+ * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back".
+ * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"]
+ * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition.
+ * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object)
+ */
+ Definition = function(ns, dependencies, func, global) {
+ this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses
+ _defLookup[ns] = this;
+ this.gsClass = null;
+ this.func = func;
+ var _classes = [];
+ this.check = function(init) {
+ var i = dependencies.length,
+ missing = i,
+ cur, a, n, cl;
+ while (--i > -1) {
+ if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) {
+ _classes[i] = cur.gsClass;
+ missing--;
+ } else if (init) {
+ cur.sc.push(this);
+ }
+ }
+ if (missing === 0 && func) {
+ a = ("com.greensock." + ns).split(".");
+ n = a.pop();
+ cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes);
+
+ //exports to multiple environments
+ if (global) {
+ _globals[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.)
+ if (typeof(define) === "function" && define.amd){ //AMD
+ define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; });
+ } else if (typeof(module) !== "undefined" && module.exports){ //node
+ module.exports = cl;
+ }
+ }
+ for (i = 0; i < this.sc.length; i++) {
+ this.sc[i].check();
+ }
+ }
+ };
+ this.check(true);
+ },
+
+ //used to create Definition instances (which basically registers a class that has dependencies).
+ _gsDefine = window._gsDefine = function(ns, dependencies, func, global) {
+ return new Definition(ns, dependencies, func, global);
+ },
+
+ //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class).
+ _class = gs._class = function(ns, func, global) {
+ func = func || function() {};
+ _gsDefine(ns, [], function(){ return func; }, global);
+ return func;
+ };
+
+ _gsDefine.globals = _globals;
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * Ease
+ * ----------------------------------------------------------------
+ */
+ var _baseParams = [0, 0, 1, 1],
+ _blankArray = [],
+ Ease = _class("easing.Ease", function(func, extraParams, type, power) {
+ this._func = func;
+ this._type = type || 0;
+ this._power = power || 0;
+ this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams;
+ }, true),
+ _easeMap = Ease.map = {},
+ _easeReg = Ease.register = function(ease, names, types, create) {
+ var na = names.split(","),
+ i = na.length,
+ ta = (types || "easeIn,easeOut,easeInOut").split(","),
+ e, name, j, type;
+ while (--i > -1) {
+ name = na[i];
+ e = create ? _class("easing."+name, null, true) : gs.easing[name] || {};
+ j = ta.length;
+ while (--j > -1) {
+ type = ta[j];
+ _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease();
+ }
+ }
+ };
+
+ p = Ease.prototype;
+ p._calcEnd = false;
+ p.getRatio = function(p) {
+ if (this._func) {
+ this._params[0] = p;
+ return this._func.apply(null, this._params);
+ }
+ var t = this._type,
+ pw = this._power,
+ r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2;
+ if (pw === 1) {
+ r *= r;
+ } else if (pw === 2) {
+ r *= r * r;
+ } else if (pw === 3) {
+ r *= r * r * r;
+ } else if (pw === 4) {
+ r *= r * r * r * r;
+ }
+ return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2);
+ };
+
+ //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut)
+ a = ["Linear","Quad","Cubic","Quart","Quint,Strong"];
+ i = a.length;
+ while (--i > -1) {
+ p = a[i]+",Power"+i;
+ _easeReg(new Ease(null,null,1,i), p, "easeOut", true);
+ _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : ""));
+ _easeReg(new Ease(null,null,3,i), p, "easeInOut");
+ }
+ _easeMap.linear = gs.easing.Linear.easeIn;
+ _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks
+
+
+/*
+ * ----------------------------------------------------------------
+ * EventDispatcher
+ * ----------------------------------------------------------------
+ */
+ var EventDispatcher = _class("events.EventDispatcher", function(target) {
+ this._listeners = {};
+ this._eventTarget = target || this;
+ });
+ p = EventDispatcher.prototype;
+
+ p.addEventListener = function(type, callback, scope, useParam, priority) {
+ priority = priority || 0;
+ var list = this._listeners[type],
+ index = 0,
+ listener, i;
+ if (list == null) {
+ this._listeners[type] = list = [];
+ }
+ i = list.length;
+ while (--i > -1) {
+ listener = list[i];
+ if (listener.c === callback && listener.s === scope) {
+ list.splice(i, 1);
+ } else if (index === 0 && listener.pr < priority) {
+ index = i + 1;
+ }
+ }
+ list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority});
+ if (this === _ticker && !_tickerActive) {
+ _ticker.wake();
+ }
+ };
+
+ p.removeEventListener = function(type, callback) {
+ var list = this._listeners[type], i;
+ if (list) {
+ i = list.length;
+ while (--i > -1) {
+ if (list[i].c === callback) {
+ list.splice(i, 1);
+ return;
+ }
+ }
+ }
+ };
+
+ p.dispatchEvent = function(type) {
+ var list = this._listeners[type],
+ i, t, listener;
+ if (list) {
+ i = list.length;
+ t = this._eventTarget;
+ while (--i > -1) {
+ listener = list[i];
+ if (listener.up) {
+ listener.c.call(listener.s || t, {type:type, target:t});
+ } else {
+ listener.c.call(listener.s || t);
+ }
+ }
+ }
+ };
+
+
+/*
+ * ----------------------------------------------------------------
+ * Ticker
+ * ----------------------------------------------------------------
+ */
+ var _reqAnimFrame = window.requestAnimationFrame,
+ _cancelAnimFrame = window.cancelAnimationFrame,
+ _getTime = Date.now || function() {return new Date().getTime();},
+ _lastUpdate = _getTime();
+
+ //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill.
+ a = ["ms","moz","webkit","o"];
+ i = a.length;
+ while (--i > -1 && !_reqAnimFrame) {
+ _reqAnimFrame = window[a[i] + "RequestAnimationFrame"];
+ _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"];
+ }
+
+ _class("Ticker", function(fps, useRAF) {
+ var _self = this,
+ _startTime = _getTime(),
+ _useRAF = (useRAF !== false && _reqAnimFrame),
+ _lagThreshold = 500,
+ _adjustedLag = 33,
+ _fps, _req, _id, _gap, _nextTime,
+ _tick = function(manual) {
+ var elapsed = _getTime() - _lastUpdate,
+ overlap, dispatch;
+ if (elapsed > _lagThreshold) {
+ _startTime += elapsed - _adjustedLag;
+ }
+ _lastUpdate += elapsed;
+ _self.time = (_lastUpdate - _startTime) / 1000;
+ overlap = _self.time - _nextTime;
+ if (!_fps || overlap > 0 || manual === true) {
+ _self.frame++;
+ _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
+ dispatch = true;
+ }
+ if (manual !== true) { //make sure the request is made before we dispatch the "tick" event so that timing is maintained. Otherwise, if processing the "tick" requires a bunch of time (like 15ms) and we're using a setTimeout() that's based on 16.7ms, it'd technically take 31.7ms between frames otherwise.
+ _id = _req(_tick);
+ }
+ if (dispatch) {
+ _self.dispatchEvent("tick");
+ }
+ };
+
+ EventDispatcher.call(_self);
+ _self.time = _self.frame = 0;
+ _self.tick = function() {
+ _tick(true);
+ };
+
+ _self.lagSmoothing = function(threshold, adjustedLag) {
+ _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
+ _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
+ };
+
+ _self.sleep = function() {
+ if (_id == null) {
+ return;
+ }
+ if (!_useRAF || !_cancelAnimFrame) {
+ clearTimeout(_id);
+ } else {
+ _cancelAnimFrame(_id);
+ }
+ _req = _emptyFunc;
+ _id = null;
+ if (_self === _ticker) {
+ _tickerActive = false;
+ }
+ };
+
+ _self.wake = function() {
+ if (_id !== null) {
+ _self.sleep();
+ } else if (_self.frame > 10) { //don't trigger lagSmoothing if we're just waking up, and make sure that at least 10 frames have elapsed because of the iOS bug that we work around below with the 1.5-second setTimout().
+ _lastUpdate = _getTime() - _lagThreshold + 5;
+ }
+ _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
+ if (_self === _ticker) {
+ _tickerActive = true;
+ }
+ _tick(2);
+ };
+
+ _self.fps = function(value) {
+ if (!arguments.length) {
+ return _fps;
+ }
+ _fps = value;
+ _gap = 1 / (_fps || 60);
+ _nextTime = this.time + _gap;
+ _self.wake();
+ };
+
+ _self.useRAF = function(value) {
+ if (!arguments.length) {
+ return _useRAF;
+ }
+ _self.sleep();
+ _useRAF = value;
+ _self.fps(_fps);
+ };
+ _self.fps(fps);
+
+ //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition.
+ setTimeout(function() {
+ if (_useRAF && (!_id || _self.frame < 5)) {
+ _self.useRAF(false);
+ }
+ }, 1500);
+ });
+
+ p = gs.Ticker.prototype = new gs.events.EventDispatcher();
+ p.constructor = gs.Ticker;
+
+
+/*
+ * ----------------------------------------------------------------
+ * Animation
+ * ----------------------------------------------------------------
+ */
+ var Animation = _class("core.Animation", function(duration, vars) {
+ this.vars = vars = vars || {};
+ this._duration = this._totalDuration = duration || 0;
+ this._delay = Number(vars.delay) || 0;
+ this._timeScale = 1;
+ this._active = (vars.immediateRender === true);
+ this.data = vars.data;
+ this._reversed = (vars.reversed === true);
+
+ if (!_rootTimeline) {
+ return;
+ }
+ if (!_tickerActive) { //some browsers (like iOS 6 Safari) shut down JavaScript execution when the tab is disabled and they [occasionally] neglect to start up requestAnimationFrame again when returning - this code ensures that the engine starts up again properly.
+ _ticker.wake();
+ }
+
+ var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline;
+ tl.add(this, tl._time);
+
+ if (this.vars.paused) {
+ this.paused(true);
+ }
+ });
+
+ _ticker = Animation.ticker = new gs.Ticker();
+ p = Animation.prototype;
+ p._dirty = p._gc = p._initted = p._paused = false;
+ p._totalTime = p._time = 0;
+ p._rawPrevTime = -1;
+ p._next = p._last = p._onUpdate = p._timeline = p.timeline = null;
+ p._paused = false;
+
+
+ //some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker.
+ var _checkTimeout = function() {
+ if (_tickerActive && _getTime() - _lastUpdate > 2000) {
+ _ticker.wake();
+ }
+ setTimeout(_checkTimeout, 2000);
+ };
+ _checkTimeout();
+
+
+ p.play = function(from, suppressEvents) {
+ if (from != null) {
+ this.seek(from, suppressEvents);
+ }
+ return this.reversed(false).paused(false);
+ };
+
+ p.pause = function(atTime, suppressEvents) {
+ if (atTime != null) {
+ this.seek(atTime, suppressEvents);
+ }
+ return this.paused(true);
+ };
+
+ p.resume = function(from, suppressEvents) {
+ if (from != null) {
+ this.seek(from, suppressEvents);
+ }
+ return this.paused(false);
+ };
+
+ p.seek = function(time, suppressEvents) {
+ return this.totalTime(Number(time), suppressEvents !== false);
+ };
+
+ p.restart = function(includeDelay, suppressEvents) {
+ return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true);
+ };
+
+ p.reverse = function(from, suppressEvents) {
+ if (from != null) {
+ this.seek((from || this.totalDuration()), suppressEvents);
+ }
+ return this.reversed(true).paused(false);
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ //stub - we override this method in subclasses.
+ };
+
+ p.invalidate = function() {
+ return this;
+ };
+
+ p.isActive = function() {
+ var tl = this._timeline, //the 2 root timelines won't have a _timeline; they're always active.
+ startTime = this._startTime,
+ rawTime;
+ return (!tl || (!this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime()) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale));
+ };
+
+ p._enabled = function (enabled, ignoreTimeline) {
+ if (!_tickerActive) {
+ _ticker.wake();
+ }
+ this._gc = !enabled;
+ this._active = this.isActive();
+ if (ignoreTimeline !== true) {
+ if (enabled && !this.timeline) {
+ this._timeline.add(this, this._startTime - this._delay);
+ } else if (!enabled && this.timeline) {
+ this._timeline._remove(this, true);
+ }
+ }
+ return false;
+ };
+
+
+ p._kill = function(vars, target) {
+ return this._enabled(false, false);
+ };
+
+ p.kill = function(vars, target) {
+ this._kill(vars, target);
+ return this;
+ };
+
+ p._uncache = function(includeSelf) {
+ var tween = includeSelf ? this : this.timeline;
+ while (tween) {
+ tween._dirty = true;
+ tween = tween.timeline;
+ }
+ return this;
+ };
+
+ p._swapSelfInParams = function(params) {
+ var i = params.length,
+ copy = params.concat();
+ while (--i > -1) {
+ if (params[i] === "{self}") {
+ copy[i] = this;
+ }
+ }
+ return copy;
+ };
+
+//----Animation getters/setters --------------------------------------------------------
+
+ p.eventCallback = function(type, callback, params, scope) {
+ if ((type || "").substr(0,2) === "on") {
+ var v = this.vars;
+ if (arguments.length === 1) {
+ return v[type];
+ }
+ if (callback == null) {
+ delete v[type];
+ } else {
+ v[type] = callback;
+ v[type + "Params"] = (_isArray(params) && params.join("").indexOf("{self}") !== -1) ? this._swapSelfInParams(params) : params;
+ v[type + "Scope"] = scope;
+ }
+ if (type === "onUpdate") {
+ this._onUpdate = callback;
+ }
+ }
+ return this;
+ };
+
+ p.delay = function(value) {
+ if (!arguments.length) {
+ return this._delay;
+ }
+ if (this._timeline.smoothChildTiming) {
+ this.startTime( this._startTime + value - this._delay );
+ }
+ this._delay = value;
+ return this;
+ };
+
+ p.duration = function(value) {
+ if (!arguments.length) {
+ this._dirty = false;
+ return this._duration;
+ }
+ this._duration = this._totalDuration = value;
+ this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration.
+ if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) {
+ this.totalTime(this._totalTime * (value / this._duration), true);
+ }
+ return this;
+ };
+
+ p.totalDuration = function(value) {
+ this._dirty = false;
+ return (!arguments.length) ? this._totalDuration : this.duration(value);
+ };
+
+ p.time = function(value, suppressEvents) {
+ if (!arguments.length) {
+ return this._time;
+ }
+ if (this._dirty) {
+ this.totalDuration();
+ }
+ return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents);
+ };
+
+ p.totalTime = function(time, suppressEvents, uncapped) {
+ if (!_tickerActive) {
+ _ticker.wake();
+ }
+ if (!arguments.length) {
+ return this._totalTime;
+ }
+ if (this._timeline) {
+ if (time < 0 && !uncapped) {
+ time += this.totalDuration();
+ }
+ if (this._timeline.smoothChildTiming) {
+ if (this._dirty) {
+ this.totalDuration();
+ }
+ var totalDuration = this._totalDuration,
+ tl = this._timeline;
+ if (time > totalDuration && !uncapped) {
+ time = totalDuration;
+ }
+ this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale);
+ if (!tl._dirty) { //for performance improvement. If the parent's cache is already dirty, it already took care of marking the ancestors as dirty too, so skip the function call here.
+ this._uncache(false);
+ }
+ //in case any of the ancestor timelines had completed but should now be enabled, we should reset their totalTime() which will also ensure that they're lined up properly and enabled. Skip for animations that are on the root (wasteful). Example: a TimelineLite.exportRoot() is performed when there's a paused tween on the root, the export will not complete until that tween is unpaused, but imagine a child gets restarted later, after all [unpaused] tweens have completed. The startTime of that child would get pushed out, but one of the ancestors may have completed.
+ if (tl._timeline) {
+ while (tl._timeline) {
+ if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) {
+ tl.totalTime(tl._totalTime, true);
+ }
+ tl = tl._timeline;
+ }
+ }
+ }
+ if (this._gc) {
+ this._enabled(true, false);
+ }
+ if (this._totalTime !== time || this._duration === 0) {
+ this.render(time, suppressEvents, false);
+ if (_lazyTweens.length) { //in case rendering caused any tweens to lazy-init, we should render them because typically when someone calls seek() or time() or progress(), they expect an immediate render.
+ _lazyRender();
+ }
+ }
+ }
+ return this;
+ };
+
+ p.progress = p.totalProgress = function(value, suppressEvents) {
+ return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, suppressEvents);
+ };
+
+ p.startTime = function(value) {
+ if (!arguments.length) {
+ return this._startTime;
+ }
+ if (value !== this._startTime) {
+ this._startTime = value;
+ if (this.timeline) if (this.timeline._sortChildren) {
+ this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
+ }
+ }
+ return this;
+ };
+
+ p.timeScale = function(value) {
+ if (!arguments.length) {
+ return this._timeScale;
+ }
+ value = value || _tinyNum; //can't allow zero because it'll throw the math off
+ if (this._timeline && this._timeline.smoothChildTiming) {
+ var pauseTime = this._pauseTime,
+ t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
+ this._startTime = t - ((t - this._startTime) * this._timeScale / value);
+ }
+ this._timeScale = value;
+ return this._uncache(false);
+ };
+
+ p.reversed = function(value) {
+ if (!arguments.length) {
+ return this._reversed;
+ }
+ if (value != this._reversed) {
+ this._reversed = value;
+ this.totalTime(((this._timeline && !this._timeline.smoothChildTiming) ? this.totalDuration() - this._totalTime : this._totalTime), true);
+ }
+ return this;
+ };
+
+ p.paused = function(value) {
+ if (!arguments.length) {
+ return this._paused;
+ }
+ if (value != this._paused) if (this._timeline) {
+ if (!_tickerActive && !value) {
+ _ticker.wake();
+ }
+ var tl = this._timeline,
+ raw = tl.rawTime(),
+ elapsed = raw - this._pauseTime;
+ if (!value && tl.smoothChildTiming) {
+ this._startTime += elapsed;
+ this._uncache(false);
+ }
+ this._pauseTime = value ? raw : null;
+ this._paused = value;
+ this._active = this.isActive();
+ if (!value && elapsed !== 0 && this._initted && this.duration()) {
+ this.render((tl.smoothChildTiming ? this._totalTime : (raw - this._startTime) / this._timeScale), true, true); //in case the target's properties changed via some other tween or manual update by the user, we should force a render.
+ }
+ }
+ if (this._gc && !value) {
+ this._enabled(true, false);
+ }
+ return this;
+ };
+
+
+/*
+ * ----------------------------------------------------------------
+ * SimpleTimeline
+ * ----------------------------------------------------------------
+ */
+ var SimpleTimeline = _class("core.SimpleTimeline", function(vars) {
+ Animation.call(this, 0, vars);
+ this.autoRemoveChildren = this.smoothChildTiming = true;
+ });
+
+ p = SimpleTimeline.prototype = new Animation();
+ p.constructor = SimpleTimeline;
+ p.kill()._gc = false;
+ p._first = p._last = null;
+ p._sortChildren = false;
+
+ p.add = p.insert = function(child, position, align, stagger) {
+ var prevTween, st;
+ child._startTime = Number(position || 0) + child._delay;
+ if (child._paused) if (this !== child._timeline) { //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order).
+ child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale);
+ }
+ if (child.timeline) {
+ child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one.
+ }
+ child.timeline = child._timeline = this;
+ if (child._gc) {
+ child._enabled(true, true);
+ }
+ prevTween = this._last;
+ if (this._sortChildren) {
+ st = child._startTime;
+ while (prevTween && prevTween._startTime > st) {
+ prevTween = prevTween._prev;
+ }
+ }
+ if (prevTween) {
+ child._next = prevTween._next;
+ prevTween._next = child;
+ } else {
+ child._next = this._first;
+ this._first = child;
+ }
+ if (child._next) {
+ child._next._prev = child;
+ } else {
+ this._last = child;
+ }
+ child._prev = prevTween;
+ if (this._timeline) {
+ this._uncache(true);
+ }
+ return this;
+ };
+
+ p._remove = function(tween, skipDisable) {
+ if (tween.timeline === this) {
+ if (!skipDisable) {
+ tween._enabled(false, true);
+ }
+ tween.timeline = null;
+
+ if (tween._prev) {
+ tween._prev._next = tween._next;
+ } else if (this._first === tween) {
+ this._first = tween._next;
+ }
+ if (tween._next) {
+ tween._next._prev = tween._prev;
+ } else if (this._last === tween) {
+ this._last = tween._prev;
+ }
+
+ if (this._timeline) {
+ this._uncache(true);
+ }
+ }
+ return this;
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ var tween = this._first,
+ next;
+ this._totalTime = this._time = this._rawPrevTime = time;
+ while (tween) {
+ next = tween._next; //record it here because the value could change after rendering...
+ if (tween._active || (time >= tween._startTime && !tween._paused)) {
+ if (!tween._reversed) {
+ tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
+ } else {
+ tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
+ }
+ }
+ tween = next;
+ }
+ };
+
+ p.rawTime = function() {
+ if (!_tickerActive) {
+ _ticker.wake();
+ }
+ return this._totalTime;
+ };
+
+/*
+ * ----------------------------------------------------------------
+ * TweenLite
+ * ----------------------------------------------------------------
+ */
+ var TweenLite = _class("TweenLite", function(target, duration, vars) {
+ Animation.call(this, duration, vars);
+ this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
+
+ if (target == null) {
+ throw "Cannot tween a null target.";
+ }
+
+ this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
+
+ var isSelector = (target.jquery || (target.length && target !== window && target[0] && (target[0] === window || (target[0].nodeType && target[0].style && !target.nodeType)))),
+ overwrite = this.vars.overwrite,
+ i, targ, targets;
+
+ this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite];
+
+ if ((isSelector || target instanceof Array || (target.push && _isArray(target))) && typeof(target[0]) !== "number") {
+ this._targets = targets = _slice.call(target, 0);
+ this._propLookup = [];
+ this._siblings = [];
+ for (i = 0; i < targets.length; i++) {
+ targ = targets[i];
+ if (!targ) {
+ targets.splice(i--, 1);
+ continue;
+ } else if (typeof(targ) === "string") {
+ targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings
+ if (typeof(targ) === "string") {
+ targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case)
+ }
+ continue;
+ } else if (targ.length && targ !== window && targ[0] && (targ[0] === window || (targ[0].nodeType && targ[0].style && !targ.nodeType))) { //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that <select> elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself.
+ targets.splice(i--, 1);
+ this._targets = targets = targets.concat(_slice.call(targ, 0));
+ continue;
+ }
+ this._siblings[i] = _register(targ, this, false);
+ if (overwrite === 1) if (this._siblings[i].length > 1) {
+ _applyOverwrite(targ, this, null, 1, this._siblings[i]);
+ }
+ }
+
+ } else {
+ this._propLookup = {};
+ this._siblings = _register(target, this, false);
+ if (overwrite === 1) if (this._siblings.length > 1) {
+ _applyOverwrite(target, this, null, 1, this._siblings);
+ }
+ }
+ if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
+ this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render)
+ this.render(-this._delay);
+ }
+ }, true),
+ _isSelector = function(v) {
+ return (v.length && v !== window && v[0] && (v[0] === window || (v[0].nodeType && v[0].style && !v.nodeType))); //we cannot check "nodeType" if the target is window from within an iframe, otherwise it will trigger a security error in some browsers like Firefox.
+ },
+ _autoCSS = function(vars, target) {
+ var css = {},
+ p;
+ for (p in vars) {
+ if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || (_plugins[p] && _plugins[p]._autoCSS))) { //note: <img> elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties.
+ css[p] = vars[p];
+ delete vars[p];
+ }
+ }
+ vars.css = css;
+ };
+
+ p = TweenLite.prototype = new Animation();
+ p.constructor = TweenLite;
+ p.kill()._gc = false;
+
+//----TweenLite defaults, overwrite management, and root updates ----------------------------------------------------
+
+ p.ratio = 0;
+ p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
+ p._notifyPluginsOfEnabled = p._lazy = false;
+
+ TweenLite.version = "1.12.1";
+ TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
+ TweenLite.defaultOverwrite = "auto";
+ TweenLite.ticker = _ticker;
+ TweenLite.autoSleep = true;
+ TweenLite.lagSmoothing = function(threshold, adjustedLag) {
+ _ticker.lagSmoothing(threshold, adjustedLag);
+ };
+ TweenLite.selector = window.$ || window.jQuery || function(e) { if (window.$) { TweenLite.selector = window.$; return window.$(e); } return window.document ? window.document.getElementById((e.charAt(0) === "#") ? e.substr(1) : e) : e; };
+
+ var _lazyTweens = [],
+ _lazyLookup = {},
+ _internals = TweenLite._internals = {isArray:_isArray, isSelector:_isSelector, lazyTweens:_lazyTweens}, //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object.
+ _plugins = TweenLite._plugins = {},
+ _tweenLookup = _internals.tweenLookup = {},
+ _tweenLookupNum = 0,
+ _reservedProps = _internals.reservedProps = {ease:1, delay:1, overwrite:1, onComplete:1, onCompleteParams:1, onCompleteScope:1, useFrames:1, runBackwards:1, startAt:1, onUpdate:1, onUpdateParams:1, onUpdateScope:1, onStart:1, onStartParams:1, onStartScope:1, onReverseComplete:1, onReverseCompleteParams:1, onReverseCompleteScope:1, onRepeat:1, onRepeatParams:1, onRepeatScope:1, easeParams:1, yoyo:1, immediateRender:1, repeat:1, repeatDelay:1, data:1, paused:1, reversed:1, autoCSS:1, lazy:1},
+ _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
+ _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
+ _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
+ _lazyRender = function() {
+ var i = _lazyTweens.length;
+ _lazyLookup = {};
+ while (--i > -1) {
+ a = _lazyTweens[i];
+ if (a && a._lazy !== false) {
+ a.render(a._lazy, false, true);
+ a._lazy = false;
+ }
+ }
+ _lazyTweens.length = 0;
+ };
+
+ _rootTimeline._startTime = _ticker.time;
+ _rootFramesTimeline._startTime = _ticker.frame;
+ _rootTimeline._active = _rootFramesTimeline._active = true;
+ setTimeout(_lazyRender, 1); //on some mobile devices, there isn't a "tick" before code runs which means any lazy renders wouldn't run before the next official "tick".
+
+ Animation._updateRoot = TweenLite.render = function() {
+ var i, a, p;
+ if (_lazyTweens.length) { //if code is run outside of the requestAnimationFrame loop, there may be tweens queued AFTER the engine refreshed, so we need to ensure any pending renders occur before we refresh again.
+ _lazyRender();
+ }
+ _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
+ _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
+ if (_lazyTweens.length) {
+ _lazyRender();
+ }
+ if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
+ for (p in _tweenLookup) {
+ a = _tweenLookup[p].tweens;
+ i = a.length;
+ while (--i > -1) {
+ if (a[i]._gc) {
+ a.splice(i, 1);
+ }
+ }
+ if (a.length === 0) {
+ delete _tweenLookup[p];
+ }
+ }
+ //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly
+ p = _rootTimeline._first;
+ if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) {
+ while (p && p._paused) {
+ p = p._next;
+ }
+ if (!p) {
+ _ticker.sleep();
+ }
+ }
+ }
+ };
+
+ _ticker.addEventListener("tick", Animation._updateRoot);
+
+ var _register = function(target, tween, scrub) {
+ var id = target._gsTweenID, a, i;
+ if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) {
+ _tweenLookup[id] = {target:target, tweens:[]};
+ }
+ if (tween) {
+ a = _tweenLookup[id].tweens;
+ a[(i = a.length)] = tween;
+ if (scrub) {
+ while (--i > -1) {
+ if (a[i] === tween) {
+ a.splice(i, 1);
+ }
+ }
+ }
+ }
+ return _tweenLookup[id].tweens;
+ },
+
+ _applyOverwrite = function(target, tween, props, mode, siblings) {
+ var i, changed, curTween, l;
+ if (mode === 1 || mode >= 4) {
+ l = siblings.length;
+ for (i = 0; i < l; i++) {
+ if ((curTween = siblings[i]) !== tween) {
+ if (!curTween._gc) if (curTween._enabled(false, false)) {
+ changed = true;
+ }
+ } else if (mode === 5) {
+ break;
+ }
+ }
+ return changed;
+ }
+ //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example)
+ var startTime = tween._startTime + _tinyNum,
+ overlaps = [],
+ oCount = 0,
+ zeroDur = (tween._duration === 0),
+ globalStart;
+ i = siblings.length;
+ while (--i > -1) {
+ if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) {
+ //ignore
+ } else if (curTween._timeline !== tween._timeline) {
+ globalStart = globalStart || _checkOverlap(tween, 0, zeroDur);
+ if (_checkOverlap(curTween, globalStart, zeroDur) === 0) {
+ overlaps[oCount++] = curTween;
+ }
+ } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) {
+ overlaps[oCount++] = curTween;
+ }
+ }
+
+ i = oCount;
+ while (--i > -1) {
+ curTween = overlaps[i];
+ if (mode === 2) if (curTween._kill(props, target)) {
+ changed = true;
+ }
+ if (mode !== 2 || (!curTween._firstPT && curTween._initted)) {
+ if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween.
+ changed = true;
+ }
+ }
+ }
+ return changed;
+ },
+
+ _checkOverlap = function(tween, reference, zeroDur) {
+ var tl = tween._timeline,
+ ts = tl._timeScale,
+ t = tween._startTime;
+ while (tl._timeline) {
+ t += tl._startTime;
+ ts *= tl._timeScale;
+ if (tl._paused) {
+ return -100;
+ }
+ tl = tl._timeline;
+ }
+ t /= ts;
+ return (t > reference) ? t - reference : ((zeroDur && t === reference) || (!tween._initted && t - reference < 2 * _tinyNum)) ? _tinyNum : ((t += tween.totalDuration() / tween._timeScale / ts) > reference + _tinyNum) ? 0 : t - reference - _tinyNum;
+ };
+
+
+//---- TweenLite instance methods -----------------------------------------------------------------------------
+
+ p._init = function() {
+ var v = this.vars,
+ op = this._overwrittenProps,
+ dur = this._duration,
+ immediate = !!v.immediateRender,
+ ease = v.ease,
+ i, initPlugins, pt, p, startVars;
+ if (v.startAt) {
+ if (this._startAt) {
+ this._startAt.render(-1, true); //if we've run a startAt previously (when the tween instantiated), we should revert it so that the values re-instantiate correctly particularly for relative tweens. Without this, a TweenLite.fromTo(obj, 1, {x:"+=100"}, {x:"-=100"}), for example, would actually jump to +=200 because the startAt would run twice, doubling the relative change.
+ this._startAt.kill();
+ }
+ startVars = {};
+ for (p in v.startAt) { //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from);
+ startVars[p] = v.startAt[p];
+ }
+ startVars.overwrite = false;
+ startVars.immediateRender = true;
+ startVars.lazy = (immediate && v.lazy !== false);
+ startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
+ this._startAt = TweenLite.to(this.target, 0, startVars);
+ if (immediate) {
+ if (this._time > 0) {
+ this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()).
+ } else if (dur !== 0) {
+ return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting.
+ }
+ }
+ } else if (v.runBackwards && dur !== 0) {
+ //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards)
+ if (this._startAt) {
+ this._startAt.render(-1, true);
+ this._startAt.kill();
+ this._startAt = null;
+ } else {
+ pt = {};
+ for (p in v) { //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through.
+ if (!_reservedProps[p] || p === "autoCSS") {
+ pt[p] = v[p];
+ }
+ }
+ pt.overwrite = 0;
+ pt.data = "isFromStart"; //we tag the tween with as "isFromStart" so that if [inside a plugin] we need to only do something at the very END of a tween, we have a way of identifying this tween as merely the one that's setting the beginning values for a "from()" tween. For example, clearProps in CSSPlugin should only get applied at the very END of a tween and without this tag, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in.
+ pt.lazy = (immediate && v.lazy !== false);
+ pt.immediateRender = immediate; //zero-duration tweens render immediately by default, but if we're not specifically instructed to render this tween immediately, we should skip this and merely _init() to record the starting values (rendering them immediately would push them to completion which is wasteful in that case - we'd have to render(-1) immediately after)
+ this._startAt = TweenLite.to(this.target, 0, pt);
+ if (!immediate) {
+ this._startAt._init(); //ensures that the initial values are recorded
+ this._startAt._enabled(false); //no need to have the tween render on the next cycle. Disable it because we'll always manually control the renders of the _startAt tween.
+ } else if (this._time === 0) {
+ return;
+ }
+ }
+ }
+ if (!ease) {
+ this._ease = TweenLite.defaultEase;
+ } else if (ease instanceof Ease) {
+ this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease;
+ } else {
+ this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase;
+ }
+ this._easeType = this._ease._type;
+ this._easePower = this._ease._power;
+ this._firstPT = null;
+
+ if (this._targets) {
+ i = this._targets.length;
+ while (--i > -1) {
+ if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) {
+ initPlugins = true;
+ }
+ }
+ } else {
+ initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op);
+ }
+
+ if (initPlugins) {
+ TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite
+ }
+ if (op) if (!this._firstPT) if (typeof(this.target) !== "function") { //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live.
+ this._enabled(false, false);
+ }
+ if (v.runBackwards) {
+ pt = this._firstPT;
+ while (pt) {
+ pt.s += pt.c;
+ pt.c = -pt.c;
+ pt = pt._next;
+ }
+ }
+ this._onUpdate = v.onUpdate;
+ this._initted = true;
+ };
+
+ p._initProps = function(target, propLookup, siblings, overwrittenProps) {
+ var p, i, initPlugins, plugin, pt, v;
+ if (target == null) {
+ return false;
+ }
+
+ if (_lazyLookup[target._gsTweenID]) {
+ _lazyRender(); //if other tweens of the same target have recently initted but haven't rendered yet, we've got to force the render so that the starting values are correct (imagine populating a timeline with a bunch of sequential tweens and then jumping to the end)
+ }
+
+ if (!this.vars.css) if (target.style) if (target !== window && target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity). Note: we cannot check "nodeType" on the window inside an iframe.
+ _autoCSS(this.vars, target);
+ }
+ for (p in this.vars) {
+ v = this.vars[p];
+ if (_reservedProps[p]) {
+ if (v) if ((v instanceof Array) || (v.push && _isArray(v))) if (v.join("").indexOf("{self}") !== -1) {
+ this.vars[p] = v = this._swapSelfInParams(v, this);
+ }
+
+ } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) {
+
+ //t - target [object]
+ //p - property [string]
+ //s - start [number]
+ //c - change [number]
+ //f - isFunction [boolean]
+ //n - name [string]
+ //pg - isPlugin [boolean]
+ //pr - priority [number]
+ this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority};
+ i = plugin._overwriteProps.length;
+ while (--i > -1) {
+ propLookup[plugin._overwriteProps[i]] = this._firstPT;
+ }
+ if (plugin._priority || plugin._onInitAllProps) {
+ initPlugins = true;
+ }
+ if (plugin._onDisable || plugin._onEnable) {
+ this._notifyPluginsOfEnabled = true;
+ }
+
+ } else {
+ this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0};
+ pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
+ pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0;
+ }
+ if (pt) if (pt._next) {
+ pt._next._prev = pt;
+ }
+ }
+
+ if (overwrittenProps) if (this._kill(overwrittenProps, target)) { //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first)
+ return this._initProps(target, propLookup, siblings, overwrittenProps);
+ }
+ if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) {
+ this._kill(propLookup, target);
+ return this._initProps(target, propLookup, siblings, overwrittenProps);
+ }
+ if (this._firstPT) if ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration)) { //zero duration tweens don't lazy render by default; everything else does.
+ _lazyLookup[target._gsTweenID] = true;
+ }
+ return initPlugins;
+ };
+
+ p.render = function(time, suppressEvents, force) {
+ var prevTime = this._time,
+ duration = this._duration,
+ prevRawPrevTime = this._rawPrevTime,
+ isComplete, callback, pt, rawPrevTime;
+ if (time >= duration) {
+ this._totalTime = this._time = duration;
+ this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
+ if (!this._reversed ) {
+ isComplete = true;
+ callback = "onComplete";
+ }
+ if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
+ time = 0;
+ }
+ if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
+ force = true;
+ if (prevRawPrevTime > _tinyNum) {
+ callback = "onReverseComplete";
+ }
+ }
+ this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ }
+
+ } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
+ this._totalTime = this._time = 0;
+ this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
+ if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
+ callback = "onReverseComplete";
+ isComplete = this._reversed;
+ }
+ if (time < 0) {
+ this._active = false;
+ if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
+ if (prevRawPrevTime >= 0) {
+ force = true;
+ }
+ this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
+ }
+ } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
+ force = true;
+ }
+ } else {
+ this._totalTime = this._time = time;
+
+ if (this._easeType) {
+ var r = time / duration, type = this._easeType, pow = this._easePower;
+ if (type === 1 || (type === 3 && r >= 0.5)) {
+ r = 1 - r;
+ }
+ if (type === 3) {
+ r *= 2;
+ }
+ if (pow === 1) {
+ r *= r;
+ } else if (pow === 2) {
+ r *= r * r;
+ } else if (pow === 3) {
+ r *= r * r * r;
+ } else if (pow === 4) {
+ r *= r * r * r * r;
+ }
+
+ if (type === 1) {
+ this.ratio = 1 - r;
+ } else if (type === 2) {
+ this.ratio = r;
+ } else if (time / duration < 0.5) {
+ this.ratio = r / 2;
+ } else {
+ this.ratio = 1 - (r / 2);
+ }
+
+ } else {
+ this.ratio = this._ease.getRatio(time / duration);
+ }
+ }
+
+ if (this._time === prevTime && !force) {
+ return;
+ } else if (!this._initted) {
+ this._init();
+ if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
+ return;
+ } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
+ this._time = this._totalTime = prevTime;
+ this._rawPrevTime = prevRawPrevTime;
+ _lazyTweens.push(this);
+ this._lazy = time;
+ return;
+ }
+ //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
+ if (this._time && !isComplete) {
+ this.ratio = this._ease.getRatio(this._time / duration);
+ } else if (isComplete && this._ease._calcEnd) {
+ this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
+ }
+ }
+ if (this._lazy !== false) { //in case a lazy render is pending, we should flush it because the new render is occuring now (imagine a lazy tween instantiating and then immediately the user calls tween.seek(tween.duration()), skipping to the end - the end render would be forced, and then if we didn't flush the lazy render, it'd fire AFTER the seek(), rendering it at the wrong time.
+ this._lazy = false;
+ }
+ if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
+ this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
+ }
+ if (prevTime === 0) {
+ if (this._startAt) {
+ if (time >= 0) {
+ this._startAt.render(time, suppressEvents, force);
+ } else if (!callback) {
+ callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
+ }
+ }
+ if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
+ this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
+ }
+ }
+
+ pt = this._firstPT;
+ while (pt) {
+ if (pt.f) {
+ pt.t[pt.p](pt.c * this.ratio + pt.s);
+ } else {
+ pt.t[pt.p] = pt.c * this.ratio + pt.s;
+ }
+ pt = pt._next;
+ }
+
+ if (this._onUpdate) {
+ if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
+ this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
+ }
+ if (!suppressEvents) if (this._time !== prevTime || isComplete) {
+ this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
+ }
+ }
+
+ if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate
+ if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
+ this._startAt.render(time, suppressEvents, force);
+ }
+ if (isComplete) {
+ if (this._timeline.autoRemoveChildren) {
+ this._enabled(false, false);
+ }
+ this._active = false;
+ }
+ if (!suppressEvents && this.vars[callback]) {
+ this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
+ }
+ if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
+ this._rawPrevTime = 0;
+ }
+ }
+
+ };
+
+ p._kill = function(vars, target) {
+ if (vars === "all") {
+ vars = null;
+ }
+ if (vars == null) if (target == null || target === this.target) {
+ this._lazy = false;
+ return this._enabled(false, false);
+ }
+ target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
+ var i, overwrittenProps, p, pt, propLookup, changed, killProps, record;
+ if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
+ i = target.length;
+ while (--i > -1) {
+ if (this._kill(vars, target[i])) {
+ changed = true;
+ }
+ }
+ } else {
+ if (this._targets) {
+ i = this._targets.length;
+ while (--i > -1) {
+ if (target === this._targets[i]) {
+ propLookup = this._propLookup[i] || {};
+ this._overwrittenProps = this._overwrittenProps || [];
+ overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all";
+ break;
+ }
+ }
+ } else if (target !== this.target) {
+ return false;
+ } else {
+ propLookup = this._propLookup;
+ overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all";
+ }
+
+ if (propLookup) {
+ killProps = vars || propLookup;
+ record = (vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (typeof(vars) !== "object" || !vars._tempKill)); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin)
+ for (p in killProps) {
+ if ((pt = propLookup[p])) {
+ if (pt.pg && pt.t._kill(killProps)) {
+ changed = true; //some plugins need to be notified so they can perform cleanup tasks first
+ }
+ if (!pt.pg || pt.t._overwriteProps.length === 0) {
+ if (pt._prev) {
+ pt._prev._next = pt._next;
+ } else if (pt === this._firstPT) {
+ this._firstPT = pt._next;
+ }
+ if (pt._next) {
+ pt._next._prev = pt._prev;
+ }
+ pt._next = pt._prev = null;
+ }
+ delete propLookup[p];
+ }
+ if (record) {
+ overwrittenProps[p] = 1;
+ }
+ }
+ if (!this._firstPT && this._initted) { //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening.
+ this._enabled(false, false);
+ }
+ }
+ }
+ return changed;
+ };
+
+ p.invalidate = function() {
+ if (this._notifyPluginsOfEnabled) {
+ TweenLite._onPluginEvent("_onDisable", this);
+ }
+ this._firstPT = null;
+ this._overwrittenProps = null;
+ this._onUpdate = null;
+ this._startAt = null;
+ this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
+ this._propLookup = (this._targets) ? {} : [];
+ return this;
+ };
+
+ p._enabled = function(enabled, ignoreTimeline) {
+ if (!_tickerActive) {
+ _ticker.wake();
+ }
+ if (enabled && this._gc) {
+ var targets = this._targets,
+ i;
+ if (targets) {
+ i = targets.length;
+ while (--i > -1) {
+ this._siblings[i] = _register(targets[i], this, true);
+ }
+ } else {
+ this._siblings = _register(this.target, this, true);
+ }
+ }
+ Animation.prototype._enabled.call(this, enabled, ignoreTimeline);
+ if (this._notifyPluginsOfEnabled) if (this._firstPT) {
+ return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this);
+ }
+ return false;
+ };
+
+
+//----TweenLite static methods -----------------------------------------------------
+
+ TweenLite.to = function(target, duration, vars) {
+ return new TweenLite(target, duration, vars);
+ };
+
+ TweenLite.from = function(target, duration, vars) {
+ vars.runBackwards = true;
+ vars.immediateRender = (vars.immediateRender != false);
+ return new TweenLite(target, duration, vars);
+ };
+
+ TweenLite.fromTo = function(target, duration, fromVars, toVars) {
+ toVars.startAt = fromVars;
+ toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
+ return new TweenLite(target, duration, toVars);
+ };
+
+ TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) {
+ return new TweenLite(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
+ };
+
+ TweenLite.set = function(target, vars) {
+ return new TweenLite(target, 0, vars);
+ };
+
+ TweenLite.getTweensOf = function(target, onlyActive) {
+ if (target == null) { return []; }
+ target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
+ var i, a, j, t;
+ if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
+ i = target.length;
+ a = [];
+ while (--i > -1) {
+ a = a.concat(TweenLite.getTweensOf(target[i], onlyActive));
+ }
+ i = a.length;
+ //now get rid of any duplicates (tweens of arrays of objects could cause duplicates)
+ while (--i > -1) {
+ t = a[i];
+ j = i;
+ while (--j > -1) {
+ if (t === a[j]) {
+ a.splice(i, 1);
+ }
+ }
+ }
+ } else {
+ a = _register(target).concat();
+ i = a.length;
+ while (--i > -1) {
+ if (a[i]._gc || (onlyActive && !a[i].isActive())) {
+ a.splice(i, 1);
+ }
+ }
+ }
+ return a;
+ };
+
+ TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, onlyActive, vars) {
+ if (typeof(onlyActive) === "object") {
+ vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted)
+ onlyActive = false;
+ }
+ var a = TweenLite.getTweensOf(target, onlyActive),
+ i = a.length;
+ while (--i > -1) {
+ a[i]._kill(vars, target);
+ }
+ };
+
+
+
+/*
+ * ----------------------------------------------------------------
+ * TweenPlugin (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another <script> call before loading plugins which is easy to forget)
+ * ----------------------------------------------------------------
+ */
+ var TweenPlugin = _class("plugins.TweenPlugin", function(props, priority) {
+ this._overwriteProps = (props || "").split(",");
+ this._propName = this._overwriteProps[0];
+ this._priority = priority || 0;
+ this._super = TweenPlugin.prototype;
+ }, true);
+
+ p = TweenPlugin.prototype;
+ TweenPlugin.version = "1.10.1";
+ TweenPlugin.API = 2;
+ p._firstPT = null;
+
+ p._addTween = function(target, prop, start, end, overwriteProp, round) {
+ var c, pt;
+ if (end != null && (c = (typeof(end) === "number" || end.charAt(1) !== "=") ? Number(end) - start : parseInt(end.charAt(0) + "1", 10) * Number(end.substr(2)))) {
+ this._firstPT = pt = {_next:this._firstPT, t:target, p:prop, s:start, c:c, f:(typeof(target[prop]) === "function"), n:overwriteProp || prop, r:round};
+ if (pt._next) {
+ pt._next._prev = pt;
+ }
+ return pt;
+ }
+ };
+
+ p.setRatio = function(v) {
+ var pt = this._firstPT,
+ min = 0.000001,
+ val;
+ while (pt) {
+ val = pt.c * v + pt.s;
+ if (pt.r) {
+ val = Math.round(val);
+ } else if (val < min) if (val > -min) { //prevents issues with converting very small numbers to strings in the browser
+ val = 0;
+ }
+ if (pt.f) {
+ pt.t[pt.p](val);
+ } else {
+ pt.t[pt.p] = val;
+ }
+ pt = pt._next;
+ }
+ };
+
+ p._kill = function(lookup) {
+ var a = this._overwriteProps,
+ pt = this._firstPT,
+ i;
+ if (lookup[this._propName] != null) {
+ this._overwriteProps = [];
+ } else {
+ i = a.length;
+ while (--i > -1) {
+ if (lookup[a[i]] != null) {
+ a.splice(i, 1);
+ }
+ }
+ }
+ while (pt) {
+ if (lookup[pt.n] != null) {
+ if (pt._next) {
+ pt._next._prev = pt._prev;
+ }
+ if (pt._prev) {
+ pt._prev._next = pt._next;
+ pt._prev = null;
+ } else if (this._firstPT === pt) {
+ this._firstPT = pt._next;
+ }
+ }
+ pt = pt._next;
+ }
+ return false;
+ };
+
+ p._roundProps = function(lookup, value) {
+ var pt = this._firstPT;
+ while (pt) {
+ if (lookup[this._propName] || (pt.n != null && lookup[ pt.n.split(this._propName + "_").join("") ])) { //some properties that are very plugin-specific add a prefix named after the _propName plus an underscore, so we need to ignore that extra stuff here.
+ pt.r = value;
+ }
+ pt = pt._next;
+ }
+ };
+
+ TweenLite._onPluginEvent = function(type, tween) {
+ var pt = tween._firstPT,
+ changed, pt2, first, last, next;
+ if (type === "_onInitAllProps") {
+ //sorts the PropTween linked list in order of priority because some plugins need to render earlier/later than others, like MotionBlurPlugin applies its effects after all x/y/alpha tweens have rendered on each frame.
+ while (pt) {
+ next = pt._next;
+ pt2 = first;
+ while (pt2 && pt2.pr > pt.pr) {
+ pt2 = pt2._next;
+ }
+ if ((pt._prev = pt2 ? pt2._prev : last)) {
+ pt._prev._next = pt;
+ } else {
+ first = pt;
+ }
+ if ((pt._next = pt2)) {
+ pt2._prev = pt;
+ } else {
+ last = pt;
+ }
+ pt = next;
+ }
+ pt = tween._firstPT = first;
+ }
+ while (pt) {
+ if (pt.pg) if (typeof(pt.t[type]) === "function") if (pt.t[type]()) {
+ changed = true;
+ }
+ pt = pt._next;
+ }
+ return changed;
+ };
+
+ TweenPlugin.activate = function(plugins) {
+ var i = plugins.length;
+ while (--i > -1) {
+ if (plugins[i].API === TweenPlugin.API) {
+ _plugins[(new plugins[i]())._propName] = plugins[i];
+ }
+ }
+ return true;
+ };
+
+ //provides a more concise way to define plugins that have no dependencies besides TweenPlugin and TweenLite, wrapping common boilerplate stuff into one function (added in 1.9.0). You don't NEED to use this to define a plugin - the old way still works and can be useful in certain (rare) situations.
+ _gsDefine.plugin = function(config) {
+ if (!config || !config.propName || !config.init || !config.API) { throw "illegal plugin definition."; }
+ var propName = config.propName,
+ priority = config.priority || 0,
+ overwriteProps = config.overwriteProps,
+ map = {init:"_onInitTween", set:"setRatio", kill:"_kill", round:"_roundProps", initAll:"_onInitAllProps"},
+ Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin",
+ function() {
+ TweenPlugin.call(this, propName, priority);
+ this._overwriteProps = overwriteProps || [];
+ }, (config.global === true)),
+ p = Plugin.prototype = new TweenPlugin(propName),
+ prop;
+ p.constructor = Plugin;
+ Plugin.API = config.API;
+ for (prop in map) {
+ if (typeof(config[prop]) === "function") {
+ p[map[prop]] = config[prop];
+ }
+ }
+ Plugin.version = config.version;
+ TweenPlugin.activate([Plugin]);
+ return Plugin;
+ };
+
+
+ //now run through all the dependencies discovered and if any are missing, log that to the console as a warning. This is why it's best to have TweenLite load last - it can check all the dependencies for you.
+ a = window._gsQueue;
+ if (a) {
+ for (i = 0; i < a.length; i++) {
+ a[i]();
+ }
+ for (p in _defLookup) {
+ if (!_defLookup[p].func) {
+ //window.console.log("GSAP encountered missing dependency: com.greensock." + p);
+ }
+ }
+ }
+
+ _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated
+
+})(window);
+
+angular.module('b2b.att.collapse', ['b2b.att.transition'])
+
+// The collapsible directive indicates a block of html that will expand and collapse
+.directive('b2bCollapse', ['$transition', function($transition) {
+ // CSS transitions don't work with height: auto, so we have to manually change the height to a
+ // specific value and then once the animation completes, we can reset the height to auto.
+ // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
+ // "collapse") then you trigger a change to height 0 in between.
+ // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
+
+ var props = {
+ open: {
+ marginTop: null,
+ marginBottom: null,
+ paddingTop: null,
+ paddingBottom: null,
+ display: 'block'
+ },
+ closed: {
+ marginTop: 0,
+ marginBottom: 0,
+ paddingTop: 0,
+ paddingBottom: 0,
+ display: 'none'
+ }
+ };
+
+ var fixUpHeight = function(scope, element, height) {
+ // We remove the collapse CSS class to prevent a transition when we change to height: auto
+ element.removeClass('b2bCollapse');
+ element.css({height: height});
+ //adjusting for any margin or padding
+ if (height === 0) {
+ element.css(props.closed);
+ } else {
+ element.css(props.open);
+ }
+ // It appears that reading offsetWidth makes the browser realise that we have changed the
+ // height already :-/
+ var x = element[0].offsetWidth;
+ element.addClass('b2bCollapse');
+ };
+
+ return {
+ link: function(scope, element, attrs) {
+ var isCollapsed;
+ var initialAnimSkip = true;
+ scope.$watch(function() {
+ return element[0].scrollHeight;
+ }, function(value) {
+ //The listener is called when scrollHeight changes
+ //It actually does on 2 scenarios:
+ // 1. Parent is set to display none
+ // 2. angular bindings inside are resolved
+ //When we have a change of scrollHeight we are setting again the correct height if the group is opened
+ if (element[0].scrollHeight !== 0) {
+ if (!isCollapsed) {
+ if (initialAnimSkip) {
+ fixUpHeight(scope, element, element[0].scrollHeight + 'px');
+ } else {
+ fixUpHeight(scope, element, 'auto');
+ element.css({overflow: 'visible'});
+ }
+ }
+ }
+ });
+
+ scope.$watch(attrs.b2bCollapse, function(value) {
+ if (value) {
+ collapse();
+ } else {
+ expand();
+ }
+ });
+
+
+ var currentTransition;
+ var doTransition = function(change) {
+ if (currentTransition) {
+ currentTransition.cancel();
+ }
+ currentTransition = $transition(element, change);
+ currentTransition.then(
+ function() {
+ currentTransition = undefined;
+ },
+ function() {
+ currentTransition = undefined;
+ }
+ );
+ return currentTransition;
+ };
+
+ var expand = function() {
+ scope.postTransition = true;
+ if (initialAnimSkip) {
+ initialAnimSkip = false;
+ if (!isCollapsed) {
+ fixUpHeight(scope, element, 'auto');
+ }
+ } else {
+ //doTransition({ height : element[0].scrollHeight + 'px' })
+ doTransition(angular.extend({height: element[0].scrollHeight + 'px'}, props.open))
+ .then(function() {
+ // This check ensures that we don't accidentally update the height if the user has closed
+ // the group while the animation was still running
+ if (!isCollapsed) {
+ fixUpHeight(scope, element, 'auto');
+ }
+ });
+ }
+ isCollapsed = false;
+ };
+
+ var collapse = function() {
+ isCollapsed = true;
+ if (initialAnimSkip) {
+ initialAnimSkip = false;
+ fixUpHeight(scope, element, 0);
+ } else {
+ fixUpHeight(scope, element, element[0].scrollHeight + 'px');
+ doTransition(angular.extend({height: 0}, props.closed)).then(function() {
+ scope.postTransition = false;
+ });
+ element.css({overflow: 'hidden'});
+ }
+ };
+ }
+ };
+}]);
+angular.module('b2b.att.position', [])
+
+.factory('$position', ['$document', '$window', function ($document, $window) {
+ function getStyle(el, cssprop) {
+ if (el.currentStyle) { //IE
+ return el.currentStyle[cssprop];
+ } else if ($window.getComputedStyle) {
+ return $window.getComputedStyle(el)[cssprop];
+ }
+ // finally try and get inline style
+ return el.style[cssprop];
+ }
+
+ /**
+ * Checks if a given element is statically positioned
+ * @param element - raw DOM element
+ */
+ function isStaticPositioned(element) {
+ return (getStyle(element, "position") || 'static') === 'static';
+ }
+
+ /**
+ * returns the closest, non-statically positioned parentOffset of a given element
+ * @param element
+ */
+ var parentOffsetEl = function (element) {
+ var docDomEl = $document[0];
+ var offsetParent = element.offsetParent || docDomEl;
+ while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docDomEl;
+ };
+
+ return {
+ /**
+ * Provides read-only equivalent of jQuery's position function:
+ * http://api.jquery.com/position/
+ */
+ position: function (element) {
+ var elBCR = this.offset(element);
+ var offsetParentBCR = {
+ top: 0,
+ left: 0
+ };
+ var offsetParentEl = parentOffsetEl(element[0]);
+ if (offsetParentEl !== $document[0]) {
+ offsetParentBCR = this.offset(angular.element(offsetParentEl));
+ offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
+ offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
+ }
+
+ return {
+ width: element.prop('offsetWidth'),
+ height: element.prop('offsetHeight'),
+ top: elBCR.top - offsetParentBCR.top,
+ left: elBCR.left - offsetParentBCR.left
+ };
+ },
+
+ /**
+ * Provides read-only equivalent of jQuery's offset function:
+ * http://api.jquery.com/offset/
+ */
+ offset: function (element) {
+ var boundingClientRect = element[0].getBoundingClientRect();
+ return {
+ width: element.prop('offsetWidth'),
+ height: element.prop('offsetHeight'),
+ top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
+ left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
+ };
+ },
+
+ /**
+ * Provides functionality to check whether an element is in view port.
+ */
+ isElementInViewport: function (element) {
+ if (element) {
+ var rect = element[0].getBoundingClientRect();
+ return (
+ rect.top >= 0 &&
+ rect.left >= 0 &&
+ rect.bottom <= ($window.innerHeight || $document[0].documentElement.clientHeight) &&
+ rect.right <= ($window.innerWidth || $document[0].documentElement.clientWidth)
+ );
+ } else {
+ return false;
+ }
+ }
+ };
+}])
+
+.factory('$isElement', [function () {
+ var isElement = function (currentElem, targetElem, alternateElem) {
+ if (currentElem[0] === targetElem[0]) {
+ return true;
+ } else if (currentElem[0] === alternateElem[0]) {
+ return false;
+ } else {
+ return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
+ }
+ };
+
+ return isElement;
+}])
+
+.directive('attPosition', ['$position', function ($position) {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr) {
+ scope.$watchCollection(function () {
+ return $position.position(elem);
+ }, function (value) {
+ scope[attr.attPosition] = value;
+ });
+ }
+ };
+}]);
+
+angular.module('b2b.att.transition', [])
+
+.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
+
+ var $transition = function(element, trigger, options) {
+ options = options || {};
+ var deferred = $q.defer();
+ var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
+
+ var transitionEndHandler = function() {
+ $rootScope.$apply(function() {
+ element.unbind(endEventName, transitionEndHandler);
+ deferred.resolve(element);
+ });
+ };
+
+ if (endEventName) {
+ element.bind(endEventName, transitionEndHandler);
+ }
+
+ // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
+ $timeout(function() {
+ if ( angular.isString(trigger) ) {
+ element.addClass(trigger);
+ } else if ( angular.isFunction(trigger) ) {
+ trigger(element);
+ } else if ( angular.isObject(trigger) ) {
+ element.css(trigger);
+ }
+ //If browser does not support transitions, instantly resolve
+ if ( !endEventName ) {
+ deferred.resolve(element);
+ }
+ }, 100);
+
+ // Add our custom cancel function to the promise that is returned
+ // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
+ // i.e. it will therefore never raise a transitionEnd event for that transition
+ deferred.promise.cancel = function() {
+ if ( endEventName ) {
+ element.unbind(endEventName, transitionEndHandler);
+ }
+ deferred.reject('Transition cancelled');
+ };
+
+ return deferred.promise;
+ };
+
+ // Work out the name of the transitionEnd event
+ var transElement = document.createElement('trans');
+ var transitionEndEventNames = {
+ 'WebkitTransition': 'webkitTransitionEnd',
+ 'MozTransition': 'transitionend',
+ 'OTransition': 'oTransitionEnd',
+ 'transition': 'transitionend'
+ };
+ var animationEndEventNames = {
+ 'WebkitTransition': 'webkitAnimationEnd',
+ 'MozTransition': 'animationend',
+ 'OTransition': 'oAnimationEnd',
+ 'transition': 'animationend'
+ };
+ function findEndEventName(endEventNames) {
+ for (var name in endEventNames){
+ if (transElement.style[name] !== undefined) {
+ return endEventNames[name];
+ }
+ }
+ }
+ $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
+ $transition.animationEndEventName = findEndEventName(animationEndEventNames);
+ return $transition;
+}])
+
+.factory('$scrollTo', ['$window', function($window) {
+ var $scrollTo = function(offsetLeft, offsetTop, duration) {
+ TweenMax.to($window, duration || 1, {scrollTo: {y: offsetTop, x: offsetLeft}, ease: Power4.easeOut});
+ };
+ return $scrollTo;
+}])
+.factory('animation', function(){
+ return TweenMax;
+})
+.factory('$progressBar', function(){
+
+ //Provides a function to pass in code for closure purposes
+ var loadingAnimationCreator = function(onUpdateCallback){
+
+ //Use closure to setup some resuable code
+ var loadingAnimation = function(callback, duration){
+ TweenMax.to({}, duration, {
+ onUpdateParams: ["{self}"],
+ onUpdate: onUpdateCallback,
+ onComplete: callback
+ });
+ };
+ //Returns a function that takes a callback function and a duration for the animation
+ return (function(){
+ return loadingAnimation;
+ })();
+ };
+
+ return loadingAnimationCreator;
+})
+.factory('$height', function(){
+ var heightAnimation = function(element,duration,height,alpha){
+ TweenMax.to(element,
+ duration,
+ {height:height, autoAlpha:alpha},
+ 0);
+ };
+ return heightAnimation;
+});
+angular.module('b2b.att.utilities', ['ngSanitize'])
+.constant('b2bUtilitiesConfig', {
+ prev: '37',
+ up: '38',
+ next: '39',
+ down: '40',
+ type: 'list',
+ columns: 1,
+ enableSearch: false,
+ searchTimer: 200,
+ circularTraversal: false
+})
+.constant('b2bWhenScrollEndsConstants', {
+ 'threshold': 100,
+ 'width': 0,
+ 'height': 0
+})
+// All breakpoints ranges from >= min and < max
+.constant('b2bAwdBreakpoints', {
+ breakpoints: {
+ mobile: {
+ min: 1,
+ max: 768
+ },
+ tablet: {
+ min: 768,
+ max: 1025
+ },
+ desktop: {
+ min: 1025,
+ max: 1920
+ }
+ }
+})
+.filter('groupBy', function ($timeout) {
+ //Custom GroupBy Filter for treeNav, returns key string and value.childarray as set of grouped elements
+ return function (data, key) {
+ if (!key) return data;
+ var outputPropertyName = '__groupBy__' + key;
+ if (!data[outputPropertyName]) {
+ var result = {};
+ for (var i = 0; i < data.length; i++) {
+ if (!result[data[i][key]])
+ result[data[i][key]] = {};
+ if (!result[data[i][key]].childArray) {
+ result[data[i][key]].childArray = [];
+ }
+ result[data[i][key]].childArray.push(data[i]);
+ if (data[i].activeGrp && data[i].activeGrp == true) {
+ console.log('make ' + data[i].grpChild + ' active');
+ result[data[i][key]].showGroup = true;
+ }
+ }
+ Object.defineProperty(result, 'length', {enumerable: false,value: Object.keys(result).length});
+ Object.defineProperty(data, outputPropertyName, {enumerable: false,configurable: true,writable:false,value:result});
+ $timeout(function(){delete data[outputPropertyName];},0,false);
+ }
+ return data[outputPropertyName];
+ };
+})
+.filter('searchObjectPropertiesFilter', [function() {
+ return function(items, searchText, attrs) {
+ if(!searchText){
+ return items;
+ }
+ var filtered = [];
+ searchText = searchText.toLowerCase();
+ angular.forEach(items, function(item) {
+ angular.forEach(attrs, function(attr) {
+ if (item.hasOwnProperty(attr) && item[attr].toLowerCase().includes(searchText)) {
+ filtered.push(item);
+ return;
+ }
+ });
+ });
+ return filtered;
+ };
+}])
+.filter('unsafe',[ '$sce', function ($sce) {
+ return function(val){
+ return $sce.trustAsHtml(val);
+ };
+}])
+.filter('b2bHighlight', function () {
+ function escapeRegexp(queryToEscape) {
+ return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
+ }
+ return function (matchItem, query, className) {
+ return query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<span class=\"' + className + '\">$&</span>') : matchItem;
+ }
+})
+/*License (MIT)
+Copyright © 2013 Matt Diamond
+https://github.com/cwilso/AudioRecorder/blob/master/js/recorderjs/recorder.js
+*/
+.factory('b2bRecorder', function() {
+
+ var Recorder = function(source, cfg) {
+ var WORKER_PATH = 'recorderWorker.js';
+ var config = cfg || {};
+ var bufferLen = config.bufferLen || 4096;
+ this.context = source.context;
+ if(!this.context.createScriptProcessor) {
+ this.node = this.context.createJavacriptProcessor(bufferLen, 2, 2);
+ } else {
+ this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
+ }
+ var workerCode = 'function init(a){sampleRate=a.sampleRate}function record(a){recBuffersL.push(a[0]),recBuffersR.push(a[1]),recLength+=a[0].length}function exportWAV(a){var b=mergeBuffers(recBuffersL,recLength),c=mergeBuffers(recBuffersR,recLength),d=interleave(b,c),e=encodeWAV(d),f=new Blob([e],{type:a});this.postMessage(f)}function exportMonoWAV(a){var b=mergeBuffers(recBuffersL,recLength),c=encodeWAV(b,!0),d=new Blob([c],{type:a});this.postMessage(d)}function getBuffers(){var a=[];a.push(mergeBuffers(recBuffersL,recLength)),a.push(mergeBuffers(recBuffersR,recLength)),this.postMessage(a)}function clear(){recLength=0,recBuffersL=[],recBuffersR=[]}function mergeBuffers(a,b){for(var c=new Float32Array(b),d=0,e=0;e<a.length;e++)c.set(a[e],d),d+=a[e].length;return c}function interleave(a,b){for(var c=a.length+b.length,d=new Float32Array(c),e=0,f=0;e<c;)d[e++]=a[f],d[e++]=b[f],f++;return d}function floatTo16BitPCM(a,b,c){for(var d=0;d<c.length;d++,b+=2){var e=Math.max(-1,Math.min(1,c[d]));a.setInt16(b,e<0?32768*e:32767*e,!0)}}function writeString(a,b,c){for(var d=0;d<c.length;d++)a.setUint8(b+d,c.charCodeAt(d))}function encodeWAV(a,b){var c=new ArrayBuffer(44+2*a.length),d=new DataView(c);return writeString(d,0,"RIFF"),d.setUint32(4,32+2*a.length,!0),writeString(d,8,"WAVE"),writeString(d,12,"fmt "),d.setUint32(16,16,!0),d.setUint16(20,1,!0),d.setUint16(22,b?1:2,!0),d.setUint32(24,sampleRate,!0),d.setUint32(28,4*sampleRate,!0),d.setUint16(32,4,!0),d.setUint16(34,16,!0),writeString(d,36,"data"),d.setUint32(40,2*a.length,!0),floatTo16BitPCM(d,44,a),d}var recLength=0,recBuffersL=[],recBuffersR=[],sampleRate;this.onmessage=function(a){switch(a.data.command){case"init":init(a.data.config);break;case"record":record(a.data.buffer);break;case"exportWAV":exportWAV(a.data.type);break;case"exportMonoWAV":exportMonoWAV(a.data.type);break;case"getBuffers":getBuffers();break;case"clear":clear()}};';
+ var blob = new Blob([workerCode]);
+
+ var worker = new Worker(window.URL.createObjectURL(blob)); //TODO: Use a blob instead
+ worker.postMessage({
+ command: 'init',
+ config: {
+ sampleRate: this.context.sampleRate
+ }
+ });
+ var recording = false,
+ currCallback;
+
+ this.node.onaudioprocess = function(e) {
+ if (!recording) return;
+ worker.postMessage({
+ command: 'record',
+ buffer: [
+ e.inputBuffer.getChannelData(0),
+ e.inputBuffer.getChannelData(1)
+ ]
+ });
+ };
+
+ this.configure = function(cfg) {
+ for (var prop in cfg) {//TODO: look into using angular.extend() here
+ if (cfg.hasOwnProperty(prop)) {
+ config[prop] = cfg[prop];
+ }
+ }
+ };
+
+ this.record = function() {
+ recording = true;
+ };
+
+ this.stop = function() {
+ recording = false;
+ };
+
+ this.clear = function() {
+ worker.postMessage({ command: 'clear' });
+ window.URL.revokeObjectURL(blob);
+ };
+
+ this.getBuffers = function(cb) {
+ currCallback = cb || config.callback;
+ worker.postMessage({ command: 'getBuffers' });
+ };
+
+ this.exportWAV = function(cb, type) {
+ currCallback = cb || config.callback;
+ type = type || config.type || 'audio/wav';
+ if (!currCallback) throw new Error('[b2bRecorder]: Callback not set!');
+ worker.postMessage({
+ command: 'exportWAV',
+ type: type
+ });
+ };
+
+ this.exportMonoWAV = function(cb, type) {
+ currCallback = cb || config.callback;
+ type = type || config.type || 'audio/wav';
+ if (!currCallback) throw new Error('[b2bRecorder]: Callback not set!');
+ worker.postMessage({
+ command: 'exportMonoWAV',
+ type: type
+ });
+ };
+
+ worker.onmessage = function(e) {
+ var blob = e.data;
+ currCallback(blob);
+ };
+
+ source.connect(this.node);
+ this.node.connect(this.context.destination); // if the script node is not connected to an output the "onaudioprocess" event is not triggerd in Chrome
+
+ };
+
+ return Recorder;
+
+})
+.factory('b2bViewport', function() {
+ /* Source: https://gist.github.com/bjankord/2399828 */
+ var _viewportWidth = function() {
+ var vpw;
+ var webkit = (!(window.webkitConvertPointFromNodeToPage == null));
+
+ // Webkit:
+ if ( webkit ) {
+ var vpwtest = document.createElement( "div" );
+ // Sets test div to width 100%, !important overrides any other misc. box model styles that may be set in the CSS
+ vpwtest.style.cssText = "width:100% !important; margin:0 !important; padding:0 !important; border:none !important;";
+ document.documentElement.insertBefore( vpwtest, document.documentElement.firstChild );
+ vpw = vpwtest.offsetWidth;
+ document.documentElement.removeChild( vpwtest );
+ }
+ // IE 6-8:
+ else if ( window.innerWidth === undefined ) {
+ vpw = document.documentElement.clientWidth;
+ }
+ // Other:
+ else{
+ vpw = window.innerWidth;
+ }
+
+ return (vpw);
+ }
+ return {
+ viewportWidth: _viewportWidth
+ };
+})
+.directive('b2bWhenScrollEnds', function(b2bWhenScrollEndsConstants, $log) {
+ return {
+ restrict: 'A',
+ link: function (scope, element, attrs) {
+ /**
+ * Exposed Attributes:
+ * threshold - integer - number of pixels before scrollbar hits end that callback is called
+ * width - integer - override for element's width (px)
+ * height - integer - override for element's height (px)
+ * axis - string - x/y for scroll bar axis
+ */
+ var threshold = parseInt(attrs.threshold, 10) || b2bWhenScrollEndsConstants.threshold;
+
+ if (!attrs.axis || attrs.axis === '') {
+ $log.warn('axis attribute must be defined for b2bWhenScrollEnds.');
+ return;
+ }
+
+ if (attrs.axis === 'x') {
+ visibleWidth = parseInt(attrs.width, 10) || b2bWhenScrollEndsConstants.width;
+ if (element.css('width')) {
+ visibleWidth = element.css('width').split('px')[0];
+ }
+
+ element[0].addEventListener('scroll', function() {
+ var scrollableWidth = element.prop('scrollWidth');
+ if (scrollableWidth === undefined) {
+ scrollableWidth = 1;
+ }
+ var hiddenContentWidth = scrollableWidth - visibleWidth;
+
+ if (hiddenContentWidth - element[0].scrollLeft <= threshold) {
+ /* Scroll almost at bottom, load more rows */
+ scope.$apply(attrs.b2bWhenScrollEnds);
+ }
+ });
+ } else if (attrs.axis === 'y') {
+ visibleHeight = parseInt(attrs.height, 10) || b2bWhenScrollEndsConstants.height;
+ if (element.css('width')) {
+ visibleHeight = element.css('height').split('px')[0];
+ }
+
+ element[0].addEventListener('scroll', function() {
+ var scrollableHeight = element.prop('scrollHeight');
+ if (scrollableHeight === undefined) {
+ scrollableHeight = 1;
+ }
+ var hiddenContentHeight = scrollableHeight - visibleHeight;
+
+ if (hiddenContentHeight - element[0].scrollTop <= threshold) {
+ /* Scroll almost at bottom, load more rows */
+ scope.$apply(attrs.b2bWhenScrollEnds);
+ }
+ });
+ }
+ }
+ };
+})
+
+.factory('$windowBind', ['$window', '$timeout', function($window, $timeout) {
+ var win = angular.element($window);
+ var _scroll = function (flag, callbackFunc, scope) {
+ scope.$watch(flag, function (val) {
+ $timeout(function () {
+ if (val) {
+ win.bind('scroll', callbackFunc);
+ } else {
+ win.unbind('scroll', callbackFunc);
+ }
+ });
+ });
+ };
+
+ var throttle = function(type, name, obj) {
+ obj = obj || window;
+ var running = false;
+ var func = function() {
+ if (running) { return; }
+ running = true;
+ requestAnimationFrame(function() {
+ obj.dispatchEvent(new CustomEvent(name));
+ running = false;
+ });
+ };
+ obj.addEventListener(type, func);
+ };
+
+ var _resize = function(callbackFunc, scope) {
+ throttle("resize", "optimizedResize");
+ window.addEventListener("optimizedResize", function(event) {
+ callbackFunc();
+ //win.bind(event, callbackFunc);
+ if (!scope.$$phase) {
+ scope.$digest();
+ }
+ });
+ };
+
+ var _click = function (flag, callbackFunc, scope) {
+ scope.$watch(flag, function (val) {
+ $timeout(function () {
+ if (val) {
+ win.bind('click', callbackFunc);
+ } else {
+ win.unbind('click', callbackFunc);
+ }
+ });
+ });
+ };
+
+ var _event = function (event, flag, callbackFunc, scope, timeoutFlag, timeoutValue) {
+ if (timeoutFlag) {
+ if (!(timeoutValue)) {
+ timeoutValue = 0;
+ }
+ scope.$watch(flag, function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ $timeout(function () {
+ if (newVal) {
+ win.bind(event, callbackFunc);
+ } else {
+ win.unbind(event, callbackFunc);
+ }
+ }, timeoutValue);
+ }
+ });
+ } else {
+ scope.$watch(flag, function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ if (newVal) {
+ win.bind(event, callbackFunc);
+ } else {
+ win.unbind(event, callbackFunc);
+ }
+ }
+ });
+ }
+ };
+
+ return {
+ click: _click,
+ scroll: _scroll,
+ event: _event,
+ resize: _resize
+ };
+}])
+
+.factory('keymap', function () {
+ return {
+ KEY: {
+ TAB: 9,
+ ENTER: 13,
+ ESC: 27,
+ SPACE: 32,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ HOME: 36,
+ END: 35,
+ BACKSPACE: 8,
+ DELETE: 46,
+ COMMAND: 91
+ },
+ MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'"
+ },
+ isControl: function (e) {
+ var k = e.keyCode;
+ switch (k) {
+ case this.KEY.COMMAND:
+ case this.KEY.SHIFT:
+ case this.KEY.CTRL:
+ case this.KEY.ALT:
+ return true;
+ default:;
+ }
+
+ if (e.metaKey) {
+ return true;
+ }
+
+ return false;
+ },
+ isFunctionKey: function (k) {
+ k = k.keyCode ? k.keyCode : k;
+ return k >= 112 && k <= 123;
+ },
+ isVerticalMovement: function (k) {
+ return ~[this.KEY.UP, this.KEY.DOWN].indexOf(k);
+ },
+ isHorizontalMovement: function (k) {
+ return ~[this.KEY.LEFT, this.KEY.RIGHT, this.KEY.BACKSPACE, this.KEY.DELETE].indexOf(k);
+ },
+ isAllowedKey: function (k) {
+ return (~[this.KEY.SPACE, this.KEY.ESC, this.KEY.ENTER].indexOf(k)) || this.isHorizontalMovement(k) || this.isVerticalMovement(k);
+ },
+ isNumericKey: function (e) {
+ var k = e.keyCode;
+ if ((k >= 48 && k <= 57) || (k >= 96 && k <= 105)) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ isAlphaNumericKey: function (e) {
+ var k = e.keyCode;
+ if ((k >= 48 && k <= 57) || (k >= 96 && k <= 105) || (k >= 65 && k <= 90)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+})
+
+.factory('$isElement', [function () {
+ var isElement = function (currentElem, targetElem, alternateElem) {
+ if (currentElem[0] === targetElem[0]) {
+ return true;
+ } else if (currentElem[0] === alternateElem[0]) {
+ return false;
+ } else {
+ return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
+ }
+ };
+
+ return isElement;
+}])
+
+.factory('events', function () {
+ var _stopPropagation = function (evt) {
+ if (evt.stopPropagation) {
+ evt.stopPropagation();
+ } else {
+ evt.returnValue = false;
+ }
+ };
+ var _preventDefault = function (evt) {
+ if (evt.preventDefault) {
+ evt.preventDefault();
+ } else {
+ evt.returnValue = false;
+ }
+ }
+ return {
+ stopPropagation: _stopPropagation,
+ preventDefault: _preventDefault
+ };
+})
+
+
+.factory('$documentBind', ['$document', '$timeout', function ($document, $timeout) {
+ var _click = function (flag, callbackFunc, scope) {
+ scope.$watch(flag, function (val) {
+ $timeout(function () {
+ if (val) {
+ $document.bind('click', callbackFunc);
+ } else {
+ $document.unbind('click', callbackFunc);
+ }
+ });
+ });
+ };
+
+ var _scroll = function (flag, callbackFunc, scope) {
+ scope.$watch(flag, function (val) {
+ $timeout(function () {
+ if (val) {
+ $document.bind('scroll', callbackFunc);
+ } else {
+ $document.unbind('scroll', callbackFunc);
+ }
+ });
+ });
+ };
+
+ var _event = function (event, flag, callbackFunc, scope, timeoutFlag, timeoutValue) {
+ if (timeoutFlag) {
+ if (!(timeoutValue)) {
+ timeoutValue = 0;
+ }
+ scope.$watch(flag, function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ $timeout(function () {
+ if (newVal) {
+ $document.bind(event, callbackFunc);
+ } else {
+ $document.unbind(event, callbackFunc);
+ }
+ }, timeoutValue);
+ }
+ });
+ } else {
+ scope.$watch(flag, function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ if (newVal) {
+ $document.bind(event, callbackFunc);
+ } else {
+ $document.unbind(event, callbackFunc);
+ }
+ }
+ });
+ }
+ };
+
+ return {
+ click: _click,
+ scroll: _scroll,
+ event: _event
+ };
+}])
+
+.directive('b2bOnlyNums', function (keymap) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elm, attrs, ctrl) {
+ var maxChars = attrs.b2bOnlyNums ? attrs.b2bOnlyNums : 4;
+ elm.on('keydown', function (event) {
+ if ((event.which >= 48 && event.which <= 57) || (event.which >= 96 && event.which <= 105)) {
+ // check for maximum characters allowed
+ if (elm.val().length < maxChars){
+ return true;
+ } else {
+ event.preventDefault();
+ return false;
+ }
+ } else if ([8, 9, 13, 27, 37, 38, 39, 40].indexOf(event.which) > -1) {
+ // to allow backspace, tab, enter, escape, arrows
+ return true;
+ } else if (event.altKey || event.ctrlKey) {
+ // to allow alter, control, and shift keys
+ return true;
+ } else {
+ // to stop others
+ event.preventDefault();
+ return false;
+ }
+ });
+
+ var validateString = function (value) {
+ if (angular.isUndefined(value) || value === null || value === '') {
+ return ctrl.$modelValue;
+ }
+ return value;
+ };
+ ctrl.$parsers.unshift(validateString);
+ }
+ }
+})
+
+.directive('b2bKeyupClick', [ function () {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr) {
+ var keyCode = [];
+ attr.$observe('b2bKeyupClick', function (value) {
+ if (value) {
+ keyCode = value.split(',');
+ }
+ });
+ elem.bind('keydown keyup', function (ev) {
+ var keyCodeCondition = function () {
+ var flag = false;
+ if (!(ev.keyCode)) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if ((ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1)) {
+ flag = true;
+ }
+ return flag;
+ };
+ if (ev.type === 'keydown' && keyCodeCondition()) {
+ ev.preventDefault();
+ }
+ else if (ev.type === 'keyup' && keyCodeCondition()) {
+ elem[0].click();
+ }
+ });
+ }
+ };
+}])
+
+.factory('b2bDOMHelper', function() {
+
+ var _isTabable = function(node) {
+ var element = angular.element(node);
+ var tagName = element[0].tagName.toUpperCase();
+
+ if (isHidden(element)) {
+ return false;
+ }
+ if (element.attr('tabindex') !== undefined) {
+ return (parseInt(element.attr('tabindex'), 10) >= 0);
+ }
+ if (tagName === 'A' || tagName === 'AREA' || tagName === 'BUTTON' || tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {
+ if (tagName === 'A' || tagName === 'AREA') {
+ // anchors/areas without href are not focusable
+ return (element[0].href !== '');
+ }
+ return !(element[0].disabled || element[0].readOnly);
+ }
+ return false;
+ };
+
+ function isValidChild(child) {
+ return child.nodeType == 1 && child.nodeName != 'SCRIPT' && child.nodeName != 'STYLE';
+ }
+
+ function isHidden(obj) {
+ var elem = angular.element(obj);
+ var elemStyle = undefined;
+ if(obj instanceof HTMLElement){
+ elemStyle = window.getComputedStyle(obj);
+ }
+ else {
+ elemStyle = window.getComputedStyle(obj[0]);
+ }
+ return elem.hasClass('ng-hide') || elem.css('display') === 'none' || elemStyle.display === 'none' || elemStyle.visibility === 'hidden' || elem.css('visibility') === 'hidden';
+ }
+
+ function hasValidParent(obj) {
+ return (isValidChild(obj) && obj.parentElement.nodeName !== 'BODY');
+ }
+
+ function traverse(obj, fromTop) {
+ var obj = obj || document.getElementsByTagName('body')[0];
+ if (isValidChild(obj) && _isTabable(obj)) {
+ return obj;
+ }
+ // If object is hidden, skip it's children
+ if (isValidChild(obj) && isHidden(obj)) {
+ return undefined;
+ }
+ // If object is hidden, skip it's children
+ if (angular.element(obj).hasClass('ng-hide')) {
+ return undefined;
+ }
+ if (obj.hasChildNodes()) {
+ var child;
+ if (fromTop) {
+ child = obj.firstChild;
+ } else {
+ child = obj.lastChild;
+ }
+ while(child) {
+ var res = traverse(child, fromTop);
+ if(res){
+ return res;
+ }
+ else{
+ if (fromTop) {
+ child = child.nextSibling;
+ } else {
+ child = child.previousSibling;
+ }
+ }
+ }
+ }
+ else{
+ return undefined;
+ }
+ }
+
+ var _previousElement = function(el, isFocusable){
+
+ var elem = el;
+ if (el.hasOwnProperty('length')) {
+ elem = el[0];
+ }
+
+ var parent = elem.parentElement;
+ var previousElem = undefined;
+
+ if(isFocusable) {
+ if (hasValidParent(elem)) {
+ var siblings = angular.element(parent).children();
+ if (siblings.length > 0) {
+ // Good practice to splice out the elem from siblings if there, saving some time.
+ // We allow for a quick check for jumping to parent first before removing.
+ if (siblings[0] === elem) {
+ // If we are looking at immidiate parent and elem is first child, we need to go higher
+ var e = _previousElement(angular.element(elem).parent(), isFocusable);
+ if (_isTabable(e)) {
+ return e;
+ }
+ } else {
+ // I need to filter myself and any nodes next to me from the siblings
+ var indexOfElem = Array.prototype.indexOf.call(siblings, elem);
+ siblings = Array.prototype.filter.call(siblings, function(item, itemIndex) {
+ if (!angular.equals(elem, item) && itemIndex < indexOfElem) {
+ return true;
+ }
+ });
+ }
+ // We need to search backwards
+ for (var i = 0; i <= siblings.length-1; i++) {//for (var i = siblings.length-1; i >= 0; i--) {
+ var ret = traverse(siblings[i], false);
+ if (ret !== undefined) {
+ return ret;
+ }
+ }
+
+ var e = _previousElement(angular.element(elem).parent(), isFocusable);
+ if (_isTabable(e)) {
+ return e;
+ }
+ }
+ }
+ } else {
+ var siblings = angular.element(parent).children();
+ if (siblings.length > 1) {
+ // Since indexOf is on Array.prototype and parent.children is a NodeList, we have to use call()
+ var index = Array.prototype.indexOf.call(siblings, elem);
+ previousElem = siblings[index-1];
+ }
+ }
+ return previousElem;
+ };
+
+ var _lastTabableElement = function(el) {
+ /* This will return the first tabable element from the parent el */
+ var elem = el;
+ if (el.hasOwnProperty('length')) {
+ elem = el[0];
+ }
+
+ return traverse(elem, false);
+ };
+
+ var _firstTabableElement = function(el) {
+ /* This will return the first tabable element from the parent el */
+ var elem = el;
+ if (el.hasOwnProperty('length')) {
+ elem = el[0];
+ }
+
+ return traverse(elem, true);
+ };
+
+ var _isInDOM = function(obj) {
+ return document.documentElement.contains(obj);
+ }
+
+ return {
+ firstTabableElement: _firstTabableElement,
+ lastTabableElement: _lastTabableElement,
+ previousElement: _previousElement,
+ isInDOM: _isInDOM,
+ isTabable: _isTabable,
+ isHidden: isHidden
+ };
+})
+
+.factory('trapFocusInElement', ['$document', '$isElement', 'DOMHelper', 'keymap', function ($document, $isElement, DOMHelper, keymap) {
+ var elementStack = [];
+ var stackHead = undefined;
+ var trapFocusInElement = function (flag) {
+ var bodyElements = $document.find('body').children();
+
+ var firstTabableElement = angular.element(DOMHelper.firstTabableElement(stackHead));
+ var lastTabableElement = angular.element(DOMHelper.lastTabableElement(stackHead));
+
+ var trapKeyboardFocusInFirstElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === true && e.keyCode === keymap.KEY.TAB) {
+ lastTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+
+ };
+
+ var trapKeyboardFocusInLastElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === false && e.keyCode === keymap.KEY.TAB) {
+ firstTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+ };
+
+ if (flag) {
+ for (var i = 0; i < bodyElements.length; i++) {
+ if (bodyElements[i] !== stackHead[0]) {
+ bodyElements.eq(i).attr('aria-hidden', true);
+ }
+ }
+ firstTabableElement.bind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.bind('keydown', trapKeyboardFocusInLastElement);
+ } else {
+ for (var j = 0; j < bodyElements.length; j++) {
+ if (bodyElements[j] !== stackHead[0]) {
+ bodyElements.eq(j).removeAttr('aria-hidden');
+ }
+ }
+ firstTabableElement.unbind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.unbind('keydown', trapKeyboardFocusInLastElement);
+ }
+ };
+ var toggleTrapFocusInElement = function (flag, element) {
+ if (angular.isDefined(flag) && angular.isDefined(element)) {
+ if (angular.isUndefined(stackHead)) {
+ stackHead = element;
+ trapFocusInElement(flag);
+ } else {
+ if (flag) {
+ trapFocusInElement(false);
+ elementStack.push(stackHead);
+ stackHead = element;
+ trapFocusInElement(true);
+ } else {
+ if (stackHead.prop('$$hashKey') === element.prop('$$hashKey')) {
+ trapFocusInElement(false);
+ stackHead = elementStack.pop();
+ if (angular.isDefined(stackHead)) {
+ trapFocusInElement(true);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ return toggleTrapFocusInElement;
+}])
+
+.factory('DOMHelper', function () {
+
+ var _isTabable = function (node) {
+ var element = angular.element(node);
+ var tagName = element[0].tagName.toUpperCase();
+
+ if (isHidden(element)) {
+ return false;
+ }
+ if (element.attr('tabindex') !== undefined) {
+ return (parseInt(element.attr('tabindex'), 10) >= 0);
+ }
+ if (tagName === 'A' || tagName === 'AREA' || tagName === 'BUTTON' || tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {
+ if (tagName === 'A' || tagName === 'AREA') {
+ // anchors/areas without href are not focusable
+ return (element[0].href !== '');
+ }
+ return !(element[0].disabled || element[0].readOnly);
+ }
+ return false;
+ };
+
+ function isValidChild(child) {
+ return child.nodeType == 1 && child.nodeName != 'SCRIPT' && child.nodeName != 'STYLE';
+ }
+
+ function isHidden(obj) {
+ var elem = angular.element(obj);
+ var style;
+ try {
+ style = window.getComputedStyle(obj);
+ }
+ catch(err) {
+ style = window.getComputedStyle(obj[0]);
+ }
+
+ // getComputedStyle() for Zepto object returns null
+ if (style === null){
+ return elem.hasClass('ng-hide') || elem.css('display') === 'none';
+ }
+
+ return elem.hasClass('ng-hide') || elem.css('display') === 'none' || style.display === 'none' || style.display === 'hidden';
+ }
+
+ function traverse(obj, fromTop) {
+ var obj = obj || document.getElementsByTagName('body')[0];
+
+ if (isValidChild(obj) && _isTabable(obj)) {
+ return obj;
+ }
+
+ // If object is hidden, skip it's children
+ if (isValidChild(obj) && isHidden(obj)) {
+ return undefined;
+ }
+ // If object is hidden, skip it's children
+ if (angular.element(obj).hasClass('ng-hide')) {
+ return undefined;
+ }
+
+ if (obj.hasChildNodes()) {
+ var child;
+ if (fromTop) {
+ child = obj.firstChild;
+ } else {
+ child = obj.lastChild;
+ }
+ while (child) {
+ var res = traverse(child, fromTop);
+ if (res) {
+ return res;
+ } else {
+ if (fromTop) {
+ child = child.nextSibling;
+ } else {
+ child = child.previousSibling;
+ }
+ }
+ }
+ } else {
+ return undefined;
+ }
+ }
+
+ var _lastTabableElement = function (el) {
+ /* This will return the last tabable element from the parent el */
+ var elem = el;
+ if (el.hasOwnProperty('length')) {
+ elem = el[0];
+ }
+
+ return traverse(elem, false);
+ };
+
+ var _firstTabableElement = function (el) {
+ /* This will return the first tabable element from the parent el */
+ var elem = el;
+ if (el.hasOwnProperty('length')) {
+ elem = el[0];
+ }
+
+ return traverse(elem, true);
+ };
+
+ return {
+ firstTabableElement: _firstTabableElement,
+ lastTabableElement: _lastTabableElement,
+ isTabable: _isTabable
+ };
+})
+
+.factory('windowOrientation', ['$window', function ($window) {
+ var _isPotrait = function () {
+ if ($window.innerHeight > $window.innerWidth) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ var _isLandscape = function () {
+ if ($window.innerHeight < $window.innerWidth) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ return {
+ isPotrait: _isPotrait,
+ isLandscape: _isLandscape
+ };
+}])
+
+.directive('b2bNextElement', function() {
+ return {
+ restrict: 'A',
+ transclude: false,
+ link: function (scope, elem, attr, ctrls) {
+
+ var keys = attr.b2bNextElement.split(',');
+
+ elem.bind('keydown', function (e) {
+ var nextElement = elem.next();
+ if(e.keyCode == 39 || e.keyCode == 40){ // if e.keyCode in keys
+ if(nextElement.length) {
+ e.preventDefault();
+ nextElement[0].focus();
+ }
+ }
+ });
+ }
+ }
+})
+
+.directive('b2bAccessibilityClick', [function () {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr, ctrl) {
+ var keyCode = [];
+ attr.$observe('b2bAccessibilityClick', function (value) {
+ if (value) {
+ keyCode = value.split(',');
+ }
+ });
+ elem.bind('keydown keypress', function (ev) {
+ var keyCodeCondition = function () {
+ var flag = false;
+ if (!(ev.keyCode)) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if ((ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1)) {
+ flag = true;
+ }
+ return flag;
+ };
+ if (keyCode.length > 0 && keyCodeCondition()) {
+ elem[0].click();
+ ev.preventDefault();
+ }
+ });
+ }
+ };
+}])
+
+.directive('b2bReset', ['$compile', function ($compile) {
+ return {
+ restrict: 'A',
+ require: ['?ngModel', 'b2bReset'],
+ controller: ['$scope', function ($scope) {
+ var resetButton = angular.element('<button type="button" class="reset-field" tabindex="-1" aria-label="Click to reset" aria-hidden="true" role="button"></button>');
+
+ this.getResetButton = function () {
+ return resetButton;
+ };
+ }],
+ link: function (scope, element, attrs, ctrls) {
+
+ var ngModelCtrl = ctrls[0];
+ var ctrl = ctrls[1];
+
+ var resetButton = ctrl.getResetButton();
+
+
+ resetButton.on('click', function () {
+ element[0].value = '';
+
+ if (ngModelCtrl) {
+ if (attrs.b2bReset) {
+ ngModelCtrl.$setViewValue(attrs.b2bReset);
+ } else {
+ ngModelCtrl.$setViewValue('');
+ }
+ element[0].value = ngModelCtrl.$viewValue;
+ ngModelCtrl.$render();
+ scope.$digest();
+ }
+ element[0].focus();
+ element[0].select();
+ });
+
+ var addResetButton = function () {
+ element.after(resetButton);
+ element.unbind('focus input', addResetButton);
+ };
+
+ element.bind('focus input', addResetButton);
+ }
+ };
+ }])
+
+.directive('b2bPrevElement', ['b2bDOMHelper', 'keymap', function (b2bDOMHelper, keymap) {
+ return {
+ restrict: 'A',
+ transclude: false,
+ link: function (scope, elem, attr) {
+
+ elem.bind('keydown', function (e) {
+ if(e.keyCode == 37 || e.keyCode == 38){
+ var prev = b2bDOMHelper.previousElement(elem, false);
+ if(prev !== undefined) {
+ e.preventDefault();
+ prev.focus();
+ }
+ }
+ });
+ }
+ }
+}])
+/**
+ * @param {integer} delay - Timeout before first and last focusable elements are found
+ * @param {boolean} trigger - A variable on scope that will trigger refinding first/last focusable elements
+ */
+.directive('b2bTrapFocusInsideElement', ['$timeout', 'b2bDOMHelper', 'keymap', 'events', function ($timeout, b2bDOMHelper, keymap, events) {
+ return {
+ restrict: 'A',
+ transclude: false,
+ link: function (scope, elem, attr) {
+
+ var delay = parseInt(attr.delay, 10) || 10;
+
+ /* Before opening modal, find the focused element */
+ var firstTabableElement = undefined,
+ lastTabableElement = undefined;
+
+ function init() {
+ $timeout(function () {
+ firstTabableElement = b2bDOMHelper.firstTabableElement(elem);
+ lastTabableElement = b2bDOMHelper.lastTabableElement(elem);
+ angular.element(firstTabableElement).bind('keydown', firstTabableElementKeyhandler);
+ angular.element(lastTabableElement).bind('keydown', lastTabableElementKeyhandler);
+ }, delay, false);
+ }
+
+ if (attr.trigger !== undefined) {
+ scope.$watch('trigger', function() {
+ if (scope.trigger) {
+ init();
+ }
+ });
+ }
+
+ var firstTabableElementKeyhandler = function(e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+ if (e.keyCode === keymap.KEY.TAB && e.shiftKey) {
+ if (attr.trapFocusInsideElement === 'true') {
+ var temp = b2bDOMHelper.lastTabableElement(elem);
+ if (lastTabableElement !== temp) {
+ // Unbind keydown handler on lastTabableElement
+ angular.element(lastTabableElement).unbind('keydown', lastTabableElementKeyhandler);
+ lastTabableElement = temp;
+ angular.element(lastTabableElement).bind('keydown', lastTabableElementKeyhandler);
+ }
+ }
+ lastTabableElement.focus();
+ events.preventDefault(e);
+ events.stopPropagation(e);
+ }
+ };
+
+ var lastTabableElementKeyhandler = function(e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+ if (e.keyCode === keymap.KEY.TAB && !e.shiftKey) {
+ if (attr.trapFocusInsideElement === 'true') {
+ var temp = b2bDOMHelper.firstTabableElement(elem);
+ if (firstTabableElement !== temp) {
+ // Unbind keydown handler on firstTabableElement
+ angular.element(firstTabableElement).unbind('keydown', firstTabableElementKeyhandler);
+ firstTabableElement = temp;
+ angular.element(firstTabableElement).bind('keydown', firstTabableElementKeyhandler);
+ }
+ }
+ firstTabableElement.focus();
+ events.preventDefault(e);
+ events.stopPropagation(e);
+ }
+ };
+
+ init();
+ }
+ };
+}])
+
+.factory('trapFocusInElement', ['$document', '$isElement', 'DOMHelper', 'keymap', '$interval', function ($document, $isElement, DOMHelper, keymap, $interval) {
+ var elementStack = [];
+ var stackHead = undefined;
+ var stopInterval = undefined;
+ var intervalRequired = false;
+ var interval = 1000;
+ var firstTabableElement, lastTabableElement;
+
+ var trapKeyboardFocusInFirstElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === true && e.keyCode === keymap.KEY.TAB) {
+ lastTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+
+ };
+
+ var trapKeyboardFocusInLastElement = function (e) {
+ if (!e.keyCode) {
+ e.keyCode = e.which;
+ }
+
+ if (e.shiftKey === false && e.keyCode === keymap.KEY.TAB) {
+ firstTabableElement[0].focus();
+ e.preventDefault(e);
+ e.stopPropagation(e);
+ }
+ };
+
+ var trapFocusInElement = function (flag, firstTabableElementParam, lastTabableElementParam) {
+ var bodyElements = $document.find('body').children();
+
+ firstTabableElement = firstTabableElementParam ? firstTabableElementParam : angular.element(DOMHelper.firstTabableElement(stackHead));
+ lastTabableElement = lastTabableElementParam ? lastTabableElementParam : angular.element(DOMHelper.lastTabableElement(stackHead));
+
+ if (flag) {
+ for (var i = 0; i < bodyElements.length; i++) {
+ if (bodyElements[i] !== stackHead[0]) {
+ bodyElements.eq(i).attr('aria-hidden', true);
+ }
+ }
+ firstTabableElement.bind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.bind('keydown', trapKeyboardFocusInLastElement);
+ } else {
+ for (var j = 0; j < bodyElements.length; j++) {
+ if (bodyElements[j] !== stackHead[0]) {
+ bodyElements.eq(j).removeAttr('aria-hidden');
+ }
+ }
+ firstTabableElement.unbind('keydown', trapKeyboardFocusInFirstElement);
+ lastTabableElement.unbind('keydown', trapKeyboardFocusInLastElement);
+ }
+
+ if (intervalRequired && flag) {
+ stopInterval = $interval(function () {
+ var firstTabableElementTemp = angular.element(DOMHelper.firstTabableElement(stackHead));
+ var lastTabableElementTemp = angular.element(DOMHelper.lastTabableElement(stackHead));
+ if (firstTabableElementTemp[0] !== firstTabableElement[0] || lastTabableElementTemp[0] !== lastTabableElement[0]) {
+ $interval.cancel(stopInterval);
+ stopInterval = undefined;
+ trapFocusInElement(false, firstTabableElement, lastTabableElement);
+ trapFocusInElement(true, firstTabableElementTemp, lastTabableElementTemp);
+ }
+ }, interval);
+ } else {
+ if (stopInterval) {
+ $interval.cancel(stopInterval);
+ stopInterval = undefined;
+ }
+ }
+ };
+ var toggleTrapFocusInElement = function (flag, element, intervalRequiredParam, intervalParam) {
+ intervalRequired = intervalRequiredParam ? intervalRequiredParam : intervalRequired;
+ interval = intervalParam ? intervalParam : interval;
+ if (angular.isDefined(flag) && angular.isDefined(element)) {
+ if (flag && angular.isUndefined(stackHead)) {
+ stackHead = element;
+ trapFocusInElement(flag);
+ } else {
+ if (flag) {
+ trapFocusInElement(false);
+ elementStack.push(stackHead);
+ stackHead = element;
+ trapFocusInElement(true);
+ } else {
+ if (angular.isDefined(stackHead) && (stackHead[0] === element[0])) {
+ trapFocusInElement(false);
+ stackHead = elementStack.pop();
+ if (angular.isDefined(stackHead)) {
+ trapFocusInElement(true);
+ }
+ }
+ }
+ }
+ } else {
+ if (angular.isDefined(stackHead)) {
+ trapFocusInElement(false, firstTabableElement, lastTabableElement);
+ trapFocusInElement(true);
+ }
+ }
+ };
+
+ return toggleTrapFocusInElement;
+}])
+
+.directive('b2bSetNextFocusOn', ['b2bDOMHelper', '$timeout', function(b2bDOMHelper, $timeout) {
+ return {
+ restrict: 'A',
+ scope: true,
+ link: function (scope, elem, attr) {
+ elem.bind('click', function(){
+ var firstFocusableElement = undefined;
+ var containerElem = undefined;
+ var containerArray = [];
+ var timeout = parseInt(attr.setNextFocusTimeout, 0) | 100;
+ var index = parseInt(attr.b2bSetNextFocusIndex, 0) | 0;
+
+ /*
+ *Fix for IE7 and lower
+ *polyfill src: https://github.com/HubSpot/pace/issues/102
+ */
+ if (!document.querySelectorAll) {
+ document.querySelectorAll = function (selectors) {
+ var style = document.createElement('style'), elements = [], element;
+ document.documentElement.firstChild.appendChild(style);
+ document._qsa = [];
+
+ style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
+ window.scrollBy(0, 0);
+ style.parentNode.removeChild(style);
+
+ while (document._qsa.length) {
+ element = document._qsa.shift();
+ element.style.removeAttribute('x-qsa');
+ elements.push(element);
+ }
+ document._qsa = null;
+ return elements;
+ };
+ }
+
+ if (attr.b2bSetNextFocusOn === '') {
+ return;
+ } else {
+ containerArray = attr.b2bSetNextFocusOn.split(' ');
+ }
+ $timeout(function(){
+ var i = 0;
+ do { // cycles thru containerArray until finds a match in DOM to set focus to
+ containerElem = document.querySelectorAll(containerArray[i])[index];
+ i++;
+ } while ( (!containerElem) && (i < containerArray.length) );
+ if(containerElem){
+ if (!angular.isDefined(firstFocusableElement)) {
+ firstFocusableElement = b2bDOMHelper.firstTabableElement(containerElem);
+ }
+ firstFocusableElement.focus();
+ }
+ }, timeout, false)
+ });
+ }
+
+ };
+}])
+
+.directive('b2bInputAllow', [function() {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ var regexExpression = null;
+ attr.$observe('b2bInputAllow', function (value) {
+ if (value) {
+ regexExpression = new RegExp(value);
+ }
+ });
+ var isValid = function(str) {
+ if (regexExpression !== null) {
+ return regexExpression.test(str);
+ }
+ return false;
+ };
+ elem.bind('keypress', function($event) {
+ var charcode = String.fromCharCode($event.which || $event.keyCode);
+ if (!isValid(charcode)) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ }
+ });
+ elem.bind('input', function (evt) {
+ var inputString = ctrl.$viewValue;
+ if (isValid(inputString)) {
+ ctrl.$setViewValue(inputString);
+ ctrl.$render();
+ scope.$apply();
+ }
+ });
+ }
+ };
+}])
+
+.directive('b2bInputDeny', [function() {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ var regexExpression = null;
+ attr.$observe('b2bInputDeny', function (value) {
+ if (value) {
+ regexExpression = new RegExp(value, 'g');
+ }
+ });
+ elem.bind('input', function () {
+ var inputString = ctrl.$viewValue && ctrl.$viewValue.replace(regexExpression, '');
+ if (inputString !== ctrl.$viewValue) {
+ ctrl.$setViewValue(inputString);
+ ctrl.$render();
+ scope.$apply();
+ }
+ });
+ }
+ };
+}])
+
+.directive('b2bDragonInput', [function() {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function (scope, elem, attr, ctrl) {
+ elem.on('focus keyup', function(){
+ elem.triggerHandler('change');
+ });
+ }
+ };
+}])
+
+.directive('b2bKey', ['b2bUtilitiesConfig', '$timeout', 'keymap', function (b2bUtilitiesConfig, $timeout, keymap) {
+ return {
+ restrict: 'EA',
+ controller: ['$scope', '$element', '$attrs', function ($scope, $element,attr) {
+ this.childElements = [];
+ this.disableNodes = {};
+ this.enableSearch = attr.enableSearch !== undefined ? true : b2bUtilitiesConfig.enableSearch;
+ this.circularTraversal = attr.circularTraversal !== undefined ? true : b2bUtilitiesConfig.circularTraversal;
+ this.counter = -1;
+ if (this.enableSearch) {
+ this.searchKeys = [];
+ }
+ var searchString = '';
+
+ var selfCtrl = this;
+
+ this.childElementsList = [];
+
+ this.b2bKeyID = "";
+
+ if (angular.isDefined(attr.b2bKey)) {
+ this.b2bKeyID = attr.b2bKey;
+ }
+
+ this.calculateChildElementsList = function () {
+ return $element[0].querySelectorAll("[b2b-key-item='" + this.b2bKeyID + "']:not([disabled])");
+ };
+
+ this.resetChildElementsList = function () {
+ return $timeout(function () {
+ selfCtrl.childElementsList = selfCtrl.calculateChildElementsList();
+ });
+ };
+
+ this.resetChildElementsList();
+
+ $scope.$on('b2b-key-reset-child-elements-list', function () {
+ selfCtrl.resetChildElementsList();
+ });
+
+
+ this.registerElement = function (childElement, searchKey) {
+ this.childElements.push(childElement);
+ if (this.enableSearch) {
+ this.searchKeys.push(searchKey);
+ }
+ var count = this.childElements.length - 1;
+ this.maxLength = count + 1;
+ return count;
+ };
+ this.toggleDisable = function (count, state) {
+ this.disableNodes[count] = state;
+ };
+ this.searchElement = function (searchExp) {
+ var regex = new RegExp("\\b" + searchExp, "gi");
+ var position = this.searchKeys.regexIndexOf(regex, this.counter + 1, true);
+ if (position > -1) {
+ this.counter = position;
+ this.moveFocus(this.counter);
+ }
+ };
+ this.startTimer = function (time) {
+ if (searchString === '') {
+ $timeout(function () {
+ searchString = '';
+ }, time);
+ }
+ };
+ this.resetCounter = function (count) {
+ this.counter = count;
+ };
+ this.moveNext = function (count) {
+ this.counter = (this.counter + count) < this.maxLength ? this.counter + count : (this.circularTraversal ? 0 : this.counter);
+ if (this.disableNodes[this.counter]) {
+ if ((this.counter + count) < this.maxLength) {
+ this.moveNext(count);
+ }
+ } else {
+ this.moveFocus(this.counter);
+ }
+ };
+ this.movePrev = function (count) {
+ this.counter = (this.counter - count) > -1 ? this.counter - count : (this.circularTraversal ? this.maxLength-1 : this.counter);
+ if (this.disableNodes[this.counter]) {
+ if ((this.counter - count) > -1) {
+ this.movePrev(count);
+ }
+ } else {
+ this.moveFocus(this.counter);
+ }
+ };
+ this.moveFocus = function (index) {
+ this.childElements[index][0].focus();
+ };
+
+ this.keyDownHandler = function (ev, count) {
+ if (angular.isDefined(count) && !isNaN(count) && count !== this.counter) {
+ this.resetCounter(count);
+ }
+ if (!ev.keyCode) {
+ if (ev.which) {
+ ev.keyCode = ev.which;
+ } else if (ev.charCode) {
+ ev.keyCode = ev.charCode;
+ }
+ }
+ if (ev.keyCode) {
+ if (this.prev && this.prev.indexOf(ev.keyCode.toString()) > -1) {
+ this.movePrev(1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (this.next && this.next.indexOf(ev.keyCode.toString()) > -1) {
+ this.moveNext(1);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (this.up && this.up.indexOf(ev.keyCode.toString()) > -1) {
+ if (this.type === 'table') {
+ this.movePrev(this.columns);
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ } else if (this.down && this.down.indexOf(ev.keyCode.toString()) > -1) {
+ if (this.type === 'table') {
+ this.moveNext(this.columns);
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ } else if (ev.keyCode === keymap.KEY.HOME) {
+ var firstIndex = 0;
+ while (this.disableNodes[firstIndex] !== false) {
+ firstIndex++;
+ };
+ var count = this.counter - firstIndex;
+ this.movePrev(count);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode === keymap.KEY.END) {
+ var lastIndex = this.childElements.length - 1;
+ while (this.disableNodes[lastIndex] !== false) {
+ lastIndex--;
+ };
+ var count = lastIndex - this.counter;
+ this.moveNext(count);
+ ev.preventDefault();
+ ev.stopPropagation();
+ } else if (ev.keyCode >= 48 && ev.keyCode <= 105) {
+ if (this.enableSearch) {
+ this.startTimer(b2bUtilitiesConfig.searchTimer);
+ searchString = searchString + (keymap.MAP[ev.keyCode] || '');
+ this.searchElement(searchString);
+ ev.preventDefault();
+ ev.stopPropagation();
+ }
+ }
+ }
+ };
+ }],
+ link: function (scope, elem, attr, ctrl) {
+ ctrl.prev = attr.prev ? attr.prev.split(',') : b2bUtilitiesConfig.prev.split(',');
+ ctrl.next = attr.next ? attr.next.split(',') : b2bUtilitiesConfig.next.split(',');
+ ctrl.type = attr.type ? attr.type : b2bUtilitiesConfig.type;
+ if (ctrl.type === 'table') {
+ ctrl.up = attr.up ? attr.up.split(',') : b2bUtilitiesConfig.up.split(',');
+ ctrl.down = attr.down ? attr.down.split(',') : b2bUtilitiesConfig.down.split(',');
+ ctrl.columns = attr.columns ? parseInt(attr.columns, 10) : b2bUtilitiesConfig.columns;
+ }
+
+ elem.bind('keydown', function (ev) {
+ ctrl.keyDownHandler(ev);
+ });
+ }
+ };
+}])
+
+.directive('b2bKeyItem', [function () {
+ return {
+ restrict: 'EA',
+ link: function (scope, elem, attr, ctrl) {
+ var parentCtrl = (elem.parent() && elem.parent().controller('b2bKey')) || undefined;
+ if (angular.isDefined(parentCtrl)) {
+ var count = parentCtrl.registerElement(elem, attr.searchKey);
+ elem.bind('keydown', function (ev) {
+ parentCtrl.keyDownHandler(ev, count);
+ });
+ scope.$watch(attr.b2bKeyItem, function (value) {
+ value = value === undefined ? true : value;
+ parentCtrl.toggleDisable(count, !value);
+ });
+ scope.$on('$destroy', function () {
+ parentCtrl.toggleDisable(count, true);
+ });
+ }
+ }
+ };
+}])
+
+.directive('b2bElementFocus', [function () {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr, ctrl) {
+ scope.$watch(attr.b2bElementFocus, function (value) {
+ if (value === true) {
+ elem[0].focus();
+ }
+ });
+ }
+ };
+}])
+
+
+.directive('b2bAppendElement', ['$compile', function ($compile) {
+ return {
+ restrict: 'A',
+ link: function (scope, elem, attr, ctrl) {
+ var parameters = attr.b2bAppendElement.split(':');
+ if (parameters.length === 1) {
+ elem.append(scope.$eval(parameters[0]));
+ } else if (parameters.length === 2) {
+ if (parameters[1] === 'compile') {
+ var element = angular.element('<span>' + scope.$eval(parameters[0]) + '</span>');
+ elem.append($compile(element)(scope));
+ }
+ }
+
+ }
+ };
+}])
+
+.directive('b2bKeyItemRefreshInNgRepeat', [function () {
+ return {
+ restrict: 'EA',
+ require: '^^b2bKey',
+ link: function (scope, elem, attr, parentCtrl) {
+ if (angular.isDefined(parentCtrl)) {
+
+ var attrToObserve = 'attrToObserve';
+
+ if (attr.b2bKeyItemRefreshInNgRepeat) {
+ attrToObserve = 'b2bKeyItemRefreshInNgRepeat';
+ }
+
+ attr.$observe(attrToObserve, function (newVal, oldVal) {
+ if (newVal && newVal !== oldVal) {
+ parentCtrl.resetChildElementsList();
+ }
+ });
+ }
+ }
+ };
+}])
+
+.filter('b2bMultiSepartorHighlight', function($sce) {
+ return function(text, searchText, searchSeperator) {
+ var splitText = function(string) {
+ if(angular.isDefined(searchSeperator)){
+ if (string.indexOf(searchSeperator) > -1) {
+ return string.split(searchSeperator);
+ } else {
+ return string
+ }
+ }else{
+ return string;
+ }
+ }
+ if (text) {
+ var newText = splitText(text);
+ var newPhrase = splitText(searchText);
+ if (angular.isArray(newPhrase)) {
+ for (var i = 0; i < newText.length; i++) {
+ if (i <= 0) {
+ text = newText[i].replace(new RegExp('(' + newPhrase[i] + ')', 'gi'),
+ '<span class="b2b-search-hightlight">$1</span>');
+ } else {
+ text = text + searchSeperator + ' ' + (newPhrase[i] ? newText[i].replace(new RegExp('(' + newPhrase[i] + ')', 'gi'),
+ '<span class="b2b-search-hightlight">$1</span>') : newText[i]);
+ }
+ }
+ } else {
+ text = text.replace(new RegExp('(' + searchText + ')', 'gi'),
+ '<span class="b2b-search-hightlight">$1</span>');
+ }
+ }
+ return $sce.trustAsHtml(text)
+ }
+ })
+
+ .factory('b2bUserAgent', [function() {
+ var _isMobile = function() {
+ return /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+ };
+ var _notMobile = function() {
+ return !/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+ };
+ var _isIE = function() {
+ return /msie|trident/i.test(navigator.userAgent);
+ };
+ var _isFF = function() {
+ return /Firefox/.test(navigator.userAgent);
+ };
+ var _isChrome = function() {
+ return /Google Inc/.test(navigator.vendor);
+ };
+ var _isSafari = function() {
+ return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
+ };
+
+ return {
+ isMobile: _isMobile,
+ notMobile: _notMobile,
+ isIE: _isIE,
+ isFF: _isFF,
+ isChrome: _isChrome,
+ isSafari: _isSafari
+ };
+ }])
+ .run(['$document', 'b2bUserAgent', function($document, b2bUserAgent) {
+ var html = $document.find('html').eq(0);
+ if (b2bUserAgent.isIE()) {
+ html.addClass('isIE');
+ } else {
+ html.removeClass('isIE');
+ }
+ }]);
+
+
+(function () {
+ String.prototype.toSnakeCase = function () {
+ return this.replace(/([A-Z])/g, function ($1) {
+ return "-" + $1.toLowerCase();
+ });
+ };
+ var concat = function (character, times) {
+ character = character || '';
+ times = (!isNaN(times) && times) || 0;
+ var finalChar = '';
+ for (var i = 0; i < times; i++) {
+ finalChar += character;
+ }
+ return finalChar;
+ };
+
+ // direction: true for left and false for right
+ var pad = function (actualString, width, character, direction) {
+ actualString = actualString || '';
+ width = (!isNaN(width) && width) || 0;
+ character = character || '';
+ if (width > actualString.length) {
+ if (direction) {
+ return concat(character, (width - actualString.length)) + actualString;
+ } else {
+ return actualString + concat(character, (width - actualString.length));
+ }
+ }
+ return actualString;
+ };
+
+ String.prototype.lPad = function (width, character) {
+ return pad(this, width, character, true);
+ };
+
+ String.prototype.rPad = function (width, character) {
+ return pad(this, width, character, false);
+ };
+
+ if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function (val) {
+ for (var index = 0; index < this.length; index++) {
+ if (this[index] === val) {
+ return index;
+ }
+ }
+ return -1;
+ };
+ }
+
+ if (!Array.prototype.regexIndexOf) {
+ Object.defineProperty(Array.prototype, 'regexIndexOf', {
+ enumerable: false,
+ value: function (regex, startIndex, loop) {
+ startIndex = startIndex && startIndex > -1 ? startIndex : 0;
+ for (var index = startIndex; index < this.length; index++) {
+ if (this[index].toString().match(regex)) {
+ return index;
+ }
+ }
+ if (loop) {
+ for (var index = 0; index < startIndex; index++) {
+ if (this[index].toString().match(regex)) {
+ return index;
+ }
+ }
+ }
+ return -1;
+ }
+ })
+ }
+})();
+angular.module("b2bTemplate/audioPlayer/audioPlayer.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/audioPlayer/audioPlayer.html",
+ "<div class=\"b2b-audio\">\n" +
+ " <audio preload=\"auto\">\n" +
+ " <source ng-src=\"{{audio.mp3 | trustedAudioUrl}}\" type=\"audio/mp3\"></source>\n" +
+ " <i>Your browser does not support the audio element.</i>\n" +
+ " </audio>\n" +
+ "\n" +
+ " <div audio-play-pause-icon class=\"controls-wrapper\" ng-click=\"toggleAudio()\" tabindex=\"0\" b2b-accessibility-click=\"13,32\" role=\"button\" aria-label=\"{{isPlayInProgress?'pause':'play'}}\">\n" +
+ " <i class=\"icoControls-pointer\" ng-show='!isPlayInProgress'></i>\n" +
+ " <i class=\"icoControls-pause\" ng-show='isPlayInProgress'></i>\n" +
+ " </div>\n" +
+ "\n" +
+ " <div class=\"seek-bar-container-wrapper\">\n" +
+ " <b2b-seek-bar min=\"0\" max=\"{{audio.duration}}\" step=\"1\" skip-interval=\"{{audio.timeShiftInSeconds}}\" no-aria-label ng-model=\"audio.currentTime\" on-drag-init=\"isAudioDragging=true\" on-drag-end=\"setAudioPosition(audio.currentTime)\"></b2b-seek-bar>\n" +
+ " <div class=\"timing-container\">\n" +
+ " <span class=\"timing-container-left\">{{timeFormatter(audio.currentTime)}}</span>\n" +
+ " <span class=\"timing-container-right\">{{timeFormatter(audio.duration)}}</span>\n" +
+ " <div class=\"timing-container-spacer\"></div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " \n" +
+ " <b2b-flyout>\n" +
+ " <div tabindex=\"0\" b2b-accessibility-click=\"13,32\" role=\"button\" aria-label=\"Volume pop-over. Volume set at {{audio.currentVolume}}%\" class=\"controls-wrapper audio-volume-control\" b2b-flyout-toggler>\n" +
+ " <i class=\"icoControls-mutespeakers\" ng-show=\"audio.currentVolume === 0\"></i>\n" +
+ " <i class=\"icoControls-volumedown\" ng-show=\"audio.currentVolume > 0 && audio.currentVolume <= 50\"></i>\n" +
+ " <i class=\"icoControls-volumeup\" ng-show=\"audio.currentVolume > 50\"></i>\n" +
+ " </div> \n" +
+ " \n" +
+ " <b2b-flyout-content horizontal-placement=\"center\" flyout-style=\"width:70px; height:190px;\" vertical-placement=\"above\">\n" +
+ " <div class=\"b2b-audio-popover text-center\">\n" +
+ " <span>Max</span>\n" +
+ " <b2b-seek-bar min=\"0\" max=\"100\" step=\"1\" skip-interval=\"10\" vertical data-ng-model=\"audio.currentVolume\" class='volume-popover'></b2b-seek-bar>\n" +
+ " <div class=\"min-label\">Min</div>\n" +
+ " </div>\n" +
+ " </b2b-flyout-content>\n" +
+ " </b2b-flyout>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/audioRecorder/audioRecorder.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/audioRecorder/audioRecorder.html",
+ "<div class=\"b2b-audio-recorder row\">\n" +
+ " <div class=\"b2b-elapsed-time span11\">\n" +
+ " <div ng-if=\"isRecording\">\n" +
+ " <span style=\"padding-right: 25px;\">{{config.whileRecordingMessage}}</span>\n" +
+ " <span>{{timeFormatter(elapsedTime)}}</span>\n" +
+ " </div>\n" +
+ " <span ng-if=\"!isRecording\">{{config.startRecordingMessage}}</span>\n" +
+ " </div> \n" +
+ " <div class=\"b2b-controls\" title=\"{{isRecording ? 'Stop' : 'REC'}}\" b2b-accessibility-click=\"13,32\" ng-click=\"toggleRecording()\" role=\"button\">\n" +
+ " <i ng-if=\"isRecording\" class=\"icoControls-stop\" ></i>\n" +
+ " <i ng-if=\"!isRecording\" class=\"icoControls-record\"></i>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/backToTop/backToTop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/backToTop/backToTop.html",
+ "<button class=\"btn-arrow b2b-backtotop-button\" type=\"button\" aria-label=\"Back to top\">\n" +
+ " <div class=\"btn-secondary b2b-top-btn\">\n" +
+ " <i class=\"icoControls-upPRIMARY\" role=\"img\"></i>\n" +
+ " </div>\n" +
+ "</button>\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/boardstrip/b2bAddBoard.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/boardstrip/b2bAddBoard.html",
+ "<div tabindex=\"0\" role=\"menuitem\" b2b-accessibility-click=\"13,32\" ng-click=\"addBoard()\" aria-label=\"Add Board\" class=\"boardstrip-item--add\">\n" +
+ " <div class=\"centered\"><i aria-hidden=\"true\" class=\"icoControls-add-maximize\"></i> Add board</div>\n" +
+ "</div> ");
+}]);
+
+angular.module("b2bTemplate/boardstrip/b2bBoard.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/boardstrip/b2bBoard.html",
+ "<li b2b-board-navigation tabindex=\"-1\" role=\"menuitem\" aria-label=\"{{boardLabel}} {{getCurrentIndex()===boardIndex?'selected':''}}\" b2b-accessibility-click=\"13,32\" ng-click=\"selectBoard(boardIndex)\" class=\"board-item\" ng-class=\"{'selected': getCurrentIndex()===boardIndex}\">\n" +
+ " <div ng-transclude></div>\n" +
+ " <div class=\"board-caret\" ng-if=\"getCurrentIndex()===boardIndex\">\n" +
+ " <div class=\"board-caret-indicator\"></div>\n" +
+ " <div class=\"board-caret-arrow-up\"></div>\n" +
+ " </div>\n" +
+ "</li>");
+}]);
+
+angular.module("b2bTemplate/boardstrip/b2bBoardstrip.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/boardstrip/b2bBoardstrip.html",
+ "<div class=\"b2b-boardstrip\">\n" +
+ " <div class=\"boardstrip-reel\" role=\"menu\">\n" +
+ " <div class=\"prev-items\">\n" +
+ " <!-- <i tabindex=\"{{isPrevBoard() ? 0 : -1}}\" ng-class=\"{'disabled': !isPrevBoard()}\" role=\"menuitem\" aria-label=\"See previous boards\" b2b-accessibility-click=\"13,32\" ng-click=\"prevBoard()\" class=\"arrow icoControls-left\"></i> -->\n" +
+ " <button class=\"btn-arrow arrow\" b2b-accessibility-click=\"13,32\" ng-click=\"prevBoard()\" ng-disabled=\"!isPrevBoard()\">\n" +
+ " <div class=\"btn btn-small btn-alt\"><i class=\"icon-primary-left\"></i>\n" +
+ " </div>\n" +
+ " <span class=\"offscreen-text\">Previous boards</span>\n" +
+ " </button>\n" +
+ " </div>\n" +
+ " <div b2b-add-board on-add-board=\"onAddBoard()\"></div>\n" +
+ " <div class=\"board-viewport\"><ul role=\"menu\" class=\"boardstrip-container\" ng-transclude></ul></div>\n" +
+ " <div class=\"next-items\">\n" +
+ " <!-- <i tabindex=\"{{isNextBoard() ? 0 : -1}}\" ng-class=\"{'disabled': !isNextBoard()}\" role=\"menuitem\" aria-label=\"See next boards\" b2b-accessibility-click=\"13,32\" ng-click=\"nextBoard()\" class=\"arrow icoControls-right\"></i> -->\n" +
+ " <button class=\"btn-arrow arrow\" b2b-accessibility-click=\"13,32\" ng-click=\"nextBoard()\" ng-disabled=\"!isNextBoard()\">\n" +
+ " <div class=\"btn btn-small btn-alt\"><i class=\"icon-primary-right\"></i>\n" +
+ " </div>\n" +
+ " <span class=\"offscreen-text\">Next boards</span>\n" +
+ " </button>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/calendar/datepicker-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/calendar/datepicker-popup.html",
+ "<div id=\"datepicker\" class=\"datepicker dropdown-menu\" ng-class=\"{'datepicker-dropdown datepicker-orient-top': !inline, 'datepicker-orient-left': !inline && orientation === 'left', 'datepicker-orient-right': !inline && orientation === 'right'}\" ng-style=\"{position: inline && 'relative', 'z-index': inline && '0', top: !inline && position.top + 'px' || 0, left: !inline && position.left + 'px'}\" style=\"display: block;\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\" b2b-key type=\"table\" columns=\"7\">\n" +
+ " <div class=\"datepicker-days\" style=\"display: block;\">\n" +
+ " <div ng-repeat=\"header in headers\" class=\"text-left\" style=\"width: 100%;\" b2b-append-element=\"header\"></div>\n" +
+ " <table class=\"table-condensed\">\n" +
+ " <thead>\n" +
+ " <tr>\n" +
+ " <th id=\"prev\" class=\"prev\" tabindex=\"0\" b2b-accessibility-click=\"13\" aria-label=\"Previous Month\" role=\"button\" b2b-element-focus=\"!disablePrev && getFocus\" ng-style=\"{visibility: visibilityPrev}\" ng-click=\"!disablePrev && move(-1,$event)\"><i class=\"icon-primary-left\" aria-hidden=\"true\"></i></th>\n" +
+ " <th id=\"month\" tabindex=\"-1\" aria-label=\"{{title}}\" class=\"datepicker-switch\" colspan=\"{{rows[0].length - 2}}\">{{title}}</th>\n" +
+ " <th id=\"next\" class=\"next\" tabindex=\"0\" b2b-accessibility-click=\"13\" b2b-element-focus=\"disablePrev && getFocus\" aria-label=\"Next Month\" role=\"button\" ng-style=\"{visibility: visibilityNext}\" ng-click=\"!disableNext && move(1,$event)\"><i class=\"icon-primary-right\" aria-hidden=\"true\"></i></th>\n" +
+ " </tr>\n" +
+ " <tr ng-show=\"labels.length > 0\">\n" +
+ " <th id=\"{{label.post}}\" class=\"dow\" ng-repeat=\"label in labels\" aria-hidden=\"true\"><span aria-hidden=\"true\">{{label.pre}}</span></th>\n" +
+ " </tr>\n" +
+ " </thead>\n" +
+ " <tbody>\n" +
+ " <tr ng-repeat=\"row in rows\">\n" +
+ " <td headers=\"{{dt.header}}\" b2b-key-item=\"dt.focusable\" b2b-accessibility-click=\"13\" b2b-element-focus=\"disablePrev && disableNext && getFocus && (dt.selected || dt.firstFocus || dt.fromDate || dt.dateRange)\" tabindex=\"{{(!(dt.focusable && (dt.selected || dt.firstFocus || dt.fromDate || currFocus)) && -1) || 0}}\" aria-hidden=\"{{(!dt.focusable && true) || false}}\" role=\"{{(dt.focusable && 'gridcell') || ''}}\" aria-label=\"{{(dt.focusable && dt.date | date : 'EEEE, MMMM d') || ''}}\" aria-selected=\"{{(dt.focusable && (dt.selected || dt.dateRange) && true) || false}}\" ng-repeat=\"dt in row\" class=\"day magic\" ng-class=\"{'active': dt.focusable && dt.selected && !dt.dateRange, 'start-date': dt.focusable && dt.fromDate && dt.dateRange, 'between-date': dt.focusable && !dt.fromDate && !dt.selected && dt.dateRange, 'end-date': dt.focusable && dt.selected && dt.dateRange, 'old': dt.oldMonth, 'new': dt.nextMonth, 'disabled': dt.disabled, 'due-date': dt.dueDate, 'late-fee': dt.pastDue}\" ng-focus=\"currFocus=true; trapFocus();\" ng-blur=\"currFocus=false; trapFocus();\" title=\"{{(dt.focusable && dt.pastDue && legendMessage) || ''}}\" ng-click=\"!ngDisabled && !dt.disabled && select(dt.date)\">\n" +
+ " <div aria-hidden=\"true\" tabindex=\"-1\" class=\"show-date\" ng-if=\"!(dt.oldMonth || dt.nextMonth)\">{{dt.label}}</div>{{(dt.focusable && dt.date | date : 'EEEE, MMMM d yyyy') || ''}}{{(dt.focusable && dt.dueDate && '. Bill-due-date.. ') || ''}}{{(dt.focusable && dt.pastDue && legendMessage) || ''}}</td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ " <tfoot>\n" +
+ " <tr ng-repeat=\"footer in footers\">\n" +
+ " <th colspan=\"7\" class=\"text-left\" style=\"width: 278px;\" b2b-append-element=\"footer\"></th>\n" +
+ " </tr>\n" +
+ " </tfoot>\n" +
+ " </table>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/calendar/datepicker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/calendar/datepicker.html",
+ "<div>\n" +
+ " <span class=\"icon-primary-calendar span12\" ng-class=\"{'disabled': ngDisabled}\" ng-transclude></span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/coachmark/coachmark.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/coachmark/coachmark.html",
+ "<div class=\"b2b-coachmark-container\" tabindex=\"-1\" role=\"dialog\" aria-label=\"{{currentCoachmark.contentHeader}} {{currentCoachmark.content}} {{currentCoachmark.offscreenText}}\" ng-style=\"{'top':coackmarkElPos.top,'left':coackmarkElPos.left}\" aria-describeby=\"{{currentCoachmark}}\">\n" +
+ " <i class=\"b2b-coachmark-caret\"></i>\n" +
+ " <div class=\"b2b-coachmark-header\">\n" +
+ " <div class=\"b2b-coachmark-countlabel\"><span ng-if=\"coachmarkIndex !== 0\">{{coachmarkIndex}} of {{(coachmarks.length-1)}}<span></div>\n" +
+ " <div class=\"corner-button\">\n" +
+ " <button type=\"button\" ng-focus=\"closeButtonFocus()\" class=\"close\" title=\"close\" aria-label=\"Close\" ng-click=\"closeCoachmark()\"></button>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-coachmark-content\"> \n" +
+ " <i class=\"icon-misc-dimmer\"></i>\n" +
+ " <div class=\"b2b-coachmark-content-header\"><span class=\"offscreen-text\">{{currentCoachmark.offscreenText}}</span>{{currentCoachmark.contentHeader}}</div>\n" +
+ " <div class=\"b2b-coachmark-description\">{{currentCoachmark.content}}</div>\n" +
+ " <div class=\"b2b-coachmark-btn-group\">\n" +
+ " <a class=\"b2b-coachmark-link\" href=\"javascript:void(0)\" ng-if=\"currentCoachmark.linkLabel !== '' && currentCoachmark.linkLabel !== undefined\" ng-click=\"actionCoachmark(currentCoachmark.linkLabel)\">{{currentCoachmark.linkLabel}}</a>\n" +
+ " <button class=\"btn btn-alt\" ng-if=\"currentCoachmark.buttonLabel !== '' && currentCoachmark.buttonLabel !== undefined\" ng-click=\"actionCoachmark(currentCoachmark.buttonLabel)\">{{currentCoachmark.buttonLabel}}</button>\n" +
+ " </div> \n" +
+ " </div> \n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/dropdowns/b2bDropdownDesktop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/dropdowns/b2bDropdownDesktop.html",
+ "<span b2b-key prev=\"38\" next=\"40\" enable-search ng-class=\"{'large': (dropdownSize === 'large'), 'disabled': (disabled), 'selectWrap': (isInputDropdown), 'selectorModule': (dropdownType === 'menu'), 'linkSelectorModule': (dropdownType === 'link-menu')}\">\n" +
+ " <input b2b-dropdown-toggle b2b-dropdown-validation ng-disabled=\"disabled\" type=\"text\" id=\"{{dropdownId}}\" name=\"{{dropdownName}}\" class=\"awd-select isWrapped\" ng-required=\"dropdownRequired\" ng-model=\"currentSelected.text\" role=\"combobox\" aria-owns=\"listbox{{$id}}\" aria-expanded=\"{{toggleFlag}}\" ng-click=\"toggleDropdown()\" ng-focus=\"focused=true\" ng-blur=\"setBlur(); focused=false\" ng-class=\"{'active': toggleFlag, 'closed': !toggleFlag, 'large': (dropdownSize === 'large'), 'focused':focused}\" style=\"width:100%;\" value=\"{{currentSelected.text}}\" ng-show=\"isInputDropdown\" aria-describedby=\"{{dropdownDescribedBy}}\" readonly=\"readonly\">\n" +
+ " <button type=\"button\" b2b-dropdown-toggle ng-disabled=\"disabled\" class=\"selectModule\" aria-label=\"{{labelText}} {{currentSelected.label}}\" aria-expanded=\"{{toggleFlag}}\" aria-haspopup=\"true\" ng-click=\"toggleDropdown()\" ng-blur=\"setBlur()\" ng-class=\"{'active opened': toggleFlag, 'closed': !toggleFlag, 'large': (dropdownSize === 'large')}\" ng-bind-html=\"currentSelected.text\" ng-show=\"!isInputDropdown\"></button>\n" +
+ " <div ng-class=\"{'selectWrapper': (isInputDropdown), 'moduleWrapper': (!isInputDropdown)}\">\n" +
+ " <ul id=\"listbox{{$id}}\" role=\"{{isInputDropdown?'listbox':'menu'}}\" ng-class=\"{'awd-select-list': (isInputDropdown), 'awd-module-list': (!isInputDropdown)}\" tabindex=\"-1\" ng-show=\"toggleFlag\" aria-label=\"Choose options\"></ul>\n" +
+ " <ul class=\"module-optinalcta\" ng-if=\"toggleFlag && optionalCta\" tabindex=\"-1\" aria-hidden=\"false\">\n" +
+ " <li class=\"module-list-item\" tabindex=\"-1\" role=\"menuitem\" value=\"\" aria-label=\"Optinal CTA\" aria-selected=\"true\">\n" +
+ " <span class=\"module-data\" b2b-append-element=\"optionalCta\"></span>\n" +
+ " </li>\n" +
+ " </ul>\n" +
+ "</div>\n" +
+ "<i class=\"icon-primary-down\" aria-hidden=\"true\"></i>\n" +
+ "</span> ");
+}]);
+
+angular.module("b2bTemplate/dropdowns/b2bDropdownGroupDesktop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/dropdowns/b2bDropdownGroupDesktop.html",
+ "<li b2b-dropdown-group-desktop class=\"optgroup-wrapper\">{{groupHeader}}\n" +
+ " <ul class=\"optgroup\" role=\"group\" aria-label=\"{{groupHeader}}\"></ul>\n" +
+ "</li>");
+}]);
+
+angular.module("b2bTemplate/dropdowns/b2bDropdownListDesktop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/dropdowns/b2bDropdownListDesktop.html",
+ "<li b2b-dropdown-list-desktop b2b-key-item b2b-accessibility-click=\"13\" aria-selected=\"{{currentSelected.value === dropdownListValue}}\" ng-class=\"{'awd-select-list-item': (isInputDropdown), 'module-list-item': (!isInputDropdown)}\" tabindex=\"0\" role=\"{{isInputDropdown?'option':'menuitem'}}\" ng-click=\"selectDropdownItem()\"></li>");
+}]);
+
+angular.module("b2bTemplate/fileUpload/fileUpload.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/fileUpload/fileUpload.html",
+ "<label class=\"b2b-file-container\">\n" +
+ " <span class=\"b2b-upload-link\" ng-transclude></span>\n" +
+ " <input type=\"file\" b2b-file-change>\n" +
+ "</label>");
+}]);
+
+angular.module("b2bTemplate/flyout/flyout.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/flyout/flyout.html",
+ "<span class=\"b2b-flyout\" b2b-flyout-trap-focus-inside>\n" +
+ " <span ng-transclude></span>\n" +
+ "</span>");
+}]);
+
+angular.module("b2bTemplate/flyout/flyoutContent.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/flyout/flyoutContent.html",
+ "<div class=\"b2b-flyout-container\" aria-live=\"polite\" aria-atomic=\"false\" ng-class=\"{'b2b-flyout-left':horizontalPlacement==='left',\n" +
+ " 'b2b-flyout-center':horizontalPlacement==='center', \n" +
+ " 'b2b-flyout-right':horizontalPlacement==='right',\n" +
+ " 'b2b-flyout-centerLeft':horizontalPlacement==='centerLeft',\n" +
+ " 'b2b-flyout-centerRight':horizontalPlacement==='centerRight', \n" +
+ " 'b2b-flyout-above':verticalPlacement==='above', \n" +
+ " 'b2b-flyout-below':verticalPlacement==='below',\n" +
+ " 'open-flyout': openFlyout,\n" +
+ " 'b2b-close-flyout': !openFlyout}\">\n" +
+ " <i class=\"b2b-flyout-caret\" ng-class=\"{'open-flyout': openFlyout, \n" +
+ " 'b2b-flyout-caret-above':verticalPlacement==='above',\n" +
+ " 'b2b-flyout-caret-below':verticalPlacement==='below'}\"></i>\n" +
+ " <span ng-transclude></span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/footer/footer_column_switch_tpl.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/footer/footer_column_switch_tpl.html",
+ "<div class=\"footer-columns \" ng-class=\"{'five-column':footerColumns===5, 'four-column':footerColumns===4, 'three-column':footerColumns===3}\" ng-repeat=\"item in footerLinkItems\">\n" +
+ " <h3 class=\"b2b-footer-header\">{{item.categoryName}}</h3>\n" +
+ " <ul>\n" +
+ " <li ng-repeat=\"i in item.values\">\n" +
+ " <a href=\"{{i.href}}\" title=\"{{item.categoryName}} - {{i.displayLink}}\">{{i.displayLink}}</a> \n" +
+ " </li>\n" +
+ " </ul>\n" +
+ "\n" +
+ "</div>\n" +
+ "\n" +
+ "<div ng-transclude></div>\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/horizontalTable/horizontalTable.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/horizontalTable/horizontalTable.html",
+ "<div class=\"b2b-horizontal-table\">\n" +
+ " <div class=\"b2b-horizontal-table-arrows row span12\">\n" +
+ " <div class=\"span4\">\n" +
+ " <button class=\"btn-arrow left\" type=\"button\" ng-click=\"moveViewportLeft()\" ddh-accessibility-click=\"13,32\" ng-disabled=\"disableLeft\"><div class=\"btn btn-alt\"><i class=\"icon-primary-left\"></i></div>Previous Set</button>\n" +
+ " </div>\n" +
+ " \n" +
+ " <span class=\"span5 b2b-horizontal-table-column-info\" aria-live=\"polite\" tabindex=\"-1\">\n" +
+ " Displaying {{getColumnSet()[0]}} - {{getColumnSet()[1]}} of {{numOfCols}} (total) columns\n" +
+ " </span>\n" +
+ " \n" +
+ " <div class=\"span3\">\n" +
+ " <button class=\"btn-arrow right\" ng-click=\"moveViewportRight()\" ddh-accessibility-click=\"13,32\" ng-disabled=\"disableRight\" type=\"button\">Next Set<div class=\"btn btn-alt\"><i class=\"icon-primary-right\"></i></div></button>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-horizontal-table-inner-container\">\n" +
+ " <span ng-transclude></span>\n" +
+ " </div>\n" +
+ "</div>\n" +
+ "\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/hourPicker/b2bHourpicker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/hourPicker/b2bHourpicker.html",
+ "<div class=\"hp-container\">\n" +
+ " <div class=\"hp-selected\">\n" +
+ " <div b2b-hourpicker-value=\"$index\" days=\"value.days\" start-time=\"value.startTime\" start-meridiem=\"value.startMeridiem\" end-time=\"value.endTime\" end-meridiem=\"value.endMeridiem\" ng-repeat=\"value in finalHourpickerValues\"></div>\n" +
+ " </div>\n" +
+ " <div b2b-hourpicker-panel></div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/hourPicker/b2bHourpickerPanel.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/hourPicker/b2bHourpickerPanel.html",
+ "<form name=\"{{'hourpickerForm' + $id}}\">\n" +
+ " <div class=\"hp-checkbox\" role=\"group\">\n" +
+ " <label class=\"checkbox\" for=\"checkbox_{{dayOption.title}}_{{$id}}\" aria-label=\"{{dayOption.title}}\" ng-repeat=\"dayOption in hourpicker.dayOptions\">\n" +
+ " <input type=\"checkbox\" id=\"checkbox_{{dayOption.title}}_{{$id}}\" name=\"{{'hourpickerDays' + $id}}\" ng-model=\"hourpickerPanelValue.days[$index].value\" ng-disabled=\"dayOption.disabled\" /><i class=\"skin\"></i><span>{{dayOption.label}}</span>\n" +
+ " </label>\n" +
+ " </div>\n" +
+ " <div class=\"row hp-dropdowns\">\n" +
+ " <div class=\"span4\">\n" +
+ " <label for=\"{{'hourpickerStartTime' + $id}}\">From</label>\n" +
+ " <select id=\"{{'hourpickerStartTime' + $parent.$id}}\" b2b-dropdown type=\"\" ng-model=\"hourpickerPanelValue.startTime\">\n" +
+ " <option b2b-dropdown-list value=\"\">From</option>\n" +
+ " <option b2b-dropdown-list option-repeat=\"startTimeOption in hourpicker.startTimeOptions\" value=\"{{startTimeOption}}\">{{startTimeOption}}</option>\n" +
+ " </select>\n" +
+ " </div>\n" +
+ " <div class=\"span8 radio-buttons\" role=\"radiogroup\" aria-label=\"Select AM or PM\">\n" +
+ " <label class=\"radio\" for=\"hourpickerStartMeridiem_AM_{{$id}}\">\n" +
+ " <input type=\"radio\" id=\"hourpickerStartMeridiem_AM_{{$id}}\" name=\"{{'hourpickerStartMeridiem' + $id}}\" value=\"am\" ng-model=\"hourpickerPanelValue.startMeridiem\" /><i class=\"skin\"></i><span>AM</span>\n" +
+ " </label>\n" +
+ " <label class=\"radio\" for=\"hourpickerStartMeridiem_PM_{{$id}}\">\n" +
+ " <input type=\"radio\" id=\"hourpickerStartMeridiem_PM_{{$id}}\" name=\"{{'hourpickerStartMeridiem' + $id}}\" value=\"pm\" ng-model=\"hourpickerPanelValue.startMeridiem\" /><i class=\"skin\"></i><span>PM</span>\n" +
+ " </label>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"row hp-dropdowns\">\n" +
+ " <div class=\"span4\">\n" +
+ " <label for=\"{{'hourpickerEndTime' + $id}}\">To</label>\n" +
+ " <select id=\"{{'hourpickerEndTime' + $parent.$id}}\" b2b-dropdown ng-model=\"hourpickerPanelValue.endTime\">\n" +
+ " <option b2b-dropdown-list value=\"\">To</option>\n" +
+ " <option b2b-dropdown-list option-repeat=\"endTimeOption in hourpicker.endTimeOptions\" value=\"{{endTimeOption}}\">{{endTimeOption}}</option>\n" +
+ " </select>\n" +
+ " </div>\n" +
+ " <div class=\"span8 radio-buttons\" role=\"radiogroup\" aria-label=\"Select AM or PM\">\n" +
+ " <label class=\"radio\" for=\"hourpickerEndMeridiem_AM_{{$id}}\">\n" +
+ " <input type=\"radio\" id=\"hourpickerEndMeridiem_AM_{{$id}}\" name=\"{{'hourpickerEndMeridiem' + $id}}\" value=\"am\" ng-model=\"hourpickerPanelValue.endMeridiem\" /><i class=\"skin\"></i><span>AM</span>\n" +
+ " </label>\n" +
+ " <label class=\"radio\" for=\"hourpickerEndMeridiem_PM_{{$id}}\">\n" +
+ " <input type=\"radio\" id=\"hourpickerEndMeridiem_PM_{{$id}}\" name=\"{{'hourpickerEndMeridiem' + $id}}\" value=\"pm\" ng-model=\"hourpickerPanelValue.endMeridiem\" /><i class=\"skin\"></i><span>PM</span>\n" +
+ " </label>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"row hp-buttons\">\n" +
+ " <div class=\"span12\">\n" +
+ " <div style=\"float:right\">\n" +
+ " <button class=\"btn btn-secondary btn-small\" ng-click=\"resetHourpickerPanelValue()\">Clear</button>\n" +
+ " <button class=\"btn btn-alt btn-small\" ng-disabled = \"disableAddBtn\" ng-click=\"updateHourpickerValue()\">{{hourpicker.editMode > -1 ? 'Update' : 'Add'}}</button>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ "</form>");
+}]);
+
+angular.module("b2bTemplate/hourPicker/b2bHourpickerValue.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/hourPicker/b2bHourpickerValue.html",
+ "<div class=\"selected-days\">\n" +
+ " <span class=\"day\">{{hourpickerValue.days}} &nbsp; {{hourpickerValue.startTime}} {{hourpickerValue.startMeridiem}} - {{hourpickerValue.endTime}} {{hourpickerValue.endMeridiem}}</span>\n" +
+ " <span style=\"float:right\">\n" +
+ " <i class=\"icon-misc-pen\" role=\"button\" title=\"Edit {{hourpickerValue.days}} &nbsp; {{hourpickerValue.startTime}} {{hourpickerValue.startMeridiem}} - {{hourpickerValue.endTime}} {{hourpickerValue.endMeridiem}}\" tabindex=\"0\" b2b-accessibility-click=\"13,32\" ng-click=\"editHourpickerValue(hourpickerValue.index)\"></i>\n" +
+ " <i class=\"icon-misc-trash\" role=\"button\" title=\"Delete {{hourpickerValue.days}} &nbsp; {{hourpickerValue.startTime}} {{hourpickerValue.startMeridiem}} - {{hourpickerValue.endTime}} {{hourpickerValue.endMeridiem}}\" tabindex=\"0\" b2b-accessibility-click=\"13,32\" ng-click=\"deleteHourpickerValue(hourpickerValue.index)\"></i>\n" +
+ " </span>\n" +
+ " <div style=\"clear:both\"></div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/leftNavigation/leftNavigation.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/leftNavigation/leftNavigation.html",
+ "<div class=\"b2b-nav-menu\" ng-init=\"(showmenu = true)\" ng-class=\"{false: 'left-menu-collapsed'}[showmenu]\">\n" +
+ " <div class=\"b2b-subnav-container\">\n" +
+ " <ul class=\"b2b-subnav-content\">\n" +
+ " <li>" +
+ " <div ng-class=\"{true: 'leftmenu-arrow-expand', false: 'leftmenu-arrow-collapse'}[showmenu]\">"+
+ " <a ng-click=\"toggleDrawer(showmenu);(showmenu = !showmenu) \" class=\"text-right\">" +
+ " <i ng-class=\"{true: 'icon-controls-left', false: 'icon-controls-right'}[showmenu]\">&nbsp;</i></a>" +
+ " </div>"+
+ " </li>" +
+ " <li ng-repeat=\"menu in menuData\" ng-click=\"!showmenu||toggleNav($index,menu.href)\">" +
+ " <span ng-class=\"{true: 'menu-icon', false: 'menu-icon-collapse'}[showmenu]\"><span class=\"{{menu.imageSrc}}\"></span>&nbsp;&nbsp;</span>" +
+ " <a ng-class=\"{expand: isOpen($index)}\" ng-if=\"showmenu\" aria-label=\"{{menu.name}}\" title=\" \" aria-expanded=\"{{(idx==$index)?true:false;}}\" href=\"javascript:void(0);\">" +
+ " {{menu.name}}" +
+ " <i aria-hidden=\"true\" ng-if=\"(menu.menuItems.length > 0)\" class=\"b2b-icon-primary-plus-minus\"ng-class=\"idx==$index ? 'icon-primary-expanded' : 'icon-primary-collapsed'\"></i>" +
+ " </a>\n" +
+ " <div role=\"region\" aria-hidden=\"{{(isOpen($index))?false:true;}}\">\n" +
+ " <ul ng-class=\"{expand: idx==$index}\">\n" +
+ " <li ng-repeat=\"menuItem in menu.menuItems\" ng-click=\"liveLink($event, $index, $parent.$index)\"><a aria-hidden=\"{{!(idx==$parent.$index)}}\" aria-label=\"{{menuItem.name}}\" title=\" \" href=\"{{menuItem.href}}\" tabindex=\"{{(idx==$parent.$index)?0:-1;}}\" ng-class=\"{active: itemIdx==$index && navIdx==$parent.$index}\">{{menuItem.name}}</a></li>\n" +
+ " </ul>\n" +
+ " </div>\n" +
+ " </li>\n" +
+ " </ul>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/listbox/listbox.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/listbox/listbox.html",
+ "<div class=\"b2b-list-box\" tabindex=\"0\" role=\"listbox\" ng-transclude>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/modalsAndAlerts/b2b-backdrop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/modalsAndAlerts/b2b-backdrop.html",
+ "<div class=\"b2b-modal-backdrop fade in hidden-by-modal\" aria-hidden=\"true\" tabindex=\"-1\"></div>");
+}]);
+
+angular.module("b2bTemplate/modalsAndAlerts/b2b-window.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/modalsAndAlerts/b2b-window.html",
+ "<div class=\"modalwrapper active {{windowClass}}\" ng-class=\"{'modal-landscape': isModalLandscape}\" role=\"{{isNotifDialog?'alertdialog':'dialog'}}\" tabindex=\"-1\" aria-labelledby=\"{{title}}\" aria-describedby=\"{{content}}\">\n" +
+ " <div class=\"modal fade in {{sizeClass}}\" ng-transclude></div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/monthSelector/monthSelector-popup.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/monthSelector/monthSelector-popup.html",
+ "<div id=\"monthselector{{$id}}\" class=\"datepicker dropdown-menu monthselector\" \n" +
+ " ng-class=\"{'datepicker-dropdown datepicker-orient-top': !inline, 'datepicker-orient-left': !inline && orientation === 'left', 'datepicker-orient-right': !inline && orientation === 'right'}\" \n" +
+ " ng-style=\"{position: inline && 'relative', 'z-index': inline && '0', top: !inline && position.top + 'px' || 0, left: !inline && position.left + 'px'}\" \n" +
+ " style=\"display: block;\" aria-hidden=\"false\" role=\"dialog presentation\" tabindex=\"-1\">\n" +
+ " <div class=\"datepicker-days\" style=\"display: block;\">\n" +
+ " <span class=\"offscreen-text\" aria-live=\"polite\" aria-atomic=\"true\">{{title}} displaying</span>\n" +
+ " <table class=\"table-condensed\" role=\"grid\">\n" +
+ " <thead>\n" +
+ " <tr ng-repeat=\"header in headers\">\n" +
+ " <th colspan=\"7\" class=\"text-left\" style=\"width: 278px;\" b2b-append-element=\"header\"></th>\n" +
+ " </tr>\n" +
+ " <tr>\n" +
+ " <th id=\"prev{{$id}}\" role=\"button\" tabindex=\"0\" b2b-accessibility-click=\"13\" aria-label=\"Previous Year\" ng-class=\"{'prev': !disablePrev}\" ng-style=\"{visibility: visibilityPrev}\" ng-click=\"!disablePrev && move(-1,$event)\"><i class=\"icon-primary-left\"></i></th>\n" +
+ " <th id=\"year{{$id}}\" role=\"heading\" tabindex=\"-1\" aria-label=\"{{title}}\" class=\"datepicker-switch b2b-monthSelector-label\" colspan=\"{{rows[0].length - 2}}\">{{title}}</th>\n" +
+ " <th id=\"next{{$id}}\" role=\"button\" tabindex=\"0\" b2b-accessibility-click=\"13\" aria-label=\"Next Year\" ng-class=\"{'next': !disableNext}\" ng-style=\"{visibility: visibilityNext}\" ng-click=\"!disableNext && move(1,$event)\"><i class=\"icon-primary-right\"></i></th>\n" +
+ " </tr>\n" +
+ " <tr ng-show=\"labels.length > 0\">\n" +
+ " <th id=\"{{label.post}}\" class=\"dow\" ng-repeat=\"label in labels\" aria-hidden=\"true\"><span aria-hidden=\"true\">{{label.pre}}</span></th>\n" +
+ " </tr>\n" +
+ " </thead>\n" +
+ " <tbody b2b-key type=\"table\" columns=\"4\" >\n" +
+ " <tr ng-repeat=\"row in rows\">\n" +
+ " <td headers=\"{{dt.header}}\" b2b-key-item=\"dt.focusable\" b2b-accessibility-click=\"13,32\" tabindex=\"{{(!(dt.focusable && (dt.selected || dt.firstFocus || currFocus)) && -1) || 0}}\" aria-hidden=\"{{(!dt.focusable && true) || false}}\" role=\"{{(dt.focusable && 'gridcell') || ''}}\" aria-label=\"{{(dt.focusable && dt.date | date : 'MMMM, y') || ''}}\" aria-selected=\"{{(dt.focusable && (dt.selected || dt.dateRange) && true) || false}}\" ng-repeat=\"dt in row\" class=\"day magic\" ng-class=\"{'active': dt.focusable && dt.selected && !dt.dateRange, 'start-date': dt.focusable && dt.fromDate && dt.dateRange, 'between-date': dt.focusable && !dt.fromDate && !dt.selected && dt.dateRange, 'end-date': dt.focusable && dt.selected && dt.dateRange, 'old': dt.oldMonth, 'new': dt.nextMonth, 'disabled': dt.disabled, 'due-date': dt.dueDate, 'late-fee': dt.pastDue}\" ng-focus=\"currFocus=true\" ng-blur=\"currFocus=false\" title=\"{{(dt.focusable && dt.pastDue && legendMessage) || ''}}\" b2b-element-focus=\"inline && dt.focusable && dt.selected && !dt.dateRange\" ng-click=\"!ngDisabled && !dt.disabled && select(dt.date)\">\n" +
+ " <div aria-hidden=\"true\" tabindex=\"-1\" class=\"show-date\" ng-if=\"!(dt.oldMonth || dt.nextMonth)\">{{dt.label | limitTo: 3}}</div>\n" +
+ " </td>\n" +
+ " </tr>\n" +
+ " </tbody>\n" +
+ " <tfoot>\n" +
+ " <tr ng-repeat=\"footer in footers\">\n" +
+ " <th colspan=\"7\" class=\"text-left\" b2b-append-element=\"footer\"></th>\n" +
+ " </tr>\n" +
+ " </tfoot>\n" +
+ " </table>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/monthSelector/monthSelector.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/monthSelector/monthSelector.html",
+ "<div>\n" +
+ " <span class=\"icon-primary-calendar span12\" ng-class=\"{'disabled': ngDisabled}\" ng-transclude></span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/monthSelector/monthSelectorLink.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/monthSelector/monthSelectorLink.html",
+ "<div>\n" +
+ " <span class=\"span12\" ng-transclude></span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/pagination/b2b-pagination.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/pagination/b2b-pagination.html",
+ "<div class=\"b2b-pager\">\n" +
+ " <div ng-if=\"notMobile && totalPages > 1\">\n" +
+ " <a tabindex=\"{{currentPage <= 1 ? -1 : 0 }}\" class=\"b2b-pager__item--prev\" b2b-accessibility-click=\"13,32\" title=\"Previous Page\" ng-click=\"prev($event)\" ng-if=\"totalPages > 10\" ng-class=\"currentPage <= 1 ? 'b2b-pager__item--prev-disabled': '' \">\n" +
+ " <i class=\"icon-primary-left\"></i>\n" +
+ " </a>\n" +
+ " <a tabindex=\"{{currentPage === 1 ? -1 : 0}}\" ng-class=\"{'b2b-pager__item--noclick': currentPage === 1}\" aria-selected=\"{{checkSelectedPage(page)}}\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page 1{{checkSelectedPage(page) ? ' selected' : '' }}\" ng-if=\"totalPages > 10 && currentPage > 6\" b2b-accessibility-click=\"13,32\" ng-click=\"selectPage(1, $event)\">\n" +
+ " 1<span class=\"offscreen-text\" ng-if=\"currentPage === 1\"> is selected</span>\n" +
+ " </a>\n" +
+ " <a tabindex=\"{{currentPage === 2 ? -1 : 0}}\" aria-selected=\"{{checkSelectedPage(page)}}\" ng-class=\"{'b2b-pager__item--noclick': currentPage === 2}\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page 2{{checkSelectedPage(page) ? ' selected' : '' }}\" ng-if=\"totalPages > 10 && currentPage > 6\" b2b-accessibility-click=\"13,32\" ng-click=\"selectPage(2, $event)\">2<span class=\"offscreen-text\" ng-if=\"currentPage === 2\"> is selected</span></a>\n" +
+ "\n" +
+ " <span class=\"b2b-pager__item\" ng-if=\"totalPages > 10 && currentPage > 6\">...</span>\n" +
+ "\n" +
+ " <a tabindex=\"{{checkSelectedPage(page) ? -1 : 0}}\" href=\"javascript:void(0)\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page {{page}}\" b2b-element-focus=\"isFocused(page)\" ng-repeat=\"page in pages\" ng-class=\"{'b2b-pager__item--active': checkSelectedPage(page), 'b2b-pager__item--noclick': checkSelectedPage(page)}\" b2b-accessibility-click=\"13,32\" ng-click=\"!checkSelectedPage(page) && selectPage(page, $event)\">{{page}}<span class=\"offscreen-text\" ng-if=\"currentPage === page\"> is selected</span></a>\n" +
+ "\n" +
+ " <span class=\"b2b-pager__item\" ng-if=\"totalPages > 10 && currentPage <= totalPages - 5\">...</span>\n" +
+ "\n" +
+ " <a tabindex=\"{{checkSelectedPage(page) ? -1 : 0}}\" href=\"javascript:void(0)\" ng-class=\"{'b2b-pager__item--noclick': checkSelectedPage(page)}\" aria-selected=\"{{checkSelectedPage(page)}}\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page {{totalPages-1}}\" ng-if=\"totalPages > 10 && currentPage <= totalPages - 5\" b2b-accessibility-click=\"13,32\" ng-click=\"selectPage(totalPages-1, $event)\">{{totalPages-1}}<span class=\"offscreen-text\" ng-if=\"currentPage === totalPages-1\"> is selected</span></a>\n" +
+ "\n" +
+ " <a tabindex=\"{{currentPage === totalPages ? -1 : 0}}\" href=\"javascript:void(0)\" ng-class=\"{'b2b-pager__item--noclick': currentPage === totalPages}\" aria-selected=\"{{checkSelectedPage(page)}}\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page {{totalPages}}\" ng-if=\"totalPages > 10 && currentPage <= totalPages - 5\" b2b-accessibility-click=\"13,32\" ng-click=\"selectPage(totalPages, $event)\">{{totalPages}}<span class=\"offscreen-text\" ng-if=\"currentPage === totalPages\"> is selected</span></a>\n" +
+ "\n" +
+ " <a tabindex=\"{{currentPage >= totalPages ? -1 : 0 }}\" href=\"javascript:void(0)\" class=\"b2b-pager__item--next\" b2b-accessibility-click=\"13,32\" title=\"Next Page\" ng-click=\"next($event)\" ng-if=\"totalPages > 10\" ng-class=\"currentPage >= totalPages ? 'b2b-pager__item--next-disabled' :'' \">\n" +
+ " <i class=\"icon-primary-right\"></i>\n" +
+ " </a>\n" +
+ " \n" +
+ " <span class=\"fieldLabel\" ng-show=\"totalPages > 10 && showInput === true\"> \n" +
+ " <label for=\"{{inputId}}\">Go to Page:</label>\n" +
+ " <input id=\"{{inputId}}\" class=\"b2b-pager__item--input\" type=\"number\" ng-blur=\"onfocusOut($event)\" ng-focus=\"onfocusIn($event)\" ng-keypress=\"gotoKeyClick($event)\" b2b-only-nums=\"4\" ng-model=\"$parent.gotoPage\" />\n" +
+ " <button class=\"btn-arrow\" ng-click=\"gotoBtnClick()\" ng-disabled=\"$parent.gotoPage !== 0 || $parent.gotoPage !== undefined\" aria-label=\"Go to\">\n" +
+ " <div class=\"btn btn-small btn-secondary\">\n" +
+ " <i class=\"icon-primary-right\"></i>\n" +
+ " </div>\n" +
+ " </button>\n" +
+ " </span>\n" +
+ " </div>\n" +
+ " <div ng-if=\"isMobile && totalPages > 1\" ng-swipe-right=\"prev()\" ng-swipe-left=\"next()\" ng-class=\"isMobile ? 'b2b-mobile-view': '' \">\n" +
+ " <a tabindex=\"{{checkSelectedPage(page) ? -1 : 0}}\" href=\"javascript:void(0)\" class=\"b2b-pager__item b2b-pager__item--link\" title=\"Page {{page}}\" b2b-element-focus=\"isFocused(page)\" ng-repeat=\"page in pages\" ng-class=\"{'b2b-pager__item--active': checkSelectedPage(page), fade1: ($index == 0 && currentPage > meanVal+1), fade2: ($index == 1 && currentPage > meanVal+1), fadesl: ($index == pages.length-2 && currentPage < totalPages - meanVal), fadel: ($last && currentPage < totalPages - meanVal), 'b2b-pager__item--noclick': checkSelectedPage(page)}\" b2b-accessibility-click=\"13,32\" ng-click=\"selectPage(page, $event)\">{{page}}</a>\n" +
+ " </div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/paneSelector/paneSelector.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/paneSelector/paneSelector.html",
+ "<div class=\"panes\" ng-transclude></div>");
+}]);
+
+angular.module("b2bTemplate/paneSelector/paneSelectorPane.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/paneSelector/paneSelectorPane.html",
+ "<div class=\"pane-block\" ng-transclude></div>");
+}]);
+
+angular.module("b2bTemplate/profileCard/profileCard-addUser.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/profileCard/profileCard-addUser.html",
+ "<div class=\"span3 b2b-profile-card b2b-add-user\">\n" +
+ " <div class=\"atcenter\">\n" +
+ " <div class=\"circle\"><i class=\"icon-primary-add-maximize\"></i></div>\n" +
+ " <div>Create new user</div>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/profileCard/profileCard.html",
+ "<div class=\"span3 b2b-profile-card\">\n" +
+ " <div class=\"top-block\">\n" +
+ " <div class=\"profile-image\">\n" +
+ " <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\" alt=\"{{profile.name}}\">\n" +
+ " <span ng-if=\"!image\" class=\"default-img\">{{initials}}</span>\n" +
+ "\n" +
+ " <h4 class=\"name\">{{profile.name}}</h4>\n" +
+ "\n" +
+ " <p class=\"status\">\n" +
+ " <span class=\"status-icon\" ng-class=\"{'status-green':colorIcon==='green','status-red':colorIcon==='red','status-blue':colorIcon==='blue','status-yellow':colorIcon==='yellow'}\"> \n" +
+ " </span>\n" +
+ " <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
+ " </p>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"bottom-block\">\n" +
+ " <div class=\"profile-details\">\n" +
+ " <label>Username</label>\n" +
+ " <div ng-if=\"shouldClip(profile.userName)\" ng-mouseover=\"showUserNameTooltip = true;\" ng-mouseleave=\"showUserNameTooltip = false;\">\n" +
+ " <div ng-if=\"shouldClip(profile.userName)\" class=\"tooltip\" b2b-tooltip show-tooltip=\"showUserNameTooltip\">\n" +
+ " {{profile.userName.slice(0, 25)+'...'}}\n" +
+ " <div class=\"arrow\"></div>\n" +
+ " <div class=\"tooltip-wrapper\" role=\"tooltip\" aria-live=\"polite\" aria-atomic=\"false\" style=\"z-index:1111\">\n" +
+ " <div class=\"tooltip-size-control\">\n" +
+ " <div class=\"helpertext\" tabindex=\"-1\" role=\"tooltip\">\n" +
+ " {{profile.userName}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div ng-if=\"!shouldClip(profile.userName)\">\n" +
+ " {{profile.userName}}\n" +
+ " </div>\n" +
+ " <label>Email</label>\n" +
+ " <div ng-if=\"shouldClip(profile.email)\" ng-mouseover=\"showEmailTooltip = true;\" ng-mouseleave=\"showEmailTooltip = false;\">\n" +
+ " <div ng-if=\"shouldClip(profile.email)\" class=\"tooltip\" data-placement=\"bottom\" b2b-tooltip show-tooltip=\"showEmailTooltip\">\n" +
+ " {{profile.email.slice(0, 25)+'...'}}\n" +
+ " <div class=\"arrow\"></div>\n" +
+ " <div class=\"tooltip-wrapper\" role=\"tooltip\" aria-live=\"polite\" aria-atomic=\"false\" style=\"z-index:1111\">\n" +
+ " <div class=\"tooltip-size-control\">\n" +
+ " <div class=\"helpertext\" tabindex=\"-1\" role=\"tooltip\">\n" +
+ " {{profile.email}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div ng-if=\"!shouldClip(profile.email)\">\n" +
+ " {{profile.email}}\n" +
+ " </div>\n" +
+ " <label>Role</label>\n" +
+ " <div ng-if=\"shouldClip(profile.role)\" ng-mouseover=\"showRoleTooltip = true;\" ng-mouseleave=\"showRoleTooltip = false;\">\n" +
+ " <div ng-if=\"shouldClip(profile.role)\" class=\"tooltip\" b2b-tooltip show-tooltip=\"showRoleTooltip\">\n" +
+ " {{profile.role.slice(0, 25)+'...'}}\n" +
+ " <div class=\"tooltip-wrapper\" role=\"tooltip\" aria-live=\"polite\" aria-atomic=\"false\" style=\"z-index:1111\">\n" +
+ " <div class=\"tooltip-size-control\">\n" +
+ " <div class=\"helpertext\" tabindex=\"-1\" role=\"tooltip\">\n" +
+ " {{profile.role}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div ng-if=\"!shouldClip(profile.role)\">\n" +
+ " {{profile.role}}\n" +
+ " </div>\n" +
+ " <label>Last login</label>\n" +
+ " <div ng-if=\"shouldClip(profile.lastLogin)\" ng-mouseover=\"showLastLoginTooltip = true;\" ng-mouseleave=\"showLastLoginTooltip = false;\">\n" +
+ " <div ng-if=\"shouldClip(profile.lastLogin)\" class=\"tooltip\" b2b-tooltip show-tooltip=\"showLastLoginTooltip\">\n" +
+ " {{profile.lastLogin.slice(0, 25)+'...'}}\n" +
+ " <div class=\"tooltip-wrapper\" role=\"tooltip\" aria-live=\"polite\" aria-atomic=\"false\" style=\"z-index:1111\">\n" +
+ " <div class=\"tooltip-size-control\">\n" +
+ " <div class=\"helpertext\" tabindex=\"-1\" role=\"tooltip\">\n" +
+ " {{profile.lastLogin}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div ng-if=\"!shouldClip(profile.lastLogin)\">\n" +
+ " {{profile.lastLogin}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/searchField/searchField.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/searchField/searchField.html",
+ "<div class=\"search-bar\">\n" +
+ " <div class='input-container' ng-blur=\"blurInput()\">\n" +
+ " <input type=\"text\" class=\"innershadow b2b-search-input-field\" id=\"{{configObj.labelId}}\" b2b-search-input ng-model=\"inputModel\" ng-disabled=\"disabled\" b2b-reset ng-keydown=\"selectionIndex($event)\" placeholder=\"{{configObj.ghostText}}\" style=\"width:100%\" maxlength=\"{{configObj.maxLength}}\" title=\"{{inputModel}}\" aria-label=\"{{inputModel.length>0?inputModel:configObj.ghostText}}\" aria-live=\"assertive\"/>\n" +
+ " <button class=\"btn-search\" ng-disabled=\"disabled\" ng-click=\"startSearch()\" b2b-accessibility-click=\"13,32\" aria-label=\"Search\" ng-focus=\"showListFlag = false\" type=\"button\"><i class=\"icoControls-magnifyingglass\"></i></button>\n" +
+ " </div>\n" +
+ " <div class=\"search-suggestion-wrapper\" ng-if=\"filterList.length >=0\" ng-show=\"showListFlag\">\n" +
+ " <ul class=\"search-suggestion-list\" role=\"listbox\"> \n" +
+ " <li class=\"no-result\" ng-if=\"filterList.length == 0 && configObj.display\">{{configObj.resultText}}</li>\n" +
+ " <li class=\"search-suggestion-item\" ng-if=\"filterList.length\" ng-repeat=\"item in filterList | limitTo:configObj.noOfItemsDisplay track by $index\" ng-bind-html=\"item.title | b2bMultiSepartorHighlight:inputModel:configObj.searchSeperator\" ng-class=\"{active:isActive($index,filterList.length)}\" ng-click=\"selectItem($index,item.title)\">\n" +
+ " {{item.title}} \n" +
+ " </li>\n" +
+ " </ul>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/seekBar/seekBar.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/seekBar/seekBar.html",
+ "<div class=\"b2b-seek-bar-container\" ng-class=\"{vertical:verticalSeekBar}\">\n" +
+ " <div class=\"b2b-seek-bar-track-container\">\n" +
+ " <div class=\"b2b-seek-bar-track\"></div>\n" +
+ " <div class=\"b2b-seek-bar-track-fill\"></div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-seek-bar-knob-container\" role=\"menu\" >\n" +
+ " <div class=\"b2b-seek-bar-knob\" tabindex=\"0\" role=\"menuitem\"></div>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/slider/slider.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/slider/slider.html",
+ "<div class=\"b2b-slider-container\" ng-class=\"{'vertical':verticalSlider}\">\n" +
+ " <div class=\"slider-track-container\">\n" +
+ " <div class=\"slider-track\"></div>\n" +
+ " <div class=\"slider-track-fill\" ng-style=\"{backgroundColor:trackFillColor}\"></div>\n" +
+ " </div>\n" +
+ " <div class=\"slider-knob-container\" ng-class=\"{'slider-knob-hidden':hideKnob}\">\n" +
+ " <div class=\"slider-knob\" role=\"slider\" aria-valuemin=\"{{min}}\" aria-valuemax=\"{{max}}\" aria-labelledby=\"{{labelId}}\" aria-valuenow=\"{{currentModelValue}}\" aria-valuetext=\"{{currentModelValue}}{{postAriaLabel}}\" aria-orientation=\"{{verticalSlider ? 'vertical' : 'horizontal'}}\"></div>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/spinButton/spinButton.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/spinButton/spinButton.html",
+ "<div class=\"btn-group btn-spinbutton-toggle\" ng-class=\"{'disabled': disabledFlag}\">\n" +
+ " <button type=\"button\" tabindex=\"{{isMobile?'0':'-1'}}\" aria-hidden=\"{{notMobile}}\" class=\"btn btn-secondary btn-prev icon-primary-subtractminimize\" ng-click=\"minus();focusInputSpinButton($event)\" aria-label=\"Remove {{step}}\" aria-controls=\"{{spinButtonId}}\" ng-class=\"{'disabled': isMinusDisabled()}\" ng-disabled=\"isMinusDisabled()\" aria-disabled=\"{{isMinusDisabled()}}\" role=\"spinbutton\"></button>\n" +
+ " <input class=\"btn pull-left\" id=\"{{spinButtonId}}\" type=\"tel\" b2b-only-nums=\"3\" maxlength=\"3\" min={{min}} max={{max}} data-max-value=\"{{max}}\" ng-model=\"inputValue[inputModelKey]\" value=\"{{inputValue[inputModelKey]}}\" aria-live=\"polite\" aria-valuenow=\"{{inputValue[inputModelKey]}}\" aria-valuemin=\"{{min}}\" aria-valuemax=\"{{max}}\" ng-disabled=\"disabledFlag\">\n" +
+ " <button type=\"button\" tabindex=\"{{isMobile?'0':'-1'}}\" aria-hidden=\"{{notMobile}}\" class=\"btn btn-secondary btn-next icon-primary-add-maximize\" ng-click=\"plus();focusInputSpinButton($event)\" aria-label=\"Add {{step}}\" aria-controls=\"{{spinButtonId}}\" ng-class=\"{'disabled': isPlusDisabled()}\" ng-disabled=\"isPlusDisabled()\" aria-disabled=\"{{isPlusDisabled()}}\" role=\"spinbutton\"></button>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/statusTracker/statusTracker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/statusTracker/statusTracker.html",
+ "<div class=\"b2b-status-tracker row\">\n" +
+ " <button tabindex=\"0\" ng-disabled=\"currentViewIndex === 0\" ng-if=\"statuses.length > b2bStatusTrackerConfig.maxViewItems\" class=\"btn-arrow\" type=\"button\" aria-label=\"Previous status\" ng-click=\"previousStatus()\">\n" +
+ " <div class=\"btn btn-small btn-secondary\">\n" +
+ " <i class=\"icon-primary-left\"></i>\n" +
+ " </div>\n" +
+ " </button>\n" +
+ " <div ng-repeat=\"status in statuses\" class=\"b2b-status-tracker-step\" ng-class=\"{ 'complete' : status.complete, 'current' : currentStatus($index)}\" ng-show=\"isInViewport($index)\">\n" +
+ " <p class=\"b2b-status-tracker-heading\">{{status.heading}}</p>\n" +
+ " <div class=\"progress\">\n" +
+ " <div class=\"progress-bar\">\n" +
+ " <span class=\"hidden-spoken\">\n" +
+ " {{status.complete ? 'Complete' : 'Incomplete'}}\n" +
+ " </span>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-status-tracker-estimate\">\n" +
+ " <i ng-show=\"status.estimate !== '' && status.estimate !== undefined\" ng-class=\"status.complete ? 'icoControls-approval' : 'icon-misc-time'\"></i> {{status.complete ? 'Complete' : status.estimate}}\n" +
+ " &nbsp;\n" +
+ " </div>\n" +
+ " \n" +
+ " <div class=\"b2b-status-tracker-description\">\n" +
+ " {{status.description}}\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <button tabindex=\"0\" ng-disabled=\"currentViewIndex + b2bStatusTrackerConfig.maxViewItems === statuses.length\" ng-if=\"statuses.length > b2bStatusTrackerConfig.maxViewItems\" class=\"btn-arrow\" type=\"button\" aria-label=\"Next status\" ng-click=\"nextStatus()\">\n" +
+ " <div class=\"btn btn-small btn-secondary\">\n" +
+ " <i class=\"icon-primary-right\"></i>\n" +
+ " </div>\n" +
+ " </button>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/stepTracker/stepTracker.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/stepTracker/stepTracker.html",
+ "<div class=\"b2b-step-tracker\">\n" +
+ " <button class=\"btn-arrow b2b-left-arrow\" ng-click=\"previousStatus()\" ng-disabled=\"currentViewIndex === 0\" ng-if=\"stepsItemsObject.length > b2bStepTrackerConfig.maxViewItems\" aria-label=\"Previous step\">\n" +
+ " <div class=\"btn btn-left btn-small btn-secondary\"><i class=\"icon-primary-left\"></i></div>\n" +
+ " </button>\n" +
+ " <button class=\"btn-arrow b2b-right-arrow\" ng-click=\"nextStatus()\" ng-disabled=\"currentViewIndex + b2bStepTrackerConfig.maxViewItems === stepsItemsObject.length\" ng-if=\"stepsItemsObject.length > b2bStepTrackerConfig.maxViewItems\" aria-label=\"Next step\">\n" +
+ " <div class=\"btn btn-small btn-right btn-secondary\"><i class=\"icon-primary-right\"></i></div>\n" +
+ " </button>\n" +
+ " <ul class=\"b2b-steps\">\n" +
+ " <li ng-class=\"{'b2b-step-done':$index < currentIndex - 1 ,'b2b-step-on':$index == currentIndex - 1}\" \n" +
+ " ng-repeat=\"stepsItem in stepsItemsObject\" ng-show=\"isInViewport($index)\">\n" +
+ " <p class=\"b2b-step-text\" data-sm-text=\"{{stepsItem.dataMobile}}\" data-large-text=\"{{stepsItem.dataDesktop}}\">{{stepsItem.text}}</p>\n" +
+ " <span class=\"hidden-spoken\">\n" +
+ " {{($index < currentIndex - 1)? 'Complete. '+stepsItem.text+' '+stepsItem.dataMobile:''}} \n" +
+ " {{($index == currentIndex - 1)? 'In Progress. '+stepsItem.text+' '+stepsItem.dataMobile:''}} \n" +
+ " {{($index > currentIndex - 1)? 'Incomplete. '+stepsItem.text+' '+stepsItem.dataMobile:''}}\n" +
+ " </span>\n" +
+ " </li>\n" +
+ " </ul>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/switches/switches-spanish.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/switches/switches-spanish.html",
+ "<div class=\"switch-overlay\" aria-hidden=\"true\">\n" +
+ " <span class=\"btn-slider-on\"><span class=\"hidden-spoken\">seleccione para hacer </span><i class=\"activo\">activo</i></span>\n" +
+ " <span class=\"switch-handle\"></span>\n" +
+ " <span class=\"btn-slider-off\"><span class=\"hidden-spoken\">seleccione para hacer </span><i class=\"inactivo\">inactivo</i></span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/switches/switches.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/switches/switches.html",
+ "<div class=\"switch-overlay\" aria-hidden=\"true\">\n" +
+ " <span class=\"btn-slider-on\">On</span>\n" +
+ " <span class=\"switch-handle\"></span>\n" +
+ " <span class=\"btn-slider-off\">Off</span>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/tableMessages/tableMessage.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tableMessages/tableMessage.html",
+ "<div class=\"b2b-table-message\">\n" +
+ " <div class=\"b2b-message\" ng-if=\"msgType === 'noMatchingResults'\">\n" +
+ " <div class=\"b2b-magnify-glass\"></div>\n" +
+ " <div>\n" +
+ " <div ng-transclude></div>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-message\" ng-if=\"msgType == 'infoCouldNotLoad'\">\n" +
+ " <div class=\"icon-primary-alert b2b-alert\" aria-label=\"Oops! The information could not load at this time. Please click link to refresh the page.\"></div>\n" +
+ " <div>Oops!</div>\n" +
+ " <div>The information could not load at this time.</div>\n" +
+ " <div>Please <a href=\"javascript:void(0)\" title=\"Refresh the page\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-message\" ng-if=\"msgType == 'magnifySearch'\">\n" +
+ " <div class=\"b2b-magnify-glass\"></div>\n" +
+ " <div>\n" +
+ " <p class=\"b2b-message-title\">Please input values to\n" +
+ " <br/> begin your search.</p>\n" +
+ " </div>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-message\" ng-if=\"msgType === 'loadingTable'\">\n" +
+ " <div class=\"icon-primary-spinner-ddh b2b-loading-dots\"></div>\n" +
+ " <div ng-transclude></div>\n" +
+ " </div>\n" +
+ "</div>\n" +
+ "");
+}]);
+
+angular.module("b2bTemplate/tableScrollbar/tableScrollbar.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tableScrollbar/tableScrollbar.html",
+ "<div class=\"b2b-table-scrollbar\">\n" +
+ " <div class=\"b2b-scrollbar-arrows\">\n" +
+ " <button class=\"btn-arrow b2b-scrollbar-arrow-left\" type=\"button\" ng-attr-aria-label=\"{{disableLeft ? 'Scroll Left Disabled' : 'Scroll Left'}}\" ng-click=\"scrollLeft()\" ng-disabled=\"disableLeft\"><div class=\"btn btn-alt\"><i class=\"icon-primary-left\"></i></div></button>\n" +
+ " <button class=\"btn-arrow b2b-scrollbar-arrow-right\" ng-attr-aria-label=\"{{disableRight ? 'Scroll Right Disabled' : 'Scroll Right'}}\" ng-click=\"scrollRight()\" ng-disabled=\"disableRight\" type=\"button\"><div class=\"btn btn-alt\"><i class=\"icon-primary-right\"></i></div></button>\n" +
+ " </div>\n" +
+ " <div class=\"b2b-table-inner-container\">\n" +
+ " <span ng-transclude></span>\n" +
+ " </div>\n" +
+ "</div>");
+}]);
+
+angular.module("b2bTemplate/tables/b2bTable.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tables/b2bTable.html",
+ "<table ng-class=\"{'striped': responsive, 'complex-table': responsive && active}\" ng-transclude></table>");
+}]);
+
+angular.module("b2bTemplate/tables/b2bTableBody.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tables/b2bTableBody.html",
+ "<td ng-hide=\"isHidden()\" ng-transclude></td>");
+}]);
+
+angular.module("b2bTemplate/tables/b2bTableHeaderSortable.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tables/b2bTableHeaderSortable.html",
+ "<th scope=\"col\" role=\"columnheader\" aria-sort=\"{{sortPattern !== 'null' && 'none' || sortPattern}}\" aria-label=\"{{headerName}} {{sortable !== 'false' && ': activate to sort' || ' '}} {{sortPattern !== 'null' && '' || sortPattern}}\" tabindex=\"{{sortable !== 'false' && '0' || '-1'}}\" b2b-accessibility-click=\"13,32\" ng-click=\"(sortable !== 'false') && sort();\" ng-hide=\"isHidden()\">\n" +
+ " <span ng-transclude></span>\n" +
+ " <i ng-class=\"{'icon-primary-arrows-sort-arrow active': sortPattern === 'ascending', 'icon-primary-arrows-sort-arrow active down': sortPattern === 'descending'}\"></i>\n" +
+ "</th>");
+}]);
+
+angular.module("b2bTemplate/tables/b2bTableHeaderUnsortable.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tables/b2bTableHeaderUnsortable.html",
+ "<th scope=\"col\" ng-hide=\"isHidden()\" ng-transclude></th>");
+}]);
+
+angular.module("b2bTemplate/tabs/b2bTab.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tabs/b2bTab.html",
+ "<li role=\"tab\" aria-selected=\"{{isTabActive()}}\" aria-controls=\"{{tabPanelId}}\" class=\"tab\" \n" +
+ " ng-class=\"{'active': isTabActive()}\" ng-click=\"clickTab()\" ng-hide=\"tabItem.disabled\">\n" +
+ " <a href=\"javascript:void(0)\" tabindex=\"{{(isTabActive() && tabItem.disabled)?-1:0}}\"\n" +
+ " ng-disabled=\"tabItem.disabled\" aria-expanded=\"{{(isTabActive() && !tabItem.disabled)}}\" \n" +
+ " b2b-accessibility-click=\"13,32\" ng-transclude></a>\n" +
+ " <span class=\"hidden-spoken\" ng-if=\"isTabActive()\">Active tab</span>\n" +
+ "</li>");
+}]);
+
+angular.module("b2bTemplate/tabs/b2bTabset.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/tabs/b2bTabset.html",
+ "<ul class=\"tabs promo-tabs\" role=\"tablist\" ng-transclude></ul>");
+}]);
+
+angular.module("b2bTemplate/treeNav/groupedTree.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNav/groupedTree.html",
+ "<ul role=\"group\">\n" +
+ " <li aria-expanded=\"{{(member.active?true:false)}}\" role=\"treeitem\" aria-label=\"{{key}}\" ng-repeat='(key,value) in collection | groupBy : \"grpChild\"' b2b-tree-link><a class=\"grp\" ng-class=\"{'active': value.showGroup == true}\" tabindex=\"-1\" href='javascript:void(0);'>{{(key)?key:''}}<span class=\"b2b-tree-node-icon\"><i ng-class=\"{'icon-primary-expanded': value.showGroup == true, 'icon-primary-collapsed': value.showGroup == undefined || value.showGroup == false }\"></i></span></a>\n" +
+ " <ul role=\"group\">\n" +
+ " <b2b-member ng-repeat='member in value.childArray' member='member' time-delay='{{timeDelay}}' group-it='groupIt'></b2b-member>\n" +
+ " </ul>\n" +
+ " </li>\n" +
+ "</ul>");
+}]);
+
+angular.module("b2bTemplate/treeNav/treeMember.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNav/treeMember.html",
+ "<li role=\"treeitem\" aria-expanded=\"{{(member.active?true:false)}}\" aria-label=\"{{member.tooltipContent ? member.tooltipContent : member.name}}\" aria-describedby=\"description_{{$id}}\" ng-class=\"{'bg':member.selected}\" b2b-tree-link>\n" +
+ " <a tabindex=\"-1\" title=\"{{member.tooltipContent ? member.tooltipContent : member.name}}\" href=\"javascript:void(0)\" ng-class=\"{'active':member.active,'b2b-locked-node':member.locked}\"> <span class=\"b2b-tree-node-name\">{{member.name}}</span>\n" +
+ " <span class=\"{{!member.child?'end':''}} b2b-tree-node-icon\">\n" +
+ " <i class=\"b2b-tree-expandCollapse-icon\" ng-class=\"{'icon-primary-expanded':member.active}\"></i>\n" +
+ " </span>\n" +
+ " <div id=\"description_{{$id}}\" class=\"offscreen-text\">\n" +
+ " {{member.descriptionText}}\n" +
+ " </div>\n" +
+ " <div class=\"b2b-tree-tooltip\" ng-if=\"member.showTooltip\">\n" +
+ " <span class=\"b2b-tree-arrow-left\"></span>\n" +
+ " <div class=\"b2b-tree-tooltip-content\">\n" +
+ " {{member.tooltipContent}}\n" +
+ " </div> \n" +
+ " </div>\n" +
+ " </a>\n" +
+ "</li>");
+}]);
+
+angular.module("b2bTemplate/treeNav/ungroupedTree.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNav/ungroupedTree.html",
+ "<ul role=\"{{setRole}}\"><b2b-member ng-repeat='member in collection' member='member' group-it='groupIt'></b2b-member></ul>");
+}]);
+
+angular.module("b2bTemplate/treeNodeCheckbox/groupedTree.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNodeCheckbox/groupedTree.html",
+ "<ul role=\"group\">\n" +
+ " <li aria-expanded=\"{{(member.active?true:false)}}\" role=\"treeitem\" aria-label=\"{{key}}\" ng-repeat='(key,value) in collection | groupBy : \"grpChild\"' b2b-tree-node-link><a class=\"grp\" ng-class=\"{'active': value.showGroup == true}\" tabindex=\"-1\" href='javascript:void(0);'>\n" +
+ " <span class=\"ng-hide\">\n" +
+ " <label class=\"checkbox\">\n" +
+ " <input type=\"checkbox\" tabindex=\"-1\" class=\"treeCheckBox grpTreeCheckbox\" style=\"margin-top:2px;\"/><i class=\"skin\"></i><span> {{(key)?key:''}}</span>\n" +
+ " </label>\n" +
+ " </span>\n" +
+ " <span>\n" +
+ " {{(key)?key:''}} \n" +
+ " </span>\n" +
+ " <span class=\"nodeIcon\"><i class=\"expandCollapseIcon\" ng-class=\"{'icon-primary-expanded': value.showGroup == true, 'icon-primary-collapsed': value.showGroup == undefined || value.showGroup == false }\"></i></span></a>\n" +
+ " <ul role=\"group\">\n" +
+ " <b2b-tree-member ng-repeat='member in value.childArray' member='member' group-it='groupIt'></b2b-tree-member>\n" +
+ " </ul>\n" +
+ " </li>\n" +
+ "</ul>");
+}]);
+
+angular.module("b2bTemplate/treeNodeCheckbox/treeMember.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNodeCheckbox/treeMember.html",
+ "<li role=\"treeitem\" aria-expanded=\"{{(member.active?true:false)}}\" aria-label=\"{{member.name}}\" ng-class=\"{'bg':member.selected}\" b2b-tree-node-link>\n" +
+ " <a tabindex=\"-1\" title=\"{{member.name}}\" href=\"javascript:void(0)\" ng-class=\"{'active':member.active}\">\n" +
+ " <span ng-show=\"member.displayCheckbox\">\n" +
+ " <label class=\"checkbox\">\n" +
+ " <input type=\"checkbox\" tabindex=\"-1\" ng-model=\"member.isSelected\" ng-class=\"{'treeCheckBox': (member.displayCheckbox !== undefined)}\" style=\"margin-top:2px;\"/><i class=\"skin\"></i><span> {{member.name}}</span>\n" +
+ " </label>\n" +
+ " </span>\n" +
+ " <span ng-show=\"!member.displayCheckbox\">\n" +
+ " {{member.name}} \n" +
+ " </span>\n" +
+ " <span class=\"nodeIcon {{!member.child?'end':''}}\">\n" +
+ " <i class=\"expandCollapseIcon\" ng-class=\"{'icon-primary-expanded':member.active}\"></i>\n" +
+ " </span>\n" +
+ " </a>\n" +
+ "</li>");
+}]);
+
+angular.module("b2bTemplate/treeNodeCheckbox/ungroupedTree.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("b2bTemplate/treeNodeCheckbox/ungroupedTree.html",
+ "<ul role=\"{{setRole}}\"><b2b-tree-member ng-repeat='member in collection' member='member' group-it='groupIt'></b2b-tree-member></ul>");
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/horse_shoe.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/horse_shoe.jpg
new file mode 100644
index 00000000..a53eb4ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/horse_shoe.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/icon-flyout.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/icon-flyout.png
new file mode 100644
index 00000000..88e10332
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/icon-flyout.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/treebg.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/treebg.png
new file mode 100644
index 00000000..32ed1b7c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/treebg.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/widget-thumbnail.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/widget-thumbnail.png
new file mode 100644
index 00000000..5fbf93c2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/style/images/widget-thumbnail.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/styles/images/icon-flyout.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/styles/images/icon-flyout.png
new file mode 100644
index 00000000..88e10332
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/b2b/js/b2b-angular/styles/images/icon-flyout.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/bootstrap/bs.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/bootstrap/bs.css
index f62911f2..f62911f2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/bootstrap/bs.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/bootstrap/bs.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/css/nv.d3.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/css/nv.d3.css
index 28ccd053..28ccd053 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/css/nv.d3.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/css/nv.d3.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/cie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/cie.js
index 45f01329..45f01329 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/cie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/cie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js
index 2295527b..2295527b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/colorbrewer.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/core.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/core.js
index 912de8d8..912de8d8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/core.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/core.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.js
index 1aaabca2..1aaabca2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js
index 981f0d64..981f0d64 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/crossfilter.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.geom.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.geom.js
index a19bb16e..a19bb16e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.geom.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.geom.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.js
index 7655eb78..7655eb78 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js
index 44c4f7de..44c4f7de 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.cloud.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.js
index abc5ebef..abc5ebef 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.layout.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.layout.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.js
index 78c4dbca..78c4dbca 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js
index cc47f1ea..cc47f1ea 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v2.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js
index 7975878f..7975878f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/d3.v3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/fisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/fisheye.js
index e1addd7b..e1addd7b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/fisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/fisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/hive.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/hive.js
index 06e53aed..06e53aed 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/hive.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/hive.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/horizon.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/horizon.js
index d84c6567..d84c6567 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/horizon.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/horizon.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
index 4dfb68dc..4dfb68dc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/interactiveLayer.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/intro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/intro.js
new file mode 100644
index 00000000..180e46f7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/intro.js
@@ -0,0 +1,2 @@
+(function(){
+});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js
index 1101dde5..1101dde5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis-min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.js
index 9895c3f0..9895c3f0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js
index 6c8ad6ab..6c8ad6ab 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/axis.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js
index 86ebeb0f..86ebeb0f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bullet.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js
index a2a0f077..a2a0f077 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/backup/bulletChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js
index 3d2360a6..3d2360a6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/boilerplate.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bullet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bullet.js
index 9b9bf4d1..9b9bf4d1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bullet.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bullet.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js
index fa5bd596..fa5bd596 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/bulletChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js
index 00f193cf..00f193cf 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/cumulativeLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js
index a20f5829..a20f5829 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js
index 48a48164..48a48164 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/discreteBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/distribution.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/distribution.js
index 62a74655..62a74655 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/distribution.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/distribution.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js
index 2a6c644d..2a6c644d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js
index a5b4a097..a5b4a097 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/historicalBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js
index 18c2700f..18c2700f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/indentedTree.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/legend.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/legend.js
index 21f9f9a4..21f9f9a4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/legend.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/legend.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/line.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/line.js
index 855cc541..855cc541 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/line.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/line.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js
index a4ffcf6a..a4ffcf6a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js
index 77fcbab7..77fcbab7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js
index 2ef31137..2ef31137 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/linePlusBarWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js
index 2b411672..2b411672 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js
index ad894190..ad894190 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFisheyeChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js
index 0afd28bd..0afd28bd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/lineWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js
index 1085919b..1085919b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js
index 0323063f..0323063f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js
index d16d4605..d16d4605 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontal.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js
index 02aa6fa4..02aa6fa4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarHorizontalChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js
index abc062c3..abc062c3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeries.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js
index 5aebafa7..5aebafa7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiBarTimeSeriesChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js
index e3e2c5e8..e3e2c5e8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/multiChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js
index 46f2b60c..46f2b60c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/ohlcBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js
index 107154f7..107154f7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/parallelCoordinates.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pie.js
index 2099c8f3..2099c8f3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js
index b4303fd6..b4303fd6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/pieChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatter.js
index 16cbee65..16cbee65 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js
index 65b6e387..65b6e387 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js
index 23c87853..23c87853 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/scatterPlusLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js
index e4c2e87b..e4c2e87b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparkline.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js
index 1535f8af..1535f8af 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/sparklinePlus.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js
index eefeb8fb..eefeb8fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedArea.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js
index a036b8b0..a036b8b0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/models/stackedAreaChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.js
index 78586667..78586667 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js
index 892379c4..892379c4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/nv.d3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/outro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/outro.js
index 158693a0..158693a0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/outro.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/outro.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/sankey.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/sankey.js
index c3bc59fb..c3bc59fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/sankey.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/sankey.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/tooltip.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/tooltip.js
index 46e5a816..46e5a816 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/tooltip.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/tooltip.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/utils.js
index 7b99e1da..7b99e1da 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/utils.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/d3/js/utils.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ds2/js/appDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ds2/js/appDS2.js
new file mode 100644
index 00000000..2847ade5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ds2/js/appDS2.js
@@ -0,0 +1 @@
+var appDS2=angular.module("abs", ["ngRoute", 'ngMessages','modalServices', 'ngCookies', 'b2b.att','gridster','ui.bootstrap','ui.bootstrap.modal']); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ebz/copyrighted-material-removed.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/ebz/copyrighted-material-removed.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/gis/js/local.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/gis/js/local.js
new file mode 100644
index 00000000..5f4208a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/gis/js/local.js
@@ -0,0 +1,178 @@
+var pointLayer= null;
+var animateFlag = false;
+var frame = 0;
+var dates = [];
+var delay = 1000;
+var intervalId = null;
+$( document ).ready(function() {
+ map(data2.map.lat,data2.map.lon,data2.map.zoom);
+ pointLayer = new L.layerGroup().addTo(map);
+ var point = getDates(data2.points);
+ drawPoints(data2,point);
+
+
+ $('#timeUp').bind('click',function(){
+ delay += 500;
+ if ( animateFlag ) {
+ clearInterval(intervalId);
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+ $('#timeDown').bind('click',function(){
+ if ( delay === 500 ) { return false; }
+ delay -= 500;
+ if ( animateFlag ) {
+ clearInterval(intervalId);
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+
+
+ $('#date').bind('change',function(){
+ drawPoints(data2,$('#date').val());
+ });
+ $('#animate').bind('click',function(){
+ if ( animateFlag ) {
+ animateFlag = false;
+ $('#animate_color').html('Off');
+ $('#animate_color').removeClass('animateOn');
+ $('#animate_color').addClass('animateOff');
+ clearInterval(intervalId);
+ } else {
+ animateFlag = true;
+ $('#animate_color').html('On');
+ $('#animate_color').removeClass('animateOff');
+ $('#animate_color').addClass('animateOn');
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+
+
+});
+
+function abc() {
+ var abc = 1;
+ var xyz = "";
+ return nul;
+
+}
+
+
+
+function animate(obj){
+ var point = dates[frame];
+ drawPoints(obj,point);
+ frame++;
+ if ( frame >= dates.length ) {
+ frame = 0;
+ }
+ $('#currDate').val(point);
+ $('#showDelay').html(delay);
+}
+
+function someFunction() {
+
+ var self = this;
+ var x = 1;
+ var z = self + x;
+}
+
+
+/**
+* drawPoints - Draw the points provided by point(date)
+* obj JSON Object - Data for Map
+* p String - Key (date) from the JSON object.
+*/
+function drawPoints(obj,p){
+ pointLayer.clearLayers();
+ var lats = obj.points[p].lats;
+ var lons = obj.points[p].lons;
+ var txt = obj.points[p].text;
+ var fills = obj.points[p].colors;
+ points(lats, lons,txt,fills);
+}
+
+/**
+* Get dates from the list provided in pIn and put them in Select.
+* then return the fist date.
+*
+*/
+function getDates(pIn) {
+ var html = "<option value='na'>--Select--</option>";
+ var c = 0;
+ var ret = 0;
+ for (var d in pIn ) {
+ var val = d.replace('"','');
+ if ( c === 0 ) { ret = val;};
+ html += "<option value='" + d + "'>" + d + "</option>";
+ dates[c] = val;
+ c++;
+ }
+ $('#date').html(html);
+ return ret;
+}
+
+/**
+* Map - pass argumets to build map as specified Lat/Lon and zoom level
+* String lat - Latitude
+* String lon - Longitude
+* String zoom - Zoom Level (1-18)
+*
+*/
+function map(lat,lon,zoom){
+ var map = L.map('map').setView([lat,lon],zoom);
+ map.addControl(new L.control.scale());
+ L.tileLayer('http://localhost/tiles-light/{z}/{x}/{y}.png', {maxZoom:18}).addTo(map);
+ window.L=L;
+ window.map=map;
+}
+
+/**
+* points - pass argumets to points specified Lat/Lon. Text and color for point is also passed.
+* Input is either all singe values or all arrays.
+* String[] lat - Latitude
+* String[] lon - Longitude
+* String[] text - Single/Array of Text for points
+* String[] fill - Single/Array of Fill colors.
+*/
+function points(lat,lon,text,fill){
+ if(lat.length) {
+ for(i=0;i<lat.length;i++) {
+ pointLayer.addLayer(L.circleMarker([lat[i], lon[i]], {
+ radius:"5",
+ color: fill[i],
+ fillColor: fill[i],
+ fillOpacity: "0.5" }).bindPopup(text[i]));
+
+ /*
+ L.circleMarker([lat[i], lon[i]], {
+ radius:"5",
+ color: fill[i],
+ fillColor: fill[i],
+ fillOpacity: "0.5" }).addTo(map).bindPopup(text[i]);
+
+ */
+
+ }
+
+ } else {
+ L.circleMarker([lat, lon], {
+ radius:"5",
+ color:fill,
+ fillColor:fill,
+ fillOpacity: "0.5"
+ }).addTo(map).bindPopup(text);
+ }
+}
+
+/**
+* Get data from json file and creat return an object of data.
+* Returns json object.
+*
+**/
+function getData(){
+ $.getJSON( "./data.json", function( data ) {
+ return data;
+ });
+
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/detect-element-resize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/detect-element-resize.js
new file mode 100644
index 00000000..cbb3c025
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/detect-element-resize.js
@@ -0,0 +1,147 @@
+/**
+* Detect Element Resize
+*
+* https://github.com/sdecima/javascript-detect-element-resize
+* Sebastian Decima
+*
+* version: 0.5.3
+**/
+
+(function () {
+ var attachEvent = document.attachEvent,
+ stylesCreated = false;
+
+ if (!attachEvent) {
+ var requestFrame = (function(){
+ var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
+ function(fn){ return window.setTimeout(fn, 20); };
+ return function(fn){ return raf(fn); };
+ })();
+
+ var cancelFrame = (function(){
+ var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
+ window.clearTimeout;
+ return function(id){ return cancel(id); };
+ })();
+
+ function resetTriggers(element){
+ var triggers = element.__resizeTriggers__,
+ expand = triggers.firstElementChild,
+ contract = triggers.lastElementChild,
+ expandChild = expand.firstElementChild;
+ contract.scrollLeft = contract.scrollWidth;
+ contract.scrollTop = contract.scrollHeight;
+ expandChild.style.width = expand.offsetWidth + 1 + 'px';
+ expandChild.style.height = expand.offsetHeight + 1 + 'px';
+ expand.scrollLeft = expand.scrollWidth;
+ expand.scrollTop = expand.scrollHeight;
+ };
+
+ function checkTriggers(element){
+ return element.offsetWidth != element.__resizeLast__.width ||
+ element.offsetHeight != element.__resizeLast__.height;
+ }
+
+ function scrollListener(e){
+ var element = this;
+ resetTriggers(this);
+ if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
+ this.__resizeRAF__ = requestFrame(function(){
+ if (checkTriggers(element)) {
+ element.__resizeLast__.width = element.offsetWidth;
+ element.__resizeLast__.height = element.offsetHeight;
+ element.__resizeListeners__.forEach(function(fn){
+ fn.call(element, e);
+ });
+ }
+ });
+ };
+
+ /* Detect CSS Animations support to detect element display/re-attach */
+ var animation = false,
+ animationstring = 'animation',
+ keyframeprefix = '',
+ animationstartevent = 'animationstart',
+ domPrefixes = 'Webkit Moz O ms'.split(' '),
+ startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
+ pfx = '';
+ {
+ var elm = document.createElement('fakeelement');
+ if( elm.style.animationName !== undefined ) { animation = true; }
+
+ if( animation === false ) {
+ for( var i = 0; i < domPrefixes.length; i++ ) {
+ if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
+ pfx = domPrefixes[ i ];
+ animationstring = pfx + 'Animation';
+ keyframeprefix = '-' + pfx.toLowerCase() + '-';
+ animationstartevent = startEvents[ i ];
+ animation = true;
+ break;
+ }
+ }
+ }
+ }
+
+ var animationName = 'resizeanim';
+ var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
+ var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
+ }
+
+ function createStyles() {
+ if (!stylesCreated) {
+ //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
+ var css = (animationKeyframes ? animationKeyframes : '') +
+ '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
+ '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
+ head = document.head || document.getElementsByTagName('head')[0],
+ style = document.createElement('style');
+
+ style.type = 'text/css';
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+
+ head.appendChild(style);
+ stylesCreated = true;
+ }
+ }
+
+ window.addResizeListener = function(element, fn){
+ if (attachEvent) element.attachEvent('onresize', fn);
+ else {
+ if (!element.__resizeTriggers__) {
+ if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
+ createStyles();
+ element.__resizeLast__ = {};
+ element.__resizeListeners__ = [];
+ (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
+ element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
+ '<div class="contract-trigger"></div>';
+ element.appendChild(element.__resizeTriggers__);
+ resetTriggers(element);
+ element.addEventListener('scroll', scrollListener, true);
+
+ /* Listen for a css animation to detect element display/re-attach */
+ animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
+ if(e.animationName == animationName)
+ resetTriggers(element);
+ });
+ }
+ element.__resizeListeners__.push(fn);
+ }
+ };
+
+ window.removeResizeListener = function(element, fn){
+ if (attachEvent) element.detachEvent('onresize', fn);
+ else {
+ element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
+ if (!element.__resizeListeners__.length) {
+ element.removeEventListener('scroll', scrollListener);
+ element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
+ }
+ }
+ }
+})(); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/jquery.resize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/jquery.resize.js
new file mode 100644
index 00000000..ba42a800
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/javascript-detect-element-resize/jquery.resize.js
@@ -0,0 +1,164 @@
+/**
+* Detect Element Resize Plugin for jQuery
+*
+* https://github.com/sdecima/javascript-detect-element-resize
+* Sebastian Decima
+*
+* version: 0.5.3
+**/
+
+(function ( $ ) {
+ var attachEvent = document.attachEvent,
+ stylesCreated = false;
+
+ var jQuery_resize = $.fn.resize;
+
+ $.fn.resize = function(callback) {
+ return this.each(function() {
+ if(this == window)
+ jQuery_resize.call(jQuery(this), callback);
+ else
+ addResizeListener(this, callback);
+ });
+ }
+
+ $.fn.removeResize = function(callback) {
+ return this.each(function() {
+ removeResizeListener(this, callback);
+ });
+ }
+
+ if (!attachEvent) {
+ var requestFrame = (function(){
+ var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
+ function(fn){ return window.setTimeout(fn, 20); };
+ return function(fn){ return raf(fn); };
+ })();
+
+ var cancelFrame = (function(){
+ var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
+ window.clearTimeout;
+ return function(id){ return cancel(id); };
+ })();
+
+ function resetTriggers(element){
+ var triggers = element.__resizeTriggers__,
+ expand = triggers.firstElementChild,
+ contract = triggers.lastElementChild,
+ expandChild = expand.firstElementChild;
+ contract.scrollLeft = contract.scrollWidth;
+ contract.scrollTop = contract.scrollHeight;
+ expandChild.style.width = expand.offsetWidth + 1 + 'px';
+ expandChild.style.height = expand.offsetHeight + 1 + 'px';
+ expand.scrollLeft = expand.scrollWidth;
+ expand.scrollTop = expand.scrollHeight;
+ };
+
+ function checkTriggers(element){
+ return element.offsetWidth != element.__resizeLast__.width ||
+ element.offsetHeight != element.__resizeLast__.height;
+ }
+
+ function scrollListener(e){
+ var element = this;
+ resetTriggers(this);
+ if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
+ this.__resizeRAF__ = requestFrame(function(){
+ if (checkTriggers(element)) {
+ element.__resizeLast__.width = element.offsetWidth;
+ element.__resizeLast__.height = element.offsetHeight;
+ element.__resizeListeners__.forEach(function(fn){
+ fn.call(element, e);
+ });
+ }
+ });
+ };
+
+ /* Detect CSS Animations support to detect element display/re-attach */
+ var animation = false,
+ animationstring = 'animation',
+ keyframeprefix = '',
+ animationstartevent = 'animationstart',
+ domPrefixes = 'Webkit Moz O ms'.split(' '),
+ startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
+ pfx = '';
+ {
+ var elm = document.createElement('fakeelement');
+ if( elm.style.animationName !== undefined ) { animation = true; }
+
+ if( animation === false ) {
+ for( var i = 0; i < domPrefixes.length; i++ ) {
+ if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
+ pfx = domPrefixes[ i ];
+ animationstring = pfx + 'Animation';
+ keyframeprefix = '-' + pfx.toLowerCase() + '-';
+ animationstartevent = startEvents[ i ];
+ animation = true;
+ break;
+ }
+ }
+ }
+ }
+
+ var animationName = 'resizeanim';
+ var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
+ var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
+ }
+
+ function createStyles() {
+ if (!stylesCreated) {
+ //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
+ var css = (animationKeyframes ? animationKeyframes : '') +
+ '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
+ '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
+ head = document.head || document.getElementsByTagName('head')[0],
+ style = document.createElement('style');
+
+ style.type = 'text/css';
+ if (style.styleSheet) {
+ style.styleSheet.cssText = css;
+ } else {
+ style.appendChild(document.createTextNode(css));
+ }
+
+ head.appendChild(style);
+ stylesCreated = true;
+ }
+ }
+
+ window.addResizeListener = function(element, fn){
+ if (attachEvent) element.attachEvent('onresize', fn);
+ else {
+ if (!element.__resizeTriggers__) {
+ if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
+ createStyles();
+ element.__resizeLast__ = {};
+ element.__resizeListeners__ = [];
+ (element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
+ element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
+ '<div class="contract-trigger"></div>';
+ element.appendChild(element.__resizeTriggers__);
+ resetTriggers(element);
+ element.addEventListener('scroll', scrollListener, true);
+
+ /* Listen for a css animation to detect element display/re-attach */
+ animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
+ if(e.animationName == animationName)
+ resetTriggers(element);
+ });
+ }
+ element.__resizeListeners__.push(fn);
+ }
+ };
+
+ window.removeResizeListener = function(element, fn){
+ if (attachEvent) element.detachEvent('onresize', fn);
+ else {
+ element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
+ if (!element.__resizeListeners__.length) {
+ element.removeEventListener('scroll', scrollListener);
+ element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
+ }
+ }
+ }
+}( jQuery )); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/.bower.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/.bower.json
new file mode 100644
index 00000000..25f5cf87
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/.bower.json
@@ -0,0 +1,25 @@
+{
+ "name": "jquery",
+ "main": "dist/jquery.js",
+ "license": "MIT",
+ "ignore": [
+ "package.json"
+ ],
+ "keywords": [
+ "jquery",
+ "javascript",
+ "browser",
+ "library"
+ ],
+ "homepage": "https://github.com/jquery/jquery-dist",
+ "version": "2.2.4",
+ "_release": "2.2.4",
+ "_resolution": {
+ "type": "version",
+ "tag": "2.2.4",
+ "commit": "c0185ab7c75aab88762c5aae780b9d83b80eda72"
+ },
+ "_source": "https://github.com/jquery/jquery-dist.git",
+ "_target": "~2.2.4",
+ "_originalSource": "jquery"
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.js
new file mode 100644
index 00000000..5c3c456a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.js
@@ -0,0 +1,9814 @@
+/*!
+ * jQuery JavaScript Library v2.2.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-05-20T17:23Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//"use strict";
+var arr = [];
+
+var document = window.document;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ version = "2.2.4",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ each: function( callback ) {
+ return jQuery.each( this, callback );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ } ) );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor();
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+
+ // Only deal with non-null/undefined values
+ if ( ( options = arguments[ i ] ) != null ) {
+
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
+
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray( src ) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject( src ) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend( {
+
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type( obj ) === "function";
+ },
+
+ isArray: Array.isArray,
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ // adding 1 corrects loss of precision from parseFloat (#15100)
+ var realStringObj = obj && obj.toString();
+ return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
+ },
+
+ isPlainObject: function( obj ) {
+ var key;
+
+ // Not plain objects:
+ // - Any object or value whose internal [[Class]] property is not "[object Object]"
+ // - DOM nodes
+ // - window
+ if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call( obj, "constructor" ) &&
+ !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android<4.0, iOS<6 (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ var script,
+ indirect = eval;
+
+ code = jQuery.trim( code );
+
+ if ( code ) {
+
+ // If the code includes a valid, prologue position
+ // strict mode pragma, execute code by injecting a
+ // script tag into the document.
+ if ( code.indexOf( "use strict" ) === 1 ) {
+ script = document.createElement( "script" );
+ script.text = code;
+ document.head.appendChild( script ).parentNode.removeChild( script );
+ } else {
+
+ // Otherwise, avoid the DOM node creation, insertion
+ // and removal by using an indirect global eval
+
+ indirect( code );
+ }
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Support: IE9-11+
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ each: function( obj, callback ) {
+ var length, i = 0;
+
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArrayLike( Object( arr ) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var length, value,
+ i = 0,
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+} );
+
+// JSHint would error on this code due to the Symbol not being defined in ES5.
+// Defining this global in .jshintrc would create a danger of using the global
+// unguarded in another place, it seems safer to just disable JSHint for these
+// three lines.
+/* jshint ignore: start */
+if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+/* jshint ignore: end */
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.1
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-10-17
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // http://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var m, i, elem, nid, nidselect, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
+
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
+
+ results = results || [];
+
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+
+ // Element context
+ } else {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
+
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
+ while ( i-- ) {
+ groups[i] = nidselect + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = arr.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, parent,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // Return early if doc is invalid or already selected
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Update global variables
+ document = doc;
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( (parent = document.defaultView) && parent.top !== parent ) {
+ // Support: IE 11
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( document.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !document.getElementsByName || !document.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ return m ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" &&
+ elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibing-combinator selector` fails
+ if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = document.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully self-exclusive
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === document ? -1 :
+ b === document ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ !compilerCache[ expr + " " ] &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, uniqueCache, outerCache, node, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType,
+ diff = false;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) {
+
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+
+ // Seek `elem` from a previously-cached index
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && cache[ 2 ];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ } else {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) &&
+ ++diff ) {
+
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, uniqueCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( (oldCache = uniqueCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ uniqueCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context === document || context || outermost;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context || document, xml) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
+ matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
+ if ( match.length === 1 ) {
+
+ // Reduce context if the leading compound selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var dir = function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+};
+
+
+var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+};
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ } );
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ } );
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
+ } );
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ } ) );
+};
+
+jQuery.fn.extend( {
+ find: function( selector ) {
+ var i,
+ len = this.length,
+ ret = [],
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter( function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ } ) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], false ) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], true ) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+} );
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context, root ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ selector.length - 1 ] === ">" &&
+ selector.length >= 3 ) {
+
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && ( match[ 1 ] || !context ) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[ 1 ] ) {
+ context = context instanceof jQuery ? context[ 0 ] : context;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[ 1 ],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[ 2 ] );
+
+ // Support: Blackberry 4.6
+ // gEBID returns nodes no longer in the document (#6963)
+ if ( elem && elem.parentNode ) {
+
+ // Inject the element directly into the jQuery object
+ this.length = 1;
+ this[ 0 ] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || root ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[ 0 ] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return root.ready !== undefined ?
+ root.ready( selector ) :
+
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+ // Methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend( {
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter( function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[ i ] ) ) {
+ return true;
+ }
+ }
+ } );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
+
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && ( pos ?
+ pos.index( cur ) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // Index in selector
+ if ( typeof elem === "string" ) {
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.uniqueSort(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter( selector )
+ );
+ }
+} );
+
+function sibling( cur, dir ) {
+ while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
+ return cur;
+}
+
+jQuery.each( {
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return siblings( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.uniqueSort( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+} );
+var rnotwhite = ( /\S+/g );
+
+
+
+// Convert String-formatted options into Object-formatted ones
+function createOptions( options ) {
+ var object = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ } );
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ createOptions( options ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+
+ // Last fire value for non-forgettable lists
+ memory,
+
+ // Flag to know if list was already fired
+ fired,
+
+ // Flag to prevent firing
+ locked,
+
+ // Actual callback list
+ list = [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
+ // Fire callbacks
+ fire = function() {
+
+ // Enforce single-firing
+ locked = options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
+ }
+ }
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
+ firing = false;
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
+ list = [];
+
+ // Otherwise, this object is spent
+ } else {
+ list = "";
+ }
+ }
+ },
+
+ // Actual Callbacks object
+ self = {
+
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ if ( jQuery.isFunction( arg ) ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+ // Inspect recursively
+ add( arg );
+ }
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Remove a callback from the list
+ remove: function() {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ } );
+ return this;
+ },
+
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ?
+ jQuery.inArray( fn, list ) > -1 :
+ list.length > 0;
+ },
+
+ // Remove all callbacks from the list
+ empty: function() {
+ if ( list ) {
+ list = [];
+ }
+ return this;
+ },
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
+ disable: function() {
+ locked = queue = [];
+ list = memory = "";
+ return this;
+ },
+ disabled: function() {
+ return !list;
+ },
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
+ lock: function() {
+ locked = queue = [];
+ if ( !memory ) {
+ list = memory = "";
+ }
+ return this;
+ },
+ locked: function() {
+ return !!locked;
+ },
+
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( !locked ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ queue.push( args );
+ if ( !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+jQuery.extend( {
+
+ Deferred: function( func ) {
+ var tuples = [
+
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks( "memory" ) ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred( function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[ 1 ] ]( function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .progress( newDefer.notify )
+ .done( newDefer.resolve )
+ .fail( newDefer.reject );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this === promise ? newDefer.promise() : this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ } );
+ } );
+ fns = null;
+ } ).promise();
+ },
+
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[ 1 ] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add( function() {
+
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[ 0 ] ] = function() {
+ deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+ } );
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 ||
+ ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred.
+ // If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // Add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .progress( updateFunc( i, progressContexts, progressValues ) )
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // If we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+} );
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+};
+
+jQuery.extend( {
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ jQuery( document ).off( "ready" );
+ }
+ }
+} );
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+}
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called
+ // after the browser event has already occurred.
+ // Support: IE9-10 only
+ // Older IE sometimes signals "interactive" too soon
+ if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+ } else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Kick off the DOM ready check even if the user does not
+jQuery.ready.promise();
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ access( elems, fn, i, key[ i ], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ /* jshint -W018 */
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+
+
+function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+
+Data.prototype = {
+
+ register: function( owner, initial ) {
+ var value = initial || {};
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable, non-writable property
+ // configurability must be true to allow the property to be
+ // deleted with the delete operator
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ writable: true,
+ configurable: true
+ } );
+ }
+ return owner[ this.expando ];
+ },
+ cache: function( owner ) {
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( !acceptData( owner ) ) {
+ return {};
+ }
+
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
+
+ // If not, create one
+ if ( !value ) {
+ value = {};
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
+
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+
+ // Handle: [ owner, key, value ] args
+ if ( typeof data === "string" ) {
+ cache[ data ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ prop ] = data[ prop ];
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
+ owner[ this.expando ] && owner[ this.expando ][ key ];
+ },
+ access: function( owner, key, value ) {
+ var stored;
+
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ( ( key && typeof key === "string" ) && value === undefined ) ) {
+
+ stored = this.get( owner, key );
+
+ return stored !== undefined ?
+ stored : this.get( owner, jQuery.camelCase( key ) );
+ }
+
+ // When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
+
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i, name, camel,
+ cache = owner[ this.expando ];
+
+ if ( cache === undefined ) {
+ return;
+ }
+
+ if ( key === undefined ) {
+ this.register( owner );
+
+ } else {
+
+ // Support array or space separated string of keys
+ if ( jQuery.isArray( key ) ) {
+
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = key.concat( key.map( jQuery.camelCase ) );
+ } else {
+ camel = jQuery.camelCase( key );
+
+ // Try the string as a key before any manipulation
+ if ( key in cache ) {
+ name = [ key, camel ];
+ } else {
+
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ name = camel;
+ name = name in cache ?
+ [ name ] : ( name.match( rnotwhite ) || [] );
+ }
+ }
+
+ i = name.length;
+
+ while ( i-- ) {
+ delete cache[ name[ i ] ];
+ }
+ }
+
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+ // Support: Chrome <= 35-45+
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://code.google.com/p/chromium/issues/detail?id=378607
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
+ }
+};
+var dataPriv = new Data();
+
+var dataUser = new Data();
+
+
+
+// Implementation Summary
+//
+// 1. Enforce API surface and semantic compatibility with 1.9.x branch
+// 2. Improve the module's maintainability by reducing the storage
+// paths to a single mechanism.
+// 3. Use the same single mechanism to support "private" and "user" data.
+// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+// 5. Avoid exposing implementation details on user objects (eg. expando properties)
+// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
+
+function dataAttr( elem, key, data ) {
+ var name;
+
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch ( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+}
+
+jQuery.extend( {
+ hasData: function( elem ) {
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return dataUser.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ dataUser.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return dataPriv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ dataPriv.remove( elem, name );
+ }
+} );
+
+jQuery.fn.extend( {
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[ 0 ],
+ attrs = elem && elem.attributes;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = dataUser.get( elem );
+
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE11+
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice( 5 ) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ dataPriv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
+ }
+
+ return access( this, function( value ) {
+ var data, camelKey;
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+
+ // Attempt to get data from the cache
+ // with the key as-is
+ data = dataUser.get( elem, key ) ||
+
+ // Try to find dashed key if it exists (gh-2779)
+ // This is for 2.2.x only
+ dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );
+
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ camelKey = jQuery.camelCase( key );
+
+ // Attempt to get data from the cache
+ // with the key camelized
+ data = dataUser.get( elem, camelKey );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, camelKey, undefined );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
+
+ // Set the data...
+ camelKey = jQuery.camelCase( key );
+ this.each( function() {
+
+ // First, attempt to store a copy or reference of any
+ // data that might've been store with a camelCased key.
+ var data = dataUser.get( this, camelKey );
+
+ // For HTML5 data-* attribute interop, we have to
+ // store property names with dashes in a camelCase form.
+ // This might not apply to all properties...*
+ dataUser.set( this, camelKey, value );
+
+ // *... In the case of properties that might _actually_
+ // have dashes, we need to also store a copy of that
+ // unchanged property.
+ if ( key.indexOf( "-" ) > -1 && data !== undefined ) {
+ dataUser.set( this, key, value );
+ }
+ } );
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
+ }
+} );
+
+
+jQuery.extend( {
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = dataPriv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray( data ) ) {
+ queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // Clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // Not public - generate a queueHooks object, or return the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.remove( elem, [ type + "queue", key ] );
+ } )
+ } );
+ }
+} );
+
+jQuery.fn.extend( {
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[ 0 ], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each( function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // Ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ dequeue: function( type ) {
+ return this.each( function() {
+ jQuery.dequeue( this, type );
+ } );
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" ||
+ !jQuery.contains( elem.ownerDocument, elem );
+ };
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() { return tween.cur(); } :
+ function() { return jQuery.css( elem, prop, "" ); },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
+ }
+ }
+ return adjusted;
+}
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+var rtagName = ( /<([\w:-]+)/ );
+
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+ // Support: IE9
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ _default: [ 0, "", "" ]
+};
+
+// Support: IE9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+ // Support: IE9-11+
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== "undefined" ?
+ context.querySelectorAll( tag || "*" ) :
+ [];
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], ret ) :
+ ret;
+}
+
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
+ }
+}
+
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
+
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( ( elem = tmp[ j++ ] ) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ return fragment;
+}
+
+
+( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0-4.3, Safari<=5.1
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Safari<=5.1, Android<4.2
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<=11+
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+
+
+var
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+// Support: IE9
+// See #13393 for more info
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+function on( elem, types, selector, data, fn, one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ if ( data == null && fn == null ) {
+
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return elem;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.get( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !( events = elemData.events ) ) {
+ events = elemData.events = {};
+ }
+ if ( !( eventHandle = elemData.handle ) ) {
+ eventHandle = elemData.handle = function( e ) {
+
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+ };
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend( {
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join( "." )
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !( handlers = events[ type ] ) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup ||
+ special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[ 2 ] &&
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector ||
+ selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown ||
+ special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove data and the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ dataPriv.remove( elem, "handle events" );
+ }
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, j, ret, matched, handleObj,
+ handlerQueue = [],
+ args = slice.call( arguments ),
+ handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[ 0 ] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( ( handleObj = matched.handlers[ j++ ] ) &&
+ !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or 2) have namespace(s)
+ // a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+ handleObj.handler ).apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( ( event.result = ret ) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var i, matches, sel, handleObj,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Support (at least): Chrome, IE9
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ //
+ // Support: Firefox<=42+
+ // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
+ if ( delegateCount && cur.nodeType &&
+ ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) > -1 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push( { elem: cur, handlers: matches } );
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
+ }
+
+ return handlerQueue;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
+ "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split( " " ),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
+ "screenX screenY toElement" ).split( " " ),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX +
+ ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
+ ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY +
+ ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
+ ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: Cordova 2.5 (WebKit) (#13255)
+ // All events should have a target; Cordova deviceready doesn't
+ if ( !event.target ) {
+ event.target = document;
+ }
+
+ // Support: Safari 6.0+, Chrome<28
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ load: {
+
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ this.focus();
+ return false;
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return jQuery.nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ }
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+};
+
+jQuery.Event = function( src, props ) {
+
+ // Allow instantiation without the 'new' keyword
+ if ( !( this instanceof jQuery.Event ) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+
+ // Support: Android<4.0
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ constructor: jQuery.Event,
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://code.google.com/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mouseenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+} );
+
+jQuery.fn.extend( {
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
+ },
+ one: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ?
+ handleObj.origType + "." + handleObj.namespace :
+ handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each( function() {
+ jQuery.event.remove( this, types, fn, selector );
+ } );
+ }
+} );
+
+
+var
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
+
+ // Support: IE 10-11, Edge 10240+
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
+
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+ return jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+ elem.getElementsByTagName( "tbody" )[ 0 ] ||
+ elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
+ elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+
+ if ( match ) {
+ elem.type = match[ 1 ];
+ } else {
+ elem.removeAttribute( "type" );
+ }
+
+ return elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // 1. Copy private data: events, handlers, etc.
+ if ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.set( dest, pdataOld );
+ events = pdataOld.events;
+
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+ }
+
+ // 2. Copy user data
+ if ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
+ }
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
+
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+function domManip( collection, args, callback, ignored ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
+ }
+
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item
+ // instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+
+ // Support: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( collection[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collection;
+}
+
+function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
+
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
+
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
+ }
+ }
+
+ return elem;
+}
+
+jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+ !jQuery.isXMLDoc( elem ) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ // Return the cloned set
+ return clone;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Support: Chrome <= 35-45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
+
+ // Support: Chrome <= 35-45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
+ }
+ }
+ }
+ }
+} );
+
+jQuery.fn.extend( {
+
+ // Keep domManip exposed until 3.0 (gh-2225)
+ domManip: domManip,
+
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
+
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ } );
+ },
+
+ prepend: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ } );
+ },
+
+ before: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ } );
+ },
+
+ after: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ } );
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; ( elem = this[ i ] ) != null; i++ ) {
+ if ( elem.nodeType === 1 ) {
+
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
+
+ // Remove any remaining nodes
+ elem.textContent = "";
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ } );
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+ value = jQuery.htmlPrefilter( value );
+
+ try {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch ( e ) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var ignored = [];
+
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
+
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
+ }
+ }
+
+ // Force callback invocation
+ }, ignored );
+ }
+} );
+
+jQuery.each( {
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1,
+ i = 0;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
+
+ // Support: QtWebKit
+ // .get() because push.apply(_, arraylike) throws
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+} );
+
+
+var iframe,
+ elemdisplay = {
+
+ // Support: Firefox
+ // We have to pre-define these values for FF (#10227)
+ HTML: "block",
+ BODY: "block"
+ };
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+ display = jQuery.css( elem[ 0 ], "display" );
+
+ // We don't have any data stored on the element,
+ // so use "detach" method as fast way to get rid of the element
+ elem.detach();
+
+ return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+
+ // Use the already-created iframe if possible
+ iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
+ .appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = iframe[ 0 ].contentDocument;
+
+ // Support: IE
+ doc.write();
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+var rmargin = ( /^margin/ );
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+
+ // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
+
+ if ( !view || !view.opener ) {
+ view = window;
+ }
+
+ return view.getComputedStyle( elem );
+ };
+
+var swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+
+var documentElement = document.documentElement;
+
+
+
+( function() {
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
+
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
+
+ // Support: IE9-11+
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
+
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
+ div.style.cssText =
+
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
+
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
+
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
+
+ documentElement.removeChild( container );
+ }
+
+ jQuery.extend( support, {
+ pixelPosition: function() {
+
+ // This test is executed only once but we still do memoizing
+ // since we can use the boxSizingReliable pre-computing.
+ // No need to check if the test was already performed, though.
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+
+ // Support: Android 4.0-4.3
+ // We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
+ // since that compresses better and they're computed together anyway.
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+
+ // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return reliableMarginLeftVal;
+ },
+ reliableMarginRight: function() {
+
+ // Support: Android 2.3
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // This support function is only executed once so no memoizing is needed.
+ var ret,
+ marginDiv = div.appendChild( document.createElement( "div" ) );
+
+ // Reset CSS: box-sizing; display; margin; border; padding
+ marginDiv.style.cssText = div.style.cssText =
+
+ // Support: Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;box-sizing:content-box;" +
+ "display:block;margin:0;border:0;padding:0";
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+ documentElement.appendChild( container );
+
+ ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );
+
+ documentElement.removeChild( container );
+ div.removeChild( marginDiv );
+
+ return ret;
+ }
+ } );
+} )();
+
+
+function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+ // Support: Opera 12.1x only
+ // Fall back to style even without computed
+ // computed is undefined for elems on document fragments
+ if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // Support: IE9
+ // getPropertyValue is only needed for .css('filter') (#12537)
+ if ( computed ) {
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret !== undefined ?
+
+ // Support: IE9-11+
+ // IE returns zIndex value as an integer.
+ ret + "" :
+ ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ if ( conditionFn() ) {
+
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+ return ( this.get = hookFn ).apply( this, arguments );
+ }
+ };
+}
+
+
+var
+
+ // Swappable if display is none or starts with table
+ // except "table", "table-cell", or "table-caption"
+ // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
+
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
+ return name;
+ }
+
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in emptyStyle ) {
+ return name;
+ }
+ }
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
+ return matches ?
+
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+
+ // Both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // At this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+
+ // At this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // At this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // Some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test( val ) ) {
+ return val;
+ }
+
+ // Check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // Use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = dataPriv.get( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = dataPriv.access(
+ elem,
+ "olddisplay",
+ defaultDisplay( elem.nodeName )
+ );
+ }
+ } else {
+ hidden = isHidden( elem );
+
+ if ( display !== "none" || !hidden ) {
+ dataPriv.set(
+ elem,
+ "olddisplay",
+ hidden ? display : jQuery.css( elem, "display" )
+ );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.extend( {
+
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "animationIterationCount": true,
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ "float": "cssFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+ // Gets hook for the prefixed version, then unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set (#7116)
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+ }
+
+ // Support: IE9-11+
+ // background-* props affect original clone's values
+ if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !( "set" in hooks ) ||
+ ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
+
+ style[ name ] = value;
+ }
+
+ } else {
+
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks &&
+ ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+ // Try prefixed name followed by the unprefixed name
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ // Convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Make numeric if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || isFinite( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+} );
+
+jQuery.each( [ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+
+ // Certain elements can have dimension info if we invisibly show them
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+ elem.offsetWidth === 0 ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ );
+
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
+
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
+ }
+
+ return setPositiveNumber( elem, value, subtract );
+ }
+ };
+} );
+
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+ function( elem, computed ) {
+ if ( computed ) {
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
+ }
+ }
+);
+
+// Support: Android 2.3
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+ function( elem, computed ) {
+ if ( computed ) {
+ return swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each( {
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // Assumes a single number if not a string
+ parts = typeof value === "string" ? value.split( " " ) : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+} );
+
+jQuery.fn.extend( {
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each( function() {
+ if ( isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ } );
+ }
+} );
+
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || jQuery.easing._default;
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // Passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails.
+ // Simple values such as "10px" are parsed to Float;
+ // complex values such as "rotate(1rad)" are returned as-is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+
+ // Use step hook for back compat.
+ // Use cssHook if its there.
+ // Use .style if available and use plain properties where available.
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.nodeType === 1 &&
+ ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+ jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE9
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ },
+ _default: "swing"
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rrun = /queueHooks$/;
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ window.setTimeout( function() {
+ fxNow = undefined;
+ } );
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ i = 0,
+ attrs = { height: type };
+
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
+
+ // We're done with this property
+ return tween;
+ }
+ }
+}
+
+function defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = dataPriv.get( elem, "fxshow" );
+
+ // Handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always( function() {
+
+ // Ensure the complete handler is called before this completes
+ anim.always( function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ } );
+ } );
+ }
+
+ // Height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE9-10 do not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ display = jQuery.css( elem, "display" );
+
+ // Test default display if display is currently "none"
+ checkDisplay = display === "none" ?
+ dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+ if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+ style.display = "inline-block";
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always( function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ } );
+ }
+
+ // show/hide pass
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // If there is dataShow left over from a stopped hide or show
+ // and we are going to proceed with show, we should pretend to be hidden
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+ // Any non-fx value stops us from restoring the original display value
+ } else {
+ display = undefined;
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = dataPriv.access( elem, "fxshow", {} );
+ }
+
+ // Store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done( function() {
+ jQuery( elem ).hide();
+ } );
+ }
+ anim.done( function() {
+ var prop;
+
+ dataPriv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ } );
+ for ( prop in orig ) {
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+
+ // If this is a noop like .hide().hide(), restore an overwritten display value
+ } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
+ style.display = display;
+ }
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // Not quite $.extend, this won't overwrite existing keys.
+ // Reusing 'index' because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = Animation.prefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+
+ // Don't match elem in the :animated selector
+ delete tick.elem;
+ } ),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+
+ // Support: Android 2.3
+ // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ] );
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise( {
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, {
+ specialEasing: {},
+ easing: jQuery.easing._default
+ }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+
+ // If we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // Resolve when we played the last frame; otherwise, reject
+ if ( gotoEnd ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ } ),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, result );
+ }
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ } )
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.match( rnotwhite );
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilters: [ defaultPrefilter ],
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ Animation.prefilters.unshift( callback );
+ } else {
+ Animation.prefilters.push( callback );
+ }
+ }
+} );
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
+ opt.duration : opt.duration in jQuery.fx.speeds ?
+ jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // Normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.fn.extend( {
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // Show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // Animate to the value specified
+ .end().animate( { opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || dataPriv.get( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each( function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = dataPriv.get( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this &&
+ ( type == null || timers[ index ].queue === type ) ) {
+
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Start the next in the queue if the last step wasn't forced.
+ // Timers currently will call their complete callbacks, which
+ // will dequeue but only if they were gotoEnd.
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each( function() {
+ var index,
+ data = dataPriv.get( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // Enable finishing flag on private data
+ data.finish = true;
+
+ // Empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // Look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // Turn off finishing flag
+ delete data.finish;
+ } );
+ }
+} );
+
+jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+} );
+
+// Generate shortcuts for custom animations
+jQuery.each( {
+ slideDown: genFx( "show" ),
+ slideUp: genFx( "hide" ),
+ slideToggle: genFx( "toggle" ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+} );
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ i = 0,
+ timers = jQuery.timers;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ if ( timer() ) {
+ jQuery.fx.start();
+ } else {
+ jQuery.timers.pop();
+ }
+};
+
+jQuery.fx.interval = 13;
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ window.clearInterval( timerId );
+
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = window.setTimeout( next, time );
+ hooks.stop = function() {
+ window.clearTimeout( timeout );
+ };
+ } );
+};
+
+
+( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
+
+ input.type = "checkbox";
+
+ // Support: iOS<=5.1, Android<=4.2+
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
+
+ // Support: IE<=11+
+ // Must access selectedIndex to make default options select
+ support.optSelected = opt.selected;
+
+ // Support: Android<=2.3
+ // Options inside disabled selects are incorrectly marked as disabled
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<=11+
+ // An input loses its value after becoming a radio
+ input = document.createElement( "input" );
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+} )();
+
+
+var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend( {
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each( function() {
+ jQuery.removeAttr( this, name );
+ } );
+ }
+} );
+
+jQuery.extend( {
+ attr: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
+ }
+
+ if ( value !== undefined ) {
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+ }
+
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" &&
+ jQuery.nodeName( elem, "input" ) ) {
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( ( name = attrNames[ i++ ] ) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( jQuery.expr.match.bool.test( name ) ) {
+
+ // Set corresponding property to false
+ elem[ propName ] = false;
+ }
+
+ elem.removeAttribute( name );
+ }
+ }
+ }
+} );
+
+// Hooks for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ elem.setAttribute( name, name );
+ }
+ return name;
+ }
+};
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle;
+ if ( !isXML ) {
+
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ name ];
+ attrHandle[ name ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ name.toLowerCase() :
+ null;
+ attrHandle[ name ] = handle;
+ }
+ return ret;
+ };
+} );
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend( {
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
+ }
+} );
+
+jQuery.extend( {
+ prop: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ return ( elem[ name ] = value );
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ return tabindex ?
+ parseInt( tabindex, 10 ) :
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+} );
+
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+ };
+}
+
+jQuery.each( [
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+} );
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
+ addClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).toggleClass(
+ value.call( this, i, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
+ }
+
+ return this.each( function() {
+ var className, i, self, classNames;
+
+ if ( type === "string" ) {
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( rnotwhite ) || [];
+
+ while ( ( className = classNames[ i++ ] ) ) {
+
+ // Check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", className );
+ }
+
+ // If the element has a class name or if we're passed `false`,
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
+ }
+ } );
+ },
+
+ hasClass: function( selector ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + getClass( elem ) + " " ).replace( rclass, " " )
+ .indexOf( className ) > -1
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} );
+
+
+
+
+var rreturn = /\r/g,
+ rspaces = /[\x20\t\r\n\f]+/g;
+
+jQuery.fn.extend( {
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[ 0 ];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] ||
+ jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks &&
+ "get" in hooks &&
+ ( ret = hooks.get( elem, "value" ) ) !== undefined
+ ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+
+ // Handle most common string cases
+ ret.replace( rreturn, "" ) :
+
+ // Handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each( function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+
+ } else if ( typeof val === "number" ) {
+ val += "";
+
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ } );
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ } );
+ }
+} );
+
+jQuery.extend( {
+ valHooks: {
+ option: {
+ get: function( elem ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE10-11+
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // IE8-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+
+ // Don't return options that are disabled or in a disabled optgroup
+ ( support.optDisabled ?
+ !option.disabled : option.getAttribute( "disabled" ) === null ) &&
+ ( !option.parentNode.disabled ||
+ !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+ if ( option.selected =
+ jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+} );
+
+// Radios and checkboxes getter/setter
+jQuery.each( [ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+} );
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "." ) > -1 ) {
+
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split( "." );
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join( "." );
+ event.rnamespace = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === ( elem.ownerDocument || document ) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( ( !special._default ||
+ special._default.apply( eventPath.pop(), data ) === false ) &&
+ acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+} );
+
+jQuery.fn.extend( {
+
+ trigger: function( type, data ) {
+ return this.each( function() {
+ jQuery.event.trigger( type, data, this );
+ } );
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[ 0 ];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+} );
+
+
+jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu" ).split( " " ),
+ function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+} );
+
+jQuery.fn.extend( {
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+} );
+
+
+
+
+support.focusin = "onfocusin" in window;
+
+
+// Support: Firefox
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome, Safari
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
+
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+}
+var location = window.location;
+
+var nonce = jQuery.now();
+
+var rquery = ( /\?/ );
+
+
+
+// Support: Android 2.3
+// Workaround failure to string-cast null input
+jQuery.parseJSON = function( data ) {
+ return JSON.parse( data + "" );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE9
+ try {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat( "*" ),
+
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+
+ // For each dataType in the dataTypeExpression
+ while ( ( dataType = dataTypes[ i++ ] ) ) {
+
+ // Prepend if requested
+ if ( dataType[ 0 ] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
+
+ // Otherwise append
+ } else {
+ ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" &&
+ !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ } );
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var ct, type, finalDataType, firstDataType,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s.throws ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return {
+ state: "parsererror",
+ error: conv ? e : "No conversion from " + prev + " to " + current
+ };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+
+jQuery.extend( {
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: location.href,
+ type: "GET",
+ isLocal: rlocalProtocol.test( location.protocol ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var transport,
+
+ // URL without anti-cache param
+ cacheURL,
+
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+
+ // timeout handle
+ timeoutTimer,
+
+ // Url cleanup var
+ urlAnchor,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ // Loop variable
+ i,
+
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+
+ // Callbacks context
+ callbackContext = s.context || s,
+
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context &&
+ ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+
+ // The jqXHR state
+ state = 0,
+
+ // Default abort message
+ strAbort = "canceled",
+
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (prefilters might expect it)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
+ .replace( rprotocol, location.protocol + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+ // A cross-domain request is in order when the origin doesn't match the current origin.
+ if ( s.crossDomain == null ) {
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE8-11+
+ // IE throws exception if url is malformed, e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE8-11+
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] +
+ ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend &&
+ ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // Aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = window.setTimeout( function() {
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ window.clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader( "Last-Modified" );
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader( "etag" );
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+
+ // Extract error from statusText and normalize for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+} );
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+
+ // Shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ }, jQuery.isPlainObject( url ) && url ) );
+ };
+} );
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax( {
+ url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ } );
+};
+
+
+jQuery.fn.extend( {
+ wrapAll: function( html ) {
+ var wrap;
+
+ if ( jQuery.isFunction( html ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( html.call( this, i ) );
+ } );
+ }
+
+ if ( this[ 0 ] ) {
+
+ // The elements to wrap the target around
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
+ }
+
+ wrap.map( function() {
+ var elem = this;
+
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
+ }
+
+ return elem;
+ } ).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).wrapInner( html.call( this, i ) );
+ } );
+ }
+
+ return this.each( function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ } );
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+ } );
+ },
+
+ unwrap: function() {
+ return this.parent().each( function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ } ).end();
+ }
+} );
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+ return !jQuery.expr.filters.visible( elem );
+};
+jQuery.expr.filters.visible = function( elem ) {
+
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ // Use OR instead of AND as the element is not visible if either is true
+ // See tickets #10406 and #13132
+ return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
+};
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams(
+ prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+ v,
+ traditional,
+ add
+ );
+ }
+ } );
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ } );
+
+ } else {
+
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend( {
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map( function() {
+
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ } )
+ .filter( function() {
+ var type = this.type;
+
+ // Use .is( ":disabled" ) so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ } )
+ .map( function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ).get();
+ }
+} );
+
+
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
+};
+
+var xhrSuccessStatus = {
+
+ // File protocol always yields status code 0, assume 200
+ 0: 200,
+
+ // Support: IE9
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
+
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr();
+
+ xhr.open(
+ options.type,
+ options.url,
+ options.async,
+ options.username,
+ options.password
+ );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE9
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
+
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
+ }
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
+
+ // Support: IE9
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
+ }
+ };
+ }
+
+ // Create the abort callback
+ callback = callback( "abort" );
+
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
+ if ( callback ) {
+ throw e;
+ }
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup( {
+ accepts: {
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /\b(?:java|ecma)script\b/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+} );
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ }
+} );
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+ var script, callback;
+ return {
+ send: function( _, complete ) {
+ script = jQuery( "<script>" ).prop( {
+ charset: s.scriptCharset,
+ src: s.url
+ } ).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
+ }
+ }
+ );
+
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ document.head.appendChild( script[ 0 ] );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup( {
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+} );
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" &&
+ ( s.contentType || "" )
+ .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+ rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters[ "script json" ] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // Force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always( function() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+
+ // Make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // Save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ } );
+
+ // Delegate to script
+ return "script";
+ }
+} );
+
+
+
+
+// Argument "data" should be string of html
+// context (optional): If specified, the fragment will be created in this context,
+// defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[ 1 ] ) ];
+ }
+
+ parsed = buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, type, response,
+ self = this,
+ off = url.indexOf( " " );
+
+ if ( off > -1 ) {
+ selector = jQuery.trim( url.slice( off ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax( {
+ url: url,
+
+ // If "type" variable is undefined, then "GET" method will be used.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
+ dataType: "html",
+ data: params
+ } ).done( function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+ } );
+ } );
+ }
+
+ return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [
+ "ajaxStart",
+ "ajaxStop",
+ "ajaxComplete",
+ "ajaxError",
+ "ajaxSuccess",
+ "ajaxSend"
+], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+} );
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+};
+
+
+
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // Set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
+
+ // Need to be able to calculate position if either
+ // top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend( {
+ offset: function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each( function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ } );
+ }
+
+ var docElem, win,
+ elem = this[ 0 ],
+ box = { top: 0, left: 0 },
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ box = elem.getBoundingClientRect();
+ win = getWindow( doc );
+ return {
+ top: box.top + win.pageYOffset - docElem.clientTop,
+ left: box.left + win.pageXOffset - docElem.clientLeft
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
+
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+ // because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+ // Assume getBoundingClientRect is there when computed position is fixed
+ offset = elem.getBoundingClientRect();
+
+ } else {
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+ };
+ },
+
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
+ offsetParent: function() {
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
+
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || documentElement;
+ } );
+ }
+} );
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? win[ prop ] : elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : win.pageXOffset,
+ top ? val : win.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length );
+ };
+} );
+
+// Support: Safari<7-8+, Chrome<37-44+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+
+ // If curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+} );
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+ function( defaultExtra, funcName ) {
+
+ // Margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ } );
+} );
+
+
+jQuery.fn.extend( {
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ },
+ size: function() {
+ return this.length;
+ }
+} );
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ } );
+}
+
+
+
+var
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( !noGlobal ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+return jQuery;
+}));
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.js
new file mode 100644
index 00000000..4024b662
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c;
+}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0!==g?g+"":g}function Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ca(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Fa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ba.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Oa(a,b,c||(g?"border":"content"),d,f)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),
+void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b)}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m=n.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Hb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.map b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.map
new file mode 100644
index 00000000..49efa4b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/jquery/dist/jquery.min.map
@@ -0,0 +1 @@
+{"version":3,"sources":["jquery.js"],"names":["global","factory","module","exports","document","w","Error","window","this","noGlobal","arr","slice","concat","push","indexOf","class2type","toString","hasOwn","hasOwnProperty","support","version","jQuery","selector","context","fn","init","rtrim","rmsPrefix","rdashAlpha","fcamelCase","all","letter","toUpperCase","prototype","jquery","constructor","length","toArray","call","get","num","pushStack","elems","ret","merge","prevObject","each","callback","map","elem","i","apply","arguments","first","eq","last","len","j","end","sort","splice","extend","options","name","src","copy","copyIsArray","clone","target","deep","isFunction","isPlainObject","isArray","undefined","expando","Math","random","replace","isReady","error","msg","noop","obj","type","Array","isWindow","isNumeric","realStringObj","parseFloat","key","nodeType","isEmptyObject","globalEval","code","script","indirect","eval","trim","createElement","text","head","appendChild","parentNode","removeChild","camelCase","string","nodeName","toLowerCase","isArrayLike","makeArray","results","Object","inArray","second","grep","invert","callbackInverse","matches","callbackExpect","arg","value","guid","proxy","tmp","args","now","Date","Symbol","iterator","split","Sizzle","Expr","getText","isXML","tokenize","compile","select","outermostContext","sortInput","hasDuplicate","setDocument","docElem","documentIsHTML","rbuggyQSA","rbuggyMatches","contains","preferredDoc","dirruns","done","classCache","createCache","tokenCache","compilerCache","sortOrder","a","b","MAX_NEGATIVE","pop","push_native","list","booleans","whitespace","identifier","attributes","pseudos","rwhitespace","RegExp","rcomma","rcombinators","rattributeQuotes","rpseudo","ridentifier","matchExpr","ID","CLASS","TAG","ATTR","PSEUDO","CHILD","bool","needsContext","rinputs","rheader","rnative","rquickExpr","rsibling","rescape","runescape","funescape","_","escaped","escapedWhitespace","high","String","fromCharCode","unloadHandler","childNodes","e","els","seed","m","nid","nidselect","match","groups","newSelector","newContext","ownerDocument","exec","getElementById","id","getElementsByTagName","getElementsByClassName","qsa","test","getAttribute","setAttribute","toSelector","join","testContext","querySelectorAll","qsaError","removeAttribute","keys","cache","cacheLength","shift","markFunction","assert","div","addHandle","attrs","handler","attrHandle","siblingCheck","cur","diff","sourceIndex","nextSibling","createInputPseudo","createButtonPseudo","createPositionalPseudo","argument","matchIndexes","documentElement","node","hasCompare","parent","doc","defaultView","top","addEventListener","attachEvent","className","createComment","getById","getElementsByName","find","filter","attrId","getAttributeNode","tag","innerHTML","input","matchesSelector","webkitMatchesSelector","mozMatchesSelector","oMatchesSelector","msMatchesSelector","disconnectedMatch","compareDocumentPosition","adown","bup","compare","sortDetached","aup","ap","bp","unshift","expr","elements","attr","val","specified","uniqueSort","duplicates","detectDuplicates","sortStable","textContent","firstChild","nodeValue","selectors","createPseudo","relative",">","dir"," ","+","~","preFilter","excess","unquoted","nodeNameSelector","pattern","operator","check","result","what","simple","forward","ofType","xml","uniqueCache","outerCache","nodeIndex","start","useCache","lastChild","uniqueID","pseudo","setFilters","idx","matched","not","matcher","unmatched","has","innerText","lang","elemLang","hash","location","root","focus","activeElement","hasFocus","href","tabIndex","enabled","disabled","checked","selected","selectedIndex","empty","header","button","even","odd","lt","gt","radio","checkbox","file","password","image","submit","reset","filters","parseOnly","tokens","soFar","preFilters","cached","addCombinator","combinator","base","checkNonElements","doneName","oldCache","newCache","elementMatcher","matchers","multipleContexts","contexts","condense","newUnmatched","mapped","setMatcher","postFilter","postFinder","postSelector","temp","preMap","postMap","preexisting","matcherIn","matcherOut","matcherFromTokens","checkContext","leadingRelative","implicitRelative","matchContext","matchAnyContext","matcherFromGroupMatchers","elementMatchers","setMatchers","bySet","byElement","superMatcher","outermost","matchedCount","setMatched","contextBackup","dirrunsUnique","token","compiled","div1","defaultValue","unique","isXMLDoc","until","truncate","is","siblings","n","rneedsContext","rsingleTag","risSimple","winnow","qualifier","self","rootjQuery","parseHTML","ready","rparentsprev","guaranteedUnique","children","contents","next","prev","targets","l","closest","pos","index","prevAll","add","addBack","sibling","parents","parentsUntil","nextAll","nextUntil","prevUntil","contentDocument","reverse","rnotwhite","createOptions","object","flag","Callbacks","firing","memory","fired","locked","queue","firingIndex","fire","once","stopOnFalse","remove","disable","lock","fireWith","Deferred","func","tuples","state","promise","always","deferred","fail","then","fns","newDefer","tuple","returned","progress","notify","resolve","reject","pipe","stateString","when","subordinate","resolveValues","remaining","updateFunc","values","progressValues","notifyWith","resolveWith","progressContexts","resolveContexts","readyList","readyWait","holdReady","hold","wait","triggerHandler","off","completed","removeEventListener","readyState","doScroll","setTimeout","access","chainable","emptyGet","raw","bulk","acceptData","owner","Data","uid","register","initial","defineProperty","writable","configurable","set","data","prop","stored","camel","hasData","dataPriv","dataUser","rbrace","rmultiDash","dataAttr","parseJSON","removeData","_data","_removeData","camelKey","dequeue","startLength","hooks","_queueHooks","stop","setter","clearQueue","count","defer","pnum","source","rcssNum","cssExpand","isHidden","el","css","adjustCSS","valueParts","tween","adjusted","scale","maxIterations","currentValue","unit","cssNumber","initialInUnit","style","rcheckableType","rtagName","rscriptType","wrapMap","option","thead","col","tr","td","_default","optgroup","tbody","tfoot","colgroup","caption","th","getAll","setGlobalEval","refElements","rhtml","buildFragment","scripts","selection","ignored","wrap","fragment","createDocumentFragment","nodes","htmlPrefilter","createTextNode","checkClone","cloneNode","noCloneChecked","rkeyEvent","rmouseEvent","rtypenamespace","returnTrue","returnFalse","safeActiveElement","err","on","types","one","origFn","event","handleObjIn","eventHandle","events","t","handleObj","special","handlers","namespaces","origType","elemData","handle","triggered","dispatch","delegateType","bindType","namespace","delegateCount","setup","mappedTypes","origCount","teardown","removeEvent","fix","handlerQueue","delegateTarget","preDispatch","isPropagationStopped","currentTarget","isImmediatePropagationStopped","rnamespace","preventDefault","stopPropagation","postDispatch","sel","isNaN","props","fixHooks","keyHooks","original","which","charCode","keyCode","mouseHooks","eventDoc","body","pageX","clientX","scrollLeft","clientLeft","pageY","clientY","scrollTop","clientTop","originalEvent","fixHook","Event","load","noBubble","trigger","blur","click","beforeunload","returnValue","isDefaultPrevented","defaultPrevented","timeStamp","isSimulated","stopImmediatePropagation","mouseenter","mouseleave","pointerenter","pointerleave","orig","related","relatedTarget","rxhtmlTag","rnoInnerhtml","rchecked","rscriptTypeMasked","rcleanScript","manipulationTarget","content","disableScript","restoreScript","cloneCopyEvent","dest","pdataOld","pdataCur","udataOld","udataCur","fixInput","domManip","collection","hasScripts","iNoClone","html","_evalUrl","keepData","cleanData","dataAndEvents","deepDataAndEvents","srcElements","destElements","inPage","detach","append","prepend","insertBefore","before","after","replaceWith","replaceChild","appendTo","prependTo","insertAfter","replaceAll","insert","iframe","elemdisplay","HTML","BODY","actualDisplay","display","defaultDisplay","write","close","rmargin","rnumnonpx","getStyles","view","opener","getComputedStyle","swap","old","pixelPositionVal","boxSizingReliableVal","pixelMarginRightVal","reliableMarginLeftVal","container","backgroundClip","clearCloneStyle","cssText","computeStyleTests","divStyle","marginLeft","width","marginRight","pixelPosition","boxSizingReliable","pixelMarginRight","reliableMarginLeft","reliableMarginRight","marginDiv","curCSS","computed","minWidth","maxWidth","getPropertyValue","addGetHookIf","conditionFn","hookFn","rdisplayswap","cssShow","position","visibility","cssNormalTransform","letterSpacing","fontWeight","cssPrefixes","emptyStyle","vendorPropName","capName","setPositiveNumber","subtract","max","augmentWidthOrHeight","extra","isBorderBox","styles","getWidthOrHeight","valueIsBorderBox","offsetWidth","offsetHeight","showHide","show","hidden","cssHooks","opacity","animationIterationCount","columnCount","fillOpacity","flexGrow","flexShrink","lineHeight","order","orphans","widows","zIndex","zoom","cssProps","float","origName","isFinite","getBoundingClientRect","left","margin","padding","border","prefix","suffix","expand","expanded","parts","hide","toggle","Tween","easing","propHooks","run","percent","eased","duration","step","fx","linear","p","swing","cos","PI","fxNow","timerId","rfxtypes","rrun","createFxNow","genFx","includeWidth","height","createTween","animation","Animation","tweeners","defaultPrefilter","opts","oldfire","checkDisplay","anim","dataShow","unqueued","overflow","overflowX","overflowY","propFilter","specialEasing","properties","stopped","prefilters","tick","currentTime","startTime","tweens","originalProperties","originalOptions","gotoEnd","rejectWith","timer","complete","*","tweener","prefilter","speed","opt","speeds","fadeTo","to","animate","optall","doAnimation","finish","stopQueue","timers","cssFn","slideDown","slideUp","slideToggle","fadeIn","fadeOut","fadeToggle","interval","setInterval","clearInterval","slow","fast","delay","time","timeout","clearTimeout","checkOn","optSelected","optDisabled","radioValue","boolHook","removeAttr","nType","attrHooks","propName","attrNames","propFix","getter","rfocusable","rclickable","removeProp","tabindex","parseInt","for","class","rclass","getClass","addClass","classes","curValue","clazz","finalValue","removeClass","toggleClass","stateVal","classNames","hasClass","rreturn","rspaces","valHooks","optionSet","rfocusMorph","onlyHandlers","bubbleType","ontype","eventPath","isTrigger","parentWindow","simulate","hover","fnOver","fnOut","focusin","attaches","nonce","rquery","JSON","parse","parseXML","DOMParser","parseFromString","rhash","rts","rheaders","rlocalProtocol","rnoContent","rprotocol","transports","allTypes","originAnchor","addToPrefiltersOrTransports","structure","dataTypeExpression","dataType","dataTypes","inspectPrefiltersOrTransports","jqXHR","inspected","seekingTransport","inspect","prefilterOrFactory","dataTypeOrTransport","ajaxExtend","flatOptions","ajaxSettings","ajaxHandleResponses","s","responses","ct","finalDataType","firstDataType","mimeType","getResponseHeader","converters","ajaxConvert","response","isSuccess","conv2","current","conv","responseFields","dataFilter","active","lastModified","etag","url","isLocal","protocol","processData","async","contentType","accepts","json","* text","text html","text json","text xml","ajaxSetup","settings","ajaxPrefilter","ajaxTransport","ajax","transport","cacheURL","responseHeadersString","responseHeaders","timeoutTimer","urlAnchor","fireGlobals","callbackContext","globalEventContext","completeDeferred","statusCode","requestHeaders","requestHeadersNames","strAbort","getAllResponseHeaders","setRequestHeader","lname","overrideMimeType","status","abort","statusText","finalText","success","method","crossDomain","host","param","traditional","hasContent","ifModified","headers","beforeSend","send","nativeStatusText","modified","getJSON","getScript","throws","wrapAll","firstElementChild","wrapInner","unwrap","visible","getClientRects","r20","rbracket","rCRLF","rsubmitterTypes","rsubmittable","buildParams","v","encodeURIComponent","serialize","serializeArray","xhr","XMLHttpRequest","xhrSuccessStatus","0","1223","xhrSupported","cors","errorCallback","open","username","xhrFields","onload","onerror","onabort","onreadystatechange","responseType","responseText","binary","text script","charset","scriptCharset","evt","oldCallbacks","rjsonp","jsonp","jsonpCallback","originalSettings","callbackName","overwritten","responseContainer","jsonProp","keepScripts","parsed","_load","params","animated","getWindow","offset","setOffset","curPosition","curLeft","curCSSTop","curTop","curOffset","curCSSLeft","calculatePosition","curElem","using","win","box","pageYOffset","pageXOffset","offsetParent","parentOffset","scrollTo","Height","Width","","defaultExtra","funcName","bind","unbind","delegate","undelegate","size","andSelf","define","amd","_jQuery","_$","$","noConflict"],"mappings":"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","file":"jquery.min.js"} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.css
new file mode 100644
index 00000000..12325502
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.css
@@ -0,0 +1,478 @@
+/* required styles */
+
+.leaflet-map-pane,
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow,
+.leaflet-tile-pane,
+.leaflet-tile-container,
+.leaflet-overlay-pane,
+.leaflet-shadow-pane,
+.leaflet-marker-pane,
+.leaflet-popup-pane,
+.leaflet-overlay-pane svg,
+.leaflet-zoom-box,
+.leaflet-image-layer,
+.leaflet-layer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ }
+.leaflet-container {
+ overflow: hidden;
+ -ms-touch-action: none;
+ }
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ -webkit-user-drag: none;
+ }
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+ display: block;
+ }
+/* map is broken in FF if you have max-width: 100% on tiles */
+.leaflet-container img {
+ max-width: none !important;
+ }
+/* stupid Android 2 doesn't understand "max-width: none" properly */
+.leaflet-container img.leaflet-image-layer {
+ max-width: 15000px !important;
+ }
+.leaflet-tile {
+ filter: inherit;
+ visibility: hidden;
+ }
+.leaflet-tile-loaded {
+ visibility: inherit;
+ }
+.leaflet-zoom-box {
+ width: 0;
+ height: 0;
+ }
+/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
+.leaflet-overlay-pane svg {
+ -moz-user-select: none;
+ }
+
+.leaflet-tile-pane { z-index: 2; }
+.leaflet-objects-pane { z-index: 3; }
+.leaflet-overlay-pane { z-index: 4; }
+.leaflet-shadow-pane { z-index: 5; }
+.leaflet-marker-pane { z-index: 6; }
+.leaflet-popup-pane { z-index: 7; }
+
+.leaflet-vml-shape {
+ width: 1px;
+ height: 1px;
+ }
+.lvml {
+ behavior: url(#default#VML);
+ display: inline-block;
+ position: absolute;
+ }
+
+
+/* control positioning */
+
+.leaflet-control {
+ position: relative;
+ z-index: 7;
+ pointer-events: auto;
+ }
+.leaflet-top,
+.leaflet-bottom {
+ position: absolute;
+ z-index: 1000;
+ pointer-events: none;
+ }
+.leaflet-top {
+ top: 0;
+ }
+.leaflet-right {
+ right: 0;
+ }
+.leaflet-bottom {
+ bottom: 0;
+ }
+.leaflet-left {
+ left: 0;
+ }
+.leaflet-control {
+ float: left;
+ clear: both;
+ }
+.leaflet-right .leaflet-control {
+ float: right;
+ }
+.leaflet-top .leaflet-control {
+ margin-top: 10px;
+ }
+.leaflet-bottom .leaflet-control {
+ margin-bottom: 10px;
+ }
+.leaflet-left .leaflet-control {
+ margin-left: 10px;
+ }
+.leaflet-right .leaflet-control {
+ margin-right: 10px;
+ }
+
+
+/* zoom and fade animations */
+
+.leaflet-fade-anim .leaflet-tile,
+.leaflet-fade-anim .leaflet-popup {
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+ }
+.leaflet-fade-anim .leaflet-tile-loaded,
+.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
+ opacity: 1;
+ }
+
+.leaflet-zoom-anim .leaflet-zoom-animated {
+ -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
+ -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
+ -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
+ transition: transform 0.25s cubic-bezier(0,0,0.25,1);
+ }
+.leaflet-zoom-anim .leaflet-tile,
+.leaflet-pan-anim .leaflet-tile,
+.leaflet-touching .leaflet-zoom-animated {
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+ }
+
+.leaflet-zoom-anim .leaflet-zoom-hide {
+ visibility: hidden;
+ }
+
+
+/* cursors */
+
+.leaflet-clickable {
+ cursor: pointer;
+ }
+.leaflet-container {
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ }
+.leaflet-popup-pane,
+.leaflet-control {
+ cursor: auto;
+ }
+.leaflet-dragging .leaflet-container,
+.leaflet-dragging .leaflet-clickable {
+ cursor: move;
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ }
+
+
+/* visual tweaks */
+
+.leaflet-container {
+ background: #ddd;
+ outline: 0;
+ }
+.leaflet-container a {
+ color: #0078A8;
+ }
+.leaflet-container a.leaflet-active {
+ outline: 2px solid orange;
+ }
+.leaflet-zoom-box {
+ border: 2px dotted #38f;
+ background: rgba(255,255,255,0.5);
+ }
+
+
+/* general typography */
+.leaflet-container {
+ font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
+ }
+
+
+/* general toolbar styles */
+
+.leaflet-bar {
+ box-shadow: 0 1px 5px rgba(0,0,0,0.65);
+ border-radius: 4px;
+ }
+.leaflet-bar a,
+.leaflet-bar a:hover {
+ background-color: #fff;
+ border-bottom: 1px solid #ccc;
+ width: 26px;
+ height: 26px;
+ line-height: 26px;
+ display: block;
+ text-align: center;
+ text-decoration: none;
+ color: black;
+ }
+.leaflet-bar a,
+.leaflet-control-layers-toggle {
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ display: block;
+ }
+.leaflet-bar a:hover {
+ background-color: #f4f4f4;
+ }
+.leaflet-bar a:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+.leaflet-bar a:last-child {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-bottom: none;
+ }
+.leaflet-bar a.leaflet-disabled {
+ cursor: default;
+ background-color: #f4f4f4;
+ color: #bbb;
+ }
+
+.leaflet-touch .leaflet-bar a {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+ }
+
+
+/* zoom control */
+
+.leaflet-control-zoom-in,
+.leaflet-control-zoom-out {
+ font: bold 18px 'Lucida Console', Monaco, monospace;
+ text-indent: 1px;
+ }
+.leaflet-control-zoom-out {
+ font-size: 20px;
+ }
+
+.leaflet-touch .leaflet-control-zoom-in {
+ font-size: 22px;
+ }
+.leaflet-touch .leaflet-control-zoom-out {
+ font-size: 24px;
+ }
+
+
+/* layers control */
+
+.leaflet-control-layers {
+ box-shadow: 0 1px 5px rgba(0,0,0,0.4);
+ background: #fff;
+ border-radius: 5px;
+ }
+.leaflet-control-layers-toggle {
+ background-image: url(images/layers.png);
+ width: 36px;
+ height: 36px;
+ }
+.leaflet-retina .leaflet-control-layers-toggle {
+ background-image: url(images/layers-2x.png);
+ background-size: 26px 26px;
+ }
+.leaflet-touch .leaflet-control-layers-toggle {
+ width: 44px;
+ height: 44px;
+ }
+.leaflet-control-layers .leaflet-control-layers-list,
+.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
+ display: none;
+ }
+.leaflet-control-layers-expanded .leaflet-control-layers-list {
+ display: block;
+ position: relative;
+ }
+.leaflet-control-layers-expanded {
+ padding: 6px 10px 6px 6px;
+ color: #333;
+ background: #fff;
+ }
+.leaflet-control-layers-selector {
+ margin-top: 2px;
+ position: relative;
+ top: 1px;
+ }
+.leaflet-control-layers label {
+ display: block;
+ }
+.leaflet-control-layers-separator {
+ height: 0;
+ border-top: 1px solid #ddd;
+ margin: 5px -10px 5px -6px;
+ }
+
+
+/* attribution and scale controls */
+
+.leaflet-container .leaflet-control-attribution {
+ background: #fff;
+ background: rgba(255, 255, 255, 0.7);
+ margin: 0;
+ }
+.leaflet-control-attribution,
+.leaflet-control-scale-line {
+ padding: 0 5px;
+ color: #333;
+ }
+.leaflet-control-attribution a {
+ text-decoration: none;
+ }
+.leaflet-control-attribution a:hover {
+ text-decoration: underline;
+ }
+.leaflet-container .leaflet-control-attribution,
+.leaflet-container .leaflet-control-scale {
+ font-size: 11px;
+ }
+.leaflet-left .leaflet-control-scale {
+ margin-left: 5px;
+ }
+.leaflet-bottom .leaflet-control-scale {
+ margin-bottom: 5px;
+ }
+.leaflet-control-scale-line {
+ border: 2px solid #777;
+ border-top: none;
+ line-height: 1.1;
+ padding: 2px 5px 1px;
+ font-size: 11px;
+ white-space: nowrap;
+ overflow: hidden;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+
+ background: #fff;
+ background: rgba(255, 255, 255, 0.5);
+ }
+.leaflet-control-scale-line:not(:first-child) {
+ border-top: 2px solid #777;
+ border-bottom: none;
+ margin-top: -2px;
+ }
+.leaflet-control-scale-line:not(:first-child):not(:last-child) {
+ border-bottom: 2px solid #777;
+ }
+
+.leaflet-touch .leaflet-control-attribution,
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+ box-shadow: none;
+ }
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+ border: 2px solid rgba(0,0,0,0.2);
+ background-clip: padding-box;
+ }
+
+
+/* popup */
+
+.leaflet-popup {
+ position: absolute;
+ text-align: center;
+ }
+.leaflet-popup-content-wrapper {
+ padding: 1px;
+ text-align: left;
+ border-radius: 12px;
+ }
+.leaflet-popup-content {
+ margin: 13px 19px;
+ line-height: 1.4;
+ }
+.leaflet-popup-content p {
+ margin: 18px 0;
+ }
+.leaflet-popup-tip-container {
+ margin: 0 auto;
+ width: 40px;
+ height: 20px;
+ position: relative;
+ overflow: hidden;
+ }
+.leaflet-popup-tip {
+ width: 17px;
+ height: 17px;
+ padding: 1px;
+
+ margin: -10px auto 0;
+
+ -webkit-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ transform: rotate(45deg);
+ }
+.leaflet-popup-content-wrapper,
+.leaflet-popup-tip {
+ background: white;
+
+ box-shadow: 0 3px 14px rgba(0,0,0,0.4);
+ }
+.leaflet-container a.leaflet-popup-close-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 4px 4px 0 0;
+ text-align: center;
+ width: 18px;
+ height: 14px;
+ font: 16px/14px Tahoma, Verdana, sans-serif;
+ color: #c3c3c3;
+ text-decoration: none;
+ font-weight: bold;
+ background: transparent;
+ }
+.leaflet-container a.leaflet-popup-close-button:hover {
+ color: #999;
+ }
+.leaflet-popup-scrolled {
+ overflow: auto;
+ border-bottom: 1px solid #ddd;
+ border-top: 1px solid #ddd;
+ }
+
+.leaflet-oldie .leaflet-popup-content-wrapper {
+ zoom: 1;
+ }
+.leaflet-oldie .leaflet-popup-tip {
+ width: 24px;
+ margin: 0 auto;
+
+ -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
+ filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
+ }
+.leaflet-oldie .leaflet-popup-tip-container {
+ margin-top: -1px;
+ }
+
+.leaflet-oldie .leaflet-control-zoom,
+.leaflet-oldie .leaflet-control-layers,
+.leaflet-oldie .leaflet-popup-content-wrapper,
+.leaflet-oldie .leaflet-popup-tip {
+ border: 1px solid #999;
+ }
+
+
+/* div icon */
+
+.leaflet-div-icon {
+ background: #fff;
+ border: 1px solid #666;
+ }
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.js
new file mode 100644
index 00000000..03434b77
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/leaflet-0.7.3/leaflet.js
@@ -0,0 +1,9 @@
+/*
+ Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com
+ (c) 2010-2013, Vladimir Agafonkin
+ (c) 2010-2011, CloudMade
+*/
+!function(t,e,i){var n=t.L,o={};o.version="0.7.3","object"==typeof module&&"object"==typeof module.exports?module.exports=o:"function"==typeof define&&define.amd&&define(o),o.noConflict=function(){return t.L=n,this},t.L=o,o.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),invokeEach:function(t,e,i){var n,o;if("object"==typeof t){o=Array.prototype.slice.call(arguments,3);for(n in t)e.apply(i,[n,t[n]].concat(o));return!0}return!1},limitExecByInterval:function(t,e,i){var n,o;return function s(){var a=arguments;return n?void(o=!0):(n=!0,setTimeout(function(){n=!1,o&&(s.apply(i,a),o=!1)},e),void t.apply(i,a))}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},trim:function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")},splitWords:function(t){return o.Util.trim(t).split(/\s+/)},setOptions:function(t,e){return t.options=o.extend({},t.options,e),t.options},getParamString:function(t,e,i){var n=[];for(var o in t)n.push(encodeURIComponent(i?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(e&&-1!==e.indexOf("?")?"&":"?")+n.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,n){var o=e[n];if(o===i)throw new Error("No value provided for variable "+t);return"function"==typeof o&&(o=o(e)),o})},isArray:Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;i<o.length&&!n;i++)n=t[o[i]+e];return n}function i(e){var i=+new Date,o=Math.max(0,16-(i-n));return n=i+o,t.setTimeout(e,o)}var n=0,s=t.requestAnimationFrame||e("RequestAnimationFrame")||i,a=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};o.Util.requestAnimFrame=function(e,n,a,r){return e=o.bind(e,n),a&&s===i?void e():s.call(t,e,r)},o.Util.cancelAnimFrame=function(e){e&&a.call(t,e)}}(),o.extend=o.Util.extend,o.bind=o.Util.bind,o.stamp=o.Util.stamp,o.setOptions=o.Util.setOptions,o.Class=function(){},o.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var n=new i;n.constructor=e,e.prototype=n;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(o.extend(e,t.statics),delete t.statics),t.includes&&(o.Util.extend.apply(null,[n].concat(t.includes)),delete t.includes),t.options&&n.options&&(t.options=o.extend({},n.options,t.options)),o.extend(n,t),n._initHooks=[];var a=this;return e.__super__=a.prototype,n.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=n._initHooks.length;e>t;t++)n._initHooks[t].call(this)}},e},o.Class.include=function(t){o.extend(this.prototype,t)},o.Class.mergeOptions=function(t){o.extend(this.prototype.options,t)},o.Class.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";o.Mixin={},o.Mixin.Events={addEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d=this[s]=this[s]||{},p=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)r={action:e,context:i||this},h=t[n],p?(l=h+"_idx",u=l+"_len",c=d[l]=d[l]||{},c[p]||(c[p]=[],d[u]=(d[u]||0)+1),c[p].push(r)):(d[h]=d[h]||[],d[h].push(r));return this},hasEventListeners:function(t){var e=this[s];return!!e&&(t in e&&e[t].length>0||t+"_idx"in e&&e[t+"_idx_len"]>0)},removeEventListener:function(t,e,i){if(!this[s])return this;if(!t)return this.clearAllEventListeners();if(o.Util.invokeEach(t,this.removeEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d,p,_=this[s],m=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)if(r=t[n],u=r+"_idx",c=u+"_len",d=_[u],e){if(h=m&&d?d[m]:_[r]){for(l=h.length-1;l>=0;l--)h[l].action!==e||i&&h[l].context!==i||(p=h.splice(l,1),p[0].action=o.Util.falseFn);i&&d&&0===h.length&&(delete d[m],_[c]--)}}else delete _[r],delete _[u],delete _[c];return this},clearAllEventListeners:function(){return delete this[s],this},fireEvent:function(t,e){if(!this.hasEventListeners(t))return this;var i,n,a,r,h,l=o.Util.extend({},e,{type:t,target:this}),u=this[s];if(u[t])for(i=u[t].slice(),n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);r=u[t+"_idx"];for(h in r)if(i=r[h].slice())for(n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);return this},addOneTimeEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addOneTimeEventListener,this,e,i))return this;var n=o.bind(function(){this.removeEventListener(t,e,i).removeEventListener(t,n,i)},this);return this.addEventListener(t,e,i).addEventListener(t,n,i)}},o.Mixin.Events.on=o.Mixin.Events.addEventListener,o.Mixin.Events.off=o.Mixin.Events.removeEventListener,o.Mixin.Events.once=o.Mixin.Events.addOneTimeEventListener,o.Mixin.Events.fire=o.Mixin.Events.fireEvent,function(){var n="ActiveXObject"in t,s=n&&!e.addEventListener,a=navigator.userAgent.toLowerCase(),r=-1!==a.indexOf("webkit"),h=-1!==a.indexOf("chrome"),l=-1!==a.indexOf("phantom"),u=-1!==a.indexOf("android"),c=-1!==a.search("android [23]"),d=-1!==a.indexOf("gecko"),p=typeof orientation!=i+"",_=t.navigator&&t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints&&!t.PointerEvent,m=t.PointerEvent&&t.navigator.pointerEnabled&&t.navigator.maxTouchPoints||_,f="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,g=e.documentElement,v=n&&"transition"in g.style,y="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix&&!c,P="MozPerspective"in g.style,L="OTransition"in g.style,x=!t.L_DISABLE_3D&&(v||y||P||L)&&!l,w=!t.L_NO_TOUCH&&!l&&function(){var t="ontouchstart";if(m||t in g)return!0;var i=e.createElement("div"),n=!1;return i.setAttribute?(i.setAttribute(t,"return;"),"function"==typeof i[t]&&(n=!0),i.removeAttribute(t),i=null,n):!1}();o.Browser={ie:n,ielt9:s,webkit:r,gecko:d&&!r&&!t.opera&&!n,android:u,android23:c,chrome:h,ie3d:v,webkit3d:y,gecko3d:P,opera3d:L,any3d:x,mobile:p,mobileWebkit:p&&r,mobileWebkit3d:p&&y,mobileOpera:p&&t.opera,touch:w,msPointer:_,pointer:m,retina:f}}(),o.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},o.Point.prototype={clone:function(){return new o.Point(this.x,this.y)},add:function(t){return this.clone()._add(o.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(o.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=o.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t=o.point(t),t.x===this.x&&t.y===this.y},contains:function(t){return t=o.point(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+o.Util.formatNum(this.x)+", "+o.Util.formatNum(this.y)+")"}},o.point=function(t,e,n){return t instanceof o.Point?t:o.Util.isArray(t)?new o.Point(t[0],t[1]):t===i||null===t?t:new o.Point(t,e,n)},o.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.Bounds.prototype={extend:function(t){return t=o.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new o.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new o.Point(this.min.x,this.max.y)},getTopRight:function(){return new o.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof o.Point?o.point(t):o.bounds(t),t instanceof o.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=o.bounds(t);var e=this.min,i=this.max,n=t.min,s=t.max,a=s.x>=e.x&&n.x<=i.x,r=s.y>=e.y&&n.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},o.bounds=function(t,e){return!t||t instanceof o.Bounds?t:new o.Bounds(t,e)},o.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},o.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new o.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},o.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,n=0,s=0,a=t,r=e.body,h=e.documentElement;do{if(n+=a.offsetTop||0,s+=a.offsetLeft||0,n+=parseInt(o.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(o.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=o.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){n+=r.scrollTop||h.scrollTop||0,s+=r.scrollLeft||h.scrollLeft||0;break}if("relative"===i&&!a.offsetLeft){var l=o.DomUtil.getStyle(a,"width"),u=o.DomUtil.getStyle(a,"max-width"),c=a.getBoundingClientRect();("none"!==l||"none"!==u)&&(s+=c.left+a.clientLeft),n+=c.top+(r.scrollTop||h.scrollTop||0);break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;n-=a.scrollTop||0,s-=a.scrollLeft||0,a=a.parentNode}while(a);return new o.Point(s,n)},documentIsLtr:function(){return o.DomUtil._docIsLtrCached||(o.DomUtil._docIsLtrCached=!0,o.DomUtil._docIsLtr="ltr"===o.DomUtil.getStyle(e.body,"direction")),o.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},hasClass:function(t,e){if(t.classList!==i)return t.classList.contains(e);var n=o.DomUtil._getClass(t);return n.length>0&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(n)},addClass:function(t,e){if(t.classList!==i)for(var n=o.Util.splitWords(e),s=0,a=n.length;a>s;s++)t.classList.add(n[s]);else if(!o.DomUtil.hasClass(t,e)){var r=o.DomUtil._getClass(t);o.DomUtil._setClass(t,(r?r+" ":"")+e)}},removeClass:function(t,e){t.classList!==i?t.classList.remove(e):o.DomUtil._setClass(t,o.Util.trim((" "+o.DomUtil._getClass(t)+" ").replace(" "+e+" "," ")))},_setClass:function(t,e){t.className.baseVal===i?t.className=e:t.className.baseVal=e},_getClass:function(t){return t.className.baseVal===i?t.className:t.className.baseVal},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){if(1===e)return}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;n<t.length;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=o.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",n=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+n},getScaleString:function(t,e){var i=o.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),n=" scale("+t+") ";return i+n},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&o.Browser.any3d?t.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(e):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},o.DomUtil.TRANSFORM=o.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),o.DomUtil.TRANSITION=o.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),o.DomUtil.TRANSITION_END="webkitTransition"===o.DomUtil.TRANSITION||"OTransition"===o.DomUtil.TRANSITION?o.DomUtil.TRANSITION+"End":"transitionend",function(){if("onselectstart"in e)o.extend(o.DomUtil,{disableTextSelection:function(){o.DomEvent.on(t,"selectstart",o.DomEvent.preventDefault)},enableTextSelection:function(){o.DomEvent.off(t,"selectstart",o.DomEvent.preventDefault)}});else{var i=o.DomUtil.testProp(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);o.extend(o.DomUtil,{disableTextSelection:function(){if(i){var t=e.documentElement.style;this._userSelect=t[i],t[i]="none"}},enableTextSelection:function(){i&&(e.documentElement.style[i]=this._userSelect,delete this._userSelect)}})}o.extend(o.DomUtil,{disableImageDrag:function(){o.DomEvent.on(t,"dragstart",o.DomEvent.preventDefault)},enableImageDrag:function(){o.DomEvent.off(t,"dragstart",o.DomEvent.preventDefault)}})}(),o.LatLng=function(t,e,n){if(t=parseFloat(t),e=parseFloat(e),isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=t,this.lng=e,n!==i&&(this.alt=parseFloat(n))},o.extend(o.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),o.LatLng.prototype={equals:function(t){if(!t)return!1;t=o.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return e<=o.LatLng.MAX_MARGIN},toString:function(t){return"LatLng("+o.Util.formatNum(this.lat,t)+", "+o.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=o.latLng(t);var e=6378137,i=o.LatLng.DEG_TO_RAD,n=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i,a=this.lat*i,r=t.lat*i,h=Math.sin(n/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new o.LatLng(this.lat,i)}},o.latLng=function(t,e){return t instanceof o.LatLng?t:o.Util.isArray(t)?"number"==typeof t[0]||"string"==typeof t[0]?new o.LatLng(t[0],t[1],t[2]):null:t===i||null===t?t:"object"==typeof t&&"lat"in t?new o.LatLng(t.lat,"lng"in t?t.lng:t.lon):e===i?null:new o.LatLng(t,e)},o.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.LatLngBounds.prototype={extend:function(t){if(!t)return this;var e=o.latLng(t);return t=null!==e?e:o.latLngBounds(t),t instanceof o.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new o.LatLng(t.lat,t.lng),this._northEast=new o.LatLng(t.lat,t.lng)):t instanceof o.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,n=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new o.LatLngBounds(new o.LatLng(e.lat-n,e.lng-s),new o.LatLng(i.lat+n,i.lng+s))},getCenter:function(){return new o.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new o.LatLng(this.getNorth(),this.getWest())},getSouthEast:function(){return new o.LatLng(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof o.LatLng?o.latLng(t):o.latLngBounds(t);var e,i,n=this._southWest,s=this._northEast;return t instanceof o.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=n.lat&&i.lat<=s.lat&&e.lng>=n.lng&&i.lng<=s.lng},intersects:function(t){t=o.latLngBounds(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&n.lat<=i.lat,r=s.lng>=e.lng&&n.lng<=i.lng;return a&&r},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t){return t?(t=o.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},o.latLngBounds=function(t,e){return!t||t instanceof o.LatLngBounds?t:new o.LatLngBounds(t,e)},o.Projection={},o.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=n*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new o.Point(s,a)},unproject:function(t){var e=o.LatLng.RAD_TO_DEG,i=t.x*e,n=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new o.LatLng(n,i)}},o.Projection.LonLat={project:function(t){return new o.Point(t.lng,t.lat)},unproject:function(t){return new o.LatLng(t.y,t.x)}},o.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)},getSize:function(t){var e=this.scale(t);return o.point(e,e)}},o.CRS.Simple=o.extend({},o.CRS,{projection:o.Projection.LonLat,transformation:new o.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),o.CRS.EPSG3857=o.extend({},o.CRS,{code:"EPSG:3857",projection:o.Projection.SphericalMercator,transformation:new o.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),o.CRS.EPSG900913=o.extend({},o.CRS.EPSG3857,{code:"EPSG:900913"}),o.CRS.EPSG4326=o.extend({},o.CRS,{code:"EPSG:4326",projection:o.Projection.LonLat,transformation:new o.Transformation(1/360,.5,-1/360,.5)}),o.Map=o.Class.extend({includes:o.Mixin.Events,options:{crs:o.CRS.EPSG3857,fadeAnimation:o.DomUtil.TRANSITION&&!o.Browser.android23,trackResize:!0,markerZoomAnimation:o.DomUtil.TRANSITION&&o.Browser.any3d},initialize:function(t,e){e=o.setOptions(this,e),this._initContainer(t),this._initLayout(),this._onResize=o.bind(this._onResize,this),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(o.latLng(e.center),e.zoom,{reset:!0}),this._handlers=[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0,this.callInitHooks(),this._addLayers(e.layers)},setView:function(t,e){return e=e===i?this.getZoom():e,this._resetView(o.latLng(t),this._limitZoom(e)),this},setZoom:function(t,e){return this._loaded?this.setView(this.getCenter(),t,{zoom:e}):(this._zoom=this._limitZoom(t),this)},zoomIn:function(t,e){return this.setZoom(this._zoom+(t||1),e)},zoomOut:function(t,e){return this.setZoom(this._zoom-(t||1),e)},setZoomAround:function(t,e,i){var n=this.getZoomScale(e),s=this.getSize().divideBy(2),a=t instanceof o.Point?t:this.latLngToContainerPoint(t),r=a.subtract(s).multiplyBy(1-1/n),h=this.containerPointToLatLng(s.add(r));return this.setView(h,e,{zoom:i})},fitBounds:function(t,e){e=e||{},t=t.getBounds?t.getBounds():o.latLngBounds(t);var i=o.point(e.paddingTopLeft||e.padding||[0,0]),n=o.point(e.paddingBottomRight||e.padding||[0,0]),s=this.getBoundsZoom(t,!1,i.add(n)),a=n.subtract(i).divideBy(2),r=this.project(t.getSouthWest(),s),h=this.project(t.getNorthEast(),s),l=this.unproject(r.add(h).divideBy(2).add(a),s);return s=e&&e.maxZoom?Math.min(e.maxZoom,s):s,this.setView(l,s,e)},fitWorld:function(t){return this.fitBounds([[-90,-180],[90,180]],t)},panTo:function(t,e){return this.setView(t,this._zoom,{pan:e})},panBy:function(t){return this.fire("movestart"),this._rawPanBy(o.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){return t=o.latLngBounds(t),this.options.maxBounds=t,t?(this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds,this)):this.off("moveend",this._panInsideMaxBounds,this)},panInsideBounds:function(t,e){var i=this.getCenter(),n=this._limitCenter(i,this._zoom,t);return i.equals(n)?this:this.panTo(n,e)},addLayer:function(t){var e=o.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this._loaded&&this._layerAdd(t),this)},removeLayer:function(t){var e=o.stamp(t);return this._layers[e]?(this._loaded&&t.onRemove(this),delete this._layers[e],this._loaded&&this.fire("layerremove",{layer:t}),this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this):this},hasLayer:function(t){return t?o.stamp(t)in this._layers:!1},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},invalidateSize:function(t){if(!this._loaded)return this;t=o.extend({animate:!1,pan:!0},t===!0?{animate:!0}:t);var e=this.getSize();this._sizeChanged=!0,this._initialCenter=null;var i=this.getSize(),n=e.divideBy(2).round(),s=i.divideBy(2).round(),a=n.subtract(s);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(o.bind(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},addHandler:function(t,e){if(!e)return this;var i=this[t]=new e(this);return this._handlers.push(i),this.options[t]&&i.enable(),this},remove:function(){this._loaded&&this.fire("unload"),this._initEvents("off");try{delete this._container._leaflet}catch(t){this._container._leaflet=i}return this._clearPanes(),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this},getCenter:function(){return this._checkIfLoaded(),this._initialCenter&&!this._moved()?this._initialCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new o.LatLngBounds(e,i)},getMinZoom:function(){return this.options.minZoom===i?this._layersMinZoom===i?0:this._layersMinZoom:this.options.minZoom},getMaxZoom:function(){return this.options.maxZoom===i?this._layersMaxZoom===i?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,i){t=o.latLngBounds(t);var n,s=this.getMinZoom()-(e?1:0),a=this.getMaxZoom(),r=this.getSize(),h=t.getNorthWest(),l=t.getSouthEast(),u=!0;i=o.point(i||[0,0]);do s++,n=this.project(l,s).subtract(this.project(h,s)).add(i),u=e?n.x<r.x||n.y<r.y:r.contains(n);while(u&&a>=s);return u&&e?null:e?s:s-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new o.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new o.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(o.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(o.point(t),e)},layerPointToLatLng:function(t){var e=o.point(t).add(this.getPixelOrigin());return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(o.latLng(t))._round();return e._subtract(this.getPixelOrigin())},containerPointToLayerPoint:function(t){return o.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return o.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(o.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(o.latLng(t)))},mouseEventToContainerPoint:function(t){return o.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=o.DomUtil.get(t);if(!e)throw new Error("Map container not found.");if(e._leaflet)throw new Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;o.DomUtil.addClass(t,"leaflet-container"+(o.Browser.touch?" leaflet-touch":"")+(o.Browser.retina?" leaflet-retina":"")+(o.Browser.ielt9?" leaflet-oldie":"")+(this.options.fadeAnimation?" leaflet-fade-anim":""));var e=o.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(o.DomUtil.addClass(t.markerPane,e),o.DomUtil.addClass(t.shadowPane,e),o.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return o.DomUtil.create("div",t,e||this._panes.objectsPane)},_clearPanes:function(){this._container.removeChild(this._mapPane)},_addLayers:function(t){t=t?o.Util.isArray(t)?t:[t]:[];for(var e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,n){var s=this._zoom!==e;n||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialCenter=t,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):o.DomUtil.setPosition(this._mapPane,new o.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),a&&(this.fire("load"),this.eachLayer(this._layerAdd,this)),this.fire("move"),(s||n)&&this.fire("zoomend"),this.fire("moveend",{hard:!i})},_rawPanBy:function(t){o.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_updateZoomLevels:function(){var t,e=1/0,n=-1/0,o=this._getZoomSpan();for(t in this._zoomBoundLayers){var s=this._zoomBoundLayers[t];isNaN(s.options.minZoom)||(e=Math.min(e,s.options.minZoom)),isNaN(s.options.maxZoom)||(n=Math.max(n,s.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e),o!==this._getZoomSpan()&&this.fire("zoomlevelschange")},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(e){if(o.DomEvent){e=e||"on",o.DomEvent[e](this._container,"click",this._onMouseClick,this);var i,n,s=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(i=0,n=s.length;n>i;i++)o.DomEvent[e](this._container,s[i],this._fireMouseEvent,this);this.options.trackResize&&o.DomEvent[e](t,"resize",this._onResize,this)}},_onResize:function(){o.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=o.Util.requestAnimFrame(function(){this.invalidateSize({debounceMoveend:!0})},this,!1,this._container)},_onMouseClick:function(t){!this._loaded||!t._simulated&&(this.dragging&&this.dragging.moved()||this.boxZoom&&this.boxZoom.moved())||o.DomEvent._skipped(t)||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded&&!o.DomEvent._skipped(t)){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&o.DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),n=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(n);this.fire(e,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this.fire("tilelayersload")},_clearHandlers:function(){for(var t=0,e=this._handlers.length;e>t;t++)this._handlers[t].disable()},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_layerAdd:function(t){t.onAdd(this),this.fire("layeradd",{layer:t})},_getMapPanePos:function(){return o.DomUtil.getPosition(this._mapPane)},_moved:function(){var t=this._getMapPanePos();return t&&!t.equals([0,0])},_getTopLeftPoint:function(){return this.getPixelOrigin().subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subtract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitCenter:function(t,e,i){if(!i)return t;var n=this.project(t,e),s=this.getSize().divideBy(2),a=new o.Bounds(n.subtract(s),n.add(s)),r=this._getBoundsOffset(a,i,e);return this.unproject(n.add(r),e)},_limitOffset:function(t,e){if(!e)return t;var i=this.getPixelBounds(),n=new o.Bounds(i.min.add(t),i.max.add(t));return t.add(this._getBoundsOffset(n,e))},_getBoundsOffset:function(t,e,i){var n=this.project(e.getNorthWest(),i).subtract(t.min),s=this.project(e.getSouthEast(),i).subtract(t.max),a=this._rebound(n.x,-s.x),r=this._rebound(n.y,-s.y);return new o.Point(a,r)},_rebound:function(t,e){return t+e>0?Math.round(t-e)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(e))},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),o.map=function(t,e){return new o.Map(t,e)},o.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.314245179,R_MAJOR:6378137,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=n*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var d=Math.tan(.5*(.5*Math.PI-h))/c;return h=-s*Math.log(d),new o.Point(r,h)},unproject:function(t){for(var e,i=o.LatLng.RAD_TO_DEG,n=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/n,r=s/n,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/n),u=Math.PI/2-2*Math.atan(l),c=15,d=1e-7,p=c,_=.1;Math.abs(_)>d&&--p>0;)e=h*Math.sin(u),_=Math.PI/2-2*Math.atan(l*Math.pow((1-e)/(1+e),.5*h))-u,u+=_;
+return new o.LatLng(u*i,a)}},o.CRS.EPSG3395=o.extend({},o.CRS,{code:"EPSG:3395",projection:o.Projection.Mercator,transformation:function(){var t=o.Projection.Mercator,e=t.R_MAJOR,i=.5/(Math.PI*e);return new o.Transformation(i,.5,-i,.5)}()}),o.TileLayer=o.Class.extend({includes:o.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:o.Browser.mobile,updateWhenIdle:o.Browser.mobile},initialize:function(t,e){e=o.setOptions(this,e),e.detectRetina&&o.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),e.bounds&&(e.bounds=o.latLngBounds(e.bounds)),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._animated=t._zoomAnimated,this._initContainer(),t.on({viewreset:this._reset,moveend:this._update},this),this._animated&&t.on({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||(this._limitedUpdate=o.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._reset,moveend:this._update},this),this._animated&&t.off({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},getContainer:function(){return this._container},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){return this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._reset({hard:!0}),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-1/0);for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){var t,e=this._tiles;if(o.Browser.ielt9)for(t in e)o.DomUtil.setOpacity(e[t],this.options.opacity);else o.DomUtil.setOpacity(this._container,this.options.opacity)},_initContainer:function(){var t=this._map._panes.tilePane;if(!this._container){if(this._container=o.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),this._animated){var e="leaflet-tile-container";this._bgBuffer=o.DomUtil.create("div",e,this._container),this._tileContainer=o.DomUtil.create("div",e,this._container)}else this._tileContainer=this._container;t.appendChild(this._container),this.options.opacity<1&&this._updateOpacity()}},_reset:function(t){for(var e in this._tiles)this.fire("tileunload",{tile:this._tiles[e]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),this._tileContainer.innerHTML="",this._animated&&t&&t.hard&&this._clearBgBuffer(),this._initContainer()},_getTileSize:function(){var t=this._map,e=t.getZoom()+this.options.zoomOffset,i=this.options.maxNativeZoom,n=this.options.tileSize;return i&&e>i&&(n=Math.round(t.getZoomScale(e)/t.getZoomScale(i)*n)),n},_update:function(){if(this._map){var t=this._map,e=t.getPixelBounds(),i=t.getZoom(),n=this._getTileSize();if(!(i>this.options.maxZoom||i<this.options.minZoom)){var s=o.bounds(e.min.divideBy(n)._floor(),e.max.divideBy(n)._floor());this._addTilesFromCenterOut(s),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(s)}}},_addTilesFromCenterOut:function(t){var i,n,s,a=[],r=t.getCenter();for(i=t.min.y;i<=t.max.y;i++)for(n=t.min.x;n<=t.max.x;n++)s=new o.Point(n,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.createDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,n=0;h>n;n++)this._addTile(a[n],l);this._tileContainer.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;var e=this.options;if(!e.continuousWorld){var i=this._getWrapTileNum();if(e.noWrap&&(t.x<0||t.x>=i.x)||t.y<0||t.y>=i.y)return!1}if(e.bounds){var n=e.tileSize,o=t.multiplyBy(n),s=o.add([n,n]),a=this._map.unproject(o),r=this._map.unproject(s);if(e.continuousWorld||e.noWrap||(a=a.wrap(),r=r.wrap()),!e.bounds.intersects([a,r]))return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(i<t.min.x||i>t.max.x||n<t.min.y||n>t.max.y)&&this._removeTile(o)},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(o.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._tileContainer&&this._tileContainer.removeChild(e),o.Browser.android||(e.onload=null,e.src=o.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),n=this._getTile();o.DomUtil.setPosition(n,i,o.Browser.chrome),this._tiles[t.x+":"+t.y]=n,this._loadTile(n,t),n.parentNode!==this._tileContainer&&e.appendChild(n)},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+=t.zoomOffset,t.maxNativeZoom?Math.min(e,t.maxNativeZoom):e},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this._getTileSize();return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return o.Util.template(this._url,o.extend({s:this._getSubdomain(t),z:t.z,x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){var t=this._map.options.crs,e=t.getSize(this._map.getZoom());return e.divideBy(this._getTileSize())._floor()},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e.x+e.x)%e.x),this.options.tms&&(t.y=e.y-t.y-1),t.z=this._getZoomForUrl()},_getSubdomain:function(t){var e=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._unusedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=o.DomUtil.create("img","leaflet-tile");return t.style.width=t.style.height=this._getTileSize()+"px",t.galleryimg="no",t.onselectstart=t.onmousemove=o.Util.falseFn,o.Browser.ielt9&&this.options.opacity!==i&&o.DomUtil.setOpacity(t,this.options.opacity),o.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden"),t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,this._adjustTilePoint(e),t.src=this.getTileUrl(e),this.fire("tileloadstart",{tile:t,url:t.src})},_tileLoaded:function(){this._tilesToLoad--,this._animated&&o.DomUtil.addClass(this._tileContainer,"leaflet-zoom-animated"),this._tilesToLoad||(this.fire("load"),this._animated&&(clearTimeout(this._clearBgBufferTimer),this._clearBgBufferTimer=setTimeout(o.bind(this._clearBgBuffer,this),500)))},_tileOnLoad:function(){var t=this._layer;this.src!==o.Util.emptyImageUrl&&(o.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),o.tileLayer=function(t,e){return new o.TileLayer(t,e)},o.TileLayer.WMS=o.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=o.extend({},this.defaultWmsParams),n=e.tileSize||this.options.tileSize;i.width=i.height=e.detectRetina&&o.Browser.retina?2*n:n;for(var s in e)this.options.hasOwnProperty(s)||"crs"===s||(i[s]=e[s]);this.wmsParams=i,o.setOptions(this,e)},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var e=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[e]=this._crs.code,o.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t){var e=this._map,i=this.options.tileSize,n=t.multiplyBy(i),s=n.add([i,i]),a=this._crs.project(e.unproject(n,t.z)),r=this._crs.project(e.unproject(s,t.z)),h=this._wmsVersion>=1.3&&this._crs===o.CRS.EPSG4326?[r.y,a.x,a.y,r.x].join(","):[a.x,r.y,r.x,a.y].join(","),l=o.Util.template(this._url,{s:this._getSubdomain(t)});return l+o.Util.getParamString(this.wmsParams,l,!0)+"&BBOX="+h},setParams:function(t,e){return o.extend(this.wmsParams,t),e||this.redraw(),this}}),o.tileLayer.wms=function(t,e){return new o.TileLayer.WMS(t,e)},o.TileLayer.Canvas=o.TileLayer.extend({options:{async:!1},initialize:function(t){o.setOptions(this,t)},redraw:function(){this._map&&(this._reset({hard:!0}),this._update());for(var t in this._tiles)this._redrawTile(this._tiles[t]);return this},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTile:function(){var t=o.DomUtil.create("canvas","leaflet-tile");return t.width=t.height=this.options.tileSize,t.onselectstart=t.onmousemove=o.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),o.tileLayer.canvas=function(t){return new o.TileLayer.Canvas(t)},o.ImageOverlay=o.Class.extend({includes:o.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=o.latLngBounds(e),o.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&o.Browser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},setUrl:function(t){this._url=t,this._image.src=this._url},getAttribution:function(){return this.options.attribution},_initImage:function(){this._image=o.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&o.Browser.any3d?o.DomUtil.addClass(this._image,"leaflet-zoom-animated"):o.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),o.extend(this._image,{galleryimg:"no",onselectstart:o.Util.falseFn,onmousemove:o.Util.falseFn,onload:o.bind(this._onImageLoad,this),src:this._url})},_animateZoom:function(t){var e=this._map,i=this._image,n=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/n)));i.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(l)+" scale("+n+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);o.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){o.DomUtil.setOpacity(this._image,this.options.opacity)}}),o.imageOverlay=function(t,e,i){return new o.ImageOverlay(t,e,i)},o.Icon=o.Class.extend({options:{className:""},initialize:function(t){o.setOptions(this,t)},createIcon:function(t){return this._createIcon("icon",t)},createShadow:function(t){return this._createIcon("shadow",t)},_createIcon:function(t,e){var i=this._getIconUrl(t);if(!i){if("icon"===t)throw new Error("iconUrl not set in Icon options (see the docs).");return null}var n;return n=e&&"IMG"===e.tagName?this._createImg(i,e):this._createImg(i),this._setIconStyles(n,t),n},_setIconStyles:function(t,e){var i,n=this.options,s=o.point(n[e+"Size"]);i=o.point("shadow"===e?n.shadowAnchor||n.iconAnchor:n.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+n.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t,i){return i=i||e.createElement("img"),i.src=t,i},_getIconUrl:function(t){return o.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),o.icon=function(t){return new o.Icon(t)},o.Icon.Default=o.Icon.extend({options:{iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];o.Browser.retina&&"icon"===t&&(t+="-2x");var i=o.Icon.Default.imagePath;if(!i)throw new Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),o.Icon.Default.imagePath=function(){var t,i,n,o,s,a=e.getElementsByTagName("script"),r=/[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=a.length;i>t;t++)if(n=a[t].src,o=n.match(r))return s=n.split(r)[0],(s?s+"/":"")+"images"}(),o.Marker=o.Class.extend({includes:o.Mixin.Events,options:{icon:new o.Icon.Default,title:"",alt:"",clickable:!0,draggable:!1,keyboard:!0,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){o.setOptions(this,e),this._latlng=o.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),this.fire("add"),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this.dragging&&this.dragging.disable(),this._removeIcon(),this._removeShadow(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this.options.icon=t,this._map&&(this._initIcon(),this.update()),this._popup&&this.bindPopup(this._popup),this},update:function(){if(this._icon){var t=this._map.latLngToLayerPoint(this._latlng).round();this._setPos(t)}return this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,n=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=t.icon.createIcon(this._icon),a=!1;s!==this._icon&&(this._icon&&this._removeIcon(),a=!0,t.title&&(s.title=t.title),t.alt&&(s.alt=t.alt)),o.DomUtil.addClass(s,n),t.keyboard&&(s.tabIndex="0"),this._icon=s,this._initInteraction(),t.riseOnHover&&o.DomEvent.on(s,"mouseover",this._bringToFront,this).on(s,"mouseout",this._resetZIndex,this);var r=t.icon.createShadow(this._shadow),h=!1;r!==this._shadow&&(this._removeShadow(),h=!0),r&&o.DomUtil.addClass(r,n),this._shadow=r,t.opacity<1&&this._updateOpacity();var l=this._map._panes;a&&l.markerPane.appendChild(this._icon),r&&h&&l.shadowPane.appendChild(this._shadow)},_removeIcon:function(){this.options.riseOnHover&&o.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),this._map._panes.markerPane.removeChild(this._icon),this._icon=null},_removeShadow:function(){this._shadow&&this._map._panes.shadowPane.removeChild(this._shadow),this._shadow=null},_setPos:function(t){o.DomUtil.setPosition(this._icon,t),this._shadow&&o.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center).round();this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];o.DomUtil.addClass(t,"leaflet-clickable"),o.DomEvent.on(t,"click",this._onMouseClick,this),o.DomEvent.on(t,"keypress",this._onKeyPress,this);for(var i=0;i<e.length;i++)o.DomEvent.on(t,e[i],this._fireMouseEvent,this);o.Handler.MarkerDrag&&(this.dragging=new o.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&o.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t,latlng:this._latlng})},_onKeyPress:function(t){13===t.keyCode&&this.fire("click",{originalEvent:t,latlng:this._latlng})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t,latlng:this._latlng}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&o.DomEvent.preventDefault(t),"mousedown"!==t.type?o.DomEvent.stopPropagation(t):o.DomEvent.preventDefault(t)},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},_updateOpacity:function(){o.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&o.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),o.marker=function(t,e){return new o.Marker(t,e)},o.DivIcon=o.Icon.extend({options:{iconSize:[12,12],className:"leaflet-div-icon",html:!1},createIcon:function(t){var i=t&&"DIV"===t.tagName?t:e.createElement("div"),n=this.options;return i.innerHTML=n.html!==!1?n.html:"",n.bgPos&&(i.style.backgroundPosition=-n.bgPos.x+"px "+-n.bgPos.y+"px"),this._setIconStyles(i,"icon"),i},createShadow:function(){return null}}),o.divIcon=function(t){return new o.DivIcon(t)},o.Map.mergeOptions({closePopupOnClick:!0}),o.Popup=o.Class.extend({includes:o.Mixin.Events,options:{minWidth:50,maxWidth:300,autoPan:!0,closeButton:!0,offset:[0,7],autoPanPadding:[5,5],keepInView:!1,className:"",zoomAnimation:!0},initialize:function(t,e){o.setOptions(this,t),this._source=e,this._animated=o.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},onAdd:function(t){this._map=t,this._container||this._initLayout();var e=t.options.fadeAnimation;e&&o.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on(this._getEvents(),this),this.update(),e&&o.DomUtil.setOpacity(this._container,1),this.fire("open"),t.fire("popupopen",{popup:this}),this._source&&this._source.fire("popupopen",{popup:this})},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),o.Util.falseFn(this._container.offsetWidth),t.off(this._getEvents(),this),t.options.fadeAnimation&&o.DomUtil.setOpacity(this._container,0),this._map=null,this.fire("close"),t.fire("popupclose",{popup:this}),this._source&&this._source.fire("popupclose",{popup:this})},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this._map&&(this._updatePosition(),this._adjustPan()),this},getContent:function(){return this._content},setContent:function(t){return this._content=t,this.update(),this},update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout(),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_getEvents:function(){var t={viewreset:this._updatePosition};return this._animated&&(t.zoomanim=this._zoomAnimation),("closeOnClick"in this.options?this.options.closeOnClick:this._map.options.closePopupOnClick)&&(t.preclick=this._close),this.options.keepInView&&(t.moveend=this._adjustPan),t},_close:function(){this._map&&this._map.closePopup(this)},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),n=this._container=o.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=o.DomUtil.create("a",e+"-close-button",n),t.href="#close",t.innerHTML="&#215;",o.DomEvent.disableClickPropagation(t),o.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=o.DomUtil.create("div",e+"-content-wrapper",n);o.DomEvent.disableClickPropagation(s),this._contentNode=o.DomUtil.create("div",e+"-content",s),o.DomEvent.disableScrollPropagation(this._contentNode),o.DomEvent.on(s,"contextmenu",o.DomEvent.stopPropagation),this._tipContainer=o.DomUtil.create("div",e+"-tip-container",n),this._tip=o.DomUtil.create("div",e+"-tip",this._tipContainer)},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var n=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&n>s?(e.height=s+"px",o.DomUtil.addClass(t,a)):o.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=o.point(this.options.offset);e&&o.DomUtil.setPosition(this._container,t),this._containerBottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);o.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,n=new o.Point(this._containerLeft,-e-this._containerBottom);this._animated&&n._add(o.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(n),a=o.point(this.options.autoPanPadding),r=o.point(this.options.autoPanPaddingTopLeft||a),h=o.point(this.options.autoPanPaddingBottomRight||a),l=t.getSize(),u=0,c=0;s.x+i+h.x>l.x&&(u=s.x+i-l.x+h.x),s.x-u-r.x<0&&(u=s.x-r.x),s.y+e+h.y>l.y&&(c=s.y+e-l.y+h.y),s.y-c-r.y<0&&(c=s.y-r.y),(u||c)&&t.fire("autopanstart").panBy([u,c])}},_onCloseButtonClick:function(t){this._close(),o.DomEvent.stop(t)}}),o.popup=function(t,e){return new o.Popup(t,e)},o.Map.include({openPopup:function(t,e,i){if(this.closePopup(),!(t instanceof o.Popup)){var n=t;t=new o.Popup(i).setLatLng(e).setContent(n)}return t._isOpen=!0,this._popup=t,this.addLayer(t)},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&(this.removeLayer(t),t._isOpen=!1),this}}),o.Marker.include({openPopup:function(){return this._popup&&this._map&&!this._map.hasLayer(this._popup)&&(this._popup.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(){return this._popup&&(this._popup._isOpen?this.closePopup():this.openPopup()),this},bindPopup:function(t,e){var i=o.point(this.options.icon.options.popupAnchor||[0,0]);return i=i.add(o.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=o.extend({offset:i},e),this._popupHandlersAdded||(this.on("click",this.togglePopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popupHandlersAdded=!0),t instanceof o.Popup?(o.setOptions(t,e),this._popup=t):this._popup=new o.Popup(e,this).setContent(t),this},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.togglePopup,this).off("remove",this.closePopup,this).off("move",this._movePopup,this),this._popupHandlersAdded=!1),this},getPopup:function(){return this._popup},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),o.LayerGroup=o.Class.extend({initialize:function(t){this._layers={};var e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=this.getLayerId(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=t in this._layers?t:this.getLayerId(t);return this._map&&this._layers[e]&&this._map.removeLayer(this._layers[e]),delete this._layers[e],this},hasLayer:function(t){return t?t in this._layers||this.getLayerId(t)in this._layers:!1},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)i=this._layers[e],i[t]&&i[t].apply(i,n);return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},getLayer:function(t){return this._layers[t]},getLayers:function(){var t=[];for(var e in this._layers)t.push(this._layers[e]);return t},setZIndex:function(t){return this.invoke("setZIndex",t)},getLayerId:function(t){return o.stamp(t)}}),o.layerGroup=function(t){return new o.LayerGroup(t)},o.FeatureGroup=o.LayerGroup.extend({includes:o.Mixin.Events,statics:{EVENTS:"click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose"},addLayer:function(t){return this.hasLayer(t)?this:("on"in t&&t.on(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return this.hasLayer(t)?(t in this._layers&&(t=this._layers[t]),t.off(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})):this},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},openPopup:function(t){for(var e in this._layers){this._layers[e].openPopup(t);break}return this},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new o.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof o.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:function(t){t=o.extend({layer:t.target,target:this},t),this.fire(t.type,t)}}),o.featureGroup=function(t){return new o.FeatureGroup(t)},o.Path=o.Class.extend({includes:[o.Mixin.Events],statics:{CLIP_PADDING:function(){var e=o.Browser.mobile?1280:2e3,i=(e/Math.max(t.outerWidth,t.outerHeight)-1)/2;return Math.max(0,Math.min(.5,i))}()},options:{stroke:!0,color:"#0033ff",dashArray:null,lineCap:null,lineJoin:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){o.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,o.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return o.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),o.Map.include({_updatePathViewport:function(){var t=o.Path.CLIP_PADDING,e=this.getSize(),i=o.DomUtil.getPosition(this._mapPane),n=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=n.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new o.Bounds(n,s)}}),o.Path.SVG_NS="http://www.w3.org/2000/svg",o.Browser.svg=!(!e.createElementNS||!e.createElementNS(o.Path.SVG_NS,"svg").createSVGRect),o.Path=o.Path.extend({statics:{SVG:o.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(o.Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this.options.className&&o.DomUtil.addClass(this._path,this.options.className),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this.options.pointerEvents&&this._path.setAttribute("pointer-events",this.options.pointerEvents),this.options.clickable||this.options.pointerEvents||this._path.setAttribute("pointer-events","none"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray"),this.options.lineCap&&this._path.setAttribute("stroke-linecap",this.options.lineCap),this.options.lineJoin&&this._path.setAttribute("stroke-linejoin",this.options.lineJoin)):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(o.Browser.svg||!o.Browser.vml)&&o.DomUtil.addClass(this._path,"leaflet-clickable"),o.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;e<t.length;e++)o.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),n=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(n);this.fire(t.type,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&o.DomEvent.preventDefault(t),"mousemove"!==t.type&&o.DomEvent.stopPropagation(t)}}}),o.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=o.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&o.Browser.any3d?(o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-animated"),this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport())
+},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,n=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;o.Browser.mobileWebkit&&r.removeChild(a),o.DomUtil.setPosition(a,e),a.setAttribute("width",n),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,n,s].join(" ")),o.Browser.mobileWebkit&&r.appendChild(a)}}}),o.Path.include({bindPopup:function(t,e){return t instanceof o.Popup?this._popup=t:((!this._popup||e)&&(this._popup=new o.Popup(e,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),o.Browser.vml=!o.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),o.Path=o.Browser.svg||!o.Browser.vml?o.Path:o.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");o.DomUtil.addClass(t,"leaflet-vml-shape"+(this.options.className?" "+this.options.className:"")),this.options.clickable&&o.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createElement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,t.dashStyle=i.dashArray?o.Util.isArray(i.dashArray)?i.dashArray.join(" "):i.dashArray.replace(/( *, *)/g," "):"",i.lineCap&&(t.endcap=i.lineCap.replace("butt","flat")),i.lineJoin&&(t.joinstyle=i.lineJoin)):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),o.Map.include(o.Browser.svg||!o.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),o.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),o.Path=o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?o.Path:o.Path.extend({statics:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return o.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&(this._map.off("click",this._onClick,this),this._map.off("mousemove",this._onMouseMove,this)),this._requestUpdate(),this.fire("remove"),this._map=null},_requestUpdate:function(){this._map&&!o.Path._updateRequest&&(o.Path._updateRequest=o.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){o.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color)},_drawPath:function(){var t,e,i,n,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0,n=this._parts[t].length;n>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof o.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill()),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&(this._map.on("mousemove",this._onMouseMove,this),this._map.on("click",this._onClick,this))},_onClick:function(t){this._containsPoint(t.layerPoint)&&this.fire("click",t)},_onMouseMove:function(t){this._map&&!this._map._animatingZoom&&(this._containsPoint(t.layerPoint)?(this._ctx.canvas.style.cursor="pointer",this._mouseInside=!0,this.fire("mouseover",t)):this._mouseInside&&(this._ctx.canvas.style.cursor="",this._mouseInside=!1,this.fire("mouseout",t)))}}),o.Map.include(o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChild(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),n=this._pathRoot;o.DomUtil.setPosition(n,e),n.width=i.x,n.height=i.y,n.getContext("2d").translate(-e.x,-e.y)}}}),o.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);return r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,i,n){var s=e.x-t.x,a=e.y-t.y,r=n.min,h=n.max;return 8&i?new o.Point(t.x+s*(h.y-t.y)/a,h.y):4&i?new o.Point(t.x+s*(r.y-t.y)/a,r.y):2&i?new o.Point(h.x,t.y+a*(h.x-t.x)/s):1&i?new o.Point(r.x,t.y+a*(r.x-t.x)/s):void 0},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8),i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,n){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,n?h*h+l*l:new o.Point(a,r)}},o.Polyline=o.Path.extend({initialize:function(t,e){o.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(o.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,arguments);return this._convertLatLngs(this._latlngs,!0),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,n=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];var d=o.LineUtil._sqClosestPointOnSegment(t,e,i,!0);n>d&&(n=d,a=o.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(n)),a},getBounds:function(){return new o.LatLngBounds(this.getLatLngs())},_convertLatLngs:function(t,e){var i,n,s=e?t:[];for(i=0,n=t.length;n>i;i++){if(o.Util.isArray(t[i])&&"number"!=typeof t[i][0])return;s[i]=o.latLng(t[i])}return s},_initEvents:function(){o.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=o.Path.VML,n=0,s=t.length,a="";s>n;n++)e=t[n],i&&e._round(),a+=(n?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,i,n=this._originalPoints,s=n.length;if(this.options.noClip)return void(this._parts=[n]);this._parts=[];var a=this._parts,r=this._map._pathViewport,h=o.LineUtil;for(t=0,e=0;s-1>t;t++)i=h.clipSegment(n[t],n[t+1],r,t),i&&(a[e]=a[e]||[],a[e].push(i[0]),(i[1]!==n[t+1]||t===s-2)&&(a[e].push(i[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e=o.LineUtil,i=0,n=t.length;n>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),o.Path.prototype._updatePath.call(this))}}),o.polyline=function(t,e){return new o.Polyline(t,e)},o.PolyUtil={},o.PolyUtil.clipPolygon=function(t,e){var i,n,s,a,r,h,l,u,c,d=[1,4,2,8],p=o.LineUtil;for(n=0,l=t.length;l>n;n++)t[n]._code=p._getBitCode(t[n],e);for(a=0;4>a;a++){for(u=d[a],i=[],n=0,l=t.length,s=l-1;l>n;s=n++)r=t[n],h=t[s],r._code&u?h._code&u||(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)):(h._code&u&&(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},o.Polygon=o.Polyline.extend({options:{fill:!0},initialize:function(t,e){o.Polyline.prototype.initialize.call(this,t,e),this._initWithHoles(t)},_initWithHoles:function(t){var e,i,n;if(t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0])for(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1),e=0,i=this._holes.length;i>e;e++)n=this._holes[e]=this._convertLatLngs(this._holes[e]),n[0].equals(n[n.length-1])&&n.pop();t=this._latlngs,t.length>=2&&t[0].equals(t[t.length-1])&&t.pop()},projectLatlngs:function(){if(o.Polyline.prototype.projectLatlngs.call(this),this._holePoints=[],this._holes){var t,e,i,n;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,n=this._holes[t].length;n>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},setLatLngs:function(t){return t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0]?(this._initWithHoles(t),this.redraw()):o.Polyline.prototype.setLatLngs.call(this,t)},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,n=this._parts.length;n>i;i++){var s=o.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=o.Polyline.prototype._getPathPartStr.call(this,t);return e+(o.Browser.svg?"z":"x")}}),o.polygon=function(t,e){return new o.Polygon(t,e)},function(){function t(t){return o.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this},getLatLngs:function(){var t=[];return this.eachLayer(function(e){t.push(e.getLatLngs())}),t}})}o.MultiPolyline=t(o.Polyline),o.MultiPolygon=t(o.Polygon),o.multiPolyline=function(t,e){return new o.MultiPolyline(t,e)},o.multiPolygon=function(t,e){return new o.MultiPolygon(t,e)}}(),o.Rectangle=o.Polygon.extend({initialize:function(t,e){o.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=o.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),o.rectangle=function(t,e){return new o.Rectangle(t,e)},o.Circle=o.Path.extend({initialize:function(t,e,i){o.Path.prototype.initialize.call(this,i),this._latlng=o.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=o.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=this._latlng,i=this._map.latLngToLayerPoint([e.lat,e.lng-t]);this._point=this._map.latLngToLayerPoint(e),this._radius=Math.max(this._point.x-i.x,1)},getBounds:function(){var t=this._getLngRadius(),e=this._mRadius/40075017*360,i=this._latlng;return new o.LatLngBounds([i.lat-e,i.lng-t],[i.lat+e,i.lng+t])},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":o.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,23592600")},getRadius:function(){return this._mRadius},_getLatRadius:function(){return this._mRadius/40075017*360},_getLngRadius:function(){return this._getLatRadius()/Math.cos(o.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),o.circle=function(t,e,i){return new o.Circle(t,e,i)},o.CircleMarker=o.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){o.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){o.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setLatLng:function(t){return o.Circle.prototype.setLatLng.call(this,t),this._popup&&this._popup._isOpen&&this._popup.setLatLng(t),this},setRadius:function(t){return this.options.radius=this._radius=t,this.redraw()},getRadius:function(){return this._radius}}),o.circleMarker=function(t,e){return new o.CircleMarker(t,e)},o.Polyline.include(o.Path.CANVAS?{_containsPoint:function(t,e){var i,n,s,a,r,h,l,u=this.options.weight/2;for(o.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],n=0,r=l.length,s=r-1;r>n;s=n++)if((e||0!==n)&&(h=o.LineUtil.pointToSegmentDistance(t,l[s],l[n]),u>=h))return!0;return!1}}:{}),o.Polygon.include(o.Path.CANVAS?{_containsPoint:function(t){var e,i,n,s,a,r,h,l,u=!1;if(o.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._parts[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],n=e[r],i.y>t.y!=n.y>t.y&&t.x<(n.x-i.x)*(t.y-i.y)/(n.y-i.y)+i.x&&(u=!u);return u}}:{}),o.Circle.include(o.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),o.CircleMarker.include(o.Path.CANVAS?{_updateStyle:function(){o.Path.prototype._updateStyle.call(this)}}:{}),o.GeoJSON=o.FeatureGroup.extend({initialize:function(t,e){o.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,n,s=o.Util.isArray(t)?t:t.features;if(s){for(e=0,i=s.length;i>e;e++)n=s[e],(n.geometries||n.geometry||n.features||n.coordinates)&&this.addData(s[e]);return this}var a=this.options;if(!a.filter||a.filter(t)){var r=o.GeoJSON.geometryToLayer(t,a.pointToLayer,a.coordsToLatLng,a);return r.feature=o.GeoJSON.asFeature(t),r.defaultOptions=r.options,this.resetStyle(r),a.onEachFeature&&a.onEachFeature(t,r),this.addLayer(r)}},resetStyle:function(t){var e=this.options.style;e&&(o.Util.extend(t.options,t.defaultOptions),this._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),o.extend(o.GeoJSON,{geometryToLayer:function(t,e,i,n){var s,a,r,h,l="Feature"===t.type?t.geometry:t,u=l.coordinates,c=[];switch(i=i||this.coordsToLatLng,l.type){case"Point":return s=i(u),e?e(t,s):new o.Marker(s);case"MultiPoint":for(r=0,h=u.length;h>r;r++)s=i(u[r]),c.push(e?e(t,s):new o.Marker(s));return new o.FeatureGroup(c);case"LineString":return a=this.coordsToLatLngs(u,0,i),new o.Polyline(a,n);case"Polygon":if(2===u.length&&!u[1].length)throw new Error("Invalid GeoJSON object.");return a=this.coordsToLatLngs(u,1,i),new o.Polygon(a,n);case"MultiLineString":return a=this.coordsToLatLngs(u,1,i),new o.MultiPolyline(a,n);case"MultiPolygon":return a=this.coordsToLatLngs(u,2,i),new o.MultiPolygon(a,n);case"GeometryCollection":for(r=0,h=l.geometries.length;h>r;r++)c.push(this.geometryToLayer({geometry:l.geometries[r],type:"Feature",properties:t.properties},e,i,n));return new o.FeatureGroup(c);default:throw new Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t){return new o.LatLng(t[1],t[0],t[2])},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):(i||this.coordsToLatLng)(t[o]),a.push(n);return a},latLngToCoords:function(t){var e=[t.lng,t.lat];return t.alt!==i&&e.push(t.alt),e},latLngsToCoords:function(t){for(var e=[],i=0,n=t.length;n>i;i++)e.push(o.GeoJSON.latLngToCoords(t[i]));return e},getFeature:function(t,e){return t.feature?o.extend({},t.feature,{geometry:e}):o.GeoJSON.asFeature(e)},asFeature:function(t){return"Feature"===t.type?t:{type:"Feature",properties:{},geometry:t}}});var a={toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"Point",coordinates:o.GeoJSON.latLngToCoords(this.getLatLng())})}};o.Marker.include(a),o.Circle.include(a),o.CircleMarker.include(a),o.Polyline.include({toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"LineString",coordinates:o.GeoJSON.latLngsToCoords(this.getLatLngs())})}}),o.Polygon.include({toGeoJSON:function(){var t,e,i,n=[o.GeoJSON.latLngsToCoords(this.getLatLngs())];if(n[0].push(n[0][0]),this._holes)for(t=0,e=this._holes.length;e>t;t++)i=o.GeoJSON.latLngsToCoords(this._holes[t]),i.push(i[0]),n.push(i);return o.GeoJSON.getFeature(this,{type:"Polygon",coordinates:n})}}),function(){function t(t){return function(){var e=[];return this.eachLayer(function(t){e.push(t.toGeoJSON().geometry.coordinates)}),o.GeoJSON.getFeature(this,{type:t,coordinates:e})}}o.MultiPolyline.include({toGeoJSON:t("MultiLineString")}),o.MultiPolygon.include({toGeoJSON:t("MultiPolygon")}),o.LayerGroup.include({toGeoJSON:function(){var e,i=this.feature&&this.feature.geometry,n=[];if(i&&"MultiPoint"===i.type)return t("MultiPoint").call(this);var s=i&&"GeometryCollection"===i.type;return this.eachLayer(function(t){t.toGeoJSON&&(e=t.toGeoJSON(),n.push(s?e.geometry:o.GeoJSON.asFeature(e)))}),s?o.GeoJSON.getFeature(this,{geometries:n,type:"GeometryCollection"}):{type:"FeatureCollection",features:n}}})}(),o.geoJson=function(t,e){return new o.GeoJSON(t,e)},o.DomEvent={addListener:function(t,e,i,n){var s,a,r,h=o.stamp(i),l="_leaflet_"+e+h;return t[l]?this:(s=function(e){return i.call(n||t,e||o.DomEvent._getEvent())},o.Browser.pointer&&0===e.indexOf("touch")?this.addPointerListener(t,e,s,h):(o.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,s,h),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",s,!1),t.addEventListener(e,s,!1)):"mouseenter"===e||"mouseleave"===e?(a=s,r="mouseenter"===e?"mouseover":"mouseout",s=function(e){return o.DomEvent._checkMouse(t,e)?a(e):void 0},t.addEventListener(r,s,!1)):"click"===e&&o.Browser.android?(a=s,s=function(t){return o.DomEvent._filterClick(t,a)},t.addEventListener(e,s,!1)):t.addEventListener(e,s,!1):"attachEvent"in t&&t.attachEvent("on"+e,s),t[l]=s,this))},removeListener:function(t,e,i){var n=o.stamp(i),s="_leaflet_"+e+n,a=t[s];return a?(o.Browser.pointer&&0===e.indexOf("touch")?this.removePointerListener(t,e,n):o.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,n):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this):this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,o.DomEvent._skipped(t),this},disableScrollPropagation:function(t){var e=o.DomEvent.stopPropagation;return o.DomEvent.on(t,"mousewheel",e).on(t,"MozMousePixelScroll",e)},disableClickPropagation:function(t){for(var e=o.DomEvent.stopPropagation,i=o.Draggable.START.length-1;i>=0;i--)o.DomEvent.on(t,o.Draggable.START[i],e);return o.DomEvent.on(t,"click",o.DomEvent._fakeStop).on(t,"dblclick",e)},preventDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return o.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,e){if(!e)return new o.Point(t.clientX,t.clientY);var i=e.getBoundingClientRect();return new o.Point(t.clientX-i.left-e.clientLeft,t.clientY-i.top-e.clientTop)},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_skipEvents:{},_fakeStop:function(t){o.DomEvent._skipEvents[t.type]=!0},_skipped:function(t){var e=this._skipEvents[t.type];return this._skipEvents[t.type]=!1,e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e},_filterClick:function(t,e){var i=t.timeStamp||t.originalEvent.timeStamp,n=o.DomEvent._lastClick&&i-o.DomEvent._lastClick;return n&&n>100&&500>n||t.target._simulatedClick&&!t._simulated?void o.DomEvent.stop(t):(o.DomEvent._lastClick=i,e(t))}},o.DomEvent.on=o.DomEvent.addListener,o.DomEvent.off=o.DomEvent.removeListener,o.Draggable=o.Class.extend({includes:o.Mixin.Events,statics:{START:o.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"}},initialize:function(t,e){this._element=t,this._dragStartTarget=e||t},enable:function(){if(!this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.on(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.off(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(this._moved=!1,!(t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(o.DomEvent.stopPropagation(t),o.Draggable._disabled||(o.DomUtil.disableImageDrag(),o.DomUtil.disableTextSelection(),this._moving)))){var i=t.touches?t.touches[0]:t;this._startPoint=new o.Point(i.clientX,i.clientY),this._startPos=this._newPos=o.DomUtil.getPosition(this._element),o.DomEvent.on(e,o.Draggable.MOVE[t.type],this._onMove,this).on(e,o.Draggable.END[t.type],this._onUp,this)}},_onMove:function(t){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,n=new o.Point(i.clientX,i.clientY),s=n.subtract(this._startPoint);(s.x||s.y)&&(o.Browser.touch&&Math.abs(s.x)+Math.abs(s.y)<3||(o.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=o.DomUtil.getPosition(this._element).subtract(s),o.DomUtil.addClass(e.body,"leaflet-dragging"),this._lastTarget=t.target||t.srcElement,o.DomUtil.addClass(this._lastTarget,"leaflet-drag-target")),this._newPos=this._startPos.add(s),this._moving=!0,o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget)))},_updatePosition:function(){this.fire("predrag"),o.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(){o.DomUtil.removeClass(e.body,"leaflet-dragging"),this._lastTarget&&(o.DomUtil.removeClass(this._lastTarget,"leaflet-drag-target"),this._lastTarget=null);for(var t in o.Draggable.MOVE)o.DomEvent.off(e,o.Draggable.MOVE[t],this._onMove).off(e,o.Draggable.END[t],this._onUp);o.DomUtil.enableImageDrag(),o.DomUtil.enableTextSelection(),this._moved&&this._moving&&(o.Util.cancelAnimFrame(this._animRequest),this.fire("dragend",{distance:this._newPos.distanceTo(this._startPos)})),this._moving=!1}}),o.Handler=o.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),o.Map.mergeOptions({dragging:!0,inertia:!o.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:o.Browser.touch?32:18,easeLinearity:.25,worldCopyJump:!1}),o.Map.Drag=o.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new o.Draggable(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this),t.whenReady(this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.project([0,180]).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(t){var e=this._map,i=e.options,n=+new Date-this._lastTime,s=!i.inertia||n>i.inertiaThreshold||!this._positions[0];if(e.fire("dragend",t),s)e.fire("moveend");else{var a=this._lastPos.subtract(this._positions[0]),r=(this._lastTime+n-this._times[0])/1e3,h=i.easeLinearity,l=a.multiplyBy(h/r),u=l.distanceTo([0,0]),c=Math.min(i.inertiaMaxSpeed,u),d=l.multiplyBy(c/u),p=c/(i.inertiaDeceleration*h),_=d.multiplyBy(-p/2).round();_.x&&_.y?(_=e._limitOffset(_,e.options.maxBounds),o.Util.requestAnimFrame(function(){e.panBy(_,{duration:p,easeLinearity:h,noMoveStart:!0})})):e.fire("moveend")}}}),o.Map.addInitHook("addHandler","dragging",o.Map.Drag),o.Map.mergeOptions({doubleClickZoom:!0}),o.Map.DoubleClickZoom=o.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var e=this._map,i=e.getZoom()+(t.originalEvent.shiftKey?-1:1);"center"===e.options.doubleClickZoom?e.setZoom(i):e.setZoomAround(t.containerPoint,i)}}),o.Map.addInitHook("addHandler","doubleClickZoom",o.Map.DoubleClickZoom),o.Map.mergeOptions({scrollWheelZoom:!0}),o.Map.ScrollWheelZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),o.DomEvent.on(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault),this._delta=0},removeHooks:function(){o.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll),o.DomEvent.off(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault)},_onWheelScroll:function(t){var e=o.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(o.bind(this._performZoom,this),i),o.DomEvent.preventDefault(t),o.DomEvent.stopPropagation(t)},_performZoom:function(){var t=this._map,e=this._delta,i=t.getZoom();e=e>0?Math.ceil(e):Math.floor(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e&&("center"===t.options.scrollWheelZoom?t.setZoom(i+e):t.setZoomAround(this._lastMousePos,i+e))}}),o.Map.addInitHook("addHandler","scrollWheelZoom",o.Map.ScrollWheelZoom),o.extend(o.DomEvent,{_touchstart:o.Browser.msPointer?"MSPointerDown":o.Browser.pointer?"pointerdown":"touchstart",_touchend:o.Browser.msPointer?"MSPointerUp":o.Browser.pointer?"pointerup":"touchend",addDoubleTapListener:function(t,i,n){function s(t){var e;if(o.Browser.pointer?(_.push(t.pointerId),e=_.length):e=t.touches.length,!(e>1)){var i=Date.now(),n=i-(r||i);h=t.touches?t.touches[0]:t,l=n>0&&u>=n,r=i}}function a(t){if(o.Browser.pointer){var e=_.indexOf(t.pointerId);if(-1===e)return;_.splice(e,1)}if(l){if(o.Browser.pointer){var n,s={};for(var a in h)n=h[a],s[a]="function"==typeof n?n.bind(h):n;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",d=this._touchstart,p=this._touchend,_=[];t[c+d+n]=s,t[c+p+n]=a;var m=o.Browser.pointer?e.documentElement:t;return t.addEventListener(d,s,!1),m.addEventListener(p,a,!1),o.Browser.pointer&&m.addEventListener(o.DomEvent.POINTER_CANCEL,a,!1),this},removeDoubleTapListener:function(t,i){var n="_leaflet_";return t.removeEventListener(this._touchstart,t[n+this._touchstart+i],!1),(o.Browser.pointer?e.documentElement:t).removeEventListener(this._touchend,t[n+this._touchend+i],!1),o.Browser.pointer&&e.documentElement.removeEventListener(o.DomEvent.POINTER_CANCEL,t[n+this._touchend+i],!1),this}}),o.extend(o.DomEvent,{POINTER_DOWN:o.Browser.msPointer?"MSPointerDown":"pointerdown",POINTER_MOVE:o.Browser.msPointer?"MSPointerMove":"pointermove",POINTER_UP:o.Browser.msPointer?"MSPointerUp":"pointerup",POINTER_CANCEL:o.Browser.msPointer?"MSPointerCancel":"pointercancel",_pointers:[],_pointerDocumentListener:!1,addPointerListener:function(t,e,i,n){switch(e){case"touchstart":return this.addPointerListenerStart(t,e,i,n);case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){o.DomEvent.preventDefault(t);for(var e=!1,i=0;i<r.length;i++)if(r[i].pointerId===t.pointerId){e=!0;
+break}e||r.push(t),t.touches=r.slice(),t.changedTouches=[t],n(t)};if(t[a+"touchstart"+s]=h,t.addEventListener(this.POINTER_DOWN,h,!1),!this._pointerDocumentListener){var l=function(t){for(var e=0;e<r.length;e++)if(r[e].pointerId===t.pointerId){r.splice(e,1);break}};e.documentElement.addEventListener(this.POINTER_UP,l,!1),e.documentElement.addEventListener(this.POINTER_CANCEL,l,!1),this._pointerDocumentListener=!0}return this},addPointerListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons){for(var e=0;e<a.length;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._pointers;return t[s+"touchmove"+n]=o,t.addEventListener(this.POINTER_MOVE,o,!1),this},addPointerListenerEnd:function(t,e,i,n){var o="_leaflet_",s=this._pointers,a=function(t){for(var e=0;e<s.length;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener(this.POINTER_UP,a,!1),t.addEventListener(this.POINTER_CANCEL,a,!1),this},removePointerListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener(this.POINTER_DOWN,o,!1);break;case"touchmove":t.removeEventListener(this.POINTER_MOVE,o,!1);break;case"touchend":t.removeEventListener(this.POINTER_UP,o,!1),t.removeEventListener(this.POINTER_CANCEL,o,!1)}return this}}),o.Map.mergeOptions({touchZoom:o.Browser.touch&&!o.Browser.android23,bounceAtZoomLimits:!0}),o.Map.TouchZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var n=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=n.add(s)._divideBy(2),this._startDist=n.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),o.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),o.DomEvent.preventDefault(t)}},_onTouchMove:function(t){var e=this._map;if(t.touches&&2===t.touches.length&&this._zooming){var i=e.mouseEventToLayerPoint(t.touches[0]),n=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(n)/this._startDist,this._delta=i._add(n)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(e.options.bounceAtZoomLimits||!(e.getZoom()===e.getMinZoom()&&this._scale<1||e.getZoom()===e.getMaxZoom()&&this._scale>1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!t.shiftKey||1!==t.which&&1!==t.button?!1:(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='<input type="radio" class="leaflet-control-layers-selector" name="'+t+'"';i&&(n+=' checked="checked"'),n+="/>";var o=e.createElement("div");return o.innerHTML=n,o.firstChild},_addItem:function(t){var i,n=e.createElement("label"),s=this._map.hasLayer(t.layer);t.overlay?(i=e.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=s):i=this._createRadioElement("leaflet-base-layers",s),i.layerId=o.stamp(t.layer),o.DomEvent.on(i,"click",this._onInputClick,this);var a=e.createElement("span");a.innerHTML=" "+t.name,n.appendChild(i),n.appendChild(a);var r=t.overlay?this._overlaysList:this._baseLayersList;return r.appendChild(n),n},_onInputClick:function(){var t,e,i,n=this._form.getElementsByTagName("input"),o=n.length;for(this._handlingClick=!0,t=0;o>t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,!0)},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return(e&&e.animate)===!0||this.getSize().contains(i)?(this.panBy(i,e),!0):!1}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return i.animate===!0||this.getSize().contains(o)?(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0):!1},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a})},this)},_onZoomTransitionEnd:function(){this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth),this._animating=!1},_clearBgBuffer:function(){var t=this._map;!t||t._animatingZoom||t.touchZoom._zooming||(this._bgBuffer.innerHTML="",this._bgBuffer.style[o.DomUtil.TRANSFORM]="")},_prepareBgBuffer:function(){var t=this._tileContainer,e=this._bgBuffer,i=this._getLoadedTilesPercentage(e),n=this._getLoadedTilesPercentage(t);return e&&i>.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js
new file mode 100644
index 00000000..f1860f12
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/lodash/4.5.1/lodash.js
@@ -0,0 +1,14932 @@
+/**
+ * @license
+ * lodash 4.5.1 <https://lodash.com/>
+ * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <https://lodash.com/license>
+ */
+;(function() {
+
+ /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+ var undefined;
+
+ /** Used as the semantic version number. */
+ var VERSION = '4.5.1';
+
+ /** Used to compose bitmasks for wrapper metadata. */
+ var BIND_FLAG = 1,
+ BIND_KEY_FLAG = 2,
+ CURRY_BOUND_FLAG = 4,
+ CURRY_FLAG = 8,
+ CURRY_RIGHT_FLAG = 16,
+ PARTIAL_FLAG = 32,
+ PARTIAL_RIGHT_FLAG = 64,
+ ARY_FLAG = 128,
+ REARG_FLAG = 256,
+ FLIP_FLAG = 512;
+
+ /** Used to compose bitmasks for comparison styles. */
+ var UNORDERED_COMPARE_FLAG = 1,
+ PARTIAL_COMPARE_FLAG = 2;
+
+ /** Used as default options for `_.truncate`. */
+ var DEFAULT_TRUNC_LENGTH = 30,
+ DEFAULT_TRUNC_OMISSION = '...';
+
+ /** Used to detect hot functions by number of calls within a span of milliseconds. */
+ var HOT_COUNT = 150,
+ HOT_SPAN = 16;
+
+ /** Used as the size to enable large array optimizations. */
+ var LARGE_ARRAY_SIZE = 200;
+
+ /** Used to indicate the type of lazy iteratees. */
+ var LAZY_FILTER_FLAG = 1,
+ LAZY_MAP_FLAG = 2,
+ LAZY_WHILE_FLAG = 3;
+
+ /** Used as the `TypeError` message for "Functions" methods. */
+ var FUNC_ERROR_TEXT = 'Expected a function';
+
+ /** Used to stand-in for `undefined` hash values. */
+ var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+ /** Used as references for various `Number` constants. */
+ var INFINITY = 1 / 0,
+ MAX_SAFE_INTEGER = 9007199254740991,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+ /** Used as references for the maximum length and index of an array. */
+ var MAX_ARRAY_LENGTH = 4294967295,
+ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
+ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+
+ /** Used as the internal argument placeholder. */
+ var PLACEHOLDER = '__lodash_placeholder__';
+
+ /** `Object#toString` result references. */
+ var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]',
+ weakMapTag = '[object WeakMap]',
+ weakSetTag = '[object WeakSet]';
+
+ var arrayBufferTag = '[object ArrayBuffer]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+ /** Used to match empty string literals in compiled template source. */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+ /** Used to match HTML entities and HTML characters. */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
+ reUnescapedHtml = /[&<>"'`]/g,
+ reHasEscapedHtml = RegExp(reEscapedHtml.source),
+ reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+ /** Used to match template delimiters. */
+ var reEscape = /<%-([\s\S]+?)%>/g,
+ reEvaluate = /<%([\s\S]+?)%>/g,
+ reInterpolate = /<%=([\s\S]+?)%>/g;
+
+ /** Used to match property names within property paths. */
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/,
+ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;
+
+ /** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
+ reHasRegExpChar = RegExp(reRegExpChar.source);
+
+ /** Used to match leading and trailing whitespace. */
+ var reTrim = /^\s+|\s+$/g,
+ reTrimStart = /^\s+/,
+ reTrimEnd = /\s+$/;
+
+ /** Used to match backslashes in property paths. */
+ var reEscapeChar = /\\(\\)?/g;
+
+ /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+ /** Used to match `RegExp` flags from their coerced string values. */
+ var reFlags = /\w*$/;
+
+ /** Used to detect hexadecimal string values. */
+ var reHasHexPrefix = /^0x/i;
+
+ /** Used to detect bad signed hexadecimal string values. */
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+ /** Used to detect binary string values. */
+ var reIsBinary = /^0b[01]+$/i;
+
+ /** Used to detect host constructors (Safari > 5). */
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+ /** Used to detect octal string values. */
+ var reIsOctal = /^0o[0-7]+$/i;
+
+ /** Used to detect unsigned integer values. */
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+ /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
+ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
+
+ /** Used to ensure capturing order of template delimiters. */
+ var reNoMatch = /($^)/;
+
+ /** Used to match unescaped characters in compiled string literals. */
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+
+ /** Used to compose unicode character classes. */
+ var rsAstralRange = '\\ud800-\\udfff',
+ rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
+ rsComboSymbolsRange = '\\u20d0-\\u20f0',
+ rsDingbatRange = '\\u2700-\\u27bf',
+ rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
+ rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
+ rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
+ rsQuoteRange = '\\u2018\\u2019\\u201c\\u201d',
+ rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
+ rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
+ rsVarRange = '\\ufe0e\\ufe0f',
+ rsBreakRange = rsMathOpRange + rsNonCharRange + rsQuoteRange + rsSpaceRange;
+
+ /** Used to compose unicode capture groups. */
+ var rsAstral = '[' + rsAstralRange + ']',
+ rsBreak = '[' + rsBreakRange + ']',
+ rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
+ rsDigits = '\\d+',
+ rsDingbat = '[' + rsDingbatRange + ']',
+ rsLower = '[' + rsLowerRange + ']',
+ rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
+ rsFitz = '\\ud83c[\\udffb-\\udfff]',
+ rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
+ rsNonAstral = '[^' + rsAstralRange + ']',
+ rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
+ rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
+ rsUpper = '[' + rsUpperRange + ']',
+ rsZWJ = '\\u200d';
+
+ /** Used to compose unicode regexes. */
+ var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')',
+ rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')',
+ reOptMod = rsModifier + '?',
+ rsOptVar = '[' + rsVarRange + ']?',
+ rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
+ rsSeq = rsOptVar + reOptMod + rsOptJoin,
+ rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
+ rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
+
+ /**
+ * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
+ * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
+ */
+ var reComboMark = RegExp(rsCombo, 'g');
+
+ /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
+ var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
+
+ /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
+ var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']');
+
+ /** Used to match non-compound words composed of alphanumeric characters. */
+ var reBasicWord = /[a-zA-Z0-9]+/g;
+
+ /** Used to match complex or compound words. */
+ var reComplexWord = RegExp([
+ rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
+ rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')',
+ rsUpper + '?' + rsLowerMisc + '+',
+ rsUpper + '+',
+ rsDigits,
+ rsEmoji
+ ].join('|'), 'g');
+
+ /** Used to detect strings that need a more robust regexp to match words. */
+ var reHasComplexWord = /[a-z][A-Z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
+
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'Buffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
+ 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_',
+ 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
+ ];
+
+ /** Used to make template sourceURLs easier to identify. */
+ var templateCounter = -1;
+
+ /** Used to identify `toStringTag` values of typed arrays. */
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dateTag] = typedArrayTags[errorTag] =
+ typedArrayTags[funcTag] = typedArrayTags[mapTag] =
+ typedArrayTags[numberTag] = typedArrayTags[objectTag] =
+ typedArrayTags[regexpTag] = typedArrayTags[setTag] =
+ typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+
+ /** Used to identify `toStringTag` values supported by `_.clone`. */
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
+ cloneableTags[dateTag] = cloneableTags[float32Tag] =
+ cloneableTags[float64Tag] = cloneableTags[int8Tag] =
+ cloneableTags[int16Tag] = cloneableTags[int32Tag] =
+ cloneableTags[mapTag] = cloneableTags[numberTag] =
+ cloneableTags[objectTag] = cloneableTags[regexpTag] =
+ cloneableTags[setTag] = cloneableTags[stringTag] =
+ cloneableTags[symbolTag] = cloneableTags[uint8Tag] =
+ cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] =
+ cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[weakMapTag] = false;
+
+ /** Used to map latin-1 supplementary letters to basic latin letters. */
+ var deburredLetters = {
+ '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+ '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+ '\xc7': 'C', '\xe7': 'c',
+ '\xd0': 'D', '\xf0': 'd',
+ '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+ '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+ '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+ '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
+ '\xd1': 'N', '\xf1': 'n',
+ '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+ '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+ '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+ '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
+ '\xc6': 'Ae', '\xe6': 'ae',
+ '\xde': 'Th', '\xfe': 'th',
+ '\xdf': 'ss'
+ };
+
+ /** Used to map characters to HTML entities. */
+ var htmlEscapes = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#39;',
+ '`': '&#96;'
+ };
+
+ /** Used to map HTML entities to characters. */
+ var htmlUnescapes = {
+ '&amp;': '&',
+ '&lt;': '<',
+ '&gt;': '>',
+ '&quot;': '"',
+ '&#39;': "'",
+ '&#96;': '`'
+ };
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used to escape characters for inclusion in compiled string literals. */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ /** Built-in method references without a dependency on `root`. */
+ var freeParseFloat = parseFloat,
+ freeParseInt = parseInt;
+
+ /** Detect free variable `exports`. */
+ var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType)
+ ? exports
+ : undefined;
+
+ /** Detect free variable `module`. */
+ var freeModule = (objectTypes[typeof module] && module && !module.nodeType)
+ ? module
+ : undefined;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = (freeModule && freeModule.exports === freeExports)
+ ? freeExports
+ : undefined;
+
+ /** Detect free variable `global` from Node.js. */
+ var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
+
+ /** Detect free variable `self`. */
+ var freeSelf = checkGlobal(objectTypes[typeof self] && self);
+
+ /** Detect free variable `window`. */
+ var freeWindow = checkGlobal(objectTypes[typeof window] && window);
+
+ /** Detect `this` as the global object. */
+ var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
+
+ /**
+ * Used as a reference to the global object.
+ *
+ * The `this` value is used if it's the global object to avoid Greasemonkey's
+ * restricted `window` object, otherwise the `window` object is used.
+ */
+ var root = freeGlobal ||
+ ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) ||
+ freeSelf || thisGlobal || Function('return this')();
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Adds the key-value `pair` to `map`.
+ *
+ * @private
+ * @param {Object} map The map to modify.
+ * @param {Array} pair The key-value pair to add.
+ * @returns {Object} Returns `map`.
+ */
+ function addMapEntry(map, pair) {
+ map.set(pair[0], pair[1]);
+ return map;
+ }
+
+ /**
+ * Adds `value` to `set`.
+ *
+ * @private
+ * @param {Object} set The set to modify.
+ * @param {*} value The value to add.
+ * @returns {Object} Returns `set`.
+ */
+ function addSetEntry(set, value) {
+ set.add(value);
+ return set;
+ }
+
+ /**
+ * A faster alternative to `Function#apply`, this function invokes `func`
+ * with the `this` binding of `thisArg` and the arguments of `args`.
+ *
+ * @private
+ * @param {Function} func The function to invoke.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} args The arguments to invoke `func` with.
+ * @returns {*} Returns the result of `func`.
+ */
+ function apply(func, thisArg, args) {
+ var length = args.length;
+ switch (length) {
+ case 0: return func.call(thisArg);
+ case 1: return func.call(thisArg, args[0]);
+ case 2: return func.call(thisArg, args[0], args[1]);
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+ }
+
+ /**
+ * A specialized version of `baseAggregator` for arrays.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * Creates a new array concatenating `array` with `other`.
+ *
+ * @private
+ * @param {Array} array The first array to concatenate.
+ * @param {Array} other The second array to concatenate.
+ * @returns {Array} Returns the new concatenated array.
+ */
+ function arrayConcat(array, other) {
+ var index = -1,
+ length = array.length,
+ othIndex = -1,
+ othLength = other.length,
+ result = Array(length + othLength);
+
+ while (++index < length) {
+ result[index] = array[index];
+ }
+ while (++othIndex < othLength) {
+ result[index++] = other[othIndex];
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.forEach` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.includes` for arrays without support for
+ * specifying an index to search from.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} target The value to search for.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludes(array, value) {
+ return !!array.length && baseIndexOf(array, value, 0) > -1;
+ }
+
+ /**
+ * A specialized version of `_.includesWith` for arrays without support for
+ * specifying an index to search from.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} target The value to search for.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+ function arrayIncludesWith(array, value, comparator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
+ /**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.reduce` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the first element of `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1,
+ length = array.length;
+
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the last element of `array` as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initAccum) {
+ var length = array.length;
+ if (initAccum && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * The base implementation of methods like `_.max` and `_.min` which accepts a
+ * `comparator` to determine the extremum value.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The iteratee invoked per iteration.
+ * @param {Function} comparator The comparator used to compare values.
+ * @returns {*} Returns the extremum value.
+ */
+ function baseExtremum(array, iteratee, comparator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index],
+ current = iteratee(value);
+
+ if (current != null && (computed === undefined
+ ? current === current
+ : comparator(current, computed)
+ )) {
+ var computed = current,
+ result = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of methods like `_.find` and `_.findKey`, without
+ * support for iteratee shorthands, which iterates over `collection` using
+ * `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to search.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @param {boolean} [retKey] Specify returning the key of the found element instead of the element itself.
+ * @returns {*} Returns the found element or its key, else `undefined`.
+ */
+ function baseFind(collection, predicate, eachFunc, retKey) {
+ var result;
+ eachFunc(collection, function(value, key, collection) {
+ if (predicate(value, key, collection)) {
+ result = retKey ? key : value;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseFindIndex(array, predicate, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOf(array, value, fromIndex) {
+ if (value !== value) {
+ return indexOfNaN(array, fromIndex);
+ }
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.reduce` and `_.reduceRight`, without support
+ * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} accumulator The initial value.
+ * @param {boolean} initAccum Specify using the first or last element of `collection` as the initial value.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the accumulated value.
+ */
+ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection) {
+ accumulator = initAccum
+ ? (initAccum = false, value)
+ : iteratee(accumulator, value, index, collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.sortBy` which uses `comparer` to define
+ * the sort order of `array` and replaces criteria objects with their
+ * corresponding values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.sum` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function baseSum(array, iteratee) {
+ var result,
+ index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var current = iteratee(array[index]);
+ if (current !== undefined) {
+ result = result === undefined ? current : (result + current);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+ function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
+ * of key-value pairs for `object` corresponding to the property names of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the new array of key-value pairs.
+ */
+ function baseToPairs(object, props) {
+ return arrayMap(props, function(key) {
+ return [key, object[key]];
+ });
+ }
+
+ /**
+ * The base implementation of `_.unary` without support for storing wrapper metadata.
+ *
+ * @private
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new function.
+ */
+ function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+ }
+
+ /**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+ function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the first unmatched string symbol.
+ */
+ function charsStartIndex(strSymbols, chrSymbols) {
+ var index = -1,
+ length = strSymbols.length;
+
+ while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
+ * that is not found in the character symbols.
+ *
+ * @private
+ * @param {Array} strSymbols The string symbols to inspect.
+ * @param {Array} chrSymbols The character symbols to find.
+ * @returns {number} Returns the index of the last unmatched string symbol.
+ */
+ function charsEndIndex(strSymbols, chrSymbols) {
+ var index = strSymbols.length;
+
+ while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
+ return index;
+ }
+
+ /**
+ * Checks if `value` is a global object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {null|Object} Returns `value` if it's a global object, else `null`.
+ */
+ function checkGlobal(value) {
+ return (value && value.Object === Object) ? value : null;
+ }
+
+ /**
+ * Compares values to sort them in ascending order.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+ function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsNull = value === null,
+ valIsUndef = value === undefined,
+ valIsReflexive = value === value;
+
+ var othIsNull = other === null,
+ othIsUndef = other === undefined,
+ othIsReflexive = other === other;
+
+ if ((value > other && !othIsNull) || !valIsReflexive ||
+ (valIsNull && !othIsUndef && othIsReflexive) ||
+ (valIsUndef && othIsReflexive)) {
+ return 1;
+ }
+ if ((value < other && !valIsNull) || !othIsReflexive ||
+ (othIsNull && !valIsUndef && valIsReflexive) ||
+ (othIsUndef && valIsReflexive)) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Used by `_.orderBy` to compare multiple properties of a value to another
+ * and stable sort them.
+ *
+ * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
+ * specify an order of "desc" for descending or "asc" for ascending sort order
+ * of corresponding values.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {boolean[]|string[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
+
+ while (++index < length) {
+ var result = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ var order = orders[index];
+ return result * (order == 'desc' ? -1 : 1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+ }
+
+ /**
+ * Gets the number of `placeholder` occurrences in `array`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} placeholder The placeholder to search for.
+ * @returns {number} Returns the placeholder count.
+ */
+ function countHolders(array, placeholder) {
+ var length = array.length,
+ result = 0;
+
+ while (length--) {
+ if (array[length] === placeholder) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
+ *
+ * @private
+ * @param {string} letter The matched letter to deburr.
+ * @returns {string} Returns the deburred letter.
+ */
+ function deburrLetter(letter) {
+ return deburredLetters[letter];
+ }
+
+ /**
+ * Used by `_.escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeHtmlChar(chr) {
+ return htmlEscapes[chr];
+ }
+
+ /**
+ * Used by `_.template` to escape characters for inclusion in compiled string literals.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeStringChar(chr) {
+ return '\\' + stringEscapes[chr];
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `NaN` is found in `array`.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched `NaN`, else `-1`.
+ */
+ function indexOfNaN(array, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 0 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ var other = array[index];
+ if (other !== other) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Checks if `value` is a host object in IE < 9.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
+ */
+ function isHostObject(value) {
+ // Many host objects are `Object` objects that can coerce to strings
+ // despite having improperly defined `toString` methods.
+ var result = false;
+ if (value != null && typeof value.toString != 'function') {
+ try {
+ result = !!(value + '');
+ } catch (e) {}
+ }
+ return result;
+ }
+
+ /**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+ function isIndex(value, length) {
+ value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return value > -1 && value % 1 == 0 && value < length;
+ }
+
+ /**
+ * Converts `iterator` to an array.
+ *
+ * @private
+ * @param {Object} iterator The iterator to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function iteratorToArray(iterator) {
+ var data,
+ result = [];
+
+ while (!(data = iterator.next()).done) {
+ result.push(data.value);
+ }
+ return result;
+ }
+
+ /**
+ * Converts `map` to an array.
+ *
+ * @private
+ * @param {Object} map The map to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function mapToArray(map) {
+ var index = -1,
+ result = Array(map.size);
+
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+ }
+
+ /**
+ * Replaces all `placeholder` elements in `array` with an internal placeholder
+ * and returns an array of their indexes.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {*} placeholder The placeholder to replace.
+ * @returns {Array} Returns the new array of placeholder indexes.
+ */
+ function replaceHolders(array, placeholder) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
+ array[index] = PLACEHOLDER;
+ result[++resIndex] = index;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `set` to an array.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function setToArray(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Gets the number of symbols in `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the string size.
+ */
+ function stringSize(string) {
+ if (!(string && reHasComplexSymbol.test(string))) {
+ return string.length;
+ }
+ var result = reComplexSymbol.lastIndex = 0;
+ while (reComplexSymbol.test(string)) {
+ result++;
+ }
+ return result;
+ }
+
+ /**
+ * Converts `string` to an array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the converted array.
+ */
+ function stringToArray(string) {
+ return string.match(reComplexSymbol);
+ }
+
+ /**
+ * Used by `_.unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {string} chr The matched character to unescape.
+ * @returns {string} Returns the unescaped character.
+ */
+ function unescapeHtmlChar(chr) {
+ return htmlUnescapes[chr];
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a new pristine `lodash` function using the `context` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `lodash` function.
+ * @example
+ *
+ * _.mixin({ 'foo': _.constant('foo') });
+ *
+ * var lodash = _.runInContext();
+ * lodash.mixin({ 'bar': lodash.constant('bar') });
+ *
+ * _.isFunction(_.foo);
+ * // => true
+ * _.isFunction(_.bar);
+ * // => false
+ *
+ * lodash.isFunction(lodash.foo);
+ * // => false
+ * lodash.isFunction(lodash.bar);
+ * // => true
+ *
+ * // Use `context` to mock `Date#getTime` use in `_.now`.
+ * var mock = _.runInContext({
+ * 'Date': function() {
+ * return { 'getTime': getTimeMock };
+ * }
+ * });
+ *
+ * // Create a suped-up `defer` in Node.js.
+ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+ */
+ function runInContext(context) {
+ context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root;
+
+ /** Built-in constructor references. */
+ var Date = context.Date,
+ Error = context.Error,
+ Math = context.Math,
+ RegExp = context.RegExp,
+ TypeError = context.TypeError;
+
+ /** Used for built-in method references. */
+ var arrayProto = context.Array.prototype,
+ objectProto = context.Object.prototype;
+
+ /** Used to resolve the decompiled source of functions. */
+ var funcToString = context.Function.prototype.toString;
+
+ /** Used to check objects for own properties. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to generate unique IDs. */
+ var idCounter = 0;
+
+ /** Used to infer the `Object` constructor. */
+ var objectCtorString = funcToString.call(Object);
+
+ /**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+ var objectToString = objectProto.toString;
+
+ /** Used to restore the original `_` reference in `_.noConflict`. */
+ var oldDash = root._;
+
+ /** Used to detect if a method is native. */
+ var reIsNative = RegExp('^' +
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+ );
+
+ /** Built-in value references. */
+ var Buffer = moduleExports ? context.Buffer : undefined,
+ Reflect = context.Reflect,
+ Symbol = context.Symbol,
+ Uint8Array = context.Uint8Array,
+ clearTimeout = context.clearTimeout,
+ enumerate = Reflect ? Reflect.enumerate : undefined,
+ getPrototypeOf = Object.getPrototypeOf,
+ getOwnPropertySymbols = Object.getOwnPropertySymbols,
+ iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
+ objectCreate = Object.create,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ setTimeout = context.setTimeout,
+ splice = arrayProto.splice;
+
+ /* Built-in method references for those with the same name as other `lodash` methods. */
+ var nativeCeil = Math.ceil,
+ nativeFloor = Math.floor,
+ nativeIsFinite = context.isFinite,
+ nativeJoin = arrayProto.join,
+ nativeKeys = Object.keys,
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeParseInt = context.parseInt,
+ nativeRandom = Math.random,
+ nativeReverse = arrayProto.reverse;
+
+ /* Built-in method references that are verified to be native. */
+ var Map = getNative(context, 'Map'),
+ Set = getNative(context, 'Set'),
+ WeakMap = getNative(context, 'WeakMap'),
+ nativeCreate = getNative(Object, 'create');
+
+ /** Used to store function metadata. */
+ var metaMap = WeakMap && new WeakMap;
+
+ /** Used to detect maps, sets, and weakmaps. */
+ var mapCtorString = Map ? funcToString.call(Map) : '',
+ setCtorString = Set ? funcToString.call(Set) : '',
+ weakMapCtorString = WeakMap ? funcToString.call(WeakMap) : '';
+
+ /** Used to convert symbols to primitives and strings. */
+ var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolValueOf = Symbol ? symbolProto.valueOf : undefined,
+ symbolToString = Symbol ? symbolProto.toString : undefined;
+
+ /** Used to lookup unminified function names. */
+ var realNames = {};
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object which wraps `value` to enable implicit method
+ * chaining. Methods that operate on and return arrays, collections, and
+ * functions can be chained together. Methods that retrieve a single value or
+ * may return a primitive value will automatically end the chain sequence and
+ * return the unwrapped value. Otherwise, the value must be unwrapped with
+ * `_#value`.
+ *
+ * Explicit chaining, which must be unwrapped with `_#value` in all cases,
+ * may be enabled using `_.chain`.
+ *
+ * The execution of chained methods is lazy, that is, it's deferred until
+ * `_#value` is implicitly or explicitly called.
+ *
+ * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
+ * fusion is an optimization to merge iteratee calls; this avoids the creation
+ * of intermediate arrays and can greatly reduce the number of iteratee executions.
+ * Sections of a chain sequence qualify for shortcut fusion if the section is
+ * applied to an array of at least two hundred elements and any iteratees
+ * accept only one argument. The heuristic for whether a section qualifies
+ * for shortcut fusion is subject to change.
+ *
+ * Chaining is supported in custom builds as long as the `_#value` method is
+ * directly or indirectly included in the build.
+ *
+ * In addition to lodash methods, wrappers have `Array` and `String` methods.
+ *
+ * The wrapper `Array` methods are:
+ * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
+ *
+ * The wrapper `String` methods are:
+ * `replace` and `split`
+ *
+ * The wrapper methods that support shortcut fusion are:
+ * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
+ * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
+ * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
+ *
+ * The chainable wrapper methods are:
+ * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
+ * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
+ * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
+ * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`,
+ * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`,
+ * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flattenDepth`,
+ * `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, `functionsIn`,
+ * `groupBy`, `initial`, `intersection`, `intersectionBy`, `intersectionWith`,
+ * `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, `keys`, `keysIn`,
+ * `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
+ * `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, `nthArg`,
+ * `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, `overEvery`,
+ * `overSome`, `partial`, `partialRight`, `partition`, `pick`, `pickBy`, `plant`,
+ * `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, `pullAt`, `push`,
+ * `range`, `rangeRight`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
+ * `sampleSize`, `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`,
+ * `splice`, `spread`, `tail`, `take`, `takeRight`, `takeRightWhile`,
+ * `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, `toPairs`, `toPairsIn`,
+ * `toPath`, `toPlainObject`, `transform`, `unary`, `union`, `unionBy`,
+ * `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, `unshift`, `unzip`,
+ * `unzipWith`, `values`, `valuesIn`, `without`, `wrap`, `xor`, `xorBy`,
+ * `xorWith`, `zip`, `zipObject`, `zipObjectDeep`, and `zipWith`
+ *
+ * The wrapper methods that are **not** chainable by default are:
+ * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
+ * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`,
+ * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
+ * `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, `forIn`,
+ * `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`,
+ * `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`,
+ * `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`,
+ * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
+ * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`,
+ * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
+ * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`,
+ * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
+ * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`,
+ * `lt`, `lte`, `max`, `maxBy`, `mean`, `min`, `minBy`, `noConflict`, `noop`,
+ * `now`, `pad`, `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`,
+ * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `sample`,
+ * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`,
+ * `sortedLastIndex`, `sortedLastIndexBy`, `startCase`, `startsWith`, `subtract`,
+ * `sum`, `sumBy`, `template`, `times`, `toLower`, `toInteger`, `toLength`,
+ * `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, `trimEnd`,
+ * `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, `upperFirst`,
+ * `value`, and `words`
+ *
+ * @name _
+ * @constructor
+ * @category Seq
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2, 3]);
+ *
+ * // Returns an unwrapped value.
+ * wrapped.reduce(_.add);
+ * // => 6
+ *
+ * // Returns a wrapped value.
+ * var squares = wrapped.map(square);
+ *
+ * _.isArray(squares);
+ * // => false
+ *
+ * _.isArray(squares.value());
+ * // => true
+ */
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, '__wrapped__')) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+
+ /**
+ * The function whose prototype all chaining wrappers inherit from.
+ *
+ * @private
+ */
+ function baseLodash() {
+ // No operation performed.
+ }
+
+ /**
+ * The base constructor for creating `lodash` wrapper objects.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
+ */
+ function LodashWrapper(value, chainAll) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__chain__ = !!chainAll;
+ this.__index__ = 0;
+ this.__values__ = undefined;
+ }
+
+ /**
+ * By default, the template delimiters used by lodash are like those in
+ * embedded Ruby (ERB). Change the following template settings to use
+ * alternative delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type {Object}
+ */
+ lodash.templateSettings = {
+
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'escape': reEscape,
+
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'evaluate': reEvaluate,
+
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @memberOf _.templateSettings
+ * @type {RegExp}
+ */
+ 'interpolate': reInterpolate,
+
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @memberOf _.templateSettings
+ * @type {string}
+ */
+ 'variable': '',
+
+ /**
+ * Used to import variables into the compiled template.
+ *
+ * @memberOf _.templateSettings
+ * @type {Object}
+ */
+ 'imports': {
+
+ /**
+ * A reference to the `lodash` function.
+ *
+ * @memberOf _.templateSettings.imports
+ * @type {Function}
+ */
+ '_': lodash
+ }
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ *
+ * @private
+ * @constructor
+ * @param {*} value The value to wrap.
+ */
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = MAX_ARRAY_LENGTH;
+ this.__views__ = [];
+ }
+
+ /**
+ * Creates a clone of the lazy wrapper object.
+ *
+ * @private
+ * @name clone
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the cloned `LazyWrapper` object.
+ */
+ function lazyClone() {
+ var result = new LazyWrapper(this.__wrapped__);
+ result.__actions__ = copyArray(this.__actions__);
+ result.__dir__ = this.__dir__;
+ result.__filtered__ = this.__filtered__;
+ result.__iteratees__ = copyArray(this.__iteratees__);
+ result.__takeCount__ = this.__takeCount__;
+ result.__views__ = copyArray(this.__views__);
+ return result;
+ }
+
+ /**
+ * Reverses the direction of lazy iteration.
+ *
+ * @private
+ * @name reverse
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ */
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result = new LazyWrapper(this);
+ result.__dir__ = -1;
+ result.__filtered__ = true;
+ } else {
+ result = this.clone();
+ result.__dir__ *= -1;
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the unwrapped value from its lazy wrapper.
+ *
+ * @private
+ * @name value
+ * @memberOf LazyWrapper
+ * @returns {*} Returns the unwrapped value.
+ */
+ function lazyValue() {
+ var array = this.__wrapped__.value(),
+ dir = this.__dir__,
+ isArr = isArray(array),
+ isRight = dir < 0,
+ arrLength = isArr ? array.length : 0,
+ view = getView(0, arrLength, this.__views__),
+ start = view.start,
+ end = view.end,
+ length = end - start,
+ index = isRight ? end : (start - 1),
+ iteratees = this.__iteratees__,
+ iterLength = iteratees.length,
+ resIndex = 0,
+ takeCount = nativeMin(length, this.__takeCount__);
+
+ if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
+ (arrLength == length && takeCount == length)) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var result = [];
+
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+
+ var iterIndex = -1,
+ value = array[index];
+
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex],
+ iteratee = data.iteratee,
+ type = data.type,
+ computed = iteratee(value);
+
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result[resIndex++] = value;
+ }
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an hash object.
+ *
+ * @private
+ * @constructor
+ * @returns {Object} Returns the new hash object.
+ */
+ function Hash() {}
+
+ /**
+ * Removes `key` and its value from the hash.
+ *
+ * @private
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function hashDelete(hash, key) {
+ return hashHas(hash, key) && delete hash[key];
+ }
+
+ /**
+ * Gets the hash value for `key`.
+ *
+ * @private
+ * @param {Object} hash The hash to query.
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function hashGet(hash, key) {
+ if (nativeCreate) {
+ var result = hash[key];
+ return result === HASH_UNDEFINED ? undefined : result;
+ }
+ return hasOwnProperty.call(hash, key) ? hash[key] : undefined;
+ }
+
+ /**
+ * Checks if a hash value for `key` exists.
+ *
+ * @private
+ * @param {Object} hash The hash to query.
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function hashHas(hash, key) {
+ return nativeCreate ? hash[key] !== undefined : hasOwnProperty.call(hash, key);
+ }
+
+ /**
+ * Sets the hash `key` to `value`.
+ *
+ * @private
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ */
+ function hashSet(hash, key, value) {
+ hash[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a map cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+ function MapCache(values) {
+ var index = -1,
+ length = values ? values.length : 0;
+
+ this.clear();
+ while (++index < length) {
+ var entry = values[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the map.
+ *
+ * @private
+ * @name clear
+ * @memberOf MapCache
+ */
+ function mapClear() {
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': Map ? new Map : [],
+ 'string': new Hash
+ };
+ }
+
+ /**
+ * Removes `key` and its value from the map.
+ *
+ * @private
+ * @name delete
+ * @memberOf MapCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function mapDelete(key) {
+ var data = this.__data__;
+ if (isKeyable(key)) {
+ return hashDelete(typeof key == 'string' ? data.string : data.hash, key);
+ }
+ return Map ? data.map['delete'](key) : assocDelete(data.map, key);
+ }
+
+ /**
+ * Gets the map value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf MapCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function mapGet(key) {
+ var data = this.__data__;
+ if (isKeyable(key)) {
+ return hashGet(typeof key == 'string' ? data.string : data.hash, key);
+ }
+ return Map ? data.map.get(key) : assocGet(data.map, key);
+ }
+
+ /**
+ * Checks if a map value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf MapCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function mapHas(key) {
+ var data = this.__data__;
+ if (isKeyable(key)) {
+ return hashHas(typeof key == 'string' ? data.string : data.hash, key);
+ }
+ return Map ? data.map.has(key) : assocHas(data.map, key);
+ }
+
+ /**
+ * Sets the map `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf MapCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the map cache object.
+ */
+ function mapSet(key, value) {
+ var data = this.__data__;
+ if (isKeyable(key)) {
+ hashSet(typeof key == 'string' ? data.string : data.hash, key, value);
+ } else if (Map) {
+ data.map.set(key, value);
+ } else {
+ assocSet(data.map, key, value);
+ }
+ return this;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ *
+ * Creates a set cache object to store unique values.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+ function SetCache(values) {
+ var index = -1,
+ length = values ? values.length : 0;
+
+ this.__data__ = new MapCache;
+ while (++index < length) {
+ this.push(values[index]);
+ }
+ }
+
+ /**
+ * Checks if `value` is in `cache`.
+ *
+ * @private
+ * @param {Object} cache The set cache to search.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `true` if `value` is found, else `false`.
+ */
+ function cacheHas(cache, value) {
+ var map = cache.__data__;
+ if (isKeyable(value)) {
+ var data = map.__data__,
+ hash = typeof value == 'string' ? data.string : data.hash;
+
+ return hash[value] === HASH_UNDEFINED;
+ }
+ return map.has(value);
+ }
+
+ /**
+ * Adds `value` to the set cache.
+ *
+ * @private
+ * @name push
+ * @memberOf SetCache
+ * @param {*} value The value to cache.
+ */
+ function cachePush(value) {
+ var map = this.__data__;
+ if (isKeyable(value)) {
+ var data = map.__data__,
+ hash = typeof value == 'string' ? data.string : data.hash;
+
+ hash[value] = HASH_UNDEFINED;
+ }
+ else {
+ map.set(value, HASH_UNDEFINED);
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a stack cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+ function Stack(values) {
+ var index = -1,
+ length = values ? values.length : 0;
+
+ this.clear();
+ while (++index < length) {
+ var entry = values[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+
+ /**
+ * Removes all key-value entries from the stack.
+ *
+ * @private
+ * @name clear
+ * @memberOf Stack
+ */
+ function stackClear() {
+ this.__data__ = { 'array': [], 'map': null };
+ }
+
+ /**
+ * Removes `key` and its value from the stack.
+ *
+ * @private
+ * @name delete
+ * @memberOf Stack
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function stackDelete(key) {
+ var data = this.__data__,
+ array = data.array;
+
+ return array ? assocDelete(array, key) : data.map['delete'](key);
+ }
+
+ /**
+ * Gets the stack value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Stack
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function stackGet(key) {
+ var data = this.__data__,
+ array = data.array;
+
+ return array ? assocGet(array, key) : data.map.get(key);
+ }
+
+ /**
+ * Checks if a stack value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Stack
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function stackHas(key) {
+ var data = this.__data__,
+ array = data.array;
+
+ return array ? assocHas(array, key) : data.map.has(key);
+ }
+
+ /**
+ * Sets the stack `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Stack
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the stack cache object.
+ */
+ function stackSet(key, value) {
+ var data = this.__data__,
+ array = data.array;
+
+ if (array) {
+ if (array.length < (LARGE_ARRAY_SIZE - 1)) {
+ assocSet(array, key, value);
+ } else {
+ data.array = null;
+ data.map = new MapCache(array);
+ }
+ }
+ var map = data.map;
+ if (map) {
+ map.set(key, value);
+ }
+ return this;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Removes `key` and its value from the associative array.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+ function assocDelete(array, key) {
+ var index = assocIndexOf(array, key);
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = array.length - 1;
+ if (index == lastIndex) {
+ array.pop();
+ } else {
+ splice.call(array, index, 1);
+ }
+ return true;
+ }
+
+ /**
+ * Gets the associative array value for `key`.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+ function assocGet(array, key) {
+ var index = assocIndexOf(array, key);
+ return index < 0 ? undefined : array[index][1];
+ }
+
+ /**
+ * Checks if an associative array value for `key` exists.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function assocHas(array, key) {
+ return assocIndexOf(array, key) > -1;
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `key` is found in `array`
+ * of key-value pairs.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} key The key to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Sets the associative array `key` to `value`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ */
+ function assocSet(array, key, value) {
+ var index = assocIndexOf(array, key);
+ if (index < 0) {
+ array.push([key, value]);
+ } else {
+ array[index][1] = value;
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Used by `_.defaults` to customize its `_.assignIn` use.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to assign.
+ * @param {Object} object The parent object of `objValue`.
+ * @returns {*} Returns the value to assign.
+ */
+ function assignInDefaults(objValue, srcValue, key, object) {
+ if (objValue === undefined ||
+ (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
+ return srcValue;
+ }
+ return objValue;
+ }
+
+ /**
+ * This function is like `assignValue` except that it doesn't assign `undefined` values.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignMergeValue(object, key, value) {
+ if ((value !== undefined && !eq(object[key], value)) ||
+ (typeof key == 'number' && value === undefined && !(key in object))) {
+ object[key] = value;
+ }
+ }
+
+ /**
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+ function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
+ (value === undefined && !(key in object))) {
+ object[key] = value;
+ }
+ }
+
+ /**
+ * Aggregates elements of `collection` on `accumulator` with keys transformed
+ * by `iteratee` and values set by `setter`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform keys.
+ * @param {Object} accumulator The initial aggregated object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseAggregator(collection, setter, iteratee, accumulator) {
+ baseEach(collection, function(value, key, collection) {
+ setter(accumulator, value, iteratee(value), collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.assign` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+ }
+
+ /**
+ * The base implementation of `_.at` without support for individual paths.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {string[]} paths The property paths of elements to pick.
+ * @returns {Array} Returns the new array of picked elements.
+ */
+ function baseAt(object, paths) {
+ var index = -1,
+ isNil = object == null,
+ length = paths.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = isNil ? undefined : get(object, paths[index]);
+ }
+ return result;
+ }
+
+ /**
+ * Casts `value` to an empty array if it's not an array like object.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the array-like object.
+ */
+ function baseCastArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+
+ /**
+ * Casts `value` to `identity` if it's not a function.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the array-like object.
+ */
+ function baseCastFunction(value) {
+ return typeof value == 'function' ? value : identity;
+ }
+
+ /**
+ * Casts `value` to a path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast property path array.
+ */
+ function baseCastPath(value) {
+ return isArray(value) ? value : stringToPath(value);
+ }
+
+ /**
+ * The base implementation of `_.clamp` which doesn't coerce arguments to numbers.
+ *
+ * @private
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ */
+ function baseClamp(number, lower, upper) {
+ if (number === number) {
+ if (upper !== undefined) {
+ number = number <= upper ? number : upper;
+ }
+ if (lower !== undefined) {
+ number = number >= lower ? number : lower;
+ }
+ }
+ return number;
+ }
+
+ /**
+ * The base implementation of `_.clone` and `_.cloneDeep` which tracks
+ * traversed objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The parent object of `value`.
+ * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, isDeep, customizer, key, object, stack) {
+ var result;
+ if (customizer) {
+ result = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result);
+ }
+ } else {
+ var tag = getTag(value),
+ isFunc = tag == funcTag || tag == genTag;
+
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ if (isHostObject(value)) {
+ return object ? value : {};
+ }
+ result = initCloneObject(isFunc ? {} : value);
+ if (!isDeep) {
+ return copySymbols(value, baseAssign(result, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, isDeep);
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stack || (stack = new Stack);
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result);
+
+ // Recursively populate clone (susceptible to call stack limits).
+ (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
+ assignValue(result, key, baseClone(subValue, isDeep, customizer, key, value, stack));
+ });
+ return isArr ? result : copySymbols(value, result);
+ }
+
+ /**
+ * The base implementation of `_.conforms` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {Function} Returns the new function.
+ */
+ function baseConforms(source) {
+ var props = keys(source),
+ length = props.length;
+
+ return function(object) {
+ if (object == null) {
+ return !length;
+ }
+ var index = length;
+ while (index--) {
+ var key = props[index],
+ predicate = source[key],
+ value = object[key];
+
+ if ((value === undefined && !(key in Object(object))) || !predicate(value)) {
+ return false;
+ }
+ }
+ return true;
+ };
+ }
+
+ /**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} prototype The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+ function baseCreate(proto) {
+ return isObject(proto) ? objectCreate(proto) : {};
+ }
+
+ /**
+ * The base implementation of `_.delay` and `_.defer` which accepts an array
+ * of `func` arguments.
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {Object} args The arguments to provide to `func`.
+ * @returns {number} Returns the timer id.
+ */
+ function baseDelay(func, wait, args) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
+ }
+
+ /**
+ * The base implementation of methods like `_.difference` without support for
+ * excluding multiple arrays or iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Array} values The values to exclude.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ */
+ function baseDifference(array, values, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ isCommon = true,
+ length = array.length,
+ result = [],
+ valuesLength = values.length;
+
+ if (!length) {
+ return result;
+ }
+ if (iteratee) {
+ values = arrayMap(values, baseUnary(iteratee));
+ }
+ if (comparator) {
+ includes = arrayIncludesWith;
+ isCommon = false;
+ }
+ else if (values.length >= LARGE_ARRAY_SIZE) {
+ includes = cacheHas;
+ isCommon = false;
+ values = new SetCache(values);
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (isCommon && computed === computed) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values[valuesIndex] === computed) {
+ continue outer;
+ }
+ }
+ result.push(value);
+ }
+ else if (!includes(values, computed, comparator)) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.forEach` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEach = createBaseEach(baseForOwn);
+
+ /**
+ * The base implementation of `_.forEachRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+
+ /**
+ * The base implementation of `_.every` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`
+ */
+ function baseEvery(collection, predicate) {
+ var result = true;
+ baseEach(collection, function(value, index, collection) {
+ result = !!predicate(value, index, collection);
+ return result;
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.fill` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ */
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+
+ start = toInteger(start);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : toInteger(end);
+ if (end < 0) {
+ end += length;
+ }
+ end = start > end ? 0 : toLength(end);
+ while (start < end) {
+ array[start++] = value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.filter` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function baseFilter(collection, predicate) {
+ var result = [];
+ baseEach(collection, function(value, index, collection) {
+ if (predicate(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.flatten` with support for restricting flattening.
+ *
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {number} depth The maximum recursion depth.
+ * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
+ * @param {Array} [result=[]] The initial result value.
+ * @returns {Array} Returns the new flattened array.
+ */
+ function baseFlatten(array, depth, isStrict, result) {
+ result || (result = []);
+
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && isArrayLikeObject(value) &&
+ (isStrict || isArray(value) || isArguments(value))) {
+ if (depth > 1) {
+ // Recursively flatten arrays (susceptible to call stack limits).
+ baseFlatten(value, depth - 1, isStrict, result);
+ } else {
+ arrayPush(result, value);
+ }
+ } else if (!isStrict) {
+ result[result.length] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `baseForIn` and `baseForOwn` which iterates
+ * over `object` properties returned by `keysFunc` invoking `iteratee` for
+ * each property. Iteratee functions may exit iteration early by explicitly
+ * returning `false`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseFor = createBaseFor();
+
+ /**
+ * This function is like `baseFor` except that it iterates over properties
+ * in the opposite order.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseForRight = createBaseFor(true);
+
+ /**
+ * The base implementation of `_.forIn` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForIn(object, iteratee) {
+ return object == null ? object : baseFor(object, iteratee, keysIn);
+ }
+
+ /**
+ * The base implementation of `_.forOwn` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwn(object, iteratee) {
+ return object && baseFor(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwnRight(object, iteratee) {
+ return object && baseForRight(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.functions` which creates an array of
+ * `object` function property names filtered from `props`.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} props The property names to filter.
+ * @returns {Array} Returns the new array of filtered property names.
+ */
+ function baseFunctions(object, props) {
+ return arrayFilter(props, function(key) {
+ return isFunction(object[key]);
+ });
+ }
+
+ /**
+ * The base implementation of `_.get` without support for default values.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseGet(object, path) {
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
+
+ var index = 0,
+ length = path.length;
+
+ while (object != null && index < length) {
+ object = object[path[index++]];
+ }
+ return (index && index == length) ? object : undefined;
+ }
+
+ /**
+ * The base implementation of `_.has` without support for deep paths.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHas(object, key) {
+ // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`,
+ // that are composed entirely of index properties, return `false` for
+ // `hasOwnProperty` checks of them.
+ return hasOwnProperty.call(object, key) ||
+ (typeof object == 'object' && key in object && getPrototypeOf(object) === null);
+ }
+
+ /**
+ * The base implementation of `_.hasIn` without support for deep paths.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+ function baseHasIn(object, key) {
+ return key in Object(object);
+ }
+
+ /**
+ * The base implementation of `_.inRange` which doesn't coerce arguments to numbers.
+ *
+ * @private
+ * @param {number} number The number to check.
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ */
+ function baseInRange(number, start, end) {
+ return number >= nativeMin(start, end) && number < nativeMax(start, end);
+ }
+
+ /**
+ * The base implementation of methods like `_.intersection`, without support
+ * for iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of shared values.
+ */
+ function baseIntersection(arrays, iteratee, comparator) {
+ var includes = comparator ? arrayIncludesWith : arrayIncludes,
+ othLength = arrays.length,
+ othIndex = othLength,
+ caches = Array(othLength),
+ result = [];
+
+ while (othIndex--) {
+ var array = arrays[othIndex];
+ if (othIndex && iteratee) {
+ array = arrayMap(array, baseUnary(iteratee));
+ }
+ caches[othIndex] = !comparator && (iteratee || array.length >= 120)
+ ? new SetCache(othIndex && array)
+ : undefined;
+ }
+ array = arrays[0];
+
+ var index = -1,
+ length = array.length,
+ seen = caches[0];
+
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (!(seen
+ ? cacheHas(seen, computed)
+ : includes(result, computed, comparator)
+ )) {
+ var othIndex = othLength;
+ while (--othIndex) {
+ var cache = caches[othIndex];
+ if (!(cache
+ ? cacheHas(cache, computed)
+ : includes(arrays[othIndex], computed, comparator))
+ ) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.invert` and `_.invertBy` which inverts
+ * `object` with values transformed by `iteratee` and set by `setter`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} setter The function to set `accumulator` values.
+ * @param {Function} iteratee The iteratee to transform values.
+ * @param {Object} accumulator The initial inverted object.
+ * @returns {Function} Returns `accumulator`.
+ */
+ function baseInverter(object, setter, iteratee, accumulator) {
+ baseForOwn(object, function(value, key, object) {
+ setter(accumulator, iteratee(value), key, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `_.invoke` without support for individual
+ * method arguments.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {Array} args The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ */
+ function baseInvoke(object, path, args) {
+ if (!isKey(path, object)) {
+ path = baseCastPath(path);
+ object = parent(object, path);
+ path = last(path);
+ }
+ var func = object == null ? object : object[path];
+ return func == null ? undefined : apply(func, object, args);
+ }
+
+ /**
+ * The base implementation of `_.isEqual` which supports partial comparisons
+ * and tracks traversed objects.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {boolean} [bitmask] The bitmask of comparison flags.
+ * The bitmask may be composed of the following flags:
+ * 1 - Unordered comparison
+ * 2 - Partial comparison
+ * @param {Object} [stack] Tracks traversed `value` and `other` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ */
+ function baseIsEqual(value, other, customizer, bitmask, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
+ }
+
+ /**
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
+ * deep comparisons and tracks traversed objects enabling objects with circular
+ * references to be compared.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
+ var objIsArr = isArray(object),
+ othIsArr = isArray(other),
+ objTag = arrayTag,
+ othTag = arrayTag;
+
+ if (!objIsArr) {
+ objTag = getTag(object);
+ if (objTag == argsTag) {
+ objTag = objectTag;
+ } else if (objTag != objectTag) {
+ objIsArr = isTypedArray(object);
+ }
+ }
+ if (!othIsArr) {
+ othTag = getTag(other);
+ if (othTag == argsTag) {
+ othTag = objectTag;
+ } else if (othTag != objectTag) {
+ othIsArr = isTypedArray(other);
+ }
+ }
+ var objIsObj = objTag == objectTag && !isHostObject(object),
+ othIsObj = othTag == objectTag && !isHostObject(other),
+ isSameTag = objTag == othTag;
+
+ if (isSameTag && !(objIsArr || objIsObj)) {
+ return equalByTag(object, other, objTag, equalFunc, customizer, bitmask);
+ }
+ var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
+ if (!isPartial) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+ if (objIsWrapped || othIsWrapped) {
+ return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack);
+ return (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack);
+ }
+
+ /**
+ * The base implementation of `_.isMatch` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Array} matchData The property names, values, and compare flags to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+ function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length,
+ length = index,
+ noCustomizer = !customizer;
+
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (index--) {
+ var data = matchData[index];
+ if ((noCustomizer && data[2])
+ ? data[1] !== object[data[0]]
+ : !(data[0] in object)
+ ) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0],
+ objValue = object[key],
+ srcValue = data[1];
+
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack,
+ result = customizer ? customizer(objValue, srcValue, key, object, source, stack) : undefined;
+
+ if (!(result === undefined
+ ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
+ : result
+ )) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.iteratee`.
+ *
+ * @private
+ * @param {*} [value=_.identity] The value to convert to an iteratee.
+ * @returns {Function} Returns the iteratee.
+ */
+ function baseIteratee(value) {
+ var type = typeof value;
+ if (type == 'function') {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (type == 'object') {
+ return isArray(value)
+ ? baseMatchesProperty(value[0], value[1])
+ : baseMatches(value);
+ }
+ return property(value);
+ }
+
+ /**
+ * The base implementation of `_.keys` which doesn't skip the constructor
+ * property of prototypes or treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeys(object) {
+ return nativeKeys(Object(object));
+ }
+
+ /**
+ * The base implementation of `_.keysIn` which doesn't skip the constructor
+ * property of prototypes or treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function baseKeysIn(object) {
+ object = object == null ? object : Object(object);
+
+ var result = [];
+ for (var key in object) {
+ result.push(key);
+ }
+ return result;
+ }
+
+ // Fallback for IE < 9 with es6-shim.
+ if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) {
+ baseKeysIn = function(object) {
+ return iteratorToArray(enumerate(object));
+ };
+ }
+
+ /**
+ * The base implementation of `_.map` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.matches` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ var key = matchData[0][0],
+ value = matchData[0][1];
+
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === value &&
+ (value !== undefined || (key in Object(object)));
+ };
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+ }
+
+ /**
+ * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatchesProperty(path, srcValue) {
+ return function(object) {
+ var objValue = get(object, path);
+ return (objValue === undefined && objValue === srcValue)
+ ? hasIn(object, path)
+ : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
+ };
+ }
+
+ /**
+ * The base implementation of `_.merge` without support for multiple sources.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
+ */
+ function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ var props = (isArray(source) || isTypedArray(source))
+ ? undefined
+ : keysIn(source);
+
+ arrayEach(props || source, function(srcValue, key) {
+ if (props) {
+ key = srcValue;
+ srcValue = source[key];
+ }
+ if (isObject(srcValue)) {
+ stack || (stack = new Stack);
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ }
+ else {
+ var newValue = customizer
+ ? customizer(object[key], srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ });
+ }
+
+ /**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
+ */
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = object[key],
+ srcValue = source[key],
+ stacked = stack.get(srcValue);
+
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ var isCommon = newValue === undefined;
+
+ if (isCommon) {
+ newValue = srcValue;
+ if (isArray(srcValue) || isTypedArray(srcValue)) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ }
+ else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
+ isCommon = false;
+ newValue = baseClone(srcValue, true);
+ }
+ else {
+ newValue = objValue;
+ }
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ stack.set(srcValue, newValue);
+
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ }
+ assignMergeValue(object, key, newValue);
+ }
+
+ /**
+ * The base implementation of `_.orderBy` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {string[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+ function baseOrderBy(collection, iteratees, orders) {
+ var index = -1,
+ toIteratee = getIteratee();
+
+ iteratees = arrayMap(iteratees.length ? iteratees : Array(1), function(iteratee) {
+ return toIteratee(iteratee);
+ });
+
+ var result = baseMap(collection, function(value, key, collection) {
+ var criteria = arrayMap(iteratees, function(iteratee) {
+ return iteratee(value);
+ });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
+
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+
+ /**
+ * The base implementation of `_.pick` without support for individual
+ * property names.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} props The property names to pick.
+ * @returns {Object} Returns the new object.
+ */
+ function basePick(object, props) {
+ object = Object(object);
+ return arrayReduce(props, function(result, key) {
+ if (key in object) {
+ result[key] = object[key];
+ }
+ return result;
+ }, {});
+ }
+
+ /**
+ * The base implementation of `_.pickBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {Function} predicate The function invoked per property.
+ * @returns {Object} Returns the new object.
+ */
+ function basePickBy(object, predicate) {
+ var result = {};
+ baseForIn(object, function(value, key) {
+ if (predicate(value, key)) {
+ result[key] = value;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new function.
+ */
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined : object[key];
+ };
+ }
+
+ /**
+ * A specialized version of `baseProperty` which supports deep paths.
+ *
+ * @private
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new function.
+ */
+ function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+ }
+
+ /**
+ * The base implementation of `_.pullAll`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAll(array, values) {
+ return basePullAllBy(array, values);
+ }
+
+ /**
+ * The base implementation of `_.pullAllBy` without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAllBy(array, values, iteratee) {
+ var index = -1,
+ length = values.length,
+ seen = array;
+
+ if (iteratee) {
+ seen = arrayMap(array, function(value) { return iteratee(value); });
+ }
+ while (++index < length) {
+ var fromIndex = 0,
+ value = values[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) {
+ if (seen !== array) {
+ splice.call(seen, fromIndex, 1);
+ }
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.pullAt` without support for individual
+ * indexes or capturing the removed elements.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {number[]} indexes The indexes of elements to remove.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0,
+ lastIndex = length - 1;
+
+ while (length--) {
+ var index = indexes[length];
+ if (lastIndex == length || index != previous) {
+ var previous = index;
+ if (isIndex(index)) {
+ splice.call(array, index, 1);
+ }
+ else if (!isKey(index, array)) {
+ var path = baseCastPath(index),
+ object = parent(array, path);
+
+ if (object != null) {
+ delete object[last(path)];
+ }
+ }
+ else {
+ delete array[index];
+ }
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.random` without support for returning
+ * floating-point numbers.
+ *
+ * @private
+ * @param {number} lower The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the random number.
+ */
+ function baseRandom(lower, upper) {
+ return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
+ }
+
+ /**
+ * The base implementation of `_.range` and `_.rangeRight` which doesn't
+ * coerce arguments to numbers.
+ *
+ * @private
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} step The value to increment or decrement by.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the new array of numbers.
+ */
+ function baseRange(start, end, step, fromRight) {
+ var index = -1,
+ length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
+ result = Array(length);
+
+ while (length--) {
+ result[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.set`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+ function baseSet(object, path, value, customizer) {
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = path[index];
+ if (isObject(nested)) {
+ var newValue = value;
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined;
+ if (newValue === undefined) {
+ newValue = objValue == null
+ ? (isIndex(path[index + 1]) ? [] : {})
+ : objValue;
+ }
+ }
+ assignValue(nested, key, newValue);
+ }
+ nested = nested[key];
+ }
+ return object;
+ }
+
+ /**
+ * The base implementation of `setData` without support for hot loop detection.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+
+ /**
+ * The base implementation of `_.slice` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array, start, end) {
+ var index = -1,
+ length = array.length;
+
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = end > length ? length : end;
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : ((end - start) >>> 0);
+ start >>>= 0;
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.some` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
+ */
+ function baseSome(collection, predicate) {
+ var result;
+
+ baseEach(collection, function(value, index, collection) {
+ result = predicate(value, index, collection);
+ return !result;
+ });
+ return !!result;
+ }
+
+ /**
+ * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
+ * performs a binary search of `array` to determine the index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function baseSortedIndex(array, value, retHighest) {
+ var low = 0,
+ high = array ? array.length : low;
+
+ if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = (low + high) >>> 1,
+ computed = array[mid];
+
+ if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return baseSortedIndexBy(array, value, identity, retHighest);
+ }
+
+ /**
+ * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
+ * which invokes `iteratee` for `value` and each element of `array` to compute
+ * their sort ranking. The iteratee is invoked with one argument; (value).
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} iteratee The iteratee invoked per element.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted into `array`.
+ */
+ function baseSortedIndexBy(array, value, iteratee, retHighest) {
+ value = iteratee(value);
+
+ var low = 0,
+ high = array ? array.length : 0,
+ valIsNaN = value !== value,
+ valIsNull = value === null,
+ valIsUndef = value === undefined;
+
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2),
+ computed = iteratee(array[mid]),
+ isDef = computed !== undefined,
+ isReflexive = computed === computed;
+
+ if (valIsNaN) {
+ var setLow = isReflexive || retHighest;
+ } else if (valIsNull) {
+ setLow = isReflexive && isDef && (retHighest || computed != null);
+ } else if (valIsUndef) {
+ setLow = isReflexive && (retHighest || isDef);
+ } else if (computed == null) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? (computed <= value) : (computed < value);
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+
+ /**
+ * The base implementation of `_.sortedUniq`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseSortedUniq(array) {
+ return baseSortedUniqBy(array);
+ }
+
+ /**
+ * The base implementation of `_.sortedUniqBy` without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseSortedUniqBy(array, iteratee) {
+ var index = 0,
+ length = array.length,
+ value = array[0],
+ computed = iteratee ? iteratee(value) : value,
+ seen = computed,
+ resIndex = 0,
+ result = [value];
+
+ while (++index < length) {
+ value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (!eq(computed, seen)) {
+ seen = computed;
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.uniqBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+ function baseUniq(array, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ length = array.length,
+ isCommon = true,
+ result = [],
+ seen = result;
+
+ if (comparator) {
+ isCommon = false;
+ includes = arrayIncludesWith;
+ }
+ else if (length >= LARGE_ARRAY_SIZE) {
+ var set = iteratee ? null : createSet(array);
+ if (set) {
+ return setToArray(set);
+ }
+ isCommon = false;
+ includes = cacheHas;
+ seen = new SetCache;
+ }
+ else {
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (!includes(seen, computed, comparator)) {
+ if (seen !== result) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.unset`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ */
+ function baseUnset(object, path) {
+ path = isKey(path, object) ? [path + ''] : baseCastPath(path);
+ object = parent(object, path);
+ var key = last(path);
+ return (object != null && has(object, key)) ? delete object[key] : true;
+ }
+
+ /**
+ * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
+ * without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length) &&
+ predicate(array[index], index, array)) {}
+
+ return isDrop
+ ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+ : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+ }
+
+ /**
+ * The base implementation of `wrapperValue` which returns the result of
+ * performing a sequence of actions on the unwrapped `value`, where each
+ * successive action is supplied the return value of the previous.
+ *
+ * @private
+ * @param {*} value The unwrapped value.
+ * @param {Array} actions Actions to perform to resolve the unwrapped value.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseWrapperValue(value, actions) {
+ var result = value;
+ if (result instanceof LazyWrapper) {
+ result = result.value();
+ }
+ return arrayReduce(actions, function(result, action) {
+ return action.func.apply(action.thisArg, arrayPush([result], action.args));
+ }, result);
+ }
+
+ /**
+ * The base implementation of methods like `_.xor`, without support for
+ * iteratee shorthands, that accepts an array of arrays to inspect.
+ *
+ * @private
+ * @param {Array} arrays The arrays to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of values.
+ */
+ function baseXor(arrays, iteratee, comparator) {
+ var index = -1,
+ length = arrays.length;
+
+ while (++index < length) {
+ var result = result
+ ? arrayPush(
+ baseDifference(result, arrays[index], iteratee, comparator),
+ baseDifference(arrays[index], result, iteratee, comparator)
+ )
+ : arrays[index];
+ }
+ return (result && result.length) ? baseUniq(result, iteratee, comparator) : [];
+ }
+
+ /**
+ * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
+ *
+ * @private
+ * @param {Array} props The property names.
+ * @param {Array} values The property values.
+ * @param {Function} assignFunc The function to assign values.
+ * @returns {Object} Returns the new object.
+ */
+ function baseZipObject(props, values, assignFunc) {
+ var index = -1,
+ length = props.length,
+ valsLength = values.length,
+ result = {};
+
+ while (++index < length) {
+ assignFunc(result, props[index], index < valsLength ? values[index] : undefined);
+ }
+ return result;
+ }
+
+ /**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var Ctor = buffer.constructor,
+ result = new Ctor(buffer.length);
+
+ buffer.copy(result);
+ return result;
+ }
+
+ /**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function cloneArrayBuffer(arrayBuffer) {
+ var Ctor = arrayBuffer.constructor,
+ result = new Ctor(arrayBuffer.byteLength),
+ view = new Uint8Array(result);
+
+ view.set(new Uint8Array(arrayBuffer));
+ return result;
+ }
+
+ /**
+ * Creates a clone of `map`.
+ *
+ * @private
+ * @param {Object} map The map to clone.
+ * @returns {Object} Returns the cloned map.
+ */
+ function cloneMap(map) {
+ var Ctor = map.constructor;
+ return arrayReduce(mapToArray(map), addMapEntry, new Ctor);
+ }
+
+ /**
+ * Creates a clone of `regexp`.
+ *
+ * @private
+ * @param {Object} regexp The regexp to clone.
+ * @returns {Object} Returns the cloned regexp.
+ */
+ function cloneRegExp(regexp) {
+ var Ctor = regexp.constructor,
+ result = new Ctor(regexp.source, reFlags.exec(regexp));
+
+ result.lastIndex = regexp.lastIndex;
+ return result;
+ }
+
+ /**
+ * Creates a clone of `set`.
+ *
+ * @private
+ * @param {Object} set The set to clone.
+ * @returns {Object} Returns the cloned set.
+ */
+ function cloneSet(set) {
+ var Ctor = set.constructor;
+ return arrayReduce(setToArray(set), addSetEntry, new Ctor);
+ }
+
+ /**
+ * Creates a clone of the `symbol` object.
+ *
+ * @private
+ * @param {Object} symbol The symbol object to clone.
+ * @returns {Object} Returns the cloned symbol object.
+ */
+ function cloneSymbol(symbol) {
+ return Symbol ? Object(symbolValueOf.call(symbol)) : {};
+ }
+
+ /**
+ * Creates a clone of `typedArray`.
+ *
+ * @private
+ * @param {Object} typedArray The typed array to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned typed array.
+ */
+ function cloneTypedArray(typedArray, isDeep) {
+ var arrayBuffer = typedArray.buffer,
+ buffer = isDeep ? cloneArrayBuffer(arrayBuffer) : arrayBuffer,
+ Ctor = typedArray.constructor;
+
+ return new Ctor(buffer, typedArray.byteOffset, typedArray.length);
+ }
+
+ /**
+ * Creates an array that is the composition of partially applied arguments,
+ * placeholders, and provided arguments into a single array of arguments.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to prepend to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersLength = holders.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(leftLength + rangeLength),
+ isUncurried = !isCurried;
+
+ while (++leftIndex < leftLength) {
+ result[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
+ }
+ while (rangeLength--) {
+ result[leftIndex++] = args[argsIndex++];
+ }
+ return result;
+ }
+
+ /**
+ * This function is like `composeArgs` except that the arguments composition
+ * is tailored for `_.partialRight`.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to append to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @params {boolean} [isCurried] Specify composing for a curried function.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1,
+ argsLength = args.length,
+ holdersIndex = -1,
+ holdersLength = holders.length,
+ rightIndex = -1,
+ rightLength = partials.length,
+ rangeLength = nativeMax(argsLength - holdersLength, 0),
+ result = Array(rangeLength + rightLength),
+ isUncurried = !isCurried;
+
+ while (++argsIndex < rangeLength) {
+ result[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+ function copyArray(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+
+ /**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property names to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @returns {Object} Returns `object`.
+ */
+ function copyObject(source, props, object) {
+ return copyObjectWith(source, props, object);
+ }
+
+ /**
+ * This function is like `copyObject` except that it accepts a function to
+ * customize copied values.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property names to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @param {Function} [customizer] The function to customize copied values.
+ * @returns {Object} Returns `object`.
+ */
+ function copyObjectWith(source, props, object, customizer) {
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : source[key];
+
+ assignValue(object, key, newValue);
+ }
+ return object;
+ }
+
+ /**
+ * Copies own symbol properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+ function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+ }
+
+ /**
+ * Creates a function like `_.groupBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} [initializer] The accumulator object initializer.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee) {
+ var func = isArray(collection) ? arrayAggregator : baseAggregator,
+ accumulator = initializer ? initializer() : {};
+
+ return func(collection, setter, getIteratee(iteratee), accumulator);
+ };
+ }
+
+ /**
+ * Creates a function like `_.assign`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+ function createAssigner(assigner) {
+ return rest(function(object, sources) {
+ var index = -1,
+ length = sources.length,
+ customizer = length > 1 ? sources[length - 1] : undefined,
+ guard = length > 2 ? sources[2] : undefined;
+
+ customizer = typeof customizer == 'function'
+ ? (length--, customizer)
+ : undefined;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined : customizer;
+ length = 1;
+ }
+ object = Object(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+ }
+
+ /**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee);
+ }
+ var length = collection.length,
+ index = fromRight ? length : -1,
+ iterable = Object(collection);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+
+ /**
+ * Creates a base function for methods like `_.forIn`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var index = -1,
+ iterable = Object(object),
+ props = keysFunc(object),
+ length = props.length;
+
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the optional `this`
+ * binding of `thisArg`.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createBaseWrapper(func, bitmask, thisArg) {
+ var isBind = bitmask & BIND_FLAG,
+ Ctor = createCtorWrapper(func);
+
+ function wrapper() {
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, arguments);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.lowerFirst`.
+ *
+ * @private
+ * @param {string} methodName The name of the `String` case method to use.
+ * @returns {Function} Returns the new function.
+ */
+ function createCaseFirst(methodName) {
+ return function(string) {
+ string = toString(string);
+
+ var strSymbols = reHasComplexSymbol.test(string)
+ ? stringToArray(string)
+ : undefined;
+
+ var chr = strSymbols ? strSymbols[0] : string.charAt(0),
+ trailing = strSymbols ? strSymbols.slice(1).join('') : string.slice(1);
+
+ return chr[methodName]() + trailing;
+ };
+ }
+
+ /**
+ * Creates a function like `_.camelCase`.
+ *
+ * @private
+ * @param {Function} callback The function to combine each word.
+ * @returns {Function} Returns the new compounder function.
+ */
+ function createCompounder(callback) {
+ return function(string) {
+ return arrayReduce(words(deburr(string)), callback, '');
+ };
+ }
+
+ /**
+ * Creates a function that produces an instance of `Ctor` regardless of
+ * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ *
+ * @private
+ * @param {Function} Ctor The constructor to wrap.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCtorWrapper(Ctor) {
+ return function() {
+ // Use a `switch` statement to work with class constructors.
+ // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+ // for more details.
+ var args = arguments;
+ switch (args.length) {
+ case 0: return new Ctor;
+ case 1: return new Ctor(args[0]);
+ case 2: return new Ctor(args[0], args[1]);
+ case 3: return new Ctor(args[0], args[1], args[2]);
+ case 4: return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype),
+ result = Ctor.apply(thisBinding, args);
+
+ // Mimic the constructor's `return` behavior.
+ // See https://es5.github.io/#x13.2.2 for more details.
+ return isObject(result) ? result : thisBinding;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to enable currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
+ * @param {number} arity The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCurryWrapper(func, bitmask, arity) {
+ var Ctor = createCtorWrapper(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ args = Array(length),
+ index = length,
+ placeholder = getPlaceholder(wrapper);
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
+ ? []
+ : replaceHolders(args, placeholder);
+
+ length -= holders.length;
+ if (length < arity) {
+ return createRecurryWrapper(
+ func, bitmask, createHybridWrapper, wrapper.placeholder, undefined,
+ args, holders, undefined, undefined, arity - length);
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return apply(fn, this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.flow` or `_.flowRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new flow function.
+ */
+ function createFlow(fromRight) {
+ return rest(function(funcs) {
+ funcs = baseFlatten(funcs, 1);
+
+ var length = funcs.length,
+ index = length,
+ prereq = LodashWrapper.prototype.thru;
+
+ if (fromRight) {
+ funcs.reverse();
+ }
+ while (index--) {
+ var func = funcs[index];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
+ var wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? index : length;
+ while (++index < length) {
+ func = funcs[index];
+
+ var funcName = getFuncName(func),
+ data = funcName == 'wrapper' ? getData(func) : undefined;
+
+ if (data && isLaziable(data[0]) &&
+ data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) &&
+ !data[4].length && data[9] == 1
+ ) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments,
+ value = args[0];
+
+ if (wrapper && args.length == 1 &&
+ isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
+ return wrapper.plant(value).value();
+ }
+ var index = 0,
+ result = length ? funcs[index].apply(this, args) : value;
+
+ while (++index < length) {
+ result = funcs[index].call(this, result);
+ }
+ return result;
+ };
+ });
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with optional `this`
+ * binding of `thisArg`, partial application, and currying.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
+ * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+ var isAry = bitmask & ARY_FLAG,
+ isBind = bitmask & BIND_FLAG,
+ isBindKey = bitmask & BIND_KEY_FLAG,
+ isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
+ isFlip = bitmask & FLIP_FLAG,
+ Ctor = isBindKey ? undefined : createCtorWrapper(func);
+
+ function wrapper() {
+ var length = arguments.length,
+ index = length,
+ args = Array(length);
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (isCurried) {
+ var placeholder = getPlaceholder(wrapper),
+ holdersCount = countHolders(args, placeholder);
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders, isCurried);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
+ }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurryWrapper(
+ func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
+ args, newHolders, argPos, ary, arity - length
+ );
+ }
+ var thisBinding = isBind ? thisArg : this,
+ fn = isBindKey ? thisBinding[func] : func;
+
+ length = args.length;
+ if (argPos) {
+ args = reorder(args, argPos);
+ } else if (isFlip && length > 1) {
+ args.reverse();
+ }
+ if (isAry && ary < length) {
+ args.length = ary;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtorWrapper(fn);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a function like `_.invertBy`.
+ *
+ * @private
+ * @param {Function} setter The function to set accumulator values.
+ * @param {Function} toIteratee The function to resolve iteratees.
+ * @returns {Function} Returns the new inverter function.
+ */
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee) {
+ return baseInverter(object, setter, toIteratee(iteratee), {});
+ };
+ }
+
+ /**
+ * Creates a function like `_.over`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over iteratees.
+ * @returns {Function} Returns the new invoker function.
+ */
+ function createOver(arrayFunc) {
+ return rest(function(iteratees) {
+ iteratees = arrayMap(baseFlatten(iteratees, 1), getIteratee());
+ return rest(function(args) {
+ var thisArg = this;
+ return arrayFunc(iteratees, function(iteratee) {
+ return apply(iteratee, thisArg, args);
+ });
+ });
+ });
+ }
+
+ /**
+ * Creates the padding for `string` based on `length`. The `chars` string
+ * is truncated if the number of characters exceeds `length`.
+ *
+ * @private
+ * @param {string} string The string to create padding for.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padding for `string`.
+ */
+ function createPadding(string, length, chars) {
+ length = toInteger(length);
+
+ var strLength = stringSize(string);
+ if (!length || strLength >= length) {
+ return '';
+ }
+ var padLength = length - strLength;
+ chars = chars === undefined ? ' ' : (chars + '');
+
+ var result = repeat(chars, nativeCeil(padLength / stringSize(chars)));
+ return reHasComplexSymbol.test(chars)
+ ? stringToArray(result).slice(0, padLength).join('')
+ : result.slice(0, padLength);
+ }
+
+ /**
+ * Creates a function that wraps `func` to invoke it with the optional `this`
+ * binding of `thisArg` and the `partials` prepended to those provided to
+ * the wrapper.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} partials The arguments to prepend to those provided to the new function.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createPartialWrapper(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & BIND_FLAG,
+ Ctor = createCtorWrapper(func);
+
+ function wrapper() {
+ var argsIndex = -1,
+ argsLength = arguments.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ args = Array(leftLength + argsLength),
+ fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ return apply(fn, isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.range` or `_.rangeRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new range function.
+ */
+ function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
+ end = step = undefined;
+ }
+ // Ensure the sign of `-0` is preserved.
+ start = toNumber(start);
+ start = start === start ? start : 0;
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = toNumber(end) || 0;
+ }
+ step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0);
+ return baseRange(start, end, step, fromRight);
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` to continue currying.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
+ * @param {Function} wrapFunc The function to create the `func` wrapper.
+ * @param {*} placeholder The placeholder value.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
+ var isCurry = bitmask & CURRY_FLAG,
+ newArgPos = argPos ? copyArray(argPos) : undefined,
+ newHolders = isCurry ? holders : undefined,
+ newHoldersRight = isCurry ? undefined : holders,
+ newPartials = isCurry ? partials : undefined,
+ newPartialsRight = isCurry ? undefined : partials;
+
+ bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
+ bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
+
+ if (!(bitmask & CURRY_BOUND_FLAG)) {
+ bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
+ }
+ var newData = [
+ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
+ newHoldersRight, newArgPos, ary, arity
+ ];
+
+ var result = wrapFunc.apply(undefined, newData);
+ if (isLaziable(func)) {
+ setData(result, newData);
+ }
+ result.placeholder = placeholder;
+ return result;
+ }
+
+ /**
+ * Creates a function like `_.round`.
+ *
+ * @private
+ * @param {string} methodName The name of the `Math` method to use when rounding.
+ * @returns {Function} Returns the new round function.
+ */
+ function createRound(methodName) {
+ var func = Math[methodName];
+ return function(number, precision) {
+ number = toNumber(number);
+ precision = toInteger(precision);
+ if (precision) {
+ // Shift with exponential notation to avoid floating-point issues.
+ // See [MDN](https://mdn.io/round#Examples) for more details.
+ var pair = (toString(number) + 'e').split('e'),
+ value = func(pair[0] + 'e' + (+pair[1] + precision));
+
+ pair = (toString(value) + 'e').split('e');
+ return +(pair[0] + 'e' + (+pair[1] - precision));
+ }
+ return func(number);
+ };
+ }
+
+ /**
+ * Creates a set of `values`.
+ *
+ * @private
+ * @param {Array} values The values to add to the set.
+ * @returns {Object} Returns the new set.
+ */
+ var createSet = !(Set && new Set([1, 2]).size === 2) ? noop : function(values) {
+ return new Set(values);
+ };
+
+ /**
+ * Creates a function that either curries or invokes `func` with optional
+ * `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to wrap.
+ * @param {number} bitmask The bitmask of wrapper flags.
+ * The bitmask may be composed of the following flags:
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry` or `_.curryRight` of a bound function
+ * 8 - `_.curry`
+ * 16 - `_.curryRight`
+ * 32 - `_.partial`
+ * 64 - `_.partialRight`
+ * 128 - `_.rearg`
+ * 256 - `_.ary`
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to be partially applied.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+ var isBindKey = bitmask & BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined;
+ }
+ ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
+ arity = arity === undefined ? arity : toInteger(arity);
+ length -= holders ? holders.length : 0;
+
+ if (bitmask & PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials,
+ holdersRight = holders;
+
+ partials = holders = undefined;
+ }
+ var data = isBindKey ? undefined : getData(func);
+
+ var newData = [
+ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
+ argPos, ary, arity
+ ];
+
+ if (data) {
+ mergeData(newData, data);
+ }
+ func = newData[0];
+ bitmask = newData[1];
+ thisArg = newData[2];
+ partials = newData[3];
+ holders = newData[4];
+ arity = newData[9] = newData[9] == null
+ ? (isBindKey ? 0 : func.length)
+ : nativeMax(newData[9] - length, 0);
+
+ if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) {
+ bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG);
+ }
+ if (!bitmask || bitmask == BIND_FLAG) {
+ var result = createBaseWrapper(func, bitmask, thisArg);
+ } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
+ result = createCurryWrapper(func, bitmask, arity);
+ } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
+ result = createPartialWrapper(func, bitmask, thisArg, partials);
+ } else {
+ result = createHybridWrapper.apply(undefined, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setter(result, newData);
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+ * @param {Object} [stack] Tracks traversed `array` and `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+ function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
+ var index = -1,
+ isPartial = bitmask & PARTIAL_COMPARE_FLAG,
+ isUnordered = bitmask & UNORDERED_COMPARE_FLAG,
+ arrLength = array.length,
+ othLength = other.length;
+
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(array);
+ if (stacked) {
+ return stacked == other;
+ }
+ var result = true;
+ stack.set(array, other);
+
+ // Ignore non-index properties.
+ while (++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, arrValue, index, other, array, stack)
+ : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined) {
+ if (compared) {
+ continue;
+ }
+ result = false;
+ break;
+ }
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (isUnordered) {
+ if (!arraySome(other, function(othValue) {
+ return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack);
+ })) {
+ result = false;
+ break;
+ }
+ } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
+ result = false;
+ break;
+ }
+ }
+ stack['delete'](array);
+ return result;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalByTag(object, other, tag, equalFunc, customizer, bitmask) {
+ switch (tag) {
+ case arrayBufferTag:
+ if ((object.byteLength != other.byteLength) ||
+ !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
+ return false;
+ }
+ return true;
+
+ case boolTag:
+ case dateTag:
+ // Coerce dates and booleans to numbers, dates to milliseconds and booleans
+ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
+ return +object == +other;
+
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+
+ case numberTag:
+ // Treat `NaN` vs. `NaN` as equal.
+ return (object != +object) ? other != +other : object == +other;
+
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings primitives and string
+ // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
+ return object == (other + '');
+
+ case mapTag:
+ var convert = mapToArray;
+
+ case setTag:
+ var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
+ convert || (convert = setToArray);
+
+ // Recursively compare objects (susceptible to call stack limits).
+ return (isPartial || object.size == other.size) &&
+ equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
+
+ case symbolTag:
+ return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other));
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
+ var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
+ objProps = keys(object),
+ objLength = objProps.length,
+ othProps = keys(other),
+ othLength = othProps.length;
+
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : baseHas(other, key))) {
+ return false;
+ }
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ var result = true;
+ stack.set(object, other);
+
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key],
+ othValue = other[key];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, objValue, key, other, object, stack)
+ : customizer(objValue, othValue, key, object, other, stack);
+ }
+ // Recursively compare objects (susceptible to call stack limits).
+ if (!(compared === undefined
+ ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
+ : compared
+ )) {
+ result = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (result && !skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
+
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ result = false;
+ }
+ }
+ stack['delete'](object);
+ return result;
+ }
+
+ /**
+ * Gets metadata for `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {*} Returns the metadata for `func`.
+ */
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+
+ /**
+ * Gets the name of `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {string} Returns the function name.
+ */
+ function getFuncName(func) {
+ var result = (func.name + ''),
+ array = realNames[result],
+ length = hasOwnProperty.call(realNames, result) ? array.length : 0;
+
+ while (length--) {
+ var data = array[length],
+ otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the appropriate "iteratee" function. If the `_.iteratee` method is
+ * customized this function returns the custom method, otherwise it returns
+ * `baseIteratee`. If arguments are provided the chosen function is invoked
+ * with them and its result is returned.
+ *
+ * @private
+ * @param {*} [value] The value to convert to an iteratee.
+ * @param {number} [arity] The arity of the created iteratee.
+ * @returns {Function} Returns the chosen function or its result.
+ */
+ function getIteratee() {
+ var result = lodash.iteratee || iteratee;
+ result = result === iteratee ? baseIteratee : result;
+ return arguments.length ? result(arguments[0], arguments[1]) : result;
+ }
+
+ /**
+ * Gets the "length" property value of `object`.
+ *
+ * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+ * that affects Safari on at least iOS 8.1-8.3 ARM64.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {*} Returns the "length" value.
+ */
+ var getLength = baseProperty('length');
+
+ /**
+ * Gets the property names, values, and compare flags of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the match data of `object`.
+ */
+ function getMatchData(object) {
+ var result = toPairs(object),
+ length = result.length;
+
+ while (length--) {
+ result[length][2] = isStrictComparable(result[length][1]);
+ }
+ return result;
+ }
+
+ /**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+ function getNative(object, key) {
+ var value = object == null ? undefined : object[key];
+ return isNative(value) ? value : undefined;
+ }
+
+ /**
+ * Gets the argument placeholder value for `func`.
+ *
+ * @private
+ * @param {Function} func The function to inspect.
+ * @returns {*} Returns the placeholder value.
+ */
+ function getPlaceholder(func) {
+ var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
+ return object.placeholder;
+ }
+
+ /**
+ * Creates an array of the own symbol properties of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+ var getSymbols = getOwnPropertySymbols || function() {
+ return [];
+ };
+
+ /**
+ * Gets the `toStringTag` of `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+ function getTag(value) {
+ return objectToString.call(value);
+ }
+
+ // Fallback for IE 11 providing `toStringTag` values for maps, sets, and weakmaps.
+ if ((Map && getTag(new Map) != mapTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
+ getTag = function(value) {
+ var result = objectToString.call(value),
+ Ctor = result == objectTag ? value.constructor : null,
+ ctorString = typeof Ctor == 'function' ? funcToString.call(Ctor) : '';
+
+ if (ctorString) {
+ switch (ctorString) {
+ case mapCtorString: return mapTag;
+ case setCtorString: return setTag;
+ case weakMapCtorString: return weakMapTag;
+ }
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Gets the view, applying any `transforms` to the `start` and `end` positions.
+ *
+ * @private
+ * @param {number} start The start of the view.
+ * @param {number} end The end of the view.
+ * @param {Array} transforms The transformations to apply to the view.
+ * @returns {Object} Returns an object containing the `start` and `end`
+ * positions of the view.
+ */
+ function getView(start, end, transforms) {
+ var index = -1,
+ length = transforms.length;
+
+ while (++index < length) {
+ var data = transforms[index],
+ size = data.size;
+
+ switch (data.type) {
+ case 'drop': start += size; break;
+ case 'dropRight': end -= size; break;
+ case 'take': end = nativeMin(end, start + size); break;
+ case 'takeRight': start = nativeMax(start, end - size); break;
+ }
+ }
+ return { 'start': start, 'end': end };
+ }
+
+ /**
+ * Checks if `path` exists on `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @param {Function} hasFunc The function to check properties.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ */
+ function hasPath(object, path, hasFunc) {
+ if (object == null) {
+ return false;
+ }
+ var result = hasFunc(object, path);
+ if (!result && !isKey(path)) {
+ path = baseCastPath(path);
+ object = parent(object, path);
+ if (object != null) {
+ path = last(path);
+ result = hasFunc(object, path);
+ }
+ }
+ var length = object ? object.length : undefined;
+ return result || (
+ !!length && isLength(length) && isIndex(path, length) &&
+ (isArray(object) || isString(object) || isArguments(object))
+ );
+ }
+
+ /**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+ function initCloneArray(array) {
+ var length = array.length,
+ result = array.constructor(length);
+
+ // Add properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+ }
+
+ /**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneObject(object) {
+ return (isFunction(object.constructor) && !isPrototype(object))
+ ? baseCreate(getPrototypeOf(object))
+ : {};
+ }
+
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+
+ case mapTag:
+ return cloneMap(object);
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ return cloneRegExp(object);
+
+ case setTag:
+ return cloneSet(object);
+
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+ }
+
+ /**
+ * Creates an array of index keys for `object` values of arrays,
+ * `arguments` objects, and strings, otherwise `null` is returned.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array|null} Returns index keys, else `null`.
+ */
+ function indexKeys(object) {
+ var length = object ? object.length : undefined;
+ if (isLength(length) &&
+ (isArray(object) || isString(object) || isArguments(object))) {
+ return baseTimes(length, String);
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the given arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
+ */
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)) {
+ return eq(object[index], value);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if `value` is a property name and not a property path.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ */
+ function isKey(value, object) {
+ if (typeof value == 'number') {
+ return true;
+ }
+ return !isArray(value) &&
+ (reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
+ (object != null && value in Object(object)));
+ }
+
+ /**
+ * Checks if `value` is suitable for use as unique object key.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
+ */
+ function isKeyable(value) {
+ var type = typeof value;
+ return type == 'number' || type == 'boolean' ||
+ (type == 'string' && value != '__proto__') || value == null;
+ }
+
+ /**
+ * Checks if `func` has a lazy counterpart.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
+ */
+ function isLaziable(func) {
+ var funcName = getFuncName(func),
+ other = lodash[funcName];
+
+ if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+
+ /**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+ function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (isFunction(Ctor) && Ctor.prototype) || objectProto;
+
+ return value === proto;
+ }
+
+ /**
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
+ */
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+
+ /**
+ * Merges the function metadata of `source` into `data`.
+ *
+ * Merging metadata reduces the number of wrappers used to invoke a function.
+ * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+ * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
+ * modify function arguments, making the order in which they are executed important,
+ * preventing the merging of metadata. However, we make an exception for a safe
+ * combined case where curried functions have `_.ary` and or `_.rearg` applied.
+ *
+ * @private
+ * @param {Array} data The destination metadata.
+ * @param {Array} source The source metadata.
+ * @returns {Array} Returns `data`.
+ */
+ function mergeData(data, source) {
+ var bitmask = data[1],
+ srcBitmask = source[1],
+ newBitmask = bitmask | srcBitmask,
+ isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG);
+
+ var isCombo =
+ ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) ||
+ ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
+ ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));
+
+ // Exit early if metadata can't be merged.
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ // Use source `thisArg` if available.
+ if (srcBitmask & BIND_FLAG) {
+ data[2] = source[2];
+ // Set when currying a bound function.
+ newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG;
+ }
+ // Compose partial arguments.
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : copyArray(value);
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : copyArray(source[4]);
+ }
+ // Compose partial right arguments.
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : copyArray(value);
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : copyArray(source[6]);
+ }
+ // Use source `argPos` if available.
+ value = source[7];
+ if (value) {
+ data[7] = copyArray(value);
+ }
+ // Use source `ary` if it's smaller.
+ if (srcBitmask & ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ // Use source `arity` if one is not provided.
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ // Use source `func` and merge bitmasks.
+ data[0] = source[0];
+ data[1] = newBitmask;
+
+ return data;
+ }
+
+ /**
+ * Used by `_.defaultsDeep` to customize its `_.merge` use.
+ *
+ * @private
+ * @param {*} objValue The destination value.
+ * @param {*} srcValue The source value.
+ * @param {string} key The key of the property to merge.
+ * @param {Object} object The parent object of `objValue`.
+ * @param {Object} source The parent object of `srcValue`.
+ * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
+ * @returns {*} Returns the value to assign.
+ */
+ function mergeDefaults(objValue, srcValue, key, object, source, stack) {
+ if (isObject(objValue) && isObject(srcValue)) {
+ stack.set(srcValue, objValue);
+ baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
+ }
+ return objValue;
+ }
+
+ /**
+ * Gets the parent value at `path` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} path The path to get the parent value of.
+ * @returns {*} Returns the parent value.
+ */
+ function parent(object, path) {
+ return path.length == 1 ? object : get(object, baseSlice(path, 0, -1));
+ }
+
+ /**
+ * Reorder `array` according to the specified indexes where the element at
+ * the first index is assigned as the first element, the element at
+ * the second index is assigned as the second element, and so on.
+ *
+ * @private
+ * @param {Array} array The array to reorder.
+ * @param {Array} indexes The arranged array indexes.
+ * @returns {Array} Returns `array`.
+ */
+ function reorder(array, indexes) {
+ var arrLength = array.length,
+ length = nativeMin(indexes.length, arrLength),
+ oldArray = copyArray(array);
+
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
+ }
+ return array;
+ }
+
+ /**
+ * Sets metadata for `func`.
+ *
+ * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+ * period of time, it will trip its breaker and transition to an identity function
+ * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
+ * for more details.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var setData = (function() {
+ var count = 0,
+ lastCalled = 0;
+
+ return function(key, value) {
+ var stamp = now(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return key;
+ }
+ } else {
+ count = 0;
+ }
+ return baseSetData(key, value);
+ };
+ }());
+
+ /**
+ * Converts `string` to a property path array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the property path array.
+ */
+ function stringToPath(string) {
+ var result = [];
+ toString(string).replace(rePropName, function(match, number, quote, string) {
+ result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+ }
+
+ /**
+ * Creates a clone of `wrapper`.
+ *
+ * @private
+ * @param {Object} wrapper The wrapper to clone.
+ * @returns {Object} Returns the cloned wrapper.
+ */
+ function wrapperClone(wrapper) {
+ if (wrapper instanceof LazyWrapper) {
+ return wrapper.clone();
+ }
+ var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+ result.__actions__ = copyArray(wrapper.__actions__);
+ result.__index__ = wrapper.__index__;
+ result.__values__ = wrapper.__values__;
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of elements split into groups the length of `size`.
+ * If `array` can't be split evenly, the final chunk will be the remaining
+ * elements.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to process.
+ * @param {number} [size=0] The length of each chunk.
+ * @returns {Array} Returns the new array containing chunks.
+ * @example
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 2);
+ * // => [['a', 'b'], ['c', 'd']]
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 3);
+ * // => [['a', 'b', 'c'], ['d']]
+ */
+ function chunk(array, size) {
+ size = nativeMax(toInteger(size), 0);
+
+ var length = array ? array.length : 0;
+ if (!length || size < 1) {
+ return [];
+ }
+ var index = 0,
+ resIndex = -1,
+ result = Array(nativeCeil(length / size));
+
+ while (index < length) {
+ result[++resIndex] = baseSlice(array, index, (index += size));
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are falsey.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ var index = -1,
+ length = array ? array.length : 0,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates a new array concatenating `array` with any additional arrays
+ * and/or values.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to concatenate.
+ * @param {...*} [values] The values to concatenate.
+ * @returns {Array} Returns the new concatenated array.
+ * @example
+ *
+ * var array = [1];
+ * var other = _.concat(array, 2, [3], [[4]]);
+ *
+ * console.log(other);
+ * // => [1, 2, 3, [4]]
+ *
+ * console.log(array);
+ * // => [1]
+ */
+ var concat = rest(function(array, values) {
+ if (!isArray(array)) {
+ array = array == null ? [] : [Object(array)];
+ }
+ values = baseFlatten(values, 1);
+ return arrayConcat(array, values);
+ });
+
+ /**
+ * Creates an array of unique `array` values not included in the other
+ * given arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.difference([3, 2, 1], [4, 2]);
+ * // => [3, 1]
+ */
+ var difference = rest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, true))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `iteratee` which
+ * is invoked for each element of `array` and `values` to generate the criterion
+ * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
+ * // => [3.1, 1.3]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var differenceBy = rest(function(array, values) {
+ var iteratee = last(values);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, true), getIteratee(iteratee))
+ : [];
+ });
+
+ /**
+ * This method is like `_.difference` except that it accepts `comparator`
+ * which is invoked to compare elements of `array` to `values`. The comparator
+ * is invoked with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The values to exclude.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ *
+ * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }]
+ */
+ var differenceWith = rest(function(array, values) {
+ var comparator = last(values);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined;
+ }
+ return isArrayLikeObject(array)
+ ? baseDifference(array, baseFlatten(values, 1, true), undefined, comparator)
+ : [];
+ });
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.drop([1, 2, 3]);
+ * // => [2, 3]
+ *
+ * _.drop([1, 2, 3], 2);
+ * // => [3]
+ *
+ * _.drop([1, 2, 3], 5);
+ * // => []
+ *
+ * _.drop([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function drop(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the end.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRight([1, 2, 3]);
+ * // => [1, 2]
+ *
+ * _.dropRight([1, 2, 3], 2);
+ * // => [1]
+ *
+ * _.dropRight([1, 2, 3], 5);
+ * // => []
+ *
+ * _.dropRight([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function dropRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the end.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.dropRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropRightWhile(users, ['active', false]);
+ * // => objects for ['barney']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropRightWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the beginning.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.dropWhile(users, function(o) { return !o.active; });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.dropWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.dropWhile(users, ['active', false]);
+ * // => objects for ['pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.dropWhile(users, 'active');
+ * // => objects for ['barney', 'fred', 'pebbles']
+ */
+ function dropWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), true)
+ : [];
+ }
+
+ /**
+ * Fills elements of `array` with `value` from `start` up to, but not
+ * including, `end`.
+ *
+ * **Note:** This method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.fill(array, 'a');
+ * console.log(array);
+ * // => ['a', 'a', 'a']
+ *
+ * _.fill(Array(3), 2);
+ * // => [2, 2, 2]
+ *
+ * _.fill([4, 6, 8, 10], '*', 1, 3);
+ * // => [4, '*', '*', 10]
+ */
+ function fill(array, value, start, end) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+
+ /**
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(o) { return o.user == 'barney'; });
+ * // => 0
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findIndex(users, ['active', false]);
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findIndex(users, 'active');
+ * // => 2
+ */
+ function findIndex(array, predicate) {
+ return (array && array.length)
+ ? baseFindIndex(array, getIteratee(predicate, 3))
+ : -1;
+ }
+
+ /**
+ * This method is like `_.findIndex` except that it iterates over elements
+ * of `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
+ * // => 2
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+ * // => 0
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastIndex(users, ['active', false]);
+ * // => 2
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastIndex(users, 'active');
+ * // => 0
+ */
+ function findLastIndex(array, predicate) {
+ return (array && array.length)
+ ? baseFindIndex(array, getIteratee(predicate, 3), true)
+ : -1;
+ }
+
+ /**
+ * Flattens `array` a single level deep.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, [3, [4]], 5]
+ */
+ function flatten(array) {
+ var length = array ? array.length : 0;
+ return length ? baseFlatten(array, 1) : [];
+ }
+
+ /**
+ * Recursively flattens `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flattenDeep([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, 3, 4, 5]
+ */
+ function flattenDeep(array) {
+ var length = array ? array.length : 0;
+ return length ? baseFlatten(array, INFINITY) : [];
+ }
+
+ /**
+ * Recursively flatten `array` up to `depth` times.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @param {number} [depth=1] The maximum recursion depth.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * var array = [1, [2, [3, [4]], 5]];
+ *
+ * _.flattenDepth(array, 1);
+ * // => [1, 2, [3, [4]], 5]
+ *
+ * _.flattenDepth(array, 2);
+ * // => [1, 2, 3, [4], 5]
+ */
+ function flattenDepth(array, depth) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
+ }
+
+ /**
+ * The inverse of `_.toPairs`; this method returns an object composed
+ * from key-value `pairs`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} pairs The key-value pairs.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.fromPairs([['fred', 30], ['barney', 40]]);
+ * // => { 'fred': 30, 'barney': 40 }
+ */
+ function fromPairs(pairs) {
+ var index = -1,
+ length = pairs ? pairs.length : 0,
+ result = {};
+
+ while (++index < length) {
+ var pair = pairs[index];
+ result[pair[0]] = pair[1];
+ }
+ return result;
+ }
+
+ /**
+ * Gets the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @alias first
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the first element of `array`.
+ * @example
+ *
+ * _.head([1, 2, 3]);
+ * // => 1
+ *
+ * _.head([]);
+ * // => undefined
+ */
+ function head(array) {
+ return array ? array[0] : undefined;
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found in `array`
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it's used as the offset
+ * from the end of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 1, 2], 2);
+ * // => 1
+ *
+ * // Search from the `fromIndex`.
+ * _.indexOf([1, 2, 1, 2], 2, 2);
+ * // => 3
+ */
+ function indexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ fromIndex = toInteger(fromIndex);
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return baseIndexOf(array, value, fromIndex);
+ }
+
+ /**
+ * Gets all but the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.initial([1, 2, 3]);
+ * // => [1, 2]
+ */
+ function initial(array) {
+ return dropRight(array, 1);
+ }
+
+ /**
+ * Creates an array of unique values that are included in all given arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of shared values.
+ * @example
+ *
+ * _.intersection([2, 1], [4, 2], [1, 2]);
+ * // => [2]
+ */
+ var intersection = rest(function(arrays) {
+ var mapped = arrayMap(arrays, baseCastArrayLikeObject);
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped)
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `iteratee`
+ * which is invoked for each element of each `arrays` to generate the criterion
+ * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of shared values.
+ * @example
+ *
+ * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
+ * // => [2.1]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }]
+ */
+ var intersectionBy = rest(function(arrays) {
+ var iteratee = last(arrays),
+ mapped = arrayMap(arrays, baseCastArrayLikeObject);
+
+ if (iteratee === last(mapped)) {
+ iteratee = undefined;
+ } else {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, getIteratee(iteratee))
+ : [];
+ });
+
+ /**
+ * This method is like `_.intersection` except that it accepts `comparator`
+ * which is invoked to compare elements of `arrays`. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of shared values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.intersectionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }]
+ */
+ var intersectionWith = rest(function(arrays) {
+ var comparator = last(arrays),
+ mapped = arrayMap(arrays, baseCastArrayLikeObject);
+
+ if (comparator === last(mapped)) {
+ comparator = undefined;
+ } else {
+ mapped.pop();
+ }
+ return (mapped.length && mapped[0] === arrays[0])
+ ? baseIntersection(mapped, undefined, comparator)
+ : [];
+ });
+
+ /**
+ * Converts all elements in `array` into a string separated by `separator`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to convert.
+ * @param {string} [separator=','] The element separator.
+ * @returns {string} Returns the joined string.
+ * @example
+ *
+ * _.join(['a', 'b', 'c'], '~');
+ * // => 'a~b~c'
+ */
+ function join(array, separator) {
+ return array ? nativeJoin.call(array, separator) : '';
+ }
+
+ /**
+ * Gets the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
+ *
+ * _.last([1, 2, 3]);
+ * // => 3
+ */
+ function last(array) {
+ var length = array ? array.length : 0;
+ return length ? array[length - 1] : undefined;
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it iterates over elements of
+ * `array` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=array.length-1] The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 1, 2], 2);
+ * // => 3
+ *
+ * // Search from the `fromIndex`.
+ * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+ * // => 1
+ */
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (fromIndex !== undefined) {
+ index = toInteger(fromIndex);
+ index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1;
+ }
+ if (value !== value) {
+ return indexOfNaN(array, index, true);
+ }
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Removes all given values from `array` using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
+ * to remove elements from an array by predicate.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...*} [values] The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3, 1, 2, 3];
+ *
+ * _.pull(array, 2, 3);
+ * console.log(array);
+ * // => [1, 1]
+ */
+ var pull = rest(pullAll);
+
+ /**
+ * This method is like `_.pull` except that it accepts an array of values to remove.
+ *
+ * **Note:** Unlike `_.difference`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3, 1, 2, 3];
+ *
+ * _.pullAll(array, [2, 3]);
+ * console.log(array);
+ * // => [1, 1]
+ */
+ function pullAll(array, values) {
+ return (array && array.length && values && values.length)
+ ? basePullAll(array, values)
+ : array;
+ }
+
+ /**
+ * This method is like `_.pullAll` except that it accepts `iteratee` which is
+ * invoked for each element of `array` and `values` to generate the criterion
+ * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to remove.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
+ *
+ * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
+ * console.log(array);
+ * // => [{ 'x': 2 }]
+ */
+ function pullAllBy(array, values, iteratee) {
+ return (array && array.length && values && values.length)
+ ? basePullAllBy(array, values, getIteratee(iteratee))
+ : array;
+ }
+
+ /**
+ * Removes elements from `array` corresponding to `indexes` and returns an
+ * array of removed elements.
+ *
+ * **Note:** Unlike `_.at`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [indexes] The indexes of elements to remove,
+ * specified individually or in arrays.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [5, 10, 15, 20];
+ * var evens = _.pullAt(array, 1, 3);
+ *
+ * console.log(array);
+ * // => [5, 15]
+ *
+ * console.log(evens);
+ * // => [10, 20]
+ */
+ var pullAt = rest(function(array, indexes) {
+ indexes = arrayMap(baseFlatten(indexes, 1), String);
+
+ var result = baseAt(array, indexes);
+ basePullAt(array, indexes.sort(compareAscending));
+ return result;
+ });
+
+ /**
+ * Removes all elements from `array` that `predicate` returns truthy for
+ * and returns an array of the removed elements. The predicate is invoked
+ * with three arguments: (value, index, array).
+ *
+ * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
+ * to pull elements from an array by value.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [1, 2, 3, 4];
+ * var evens = _.remove(array, function(n) {
+ * return n % 2 == 0;
+ * });
+ *
+ * console.log(array);
+ * // => [1, 3]
+ *
+ * console.log(evens);
+ * // => [2, 4]
+ */
+ function remove(array, predicate) {
+ var result = [];
+ if (!(array && array.length)) {
+ return result;
+ }
+ var index = -1,
+ indexes = [],
+ length = array.length;
+
+ predicate = getIteratee(predicate, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result;
+ }
+
+ /**
+ * Reverses `array` so that the first element becomes the last, the second
+ * element becomes the second to last, and so on.
+ *
+ * **Note:** This method mutates `array` and is based on
+ * [`Array#reverse`](https://mdn.io/Array/reverse).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.reverse(array);
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function reverse(array) {
+ return array ? nativeReverse.call(array) : array;
+ }
+
+ /**
+ * Creates a slice of `array` from `start` up to, but not including, `end`.
+ *
+ * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice)
+ * to ensure dense arrays are returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function slice(array, start, end) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ }
+ else {
+ start = start == null ? 0 : toInteger(start);
+ end = end === undefined ? length : toInteger(end);
+ }
+ return baseSlice(array, start, end);
+ }
+
+ /**
+ * Uses a binary search to determine the lowest index at which `value` should
+ * be inserted into `array` in order to maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted into `array`.
+ * @example
+ *
+ * _.sortedIndex([30, 50], 40);
+ * // => 1
+ *
+ * _.sortedIndex([4, 5], 4);
+ * // => 0
+ */
+ function sortedIndex(array, value) {
+ return baseSortedIndex(array, value);
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted into `array`.
+ * @example
+ *
+ * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 };
+ *
+ * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
+ * // => 1
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
+ * // => 0
+ */
+ function sortedIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee));
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedIndexOf([1, 1, 2, 2], 2);
+ * // => 2
+ */
+ function sortedIndexOf(array, value) {
+ var length = array ? array.length : 0;
+ if (length) {
+ var index = baseSortedIndex(array, value);
+ if (index < length && eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.sortedIndex` except that it returns the highest
+ * index at which `value` should be inserted into `array` in order to
+ * maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @returns {number} Returns the index at which `value` should be inserted into `array`.
+ * @example
+ *
+ * _.sortedLastIndex([4, 5], 4);
+ * // => 1
+ */
+ function sortedLastIndex(array, value) {
+ return baseSortedIndex(array, value, true);
+ }
+
+ /**
+ * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
+ * which is invoked for `value` and each element of `array` to compute their
+ * sort ranking. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the index at which `value` should be inserted into `array`.
+ * @example
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
+ * // => 1
+ */
+ function sortedLastIndexBy(array, value, iteratee) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee), true);
+ }
+
+ /**
+ * This method is like `_.lastIndexOf` except that it performs a binary
+ * search on a sorted `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.sortedLastIndexOf([1, 1, 2, 2], 2);
+ * // => 3
+ */
+ function sortedLastIndexOf(array, value) {
+ var length = array ? array.length : 0;
+ if (length) {
+ var index = baseSortedIndex(array, value, true) - 1;
+ if (eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * This method is like `_.uniq` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniq([1, 1, 2]);
+ * // => [1, 2]
+ */
+ function sortedUniq(array) {
+ return (array && array.length)
+ ? baseSortedUniq(array)
+ : [];
+ }
+
+ /**
+ * This method is like `_.uniqBy` except that it's designed and optimized
+ * for sorted arrays.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
+ * // => [1.1, 2.3]
+ */
+ function sortedUniqBy(array, iteratee) {
+ return (array && array.length)
+ ? baseSortedUniqBy(array, getIteratee(iteratee))
+ : [];
+ }
+
+ /**
+ * Gets all but the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.tail([1, 2, 3]);
+ * // => [2, 3]
+ */
+ function tail(array) {
+ return drop(array, 1);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.take([1, 2, 3]);
+ * // => [1]
+ *
+ * _.take([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.take([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.take([1, 2, 3], 0);
+ * // => []
+ */
+ function take(array, n, guard) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the end.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRight([1, 2, 3]);
+ * // => [3]
+ *
+ * _.takeRight([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * _.takeRight([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.takeRight([1, 2, 3], 0);
+ * // => []
+ */
+ function takeRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ n = (guard || n === undefined) ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the end. Elements are
+ * taken until `predicate` returns falsey. The predicate is invoked with three
+ * arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.takeRightWhile(users, function(o) { return !o.active; });
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
+ * // => objects for ['pebbles']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeRightWhile(users, ['active', false]);
+ * // => objects for ['fred', 'pebbles']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeRightWhile(users, 'active');
+ * // => []
+ */
+ function takeRightWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3), false, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the beginning. Elements
+ * are taken until `predicate` returns falsey. The predicate is invoked with
+ * three arguments: (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false},
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.takeWhile(users, function(o) { return !o.active; });
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.takeWhile(users, { 'user': 'barney', 'active': false });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.takeWhile(users, ['active', false]);
+ * // => objects for ['barney', 'fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.takeWhile(users, 'active');
+ * // => []
+ */
+ function takeWhile(array, predicate) {
+ return (array && array.length)
+ ? baseWhile(array, getIteratee(predicate, 3))
+ : [];
+ }
+
+ /**
+ * Creates an array of unique values, in order, from all given arrays using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([2, 1], [4, 2], [1, 2]);
+ * // => [2, 1, 4]
+ */
+ var union = rest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, true));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by which
+ * uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
+ * // => [2.1, 1.2, 4.3]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ var unionBy = rest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return baseUniq(baseFlatten(arrays, 1, true), getIteratee(iteratee));
+ });
+
+ /**
+ * This method is like `_.union` except that it accepts `comparator` which
+ * is invoked to compare elements of `arrays`. The comparator is invoked
+ * with two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.unionWith(objects, others, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var unionWith = rest(function(arrays) {
+ var comparator = last(arrays);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined;
+ }
+ return baseUniq(baseFlatten(arrays, 1, true), undefined, comparator);
+ });
+
+ /**
+ * Creates a duplicate-free version of an array, using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons, in which only the first occurrence of each element
+ * is kept.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniq([2, 1, 2]);
+ * // => [2, 1]
+ */
+ function uniq(array) {
+ return (array && array.length)
+ ? baseUniq(array)
+ : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
+ * // => [2.1, 1.2]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ function uniqBy(array, iteratee) {
+ return (array && array.length)
+ ? baseUniq(array, getIteratee(iteratee))
+ : [];
+ }
+
+ /**
+ * This method is like `_.uniq` except that it accepts `comparator` which
+ * is invoked to compare elements of `array`. The comparator is invoked with
+ * two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.uniqWith(objects, _.isEqual);
+ * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
+ */
+ function uniqWith(array, comparator) {
+ return (array && array.length)
+ ? baseUniq(array, undefined, comparator)
+ : [];
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts an array of grouped
+ * elements and creates an array regrouping the elements to their pre-zip
+ * configuration.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
+ *
+ * _.unzip(zipped);
+ * // => [['fred', 'barney'], [30, 40], [true, false]]
+ */
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var length = 0;
+ array = arrayFilter(array, function(group) {
+ if (isArrayLikeObject(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ return baseTimes(length, function(index) {
+ return arrayMap(array, baseProperty(index));
+ });
+ }
+
+ /**
+ * This method is like `_.unzip` except that it accepts `iteratee` to specify
+ * how regrouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @param {Function} [iteratee=_.identity] The function to combine regrouped values.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
+ * // => [[1, 10, 100], [2, 20, 200]]
+ *
+ * _.unzipWith(zipped, _.add);
+ * // => [3, 30, 300]
+ */
+ function unzipWith(array, iteratee) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var result = unzip(array);
+ if (iteratee == null) {
+ return result;
+ }
+ return arrayMap(result, function(group) {
+ return apply(iteratee, undefined, group);
+ });
+ }
+
+ /**
+ * Creates an array excluding all given values using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to filter.
+ * @param {...*} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.without([1, 2, 1, 3], 1, 2);
+ * // => [3]
+ */
+ var without = rest(function(array, values) {
+ return isArrayLikeObject(array)
+ ? baseDifference(array, values)
+ : [];
+ });
+
+ /**
+ * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+ * of the given arrays.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of values.
+ * @example
+ *
+ * _.xor([2, 1], [4, 2]);
+ * // => [1, 4]
+ */
+ var xor = rest(function(arrays) {
+ return baseXor(arrayFilter(arrays, isArrayLikeObject));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `iteratee` which is
+ * invoked for each element of each `arrays` to generate the criterion by which
+ * uniqueness is computed. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Array} Returns the new array of values.
+ * @example
+ *
+ * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor);
+ * // => [1.2, 4.3]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 2 }]
+ */
+ var xorBy = rest(function(arrays) {
+ var iteratee = last(arrays);
+ if (isArrayLikeObject(iteratee)) {
+ iteratee = undefined;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee));
+ });
+
+ /**
+ * This method is like `_.xor` except that it accepts `comparator` which is
+ * invoked to compare elements of `arrays`. The comparator is invoked with
+ * two arguments: (arrVal, othVal).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new array of values.
+ * @example
+ *
+ * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
+ * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
+ *
+ * _.xorWith(objects, others, _.isEqual);
+ * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
+ */
+ var xorWith = rest(function(arrays) {
+ var comparator = last(arrays);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
+ });
+
+ /**
+ * Creates an array of grouped elements, the first of which contains the first
+ * elements of the given arrays, the second of which contains the second elements
+ * of the given arrays, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
+ */
+ var zip = rest(unzip);
+
+ /**
+ * This method is like `_.fromPairs` except that it accepts two arrays,
+ * one of property names and one of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} [props=[]] The property names.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObject(['a', 'b'], [1, 2]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+ function zipObject(props, values) {
+ return baseZipObject(props || [], values || [], assignValue);
+ }
+
+ /**
+ * This method is like `_.zipObject` except that it supports property paths.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} [props=[]] The property names.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
+ * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
+ */
+ function zipObjectDeep(props, values) {
+ return baseZipObject(props || [], values || [], baseSet);
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts `iteratee` to specify
+ * how grouped values should be combined. The iteratee is invoked with the
+ * elements of each group: (...group).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @param {Function} [iteratee=_.identity] The function to combine grouped values.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
+ * return a + b + c;
+ * });
+ * // => [111, 222]
+ */
+ var zipWith = rest(function(arrays) {
+ var length = arrays.length,
+ iteratee = length > 1 ? arrays[length - 1] : undefined;
+
+ iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
+ return unzipWith(arrays, iteratee);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object that wraps `value` with explicit method chaining enabled.
+ * The result of such method chaining must be unwrapped with `_#value`.
+ *
+ * @static
+ * @memberOf _
+ * @category Seq
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'pebbles', 'age': 1 }
+ * ];
+ *
+ * var youngest = _
+ * .chain(users)
+ * .sortBy('age')
+ * .map(function(o) {
+ * return o.user + ' is ' + o.age;
+ * })
+ * .head()
+ * .value();
+ * // => 'pebbles is 1'
+ */
+ function chain(value) {
+ var result = lodash(value);
+ result.__chain__ = true;
+ return result;
+ }
+
+ /**
+ * This method invokes `interceptor` and returns `value`. The interceptor
+ * is invoked with one argument; (value). The purpose of this method is to
+ * "tap into" a method chain in order to modify intermediate results.
+ *
+ * @static
+ * @memberOf _
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * _([1, 2, 3])
+ * .tap(function(array) {
+ * // Mutate input array.
+ * array.pop();
+ * })
+ * .reverse()
+ * .value();
+ * // => [2, 1]
+ */
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+
+ /**
+ * This method is like `_.tap` except that it returns the result of `interceptor`.
+ * The purpose of this method is to "pass thru" values replacing intermediate
+ * results in a method chain.
+ *
+ * @static
+ * @memberOf _
+ * @category Seq
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {*} Returns the result of `interceptor`.
+ * @example
+ *
+ * _(' abc ')
+ * .chain()
+ * .trim()
+ * .thru(function(value) {
+ * return [value];
+ * })
+ * .value();
+ * // => ['abc']
+ */
+ function thru(value, interceptor) {
+ return interceptor(value);
+ }
+
+ /**
+ * This method is the wrapper version of `_.at`.
+ *
+ * @name at
+ * @memberOf _
+ * @category Seq
+ * @param {...(string|string[])} [paths] The property paths of elements to pick,
+ * specified individually or in arrays.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _(object).at(['a[0].b.c', 'a[1]']).value();
+ * // => [3, 4]
+ *
+ * _(['a', 'b', 'c']).at(0, 2).value();
+ * // => ['a', 'c']
+ */
+ var wrapperAt = rest(function(paths) {
+ paths = baseFlatten(paths, 1);
+ var length = paths.length,
+ start = length ? paths[0] : 0,
+ value = this.__wrapped__,
+ interceptor = function(object) { return baseAt(object, paths); };
+
+ if (length > 1 || this.__actions__.length ||
+ !(value instanceof LazyWrapper) || !isIndex(start)) {
+ return this.thru(interceptor);
+ }
+ value = value.slice(start, +start + (length ? 1 : 0));
+ value.__actions__.push({
+ 'func': thru,
+ 'args': [interceptor],
+ 'thisArg': undefined
+ });
+ return new LodashWrapper(value, this.__chain__).thru(function(array) {
+ if (length && !array.length) {
+ array.push(undefined);
+ }
+ return array;
+ });
+ });
+
+ /**
+ * Enables explicit method chaining on the wrapper object.
+ *
+ * @name chain
+ * @memberOf _
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // A sequence without explicit chaining.
+ * _(users).head();
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // A sequence with explicit chaining.
+ * _(users)
+ * .chain()
+ * .head()
+ * .pick('user')
+ * .value();
+ * // => { 'user': 'barney' }
+ */
+ function wrapperChain() {
+ return chain(this);
+ }
+
+ /**
+ * Executes the chained sequence and returns the wrapped result.
+ *
+ * @name commit
+ * @memberOf _
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapped = _(array).push(3);
+ *
+ * console.log(array);
+ * // => [1, 2]
+ *
+ * wrapped = wrapped.commit();
+ * console.log(array);
+ * // => [1, 2, 3]
+ *
+ * wrapped.last();
+ * // => 3
+ *
+ * console.log(array);
+ * // => [1, 2, 3]
+ */
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+
+ /**
+ * This method is the wrapper version of `_.flatMap`.
+ *
+ * @name flatMap
+ * @memberOf _
+ * @category Seq
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [n, n];
+ * }
+ *
+ * _([1, 2]).flatMap(duplicate).value();
+ * // => [1, 1, 2, 2]
+ */
+ function wrapperFlatMap(iteratee) {
+ return this.map(iteratee).flatten();
+ }
+
+ /**
+ * Gets the next value on a wrapped object following the
+ * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
+ *
+ * @name next
+ * @memberOf _
+ * @category Seq
+ * @returns {Object} Returns the next iterator value.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 1 }
+ *
+ * wrapped.next();
+ * // => { 'done': false, 'value': 2 }
+ *
+ * wrapped.next();
+ * // => { 'done': true, 'value': undefined }
+ */
+ function wrapperNext() {
+ if (this.__values__ === undefined) {
+ this.__values__ = toArray(this.value());
+ }
+ var done = this.__index__ >= this.__values__.length,
+ value = done ? undefined : this.__values__[this.__index__++];
+
+ return { 'done': done, 'value': value };
+ }
+
+ /**
+ * Enables the wrapper to be iterable.
+ *
+ * @name Symbol.iterator
+ * @memberOf _
+ * @category Seq
+ * @returns {Object} Returns the wrapper object.
+ * @example
+ *
+ * var wrapped = _([1, 2]);
+ *
+ * wrapped[Symbol.iterator]() === wrapped;
+ * // => true
+ *
+ * Array.from(wrapped);
+ * // => [1, 2]
+ */
+ function wrapperToIterator() {
+ return this;
+ }
+
+ /**
+ * Creates a clone of the chained sequence planting `value` as the wrapped value.
+ *
+ * @name plant
+ * @memberOf _
+ * @category Seq
+ * @param {*} value The value to plant.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var wrapped = _([1, 2]).map(square);
+ * var other = wrapped.plant([3, 4]);
+ *
+ * other.value();
+ * // => [9, 16]
+ *
+ * wrapped.value();
+ * // => [1, 4]
+ */
+ function wrapperPlant(value) {
+ var result,
+ parent = this;
+
+ while (parent instanceof baseLodash) {
+ var clone = wrapperClone(parent);
+ clone.__index__ = 0;
+ clone.__values__ = undefined;
+ if (result) {
+ previous.__wrapped__ = clone;
+ } else {
+ result = clone;
+ }
+ var previous = clone;
+ parent = parent.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result;
+ }
+
+ /**
+ * This method is the wrapper version of `_.reverse`.
+ *
+ * **Note:** This method mutates the wrapped array.
+ *
+ * @name reverse
+ * @memberOf _
+ * @category Seq
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _(array).reverse().value()
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({
+ 'func': thru,
+ 'args': [reverse],
+ 'thisArg': undefined
+ });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(reverse);
+ }
+
+ /**
+ * Executes the chained sequence to extract the unwrapped value.
+ *
+ * @name value
+ * @memberOf _
+ * @alias toJSON, valueOf
+ * @category Seq
+ * @returns {*} Returns the resolved unwrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the number of times the key was returned by `iteratee`.
+ * The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
+ */
+ var countBy = createAggregator(function(result, value, key) {
+ hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
+ });
+
+ /**
+ * Checks if `predicate` returns truthy for **all** elements of `collection`.
+ * Iteration is stopped once `predicate` returns falsey. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.every(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.every(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.every(users, 'active');
+ * // => false
+ */
+ function every(collection, predicate, guard) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.filter(users, { 'age': 36, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.filter(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.filter(users, 'active');
+ * // => objects for ['barney']
+ */
+ function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.find(users, function(o) { return o.age < 40; });
+ * // => object for 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.find(users, { 'age': 1, 'active': true });
+ * // => object for 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.find(users, ['active', false]);
+ * // => object for 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.find(users, 'active');
+ * // => object for 'barney'
+ */
+ function find(collection, predicate) {
+ predicate = getIteratee(predicate, 3);
+ if (isArray(collection)) {
+ var index = baseFindIndex(collection, predicate);
+ return index > -1 ? collection[index] : undefined;
+ }
+ return baseFind(collection, predicate, baseEach);
+ }
+
+ /**
+ * This method is like `_.find` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * _.findLast([1, 2, 3, 4], function(n) {
+ * return n % 2 == 1;
+ * });
+ * // => 3
+ */
+ function findLast(collection, predicate) {
+ predicate = getIteratee(predicate, 3);
+ if (isArray(collection)) {
+ var index = baseFindIndex(collection, predicate, true);
+ return index > -1 ? collection[index] : undefined;
+ }
+ return baseFind(collection, predicate, baseEachRight);
+ }
+
+ /**
+ * Creates an array of flattened values by running each element in `collection`
+ * through `iteratee` and concating its result to the other mapped values.
+ * The iteratee is invoked with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * function duplicate(n) {
+ * return [n, n];
+ * }
+ *
+ * _.flatMap([1, 2], duplicate);
+ * // => [1, 1, 2, 2]
+ */
+ function flatMap(collection, iteratee) {
+ return baseFlatten(map(collection, iteratee), 1);
+ }
+
+ /**
+ * Iterates over elements of `collection` invoking `iteratee` for each element.
+ * The iteratee is invoked with three arguments: (value, index|key, collection).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * **Note:** As with other "Collections" methods, objects with a "length" property
+ * are iterated like arrays. To avoid this behavior use `_.forIn` or `_.forOwn`
+ * for object iteration.
+ *
+ * @static
+ * @memberOf _
+ * @alias each
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @example
+ *
+ * _([1, 2]).forEach(function(value) {
+ * console.log(value);
+ * });
+ * // => logs `1` then `2`
+ *
+ * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a' then 'b' (iteration order is not guaranteed)
+ */
+ function forEach(collection, iteratee) {
+ return (typeof iteratee == 'function' && isArray(collection))
+ ? arrayEach(collection, iteratee)
+ : baseEach(collection, baseCastFunction(iteratee));
+ }
+
+ /**
+ * This method is like `_.forEach` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @alias eachRight
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @example
+ *
+ * _.forEachRight([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => logs `2` then `1`
+ */
+ function forEachRight(collection, iteratee) {
+ return (typeof iteratee == 'function' && isArray(collection))
+ ? arrayEachRight(collection, iteratee)
+ : baseEachRight(collection, baseCastFunction(iteratee));
+ }
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is an array of elements responsible for generating the key.
+ * The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([6.1, 4.2, 6.3], Math.floor);
+ * // => { '4': [4.2], '6': [6.1, 6.3] }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ var groupBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ result[key].push(value);
+ } else {
+ result[key] = [value];
+ }
+ });
+
+ /**
+ * Checks if `value` is in `collection`. If `collection` is a string it's checked
+ * for a substring of `value`, otherwise [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * is used for equality comparisons. If `fromIndex` is negative, it's used as
+ * the offset from the end of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`.
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
+ * // => true
+ *
+ * _.includes('pebbles', 'eb');
+ * // => true
+ */
+ function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
+
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection)
+ ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
+ : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
+ }
+
+ /**
+ * Invokes the method at `path` of each element in `collection`, returning
+ * an array of the results of each invoked method. Any additional arguments
+ * are provided to each invoked method. If `methodName` is a function it's
+ * invoked for, and `this` bound to, each element in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Array|Function|string} path The path of the method to invoke or
+ * the function invoked per iteration.
+ * @param {...*} [args] The arguments to invoke each method with.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invokeMap([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
+ */
+ var invokeMap = rest(function(collection, path, args) {
+ var index = -1,
+ isFunc = typeof path == 'function',
+ isProp = isKey(path),
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value) {
+ var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
+ result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args);
+ });
+ return result;
+ });
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the last element responsible for generating the key. The
+ * iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * var array = [
+ * { 'dir': 'left', 'code': 97 },
+ * { 'dir': 'right', 'code': 100 }
+ * ];
+ *
+ * _.keyBy(array, function(o) {
+ * return String.fromCharCode(o.code);
+ * });
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.keyBy(array, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ */
+ var keyBy = createAggregator(function(result, value, key) {
+ result[key] = value;
+ });
+
+ /**
+ * Creates an array of values by running each element in `collection` through
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, `fill`,
+ * `invert`, `parseInt`, `random`, `range`, `rangeRight`, `slice`, `some`,
+ * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimEnd`, `trimStart`,
+ * and `words`
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * _.map([4, 8], square);
+ * // => [16, 64]
+ *
+ * _.map({ 'a': 4, 'b': 8 }, square);
+ * // => [16, 64] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
+ */
+ function map(collection, iteratee) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, getIteratee(iteratee, 3));
+ }
+
+ /**
+ * This method is like `_.sortBy` except that it allows specifying the sort
+ * orders of the iteratees to sort by. If `orders` is unspecified, all values
+ * are sorted in ascending order. Otherwise, specify an order of "desc" for
+ * descending or "asc" for ascending sort order of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} [iteratees=[_.identity]] The iteratees to sort by.
+ * @param {string[]} [orders] The sort orders of `iteratees`.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 34 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 36 }
+ * ];
+ *
+ * // Sort by `user` in ascending order and by `age` in descending order.
+ * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ */
+ function orderBy(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ orders = guard ? undefined : orders;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseOrderBy(collection, iteratees, orders);
+ }
+
+ /**
+ * Creates an array of elements split into two groups, the first of which
+ * contains elements `predicate` returns truthy for, the second of which
+ * contains elements `predicate` returns falsey for. The predicate is
+ * invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the array of grouped elements.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true },
+ * { 'user': 'pebbles', 'age': 1, 'active': false }
+ * ];
+ *
+ * _.partition(users, function(o) { return o.active; });
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.partition(users, { 'age': 1, 'active': false });
+ * // => objects for [['pebbles'], ['barney', 'fred']]
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.partition(users, ['active', false]);
+ * // => objects for [['barney', 'pebbles'], ['fred']]
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.partition(users, 'active');
+ * // => objects for [['fred'], ['barney', 'pebbles']]
+ */
+ var partition = createAggregator(function(result, value, key) {
+ result[key ? 0 : 1].push(value);
+ }, function() { return [[], []]; });
+
+ /**
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` through `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not given the first element of `collection` is used as the initial
+ * value. The iteratee is invoked with four arguments:
+ * (accumulator, value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
+ * and `sortBy`
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.reduce([1, 2], function(sum, n) {
+ * return sum + n;
+ * }, 0);
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * return result;
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
+ */
+ function reduce(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
+ }
+
+ /**
+ * This method is like `_.reduce` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * var array = [[0, 1], [2, 3], [4, 5]];
+ *
+ * _.reduceRight(array, function(flattened, other) {
+ * return flattened.concat(other);
+ * }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ function reduceRight(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduceRight : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
+ }
+
+ /**
+ * The opposite of `_.filter`; this method returns the elements of `collection`
+ * that `predicate` does **not** return truthy for.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true }
+ * ];
+ *
+ * _.reject(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.reject(users, { 'age': 40, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.reject(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.reject(users, 'active');
+ * // => objects for ['barney']
+ */
+ function reject(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ predicate = getIteratee(predicate, 3);
+ return func(collection, function(value, index, collection) {
+ return !predicate(value, index, collection);
+ });
+ }
+
+ /**
+ * Gets a random element from `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @returns {*} Returns the random element.
+ * @example
+ *
+ * _.sample([1, 2, 3, 4]);
+ * // => 2
+ */
+ function sample(collection) {
+ var array = isArrayLike(collection) ? collection : values(collection),
+ length = array.length;
+
+ return length > 0 ? array[baseRandom(0, length - 1)] : undefined;
+ }
+
+ /**
+ * Gets `n` random elements at unique keys from `collection` up to the
+ * size of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to sample.
+ * @param {number} [n=0] The number of elements to sample.
+ * @returns {Array} Returns the random elements.
+ * @example
+ *
+ * _.sampleSize([1, 2, 3], 2);
+ * // => [3, 1]
+ *
+ * _.sampleSize([1, 2, 3], 4);
+ * // => [2, 3, 1]
+ */
+ function sampleSize(collection, n) {
+ var index = -1,
+ result = toArray(collection),
+ length = result.length,
+ lastIndex = length - 1;
+
+ n = baseClamp(toInteger(n), 0, length);
+ while (++index < n) {
+ var rand = baseRandom(index, lastIndex),
+ value = result[rand];
+
+ result[rand] = result[index];
+ result[index] = value;
+ }
+ result.length = n;
+ return result;
+ }
+
+ /**
+ * Creates an array of shuffled values, using a version of the
+ * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4]);
+ * // => [4, 1, 3, 2]
+ */
+ function shuffle(collection) {
+ return sampleSize(collection, MAX_ARRAY_LENGTH);
+ }
+
+ /**
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @returns {number} Returns the collection size.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
+ */
+ function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ var result = collection.length;
+ return (result && isString(collection)) ? stringSize(collection) : result;
+ }
+ return keys(collection).length;
+ }
+
+ /**
+ * Checks if `predicate` returns truthy for **any** element of `collection`.
+ * Iteration is stopped once `predicate` returns truthy. The predicate is
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.some(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.some(users, ['active', false]);
+ * // => true
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.some(users, 'active');
+ * // => true
+ */
+ function some(collection, predicate, guard) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+
+ /**
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection through each iteratee. This method
+ * performs a stable sort, that is, it preserves the original sort order of
+ * equal elements. The iteratees are invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {...(Function|Function[]|Object|Object[]|string|string[])} [iteratees=[_.identity]]
+ * The iteratees to sort by, specified individually or in arrays.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.sortBy(users, function(o) { return o.user; });
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ *
+ * _.sortBy(users, ['user', 'age']);
+ * // => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
+ *
+ * _.sortBy(users, 'user', function(o) {
+ * return Math.floor(o.age / 10);
+ * });
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ */
+ var sortBy = rest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees.length = 1;
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Gets the timestamp of the number of milliseconds that have elapsed since
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @type {Function}
+ * @category Date
+ * @returns {number} Returns the timestamp.
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => logs the number of milliseconds it took for the deferred function to be invoked
+ */
+ var now = Date.now;
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The opposite of `_.before`; this method creates a function that invokes
+ * `func` once it's called `n` or more times.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls before `func` is invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var saves = ['profile', 'settings'];
+ *
+ * var done = _.after(saves.length, function() {
+ * console.log('done saving!');
+ * });
+ *
+ * _.forEach(saves, function(type) {
+ * asyncSave({ 'type': type, 'complete': done });
+ * });
+ * // => logs 'done saving!' after the two async saves have completed
+ */
+ function after(n, func) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a function that accepts up to `n` arguments, ignoring any
+ * additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @param {number} [n=func.length] The arity cap.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+ * // => [6, 8, 10]
+ */
+ function ary(func, n, guard) {
+ n = guard ? undefined : n;
+ n = (func && n == null) ? func.length : n;
+ return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
+ }
+
+ /**
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it's called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * jQuery(element).on('click', _.before(5, addContactToList));
+ * // => allows adding up to 4 contacts to the list
+ */
+ function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and prepends any additional `_.bind` arguments to those provided to the
+ * bound function.
+ *
+ * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** Unlike native `Function#bind` this method doesn't set the "length"
+ * property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var greet = function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * };
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * var bound = _.bind(greet, object, 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bind(greet, object, _, '!');
+ * bound('hi');
+ * // => 'hi fred!'
+ */
+ var bind = rest(function(func, thisArg, partials) {
+ var bitmask = BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getPlaceholder(bind));
+ bitmask |= PARTIAL_FLAG;
+ }
+ return createWrapper(func, bitmask, thisArg, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes the method at `object[key]` and prepends
+ * any additional `_.bindKey` arguments to those provided to the bound function.
+ *
+ * This method differs from `_.bind` by allowing bound functions to reference
+ * methods that may be redefined or don't yet exist.
+ * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
+ * for more details.
+ *
+ * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Object} object The object to invoke the method on.
+ * @param {string} key The key of the method.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var object = {
+ * 'user': 'fred',
+ * 'greet': function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ * };
+ *
+ * var bound = _.bindKey(object, 'greet', 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * object.greet = function(greeting, punctuation) {
+ * return greeting + 'ya ' + this.user + punctuation;
+ * };
+ *
+ * bound('!');
+ * // => 'hiya fred!'
+ *
+ * // Bound with placeholders.
+ * var bound = _.bindKey(object, 'greet', _, '!');
+ * bound('hi');
+ * // => 'hiya fred!'
+ */
+ var bindKey = rest(function(object, key, partials) {
+ var bitmask = BIND_FLAG | BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getPlaceholder(bindKey));
+ bitmask |= PARTIAL_FLAG;
+ }
+ return createWrapper(key, bitmask, object, partials, holders);
+ });
+
+ /**
+ * Creates a function that accepts arguments of `func` and either invokes
+ * `func` returning its result, if at least `arity` number of arguments have
+ * been provided, or returns a function that accepts the remaining `func`
+ * arguments, and so on. The arity of `func` may be specified if `func.length`
+ * is not sufficient.
+ *
+ * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curry(abc);
+ *
+ * curried(1)(2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(1)(_, 3)(2);
+ * // => [1, 2, 3]
+ */
+ function curry(func, arity, guard) {
+ arity = guard ? undefined : arity;
+ var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
+ result.placeholder = curry.placeholder;
+ return result;
+ }
+
+ /**
+ * This method is like `_.curry` except that arguments are applied to `func`
+ * in the manner of `_.partialRight` instead of `_.partial`.
+ *
+ * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curryRight(abc);
+ *
+ * curried(3)(2)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(2, 3)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // Curried with placeholders.
+ * curried(3)(1, _)(2);
+ * // => [1, 2, 3]
+ */
+ function curryRight(func, arity, guard) {
+ arity = guard ? undefined : arity;
+ var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
+ result.placeholder = curryRight.placeholder;
+ return result;
+ }
+
+ /**
+ * Creates a debounced function that delays invoking `func` until after `wait`
+ * milliseconds have elapsed since the last time the debounced function was
+ * invoked. The debounced function comes with a `cancel` method to cancel
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
+ * Provide an options object to indicate whether `func` should be invoked on
+ * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked
+ * with the last arguments provided to the debounced function. Subsequent calls
+ * to the debounced function return the result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the debounced function is
+ * invoked more than once during the `wait` timeout.
+ *
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.debounce` and `_.throttle`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=false] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {number} [options.maxWait] The maximum time `func` is allowed to be
+ * delayed before it's invoked.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * // Avoid costly calculations while the window size is in flux.
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+ *
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
+ *
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', debounced);
+ *
+ * // Cancel the trailing debounced invocation.
+ * jQuery(window).on('popstate', debounced.cancel);
+ */
+ function debounce(func, wait, options) {
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ leading = false,
+ maxWait = false,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxWait = 'maxWait' in options && nativeMax(toNumber(options.maxWait) || 0, wait);
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+
+ function cancel() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ lastCalled = 0;
+ args = maxTimeoutId = thisArg = timeoutId = trailingCall = undefined;
+ }
+
+ function complete(isCalled, id) {
+ if (id) {
+ clearTimeout(id);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = undefined;
+ }
+ }
+ }
+
+ function delayed() {
+ var remaining = wait - (now() - stamp);
+ if (remaining <= 0 || remaining > wait) {
+ complete(trailingCall, maxTimeoutId);
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ }
+
+ function flush() {
+ if ((timeoutId && trailingCall) || (maxTimeoutId && trailing)) {
+ result = func.apply(thisArg, args);
+ }
+ cancel();
+ return result;
+ }
+
+ function maxDelayed() {
+ complete(trailing, timeoutId);
+ }
+
+ function debounced() {
+ args = arguments;
+ stamp = now();
+ thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
+
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!lastCalled && !maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled);
+
+ var isCalled = (remaining <= 0 || remaining > maxWait) &&
+ (leading || maxTimeoutId);
+
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
+ result = func.apply(thisArg, args);
+ }
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = undefined;
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+ }
+
+ /**
+ * Defers invoking the `func` until the current call stack has cleared. Any
+ * additional arguments are provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to defer.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.defer(function(text) {
+ * console.log(text);
+ * }, 'deferred');
+ * // => logs 'deferred' after one or more milliseconds
+ */
+ var defer = rest(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+
+ /**
+ * Invokes `func` after `wait` milliseconds. Any additional arguments are
+ * provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {...*} [args] The arguments to invoke `func` with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.delay(function(text) {
+ * console.log(text);
+ * }, 1000, 'later');
+ * // => logs 'later' after one second
+ */
+ var delay = rest(function(func, wait, args) {
+ return baseDelay(func, toNumber(wait) || 0, args);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments reversed.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to flip arguments for.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var flipped = _.flip(function() {
+ * return _.toArray(arguments);
+ * });
+ *
+ * flipped('a', 'b', 'c', 'd');
+ * // => ['d', 'c', 'b', 'a']
+ */
+ function flip(func) {
+ return createWrapper(func, FLIP_FLAG);
+ }
+
+ /**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is used as the map cache key. The `func`
+ * is invoked with the `this` binding of the memoized function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
+ * method interface of `delete`, `get`, `has`, and `set`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoizing function.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ * var other = { 'c': 3, 'd': 4 };
+ *
+ * var values = _.memoize(_.values);
+ * values(object);
+ * // => [1, 2]
+ *
+ * values(other);
+ * // => [3, 4]
+ *
+ * object.a = 2;
+ * values(object);
+ * // => [1, 2]
+ *
+ * // Modify the result cache.
+ * values.cache.set(object, ['a', 'b']);
+ * values(object);
+ * // => ['a', 'b']
+ *
+ * // Replace `_.memoize.Cache`.
+ * _.memoize.Cache = WeakMap;
+ */
+ function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments,
+ key = resolver ? resolver.apply(this, args) : args[0],
+ cache = memoized.cache;
+
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result = func.apply(this, args);
+ memoized.cache = cache.set(key, result);
+ return result;
+ };
+ memoized.cache = new memoize.Cache;
+ return memoized;
+ }
+
+ /**
+ * Creates a function that negates the result of the predicate `func`. The
+ * `func` predicate is invoked with the `this` binding and arguments of the
+ * created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} predicate The predicate to negate.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function isEven(n) {
+ * return n % 2 == 0;
+ * }
+ *
+ * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+ * // => [1, 3, 5]
+ */
+ function negate(predicate) {
+ if (typeof predicate != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ }
+
+ /**
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first invocation. The `func` is
+ * invoked with the `this` binding and arguments of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // `initialize` invokes `createApplication` once
+ */
+ function once(func) {
+ return before(2, func);
+ }
+
+ /**
+ * Creates a function that invokes `func` with arguments transformed by
+ * corresponding `transforms`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to wrap.
+ * @param {...(Function|Function[])} [transforms] The functions to transform
+ * arguments, specified individually or in arrays.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function doubled(n) {
+ * return n * 2;
+ * }
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var func = _.overArgs(function(x, y) {
+ * return [x, y];
+ * }, square, doubled);
+ *
+ * func(9, 3);
+ * // => [81, 6]
+ *
+ * func(10, 5);
+ * // => [100, 10]
+ */
+ var overArgs = rest(function(func, transforms) {
+ transforms = arrayMap(baseFlatten(transforms, 1), getIteratee());
+
+ var funcsLength = transforms.length;
+ return rest(function(args) {
+ var index = -1,
+ length = nativeMin(args.length, funcsLength);
+
+ while (++index < length) {
+ args[index] = transforms[index].call(this, args[index]);
+ }
+ return apply(func, this, args);
+ });
+ });
+
+ /**
+ * Creates a function that invokes `func` with `partial` arguments prepended
+ * to those provided to the new function. This method is like `_.bind` except
+ * it does **not** alter the `this` binding.
+ *
+ * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
+ *
+ * var sayHelloTo = _.partial(greet, 'hello');
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ *
+ * // Partially applied with placeholders.
+ * var greetFred = _.partial(greet, _, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ */
+ var partial = rest(function(func, partials) {
+ var holders = replaceHolders(partials, getPlaceholder(partial));
+ return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders);
+ });
+
+ /**
+ * This method is like `_.partial` except that partially applied arguments
+ * are appended to those provided to the new function.
+ *
+ * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method doesn't set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
+ *
+ * var greetFred = _.partialRight(greet, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ *
+ * // Partially applied with placeholders.
+ * var sayHelloTo = _.partialRight(greet, 'hello', _);
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ */
+ var partialRight = rest(function(func, partials) {
+ var holders = replaceHolders(partials, getPlaceholder(partialRight));
+ return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders);
+ });
+
+ /**
+ * Creates a function that invokes `func` with arguments arranged according
+ * to the specified indexes where the argument value at the first index is
+ * provided as the first argument, the argument value at the second index is
+ * provided as the second argument, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to rearrange arguments for.
+ * @param {...(number|number[])} indexes The arranged argument indexes,
+ * specified individually or in arrays.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var rearged = _.rearg(function(a, b, c) {
+ * return [a, b, c];
+ * }, 2, 0, 1);
+ *
+ * rearged('b', 'c', 'a')
+ * // => ['a', 'b', 'c']
+ */
+ var rearg = rest(function(func, indexes) {
+ return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1));
+ });
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * created function and arguments from `start` and beyond provided as an array.
+ *
+ * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters).
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.rest(function(what, names) {
+ * return what + ' ' + _.initial(names).join(', ') +
+ * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
+ * });
+ *
+ * say('hello', 'fred', 'barney', 'pebbles');
+ * // => 'hello fred, barney, & pebbles'
+ */
+ function rest(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ array = Array(length);
+
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ switch (start) {
+ case 0: return func.call(this, array);
+ case 1: return func.call(this, args[0], array);
+ case 2: return func.call(this, args[0], args[1], array);
+ }
+ var otherArgs = Array(start + 1);
+ index = -1;
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = array;
+ return apply(func, this, otherArgs);
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the created
+ * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
+ *
+ * **Note:** This method is based on the [spread operator](https://mdn.io/spread_operator).
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to spread arguments over.
+ * @param {number} [start=0] The start position of the spread.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.spread(function(who, what) {
+ * return who + ' says ' + what;
+ * });
+ *
+ * say(['fred', 'hello']);
+ * // => 'fred says hello'
+ *
+ * var numbers = Promise.all([
+ * Promise.resolve(40),
+ * Promise.resolve(36)
+ * ]);
+ *
+ * numbers.then(_.spread(function(x, y) {
+ * return x + y;
+ * }));
+ * // => a Promise of 76
+ */
+ function spread(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
+ return rest(function(args) {
+ var array = args[start],
+ otherArgs = args.slice(0, start);
+
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
+ }
+
+ /**
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed `func` invocations and a `flush` method to
+ * immediately invoke them. Provide an options object to indicate whether
+ * `func` should be invoked on the leading and/or trailing edge of the `wait`
+ * timeout. The `func` is invoked with the last arguments provided to the
+ * throttled function. Subsequent calls to the throttled function return the
+ * result of the last `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the throttled function is
+ * invoked more than once during the `wait` timeout.
+ *
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.throttle` and `_.debounce`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=true] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // Avoid excessively updating the position while scrolling.
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
+ * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
+ * jQuery(element).on('click', throttled);
+ *
+ * // Cancel the trailing throttled invocation.
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ 'leading': leading,
+ 'maxWait': wait,
+ 'trailing': trailing
+ });
+ }
+
+ /**
+ * Creates a function that accepts up to one argument, ignoring any
+ * additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.unary(parseInt));
+ * // => [6, 8, 10]
+ */
+ function unary(func) {
+ return ary(func, 1);
+ }
+
+ /**
+ * Creates a function that provides `value` to the wrapper function as its
+ * first argument. Any additional arguments provided to the function are
+ * appended to those provided to the wrapper function. The wrapper is invoked
+ * with the `this` binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {*} value The value to wrap.
+ * @param {Function} [wrapper=identity] The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var p = _.wrap(_.escape, function(func, text) {
+ * return '<p>' + func(text) + '</p>';
+ * });
+ *
+ * p('fred, barney, & pebbles');
+ * // => '<p>fred, barney, &amp; pebbles</p>'
+ */
+ function wrap(value, wrapper) {
+ wrapper = wrapper == null ? identity : wrapper;
+ return partial(wrapper, value);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Casts `value` as an array if it's not one.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to inspect.
+ * @returns {Array} Returns the cast array.
+ * @example
+ *
+ * _.castArray(1);
+ * // => [1]
+ *
+ * _.castArray({ 'a': 1 });
+ * // => [{ 'a': 1 }]
+ *
+ * _.castArray('abc');
+ * // => ['abc']
+ *
+ * _.castArray(null);
+ * // => [null]
+ *
+ * _.castArray(undefined);
+ * // => [undefined]
+ *
+ * _.castArray();
+ * // => []
+ *
+ * var array = [1, 2, 3];
+ * console.log(_.castArray(array) === array);
+ * // => true
+ */
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+
+ /**
+ * Creates a shallow clone of `value`.
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
+ * and supports cloning arrays, array buffers, booleans, date objects, maps,
+ * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
+ * arrays. The own enumerable properties of `arguments` objects are cloned
+ * as plain objects. An empty object is returned for uncloneable values such
+ * as error objects, functions, DOM nodes, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @returns {*} Returns the cloned value.
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var shallow = _.clone(objects);
+ * console.log(shallow[0] === objects[0]);
+ * // => true
+ */
+ function clone(value) {
+ return baseClone(value);
+ }
+
+ /**
+ * This method is like `_.clone` except that it accepts `customizer` which
+ * is invoked to produce the cloned value. If `customizer` returns `undefined`
+ * cloning is handled by the method instead. The `customizer` is invoked with
+ * up to four arguments; (value [, index|key, object, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the cloned value.
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(false);
+ * }
+ * }
+ *
+ * var el = _.cloneWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 0
+ */
+ function cloneWith(value, customizer) {
+ return baseClone(value, false, customizer);
+ }
+
+ /**
+ * This method is like `_.clone` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @returns {*} Returns the deep cloned value.
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var deep = _.cloneDeep(objects);
+ * console.log(deep[0] === objects[0]);
+ * // => false
+ */
+ function cloneDeep(value) {
+ return baseClone(value, true);
+ }
+
+ /**
+ * This method is like `_.cloneWith` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @param {Function} [customizer] The function to customize cloning.
+ * @returns {*} Returns the deep cloned value.
+ * @example
+ *
+ * function customizer(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(true);
+ * }
+ * }
+ *
+ * var el = _.cloneDeepWith(document.body, customizer);
+ *
+ * console.log(el === document.body);
+ * // => false
+ * console.log(el.nodeName);
+ * // => 'BODY'
+ * console.log(el.childNodes.length);
+ * // => 20
+ */
+ function cloneDeepWith(value, customizer) {
+ return baseClone(value, true, customizer);
+ }
+
+ /**
+ * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * comparison between two values to determine if they are equivalent.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'fred' };
+ *
+ * _.eq(object, object);
+ * // => true
+ *
+ * _.eq(object, other);
+ * // => false
+ *
+ * _.eq('a', 'a');
+ * // => true
+ *
+ * _.eq('a', Object('a'));
+ * // => false
+ *
+ * _.eq(NaN, NaN);
+ * // => true
+ */
+ function eq(value, other) {
+ return value === other || (value !== value && other !== other);
+ }
+
+ /**
+ * Checks if `value` is greater than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.
+ * @example
+ *
+ * _.gt(3, 1);
+ * // => true
+ *
+ * _.gt(3, 3);
+ * // => false
+ *
+ * _.gt(1, 3);
+ * // => false
+ */
+ function gt(value, other) {
+ return value > other;
+ }
+
+ /**
+ * Checks if `value` is greater than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`.
+ * @example
+ *
+ * _.gte(3, 1);
+ * // => true
+ *
+ * _.gte(3, 3);
+ * // => true
+ *
+ * _.gte(1, 3);
+ * // => false
+ */
+ function gte(value, other) {
+ return value >= other;
+ }
+
+ /**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
+ return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
+ (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
+ }
+
+ /**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @type {Function}
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+ var isArray = Array.isArray;
+
+ /**
+ * Checks if `value` is classified as an `ArrayBuffer` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArrayBuffer(new ArrayBuffer(2));
+ * // => true
+ *
+ * _.isArrayBuffer(new Array(2));
+ * // => false
+ */
+ function isArrayBuffer(value) {
+ return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
+ }
+
+ /**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+ function isArrayLike(value) {
+ return value != null &&
+ !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
+ }
+
+ /**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+ function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a boolean primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isBoolean(false);
+ * // => true
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false ||
+ (isObjectLike(value) && objectToString.call(value) == boolTag);
+ }
+
+ /**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+ var isBuffer = !Buffer ? constant(false) : function(value) {
+ return value instanceof Buffer;
+ };
+
+ /**
+ * Checks if `value` is classified as a `Date` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ *
+ * _.isDate('Mon April 23 2012');
+ * // => false
+ */
+ function isDate(value) {
+ return isObjectLike(value) && objectToString.call(value) == dateTag;
+ }
+
+ /**
+ * Checks if `value` is likely a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ *
+ * _.isElement('<body>');
+ * // => false
+ */
+ function isElement(value) {
+ return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
+ }
+
+ /**
+ * Checks if `value` is empty. A value is considered empty unless it's an
+ * `arguments` object, array, string, or jQuery-like collection with a length
+ * greater than `0` or an object with own enumerable properties.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {Array|Object|string} value The value to inspect.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty(null);
+ * // => true
+ *
+ * _.isEmpty(true);
+ * // => true
+ *
+ * _.isEmpty(1);
+ * // => true
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
+ */
+ function isEmpty(value) {
+ if (isArrayLike(value) &&
+ (isArray(value) || isString(value) ||
+ isFunction(value.splice) || isArguments(value))) {
+ return !value.length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent.
+ *
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
+ * date objects, error objects, maps, numbers, `Object` objects, regexes,
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
+ * by their own, not inherited, enumerable properties. Functions and DOM
+ * nodes are **not** supported.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'fred' };
+ *
+ * _.isEqual(object, other);
+ * // => true
+ *
+ * object === other;
+ * // => false
+ */
+ function isEqual(value, other) {
+ return baseIsEqual(value, other);
+ }
+
+ /**
+ * This method is like `_.isEqual` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined` comparisons
+ * are handled by the method instead. The `customizer` is invoked with up to
+ * six arguments: (objValue, othValue [, index|key, object, other, stack]).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, othValue) {
+ * if (isGreeting(objValue) && isGreeting(othValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var array = ['hello', 'goodbye'];
+ * var other = ['hi', 'goodbye'];
+ *
+ * _.isEqualWith(array, other, customizer);
+ * // => true
+ */
+ function isEqualWith(value, other, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ var result = customizer ? customizer(value, other) : undefined;
+ return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
+ }
+
+ /**
+ * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+ * `SyntaxError`, `TypeError`, or `URIError` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
+ * @example
+ *
+ * _.isError(new Error);
+ * // => true
+ *
+ * _.isError(Error);
+ * // => false
+ */
+ function isError(value) {
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ return (objectToString.call(value) == errorTag) ||
+ (typeof value.message == 'string' && typeof value.name == 'string');
+ }
+
+ /**
+ * Checks if `value` is a finite primitive number.
+ *
+ * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(3);
+ * // => true
+ *
+ * _.isFinite(Number.MAX_VALUE);
+ * // => true
+ *
+ * _.isFinite(3.14);
+ * // => true
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ */
+ function isFinite(value) {
+ return typeof value == 'number' && nativeIsFinite(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+ function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 8 which returns 'object' for typed array constructors, and
+ // PhantomJS 1.9 which returns 'function' for `NodeList` instances.
+ var tag = isObject(value) ? objectToString.call(value) : '';
+ return tag == funcTag || tag == genTag;
+ }
+
+ /**
+ * Checks if `value` is an integer.
+ *
+ * **Note:** This method is based on [`Number.isInteger`](https://mdn.io/Number/isInteger).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
+ * @example
+ *
+ * _.isInteger(3);
+ * // => true
+ *
+ * _.isInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isInteger(Infinity);
+ * // => false
+ *
+ * _.isInteger('3');
+ * // => false
+ */
+ function isInteger(value) {
+ return typeof value == 'number' && value == toInteger(value);
+ }
+
+ /**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+ function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+ function isObject(value) {
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+ }
+
+ /**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+ function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+ }
+
+ /**
+ * Checks if `value` is classified as a `Map` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isMap(new Map);
+ * // => true
+ *
+ * _.isMap(new WeakMap);
+ * // => false
+ */
+ function isMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+
+ /**
+ * Performs a partial deep comparison between `object` and `source` to
+ * determine if `object` contains equivalent property values. This method is
+ * equivalent to a `_.matches` function when `source` is partially applied.
+ *
+ * **Note:** This method supports comparing the same values as `_.isEqual`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * var object = { 'user': 'fred', 'age': 40 };
+ *
+ * _.isMatch(object, { 'age': 40 });
+ * // => true
+ *
+ * _.isMatch(object, { 'age': 36 });
+ * // => false
+ */
+ function isMatch(object, source) {
+ return object === source || baseIsMatch(object, source, getMatchData(source));
+ }
+
+ /**
+ * This method is like `_.isMatch` except that it accepts `customizer` which
+ * is invoked to compare values. If `customizer` returns `undefined` comparisons
+ * are handled by the method instead. The `customizer` is invoked with five
+ * arguments: (objValue, srcValue, index|key, object, source).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * function isGreeting(value) {
+ * return /^h(?:i|ello)$/.test(value);
+ * }
+ *
+ * function customizer(objValue, srcValue) {
+ * if (isGreeting(objValue) && isGreeting(srcValue)) {
+ * return true;
+ * }
+ * }
+ *
+ * var object = { 'greeting': 'hello' };
+ * var source = { 'greeting': 'hi' };
+ *
+ * _.isMatchWith(object, source, customizer);
+ * // => true
+ */
+ function isMatchWith(object, source, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return baseIsMatch(object, source, getMatchData(source), customizer);
+ }
+
+ /**
+ * Checks if `value` is `NaN`.
+ *
+ * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
+ * which returns `true` for `undefined` and other non-numeric values.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * _.isNaN(new Number(NaN));
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // An `NaN` primitive is the only value that is not equal to itself.
+ // Perform the `toStringTag` check first to avoid errors with some ActiveX objects in IE.
+ return isNumber(value) && value != +value;
+ }
+
+ /**
+ * Checks if `value` is a native function.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+ function isNative(value) {
+ if (value == null) {
+ return false;
+ }
+ if (isFunction(value)) {
+ return reIsNative.test(funcToString.call(value));
+ }
+ return isObjectLike(value) &&
+ (isHostObject(value) ? reIsNative : reIsHostCtor).test(value);
+ }
+
+ /**
+ * Checks if `value` is `null`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(void 0);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if `value` is `null` or `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
+ * @example
+ *
+ * _.isNil(null);
+ * // => true
+ *
+ * _.isNil(void 0);
+ * // => true
+ *
+ * _.isNil(NaN);
+ * // => false
+ */
+ function isNil(value) {
+ return value == null;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Number` primitive or object.
+ *
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+ * as numbers, use the `_.isFinite` method.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isNumber(3);
+ * // => true
+ *
+ * _.isNumber(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isNumber(Infinity);
+ * // => true
+ *
+ * _.isNumber('3');
+ * // => false
+ */
+ function isNumber(value) {
+ return typeof value == 'number' ||
+ (isObjectLike(value) && objectToString.call(value) == numberTag);
+ }
+
+ /**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+ function isPlainObject(value) {
+ if (!isObjectLike(value) ||
+ objectToString.call(value) != objectTag || isHostObject(value)) {
+ return false;
+ }
+ var proto = getPrototypeOf(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = proto.constructor;
+ return (typeof Ctor == 'function' &&
+ Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
+ }
+
+ /**
+ * Checks if `value` is classified as a `RegExp` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isRegExp(/abc/);
+ * // => true
+ *
+ * _.isRegExp('/abc/');
+ * // => false
+ */
+ function isRegExp(value) {
+ return isObject(value) && objectToString.call(value) == regexpTag;
+ }
+
+ /**
+ * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
+ * double precision number which isn't the result of a rounded unsafe integer.
+ *
+ * **Note:** This method is based on [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
+ * @example
+ *
+ * _.isSafeInteger(3);
+ * // => true
+ *
+ * _.isSafeInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isSafeInteger(Infinity);
+ * // => false
+ *
+ * _.isSafeInteger('3');
+ * // => false
+ */
+ function isSafeInteger(value) {
+ return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isSet(new Set);
+ * // => true
+ *
+ * _.isSet(new WeakSet);
+ * // => false
+ */
+ function isSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+ function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+ function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+ function isTypedArray(value) {
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
+ }
+
+ /**
+ * Checks if `value` is `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ *
+ * _.isUndefined(null);
+ * // => false
+ */
+ function isUndefined(value) {
+ return value === undefined;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakMap` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isWeakMap(new WeakMap);
+ * // => true
+ *
+ * _.isWeakMap(new Map);
+ * // => false
+ */
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `WeakSet` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isWeakSet(new WeakSet);
+ * // => true
+ *
+ * _.isWeakSet(new Set);
+ * // => false
+ */
+ function isWeakSet(value) {
+ return isObjectLike(value) && objectToString.call(value) == weakSetTag;
+ }
+
+ /**
+ * Checks if `value` is less than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
+ * @example
+ *
+ * _.lt(1, 3);
+ * // => true
+ *
+ * _.lt(3, 3);
+ * // => false
+ *
+ * _.lt(3, 1);
+ * // => false
+ */
+ function lt(value, other) {
+ return value < other;
+ }
+
+ /**
+ * Checks if `value` is less than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`.
+ * @example
+ *
+ * _.lte(1, 3);
+ * // => true
+ *
+ * _.lte(3, 3);
+ * // => true
+ *
+ * _.lte(3, 1);
+ * // => false
+ */
+ function lte(value, other) {
+ return value <= other;
+ }
+
+ /**
+ * Converts `value` to an array.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the converted array.
+ * @example
+ *
+ * _.toArray({ 'a': 1, 'b': 2 });
+ * // => [1, 2]
+ *
+ * _.toArray('abc');
+ * // => ['a', 'b', 'c']
+ *
+ * _.toArray(1);
+ * // => []
+ *
+ * _.toArray(null);
+ * // => []
+ */
+ function toArray(value) {
+ if (!value) {
+ return [];
+ }
+ if (isArrayLike(value)) {
+ return isString(value) ? stringToArray(value) : copyArray(value);
+ }
+ if (iteratorSymbol && value[iteratorSymbol]) {
+ return iteratorToArray(value[iteratorSymbol]());
+ }
+ var tag = getTag(value),
+ func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
+
+ return func(value);
+ }
+
+ /**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3');
+ * // => 3
+ */
+ function toInteger(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ var remainder = value % 1;
+ return value === value ? (remainder ? value - remainder : value) : 0;
+ }
+
+ /**
+ * Converts `value` to an integer suitable for use as the length of an
+ * array-like object.
+ *
+ * **Note:** This method is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toLength(3);
+ * // => 3
+ *
+ * _.toLength(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toLength(Infinity);
+ * // => 4294967295
+ *
+ * _.toLength('3');
+ * // => 3
+ */
+ function toLength(value) {
+ return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
+ }
+
+ /**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3);
+ * // => 3
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3');
+ * // => 3
+ */
+ function toNumber(value) {
+ if (isObject(value)) {
+ var other = isFunction(value.valueOf) ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+ }
+
+ /**
+ * Converts `value` to a plain object flattening inherited enumerable
+ * properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+ function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+ }
+
+ /**
+ * Converts `value` to a safe integer. A safe integer can be compared and
+ * represented correctly.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toSafeInteger(3);
+ * // => 3
+ *
+ * _.toSafeInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toSafeInteger(Infinity);
+ * // => 9007199254740991
+ *
+ * _.toSafeInteger('3');
+ * // => 3
+ */
+ function toSafeInteger(value) {
+ return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
+ }
+
+ /**
+ * Converts `value` to a string if it's not one. An empty string is returned
+ * for `null` and `undefined` values. The sign of `-0` is preserved.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ * @example
+ *
+ * _.toString(null);
+ * // => ''
+ *
+ * _.toString(-0);
+ * // => '-0'
+ *
+ * _.toString([1, 2, 3]);
+ * // => '1,2,3'
+ */
+ function toString(value) {
+ // Exit early for strings to avoid a performance hit in some environments.
+ if (typeof value == 'string') {
+ return value;
+ }
+ if (value == null) {
+ return '';
+ }
+ if (isSymbol(value)) {
+ return Symbol ? symbolToString.call(value) : '';
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Assigns own enumerable properties of source objects to the destination
+ * object. Source objects are applied from left to right. Subsequent sources
+ * overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object` and is loosely based on
+ * [`Object.assign`](https://mdn.io/Object/assign).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.c = 3;
+ * }
+ *
+ * function Bar() {
+ * this.e = 5;
+ * }
+ *
+ * Foo.prototype.d = 4;
+ * Bar.prototype.f = 6;
+ *
+ * _.assign({ 'a': 1 }, new Foo, new Bar);
+ * // => { 'a': 1, 'c': 3, 'e': 5 }
+ */
+ var assign = createAssigner(function(object, source) {
+ copyObject(source, keys(source), object);
+ });
+
+ /**
+ * This method is like `_.assign` except that it iterates over own and
+ * inherited source properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @alias extend
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * function Bar() {
+ * this.d = 4;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ * Bar.prototype.e = 5;
+ *
+ * _.assignIn({ 'a': 1 }, new Foo, new Bar);
+ * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 }
+ */
+ var assignIn = createAssigner(function(object, source) {
+ copyObject(source, keysIn(source), object);
+ });
+
+ /**
+ * This method is like `_.assignIn` except that it accepts `customizer` which
+ * is invoked to produce the assigned values. If `customizer` returns `undefined`
+ * assignment is handled by the method instead. The `customizer` is invoked
+ * with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @alias extendWith
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignInWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObjectWith(source, keysIn(source), object, customizer);
+ });
+
+ /**
+ * This method is like `_.assign` except that it accepts `customizer` which
+ * is invoked to produce the assigned values. If `customizer` returns `undefined`
+ * assignment is handled by the method instead. The `customizer` is invoked
+ * with five arguments: (objValue, srcValue, key, object, source).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * return _.isUndefined(objValue) ? srcValue : objValue;
+ * }
+ *
+ * var defaults = _.partialRight(_.assignWith, customizer);
+ *
+ * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+ var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObjectWith(source, keys(source), object, customizer);
+ });
+
+ /**
+ * Creates an array of values corresponding to `paths` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {...(string|string[])} [paths] The property paths of elements to pick,
+ * specified individually or in arrays.
+ * @returns {Array} Returns the new array of picked elements.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
+ *
+ * _.at(object, ['a[0].b.c', 'a[1]']);
+ * // => [3, 4]
+ *
+ * _.at(['a', 'b', 'c'], 0, 2);
+ * // => ['a', 'c']
+ */
+ var at = rest(function(object, paths) {
+ return baseAt(object, baseFlatten(paths, 1));
+ });
+
+ /**
+ * Creates an object that inherits from the `prototype` object. If a `properties`
+ * object is given its own enumerable properties are assigned to the created object.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} prototype The object to inherit from.
+ * @param {Object} [properties] The properties to assign to the object.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
+ *
+ * function Circle() {
+ * Shape.call(this);
+ * }
+ *
+ * Circle.prototype = _.create(Shape.prototype, {
+ * 'constructor': Circle
+ * });
+ *
+ * var circle = new Circle;
+ * circle instanceof Circle;
+ * // => true
+ *
+ * circle instanceof Shape;
+ * // => true
+ */
+ function create(prototype, properties) {
+ var result = baseCreate(prototype);
+ return properties ? baseAssign(result, properties) : result;
+ }
+
+ /**
+ * Assigns own and inherited enumerable properties of source objects to the
+ * destination object for all destination properties that resolve to `undefined`.
+ * Source objects are applied from left to right. Once a property is set,
+ * additional values of the same property are ignored.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+ * // => { 'user': 'barney', 'age': 36 }
+ */
+ var defaults = rest(function(args) {
+ args.push(undefined, assignInDefaults);
+ return apply(assignInWith, undefined, args);
+ });
+
+ /**
+ * This method is like `_.defaults` except that it recursively assigns
+ * default properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
+ * // => { 'user': { 'name': 'barney', 'age': 36 } }
+ *
+ */
+ var defaultsDeep = rest(function(args) {
+ args.push(undefined, mergeDefaults);
+ return apply(mergeWith, undefined, args);
+ });
+
+ /**
+ * This method is like `_.find` except that it returns the key of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findKey(users, function(o) { return o.age < 40; });
+ * // => 'barney' (iteration order is not guaranteed)
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findKey(users, { 'age': 1, 'active': true });
+ * // => 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findKey(users, 'active');
+ * // => 'barney'
+ */
+ function findKey(object, predicate) {
+ return baseFind(object, getIteratee(predicate, 3), baseForOwn, true);
+ }
+
+ /**
+ * This method is like `_.findKey` except that it iterates over elements of
+ * a collection in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findLastKey(users, function(o) { return o.age < 40; });
+ * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findLastKey(users, { 'age': 36, 'active': true });
+ * // => 'barney'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findLastKey(users, ['active', false]);
+ * // => 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findLastKey(users, 'active');
+ * // => 'pebbles'
+ */
+ function findLastKey(object, predicate) {
+ return baseFind(object, getIteratee(predicate, 3), baseForOwnRight, true);
+ }
+
+ /**
+ * Iterates over own and inherited enumerable properties of an object invoking
+ * `iteratee` for each property. The iteratee is invoked with three arguments:
+ * (value, key, object). Iteratee functions may exit iteration early by explicitly
+ * returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a', 'b', then 'c' (iteration order is not guaranteed)
+ */
+ function forIn(object, iteratee) {
+ return object == null
+ ? object
+ : baseFor(object, baseCastFunction(iteratee), keysIn);
+ }
+
+ /**
+ * This method is like `_.forIn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forInRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'
+ */
+ function forInRight(object, iteratee) {
+ return object == null
+ ? object
+ : baseForRight(object, baseCastFunction(iteratee), keysIn);
+ }
+
+ /**
+ * Iterates over own enumerable properties of an object invoking `iteratee`
+ * for each property. The iteratee is invoked with three arguments:
+ * (value, key, object). Iteratee functions may exit iteration early by
+ * explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a' then 'b' (iteration order is not guaranteed)
+ */
+ function forOwn(object, iteratee) {
+ return object && baseForOwn(object, baseCastFunction(iteratee));
+ }
+
+ /**
+ * This method is like `_.forOwn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwnRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'
+ */
+ function forOwnRight(object, iteratee) {
+ return object && baseForOwnRight(object, baseCastFunction(iteratee));
+ }
+
+ /**
+ * Creates an array of function property names from own enumerable properties
+ * of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the new array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functions(new Foo);
+ * // => ['a', 'b']
+ */
+ function functions(object) {
+ return object == null ? [] : baseFunctions(object, keys(object));
+ }
+
+ /**
+ * Creates an array of function property names from own and inherited
+ * enumerable properties of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the new array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = _.constant('a');
+ * this.b = _.constant('b');
+ * }
+ *
+ * Foo.prototype.c = _.constant('c');
+ *
+ * _.functionsIn(new Foo);
+ * // => ['a', 'b', 'c']
+ */
+ function functionsIn(object) {
+ return object == null ? [] : baseFunctions(object, keysIn(object));
+ }
+
+ /**
+ * Gets the value at `path` of `object`. If the resolved value is
+ * `undefined` the `defaultValue` is used in its place.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.get(object, 'a[0].b.c');
+ * // => 3
+ *
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
+ *
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
+ */
+ function get(object, path, defaultValue) {
+ var result = object == null ? undefined : baseGet(object, path);
+ return result === undefined ? defaultValue : result;
+ }
+
+ /**
+ * Checks if `path` is a direct property of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = { 'a': { 'b': { 'c': 3 } } };
+ * var other = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) });
+ *
+ * _.has(object, 'a');
+ * // => true
+ *
+ * _.has(object, 'a.b.c');
+ * // => true
+ *
+ * _.has(object, ['a', 'b', 'c']);
+ * // => true
+ *
+ * _.has(other, 'a');
+ * // => false
+ */
+ function has(object, path) {
+ return hasPath(object, path, baseHas);
+ }
+
+ /**
+ * Checks if `path` is a direct or inherited property of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) });
+ *
+ * _.hasIn(object, 'a');
+ * // => true
+ *
+ * _.hasIn(object, 'a.b.c');
+ * // => true
+ *
+ * _.hasIn(object, ['a', 'b', 'c']);
+ * // => true
+ *
+ * _.hasIn(object, 'b');
+ * // => false
+ */
+ function hasIn(object, path) {
+ return hasPath(object, path, baseHasIn);
+ }
+
+ /**
+ * Creates an object composed of the inverted keys and values of `object`.
+ * If `object` contains duplicate values, subsequent values overwrite property
+ * assignments of previous values.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invert(object);
+ * // => { '1': 'c', '2': 'b' }
+ */
+ var invert = createInverter(function(result, value, key) {
+ result[value] = key;
+ }, constant(identity));
+
+ /**
+ * This method is like `_.invert` except that the inverted object is generated
+ * from the results of running each element of `object` through `iteratee`.
+ * The corresponding inverted value of each inverted key is an array of keys
+ * responsible for generating the inverted value. The iteratee is invoked
+ * with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invertBy(object);
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ *
+ * _.invertBy(object, function(value) {
+ * return 'group' + value;
+ * });
+ * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
+ */
+ var invertBy = createInverter(function(result, value, key) {
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }, getIteratee);
+
+ /**
+ * Invokes the method at `path` of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
+ *
+ * _.invoke(object, 'a[0].b.c.slice', 1, 3);
+ * // => [2, 3]
+ */
+ var invoke = rest(baseInvoke);
+
+ /**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+ function keys(object) {
+ var isProto = isPrototype(object);
+ if (!(isProto || isArrayLike(object))) {
+ return baseKeys(object);
+ }
+ var indexes = indexKeys(object),
+ skipIndexes = !!indexes,
+ result = indexes || [],
+ length = result.length;
+
+ for (var key in object) {
+ if (baseHas(object, key) &&
+ !(skipIndexes && (key == 'length' || isIndex(key, length))) &&
+ !(isProto && key == 'constructor')) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+ function keysIn(object) {
+ var index = -1,
+ isProto = isPrototype(object),
+ props = baseKeysIn(object),
+ propsLength = props.length,
+ indexes = indexKeys(object),
+ skipIndexes = !!indexes,
+ result = indexes || [],
+ length = result.length;
+
+ while (++index < propsLength) {
+ var key = props[index];
+ if (!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
+ !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The opposite of `_.mapValues`; this method creates an object with the
+ * same values as `object` and keys generated by running each own enumerable
+ * property of `object` through `iteratee`. The iteratee is invoked with
+ * three arguments: (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @example
+ *
+ * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
+ * return key + value;
+ * });
+ * // => { 'a1': 1, 'b2': 2 }
+ */
+ function mapKeys(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ result[iteratee(value, key, object)] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Creates an object with the same keys as `object` and values generated by
+ * running each own enumerable property of `object` through `iteratee`. The
+ * iteratee is invoked with three arguments: (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @example
+ *
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
+ *
+ * _.mapValues(users, function(o) { return o.age; });
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ */
+ function mapValues(object, iteratee) {
+ var result = {};
+ iteratee = getIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ result[key] = iteratee(value, key, object);
+ });
+ return result;
+ }
+
+ /**
+ * Recursively merges own and inherited enumerable properties of source objects
+ * into the destination object. Source properties that resolve to `undefined`
+ * are skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var users = {
+ * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
+ * };
+ *
+ * var ages = {
+ * 'data': [{ 'age': 36 }, { 'age': 40 }]
+ * };
+ *
+ * _.merge(users, ages);
+ * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
+ */
+ var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+ });
+
+ /**
+ * This method is like `_.merge` except that it accepts `customizer` which
+ * is invoked to produce the merged values of the destination and source
+ * properties. If `customizer` returns `undefined` merging is handled by the
+ * method instead. The `customizer` is invoked with seven arguments:
+ * (objValue, srcValue, key, object, source, stack).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} sources The source objects.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function customizer(objValue, srcValue) {
+ * if (_.isArray(objValue)) {
+ * return objValue.concat(srcValue);
+ * }
+ * }
+ *
+ * var object = {
+ * 'fruits': ['apple'],
+ * 'vegetables': ['beet']
+ * };
+ *
+ * var other = {
+ * 'fruits': ['banana'],
+ * 'vegetables': ['carrot']
+ * };
+ *
+ * _.mergeWith(object, other, customizer);
+ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
+ */
+ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
+ baseMerge(object, source, srcIndex, customizer);
+ });
+
+ /**
+ * The opposite of `_.pick`; this method creates an object composed of the
+ * own and inherited enumerable properties of `object` that are not omitted.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [props] The property names to omit, specified
+ * individually or in arrays.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omit(object, ['a', 'c']);
+ * // => { 'b': '2' }
+ */
+ var omit = rest(function(object, props) {
+ if (object == null) {
+ return {};
+ }
+ props = arrayMap(baseFlatten(props, 1), String);
+ return basePick(object, baseDifference(keysIn(object), props));
+ });
+
+ /**
+ * The opposite of `_.pickBy`; this method creates an object composed of
+ * the own and inherited enumerable properties of `object` that `predicate`
+ * doesn't return truthy for. The predicate is invoked with two arguments:
+ * (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.omitBy(object, _.isNumber);
+ * // => { 'b': '2' }
+ */
+ function omitBy(object, predicate) {
+ predicate = getIteratee(predicate);
+ return basePickBy(object, function(value, key) {
+ return !predicate(value, key);
+ });
+ }
+
+ /**
+ * Creates an object composed of the picked `object` properties.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [props] The property names to pick, specified
+ * individually or in arrays.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pick(object, ['a', 'c']);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ var pick = rest(function(object, props) {
+ return object == null ? {} : basePick(object, baseFlatten(props, 1));
+ });
+
+ /**
+ * Creates an object composed of the `object` properties `predicate` returns
+ * truthy for. The predicate is invoked with two arguments: (value, key).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked per property.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pickBy(object, _.isNumber);
+ * // => { 'a': 1, 'c': 3 }
+ */
+ function pickBy(object, predicate) {
+ return object == null ? {} : basePickBy(object, getIteratee(predicate));
+ }
+
+ /**
+ * This method is like `_.get` except that if the resolved value is a function
+ * it's invoked with the `this` binding of its parent object and its result
+ * is returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to resolve.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+ *
+ * _.result(object, 'a[0].b.c1');
+ * // => 3
+ *
+ * _.result(object, 'a[0].b.c2');
+ * // => 4
+ *
+ * _.result(object, 'a[0].b.c3', 'default');
+ * // => 'default'
+ *
+ * _.result(object, 'a[0].b.c3', _.constant('default'));
+ * // => 'default'
+ */
+ function result(object, path, defaultValue) {
+ if (!isKey(path, object)) {
+ path = baseCastPath(path);
+ var result = get(object, path);
+ object = parent(object, path);
+ } else {
+ result = object == null ? undefined : object[path];
+ }
+ if (result === undefined) {
+ result = defaultValue;
+ }
+ return isFunction(result) ? result.call(object) : result;
+ }
+
+ /**
+ * Sets the value at `path` of `object`. If a portion of `path` doesn't exist
+ * it's created. Arrays are created for missing index properties while objects
+ * are created for all other missing properties. Use `_.setWith` to customize
+ * `path` creation.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
+ *
+ * _.set(object, 'x[0].y.z', 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
+ */
+ function set(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+ }
+
+ /**
+ * This method is like `_.set` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.setWith({ '0': { 'length': 2 } }, '[0][1][2]', 3, Object);
+ * // => { '0': { '1': { '2': 3 }, 'length': 2 } }
+ */
+ function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return object == null ? object : baseSet(object, path, value, customizer);
+ }
+
+ /**
+ * Creates an array of own enumerable key-value pairs for `object` which
+ * can be consumed by `_.fromPairs`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the new array of key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairs(new Foo);
+ * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
+ */
+ function toPairs(object) {
+ return baseToPairs(object, keys(object));
+ }
+
+ /**
+ * Creates an array of own and inherited enumerable key-value pairs for
+ * `object` which can be consumed by `_.fromPairs`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the new array of key-value pairs.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.toPairsIn(new Foo);
+ * // => [['a', 1], ['b', 2], ['c', 1]] (iteration order is not guaranteed)
+ */
+ function toPairsIn(object) {
+ return baseToPairs(object, keysIn(object));
+ }
+
+ /**
+ * An alternative to `_.reduce`; this method transforms `object` to a new
+ * `accumulator` object which is the result of running each of its own enumerable
+ * properties through `iteratee`, with each invocation potentially mutating
+ * the `accumulator` object. The iteratee is invoked with four arguments:
+ * (accumulator, value, key, object). Iteratee functions may exit iteration
+ * early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The custom accumulator value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.transform([2, 3, 4], function(result, n) {
+ * result.push(n *= n);
+ * return n % 2 == 0;
+ * }, []);
+ * // => [4, 9]
+ *
+ * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ */
+ function transform(object, iteratee, accumulator) {
+ var isArr = isArray(object) || isTypedArray(object);
+ iteratee = getIteratee(iteratee, 4);
+
+ if (accumulator == null) {
+ if (isArr || isObject(object)) {
+ var Ctor = object.constructor;
+ if (isArr) {
+ accumulator = isArray(object) ? new Ctor : [];
+ } else {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototypeOf(object)) : {};
+ }
+ } else {
+ accumulator = {};
+ }
+ }
+ (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ return iteratee(accumulator, value, index, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Removes the property at `path` of `object`.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to unset.
+ * @returns {boolean} Returns `true` if the property is deleted, else `false`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 7 } }] };
+ * _.unset(object, 'a[0].b.c');
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ *
+ * _.unset(object, 'a[0].b.c');
+ * // => true
+ *
+ * console.log(object);
+ * // => { 'a': [{ 'b': {} }] };
+ */
+ function unset(object, path) {
+ return object == null ? true : baseUnset(object, path);
+ }
+
+ /**
+ * Creates an array of the own enumerable property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+ function values(object) {
+ return object ? baseValues(object, keys(object)) : [];
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.valuesIn(new Foo);
+ * // => [1, 2, 3] (iteration order is not guaranteed)
+ */
+ function valuesIn(object) {
+ return object == null ? [] : baseValues(object, keysIn(object));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Clamps `number` within the inclusive `lower` and `upper` bounds.
+ *
+ * @static
+ * @memberOf _
+ * @category Number
+ * @param {number} number The number to clamp.
+ * @param {number} [lower] The lower bound.
+ * @param {number} upper The upper bound.
+ * @returns {number} Returns the clamped number.
+ * @example
+ *
+ * _.clamp(-10, -5, 5);
+ * // => -5
+ *
+ * _.clamp(10, -5, 5);
+ * // => 5
+ */
+ function clamp(number, lower, upper) {
+ if (upper === undefined) {
+ upper = lower;
+ lower = undefined;
+ }
+ if (upper !== undefined) {
+ upper = toNumber(upper);
+ upper = upper === upper ? upper : 0;
+ }
+ if (lower !== undefined) {
+ lower = toNumber(lower);
+ lower = lower === lower ? lower : 0;
+ }
+ return baseClamp(toNumber(number), lower, upper);
+ }
+
+ /**
+ * Checks if `n` is between `start` and up to but not including, `end`. If
+ * `end` is not specified it's set to `start` with `start` then set to `0`.
+ * If `start` is greater than `end` the params are swapped to support
+ * negative ranges.
+ *
+ * @static
+ * @memberOf _
+ * @category Number
+ * @param {number} number The number to check.
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
+ * @example
+ *
+ * _.inRange(3, 2, 4);
+ * // => true
+ *
+ * _.inRange(4, 8);
+ * // => true
+ *
+ * _.inRange(4, 2);
+ * // => false
+ *
+ * _.inRange(2, 2);
+ * // => false
+ *
+ * _.inRange(1.2, 2);
+ * // => true
+ *
+ * _.inRange(5.2, 4);
+ * // => false
+ *
+ * _.inRange(-3, -2, -6);
+ * // => true
+ */
+ function inRange(number, start, end) {
+ start = toNumber(start) || 0;
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = toNumber(end) || 0;
+ }
+ number = toNumber(number);
+ return baseInRange(number, start, end);
+ }
+
+ /**
+ * Produces a random number between the inclusive `lower` and `upper` bounds.
+ * If only one argument is provided a number between `0` and the given number
+ * is returned. If `floating` is `true`, or either `lower` or `upper` are floats,
+ * a floating-point number is returned instead of an integer.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @memberOf _
+ * @category Number
+ * @param {number} [lower=0] The lower bound.
+ * @param {number} [upper=1] The upper bound.
+ * @param {boolean} [floating] Specify returning a floating-point number.
+ * @returns {number} Returns the random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => an integer between 0 and 5
+ *
+ * _.random(5);
+ * // => also an integer between 0 and 5
+ *
+ * _.random(5, true);
+ * // => a floating-point number between 0 and 5
+ *
+ * _.random(1.2, 5.2);
+ * // => a floating-point number between 1.2 and 5.2
+ */
+ function random(lower, upper, floating) {
+ if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
+ upper = floating = undefined;
+ }
+ if (floating === undefined) {
+ if (typeof upper == 'boolean') {
+ floating = upper;
+ upper = undefined;
+ }
+ else if (typeof lower == 'boolean') {
+ floating = lower;
+ lower = undefined;
+ }
+ }
+ if (lower === undefined && upper === undefined) {
+ lower = 0;
+ upper = 1;
+ }
+ else {
+ lower = toNumber(lower) || 0;
+ if (upper === undefined) {
+ upper = lower;
+ lower = 0;
+ } else {
+ upper = toNumber(upper) || 0;
+ }
+ }
+ if (lower > upper) {
+ var temp = lower;
+ lower = upper;
+ upper = temp;
+ }
+ if (floating || lower % 1 || upper % 1) {
+ var rand = nativeRandom();
+ return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
+ }
+ return baseRandom(lower, upper);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the camel cased string.
+ * @example
+ *
+ * _.camelCase('Foo Bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('--foo-bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('__foo_bar__');
+ * // => 'fooBar'
+ */
+ var camelCase = createCompounder(function(result, word, index) {
+ word = word.toLowerCase();
+ return result + (index ? capitalize(word) : word);
+ });
+
+ /**
+ * Converts the first character of `string` to upper case and the remaining
+ * to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to capitalize.
+ * @returns {string} Returns the capitalized string.
+ * @example
+ *
+ * _.capitalize('FRED');
+ * // => 'Fred'
+ */
+ function capitalize(string) {
+ return upperFirst(toString(string).toLowerCase());
+ }
+
+ /**
+ * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+ * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to deburr.
+ * @returns {string} Returns the deburred string.
+ * @example
+ *
+ * _.deburr('déjà vu');
+ * // => 'deja vu'
+ */
+ function deburr(string) {
+ string = toString(string);
+ return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
+ }
+
+ /**
+ * Checks if `string` ends with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to search.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=string.length] The position to search from.
+ * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.
+ * @example
+ *
+ * _.endsWith('abc', 'c');
+ * // => true
+ *
+ * _.endsWith('abc', 'b');
+ * // => false
+ *
+ * _.endsWith('abc', 'b', 2);
+ * // => true
+ */
+ function endsWith(string, target, position) {
+ string = toString(string);
+ target = typeof target == 'string' ? target : (target + '');
+
+ var length = string.length;
+ position = position === undefined
+ ? length
+ : baseClamp(toInteger(position), 0, length);
+
+ position -= target.length;
+ return position >= 0 && string.indexOf(target, position) == position;
+ }
+
+ /**
+ * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to
+ * their corresponding HTML entities.
+ *
+ * **Note:** No other characters are escaped. To escape additional
+ * characters use a third-party library like [_he_](https://mths.be/he).
+ *
+ * Though the ">" character is escaped for symmetry, characters like
+ * ">" and "/" don't need escaping in HTML and have no special meaning
+ * unless they're part of a tag or unquoted attribute value.
+ * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+ * (under "semi-related fun fact") for more details.
+ *
+ * Backticks are escaped because in IE < 9, they can break out of
+ * attribute values or HTML comments. See [#59](https://html5sec.org/#59),
+ * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
+ * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
+ * for more details.
+ *
+ * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
+ * to reduce XSS vectors.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escape('fred, barney, & pebbles');
+ * // => 'fred, barney, &amp; pebbles'
+ */
+ function escape(string) {
+ string = toString(string);
+ return (string && reHasUnescapedHtml.test(string))
+ ? string.replace(reUnescapedHtml, escapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
+ * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escapeRegExp('[lodash](https://lodash.com/)');
+ * // => '\[lodash\]\(https://lodash\.com/\)'
+ */
+ function escapeRegExp(string) {
+ string = toString(string);
+ return (string && reHasRegExpChar.test(string))
+ ? string.replace(reRegExpChar, '\\$&')
+ : string;
+ }
+
+ /**
+ * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the kebab cased string.
+ * @example
+ *
+ * _.kebabCase('Foo Bar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('fooBar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('__foo_bar__');
+ * // => 'foo-bar'
+ */
+ var kebabCase = createCompounder(function(result, word, index) {
+ return result + (index ? '-' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts `string`, as space separated words, to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the lower cased string.
+ * @example
+ *
+ * _.lowerCase('--Foo-Bar');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('fooBar');
+ * // => 'foo bar'
+ *
+ * _.lowerCase('__FOO_BAR__');
+ * // => 'foo bar'
+ */
+ var lowerCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts the first character of `string` to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.lowerFirst('Fred');
+ * // => 'fred'
+ *
+ * _.lowerFirst('FRED');
+ * // => 'fRED'
+ */
+ var lowerFirst = createCaseFirst('toLowerCase');
+
+ /**
+ * Converts the first character of `string` to upper case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.upperFirst('fred');
+ * // => 'Fred'
+ *
+ * _.upperFirst('FRED');
+ * // => 'FRED'
+ */
+ var upperFirst = createCaseFirst('toUpperCase');
+
+ /**
+ * Pads `string` on the left and right sides if it's shorter than `length`.
+ * Padding characters are truncated if they can't be evenly divided by `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.pad('abc', 8);
+ * // => ' abc '
+ *
+ * _.pad('abc', 8, '_-');
+ * // => '_-abc_-_'
+ *
+ * _.pad('abc', 3);
+ * // => 'abc'
+ */
+ function pad(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+
+ var strLength = stringSize(string);
+ if (!length || strLength >= length) {
+ return string;
+ }
+ var mid = (length - strLength) / 2,
+ leftLength = nativeFloor(mid),
+ rightLength = nativeCeil(mid);
+
+ return createPadding('', leftLength, chars) + string + createPadding('', rightLength, chars);
+ }
+
+ /**
+ * Pads `string` on the right side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padEnd('abc', 6);
+ * // => 'abc '
+ *
+ * _.padEnd('abc', 6, '_-');
+ * // => 'abc_-_'
+ *
+ * _.padEnd('abc', 3);
+ * // => 'abc'
+ */
+ function padEnd(string, length, chars) {
+ string = toString(string);
+ return string + createPadding(string, length, chars);
+ }
+
+ /**
+ * Pads `string` on the left side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padStart('abc', 6);
+ * // => ' abc'
+ *
+ * _.padStart('abc', 6, '_-');
+ * // => '_-_abc'
+ *
+ * _.padStart('abc', 3);
+ * // => 'abc'
+ */
+ function padStart(string, length, chars) {
+ string = toString(string);
+ return createPadding(string, length, chars) + string;
+ }
+
+ /**
+ * Converts `string` to an integer of the specified radix. If `radix` is
+ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
+ * in which case a `radix` of `16` is used.
+ *
+ * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#x15.1.2.2)
+ * of `parseInt`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} string The string to convert.
+ * @param {number} [radix=10] The radix to interpret `value` by.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.parseInt('08');
+ * // => 8
+ *
+ * _.map(['6', '08', '10'], _.parseInt);
+ * // => [6, 8, 10]
+ */
+ function parseInt(string, radix, guard) {
+ // Chrome fails to trim leading <BOM> whitespace characters.
+ // See https://code.google.com/p/v8/issues/detail?id=3109 for more details.
+ if (guard || radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ string = toString(string).replace(reTrim, '');
+ return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
+ }
+
+ /**
+ * Repeats the given string `n` times.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to repeat.
+ * @param {number} [n=0] The number of times to repeat the string.
+ * @returns {string} Returns the repeated string.
+ * @example
+ *
+ * _.repeat('*', 3);
+ * // => '***'
+ *
+ * _.repeat('abc', 2);
+ * // => 'abcabc'
+ *
+ * _.repeat('abc', 0);
+ * // => ''
+ */
+ function repeat(string, n) {
+ string = toString(string);
+ n = toInteger(n);
+
+ var result = '';
+ if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
+ return result;
+ }
+ // Leverage the exponentiation by squaring algorithm for a faster repeat.
+ // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
+ do {
+ if (n % 2) {
+ result += string;
+ }
+ n = nativeFloor(n / 2);
+ string += string;
+ } while (n);
+
+ return result;
+ }
+
+ /**
+ * Replaces matches for `pattern` in `string` with `replacement`.
+ *
+ * **Note:** This method is based on [`String#replace`](https://mdn.io/String/replace).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to modify.
+ * @param {RegExp|string} pattern The pattern to replace.
+ * @param {Function|string} replacement The match replacement.
+ * @returns {string} Returns the modified string.
+ * @example
+ *
+ * _.replace('Hi Fred', 'Fred', 'Barney');
+ * // => 'Hi Barney'
+ */
+ function replace() {
+ var args = arguments,
+ string = toString(args[0]);
+
+ return args.length < 3 ? string : string.replace(args[1], args[2]);
+ }
+
+ /**
+ * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the snake cased string.
+ * @example
+ *
+ * _.snakeCase('Foo Bar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('fooBar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('--foo-bar');
+ * // => 'foo_bar'
+ */
+ var snakeCase = createCompounder(function(result, word, index) {
+ return result + (index ? '_' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Splits `string` by `separator`.
+ *
+ * **Note:** This method is based on [`String#split`](https://mdn.io/String/split).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to split.
+ * @param {RegExp|string} separator The separator pattern to split by.
+ * @param {number} [limit] The length to truncate results to.
+ * @returns {Array} Returns the new array of string segments.
+ * @example
+ *
+ * _.split('a-b-c', '-', 2);
+ * // => ['a', 'b']
+ */
+ function split(string, separator, limit) {
+ return toString(string).split(separator, limit);
+ }
+
+ /**
+ * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the start cased string.
+ * @example
+ *
+ * _.startCase('--foo-bar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('fooBar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('__foo_bar__');
+ * // => 'Foo Bar'
+ */
+ var startCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + capitalize(word);
+ });
+
+ /**
+ * Checks if `string` starts with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to search.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=0] The position to search from.
+ * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.
+ * @example
+ *
+ * _.startsWith('abc', 'a');
+ * // => true
+ *
+ * _.startsWith('abc', 'b');
+ * // => false
+ *
+ * _.startsWith('abc', 'b', 1);
+ * // => true
+ */
+ function startsWith(string, target, position) {
+ string = toString(string);
+ position = baseClamp(toInteger(position), 0, string.length);
+ return string.lastIndexOf(target, position) == position;
+ }
+
+ /**
+ * Creates a compiled template function that can interpolate data properties
+ * in "interpolate" delimiters, HTML-escape interpolated data properties in
+ * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
+ * properties may be accessed as free variables in the template. If a setting
+ * object is given it takes precedence over `_.templateSettings` values.
+ *
+ * **Note:** In the development build `_.template` utilizes
+ * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * for easier debugging.
+ *
+ * For more information on precompiling templates see
+ * [lodash's custom builds documentation](https://lodash.com/custom-builds).
+ *
+ * For more information on Chrome extension sandboxes see
+ * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The template string.
+ * @param {Object} [options] The options object.
+ * @param {RegExp} [options.escape] The HTML "escape" delimiter.
+ * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+ * @param {Object} [options.imports] An object to import into the template as free variables.
+ * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+ * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
+ * @param {string} [options.variable] The data object variable name.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Function} Returns the compiled template function.
+ * @example
+ *
+ * // Use the "interpolate" delimiter to create a compiled template.
+ * var compiled = _.template('hello <%= user %>!');
+ * compiled({ 'user': 'fred' });
+ * // => 'hello fred!'
+ *
+ * // Use the HTML "escape" delimiter to escape data property values.
+ * var compiled = _.template('<b><%- value %></b>');
+ * compiled({ 'value': '<script>' });
+ * // => '<b>&lt;script&gt;</b>'
+ *
+ * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
+ * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // Use the internal `print` function in "evaluate" delimiters.
+ * var compiled = _.template('<% print("hello " + user); %>!');
+ * compiled({ 'user': 'barney' });
+ * // => 'hello barney!'
+ *
+ * // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
+ * var compiled = _.template('hello ${ user }!');
+ * compiled({ 'user': 'pebbles' });
+ * // => 'hello pebbles!'
+ *
+ * // Use custom template delimiters.
+ * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
+ * var compiled = _.template('hello {{ user }}!');
+ * compiled({ 'user': 'mustache' });
+ * // => 'hello mustache!'
+ *
+ * // Use backslashes to treat delimiters as plain text.
+ * var compiled = _.template('<%= "\\<%- value %\\>" %>');
+ * compiled({ 'value': 'ignored' });
+ * // => '<%- value %>'
+ *
+ * // Use the `imports` option to import `jQuery` as `jq`.
+ * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
+ * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // Use the `sourceURL` option to specify a custom sourceURL for the template.
+ * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
+ * compiled(data);
+ * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+ *
+ * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
+ * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
+ * compiled.source;
+ * // => function(data) {
+ * // var __t, __p = '';
+ * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
+ * // return __p;
+ * // }
+ *
+ * // Use the `source` property to inline compiled templates for meaningful
+ * // line numbers in error messages and stack traces.
+ * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+ * var JST = {\
+ * "main": ' + _.template(mainText).source + '\
+ * };\
+ * ');
+ */
+ function template(string, options, guard) {
+ // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)
+ // and Laura Doktorova's doT.js (https://github.com/olado/doT).
+ var settings = lodash.templateSettings;
+
+ if (guard && isIterateeCall(string, options, guard)) {
+ options = undefined;
+ }
+ string = toString(string);
+ options = assignInWith({}, options, settings, assignInDefaults);
+
+ var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
+ importsKeys = keys(imports),
+ importsValues = baseValues(imports, importsKeys);
+
+ var isEscaping,
+ isEvaluating,
+ index = 0,
+ interpolate = options.interpolate || reNoMatch,
+ source = "__p += '";
+
+ // Compile the regexp to match each delimiter.
+ var reDelimiters = RegExp(
+ (options.escape || reNoMatch).source + '|' +
+ interpolate.source + '|' +
+ (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+ (options.evaluate || reNoMatch).source + '|$'
+ , 'g');
+
+ // Use a sourceURL for easier debugging.
+ var sourceURL = '//# sourceURL=' +
+ ('sourceURL' in options
+ ? options.sourceURL
+ : ('lodash.templateSources[' + (++templateCounter) + ']')
+ ) + '\n';
+
+ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+
+ // Escape characters that can't be included in string literals.
+ source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+ // Replace delimiters with snippets.
+ if (escapeValue) {
+ isEscaping = true;
+ source += "' +\n__e(" + escapeValue + ") +\n'";
+ }
+ if (evaluateValue) {
+ isEvaluating = true;
+ source += "';\n" + evaluateValue + ";\n__p += '";
+ }
+ if (interpolateValue) {
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+ }
+ index = offset + match.length;
+
+ // The JS engine embedded in Adobe products needs `match` returned in
+ // order to produce the correct `offset` value.
+ return match;
+ });
+
+ source += "';\n";
+
+ // If `variable` is not specified wrap a with-statement around the generated
+ // code to add the data object to the top of the scope chain.
+ var variable = options.variable;
+ if (!variable) {
+ source = 'with (obj) {\n' + source + '\n}\n';
+ }
+ // Cleanup code by stripping empty strings.
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+ .replace(reEmptyStringMiddle, '$1')
+ .replace(reEmptyStringTrailing, '$1;');
+
+ // Frame code as the function body.
+ source = 'function(' + (variable || 'obj') + ') {\n' +
+ (variable
+ ? ''
+ : 'obj || (obj = {});\n'
+ ) +
+ "var __t, __p = ''" +
+ (isEscaping
+ ? ', __e = _.escape'
+ : ''
+ ) +
+ (isEvaluating
+ ? ', __j = Array.prototype.join;\n' +
+ "function print() { __p += __j.call(arguments, '') }\n"
+ : ';\n'
+ ) +
+ source +
+ 'return __p\n}';
+
+ var result = attempt(function() {
+ return Function(importsKeys, sourceURL + 'return ' + source)
+ .apply(undefined, importsValues);
+ });
+
+ // Provide the compiled function's source by its `toString` method or
+ // the `source` property as a convenience for inlining compiled templates.
+ result.source = source;
+ if (isError(result)) {
+ throw result;
+ }
+ return result;
+ }
+
+ /**
+ * Converts `string`, as a whole, to lower case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the lower cased string.
+ * @example
+ *
+ * _.toLower('--Foo-Bar');
+ * // => '--foo-bar'
+ *
+ * _.toLower('fooBar');
+ * // => 'foobar'
+ *
+ * _.toLower('__FOO_BAR__');
+ * // => '__foo_bar__'
+ */
+ function toLower(value) {
+ return toString(value).toLowerCase();
+ }
+
+ /**
+ * Converts `string`, as a whole, to upper case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the upper cased string.
+ * @example
+ *
+ * _.toUpper('--foo-bar');
+ * // => '--FOO-BAR'
+ *
+ * _.toUpper('fooBar');
+ * // => 'FOOBAR'
+ *
+ * _.toUpper('__foo_bar__');
+ * // => '__FOO_BAR__'
+ */
+ function toUpper(value) {
+ return toString(value).toUpperCase();
+ }
+
+ /**
+ * Removes leading and trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trim(' abc ');
+ * // => 'abc'
+ *
+ * _.trim('-_-abc-_-', '_-');
+ * // => 'abc'
+ *
+ * _.map([' foo ', ' bar '], _.trim);
+ * // => ['foo', 'bar']
+ */
+ function trim(string, chars, guard) {
+ string = toString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard || chars === undefined) {
+ return string.replace(reTrim, '');
+ }
+ chars = (chars + '');
+ if (!chars) {
+ return string;
+ }
+ var strSymbols = stringToArray(string),
+ chrSymbols = stringToArray(chars);
+
+ return strSymbols
+ .slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1)
+ .join('');
+ }
+
+ /**
+ * Removes trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimEnd(' abc ');
+ * // => ' abc'
+ *
+ * _.trimEnd('-_-abc-_-', '_-');
+ * // => '-_-abc'
+ */
+ function trimEnd(string, chars, guard) {
+ string = toString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard || chars === undefined) {
+ return string.replace(reTrimEnd, '');
+ }
+ chars = (chars + '');
+ if (!chars) {
+ return string;
+ }
+ var strSymbols = stringToArray(string);
+ return strSymbols
+ .slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1)
+ .join('');
+ }
+
+ /**
+ * Removes leading whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimStart(' abc ');
+ * // => 'abc '
+ *
+ * _.trimStart('-_-abc-_-', '_-');
+ * // => 'abc-_-'
+ */
+ function trimStart(string, chars, guard) {
+ string = toString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard || chars === undefined) {
+ return string.replace(reTrimStart, '');
+ }
+ chars = (chars + '');
+ if (!chars) {
+ return string;
+ }
+ var strSymbols = stringToArray(string);
+ return strSymbols
+ .slice(charsStartIndex(strSymbols, stringToArray(chars)))
+ .join('');
+ }
+
+ /**
+ * Truncates `string` if it's longer than the given maximum string length.
+ * The last characters of the truncated string are replaced with the omission
+ * string which defaults to "...".
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to truncate.
+ * @param {Object} [options=({})] The options object.
+ * @param {number} [options.length=30] The maximum string length.
+ * @param {string} [options.omission='...'] The string to indicate text is omitted.
+ * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
+ * @returns {string} Returns the truncated string.
+ * @example
+ *
+ * _.truncate('hi-diddly-ho there, neighborino');
+ * // => 'hi-diddly-ho there, neighbo...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': ' '
+ * });
+ * // => 'hi-diddly-ho there,...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': /,? +/
+ * });
+ * // => 'hi-diddly-ho there...'
+ *
+ * _.truncate('hi-diddly-ho there, neighborino', {
+ * 'omission': ' [...]'
+ * });
+ * // => 'hi-diddly-ho there, neig [...]'
+ */
+ function truncate(string, options) {
+ var length = DEFAULT_TRUNC_LENGTH,
+ omission = DEFAULT_TRUNC_OMISSION;
+
+ if (isObject(options)) {
+ var separator = 'separator' in options ? options.separator : separator;
+ length = 'length' in options ? toInteger(options.length) : length;
+ omission = 'omission' in options ? toString(options.omission) : omission;
+ }
+ string = toString(string);
+
+ var strLength = string.length;
+ if (reHasComplexSymbol.test(string)) {
+ var strSymbols = stringToArray(string);
+ strLength = strSymbols.length;
+ }
+ if (length >= strLength) {
+ return string;
+ }
+ var end = length - stringSize(omission);
+ if (end < 1) {
+ return omission;
+ }
+ var result = strSymbols
+ ? strSymbols.slice(0, end).join('')
+ : string.slice(0, end);
+
+ if (separator === undefined) {
+ return result + omission;
+ }
+ if (strSymbols) {
+ end += (result.length - end);
+ }
+ if (isRegExp(separator)) {
+ if (string.slice(end).search(separator)) {
+ var match,
+ substring = result;
+
+ if (!separator.global) {
+ separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
+ }
+ separator.lastIndex = 0;
+ while ((match = separator.exec(substring))) {
+ var newEnd = match.index;
+ }
+ result = result.slice(0, newEnd === undefined ? end : newEnd);
+ }
+ } else if (string.indexOf(separator, end) != end) {
+ var index = result.lastIndexOf(separator);
+ if (index > -1) {
+ result = result.slice(0, index);
+ }
+ }
+ return result + omission;
+ }
+
+ /**
+ * The inverse of `_.escape`; this method converts the HTML entities
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their
+ * corresponding characters.
+ *
+ * **Note:** No other HTML entities are unescaped. To unescape additional HTML
+ * entities use a third-party library like [_he_](https://mths.be/he).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to unescape.
+ * @returns {string} Returns the unescaped string.
+ * @example
+ *
+ * _.unescape('fred, barney, &amp; pebbles');
+ * // => 'fred, barney, & pebbles'
+ */
+ function unescape(string) {
+ string = toString(string);
+ return (string && reHasEscapedHtml.test(string))
+ ? string.replace(reEscapedHtml, unescapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Converts `string`, as space separated words, to upper case.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the upper cased string.
+ * @example
+ *
+ * _.upperCase('--foo-bar');
+ * // => 'FOO BAR'
+ *
+ * _.upperCase('fooBar');
+ * // => 'FOO BAR'
+ *
+ * _.upperCase('__foo_bar__');
+ * // => 'FOO BAR'
+ */
+ var upperCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + word.toUpperCase();
+ });
+
+ /**
+ * Splits `string` into an array of its words.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {RegExp|string} [pattern] The pattern to match words.
+ * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
+ * @returns {Array} Returns the words of `string`.
+ * @example
+ *
+ * _.words('fred, barney, & pebbles');
+ * // => ['fred', 'barney', 'pebbles']
+ *
+ * _.words('fred, barney, & pebbles', /[^, ]+/g);
+ * // => ['fred', 'barney', '&', 'pebbles']
+ */
+ function words(string, pattern, guard) {
+ string = toString(string);
+ pattern = guard ? undefined : pattern;
+
+ if (pattern === undefined) {
+ pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord;
+ }
+ return string.match(pattern) || [];
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Attempts to invoke `func`, returning either the result or the caught error
+ * object. Any additional arguments are provided to `func` when it's invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Function} func The function to attempt.
+ * @returns {*} Returns the `func` result or error object.
+ * @example
+ *
+ * // Avoid throwing errors for invalid selectors.
+ * var elements = _.attempt(function(selector) {
+ * return document.querySelectorAll(selector);
+ * }, '>_>');
+ *
+ * if (_.isError(elements)) {
+ * elements = [];
+ * }
+ */
+ var attempt = rest(function(func, args) {
+ try {
+ return apply(func, undefined, args);
+ } catch (e) {
+ return isError(e) ? e : new Error(e);
+ }
+ });
+
+ /**
+ * Binds methods of an object to the object itself, overwriting the existing
+ * method.
+ *
+ * **Note:** This method doesn't set the "length" property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {...(string|string[])} methodNames The object method names to bind,
+ * specified individually or in arrays.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var view = {
+ * 'label': 'docs',
+ * 'onClick': function() {
+ * console.log('clicked ' + this.label);
+ * }
+ * };
+ *
+ * _.bindAll(view, 'onClick');
+ * jQuery(element).on('click', view.onClick);
+ * // => logs 'clicked docs' when clicked
+ */
+ var bindAll = rest(function(object, methodNames) {
+ arrayEach(baseFlatten(methodNames, 1), function(key) {
+ object[key] = bind(object[key], object);
+ });
+ return object;
+ });
+
+ /**
+ * Creates a function that iterates over `pairs` invoking the corresponding
+ * function of the first predicate to return truthy. The predicate-function
+ * pairs are invoked with the `this` binding and arguments of the created
+ * function.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Array} pairs The predicate-function pairs.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.cond([
+ * [_.matches({ 'a': 1 }), _.constant('matches A')],
+ * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
+ * [_.constant(true), _.constant('no match')]
+ * ]);
+ *
+ * func({ 'a': 1, 'b': 2 });
+ * // => 'matches A'
+ *
+ * func({ 'a': 0, 'b': 1 });
+ * // => 'matches B'
+ *
+ * func({ 'a': '1', 'b': '2' });
+ * // => 'no match'
+ */
+ function cond(pairs) {
+ var length = pairs ? pairs.length : 0,
+ toIteratee = getIteratee();
+
+ pairs = !length ? [] : arrayMap(pairs, function(pair) {
+ if (typeof pair[1] != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return [toIteratee(pair[0]), pair[1]];
+ });
+
+ return rest(function(args) {
+ var index = -1;
+ while (++index < length) {
+ var pair = pairs[index];
+ if (apply(pair[0], this, args)) {
+ return apply(pair[1], this, args);
+ }
+ }
+ });
+ }
+
+ /**
+ * Creates a function that invokes the predicate properties of `source` with
+ * the corresponding property values of a given object, returning `true` if
+ * all predicates return truthy, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} source The object of property predicates to conform to.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * _.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) }));
+ * // => [{ 'user': 'fred', 'age': 40 }]
+ */
+ function conforms(source) {
+ return baseConforms(baseClone(source, true));
+ }
+
+ /**
+ * Creates a function that returns `value`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {*} value The value to return from the new function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ * var getter = _.constant(object);
+ *
+ * getter() === object;
+ * // => true
+ */
+ function constant(value) {
+ return function() {
+ return value;
+ };
+ }
+
+ /**
+ * Creates a function that returns the result of invoking the given functions
+ * with the `this` binding of the created function, where each successive
+ * invocation is supplied the return value of the previous.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flow(_.add, square);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flow = createFlow();
+
+ /**
+ * This method is like `_.flow` except that it creates a function that
+ * invokes the given functions from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flowRight(square, _.add);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flowRight = createFlow(true);
+
+ /**
+ * This method returns the first argument given to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.identity(object) === object;
+ * // => true
+ */
+ function identity(value) {
+ return value;
+ }
+
+ /**
+ * Creates a function that invokes `func` with the arguments of the created
+ * function. If `func` is a property name the created callback returns the
+ * property value for a given element. If `func` is an object the created
+ * callback returns `true` for elements that contain the equivalent object
+ * properties, otherwise it returns `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {*} [func=_.identity] The value to convert to a callback.
+ * @returns {Function} Returns the callback.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // Create custom iteratee shorthands.
+ * _.iteratee = _.wrap(_.iteratee, function(callback, func) {
+ * var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func);
+ * return !p ? callback(func) : function(object) {
+ * return (p[2] == '>' ? object[p[1]] > p[3] : object[p[1]] < p[3]);
+ * };
+ * });
+ *
+ * _.filter(users, 'age > 36');
+ * // => [{ 'user': 'fred', 'age': 40 }]
+ */
+ function iteratee(func) {
+ return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
+ }
+
+ /**
+ * Creates a function that performs a partial deep comparison between a given
+ * object and `source`, returning `true` if the given object has equivalent
+ * property values, else `false`. The created function is equivalent to
+ * `_.isMatch` with a `source` partially applied.
+ *
+ * **Note:** This method supports comparing the same values as `_.isEqual`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, _.matches({ 'age': 40, 'active': false }));
+ * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
+ */
+ function matches(source) {
+ return baseMatches(baseClone(source, true));
+ }
+
+ /**
+ * Creates a function that performs a partial deep comparison between the
+ * value at `path` of a given object to `srcValue`, returning `true` if the
+ * object value is equivalent, else `false`.
+ *
+ * **Note:** This method supports comparing the same values as `_.isEqual`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * _.find(users, _.matchesProperty('user', 'fred'));
+ * // => { 'user': 'fred' }
+ */
+ function matchesProperty(path, srcValue) {
+ return baseMatchesProperty(path, baseClone(srcValue, true));
+ }
+
+ /**
+ * Creates a function that invokes the method at `path` of a given object.
+ * Any additional arguments are provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': { 'c': _.constant(2) } } },
+ * { 'a': { 'b': { 'c': _.constant(1) } } }
+ * ];
+ *
+ * _.map(objects, _.method('a.b.c'));
+ * // => [2, 1]
+ *
+ * _.invokeMap(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');
+ * // => [1, 2]
+ */
+ var method = rest(function(path, args) {
+ return function(object) {
+ return baseInvoke(object, path, args);
+ };
+ });
+
+ /**
+ * The opposite of `_.method`; this method creates a function that invokes
+ * the method at a given path of `object`. Any additional arguments are
+ * provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} object The object to query.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var array = _.times(3, _.constant),
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.methodOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
+ * // => [2, 0]
+ */
+ var methodOf = rest(function(object, args) {
+ return function(path) {
+ return baseInvoke(object, path, args);
+ };
+ });
+
+ /**
+ * Adds all own enumerable function properties of a source object to the
+ * destination object. If `object` is a function then methods are added to
+ * its prototype as well.
+ *
+ * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
+ * avoid conflicts caused by modifying the original.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Function|Object} [object=lodash] The destination object.
+ * @param {Object} source The object of functions to add.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.chain=true] Specify whether the functions added
+ * are chainable.
+ * @returns {Function|Object} Returns `object`.
+ * @example
+ *
+ * function vowels(string) {
+ * return _.filter(string, function(v) {
+ * return /[aeiou]/i.test(v);
+ * });
+ * }
+ *
+ * _.mixin({ 'vowels': vowels });
+ * _.vowels('fred');
+ * // => ['e']
+ *
+ * _('fred').vowels().value();
+ * // => ['e']
+ *
+ * _.mixin({ 'vowels': vowels }, { 'chain': false });
+ * _('fred').vowels();
+ * // => ['e']
+ */
+ function mixin(object, source, options) {
+ var props = keys(source),
+ methodNames = baseFunctions(source, props);
+
+ if (options == null &&
+ !(isObject(source) && (methodNames.length || !props.length))) {
+ options = source;
+ source = object;
+ object = this;
+ methodNames = baseFunctions(source, keys(source));
+ }
+ var chain = (isObject(options) && 'chain' in options) ? options.chain : true,
+ isFunc = isFunction(object);
+
+ arrayEach(methodNames, function(methodName) {
+ var func = source[methodName];
+ object[methodName] = func;
+ if (isFunc) {
+ object.prototype[methodName] = function() {
+ var chainAll = this.__chain__;
+ if (chain || chainAll) {
+ var result = object(this.__wrapped__),
+ actions = result.__actions__ = copyArray(this.__actions__);
+
+ actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
+ result.__chain__ = chainAll;
+ return result;
+ }
+ return func.apply(object, arrayPush([this.value()], arguments));
+ };
+ }
+ });
+
+ return object;
+ }
+
+ /**
+ * Reverts the `_` variable to its previous value and returns a reference to
+ * the `lodash` function.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @returns {Function} Returns the `lodash` function.
+ * @example
+ *
+ * var lodash = _.noConflict();
+ */
+ function noConflict() {
+ if (root._ === this) {
+ root._ = oldDash;
+ }
+ return this;
+ }
+
+ /**
+ * A no-operation function that returns `undefined` regardless of the
+ * arguments it receives.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.noop(object) === undefined;
+ * // => true
+ */
+ function noop() {
+ // No operation performed.
+ }
+
+ /**
+ * Creates a function that returns its nth argument.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {number} [n=0] The index of the argument to return.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.nthArg(1);
+ *
+ * func('a', 'b', 'c');
+ * // => 'b'
+ */
+ function nthArg(n) {
+ n = toInteger(n);
+ return function() {
+ return arguments[n];
+ };
+ }
+
+ /**
+ * Creates a function that invokes `iteratees` with the arguments provided
+ * to the created function and returns their results.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} iteratees The iteratees to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.over(Math.max, Math.min);
+ *
+ * func(1, 2, 3, 4);
+ * // => [4, 1]
+ */
+ var over = createOver(arrayMap);
+
+ /**
+ * Creates a function that checks if **all** of the `predicates` return
+ * truthy when invoked with the arguments provided to the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} predicates The predicates to check.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.overEvery(Boolean, isFinite);
+ *
+ * func('1');
+ * // => true
+ *
+ * func(null);
+ * // => false
+ *
+ * func(NaN);
+ * // => false
+ */
+ var overEvery = createOver(arrayEvery);
+
+ /**
+ * Creates a function that checks if **any** of the `predicates` return
+ * truthy when invoked with the arguments provided to the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {...(Function|Function[])} predicates The predicates to check.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var func = _.overSome(Boolean, isFinite);
+ *
+ * func('1');
+ * // => true
+ *
+ * func(null);
+ * // => true
+ *
+ * func(NaN);
+ * // => false
+ */
+ var overSome = createOver(arraySome);
+
+ /**
+ * Creates a function that returns the value at `path` of a given object.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': { 'c': 2 } } },
+ * { 'a': { 'b': { 'c': 1 } } }
+ * ];
+ *
+ * _.map(objects, _.property('a.b.c'));
+ * // => [2, 1]
+ *
+ * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
+ * // => [1, 2]
+ */
+ function property(path) {
+ return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
+ }
+
+ /**
+ * The opposite of `_.property`; this method creates a function that returns
+ * the value at a given path of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {Object} object The object to query.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var array = [0, 1, 2],
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
+ * // => [2, 0]
+ */
+ function propertyOf(object) {
+ return function(path) {
+ return object == null ? undefined : baseGet(object, path);
+ };
+ }
+
+ /**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to, but not including, `end`. A step of `-1` is used if a negative
+ * `start` is specified without an `end` or `step`. If `end` is not specified
+ * it's set to `start` with `start` then set to `0`.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the new array of numbers.
+ * @example
+ *
+ * _.range(4);
+ * // => [0, 1, 2, 3]
+ *
+ * _.range(-4);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 5);
+ * // => [1, 2, 3, 4]
+ *
+ * _.range(0, 20, 5);
+ * // => [0, 5, 10, 15]
+ *
+ * _.range(0, -4, -1);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.range(0);
+ * // => []
+ */
+ var range = createRange();
+
+ /**
+ * This method is like `_.range` except that it populates values in
+ * descending order.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the new array of numbers.
+ * @example
+ *
+ * _.rangeRight(4);
+ * // => [3, 2, 1, 0]
+ *
+ * _.rangeRight(-4);
+ * // => [-3, -2, -1, 0]
+ *
+ * _.rangeRight(1, 5);
+ * // => [4, 3, 2, 1]
+ *
+ * _.rangeRight(0, 20, 5);
+ * // => [15, 10, 5, 0]
+ *
+ * _.rangeRight(0, -4, -1);
+ * // => [-3, -2, -1, 0]
+ *
+ * _.rangeRight(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.rangeRight(0);
+ * // => []
+ */
+ var rangeRight = createRange(true);
+
+ /**
+ * Invokes the iteratee `n` times, returning an array of the results of
+ * each invocation. The iteratee is invoked with one argument; (index).
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.times(3, String);
+ * // => ['0', '1', '2']
+ *
+ * _.times(4, _.constant(true));
+ * // => [true, true, true, true]
+ */
+ function times(n, iteratee) {
+ n = toInteger(n);
+ if (n < 1 || n > MAX_SAFE_INTEGER) {
+ return [];
+ }
+ var index = MAX_ARRAY_LENGTH,
+ length = nativeMin(n, MAX_ARRAY_LENGTH);
+
+ iteratee = baseCastFunction(iteratee);
+ n -= MAX_ARRAY_LENGTH;
+
+ var result = baseTimes(length, iteratee);
+ while (++index < n) {
+ iteratee(index);
+ }
+ return result;
+ }
+
+ /**
+ * Converts `value` to a property path array.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the new property path array.
+ * @example
+ *
+ * _.toPath('a.b.c');
+ * // => ['a', 'b', 'c']
+ *
+ * _.toPath('a[0].b.c');
+ * // => ['a', '0', 'b', 'c']
+ *
+ * var path = ['a', 'b', 'c'],
+ * newPath = _.toPath(path);
+ *
+ * console.log(newPath);
+ * // => ['a', 'b', 'c']
+ *
+ * console.log(path === newPath);
+ * // => false
+ */
+ function toPath(value) {
+ return isArray(value) ? arrayMap(value, String) : stringToPath(value);
+ }
+
+ /**
+ * Generates a unique ID. If `prefix` is given the ID is appended to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Util
+ * @param {string} [prefix=''] The value to prefix the ID with.
+ * @returns {string} Returns the unique ID.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ *
+ * _.uniqueId();
+ * // => '105'
+ */
+ function uniqueId(prefix) {
+ var id = ++idCounter;
+ return toString(prefix) + id;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Adds two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} augend The first number in an addition.
+ * @param {number} addend The second number in an addition.
+ * @returns {number} Returns the total.
+ * @example
+ *
+ * _.add(6, 4);
+ * // => 10
+ */
+ function add(augend, addend) {
+ var result;
+ if (augend === undefined && addend === undefined) {
+ return 0;
+ }
+ if (augend !== undefined) {
+ result = augend;
+ }
+ if (addend !== undefined) {
+ result = result === undefined ? addend : (result + addend);
+ }
+ return result;
+ }
+
+ /**
+ * Computes `number` rounded up to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} number The number to round up.
+ * @param {number} [precision=0] The precision to round up to.
+ * @returns {number} Returns the rounded up number.
+ * @example
+ *
+ * _.ceil(4.006);
+ * // => 5
+ *
+ * _.ceil(6.004, 2);
+ * // => 6.01
+ *
+ * _.ceil(6040, -2);
+ * // => 6100
+ */
+ var ceil = createRound('ceil');
+
+ /**
+ * Computes `number` rounded down to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} number The number to round down.
+ * @param {number} [precision=0] The precision to round down to.
+ * @returns {number} Returns the rounded down number.
+ * @example
+ *
+ * _.floor(4.006);
+ * // => 4
+ *
+ * _.floor(0.046, 2);
+ * // => 0.04
+ *
+ * _.floor(4060, -2);
+ * // => 4000
+ */
+ var floor = createRound('floor');
+
+ /**
+ * Computes the maximum value of `array`. If `array` is empty or falsey
+ * `undefined` is returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * _.max([4, 2, 8, 6]);
+ * // => 8
+ *
+ * _.max([]);
+ * // => undefined
+ */
+ function max(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, gt)
+ : undefined;
+ }
+
+ /**
+ * This method is like `_.max` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * the value is ranked. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * var objects = [{ 'n': 1 }, { 'n': 2 }];
+ *
+ * _.maxBy(objects, function(o) { return o.n; });
+ * // => { 'n': 2 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.maxBy(objects, 'n');
+ * // => { 'n': 2 }
+ */
+ function maxBy(array, iteratee) {
+ return (array && array.length)
+ ? baseExtremum(array, getIteratee(iteratee), gt)
+ : undefined;
+ }
+
+ /**
+ * Computes the mean of the values in `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {number} Returns the mean.
+ * @example
+ *
+ * _.mean([4, 2, 8, 6]);
+ * // => 5
+ */
+ function mean(array) {
+ return sum(array) / (array ? array.length : 0);
+ }
+
+ /**
+ * Computes the minimum value of `array`. If `array` is empty or falsey
+ * `undefined` is returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * _.min([4, 2, 8, 6]);
+ * // => 2
+ *
+ * _.min([]);
+ * // => undefined
+ */
+ function min(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, lt)
+ : undefined;
+ }
+
+ /**
+ * This method is like `_.min` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * the value is ranked. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * var objects = [{ 'n': 1 }, { 'n': 2 }];
+ *
+ * _.minBy(objects, function(o) { return o.n; });
+ * // => { 'n': 1 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.minBy(objects, 'n');
+ * // => { 'n': 1 }
+ */
+ function minBy(array, iteratee) {
+ return (array && array.length)
+ ? baseExtremum(array, getIteratee(iteratee), lt)
+ : undefined;
+ }
+
+ /**
+ * Computes `number` rounded to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} number The number to round.
+ * @param {number} [precision=0] The precision to round to.
+ * @returns {number} Returns the rounded number.
+ * @example
+ *
+ * _.round(4.006);
+ * // => 4
+ *
+ * _.round(4.006, 2);
+ * // => 4.01
+ *
+ * _.round(4060, -2);
+ * // => 4100
+ */
+ var round = createRound('round');
+
+ /**
+ * Subtract two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} minuend The first number in a subtraction.
+ * @param {number} subtrahend The second number in a subtraction.
+ * @returns {number} Returns the difference.
+ * @example
+ *
+ * _.subtract(6, 4);
+ * // => 2
+ */
+ function subtract(minuend, subtrahend) {
+ var result;
+ if (minuend === undefined && subtrahend === undefined) {
+ return 0;
+ }
+ if (minuend !== undefined) {
+ result = minuend;
+ }
+ if (subtrahend !== undefined) {
+ result = result === undefined ? subtrahend : (result - subtrahend);
+ }
+ return result;
+ }
+
+ /**
+ * Computes the sum of the values in `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * _.sum([4, 2, 8, 6]);
+ * // => 20
+ */
+ function sum(array) {
+ return (array && array.length)
+ ? baseSum(array, identity)
+ : 0;
+ }
+
+ /**
+ * This method is like `_.sum` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the value to be summed.
+ * The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
+ *
+ * _.sumBy(objects, function(o) { return o.n; });
+ * // => 20
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.sumBy(objects, 'n');
+ * // => 20
+ */
+ function sumBy(array, iteratee) {
+ return (array && array.length)
+ ? baseSum(array, getIteratee(iteratee))
+ : 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Ensure wrappers are instances of `baseLodash`.
+ lodash.prototype = baseLodash.prototype;
+
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+
+ // Avoid inheriting from `Object.prototype` when possible.
+ Hash.prototype = nativeCreate ? nativeCreate(null) : objectProto;
+
+ // Add functions to the `MapCache`.
+ MapCache.prototype.clear = mapClear;
+ MapCache.prototype['delete'] = mapDelete;
+ MapCache.prototype.get = mapGet;
+ MapCache.prototype.has = mapHas;
+ MapCache.prototype.set = mapSet;
+
+ // Add functions to the `SetCache`.
+ SetCache.prototype.push = cachePush;
+
+ // Add functions to the `Stack` cache.
+ Stack.prototype.clear = stackClear;
+ Stack.prototype['delete'] = stackDelete;
+ Stack.prototype.get = stackGet;
+ Stack.prototype.has = stackHas;
+ Stack.prototype.set = stackSet;
+
+ // Assign cache to `_.memoize`.
+ memoize.Cache = MapCache;
+
+ // Add functions that return wrapped values when chaining.
+ lodash.after = after;
+ lodash.ary = ary;
+ lodash.assign = assign;
+ lodash.assignIn = assignIn;
+ lodash.assignInWith = assignInWith;
+ lodash.assignWith = assignWith;
+ lodash.at = at;
+ lodash.before = before;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.castArray = castArray;
+ lodash.chain = chain;
+ lodash.chunk = chunk;
+ lodash.compact = compact;
+ lodash.concat = concat;
+ lodash.cond = cond;
+ lodash.conforms = conforms;
+ lodash.constant = constant;
+ lodash.countBy = countBy;
+ lodash.create = create;
+ lodash.curry = curry;
+ lodash.curryRight = curryRight;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defaultsDeep = defaultsDeep;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.differenceBy = differenceBy;
+ lodash.differenceWith = differenceWith;
+ lodash.drop = drop;
+ lodash.dropRight = dropRight;
+ lodash.dropRightWhile = dropRightWhile;
+ lodash.dropWhile = dropWhile;
+ lodash.fill = fill;
+ lodash.filter = filter;
+ lodash.flatMap = flatMap;
+ lodash.flatten = flatten;
+ lodash.flattenDeep = flattenDeep;
+ lodash.flattenDepth = flattenDepth;
+ lodash.flip = flip;
+ lodash.flow = flow;
+ lodash.flowRight = flowRight;
+ lodash.fromPairs = fromPairs;
+ lodash.functions = functions;
+ lodash.functionsIn = functionsIn;
+ lodash.groupBy = groupBy;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.intersectionBy = intersectionBy;
+ lodash.intersectionWith = intersectionWith;
+ lodash.invert = invert;
+ lodash.invertBy = invertBy;
+ lodash.invokeMap = invokeMap;
+ lodash.iteratee = iteratee;
+ lodash.keyBy = keyBy;
+ lodash.keys = keys;
+ lodash.keysIn = keysIn;
+ lodash.map = map;
+ lodash.mapKeys = mapKeys;
+ lodash.mapValues = mapValues;
+ lodash.matches = matches;
+ lodash.matchesProperty = matchesProperty;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.mergeWith = mergeWith;
+ lodash.method = method;
+ lodash.methodOf = methodOf;
+ lodash.mixin = mixin;
+ lodash.negate = negate;
+ lodash.nthArg = nthArg;
+ lodash.omit = omit;
+ lodash.omitBy = omitBy;
+ lodash.once = once;
+ lodash.orderBy = orderBy;
+ lodash.over = over;
+ lodash.overArgs = overArgs;
+ lodash.overEvery = overEvery;
+ lodash.overSome = overSome;
+ lodash.partial = partial;
+ lodash.partialRight = partialRight;
+ lodash.partition = partition;
+ lodash.pick = pick;
+ lodash.pickBy = pickBy;
+ lodash.property = property;
+ lodash.propertyOf = propertyOf;
+ lodash.pull = pull;
+ lodash.pullAll = pullAll;
+ lodash.pullAllBy = pullAllBy;
+ lodash.pullAt = pullAt;
+ lodash.range = range;
+ lodash.rangeRight = rangeRight;
+ lodash.rearg = rearg;
+ lodash.reject = reject;
+ lodash.remove = remove;
+ lodash.rest = rest;
+ lodash.reverse = reverse;
+ lodash.sampleSize = sampleSize;
+ lodash.set = set;
+ lodash.setWith = setWith;
+ lodash.shuffle = shuffle;
+ lodash.slice = slice;
+ lodash.sortBy = sortBy;
+ lodash.sortedUniq = sortedUniq;
+ lodash.sortedUniqBy = sortedUniqBy;
+ lodash.split = split;
+ lodash.spread = spread;
+ lodash.tail = tail;
+ lodash.take = take;
+ lodash.takeRight = takeRight;
+ lodash.takeRightWhile = takeRightWhile;
+ lodash.takeWhile = takeWhile;
+ lodash.tap = tap;
+ lodash.throttle = throttle;
+ lodash.thru = thru;
+ lodash.toArray = toArray;
+ lodash.toPairs = toPairs;
+ lodash.toPairsIn = toPairsIn;
+ lodash.toPath = toPath;
+ lodash.toPlainObject = toPlainObject;
+ lodash.transform = transform;
+ lodash.unary = unary;
+ lodash.union = union;
+ lodash.unionBy = unionBy;
+ lodash.unionWith = unionWith;
+ lodash.uniq = uniq;
+ lodash.uniqBy = uniqBy;
+ lodash.uniqWith = uniqWith;
+ lodash.unset = unset;
+ lodash.unzip = unzip;
+ lodash.unzipWith = unzipWith;
+ lodash.values = values;
+ lodash.valuesIn = valuesIn;
+ lodash.without = without;
+ lodash.words = words;
+ lodash.wrap = wrap;
+ lodash.xor = xor;
+ lodash.xorBy = xorBy;
+ lodash.xorWith = xorWith;
+ lodash.zip = zip;
+ lodash.zipObject = zipObject;
+ lodash.zipObjectDeep = zipObjectDeep;
+ lodash.zipWith = zipWith;
+
+ // Add aliases.
+ lodash.extend = assignIn;
+ lodash.extendWith = assignInWith;
+
+ // Add functions to `lodash.prototype`.
+ mixin(lodash, lodash);
+
+ /*------------------------------------------------------------------------*/
+
+ // Add functions that return unwrapped values when chaining.
+ lodash.add = add;
+ lodash.attempt = attempt;
+ lodash.camelCase = camelCase;
+ lodash.capitalize = capitalize;
+ lodash.ceil = ceil;
+ lodash.clamp = clamp;
+ lodash.clone = clone;
+ lodash.cloneDeep = cloneDeep;
+ lodash.cloneDeepWith = cloneDeepWith;
+ lodash.cloneWith = cloneWith;
+ lodash.deburr = deburr;
+ lodash.endsWith = endsWith;
+ lodash.eq = eq;
+ lodash.escape = escape;
+ lodash.escapeRegExp = escapeRegExp;
+ lodash.every = every;
+ lodash.find = find;
+ lodash.findIndex = findIndex;
+ lodash.findKey = findKey;
+ lodash.findLast = findLast;
+ lodash.findLastIndex = findLastIndex;
+ lodash.findLastKey = findLastKey;
+ lodash.floor = floor;
+ lodash.forEach = forEach;
+ lodash.forEachRight = forEachRight;
+ lodash.forIn = forIn;
+ lodash.forInRight = forInRight;
+ lodash.forOwn = forOwn;
+ lodash.forOwnRight = forOwnRight;
+ lodash.get = get;
+ lodash.gt = gt;
+ lodash.gte = gte;
+ lodash.has = has;
+ lodash.hasIn = hasIn;
+ lodash.head = head;
+ lodash.identity = identity;
+ lodash.includes = includes;
+ lodash.indexOf = indexOf;
+ lodash.inRange = inRange;
+ lodash.invoke = invoke;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isArrayBuffer = isArrayBuffer;
+ lodash.isArrayLike = isArrayLike;
+ lodash.isArrayLikeObject = isArrayLikeObject;
+ lodash.isBoolean = isBoolean;
+ lodash.isBuffer = isBuffer;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isEqualWith = isEqualWith;
+ lodash.isError = isError;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isInteger = isInteger;
+ lodash.isLength = isLength;
+ lodash.isMap = isMap;
+ lodash.isMatch = isMatch;
+ lodash.isMatchWith = isMatchWith;
+ lodash.isNaN = isNaN;
+ lodash.isNative = isNative;
+ lodash.isNil = isNil;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isObjectLike = isObjectLike;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isSafeInteger = isSafeInteger;
+ lodash.isSet = isSet;
+ lodash.isString = isString;
+ lodash.isSymbol = isSymbol;
+ lodash.isTypedArray = isTypedArray;
+ lodash.isUndefined = isUndefined;
+ lodash.isWeakMap = isWeakMap;
+ lodash.isWeakSet = isWeakSet;
+ lodash.join = join;
+ lodash.kebabCase = kebabCase;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.lowerCase = lowerCase;
+ lodash.lowerFirst = lowerFirst;
+ lodash.lt = lt;
+ lodash.lte = lte;
+ lodash.max = max;
+ lodash.maxBy = maxBy;
+ lodash.mean = mean;
+ lodash.min = min;
+ lodash.minBy = minBy;
+ lodash.noConflict = noConflict;
+ lodash.noop = noop;
+ lodash.now = now;
+ lodash.pad = pad;
+ lodash.padEnd = padEnd;
+ lodash.padStart = padStart;
+ lodash.parseInt = parseInt;
+ lodash.random = random;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.repeat = repeat;
+ lodash.replace = replace;
+ lodash.result = result;
+ lodash.round = round;
+ lodash.runInContext = runInContext;
+ lodash.sample = sample;
+ lodash.size = size;
+ lodash.snakeCase = snakeCase;
+ lodash.some = some;
+ lodash.sortedIndex = sortedIndex;
+ lodash.sortedIndexBy = sortedIndexBy;
+ lodash.sortedIndexOf = sortedIndexOf;
+ lodash.sortedLastIndex = sortedLastIndex;
+ lodash.sortedLastIndexBy = sortedLastIndexBy;
+ lodash.sortedLastIndexOf = sortedLastIndexOf;
+ lodash.startCase = startCase;
+ lodash.startsWith = startsWith;
+ lodash.subtract = subtract;
+ lodash.sum = sum;
+ lodash.sumBy = sumBy;
+ lodash.template = template;
+ lodash.times = times;
+ lodash.toInteger = toInteger;
+ lodash.toLength = toLength;
+ lodash.toLower = toLower;
+ lodash.toNumber = toNumber;
+ lodash.toSafeInteger = toSafeInteger;
+ lodash.toString = toString;
+ lodash.toUpper = toUpper;
+ lodash.trim = trim;
+ lodash.trimEnd = trimEnd;
+ lodash.trimStart = trimStart;
+ lodash.truncate = truncate;
+ lodash.unescape = unescape;
+ lodash.uniqueId = uniqueId;
+ lodash.upperCase = upperCase;
+ lodash.upperFirst = upperFirst;
+
+ // Add aliases.
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
+ lodash.first = head;
+
+ mixin(lodash, (function() {
+ var source = {};
+ baseForOwn(lodash, function(func, methodName) {
+ if (!hasOwnProperty.call(lodash.prototype, methodName)) {
+ source[methodName] = func;
+ }
+ });
+ return source;
+ }()), { 'chain': false });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The semantic version number.
+ *
+ * @static
+ * @memberOf _
+ * @type {string}
+ */
+ lodash.VERSION = VERSION;
+
+ // Assign default placeholders.
+ arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
+ lodash[methodName].placeholder = lodash;
+ });
+
+ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
+ arrayEach(['drop', 'take'], function(methodName, index) {
+ LazyWrapper.prototype[methodName] = function(n) {
+ var filtered = this.__filtered__;
+ if (filtered && !index) {
+ return new LazyWrapper(this);
+ }
+ n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
+
+ var result = this.clone();
+ if (filtered) {
+ result.__takeCount__ = nativeMin(n, result.__takeCount__);
+ } else {
+ result.__views__.push({
+ 'size': nativeMin(n, MAX_ARRAY_LENGTH),
+ 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
+ });
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype[methodName + 'Right'] = function(n) {
+ return this.reverse()[methodName](n).reverse();
+ };
+ });
+
+ // Add `LazyWrapper` methods that accept an `iteratee` value.
+ arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
+ var type = index + 1,
+ isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
+
+ LazyWrapper.prototype[methodName] = function(iteratee) {
+ var result = this.clone();
+ result.__iteratees__.push({
+ 'iteratee': getIteratee(iteratee, 3),
+ 'type': type
+ });
+ result.__filtered__ = result.__filtered__ || isFilter;
+ return result;
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.head` and `_.last`.
+ arrayEach(['head', 'last'], function(methodName, index) {
+ var takeName = 'take' + (index ? 'Right' : '');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this[takeName](1).value()[0];
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
+ arrayEach(['initial', 'tail'], function(methodName, index) {
+ var dropName = 'drop' + (index ? '' : 'Right');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
+ };
+ });
+
+ LazyWrapper.prototype.compact = function() {
+ return this.filter(identity);
+ };
+
+ LazyWrapper.prototype.find = function(predicate) {
+ return this.filter(predicate).head();
+ };
+
+ LazyWrapper.prototype.findLast = function(predicate) {
+ return this.reverse().find(predicate);
+ };
+
+ LazyWrapper.prototype.invokeMap = rest(function(path, args) {
+ if (typeof path == 'function') {
+ return new LazyWrapper(this);
+ }
+ return this.map(function(value) {
+ return baseInvoke(value, path, args);
+ });
+ });
+
+ LazyWrapper.prototype.reject = function(predicate) {
+ predicate = getIteratee(predicate, 3);
+ return this.filter(function(value) {
+ return !predicate(value);
+ });
+ };
+
+ LazyWrapper.prototype.slice = function(start, end) {
+ start = toInteger(start);
+
+ var result = this;
+ if (result.__filtered__ && (start > 0 || end < 0)) {
+ return new LazyWrapper(result);
+ }
+ if (start < 0) {
+ result = result.takeRight(-start);
+ } else if (start) {
+ result = result.drop(start);
+ }
+ if (end !== undefined) {
+ end = toInteger(end);
+ result = end < 0 ? result.dropRight(-end) : result.take(end - start);
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype.takeRightWhile = function(predicate) {
+ return this.reverse().takeWhile(predicate).reverse();
+ };
+
+ LazyWrapper.prototype.toArray = function() {
+ return this.take(MAX_ARRAY_LENGTH);
+ };
+
+ // Add `LazyWrapper` methods to `lodash.prototype`.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
+ isTaker = /^(?:head|last)$/.test(methodName),
+ lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
+ retUnwrapped = isTaker || /^find/.test(methodName);
+
+ if (!lodashFunc) {
+ return;
+ }
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__,
+ args = isTaker ? [1] : arguments,
+ isLazy = value instanceof LazyWrapper,
+ iteratee = args[0],
+ useLazy = isLazy || isArray(value);
+
+ var interceptor = function(value) {
+ var result = lodashFunc.apply(lodash, arrayPush([value], args));
+ return (isTaker && chainAll) ? result[0] : result;
+ };
+
+ if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
+ // Avoid lazy use if the iteratee has a "length" value other than `1`.
+ isLazy = useLazy = false;
+ }
+ var chainAll = this.__chain__,
+ isHybrid = !!this.__actions__.length,
+ isUnwrapped = retUnwrapped && !chainAll,
+ onlyLazy = isLazy && !isHybrid;
+
+ if (!retUnwrapped && useLazy) {
+ value = onlyLazy ? value : new LazyWrapper(this);
+ var result = func.apply(value, args);
+ result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
+ return new LodashWrapper(result, chainAll);
+ }
+ if (isUnwrapped && onlyLazy) {
+ return func.apply(this, args);
+ }
+ result = this.thru(interceptor);
+ return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
+ };
+ });
+
+ // Add `Array` and `String` methods to `lodash.prototype`.
+ arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
+ var func = arrayProto[methodName],
+ chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
+ retUnwrapped = /^(?:pop|shift)$/.test(methodName);
+
+ lodash.prototype[methodName] = function() {
+ var args = arguments;
+ if (retUnwrapped && !this.__chain__) {
+ return func.apply(this.value(), args);
+ }
+ return this[chainName](function(value) {
+ return func.apply(value, args);
+ });
+ };
+ });
+
+ // Map minified function names to their real names.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var lodashFunc = lodash[methodName];
+ if (lodashFunc) {
+ var key = (lodashFunc.name + ''),
+ names = realNames[key] || (realNames[key] = []);
+
+ names.push({ 'name': methodName, 'func': lodashFunc });
+ }
+ });
+
+ realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
+ 'name': 'wrapper',
+ 'func': undefined
+ }];
+
+ // Add functions to the lazy wrapper.
+ LazyWrapper.prototype.clone = lazyClone;
+ LazyWrapper.prototype.reverse = lazyReverse;
+ LazyWrapper.prototype.value = lazyValue;
+
+ // Add chaining functions to the `lodash` wrapper.
+ lodash.prototype.at = wrapperAt;
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.commit = wrapperCommit;
+ lodash.prototype.flatMap = wrapperFlatMap;
+ lodash.prototype.next = wrapperNext;
+ lodash.prototype.plant = wrapperPlant;
+ lodash.prototype.reverse = wrapperReverse;
+ lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+
+ if (iteratorSymbol) {
+ lodash.prototype[iteratorSymbol] = wrapperToIterator;
+ }
+ return lodash;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export lodash.
+ var _ = runInContext();
+
+ // Expose lodash on the free variable `window` or `self` when available. This
+ // prevents errors in cases where lodash is loaded by a script tag in the presence
+ // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
+ (freeWindow || freeSelf || {})._ = _;
+
+ // Some AMD build optimizers like r.js check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Define as an anonymous module so, through path mapping, it can be
+ // referenced as the "underscore" module.
+ define(function() {
+ return _;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for Node.js.
+ if (moduleExports) {
+ (freeModule.exports = _)._ = _;
+ }
+ // Export for CommonJS support.
+ freeExports._ = _;
+ }
+ else {
+ // Export to the global object.
+ root._ = _;
+ }
+}.call(this));
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/images/blank.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/images/blank.gif
index 75b945d2..75b945d2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/images/blank.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/images/blank.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/scribble.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/scribble.css
new file mode 100644
index 00000000..9986f2ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/scribble.css
@@ -0,0 +1,40 @@
+#scribble-pad {
+/* margin-left:auto;
+ margin-right:auto;
+ height: 475px;
+ width: 475px;*/
+ background:url(https://www.ibm.com/developerworks/mydeveloperworks/blogs/bobleah/resource/stickynote.jpg) no-repeat center center;
+ background-size: 110% 110%;
+}
+
+
+
+#scribble {
+ white-space: pre-wrap; /* css-3 */
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
+ max-width: 300px;
+ padding: 120px 100px 100px 75px;
+ color: #486891;
+ border-color: #ff0000 #0000ff;
+ border-color: transparent;
+ background-color:rgba(0, 0, 0, 0);
+ font-family: Arial,sans-serif;
+ font-size: 120%;
+ font-style: italic;
+ font-weight:bold;
+ line-height: 1.5em;
+}
+
+#scribble:focus {
+outline-width: 0;
+}
+.c-link {
+ color: #486891;
+ font-family: Arial,sans-serif;
+ font-size: 95%;
+ font-weight:bold;
+ text-decoration: none;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/slider.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/slider.css
new file mode 100644
index 00000000..f609403c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/slider.css
@@ -0,0 +1,142 @@
+div,span,p { margin:0; padding:0; border:0; outline:0; font-weight:inherit; font-style:inherit; font-size:100%; font-family:inherit; vertical-align:baseline; }
+
+
+#container {
+ width:580px;
+ padding:10px;
+ margin:0 auto;
+ position:relative;
+ z-index:0;
+}
+
+#example {
+ width:600px;
+ height:350px;
+ position:relative;
+}
+
+#ribbon {
+ position:absolute;
+ top:-3px;
+ left:-15px;
+ z-index:500;
+}
+
+#frame {
+ position:absolute;
+ z-index:0;
+ width:739px;
+ height:341px;
+ top:-3px;
+ left:-80px;
+}
+
+/*
+ Slideshow
+*/
+
+#slides {
+ position:absolute;
+ top:15px;
+ left:4px;
+ z-index:100;
+}
+
+/*
+ Slides container
+ Important:
+ Set the width of your slides container
+ Set to display none, prevents content flash
+*/
+
+.slides_container {
+ width:570px;
+ overflow:hidden;
+ position:relative;
+ display:none;
+}
+
+/*
+ Each slide
+ Important:
+ Set the width of your slides
+ If height not specified height will be set by the slide content
+ Set to display block
+*/
+
+.slides_container div.slide {
+ width:570px;
+ height:270px;
+ display:block;
+}
+
+
+/*
+ Next/prev buttons
+*/
+
+#slides .next,#slides .prev {
+ position:absolute;
+ top:107px;
+ left:-39px;
+ width:24px;
+ height:43px;
+ display:block;
+ z-index:101;
+}
+
+#slides .next {
+ left:585px;
+}
+
+/*
+ Pagination
+*/
+
+.pagination {
+ margin:26px auto 0;
+ width:100px;
+}
+
+.pagination li {
+ float:left;
+ margin:0 1px;
+ list-style:none;
+}
+
+.pagination li a {
+ display:block;
+ width:12px;
+ height:0;
+ padding-top:12px;
+ background-image:url(../images/pagination.png);
+ background-position:0 0;
+ float:left;
+ overflow:hidden;
+}
+
+.pagination li.current a {
+ background-position:0 -12px;
+}
+
+/*
+ Caption
+*/
+
+.caption {
+ z-index:500;
+ position:absolute;
+ bottom:-35px;
+ left:0;
+ height:30px;
+ padding:5px 20px 0 20px;
+ background:#000;
+ background:rgba(0,0,0,.5);
+ width:540px;
+ font-size:1.3em;
+ line-height:1.33;
+ color:#fff;
+ border-top:1px solid #000;
+ text-shadow:none;
+}
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/spacegallery.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/spacegallery.css
new file mode 100644
index 00000000..ce4fd57c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/css/spacegallery.css
@@ -0,0 +1,18 @@
+.spacegallery {
+ position: relative;
+ overflow: hidden;
+}
+.spacegallery img {
+ position: absolute;
+ left: 50%;
+}
+.spacegallery a {
+ position: absolute;
+ z-index: 1000;
+ display: block;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: url(images/blank.gif);
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/area_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/area_chart.html
new file mode 100644
index 00000000..30ef2011
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/area_chart.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 175px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"line", "key": "AP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.13}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.36}, { "x":1388552400000 , "y":10.0}, { "x":1391230800000 , "y":3.15}, { "x":1391230800000 , "y":2.88}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":4.0}, { "x":1393650000000 , "y":8.0}, { "x":1393650000000 , "y":3.93}, { "x":1393650000000 , "y":4.27}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.25}, { "x":1396324800000 , "y":5.35}, { "x":1396324800000 , "y":5.92}, { "x":1396324800000 , "y":12.0}, { "x":1398916800000 , "y":5.55}, { "x":1398916800000 , "y":4.89}, { "x":1398916800000 , "y":5.01}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.27}, { "x":1401595200000 , "y":9.17}, { "x":1401595200000 , "y":9.31}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.37}, { "x":1404187200000 , "y":8.11}, { "x":1404187200000 , "y":8.84}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.79}, { "x":1406865600000 , "y":12.22}, { "x":1406865600000 , "y":12.6}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":15.27}, { "x":1409544000000 , "y":19.09}, { "x":1409544000000 , "y":16.09}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":18.4}, { "x":1412136000000 , "y":22.05}, { "x":1412136000000 , "y":21.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":19.13}, { "x":1414814400000 , "y":19.61}, { "x":1414814400000 , "y":17.61}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":19.0}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.67}, { "x":1420088400000 , "y":15.19}, { "x":1420088400000 , "y":15.02}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":16.95}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":12.9}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"line", "key": "ROUTER_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":3.0}, { "x":1388552400000 , "y":4.0}, { "x":1388552400000 , "y":4.89}, { "x":1388552400000 , "y":7.0}, { "x":1391230800000 , "y":4.57}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":7.0}, { "x":1393650000000 , "y":7.0}, { "x":1393650000000 , "y":4.18}, { "x":1393650000000 , "y":5.0}, { "x":1393650000000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.06}, { "x":1396324800000 , "y":6.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.09}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.0}, { "x":1404187200000 , "y":6.36}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1406865600000 , "y":7.0}, { "x":1406865600000 , "y":7.02}, { "x":1406865600000 , "y":7.24}, { "x":1406865600000 , "y":7.0}, { "x":1409544000000 , "y":8.23}, { "x":1409544000000 , "y":8.11}, { "x":1409544000000 , "y":8.12}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9.0}, { "x":1412136000000 , "y":8.93}, { "x":1412136000000 , "y":8.57}, { "x":1412136000000 , "y":9.0}, { "x":1414814400000 , "y":5.97}, { "x":1414814400000 , "y":6.0}, { "x":1414814400000 , "y":9.0}, { "x":1414814400000 , "y":9.0}, { "x":1417410000000 , "y":9.0}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":2.01}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2.67}, { "x":1422766800000 , "y":2.0}, { "x":1425186000000 , "y":2.8}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"line", "key": "SCTP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":7.0}, { "x":1388552400000 , "y":10.0}, { "x":1388552400000 , "y":8.27}, { "x":1388552400000 , "y":8.0}, { "x":1391230800000 , "y":10.02}, { "x":1391230800000 , "y":8.04}, { "x":1391230800000 , "y":9.0}, { "x":1391230800000 , "y":10.0}, { "x":1393650000000 , "y":12.0}, { "x":1393650000000 , "y":10.04}, { "x":1393650000000 , "y":11.16}, { "x":1393650000000 , "y":10.0}, { "x":1396324800000 , "y":10.7}, { "x":1396324800000 , "y":13.31}, { "x":1396324800000 , "y":12.73}, { "x":1396324800000 , "y":9.0}, { "x":1398916800000 , "y":12.41}, { "x":1398916800000 , "y":11.95}, { "x":1398916800000 , "y":12.82}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.28}, { "x":1401595200000 , "y":14.01}, { "x":1401595200000 , "y":14.63}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.06}, { "x":1404187200000 , "y":13.96}, { "x":1404187200000 , "y":14.66}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":16.6}, { "x":1406865600000 , "y":16.95}, { "x":1406865600000 , "y":17.11}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":19.86}, { "x":1409544000000 , "y":22.97}, { "x":1409544000000 , "y":21.56}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":22.66}, { "x":1412136000000 , "y":26.79}, { "x":1412136000000 , "y":26.54}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":21.0}, { "x":1414814400000 , "y":20.35}, { "x":1414814400000 , "y":21.93}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":24.0}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.63}, { "x":1420088400000 , "y":25.14}, { "x":1420088400000 , "y":21.85}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":26.3}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":23.3833333333333}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"line", "key": "DP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.0}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.17}, { "x":1388552400000 , "y":2.0}, { "x":1391230800000 , "y":3.01}, { "x":1391230800000 , "y":2.56}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":9.0}, { "x":1393650000000 , "y":10.0}, { "x":1393650000000 , "y":3.64}, { "x":1393650000000 , "y":4.06}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.04}, { "x":1396324800000 , "y":5.11}, { "x":1396324800000 , "y":5.9}, { "x":1396324800000 , "y":8.0}, { "x":1398916800000 , "y":5.08}, { "x":1398916800000 , "y":4.65}, { "x":1398916800000 , "y":4.74}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":6.13}, { "x":1401595200000 , "y":8.98}, { "x":1401595200000 , "y":9.22}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.12}, { "x":1404187200000 , "y":7.89}, { "x":1404187200000 , "y":8.41}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":11.06}, { "x":1406865600000 , "y":11.84}, { "x":1406865600000 , "y":11.92}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":14.58}, { "x":1409544000000 , "y":18.39}, { "x":1409544000000 , "y":15.5}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.01}, { "x":1412136000000 , "y":21.3}, { "x":1412136000000 , "y":21.11}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":18.59}, { "x":1414814400000 , "y":18.81}, { "x":1414814400000 , "y":17.13}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":18.0}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.16}, { "x":1420088400000 , "y":12.13}, { "x":1420088400000 , "y":11.76}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.47}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.2333333333333}, { "x":1425186000000 , "y":12.4} ] }
+];
+
+</script>
+<script src="js/area_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/bar_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/bar_chart.html
new file mode 100644
index 00000000..0be16ec1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/bar_chart.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 420px;
+ width: 700px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/tooltip.js"></script>
+<script src="../../d3/js/utils.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script src="../../d3/js/models/multiChart.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"bar", "key": "AP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":10}, { "x":1391230800000 , "y":4}, { "x":1393650000000 , "y":4}, { "x":1396324800000 , "y":12}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"bar", "key": "ROUTER_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":7}, { "x":1391230800000 , "y":7}, { "x":1393650000000 , "y":5}, { "x":1396324800000 , "y":6}, { "x":1398916800000 , "y":5}, { "x":1401595200000 , "y":6}, { "x":1404187200000 , "y":7}, { "x":1406865600000 , "y":7}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9}, { "x":1414814400000 , "y":9}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"bar", "key": "SCTP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":8}, { "x":1391230800000 , "y":10}, { "x":1393650000000 , "y":10}, { "x":1396324800000 , "y":9}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"bar", "key": "DP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":2}, { "x":1391230800000 , "y":9}, { "x":1393650000000 , "y":4}, { "x":1396324800000 , "y":8}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.4} ] }
+];
+var chart;
+nv.addGraph(function() {
+ chart = nv.models.multiBarChart()
+ .margin({top: 30, right: 60, bottom: 50, left: 100})
+ .showLegend(true)
+ .reduceXTicks(false)
+ .forceY([0, 34.0])
+ .showControls(true)
+ .stacked(false)
+ .logScale(false)
+ .legendPos('top')
+ .color(d3.scale.category10().range());
+ chart.xAxis
+ .tickValues([1388552400000,1391230800000,1393650000000,1396324800000,1398916800000,1401595200000,1404187200000,1406865600000,1409544000000,1412136000000,1414814400000,1417410000000,1420088400000,1422766800000])
+ .staggerLabels(false)
+ .showMaxMin(false)
+ .rotateLabels(90)
+ .axisLabel('Timestamp')
+ .tickFormat(function(d) {
+ return d3.time.format('%b %y')(new Date(d)) });
+ chart.yAxis
+ .logScale(false)
+ .axisLabel('')
+ .tickFormat(d3.format(',.1f'));
+ d3.select('#chart461 svg')
+ .datum(historicalBarChart)
+ .transition().duration(1000)
+ .call(chart);
+nv.utils.windowResize(chart.update);
+return chart;
+});
+function redraw() {
+ d3.select('#chart461 svg')
+ .datum(historicalBarChart)
+ .transition().duration(500)
+ .call(chart);
+}
+
+ setInterval(function () {
+ redraw();
+ }, 1500)
+if(historicalBarChart.length <= 0 ) {
+ document.getElementById("chart461").innerHTML = "<div id='noData'><b>No Data Available</b></div>";
+ document.getElementById("chart461").className="nodatadiv";
+ document.getElementById("nodata").className="nodatainner";
+}
+</script> </body></html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/busy_hour_traffic.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/busy_hour_traffic.html
new file mode 100644
index 00000000..54ff7849
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/busy_hour_traffic.html
@@ -0,0 +1,188 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html;charset=utf-8">
+
+<title>Busy hour traffic analysis by day of week</title>
+
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/scribble.css" />
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/flexslider.css" />
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/welcome.css" />
+<script src="../../../../../app/fusion/external/angular-1.4.8/angular.js"></script>
+<script src="../../../../../static/js/jquery-1.10.2.js"></script>
+<script src="../../../../fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
+<!--for line Chart and Area Chart-->
+<script src="../../../../../static/fusion/d3/js/d3.v3.min.js"></script>
+<script src="../../../../../static/fusion/d3/js/nv.d3.min.js"></script>
+<script src="../../../../../static/fusion/d3/js/models/axis.min.js"></script>
+<!-- Style for line Chart and area chart -->
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/d3/css/nv.d3.css">
+<script type="text/javascript" src="../../../../../static/fusion/sample/js/FusionCharts.js"></script>
+<script type="text/javascript" src="../../../../../static/fusion/sample/js/scribble.js"></script>
+<script>
+ var app = angular.module("myApp", []);
+ app.controller('trafficController',function($scope) {
+ $scope.BusyHourTraffic = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ url : '#Incoming'
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ url : '#BHNational'
+ }
+
+ ];
+ $scope.currentSelectedBusyHourTraffic = '#Incoming';
+ $scope.onClickTab2 = function (TrafficTab) {
+ $scope.currentSelectedBusyHourTraffic = TrafficTab.url;
+ }
+ $scope.isActiveTab2 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedBusyHourTraffic;
+ }
+ $scope.activeTabId2 = 'Incoming';
+ //for generic tabs
+ $scope.gTabs2 = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ id : 'Incoming',
+ url : '#Incoming',
+ selected : true
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ id : 'Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ id : 'Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ id : 'Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ id : 'BHNational',
+ url : '#BHNational'
+ }];
+
+ $scope.activeTabId3 = 'Incoming';
+ //for generic tabs
+ $scope.gTabs3 = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ id: 'Incoming',
+ url : '#Incoming',
+ selected : true
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ id : 'Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ id : 'Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ id : 'Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ id : 'BHNational',
+ url : '#BHNational'
+ }];
+ $scope.currentSelectedBusyHourTraffic = '#Incoming';
+ $scope.onClickTab2 = function (TrafficTab) {
+ $scope.currentSelectedBusyHourTraffic = TrafficTab.url;
+ }
+ $scope.isActiveTab2 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedBusyHourTraffic;
+ }
+ $scope.toggleEastToWest = function() {
+ $("#toggle").toggle('slide');
+ if ($("#leftIcon").is(":visible")) {
+ $("#rightIcon").show();
+ $("#leftIcon").hide();
+ }
+ else if ($("#rightIcon").is(":visible")) {
+ $("#rightIcon").hide();
+ $("#leftIcon").show();
+ }
+ };
+
+ $scope.group1 = {
+ open : true
+ };
+ $scope.group2 = {
+ open : true
+ };
+ $scope.group3 = {
+ open : true
+ };
+ $scope.group4 = {
+ open : true
+ };
+ $scope.group5 = {
+ open : true
+ };
+ $scope.group6 = {
+ open : true
+ };
+ $scope.group7 = {
+ open : true
+ };
+ $scope.group71 = {
+ open : true
+ };
+ $scope.group8 = {
+ open : true
+ };
+ $scope.group9 = {
+ open : true
+ };
+ $scope.group10 = {
+ open : true
+ };
+ $scope.group11 = {
+ open : true
+ };
+ $scope.group12 = {
+ open : false
+ };
+});
+</script>
+
+</head>
+ <body ng-app="myApp">
+ <div ng-controller="trafficController">
+ <div id = "BusyHourTraffic">
+ <ul>
+ <li ng-repeat="TrafficTab in BusyHourTraffic" ng-class="{active2:isActiveTab2(TrafficTab.url)}" ng-click="onClickTab2(TrafficTab)">{{TrafficTab.title}}</li>
+ </ul>
+ <div id = "BusyHourTrafficView">
+ <div ng-include="currentSelectedBusyHourTraffic"></div>
+ </div>
+ <script type="text/ng-template" id="#Incoming">
+ <div id="Incoming" align="left"><img src="../../../../../static/fusion/sample/images/tunnels/BH_DLSTX_IN.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#Outgoing">
+ <div id="Outgoing" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#Default">
+ <div id="Default" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/BH_Nat_Def.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#Priority">
+ <div id="Priority" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/BH_Nat_Priority.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#BHNational">
+ <div id="BHNational" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/BH_Nat.png" width=100% height=100%></div>
+ </script>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/d3_gauges_demo.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/d3_gauges_demo.html
new file mode 100644
index 00000000..94596e73
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/d3_gauges_demo.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>d3.js gauges</title>
+
+ <style>
+
+ body
+ {
+ font: 10px arial;
+ }
+
+ </style>
+
+ <script src="../../d3/js/d3.v3.min.js" charset="utf-8"></script>
+
+
+ <script>
+
+ var dataURL = "data/speedometer2.csv";
+ var gauges = [];
+ var recordLength = 0;
+ var dataset ;
+
+ </script>
+ <script type="text/javascript" src="js/gauges.min.js"></script>
+
+ </head>
+
+ <body onload="initialize()">
+ <span id="Bedminster"></span>
+ <span id="Piscataway"></span>
+ <br/>
+ <span id="Middletown"></span>
+ <span id="Paramus"></span>
+ </body>
+
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer2.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer2.csv
new file mode 100644
index 00000000..406143ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer2.csv
@@ -0,0 +1,16 @@
+"YEARMONTH","Bedminster","Piscataway","Middletown","Paramus"
+"201401",8.27,4.89,2.36,2.17
+"201402",10.02,4.57,3.15,3.01
+"201403",11.16,5.00,4.27,4.06
+"201404",13.31,5.00,5.35,5.11
+"201405",12.82,5.00,5.01,4.74
+"201406",14.01,6.09,9.17,8.98
+"201407",14.66,7.00,8.84,8.41
+"201408",16.95,7.02,12.22,11.84
+"201409",21.56,8.12,16.09,15.50
+"201410",25.35,9.00,19.04,18.37
+"201411",21.93,9.00,17.61,17.13
+"201412",24.00,9.00,19.00,18.00
+"201501",25.14,2.01,15.19,12.13
+"201502",26.30,2.67,16.95,13.47
+"201503",26.5833333333333,45.63333333333333,16.1166666666667,12.40
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer3.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer3.csv
new file mode 100644
index 00000000..046383e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/speedometer3.csv
@@ -0,0 +1,2 @@
+"YEARMONTH","Bedminster","Piscataway","Middletown","Paramus"
+"201401",8.27,4.89,2.36,2.17 \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/worddata.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/worddata.csv
index 6a74cded..6a74cded 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/data/worddata.csv
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/data/worddata.csv
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/donut_d3.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/donut_d3.html
new file mode 100644
index 00000000..afcac359
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/donut_d3.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+
+body {
+ font: 10px sans-serif;
+}
+
+svg {
+ padding: 10px 0 0 10px;
+}
+
+.arc {
+ stroke: #fff;
+}
+
+ .slice text {
+ font-size: 16pt;
+ font-family: Arial;
+ }
+</style>
+<body>
+<script src="../../d3/js/d3.js"></script>
+
+<script>
+
+var radius = 74,
+ padding = 10;
+
+var width = 200,
+ height = 200;
+
+var outerRadius = height / 2 - 20,
+ innerRadius = outerRadius / 3,
+ cornerRadius = 10;
+//var color = d3.scale.ordinal()
+ // .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
+ var color = d3.scale.category10();
+ var dataURL = "data/speedometer3.csv";
+
+
+</script>
+<script src="js/donut.min.js"></script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/area_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/area_chart.min.js
new file mode 100644
index 00000000..9b3decb9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/area_chart.min.js
@@ -0,0 +1 @@
+function redrawAreaChart(){d3.select("#areaChart svg").datum(historicalBarChart).call(area_chart)}var area_chart;nv.addGraph(function(){return area_chart=nv.models.stackedAreaChart().showControls(!1).margin({top:30,right:60,bottom:50,left:100}).showLegend(!1).yAxisTooltipFormat(d3.format(",.1f")).x(function(a){return a.x}).y(function(a){return a.y}).color(d3.scale.category10().range()),area_chart.xAxis.axisLabel("").staggerLabels(!1).showMaxMin(!1).rotateLabels(90).tickFormat(function(a){return d3.time.format("%b %y")(new Date(a))}),area_chart.yAxis.axisLabel("").tickFormat(d3.format(",.1f")),d3.select("#areaChart svg").datum(historicalBarChart).call(area_chart),nv.utils.windowResize(area_chart.update),area_chart}),redrawAreaChart(),historicalBarChart.length<=0&&(document.getElementById("areaChart").innerHTML="<div id='noData'><b>No Data Available</b></div>",document.getElementById("areaChart").className="nodatadiv",document.getElementById("nodata").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/donut.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/donut.min.js
new file mode 100644
index 00000000..60c4fd4b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/donut.min.js
@@ -0,0 +1 @@
+function angle(t){var e=90*(t.startAngle+t.endAngle)/Math.PI-90;return e>90?e-180:e}function arcTween(t,e){return function(){d3.select(this).transition().delay(e).attrTween("d",function(e){var r=d3.interpolate(e.outerRadius,t);return function(t){return e.outerRadius=r(t),arc(e)}})}}var arc=d3.svg.arc().padRadius(outerRadius).innerRadius(innerRadius),pie=d3.layout.pie().sort(null).padAngle(.02).value(function(t){return t.performance});d3.csv(dataURL,function(t,e){color.domain(d3.keys(e[0]).filter(function(t){return"YEARMONTH"!==t})),e.forEach(function(t){t.performance=color.domain().map(function(e){return{name:e,performance:+t[e]}})});var r=d3.select("body").append("svg").attr("class","legend").attr("width",radius).attr("height",2*radius).selectAll("g").data(color.domain().slice().reverse()).enter().append("g").attr("transform",function(t,e){return"translate(0,"+20*e+")"});r.append("rect").attr("width",18).attr("height",18).style("fill",color),r.append("text").attr("x",24).attr("y",9).attr("dy",".35em").text(function(t){return t});var a=d3.select("body").append("svg").attr("width",width).attr("height",height).data(e).append("g").attr("transform","translate("+radius+","+height/2+")"),n=a.selectAll("g.slice").data(function(t){return pie(t.performance)}).enter().append("g").attr("class","slice");n.append("path").each(function(t){t.outerRadius=outerRadius-10}).attr("class","arc").attr("d",arc).style("fill",function(t){return color(t.data.name)}).on("mouseover",arcTween(outerRadius,0)).on("mouseout",arcTween(outerRadius-10,150)),n.append("text").attr("dy",".35em").attr("transform",function(t){return t.outerRadius=outerRadius,t.innerRadius=outerRadius/2,"translate("+arc.centroid(t)+")rotate("+angle(t)+")"}).attr("text-anchor","middle").style("fill","white").style("font","bold 12px Arial").text(function(t){return t.value}),a.append("text").attr("dy",".35em").style("text-anchor","middle").text(function(t){return t.YEARMONTH})}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/gauges.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/gauges.min.js
new file mode 100644
index 00000000..c0fd7484
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/gauges.min.js
@@ -0,0 +1 @@
+function Gauge(t,i){this.placeholderName=t;var n=this;this.configure=function(t){this.config=t,this.config.size=.9*this.config.size,this.config.raduis=.97*this.config.size/2,this.config.cx=this.config.size/2,this.config.cy=this.config.size/2,this.config.min=void 0!=t.min?t.min:0,this.config.max=void 0!=t.max?t.max:100,this.config.range=this.config.max-this.config.min,this.config.majorTicks=t.majorTicks||5,this.config.minorTicks=t.minorTicks||2,this.config.greenColor=t.greenColor||"#109618",this.config.yellowColor=t.yellowColor||"#FF9900",this.config.redColor=t.redColor||"#DC3912",this.config.transitionDuration=t.transitionDuration||500},this.render=function(){this.body=d3.select("#"+this.placeholderName).append("svg:svg").attr("class","gauge").attr("width",this.config.size).attr("height",this.config.size),this.body.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",this.config.raduis).style("fill","#ccc").style("stroke","#000").style("stroke-width","0.5px"),this.body.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",.9*this.config.raduis).style("fill","#fff").style("stroke","#e0e0e0").style("stroke-width","2px");for(var t in this.config.greenZones)this.drawBand(this.config.greenZones[t].from,this.config.greenZones[t].to,n.config.greenColor);for(var t in this.config.yellowZones)this.drawBand(this.config.yellowZones[t].from,this.config.yellowZones[t].to,n.config.yellowColor);for(var t in this.config.redZones)this.drawBand(this.config.redZones[t].from,this.config.redZones[t].to,n.config.redColor);if(void 0!=this.config.label){var i=Math.round(this.config.size/12);this.body.append("svg:text").attr("x",this.config.cx).attr("y",this.config.cy/2+i/2).attr("dy",i/2).attr("text-anchor","middle").text(this.config.label).style("font-size",i+"px").style("fill","#333").style("stroke-width","0px")}for(var i=Math.round(this.config.size/16),e=this.config.range/(this.config.majorTicks-1),o=this.config.min;o<=this.config.max;o+=e){for(var a=e/this.config.minorTicks,r=o+a;r<Math.min(o+e,this.config.max);r+=a){var s=this.valueToPoint(r,.75),c=this.valueToPoint(r,.85);this.body.append("svg:line").attr("x1",s.x).attr("y1",s.y).attr("x2",c.x).attr("y2",c.y).style("stroke","#666").style("stroke-width","1px")}var s=this.valueToPoint(o,.7),c=this.valueToPoint(o,.85);if(this.body.append("svg:line").attr("x1",s.x).attr("y1",s.y).attr("x2",c.x).attr("y2",c.y).style("stroke","#333").style("stroke-width","2px"),o==this.config.min||o==this.config.max){var g=this.valueToPoint(o,.63);this.body.append("svg:text").attr("x",g.x).attr("y",g.y).attr("dy",i/3).attr("text-anchor",o==this.config.min?"start":"end").text(o).style("font-size",i+"px").style("fill","#333").style("stroke-width","0px")}}var f=this.body.append("svg:g").attr("class","pointerContainer"),h=(this.config.min+this.config.max)/2,l=this.buildPointerPath(h),d=d3.svg.line().x(function(t){return t.x}).y(function(t){return t.y}).interpolate("basis");f.selectAll("path").data([l]).enter().append("svg:path").attr("d",d).style("fill","#dc3912").style("stroke","#c63310").style("fill-opacity",.7),f.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",.12*this.config.raduis).style("fill","#4684EE").style("stroke","#666").style("opacity",1);var i=Math.round(this.config.size/10);f.selectAll("text").data([h]).enter().append("svg:text").attr("x",this.config.cx).attr("y",this.config.size-this.config.cy/4-i).attr("dy",i/2).attr("text-anchor","middle").style("font-size",i+"px").style("fill","#000").style("stroke-width","0px"),this.redraw(this.config.min,0)},this.buildPointerPath=function(t){function i(t,i){var e=n.valueToPoint(t,i);return e.x-=n.config.cx,e.y-=n.config.cy,e}var e=this.config.range/13,o=i(t,.85),a=i(t-e,.12),r=i(t+e,.12),s=t-this.config.range*(1/.75)/2,c=i(s,.28),g=i(s-e,.12),f=i(s+e,.12);return[o,a,f,c,g,r,o]},this.drawBand=function(t,i,e){0>=i-t||this.body.append("svg:path").style("fill",e).attr("d",d3.svg.arc().startAngle(this.valueToRadians(t)).endAngle(this.valueToRadians(i)).innerRadius(.65*this.config.raduis).outerRadius(.85*this.config.raduis)).attr("transform",function(){return"translate("+n.config.cx+", "+n.config.cy+") rotate(270)"})},this.redraw=function(t,i,e){var o=this.body.select(".pointerContainer"),a=o.selectAll("text");y=a.attr("y"),dy=parseFloat(a.attr("dy")),a.selectAll("tspan").remove(),a.append("tspan").attr("x",45).attr("dy",0).text(Math.round(t)),a.append("tspan").attr("x",45).attr("dy",10).text(i),o.selectAll("text").style("fill",function(){var i=n.config.max-n.config.min;return Math.round(t)>.9*i?"#DC3912":Math.round(t)>.5*i&&Math.round(t)<.9*i?"#FF9900":"#000000"});var r=o.selectAll("path");r.transition().duration(void 0!=e?e:this.config.transitionDuration).attrTween("transform",function(){var i=t;t>n.config.max?i=n.config.max+.02*n.config.range:t<n.config.min&&(i=n.config.min-.02*n.config.range);var e=n.valueToDegrees(i)-90,o=n._currentRotation||e;return n._currentRotation=e,function(t){var i=o+(e-o)*t;return"translate("+n.config.cx+", "+n.config.cy+") rotate("+i+")"}})},this.valueToDegrees=function(t){return t/this.config.range*270-(this.config.min/this.config.range*270+45)},this.valueToRadians=function(t){return this.valueToDegrees(t)*Math.PI/180},this.valueToPoint=function(t,i){return{x:this.config.cx-this.config.raduis*i*Math.cos(this.valueToRadians(t)),y:this.config.cy-this.config.raduis*i*Math.sin(this.valueToRadians(t))}},this.configure(i)}function createGauge(t,i,n,e){var o={size:100,label:i,min:void 0!=n?n:0,max:void 0!=e?e:100,minorTicks:5},a=o.max-o.min;o.yellowZones=[{from:o.min+.5*a,to:o.min+.9*a}],o.redZones=[{from:o.min+.9*a,to:o.max}],gauges[t]=new Gauge(t,o),gauges[t].render()}function createGauges(){createGauge("Bedminster","Bedminster",0,50),createGauge("Piscataway","Piscataway",0,50),createGauge("Middletown","Middletown",0,50),createGauge("Paramus","Paramus",0,50)}function updateGauges(t){for(var i in gauges){var n=getValue(i,t),e=getDate1(i,t);n&&gauges[i].redraw(n,e,100)}}function getValue(gauge_id,index){var d=dataset[index];return eval("d."+gauge_id)}function getDate1(t,i){var n=dataset[i];return n.YEARMONTH}function getROUTER_CPU_Value(t){d3.csv(dataURL,function(i){i.forEach(function(i,n){return n==t?i.ROUTER_CPU:void 0})})}function getAP_CPU_Value(t){d3.csv(dataURL,function(i){i.forEach(function(i,n){return n==t?i.AP_CPU:void 0})})}function updateData(){for(var t=0;t<recordLength;t++);}function initialize(){createGauges(),d3.csv(dataURL,function(t){dataset=t,recordLength=t.length,dataset.some(function(t,i){return 1==i?(updateGauges(i),1==i):void 0});var i=1e3,n=2,e=function(){return function(){return updateGauges(n++),n<recordLength?(d3.timer(e(),i),!0):(n=0,d3.timer(e(),i),!0)}};d3.timer(e(),i)})} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/line_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/line_chart.min.js
new file mode 100644
index 00000000..e501260b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/line_chart.min.js
@@ -0,0 +1 @@
+function redrawLineChart(){d3.select("#lineChart svg").datum(historicalBarChart).call(line_chart)}var line_chart;nv.addGraph(function(){return line_chart=nv.models.multiChart().dualaxis(!1).legendPos("top").margin({top:30,right:60,bottom:50,left:100}).showLegend(!1).color(d3.scale.category10().range()),line_chart.lines1.forceY([0,34]),line_chart.lines2.forceY([0,1]),line_chart.xAxis.axisLabel("").staggerLabels(!1).showMaxMin(!1).rotateLabels(90).tickFormat(function(a){return d3.time.format("%b %y")(new Date(a))}),line_chart.yAxis1.axisLabel("").tickFormat(d3.format(",.1f")),d3.select("#lineChart svg").datum(historicalBarChart).call(line_chart),nv.utils.windowResize(line_chart.update),line_chart}),redrawLineChart(),historicalBarChart.length<=0&&(document.getElementById("lineChart").innerHTML="<div id='noData2'><b>No Data Available</b></div>",document.getElementById("lineChart").className="nodatadiv",document.getElementById("nodata2").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/pie_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/pie_chart.min.js
new file mode 100644
index 00000000..f78eec70
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/pie_chart.min.js
@@ -0,0 +1 @@
+function redraw(){d3.select("#chart423 svg").datum(historicalBarChart).transition().duration(500).call(chart)}var chart;nv.addGraph(function(){return chart=nv.models.pieChart().margin({top:30,right:60,bottom:50,left:100}).x(function(t){return t.key}).y(function(t){return t.y}),chart.showLegend(!1),d3.select("#chart423 svg").datum(historicalBarChart).transition().duration(1200).call(chart),nv.utils.windowResize(chart.update),chart}),setInterval(function(){redraw()},1500),historicalBarChart.length<=0&&(document.getElementById("chart423").innerHTML="<div id='noData'><b>No Data Available</b></div>",document.getElementById("chart423").className="nodatadiv",document.getElementById("nodata").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/worddata.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/worddata.min.js
new file mode 100644
index 00000000..6b827460
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/js/worddata.min.js
@@ -0,0 +1 @@
+function dataViz(t){function e(t){var e=d3.select("svg").append("g").attr("id","wordCloudG").attr("transform","translate(210,175)");e.selectAll("text").data(t).enter().append("text").style("font-size",function(t){return 1*t.size+"px"}).style("fill",function(t){return keywords.indexOf(t.text)>-1?"red":"black"}).style("opacity",.75).attr("text-anchor","middle").attr("transform",function(t){return"translate("+[t.x,t.y]+")rotate("+t.rotate+")"}).text(function(t){return t.text})}d3.layout.cloud().size([420,350]).words(t).rotate(function(t){return t.text.length>5?0:90}).fontSize(function(t){return wordScale(t.frequency)}).on("end",e).start()}d3.csv(dataURL,function(t){dataViz(t)}),wordScale=d3.scale.linear().domain([0,100]).range([0,70]).clamp(!0); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/line_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/line_chart.html
new file mode 100644
index 00000000..d4ba57a4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/line_chart.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 175px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"line", "key": "AP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.13}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.36}, { "x":1388552400000 , "y":10.0}, { "x":1391230800000 , "y":3.15}, { "x":1391230800000 , "y":2.88}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":4.0}, { "x":1393650000000 , "y":8.0}, { "x":1393650000000 , "y":3.93}, { "x":1393650000000 , "y":4.27}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.25}, { "x":1396324800000 , "y":5.35}, { "x":1396324800000 , "y":5.92}, { "x":1396324800000 , "y":12.0}, { "x":1398916800000 , "y":5.55}, { "x":1398916800000 , "y":4.89}, { "x":1398916800000 , "y":5.01}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.27}, { "x":1401595200000 , "y":9.17}, { "x":1401595200000 , "y":9.31}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.37}, { "x":1404187200000 , "y":8.11}, { "x":1404187200000 , "y":8.84}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.79}, { "x":1406865600000 , "y":12.22}, { "x":1406865600000 , "y":12.6}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":15.27}, { "x":1409544000000 , "y":19.09}, { "x":1409544000000 , "y":16.09}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":18.4}, { "x":1412136000000 , "y":22.05}, { "x":1412136000000 , "y":21.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":19.13}, { "x":1414814400000 , "y":19.61}, { "x":1414814400000 , "y":17.61}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":19.0}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.67}, { "x":1420088400000 , "y":15.19}, { "x":1420088400000 , "y":15.02}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":16.95}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":12.9}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"line", "key": "ROUTER_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":3.0}, { "x":1388552400000 , "y":4.0}, { "x":1388552400000 , "y":4.89}, { "x":1388552400000 , "y":7.0}, { "x":1391230800000 , "y":4.57}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":7.0}, { "x":1393650000000 , "y":7.0}, { "x":1393650000000 , "y":4.18}, { "x":1393650000000 , "y":5.0}, { "x":1393650000000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.06}, { "x":1396324800000 , "y":6.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.09}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.0}, { "x":1404187200000 , "y":6.36}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1406865600000 , "y":7.0}, { "x":1406865600000 , "y":7.02}, { "x":1406865600000 , "y":7.24}, { "x":1406865600000 , "y":7.0}, { "x":1409544000000 , "y":8.23}, { "x":1409544000000 , "y":8.11}, { "x":1409544000000 , "y":8.12}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9.0}, { "x":1412136000000 , "y":8.93}, { "x":1412136000000 , "y":8.57}, { "x":1412136000000 , "y":9.0}, { "x":1414814400000 , "y":5.97}, { "x":1414814400000 , "y":6.0}, { "x":1414814400000 , "y":9.0}, { "x":1414814400000 , "y":9.0}, { "x":1417410000000 , "y":9.0}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":2.01}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2.67}, { "x":1422766800000 , "y":2.0}, { "x":1425186000000 , "y":2.8}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"line", "key": "SCTP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":7.0}, { "x":1388552400000 , "y":10.0}, { "x":1388552400000 , "y":8.27}, { "x":1388552400000 , "y":8.0}, { "x":1391230800000 , "y":10.02}, { "x":1391230800000 , "y":8.04}, { "x":1391230800000 , "y":9.0}, { "x":1391230800000 , "y":10.0}, { "x":1393650000000 , "y":12.0}, { "x":1393650000000 , "y":10.04}, { "x":1393650000000 , "y":11.16}, { "x":1393650000000 , "y":10.0}, { "x":1396324800000 , "y":10.7}, { "x":1396324800000 , "y":13.31}, { "x":1396324800000 , "y":12.73}, { "x":1396324800000 , "y":9.0}, { "x":1398916800000 , "y":12.41}, { "x":1398916800000 , "y":11.95}, { "x":1398916800000 , "y":12.82}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.28}, { "x":1401595200000 , "y":14.01}, { "x":1401595200000 , "y":14.63}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.06}, { "x":1404187200000 , "y":13.96}, { "x":1404187200000 , "y":14.66}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":16.6}, { "x":1406865600000 , "y":16.95}, { "x":1406865600000 , "y":17.11}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":19.86}, { "x":1409544000000 , "y":22.97}, { "x":1409544000000 , "y":21.56}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":22.66}, { "x":1412136000000 , "y":26.79}, { "x":1412136000000 , "y":26.54}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":21.0}, { "x":1414814400000 , "y":20.35}, { "x":1414814400000 , "y":21.93}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":24.0}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.63}, { "x":1420088400000 , "y":25.14}, { "x":1420088400000 , "y":21.85}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":26.3}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":23.3833333333333}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"line", "key": "DP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.0}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.17}, { "x":1388552400000 , "y":2.0}, { "x":1391230800000 , "y":3.01}, { "x":1391230800000 , "y":2.56}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":9.0}, { "x":1393650000000 , "y":10.0}, { "x":1393650000000 , "y":3.64}, { "x":1393650000000 , "y":4.06}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.04}, { "x":1396324800000 , "y":5.11}, { "x":1396324800000 , "y":5.9}, { "x":1396324800000 , "y":8.0}, { "x":1398916800000 , "y":5.08}, { "x":1398916800000 , "y":4.65}, { "x":1398916800000 , "y":4.74}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":6.13}, { "x":1401595200000 , "y":8.98}, { "x":1401595200000 , "y":9.22}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.12}, { "x":1404187200000 , "y":7.89}, { "x":1404187200000 , "y":8.41}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":11.06}, { "x":1406865600000 , "y":11.84}, { "x":1406865600000 , "y":11.92}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":14.58}, { "x":1409544000000 , "y":18.39}, { "x":1409544000000 , "y":15.5}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.01}, { "x":1412136000000 , "y":21.3}, { "x":1412136000000 , "y":21.11}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":18.59}, { "x":1414814400000 , "y":18.81}, { "x":1414814400000 , "y":17.13}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":18.0}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.16}, { "x":1420088400000 , "y":12.13}, { "x":1420088400000 , "y":11.76}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.47}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.2333333333333}, { "x":1425186000000 , "y":12.4} ] }
+];
+
+</script>
+<script src="js/line_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/pie_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/pie_chart.html
new file mode 100644
index 00000000..ebbdd9c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/pie_chart.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); } svg { display: block; } #chart423 svg {
+ height: 275px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ </style>
+<body>
+<div id="chart423"><svg></svg></div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/legend.js"></script>
+<script src="../../d3/js/models/pie.js"></script>
+<script src="../../d3/js/models/pieChart.js"></script>
+<script src="../../d3/js/utils.js"></script>
+<script>
+historicalBarChart = [
+{ "key":"Bedminster", "y":8.27},
+{ "key":"Middletown", "y":2.36},
+{ "key":"Paramus", "y":2.17},
+{ "key":"Piscataway", "y":4.89}
+];
+
+</script>
+<script src="js/pie_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/traffic_distribution.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/traffic_distribution.html
new file mode 100644
index 00000000..0b196bae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/traffic_distribution.html
@@ -0,0 +1,205 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html;charset=utf-8">
+
+<title>Traffic distribution by day of week</title>
+
+<script src="../../d3/js/d3.v3.min.js" charset="utf-8"></script>
+
+
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/scribble.css" />
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/flexslider.css" />
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/sample/css/welcome.css" />
+
+<script src="../../../../../app/fusion/external/angular-1.4.8/angular.js"></script>
+
+<script src="../../../../../static/js/jquery-1.10.2.js"></script>
+<script src="../../../../fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
+
+
+<!--for line Chart and Area Chart-->
+<script src="../../../../../static/fusion/d3/js/d3.v3.min.js"></script>
+<script src="../../../../../static/fusion/d3/js/nv.d3.min.js"></script>
+<script src="../../../../../static/fusion/d3/js/models/axis.min.js"></script>
+
+<!-- Style for line Chart and area chart -->
+<link rel="stylesheet" type="text/css" href="../../../../../static/fusion/d3/css/nv.d3.css">
+<!-- Charts -->
+<script type="text/javascript" src="../../../../../static/fusion/sample/js/charts.js"></script>
+<!-- Charts -->
+<script type="text/javascript" src="../../../../../static/fusion/sample/js/scribble.js"></script>
+
+
+<script>
+ var app = angular.module("myApp", []);
+ app.controller('trafficController',function($scope) {
+ $scope.activeTabId = 'Monday';
+ $scope.selectedTrafficDay = [{
+ title : 'Mon',
+ url : '#Monday'
+ }, {
+ title : 'Tue',
+ url : '#Tuesday'
+ }, {
+ title : 'Wed',
+ url : '#Wednesday'
+ }, {
+ title : 'Thu',
+ url : '#Thursday'
+ }, {
+ title : 'Fri',
+ url : '#Friday'
+ }, {
+ title : 'Sat',
+ url : '#Saturday'
+ }, {
+ title : 'Sun',
+ url : '#Sunday'
+ }];
+
+ $scope.currentSelectedDayTab = '#Monday';
+
+ $scope.onClickTab1 = function (Daytab) {
+ $scope.currentSelectedDayTab = Daytab.url;
+ }
+
+ $scope.isActiveTab1 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedDayTab;
+ }
+
+
+ $scope.gTabs = [ {
+ title : 'Monday',
+ id : 'Monday',
+ url : '#Monday',
+ selected : true
+ }, {
+ title : 'Tuesday',
+ id : 'Tuesday',
+ url : '#Tuesday'
+ }, {
+ title : 'Wednesday',
+ id : 'Wednesday',
+ url : '#Wednesday'
+ }, {
+ title : 'Thursday',
+ id : 'Thursday',
+ url : '#Thursday'
+ }, {
+ title : 'Friday',
+ id : 'Friday',
+ url : '#Friday'
+ }, {
+ title : 'Saturday',
+ id : 'Saturday',
+ url : '#Saturday'
+ }, {
+ title : 'Sunday',
+ id : 'Sunday',
+ url : '#Sunday'
+ }];
+
+
+
+
+
+ $scope.currentSelectedBusyHourTraffic = '#Incoming';
+
+ $scope.onClickTab2 = function (TrafficTab) {
+ $scope.currentSelectedBusyHourTraffic = TrafficTab.url;
+ }
+
+ $scope.isActiveTab2 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedBusyHourTraffic;
+ }
+
+ $scope.toggleEastToWest = function() {
+ $("#toggle").toggle('slide');
+ if ($("#leftIcon").is(":visible")) {
+ $("#rightIcon").show();
+ $("#leftIcon").hide();
+ }
+ else if ($("#rightIcon").is(":visible")) {
+ $("#rightIcon").hide();
+ $("#leftIcon").show();
+ }
+ };
+
+ $scope.group1 = {
+ open : true
+ };
+ $scope.group2 = {
+ open : true
+ };
+ $scope.group3 = {
+ open : true
+ };
+ $scope.group4 = {
+ open : true
+ };
+ $scope.group5 = {
+ open : true
+ };
+ $scope.group6 = {
+ open : true
+ };
+ $scope.group7 = {
+ open : true
+ };
+ $scope.group71 = {
+ open : true
+ };
+ $scope.group8 = {
+ open : true
+ };
+ $scope.group9 = {
+ open : true
+ };
+ $scope.group10 = {
+ open : true
+ };
+ $scope.group11 = {
+ open : true
+ };
+ $scope.group12 = {
+ open : false
+ };
+ });
+</script>
+
+</head>
+ <body ng-app="myApp">
+ <div ng-controller="trafficController">
+ <div id="selectedTrafficDay">
+ <ul>
+ <li ng-repeat="Daytab in selectedTrafficDay" ng-class="{active1:isActiveTab1(Daytab.url)}" ng-click="onClickTab1(Daytab)">{{Daytab.title}}</li>
+ </ul>
+ <div id="SelectedTrafficeDayView">
+ <div ng-include="currentSelectedDayTab"></div>
+ </div>
+ <script type="text/ng-template" id="#Monday">
+ <div id="Monday" align="centers"><img src="../../../../../static/fusion/sample/images/tunnels/1_mon.png" width=100% height=100% alt="Monday"></div>
+ </script>
+ <script type="text/ng-template" id="#Tuesday">
+ <div id="Tuesday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/2_tue.png" width=100% height=100% alt="Tuesday"></div>
+ </script>
+ <script type="text/ng-template" id="#Wednesday">
+ <div id="Wednesday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/3_wed.png" width=100% height=100% alt="Wednesday"></div>
+ </script>
+ <script type="text/ng-template" id="#Thursday">
+ <div id="Thursday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/4_thu.png" width=100% height=100% alt="Thursday"></div>
+ </script>
+ <script type="text/ng-template" id="#Friday">
+ <div id="Friday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/5_fri.png" width=100% height=100% alt="Friday"></div>
+ </script>
+ <script type="text/ng-template" id="#Saturday">
+ <div id="Saturday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/6_sat.png" width=100% height=100% alt="Saturday"></div>
+ </script>
+ <script type="text/ng-template" id="#Sunday">
+ <div id="Sunday" align="center"><img src="../../../../../static/fusion/sample/images/tunnels/7_sun.png" width=100% height=100% alt="Sunday"></div>
+ </script>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/wordcloud.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/wordcloud.html
index d9fc53fb..d9fc53fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/html/wordcloud.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/html/wordcloud.html
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/Calendar-16x16.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/Calendar-16x16.png
new file mode 100644
index 00000000..ac970bda
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/Calendar-16x16.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-next.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-next.png
index 1a4f72c6..1a4f72c6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-next.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-next.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-prev.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-prev.png
index 8211eba1..8211eba1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/arrow-prev.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/arrow-prev.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_drive_test_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_drive_test_map.png
new file mode 100644
index 00000000..78a8873b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_drive_test_map.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_county.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_county.png
new file mode 100644
index 00000000..df471d7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_county.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_regression.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_regression.png
new file mode 100644
index 00000000..e59fc189
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_eppt_regression.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_ios_throughput.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_ios_throughput.png
new file mode 100644
index 00000000..76a2d2b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_ios_throughput.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map.png
new file mode 100644
index 00000000..174ef9b8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map_legend.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map_legend.png
new file mode 100644
index 00000000..f7f2719a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_lata_map_legend.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_nova_sdn_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_nova_sdn_map.png
new file mode 100644
index 00000000..ee0ddef9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/carousel/slide_b_nova_sdn_map.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/copyicon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/copyicon.png
index 6c1c3c15..6c1c3c15 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/copyicon.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/copyicon.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/deleteicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/deleteicon.gif
index 4b07af82..4b07af82 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/deleteicon.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/deleteicon.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/example-frame.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/example-frame.png
index 31f2fe1c..31f2fe1c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/example-frame.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/example-frame.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/loading.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/loading.gif
index cccb0fc9..cccb0fc9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/images/loading.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/loading.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/1_mon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/1_mon.png
new file mode 100644
index 00000000..d46eee50
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/1_mon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/2_tue.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/2_tue.png
new file mode 100644
index 00000000..ed82aad3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/2_tue.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/3_wed.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/3_wed.png
new file mode 100644
index 00000000..8f8c0328
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/3_wed.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/4_thu.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/4_thu.png
new file mode 100644
index 00000000..750dca5d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/4_thu.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/5_fri.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/5_fri.png
new file mode 100644
index 00000000..599e51f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/5_fri.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/6_sat.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/6_sat.png
new file mode 100644
index 00000000..70323ea0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/6_sat.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/7_sun.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/7_sun.png
new file mode 100644
index 00000000..9d579d68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/7_sun.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_IN.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_IN.png
new file mode 100644
index 00000000..af1ac0a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_IN.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_OUT.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_OUT.png
new file mode 100644
index 00000000..935b5386
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_DLSTX_OUT.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat.png
new file mode 100644
index 00000000..916a655f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Def.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Def.png
new file mode 100644
index 00000000..a8b516d9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Def.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Priority.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Priority.png
new file mode 100644
index 00000000..2cf81411
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/images/tunnels/BH_Nat_Priority.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/FusionCharts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/FusionCharts.js
new file mode 100644
index 00000000..4c174dfa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/FusionCharts.js
@@ -0,0 +1,361 @@
+/**
+ * FusionCharts: Flash Player detection and Chart embedding.
+ * Version 1.2.3F ( 22 November 2008) - Specialized for FusionChartsFREE
+ * Checking Flash Version >=6 and added updateChartXML() for FREE Charts.
+ * Version: 1.2.3 (1st September, 2008) - Added Fix for % and & characters, scaled dimensions, fixes in to properly handling of double quotes and single quotes in setDataXML() function.
+ * Version: 1.2.2 (10th July, 2008) - Added Fix for % scaled dimensions, fixes in setDataXML() and setDataURL() functions
+ * Version: 1.2.1 (21st December, 2007) - Added setting up Transparent/opaque mode: setTransparent() function
+ * Version: 1.2 (1st November, 2007) - Added FORM fixes for IE
+ * Version: 1.1 (29th June, 2007) - Added Player detection, New conditional fixes for IE
+ *
+ * Morphed from SWFObject (http://blog.deconcept.com/swfobject/) under MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+if(typeof infosoftglobal == "undefined") var infosoftglobal = new Object();
+if(typeof infosoftglobal.FusionChartsUtil == "undefined") infosoftglobal.FusionChartsUtil = new Object();
+infosoftglobal.FusionCharts = function(swf, id, w, h, debugMode, registerWithJS, c, scaleMode, lang, detectFlashVersion, autoInstallRedirect){
+ if (!document.getElementById) { return; }
+
+ //Flag to see whether data has been set initially
+ this.initialDataSet = false;
+
+ //Create container objects
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+
+ //Set attributes for the SWF
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+
+ w=w.toString().replace(/\%$/,"%25");
+ if(w) { this.setAttribute('width', w); }
+ h=h.toString().replace(/\%$/,"%25");
+ if(h) { this.setAttribute('height', h); }
+
+
+ //Set background color
+ if(c) { this.addParam('bgcolor', c); }
+
+ //Set Quality
+ this.addParam('quality', 'high');
+
+ //Add scripting access parameter
+ this.addParam('allowScriptAccess', 'always');
+
+ //Pass width and height to be appended as chartWidth and chartHeight
+ this.addVariable('chartWidth', w);
+ this.addVariable('chartHeight', h);
+
+ //Whether in debug mode
+ debugMode = debugMode ? debugMode : 0;
+ this.addVariable('debugMode', debugMode);
+ //Pass DOM ID to Chart
+ this.addVariable('DOMId', id);
+ //Whether to registed with JavaScript
+ registerWithJS = registerWithJS ? registerWithJS : 0;
+ this.addVariable('registerWithJS', registerWithJS);
+
+ //Scale Mode of chart
+ scaleMode = scaleMode ? scaleMode : 'noScale';
+ this.addVariable('scaleMode', scaleMode);
+
+ //Application Message Language
+ lang = lang ? lang : 'EN';
+ this.addVariable('lang', lang);
+
+ //Whether to auto detect and re-direct to Flash Player installation
+ this.detectFlashVersion = detectFlashVersion?detectFlashVersion:1;
+ this.autoInstallRedirect = autoInstallRedirect?autoInstallRedirect:1;
+
+ //Ger Flash Player version
+ this.installedVer = infosoftglobal.FusionChartsUtil.getPlayerVersion();
+
+ if (!window.opera && document.all && this.installedVer.major > 7) {
+ // Only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
+ infosoftglobal.FusionCharts.doPrepUnload = true;
+ }
+}
+
+infosoftglobal.FusionCharts.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
+ // netscape plugin architecture
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" ';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ setDataURL: function(strDataURL){
+ //This method sets the data URL for the chart.
+ //If being set initially
+ if (this.initialDataSet==false){
+ this.addVariable('dataURL',strDataURL);
+ //Update flag
+ this.initialDataSet = true;
+ }else{
+ //Else, we update the chart data using External Interface
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(this.getAttribute('id'));
+
+ if (!chartObj.setDataURL)
+ {
+ __flash__addCallback(chartObj, "setDataURL");
+ }
+
+ chartObj.setDataURL(strDataURL);
+ }
+ },
+ //This function :
+ //fixes the double quoted attributes to single quotes
+ //Encodes all quotes inside attribute values
+ //Encodes % to %25 and & to %26;
+ encodeDataXML: function(strDataXML){
+
+ var regExpReservedCharacters=["\\$","\\+"];
+ var arrDQAtt=strDataXML.match(/=\s*\".*?\"/g);
+ if (arrDQAtt){
+ for(var i=0;i<arrDQAtt.length;i++){
+ var repStr=arrDQAtt[i].replace(/^=\s*\"|\"$/g,"");
+ repStr=repStr.replace(/\'/g,"%26apos;");
+ var strTo=strDataXML.indexOf(arrDQAtt[i]);
+ var repStrr="='"+repStr+"'";
+ var strStart=strDataXML.substring(0,strTo);
+ var strEnd=strDataXML.substring(strTo+arrDQAtt[i].length);
+ var strDataXML=strStart+repStrr+strEnd;
+ }
+ }
+
+ strDataXML=strDataXML.replace(/\"/g,"%26quot;");
+ strDataXML=strDataXML.replace(/%(?![\da-f]{2}|[\da-f]{4})/ig,"%25");
+ strDataXML=strDataXML.replace(/\&/g,"%26");
+
+ return strDataXML;
+
+ },
+ setDataXML: function(strDataXML){
+ //If being set initially
+ if (this.initialDataSet==false){
+ //This method sets the data XML for the chart INITIALLY.
+ this.addVariable('dataXML',this.encodeDataXML(strDataXML));
+ //Update flag
+ this.initialDataSet = true;
+ }else{
+ //Else, we update the chart data using External Interface
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(this.getAttribute('id'));
+ chartObj.setDataXML(strDataXML);
+ }
+ },
+ setTransparent: function(isTransparent){
+ //Sets chart to transparent mode when isTransparent is true (default)
+ //When no parameter is passed, we assume transparent to be true.
+ if(typeof isTransparent=="undefined") {
+ isTransparent=true;
+ }
+ //Set the property
+ if(isTransparent)
+ this.addParam('WMode', 'transparent');
+ else
+ this.addParam('WMode', 'Opaque');
+ },
+
+ render: function(elementId){
+ //First check for installed version of Flash Player - we need a minimum of 6
+ if((this.detectFlashVersion==1) && (this.installedVer.major < 6)){
+ if (this.autoInstallRedirect==1){
+ //If we can auto redirect to install the player?
+ var installationConfirm = window.confirm("You need Adobe Flash Player 6 (or above) to view the charts. It is a free and lightweight installation from Adobe.com. Please click on Ok to install the same.");
+ if (installationConfirm){
+ window.location = "http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash";
+ }else{
+ return false;
+ }
+ }else{
+ //Else, do not take an action. It means the developer has specified a message in the DIV (and probably a link).
+ //So, expect the developers to provide a course of way to their end users.
+ //window.alert("You need Adobe Flash Player 8 (or above) to view the charts. It is a free and lightweight installation from Adobe.com. ");
+ return false;
+ }
+ }else{
+ //Render the chart
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+
+ //Added <FORM> compatibility
+ //Check if it's added in Mozilla embed array or if already exits
+ if(!document.embeds[this.getAttribute('id')] && !window[this.getAttribute('id')])
+ window[this.getAttribute('id')]=document.getElementById(this.getAttribute('id'));
+ //or else document.forms[formName/formIndex][chartId]
+ return true;
+ }
+ }
+}
+
+/* ---- detection functions ---- */
+infosoftglobal.FusionChartsUtil.getPlayerVersion = function(){
+ var PlayerVersion = new infosoftglobal.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new infosoftglobal.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){
+ //If Windows CE
+ var axo = 1;
+ var counter = 3;
+ while(axo) {
+ try {
+ counter++;
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
+ PlayerVersion = new infosoftglobal.PlayerVersion([counter,0,0]);
+ } catch (e) {
+ axo = null;
+ }
+ }
+ } else {
+ // Win IE (non mobile)
+ // Do minor version lookup in IE, but avoid Flash Player 6 crashing issues
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ }catch(e){
+ try {
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ PlayerVersion = new infosoftglobal.PlayerVersion([6,0,21]);
+ axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
+ } catch(e) {
+ if (PlayerVersion.major == 6) {
+ return PlayerVersion;
+ }
+ }
+ try {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ } catch(e) {}
+ }
+ if (axo != null) {
+ PlayerVersion = new infosoftglobal.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }
+ }
+ return PlayerVersion;
+}
+infosoftglobal.PlayerVersion = function(arrVersion){
+ this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
+ this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
+}
+// ------------ Fix for Out of Memory Bug in IE in FP9 ---------------//
+/* Fix for video streaming bug */
+infosoftglobal.FusionChartsUtil.cleanupSWFs = function() {
+ var objects = document.getElementsByTagName("OBJECT");
+ for (var i = objects.length - 1; i >= 0; i--) {
+ objects[i].style.display = 'none';
+ for (var x in objects[i]) {
+ if (typeof objects[i][x] == 'function') {
+ objects[i][x] = function(){};
+ }
+ }
+ }
+}
+// Fixes bug in fp9
+if (infosoftglobal.FusionCharts.doPrepUnload) {
+ if (!infosoftglobal.unloadSet) {
+ infosoftglobal.FusionChartsUtil.prepUnload = function() {
+ __flash_unloadHandler = function(){};
+ __flash_savedUnloadHandler = function(){};
+ window.attachEvent("onunload", infosoftglobal.FusionChartsUtil.cleanupSWFs);
+ }
+ window.attachEvent("onbeforeunload", infosoftglobal.FusionChartsUtil.prepUnload);
+ infosoftglobal.unloadSet = true;
+ }
+}
+/* Add document.getElementById if needed (mobile IE < 5) */
+if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}
+/* Add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* Function to return Flash Object from ID */
+infosoftglobal.FusionChartsUtil.getChartObject = function(id)
+{
+ var chartRef=null;
+ if (navigator.appName.indexOf("Microsoft Internet")==-1) {
+ if (document.embeds && document.embeds[id])
+ chartRef = document.embeds[id];
+ else
+ chartRef = window.document[id];
+ }
+ else {
+ chartRef = window[id];
+ }
+ if (!chartRef)
+ chartRef = document.getElementById(id);
+
+ return chartRef;
+}
+/*
+ Function to update chart's data at client side (FOR FusionCharts vFREE and 2.x
+*/
+infosoftglobal.FusionChartsUtil.updateChartXML = function(chartId, strXML){
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(chartId);
+ //Set dataURL to null
+ chartObj.SetVariable("_root.dataURL","");
+ //Set the flag
+ chartObj.SetVariable("_root.isNewData","1");
+ //Set the actual data
+ chartObj.SetVariable("_root.newData",strXML);
+ //Go to the required frame
+ chartObj.TGotoLabel("/", "JavaScriptHandler");
+}
+
+
+/* Aliases for easy usage */
+var getChartFromId = infosoftglobal.FusionChartsUtil.getChartObject;
+var updateChartXML = infosoftglobal.FusionChartsUtil.updateChartXML;
+var FusionCharts = infosoftglobal.FusionCharts; \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/charts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/charts.js
new file mode 100644
index 00000000..4bebbd36
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/charts.js
@@ -0,0 +1,132 @@
+
+function drawSingleSeriesChart(tabId, chartId, chartWidth, chartHeight, chartType, chartData,mme,yyyyMo) {
+ // define, set the data for each chart, and render them (if indicated)
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/" + chartType, "myChartId" + chartId, chartWidth, chartHeight);
+
+ var mmeLabel = "";//mme + "";
+
+ var chartCaptionId = tabId + "-chartdiv" + chartId + "-label";
+
+ document.getElementById(chartCaptionId).innerHTML = "Hosted Voice Usage in "+ yyyyMo;
+
+ myChart.setDataXML("<graph caption='"+mmeLabel + "' xAxisName='' yAxisName='# of Inbound/Outbound calls' showNames='1' decimalPrecision='0' formatNumberScale='0'>" + chartData + "</graph>");
+ myChart.setTransparent(true);
+ myChart.render(tabId + "-"+ "chartdiv" + chartId);
+
+
+ }
+
+
+ // gauge charts
+ function drawGaugeChart(chartId, gaugeIndex, value) {
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/AngularGauge.swf", "myChartId" + chartId, "300", "300", "0", "0");
+ //CPU for NYCMNYBWLT1 on 201301 : 12.63//
+ var chartData =
+ "<Chart showBorder='0' editMode='1' bgColor='FFFFFF' upperLimit='100' lowerLimit='0' label='CPU' baseFontColor='FFFFFF' majorTMNumber='11' majorTMColor='FFFFFF' majorTMHeight='8' minorTMNumber='5' minorTMColor='FFFFFF' minorTMHeight='3' toolTipBorderColor='FFFFFF' toolTipBgColor='333333' gaugeOuterRadius='100' gaugeOriginX='150' gaugeOriginY='150' gaugeScaleAngle='270' placeValuesInside='1' gaugeInnerRadius='80%25' annRenderDelay='0' gaugeFillMix='' pivotRadius='10' showPivotBorder='0' pivotFillMix='{CCCCCC},{333333}' pivotFillRatio='50,50' showShadow='0' >" +
+ "<colorRange>" +
+ "<color minValue='0' maxValue='50' code='C1E1C1' alpha='60'/>" +
+ "<color minValue='50' maxValue='85' code='F6F164' alpha='60'/>" +
+ "<color minValue='85' maxValue='120' code='F70118' alpha='60'/>" +
+ "</colorRange>" +
+ "<dials>" +
+ "<dial value='" + value + "' borderColor='FFFFFF' bgColor='000000,CCCCCC,000000' borderAlpha='0' baseWidth='10'/>" +
+ "</dials>" +
+ "<annotations>" +
+ "<annotationGroup xPos='150' yPos='150' showBelow='1'>" +
+ "<annotation type='circle' xPos='0' yPos='0' radius='120' startAngle='0' endAngle='360' fillColor='CCCCCC,111111' fillPattern='linear' fillAlpha='100,100' fillRatio='50,50' fillAngle='-45'/>" +
+ "<annotation type='circle' xPos='0' yPos='0' radius='110' startAngle='0' endAngle='360' fillColor='111111,cccccc' fillPattern='linear' fillAlpha='100,100' fillRatio='50,50' fillAngle='-45'/>" +
+ "<annotation type='text' label='CPU'/>" +
+ "</annotationGroup>" +
+ "</annotations>" +
+ "</Chart>";
+
+ myChart.setDataXML(chartData);
+ myChart.render("chartdiv" + chartId);
+ }
+
+
+ function updateGaugeChart(chartId, gaugeIndex, refreshCount) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ var val = 0;
+ if (gaugeIndex == "10") val = 12;
+ else if (gaugeIndex == "20") val = 15;
+ else if (gaugeIndex == "30") val = 52;
+ else if (gaugeIndex == "40") val = 42;
+ myChart.setData(1, val);
+ myChart.setData(2, val+20);
+ }
+
+ function updateGaugeChartWithMMEData(chartId, value) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ myChart.setData(1, value);
+ }
+
+
+ function updateGaugeChartWithMMEData(chartId, value, yyyyMo, mme) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ myChart.setData(1, value);
+ document.getElementById("cpuYyyyMm").innerHTML = "Hosted Voice Utilization in "+ yyyyMo;
+
+ }
+
+ function drawMultiSeriesChart(tabId,chartId, chartWidth, chartHeight, chartType) {
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/" + chartType, "myChartId" + chartId, chartWidth, chartHeight, "0", "0");
+
+ myChart.setTransparent(true);
+
+ var chartData =
+ "<graph caption='Hosted Voice v Audited Communication' xAxisName='Month' yAxisName='Bandwidth Usage'" +
+ " showValues='0' decimalPrecision='0' bgcolor='ffffff' bgAlpha='70'" +
+ " showColumnShadow='1' divlinecolor='c5c5c5' divLineAlpha='60' showAlternateHGridColor='1'" +
+ " alternateHGridColor='f8f8f8' alternateHGridAlpha='60' >" +
+ "<categories>" +
+ "<category name='Jan' />" +
+ "<category name='Feb' />" +
+ "<category name='Mar' />" +
+ "<category name='Apr' />" +
+ "<category name='May' />" +
+ "<category name='Jun' />" +
+ "<category name='Jul' />" +
+ "<category name='Aug' />" +
+ "<category name='Sep' />" +
+ "<category name='Oct' />" +
+ "<category name='Nov' />" +
+ "<category name='Dec' />" +
+ "</categories>" +
+ "<dataset seriesName='Hosted Voice' color='c4e3f7' >" +
+ "<set value='7' />" +
+ "<set value='8.04' />" +
+ "<set value='10.04' />" +
+ "<set value='12.73' />" +
+ "<set value='12.41' />" +
+ "<set value='11.83' />" +
+ "<set value='14.06' />" +
+ "<set value='15.94' />" +
+ "<set value='22.97' />" +
+ "<set value='26.79' />" +
+ "<set value='20.35' />" +
+ "<set value='12.63' />" +
+ "</dataset>" +
+ "<dataset seriesName='Audited Communication' color='Fad35e' >" +
+ "<set value='5.49'/>" +
+ "<set value='8.05'/>" +
+ "<set value='15.36'/>" +
+ "<set value='21.23'/>" +
+ "<set value='23.48' />" +
+ "<set value='15.49' />" +
+ "<set value='26.8' />" +
+ "<set value='30.54' />" +
+ "<set value='64' />" +
+ "<set value='75' />" +
+ "<set value='63' />" +
+ "<set value='34' />" +
+ "</dataset>" +
+ "<trendlines>" +
+ "<line startValue='26000' color='91C728' displayValue='Target' showOnTop='1'/>" +
+ "</trendlines>" +
+ "</graph>";
+
+ myChart.setDataXML(chartData);
+ myChart.render(tabId + "-" + "chartdiv" + chartId);
+ }
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/eye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/eye.js
new file mode 100644
index 00000000..8a281dc3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/eye.js
@@ -0,0 +1,34 @@
+/**
+ *
+ * Zoomimage
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($){
+ var EYE = window.EYE = function() {
+ var _registered = {
+ init: []
+ };
+ return {
+ init: function() {
+ $.each(_registered.init, function(nr, fn){
+ fn.call();
+ });
+ },
+ extend: function(prop) {
+ for (var i in prop) {
+ if (prop[i] != undefined) {
+ this[i] = prop[i];
+ }
+ }
+ },
+ register: function(fn, type) {
+ if (!_registered[type]) {
+ _registered[type] = [];
+ }
+ _registered[type].push(fn);
+ }
+ };
+ }();
+ $(EYE.init);
+})(jQuery);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/scribble.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/scribble.js
new file mode 100644
index 00000000..5384b304
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/scribble.js
@@ -0,0 +1,19 @@
+ function storeUserScribble(id) {
+ var scribble = document.getElementById('scribble').innerHTML;
+ localStorage.setItem('userScribble',scribble);
+ }
+
+ function getUserScribble() {
+ if ( localStorage.getItem('userScribble')) {
+ var scribble = localStorage.getItem('userScribble');
+ }
+ else {
+ var scribble = 'You can scribble directly on this sticky... and I will also remember your message the next time you visit my blog!';
+ }
+ document.getElementById('scribble').innerHTML = scribble;
+ }
+
+ function clearLocal() {
+ clear: localStorage.clear();
+ return false;
+ }
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/slides.min.jquery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/slides.min.jquery.js
new file mode 100644
index 00000000..1a1fcdd8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/slides.min.jquery.js
@@ -0,0 +1,20 @@
+/*
+* Slides, A Slideshow Plugin for jQuery
+* Intructions: http://slidesjs.com
+* By: Nathan Searles, http://nathansearles.com
+* Version: 1.1.9
+* Updated: September 5th, 2011
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+(function(a){a.fn.slides=function(b){return b=a.extend({},a.fn.slides.option,b),this.each(function(){function w(g,h,i){if(!p&&o){p=!0,b.animationStart(n+1);switch(g){case"next":l=n,k=n+1,k=e===k?0:k,r=f*2,g=-f*2,n=k;break;case"prev":l=n,k=n-1,k=k===-1?e-1:k,r=0,g=0,n=k;break;case"pagination":k=parseInt(i,10),l=a("."+b.paginationClass+" li."+b.currentClass+" a",c).attr("href").match("[^#/]+$"),k>l?(r=f*2,g=-f*2):(r=0,g=0),n=k}h==="fade"?b.crossfade?d.children(":eq("+k+")",c).css({zIndex:10}).fadeIn(b.fadeSpeed,b.fadeEasing,function(){b.autoHeight?d.animate({height:d.children(":eq("+k+")",c).outerHeight()},b.autoHeightSpeed,function(){d.children(":eq("+l+")",c).css({display:"none",zIndex:0}),d.children(":eq("+k+")",c).css({zIndex:0}),b.animationComplete(k+1),p=!1}):(d.children(":eq("+l+")",c).css({display:"none",zIndex:0}),d.children(":eq("+k+")",c).css({zIndex:0}),b.animationComplete(k+1),p=!1)}):d.children(":eq("+l+")",c).fadeOut(b.fadeSpeed,b.fadeEasing,function(){b.autoHeight?d.animate({height:d.children(":eq("+k+")",c).outerHeight()},b.autoHeightSpeed,function(){d.children(":eq("+k+")",c).fadeIn(b.fadeSpeed,b.fadeEasing)}):d.children(":eq("+k+")",c).fadeIn(b.fadeSpeed,b.fadeEasing,function(){a.browser.msie&&a(this).get(0).style.removeAttribute("filter")}),b.animationComplete(k+1),p=!1}):(d.children(":eq("+k+")").css({left:r,display:"block"}),b.autoHeight?d.animate({left:g,height:d.children(":eq("+k+")").outerHeight()},b.slideSpeed,b.slideEasing,function(){d.css({left:-f}),d.children(":eq("+k+")").css({left:f,zIndex:5}),d.children(":eq("+l+")").css({left:f,display:"none",zIndex:0}),b.animationComplete(k+1),p=!1}):d.animate({left:g},b.slideSpeed,b.slideEasing,function(){d.css({left:-f}),d.children(":eq("+k+")").css({left:f,zIndex:5}),d.children(":eq("+l+")").css({left:f,display:"none",zIndex:0}),b.animationComplete(k+1),p=!1})),b.pagination&&(a("."+b.paginationClass+" li."+b.currentClass,c).removeClass(b.currentClass),a("."+b.paginationClass+" li:eq("+k+")",c).addClass(b.currentClass))}}function x(){clearInterval(c.data("interval"))}function y(){b.pause?(clearTimeout(c.data("pause")),clearInterval(c.data("interval")),u=setTimeout(function(){clearTimeout(c.data("pause")),v=setInterval(function(){w("next",i)},b.play),c.data("interval",v)},b.pause),c.data("pause",u)):x()}a("."+b.container,a(this)).children().wrapAll('<div class="slides_control"/>');var c=a(this),d=a(".slides_control",c),e=d.children().size(),f=d.children().outerWidth(),g=d.children().outerHeight(),h=b.start-1,i=b.effect.indexOf(",")<0?b.effect:b.effect.replace(" ","").split(",")[0],j=b.effect.indexOf(",")<0?i:b.effect.replace(" ","").split(",")[1],k=0,l=0,m=0,n=0,o,p,q,r,s,t,u,v;if(e<2)return a("."+b.container,a(this)).fadeIn(b.fadeSpeed,b.fadeEasing,function(){o=!0,b.slidesLoaded()}),a("."+b.next+", ."+b.prev).fadeOut(0),!1;if(e<2)return;h<0&&(h=0),h>e&&(h=e-1),b.start&&(n=h),b.randomize&&d.randomize(),a("."+b.container,c).css({overflow:"hidden",position:"relative"}),d.children().css({position:"absolute",top:0,left:d.children().outerWidth(),zIndex:0,display:"none"}),d.css({position:"relative",width:f*3,height:g,left:-f}),a("."+b.container,c).css({display:"block"}),b.autoHeight&&(d.children().css({height:"auto"}),d.animate({height:d.children(":eq("+h+")").outerHeight()},b.autoHeightSpeed));if(b.preload&&d.find("img:eq("+h+")").length){a("."+b.container,c).css({background:"url("+b.preloadImage+") no-repeat 50% 50%"});var z=d.find("img:eq("+h+")").attr("src")+"?"+(new Date).getTime();a("img",c).parent().attr("class")!="slides_control"?t=d.children(":eq(0)")[0].tagName.toLowerCase():t=d.find("img:eq("+h+")"),d.find("img:eq("+h+")").attr("src",z).load(function(){d.find(t+":eq("+h+")").fadeIn(b.fadeSpeed,b.fadeEasing,function(){a(this).css({zIndex:5}),a("."+b.container,c).css({background:""}),o=!0,b.slidesLoaded()})})}else d.children(":eq("+h+")").fadeIn(b.fadeSpeed,b.fadeEasing,function(){o=!0,b.slidesLoaded()});b.bigTarget&&(d.children().css({cursor:"pointer"}),d.children().click(function(){return w("next",i),!1})),b.hoverPause&&b.play&&(d.bind("mouseover",function(){x()}),d.bind("mouseleave",function(){y()})),b.generateNextPrev&&(a("."+b.container,c).after('<a href="#" class="'+b.prev+'">Prev</a>'),a("."+b.prev,c).after('<a href="#" class="'+b.next+'">Next</a>')),a("."+b.next,c).click(function(a){a.preventDefault(),b.play&&y(),w("next",i)}),a("."+b.prev,c).click(function(a){a.preventDefault(),b.play&&y(),w("prev",i)}),b.generatePagination?(b.prependPagination?c.prepend("<ul class="+b.paginationClass+"></ul>"):c.append("<ul class="+b.paginationClass+"></ul>"),d.children().each(function(){a("."+b.paginationClass,c).append('<li><a href="#'+m+'">'+(m+1)+"</a></li>"),m++})):a("."+b.paginationClass+" li a",c).each(function(){a(this).attr("href","#"+m),m++}),a("."+b.paginationClass+" li:eq("+h+")",c).addClass(b.currentClass),a("."+b.paginationClass+" li a",c).click(function(){return b.play&&y(),q=a(this).attr("href").match("[^#/]+$"),n!=q&&w("pagination",j,q),!1}),a("a.link",c).click(function(){return b.play&&y(),q=a(this).attr("href").match("[^#/]+$")-1,n!=q&&w("pagination",j,q),!1}),b.play&&(v=setInterval(function(){w("next",i)},b.play),c.data("interval",v))})},a.fn.slides.option={preload:!1,preloadImage:"/img/loading.gif",container:"slides_container",generateNextPrev:!1,next:"next",prev:"prev",pagination:!0,generatePagination:!0,prependPagination:!1,paginationClass:"pagination",currentClass:"current",fadeSpeed:350,fadeEasing:"",slideSpeed:350,slideEasing:"",start:1,effect:"slide",crossfade:!1,randomize:!1,play:0,pause:0,hoverPause:!1,autoHeight:!1,autoHeightSpeed:350,bigTarget:!1,animationStart:function(){},animationComplete:function(){},slidesLoaded:function(){}},a.fn.randomize=function(b){function c(){return Math.round(Math.random())-.5}return a(this).each(function(){var d=a(this),e=d.children(),f=e.length;if(f>1){e.hide();var g=[];for(i=0;i<f;i++)g[g.length]=i;g=g.sort(c),a.each(g,function(a,c){var f=e.eq(c),g=f.clone(!0);g.show().appendTo(d),b!==undefined&&b(f,g),f.remove()})}})}})(jQuery) \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/spacegallery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/spacegallery.js
new file mode 100644
index 00000000..69ab2ccc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/spacegallery.js
@@ -0,0 +1,235 @@
+/**
+ *
+ * Spacegallery
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+
+(function($){
+ EYE.extend({
+
+ spacegallery: {
+
+ //default options (many options are controled via CSS)
+ defaults: {
+ border: 6, // border arround the image
+ perspective: 140, // perpective height
+ minScale: 0.2, // minimum scale for the image in the back
+ duration: 800, // aimation duration
+ loadingClass: null, // CSS class applied to the element while looading images
+ before: function(){return false},
+ after: function(){return false}
+ },
+
+ animated: false,
+
+ //position images
+ positionImages: function(el) {
+ var top = 0;
+ EYE.spacegallery.animated = false;
+ $(el)
+ .find('a')
+ .removeClass(el.spacegalleryCfg.loadingClass)
+ .end()
+ .find('img')
+ .removeAttr('height')
+ .each(function(nr){
+ var newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * el.spacegalleryCfg.asins[nr];
+ $(this)
+ .css({
+ top: el.spacegalleryCfg.tops[nr] + 'px',
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px',
+ opacity: 1 - el.spacegalleryCfg.asins[nr]
+ })
+ .attr('width', parseInt(newWidth));
+ this.spacegallery.next = el.spacegalleryCfg.asins[nr+1];
+ this.spacegallery.nextTop = el.spacegalleryCfg.tops[nr+1] - el.spacegalleryCfg.tops[nr];
+ this.spacegallery.origTop = el.spacegalleryCfg.tops[nr];
+ this.spacegallery.opacity = 1 - el.spacegalleryCfg.asins[nr];
+ this.spacegallery.increment = el.spacegalleryCfg.asins[nr] - this.spacegallery.next;
+ this.spacegallery.current = el.spacegalleryCfg.asins[nr];
+ this.spacegallery.width = newWidth;
+ })
+ },
+
+ //animate to nex image
+ next: function(e) {
+ if (EYE.spacegallery.animated === false) {
+ EYE.spacegallery.animated = true;
+ var el = this.parentNode;
+ el.spacegalleryCfg.before.apply(el);
+ $(el)
+ .css('spacegallery', 0)
+ .animate({
+ spacegallery: 100
+ },{
+ easing: 'easeOut',
+ duration: el.spacegalleryCfg.duration,
+ complete: function() {
+ $(el)
+ .find('img:last')
+ .prependTo(el);
+ EYE.spacegallery.positionImages(el);
+ el.spacegalleryCfg.after.apply(el);
+ },
+ step: function(now) {
+ $('img', this)
+ .each(function(nr){
+ var newWidth, top, next;
+ if (nr + 1 == el.spacegalleryCfg.images) {
+ top = this.spacegallery.origTop + this.spacegallery.nextTop * 4 * now /100;
+ newWidth = this.spacegallery.width * top / this.spacegallery.origTop;
+ $(this)
+ .css({
+ top: top + 'px',
+ opacity: 0.7 - now/100,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ } else {
+ next = this.spacegallery.current - this.spacegallery.increment * now /100;
+ newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * next;
+ $(this).css({
+ top: this.spacegallery.origTop + this.spacegallery.nextTop * now /100 + 'px',
+ opacity: 1 - next,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ }
+ });
+ }
+ });
+ }
+
+ this.blur();
+ return false;
+ },
+
+ autoNext: function(el) {
+
+ if (EYE.spacegallery.animated === false) {
+ EYE.spacegallery.animated = true;
+ el.spacegalleryCfg.before.apply(el); // run the "before" function
+ $(el)
+ .css('spacegallery', 0)
+ .animate({
+ spacegallery: 100
+ },{
+ easing: 'easeOut',
+ duration: el.spacegalleryCfg.duration,
+ complete: function() { // after animation is complete, move the front image to the back
+ $(el)
+ .find('img:last') // find the last image in this div
+ .prependTo(el); // and stick it at the beginning
+ EYE.spacegallery.positionImages(el); // run "position images"
+ el.spacegalleryCfg.after.apply(el); //run the "after" function
+ },
+ step: function(now) {
+ $('img', this)
+ .each(function(nr){
+ var newWidth, top, next;
+ if (nr + 1 == el.spacegalleryCfg.images) {
+ top = this.spacegallery.origTop + this.spacegallery.nextTop * 4 * now /100;
+ newWidth = this.spacegallery.width * top / this.spacegallery.origTop;
+ $(this)
+ .css({
+ top: top + 'px',
+ opacity: 0.7 - now/100,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ } else {
+ next = this.spacegallery.current - this.spacegallery.increment * now /100;
+ newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * next;
+ $(this).css({
+ top: this.spacegallery.origTop + this.spacegallery.nextTop * now /100 + 'px',
+ opacity: 1 - next,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ }
+ });
+ }
+ });
+ }
+
+ return false;
+ },
+
+ //constructor
+ init: function(opt) {
+ opt = $.extend({}, EYE.spacegallery.defaults, opt||{});
+ return this.each(function(){
+ var el = this;
+ if ($(el).is('.spacegallery')) {
+ $('<a href="#"></a>')
+ .appendTo(this)
+ .addClass(opt.loadingClass)
+ .bind('click', EYE.spacegallery.next);
+ el.spacegalleryCfg = opt;
+ el.spacegalleryCfg.images = el.getElementsByTagName('img').length;
+ el.spacegalleryCfg.loaded = 0;
+ el.spacegalleryCfg.asin = Math.asin(1);
+ el.spacegalleryCfg.asins = {};
+ el.spacegalleryCfg.tops = {};
+ el.spacegalleryCfg.increment = parseInt(el.spacegalleryCfg.perspective/el.spacegalleryCfg.images, 10);
+ var top = 0;
+ $('img', el)
+ .each(function(nr){
+ var imgEl = new Image();
+ var elImg = this;
+ el.spacegalleryCfg.asins[nr] = 1 - Math.asin((nr+1)/el.spacegalleryCfg.images)/el.spacegalleryCfg.asin;
+ top += el.spacegalleryCfg.increment - el.spacegalleryCfg.increment * el.spacegalleryCfg.asins[nr];
+ el.spacegalleryCfg.tops[nr] = top;
+ elImg.spacegallery = {};
+ imgEl.src = this.src;
+ if (imgEl.complete) {
+ el.spacegalleryCfg.loaded ++;
+ elImg.spacegallery.origWidth = imgEl.width;
+ elImg.spacegallery.origHeight = imgEl.height
+ } else {
+ imgEl.onload = function() {
+ el.spacegalleryCfg.loaded ++;
+ elImg.spacegallery.origWidth = imgEl.width;
+ elImg.spacegallery.origHeight = imgEl.height
+ if (el.spacegalleryCfg.loaded == el.spacegalleryCfg.images) {
+
+ EYE.spacegallery.positionImages(el);
+ }
+ };
+ }
+ });
+ el.spacegalleryCfg.asins[el.spacegalleryCfg.images] = el.spacegalleryCfg.asins[el.spacegalleryCfg.images - 1] * 1.3;
+ el.spacegalleryCfg.tops[el.spacegalleryCfg.images] = el.spacegalleryCfg.tops[el.spacegalleryCfg.images - 1] * 1.3;
+ if (el.spacegalleryCfg.loaded == el.spacegalleryCfg.images) {
+ EYE.spacegallery.positionImages(el);
+ setInterval(function() { EYE.spacegallery.autoNext(el); }, 4000);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ $.fn.extend({
+
+ /**
+ * Create a space gallery
+ * @name spacegallery
+ * @description create a space gallery
+ * @option int border Images' border. Default: 6
+ * @option int perspective Perpective height. Default: 140
+ * @option float minScale Minimum scale for the image in the back. Default: 0.2
+ * @option int duration Animation duration. Default: 800
+ * @option string loadingClass CSS class applied to the element while looading images. Default: null
+ * @option function before Callback function triggered before going to the next image
+ * @option function after Callback function triggered after going to the next image
+ */
+ spacegallery: EYE.spacegallery.init
+ });
+ $.extend($.easing,{
+ easeOut:function (x, t, b, c, d) {
+ return -c *(t/=d)*(t-2) + b;
+ }
+ });
+})(jQuery); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/utils.js
new file mode 100644
index 00000000..d9be8532
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/js/utils.js
@@ -0,0 +1,252 @@
+/**
+ *
+ * Utilities
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($) {
+EYE.extend({
+ getPosition : function(e, forceIt)
+ {
+ var x = 0;
+ var y = 0;
+ var es = e.style;
+ var restoreStyles = false;
+ if (forceIt && jQuery.curCSS(e,'display') == 'none') {
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ restoreStyles = true;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ }
+ var el = e;
+ if (el.getBoundingClientRect) { // IE
+ var box = el.getBoundingClientRect();
+ x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
+ y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
+ } else {
+ x = el.offsetLeft;
+ y = el.offsetTop;
+ el = el.offsetParent;
+ if (e != el) {
+ while (el) {
+ x += el.offsetLeft;
+ y += el.offsetTop;
+ el = el.offsetParent;
+ }
+ }
+ if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
+ x -= document.body.offsetLeft;
+ y -= document.body.offsetTop;
+ }
+ el = e.parentNode;
+ while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML')
+ {
+ if (jQuery.curCSS(el, 'display') != 'inline') {
+ x -= el.scrollLeft;
+ y -= el.scrollTop;
+ }
+ el = el.parentNode;
+ }
+ }
+ if (restoreStyles == true) {
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {x:x, y:y};
+ },
+ getSize : function(e)
+ {
+ var w = parseInt(jQuery.curCSS(e,'width'), 10);
+ var h = parseInt(jQuery.curCSS(e,'height'), 10);
+ var wb = 0;
+ var hb = 0;
+ if (jQuery.curCSS(e, 'display') != 'none') {
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ } else {
+ var es = e.style;
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {w:w, h:h, wb:wb, hb:hb};
+ },
+ getClient : function(e)
+ {
+ var h, w;
+ if (e) {
+ w = e.clientWidth;
+ h = e.clientHeight;
+ } else {
+ var de = document.documentElement;
+ w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
+ h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
+ }
+ return {w:w,h:h};
+ },
+ getScroll : function (e)
+ {
+ var t=0, l=0, w=0, h=0, iw=0, ih=0;
+ if (e && e.nodeName.toLowerCase() != 'body') {
+ t = e.scrollTop;
+ l = e.scrollLeft;
+ w = e.scrollWidth;
+ h = e.scrollHeight;
+ } else {
+ if (document.documentElement) {
+ t = document.documentElement.scrollTop;
+ l = document.documentElement.scrollLeft;
+ w = document.documentElement.scrollWidth;
+ h = document.documentElement.scrollHeight;
+ } else if (document.body) {
+ t = document.body.scrollTop;
+ l = document.body.scrollLeft;
+ w = document.body.scrollWidth;
+ h = document.body.scrollHeight;
+ }
+ if (typeof pageYOffset != 'undefined') {
+ t = pageYOffset;
+ l = pageXOffset;
+ }
+ iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
+ ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
+ }
+ return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
+ },
+ getMargins : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'marginTop') || '';
+ var r = jQuery.curCSS(e,'marginRight') || '';
+ var b = jQuery.curCSS(e,'marginBottom') || '';
+ var l = jQuery.curCSS(e,'marginLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getPadding : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'paddingTop') || '';
+ var r = jQuery.curCSS(e,'paddingRight') || '';
+ var b = jQuery.curCSS(e,'paddingBottom') || '';
+ var l = jQuery.curCSS(e,'paddingLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getBorder : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'borderTopWidth') || '';
+ var r = jQuery.curCSS(e,'borderRightWidth') || '';
+ var b = jQuery.curCSS(e,'borderBottomWidth') || '';
+ var l = jQuery.curCSS(e,'borderLeftWidth') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)||0
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ traverseDOM : function(nodeEl, func)
+ {
+ func(nodeEl);
+ nodeEl = nodeEl.firstChild;
+ while(nodeEl){
+ EYE.traverseDOM(nodeEl, func);
+ nodeEl = nodeEl.nextSibling;
+ }
+ },
+ getInnerWidth : function(el, scroll) {
+ var offsetW = el.offsetWidth;
+ return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
+ },
+ getInnerHeight : function(el, scroll) {
+ var offsetH = el.offsetHeight;
+ return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
+ },
+ getExtraWidth : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingLeft'))||0)
+ + (parseInt($.curCSS(el, 'paddingRight'))||0)
+ + (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderRightWidth'))||0);
+ return 0;
+ },
+ getExtraHeight : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingTop'))||0)
+ + (parseInt($.curCSS(el, 'paddingBottom'))||0)
+ + (parseInt($.curCSS(el, 'borderTopWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
+ return 0;
+ },
+ isChildOf: function(parentEl, el, container) {
+ if (parentEl == el) {
+ return true;
+ }
+ if (!el || !el.nodeType || el.nodeType != 1) {
+ return false;
+ }
+ if (parentEl.contains && !$.browser.safari) {
+ return parentEl.contains(el);
+ }
+ if ( parentEl.compareDocumentPosition ) {
+ return !!(parentEl.compareDocumentPosition(el) & 16);
+ }
+ var prEl = el.parentNode;
+ while(prEl && prEl != container) {
+ if (prEl == parentEl)
+ return true;
+ prEl = prEl.parentNode;
+ }
+ return false;
+ },
+ centerEl : function(el, axis)
+ {
+ var clientScroll = EYE.getScroll();
+ var size = EYE.getSize(el);
+ if (!axis || axis == 'vertically')
+ $(el).css(
+ {
+ top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
+ }
+ );
+ if (!axis || axis == 'horizontally')
+ $(el).css(
+ {
+ left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
+ }
+ );
+ }
+});
+if (!$.easing.easeout) {
+ $.easing.easeout = function(p, n, firstNum, delta, duration) {
+ return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
+ };
+}
+
+})(jQuery); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/bootstrap.min.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/bootstrap.min.css
new file mode 100644
index 00000000..3424a5f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/bootstrap.min.css
@@ -0,0 +1,351 @@
+html,body{margin:0;padding:0;}
+h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,cite,code,del,dfn,em,img,q,s,samp,small,strike,strong,sub,sup,tt,var,dd,dl,dt,li,ol,ul,fieldset,form,label,legend,button,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;}
+ol,ul{list-style:none;}
+q:before,q:after,blockquote:before,blockquote:after{content:"";}
+html{overflow-y:scroll;font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
+a:focus{outline:thin dotted;}
+a:hover,a:active{outline:0;}
+article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
+audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
+audio:not([controls]){display:none;}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
+sup{top:-0.5em;}
+sub{bottom:-0.25em;}
+img{border:0;-ms-interpolation-mode:bicubic;}
+button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;}
+button,input{line-height:normal;*overflow:visible;}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
+button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
+input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
+input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
+textarea{overflow:auto;vertical-align:top;}
+body{background-color:#ffffff;margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;color:#404040;}
+.container{width:940px;margin-left:auto;margin-right:auto;zoom:1;}.container:before,.container:after{display:table;content:"";zoom:1;}
+.container:after{clear:both;}
+.container-fluid{position:relative;min-width:940px;padding-left:20px;padding-right:20px;zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";zoom:1;}
+.container-fluid:after{clear:both;}
+.container-fluid>.sidebar{position:absolute;top:0;left:20px;width:220px;}
+.container-fluid>.content{margin-left:240px;}
+a{color:#0069d6;text-decoration:none;line-height:inherit;font-weight:inherit;}a:hover{color:#00438a;text-decoration:underline;}
+.pull-right{float:right;}
+.pull-left{float:left;}
+.hide{display:none;}
+.show{display:block;}
+.row{zoom:1;margin-left:-20px;}.row:before,.row:after{display:table;content:"";zoom:1;}
+.row:after{clear:both;}
+.row>[class*="span"]{display:inline;float:left;margin-left:20px;}
+.span1{width:40px;}
+.span2{width:100px;}
+.span3{width:160px;}
+.span4{width:220px;}
+.span5{width:280px;}
+.span6{width:340px;}
+.span7{width:400px;}
+.span8{width:460px;}
+.span9{width:520px;}
+.span10{width:580px;}
+.span11{width:640px;}
+.span12{width:700px;}
+.span13{width:760px;}
+.span14{width:820px;}
+.span15{width:880px;}
+.span16{width:940px;}
+.span17{width:1000px;}
+.span18{width:1060px;}
+.span19{width:1120px;}
+.span20{width:1180px;}
+.span21{width:1240px;}
+.span22{width:1300px;}
+.span23{width:1360px;}
+.span24{width:1420px;}
+.row>.offset1{margin-left:80px;}
+.row>.offset2{margin-left:140px;}
+.row>.offset3{margin-left:200px;}
+.row>.offset4{margin-left:260px;}
+.row>.offset5{margin-left:320px;}
+.row>.offset6{margin-left:380px;}
+.row>.offset7{margin-left:440px;}
+.row>.offset8{margin-left:500px;}
+.row>.offset9{margin-left:560px;}
+.row>.offset10{margin-left:620px;}
+.row>.offset11{margin-left:680px;}
+.row>.offset12{margin-left:740px;}
+.span-one-third{width:300px;}
+.span-two-thirds{width:620px;}
+.offset-one-third{margin-left:340px;}
+.offset-two-thirds{margin-left:660px;}
+p{font-size:13px;font-weight:normal;line-height:18px;margin-bottom:9px;}p small{font-size:11px;color:#bfbfbf;}
+h1,h2,h3,h4,h5,h6{font-weight:bold;color:#404040;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#bfbfbf;}
+h1{margin-bottom:18px;font-size:30px;line-height:36px;}h1 small{font-size:18px;}
+h2{font-size:24px;line-height:36px;}h2 small{font-size:14px;}
+h3,h4,h5,h6{line-height:36px;}
+h3{font-size:18px;}h3 small{font-size:14px;}
+h4{font-size:16px;}h4 small{font-size:12px;}
+h5{font-size:14px;}
+h6{font-size:13px;color:#bfbfbf;text-transform:uppercase;}
+ul,ol{margin:0 0 18px 25px;}
+ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
+ul{list-style:disc;}
+ol{list-style:decimal;}
+li{line-height:18px;color:#808080;}
+ul.unstyled{list-style:none;margin-left:0;}
+dl{margin-bottom:18px;}dl dt,dl dd{line-height:18px;}
+dl dt{font-weight:bold;}
+dl dd{margin-left:9px;}
+hr{margin:20px 0 19px;border:0;border-bottom:1px solid #eee;}
+strong{font-style:inherit;font-weight:bold;}
+em{font-style:italic;font-weight:inherit;line-height:inherit;}
+.muted{color:#bfbfbf;}
+blockquote{margin-bottom:18px;border-left:5px solid #eee;padding-left:15px;}blockquote p{font-size:14px;font-weight:300;line-height:18px;margin-bottom:0;}
+blockquote small{display:block;font-size:12px;font-weight:300;line-height:18px;color:#bfbfbf;}blockquote small:before{content:'\2014 \00A0';}
+address{display:block;line-height:18px;margin-bottom:18px;}
+code,pre{padding:0 3px 2px;font-family:Monaco, Andale Mono, Courier New, monospace;font-size:12px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+code{background-color:#fee9cc;color:rgba(0, 0, 0, 0.75);padding:1px 3px;}
+pre{background-color:#f5f5f5;display:block;padding:8.5px;margin:0 0 18px;line-height:18px;font-size:12px;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;white-space:pre;white-space:pre-wrap;word-wrap:break-word;}
+form{margin-bottom:18px;}
+fieldset{margin-bottom:18px;padding-top:18px;}fieldset legend{display:block;padding-left:150px;font-size:19.5px;line-height:1;color:#404040;*padding:0 0 5px 145px;*line-height:1.5;}
+form .clearfix{margin-bottom:18px;zoom:1;}form .clearfix:before,form .clearfix:after{display:table;content:"";zoom:1;}
+form .clearfix:after{clear:both;}
+label,input,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:normal;}
+label{padding-top:6px;font-size:13px;line-height:18px;float:left;width:130px;text-align:right;color:#404040;}
+form .input{margin-left:150px;}
+input[type=checkbox],input[type=radio]{cursor:pointer;}
+input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;font-size:13px;line-height:18px;color:#808080;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+select{padding:initial;}
+input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:none;}
+input[type=file]{background-color:#ffffff;padding:initial;border:initial;line-height:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+input[type=button],input[type=reset],input[type=submit]{width:auto;height:auto;}
+select,input[type=file]{height:27px;*height:auto;line-height:27px;*margin-top:4px;}
+select[multiple]{height:inherit;background-color:#ffffff;}
+textarea{height:auto;}
+.uneditable-input{background-color:#ffffff;display:block;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
+:-moz-placeholder{color:#bfbfbf;}
+::-webkit-input-placeholder{color:#bfbfbf;}
+input,textarea{-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);}
+input:focus,textarea:focus{outline:0;border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);}
+input[type=file]:focus,input[type=checkbox]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:1px dotted #666;}
+form .clearfix.error>label,form .clearfix.error .help-block,form .clearfix.error .help-inline{color:#b94a48;}
+form .clearfix.error input,form .clearfix.error textarea{color:#b94a48;border-color:#ee5f5b;}form .clearfix.error input:focus,form .clearfix.error textarea:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
+form .clearfix.error .input-prepend .add-on,form .clearfix.error .input-append .add-on{color:#b94a48;background-color:#fce6e6;border-color:#b94a48;}
+form .clearfix.warning>label,form .clearfix.warning .help-block,form .clearfix.warning .help-inline{color:#c09853;}
+form .clearfix.warning input,form .clearfix.warning textarea{color:#c09853;border-color:#ccae64;}form .clearfix.warning input:focus,form .clearfix.warning textarea:focus{border-color:#be9a3f;-webkit-box-shadow:0 0 6px #e5d6b1;-moz-box-shadow:0 0 6px #e5d6b1;box-shadow:0 0 6px #e5d6b1;}
+form .clearfix.warning .input-prepend .add-on,form .clearfix.warning .input-append .add-on{color:#c09853;background-color:#d2b877;border-color:#c09853;}
+form .clearfix.success>label,form .clearfix.success .help-block,form .clearfix.success .help-inline{color:#468847;}
+form .clearfix.success input,form .clearfix.success textarea{color:#468847;border-color:#57a957;}form .clearfix.success input:focus,form .clearfix.success textarea:focus{border-color:#458845;-webkit-box-shadow:0 0 6px #9acc9a;-moz-box-shadow:0 0 6px #9acc9a;box-shadow:0 0 6px #9acc9a;}
+form .clearfix.success .input-prepend .add-on,form .clearfix.success .input-append .add-on{color:#468847;background-color:#bcddbc;border-color:#468847;}
+.input-mini,input.mini,textarea.mini,select.mini{width:60px;}
+.input-small,input.small,textarea.small,select.small{width:90px;}
+.input-medium,input.medium,textarea.medium,select.medium{width:150px;}
+.input-large,input.large,textarea.large,select.large{width:210px;}
+.input-xlarge,input.xlarge,textarea.xlarge,select.xlarge{width:270px;}
+.input-xxlarge,input.xxlarge,textarea.xxlarge,select.xxlarge{width:530px;}
+textarea.xxlarge{overflow-y:auto;}
+input.span1,textarea.span1{display:inline-block;float:none;width:30px;margin-left:0;}
+input.span2,textarea.span2{display:inline-block;float:none;width:90px;margin-left:0;}
+input.span3,textarea.span3{display:inline-block;float:none;width:150px;margin-left:0;}
+input.span4,textarea.span4{display:inline-block;float:none;width:210px;margin-left:0;}
+input.span5,textarea.span5{display:inline-block;float:none;width:270px;margin-left:0;}
+input.span6,textarea.span6{display:inline-block;float:none;width:330px;margin-left:0;}
+input.span7,textarea.span7{display:inline-block;float:none;width:390px;margin-left:0;}
+input.span8,textarea.span8{display:inline-block;float:none;width:450px;margin-left:0;}
+input.span9,textarea.span9{display:inline-block;float:none;width:510px;margin-left:0;}
+input.span10,textarea.span10{display:inline-block;float:none;width:570px;margin-left:0;}
+input.span11,textarea.span11{display:inline-block;float:none;width:630px;margin-left:0;}
+input.span12,textarea.span12{display:inline-block;float:none;width:690px;margin-left:0;}
+input.span13,textarea.span13{display:inline-block;float:none;width:750px;margin-left:0;}
+input.span14,textarea.span14{display:inline-block;float:none;width:810px;margin-left:0;}
+input.span15,textarea.span15{display:inline-block;float:none;width:870px;margin-left:0;}
+input.span16,textarea.span16{display:inline-block;float:none;width:930px;margin-left:0;}
+input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;}
+.actions{background:#f5f5f5;margin-top:18px;margin-bottom:18px;padding:17px 20px 18px 150px;border-top:1px solid #ddd;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;}.actions .secondary-action{float:right;}.actions .secondary-action a{line-height:30px;}.actions .secondary-action a:hover{text-decoration:underline;}
+.help-inline,.help-block{font-size:13px;line-height:18px;color:#bfbfbf;}
+.help-inline{padding-left:5px;*position:relative;*top:-5px;}
+.help-block{display:block;max-width:600px;}
+.inline-inputs{color:#808080;}.inline-inputs span{padding:0 2px 0 1px;}
+.input-prepend input,.input-append input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
+.input-prepend .add-on,.input-append .add-on{position:relative;background:#f5f5f5;border:1px solid #ccc;z-index:2;float:left;display:block;width:auto;min-width:16px;height:18px;padding:4px 4px 4px 5px;margin-right:-1px;font-weight:normal;line-height:18px;color:#bfbfbf;text-align:center;text-shadow:0 1px 0 #ffffff;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
+.input-prepend .active,.input-append .active{background:#a9dba9;border-color:#46a546;}
+.input-prepend .add-on{*margin-top:1px;}
+.input-append input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
+.input-append .add-on{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;margin-right:0;margin-left:-1px;}
+.inputs-list{margin:0 0 5px;width:100%;}.inputs-list li{display:block;padding:0;width:100%;}
+.inputs-list label{display:block;float:none;width:auto;padding:0;margin-left:20px;line-height:18px;text-align:left;white-space:normal;}.inputs-list label strong{color:#808080;}
+.inputs-list label small{font-size:11px;font-weight:normal;}
+.inputs-list .inputs-list{margin-left:25px;margin-bottom:10px;padding-top:0;}
+.inputs-list:first-child{padding-top:6px;}
+.inputs-list li+li{padding-top:2px;}
+.inputs-list input[type=radio],.inputs-list input[type=checkbox]{margin-bottom:0;margin-left:-20px;float:left;}
+.form-stacked{padding-left:20px;}.form-stacked fieldset{padding-top:9px;}
+.form-stacked legend{padding-left:0;}
+.form-stacked label{display:block;float:none;width:auto;font-weight:bold;text-align:left;line-height:20px;padding-top:0;}
+.form-stacked .clearfix{margin-bottom:9px;}.form-stacked .clearfix div.input{margin-left:0;}
+.form-stacked .inputs-list{margin-bottom:0;}.form-stacked .inputs-list li{padding-top:0;}.form-stacked .inputs-list li label{font-weight:normal;padding-top:0;}
+.form-stacked div.clearfix.error{padding-top:10px;padding-bottom:10px;padding-left:10px;margin-top:0;margin-left:-10px;}
+.form-stacked .actions{margin-left:-20px;padding-left:20px;}
+.condensed-table th,.condensed-table td{padding:5px 5px 4px;}
+.bordered-table{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.bordered-table th+th,.bordered-table td+td,.bordered-table th+td{border-left:1px solid #ddd;}
+.bordered-table thead tr:first-child th:first-child,.bordered-table tbody tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;}
+.bordered-table thead tr:first-child th:last-child,.bordered-table tbody tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;}
+.bordered-table tbody tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;}
+.bordered-table tbody tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;}
+table .span1{width:20px;}
+table .span2{width:60px;}
+table .span3{width:100px;}
+table .span4{width:140px;}
+table .span5{width:180px;}
+table .span6{width:220px;}
+table .span7{width:260px;}
+table .span8{width:300px;}
+table .span9{width:340px;}
+table .span10{width:380px;}
+table .span11{width:420px;}
+table .span12{width:460px;}
+table .span13{width:500px;}
+table .span14{width:540px;}
+table .span15{width:580px;}
+table .span16{width:620px;}
+.zebra-striped tbody tr:nth-child(odd) td,.zebra-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;}
+.zebra-striped tbody tr:hover td,.zebra-striped tbody tr:hover th{background-color:#f5f5f5;}
+table .header{cursor:pointer;}table .header:after{content:"";float:right;margin-top:7px;border-width:0 4px 4px;border-style:solid;border-color:#000 transparent;visibility:hidden;}
+table .headerSortUp,table .headerSortDown{background-color:rgba(141, 192, 219, 0.25);text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);}
+table .header:hover:after{visibility:visible;}
+table .headerSortDown:after,table .headerSortDown:hover:after{visibility:visible;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;}
+table .headerSortUp:after{border-bottom:none;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000;visibility:visible;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;}
+table .blue{color:#049cdb;border-bottom-color:#049cdb;}
+table .headerSortUp.blue,table .headerSortDown.blue{background-color:#ade6fe;}
+table .green{color:#46a546;border-bottom-color:#46a546;}
+table .headerSortUp.green,table .headerSortDown.green{background-color:#cdeacd;}
+table .red{color:#9d261d;border-bottom-color:#9d261d;}
+table .headerSortUp.red,table .headerSortDown.red{background-color:#f4c8c5;}
+table .yellow{color:#ffc40d;border-bottom-color:#ffc40d;}
+table .headerSortUp.yellow,table .headerSortDown.yellow{background-color:#fff6d9;}
+table .orange{color:#f89406;border-bottom-color:#f89406;}
+table .headerSortUp.orange,table .headerSortDown.orange{background-color:#fee9cc;}
+table .purple{color:#7a43b6;border-bottom-color:#7a43b6;}
+table .headerSortUp.purple,table .headerSortDown.purple{background-color:#e2d5f0;}
+.topbar{height:40px;position:fixed;top:0;left:0;right:0;z-index:10000;overflow:visible;}.topbar a{color:#bfbfbf;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}
+.topbar h3 a:hover,.topbar .brand:hover,.topbar ul .active>a{background-color:#333;background-color:rgba(255, 255, 255, 0.05);color:#ffffff;text-decoration:none;}
+.topbar h3{position:relative;}
+.topbar h3 a,.topbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;color:#ffffff;font-size:20px;font-weight:200;line-height:1;}
+.topbar p{margin:0;line-height:40px;}.topbar p a:hover{background-color:transparent;color:#ffffff;}
+.topbar form{float:left;margin:5px 0 0 0;position:relative;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
+.topbar form.pull-right{float:right;}
+.topbar input{background-color:#444;background-color:rgba(255, 255, 255, 0.3);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:normal;font-weight:13px;line-height:1;padding:4px 9px;color:#ffffff;color:rgba(255, 255, 255, 0.75);border:1px solid #111;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.topbar input:-moz-placeholder{color:#e6e6e6;}
+.topbar input::-webkit-input-placeholder{color:#e6e6e6;}
+.topbar input:hover{background-color:#bfbfbf;background-color:rgba(255, 255, 255, 0.5);color:#ffffff;}
+.topbar input:focus,.topbar input.focused{outline:0;background-color:#ffffff;color:#404040;text-shadow:0 1px 0 #ffffff;border:0;padding:5px 10px;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);}
+.topbar-inner,.topbar .fill{background-color:#222;background-color:#222222;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);}
+.topbar div>ul,.nav{display:block;float:left;margin:0 10px 0 0;position:relative;left:0;}.topbar div>ul>li,.nav>li{display:block;float:left;}
+.topbar div>ul a,.nav a{display:block;float:none;padding:10px 10px 11px;line-height:19px;text-decoration:none;}.topbar div>ul a:hover,.nav a:hover{color:#ffffff;text-decoration:none;}
+.topbar div>ul .active>a,.nav .active>a{background-color:#222;background-color:rgba(0, 0, 0, 0.5);}
+.topbar div>ul.secondary-nav,.nav.secondary-nav{float:right;margin-left:10px;margin-right:0;}.topbar div>ul.secondary-nav .menu-dropdown,.nav.secondary-nav .menu-dropdown,.topbar div>ul.secondary-nav .dropdown-menu,.nav.secondary-nav .dropdown-menu{right:0;border:0;}
+.topbar div>ul a.menu:hover,.nav a.menu:hover,.topbar div>ul li.open .menu,.nav li.open .menu,.topbar div>ul .dropdown-toggle:hover,.nav .dropdown-toggle:hover,.topbar div>ul .dropdown.open .dropdown-toggle,.nav .dropdown.open .dropdown-toggle{background:#444;background:rgba(255, 255, 255, 0.05);}
+.topbar div>ul .menu-dropdown,.nav .menu-dropdown,.topbar div>ul .dropdown-menu,.nav .dropdown-menu{background-color:#333;}.topbar div>ul .menu-dropdown a.menu,.nav .menu-dropdown a.menu,.topbar div>ul .dropdown-menu a.menu,.nav .dropdown-menu a.menu,.topbar div>ul .menu-dropdown .dropdown-toggle,.nav .menu-dropdown .dropdown-toggle,.topbar div>ul .dropdown-menu .dropdown-toggle,.nav .dropdown-menu .dropdown-toggle{color:#ffffff;}.topbar div>ul .menu-dropdown a.menu.open,.nav .menu-dropdown a.menu.open,.topbar div>ul .dropdown-menu a.menu.open,.nav .dropdown-menu a.menu.open,.topbar div>ul .menu-dropdown .dropdown-toggle.open,.nav .menu-dropdown .dropdown-toggle.open,.topbar div>ul .dropdown-menu .dropdown-toggle.open,.nav .dropdown-menu .dropdown-toggle.open{background:#444;background:rgba(255, 255, 255, 0.05);}
+.topbar div>ul .menu-dropdown li a,.nav .menu-dropdown li a,.topbar div>ul .dropdown-menu li a,.nav .dropdown-menu li a{color:#999;text-shadow:0 1px 0 rgba(0, 0, 0, 0.5);}.topbar div>ul .menu-dropdown li a:hover,.nav .menu-dropdown li a:hover,.topbar div>ul .dropdown-menu li a:hover,.nav .dropdown-menu li a:hover{background-color:#191919;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919));background-image:-moz-linear-gradient(top, #292929, #191919);background-image:-ms-linear-gradient(top, #292929, #191919);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919));background-image:-webkit-linear-gradient(top, #292929, #191919);background-image:-o-linear-gradient(top, #292929, #191919);background-image:linear-gradient(top, #292929, #191919);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0);color:#ffffff;}
+.topbar div>ul .menu-dropdown .active a,.nav .menu-dropdown .active a,.topbar div>ul .dropdown-menu .active a,.nav .dropdown-menu .active a{color:#ffffff;}
+.topbar div>ul .menu-dropdown .divider,.nav .menu-dropdown .divider,.topbar div>ul .dropdown-menu .divider,.nav .dropdown-menu .divider{background-color:#222;border-color:#444;}
+.topbar ul .menu-dropdown li a,.topbar ul .dropdown-menu li a{padding:4px 15px;}
+li.menu,.dropdown{position:relative;}
+a.menu:after,.dropdown-toggle:after{width:0;height:0;display:inline-block;content:"&darr;";text-indent:-99999px;vertical-align:top;margin-top:8px;margin-left:4px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
+.menu-dropdown,.dropdown-menu{background-color:#ffffff;float:left;display:none;position:absolute;top:40px;z-index:900;min-width:160px;max-width:220px;_width:160px;margin-left:0;margin-right:0;padding:6px 0;zoom:1;border-color:#999;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:0 1px 1px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.menu-dropdown li,.dropdown-menu li{float:none;display:block;background-color:none;}
+.menu-dropdown .divider,.dropdown-menu .divider{height:1px;margin:5px 0;overflow:hidden;background-color:#eee;border-bottom:1px solid #ffffff;}
+.topbar .dropdown-menu a,.dropdown-menu a{display:block;padding:4px 15px;clear:both;font-weight:normal;line-height:18px;color:#808080;text-shadow:0 1px 0 #ffffff;}.topbar .dropdown-menu a:hover,.dropdown-menu a:hover,.topbar .dropdown-menu a.hover,.dropdown-menu a.hover{background-color:#dddddd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));background-image:-moz-linear-gradient(top, #eeeeee, #dddddd);background-image:-ms-linear-gradient(top, #eeeeee, #dddddd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd));background-image:-webkit-linear-gradient(top, #eeeeee, #dddddd);background-image:-o-linear-gradient(top, #eeeeee, #dddddd);background-image:linear-gradient(top, #eeeeee, #dddddd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0);color:#404040;text-decoration:none;-webkit-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);}
+.open .menu,.dropdown.open .menu,.open .dropdown-toggle,.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);}
+.open .menu-dropdown,.dropdown.open .menu-dropdown,.open .dropdown-menu,.dropdown.open .dropdown-menu{display:block;}
+.tabs,.pills{margin:0 0 18px;padding:0;list-style:none;zoom:1;}.tabs:before,.pills:before,.tabs:after,.pills:after{display:table;content:"";zoom:1;}
+.tabs:after,.pills:after{clear:both;}
+.tabs>li,.pills>li{float:left;}.tabs>li>a,.pills>li>a{display:block;}
+.tabs{border-color:#ddd;border-style:solid;border-width:0 0 1px;}.tabs>li{position:relative;margin-bottom:-1px;}.tabs>li>a{padding:0 15px;margin-right:2px;line-height:34px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.tabs>li>a:hover{text-decoration:none;background-color:#eee;border-color:#eee #eee #ddd;}
+.tabs .active>a,.tabs .active>a:hover{color:#808080;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
+.tabs .menu-dropdown,.tabs .dropdown-menu{top:35px;border-width:1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
+.tabs a.menu:after,.tabs .dropdown-toggle:after{border-top-color:#999;margin-top:15px;margin-left:5px;}
+.tabs li.open.menu .menu,.tabs .open.dropdown .dropdown-toggle{border-color:#999;}
+.tabs li.open a.menu:after,.tabs .dropdown.open .dropdown-toggle:after{border-top-color:#555;}
+.pills a{margin:5px 3px 5px 0;padding:0 15px;line-height:30px;text-shadow:0 1px 1px #ffffff;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}.pills a:hover{color:#ffffff;text-decoration:none;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#00438a;}
+.pills .active a{color:#ffffff;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#0069d6;}
+.pills-vertical>li{float:none;}
+.tab-content>.tab-pane,.pill-content>.pill-pane,.tab-content>div,.pill-content>div{display:none;}
+.tab-content>.active,.pill-content>.active{display:block;}
+.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#f5f5f5;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;}
+.breadcrumb .divider{padding:0 5px;color:#bfbfbf;}
+.breadcrumb .active a{color:#404040;}
+.hero-unit{background-color:#f5f5f5;margin-bottom:30px;padding:60px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;}
+.hero-unit p{font-size:18px;font-weight:200;line-height:27px;}
+footer{margin-top:17px;padding-top:17px;border-top:1px solid #eee;}
+.page-header{margin-bottom:17px;border-bottom:1px solid #ddd;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}.page-header h1{margin-bottom:8px;}
+.btn.danger,.alert-message.danger,.btn.danger:hover,.alert-message.danger:hover,.btn.error,.alert-message.error,.btn.error:hover,.alert-message.error:hover,.btn.success,.alert-message.success,.btn.success:hover,.alert-message.success:hover,.btn.info,.alert-message.info,.btn.info:hover,.alert-message.info:hover{color:#ffffff;}
+.btn .close,.alert-message .close{font-family:Arial,sans-serif;line-height:18px;}
+.btn.danger,.alert-message.danger,.btn.error,.alert-message.error{background-color:#c43c35;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#c43c35 #c43c35 #882a25;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.success,.alert-message.success{background-color:#57a957;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#57a957 #57a957 #3d773d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.info,.alert-message.info{background-color:#339bb9;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#339bb9 #339bb9 #22697d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn{cursor:pointer;display:inline-block;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);padding:5px 14px 6px;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);color:#333;font-size:13px;line-height:normal;border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-webkit-transition:0.1s linear all;-moz-transition:0.1s linear all;-ms-transition:0.1s linear all;-o-transition:0.1s linear all;transition:0.1s linear all;}.btn:hover{background-position:0 -15px;color:#333;text-decoration:none;}
+.btn:focus{outline:1px dotted #666;}
+.btn.primary{color:#ffffff;background-color:#0064cd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));background-image:-moz-linear-gradient(top, #049cdb, #0064cd);background-image:-ms-linear-gradient(top, #049cdb, #0064cd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));background-image:-webkit-linear-gradient(top, #049cdb, #0064cd);background-image:-o-linear-gradient(top, #049cdb, #0064cd);background-image:linear-gradient(top, #049cdb, #0064cd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#0064cd #0064cd #003f81;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.active,.btn :active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);}
+.btn.disabled{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn.large{font-size:15px;line-height:normal;padding:9px 14px 9px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
+.btn.small{padding:7px 9px 7px;font-size:11px;}
+:root .alert-message,:root .btn{border-radius:0 \0;}
+button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0;}
+.close{float:right;color:#000000;font-size:20px;font-weight:bold;line-height:13.5px;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;}.close:hover{color:#000000;text-decoration:none;filter:alpha(opacity=40);-khtml-opacity:0.4;-moz-opacity:0.4;opacity:0.4;}
+.alert-message{position:relative;padding:7px 15px;margin-bottom:18px;color:#404040;background-color:#eedc94;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));background-image:-moz-linear-gradient(top, #fceec1, #eedc94);background-image:-ms-linear-gradient(top, #fceec1, #eedc94);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));background-image:-webkit-linear-gradient(top, #fceec1, #eedc94);background-image:-o-linear-gradient(top, #fceec1, #eedc94);background-image:linear-gradient(top, #fceec1, #eedc94);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#eedc94 #eedc94 #e4c652;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);border-width:1px;border-style:solid;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);}.alert-message .close{margin-top:1px;*margin-top:0;}
+.alert-message a{font-weight:bold;color:#404040;}
+.alert-message.danger p a,.alert-message.error p a,.alert-message.success p a,.alert-message.info p a{color:#ffffff;}
+.alert-message h5{line-height:18px;}
+.alert-message p{margin-bottom:0;}
+.alert-message div{margin-top:5px;margin-bottom:2px;line-height:28px;}
+.alert-message .btn{-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);}
+.alert-message.block-message{background-image:none;background-color:#fdf5d9;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);padding:14px;border-color:#fceec1;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.alert-message.block-message ul,.alert-message.block-message p{margin-right:30px;}
+.alert-message.block-message ul{margin-bottom:0;}
+.alert-message.block-message li{color:#404040;}
+.alert-message.block-message .alert-actions{margin-top:5px;}
+.alert-message.block-message.error,.alert-message.block-message.success,.alert-message.block-message.info{color:#404040;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
+.alert-message.block-message.error{background-color:#fddfde;border-color:#fbc7c6;}
+.alert-message.block-message.success{background-color:#d1eed1;border-color:#bfe7bf;}
+.alert-message.block-message.info{background-color:#ddf4fb;border-color:#c6edf9;}
+.alert-message.block-message.danger p a,.alert-message.block-message.error p a,.alert-message.block-message.success p a,.alert-message.block-message.info p a{color:#404040;}
+.pagination{height:36px;margin:18px 0;}.pagination ul{float:left;margin:0;border:1px solid #ddd;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
+.pagination li{display:inline;}
+.pagination a{float:left;padding:0 14px;line-height:34px;border-right:1px solid;border-right-color:#ddd;border-right-color:rgba(0, 0, 0, 0.15);*border-right-color:#ddd;text-decoration:none;}
+.pagination a:hover,.pagination .active a{background-color:#c7eefe;}
+.pagination .disabled a,.pagination .disabled a:hover{background-color:transparent;color:#bfbfbf;}
+.pagination .next a{border:0;}
+.well{background-color:#f5f5f5;margin-bottom:20px;padding:19px;min-height:20px;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
+.modal-backdrop{background-color:#000000;position:fixed;top:0;left:0;right:0;bottom:0;z-index:10000;}.modal-backdrop.fade{opacity:0;}
+.modal-backdrop,.modal-backdrop.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}
+.modal{position:fixed;top:50%;left:50%;z-index:11000;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal .close{margin-top:7px;}
+.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
+.modal.fade.in{top:50%;}
+.modal-header{border-bottom:1px solid #eee;padding:5px 15px;}
+.modal-body{padding:15px;}
+.modal-body form{margin-bottom:0;}
+.modal-footer{background-color:#f5f5f5;padding:14px 15px 15px;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;zoom:1;margin-bottom:0;}.modal-footer:before,.modal-footer:after{display:table;content:"";zoom:1;}
+.modal-footer:after{clear:both;}
+.modal-footer .btn{float:right;margin-left:5px;}
+.modal .popover,.modal .twipsy{z-index:12000;}
+.twipsy{display:block;position:absolute;visibility:visible;padding:5px;font-size:11px;z-index:1000;filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}.twipsy.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}
+.twipsy.above .twipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
+.twipsy.left .twipsy-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
+.twipsy.below .twipsy-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
+.twipsy.right .twipsy-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
+.twipsy-inner{padding:3px 8px;background-color:#000000;color:white;text-align:center;max-width:200px;text-decoration:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.twipsy-arrow{position:absolute;width:0;height:0;}
+.popover{position:absolute;top:0;left:0;z-index:1000;padding:5px;display:none;}.popover.above .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
+.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
+.popover.below .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
+.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
+.popover .arrow{position:absolute;width:0;height:0;}
+.popover .inner{background:#000000;background:rgba(0, 0, 0, 0.8);padding:3px;overflow:hidden;width:280px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);}
+.popover .title{background-color:#f5f5f5;padding:9px 15px;line-height:1;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;border-bottom:1px solid #eee;}
+.popover .content{background-color:#ffffff;padding:14px;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover .content p,.popover .content ul,.popover .content ol{margin-bottom:0;}
+.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;}
+.label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;white-space:nowrap;background-color:#bfbfbf;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}.label.important{background-color:#c43c35;}
+.label.warning{background-color:#f89406;}
+.label.success{background-color:#46a546;}
+.label.notice{background-color:#62cffc;}
+.media-grid{margin-left:-20px;margin-bottom:0;zoom:1;}.media-grid:before,.media-grid:after{display:table;content:"";zoom:1;}
+.media-grid:after{clear:both;}
+.media-grid li{display:inline;}
+.media-grid a{float:left;padding:4px;margin:0 0 18px 20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}.media-grid a img{display:block;}
+.media-grid a:hover{border-color:#0069d6;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/custom.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/custom.css
new file mode 100644
index 00000000..b7df8c25
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/custom.css
@@ -0,0 +1,97 @@
+body, html, div, p, span, a, h1, h2, h3, h4, h5{
+ margin : 0;
+ padding : 0;
+}
+
+body, html{
+ width : 100%;
+}
+
+body{
+ color : white;
+ font-family : tahoma;
+ font-weight : lighter;
+ padding-top : 40px;
+}
+
+ body p{
+ font-size : 14px;
+ }
+
+ body p a{
+ font-size : 16px;
+ }
+
+h1 {
+ color : #E05E00;
+ font-style : italic;
+}
+
+a{
+ color : #E05E00;
+ text-decoration : none;
+}
+
+a:hover{
+ text-decoration : underline;
+}
+
+/* general */
+.clear {
+ clear: both;
+}
+
+/* Header */
+.brand{
+ color : #E05E00 !important;
+ font-family : georgia;
+ font-style : italic;
+}
+
+/* list stuff */
+#org{
+ background-color : white;
+ margin : 10px;
+ padding : 10px;
+}
+
+#show-list{
+ cursor : pointer;
+}
+
+/* bootstrap overrides */
+.alert-message{
+ margin: 2px 0;
+}
+
+.topbar{
+ position : absolute;
+}
+
+/* Custom chart styling */
+.jOrgChart {
+ margin : 10px;
+ padding : 20px;
+}
+
+/* Custom node styling */
+.jOrgChart .node {
+ font-weight : bold;
+ font-size : 14px;
+ background-color : #D5D6DB;
+ border-radius : 8px;
+ border : 5px solid gray;
+ color : #793a06;
+ -moz-border-radius : 8px;
+}
+ .node p{
+ font-family : tahoma;
+ font-size : 10px;
+ line-height : 11px;
+ padding : 2px;
+ }
+
+table {
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/jquery.jOrgChart.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/jquery.jOrgChart.css
new file mode 100644
index 00000000..ffabe274
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/jquery.jOrgChart.css
@@ -0,0 +1,51 @@
+/* Basic styling */
+/* Draw the lines */
+.jOrgChart .line {
+ height : 20px;
+ width : 4px;
+}
+
+.jOrgChart .down {
+ background-color : black;
+ margin : 0px auto;
+}
+
+.jOrgChart .top {
+ border-top : 3px solid black;
+}
+
+.jOrgChart .left {
+ border-right : 2px solid black;
+}
+
+.jOrgChart .right {
+ border-left : 2px solid black;
+}
+
+/* node cell */
+.jOrgChart td {
+ text-align : center;
+ vertical-align : top;
+ padding : 0;
+}
+
+/* The node */
+.jOrgChart .node {
+ background-color : #35363B;
+ display : inline-block;
+ width : 120px;
+ height : 60px;
+ z-index : 10;
+ margin : 0 2px;
+}
+
+/* jQuery drag 'n drop */
+
+.drag-active {
+ border-style : dashed !important;
+}
+
+.drop-hover {
+ border-style : solid !important;
+ border-color : #E05E00 !important;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/prettify.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/prettify.css
new file mode 100644
index 00000000..d44b3a22
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/css/prettify.css
@@ -0,0 +1 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example.html
new file mode 100644
index 00000000..543b0f92
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>jOrgChart - A jQuery OrgChart Plugin</title>
+ <link rel="stylesheet" href="css/bootstrap.min.css"/>
+ <link rel="stylesheet" href="css/jquery.jOrgChart.css"/>
+ <link rel="stylesheet" href="css/custom.css"/>
+ <link href="css/prettify.css" type="text/css" rel="stylesheet" />
+
+ <script type="text/javascript" src="prettify.js"></script>
+
+ <!-- jQuery includes -->
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
+
+ <script src="jquery.jOrgChart.js"></script>
+
+ <script>
+ jQuery(document).ready(function() {
+ $("#org").jOrgChart({
+ chartElement : '#chart',
+ dragAndDrop : true
+ });
+ });
+ </script>
+ </head>
+
+ <body onload="prettyPrint();">
+ <ul id="org" style="display:none">
+ <li>Product 1<br/>
+ <ul>
+ <li>Service 1<br/>
+ <ul>
+ <li>Resource 1<br/></li>
+ <li>Resource 2<br/></li>
+ <li>Resource 3<br/></li>
+ <li>Resource 4<br/></li>
+ <li>Resource 5<br/></li>
+ </ul>
+ </li>
+ <li>Service 6<br/></li>
+ <li>Service 7<br/>
+ <ul>
+ <li>Resource 8<br/></li>
+ <li>Resource 9<br/></li>
+ <li>Resource 10<br/></li>
+ <li>Resource 11<br/></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <div id="chart" class="orgChart"></div>
+
+ <script>
+ jQuery(document).ready(function() {
+
+ /* Custom jQuery for the example */
+ $("#show-list").click(function(e){
+ e.preventDefault();
+
+ $('#list-html').toggle('fast', function(){
+ if($(this).is(':visible')){
+ $('#show-list').text('Hide underlying list.');
+ $(".topbar").fadeTo('fast',0.9);
+ }else{
+ $('#show-list').text('Show underlying list.');
+ $(".topbar").fadeTo('fast',1);
+ }
+ });
+ });
+
+ $('#list-html').text($('#org').html());
+
+ $("#org").bind("DOMSubtreeModified", function() {
+ $('#list-html').text('');
+
+ $('#list-html').text($('#org').html());
+
+ prettyPrint();
+ });
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example_vsp.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example_vsp.html
new file mode 100644
index 00000000..a2e3703d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/example_vsp.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>jOrgChart - A jQuery OrgChart Plugin</title>
+ <link rel="stylesheet" href="css/bootstrap.min.css"/>
+ <link rel="stylesheet" href="css/jquery.jOrgChart.css"/>
+ <link rel="stylesheet" href="css/custom.css"/>
+ <link href="css/prettify.css" type="text/css" rel="stylesheet" />
+
+ <script type="text/javascript" src="prettify.js"></script>
+
+ <!-- jQuery includes -->
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
+
+ <script src="jquery.jOrgChart.js"></script>
+
+ <script>
+ jQuery(document).ready(function() {
+ $("#org").jOrgChart({
+ chartElement : '#chart',
+ dragAndDrop : true
+ });
+ });
+ </script>
+ </head>
+
+ <body onload="prettyPrint();">
+ <ul id="org" style="display:none">
+ <li>Trinity<br/>
+ <ul>
+ <li>Call Forwarding<br/>
+ <ul>
+ <li>Call Forwarding Busy<br/></li>
+ <li>Call Forwarding Always<br/></li>
+ <li>Call Forwarding Not Reachable<br/></li>
+ </ul>
+ </li>
+ <li>Dial Restrictions<br/>
+ <ul>
+ <li>Outgoing Calls<br/></li>
+ <li>Redirecting Calls<br/></li>
+ <li>Incoming Calls<br/></li>
+ </ul>
+ </li>
+ <li>Messaging<br/>
+ <ul>
+ <li>Voice Management<br/></li>
+ <li>Greetings<br/></li>
+ <li>Fax Messaging<br/></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <div id="chart" class="orgChart"></div>
+
+ <script>
+ jQuery(document).ready(function() {
+
+ /* Custom jQuery for the example */
+ $("#show-list").click(function(e){
+ e.preventDefault();
+
+ $('#list-html').toggle('fast', function(){
+ if($(this).is(':visible')){
+ $('#show-list').text('Hide underlying list.');
+ $(".topbar").fadeTo('fast',0.9);
+ }else{
+ $('#show-list').text('Show underlying list.');
+ $(".topbar").fadeTo('fast',1);
+ }
+ });
+ });
+
+ $('#list-html').text($('#org').html());
+
+ $("#org").bind("DOMSubtreeModified", function() {
+ $('#list-html').text('');
+
+ $('#list-html').text($('#org').html());
+
+ prettyPrint();
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/bkgd.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/bkgd.png
new file mode 100644
index 00000000..3bbaf5ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/bkgd.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/raspberry.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/raspberry.jpg
new file mode 100644
index 00000000..e79a0515
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/images/raspberry.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/jquery.jOrgChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/jquery.jOrgChart.js
new file mode 100644
index 00000000..89411b29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/jquery.jOrgChart.js
@@ -0,0 +1,267 @@
+/**
+ * jQuery org-chart/tree plugin.
+ *
+ * Author: Wes Nolte
+ * http://twitter.com/wesnolte
+ *
+ * Based on the work of Mark Lee
+ * http://www.capricasoftware.co.uk
+ *
+ * Copyright (c) 2011 Wesley Nolte
+ * Dual licensed under the MIT and GPL licenses.
+ *
+ */
+(function($) {
+
+ $.fn.jOrgChart = function(options) {
+ var opts = $.extend({}, $.fn.jOrgChart.defaults, options);
+ var $appendTo = $(opts.chartElement);
+
+ // build the tree
+ $this = $(this);
+ var $container = $("<div class='" + opts.chartClass + "'/>");
+ if($this.is("ul")) {
+ buildNode($this.find("li:first"), $container, 0, opts);
+ }
+ else if($this.is("li")) {
+ buildNode($this, $container, 0, opts);
+ }
+ $appendTo.append($container);
+
+ // add drag and drop if enabled
+ if(opts.dragAndDrop){
+ $('div.node').draggable({
+ cursor : 'move',
+ distance : 40,
+ helper : 'clone',
+ opacity : 0.8,
+ revert : true,
+ revertDuration : 100,
+ snap : 'div.node.expanded',
+ snapMode : 'inner',
+ stack : 'div.node'
+ });
+
+ $('div.node').droppable({
+ accept : '.node',
+ activeClass : 'drag-active',
+ hoverClass : 'drop-hover'
+ });
+
+ // Drag start event handler for nodes
+ $('div.node').bind("dragstart", function handleDragStart( event, ui ){
+
+ var sourceNode = $(this);
+ sourceNode.parentsUntil('.node-container')
+ .find('*')
+ .filter('.node')
+ .droppable('disable');
+ });
+
+ // Drag stop event handler for nodes
+ $('div.node').bind("dragstop", function handleDragStop( event, ui ){
+
+ /* reload the plugin */
+ $(opts.chartElement).children().remove();
+ $this.jOrgChart(opts);
+ });
+
+ // Drop event handler for nodes
+ $('div.node').bind("drop", function handleDropEvent( event, ui ) {
+ var sourceNode = ui.draggable;
+ var targetNode = $(this);
+
+ // finding nodes based on plaintext and html
+ // content is hard!
+ var targetLi = $('li').filter(function(){
+
+ li = $(this).clone()
+ .children("ul,li")
+ .remove()
+ .end();
+ var attr = li.attr('id');
+ if (typeof attr !== 'undefined' && attr !== false) {
+ return li.attr("id") == targetNode.attr("id");
+ }
+ else {
+ return li.html() == targetNode.html();
+ }
+
+ });
+
+ var sourceLi = $('li').filter(function(){
+
+ li = $(this).clone()
+ .children("ul,li")
+ .remove()
+ .end();
+ var attr = li.attr('id');
+ if (typeof attr !== 'undefined' && attr !== false) {
+ return li.attr("id") == sourceNode.attr("id");
+ }
+ else {
+ return li.html() == sourceNode.html();
+ }
+
+ });
+
+ var sourceliClone = sourceLi.clone();
+ var sourceUl = sourceLi.parent('ul');
+
+ if(sourceUl.children('li').size() > 1){
+ sourceLi.remove();
+ }else{
+ sourceUl.remove();
+ }
+
+ var id = sourceLi.attr("id");
+
+ if(targetLi.children('ul').size() >0){
+ if (typeof id !== 'undefined' && id !== false) {
+ targetLi.children('ul').append('<li id="'+id+'">'+sourceliClone.html()+'</li>');
+ }else{
+ targetLi.children('ul').append('<li>'+sourceliClone.html()+'</li>');
+ }
+ }else{
+ if (typeof id !== 'undefined' && id !== false) {
+ targetLi.append('<ul><li id="'+id+'">'+sourceliClone.html()+'</li></ul>');
+ }else{
+ targetLi.append('<ul><li>'+sourceliClone.html()+'</li></ul>');
+ }
+ }
+
+ }); // handleDropEvent
+
+ } // Drag and drop
+ };
+
+ // Option defaults
+ $.fn.jOrgChart.defaults = {
+ chartElement : 'body',
+ depth : -1,
+ chartClass : "jOrgChart",
+ dragAndDrop: false
+ };
+
+ // Method that recursively builds the tree
+ function buildNode($node, $appendTo, level, opts) {
+ var $table = $("<table cellpadding='0' cellspacing='0' border='0'/>");
+ var $tbody = $("<tbody/>");
+
+ // Construct the node container(s)
+ var $nodeRow = $("<tr/>").addClass("node-cells");
+ var $nodeCell = $("<td/>").addClass("node-cell").attr("colspan", 2);
+ var $childNodes = $node.children("ul:first").children("li");
+ var $nodeDiv;
+
+ if($childNodes.length > 1) {
+ $nodeCell.attr("colspan", $childNodes.length * 2);
+ }
+ // Draw the node
+ // Get the contents - any markup except li and ul allowed
+ var $nodeContent = $node.clone()
+ .children("ul,li")
+ .remove()
+ .end()
+ .html();
+
+ var new_node_id = $node.attr("id");
+ if (typeof new_node_id !== 'undefined' && new_node_id !== false) {
+ $nodeDiv = $("<div>").addClass("node").attr("id", $node.attr("id")).append($nodeContent);
+ }else{
+ $nodeDiv = $("<div>").addClass("node").append($nodeContent);
+ }
+
+ // Expand and contract nodes
+ if ($childNodes.length > 0) {
+ $nodeDiv.click(function() {
+ var $this = $(this);
+ var $tr = $this.closest("tr");
+
+ if($tr.hasClass('contracted')){
+ $this.css('cursor','n-resize');
+ $tr.removeClass('contracted').addClass('expanded');
+ $tr.nextAll("tr").css('visibility', '');
+ }else{
+ $this.css('cursor','s-resize');
+ $tr.removeClass('expanded').addClass('contracted');
+ $tr.nextAll("tr").css('visibility', 'hidden');
+ }
+ });
+ }
+
+ $nodeCell.append($nodeDiv);
+ $nodeRow.append($nodeCell);
+ $tbody.append($nodeRow);
+
+ if($childNodes.length > 0) {
+ // if it can be expanded then change the cursor
+ $nodeDiv.css('cursor','n-resize').addClass('expanded');
+
+ // recurse until leaves found (-1) or to the level specified
+ if(opts.depth == -1 || (level+1 < opts.depth)) {
+ var $downLineRow = $("<tr/>");
+ var $downLineCell = $("<td/>").attr("colspan", $childNodes.length*2);
+ $downLineRow.append($downLineCell);
+
+ // draw the connecting line from the parent node to the horizontal line
+ $downLine = $("<div></div>").addClass("line down");
+ $downLineCell.append($downLine);
+ $tbody.append($downLineRow);
+
+ // Draw the horizontal lines
+ var $linesRow = $("<tr/>");
+ $childNodes.each(function() {
+ var $left = $("<td>&nbsp;</td>").addClass("line left top");
+ var $right = $("<td>&nbsp;</td>").addClass("line right top");
+ $linesRow.append($left).append($right);
+ });
+
+ // horizontal line shouldn't extend beyond the first and last child branches
+ $linesRow.find("td:first")
+ .removeClass("top")
+ .end()
+ .find("td:last")
+ .removeClass("top");
+
+ $tbody.append($linesRow);
+ var $childNodesRow = $("<tr/>");
+ $childNodes.each(function() {
+ var $td = $("<td class='node-container'/>");
+ $td.attr("colspan", 2);
+ // recurse through children lists and items
+ buildNode($(this), $td, level+1, opts);
+ $childNodesRow.append($td);
+ });
+
+ }
+ $tbody.append($childNodesRow);
+ }
+
+ // any classes on the LI element get copied to the relevant node in the tree
+ // apart from the special 'collapsed' class, which collapses the sub-tree at this point
+ if ($node.attr('class') != undefined) {
+ var classList = $node.attr('class').split(/\s+/);
+ $.each(classList, function(index,item) {
+ if (item == 'collapsed') {
+ $nodeRow.nextAll('tr').css('display', 'none');
+ $nodeRow.removeClass('expanded');
+ $nodeRow.addClass('contracted');
+ $nodeDiv.css('cursor','s-resize');
+ } else {
+ $nodeDiv.addClass(item);
+ }
+ });
+ }
+
+ $table.append($tbody);
+ $appendTo.append($table);
+
+ /* Prevent trees collapsing if a link inside a node is clicked */
+ $nodeDiv.children('a').click(function(e){
+ console.log(e);
+ e.stopPropagation();
+ });
+ };
+
+})(jQuery);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/prettify.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/prettify.js
new file mode 100644
index 00000000..eef5ad7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/samples/org_chart/prettify.js
@@ -0,0 +1,28 @@
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
+f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
+(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
+{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
+t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
+"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
+l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
+q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
+q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
+"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
+a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
+for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
+m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
+a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
+j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
+H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
+J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
+I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
+["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
+/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
+["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
+hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
+!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
+250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
+PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/showdown/0.3.4/showdown.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/showdown/0.3.4/showdown.js
new file mode 100644
index 00000000..25bed634
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/showdown/0.3.4/showdown.js
@@ -0,0 +1,1454 @@
+//
+// showdown.js -- A javascript port of Markdown.
+//
+// Copyright (c) 2007 John Fraser.
+//
+// Original Markdown Copyright (c) 2004-2005 John Gruber
+// <http://daringfireball.net/projects/markdown/>
+//
+// Redistributable under a BSD-style open source license.
+// See license.txt for more information.
+//
+// The full source distribution is at:
+//
+// A A L
+// T C A
+// T K B
+//
+// <http://www.attacklab.net/>
+//
+
+//
+// Wherever possible, Showdown is a straight, line-by-line port
+// of the Perl version of Markdown.
+//
+// This is not a normal parser design; it's basically just a
+// series of string substitutions. It's hard to read and
+// maintain this way, but keeping Showdown close to the original
+// design makes it easier to port new features.
+//
+// More importantly, Showdown behaves like markdown.pl in most
+// edge cases. So web applications can do client-side preview
+// in Javascript, and then build identical HTML on the server.
+//
+// This port needs the new RegExp functionality of ECMA 262,
+// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers
+// should do fine. Even with the new regular expression features,
+// We do a lot of work to emulate Perl's regex functionality.
+// The tricky changes in this file mostly have the "attacklab:"
+// label. Major or self-explanatory changes don't.
+//
+// Smart diff tools like Araxis Merge will be able to match up
+// this file with markdown.pl in a useful way. A little tweaking
+// helps: in a copy of markdown.pl, replace "#" with "//" and
+// replace "$text" with "text". Be sure to ignore whitespace
+// and line endings.
+//
+
+
+//
+// Showdown usage:
+//
+// var text = "Markdown *rocks*.";
+//
+// var converter = new Showdown.converter();
+// var html = converter.makeHtml(text);
+//
+// alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+
+
+//
+// Showdown namespace
+//
+var Showdown = {extensions: {}};
+
+//
+// forEach
+//
+var forEach = Showdown.forEach = function (obj, callback) {
+ if (typeof obj.forEach === 'function') {
+ obj.forEach(callback);
+ } else {
+ var i, len = obj.length;
+ for (i = 0; i < len; i++) {
+ callback(obj[i], i, obj);
+ }
+ }
+};
+
+//
+// Standard extension naming
+//
+var stdExtName = function (s) {
+ return s.replace(/[_-]||\s/g, '').toLowerCase();
+};
+
+//
+// converter
+//
+// Wraps all "globals" so that the only thing
+// exposed is makeHtml().
+//
+Showdown.converter = function (converter_options) {
+
+//
+// Globals:
+//
+
+// Global hashes, used by various utility routines
+ var g_urls;
+ var g_titles;
+ var g_html_blocks;
+
+// Used to track when we're inside an ordered or unordered list
+// (see _ProcessListItems() for details):
+ var g_list_level = 0;
+
+// Global extensions
+ var g_lang_extensions = [];
+ var g_output_modifiers = [];
+
+
+//
+// Automatic Extension Loading (node only):
+//
+ if (typeof module !== 'undefined' && typeof exports !== 'undefined' && typeof require !== 'undefined') {
+ var fs = require('fs');
+
+ if (fs) {
+ // Search extensions folder
+ var extensions = fs.readdirSync((__dirname || '.') + '/extensions').filter(function (file) {
+ return ~file.indexOf('.js');
+ }).map(function (file) {
+ return file.replace(/\.js$/, '');
+ });
+ // Load extensions into Showdown namespace
+ Showdown.forEach(extensions, function (ext) {
+ var name = stdExtName(ext);
+ Showdown.extensions[name] = require('./extensions/' + ext);
+ });
+ }
+ }
+
+ this.makeHtml = function (text) {
+//
+// Main function. The order in which other subs are called here is
+// essential. Link and image substitutions need to happen before
+// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
+// and <img> tags get encoded.
+//
+
+ // Clear the global hashes. If we don't clear these, you get conflicts
+ // from other articles when generating a page which contains more than
+ // one article (e.g. an index page that shows the N most recent
+ // articles):
+ g_urls = {};
+ g_titles = {};
+ g_html_blocks = [];
+
+ // attacklab: Replace ~ with ~T
+ // This lets us use tilde as an escape char to avoid md5 hashes
+ // The choice of character is arbitray; anything that isn't
+ // magic in Markdown will work.
+ text = text.replace(/~/g, "~T");
+
+ // attacklab: Replace $ with ~D
+ // RegExp interprets $ as a special character
+ // when it's in a replacement string
+ text = text.replace(/\$/g, "~D");
+
+ // Standardize line endings
+ text = text.replace(/\r\n/g, "\n"); // DOS to Unix
+ text = text.replace(/\r/g, "\n"); // Mac to Unix
+
+ // Make sure text begins and ends with a couple of newlines:
+ text = "\n\n" + text + "\n\n";
+
+ // Convert all tabs to spaces.
+ text = _Detab(text);
+
+ // Strip any lines consisting only of spaces and tabs.
+ // This makes subsequent regexen easier to write, because we can
+ // match consecutive blank lines with /\n+/ instead of something
+ // contorted like /[ \t]*\n+/ .
+ text = text.replace(/^[ \t]+$/mg, "");
+
+ // Run language extensions
+ Showdown.forEach(g_lang_extensions, function (x) {
+ text = _ExecuteExtension(x, text);
+ });
+
+ // Handle github codeblocks prior to running HashHTML so that
+ // HTML contained within the codeblock gets escaped propertly
+ text = _DoGithubCodeBlocks(text);
+
+ // Turn block-level HTML blocks into hash entries
+ text = _HashHTMLBlocks(text);
+
+ // Strip link definitions, store in hashes.
+ text = _StripLinkDefinitions(text);
+
+ text = _RunBlockGamut(text);
+
+ text = _UnescapeSpecialChars(text);
+
+ // attacklab: Restore dollar signs
+ text = text.replace(/~D/g, "$$");
+
+ // attacklab: Restore tildes
+ text = text.replace(/~T/g, "~");
+
+ // Run output modifiers
+ Showdown.forEach(g_output_modifiers, function (x) {
+ text = _ExecuteExtension(x, text);
+ });
+
+ return text;
+ };
+
+
+//
+// Options:
+//
+
+// Parse extensions options into separate arrays
+ if (converter_options && converter_options.extensions) {
+
+ var self = this;
+
+ // Iterate over each plugin
+ Showdown.forEach(converter_options.extensions, function (plugin) {
+
+ // Assume it's a bundled plugin if a string is given
+ if (typeof plugin === 'string') {
+ plugin = Showdown.extensions[stdExtName(plugin)];
+ }
+
+ if (typeof plugin === 'function') {
+ // Iterate over each extension within that plugin
+ Showdown.forEach(plugin(self), function (ext) {
+ // Sort extensions by type
+ if (ext.type) {
+ if (ext.type === 'language' || ext.type === 'lang') {
+ g_lang_extensions.push(ext);
+ } else if (ext.type === 'output' || ext.type === 'html') {
+ g_output_modifiers.push(ext);
+ }
+ } else {
+ // Assume language extension
+ g_output_modifiers.push(ext);
+ }
+ });
+ } else {
+ throw "Extension '" + plugin + "' could not be loaded. It was either not found or is not a valid extension.";
+ }
+ });
+ }
+
+
+ var _ExecuteExtension = function (ext, text) {
+ if (ext.regex) {
+ var re = new RegExp(ext.regex, 'g');
+ return text.replace(re, ext.replace);
+ } else if (ext.filter) {
+ return ext.filter(text);
+ }
+ };
+
+ var _StripLinkDefinitions = function (text) {
+//
+// Strips link definitions from text, stores the URLs and titles in
+// hash references.
+//
+
+ // Link defs are in the form: ^[id]: url "optional title"
+
+ /*
+ var text = text.replace(/
+ ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
+ [ \t]*
+ \n? // maybe *one* newline
+ [ \t]*
+ <?(\S+?)>? // url = $2
+ [ \t]*
+ \n? // maybe one newline
+ [ \t]*
+ (?:
+ (\n*) // any lines skipped = $3 attacklab: lookbehind removed
+ ["(]
+ (.+?) // title = $4
+ [")]
+ [ \t]*
+ )? // title is optional
+ (?:\n+|$)
+ /gm,
+ function(){...});
+ */
+
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+ text += "~0";
+
+ text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,
+ function (wholeMatch, m1, m2, m3, m4) {
+ m1 = m1.toLowerCase();
+ g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive
+ if (m3) {
+ // Oops, found blank lines, so it's not a title.
+ // Put back the parenthetical statement we stole.
+ return m3 + m4;
+ } else if (m4) {
+ g_titles[m1] = m4.replace(/"/g, "&quot;");
+ }
+
+ // Completely remove the definition from the text
+ return "";
+ }
+ );
+
+ // attacklab: strip sentinel
+ text = text.replace(/~0/, "");
+
+ return text;
+ }
+
+ var _HashHTMLBlocks = function (text) {
+ // attacklab: Double up blank lines to reduce lookaround
+ text = text.replace(/\n/g, "\n\n");
+
+ // Hashify HTML blocks:
+ // We only want to do this for block-level HTML tags, such as headers,
+ // lists, and tables. That's because we still want to wrap <p>s around
+ // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ // phrase emphasis, and spans. The list of tags we're looking for is
+ // hard-coded:
+ var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside";
+ var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";
+
+ // First, look for nested blocks, e.g.:
+ // <div>
+ // <div>
+ // tags for inner block must be indented.
+ // </div>
+ // </div>
+ //
+ // The outermost tags must start at the left margin for this to match, and
+ // the inner nested divs must be indented.
+ // We need to do this before the next, more liberal match, because the next
+ // match will start at the first `<div>` and stop at the first `</div>`.
+
+ // attacklab: This regex can be expensive when it fails.
+ /*
+ var text = text.replace(/
+ ( // save in $1
+ ^ // start of line (with /m)
+ <($block_tags_a) // start tag = $2
+ \b // word break
+ // attacklab: hack around khtml/pcre bug...
+ [^\r]*?\n // any number of lines, minimally matching
+ </\2> // the matching end tag
+ [ \t]* // trailing spaces/tabs
+ (?=\n+) // followed by a newline
+ ) // attacklab: there are sentinel newlines at end of document
+ /gm,function(){...}};
+ */
+ text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement);
+
+ //
+ // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
+ //
+
+ /*
+ var text = text.replace(/
+ ( // save in $1
+ ^ // start of line (with /m)
+ <($block_tags_b) // start tag = $2
+ \b // word break
+ // attacklab: hack around khtml/pcre bug...
+ [^\r]*? // any number of lines, minimally matching
+ </\2> // the matching end tag
+ [ \t]* // trailing spaces/tabs
+ (?=\n+) // followed by a newline
+ ) // attacklab: there are sentinel newlines at end of document
+ /gm,function(){...}};
+ */
+ text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement);
+
+ // Special case just for <hr />. It was easier to make a special case than
+ // to make the other regex more complicated.
+
+ /*
+ text = text.replace(/
+ ( // save in $1
+ \n\n // Starting after a blank line
+ [ ]{0,3}
+ (<(hr) // start tag = $2
+ \b // word break
+ ([^<>])*? //
+ \/?>) // the matching end tag
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashElement);
+ */
+ text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement);
+
+ // Special case for standalone HTML comments:
+
+ /*
+ text = text.replace(/
+ ( // save in $1
+ \n\n // Starting after a blank line
+ [ ]{0,3} // attacklab: g_tab_width - 1
+ <!
+ (--[^\r]*?--\s*)+
+ >
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashElement);
+ */
+ text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g, hashElement);
+
+ // PHP and ASP-style processor instructions (<?...?> and <%...%>)
+
+ /*
+ text = text.replace(/
+ (?:
+ \n\n // Starting after a blank line
+ )
+ ( // save in $1
+ [ ]{0,3} // attacklab: g_tab_width - 1
+ (?:
+ <([?%]) // $2
+ [^\r]*?
+ \2>
+ )
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashElement);
+ */
+ text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement);
+
+ // attacklab: Undo double lines (see comment at top of this function)
+ text = text.replace(/\n\n/g, "\n");
+ return text;
+ }
+
+ var hashElement = function (wholeMatch, m1) {
+ var blockText = m1;
+
+ // Undo double lines
+ blockText = blockText.replace(/\n\n/g, "\n");
+ blockText = blockText.replace(/^\n/, "");
+
+ // strip trailing blank lines
+ blockText = blockText.replace(/\n+$/g, "");
+
+ // Replace the element text with a marker ("~KxK" where x is its key)
+ blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n";
+
+ return blockText;
+ };
+
+ var _RunBlockGamut = function (text) {
+//
+// These are all the transformations that form block-level
+// tags like paragraphs, headers, and list items.
+//
+ text = _DoHeaders(text);
+
+ // Do Horizontal Rules:
+ var key = hashBlock("<hr />");
+ text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
+ text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
+ text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, key);
+
+ text = _DoLists(text);
+ text = _DoCodeBlocks(text);
+ text = _DoBlockQuotes(text);
+
+ // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+ // was to escape raw HTML in the original Markdown source. This time,
+ // we're escaping the markup we've just created, so that we don't wrap
+ // <p> tags around block-level tags.
+ text = _HashHTMLBlocks(text);
+ text = _FormParagraphs(text);
+
+ return text;
+ };
+
+ var _RunSpanGamut = function (text) {
+//
+// These are all the transformations that occur *within* block-level
+// tags like paragraphs, headers, and list items.
+//
+
+ text = _DoCodeSpans(text);
+ text = _EscapeSpecialCharsWithinTagAttributes(text);
+ text = _EncodeBackslashEscapes(text);
+
+ // Process anchor and image tags. Images must come first,
+ // because ![foo][f] looks like an anchor.
+ text = _DoImages(text);
+ text = _DoAnchors(text);
+
+ // Make links out of things like `<http://example.com/>`
+ // Must come after _DoAnchors(), because you can use < and >
+ // delimiters in inline links like [this](<url>).
+ text = _DoAutoLinks(text);
+ text = _EncodeAmpsAndAngles(text);
+ text = _DoItalicsAndBold(text);
+
+ // Do hard breaks:
+ text = text.replace(/ +\n/g, " <br />\n");
+
+ return text;
+ }
+
+ var _EscapeSpecialCharsWithinTagAttributes = function (text) {
+//
+// Within tags -- meaning between < and > -- encode [\ ` * _] so they
+// don't conflict with their use in Markdown for code, italics and strong.
+//
+
+ // Build a regex to find HTML tags and comments. See Friedl's
+ // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+ var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+
+ text = text.replace(regex, function (wholeMatch) {
+ var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
+ tag = escapeCharacters(tag, "\\`*_");
+ return tag;
+ });
+
+ return text;
+ }
+
+ var _DoAnchors = function (text) {
+//
+// Turn Markdown link shortcuts into XHTML <a> tags.
+//
+ //
+ // First, handle reference-style links: [link text] [id]
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ (
+ (?:
+ \[[^\]]*\] // allow brackets nested one level
+ |
+ [^\[] // or anything else
+ )*
+ )
+ \]
+
+ [ ]? // one optional space
+ (?:\n[ ]*)? // one optional newline followed by spaces
+
+ \[
+ (.*?) // id = $3
+ \]
+ )()()()() // pad remaining backreferences
+ /g,_DoAnchors_callback);
+ */
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
+
+ //
+ // Next, inline-style links: [link text](url "optional title")
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ (
+ (?:
+ \[[^\]]*\] // allow brackets nested one level
+ |
+ [^\[\]] // or anything else
+ )
+ )
+ \]
+ \( // literal paren
+ [ \t]*
+ () // no id, so leave $3 empty
+ <?(.*?)>? // href = $4
+ [ \t]*
+ ( // $5
+ (['"]) // quote char = $6
+ (.*?) // Title = $7
+ \6 // matching quote
+ [ \t]* // ignore any spaces/tabs between closing quote and )
+ )? // title is optional
+ \)
+ )
+ /g,writeAnchorTag);
+ */
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
+
+ //
+ // Last, handle reference-style shortcuts: [link text]
+ // These must come last in case you've also got [link test][1]
+ // or [link test](/foo)
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ ([^\[\]]+) // link text = $2; can't contain '[' or ']'
+ \]
+ )()()()()() // pad rest of backreferences
+ /g, writeAnchorTag);
+ */
+ text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+ return text;
+ }
+
+ var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+ if (m7 == undefined) m7 = "";
+ var whole_match = m1;
+ var link_text = m2;
+ var link_id = m3.toLowerCase();
+ var url = m4;
+ var title = m7;
+
+ if (url == "") {
+ if (link_id == "") {
+ // lower-case and turn embedded newlines into spaces
+ link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
+ }
+ url = "#" + link_id;
+
+ if (g_urls[link_id] != undefined) {
+ url = g_urls[link_id];
+ if (g_titles[link_id] != undefined) {
+ title = g_titles[link_id];
+ }
+ }
+ else {
+ if (whole_match.search(/\(\s*\)$/m) > -1) {
+ // Special case for explicit empty url
+ url = "";
+ } else {
+ return whole_match;
+ }
+ }
+ }
+
+ url = escapeCharacters(url, "*_");
+ var result = "<a href=\"" + url + "\"";
+
+ if (title != "") {
+ title = title.replace(/"/g, "&quot;");
+ title = escapeCharacters(title, "*_");
+ result += " title=\"" + title + "\"";
+ }
+
+ result += ">" + link_text + "</a>";
+
+ return result;
+ }
+
+ var _DoImages = function (text) {
+//
+// Turn Markdown image shortcuts into <img> tags.
+//
+
+ //
+ // First, handle reference-style labeled images: ![alt text][id]
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ !\[
+ (.*?) // alt text = $2
+ \]
+
+ [ ]? // one optional space
+ (?:\n[ ]*)? // one optional newline followed by spaces
+
+ \[
+ (.*?) // id = $3
+ \]
+ )()()()() // pad rest of backreferences
+ /g,writeImageTag);
+ */
+ text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
+
+ //
+ // Next, handle inline images: ![alt text](url "optional title")
+ // Don't forget: encode * and _
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ !\[
+ (.*?) // alt text = $2
+ \]
+ \s? // One optional whitespace character
+ \( // literal paren
+ [ \t]*
+ () // no id, so leave $3 empty
+ <?(\S+?)>? // src url = $4
+ [ \t]*
+ ( // $5
+ (['"]) // quote char = $6
+ (.*?) // title = $7
+ \6 // matching quote
+ [ \t]*
+ )? // title is optional
+ \)
+ )
+ /g,writeImageTag);
+ */
+ text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
+
+ return text;
+ }
+
+ var writeImageTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+ var whole_match = m1;
+ var alt_text = m2;
+ var link_id = m3.toLowerCase();
+ var url = m4;
+ var title = m7;
+
+ if (!title) title = "";
+
+ if (url == "") {
+ if (link_id == "") {
+ // lower-case and turn embedded newlines into spaces
+ link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
+ }
+ url = "#" + link_id;
+
+ if (g_urls[link_id] != undefined) {
+ url = g_urls[link_id];
+ if (g_titles[link_id] != undefined) {
+ title = g_titles[link_id];
+ }
+ }
+ else {
+ return whole_match;
+ }
+ }
+
+ alt_text = alt_text.replace(/"/g, "&quot;");
+ url = escapeCharacters(url, "*_");
+ var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
+
+ // attacklab: Markdown.pl adds empty title attributes to images.
+ // Replicate this bug.
+
+ //if (title != "") {
+ title = title.replace(/"/g, "&quot;");
+ title = escapeCharacters(title, "*_");
+ result += " title=\"" + title + "\"";
+ //}
+
+ result += " />";
+
+ return result;
+ }
+
+ var _DoHeaders = function (text) {
+
+ // Setext-style headers:
+ // Header 1
+ // ========
+ //
+ // Header 2
+ // --------
+ //
+ text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+ function (wholeMatch, m1) {
+ return hashBlock('<h1 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h1>");
+ });
+
+ text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+ function (matchFound, m1) {
+ return hashBlock('<h2 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h2>");
+ });
+
+ // atx-style headers:
+ // # Header 1
+ // ## Header 2
+ // ## Header 2 with closing hashes ##
+ // ...
+ // ###### Header 6
+ //
+
+ /*
+ text = text.replace(/
+ ^(\#{1,6}) // $1 = string of #'s
+ [ \t]*
+ (.+?) // $2 = Header text
+ [ \t]*
+ \#* // optional closing #'s (not counted)
+ \n+
+ /gm, function() {...});
+ */
+
+ text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
+ function (wholeMatch, m1, m2) {
+ var h_level = m1.length;
+ return hashBlock("<h" + h_level + ' id="' + headerId(m2) + '">' + _RunSpanGamut(m2) + "</h" + h_level + ">");
+ });
+
+ function headerId(m) {
+ return m.replace(/[^\w]/g, '').toLowerCase();
+ }
+
+ return text;
+ }
+
+// This declaration keeps Dojo compressor from outputting garbage:
+ var _ProcessListItems;
+
+ var _DoLists = function (text) {
+//
+// Form HTML ordered (numbered) and unordered (bulleted) lists.
+//
+
+ // attacklab: add sentinel to hack around khtml/safari bug:
+ // http://bugs.webkit.org/show_bug.cgi?id=11231
+ text += "~0";
+
+ // Re-usable pattern to match any entirel ul or ol list:
+
+ /*
+ var whole_list = /
+ ( // $1 = whole list
+ ( // $2
+ [ ]{0,3} // attacklab: g_tab_width - 1
+ ([*+-]|\d+[.]) // $3 = first list item marker
+ [ \t]+
+ )
+ [^\r]+?
+ ( // $4
+ ~0 // sentinel for workaround; should be $
+ |
+ \n{2,}
+ (?=\S)
+ (?! // Negative lookahead for another list item marker
+ [ \t]*
+ (?:[*+-]|\d+[.])[ \t]+
+ )
+ )
+ )/g
+ */
+ var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+ if (g_list_level) {
+ text = text.replace(whole_list, function (wholeMatch, m1, m2) {
+ var list = m1;
+ var list_type = (m2.search(/[*+-]/g) > -1) ? "ul" : "ol";
+
+ // Turn double returns into triple returns, so that we can make a
+ // paragraph for the last item in a list, if necessary:
+ list = list.replace(/\n{2,}/g, "\n\n\n");
+ ;
+ var result = _ProcessListItems(list);
+
+ // Trim any trailing whitespace, to put the closing `</$list_type>`
+ // up on the preceding line, to get it past the current stupid
+ // HTML block parser. This is a hack to work around the terrible
+ // hack that is the HTML block parser.
+ result = result.replace(/\s+$/, "");
+ result = "<" + list_type + ">" + result + "</" + list_type + ">\n";
+ return result;
+ });
+ } else {
+ whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
+ text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) {
+ var runup = m1;
+ var list = m2;
+
+ var list_type = (m3.search(/[*+-]/g) > -1) ? "ul" : "ol";
+ // Turn double returns into triple returns, so that we can make a
+ // paragraph for the last item in a list, if necessary:
+ var list = list.replace(/\n{2,}/g, "\n\n\n");
+ ;
+ var result = _ProcessListItems(list);
+ result = runup + "<" + list_type + ">\n" + result + "</" + list_type + ">\n";
+ return result;
+ });
+ }
+
+ // attacklab: strip sentinel
+ text = text.replace(/~0/, "");
+
+ return text;
+ }
+
+ _ProcessListItems = function (list_str) {
+//
+// Process the contents of a single ordered or unordered list, splitting it
+// into individual list items.
+//
+ // The $g_list_level global keeps track of when we're inside a list.
+ // Each time we enter a list, we increment it; when we leave a list,
+ // we decrement. If it's zero, we're not in a list anymore.
+ //
+ // We do this because when we're not inside a list, we want to treat
+ // something like this:
+ //
+ // I recommend upgrading to version
+ // 8. Oops, now this line is treated
+ // as a sub-list.
+ //
+ // As a single paragraph, despite the fact that the second line starts
+ // with a digit-period-space sequence.
+ //
+ // Whereas when we're inside a list (or sub-list), that line will be
+ // treated as the start of a sub-list. What a kludge, huh? This is
+ // an aspect of Markdown's syntax that's hard to parse perfectly
+ // without resorting to mind-reading. Perhaps the solution is to
+ // change the syntax rules such that sub-lists must start with a
+ // starting cardinal number; e.g. "1." or "a.".
+
+ g_list_level++;
+
+ // trim trailing blank lines:
+ list_str = list_str.replace(/\n{2,}$/, "\n");
+
+ // attacklab: add sentinel to emulate \z
+ list_str += "~0";
+
+ /*
+ list_str = list_str.replace(/
+ (\n)? // leading line = $1
+ (^[ \t]*) // leading whitespace = $2
+ ([*+-]|\d+[.]) [ \t]+ // list marker = $3
+ ([^\r]+? // list item text = $4
+ (\n{1,2}))
+ (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
+ /gm, function(){...});
+ */
+ list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+ function (wholeMatch, m1, m2, m3, m4) {
+ var item = m4;
+ var leading_line = m1;
+ var leading_space = m2;
+
+ if (leading_line || (item.search(/\n{2,}/) > -1)) {
+ item = _RunBlockGamut(_Outdent(item));
+ }
+ else {
+ // Recursion for sub-lists:
+ item = _DoLists(_Outdent(item));
+ item = item.replace(/\n$/, ""); // chomp(item)
+ item = _RunSpanGamut(item);
+ }
+
+ return "<li>" + item + "</li>\n";
+ }
+ );
+
+ // attacklab: strip sentinel
+ list_str = list_str.replace(/~0/g, "");
+
+ g_list_level--;
+ return list_str;
+ }
+
+ var _DoCodeBlocks = function (text) {
+//
+// Process Markdown `<pre><code>` blocks.
+//
+
+ /*
+ text = text.replace(text,
+ /(?:\n\n|^)
+ ( // $1 = the code block -- one or more lines, starting with a space/tab
+ (?:
+ (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+ .*\n+
+ )+
+ )
+ (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
+ /g,function(){...});
+ */
+
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+ text += "~0";
+
+ text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+ function (wholeMatch, m1, m2) {
+ var codeblock = m1;
+ var nextChar = m2;
+
+ codeblock = _EncodeCode(_Outdent(codeblock));
+ codeblock = _Detab(codeblock);
+ codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
+ codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
+
+ codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
+
+ return hashBlock(codeblock) + nextChar;
+ }
+ );
+
+ // attacklab: strip sentinel
+ text = text.replace(/~0/, "");
+
+ return text;
+ };
+
+ var _DoGithubCodeBlocks = function (text) {
+//
+// Process Github-style code blocks
+// Example:
+// ```ruby
+// def hello_world(x)
+// puts "Hello, #{x}"
+// end
+// ```
+//
+
+
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+ text += "~0";
+
+ text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,
+ function (wholeMatch, m1, m2) {
+ var language = m1;
+ var codeblock = m2;
+
+ codeblock = _EncodeCode(codeblock);
+ codeblock = _Detab(codeblock);
+ codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
+ codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
+
+ codeblock = "<pre><code" + (language ? " class=\"" + language + '"' : "") + ">" + codeblock + "\n</code></pre>";
+
+ return hashBlock(codeblock);
+ }
+ );
+
+ // attacklab: strip sentinel
+ text = text.replace(/~0/, "");
+
+ return text;
+ }
+
+ var hashBlock = function (text) {
+ text = text.replace(/(^\n+|\n+$)/g, "");
+ return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
+ }
+
+ var _DoCodeSpans = function (text) {
+//
+// * Backtick quotes are used for <code></code> spans.
+//
+// * You can use multiple backticks as the delimiters if you want to
+// include literal backticks in the code span. So, this input:
+//
+// Just type ``foo `bar` baz`` at the prompt.
+//
+// Will translate to:
+//
+// <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
+//
+// There's no arbitrary limit to the number of backticks you
+// can use as delimters. If you need three consecutive backticks
+// in your code, use four for delimiters, etc.
+//
+// * You can use spaces to get literal backticks at the edges:
+//
+// ... type `` `bar` `` ...
+//
+// Turns to:
+//
+// ... type <code>`bar`</code> ...
+//
+
+ /*
+ text = text.replace(/
+ (^|[^\\]) // Character before opening ` can't be a backslash
+ (`+) // $2 = Opening run of `
+ ( // $3 = The code block
+ [^\r]*?
+ [^`] // attacklab: work around lack of lookbehind
+ )
+ \2 // Matching closer
+ (?!`)
+ /gm, function(){...});
+ */
+
+ text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
+ function (wholeMatch, m1, m2, m3, m4) {
+ var c = m3;
+ c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
+ c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
+ c = _EncodeCode(c);
+ return m1 + "<code>" + c + "</code>";
+ });
+
+ return text;
+ }
+
+ var _EncodeCode = function (text) {
+//
+// Encode/escape certain characters inside Markdown code runs.
+// The point is that in code, these characters are literals,
+// and lose their special Markdown meanings.
+//
+ // Encode all ampersands; HTML entities are not
+ // entities within a Markdown code span.
+ text = text.replace(/&/g, "&amp;");
+
+ // Do the angle bracket song and dance:
+ text = text.replace(/</g, "&lt;");
+ text = text.replace(/>/g, "&gt;");
+
+ // Now, escape characters that are magic in Markdown:
+ text = escapeCharacters(text, "\*_{}[]\\", false);
+
+// jj the line above breaks this:
+//---
+
+//* Item
+
+// 1. Subitem
+
+// special char: *
+//---
+
+ return text;
+ }
+
+ var _DoItalicsAndBold = function (text) {
+
+ // <strong> must go first:
+ text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
+ "<strong>$2</strong>");
+
+ text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
+ "<em>$2</em>");
+
+ return text;
+ }
+
+ var _DoBlockQuotes = function (text) {
+
+ /*
+ text = text.replace(/
+ ( // Wrap whole match in $1
+ (
+ ^[ \t]*>[ \t]? // '>' at the start of a line
+ .+\n // rest of the first line
+ (.+\n)* // subsequent consecutive lines
+ \n* // blanks
+ )+
+ )
+ /gm, function(){...});
+ */
+
+ text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
+ function (wholeMatch, m1) {
+ var bq = m1;
+
+ // attacklab: hack around Konqueror 3.5.4 bug:
+ // "----------bug".replace(/^-/g,"") == "bug"
+
+ bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
+
+ // attacklab: clean up hack
+ bq = bq.replace(/~0/g, "");
+
+ bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines
+ bq = _RunBlockGamut(bq); // recurse
+
+ bq = bq.replace(/(^|\n)/g, "$1 ");
+ // These leading spaces screw with <pre> content, so we need to fix that:
+ bq = bq.replace(
+ /(\s*<pre>[^\r]+?<\/pre>)/gm,
+ function (wholeMatch, m1) {
+ var pre = m1;
+ // attacklab: hack around Konqueror 3.5.4 bug:
+ pre = pre.replace(/^ /mg, "~0");
+ pre = pre.replace(/~0/g, "");
+ return pre;
+ });
+
+ return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
+ });
+ return text;
+ }
+
+ var _FormParagraphs = function (text) {
+//
+// Params:
+// $text - string to process with html <p> tags
+//
+
+ // Strip leading and trailing lines:
+ text = text.replace(/^\n+/g, "");
+ text = text.replace(/\n+$/g, "");
+
+ var grafs = text.split(/\n{2,}/g);
+ var grafsOut = [];
+
+ //
+ // Wrap <p> tags.
+ //
+ var end = grafs.length;
+ for (var i = 0; i < end; i++) {
+ var str = grafs[i];
+
+ // if this is an HTML marker, copy it
+ if (str.search(/~K(\d+)K/g) >= 0) {
+ grafsOut.push(str);
+ }
+ else if (str.search(/\S/) >= 0) {
+ str = _RunSpanGamut(str);
+ str = str.replace(/^([ \t]*)/g, "<p>");
+ str += "</p>"
+ grafsOut.push(str);
+ }
+
+ }
+
+ //
+ // Unhashify HTML blocks
+ //
+ end = grafsOut.length;
+ for (var i = 0; i < end; i++) {
+ // if this is a marker for an html block...
+ while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
+ var blockText = g_html_blocks[RegExp.$1];
+ blockText = blockText.replace(/\$/g, "$$$$"); // Escape any dollar signs
+ grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
+ }
+ }
+
+ return grafsOut.join("\n\n");
+ }
+
+ var _EncodeAmpsAndAngles = function (text) {
+// Smart processing for ampersands and angle brackets that need to be encoded.
+
+ // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+ // http://bumppo.net/projects/amputator/
+ text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&amp;");
+
+ // Encode naked <'s
+ text = text.replace(/<(?![a-z\/?\$!])/gi, "&lt;");
+
+ return text;
+ }
+
+ var _EncodeBackslashEscapes = function (text) {
+//
+// Parameter: String.
+// Returns: The string, with after processing the following backslash
+// escape sequences.
+//
+
+ // attacklab: The polite way to do this is with the new
+ // escapeCharacters() function:
+ //
+ // text = escapeCharacters(text,"\\",true);
+ // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
+ //
+ // ...but we're sidestepping its use of the (slow) RegExp constructor
+ // as an optimization for Firefox. This function gets called a LOT.
+
+ text = text.replace(/\\(\\)/g, escapeCharacters_callback);
+ text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, escapeCharacters_callback);
+ return text;
+ }
+
+ var _DoAutoLinks = function (text) {
+
+ text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, "<a href=\"$1\">$1</a>");
+
+ // Email addresses: <address@domain.foo>
+
+ /*
+ text = text.replace(/
+ <
+ (?:mailto:)?
+ (
+ [-.\w]+
+ \@
+ [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+ )
+ >
+ /gi, _DoAutoLinks_callback());
+ */
+ text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
+ function (wholeMatch, m1) {
+ return _EncodeEmailAddress(_UnescapeSpecialChars(m1));
+ }
+ );
+
+ return text;
+ }
+
+ var _EncodeEmailAddress = function (addr) {
+//
+// Input: an email address, e.g. "foo@example.com"
+//
+// Output: the email address as a mailto link, with each character
+// of the address encoded as either a decimal or hex entity, in
+// the hopes of foiling most address harvesting spam bots. E.g.:
+//
+// <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
+// x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
+// &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
+//
+// Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+// mailing list: <http://tinyurl.com/yu7ue>
+//
+
+ var encode = [
+ function (ch) {
+ return "&#" + ch.charCodeAt(0) + ";";
+ },
+ function (ch) {
+ return "&#x" + ch.charCodeAt(0).toString(16) + ";";
+ },
+ function (ch) {
+ return ch;
+ }
+ ];
+
+ addr = "mailto:" + addr;
+
+ addr = addr.replace(/./g, function (ch) {
+ if (ch == "@") {
+ // this *must* be encoded. I insist.
+ ch = encode[Math.floor(Math.random() * 2)](ch);
+ } else if (ch != ":") {
+ // leave ':' alone (to spot mailto: later)
+ var r = Math.random();
+ // roughly 10% raw, 45% hex, 45% dec
+ ch = (
+ r > .9 ? encode[2](ch) :
+ r > .45 ? encode[1](ch) :
+ encode[0](ch)
+ );
+ }
+ return ch;
+ });
+
+ addr = "<a href=\"" + addr + "\">" + addr + "</a>";
+ addr = addr.replace(/">.+:/g, "\">"); // strip the mailto: from the visible part
+
+ return addr;
+ }
+
+ var _UnescapeSpecialChars = function (text) {
+//
+// Swap back in all the special characters we've hidden.
+//
+ text = text.replace(/~E(\d+)E/g,
+ function (wholeMatch, m1) {
+ var charCodeToReplace = parseInt(m1);
+ return String.fromCharCode(charCodeToReplace);
+ }
+ );
+ return text;
+ }
+
+ var _Outdent = function (text) {
+//
+// Remove one level of line-leading tabs or spaces
+//
+
+ // attacklab: hack around Konqueror 3.5.4 bug:
+ // "----------bug".replace(/^-/g,"") == "bug"
+
+ text = text.replace(/^(\t|[ ]{1,4})/gm, "~0"); // attacklab: g_tab_width
+
+ // attacklab: clean up hack
+ text = text.replace(/~0/g, "")
+
+ return text;
+ }
+
+ var _Detab = function (text) {
+// attacklab: Detab's completely rewritten for speed.
+// In perl we could fix it by anchoring the regexp with \G.
+// In javascript we're less fortunate.
+
+ // expand first n-1 tabs
+ text = text.replace(/\t(?=\t)/g, " "); // attacklab: g_tab_width
+
+ // replace the nth with two sentinels
+ text = text.replace(/\t/g, "~A~B");
+
+ // use the sentinel to anchor our regex so it doesn't explode
+ text = text.replace(/~B(.+?)~A/g,
+ function (wholeMatch, m1, m2) {
+ var leadingText = m1;
+ var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width
+
+ // there *must* be a better way to do this:
+ for (var i = 0; i < numSpaces; i++) leadingText += " ";
+
+ return leadingText;
+ }
+ );
+
+ // clean up sentinels
+ text = text.replace(/~A/g, " "); // attacklab: g_tab_width
+ text = text.replace(/~B/g, "");
+
+ return text;
+ }
+
+
+//
+// attacklab: Utility functions
+//
+
+
+ var escapeCharacters = function (text, charsToEscape, afterBackslash) {
+ // First we have to escape the escape characters so that
+ // we can build a character class out of them
+ var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])";
+
+ if (afterBackslash) {
+ regexString = "\\\\" + regexString;
+ }
+
+ var regex = new RegExp(regexString, "g");
+ text = text.replace(regex, escapeCharacters_callback);
+
+ return text;
+ }
+
+
+ var escapeCharacters_callback = function (wholeMatch, m1) {
+ var charCodeToEscape = m1.charCodeAt(0);
+ return "~E" + charCodeToEscape + "E";
+ }
+
+} // end of Showdown.converter
+
+
+// export
+if (typeof module !== 'undefined') module.exports = Showdown;
+
+// stolen from AMD branch of underscore
+// AMD define happens at the end for compatibility with AMD loaders
+// that don't enforce next-turn semantics on modules.
+if (typeof define === 'function' && define.amd) {
+ define('showdown', function () {
+ return Showdown;
+ });
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/utils/js/browserCheck.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/utils/js/browserCheck.js
new file mode 100644
index 00000000..2a290d04
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/external/utils/js/browserCheck.js
@@ -0,0 +1,5 @@
+var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
+var isFirefox = typeof window.InstallTrigger !== 'undefined';
+var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
+var isChrome = !!window.chrome && !isOpera;
+var isIE = !!document.documentMode; \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/fonts/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/fonts/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js
new file mode 100644
index 00000000..2c8740d6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js
@@ -0,0 +1,15 @@
+app.config(function($routeProvider) {
+ $routeProvider
+
+ //.when('/notebook-frame/:id/:key/:value',{
+ //.when('/notebook-frame/:nid/:qprms',{
+ /*.when('/notebook-frame',{
+ templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
+ controller: 'notebookFrameController'
+ })*/
+
+ .otherwise({
+ templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-viz.html',
+ controller: 'notebookFrameController'
+ });
+}) \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js
new file mode 100644
index 00000000..e6f35384
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js
@@ -0,0 +1,97 @@
+
+app.config(function($routeProvider) {
+ $routeProvider
+
+ .otherwise({
+ // templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
+ templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebookInputs.html',
+ controller: 'nbookController'
+ });
+}).controller('nbookController', ['$scope', '$location','$window','$http', function ($scope,$location,$window,$http) {
+
+ $scope.keyValueList = [{}];
+ console.log('onload nbookController');
+ $scope.submitParameters = function() {
+
+ $scope.iframevisibility = false;
+ console.log('Inside nbook invoke save');
+
+ $scope.postData = {};
+
+ $scope.additionalqueryParams = {};
+
+ //Use this if there is only one 1 query param key value pair
+ $scope.additionalqueryParams.paramKey = $scope.qparamKey;
+ $scope.additionalqueryParams.paramVal = $scope.qparamVal;
+
+
+ // console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
+ console.log('$scope.notebookvalue',$scope.notebookvalue);
+
+
+ console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
+
+ console.log('$scope.keyValueList',$scope.keyValueList);
+
+ console.log('$scope.keyValueList.length',$scope.keyValueList.length);
+
+ var qryStr = '';
+ for(var i = 0; i < $scope.keyValueList.length; i++) {
+ var obj = $scope.keyValueList[i];
+ //console.log('obj.qK',obj.qK);
+ if (obj.qK != undefined && obj.qV != undefined) {
+ //console.log('Inside qk defined');
+ if (qryStr!='')
+ qryStr = qryStr+'&'+obj.qK+'='+obj.qV;
+ else
+ qryStr = obj.qK+'='+obj.qV;
+
+ }
+
+ }
+ console.log('qryStr',qryStr);
+
+
+
+ //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&k1='+$scope.additionalqueryParams.paramKey+'&v1='+$scope.additionalqueryParams.paramVal;
+
+ // var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+$scope.additionalqueryParams.paramKey+'='+$scope.additionalqueryParams.paramVal;
+
+ var queryurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+qryStr;
+
+ // var testurl = 'notebook.htm#/notebook-frame';
+
+ window.open (queryurl,'_self',false);
+
+
+ }
+
+ $scope.addKeyValuePairs = function (kv) {
+
+
+ if ($scope.keyValueList.length < 9) {
+ $scope.keyValueList.push({
+
+ });
+ // alert($scope.reportRunJson.rangeAxisList.length);
+ // console.log('$scope.keyValueList',$scope.keyValueList);
+
+ } else {
+ //document.getElementById("addbtn").disabled = true;
+ // $scope.btnactive = false;
+ document.getElementById("addbtn")["disabled"] = true;
+ //document.getElementById("addbtn")["style.background-color"] = "#FFFF00";
+
+ //$('#addbtn').btn('type') = "disabled";
+ }
+ }
+
+ $scope.removeKeyValuePairs = function (index) {
+ $scope.keyValueList.splice(index, 1);
+ if ($scope.keyValueList.length == 8) {
+ document.getElementById("addbtn")["disabled"] = false;
+ }
+ //console.log($scope.hardCodeReport.rangeAxisList)
+ }
+
+}]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js
new file mode 100644
index 00000000..e819c92f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js
@@ -0,0 +1,81 @@
+/*app.
+controller('notebookFrameController', ['$scope', '$location','$window','$http', function ($scope,$location,$window,$http) {
+
+ $scope.invokeSaveNotebook() = function() {
+
+
+ // $http.post('rNotebookFE/authCr', $scope.postData).success(function(data, status) {
+ $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
+ console.log('Data Sent', data);
+ console.log('Status ', status);
+
+
+
+ // iframe.name = "my_iframe";
+
+ // $scope.ifr = "<div><iframe src='http://www.w3schools.com'/></div>"
+
+ // var url = "https://rcloud.research.att.com";
+ // document.getElementById('itestfr').src = data;
+ window.open ('notebook.htm#/notebook-frame','_self',false);
+ // $scope.iframevisibility = true;
+ // document.getElementById('itestfr').src = data;
+
+
+ })
+
+
+ }
+
+}]);*/
+app.controller('notebookFrameController', function ($scope,$location,$window,$http,$routeParams) {
+
+ //alert($location.search(1, $scope.additionalqueryParams));
+ //var nid = $routeParams.nid;
+ //var qprms = $routeParams.qprms;
+ //var value = $routeParams.value;
+ //console.log('check id ');
+ var nid = $window.location.search.substr($window.location.search.indexOf("=")+1);
+ //console.log('nid',nid);
+ //console.log('qprms',qprms);
+ //$scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
+ $scope.additionalqueryParams={};
+ if ($window.location.search.substr($window.location.search.indexOf("=")+1)) {
+ $scope.queryParams = $window.location.search;
+ //console.log('$window.location.search',$window.location.search.substring(0, $window.location.search.length-1));
+ //if ($window.location.search.indexOf("&")!=-1) {
+ if($window.location.search.substring(0, $window.location.search.length-1).indexOf("&")!=-1) {
+ $scope.notebookparam = $window.location.search.substring($window.location.search.indexOf("?")+1,$window.location.search.indexOf("&"));
+ $scope.additionalqueryParams = JSON.parse('{"' + decodeURI($scope.queryParams.substr($scope.queryParams.indexOf("&")+1).replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}');
+ //console.log('Additional parameters present');
+ }
+ else {
+ $scope.notebookparam1 = $window.location.search.substr($window.location.search.indexOf("?")+1);
+ $scope.notebookparam = $scope.notebookparam1.substring(0, $scope.notebookparam1.length - 1);
+ //console.log('Additional parameters absent');
+ }
+ //console.log('add parameters',$scope.additionalqueryParams);
+ // $scope.notebookid = $scope.notebookparam.substring(0,$scope.notebookparam.indexOf("="));
+ $scope.notebookvalue = $scope.notebookparam.substr($scope.notebookparam.indexOf("=")+1);
+ // $scope.notebookvalue = $scope.notebookvalue1.substring(0, $scope.notebookvalue1.length - 1);
+ //console.log('New VALL',$scope.notebookvalue);
+ //$scope.postData = $window.location.search.substr($window.location.search.indexOf("=")+1);
+ //console.log('Notebook value present ',$scope.notebookvalue);
+ }
+ else {
+ $scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
+ //console.log('Notebook value absent ',$scope.notebookvalue);
+ }
+
+
+
+ $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
+ //console.log('Data received', data);
+ //console.log('Status ', status);
+ document.getElementById('itestframe').src = data;
+
+ })
+
+
+
+});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js
index 9e6a4f4f..9e6a4f4f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/dependency/angular.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html
new file mode 100644
index 00000000..c6dcfa8f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html
@@ -0,0 +1,65 @@
+<!-- <!DOCTYPE html>
+<html>
+<head>
+<meta charset="ISO-8859-1">
+<title>Insert title here</title>
+</head>
+<body>
+<div style="min-height:500px" data-ng-init="invokeSaveNotebook()">
+
+
+ <div><iframe id='itestfr' width="1400" height="1400"></iframe></div>
+
+
+ </div>
+
+</body>
+</html> -->
+
+<!-- <div ng-controller="notebookFrameController" style="min-height:500px">
+
+
+ <div><iframe id='itestframe' width="1400" height="1400"></iframe></div>
+
+
+ </div> -->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta http-equiv="cache-control" content="max-age=0" />
+ <meta http-equiv="cache-control" content="no-cache" />
+ <meta http-equiv="expires" content="0" />
+ <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+ <meta http-equiv="pragma" content="no-cache"/>
+
+ <script src= "app/fusion/scripts/utils/page-resource.js"></script>
+
+ <script>
+ // loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookController.js", "js");
+
+ loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js", "js");
+ loadjscssfile("app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js", "js");
+
+ </script>
+
+
+
+
+ </head>
+ <body class="appBody" ng-app="abs">
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
+ <div q-header></div>
+ <div q-menu class="appLeftMenu"></div>
+ <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:110px;"></div>
+ <div q-footer class="appFooter"></div>
+ </body>
+</html>
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html
new file mode 100644
index 00000000..252b51ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html
@@ -0,0 +1,7 @@
+ <div style="min-height:500px">
+
+
+ <div><iframe id='itestframe' width="1400" height="1400" ></iframe></div>
+
+
+ </div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm
new file mode 100644
index 00000000..71aca7ab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta http-equiv="cache-control" content="max-age=0" />
+ <meta http-equiv="cache-control" content="no-cache" />
+ <meta http-equiv="expires" content="0" />
+ <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+ <meta http-equiv="pragma" content="no-cache"/>
+
+ <script src= "app/fusion/scripts/utils/page-resource.js"></script>
+
+ <script>
+ // loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookController.js", "js");
+ loadjscssfile("app/fusion/notebook-integration/scripts/controllers/nbookController.js", "js");
+ </script>
+
+
+
+
+ </head>
+ <body class="appBody" ng-app="abs">
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
+ <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
+ <div q-header></div>
+ <div q-menu class="appLeftMenu"></div>
+ <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:110px;"></div>
+ <div q-footer class="appFooter"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html
new file mode 100644
index 00000000..0969aa2f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="ISO-8859-1">
+<title></title>
+</head>
+<body>
+
+<div style="min-height:500px">
+ <br>
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label">Notebook ID:</label><BR>
+ <input type="text" name="notebookid" maxlength=200 ng-model="notebookvalue" ng-init="notebookvalue='833c0a69ec1433fbb2f8752af733cf0e'" style="width:180px"/>
+ </div>
+ <BR>
+
+ <!-- Use this for only 1 key value query parameter
+ <div class="fn-ebz-container">
+
+ <label class="fn-ebz-text-label">Key</label><BR>
+ <input type="text" name="key" maxlength=200 ng-model="qparamKey" style="width:180px"/>
+ </div>
+
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label">Value</label><BR>
+ <input type="text" name="val" maxlength=200 ng-model="qparamVal" style="width:180px"/>
+ </div> -->
+
+
+
+ <!-- Use this for multiple key value query parameters -->
+ <div style="border:2px;border-style:solid;border-color:#808080;margin-bottom:9px">
+ <div ng-repeat="kv in keyValueList">
+ <div style="margin-left:5px">
+
+ <div class="fn-ebz-container">
+
+ <label class="fn-ebz-text-label">Key</label><BR>
+ <input type="text" name="key" maxlength=100 ng-model="kv.qK" style="width:180px"/>
+ </div>
+
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label">Value</label><BR>
+ <input type="text" name="val" maxlength=100 ng-model="kv.qV" style="width:180px"/>
+ </div>
+
+ <div class="fn-ebz-container" style="position:relative; top: 25px;">
+ <button href="javascript:void(0)" id="addbtn" ng-show="{{$index==0}}" style="float: right;" att-button size="small" att-accessibility-click="13,32"
+ ng-click="addKeyValuePairs(kv);" >Add</button>
+ <a href="javascript:void(0)" ng-show="{{$index>0}}" style="float: right;" att-button size="small" att-accessibility-click="13,32" ng-click="removeKeyValuePairs($index);" >
+ Remove</a>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+
+
+ <BR>
+
+ <div class="fn-ebz-container">
+ <a att-button btn-type="primary" att-accessibility-click="13,32" ng-click="submitParameters();">Submit</a>
+ </div>
+
+ <!-- <div ng-show="iframevisibility"><iframe id='itestfr' width="1400" height="1400"></iframe></div> -->
+
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-closed-cloop.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-closed-cloop.js
new file mode 100644
index 00000000..94169ff4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-closed-cloop.js
@@ -0,0 +1,28 @@
+appDS2.controller('adminClosedLoopController', ['$scope','$http','$q','$log',function ($scope, $http,$q, $log){
+ $scope.camunda_cockpit_url = '';
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_camunda_cockpit_link",
+ }).success( function(res) {
+ // if the returned response is error HTML page in string format
+ if(res.link_defined=='false'){
+ $log.error('Retrieval of camunda cockpit link failed. Please make sure the variable "camunda_cockpit_url" is defined in the system.properties file.');
+ deferred.reject(status);
+ }
+ // valid cockpit url
+ else if(res.camunda_cockpit_link!=null & res.camunda_cockpit_link!= '') {
+ $scope.camunda_cockpit_url = res.camunda_cockpit_link;
+ deferred.resolve(res);
+ // if the defined url is empty;
+ } else {
+ $log.error('Please ensure the variable "camunda_cockpit_url" is properly defined in system.properties file (i.e., neither null nor empty).');
+ deferred.reject(status);
+ }
+ // API call fails
+ }).error( function(status) {
+ $log.error('get_camunda_cockpit_link RestAPI call failed.');
+ deferred.reject(status);
+ });
+ return deferred.promise;
+}]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-controller.js
new file mode 100644
index 00000000..8d664fcb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-controller.js
@@ -0,0 +1,940 @@
+appDS2.controller('adminController', function($scope, $http,AdminService, $modal, $routeParams, $rootScope){
+
+ $scope.totalPages = 5;
+ $scope.viewPerPage = 8;
+ $scope.searchString = "";
+ $scope.currentPage = 1;
+ $scope.nextSort="";
+ $scope.showLoader = false;
+ $scope.tableData=[];
+ $scope.routeRoleId = $routeParams.roleId;
+ $scope.regions = [];
+ /*function*/
+ $scope.getFunctionList = function(){
+ $scope.tableData.length=0;
+ AdminService.getRoleFunctionList().then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData =JSON.parse($scope.data.availableRoleFunctions);
+ },function(error){
+ console.log("failed");
+ });
+ }
+
+ $scope.getCacheRegionsList = function(){
+ // $scope.regions.length=0;
+ AdminService.getCacheRegions().then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ /* for(var i = 0; i< $scope.data.length; i++){
+ if($scope.data[i].cacheName !== '[object Object]'){
+ $scope.regions.push($scope.data[i]);
+ }
+ }*/
+ $scope.regions =$scope.data;
+ },function(error){
+ console.log("failed");
+ //reloadPageOnce();
+ });
+ }
+
+
+ $scope.delRoleFunc = function(roleData){
+ AdminService.delRoleFunctionList(roleData).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successPopUp();
+ $scope.getFunctionList();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+ $scope.saveRoleFunction = function(roleData){
+ AdminService.saveRoleFunctionList(roleData).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successPopUp();
+ $scope.getFunctionList();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+ $scope.addRoleFunction = function(roleData){
+ AdminService.addRoleFunctionList(roleData).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successPopUp();
+ $scope.getFunctionList();
+ }else if(status=='"code exists"'){
+ $scope.errorPopUp('Code already exists');
+ $scope.getFunctionList();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+ /*init*/
+ $scope.getFunctionList();
+ $scope.getCacheRegionsList();
+ /*popup*/
+ var ModalInstanceCtrl = function ($scope, $modalInstance, items, AdminService,$rootScope) {
+ $scope.roleFun=items;
+ $scope.msg=items;
+
+ // remove role function associated to a role on Role Edit page
+ $scope.roleFunRemoveRole = function (roleFunction) {
+ AdminService.removeRoleFunction(roleFunction, $routeParams.roleId).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.role){
+ $rootScope.$broadcast('updateRoleFunctions',{data:message.role});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ //role activation for selected child role
+ $scope.activateRoleChildConfirmPopUp = function (selected, availableRole) {
+ $scope.msg.roleFun = availableRole.name;
+ $scope.msg.selected = selected;
+ $scope.msg.availableRole = availableRole;
+ var toggleType = null;
+ if(selected) {
+ toggleType = "activate";
+ } else {
+ toggleType = "inactivate";
+ }
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-child-add-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return $scope.msg;
+ }
+ }
+ });
+ }
+
+ // confirm Child Role Add
+ $scope.confirmRoleChildAdd = function(selected,availableRole,id){
+ AdminService.confirmRoleChildAdd(selected,availableRole,id).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.role){
+ //$rootScope.$broadcast('updateAvailbleRoles',{data:message.availableRoles});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ // confirm Child Role Remove
+ $scope.confirmRoleChildRemove = function(selected,availableRole,id){
+ AdminService.confirmRoleChildRemove(selected,availableRole,id).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.role){
+ //$rootScope.$broadcast('updateAvailbleRoles',{data:message.availableRoles});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ //role activation for role function
+ $scope.activateRoleConfirmPopUp = function (selected, availableRole) {
+ $scope.msg.roleFun = availableRole.name;
+ $scope.msg.selected = selected;
+ $scope.msg.availableRole = availableRole;
+ var toggleType = null;
+ if(selected) {
+ toggleType = "activate";
+ } else {
+ toggleType = "inactivate";
+ }
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-add-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return $scope.msg;
+ }
+ }
+ });
+ }
+
+ // confirm Role Function Add
+ $scope.confirmRoleFunAdd = function(selected,availableRole,id){
+ AdminService.confirmRoleFunAdd(selected,availableRole,id).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.role){
+ $rootScope.$broadcast('updateRoleFunctions',{data:message.role});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ // confirm Role Function Remove
+ $scope.confirmRoleFunRemove = function(selected,availableRole,id){
+ AdminService.confirmRoleFunRemove(selected,availableRole,id).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.role){
+ $rootScope.$broadcast('updateRoleFunctions',{data:message.role});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ //role activation
+ $scope.roleActivate = function(selected,availableRole){
+ AdminService.activateRole(selected,availableRole).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.availableRoles){
+ $rootScope.$broadcast('updateAvailbleRoles',{data:message.availableRoles});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+ console.log("error");
+ });
+ }
+
+ //role deletion
+ $scope.delRole = function(roleData){
+ AdminService.delRoleList(roleData).then(function(msg){
+ var message = msg;
+ $scope.cancel();
+ if(message.availableRoles){
+ $rootScope.$broadcast('updateAvailbleRoles',{data:message.availableRoles});
+ /*$modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small',
+ })*/
+ }else{
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ })
+ }
+
+ },function(error){
+
+ });
+ }
+
+ $scope.save = function (data) {
+ $modalInstance.close(data);
+ };
+
+ // Cancel for toggle switch on Role Fn
+ $scope.cancelRoleFunSwitch = function (msg) {
+ $scope.msg.availableRole.selected = !$scope.msg.availableRole.selected;
+ //$scope.msg.availableRoleFunctions[$scope.msg.availableRoleFunctions.indexOf($scope.msg.availableRole)] = $scope.selectedRoleFun;
+ $modalInstance.dismiss('cancel');
+ };
+
+ // Cancel for toggle switch on Role List
+ $scope.cancelRoleSwitch = function (msg) {
+ $scope.msg.availableRole.active = !$scope.msg.availableRole.active;
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.deleteFun = function(data){
+ $modalInstance.close(data);
+ }
+ };
+
+ $scope.successPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+
+ $scope.successTestModelPopUp = function (response) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modalpopup.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-large',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: response
+ };
+ return message;
+ }
+ }
+ });
+ };
+ $scope.errorPopUp = function (msg) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ });
+ };
+ $scope.saveRoleFuncPopUp = function (availableRoleFunction) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-edit.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return availableRoleFunction;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (data) {
+ $scope.saveRoleFunction(data);
+ });
+ }
+
+ $scope.addRoleFuncPopUp = function (availableRoleFunction) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-add.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return availableRoleFunction;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (data) {
+ $scope.addRoleFunction(data);
+ });
+ }
+
+ $scope.delRoleFuncConfirmPopUp = function (availableRoleFunction) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-del-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: availableRoleFunction.name,
+ content: availableRoleFunction
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (data) {
+ $scope.delRoleFunc(data.content);
+ });
+ }
+ $scope.clearAllFuncPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ // return availableRoleFunction;
+ }
+ }
+ });
+
+ modalInstance.result.then(function () {
+ $scope.clearAll();
+ });
+ }
+
+ $scope.clearAll = function(){
+ AdminService.clearAdminRegions().then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successTestModelPopUp('');
+ $scope.getCacheRegionsList();
+ }else{
+ $scope.errorPopUp();
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+ $scope.showRegionDetailsFuncPopUp = function (response) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/success_modalpopup.html',
+ controller: ModalInstanceCtrl,
+ //sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: response,
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (response) {
+ $scope.showRegionDetails(response);
+ });
+ }
+
+ $scope.showRegionDetails = function(cacheName) {
+ AdminService.showRegionDetails(cacheName).then(function(res){
+
+ var message = res.data;
+ var msgParsed = JSON.stringify(message);
+ // alert('1 : '+msgParsed);
+
+ var messaged = message.data;
+ var msgParsedd = JSON.stringify(messaged);
+ //alert('2 : '+msgParsedd);
+ //console.log('2 '+msgParsedd);
+ //console.log('4 '+msgParsedd.substr(3,msgParsedd.length -2).split('\\n'));
+
+
+ if(message.data!=null && message.data!=''){
+ var status = res.status;
+
+
+ if(status==200){
+
+
+
+ var htmlstring = message.data.toString();
+ var htmlStrReplace = htmlstring.replace(/['"]+/g, '');
+ var htmlStrReplaceSplit = htmlStrReplace.split('\n');
+ var dataStr = htmlStrReplace.replace(/\\n/g, "\n"); //htmlstring.replace(/\n/g, " ");
+ $scope.successTestModelPopUp(dataStr);
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+ $scope.clearRegionFuncPopUp = function (cacheName) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-region-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: cacheName
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (cacheName) {
+ $scope.clearRegionFunction(cacheName);
+ });
+ }
+
+ $scope.clearRegionFunction = function(cacheName){
+ AdminService.clearRegionFunction(cacheName).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successPopUp();
+ $scope.getCacheRegionsList()();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+ $scope.clearItemFuncPopUp = function (cacheName, key) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/clearItem-region-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: cacheName
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (cacheName, key) {
+ $scope.clearItemFunction(cacheName, key);
+ });
+ }
+
+ $scope.clearItemFunction = function(cacheName, key){
+ AdminService.clearItemnFunction(cacheName, key).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+ $scope.successPopUp();
+ $scope.getCacheRegionsList()();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+
+ /*$scope.showItemDetails = function(cacheName,key) {
+ $http.get("jcs_admin/showItemDetails?keyName="+key+"&cacheName="+cacheName).success(function(response){
+ var message = "CacheName: "+ response.cacheName
+ +"\nkey: "+response.key
+ +"\nIS_SPOOL: "+response.attr.IS_SPOOL
+ +"\nIS_LATERAL: "+response.attr.IS_LATERAL
+ +"\nIS_REMOTE: "+response.attr.IS_REMOTE
+ +"\nIS_ETERNAL: "+response.attr.IS_ETERNAL
+ +"\nversion: "+response.attr.version
+ +"\nmaxLifeSeconds: "+response.attr.maxLifeSeconds
+ +"\nmaxIdleTimeSeconds: "+response.attr.maxIdleTimeSeconds
+ +"\nsize: "+response.attr.size
+ +"\ncreateTime: "+response.attr.createTime
+ +"\nlastAccessTime: "+response.attr.lastAccessTime
+ +"\nidleTime: "+response.attr.idleTime
+ +"\ntimeToLiveSeconds: "+response.attr.timeToLiveSeconds
+ +"\nisSpool: "+response.attr.isSpool
+ +"\nisLateral: "+response.attr.isLateral
+ +"\nisRemote: "+response.attr.isRemote
+ +"\nisEternal: "+response.attr.isEternal;
+ modalService.showSuccess('',message);});
+ };*/
+
+
+ $scope.showItemDetails = function(cacheName, key){
+ AdminService.showItemDetails(cacheName, key).then(function(msg){
+ var message = msg;
+ if(message.data!=null && message.data!=''){
+ var status = message.data;
+ if(status=='"success"'){
+
+ $scope.successPopUp();
+ $scope.getCacheRegionsList()();
+ }else{
+ $scope.errorPopUp('');
+ }
+ }
+
+ },function(error){
+
+ });
+ }
+
+
+ //role deletion pop up
+ $scope.delRoleConfirmPopUp = function (availableRole) {
+
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-delete-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ availableRole:availableRole,
+ roleName: availableRole.name
+ };
+ return message;
+ }
+ }
+ });
+
+ /*modalInstance.result.then(function (data) {
+ $scope.delRole(data);
+ });*/
+ }
+
+ // role activation
+ $scope.activateRoleConfirmPopUp = function (selected, availableRole) {
+ var toggleType = null;
+ if(selected) {
+ toggleType = "activate";
+ } else {
+ toggleType = "inactivate";
+ }
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-confirm-activation.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ //availableRole: $scope.msg.availableRole,
+ text: toggleType,
+ selected:selected,
+ availableRole:availableRole,
+ roleName:availableRole.name
+ };
+ return message;
+ }
+ }
+ });
+
+ /*modalInstance.result.then(function (data) {
+ $scope.activateRole(data);
+ });*/
+ }
+
+ $scope.roleFnInit = function(){
+ AdminService.getRole($routeParams.roleId).then(function(data){
+
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+
+ $scope.role =JSON.parse($scope.data.role);
+ // console.log($scope.role);
+
+ $scope.ociavailableRoleFunctions =JSON.parse($scope.data.availableRoleFunctions);
+ // console.log($scope.ociavailableRoleFunctions);
+ $scope.availableRoleFunctions=[];
+
+ if($scope.ociavailableRoleFunctions)
+ angular.forEach($scope.ociavailableRoleFunctions, function(a,i){
+ var availableRoleFunction = a;
+ availableRoleFunction.selected = false;
+ angular.forEach($scope.role.roleFunctions, function(b,j){
+ if(a.code === b.code) {
+ availableRoleFunction.selected = true;
+ }
+ });
+ $scope.availableRoleFunctions.push(availableRoleFunction);
+ });
+
+
+ $scope.ociavailableRoles=JSON.parse($scope.data.availableRoles);
+ // console.log($scope.ociavailableRoles);
+ //console.log("testing roles if exist");
+ $scope.availableRoles=[];
+
+ if($scope.ociavailableRoles)
+ angular.forEach($scope.ociavailableRoles, function(a,i){
+ var availableRole = a;
+ availableRole.selected = false;
+ if($scope.role.childRoles){
+ angular.forEach($scope.role.childRoles, function(b,j){
+ if(a.id === b.id) {
+ availableRole.selected = true;
+ }
+ });
+ };
+ $scope.availableRoles.push(availableRole);
+ });
+
+
+ },function(error){
+ console.log("roleControllerDS2 failed: " + error);
+ reloadPageOnce();
+ });
+ }
+
+ // updating roles on role list page after deletion of a role
+ $rootScope.$on('updateAvailbleRoles', function(e,d){
+ $scope.ociavailableRoles = d.data;
+ })
+
+ // updating role functions on roles page after deletion of a role function
+ $rootScope.$on('updateRoleFunctions',function(e,d){
+ $scope.role = d.data;
+ })
+
+ $scope.roleFnInit();
+
+ $scope.saveRole = function() {
+ var errorMsg;
+ // Validate non-empty priority as integer
+ if ($scope.role.priority && $scope.role.priority != '' && isNaN(parseInt($scope.role.priority))) {
+ errorMsg = 'Priority must be an integer.';
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return errorMsg;
+ }
+ }
+ });
+ return;
+ }
+ for (x in $scope.availableRoles){
+ // console.log($scope.availableRoles[x].name);
+ if ($scope.availableRoles[x].name==$scope.role.name){
+ errorMsg = 'Role already exists.';
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return errorMsg;
+ }
+ }
+ });
+ return;
+ }
+ }
+ if(!errorMsg){
+ var postData={
+ role: $scope.role,
+ childRoles: $scope.role.childRoles,
+ roleFunctions : $scope.role.roleFunctions
+ };
+ AdminService.saveRole(postData, $routeParams.roleId).then(function(msg){
+ if(msg.role){
+ //$scope.role = msg.role;
+ sessionStorage.setItem('addCall', true);
+ location.href='admin#/role/'+msg.role.id;
+ $scope.availableRoles.push(msg);
+ $scope.routeRoleId = msg.role.id;
+ $rootScope.$broadcast('updateAvailbleRoles',{data:$scope.availableRoles});
+ //saving the addCall variable in sessionStorage to change the url from AddRole to Edit Role on success of Save and displaying the success pop up
+ if(sessionStorage.addCall){
+ $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ sizeClass: 'modal-small'
+ });
+ sessionStorage.removeItem('addCall');
+ }
+ } else{
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ msg = 'Error saving Role. Please retry';
+ return msg;
+ }
+ }
+ });
+ }
+ },function(error){
+ console.log("error msg");
+ })
+
+ }
+ }
+
+ $scope.addNewRoleFunctionModalPopup = function(data, role,info) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-large',
+ resolve: {
+ items: function () {
+ var message = {
+ roleFunctions:data,
+ role:role,
+ roleId:info.id,
+ availableRoleFunctions:$scope.ociavailableRoleFunctions
+ };
+ return message;
+ }
+ }
+ });
+ }
+
+ $scope.addNewChildRoleFunctionModalPopup = function(data, role,info) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-child-roles-modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-large',
+ resolve: {
+ items: function () {
+ var message = {
+ roleChildFunctions:data,
+ role:role,
+ roleId:info.id
+ };
+ return message;
+ }
+ }
+ });
+ }
+
+ // remove role function associated to a role on Role Edit page
+ $scope.removeRoleFunction= function(roleFunction){
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-role-del-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ roleFunction:roleFunction
+ };
+ return message;
+ }
+ }
+ });
+ }
+
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-menu-edit.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-menu-edit.js
new file mode 100644
index 00000000..00cd92d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-menu-edit.js
@@ -0,0 +1,184 @@
+appDS2.controller('AdminMenuEditController', function ($scope, AdminMenuService, $modal, $route,AdminService){
+
+ $scope.showInput = true;
+ $scope.totalPages1 = 5;
+ $scope.viewPerPage1 = 8;
+ $scope.currentPage1 = 1;
+ $scope.showLoader = false;
+ $scope.firstPlay = true;
+ $scope.tableFnMenuItems = [];
+ $scope.$watch('viewPerPage1', function(val) {
+ $scope.showLoader = true;
+ AdminMenuService.getFnMenuItems($scope.currentPage1, val).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.fnMenuItems = $scope.data.fnMenuItems;
+ var totalItems = $scope.fnMenuItems.length;
+ $scope.totalPages1 = Math.ceil(totalItems / $scope.viewPerPage1);
+ for (x in $scope.fnMenuItems) {
+ if ($scope.fnMenuItems[x].active_yn=='Y')
+ $scope.fnMenuItems[x].active_yn=true;
+ else
+ $scope.fnMenuItems[x].active_yn=false;
+ }
+ $scope.showLoader = false;
+ $scope.currentPage1=1;
+ var endIndex = 1 * $scope.viewPerPage1;
+ var startIndex = endIndex - $scope.viewPerPage1;
+ $scope.tableFnMenuItems = $scope.fnMenuItems.slice(startIndex, endIndex);
+ },function(error){
+ console.log('AdminMenuEditControler::$watch viewPerPage1 failed', error);
+ reloadPageOnce();
+ });
+
+ });
+
+ $scope.customHandler1 = function(num) {
+ $scope.currentPage1=num;
+ var endIndex = num * $scope.viewPerPage1;
+ var startIndex = endIndex - $scope.viewPerPage1;
+ $scope.tableFnMenuItems = $scope.fnMenuItems.slice(startIndex, endIndex);
+ };
+
+ $scope.init = function () {
+ $scope.numberOfRecordstoShow=20;
+ AdminMenuService.getFnMenuItems().then(function(data){
+ var j = data;
+ $scope.data =JSON.parse(j.data);
+ $scope.fnMenuItems =($scope.data.fnMenuItems);
+ },function(error){
+ console.log('AdminMenuEditControler::init failed');
+ });
+ }
+
+ $scope.init();
+
+ $scope.mapActiveStatus = function(status){
+ if(status)
+ status = "Y";
+ else
+ status = "N";
+ return status;
+ };
+
+ $scope.addNewFnMenuItemModalPopup = function(availableFnMenuItem) {
+ $scope.editFnMenuItem = null;
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html',
+ controller: fn_menu_popupController,
+ resolve: {
+ message: function () {
+ var message = {
+ availableFnMenuItem: $scope.editFnMenuItem
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function(response){
+ // console.log('response', response);
+ $scope.availableFnMenuItems=response.availableFnMenuItems;
+ $route.reload();
+ });
+
+ };
+
+ $scope.removeMenuItem = function (fnMenuItem) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/admin-menu-del-confirm.html',
+ controller: deletefn_menu_popupController,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: fnMenuItem.label
+ };
+ return fnMenuItem;
+ }
+ }
+ });
+ };
+
+
+ $scope.editRoleFunction = null;
+ var dialog = null;
+ $scope.editRoleFunctionPopup = function(availableRoleFunction) {
+ $scope.editRoleFunction = availableRoleFunction;
+ $( "#dialog" ).dialog({
+ modal: true
+ });
+ };
+
+ $scope.editMenuItemModalPopup = function(availableFnMenuItem) {
+ $scope.editFnMenuItem = availableFnMenuItem;
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html',
+ controller: fn_menu_popupController,
+ resolve: {
+ message: function () {
+ var message = {
+ availableFnMenuItem: $scope.editFnMenuItem
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function(response){
+ $scope.availableFnMenuItems=response.availableFnMenuItems;
+ $route.reload();
+ });
+ };
+
+ $scope.editRoleFunctionModalPopup = function(availableRoleFunction) {
+ $scope.editRoleFunction = availableRoleFunction;
+ var modalInstance = $modal.open({
+ templateUrl: 'edit_role_function_popup.html',
+ controller: 'rolefunctionpopupController',
+ resolve: {
+ message: function () {
+ var message = {
+ availableRoleFunction: $scope.editRoleFunction
+ };
+ return message;
+ }
+ }
+ });
+ modalInstance.result.then(function(response){
+ // console.log('response', response);
+ $scope.availableRoleFunctions=response.availableRoleFunctions;
+ });
+ };
+
+ $scope.addNewRoleFunctionModalPopup = function(availableRoleFunction) {
+ $scope.editRoleFunction = null;
+ var modalInstance = $modal.open({
+ templateUrl: 'edit_role_function_popup.html',
+ controller: 'rolefunctionpopupController',
+ resolve: {
+ message: function () {
+ var message = {
+ availableRoleFunction: $scope.editRoleFunction
+ };
+ return message;
+ }
+ }
+ });
+
+ modalInstance.result.then(function(response){
+ $scope.availableRoleFunctions=response.availableRoleFunctions;
+ });
+ };
+
+ $scope.addNewRoleFunctionPopup = function() {
+ $scope.editRoleFunction = null;
+ $( "#dialog" ).dialog({
+ modal: true
+ });
+ };
+
+
+
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-route.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-route.js
new file mode 100644
index 00000000..c7c06a7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-route.js
@@ -0,0 +1,43 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/net_map', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-sample-page/net_map.html',
+ controller: "netMapController"
+ })
+ .when('/jcs_admin', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html',
+ controller: 'adminController'
+ })
+ .when('/admin_menu_edit', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html',
+ controller: 'AdminMenuEditController'
+ })
+ .when('/usage_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/usage.html',
+ controller: 'usageListControllerDS2'
+ })
+ .when('/role_function_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html',
+ controller : "adminController"
+ })
+ .when('/role/:roleId', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role.html',
+ controller: 'adminController'
+ })
+ .when('/collaborate_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html',
+ controller: 'collaborateListControllerDS2'
+ })
+ .when('/adminClosedLoop', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin_closed_loop.html',
+ controller: 'adminClosedLoopController'
+ })
+ .when('/all', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html',
+ controller: 'workflowsController'
+ })
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html',
+ controller : 'adminController'
+ });
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-whitelist.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-whitelist.js
new file mode 100644
index 00000000..3e82df8e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/admin-whitelist.js
@@ -0,0 +1,3 @@
+appDS2.config(function ($sceDelegateProvider) {
+ $sceDelegateProvider.resourceUrlWhitelist(['self','**']);
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate-list-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate-list-controller.js
new file mode 100644
index 00000000..670e8fc1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate-list-controller.js
@@ -0,0 +1,71 @@
+appDS2.controller("collaborateListControllerDS2", function ($scope,$http, $modal,AdminService) {
+
+ $scope.showInput = true;
+ $scope.totalPages1 = 5;
+ $scope.viewPerPage1 = 8;
+ $scope.currentPage1 = 1;
+ $scope.showLoader = false;
+ $scope.firstPlay = true;
+ // Start with empty list to silence error in console
+ $scope.tableData = [];
+ $scope.tableCollbItems = [];
+ // $scope.totalPages1 = 20;
+ $scope.$watch('viewPerPage1', function(val) {
+ $scope.showLoader = true;
+ AdminService.getCollaborateList($scope.currentPage1, val).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData = $scope.data;
+ var totalItems = $scope.tableData.length;
+ //console.log(totalItems);
+ $scope.totalPages1 = Math.ceil(totalItems / $scope.viewPerPage1);
+ $scope.showLoader = false;
+ $scope.currentPage1=1;
+ var endIndex = 1 * $scope.viewPerPage1;
+ var startIndex = endIndex - $scope.viewPerPage1;
+ $scope.tableCollbItems = $scope.tableData.slice(startIndex, endIndex);
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+ });
+
+ $scope.customHandler1 = function(num) {
+ $scope.currentPage1=num;
+ var endIndex = num * $scope.viewPerPage1;
+ var startIndex = endIndex - $scope.viewPerPage1;
+ $scope.tableCollbItems = $scope.tableData.slice(startIndex, endIndex);
+ };
+
+ $scope.openCollaboration = function(chatId){
+ openInNewTab('openCollaboration?chat_id=' + chatId);
+ }
+
+ $scope.toggleProfileActive = function(profileId) {
+ modalService.popupConfirmWin("Confirm","You are about to change user's active status. Do you want to continue?",
+ function(){
+ $http.get("profile/toggleProfileActive?profile_id="+profileId).success(function(){});
+ })
+ };
+
+});
+
+function openInNewTab(url) {
+ var win = window.open(url, '_blank');
+ win.focus();
+};
+
+function downloadScreenCaptureExtenstion() {
+
+ var chromeURL = 'https://chrome.google.com/webstore/detail/icgmlogfeajbfdffajhoebcfbibfhaen';
+ var firefoxURL = 'https://addons.mozilla.org/en-US/firefox/addon/screen-capturing-capability';
+ var url;
+
+ if(isChrome)
+ url = chromeURL;
+ else if(isFirefox)
+ url = firefoxURL;
+
+ var win = window.open(url);
+ win.focus();
+};
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/collaborate.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/collaborate.js
new file mode 100644
index 00000000..fa9af088
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/collaborate.js
@@ -0,0 +1,7 @@
+app.config(function($routeProvider) {
+ $routeProvider
+ .when('/collaborate_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html',
+ controller: 'collaborateListControllerDS2'
+ })
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/workflowController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/workflowController.js
new file mode 100644
index 00000000..c43ad8b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborate/workflowController.js
@@ -0,0 +1,490 @@
+app.controller('workflowsController', function($scope, $http, $uibModal, $log, modalService, $modal) {
+
+ $scope.viewPerPage = 5;
+ $scope.scrollViewsPerPage = 20;
+ $scope.currentPage = 2;
+ $scope.totalPage;
+ $scope.searchCategory = "";
+ $scope.searchString = "";
+ $scope.radio = {
+ value: ""
+ };
+
+
+ $scope.showModal = false;
+ $scope.toggleModal = function(){
+ $scope.showModal = !$scope.showModal;
+ };
+
+ $scope.workflow = {};
+ $scope.workflow.active = "true";
+
+ $scope.updateAllWorkflowStatus = function() {
+ angular.forEach($scope.workflows,function(value){
+ $scope.checkWorkflowStatus(value);
+ })
+ }
+
+ $scope.fetchWorkflowsList = function() {
+ $http.get('workflows/list').then(function(workflowList){
+ console.log('Got new list from server = ' + workflowList.data);
+ $scope.workflows = workflowList.data;
+ $scope.updateAllWorkflowStatus();
+ });
+ };
+
+ $scope.addNewWorkflow = function(newWorkflow) {
+ $http.post('workflows/addWorkflow/', JSON.stringify(newWorkflow)).success(function() {
+ $scope.fetchWorkflowsList();
+ });
+
+ $scope.workflow.name = '';
+
+ };
+
+ $scope.updateWorkflow = function (workflowToEdit) {
+ //workflowToEdit.active='true';
+ var modalInstance = $uibModal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-new.html',
+ //size : modalSize,
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.workflow = workflowToEdit;
+ $scope.ok = function() {
+ console.log('Updating existing workflow ... ' + JSON.stringify($scope.workflow));
+ $http.post('workflows/editWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
+ console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
+ $uibModalInstance.close($scope.workflow);
+ });
+ };
+
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }],
+ //End of inner controller
+ resolve: {
+ workflow: function() {
+ console.log('Passing ' + JSON.stringify($scope.workflow));
+ return $scope.workflow;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (editedWorkFlow) {
+ //Need to convert to proper date - later
+ delete editedWorkFlow.created;
+ delete editedWorkFlow.updated;
+
+ delete editedWorkFlow.createdBy;
+ delete editedWorkFlow.modifiedBy;
+
+ console.log('selected Item ' + JSON.stringify(editedWorkFlow));
+ $scope.$emit('workflowAdded', editedWorkFlow);
+
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };
+
+ $scope.reset = function(){
+ console.log("Resetting ....");
+ };
+
+ $scope.update = function(){
+ console.log("updating ....");
+ };
+
+ $scope.createWorkflow = function (modalSize) {
+
+ var modalInstance = $uibModal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-new.html',
+ size : modalSize,
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.workflow = {};
+ $scope.workflow.active = 'true';
+ $scope.ok = function() {
+ console.log('Saving new workflow ... ' + JSON.stringify($scope.workflow));
+ $http.post('workflows/addWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
+ console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
+ $uibModalInstance.close($scope.workflow);
+ });
+ };
+/* console.log(size);*/
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }],
+ //End of inner controller
+ resolve: {
+ workflow: function() {
+ console.log('Passing ' + JSON.stringify($scope.workflow));
+ return $scope.workflow;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (newWorkflow) {
+ console.log('selected Item ' + JSON.stringify(newWorkflow));
+ $scope.$emit('workflowAdded', newWorkflow);
+
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };//End of createWorkflow function
+
+
+ $scope.removeWorkflow = function(workflowToRemove){
+ var modalInstance = $uibModal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-remove.html',
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.workflowToRemove = workflowToRemove;
+ $scope.ok = function() {
+ console.log('Removing workflow ... ' + JSON.stringify($scope.workflowToRemove) + ' on client request.');
+ $http.post('workflows/removeWorkflow/', JSON.stringify($scope.workflowToRemove.id)).then(function(){
+ console.log('Workflow successfully removed !!!');
+ $uibModalInstance.close();
+ });
+ };
+
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+
+ $scope.scheduleWorkflow = function(workflowToSchedule){
+ var modalInstance = $uibModal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-schedule.html',
+ size:'lg',
+
+ controller: ['$scope', '$uibModalInstance', '$http','dateFilter', function ($scope, $uibModalInstance, $http,dateFilter) {
+
+ $scope.workflowToSchedule = workflowToSchedule;
+ $scope.dt = new Date();
+ $scope.dt2 = new Date();
+ $scope.dateformat = 'MM/dd/yyyy',
+ $scope.datetimeformat = "hh:mm a";
+
+ $scope.recurrenceOptions =[{
+ index:0, value:'One-Time', title:'One-Time'
+ },{
+ index:1, value: 'Hourly',title:'Hourly'
+ },{
+ index:2, value: 'Daily',title:'Daily'
+ },{
+ index:3, value: 'Weekly',title:'Weekly'
+ }]
+ $scope.selectRecurrenceOpt = $scope.recurrenceOptions[0];
+
+ $scope.hours = [];
+ for (var i=0; i<24; i++){
+ var newObj={}
+ newObj.index = i;
+ newObj.value = ""+i;
+ newObj.title = ""+i;
+ $scope.hours.push(newObj);
+ }
+
+ $scope.minutes = [];
+ for (var i=0; i<60; i++){
+ var newObj={}
+ newObj.index = i;
+ newObj.value = ""+i;
+ newObj.title = ""+i;
+ $scope.minutes.push(newObj);
+ }
+
+ $scope.AMPMOptions =[
+ {
+ index:0, value:'AM', title:'AM'
+ },{
+ index:1, value: 'PM',title:'PM'
+ }]
+
+ $scope.selectFirstHour =$scope.hours[0];
+ $scope.selectFirstMinute =$scope.minutes[0];
+
+ $scope.selectLastHour =$scope.hours[0];
+ $scope.selectLastMinute =$scope.minutes[0];
+
+ $scope.selectStartAMPMOption=$scope.AMPMOptions[0];
+ $scope.selectLastAMPMOption=$scope.AMPMOptions[0];
+
+ var GenerateCronExpression = function(trigger_dt, RecurrenceOpt) {
+ var CRON_sec = trigger_dt.getSeconds();
+ var CRON_min = trigger_dt.getMinutes();
+ var CRON_hr = trigger_dt.getHours();
+ var CRON_date= trigger_dt.getDate();
+ var CRON_month = trigger_dt.toLocaleString('en-US', {month: 'short'}).toUpperCase();
+ var CRON_day = trigger_dt.toLocaleString('en-US', {weekday: 'short'}).toUpperCase();
+ var CRON_year = trigger_dt.getFullYear();
+ if (RecurrenceOpt ==="One-Time") {
+ CRON_day = '?'
+ } else {
+ if (RecurrenceOpt ==="Hourly") {
+ CRON_hr = '*';
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_day = '?'
+ CRON_year = '*'
+ } else if (RecurrenceOpt ==="Daily") {
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_day = '?'
+ CRON_year = '*'
+ } else if (RecurrenceOpt ==="Weekly") {
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_year = '*'
+ }
+ }
+
+ var CRON_Expression = [CRON_sec, CRON_min, CRON_hr, CRON_date, CRON_month, CRON_day, CRON_year];
+ return CRON_Expression.join(" ");
+ }
+
+ $scope.ok = function() {
+
+ // DateTime for the start time: it should be noted that the start time
+ // for a CRON job should be prior to the trigger time.
+ $scope.trigger_dt = new Date( $scope.dt.getFullYear() +
+ "-" + ("0"+($scope.dt.getMonth()+1)).slice(-2) +
+ "-" +("0"+ $scope.dt.getDate()).slice(-2) +
+ " " + ("0" + $scope.selectFirstHour.value).slice(-2) +
+ ":" +("0" + $scope.selectFirstMinute.value).slice(-2) +
+ ":00.0");
+
+ $scope.startDateTime_CRON = GenerateCronExpression($scope.trigger_dt, $scope.selectRecurrenceOpt.value)
+
+ //roll back the the start date time by 30 seconds (start time should be 30 seconds prior to trigger time)
+ dt_st = new Date($scope.trigger_dt - 30*1000)
+
+ startDateTime = dt_st.getFullYear() +
+ "-" + ("0"+(dt_st.getMonth()+1)).slice(-2) +
+ "-" +("0"+ dt_st.getDate()).slice(-2) +
+ " " + ("0" + dt_st.getHours()).slice(-2) +
+ ":" +("0" + dt_st.getMinutes()).slice(-2) +
+ ":" + ("0" + dt_st.getSeconds()).slice(-2) +".0";
+ $scope.startDateTime = startDateTime;
+
+ $scope.endDateTime = $scope.dt2.getFullYear() +
+ "-" + ("0"+($scope.dt2.getMonth()+1)).slice(-2) +
+ "-" +("0"+ $scope.dt2.getDate()).slice(-2) +
+ " " + ("0"+ $scope.selectLastHour.value).slice(-2) +
+ ":" +("0" + $scope.selectLastMinute.value).slice(-2) +
+ ":00.0"
+
+ $scope.WorkflowScheduleObject = {};
+ $scope.WorkflowScheduleObject['startDateTime_CRON'] = $scope.startDateTime_CRON;
+ $scope.WorkflowScheduleObject['startDateTime'] = $scope.startDateTime;
+ $scope.WorkflowScheduleObject['endDateTime'] = $scope.endDateTime;
+ $scope.WorkflowScheduleObject['workflowKey'] = $scope.workflowToSchedule.workflowKey;
+ $scope.WorkflowScheduleObject['recurrence'] = $scope.selectRecurrenceOpt.value;
+ $scope.WorkflowScheduleObject['workflow_arguments'] = "test";
+ $scope.WorkflowScheduleObject['workflow_server_url'] = $scope.workflowToSchedule.runLink;
+
+
+ TimeFromNowToStart = new Date($scope.startDateTime)-new Date()
+ TimeStartToEnd = new Date($scope.endDateTime)-new Date($scope.startDateTime)
+
+ if (TimeFromNowToStart<=0) {
+ console.log("invalid start time input")
+ alert("Please ensure the scheduled start date time is later than current time.")
+ return;
+ }
+ if (TimeStartToEnd<=0) {
+ console.log("invalid end time input")
+ alert("Please ensure the schduled end date time is later than the start time.")
+ return;
+ }
+ // if successful then save and close
+ $scope.saveCronJob($scope.WorkflowScheduleObject);
+ $uibModalInstance.close();
+
+ };
+
+ $scope.saveCronJob = function(cronJobData){
+
+ console.log('saving cron job data: ' + cronJobData);
+ var uuu = "workflows/saveCronJob.htm";
+ var postData={cronJobDataObj: cronJobData};
+ $.ajax({
+ type : 'POST',
+ url : uuu,
+ //dataType: 'json', // data type expected from server
+ contentType: 'application/json',
+ data: JSON.stringify(postData), // data type sent to server
+ success : function(data){
+ $scope.$apply(function(){
+ //$scope.availableRoleFunctions=[];$scope.$apply();
+ // new // $scope.availableFnMenuItems=data.availableFnMenuItems;
+ }
+ );
+ //alert("Update Successful.") ;
+ //$scope.editRoleFunction = null;
+ // new /// $modalInstance.close({availableFnMenuItems:$scope.availableRoleFunctions});
+ },
+ error : function(data){
+ alert("Error while saving.");
+ }
+ });
+
+ };
+
+ $scope.cancel = function() {
+ console.log("cancel triggered")
+ $uibModalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+
+
+
+
+
+
+ $scope.previewWorkflow = function(workflowToPreview,modalSize){
+ var modalInstance = $uibModal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-preview.html',
+ size:modalSize,
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.workflowToPreview = workflowToPreview;
+ console.log('previewWorkFlow invoked');
+ console.log($scope.workflowToPreview);
+
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+ /* change work flow status based on the boolean variable "suspendBool" which corresponds whether
+ * we would like to suspend or activate a workflow specified by key. */
+ $scope.changeWorkflowStatus = function(workflowToChangeStatus,suspendBool){
+ if (workflowToChangeStatus!==null) {
+ var statusUrl= workflowToChangeStatus.runLink+"/engine-rest/process-definition/key/"+workflowToChangeStatus.workflowKey
+ var suspendedUrl= statusUrl+"/suspended"
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.open('PUT', suspendedUrl, false);
+ xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
+ xmlHttp.onload = function() {
+ if (suspendBool) {
+ console.log("process definition is now suspended");
+ workflowToChangeStatus.active="false"
+ } else {
+ console.log("process definition is now activated");
+ workflowToChangeStatus.active="true"
+ }
+ };
+ xmlHttp.send(JSON.stringify({
+ "suspended" : suspendBool,
+ "includeProcessInstances" : true,
+ "executionDate" : "2013-11-21T10:49:45"
+ }));
+ }
+
+ };
+
+ $scope.activateWorkflow = function(workflowToActivate){
+ $scope.changeWorkflowStatus(workflowToActivate,false)
+
+ };
+
+ $scope.suspendWorkflow = function(workflowToActivate){
+ $scope.changeWorkflowStatus(workflowToActivate,true)
+ };
+
+ $scope.checkWorkflowStatus = function(workflow) {
+ if (workflow!==null) {
+ var statusUrl= workflow.runLink+"/engine-rest/process-definition/key/"+workflow.workflowKey
+ var xmlHttp3 = new XMLHttpRequest();
+ xmlHttp3.open('GET', statusUrl, true);
+ xmlHttp3.withCredentials = true;
+ xmlHttp3.send();
+ xmlHttp3.onreadystatechange = function() {
+ if (xmlHttp3.readyState == 4 && xmlHttp3.status == 200) {
+ // do something with the response in the variable data
+ var temp = JSON.parse(xmlHttp3.responseText)
+ if (temp.suspended == false){
+ console.log("Activated")
+ workflow.active="true"
+ } else {
+ console.log("Suspended")
+ workflow.active="false"
+ }
+ }
+ }
+ }
+ };
+
+ $scope.StartWorkflowInstance = function(workflowToStart){
+ if (workflowToStart!==null) {
+ var statusUrl= workflowToStart.runLink+"/engine-rest/process-definition/key/"+workflowToStart.workflowKey
+ var suspendedUrl= statusUrl+"/submit-form"
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.open('POST', suspendedUrl, false);
+ xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
+ xmlHttp.onload = function() {
+ };
+ xmlHttp.send(JSON.stringify({
+ "variables": {
+ "customerId": {"value":"asdasda","type":"String"},
+ "amount":{"value":"100","type":"String"}
+ }
+ }));
+ }
+
+ };
+
+
+ $scope.$on('workflowAdded', function(event, newWorkflow) {
+ console.log("New Workflow to be added in list scope " + JSON.stringify(newWorkflow));
+ //$scope.workflows.push(newWorkflow);
+ $scope.fetchWorkflowsList();
+ console.log('newly added workflow = ' + JSON.stringify(newWorkflow));
+ });
+
+ $scope.$on('workflowRemoved', function(event) {
+ $scope.fetchWorkflowsList();
+ });
+
+ $scope.fetchWorkflowsList();
+
+
+
+});
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborateList-route.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborateList-route.js
new file mode 100644
index 00000000..d402fd7b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaborateList-route.js
@@ -0,0 +1,19 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/collaborate_list', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html',
+ controller: 'collaborateListControllerDS2'
+ })
+ .when('/notebook', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html',
+ controller: 'nbookController'
+ })
+ .when('/leafletMap', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/leafletMap.html',
+ controller: 'leafletController'
+ })
+ .when('/notebook', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html',
+ controller: 'nbookController'
+ })
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaboration-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaboration-controller.js
new file mode 100644
index 00000000..a800c009
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/collaboration-controller.js
@@ -0,0 +1,266 @@
+
+
+appDS2.controller('collaborationControllerDS2', function ($scope,$http, $modal) {
+ console.log("modal", $modal);
+ var popupModalService;
+
+ });
+
+
+ $(document).ready(function () {
+
+ // OUTER-LAYOUT
+ panelLayout = $('body').layout({
+ center__paneSelector: ".outer-center"
+ , west__paneSelector: ".outer-west"
+ , east__paneSelector: ".outer-east"
+ //, west__size: 800
+ //, east__size: 125
+ , spacing_open: 8 // ALL panes
+ , spacing_closed: 12 // ALL panes
+
+ , center__childOptions: {
+ center__paneSelector: ".inner-center"
+ , west__paneSelector: ".inner-west"
+ , east__paneSelector: ".inner-east"
+ , west__size: 75
+ , east__size: 75
+ , spacing_open: 8 // ALL panes
+ , spacing_closed: 8 // ALL panes
+ , west__spacing_closed: 12
+ , east__spacing_closed: 12
+ }
+
+
+
+
+ });
+
+
+ function initializeConnections() {
+
+ var channelId = null;
+ channelId = location.href.replace(/\/|:|#|%|\.|\[|\]/g, '');
+ var videoChannelId = channelId.concat("video");
+ var screenChannelId = channelId.concat("screen");
+
+ videoConnection = new RTCMultiConnection(videoChannelId);
+ screenConnection = new RTCMultiConnection(screenChannelId);
+
+ configConnection(videoConnection,true,true,false,true,false);
+ configConnection(screenConnection,false,false,true,false,true);
+
+ };
+
+ function configConnection(_connection, _audio, _video, _screen, _data, _oneway) {
+ _connection.session = {
+ audio: _audio, // by default, it is true
+ video: _video, // by default, it is true
+ screen: _screen,
+ data: _data,
+ oneway: _oneway,
+ broadcast: false
+ };
+
+ _connection.direction = "one-to-one";
+
+ if( _data == true ) {
+ _connection.onmessage = function(e) {
+ appendDIV(e.data);
+
+ console.debug(e.userid, 'posted', e.data);
+ console.log('latency:', e.latency, 'ms');
+ };
+ }
+
+
+ };
+
+ function assignStreamToDom() {
+
+
+ screenConnection.screenbody = document.querySelector('.screenContainer1');
+ screenConnection.videobody = document.querySelector('.videoContainer2');
+
+ videoConnection.screenbody = document.querySelector('.screenContainer2');
+ videoConnection.videobody = document.querySelector('.videoContainer1');
+ };
+
+ function maximizeLayout() {
+
+ // open the panes and maximize the window.
+ top.window.resizeTo(screen.availWidth,screen.availHeight);
+ panelLayout.open('west');
+ // panelLayout.open('south'); is not working due to state initialization problem; debug to find out. so replacing the call with work around below - hack.
+ $(".ui-layout-toggler-south-closed").first().click();
+
+ };
+
+ function minimizeLayout() {
+
+ // close the panes and minimize the window.
+ top.window.resizeTo(screen.availWidth - 2*screen.availWidth/3, screen.availHeight - screen.availHeight/2);
+ panelLayout.close('west');
+ // panelLayout.close('south'); is not working due to state initialization problem; debug to find out. so replacing the call with work around below - hack.
+ $(".ui-layout-toggler-south-opened").first().click();
+ };
+
+ function emptyContainers() {
+ $('.screenContainer1').empty();
+ $('.videoContainer2').empty();
+
+ $('.screenContainer2').empty();
+ $('.videoContainer1').empty();
+ };
+
+ function appendDIV(div, parent) {
+ if (typeof div === 'string') {
+ var content = div;
+ div = document.createElement('div');
+ div.innerHTML = content;
+ };
+
+ var chatOutput = document.getElementById('chat-output'),
+ fileProgress = document.getElementById('file-progress');
+
+ if (!parent) chatOutput.insertBefore(div, chatOutput.firstChild);
+ else fileProgress.insertBefore(div, fileProgress.firstChild);
+
+ div.tabIndex = 0;
+ $('#chat-input').focus();
+ };
+
+ function confirmClose() {
+ var message = "Are you sure you want to close the session?";
+
+ /* if(popupModalService != undefined) {
+ popupModalService.popupConfirmWin("Confirm", message, function(){ location.reload();});
+ }
+
+ else */
+ if (confirm(message) == true) {
+ location.reload();
+ //window.opener.location.reload(); // go to the parent window
+ //close();
+ } else {
+ // do nothing
+ }
+
+ };
+
+ function notifyOthers() {
+
+ // var websocket = localStorage.getItem('notifySocket');
+ //if( websocket != null) {
+ // handling websocket peer broadcast session
+ var currentUser = "${sessionScope.user.sbcid}";
+ var initialPageVisit = "${sessionScope.initialPageVisit}";
+ var remoteUser = '';
+
+ var userList = location.search.split('chat_id=')[1].split('-');
+ for(var i=0;i<userList.length;i++) {
+ if(userList[i] !== currentUser) {
+ remoteUser = userList[i];
+ break;
+ }
+ }
+
+ socketSetup(initialPageVisit, currentUser, remoteUser,"socketSend");
+
+
+
+
+
+
+ };
+
+ function makeChatVisible() {
+
+ $('#chat-input').css("visibility", 'visible');
+ };
+
+
+
+ /* on click button enabled*/
+ window.onload = function () {
+ document.getElementById('share-screen').onclick = function() {
+
+ emptyContainers();
+ videoConnection.close();
+ screenConnection.close();
+
+ maximizeLayout();
+ emptyContainers();
+ makeChatVisible();
+
+ videoConnection.open();
+ screenConnection.open();
+
+
+ notifyOthers();
+
+
+
+ };
+ };
+
+ document.getElementById('stop-share-screen').onclick = function() {
+
+ emptyContainers();
+
+ videoConnection.close();
+ screenConnection.close();
+
+ confirmClose();
+
+ };
+
+ document.getElementById('view-screen').onclick = function() {
+
+ maximizeLayout();
+ emptyContainers();
+ makeChatVisible();
+
+ // timeout is required for the sharing to properly work
+ setTimeout(function() {
+ screenConnection.connect();
+ },2000);
+ setTimeout(function() {
+ videoConnection.connect();
+ },1000);
+
+
+ };
+
+ document.getElementById('chat-input').onkeypress = function(e) {
+ if (e.keyCode !== 13 || !this.value) return;
+ var message = "<b>${model.name}</b>: " + this.value;
+ appendDIV(message);
+
+ // sending text message
+ videoConnection.send(message);
+
+ this.value = '';
+ };
+
+ /*
+ document.getElementById('file').onchange = function() {
+ videoConnection.send(this.files[0]);
+ };
+ */
+
+
+ //document.querySelector('.screenContainerPane').appenChild(document.querySelector('.screenContainer'));
+ //document.querySelector('.videoContainerPane').appendChild(document.querySelector('.videoContainer'));
+
+ //panelLayout.bindButton($('#share-screen'), 'open', 'outer-west');
+ //panelLayout.bindButton($('#stop-share-screen'), 'close', 'outer-west');
+ var videoConnection = null, screenConnection = null;
+ initializeConnections();
+ assignStreamToDom();
+
+ // start the share
+ //document.getElementById('share-screen').click();
+ //
+ });
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-profile/self-profile-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-profile/self-profile-controller.js
new file mode 100644
index 00000000..efe2b749
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-profile/self-profile-controller.js
@@ -0,0 +1,358 @@
+appDS2.controller('selfProfileController', function($scope, $http, $modal, $routeParams, $rootScope,SelfProfileService){
+
+ /************init values***********************/
+ $scope.tableData=[];
+ $scope.profile=[];
+ $scope.oriProfile=[];
+ $scope.ociavailableRoles=[];
+ $scope.ociTimeZones;
+ $scope.ociCountries;
+ var stateList=[];
+ $scope.availableRoles = [];
+ $scope.timeZones = [];
+ $scope.selectedTimeZone = {"index":'',"value":"","title":""};
+ $scope.countries = [];
+ $scope.selectedCountry = {"index":'',"value":"","title":""};
+
+ $scope.isUserSystemAdmin = false;
+ $scope.profileId='';
+ $scope.showLoader=false;
+ $scope.pageType=1 /*1 for slef page 2 for general profile page*/
+ $scope.pageTitle='Self Profile Detail';
+ $scope.profileIdParam = $routeParams.profileId;
+ if (typeof($scope.profileIdParam) != "undefined" && $scope.profileIdParam!=''){
+ $scope.pageTitle='Profile Detail';
+ $scope.pageType=2;
+ }
+
+ $scope.sbcid=$scope.profile.sbcid;
+ $scope.managerAttuid=$scope.profile.managerAttuid;
+
+ /***********************************************************functions***********************************************/
+ $scope.getProfileDetail = function(profileIdParam){
+ $scope.showLoader=true;
+ SelfProfileService.getProfileDetail(profileIdParam).then(function(data){
+ $scope.showLoader=false;
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.profile =JSON.parse($scope.data.profile);
+ $scope.oriProfile=JSON.parse($scope.data.profile); /*original value*/
+ $scope.profileId = $scope.profile.id;
+ $scope.ociavailableRoles =JSON.parse($scope.data.availableRoles);
+ $scope.ociTimeZones=JSON.parse($scope.data.timeZones);
+ $scope.ociCountries=JSON.parse($scope.data.countries);
+ stateList=JSON.parse($scope.data.stateList);
+ $scope.sbcid=$scope.profile.sbcid;
+ $scope.managerAttuid=$scope.profile.managerAttuid;
+
+ if($scope.ociavailableRoles)
+ $.each($scope.ociavailableRoles, function(i, a){
+ var availableRole = a;
+ availableRole.selected = false;
+ $.each($scope.profile.roles, function(j, b){
+ if(a.id === b.id) {
+ availableRole.selected = true;
+ if(a.id === 1){
+ $scope.isUserSystemAdmin = true;
+ }
+ }
+ });
+ $scope.availableRoles.push(availableRole);
+ });
+ ;
+ if($scope.ociTimeZones){
+ $.each($scope.ociTimeZones, function(i, a){
+ var timeZone = {"index":i, "value":a.value, "title":a.label};
+ $scope.timeZones.push(timeZone);
+ if($scope.profile.timeZoneId !== null && a.value === $scope.profile.timeZoneId.toString()){
+ $scope.selectedTimeZone = timeZone;
+ }
+ });
+ };
+ if($scope.ociCountries)
+ $.each($scope.ociCountries, function(i, a){
+ var country = {"index":i, "value":a.value, "title":a.label};
+ $scope.countries.push(country);
+ if(a.value === $scope.profile.country){
+ $scope.selectedCountry = country;
+ }
+ });
+ ;
+ stateList = stateList== null? []: stateList;
+ var selectedState= $scope.profile.state ? $scope.profile.state:"";
+ $scope.stateList = initDropdownWithLookUp(stateList,selectedState );
+ },function(error){
+ $scope.errorPopUp(error);
+ $scope.showLoader=false;
+ });
+ }
+
+ $scope.getSelfProfileDetail = function(){
+ $scope.showLoader=true;
+ SelfProfileService.getSelfProfileDetail().then(function(data){
+ $scope.showLoader=false;
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.profile =JSON.parse($scope.data.profile);
+ $scope.oriProfile=JSON.parse($scope.data.profile); /*original value*/
+ $scope.profileId = $scope.profile.id;
+ $scope.ociavailableRoles =JSON.parse($scope.data.availableRoles);
+ $scope.ociTimeZones=JSON.parse($scope.data.timeZones);
+ $scope.ociCountries=JSON.parse($scope.data.countries);
+ stateList=JSON.parse($scope.data.stateList);
+ $scope.sbcid=$scope.profile.sbcid;
+ $scope.managerAttuid=$scope.profile.managerAttuid;
+
+ if($scope.ociavailableRoles)
+ $.each($scope.ociavailableRoles, function(i, a){
+ var availableRole = a;
+ availableRole.selected = false;
+ $.each($scope.profile.roles, function(j, b){
+ if(a.id === b.id) {
+ availableRole.selected = true;
+ if(a.id === 1){
+ $scope.isUserSystemAdmin = true;
+ }
+ }
+ });
+ $scope.availableRoles.push(availableRole);
+ });
+ ;
+ if($scope.ociTimeZones){
+ $.each($scope.ociTimeZones, function(i, a){
+ var timeZone = {"index":i, "value":a.value, "title":a.label};
+ $scope.timeZones.push(timeZone);
+ if($scope.profile.timeZoneId !== null && a.value === $scope.profile.timeZoneId.toString()){
+ $scope.selectedTimeZone = timeZone;
+ }
+ });
+ };
+ if($scope.ociCountries)
+ $.each($scope.ociCountries, function(i, a){
+ var country = {"index":i, "value":a.value, "title":a.label};
+ $scope.countries.push(country);
+ if(a.value === $scope.profile.country){
+ $scope.selectedCountry = country;
+ }
+ });
+ ;
+ stateList = stateList== null? []: stateList;
+ var selectedState= $scope.profile.state ? $scope.profile.state:"";
+ $scope.stateList = initDropdownWithLookUp(stateList,selectedState );
+ },function(error){
+ $scope.errorPopUp(error);
+ $scope.showLoader=false;
+ });
+ }
+
+
+ $scope.removeRole = function(data) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-del-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ role:data,
+ roleId:$scope.profileId,
+ };
+ return message;
+ }
+ }
+ });
+ };
+ $scope.addNewRoleFunctionModalPopup = function(data) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add.html',
+ controller: ModalInstanceCtrl,
+ windowClass:'modal-docked',
+ sizeClass: 'modal-medium',
+ resolve: {
+ items: function () {
+ var message = {
+ roleFunctions:data,
+ roleId:$scope.profileId,
+ availableRoleFunctions:$scope.ociavailableRoles
+ };
+ return message;
+ }
+ }
+ });
+ }
+
+
+ $scope.successPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+
+ $scope.errorPopUp = function (msg) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ });
+ };
+ $scope.saveProfile = function() {
+ $scope.errorMsg = '';
+ if($scope.oriProfile.orgUserId != $scope.profile.orgUserId){
+ $scope.errorPopUp('Organization User ID cannot be changed');
+ return;
+ }
+ if($scope.oriProfile.orgManagerUserId != $scope.profile.orgManagerUserId){
+ $scope.errorPopUp('Organization Manager ID cannot be changed');
+ return;
+ }
+ if($scope.oriProfile.loginId != $scope.profile.loginId){
+ $scope.errorPopUp('Login ID cannot be changed');
+ return;
+ }
+ if($scope.oriProfile.loginPwd != $scope.profile.loginPwd){
+ $scope.errorPopUp('Login Password cannot be changed');
+ return;
+ }
+
+ var postData={
+ profile: $scope.profile,
+ selectedCountry:$scope.selectedCountry!=null?$scope.selectedCountry.value:"",
+ selectedState:$scope.stateList.selected!=null?$scope.stateList.selected.value:"",
+ selectedTimeZone:$scope.selectedTimeZone!=null?$scope.selectedTimeZone.value:""
+ };
+ SelfProfileService.saveProfile(postData, $scope.profileId).then(function(msg){
+ $scope.successPopUp();
+ },function(error){
+ $scope.errorPopUp(error);
+ });
+ }
+ /* updating role tables after adding or deleting*/
+ $rootScope.$on('updateRoles',function(e,d){
+ $scope.profile.roles = d.data;
+ })
+ /*****init call*****/
+
+ if ($scope.pageType==2){
+ $scope.getProfileDetail($scope.profileIdParam);
+ }else{
+ $scope.getSelfProfileDetail();
+ }
+
+
+ /****************************************************************popup modal*************************************************************/
+ var ModalInstanceCtrl = function ($scope, $modalInstance, items,$rootScope) {
+ $scope.roleFun=items;
+ $scope.msg=items;
+ $scope.activateRoleConfirmPopUp = function (selected, availableRole) {
+ $scope.msg.roleFun = availableRole.name;
+ $scope.msg.selected = selected;
+ $scope.msg.availableRole = availableRole;
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add-confirm.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return $scope.msg;
+ }
+ }
+ });
+ }
+ $scope.confirmRoleDel = function(role,profileId){
+ var postData={role:role};
+ SelfProfileService.removeRole(postData,profileId).then(function(msg){
+ $scope.cancel();
+ $scope.roleTableRefresh(profileId);
+ },function(error){
+ $scope.errorPopUp(error);
+ });
+ }
+ $scope.confirmRoleFunAdd = function(availableRole,profileId){
+ var postData={role:availableRole};
+ SelfProfileService.addRole(postData,profileId).then(function(msg){
+ $scope.cancel();
+ $scope.roleTableRefresh(profileId);
+ },function(error){
+ $scope.errorPopUp(error);
+ });
+ }
+
+ // confirm Role Function Remove
+ $scope.confirmRoleFunRemove = function(availableRole,profileId){
+ var postData={role:availableRole};
+ SelfProfileService.deRole(postData,profileId).then(function(msg){
+ $scope.cancel();
+ $scope.roleTableRefresh(profileId);
+ },function(error){
+ $scope.errorPopUp(error);
+ });
+ }
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.cancelRoleFunSwitch = function (msg) {
+ $scope.msg.availableRole.selected = !$scope.msg.availableRole.selected;
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.selfProfileRoleRefresh = function(){
+ SelfProfileService.getSelfProfileDetail().then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.profileTemp =JSON.parse($scope.data.profile);
+ $rootScope.$broadcast('updateRoles',{data:$scope.profileTemp.roles});
+ });
+ }
+ $scope.profileRoleRefresh = function(profileId){
+ SelfProfileService.getProfileDetail(profileId).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.profileTemp =JSON.parse($scope.data.profile);
+ $rootScope.$broadcast('updateRoles',{data:$scope.profileTemp.roles});
+ });
+ }
+ $scope.roleTableRefresh = function (profileId) {
+ if($scope.pageType==1)
+ $scope.selfProfileRoleRefresh();
+ else
+ $scope.profileRoleRefresh(profileId);
+ };
+
+ };
+
+});
+function initDropdownWithLookUp(arr,selectedValue){
+ var dropdownArray=[];
+ var selected = null;
+ if(arr){
+ for(var i = 0,l = arr.length; i < l; i++) {
+ var option = {
+ "index" : i ,
+ "value" : arr[i].value,
+ "title" : arr[i].label
+ };
+ dropdownArray.push(option);
+ if(arr[i].value === selectedValue){
+ selected = option;
+ }
+ }
+ }
+ var dropDown={};
+ dropDown.options = dropdownArray;
+ dropDown.selected = selected!=null?selected:{"index":'',"value":"","title":""};
+ return dropDown;
+};
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-import-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-import-controller.js
new file mode 100644
index 00000000..a8f853fd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-import-controller.js
@@ -0,0 +1,20 @@
+appDS2.controller('reportImportController', function($scope,$http,$location, $routeParams, $q, $modal,$log,$window, raptorReportFactory, stepFormFactory, DOMHelper) {
+ $scope.importXML = function(){
+
+ var importXMLJSON = {
+ "tabId":"Import",
+ "tabName":"Import",
+ "reportXML":$scope.xmlContent
+ }
+ $scope.errorMessage = ""
+ raptorReportFactory.postImportXml(importXMLJSON).then(function(data){
+ if (data.errormessage) {
+ $scope.errorMessage = data.errormessage;
+ } else {
+ $window.location.href = 'report#/report_wizard/-1';
+ };
+ },function(error){
+ $log.error("raptorReportFactory: postImportXml failed.");
+ });
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-router.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-router.js
new file mode 100644
index 00000000..db3422ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-router.js
@@ -0,0 +1,37 @@
+appDS2.config(['$routeProvider',
+ function($routeProvider) {
+ $routeProvider.
+ when('/', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html',
+ controller: 'reportSearchController'
+ }).
+ when('/report_search', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html',
+ controller: 'reportSearchController'
+ }).
+ when('/report_run/:reportUrlParams*', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/report-run.html',
+ controller: 'reportRunController'
+ }).
+ when('/report_chart_wizard/:reportId', {
+ templateUrl: 'static/fusion/raptor/ebz/report_chart_wizard.html',
+ controller: 'ChartController'
+ }).
+ when("/report_wizard", {
+ templateUrl : "app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html",
+ controller: "reportStepController"
+ }).
+ when("/report_wizard/:reportId", {
+ templateUrl : "app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html",
+ controller: "reportStepController"
+ }).
+ when("/report_wizard/:reportMode/:reportId", {
+ templateUrl : "app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html",
+ controller: "reportStepController"
+ }).
+ when("/report_import", {
+ templateUrl : "app/fusion/scripts/DS2-view-models/ds2-reports/report-import.html",
+ controller: "reportImportController"
+ })
+ ;
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-run-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-run-controller.js
new file mode 100644
index 00000000..02f58985
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-run-controller.js
@@ -0,0 +1,326 @@
+appDS2.controller("reportRunController", ['$scope','$rootScope','$routeParams','$http','dateFilter', '$window', '$timeout', 'rowSorter',
+ function ($scope,$rootScope,$routeParams,$http,dateFilter,$window,$timeout,rowSorter) {
+ $scope.dateformat = "MM/dd/yyyy";
+ $scope.datetimeformat = "MM/dd/yyyy hh:mm a";
+ $scope.showFormFields = false;
+ $scope.showGrid = false;
+ $scope.showChart = false;
+ $scope.showBackButton = false;
+ $scope.reportData = {};
+ $scope.reportData.allowEdit = false;
+ $scope.formFieldSelectedValues = {};
+ $scope.showFormFieldIds = false;
+
+ $scope.isInProgress = true;
+
+ if($routeParams.reportUrlParams.indexOf("parent___params===")>-1) {
+ $scope.showBackButton = true;
+ $scope.parentReportUrlParams = $routeParams.reportUrlParams.substring($routeParams.reportUrlParams.indexOf("parent___params===")+18);
+ $scope.currentReportUrlParams = $routeParams.reportUrlParams.substring(0,$routeParams.reportUrlParams.indexOf("parent___params==="));
+ } else {
+ $scope.currentReportUrlParams = $routeParams.reportUrlParams;
+ }
+ console.log($routeParams.reportUrlParams);
+ var parseQueryString = function( queryString ) {
+ var params = {}, queries, temp, i, l;
+ // Split into key/value pairs
+ queries = queryString.split("&");
+ // Convert the array of strings into an object
+ for ( i = 0, l = queries.length; i < l; i++ ) {
+ temp = queries[i].split('=');
+ //console.log(temp[0]);
+ //console.log(temp[0] != "refresh");
+ if(temp[0] && temp[0] != "refresh")
+ params[temp[0]] = temp[1];
+ }
+ return params;
+ };
+
+ var convertQueryString = function(queryString) {
+ var keys = ""; var str = "";
+ keys = Object.keys(queryString);
+ //console.log(keys);
+ for ( i = 0, l = keys.length; i < l; i++ ) {
+ str += keys[i]+"="+queryString[keys[i]] + "&";
+
+ }
+ return str;
+ //queryString =
+ }
+
+
+
+
+ $scope.urlParams = parseQueryString($scope.currentReportUrlParams);
+
+ $scope.reportChartURL = 'report#/report_chart_wizard/'+$scope.urlParams.c_master;
+
+ $scope.reportEditURL = 'report_wizard.htm?action=report.edit&c_master='+$scope.urlParams.c_master;
+
+
+ $http.get('raptor.htm?action=report.run.container&'+$scope.currentReportUrlParams).then(
+ function(response){
+ console.log(response);
+ $scope.isInProgress = false;
+ $scope.reportData = response.data;
+ console.log('reportData report run container response',$scope.reportData);
+ if ($scope.reportData.reportTitle) {
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ if ($scope.reportData.reportSubTitle) {
+ $scope.reportData.reportSubTitle = $scope.reportData.reportSubTitle;
+ }
+ }
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;
+ if(!$scope.urlParams.hideChart && $scope.reportData.chartAvailable && $scope.reportData.totalRows>1){
+ console.log('raptor.htm?action=chart.run&'+convertQueryString($scope.urlParams));
+ $http.get('raptor.htm?action=chart.run&'+convertQueryString($scope.urlParams)).then(
+ function(response){
+ $scope.showChart = true;
+ document.getElementById('chartiframe').contentWindow.document.write(response.data);
+ document.getElementById('chartiframe').contentWindow.document.close();
+ });
+ }
+
+ if($scope.reportData.displayForm && $scope.reportData.formFieldList && $scope.reportData.formFieldList.length>0 && !$scope.urlParams.hideFormFields){
+ $scope.showFormFields = true;
+ }
+ });
+ $scope.getFormFieldSelectedValuesAsURL = function(){
+ var formFieldsUrl = '';
+ $scope.reportData.formFieldList.forEach(function(formField) {
+ if(formField.fieldType==='LIST_BOX') {
+ if($scope.formFieldSelectedValues && $scope.formFieldSelectedValues[formField.fieldId] && $scope.formFieldSelectedValues[formField.fieldId].value != '') {
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId].value+'&';
+ }
+ } else if(formField.fieldType==='LIST_MULTI_SELECT') {
+ if($scope.formFieldSelectedValues[formField.fieldId].length >0) {
+ for (var i = 0; i < $scope.formFieldSelectedValues[formField.fieldId].length; i++) {
+ if($scope.formFieldSelectedValues[formField.fieldId][i].defaultValue){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId][i].value+'&';
+ }
+ }
+ }
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && formField.validationType === 'DATE'){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+dateFilter($scope.formFieldSelectedValues[formField.fieldId],$scope.dateformat)+'&';
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && formField.validationType === 'TIMESTAMP_MIN'){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+dateFilter($scope.formFieldSelectedValues[formField.fieldId],$scope.datetimeformat)+'&';
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && $scope.formFieldSelectedValues[formField.fieldId] && $scope.formFieldSelectedValues[formField.fieldId] != ''){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId]+'&';
+ }
+ });
+ return formFieldsUrl;
+
+ }
+
+ $scope.runReport = function(pagination){
+ var formFieldsUrl = $scope.getFormFieldSelectedValuesAsURL();
+ /*if ($scope.reportData.reportTitle)
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;*/
+
+ console.log("pagination");
+ if(!pagination) {
+ //console.log("refreshed ...");
+ $scope.gridOptions.pageNumber = 1;
+ paginationOptions.pageNumber = 1;
+ paginationOptions.pageSize = $scope.reportData.pageSize;
+ //console.log($scope.gridOptions);
+ $scope.gridOptions.paginationCurrentPage = 1;
+ $scope.gridOptions.paginationPageSizes= [$scope.reportData.pageSize];
+ $scope.gridOptions.paginationPageSize= $scope.reportData.pageSize;
+ if($scope.reportData.totalRows<14){
+ $scope.gridHeight = ($scope.reportData.totalRows+7)*30+'px';
+ } else{
+ $scope.gridHeight = '400px';
+ }
+ $scope.gridOptions.totalItems = $scope.reportData.totalRows;
+ $scope.gridOptions.data= $scope.reportData.reportDataRows;
+ $scope.gridOptions.exporterPdfHeader.text= $scope.reportData.reportName;
+
+ }
+ $scope.currentReportUrlParams = 'c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'&display_content=Y&r_page='+(paginationOptions.pageNumber-1);
+ console.log('raptor.htm?action=report.run.container&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1));
+ $http.get('raptor.htm?action=report.run.container&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
+ function(response){
+ $scope.reportData = response.data;
+ if ($scope.reportData.reportTitle) {
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ if ($scope.reportData.reportSubTitle) {
+ $scope.reportData.reportSubTitle = $scope.reportData.reportSubTitle;
+ }
+ }
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;
+
+ if($scope.reportData.errormessage) {
+ //console.log($scope.reportData);
+ var stacktraceFP = $scope.reportData.stacktrace.substring(0, $scope.reportData.stacktrace.indexOf(":")+1);
+ document.getElementById('errorDiv').innerHTML = stacktraceFP + " " + $scope.reportData.errormessage;
+ //console.log(document.getElementById('errorDiv').innerHtml);
+ //console.log(stacktraceFP + " " + $scope.reportData.errormessage);
+ }
+ if(!pagination) {
+ if(!$scope.urlParams.hideChart && $scope.reportData.chartAvailable && $scope.reportData.totalRows>1){
+ console.log('raptor.htm?action=chart.run&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'display_content=Y&r_page='+(paginationOptions.pageNumber-1));
+ $http.get('raptor.htm?action=chart.run&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
+ function(response) {
+ console.log(response.data);
+ $scope.showChart = true;
+ console.log('response.data',response.data);
+ document.getElementById('chartiframe').contentWindow.document.write(response.data);
+ document.getElementById('chartiframe').contentWindow.document.close();
+ });
+ } else {
+ $scope.showChart = false;
+ }
+ }
+ if($scope.reportData.displayForm && $scope.reportData.formFieldList && $scope.reportData.formFieldList.length>0 && !$scope.urlParams.hideFormFields && !$scope.reportData.hideFormFieldsAfterRun){
+ $scope.showFormFields = true;
+ } else {
+ $scope.showFormFields = false;
+ }
+ });
+ };
+
+ var paginationOptions = {
+ pageNumber: 1,
+ pageSize: 5,
+ sort: null
+ };
+
+ var correctTotalPaginationTemplate =
+ //same as normal template, but fixed totals: {{(((grid.options.paginationCurrentPage-1)*grid.options.paginationPageSize)+1)}} {{(grid.options.paginationCurrentPage*grid.options.paginationPageSize>grid.options.totalItems?grid.options.totalItems:grid.options.paginationCurrentPage*grid.options.paginationPageSize)}}
+ "<div role=\"contentinfo\" class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div role=\"menubar\" class=\"ui-grid-pager-control\"><button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle\"><div class=\"first-bar\"></div></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle prev-triangle\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div class=\"last-triangle next-triangle\"></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div class=\"last-triangle\"><div class=\"last-bar\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{(((grid.options.paginationCurrentPage-1)*grid.options.paginationPageSize)+1)}} <abbr ui-grid-one-bind-title=\"paginationThrough\">-</abbr> {{(grid.options.paginationCurrentPage*grid.options.paginationPageSize>grid.options.totalItems?grid.options.totalItems:grid.options.paginationCurrentPage*grid.options.paginationPageSize)}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>";
+
+ $scope.gridOptions = {
+ pageNumber: 1,
+ sort : null,
+ paginationPageSizes: [5],
+ paginationPageSize: 5,
+ paginationTemplate: correctTotalPaginationTemplate,
+ columnDefs: [],
+ data: [],
+ enableGridMenu: true,
+ enableSelectAll: true,
+ gridMenuCustomItems : [
+ { title : 'All Reports',
+ action : function($event) {
+ $window.open('report.htm','_self');
+ }, order : 210 },
+ { title : 'Edit Report',
+ action : function($event) {
+ $window.open($scope.reportEditURL,'_self');
+ }, order : 211 },
+ { title : 'Export All data as Excel 2007',
+ action : function($event) {
+ $window.open('raptor.htm?c_master='+$scope.reportData.reportID+'&r_action=report.download.excel2007.session','_self');
+ }, order : 212 },
+ { title : 'Export All data as Excel',
+ action : function($event) {
+ $window.open('raptor.htm?c_master='+$scope.reportData.reportID+'&r_action=report.download.excel.session','_self');
+ }, order : 213 },
+ { title : 'Export All data as CSV',
+ action : function($event) {
+ $window.open('raptor.htm?c_master='+$scope.reportData.reportID+'&r_action=report.download.csv.session','_self');
+ }, order : 214 },
+ { title : 'Export All data as PDF',
+ action : function($event) {
+ $window.open('raptor.htm?c_master='+$scope.reportData.reportID+'&r_action=report.download.pdf.session','_self');
+ }, order : 215 } ],
+ exporterMenuPdf: false,
+ exporterMenuCsv: false,
+ exporterCsvFilename: 'myFile.csv',
+ exporterPdfDefaultStyle: {fontSize: 9},
+ exporterPdfTableStyle: {margin: [30, 30, 30, 30]},
+ exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: true, color: 'red'},
+ exporterPdfHeader: { text: "My Header", style: 'headerStyle' },
+ exporterPdfFooter: function ( currentPage, pageCount ) {
+ return { text: currentPage.toString() + ' of ' + pageCount.toString(), style: 'footerStyle' };
+ },
+ exporterPdfCustomFormatter: function ( docDefinition ) {
+ docDefinition.styles.headerStyle = { fontSize: 22, bold: true };
+ docDefinition.styles.footerStyle = { fontSize: 10, bold: true };
+ return docDefinition;
+ },
+ exporterPdfOrientation: 'portrait',
+ exporterPdfPageSize: 'LETTER',
+ exporterPdfMaxGridWidth: 500,
+ exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
+ onRegisterApi: function(gridApi) {
+ $scope.gridApi = gridApi;
+ gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
+ paginationOptions.pageNumber = newPage;
+ paginationOptions.pageSize = pageSize;
+ $scope.runReport(true);
+ });
+ }
+ };
+
+ $scope.uiGridRefresh = function(){
+ var columnDefsArray = [];
+ var columnFreezeEndColumn = $scope.reportData.colIdxTobeFreezed;
+ var doColumnNeedToFreeze = false;
+ if(columnFreezeEndColumn && columnFreezeEndColumn.length>0) {
+ doColumnNeedToFreeze = true;
+ }
+ $scope.reportData.reportDataColumns.forEach(function(entry) {
+ var tempColumnDef = { displayName: entry.columnTitle, field: entry.colId, enableSorting: entry.sortable,
+ sortingAlgorithm: function(a, b) {
+ return rowSorter.sortAlpha(a.displayValue, b.displayValue);
+ },
+ cellTemplate: '<div class="ui-grid-cell-contents" style="text-align:{{COL_FIELD.alignment}};" title="TOOLTIP"> '+
+ ' <div ng-if="!COL_FIELD.drillDownURL || COL_FIELD.drillDownURL==\'\'">{{COL_FIELD.displayValue}}</div>' +
+ ' <a ng-if="COL_FIELD.drillDownURL && COL_FIELD.drillDownURL!=\'\'" ng-href="{{COL_FIELD.drillDownURL}}&parent___params==={{grid.appScope.currentReportUrlParams}}" >{{COL_FIELD.displayValue}}</a>' +
+ '</div>'};
+ if(entry.columnWidth && entry.columnWidth!='null' && entry.columnWidth!='pxpx' && entry.columnWidth!='nullpx' && entry.columnWidth!='nullpxpx'){
+ tempColumnDef['minWidth'] = entry.columnWidth.substring(0, entry.columnWidth.length - 2);
+ } else {
+ tempColumnDef['minWidth'] = '100';
+ }
+ if(doColumnNeedToFreeze) {
+ tempColumnDef['pinnedLeft']= true;
+ if(columnFreezeEndColumn === entry.colId){
+ doColumnNeedToFreeze = false;
+ }
+ }
+ columnDefsArray.push(tempColumnDef);
+ });
+
+ $scope.gridOptions.paginationPageSizes= [$scope.reportData.pageSize];
+ $scope.gridOptions.paginationPageSize= $scope.reportData.pageSize;
+ if($scope.reportData.totalRows<14){
+ $scope.gridHeight = ($scope.reportData.totalRows+5)*30+'px';
+ }else{
+ $scope.gridHeight = '400px';
+ }
+ $scope.gridOptions.totalItems = $scope.reportData.totalRows;
+ $scope.gridOptions.columnDefs= columnDefsArray;
+ $scope.gridOptions.data= $scope.reportData.reportDataRows;
+ $scope.gridOptions.exporterPdfHeader.text= $scope.reportData.reportName;
+ };
+
+ $scope.$watch("reportData",function(newValue,oldValue) {
+ if(!$scope.urlParams.hideGrid){
+ if($scope.reportData){
+ if($scope.reportData.displayData && $scope.reportData.reportDataColumns){
+ $scope.showGrid = true;
+ $scope.uiGridRefresh();
+ }
+ }
+ }
+ });
+
+ $scope.triggerOtherFormFields = function(){
+ console.log("report_run");
+ var formFieldsUrl = $scope.getFormFieldSelectedValuesAsURL();
+ $http.get('raptor.htm?action=report.formfields.run.container&c_master='+$scope.reportData.reportID+'&'+formFieldsUrl).then(
+ function(response){
+ $scope.reportData = response.data;
+ });
+ };
+ $timeout(function() {
+ $rootScope.isViewRendering = false;
+ });
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-search-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-search-controller.js
new file mode 100644
index 00000000..1e01a297
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-search-controller.js
@@ -0,0 +1,184 @@
+appDS2.requires.push('ui.grid');
+appDS2.requires.push('ui.grid.pagination');
+appDS2.controller("reportSearchController", ['$scope','$rootScope','$http','$timeout','uiGridConstants','$modal','$q','$log','raptorReportFactory',function ($scope,$rootScope,$http,$timeout,uiGridConstants,$modal,$q,$log,raptorReportFactory) {
+
+ $scope.getSearchData = function(){
+ raptorReportFactory.getSearchData().then(function(data){
+ $scope.searchdData = data;
+ },function(error){
+ $log.error("raptorReportFactory: getSearchData failed.");
+ });
+ }
+
+ $scope.getSearchData();
+
+ $scope.runReport = function(){
+ var searchParams = '';
+ if($scope.reportId && $scope.reportId!=''){
+ searchParams = '&rep_id='+$scope.reportId+'&rep_id_options='+$scope.operatorRepId.index;
+ }
+ if($scope.reportName && $scope.reportName!=''){
+ searchParams = searchParams+'&rep_name='+$scope.reportName+'&rep_name_options='+$scope.operatorRepName.index;
+ }
+
+ var pageSearchParameter = ($scope.paginationOptions.pageNumber-1)+searchParams
+ raptorReportFactory.getSearchDataAtPage(pageSearchParameter).then(function(data){
+ $scope.searchdData = data
+ },function(error){
+ $log.error("raptorReportFactory: getSearchDataAtPage failed.");
+ });
+ };
+
+
+ $scope.paginationOptions = {
+ pageNumber: 1,
+ pageSize: 5,
+ sort: null
+ };
+
+ var correctTotalPaginationTemplate =
+ //same as normal template, but fixed totals: {{(((grid.options.paginationCurrentPage-1)*grid.options.paginationPageSize)+1)}} {{(grid.options.paginationCurrentPage*grid.options.paginationPageSize>grid.options.totalItems?grid.options.totalItems:grid.options.paginationCurrentPage*grid.options.paginationPageSize)}}
+ "<div role=\"contentinfo\" class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div role=\"menubar\" class=\"ui-grid-pager-control\"><button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle\"><div class=\"first-bar\"></div></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle prev-triangle\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div class=\"last-triangle next-triangle\"></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div class=\"last-triangle\"><div class=\"last-bar\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{(((grid.options.paginationCurrentPage-1)*grid.options.paginationPageSize)+1)}} <abbr ui-grid-one-bind-title=\"paginationThrough\">-</abbr> {{(grid.options.paginationCurrentPage*grid.options.paginationPageSize>grid.options.totalItems?grid.options.totalItems:grid.options.paginationCurrentPage*grid.options.paginationPageSize)}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>";
+
+ $scope.gridOptions = {
+ paginationPageSizes: [5],
+ paginationPageSize: 5,
+ paginationTemplate: correctTotalPaginationTemplate,
+ columnDefs: [],
+ data: [],
+ enableGridMenu: true,
+ enableSelectAll: true,
+ exporterMenuPdf: false,
+ exporterMenuCsv: false,
+ exporterCsvFilename: 'myFile.csv',
+ exporterPdfDefaultStyle: {fontSize: 9},
+ exporterPdfTableStyle: {margin: [30, 30, 30, 30]},
+ exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: true, color: 'red'},
+ exporterPdfHeader: { text: "My Header", style: 'headerStyle' },
+ exporterPdfFooter: function ( currentPage, pageCount ) {
+ return { text: currentPage.toString() + ' of ' + pageCount.toString(), style: 'footerStyle' };
+ },
+ exporterPdfCustomFormatter: function ( docDefinition ) {
+ docDefinition.styles.headerStyle = { fontSize: 22, bold: true };
+ docDefinition.styles.footerStyle = { fontSize: 10, bold: true };
+ return docDefinition;
+ },
+ exporterPdfOrientation: 'portrait',
+ exporterPdfPageSize: 'LETTER',
+ exporterPdfMaxGridWidth: 500,
+ exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
+ onRegisterApi: function(gridApi) {
+ gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
+ $scope.paginationOptions.pageNumber = newPage;
+ $scope.paginationOptions.pageSize = pageSize;
+ $scope.runReport();
+ });
+ }
+ };
+
+
+ var getPage = function() {
+ $scope.gridOptions.columnDefs = [];
+ $scope.searchdData.columns[0].forEach(function(entry) {
+ if(entry.columnTitle=='Run'){
+ $scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId, enableSorting: false,
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="#/report_run/{{COL_FIELD.drillDownLink.substr(39)}}" class="icon-controls-pointer" style="font-size:20px;"></a></div>'
+ });
+ } else if(entry.columnTitle=='Edit'){
+ $scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId, enableSorting: false,
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD.drillDownLink}}" class="icon-misc-pen" style="font-size:20px;"></a></div>'
+ });
+ } else if(entry.columnTitle=='Delete'){
+ $scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId, enableSorting: false,
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-click="grid.appScope.removeReport(COL_FIELD.drillDownLink,row)" class="icon-misc-trash" style="font-size:20px;"></a></div>'
+ });
+ } else if(entry.columnTitle=='Copy'){
+ $scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId, enableSorting: false,
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD.drillDownLink}}" class="icon-documents-copy" style="font-size:20px;"></a></div>'
+ });
+ } else if(entry.columnTitle=='Schedule'){
+ } else if(entry.columnTitle=='No'){
+ } else {
+ $scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId,
+ enableSorting: true,
+ cellTemplate: '<div class="ui-grid-cell-contents" style="text-align:{{COL_FIELD.alignment}};" title="TOOLTIP"> <div>{{COL_FIELD.displayValue}}</div> </div>'
+ });
+ }
+ });
+
+ $scope.gridOptions.paginationPageSizes= [$scope.searchdData.metaReport.pageSize];
+ $scope.gridOptions.paginationPageSize= $scope.searchdData.metaReport.pageSize;
+ $scope.gridOptions.totalItems = $scope.searchdData.metaReport.totalSize;
+
+ $scope.gridOptions.data = [];
+ $scope.searchdData.rows[0].forEach(function(entry) {
+ var localData = {};
+ entry.forEach(function(rowData){
+ localData[rowData["columnId"]]= rowData["searchresultField"];
+ });
+ $scope.gridOptions.data.push(localData);
+ });
+ };
+
+ $scope.$watch("searchdData",function(newValue,oldValue) {
+ if($scope.searchdData){
+ getPage();
+ }
+ });
+
+ $scope.operatorsRepId = [
+ {index: 0, value: 'Equal To', text: 'Equal To', alias:'Equal To'},
+ {index: 1, value: 'Less Than', text: 'Less Than', alias:'Less Than'},
+ {index: 2, value: 'Greater Than', text: 'Greater Than', alias:'Greater Than'}];
+ $scope.operatorRepId = {};
+ $scope.operatorRepId.value = $scope.operatorsRepId[0].value;
+ $scope.operatorRepId.index = $scope.operatorsRepId[0].index;
+
+ $scope.operatorsRepName = [
+ {index: 0, value: 'Starts With', text: 'Starts With', alias:'Starts With'},
+ {index:1, value: 'Ends With', text: 'Ends With', alias:'Ends With'},
+ {index: 2, value: 'Contains', text: 'Contains', alias:'Contains'}];
+
+ $scope.operatorRepName = {};
+ $scope.operatorRepName.value = $scope.operatorsRepName[0].value;
+ $scope.operatorRepName.index = $scope.operatorsRepName[0].index;
+
+ $scope.removeReport = function(reportDeleteUrl,row) {
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-del-confirm.html',
+ sizeClass: 'modal-small',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory', function ($scope, $modalInstance, $http, $log, raptorReportFactory) {
+ $scope.ok = function() {
+ raptorReportFactory.getReportDeleteStatus(reportDeleteUrl).then(function(data){
+ if (!(data.deleted)) {
+ $log.error("raptorReportFactory: report removal failed.")
+ }
+ $modalInstance.close();
+ },function(error){
+ $log.error("report removal error.")
+ });
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('RefreshGridOptions');
+ }, function () {
+ });
+ };
+
+ $scope.$on('RefreshGridOptions', function(event) {
+ $scope.getSearchData();
+ });
+
+ $timeout(function() {
+ $rootScope.isViewRendering = false;
+ });
+
+
+}]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-step-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-step-controller.js
new file mode 100644
index 00000000..6133fe64
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-reports/report-step-controller.js
@@ -0,0 +1,900 @@
+appDS2.controller('reportStepController', function($scope,$http,$location, $routeParams, $q, $modal,$log,$window, raptorReportFactory, stepFormFactory, DOMHelper) {
+
+ // tabs for report wizard steps:
+ $scope.activeTabsId = 'Definition';
+
+ // For all the dropdown box, please declare the active selection variable in the following manner:
+ // $scope.selectedOpt = {};
+ // $scope.selectedOpt.value = "";
+ $scope.getDefinitionById = function(id) {
+ raptorReportFactory.getDefinitionByReportId(id).then(function(data){
+ $scope.loadDefinition(data);
+ $scope.definitionData = data;
+ },function(error){
+ $log.error("raptorReportFactory: getSearchData failed.");
+ });
+ }
+
+
+ $scope.createNewDefinition = function() {
+ raptorReportFactory.createNewDefinition().then(function(data){
+ $scope.loadDefinition(data);
+ $scope.definitionData = data;
+ },function(error){
+ $log.error("raptorReportFactory: getSearchData failed.");
+ });
+ }
+
+ var initializeCreateReport = function() {
+ $scope["selectedReportType"] ={};
+ $scope.selectedReportType.value ="linear";
+ $scope.selectedReportType2 ={};
+ $scope.selectedReportType2.value ="";
+ $scope.selectedDataSource ={};
+ $scope.selectedDataSource.value="local";
+ $scope.sqlScript = "SELECT ";
+ $scope.pageSize = {"value":"50"};
+ }
+
+
+ var loadSqlInSession = function(){
+ raptorReportFactory.getSqlInSession().then(function(data){
+ $scope.sqlInSessionJSON = data;
+ $scope.sqlScript = data.query;
+ },function(error){
+ $log.error("raptorReportFactory: getSearchData failed.");
+ });
+ };
+
+ initializeCreateReport();
+ if ($routeParams.reportMode) {
+ if ($routeParams.reportMode=="copy") {
+ raptorReportFactory.copyReportById($routeParams.reportId).then(function(data){
+ $scope.$emit('RefreshInsession');
+ },function(error){
+ $log.error("raptorReportFactory: deleteFormFieldById failed.");
+ });
+ } else if ($routeParams.reportMode=="import") {
+ $scope.$emit('RefreshInsession');
+ }
+ } else if ($routeParams.reportId) {
+ $scope.getDefinitionById($routeParams.reportId);
+ $scope.isEdit = true;
+ $scope.reportId = $routeParams.reportId;
+ } else {
+ $scope.isEdit = false;
+ $scope.createNewDefinition();
+ }
+
+
+ $scope.RunCurrentReport = function (){
+ $window.location.href = "#/report_run/c_master="+$scope.reportId+"&refresh=Y";
+ }
+
+ $scope.deleteFormField = function(rowData) {
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-formfield-del-confirm.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory','rowData', function ($scope, $modalInstance, $http, $log, raptorReportFactory, rowData) {
+ $scope.tempFieldId = rowData.id;
+ $scope.ok = function() {
+ raptorReportFactory.deleteFormFieldById(rowData.id).then(function(data){
+ $modalInstance.close();
+ },function(error){
+ $log.error("raptorReportFactory: deleteFormFieldById failed.");
+ });
+ }
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ resolve:{
+ rowData: function(){
+ return rowData;
+ }
+ }
+ });
+ modalInstance.result.then(function () {
+ $scope.$emit('RefreshFormField');
+ }, function () {
+ });
+ }
+
+ $scope.loadDefinition = function(definitionData) {
+ $scope.reportId = definitionData.reportId+"";
+ $scope.reportName = definitionData.reportName;
+ $scope.reportDescr = definitionData.reportDescr;
+ $scope.formHelpText = definitionData.formHelpText;
+ $scope.selectedPageSize = {"value": definitionData.pageSize+''};
+ $scope.selectedMaxRowsInExcelCSVDownload = {"value": definitionData.maxRowsInExcelCSVDownload};
+ $scope.reportTitle = definitionData.reportTitle;
+ $scope.reportSubTitle = definitionData.reportSubTitle;
+ $scope.selectedNumFormCols ={"value": definitionData.numFormCols+''};
+ $scope.selectedFrozenColumns={"value": definitionData.frozenColumns+''};
+ $scope.selectedDataGridAlign = {"value":definitionData.dataGridAlign+''};
+ $scope.emptyMessage = definitionData.emptyMessage+'';
+ $scope.selectedDataContainerHeight = {"value":definitionData.dataContainerHeight+''};
+ $scope.selectedDataContainerWidth = {"value":definitionData.dataContainerWidth+''};
+ var displayAreaValue = "null"
+ for (var i=0; i<3; i++ ) {
+ if (definitionData.displayArea[i].selected) {
+ displayAreaValue = definitionData.displayArea[i].name;
+ }
+ }
+ $scope.selectedDisplayArea = {"value":displayAreaValue+""};
+
+ $scope.hideFormFieldsAfterRunSelected = {"value": definitionData.hideFormFieldsAfterRun}
+
+ $scope.hideFormFieldsSelected = {"value":definitionData.displayOptions[0].selected};
+ $scope.hideChartSelected = {"value":definitionData.displayOptions[1].selected};
+ $scope.hideReportDataSelected = {"value":definitionData.displayOptions[2].selected};
+ $scope.hideExcelSelected = {"value":definitionData.displayOptions[3].selected};
+ $scope.hidePdfSelected = {"value":definitionData.displayOptions[4].selected};
+ $scope.runtimeColSortDisabled = {"value":definitionData.runtimeColSortDisabled};
+ }
+
+
+ var setDefinition = function(){
+ $scope.updatedDefJson = {
+ "tabName" : "Definition",
+ "tabId" : "Def",
+ "reportId" : ($scope.isEdit?$scope.reportId+'':"-1"),
+ "reportName" : $scope.reportName,
+ "reportDescr" : $scope.reportDescr,
+ "reportType" : "Linear",
+ "dbInfo" : "local",
+ "formHelpText" : $scope.formHelpText,
+ "pageSize" : Number($scope.selectedPageSize.value),
+ "displayArea" : [ {
+ "id" : "HOME",
+ "name" : "HOME",
+ "selected" : ($scope.selectedDisplayArea.value=="HOME")
+ }, {
+ "id" : "CUSTOMER",
+ "name" : "CUSTOMER",
+ "selected" : ($scope.selectedDisplayArea.value==="CUSTOMER")
+ }, {
+ "id" : "REPORTS",
+ "name" : "REPORTS",
+ "selected" : ($scope.selectedDisplayArea.value==="REPORTS")
+ } ],
+ "hideFormFieldsAfterRun" : $scope.hideFormFieldsAfterRunSelected.value,
+ "maxRowsInExcelCSVDownload" : Number($scope.selectedMaxRowsInExcelCSVDownload.value),
+ "frozenColumns" : Number($scope.selectedFrozenColumns.value),
+ "dataGridAlign" : $scope.selectedDataGridAlign.value,
+ "emptyMessage" : $scope.emptyMessage,
+ "dataContainerHeight" : $scope.selectedDataContainerHeight.value,
+ "dataContainerWidth" : $scope.selectedDataContainerWidth.value,
+ "displayOptions" : [ {
+ "name" : "HideFormFields",
+ "selected" : $scope.hideFormFieldsSelected.value
+ }, {
+ "name" : "HideChart",
+ "selected" : $scope.hideChartSelected.value
+ }, {
+ "name" : "HideReportData",
+ "selected" : $scope.hideReportDataSelected.value
+ }, {
+ "name" : "HideExcel",
+ "selected" : $scope.hideExcelSelected.value
+ }, {
+ "name" : "HidePdf",
+ "selected" : $scope.hidePdfSelected.value
+ } ],
+ "runtimeColSortDisabled" : $scope.runtimeColSortDisabled.value,
+ "numFormCols" : Number($scope.selectedNumFormCols.value),
+ "reportTitle" : $scope.reportTitle,
+ "reportSubTitle" : $scope.reportSubTitle
+ }
+
+ }
+
+ var updateDefinitionData = function() {
+ setDefinition();
+ raptorReportFactory.updateDefinition($scope.updatedDefJson,$scope.isEdit).then(function(data){
+ },function(error){
+ $log.error("raptorReportFactory: updateDefinition by Id failed.");
+ });
+ }
+
+ var saveNewDefinitionData = function() {
+ setDefinition();
+ raptorReportFactory.saveNewDefinition($scope.updatedDefJson).then(function(data){
+ },function(error){
+ $log.error("raptorReportFactory: saveNewDefinition by Id failed.");
+ });
+ }
+
+ $scope.testRunSql = function(){
+ var queryJSON = {query: $scope.sqlScript};
+ queryJSON = JSON.stringify(queryJSON);
+ raptorReportFactory.testRunSQL(queryJSON).then(function(data){
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory','queriedData', function ($scope, $modalInstance, $http, $log, raptorReportFactory, queriedData) {
+ var init = function() {
+ $scope.isError = false;
+ if (queriedData.errormessage) {
+ $scope.isError = true;
+ $scope.errormessage = queriedData.errormessage;
+ $scope.stacktrace = queriedData.stacktrace;
+ } else {
+ $scope.queryData = queriedData;
+ }
+ }
+ init();
+ $scope.close = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ resolve:{
+ queriedData: function(){
+ return data;
+ }
+ }
+ })
+
+ },function(error){
+ $log.error("raptorReportFactory: test run SQL failed.");
+ });
+ }
+
+
+ $scope.formFieldVerifySQL= function(sqlScript){
+ var queryJSON = {query: sqlScript};
+ queryJSON = JSON.stringify(queryJSON);
+ raptorReportFactory.formFieldVerifySQL(queryJSON).then(function(data){
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory','queriedData', function ($scope, $modalInstance, $http, $log, raptorReportFactory, queriedData) {
+ var init = function() {
+ $scope.isError = false;
+ if (queriedData.errormessage) {
+ $scope.isError = true;
+ $scope.errormessage = queriedData.errormessage;
+ $scope.stacktrace = queriedData.stacktrace;
+ } else {
+ $scope.queryData = queriedData;
+ }
+ }
+ init();
+ $scope.close = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ resolve:{
+ queriedData: function(){
+ return data;
+ }
+ }
+ })
+
+ },function(error){
+ $log.error("raptorReportFactory: test run SQL failed.");
+ });
+ }
+
+
+ /* $scope.selectedDataSource.allowSchedule={};
+ $scope.selectedDataSource.allowSchedule.value=""*/
+
+ var getJsonSrcName = function(stepNum){
+ var JsonSrcPrefix = "app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step"
+ return JsonSrcPrefix + stepNum +".json";
+ }
+
+ $scope.gTabs = [
+ {
+ title: 'Definition',
+ id: 'Definition',
+ uniqueId: 'uniqueTab1x',
+ tabPanelId: 'threetab1x'
+ }, {
+ title: 'SQL',
+ id: 'SQL',
+ uniqueId: 'uniqueTab2x',
+ tabPanelId: 'threetab2x',
+ disabled: (!$scope.isEdit)
+ }, {
+ title: 'Columns',
+ id: 'Columns',
+ uniqueId: 'uniqueTab3x',
+ tabPanelId: 'threetab3x',
+ disabled: (!$scope.isEdit)
+ }, {
+ title: 'Form Fields',
+ id: 'Form Fields',
+ uniqueId: 'uniqueTab4x',
+ tabPanelId: 'threetab4x',
+ disabled: (!$scope.isEdit)
+ }, {
+ title: 'Run',
+ id: 'Run',
+ uniqueId: 'uniqueTab5x',
+ tabPanelId: 'threetab5x',
+ disabled: (!$scope.isEdit)
+ }
+ ];
+
+ $scope.unhideAllOtherTabs = function(){
+ for (var selectedTab = 0; selectedTab < $scope.gTabs.length; selectedTab++) {
+ $scope.gTabs[selectedTab].disabled = false;
+ }
+ }
+
+ $scope.openColumnPopup = function (rowData) {
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-col-edit.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory','colData', function ($scope, $modalInstance, $http, $log, raptorReportFactory, colData) {
+ raptorReportFactory.getColumnEditInfoById(colData.id).then(function(data){
+ $scope.columnEditData = data;
+ $scope.colId = data.colId;
+/* $scope.colName = data.colName;*/
+ $scope.colName = {'value':data.colName+''};
+ $scope.selectedDisplayAlignment = {"value":data.displayAlignment+''};
+ $scope.selectedDisplayHeaderAlignment = {"value":data.displayHeaderAlignment+''};
+ $scope.sortable = {"value":''+data.sortable};
+ $scope.visible = {"value":''+data.visible};
+ $scope.drilldownURL = data.drilldownURL;
+ $scope.drilldownParams = data.drilldownParams;
+ $scope.drilldownType = data.drilldownType;
+ },function(error){
+ $log.error("raptorReportFactory: getColumnEditInfoById failed.");
+ });
+
+ var init = function() {
+/* $scope.colTableRowData = colData;*/
+ $scope.displayAlignmentOptions = [
+ {value:"null", text:""},
+ {value:"Left", text:"Left"},
+ {value:"Center", text:"Center"},
+ {value:"Right", text:"Right"}
+ ];
+ $scope.ynOptions = [
+ {value:"true", text:"Yes"},
+ {value:"false", text:"No"}
+ ];
+ $scope.drillDownOptions = [
+ {value:"drillDownOpt1", text:"drillDownOpt1"},
+ {value:"drillDownOpt2", text:"drillDownOpt2"},
+ {value:"drillDownOpt3", text:"drillDownOpt3"}
+ ];
+ }
+
+ init();
+
+ $scope.save = function() {
+ var colInfo = {
+ "tabId" : "ColEdit",
+ "tabName" : "Column Edit",
+ "colId" : $scope.colId,
+ "colName" : $scope.colName.value,
+ "displayAlignment" : ($scope.selectedDisplayAlignment.value=="null")?null:$scope.selectedDisplayAlignment.value,
+ "displayHeaderAlignment" : ($scope.selectedDisplayHeaderAlignment.value=="null")?null:$scope.selectedDisplayHeaderAlignment.value,
+ "sortable" : ($scope.sortable.value=="true"),
+ "visible" : ($scope.visible.value=="true"),
+ "drilldownURL" : "",
+ "drilldownParams" : "",
+ "drilldownType" : ""
+ }
+ raptorReportFactory.saveColumnEditInfo(colInfo).then(function(data){
+ $modalInstance.close();
+ },function(error){
+ $log.error("raptorReportFactory: getColumnEditInfoById failed.");
+ });
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ resolve:{
+ colData: function(){
+ return rowData;
+ }
+ }
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('RefreshColumnList');
+ }, function () {
+ });
+ };
+ $scope.addNewFormField = function () {
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory', function ($scope, $modalInstance, $http, $log, raptorReportFactory) {
+ raptorReportFactory.getFormFieldEditInfoById("add").then(function(data){
+ $scope.formFieldEditData = data;
+ $scope.fieldId = $scope.formFieldEditData.fieldId;
+ $scope.fieldName ={"value": $scope.formFieldEditData.fieldName};
+ $scope.selectedVisible = {"value":$scope.formFieldEditData.visible+''};
+ $scope.defaultValue = {"value": $scope.formFieldEditData.defaultValue};
+ $scope.fieldDefaultSQL = {"value": $scope.formFieldEditData.fieldDefaultSQL};
+ $scope.fieldSqlContent = {"value": $scope.formFieldEditData.fieldSQL};
+ $scope.selectedValidationType = {"value":$scope.formFieldEditData.validationType +''};
+ $scope.selectedFieldType = {"value":$scope.formFieldEditData.fieldType +''};
+ $scope.sqlDefaultValueSelected= {value:false};
+ $scope.sqlDefaultValueSelected ={"value":false};
+ if (($scope.fieldDefaultSQL.value)&&($scope.fieldDefaultSQL.value!="")) {
+ $scope.sqlDefaultValueSelected.value =true;
+ }
+ },function(error){
+ $log.error("raptorReportFactory: getColumnEditInfoById failed.");
+ });
+
+
+ $scope.ynOptions = [
+ {value:"true", text:"Yes"},
+ {value:"false", text:"No"}
+ ];
+
+ $scope.verifyFieldValueOptions = [
+ {value:"DATE", text:"Date"},
+ {value:"TIME_STAMP_HOUR", text:"TimeStamp (Hour)"},
+ {value:"TIME_STAMP_HOUR_MIN", text:"TimeStamp (Hour,Min)"},
+ {value:"HIDDEN", text:"Hidden"}
+ ]
+
+ $scope.fieldTypeOptions = [
+ {value:"TEXT", text:"Text Box"},
+ {value:"LIST_BOX", text:"List Box"},
+ {value:"LIST_MULTI_SELECT", text:"Multi-select List Box"},
+ {value:"HIDDEN", text:"Hidden"}
+ ];
+
+ $scope.save = function() {
+ var formFieldJSON = {
+ "tabId" : "FormEdit",
+ "tabName" : "Form Edit",
+ "fieldId" : $scope.fieldId,
+ "fieldName" : $scope.fieldName.value,
+ "fieldType" : $scope.selectedFieldType.value,
+ "visible" : ($scope.selectedVisible.value=="true"),
+ "defaultValue" : ($scope.sqlDefaultValueSelected.value?'':$scope.defaultValue.value),
+ "fieldDefaultSQL" : ($scope.sqlDefaultValueSelected.value?$scope.fieldDefaultSQL.value:""),
+ "fieldSQL" :$scope.fieldSqlContent.value,
+ "validationType" : "NONE",
+ "predefinedValueList" :null
+ }
+ raptorReportFactory.saveFormFieldEditInfo(formFieldJSON).then(function(data){
+ $modalInstance.close();
+ },function(error){
+ $log.error("raptorReportFactory: saveFormFieldEditInfo failed.");
+ });
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }]
+ });
+ modalInstance.result.then(function () {
+ $scope.$emit('RefreshFormField');
+ }, function () {
+ });
+ };
+
+ $scope.openFormFieldPopup = function (rowData) {
+ var modalInstance = $modal.open({
+ scope: $scope,
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html',
+ sizeClass: 'modal-large',
+ controller: ['$scope', '$modalInstance', '$http', '$log','raptorReportFactory','fieldData', function ($scope, $modalInstance, $http, $log, raptorReportFactory, fieldData) {
+ var init = function() {
+ raptorReportFactory.getFormFieldEditInfoById(fieldData.id).then(function(data){
+ $scope.formFieldEditData = data;
+ $scope.fieldId = $scope.formFieldEditData.fieldId;
+ $scope.fieldName = {"value":$scope.formFieldEditData.fieldName};
+ $scope.selectedVisible = {"value":$scope.formFieldEditData.visible+''};
+ $scope.defaultValue = {"value":$scope.formFieldEditData.defaultValue};
+ $scope.fieldDefaultSQL = {"value": $scope.formFieldEditData.fieldDefaultSQL};
+ $scope.fieldSqlContent = {"value": $scope.formFieldEditData.fieldSQL};
+ $scope.selectedValidationType = {"value":$scope.formFieldEditData.validationType +''};
+ $scope.selectedFieldType = {"value":$scope.formFieldEditData.fieldType +''};
+ $scope.sqlDefaultValueSelected ={"value":false};
+ if (($scope.fieldDefaultSQL.value)&&($scope.fieldDefaultSQL.value!="")) {
+ $scope.sqlDefaultValueSelected.value =true;
+ }
+ },function(error){
+ $log.error("raptorReportFactory: getColumnEditInfoById failed.");
+ });
+
+ $scope.ynOptions = [
+ {value:"true", text:"Yes"},
+ {value:"false", text:"No"}
+ ];
+
+ $scope.verifyFieldValueOptions = [
+ {value:"DATE", text:"Date"},
+ {value:"TIME_STAMP_HOUR", text:"TimeStamp (Hour)"},
+ {value:"TIME_STAMP_HOUR_MIN", text:"TimeStamp (Hour,Min)"},
+ {value:"HIDDEN", text:"Hidden"}
+ ]
+
+ $scope.fieldTypeOptions = [
+ {value:"TEXT", text:"Text Box"},
+ {value:"LIST_BOX", text:"List Box"},
+ {value:"LIST_MULTI_SELECT", text:"Multi-select List Box"},
+ {value:"HIDDEN", text:"Hidden"}
+ ];
+
+ }
+
+ init();
+
+ $scope.save = function() {
+ var formFieldJSON = {
+ "tabId" : "FormEdit",
+ "tabName" : "Form Edit",
+ "fieldId" : $scope.fieldId,
+ "fieldName" : $scope.fieldName.value,
+ "fieldType" : $scope.selectedFieldType.value,
+ "visible" : ($scope.selectedVisible.value=="true"),
+ "defaultValue" : ($scope.sqlDefaultValueSelected.value?'':$scope.defaultValue.value),
+ "fieldDefaultSQL" : ($scope.sqlDefaultValueSelected.value?$scope.fieldDefaultSQL.value:""),
+ "fieldSQL" :$scope.fieldSqlContent.value,
+ "validationType" : "NONE",
+ "predefinedValueList" :null
+ }
+ raptorReportFactory.saveFormFieldEditInfo(formFieldJSON).then(function(data){
+ $modalInstance.close();
+ },function(error){
+ $log.error("raptorReportFactory: saveFormFieldEditInfo failed.");
+ });
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ resolve:{
+ fieldData: function(){
+ return rowData;
+ }
+ }
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('RefreshFormField');
+ }, function () {
+ });
+ };
+
+
+ $scope.$watch('activeTabsId', function (newVal, oldVal) {
+ if(newVal !== oldVal) {
+ var selectedTab;
+ for (selectedTab = 0; selectedTab < $scope.gTabs.length; selectedTab++) {
+ if ($scope.gTabs[selectedTab].id === newVal) {
+ $scope.stepNum = selectedTab;
+/* stepFormFactory.getStepJSONData(getJsonSrcName($scope.stepNum))*/
+ $scope.isColumnStep = false;
+ $scope.isFormFieldStep = false;
+ $scope.renderStep(selectedTab+1);
+ if ($scope.stepNum == 2) {
+ loadSqlInSession();
+ } else if ($scope.stepNum == 3) {
+ $scope.isColumnStep = true;
+
+ raptorReportFactory.getColumnList().then(function(data){
+ $scope.colTableRowData = data;
+ },function(error){
+ $log.error("raptorReportFactory: get column list failed."); });
+
+ } else if ($scope.stepNum == 4) {
+ $scope.isFormFieldStep = true;
+ // put within then function:
+ raptorReportFactory.getFormFieldList().then(function(data){
+ $scope.formFieldData = data;
+ },function(error){
+ $log.error("raptorReportFactory: get formfields failed."); });
+ } else if ($scope.stepNum == 5) {
+ raptorReportFactory.getDefinitionInSession().then(function(data){
+ $scope.reportId = data.reportId;
+ },function(error){
+ $log.error("raptorReportFactory: getDefinitionInSession failed."); });
+ }
+
+ if ($scope.stepNum>1){
+ $scope.unhideAllOtherTabs();
+ }
+ break;
+ }
+ }
+
+ var selectedTabPanelElement = document.getElementById($scope.gTabs[selectedTab].tabPanelId);
+
+ var elem = null;
+ if (selectedTabPanelElement) {
+ elem = DOMHelper.firstTabableElement(selectedTabPanelElement);
+ }
+
+ if (elem) {
+ $timeout(function () {
+ elem.focus();
+ }, 100);
+ }
+ }
+ });
+
+
+ $scope.renderStep = function(stepNum){
+ var containerElement = angular.element(document.getElementById("stepView"));
+ containerElement.empty();
+ $scope.stepNum = stepNum;
+ var jsonSrcName = getJsonSrcName(stepNum);
+ stepFormFactory.renderForm(jsonSrcName, containerElement, $scope);
+ }
+
+ // initialize the page at step 1;
+ $scope.renderStep(1);
+
+ // create a message to display in our view
+ $scope.allProjects = [];
+ if(!$routeParams.step && $routeParams.step == "") $routeParams.step = 1;
+ if($routeParams.proj && $routeParams.proj > 0)
+ $scope.projid = $routeParams.proj;
+ if($routeParams.step)
+ $scope.stepNum = $routeParams.step;
+ else
+ $scope.stepNum = 1;
+
+ $scope.jsonSrcName = getJsonSrcName($scope.stepNum);
+
+ $scope.selectAction = function () {
+ var containerElement = angular.element(document.getElementById("stepView"));
+ containerElement.empty();
+ $scope.project_name = this.prj.projectName;
+ $scope.stepNum = 1;
+ var stepNum = $scope.stepNum;
+ var jsonSrcName = getJsonSrcName(stepNum);
+ stepFormFactory.renderForm(jsonSrcName, containerElement, $scope);
+ renderProject(this.prj.id, 1);
+ };
+
+
+ $scope.createAction = function () {
+ var containerElement = angular.element(document.getElementById("stepView"));
+ containerElement.empty();
+ $scope.stepNum = 1;
+ var stepNum = $scope.stepNum;
+ $scope.jsonSrcName = "app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step"+$scope.stepNum +".json";
+ var jsonSrcName = $scope.jsonSrcName;
+ stepFormFactory.renderForm(jsonSrcName, containerElement, $scope);
+ };
+
+ // select current project
+ renderProject = function (proj_id, stepNum) {
+ var userSelectedPrjId = proj_id;
+ $http({
+ method: 'GET',
+ url: 'get_selected_project_data',
+ params:{'selectedPrjId':userSelectedPrjId, 'step': stepNum}
+ }).then(function successCallback(response) {
+ var selectedproject = response.data;
+ $scope.projid = userSelectedPrjId;
+ //$scope.allProjects = projectLists;
+ //$location.path('/'+userSelectedPrjId+'/'+stepNum);
+ var div = d3.select("#stepView");
+ div.select("[name='proj_id']").text(userSelectedPrjId);
+ div.select("[name='proj_id']").property("value", userSelectedPrjId);
+ d3.select("[name='project_id']").property("value", userSelectedPrjId);
+ var h3Text = div.select("h3").text();
+ div.select("h3").text($scope.project_name+ " - " + h3Text);
+ for (var key in selectedproject) {
+ if (selectedproject.hasOwnProperty(key)) {
+ var val = selectedproject[key];
+ var formElement = d3.selectAll("[name='" + key + "']");
+ if(formElement[0].length > 0)
+ console.log(formElement.attr("type"));
+ if(formElement[0].length > 0 && formElement.attr("type") === "radio") {
+ var formRadio = d3.selectAll("[id='" + key +"_"+val + "']");
+ formRadio.property('checked', true);
+ }
+ if(formElement[0].length > 0 && formElement.property("type") === "textarea") {
+ div.select("textarea[name='" + key +"']").property('value', val);
+ }
+ if(formElement[0].length > 0 && formElement.attr("type") === "text") {
+ var formText = d3.selectAll("[name='" + key + "']");
+ formText.property("value", val);
+ }
+ if(formElement[0].length > 0 && formElement.html().startsWith("<option")) {
+ var formSelect = d3.selectAll("[name='" + key + "']");
+
+ var checkOption = function (e) {
+ if(e.label === val){
+ return formSelect.property("selectedIndex", e.index );
+ }
+ };
+
+ formSelect.selectAll("option").forEach(function(d) {d.forEach(function(optionD) { console.log(optionD);checkOption(optionD); }) });
+ }
+
+ if(formElement[0].length == 0) {
+ if(key != 'step') {
+ if( Object.prototype.toString.call( val ) === '[object Array]' ) {
+ val.forEach(function(d){
+ for (var keyCheck in d) {
+ if (d.hasOwnProperty(keyCheck)) {
+ var valCheck = d[keyCheck];
+ var formCheck = d3.selectAll("[name='" + key + "_"+keyCheck + "']");
+ if(valCheck === true)
+ formCheck.property('checked', true);
+ }
+ }
+ });
+ }
+ }
+ var formElementOther = d3.selectAll("[name='" + key + "_"+ val + "']");
+ if(formElementOther[0].length > 0 && formElementOther.attr("type") === "checkbox") {
+ var formCheckbox = d3.selectAll("[name='" + key +"_"+val + "']");
+ formRadio.property('checked', true);
+ }
+ }
+ }
+ }
+
+
+
+ });
+ }
+
+ //submit function
+ $scope.submit = function(){
+ let defer = $q.defer();
+
+ var div = d3.select("#stepView");
+ var jsonSrcName = $scope.jsonSrcName;
+ var stepNum = $scope.stepNum;
+ var values = "";
+ $http({
+ method: 'GET',
+ url: jsonSrcName
+ }).then(function successCallback(response) {
+ var json = response.data;
+ var step = json.step;
+ if(step > 0) {
+ var sections = json.content.sections;
+ sections.forEach(function(d, i) {
+ var elements = d.elements;
+ if(elements) {
+ //elements.forEach(function(element, elementIndex) {
+ values += "{";
+ values += "\"step\""+ ":\"" + step + "\",";
+ values += "\"proj_id\""+ ":\"" + d3.select('input[name="project_id"]').property("value") + "\",";
+
+ for (elementIndex = 0; elementIndex < elements.length; elementIndex++) {
+ var element = elements[elementIndex];
+
+ if(elementIndex > 0) values += ",";
+ values += "\""+element.name +"\""+ ":" ;
+ if(element.input === "hidden") {
+ values += "\""+div.select('input[name="'+element.name+'"]').property("value") +"\"";
+ }
+ if(element.input === "radio") {
+ values += "\""+ div.select('input[name="'+element.name+'"]:checked').property("value") +"\"";
+ }
+ if(element.input === "checkbox") {
+ var checkOptions = element.options;
+ values += "[{";
+ checkOptions.forEach(function(d, i) {
+ // if(document.getElementById("'"+element.name+"_"+d.id+"'") != null)
+ values += "\""+d.id+"\""+ ":" + div.select('input[name="'+element.name+"_"+d.id+'"]').property("checked") ;
+ if(i<checkOptions.length-1) {
+ values += ",";
+ }
+ })
+ values += "}]";
+ }
+ if(element.input === "text") {
+ values += "\""+div.select('input[name="'+element.name+'"]').property("value") +"\"";
+ }
+ if(element.input === "textarea") {
+ values += "\""+div.select('textarea[name="'+element.name+'"]').node().value +"\"";
+ }
+ if(element.input === "select") {
+ values += "\""+ div.select('select[name="'+element.name+'"]').property("value") + "\"";
+ }
+
+ };
+ values += "}";
+ }
+ });
+ }
+ var valueJSON = JSON.parse(values);
+ var valueStr = JSON.stringify(valueJSON, null, 4);
+ $http({method:'POST', url:'save_steps', data: jsonSrcName, params:{'result' : valueStr, 'proj_id' : values.proj_id}}).success(function(data, status) {
+ if(data.project_name)
+ $scope.project_name = data.project_name;
+ div.select("[name='proj_id']").property("value", data.proj_id);
+ d3.select("[name='project_id']").property("value", data.proj_id);
+ //$scope.projid = data.proj_id;
+ valueStr=JSON.stringify(data, null, 4);
+ defer.resolve();
+ //stepNum = Number(stepNum || 0)+1;
+ //document.getElementById('itestframe').src = data;
+
+ })
+
+ defer.resolve();
+
+ });
+ // $location.path('/step'+($scope.stepNum+1));
+ return defer.promise;
+
+ };
+
+ //Save function
+ $scope.save = function() {
+ if ($scope.stepNum ==1) {
+ updateDefinitionData();
+ }
+ };
+
+ //Next function
+ $scope.next = function(){
+ if ($scope.stepNum ==1) {
+ updateDefinitionData();
+ }
+ $scope.stepNum = $scope.stepNum +1;
+ $scope.activeTabsId = $scope.gTabs[$scope.stepNum-1].id;
+ };
+
+ //Previous function
+ $scope.previous = function(){
+ $scope.stepNum = $scope.stepNum -1;
+ $scope.activeTabsId = $scope.gTabs[$scope.stepNum-1].id;
+
+ };
+
+ $scope.$on('RefreshInsession', function(event) {
+ $scope.isEdit = true;
+ $scope.reportId = -1;
+ $scope.getDefinitionById(-1);
+ });
+
+ $scope.$on('RefreshFormField', function(event) {
+ raptorReportFactory.getFormFieldList().then(function(data){
+ $scope.formFieldData = data;
+ },function(error){
+ $log.error("raptorReportFactory: get formfields failed.");
+ });
+ });
+
+ $scope.$on('RefreshColumnList', function(event) {
+ raptorReportFactory.getColumnList().then(function(data){
+ $scope.colTableRowData = data;
+ },function(error){
+ $log.error("raptorReportFactory: get column list failed.");
+ });
+ });
+
+ $scope.getAllProjects = function(){
+ $http({
+ method: 'GET',
+ url: 'get_projects'
+ }).then(function successCallback(response) {
+ var projectLists = response.data;
+ $scope.allProjects = projectLists;
+ });
+ }
+
+ // getAllProjects();
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/drools-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/drools-controller.js
new file mode 100644
index 00000000..1d4659e3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/drools-controller.js
@@ -0,0 +1,53 @@
+appDS2.controller('droolsController', function($scope, $modal, $routeParams, DroolsService, modalService) {
+ $scope.tableDate=[];
+ $scope.resultsString = "";
+ $scope.postDroolsBean={
+ droolsFile:'',
+ className:'',
+ selectedRules:''
+ };
+ $scope.filenameFromUrl = $routeParams.filename;
+ if($scope.filenameFromUrl!='' && $scope.filenameFromUrl!='0')
+ $scope.postDroolsBean.droolsFile = $scope.filenameFromUrl
+ $scope.execute = function(postDroolsBean) {
+ if($scope.postDroolsBean.droolsFile=='' ||$scope.postDroolsBean.className=='' || $scope.postDroolsBean.selectedRules=='' ){
+ modalService.errorPopUp ("Required fields cannot be empty");
+ return;
+ }
+ var uuu = "post_drools/execute";
+ var postData={postDroolsBean:postDroolsBean};
+ DroolsService.executeDrools(postData).then(function(data){
+ $scope.resultsString=data.resultsString;
+ modalService.successPopUp($scope.resultsString);
+ },function(error){
+ modalService.errorPopUp (error);
+ });
+ };
+});
+
+appDS2.controller('droolsListController', function($scope, $modal, DroolsService, modalService) {
+ $scope.tableDate=[];
+ $scope.resultsString = "";
+ $scope.postDroolsBean="";
+
+ $scope.getDroolsList = function(){
+ DroolsService.getDroolsList().then(function(data){
+ var j = data;
+ $scope.tableData = JSON.parse(j.data);
+ $scope.buildTable();
+ },function(error){
+ modalService.errorPopUp (error);
+ });
+ }
+
+ $scope.buildTable = function(){
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ }
+
+});
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js
new file mode 100644
index 00000000..ab88aed9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js
@@ -0,0 +1,15 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+
+ //.when('/notebook-frame/:id/:key/:value',{
+ //.when('/notebook-frame/:nid/:qprms',{
+ /*.when('/notebook-frame',{
+ templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
+ controller: 'notebookFrameController'
+ })*/
+
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-viz.html',
+ controller: 'notebookFrameController'
+ });
+}) \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebook-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebook-controller.js
new file mode 100644
index 00000000..c32cdd39
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebook-controller.js
@@ -0,0 +1,170 @@
+
+appDS2.controller('nbookController', ['$scope', '$location','$window','$http', function ($scope,$location,$window,$http) {
+
+ $scope.keyValueList = [{}];
+ //console.log('onload nbookController');
+ $scope.submitParameters = function() {
+
+ $scope.iframevisibility = false;
+ console.log('Inside nbook invoke save');
+
+ $scope.postData = {};
+
+ $scope.additionalqueryParams = {};
+
+ //Use this if there is only one 1 query param key value pair
+ $scope.additionalqueryParams.paramKey = $scope.qparamKey;
+ $scope.additionalqueryParams.paramVal = $scope.qparamVal;
+
+
+ // console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
+ //console.log('$scope.notebookvalue',$scope.notebookvalue);
+
+
+ //$scope.postData['notebookid'] = 'a06a9cf14211012e221bf842c168849d';
+ //$scope.postData['param1'] = 'p1';
+ //$scope.postData['param2'] = 'p2';
+
+ //console.log('Report Schedule object', $scope.reportScheduleObject);
+
+
+ /* if ($window.location.search.substr($window.location.search.indexOf("=")+1)) {
+ $scope.queryParams = $window.location.search;
+
+ if ($window.location.search.indexOf("&")!=-1) {
+ $scope.notebookparam = $window.location.search.substring($window.location.search.indexOf("?")+1,$window.location.search.indexOf("&"));
+ $scope.additionalqueryParams = JSON.parse('{"' + decodeURI($scope.queryParams.substr($scope.queryParams.indexOf("&")+1).replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}');
+ console.log('Additional parameters present');
+ }
+ else {
+ $scope.notebookparam = $window.location.search.substr($window.location.search.indexOf("?")+1);
+ console.log('Additional parameters absent');
+ }
+ console.log('add parameters',$scope.additionalqueryParams);
+ // $scope.notebookid = $scope.notebookparam.substring(0,$scope.notebookparam.indexOf("="));
+ $scope.notebookvalue = $scope.notebookparam.substr($scope.notebookparam.indexOf("=")+1);
+ $scope.postData = $window.location.search.substr($window.location.search.indexOf("=")+1);
+ console.log('Notebook value present ',$scope.notebookvalue);
+ }
+ else {
+ $scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
+ console.log('Notebook value absent ',$scope.notebookvalue);
+ }*/
+
+ // $http.get("notebook.htm#/notebook-frame", {params : {"a" : "b"}})
+
+ /* $http.get("app/fusion/notebook-integration/scripts/view-models/notebook-frame.html", {params : {"a" : "b"}})
+ .then(function(response) {
+ console.log("Got response from http get ");
+ // window.open ('notebook.htm#/notebook-frame','_self',false);
+ }); */
+
+ // $location.search(1, $scope.additionalqueryParams);
+// }
+ //console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
+// $scope.invokeSaveNotebook() = function() {
+ // window.open ('notebook.htm#/notebook-frame/1/2/3','_self',false);
+
+ //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue;
+ //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+encodeURIComponent(JSON.stringify($scope.additionalqueryParams));
+ // var testurl = 'notebook.htm#/notebook-frame/' + $scope.notebookvalue + '/' + encodeURIComponent(JSON.stringify($scope.additionalqueryParams));
+
+ // console.log('$scope.keyValueList',$scope.keyValueList);
+
+ /*for (var obj in $scope.keyValueList) {
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
+ console.log('property',obj[prop]);
+ //console.log("prop: " + prop.qk + " value: " + obj[prop.qk]);
+ }
+ }
+ }*/
+
+ //console.log('$scope.keyValueList.length',$scope.keyValueList.length);
+
+ var qryStr = '';
+ for(var i = 0; i < $scope.keyValueList.length; i++) {
+ var obj = $scope.keyValueList[i];
+ //console.log('obj.qK',obj.qK);
+ if (obj.qK != undefined && obj.qV != undefined) {
+ //console.log('Inside qk defined');
+ if (qryStr!='')
+ qryStr = qryStr+'&'+obj.qK+'='+obj.qV;
+ else
+ qryStr = obj.qK+'='+obj.qV;
+
+ }
+
+ }
+ //console.log('qryStr',qryStr);
+
+
+
+ //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&k1='+$scope.additionalqueryParams.paramKey+'&v1='+$scope.additionalqueryParams.paramVal;
+
+ // var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+$scope.additionalqueryParams.paramKey+'='+$scope.additionalqueryParams.paramVal;
+
+ var queryurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+qryStr;
+
+ // var testurl = 'notebook.htm#/notebook-frame';
+
+ window.open (queryurl,'_self',false);
+
+
+ // var w = window.open ('notebook.htm#/notebook-frame','_self',false);
+ // w.nid = $scope.notebookvalue;
+
+
+ // $http.post('rNotebookFE/authCr', $scope.postData).success(function(data, status) {
+ /* $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
+ console.log('Data Sent', data);
+ console.log('Status ', status);
+
+
+
+ // iframe.name = "my_iframe";
+
+ // $scope.ifr = "<div><iframe src='http://www.w3schools.com'/></div>"
+
+ // var url = "https://rcloud.research.att.com";
+ // document.getElementById('itestfr').src = data;
+ // window.open ('notebook.htm#/notebook-frame/1/2/3','_self',false);
+ // $scope.iframevisibility = true;
+ // document.getElementById('itestfr').src = data;
+
+
+ })*/
+
+
+ }
+
+ $scope.addKeyValuePairs = function (kv) {
+
+
+ if ($scope.keyValueList.length < 9) {
+ $scope.keyValueList.push({
+
+ });
+ // alert($scope.reportRunJson.rangeAxisList.length);
+ // console.log('$scope.keyValueList',$scope.keyValueList);
+
+ } else {
+ //document.getElementById("addbtn").disabled = true;
+ // $scope.btnactive = false;
+ document.getElementById("addbtn")["disabled"] = true;
+ //document.getElementById("addbtn")["style.background-color"] = "#FFFF00";
+
+ //$('#addbtn').btn('type') = "disabled";
+ }
+ }
+
+ $scope.removeKeyValuePairs = function (index) {
+ $scope.keyValueList.splice(index, 1);
+ if ($scope.keyValueList.length == 8) {
+ document.getElementById("addbtn")["disabled"] = false;
+ }
+ //console.log($scope.hardCodeReport.rangeAxisList)
+ }
+
+}]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js
new file mode 100644
index 00000000..9522611c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js
@@ -0,0 +1,85 @@
+/*app.
+controller('notebookFrameController', ['$scope', '$location','$window','$http', function ($scope,$location,$window,$http) {
+
+ $scope.invokeSaveNotebook() = function() {
+
+
+ // $http.post('rNotebookFE/authCr', $scope.postData).success(function(data, status) {
+ $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
+ console.log('Data Sent', data);
+ console.log('Status ', status);
+
+
+
+ // iframe.name = "my_iframe";
+
+ // $scope.ifr = "<div><iframe src='http://www.w3schools.com'/></div>"
+
+ // var url = "https://rcloud.research.att.com";
+ // document.getElementById('itestfr').src = data;
+ window.open ('notebook.htm#/notebook-frame','_self',false);
+ // $scope.iframevisibility = true;
+ // document.getElementById('itestfr').src = data;
+
+
+ })
+
+
+ }
+
+}]);*/
+appDS2.controller('notebookFrameController', function ($scope,$location,$window,$http,$routeParams) {
+
+ //alert($location.search(1, $scope.additionalqueryParams));
+ //var nid = $routeParams.nid;
+ //var qprms = $routeParams.qprms;
+ //var value = $routeParams.value;
+ //console.log('check id ');
+ var nid = $window.location.search.substr($window.location.search.indexOf("=")+1);
+ //console.log('nid',nid);
+ //console.log('qprms',qprms);
+ //$scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
+ $scope.additionalqueryParams={};
+ if ($window.location.search.substr($window.location.search.indexOf("=")+1)) {
+ $scope.queryParams = $window.location.search;
+ //console.log('$window.location.search',$window.location.search.substring(0, $window.location.search.length-1));
+ //if ($window.location.search.indexOf("&")!=-1) {
+ if($window.location.search.substring(0, $window.location.search.length-1).indexOf("&")!=-1) {
+ $scope.notebookparam = $window.location.search.substring($window.location.search.indexOf("?")+1,$window.location.search.indexOf("&"));
+ $scope.additionalqueryParams = JSON.parse('{"' + decodeURI($scope.queryParams.substr($scope.queryParams.indexOf("&")+1).replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}');
+ //console.log('Additional parameters present');
+ }
+ else {
+ $scope.notebookparam1 = $window.location.search.substr($window.location.search.indexOf("?")+1);
+ $scope.notebookparam = $scope.notebookparam1.substring(0, $scope.notebookparam1.length - 1);
+ //console.log('Additional parameters absent');
+ }
+ //console.log('add parameters',$scope.additionalqueryParams);
+ // $scope.notebookid = $scope.notebookparam.substring(0,$scope.notebookparam.indexOf("="));
+ $scope.notebookvalue = $scope.notebookparam.substr($scope.notebookparam.indexOf("=")+1);
+ // $scope.notebookvalue = $scope.notebookvalue1.substring(0, $scope.notebookvalue1.length - 1);
+ //console.log('New VALL',$scope.notebookvalue);
+ //$scope.postData = $window.location.search.substr($window.location.search.indexOf("=")+1);
+ //console.log('Notebook value present ',$scope.notebookvalue);
+ }
+ else {
+ $scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
+ //console.log('Notebook value absent ',$scope.notebookvalue);
+ }
+
+
+
+/* $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
+ //console.log('Data received', data);
+ //console.log('Status ', status);
+ document.getElementById('itestframe').src = data;
+
+ })*/
+ $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}, transformResponse: [function (data) {
+ // Do whatever you want!
+ document.getElementById('itestframe').src = data;
+ return data;
+ }]})
+
+
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowApp.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowApp.js
new file mode 100644
index 00000000..a3496785
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowApp.js
@@ -0,0 +1,5 @@
+angular.module('att.abs.helper', []);
+angular.module('quantum', []);
+//angular.module('ui.bootstrap', []);
+appDS2=angular.module("workflowApp", ["ngRoute", 'ngMessages', 'ngCookies', 'b2b.att.tpls', 'ddh.att.tpls','ddh.att.dropdowns', 'ddh.att.switches', 'b2b.att.footer', 'b2b.att.header','gridster','ui.bootstrap']);
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowController.js
new file mode 100644
index 00000000..f18f00e9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowController.js
@@ -0,0 +1,513 @@
+
+
+appDS2.controller('workflowsControllerDS2', function($scope, $http, $log, $modal) {
+ $scope.viewPerPage = 5;
+ $scope.scrollViewsPerPage = 20;
+ $scope.currentPage = 2;
+ $scope.totalPage;
+ $scope.searchCategory = "";
+ $scope.searchString = "";
+ $scope.radio = {
+ value: ""
+ };
+
+
+ $scope.showModal = false;
+ $scope.toggleModal = function(){
+ $scope.showModal = !$scope.showModal;
+ };
+
+ $scope.workflow = {};
+ $scope.workflow.active = "true";
+
+ $scope.updateAllWorkflowStatus = function() {
+ angular.forEach($scope.workflows,function(value){
+ $scope.checkWorkflowStatus(value);
+ })
+ }
+
+ $scope.fetchWorkflowsList = function() {
+ $http.get('workflows/list').then(function(workflowList){
+ console.log('Got new list from server = ' + workflowList.data);
+ $scope.workflows = workflowList.data;
+ $scope.updateAllWorkflowStatus();
+ });
+ };
+
+ $scope.addNewWorkflow = function(newWorkflow) {
+ $http.post('workflows/addWorkflow/', JSON.stringify(newWorkflow)).success(function() {
+ $scope.fetchWorkflowsList();
+ });
+
+ $scope.workflow.name = '';
+
+ };
+
+ $scope.updateWorkflow = function (workflowToEdit) {
+ //workflowToEdit.active='true';
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html',
+ sizeClass: 'modal-small',
+ controller: ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {
+ $scope.workflow = workflowToEdit;
+ $scope.ok = function() {
+ if(
+ $scope.workflow.name== undefined|| $scope.workflow.name == null|| $scope.workflow.name == ""
+ ||$scope.workflow.workflowKey == undefined ||$scope.workflow.workflowKey==null||$scope.workflow.workflowKey==""
+ ||$scope.workflow.runLink==undefined||$scope.workflow.runLink==null||$scope.workflow.runLink==""
+
+ )
+ {
+ alert("please provide valid entries !");
+ }
+ else{
+
+ console.log('Updating existing workflow ... ' + JSON.stringify($scope.workflow));
+ $http.post('workflows/editWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
+ console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
+ $modalInstance.close($scope.workflow);
+ });
+ }
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ //End of inner controller
+ resolve: {
+ workflow: function() {
+ console.log('Passing ' + JSON.stringify($scope.workflow));
+ return $scope.workflow;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (editedWorkFlow) {
+ //Need to convert to proper date - later
+ delete editedWorkFlow.created;
+ delete editedWorkFlow.updated;
+
+ delete editedWorkFlow.createdBy;
+ delete editedWorkFlow.modifiedBy;
+
+ console.log('selected Item ' + JSON.stringify(editedWorkFlow));
+ $scope.$emit('workflowAdded', editedWorkFlow);
+
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };
+
+ $scope.reset = function(){
+ console.log("Resetting ....");
+ };
+
+ $scope.update = function(){
+ console.log("updating ....");
+ };
+
+ $scope.createWorkflow = function (modalSize) {
+
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html',
+ sizeClass: 'modal-small',
+ controller: ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {
+ $scope.workflow = {};
+ $scope.workflow.active = 'true';
+ $scope.ok = function() {
+ if($scope.workflow.name== undefined|| $scope.workflow.name == null|| $scope.workflow.name == ""
+ ||$scope.workflow.workflowKey == undefined ||$scope.workflow.workflowKey==null||$scope.workflow.workflowKey==""
+ ||$scope.workflow.runLink==undefined||$scope.workflow.runLink==null||$scope.workflow.runLink==""
+
+ )
+ {
+ alert("please provide valid entries !");
+ }
+ else{
+ console.log('Saving new workflow ... ' + JSON.stringify($scope.workflow));
+ $http.post('workflows/addWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
+ console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
+ $modalInstance.close($scope.workflow);
+ });
+ }
+ };
+/* console.log(size);*/
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }],
+ //End of inner controller
+ resolve: {
+ workflow: function() {
+ console.log('Passing ' + JSON.stringify($scope.workflow));
+ return $scope.workflow;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (newWorkflow) {
+ console.log('selected Item ' + JSON.stringify(newWorkflow));
+ $scope.$emit('workflowAdded', newWorkflow);
+
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };//End of createWorkflow function
+
+
+ $scope.removeWorkflow = function(workflowToRemove){
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-remove.html',
+ sizeClass: 'modal-small',
+ controller: ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {
+ $scope.workflowToRemove = workflowToRemove;
+ $scope.ok = function() {
+ console.log('Removing workflow ... ' + JSON.stringify($scope.workflowToRemove) + ' on client request.');
+ $http.post('workflows/removeWorkflow/', JSON.stringify($scope.workflowToRemove.id)).then(function(){
+ console.log('Workflow successfully removed !!!');
+ $modalInstance.close();
+ });
+ };
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+
+ $scope.scheduleWorkflow = function(workflowToSchedule){
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-schedule.html',
+
+ controller: ['$scope', '$modalInstance', '$http','dateFilter', function ($scope, $modalInstance, $http,dateFilter) {
+
+ $scope.workflowToSchedule = workflowToSchedule;
+ $scope.dt = new Date();
+ $scope.dt2 = new Date();
+ $scope.dateformat = 'MM/dd/yyyy',
+ $scope.datetimeformat = "hh:mm a";
+
+ $scope.recurrenceOptions =[{
+ index:0, value:'One-Time', title:'One-Time'
+ },{
+ index:1, value: 'Hourly',title:'Hourly'
+ },{
+ index:2, value: 'Daily',title:'Daily'
+ },{
+ index:3, value: 'Weekly',title:'Weekly'
+ }]
+ $scope.selectRecurrenceOpt = $scope.recurrenceOptions[0];
+
+ $scope.hours = [];
+ for (var i=0; i<24; i++){
+ var newObj={}
+ newObj.index = i;
+ newObj.value = ""+i;
+ newObj.title = ""+i;
+ $scope.hours.push(newObj);
+ }
+
+ $scope.minutes = [];
+ for (var i=0; i<60; i++){
+ var newObj={}
+ newObj.index = i;
+ newObj.value = ""+i;
+ newObj.title = ""+i;
+ $scope.minutes.push(newObj);
+ }
+
+ $scope.AMPMOptions =[
+ {
+ index:0, value:'AM', title:'AM'
+ },{
+ index:1, value: 'PM',title:'PM'
+ }]
+
+ $scope.selectFirstHour =$scope.hours[0];
+ $scope.selectFirstMinute =$scope.minutes[0];
+
+ $scope.selectLastHour =$scope.hours[0];
+ $scope.selectLastMinute =$scope.minutes[0];
+
+ $scope.selectStartAMPMOption=$scope.AMPMOptions[0];
+ $scope.selectLastAMPMOption=$scope.AMPMOptions[0];
+
+ var GenerateCronExpression = function(trigger_dt, RecurrenceOpt) {
+ var CRON_sec = trigger_dt.getSeconds();
+ var CRON_min = trigger_dt.getMinutes();
+ var CRON_hr = trigger_dt.getHours();
+ var CRON_date= trigger_dt.getDate();
+ var CRON_month = trigger_dt.toLocaleString('en-US', {month: 'short'}).toUpperCase();
+ var CRON_day = trigger_dt.toLocaleString('en-US', {weekday: 'short'}).toUpperCase();
+ var CRON_year = trigger_dt.getFullYear();
+ if (RecurrenceOpt ==="One-Time") {
+ CRON_day = '?'
+ } else {
+ if (RecurrenceOpt ==="Hourly") {
+ CRON_hr = '*';
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_day = '?'
+ CRON_year = '*'
+ } else if (RecurrenceOpt ==="Daily") {
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_day = '?'
+ CRON_year = '*'
+ } else if (RecurrenceOpt ==="Weekly") {
+ CRON_date = '*'
+ CRON_month = '*'
+ CRON_year = '*'
+ }
+ }
+
+ var CRON_Expression = [CRON_sec, CRON_min, CRON_hr, CRON_date, CRON_month, CRON_day, CRON_year];
+ return CRON_Expression.join(" ");
+ }
+
+ $scope.ok = function() {
+
+ // DateTime for the start time: it should be noted that the start time
+ // for a CRON job should be prior to the trigger time.
+ $scope.trigger_dt = new Date( $scope.dt.getFullYear() +
+ "-" + ("0"+($scope.dt.getMonth()+1)).slice(-2) +
+ "-" +("0"+ $scope.dt.getDate()).slice(-2) +
+ " " + ("0" + $scope.selectFirstHour.value).slice(-2) +
+ ":" +("0" + $scope.selectFirstMinute.value).slice(-2) +
+ ":00.0");
+
+ $scope.startDateTime_CRON = GenerateCronExpression($scope.trigger_dt, $scope.selectRecurrenceOpt.value)
+
+ //roll back the the start date time by 30 seconds (start time should be 30 seconds prior to trigger time)
+ dt_st = new Date($scope.trigger_dt - 30*1000)
+
+ startDateTime = dt_st.getFullYear() +
+ "-" + ("0"+(dt_st.getMonth()+1)).slice(-2) +
+ "-" +("0"+ dt_st.getDate()).slice(-2) +
+ " " + ("0" + dt_st.getHours()).slice(-2) +
+ ":" +("0" + dt_st.getMinutes()).slice(-2) +
+ ":" + ("0" + dt_st.getSeconds()).slice(-2) +".0";
+ $scope.startDateTime = startDateTime;
+
+ $scope.endDateTime = $scope.dt2.getFullYear() +
+ "-" + ("0"+($scope.dt2.getMonth()+1)).slice(-2) +
+ "-" +("0"+ $scope.dt2.getDate()).slice(-2) +
+ " " + ("0"+ $scope.selectLastHour.value).slice(-2) +
+ ":" +("0" + $scope.selectLastMinute.value).slice(-2) +
+ ":00.0"
+
+ $scope.WorkflowScheduleObject = {};
+ $scope.WorkflowScheduleObject['startDateTime_CRON'] = $scope.startDateTime_CRON;
+ $scope.WorkflowScheduleObject['startDateTime'] = $scope.startDateTime;
+ $scope.WorkflowScheduleObject['endDateTime'] = $scope.endDateTime;
+ $scope.WorkflowScheduleObject['workflowKey'] = $scope.workflowToSchedule.workflowKey;
+ $scope.WorkflowScheduleObject['recurrence'] = $scope.selectRecurrenceOpt.value;
+ $scope.WorkflowScheduleObject['workflow_arguments'] = "test";
+ $scope.WorkflowScheduleObject['workflow_server_url'] = $scope.workflowToSchedule.runLink;
+
+
+ TimeFromNowToStart = new Date($scope.startDateTime)-new Date()
+ TimeStartToEnd = new Date($scope.endDateTime)-new Date($scope.startDateTime)
+
+ if (TimeFromNowToStart<=0) {
+ console.log("invalid start time input")
+ alert("Please ensure the scheduled start date time is later than current time.")
+ return;
+ }
+ if (TimeStartToEnd<=0) {
+ console.log("invalid end time input")
+ alert("Please ensure the schduled end date time is later than the start time.")
+ return;
+ }
+ // if successful then save and close
+ $scope.saveCronJob($scope.WorkflowScheduleObject);
+ $modalInstance.close();
+
+ };
+
+ $scope.saveCronJob = function(cronJobData){
+
+ console.log('saving cron job data: ' + cronJobData);
+ var uuu = "workflows/saveCronJob.htm";
+ var postData={cronJobDataObj: cronJobData};
+ $http.post({
+
+ url : uuu,
+ //dataType: 'json', // data type expected from server
+ contentType: 'application/json',
+ data: JSON.stringify(postData), // data type sent to server
+ success : function(data){
+ $scope.$apply(function(){
+ //$scope.availableRoleFunctions=[];$scope.$apply();
+ // new // $scope.availableFnMenuItems=data.availableFnMenuItems;
+ }
+ );
+ //alert("Update Successful.") ;
+ //$scope.editRoleFunction = null;
+ // new /// $modalInstance.close({availableFnMenuItems:$scope.availableRoleFunctions});
+ },
+ error : function(data){
+ alert("Error while saving.");
+ }
+ });
+
+ };
+
+ $scope.cancel = function() {
+ console.log("cancel triggered")
+ $modalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+
+
+
+
+
+
+ $scope.previewWorkflow = function(workflowToPreview,modalSize){
+ var modalInstance = $modal.open({
+ animation: $scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-preview.html',
+ sizeClass: 'modal-medium',
+ controller: ['$scope', '$modalInstance', '$http', function ($scope, $modalInstance, $http) {
+ $scope.workflowToPreview = workflowToPreview;
+ console.log('previewWorkFlow invoked');
+ console.log($scope.workflowToPreview);
+
+ $scope.cancel = function() {
+ $modalInstance.dismiss();
+ };
+ }]
+ });
+
+ modalInstance.result.then(function () {
+ $scope.$emit('workflowRemoved');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+
+ };
+
+
+ /* change work flow status based on the boolean variable "suspendBool" which corresponds whether
+ * we would like to suspend or activate a workflow specified by key. */
+ $scope.changeWorkflowStatus = function(workflowToChangeStatus,suspendBool){
+ if (workflowToChangeStatus!==null) {
+ var statusUrl= workflowToChangeStatus.runLink+"/engine-rest/process-definition/key/"+workflowToChangeStatus.workflowKey
+ var suspendedUrl= statusUrl+"/suspended"
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.open('PUT', suspendedUrl, false);
+ xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
+ xmlHttp.onload = function() {
+ if (suspendBool) {
+ console.log("process definition is now suspended");
+ workflowToChangeStatus.active="false"
+ } else {
+ console.log("process definition is now activated");
+ workflowToChangeStatus.active="true"
+ }
+ };
+ xmlHttp.send(JSON.stringify({
+ "suspended" : suspendBool,
+ "includeProcessInstances" : true,
+ "executionDate" : "2013-11-21T10:49:45"
+ }));
+ }
+
+ };
+
+ $scope.activateWorkflow = function(workflowToActivate){
+ $scope.changeWorkflowStatus(workflowToActivate,false)
+
+ };
+
+ $scope.suspendWorkflow = function(workflowToActivate){
+ $scope.changeWorkflowStatus(workflowToActivate,true)
+ };
+
+ $scope.checkWorkflowStatus = function(workflow) {
+ if (workflow!==null) {
+ var statusUrl= workflow.runLink+"/engine-rest/process-definition/key/"+workflow.workflowKey
+ var xmlHttp3 = new XMLHttpRequest();
+ xmlHttp3.open('GET', statusUrl, true);
+ xmlHttp3.withCredentials = true;
+ xmlHttp3.send();
+ xmlHttp3.onreadystatechange = function() {
+ if (xmlHttp3.readyState == 4 && xmlHttp3.status == 200) {
+ // do something with the response in the variable data
+ var temp = JSON.parse(xmlHttp3.responseText)
+ if (temp.suspended == false){
+ console.log("Activated")
+ workflow.active="true"
+ } else {
+ console.log("Suspended")
+ workflow.active="false"
+ }
+ }
+ }
+ }
+ };
+
+ $scope.StartWorkflowInstance = function(workflowToStart){
+ if (workflowToStart!==null) {
+ var statusUrl= workflowToStart.runLink+"/engine-rest/process-definition/key/"+workflowToStart.workflowKey
+ var suspendedUrl= statusUrl+"/submit-form"
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.open('POST', suspendedUrl, false);
+ xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
+ xmlHttp.onload = function() {
+ };
+ xmlHttp.send(JSON.stringify({
+ "variables": {
+ "customerId": {"value":"asdasda","type":"String"},
+ "amount":{"value":"100","type":"String"}
+ }
+ }));
+ }
+
+ };
+
+
+ $scope.$on('workflowAdded', function(event, newWorkflow) {
+ console.log("New Workflow to be added in list scope " + JSON.stringify(newWorkflow));
+ //$scope.workflows.push(newWorkflow);
+ $scope.fetchWorkflowsList();
+ console.log('newly added workflow = ' + JSON.stringify(newWorkflow));
+ });
+
+ $scope.$on('workflowRemoved', function(event) {
+ $scope.fetchWorkflowsList();
+ });
+
+ $scope.fetchWorkflowsList();
+
+
+
+});
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowRouting.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowRouting.js
new file mode 100644
index 00000000..f6ffe8f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/ds2-workflows/workflowRouting.js
@@ -0,0 +1,8 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/all', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html',
+ controller: 'workflowsControllerDS2'
+ })
+});
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js
new file mode 100644
index 00000000..2b3663c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js
@@ -0,0 +1,339 @@
+var deletefn_menu_popupController = function ($scope,$modal, items,$modalInstance, $http){
+ $scope.fnMenuItem=items;
+ console.log("fnMenuItems",$scope.fnMenuItem);
+ var ModalInstanceCtrl = function ($scope, $modalInstance, items,AdminMenuService,$http,$modal) {
+ $scope.fnMenuItem=items;
+ $scope.save = function (data) {
+ $modalInstance.close(data);
+ };
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.deleteFun = function(data){
+ $modalInstance.close(data);
+ }
+ };
+ $scope.successPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+ $scope.successModelPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modalpopup.html',
+ controller: ModalInstanceCtrl,
+ //sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+ $scope.errorPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+ $scope.deleteMenuItem= function(fnMenuItem){
+ var uuu = "admin_fn_menu/removeMenuItem.htm";
+ var postData={fnMenuItem: fnMenuItem};
+ $http({
+ method :'POST',
+ url : uuu,
+ dataType: 'json',
+ contentType: 'application/json',
+ data: JSON.stringify(postData)
+
+ }).then(function(data){
+ $scope.successPopUp();
+ // $scope.$apply(function(){$scope.fnMenuItem=data.data.fnMenuItem;});
+ location.reload();
+ },function(data){
+ $scope.errorPopUp();
+ // console.log(data);
+ // modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
+ });
+ }/// examine the LeftMenuService
+}
+ var fn_menu_popupController = function ($scope, $modalInstance, message, $http){ /// examine the LeftMenuService
+
+ if(message.availableFnMenuItem==null)
+ $scope.label='Add New Menu Item'
+
+ else{
+ $scope.label='Edit Menu Item'
+ //$scope.disableParentId=true;
+ }
+
+ $scope.getParentData = function(){
+ var uuu = "admin_fn_menu/get_parent_list"
+ $http({
+ method : 'GET',
+ url : uuu,
+ dataType: 'json', // data type expected from server
+ contentType: 'application/json',
+ //data: JSON.stringify(postData), // data type sent to server
+
+ }).then(function(data){
+ //$scope.$apply(function(){
+ //$scope.availableRoleFunctions=[];$scope.$apply();
+ $scope.parentListSelectData=data.data; // data from server
+ menuItems = $scope.parentListSelectData;
+ var heirarchicalMenuItems = [];
+ var children = [];
+ for ( var i=0; i<menuItems.length; i++){
+ for(var j=0; j<menuItems.length; j++){
+ if(menuItems[j][2]==menuItems[i][0])
+ children.push(
+ {
+ menuId: menuItems[j][0],
+ label: menuItems[j][1]
+ }
+ );
+ }
+ if(children.length!=0){
+ heirarchicalMenuItems.push(
+ {
+
+ menuId: menuItems[i][0],
+ label: menuItems[i][1],
+ children: children.sort($scope.sortItems("label"))
+ }
+
+ );
+ }
+ children = [];
+
+ }
+ heirarchicalMenuItems.sort($scope.sortItems("label"));
+ $scope.childListSelectData = heirarchicalMenuItems;
+ //console.log(data);
+ //});
+ //$scope.editRoleFunction = null;
+ ///$modalInstance.close({functionCDselectData:$scope.functionCDselectData});
+ },function(data){
+ alert("Parent Data not available !");
+ });
+
+ };
+
+ $scope.sortItems = function(prop){
+ return function(a, b) {
+ if (a[prop] > b[prop]) {
+ return 1;
+ } else if (a[prop] < b[prop]) {
+ return -1;
+ }
+ return 0;
+ }
+
+ };
+
+ $scope.getParentLabel = function(parentId, parentListSelectData){
+ var element;
+ element = parentListSelectData[0];
+ for (var i=0; i<parentListSelectData.length; i++){
+
+ element = parentListSelectData[i];
+ if (element[0] == parentId)
+ return element[1];
+ else "---";
+ }
+ };
+
+
+ $scope.getFunctionCDselectData = function(){
+ var uuu = "admin_fn_menu/get_function_cd_list"
+ $http({
+ method : 'GET',
+ url : uuu,
+ dataType: 'json', // data type expected from server
+ contentType: 'application/json',
+ //data: JSON.stringify(postData), // data type sent to server
+
+ }).then(function(data){
+ //$scope.$apply(function(){
+ //$scope.availableRoleFunctions=[];$scope.$apply();
+ $scope.functionCDselectData=data.data;
+ //});
+ //alert("Update Successful.") ;
+ //$scope.editRoleFunction = null;
+ ///$modalInstance.close({functionCDselectData:$scope.functionCDselectData});
+ },function(data){
+ alert("Function Code Data not available !");
+ });
+
+ };
+
+ if(message.availableFnMenuItem){
+ $scope.addFnMenuItem = message.availableFnMenuItem;
+ } else {
+ $scope.addFnMenuItem = {};
+ }
+ $scope.addFnMenuItem.menuSetCode = "APP";
+
+ $scope.statusOptions = [
+ {index: 0, value: 'true', title: 'Y'},
+ {index: 1, value: 'false', title: 'N'}
+ ];
+ $scope.selectedValue = $scope.statusOptions[0];
+
+ $scope.separator = {
+ availableOptions:[
+ {value: 'true', name: 'Y'},
+ {value: 'false', name: 'N'}
+ ],
+
+ selectedOption: {value: 'true', name: 'Y'}
+
+ };
+
+
+ $scope.activeStatusOptions = [
+ {index: 0, value: 'true', title: 'Y'},
+ {index: 1, value: 'false', title: 'N'}
+ ];
+ $scope.activeSelectedValue = $scope.activeStatusOptions[0];
+
+ $scope.separatorStatusOptions = [
+ {index: 0, value: 'true', title: 'Y'},
+ {index: 1, value: 'false', title: 'N'}
+ ];
+ $scope.separatorSelectedValue = $scope.separatorStatusOptions[1];
+
+ $scope.active = {
+ availableOptions:[
+ {value: 'true', name: 'Y'},
+ {value: 'false', name: 'N'}
+ ],
+
+ selectedOption: {value: 'true', name: 'Y'}
+
+ };
+
+
+ $scope.updateFnMenu = function(availableFnMenuItem) {
+ // form validation
+ if( document.getElementById("popupAddMenuItemImageSrc").value == "" ) availableFnMenuItem.imageSrc = "N/A";
+ if( document.getElementById("popupAddMenuItemTarget").value == "" ) availableFnMenuItem.target = "N/A";
+ if( document.getElementById("popupAddMenuItemExternalUrl").value == "" ) availableFnMenuItem.externalUrl = "N/A";
+ if( document.getElementById("popupAddMenuItemQueryString").value == "" ) availableFnMenuItem.queryString = "N/A";
+ if( document.getElementById("popupAddMenuItemServlet").value == "" ) availableFnMenuItem.servlet = "N/A";
+
+ validationRule = /^\S{3,}$/;
+ var selectedFunction = document.getElementById("repeatSelect");
+ var selectedFunctionText = selectedFunction.options[selectedFunction.selectedIndex].text;
+ if(
+ (document.getElementById("popupAddMenuItemLabel").value == "" || document.getElementById("popupAddMenuItemLabel").value.replace(" ", "").length == 0 ) ||//!validationRule.test(document.getElementById("popupAddMenuItemLabel").value)) ||
+ $scope.addFnMenuItem.parentIdAsString == "" ||
+ document.getElementById("popupAddMenuItemAction").value == "" ||
+ selectedFunctionText == "" ||
+ document.getElementById("popupAddMenuItemSortOrder").value == "" ||
+ document.getElementById("popupAddMenuItemMenuSetCode").value == ""
+ )
+ {
+ alert("please provide valid entries !");
+ }
+
+ else{
+ var uuu = "admin_fn_menu/updateFnMenu.htm";
+ availableFnMenuItem.parentId=parseFloat($scope.addFnMenuItem.parentIdAsString);
+ availableFnMenuItem.active=('true'==$scope.addFnMenuItem.activeAsString);
+ availableFnMenuItem.separator=('true'==$scope.addFnMenuItem.separatorAsString);
+
+
+ var postData={availableFnMenuItem: availableFnMenuItem};
+
+ $http({
+ method :'POST',
+ url : uuu,
+ //dataType: 'json', // data type expected from server
+ contentType: 'application/json',
+ data: JSON.stringify(postData), // data type sent to server
+ }).then(function(data){
+ //$scope.$apply(function(){
+ $scope.availableFnMenuItems=data.availableFnMenuItems;
+ //});
+
+ $modalInstance.close({availableFnMenuItems:$scope.availableRoleFunctions}),function(data){
+ alert("Error while saving.");
+ }
+ },function(data){
+ console.log("Error",data);
+ });
+ $scope.getLeftMenuItems(); // get left menu items again from database
+
+ };
+
+ $scope.getLeftMenuItems = function() {
+ return $http.get('get_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ var leftChildData=[];
+ var leftParentData=[];
+ var leftMenuItems = [];
+ var j = response;
+ try{
+ if(j && j !== "null" && j!== "undefined"){
+ leftParentData = JSON.parse(j.data);
+ leftChildData = JSON.parse(j.data2);
+ }else{
+ throw "Get Left Menu respsone is not an object/is empty";
+ }
+ try{
+ var leftChildItemList = leftChildData;
+ var pageUrl = window.location.href.split('/')[window.location.href.split('/').length-1];
+ var leftParentList = leftParentData;
+ for (var i = 0; i < leftParentList.length; i++) {
+ $scope.item = {
+ parentLabel : leftParentList[i].label,
+ parentAction : leftParentList[i].action,
+ parentImageSrc : leftParentList[i].imageSrc,
+ open:pageUrl==leftParentList[i].action?true:false,
+ childItemList : leftChildItemList[i]==null?'x':leftChildItemList[i]
+ }
+ leftMenuItems.push($scope.item);
+ };
+
+ $scope.leftMenuItems = leftMenuItems;
+
+ }catch(err){
+ console.log("error happened while trying to set left menu structure: "+err);
+ }
+ }catch (e) {
+ console.log("error happened while trying to get left menu items: "+e);
+ reloadPageOnce();
+ return;
+ }
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ };
+
+ $scope.close = function() {
+ $modalInstance.close();
+ };
+}
+ } \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-route.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-route.js
new file mode 100644
index 00000000..c82185c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-route.js
@@ -0,0 +1,19 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/profile/:profileId', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
+ controller: 'selfProfileController'
+ })
+ .when('/self_profile', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
+ controller: 'selfProfileController'
+ })
+ .when('/post_search', {
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/post.html',
+ controller: 'postController'
+ })
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html',
+ controller : "profileSearchCtrlDS2"
+ });
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-search-controller-DS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-search-controller-DS2.js
new file mode 100644
index 00000000..57e2e80b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/profile-search-controller-DS2.js
@@ -0,0 +1,64 @@
+appDS2.controller('profileSearchCtrlDS2', function($scope, $http,ProfileServiceDS2){
+ $scope.showInput = true;
+ $scope.totalPages1 = 5;
+ $scope.viewPerPage1 = 8;
+ $scope.currentPage1 = 1;
+ $scope.showLoader = false;
+
+ $scope.$watch('viewPerPage1', function(val) {
+ $scope.showLoader = true;
+ ProfileServiceDS2.getProfilePagination($scope.currentPage1, val).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData =JSON.parse($scope.data.profileList);
+ $scope.totalPages1 =JSON.parse($scope.data.totalPage);
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ $scope.showLoader = false;
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ });
+
+ $scope.customHandler = function(num) {
+ $scope.currentPage1 = num;
+ $scope.showLoader = true;
+ ProfileServiceDS2.getProfilePagination($scope.currentPage1,$scope.viewPerPage1).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData =JSON.parse($scope.data.profileList);
+ $scope.totalPages1 =JSON.parse($scope.data.totalPage);
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ $scope.showLoader = false;
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ };
+
+ $scope.editRow = function(profileId){
+ window.location = 'userProfile#/profile/' + profileId;
+ };
+
+ $scope.toggleProfileActive = function(rowData) {
+ modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?",
+ function(){
+ $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){});
+ },
+ function(){
+ rowData.active=!rowData.active;
+ })
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/sampleProfileController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/sampleProfileController.js
new file mode 100644
index 00000000..0f02e46f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/sampleProfileController.js
@@ -0,0 +1,22 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .when('/profile/:profileId', {
+ templateUrl: 'app/fusion/scripts/view-models/profile-page/profile_detail.html',
+ controller: 'profileController'
+ })
+ .when('/post_search', {
+ templateUrl: 'app/fusion/scripts/view-models/profile-page/post_search.html',
+ controller: 'postSearchCtrl'
+ })
+ .when('/ase', {
+ templateUrl: 'app/fusion/ase/index.html'
+ })
+ .when('/self_profile', {
+ templateUrl: 'app/fusion/scripts/view-models/profile-page/self_profile.html',
+ controller: 'selfProfileController'
+ })
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/DS2-profile-page/profile_searchDS2.html',
+ controller : "profileSearchCtrlDS2"
+ });
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/usage-list-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/usage-list-controller.js
new file mode 100644
index 00000000..ab229714
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/usage-list-controller.js
@@ -0,0 +1,39 @@
+appDS2.controller('usageListControllerDS2', function ($scope,$interval,$http,$modal, AdminService){
+ AdminService.getUsageList().then(function(data){
+
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.users =$scope.data;
+ //$scope.resetMenu();
+
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ $scope.successPopUp = function () {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return '';
+ }
+ }
+ });
+ };
+
+ $scope.removeSession = function(sessionId) {
+
+ $http.get("usage_list/removeSession?deleteSessionId="+sessionId).success(function(response){
+ $scope.users=response;
+ $scope.successPopUp();
+ });
+/* modalService.popupConfirmWin("Confirm","You are about to expel this user from the application. All of their unsaved data will be lost. Do you want to continue?",
+ function(){
+ $http.get("usage_list/removeSession?deleteSessionId="+sessionId).success(function(response){$scope.users=response;});
+ })*/
+
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-controller.js
new file mode 100644
index 00000000..b2b3a43b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-controller.js
@@ -0,0 +1,408 @@
+appDS2
+ .directive(
+ 'integer',
+ function() {
+ return {
+ require : 'ngModel',
+ link : function(scope, ele, attr, ctrl) {
+ ctrl.$parsers.unshift(function(viewValue) {
+ if (viewValue === '' || viewValue === null
+ || typeof viewValue === 'undefined') {
+ return null;
+ }
+ return parseInt(viewValue, 10);
+ });
+ }
+ };
+ })
+
+ .controller(
+ 'welcomeController',
+ function($scope, $interval, $http, $modal, $log, ManifestService) {
+
+ $scope.testMsg = "Welcome Page1";
+ $scope.gridsterOpts = {
+ columns : 6, // the width of the grid, in columns
+ pushing : true, // whether to push other items out of
+ // the way on move or resize
+ floating : true, // whether to automatically float
+ // items up so they stack (you can
+ // temporarily disable if you are
+ // adding unsorted items with
+ // ng-repeat)
+ width : 'auto', // can be an integer or 'auto'. 'auto'
+ // scales gridster to be the full width
+ // of its containing element
+ colWidth : 'auto', // can be an integer or 'auto'.
+ // 'auto' uses the pixel width of
+ // the element divided by 'columns'
+ rowHeight : 60, // can be an integer or 'match'. Match
+ // uses the colWidth, giving you square
+ // widgets.
+ margins : [ 10, 10 ], // the pixel distance between
+ // each widget
+ outerMargin : true, // whether margins apply to outer
+ // edges of the grid
+ swapping : true,
+ draggable : {
+ enabled : true, // whether dragging items is
+ // supported
+ stop : function(event, uiWidget, $element) {
+ $scope.setCookie();
+ } // optional callback fired when item is finished
+ // dragging
+ }
+
+ };
+
+ /*
+ * $scope.gridsterOpts = { columns: 6, width: 'auto',
+ * colWidth: '230', rowHeight: '120', margins: [10, 10],
+ * outerMargin: true, pushing: true, floating: true,
+ * swapping: true };
+ */
+
+ $scope.toggleMinMax = function(index, tileName) {
+ if (tileName == '') {
+ $scope.standardItems[index].max = !$scope.standardItems[index].max;
+ if ($scope.standardItems[index].max)
+ $scope.standardItems[index].sizeY = $scope.standardItems[index].maxHeight;
+ else
+ $scope.standardItems[index].sizeY = 0;
+ } else {
+ $scope.tileTemp = $scope.$eval(tileName);
+ var tileMax = $parse(tileName + '.max');
+ tileMax.assign($scope, !$scope.$eval(tileName).max);
+ var tileSizeY = $parse(tileName + '.sizeY');
+ if ($scope.tileTemp.max)
+ tileSizeY.assign($scope,
+ $scope.tileTemp.maxHeight);
+ else
+ tileSizeY.assign($scope, 0);
+ }
+ };
+
+ // These map directly to gridsterItem options
+ // IMPORTANT: Items should be placed in the grid in the
+ // order in which
+ // they should appear.
+ // In most cases the sorting should be by row ASC, col ASC
+ $scope.standardItems = [
+ {
+ sizeX : 2,
+ sizeY : 8,
+ maxHeight : 8,
+ row : 0,
+ col : 0,
+ headerText : 'Dashboard',
+ max : false
+
+ },
+ {
+ sizeX : 2,
+ sizeY : 5,
+ maxHeight : 5,
+ row : 0,
+ col : 2,
+ headerText : 'Donut Chart',
+ max : false
+
+ },/*
+ * { sizeX : 1, sizeY : 5, maxHeight : 5, row :
+ * 0, col : 2, headerText : 'Area Chart', max :
+ * false },
+ */
+ {
+ sizeX : 2,
+ sizeY : 5,
+ maxHeight : 5,
+ row : 8,
+ col : 0,
+ headerText : 'Pie Chart',
+ max : false
+ },
+ /*
+ * { sizeX : 1, sizeY : 5, maxHeight : 5, row : 8,
+ * col : 1, headerText : 'Line Chart', max : false },
+ */
+ {
+ sizeX : 2,
+ sizeY : 5,
+ maxHeight : 5,
+ row : 8,
+ col : 4,
+ headerText : 'Gauges',
+ max : false
+ },
+ {
+ sizeX : 2,
+ sizeY : 8,
+ maxHeight : 8,
+ row : 16,
+ col : 0,
+ headerText : 'Traffic distribution by day of week',
+ max : false
+ },
+ {
+ sizeX : 2,
+ sizeY : 8,
+ maxHeight : 8,
+ row : 16,
+ col : 2,
+ headerText : 'Busy hour traffic analysis by day of week',
+ max : false
+ }, {
+ sizeX : 2,
+ sizeY : 6,
+ maxHeight : 7,
+ row : 24,
+ col : 4,
+ headerText : 'Additional Samples',
+ max : false
+ }, {
+ sizeX : 2,
+ sizeY : 8,
+ maxHeight : 8,
+ row : 24,
+ col : 2,
+ headerText : 'Sticky Notes',
+ max : false
+ }, {
+ sizeX : 6,
+ sizeY : 10,
+ maxHeight : 10,
+ row : 32,
+ col : 0,
+ headerText : 'Service Configuration',
+ max : false
+ } ];
+
+ /*
+ * $.each($scope.standardItems, function(i, a) {
+ * $scope.toggleMinMax(i, ''); });
+ */
+ var counter = 0;
+ angular.forEach($scope.standardItems, function(i, a) {
+ $scope.toggleMinMax(counter, '');
+ counter = counter + 1;
+ });
+
+ $scope.activeTabId = 'Monday';
+ // for generic tabs
+
+ $scope.selectedTrafficDay = [ {
+ title : 'Mon',
+ url : '#Monday'
+ }, {
+ title : 'Tue',
+ url : '#Tuesday'
+ }, {
+ title : 'Wed',
+ url : '#Wednesday'
+ }, {
+ title : 'Thu',
+ url : '#Thursday'
+ }, {
+ title : 'Fri',
+ url : '#Friday'
+ }, {
+ title : 'Sat',
+ url : '#Saturday'
+ }, {
+ title : 'Sun',
+ url : '#Sunday'
+ } ];
+
+ $scope.currentSelectedDayTab = '#Monday';
+
+ $scope.onClickTab1 = function(Daytab) {
+ $scope.currentSelectedDayTab = Daytab.url;
+ }
+
+ $scope.isActiveTab1 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedDayTab;
+ }
+
+ $scope.gTabs = [ {
+ title : 'Monday',
+ id : 'Monday',
+ url : '#Monday',
+ selected : true
+ }, {
+ title : 'Tuesday',
+ id : 'Tuesday',
+ url : '#Tuesday'
+ }, {
+ title : 'Wednesday',
+ id : 'Wednesday',
+ url : '#Wednesday'
+ }, {
+ title : 'Thursday',
+ id : 'Thursday',
+ url : '#Thursday'
+ }, {
+ title : 'Friday',
+ id : 'Friday',
+ url : '#Friday'
+ }, {
+ title : 'Saturday',
+ id : 'Saturday',
+ url : '#Saturday'
+ }, {
+ title : 'Sunday',
+ id : 'Sunday',
+ url : '#Sunday'
+ } ];
+
+ $scope.BusyHourTraffic = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ url : '#Incoming'
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ url : '#BHNational'
+ }
+
+ ];
+
+ $scope.currentSelectedBusyHourTraffic = '#Incoming';
+
+ $scope.onClickTab2 = function(TrafficTab) {
+ $scope.currentSelectedBusyHourTraffic = TrafficTab.url;
+ }
+
+ $scope.isActiveTab2 = function(tabUrl) {
+ return tabUrl == $scope.currentSelectedBusyHourTraffic;
+ }
+
+ $scope.activeTabId2 = 'Incoming';
+ // for generic tabs
+ $scope.gTabs2 = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ id : 'Incoming',
+ url : '#Incoming',
+ selected : true
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ id : 'Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ id : 'Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ id : 'Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ id : 'BHNational',
+ url : '#BHNational'
+ } ];
+
+ $scope.activeTabId3 = 'Incoming';
+ // for generic tabs
+ $scope.gTabs3 = [ {
+ title : 'BH SNRC DLSTX - Incoming',
+ id : 'Incoming',
+ url : '#Incoming',
+ selected : true
+ }, {
+ title : 'BH SNRC DLSTX - Outgoing',
+ id : 'Outgoing',
+ url : '#Outgoing'
+ }, {
+ title : 'BH National - Default',
+ id : 'Default',
+ url : '#Default'
+ }, {
+ title : 'BH National - Priority',
+ id : 'Priority',
+ url : '#Priority'
+ }, {
+ title : 'BH National',
+ id : 'BHNational',
+ url : '#BHNational'
+ } ];
+
+ /*
+ * $scope.$watch('activeTabId', function(newVal) {
+ * alert(newval); $('#'+newval).show(); }, true);
+ */
+
+ $scope.toggleEastToWest = function() {
+ $("#toggle").toggle('slide');
+ if ($("#leftIcon").is(":visible")) {
+ $("#rightIcon").show();
+ $("#leftIcon").hide();
+ } else if ($("#rightIcon").is(":visible")) {
+ $("#rightIcon").hide();
+ $("#leftIcon").show();
+ }
+ };
+
+ $scope.group1 = {
+ open : true
+ };
+ $scope.group2 = {
+ open : true
+ };
+ $scope.group3 = {
+ open : true
+ };
+ $scope.group4 = {
+ open : true
+ };
+ $scope.group5 = {
+ open : true
+ };
+ $scope.group6 = {
+ open : true
+ };
+ $scope.group7 = {
+ open : true
+ };
+ $scope.group71 = {
+ open : true
+ };
+ $scope.group8 = {
+ open : true
+ };
+ $scope.group9 = {
+ open : true
+ };
+ $scope.group10 = {
+ open : true
+ };
+ $scope.group11 = {
+ open : true
+ };
+ $scope.group12 = {
+ open : false
+ };
+
+ // Fetch manifest info
+ $scope.manifest = {};
+ ManifestService.getManifest()
+ .then(function(jsonObj) {
+ // $log.debug("welcome-controller: getManifest returned " + JSON.stringify(jsonObj));
+ if (jsonObj.error) {
+ $log.error('welcome-controller: failed to get manifest: ' + JSON.stringify(jsonObj));
+ }
+ else {
+ $scope.manifest=jsonObj;
+ }
+ },function(error){
+ $log.error("welcome-controller: getManifest failed: " + error);
+ });
+
+
+ });
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-route.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-route.js
new file mode 100644
index 00000000..8f4b1fdb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-controllers/welcome-route.js
@@ -0,0 +1,7 @@
+appDS2.config(function($routeProvider) {
+ $routeProvider
+ .otherwise({
+ templateUrl: 'app/fusion/scripts/DS2-view-models/welcome-content.html',
+ controller : "welcomeController"
+ });
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js
new file mode 100644
index 00000000..64da0a49
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js
@@ -0,0 +1,64 @@
+appDS2.directive('leftMenuEcomp', function () {
+ /*
+ * Custom version of b2b-left-navigation directive:
+ * 1. Make parent menu a link if no child menus.
+ * 2. Add unique IDs to all items.
+ * 3. Hide icon if no child menus.
+ * 4. Arrow toggle button.
+ * 5. Adjust the page on collapse/expand.
+ */
+ return {
+ restrict: 'EA',
+ templateUrl: 'app/fusion/scripts/DS2-view-models/b2b-leftnav-ext.html',
+ scope: {
+ menuData: '='
+ },
+ link: function (scope, element, attrs, ctrl) {
+ scope.idx = -1;
+ scope.itemIdx = -1;
+ scope.navIdx = -1;
+ /*assuming menu is expanded when page loads*/
+ scope.showmenu=true;
+ scope.leftMenuClass= "";
+ scope.leftMenuArrowClass="leftmenu-arrow-expand";
+ scope.toggleNav = function (val,link,menuStatus) {
+
+ if(!menuStatus){
+ scope.toggleDrawer(menuStatus);
+ return;
+ }
+ if(link!=null && link!=''){
+ location.href = link;
+ return;
+ }
+ if (val === scope.idx) {
+ scope.idx = -1;
+ return;
+ }
+ scope.idx = val;
+ };
+ scope.toggleDrawer = function(menuStatus){
+ scope.idx=-1; /*hide the sub menus*/
+ if(menuStatus){
+ //Collapse Menu
+ scope.showmenu=false;
+ scope.leftMenuClass = "left-menu-collapsed";
+ scope.leftMenuArrowClass="leftmenu-arrow-collapse";
+ document.getElementById('page-content').style.marginLeft = "50px";
+ }else{
+ //Expand Menu
+ scope.showmenu=true;
+ scope.leftMenuClass = "";
+ scope.leftMenuArrowClass="leftmenu-arrow-expand";
+ document.getElementById('page-content').style.marginLeft = "250px";
+ }
+
+ };
+ scope.liveLink = function (evt, val1, val2) {
+ scope.itemIdx = val1;
+ scope.navIdx = val2;
+ evt.stopPropagation();
+ };
+ }
+ };
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2Header.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2Header.js
new file mode 100644
index 00000000..87ae7a31
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2Header.js
@@ -0,0 +1,152 @@
+ appDS2.directive('ds2Header', function () {
+ return {
+ restrict: 'A', //This menas that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
+ replace: false,
+ templateUrl: "app/fusion/scripts/DS2-view-models/ds2Header.html",
+ controller: ['$scope', '$filter','$http','$timeout', '$log','UserInfoServiceDS2', '$window', '$cookies', "$cookieStore", function ($scope, $filter, $http, $timeout, $log,UserInfoServiceDS2, $window, $cookies, $cookieStore) {
+ // copy from existing DS1
+ /*Define fields*/
+ $scope.userName;
+ $scope.userFirstName;
+ /*$scope.redirectUrl;
+ $scope.contactUsUrl;
+ $scope.getAccessUrl;
+ $scope.childData=[];
+ $scope.parentData=[];
+ $scope.menuItems = [];
+ $scope.loadMenufail=false;
+ $scope.megaMenuDataObject=[];
+ $scope.activeClickSubMenu = {
+ x: ''
+ };
+ $scope.activeClickMenu = {
+ x: ''
+ };
+ $scope.favoritesMenuItems = [];
+ $scope.favoriteItemsCount = 0;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ $scope.favoritesWindow = false;*/
+
+ //DS2 code
+ $scope.tabItems = [
+ {
+ 'title': 'ECOMP'
+ },
+ {
+ 'title': 'Help',
+ 'subitems': [{
+ 'value': 'Contact Us'
+
+ }, {
+ 'value': 'Get Access'
+ },
+ ]},
+ ];
+
+ $scope.userProfile = {};
+ $scope.showInfo = false;
+ $scope.showProfile = function () {
+ $scope.showInfo = !$scope.showInfo;
+ };
+ $scope.loginOptions1 = [
+ {value: '', text: 'Log In..'},
+ {value: '1', text: 'Premier'},
+ {value: '2', text: 'Wifi Services'},
+ {value: '3', text: 'Cloud Solutions'}
+ ];
+ $scope.loginVal = {};
+ $scope.loginVal.value = $scope.loginOptions1[0].value;
+
+ $scope.clickLogin = function () {
+ $scope.openDropdown = !$scope.openDropdown;
+ };
+ $scope.skipNavigation = function () {
+ var element = angular.element(document.querySelector('li.last'))[0];
+ element.children[0].focus();
+ };
+
+ /***************functions**************/
+ /*Put user info into fields*/
+
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if(typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null){
+ $scope.userFirstName = userInfo.USER_FIRST_NAME;
+ }
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoServiceDS2.getFunctionalMenuStaticDetailSession()
+ .then(function (res) {
+ $scope.contactUsUrl=res.contactUsLink;
+ $scope.userName = res.userName;
+ $scope.userFirstName = res.firstName;
+ $scope.redirectUrl = res.portalUrl;
+ $scope.getAccessUrl = res.getAccessUrl;
+ $scope.userProfile.fullName = res.userName;
+ $scope.userProfile.email = res.email;
+ });
+ }
+
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
+ $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
+ if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
+ $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
+ if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
+ $scope.userProfile.email = userInfo.USER_EMAIL;
+ }
+ }
+
+ /*getting user info from shared context*/
+ $scope.getUserName=function() {
+ var promise = UserInfoServiceDS2.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.warn('DS2HeaderCtlr::getUserName: failed to get info from shared context');
+ $scope.getUserNameFromSession();
+ }else{
+ // $log.info('Received User information from shared context',res);
+ var resData = res;
+ $scope.inputUserInfo(resData);
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ }
+ },
+ function(err) {
+ console.log('error');
+ }
+ );
+ };
+
+ $scope.adjustHeader=function() {
+ $scope.showHeader = ($cookieStore.get("show_app_header") == undefined ? true : $cookies.show_app_header);
+ if($scope.showHeader == true) {
+ $scope.drawer_margin_top = 70;
+ $scope.drawer_custom_top = 54;
+ $scope.toggle_drawer_top = 55;
+ }
+ else {
+
+ $scope.drawer_margin_top = 60;
+ $scope.drawer_custom_top = 0;
+ $scope.toggle_drawer_top = 10;
+ }
+
+ }
+
+ /*call the get user info function*/
+ try{
+ $scope.getUserName();
+ $scope.adjustHeader();
+
+ }catch(err){
+ $log.info('Error while getting User information',err);
+ }
+ }]
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2LeftMenu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2LeftMenu.js
new file mode 100644
index 00000000..8174c586
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/ds2LeftMenu.js
@@ -0,0 +1,89 @@
+appDS2.directive('ds2Menu', function () {
+ return {
+ restrict: 'A', //This means that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
+ replace: false,
+ templateUrl: "app/fusion/scripts/DS2-view-models/ds2Left_menu.html",
+ controller: ['$scope','$filter','$http','$timeout','$cookies','LeftMenuServiceDS2', function ($scope, $filter, $http, $timeout, $cookies, LeftMenuServiceDS2) {
+ $scope.menuData = [];
+ $scope.leftChildData = [];
+ $scope.leftParentData = [];
+ $scope.leftMenuItems = [];
+ $scope.app_name = "";
+ $scope.app_name_full = "";
+ LeftMenuServiceDS2.getLeftMenu().then(function(response){
+ var j = response;
+ if (j && j !== "null" && j !== "undefined"){
+ $scope.leftParentData = JSON.parse(j.data);
+ $scope.leftChildData = JSON.parse(j.data2);
+ } else {
+ console.log("ds2Menu::controller: unexpected getLeftMenu response");
+ return;
+ }
+ var leftParentList = $scope.leftParentData;
+ var leftChildItemList = $scope.leftChildData;
+ for (var i = 0; i < leftParentList.length; i++) {
+ var parentItem = {};
+ parentItem.name = leftParentList[i].label;
+ parentItem.imageSrc = leftParentList[i].imageSrc;
+ // Add link to items with no subitems
+ if (leftChildItemList[i].length == 0)
+ parentItem.href = leftParentList[i].action;
+ parentItem.menuItems = [];
+ for (var j = 0; j < leftChildItemList[i].length; j++) {
+ if (leftChildItemList[i][j].label != null && leftChildItemList[i][j].label.length > 0) {
+ var childItem = {};
+ childItem.name = leftChildItemList[i][j].label;
+ childItem.href = leftChildItemList[i][j].action;
+ parentItem.menuItems.push(childItem)
+ }
+ }
+ $scope.menuData.push(parentItem);
+ }
+ },function(error){
+ console.log("ds2Menu::controller: getLeftMenu failed", error);
+ });
+
+ LeftMenuServiceDS2.getAppName().then(function(response){
+ var j = response;
+ try {
+ if (j && j !== "null" && j!== "undefined"){
+ $scope.app_name_full = j.data;
+ var processed_app_name = j.data;
+ var n = processed_app_name.length;
+ if (n > 15) {
+ n = 15;
+ }
+ $scope.app_name = processed_app_name.substr(0, n);
+ } else {
+ throw "Get app_name respsone is not an object/is empty";
+ }
+ } catch (e) {
+ console.log("error happened while trying to get app name "+e);
+ return;
+ }
+ },function(error){
+ console.log("error happened while calling getAppName "+error);
+ });
+
+ $scope.adjustHeader=function() {
+ $scope.showHeader = ($cookies.show_app_header == undefined ? true : $cookies.show_app_header);
+ if ($scope.showHeader == true) {
+ $scope.drawer_margin_top = 50;
+ $scope.drawer_custom_top = 54;
+ $scope.toggle_drawer_top = 55;
+ }
+ else {
+ $scope.drawer_margin_top = 40;
+ $scope.drawer_custom_top = 0;
+ $scope.toggle_drawer_top = 10;
+ }
+ }; // adjustHeader
+
+
+ $scope.adjustHeader();
+ $scope.drawerOpen = true;
+
+
+ }]
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/footer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/footer.js
new file mode 100644
index 00000000..e11c3a05
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-directives/footer.js
@@ -0,0 +1,27 @@
+appDS2.directive('ds2Footer', function () {
+ return {
+ restrict: 'A', //This means that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
+ replace: false,
+ templateUrl: "app/fusion/scripts/DS2-view-models/footer.html",
+ controller: ['$scope', '$filter','ManifestService', function ($scope, $filter,ManifestService) {
+ $scope.build_number = '';
+ ManifestService.getManifest().then(function(response){
+ $scope.build_number=response['Build-Number'];
+ });
+ }]
+ }
+});
+
+/*Analytics for all the pages*/
+$(function() {
+ portalHook();
+ function portalHook() {
+ var script = document.createElement('script');
+ script.src = "api/v2/analytics"
+ script.async = true;
+ script.onload = function() {
+ runAnalytics(); //runAnaltics() has endpoint in epsdk-fw library.
+ }
+ document.head.appendChild(script);
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/error_modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/error_modal.html
new file mode 100644
index 00000000..895abaf9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/error_modal.html
@@ -0,0 +1,19 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Error!</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content">
+ <p style="word-wrap: break-word;">{{msg}}</p>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="$dismiss('cancel')">OK</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modal.html
new file mode 100644
index 00000000..2584216c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modal.html
@@ -0,0 +1,20 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Success!</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 40px;">
+ Your change has been saved! {{msg.text}}
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="$dismiss('cancel')">OK</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modalpopup.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modalpopup.html
new file mode 100644
index 00000000..e0a168ab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-modal/success_modalpopup.html
@@ -0,0 +1,20 @@
+<div style="overflow-y:auto">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Success!</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 600px;overflow-y: auto;">
+ <pre> {{msg.text}}</pre>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="$dismiss('cancel')">OK</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminMenuService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminMenuService.js
new file mode 100644
index 00000000..86bf5cd4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminMenuService.js
@@ -0,0 +1,129 @@
+appDS2.factory('AdminMenuService', function ($http, $q) {
+ return {
+ getRoleFunctionList: function() {
+ return $http.get('get_role_functions')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+getFnMenuItems: function(){
+
+ return $http.get('admin_fn_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ getCollaborateList: function() {
+ return $http.get('get_collaborate_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+/* saveRoleFunctionList: function(roleData) {
+ return $http.post('role_function_list/saveRoleFunction',{
+ roleData
+ })
+ .then(function(response) {
+ console.log(response);
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ console.log('eror');
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }*/
+ saveRoleFunctionList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_function_list/saveRoleFunction",
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ delRoleFunctionList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_function_list/removeRoleFunction",
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ clearAdminRegions: function() {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/clearAll",
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+
+
+
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminService.js
new file mode 100644
index 00000000..e92ebaf3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/adminService.js
@@ -0,0 +1,453 @@
+appDS2.factory('AdminService', function ($http, $q) {
+ return {
+ getRole: function(roleId) {
+ return $http.get('get_role?role_id=' + roleId)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ getCollaborateList: function() {
+ return $http.get('get_collaborate_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getCacheRegions: function() {
+ return $http.get('get_regions')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getUsageList: function() {
+ return $http.get('get_usage_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+getFnMenuItems: function(){
+
+ return $http.get('admin_fn_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+/* saveRoleFunctionList: function(roleData) {
+ return $http.post('role_function_list/saveRoleFunction',{
+ roleData
+ })
+ .then(function(response) {
+ console.log(response);
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ console.log('eror');
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }*/
+
+ getRoleFunctionList: function() {
+ return $http.get('get_role_functions')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ saveRoleFunctionList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_function_list/saveRoleFunction",
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ addRoleFunctionList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_function_list/addRoleFunction",
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ delRoleFunctionList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_function_list/removeRoleFunction",
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ clearAdminRegions: function() {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/clearAll"
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ showRegionDetails: function(cacheName) {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/showRegionDetails?cacheName="+cacheName,
+ contentType: 'application/json',
+ }).then(function(response) {
+ //var parsed = JSON.stringify(response);
+ var responseData = JSON.stringify(response);
+ if (response.status == 200) {
+ return response;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ console.log('response'+response);
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ clearRegionFunction: function(cacheName) {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/clearRegion?cacheName="+cacheName
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ clearItemnFunction: function(cacheName, key) {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/clearItem?keyName="+key+"&cacheName="+cacheName
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ showItemDetails: function(cacheName, key) {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/showItemDetails?keyName="+key+"&cacheName="+cacheName
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ //role deletion
+ delRoleList: function(roleData) {
+ return $http({
+ method: "POST",
+ url: "role_list/removeRole",
+ data:JSON.stringify({role:roleData})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // activate role
+ activateRole: function(selected,availableRole){
+ return $http({
+ method: "POST",
+ url: "role_list/toggleRole",
+ data:JSON.stringify({role:availableRole})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // save Role
+ saveRole: function(role,roleId){
+ return $http({
+ method: "POST",
+ url: "role/saveRole.htm?role_id="+roleId,
+ data:JSON.stringify(role)
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // activate RoleFun Remove
+ confirmRoleFunRemove: function(selected,availableRole,id){
+ return $http({
+ method: "POST",
+ url: "role/removeRoleFunction.htm?role_id=" + id,
+ data:JSON.stringify({roleFunction:availableRole})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // activate RoleFun Add
+ confirmRoleFunAdd: function(selected,availableRole,id){
+ return $http({
+ method: "POST",
+ url: "role/addRoleFunction.htm?role_id=" + id,
+ data:JSON.stringify({roleFunction:availableRole})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // activate RoleChild Remove
+ confirmRoleChildRemove: function(selected,availableRole,id){
+ return $http({
+ method: "POST",
+ url: "role/removeChildRole.htm?role_id=" + roleId,
+ data:JSON.stringify({roleFunction:availableRole})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ // activate RoleChild Add
+ confirmRoleChildAdd: function(selected,availableRole,id){
+ return $http({
+ method: "POST",
+ url: "role/addChildRole.htm?role_id=" + roleId,
+ data:JSON.stringify({roleFunction:availableRole})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ //Role Function delete for associated role on Edit Role
+ removeRoleFunction: function(roleFunction,roleId){
+ return $http({
+ method: "POST",
+ url: "role/removeRoleFunction.htm?role_id=" + roleId,
+ data:JSON.stringify({roleFunction:roleFunction})
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+
+/* toggleProfileActiveFunction: function(profileId) {
+ return $http({
+ method: "GET",
+ url: "jcs_admin/clearRegion?cacheName="+cacheName
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }*/
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-modal/modalService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-modal/modalService.js
new file mode 100644
index 00000000..061d1ba2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-modal/modalService.js
@@ -0,0 +1,38 @@
+angular.module("modalServices",[]).service('modalService', ['$modal', function ($modal) {
+ var ModalInstanceCtrl = function ($scope, $modalInstance, items,$rootScope) {
+ $scope.roleFun=items;
+ $scope.msg=items;
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+ };
+ this.errorPopUp = function (msg) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/error_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ return msg;
+ }
+ }
+ });
+ };
+ this.successPopUp = function (msg) {
+ var modalInstance = $modal.open({
+ templateUrl: 'app/fusion/scripts/DS2-modal/success_modal.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-small',
+ resolve: {
+ items: function () {
+ var message = {
+ title: '',
+ text: msg
+ };
+ return message;
+ }
+ }
+ });
+ };
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-profile/selfProfileService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-profile/selfProfileService.js
new file mode 100644
index 00000000..bc18f2c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-profile/selfProfileService.js
@@ -0,0 +1,114 @@
+appDS2.factory('SelfProfileService', function ($http, $q) {
+ return {
+ getProfileDetail: function(profileId) {
+ return $http({
+ method: "GET",
+ url: "get_profile?profile_id=" + profileId,
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getSelfProfileDetail: function() {
+ return $http.get('get_self_profile')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ addRole: function(roleData,profileId) {
+ return $http({
+ method: "POST",
+ url: "profile/addNewRole?profile_id=" + profileId,
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ deRole: function(roleData,profileId) {
+ return $http({
+ method: "POST",
+ url: "profile/removeRole?profile_id=" + profileId,
+ data:roleData
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ saveProfile: function(data,profileId) {
+ return $http({
+ method: "POST",
+ url: "profile/saveProfile?profile_id=" + profileId,
+ data:data
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ removeRole: function(data,profileId) {
+ return $http({
+ method: "POST",
+ url: "profile/removeRole?profile_id=" + profileId,
+ data:data
+
+ }).then(function(response) {
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/raptorReportFactory.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/raptorReportFactory.js
new file mode 100644
index 00000000..06324d39
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/raptorReportFactory.js
@@ -0,0 +1,331 @@
+appDS2.factory('raptorReportFactory', function($http, $q) {
+ return {
+ getDefinitionByReportId: function(reportId) {
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/Def/"+reportId,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getDefinitionByReportId did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getDefinitionByReportId callback failed");
+ });
+ },
+ getDefinitionInSession: function() {
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/Def/InSession",
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getDefinitionInSession did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getDefinitionInSession callback failed");
+ });
+ },
+
+ createNewDefinition: function() {
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/Def/Create",
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: createNewDefinition did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: createNewDefinition callback failed");
+ });
+ },
+ updateDefinition: function(updatedJson,isUpdate) {
+ return $http({
+ method: "POST",
+ url: (isUpdate?("report/wizard/save_def_tab_data/"+updatedJson.reportId):"report/wizard/save_def_tab_data/Create"),
+ data: updatedJson
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: updateDefinition did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: updateDefinition callback failed");
+ });
+ },
+ saveNewDefinition: function(updatedJson) {
+ return $http({
+ method: "POST",
+ url: "report/wizard/save_def_tab_data/InSession",
+ data: updatedJson
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: saveNewDefinition did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: saveNewDefinition callback failed");
+ });
+ },
+ getSqlInSession: function() {
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/Sql/InSession",
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getSqlInSession did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getSqlInSession callback failed");
+ });
+ },
+ testRunSQL: function(queryJSON) {
+ return $http({
+ method: "POST",
+ url: "report/wizard/retrieve_data/true",
+ data: queryJSON
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: testRunSQL did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: testRunSQL callback failed");
+ });
+ },
+ formFieldVerifySQL: function(queryJSON) {
+ return $http({
+ method: "POST",
+ url: "report/wizard/retrieve_data/false",
+ data: queryJSON
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: formFieldVerifySQL did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: formFieldVerifySQL callback failed");
+ });
+ },
+ getColumnList: function() {
+ return $http({
+ method: "GET",
+ url: "report/wizard/list_columns",
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getColumnList did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getColumnList callback failed");
+ });
+ },
+
+ getColumnEditInfoById: function(columnId){
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/ColEdit/"+columnId,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getColumnEditInfoById did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getColumnEditInfoById callback failed");
+ });
+ },
+ saveColumnEditInfo: function(updatedColumnJson){
+ return $http({
+ method: "POST",
+ url: "report/wizard/save_col_tab_data",
+ data: updatedColumnJson
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: saveColumnEditInfo did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: saveColumnEditInfo callback failed");
+ });
+ },
+ postImportXml: function(importXMLJSON){
+ return $http({
+ method: "POST",
+ url: "report/wizard/import_report",
+ data: importXMLJSON
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: importXml did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: importXml callback failed");
+ });
+ },
+ copyReportById: function(reportId) {
+ return $http({
+ method: "GET",
+ url: "report/wizard/copy_report/"+reportId,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: copyReportById did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: copyReportById callback failed");
+ });
+ },
+ saveFormFieldEditInfo: function(updatedFormFieldJson){
+ return $http({
+ method: "POST",
+ url: "report/wizard/save_formfield_tab_data",
+ data: updatedFormFieldJson
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: saveFormFieldEditInfo did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: saveFormFieldEditInfo callback failed");
+ });
+ },
+ getFormFieldList: function() {
+ return $http({
+ method: "GET",
+ url: "report/wizard/list_formfields",
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getFormFieldList did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getFormFieldList callback failed");
+ });
+ },
+ getFormFieldEditInfoById: function(fieldId){
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/FormEdit/"+fieldId,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getColumnEditInfoById did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getFormFieldEditInfoById callback failed");
+ });
+ },
+ deleteFormFieldById: function(fieldId){
+ return $http({
+ method: "GET",
+ url: "report/wizard/retrieve_tab_wise_data/FormEdit/delete/"+fieldId,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: deleteFormFieldById did not return a valid JSON object.");
+ }
+ return response.data;
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: deleteFormFieldById callback failed");
+ });
+ },
+ getColumns: function() {
+ return $http
+ .get('raptor.htm?action=report.search.execute&r_page=0')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getColumns did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getColumns callback failed");
+ });
+ },
+
+ getSearchData : function() {
+ return $http
+ .get('raptor.htm?action=report.search.execute&r_page=0')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getSearchData did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getSearchData callback failed");
+ });
+ },
+
+ getSearchDataAtPage : function(pageSearchParameter) {
+ return $http
+ .get('raptor.htm?action=report.search.execute&r_page='+pageSearchParameter)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getSearchDataAtPage did not return a valid JSON object.");
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getSearchDataAtPage callback failed");
+ });
+ },
+ getReportDeleteStatus : function(deleteUrl) {
+ return $http.get(deleteUrl).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject("raptorReportFactory: getReportDeleteStatus did not return a valid JSON object.");
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject("raptorReportFactory: getReportDeleteStatus callback failed");
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/stepFormFactory.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/stepFormFactory.js
new file mode 100644
index 00000000..5c711425
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-raptor-report/stepFormFactory.js
@@ -0,0 +1,198 @@
+(function(){
+ var stepFormFactory = function($http, $compile, $q, $log) {
+
+ var factory = {};
+
+ factory.getStepJSONData = function(jsonSrcName) {
+ $http({
+ method: "GET",
+ url: jsonSrcName,
+ }).then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+
+
+ factory.renderColumnForm = function(scope) {
+
+ }
+ factory.renderForm = function(jsonSrcName, elem, scope) {
+ let defer = $q.defer();
+ var divStepForm = document.getElementById('stepView');
+ var textStyle = "width:300px"
+ var textAreaStyle = "width:300px"
+ if(divStepForm)
+ while(divStepForm && divStepForm.firstChild){
+ divStepForm.removeChild(divStepForm.firstChild);
+ }
+ $http({
+ method: 'GET',
+ url: jsonSrcName
+ }).then(function successCallback(response) {
+ // this callback will be called asynchronously
+ // when the response is available
+ if (typeof response.data === 'object') {
+ var json = response.data;
+ var step = json.step;
+ var div =d3.select(elem[0]);
+ var modelNameDict = {};
+
+ div.append("h1").attr({"class":"font-color:blue"}).text(json.content.title);
+ div.append("div").html(json.content.contentHtml);
+ var sections = json.content.sections;
+ sections.forEach(function(d, i) {
+ var sectionDiv = div.append("div");
+ sectionDiv.attr("id", "section_"+i);
+ if(d.title != "finalButton")
+ sectionDiv.append("h4").text(d.title);
+ var proj_id_hidden = sectionDiv.append("input");
+ proj_id_hidden.attr({"type":"hidden", "value":"", "name": "proj_id", "ng-model":"proj_id", "style": "" });
+
+ var elements = d.elements;
+ var buttons = d.buttons;
+ var elementTable ;
+ if(elements) {
+ elements.forEach(function(element, elementIndex) {
+
+ var elementBody ;
+ if(elementIndex == 0) {
+ elementTable = sectionDiv.append("table").attr({"border":"0", "cellpadding":"4", "cellspacing":"0"});
+ elementBody = elementTable.append("tbody");
+ } else {
+ elementBody = elementTable = sectionDiv.select("tbody");
+ }
+ if(element.input == 'hidden') {
+
+ } else {
+ var tr = elementBody.append("tr")
+ var cellWidthStyle = {"width":"50%"}
+
+ if (!(element.spanOverTwoColumns)){
+ var td = tr.append("td").attr({"width":"30%","class":"tdLeftColumn"});
+ if (element.input=="checkboxGroup") {
+ td = td.attr({"rowspan":element.checkboxes.length})
+ }
+ td.text(element.displayName);
+ var cellWidthStyle = {"width":"500px;"}
+ }
+ td = tr.append("td").attr(cellWidthStyle);
+ var model_name_appendix='';
+ if (element.name in modelNameDict) {
+ modelNameDict[element.name]=modelNameDict[element.name]+1
+ model_name_appendix ='_'+modelNameDict[element.name]
+ } else {
+ modelNameDict[element.name]=0
+ }
+ if(element.input == 'text') {
+ var inp_text = td.append("input");
+ inp_text.attr({"type":"text", "value":element.defaultValue, "name": element.name, "ng-model":element.name+model_name_appendix, "style": (element.style?element.style:textStyle) });
+ }
+ else if(element.input === 'checkbox') {
+ var temptd= td.append("label").attr({"class":"checkbox"});
+ var temptd2= temptd.append("input").attr({"type":"checkbox", "ng-model": element.checkbox.value});
+ var temptd3= temptd.append("i").attr({"class":"skin"})
+ var temptd3= temptd.append("span").text(element.checkbox.text);
+
+ } else if (element.input === 'radio') {
+ element.options.forEach(function(d,i) {
+ td.append("input").attr({"type":"radio", "id":element.name+"_"+d.id, "ng-model":element.name+model_name_appendix, "name": element.name, "value": d.id});
+ td.append("label").text(d.name);
+ })
+ } else if (element.input === 'checkboxGroup') {
+
+ element.checkboxes.forEach(function(d,i) {
+ if (i==0) {
+ var temptd= td.append("label").attr({"class":"checkbox"});
+ var temptd2= temptd.append("input").attr({"type":"checkbox", "ng-model": d.value});
+ var temptd3= temptd.append("i").attr({"class":"skin"})
+ var temptd3= temptd.append("span").text(d.text);
+ } else {
+ var tr = elementBody.append("tr")
+ td = tr.append("td").attr({"width":"50%"});
+ var temptd= td.append("label").attr({"class":"checkbox"});
+ var temptd2= temptd.append("input").attr({"type":"checkbox", "ng-model": d.value});
+ var temptd3= temptd.append("i").attr({"class":"skin"})
+ var temptd3= temptd.append("span").text(d.text);
+ }
+ })
+ } else if (element.input === 'textarea') {
+ td.append("textarea").attr({"rows":"4", "cols":"50", "ng-model":element.name+model_name_appendix, "name": element.name, "style": (element.style?element.style:textAreaStyle)});
+ }
+ else if (element.input === 'select') {
+ var select = td.append("select");
+ // need to store options into element name;
+ select
+ .attr({"name": element.name,"b2b-dropdown":"","ng-model":element.ngModelName,"style":"width:300px"})
+ .attr("placeholder-text","Select");
+
+
+ /* var data = ["Option 1", "Option 2", "Option 3"]*/
+ var options = select
+ .selectAll('option')
+ .data(element.options).enter()
+ .append('option').attr("value", function(d) {return d.value})
+ .attr("b2b-dropdown-list","")
+ .text(function (d) { return d.text; })
+ ;
+ } else if (element.input === 'tabletext') {
+ var colArray = element.columns.split(',');
+ var table = td.append("table");
+ table.attr("border", "1");
+
+ colArray.forEach(function(d) {
+ table.append("th").text(d);
+ })
+
+ }
+ }
+ })
+ if (buttons) {
+ buttons.forEach(function(button, buttonIndex) {
+ sectionDiv.append("input").attr({"type":"button", "value": button.text, "ng-click":button.ngFunction,"class":"btn btn-alt btn-small"});
+ })
+ sectionDiv.append("br");
+ }
+ }
+ else { //if elements
+ if((json.step != "1")&&(!json.hideBackButton))
+ sectionDiv.append("input").attr({"type":"button", "value": "Back", "ng-click":"previous()","class":"btn btn-alt btn-small"});
+ if((d.title == "finalButton")&(!json.hideSaveButton))
+ sectionDiv.append("input").attr({"type":"button", "value": "Save", "ng-click":"save()", "class":"btn btn-alt btn-small"});
+ if(!json.last_step)
+ sectionDiv.append("input").attr({"type":"button", "value": "Next", "ng-click":"next()", "class":"btn btn-alt btn-small"});
+
+ }
+ })
+ elem.html(div.html());
+ elem.removeAttr("step-form");
+ $compile(elem.contents())(scope);
+ defer.resolve();
+ } else {
+ $log.error
+ return $q.reject(response.data);
+ }
+ }, function errorCallback(response) {
+ // called asynchronously if an error occurs
+ // or server returns response with an error status.
+ $log.error("reponse data is not a valid JSON object");
+ defer.resolve();
+ });
+ //}
+ return defer.promise;
+ };
+
+ return factory;
+ };
+
+ stepFormFactory.$inject = ['$http', '$compile', '$q'];
+
+ appDS2.factory('stepFormFactory', stepFormFactory);
+
+}())
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-sample-page/droolsService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-sample-page/droolsService.js
new file mode 100644
index 00000000..90c3d00d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/ds2-sample-page/droolsService.js
@@ -0,0 +1,53 @@
+appDS2.factory('DroolsService', function ($http, $q) {
+ return {
+ getDroolsList: function() {
+ return $http.get('getDrools')
+ .then(function(response) {
+ console.log(response);
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getDroolDetails: function(selectedFile) {
+ return $http.get('getDroolDetails'+'?selectedFile=' + selectedFile )
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ executeDrools:function(droolsData) {
+ return $http({
+ method: "POST",
+ url: "post_drools/execute",
+ data:droolsData
+ }).then(function(response) {
+ console.log(response);
+ if (response.status == 200) {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ return response.data;
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/headerServiceDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/headerServiceDS2.js
new file mode 100644
index 00000000..92a99be0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/headerServiceDS2.js
@@ -0,0 +1,483 @@
+appDS2.directive('qHeader', function () {
+
+ return {
+ restrict: 'A', //This menas that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
+ replace: false,
+ templateUrl: "app/fusion/scripts/DS2-view-models/ds2Header.html",
+ controller: ['$scope', '$filter','$http','$timeout', '$log','UserInfoServiceDS2', '$window', '$cookies', function ($scope, $filter, $http, $timeout, $log,UserInfoServiceDS2, $window, $cookies) {
+
+ //alert("in header service")
+ /*Define fields*/
+ $scope.userName;
+ $scope.userFirstName;
+ $scope.redirectUrl;
+ $scope.contactUsUrl;
+ $scope.getAccessUrl;
+ $scope.childData=[];
+ $scope.parentData=[];
+ $scope.menuItems = [];
+ $scope.loadMenufail=false;
+ $scope.megaMenuDataObject=[];
+ $scope.activeClickSubMenu = {
+ x: ''
+ };
+ $scope.activeClickMenu = {
+ x: ''
+ };
+ $scope.favoritesMenuItems = [];
+ $scope.favoriteItemsCount = 0;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ $scope.favoritesWindow = false;
+
+ /* Menu Structure
+ var menuStructureConvert = function(menuItems) {
+ console.log(menuItems);
+ $scope.megaMenuDataObjectTemp =
+ [
+ {
+ text: "ECOMP",
+ children: menuItems
+ },
+ {
+ text: "Help",
+ children: [
+ {
+ text:"Contact Us",
+ url:$scope.contactUsUrl
+ },
+ {
+ text:"Get Access",
+ url:$scope.getAccessUrl
+ }]
+ }
+ ];
+ return $scope.megaMenuDataObjectTemp;
+ };
+ */
+ /***************functions**************/
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if(typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null){
+ $scope.userFirstName = userInfo.USER_FIRST_NAME;
+ }
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoServiceDS2.getFunctionalMenuStaticDetailSession()
+ .then(function (res) {
+ $scope.contactUsUrl=res.contactUsLink;
+ $scope.userName = res.userName;
+ $scope.userFirstName = res.firstName;
+ $scope.redirectUrl = res.portalUrl;
+ $scope.getAccessUrl = res.getAccessUrl;
+ });
+ }
+ $scope.getTopMenuStaticInfo=function() {
+ var promise = UserInfoServiceDS2.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('failed getting static User information');
+ $scope.getUserNameFromSession();
+ }else{
+ $log.info('Received static User information');
+
+ var resData = res;
+ console.log(resData);
+ $scope.inputUserInfo(resData);
+ $scope.userName = $scope.firstName+ ' '+ $scope.lastName;
+ }
+ },
+ function(err) {
+ $log.info('failed getting static User information');
+ }
+ );
+ }
+
+ $scope.returnToPortal=function(){
+ window.location.href = $scope.redirectUrl;
+ }
+
+ var unflatten = function( array, parent, tree ){
+ tree = typeof tree !== 'undefined' ? tree : [];
+ parent = typeof parent !== 'undefined' ? parent : { menuId: null };
+ var children = _.filter( array, function(child){ return child.parentMenuId == parent.menuId; });
+ if( !_.isEmpty( children ) ){
+ if( parent.menuId === null ){
+ tree = children;
+ }else{
+ parent['children'] = children
+ }
+ _.each( children, function( child ){ unflatten( array, child ) } );
+ }
+ return tree;
+ }
+
+ $scope.getMenu=function() {
+ $scope.getTopMenuStaticInfo();
+ $http({
+ method: "GET",
+ url: 'get_functional_menu',
+// TIMEOUT USED FOR LOCAL TESTING ONLY
+// timeout: 100
+ }).success(function (response) {
+
+ if (response == '101: Timeout') {
+ $log.debug('Timeout attempting to get_functional_menu');
+ $scope.megaMenuDataObject = menuStructureConvert("");
+// $scope.createErrorMenu();
+ //$scope.loadMenufail=true;
+ } else {
+ if(typeof response != 'undefined' && response.length!=0 && typeof response[0] != 'undefined' && typeof response[0].error!="undefined"){
+ $log.debug('Timeout attempting to get_functional_menu');
+ $scope.menuItems = unflatten( response);
+ $scope.megaMenuDataObject = menuStructureConvert($scope.menuItems);
+// $scope.createErrorMenu();
+ //$scope.loadMenufail=true;
+ }else{
+ $scope.loadMenufail=false;
+ $scope.contactUsURL = response.contactUsLink;
+ $log.debug('functional_menu',response);
+ $scope.megaMenuDataObject = menuStructureConvert("");
+ }
+ }
+ }).error(function (response){
+ $scope.megaMenuDataObject = menuStructureConvert("");
+// $scope.createErrorMenu();
+ //$scope.loadMenufail=true;
+ $log.debug('REST API failed get_functional_menu...');
+ });
+
+ }
+
+ /*$scope.adjustHeader=function() {
+ $scope.showHeader = ($cookies.show_app_header == undefined ? true : $cookies.show_app_header);
+
+ if($scope.showHeader == true) {
+ $scope.drawer_margin_top = 70;
+ $scope.drawer_custom_top = 54;
+ $scope.toggle_drawer_top = 55;
+ }
+ else {
+
+ $scope.drawer_margin_top = 60;
+ $scope.drawer_custom_top = 0;
+ $scope.toggle_drawer_top = 10;
+ }
+
+ }*/
+
+ $scope.getMenu();
+ // $scope.adjustHeader();
+
+/* **************************************************************************/
+/* Logic for the favorite menus is here */
+
+ $scope.loadFavorites = function () {
+ $log.debug('loadFavorites has happened.');
+ if ($scope.favoritesMenuItems == '') {
+ $scope.generateFavoriteItems();
+ $log.debug('loadFavorites is calling generateFavoriteItems()');
+ } else {
+ $log.debug('loadFavorites is NOT calling generateFavoriteItems()');
+ }
+ }
+
+ $scope.goToUrl = function (item) {
+ $log.info("goToUrl called")
+ $log.info(item);
+
+ var url = item.url;
+ var restrictedApp = item.restrictedApp;
+ $log.debug('Restricted app status is: ' + restrictedApp);
+ if (!url) {
+ $log.info('No url found for this application, doing nothing..');
+ return;
+ }
+ if (restrictedApp) {
+ $window.open(url, '_blank');
+ } else {
+ $window.open(url, '_self');
+ }
+
+ }
+
+ $scope.submenuLevelAction = function(index, column) {
+ if ($scope.favoritesMenuItems == '') {
+ $scope.generateFavoriteItems();
+ $log.debug('submenuLevelAction is calling generateFavoriteItems()');
+ }
+ $log.debug('item hovered/clicked: ' + index + '; column = ' + column);
+ if (column == 2) { // 2 is Design
+ $scope.favoritesWindow = false;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+ if (index=='Favorites' && $scope.favoriteItemsCount != 0) {
+ $log.debug('Showing Favorites window');
+ $scope.favoritesWindow = true;
+ $scope.showFavorites = true;
+ $scope.emptyFavorites = false;
+ }
+ if (index=='Favorites' && $scope.favoriteItemsCount == 0) {
+ $log.debug('Hiding Favorites window in favor of No Favorites Window');
+ $scope.favoritesWindow = true;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = true;
+ }
+ if (column > 2) {
+ $scope.favoritesWindow = false;
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+ };
+
+ $scope.hideFavoritesWindow = function() {
+ $log.debug('$scope.hideFavoritesWindow has been called');
+ $scope.showFavorites = false;
+ $scope.emptyFavorites = false;
+ }
+
+ $scope.isUrlFavorite = function (menuId) {
+// $log.debug('array objects in menu favorites = ' + $scope.favoriteItemsCount + '; menuId=' + menuId);
+ var jsonMenu = JSON.stringify($scope.favoritesMenuItems);
+ var isMenuFavorite = jsonMenu.indexOf('menuId\":' + menuId);
+ if (isMenuFavorite==-1) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ $scope.generateFavoriteItems = function() {
+ $http({
+ method: "GET",
+ url: 'get_favorites',
+// TIMEOUT USED FOR LOCAL TESTING ONLY
+// timeout: 100
+ }).success(function (response) {
+ if (response == '101: Timeout') {
+ $log.error('Timeout attempting to get_favorites_menu');
+ } else {
+ if(typeof response != 'undefined' && response.length!=0 && typeof response[0] != 'undefined' && typeof response[0].error!="undefined"){
+ $log.error('REST API failed get_favorites' + response);
+ }else{
+ $log.debug('get_favorites = ' + JSON.stringify(response));
+ $scope.favoritesMenuItems = response;
+ $scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
+ $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ }
+ }
+ }).error(function (response){
+ $log.error('REST API failed get_favorites' + response);
+//createFavoriteErrorMenu() USED FOR LOCAL TESTING ONLY
+// $scope.createFavoriteErrorMenu();
+ });
+ }
+
+ $scope.createFavoriteErrorMenu=function() {
+ $scope.favoritesMenuItems = [];
+ $scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
+ $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ }
+
+ /* end of Favorite Menu code */
+ /* **************************************************************************/
+
+
+ /* **************************************************************************/
+ // THIS IS USED FOR LOCAL TESTING ONLY
+ /* **************************************************************************/
+ $scope.createErrorMenu=function() {
+ $log.debug('Creating fake menu now...');
+// $scope.loadMenufail=true;
+ $scope.menuItems = [
+ {
+ "menuId": 1,
+ "column": 2,
+ "text": "Design",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 2,
+ "column": 3,
+ "text": "Infrastructure Ordering",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 3,
+ "column": 4,
+ "text": "Service Creation",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 4,
+ "column": 5,
+ "text": "Service Mgmt",
+ "parentMenuId": null,
+ "url": ""
+ },
+ {
+ "menuId": 90,
+ "column": 1,
+ "text": "Google",
+ "parentMenuId": 1,
+ "url": "http://google.com"
+ },
+ {
+ "menuId": 91,
+ "column": 1,
+ "text": "Mike Little's Coffee Cup",
+ "parentMenuId": 2,
+ "url": "http://coffee.com"
+ },
+ {
+ "menuId": 92,
+ "column": 2,
+ "text": "Andy and his Astrophotgraphy",
+ "parentMenuId": 3,
+ "url": "http://nightskypix.com"
+ },
+ {
+ "menuId": 93,
+ "column": 1,
+ "text": "JSONLint",
+ "parentMenuId": 4,
+ "url": "http://http://jsonlint.com"
+ },
+ {
+ "menuId": 94,
+ "column": 2,
+ "text": "HROneStop",
+ "parentMenuId": 4,
+ "url": "http://ebiz.sbc.com/hronestop"
+ },
+ {
+ "menuId": 95,
+ "column": 2,
+ "text": "4th Level App4a R16",
+ "parentMenuId": 4,
+ "url": "http://www.e-access.att.com/ecomp_portal_ist/ecompportal/widgets"
+ },
+ {
+ "menuId": 96,
+ "column": 3,
+ "text": "3rd Level App1c R200",
+ "parentMenuId": 4,
+ "url": "http://app1c.com"
+ },
+ {
+ "menuId": 97,
+ "column": 1,
+ "text": "3rd Level App4b R16",
+ "parentMenuId": 5,
+ "url": "http://app4b.com"
+ },
+ {
+ "menuId": 98,
+ "column": 2,
+ "text": "3rd Level App2b R16",
+ "parentMenuId": 5,
+ "url": "http://app2b.com"
+ },
+ {
+ "menuId": 99,
+ "column": 1,
+ "text": "Favorites",
+ "parentMenuId": null,
+ "url": ""
+ }
+ ];
+ $scope.menuItems = unflatten( $scope.menuItems );
+ //remove this
+ $scope.megaMenuDataObject = menuStructureConvert($scope.menuItems);
+ }
+ }]
+ }
+});
+
+appDS2.filter("ellipsis", function(){
+ return function(text, length){
+ if (text) {
+ var ellipsis = text.length > length ? "..." : "";
+ return text.slice(0, length) + ellipsis;
+ };
+ return text;
+ }
+});
+function reloadPageOnce() {
+ if( window.localStorage )
+ {
+ if( !localStorage.getItem('firstLoad') )
+ {
+ localStorage['firstLoad'] = true;
+ window.location.reload();
+ }
+ else
+ localStorage.removeItem('firstLoad');
+ }
+}
+appDS2.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoServiceDS2){
+ /*Define fields*/
+ $scope.userProfile={
+ firstName:'',
+ lastName:'',
+ fullName:'',
+ email:'',
+ }
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
+ $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
+ if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
+ $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
+ if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
+ $scope.userProfile.email = userInfo.USER_EMAIL;
+
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoServiceDS2.getFunctionalMenuStaticDetailSession()
+ .then(function (response) {
+ $scope.userProfile.fullName = response.userName;
+ $scope.userProfile.email = response.email;
+ });
+ }
+ /*getting user info from shared context*/
+ $scope.getUserName=function() {
+ var promise = UserInfoServiceDS2.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('headerServiceDS2: get user information from session');
+ $scope.getUserNameFromSession();
+
+ }else{
+ // $log.info('Received User information from shared context',res);
+ var resData = res;
+ console.log(resData);
+ $scope.inputUserInfo(resData);
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ }
+ },
+ function(err) {
+ console.log('error');
+ }
+ );
+ };
+ /*call the get user info function*/
+ try{
+ $scope.getUserName();
+ }catch(err){
+ $log.info('Error while getting User information',err);
+ }
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/leftMenuServiceDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/leftMenuServiceDS2.js
new file mode 100644
index 00000000..879da8e7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/leftMenuServiceDS2.js
@@ -0,0 +1,110 @@
+function isRealValue(obj){
+ return obj && obj !== "null" && obj!== "undefined";
+}
+appDS2.factory('LeftMenuServiceDS2', function ($http,$log, $q) {
+ return {
+ getLeftMenu: function() {
+ return $http.get('get_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ getAppName: function() {
+ return $http.get('get_app_name')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+
+ };
+});
+
+/* check if the body height has changed */
+function onElementHeightChange(elm, callback){
+ if (!elm) {
+ console.log('onElementHeightChange: null element!');
+ return;
+ }
+ var lastHeight = elm.clientHeight, newHeight;
+ (function run(){
+ newHeight = elm.clientHeight;
+ if( lastHeight != newHeight )
+ callback();
+ lastHeight = newHeight;
+
+ if( elm.onElementHeightChangeTimer )
+ clearTimeout(elm.onElementHeightChangeTimer);
+ elm.onElementHeightChangeTimer = setTimeout(run, 200);
+ })();
+}
+
+/*adjust height of left menu*/
+function adjustLeftMenuHeight() {
+
+ try{
+ var footerTop = $('.footer-container').offset().top;
+ var scrollTop = $(window).scrollTop();
+ $(".menu-container").css({
+ "height" : footerTop- scrollTop,
+ });
+ }catch(err){
+ console.log('adjustLeftMenuHeight failed', err)
+ }
+}
+/* adjust left menu height on scroll */
+window.onscroll = function (e) {
+ adjustLeftMenuHeight();
+}
+
+function adjustHeader() {
+ var showHeader = getCookie("show_app_header");
+ if(showHeader==''){
+ $(".menu-container").css({
+ "margin-top" : 45,
+ });
+ }else{
+ $(".menu-container").css({
+ "margin-top" : 0,
+ });
+ }
+};
+/* adjust left menu height on page load */
+$(function() {
+ adjustLeftMenuHeight();
+ adjustHeader();
+});
+
+
+onElementHeightChange(document.body, function(){
+ adjustLeftMenuHeight();
+});
+
+function getCookie(cname) {
+ var name = cname + "=";
+ var decodedCookie = decodeURIComponent(document.cookie);
+ var ca = decodedCookie.split(';');
+ for(var i = 0; i <ca.length; i++) {
+ var c = ca[i];
+ while (c.charAt(0) == ' ') {
+ c = c.substring(1);
+ }
+ if (c.indexOf(name) == 0) {
+ return c.substring(name.length, c.length);
+ }
+ }
+ return "";
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/manifestService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/manifestService.js
new file mode 100644
index 00000000..27e3a6ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/manifestService.js
@@ -0,0 +1,24 @@
+appDS2.factory('ManifestService', function ($http, $q, $log) {
+ return {
+ // Gets and returns the manifest for the webapp.
+ getManifest: function() {
+ // cache control for IE
+ var cc = "?cc=" + new Date().getTime().toString();
+ return $http({
+ method: 'GET',
+ url: 'manifest' + cc,
+ cache: false,
+ responseType: 'json'})
+ .then(function(response) {
+ // $log.debug("ManifestService.getManifest: " + JSON.stringify(response));
+ if (response.data == null || typeof response.data != 'object')
+ return $q.reject('ManifestService.getManifest: response.data null or not object');
+ else
+ return response.data;
+ }, function(error) {
+ $log.error('ManifestService.getManifest failed: ' + error.data);
+ return $q.reject(error.data);
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalService.js
new file mode 100644
index 00000000..cb85ffce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalService.js
@@ -0,0 +1,57 @@
+
+angular.module("template/modalsAndAlerts/window2.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/modalsAndAlerts/window.html",
+ "<div class=\"modalwrapper active {{windowClass}}\" ng-class=\"{'modal-landscape': isModalLandscape}\" role=\"dialog\" tabindex=\"-1\" aria-labelledby=\"{{title}}\" aria-describedby=\"{{content}}\">\n" +
+ " <div class=\"modal fade {{sizeClass}}\">sdfdsfsfd</div>\n" +
+ "</div>");
+ }]);
+
+angular.module('ddh.att.modalsAndAlerts')
+
+.controller('modalsAndAlertsController', function ($scope, $modal, $log) {
+ $scope.name='eeee';
+ $scope.items = ['item1', 'item2', 'item3'];
+ $scope.dt = new Date("March 10, 2014 00:00:00");
+ $scope.helperText = "The date you selected is $date. Double tap to open calendar. Select a date to close the calendar.";
+ $scope.open = function (event) {
+ var modalInstance = $modal.open({
+ templateUrl: 'template/modalsAndAlerts/modal-demo.html',
+ controller: ModalInstanceCtrl,
+ sizeClass: 'modal-long-adjust',
+ resolve: {
+ items: function () {
+ return $scope.items;
+ }
+ }
+ });
+
+ modalInstance.result.then(function (selectedItem) {
+ $scope.selected = selectedItem;
+ event.target.focus();
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ event.target.focus();
+ });
+ };
+ $scope.ok = function () {
+ //add the ok functionality
+ console.log("ok");
+ };
+ $scope.cancel = function () {
+ //add the cancel functionality
+ console.log("cancel");
+ };
+})
+
+var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
+ $scope.items = items;
+ $scope.selected = {
+ item: $scope.items[0]
+ };
+ $scope.ok = function () {
+ $modalInstance.close($scope.selected.item);
+ };
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+};
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalServiceDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalServiceDS2.js
new file mode 100644
index 00000000..d3cd8737
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/modalServiceDS2.js
@@ -0,0 +1,31 @@
+angular.module("modalServicesDS2",[]).service('modalService', ['$modal', function ($modal) {
+
+ this.popupConfirmWinWithCancel = function(title, msgBody, callback,dismissCallback){
+ debugger;
+ var modalInstance = $modal.open({
+ templateUrl: 'confirmation_informativeDS2.html',
+ //controller: 'modalpopupControllerDS2',
+ //size: 'sm',
+ resolve: {
+ message: function () {
+ var message = {
+ title: title,
+ text: msgBody
+ };
+ return message;
+ }
+ }
+ });
+ var args = Array.prototype.slice.call( arguments, 0 );
+ args.splice( 0, 3);
+ modalInstance.result.then(function(){
+ callback.apply(null, args);
+ }, function() {
+ dismissCallback();
+ })['finally'](function(){
+ modalInstance = undefined;
+ });
+
+ };
+
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/profileServiceDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/profileServiceDS2.js
new file mode 100644
index 00000000..1ca373f9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/profileServiceDS2.js
@@ -0,0 +1,78 @@
+appDS2.factory('ProfileServiceDS2', function ($http, $q) {
+ return {
+ getProfile: function() {
+ return $http.get('get_user')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getProfilePagination: function(pageNum,viewPerPage) {
+ return $http.get('get_user_pagination?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getPostProfile: function() {
+ return $http.get('post_search_sample')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getProfileDetail: function(profileId) {
+ return $http.get('get_profile?profile_id='+profileId)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getSelfProfileDetail: function() {
+ return $http.get('get_self_profile')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/sampleService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/sampleService.js
new file mode 100644
index 00000000..d762dc9c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/sampleService.js
@@ -0,0 +1,19 @@
+appDS2.factory('SampleService', function ($http, $q) {
+ return {
+ getCollaborateList: function() {
+ return $http.get('get_collaborate_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ }
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/userInfoServiceDS2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/userInfoServiceDS2.js
new file mode 100644
index 00000000..cfb12dd5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-services/userInfoServiceDS2.js
@@ -0,0 +1,32 @@
+appDS2.factory('UserInfoServiceDS2', function ($http, $q,$log) {
+ return {
+ getFunctionalMenuStaticDetailShareContext: function(contextId,key) {
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_userinfo",
+ }).success( function(res) {
+ if(res==null || res=='')
+ $log.error('userInfoServiceDs2: failed to get user info');
+ deferred.resolve(res);
+ }).error( function(status) {
+ deferred.reject(status);
+ });
+ return deferred.promise;
+ },
+ getFunctionalMenuStaticDetailSession: function() {
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_topMenuInfo",
+ }).success(function(res) {
+ if(res==null || res=='')
+ $log.error('userInfoServiceDs2: failed to get top menu info');
+ deferred.resolve(res);
+ }).error( function(status) {
+ deferred.reject(status);
+ });
+ return deferred.promise;
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-landing.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-landing.html
new file mode 100644
index 00000000..fc90c273
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-landing.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App workflow page using DS2 look and feel -->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Workflow</title>
+
+ <!-- Common items -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+
+ <!-- Page specific items -->
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-workflows/workflowRouting.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-workflows/workflowController.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-workflows/workflowApp.js"></script>
+
+ <!-- <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/scribble.css" />
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/workflows/workflows.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/workflows/bs-workflow.css" >
+ -->
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html
new file mode 100644
index 00000000..452dcafa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-listing.html
@@ -0,0 +1,65 @@
+
+<div id="page-content" style=" width: 100%;" >
+ <br/>
+ <div >
+ <h1 class="heading-page">Workflow</h1>
+ <button type="submit" ng-click="createWorkflow('md')" class="btn btn-alt btn-small" >Create Workflow</button>
+ </div>
+ <div>
+ <form>
+ <div class="form-group" align="right">
+ <input type="text" ng-model="search" placeholder = "Search Workflows"/>
+ </div>
+ </form>
+ </div>
+
+
+
+
+<div>
+<table class="striped" table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
+ <thead >
+ <tr class="info">
+ <th >Id</th>
+ <th>Name</th>
+ <th>Key</th>
+ <th>Description</th>
+ <th>Workflow Server URL</th>
+ <!-- <th>Suspend Link</th> -->
+ <th>View</th>
+ <th>Active</th>
+ <th>Created </th>
+ <th>Created By</th>
+ <th>Action</th>
+ <th>Schedule</th>
+ <th>Edit</th>
+ <th>Delete?</th>
+
+
+ </tr>
+ </thead>
+
+
+ <tbody type="body" ng-repeat="workflow in workflows | filter: search">
+ <tr>
+ <td>{{workflow.id}}</td>
+ <td>{{workflow.name}}</td>
+ <td>{{workflow.workflowKey}}</td>
+ <td>{{workflow.description}}</td>
+ <td>{{workflow.runLink}}</td>
+ <td><div ng-click="previewWorkflow(workflow,'lg');" style="font-size:20px;"><a href="javascript:void(0)" class=" icon-people-preview"></a></div></td>
+ <!-- <td>{{workflow.suspendLink}}</td> -->
+ <td >{{workflow.active}}</td>
+ <td>{{workflow.created}}</td>
+ <td>{{workflow.createdBy}}</td>
+ <td><div ng-show="workflow.active ==='false'" ng-click="activateWorkflow(workflow)" style="font-size:20px;"><a href="javascript:void(0)" class="icon-controls-playalt"></a></div>
+ <div ng-show="workflow.active ==='true'" ng-click="suspendWorkflow(workflow)" style="font-size:20px;"><a href="javascript:void(0)" class="icon-controls-pauseL"></a></div></td>
+ <td><div ng-click="scheduleWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-misc-time"></a></div></td>
+ <td><div ng-click="updateWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-misc-pen"></a></div></td>
+ <td><div ng-click="removeWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-misc-trash"></a></div></td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+ </div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html
new file mode 100644
index 00000000..9daebd07
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-new.html
@@ -0,0 +1,110 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Create Workflows</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in">
+ <form name="workflowForm" class="css-form" novalidate>
+ <div class="form-row input-emphasized-field">
+ <label for="textinputID1">Name *: </label>
+
+ <div class="field-group">
+ <input type="text" id="textinputID-2a" ddh-reset ng-model="workflow.name" class="span12 input-emphasized"
+ name="workflowName" required="required" placeholder="Workflow Name" />
+
+ <div ng-show="workflowForm.$submitted || workflowForm.workflowName.$touched">
+ <span ng-show="workflowForm.workflowName.$error.required">Workflow Name is required !!!</span>
+ </div>
+
+ </div>
+ </div>
+
+
+ <div class="form-row input-emphasized-field">
+ <label for="textinputID1">Key*: </label>
+ <div class="field-group">
+ <input type="text" id="textinputID-2a" ddh-reset ng-model="workflow.workflowKey" class="span12 input-emphasized"
+ name="workflowKey" required="required" placeholder="Workflow Key" />
+
+ <div ng-show="workflowForm.$submitted || workflowForm.workflowKey.$touched">
+ <span ng-show="workflowForm.workflowKey.$error.required">Workflow Key is required !!!</span>
+ </div>
+
+ </div>
+ </div>
+
+
+ <div class="form-row input-emphasized-field">
+ <label for="textinputID1">Description: </label>
+
+ <div class="field-group">
+ <input type="text" ng-model="workflow.description" id = "textinputID-2a" ddh-reset name="workflowDescription" class="span12 input-emphasized" placeholder="Brief Description"/>
+ </div>
+ </div>
+
+ <div class="form-row input-emphasized-field">
+ <label for="textinputID1">Workflow Server URL*</label>
+ <div class="field-group">
+ <input type = "url" ng-model = "workflow.runLink" id = "workflowRunLink" ddh-reset name = "workflowRunLink" required = "required" class="span12 input-emphasized"/>
+ </div>
+
+ <div ng-show="workflowForm.$submitted || workflowForm.workflowRunLink.$touched">
+ <span ng-show="workflowForm.workflowRunLink.$error.required">Run Link is required !!!</span>
+ <span class="error" ng-show="workflowForm.workflowRunLink.$error.url">Not valid url!</span>
+ </div>
+
+ </div>
+
+ <!-- <div class="control-group">
+ <label class="fn-ebz-text large" for="workflowSuspendLink">Suspend Link*</label>
+ <div class="controls">
+ <input type = "url" ng-model = "workflow.suspendLink" id = "workflowSuspendLink" name = "workflowSuspendLink" required = "required" class="fn-ebz-text extra-large"/>
+ </div>
+
+ <div ng-show="workflowForm.$submitted || workflowForm.workflowSuspendLink.$touched">
+ <span ng-show="workflowForm.workflowSuspendLink.$error.required">Suspend Link is required !!!</span>
+ <span class="error" ng-show="workflowForm.workflowSuspendLink.$error.url">Not valid url!</span>
+ </div>
+ </div> -->
+
+ <div class="form-row" role="radio">
+ <fieldset role="radiogroup" radio-group-accessibility aria-labelledby="radiolabel1">
+ <label for="optionsRadios1111" class="radio">
+ <!-- <input type = "text" ng-model = "workflow.active" id="workflowActive" name="workflowActive" class="fn-ebz-text extra-large"/> -->
+ <input type="radio" ng-model="workflow.active" id="optionsRadios1111" name="optionsRadio11" value="true" required="">
+ <i class="skin"></i>
+ <span>Active</span>
+ </label>
+ </div>
+ <div class="form-row" role="radio">
+ <label for="optionsRadios2222" class="radio">
+ <input type="radio" ng-model ="workflow.active" id="optionsRadios2222" name="optionsRadio11" value="false">
+ <i class="skin"></i>
+ <span>Inactive</span>
+ </label>
+ <!-- </div>
+ <input type="radio" ng-model="workflow.active" value="true">Active
+ <input type="radio" ng-model="workflow.active" value="false">Inactive
+
+
+ </div> -->
+ </div>
+ </fieldset>
+ </div>
+
+
+
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small"" type="button" ng-click="ok()">OK</button>
+ <button class="btn btn-medium" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-preview.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-preview.html
new file mode 100644
index 00000000..0fb1ffa2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-preview.html
@@ -0,0 +1,24 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">View Workflow</h3>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" >
+ <form name="workflowForm" class="css-form" novalidate>
+
+ <div style="overflow:scroll">
+ <img ng-src="{{workflowToPreview.runLink}}/engine-rest/process-definition/key/{{workflowToPreview.workflowKey}}/diagram">
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-medium" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-remove.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-remove.html
new file mode 100644
index 00000000..a355c07e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-remove.html
@@ -0,0 +1,26 @@
+<div style=" height: 276px;">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Remove Workflow</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+ <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">Workflow "{{workflowToRemove.name}}" is going to be removed. Do you want to continue</label>
+ </div>
+
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="ok()">OK</button>
+ <button class="btn btn-medium" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-schedule.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-schedule.html
new file mode 100644
index 00000000..b939a598
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/DS2-workflows-page/workflow-schedule.html
@@ -0,0 +1,130 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Workflow: {{workflowToSchedule.name}}</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+
+ </div>
+ <table style="width:60%; margin-bottom: -21px">
+ <tr><td>Workflow Key:</td> <td>{{workflowToSchedule.workflowKey}}</td></tr>
+ <tr><td>Workflow Description:</td> <td>{{workflowToSchedule.description}}</td></tr>
+ </table>
+
+
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="padding:0px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+ <table>
+ <tr>
+ <form name="myForm">
+ <td>
+ <label for="singleSelect"> Recurrence: </label>
+ </td>
+ <td style="padding-top: 0px;padding-bottom: 0px;">
+ <div class="span12">
+ <div class="form-row">
+ <select name="dropdown1" b2b-dropdown ng-model="selectRecurrenceOpt">
+ <option b2b-dropdown-list option-repeat="d in recurrenceOptions" value="{{d.value}}" init-value="{{selectRecurrenceOpt.title}}">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+
+ <br>
+ </td>
+ <td> </td>
+ </form>
+ </tr>
+<tr>
+<td>
+
+</td>
+<td>
+Pick a date:
+</td>
+<td>
+Hour:
+</td>
+<td>
+Minute:
+</td>
+</tr>
+ <tr>
+ <td>
+ <form name="FirstScheduleForm">
+ <label for="dateSelect"> First Schedule: </label>
+ </form>
+ </td>
+ <td >
+ <!--DATEPICKER POPUP-->
+ <input class="span12" id="datepicker1" type="text" style="overflow-y:scroll;" ng-model="dt" b2b-datepicker >
+ </td>
+ <td>
+ <div class="span12">
+ <div class="form-row">
+ <select name="dropdown1" b2b-dropdown ng-model="selectFirstHour">
+ <option b2b-dropdown-list option-repeat="d in hours" value="{{d.value}}" init-value="{{selectFirstHour.title}}" placeholder="Select an Option">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ </td>
+ <td>
+ <div class="span12">
+ <div class="form-row">
+ <select name="dropdown1" b2b-dropdown ng-model="selectFirstMinute">
+ <option b2b-dropdown-list option-repeat="d in minutes" value="{{d.value}}" init-value="{{selectFirstMinute.title}}" placeholder="Select an Option">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ </td>
+</tr>
+<tr >
+ <td>
+ <form name="LastScheduleForm">
+ <label for="dateSelect"> Last Schedule: </label>
+ </form>
+ </td>
+ <td>
+ <div >
+ <input class="span12" id="datepicker2" type="text" ng-model="dt2" b2b-datepicker>
+ </div>
+ </td>
+ <td>
+ <div class="span12">
+ <div class="form-row">
+ <select name="dropdown1" b2b-dropdown ng-model="selectLastHour">
+ <option b2b-dropdown-list option-repeat="d in hours" value="{{d.value}}" init-value="{{selectLastHour.title}}" placeholder="Select an Option">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ </td>
+ <td>
+ <div class="span12">
+ <div class="form-row">
+ <select name="dropdown1" b2b-dropdown ng-model="selectLastMinute">
+ <option b2b-dropdown-list option-repeat="d in minutes" value="{{d.value}}" init-value="{{selectLastMinute.title}}" placeholder="Select an Option">{{d.title}}</option>
+ </select>
+ </div>
+ </div>
+ </td>
+ :
+
+ </tr>
+<tr>
+
+</tr>
+
+</table>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="ok()">OK</button>
+ <button class="btn btn-medium" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/b2b-leftnav-ext.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/b2b-leftnav-ext.html
new file mode 100644
index 00000000..fad0e041
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/b2b-leftnav-ext.html
@@ -0,0 +1,43 @@
+<div class="b2b-nav-menu" id="left-menu-main-div" ng-class="leftMenuClass">
+ <div class="b2b-subnav-container" id="left-menu-subnav-container">
+ <ul class="b2b-subnav-content" id="left-menu-subnav-content">
+ <li id="b2b-subnav-content-li">
+ <div ng-class="leftMenuArrowClass" id="left-menu-arrow-toggle-div">
+ <a ng-click="toggleDrawer(showmenu);" class="text-right" id="left-menu-arrow-toggle-anchor">
+ <i ng-class="{true: 'icon-controls-left', false: 'icon-controls-right'}[showmenu]" id="left-menuf-arrow-toggle-icon">&nbsp;</i>
+ </a>
+ </div>
+ </li>
+ <li ng-repeat="menu in menuData" ng-click="toggleNav($index,menu.href,showmenu)" id="left-menu-li-{{menu.name.split(' ').join('-')}}">
+ <span ng-class="{true: 'menu-icon', false: 'menu-icon-collapse'}[showmenu]" id="left-menu-span-{{menu.name.split(' ').join('-')}}">
+ <span class="{{menu.imageSrc}}" id="icon-image-{{menu.name.split(' ').join('-')}}"></span>&nbsp;&nbsp;
+ </span>
+ <a ng-class="{expand: isOpen($index)}"
+ id="parent-item-{{menu.name.split(' ').join('-')}}"
+ ng-if="showmenu"
+ aria-label="{{menu.name}}" title="{{menu.name}}"
+ aria-expanded="{{(idx==$index)?true:false;}}"
+ href="javascript:void(0);">
+ {{menu.name}}
+ <i aria-hidden="true"
+ ng-if="(menu.menuItems.length > 0)"
+ class="b2b-icon-primary-plus-minus"
+ ng-class="idx==$index ? 'icon-primary-expanded' : 'icon-primary-collapsed'"></i>
+ </a>
+ <div role="region" aria-hidden="{{(isOpen($index))?false:true;}}" id="left-menu-child-div-{{menu.name.split(' ').join('-')}}">
+ <ul ng-class="{expand: idx==$index}" id="left-menu-child-ul-{{menu.name.split(' ').join('-')}}">
+ <li ng-repeat="menuItem in menu.menuItems"
+ ng-click="liveLink($event, $index, $parent.$index)"
+ id="left-menu-child-li-{{menuItem.name.split(' ').join('-')}}-{{menu.name.split(' ').join('-')}}">
+ <a aria-hidden="{{!(idx==$parent.$index)}}"
+ aria-label="{{menuItem.name}}" title="{{menuItem.name}}"
+ id="child-item-{{menuItem.name.split(' ').join('-')}}"
+ href="{{menuItem.href}}" tabindex="{{(idx==$parent.$index)?0:-1;}}"
+ ng-class="{active: itemIdx==$index && navIdx==$parent.$index}">{{menuItem.name}}</a>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html
new file mode 100644
index 00000000..69fd324b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html
@@ -0,0 +1,102 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="AdminMenuItems">Admin Menu Items</h1>
+ </div>
+ <div>
+ <button type="submit" ng-click="addNewFnMenuItemModalPopup();" class="btn btn-alt btn-small">Add Menu Item</button>
+ </div>
+
+ <h3 class="heading-small">
+ Existing menu items
+ </h3>
+
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img" aria-label="Please wait while we load your content"></i>
+ </div>
+
+ <div ng-hide="showLoader">
+ <table>
+ <thead>
+ <tr>
+ <th sortable="true" key="id" default-sort="a">Menu ID</th>
+ <th sortable="true" key="label">Label</th>
+ <th sortable="true" key="ParentId">ParentId</th>
+ <th sortable="true" key="sortOrder">Sort Order</th>
+ <th sortable="true" key="action">Action</th>
+ <th sortable="true" key="functionCd">Function</th>
+ <th sortable="true" key="active">Active</th>
+ <th sortable="true" key="servlet">Servlet</th>
+ <th sortable="true" key="queryString">Query String</th>
+ <th sortable="true" key="externalUrl">External URL</th>
+ <th sortable="true" key="target">Target</th>
+ <th sortable="true" key="menuSetCode">Menu Set Code</th>
+ <th sortable="true" key="separator">Separator</th>
+ <th sortable="true" key="imageSrc">Image Source</th>
+ <th sortable="false" key="edit">Edit</th>
+ <th sortable="false" key="delete">Delete</th>
+ </tr>
+ </thead>
+ <tbody ng-repeat="fnMenuItem in tableFnMenuItems" >
+ <tr>
+ <td ng-bind="fnMenuItem.id"></td>
+ <td ng-bind="fnMenuItem.label"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.parentId"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.sortOrder"></td>
+ <td ng-bind="fnMenuItem.action"></td>
+ <td ng-bind="fnMenuItem.functionCd"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.active ? 'Y' : 'N'"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.servlet"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.queryString"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.externalUrl"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.target"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.menuSetCode"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.separator ? 'Y' : 'N'"></td>
+ <td style="word-break: break-all;" ng-bind="fnMenuItem.imageSrc"></td>
+ <td >
+ <div ng-click="editMenuItemModalPopup(fnMenuItem);"
+ style="font-size: 20px;"><a href="javascript:void(0)" class="icon-misc-pen"></a>
+ </div>
+ </td>
+ <td>
+ <div ng-click="removeMenuItem(fnMenuItem);"><a href="javascript:void(0)" class="icon-misc-trash"></a>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="well" style="padding-bottom: 35px;">
+ <div class="row ddh-page short">
+ <div b2b-pagination="" total-pages="totalPages1"
+ current-page="currentPage1" click-handler="customHandler1"
+ role="navigation" aria-label="Customer Data Pages"></div>
+ </div>
+
+ <!-- <div class="row span10 offset1">
+ <div class="span6">
+ <div class="form-row">
+ <label for="totalPages1">Total Pages:</label>
+ <div class="field-group">
+ <input id="totalPages1" type="number" class="span12"
+ only-digits="" name="totalPages1" ng-model="totalPages1"
+ title="Total Pages {{totalPages1}}"style="pointer-events: none;">
+ </div>
+ </div>
+ </div>
+ <div class="span6 font-clearview">
+ <div class="form-row">
+ <label for="currentPage1">Current Page:</label>
+ <div class="field-group">
+ <input id="currentPage1" type="number" class="span12"
+ only-digits="" name="currentPage1" ng-model="currentPage1"
+ title="Current Page {{currentPage1}}">
+ </div>
+ </div>
+ </div>
+ </div> -->
+ </div>
+ </div>
+
+</div>
+
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin.html
new file mode 100644
index 00000000..8b352652
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App admin pages using DS2 look and feel -->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Admin</title>
+
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+ <script src="app/fusion/external/angular-1.4.8/angular.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <!-- B2b Library -->
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <!-- Page-specific items -->
+ <script src="app/fusion/scripts/DS2-controllers/admin-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/admin-route.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/admin-menu-edit.js"></script>
+ <script src="app/fusion/scripts/DS2-services/adminService.js"></script>
+ <script src="app/fusion/scripts/DS2-services/adminMenuService.js"></script>
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/usage-list-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/collaborate-list-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/admin-closed-cloop.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/admin-whitelist.js"></script>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin_closed_loop.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin_closed_loop.html
new file mode 100644
index 00000000..4f65e7b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/admin_closed_loop.html
@@ -0,0 +1,17 @@
+<div style=" margin-right:50px;" id="fnMenueContent">
+ <div id="page-content" class="pageTitle" align="left">
+
+ <h1 class="heading1" style="margin-top:20px;">Closed Loop</h1>
+ <br/>
+ <br>
+ </div>
+ <div id="page-content" style="margin-right: 20px;text-align: justify;text-align-last:auto;">
+ Cloop Server
+ </div>
+ <br>
+ <div id="hiddenCamundaDiv" style="width:500px;"></div>
+ <br>
+ <iframe id="camundaFrame" style=" margin-left: 250px;"
+ ng-src="{{camunda_cockpit_url}}"
+ width="100%" height="500"></iframe>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html
new file mode 100644
index 00000000..05c316c8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaborate-list.html
@@ -0,0 +1,76 @@
+
+<div id="page-content">
+ <div>
+ <div align="right">
+ <a href="JavaScript:void(0);" style= "color:#00547A" onClick="downloadScreenCaptureExtenstion()" id="install-button" >
+ Please download the extension for ScreenCapture and refresh page</a>
+ </div>
+ <div>
+ <h1 class="heading-page">User List</h1>
+ </div>
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img" aria-label="Please wait while we load your content"></i>
+ </div>
+ <div>
+
+ <table class="striped" table-data="tableCollbItems">
+
+ <thead>
+ <tr>
+ <th key="id">User ID</th>
+ <th key="lastName">Last Name</th>
+ <th key="firstName">First Name</th>
+ <th key="email">Email</th>
+ <th key="orgUserId">Organization User ID</th>
+ <th key="online">Online/Offline</th>
+ </tr>
+
+ </thead>
+ <tbody type="body" ng-repeat="rowData in tableCollbItems">
+ <tr>
+ <td ng-bind="rowData['id']">{{rowData.id}}</td>
+ <td ng-bind="rowData['lastName']">{{rowData.lastName}}</td>
+ <td ng-bind="rowData['firstName']">{{rowData.firstName}}</td>
+ <td ng-bind="rowData['email']">{{rowData.email}}</td>
+ <td ng-bind="rowData['orgUserId']">{{rowData.loginId}}</td>
+ <td>
+ <div ng-hide="rowData.online" ng-click="rowData.isActive=true;openCollaboration(rowData.chatId)"><span class="icon-misc-lightsoff" ></span>Offline</div>
+ <div ng-show="rowData.online"ng-click="rowData.isActive=false;openCollaboration(rowData.chatId)"><span class="icon-misc-bulb" ></span>Online</div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="well" style="padding-bottom: 35px;">
+ <div class="row">
+ <div b2b-pagination="" total-pages="totalPages1"
+ current-page="currentPage1" click-handler="customHandler1"
+ role="navigation" aria-label="Customer Data Pages"></div>
+ </div>
+
+ <!-- <div class="row span10 offset1">
+ <div class="span6">
+ <div class="form-row">
+ <label for="totalPages1">Total Pages:</label>
+ <div class="field-group">
+ <input id="totalPages1" type="number" class="span12"
+ only-digits="" name="totalPages1" ng-model="totalPages1"
+ title="Total Pages {{totalPages1}}"style="pointer-events: none;">
+ </div>
+ </div>
+ </div>
+ <div class="span6 font-clearview">
+ <div class="form-row">
+ <label for="currentPage1">Current Page:</label>
+ <div class="field-group">
+ <input id="currentPage1" type="number" class="span12"
+ only-digits="" name="currentPage1" ng-model="currentPage1"
+ title="Current Page {{currentPage1}}">
+ </div>
+ </div>
+ </div>
+ </div> -->
+ </div>
+ </div>
+<div id="peerBroadcastSection"></div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaboration.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaboration.html
new file mode 100644
index 00000000..cca54a6b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/collaboration.html
@@ -0,0 +1,182 @@
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <style type="text/css">
+ /*
+ * NOTE: All CSS is purely cosmetic - it does not affect functionality
+ * http://layout.jquery-dev.com/demos.cfm
+ */
+
+ /* customize borders to avoid double-borders around inner-layouts */
+ .ui-layout-pane {
+ border: 0; /* override layout-default-latest.css */
+ border-top: 1px solid #BBB;
+ border-bottom: 1px solid #BBB;
+ }
+ .ui-layout-pane-north ,
+ .ui-layout-pane-south {
+ border: 1px solid #BBB;
+ overflow: auto;
+ }
+ .ui-layout-pane-west ,
+ .ui-layout-pane-east {
+ }
+ .ui-layout-pane-center {
+ border-left: 0;
+ border-right: 0;
+ }
+ .inner-center {
+ border: 1px solid #BBB;
+ }
+
+ /* add shading to outer sidebar-panes */
+ .outer-west ,
+ .outer-east {
+ background-color: #EEE;
+ }
+ .middle-west ,
+ .middle-east {
+ background-color: #F8F8F8;
+ }
+
+ /* remove padding & scrolling from panes that are 'containers' for nested layouts */
+ .outer-center ,
+ .middle-center {
+ border: 0; /* cosmetic */
+ padding: 0;
+ overflow: auto;
+ }
+
+ /*
+ * customize borders on panes/resizers to make pretty
+ */
+ .ui-layout-pane-west { border-right: 0; }
+ .ui-layout-resizer-west { border-left: 1px solid #BBB; }
+ .ui-layout-pane-east { border-left: 0; }
+ .ui-layout-resizer-east { border-right: 1px solid #BBB; }
+ .ui-layout-pane-north { border-bottom: 0; }
+ .ui-layout-resizer-north { border-top: 1px solid #BBB; }
+ .ui-layout-pane-south { border-top: 0; }
+ .ui-layout-resizer-south { border-bottom: 1px solid #BBB; }
+ /*
+ * add borders to resizers when pane is 'closed'
+ *
+ *.ui-layout-resizer-closed { border: 1px solid #BBB; }
+ */
+ /*
+ * show both borders when the resizer is 'dragging'
+ */
+ .ui-layout-resizer-west-dragging ,
+ .ui-layout-resizer-east-dragging {
+ border-left: 1px solid #BBB;
+ border-right: 1px solid #BBB;
+ }
+ .ui-layout-resizer-north-dragging ,
+ .ui-layout-resizer-south-dragging {
+ border-top: 1px solid #BBB;
+ border-bottom: 1px solid #BBB;
+ }
+
+
+ /*
+ layout toggler background image
+ */
+ .ui-layout-toggler-west, .ui-layout-toggler-east {
+ border-width: 1px 0;
+ background-image: url("static/fusion/images/layout/panel-e-w-toggle.png");
+ background-size: 10px 10px;
+ background-repeat: no-repeat;
+ background-position: center;
+ }
+
+ .ui-layout-toggler-north, .ui-layout-toggler-south {
+ border-width: 0 1px;
+ background-image: url("static/fusion/images/layout/panel-n-s-toggle.png");
+ background-size: 10px 10px;
+ background-repeat: no-repeat;
+ background-position: center;
+ }
+
+ body{background-color:#fff;font-size:14px;font-size:.875rem;margin:0;padding:0px 0 20px;position:relative}
+
+ </style>
+<!-- LAYOUT v 1.3.0 -->
+ <script type="text/javascript" src="app/fusion/scripts/layout/jquery-latest.js"></script>
+ <script type="text/javascript" src="app/fusion/scripts/layout/jquery-ui-latest.js"></script>
+ <script type="text/javascript" src="app/fusion/scripts/layout/jquery.layout-latest.js"></script>
+ <script type="text/javascript" src="app/fusion/scripts/webrtc/RTCMultiConnection.js"></script>
+ <script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
+ <script type="text/javascript" src="app/fusion/scripts/layout/debug.js"></script>
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+
+
+ <script type="text/javascript" src= "app/fusion/scripts/DS2-controllers/collaboration-controller.js"></script>
+
+<div class="outer-center" style="position: absolute; left: 12px; right: 0px; top: 0px;bottom: 0px;">
+ <div class="inner-center">
+
+ <!-- <jsp:include page="/WEB-INF/fusion/zul/chatOne.zul" /> -->
+
+
+
+ <table style="width: 100%;">
+ <tbody><tr>
+ <td>
+ <button type="button" id="share-screen" class="btn btn-alt btn-small setup">Start Session</button>
+ <button id="stop-share-screen" class="btn btn-alt btn-small setup">Stop Session</button>
+ <button id="view-screen" class="btn btn-alt btn-small setup">View</button>
+
+ </td>
+
+ </tr>
+ </tbody>
+
+ <tbody><tr>
+ <td>
+ <input type="text" id="chat-input" style="font-size: 1.2em;visibility:collapse;" placeholder="type here.."/>
+ <div id="chat-output"></div>
+ </td>
+ <!--
+ <td style="background: white;">
+ <input type="file" id="file">
+ <div id="file-progress"></div>
+ </td>
+ -->
+ </tr>
+ </tbody>
+ </table>
+
+
+ </div>
+ <div id="inner-south" class="ui-layout-south">
+ <div class="videoContainer1"></div>
+ <div class="videoContainer2"></div>
+
+ </div>
+</div>
+
+<div class="outer-west">
+ <div class="screenContainer1"></div>
+ <div class="screenContainer2"></div>
+ <div ng-controller="collaborationControllerDS2">
+ </div>
+</div>
+
+
+
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html
new file mode 100644
index 00000000..fd8a5302
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html
@@ -0,0 +1,73 @@
+<div id="page-content" style=" width: 100%">
+
+ <div>
+ <h1 class="heading-page" id="CacheRegions">Cache Regions</h1>
+ </div>
+
+ <div style="margin-right:20px; text-align:justify; text-align-last:auto;">
+ <p>
+ These are the regions which are currently defined in the cache. 'Items' and 'Bytes' refer to the elements currently in memory (not spooled).
+ You can clear all items for a region by clicking on the Clear icon next to the desired region below. You can also <a href="admin#/jcs_admin" ng-click="clearAllFuncPopUp();">clear all regions</a>
+ which empties the entire cache.</p>
+ </div>
+
+ <!-- This implements an accordion table in place -->
+ <div style="border-top: 1px solid #c4c4c4; margin-top: 0px; margin-bottom:30px; margin-right: 20px; background-color: #fff; padding: 10px 0; color: #646464s">
+ <div class="row" style="margin: 0 20px 10px 0px; float: left; width: 97%;">
+ <div class="col-md-4" style=" width: 16.6666666667%;"><b>Cache Name</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;"><b># of Items</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;"><b>Bytes</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;"><b>Status</b></div>
+ <div class="col-md-3" style=" width: 12.5%;"><b>Memory Hits</b></div>
+ <div class="col-md-3" style=" width: 12.5%;"><b>Aux Hits</b></div>
+ <div class="col-md-3" style=" width: 12.5%;"><b>Not Found Misses</b></div>
+ <div class="col-md-3" style=" width:12.5%;"><b>Expired Misses</b></div>
+ <div class="col-md-1" style=" width: 4.1666666667%;"><b>Clear?</b></div>
+ <div class="col-md-1" style=" width: 4.1666666667%;"><b>Items</b></div>
+ </div>
+
+ <div ng-repeat="region in regions">
+ <div class="row" style="margin: 0 20px 10px 0px; float: left; width: 97%;">
+ <div class="col-md-4" style=" width: 16.6666666667%;">
+ <a b2b-tooltip="Click to Show Region Details" ng-click="showRegionDetails(region.cacheName);" href="admin#/jcs_admin">{{region.cacheName}}</a></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{region.size}}</div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{region.byteCount}}</div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{region.status}}</div>
+ <div class="col-md-3" style=" width: 12.5%;">{{region.hitCountRam}}</div>
+ <div class="col-md-3" style=" width: 12.5%;">{{region.hitCountAux}}</div>
+ <div class="col-md-3" style=" width: 12.5%;">{{region.missCountNotFound}}</div>
+ <div class="col-md-3" style=" width: 12.5%;">{{region.missCountExpired}}</div>
+ <div class="col-md-1" style=" width: 4.1666666667%;">
+ <div ng-click="clearRegionFuncPopUp(region.cacheName);" style="font-size:20px;">
+ <a href="javascript:void(0)" class="icon-misc-trash"></a></div>
+ </div>
+ <div class="col-md-1"><i class="icon-primary-accordion-plus" ng-class="{true: 'icon-primary-accordion-plus', false: 'icon-primary-accordion-minus'}[ !bling$index]" ng-click="bling$index = !bling$index" style="display: block;"></i></div>
+ </div>
+ <div class="row" style="margin: 0px 20px 0px 30px; float: left; width: 95%; border-top: 1px solid #e4e4e4; padding-top: 10px"
+ ng-show="bling$index">
+ <span style="height: 20px; width: 20px; display: inline-block; float: left"></span>
+ <div class="col-md-12" style=" width: 50%;"><b>Key</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%"><b>Eternal?</b></div>
+ <div class="col-md-4" style=" width: 16.6666666667%;"><b>Created</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;"><b>Max Life</b></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;"><b>Expires</b></div>
+ <div class="col-md-1" style=" width: 4.1666666667%;"><b>Clear?</b></div>
+ </div>
+ <div ng-repeat="item in region.items">
+ <div class="row" style="margin: 0px 20px 0px 30px; float: left; width: 95%;" ng-show="bling$index">
+ <span style="height: 20px; width: 20px; display: inline-block; float: left"></span>
+ <div class="col-md-12" style=" width: 50%;"><a href="#" tooltip="Click to Show Item Details" ng-click="showItemDetails(region.cacheName,item.key);">{{item.key}}</a></div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{item.eternal}}</div>
+ <div class="col-md-4" style=" width: 16.6666666667%;">{{item.createTime}}</div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{item.maxLifeSeconds}}</div>
+ <div class="col-md-2" style=" width: 8.3333333333%;">{{item.expiresInSeconds}}</div>
+ <div class="col-md-1" style=" width: 4.1666666667%;">
+ <div ng-click="clearItemFuncPopUp(region.cacheName,item.key);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-misc-trash"></a></div>
+ </div>
+ </div>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/admin-menu-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/admin-menu-del-confirm.html
new file mode 100644
index 00000000..5d6cb16c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/admin-menu-del-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title=""> Menu Item Deletion</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+ You are about to delete '{{fnMenuItem.label}}' Menu Item. Please click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="deleteMenuItem(fnMenuItem);">Ok</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-confirm.html
new file mode 100644
index 00000000..d3eda5e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title="">Clear All Cache Regions</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+ You are about to clear all cache regions. Please click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="deleteFun(roleFun);">Ok</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-region-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-region-confirm.html
new file mode 100644
index 00000000..5f43e2a0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/cache-menu-clear-region-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title="">Clear Cache Region</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+ You are about to clear all of the items in the cache region {{msg.text}}. Please click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="deleteFun(roleFun);">Ok</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/clearItem-region-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/clearItem-region-confirm.html
new file mode 100644
index 00000000..004b49d8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/clearItem-region-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title="">Clear Item Cache Region</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+ You are about to clear this item from the cache region {{msg.text}}. Please click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="deleteFun(roleFun);">Ok</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/collaborate-list-toggle-profile-active-status.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/collaborate-list-toggle-profile-active-status.html
new file mode 100644
index 00000000..6a91cb0a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/collaborate-list-toggle-profile-active-status.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title="">Change User Status</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+ You are about to change user's active status. Please click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="deleteFun(roleFun);">Ok</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fn-menu-edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fn-menu-edit.html
new file mode 100644
index 00000000..2ccdf2af
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fn-menu-edit.html
@@ -0,0 +1,129 @@
+<script type="text/ng-template" id="edit_menu_item_popup.html">
+
+ <div class="modal__informative font-showcase" style="width:1100px;">
+ <div class="modal__header">
+ <h2 class="font-showcase-font-name" style="width: 500px;">{{label}}</h2>
+ </div>
+ <div class="divider-container"><hr> </div>
+
+ <div class="modal__content" >
+ <table>
+ <tr>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Label:</label><br>
+ <input id="popupAddMenuItemLabel" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.label" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" style = "display:none" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Parent:</label><br>
+ <input id="popupAddMenuItemParentId" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.parentId" ng-disabled="disableParentId" maxlength="30" />
+ </div>
+ <div class="fn-ebz-container" ng-init="getParentData();">
+ <form name="parentListForm">
+ <label class="fn-ebz-text-label" for="parentSelect"><sup><b>*</b></sup>Parent:</label><br>
+ <select class="form-field" name="parentSelect" id="parentSelect" ng-model="addFnMenuItem.parentId">
+ <option>{{getParentLabel(addFnMenuItem.parentId, parentListSelectData)}}</option>
+ <option ng-repeat="option in parentListSelectData" value="{{option[0]}}" "{{(addFnMenuItem.parentId===option[0]) ? 'selected' : '' }}">{{option[1]}}</option>
+ </select>
+ </form>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Sort Order:</label><br>
+ <input id="popupAddMenuItemSortOrder" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.sortOrder" ng-disabled="disableSortOrder" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Action:</label><br>
+ <input id="popupAddMenuItemAction" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.action" ng-disabled="disableAction" maxlength="30" />
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <div class="fn-ebz-container" ng-init="getFunctionCDselectData();">
+ <form name="functionCDform">
+ <label class="fn-ebz-text-label" for="repeatSelect"><sup><b>*</b></sup>Function:</label><br>
+ <select class="form-field" name="repeatSelect" id="repeatSelect" ng-model="addFnMenuItem.functionCd">
+ <option>{{addFnMenuItem.functionCd}}</option>
+ <option ng-repeat="option in functionCDselectData" value="{{option}}" >{{option}}</option>
+ </select>
+ </form>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Active:</label><br>
+ <select class="form-field" name="selectActive" ng-model="addFnMenuItem.active">
+ <option ng-repeat="active in activeStatusOptions" value="{{active.value}}" ng-selected="{{active.value}}=={{addFnMenuItem.active}}" >{{active.title}}</option>
+ </select>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Servlet:</label><br>
+ <input id="popupAddMenuItemServlet" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.servlet" ng-disabled="disableServlet" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Query String:</label><br>
+ <input id="popupAddMenuItemQueryString" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.queryString" ng-disabled="disableQueryString" maxlength="30" />
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>External URL:</label><br>
+ <input id="popupAddMenuItemExternalUrl" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.externalUrl" ng-disabled="disableExternalUrl" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Target:</label><br>
+ <input id="popupAddMenuItemTarget" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.target" ng-disabled="disableTarget" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Menu Set Code:</label><br>
+ <input id="popupAddMenuItemMenuSetCode" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.menuSetCode" ng-disabled="disableMenuSetCode" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Separator:</label><br>
+ <select class="form-field" name="select" ng-model="addFnMenuItem.separator">
+ <option ng-repeat="separator in separatorStatusOptions" value="{{separator.value}}" ng-selected="{{separator.value}}=={{addFnMenuItem.separator}}" >{{separator.title}}</option>
+ </select>
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Image Source:</label><br>
+ <input id="popupAddMenuItemImageSrc" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.imageSrc" ng-disabled="disableImageSrc" maxlength="30" />
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="updateFnMenu(addFnMenuItem);">Save</button>
+ <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
+ <!--
+ <div class="modal__footer">
+ </div>
+ -->
+ </div>
+</script>
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html
new file mode 100644
index 00000000..167defb7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/popup-modal-fnmenu-add.html
@@ -0,0 +1,136 @@
+<div>
+ <div class="b2b-modal-header ng-scope">
+ <h2 id="myModalLabel" modal-title="">{{label}}</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+ role="region" aria-label="Modal header text content">
+
+ <table>
+ <tr>
+ <td>
+
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Label:</label><br>
+ <input id="popupAddMenuItemLabel" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.label" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" style = "display:none" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Parent:</label><br>
+ <input id="popupAddMenuItemParentId" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.parentId" ng-disabled="disableParentId" maxlength="30" />
+ </div>
+ <div class="fn-ebz-container" ng-init="getParentData();">
+ <form name="parentListForm">
+ <label class="fn-ebz-text-label" for="parentSelect"><sup><b>*</b></sup>Parent:</label><br>
+ <select name="select_projects" id="select_projects" ng-model="addFnMenuItem.parentIdAsString">
+
+ <optgroup label="" ng-repeat="header in childListSelectData">
+ <option label="{{header.label}}" value="{{header.menuId}}" style="color:black;font-weight:bold;">{{header.label}}</option>
+ <option ng-repeat="child in header.children" value="{{child.menuId}}" ng-selected="child.menuId == addFnMenuItem.parentId">{{child.label}}</option>
+ </optgroup>
+ </select>
+ </form>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Sort Order:</label><br>
+ <input id="popupAddMenuItemSortOrder" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.sortOrder" ng-disabled="disableSortOrder" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Action:</label><br>
+ <input id="popupAddMenuItemAction" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.action" ng-disabled="disableAction" maxlength="200" />
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="fn-ebz-container" ng-init="getFunctionCDselectData();">
+ <form name="functionCDform">
+ <label class="fn-ebz-text-label" for="repeatSelect"><sup><b>*</b></sup>Function:</label><br>
+ <select class="form-field" name="repeatSelect" id="repeatSelect" ng-model="addFnMenuItem.functionCd">
+ <option>{{addFnMenuItem.functionCd}}</option>
+ <option ng-repeat="option in functionCDselectData" value="{{option}}" ng-selected="option==addFnMenuItem.functionCd">{{option}}</option>
+ </select>
+ </form>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Active:</label><br>
+ <select class="form-field" name="selectActive" ng-model="addFnMenuItem.activeAsString" >
+ <option ng-repeat="active in activeStatusOptions" value="{{active.value}}" ng-selected="{{active.value}} == {{addFnMenuItem.active}}" >{{active.title}}</option>
+ </select>
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Servlet:</label><br>
+ <input id="popupAddMenuItemServlet" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.servlet" ng-disabled="disableServlet" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Query String:</label><br>
+ <input id="popupAddMenuItemQueryString" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.queryString" ng-disabled="disableQueryString" maxlength="30" />
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>External URL:</label><br>
+ <input id="popupAddMenuItemExternalUrl" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.externalUrl" ng-disabled="disableExternalUrl" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Target:</label><br>
+ <input id="popupAddMenuItemTarget" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.target" ng-disabled="disableTarget" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Menu Set Code:</label><br>
+ <input id="popupAddMenuItemMenuSetCode" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.menuSetCode" ng-disabled="disableMenuSetCode" maxlength="30" />
+ </div>
+ </td>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Separator:</label><br>
+ <select class="form-field" name="select" ng-model="addFnMenuItem.separatorAsString">
+ <option ng-repeat="separator in separatorStatusOptions" value="{{separator.value}}" ng-selected="{{separator.value}}=={{addFnMenuItem.separator}}" >{{separator.title}}</option>
+ </select>
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b></b></sup>Image Source:</label><br>
+ <input id="popupAddMenuItemImageSrc" type="text" class="fn-ebz-text" ng-model="addFnMenuItem.imageSrc" ng-disabled="disableImageSrc" maxlength="30" />
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="updateFnMenu(addFnMenuItem);">Save</button>
+ <button class="btn btn-small" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
+
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-child-add-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-child-add-confirm.html
new file mode 100644
index 00000000..62f05269
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-child-add-confirm.html
@@ -0,0 +1,25 @@
+<div>
+ <div class="modal-header ng-scope in">
+ <h1><i class="icon-primary-alert"></i></h1>
+ <h2 id="myModalLabel" modal-title="">Confirm</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to add the role function {{msg.roleFun}} to the role for {{msg.role}}. Do you want to continue?
+ </div>
+ <div class="modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button ng-if="!msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleChildRemove(msg.selected,msg.availableRole,msg.roleId);">Yes</button>
+ <button ng-if="msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleChildAdd(msg.selected,msg.availableRole,msg.roleId);">Yes</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-confirm-activation.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-confirm-activation.html
new file mode 100644
index 00000000..7a663cf3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-confirm-activation.html
@@ -0,0 +1,23 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h1><i class="icon-primary-alert"></i></h1>
+ <h2 id="myModalLabel" modal-title="">Confirm</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to {{msg.text}} the {{msg.roleName}} role. Do you want to continue?
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="roleActivate(msg.selected,msg.availableRole);">Ok</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="cancelRoleSwitch(msg)">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-delete-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-delete-confirm.html
new file mode 100644
index 00000000..45e5ddfc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-delete-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="heading-medium" modal-title="">Confrim</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to delete {{msg.roleName}} role. Click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="delRole(msg.availableRole);">Ok</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-add-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-add-confirm.html
new file mode 100644
index 00000000..ff5ac253
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-add-confirm.html
@@ -0,0 +1,25 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h1><i class="icon-primary-alert"></i></h1>
+ <h2 id="myModalLabel" modal-title="">Confirm</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to add the role function {{msg.roleFun}} to the role for {{msg.role}}. Do you want to continue?
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button ng-if="!msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleFunRemove(msg.selected,msg.availableRole,msg.roleId);">Yes</button>
+ <button ng-if="msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleFunAdd(msg.selected,msg.availableRole,msg.roleId);">Yes</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="cancelRoleFunSwitch(msg)">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-role-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-role-del-confirm.html
new file mode 100644
index 00000000..f293152c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-fun-role-del-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Role</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to delete this Role Function. Click 'OK' to continue.
+ </div>
+ <div class="modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="roleFunRemoveRole(msg.roleFunction)">Ok</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-add.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-add.html
new file mode 100644
index 00000000..a6912571
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-add.html
@@ -0,0 +1,32 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Role Function Create</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 145px;">
+
+ <div class="field-group">
+ Name <input id="textinputID-2a" ddh-reset ng-model="roleFun['name']"
+ placeholder="Name" class="span12" type="text">
+ </div>
+ <div class="field-group">
+ Code <input id="textinputID-2a" ddh-reset ng-model="roleFun['code']"
+ placeholder="Code" class="span12" type="text">
+
+ </div>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="save(roleFun);">Create</button>
+ <button class="btn btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-del-confirm.html
new file mode 100644
index 00000000..31109112
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-del-confirm.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Role Function Delete</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to delete this role function, '{{msg.text}}'. Click 'OK' to continue.
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="deleteFun(roleFun);">Ok</button>
+ <button class="btn btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-edit.html
new file mode 100644
index 00000000..ecf69b5a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-function-edit.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="b2b-modal-header">
+ <h2 id="myModalLabel" b2b-modal-title>Role Function Edit</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close" ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body" tabindex="0" role="region" aria-label="Modal header text content" style="height: 145px;">
+ <div class="field-group">
+ Name <input id="textinputID-2a" ng-model="roleFun['name']" placeholder="Name" class="span12" type="text">
+ </div>
+ <div class="field-group">
+ Code <input id="textinputID-2a" ng-model="roleFun['code']" disabled placeholder="Code" class="span12" type="text">
+ </div>
+ </div>
+ <div class="b2b-modal-footer">
+ <div class="cta-button-group">
+ <button class="btn btn-alt btn-medium" type="button" ng-click="save(roleFun);">Save</button>
+ <button class="btn btn-medium" type="button" ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-child-roles-modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-child-roles-modal.html
new file mode 100644
index 00000000..94211773
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-child-roles-modal.html
@@ -0,0 +1,34 @@
+<div>
+ <div class="b2b-modal-header">
+ <br/>
+ <h1 class="heading-medium" id="SelectRole">Select Child Roles</h1>
+ </div>
+ <br/>
+ <div class="b2b-modal-body" tabindex="0" aria-label="Modal header text content" role="region">
+ <table class="striped">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Role</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="role in role.childRoles">
+ <tr>
+ <td>
+ <label ng-click="activateRoleChildConfirmPopUp(roleFunction.selected,roleFunction);" class="btn-switch-label" tabindex="0" role="option">
+ <input type="checkbox" ddh-switches ng-model="roleFunction.selected"
+ size-class="modal-small modal-alert" >
+ </label>
+ </td>
+ <td>{{ roleFunction.name }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class="b2b-modal-footer">
+ <div class="cta-button-group in">
+ <button style="float: right; margin-right: 20px;" class="btn btn-alt btn-small" ng-click="$dismiss('cancel')">Close</button>
+ </div>
+ <br/>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-modal.html
new file mode 100644
index 00000000..c4115c4a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/modals/role-functions-modal.html
@@ -0,0 +1,36 @@
+<div>
+ <div class="b2b-modal-header">
+ <h1 class="heading-medium" id="SelectRole">Select Role Functions</h1>
+
+ </div>
+
+ <div class="b2b-modal-body" tabindex="0" aria-label="Modal header text content" role="region">
+ <table class="striped">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Role Function</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="roleFunction in msg.availableRoleFunctions">
+ <tr>
+ <td>
+ <label class="btn-switch-label" tabindex="0" role="option">
+ <input ng-click="activateRoleConfirmPopUp(roleFunction.selected,roleFunction);" type="checkbox" b2b-switches ng-model="roleFunction.selected" size-class="modal-small modal-alert">
+ </label>
+ </td>
+ <td>{{roleFunction.name}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="b2b-modal-footer">
+ <div class="cta-button-group in">
+ <button style="float: right; margin-right: 20px;"
+ class="btn btn-alt btn-small"
+ ng-click="$dismiss('cancel')">Close</button>
+ </div>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html
new file mode 100644
index 00000000..0b07d6e8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html
@@ -0,0 +1,63 @@
+<div id="page-content">
+ <h1 class="heading-page" id="profileSearch">Role Function</h1>
+
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <div class="field-group">
+ <button class="btn btn-alt btn-medium" type="button"
+ ng-click="addRoleFuncPopUp(rowData);">Create</button>
+ </div>
+ </div>
+ </div>
+ <div class="span12">
+ <div class="form-row">
+ <div style="float: right;">
+ <div class="form-field form-field__small">
+ <input type="text" placeholder="Search role functions" ng-model="searchString" />
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img"
+ aria-label="Please wait while we load your content"></i>
+ </div>
+
+ <div b2b-table class="b2b-table-div" table-data="tableData"
+ search-string="searchString" current-page="currentPage"
+ next-sort="nextSort">
+
+ <table>
+ <thead b2b-table-row type="header">
+ <tr>
+ <th b2b-table-header key="name">Name</th>
+ <th b2b-table-header key="code">Code</th>
+ <th b2b-table-header sortable="false">Edit</th>
+ <th b2b-table-header sortable="false">Delete</th>
+ </tr>
+ </thead>
+ <tbody b2b-table-row type="body" row-repeat="rowData in tableData">
+ <tr>
+ <td b2b-table-body ng-bind="rowData['name']"></td>
+ <td b2b-table-body ng-bind="rowData['code']"></td>
+ <td b2b-table-body>
+ <div style="font-size: 20px;">
+ <a ng-click="saveRoleFuncPopUp(rowData);" class="icon-misc-pen"></a>
+ </div>
+ </td>
+ <td b2b-table-body>
+ <div style="font-size: 20px;">
+ <a href="javascript:void(0)"
+ ng-click="delRoleFuncConfirmPopUp(rowData);"
+ class="icon-misc-trash"></a>
+ </div>
+ </td>
+
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role.html
new file mode 100644
index 00000000..12d8df70
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role.html
@@ -0,0 +1,96 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="Roles">Manage Roles</h1>
+ </div>
+ <div>
+ <h2 class="heading-small-content">Please edit the role details below: </h2>
+ </div>
+
+ <div>
+ <label>*Name: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ <input type="text" ng-model="role.name"
+ maxlength="30" />
+ </label>
+ </div>
+
+ <div>
+ <label>Priority: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ <input type="text" ng-model="role.priority"
+ maxlength="30"/>
+ </label>
+ </div>
+
+ <div>
+ <button style="margin-left: 105px;" class="btn btn-small" onClick="window.location='admin'">Cancel</button>
+ <button class="btn btn-alt btn-small" ng-click="saveRole();">Save</button>
+ </div>
+ <br/>
+ <div ng-if="routeRoleId != 0">
+ <div>
+ <h3 class="heading-small-emphasis">Role Functions</h3>
+ <button class="btn btn-alt btn-small" ng-click="addNewRoleFunctionModalPopup(role.roleFunctions,role.name, role);">Manage Role Functions</button>
+
+ <table class="striped" ng-if="role.roleFunctions.length">
+ <thead>
+ <tr>
+ <th>Role Function Name</th>
+ <th>Remove</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="roleFunction in role.roleFunctions">
+ <tr>
+ <td width="70%">{{ roleFunction.name }}</td>
+ <td width="10%">
+ <div ng-click="removeRoleFunction(roleFunction);"><a href="javascript:void(0)" class="icon-misc-trash"></a></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <br/>
+
+ <div>
+ <h4 class="heading-small-emphasis">Child Roles</h4>
+ <button class="btn btn-alt btn-small" ng-click="addNewChildRoleFunctionModalPopup(role.roleFunctions,role.name, role);">Manage Child Roles</button>
+
+ <table class="striped" ng-if="role.childRoles.length">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Remove?</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="role in role.childRoles">
+ <tr>
+ <td width="70%">{{ role.name }}</td>
+ <td width="10%">
+ <div ng-click="removeChildRole(role);"><a href="javascript:void(0)" class="icon-misc-trash"></a></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <br/>
+ <div>
+ <a href="admin#/role_function_list">Manage Role Functions</a><br><br>
+ </div>
+ <!-- <table class="striped" table-data="availableRoles">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Role</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="availableRole in availableRoles">
+ <tr>
+ <td width="70%">
+ <div ng-click="toggleChildRole(availableRole.selected,availableRole);">
+ <input type="checkbox" ng-model="availableRole.selected" />
+ </div>
+ </td>
+ <td> {{ availableRole.name }} </td>
+ </tr>
+ </tbody>
+ </table> -->
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html
new file mode 100644
index 00000000..a608a0db
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html
@@ -0,0 +1,42 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="Roles">Roles</h1>
+ </div>
+
+ <div>
+ <button type="submit" onClick="window.location='admin#/role/0';" class="btn btn-alt btn-small">Add New Role</button>
+ </div>
+ <h2 class="heading-small">Click on a Role to view its details.</h2>
+
+ <table class="striped" ng-if="availableRoleFunctions" style="width: auto;">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Priority</th>
+ <th>Edit</th>
+ <th>Active?</th>
+ <th>Delete?</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="availableRole in ociavailableRoles">
+ <tr>
+ <td>{{ availableRole.name }}</td>
+ <td>{{ availableRole.priority }}</td>
+ <td>
+ <a href="admin#/role/{{availableRole.id}}" class="icon-misc-pen"></a>
+ </td>
+ <td>
+ <div >
+ <label class="btn-switch-label" tabindex="0" role="option">
+ <input type="checkbox" b2b-switches ng-model="availableRole.active" ng-click="activateRoleConfirmPopUp(availableRole.active,availableRole);" >
+ </label>
+ </div>
+ </td>
+ <td width="10%">
+ <div ng-click="delRoleConfirmPopUp(availableRole);"><a href="javascript:void(0)" class="icon-misc-trash"></a></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/usage.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/usage.html
new file mode 100644
index 00000000..8e411141
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-admin/usage.html
@@ -0,0 +1,43 @@
+<div id="page-content">
+ <div>
+ <h1 class="heading-page" id="Usage">Current Usage</h1>
+ </div>
+
+ <h3 class="heading-small">
+ The following table shows all current user sessions. Click the icon to end a user's session.
+ </h3>
+
+ <!-- A simple table requires no b2b tags -->
+ <table style="width: auto;">
+
+ <thead>
+ <tr>
+ <th key="0" sortable="false" width="10%" align="center">User Id</th>
+ <th key="1" sortable="true" width="10%" align="center">User Name</th>
+ <th key="2" sortable="false" width="10%" align="center">Email</th>
+ <th key="3" sortable="true" width="10%" align="center">Last Access Time (minutes)</th>
+ <th key="4" sortable="false" width="10%" align="center">Time Remaining (minutes)</th>
+ <th key="5" sortable="false" width="10%" align="center">Expire User Session?</th>
+ </tr>
+ </thead>
+
+ <tbody ng-repeat="user in users" style="max-height: 980px;" >
+ <tr>
+ <td width="10%">{{user.id}}</td>
+ <td width="10%">{{user.lastName}}</td>
+ <td width="10%">{{user.email}}</td>
+ <td width="10%">{{user.lastAccess}}</td>
+ <td width="10%">{{user.remaining}}</td>
+ <td width="10%"><div ng-hide="user.delete=='yes'">Current Session</div>
+ <div ng-click="removeSession(user.sessionId);"
+ ng-hide="user.delete=='no'"
+ style="font-size:20px;text-align:center">
+ <a href="javascript:void(0)" class="icon-misc-trash"></a>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+
+ </table>
+
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add-confirm.html
new file mode 100644
index 00000000..edaa0a1e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add-confirm.html
@@ -0,0 +1,25 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h1><i class="icon-primary-alert"></i></h1>
+ <h2 id="myModalLabel" modal-title="">Confirm</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 55px;">
+ You are about to change the role {{msg.roleFun}} Do you want to continue?
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button ng-if="!msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleFunRemove(msg.availableRole,msg.roleId);">Yes</button>
+ <button ng-if="msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleFunAdd(msg.availableRole,msg.roleId);">Yes</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="cancelRoleFunSwitch(msg)">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add.html
new file mode 100644
index 00000000..d662fc01
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-add.html
@@ -0,0 +1,36 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h1 class="heading-medium" id="SelectRole">Select Role Functions</h1>
+
+ </div>
+
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0" aria-label="Modal header text content" role="region">
+ <table class="striped">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Role Function</th>
+ </tr>
+ </thead>
+ <tbody type="body"ng-repeat="roleFunction in msg.availableRoleFunctions">
+ <tr>
+ <td>
+ <label class="btn-switch-label" tabindex="0" role="option">
+ <input type="checkbox" b2b-switches ng-model="roleFunction.selected" ng-click="activateRoleConfirmPopUp(roleFunction.selected,roleFunction);" size-class="modal-small modal-alert">
+ </label>
+ </td>
+ <td>{{roleFunction.name}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button style="float: right; margin-right: 20px;"
+ class="btn btn-alt btn-small"
+ ng-click="$dismiss('cancel')">Close</button>
+ </div>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-del-confirm.html
new file mode 100644
index 00000000..b795d35f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/modals/role-del-confirm.html
@@ -0,0 +1,23 @@
+<div>
+ <div class="b2b-modal-header ng-scope in">
+ <h1><i class="icon-primary-alert"></i></h1>
+ <h2 id="myModalLabel" modal-title="">Confirm</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" tabindex="0"
+ role="region" aria-label="Modal header text content"
+ style="height: 50px;">
+ You are about to delete the role '{{msg.role.name}}'. Do you want to continue?
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button ng-if="!msg.selected" class="btn btn-alt btn-medium" type="button"
+ ng-click="confirmRoleDel(msg.role,msg.roleId);">Yes</button>
+ <button class="btn btn-clear btn-medium" type="button"
+ ng-click="$dismiss('cancel')">Cancel</button>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile.html
new file mode 100644
index 00000000..97bb9aee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-profile/profile.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App profile pages using DS2 look and feel -->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Profile Search</title>
+
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+
+ <!-- B2b Library -->
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+
+ <!-- Page-specific scripts -->
+
+ <script src="app/fusion/scripts/DS2-controllers/profile-route.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds-profile/post-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-profile/self-profile-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-services/ds2-profile/selfProfileService.js"></script>
+ <script src="app/fusion/scripts/DS2-services/profileServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/postSearch.js"></script>
+ <script src="app/fusion/scripts/DS2-services/adminService.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/profile-search-controller-DS2.js"></script>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/all-reports.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/all-reports.html
new file mode 100644
index 00000000..c90f95b4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/all-reports.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Reports</title>
+
+ <!-- Resources -->
+
+
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-gridster/dist/angular-gridster.min.css">
+ <!-- digital-design-library must be loaded late -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/digital-design-library.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <!-- EPSDK App scripts and common services -->
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src= "app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+
+ <!-- Page specific items -->
+ <script src="app/fusion/external/d3/js/d3.js"></script>
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-ui-grid/ui-grid.css">
+ <script src="app/fusion/external/angular-ui-grid/ui-grid.min.js"></script>
+ <script src="./app/fusion/scripts/DS2-services/ds2-raptor-report/raptorReportFactory.js"></script>
+ <script src="./app/fusion/scripts/DS2-services/ds2-raptor-report/stepFormFactory.js"></script>
+ <script src="./app/fusion/scripts/DS2-controllers/ds2-reports/report-search-controller.js"></script>
+ <script src="./app/fusion/scripts/DS2-controllers/ds2-reports/report-run-controller.js"></script>
+ <script src="./app/fusion/scripts/DS2-controllers/ds2-reports/report-step-controller.js"></script>
+ <script src="./app/fusion/scripts/DS2-controllers/ds2-reports/report-import-controller.js"></script>
+ <script src="./app/fusion/scripts/DS2-view-models/ds2-reports/directive/dynamicform.js"></script>
+ <script src="./app/fusion/scripts/DS2-controllers/ds2-reports/report-router.js"></script>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/dynamicform.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/dynamicform.js
new file mode 100644
index 00000000..9064b0dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/dynamicform.js
@@ -0,0 +1,113 @@
+appDS2
+.directive('formBuilder', ['$q', '$parse', '$http', '$templateCache', '$compile', '$document', '$timeout', function ($q, $parse, $http, $templateCache, $compile, $document, $timeout) {
+ return {
+ restrict: 'E', // supports using directive as element only
+ scope:{
+ ngModel: '=',
+ ngFormFields: '=',
+ ngNumFormCols: '=',
+ ngTriggerMethod: '=',
+ ngShowFieldId: '='
+ },
+ link: function ($scope, element, attrs) {
+ $scope.element=element;
+ $scope.datetimeformat = "MM/dd/yyyy hh:mm a";
+ console.log("$scope");
+ console.log($scope);
+ $scope.buildField = function (field, parentElement) {
+ var x = '';
+ if(field.visible) {
+ if (field.fieldType === 'LIST_MULTI_SELECT') {
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br>'+
+ '<div class="select2-container ebz-listbox form-field" style="height:100px;" tabindex="0" >'+
+ '<label ng-repeat="item in ngModel.'+field.fieldId+'" style="display:block;">'+
+ '<input type="checkbox" style="margin-top: 10px;" ng-model="item.defaultValue" ng-change="triggerFormFields('+field.triggerOtherFormFields+')" att-checkbox title="{{item.title}}"/> {{item.title}}<br/>'+
+ '</label>'+
+ '</div>');
+ } else if (field.fieldType === 'LIST_BOX') {
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br> <div class="form-field" att-select="formFieldLuValues.'+field.fieldId+'" ng-model="ngModel.'+field.fieldId+'" ng-change="triggerFormFields('+field.triggerOtherFormFields+')"></div>');
+ } else if((field.fieldType === 'text' || field.fieldType === 'TEXT') && field.validationType === 'DATE'){
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br> <input id="'+field.fieldId+'" type="text" ng-model="ngModel.'+field.fieldId+'" tabindex="0" ng-change="triggerFormFields('+field.triggerOtherFormFields+')" att-datepicker>');
+ } else if((field.fieldType === 'text' || field.fieldType === 'TEXT') && field.validationType === 'TIMESTAMP_MIN'){
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br> <input id="'+field.fieldId+'" type="text" date-format="datetimeformat" ng-model="ngModel.'+field.fieldId+'" tabindex="0" ng-change="triggerFormFields('+field.triggerOtherFormFields+')" att-date-time-picker>');
+ } else if(field.fieldType === 'text' || field.fieldType === 'TEXT'){
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br> <input type="text" class="form-field" ng-model="ngModel.'+field.fieldId+'" maxlength="'+field.length+'" ng-blur="triggerFormFields('+field.triggerOtherFormFields+')" />');
+ } else if(field.fieldType === 'CHECK_BOX'){
+ x = angular.element('<label><i>'+field.fieldDisplayName+'<span ng-show="ngShowFieldId"> [ '+field.fieldId+' ] </span>:</i></label><br> <input type="checkbox" ng-model="ngModel.'+field.fieldId+'" tabindex="0" ng-change="triggerFormFields('+field.triggerOtherFormFields+')" att-checkbox>');
+ }
+ }
+ parentElement.append(x);
+ $compile(x)($scope);
+ };
+ $scope.buildForm = function() {
+ // create elements <table> and a <tbody>
+ var tbl = angular.element("<table></table>");
+ var tblBody = angular.element("<tbody></tbody>");
+ var row = angular.element("<tr></tr>");
+
+ var ngFormFieldsLength = $scope.ngFormFields.length;
+
+ for (var j = 0; j < ngFormFieldsLength; j++) {
+ var cell = angular.element("<td style='padding: 5px;'></td>");
+ $scope.buildField($scope.ngFormFields[j],cell);
+ row.append(cell);
+
+ if((j!=0 && (j+1)%$scope.ngNumFormCols==0) || j==(ngFormFieldsLength-1)){
+ tblBody.append(row);
+ row = angular.element("<tr></tr>");
+ }
+ }
+ tbl.append(tblBody);
+ angular.element($scope.element).html('');
+ $scope.element.append(tbl);
+ };
+
+
+ $scope.formFieldLuValues = {};
+ $scope.getEBZFormat = function() {
+ if($scope.ngFormFields && $scope.ngFormFields.length>0){
+ $scope.ngFormFields.forEach(function(formField) {
+ if(formField.fieldType === 'LIST_MULTI_SELECT') {
+ $scope.ngModel[formField.fieldId]= [];
+ if(formField.formFieldValues && formField.formFieldValues.length>0){
+ formField.formFieldValues.forEach(function(entry,i) {
+ $scope.ngModel[formField.fieldId].push({ index: i, value: entry.id, title: entry.name, defaultValue: entry.defaultValue});
+ });
+ }
+ } else if(formField.fieldType==='LIST_BOX') {
+ $scope.formFieldLuValues[formField.fieldId]= [];
+ if(formField.formFieldValues && formField.formFieldValues.length>0){
+ formField.formFieldValues.forEach(function(entry,i) {
+ $scope.formFieldLuValues[formField.fieldId].push({ index: i, value: entry.id, title: entry.name});
+ if(entry.defaultValue){
+ $scope.ngModel[formField.fieldId]={ index: i, value: entry.id, title: entry.name};
+ }
+ });
+ }
+ } else if(formField.fieldType === 'text' || formField.fieldType === 'TEXT' ||
+ formField.validationType === 'DATE' || formField.validationType === 'TIMESTAMP_MIN') {
+ if(formField.formFieldValues && formField.formFieldValues.length>0){
+ $scope.ngModel[formField.fieldId]=formField.formFieldValues[0].id;
+ }
+ }
+ });
+ }
+ };
+
+ $scope.$watch("ngFormFields",function(newValue,oldValue) {
+ if($scope.ngFormFields){
+ $scope.getEBZFormat();
+ $scope.buildForm();
+ }
+ });
+
+ $scope.triggerFormFields = function(triggerFlag) {
+ if(triggerFlag){
+ $scope.element.html('Loading...');
+ $scope.ngTriggerMethod();
+ }
+ };
+
+ }
+ };
+ }]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/step-form-directive.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/step-form-directive.js
new file mode 100644
index 00000000..a64309bf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/directive/step-form-directive.js
@@ -0,0 +1,14 @@
+appDS2
+.directive('stepForm', function($compile,$http, stepFormFactory) {
+ return {
+ restrict: 'AE',
+
+ // scope: {
+ // jsonSource: '='
+ // },
+ link: function(scope, elem, attrs) {
+ var jsonSrcName = "app/fusionapp/scripts/view-models/wz_steps/json/step1.json";
+ stepFormFactory.renderForm(jsonSrcName, elem, scope);
+ }
+ }
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-del-confirm.html
new file mode 100644
index 00000000..da255bbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-del-confirm.html
@@ -0,0 +1,26 @@
+<div style="height:400px">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Remove Report</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+ <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">The selected report will be removed. Do you want to continue</label>
+ </div>
+
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="ok()">OK</button>
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-formfield-del-confirm.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-formfield-del-confirm.html
new file mode 100644
index 00000000..7bdf5a29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-formfield-del-confirm.html
@@ -0,0 +1,26 @@
+<div style="height:400px">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Remove Formfield</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+ <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">The selected formfield {{tempFieldId}} will be removed. Do you want to continue</label>
+ </div>
+
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="ok()">OK</button>
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-col-edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-col-edit.html
new file mode 100644
index 00000000..ad081991
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-col-edit.html
@@ -0,0 +1,125 @@
+<style>
+#columnEditTable table tbody td {
+ border: none;
+}
+
+#columnEditTable table tbody tr {
+ border: none;
+}
+
+.colTableLeftColumn {
+ width: 45%;
+ text-align: right;
+ vertical-align:middle;
+}
+
+.colTableInput {
+ width:220px;
+}
+
+#columnEditTable .selectWrap{
+ width:220px;
+}
+</style>
+
+<div style="height: 700px;">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Report Column - Edit </h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+<!-- <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">The selected report will be removed. Do you want to continue</label>
+ </div> -->
+ <div id="columnEditTable">
+ <table class="striped">
+<!-- <caption><span>Table caption</span></caption> -->
+<!-- <thead>
+ <tr>
+ <th>Column ID:</th>
+ <th>Name</th>
+ <th>ID</th>
+ <th>Edit</th>
+ </tr>
+ </thead> -->
+ <tbody>
+ <tr>
+ <td class="colTableLeftColumn">Column ID:</td>
+ <td>{{columnEditData.colId}}</td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Display Name:</td>
+ <td><input type="text" name="displayName" ng-model="colName.value" class="colTableInput"></td>
+ </tr>
+
+<!-- <tr>
+ <td class="colTableLeftColumn">Display Width (px):</td>
+ <td><input type="text" name="displayWidth" ng-model="displayWidth" class="colTableInput"></td>
+ </tr> -->
+
+ <tr>
+ <td class="colTableLeftColumn">Display Alignment: </td>
+ <td>
+ <select name="displayAlignment" b2b-dropdown ng-model="selectedDisplayAlignment.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in displayAlignmentOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Display Header Alignment:</td>
+ <td>
+ <select name="displayHeaderAlignment" b2b-dropdown ng-model="selectedDisplayHeaderAlignment.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in displayAlignmentOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Sortable:</td>
+ <td>
+ <select name="sortable" b2b-dropdown ng-model="sortable.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in ynOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Visible:</td>
+ <td>
+ <select name="visible" b2b-dropdown ng-model="visible.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in ynOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+<!-- <tr>
+ <td class="colTableLeftColumn">Drill-down Link:</td>
+ <td>
+ <select name="drillDown" b2b-dropdown ng-model="selectedDrillDownLink.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in drillDownOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr> -->
+
+
+ </tbody>
+ </table>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="save()">Save</button>
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html
new file mode 100644
index 00000000..c88eb596
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-formfield-edit.html
@@ -0,0 +1,149 @@
+<style>
+#columnEditTable table tbody td {
+ border: none;
+}
+
+#columnEditTable table tbody tr {
+ border: none;
+}
+
+.colTableLeftColumn {
+ width: 45%;
+ text-align: right;
+ vertical-align:middle;
+}
+
+.colTableInput {
+ width:220px;
+}
+
+#columnEditTable .selectWrap{
+ width:220px;
+}
+</style>
+
+<div style="height: 700px;">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">Report Form Field - Edit</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+
+<!-- <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">The selected report will be removed. Do you want to continue</label>
+ </div> -->
+ <div id="columnEditTable">
+ <table class="striped">
+<!-- <caption><span>Table caption</span></caption> -->
+<!-- <thead>
+ <tr>
+ <th>Column ID:</th>
+ <th>Name</th>
+ <th>ID</th>
+ <th>Edit</th>
+ </tr>
+ </thead> -->
+ <tbody>
+<!-- <tr>
+ <td class="colTableLeftColumn">Field ID:</td>
+ <td>{{formFieldEditData.fieldId}}</td>
+ </tr> -->
+
+ <tr>
+ <td class="colTableLeftColumn">Field Name:</td>
+ <td><input type="text" name="displayName" ng-model="fieldName.value" class="colTableInput"></td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Field Type: </td>
+ <td>
+ <select name="displayAlignment" b2b-dropdown ng-model="selectedFieldType.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in fieldTypeOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">Visible:</td>
+ <td>
+ <select name="displayHeaderAlignment" b2b-dropdown ng-model="selectedVisible.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in ynOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="colTableLeftColumn">SQL as Default Value:</td>
+ <td>
+ <label for="checkbox1" class="checkbox">
+ <input id="checkbox1" type="checkbox" ng-model="sqlDefaultValueSelected.value" /><i class="skin"></i><span></span>
+ </label>
+ </td>
+ </tr>
+
+ <tr ng-hide="sqlDefaultValueSelected.value">
+ <td class="colTableLeftColumn">Default Value:</td>
+ <td><input type="text" name="defaultValue" ng-model="defaultValue.value" class="colTableInput"></td>
+ </tr>
+
+
+ <tr ng-show="sqlDefaultValueSelected.value">
+ <td class="colTableLeftColumn">Default SQL:</td>
+ <td>
+ <textarea b2b-reset b2b-dragon-input b2b-reset-textarea ng-model="fieldDefaultSQL.value" style="height:80px">
+ </textarea>
+ </td>
+ <td>
+ <p><button ng-click="formFieldVerifySQL(fieldDefaultSQL.value)" class="btn btn-alt btn-small">Verify</button></p>
+ </td>
+ </tr>
+
+<!-- <tr>
+ <td class="colTableLeftColumn">Verify Field Value As: </td>
+ <td>
+ <select name="displayAlignment" b2b-dropdown ng-model="selectedVerifyFieldValue.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in verifyFieldValueOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr> -->
+
+ <tr>
+ <td class="colTableLeftColumn">SQL Generating Custom List of Values:</td>
+ <td>
+ <textarea b2b-reset b2b-dragon-input b2b-reset-textarea ng-model="fieldSqlContent.value" style="height:80px">
+ </textarea>
+ </td>
+ <td>
+ <p><button ng-click="formFieldVerifySQL(fieldSqlContent.value)" class="btn btn-alt btn-small">Verify</button></p>
+ </td>
+ </tr>
+
+<!-- <tr>
+ <td class="colTableLeftColumn">Drill-down Link:</td>
+ <td>
+ <select name="drillDown" b2b-dropdown ng-model="selectedDrillDownLink.value" placeholder-text="Select">
+ <option b2b-dropdown-list option-repeat="d in drillDownOptions" value="{{d.value}}">{{d.text}}</option>
+ </select>
+ </td>
+ </tr> -->
+
+
+ </tbody>
+ </table>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button" ng-click="save()">Save</button>
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="cancel()">Cancel</button>
+ </div>
+
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html
new file mode 100644
index 00000000..a7955cad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/modal/report-wizard-test-run-sql.html
@@ -0,0 +1,62 @@
+<style>
+.colTableLeftColumn {
+ width: 45%;
+ text-align: right;
+ vertical-align:middle;
+}
+
+.colTableInput {
+ width:220px;
+}
+
+#columnEditTable .selectWrap{
+ width:220px;
+}
+</style>
+
+<div style="height: 700px;">
+ <div class="b2b-modal-header ng-scope in">
+ <h2 id="myModalLabel" modal-title="">SQL Test Run - {{isError?'Failed':'Executed'}}</h2>
+ <div class="corner-button in">
+ <button type="button" class="close" aria-label="Close"
+ ng-click="$dismiss('cancel')"></button>
+ </div>
+ </div>
+ <div class="b2b-modal-body ng-scope ng-isolate-scope in" style="margin-bottom: -50px;">
+ <form name="workflowForm" class="css-form" novalidate>
+<!-- <div class="form-row input-emphasized-field">
+ <label class="span12 input-emphasized" for="textinputID-2a">The selected report will be removed. Do you want to continue</label>
+ </div> -->
+ <div>
+
+ <div ng-show="isError">
+ <h2>Error Message:</h2><br>
+ <p>{{errormessage}}</p>
+ <h2>Stack Trace:</h2><br>
+ <p>{{stacktrace}}</p>
+
+ </div>
+ <table class="striped">
+ <thead>
+ <tr>
+ <th ng-repeat="colName in queryData.reportDataColumns">{{colName}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="rowData in queryData.reportDataRows">
+ <td ng-repeat="keyName in queryData.reportDataColumns">{{rowData[keyName]}}</td>
+ </tr>
+
+ </tbody>
+ </table>
+ </div>
+ <div class="b2b-modal-footer ng-scope ng-isolate-scope in">
+ <div class="cta-button-group in">
+ <button class="btn btn-alt btn-small" type="button"
+ ng-click="close()">Close</button>
+ </div>
+ </div>
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-import.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-import.html
new file mode 100644
index 00000000..cd64b09f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-import.html
@@ -0,0 +1,14 @@
+<div id="page-content">
+
+<h1 class="heading-page">Report Import</h1>
+
+ <h2 id="myModalLabel" modal-title="">Import XML</h2>
+
+<div style="margin-top:5px; color:red;" ng-if="errorMessage&&errorMessage.length>0">
+ <h2 id="myModalLabel" modal-title="" style="color:red;">{{errorMessage}}</h2>
+</div>
+ <textarea b2b-reset b2b-dragon-input b2b-reset-textarea ng-model="xmlContent" class="span12" id="textareaXmlContent" style="height:480px;margin-top:5px;"></textarea>
+
+ <button style="margin-top:5px;" type="submit" class="btn btn-alt btn-small" ng-click="importXML();">Import</button>
+
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-run.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-run.html
new file mode 100644
index 00000000..82b7e878
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-run.html
@@ -0,0 +1,91 @@
+<style>
+table tbody td {
+ border: none;
+}
+
+table tbody tr {
+ border: none;
+}
+
+table tbody{
+ border: none;
+}
+
+table {
+ border: none;
+}
+
+.grid {
+ width: 100%;
+ height: 400;
+}
+.no-rows {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ background: rgba(0, 0, 0, 0.4);
+}
+
+.no-rows .msg {
+ opacity: 1;
+ position: absolute;
+ top: 20%;
+ left: 20%;
+ width: 60%;
+ height: 50%;
+ line-height: 200%;
+ background-color: #eee;
+ border-radius: 4px;
+ border: 1px solid #555;
+ text-align: center;
+ font-size: 24px;
+ display: table;
+}
+
+.no-rows .msg span {
+ display: table-cell;
+ vertical-align: middle;
+}
+.grid .ui-grid-header-cell {
+ text-align:center;
+}
+body {
+ font-size:13px;
+}
+</style>
+
+<div id="page-content">
+ <!-- <h1 class="heading2">{{reportData.reportName}} -->
+ <h1 class="heading-page">{{reportData.reportHeading}}
+ <a ng-href="{{reportEditURL}}" ng-show="reportData.allowEdit" class="icon-edit" style="font-size:20px;"></a>
+
+ &nbsp;&nbsp;&nbsp;<a ng-href="{{reportChartURL}}" ng-show="reportData.allowEdit && reportData.chartWizardAvailable" class="icon-bar-chart-vertical" style="font-size:20px;"></a>
+ &nbsp;&nbsp;&nbsp;<span ng-show="reportData.allowEdit && showFormFields" ><input type="checkbox" ng-model="showFormFieldIds" ng-true-value="Hide_IDs" ng-false-value="Show_IDs" att-toggle-main></span>
+
+ <!-- &nbsp;&nbsp;&nbsp;<a ng-href="{{reportChartURLNew}}" ng-show="reportData.allowEdit" class="icon-bar-chart-horizontal" style="font-size:20px;"></a> -->
+ </h1>
+
+ <h3 class="heading3">{{reportData.reportSubTitle}} </h3>
+
+ <div ng-show="isInProgress" style="font-size:50px;color:#2ca02c">Loading...</div>
+
+ <form ng-show="showFormFields" class="row section-row" style="margin: 10px">
+ <form-builder ng-form-fields="reportData.formFieldList" ng-show-field-id="showFormFieldIds" ng-num-form-cols="reportData.numFormCols" ng-model="formFieldSelectedValues" ng-trigger-method="triggerOtherFormFields"></form-builder>
+ <br><br>
+ <button type="submit" style="width: 90px; height:35px;margin-top:20px; margin-left:5px;" class="btn btn-alt btn-small" ng-click="runReport()">Run</button>
+ </form>
+ <a type="submit" ng-show="showBackButton" style="margin: 10px" ng-href="report.htm#/report_run/{{parentReportUrlParams}}" att-button btn-type="primary" size="small" title='Back'>Back</a>
+ <iframe id="chartiframe" ng-show="showChart" width="100%" height="450px" style="border: none" scrolling="no"></iframe>
+ <div id="errorDiv"></div>
+ <div ng-if="showGrid">
+ <div id="grid1" ui-grid="gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-resize-columns class="grid" style="height: {{gridHeight}}">
+ <div class="no-rows" ng-show="!gridOptions.data.length">
+ <div class="msg">
+ <span>{{reportData.message}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- <a type="submit" ng-show="showBackButton" style="margin: 10px" ng-href="report.htm#/report_run/{{parentReportUrlParams}}" att-button btn-type="primary" size="small" title='Back'>Back</a> -->
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html
new file mode 100644
index 00000000..7524acca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/report-search.html
@@ -0,0 +1,54 @@
+<div id="page-content" style="margin-right:-230px;">
+<style>
+.grid {
+ width: 100%;
+ height: 400px;
+}
+.grid .ui-grid-header-cell {
+ text-align:center;
+}
+.icon-add-widget:before {
+ content: "\e717";
+}
+.ui-grid-icon-angle-down {
+ margin-top: 5px;
+}
+body {
+ font-size:13px;
+}
+</style>
+<h1 class="heading-page">Report search</h1>
+<br>
+<div >
+<label style="float:left;margin-top:10px; margin-right: 5px;">Report Id:</label>
+
+<div class="form-row" style="float:left; width:160px;">
+ <select id="dropdown1" name="dropdown1" b2b-dropdown placeholder-text="Select" ng-model="operatorRepId.index">
+ <option b2b-dropdown-list option-repeat="d in operatorsRepId" value="{{d.index}}">{{d.text}}</option>
+ </select>
+</div>
+
+<div class="form-field form-field__glued pull-left size-onefifth" style="float:left; width:160px;margin-right: 40px;">
+ <input ng-model="reportId" type="text" placeholder="Search value?" style="margin-top:5px;width:160px;">
+</div>
+
+<label class="pull-left" style="float:left;margin-top: 10px;margin-right: 5px;">Report Name:</label>
+
+<div class="form-row" style="float:left; width:160px;">
+ <select id="dropdown2" name="dropdown2" b2b-dropdown placeholder-text="Select" ng-model="operatorRepName.index">
+ <option b2b-dropdown-list option-repeat="e in operatorsRepName" value="{{e.index}}">{{e.text}}</option>
+ </select>
+</div>
+
+<div class="form-field form-field__glued pull-left size-onefifth" style="width:13% !important;">
+ <input ng-model="reportName" type="text" placeholder="Search value?" style="margin-top:5px;width:160px;">
+</div>
+
+<div>
+ <button style="margin-left:50px;margin-top:4px;" type="submit" class="btn btn-alt btn-small" ng-click="runReport();">Submit</button>
+</div>
+</div>
+<br>
+
+<div id="grid1" ui-grid="gridOptions" ui-grid-pagination class="grid">
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step1.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step1.json
new file mode 100644
index 00000000..091d47e5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step1.json
@@ -0,0 +1,218 @@
+{
+ "step" : "1",
+ "content": {
+ "title": "Step 1 : Report Definition",
+ "sections": [
+ {
+ "title": "",
+ "elements": [
+ {
+ "input": "hidden",
+ "name": "proj_id",
+ "displayName": "Project Id",
+ "defaultValue": ""
+ },
+ {
+ "input": "text",
+ "name": "reportName",
+ "displayName": "Report Name:",
+ "defaultValue": ""
+ },
+ {
+ "input": "textarea",
+ "name": "reportDescr",
+ "displayName": "Report Description:",
+ "style":"width:300px;height:80px;"
+ },
+ {
+ "input": "select",
+ "name": "reportType",
+ "ngModelName":"selectedReportType.value",
+ "displayName": "Report Type: ",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"reportTypes",
+ "options":[{"value":"linear", "text":"Linear"}]
+ },
+ {
+ "input": "select",
+ "name": "dataSource",
+ "ngModelName":"selectedDataSource.value",
+ "displayName": "Data Source:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"DataSources",
+ "options":[{"value":"local", "text":"Local"}]
+ },
+ {
+ "input": "textarea",
+ "name": "formHelpText",
+ "displayName": "Form Help Text:",
+ "style":"width:300px;height:80px;"
+ },
+ {
+ "input": "select",
+ "name": "pageSize",
+ "ngModelName":"selectedPageSize.value",
+ "displayName": "Page Size:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"PageSizes",
+ "options":[ {"value":"10", "text":"10"},
+ {"value":"20", "text":"20"},
+ {"value":"50", "text":"50"},
+ {"value":"100", "text":"100"},
+ {"value":"500", "text":"500"}
+ ]
+ },
+ {
+ "input": "checkboxGroup",
+ "name":"displayArea",
+ "displayName": "Display Area:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "checkboxes":[{"value":"homeSelected.value", "text":"HOME"},
+ {"value":"customerSelected.value", "text":"CUSTOMER"},
+ {"value":"reportsSelected.value", "text":"REPORTS"}
+ ]
+ },
+
+ {
+ "input": "checkboxGroup",
+ "name": "hideFormFieldsAfterRun",
+ "displayName": "Hide Form Fields After Run:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"HideFormFieldsAfterRun",
+ "checkboxes":[{"value":"hideFormFieldsAfterRunSelected.value", "text":""}
+ ]
+ },
+ {
+ "input": "select",
+ "name": "maxRowsInExcelCSVDownload",
+ "ngModelName":"selectedMaxRowsInExcelCSVDownload.value",
+ "displayName": "Max Rows in Excel/CSV Download:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"PageSizes",
+ "options":[{"value":"500","text":"500"},{"value":"1000","text":"1000"},{"value":"2000","text":"2000"},{"value":"3000","text":"3000"},{"value":"4000","text":"4000"},{"value":"5000","text":"5000"},{"value":"10000","text":"10000"},{"value":"15000","text":"15000"},{"value":"20000","text":"20000"},{"value":"25000","text":"25000"},{"value":"30000","text":"30000"},{"value":"35000","text":"35000"},{"value":"40000","text":"40000"},{"value":"45000","text":"45000"},{"value":"50000","text":"50000"},{"value":"65000","text":"65000"}]
+ },
+ {
+ "input": "select",
+ "name": "frozenColumns",
+ "ngModelName":"selectedFrozenColumns.value",
+ "displayName": "Columns to be Frozen:",
+ "defaultValue": "",
+ "action": "",
+ "action_img": "",
+ "optionsName":"frozenColumnsOptions",
+ "options":[{"value":"0","text":"0"},{"value":"1","text":"1"},{"value":"2","text":"2"},{"value":"3","text":"3"},{"value":"4","text":"4"}]
+ },
+ {
+ "input": "select",
+ "name": "dataGridAlign",
+ "ngModelName":"selectedDataGridAlign.value",
+ "displayName": "Data Grid Align:",
+ "defaultValue": "",
+ "action": "",
+ "action_img": "",
+ "optionsName":"selectedDataGridAlignOptions",
+ "options":[{"value":"left","text":"Left"},{"value":"right","text":"Right"},{"value":"center","text":"Center"}]
+ },
+ {
+ "input": "textarea",
+ "name": "emptyMessage",
+ "displayName": "Empty Message:",
+ "style":"width:300px;height:80px;"
+ },
+ {
+ "input": "select",
+ "name": "dataContainerHeight",
+ "ngModelName":"selectedDataContainerHeight.value",
+ "displayName": "Height of the Data Container:",
+ "defaultValue": "",
+ "action": "",
+ "action_img": "",
+ "optionsName":"dataContainerHeightOptions",
+ "options":[{"value":"200","text":"200%"},{"value":"190","text":"190%"},{"value":"180","text":"180%"},{"value":"170","text":"170%"},{"value":"160","text":"160%"},{"value":"150","text":"150%"},{"value":"140","text":"140%"},{"value":"130","text":"130%"},{"value":"120","text":"120%"},{"value":"110","text":"110%"},{"value":"100","text":"100%"},{"value":"90","text":"90%"},{"value":"80","text":"80%"},{"value":"70","text":"70%"},{"value":"60","text":"60%"},{"value":"50","text":"50%"},{"value":"40","text":"40%"},{"value":"30","text":"30%"},{"value":"20","text":"20%"},{"value":"10","text":"10%"}]
+ },
+ {
+ "input": "select",
+ "name": "dataContainerWidth",
+ "ngModelName":"selectedDataContainerWidth.value",
+ "displayName": "Width of the Data Container:",
+ "defaultValue": "",
+ "action": "",
+ "action_img": "",
+ "optionsName":"dataContainerWidthOptions",
+ "options":[{"value":"200","text":"200%"},{"value":"190","text":"190%"},{"value":"180","text":"180%"},{"value":"170","text":"170%"},{"value":"160","text":"160%"},{"value":"150","text":"150%"},{"value":"140","text":"140%"},{"value":"130","text":"130%"},{"value":"120","text":"120%"},{"value":"110","text":"110%"},{"value":"100","text":"100%"},{"value":"90","text":"90%"},{"value":"80","text":"80%"},{"value":"70","text":"70%"},{"value":"60","text":"60%"},{"value":"50","text":"50%"},{"value":"40","text":"40%"},{"value":"30","text":"30%"},{"value":"20","text":"20%"},{"value":"10","text":"10%"}]
+ },
+ {
+ "input": "checkboxGroup",
+ "name": "displayOptions",
+ "displayName": "Display Options:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "checkboxes":[{"value":"hideFormFieldsSelected.value", "text":"Hide Form Fields"},
+ {"value":"hideChartSelected.value", "text":"Hide Chart"},
+ {"value":"hideReportDataSelected.value", "text":"Hide Report Data"},
+ {"value":"hideExcelSelected.value", "text":"Hide Excel"},
+ {"value":"hidePdfSelected.value", "text":"Hide PDF"}
+ ]
+ },
+ {
+ "input": "checkboxGroup",
+ "name":"runtimeColSort",
+ "displayName": "Disable column sort at runtime:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "checkboxes":[{"value":"runtimeColSortDisabled.value", "text":""}
+ ]
+ },
+ {
+ "input": "select",
+ "name": "runtimeFormNumberColumns",
+ "ngModelName":"selectedNumFormCols.value",
+ "displayName": "Run-time Form Number Columns:",
+ "defaultValue": "no",
+ "action": "",
+ "action_img": "",
+ "optionsName":"runtimeFormNumberColumns",
+ "options":[ {"value":"1", "text":"1"},
+ {"value":"2", "text":"2"},
+ {"value":"3", "text":"3"},
+ {"value":"3", "text":"4"}
+ ]
+ },
+ {
+ "input": "text",
+ "name": "reportTitle",
+ "displayName": "Report Title:",
+ "defaultValue": ""
+ },
+ {
+ "input": "text",
+ "name": "reportSubTitle",
+ "displayName": "Report Subtitle:",
+ "defaultValue": ""
+ }
+ ]
+
+ },
+ {
+ "title": "finalButton",
+ "submitAction" : "",
+ "next":"Microservice Config",
+ "previous":"none"
+ }
+ ]
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step2.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step2.json
new file mode 100644
index 00000000..ca01985d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step2.json
@@ -0,0 +1,34 @@
+{
+ "step" : "2",
+ "content": {
+ "title": "Step 2 : Report SQL",
+ "sections": [
+ {
+ "title": "",
+ "elements": [
+ {
+ "input": "textarea",
+ "spanOverTwoColumns":"true",
+ "name": "sqlScript",
+ "displayName": "SQL script:",
+ "defaultValue":"SELECT ",
+ "style":"width: 600px; height: 400px"
+ }
+ ],
+ "buttons": [
+ {
+ "text":"Validate/Test Run SQL",
+ "value":"next",
+ "ngFunction":"testRunSql()"
+ }]
+
+ },
+ {
+ "title": "finalButton",
+ "submitAction" : "",
+ "next":"Microservice Config",
+ "previous":"none"
+ }
+ ]
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step3.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step3.json
new file mode 100644
index 00000000..9ea9b6f4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step3.json
@@ -0,0 +1,19 @@
+{
+ "step" : "3",
+ "content": {
+ "title": "",
+ "sections": [
+ {
+ "title": "",
+ "elements": [
+ ]
+ },
+ {
+ "title": "finalButton",
+ "submitAction" : "",
+ "next":"Microservice Config",
+ "previous":"none"
+ }
+ ]
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step4.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step4.json
new file mode 100644
index 00000000..971a0cf3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step4.json
@@ -0,0 +1,25 @@
+{
+ "step" : "4",
+ "content": {
+ "title": "",
+ "sections": [
+ {
+ "title": "",
+ "elements": [
+ ],
+ "buttons": [
+ {
+ "text":"Add",
+ "value":"add",
+ "ngFunction":"addNewFormField()"
+ }]
+ },
+ {
+ "title": "finalButton",
+ "submitAction" : "",
+ "next":"Microservice Config",
+ "previous":"none"
+ }
+ ]
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step5.json b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step5.json
new file mode 100644
index 00000000..e1675cde
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/json/step5.json
@@ -0,0 +1,28 @@
+{
+ "step" : "5",
+ "last_step": true,
+ "hideSaveButton":true,
+ "hideBackButton":true,
+ "content": {
+ "title": "Step 5 : Run",
+ "sections": [
+ {
+ "elements": [
+ ],
+ "buttons": [
+ {
+ "text":"Run Report",
+ "value":"next",
+ "ngFunction":"RunCurrentReport()"
+ }]
+ },
+ {
+ "title": "finalButton",
+ "submitAction" : "",
+ "next":"Microservice Config",
+ "previous":"none"
+ }
+ ]
+
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html
new file mode 100644
index 00000000..5767afb2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-reports/wz_steps/report-step.html
@@ -0,0 +1,101 @@
+<!-- <link rel="stylesheet" type="text/css" href="static/fusion/raptor/css/raptor.css"> -->
+<style>
+#stepView table tbody td {
+ border: none;
+}
+
+#stepView table tbody tr {
+ border: none;
+}
+
+
+.selectWrap {
+ width: 300px;
+}
+.tdLeftColumn {
+ text-align: right;
+ vertical-align:middle;
+}
+</style>
+
+<div id="page-content">
+<h1 class="heading-page">Report Wizard</h1>
+
+
+
+<!-- <h1 id="tabs---promo">Tabs - Promo</h1>
+<button class="btn btn-secondary btn-small" ng-click="gTabs[3].disabled = !gTabs[3].disabled">{{gTabs[3].disabled?'Enable':'Disable'}}</button> - Toggle 4th (Features) Tab
+<br><br> -->
+ <b2b-tabset tab-id-selected="activeTabsId">
+ <b2b-tab ng-repeat="tab in gTabs" tab-item="tab"
+ id="{{tab.uniqueId}}" aria-controls="{{tab.tabPanelId}}"
+ ng-disabled="tab.disabled">
+ {{tab.title}}
+ </b2b-tab>
+ </b2b-tabset>
+<br><br>
+<!-- <select ng-model="prj"
+ ng-options="item.projectName for item in allProjects track by item.id" data-ng-init="getAllProjects()"
+ ng-change="selectAction();">
+ <option value="">Select project</option>
+</select>
+
+<a ng-click="createAction()" class="pointer">Create Project</a> -->
+
+<input type="hidden" name="project_id" ng-model="project_id" value = ""/>
+
+<div id="stepViewColumn" ng-show = "isColumnStep">
+ <h1>Step 3 : Columns</h1>
+ <table class="striped">
+ <thead>
+ <tr>
+ <th>No</th>
+ <th>Column Name</th>
+ <th>ID</th>
+ <th>Edit</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat = "rowData in colTableRowData">
+ <td>{{$index+1}}</td>
+ <td>{{rowData.name}}</td>
+ <td>{{rowData.id}}</td>
+ <td><a ng-click="openColumnPopup(rowData)" class="icon-misc-pen"></a></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<div id="stepViewFormField" ng-show = "isFormFieldStep">
+ <h1>Step 4 : Form Fields</h1>
+ <table class="striped">
+ <thead>
+ <tr>
+ <th>No</th>
+ <th>Field Name</th>
+ <th>Edit</th>
+ <th>Delete</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat = "rowData in formFieldData">
+ <td>{{$index+1}}</td>
+ <td>{{rowData.name}}[{{rowData.id}}]</td>
+<!-- <td>id</td> -->
+ <td><a ng-click="openFormFieldPopup(rowData)" class="icon-misc-pen"></a></td>
+ <td><a ng-click="deleteFormField(rowData)" class="icon-misc-trash"></a></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<div id="stepView">
+<!-- <step-form ng-model="jsonSrcName" renderForm="changeme"></step-form> -->
+</div>
+
+
+<!-- <select id="dropdown1" name="dropdown1" b2b-dropdown placeholder-text="Select" ng-model="selectedReportType.value">
+ <option b2b-dropdown-list option-repeat="d in reportTypes" value="{{d.value}}">{{d.text}}</option>
+</select>
+<h1>{{selectedReportType.value}}</h1> -->
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools-list.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools-list.html
new file mode 100644
index 00000000..b94b5c08
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools-list.html
@@ -0,0 +1,32 @@
+<div id="page-content">
+ <h1 class="heading-page">Drools List</h1>
+ <div id="droolsTable" title="Drools List">
+ <table class="striped" table-data="tableData">
+ <thead>
+ <tr>
+ <th>Drools File Name</th>
+ <th>Class Name</th>
+ <th>Run Rule</th>
+ </tr>
+ </thead>
+ <tbody type="body" ng-repeat="rowData in tableData">
+ <tr>
+ <td ng-bind="rowData['droolsFile']"></td>
+ <td ng-bind="rowData['className']"></td>
+ <td>
+ <div>
+ <a href="samplePage#/drools/{{rowData.droolsFile}}" class="icon-controls-playalt"></a>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ <div ng-if="tableData==null || tableData.length==0" align="center">No records found</div>
+ </div>
+ <a href="samplePage#/drools/0">Go to Drools Rule Engine import page</a>
+
+</div>
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools.html
new file mode 100644
index 00000000..cbc0cfc0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/drools.html
@@ -0,0 +1,55 @@
+
+<div id="page-content">
+ <div>
+ <h1 class="heading-page">Drools Rule Engine</h1>
+ </div>
+ <div>
+ <h2>Please enter below details:</h2>
+ </div>
+ <div ng-show="showLoader" class="span loader-container">
+ <i class="icon-primary-spinner" role="img"
+ aria-label="Please wait while we load your content"></i>
+ </div>
+ <div class="row-nowrap">
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-2a">*Drools File</label>
+ <div class="field-group">
+ <input id="textinputID-2a" ddh-reset=""
+ class="span12" type="text" data-ng-model="postDroolsBean.droolsFile">
+ </div>
+ </div>
+ </div>
+ <br>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">*Class Name</label>
+ <div class="field-group">
+ <input id="textinputID-3a" ddh-reset=""
+ class="span12" type="text"
+ data-ng-model="postDroolsBean.className">
+ </div>
+ </div>
+ </div>
+ <br>
+ <div class="span12">
+ <div class="form-row">
+ <label for="textinputID-3a">*Selected Rules </label>
+ <div class="field-group">
+ <input id="textinputID-3a" ddh-reset=""
+ class="span12" type="text"
+ data-ng-model="postDroolsBean.selectedRules">
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <br>
+ <div>
+ <button class="btn btn-alt btn-small" type="button" ng-click="execute(postDroolsBean);">Execute Rules</button>
+ <a href="samplePage#/droolsList">Go to Drools list page</a>
+ </div>
+</div>
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/frame_insert.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/frame_insert.html
new file mode 100644
index 00000000..5c2e45f9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/frame_insert.html
@@ -0,0 +1,27 @@
+<div>test</div>
+
+<iframe id="frame_insert" src="net_map_int"></iframe>
+
+<script type="text/javascript">
+
+ var frameId = "#frame_insert";
+
+ $(frameId).load(function(){
+ iframeLoaded()
+
+ });
+
+
+ function iframeLoaded() {
+ var iFrameRef = $(frameId);
+ if(iFrameRef) {
+
+ var height = iFrameRef.contents().find("input[name='inner_height']");
+ var width = iFrameRef.contents().find("input[name='inner_width']");
+
+ iFrameRef.css('height', (height.val() != undefined ? height.val():"500px"));
+ iFrameRef.css('width', (width.val() != undefined ? width.val():"500px"));
+ iFrameRef.css('border','none');
+ }
+ }
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-frame.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-frame.html
new file mode 100644
index 00000000..c9bcc27d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-frame.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Notebook Page</title>
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+ <!-- Common scripts -->
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+
+ <script src="app/fusion/external/utils/js/browserCheck.js"></script>
+
+
+
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js"></script>
+
+
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/notebookFrameController.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/ds2-sample/nbook-framecontroller.js"></script>
+
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+
+ <!-- loadjscssfile("./app/fusion/external/utils/js/browserCheck.js","js");
+ loadjscssfile("./app/fusion/scripts/DS2-services/adminService.js","js");
+ loadjscssfile("./app/fusion/scripts/DS2-services/adminMenuService.js","js"); -->
+
+
+
+<!-- //<script src="dependency/joint.js"></script> -->
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
+
+
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html
new file mode 100644
index 00000000..0db933d6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-page.html
@@ -0,0 +1,80 @@
+<div id="page-content" style="min-height: 500px">
+ <div>
+ <h1 class="heading-page">Notebook</h1>
+ </div>
+ <div class="form-row">
+ <label for="textinputID1">Notebook ID:</label><BR> <input
+ type="text" name="notebookid" b2b-reset maxlength=200 class="span12 "
+ ng-model="notebookvalue"
+ ng-init="notebookvalue='833c0a69ec1433fbb2f8752af733cf0e'"
+ style="width: 180px" />
+ </div>
+ <BR>
+
+ <!-- Use this for only 1 key value query parameter
+ <div class="fn-ebz-container">
+
+ <label class="fn-ebz-text-label">Key</label><BR>
+ <input type="text" name="key" maxlength=200 ng-model="qparamKey" style="width:180px"/>
+ </div>
+
+ <div class="fn-ebz-container">
+ <label class="fn-ebz-text-label">Value</label><BR>
+ <input type="text" name="val" maxlength=200 ng-model="qparamVal" style="width:180px"/>
+ </div> -->
+
+
+
+ <!-- Use this for multiple key value query parameters -->
+ <div
+ style="border: 2px; border-style: solid; border-color: #808080; margin-bottom: 9px; width: 55%; padding-bottom: 20px;">
+ <div ng-repeat="kv in keyValueList">
+ <div style="margin-left: 5px">
+ <div class=" row-nowrap">
+ <div class="form-row input-emphasized-field">
+
+ <label for="textinputID1">Key</label><BR> <input type="text"
+ id="textinputID-2a" b2b-reset name="key"
+ class="span12 input-emphasized" maxlength=100 ng-model="kv.qK"
+ style="width: 180px" />
+ </div>
+
+ <div class="form-row input-emphasized-field"
+ style="padding-left: 50px;">
+ <label for="textinputID1">Value</label><BR> <input
+ type="text" id="textinputID-2a" b2b-reset name="val"
+ class="span12 input-emphasized" maxlength=100 ng-model="kv.qV"
+ style="width: 180px" />
+ </div>
+
+ <div class="fn-ebz-container"
+ style="position: relative; top: 25px;">
+ <button href="javascript:void(0)" id="addbtn"
+ ng-show="{{$index==0}}"
+ style="float: right; margin-left: 150px; bottom: -17px;"
+ size="small" att-accessibility-click="13,32"
+ class="btn btn-alt btn-small" ng-click="addKeyValuePairs(kv);">Add</button>
+ <a href="javascript:void(0)" ng-show="{{$index>0}}"
+ style="float: right; margin-left: 150px; bottom: -17px;"
+ size="small" att-accessibility-click="13,32"
+ ng-click="removeKeyValuePairs($index);"
+ class="btn btn-alt btn-small"> Remove</a>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+
+
+ <BR>
+
+ <div class="fn-ebz-container">
+ <a class="btn btn-alt btn-small" btn-type="primary"
+ att-accessibility-click="13,32" ng-click="submitParameters();">Submit</a>
+ </div>
+
+ <!-- <div ng-show="iframevisibility"><iframe id='itestfr' width="1400" height="1400"></iframe></div> -->
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-viz.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-viz.html
new file mode 100644
index 00000000..4c89ee41
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2-samplePages/notebook-viz.html
@@ -0,0 +1,7 @@
+ <div style="min-height:500px">
+
+
+ <div><iframe id='itestframe' width="1400" height="1400" style="margin-left:300px;"></iframe></div>
+
+
+ </div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Header.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Header.html
new file mode 100644
index 00000000..ef847518
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Header.html
@@ -0,0 +1,69 @@
+<div style="position:relative;width: 100%;top: 0px;left: 0;background-color: #222;z-index:9999">
+ <header class="b2b-header-tabs" b2b-header-responsive ng-show="{{showHeader}}">
+ <ul class="header__items" role="navigation">
+ <li class="header__item icon__item" tabindex="0">
+
+ <!--
+ -TODO: needs to be this icon but is not availble
+ -->
+
+ <span class="globe-text">ECOMP Portal</span>
+ </li>
+ <li b2b-header-menu class="header__item b2b-headermenu" ng-repeat="item in menuItems" role="presentation">
+ <a href="#" class="menu__item" role="menuitem"></a>
+ <div class="header-secondary-wrapper">
+ <ul class="header-secondary" role="menu">
+ <li class="header-subitem" b2b-header-submenu ng-repeat="i in item.subitems" role="presentation">
+ <a href="#" class="menu__item" aria-haspopup="{{i.links ? true:false}}" role="menuitem">{{i.value}}</a>
+ <div class="header-tertiary-wrapper" ng-if="i.links">
+ <ul class="header-tertiary" role="menu">
+ <li b2b-header-tertiarymenu ng-repeat="link in i.links" role="presentation">
+ <label>{{link.title}}</label>
+ <div b2b-tertiary-link ng-repeat="title in link.value">
+ <a href="{{link.href}}" class="header-tertiaryitem" ng-if="!title.subitems" aria-haspopup="false" role="menuitem"><span class="b2b-label-hide">{{link.title}}</span>{{title.title}}</a>
+ <a href="{{link.href}}" class="header-tertiaryitem" b2b-header-togglemenu ng-if="title.subitems" aria-haspopup="true" role="menuitem"><span class="b2b-label-hide">{{link.title}}</span>{{title.title}}</a>
+ <ul class="header-quarternary" role="menu" ng-if="title.subitems">
+ <li b2b-header-quarternarymenu role="presentation">
+ <a href="{{nav.href}}" ng-repeat="nav in title.subitems" role="menuitem" aria-haspopup="true">
+ {{nav.title}}
+ </a>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </li>
+ </ul>
+ </div>
+ </li>
+ <!--<li class="header__item profile" b2b-header-responsive>-->
+ <li class="header__item profile">
+
+ <label ng-click="showInfo = !showInfo" class="headerUserName" tabindex="0" ddh-accessibility-click="13,32">
+ <!-- Temporarily copied the font file from DS1 to local directory(as DS2 component is not working yet) -->
+ <!-- <div class="icon-user-small login-snippet-icon"></div> -->
+ <i class="icon-user" style="color:#FFFFFF;"></i>
+ <span class="header_profile">{{userFirstName}}</span>
+ </label>
+
+ <div class="profile-info" ng-class="{'open': showInfo,'': !showInfo}">
+ <h6 id="example_source_john-smith">{{userProfile.fullName}}</h6>
+ <label for='email'>Email</label> <span id='email'>{{userProfile.email}}</span>
+ <label for='profileId'>Organization User ID</label> <span id='profileId'>{{userProfile.orgUserId}}</span>
+ <!-- <label for='comp'>Company</label> <span id='comp'>{{userProfile.serviceProviderName}}</span> -->
+ <i class="caret"></i>
+ <!-- <p>
+ <a href="{{userProfile.userProfileUrl}}" style="float: left">My Profile</a>
+ <a href="{{userProfile.companyProfileUrl}}" style="float: right">Company Profile</a>
+ </p> -->
+ <p>
+ <a class="btn btn-alt" style="float: right" href="logout.htm">Log Out</a>
+ </p>
+ </div>
+ <div style="width:250px;"></div>
+ </li>
+ </ul>
+ </header>
+
+ </div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Left_menu.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Left_menu.html
new file mode 100644
index 00000000..c30a0b69
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/ds2Left_menu.html
@@ -0,0 +1,3 @@
+<div>
+ <left-menu-ecomp menu-data="menuData"></left-menu-ecomp>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/loginSnippet.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/loginSnippet.html
new file mode 100644
index 00000000..19868bb6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/loginSnippet.html
@@ -0,0 +1,63 @@
+
+
+<script>
+var loginSnippetCtrl = function ($scope,$http, $log,UserInfoServiceDS2){
+ /*Define fields*/
+ $scope.userProfile={
+ firstName:'',
+ lastName:'',
+ fullName:'',
+ email:''
+ }
+ /*Put user info into fields*/
+ $scope.inputUserInfo = function(userInfo){
+ if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
+ if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
+ $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
+ if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
+ $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
+ if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
+ $scope.userProfile.email = userInfo.USER_EMAIL;
+ if (typeof(userInfo.USER_ORG_USER_ID) != "undefined" && userInfo.USER_ORG_USER_ID!=null && userInfo.USER_ORG_USER_ID!='')
+ $scope.userProfile.orgUserId = userInfo.USER_ORG_USER_ID;
+ }
+ }
+ /*getting user info from session*/
+ $scope.getUserNameFromSession = function(){
+ UserInfoService.getFunctionalMenuStaticDetailSession()
+ .then(function (response) {
+ var j = response;
+ // console.log(response);
+ $scope.userProfile.fullName = response.userName;
+ $scope.userProfile.orgUserId = response.orgUserId;
+ $scope.userProfile.email = response.email;
+ });
+ }
+ /*getting user info from shared context*/
+ $scope.getUserName=function() {
+ var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('loginSnippet: get user information from session');
+ $scope.getUserNameFromSession();
+ }else{
+ // $log.info('Received User information from shared context',res);
+ var resData = res;
+ /* $scope.inputUserInfo(resData); */
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ }
+ },
+ function(err) {
+ console.log('error');
+ }
+ );
+ };
+ /*call the get user info function*/
+ try{
+ $scope.getUserName();
+ }catch(err){
+ $log.info('Error while getting User information',err);
+ }
+}
+ </script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-content.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-content.html
new file mode 100644
index 00000000..2626d01a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-content.html
@@ -0,0 +1,191 @@
+<div id="page-content" class="content" gridster="gridsterOpts">
+
+ <!-- Gridster Item starts here -->
+ <div>
+ <ul>
+ <li gridster-item="item" ng-repeat="item in standardItems">
+ <div class="box">
+ <div class="box-header">
+ <table >
+ <tr>
+ <th table-body width="5%" style="height:20px; float:left;height:100%;" class="icon-content-gridguide" ></th>
+ <th>
+ <h3 ng-if="item.max">{{item.headerText}}</h3>
+ <h3 ng-hide="item.max">{{item.headerText.length<36?item.headerText:item.headerText.substring(0,35)+' ...'}} </h3>
+ </th>
+ <th>
+ <div style="height:20px;" class="box-header-btns pull-right" >
+ <div class="tileMinMaxBtn" ng-click="toggleMinMax($index,'')">
+ <span class="tileMinMaxIcon">
+ <i class="icon-controls-up" style="color:gray" ng-show="item.max"></i>
+ <i class="icon-controls-down" style="color:gray" ng-hide="item.max"></i>
+ </span>
+ </div>
+<!-- <a title="settings" ng-click="openSettings(widget)"><i class="glyphicon glyphicon-cog"></i></a>
+ <a title="Remove widget" ng-click="remove(widget)"><i class="glyphicon glyphicon-trash"></i></a> -->
+ <class="icon-up">
+ </div>
+ </th>
+ </tr>
+ </table>
+ </div>
+ <div class="box-content">
+
+ <div class="box-content-frame" align="center">
+
+ <div align="left" ng-if="item.headerText=='Dashboard' && item.max" style="height: 360px;">
+ <label>&nbsp; Sample Charts</label><BR>
+ <iframe scrolling="yes" frameBorder="0" style="display:block; width: 460px; height:100%;" src="static/fusion/sample/html/wordcloud.html"></iframe>
+ </div>
+ <div ng-if="item.headerText=='Donut Chart' && item.max">
+ <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/donut_d3.html"></iframe>
+ </div>
+ <div ng-if="item.headerText=='Area Chart' && item.max">
+ <div id="areaChart">
+ <div> <svg></svg> </div>
+ <script src="static/fusion/sample/html/js/area_chart.min.js"></script>
+ </div>
+ <!-- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/area_chart.html"></iframe> -->
+ </div>
+ <div ng-if="item.headerText=='Pie Chart' && item.max">
+ <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/pie_chart.html"></iframe>
+ </div>
+ <div ng-if="item.headerText=='Line Chart' && item.max">
+ <div id="lineChart">
+ <div> <svg></svg> </div>
+ <script src="static/fusion/sample/html/js/line_chart.min.js"></script>
+ </div>
+
+<!-- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/line_chart.html"></iframe> -->
+ </div>
+ <div ng-if="item.headerText=='Gauges' && item.max">
+ <iframe scrolling="no" frameBorder="0" style="width: 310pxx; height: 210px;" src="static/fusion/sample/html/d3_gauges_demo.html"></iframe>
+ </div>
+
+ <div align="left" ng-if="item.headerText=='Traffic distribution by day of week' && item.max">
+ <div id = "selectedTrafficDay">
+ <ul>
+ <li ng-repeat="Daytab in selectedTrafficDay"
+ ng-class="{active1:isActiveTab1(Daytab.url)}"
+ ng-click="onClickTab1(Daytab)">{{Daytab.title}}</li>
+ </ul>
+ <div id = "SelectedTrafficeDayView">
+ <div ng-include="currentSelectedDayTab"></div>
+ </div>
+ <script type="text/ng-template" id="#Monday">
+ <div id="Monday" align="centers"><img src="static/fusion/sample/images/tunnels/1_mon.png" width=100% height=100% alt="Monday"></div>
+ </script>
+ <script type="text/ng-template" id="#Tuesday">
+ <div id="Tuesday" align="center"><img src="static/fusion/sample/images/tunnels/2_tue.png" width=100% height=100% alt="Tuesday"></div>
+ </script>
+ <script type="text/ng-template" id="#Wednesday">
+ <div id="Wednesday" align="center"><img src="static/fusion/sample/images/tunnels/3_wed.png" width=100% height=100% alt="Wednesday"></div>
+ </script>
+ <script type="text/ng-template" id="#Thursday">
+ <div id="Thursday" align="center"><img src="static/fusion/sample/images/tunnels/4_thu.png" width=100% height=100% alt="Thursday"></div>
+ </script>
+ <script type="text/ng-template" id="#Friday">
+ <div id="Friday" align="center"><img src="static/fusion/sample/images/tunnels/5_fri.png" width=100% height=100% alt="Friday"></div>
+ </script>
+ <script type="text/ng-template" id="#Saturday">
+ <div id="Saturday" align="center"><img src="static/fusion/sample/images/tunnels/6_sat.png" width=100% height=100% alt="Saturday"></div>
+ </script>
+ <script type="text/ng-template" id="#Sunday">
+ <div id="Sunday" align="center"><img src="static/fusion/sample/images/tunnels/7_sun.png" width=100% height=100% alt="Sunday"></div>
+ </script>
+ </div>
+ </div>
+
+ <div align="left" ng-if="item.headerText=='Busy hour traffic analysis by day of week' && item.max">
+ <div id = "BusyHourTraffic">
+ <ul>
+ <li ng-repeat="TrafficTab in BusyHourTraffic"
+ ng-class="{active2:isActiveTab2(TrafficTab.url)}"
+ ng-click="onClickTab2(TrafficTab)">{{TrafficTab.title}}</li>
+ </ul>
+ <div id = "BusyHourTrafficView">
+ <div ng-include="currentSelectedBusyHourTraffic"></div>
+ </div>
+ <script type="text/ng-template" id="#Incoming">
+ <div id="Incoming" align="left"><img src="static/fusion/sample/images/tunnels/BH_DLSTX_IN.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#Outgoing">
+ <div id="Outgoing" align="center"><img src="static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png" width=100% height=100%></div>
+ </script>
+ <script type="text/n g-template" id="#Default">
+ <div id="Default" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat_Def.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#Priority">
+ <div id="Priority" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat_Priority.png" width=100% height=100%></div>
+ </script>
+ <script type="text/ng-template" id="#BHNational">
+ <div id="BHNational" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat.png" width=100% height=100%></div>
+ </script>
+ </div>
+ </div>
+
+ <div align="left" ng-if="item.headerText=='Additional Samples' && item.max">
+ <label>&nbsp;Quick Links</label>
+ <table table
+ id="additional-samples-table"
+ search-string="searchStringIgnored"
+ view-per-page="viewPerPageIgnored"
+ current-page="currentPageIgnored"
+ total-page="totalPageIgnored">
+
+
+ <tr>
+ <td table-body width="90%" ><a href="http://jquery.com" target="_blank">JQuery</a></td>
+ <td table-body width="10%">
+ <a ng-click="removeRole();" class="icon-misc-trash"></a>
+ </td>
+ </tr>
+ <tr>
+ <td table-body width="90%" ><a href="app/sequence/views/details.html" target="_blank">Network Simulation</a></td>
+ <td table-body width="10%">
+ <a ng-click="removeRole();" class="icon-misc-trash"></a>
+ </td>
+ </tr>
+ <!-- <tr>
+ <td table-body width="90%" ><a href="sample_heat_map.htm" target="">Heat Map</a></td>
+ <td table-body width="10%">
+ <a ng-click="removeRole();" ><img src="static/fusion/sample/images/deleteicon.gif"></a>
+ </td>
+ </tr> -->
+ <tr>
+ <td table-body width="90%" ><a href="leafletMap.htm" target="">Animated Map</a></td>
+ <td table-body width="10%">
+ <a ng-click="removeRole();" class="icon-misc-trash"></a>
+ </td>
+ </tr>
+ <tr>
+ <td table-body width="90%" ><a href="collaborate_list.htm">Chat Session</a></td>
+ <td table-body width="10%">
+ <a ng-click="removeRole();" class="icon-misc-trash"></a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div ng-if="item.headerText=='Sticky Notes' && item.max">
+ <div style="width:100%; height:400px" id="scribble-pad"><pre id="scribble" contenteditable="true" onkeyup="storeUserScribble(this.id);"></pre></div>
+ </div>
+
+ <div ng-if="item.headerText=='Service Configuration' && item.max">
+<!-- <accordion close-others="true" css="accordion" > -->
+ <accordion-group heading="Service Configuration" ng-if="group11.open">
+ <iframe style="overflow:auto" frameBorder="0" align="center" width="100%" height="400px" src="static/fusion/sample/org_chart/example.html" ></iframe>
+ </accordion-group>
+ <accordion-group heading="VSP Service Configuration" ng-if="group12.open">
+ <iframe style="overflow:auto" frameBorder="0" align="center" width="100%" height="400px" src="static/fusion/sample/org_chart/example_vsp.html" ></iframe>
+ </accordion-group>
+<!-- </accordion> -->
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </li>
+ </ul>
+ </div>
+ <!-- Gridster Item ends here -->
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-sample.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-sample.html
new file mode 100644
index 00000000..52305d55
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome-sample.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App welcome page using DS2 look and feel -->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <title>Welcome</title>
+
+ <!-- Common CSS -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/extras/ds2-accordion.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/extras/ds2-bootstrap-datepicker.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/extras/ds2-cc-input-field.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/extras/ds2-tooltip.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/extras/x-tabs-pills.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-accordion.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-bootstrap-datepicker.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-c2c.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-cc-input-field.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-filmstrip.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-filters.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-legacynav-fix.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-marquee.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-pagination.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-popover.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-progressbar.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ds2-tooltip.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/global.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/digital-design-library.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-gridster/dist/angular-gridster.min.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-arrows.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-buildings.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-content.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-controls.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-datanetwork.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-devices.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-documents.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-healthcare.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-location.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-misc.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-numslets.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-people.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-retail.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-securityalerts.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-social.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-speechbubbles.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-test.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-transportation.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/icon-weather.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/x-tabs-pills.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+
+ <script src="app/fusion/external/ds2/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src="app/fusion/external/ds2/js/digital-ng-library/digital-design-library.js"></script>
+
+ <!-- Page-specific items -->
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/welcome-route.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/welcome-controller.js"></script>
+
+ <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/scribble.css" />
+ <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/flexslider.css" />
+ <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/welcome.css" />
+
+ <script src="static/fusion/d3/js/d3.v3.min.js"></script>
+ <script src="static/fusion/d3/js/nv.d3.min.js"></script>
+ <script src="static/fusion/d3/js/models/axis.min.js"></script>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <!-- commented the header for now to avoid duplicate headers on portal -->
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container" ></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome.html
new file mode 100644
index 00000000..b2cafdac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/DS2-view-models/welcome.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<!-- Single-page application for EPSDK-App welcome page using DS2 look and feel. X-->
+<html>
+<head>
+ <meta charset="ISO-8859-1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
+
+ <title>Welcome</title>
+
+ <!-- B2b Library -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <!-- icons in open source -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ionicons.css">
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-bootstrap/ui-bootstrap-csp.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/angular-gridster/dist/angular-gridster.min.css">
+ <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/scribble.css" />
+ <link rel="stylesheet" type="text/css" href="static/fusion/sample/css/welcome.css" />
+
+ <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
+
+ <!-- Common scripts -->
+ <script src="app/fusion/external/angular-1.4.8/angular.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-messages.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-touch.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.min.js"></script>
+ <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
+ <script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>
+ <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
+ <script src="app/fusion/external/angular-gridster/dist/angular-gridster.min.js"></script>
+
+ <!-- EPSDK App scripts and common services -->
+ <!-- B2b Library -->
+ <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.min.js"></script>
+ <script src="app/fusion/scripts/DS2-services/ds2-modal/modalService.js"></script>
+ <script src="app/fusion/external/ds2/js/appDS2.js"></script>
+
+ <script src="app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/headerServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/leftMenuServiceDS2.js"></script>
+ <script src="app/fusion/scripts/DS2-services/manifestService.js"></script>
+
+ <script src="app/fusion/scripts/DS2-directives/footer.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2Header.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/ds2LeftMenu.js"></script>
+ <script src="app/fusion/scripts/DS2-directives/b2b-leftnav-ext.js"></script>
+ <script src= "app/fusion/scripts/DS2-services/userInfoServiceDS2.js"></script>
+
+ <!-- Page specific items -->
+ <script src="app/fusion/scripts/DS2-controllers/welcome-controller.js"></script>
+ <script src="app/fusion/scripts/DS2-controllers/welcome-route.js"></script>
+
+<style>
+
+.controls {
+ margin-bottom: 20px;
+}
+.page-header {
+ margin-top: 20px;
+}
+ul {
+ list-style: none;
+}
+.box {
+ height: 100%;
+ border: 1px solid #ccc;
+ background-color: #fff;
+ position: relative;
+ overflow: hidden;
+}
+.box-header {
+ background-color: #eee;
+ padding: 0px 0px 0px 0px;
+/* border-bottom: 1px solid #ccc; */
+ margin-bottom: -25px;
+ cursor: move;
+ position: relative;
+}
+.box-header h3 {
+ margin-top: 0px;
+ display: inline-block;
+}
+.box-content {
+ padding: 10px;
+ display:block;
+ height: 100%;
+ position: relative;
+ overflow-x:auto;
+ overflow-y:auto;
+}
+.box-header-btns {
+ top: 15px;
+ right: 10px;
+ cursor: pointer;
+ position: absolute;
+}
+
+.gridster {
+ border: none;
+ position:relative;
+}
+
+.box-content .box-content-frame{
+
+}
+
+.box table{
+border:none;
+display:block;
+}
+
+.box table tr{
+line-height:20px;
+}
+
+.box table th{
+border:none;
+line-height:20px;
+}
+
+/* .header-container{
+ margin-top:-50px;
+} */
+/* .content-container{
+ margin-top:50px;
+} */
+.menu-container{
+margin-top:0px
+}
+
+.handle-e {
+width:3px;
+}
+
+</style>
+
+</head>
+ <body class="appBody" ng-app="abs">
+ <!-- commented the header for now to avoid duplicate headers on portal -->
+ <div ds2-Header class="header-container" ></div>
+ <div ds2-menu id="menuContainer" class="menu-container"></div>
+ <div ng-view id="rightContentProfile" class="content-container"></div>
+ <div ds2-Footer class="footer-container"></div>
+ </body>
+</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js
index 985fa434..985fa434 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/angular-gridster.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js
index 3ca3db7d..3ca3db7d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/att_angular_gridster/ui-gridster-tpls.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-closed-cloop.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-closed-cloop.js
new file mode 100644
index 00000000..39ef50e8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-closed-cloop.js
@@ -0,0 +1,28 @@
+app.controller('adminClosedLoopController', ['$scope','$http','$q','$log',function ($scope, $http,$q, $log){
+ $scope.camunda_cockpit_url = '';
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_camunda_cockpit_link",
+ }).success( function(res) {
+ // if the returned response is error HTML page in string format
+ if(res.link_defined=='false'){
+ $log.error('Retrieval of camunda cockpit link failed. Please make sure the variable "camunda_cockpit_url" is defined in the system.properties file.');
+ deferred.reject(status);
+ }
+ // valid cockpit url
+ else if(res.camunda_cockpit_link!=null & res.camunda_cockpit_link!= '') {
+ $scope.camunda_cockpit_url = res.camunda_cockpit_link;
+ deferred.resolve(res);
+ // if the defined url is empty;
+ } else {
+ $log.error('Please ensure the variable "camunda_cockpit_url" is properly defined in system.properties file (i.e., neither null nor empty).');
+ deferred.reject(status);
+ }
+ // API call fails
+ }).error( function(status) {
+ $log.error('get_camunda_cockpit_link RestAPI call failed.');
+ deferred.reject(status);
+ });
+ return deferred.promise;
+}]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-whitelist.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-whitelist.js
new file mode 100644
index 00000000..5eed3003
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/admin-whitelist.js
@@ -0,0 +1,3 @@
+app.config(function ($sceDelegateProvider) {
+ $sceDelegateProvider.resourceUrlWhitelist(['self','**']);
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js
new file mode 100644
index 00000000..3d92220f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js
@@ -0,0 +1,3 @@
+app.controller('aseCtrl', function ($scope){
+/* do nothing yet*/
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js
new file mode 100644
index 00000000..a6cde5ae
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js
@@ -0,0 +1,60 @@
+app.controller('broadcastController', function ($scope, modalService, $modal,AdminService,$routeParams){
+ //$scope.broadcastMessage=${broadcastMessage};
+ //$scope.broadcastSites=${broadcastSites};
+ //console.log($scope.broadcastMessage);
+ $scope.broadcastMessage=[];
+ $scope.broadcastSites=[];
+ AdminService.getBroadcast($routeParams.messageLocationId, $routeParams.messageLocation, $routeParams.messageId).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.broadcastMessage=JSON.parse($scope.data.broadcastMessage);
+ $scope.broadcastSites=JSON.parse($scope.data.broadcastSites);
+ console.log($scope.broadcastMessage);
+ console.log($scope.broadcastMessage.id);
+ console.log($scope.broadcastSites);
+ //$scope.resetMenu();
+
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ $scope.save = function() {
+ var uuu = "broadcast/save";
+ var postData={broadcastMessage: $scope.broadcastMessage};
+ $.ajax({
+ type : 'POST',
+ url : uuu,
+ dataType: 'json',
+ contentType: 'application/json',
+ data: JSON.stringify(postData),
+ success : function(data){
+ window.location.href = "admin#/broadcast_list";
+ },
+ error : function(data){
+ modalService.showFailure("Fail","Error while saving.");
+ }
+ });
+ };
+
+ $scope.close = function() {
+ window.location.href = "admin#/broadcast_list";
+};
+
+});
+
+$(function() {
+ $( "#startDatepicker" ).datepicker();
+ $( "#endDatepicker" ).datepicker();
+
+ $( "#startDatepicker" ).change(function() {
+ var tempStartDate = moment($( "#startDatepicker" ).val()).format('YYYY-MM-DD hh:mm:ss.S');
+ $( "#startDateHidden" ).val(tempStartDate.toString());
+ //alert( $( "#startDateHidden" ).val() );
+ });
+ $( "#endDatepicker" ).change(function() {
+ var tempEndDate = moment($( "#endDatepicker" ).val()).format('YYYY-MM-DD hh:mm:ss.S');
+ $( "#endDateHidden" ).val(tempEndDate.toString());
+ //alert( $( "#endDateHidden" ).val() );
+ });
+});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js
index cb10a29b..0af15b78 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/broadcast-list-controller.js
@@ -1,22 +1,3 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
app.controller('broadcastListController', function ($scope, modalService, $modal,AdminService){
//$scope.broadcastMessage=${broadcastMessage};
//$scope.broadcastSites=${broadcastSites};
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js
new file mode 100644
index 00000000..a1831b7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js
@@ -0,0 +1,44 @@
+app.controller("collaborateListController", function ($scope,$http,modalService, $modal,AdminService) {
+ // Table Data
+ AdminService.getCollaborateList().then(function(data){
+
+ var j = data;
+ $scope.tableData = JSON.parse(j.data);
+ //$scope.resetMenu();
+
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ $scope.viewPerPage = 20;
+ $scope.scrollViewsPerPage = 2;
+ $scope.currentPage = 1;
+ $scope.totalPage;
+ $scope.searchCategory = "";
+ $scope.searchString = "";
+ /* modalService.showSuccess('','Modal Sample') ; */
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ $scope.openCollaboration = function(chatId){
+ openInNewTab('openCollaboration?chat_id=' + chatId);
+ }
+
+ $scope.toggleProfileActive = function(profileId) {
+ modalService.popupConfirmWin("Confirm","You are about to change user's active status. Do you want to continue?",
+ function(){
+ $http.get("profile/toggleProfileActive?profile_id="+profileId).success(function(){});
+
+ })
+ };
+
+});
+
+function openInNewTab(url) {
+ var win = window.open(url, '_blank');
+ win.focus();
+}; \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js
new file mode 100644
index 00000000..48fbbc03
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js
@@ -0,0 +1,21 @@
+var modalpopupController = function ($scope, $modalInstance, message){
+
+ $scope.message = message;
+
+
+ $scope.hello = function () {
+ $modalInstance.close($scope.digitPattern);
+ };
+ $modalInstance.ok = function() {
+ //add the ok functionality
+ alert("Logout");
+ };
+ $modalInstance.cancel = function() {
+ //add the cancel functionality
+ alert("Keep Log in");
+ };
+ $modalInstance.cancelbutton = function() {
+ //add the cancel functionality
+ alert("Modal Waring popup close event");
+ };
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/footer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/footer.js
new file mode 100644
index 00000000..d49f5980
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/footer.js
@@ -0,0 +1,11 @@
+app.directive('qFooter', function () {
+ return {
+ restrict: 'A', //This menas that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
+ replace: false,
+ templateUrl: "app/fusion/scripts/view-models/footer.html",
+ controller: ['$scope', '$filter', function ($scope, $filter) {
+ // Your behaviour goes here :)
+ }]
+ }
+});
+
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/header.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/header.js
index bc90d200..7696251e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/header.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/header.js
@@ -1,22 +1,3 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
app.directive('qHeader', function () {
return {
restrict: 'A', //This menas that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
@@ -49,7 +30,7 @@ app.directive('qHeader', function () {
/*Menu Structure*/
var menuStructureConvert = function(menuItems) {
- console.log(menuItems);
+ // console.log(menuItems);
$scope.megaMenuDataObjectTemp =
[
{
@@ -97,19 +78,18 @@ app.directive('qHeader', function () {
promise.then(
function(res) {
if(res==null || res==''){
- $log.info('failed getting static User information');
+ $log.error('failed to get static User information');
$scope.getUserNameFromSession();
}else{
- $log.info('Received static User information');
-
+ // $log.info('Received static User information');
var resData = res;
- console.log(resData);
+ // console.log(resData);
$scope.inputUserInfo(resData);
$scope.userName = $scope.firstName+ ' '+ $scope.lastName;
}
},
function(err) {
- $log.info('failed getting static User information');
+ $log.error('getFunctionalMenuStaticDetailShareContext failed', err);
}
);
}
@@ -204,14 +184,13 @@ app.directive('qHeader', function () {
}
$scope.goToUrl = function (item) {
- $log.info("goToUrl called")
- $log.info(item);
+ $log.debug("goToUrl called", item);
var url = item.url;
var restrictedApp = item.restrictedApp;
- $log.debug('Restricted app status is: ' + restrictedApp);
+ // $log.debug('Restricted app status is: ' + restrictedApp);
if (!url) {
- $log.info('No url found for this application, doing nothing..');
+ $log.error('No url found for this application, doing nothing..');
return;
}
if (restrictedApp) {
@@ -286,7 +265,7 @@ app.directive('qHeader', function () {
$log.debug('get_favorites = ' + JSON.stringify(response));
$scope.favoritesMenuItems = response;
$scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
- $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ // $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
}
}
}).error(function (response){
@@ -299,7 +278,7 @@ app.directive('qHeader', function () {
$scope.createFavoriteErrorMenu=function() {
$scope.favoritesMenuItems = [];
$scope.favoriteItemsCount = Object.keys($scope.favoritesMenuItems).length;
- $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
+ // $log.info('number of favorite menus: ' + $scope.favoriteItemsCount);
}
/* end of Favorite Menu code */
@@ -346,63 +325,63 @@ app.directive('qHeader', function () {
"column": 1,
"text": "Google",
"parentMenuId": 1,
- "url": ""
+ "url": "http://google.com"
},
{
"menuId": 91,
"column": 1,
"text": "Mike Little's Coffee Cup",
"parentMenuId": 2,
- "url": ""
+ "url": "http://coffee.com"
},
{
"menuId": 92,
"column": 2,
"text": "Andy and his Astrophotgraphy",
"parentMenuId": 3,
- "url": ""
+ "url": "http://nightskypix.com"
},
{
"menuId": 93,
"column": 1,
"text": "JSONLint",
"parentMenuId": 4,
- "url": ""
+ "url": "http://http://jsonlint.com"
},
{
"menuId": 94,
"column": 2,
"text": "HROneStop",
"parentMenuId": 4,
- "url": ""
+ "url": "http://ebiz.sbc.com/hronestop"
},
{
"menuId": 95,
"column": 2,
"text": "4th Level App4a R16",
"parentMenuId": 4,
- "url": ""
+ "url": "http://www.e-access.att.com/ecomp_portal_ist/ecompportal/widgets"
},
{
"menuId": 96,
"column": 3,
"text": "3rd Level App1c R200",
"parentMenuId": 4,
- "url": ""
+ "url": "http://app1c.com"
},
{
"menuId": 97,
"column": 1,
"text": "3rd Level App4b R16",
"parentMenuId": 5,
- "url": ""
+ "url": "http://app4b.com"
},
{
"menuId": 98,
"column": 2,
"text": "3rd Level App2b R16",
"parentMenuId": 5,
- "url": ""
+ "url": "http://app2b.com"
},
{
"menuId": 99,
@@ -449,7 +428,6 @@ app.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoService)
lastName:'',
fullName:'',
email:'',
- userid:''
}
/*Put user info into fields*/
$scope.inputUserInfo = function(userInfo){
@@ -460,8 +438,7 @@ app.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoService)
$scope.userProfile.lastName = userInfo.USER_LAST_NAME;
if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
$scope.userProfile.email = userInfo.USER_EMAIL;
- if (typeof(userInfo.USER_ORGUSERID) != "undefined" && userInfo.USER_ORGUSERID!=null && userInfo.USER_ORGUSERID!='')
- $scope.userProfile.userid = userInfo.USER_ORGUSERID;
+
}
}
/*getting user info from session*/
@@ -469,7 +446,6 @@ app.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoService)
UserInfoService.getFunctionalMenuStaticDetailSession()
.then(function (response) {
$scope.userProfile.fullName = response.userName;
- $scope.userProfile.userid = response.userid;
$scope.userProfile.email = response.email;
});
}
@@ -479,19 +455,18 @@ app.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoService)
promise.then(
function(res) {
if(res==null || res==''){
- $log.info('Getting User information from session');
- $scope.getUserNameFromSession();
-
+ $log.error('getFunctionalMenuStaticDetailShareContext failed');
+ $scope.getUserNameFromSession();
}else{
- $log.info('Received User information from shared context',res);
+ // $log.info('Received User information from shared context',res);
var resData = res;
- console.log(resData);
+ // console.log(resData);
$scope.inputUserInfo(resData);
$scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
}
},
function(err) {
- console.log('error');
+ console.log('getFunctionalMenuStaticDetailShareContext failed', err);
}
);
};
@@ -499,6 +474,6 @@ app.controller('loginSnippetCtrl', function ($scope,$http, $log,UserInfoService)
try{
$scope.getUserName();
}catch(err){
- $log.info('Error while getting User information',err);
+ $log.info('getUserName failed', err);
}
});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/leftMenu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/leftMenu.js
index 737cb801..f42276fe 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/leftMenu.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/directives/leftMenu.js
@@ -1,22 +1,3 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
app.directive('qMenu', function () {
return {
@@ -37,7 +18,7 @@ app.directive('qMenu', function () {
$scope.leftParentData = JSON.parse(j.data);
$scope.leftChildData = JSON.parse(j.data2);
}else{
- throw "Get Left Menu respsone is not an object/is empty";
+ throw "Get Left Menu response is not an object/is empty";
}
try{
var leftChildItemList = $scope.leftChildData;
@@ -54,22 +35,22 @@ app.directive('qMenu', function () {
$scope.leftMenuItems.push($scope.item);
};
}catch(err){
- console.log("error happened while trying to set left menu structure"+err);
+ console.log("failed to set left menu structure", err);
}
}catch (e) {
- console.log("error happened while trying to get left menu items"+e);
+ console.log("failed to get left menu items", e);
reloadPageOnce();
return;
}
},function(error){
- console.log("error happened while calling getLeftMenu"+error);
+ console.log("error happened while calling getLeftMenu", error);
});
LeftMenuService.getAppName().then(function(response){
var j = response;
try{
if(j && j !== "null" && j!== "undefined"){
- console.log("app name is " + $scope.app_name);
+ // console.log("app name is " + $scope.app_name);
$scope.app_name_full = j.data;
var processed_app_name = j.data;
var n = processed_app_name.length;
@@ -81,11 +62,11 @@ app.directive('qMenu', function () {
throw "Get app_name respsone is not an object/is empty";
}
}catch (e) {
- console.log("error happened while trying to get app name "+e);
+ console.log("failed to get app name", e);
return;
}
},function(error){
- console.log("error happened while calling getAppName "+error);
+ console.log("failed in getAppName", error);
});
$scope.adjustHeader=function() {
@@ -93,14 +74,14 @@ app.directive('qMenu', function () {
if($scope.showHeader == true) {
$scope.drawer_margin_top = 50;
- $scope.drawer_custom_top = 20;
+ $scope.drawer_custom_top = 54;
$scope.toggle_drawer_top = 55;
}
else {
- $scope.drawer_margin_top = 0;
+ $scope.drawer_margin_top = 40;
$scope.drawer_custom_top = 0;
- $scope.toggle_drawer_top = 0;
+ $scope.toggle_drawer_top = 10;
}
@@ -198,6 +179,6 @@ function detectScrollEvent() {
});
}
}catch(err){
- console.log(err)
+ console.log('detectScrollEvent failed', err)
}
}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/jquery.resize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/jquery.resize.js
index 1ebd6c95..1ebd6c95 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/jquery.resize.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/jquery.resize.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/debug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/debug.js
index eff36a25..eff36a25 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/debug.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/debug.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js
index 1c998bab..1c998bab 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js
index aa83af97..aa83af97 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery-ui-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js
index 434724d9..434724d9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/layout/jquery.layout-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/modalService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/modalService.js
index 74c848e8..74c848e8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/modalService.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/modalService.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/moment.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/moment.min.js
index 62b1697b..62b1697b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/moment.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/moment.min.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/network/net_map.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/network/net_map.js
new file mode 100644
index 00000000..49599503
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/network/net_map.js
@@ -0,0 +1,947 @@
+var graph,paper;
+var zoomIndex = 1;
+var recentCallFlow;
+var recentCallFlowStep;
+var hash_map = new Object();
+var hashVertexDomainXMap = new Object();
+
+var globalCollapseDomanString = "";
+var changeIcon = false;
+var colorSet = ["#0000FF","#8A2BE2","#DEB887",
+ "#5F9EA0","#7FFF00","#D2691E","#6495ED","#DC143C",
+ "#000000","#A9A9A9","#BDB76B",
+ "#FF1493","#48D1CC","#A52A2A","#FF7F50","#DAA520","#32CD32"];
+var colorIndex = 0;
+String.prototype.startsWith = function (str)
+{
+ return this.indexOf(str) == 0;
+}
+
+String.prototype.replaceAt=function(index, character) {
+ return this.substr(0, index) + character + this.substr(index+character.length);
+}
+function getColor(id1,id2) {
+
+ var color = colorSet[colorIndex];
+ colorIndex++;
+ return color;
+}
+/////////////////////////////////////////////////////////////////////////////////////
+ $('.legend-toggle').click(function (a) {
+
+ $('.legend-toggle .toggle').hasClass("on")?($('.legend-toggle .toggle').removeClass("on"),$("#legend").fadeOut(350)):($('.legend-toggle .toggle').addClass("on"),$("#legend").fadeIn(350));
+
+ });
+
+ $('.symbols-toggle').click(function (a) {
+
+ $('.symbols-toggle .toggle').hasClass("on")?($('.symbols-toggle .toggle').removeClass("on"),$("#symbols").fadeOut(350)):($('.symbols-toggle .toggle').addClass("on"),$("#symbols").fadeIn(350));
+ });
+
+
+
+plotNodes = function(domain) {
+
+ if(domain.containerList) {
+
+ var containerList = domain.containerList;
+
+ for(var i=0; i<containerList.length; i++) {
+
+ var container = containerList[i];
+ plotContainer(container, 'outContainer');
+ }
+
+ }
+
+ if(domain.innerCList) {
+
+ var containerList = domain.innerCList;
+
+ for(var i=0; i<containerList.length; i++) {
+
+ var container = containerList[i];
+ plotContainer(container, 'insideContainer');
+ }
+
+ }
+
+ if(domain.elementList) {
+ var elementList = domain.elementList;
+
+ for(var i=0; i<elementList.length; i++) {
+
+ var element = elementList[i];
+ plotElement(element);
+ }
+
+ }
+}
+
+plotNodesIcon = function(domain) {
+
+ if(domain.containerList) {
+
+ var containerList = domain.containerList;
+
+ for(var i=0; i<containerList.length; i++) {
+
+ var container = containerList[i];
+ plotContainerIcon(container, 'outContainer');
+ }
+
+ }
+
+ if(domain.innerCList) {
+
+ var containerList = domain.innerCList;
+
+ for(var i=0; i<containerList.length; i++) {
+
+ var container = containerList[i];
+ plotContainerIcon(container, 'insideContainer');
+ }
+
+ }
+
+ if(domain.elementList) {
+ var elementList = domain.elementList;
+
+ for(var i=0; i<elementList.length; i++) {
+
+ var element = elementList[i];
+ plotElementIcon(element);
+ }
+
+ }
+
+}
+
+plotExpand = function(container) {
+ attributes = container;
+ $('#networkModelContainer').append('<div class="expandtri"' + 'id= "' + attributes.name + '"' + 'title= "'+ attributes.name + '"' + ' style="position:absolute;left:'+ (attributes.newXafterColl) +'px;top:' + (attributes.YafterColl) + 'px;width:' + 30 + 'px;height:' + 50 + 'px;z-index:200;">' + '<img src="static/img/map/expand-icon.png" height="42" width="42"></div>');
+
+
+}
+
+plotContainer = function(container, cssType) {
+
+ attributes = container;
+ //console.log(attributes);
+ if(cssType === 'domain'){
+ $('#networkModelContainer').append('<div class="container ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;"><p class="textconetent" style="text-align:center;margin-top:11px;color:white;font-weight:bold;font-size:24px;">' + attributes.name + '</p></div>');
+ $('#networkModelContainer').append('<div class="contracttri"' + 'id= "' + attributes.name + '"' + ' style="position:absolute;left:'+ (attributes.left+attributes.width - 40) +'px;top:' + attributes.top + 'px;width:' + 20 + 'px;height:' + (attributes.height/3) + 'px;z-index:200;">' + '<img src="static/img/map/contract-icon.png" height="42" width="42"></div>');
+
+
+ }else if(attributes.visibilityType==='invisible'){
+
+ $('#networkModelContainer').append('<div ' + '" style="position:absolute;left:'+ (attributes.left+14) +'px;top:' + (attributes.top-5) + 'px;width:' + attributes.width + 'px;height:' + (attributes.height-35) + 'px;' + 'border:1px blue;"><p style="font-weight:bold;font-size:10px;">' + attributes.name + '</p></div>');
+
+ }else{
+
+ if(!recentCallFlow){
+ $('#networkModelContainer').append('<div class="container borderContainer ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;">' + '</div>');
+ //$('#networkModelContainer').append('<p class="speech"' + ' style="position:absolute;left:' + (attributes.left-20) + 'px;top:' + (attributes.top-30) + 'px;width:' + attributes.width + 'px"' + '>'+ attributes.name + '</p>');
+ plotHeader(attributes,cssType);
+ }else{
+ $('#networkModelContainer').append('<div class="container ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;">' + '</div>');
+ //$('#networkModelContainer').append('<p class="speech"' + ' style="position:absolute;left:' + (attributes.left-20) + 'px;top:' + (attributes.top-30) + 'px;width:' + attributes.width + 'px"' + '>'+ attributes.name + '</p>');
+ plotHeader(attributes,cssType);
+ }
+
+ }
+
+ plotNodes(container);
+
+ }
+
+plotContainerIcon = function(container, cssType) {
+ attributes = container;
+ //console.log(attributes);
+ if(cssType === 'domain'){
+ $('#networkModelContainer').append('<div class="container ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;"><p class="textconetent" style="text-align:center;margin-top:11px;color:white;font-weight:bold;font-size:24px;">' + attributes.name + '</p></div>');
+ $('#networkModelContainer').append('<div class="contracttri"' + 'id= "' + attributes.name + '"' + ' style="position:absolute;left:'+ (attributes.left+attributes.width - 40) +'px;top:' + attributes.top + 'px;width:' + 20 + 'px;height:' + (attributes.height/3) + 'px;z-index:200;">' + '<img src="static/img/map/contract-icon.png" height="42" width="42"></div>');
+
+ }else if(attributes.visibilityType==='invisible'){
+
+ $('#networkModelContainer').append('<div ' + '" style="position:absolute;left:'+ (attributes.left+14) +'px;top:' + (attributes.top-5) + 'px;width:' + attributes.width + 'px;height:' + (attributes.height-35) + 'px;' + 'border:1px blue;"><p style="font-weight:bold;font-size:10px;">' + attributes.name + '</p></div>');
+ }
+ else{
+ if(!recentCallFlow){
+ $('#networkModelContainer').append('<div class="container borderContainer ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;">' + '</div>');
+ //$('#networkModelContainer').append('<p class="speech"' + ' style="position:absolute;left:' + (attributes.left-20) + 'px;top:' + (attributes.top-30) + 'px;width:' + attributes.width + 'px"' + '>'+ attributes.name + '</p>');
+ plotHeader(attributes,cssType);
+ }else{
+ $('#networkModelContainer').append('<div class="container ' + cssType + '" style="position:absolute;left:'+ attributes.left +'px;top:' + attributes.top + 'px;width:' + attributes.width + 'px;height:' + attributes.height + 'px;z-index:-200;' + 'border:1px blue;">' + '</div>');
+ //$('#networkModelContainer').append('<p class="speech"' + ' style="position:absolute;left:' + (attributes.left-20) + 'px;top:' + (attributes.top-30) + 'px;width:' + attributes.width + 'px"' + '>'+ attributes.name + '</p>');
+ plotHeader(attributes,cssType);
+ }
+ }
+
+ plotNodesIcon(container);
+
+}
+
+joint.shapes.basic.newRect = joint.shapes.basic.Generic.extend({
+
+ markup: '<g class="rotatable"><g class="scalable"><rect/></g><text/></g>',
+
+ defaults: joint.util.deepSupplement({
+
+ type: 'basic.newRect',
+ attrs: {
+ 'rect': { fill: 'white', stroke: 'black', 'follow-scale': true, width: 80, height: 40},
+ 'text': { 'font-size': 14, 'ref-x': .5, 'ref-y': .5, ref: 'rect', 'y-alignment': 'middle', 'x-alignment': 'middle'}
+ },
+ shortname: 'Transcoder',
+ description: 'Reconciles mismatched CODECs',
+ longname: 'ACME SBC device providing dedicated Transcoder function',
+ vendor: 'ORACLE ACME',
+ primary_function: 'Allows endpoints utilizing different CODECs to communicate',
+ key_interface: 'SBC, MSC',
+ network_domain: 'Universal Services Platform - Access Module Group - ISA Core Office',
+
+}, joint.shapes.basic.Generic.prototype.defaults)});
+
+plotHeader = function(attributes,cssType){
+
+ var nameLength = attributes.name.length;
+ var headName;
+ if (nameLength>22){
+ headName = attributes.name.substring(0,12) + "-\n" + attributes.name.substring(12);
+
+ }else{
+ headName = attributes.name;
+ }
+
+ var thisElement = new joint.shapes.basic.newRect({
+ position: { x: attributes.left+10, y: attributes.top + 4 },
+ size: { width: attributes.width-20, height: 15 },
+ attrs: {
+ rect: { fill: "gray" ,stroke: "gray",opacity:"0.8"},
+ text: { text: headName, fill: 'black' ,'font-size':10, 'font-weight':'700','text-transform': 'capitalize'}
+
+ }
+ });
+ if(cssType==="outContainer"){
+
+ thisElement.attr({
+ rect:{fill:"#e7e7e7", stroke: "#e7e7e7",opacity:"0.8"}
+ });
+
+ }else{
+
+ thisElement.attr({
+ rect:{fill:"ghostwhite", stroke: "ghostwhite",opacity:"0.8"}
+ });
+
+
+ }
+ graph.addCells([thisElement]);
+
+}
+plotElement = function(element) {
+
+ if(element.left){
+ if(!element.id.startsWith("com.att.trinity.ue")){
+ left = element.left ;
+ var thisColor = element.bgColor;
+ var thisElement = new joint.shapes.basic.newRect({
+ id:element.id,
+ position: { x: element.left, y: element.top },
+ size: { width: element.width, height: element.height*2 },
+
+ attrs: {
+ rect: { fill: "lightgray" ,stroke: "gray"},
+ text: { text: element.name.replace(" ","\n"), fill: 'black' ,'font-size': 9, 'font-weight': 'bold','font-variant': 'small-caps', 'text-transform': 'capitalize'}
+
+ }
+
+ });
+ if(!recentCallFlow){
+ thisElement.attr({
+ rect:{fill:element.bgColor, stroke: thisColor}
+ });
+
+ }
+ //thisElement.attr({rect:{style:{"pointer-events":"none"}}});
+ thisElement.set('bg-color', (element.bgColor!= null?element.bgColor:"blue"));
+ thisElement.set('icon_path', (element.imgFileName != null? element.imgFileName: "static/img/map/icons/sgw-icon.png"));
+ thisElement.set('shortname', element.name);
+ thisElement.set('description', element.details.description);
+ thisElement.set('longname', element.details.display_longname);
+ thisElement.set('vendor', element.details.vendor);
+ thisElement.set('primary_function', element.details.primary_function);
+ thisElement.set('key_interface', element.details.key_interfaces);
+ thisElement.set('location', element.details.location);
+ thisElement.set('network_function', (element.details.network_function=="V")? "Virtual" : "Physical" );
+ if(element.borderType == 'dashed'){
+
+ thisElement.attr({
+ rect: {stroke: 'black','stroke-width':"2",'stroke-dasharray': "5,2" },
+ });
+
+ }
+
+
+ hash_map[element.name+'']=thisElement.name;
+ graph.addCells([thisElement]);
+
+ }else{
+ plotElementIcon(element);
+ }
+ }
+
+}
+
+joint.shapes.basic.DecoratedRect = joint.shapes.basic.Generic.extend({
+
+ markup: '<g class="rotatable"><g class="scalable"><rect/></g><image/><text/></g>',
+
+ defaults: joint.util.deepSupplement({
+
+ type: 'basic.DecoratedRect',
+ size: { width: 100, height: 60 },
+ attrs: {
+ 'rect': { fill: 'lightgray', width: 100, height: 60 },
+ 'text': { 'font-size': 14, text: '', 'ref-x': .5, 'ref-y': .5, ref: 'rect', 'y-alignment': 'middle', 'x-alignment': 'middle', fill: 'black'},
+ 'image': { ref: 'rect', width: 35, height: 25}
+ },
+ shortname: 'Transcoder',
+ description: 'Reconciles mismatched CODECs',
+ longname: 'ACME SBC device providing dedicated Transcoder function',
+ vendor: 'ORACLE ACME',
+ primary_function: 'Allows endpoints utilizing different CODECs to communicate',
+ key_interface: 'SBC, MSC',
+ network_domain: 'Universal Services Platform - Access Module Group - ISA Core Office',
+
+ }, joint.shapes.basic.Generic.prototype.defaults)
+});
+
+plotElementIcon = function(element) {
+
+
+ if(element.left){
+
+ left = element.left ;
+ uetop = element.top;
+ if(element.id.startsWith("com.att.trinity.ue")) {
+ uetop = element.top - 30;
+ } else {
+ uetop = element.top ;
+ }
+ var thisElement = new joint.shapes.basic.DecoratedRect({
+ id:element.id,
+ position: { x: element.left, y: uetop },
+ size: { width:element.width, height: element.height*2 },
+ // style:{'pointer-events':'none'},
+ attrs: {
+ //image: { 'xlink:href': 'static/img/map/icons/sgw-icon.png'
+ image: { 'xlink:href': element.imgFileName}
+ //rect:{style:{"pointer-events":"none"}}
+ // style:{'pointer-events':'none'}
+ // 'pointer-events':'none'
+ }
+ });
+ // thisElement.attr({rect:{style:{"pointer-events":"none"}}});
+ thisElement.set('bg-color', element.bgColor);
+ thisElement.set('icon_path', element.imgFileName);
+ thisElement.set('shortname', element.name);
+ thisElement.set('description', element.details.description);
+ thisElement.set('longname', element.details.display_longname);
+ thisElement.set('vendor', element.details.vendor);
+ thisElement.set('primary_function', element.details.primary_function);
+ thisElement.set('key_interface', element.details.key_interfaces);
+ thisElement.set('location', element.details.location);
+ thisElement.set('network_function', (element.details.network_function=="V")? "Virtual" : "Physical");
+
+ if(!recentCallFlow ){
+ thisElement.attr({
+ rect:{fill:element.bgColor }
+ });
+
+ }
+ if(element.borderType == 'dashed'){
+
+ thisElement.attr({
+ rect: {stroke: 'lightskyblue','stroke-width':"2",'stroke-dasharray': "5,2" },
+ });
+
+ }
+ if(element.id.startsWith("com.att.trinity.ue")){
+ thisElement.attr({
+ rect: {fill: 'white', style:{'pointer-events':'none'}},
+ image: { style:{'pointer-events':'none'}}
+ });
+
+ //thisElement.css('pointer-events', 'none');
+ // paper.thisElement.css('pointer-events', 'none');
+ }
+ hash_map[element.name+'']=thisElement.name;
+ graph.addCells([thisElement]);
+
+ }
+
+}
+
+
+plotNetMapCallFlow = function(callFlow, callFlowStep, collapsedDomainString, expandedDomainString, icon) {
+
+ init();
+
+ recentCallFlow = callFlow; //callFlow != null ? callFlow : recentCallFlow;
+ recentCallFlowStep = callFlowStep; //callFlowStep != null ? callFlowStep : recentCallFlowStep;
+
+ // $.get( "static/trisim_files/network_map.yml", function( data ) {
+
+ if(callFlow != null &&callFlow.title != null) {
+
+ $(".map-title").html(callFlow.title);
+
+ }else{
+ $(".map-title").html("Network Map");
+
+ }
+ $.post('network_model.htm?action=layout', {
+ collapsedDomains : collapsedDomainString,
+ expandedDomains : expandedDomainString
+ }, function(data) {
+ var yamlObject = jsyaml.load(data);
+
+ var layout = yamlObject.domainList;
+ for(var i=0; i<layout.length; i++) {
+ domain = layout[i];
+ if(icon)
+ plotContainerIcon(domain,'domain');
+ else
+ plotContainer(domain,'domain');
+
+ hashVertexDomainXMap[domain.name] = domain.left;
+ }
+
+ var collapseLayout = yamlObject.collapsedDomainList;
+ globalCollapseDomanString = "";
+ for(var i=0; i<collapseLayout.length; i++) {
+ domain = collapseLayout[i];
+ globalCollapseDomanString += (domain.name + ",");
+ plotExpand(domain);
+ addExpandEvents();
+
+ // some hardcoded hack; need to revise; if any one if these are collapsed , then we should not display hard coded links in addLinkVertices method
+ if((globalCollapseDomanString.indexOf("USP") > -1)|| (globalCollapseDomanString.indexOf("RAN") > -1)|| (globalCollapseDomanString.indexOf("EPC") > -1)) {
+ hashVertexDomainXMap["USP"] = -999;
+ hashVertexDomainXMap["RAN"] = -999;
+ hashVertexDomainXMap["EPC"] = -999;
+ }
+
+ }
+
+
+ addCollapseEvents(); //onclick="alert(\'hello\')"
+ //console.log(yamlObject);
+ //addLink('EATF','SDG');
+ if(icon == false)
+ $('.icons-toggle .toggle').removeClass("on");
+
+
+ if(callFlow != null && callFlow.id != null) {
+
+ // var callFlowLinkFile = callFlow + "_" + callFlowStep + ".yml";
+
+ $.post('network_model.htm?action=callflow', {
+ callFlowName : callFlow.id,
+ callFlowStep : callFlowStep
+ }, function( data ) {
+
+ try{
+ var yamlObject = jsyaml.load(data);
+ //addLink("EATF","MRF");
+ var layout = yamlObject.linkList;
+
+ var hashLinkElements = new Object();
+ for(var i=0; i<layout.length; i++) {
+ domain = layout[i];
+ try {
+ if(hashLinkElements[domain.s] != undefined)
+ hashLinkElements[domain.s] +=1;
+ else hashLinkElements[domain.s] =1;
+ if(hashLinkElements[domain.d] != undefined )
+ hashLinkElements[domain.d] +=1;
+ else hashLinkElements[domain.d] =1;
+ } catch (exception) {}
+ }
+
+ for(var i=0; i<layout.length; i++) {
+ domain = layout[i];
+ try {
+ addLink(domain.s,domain.d, hashLinkElements,'none');
+ } catch (exception) {}
+ }
+
+ //console.log(yamlObject);
+ }
+ catch(err) {}
+
+ $.post('network_model.htm?action=callflowAdditional', {
+ callFlowName : callFlow.id,
+ callFlowStep : callFlowStep
+ }, function( data ) {
+
+ try{
+ var yamlObject = jsyaml.load(data);
+ //addLink("EATF","MRF");
+ var layout = yamlObject.linkList;
+ if(layout != undefined)
+ for(var i=0; i<layout.length; i++) {
+ domain = layout[i];
+ try {
+ var source = domain.s.split(",");
+ var destination = domain.d.split(",");
+ addLinkVertices(source[0],source[1],source[2], source[3], destination[0], destination[1], destination[2],'none');
+
+ } catch (exception) {}
+ }
+
+ //make cells active
+ var activeIds = yamlObject.activeIds;
+ if(activeIds != undefined)
+ for(var i=0; i<activeIds.length; i++) {
+
+ var chosenElement1 = graph.getCell(activeIds[i]);
+ chosenElement1.attr({
+ rect: { fill: chosenElement1.get('bg-color')}
+ });
+ }
+
+ // disconnect some links
+
+ var disconnectLinks = yamlObject.disconnectLinks;
+ if(disconnectLinks != undefined)
+ var availableLinks = graph.getLinks();
+ //var availableLinks = paper.model.getLinks();
+ for(var i=0; i<disconnectLinks.length; i++) {
+
+ for(var j=0;j<availableLinks.length; j++) {
+
+ if(availableLinks[j].attributes.source.id != undefined ) {
+
+
+ if(disconnectLinks[i].s == availableLinks[j].attributes.source.id && disconnectLinks[i].d == availableLinks[j].attributes.target.id) {
+
+ availableLinks[j].remove();
+ break;
+ }
+
+ }
+ }
+ }
+
+
+ //console.log(yamlObject);
+ }
+ catch(err) {}
+ finally {
+
+ makeLinksVisible();
+ }
+
+
+ });
+
+
+ });
+
+
+
+
+
+
+ }
+
+
+ });
+
+
+
+
+
+
+};
+
+
+makeLinksVisible = function() {
+
+ var linkElements = $(".link");
+
+ for(var i= 0;i<linkElements.length;i++) {
+ var pathElement = linkElements[i].childNodes[0];
+ pathElement.attributes.display.value = 'inline';
+ }
+
+
+};
+
+parseYaml = function(callFlow, callFlowStep, collapsedDomainString, expandedDomainString) {
+ $('#containerScrollDiv').css("z-index",0);
+ plotNetMapCallFlow(callFlow, callFlowStep, collapsedDomainString, expandedDomainString,false);
+
+};
+
+
+parseYamlIcon = function(callFlow, callFlowStep, collapsedDomainString, expandedDomainString){
+ $('#containerScrollDiv').css("z-index",0);
+ plotNetMapCallFlow(callFlow, callFlowStep, collapsedDomainString, expandedDomainString,true);
+
+};
+
+addLinkVertices = function(sourceX,sourceY, sourceDomain, sourceLabel, destinationX, destinationY, destinationDomain, display){
+
+ if(Number(hashVertexDomainXMap[sourceDomain]) == -999)
+ return ;
+
+ var link = new joint.dia.Link({
+ source: { x: Number(hashVertexDomainXMap[sourceDomain]) + Number(sourceX), y: Number(sourceY)},
+ target: { x: Number(hashVertexDomainXMap[destinationDomain]) + Number(destinationX), y: Number(destinationY)},
+ attrs: {
+ '.connection': {
+ stroke: '#b5af4c',
+ //stroke:getColor(id1,id2),
+ 'stroke-width': 2,
+ 'display' : (display == undefined ? 'block' : display)
+ }
+ }
+
+ });
+
+ if(sourceLabel != "-" ) {
+
+ link.label(0, {
+ position: .5,
+ attrs: {
+ text: { fill: 'black', text: sourceLabel.replace(" ","\n") }
+ }
+ });
+
+ }
+
+ graph.addCells([link]);
+ link.toBack();
+
+}
+
+addLink = function(id1,id2, hashLinkElements, display){
+
+ var elementId1 = graph.getCell(id1);
+ var elementId2 = graph.getCell(id2);
+ var elementId1x = elementId1.attributes.position.x;
+ var elementId1y = elementId1.attributes.position.y;
+ var elementId2x = elementId2.attributes.position.x;
+ var elementId2y = elementId1.attributes.position.y;
+
+
+ var link = new joint.dia.Link({
+ source: { id: elementId1.id},
+ target: { id: elementId2.id},
+ //source: { x: elementId1.attributes.position.x+10, y: elementId1.attributes.position.y+10},
+ //target: { x: elementId2.attributes.position.x+10, y: elementId2.attributes.position.y+10},
+ router: { name: 'manhattan' },
+ connector: { name: 'normal' },
+ attrs: {
+ '.connection': {
+ //stroke: '#333333',
+ stroke:getColor(id1,id2),
+ 'stroke-width': 2,
+ 'z-index' :-300,
+ 'display' : (display == undefined ? 'block' : display)
+ },
+
+ },
+ });
+
+ graph.addCells([link]);
+ link.toBack();
+ //link.set('vertices', [{ x: (elementId1x + elementId2x)/2 , y: (elementId1y + elementId2y)/2 }]);
+ //link.translate(10, 10);
+
+
+ var chosenElement1 = graph.getCell(id1);
+ chosenElement1.attr({
+ rect: { fill: chosenElement1.get('bg-color')}
+ });
+ var chosenElement2 = graph.getCell(id2);
+ chosenElement2.attr({
+ rect: { fill: chosenElement2.get('bg-color')}
+ });
+
+ // logic to avoid overlapping links ; create dummy hidden objects at the vertices so that smart routing will avoid these obstacle when plotting the link
+ if(hashLinkElements[id1]> 0 || hashLinkElements[id2] >0) {
+ var linkElement = $("[model-id^=" + link.id +"]");
+ var pathElement = linkElement.children("path")[0];
+ var pathCoordinates = pathElement.attributes.d.value.split(" ");
+ for(var i = 1; i<pathCoordinates.length/2 ;i+=2) {
+
+ try{
+ // plot an element on the starting points
+ plotHiddenDummyElement(link.id+"-"+i,Number(pathCoordinates[i]), Number(pathCoordinates[i+1]) );
+ }catch(err){
+ console.log(err);
+ }
+
+ try{
+ // plot half way on the edge too
+ plotHiddenDummyElement(link.id+"--"+i,(Number(pathCoordinates[i])+Number(pathCoordinates[i+2]))/2, (Number(pathCoordinates[i+1])+Number(pathCoordinates[i+3]))/2 );
+ }catch(err){}
+
+ }
+ var newPathCoordinates = "M";
+ // in IE every XandY coordinates pair is delimited with L; so two x coordinates are 2 elements apart. In firefox and chrome, they are one element apart. For more clarification,
+ // check the pathCoordinates in debug window
+ var nextIndex = Browser.isIE == true ? 3 : 2;
+ for(var i = 1; i<pathCoordinates.length ;i++) {
+ if( i == 1 ) {
+ if(pathCoordinates[i] == pathCoordinates[i+nextIndex]) {// x coordinates are the same
+ var originalI = Number(pathCoordinates[i]);
+ var newI = originalI + (Number(hashLinkElements[id1])*2);
+
+ // iteratively change the x coordinates for all the segments
+ for(var j = i; j<pathCoordinates.length; j+=nextIndex) {
+ if(pathCoordinates[j] == originalI)
+ pathCoordinates[j] = newI;
+ }
+
+ }
+ else if(pathCoordinates[i+1] == pathCoordinates[i+1+nextIndex]) {// y coordinates are the same
+
+ var originalI = Number(pathCoordinates[i+1]);
+ var newI = originalI - (Number(hashLinkElements[id1])*2);
+
+ // iteratively change the y coordinates for all the segments
+ for(var j = i+1; j<pathCoordinates.length; j+=nextIndex) {
+ if(pathCoordinates[j] == originalI)
+ pathCoordinates[j] = newI;
+ }
+
+ }
+
+ hashLinkElements[id1]-=1;
+ }
+ newPathCoordinates += " "+ pathCoordinates[i];
+ }
+
+ pathElement.attributes.d.value = newPathCoordinates;
+
+ }
+ //
+
+};
+
+plotHiddenDummyElement = function(dummyId, left, top) {
+
+ var thisElement = new joint.shapes.basic.newRect({
+ id:dummyId,
+ position: { x: left-5, y: top-5 },
+ size: { width: 10, height: 10 }
+ });
+
+ thisElement.attr('./display', 'none');
+ graph.addCells([thisElement]);
+
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+init = function() {
+
+ $('.close-btn').click(function (a) {
+ $('#popup').fadeOut();
+ });
+
+
+ if ( window.name === tsWindow.detailWindow && tsWindow.newWindow !== null ) {
+ $("#map-controls").fadeOut();
+ } else {
+ $("#map-controls").fadeIn();
+ }
+ colorIndex= 0;
+
+ if(!changeIcon){
+ //$('.legend-toggle .toggle').addClass("on");
+ //$("#legend").fadeIn(350);
+ }
+
+ if(typeof graph!=='undefined'){
+ graph.clear();
+ $('#networkModelContainer').empty();
+ }
+ graph = new joint.dia.Graph;
+
+ paper = new joint.dia.Paper({
+ interactive: false,
+ el: $('#networkModelContainer'),
+ width: "1400",
+ height: 1000,
+ model: graph,
+ gridSize: 1
+ });
+
+ //paper.setOrigin(100,100);
+
+ // paper.$el.css('pointer-events', 'none');
+ paper.on('cell:pointerdown',
+ function(cellView, evt, x, y) {
+
+ var clickedElement = graph.getCell(cellView.model.id);
+ if(clickedElement.get('icon_path')!=null){
+
+ // if (clickedElement.get('description') != '') {
+
+ $('#popupImg').attr('src',clickedElement.get('icon_path'));
+ $("#popupImg").css("background-color",clickedElement.get('bg-color'));
+ $('#shortname').text(clickedElement.get('shortname'));
+ $('#longname').text(clickedElement.get('longname'));
+ $('#name').text(clickedElement.get('longname'));
+ $('#description').text(clickedElement.get('description'));
+ $('#vendor').text(clickedElement.get('vendor'));
+ $('#primary_function').text(clickedElement.get('primary_function'));
+ $('#key_interface').text(clickedElement.get('key_interface'));
+ $('#location').text(clickedElement.get('location'));
+ $('#network_function').text(clickedElement.get('network_function'));
+ $('#popup').fadeIn();
+ // }
+ }
+
+
+ }
+
+
+ );
+
+ /**
+ * Zoom In/Out Button
+ */
+ var w = $("#networkModelContainer").css("width");
+ var h = $("#networkModelContainer").css("height");
+ $('#btn-zoom-in').unbind("click");
+ $('#btn-zoom-in').click(function (a) {
+ zoomIndex+=0.04;
+ //$("#containerScrollDiv").css("transform",'scale('+ zoomIndex + ')');
+ //$("#containerScrollDiv").css("transform-origin",'top left');
+ $("#networkModelContainer").css("transform",'scale('+ zoomIndex + ')');
+ $("#networkModelContainer").css("transform-origin",'top left');
+ $("#networkModelContainer").css("width",w);
+ $("#networkModelContainer").css("height",h);
+ $("#containerScrollDiv").mCustomScrollbar('update');
+ //$("#containerScrollDiv").mCustomScrollbar({
+ // axis:"yx" //horizontal scrollbar
+ // });
+
+
+ });
+ $('#btn-zoom-out').unbind("click");
+
+ $('#btn-zoom-out').click(function (a) {
+
+ if(zoomIndex > 0.9){
+ zoomIndex-=0.04;
+ //$("#containerScrollDiv").css("transform",'scale('+ zoomIndex + ')');
+ //$("#containerScrollDiv").css("transform-origin",'top left');
+ $("#networkModelContainer").css("transform",'scale('+ zoomIndex + ')');
+ $("#networkModelContainer").css("transform-origin",'top left');
+ $("#networkModelContainer").css("width",w);
+ $("#networkModelContainer").css("height",h);
+
+ //$("#containerScrollDiv").mCustomScrollbar('update');
+ $("#containerScrollDiv").mCustomScrollbar('destroy');
+ $("#containerScrollDiv").mCustomScrollbar({
+ axis:"yx", //horizontal scrollbar
+ theme:"3d-thick-dark",
+ scrollButtons:{enable:true},
+ alwaysShowScrollbar:2
+ });
+ }
+
+ });
+
+
+ $('.icons-toggle').unbind("click");
+ $('.icons-toggle').click(function (a) {
+
+ if($('.icons-toggle .toggle').hasClass("on")){
+
+ changeIcon = true;
+ $("#networkModelContainer").empty();
+ parseYamlIcon(recentCallFlow, recentCallFlowStep, globalCollapseDomanString);
+
+ }else{
+
+ changeIcon = true;
+ $("#networkModelContainer").empty();
+ parseYaml(recentCallFlow, recentCallFlowStep, globalCollapseDomanString);
+
+ }
+
+ });
+
+ paper.$el.addClass('connecting');
+
+
+};
+
+
+
+ addCollapseEvents = function() {
+
+ /*$(document).on("click",".contract",function() {
+ alert("click bound to document listening for #test-element");
+ });
+ */
+ var contractElement =$('.contracttri');
+
+ contractElement.unbind("click");
+ contractElement.css('cursor', 'pointer');
+ contractElement.click(function() {
+
+ if($('.icons-toggle .toggle').hasClass("on")){
+
+ $("#networkModelContainer").empty();
+ parseYamlIcon(recentCallFlow, recentCallFlowStep, (globalCollapseDomanString + this.id));
+
+ }else{
+
+ $("#networkModelContainer").empty();
+ parseYaml(recentCallFlow, recentCallFlowStep, (globalCollapseDomanString + this.id));
+
+ }
+
+ });
+
+ };
+
+
+ addExpandEvents = function() {
+
+ /*$(document).on("click",".contract",function() {
+ alert("click bound to document listening for #test-element");
+ });
+ */
+ var contractElement =$('.expandtri');
+
+ contractElement.unbind("click");
+ contractElement.css('cursor', 'pointer');
+ contractElement.click(function() {
+
+ if($('.icons-toggle .toggle').hasClass("on")){
+
+ $("#networkModelContainer").empty();
+ parseYamlIcon(recentCallFlow, recentCallFlowStep, globalCollapseDomanString, (this.id));
+
+ }else{
+
+ $("#networkModelContainer").empty();
+ parseYaml(recentCallFlow, recentCallFlowStep, globalCollapseDomanString, (this.id));
+
+ }
+
+ });
+
+};
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/adminService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/adminService.js
new file mode 100644
index 00000000..cb5fb80d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/adminService.js
@@ -0,0 +1,141 @@
+app.factory('AdminService', function ($http, $q) {
+ return {
+ getRoles: function() {
+ return $http.get('get_roles')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getRoleFunctionList: function() {
+ return $http.get('get_role_functions')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getFnMenuItems: function(){
+
+ return $http.get('admin_fn_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getCacheRegions: function() {
+ return $http.get('get_regions')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getUsageList: function() {
+ return $http.get('get_usage_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getBroadcastList: function() {
+ return $http.get('get_broadcast_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getBroadcast: function(messageLocationId, messageLocation, messageId) {
+ return $http.get('get_broadcast?message_location_id='+messageLocationId + '&message_location=' + messageLocation + ((messageId != null) ? '&message_id=' + messageId : ''))
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getCollaborateList: function() {
+ return $http.get('get_collaborate_list')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getRole: function(roleId) {
+
+ return $http.get('get_role?role_id=' + roleId)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+ };
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/headerService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/headerService.js
new file mode 100644
index 00000000..4566c8fa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/headerService.js
@@ -0,0 +1,70 @@
+var menuStructureConvert = function(menuItems) {
+ var megaMenuDataObjectTemp = [
+ {
+ text: "ECOMP",
+ children:menuItems
+ },
+ {
+ text: "Help",
+ children: [{
+ text:"Contact Us",
+ url:"javascript:angular.element('[ng-controller=headerController]').scope().redirectLink('contact');"
+ },
+ {
+ text:"Get Access",
+ url:"javascript:angular.element('[ng-controller=headerController]').scope().redirectLink('access');"
+ }]
+ }
+ ];
+ return megaMenuDataObjectTemp;
+};
+var unflatten = function( array, parent, tree ){
+ tree = typeof tree !== 'undefined' ? tree : [];
+ parent = typeof parent !== 'undefined' ? parent : { menuId: null };
+ var children = _.filter( array, function(child){ return child.parentMenuId == parent.menuId; });
+
+ if( !_.isEmpty( children ) ){
+ if( parent.menuId === null ){
+ tree = children;
+ }else{
+ parent['children'] = children
+ }
+ _.each( children, function( child ){ unflatten( array, child ) } );
+ }
+
+ return tree;
+ }
+app.service('HeaderService', function ($http,$log, $q,UserInfoService) {
+ return{
+
+ getUserNameFromSession : function(){
+ UserInfoService.getFunctionalMenuStaticDetailSession()
+ .then(function (res) {
+ $scope.userName = res.userName;
+ $scope.redirectUrl = res.portalUrl;
+ });
+ },
+ getTopMenuStaticInfo:function() {
+ var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
+ promise.then(
+ function(res) {
+ if(res==null || res==''){
+ $log.info('failed getting static User information');
+ this.getUserNameFromSession();
+ }else{
+ $log.info('Received static User information');
+ var resData = res;
+ $scope.inputUserInfo(resData);
+ $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
+ return $scope.userProfile;
+ }
+ },
+ function(err) {
+ $log.info('failed getting static User information');
+ }
+ );
+ }
+ }
+ }
+);
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/leftMenuService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/leftMenuService.js
new file mode 100644
index 00000000..12e19df2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/leftMenuService.js
@@ -0,0 +1,35 @@
+function isRealValue(obj){
+ return obj && obj !== "null" && obj!== "undefined";
+}
+app.factory('LeftMenuService', function ($http,$log, $q) {
+ return {
+ getLeftMenu: function() {
+ return $http.get('get_menu')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+ getAppName: function() {
+ return $http.get('get_app_name')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+
+ };
+});
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/profileService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/profileService.js
new file mode 100644
index 00000000..ca4252df
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/profileService.js
@@ -0,0 +1,79 @@
+
+app.factory('ProfileService', function ($http, $q) {
+ return {
+ getProfile: function() {
+ return $http.get('get_user')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getProfilePagination: function(pageNum,viewPerPage) {
+ return $http.get('get_user_pagination?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getPostProfile: function() {
+ return $http.get('post_search_sample')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getProfileDetail: function(profileId) {
+ return $http.get('get_profile?profile_id='+profileId)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getSelfProfileDetail: function() {
+ return $http.get('get_self_profile')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/userInfoService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/userInfoService.js
new file mode 100644
index 00000000..66aa1c18
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/services/userInfoService.js
@@ -0,0 +1,32 @@
+app.factory('UserInfoService', function ($http, $q,$log) {
+ return {
+ getFunctionalMenuStaticDetailShareContext: function(contextId,key) {
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_userinfo",
+ }).success( function(res) {
+ if(res==null || res=='')
+ $log.info('Not be able to get User Info via shared context');
+ deferred.resolve(res);
+ }).error( function(status) {
+ deferred.reject(status);
+ });
+ return deferred.promise;
+ },
+ getFunctionalMenuStaticDetailSession: function() {
+ var deferred = $q.defer();
+ $http({
+ method: "GET",
+ url: "get_topMenuInfo",
+ }).success(function(res) {
+ if(res==null || res=='')
+ $log.info('Not be able to get User Info via shared context');
+ deferred.resolve(res);
+ }).error( function(status) {
+ deferred.reject(status);
+ });
+ return deferred.promise;
+ }
+ };
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js
new file mode 100644
index 00000000..d056ce48
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js
@@ -0,0 +1,103 @@
+
+var output = $('#peerBroadcastSection');
+var websocket = '';
+var currentUser = '';
+var remoteUser = '';
+var f = '';
+var popupService;
+
+function setPopupService(_popupService) {
+ popupService = _popupService;
+}
+
+function socketSetup(initialPageVisit,_currentUser, _remoteUser, _f) {
+
+
+
+ if( true) {
+
+ var href = window.location.href;
+ var hostPatt = new RegExp(window.location.host +"/[^/]*");
+ var res = hostPatt.exec(href);
+ var protocol = window.location.protocol.replace("http","ws");
+
+ var signalingServerPath = protocol + "//" + res + "/contact";
+ var wsUri = signalingServerPath;
+ console.log("Connecting to " + wsUri);
+ websocket = new WebSocket(wsUri);
+ //localStorage.notifySocket = JSON.stringify(websocket);
+ //window.top.notifySocket = websocket;
+
+ currentUser = _currentUser;
+ remoteUser = _remoteUser;
+ f = socketSend;
+
+
+ }
+
+ //var websocket = JSON.parse(localStorage.notifySocket || "{}") ;
+ if( websocket != null) {
+ websocket.onopen = function(evt) { onOpen(evt); };
+ websocket.onmessage = function(evt) { onMessage(evt); };
+ websocket.onerror = function(evt) { onError(evt); };
+
+ }
+
+ //if(f != undefined)
+ // f();
+
+ //window.top.notifySocket.send("");
+}
+
+
+function socketSend(currentUser, remoteUser) {
+
+
+
+ websocket.send(JSON.stringify({
+ from: currentUser,
+ to: remoteUser
+ }));
+
+ //window.top.notifySocket.send("");
+}
+
+
+
+
+function onOpen(evt) {
+ console.log("onOpen");
+ //writeToScreen("CONNECTED");
+
+ if(f != undefined)
+ f(currentUser, remoteUser);
+
+}
+
+function onMessage(evt) {
+ if (typeof evt.data == "string") {
+ writeToScreen("RECEIVED (text): " + evt.data);
+
+ if(popupService != undefined) {
+ popupService.showMessage("Call Request","You are being contacted by " + JSON.parse(evt.data).from + ". Please click on the online icon and then click view");
+
+ }
+ //if (confirm("You are being contacted by " + JSON.parse(evt.data).from )) {
+
+ //}
+
+ } else {
+ writeToScreen("RECEIVED (binary): " + evt.data);
+ }
+}
+
+function onError(evt) {
+ writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
+}
+
+function writeToScreen(message) {
+ var pre = document.createElement("p");
+ pre.style.wordWrap = "break-word";
+ pre.innerHTML = message;
+ output.append(pre);
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/directives/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/directives/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html
index d04eba9c..d04eba9c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/utils/sandbox-resources.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/utils/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/utils/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/header.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/header.html
index adb5be35..e7616d94 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/header.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/header.html
@@ -1,22 +1,3 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
<div style="position: relative; z-index: 999;">
<div class="headerContainer" id="headerContainer" ng-show="{{showHeader}}">
<div style="position: relative; z-index: 999;">
@@ -29,8 +10,8 @@
<div parentmenu-tabs mega-menu="true" menu-items="megaMenuDataObject" style="height:55px;">
<div style="float:left">
<li class="megamenu__item" style="line-height:55px;" ng-click="returnToPortal()">
- <div></div>
- <strong style="font-weight: 400 !important; font-family: Arial !important; font-size: 18px;" >ECOMP Portal</strong>
+
+ <strong style="font-weight: 400 !important; font-family: clearview_att_bold !important; font-size: 18px;" >ECOMP Portal</strong>
</li>
<div menu-tabs mega-menu="true" tab-name="item.text" menu-item="item"
active-menu="activeClickMenu.x"
@@ -114,7 +95,7 @@
</div>
<div>
<br>
- <p style='font-weight: 400; font-family: Arial !important;
+ <p style='font-weight: 400; font-family: clearview_att_bold !important;
font-size: 18px; text-align: center; background-color: lightgray;
width: 400px; margin-left: 25%; margin-right: 25%;'>
Manage favorites on ECOMP Portal.
@@ -135,21 +116,18 @@
</div>
</div >
<li class="megamenu__item" style="line-height:55px;" ng-if="loadMenufail">
- <strong style="font-weight: 400 !important; font-family: Arial !important; font-size: 18px;" >Unable to load menus</strong>
+ <strong style="font-weight: 400 !important; font-family: clearview_att_bold !important; font-size: 18px;" >Unable to load menus</strong>
</li>
<div style="float:right">
<li id="bcLoginSnippet" class="megamenu__item" style="width: 140px;" >
<div popover="loginSnippet.html" aria-label="Login Snippet"
referby="loginSnippet" att-accessibility-click="13,32" popover-style="\" popover-placement="below" style="width: 200px;">
- <div class="ion-android-person login-snippet-icon" style="display:inline-block"></div>
+ <div class="icon-user-small login-snippet-icon"></div>
<div class="login-snippet-text" style="display: inline-block; font-size:12px; margin-left:5px;overflow: hidden; max-height: 31px; overflow: hidden; max-height: 31px; max-width:120px; padding-top: 0px; margin-top: 0px; white-space: nowrap;">{{userFirstName}}</div>
</div>
</li>
- <li class="megamenu__item" style="width:120px;">&nbsp;</li>
</div>
-
</div>
-
</div>
</div>
<div style="clear: both"></div>
@@ -177,9 +155,7 @@
<li><div class="reg-userName-table"><div id="reg-userName-table-row"><div id="reg-userName-table-cell"><h3 class="att-global-fonts" style="font-size:18px !important;" id="reg-userName">{{userProfile.fullName}}&nbsp;</h3><span class="visuallyhidden">.</span></div></div></div></li>
<li><div class="reg-userEmail-label"><span class="reg-userEmail-label-spn">EMAIL<span class="visuallyhidden">:</span></span></div></li>
<li><div class="reg-userEmail-value"><span class="reg-userEmail-value-spn">{{userProfile.email}}<span class="visuallyhidden">.</span></span></div></li>
- <li><div class="reg-userRole-label"><span class="reg-userRole-label-spn">User ID<span class="visuallyhidden">:</span></span></div></li>
- <li><div class="reg-userRole-value"><span class="reg-userRole-value-spn">{{userProfile.orgUserId}}<span class="visuallyhidden"></span></span></div></li>
- </ul>
+ </ul>
</div>
</div>
</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/left_menu.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/left_menu.html
new file mode 100644
index 00000000..ad4e5d91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/left_menu.html
@@ -0,0 +1,27 @@
+ <div class="license-notification">
+ <a href="javascript:void(0)" style="background-color:#bbb;" class="button button--small" tooltip="Please contact ECOMP Portal team to get the license" tooltip-placement="below" tooltip-style="light" tooltip-popup-delay="500" >
+ <span style="">{{app_name_full}}</span>
+ </a>
+</div>
+<div ng-cloak>
+ <span ng-style="adjustHLeftMenu('burgerIcon')" style="z-index:998; position:fixed; left:0%; font-size:35px; margin-left:10px;text-decoration:none;">
+ <a ng-click="toggleDrawer();isOpen = !isOpen" href="javascript:void(0);" class="arrow-icon-left" >
+ <span class="icon-hamburger"></span></a>
+ <span ng-init="isOpen = true" ng-show="isOpen" style="font-size:16px; position:relative; top:-8px; left:-15px;">&nbsp&nbsp&nbsp {{app_name}}</span>
+ </span>
+ <div att-drawer drawer-slide="left" drawer-custom-top="{{drawer_custom_top}}px" drawer-size="200px" drawer-open="drawerOpen" drawer-custom-height="100%" >
+ <div ng-style="adjustHLeftMenu('leftMenu')">
+ <div class="attDrawer" style="z-index:998">
+ <div class="appLeftMenuAccordDiv">
+ <accordion close-others="true" css="att-accordion--no-box">
+ <accordion-group ng-repeat="parent in leftMenuItems" heading="{{parent.parentLabel}}" parent-link="{{parent.parentAction}}" image-source="{{parent.parentImageSrc}}" child-length="{{parent.childItemList.length}}" is-open="parent.open">
+ <div ng-repeat="subMenu in parent.childItemList" style="font-size:12px; margin-left:10px;">
+ <a href="{{subMenu.action}}" style="font-size:12px; color:#666666;" >{{subMenu.label}}</a>
+ </div>
+ </accordion-group>
+ </accordion>
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_closed_loop.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_closed_loop.html
new file mode 100644
index 00000000..a3a5dfc1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_closed_loop.html
@@ -0,0 +1,20 @@
+<div style="margin-left:0px; margin-right:50px;" id="fnMenueContent">
+ <div class="pageTitle" align="left">
+
+ <h1 class="heading1" style="margin-top:20px;">Closed Loop</h1>
+ <br/>
+ <br>
+ </div>
+ <div style="margin-right: 20px;text-align: justify;text-align-last:auto;">
+ Cloop Server
+ </div>
+ <br>
+
+ <div id="hiddenCamundaDiv" style="width:500px;"></div>
+ <br>
+ <iframe id="camundaFrame"
+ ng-src="{{camunda_cockpit_url}}"
+ width="100%" height="500"
+ ></iframe>
+</div>
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html
new file mode 100644
index 00000000..9ffd9810
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html
@@ -0,0 +1,42 @@
+<div style="width:80%;margin-bottom:20px">
+ <br/>
+ <h1 class="heading1">Broadcast Message Edit</h1>
+ <br/>
+
+ <div ng-controller="broadcastController" >
+ Please edit the broadcast message details below:&nbsp;<br><br>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Message Text:</label><BR>
+ <textarea name="comment" ng-model="broadcastMessage.messageText" rows="5" cols="200" style="height:100px"></textarea>
+ </div>
+ <br>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Start Date:</label><BR>
+ <input type="hidden" name="startDateHidden" ng-model="broadcastMessage.startDate">
+ <input type="text" class="fn-ebz-text" id="startDatepicker" />
+ </div>
+
+ <div class="fn-ebz-container" style="margin-left:3em" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>End Date:</label><BR>
+ <input type="hidden" name="endDateHidden" ng-model="broadcastMessage.endDate">
+ <input type="text" class="fn-ebz-text" id="endDatepicker" />
+ </div>
+
+ <div class="fn-ebz-container" style="margin-left:3em" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Sort Order:</label><BR>
+ <input type="text" class="fn-ebz-text" ng-model="broadcastMessage.sortOrder"
+ maxlength="30" />
+ </div>
+
+ <div class="fn-ebz-container" style="margin-left:1em" >
+ <label class="fn-ebz-text-label">Server:</label><BR>
+ <div class="form-field" att-select="broadcastSites" ng-model="broadcastMessage.siteCd"></div>
+ </div>
+
+ <br>
+ <div align="left" >
+ <button type="submit" ng-click="save();" att-button btn-type="primary" size="small">Save</button>
+ <button class="button button--information button--small" herf="javascript:void(0)" ng-click="close();">Cancel</button>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html
new file mode 100644
index 00000000..512ce7e8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html
@@ -0,0 +1,52 @@
+<div style="width:80%;">
+
+<div ng-controller="broadcastListController" >
+
+ <h1 class="heading1">Broadcast Messages</h1>
+ <br>
+ <div ng-repeat="location in messageLocations" >
+ {{location.label}} Messages
+ <div title="{{location.label}} Messages">
+
+ <table att-table table-data="location.messages" current-page="1">
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header sortable="false" width="10%">No.</th>
+ <th att-table-header sortable="false" width="30%">Message Text</th>
+ <th att-table-header sortable="false" width="10%">Start Date</th>
+ <th att-table-header sortable="false" width="10%">End Date</th>
+ <th att-table-header sortable="false" width="10%">Sort Order</th>
+ <th att-table-header sortable="false" width="10%">Server</th>
+ <th att-table-header sortable="false" width="10%">Active?</th>
+ <th att-table-header sortable="false" width="10%">Delete?</th>
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" row-repeat="message in location.messages" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
+ <tr>
+ {{message.id}}
+ <td width="10%"><a href="javascript:editMessage({{location.value}},'{{location.label}}',{{message.id}});">{{$index+1}}</a></td>
+ <td width="30%">{{message.messageText}}</td>
+ <td width="10%">
+ {{message.displayStartDate}}
+ </td>
+ <td width="10%">{{message.displayEndDate}}</td>
+ <td width="10%">{{message.sortOrder}}</td>
+ <td width="10%">{{message.siteCd}}</td>
+ <td width="10%">
+ <div ng-click="toggleActive(message);">
+ <input type="checkbox" ng-model="message.active" att-toggle-main>
+ </div>
+ </td>
+ <td att-table-body width="10%">
+ <div ng-click="remove(message);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-trash"></a></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </div>
+ <input att-button btn-type="primary" size="small" class="button" type="button" value="Add" ng-click="editMessage(location);"/>
+ <br/><br/><br/>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html
index 3cde902c..433e0c3f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal.html
@@ -1,22 +1,3 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
<script type="text/ng-template" id="modal_informative.html">
<div class="modal__informative font-showcase" >
<div class="modal__header">
@@ -279,4 +260,4 @@
<button class="button button--primary button--small" herf="javascript:void(0)" ng-click="$dismiss()">Cancel</button>
</div>
</div>
- </script>
+ </script> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html
index 760f10b5..b1c9135a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html
@@ -1,22 +1,3 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
<script type="text/ng-template" id="fn_menu_add_popup.html">
<div class="modal__informative font-showcase" style="width:1100px;">
<div class="modal__header">
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html
index 4c23ba6f..2ccdf2af 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html
@@ -1,22 +1,3 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
<script type="text/ng-template" id="edit_menu_item_popup.html">
<div class="modal__informative font-showcase" style="width:1100px;">
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html
new file mode 100644
index 00000000..cbfd6133
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html
@@ -0,0 +1,75 @@
+
+<script type="text/ng-template" id="role_functions_popup.html">
+ <div class="modal__informative font-showcase" style="width:700px;height:500px;overflow:scroll">
+ <div class="modal__header">
+ <h2 class="font-showcase-font-name" style="width: 500px;">Select Role Functions</h2>
+ </div>
+ <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
+ <div class="divider-container"><hr> </div>
+ <div class="modal__content">
+ <table att-table
+ table-data="availableRoleFunctions"
+ view-per-page="viewPerPageIgnore"
+ current-page="currentPageIgnore"
+ search-category="searchCategoryIgnore"
+ search-string="searchStringIgnore"
+ total-page="totalPageIgnore">
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header sortable="false" width="10%"> </th>
+ <th att-table-header sortable="false" width="90%">Role Function</th>
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" row-repeat="availableRoleFunction in availableRoleFunctions" style="max-height: 980px;" >
+ <tr>
+
+ <td width="10%">
+ <div ng-click="toggleRoleFunction(availableRoleFunction.selected,availableRoleFunction);">
+ <input type="checkbox" ng-model="availableRoleFunction.selected" att-toggle-main>
+ </div>
+ </td>
+ <td width="90%">{{ availableRoleFunction.name }}</td>
+
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</script>
+
+
+<script type="text/ng-template" id="child_roles_popup.html">
+ <div class="modal__informative font-showcase" style="width:700px;height:500px;overflow:scroll">
+ <div class="modal__header">
+ <h2 class="font-showcase-font-name" style="width: 500px;">Select Child Roles</h2>
+ </div>
+ <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
+ <div class="divider-container"><hr> </div>
+ <div class="modal__content">
+ <table att-table
+ table-data="availableRoles"
+ view-per-page="viewPerPageIgnore"
+ current-page="currentPageIgnore"
+ search-category="searchCategoryIgnore"
+ search-string="searchStringIgnore"
+ total-page="totalPageIgnore">
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header sortable="false" width="10%"> </th>
+ <th att-table-header sortable="false" width="90%">Role</th>
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" >
+ <tr>
+ <td att-table-body width="10%">
+ <div ng-click="toggleChildRole(availableRole.selected,availableRole);">
+ <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
+ </div>
+ </td>
+ <td att-table-body width="90%">{{ availableRole.name }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html
new file mode 100644
index 00000000..b5fd76ad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html
@@ -0,0 +1,27 @@
+<script type="text/ng-template" id="edit_role_function_popup.html">
+ <div class="modal__informative font-showcase" style="width:400px;">
+ <div class="modal__header">
+ <h2 class="font-showcase-font-name" style="width: 500px;">{{label}}</h2>
+ </div>
+ <div class="divider-container"><hr> </div>
+ <div class="modal__content">
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><br>
+ <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.name"
+ maxlength="30" />
+ </div>
+ <br/>
+ <div class="fn-ebz-container" >
+ <label class="fn-ebz-text-label"><sup><b>*</b></sup>Code:</label><br>
+ <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.code" ng-disabled="disableCd"
+ maxlength="30" />
+ </div>
+ </div>
+ <div class="modal__footer">
+ <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="saveRoleFunction(editRoleFunction);">Save</button>
+ <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
+ </div>
+ </div>
+</script>
+
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/customWidgetSettings.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/customWidgetSettings.js
new file mode 100644
index 00000000..6cabe9f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/customWidgetSettings.js
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .controller('CustomSettingsDemoCtrl', function($scope, $interval, $window, widgetDefinitions, defaultWidgets, RandomDataModel) {
+
+
+ // Add an additional widget with setting overrides
+ var definitions = [{
+ name: 'congfigurable widget',
+ directive: 'wt-scope-watch',
+ dataAttrName: 'value',
+ dataModelType: RandomDataModel,
+ dataModelOptions: {
+ limit: 10
+ },
+ settingsModalOptions: {
+ partialTemplateUrl: 'template/configurableWidgetModalOptions.html'
+ },
+ onSettingsClose: function (result, widget) {
+ if (widget.dataModel && widget.dataModel.updateLimit) {
+ widget.dataModel.updateLimit(result.dataModelOptions.limit);
+ }
+ }
+ }, {
+ name: 'override modal widget',
+ directive: 'wt-scope-watch',
+ dataAttrName: 'value',
+ dataModelType: RandomDataModel,
+ settingsModalOptions: {
+ templateUrl: 'template/WidgetSpecificSettings.html',
+ controller: 'WidgetSpecificSettingsCtrl',
+ backdrop: false
+ },
+ onSettingsClose: function(result, widget) {
+ console.log('Widget-specific settings resolved!');
+ jQuery.extend(true, widget, result);
+ },
+ onSettingsDismiss: function(reason, scope) {
+ console.log('Settings have been dismissed: ', reason);
+ console.log('Dashboard scope: ', scope);
+ }
+ }];
+
+ var defaultWidgets = [
+ { name: 'congfigurable widget' },
+ { name: 'override modal widget' }
+ ];
+
+ $scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: definitions,
+ defaultWidgets: defaultWidgets,
+ storage: $window.localStorage,
+ storageId: 'custom-settings',
+
+ /*
+ // Overrides default $uibModal options.
+ // This can also be set on individual
+ // widget definition objects (see above).
+ settingsModalOptions: {
+ // This will completely override the modal template for all widgets.
+ // You also have the option to add to the default modal template with settingsModalOptions.partialTemplateUrl (see "configurable widget" above)
+ templateUrl: 'template/customSettingsTemplate.html'
+ // We could pass a custom controller name here to be used
+ // with the widget settings dialog, but for this demo we
+ // will just keep the default.
+ //
+ // controller: 'CustomSettingsModalCtrl'
+ //
+ // Other options passed to $uibModal.open can be put here,
+ // eg:
+ //
+ // backdrop: false,
+ // keyboard: false
+ //
+ // @see http://angular-ui.github.io/bootstrap/#/modal <-- heads up: routing on their site was broken as of this writing
+ },
+ */
+
+ // Called when a widget settings dialog is closed
+ // by the "ok" method (i.e., the promise is resolved
+ // and not rejected). This can also be set on individual
+ // widgets (see above).
+ onSettingsClose: function(result, widget, scope) {
+ console.log('Settings result: ', result);
+ console.log('Widget: ', widget);
+ console.log('Dashboard scope: ', scope);
+ jQuery.extend(true, widget, result);
+ },
+
+ // Called when a widget settings dialog is closed
+ // by the "cancel" method (i.e., the promise is rejected
+ // and not resolved). This can also be set on individual
+ // widgets (see above).
+ onSettingsDismiss: function(reason, scope) {
+ console.log('Settings have been dismissed: ', reason);
+ console.log('Dashboard scope: ', scope);
+ }
+ };
+ })
+ .controller('WidgetSpecificSettingsCtrl', function ($scope, $uibModalInstance, widget) {
+ // add widget to scope
+ $scope.widget = widget;
+
+ // set up result object
+ $scope.result = jQuery.extend(true, {}, widget);
+
+ $scope.ok = function () {
+ console.log('calling ok from widget-specific settings controller!');
+ $uibModalInstance.close($scope.result);
+ };
+
+ $scope.cancel = function () {
+ console.log('calling cancel from widget-specific settings controller!');
+ $uibModalInstance.dismiss('cancel');
+ };
+ })
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/dataModel.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/dataModel.js
new file mode 100644
index 00000000..d9be52ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/dataModel.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .factory('RandomDataModel', function ($interval, WidgetDataModel) {
+ function RandomDataModel() {
+ }
+
+ RandomDataModel.prototype = Object.create(WidgetDataModel.prototype);
+ RandomDataModel.prototype.constructor = WidgetDataModel;
+
+ angular.extend(RandomDataModel.prototype, {
+ init: function () {
+ var dataModelOptions = this.dataModelOptions;
+ this.limit = (dataModelOptions && dataModelOptions.limit) ? dataModelOptions.limit : 100;
+
+ this.updateScope('-');
+ this.startInterval();
+ },
+
+ startInterval: function () {
+ $interval.cancel(this.intervalPromise);
+
+ this.intervalPromise = $interval(function () {
+ var value = Math.floor(Math.random() * this.limit);
+ this.updateScope(value);
+ }.bind(this), 500);
+ },
+
+ updateLimit: function (limit) {
+ this.dataModelOptions = this.dataModelOptions ? this.dataModelOptions : {};
+ this.dataModelOptions.limit = limit;
+ this.limit = limit;
+ },
+
+ destroy: function () {
+ WidgetDataModel.prototype.destroy.call(this);
+ $interval.cancel(this.intervalPromise);
+ }
+ });
+
+ return RandomDataModel;
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.js
new file mode 100644
index 00000000..d598f0d0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.js
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+.config(function ($routeProvider) {
+ $routeProvider
+ .when('/view', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html',
+ controller: 'DemoCtrl',
+ title: 'simple',
+ description: 'This is the simplest demo.'
+ })
+ .when('/resize', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html',
+ controller: 'ResizeDemoCtrl',
+ title: 'resize',
+ description: 'This demo showcases widget resizing.'
+ })
+ .when('/custom-settings', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html',
+ controller: 'CustomSettingsDemoCtrl',
+ title: 'custom widget settings',
+ description: 'This demo showcases overriding the widget settings dialog/modal ' +
+ 'for the entire dashboard and for a specific widget. Click on the cog of each ' +
+ 'widget to see the custom modal. \n"configurable widget" has "limit" option in the modal ' +
+ 'that controls RandomDataModel.'
+ })
+ .when('/explicit-saving', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html',
+ controller: 'ExplicitSaveDemoCtrl',
+ title: 'explicit saving',
+ description: 'This demo showcases an option to only save the dashboard state '+
+ 'explicitly, e.g. by user input. Notice the "all saved" button in the controls ' +
+ 'updates as you make saveable changes.'
+ })
+ .when('/layouts', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html',
+ controller: 'LayoutsDemoCtrl',
+ title: 'dashboard layouts',
+ description: 'This demo showcases the ability to have "dashboard layouts", ' +
+ 'meaning the ability to have multiple arbitrary configurations of widgets. For more ' +
+ 'information, take a look at [issue #31](https://github.com/DataTorrent/malhar-angular-dashboard/issues/31)'
+ })
+ .when('/', {
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html',
+ controller: 'LayoutsDemoExplicitSaveCtrl',
+ title: 'layouts explicit saving',
+ description: 'This demo showcases dashboard layouts with explicit saving enabled.'
+ })
+ .otherwise({
+ redirectTo: '/'
+ });
+ })
+ .controller('NavBarCtrl', function($scope, $route) {
+ $scope.$route = $route;
+ })
+ .factory('widgetDefinitions', function(RandomDataModel) {
+ return [
+ {
+ name: 'random',
+ directive: 'wt-scope-watch',
+ attrs: {
+ value: 'randomValue'
+ }
+ },
+ {
+ name: 'time',
+ directive: 'wt-time'
+ },
+ {
+ name: 'datamodel',
+ directive: 'wt-scope-watch',
+ dataAttrName: 'value',
+ dataModelType: RandomDataModel
+ },
+ {
+ name: 'resizable',
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/resizable.html',
+ attrs: {
+ class: 'demo-widget-resizable'
+ }
+ },
+ {
+ name: 'fluid',
+ directive: 'wt-fluid',
+ size: {
+ width: '50%',
+ height: '250px'
+ }
+ },
+ {
+ name: 'raptor-report-data',
+ directive: 'raptor-report-data',
+ size: {
+ width: '50%',
+ height: '300px'
+ }
+ },
+ {
+ name: 'raptor-report-chart',
+ directive: 'raptor-report-chart',
+ size: {
+ width: '50%',
+ height: '300px'
+ }
+ },
+ {
+ name: 'r-cloud',
+ directive: 'r-cloud',
+ size: {
+ width: '50%',
+ height: '300px'
+ }
+ }
+ ];
+
+ })
+ .value('defaultWidgets', [
+// { name: 'random' },
+// { name: 'time' },
+// { name: 'datamodel' },
+// {
+// name: 'random',
+// style: {
+// width: '50%',
+// minWidth: '39%'
+// }
+// },
+// {
+// name: 'time',
+// style: {
+// width: '50%'
+// }
+// }
+// {"name":"raptor-report","title":"Spam Source Line Chart","style":{},"size":{"height":"450px","width":"40%"},"attrs":{"value":"randomValue"},"report_id":"3360"}
+
+ ])
+ .controller('DemoCtrl', function ($scope, $interval, $window, widgetDefinitions, defaultWidgets) {
+
+ $scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ storage: $window.localStorage,
+ storageId: 'demo_simple'
+ };
+ $scope.randomValue = Math.random();
+ $interval(function () {
+ $scope.randomValue = Math.random();
+ }, 500);
+
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.less b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.less
new file mode 100644
index 00000000..91f4cee9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.less
@@ -0,0 +1,24 @@
+body {
+ margin: 15px;
+ padding-top: 50px;
+}
+a {
+ cursor: pointer;
+}
+.layout-tabs {
+ margin-bottom: 10px;
+}
+
+.demo-widget-fluid {
+ border: 1px solid blue;
+ height: 100%;
+}
+
+.demo-widget-fluid > div {
+ border: 1px solid red;
+ position: relative;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/directives.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/directives.js
new file mode 100644
index 00000000..fe3ee7f7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/directives.js
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .directive('wtTime', function ($interval) {
+ return {
+ restrict: 'A',
+ scope: true,
+ replace: true,
+ template: '<div>Time<div class="alert alert-success">{{time}}</div></div>',
+ link: function (scope) {
+ function update() {
+ scope.time = new Date().toLocaleTimeString();
+ }
+
+ update();
+
+ var promise = $interval(update, 500);
+
+ scope.$on('$destroy', function () {
+ $interval.cancel(promise);
+ });
+ }
+ };
+ })
+ .directive('wtScopeWatch', function () {
+ return {
+ restrict: 'A',
+ replace: true,
+ template: '<div>Value<div class="alert alert-info">{{value}}</div></div>',
+ scope: {
+ value: '=value'
+ }
+ };
+ })
+ .directive('wtFluid', function () {
+ return {
+ restrict: 'A',
+ replace: true,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/fluid.html',
+ scope: true,
+ controller: function ($scope) {
+ $scope.$on('widgetResized', function (event, size) {
+ $scope.width = size.width || $scope.width;
+ $scope.height = size.height || $scope.height;
+ });
+ }
+ };
+ })
+ .directive('raptorReportChart', ['widgetDefinitions','defaultWidgets',function (widgetDefinitions, defaultWidgets) {
+ return {
+ restrict: 'A',
+ replace: true,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html',
+ scope: true,
+ controller: function ($scope,$http, $rootScope) {
+// console.log('================= Raptor Report scope =================');
+// console.log($scope);
+ $scope.showChart = false;
+ $scope.url = "report_embedded#/report_run/c_master="+$scope.widget.report_id+ "&refresh=Y&hideGrid=Y&width="+Math.floor($scope.width*13)+"&height=300";
+// $scope.url = "report_embedded#/report_run/c_master="+$scope.widget.report_id+ "&refresh=Y&hideGrid="+$scope.hideGrid+"&width=550&height=300";
+ $rootScope.showdataContainer = false;
+ $rootScope.$watch('showdataContainer', function () {
+ console.log('change showdataContainer');
+ console.log($rootScope.showdataContainer);
+ $scope.gridOptions = $rootScope.gridOptions;
+ $scope.gridOptions = $rootScope.gridOptions;
+ $scope.uiGridRefresh = function(){
+ var columnDefsArray = [];
+ var columnFreezeEndColumn = $scope.widget.reportData.colIdxTobeFreezed;
+ var doColumnNeedToFreeze = false;
+ if(columnFreezeEndColumn && columnFreezeEndColumn.length>0) {
+ doColumnNeedToFreeze = true;
+ }
+ $scope.widget.reportData.reportDataColumns.forEach(function(entry) {
+ var tempColumnDef = { displayName: entry.columnTitle, field: entry.colId, enableSorting: entry.sortable,
+ sortingAlgorithm: function(a, b) {
+ return rowSorter.sortAlpha(a.displayValue, b.displayValue);
+ },
+ cellTemplate: '<div class="ui-grid-cell-contents" style="text-align:{{COL_FIELD.alignment}};" title="TOOLTIP"> '+
+ ' <div ng-if="!COL_FIELD.drillDownURL || COL_FIELD.drillDownURL==\'\'">{{COL_FIELD.displayValue}}</div>' +
+ ' <a ng-if="COL_FIELD.drillDownURL && COL_FIELD.drillDownURL!=\'\'" ng-href="{{COL_FIELD.drillDownURL}}&parent___params==={{grid.appScope.currentReportUrlParams}}" >{{COL_FIELD.displayValue}}</a>' +
+ '</div>'};
+ if(entry.columnWidth && entry.columnWidth!='null' && entry.columnWidth!='pxpx' && entry.columnWidth!='nullpx' && entry.columnWidth!='nullpxpx'){
+ tempColumnDef['minWidth'] = entry.columnWidth.substring(0, entry.columnWidth.length - 2);
+ } else {
+ tempColumnDef['minWidth'] = '100';
+ }
+ if(doColumnNeedToFreeze) {
+ tempColumnDef['pinnedLeft']= true;
+ if(columnFreezeEndColumn === entry.colId){
+ doColumnNeedToFreeze = false;
+ }
+ }
+ columnDefsArray.push(tempColumnDef);
+ });
+
+ $scope.gridOptions.paginationPageSizes= [$scope.widget.reportData.pageSize];
+ $scope.gridOptions.paginationPageSize= $scope.widget.reportData.pageSize;
+ if($scope.widget.reportData.totalRows<14){
+ $scope.widget.gridHeight = (widget.reportData.totalRows+5)*30+'px';
+ }else{
+ $scope.gridHeight = '400px';
+ }
+ $scope.gridOptions.totalItems = $scope.widget.reportData.totalRows;
+ $scope.gridOptions.columnDefs= columnDefsArray;
+ $scope.gridOptions.data= $scope.widget.reportData.reportDataRows;
+ $scope.gridOptions.exporterPdfHeader.text= $scope.widget.reportData.reportName;
+ };
+ $scope.uiGridRefresh();
+
+
+ /*presence.setGlobal({
+ u: $rootScope.currentUser,
+ s: 'on'
+ })*/
+ })
+ $scope.$on('widgetResized', function (event, size) {
+ console.log("===$scope===");
+ console.log($scope);
+ $scope.width = size.width || $scope.width;
+ $scope.height = size.height || $scope.height;
+ $scope.url = "report_embedded#/report_run/c_master="+$scope.widget.report_id+ "&refresh=Y&hideGrid=Y&width="+Math.floor($scope.width*13)+"&height=300";
+ });
+ }
+ };
+ }])
+ .directive('raptorReportData', ['widgetDefinitions','defaultWidgets',function (widgetDefinitions, defaultWidgets) {
+ return {
+ restrict: 'A',
+ replace: true,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html',
+ scope: true,
+ controller: function ($scope,$http, $rootScope) {
+// console.log('================= Raptor Report scope =================');
+// console.log($scope);
+ $scope.showChart = false;
+ $scope.url = "report_embedded#/report_run/c_master="+$scope.widget.report_id+ "&refresh=Y&hideChart=Y&width="+Math.floor($scope.width*13)+"&height=300";
+// $scope.url = "report_embedded#/report_run/c_master="+$scope.widget.report_id+ "&refresh=Y&hideGrid="+$scope.hideGrid+"&width=550&height=300";
+ $rootScope.showdataContainer = false;
+ $rootScope.$watch('showdataContainer', function () {
+ console.log('change showdataContainer');
+ console.log($rootScope.showdataContainer);
+ $scope.gridOptions = $rootScope.gridOptions;
+ $scope.gridOptions = $rootScope.gridOptions;
+ $scope.uiGridRefresh = function(){
+ var columnDefsArray = [];
+ var columnFreezeEndColumn = $scope.widget.reportData.colIdxTobeFreezed;
+ var doColumnNeedToFreeze = false;
+ if(columnFreezeEndColumn && columnFreezeEndColumn.length>0) {
+ doColumnNeedToFreeze = true;
+ }
+ $scope.widget.reportData.reportDataColumns.forEach(function(entry) {
+ var tempColumnDef = { displayName: entry.columnTitle, field: entry.colId, enableSorting: entry.sortable,
+ sortingAlgorithm: function(a, b) {
+ return rowSorter.sortAlpha(a.displayValue, b.displayValue);
+ },
+ cellTemplate: '<div class="ui-grid-cell-contents" style="text-align:{{COL_FIELD.alignment}};" title="TOOLTIP"> '+
+ ' <div ng-if="!COL_FIELD.drillDownURL || COL_FIELD.drillDownURL==\'\'">{{COL_FIELD.displayValue}}</div>' +
+ ' <a ng-if="COL_FIELD.drillDownURL && COL_FIELD.drillDownURL!=\'\'" ng-href="{{COL_FIELD.drillDownURL}}&parent___params==={{grid.appScope.currentReportUrlParams}}" >{{COL_FIELD.displayValue}}</a>' +
+ '</div>'};
+ if(entry.columnWidth && entry.columnWidth!='null' && entry.columnWidth!='pxpx' && entry.columnWidth!='nullpx' && entry.columnWidth!='nullpxpx'){
+ tempColumnDef['minWidth'] = entry.columnWidth.substring(0, entry.columnWidth.length - 2);
+ } else {
+ tempColumnDef['minWidth'] = '100';
+ }
+ if(doColumnNeedToFreeze) {
+ tempColumnDef['pinnedLeft']= true;
+ if(columnFreezeEndColumn === entry.colId){
+ doColumnNeedToFreeze = false;
+ }
+ }
+ columnDefsArray.push(tempColumnDef);
+ });
+
+ $scope.gridOptions.paginationPageSizes= [$scope.widget.reportData.pageSize];
+ $scope.gridOptions.paginationPageSize= $scope.widget.reportData.pageSize;
+ if($scope.widget.reportData.totalRows<14){
+ $scope.widget.gridHeight = (widget.reportData.totalRows+5)*30+'px';
+ }else{
+ $scope.gridHeight = '400px';
+ }
+ $scope.gridOptions.totalItems = $scope.widget.reportData.totalRows;
+ $scope.gridOptions.columnDefs= columnDefsArray;
+ $scope.gridOptions.data= $scope.widget.reportData.reportDataRows;
+ $scope.gridOptions.exporterPdfHeader.text= $scope.widget.reportData.reportName;
+ };
+ $scope.uiGridRefresh();
+
+
+ /*presence.setGlobal({
+ u: $rootScope.currentUser,
+ s: 'on'
+ })*/
+ })
+ }
+ };
+ }])
+ .directive('rCloud', function () {
+ return {
+ restrict: 'A',
+ replace: true,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/app/template/r-cloud.html',
+ scope: true,
+ controller: function ($scope,$http) {
+ $scope.showChart = false;
+ $scope.hideGrid = 'true';
+ $scope.url = $scope.widget.rcloud_url;
+ $scope.$on('widgetResized', function (event, size) {
+ $scope.width = size.width || $scope.width;
+ $scope.height = size.height || $scope.height;
+ });
+ }
+ };
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/explicitSave.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/explicitSave.js
new file mode 100644
index 00000000..ad959b21
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/explicitSave.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .controller('ExplicitSaveDemoCtrl', function ($scope, $interval, $window, widgetDefinitions, defaultWidgets) {
+ $scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ storage: $window.localStorage,
+ storageId: 'explicitSave',
+ explicitSave: true
+ };
+ $scope.randomValue = Math.random();
+ $interval(function () {
+ $scope.randomValue = Math.random();
+ }, 500);
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.css
new file mode 100644
index 00000000..c05f70c1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.css
@@ -0,0 +1,146 @@
+/* #rightContentUiDashboard {
+ display:inline-block;
+} */
+
+#rightContentUiDashboard .browsehappy {
+ margin: 0.2em 0;
+ background: #ccc;
+ color: #000;
+ padding: 0.2em 0;
+}
+#rightContentUiDashboard .thumbnail {
+ height: 200px;
+}
+#rightContentUiDashboard .thumbnail img.pull-right {
+ width: 50px;
+}
+#rightContentUiDashboard body {
+ margin: 15px;
+ padding-top: 50px;
+}
+#rightContentUiDashboard a {
+ cursor: pointer;
+}
+#rightContentUiDashboard .layout-tabs {
+ margin-bottom: 10px;
+}
+#rightContentUiDashboard .demo-widget-fluid {
+ border: 1px solid blue;
+ height: 100%;
+}
+#rightContentUiDashboard .demo-widget-fluid > div {
+ border: 1px solid red;
+ position: relative;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+#rightContentUiDashboard .dashboard-widget-area {
+ margin: 10px 0 30px;
+ min-height: 200px;
+}
+#rightContentUiDashboard .widget-container {
+ float: left;
+ display: inline-block;
+ width: 33%;
+ padding-bottom: 0em;
+}
+#rightContentUiDashboard .widget {
+ margin: 0 1em 0 0;
+ background-color: white;
+ border-radius: 5px;
+ position: relative;
+ height: 100%;
+}
+#rightContentUiDashboard .widget-header {
+ overflow: hidden;
+ width:100%; /* for overlaying effect start*/
+ position: absolute;
+ z-index: 10;
+ opacity: 0.8;
+ top: 1px;
+ filter: alpha(opacity=80); /* For IE8 and earlier */
+ -webkit-transition: width 2s, height 4s; /* Safari */
+ transition: width 2s, height 4s;
+}
+#rightContentUiDashboard .widget-header .label {
+ display: inline-block;
+ vertical-align: middle;
+}
+#rightContentUiDashboard .widget-header .glyphicon {
+ cursor: pointer;
+ float: right;
+ opacity: 0.5;
+ margin-left: 5px;
+}
+#rightContentUiDashboard .widget-header .glyphicon:hover {
+ opacity: 1;
+}
+#rightContentUiDashboard .widget-header .widget-title {
+ vertical-align: middle;
+}
+#rightContentUiDashboard .widget-header form.widget-title {
+ display: inline;
+}
+#rightContentUiDashboard .widget-header form.widget-title input.form-control {
+ width: auto;
+ display: inline-block;
+}
+#rightContentUiDashboard .widget-content {
+ padding:0px;
+ overflow: hidden;
+ position: relative; /* for overlaying effect */
+}
+#rightContentUiDashboard .widget .widget-ew-resizer {
+ position: absolute;
+ width: 5px;
+ right: -2px;
+ height: 100%;
+ top: 0;
+ cursor: ew-resize;
+}
+#rightContentUiDashboard .widget .widget-s-resizer {
+ cursor: ns-resize;
+ height: 5px;
+ width: 100%;
+ bottom: -7px;
+ left: 0;
+}
+#rightContentUiDashboard .widget .widget-resizer-marquee {
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.5);
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+}
+#rightContentUiDashboard .remove-layout-icon {
+ vertical-align: text-top;
+ cursor: pointer;
+ opacity: 0.3;
+}
+#rightContentUiDashboard .remove-layout-icon:hover {
+ opacity: 1;
+}
+#rightContentUiDashboard .layout-title {
+ display: inline-block;
+}
+
+/*
+#container {
+ width: 100px;
+ height: 100px;
+ position: relative;
+}
+#navi,
+#infoi {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+#infoi {
+ z-index: 10;
+}
+
+ */ \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.js
new file mode 100644
index 00000000..b4cfb97d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.js
@@ -0,0 +1,3 @@
+'use strict';
+
+angular.module('dashboard', ['ui.bootstrap']);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.less b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.less
new file mode 100644
index 00000000..87955cbe
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index.less
@@ -0,0 +1,16 @@
+.browsehappy {
+ margin: 0.2em 0;
+ background: #ccc;
+ color: #000;
+ padding: 0.2em 0;
+}
+
+.thumbnail {
+ height: 200px;
+
+ img.pull-right {
+ width: 50px;
+ }
+}
+// injector
+// endinjector
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index_original.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index_original.css
new file mode 100644
index 00000000..d5cebfb0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/index_original.css
@@ -0,0 +1,113 @@
+.browsehappy {
+ margin: 0.2em 0;
+ background: #ccc;
+ color: #000;
+ padding: 0.2em 0;
+}
+.thumbnail {
+ height: 200px;
+}
+.thumbnail img.pull-right {
+ width: 50px;
+}
+body {
+ margin: 15px;
+ padding-top: 50px;
+}
+a {
+ cursor: pointer;
+}
+.layout-tabs {
+ margin-bottom: 10px;
+}
+.demo-widget-fluid {
+ border: 1px solid blue;
+ height: 100%;
+}
+.demo-widget-fluid > div {
+ border: 1px solid red;
+ position: relative;
+ top: 50%;
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+.dashboard-widget-area {
+ margin: 10px 0 30px;
+ min-height: 200px;
+}
+.widget-container {
+ float: left;
+ display: inline-block;
+ width: 33%;
+ padding-bottom: 1em;
+}
+.widget {
+ margin: 0 1em 0 0;
+ background-color: white;
+ border: 2px solid #444;
+ border-radius: 5px;
+ position: relative;
+ height: 100%;
+}
+.widget-header {
+ overflow: hidden;
+}
+.widget-header .label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.widget-header .glyphicon {
+ cursor: pointer;
+ float: right;
+ opacity: 0.5;
+ margin-left: 5px;
+}
+.widget-header .glyphicon:hover {
+ opacity: 1;
+}
+.widget-header .widget-title {
+ vertical-align: middle;
+}
+.widget-header form.widget-title {
+ display: inline;
+}
+.widget-header form.widget-title input.form-control {
+ width: auto;
+ display: inline-block;
+}
+.widget-content {
+ overflow: hidden;
+}
+.widget .widget-ew-resizer {
+ position: absolute;
+ width: 5px;
+ right: -2px;
+ height: 100%;
+ top: 0;
+ cursor: ew-resize;
+}
+.widget .widget-s-resizer {
+ cursor: ns-resize;
+ height: 5px;
+ width: 100%;
+ bottom: -7px;
+ left: 0;
+}
+.widget .widget-resizer-marquee {
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.5);
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+}
+.remove-layout-icon {
+ vertical-align: text-top;
+ cursor: pointer;
+ opacity: 0.3;
+}
+.remove-layout-icon:hover {
+ opacity: 1;
+}
+.layout-title {
+ display: inline-block;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/layouts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/layouts.js
new file mode 100644
index 00000000..154a6b08
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/layouts.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .controller('LayoutsDemoCtrl', function($scope, widgetDefinitions, defaultWidgets, LayoutStorage, $interval) {
+ $scope.layoutOptions = {
+ storageId: 'demo-layouts',
+ storage: localStorage,
+ storageHash: 'fs4df4d51',
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ lockDefaultLayouts: true,
+ defaultLayouts: [
+ { title: 'Layout 1', active: true , defaultWidgets: defaultWidgets },
+ { title: 'Layout 2', active: false, defaultWidgets: defaultWidgets },
+ { title: 'Layout 3', active: false, defaultWidgets: defaultWidgets, locked: false }
+ ]
+ };
+ $scope.randomValue = Math.random();
+ $interval(function () {
+ $scope.randomValue = Math.random();
+ }, 500);
+
+ })
+ .controller('LayoutsDemoExplicitSaveCtrl', function($scope, widgetDefinitions, defaultWidgets, LayoutStorage, $interval, $http) {
+ $http.get('raptor.htm?action=report.search.execute').then(
+ function(result){
+ var data = result.data;
+ var report_id_name = [];
+ for (var i in data.rows[0]) {
+ report_id_name.push({index:i, value: data.rows[0][i][1].searchresultField.displayValue, title: data.rows[0][i][2].searchresultField.displayValue})
+ }
+ $scope.reports = report_id_name;
+ console.log($scope.reports);
+ $scope.report1 = $scope.reports[1];
+ });
+
+ $scope.rcloud_url= "https://rcloud.research.att.com/mini.html?notebook=c131ea997453e75303588699936d1896";
+ $scope.layoutOptions = {
+ storageId: 'demo-layouts-explicit-save',
+ storage: localStorage,
+ storageHash: 'fs4df4d51',
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ explicitSave: true,
+ defaultLayouts: [
+ { title: 'Layout 1', active: true , defaultWidgets: defaultWidgets },
+ { title: 'Layout 2', active: false, defaultWidgets: defaultWidgets },
+ { title: 'Layout 3', active: false, defaultWidgets: defaultWidgets }
+ ]
+ };
+ $scope.randomValue = Math.random();
+ $interval(function () {
+ $scope.randomValue = Math.random();
+ }, 500);
+
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/report_whitelist.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/report_whitelist.js
new file mode 100644
index 00000000..f1e76096
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/report_whitelist.js
@@ -0,0 +1,3 @@
+app.config(function ($sceDelegateProvider) {
+ $sceDelegateProvider.resourceUrlWhitelist(['self','https://rcloud.research.att.com/**']);
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/resize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/resize.js
new file mode 100644
index 00000000..db22e548
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/resize.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+app
+ .controller('ResizeDemoCtrl', function ($scope, $interval, $window, widgetDefinitions, defaultWidgets) {
+ defaultWidgets = [
+ { name: 'fluid' },
+ { name: 'resizable' },
+ { name: 'random', style: { width: '50%' } },
+ { name: 'time', style: { width: '50%' } }
+ ];
+
+ $scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ storage: $window.localStorage,
+ storageId: 'demo_resize'
+ };
+ $scope.randomValue = Math.random();
+ $interval(function () {
+ $scope.randomValue = Math.random();
+ }, 500);
+ })
+ .controller('ResizableCtrl', function ($scope) {
+ $scope.$on('widgetResized', function (event, size) {
+ $scope.width = size.width || $scope.width;
+ $scope.height = size.height || $scope.height;
+ });
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/configurableWidgetModalOptions.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/configurableWidgetModalOptions.html
new file mode 100644
index 00000000..b12c3ade
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/configurableWidgetModalOptions.html
@@ -0,0 +1,6 @@
+<div class="form-group">
+ <label class="col-sm-2 control-label">Random Limit</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="result.dataModelOptions.limit">
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/customSettingsTemplate.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/customSettingsTemplate.html
new file mode 100644
index 00000000..be13a89b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/customSettingsTemplate.html
@@ -0,0 +1,19 @@
+<div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
+ <h3>Custom Settings Dialog for <small>{{widget.title}}</small></h3>
+</div>
+<div class="modal-body">
+ <form name="form" novalidate class="form-horizontal">
+ <div class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">Title</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="result.title">
+ </div>
+ </div>
+ <div ng-if="widget.partialSettingTemplateUrl" ng-include="widget.partialSettingTemplateUrl"></div>
+ </form>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/fluid.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/fluid.html
new file mode 100644
index 00000000..4bb0c94a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/fluid.html
@@ -0,0 +1,8 @@
+<div class="demo-widget-fluid">
+ <div>
+ <p>Widget takes 100% height (blue border).<p>
+ <p>Resize the widget vertically to see that this text (red border) stays middle aligned.</p>
+ <p>New width: {{width}}</p>
+ <p>New height: {{height}}</p>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html
new file mode 100644
index 00000000..8d6854f7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/layouts.html
@@ -0,0 +1 @@
+<div dashboard-layouts="layoutOptions"></div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/r-cloud.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/r-cloud.html
new file mode 100644
index 00000000..46cf7b8b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/r-cloud.html
@@ -0,0 +1,8 @@
+<div class="demo-widget-rcloud">
+ <div>
+<!-- <h1>R Cloud</h1> -->
+<!-- <p>{{url}}</p> -->
+ <iframe src= {{url}} width="100%" height="500" style="border: none; background-color: #f2f2f2; opacity: 1;">
+ </iframe>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html
new file mode 100644
index 00000000..fed32ada
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/raptor-report.html
@@ -0,0 +1,29 @@
+<div class="demo-widget-raptor">
+ <div ng-show="true">
+<!-- <p>{{url}}</p> -->
+ <div style="display:block; border: none; height:50px; background-color:#f2f2f2;"></div>
+ <iframe src= {{url}}
+ width="100%" height="500"
+ style="border: none; background-color: #f2f2f2; opacity: 1;"></iframe>
+ </div>
+
+<!-- <div ng-show="!showChart">
+ <p>{{showChart}}</p>
+ <iframe id="chartiframe" ng-show="showChart" width="100%" height="450px" style="border: none" scrolling="no"></iframe>
+ </div> -->
+
+ <div>
+ <div>
+ <div id="grid1" ui-grid="gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-resize-columns class="grid" style="height: {{gridHeight}}">
+ <div class="no-rows" ng-show="!gridOptions.data.length">
+ <div class="msg">
+ <span>{{reportData.message}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/resizable.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/resizable.html
new file mode 100644
index 00000000..6abaad81
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/resizable.html
@@ -0,0 +1,6 @@
+<div ng-controller="ResizableCtrl">
+ <div>
+ <div>New width: {{width}}</div>
+ <div>New height: {{height}}</div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html
new file mode 100644
index 00000000..23b72c28
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/view.html
@@ -0,0 +1,5 @@
+<div class="row">
+ <div class="col-md-12">
+ <div dashboard="dashboardOptions" class="dashboard-container"></div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/widgetSpecificSettings.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/widgetSpecificSettings.html
new file mode 100644
index 00000000..3b93a0a9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/template/widgetSpecificSettings.html
@@ -0,0 +1,19 @@
+<div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
+ <h3>Custom Settings for a special widget</h3>
+</div>
+<div class="modal-body">
+ <form name="form" novalidate class="form-horizontal">
+ <p>I override the entire widget settings modal template. This can be used for maximum customization!</p>
+ <div class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">Title</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="result.title">
+ </div>
+ </div>
+ </form>
+</div>
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">fuhget about it</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">hell yea</button>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css
new file mode 100644
index 00000000..a7e815ed
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css
@@ -0,0 +1,6658 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+html {
+ font-family: sans-serif;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+mark {
+ background: #ff0;
+ color: #000;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+sup {
+ top: -0.5em;
+}
+sub {
+ bottom: -0.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: textfield;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+legend {
+ border: 0;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+td,
+th {
+ padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+ *,
+ *:before,
+ *:after {
+ background: transparent !important;
+ color: #000 !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+ thead {
+ display: table-header-group;
+ }
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+ img {
+ max-width: 100% !important;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+ .navbar {
+ display: none;
+ }
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+ .label {
+ border: 1px solid #000;
+ }
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+@font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot');
+ src: url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), url('../../bower_components/boostrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../../bower_components/boostrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+ content: "\002a";
+}
+.glyphicon-plus:before {
+ content: "\002b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+ content: "\20ac";
+}
+.glyphicon-minus:before {
+ content: "\2212";
+}
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+.glyphicon-glass:before {
+ content: "\e001";
+}
+.glyphicon-music:before {
+ content: "\e002";
+}
+.glyphicon-search:before {
+ content: "\e003";
+}
+.glyphicon-heart:before {
+ content: "\e005";
+}
+.glyphicon-star:before {
+ content: "\e006";
+}
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+.glyphicon-user:before {
+ content: "\e008";
+}
+.glyphicon-film:before {
+ content: "\e009";
+}
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+.glyphicon-th:before {
+ content: "\e011";
+}
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+.glyphicon-ok:before {
+ content: "\e013";
+}
+.glyphicon-remove:before {
+ content: "\e014";
+}
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+.glyphicon-off:before {
+ content: "\e017";
+}
+.glyphicon-signal:before {
+ content: "\e018";
+}
+.glyphicon-cog:before {
+ content: "\e019";
+}
+.glyphicon-trash:before {
+ content: "\e020";
+}
+.glyphicon-home:before {
+ content: "\e021";
+}
+.glyphicon-file:before {
+ content: "\e022";
+}
+.glyphicon-time:before {
+ content: "\e023";
+}
+.glyphicon-road:before {
+ content: "\e024";
+}
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+.glyphicon-download:before {
+ content: "\e026";
+}
+.glyphicon-upload:before {
+ content: "\e027";
+}
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+.glyphicon-lock:before {
+ content: "\e033";
+}
+.glyphicon-flag:before {
+ content: "\e034";
+}
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+.glyphicon-tag:before {
+ content: "\e041";
+}
+.glyphicon-tags:before {
+ content: "\e042";
+}
+.glyphicon-book:before {
+ content: "\e043";
+}
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+.glyphicon-print:before {
+ content: "\e045";
+}
+.glyphicon-camera:before {
+ content: "\e046";
+}
+.glyphicon-font:before {
+ content: "\e047";
+}
+.glyphicon-bold:before {
+ content: "\e048";
+}
+.glyphicon-italic:before {
+ content: "\e049";
+}
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+.glyphicon-list:before {
+ content: "\e056";
+}
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+.glyphicon-picture:before {
+ content: "\e060";
+}
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+.glyphicon-tint:before {
+ content: "\e064";
+}
+.glyphicon-edit:before {
+ content: "\e065";
+}
+.glyphicon-share:before {
+ content: "\e066";
+}
+.glyphicon-check:before {
+ content: "\e067";
+}
+.glyphicon-move:before {
+ content: "\e068";
+}
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+.glyphicon-backward:before {
+ content: "\e071";
+}
+.glyphicon-play:before {
+ content: "\e072";
+}
+.glyphicon-pause:before {
+ content: "\e073";
+}
+.glyphicon-stop:before {
+ content: "\e074";
+}
+.glyphicon-forward:before {
+ content: "\e075";
+}
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+.glyphicon-eject:before {
+ content: "\e078";
+}
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+.glyphicon-gift:before {
+ content: "\e102";
+}
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+.glyphicon-fire:before {
+ content: "\e104";
+}
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+.glyphicon-plane:before {
+ content: "\e108";
+}
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+.glyphicon-random:before {
+ content: "\e110";
+}
+.glyphicon-comment:before {
+ content: "\e111";
+}
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+.glyphicon-bell:before {
+ content: "\e123";
+}
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+.glyphicon-globe:before {
+ content: "\e135";
+}
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+.glyphicon-filter:before {
+ content: "\e138";
+}
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+.glyphicon-link:before {
+ content: "\e144";
+}
+.glyphicon-phone:before {
+ content: "\e145";
+}
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+.glyphicon-usd:before {
+ content: "\e148";
+}
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+.glyphicon-sort:before {
+ content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+.glyphicon-expand:before {
+ content: "\e158";
+}
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+.glyphicon-flash:before {
+ content: "\e162";
+}
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+.glyphicon-record:before {
+ content: "\e165";
+}
+.glyphicon-save:before {
+ content: "\e166";
+}
+.glyphicon-open:before {
+ content: "\e167";
+}
+.glyphicon-saved:before {
+ content: "\e168";
+}
+.glyphicon-import:before {
+ content: "\e169";
+}
+.glyphicon-export:before {
+ content: "\e170";
+}
+.glyphicon-send:before {
+ content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+.glyphicon-header:before {
+ content: "\e180";
+}
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+.glyphicon-tower:before {
+ content: "\e184";
+}
+.glyphicon-stats:before {
+ content: "\e185";
+}
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+.glyphicon-cd:before {
+ content: "\e201";
+}
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+.glyphicon-copy:before {
+ content: "\e205";
+}
+.glyphicon-paste:before {
+ content: "\e206";
+}
+.glyphicon-alert:before {
+ content: "\e209";
+}
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+.glyphicon-king:before {
+ content: "\e211";
+}
+.glyphicon-queen:before {
+ content: "\e212";
+}
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+.glyphicon-knight:before {
+ content: "\e215";
+}
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+.glyphicon-bed:before {
+ content: "\e219";
+}
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+.glyphicon-erase:before {
+ content: "\e221";
+}
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+.glyphicon-btc:before {
+ content: "\e227";
+}
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+.glyphicon-scale:before {
+ content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+.glyphicon-education:before {
+ content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+.glyphicon-oil:before {
+ content: "\e238";
+}
+.glyphicon-grain:before {
+ content: "\e239";
+}
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+.glyphicon-console:before {
+ content: "\e254";
+}
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+* {
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ box-sizing: border-box;
+}
+html {
+ font-size: 10px;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #333333;
+ background-color: #ffffff;
+}
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+a {
+ color: #337ab7;
+ text-decoration: none;
+}
+a:hover,
+a:focus {
+ color: #23527c;
+ text-decoration: underline;
+}
+a:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+figure {
+ margin: 0;
+}
+img {
+ vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+.img-rounded {
+ border-radius: 6px;
+}
+.img-thumbnail {
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ transition: all 0.2s ease-in-out;
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+}
+.img-circle {
+ border-radius: 50%;
+}
+hr {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #eeeeee;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+[role="button"] {
+ cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #777777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+ font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+ font-size: 75%;
+}
+h1,
+.h1 {
+ font-size: 36px;
+}
+h2,
+.h2 {
+ font-size: 30px;
+}
+h3,
+.h3 {
+ font-size: 24px;
+}
+h4,
+.h4 {
+ font-size: 18px;
+}
+h5,
+.h5 {
+ font-size: 14px;
+}
+h6,
+.h6 {
+ font-size: 12px;
+}
+p {
+ margin: 0 0 10px;
+}
+.lead {
+ margin-bottom: 20px;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 1.4;
+}
+@media (min-width: 768px) {
+ .lead {
+ font-size: 21px;
+ }
+}
+small,
+.small {
+ font-size: 85%;
+}
+mark,
+.mark {
+ background-color: #fcf8e3;
+ padding: .2em;
+}
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
+.text-lowercase {
+ text-transform: lowercase;
+}
+.text-uppercase {
+ text-transform: uppercase;
+}
+.text-capitalize {
+ text-transform: capitalize;
+}
+.text-muted {
+ color: #777777;
+}
+.text-primary {
+ color: #337ab7;
+}
+a.text-primary:hover,
+a.text-primary:focus {
+ color: #286090;
+}
+.text-success {
+ color: #3c763d;
+}
+a.text-success:hover,
+a.text-success:focus {
+ color: #2b542c;
+}
+.text-info {
+ color: #31708f;
+}
+a.text-info:hover,
+a.text-info:focus {
+ color: #245269;
+}
+.text-warning {
+ color: #8a6d3b;
+}
+a.text-warning:hover,
+a.text-warning:focus {
+ color: #66512c;
+}
+.text-danger {
+ color: #a94442;
+}
+a.text-danger:hover,
+a.text-danger:focus {
+ color: #843534;
+}
+.bg-primary {
+ color: #fff;
+ background-color: #337ab7;
+}
+a.bg-primary:hover,
+a.bg-primary:focus {
+ background-color: #286090;
+}
+.bg-success {
+ background-color: #dff0d8;
+}
+a.bg-success:hover,
+a.bg-success:focus {
+ background-color: #c1e2b3;
+}
+.bg-info {
+ background-color: #d9edf7;
+}
+a.bg-info:hover,
+a.bg-info:focus {
+ background-color: #afd9ee;
+}
+.bg-warning {
+ background-color: #fcf8e3;
+}
+a.bg-warning:hover,
+a.bg-warning:focus {
+ background-color: #f7ecb5;
+}
+.bg-danger {
+ background-color: #f2dede;
+}
+a.bg-danger:hover,
+a.bg-danger:focus {
+ background-color: #e4b9b9;
+}
+.page-header {
+ padding-bottom: 9px;
+ margin: 40px 0 20px;
+ border-bottom: 1px solid #eeeeee;
+}
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+ margin-bottom: 0;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+.list-inline {
+ padding-left: 0;
+ list-style: none;
+ margin-left: -5px;
+}
+.list-inline > li {
+ display: inline-block;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+dl {
+ margin-top: 0;
+ margin-bottom: 20px;
+}
+dt,
+dd {
+ line-height: 1.42857143;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .dl-horizontal dt {
+ float: left;
+ width: 160px;
+ clear: left;
+ text-align: right;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .dl-horizontal dd {
+ margin-left: 180px;
+ }
+}
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #777777;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+blockquote {
+ padding: 10px 20px;
+ margin: 0 0 20px;
+ font-size: 17.5px;
+ border-left: 5px solid #eeeeee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+ margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+ display: block;
+ font-size: 80%;
+ line-height: 1.42857143;
+ color: #777777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+ content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid #eeeeee;
+ border-left: 0;
+ text-align: right;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+ content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+ content: '\00A0 \2014';
+}
+address {
+ margin-bottom: 20px;
+ font-style: normal;
+ line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #c7254e;
+ background-color: #f9f2f4;
+ border-radius: 4px;
+}
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #ffffff;
+ background-color: #333333;
+ border-radius: 3px;
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+ box-shadow: none;
+}
+pre {
+ display: block;
+ padding: 9.5px;
+ margin: 0 0 10px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #333333;
+ background-color: #f5f5f5;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+}
+pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+}
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+.container {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+@media (min-width: 768px) {
+ .container {
+ width: 750px;
+ }
+}
+@media (min-width: 992px) {
+ .container {
+ width: 970px;
+ }
+}
+@media (min-width: 1200px) {
+ .container {
+ width: 1170px;
+ }
+}
+.container-fluid {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.row {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+ position: relative;
+ min-height: 1px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+ float: left;
+}
+.col-xs-12 {
+ width: 100%;
+}
+.col-xs-11 {
+ width: 91.66666667%;
+}
+.col-xs-10 {
+ width: 83.33333333%;
+}
+.col-xs-9 {
+ width: 75%;
+}
+.col-xs-8 {
+ width: 66.66666667%;
+}
+.col-xs-7 {
+ width: 58.33333333%;
+}
+.col-xs-6 {
+ width: 50%;
+}
+.col-xs-5 {
+ width: 41.66666667%;
+}
+.col-xs-4 {
+ width: 33.33333333%;
+}
+.col-xs-3 {
+ width: 25%;
+}
+.col-xs-2 {
+ width: 16.66666667%;
+}
+.col-xs-1 {
+ width: 8.33333333%;
+}
+.col-xs-pull-12 {
+ right: 100%;
+}
+.col-xs-pull-11 {
+ right: 91.66666667%;
+}
+.col-xs-pull-10 {
+ right: 83.33333333%;
+}
+.col-xs-pull-9 {
+ right: 75%;
+}
+.col-xs-pull-8 {
+ right: 66.66666667%;
+}
+.col-xs-pull-7 {
+ right: 58.33333333%;
+}
+.col-xs-pull-6 {
+ right: 50%;
+}
+.col-xs-pull-5 {
+ right: 41.66666667%;
+}
+.col-xs-pull-4 {
+ right: 33.33333333%;
+}
+.col-xs-pull-3 {
+ right: 25%;
+}
+.col-xs-pull-2 {
+ right: 16.66666667%;
+}
+.col-xs-pull-1 {
+ right: 8.33333333%;
+}
+.col-xs-pull-0 {
+ right: auto;
+}
+.col-xs-push-12 {
+ left: 100%;
+}
+.col-xs-push-11 {
+ left: 91.66666667%;
+}
+.col-xs-push-10 {
+ left: 83.33333333%;
+}
+.col-xs-push-9 {
+ left: 75%;
+}
+.col-xs-push-8 {
+ left: 66.66666667%;
+}
+.col-xs-push-7 {
+ left: 58.33333333%;
+}
+.col-xs-push-6 {
+ left: 50%;
+}
+.col-xs-push-5 {
+ left: 41.66666667%;
+}
+.col-xs-push-4 {
+ left: 33.33333333%;
+}
+.col-xs-push-3 {
+ left: 25%;
+}
+.col-xs-push-2 {
+ left: 16.66666667%;
+}
+.col-xs-push-1 {
+ left: 8.33333333%;
+}
+.col-xs-push-0 {
+ left: auto;
+}
+.col-xs-offset-12 {
+ margin-left: 100%;
+}
+.col-xs-offset-11 {
+ margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+ margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+ margin-left: 75%;
+}
+.col-xs-offset-8 {
+ margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+ margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+ margin-left: 50%;
+}
+.col-xs-offset-5 {
+ margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+ margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+ margin-left: 25%;
+}
+.col-xs-offset-2 {
+ margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+ margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+ margin-left: 0%;
+}
+@media (min-width: 768px) {
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+ float: left;
+ }
+ .col-sm-12 {
+ width: 100%;
+ }
+ .col-sm-11 {
+ width: 91.66666667%;
+ }
+ .col-sm-10 {
+ width: 83.33333333%;
+ }
+ .col-sm-9 {
+ width: 75%;
+ }
+ .col-sm-8 {
+ width: 66.66666667%;
+ }
+ .col-sm-7 {
+ width: 58.33333333%;
+ }
+ .col-sm-6 {
+ width: 50%;
+ }
+ .col-sm-5 {
+ width: 41.66666667%;
+ }
+ .col-sm-4 {
+ width: 33.33333333%;
+ }
+ .col-sm-3 {
+ width: 25%;
+ }
+ .col-sm-2 {
+ width: 16.66666667%;
+ }
+ .col-sm-1 {
+ width: 8.33333333%;
+ }
+ .col-sm-pull-12 {
+ right: 100%;
+ }
+ .col-sm-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-sm-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-sm-pull-9 {
+ right: 75%;
+ }
+ .col-sm-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-sm-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-sm-pull-6 {
+ right: 50%;
+ }
+ .col-sm-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-sm-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-sm-pull-3 {
+ right: 25%;
+ }
+ .col-sm-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-sm-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-sm-pull-0 {
+ right: auto;
+ }
+ .col-sm-push-12 {
+ left: 100%;
+ }
+ .col-sm-push-11 {
+ left: 91.66666667%;
+ }
+ .col-sm-push-10 {
+ left: 83.33333333%;
+ }
+ .col-sm-push-9 {
+ left: 75%;
+ }
+ .col-sm-push-8 {
+ left: 66.66666667%;
+ }
+ .col-sm-push-7 {
+ left: 58.33333333%;
+ }
+ .col-sm-push-6 {
+ left: 50%;
+ }
+ .col-sm-push-5 {
+ left: 41.66666667%;
+ }
+ .col-sm-push-4 {
+ left: 33.33333333%;
+ }
+ .col-sm-push-3 {
+ left: 25%;
+ }
+ .col-sm-push-2 {
+ left: 16.66666667%;
+ }
+ .col-sm-push-1 {
+ left: 8.33333333%;
+ }
+ .col-sm-push-0 {
+ left: auto;
+ }
+ .col-sm-offset-12 {
+ margin-left: 100%;
+ }
+ .col-sm-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-sm-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-sm-offset-9 {
+ margin-left: 75%;
+ }
+ .col-sm-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-sm-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-sm-offset-6 {
+ margin-left: 50%;
+ }
+ .col-sm-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-sm-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-sm-offset-3 {
+ margin-left: 25%;
+ }
+ .col-sm-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-sm-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-sm-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ float: left;
+ }
+ .col-md-12 {
+ width: 100%;
+ }
+ .col-md-11 {
+ width: 91.66666667%;
+ }
+ .col-md-10 {
+ width: 83.33333333%;
+ }
+ .col-md-9 {
+ width: 75%;
+ }
+ .col-md-8 {
+ width: 66.66666667%;
+ }
+ .col-md-7 {
+ width: 58.33333333%;
+ }
+ .col-md-6 {
+ width: 50%;
+ }
+ .col-md-5 {
+ width: 41.66666667%;
+ }
+ .col-md-4 {
+ width: 33.33333333%;
+ }
+ .col-md-3 {
+ width: 25%;
+ }
+ .col-md-2 {
+ width: 16.66666667%;
+ }
+ .col-md-1 {
+ width: 8.33333333%;
+ }
+ .col-md-pull-12 {
+ right: 100%;
+ }
+ .col-md-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-md-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-md-pull-9 {
+ right: 75%;
+ }
+ .col-md-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-md-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-md-pull-6 {
+ right: 50%;
+ }
+ .col-md-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-md-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-md-pull-3 {
+ right: 25%;
+ }
+ .col-md-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-md-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-md-pull-0 {
+ right: auto;
+ }
+ .col-md-push-12 {
+ left: 100%;
+ }
+ .col-md-push-11 {
+ left: 91.66666667%;
+ }
+ .col-md-push-10 {
+ left: 83.33333333%;
+ }
+ .col-md-push-9 {
+ left: 75%;
+ }
+ .col-md-push-8 {
+ left: 66.66666667%;
+ }
+ .col-md-push-7 {
+ left: 58.33333333%;
+ }
+ .col-md-push-6 {
+ left: 50%;
+ }
+ .col-md-push-5 {
+ left: 41.66666667%;
+ }
+ .col-md-push-4 {
+ left: 33.33333333%;
+ }
+ .col-md-push-3 {
+ left: 25%;
+ }
+ .col-md-push-2 {
+ left: 16.66666667%;
+ }
+ .col-md-push-1 {
+ left: 8.33333333%;
+ }
+ .col-md-push-0 {
+ left: auto;
+ }
+ .col-md-offset-12 {
+ margin-left: 100%;
+ }
+ .col-md-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-md-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-md-offset-9 {
+ margin-left: 75%;
+ }
+ .col-md-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-md-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-md-offset-6 {
+ margin-left: 50%;
+ }
+ .col-md-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-md-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-md-offset-3 {
+ margin-left: 25%;
+ }
+ .col-md-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-md-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-md-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+ float: left;
+ }
+ .col-lg-12 {
+ width: 100%;
+ }
+ .col-lg-11 {
+ width: 91.66666667%;
+ }
+ .col-lg-10 {
+ width: 83.33333333%;
+ }
+ .col-lg-9 {
+ width: 75%;
+ }
+ .col-lg-8 {
+ width: 66.66666667%;
+ }
+ .col-lg-7 {
+ width: 58.33333333%;
+ }
+ .col-lg-6 {
+ width: 50%;
+ }
+ .col-lg-5 {
+ width: 41.66666667%;
+ }
+ .col-lg-4 {
+ width: 33.33333333%;
+ }
+ .col-lg-3 {
+ width: 25%;
+ }
+ .col-lg-2 {
+ width: 16.66666667%;
+ }
+ .col-lg-1 {
+ width: 8.33333333%;
+ }
+ .col-lg-pull-12 {
+ right: 100%;
+ }
+ .col-lg-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-lg-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-lg-pull-9 {
+ right: 75%;
+ }
+ .col-lg-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-lg-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-lg-pull-6 {
+ right: 50%;
+ }
+ .col-lg-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-lg-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-lg-pull-3 {
+ right: 25%;
+ }
+ .col-lg-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-lg-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-lg-pull-0 {
+ right: auto;
+ }
+ .col-lg-push-12 {
+ left: 100%;
+ }
+ .col-lg-push-11 {
+ left: 91.66666667%;
+ }
+ .col-lg-push-10 {
+ left: 83.33333333%;
+ }
+ .col-lg-push-9 {
+ left: 75%;
+ }
+ .col-lg-push-8 {
+ left: 66.66666667%;
+ }
+ .col-lg-push-7 {
+ left: 58.33333333%;
+ }
+ .col-lg-push-6 {
+ left: 50%;
+ }
+ .col-lg-push-5 {
+ left: 41.66666667%;
+ }
+ .col-lg-push-4 {
+ left: 33.33333333%;
+ }
+ .col-lg-push-3 {
+ left: 25%;
+ }
+ .col-lg-push-2 {
+ left: 16.66666667%;
+ }
+ .col-lg-push-1 {
+ left: 8.33333333%;
+ }
+ .col-lg-push-0 {
+ left: auto;
+ }
+ .col-lg-offset-12 {
+ margin-left: 100%;
+ }
+ .col-lg-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-lg-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-lg-offset-9 {
+ margin-left: 75%;
+ }
+ .col-lg-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-lg-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-lg-offset-6 {
+ margin-left: 50%;
+ }
+ .col-lg-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-lg-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-lg-offset-3 {
+ margin-left: 25%;
+ }
+ .col-lg-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-lg-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-lg-offset-0 {
+ margin-left: 0%;
+ }
+}
+table {
+ background-color: transparent;
+}
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #777777;
+ text-align: left;
+}
+th {
+ text-align: left;
+}
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #dddddd;
+}
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #dddddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+ border-top: 0;
+}
+.table > tbody + tbody {
+ border-top: 2px solid #dddddd;
+}
+.table .table {
+ background-color: #ffffff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+ padding: 5px;
+}
+.table-bordered {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+ border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+ background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+ background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-column;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-cell;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+ background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+ background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+ background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+ background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+ background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+ background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+ background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+ background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+ background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+ background-color: #ebcccc;
+}
+.table-responsive {
+ overflow-x: auto;
+ min-height: 0.01%;
+}
+@media screen and (max-width: 767px) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: 15px;
+ overflow-y: hidden;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid #dddddd;
+ }
+ .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ .table-responsive > .table > thead > tr > th,
+ .table-responsive > .table > tbody > tr > th,
+ .table-responsive > .table > tfoot > tr > th,
+ .table-responsive > .table > thead > tr > td,
+ .table-responsive > .table > tbody > tr > td,
+ .table-responsive > .table > tfoot > tr > td {
+ white-space: nowrap;
+ }
+ .table-responsive > .table-bordered {
+ border: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+ }
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+ border-bottom: 0;
+ }
+}
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ min-width: 0;
+}
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 20px;
+ font-size: 21px;
+ line-height: inherit;
+ color: #333333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+label {
+ display: inline-block;
+ max-width: 100%;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+input[type="search"] {
+ box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ line-height: normal;
+}
+input[type="file"] {
+ display: block;
+}
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+select[multiple],
+select[size] {
+ height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+output {
+ display: block;
+ padding-top: 7px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555555;
+}
+.form-control {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555555;
+ background-color: #ffffff;
+ background-image: none;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.form-control::-moz-placeholder {
+ color: #999999;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #999999;
+}
+.form-control::-webkit-input-placeholder {
+ color: #999999;
+}
+.form-control::-ms-expand {
+ border: 0;
+ background-color: transparent;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+ background-color: #eeeeee;
+ opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+ cursor: not-allowed;
+}
+textarea.form-control {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type="date"].form-control,
+ input[type="time"].form-control,
+ input[type="datetime-local"].form-control,
+ input[type="month"].form-control {
+ line-height: 34px;
+ }
+ input[type="date"].input-sm,
+ input[type="time"].input-sm,
+ input[type="datetime-local"].input-sm,
+ input[type="month"].input-sm,
+ .input-group-sm input[type="date"],
+ .input-group-sm input[type="time"],
+ .input-group-sm input[type="datetime-local"],
+ .input-group-sm input[type="month"] {
+ line-height: 30px;
+ }
+ input[type="date"].input-lg,
+ input[type="time"].input-lg,
+ input[type="datetime-local"].input-lg,
+ input[type="month"].input-lg,
+ .input-group-lg input[type="date"],
+ .input-group-lg input[type="time"],
+ .input-group-lg input[type="datetime-local"],
+ .input-group-lg input[type="month"] {
+ line-height: 46px;
+ }
+}
+.form-group {
+ margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+ position: relative;
+ display: block;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+ min-height: 20px;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ position: absolute;
+ margin-left: -20px;
+ margin-top: 4px \9;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+ position: relative;
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ vertical-align: middle;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+ cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+ cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+ cursor: not-allowed;
+}
+.form-control-static {
+ padding-top: 7px;
+ padding-bottom: 7px;
+ margin-bottom: 0;
+ min-height: 34px;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-sm {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-sm {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+ height: auto;
+}
+.form-group-sm .form-control {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.form-group-sm select.form-control {
+ height: 30px;
+ line-height: 30px;
+}
+.form-group-sm textarea.form-control,
+.form-group-sm select[multiple].form-control {
+ height: auto;
+}
+.form-group-sm .form-control-static {
+ height: 30px;
+ min-height: 32px;
+ padding: 6px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.input-lg {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-lg {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+ height: auto;
+}
+.form-group-lg .form-control {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.form-group-lg select.form-control {
+ height: 46px;
+ line-height: 46px;
+}
+.form-group-lg textarea.form-control,
+.form-group-lg select[multiple].form-control {
+ height: auto;
+}
+.form-group-lg .form-control-static {
+ height: 46px;
+ min-height: 38px;
+ padding: 11px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.has-feedback {
+ position: relative;
+}
+.has-feedback .form-control {
+ padding-right: 42.5px;
+}
+.form-control-feedback {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ display: block;
+ width: 34px;
+ height: 34px;
+ line-height: 34px;
+ text-align: center;
+ pointer-events: none;
+}
+.input-lg + .form-control-feedback,
+.input-group-lg + .form-control-feedback,
+.form-group-lg .form-control + .form-control-feedback {
+ width: 46px;
+ height: 46px;
+ line-height: 46px;
+}
+.input-sm + .form-control-feedback,
+.input-group-sm + .form-control-feedback,
+.form-group-sm .form-control + .form-control-feedback {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+ color: #3c763d;
+}
+.has-success .form-control {
+ border-color: #3c763d;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-success .form-control:focus {
+ border-color: #2b542c;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+ color: #3c763d;
+ border-color: #3c763d;
+ background-color: #dff0d8;
+}
+.has-success .form-control-feedback {
+ color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+ color: #8a6d3b;
+}
+.has-warning .form-control {
+ border-color: #8a6d3b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-warning .form-control:focus {
+ border-color: #66512c;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+ color: #8a6d3b;
+ border-color: #8a6d3b;
+ background-color: #fcf8e3;
+}
+.has-warning .form-control-feedback {
+ color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+ color: #a94442;
+}
+.has-error .form-control {
+ border-color: #a94442;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-error .form-control:focus {
+ border-color: #843534;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+ color: #a94442;
+ border-color: #a94442;
+ background-color: #f2dede;
+}
+.has-error .form-control-feedback {
+ color: #a94442;
+}
+.has-feedback label ~ .form-control-feedback {
+ top: 25px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+ top: 0;
+}
+.help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #737373;
+}
+@media (min-width: 768px) {
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-static {
+ display: inline-block;
+ }
+ .form-inline .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .form-inline .input-group .input-group-addon,
+ .form-inline .input-group .input-group-btn,
+ .form-inline .input-group .form-control {
+ width: auto;
+ }
+ .form-inline .input-group > .form-control {
+ width: 100%;
+ }
+ .form-inline .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio,
+ .form-inline .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio label,
+ .form-inline .checkbox label {
+ padding-left: 0;
+ }
+ .form-inline .radio input[type="radio"],
+ .form-inline .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 7px;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+ min-height: 27px;
+}
+.form-horizontal .form-group {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .control-label {
+ text-align: right;
+ margin-bottom: 0;
+ padding-top: 7px;
+ }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+ right: 15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-lg .control-label {
+ padding-top: 11px;
+ font-size: 18px;
+ }
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-sm .control-label {
+ padding-top: 6px;
+ font-size: 12px;
+ }
+}
+.btn {
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #333333;
+ text-decoration: none;
+}
+.btn:active,
+.btn.active {
+ outline: 0;
+ background-image: none;
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ box-shadow: none;
+}
+a.btn.disabled,
+fieldset[disabled] a.btn {
+ pointer-events: none;
+}
+.btn-default {
+ color: #333333;
+ background-color: #ffffff;
+ border-color: #cccccc;
+}
+.btn-default:focus,
+.btn-default.focus {
+ color: #333333;
+ background-color: #e6e6e6;
+ border-color: #8c8c8c;
+}
+.btn-default:hover {
+ color: #333333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ color: #333333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active:hover,
+.btn-default.active:hover,
+.open > .dropdown-toggle.btn-default:hover,
+.btn-default:active:focus,
+.btn-default.active:focus,
+.open > .dropdown-toggle.btn-default:focus,
+.btn-default:active.focus,
+.btn-default.active.focus,
+.open > .dropdown-toggle.btn-default.focus {
+ color: #333333;
+ background-color: #d4d4d4;
+ border-color: #8c8c8c;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ background-image: none;
+}
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus {
+ background-color: #ffffff;
+ border-color: #cccccc;
+}
+.btn-default .badge {
+ color: #ffffff;
+ background-color: #333333;
+}
+.btn-primary {
+ color: #ffffff;
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary:focus,
+.btn-primary.focus {
+ color: #ffffff;
+ background-color: #286090;
+ border-color: #122b40;
+}
+.btn-primary:hover {
+ color: #ffffff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ color: #ffffff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active:hover,
+.btn-primary.active:hover,
+.open > .dropdown-toggle.btn-primary:hover,
+.btn-primary:active:focus,
+.btn-primary.active:focus,
+.open > .dropdown-toggle.btn-primary:focus,
+.btn-primary:active.focus,
+.btn-primary.active.focus,
+.open > .dropdown-toggle.btn-primary.focus {
+ color: #ffffff;
+ background-color: #204d74;
+ border-color: #122b40;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ background-image: none;
+}
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus {
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary .badge {
+ color: #337ab7;
+ background-color: #ffffff;
+}
+.btn-success {
+ color: #ffffff;
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success:focus,
+.btn-success.focus {
+ color: #ffffff;
+ background-color: #449d44;
+ border-color: #255625;
+}
+.btn-success:hover {
+ color: #ffffff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ color: #ffffff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active:hover,
+.btn-success.active:hover,
+.open > .dropdown-toggle.btn-success:hover,
+.btn-success:active:focus,
+.btn-success.active:focus,
+.open > .dropdown-toggle.btn-success:focus,
+.btn-success:active.focus,
+.btn-success.active.focus,
+.open > .dropdown-toggle.btn-success.focus {
+ color: #ffffff;
+ background-color: #398439;
+ border-color: #255625;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ background-image: none;
+}
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus {
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success .badge {
+ color: #5cb85c;
+ background-color: #ffffff;
+}
+.btn-info {
+ color: #ffffff;
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info:focus,
+.btn-info.focus {
+ color: #ffffff;
+ background-color: #31b0d5;
+ border-color: #1b6d85;
+}
+.btn-info:hover {
+ color: #ffffff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ color: #ffffff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active:hover,
+.btn-info.active:hover,
+.open > .dropdown-toggle.btn-info:hover,
+.btn-info:active:focus,
+.btn-info.active:focus,
+.open > .dropdown-toggle.btn-info:focus,
+.btn-info:active.focus,
+.btn-info.active.focus,
+.open > .dropdown-toggle.btn-info.focus {
+ color: #ffffff;
+ background-color: #269abc;
+ border-color: #1b6d85;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ background-image: none;
+}
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus {
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info .badge {
+ color: #5bc0de;
+ background-color: #ffffff;
+}
+.btn-warning {
+ color: #ffffff;
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning:focus,
+.btn-warning.focus {
+ color: #ffffff;
+ background-color: #ec971f;
+ border-color: #985f0d;
+}
+.btn-warning:hover {
+ color: #ffffff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ color: #ffffff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active:hover,
+.btn-warning.active:hover,
+.open > .dropdown-toggle.btn-warning:hover,
+.btn-warning:active:focus,
+.btn-warning.active:focus,
+.open > .dropdown-toggle.btn-warning:focus,
+.btn-warning:active.focus,
+.btn-warning.active.focus,
+.open > .dropdown-toggle.btn-warning.focus {
+ color: #ffffff;
+ background-color: #d58512;
+ border-color: #985f0d;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ background-image: none;
+}
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus {
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning .badge {
+ color: #f0ad4e;
+ background-color: #ffffff;
+}
+.btn-danger {
+ color: #ffffff;
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger:focus,
+.btn-danger.focus {
+ color: #ffffff;
+ background-color: #c9302c;
+ border-color: #761c19;
+}
+.btn-danger:hover {
+ color: #ffffff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ color: #ffffff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active:hover,
+.btn-danger.active:hover,
+.open > .dropdown-toggle.btn-danger:hover,
+.btn-danger:active:focus,
+.btn-danger.active:focus,
+.open > .dropdown-toggle.btn-danger:focus,
+.btn-danger:active.focus,
+.btn-danger.active.focus,
+.open > .dropdown-toggle.btn-danger.focus {
+ color: #ffffff;
+ background-color: #ac2925;
+ border-color: #761c19;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ background-image: none;
+}
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus {
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger .badge {
+ color: #d9534f;
+ background-color: #ffffff;
+}
+.btn-link {
+ color: #337ab7;
+ font-weight: normal;
+ border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+ background-color: transparent;
+ box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+ border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+ color: #23527c;
+ text-decoration: underline;
+ background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+ color: #777777;
+ text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+.fade {
+ opacity: 0;
+ transition: opacity 0.15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.collapse {
+ display: none;
+}
+.collapse.in {
+ display: block;
+}
+tr.collapse.in {
+ display: table-row;
+}
+tbody.collapse.in {
+ display: table-row-group;
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ transition-property: height, visibility;
+ transition-duration: 0.35s;
+ transition-timing-function: ease;
+}
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: 4px dashed;
+ border-top: 4px solid \9;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle:focus {
+ outline: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ list-style: none;
+ font-size: 14px;
+ text-align: left;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 4px;
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ background-clip: padding-box;
+}
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.42857143;
+ color: #333333;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ text-decoration: none;
+ color: #262626;
+ background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ text-decoration: none;
+ outline: 0;
+ background-color: #337ab7;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #777777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ cursor: not-allowed;
+}
+.open > .dropdown-menu {
+ display: block;
+}
+.open > a {
+ outline: 0;
+}
+.dropdown-menu-right {
+ left: auto;
+ right: 0;
+}
+.dropdown-menu-left {
+ left: 0;
+ right: auto;
+}
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: 12px;
+ line-height: 1.42857143;
+ color: #777777;
+ white-space: nowrap;
+}
+.dropdown-backdrop {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ z-index: 990;
+}
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ border-top: 0;
+ border-bottom: 4px dashed;
+ border-bottom: 4px solid \9;
+ content: "";
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-right .dropdown-menu {
+ left: auto;
+ right: 0;
+ }
+ .navbar-right .dropdown-menu-left {
+ left: 0;
+ right: auto;
+ }
+}
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+ z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+ margin-left: -1px;
+}
+.btn-toolbar {
+ margin-left: -5px;
+}
+.btn-toolbar .btn,
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+ float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+ margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+.btn-group > .btn:first-child {
+ margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+.btn-group.open .dropdown-toggle {
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+ box-shadow: none;
+}
+.btn .caret {
+ margin-left: 0;
+}
+.btn-lg .caret {
+ border-width: 5px 5px 0;
+ border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+ border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+ float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+ float: none;
+ display: table-cell;
+ width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+ width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+ left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+.input-group {
+ position: relative;
+ display: table;
+ border-collapse: separate;
+}
+.input-group[class*="col-"] {
+ float: none;
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+}
+.input-group .form-control:focus {
+ z-index: 3;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+.input-group-addon {
+ padding: 6px 12px;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1;
+ color: #555555;
+ text-align: center;
+ background-color: #eeeeee;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+}
+.input-group-addon.input-sm {
+ padding: 5px 10px;
+ font-size: 12px;
+ border-radius: 3px;
+}
+.input-group-addon.input-lg {
+ padding: 10px 16px;
+ font-size: 18px;
+ border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+ margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap;
+}
+.input-group-btn > .btn {
+ position: relative;
+}
+.input-group-btn > .btn + .btn {
+ margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+ z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+ margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+ z-index: 2;
+ margin-left: -1px;
+}
+.nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+}
+.nav > li {
+ position: relative;
+ display: block;
+}
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #eeeeee;
+}
+.nav > li.disabled > a {
+ color: #777777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+ color: #777777;
+ text-decoration: none;
+ background-color: transparent;
+ cursor: not-allowed;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #eeeeee;
+ border-color: #337ab7;
+}
+.nav .nav-divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.nav > li > a > img {
+ max-width: none;
+}
+.nav-tabs {
+ border-bottom: 1px solid #dddddd;
+}
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+ border-color: #eeeeee #eeeeee #dddddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #555555;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-bottom-color: transparent;
+ cursor: default;
+}
+.nav-tabs.nav-justified {
+ width: 100%;
+ border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+ float: none;
+}
+.nav-tabs.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-tabs.nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs.nav-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs.nav-justified > .active > a,
+ .nav-tabs.nav-justified > .active > a:hover,
+ .nav-tabs.nav-justified > .active > a:focus {
+ border-bottom-color: #ffffff;
+ }
+}
+.nav-pills > li {
+ float: left;
+}
+.nav-pills > li > a {
+ border-radius: 4px;
+}
+.nav-pills > li + li {
+ margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+ color: #ffffff;
+ background-color: #337ab7;
+}
+.nav-stacked > li {
+ float: none;
+}
+.nav-stacked > li + li {
+ margin-top: 2px;
+ margin-left: 0;
+}
+.nav-justified {
+ width: 100%;
+}
+.nav-justified > li {
+ float: none;
+}
+.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs-justified {
+ border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs-justified > .active > a,
+ .nav-tabs-justified > .active > a:hover,
+ .nav-tabs-justified > .active > a:focus {
+ border-bottom-color: #ffffff;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-header {
+ float: left;
+ }
+}
+.navbar-collapse {
+ overflow-x: visible;
+ padding-right: 15px;
+ padding-left: 15px;
+ border-top: 1px solid transparent;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
+ -webkit-overflow-scrolling: touch;
+}
+.navbar-collapse.in {
+ overflow-y: auto;
+}
+@media (min-width: 768px) {
+ .navbar-collapse {
+ width: auto;
+ border-top: 0;
+ box-shadow: none;
+ }
+ .navbar-collapse.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0;
+ overflow: visible !important;
+ }
+ .navbar-collapse.in {
+ overflow-y: visible;
+ }
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-static-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+ max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ max-height: 200px;
+ }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .container > .navbar-header,
+ .container-fluid > .navbar-header,
+ .container > .navbar-collapse,
+ .container-fluid > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.navbar-static-top {
+ z-index: 1000;
+ border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+ .navbar-static-top {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+@media (min-width: 768px) {
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0;
+ border-width: 1px 0 0;
+}
+.navbar-brand {
+ float: left;
+ padding: 15px 15px;
+ font-size: 18px;
+ line-height: 20px;
+ height: 50px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+.navbar-brand > img {
+ display: block;
+}
+@media (min-width: 768px) {
+ .navbar > .container .navbar-brand,
+ .navbar > .container-fluid .navbar-brand {
+ margin-left: -15px;
+ }
+}
+.navbar-toggle {
+ position: relative;
+ float: right;
+ margin-right: 15px;
+ padding: 9px 10px;
+ margin-top: 8px;
+ margin-bottom: 8px;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.navbar-toggle:focus {
+ outline: 0;
+}
+.navbar-toggle .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+ margin-top: 4px;
+}
+@media (min-width: 768px) {
+ .navbar-toggle {
+ display: none;
+ }
+}
+.navbar-nav {
+ margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 20px;
+}
+@media (max-width: 767px) {
+ .navbar-nav .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ box-shadow: none;
+ }
+ .navbar-nav .open .dropdown-menu > li > a,
+ .navbar-nav .open .dropdown-menu .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a {
+ line-height: 20px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-nav .open .dropdown-menu > li > a:focus {
+ background-image: none;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+ .navbar-nav > li {
+ float: left;
+ }
+ .navbar-nav > li > a {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+}
+.navbar-form {
+ margin-left: -15px;
+ margin-right: -15px;
+ padding: 10px 15px;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+@media (min-width: 768px) {
+ .navbar-form .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control-static {
+ display: inline-block;
+ }
+ .navbar-form .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .navbar-form .input-group .input-group-addon,
+ .navbar-form .input-group .input-group-btn,
+ .navbar-form .input-group .form-control {
+ width: auto;
+ }
+ .navbar-form .input-group > .form-control {
+ width: 100%;
+ }
+ .navbar-form .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio,
+ .navbar-form .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio label,
+ .navbar-form .checkbox label {
+ padding-left: 0;
+ }
+ .navbar-form .radio input[type="radio"],
+ .navbar-form .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .navbar-form .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+@media (max-width: 767px) {
+ .navbar-form .form-group {
+ margin-bottom: 5px;
+ }
+ .navbar-form .form-group:last-child {
+ margin-bottom: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-form {
+ width: auto;
+ border: 0;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ box-shadow: none;
+ }
+}
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ margin-bottom: 0;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.navbar-btn {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+ margin-top: 14px;
+ margin-bottom: 14px;
+}
+.navbar-text {
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .navbar-text {
+ float: left;
+ margin-left: 15px;
+ margin-right: 15px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -15px;
+ }
+ .navbar-right ~ .navbar-right {
+ margin-right: 0;
+ }
+}
+.navbar-default {
+ background-color: #f8f8f8;
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+ color: #777777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+ color: #5e5e5e;
+ background-color: transparent;
+}
+.navbar-default .navbar-text {
+ color: #777777;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #777777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+ color: #333333;
+ background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+ color: #555555;
+ background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+ border-color: #dddddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+ background-color: #dddddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #888888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+ background-color: #e7e7e7;
+ color: #555555;
+}
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #777777;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #333333;
+ background-color: transparent;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #555555;
+ background-color: #e7e7e7;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+ }
+}
+.navbar-default .navbar-link {
+ color: #777777;
+}
+.navbar-default .navbar-link:hover {
+ color: #333333;
+}
+.navbar-default .btn-link {
+ color: #777777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+ color: #333333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+ color: #cccccc;
+}
+.navbar-inverse {
+ background-color: #222222;
+ border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #ffffff;
+ background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+ color: #444444;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: #333333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #333333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #ffffff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ background-color: #080808;
+ color: #ffffff;
+}
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+ border-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #9d9d9d;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #444444;
+ background-color: transparent;
+ }
+}
+.navbar-inverse .navbar-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+ color: #444444;
+}
+.breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 20px;
+ list-style: none;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+}
+.breadcrumb > li {
+ display: inline-block;
+}
+.breadcrumb > li + li:before {
+ content: "/\00a0";
+ padding: 0 5px;
+ color: #cccccc;
+}
+.breadcrumb > .active {
+ color: #777777;
+}
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: 20px 0;
+ border-radius: 4px;
+}
+.pagination > li {
+ display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+ position: relative;
+ float: left;
+ padding: 6px 12px;
+ line-height: 1.42857143;
+ text-decoration: none;
+ color: #337ab7;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ margin-left: -1px;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+ margin-left: 0;
+ border-bottom-left-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+ z-index: 2;
+ color: #23527c;
+ background-color: #eeeeee;
+ border-color: #dddddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+ z-index: 3;
+ color: #ffffff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+ cursor: default;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+ color: #777777;
+ background-color: #ffffff;
+ border-color: #dddddd;
+ cursor: not-allowed;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+ border-bottom-left-radius: 6px;
+ border-top-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+ border-bottom-right-radius: 6px;
+ border-top-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+ border-bottom-left-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+ border-bottom-right-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.pager {
+ padding-left: 0;
+ margin: 20px 0;
+ list-style: none;
+ text-align: center;
+}
+.pager li {
+ display: inline;
+}
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #eeeeee;
+}
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+ color: #777777;
+ background-color: #ffffff;
+ cursor: not-allowed;
+}
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #ffffff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.label:empty {
+ display: none;
+}
+.btn .label {
+ position: relative;
+ top: -1px;
+}
+.label-default {
+ background-color: #777777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+ background-color: #5e5e5e;
+}
+.label-primary {
+ background-color: #337ab7;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+ background-color: #286090;
+}
+.label-success {
+ background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+ background-color: #449d44;
+}
+.label-info {
+ background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+ background-color: #31b0d5;
+}
+.label-warning {
+ background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+ background-color: #ec971f;
+}
+.label-danger {
+ background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+ background-color: #c9302c;
+}
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: 12px;
+ font-weight: bold;
+ color: #ffffff;
+ line-height: 1;
+ vertical-align: middle;
+ white-space: nowrap;
+ text-align: center;
+ background-color: #777777;
+ border-radius: 10px;
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+ top: 0;
+ padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: #337ab7;
+ background-color: #ffffff;
+}
+.list-group-item > .badge {
+ float: right;
+}
+.list-group-item > .badge + .badge {
+ margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
+.jumbotron {
+ padding-top: 30px;
+ padding-bottom: 30px;
+ margin-bottom: 30px;
+ color: inherit;
+ background-color: #eeeeee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+ color: inherit;
+}
+.jumbotron p {
+ margin-bottom: 15px;
+ font-size: 21px;
+ font-weight: 200;
+}
+.jumbotron > hr {
+ border-top-color: #d5d5d5;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+ border-radius: 6px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.jumbotron .container {
+ max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+ .jumbotron {
+ padding-top: 48px;
+ padding-bottom: 48px;
+ }
+ .container .jumbotron,
+ .container-fluid .jumbotron {
+ padding-left: 60px;
+ padding-right: 60px;
+ }
+ .jumbotron h1,
+ .jumbotron .h1 {
+ font-size: 63px;
+ }
+}
+.thumbnail {
+ display: block;
+ padding: 4px;
+ margin-bottom: 20px;
+ line-height: 1.42857143;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ transition: border 0.2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+ margin-left: auto;
+ margin-right: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: #337ab7;
+}
+.thumbnail .caption {
+ padding: 9px;
+ color: #333333;
+}
+.alert {
+ padding: 15px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.alert h4 {
+ margin-top: 0;
+ color: inherit;
+}
+.alert .alert-link {
+ font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+ margin-bottom: 0;
+}
+.alert > p + p {
+ margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+ padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+}
+.alert-success {
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+ color: #3c763d;
+}
+.alert-success hr {
+ border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+ color: #2b542c;
+}
+.alert-info {
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+ color: #31708f;
+}
+.alert-info hr {
+ border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+ color: #245269;
+}
+.alert-warning {
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+ color: #8a6d3b;
+}
+.alert-warning hr {
+ border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+ color: #66512c;
+}
+.alert-danger {
+ background-color: #f2dede;
+ border-color: #ebccd1;
+ color: #a94442;
+}
+.alert-danger hr {
+ border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+ color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ overflow: hidden;
+ height: 20px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+.progress-bar {
+ float: left;
+ width: 0%;
+ height: 100%;
+ font-size: 12px;
+ line-height: 20px;
+ color: #ffffff;
+ text-align: center;
+ background-color: #337ab7;
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ transition: width 0.6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+ background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+ background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+ background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+ background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+.media,
+.media-body {
+ zoom: 1;
+ overflow: hidden;
+}
+.media-body {
+ width: 10000px;
+}
+.media-object {
+ display: block;
+}
+.media-object.img-thumbnail {
+ max-width: none;
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+ display: table-cell;
+ vertical-align: top;
+}
+.media-middle {
+ vertical-align: middle;
+}
+.media-bottom {
+ vertical-align: bottom;
+}
+.media-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
+.list-group {
+ margin-bottom: 20px;
+ padding-left: 0;
+}
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+}
+.list-group-item:first-child {
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+a.list-group-item,
+button.list-group-item {
+ color: #555555;
+}
+a.list-group-item .list-group-item-heading,
+button.list-group-item .list-group-item-heading {
+ color: #333333;
+}
+a.list-group-item:hover,
+button.list-group-item:hover,
+a.list-group-item:focus,
+button.list-group-item:focus {
+ text-decoration: none;
+ color: #555555;
+ background-color: #f5f5f5;
+}
+button.list-group-item {
+ width: 100%;
+ text-align: left;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+ background-color: #eeeeee;
+ color: #777777;
+ cursor: not-allowed;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+ color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+ color: #777777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ z-index: 2;
+ color: #ffffff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+ color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+ color: #c7ddef;
+}
+.list-group-item-success {
+ color: #3c763d;
+ background-color: #dff0d8;
+}
+a.list-group-item-success,
+button.list-group-item-success {
+ color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-success:hover,
+button.list-group-item-success:hover,
+a.list-group-item-success:focus,
+button.list-group-item-success:focus {
+ color: #3c763d;
+ background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+button.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+button.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus,
+button.list-group-item-success.active:focus {
+ color: #fff;
+ background-color: #3c763d;
+ border-color: #3c763d;
+}
+.list-group-item-info {
+ color: #31708f;
+ background-color: #d9edf7;
+}
+a.list-group-item-info,
+button.list-group-item-info {
+ color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-info:hover,
+button.list-group-item-info:hover,
+a.list-group-item-info:focus,
+button.list-group-item-info:focus {
+ color: #31708f;
+ background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+button.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+button.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus,
+button.list-group-item-info.active:focus {
+ color: #fff;
+ background-color: #31708f;
+ border-color: #31708f;
+}
+.list-group-item-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+}
+a.list-group-item-warning,
+button.list-group-item-warning {
+ color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-warning:hover,
+button.list-group-item-warning:hover,
+a.list-group-item-warning:focus,
+button.list-group-item-warning:focus {
+ color: #8a6d3b;
+ background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+button.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:focus {
+ color: #fff;
+ background-color: #8a6d3b;
+ border-color: #8a6d3b;
+}
+.list-group-item-danger {
+ color: #a94442;
+ background-color: #f2dede;
+}
+a.list-group-item-danger,
+button.list-group-item-danger {
+ color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-danger:hover,
+button.list-group-item-danger:hover,
+a.list-group-item-danger:focus,
+button.list-group-item-danger:focus {
+ color: #a94442;
+ background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+button.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:focus {
+ color: #fff;
+ background-color: #a94442;
+ border-color: #a94442;
+}
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
+.panel {
+ margin-bottom: 20px;
+ background-color: #ffffff;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.panel-body {
+ padding: 15px;
+}
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+ color: inherit;
+}
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 16px;
+ color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+ color: inherit;
+}
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #dddddd;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+ margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+ border-top: 0;
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+ border-bottom: 0;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+ border-top-width: 0;
+}
+.list-group + .panel-footer {
+ border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+ margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+ border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+ border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+ border-top: 1px solid #dddddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+ border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+ border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+ border-bottom: 0;
+}
+.panel > .table-responsive {
+ border: 0;
+ margin-bottom: 0;
+}
+.panel-group {
+ margin-bottom: 20px;
+}
+.panel-group .panel {
+ margin-bottom: 0;
+ border-radius: 4px;
+}
+.panel-group .panel + .panel {
+ margin-top: 5px;
+}
+.panel-group .panel-heading {
+ border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+ border-top: 1px solid #dddddd;
+}
+.panel-group .panel-footer {
+ border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+ border-bottom: 1px solid #dddddd;
+}
+.panel-default {
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading {
+ color: #333333;
+ background-color: #f5f5f5;
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #dddddd;
+}
+.panel-default > .panel-heading .badge {
+ color: #f5f5f5;
+ background-color: #333333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #dddddd;
+}
+.panel-primary {
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading {
+ color: #ffffff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #337ab7;
+}
+.panel-primary > .panel-heading .badge {
+ color: #337ab7;
+ background-color: #ffffff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #337ab7;
+}
+.panel-success {
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+ color: #dff0d8;
+ background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #d6e9c6;
+}
+.panel-info {
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+ color: #31708f;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+ color: #d9edf7;
+ background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #bce8f1;
+}
+.panel-warning {
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+ color: #fcf8e3;
+ background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #faebcc;
+}
+.panel-danger {
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+ color: #f2dede;
+ background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ height: 100%;
+ width: 100%;
+ border: 0;
+}
+.embed-responsive-16by9 {
+ padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+ padding-bottom: 75%;
+}
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-radius: 4px;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, 0.15);
+}
+.well-lg {
+ padding: 24px;
+ border-radius: 6px;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: 3px;
+}
+.close {
+ float: right;
+ font-size: 21px;
+ font-weight: bold;
+ line-height: 1;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+.close:hover,
+.close:focus {
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ display: none;
+ overflow: hidden;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+ transition: -webkit-transform 0.3s ease-out;
+ transition: transform 0.3s ease-out;
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #ffffff;
+ border: 1px solid #999999;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 6px;
+ box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
+ background-clip: padding-box;
+ outline: 0;
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000000;
+}
+.modal-backdrop.fade {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.modal-backdrop.in {
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+.modal-header {
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 15px;
+}
+.modal-footer {
+ padding: 15px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-left: 5px;
+ margin-bottom: 0;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ letter-spacing: normal;
+ line-break: auto;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ white-space: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ font-size: 12px;
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.tooltip.in {
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.tooltip.top {
+ margin-top: -3px;
+ padding: 5px 0;
+}
+.tooltip.right {
+ margin-left: 3px;
+ padding: 0 5px;
+}
+.tooltip.bottom {
+ margin-top: 3px;
+ padding: 5px 0;
+}
+.tooltip.left {
+ margin-left: -3px;
+ padding: 0 5px;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #ffffff;
+ text-align: center;
+ background-color: #000000;
+ border-radius: 4px;
+}
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.top-left .tooltip-arrow {
+ bottom: 0;
+ right: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.top-right .tooltip-arrow {
+ bottom: 0;
+ left: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-width: 5px 5px 5px 0;
+ border-right-color: #000000;
+}
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-width: 5px 0 5px 5px;
+ border-left-color: #000000;
+}
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+ top: 0;
+ right: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+ top: 0;
+ left: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ letter-spacing: normal;
+ line-break: auto;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ white-space: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ font-size: 14px;
+ background-color: #ffffff;
+ background-clip: padding-box;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 6px;
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+}
+.popover.top {
+ margin-top: -10px;
+}
+.popover.right {
+ margin-left: 10px;
+}
+.popover.bottom {
+ margin-top: 10px;
+}
+.popover.left {
+ margin-left: -10px;
+}
+.popover-title {
+ margin: 0;
+ padding: 8px 14px;
+ font-size: 14px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-radius: 5px 5px 0 0;
+}
+.popover-content {
+ padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.popover > .arrow {
+ border-width: 11px;
+}
+.popover > .arrow:after {
+ border-width: 10px;
+ content: "";
+}
+.popover.top > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-bottom-width: 0;
+ border-top-color: #999999;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ bottom: -11px;
+}
+.popover.top > .arrow:after {
+ content: " ";
+ bottom: 1px;
+ margin-left: -10px;
+ border-bottom-width: 0;
+ border-top-color: #ffffff;
+}
+.popover.right > .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-left-width: 0;
+ border-right-color: #999999;
+ border-right-color: rgba(0, 0, 0, 0.25);
+}
+.popover.right > .arrow:after {
+ content: " ";
+ left: 1px;
+ bottom: -10px;
+ border-left-width: 0;
+ border-right-color: #ffffff;
+}
+.popover.bottom > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: #999999;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+ top: -11px;
+}
+.popover.bottom > .arrow:after {
+ content: " ";
+ top: 1px;
+ margin-left: -10px;
+ border-top-width: 0;
+ border-bottom-color: #ffffff;
+}
+.popover.left > .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: #999999;
+ border-left-color: rgba(0, 0, 0, 0.25);
+}
+.popover.left > .arrow:after {
+ content: " ";
+ right: 1px;
+ border-right-width: 0;
+ border-left-color: #ffffff;
+ bottom: -10px;
+}
+.carousel {
+ position: relative;
+}
+.carousel-inner {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+}
+.carousel-inner > .item {
+ display: none;
+ position: relative;
+ transition: 0.6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+ .carousel-inner > .item {
+ transition: -webkit-transform 0.6s ease-in-out;
+ transition: transform 0.6s ease-in-out;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-perspective: 1000px;
+ perspective: 1000px;
+ }
+ .carousel-inner > .item.next,
+ .carousel-inner > .item.active.right {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.prev,
+ .carousel-inner > .item.active.left {
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.next.left,
+ .carousel-inner > .item.prev.right,
+ .carousel-inner > .item.active {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ left: 0;
+ }
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ display: block;
+}
+.carousel-inner > .active {
+ left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+.carousel-inner > .next {
+ left: 100%;
+}
+.carousel-inner > .prev {
+ left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+ left: 0;
+}
+.carousel-inner > .active.left {
+ left: -100%;
+}
+.carousel-inner > .active.right {
+ left: 100%;
+}
+.carousel-control {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 15%;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ font-size: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+ background-color: rgba(0, 0, 0, 0);
+}
+.carousel-control.left {
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+.carousel-control.right {
+ left: auto;
+ right: 0;
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+.carousel-control:hover,
+.carousel-control:focus {
+ outline: 0;
+ color: #ffffff;
+ text-decoration: none;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ margin-top: -10px;
+ z-index: 5;
+ display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+ left: 50%;
+ margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+ right: 50%;
+ margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+ width: 20px;
+ height: 20px;
+ line-height: 1;
+ font-family: serif;
+}
+.carousel-control .icon-prev:before {
+ content: '\2039';
+}
+.carousel-control .icon-next:before {
+ content: '\203a';
+}
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ margin-left: -30%;
+ padding-left: 0;
+ list-style: none;
+ text-align: center;
+}
+.carousel-indicators li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ border: 1px solid #ffffff;
+ border-radius: 10px;
+ cursor: pointer;
+ background-color: #000 \9;
+ background-color: rgba(0, 0, 0, 0);
+}
+.carousel-indicators .active {
+ margin: 0;
+ width: 12px;
+ height: 12px;
+ background-color: #ffffff;
+}
+.carousel-caption {
+ position: absolute;
+ left: 15%;
+ right: 15%;
+ bottom: 20px;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+.carousel-caption .btn {
+ text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-prev,
+ .carousel-control .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -10px;
+ font-size: 30px;
+ }
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .icon-prev {
+ margin-left: -10px;
+ }
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-next {
+ margin-right: -10px;
+ }
+ .carousel-caption {
+ left: 20%;
+ right: 20%;
+ padding-bottom: 30px;
+ }
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-header:before,
+.modal-header:after,
+.modal-footer:before,
+.modal-footer:after {
+ content: " ";
+ display: table;
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-header:after,
+.modal-footer:after {
+ clear: both;
+}
+.center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+.hidden {
+ display: none !important;
+}
+.affix {
+ position: fixed;
+}
+@-ms-viewport {
+ width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+ display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+ display: none !important;
+}
+@media (max-width: 767px) {
+ .visible-xs {
+ display: block !important;
+ }
+ table.visible-xs {
+ display: table !important;
+ }
+ tr.visible-xs {
+ display: table-row !important;
+ }
+ th.visible-xs,
+ td.visible-xs {
+ display: table-cell !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-block {
+ display: block !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline {
+ display: inline !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm {
+ display: block !important;
+ }
+ table.visible-sm {
+ display: table !important;
+ }
+ tr.visible-sm {
+ display: table-row !important;
+ }
+ th.visible-sm,
+ td.visible-sm {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-block {
+ display: block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md {
+ display: block !important;
+ }
+ table.visible-md {
+ display: table !important;
+ }
+ tr.visible-md {
+ display: table-row !important;
+ }
+ th.visible-md,
+ td.visible-md {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-block {
+ display: block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg {
+ display: block !important;
+ }
+ table.visible-lg {
+ display: table !important;
+ }
+ tr.visible-lg {
+ display: table-row !important;
+ }
+ th.visible-lg,
+ td.visible-lg {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-block {
+ display: block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
+.visible-print {
+ display: none !important;
+}
+@media print {
+ .visible-print {
+ display: block !important;
+ }
+ table.visible-print {
+ display: table !important;
+ }
+ tr.visible-print {
+ display: table-row !important;
+ }
+ th.visible-print,
+ td.visible-print {
+ display: table-cell !important;
+ }
+}
+.visible-print-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-block {
+ display: block !important;
+ }
+}
+.visible-print-inline {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline {
+ display: inline !important;
+ }
+}
+.visible-print-inline-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline-block {
+ display: inline-block !important;
+ }
+}
+@media print {
+ .hidden-print {
+ display: none !important;
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.less b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.less
new file mode 100644
index 00000000..2d0f5cc6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.less
@@ -0,0 +1,3 @@
+@import '../../bower_components/bootstrap/less/bootstrap.less';
+
+@icon-font-path: '/fonts/';
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/angular-markdown-directive/markdown.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/angular-markdown-directive/markdown.js
new file mode 100644
index 00000000..989a6bec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/angular-markdown-directive/markdown.js
@@ -0,0 +1,36 @@
+/*
+ * angular-markdown-directive v0.3.1
+ * (c) 2013-2014 Brian Ford http://briantford.com
+ * License: MIT
+ */
+
+'use strict';
+
+angular.module('btford.markdown', ['ngSanitize']).
+ provider('markdownConverter', function () {
+ var opts = {};
+ return {
+ config: function (newOpts) {
+ opts = newOpts;
+ },
+ $get: function () {
+ return new Showdown.converter(opts);
+ }
+ };
+ }).
+ directive('btfMarkdown', ['$sanitize', 'markdownConverter', function ($sanitize, markdownConverter) {
+ return {
+ restrict: 'AE',
+ link: function (scope, element, attrs) {
+ if (attrs.btfMarkdown) {
+ scope.$watch(attrs.btfMarkdown, function (newVal) {
+ var html = newVal ? $sanitize(markdownConverter.makeHtml(newVal)) : '';
+ element.html(html);
+ });
+ } else {
+ var html = $sanitize(markdownConverter.makeHtml(element.text()));
+ element.html(html);
+ }
+ }
+ };
+ }]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsCtrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsCtrl.js
new file mode 100644
index 00000000..4b420a27
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsCtrl.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .controller('WidgetSettingsCtrl', ['$scope', '$uibModalInstance', 'widget', function ($scope, $uibModalInstance, widget) {
+ // add widget to scope
+ $scope.widget = widget;
+
+ // set up result object
+ $scope.result = jQuery.extend(true, {}, widget);
+
+ $scope.ok = function () {
+ $uibModalInstance.close($scope.result);
+ };
+
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsRaptorReportCtrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsRaptorReportCtrl.js
new file mode 100644
index 00000000..fd6a0b02
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsRaptorReportCtrl.js
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .controller('WidgetSettingsRaptorReportCtrl', ['$http','$scope','$rootScope','$uibModalInstance', 'widget', function ($http,$scope,$rootScope,$uibModalInstance, widget) {
+
+ // add watch function for widget here
+ // leave ajax call to the dashboard.js
+
+ console.log("============= WidgetSettingsRaptorReportCtrl scope =================");
+ console.log($scope);
+
+ var getFormFieldListUrl = "raptor.htm?action=report.run.container&c_master="+widget.report_id + "&refresh=Y"
+ console.log("============= getFormFieldListUrl =============");
+ console.log(getFormFieldListUrl);
+ $http.get(getFormFieldListUrl).then(
+ function(res){
+ $scope.reportData = res.data;
+ // add widget to scope
+ $scope.showFormFieldIds = false;
+ $scope.formFieldSelectedValues = {};
+});
+
+ var parseQueryString = function( queryString ) {
+ var params = {}, queries, temp, i, l;
+ // Split into key/value pairs
+ queries = queryString.split("&");
+ // Convert the array of strings into an object
+ for ( i = 0, l = queries.length; i < l; i++ ) {
+ temp = queries[i].split('=');
+ //console.log(temp[0]);
+ //console.log(temp[0] != "refresh");
+ if(temp[0] && temp[0] != "refresh")
+ params[temp[0]] = temp[1];
+ }
+ return params;
+ };
+
+ var paginationOptions = {
+ pageNumber: 1,
+ pageSize: 5,
+ sort: null
+ };
+
+ $scope.gridOptions = {
+ paginationPageSizes: [5],
+ paginationPageSize: 5,
+ useExternalPagination: true,
+ columnDefs: [],
+ data: [],
+ enableGridMenu: true,
+ enableSelectAll: true,
+ exporterMenuPdf: false,
+ exporterMenuCsv: false,
+ exporterCsvFilename: 'myFile.csv',
+ exporterPdfDefaultStyle: {fontSize: 9},
+ exporterPdfTableStyle: {margin: [30, 30, 30, 30]},
+ exporterPdfTableHeaderStyle: {fontSize: 10, bol$rootScoped: true, italics: true, color: 'red'},
+ exporterPdfHeader: { text: "My Header", style: 'headerStyle' },
+ exporterPdfFooter: function ( currentPage, pageCount ) {
+ return { text: currentPage.toString() + ' of ' + pageCount.toString(), style: 'footerStyle' };
+ },
+ exporterPdfCustomFormatter: function ( docDefinition ) {
+ docDefinition.styles.headerStyle = { fontSize: 22, bold: true };
+ docDefinition.styles.footerStyle = { fontSize: 10, bold: true };
+ return docDefinition;
+ },
+ exporterPdfOrientation: 'portrait',
+ exporterPdfPageSize: 'LETTER',
+ exporterPdfMaxGridWidth: 500,
+ exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
+ onRegisterApi: function(gridApi) {
+ $scope.gridApi = gridApi;
+ gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
+ paginationOptions.pageNumber = newPage;
+ paginationOptions.pageSize = pageSize;
+ $scope.runReport();
+ });
+ }
+ };
+
+
+
+ $scope.getFormFieldSelectedValuesAsURL = function(){
+ var formFieldsUrl = '';
+ $scope.widget.reportData.formFieldList.forEach(function(formField) {
+ if(formField.fieldType==='LIST_BOX') {
+ if($scope.formFieldSelectedValues && $scope.formFieldSelectedValues[formField.fieldId] && $scope.formFieldSelectedValues[formField.fieldId].value != '') {
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId].value+'&';
+ }
+ } else if(formField.fieldType==='LIST_MULTI_SELECT') {
+ if($scope.formFieldSelectedValues[formField.fieldId].length >0) {
+ for (var i = 0; i < $scope.formFieldSelectedValues[formField.fieldId].length; i++) {
+ if($scope.formFieldSelectedValues[formField.fieldId][i].defaultValue){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId][i].value+'&';
+ }
+ }
+ }
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && formField.validationType === 'DATE'){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+dateFilter($scope.formFieldSelectedValues[formField.fieldId],$scope.dateformat)+'&';
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && formField.validationType === 'TIMESTAMP_MIN'){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+dateFilter($scope.formFieldSelectedValues[formField.fieldId],$scope.datetimeformat)+'&';
+ } else if((formField.fieldType === 'text' || formField.fieldType === 'TEXT') && $scope.formFieldSelectedValues[formField.fieldId] && $scope.formFieldSelectedValues[formField.fieldId] != ''){
+ formFieldsUrl = formFieldsUrl+formField.fieldId+'='+$scope.formFieldSelectedValues[formField.fieldId]+'&';
+ }
+ });
+ return formFieldsUrl;
+
+ }
+
+ $scope.triggerOtherFormFields = function(){
+ console.log("report_run");
+ var formFieldsUrl = $scope.getFormFieldSelectedValuesAsURL();
+ $http.get('raptor.htm?action=report.formfields.run.container&c_master='+widget.report_id+'&'+formFieldsUrl).then(
+ function(response){
+ $scope.widget.reportData = response.data;
+ });
+ };
+
+
+ $scope.runReport = function(pagination){
+ var formFieldsUrl = $scope.getFormFieldSelectedValuesAsURL();
+ console.log("pagination");
+ if(!pagination) {
+ console.log("refreshed ...");
+ $scope.gridOptions.pageNumber = 1;
+ $scope.gridOptions.paginationPageSizes= [widget.reportData.pageSize];
+ $scope.gridOptions.paginationPageSize= widget.reportData.pageSize;
+ if(widget.reportData.totalRows<14){
+ $scope.gridHeight = (widget.reportData.totalRows+7)*30+'px';
+ } else{
+ $scope.gridHeight = '400px';
+ }
+ $scope.gridOptions.totalItems = widget.reportData.totalRows;
+ $scope.gridOptions.data= widget.reportData.reportDataRows;
+ $scope.gridOptions.exporterPdfHeader.text= widget.reportData.reportName;
+ }
+/* $scope.currentReportUrlParams = 'c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'&display_content=Y&r_page='+(paginationOptions.pageNumber-1);
+ console.log('raptor.htm?action=report.run.container&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1));
+ $http.get('raptor.htm?action=report.run.container&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
+ */
+ $scope.currentReportUrlParams = 'c_master='+ widget.report_id+'&'+formFieldsUrl+'&display_content=Y&r_page='+(paginationOptions.pageNumber-1);
+ $scope.urlParams = parseQueryString($scope.currentReportUrlParams);
+
+ console.log('raptor.htm?action=report.run.container&c_master='+ widget.report_id +'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1));
+ $http.get('raptor.htm?action=report.run.container&c_master='+widget.report_id+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
+ function(response){
+ widget.reportData = response.data;
+ if(widget.reportData.errormessage) {
+ document.getElementById('errorDiv').innerHTML = widget.reportData.errormessage;
+ console.log(document.getElementById('errorDiv').innerHtml);
+ console.log(widget.reportData.errormessage);
+ }
+ if(!pagination) {
+ if(!$scope.urlParams.hideChart && widget.reportData.chartAvailable && widget.reportData.totalRows>1){
+ console.log('raptor.htm?action=chart.run&c_master='+widget.report_id+'&'+formFieldsUrl+'display_content=Y&r_page='+(paginationOptions.pageNumber-1));
+ $http.get('raptor.htm?action=chart.run&c_master='+widget.report_id +'&'+formFieldsUrl+'display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
+ function(response) {
+ console.log(response.data);
+ $scope.showChart = true;
+ document.getElementById('chartiframe').contentWindow.document.write(response.data);
+ document.getElementById('chartiframe').contentWindow.document.close();
+ });
+ } else {
+ $scope.showChart = false;
+ }
+ }
+ if($scope.reportData.displayForm && $scope.reportData.formFieldList && $scope.reportData.formFieldList.length>0 && !$scope.urlParams.hideFormFields){
+ $scope.showFormFields = true;
+ } else {
+ $scope.showFormFields = false;
+ }
+ });
+ $rootScope.gridOptions = $scope.gridOptions;
+ $rootScope.gridHeight = $scope.gridHeight;
+ $rootScope.showdataContainer = true;
+ };
+
+
+
+
+
+ // set up result object
+ $scope.result = jQuery.extend(true, {}, widget);
+
+ $scope.ok = function () {
+ $uibModalInstance.close($scope.result);
+ };
+
+ $scope.okay = function () {
+ console.log("$scope.okay!")
+ console.log($scope);
+ $scope.runReport();
+/* $uibModalInstance.close($scope.result);*/
+ };
+
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss('cancel');
+ };
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-raptor-report-template.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-raptor-report-template.html
new file mode 100644
index 00000000..00d6c41a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-raptor-report-template.html
@@ -0,0 +1,26 @@
+<div>
+ <div class="modal-header">
+ <h3 class="modal-title"> Add a Raptor Report</h3>
+ </div>
+
+ <div >
+ <form name="addRaptorReportForm" class="css-form" novalidate>
+ <div style="width: 100%;">
+ <div style="width: 20%; margin-left: 50px;margin-top:28px; float: left; font-size: 15px;">Report Name: </div>
+ <div style="margin-top:20px;" class="form-field" att-select="raptorReportList" ng-model="selectedRaptorReport" placeholder="Select a Raptor Report" no-filter="true"></div>
+
+ <form action="">
+ <input name="radio" type="radio" ng-model="radioValue" att-radio="chart" title="chart" aria-label="chart radio"> chart
+ <input name="radio" type="radio" ng-model="radioValue" att-radio="data" title="data" aria-label="data radio"> data
+ </form>
+ </div>
+
+ <div class="modal-footer">
+ <a att-button btn-type="primary" ng-click="ok()">OK</a>
+ <a att-button btn-type="primary" ng-click="cancel()">Cancel</a>
+ </div>
+
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-rcloud-notebook-template.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-rcloud-notebook-template.html
new file mode 100644
index 00000000..239497c9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-rcloud-notebook-template.html
@@ -0,0 +1,22 @@
+<div>
+ <div class="modal-header">
+ <h3 class="modal-title"> Add a Raptor Report</h3>
+ </div>
+
+ <div >
+ <form name="addRaptorReportForm" class="css-form" novalidate>
+ <div style="width: 100%;">
+ <div style="margin-left: 50px;margin-top:28px; font-size: 15px;">RCloud Notebook URL: </div>
+<!-- <div style="margin-top:20px;" class="form-field" att-select="raptorReportList" ng-model="selectedRaptorReport" placeholder="Select a Raptor Report" no-filter="true"></div> -->
+ <textarea style="margin-left: 50px; width:450px; height: 150px;" ng-model="rcloud_url" name="content">
+ </textarea>
+ </div>
+ <div class="modal-footer">
+ <a att-button btn-type="primary" ng-click="ok()">OK</a>
+ <a att-button btn-type="primary" ng-click="cancel()">Cancel</a>
+ </div>
+
+ </form>
+ <br />
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/altDashboard.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/altDashboard.html
new file mode 100644
index 00000000..189bccea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/altDashboard.html
@@ -0,0 +1,49 @@
+<div>
+ <div class="btn-toolbar" ng-if="!options.hideToolbar">
+ <div class="btn-group" ng-if="!options.widgetButtons">
+ <span class="dropdown" on-toggle="toggled(open)">
+ <button type="button" class="btn btn-primary dropdown-toggle" ng-disabled="disabled">
+ Button dropdown <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" role="menu">
+ <li ng-repeat="widget in widgetDefs">
+ <a href="#" ng-click="addWidgetInternal($event, widget);" class="dropdown-toggle">{{widget.name}}</a>
+ </li>
+ </ul>
+ </span>
+ </div>
+
+ <div class="btn-group" ng-if="options.widgetButtons">
+ <button ng-repeat="widget in widgetDefs"
+ ng-click="addWidgetInternal($event, widget);" type="button" class="btn btn-primary">
+ {{widget.name}}
+ </button>
+ </div>
+
+ <button class="btn btn-warning" ng-click="resetWidgetsToDefault()">Default Widgets</button>
+
+ <button ng-if="options.storage && options.explicitSave" ng-click="options.saveDashboard()" class="btn btn-success" ng-hide="!options.unsavedChangeCount">{{ !options.unsavedChangeCount ? "Alternative - No Changes" : "Save" }}</button>
+
+ <button ng-click="clear();" ng-hide="!widgets.length" type="button" class="btn btn-info">Clear</button>
+ </div>
+
+ <div ui-sortable="sortableOptions" ng-model="widgets" class="dashboard-widget-area">
+ <div ng-repeat="widget in widgets" ng-style="widget.style" class="widget-container" widget>
+ <div class="widget panel panel-default">
+ <div class="widget-header panel-heading">
+ <h3 class="panel-title">
+ <span class="widget-title" ng-dblclick="editTitle(widget)" ng-hide="widget.editingTitle">{{widget.title}}</span>
+ <form action="" class="widget-title" ng-show="widget.editingTitle" ng-submit="saveTitleEdit(widget)">
+ <input type="text" ng-model="widget.title" class="form-control">
+ </form>
+ <span class="label label-primary" ng-if="!options.hideWidgetName">{{widget.name}}</span>
+ <span ng-click="removeWidget(widget);" class="glyphicon glyphicon-remove icon-erase" ng-if="!options.hideWidgetClose"></span>
+ <span ng-click="openWidgetSettings(widget);" class="glyphicon glyphicon-cog icon-settings" ng-if="!options.hideWidgetSettings"></span>
+ </h3>
+ </div>
+ <div class="panel-body widget-content"></div>
+ <div class="widget-ew-resizer" ng-mousedown="grabResizer($event)"></div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html
new file mode 100644
index 00000000..e891b565
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html
@@ -0,0 +1,74 @@
+
+<div>
+ <div class="btn-toolbar" ng-if="!options.hideToolbar">
+ <div class="btn-group" ng-if="!options.widgetButtons">
+
+ <span class="dropdown" on-toggle="toggled(open)">
+ <!--<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
+ Button dropdown<span class="caret"></span>
+ </button>-->
+ <ul class="dropdown-menu" role="menu">
+ <li ng-repeat="widget in widgetDefs">
+ <a href="#" ng-click="addWidgetInternal($event, widget);" class="dropdown-toggle"><span class="label label-primary">{{widget.name}}</span></a>
+ </li>
+ </ul>
+ </span>
+ </div>
+
+ <div class="btn-group" ng-if="options.widgetButtons">
+ <button ng-repeat="widget in widgetDefs"
+ ng-click="addWidgetInternal($event, widget);" type="button" class="btn btn-primary">
+ {{widget.name}}
+ </button>
+ </div>
+
+<!-- <div style="float: left" class="form-field" att-select="reports" ng-model="report1" placeholder="Select a Report"></div>
+ <button class="btn btn-primary" ng-click="addReport(report1)">Add Raptor Report</button> -->
+ <button class="btn btn-primary" ng-click="popupAddReport()">+ Raptor Report</button>
+
+<!-- <div style = "float:left"> <input ng-model = "rcloud_url"> </div>
+ <button class="btn btn-primary" ng-click="addRCloudNotebook(rcloud_url)">Add R Cloud</button> -->
+ <button class="btn btn-primary" ng-click="popupAddRCloudNotebook()">+ RCloud Notebook</button>
+
+<!-- <button class="btn btn-warning" ng-click="resetWidgetsToDefault()">Default Widgets</button> -->
+
+ <button ng-if="options.storage && options.explicitSave" ng-click="options.saveDashboard()" class="btn btn-success" ng-disabled="!options.unsavedChangeCount">{{ !options.unsavedChangeCount ? "All Saved" : "Save Changes (" + options.unsavedChangeCount + ")" }}</button>
+
+ <button ng-click="clear();" type="button" class="btn btn-info">Clear</button>
+
+<!-- <button style="float:right" ng-click="clear();" type="button" class="btn btn-info">Save to Database</button> -->
+ </div>
+
+
+<!--
+ <div id="container">
+ <div id="navi">navi</div>
+ <div id="infoi">
+ <img src="https://appharbor.com/assets/images/stackoverflow-logo.png" height="20" width="32" />infoi
+ </div>
+</div>
+ -->
+
+ <div ui-sortable="sortableOptions" ng-model="widgets" class="dashboard-widget-area">
+ <div ng-mouseover="hoverIn()" ng-mouseleave="hoverOut()" ng-repeat="widget in widgets" ng-style="widget.containerStyle" class="widget-container" widget>
+ <div class="widget panel panel-default">
+ <div style="opacity: 0.8; background-color: #E5E5E5; border: #d3d3d3;" ng-show="hoverEdit" class="widget-header panel-heading">
+ <img style="float:left; margin-right: 10px" src="static/fusion/images/att_angular_gridster/grips.png">
+ <h3 class="panel-title">
+ <span class="widget-title" ng-dblclick="editTitle(widget)" ng-hide="widget.editingTitle"></span>
+ <form action="" class="widget-title" ng-show="widget.editingTitle" ng-submit="saveTitleEdit(widget)">
+ <input type="text" ng-model="widget.title" class="form-control">
+ </form>
+ <span class="label label-primary" ng-if="!options.hideWidgetName">{{widget.name}}</span>
+ <span ng-click="removeWidget(widget);" class="glyphicon glyphicon-remove icon-erase" ng-if="!options.hideWidgetClose"></span>
+ <span ng-click="openWidgetSettings(widget);" class="glyphicon glyphicon-cog icon-settings" ng-if="!options.hideWidgetSettings"></span>
+ <span ng-click="widget.contentStyle.display = widget.contentStyle.display === 'none' ? 'block' : 'none'" class="glyphicon" ng-class="{'glyphicon-plus': widget.contentStyle.display === 'none', 'glyphicon-minus': widget.contentStyle.display !== 'none' }"></span>
+ </h3>
+ </div>
+ <div class="panel-body widget-content" ng-style="widget.contentStyle"></div>
+ <div class="widget-ew-resizer" ng-mousedown="grabResizer($event)"></div>
+ <div style="background-color:#f2f2f2" ng-if="widget.enableVerticalResize" class="widget-s-resizer" ng-mousedown="grabSouthResizer($event)"></div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.js
new file mode 100644
index 00000000..4062694e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.js
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+'use strict';
+
+angular.module('ui.dashboard', ['ui.bootstrap', 'ui.sortable']);
+
+angular.module('ui.dashboard')
+
+ .directive('dashboard', ['$http','WidgetModel', 'WidgetDefCollection', '$uibModal', 'DashboardState', '$log', function ($http, WidgetModel, WidgetDefCollection, $uibModal, DashboardState, $log) {
+
+ return {
+ restrict: 'A',
+ templateUrl: function(element, attr) {
+ return attr.templateUrl ? attr.templateUrl : 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html';
+ },
+ scope: true,
+
+ controller: ['$scope', '$attrs', function (scope, attrs) {
+ // default options
+ var defaults = {
+ stringifyStorage: true,
+ hideWidgetSettings: false,
+ hideWidgetClose: false,
+ settingsModalOptions: {
+ // templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html',
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-raptor-report-template.html',
+ // controller: 'WidgetSettingsCtrl'
+ controller: 'WidgetSettingsRaptorReportCtrl'
+ },
+ onSettingsClose: function(result, widget) { // NOTE: dashboard scope is also passed as 3rd argument
+ jQuery.extend(true, widget, result);
+ },
+ onSettingsDismiss: function(reason) { // NOTE: dashboard scope is also passed as 2nd argument
+ $log.info('widget settings were dismissed. Reason: ', reason);
+ }
+ };
+
+ scope.hoverEdit = false;
+
+ scope.hoverIn = function(){
+ this.hoverEdit = true;
+ };
+
+ scope.hoverOut = function(){
+ this.hoverEdit = false;
+ };
+
+ // from dashboard="options"
+ scope.options = scope.$eval(attrs.dashboard);
+
+ // Deep options
+ scope.options.settingsModalOptions = scope.options.settingsModalOptions || {};
+ _.each(['settingsModalOptions'], function(key) {
+ // Ensure it exists on scope.options
+ scope.options[key] = scope.options[key] || {};
+ // Set defaults
+ _.defaults(scope.options[key], defaults[key]);
+ });
+
+ // Shallow options
+ _.defaults(scope.options, defaults);
+
+ // sortable options
+ var sortableDefaults = {
+ stop: function () {
+ scope.saveDashboard();
+ },
+ handle: '.widget-header',
+ distance: 5
+ };
+ scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});
+
+ }],
+ link: function (scope) {
+
+ // Save default widget config for reset
+ scope.defaultWidgets = scope.options.defaultWidgets;
+
+ scope.widgetDefs = new WidgetDefCollection(scope.options.widgetDefinitions);
+ var count = 1;
+
+ // Instantiate new instance of dashboard state
+ scope.dashboardState = new DashboardState(
+ scope.options.storage,
+ scope.options.storageId,
+ scope.options.storageHash,
+ scope.widgetDefs,
+ scope.options.stringifyStorage
+ );
+
+ /**
+ * Instantiates a new widget on the dashboard
+ * @param {Object} widgetToInstantiate The definition object of the widget to be instantiated
+ */
+ scope.addWidget = function (widgetToInstantiate, doNotSave) {
+
+ if (typeof widgetToInstantiate === 'string') {
+ widgetToInstantiate = {
+ name: widgetToInstantiate
+ };
+ }
+
+ var defaultWidgetDefinition = scope.widgetDefs.getByName(widgetToInstantiate.name);
+ if (!defaultWidgetDefinition) {
+ throw 'Widget ' + widgetToInstantiate.name + ' is not found.';
+ }
+
+ // Determine the title for the new widget
+ var title;
+ if (!widgetToInstantiate.title && !defaultWidgetDefinition.title) {
+ widgetToInstantiate.title = 'Widget ' + count++;
+ }
+
+ // Instantiation
+ var widget = new WidgetModel(defaultWidgetDefinition, widgetToInstantiate);
+
+ // Add to the widgets array
+ scope.widgets.push(widget);
+ if (!doNotSave) {
+ scope.saveDashboard();
+ }
+
+ return widget;
+ };
+
+ /**
+ * Removes a widget instance from the dashboard
+ * @param {Object} widget The widget instance object (not a definition object)
+ */
+ scope.removeWidget = function (widget) {
+ scope.widgets.splice(_.indexOf(scope.widgets, widget), 1);
+ scope.saveDashboard();
+ };
+
+ /**
+ * Opens a dialog for setting and changing widget properties
+ * @param {Object} widget The widget instance object
+ */
+ scope.openWidgetSettings = function (widget) {
+/* console.log('======= widgets =======');
+ console.log(widget);
+ console.log('widget.report_id');
+ console.log(widget.report_id);
+*/
+ if (widget.directive.includes("raptor-report")) {
+ var getFormFieldListUrl = "raptor.htm?action=report.run.container&c_master="+widget.report_id + "&refresh=Y";
+ $http.get(getFormFieldListUrl).then(
+ function(res){
+ widget.reportData = res.data;
+ });
+
+ // Set up $uibModal options
+ var options = _.defaults(
+ { scope: scope },
+ widget.settingsModalOptions,
+ scope.options.settingsModalOptions);
+
+/* console.log('======= options =======');
+ console.log(options);
+*/
+ // Ensure widget is resolved
+ options.resolve = {
+ widget: function () {
+ return widget;
+ }
+ };
+
+ // Create the modal
+ var modalInstance = $uibModal.open(options);
+ var onClose = widget.onSettingsClose || scope.options.onSettingsClose;
+ var onDismiss = widget.onSettingsDismiss || scope.options.onSettingsDismiss;
+
+ // Set resolve and reject callbacks for the result promise
+ modalInstance.result.then(
+ function (result) {
+
+ // Call the close callback
+ onClose(result, widget, scope);
+
+ //AW Persist title change from options editor
+ scope.$emit('widgetChanged', widget);
+ },
+ function (reason) {
+
+ // Call the dismiss callback
+ onDismiss(reason, scope);
+
+ }
+ );
+
+ }
+
+ };
+
+ /**
+ * Remove all widget instances from dashboard
+ */
+ scope.clear = function (doNotSave) {
+ scope.widgets = [];
+ if (doNotSave === true) {
+ return;
+ }
+ scope.saveDashboard();
+ };
+
+ /**
+ * Used for preventing default on click event
+ * @param {Object} event A click event
+ * @param {Object} widgetDef A widget definition object
+ */
+ scope.addWidgetInternal = function (event, widgetDef) {
+// event.preventDefault();
+ scope.addWidget(widgetDef);
+ };
+
+ /**
+ * Add report to dashboard
+ */
+ scope.popupAddReport = function () {
+ var modalInstance = $uibModal.open({
+ animation: scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-raptor-report-template.html',
+ size:'sm',
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.radioValue="chart"
+ $http.get('raptor.htm?action=report.search.execute').then(
+ function(result){
+ var data = result.data;
+ var report_id_name = [];
+ for (var i in data.rows[0]) {
+ report_id_name.push({index:i, value: data.rows[0][i][1].searchresultField.displayValue, title: data.rows[0][i][2].searchresultField.displayValue})
+ }
+ $scope.raptorReportList = report_id_name;
+ });
+
+ $scope.ok = function() {
+ scope.addReport($scope.selectedRaptorReport,$scope.radioValue);
+ $uibModalInstance.close();
+ };
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }]
+ });
+ modalInstance.result.then(function () {
+ $scope.$emit('raptorReportWidgetAdded');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };
+
+
+ scope.popupAddRCloudNotebook = function () {
+ var modalInstance = $uibModal.open({
+ animation: scope.animationsEnabled,
+ templateUrl: 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/add-rcloud-notebook-template.html',
+ size:'sm',
+ controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
+ $scope.rcloud_url = ""
+
+ $scope.ok = function() {
+ scope.addRCloudNotebook($scope.rcloud_url);
+ $uibModalInstance.close();
+ };
+ $scope.cancel = function() {
+ $uibModalInstance.dismiss();
+ };
+ }]
+ });
+ modalInstance.result.then(function () {
+ $scope.$emit('raptorReportWidgetAdded');
+ }, function () {
+ $log.info('Modal dismissed at: ' + new Date());
+ });
+ };
+
+
+ scope.addReport = function (report1,radioValue) {
+ scope.report1 =report1
+ var raptor_report_type = "raptor-report-chart"
+ if (radioValue ==='data') {
+ raptor_report_type = 'raptor-report-data'
+ }
+ console.log("report1")
+ console.log(report1);
+// event.preventDefault();
+ var newreport = {"title":report1.title,"name":raptor_report_type ,"style":{},"size":{"height":"350px","width":"40%"},"attrs":{"value":"randomValue"},"report_id":report1.value};
+ scope.addWidget(newreport, true);
+ console.log("widgets");
+ console.log(scope.widgets);
+ ++scope.options.unsavedChangeCount;
+ return false;
+ };
+
+ /**
+ * Add rcloud notebook to dashboard
+ */
+ scope.addRCloudNotebook = function (rcloud_url) {
+ ++scope.options.unsavedChangeCount;
+ /* open a new prompt window */
+ //event.preventDefault();
+ var newreport = {"title":"R-Cloud","name":"r-cloud","style":{},"size":{"height":"450px","width":"40%"},"attrs":{"value":"randomValue"},"rcloud_url":rcloud_url};
+// console.log("newport");
+ console.log(newreport)
+ scope.addWidget(newreport, true);
+ /* scope.addWidget("raptor-report");*/
+ return false;
+ };
+
+ /**
+ * Uses dashboardState service to save state
+ */
+ scope.saveDashboard = function (force) {
+ if (!scope.options.explicitSave) {
+ scope.dashboardState.save(scope.widgets);
+ } else {
+ if (!angular.isNumber(scope.options.unsavedChangeCount)) {
+ scope.options.unsavedChangeCount = 0;
+ }
+ if (force) {
+ scope.options.unsavedChangeCount = 0;
+ scope.dashboardState.save(scope.widgets);
+
+ } else {
+ ++scope.options.unsavedChangeCount;
+ }
+ }
+ };
+
+ /**
+ * Wraps saveDashboard for external use.
+ */
+ scope.externalSaveDashboard = function(force) {
+ if (angular.isDefined(force)) {
+ scope.saveDashboard(force);
+ } else {
+ scope.saveDashboard(true);
+ }
+ };
+
+ /**
+ * Clears current dash and instantiates widget definitions
+ * @param {Array} widgets Array of definition objects
+ */
+ scope.loadWidgets = function (widgets) {
+ // AW dashboards are continuously saved today (no "save" button).
+ console.log("widgets")
+ scope.defaultWidgets = widgets;
+ widgets =
+ [
+// {"title":"DEMO Bar Chart","name":"raptor-report-chart","style":{},"size":{"height":"450px","width":"40%"},"attrs":{"value":"randomValue"},"report_id":"2"},
+// {"title":"Pie Chart","name":"raptor-report-data","style":{},"size":{"height":"450px","width":"40%"},"attrs":{"value":"randomValue"},"report_id":"5"},
+// {"title":"Pie Chart","name":"raptor-report-chart","style":{},"size":{"height":"450px","width":"40%"},"attrs":{"value":"randomValue"},"report_id":"5"}
+ ];
+ console.log('widgets: ');
+ console.log(JSON.stringify(widgets));
+
+ scope.savedWidgetDefs = widgets;
+ scope.clear(true);
+ _.each(widgets, function (widgetDef) {
+ scope.addWidget(widgetDef, true);
+ });
+ };
+
+ /**
+ * Resets widget instances to default config
+ * @return {[type]} [description]
+ */
+ scope.resetWidgetsToDefault = function () {
+ scope.loadWidgets(scope.defaultWidgets);
+ scope.saveDashboard();
+ };
+
+ // Set default widgets array
+ var savedWidgetDefs = scope.dashboardState.load();
+
+ // Success handler
+ function handleStateLoad(saved) {
+ scope.options.unsavedChangeCount = 0;
+ if (saved && saved.length) {
+ scope.loadWidgets(saved);
+ } else if (scope.defaultWidgets) {
+ scope.loadWidgets(scope.defaultWidgets);
+ } else {
+ scope.clear(true);
+ }
+ }
+
+ if (angular.isArray(savedWidgetDefs)) {
+ handleStateLoad(savedWidgetDefs);
+ } else if (savedWidgetDefs && angular.isObject(savedWidgetDefs) && angular.isFunction(savedWidgetDefs.then)) {
+ savedWidgetDefs.then(handleStateLoad, handleStateLoad);
+ } else {
+ handleStateLoad();
+ }
+
+ // expose functionality externally
+ // functions are appended to the provided dashboard options
+ scope.options.addWidget = scope.addWidget;
+ scope.options.loadWidgets = scope.loadWidgets;
+ scope.options.saveDashboard = scope.externalSaveDashboard;
+ scope.options.removeWidget = scope.removeWidget;
+ scope.options.openWidgetSettings = scope.openWidgetSettings;
+ scope.options.clear = scope.clear;
+ scope.options.resetWidgetsToDefault = scope.resetWidgetsToDefault
+
+ // save state
+ scope.$on('widgetChanged', function (event) {
+ event.stopPropagation();
+ scope.saveDashboard();
+ });
+ }
+ };
+ }]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.less b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.less
new file mode 100644
index 00000000..6b5b717f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.less
@@ -0,0 +1,88 @@
+.dashboard-widget-area {
+ margin: 10px 0 30px;
+ min-height: 200px;
+}
+
+.widget-container {
+ float:left;
+ display: inline-block;
+ width: 33%;
+ padding-bottom: 1em;
+}
+
+.widget {
+ margin: 0 1em 0 0;
+ background-color: white;
+ border: 2px solid #444;
+ border-radius: 5px;
+ position: relative;
+ height: 100%;
+}
+.widget-header {
+ overflow: hidden;
+}
+.widget-header .label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.widget-header .glyphicon {
+ cursor: pointer;
+ float: right;
+ opacity: 0.5;
+ margin-left: 5px;
+}
+.widget-header .glyphicon:hover {
+ opacity: 1;
+}
+.widget-header .widget-title {
+ vertical-align: middle;
+}
+.widget-header form.widget-title {
+ display: inline;
+}
+
+.widget-header form.widget-title input.form-control {
+ width: auto;
+ display: inline-block;
+}
+
+.widget-content {
+ overflow: hidden;
+}
+
+.widget .widget-ew-resizer {
+ position: absolute;
+ width: 5px;
+ right: -2px;
+ height:100%;
+ top:0;
+ cursor: ew-resize;
+}
+
+.widget .widget-s-resizer {
+ cursor: ns-resize;
+ height: 5px;
+ width: 100%;
+ bottom: -7px;
+ left: 0;
+}
+
+.widget .widget-resizer-marquee {
+ box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5);
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+}
+
+.remove-layout-icon {
+ vertical-align: text-top;
+ cursor: pointer;
+ opacity: 0.3;
+}
+.remove-layout-icon:hover {
+ opacity: 1;
+}
+.layout-title {
+ display: inline-block;
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.spec.js
new file mode 100644
index 00000000..453de431
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.spec.js
@@ -0,0 +1,878 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+describe('Directive: dashboard', function () {
+
+ var scope, element, childScope, DashboardState, mockModal, modalOptions, $compile, $q, mockLog;
+
+ // mock UI Sortable
+ beforeEach(function () {
+ angular.module('ui.sortable', []);
+ });
+
+ // load the directive's module
+ beforeEach(module('ui.dashboard', function($provide) {
+ mockModal = {
+ open: function(options) {
+ modalOptions = options;
+ }
+ };
+ mockLog = {
+ info: function() {
+
+ }
+ };
+ $provide.value('$uibModal', mockModal);
+ $provide.value('$log', mockLog);
+ }));
+
+ beforeEach(inject(function (_$compile_, $rootScope, _DashboardState_, _$q_) {
+ // services
+ scope = $rootScope.$new();
+ $compile = _$compile_;
+ DashboardState = _DashboardState_;
+ $q = _$q_;
+
+ // options
+ var widgetDefinitions = [
+ {
+ name: 'wt-one',
+ template: '<div class="wt-one-value">{{2 + 2}}</div>'
+ },
+ {
+ name: 'wt-two',
+ template: '<span class="wt-two-value">{{value}}</span>'
+ }
+ ];
+ var defaultWidgets = _.clone(widgetDefinitions);
+ scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ sortableOptions: {
+ testProperty: 'foobar'
+ }
+ };
+ scope.value = 10;
+
+ // element setup
+ element = $compile('<div dashboard="dashboardOptions"></div>')(scope);
+ scope.$digest();
+ childScope = element.scope();
+ }));
+
+ it('should have toolbar', function () {
+ var toolbar = element.find('.btn-toolbar');
+ expect(toolbar.length).toEqual(1);
+ });
+
+ it('should have UI.Sortable directive', function () {
+ var widgetArea = element.find('.dashboard-widget-area');
+ expect(widgetArea.attr('ui-sortable')).toBeDefined();
+ });
+
+ it('should render widgets', function () {
+ var widgets = element.find('.widget');
+ expect(widgets.length).toEqual(2);
+ });
+
+ it('should evaluate widget expressions', function () {
+ var divWidget = element.find('.wt-one-value');
+ expect(divWidget.html()).toEqual('4');
+ });
+
+ it('should evaluate scope expressions', function () {
+ var spanWidget = element.find('.wt-two-value');
+ expect(spanWidget.html()).toEqual('10');
+ });
+
+ it('should fill options with defaults', function() {
+ expect(scope.dashboardOptions.stringifyStorage).toEqual(true);
+ });
+
+ it('should not overwrite specified options with defaults', inject(function($compile) {
+ scope.dashboardOptions.stringifyStorage = false;
+ element = $compile('<div dashboard="dashboardOptions"></div>')(scope);
+ $compile(element)(scope);
+ scope.$digest();
+ expect(scope.dashboardOptions.stringifyStorage).toEqual(false);
+ }));
+
+ it('should be able to use a different dashboard template', inject(function($compile, $templateCache) {
+ $templateCache.put(
+ 'myCustomTemplate.html',
+ '<div>' +
+ '<div ui-sortable="sortableOptions" ng-model="widgets">' +
+ '<div ng-repeat="widget in widgets" ng-style="widget.style" class="widget-container custom-widget" widget>' +
+ '<h3 class="widget-header">' +
+ '{{widget.title}}' +
+ '<span ng-click="removeWidget(widget);" class="glyphicon glyphicon-remove icon-erase" ng-if="!options.hideWidgetClose"></span>' +
+ '<span ng-click="openWidgetSettings(widget);" class="glyphicon glyphicon-cog icon-settings" ng-if="!options.hideWidgetSettings"></span>' +
+ '</h3>' +
+ '<div class="widget-content"></div>' +
+ '<div class="widget-ew-resizer" ng-mousedown="grabResizer($event)"></div>' +
+ '</div>' +
+ '</div>' +
+ '</div>'
+ );
+ var customElement = $compile('<div dashboard="dashboardOptions" template-url="myCustomTemplate.html"></div>')(scope);
+ scope.$digest();
+ expect(customElement.find('.custom-widget').length).toEqual(2);
+ }));
+
+ it('should set scope.widgets to an empty array if no defaultWidgets are specified', inject(function($compile) {
+ delete scope.dashboardOptions.defaultWidgets;
+ var element2 = $compile('<div dashboard="dashboardOptions"></div>')(scope);
+ scope.$digest();
+ var childScope2 = element2.scope();
+ expect(childScope2.widgets instanceof Array).toEqual(true);
+ }));
+
+ it('should set options.unsavedChangeCount to 0 upon load', function() {
+ expect(scope.dashboardOptions.unsavedChangeCount).toEqual(0);
+ });
+
+ it('should not call saveDashboard on load', inject(function($compile) {
+ spyOn(DashboardState.prototype, 'save');
+ var s = scope.$new();
+ element = $compile('<div dashboard="dashboardOptions"></div>')(s);
+ scope.$digest();
+ expect(DashboardState.prototype.save).not.toHaveBeenCalled();
+ }));
+
+ describe('the sortableOptions', function() {
+
+ it('should exist', function() {
+ expect(typeof childScope.sortableOptions).toEqual('object');
+ });
+
+ it('should be possible to be extendable from the dashboardOptions', function() {
+ expect(childScope.sortableOptions.testProperty).toEqual('foobar');
+ })
+
+ it('should have a stop function that calls $scope.saveDashboard', function() {
+ expect(typeof childScope.sortableOptions.stop).toEqual('function');
+ spyOn(childScope, 'saveDashboard');
+ childScope.sortableOptions.stop();
+ expect(childScope.saveDashboard).toHaveBeenCalled();
+ });
+ });
+
+ describe('the addWidget function', function() {
+
+ var widgetCreated, widgetPassed, widgetDefault;
+
+ beforeEach(function() {
+ childScope.widgets.push = function(w) {
+ widgetCreated = w;
+ }
+ });
+
+ it('should be a function', function() {
+ expect(typeof childScope.addWidget).toEqual('function');
+ });
+
+ it('should throw if no default widgetDefinition was found', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue(false);
+ function fn () {
+ childScope.addWidget({ name: 'notReal' });
+ }
+ expect(fn).toThrow();
+ });
+
+ it('should look to the passed widgetToInstantiate object for the title before anything else', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue({ title: 'defaultTitle', name: 'A' });
+ childScope.addWidget({ title: 'highestPrecedence', name: 'A' });
+ expect(widgetCreated.title).toEqual('highestPrecedence');
+ });
+
+ it('should use the defaultWidget\'s title second', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue({ title: 'defaultTitle', name: 'A' });
+ childScope.addWidget({ name: 'A' });
+ expect(widgetCreated.title).toEqual('defaultTitle');
+ });
+
+ it('should call the saveDashboard method (internal)', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue({ title: 'defaultTitle', name: 'A' });
+ spyOn(childScope, 'saveDashboard');
+ childScope.addWidget({ name: 'A' });
+ expect(childScope.saveDashboard).toHaveBeenCalled();
+ });
+
+ it('should support passing just the widget name as a string', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue({ title: 'defaultTitle', name: 'A' });
+ childScope.addWidget('A');
+ expect(childScope.widgetDefs.getByName).toHaveBeenCalledWith('A');
+ expect(widgetCreated.title).toEqual('defaultTitle');
+ });
+
+ describe('@awashbrook Test Case', function() {
+ beforeEach(function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue(widgetDefault = {
+ "name": "nvLineChartAlpha",
+ "directive": "nvd3-line-chart",
+ "dataAttrName": "data",
+ "attrs": {
+ "isArea": true,
+ "height": 400,
+ "showXAxis": true,
+ "showYAxis": true,
+ "xAxisTickFormat": "xAxisTickFormat()",
+ "interactive": true,
+ "useInteractiveGuideline": true,
+ "tooltips": true,
+ "showLegend": true,
+ "noData": "No data for YOU!",
+ "color": "colorFunction()",
+ "forcey": "[0,2]"
+ },
+ "dataModelOptions": {
+ "params": {
+ "from": "-2h",
+ "until": "now"
+ }
+ },
+ "style": {
+ "width": "400px"
+ },
+ });
+ childScope.addWidget(widgetPassed = {
+ "title": "Andy",
+ "name": "nvLineChartAlpha",
+ "style": {
+ "width": "400px"
+ },
+ "dataModelOptions": {
+ "params": {
+ "from": "-1h",
+ "target": [
+ "randomWalk(\"random Andy 1\")",
+ "randomWalk(\"random walk 2\")",
+ "randomWalk(\"random walk 3\")"
+ ]
+ }
+ },
+ "attrs": {
+ "height": 400,
+ "showXAxis": true,
+ "showYAxis": true,
+ "xAxisTickFormat": "xAxisTickFormat()",
+ "interactive": false,
+ "useInteractiveGuideline": true,
+ "tooltips": true,
+ "showLegend": true,
+ "noData": "No data for YOU!",
+ "color": "colorFunction()",
+ "forcey": "[0,2]",
+ "data": "widgetData"
+ }
+ });
+ });
+
+ it('should keep overrides from widgetPassed', function() {
+ expect(widgetCreated.attrs.interactive).toEqual(widgetPassed.attrs.interactive);
+ });
+
+ it('should fill in default attrs', function() {
+ expect(widgetCreated.attrs.isArea).toEqual(widgetDefault.attrs.isArea);
+ });
+
+ it('should override deep options in dataModelOptions', function() {
+ expect(widgetCreated.dataModelOptions.params.from).toEqual(widgetPassed.dataModelOptions.params.from);
+ });
+
+ it('should fill in deep default attrs', function() {
+ expect(widgetCreated.dataModelOptions.params.until).toEqual(widgetDefault.dataModelOptions.params.until);
+ });
+ });
+
+ describe('the doNotSave parameter', function() {
+
+ it('should prevent save from being called if set to true', function() {
+ spyOn(childScope.widgetDefs, 'getByName').and.returnValue({ title: 'defaultTitle', name: 'A' });
+ spyOn(childScope, 'saveDashboard');
+ childScope.addWidget({ name: 'A' }, true);
+ expect(childScope.saveDashboard).not.toHaveBeenCalled();
+ });
+
+ });
+
+ });
+
+ describe('the removeWidget function', function() {
+
+ it('should be a function', function() {
+ expect(typeof childScope.removeWidget).toEqual('function');
+ });
+
+ it('should remove the provided widget from childScope.widgets array', function() {
+ var startingLength = childScope.widgets.length;
+ var expectedLength = startingLength - 1;
+
+ var widgetToRemove = childScope.widgets[0];
+ childScope.removeWidget(widgetToRemove);
+
+ expect(childScope.widgets.length).toEqual(expectedLength);
+ expect(childScope.widgets.indexOf(widgetToRemove)).toEqual(-1);
+ });
+
+ it('should call saveDashboard', function() {
+ spyOn(childScope, 'saveDashboard');
+ var widgetToRemove = childScope.widgets[0];
+ childScope.removeWidget(widgetToRemove);
+ expect(childScope.saveDashboard).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the saveDashboard function', function() {
+
+ it('should be attached to the options object after initialization', function() {
+ expect(typeof scope.dashboardOptions.saveDashboard).toEqual('function');
+ expect(scope.dashboardOptions.saveDashboard === childScope.externalSaveDashboard).toEqual(true);
+ });
+
+ it('should call scope.dashboardState.save when called internally if explicitSave is falsey', function() {
+ spyOn(childScope.dashboardState, 'save').and.returnValue(true);
+ childScope.saveDashboard();
+ expect(childScope.dashboardState.save).toHaveBeenCalled();
+ });
+
+ it('should not call scope.dashboardState.save when called internally if explicitSave is truthy', function() {
+ scope.dashboardOptions.explicitSave = true;
+ spyOn(childScope.dashboardState, 'save').and.returnValue(true);
+ childScope.saveDashboard();
+ expect(childScope.dashboardState.save).not.toHaveBeenCalled();
+ });
+
+ it('should call scope.dashboardState.save when called externally, no matter what explicitSave value is', function() {
+ spyOn(childScope.dashboardState, 'save').and.returnValue(true);
+
+ scope.dashboardOptions.explicitSave = false;
+ scope.dashboardOptions.saveDashboard();
+ expect(childScope.dashboardState.save.calls.count()).toEqual(1);
+
+ scope.dashboardOptions.explicitSave = true;
+ scope.dashboardOptions.saveDashboard();
+ expect(childScope.dashboardState.save.calls.count()).toEqual(2);
+ });
+
+ it('should keep a count of unsaved changes as unsavedChangeCount', function() {
+ scope.dashboardOptions.explicitSave = true;
+ spyOn(childScope.dashboardState, 'save').and.returnValue(true);
+ childScope.saveDashboard();
+ expect(scope.dashboardOptions.unsavedChangeCount).toEqual(1);
+ childScope.saveDashboard();
+ childScope.saveDashboard();
+ expect(scope.dashboardOptions.unsavedChangeCount).toEqual(3);
+ });
+
+ it('should reset the cound of unsaved changes if a successful force save occurs', function() {
+ scope.dashboardOptions.explicitSave = true;
+ spyOn(childScope.dashboardState, 'save').and.returnValue(true);
+
+ childScope.saveDashboard();
+ childScope.saveDashboard();
+ childScope.saveDashboard();
+
+ childScope.saveDashboard(true);
+
+ expect(scope.dashboardOptions.unsavedChangeCount).toEqual(0);
+ });
+
+ });
+
+ describe('the loadWidgets function', function() {
+
+ it('should be a function', function() {
+ expect(typeof childScope.loadWidgets).toEqual('function');
+ });
+
+ it('should set savedWidgetDefs on scope as passed array', function() {
+ var widgets = [];
+ childScope.loadWidgets(widgets);
+ expect(childScope.savedWidgetDefs === widgets).toEqual(true);
+ });
+
+ it('should call clear on the scope with true as the only argument', function() {
+ spyOn(childScope, 'clear');
+ childScope.loadWidgets([]);
+ expect(childScope.clear).toHaveBeenCalled();
+ expect(childScope.clear.calls.argsFor(0)).toEqual([true]);
+ });
+
+ it('should call addWidget for each widget in the array', function() {
+ spyOn(childScope, 'addWidget').and.returnValue(null);
+ var widgets = [{},{},{}];
+ childScope.loadWidgets(widgets);
+ expect(childScope.addWidget.calls.count()).toEqual(3);
+ });
+
+ it('should call addWidget for each widget with true as the second parameter (doNotSave)', function() {
+ spyOn(childScope, 'addWidget').and.returnValue(null);
+ var widgets = [{},{},{}];
+ childScope.loadWidgets(widgets);
+ expect(childScope.addWidget.calls.argsFor(0)).toEqual( [ widgets[0], true] );
+ expect(childScope.addWidget.calls.argsFor(1)).toEqual( [ widgets[1], true] );
+ expect(childScope.addWidget.calls.argsFor(2)).toEqual( [ widgets[2], true] );
+ });
+
+ });
+
+ describe('the clear function', function() {
+
+ it('should set the scope to an empty array', function() {
+ childScope.clear();
+ expect(childScope.widgets).toEqual([]);
+ });
+
+ it('should not call saveDashboard if first arg is true', function() {
+ spyOn(childScope, 'saveDashboard');
+ childScope.clear(true);
+ expect(childScope.saveDashboard).not.toHaveBeenCalled();
+ });
+
+ it('should call saveDashboard if first arg is not true', function() {
+ spyOn(childScope, 'saveDashboard');
+ childScope.clear();
+ expect(childScope.saveDashboard).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the openWidgetSettings function', function() {
+
+ it('should be a function', function() {
+ expect(typeof childScope.openWidgetSettings).toEqual('function');
+ });
+
+ it('should call $uibModal.open with default options', function() {
+ var widget = {};
+ spyOn(mockModal, 'open').and.returnValue({
+ result: { then: function(fn) {} }
+ });
+ childScope.openWidgetSettings(widget);
+ expect(mockModal.open).toHaveBeenCalled();
+ });
+
+ it('should have widget in the resolve object', function() {
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.resolve.widget() === widget).toEqual(true);
+ });
+
+ it('should set the templateUrl in modal options to the default ("app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html")', function() {
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.templateUrl).toEqual('app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html');
+ });
+
+ it('should set the templateUrl in modal options to scope.options.settingsModalOptions.templateUrl', function() {
+ var other;
+ scope.dashboardOptions.settingsModalOptions = {
+ templateUrl: other = 'some/other/url.html'
+ };
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.templateUrl).toEqual(other);
+ });
+
+ it('should set the templateUrl in modal options to widget.settingsModalOptions.templateUrl, if present', function() {
+ var expected;
+ var widget = {
+ settingsModalOptions: {
+ templateUrl: expected = 'specific/template.html'
+ }
+ };
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.templateUrl).toEqual(expected);
+ });
+
+ it('should set the controller in modal options to the default ("WidgetSettingsCtrl")', function() {
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.controller).toEqual('WidgetSettingsCtrl');
+ });
+
+ it('should set the controller in modal options to the default ("WidgetSettingsCtrl"), even when settingsModalOptions is supplied in options', inject(function($rootScope) {
+
+ scope = $rootScope.$new();
+
+ // options
+ var widgetDefinitions = [
+ {
+ name: 'wt-one',
+ template: '<div class="wt-one-value">{{2 + 2}}</div>'
+ },
+ {
+ name: 'wt-two',
+ template: '<span class="wt-two-value">{{value}}</span>'
+ }
+ ];
+ var defaultWidgets = _.clone(widgetDefinitions);
+ scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ sortableOptions: {
+ testProperty: 'foobar'
+ },
+ settingsModalOptions: {
+ backdrop: false
+ }
+ };
+ scope.value = 10;
+
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+
+ // element setup
+ element = $compile('<div dashboard="dashboardOptions"></div>')(scope);
+ scope.$digest();
+ childScope = element.scope();
+
+ childScope.openWidgetSettings({});
+ expect(modalOptions.controller).toEqual('WidgetSettingsCtrl');
+
+ }));
+
+ it('should set the controller in modal options to the default ("WidgetSettingsCtrl"), even when settingsModalOptions is supplied in widget', inject(function($rootScope) {
+
+ scope = $rootScope.$new();
+
+ // options
+ var widgetDefinitions = [
+ {
+ name: 'wt-one',
+ template: '<div class="wt-one-value">{{2 + 2}}</div>'
+ },
+ {
+ name: 'wt-two',
+ template: '<span class="wt-two-value">{{value}}</span>'
+ }
+ ];
+ var defaultWidgets = _.clone(widgetDefinitions);
+ scope.dashboardOptions = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultWidgets: defaultWidgets,
+ sortableOptions: {
+ testProperty: 'foobar'
+ },
+ settingsModalOptions: {
+ backdrop: false
+ }
+ };
+ scope.value = 10;
+
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+
+ // element setup
+ element = $compile('<div dashboard="dashboardOptions"></div>')(scope);
+ scope.$digest();
+ childScope = element.scope();
+
+ childScope.openWidgetSettings({
+ settingsModalOptions: {
+ templateUrl: 'custom/widget/template.html'
+ }
+ });
+ expect(modalOptions.controller).toEqual('WidgetSettingsCtrl');
+ expect(modalOptions.backdrop).toEqual(false);
+ expect(modalOptions.templateUrl).toEqual('custom/widget/template.html');
+
+ }));
+
+ it('should set the controller to scope.options.settingsModalOptions.controller if provided', function() {
+ scope.dashboardOptions.settingsModalOptions = {};
+ var expected = scope.dashboardOptions.settingsModalOptions.controller = 'MyCustomCtrl';
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.controller).toEqual(expected);
+ });
+
+ it('should set the controller to widget.settingsModalOptions.controller if provided', function() {
+ var expected;
+ var widget = {
+ settingsModalOptions: {
+ controller: expected = 'MyWidgetCtrl'
+ }
+ };
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.controller).toEqual(expected);
+ });
+
+ it('should pass in other modal options set in scope.options.settingsModalOptions', function() {
+ scope.dashboardOptions.settingsModalOptions = {
+ keyboard: false,
+ windowClass: 'my-extra-class'
+ };
+ var widget = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.keyboard).toEqual(false);
+ expect(modalOptions.windowClass).toEqual('my-extra-class');
+ });
+
+ it('should pass in other modal options set in widget.settingsModalOptions', function() {
+ scope.dashboardOptions.settingsModalOptions = {
+ keyboard: false,
+ windowClass: 'my-extra-class'
+ };
+ var widget = {
+ settingsModalOptions: {
+ keyboard: true,
+ size: 'sm'
+ }
+ };
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ childScope.openWidgetSettings(widget);
+ expect(modalOptions.keyboard).toEqual(true);
+ expect(modalOptions.size).toEqual('sm');
+ expect(modalOptions.windowClass).toEqual('my-extra-class');
+ });
+
+ it('should emit a "widgetChanged" event on the childScope when the modal promise is called', function(done) {
+ var widget = {};
+ var result = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ spyOn(childScope.options, 'onSettingsClose');
+ childScope.openWidgetSettings(widget);
+ childScope.$on('widgetChanged', done);
+ dfr.resolve(result, widget);
+ childScope.$digest();
+ });
+
+ it('should call scope.options.onSettingsClose when the modal promise is resolved by default', function() {
+ var widget = {};
+ var result = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ spyOn(childScope.options, 'onSettingsClose');
+ childScope.openWidgetSettings(widget);
+ dfr.resolve(result);
+ childScope.$digest();
+ expect(scope.dashboardOptions.onSettingsClose).toHaveBeenCalledWith(result, widget, childScope);
+ });
+
+ it('should call scope.options.onSettingsDismiss when the modal promise is rejected by default', function() {
+ var widget = {};
+ var result = {};
+ var dfr = $q.defer();
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ spyOn(childScope.options, 'onSettingsDismiss');
+ childScope.openWidgetSettings(widget);
+ dfr.reject('Testing failure');
+ childScope.$digest();
+ expect(scope.dashboardOptions.onSettingsDismiss).toHaveBeenCalledWith('Testing failure', childScope);
+ });
+
+ it('should call widget.onSettingsClose if provided when the modal promise is resolved', function() {
+ var widget = {
+ onSettingsClose: function(result, widget, scope) {
+
+ }
+ };
+ var result = {};
+ var dfr = $q.defer();
+ spyOn(widget, 'onSettingsClose');
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ spyOn(childScope.options, 'onSettingsClose');
+ childScope.openWidgetSettings(widget);
+ dfr.resolve(result);
+ childScope.$digest();
+ expect(scope.dashboardOptions.onSettingsClose).not.toHaveBeenCalled();
+ expect(widget.onSettingsClose).toHaveBeenCalledWith(result, widget, childScope);
+ });
+
+ it('should call widget.onSettingsDismiss if provided when the modal promise is rejected', function() {
+ var widget = {
+ onSettingsDismiss: function(result, widget, scope) {
+
+ }
+ };
+ var result = {};
+ var dfr = $q.defer();
+ spyOn(widget, 'onSettingsDismiss');
+ spyOn(mockModal, 'open').and.callFake(function(options) {
+ modalOptions = options;
+ return {
+ result: dfr.promise
+ };
+ });
+ spyOn(childScope.options, 'onSettingsDismiss');
+ childScope.openWidgetSettings(widget);
+ dfr.reject('Testing failure');
+ childScope.$digest();
+ expect(scope.dashboardOptions.onSettingsDismiss).not.toHaveBeenCalled();
+ expect(widget.onSettingsDismiss).toHaveBeenCalledWith('Testing failure', childScope);
+ });
+
+ });
+
+ describe('the default onSettingsClose callback', function() {
+
+ var onSettingsClose;
+
+ beforeEach(function() {
+ onSettingsClose = childScope.options.onSettingsClose;
+ });
+
+ it('should exist', function() {
+ expect(typeof onSettingsClose).toEqual('function');
+ });
+
+ it('should deep extend widget with result', function() {
+ var result = {
+ title: 'andy',
+ style: {
+ 'float': 'left'
+ }
+ };
+ var widget = {
+ title: 'scott',
+ style: {
+ width: '100px'
+ }
+ };
+ onSettingsClose(result, widget, {});
+ expect(widget).toEqual({
+ title: 'andy',
+ style: {
+ width: '100px',
+ 'float': 'left'
+ }
+ });
+ });
+
+ });
+
+ describe('the default onSettingsDismiss callback', function() {
+
+ var onSettingsDismiss;
+
+ beforeEach(function() {
+ onSettingsDismiss = childScope.options.onSettingsDismiss;
+ });
+
+ it('should exist', function() {
+ expect(typeof onSettingsDismiss).toEqual('function');
+ });
+
+ it('should call $log.info with the reason', function() {
+ spyOn(mockLog, 'info');
+ onSettingsDismiss('dismiss reason');
+ expect(mockLog.info).toHaveBeenCalled();
+ });
+
+ });
+
+});
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-raptor-report-template.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-raptor-report-template.html
new file mode 100644
index 00000000..7a533c3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-raptor-report-template.html
@@ -0,0 +1,58 @@
+<div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
+ <h3>Widget Options <small>{{widget.title}}</small></h3>
+</div>
+
+<div class="modal-body">
+ <form name="form" novalidate class="form-horizontal">
+<!-- <div class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">Title</label>
+ <div style="margin-left:120px" class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="result.title">
+ </div>
+ </div> -->
+
+<!-- <div>{{showFormFieldIds}}</div>
+<div>{{formFieldSelectedValues}}</div>
+<div>{{JSON.strigify(widget.reportData.formFieldList)}}</div>
+ -->
+<form ng-show="true" class="row section-row" style="margin: 10px">
+ <form-builder ng-form-fields="reportData.formFieldList" ng-show-field-id="showFormFieldIds" ng-num-form-cols="reportData.numFormCols" ng-model="formFieldSelectedValues" ng-trigger-method="triggerOtherFormFields"></form-builder>
+</form>
+
+<!-- <div ng-repeat="formfield in widget.reportData.formFieldList">
+ <div class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">{{formfield.fieldDisplayName}}:</label>
+ <div style="margin-left:120px" class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="formfield.title">
+ </div>
+ </div>
+ </div> -->
+<!-- <div ng-repeat="(formfield_key,formfield_value) in widget.reportData.formFieldList[0]" class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">{{formfield_key}}</label>
+ <div style="margin-left:120px" class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="formfield_value">
+ </div>
+ </div> -->
+
+
+ <div ng-if="widget.settingsModalOptions.partialTemplateUrl"
+ ng-include="widget.settingsModalOptions.partialTemplateUrl"></div>
+
+<!--
+ <div ng-show="true" id="grid1" ui-grid="gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-resize-columns class="grid" style="height: {{gridHeight}}">
+ <div class="no-rows" ng-show="!gridOptions.data.length">
+ <div class="msg">
+ <span>{{widget.reportData.message}}</span>
+ </div>
+ </div>
+ </div>
+ -->
+ </form>
+
+</div>
+
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html
new file mode 100644
index 00000000..a57d4366
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/widget-settings-template.html
@@ -0,0 +1,22 @@
+<div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
+ <h3>Widget Options <small>{{widget.title}}</small></h3>
+</div>
+
+<div class="modal-body">
+ <form name="form" novalidate class="form-horizontal">
+ <div class="form-group">
+ <label for="widgetTitle" class="col-sm-2 control-label">Title</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" name="widgetTitle" ng-model="result.title">
+ </div>
+ </div>
+ <div ng-if="widget.settingsModalOptions.partialTemplateUrl"
+ ng-include="widget.settingsModalOptions.partialTemplateUrl"></div>
+ </form>
+</div>
+
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">Cancel</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModal.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModal.html
new file mode 100644
index 00000000..f9f6f361
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModal.html
@@ -0,0 +1,13 @@
+<div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">&times;</button>
+ <h3>Unsaved Changes to "{{layout.title}}"</h3>
+</div>
+
+<div class="modal-body">
+ <p>You have {{layout.dashboard.unsavedChangeCount}} unsaved changes on this dashboard. Would you like to save them?</p>
+</div>
+
+<div class="modal-footer">
+ <button type="button" class="btn btn-default" ng-click="cancel()">Don't Save</button>
+ <button type="button" class="btn btn-primary" ng-click="ok()">Save</button>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModalCtrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModalCtrl.js
new file mode 100644
index 00000000..252f9df4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModalCtrl.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .controller('SaveChangesModalCtrl', ['$scope', '$uibModalInstance', 'layout', function ($scope, $uibModalInstance, layout) {
+
+ // add layout to scope
+ $scope.layout = layout;
+
+ $scope.ok = function () {
+ $uibModalInstance.close();
+ };
+
+ $scope.cancel = function () {
+ $uibModalInstance.dismiss();
+ };
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.html
new file mode 100644
index 00000000..54aef297
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.html
@@ -0,0 +1,19 @@
+<ul ui-sortable="sortableOptions" ng-model="layouts" class="nav nav-tabs layout-tabs">
+ <li ng-repeat="layout in layouts" ng-class="{ active: layout.active }">
+ <a ng-click="makeLayoutActive(layout)">
+ <span ng-dblclick="editTitle(layout)" ng-show="!layout.editingTitle">{{layout.title}}</span>
+ <form action="" class="layout-title" ng-show="layout.editingTitle" ng-submit="saveTitleEdit(layout)">
+ <input type="text" ng-model="layout.title" class="form-control" data-layout="{{layout.id}}">
+ </form>
+ <span ng-if="!layout.locked" ng-click="removeLayout(layout)" class="glyphicon glyphicon-remove icon-erase remove-layout-icon"></span>
+ <!-- <span class="glyphicon glyphicon-pencil"></span> -->
+ <!-- <span class="glyphicon glyphicon-remove"></span> -->
+ </a>
+ </li>
+ <li>
+ <a ng-click="createNewLayout()">
+ <span class="glyphicon glyphicon-plus"></span>
+ </a>
+ </li>
+</ul>
+<div ng-repeat="layout in layouts | filter:isActive" dashboard="layout.dashboard" template-url="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.html"></div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.js
new file mode 100644
index 00000000..bbf107a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.js
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .directive('dashboardLayouts', ['LayoutStorage', '$timeout', '$uibModal',
+ function(LayoutStorage, $timeout, $uibModal) {
+ return {
+ scope: true,
+ templateUrl: function(element, attr) {
+ return attr.templateUrl ? attr.templateUrl : 'app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.html';
+ },
+ link: function(scope, element, attrs) {
+
+ scope.options = scope.$eval(attrs.dashboardLayouts);
+
+ var layoutStorage = new LayoutStorage(scope.options);
+
+ scope.layouts = layoutStorage.layouts;
+
+ scope.createNewLayout = function() {
+ var newLayout = {
+ title: 'Custom',
+ defaultWidgets: scope.options.defaultWidgets || []
+ };
+ layoutStorage.add(newLayout);
+ scope.makeLayoutActive(newLayout);
+ layoutStorage.save();
+ return newLayout;
+ };
+
+ scope.removeLayout = function(layout) {
+ layoutStorage.remove(layout);
+ layoutStorage.save();
+ };
+
+ scope.makeLayoutActive = function(layout) {
+
+ var current = layoutStorage.getActiveLayout();
+
+ if (current && current.dashboard.unsavedChangeCount) {
+ var modalInstance = $uibModal.open({
+ templateUrl: 'template/SaveChangesModal.html',
+ resolve: {
+ layout: function() {
+ return layout;
+ }
+ },
+ controller: 'SaveChangesModalCtrl'
+ });
+
+ // Set resolve and reject callbacks for the result promise
+ modalInstance.result.then(
+ function() {
+ current.dashboard.saveDashboard();
+ scope._makeLayoutActive(layout);
+ },
+ function() {
+ scope._makeLayoutActive(layout);
+ }
+ );
+ } else {
+ scope._makeLayoutActive(layout);
+ }
+
+ };
+
+ scope._makeLayoutActive = function(layout) {
+ angular.forEach(scope.layouts, function(l) {
+ if (l !== layout) {
+ l.active = false;
+ } else {
+ l.active = true;
+ }
+ });
+ layoutStorage.save();
+ };
+
+ scope.isActive = function(layout) {
+ return !!layout.active;
+ };
+
+ scope.editTitle = function(layout) {
+ if (layout.locked) {
+ return;
+ }
+
+ var input = element.find('input[data-layout="' + layout.id + '"]');
+ layout.editingTitle = true;
+
+ $timeout(function() {
+ input.focus()[0].setSelectionRange(0, 9999);
+ });
+ };
+
+ // saves whatever is in the title input as the new title
+ scope.saveTitleEdit = function(layout) {
+ layout.editingTitle = false;
+ layoutStorage.save();
+ };
+
+ scope.options.saveLayouts = function() {
+ layoutStorage.save(true);
+ };
+ scope.options.addWidget = function() {
+ var layout = layoutStorage.getActiveLayout();
+ if (layout) {
+ layout.dashboard.addWidget.apply(layout.dashboard, arguments);
+ }
+ };
+ scope.options.loadWidgets = function() {
+ var layout = layoutStorage.getActiveLayout();
+ if (layout) {
+ layout.dashboard.loadWidgets.apply(layout.dashboard, arguments);
+ }
+ };
+ scope.options.saveDashboard = function() {
+ console.log("================= saveDashboard called =================")
+ var layout = layoutStorage.getActiveLayout();
+ console.log("===================== layout ===========================");
+ console.log(layout);
+ if (layout) {
+ layout.dashboard.saveDashboard.apply(layout.dashboard, arguments);
+ }
+ };
+
+ var sortableDefaults = {
+ stop: function() {
+ scope.options.saveLayouts();
+ },
+ distance: 5
+ };
+ scope.sortableOptions = angular.extend({}, sortableDefaults, scope.options.sortableOptions || {});
+ }
+ };
+ }
+ ]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.spec.js
new file mode 100644
index 00000000..8533a211
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.spec.js
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+describe('Directive: dashboard-layouts', function () {
+
+ var $rootScope, element, options, childScope, DashboardState, LayoutStorage, $mockModal, $mockTimeout, toFn;
+
+ // mock UI Sortable
+ beforeEach(function () {
+ angular.module('ui.sortable', []);
+ });
+
+ // load the directive's module
+ beforeEach(module('ui.dashboard', function($provide) {
+ $mockModal = {
+ open: function() {}
+ };
+ $mockTimeout = function(fn, delay) {
+ toFn = fn;
+ };
+ $provide.value('$uibModal', $mockModal);
+ $provide.value('$timeout', $mockTimeout);
+ }));
+
+ beforeEach(inject(function ($compile, _$rootScope_, _DashboardState_, _LayoutStorage_) {
+ // services
+ $rootScope = _$rootScope_;
+ DashboardState = _DashboardState_;
+ LayoutStorage = _LayoutStorage_;
+
+ // options
+ var widgetDefinitions = [
+ {
+ name: 'wt-one',
+ template: '<div class="wt-one-value">{{2 + 2}}</div>'
+ },
+ {
+ name: 'wt-two',
+ template: '<span class="wt-two-value">{{value}}</span>'
+ }
+ ];
+ var defaultWidgets = _.clone(widgetDefinitions);
+ $rootScope.dashboardOptions = options = {
+ widgetButtons: true,
+ widgetDefinitions: widgetDefinitions,
+ defaultLayouts: [
+ {
+ title: 'first',
+ active: true,
+ defaultWidgets: defaultWidgets
+ },
+ {
+ title: 'second',
+ active: false,
+ defaultWidgets: defaultWidgets
+ }
+ ],
+ defaultWidgets: defaultWidgets,
+ storage: {
+ setItem: function(key, val) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ }
+ };
+ $rootScope.value = 10;
+
+ // element setup
+ element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
+ $rootScope.$digest();
+ childScope = element.scope();
+ }));
+
+ it('should not require storage', inject(function($compile) {
+ delete $rootScope.dashboardOptions.storage;
+ expect(function() {
+ var noStorageEl = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
+ $rootScope.$digest();
+ }).not.toThrow();
+
+ }));
+
+ it('should be able to use a different dashboard-layouts template', inject(function($compile, $templateCache) {
+ $templateCache.put(
+ 'myCustomTemplate.html',
+ '<ul class="my-custom-tabs layout-tabs">' +
+ '<li ng-repeat="layout in layouts" ng-class="{ active: layout.active }">' +
+ '<a ng-click="makeLayoutActive(layout)">' +
+ '<span ng-dblclick="editTitle(layout)" ng-show="!layout.editingTitle">{{layout.title}}</span>' +
+ '<form action="" class="layout-title" ng-show="layout.editingTitle" ng-submit="saveTitleEdit(layout)">' +
+ '<input type="text" ng-model="layout.title" class="form-control" data-layout="{{layout.id}}">' +
+ '</form>' +
+ '<span ng-click="removeLayout(layout)" class="glyphicon glyphicon-remove icon-erase"></span>' +
+ '<!-- <span class="glyphicon glyphicon-pencil"></span> -->' +
+ '<!-- <span class="glyphicon glyphicon-remove"></span> -->' +
+ '</a>' +
+ '</li>' +
+ '<li>' +
+ '<a ng-click="createNewLayout()">' +
+ '<span class="glyphicon glyphicon-plus"></span>' +
+ '</a>' +
+ '</li>' +
+ '</ul>' +
+ '<div ng-repeat="layout in layouts | filter:isActive" dashboard="layout.dashboard" templateUrl="template/dashboard.html"></div>'
+ );
+ var customElement = $compile('<div dashboard-layouts="dashboardOptions" template-url="myCustomTemplate.html"></div>')($rootScope);
+ $rootScope.$digest();
+ expect(customElement.find('ul.my-custom-tabs').length).toEqual(1);
+
+ }));
+
+ it('should set the first dashboard to active if there is not one already active', inject(function($compile) {
+ options.defaultLayouts[0].active = options.defaultLayouts[1].active = false;
+ element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
+ $rootScope.$digest();
+ childScope = element.scope();
+
+ var layouts = childScope.layouts;
+ var active;
+ for (var i = 0; i < layouts.length; i++) {
+ if (layouts[i].active) {
+ active = layouts[i];
+ break;
+ }
+ };
+ expect(active).not.toBeUndefined();
+ }));
+
+ describe('the createNewLayout method', function() {
+
+ it('should call the add and save methods of LayoutStorage', function() {
+ spyOn(LayoutStorage.prototype, 'add');
+ spyOn(LayoutStorage.prototype, 'save');
+
+ childScope.createNewLayout();
+ expect(LayoutStorage.prototype.add).toHaveBeenCalled();
+ expect(LayoutStorage.prototype.save).toHaveBeenCalled();
+ });
+
+ it('should return the newly created layout object', function() {
+ var result = childScope.createNewLayout();
+ expect(typeof result).toEqual('object');
+ });
+
+ it('should set active=true on the newly created layout', function() {
+ var result = childScope.createNewLayout();
+ expect(result.active).toEqual(true);
+ });
+
+ it('should set defaultWidgets to dashboardOptions.defaultWidgets if it is present', function() {
+ var result = childScope.createNewLayout();
+ expect(result.defaultWidgets === options.defaultWidgets).toEqual(true);
+ });
+
+ it('should set defaultWidgets to an empty array if dashboardOptions.defaultWidgets is not present', inject(function($compile) {
+ delete options.defaultWidgets;
+ element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
+ $rootScope.$digest();
+ childScope = element.scope();
+ var result = childScope.createNewLayout();
+ expect(result.defaultWidgets).toEqual([]);
+ }));
+
+ });
+
+ describe('the removeLayout method', function() {
+
+ it('should call the remove and save methods of LayoutStorage', function() {
+ spyOn(LayoutStorage.prototype, 'remove');
+ spyOn(LayoutStorage.prototype, 'save');
+
+ childScope.removeLayout(childScope.layouts[0]);
+ expect(LayoutStorage.prototype.remove).toHaveBeenCalled();
+ expect(LayoutStorage.prototype.save).toHaveBeenCalled();
+ });
+
+ it('should call remove with the layout it was passed', function() {
+ spyOn(LayoutStorage.prototype, 'remove');
+ var layout = childScope.layouts[0];
+ childScope.removeLayout(layout);
+ expect(LayoutStorage.prototype.remove.calls.argsFor(0)[0]).toEqual(layout);
+ });
+
+ });
+
+ describe('the makeLayoutActive method', function() {
+
+ it('should call _makeLayoutActive if there is not a currently active dashboard with unsaved changes', function() {
+ spyOn(childScope, '_makeLayoutActive');
+ var layout = childScope.layouts[1];
+ childScope.makeLayoutActive(layout);
+ expect(childScope._makeLayoutActive).toHaveBeenCalled();
+ });
+
+ describe('when there are unsaved changes on the current dashboard', function() {
+
+ var current, options, successCb, errorCb, layout;
+
+ beforeEach(function() {
+ current = childScope.layouts[0];
+ current.dashboard.unsavedChangeCount = 1;
+
+ spyOn($mockModal, 'open').and.callFake(function(arg) {
+ options = arg;
+ return {
+ result: {
+ then: function(success, error) {
+ successCb = success;
+ errorCb = error;
+ }
+ }
+ }
+ });
+
+ layout = childScope.layouts[1];
+ childScope.makeLayoutActive(layout);
+ });
+
+ it('should create a modal', function() {
+ expect($mockModal.open).toHaveBeenCalled();
+ });
+
+ it('should resolve layout to the layout to be made active', function() {
+ expect(options.resolve.layout()).toEqual(layout);
+ });
+
+ it('should provide a success callback that saves the current dashboard and then calls _makeLayoutActive', function() {
+ spyOn(current.dashboard, 'saveDashboard');
+ spyOn(childScope, '_makeLayoutActive');
+ successCb();
+ expect(current.dashboard.saveDashboard).toHaveBeenCalled();
+ expect(childScope._makeLayoutActive).toHaveBeenCalled();
+ expect(childScope._makeLayoutActive.calls.argsFor(0)[0]).toEqual(layout);
+ });
+
+ it('should provide an error callback that only calls _makeLayoutActive', function() {
+ spyOn(current.dashboard, 'saveDashboard');
+ spyOn(childScope, '_makeLayoutActive');
+ errorCb();
+ expect(current.dashboard.saveDashboard).not.toHaveBeenCalled();
+ expect(childScope._makeLayoutActive).toHaveBeenCalled();
+ expect(childScope._makeLayoutActive.calls.argsFor(0)[0]).toEqual(layout);
+ });
+
+ });
+
+ });
+
+ describe('the editTitle method', function() {
+
+ it('should set the editingTitle attribute to true on the layout it is passed', function() {
+ var layout = { id: '1' };
+ childScope.editTitle(layout);
+ $rootScope.$digest();
+ expect(layout.editingTitle).toEqual(true);
+ toFn();
+ });
+
+ });
+
+ describe('the saveTitleEdit method', function() {
+
+ it('should set editingTitle to false', function() {
+ var layout = { id: '1' };
+ childScope.saveTitleEdit(layout);
+ expect(layout.editingTitle).toEqual(false);
+ });
+
+ it('should call layoutStorage.save', function() {
+ var layout = { id: '1' };
+ spyOn(LayoutStorage.prototype, 'save').and.callThrough();
+ childScope.saveTitleEdit(layout);
+ expect(LayoutStorage.prototype.save).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the saveLayouts method', function() {
+
+ it('should call LayoutStorage.save', function() {
+ spyOn(LayoutStorage.prototype, 'save').and.callThrough();
+ $rootScope.dashboardOptions.saveLayouts();
+ expect(LayoutStorage.prototype.save).toHaveBeenCalled();
+ });
+
+ it('should call LayoutStorage.save with true as the first arg', function() {
+ spyOn(LayoutStorage.prototype, 'save').and.callThrough();
+ $rootScope.dashboardOptions.saveLayouts();
+ expect(LayoutStorage.prototype.save.calls.argsFor(0)[0]).toEqual(true);
+ });
+
+ });
+ describe('the proxy methods to active layout', function() {
+
+ var mockDash, galSpy;
+
+ beforeEach(function() {
+ mockDash = {
+ active: true,
+ dashboard: {
+ addWidget: function() {},
+ loadWidgets: function() {},
+ saveDashboard: function() {}
+ }
+ };
+ spyOn(mockDash.dashboard, 'addWidget');
+ spyOn(mockDash.dashboard, 'loadWidgets');
+ spyOn(mockDash.dashboard, 'saveDashboard');
+ galSpy = spyOn(LayoutStorage.prototype, 'getActiveLayout').and;
+ galSpy.returnValue(mockDash);
+ });
+
+ describe('the addWidget method', function() {
+
+ it('should call dashboard.addWidget method of the active layout', function() {
+ options.addWidget(1,2,3);
+ expect(mockDash.dashboard.addWidget).toHaveBeenCalled();
+ var firstCall = mockDash.dashboard.addWidget.calls.first();
+ expect(firstCall.object).toEqual(mockDash.dashboard);
+ expect(firstCall.args).toEqual([1,2,3]);
+ });
+
+ it('should do nothing if there is no active layout', function() {
+ galSpy.returnValue(null);
+ expect(function() {
+ options.addWidget();
+ }).not.toThrow();
+ });
+
+ });
+
+ describe('the loadWidgets method', function() {
+
+ it('should call dashboard.loadWidgets of the current layout', function() {
+ options.loadWidgets(1,2,3);
+ expect(mockDash.dashboard.loadWidgets).toHaveBeenCalled();
+ var firstCall = mockDash.dashboard.loadWidgets.calls.first();
+ expect(firstCall.object).toEqual(mockDash.dashboard);
+ expect(firstCall.args).toEqual([1,2,3]);
+ });
+
+ it('should do nothing if there is no active layout', function() {
+ galSpy.returnValue(null);
+ expect(function() {
+ options.loadWidgets();
+ }).not.toThrow();
+ });
+
+ });
+
+ describe('the saveDashboard method', function() {
+
+ it('should call dashboard.saveDashboard of the current layout', function() {
+ options.saveDashboard(1,2,3);
+ expect(mockDash.dashboard.saveDashboard).toHaveBeenCalled();
+ var firstCall = mockDash.dashboard.saveDashboard.calls.first();
+ expect(firstCall.object).toEqual(mockDash.dashboard);
+ expect(firstCall.args).toEqual([1,2,3]);
+ });
+
+ it('should do nothing if there is no active layout', function() {
+ galSpy.returnValue(null);
+ expect(function() {
+ options.saveDashboard();
+ }).not.toThrow();
+ });
+
+ });
+
+ });
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.js
new file mode 100644
index 00000000..9ac57b19
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.js
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .controller('DashboardWidgetCtrl', ['$scope', '$element', '$compile', '$window', '$timeout',
+ function($scope, $element, $compile, $window, $timeout) {
+
+ $scope.status = {
+ isopen: false
+ };
+
+ // Fills "container" with compiled view
+ $scope.makeTemplateString = function() {
+
+ var widget = $scope.widget;
+
+ // First, build template string
+ var templateString = '';
+
+ if (widget.templateUrl) {
+
+ // Use ng-include for templateUrl
+ templateString = '<div ng-include="\'' + widget.templateUrl + '\'"></div>';
+
+ } else if (widget.template) {
+
+ // Direct string template
+ templateString = widget.template;
+
+ } else {
+
+ // Assume attribute directive
+ templateString = '<div ' + widget.directive;
+
+ // Check if data attribute was specified
+ if (widget.dataAttrName) {
+ widget.attrs = widget.attrs || {};
+ widget.attrs[widget.dataAttrName] = 'widgetData';
+ }
+
+ // Check for specified attributes
+ if (widget.attrs) {
+
+ // First check directive name attr
+ if (widget.attrs[widget.directive]) {
+ templateString += '="' + widget.attrs[widget.directive] + '"';
+ }
+
+ // Add attributes
+ _.each(widget.attrs, function(value, attr) {
+
+ // make sure we aren't reusing directive attr
+ if (attr !== widget.directive) {
+ templateString += ' ' + attr + '="' + value + '"';
+ }
+
+ });
+ }
+ templateString += '></div>';
+ }
+ return templateString;
+ };
+
+ $scope.grabResizer = function(e) {
+
+ var widget = $scope.widget;
+ var widgetElm = $element.find('.widget');
+
+ // ignore middle- and right-click
+ if (e.which !== 1) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.originalEvent.preventDefault();
+
+ // get the starting horizontal position
+ var initX = e.clientX;
+ // console.log('initX', initX);
+
+ // Get the current width of the widget and dashboard
+ var pixelWidth = widgetElm.width();
+ var pixelHeight = widgetElm.height();
+ var widgetStyleWidth = widget.containerStyle.width;
+ var widthUnits = widget.widthUnits;
+ var unitWidth = parseFloat(widgetStyleWidth);
+
+ // create marquee element for resize action
+ var $marquee = angular.element('<div class="widget-resizer-marquee" style="height: ' + pixelHeight + 'px; width: ' + pixelWidth + 'px; z-index:'+ 200 +';"></div>');
+ widgetElm.append($marquee);
+ // create an overlaying div to block other widgets in order to stop their iframe events from being triggered
+ var $marquee2 = angular.element('<div style=" position: absolute; top: 0; left: 0; height: ' + pixelHeight + 'px; width: ' + (pixelWidth+200) + 'px; z-index:'+ 100 +';"></div>');
+ widgetElm.append($marquee2);
+
+ // determine the unit/pixel ratio
+ var transformMultiplier = unitWidth / pixelWidth;
+
+ // updates marquee with preview of new width
+ var mousemove = function(e) {
+ var curX = e.clientX;
+// console.log(curX);
+// console.log(e);
+ var pixelChange = curX - initX;
+ var newWidth = pixelWidth + pixelChange;
+ $marquee.css('width', newWidth + 'px');
+ $marquee2.css('width', (newWidth + 200) + 'px');
+
+ };
+
+ // sets new widget width on mouseup
+ var mouseup = function(e) {
+ // remove listener and marquee
+ jQuery($window).off('mousemove', mousemove);
+ $marquee.remove();
+ $marquee2.remove();
+
+ // calculate change in units
+ var curX = e.clientX;
+ var pixelChange = curX - initX;
+ var unitChange = Math.round(pixelChange * transformMultiplier * 100) / 100;
+
+ // add to initial unit width
+ var newWidth = unitWidth * 1 + unitChange;
+ widget.setWidth(newWidth, widthUnits);
+ $scope.$emit('widgetChanged', widget);
+ $scope.$apply();
+ $scope.$broadcast('widgetResized', {
+ width: newWidth
+ });
+ };
+
+// jQuery($window).on('mousemove', mousemove).one('mouseup', mouseup);
+ jQuery($window).on('mousemove', mousemove).one('mouseup', mouseup);
+ };
+
+ //TODO refactor
+ $scope.grabSouthResizer = function(e) {
+ var widgetElm = $element.find('.widget');
+
+ // ignore middle- and right-click
+ if (e.which !== 1) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.originalEvent.preventDefault();
+
+ // get the starting horizontal position
+ var initY = e.clientY;
+ // console.log('initX', initX);
+
+ // Get the current width of the widget and dashboard
+ var pixelWidth = widgetElm.width();
+ var pixelHeight = widgetElm.height();
+
+ // create marquee element for resize action
+ var $marquee = angular.element('<div class="widget-resizer-marquee" style="height: ' + pixelHeight + 'px; width: ' + pixelWidth + 'px;"></div>');
+ widgetElm.append($marquee);
+
+ // updates marquee with preview of new height
+ var mousemove = function(e) {
+ var curY = e.clientY;
+ var pixelChange = curY - initY;
+ var newHeight = pixelHeight + pixelChange;
+ $marquee.css('height', newHeight + 'px');
+ };
+
+ // sets new widget width on mouseup
+ var mouseup = function(e) {
+ // remove listener and marquee
+ jQuery($window).off('mousemove', mousemove);
+ $marquee.remove();
+
+ // calculate height change
+ var curY = e.clientY;
+ var pixelChange = curY - initY;
+
+ //var widgetContainer = widgetElm.parent(); // widget container responsible for holding widget width and height
+ var widgetContainer = widgetElm.find('.widget-content');
+
+ var diff = pixelChange;
+ var height = parseInt(widgetContainer.css('height'), 10);
+ var newHeight = (height + diff);
+
+ //$scope.widget.style.height = newHeight + 'px';
+
+ $scope.widget.setHeight(newHeight + 'px');
+
+ $scope.$emit('widgetChanged', $scope.widget);
+ $scope.$apply(); // make AngularJS to apply style changes
+
+ $scope.$broadcast('widgetResized', {
+ height: newHeight
+ });
+ };
+
+ jQuery($window).on('mousemove', mousemove).one('mouseup', mouseup);
+ };
+
+ // replaces widget title with input
+ $scope.editTitle = function(widget) {
+ var widgetElm = $element.find('.widget');
+ widget.editingTitle = true;
+ // HACK: get the input to focus after being displayed.
+ $timeout(function() {
+ widgetElm.find('form.widget-title input:eq(0)').focus()[0].setSelectionRange(0, 9999);
+ });
+ };
+
+ // saves whatever is in the title input as the new title
+ $scope.saveTitleEdit = function(widget) {
+ widget.editingTitle = false;
+ $scope.$emit('widgetChanged', widget);
+ };
+
+ $scope.compileTemplate = function() {
+ var container = $scope.findWidgetContainer($element);
+ var templateString = $scope.makeTemplateString();
+ var widgetElement = angular.element(templateString);
+
+ container.empty();
+ container.append(widgetElement);
+ $compile(widgetElement)($scope);
+ };
+
+ $scope.findWidgetContainer = function(element) {
+ // widget placeholder is the first (and only) child of .widget-content
+ return element.find('.widget-content');
+ };
+ }
+ ]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.spec.js
new file mode 100644
index 00000000..55604646
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.spec.js
@@ -0,0 +1,164 @@
+'use strict';
+
+describe('Controller: DashboardWidgetCtrl', function() {
+
+ var $scope, $element, $timeout, injections;
+
+ beforeEach(module('ui.dashboard'));
+
+ beforeEach(inject(function($rootScope, $controller){
+ $scope = $rootScope.$new();
+ $element = angular.element('<div><div class="widget"></div></div>');
+ $timeout = function timeout(fn) {
+ fn();
+ };
+ injections = {
+ $scope: $scope,
+ $element: $element,
+ $timeout: $timeout
+ };
+ spyOn(injections, '$timeout');
+ $controller('DashboardWidgetCtrl', injections);
+ }));
+
+ describe('the makeTemplateString method', function() {
+
+ it('should return a string', function() {
+ $scope.widget = {
+ templateUrl: 'some/template.html'
+ };
+ expect(typeof $scope.makeTemplateString()).toEqual('string');
+ });
+
+ it('should use ng-include if templateUrl is specified on widget, despite any other options', function() {
+ $scope.widget = {
+ templateUrl: 'some/template.html',
+ template: 'not this one',
+ directive: 'or-this',
+ attrs: {
+ something: 'awesome',
+ other: 'thing'
+ }
+ };
+ expect($scope.makeTemplateString()).toMatch(/ng-include="'some\/template\.html'"/);
+ });
+
+ it('should return widget.template if specified, regardless of presence of directive or attrs', function() {
+ $scope.widget = {
+ template: '<div class="testing"></div>',
+ directive: 'no-good'
+ };
+ expect($scope.makeTemplateString()).toEqual($scope.widget.template);
+ });
+
+ it('should use widget.directive as attribute directive', function() {
+ $scope.widget = {
+ directive: 'ng-awesome'
+ };
+ expect($scope.makeTemplateString()).toEqual('<div ng-awesome></div>');
+ });
+
+ it('should attach attributes if provided', function() {
+ $scope.widget = {
+ directive: 'ng-awesome',
+ attrs: {
+ 'ng-awesome': 'test1',
+ other: 'attr',
+ more: 'stuff'
+ }
+ };
+ expect($scope.makeTemplateString()).toEqual('<div ng-awesome="test1" other="attr" more="stuff"></div>');
+ });
+
+ it('should place widgetData into dataAttrName attribute if specified', function() {
+ $scope.widget = {
+ directive: 'ng-awesome',
+ attrs: {
+ 'ng-awesome': 'test1',
+ other: 'attr',
+ more: 'stuff'
+ },
+ dataAttrName: 'data'
+ };
+ expect($scope.makeTemplateString()).toEqual('<div ng-awesome="test1" other="attr" more="stuff" data="widgetData"></div>');
+ });
+
+ it('should add attrs to the widget object if it does not exist and dataAttrName is specified', function() {
+ $scope.widget = {
+ directive: 'ng-awesome',
+ dataAttrName: 'data'
+ };
+ expect($scope.makeTemplateString()).toEqual('<div ng-awesome data="widgetData"></div>');
+ });
+
+ });
+
+ describe('the grabResizer method', function() {
+
+ var evt, widget, WidgetModel;
+
+ beforeEach(inject(function (_WidgetModel_) {
+ WidgetModel = _WidgetModel_;
+ }));
+
+ beforeEach(function() {
+ evt = {
+ stopPropagation: jasmine.createSpy('stopPropagation'),
+ originalEvent: {
+ preventDefault: jasmine.createSpy('preventDefault')
+ },
+ clientX: 100,
+ which: 1
+ };
+ $scope.widget = widget = new WidgetModel({
+ style: {
+ width: '30%'
+ }
+ });
+ });
+
+ it('should do nothing if event.which is not 1 (left click)', function() {
+ evt.which = 2;
+ $scope.grabResizer(evt);
+ expect(evt.stopPropagation).not.toHaveBeenCalled();
+ });
+
+ it('should call stopPropagation and preventDefault', function() {
+ $scope.grabResizer(evt);
+ expect(evt.stopPropagation).toHaveBeenCalled();
+ expect(evt.originalEvent.preventDefault).toHaveBeenCalled();
+ });
+
+ it('should add a .widget-resizer-marquee element to the .widget element', function() {
+ $scope.grabResizer(evt);
+ expect($element.find('.widget-resizer-marquee').length).toBeGreaterThan(0);
+ });
+
+ });
+
+ describe('the editTitle method', function() {
+
+ it('should set editingTitle=true on the widget object', function() {
+ var widget = {};
+ $scope.editTitle(widget);
+ expect(widget.editingTitle).toEqual(true);
+ });
+
+ it('should call $timeout', function() {
+ var widget = {};
+ $scope.editTitle(widget);
+ expect(injections.$timeout).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the saveTitleEdit method', function() {
+
+ it('should set editingTitle=false', function() {
+ var widget = { editingTitle: true };
+ $scope.saveTitleEdit(widget);
+ expect(widget.editingTitle).toEqual(false);
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.js
new file mode 100644
index 00000000..f5a6ebef
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.js
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .directive('widget', ['$injector', function ($injector) {
+
+ return {
+
+ controller: 'DashboardWidgetCtrl',
+
+ link: function (scope) {
+
+ var widget = scope.widget;
+ var dataModelType = widget.dataModelType;
+
+ // set up data source
+ if (dataModelType) {
+ var DataModelConstructor; // data model constructor function
+
+ if (angular.isFunction(dataModelType)) {
+ DataModelConstructor = dataModelType;
+ } else if (angular.isString(dataModelType)) {
+ $injector.invoke([dataModelType, function (DataModelType) {
+ DataModelConstructor = DataModelType;
+ }]);
+ } else {
+ throw new Error('widget dataModelType should be function or string');
+ }
+
+ var ds;
+ if (widget.dataModelArgs) {
+ ds = new DataModelConstructor(widget.dataModelArgs);
+ } else {
+ ds = new DataModelConstructor();
+ }
+ widget.dataModel = ds;
+ ds.setup(widget, scope);
+ ds.init();
+ scope.$on('$destroy', _.bind(ds.destroy,ds));
+ }
+
+ // Compile the widget template, emit add event
+ scope.compileTemplate();
+ scope.$emit('widgetAdded', widget);
+
+ }
+
+ };
+ }]);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.spec.js
new file mode 100644
index 00000000..0997e071
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.spec.js
@@ -0,0 +1,104 @@
+// 'use strict';
+
+describe('Directive: widget', function () {
+
+ var element, scope, rootScope, isoScope, compile, provide;
+
+ function Type() {
+ }
+
+ Type.prototype = {
+ setup: function () {
+ },
+ init: function () {
+ },
+ destroy: function () {
+ }
+ };
+
+ beforeEach(function () {
+ spyOn(Type.prototype, 'setup');
+ spyOn(Type.prototype, 'init');
+ spyOn(Type.prototype, 'destroy');
+ // define mock objects here
+ });
+
+ // load the directive's module
+ beforeEach(module('ui.dashboard', function ($provide, $controllerProvider) {
+ provide = $provide;
+ // Inject dependencies like this:
+ $controllerProvider.register('DashboardWidgetCtrl', function ($scope) {
+
+ });
+
+ }));
+
+ beforeEach(inject(function ($compile, $rootScope) {
+ // Cache these for reuse
+ rootScope = $rootScope;
+ compile = $compile;
+
+ // Other setup, e.g. helper functions, etc.
+
+ // Set up the outer scope
+ scope = $rootScope.$new();
+ scope.widget = {
+ dataModelType: Type
+ };
+
+ compileTemplate = jasmine.createSpy('compileTemplate');
+ scope.compileTemplate = compileTemplate;
+ }));
+
+ function compileWidget() {
+ // Define and compile the element
+ element = angular.element('<div widget><div class="widget-content"></div></div>');
+ element = compile(element)(scope);
+ scope.$digest();
+ isoScope = element.isolateScope();
+ }
+
+ it('should create a new instance of dataModelType if provided in scope.widget', function () {
+ compileWidget();
+ expect(scope.widget.dataModel instanceof Type).toBe(true);
+ });
+
+ it('should call setup and init on the new dataModel', function () {
+ compileWidget();
+ expect(Type.prototype.setup).toHaveBeenCalled();
+ expect(Type.prototype.init).toHaveBeenCalled();
+ });
+
+ it('should call compile template', function () {
+ compileWidget();
+ expect(scope.compileTemplate).toHaveBeenCalled();
+ });
+
+ it('should create a new instance of dataModelType from string name', function () {
+ // register data model with $injector
+ provide.factory('StringNameDataModel', function () {
+ return Type;
+ });
+
+ scope.widget = {
+ dataModelType: 'StringNameDataModel'
+ };
+
+ compileWidget();
+
+ expect(scope.widget.dataModel instanceof Type).toBe(true);
+ expect(Type.prototype.setup).toHaveBeenCalled();
+ expect(Type.prototype.init).toHaveBeenCalled();
+ });
+
+ it('should validate data model type', function () {
+ scope.widget = {
+ dataModelType: {}
+ };
+
+ expect(function () {
+ compileWidget()
+ }).toThrowError();
+ });
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/DashboardState.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/DashboardState.js
new file mode 100644
index 00000000..67948ead
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/DashboardState.js
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .factory('DashboardState', ['$log', '$q', function ($log, $q) {
+ function DashboardState(storage, id, hash, widgetDefinitions, stringify) {
+ this.storage = storage;
+ this.id = id;
+ this.hash = hash;
+ this.widgetDefinitions = widgetDefinitions;
+ this.stringify = stringify;
+ }
+
+ DashboardState.prototype = {
+ /**
+ * Takes array of widget instance objects, serializes,
+ * and saves state.
+ *
+ * @param {Array} widgets scope.widgets from dashboard directive
+ * @return {Boolean} true on success, false on failure
+ */
+ save: function (widgets) {
+
+ if (!this.storage) {
+ return true;
+ }
+
+ var serialized = _.map(widgets, function (widget) {
+ return widget.serialize();
+ });
+
+ var item = { widgets: serialized, hash: this.hash };
+
+ if (this.stringify) {
+ item = JSON.stringify(item);
+ }
+
+ this.storage.setItem(this.id, item);
+ return true;
+ },
+
+ /**
+ * Loads dashboard state from the storage object.
+ * Can handle a synchronous response or a promise.
+ *
+ * @return {Array|Promise} Array of widget definitions or a promise
+ */
+ load: function () {
+
+ if (!this.storage) {
+ return null;
+ }
+
+ var serialized;
+
+ // try loading storage item
+ serialized = this.storage.getItem( this.id );
+
+ if (serialized) {
+ // check for promise
+ if (angular.isObject(serialized) && angular.isFunction(serialized.then)) {
+ return this._handleAsyncLoad(serialized);
+ }
+ // otherwise handle synchronous load
+ return this._handleSyncLoad(serialized);
+ } else {
+ return null;
+ }
+ },
+
+ _handleSyncLoad: function(serialized) {
+
+ var deserialized, result = [];
+
+ if (!serialized) {
+ return null;
+ }
+
+ if (this.stringify) {
+ try { // to deserialize the string
+
+ deserialized = JSON.parse(serialized);
+
+ } catch (e) {
+
+ // bad JSON, log a warning and return
+ $log.warn('Serialized dashboard state was malformed and could not be parsed: ', serialized);
+ return null;
+
+ }
+ }
+ else {
+ deserialized = serialized;
+ }
+
+ // check hash against current hash
+ if (deserialized.hash !== this.hash) {
+
+ $log.info('Serialized dashboard from storage was stale (old hash: ' + deserialized.hash + ', new hash: ' + this.hash + ')');
+ this.storage.removeItem(this.id);
+ return null;
+
+ }
+
+ // Cache widgets
+ var savedWidgetDefs = deserialized.widgets;
+
+ // instantiate widgets from stored data
+ for (var i = 0; i < savedWidgetDefs.length; i++) {
+
+ // deserialized object
+ var savedWidgetDef = savedWidgetDefs[i];
+
+ // widget definition to use
+ var widgetDefinition = this.widgetDefinitions.getByName(savedWidgetDef.name);
+
+ // check for no widget
+ if (!widgetDefinition) {
+ // no widget definition found, remove and return false
+ $log.warn('Widget with name "' + savedWidgetDef.name + '" was not found in given widget definition objects');
+ continue;
+ }
+
+ // check widget-specific storageHash
+ if (widgetDefinition.hasOwnProperty('storageHash') && widgetDefinition.storageHash !== savedWidgetDef.storageHash) {
+ // widget definition was found, but storageHash was stale, removing storage
+ $log.info('Widget Definition Object with name "' + savedWidgetDef.name + '" was found ' +
+ 'but the storageHash property on the widget definition is different from that on the ' +
+ 'serialized widget loaded from storage. hash from storage: "' + savedWidgetDef.storageHash + '"' +
+ ', hash from WDO: "' + widgetDefinition.storageHash + '"');
+ continue;
+ }
+
+ // push instantiated widget to result array
+ result.push(savedWidgetDef);
+ }
+
+ return result;
+ },
+
+ _handleAsyncLoad: function(promise) {
+ var self = this;
+ var deferred = $q.defer();
+ promise.then(
+ // success
+ function(res) {
+ var result = self._handleSyncLoad(res);
+ if (result) {
+ deferred.resolve(result);
+ } else {
+ deferred.reject(result);
+ }
+ },
+ // failure
+ function(res) {
+ deferred.reject(res);
+ }
+ );
+
+ return deferred.promise;
+ }
+
+ };
+ return DashboardState;
+ }]); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.js
new file mode 100644
index 00000000..3685fd3f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.js
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .factory('LayoutStorage', function() {
+
+ var noopStorage = {
+ setItem: function() {
+
+ },
+ getItem: function() {
+
+ },
+ removeItem: function() {
+
+ }
+ };
+
+
+
+ function LayoutStorage(options) {
+
+ var defaults = {
+ storage: noopStorage,
+ storageHash: '',
+ stringifyStorage: true
+ };
+
+ angular.extend(defaults, options);
+ angular.extend(options, defaults);
+
+ this.id = options.storageId;
+ this.storage = options.storage;
+ this.storageHash = options.storageHash;
+ this.stringifyStorage = options.stringifyStorage;
+ this.widgetDefinitions = options.widgetDefinitions;
+ this.defaultLayouts = options.defaultLayouts;
+ this.lockDefaultLayouts = options.lockDefaultLayouts;
+ this.widgetButtons = options.widgetButtons;
+ this.explicitSave = options.explicitSave;
+ this.defaultWidgets = options.defaultWidgets;
+ this.settingsModalOptions = options.settingsModalOptions;
+ this.onSettingsClose = options.onSettingsClose;
+ this.onSettingsDismiss = options.onSettingsDismiss;
+ this.options = options;
+ this.options.unsavedChangeCount = 0;
+
+ this.layouts = [];
+ this.states = {};
+ this.load();
+ this._ensureActiveLayout();
+ }
+
+ LayoutStorage.prototype = {
+
+ add: function(layouts) {
+ if (!angular.isArray(layouts)) {
+ layouts = [layouts];
+ }
+ var self = this;
+ angular.forEach(layouts, function(layout) {
+ layout.dashboard = layout.dashboard || {};
+ layout.dashboard.storage = self;
+ layout.dashboard.storageId = layout.id = self._getLayoutId.call(self,layout);
+ layout.dashboard.widgetDefinitions = layout.widgetDefinitions || self.widgetDefinitions;
+ layout.dashboard.stringifyStorage = false;
+ layout.dashboard.defaultWidgets = layout.defaultWidgets || self.defaultWidgets;
+ layout.dashboard.widgetButtons = self.widgetButtons;
+ layout.dashboard.explicitSave = self.explicitSave;
+ layout.dashboard.settingsModalOptions = self.settingsModalOptions;
+ layout.dashboard.onSettingsClose = self.onSettingsClose;
+ layout.dashboard.onSettingsDismiss = self.onSettingsDismiss;
+ self.layouts.push(layout);
+ });
+ },
+
+ remove: function(layout) {
+ var index = this.layouts.indexOf(layout);
+ if (index >= 0) {
+ this.layouts.splice(index, 1);
+ delete this.states[layout.id];
+
+ // check for active
+ if (layout.active && this.layouts.length) {
+ var nextActive = index > 0 ? index - 1 : 0;
+ this.layouts[nextActive].active = true;
+ }
+ }
+ },
+
+ save: function() {
+
+ var state = {
+ layouts: this._serializeLayouts(),
+ states: this.states,
+ storageHash: this.storageHash
+ };
+
+ if (this.stringifyStorage) {
+ state = JSON.stringify(state);
+ }
+
+ this.storage.setItem(this.id, state);
+ this.options.unsavedChangeCount = 0;
+ },
+
+ load: function() {
+
+ var serialized = this.storage.getItem(this.id);
+
+ this.clear();
+
+ if (serialized) {
+ // check for promise
+ if (angular.isObject(serialized) && angular.isFunction(serialized.then)) {
+ this._handleAsyncLoad(serialized);
+ } else {
+ this._handleSyncLoad(serialized);
+ }
+ } else {
+ this._addDefaultLayouts();
+ }
+ },
+
+ clear: function() {
+ this.layouts = [];
+ this.states = {};
+ },
+
+ setItem: function(id, value) {
+ this.states[id] = value;
+ this.save();
+ },
+
+ getItem: function(id) {
+ return this.states[id];
+ },
+
+ removeItem: function(id) {
+ delete this.states[id];
+ this.save();
+ },
+
+ getActiveLayout: function() {
+ var len = this.layouts.length;
+ for (var i = 0; i < len; i++) {
+ var layout = this.layouts[i];
+ if (layout.active) {
+ return layout;
+ }
+ }
+ return false;
+ },
+
+ _addDefaultLayouts: function() {
+ var self = this;
+ var defaults = this.lockDefaultLayouts ? { locked: true } : {};
+ angular.forEach(this.defaultLayouts, function(layout) {
+ self.add(angular.extend(_.clone(defaults), layout));
+ });
+ },
+
+ _serializeLayouts: function() {
+ var result = [];
+ angular.forEach(this.layouts, function(l) {
+ result.push({
+ title: l.title,
+ id: l.id,
+ active: l.active,
+ locked: l.locked,
+ defaultWidgets: l.dashboard.defaultWidgets
+ });
+ });
+ return result;
+ },
+
+ _handleSyncLoad: function(serialized) {
+
+ var deserialized;
+
+ if (this.stringifyStorage) {
+ try {
+
+ deserialized = JSON.parse(serialized);
+
+ } catch (e) {
+ this._addDefaultLayouts();
+ return;
+ }
+ } else {
+
+ deserialized = serialized;
+
+ }
+
+ if (this.storageHash !== deserialized.storageHash) {
+ this._addDefaultLayouts();
+ return;
+ }
+ this.states = deserialized.states;
+ this.add(deserialized.layouts);
+ },
+
+ _handleAsyncLoad: function(promise) {
+ var self = this;
+ promise.then(
+ angular.bind(self, this._handleSyncLoad),
+ angular.bind(self, this._addDefaultLayouts)
+ );
+ },
+
+ _ensureActiveLayout: function() {
+ for (var i = 0; i < this.layouts.length; i++) {
+ var layout = this.layouts[i];
+ if (layout.active) {
+ return;
+ }
+ }
+ if (this.layouts[0]) {
+ this.layouts[0].active = true;
+ }
+ },
+
+ _getLayoutId: function(layout) {
+ if (layout.id) {
+ return layout.id;
+ }
+ var max = 0;
+ for (var i = 0; i < this.layouts.length; i++) {
+ var id = this.layouts[i].id;
+ max = Math.max(max, id * 1);
+ }
+ return max + 1;
+ }
+
+ };
+ return LayoutStorage;
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.spec.js
new file mode 100644
index 00000000..3310cad9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.spec.js
@@ -0,0 +1,692 @@
+'use strict';
+
+describe('Factory: LayoutStorage', function () {
+
+ // mock UI Sortable
+ beforeEach(function () {
+ angular.module('ui.sortable', []);
+ });
+
+ // load the service's module
+ beforeEach(module('ui.dashboard'));
+
+ // instantiate service
+ var LayoutStorage;
+ beforeEach(inject(function (_LayoutStorage_) {
+ LayoutStorage = _LayoutStorage_;
+ }));
+
+ describe('the constructor', function() {
+
+ var storage, options;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'something'},
+ {title: 'something'},
+ {title: 'something'}
+ ],
+ widgetButtons: false,
+ explicitSave: false,
+ settingsModalOptions: {},
+ onSettingsClose: function() {
+
+ },
+ onSettingsDismiss: function() {
+
+ }
+ };
+ storage = new LayoutStorage(options);
+ });
+
+ it('should provide an empty implementation of storage if it is not provided', function() {
+ delete options.storage;
+ var stateless = new LayoutStorage(options);
+ var noop = stateless.storage;
+ angular.forEach(['setItem', 'getItem', 'removeItem'], function(method) {
+ expect(typeof noop[method]).toEqual('function');
+ expect(noop[method]).not.toThrow();
+ noop[method]();
+ });
+ });
+
+ it('should set a subset of the options directly on the LayoutStorage instance itself', function() {
+ var properties = {
+ id: 'storageId',
+ storage: 'storage',
+ storageHash: 'storageHash',
+ stringifyStorage: 'stringifyStorage',
+ widgetDefinitions: 'widgetDefinitions',
+ defaultLayouts: 'defaultLayouts',
+ widgetButtons: 'widgetButtons',
+ explicitSave: 'explicitSave',
+ settingsModalOptions: 'settingsModalOptions',
+ onSettingsClose: 'onSettingsClose',
+ onSettingsDismiss: 'onSettingsDismiss'
+ };
+
+ angular.forEach(properties, function(val, key) {
+ expect( storage[key] ).toEqual( options[val] );
+ });
+
+ });
+
+ it('should set stringify as true by default', function() {
+ delete options.stringifyStorage;
+ storage = new LayoutStorage(options);
+ expect(storage.stringifyStorage).toEqual(true);
+ });
+
+ it('should allow stringify to be overridden by option', function() {
+ options.stringifyStorage = false;
+ storage = new LayoutStorage(options);
+ expect(storage.stringifyStorage).toEqual(false);
+ });
+
+ it('should create a layouts array and states object', function() {
+ expect(storage.layouts instanceof Array).toEqual(true);
+ expect(typeof storage.states).toEqual('object');
+ });
+
+ it('should call load', function() {
+ spyOn(LayoutStorage.prototype, 'load');
+ storage = new LayoutStorage(options);
+ expect(LayoutStorage.prototype.load).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the load method', function() {
+
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'something'},
+ {title: 'something'},
+ {title: 'something'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should use the default layouts if no stored info was found', function() {
+ expect(storage.layouts.length).toEqual(options.defaultLayouts.length);
+ });
+
+ it('should clone default layouts rather than use them directly', function() {
+ expect(storage.layouts.indexOf(options.defaultLayouts[0])).toEqual(-1);
+ });
+
+ it('should use the result from getItem for layouts.', function() {
+ spyOn(options.storage, 'getItem').and.returnValue(JSON.stringify({
+ storageHash: 'ds5f9d1f',
+ layouts: [
+ { id: 0, title: 'title', defaultWidgets: [], active: true },
+ { id: 1, title: 'title2', defaultWidgets: [], active: false },
+ { id: 2, title: 'title3', defaultWidgets: [], active: false },
+ { id: 3, title: 'custom', defaultWidgets: [], active: false }
+ ],
+ states: {
+ 0: {},
+ 1: {},
+ 2: {}
+ }
+ }));
+ storage.load();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['title', 'title2', 'title3', 'custom']);
+ });
+
+ it('should NOT use result from getItem for layouts if the storageHash doesnt match', function() {
+ spyOn(options.storage, 'getItem').and.returnValue(JSON.stringify({
+ storageHash: 'alskdjf02iej',
+ layouts: [
+ { id: 0, title: 'title', defaultWidgets: [], active: true },
+ { id: 1, title: 'title2', defaultWidgets: [], active: false },
+ { id: 2, title: 'title3', defaultWidgets: [], active: false },
+ { id: 3, title: 'custom', defaultWidgets: [], active: false }
+ ],
+ states: {
+ 0: {},
+ 1: {},
+ 2: {}
+ }
+ }));
+ storage.load();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['something', 'something', 'something']);
+ });
+
+ it('should be able to handle async loading via promise', inject(function($rootScope,$q) {
+ var deferred = $q.defer();
+ spyOn(options.storage, 'getItem').and.returnValue(deferred.promise);
+ storage.load();
+ expect(storage.layouts).toEqual([]);
+ deferred.resolve(JSON.stringify({
+ storageHash: 'ds5f9d1f',
+ layouts: [
+ { id: 0, title: 'title', defaultWidgets: [], active: true },
+ { id: 1, title: 'title2', defaultWidgets: [], active: false },
+ { id: 2, title: 'title3', defaultWidgets: [], active: false },
+ { id: 3, title: 'custom', defaultWidgets: [], active: false }
+ ],
+ states: {
+ 0: {},
+ 1: {},
+ 2: {}
+ }
+ }));
+ $rootScope.$apply();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['title', 'title2', 'title3', 'custom']);
+ }));
+
+ it('should load defaults if the deferred is rejected', inject(function($rootScope,$q) {
+ var deferred = $q.defer();
+ spyOn(options.storage, 'getItem').and.returnValue(deferred.promise);
+ storage.load();
+ deferred.reject();
+ $rootScope.$apply();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['something', 'something', 'something']);
+ }));
+
+ it('should load defaults if the json is malformed', inject(function($rootScope,$q) {
+ var deferred = $q.defer();
+ spyOn(options.storage, 'getItem').and.returnValue(deferred.promise);
+ storage.load();
+ expect(storage.layouts).toEqual([]);
+ deferred.resolve(JSON.stringify({
+ storageHash: 'ds5f9d1f',
+ layouts: [
+ { id: 0, title: 'title', defaultWidgets: [], active: true },
+ { id: 1, title: 'title2', defaultWidgets: [], active: false },
+ { id: 2, title: 'title3', defaultWidgets: [], active: false },
+ { id: 3, title: 'custom', defaultWidgets: [], active: false }
+ ],
+ states: {
+ 0: {},
+ 1: {},
+ 2: {}
+ }
+ }).replace('{','{{'));
+ $rootScope.$apply();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['something', 'something', 'something']);
+ }));
+
+ it('should not try to JSON.parse the result if stringifyStorage is false.', function() {
+ options.stringifyStorage = false;
+ storage = new LayoutStorage(options);
+ spyOn(options.storage, 'getItem').and.returnValue({
+ storageHash: 'ds5f9d1f',
+ layouts: [
+ { id: 0, title: 'title', defaultWidgets: [], active: true },
+ { id: 1, title: 'title2', defaultWidgets: [], active: false },
+ { id: 2, title: 'title3', defaultWidgets: [], active: false },
+ { id: 3, title: 'custom', defaultWidgets: [], active: false }
+ ],
+ states: {
+ 0: {},
+ 1: {},
+ 2: {}
+ }
+ });
+ storage.load();
+ expect(storage.layouts.map(function(l) {return l.title})).toEqual(['title', 'title2', 'title3', 'custom']);
+ });
+
+ });
+
+ describe('the add method', function() {
+
+ var storage, options;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [],
+ widgetButtons: false,
+ explicitSave: false
+ }
+
+ spyOn(LayoutStorage.prototype, 'load' );
+
+ storage = new LayoutStorage(options);
+
+ });
+
+ it('should add to storage.layouts', function() {
+ var newLayout = { title: 'my-layout' };
+ storage.add(newLayout);
+ expect(storage.layouts[0]).toEqual(newLayout);
+ });
+
+ it('should be able to take an array of new layouts', function() {
+ var newLayouts = [ { title: 'my-layout' }, { title: 'my-layout-2' } ];
+ storage.add(newLayouts);
+ expect(storage.layouts.length).toEqual(2);
+ expect(storage.layouts.indexOf(newLayouts[0])).not.toEqual(-1);
+ expect(storage.layouts.indexOf(newLayouts[1])).not.toEqual(-1);
+ });
+
+ it('should look for defaultWidgets on storage options if not supplied on layout definition', function() {
+ options.defaultWidgets = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
+ storage = new LayoutStorage(options);
+
+ var newLayouts = [ { title: 'my-layout', defaultWidgets: [] }, { title: 'my-layout-2' } ];
+ storage.add(newLayouts);
+ expect(newLayouts[0].dashboard.defaultWidgets === newLayouts[0].defaultWidgets).toEqual(true);
+ expect(newLayouts[1].dashboard.defaultWidgets === options.defaultWidgets).toEqual(true);
+ });
+
+ it('should use defaultWidgets if supplied in the layout definition', function() {
+ options.defaultWidgets = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
+ storage = new LayoutStorage(options);
+
+ var newLayouts = [ { title: 'my-layout', defaultWidgets: [] }, { title: 'my-layout-2' } ];
+ storage.add(newLayouts);
+ expect(newLayouts[0].dashboard.defaultWidgets).toEqual([]);
+ expect(newLayouts[1].dashboard.defaultWidgets).toEqual(options.defaultWidgets);
+ });
+
+ it('should look for widgetDefinitions on storage options if not supplied on layout definition', function() {
+ options.widgetDefinitions = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
+ storage = new LayoutStorage(options);
+
+ var newLayouts = [ { title: 'my-layout', widgetDefinitions: [] }, { title: 'my-layout-2' } ];
+ storage.add(newLayouts);
+ expect(newLayouts[0].dashboard.widgetDefinitions === newLayouts[0].widgetDefinitions).toEqual(true);
+ expect(newLayouts[1].dashboard.widgetDefinitions === options.widgetDefinitions).toEqual(true);
+ });
+
+ it('should use widgetDefinitions if supplied in the layout definition', function() {
+ options.widgetDefinitions = [{name: 'a'}, {name: 'b'}, {name: 'c'}];
+ storage = new LayoutStorage(options);
+
+ var newLayouts = [ { title: 'my-layout', widgetDefinitions: [] }, { title: 'my-layout-2' } ];
+ storage.add(newLayouts);
+ expect(newLayouts[0].dashboard.widgetDefinitions).toEqual([]);
+ expect(newLayouts[1].dashboard.widgetDefinitions).toEqual(options.widgetDefinitions);
+ });
+
+ });
+
+ describe('the remove method', function() {
+
+ var storage, options;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+ { name: 'A' },
+ { name: 'B' },
+ { name: 'C' }
+ ],
+ defaultLayouts: [
+ { title: '1' },
+ { title: '2', active: true },
+ { title: '3' }
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+
+ storage = new LayoutStorage(options);
+ });
+
+ it('should remove the supplied layout', function() {
+ var layout = storage.layouts[1];
+ storage.remove(layout);
+ expect(storage.layouts.indexOf(layout)).toEqual(-1);
+ });
+
+ it('should delete the state', function() {
+ var layout = storage.layouts[1];
+ storage.setItem(layout.id, {});
+ storage.remove(layout);
+ expect(storage.states[layout.id]).toBeUndefined();
+ });
+
+ it('should do nothing if layout is not in layouts', function() {
+ var layout = {};
+ var before = storage.layouts.length;
+ storage.remove(layout);
+ var after = storage.layouts.length;
+ expect(before).toEqual(after);
+ });
+
+ it('should set another dashboard to active if the layout removed was active', function() {
+ var layout = storage.layouts[1];
+ storage.remove(layout);
+ expect(storage.layouts[0].active || storage.layouts[1].active).toEqual(true);
+ });
+
+ it('should set the layout at index 0 to active if the removed layout was 0', function() {
+ storage.layouts[1].active = false;
+ storage.layouts[0].active = true;
+ storage.remove(storage.layouts[0]);
+ expect(storage.layouts[0].active).toEqual(true);
+ });
+
+ it('should not change the active layout if it was not the one that got removed', function() {
+ var active = storage.layouts[1];
+ var layout = storage.layouts[0];
+ storage.remove(layout);
+ expect(active.active).toEqual(true);
+ });
+
+ });
+
+ describe('the save method', function() {
+
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'something'},
+ {title: 'something'},
+ {title: 'something'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should call options.storage.setItem with a stringified object', function() {
+ spyOn(options.storage, 'setItem' );
+ storage.save();
+ expect(options.storage.setItem).toHaveBeenCalled();
+ expect(options.storage.setItem.calls.argsFor(0)[0]).toEqual(storage.id);
+ expect(typeof options.storage.setItem.calls.argsFor(0)[1]).toEqual('string');
+ expect(function(){
+ JSON.parse(options.storage.setItem.calls.argsFor(0)[1]);
+ }).not.toThrow();
+ });
+
+ it('should save an object that has layouts, states, and storageHash', function() {
+ spyOn(options.storage, 'setItem' );
+ storage.save();
+ var obj = JSON.parse(options.storage.setItem.calls.argsFor(0)[1]);
+ expect(obj.hasOwnProperty('layouts')).toEqual(true);
+ expect(obj.layouts instanceof Array).toEqual(true);
+ expect(obj.hasOwnProperty('states')).toEqual(true);
+ expect(typeof obj.states).toEqual('object');
+ expect(obj.hasOwnProperty('storageHash')).toEqual(true);
+ expect(typeof obj.storageHash).toEqual('string');
+ });
+
+ it('should call options.storage.setItem with an object when stringifyStorage is false', function() {
+ options.stringifyStorage = false;
+ storage = new LayoutStorage(options);
+ spyOn(options.storage, 'setItem' );
+ storage.save();
+ expect(options.storage.setItem).toHaveBeenCalled();
+ expect(options.storage.setItem.calls.argsFor(0)[0]).toEqual(storage.id);
+ expect(typeof options.storage.setItem.calls.argsFor(0)[1]).toEqual('object');
+ });
+
+ });
+
+ describe('the setItem method', function() {
+
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'something'},
+ {title: 'something'},
+ {title: 'something'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should set storage.states[id] to the second argument', function() {
+ var state = { some: 'thing'};
+ storage.setItem('id', state);
+ expect(storage.states.id).toEqual(state);
+ });
+
+ it('should call save', function() {
+ spyOn(storage, 'save');
+ var state = { some: 'thing'};
+ storage.setItem('id', state);
+ expect(storage.save).toHaveBeenCalled();
+ });
+
+ });
+
+ describe('the getItem method', function() {
+
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'something'},
+ {title: 'something'},
+ {title: 'something'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should return states[id]', function() {
+ storage.states['myId'] = {};
+ var result = storage.getItem('myId');
+ expect(result === storage.states['myId']).toEqual(true);
+ });
+
+ });
+
+ describe('the getActiveLayout method', function() {
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'i am active', active: true},
+ {title: 'i am not'},
+ {title: 'me neither'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should return the layout with active:true', function() {
+ var layout = storage.getActiveLayout();
+ expect(layout.title).toEqual('i am active');
+ });
+
+ it('should return false if no layout is active', function() {
+ var layout = storage.getActiveLayout();
+ layout.active = false;
+ var result = storage.getActiveLayout();
+ expect(result).toEqual(false);
+ });
+
+ });
+
+ describe('the removeItem', function() {
+
+ var options, storage;
+
+ beforeEach(function() {
+ options = {
+ storageId: 'testingStorage',
+ storage: {
+ setItem: function(key, value) {
+
+ },
+ getItem: function(key) {
+
+ },
+ removeItem: function(key) {
+
+ }
+ },
+ storageHash: 'ds5f9d1f',
+ stringifyStorage: true,
+ widgetDefinitions: [
+
+ ],
+ defaultLayouts: [
+ {title: 'i am active', active: true},
+ {title: 'i am not'},
+ {title: 'me neither'}
+ ],
+ widgetButtons: false,
+ explicitSave: false
+ }
+ storage = new LayoutStorage(options);
+ });
+
+ it('should remove states[id]', function() {
+ var state = {};
+ storage.setItem('1', state);
+ storage.removeItem('1');
+ expect(storage.states['1']).toBeUndefined();
+ });
+
+ it('should call save', function() {
+ spyOn(storage, 'save');
+ var state = {};
+ storage.setItem('1', state);
+ storage.removeItem('1');
+ expect(storage.save).toHaveBeenCalled();
+ });
+
+ });
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDataModel.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDataModel.js
new file mode 100644
index 00000000..547f2e96
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDataModel.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .factory('WidgetDataModel', function () {
+ function WidgetDataModel() {
+ }
+
+ WidgetDataModel.prototype = {
+ setup: function (widget, scope) {
+ this.dataAttrName = widget.dataAttrName;
+ this.dataModelOptions = widget.dataModelOptions;
+ this.widgetScope = scope;
+ },
+
+ updateScope: function (data) {
+ this.widgetScope.widgetData = data;
+ },
+
+ init: function () {
+ // to be overridden by subclasses
+ },
+
+ destroy: function () {
+ // to be overridden by subclasses
+ }
+ };
+
+ return WidgetDataModel;
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDefCollection.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDefCollection.js
new file mode 100644
index 00000000..27765440
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDefCollection.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .factory('WidgetDefCollection', function () {
+
+ function convertToDefinition(d) {
+ if (typeof d === 'function') {
+ return new d();
+ }
+ return d;
+ }
+
+ function WidgetDefCollection(widgetDefs) {
+
+ widgetDefs = widgetDefs.map(convertToDefinition);
+
+ this.push.apply(this, widgetDefs);
+
+ // build (name -> widget definition) map for widget lookup by name
+ var map = {};
+ _.each(widgetDefs, function (widgetDef) {
+ map[widgetDef.name] = widgetDef;
+ });
+ this.map = map;
+ }
+
+ WidgetDefCollection.prototype = Object.create(Array.prototype);
+
+ WidgetDefCollection.prototype.getByName = function (name) {
+ return this.map[name];
+ };
+
+ WidgetDefCollection.prototype.add = function(def) {
+ def = convertToDefinition(def);
+ this.push(def);
+ this.map[def.name] = def;
+ };
+
+ return WidgetDefCollection;
+ });
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.js
new file mode 100644
index 00000000..c378d3b6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.js
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+angular.module('ui.dashboard')
+ .factory('WidgetModel', function ($log) {
+
+ function defaults() {
+ return {
+ title: 'Widget',
+ style: {},
+ size: {},
+ enableVerticalResize: true,
+ containerStyle: { width: '33%' }, // default width
+ contentStyle: {}
+ };
+ };
+
+ // constructor for widget model instances
+ function WidgetModel(widgetDefinition, overrides) {
+
+ // Extend this with the widget definition object with overrides merged in (deep extended).
+ angular.extend(this, defaults(), _.merge(angular.copy(widgetDefinition), overrides));
+
+ this.updateContainerStyle(this.style);
+
+ if (!this.templateUrl && !this.template && !this.directive) {
+ this.directive = widgetDefinition.name;
+ }
+
+ if (this.size && _.has(this.size, 'height')) {
+ this.setHeight(this.size.height);
+ }
+
+ if (this.style && _.has(this.style, 'width')) { //TODO deprecate style attribute
+ this.setWidth(this.style.width);
+ }
+
+ if (this.size && _.has(this.size, 'width')) {
+ this.setWidth(this.size.width);
+ }
+ }
+
+ WidgetModel.prototype = {
+ // sets the width (and widthUnits)
+ setWidth: function (width, units) {
+ width = width.toString();
+ units = units || width.replace(/^[-\.\d]+/, '') || '%';
+
+ this.widthUnits = units;
+ width = parseFloat(width);
+
+ // check with min width if set, unit refer to width's unit
+ if (this.size && _.has(this.size, 'minWidth')) {
+ width = _.max([parseFloat(this.size.minWidth), width]);
+ }
+
+ if (width < 0 || isNaN(width)) {
+ $log.warn('malhar-angular-dashboard: setWidth was called when width was ' + width);
+ return false;
+ }
+
+ if (units === '%') {
+ width = Math.min(100, width);
+ width = Math.max(0, width);
+ }
+
+ this.containerStyle.width = width + '' + units;
+
+ this.updateSize(this.containerStyle);
+
+ return true;
+ },
+
+ setHeight: function (height) {
+ this.contentStyle.height = height;
+ this.updateSize(this.contentStyle);
+ },
+
+ setStyle: function (style) {
+ this.style = style;
+ this.updateContainerStyle(style);
+ },
+
+ updateSize: function (size) {
+ angular.extend(this.size, size);
+ },
+
+ updateContainerStyle: function (style) {
+ angular.extend(this.containerStyle, style);
+ },
+ serialize: function() {
+ return _.pick(this, ['title', 'name', 'report_id', 'hideGrid', 'showChart' ,'rcloud_url','reportData','style', 'size', 'dataModelOptions', 'attrs', 'storageHash']);
+ }
+ };
+
+ return WidgetModel;
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.spec.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.spec.js
new file mode 100644
index 00000000..151e560a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.spec.js
@@ -0,0 +1,156 @@
+'use strict';
+
+describe('Factory: WidgetModel', function () {
+
+ // load the service's module
+ beforeEach(module('ui.dashboard'));
+
+ // instantiate service
+ var WidgetModel;
+ beforeEach(inject(function (_WidgetModel_) {
+ WidgetModel = _WidgetModel_;
+ }));
+
+ it('should be a function', function() {
+ expect(typeof WidgetModel).toEqual('function');
+ });
+
+ describe('the constructor', function() {
+ var m, Class, Class2, overrides;
+
+ beforeEach(function() {
+ Class = {
+ name: 'TestWidget',
+ attrs: {},
+ dataAttrName: 'attr-name',
+ dataModelType: function TestType() {},
+ dataModelOptions: {},
+ style: { width: '10em' },
+ settingsModalOptions: {},
+ onSettingsClose: function() {},
+ onSettingsDismiss: function() {},
+ funkyChicken: {
+ cool: false,
+ fun: true
+ }
+ };
+
+ Class2 = {
+ name: 'TestWidget2',
+ attrs: {},
+ dataAttrName: 'attr-name',
+ dataModelType: function TestType() {},
+ dataModelOptions: {},
+ style: { width: '10em' },
+ templateUrl: 'my/url.html',
+ template: '<div>some template</div>'
+ };
+
+ overrides = {
+ style: {
+ width: '15em'
+ }
+ };
+ spyOn(WidgetModel.prototype, 'setWidth');
+ m = new WidgetModel(Class, overrides);
+ });
+
+ it('should copy class defaults, so that changes on an instance do not change the Class', function() {
+ m.style.width = '20em';
+ expect(Class.style.width).toEqual('10em');
+ });
+
+ it('should call setWidth', function() {
+ expect(WidgetModel.prototype.setWidth).toHaveBeenCalled();
+ });
+
+ it('should take overrides as precedent over Class defaults', function() {
+ expect(m.style.width).toEqual('15em');
+ });
+
+ it('should copy arbitrary data from the widget definition', function() {
+ expect(m.funkyChicken.cool).toEqual(false);
+ expect(m.funkyChicken.fun).toEqual(true);
+ expect(m.funkyChicken===Class.funkyChicken).toEqual(false);
+ });
+
+ it('should set templateUrl if and only if it is present on Class', function() {
+ var m2 = new WidgetModel(Class2, overrides);
+ expect(m2.templateUrl).toEqual('my/url.html');
+ });
+
+ it('should set template if and only if it is present on Class', function() {
+ delete Class2.templateUrl;
+ var m2 = new WidgetModel(Class2, overrides);
+ expect(m2.template).toEqual('<div>some template</div>');
+ });
+
+ it('should look for directive if neither templateUrl nor template is found on Class', function() {
+ delete Class2.templateUrl;
+ delete Class2.template;
+ Class2.directive = 'ng-bind';
+ var m2 = new WidgetModel(Class2, overrides);
+ expect(m2.directive).toEqual('ng-bind');
+ });
+
+ it('should set the name as directive if templateUrl, template, and directive are not defined', function() {
+ delete Class2.templateUrl;
+ delete Class2.template;
+ var m2 = new WidgetModel(Class2, overrides);
+ expect(m2.directive).toEqual('TestWidget2');
+ });
+
+ it('should not require overrides', function() {
+ var fn = function() {
+ var m2 = new WidgetModel(Class);
+ }
+ expect(fn).not.toThrow();
+ });
+
+ it('should copy references to settingsModalOptions, onSettingsClose, onSettingsDismiss', function() {
+ var m = new WidgetModel(Class);
+ expect(m.settingsModalOptions).toEqual(Class.settingsModalOptions);
+ expect(m.onSettingsClose).toEqual(Class.onSettingsClose);
+ expect(m.onSettingsDismiss).toEqual(Class.onSettingsDismiss);
+ });
+
+ });
+
+ describe('setWidth method', function() {
+
+ var context, setWidth;
+
+ beforeEach(function() {
+ context = new WidgetModel({});
+ setWidth = WidgetModel.prototype.setWidth;
+ });
+
+ it('should take one argument as a string with units', function() {
+ setWidth.call(context, '100px');
+ expect(context.containerStyle.width).toEqual('100px');
+ });
+
+ it('should take two args as a number and string as units', function() {
+ setWidth.call(context, 100, 'px');
+ expect(context.containerStyle.width).toEqual('100px');
+ });
+
+ it('should return false and not set anything if width is less than 0', function() {
+ var result = setWidth.call(context, -100, 'em');
+ expect(result).toEqual(false);
+ expect(context.containerStyle.width).not.toEqual('-100em');
+ });
+
+ it('should assume % if no unit is given', function() {
+ setWidth.call(context, 50);
+ expect(context.containerStyle.width).toEqual('50%');
+ });
+
+ it('should force greater than 0% and less than or equal 100%', function() {
+ setWidth.call(context, '110%');
+ expect(context.containerStyle.width).toEqual('100%');
+ });
+
+ });
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/report-dashboard.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/report-dashboard.html
new file mode 100644
index 00000000..8fecfb7b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/view-models/reportdashboard-page/src/report-dashboard.html
@@ -0,0 +1,220 @@
+<!doctype html>
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta http-equiv="cache-control" content="max-age=0" />
+ <meta http-equiv="cache-control" content="no-cache" />
+ <meta http-equiv="expires" content="0" />
+ <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
+ <meta http-equiv="pragma" content="no-cache"/>
+
+ <link rel="stylesheet" href="app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css">
+<!-- <meta charset="utf-8">
+ <title>Malhar Angular Dashboard</title>
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width"> -->
+ <!-- CSS -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
+ <link rel="import" href="app/fusion/scripts/view-models/header.html">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/demo.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/base.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/btn.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/dtpk.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/frms.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/sldr.css" >
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
+ <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
+ <!--
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
+ -->
+ <!-- Basic AngularJS -->
+
+
+ <!-- build:css({.tmp/serve,src}) styles/vendor.css -->
+
+<!-- <link rel="stylesheet" href="app/fusion/scripts/view-models/reportdashboard-page/src/app/vendor.css"> -->
+ <!-- bower:css -->
+ <!-- endbower -->
+ <!-- endbuild -->
+
+ <!-- build:css({.tmp/serve,src}) styles/app.css -->
+ <!-- inject:css -->
+ <link rel="stylesheet" href="app/fusion/scripts/view-models/reportdashboard-page/src/app/index.css">
+ <!-- endinject -->
+ <!-- endbuild -->
+
+ <!-- build:js(src) scripts/vendor.js -->
+ <!-- bower:js -->
+<!-- <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/jquery/dist/jquery.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular/angular.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/jquery-ui/jquery-ui.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-ui-sortable/sortable.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/bootstrap/dist/js/bootstrap.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/lodash/lodash.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-cookies/angular-cookies.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-mocks/angular-mocks.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-route/angular-route.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-sanitize/angular-sanitize.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/showdown/src/showdown.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/bower_components/angular-markdown-directive/markdown.js"></script>
+ -->
+ <script src="app/fusion/ase/scripts/dependencies/jquery-2.1.4.min.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-cookies.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-mocks.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-route.js"></script>
+ <script src="app/fusion/external/angular-1.4.8/angular-sanitize.js"></script>
+ <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.2.4.min.js"></script>
+ <script src="app/fusion/ase/scripts/menus/jquery-ui.min.js"></script>
+ <script src="app/fusion/ase/scripts/menus/bootstrap.min.js"></script>
+ <script src="app/fusion/external/angular-ui/ui-sortable/v0.13.4/sortable.min.js"></script>
+ <script src="app/fusion/external/lodash/4.5.1/lodash.js"></script>
+ <script src="app/fusion/external/showdown/0.3.4/showdown.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/angular-markdown-directive/markdown.js"></script>
+
+ <!-- endbower -->
+ <!-- endbuild -->
+
+
+<!-- app/fusion/scripts/view-models/reportdashboard-page/ -->
+ <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
+ <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
+ <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
+ <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
+<!-- <script src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script> -->
+
+<!-- <script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
+ <script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
+ <script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
+ <script src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script>
+ <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
+ <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
+ <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/0.10.0/lodash.min.js"></script>
+ <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script> -->
+
+ <!-- jQuery -->
+<!-- <script src="static/js/jquery-1.10.2.js"></script>
+ <script src="static/js/jquery.mask.min.js" type="text/javascript"></script>
+ <script src="static/js/jquery-ui.js" type="text/javascript"></script> -->
+
+ <!-- AngularJS Gridster -->
+ <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
+ <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
+ <!-- AngularJS Config -->
+ <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
+ <!-- Utility -->
+ <script src="app/fusion/scripts/modalService.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/report_whitelist.js"></script>
+ <!-- Controller js -->
+<!-- <script src="app/fusion/scripts/controllers/fn_menu_add_popup_controller.js"></script>
+ <script src="app/fusion/scripts/controllers/admin_menu_edit.js"></script>
+ <script src="app/fusion/scripts/controllers/profile-search-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/profile-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/post-search-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/role-list-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/role-function-list-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/rolefunctionpopupController.js"></script>
+ <script src="app/fusion/scripts/controllers/modelpopupController.js"></script>
+ <script src="app/fusion/scripts/controllers/jcs-admin-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/broadcast-list-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/broadcast-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/usage-list-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/collaborate-list-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/role-controller.js"></script>
+ <script src="app/fusion/scripts/controllers/rolepopupmodelController.js"></script>-->
+ <!-- Header and Footer -->
+ <!-- <script src="app/fusion/external/ebz/js/attHeaderSnippet.js"></script>
+ <script src="app/fusion/external/ebz/js/attHeader.js"></script> -->
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
+ <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
+ <script src="app/fusion/scripts/directives/footer.js"></script>
+ <script src="app/fusion/external/ebz/js/footer.js"></script>
+ <script src="app/fusion/scripts/directives/header.js"></script>
+ <script src="app/fusion/scripts/directives/leftMenu.js"></script>
+ <script src="app/fusion/scripts/services/leftMenuService.js"></script>
+
+ <!-- Services -->
+ <script src="app/fusion/scripts/services/profileService.js"></script>
+ <script src="app/fusion/scripts/services/adminService.js"></script>
+ <script src="app/fusion/scripts/services/userInfoService.js"></script>
+ <!-- Controller -->
+<!-- <script src="app/fusion/scripts/controllers/adminController.js"></script> -->
+ <!-- other js lib -->
+ <script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
+ <script src="app/fusion/scripts/moment.min.js"></script>
+
+ <!-- build:js({.tmp/serve,.tmp/partials,src}) scripts/app.js -->
+ <!-- inject:js -->
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/demo.js"></script>
+<!-- <script src="app/fusion/scripts/view-models/reportdashboard-page/src/templateCacheHtml.js"></script> -->
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/dashboard.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/widget.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/widget/DashboardWidgetCtrl.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/dashboardLayouts.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboardLayouts/SaveChangesModalCtrl.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsCtrl.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/directives/dashboard/WidgetSettingsRaptorReportCtrl.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetModel.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDefCollection.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/models/WidgetDataModel.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/models/LayoutStorage.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/components/models/DashboardState.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/resize.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/layouts.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/index.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/explicitSave.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/directives.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/dataModel.js"></script>
+ <script src="app/fusion/scripts/view-models/reportdashboard-page/src/app/customWidgetSettings.js"></script>
+ <script src="static/fusion/raptor/ebz/dynamicform.js"></script>
+ <script src="static/fusion/raptor/ebz/multiselect.js"></script>
+ <script src="static/fusion/raptor/ebz/report_search.js"></script>
+<!-- <script src="static/fusion/raptor/ebz/report_run.js"></script> -->
+ <script src="static/fusion/raptor/ebz/quick_links.js"></script>
+
+ <script src="static/fusion/raptor/uigrid/vfs_fonts.js"></script>
+ <script src="static/fusion/raptor/uigrid/ui-grid.js"></script>
+
+ <script src="static/fusion/raptor/ebz/report_chart_wizard.js"></script>
+
+
+ <script src="app/fusion/scripts/controllers/modelpopupController.js"></script>
+
+ <script src="static/fusion/raptor/ebz/date_time_picker.js"></script>
+ <script src="static/fusion/raptor/ebz/moment.js"></script>
+ <link rel="stylesheet" href="static/fusion/raptor/ebz/date_time_picker.css"/>
+ <link rel="stylesheet" href="static/fusion/raptor/uigrid/ui-grid.css" type="text/css">
+
+
+ <script>
+ app.requires.push('ui.dashboard');
+ </script>
+ <script>
+ angular.module('abs').requires.push('quantum', 'ngRoute', 'ui.grid',
+ 'ui.grid.pagination','ui.grid.resizeColumns',
+ 'ui.grid.pinning');
+ </script>
+
+ <!-- endinject -->
+
+ <!-- inject:partials -->
+ <!-- angular templates will be automatically converted in js and inserted here -->
+ <!-- endinject -->
+ <!-- endbuild -->
+
+
+
+
+
+ </head>
+ <body class="appBody" ng-app="abs">
+ <div q-header></div>
+ <div q-menu class="appLeftMenu"></div>
+ <div ng-view id="rightContentUiDashboard" style="position:relative; min-height: 1500px; top:-40px; margin-left:210px;"></div>
+ <div q-footer class="appFooter"></div>
+ </body>
+
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js
index 449e8d59..3ce348b6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/RTCMultiConnection.js
@@ -5575,7 +5575,7 @@
firebase: 'https://cdn.webrtc-experiment.com/firebase.js',
firebaseio: 'https://webrtc-signaling.firebaseio.com/',
-
+ muted: 'static/fusion/images/ATT_Labs_Logo.png',
getConnectionStats: 'https://cdn.webrtc-experiment.com/getConnectionStats.js',
FileBufferReader: 'https://cdn.webrtc-experiment.com/FileBufferReader.js'
@@ -5995,7 +5995,7 @@
username: 'ambient'
});
- /* CHANGED: Fusion: These are servers for testing purposes
+ /* CHANGED: Fusion: These are non-att servers for testing purposes
iceServers.push({
url: 'stun:stun.l.google.com:19302'
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html
index 6f660025..6f660025 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/scripts/webrtc/getSourceId.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css
index a9edba8f..a9edba8f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/sandbox-gridster.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css
index 827e354e..827e354e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/att_angular_gridster/ui-gridster.css
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/ecomp.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/ecomp.css
new file mode 100644
index 00000000..7b659e9c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/ecomp.css
@@ -0,0 +1,135 @@
+.menu-icon {
+ line-height: 40px;
+}
+
+.menu-icon-collapse {
+ line-height: 40px;
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+.header-container {
+ width: 100%;
+ float: left;
+}
+.menu-container {
+ float: left;
+ position:fixed;
+ background-color:#f2f2f2
+}
+.content-container {
+ min-height: 650px;
+ width: calc(100% - 250px);
+}
+.footer-container {
+ float:left;
+ position: relative;
+ z-index: 2;
+ width: 100%;
+ position:relative;
+ z-index:2;
+}
+
+.footer-global i {
+ font-size:40px;
+}
+
+.b2b-header-tabs .header__item.profile .profile-info{
+ border: 1px solid #d3d3d3;
+ max-width:400px;
+ width:300px;
+ padding: 20px;
+ pointer-events: auto;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 16px;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ background: #fff;
+ border-radius: 5px;
+ box-shadow: 0 5px 6px 0 rgba(0,0,0,.25);
+ color: #333;
+ line-height: 20px;
+ position: absolute;
+ left:-123px;
+ top:38px;
+ display:none;
+}
+
+
+/* .icon-accordion-plus, .icon-accordion-minus {
+ float: right;
+ line-height: 40px;
+}
+ */
+ .b2b-ln-icon-fix-pos{
+ margin-top:10px;
+ }
+.left-menu-collapsed {
+ width: 22px !important;
+}
+
+.b2b-subnav-content > li > a {
+ display: inline;
+}
+
+#page-content{
+ margin-left:250px;
+}
+
+.leftmenu-arrow-expand{
+ margin-left:200px
+}
+.leftmenu-arrow-collapse{
+ margin-left:0px;
+}
+
+.leftment-items{
+ margin-left:40px;
+}
+
+.error-popup-body{
+ word-wrap: break-word;
+}
+
+.build_number{
+ color:white
+}
+
+
+/*popup modal sizes*/
+.b2b-footer-wrapper .divider-bottom-footer{
+ padding: 30px 0 50px 0;
+}
+
+.b2b-modal-header{
+ font-size: 24px;
+}
+
+.b2b-modal-body{
+ font-size: 14px;
+}
+
+/* applying default styles */
+
+p,a{
+ font-size:14px;
+}
+
+.b2b-footer-wrapper .copyright-text-sdk {
+ color: #fff;
+ font-size: 11px;
+ text-align: left;
+ font-family: "Omnes-ECOMP-W02", Arial;
+}
+.b2b-footer-wrapper .copyright-text-sdk a {
+ color: #fff;
+ font-size: 11px;
+ text-decoration: underline;
+ display: inline-block;
+}
+.b2b-footer-wrapper .copyright-text-sdk a:hover {
+ text-decoration: none;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/fusion-sunny.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/fusion-sunny.css
new file mode 100644
index 00000000..f9154a1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/fusion-sunny.css
@@ -0,0 +1,362 @@
+ input, textarea, select, div {
+ font-family: Arial;
+ font-size: 11px;
+ font-weight: normal;
+ }
+
+ form {
+ margin-top: 5px;
+ }
+
+
+ .applicationWindow { border-width: 0px 0px 1px 0px;
+ border-style: solid;
+ border-color: #959595;
+ box-shadow: inset 0 0 10px #000000;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+
+ .feedbackMessage { width: 99%;
+ font-family: Arial;
+ font-size: 11px;
+ color: #1f1f1f;
+ padding: 3px;
+ border: 1px #eeb420 solid;
+ margin: 3px;
+ background: #fff9e5;
+ }
+
+ .menubar {
+ border-width: 0px 0px 0px 1px; border-style: solid; border-color: #959595;
+ }
+
+ .footer {
+ /*clear: both;*/
+ border-width: 0px 1px 0px 1px; border-style: solid; border-color: #959595;
+ font-family: Verdana,Arial,Helvetica, sans-serif;
+ font-size: 9px;
+ padding: 10px 10px 30px 10px;
+ background: white;
+ }
+
+ .pageTitle {
+ font-family: Arial;
+ font-size: 18px;
+ font-weight: bold;
+ margin-top: 5px;
+ }
+
+ .content {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ font-family: Arial;
+ font-size: 11px;
+ padding: 5px;
+ background: white;
+ /*height: 600px;*/
+ }
+
+ .popupContent {
+ font-family: Arial;
+ font-size: 11px;
+ padding: 3px;
+ }
+
+ .logo {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ text-align: right;
+ }
+
+ .sep {
+ border: 1px solid black
+ }
+
+ .logo { /*position: relative;*/
+ float:left;
+ padding-top: 25px;
+ padding-left: 25px;
+ }
+
+ .applicationLogo { float:right;
+ padding-top: 25px;
+ padding-right: 25px;
+ }
+
+ .applinkWhite { font-family: Arial;
+ font-size: 13px;
+ font-weight: 900;
+ color: #FFFFFF;
+ text-decoration: none; }
+
+ .terms { font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 9px;
+ }
+
+ .broadcastMessage { color: red; }
+ .broadcastMessageList { color: red; }
+
+ .button {
+ margin: 5px 1px 5px 1px;
+ padding: 3px; }
+
+ .toolbarbutton:hover {
+ color:#005491;
+ }
+
+ .headerText { font-family: Arial;
+ font-size: 15px;
+ font-weight: 700;
+ color: #000000; }
+
+ .headerBackground { background: #336699; }
+
+ .errorMessageText { font-family: Arial;
+ font-size: 11px;
+ font-weight: bold;
+ color: red; }
+
+
+ .normalText { font-family: Arial;
+ font-size: 11px;
+ color: #000000; }
+
+ .normalTextRed { font-family: Arial;
+ font-size: 11px;
+ color: red; }
+
+
+ .smallNormalText { font-family: Arial;
+ font-size: 9px;
+ color: #000000; }
+
+ .tableBorder { border:1px outset teal }
+
+ .validationError { background: #b9eaff; }
+
+ .templatebody {
+ background: url(../images/body_graphic.jpg) repeat-x;
+ /*margin: 40px 80px 40px 80px;*/
+ }
+
+ /*--------------------- General Content ------------------------------------*/
+
+ .relative {
+ position:relative;
+ }
+
+ .clear{
+ clear:both;
+ }
+
+ .left {
+ float: left;
+ }
+
+ .leftCentered{
+ float: left;
+ text-align: center;
+ }
+
+ .right {
+ float: right;
+ }
+
+ .rightAligned{
+ text-align: right;
+ }
+
+ .centered {
+ text-align: center;
+ align: center;
+ }
+
+
+ .noWrap{
+ white-space:nowrap;
+ }
+
+ .disabled {
+ color:gray;
+ cursor:hand;
+ }
+
+ /*--------------------- Tab styles -------------------------------------*/
+
+ .current {
+ font-weight: bold;
+ border-width: 1px 1px 1px 1px;
+ border-color: silver;
+ border-style: solid;
+ }
+
+ .subTab {
+ font-weight:bold;
+ font-family: Arial;
+ font-size: 11px;
+ color: #0F3B82;
+ }
+
+
+ /*--------------------- Grid styles ------------------------------------*/
+
+ /* Grid navigation and header styles */
+ .gridFilterLabel {font-size: 7pt;
+ font-align: justify;
+ font-weight: bold;
+ display: block;}
+
+ .gridFilterText {height: 17px;
+ font-size: 8pt;
+ width: 60%;
+ font-align: justify;}
+
+ .gridNavigationBar { font-family:Arial,Verdana;
+ font-size:11px;
+ font-weight:normal;
+ color:#000;
+ margin: 0px;
+ width: 100%;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .navLinks { float: left;
+ margin-right:15px;
+ padding-top: 2px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls { float: left;
+ margin-right: 15px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .pageInfo { float: right;
+ vertical-align: middle;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageInfo input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+
+ .gridNavigationBar span { padding: 3px; }
+
+ .gridNavigationBar a {
+ text-decoration:underline;
+ color:#000;
+ font-weight:normal;
+ }
+
+ .gridNavigationBar img { vertical-align: middle; }
+
+ .gridBulkUpdateRow {
+ height: 35px;
+ line-height: 35px;
+ }
+
+ .gridBulkUpdateRow input {
+ vertical-align: middle;
+ }
+
+
+ /* dummy class used to lock the form elements of a grid - ex. bulk transaction processing */
+ .alwaysEnabled {}
+
+ .hidden {
+ display: none;
+ }
+
+ .selectedPage {
+ background-color:#C4DFFB;
+ color: white;
+ border-style: solid;
+ border-width: 1px;
+ border-color: gray;
+ padding-left: 3px;
+ padding-right: 3px;
+ vertical-align: middle;
+ }
+
+ .selectedRow{
+ /*background-color:#C4DFFB;*/
+ }
+
+ /* Action Item styles */
+ .actionList {
+ margin-left: -20px;
+ margin-right: -10px;
+ padding-left: 5px;
+ }
+
+ .actionList li {
+ float:left;
+ padding-left: 3px;
+ padding-right: 3px;
+ }
+
+ .actionList li a {
+ text-decoration:none;
+ color:#000;
+ }
+
+ /* Filter Operator List styles */
+
+ .filterList {
+ margin: 0px;
+ }
+
+ .filterList li {
+ list-style-type: none;
+ padding:3px 3px 3px 2px;
+ cursor:hand;
+ font-size:11px;
+ }
+
+ .filterList li:hover {
+ background: #404040;
+ }
+
+ .filterList li a {
+ color: #000;
+ text-decoration: none;
+ }
+
+ .filterList li:hover a {
+ color: white;
+ }
+
+ .filterList li a:hover {
+ text-decoration: none;
+ color: white;
+ }
+
+ .filterListItem a {
+ text-decoration:none;
+ padding:3px 2px 3px 2px;
+ }
+
+
+ /*---------------------- Customized ZK Styles ------------------------------*/
+
+ .z-datebox input, .z-timebox input {
+ font-family: Arial;
+ font-size: 11px;
+ height: 15px;
+ margin-top:1px;
+ }
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/global.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/global.css
new file mode 100644
index 00000000..25d1c578
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/global.css
@@ -0,0 +1,178 @@
+body{
+ margin: 0;
+ padding: 0;
+ padding-bottom: 0 !important;
+ min-width: 980px;
+}
+label {
+ display: inline-block;
+ margin-bottom: 5px;
+ font-weight: 700;
+}
+.footer-columns label {
+ color: #009fdb;
+ font-size: 18px;
+}
+
+.b2b-header-tabs .header__item.profile .profile-info{
+ border: 1px solid #d3d3d3;
+ max-width:400px;
+ width:300px;
+ padding: 20px;
+ pointer-events: auto;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 16px;
+ -webkit-transition: opacity .2s ease-out;
+ -moz-transition: opacity .2s ease-out;
+ transition: opacity .2s ease-out;
+ background: #fff;
+ border-radius: 5px;
+ box-shadow: 0 5px 6px 0 rgba(0,0,0,.25);
+ color: #333;
+ line-height: 20px;
+ position: absolute;
+ left:-123px;
+ top:38px;
+ display:none;
+}
+.b2b-header-tabs .header__item.profile .profile-info.open{
+ display:block;
+}
+.b2b-header-tabs .header__item.profile .profile-info label{
+ font-family:Omnes-ATT-W02;
+ display:block;
+ margin-top:20px;
+ font-size: 16px;
+}
+.b2b-header-tabs .header__item.profile .profile-info span{
+ font-family:Omnes_ATTW02Medium;
+ display:block;
+}
+
+.b2b-header-tabs .selectWrap button.awd-select{
+ height:36px;
+ line-height:31px;
+ font-size:1rem;
+ display:inline-block;
+}
+/* @font-face {
+ font-family: atticons;
+ src: url(../fonts/atticons.eot?#iefix) format("embedded-opentype"), url(../fonts/atticons.woff) format("woff"), url(../fonts/atticons.ttf) format("truetype"), url(../fonts/atticons.svg#atticons) format("svg");
+ font-weight: normal;
+ font-style: normal;
+} */
+[class*=" icon-"], [class^=icon-] {
+ font-family: atticons;
+ speak: none;
+ font-style: normal;
+ font-weight: 400;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 40px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-user-small {
+ display: inline-block;
+ vertical-align: middle;
+ width: 20px;
+ font-size: 56px;
+ margin-right: 16px;
+ float: left;
+}
+.icon-user-small:before {
+ content: "\e60b";
+}
+.icon-local-search {
+ content: "\e685";
+}
+.header-container {
+ width: 100%;
+ float: left;
+}
+.menu-container {
+ width: 250px;
+ float: left;
+}
+.content-container {
+ float: left;
+ min-height: 650px;
+ width: calc(100% - 250px);
+}
+.footer-container {
+ float:left;
+ width: 100%;
+}
+.profile-info {
+ font-size: 16px;
+ color: #333;
+ line-height: 20px;
+}
+h6 {
+ font-weight: bold;
+ font-size: 1.125em;
+ line-height: 1.3333333333;
+}
+
+.icon-primary-accordion-plus, .icon-primary-accordion-minus {
+ float: right;
+ line-height: 20px;
+}
+.left-menu-collapsed {
+ width: 0px !important;
+}
+.menu-icon {
+ float: left;
+ line-height: 20px;
+ width: 25px;
+ height: 20px;
+ margin-top: -10px;
+}
+.b2b-footer-wrapper {
+ width: 100%;
+ background-color: #222;
+ height: 88px;
+}
+.icon-primary-right {
+ margin-left: -11px;
+}
+@media (max-width: 768px) {
+ .divider-bottom-footer .footerLogo {
+ margin: 10px 0 0 0px;
+ }
+ .b2b-header-tabs .header__items {
+ width: 700px;
+ }
+}
+@media screen and (min-device-width: 769px) and (max-width: 1200px) {
+ .b2b-header-tabs .header__items {
+ width: 700px;
+ }
+}
+@media screen and (max-width: 1100px) {
+ .b2b-header-tabs .header__item.profile {
+ float: right;
+ }
+}
+@media screen and (min-width: 768px) and (max-width: 1105px) {
+ table th, table td{
+ padding: 19px 10px;
+ }
+}
+.icon-spinner {
+ animation: spinner 1s linear infinite;
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2036%2036%22%3E%0A%20%20%3Cpath%20fill%3D%22%230569AE%22%20d%3D%22M18%2036c-2.7%200-4.8-.6-6.2-1C8%2033.6%205.4%2031.1%204%2029.3%202.7%2027.6.9%2024.7.3%2020.8c-.3-2.1-.5-5.4.9-9.1C3%206.8%206.4%204.1%208.3%202.8%2011.8.5%2015.4%200%2017.8%200l.1%204.3c-1.8%200-4.6.4-7.3%202.2-1.4.9-4%203-5.4%206.7-1%202.8-.9%205.3-.7%206.9.5%203%201.8%205.1%202.9%206.4%201.1%201.4%203%203.2%206%204.3%201.5.5%204.6%201.3%208.3.3%203-.8%205-2.5%206.2-3.7%201.4-1.4%202.4-3.2%203.1-5%20.4-1.3.9-3.3.6-5.8-.5-4.2-2.8-7.1-4.2-8.5L30.5%205c1.8%201.8%204.8%205.6%205.4%2011.1.3%203.2-.3%205.9-.9%207.6-.8%202.4-2.2%204.8-4%206.7-1.5%201.6-4.2%203.8-8.1%204.9-1.8.5-3.4.7-4.9.7z%22%2F%3E%0A%20%20%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M17.8%202.2c1.8%200%204.9.3%208.2%202.2%201.2.7%202.2%201.5%203%202.3%22%2F%3E%0A%20%20%3Cpath%20fill%3D%22%23F2F2F3%22%20d%3D%22M27.5%208.1c-.8-.8-1.7-1.4-2.6-1.9-2.1-1.2-4.5-1.9-7.1-1.9V0c3.3%200%206.5.9%209.3%202.4%201.2.8%202.3%201.6%203.4%202.6l-3%203.1z%22%2F%3E%0A%3C%2Fsvg%3E");
+ height: 50px;
+ width: 50px;
+}
+.loader-container {
+ position: fixed;
+ top: calc(50vh - 25px);
+ left: calc(50vw - 25px);
+}
+.loader-container i {
+ float: left;
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/jquery-ui.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/jquery-ui.css
index 1c22746c..1c22746c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/jquery-ui.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/jquery-ui.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css
index aa382de3..aa382de3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/layout/layout-default-latest.css
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/bs-workflow.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/bs-workflow.css
new file mode 100644
index 00000000..09e0a927
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/bs-workflow.css
@@ -0,0 +1,134 @@
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity .15s linear;
+ -o-transition: opacity .15s linear;
+ transition: opacity .15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 99999;
+ display: none;
+ overflow: hidden;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+ background-color: transparent;
+}
+.modal.fade .modal-dialog {
+ -webkit-transition: -webkit-transform .3s ease-out;
+ -o-transition: -o-transform .3s ease-out;
+ transition: transform .3s ease-out;
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ -o-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ outline: 0;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 9997;
+ background-color: #000;
+}
+.modal-backdrop.fade {
+ filter: alpha(opacity=0);
+ opacity: 0;
+}
+.modal-backdrop.in {
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.modal-header {
+ min-height: 16.42857143px;
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 15px;
+}
+.modal-footer {
+ padding: 15px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/workflows.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/workflows.css
new file mode 100644
index 00000000..2a740ec5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusion/styles/workflows/workflows.css
@@ -0,0 +1,31 @@
+.scrolling-table{
+ width: 1200px;
+}
+.scrolling-table .scroll-viewport {
+ height: 200px !important;
+ width: 99.5% !important;
+ background-color:white;
+}
+
+.scrolling-table .scroll-overview{
+ margin-top:-14px !important;
+}
+
+.scrolling-table .scroll-viewport:hover{
+ background-color:white;
+}
+
+.scrolling-table #att-scroll-table-content{
+ height:200px;
+ position: absolute !important;
+ width:700px;
+ padding-left: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-right:5px;
+}
+
+.workflow-popup-body{
+ position: relative;
+ padding: 30px;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js
new file mode 100644
index 00000000..c8a363c9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js
@@ -0,0 +1,43 @@
+app.controller("droolsListController", function ($scope,$http,droolsService, modalService, $modal) {
+ // Table Data
+ droolsService.getDrools().then(function(data){
+
+ var j = data;
+ $scope.tableData = JSON.parse(j.data);
+ //$scope.resetMenu();
+
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ $scope.viewPerPage = 20;
+ $scope.scrollViewsPerPage = 2;
+ $scope.currentPage = 1;
+ $scope.totalPage;
+ $scope.searchCategory = "";
+ $scope.searchString = "";
+ /* modalService.showSuccess('','Modal Sample') ; */
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ $scope.openDialog = function(droolFile){
+ droolsService.setSelectedFile(droolFile);
+ $modal.open({
+ templateUrl: 'app/fusionapp/drools/view-models/droolsView.html',
+ controller: 'droolsViewController'
+
+ })
+ }
+
+
+
+});
+
+function openInNewTab(url) {
+ var win = window.open(url, '_blank');
+ win.focus();
+}; \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js
new file mode 100644
index 00000000..0412718f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js
@@ -0,0 +1,45 @@
+app.controller('droolsViewController', function ($scope,modalService,droolsService){
+
+
+ $scope.resultsString = "";
+ // Table Data
+ droolsService.getDroolDetails(droolsService.getSelectedFile()).then(function(data){
+
+ var j = data;
+ $scope.postDroolsBean = JSON.parse(j.data);
+ //execute($scope.postDroolsBean);
+
+ },function(error){
+ console.log("failed");
+ //reloadPageOnce();
+ });
+
+
+
+ $scope.execute = function(postDroolsBean) {
+ console.log(postDroolsBean);
+ var uuu = "post_drools/execute";
+ var postData={postDroolsBean:postDroolsBean};
+ $.ajax({
+ type : 'POST',
+ url : uuu,
+ dataType: 'json',
+ contentType: 'application/json',
+ data: JSON.stringify(postData),
+ success : function(data){
+ $scope.$apply(function(){
+ $scope.resultsString=data.resultsString;
+ console.log($scope.resultsString);
+ });
+ },
+ error : function(data){
+ console.log(data);
+ modalService.showFailure("Fail","Error while executing: "+ data.responseText);
+ }
+ });
+
+ };
+
+
+
+ }); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/droolsController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/droolsController.js
new file mode 100644
index 00000000..c5c4e708
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/droolsController.js
@@ -0,0 +1,11 @@
+app.config(function($routeProvider) {
+ $routeProvider
+ .when('/view', {
+ templateUrl: 'app/fusionapp/drools/view-models/droolsView.html',
+ controller : "droolsViewController"
+ })
+ .otherwise({
+ templateUrl: 'app/fusionapp/drools/view-models/droolsList.html',
+ controller : "droolsListController"
+ });
+}); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/controller/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/external/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/directives/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/external/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/directives/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/services/droolsService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/services/droolsService.js
new file mode 100644
index 00000000..3b4ba3eb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/services/droolsService.js
@@ -0,0 +1,57 @@
+app.factory('droolsService', function ($http, $q) {
+ return {
+ getDrools: function() {
+ return $http.get('getDrools')
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getDroolDetails: function(selectedFile) {
+ return $http.get('getDroolDetails'+'?selectedFile=' + selectedFile )
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getRole: function(roleId) {
+
+ return $http.get('get_role?role_id=' + roleId)
+ .then(function(response) {
+ if (typeof response.data === 'object') {
+ return response.data;
+ } else {
+ return $q.reject(response.data);
+ }
+
+ }, function(response) {
+ // something went wrong
+ return $q.reject(response.data);
+ });
+ },
+
+ getSelectedFile: function() {
+ return this.selectedFile;
+ },
+
+ setSelectedFile: function(_selectedFile) {
+ this.selectedFile = _selectedFile;
+ }
+ };
+}); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/fonts/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/utils/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/fonts/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/utils/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html
new file mode 100644
index 00000000..91e68a15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html
@@ -0,0 +1,28 @@
+<div ng-controller="droolsListController">
+ <div>
+ <h1 class="heading1" style="margin-top:20px;">Drools List</h1>
+ <div style="margin-top:30px">
+ <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
+
+ <thead att-table-row type="header">
+ <tr>
+ <th att-table-header key="droolsFile">Drools File Name</th>
+ <th att-table-header key="className">Class Name</th>
+ <th att-table-header key="selectedRules">Run Rule</th>
+
+ </tr>
+ </thead>
+ <tbody att-table-row type="body" row-repeat="rowData in tableData">
+ <tr>
+ <td att-table-body ng-bind="rowData['droolsFile']">{{rowData.droolsFile}}</td>
+ <td att-table-body ng-bind="rowData['className']">{{rowData.className}}</td>
+
+ <td att-table-body >
+ <div ng-click="openDialog(rowData.droolsFile)" style="font-size:20px;"><a href="javascript:void(0)" class="icon-play"></a></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <input ng-model="currentPage"></input>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html
index 1d4f1bfd..a1d0a5ba 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsSinglePage.html
@@ -1,24 +1,4 @@
<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
@@ -39,8 +19,6 @@
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
<link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
- <!-- Icons -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
<!-- Basic AngularJS -->
<script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
<script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
@@ -69,6 +47,8 @@
<script src="app/fusionapp/drools/controller/drools-list-controller.js"></script>
<script src="app/fusionapp/drools/controller/drools-view-controller.js"></script>
<!-- Header and Footer -->
+ <script src="app/fusion/external/ebz/js/attHeaderSnippet.js"></script>
+ <script src="app/fusion/external/ebz/js/attHeader.js"></script>
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
<script src="app/fusion/scripts/directives/footer.js"></script>
@@ -89,4 +69,4 @@
<div id="rightContentAdmin" ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:10px;"></div>
<div q-footer class="appFooter"></div>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html
new file mode 100644
index 00000000..bcc80b73
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html
@@ -0,0 +1,42 @@
+<div ng-controller="droolsViewController" class="modal__informative font-showcase">
+
+<h1 class="heading1" style="margin-top:20px;">Drools Rule Engine</h1>
+ <br>
+ Please enter below details:<br/>
+
+ <div class="fn-ebz-container">
+ Drools File:<br/>
+ <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.droolsFile" value="" size="25">
+ </div>
+
+ <div class="fn-ebz-container">
+ Class Name:<br/>
+ <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.className" value="" size="25">
+ </div>
+
+ <div class="fn-ebz-container">
+ Selected Rules:<br/>
+ <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.selectedRules" value="" size="25">
+ </div>
+
+
+ <div>
+ <input att-button btn-type="primary" size="small" class="button" type="submit" value="Execute Rules" ng-click="execute(postDroolsBean);" />
+ </div>
+ <br>
+ {{resultsString}}
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+
+
+
+
+</div>
+
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/images/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/images/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/drools/view-models/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/external/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/external/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/fonts/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/fonts/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-icon.png
new file mode 100644
index 00000000..52ab2b54
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-text.png
new file mode 100644
index 00000000..9b3c3325
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7450-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-icon.png
new file mode 100644
index 00000000..9ee5499a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-text.png
new file mode 100644
index 00000000..aeb2dd00
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/7750-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-icon.png
new file mode 100644
index 00000000..0ba5c523
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-text.png
new file mode 100644
index 00000000..46631163
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/apn-dns-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-text.png
new file mode 100644
index 00000000..1566d5be
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atcf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-text.png
new file mode 100644
index 00000000..f7c50c60
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/atgw-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-text.png
new file mode 100644
index 00000000..b1e0869e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/bgcf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/com-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/com-icon.png
new file mode 100644
index 00000000..59463a91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/com-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-icon.png
new file mode 100644
index 00000000..9176a0d2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-text.png
new file mode 100644
index 00000000..5b35e77d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/cpm-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/default-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/default-icon.png
new file mode 100644
index 00000000..296a6f5c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/default-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-icon.png
new file mode 100644
index 00000000..74bfcfce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-text.png
new file mode 100644
index 00000000..00f2a2e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-epc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-icon.png
new file mode 100644
index 00000000..74bfcfce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-text.png
new file mode 100644
index 00000000..1d54d9aa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dra-ims-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-icon.png
new file mode 100644
index 00000000..b2a0585a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-text.png
new file mode 100644
index 00000000..1452d2e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/dslam-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-icon.png
new file mode 100644
index 00000000..59463a91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-text.png
new file mode 100644
index 00000000..ba9b216d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/eatf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-text.png
new file mode 100644
index 00000000..ca98a51d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ecscf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/emsc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/emsc-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/emsc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-icon.png
new file mode 100644
index 00000000..e03be510
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-text.png
new file mode 100644
index 00000000..9fbf8c29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enb-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-text.png
new file mode 100644
index 00000000..f04e3d5c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/enum-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-text.png
new file mode 100644
index 00000000..0a29e736
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/esmlc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-icon.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-text.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ettcs-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-text.png
new file mode 100644
index 00000000..43cf74d9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/gmlc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-text.png
new file mode 100644
index 00000000..b2762502
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hlr-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-text.png
new file mode 100644
index 00000000..9739214f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-epc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-text.png
new file mode 100644
index 00000000..ec69f259
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/hss-ims-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-text.png
new file mode 100644
index 00000000..6dbfc819
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/icscf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-icon.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-text.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ipag-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-text.png
new file mode 100644
index 00000000..a842e9ff
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/isbc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-icon.png
new file mode 100644
index 00000000..a82e73c1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-text.png
new file mode 100644
index 00000000..4d0092eb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/iwf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-icon.png
new file mode 100644
index 00000000..82b5c473
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-text.png
new file mode 100644
index 00000000..14daba85
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrf-rdf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrg-rdf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrg-rdf-text.png
new file mode 100644
index 00000000..3f7e2245
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/lrg-rdf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-text.png
new file mode 100644
index 00000000..2ba933a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgc8-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-text.png
new file mode 100644
index 00000000..74bf8f2c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgcf-emsc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-text.png
new file mode 100644
index 00000000..a2470f5d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mgw-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-text.png
new file mode 100644
index 00000000..84f9d86d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mind-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-icon.png
new file mode 100644
index 00000000..58ab86c5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-text.png
new file mode 100644
index 00000000..e524f192
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mme-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-icon.png
new file mode 100644
index 00000000..59463a91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-text.png
new file mode 100644
index 00000000..fa9a61cc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/mrf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msc-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-icon.png
new file mode 100644
index 00000000..8386fcb4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-text.png
new file mode 100644
index 00000000..954982f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/msn-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/multi-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/multi-icon.png
new file mode 100644
index 00000000..296a6f5c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/multi-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-icon.png
new file mode 100644
index 00000000..1ed07db4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-text.png
new file mode 100644
index 00000000..9b3c3325
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7450-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-icon.png
new file mode 100644
index 00000000..79ba2fc2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-text.png
new file mode 100644
index 00000000..afad34de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750a-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-icon.png
new file mode 100644
index 00000000..bfce0b12
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-text.png
new file mode 100644
index 00000000..afad34de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750b-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-icon.png
new file mode 100644
index 00000000..47870bc5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-text.png
new file mode 100644
index 00000000..afad34de
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750c-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-icon.png
new file mode 100644
index 00000000..f407a0f6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-text.png
new file mode 100644
index 00000000..6e25a269
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/n7750d-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-icon.png
new file mode 100644
index 00000000..e03be510
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-text.png
new file mode 100644
index 00000000..bbc1357b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/nb-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-icon.png
new file mode 100644
index 00000000..74bfcfce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-text.png
new file mode 100644
index 00000000..48b1e273
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pas-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-icon.png
new file mode 100644
index 00000000..17ed4a4a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-text.png
new file mode 100644
index 00000000..23faa7d7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcef-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-icon.png
new file mode 100644
index 00000000..17ed4a4a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-text.png
new file mode 100644
index 00000000..e48c305e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcrf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-text.png
new file mode 100644
index 00000000..b8d2c3dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pcscf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-text.png
new file mode 100644
index 00000000..d5f86b59
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pgw-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-icon.png
new file mode 100644
index 00000000..82b5c473
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-text.png
new file mode 100644
index 00000000..72662ef4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/plrf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/psap-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/psap-icon.png
new file mode 100644
index 00000000..2145c5f6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/psap-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-icon.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-text.png
new file mode 100644
index 00000000..6f15bdbf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/pstn-tdm-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-text.png
new file mode 100644
index 00000000..ab93224c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rg-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-icon.png
new file mode 100644
index 00000000..733d3da5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-text.png
new file mode 100644
index 00000000..24cab754
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/rnc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-text.png
new file mode 100644
index 00000000..f71bfba5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sbc-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-icon.png
new file mode 100644
index 00000000..59463a91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-text.png
new file mode 100644
index 00000000..1ca4e1dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sccas-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-icon.png
new file mode 100644
index 00000000..dafbe9e0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-text.png
new file mode 100644
index 00000000..fd3cab53
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/scscf-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-icon.png
new file mode 100644
index 00000000..b4c0288b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-text.png
new file mode 100644
index 00000000..3881e662
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sdg-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-icon.png
new file mode 100644
index 00000000..8df1aac1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-text.png
new file mode 100644
index 00000000..92cbd290
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgsns4-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-icon.png
new file mode 100644
index 00000000..2904d277
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-text.png
new file mode 100644
index 00000000..0801d797
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/sgw-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-icon.png
new file mode 100644
index 00000000..b2a0585a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-text.png
new file mode 100644
index 00000000..323c125e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/siad-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-icon.png
new file mode 100644
index 00000000..319bb37c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-text.png
new file mode 100644
index 00000000..1ba8a76d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7-gport-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-icon.png
new file mode 100644
index 00000000..daee75ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-text.png
new file mode 100644
index 00000000..8656f9f8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ss7gport-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/switch-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/switch-icon.png
new file mode 100644
index 00000000..6e512719
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/switch-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-icon.png
new file mode 100644
index 00000000..59463a91
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-text.png
new file mode 100644
index 00000000..7a843e8b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/tas-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-icon.png
new file mode 100644
index 00000000..b2a0585a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-text.png
new file mode 100644
index 00000000..975dd30b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/transcoder-text.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ue-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ue-icon.png
new file mode 100644
index 00000000..e23dfd36
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/ue-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/uephone-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/uephone-icon.png
new file mode 100644
index 00000000..50182db9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/uephone-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-icon.png
new file mode 100644
index 00000000..0ba5c523
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-icon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-text.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-text.png
new file mode 100644
index 00000000..46de0c26
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/icons/usp-dns-text.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/images/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/images/dummy.txt
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js
new file mode 100644
index 00000000..ad4f777e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js
@@ -0,0 +1,61 @@
+app.controller('samplePageController', function($scope, $http,ProfileService,modalService){
+ $scope.tableData=[];
+ $scope.viewPerPage=20;
+ $scope.scrollViewPerPage=2;
+ $scope.currentPage=1;
+ $scope.totalPage;
+ $scope.searchCategory;
+ $scope.searchString="";
+ $scope.currentPageNum=1;
+ ProfileService.getProfilePagination(1,$scope.viewPerPage).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData =JSON.parse($scope.data.profileList);
+ $scope.totalPages =JSON.parse($scope.data.totalPage);
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ //$scope.resetMenu();
+ },function(error){
+ console.log("failed");
+ reloadPageOnce();
+ });
+
+ $scope.$watch('currentPageNum', function(val) {
+
+ ProfileService.getProfilePagination(val,$scope.viewPerPage).then(function(data){
+ var j = data;
+ $scope.data = JSON.parse(j.data);
+ $scope.tableData =JSON.parse($scope.data.profileList);
+ $scope.totalPages =JSON.parse($scope.data.totalPage);
+ for(x in $scope.tableData){
+ if($scope.tableData[x].active_yn=='Y')
+ $scope.tableData[x].active_yn=true;
+ else
+ $scope.tableData[x].active_yn=false;
+ }
+ //$scope.resetMenu();
+ },function(error){
+ console.log("failed");
+ });
+
+ });
+
+ $scope.editRow = function(profileId){
+ window.location = 'userProfile#/profile/' + profileId;
+ }
+
+ $scope.toggleProfileActive = function(rowData) {
+ modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?",
+ function(){
+ $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){});
+ },
+ function(){
+ rowData.active=!rowData.active;
+ })
+ };
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js
new file mode 100644
index 00000000..8ba4eb54
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js
@@ -0,0 +1,4 @@
+app.controller('samplePageWithIframeController', function($scope, $http,ProfileService,modalService){
+
+
+}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js
new file mode 100644
index 00000000..518880c7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js
@@ -0,0 +1,11 @@
+app.config(function($routeProvider) {
+ $routeProvider
+ .when('/iframe', {
+ templateUrl: 'app/fusionapp/scripts/view-models/sampleWithIframe.html',
+ controller : "samplePageWithIframeController"
+ })
+ .otherwise({
+ templateUrl: 'app/fusionapp/scripts/view-models/sample.html',
+ controller : "samplePageController"
+ });
+}); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/styles/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt
index e69de29b..e69de29b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/styles/dummy.txt
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/directives/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/utils/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html
new file mode 100644
index 00000000..dafdc6a9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html
@@ -0,0 +1,3 @@
+<div ng-controller="samplePageWithIframeController" style="margin-left: auto;margin-right: auto;height:700px;">
+ <iframe style="margin-top:5px;width:100%;height:100%" frameBorder="0" vspace="0" src="user_profile"></iframe>
+</div> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/styles/dummy.txt b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/styles/dummy.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/app/fusionapp/styles/dummy.txt
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/index.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/index.jsp
new file mode 100644
index 00000000..f6030c97
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/index.jsp
@@ -0,0 +1,24 @@
+<%--
+ ================================================================================
+ eCOMP Portal SDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ --%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
+<%-- Forward to the intended start page to reduce frustration for new users. --%>
+<c:redirect url="/login.htm"></c:redirect>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/manifest.jsp b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/manifest.jsp
index b7345adb..b7345adb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/manifest.jsp
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/manifest.jsp
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css
new file mode 100644
index 00000000..a9edba8f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/sandbox-gridster.css
@@ -0,0 +1,173 @@
+.gridster {
+ position: relative;
+ margin: auto;
+ /* height: 0
+ */}
+
+.gridster>ul {
+ margin: 0;
+ list-style: none;
+ padding: 0
+}
+
+.gridster-item {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ list-style: none;
+ z-index: 2;
+ position: absolute;
+ display: none
+}
+
+.gridster-loaded {
+ -webkit-transition: height .3s;
+ -moz-transition: height .3s;
+ -o-transition: height .3s;
+ transition: height .3s
+}
+
+.gridster-loaded .gridster-item {
+ display: block;
+ position: absolute;
+ -webkit-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -moz-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -o-transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ transition: opacity .3s, left .3s, top .3s, width .3s, height .3s;
+ -webkit-transition-delay: 50ms;
+ -moz-transition-delay: 50ms;
+ -o-transition-delay: 50ms;
+ transition-delay: 50ms
+}
+
+.gridster-loaded .gridster-preview-holder {
+ display: none;
+ z-index: 1;
+ position: absolute;
+ background-color: #067ab4;
+ /*
+ background-color: rgb(6, 122, 180);
+ -ms-filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#067ab4', endColorstr='#067ab4'); IE
+ opacity: 0.2;
+ */
+ border-color: #fff;
+ -webkit-transition: width .2s, height .3s;
+ -moz-transition: width .2s, height .3s;
+ -o-transition: width .2s, height .3s;
+ transition: width .2s, height .3s;
+ -webkit-transition-delay: 50ms;
+ -moz-transition-delay: 50ms;
+ -o-transition-delay: 50ms;
+ transition-delay: 50ms
+}
+
+.gridster-loaded .gridster-item.gridster-item-moving {
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+ opacity: 0.9;
+}
+
+.gridster-mobile {
+ height: auto !important
+}
+
+.gridster-mobile .gridster-item {
+ height: auto;
+ position: static;
+ float: none
+}
+
+.gridster-item.ng-leave.ng-leave-active {
+ opacity: 0
+}
+
+.gridster-item.ng-enter {
+ opacity: 1
+}
+
+.gridster-item-moving {
+ z-index: 3
+}
+
+.gridster-item-resizable-handler {
+ position: absolute;
+ font-size: 1px;
+ display: block
+}
+
+.handle-se {
+ cursor: se-resize;
+ width: 0;
+ height: 0;
+ right: 1px;
+ bottom: 1px;
+ border-style: solid;
+ border-width: 0 0 12px 12px;
+ border-color: transparent
+}
+
+.handle-ne {
+ cursor: ne-resize;
+ width: 12px;
+ height: 12px;
+ right: 1px;
+ top: 1px
+}
+
+.handle-nw {
+ cursor: nw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ top: 1px
+}
+
+.handle-sw {
+ cursor: sw-resize;
+ width: 12px;
+ height: 12px;
+ left: 1px;
+ bottom: 1px
+}
+
+.handle-e {
+ cursor: e-resize;
+ width: 12px;
+ bottom: 0;
+ right: 1px;
+ top: 0
+}
+
+.handle-s {
+ cursor: s-resize;
+ height: 12px;
+ right: 0;
+ bottom: 1px;
+ left: 0
+}
+
+.handle-n {
+ cursor: n-resize;
+ height: 12px;
+ right: 0;
+ top: 1px;
+ left: 0
+}
+
+.handle-w {
+ cursor: w-resize;
+ width: 12px;
+ left: 1px;
+ top: 0;
+ bottom: 0
+}
+
+.gridster .gridster-item:hover .gridster-box {
+ border: 1.5px solid #B3B2B3
+}
+
+.gridster .gridster-item:hover .handle-se {
+ border-color: transparent transparent #ccc
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css
index 827e354e..827e354e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/att_angular_gridster/ui-gridster.css
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/fusion-sunny.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/fusion-sunny.css
new file mode 100644
index 00000000..f9154a1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/css/fusion-sunny.css
@@ -0,0 +1,362 @@
+ input, textarea, select, div {
+ font-family: Arial;
+ font-size: 11px;
+ font-weight: normal;
+ }
+
+ form {
+ margin-top: 5px;
+ }
+
+
+ .applicationWindow { border-width: 0px 0px 1px 0px;
+ border-style: solid;
+ border-color: #959595;
+ box-shadow: inset 0 0 10px #000000;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+
+ .feedbackMessage { width: 99%;
+ font-family: Arial;
+ font-size: 11px;
+ color: #1f1f1f;
+ padding: 3px;
+ border: 1px #eeb420 solid;
+ margin: 3px;
+ background: #fff9e5;
+ }
+
+ .menubar {
+ border-width: 0px 0px 0px 1px; border-style: solid; border-color: #959595;
+ }
+
+ .footer {
+ /*clear: both;*/
+ border-width: 0px 1px 0px 1px; border-style: solid; border-color: #959595;
+ font-family: Verdana,Arial,Helvetica, sans-serif;
+ font-size: 9px;
+ padding: 10px 10px 30px 10px;
+ background: white;
+ }
+
+ .pageTitle {
+ font-family: Arial;
+ font-size: 18px;
+ font-weight: bold;
+ margin-top: 5px;
+ }
+
+ .content {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ font-family: Arial;
+ font-size: 11px;
+ padding: 5px;
+ background: white;
+ /*height: 600px;*/
+ }
+
+ .popupContent {
+ font-family: Arial;
+ font-size: 11px;
+ padding: 3px;
+ }
+
+ .logo {
+ border-width: 0px 1px 0px 1px;
+ border-style: solid;
+ border-color: #959595;
+ text-align: right;
+ }
+
+ .sep {
+ border: 1px solid black
+ }
+
+ .logo { /*position: relative;*/
+ float:left;
+ padding-top: 25px;
+ padding-left: 25px;
+ }
+
+ .applicationLogo { float:right;
+ padding-top: 25px;
+ padding-right: 25px;
+ }
+
+ .applinkWhite { font-family: Arial;
+ font-size: 13px;
+ font-weight: 900;
+ color: #FFFFFF;
+ text-decoration: none; }
+
+ .terms { font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 9px;
+ }
+
+ .broadcastMessage { color: red; }
+ .broadcastMessageList { color: red; }
+
+ .button {
+ margin: 5px 1px 5px 1px;
+ padding: 3px; }
+
+ .toolbarbutton:hover {
+ color:#005491;
+ }
+
+ .headerText { font-family: Arial;
+ font-size: 15px;
+ font-weight: 700;
+ color: #000000; }
+
+ .headerBackground { background: #336699; }
+
+ .errorMessageText { font-family: Arial;
+ font-size: 11px;
+ font-weight: bold;
+ color: red; }
+
+
+ .normalText { font-family: Arial;
+ font-size: 11px;
+ color: #000000; }
+
+ .normalTextRed { font-family: Arial;
+ font-size: 11px;
+ color: red; }
+
+
+ .smallNormalText { font-family: Arial;
+ font-size: 9px;
+ color: #000000; }
+
+ .tableBorder { border:1px outset teal }
+
+ .validationError { background: #b9eaff; }
+
+ .templatebody {
+ background: url(../images/body_graphic.jpg) repeat-x;
+ /*margin: 40px 80px 40px 80px;*/
+ }
+
+ /*--------------------- General Content ------------------------------------*/
+
+ .relative {
+ position:relative;
+ }
+
+ .clear{
+ clear:both;
+ }
+
+ .left {
+ float: left;
+ }
+
+ .leftCentered{
+ float: left;
+ text-align: center;
+ }
+
+ .right {
+ float: right;
+ }
+
+ .rightAligned{
+ text-align: right;
+ }
+
+ .centered {
+ text-align: center;
+ align: center;
+ }
+
+
+ .noWrap{
+ white-space:nowrap;
+ }
+
+ .disabled {
+ color:gray;
+ cursor:hand;
+ }
+
+ /*--------------------- Tab styles -------------------------------------*/
+
+ .current {
+ font-weight: bold;
+ border-width: 1px 1px 1px 1px;
+ border-color: silver;
+ border-style: solid;
+ }
+
+ .subTab {
+ font-weight:bold;
+ font-family: Arial;
+ font-size: 11px;
+ color: #0F3B82;
+ }
+
+
+ /*--------------------- Grid styles ------------------------------------*/
+
+ /* Grid navigation and header styles */
+ .gridFilterLabel {font-size: 7pt;
+ font-align: justify;
+ font-weight: bold;
+ display: block;}
+
+ .gridFilterText {height: 17px;
+ font-size: 8pt;
+ width: 60%;
+ font-align: justify;}
+
+ .gridNavigationBar { font-family:Arial,Verdana;
+ font-size:11px;
+ font-weight:normal;
+ color:#000;
+ margin: 0px;
+ width: 100%;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .navLinks { float: left;
+ margin-right:15px;
+ padding-top: 2px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls { float: left;
+ margin-right: 15px;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageControls input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+ .gridNavigationBar .pageInfo { float: right;
+ vertical-align: middle;
+ height: 19px;
+ line-height: 19px;
+ }
+
+ .gridNavigationBar .pageInfo input { font-size: 8pt;
+ height: 17px;
+ vertical-align: middle;
+ }
+
+
+ .gridNavigationBar span { padding: 3px; }
+
+ .gridNavigationBar a {
+ text-decoration:underline;
+ color:#000;
+ font-weight:normal;
+ }
+
+ .gridNavigationBar img { vertical-align: middle; }
+
+ .gridBulkUpdateRow {
+ height: 35px;
+ line-height: 35px;
+ }
+
+ .gridBulkUpdateRow input {
+ vertical-align: middle;
+ }
+
+
+ /* dummy class used to lock the form elements of a grid - ex. bulk transaction processing */
+ .alwaysEnabled {}
+
+ .hidden {
+ display: none;
+ }
+
+ .selectedPage {
+ background-color:#C4DFFB;
+ color: white;
+ border-style: solid;
+ border-width: 1px;
+ border-color: gray;
+ padding-left: 3px;
+ padding-right: 3px;
+ vertical-align: middle;
+ }
+
+ .selectedRow{
+ /*background-color:#C4DFFB;*/
+ }
+
+ /* Action Item styles */
+ .actionList {
+ margin-left: -20px;
+ margin-right: -10px;
+ padding-left: 5px;
+ }
+
+ .actionList li {
+ float:left;
+ padding-left: 3px;
+ padding-right: 3px;
+ }
+
+ .actionList li a {
+ text-decoration:none;
+ color:#000;
+ }
+
+ /* Filter Operator List styles */
+
+ .filterList {
+ margin: 0px;
+ }
+
+ .filterList li {
+ list-style-type: none;
+ padding:3px 3px 3px 2px;
+ cursor:hand;
+ font-size:11px;
+ }
+
+ .filterList li:hover {
+ background: #404040;
+ }
+
+ .filterList li a {
+ color: #000;
+ text-decoration: none;
+ }
+
+ .filterList li:hover a {
+ color: white;
+ }
+
+ .filterList li a:hover {
+ text-decoration: none;
+ color: white;
+ }
+
+ .filterListItem a {
+ text-decoration:none;
+ padding:3px 2px 3px 2px;
+ }
+
+
+ /*---------------------- Customized ZK Styles ------------------------------*/
+
+ .z-datebox input, .z-timebox input {
+ font-family: Arial;
+ font-size: 11px;
+ height: 15px;
+ margin-top:1px;
+ }
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/css/nv.d3.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/css/nv.d3.css
index 28ccd053..28ccd053 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/css/nv.d3.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/css/nv.d3.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/cie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/cie.js
index 45f01329..45f01329 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/cie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/cie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/colorbrewer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/colorbrewer.js
index 2295527b..2295527b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/colorbrewer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/colorbrewer.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/core.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/core.js
index 912de8d8..912de8d8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/core.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/core.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.js
index 1aaabca2..1aaabca2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.min.js
index 981f0d64..981f0d64 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/crossfilter.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/crossfilter.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.geom.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.geom.js
index a19bb16e..a19bb16e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.geom.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.geom.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.js
index 7655eb78..7655eb78 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js
index 44c4f7de..44c4f7de 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.cloud.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.js
index abc5ebef..abc5ebef 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.layout.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.layout.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.js
index 78c4dbca..78c4dbca 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.min.js
index cc47f1ea..cc47f1ea 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v2.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v2.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v3.min.js
index 7975878f..7975878f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/d3.v3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/d3.v3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/fisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/fisheye.js
index e1addd7b..e1addd7b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/fisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/fisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/hive.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/hive.js
index 06e53aed..06e53aed 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/hive.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/hive.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/horizon.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/horizon.js
index d84c6567..d84c6567 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/horizon.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/horizon.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/interactiveLayer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/interactiveLayer.js
index 4dfb68dc..4dfb68dc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/interactiveLayer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/interactiveLayer.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/intro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/intro.js
index af50383e..af50383e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/d3/js/intro.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/intro.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis-min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis-min.js
index 1101dde5..1101dde5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis-min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis-min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.js
index 9895c3f0..9895c3f0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.min.js
index 6c8ad6ab..6c8ad6ab 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/axis.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/axis.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js
index 86ebeb0f..86ebeb0f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bullet.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js
index a2a0f077..a2a0f077 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/backup/bulletChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/boilerplate.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/boilerplate.js
index 3d2360a6..3d2360a6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/boilerplate.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/boilerplate.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bullet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bullet.js
index 9b9bf4d1..9b9bf4d1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bullet.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bullet.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bulletChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bulletChart.js
index fa5bd596..fa5bd596 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/bulletChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/bulletChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js
index 00f193cf..00f193cf 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/cumulativeLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBar.js
index a20f5829..a20f5829 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js
index 48a48164..48a48164 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/discreteBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/distribution.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/distribution.js
index 62a74655..62a74655 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/distribution.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/distribution.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBar.js
index 2a6c644d..2a6c644d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js
index a5b4a097..a5b4a097 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/historicalBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/indentedTree.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/indentedTree.js
index 18c2700f..18c2700f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/indentedTree.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/indentedTree.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/legend.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/legend.js
index 21f9f9a4..21f9f9a4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/legend.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/legend.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/line.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/line.js
index 855cc541..855cc541 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/line.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/line.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineChart.js
index a4ffcf6a..a4ffcf6a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js
index 77fcbab7..77fcbab7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js
index 2ef31137..2ef31137 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/linePlusBarWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js
index 2b411672..2b411672 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js
index ad894190..ad894190 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFisheyeChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js
index 0afd28bd..0afd28bd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/lineWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBar.js
index 1085919b..1085919b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js
index 0323063f..0323063f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js
index d16d4605..d16d4605 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontal.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js
index 02aa6fa4..02aa6fa4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarHorizontalChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js
index abc062c3..abc062c3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeries.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js
index 5aebafa7..5aebafa7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiBarTimeSeriesChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiChart.js
index e3e2c5e8..e3e2c5e8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/multiChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/multiChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js
index 46f2b60c..46f2b60c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/ohlcBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js
index 107154f7..107154f7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/parallelCoordinates.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pie.js
index 2099c8f3..2099c8f3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pieChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pieChart.js
index b4303fd6..b4303fd6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/pieChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/pieChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatter.js
index 16cbee65..16cbee65 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterChart.js
index 65b6e387..65b6e387 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js
index 23c87853..23c87853 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/scatterPlusLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparkline.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparkline.js
index e4c2e87b..e4c2e87b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparkline.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparkline.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js
index 1535f8af..1535f8af 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/sparklinePlus.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedArea.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedArea.js
index eefeb8fb..eefeb8fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedArea.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedArea.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js
index a036b8b0..a036b8b0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/models/stackedAreaChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.js
index 78586667..78586667 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.min.js
index 892379c4..892379c4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/nv.d3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/nv.d3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/outro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/outro.js
index 158693a0..158693a0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/outro.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/outro.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/sankey.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/sankey.js
index c3bc59fb..c3bc59fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/sankey.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/sankey.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/tooltip.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/tooltip.js
index 46e5a816..46e5a816 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/tooltip.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/tooltip.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/utils.js
index 7b99e1da..7b99e1da 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/utils.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/d3/js/utils.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/gis/js/local.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/gis/js/local.js
new file mode 100644
index 00000000..5f4208a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/gis/js/local.js
@@ -0,0 +1,178 @@
+var pointLayer= null;
+var animateFlag = false;
+var frame = 0;
+var dates = [];
+var delay = 1000;
+var intervalId = null;
+$( document ).ready(function() {
+ map(data2.map.lat,data2.map.lon,data2.map.zoom);
+ pointLayer = new L.layerGroup().addTo(map);
+ var point = getDates(data2.points);
+ drawPoints(data2,point);
+
+
+ $('#timeUp').bind('click',function(){
+ delay += 500;
+ if ( animateFlag ) {
+ clearInterval(intervalId);
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+ $('#timeDown').bind('click',function(){
+ if ( delay === 500 ) { return false; }
+ delay -= 500;
+ if ( animateFlag ) {
+ clearInterval(intervalId);
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+
+
+ $('#date').bind('change',function(){
+ drawPoints(data2,$('#date').val());
+ });
+ $('#animate').bind('click',function(){
+ if ( animateFlag ) {
+ animateFlag = false;
+ $('#animate_color').html('Off');
+ $('#animate_color').removeClass('animateOn');
+ $('#animate_color').addClass('animateOff');
+ clearInterval(intervalId);
+ } else {
+ animateFlag = true;
+ $('#animate_color').html('On');
+ $('#animate_color').removeClass('animateOff');
+ $('#animate_color').addClass('animateOn');
+ intervalId = window.setInterval(function(){animate(data2);},delay);
+ }
+ });
+
+
+});
+
+function abc() {
+ var abc = 1;
+ var xyz = "";
+ return nul;
+
+}
+
+
+
+function animate(obj){
+ var point = dates[frame];
+ drawPoints(obj,point);
+ frame++;
+ if ( frame >= dates.length ) {
+ frame = 0;
+ }
+ $('#currDate').val(point);
+ $('#showDelay').html(delay);
+}
+
+function someFunction() {
+
+ var self = this;
+ var x = 1;
+ var z = self + x;
+}
+
+
+/**
+* drawPoints - Draw the points provided by point(date)
+* obj JSON Object - Data for Map
+* p String - Key (date) from the JSON object.
+*/
+function drawPoints(obj,p){
+ pointLayer.clearLayers();
+ var lats = obj.points[p].lats;
+ var lons = obj.points[p].lons;
+ var txt = obj.points[p].text;
+ var fills = obj.points[p].colors;
+ points(lats, lons,txt,fills);
+}
+
+/**
+* Get dates from the list provided in pIn and put them in Select.
+* then return the fist date.
+*
+*/
+function getDates(pIn) {
+ var html = "<option value='na'>--Select--</option>";
+ var c = 0;
+ var ret = 0;
+ for (var d in pIn ) {
+ var val = d.replace('"','');
+ if ( c === 0 ) { ret = val;};
+ html += "<option value='" + d + "'>" + d + "</option>";
+ dates[c] = val;
+ c++;
+ }
+ $('#date').html(html);
+ return ret;
+}
+
+/**
+* Map - pass argumets to build map as specified Lat/Lon and zoom level
+* String lat - Latitude
+* String lon - Longitude
+* String zoom - Zoom Level (1-18)
+*
+*/
+function map(lat,lon,zoom){
+ var map = L.map('map').setView([lat,lon],zoom);
+ map.addControl(new L.control.scale());
+ L.tileLayer('http://localhost/tiles-light/{z}/{x}/{y}.png', {maxZoom:18}).addTo(map);
+ window.L=L;
+ window.map=map;
+}
+
+/**
+* points - pass argumets to points specified Lat/Lon. Text and color for point is also passed.
+* Input is either all singe values or all arrays.
+* String[] lat - Latitude
+* String[] lon - Longitude
+* String[] text - Single/Array of Text for points
+* String[] fill - Single/Array of Fill colors.
+*/
+function points(lat,lon,text,fill){
+ if(lat.length) {
+ for(i=0;i<lat.length;i++) {
+ pointLayer.addLayer(L.circleMarker([lat[i], lon[i]], {
+ radius:"5",
+ color: fill[i],
+ fillColor: fill[i],
+ fillOpacity: "0.5" }).bindPopup(text[i]));
+
+ /*
+ L.circleMarker([lat[i], lon[i]], {
+ radius:"5",
+ color: fill[i],
+ fillColor: fill[i],
+ fillOpacity: "0.5" }).addTo(map).bindPopup(text[i]);
+
+ */
+
+ }
+
+ } else {
+ L.circleMarker([lat, lon], {
+ radius:"5",
+ color:fill,
+ fillColor:fill,
+ fillOpacity: "0.5"
+ }).addTo(map).bindPopup(text);
+ }
+}
+
+/**
+* Get data from json file and creat return an object of data.
+* Returns json object.
+*
+**/
+function getData(){
+ $.getJSON( "./data.json", function( data ) {
+ return data;
+ });
+
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js
new file mode 100644
index 00000000..985fa434
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/angular-gridster.js
@@ -0,0 +1,2244 @@
+/*global define:true*/
+(function(root, factory) {
+
+ 'use strict';
+
+ if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(['angular'], factory);
+ } else if (typeof exports === 'object') {
+ // CommonJS
+ module.exports = factory(require('angular'));
+ } else {
+ // Browser, nothing "exported". Only registered as a module with angular.
+ factory(root.angular);
+ }
+}(this, function(angular) {
+
+ 'use strict';
+
+ var ie8 = false;
+
+ var getInternetExplorerVersion = function ()
+ // Returns the version of Internet Explorer >4 or
+ // undefined(indicating the use of another browser).
+ {
+ var isIE10 = (eval("/*@cc_on!@*/false") && document.documentMode === 10);
+ if (isIE10) {
+ return 10;
+ }
+ var v = 3,
+ div = document.createElement('div'),
+ all = div.getElementsByTagName('i');
+ do {
+ div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
+ } while (all[0]);
+ return v > 4 ? v : undefined;
+ };
+
+ var browserVersion = getInternetExplorerVersion();
+
+ if (browserVersion && browserVersion < 9) {
+ ie8 = true;
+ }
+
+ // This returned angular module 'gridster' is what is exported.
+ return angular.module('attGridsterLib', [])
+
+ .constant('gridsterConfig', {
+ columns: 6, // number of columns in the grid
+ pushing: true, // whether to push other items out of the way
+ floating: true, // whether to automatically float items up so they stack
+ swapping: true, // whether or not to have items switch places instead of push down if they are the same size
+ width: 'auto', // width of the grid. "auto" will expand the grid to its parent container
+ colWidth: 'auto', // width of grid columns. "auto" will divide the width of the grid evenly among the columns
+ rowHeight: 'match', // height of grid rows. 'match' will make it the same as the column width, a numeric value will be interpreted as pixels, '/2' is half the column width, '*5' is five times the column width, etc.
+ margins: [10, 10], // margins in between grid items
+ outerMargin: false,
+ isMobile: false, // toggle mobile view
+ mobileBreakPoint: 100, // width threshold to toggle mobile mode
+ mobileModeEnabled: true, // whether or not to toggle mobile mode when screen width is less than mobileBreakPoint
+ minColumns: 1, // minimum amount of columns the grid can scale down to
+ minRows: 1, // minimum amount of rows to show if the grid is empty
+ maxRows: 100, // maximum amount of rows in the grid
+ defaultSizeX: 1, // default width of an item in columns
+ defaultSizeY: 1, // default height of an item in rows
+ minSizeX: 1, // minimum column width of an item
+ maxSizeX: null, // maximum column width of an item
+ minSizeY: 1, // minumum row height of an item
+ maxSizeY: null, // maximum row height of an item
+ saveGridItemCalculatedHeightInMobile: false, // grid item height in mobile display. true- to use the calculated height by sizeY given
+ resizable: { // options to pass to resizable handler
+ enabled: false,
+ handles: ['s', 'e', 'n', 'w', 'se', 'ne', 'sw', 'nw']
+ },
+ draggable: { // options to pass to draggable handler
+ enabled: true,
+ scrollSensitivity: 20, // Distance in pixels from the edge of the viewport after which the viewport should scroll, relative to pointer
+ scrollSpeed: 15 // Speed at which the window should scroll once the mouse pointer gets within scrollSensitivity distance
+ }
+ })
+
+ .controller('GridsterCtrl', ['gridsterConfig', '$timeout',
+ function(gridsterConfig, $timeout) {
+
+ var gridster = this;
+
+ /**
+ * Create options from gridsterConfig constant
+ */
+ angular.extend(this, gridsterConfig);
+
+ this.resizable = angular.extend({}, gridsterConfig.resizable || {});
+ this.draggable = angular.extend({}, gridsterConfig.draggable || {});
+
+ var flag = false;
+ this.layoutChanged = function() {
+ if (flag) {
+ return;
+ }
+ flag = true;
+ $timeout(function() {
+ flag = false;
+ if (gridster.loaded) {
+ gridster.floatItemsUp();
+ }
+ gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);
+ }, 30);
+ };
+
+ /**
+ * A positional array of the items in the grid
+ */
+ this.grid = [];
+
+ /**
+ * Clean up after yourself
+ */
+ this.destroy = function() {
+ // empty the grid to cut back on the possibility
+ // of circular references
+ if (this.grid) {
+ this.grid = [];
+ }
+ this.$element = null;
+ };
+
+ /**
+ * Overrides default options
+ *
+ * @param {Object} options The options to override
+ */
+ this.setOptions = function(options) {
+ if (!options) {
+ return;
+ }
+
+ options = angular.extend({}, options);
+
+ // all this to avoid using jQuery...
+ if (options.draggable) {
+ angular.extend(this.draggable, options.draggable);
+ delete(options.draggable);
+ }
+ if (options.resizable) {
+ angular.extend(this.resizable, options.resizable);
+ delete(options.resizable);
+ }
+
+ angular.extend(this, options);
+
+ if (!this.margins || this.margins.length !== 2) {
+ this.margins = [0, 0];
+ } else {
+ for (var x = 0, l = this.margins.length; x < l; ++x) {
+ this.margins[x] = parseInt(this.margins[x], 10);
+ if (isNaN(this.margins[x])) {
+ this.margins[x] = 0;
+ }
+ }
+ }
+ };
+
+ /**
+ * Check if item can occupy a specified position in the grid
+ *
+ * @param {Object} item The item in question
+ * @param {Number} row The row index
+ * @param {Number} column The column index
+ * @returns {Boolean} True if if item fits
+ */
+ this.canItemOccupy = function(item, row, column) {
+ return row > -1 && column > -1 && item.sizeX + column <= this.columns && item.sizeY + row <= this.maxRows;
+ };
+
+ /**
+ * Set the item in the first suitable position
+ *
+ * @param {Object} item The item to insert
+ */
+ this.autoSetItemPosition = function(item) {
+ // walk through each row and column looking for a place it will fit
+ for (var rowIndex = 0; rowIndex < this.maxRows; ++rowIndex) {
+ for (var colIndex = 0; colIndex < this.columns; ++colIndex) {
+ // only insert if position is not already taken and it can fit
+ var items = this.getItems(rowIndex, colIndex, item.sizeX, item.sizeY, item);
+ if (items.length === 0 && this.canItemOccupy(item, rowIndex, colIndex)) {
+ this.putItem(item, rowIndex, colIndex);
+ return;
+ }
+ }
+ }
+ throw new Error('Unable to place item!');
+ };
+
+ /**
+ * Gets items at a specific coordinate
+ *
+ * @param {Number} row
+ * @param {Number} column
+ * @param {Number} sizeX
+ * @param {Number} sizeY
+ * @param {Array} excludeItems An array of items to exclude from selection
+ * @returns {Array} Items that match the criteria
+ */
+ this.getItems = function(row, column, sizeX, sizeY, excludeItems) {
+ var items = [];
+ if (!sizeX || !sizeY) {
+ sizeX = sizeY = 1;
+ }
+ if (excludeItems && !(excludeItems instanceof Array)) {
+ excludeItems = [excludeItems];
+ }
+ for (var h = 0; h < sizeY; ++h) {
+ for (var w = 0; w < sizeX; ++w) {
+ var item = this.getItem(row + h, column + w, excludeItems);
+ if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && items.indexOf(item) === -1) {
+ items.push(item);
+ }
+ }
+ }
+ return items;
+ };
+
+ /**
+ * @param {Array} items
+ * @returns {Object} An item that represents the bounding box of the items
+ */
+ this.getBoundingBox = function(items) {
+
+ if (items.length === 0) {
+ return null;
+ }
+ if (items.length === 1) {
+ return {
+ row: items[0].row,
+ col: items[0].col,
+ sizeY: items[0].sizeY,
+ sizeX: items[0].sizeX
+ };
+ }
+
+ var maxRow = 0;
+ var maxCol = 0;
+ var minRow = 9999;
+ var minCol = 9999;
+
+ for (var i = 0, l = items.length; i < l; ++i) {
+ var item = items[i];
+ minRow = Math.min(item.row, minRow);
+ minCol = Math.min(item.col, minCol);
+ maxRow = Math.max(item.row + item.sizeY, maxRow);
+ maxCol = Math.max(item.col + item.sizeX, maxCol);
+ }
+
+ return {
+ row: minRow,
+ col: minCol,
+ sizeY: maxRow - minRow,
+ sizeX: maxCol - minCol
+ };
+ };
+
+
+ /**
+ * Removes an item from the grid
+ *
+ * @param {Object} item
+ */
+ this.removeItem = function(item) {
+ for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ var index = columns.indexOf(item);
+ if (index !== -1) {
+ columns[index] = null;
+ break;
+ }
+ }
+ this.layoutChanged();
+ };
+
+ /**
+ * Returns the item at a specified coordinate
+ *
+ * @param {Number} row
+ * @param {Number} column
+ * @param {Array} excludeItems Items to exclude from selection
+ * @returns {Object} The matched item or null
+ */
+ this.getItem = function(row, column, excludeItems) {
+ if (excludeItems && !(excludeItems instanceof Array)) {
+ excludeItems = [excludeItems];
+ }
+ var sizeY = 1;
+ while (row > -1) {
+ var sizeX = 1,
+ col = column;
+ while (col > -1) {
+ var items = this.grid[row];
+ if (items) {
+ var item = items[col];
+ if (item && (!excludeItems || excludeItems.indexOf(item) === -1) && item.sizeX >= sizeX && item.sizeY >= sizeY) {
+ return item;
+ }
+ }
+ ++sizeX;
+ --col;
+ }
+ --row;
+ ++sizeY;
+ }
+ return null;
+ };
+
+ /**
+ * Insert an array of items into the grid
+ *
+ * @param {Array} items An array of items to insert
+ */
+ this.putItems = function(items) {
+ for (var i = 0, l = items.length; i < l; ++i) {
+ this.putItem(items[i]);
+ }
+ };
+
+ /**
+ * Insert a single item into the grid
+ *
+ * @param {Object} item The item to insert
+ * @param {Number} row (Optional) Specifies the items row index
+ * @param {Number} column (Optional) Specifies the items column index
+ * @param {Array} ignoreItems
+ */
+ this.putItem = function(item, row, column, ignoreItems) {
+ // auto place item if no row specified
+ if (typeof row === 'undefined' || row === null) {
+ row = item.row;
+ column = item.col;
+ if (typeof row === 'undefined' || row === null) {
+ this.autoSetItemPosition(item);
+ return;
+ }
+ }
+
+ // keep item within allowed bounds
+ if (!this.canItemOccupy(item, row, column)) {
+ column = Math.min(this.columns - item.sizeX, Math.max(0, column));
+ row = Math.min(this.maxRows - item.sizeY, Math.max(0, row));
+ }
+
+ // check if item is already in grid
+ if (item.oldRow !== null && typeof item.oldRow !== 'undefined') {
+ var samePosition = item.oldRow === row && item.oldColumn === column;
+ var inGrid = this.grid[row] && this.grid[row][column] === item;
+ if (samePosition && inGrid) {
+ item.row = row;
+ item.col = column;
+ return;
+ } else {
+ // remove from old position
+ var oldRow = this.grid[item.oldRow];
+ if (oldRow && oldRow[item.oldColumn] === item) {
+ delete oldRow[item.oldColumn];
+ }
+ }
+ }
+
+ item.oldRow = item.row = row;
+ item.oldColumn = item.col = column;
+
+ this.moveOverlappingItems(item, ignoreItems);
+
+ if (!this.grid[row]) {
+ this.grid[row] = [];
+ }
+ this.grid[row][column] = item;
+
+ if (this.movingItem === item) {
+ this.floatItemUp(item);
+ }
+ this.layoutChanged();
+ };
+
+ /**
+ * Trade row and column if item1 with item2
+ *
+ * @param {Object} item1
+ * @param {Object} item2
+ */
+ this.swapItems = function(item1, item2) {
+ this.grid[item1.row][item1.col] = item2;
+ this.grid[item2.row][item2.col] = item1;
+
+ var item1Row = item1.row;
+ var item1Col = item1.col;
+ item1.row = item2.row;
+ item1.col = item2.col;
+ item2.row = item1Row;
+ item2.col = item1Col;
+ };
+
+ /**
+ * Prevents items from being overlapped
+ *
+ * @param {Object} item The item that should remain
+ * @param {Array} ignoreItems
+ */
+ this.moveOverlappingItems = function(item, ignoreItems) {
+ // don't move item, so ignore it
+ if (!ignoreItems) {
+ ignoreItems = [item];
+ } else if (ignoreItems.indexOf(item) === -1) {
+ ignoreItems = ignoreItems.slice(0);
+ ignoreItems.push(item);
+ }
+
+ // get the items in the space occupied by the item's coordinates
+ var overlappingItems = this.getItems(
+ item.row,
+ item.col,
+ item.sizeX,
+ item.sizeY,
+ ignoreItems
+ );
+ this.moveItemsDown(overlappingItems, item.row + item.sizeY, ignoreItems);
+ };
+
+ /**
+ * Moves an array of items to a specified row
+ *
+ * @param {Array} items The items to move
+ * @param {Number} newRow The target row
+ * @param {Array} ignoreItems
+ */
+ this.moveItemsDown = function(items, newRow, ignoreItems) {
+ if (!items || items.length === 0) {
+ return;
+ }
+ items.sort(function(a, b) {
+ return a.row - b.row;
+ });
+
+ ignoreItems = ignoreItems ? ignoreItems.slice(0) : [];
+ var topRows = {},
+ item, i, l;
+
+ // calculate the top rows in each column
+ for (i = 0, l = items.length; i < l; ++i) {
+ item = items[i];
+ var topRow = topRows[item.col];
+ if (typeof topRow === 'undefined' || item.row < topRow) {
+ topRows[item.col] = item.row;
+ }
+ }
+
+ // move each item down from the top row in its column to the row
+ for (i = 0, l = items.length; i < l; ++i) {
+ item = items[i];
+ var rowsToMove = newRow - topRows[item.col];
+ this.moveItemDown(item, item.row + rowsToMove, ignoreItems);
+ ignoreItems.push(item);
+ }
+ };
+
+ /**
+ * Moves an item down to a specified row
+ *
+ * @param {Object} item The item to move
+ * @param {Number} newRow The target row
+ * @param {Array} ignoreItems
+ */
+ this.moveItemDown = function(item, newRow, ignoreItems) {
+ if (item.row >= newRow) {
+ return;
+ }
+ while (item.row < newRow) {
+ ++item.row;
+ this.moveOverlappingItems(item, ignoreItems);
+ }
+ this.putItem(item, item.row, item.col, ignoreItems);
+ };
+
+ /**
+ * Moves all items up as much as possible
+ */
+ this.floatItemsUp = function() {
+ if (this.floating === false) {
+ return;
+ }
+ for (var rowIndex = 0, l = this.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ var item = columns[colIndex];
+ if (item) {
+ this.floatItemUp(item);
+ }
+ }
+ }
+ };
+
+ /**
+ * Float an item up to the most suitable row
+ *
+ * @param {Object} item The item to move
+ */
+ this.floatItemUp = function(item) {
+ if (this.floating === false) {
+ return;
+ }
+ var colIndex = item.col,
+ sizeY = item.sizeY,
+ sizeX = item.sizeX,
+ bestRow = null,
+ bestColumn = null,
+ rowIndex = item.row - 1;
+
+ while (rowIndex > -1) {
+ var items = this.getItems(rowIndex, colIndex, sizeX, sizeY, item);
+ if (items.length !== 0) {
+ break;
+ }
+ bestRow = rowIndex;
+ bestColumn = colIndex;
+ --rowIndex;
+ }
+ if (bestRow !== null) {
+ this.putItem(item, bestRow, bestColumn);
+ }
+ };
+
+ /**
+ * Update gridsters height
+ *
+ * @param {Number} plus (Optional) Additional height to add
+ */
+ this.updateHeight = function(plus) {
+ var maxHeight = this.minRows;
+ plus = plus || 0;
+ for (var rowIndex = this.grid.length; rowIndex >= 0; --rowIndex) {
+ var columns = this.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ if (columns[colIndex]) {
+ maxHeight = Math.max(maxHeight, rowIndex + plus + columns[colIndex].sizeY);
+ }
+ }
+ }
+ this.gridHeight = this.maxRows - maxHeight > 0 ? Math.min(this.maxRows, maxHeight) : Math.max(this.maxRows, maxHeight);
+ };
+
+ /**
+ * Returns the number of rows that will fit in given amount of pixels
+ *
+ * @param {Number} pixels
+ * @param {Boolean} ceilOrFloor (Optional) Determines rounding method
+ */
+ this.pixelsToRows = function(pixels, ceilOrFloor) {
+ if (ceilOrFloor === true) {
+ return Math.ceil(pixels / this.curRowHeight);
+ } else if (ceilOrFloor === false) {
+ return Math.floor(pixels / this.curRowHeight);
+ }
+
+ return Math.round(pixels / this.curRowHeight);
+ };
+
+ /**
+ * Returns the number of columns that will fit in a given amount of pixels
+ *
+ * @param {Number} pixels
+ * @param {Boolean} ceilOrFloor (Optional) Determines rounding method
+ * @returns {Number} The number of columns
+ */
+ this.pixelsToColumns = function(pixels, ceilOrFloor) {
+ if (ceilOrFloor === true) {
+ return Math.ceil(pixels / this.curColWidth);
+ } else if (ceilOrFloor === false) {
+ return Math.floor(pixels / this.curColWidth);
+ }
+
+ return Math.round(pixels / this.curColWidth);
+ };
+ }
+ ])
+
+ .directive('gridsterPreview', function() {
+ return {
+ replace: true,
+ scope: true,
+ require: '^gridster',
+ template: '<div ng-style="previewStyle()" class="gridster-item gridster-preview-holder"></div>',
+ link: function(scope, $el, attrs, gridster) {
+
+ /**
+ * @returns {Object} style object for preview element
+ */
+ scope.previewStyle = function() {
+
+ if (!gridster.movingItem) {
+ return {
+ display: 'none'
+ };
+ }
+
+ return {
+ display: 'block',
+ height: (gridster.movingItem.sizeY * gridster.curRowHeight - gridster.margins[0]) + 'px',
+ width: (gridster.movingItem.sizeX * gridster.curColWidth - gridster.margins[1]) + 'px',
+ top: (gridster.movingItem.row * gridster.curRowHeight + (gridster.outerMargin ? gridster.margins[0] : 0)) + 'px',
+ left: (gridster.movingItem.col * gridster.curColWidth + (gridster.outerMargin ? gridster.margins[1] : 0)) + 'px'
+ };
+ };
+ }
+ };
+ })
+
+ /**
+ * The gridster directive
+ *
+ * @param {Function} $timeout
+ * @param {Object} $window
+ * @param {Object} $rootScope
+ * @param {Function} gridsterDebounce
+ */
+ .directive('gridster', ['$timeout', '$window', '$rootScope', 'gridsterDebounce',
+ function($timeout, $window, $rootScope, gridsterDebounce) {
+ return {
+ scope: true,
+ restrict: 'EAC',
+ controller: 'GridsterCtrl',
+ controllerAs: 'gridster',
+ compile: function($tplElem) {
+
+ $tplElem.prepend('<div ng-if="gridster.movingItem" gridster-preview></div>');
+
+ return function(scope, $elem, attrs, gridster) {
+ gridster.loaded = false;
+
+ gridster.$element = $elem;
+
+ scope.gridster = gridster;
+
+ $elem.addClass('gridster');
+
+ var isVisible = function(ele) {
+ return ele.style.visibility !== 'hidden' && ele.style.display !== 'none';
+ };
+
+ function refresh(config) {
+ gridster.setOptions(config);
+
+ if (!isVisible($elem[0])) {
+ return;
+ }
+
+ // resolve "auto" & "match" values
+ if (gridster.width === 'auto') {
+ gridster.curWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+ } else {
+ gridster.curWidth = gridster.width;
+ }
+
+ if (gridster.colWidth === 'auto') {
+ gridster.curColWidth = (gridster.curWidth + (gridster.outerMargin ? -gridster.margins[1] : gridster.margins[1])) / gridster.columns;
+ } else {
+ gridster.curColWidth = gridster.colWidth;
+ }
+
+ gridster.curRowHeight = gridster.rowHeight;
+ if (typeof gridster.rowHeight === 'string') {
+ if (gridster.rowHeight === 'match') {
+ gridster.curRowHeight = Math.round(gridster.curColWidth);
+ } else if (gridster.rowHeight.indexOf('*') !== -1) {
+ gridster.curRowHeight = Math.round(gridster.curColWidth * gridster.rowHeight.replace('*', '').replace(' ', ''));
+ } else if (gridster.rowHeight.indexOf('/') !== -1) {
+ gridster.curRowHeight = Math.round(gridster.curColWidth / gridster.rowHeight.replace('/', '').replace(' ', ''));
+ }
+ }
+
+ gridster.isMobile = gridster.mobileModeEnabled && gridster.curWidth <= gridster.mobileBreakPoint;
+
+ // loop through all items and reset their CSS
+ for (var rowIndex = 0, l = gridster.grid.length; rowIndex < l; ++rowIndex) {
+ var columns = gridster.grid[rowIndex];
+ if (!columns) {
+ continue;
+ }
+
+ for (var colIndex = 0, len = columns.length; colIndex < len; ++colIndex) {
+ if (columns[colIndex]) {
+ var item = columns[colIndex];
+ item.setElementPosition();
+ item.setElementSizeY();
+ item.setElementSizeX();
+ }
+ }
+ }
+
+ updateHeight();
+ }
+
+ var optionsKey = attrs.gridster;
+ if (optionsKey) {
+ scope.$parent.$watch(optionsKey, function(newConfig) {
+ refresh(newConfig);
+ }, true);
+ } else {
+ refresh({});
+ }
+
+ scope.$watch(function() {
+ return gridster.loaded;
+ }, function() {
+ if (gridster.loaded) {
+ $elem.addClass('gridster-loaded');
+ } else {
+ $elem.removeClass('gridster-loaded');
+ }
+ });
+
+ scope.$watch(function() {
+ return gridster.isMobile;
+ }, function() {
+ if (gridster.isMobile) {
+ $elem.addClass('gridster-mobile').removeClass('gridster-desktop');
+ } else {
+ $elem.removeClass('gridster-mobile').addClass('gridster-desktop');
+ }
+ $rootScope.$broadcast('gridster-mobile-changed', gridster);
+ });
+
+ scope.$watch(function() {
+ return gridster.draggable;
+ }, function() {
+ $rootScope.$broadcast('gridster-draggable-changed', gridster);
+ }, true);
+
+ scope.$watch(function() {
+ return gridster.resizable;
+ }, function() {
+ $rootScope.$broadcast('gridster-resizable-changed', gridster);
+ }, true);
+
+ function updateHeight() {
+ if(gridster.gridHeight){ //need to put this check, otherwise fail in IE8
+ $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');
+ }
+ }
+
+ scope.$watch(function() {
+ return gridster.gridHeight;
+ }, updateHeight);
+
+ scope.$watch(function() {
+ return gridster.movingItem;
+ }, function() {
+ gridster.updateHeight(gridster.movingItem ? gridster.movingItem.sizeY : 0);
+ });
+
+ var prevWidth = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+
+ var resize = function() {
+ var width = $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+
+ if (!width || width === prevWidth || gridster.movingItem) {
+ return;
+ }
+ prevWidth = width;
+
+ if (gridster.loaded) {
+ $elem.removeClass('gridster-loaded');
+ }
+
+ refresh();
+
+ if (gridster.loaded) {
+ $elem.addClass('gridster-loaded');
+ }
+
+ $rootScope.$broadcast('gridster-resized', [width, $elem[0].offsetHeight], gridster);
+ };
+
+ // track element width changes any way we can
+ var onResize = gridsterDebounce(function onResize() {
+ resize();
+ $timeout(function() {
+ scope.$apply();
+ });
+ }, 100);
+
+ scope.$watch(function() {
+ return isVisible($elem[0]);
+ }, onResize);
+
+ // see https://github.com/sdecima/javascript-detect-element-resize
+ if (typeof window.addResizeListener === 'function') {
+ window.addResizeListener($elem[0], onResize);
+ } else {
+ scope.$watch(function() {
+ return $elem[0].offsetWidth || parseInt($elem.css('width'), 10);
+ }, resize);
+ }
+ var $win = angular.element($window);
+ $win.on('resize', onResize);
+
+ // be sure to cleanup
+ scope.$on('$destroy', function() {
+ gridster.destroy();
+ $win.off('resize', onResize);
+ if (typeof window.removeResizeListener === 'function') {
+ window.removeResizeListener($elem[0], onResize);
+ }
+ });
+
+ // allow a little time to place items before floating up
+ $timeout(function() {
+ scope.$watch('gridster.floating', function() {
+ gridster.floatItemsUp();
+ });
+ gridster.loaded = true;
+ }, 100);
+ };
+ }
+ };
+ }
+ ])
+
+ .controller('GridsterItemCtrl', function() {
+ this.$element = null;
+ this.gridster = null;
+ this.row = null;
+ this.col = null;
+ this.sizeX = null;
+ this.sizeY = null;
+ this.minSizeX = 0;
+ this.minSizeY = 0;
+ this.maxSizeX = null;
+ this.maxSizeY = null;
+
+ this.init = function($element, gridster) {
+ this.$element = $element;
+ this.gridster = gridster;
+ this.sizeX = gridster.defaultSizeX;
+ this.sizeY = gridster.defaultSizeY;
+ };
+
+ this.destroy = function() {
+ // set these to null to avoid the possibility of circular references
+ this.gridster = null;
+ this.$element = null;
+ };
+
+ /**
+ * Returns the items most important attributes
+ */
+ this.toJSON = function() {
+ return {
+ row: this.row,
+ col: this.col,
+ sizeY: this.sizeY,
+ sizeX: this.sizeX
+ };
+ };
+
+ this.isMoving = function() {
+ return this.gridster.movingItem === this;
+ };
+
+ /**
+ * Set the items position
+ *
+ * @param {Number} row
+ * @param {Number} column
+ */
+ this.setPosition = function(row, column) {
+ this.gridster.putItem(this, row, column);
+
+ if (!this.isMoving()) {
+ this.setElementPosition();
+ }
+ };
+
+ /**
+ * Sets a specified size property
+ *
+ * @param {String} key Can be either "x" or "y"
+ * @param {Number} value The size amount
+ * @param {Boolean} preventMove
+ */
+ this.setSize = function(key, value, preventMove) {
+ key = key.toUpperCase();
+ var camelCase = 'size' + key,
+ titleCase = 'Size' + key;
+ if (value === '') {
+ return;
+ }
+ value = parseInt(value, 10);
+ if (isNaN(value) || value === 0) {
+ value = this.gridster['default' + titleCase];
+ }
+ var max = key === 'X' ? this.gridster.columns : this.gridster.maxRows;
+ if (this['max' + titleCase]) {
+ max = Math.min(this['max' + titleCase], max);
+ }
+ if (this.gridster['max' + titleCase]) {
+ max = Math.min(this.gridster['max' + titleCase], max);
+ }
+ if (key === 'X' && this.cols) {
+ max -= this.cols;
+ } else if (key === 'Y' && this.rows) {
+ max -= this.rows;
+ }
+
+ var min = 0;
+ if (this['min' + titleCase]) {
+ min = Math.max(this['min' + titleCase], min);
+ }
+ if (this.gridster['min' + titleCase]) {
+ min = Math.max(this.gridster['min' + titleCase], min);
+ }
+
+ value = Math.max(Math.min(value, max), min);
+
+ var changed = (this[camelCase] !== value || (this['old' + titleCase] && this['old' + titleCase] !== value));
+ this['old' + titleCase] = this[camelCase] = value;
+
+ if (!this.isMoving()) {
+ this['setElement' + titleCase]();
+ }
+ if (!preventMove && changed) {
+ this.gridster.moveOverlappingItems(this);
+ this.gridster.layoutChanged();
+ }
+
+ return changed;
+ };
+
+ /**
+ * Sets the items sizeY property
+ *
+ * @param {Number} rows
+ * @param {Boolean} preventMove
+ */
+ this.setSizeY = function(rows, preventMove) {
+ return this.setSize('Y', rows, preventMove);
+ };
+
+ /**
+ * Sets the items sizeX property
+ *
+ * @param {Number} columns
+ * @param {Boolean} preventMove
+ */
+ this.setSizeX = function(columns, preventMove) {
+ return this.setSize('X', columns, preventMove);
+ };
+
+ /**
+ * Sets an elements position on the page
+ */
+ this.setElementPosition = function() {
+ if (this.gridster.isMobile) {
+ this.$element.css({
+ marginLeft: this.gridster.margins[0] + 'px',
+ marginRight: this.gridster.margins[0] + 'px',
+ marginTop: this.gridster.margins[1] + 'px',
+ marginBottom: this.gridster.margins[1] + 'px',
+ top: '',
+ left: ''
+ });
+ } else {
+ this.$element.css({
+ margin: 0,
+ top: (this.row * this.gridster.curRowHeight + (this.gridster.outerMargin ? this.gridster.margins[0] : 0)) + 'px',
+ left: (this.col * this.gridster.curColWidth + (this.gridster.outerMargin ? this.gridster.margins[1] : 0)) + 'px'
+ });
+ }
+ };
+
+ /**
+ * Sets an elements height
+ */
+ this.setElementSizeY = function() {
+ if (this.gridster.isMobile && !this.gridster.saveGridItemCalculatedHeightInMobile) {
+ this.$element.css('height', '');
+ } else {
+ var computedHeight = (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]) + 'px';
+ //this.$element.css('height', computedHeight);
+ this.$element.attr('style', this.$element.attr('style') + '; ' + 'height: '+computedHeight+' !important;');
+ }
+ };
+
+ /**
+ * Sets an elements width
+ */
+ this.setElementSizeX = function() {
+ if (this.gridster.isMobile) {
+ this.$element.css('width', '');
+ } else {
+ this.$element.css('width', (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]) + 'px');
+ }
+ };
+
+ /**
+ * Gets an element's width
+ */
+ this.getElementSizeX = function() {
+ return (this.sizeX * this.gridster.curColWidth - this.gridster.margins[1]);
+ };
+
+ /**
+ * Gets an element's height
+ */
+ this.getElementSizeY = function() {
+ return (this.sizeY * this.gridster.curRowHeight - this.gridster.margins[0]);
+ };
+
+ })
+
+ .factory('GridsterTouch', [function() {
+ return function GridsterTouch(target, startEvent, moveEvent, endEvent) {
+ var lastXYById = {};
+
+ // Opera doesn't have Object.keys so we use this wrapper
+ var numberOfKeys = function(theObject) {
+ if (Object.keys) {
+ return Object.keys(theObject).length;
+ }
+
+ var n = 0,
+ key;
+ for (key in theObject) {
+ ++n;
+ }
+
+ return n;
+ };
+
+ // this calculates the delta needed to convert pageX/Y to offsetX/Y because offsetX/Y don't exist in the TouchEvent object or in Firefox's MouseEvent object
+ var computeDocumentToElementDelta = function(theElement) {
+ var elementLeft = 0;
+ var elementTop = 0;
+ var oldIEUserAgent = navigator.userAgent.match(/\bMSIE\b/);
+
+ for (var offsetElement = theElement; offsetElement != null; offsetElement = offsetElement.offsetParent) {
+ // the following is a major hack for versions of IE less than 8 to avoid an apparent problem on the IEBlog with double-counting the offsets
+ // this may not be a general solution to IE7's problem with offsetLeft/offsetParent
+ if (oldIEUserAgent &&
+ (!document.documentMode || document.documentMode < 8) &&
+ offsetElement.currentStyle.position === 'relative' && offsetElement.offsetParent && offsetElement.offsetParent.currentStyle.position === 'relative' && offsetElement.offsetLeft === offsetElement.offsetParent.offsetLeft) {
+ // add only the top
+ elementTop += offsetElement.offsetTop;
+ } else {
+ elementLeft += offsetElement.offsetLeft;
+ elementTop += offsetElement.offsetTop;
+ }
+ }
+
+ return {
+ x: elementLeft,
+ y: elementTop
+ };
+ };
+
+ // cache the delta from the document to our event target (reinitialized each mousedown/MSPointerDown/touchstart)
+ var documentToTargetDelta = computeDocumentToElementDelta(target);
+
+ // common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events
+ var doEvent = function(theEvtObj) {
+
+ if (theEvtObj.type === 'mousemove' && numberOfKeys(lastXYById) === 0) {
+ return;
+ }
+
+ var prevent = true;
+
+ var pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];
+
+ for (var i = 0; i < pointerList.length; ++i) {
+ var pointerObj = pointerList[i];
+ var pointerId = (typeof pointerObj.identifier !== 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId !== 'undefined') ? pointerObj.pointerId : 1;
+
+ // use the pageX/Y coordinates to compute target-relative coordinates when we have them (in ie < 9, we need to do a little work to put them there)
+ if (typeof pointerObj.pageX === 'undefined') {
+
+ // initialize assuming our source element is our target
+ if(!ie8){
+ pointerObj.pageX = pointerObj.offsetX + documentToTargetDelta.x;
+ pointerObj.pageY = pointerObj.offsetY + documentToTargetDelta.y;
+ }
+ else{
+ pointerObj.pageX = pointerObj.clientX;
+ pointerObj.pageY = pointerObj.clientY;
+ }
+
+ if (pointerObj.srcElement.offsetParent === target && document.documentMode && document.documentMode === 8 && pointerObj.type === 'mousedown') {
+ // source element is a child piece of VML, we're in IE8, and we've not called setCapture yet - add the origin of the source element
+ pointerObj.pageX += pointerObj.srcElement.offsetLeft;
+ pointerObj.pageY += pointerObj.srcElement.offsetTop;
+ } else if (pointerObj.srcElement !== target && !document.documentMode || document.documentMode < 8) {
+ // source element isn't the target (most likely it's a child piece of VML) and we're in a version of IE before IE8 -
+ // the offsetX/Y values are unpredictable so use the clientX/Y values and adjust by the scroll offsets of its parents
+ // to get the document-relative coordinates (the same as pageX/Y)
+ var sx = -2,
+ sy = -2; // adjust for old IE's 2-pixel border
+ for (var scrollElement = pointerObj.srcElement; scrollElement !== null; scrollElement = scrollElement.parentNode) {
+ sx += scrollElement.scrollLeft ? scrollElement.scrollLeft : 0;
+ sy += scrollElement.scrollTop ? scrollElement.scrollTop : 0;
+ }
+
+ pointerObj.pageX = pointerObj.clientX + sx;
+ pointerObj.pageY = pointerObj.clientY + sy;
+ }
+ }
+
+
+ var pageX = pointerObj.pageX;
+ var pageY = pointerObj.pageY;
+
+ if (theEvtObj.type.match(/(start|down)$/i)) {
+ // clause for processing MSPointerDown, touchstart, and mousedown
+
+ // refresh the document-to-target delta on start in case the target has moved relative to document
+ documentToTargetDelta = computeDocumentToElementDelta(target);
+
+ // protect against failing to get an up or end on this pointerId
+ if (lastXYById[pointerId]) {
+ if (endEvent) {
+ endEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ delete lastXYById[pointerId];
+ }
+
+ if (startEvent) {
+ if (prevent) {
+ prevent = startEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+ }
+
+ // init last page positions for this pointer
+ lastXYById[pointerId] = {
+ x: pageX,
+ y: pageY
+ };
+
+ // IE pointer model
+ if (target.msSetPointerCapture) {
+ target.msSetPointerCapture(pointerId);
+ } else if (theEvtObj.type === 'mousedown' && numberOfKeys(lastXYById) === 1) {
+ if (useSetReleaseCapture) {
+ target.setCapture(true);
+ } else {
+ document.addEventListener('mousemove', doEvent, false);
+ document.addEventListener('mouseup', doEvent, false);
+ }
+ }
+ } else if (theEvtObj.type.match(/move$/i)) {
+ // clause handles mousemove, MSPointerMove, and touchmove
+
+ if (lastXYById[pointerId] && !(lastXYById[pointerId].x === pageX && lastXYById[pointerId].y === pageY)) {
+ // only extend if the pointer is down and it's not the same as the last point
+
+ if (moveEvent && prevent) {
+ prevent = moveEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ // update last page positions for this pointer
+ lastXYById[pointerId].x = pageX;
+ lastXYById[pointerId].y = pageY;
+ }
+ } else if (lastXYById[pointerId] && theEvtObj.type.match(/(up|end|cancel)$/i)) {
+ // clause handles up/end/cancel
+
+ if (endEvent && prevent) {
+ prevent = endEvent({
+ target: theEvtObj.target,
+ which: theEvtObj.which,
+ pointerId: pointerId,
+ pageX: pageX,
+ pageY: pageY
+ });
+ }
+
+ // delete last page positions for this pointer
+ delete lastXYById[pointerId];
+
+ // in the Microsoft pointer model, release the capture for this pointer
+ // in the mouse model, release the capture or remove document-level event handlers if there are no down points
+ // nothing is required for the iOS touch model because capture is implied on touchstart
+ if (target.msReleasePointerCapture) {
+ target.msReleasePointerCapture(pointerId);
+ } else if (theEvtObj.type === 'mouseup' && numberOfKeys(lastXYById) === 0) {
+ if (useSetReleaseCapture) {
+ target.releaseCapture();
+ } else {
+ document.removeEventListener('mousemove', doEvent, false);
+ document.removeEventListener('mouseup', doEvent, false);
+ }
+ }
+ }
+ }
+
+ if (prevent) {
+ if (theEvtObj.preventDefault) {
+ theEvtObj.preventDefault();
+ }
+
+ if (theEvtObj.preventManipulation) {
+ theEvtObj.preventManipulation();
+ }
+
+ if (theEvtObj.preventMouseEvent) {
+ theEvtObj.preventMouseEvent();
+ }
+ }
+ };
+
+ var useSetReleaseCapture = false;
+ // saving the settings for contentZooming and touchaction before activation
+ var contentZooming, msTouchAction;
+
+ this.enable = function() {
+
+ if (window.navigator.msPointerEnabled) {
+ // Microsoft pointer model
+ target.addEventListener('MSPointerDown', doEvent, false);
+ target.addEventListener('MSPointerMove', doEvent, false);
+ target.addEventListener('MSPointerUp', doEvent, false);
+ target.addEventListener('MSPointerCancel', doEvent, false);
+
+ // css way to prevent panning in our target area
+ if (typeof target.style.msContentZooming !== 'undefined') {
+ contentZooming = target.style.msContentZooming;
+ target.style.msContentZooming = 'none';
+ }
+
+ // new in Windows Consumer Preview: css way to prevent all built-in touch actions on our target
+ // without this, you cannot touch draw on the element because IE will intercept the touch events
+ if (typeof target.style.msTouchAction !== 'undefined') {
+ msTouchAction = target.style.msTouchAction;
+ target.style.msTouchAction = 'none';
+ }
+ } else if (target.addEventListener) {
+ // iOS touch model
+ target.addEventListener('touchstart', doEvent, false);
+ target.addEventListener('touchmove', doEvent, false);
+ target.addEventListener('touchend', doEvent, false);
+ target.addEventListener('touchcancel', doEvent, false);
+
+ // mouse model
+ target.addEventListener('mousedown', doEvent, false);
+
+ // mouse model with capture
+ // rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target
+ if (target.setCapture && !window.navigator.userAgent.match(/\bGecko\b/)) {
+ useSetReleaseCapture = true;
+
+ target.addEventListener('mousemove', doEvent, false);
+ target.addEventListener('mouseup', doEvent, false);
+ }
+ } else if (target.attachEvent && target.setCapture) {
+ // legacy IE mode - mouse with capture
+ useSetReleaseCapture = true;
+ target.attachEvent('onmousedown', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ target.attachEvent('onmousemove', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ target.attachEvent('onmouseup', function() {
+ doEvent(window.event);
+ window.event.returnValue = false;
+ return false;
+ });
+ }
+ };
+
+ this.disable = function() {
+ if (window.navigator.msPointerEnabled) {
+ // Microsoft pointer model
+ target.removeEventListener('MSPointerDown', doEvent, false);
+ target.removeEventListener('MSPointerMove', doEvent, false);
+ target.removeEventListener('MSPointerUp', doEvent, false);
+ target.removeEventListener('MSPointerCancel', doEvent, false);
+
+ // reset zooming to saved value
+ if (contentZooming) {
+ target.style.msContentZooming = contentZooming;
+ }
+
+ // reset touch action setting
+ if (msTouchAction) {
+ target.style.msTouchAction = msTouchAction;
+ }
+ } else if (target.removeEventListener) {
+ // iOS touch model
+ target.removeEventListener('touchstart', doEvent, false);
+ target.removeEventListener('touchmove', doEvent, false);
+ target.removeEventListener('touchend', doEvent, false);
+ target.removeEventListener('touchcancel', doEvent, false);
+
+ // mouse model
+ target.removeEventListener('mousedown', doEvent, false);
+
+ // mouse model with capture
+ // rejecting gecko because, unlike ie, firefox does not send events to target when the mouse is outside target
+ if (target.setCapture && !window.navigator.userAgent.match(/\bGecko\b/)) {
+ useSetReleaseCapture = true;
+
+ target.removeEventListener('mousemove', doEvent, false);
+ target.removeEventListener('mouseup', doEvent, false);
+ }
+ } else if (target.detachEvent && target.setCapture) {
+ // legacy IE mode - mouse with capture
+ useSetReleaseCapture = true;
+ target.detachEvent('onmousedown');
+ target.detachEvent('onmousemove');
+ target.detachEvent('onmouseup');
+ }
+ };
+
+ return this;
+ };
+ }])
+
+ .factory('GridsterDraggable', ['$document', '$timeout', '$window', 'GridsterTouch',
+ function($document, $timeout, $window, GridsterTouch) {
+ function GridsterDraggable($el, scope, gridster, item, itemOptions) {
+
+ var elmX, elmY, elmW, elmH,
+
+ mouseX = 0,
+ mouseY = 0,
+ lastMouseX = 0,
+ lastMouseY = 0,
+ mOffX = 0,
+ mOffY = 0,
+
+ minTop = 0,
+ maxTop = 9999,
+ minLeft = 0,
+ realdocument = $document[0];
+
+ var originalCol, originalRow;
+ var inputTags = ['select', 'input', 'textarea', 'button'];
+
+ var gridsterItemDragElement = $el[0].querySelector('[gridster-item-drag]');
+ //console.log(gridsterItemDragElement);
+ var isDraggableAreaDefined = gridsterItemDragElement?true:false;
+ //console.log(isDraggableAreaDefined);
+
+ function mouseDown(e) {
+
+ if(ie8){
+ e.target = window.event.srcElement;
+ e.which = window.event.button;
+ }
+
+ if(isDraggableAreaDefined && (!gridsterItemDragElement.contains(e.target))){
+ return false;
+ }
+
+ if (inputTags.indexOf(e.target.nodeName.toLowerCase()) !== -1) {
+ return false;
+ }
+
+ var $target = angular.element(e.target);
+
+ // exit, if a resize handle was hit
+ if ($target.hasClass('gridster-item-resizable-handler')) {
+ return false;
+ }
+
+ // exit, if the target has it's own click event
+ if ($target.attr('onclick') || $target.attr('ng-click')) {
+ return false;
+ }
+
+ // only works if you have jQuery
+ if ($target.closest && $target.closest('.gridster-no-drag').length) {
+ return false;
+ }
+
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+
+ lastMouseX = e.pageX;
+ lastMouseY = e.pageY;
+
+ elmX = parseInt($el.css('left'), 10);
+ elmY = parseInt($el.css('top'), 10);
+ elmW = $el[0].offsetWidth;
+ elmH = $el[0].offsetHeight;
+
+ originalCol = item.col;
+ originalRow = item.row;
+
+ dragStart(e);
+
+ return true;
+ }
+
+ function mouseMove(e) {
+ if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {
+ return false;
+ }
+
+ var maxLeft = gridster.curWidth - 1;
+
+ // Get the current mouse position.
+ mouseX = e.pageX;
+ mouseY = e.pageY;
+
+ // Get the deltas
+ var diffX = mouseX - lastMouseX + mOffX;
+ var diffY = mouseY - lastMouseY + mOffY;
+ mOffX = mOffY = 0;
+
+ // Update last processed mouse positions.
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+
+ var dX = diffX,
+ dY = diffY;
+ if (elmX + dX < minLeft) {
+ diffX = minLeft - elmX;
+ mOffX = dX - diffX;
+ } else if (elmX + elmW + dX > maxLeft) {
+ diffX = maxLeft - elmX - elmW;
+ mOffX = dX - diffX;
+ }
+
+ if (elmY + dY < minTop) {
+ diffY = minTop - elmY;
+ mOffY = dY - diffY;
+ } else if (elmY + elmH + dY > maxTop) {
+ diffY = maxTop - elmY - elmH;
+ mOffY = dY - diffY;
+ }
+ elmX += diffX;
+ elmY += diffY;
+
+ // set new position
+ $el.css({
+ 'top': elmY + 'px',
+ 'left': elmX + 'px'
+ });
+
+ drag(e);
+
+ return true;
+ }
+
+ function mouseUp(e) {
+ if (!$el.hasClass('gridster-item-moving') || $el.hasClass('gridster-item-resizing')) {
+ return false;
+ }
+
+ mOffX = mOffY = 0;
+
+ dragStop(e);
+
+ return true;
+ }
+
+ function dragStart(event) {
+ $el.addClass('gridster-item-moving');
+ gridster.movingItem = item;
+
+ gridster.updateHeight(item.sizeY);
+ scope.$apply(function() {
+ if (gridster.draggable && gridster.draggable.start) {
+ gridster.draggable.start(event, $el, itemOptions);
+ }
+ });
+ }
+
+ function drag(event) {
+ var oldRow = item.row,
+ oldCol = item.col,
+ hasCallback = gridster.draggable && gridster.draggable.drag,
+ scrollSensitivity = gridster.draggable.scrollSensitivity,
+ scrollSpeed = gridster.draggable.scrollSpeed;
+
+ var row = gridster.pixelsToRows(elmY);
+ var col = gridster.pixelsToColumns(elmX);
+
+ var itemsInTheWay = gridster.getItems(row, col, item.sizeX, item.sizeY, item);
+ var hasItemsInTheWay = itemsInTheWay.length !== 0;
+
+ if (gridster.swapping === true && hasItemsInTheWay) {
+ var boundingBoxItem = gridster.getBoundingBox(itemsInTheWay),
+ sameSize = boundingBoxItem.sizeX === item.sizeX && boundingBoxItem.sizeY === item.sizeY,
+ sameRow = boundingBoxItem.row === oldRow,
+ sameCol = boundingBoxItem.col === oldCol,
+ samePosition = boundingBoxItem.row === row && boundingBoxItem.col === col,
+ inline = sameRow || sameCol;
+
+ if (sameSize && itemsInTheWay.length === 1) {
+ if (samePosition) {
+ gridster.swapItems(item, itemsInTheWay[0]);
+ } else if (inline) {
+ return;
+ }
+ } else if (boundingBoxItem.sizeX <= item.sizeX && boundingBoxItem.sizeY <= item.sizeY && inline) {
+ var emptyRow = item.row <= row ? item.row : row + item.sizeY,
+ emptyCol = item.col <= col ? item.col : col + item.sizeX,
+ rowOffset = emptyRow - boundingBoxItem.row,
+ colOffset = emptyCol - boundingBoxItem.col;
+
+ for (var i = 0, l = itemsInTheWay.length; i < l; ++i) {
+ var itemInTheWay = itemsInTheWay[i];
+
+ var itemsInFreeSpace = gridster.getItems(
+ itemInTheWay.row + rowOffset,
+ itemInTheWay.col + colOffset,
+ itemInTheWay.sizeX,
+ itemInTheWay.sizeY,
+ item
+ );
+
+ if (itemsInFreeSpace.length === 0) {
+ gridster.putItem(itemInTheWay, itemInTheWay.row + rowOffset, itemInTheWay.col + colOffset);
+ }
+ }
+ }
+ }
+
+ if (gridster.pushing !== false || !hasItemsInTheWay) {
+ item.row = row;
+ item.col = col;
+ }
+
+ if(($window.navigator.appName === 'Microsoft Internet Explorer' && !ie8) || $window.navigator.userAgent.indexOf("Firefox")!==-1){
+ if (event.pageY - realdocument.documentElement.scrollTop < scrollSensitivity) {
+ realdocument.documentElement.scrollTop = realdocument.documentElement.scrollTop - scrollSpeed;
+ } else if ($window.innerHeight - (event.pageY - realdocument.documentElement.scrollTop) < scrollSensitivity) {
+ realdocument.documentElement.scrollTop = realdocument.documentElement.scrollTop + scrollSpeed;
+ }
+ }
+ else{
+ if (event.pageY - realdocument.body.scrollTop < scrollSensitivity) {
+ realdocument.body.scrollTop = realdocument.body.scrollTop - scrollSpeed;
+ } else if ($window.innerHeight - (event.pageY - realdocument.body.scrollTop) < scrollSensitivity) {
+ realdocument.body.scrollTop = realdocument.body.scrollTop + scrollSpeed;
+ }
+ }
+
+
+
+ if (event.pageX - realdocument.body.scrollLeft < scrollSensitivity) {
+ realdocument.body.scrollLeft = realdocument.body.scrollLeft - scrollSpeed;
+ } else if ($window.innerWidth - (event.pageX - realdocument.body.scrollLeft) < scrollSensitivity) {
+ realdocument.body.scrollLeft = realdocument.body.scrollLeft + scrollSpeed;
+ }
+
+ if (hasCallback || oldRow !== item.row || oldCol !== item.col) {
+ scope.$apply(function() {
+ if (hasCallback) {
+ gridster.draggable.drag(event, $el, itemOptions);
+ }
+ });
+ }
+ }
+
+ function dragStop(event) {
+ $el.removeClass('gridster-item-moving');
+ var row = gridster.pixelsToRows(elmY);
+ var col = gridster.pixelsToColumns(elmX);
+ if (gridster.pushing !== false || gridster.getItems(row, col, item.sizeX, item.sizeY, item).length === 0) {
+ item.row = row;
+ item.col = col;
+ }
+ gridster.movingItem = null;
+ item.setPosition(item.row, item.col);
+
+ scope.$apply(function() {
+ if (gridster.draggable && gridster.draggable.stop) {
+ gridster.draggable.stop(event, $el, itemOptions);
+ }
+ });
+ }
+
+ var enabled = null;
+ var $dragHandles = null;
+ var unifiedInputs = [];
+
+ this.enable = function() {
+ if (enabled === true) {
+ return;
+ }
+
+ // disable and timeout required for some template rendering
+ $timeout(function() {
+ // disable any existing draghandles
+ for (var u = 0, ul = unifiedInputs.length; u < ul; ++u) {
+ unifiedInputs[u].disable();
+ }
+ unifiedInputs = [];
+
+ if (gridster.draggable && gridster.draggable.handle) {
+ $dragHandles = angular.element($el[0].querySelectorAll(gridster.draggable.handle));
+ if ($dragHandles.length === 0) {
+ // fall back to element if handle not found...
+ $dragHandles = $el;
+ }
+ } else {
+ $dragHandles = $el;
+ }
+
+ for (var h = 0, hl = $dragHandles.length; h < hl; ++h) {
+ unifiedInputs[h] = new GridsterTouch($dragHandles[h], mouseDown, mouseMove, mouseUp);
+ unifiedInputs[h].enable();
+ }
+
+ enabled = true;
+ });
+ };
+
+ this.disable = function() {
+ if (enabled === false) {
+ return;
+ }
+
+ // timeout to avoid race contition with the enable timeout
+ $timeout(function() {
+
+ for (var u = 0, ul = unifiedInputs.length; u < ul; ++u) {
+ unifiedInputs[u].disable();
+ }
+
+ unifiedInputs = [];
+ enabled = false;
+ });
+ };
+
+ this.toggle = function(enabled) {
+ if (enabled) {
+ this.enable();
+ } else {
+ this.disable();
+ }
+ };
+
+ this.destroy = function() {
+ this.disable();
+ };
+ }
+
+ return GridsterDraggable;
+ }
+ ])
+
+ .factory('GridsterResizable', ['GridsterTouch', function(GridsterTouch) {
+ function GridsterResizable($el, scope, gridster, item, itemOptions) {
+
+ function ResizeHandle(handleClass) {
+
+ var hClass = handleClass;
+
+ var elmX, elmY, elmW, elmH,
+
+ mouseX = 0,
+ mouseY = 0,
+ lastMouseX = 0,
+ lastMouseY = 0,
+ mOffX = 0,
+ mOffY = 0,
+
+ minTop = 0,
+ maxTop = 9999,
+ minLeft = 0;
+
+ var getMinHeight = function() {
+ return (item.minSizeY ? item.minSizeY : 1) * gridster.curRowHeight - gridster.margins[0];
+ };
+ var getMinWidth = function() {
+ return (item.minSizeX ? item.minSizeX : 1) * gridster.curColWidth - gridster.margins[1];
+ };
+
+ var originalWidth, originalHeight;
+ var savedDraggable;
+
+ function mouseDown(e) {
+ switch (e.which) {
+ case 1:
+ // left mouse button
+ break;
+ case 2:
+ case 3:
+ // right or middle mouse button
+ return;
+ }
+
+ // save the draggable setting to restore after resize
+ savedDraggable = gridster.draggable.enabled;
+ if (savedDraggable) {
+ gridster.draggable.enabled = false;
+ scope.$broadcast('gridster-draggable-changed', gridster);
+ }
+
+ // Get the current mouse position.
+ lastMouseX = e.pageX;
+ lastMouseY = e.pageY;
+
+ // Record current widget dimensions
+ elmX = parseInt($el.css('left'), 10);
+ elmY = parseInt($el.css('top'), 10);
+ elmW = $el[0].offsetWidth;
+ elmH = $el[0].offsetHeight;
+
+ originalWidth = item.sizeX;
+ originalHeight = item.sizeY;
+
+ resizeStart(e);
+
+ return true;
+ }
+
+ function resizeStart(e) {
+ $el.addClass('gridster-item-moving');
+ $el.addClass('gridster-item-resizing');
+
+ gridster.movingItem = item;
+
+ item.setElementSizeX();
+ item.setElementSizeY();
+ item.setElementPosition();
+ gridster.updateHeight(1);
+
+ scope.$apply(function() {
+ // callback
+ if (gridster.resizable && gridster.resizable.start) {
+ gridster.resizable.start(e, $el, itemOptions); // options is the item model
+ }
+ });
+ }
+
+ function mouseMove(e) {
+ var maxLeft = gridster.curWidth - 1;
+
+ // Get the current mouse position.
+ mouseX = e.pageX;
+ mouseY = e.pageY;
+
+ // Get the deltas
+ var diffX = mouseX - lastMouseX + mOffX;
+ var diffY = mouseY - lastMouseY + mOffY;
+ mOffX = mOffY = 0;
+
+ // Update last processed mouse positions.
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+
+ var dY = diffY,
+ dX = diffX;
+
+ if (hClass.indexOf('n') >= 0) {
+ if (elmH - dY < getMinHeight()) {
+ diffY = elmH - getMinHeight();
+ mOffY = dY - diffY;
+ } else if (elmY + dY < minTop) {
+ diffY = minTop - elmY;
+ mOffY = dY - diffY;
+ }
+ elmY += diffY;
+ elmH -= diffY;
+ }
+ if (hClass.indexOf('s') >= 0) {
+ if (elmH + dY < getMinHeight()) {
+ diffY = getMinHeight() - elmH;
+ mOffY = dY - diffY;
+ } else if (elmY + elmH + dY > maxTop) {
+ diffY = maxTop - elmY - elmH;
+ mOffY = dY - diffY;
+ }
+ elmH += diffY;
+ }
+ if (hClass.indexOf('w') >= 0) {
+ if (elmW - dX < getMinWidth()) {
+ diffX = elmW - getMinWidth();
+ mOffX = dX - diffX;
+ } else if (elmX + dX < minLeft) {
+ diffX = minLeft - elmX;
+ mOffX = dX - diffX;
+ }
+ elmX += diffX;
+ elmW -= diffX;
+ }
+ if (hClass.indexOf('e') >= 0) {
+ if (elmW + dX < getMinWidth()) {
+ diffX = getMinWidth() - elmW;
+ mOffX = dX - diffX;
+ } else if (elmX + elmW + dX > maxLeft) {
+ diffX = maxLeft - elmX - elmW;
+ mOffX = dX - diffX;
+ }
+ elmW += diffX;
+ }
+
+ // set new position
+ $el.css({
+ 'top': elmY + 'px',
+ 'left': elmX + 'px',
+ 'width': elmW + 'px',
+ 'height': elmH + 'px'
+ });
+
+ resize(e);
+
+ return true;
+ }
+
+ function mouseUp(e) {
+ // restore draggable setting to its original state
+ if (gridster.draggable.enabled !== savedDraggable) {
+ gridster.draggable.enabled = savedDraggable;
+ scope.$broadcast('gridster-draggable-changed', gridster);
+ }
+
+ mOffX = mOffY = 0;
+
+ resizeStop(e);
+
+ return true;
+ }
+
+ function resize(e) {
+ var oldRow = item.row,
+ oldCol = item.col,
+ oldSizeX = item.sizeX,
+ oldSizeY = item.sizeY,
+ hasCallback = gridster.resizable && gridster.resizable.resize;
+
+ var col = item.col;
+ // only change column if grabbing left edge
+ if (['w', 'nw', 'sw'].indexOf(handleClass) !== -1) {
+ col = gridster.pixelsToColumns(elmX, false);
+ }
+
+ var row = item.row;
+ // only change row if grabbing top edge
+ if (['n', 'ne', 'nw'].indexOf(handleClass) !== -1) {
+ row = gridster.pixelsToRows(elmY, false);
+ }
+
+ var sizeX = item.sizeX;
+ // only change row if grabbing left or right edge
+ if (['n', 's'].indexOf(handleClass) === -1) {
+ sizeX = gridster.pixelsToColumns(elmW, true);
+ }
+
+ var sizeY = item.sizeY;
+ // only change row if grabbing top or bottom edge
+ if (['e', 'w'].indexOf(handleClass) === -1) {
+ sizeY = gridster.pixelsToRows(elmH, true);
+ }
+
+ if (gridster.pushing !== false || gridster.getItems(row, col, sizeX, sizeY, item).length === 0) {
+ item.row = row;
+ item.col = col;
+ item.sizeX = sizeX;
+ item.sizeY = sizeY;
+ }
+ var isChanged = item.row !== oldRow || item.col !== oldCol || item.sizeX !== oldSizeX || item.sizeY !== oldSizeY;
+
+ if (hasCallback || isChanged) {
+ scope.$apply(function() {
+ if (hasCallback) {
+ gridster.resizable.resize(e, $el, itemOptions); // options is the item model
+ }
+ });
+ }
+ }
+
+ function resizeStop(e) {
+ $el.removeClass('gridster-item-moving');
+ $el.removeClass('gridster-item-resizing');
+
+ gridster.movingItem = null;
+
+ item.setPosition(item.row, item.col);
+ item.setSizeY(item.sizeY);
+ item.setSizeX(item.sizeX);
+
+ scope.$apply(function() {
+ if (gridster.resizable && gridster.resizable.stop) {
+ gridster.resizable.stop(e, $el, itemOptions); // options is the item model
+ }
+ });
+ }
+
+ var $dragHandle = null;
+ var unifiedInput;
+
+ this.enable = function() {
+ if (!$dragHandle) {
+ $dragHandle = angular.element('<div class="gridster-item-resizable-handler handle-' + hClass + '"></div>');
+ $el.append($dragHandle);
+ }
+
+ unifiedInput = new GridsterTouch($dragHandle[0], mouseDown, mouseMove, mouseUp);
+ unifiedInput.enable();
+ };
+
+ this.disable = function() {
+ if ($dragHandle) {
+ $dragHandle.remove();
+ $dragHandle = null;
+ }
+
+ unifiedInput.disable();
+ unifiedInput = undefined;
+ };
+
+ this.destroy = function() {
+ this.disable();
+ };
+ }
+
+ var handles = [];
+ var handlesOpts = gridster.resizable.handles;
+ if (typeof handlesOpts === 'string') {
+ handlesOpts = gridster.resizable.handles.split(',');
+ }
+ var enabled = false;
+
+ for (var c = 0, l = handlesOpts.length; c < l; c++) {
+ handles.push(new ResizeHandle(handlesOpts[c]));
+ }
+
+ this.enable = function() {
+ if (enabled) {
+ return;
+ }
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].enable();
+ }
+ enabled = true;
+ };
+
+ this.disable = function() {
+ if (!enabled) {
+ return;
+ }
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].disable();
+ }
+ enabled = false;
+ };
+
+ this.toggle = function(enabled) {
+ if (enabled) {
+ this.enable();
+ } else {
+ this.disable();
+ }
+ };
+
+ this.destroy = function() {
+ for (var c = 0, l = handles.length; c < l; c++) {
+ handles[c].destroy();
+ }
+ };
+ }
+ return GridsterResizable;
+ }])
+
+ .factory('gridsterDebounce', function() {
+ return function gridsterDebounce(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var context = this,
+ args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) {
+ func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) {
+ func.apply(context, args);
+ }
+ };
+ };
+ })
+
+ /**
+ * GridsterItem directive
+ * @param $parse
+ * @param GridsterDraggable
+ * @param GridsterResizable
+ * @param gridsterDebounce
+ */
+ .directive('gridsterItem', ['$parse', 'GridsterDraggable', 'GridsterResizable', 'gridsterDebounce',
+ function($parse, GridsterDraggable, GridsterResizable, gridsterDebounce) {
+ return {
+ scope: true,
+ restrict: 'EA',
+ controller: 'GridsterItemCtrl',
+ controllerAs: 'gridsterItem',
+ require: ['^gridster', 'gridsterItem'],
+ link: function(scope, $el, attrs, controllers) {
+ var optionsKey = attrs.gridsterItem,
+ options;
+
+ var gridster = controllers[0],
+ item = controllers[1];
+
+ scope.gridster = gridster;
+
+
+ // bind the item's position properties
+ // options can be an object specified by gridster-item="object"
+ // or the options can be the element html attributes object
+ if (optionsKey) {
+ var $optionsGetter = $parse(optionsKey);
+ options = $optionsGetter(scope) || {};
+ if (!options && $optionsGetter.assign) {
+ options = {
+ row: item.row,
+ col: item.col,
+ sizeX: item.sizeX,
+ sizeY: item.sizeY,
+ minSizeX: 0,
+ minSizeY: 0,
+ maxSizeX: null,
+ maxSizeY: null
+ };
+ $optionsGetter.assign(scope, options);
+ }
+ } else {
+ options = attrs;
+ }
+
+ item.init($el, gridster);
+
+ $el.addClass('gridster-item');
+
+ var aspects = ['minSizeX', 'maxSizeX', 'minSizeY', 'maxSizeY', 'sizeX', 'sizeY', 'row', 'col'],
+ $getters = {};
+
+ var expressions = [];
+ var aspectFn = function(aspect) {
+ var expression;
+ if (typeof options[aspect] === 'string') {
+ // watch the expression in the scope
+ expression = options[aspect];
+ } else if (typeof options[aspect.toLowerCase()] === 'string') {
+ // watch the expression in the scope
+ expression = options[aspect.toLowerCase()];
+ } else if (optionsKey) {
+ // watch the expression on the options object in the scope
+ expression = optionsKey + '.' + aspect;
+ } else {
+ return;
+ }
+ expressions.push('"' + aspect + '":' + expression);
+ $getters[aspect] = $parse(expression);
+
+ // initial set
+ var val = $getters[aspect](scope);
+ if (typeof val === 'number') {
+ item[aspect] = val;
+ }
+ };
+
+ for (var i = 0, l = aspects.length; i < l; ++i) {
+ aspectFn(aspects[i]);
+ }
+
+ var watchExpressions = '{' + expressions.join(',') + '}';
+
+ // when the value changes externally, update the internal item object
+ scope.$watchCollection(watchExpressions, function(newVals, oldVals) {
+ for (var aspect in newVals) {
+ var newVal = newVals[aspect];
+ var oldVal = oldVals[aspect];
+ if (oldVal === newVal) {
+ continue;
+ }
+ newVal = parseInt(newVal, 10);
+ if (!isNaN(newVal)) {
+ item[aspect] = newVal;
+ }
+ }
+ });
+
+ function positionChanged() {
+ // call setPosition so the element and gridster controller are updated
+ item.setPosition(item.row, item.col);
+
+ // when internal item position changes, update externally bound values
+ if ($getters.row && $getters.row.assign) {
+ $getters.row.assign(scope, item.row);
+ }
+ if ($getters.col && $getters.col.assign) {
+ $getters.col.assign(scope, item.col);
+ }
+ }
+ scope.$watch(function() {
+ return item.row + ',' + item.col;
+ }, positionChanged);
+
+ function sizeChanged() {
+ var changedX = item.setSizeX(item.sizeX, true);
+ if (changedX && $getters.sizeX && $getters.sizeX.assign) {
+ $getters.sizeX.assign(scope, item.sizeX);
+ }
+ var changedY = item.setSizeY(item.sizeY, true);
+ if (changedY && $getters.sizeY && $getters.sizeY.assign) {
+ $getters.sizeY.assign(scope, item.sizeY);
+ }
+
+ if (changedX || changedY) {
+ item.gridster.moveOverlappingItems(item);
+ gridster.layoutChanged();
+ scope.$broadcast('gridster-item-resized', item);
+ }
+ }
+
+ scope.$watch(function() {
+ return item.sizeY + ',' + item.sizeX + ',' + item.minSizeX + ',' + item.maxSizeX + ',' + item.minSizeY + ',' + item.maxSizeY;
+ }, sizeChanged);
+
+ var draggable = new GridsterDraggable($el, scope, gridster, item, options);
+ var resizable = new GridsterResizable($el, scope, gridster, item, options);
+
+ var updateResizable = function() {
+ resizable.toggle(!gridster.isMobile && gridster.resizable && gridster.resizable.enabled);
+ };
+ updateResizable();
+
+ var updateDraggable = function() {
+ draggable.toggle(!gridster.isMobile && gridster.draggable && gridster.draggable.enabled);
+ };
+ updateDraggable();
+
+ scope.$on('gridster-draggable-changed', updateDraggable);
+ scope.$on('gridster-resizable-changed', updateResizable);
+ scope.$on('gridster-resized', updateResizable);
+ scope.$on('gridster-mobile-changed', function() {
+ updateResizable();
+ updateDraggable();
+ });
+
+ function whichTransitionEvent() {
+ var el = document.createElement('div');
+ var transitions = {
+ 'transition': 'transitionend',
+ 'OTransition': 'oTransitionEnd',
+ 'MozTransition': 'transitionend',
+ 'WebkitTransition': 'webkitTransitionEnd'
+ };
+ for (var t in transitions) {
+ if (el.style[t] !== undefined) {
+ return transitions[t];
+ }
+ }
+ }
+
+ var debouncedTransitionEndPublisher = gridsterDebounce(function() {
+ scope.$apply(function() {
+ scope.$broadcast('gridster-item-transition-end', item);
+ });
+ }, 50);
+
+ if(whichTransitionEvent()){ //check for IE8, as it evaluates to null
+ $el.on(whichTransitionEvent(), debouncedTransitionEndPublisher);
+ }
+
+ scope.$broadcast('gridster-item-initialized', item);
+
+ return scope.$on('$destroy', function() {
+ try {
+ resizable.destroy();
+ draggable.destroy();
+ } catch (e) {}
+
+ try {
+ gridster.removeItem(item);
+ } catch (e) {}
+
+ try {
+ item.destroy();
+ } catch (e) {}
+ });
+ }
+ };
+ }
+ ])
+
+ .directive('gridsterNoDrag', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, $element) {
+ $element.addClass('gridster-no-drag');
+ }
+ };
+ })
+
+ ;
+
+}));
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js
new file mode 100644
index 00000000..3ca3db7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/att_angular_gridster/ui-gridster-tpls.js
@@ -0,0 +1,168 @@
+/**
+* FileName ui-gridster
+* Version 0.0.1
+* Build number ad58c6f4f8f8fd7f04ac457f95d76f09
+* Date 08/17/2015
+*/
+
+
+(function(angular, window){
+angular.module("att.gridster", ["att.gridster.tpls", "att.gridster.utilities","att.gridster.gridster"]);
+angular.module("att.gridster.tpls", ["template/gridster/gridster.html","template/gridster/gridsterItem.html","template/gridster/gridsterItemBody.html","template/gridster/gridsterItemFooter.html","template/gridster/gridsterItemHeader.html"]);
+angular.module('att.gridster.utilities', [])
+ .factory('$extendObj', [function() {
+ var _extendDeep = function(dst) {
+ angular.forEach(arguments, function(obj) {
+ if (obj !== dst) {
+ angular.forEach(obj, function(value, key) {
+ if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
+ _extendDeep(dst[key], value);
+ } else {
+ dst[key] = value;
+ }
+ });
+ }
+ });
+ return dst;
+ };
+ return {
+ extendDeep: _extendDeep
+ };
+ }]);
+
+angular.module('att.gridster.gridster', ['attGridsterLib', 'att.gridster.utilities'])
+ .config(['$compileProvider', function($compileProvider) {
+ $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
+ }])
+ .constant('attGridsterConfig',
+ {
+ columns: 3,
+ margins: [10, 10],
+ outerMargin: true,
+ pushing: true,
+ floating: true,
+ swapping: true,
+ draggable: {
+ enabled: true
+ }
+ })
+ .directive('attGridster', ['attGridsterConfig', '$extendObj', function(attGridsterConfig, $extendObj) {
+ return {
+ restrict: 'EA',
+ scope: {
+ attGridsterOptions: '=?'
+ },
+ templateUrl: 'template/gridster/gridster.html',
+ replace: false,
+ transclude: true,
+ controller: [function() {}],
+ link: function(scope) {
+ if (angular.isDefined(scope.attGridsterOptions)) {
+ attGridsterConfig = $extendObj.extendDeep(attGridsterConfig, scope.attGridsterOptions);
+ }
+ scope.attGridsterConfig = attGridsterConfig;
+ }
+ };
+ }])
+ .directive('attGridsterItem', ['$timeout', function($timeout) {
+ return {
+ restrict: 'EA',
+ require: ['^attGridster'],
+ scope: {
+ attGridsterItem: '='
+ },
+ templateUrl: 'template/gridster/gridsterItem.html',
+ replace: false,
+ transclude: true,
+ controller: [function() {}]
+ };
+ }])
+ .directive('attGridsterItemHeader', [function() {
+ return {
+ restrict: 'EA',
+ require: ['^attGridsterItem'],
+ scope: {
+ headerText: '@',
+ subHeaderText: '@?'
+ },
+ templateUrl: 'template/gridster/gridsterItemHeader.html',
+ replace: true,
+ transclude: true,
+ link: function(scope, element) {
+ if (angular.isDefined(scope.subHeaderText) && scope.subHeaderText) {
+ angular.element(element[0].querySelector('span.gridster-item-sub-header-content')).attr("tabindex", "0");
+ angular.element(element[0].querySelector('span.gridster-item-sub-header-content')).attr("aria-label", scope.subHeaderText);
+ }
+ }
+ };
+ }])
+ .directive('attGridsterItemBody', [function() {
+ return {
+ restrict: 'EA',
+ require: ['^attGridsterItem'],
+ scope: {},
+ templateUrl: 'template/gridster/gridsterItemBody.html',
+ replace: true,
+ transclude: true
+ };
+ }])
+ .directive('attGridsterItemFooter', ['$location', function($location) {
+ return {
+ restrict: 'EA',
+ require: ['^attGridsterItem'],
+ scope: {
+ attGridsterItemFooterLink: '@?'
+ },
+ templateUrl: 'template/gridster/gridsterItemFooter.html',
+ replace: true,
+ transclude: true,
+ controller: ['$scope', function($scope) {
+ $scope.clickOnFooterLink = function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if ($scope.attGridsterItemFooterLink) {
+ $location.url($scope.attGridsterItemFooterLink);
+ }
+ };
+ }],
+ link: function(scope, element) {
+ if (angular.isDefined(scope.attGridsterItemFooterLink) && scope.attGridsterItemFooterLink) {
+ element.attr("role", "link");
+ }
+ }
+ };
+ }]);
+angular.module("template/gridster/gridster.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/gridster/gridster.html",
+ "<div gridster='attGridsterConfig'><div ng-transclude></div></div>");
+}]);
+
+angular.module("template/gridster/gridsterItem.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/gridster/gridsterItem.html",
+ "<div gridster-item='attGridsterItem' class=\"gridster-item-container\" ng-transclude></div>");
+}]);
+
+angular.module("template/gridster/gridsterItemBody.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/gridster/gridsterItemBody.html",
+ "<div class=\"gridster-item-body\" ng-transclude></div>");
+}]);
+
+angular.module("template/gridster/gridsterItemFooter.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/gridster/gridsterItemFooter.html",
+ "<div class=\"gridster-item-footer\" ng-click=\"clickOnFooterLink($event)\" tabindex=\"0\" ng-keydown=\"(($event.keyCode && $event.keyCode === 13) || ($event.which && $event.which === 13)) && clickOnFooterLink($event)\" >\n" +
+ " <span class=\"gridster-item-footer-content\" ng-transclude></span>\n" +
+ "</div>");
+}]);
+
+angular.module("template/gridster/gridsterItemHeader.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/gridster/gridsterItemHeader.html",
+ "<div class=\"gridster-item-header\">\n" +
+ " <img gridster-item-drag src=\"static/fusion/images/att_angular_gridster/grips.png\" alt=\"||\" aria-label=\"Tap/Click to move\" class=\"gridster-item-handle\" />\n" +
+ " <span class=\"gridster-item-header-content\" tabindex=\"0\" role=\"presentation\" aria-label=\"{{headerText}}\">{{headerText}}</span>\n" +
+ " <span class=\"gridster-item-sub-header-content\" role=\"presentation\">{{subHeaderText}}</span>\n" +
+ " <div class=\"gridster-item-header-buttons-container\" ng-transclude></div>\n" +
+ "</div>");
+}]);
+
+return {}
+})(angular, window); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/jquery.resize.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/jquery.resize.js
index 1ebd6c95..1ebd6c95 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/jquery.resize.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/jquery.resize.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/debug.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/debug.js
index eff36a25..eff36a25 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/debug.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/debug.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-latest.js
index 1c998bab..1c998bab 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js
index aa83af97..aa83af97 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery-ui-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js
index 434724d9..434724d9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/layout/jquery.layout-latest.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/moment.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/moment.min.js
index 62b1697b..62b1697b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/js/moment.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/js/moment.min.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Entries b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Entries
new file mode 100644
index 00000000..a4612779
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Entries
@@ -0,0 +1,9 @@
+D/tree////
+/calendar.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/dashboard.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/form-field-tooltip.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/mobile_raptor.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/novamap.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/picker.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/ral.css/1.2/Tue Oct 01 18:58:02 2013/-ko/TQuantum_BD
+/raptor.css/1.2/Wed Jul 03 21:16:48 2013/-ko/TQuantum_BD
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Repository b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Repository
new file mode 100644
index 00000000..d4b93eab
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Repository
@@ -0,0 +1 @@
+fusion/war/static/fusion/raptor/css
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Root b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Root
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Root
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Tag b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Tag
new file mode 100644
index 00000000..8f405b6d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/CVS/Tag
@@ -0,0 +1 @@
+TQuantum_BD
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/Style.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/Style.css
index 1fa71bef..1fa71bef 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/Style.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/Style.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css
index 8674a88c..8674a88c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/bd_quantum_raptor.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/calendar.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/calendar.css
index fdd2242f..fdd2242f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/calendar.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/calendar.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/dashboard.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/dashboard.css
index 2c79da20..2c79da20 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/dashboard.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/dashboard.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/drupal.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/drupal.css
index 15850790..15850790 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/drupal.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/drupal.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css
index 24b40da9..24b40da9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/form-field-tooltip.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css
index b47fc431..b47fc431 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/mobile_raptor.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/novamap.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/novamap.css
index 7bbf4bf5..7bbf4bf5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/novamap.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/novamap.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/picker.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/picker.css
index bbc439ec..bbc439ec 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/picker.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/picker.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/ral.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/ral.css
index 4e45ddca..65fb6fd2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/ral.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/ral.css
@@ -969,7 +969,7 @@ text-align:right;
padding-right:10px;
}
-/*------------------------mCA: Contact-------------------------*/
+/*------------------------mCA: Contact -------------------------*/
.mCA{
position:relative;
width:50%;
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/raptor.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/raptor.css
index ea37015a..ea37015a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/css/raptor.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/raptor.css
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/context-menu.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/context-menu.css
new file mode 100644
index 00000000..160c2a11
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/context-menu.css
@@ -0,0 +1,57 @@
+/************************************************************************************************************
+
+ DHTML Suite for Applications
+ (C) www.dhtmlgoodies.com, August 2006
+
+ CSS for the context menu class.
+
+ Terms of use:
+ Look at the terms of use at http://www.dhtmlgoodies.com/index.html?page=termsOfUse
+
+ Thank you!
+
+ www.dhtmlgoodies.com
+ Alf Magne Kalleland
+
+************************************************************************************************************/
+
+.DHTMLSuite_contextMenu{ /* The bar that is parent of the menu strip */
+ position:absolute;
+ background-color:#FFF;
+ border:1px solid #000;
+ padding:1px;
+}
+
+.DHTMLSuite_contextMenu li{
+ list-style-type:none;
+ padding:1px; /* Equal to border + padding of .DHTMLSuite_item_mouseover */
+ border:0px;
+ cursor: pointer;
+ background-repeat:no-repeat;
+ background-position:left center;
+}
+.DHTMLSuite_contextMenu .DHTMLSuite_item_mouseover{
+ border:1px solid #000;
+ background-color:#EEE;
+ padding:0px; /* Padding + border of this element should be equal to padding of li element (see above ) */
+}
+.DHTMLSuite_contextMenu ul{
+ margin:0px;
+ padding:0px;
+}
+
+.DHTMLSuite_contextMenu a{
+ text-decoration:none;
+ color:#000;
+ padding-left:25px;
+}
+
+.DHTMLSuite_contextMenu div.DHTMLSuite_contextMenu_separator{ /* Css for the separator line */
+ height:1px;
+ line-height:1px;
+ padding:0px;
+ background-color: #AAA;
+ overflow:hidden;
+ margin-top:1px;
+ margin-bottom:1px;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/drag-drop-folder-tree.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/drag-drop-folder-tree.css
new file mode 100644
index 00000000..67afc894
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/css/tree/drag-drop-folder-tree.css
@@ -0,0 +1,64 @@
+ ul,ol{
+ top:0;
+ left:0px;
+ margin:0px 0px;
+ position:static;
+ border:0;
+ padding:0;
+ }
+
+ p{
+ font-family:arial;
+
+ }
+ a{
+ color:#000;
+ font-family:arial;
+ }
+
+ .dhtmlgoodies_tree,#floatingContainer{
+ margin:0px;
+ padding:0px;
+ }
+ .dhtmlgoodies_tree ul{ /* Sub menu groups */
+ margin-left:20px; /* Left spacing */
+ padding-left:0px;
+ display:none; /* Initially hide sub nodes */
+ }
+
+ #floatingContainer ul{
+ margin-left:20px; /* Left spacing */
+ padding-left:0px;
+ }
+ .dhtmlgoodies_tree li,#floatingContainer li{ /* Nodes */
+ list-style-type:none;
+ vertical-align:middle;
+
+ }
+ .dhtmlgoodies_tree li a,#floatingContainer li a{ /* Node links */
+ color:#000;
+ text-decoration:none;
+ font-family:arial;
+ font-size:0.8em;
+ padding-left:1px;
+ line-height:13px;
+ margin-left:2px;
+
+ }
+ .dhtmlgoodies_tree li a.highlightedNodeItem{
+ color:#FFF;
+ background-color:#009;
+ }
+
+
+ body{
+ margin:0px;
+ padding:0px;
+ }
+
+ .dhtmlgoodies_tree input.folderTreeTextBox{ /* Css for the text input - rename item */
+ font-size:10px;
+ margin:0px;
+ padding:0px;
+ height:12px;
+ } \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css
index 28ccd053..28ccd053 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/css/nv.d3.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/cie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/cie.js
index 45f01329..45f01329 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/cie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/cie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js
index 2295527b..2295527b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/colorbrewer.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/core.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/core.js
index 912de8d8..912de8d8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/core.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/core.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js
index 1aaabca2..1aaabca2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js
index 981f0d64..981f0d64 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/crossfilter.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js
index a19bb16e..a19bb16e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.geom.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.js
index 250d9767..250d9767 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js
index abc5ebef..abc5ebef 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.layout.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js
index 714656b3..714656b3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js
index cc47f1ea..cc47f1ea 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v2.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js
index bf4a8c10..bf4a8c10 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js
index 7975878f..7975878f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/d3.v3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js
index e1addd7b..e1addd7b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/fisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/hive.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/hive.js
index 06e53aed..06e53aed 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/hive.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/hive.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/horizon.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/horizon.js
index d84c6567..d84c6567 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/horizon.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/horizon.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js
index 4dfb68dc..4dfb68dc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/interactiveLayer.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/intro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/intro.js
index af50383e..af50383e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/d3/js/intro.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/intro.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js
index 1101dde5..1101dde5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis-min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js
index 9895c3f0..9895c3f0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js
index 6c8ad6ab..6c8ad6ab 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/axis.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js
index 3d2360a6..3d2360a6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/boilerplate.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js
index 9b9bf4d1..9b9bf4d1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bullet.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js
index fa5bd596..fa5bd596 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/bulletChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js
index 00f193cf..00f193cf 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/cumulativeLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js
index a20f5829..a20f5829 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js
index 48a48164..48a48164 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/discreteBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js
index 62a74655..62a74655 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/distribution.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js
index 2a6c644d..2a6c644d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js
index a5b4a097..a5b4a097 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/historicalBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js
index 18c2700f..18c2700f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/indentedTree.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js
index 21f9f9a4..21f9f9a4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/legend.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/line.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/line.js
index 855cc541..855cc541 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/line.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/line.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js
index a4ffcf6a..a4ffcf6a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js
index 77fcbab7..77fcbab7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js
index 2ef31137..2ef31137 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/linePlusBarWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js
index 2b411672..2b411672 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheye.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js
index ad894190..ad894190 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFisheyeChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js
index 0afd28bd..0afd28bd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/lineWithFocusChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js
index 1085919b..1085919b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js
index 0323063f..0323063f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js
index d16d4605..d16d4605 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontal.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js
index 02aa6fa4..02aa6fa4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarHorizontalChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js
index abc062c3..abc062c3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeries.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js
index 5aebafa7..5aebafa7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiBarTimeSeriesChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js
index e3e2c5e8..e3e2c5e8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/multiChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js
index 46f2b60c..46f2b60c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/ohlcBar.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js
index 107154f7..107154f7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/parallelCoordinates.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js
index 2099c8f3..2099c8f3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak
index aac835d2..aac835d2 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pie.js.bak
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js
index b4303fd6..b4303fd6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/pieChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js
index 16cbee65..16cbee65 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatter.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js
index 65b6e387..65b6e387 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js
index 23c87853..23c87853 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/scatterPlusLineChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js
index e4c2e87b..e4c2e87b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparkline.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js
index 1535f8af..1535f8af 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/sparklinePlus.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js
index eefeb8fb..eefeb8fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedArea.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js
index a036b8b0..a036b8b0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/models/stackedAreaChart.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js
index 892379c4..892379c4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/nv.d3.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/outro.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/outro.js
index 158693a0..158693a0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/outro.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/outro.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/sankey.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/sankey.js
index c3bc59fb..c3bc59fb 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/sankey.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/sankey.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js
index 46e5a816..46e5a816 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/tooltip.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/utils.js
index 7b99e1da..7b99e1da 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/utils.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/d3/js/utils.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js
index cec77298..cec77298 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dashed-canvas.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/data.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/data.js
index d92a6339..d92a6339 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/data.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/data.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js
index cba4f449..cba4f449 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-canvas.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js
index 4f864538..4f864538 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js
index 2f7b14b8..2f7b14b8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-combined_bak_color.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js
index c06d23d5..c06d23d5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-dev.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js
index ed5de4c1..ed5de4c1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-externs.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js
index 988e0ace..988e0ace 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-gviz.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js
index 2af345c7..2af345c7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-interaction-model.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js
index e766e8f5..e766e8f5 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-layout.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js
index 64e738d4..64e738d4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options-reference.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js
index 0f90086c..0f90086c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-options.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js
index 7f758a9a..7f758a9a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-base.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js
index 806a9274..806a9274 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-plugin-install.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js
index f4778b12..f4778b12 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-tickers.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js
index 1ec1795d..1ec1795d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph-utils.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js
index 1ee711ca..1ee711ca 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/dygraph.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js
index 367764b4..367764b4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/excanvas.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js
index 23847845..23847845 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js
index e3f736a8..e3f736a8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js
index 92a0dbd7..92a0dbd7 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/interaction_sun.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js
index 62b1697b..62b1697b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/moment.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js
index 22f46870..22f46870 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-driver.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js
index b98c3f03..b98c3f03 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/phantom-perf.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README
index f216545b..f216545b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/README
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js
index 85761040..85761040 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/annotations.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js
index cacda86e..cacda86e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/axes.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js
index da231d80..da231d80 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/chart-labels.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js
index 425d93f6..425d93f6 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/grid.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js
index 7406f82a..7406f82a 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/legend.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js
index 089e64aa..089e64aa 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/plugins/range-selector.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js
index 5a882446..5a882446 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/rgbcolor/rgbcolor.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js
index 4d0384d1..4d0384d1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/stacktrace.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile
index 26ac5a53..26ac5a53 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/Doxyfile
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js
index 8207714e..8207714e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime-min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js
index d622df9e..d622df9e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/dy3/js/strftime/strftime.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css
index a44c3560..a44c3560 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js
index ae69a913..ae69a913 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/date_time_picker.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js
index e711f414..e711f414 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/dynamicform.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/moment.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/moment.js
index b5f0b364..b5f0b364 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/moment.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/moment.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/multiselect.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/multiselect.js
index eda8da08..eda8da08 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/multiselect.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/multiselect.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/quick_links.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/quick_links.js
index 81e8276e..81e8276e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/quick_links.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/quick_links.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html
index 35fad2b4..35fad2b4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.html
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js
index 7fc167c1..7fc167c1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_chart_wizard.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.html
index afdb692e..1041d8b1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.html
@@ -35,16 +35,20 @@
text-align:center;
}
</style>
-<!-- Icons -->
-<link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
+
<div>
- <h1 class="heading2">{{reportData.reportName}} <a ng-href="{{reportEditURL}}" ng-show="reportData.allowEdit" class="ion-edit" style="font-size:20px;"></a>
+ <!-- <h1 class="heading2">{{reportData.reportName}} -->
+ <h1 class="heading2">{{reportData.reportHeading}}
+ <a ng-href="{{reportEditURL}}" ng-show="reportData.allowEdit" class="icon-edit" style="font-size:20px;"></a>
- &nbsp;&nbsp;&nbsp;<a ng-href="{{reportChartURL}}" ng-show="reportData.allowEdit && reportData.chartWizardAvailable" class="ion-stats-bars" style="font-size:20px;"></a>
+ &nbsp;&nbsp;&nbsp;<a ng-href="{{reportChartURL}}" ng-show="reportData.allowEdit && reportData.chartWizardAvailable" class="icon-bar-chart-vertical" style="font-size:20px;"></a>
&nbsp;&nbsp;&nbsp;<span ng-show="reportData.allowEdit && showFormFields" ><input type="checkbox" ng-model="showFormFieldIds" ng-true-value="Hide_IDs" ng-false-value="Show_IDs" att-toggle-main></span>
<!-- &nbsp;&nbsp;&nbsp;<a ng-href="{{reportChartURLNew}}" ng-show="reportData.allowEdit" class="icon-bar-chart-horizontal" style="font-size:20px;"></a> -->
</h1>
+
+ <h3 class="heading3">{{reportData.reportSubTitle}} </h3>
+
<div ng-show="isInProgress" style="font-size:50px;color:#2ca02c">Loading...</div>
<form ng-show="showFormFields" class="row section-row" style="margin: 10px">
@@ -55,13 +59,14 @@
<a type="submit" ng-show="showBackButton" style="margin: 10px" ng-href="report.htm#/report_run/{{parentReportUrlParams}}" att-button btn-type="primary" size="small" title='Back'>Back</a>
<iframe id="chartiframe" ng-show="showChart" width="100%" height="450px" style="border: none" scrolling="no"></iframe>
<div id="errorDiv"></div>
- <div ng-if="showGrid">
+ <div ng-if="showGrid">
<div id="grid1" ui-grid="gridOptions" ui-grid-pagination ui-grid-pinning ui-grid-resize-columns class="grid" style="height: {{gridHeight}}">
<div class="no-rows" ng-show="!gridOptions.data.length">
<div class="msg">
<span>{{reportData.message}}</span>
</div>
</div>
- </div>
- </div>
+ </div>
+ </div>
+ <!-- <a type="submit" ng-show="showBackButton" style="margin: 10px" ng-href="report.htm#/report_run/{{parentReportUrlParams}}" att-button btn-type="primary" size="small" title='Back'>Back</a> -->
</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.js
index 0df56796..436dedd0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_run.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_run.js
@@ -63,7 +63,16 @@ app.controller("reportRunController", ['$scope','$rootScope','$routeParams','$ht
console.log(response);
$scope.isInProgress = false;
$scope.reportData = response.data;
- if(!$scope.urlParams.hideChart && $scope.reportData.chartAvailable && $scope.reportData.totalRows>1){
+ console.log('reportData report run container response',$scope.reportData);
+ if ($scope.reportData.reportTitle) {
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ if ($scope.reportData.reportSubTitle) {
+ $scope.reportData.reportSubTitle = $scope.reportData.reportSubTitle;
+ }
+ }
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;
+ if(!$scope.urlParams.hideChart && $scope.reportData.chartAvailable && $scope.reportData.totalRows>1){
console.log('raptor.htm?action=chart.run&'+convertQueryString($scope.urlParams));
$http.get('raptor.htm?action=chart.run&'+convertQueryString($scope.urlParams)).then(
function(response){
@@ -105,12 +114,20 @@ app.controller("reportRunController", ['$scope','$rootScope','$routeParams','$ht
}
$scope.runReport = function(pagination){
-
var formFieldsUrl = $scope.getFormFieldSelectedValuesAsURL();
- console.log("pagination");
+ /*if ($scope.reportData.reportTitle)
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;*/
+
+ console.log("pagination");
if(!pagination) {
- console.log("refreshed ...");
+ //console.log("refreshed ...");
$scope.gridOptions.pageNumber = 1;
+ paginationOptions.pageNumber = 1;
+ paginationOptions.pageSize = $scope.reportData.pageSize;
+ //console.log($scope.gridOptions);
+ $scope.gridOptions.paginationCurrentPage = 1;
$scope.gridOptions.paginationPageSizes= [$scope.reportData.pageSize];
$scope.gridOptions.paginationPageSize= $scope.reportData.pageSize;
if($scope.reportData.totalRows<14){
@@ -128,10 +145,21 @@ app.controller("reportRunController", ['$scope','$rootScope','$routeParams','$ht
$http.get('raptor.htm?action=report.run.container&c_master='+$scope.urlParams.c_master+'&'+formFieldsUrl+'refresh=Y&display_content=Y&r_page='+(paginationOptions.pageNumber-1)).then(
function(response){
$scope.reportData = response.data;
+ if ($scope.reportData.reportTitle) {
+ $scope.reportData.reportHeading = $scope.reportData.reportTitle;
+ if ($scope.reportData.reportSubTitle) {
+ $scope.reportData.reportSubTitle = $scope.reportData.reportSubTitle;
+ }
+ }
+ else
+ $scope.reportData.reportHeading = $scope.reportData.reportName;
+
if($scope.reportData.errormessage) {
- document.getElementById('errorDiv').innerHTML = $scope.reportData.errormessage;
- console.log(document.getElementById('errorDiv').innerHtml);
- console.log($scope.reportData.errormessage);
+ //console.log($scope.reportData);
+ var stacktraceFP = $scope.reportData.stacktrace.substring(0, $scope.reportData.stacktrace.indexOf(":")+1);
+ document.getElementById('errorDiv').innerHTML = stacktraceFP + " " + $scope.reportData.errormessage;
+ //console.log(document.getElementById('errorDiv').innerHtml);
+ //console.log(stacktraceFP + " " + $scope.reportData.errormessage);
}
if(!pagination) {
if(!$scope.urlParams.hideChart && $scope.reportData.chartAvailable && $scope.reportData.totalRows>1){
@@ -140,6 +168,7 @@ app.controller("reportRunController", ['$scope','$rootScope','$routeParams','$ht
function(response) {
console.log(response.data);
$scope.showChart = true;
+ console.log('response.data',response.data);
document.getElementById('chartiframe').contentWindow.document.write(response.data);
document.getElementById('chartiframe').contentWindow.document.close();
});
@@ -147,7 +176,7 @@ app.controller("reportRunController", ['$scope','$rootScope','$routeParams','$ht
$scope.showChart = false;
}
}
- if($scope.reportData.displayForm && $scope.reportData.formFieldList && $scope.reportData.formFieldList.length>0 && !$scope.urlParams.hideFormFields){
+ if($scope.reportData.displayForm && $scope.reportData.formFieldList && $scope.reportData.formFieldList.length>0 && !$scope.urlParams.hideFormFields && !$scope.reportData.hideFormFieldsAfterRun){
$scope.showFormFields = true;
} else {
$scope.showFormFields = false;
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.html
index db00037c..37b388ff 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.html
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.html
@@ -10,7 +10,7 @@
content: "\e717";
}
</style>
-<h1 class="heading1">Report search</span></h1>
+<h1 class="heading1">Report search</h1>
<br>
<div >
<label class="pull-left" style="margin-top: 10px;margin-right: 5px;">Report Id:</label>
@@ -29,6 +29,7 @@
<input ng-model="reportName" type="text" placeholder="Search value?" style="border-radius:0px 5px 5px 0px">
</div>
<button type="submit" ng-click="runReport()" att-button btn-type="primary" style="margin-top: 10px;margin-left: 40px;" size="small" title='Submit'>Submit</button>
+
</div>
<br>
<div id="grid1" ui-grid="gridOptions" ui-grid-pagination ui-grid-resize-columns class="grid"></div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.js
index d2194224..afea176c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/ebz/report_search.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/ebz/report_search.js
@@ -70,19 +70,19 @@ app.controller("reportSearchController", ['$scope','$rootScope','$http','$timeou
$scope.searchdData.columns[0].forEach(function(entry) {
if(entry.columnTitle=='Run'){
$scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId+'==drillDownLink', enableSorting: false,
- cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="#/report_run/{{COL_FIELD.substr(39)}}" class="ion-arrow-right-b" style="font-size:20px;"></a></div>'
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="#/report_run/{{COL_FIELD.substr(39)}}" class="icon-play" style="font-size:20px;"></a></div>'
});
} else if(entry.columnTitle=='Edit'){
$scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId+'==drillDownLink', enableSorting: false,
- cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD}}" class="ion-edit" style="font-size:20px;"></a></div>'
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD}}" class="icon-edit" style="font-size:20px;"></a></div>'
});
} else if(entry.columnTitle=='Delete'){
$scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId+'==drillDownLink', enableSorting: false,
- cellTemplate: '<div class="ui-grid-cell-contents"><a href="" ng-click="grid.appScope.deleteReport(COL_FIELD,row)" class="ion-trash-b" style="font-size:20px;"></a></div>'
+ cellTemplate: '<div class="ui-grid-cell-contents"><a href="" ng-click="grid.appScope.deleteReport(COL_FIELD,row)" class="icon-trash" style="font-size:20px;"></a></div>'
});
} else if(entry.columnTitle=='Copy'){
$scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId+'==drillDownLink', enableSorting: false,
- cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD}}" class="ion-document-text" style="font-size:20px;"></a></div>'
+ cellTemplate: '<div class="ui-grid-cell-contents"><a ng-href="{{COL_FIELD}}" class="icon-plans" style="font-size:20px;"></a></div>'
});
} else if(entry.columnTitle=='Schedule'){
//$scope.gridOptions.columnDefs.push({ displayName: entry.columnTitle, field: entry.columnId+'==drillDownLink',
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ATT_Business_logo.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ATT_Business_logo.gif
new file mode 100644
index 00000000..56c4f8db
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ATT_Business_logo.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/RAPTOR_BANNER.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/RAPTOR_BANNER.jpg
new file mode 100644
index 00000000..afdc7825
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/RAPTOR_BANNER.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/accessicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/accessicon.gif
new file mode 100644
index 00000000..973f7590
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/accessicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/active.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/active.gif
new file mode 100644
index 00000000..944cb3b5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/active.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/addbtn.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/addbtn.png
new file mode 100644
index 00000000..8f746db6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/addbtn.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ajax-loader.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ajax-loader.gif
new file mode 100644
index 00000000..f2a1bc0c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/ajax-loader.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add.gif
new file mode 100644
index 00000000..f3cfc64e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_edge.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_edge.gif
new file mode 100644
index 00000000..ada0334c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_edge.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_multiple.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_multiple.gif
new file mode 100644
index 00000000..904369e5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_multiple.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_one.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_one.gif
new file mode 100644
index 00000000..e7fe4690
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_add_one.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_back.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_back.gif
new file mode 100644
index 00000000..c8ee935d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_back.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_cancel.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_cancel.gif
new file mode 100644
index 00000000..1d1d001b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_cancel.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left.gif
new file mode 100644
index 00000000..a79ccadd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left2.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left2.gif
new file mode 100644
index 00000000..726d4227
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_left2.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_next.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_next.gif
new file mode 100644
index 00000000..6743e7af
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_next.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_plus.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_plus.gif
new file mode 100644
index 00000000..7a402426
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_plus.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.gif
new file mode 100644
index 00000000..d67e1a63
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.png
new file mode 100644
index 00000000..bca729f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_reorder_all.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right.gif
new file mode 100644
index 00000000..e4879966
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right2.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right2.gif
new file mode 100644
index 00000000..302cb291
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_right2.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_save.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_save.gif
new file mode 100644
index 00000000..2702547a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/arrow_save.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/att-globe1.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/att-globe1.jpg
new file mode 100644
index 00000000..a88bedb3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/att-globe1.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/button_import.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/button_import.png
new file mode 100644
index 00000000..7fab1a02
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/button_import.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon.gif
new file mode 100644
index 00000000..caf77f9a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav.gif
new file mode 100644
index 00000000..2bccb616
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav1.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav1.gif
new file mode 100644
index 00000000..093ef50a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calendar_icon_nav1.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calender_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calender_icon.gif
new file mode 100644
index 00000000..caf77f9a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/calender_icon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankdown.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankdown.gif
new file mode 100644
index 00000000..15d1aac7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankdown.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankup.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankup.gif
new file mode 100644
index 00000000..f76975bd
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnblankup.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columndown.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columndown.gif
new file mode 100644
index 00000000..6c8d80e6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columndown.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnup.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnup.gif
new file mode 100644
index 00000000..1c9b24f8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/columnup.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/crosshairs.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/crosshairs.png
new file mode 100644
index 00000000..c90509ce
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/crosshairs.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/csv_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/csv_icon.gif
new file mode 100644
index 00000000..d73e93a6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/csv_icon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/deleteicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/deleteicon.gif
new file mode 100644
index 00000000..d544b59b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/deleteicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/downloadicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/downloadicon.gif
new file mode 100644
index 00000000..1dddfb68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/downloadicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.jpg
new file mode 100644
index 00000000..77d7cc20
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.png
new file mode 100644
index 00000000..7a8e9c83
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excel2007.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon.gif
new file mode 100644
index 00000000..3ca1270b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon_multi.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon_multi.gif
new file mode 100644
index 00000000..8ca69611
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/excelicon_multi.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow-right.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow-right.gif
new file mode 100644
index 00000000..d3e37e84
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow-right.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow.gif
new file mode 100644
index 00000000..40a44336
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/green-arrow.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowdn.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowdn.gif
new file mode 100644
index 00000000..4c312a35
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowdn.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowup.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowup.gif
new file mode 100644
index 00000000..23442aaf
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/grnarrowup.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/h.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/h.png
new file mode 100644
index 00000000..389eb08a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/h.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/inactive.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/inactive.gif
new file mode 100644
index 00000000..bb0a7112
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/inactive.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loader.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loader.gif
new file mode 100644
index 00000000..32af9875
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loader.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loading.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loading.gif
new file mode 100644
index 00000000..7ca73e93
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/loading.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/lookup_arrow.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/lookup_arrow.gif
new file mode 100644
index 00000000..84e1aaad
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/lookup_arrow.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/blue.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/blue.png
new file mode 100644
index 00000000..69590b92
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/blue.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/green.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/green.png
new file mode 100644
index 00000000..0f79315e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/green.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/lightblue.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/lightblue.png
new file mode 100644
index 00000000..03586d7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/lightblue.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/map_iphone.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/map_iphone.jpg
new file mode 100644
index 00000000..d6b996c5
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/map_iphone.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/orange.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/orange.png
new file mode 100644
index 00000000..8bee9da3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/orange.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/pink.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/pink.png
new file mode 100644
index 00000000..71a7cd65
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/pink.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/purple.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/purple.png
new file mode 100644
index 00000000..b5787389
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/purple.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/red.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/red.png
new file mode 100644
index 00000000..e993751a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/red.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/yellow.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/yellow.png
new file mode 100644
index 00000000..a9d65acc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/maps/yellow.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/minus.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/minus.gif
index 0c62d1a0..0c62d1a0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/minus.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/minus.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/modify_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/modify_icon.gif
index 994fe655..994fe655 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/modify_icon.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/modify_icon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/page.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/page.gif
new file mode 100644
index 00000000..01c9fbfb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/page.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_large.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_large.gif
new file mode 100644
index 00000000..39673df7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_large.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_small.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_small.gif
new file mode 100644
index 00000000..bb5edcac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pdficon_small.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pen_paper.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pen_paper.gif
new file mode 100644
index 00000000..ba562347
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/pen_paper.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/plus.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/plus.gif
index 4a51f04d..4a51f04d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/plus.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/plus.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/popupicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/popupicon.gif
new file mode 100644
index 00000000..7babac50
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/popupicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/position.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/position.png
new file mode 100644
index 00000000..ba003bca
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/position.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/printer.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/printer.gif
new file mode 100644
index 00000000..b2ce8173
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/printer.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/progress.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/progress.gif
new file mode 100644
index 00000000..b713e27d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/progress.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/question_mark.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/question_mark.jpg
new file mode 100644
index 00000000..808e424d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/question_mark.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_dk.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_dk.gif
new file mode 100644
index 00000000..05fe83ec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_dk.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_lt.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_lt.gif
new file mode 100644
index 00000000..b629545e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/quickhelp_lt.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/r_back.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/r_back.gif
new file mode 100644
index 00000000..d3dc5791
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/r_back.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor.jpg
new file mode 100644
index 00000000..401efb4b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.gif
new file mode 100644
index 00000000..5ea26299
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.jpg
new file mode 100644
index 00000000..23c755b3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/raptor_logo.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/required.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/required.gif
new file mode 100644
index 00000000..4c28998d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/required.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/shareicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/shareicon.gif
new file mode 100644
index 00000000..31153568
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/shareicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/sv.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/sv.png
new file mode 100644
index 00000000..f57fecb1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/sv.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left.gif
new file mode 100644
index 00000000..ccb53633
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left_sel.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left_sel.gif
new file mode 100644
index 00000000..9a534806
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_left_sel.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right.gif
new file mode 100644
index 00000000..62f25162
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right_sel.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right_sel.gif
new file mode 100644
index 00000000..b59c337c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tab_right_sel.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/test_run.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/test_run.gif
new file mode 100644
index 00000000..92c1c3dc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/test_run.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/text.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/text.gif
new file mode 100644
index 00000000..6db2fe1e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/text.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/context-menu-gradient.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/context-menu-gradient.gif
new file mode 100644
index 00000000..6e289cec
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/context-menu-gradient.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_folder.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_folder.gif
new file mode 100644
index 00000000..cd89accb
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_folder.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_minus.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_minus.gif
new file mode 100644
index 00000000..45ff7280
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_minus.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_plus.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_plus.gif
new file mode 100644
index 00000000..39a6bde8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_plus.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet.gif
new file mode 100644
index 00000000..be072083
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_crosstab.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_crosstab.gif
new file mode 100644
index 00000000..f8ccce34
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_crosstab.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_dashboard.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_dashboard.gif
new file mode 100644
index 00000000..46632c8c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_dashboard.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_graph.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_graph.gif
new file mode 100644
index 00000000..c8efeed8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dhtmlgoodies_sheet_graph.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind1.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind1.gif
new file mode 100644
index 00000000..2f9bf5a6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind1.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind2.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind2.gif
new file mode 100644
index 00000000..a1da6310
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/dragDrop_ind2.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_close.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_close.gif
new file mode 100644
index 00000000..bba11d39
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_close.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_dots.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_dots.gif
new file mode 100644
index 00000000..db93fd92
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_dots.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_folder.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_folder.gif
new file mode 100644
index 00000000..ef555b7a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_folder.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_lastsub.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_lastsub.gif
new file mode 100644
index 00000000..6e122445
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_lastsub.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_open.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_open.gif
new file mode 100644
index 00000000..b6d60b84
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_open.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_sub.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_sub.gif
new file mode 100644
index 00000000..e3c8e44e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/folder_sub.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowleft.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowleft.gif
new file mode 100644
index 00000000..22b9bdbe
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowleft.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowright.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowright.gif
new file mode 100644
index 00000000..b827b06a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/tree/grnarrowright.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/txt_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/txt_icon.gif
new file mode 100644
index 00000000..0a73eb52
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/txt_icon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF033.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF033.png
new file mode 100644
index 00000000..74db3c9a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF033.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF034.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF034.png
new file mode 100644
index 00000000..4f607345
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF034.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF035.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF035.png
new file mode 100644
index 00000000..cdc43ff3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF035.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF036.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF036.png
new file mode 100644
index 00000000..da9db296
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/images/uF036.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/BorderLayout-24x24.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/BorderLayout-24x24.png
new file mode 100644
index 00000000..a5324fc3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/BorderLayout-24x24.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/Calendar-16x16.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/Calendar-16x16.png
new file mode 100644
index 00000000..ac970bda
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/Calendar-16x16.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/DeleteCross-16x16.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/DeleteCross-16x16.png
new file mode 100644
index 00000000..79daacfc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/DeleteCross-16x16.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/addbtn.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/addbtn.png
new file mode 100644
index 00000000..8f746db6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/addbtn.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/button_import.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/button_import.png
new file mode 100644
index 00000000..7fab1a02
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/button_import.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon-highlighted.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon-highlighted.png
index 312c4398..312c4398 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/copyicon-highlighted.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon-highlighted.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon.png
new file mode 100644
index 00000000..6c1c3c15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/copyicon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/cross-small.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/cross-small.png
new file mode 100644
index 00000000..bf0ccbe7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/cross-small.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.gif
new file mode 100644
index 00000000..d73e93a6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.jpg
index b4d795bd..b4d795bd 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.jpg
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.jpg
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.png
index bfae8fc3..bfae8fc3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/csv_icon.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/csv_icon.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.gif
index b62241b4..b62241b4 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.png
index aee193de..aee193de 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/deleteicon-highlighted.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon-highlighted.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon.gif
new file mode 100644
index 00000000..4b07af82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/deleteicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/downloadicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/downloadicon.gif
new file mode 100644
index 00000000..1dddfb68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/downloadicon.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/editicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/editicon.gif
index 48538c18..48538c18 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/editicon.gif
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/editicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excel2007.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excel2007.jpg
new file mode 100644
index 00000000..77d7cc20
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excel2007.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon.gif
new file mode 100644
index 00000000..3ca1270b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon_multi.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon_multi.gif
new file mode 100644
index 00000000..8ca69611
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/excelicon_multi.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/executeicon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/executeicon.png
index 295c429b..295c429b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/executeicon.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/executeicon.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_import.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/file_import.png
index 2374ba3f..2374ba3f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_import.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/file_import.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pdficon_small.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pdficon_small.gif
new file mode 100644
index 00000000..bb5edcac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pdficon_small.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pen_paper.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pen_paper.gif
new file mode 100644
index 00000000..ba562347
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pen_paper.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pencil-small.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pencil-small.png
new file mode 100644
index 00000000..e6f2ca02
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/pencil-small.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-add.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-add.png
index c75b6663..c75b6663 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-add.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-add.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-favorite.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-favorite.png
index e75cacc3..e75cacc3 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-favorite.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-favorite.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-my.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-my.png
index 1b9e092d..1b9e092d 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-my.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-my.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-public.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-public.png
index 9ee052ec..9ee052ec 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report-public.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report-public.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report.png
index b0cd69fc..b0cd69fc 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/report.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/report.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/reports.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/reports.png
index 40dca71e..40dca71e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/reports.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/reports.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.gif
new file mode 100644
index 00000000..164b9123
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.gif
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.png
index 7ff964f8..7ff964f8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search.png
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/search.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/tick-small.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/tick-small.png
new file mode 100644
index 00000000..a110aef9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/img/tick-small.png
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js
index 07cd7ee8..07cd7ee8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/CalendarPopup.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax.js
index c24c2688..c24c2688 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js
index 077932e1..077932e1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/ajax_dynamic_content.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/cingular_button.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/cingular_button.js
index 9a053183..9a053183 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/cingular_button.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/cingular_button.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/drupal.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/drupal.js
index cb605f9b..cb605f9b 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/drupal.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/drupal.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/editabledropdown.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/editabledropdown.js
index 6511d8a0..6511d8a0 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/editabledropdown.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/editabledropdown.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js
index b499ca08..b499ca08 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/form-field-tooltip.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/gmap.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/gmap.js
index ba214f61..ba214f61 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/gmap.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/gmap.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.js
index 462cde56..462cde56 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.min.js
index 7c243080..7c243080 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/jquery.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/jquery.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/label_quantum.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/label_quantum.js
index 6e07cbc1..6e07cbc1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/label_quantum.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/label_quantum.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/nova_button.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/nova_button.js
index 75dc28a1..75dc28a1 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/nova_button.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/nova_button.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/other_scripts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/other_scripts.js
index 3784600b..e45b97f9 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/other_scripts.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/other_scripts.js
@@ -271,10 +271,10 @@ function uitmpl_popUpConfig(url, name, w, h, sc, rsz) {
function uitmpl_contact(){
-uitmpl_popUpReg("");
+ uitmpl_popUpReg("");
}
function uitmpl_bizDirect(){
-uitmpl_popUpReg("");
+ uitmpl_popUpReg("");
}
//function uitmpl_closeApp(){
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/persist_table_header.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/persist_table_header.js
index 2c90306f..2c90306f 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/persist_table_header.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/persist_table_header.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/projected_overlay.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/projected_overlay.js
new file mode 100644
index 00000000..00ce65a1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/projected_overlay.js
@@ -0,0 +1,129 @@
+// Create an overlay on the map from a projected image...
+// Author. John D. Coryat 01/2008
+// USNaviguide LLC - http://www.usnaviguide.com
+// Thanks go to Mile Williams EInsert: http://econym.googlepages.com/einsert.js, Google's GOverlay Example and Bratliff's suggestion...
+// Opacity code from TPhoto: http://gmaps.tommangan.us/addtphoto.html
+// 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.
+//
+// Parameters:
+// imageUrl: URL of the image
+// bounds: Bounds object of image destination
+// addZoom: Added Zoom factor as a parameter to the imageUrl (include complete parameter, including separater like '?zoom='
+//
+
+function ProjectedOverlay(imageUrl, bounds, addZoom)
+{
+ this.url_ = imageUrl ;
+ this.bounds_ = bounds ;
+ this.addZ_ = addZoom ; // Add the zoom to the image as a parameter
+
+ // Is this IE, if so we need to use AlphaImageLoader
+
+ this.ie = false ;
+ var agent = navigator.userAgent.toLowerCase();
+ if ((agent.indexOf("msie") > -1) && (agent.indexOf("opera") < 1))
+ {
+ this.ie = true ;
+ }
+}
+
+ProjectedOverlay.prototype = new GOverlay();
+
+ProjectedOverlay.prototype.initialize = function(map)
+{
+ var div = document.createElement("div") ;
+ div.style.position = "absolute" ;
+ div.setAttribute('id',this.id) ;
+ map.getPane(G_MAP_MAP_PANE).appendChild(div) ;
+ this.map_ = map ;
+ this.div_ = div ;
+ if( this.percentOpacity )
+ {
+ this.setOpacity(this.percentOpacity) ;
+ }
+}
+
+// Remove the main DIV from the map pane
+
+ProjectedOverlay.prototype.remove = function()
+{
+ this.div_.parentNode.removeChild(this.div_);
+ delete(this.map) ;
+ delete(this.div) ;
+}
+
+// Copy our data to a new ProjectedOverlay...
+
+ProjectedOverlay.prototype.copy = function()
+{
+ return new ProjectedOverlay(this.url_, this.bounds_, this.addZ_);
+}
+
+// Redraw based on the current projection and zoom level...
+
+ProjectedOverlay.prototype.redraw = function(force)
+{
+ // We only need to redraw if the coordinate system has changed
+ if (!force)
+ {
+ return ;
+ }
+
+ var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
+ var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());
+
+ // Now position our DIV based on the DIV coordinates of our bounds
+
+ this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
+ this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
+ this.div_.style.left = Math.min(c2.x, c1.x) + "px";
+ this.div_.style.top = Math.min(c2.y, c1.y) + "px";
+
+ var url = this.url_ ;
+ var extn = url.substring(url.length - 4, 4) ;
+
+ if ( this.addZ_ )
+ {
+ url += this.addZ_ + this.map_.getZoom() ;
+ }
+
+ if (this.ie && extn.toLowerCase() == '.png')
+ {
+ var loader = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url + "', sizingMethod='scale');" ;
+ this.div_.innerHTML = '<div style="height:' + this.div_.style.height + 'px; width:' + this.div_.style.width + 'px; ' + loader + '" ></div>' ;
+ } else
+ {
+ this.div_.innerHTML = '<img src="' + url + '" width=' + this.div_.style.width + ' height=' + this.div_.style.height + ' >' ;
+ }
+}
+
+ProjectedOverlay.prototype.setOpacity=function(opacity)
+{
+ if (opacity < 0)
+ {
+ opacity = 0 ;
+ }
+ if(opacity > 100)
+ {
+ opacity = 100 ;
+ }
+ var c = opacity/100 ;
+ var d = document.getElementById( this.id ) ;
+
+ if (typeof(d.style.filter) =='string')
+ {
+ d.style.filter = 'alpha(opacity:' + opacity + ')' ;
+ }
+ if (typeof(d.style.KHTMLOpacity) == 'string' )
+ {
+ d.style.KHTMLOpacity = c ;
+ }
+ if (typeof(d.style.MozOpacity) == 'string')
+ {
+ d.style.MozOpacity = c ;
+ }
+ if (typeof(d.style.opacity) == 'string')
+ {
+ d.style.opacity = c ;
+ }
+}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js
index dfe8ab4e..dfe8ab4e 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/prototype-1.6.0.3.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/raptor.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/raptor.js
index a13e77c8..a13e77c8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/raptor.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/raptor.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/rounded-corners.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/rounded-corners.js
index f5df01ce..f5df01ce 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/rounded-corners.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/rounded-corners.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/script.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/script.js
index ea153016..ea153016 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/js/script.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/script.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/ajax.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/ajax.js
new file mode 100644
index 00000000..a727447d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/ajax.js
@@ -0,0 +1,194 @@
+/* Simple AJAX Code-Kit (SACK) v1.6.1 */
+/* ©2005 Gregory Wild-Smith */
+/* www.twilightuniverse.com */
+/* Software licenced under a modified X11 licence,
+ see documentation or authors website for more details */
+
+function sack(file) {
+ this.xmlhttp = null;
+ this.resetData = function() {
+ this.method = "POST";
+ this.queryStringSeparator = "?";
+ this.argumentSeparator = "&";
+ this.URLString = "";
+ this.encodeURIString = true;
+ this.execute = false;
+ this.element = null;
+ this.elementObj = null;
+ this.requestFile = file;
+ this.vars = new Object();
+ this.responseStatus = new Array(2);
+ };
+
+ this.resetFunctions = function() {
+ this.onLoading = function() { };
+ this.onLoaded = function() { };
+ this.onInteractive = function() { };
+ this.onCompletion = function() { };
+ this.onError = function() { };
+ this.onFail = function() { };
+ };
+
+ this.reset = function() {
+ this.resetFunctions();
+ this.resetData();
+ };
+
+ this.createAJAX = function() {
+ try {
+ this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e1) {
+ try {
+ this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (e2) {
+ this.xmlhttp = null;
+ }
+ }
+
+ if (! this.xmlhttp) {
+ if (typeof XMLHttpRequest != "undefined") {
+ this.xmlhttp = new XMLHttpRequest();
+ } else {
+ this.failed = true;
+ }
+ }
+ };
+
+ this.setVar = function(name, value){
+ this.vars[name] = Array(value, false);
+ };
+
+ this.encVar = function(name, value, returnvars) {
+ if (true == returnvars) {
+ return Array(encodeURIComponent(name), encodeURIComponent(value));
+ } else {
+ this.vars[encodeURIComponent(name)] = Array(encodeURIComponent(value), true);
+ }
+ }
+
+ this.processURLString = function(string, encode) {
+ encoded = encodeURIComponent(this.argumentSeparator);
+ regexp = new RegExp(this.argumentSeparator + "|" + encoded);
+ varArray = string.split(regexp);
+ for (i = 0; i < varArray.length; i++){
+ urlVars = varArray[i].split("=");
+ if (true == encode){
+ this.encVar(urlVars[0], urlVars[1]);
+ } else {
+ this.setVar(urlVars[0], urlVars[1]);
+ }
+ }
+ }
+
+ this.createURLString = function(urlstring) {
+ if (this.encodeURIString && this.URLString.length) {
+ this.processURLString(this.URLString, true);
+ }
+ if (urlstring) {
+ if (this.URLString.length) {
+ this.URLString += this.argumentSeparator + urlstring;
+ } else {
+ this.URLString = urlstring;
+ }
+ }
+
+ // prevents caching of URLString
+ this.setVar("rndval", new Date().getTime());
+
+ urlstringtemp = new Array();
+ for (key in this.vars) {
+ if (false == this.vars[key][1] && true == this.encodeURIString) {
+ encoded = this.encVar(key, this.vars[key][0], true);
+ delete this.vars[key];
+ this.vars[encoded[0]] = Array(encoded[1], true);
+ key = encoded[0];
+ }
+
+ urlstringtemp[urlstringtemp.length] = key + "=" + this.vars[key][0];
+ }
+ if (urlstring){
+ this.URLString += this.argumentSeparator + urlstringtemp.join(this.argumentSeparator);
+ } else {
+ this.URLString += urlstringtemp.join(this.argumentSeparator);
+ }
+ }
+
+ this.runResponse = function() {
+ eval(this.response);
+ }
+
+ this.runAJAX = function(urlstring) {
+ if (this.failed) {
+ this.onFail();
+ } else {
+ this.createURLString(urlstring);
+
+ if (this.element) {
+ this.elementObj = document.getElementById(this.element);
+ }
+
+ if (this.xmlhttp) {
+ var self = this;
+ if (this.method == "GET") {
+ totalurlstring = this.requestFile + this.queryStringSeparator + this.URLString;
+ this.xmlhttp.open(this.method, totalurlstring, true);
+ } else {
+ this.xmlhttp.open(this.method, this.requestFile, true);
+ try {
+ this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
+ } catch (e) { }
+ }
+ //document.myForm.action=urlstring;
+ //document.myForm.submit();
+ this.xmlhttp.onreadystatechange = function() {
+ switch (self.xmlhttp.readyState) {
+ case 1:
+ self.onLoading();
+ break;
+ case 2:
+ self.onLoaded();
+ break;
+ case 3:
+ self.onInteractive();
+ break;
+ case 4:
+ self.response = self.xmlhttp.responseText;
+ self.responseXML = self.xmlhttp.responseXML;
+ self.responseStatus[0] = self.xmlhttp.status;
+ self.responseStatus[1] = self.xmlhttp.statusText;
+
+ if (self.execute) {
+ self.runResponse();
+ }
+
+ if (self.elementObj) {
+ elemNodeName = self.elementObj.nodeName;
+ elemNodeName.toLowerCase();
+ if (elemNodeName == "input"
+ || elemNodeName == "select"
+ || elemNodeName == "option"
+ || elemNodeName == "textarea") {
+ self.elementObj.value = self.response;
+ } else {
+ self.elementObj.innerHTML = self.response;
+ }
+ }
+ if (self.responseStatus[0] == "200") {
+ self.onCompletion();
+ } else {
+ self.onError();
+ }
+
+ self.URLString = "";
+ break;
+ }
+ };
+ this.xmlhttp.send(this.URLString);
+
+ }
+ }
+ };
+
+ this.reset() ;
+ this.createAJAX();
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/context-menu.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/context-menu.js
new file mode 100644
index 00000000..70fb7096
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/context-menu.js
@@ -0,0 +1,444 @@
+/************************************************************************************************************
+Context menu
+Copyright (C) 2006 DTHMLGoodies.com, Alf Magne Kalleland
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Dhtmlgoodies.com., hereby disclaims all copyright interest in this script
+written by Alf Magne Kalleland.
+
+Alf Magne Kalleland, 2006
+Owner of DHTMLgoodies.com
+
+
+************************************************************************************************************/
+
+DHTMLGoodies_menuModel = function()
+{
+ var menuItems;
+ this.menuItems = new Array();
+
+
+}
+
+/************************************************************************************************************
+* DHTML menu model class
+*
+* Created: October, 30th, 2006
+* @class Purpose of class: Saves menu item data
+*
+*
+* Demos of this class: demo-menu-strip.html
+*
+* Update log:
+*
+************************************************************************************************************/
+
+
+/**
+* @constructor
+* @class Purpose of class: Organize menu items for different menu widgets. demos of menus: (<a href="../../demos/demo-menu-strip.html" target="_blank">Demo</a>)
+* @version 1.0
+* @author Alf Magne Kalleland(www.dhtmlgoodies.com)
+*/
+
+
+DHTMLGoodies_menuModel.prototype = {
+ // {{{ addItem()
+ /**
+ * Add separator (special type of menu item)
+ *
+ * @param int id of menu item
+ * @param string itemText = text of menu item
+ * @param string itemIcon = file name of menu icon(in front of menu text. Path will be imagePath for the DHTMLSuite + file name)
+ * @param string url = Url of menu item
+ * @param int parent id of menu item
+ * @param String jsFunction Name of javascript function to execute. It will replace the url param. The function with this name will be called and the element triggering the action will be
+ * sent as argument. Name of the element which triggered the menu action may also be sent as a second argument. That depends on the widget. The context menu is an example where
+ * the element triggering the context menu is sent as second argument to this function.
+ *
+ * @public
+ */
+ addItem : function(id,itemText,itemIcon,url,parentId,jsFunction)
+ {
+ this.menuItems[id] = new Array();
+ this.menuItems[id]['id'] = id;
+ this.menuItems[id]['itemText'] = itemText;
+ this.menuItems[id]['itemIcon'] = itemIcon;
+ this.menuItems[id]['url'] = url;
+ this.menuItems[id]['parentId'] = parentId;
+ this.menuItems[id]['separator'] = false;
+ this.menuItems[id]['jsFunction'] = jsFunction;
+
+ }
+ ,
+ // {{{ addSeparator()
+ /**
+ * Add separator (special type of menu item)
+ *
+ * @param int id of menu item
+ * @param int parent id of menu item
+ * @public
+ */
+ addSeparator : function(id,parentId)
+ {
+ this.menuItems[id] = new Array();
+ this.menuItems[id]['parentId'] = parentId;
+ this.menuItems[id]['separator'] = true;
+ }
+ ,
+ // {{{ init()
+ /**
+ * Initilizes the menu model. This method should be called when all items has been added to the model.
+ *
+ *
+ * @public
+ */
+ init : function()
+ {
+ this.__getDepths();
+
+ }
+ // }}}
+ ,
+ // {{{ __getDepths()
+ /**
+ * Create variable for the depth of each menu item.
+ *
+ *
+ * @private
+ */
+ getItems : function()
+ {
+ return this.menuItems;
+ }
+
+ ,
+ // {{{ __getDepths()
+ /**
+ * Create variable for the depth of each menu item.
+ *
+ *
+ * @private
+ */
+ __getDepths : function()
+ {
+ for(var no in this.menuItems){
+ this.menuItems[no]['depth'] = 1;
+ if(this.menuItems[no]['parentId']){
+ this.menuItems[no]['depth'] = this.menuItems[this.menuItems[no]['parentId']]['depth']+1;
+ }
+ }
+ }
+ ,
+ // {{{ __hasSubs()
+ /**
+ * Does a menu item have sub elements ?
+ *
+ *
+ * @private
+ */
+ // }}}
+ __hasSubs : function(id)
+ {
+ for(var no in this.menuItems){ // Looping through menu items
+ if(this.menuItems[no]['parentId']==id)return true;
+ }
+ return false;
+ }
+
+
+}
+
+
+
+var referenceToDHTMLSuiteContextMenu;
+
+
+DHTMLGoodies_contextMenu = function()
+{
+ var menuModels;
+ var menuItems;
+ var menuObject; // Reference to context menu div
+ var layoutCSS;
+ var menuUls; // Array of <ul> elements
+ var width; // Width of context menu
+ var srcElement; // Reference to the element which triggered the context menu, i.e. the element which caused the context menu to be displayed.
+ var indexCurrentlyDisplayedMenuModel; // Index of currently displayed menu model.
+ var imagePath;
+
+ this.menuModels = new Array();
+ this.menuObject = false;
+ this.menuUls = new Array();
+ this.width = 100;
+ this.srcElement = false;
+ this.indexCurrentlyDisplayedMenuModel = false;
+ this.imagePath = imgFolder+'tree/';
+
+}
+
+DHTMLGoodies_contextMenu.prototype =
+{
+
+ setWidth : function(newWidth)
+ {
+ this.width = newWidth;
+ }
+ // }}}
+ ,
+ // {{{ setLayoutCss()
+ /**
+ * Add menu items
+ *
+ * @param String cssFileName Name of css file
+ *
+ * @public
+ */
+ setLayoutCss : function(cssFileName)
+ {
+ this.layoutCSS = cssFileName;
+ }
+ // }}}
+ ,
+ // {{{ attachToElement()
+ /**
+ * Add menu items
+ *
+ * @param Object HTML Element = Reference to html element
+ * @param String elementId = String id of element(optional). An alternative to HTML Element
+ *
+ * @public
+ */
+ attachToElement : function(element,elementId,menuModel)
+ {
+ window.refToThisContextMenu = this;
+ if(!element && elementId)element = document.getElementById(elementId);
+ if(!element.id){
+ element.id = 'context_menu' + Math.random();
+ element.id = element.id.replace('.','');
+ }
+ this.menuModels[element.id] = menuModel;
+ element.oncontextmenu = this.__displayContextMenu;
+ //element.onmousedown = function() { window.refToThisContextMenu.__setReference(window.refToThisContextMenu); };
+ document.documentElement.onclick = this.__hideContextMenu;
+
+ }
+ // }}}
+ ,
+ // {{{ __setReference()
+ /**
+ * Creates a reference to current context menu object. (Note: This method should be deprecated as only one context menu object is needed)
+ *
+ * @param Object context menu object = Reference to context menu object
+ *
+ * @private
+ */
+ __setReference : function(obj)
+ {
+ referenceToDHTMLSuiteContextMenu = obj;
+ }
+ ,
+ // {{{ __displayContextMenu()
+ /**
+ * Displays the context menu
+ *
+ * @param Event e
+ *
+ * @private
+ */
+ __displayContextMenu : function(e)
+ {
+ if(document.all)e = event;
+ var ref = referenceToDHTMLSuiteContextMenu;
+ ref.srcElement = ref.getSrcElement(e);
+
+ if(!ref.indexCurrentlyDisplayedMenuModel || ref.indexCurrentlyDisplayedMenuModel!=this.id){
+ if(ref.indexCurrentlyDisplayedMenuModel){
+ ref.menuObject.innerHTML = '';
+ }else{
+ ref.__createDivs();
+ }
+ ref.menuItems = ref.menuModels[this.id].getItems();
+ ref.__createMenuItems();
+ }
+ ref.indexCurrentlyDisplayedMenuModel=this.id;
+
+ ref.menuObject.style.left = (e.clientX + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft)) + 'px';
+ ref.menuObject.style.top = (e.clientY + Math.max(document.body.scrollTop,document.documentElement.scrollTop)) + 'px';
+ ref.menuObject.style.display='block';
+ return false;
+
+ }
+ // }}}
+ ,
+ // {{{ __displayContextMenu()
+ /**
+ * Add menu items
+ *
+ * @param Event e
+ *
+ * @private
+ */
+ __hideContextMenu : function()
+ {
+ var ref = referenceToDHTMLSuiteContextMenu;
+ if(ref.menuObject)ref.menuObject.style.display = 'none';
+
+
+ }
+ // }}}
+ ,
+ // {{{ __createDivs()
+ /**
+ * Creates general divs for the menu
+ *
+ *
+ * @private
+ */
+ __createDivs : function()
+ {
+ this.menuObject = document.createElement('DIV');
+ this.menuObject.className = 'DHTMLSuite_contextMenu';
+ this.menuObject.style.backgroundImage = 'url(\'' + this.imagePath + 'context-menu-gradient.gif' + '\')';
+ this.menuObject.style.backgroundRepeat = 'repeat-y';
+ if(this.width)this.menuObject.style.width = this.width + 'px';
+ document.body.appendChild(this.menuObject);
+ }
+ // }}}
+ ,
+
+ // {{{ __mouseOver()
+ /**
+ * Display mouse over effect when moving the mouse over a menu item
+ *
+ *
+ * @private
+ */
+ __mouseOver : function()
+ {
+ this.className = 'DHTMLSuite_item_mouseover';
+ if(!document.all){
+ this.style.backgroundPosition = 'left center';
+ }
+
+ }
+ // }}}
+ ,
+ // {{{ __mouseOut()
+ /**
+ * Remove mouse over effect when moving the mouse away from a menu item
+ *
+ *
+ * @private
+ */
+ __mouseOut : function()
+ {
+ this.className = '';
+ if(!document.all){
+ this.style.backgroundPosition = '1px center';
+ }
+ }
+ // }}}
+ ,
+ // {{{ __createMenuItems()
+ /**
+ * Create menu items
+ *
+ *
+ * @private
+ */
+ __evalUrl : function()
+ {
+ var js = this.getAttribute('jsFunction');
+ if(!js)js = this.jsFunction;
+ if(js)eval(js);
+
+ }
+ // }}}
+ ,
+ // {{{ __createMenuItems()
+ /**
+ * Create menu items
+ *
+ *
+ * @private
+ */
+ __createMenuItems : function()
+ {
+ window.refToContextMenu = this; // Reference to menu strip object
+ this.menuUls = new Array();
+ for(var no in this.menuItems){ // Looping through menu items
+ if(!this.menuUls[0]){ // Create main ul element
+ this.menuUls[0] = document.createElement('UL');
+ this.menuObject.appendChild(this.menuUls[0]);
+ }
+
+ if(this.menuItems[no]['depth']==1){
+
+ if(this.menuItems[no]['separator']){
+ var li = document.createElement('DIV');
+ li.className = 'DHTMLSuite_contextMenu_separator';
+ }else{
+ var li = document.createElement('LI');
+ if(this.menuItems[no]['jsFunction']){
+ this.menuItems[no]['url'] = this.menuItems[no]['jsFunction'] + '(this,referenceToDHTMLSuiteContextMenu.srcElement)';
+ }
+ if(this.menuItems[no]['itemIcon']){
+ li.style.backgroundImage = 'url(\'' + this.menuItems[no]['itemIcon'] + '\')';
+ if(!document.all)li.style.backgroundPosition = '1px center';
+
+ }
+
+ if(this.menuItems[no]['url']){
+ var url = this.menuItems[no]['url'] + '';
+ var tmpUrl = url + '';
+ li.setAttribute('jsFunction',url);
+ li.jsFunction = url;
+ li.onclick = this.__evalUrl;
+
+ }
+
+ li.innerHTML = '<a href="#" onclick="return false">' + this.menuItems[no]['itemText'] + '</a>';
+ li.onmouseover = this.__mouseOver;
+ li.onmouseout = this.__mouseOut;
+ }
+ this.menuUls[0].appendChild(li);
+ }
+ }
+ }
+
+ ,
+
+ // {{{ getSrcElement()
+ /**
+ *
+ * Returns a reference to the element which triggered an event.
+ * @param Event e = Event object
+ *
+ *
+ * @private
+ */
+ getSrcElement : function(e)
+ {
+ var el;
+ // Dropped on which element
+ if (e.target) el = e.target;
+ else if (e.srcElement) el = e.srcElement;
+ if (el.nodeType == 3) // defeat Safari bug
+ el = el.parentNode;
+ return el;
+ }
+
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/drag-drop-folder-tree.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/drag-drop-folder-tree.js
new file mode 100644
index 00000000..165306f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/js/tree/drag-drop-folder-tree.js
@@ -0,0 +1,1059 @@
+ /************************************************************************************************************
+Drag and drop folder tree
+Copyright (C) 2006 DTHMLGoodies.com, Alf Magne Kalleland
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Dhtmlgoodies.com., hereby disclaims all copyright interest in this script
+written by Alf Magne Kalleland.
+
+Alf Magne Kalleland, 2006
+Owner of DHTMLgoodies.com
+
+
+************************************************************************************************************/
+
+ var JSTreeObj;
+ var treeUlCounter = 0;
+ var nodeId = 1;
+
+ /* Constructor */
+ function JSDragDropTree()
+ {
+ var idOfTree;
+ var imageFolder;
+ var folderImage;
+ var plusImage;
+ var minusImage;
+ var maximumDepth;
+ var dragNode_source;
+ var dragNode_parent;
+ var dragNode_sourceNextSib;
+ var dragNode_noSiblings;
+ var ajaxObjects;
+
+ var dragNode_destination;
+ var floatingContainer;
+ var dragDropTimer;
+ var dropTargetIndicator;
+ var insertAsSub;
+ var indicator_offsetX;
+ var indicator_offsetX_sub;
+ var indicator_offsetY;
+
+ this.imageFolder = imgFolder+'tree/';
+ this.folderImage = 'dhtmlgoodies_folder.gif';
+ this.plusImage = 'dhtmlgoodies_plus.gif';
+ this.minusImage = 'dhtmlgoodies_minus.gif';
+ this.maximumDepth = 6;
+ var messageMaximumDepthReached;
+ var messageNoRightsOnFolder;
+ var filePathRenameItem;
+ var filePathDeleteItem;
+ var additionalRenameRequestParameters = {};
+ var additionalDeleteRequestParameters = {};
+
+ var renameAllowed;
+ var deleteAllowed;
+ var addAllowed;
+ var currentlyActiveItem;
+ var contextMenu;
+ var currentItemToEdit; // Reference to item currently being edited(example: renamed)
+ var selectedItem; // ADDED BY FARHAN
+ var helpObj;
+
+ this.contextMenu = false;
+ this.floatingContainer = document.createElement('UL');
+ this.floatingContainer.style.position = 'absolute';
+ this.floatingContainer.style.display='none';
+ this.floatingContainer.id = 'floatingContainer';
+ this.insertAsSub = false;
+ document.body.appendChild(this.floatingContainer);
+ this.dragDropTimer = -1;
+ this.dragNode_noSiblings = false;
+ this.currentItemToEdit = false;
+
+ if(document.all){
+ this.indicator_offsetX = 2; // Offset position of small black lines indicating where nodes would be dropped.
+ this.indicator_offsetX_sub = 4;
+ this.indicator_offsetY = 2;
+ }else{
+ this.indicator_offsetX = 1; // Offset position of small black lines indicating where nodes would be dropped.
+ this.indicator_offsetX_sub = 3;
+ this.indicator_offsetY = 2;
+ }
+ if(navigator.userAgent.indexOf('Opera')>=0){
+ this.indicator_offsetX = 2; // Offset position of small black lines indicating where nodes would be dropped.
+ this.indicator_offsetX_sub = 3;
+ this.indicator_offsetY = -7;
+ }
+
+ this.messageMaximumDepthReached = ''; // Use '' if you don't want to display a message
+ this.messageNoRightsOnFolder = 'You do not have access to this folder';
+
+ this.renameAllowed = true;
+ this.deleteAllowed = true;
+ this.addAllowed = true;
+ this.currentlyActiveItem = false;
+ this.filePathRenameItem = 'folderTree_updateItem.php';
+ this.filePathDeleteItem = 'tree';
+ this.ajaxObjects = new Array();
+ this.helpObj = false;
+
+ this.RENAME_STATE_BEGIN = 1;
+ this.RENAME_STATE_CANCELED = 2;
+ this.RENAME_STATE_REQUEST_SENDED = 3;
+ this.renameState = null;
+ }
+
+
+ /* JSDragDropTree class */
+ JSDragDropTree.prototype = {
+ // {{{ addEvent()
+ /**
+ *
+ * This function adds an event listener to an element on the page.
+ *
+ * @param Object whichObject = Reference to HTML element(Which object to assigne the event)
+ * @param String eventType = Which type of event, example "mousemove" or "mouseup"
+ * @param functionName = Name of function to execute.
+ *
+ * @public
+ */
+ addEvent : function(whichObject,eventType,functionName)
+ {
+ if(whichObject.attachEvent){
+ whichObject['e'+eventType+functionName] = functionName;
+ whichObject[eventType+functionName] = function(){whichObject['e'+eventType+functionName]( window.event );}
+ whichObject.attachEvent( 'on'+eventType, whichObject[eventType+functionName] );
+ } else
+ whichObject.addEventListener(eventType,functionName,false);
+ }
+ // }}}
+ ,
+ // {{{ removeEvent()
+ /**
+ *
+ * This function removes an event listener from an element on the page.
+ *
+ * @param Object whichObject = Reference to HTML element(Which object to assigne the event)
+ * @param String eventType = Which type of event, example "mousemove" or "mouseup"
+ * @param functionName = Name of function to execute.
+ *
+ * @public
+ */
+ removeEvent : function(whichObject,eventType,functionName)
+ {
+ if(whichObject.detachEvent){
+ whichObject.detachEvent('on'+eventType, whichObject[eventType+functionName]);
+ whichObject[eventType+functionName] = null;
+ } else
+ whichObject.removeEventListener(eventType,functionName,false);
+ }
+ ,
+ Get_Cookie : function(name) {
+ var start = document.cookie.indexOf(name+"=");
+ var len = start+name.length+1;
+ if ((!start) && (name != document.cookie.substring(0,name.length))) return null;
+ if (start == -1) return null;
+ var end = document.cookie.indexOf(";",len);
+ if (end == -1) end = document.cookie.length;
+ return unescape(document.cookie.substring(len,end));
+ }
+ ,
+ // This function has been slightly modified
+ Set_Cookie : function(name,value,expires,path,domain,secure) {
+ expires = expires * 60*60*24*1000;
+ var today = new Date();
+ var expires_date = new Date( today.getTime() + (expires) );
+ var cookieString = name + "=" +escape(value) +
+ ( (expires) ? ";expires=" + expires_date.toGMTString() : "") +
+ ( (path) ? ";path=" + path : "") +
+ ( (domain) ? ";domain=" + domain : "") +
+ ( (secure) ? ";secure" : "");
+ document.cookie = cookieString;
+ }
+ ,
+ setFileNameRename : function(newFileName)
+ {
+ this.filePathRenameItem = newFileName;
+ }
+ ,
+ setFileNameDelete : function(newFileName)
+ {
+ this.filePathDeleteItem = newFileName;
+ }
+ ,
+ setAdditionalRenameRequestParameters : function(requestParameters)
+ {
+ this.additionalRenameRequestParameters = requestParameters;
+ }
+ ,
+ setAdditionalDeleteRequestParameters : function(requestParameters)
+ {
+ this.additionalDeleteRequestParameters = requestParameters;
+ }
+ ,setRenameAllowed : function(renameAllowed)
+ {
+ this.renameAllowed = renameAllowed;
+ }
+ ,
+ setDeleteAllowed : function(deleteAllowed)
+ {
+ this.deleteAllowed = deleteAllowed;
+ }
+ ,
+ setAddAllowed : function(addAllowed)
+ {
+ this.addAllowed = addAllowed;
+ }
+ ,setMaximumDepth : function(maxDepth)
+ {
+ this.maximumDepth = maxDepth;
+ }
+ ,setMessageMaximumDepthReached : function(newMessage)
+ {
+ this.messageMaximumDepthReached = newMessage;
+ }
+ ,
+ setImageFolder : function(path)
+ {
+ this.imageFolder = path;
+ }
+ ,
+ setFolderImage : function(imagePath)
+ {
+ this.folderImage = imagePath;
+ }
+ ,
+ setPlusImage : function(imagePath)
+ {
+ this.plusImage = imagePath;
+ }
+ ,
+ setMinusImage : function(imagePath)
+ {
+ this.minusImage = imagePath;
+ }
+ ,
+ setTreeId : function(idOfTree)
+ {
+ this.idOfTree = idOfTree;
+ }
+ ,
+ expandAll : function()
+ {
+ var menuItems = document.getElementById(this.idOfTree).getElementsByTagName('LI');
+ for(var no=0;no<menuItems.length;no++){
+ var subItems = menuItems[no].getElementsByTagName('UL');
+ if(subItems.length>0 && subItems[0].style.display!='block'){
+ JSTreeObj.showHideNode(false,menuItems[no].id);
+ }
+ }
+ }
+ ,
+ collapseAll : function()
+ {
+ var menuItems = document.getElementById(this.idOfTree).getElementsByTagName('LI');
+ for(var no=0;no<menuItems.length;no++){
+ var subItems = menuItems[no].getElementsByTagName('UL');
+ if(subItems.length>0 && subItems[0].style.display=='block'){
+ JSTreeObj.showHideNode(false,menuItems[no].id);
+ }
+ }
+ JSTreeObj.showHideNode(false,menuItems[0].id);
+ }
+ ,
+ /*
+ Find top pos of a tree node
+ */
+ getTopPos : function(obj){
+ var top = obj.offsetTop/1;
+ while((obj = obj.offsetParent) != null){
+ if(obj.tagName!='HTML')top += obj.offsetTop;
+ }
+ if(document.all)top = top/1 + 13; else top = top/1 + 4;
+ return top;
+ }
+ ,
+ /*
+ Find left pos of a tree node
+ */
+ getLeftPos : function(obj){
+ var left = obj.offsetLeft/1 + 1;
+ while((obj = obj.offsetParent) != null){
+ if(obj.tagName!='HTML')left += obj.offsetLeft;
+ }
+
+ if(document.all)left = left/1 - 2;
+ return left;
+ }
+
+ ,
+ showHideNode : function(e,inputId)
+ {
+ if(inputId){
+ if(!document.getElementById(inputId))return;
+ thisNode = document.getElementById(inputId).getElementsByTagName('IMG')[0];
+ }else {
+ thisNode = this;
+ if(this.tagName=='A')thisNode = this.parentNode.getElementsByTagName('IMG')[0];
+
+ }
+ if(thisNode.style.visibility=='hidden')return;
+ var parentNode = thisNode.parentNode;
+ inputId = parentNode.id.replace(/[^0-9]/g,'');
+ if(thisNode.src.indexOf(JSTreeObj.plusImage)>=0){
+ thisNode.src = thisNode.src.replace(JSTreeObj.plusImage,JSTreeObj.minusImage);
+ var ul = parentNode.getElementsByTagName('UL')[0];
+ ul.style.display='block';
+ if(!initExpandedNodes)initExpandedNodes = ',';
+ if(initExpandedNodes.indexOf(',' + inputId + ',')<0) initExpandedNodes = initExpandedNodes + inputId + ',';
+ }else{
+ thisNode.src = thisNode.src.replace(JSTreeObj.minusImage,JSTreeObj.plusImage);
+ parentNode.getElementsByTagName('UL')[0].style.display='none';
+ initExpandedNodes = initExpandedNodes.replace(',' + inputId,'');
+ }
+ JSTreeObj.Set_Cookie('dhtmlgoodies_expandedNodes',initExpandedNodes,500);
+ return false;
+ }
+ ,
+ /*expand only the selected node*/
+ showSelectedNode : function(selectedItemId)
+ {
+ var menuItems = document.getElementById(this.idOfTree).getElementsByTagName('LI'); // Get an array of all menu items
+
+ var selectedNode ;
+ for(var no=0;no<menuItems.length;no++){
+ if (selectedItemId != null && selectedItemId == menuItems[no].id.replace(/[^0-9]/gi,'')){
+ selectedNode = menuItems[no];
+ break;
+ }
+ }
+ do{
+ if (selectedNode != null){
+ var subItems = selectedNode.getElementsByTagName('UL');
+ if(subItems && subItems.length>0 && subItems[0].style.display!='block'){
+ JSTreeObj.showHideNode(false,selectedNode.id);
+ }
+ selectedNode = selectedNode.parentNode;
+ }
+ }while (selectedNode && selectedNode.id.replace(/[^0-9]/gi,'') != '0');
+ return false;
+ }
+ ,
+ isDeleteAllowed : function(selectedItemId)
+ {
+ var menuItems = document.getElementById(this.idOfTree).getElementsByTagName('LI'); // Get an array of all menu items
+
+ var selectedNode ;
+ for(var no=0;no<menuItems.length;no++){
+ if (selectedItemId != null && selectedItemId == menuItems[no].id.replace(/[^0-9]/gi,'')){
+ selectedNode = menuItems[no];
+ break;
+ }
+ }
+ if (selectedNode && selectedNode.getAttribute('noDelete') && selectedNode.getAttribute('noDelete') == 'true')
+ return false;
+ else
+ return true;
+
+ }
+ ,
+ isAddAllowed : function(selectedItemId)
+ {
+ var menuItems = document.getElementById(this.idOfTree).getElementsByTagName('LI'); // Get an array of all menu items
+
+ var selectedNode ;
+ for(var no=0;no<menuItems.length;no++){
+ if (selectedItemId != null && selectedItemId == menuItems[no].id.replace(/[^0-9]/gi,'')){
+ selectedNode = menuItems[no];
+ break;
+ }
+ }
+ if (selectedNode && selectedNode.getAttribute('noChild') && selectedNode.getAttribute('noChild') == 'true')
+ return false;
+ else
+ return true;
+
+ }
+ ,
+ /* Initialize drag */
+ initDrag : function(e)
+ {
+ if(document.all)e = event;
+
+ var subs = JSTreeObj.floatingContainer.getElementsByTagName('LI');
+ if(subs.length>0){
+ if(JSTreeObj.dragNode_sourceNextSib){
+ JSTreeObj.dragNode_parent.insertBefore(JSTreeObj.dragNode_source,JSTreeObj.dragNode_sourceNextSib);
+ }else{
+ JSTreeObj.dragNode_parent.appendChild(JSTreeObj.dragNode_source);
+ }
+ }
+
+ JSTreeObj.dragNode_source = this.parentNode;
+ JSTreeObj.dragNode_parent = this.parentNode.parentNode;
+ JSTreeObj.dragNode_sourceNextSib = false;
+
+
+ if(JSTreeObj.dragNode_source.nextSibling)JSTreeObj.dragNode_sourceNextSib = JSTreeObj.dragNode_source.nextSibling;
+ JSTreeObj.dragNode_destination = false;
+ JSTreeObj.dragDropTimer = 0;
+ JSTreeObj.timerDrag();
+ return false;
+ }
+ ,
+ timerDrag : function()
+ {
+ if(this.dragDropTimer>=0 && this.dragDropTimer<10){
+ this.dragDropTimer = this.dragDropTimer + 1;
+ setTimeout('JSTreeObj.timerDrag()',20);
+ return;
+ }
+ if(this.dragDropTimer==10)
+ {
+ JSTreeObj.floatingContainer.style.display='block';
+ JSTreeObj.floatingContainer.appendChild(JSTreeObj.dragNode_source);
+ }
+ }
+ ,
+ moveDragableNodes : function(e)
+ {
+ if(JSTreeObj.dragDropTimer<10)return;
+ if(document.all)e = event;
+ dragDrop_x = e.clientX/1 + 5 + document.body.scrollLeft;
+ dragDrop_y = e.clientY/1 + 5 + document.documentElement.scrollTop;
+
+ JSTreeObj.floatingContainer.style.left = dragDrop_x + 'px';
+ JSTreeObj.floatingContainer.style.top = dragDrop_y + 'px';
+
+ var thisObj = this;
+ if(thisObj.tagName=='A' || thisObj.tagName=='IMG')thisObj = thisObj.parentNode;
+
+ JSTreeObj.dragNode_noSiblings = false;
+ var tmpVar = thisObj.getAttribute('noSiblings');
+ if(!tmpVar)tmpVar = thisObj.noSiblings;
+ if(tmpVar=='true')JSTreeObj.dragNode_noSiblings=true;
+
+ if(thisObj && thisObj.id)
+ {
+ JSTreeObj.dragNode_destination = thisObj;
+ var img = thisObj.getElementsByTagName('IMG')[1];
+ var tmpObj= JSTreeObj.dropTargetIndicator;
+ tmpObj.style.display='block';
+
+ var eventSourceObj = this;
+ if(JSTreeObj.dragNode_noSiblings && eventSourceObj.tagName=='IMG')eventSourceObj = eventSourceObj.nextSibling;
+
+ var tmpImg = tmpObj.getElementsByTagName('IMG')[0];
+ if(this.tagName=='A' || JSTreeObj.dragNode_noSiblings){
+ tmpImg.src = tmpImg.src.replace('ind1','ind2');
+ JSTreeObj.insertAsSub = true;
+ tmpObj.style.left = (JSTreeObj.getLeftPos(eventSourceObj) + JSTreeObj.indicator_offsetX_sub) + 'px';
+ }else{
+ tmpImg.src = tmpImg.src.replace('ind2','ind1');
+ JSTreeObj.insertAsSub = false;
+ tmpObj.style.left = (JSTreeObj.getLeftPos(eventSourceObj) + JSTreeObj.indicator_offsetX) + 'px';
+ }
+
+ tmpObj.style.top = (JSTreeObj.getTopPos(thisObj) + JSTreeObj.indicator_offsetY) - document.getElementById("scrollableTable").scrollTop + 'px' ;
+
+
+ }
+ var divHeight = document.getElementById("scrollableTable").style.height;
+ divHeight = divHeight.substring(0, divHeight.indexOf("px"));
+ if (dragDrop_y - JSTreeObj.getTopPos(document.getElementById("scrollableTable"))< 50)
+ document.getElementById("scrollableTable").scrollTop = document.getElementById("scrollableTable").scrollTop - 5;
+ else if (dragDrop_y - JSTreeObj.getTopPos(document.getElementById("scrollableTable")) > divHeight - 50)
+ document.getElementById("scrollableTable").scrollTop = document.getElementById("scrollableTable").scrollTop + 5;
+
+ return false;
+
+ }
+ ,
+ dropDragableNodes:function()
+ {
+ if(JSTreeObj.dragDropTimer<10){
+ JSTreeObj.dragDropTimer = -1;
+ return;
+ }
+ var showMessage = false;
+ var message = '';
+ if(JSTreeObj.dragNode_destination){ // Check depth
+ var countUp = JSTreeObj.dragDropCountLevels(JSTreeObj.dragNode_destination,'up');
+ var countDown = JSTreeObj.dragDropCountLevels(JSTreeObj.dragNode_source,'down');
+ var countLevels = countUp/1 + countDown/1 + (JSTreeObj.insertAsSub?1:0);
+
+ if(countLevels>JSTreeObj.maximumDepth){
+ JSTreeObj.dragNode_destination = false;
+ showMessage = true; // Used later down in this function
+ message = JSTreeObj.messageMaximumDepthReachedl
+ }
+ }
+ if (JSTreeObj.dragNode_destination && JSTreeObj.dragNode_destination.getAttribute('noDrop') == 'true'){
+ JSTreeObj.dragNode_destination = false;
+ showMessage = true; // Used later down in this function
+ message = JSTreeObj.messageNoRightsOnFolder;
+ }
+
+
+ if(JSTreeObj.dragNode_destination){
+
+ if(JSTreeObj.insertAsSub){
+ var uls = JSTreeObj.dragNode_destination.getElementsByTagName('UL');
+ if(uls.length>0){
+ ul = uls[0];
+ ul.style.display='block';
+
+ var lis = ul.getElementsByTagName('LI');
+
+ if(lis.length>0){ // Sub elements exists - drop dragable node before the first one
+ ul.insertBefore(JSTreeObj.dragNode_source,lis[0]);
+ }else { // No sub exists - use the appendChild method - This line should not be executed unless there's something wrong in the HTML, i.e empty <ul>
+ ul.appendChild(JSTreeObj.dragNode_source);
+ }
+ }else{
+ var ul = document.createElement('UL');
+ ul.style.display='block';
+ JSTreeObj.dragNode_destination.appendChild(ul);
+ ul.appendChild(JSTreeObj.dragNode_source);
+ }
+ var img = JSTreeObj.dragNode_destination.getElementsByTagName('IMG')[0];
+ img.style.visibility='visible';
+ img.src = img.src.replace(JSTreeObj.plusImage,JSTreeObj.minusImage);
+
+
+ }else{
+ if(JSTreeObj.dragNode_destination.nextSibling){
+ var nextSib = JSTreeObj.dragNode_destination.nextSibling;
+ nextSib.parentNode.insertBefore(JSTreeObj.dragNode_source,nextSib);
+ }else{
+ JSTreeObj.dragNode_destination.parentNode.appendChild(JSTreeObj.dragNode_source);
+ }
+ }
+ /* Clear parent object */
+ var tmpObj = JSTreeObj.dragNode_parent;
+ var lis = tmpObj.getElementsByTagName('LI');
+ if(lis.length==0){
+ var img = tmpObj.parentNode.getElementsByTagName('IMG')[0];
+ img.style.visibility='hidden'; // Hide [+],[-] icon
+ tmpObj.parentNode.removeChild(tmpObj);
+ }
+
+ }else{
+ // Putting the item back to it's original location
+
+ if(JSTreeObj.dragNode_sourceNextSib){
+ JSTreeObj.dragNode_parent.insertBefore(JSTreeObj.dragNode_source,JSTreeObj.dragNode_sourceNextSib);
+ }else{
+ JSTreeObj.dragNode_parent.appendChild(JSTreeObj.dragNode_source);
+ }
+
+ }
+ JSTreeObj.dropTargetIndicator.style.display='none';
+ JSTreeObj.dragDropTimer = -1;
+ if(showMessage && message){ alert(message); return;}
+ //save tree structure
+ saveMyTree_byForm();
+ }
+ ,
+ createDropIndicator : function()
+ {
+ this.dropTargetIndicator = document.createElement('DIV');
+ this.dropTargetIndicator.style.position = 'absolute';
+ this.dropTargetIndicator.style.display='none';
+ var img = document.createElement('IMG');
+ img.src = this.imageFolder + 'dragDrop_ind1.gif';
+ img.id = 'dragDropIndicatorImage';
+ this.dropTargetIndicator.appendChild(img);
+ document.body.appendChild(this.dropTargetIndicator);
+
+ }
+ ,
+ dragDropCountLevels : function(obj,direction,stopAtObject){
+ var countLevels = 0;
+ if(direction=='up'){
+ while(obj.parentNode && obj.parentNode!=stopAtObject){
+ obj = obj.parentNode;
+ if(obj.tagName=='UL')countLevels = countLevels/1 +1;
+ }
+ return countLevels;
+ }
+
+ if(direction=='down'){
+ var subObjects = obj.getElementsByTagName('LI');
+ for(var no=0;no<subObjects.length;no++){
+ countLevels = Math.max(countLevels,JSTreeObj.dragDropCountLevels(subObjects[no],"up",obj));
+ }
+ return countLevels;
+
+ }
+ }
+ ,
+ cancelEvent : function()
+ {
+ return false;
+ }
+ ,
+ cancelSelectionEvent : function()
+ {
+
+ if(JSTreeObj.dragDropTimer<10)return true;
+ return false;
+ }
+ ,getNodeOrders : function(initObj,saveString)
+ {
+
+ if(!saveString)var saveString = '';
+ if(!initObj){
+ initObj = document.getElementById(this.idOfTree);
+
+ }
+ var lis = initObj.getElementsByTagName('LI');
+
+ if(lis.length>0){
+ var li = lis[0];
+ while(li){
+ if(li.id){
+ if(saveString.length>0)saveString = saveString + ',';
+ var numericID = li.id.replace(/[^0-9]/gi,'');
+ if(numericID.length==0)numericID='A';
+ var numericParentID = li.parentNode.parentNode.id.replace(/[^0-9]/gi,'');
+ if(numericID!='0'){
+ saveString = saveString + numericID;
+ saveString = saveString + '-';
+
+
+ if(li.parentNode.id!=this.idOfTree)saveString = saveString + numericParentID; else saveString = saveString + '0';
+ }
+ var ul = li.getElementsByTagName('UL');
+ if(ul.length>0){
+ saveString = this.getNodeOrders(ul[0],saveString);
+ }
+ }
+ li = li.nextSibling;
+ }
+ }
+
+ if(initObj.id == this.idOfTree){
+ return saveString;
+
+ }
+ return saveString;
+ }
+ ,highlightItem : function(inputObj,e)
+ {
+ if(JSTreeObj.currentlyActiveItem)JSTreeObj.currentlyActiveItem.className = '';
+ this.className = 'highlightedNodeItem';
+ JSTreeObj.currentlyActiveItem = this;
+ }
+ ,clickItem : function(inputObj,e)
+ {
+ if(JSTreeObj.currentlyActiveItem) JSTreeObj.currentlyActiveItem.className = '';
+ this.className = 'highlightedNodeItem';
+ JSTreeObj.currentlyActiveItem = this;
+ JSTreeObj.selectedItem = this;
+ },
+ removeHighlight : function()
+ {
+ //if(JSTreeObj.currentlyActiveItem)JSTreeObj.currentlyActiveItem.className = '';
+ //JSTreeObj.currentlyActiveItem = false;
+ }
+ ,
+ hasSubNodes : function(obj)
+ {
+ var subs = obj.getElementsByTagName('LI');
+ if(subs.length>0)return true;
+ return false;
+ }
+ ,
+ deleteItem : function(obj1,obj2)
+ {
+ var message = 'Click OK to delete item ' + obj2.innerHTML;
+ if(this.hasSubNodes(obj2.parentNode)) message = message + ' and it\'s sub nodes';
+ if(confirm(message)){
+ this.__deleteItem_step2(obj2.parentNode); // Sending <LI> tag to the __deleteItem_step2 method
+ //deleteItem();
+ }else{
+ return false;
+ }
+
+
+ }
+ ,
+ addItem : function(obj1,obj2)
+ {
+ var message = 'Click OK to Add item ' + obj2.innerHTML;
+ return this.__addItem_step2(obj2.parentNode); // Sending <LI> tag to the __addItem_step2 method
+ }
+ ,
+ createMenuReport : function(obj1,obj2)
+ {
+ JSTreeObj.selectedItem = obj2;
+ createReport();
+ }
+ ,
+ runMenuReport : function(obj1,obj2)
+ {
+ JSTreeObj.selectedItem = obj2;
+ runReport();
+
+ }
+ ,
+ editMenuReport : function(obj1,obj2)
+ {
+ JSTreeObj.selectedItem = obj2;
+ editReport();
+ }
+ ,
+ deleteMenuReport : function(obj1,obj2)
+ {
+ JSTreeObj.selectedItem = obj2;
+ if (confirm("Do you want to delete this report?")){
+ deleteReport();
+ }
+
+ }
+ ,
+ __refreshDisplay : function(obj)
+ {
+ if(this.hasSubNodes(obj))return;
+
+ var img = obj.getElementsByTagName('IMG')[0];
+ img.style.visibility = 'hidden';
+ }
+ ,
+ __deleteItem_step2 : function(obj)
+ {
+
+ var saveString = obj.id.replace(/[^0-9]/gi,'');
+
+ var lis = obj.getElementsByTagName('LI');
+ for(var no=0;no<lis.length;no++){
+ saveString = saveString + ',' + lis[no].id.replace(/[^0-9]/gi,'');
+ }
+
+ // Creating ajax object and send items
+ var ajaxIndex = JSTreeObj.ajaxObjects.length;
+ JSTreeObj.ajaxObjects[ajaxIndex] = new sack();
+ JSTreeObj.ajaxObjects[ajaxIndex].method = "GET";
+ JSTreeObj.ajaxObjects[ajaxIndex].setVar("deleteIds", saveString);
+ document.all.deleteIds.value=saveString;
+ JSTreeObj.__addAdditionalRequestParameters(JSTreeObj.ajaxObjects[ajaxIndex], JSTreeObj.additionalDeleteRequestParameters);
+ JSTreeObj.ajaxObjects[ajaxIndex].requestFile = JSTreeObj.filePathDeleteItem; // Specifying which file to get
+ JSTreeObj.ajaxObjects[ajaxIndex].onCompletion = function() { JSTreeObj.__deleteComplete(ajaxIndex,obj); } ; // Specify function that will be executed after file has been found
+ //JSTreeObj.ajaxObjects[ajaxIndex].runAJAX(); // Execute AJAX function
+ deleteMyTree_byForm();
+
+
+ }
+ ,
+ __addItem_step2 : function(obj)
+ {
+ var parentId = obj.id.replace(/[^0-9]/gi,'');
+ document.all.newName.value="";
+ document.all.saveString.value=parentId;
+ if (selectedFolderId)
+ selectedFolderId = parentId;
+
+ addMyTree_byForm();
+
+ }
+ ,
+ __deleteComplete : function(ajaxIndex,obj)
+ {
+ if(this.ajaxObjects[ajaxIndex].response!='OK'){
+ alert('ERROR WHEN TRYING TO DELETE NODE: ' + this.ajaxObjects[ajaxIndex].response); // Rename failed
+ }else{
+ var parentRef = obj.parentNode.parentNode;
+ obj.parentNode.removeChild(obj);
+ this.__refreshDisplay(parentRef);
+
+ }
+
+ }
+ ,
+ __renameComplete : function(ajaxIndex)
+ {
+ if(this.ajaxObjects[ajaxIndex].response!='OK'){
+ alert('ERROR WHEN TRYING TO RENAME NODE: ' + this.ajaxObjects[ajaxIndex].response); // Rename failed
+ }
+ }
+ ,
+ __saveTextBoxChanges : function(e,inputObj)
+ {
+ if(!inputObj && this)inputObj = this;
+ if(document.all)e = event;
+ if(e.keyCode && e.keyCode==27){
+ JSTreeObj.__cancelRename(e,inputObj);
+ return;
+ }
+ inputObj.style.display='none';
+ inputObj.nextSibling.style.visibility='visible';
+ if(inputObj.value.length>0){
+ inputObj.nextSibling.innerHTML = inputObj.value;
+ // Send changes to the server.
+ if (JSTreeObj.renameState != JSTreeObj.RENAME_STATE_BEGIN) {
+ return;
+ }
+ JSTreeObj.renameState = JSTreeObj.RENAME_STATE_REQUEST_SENDED;
+ var ajaxIndex = JSTreeObj.ajaxObjects.length;
+ JSTreeObj.ajaxObjects[ajaxIndex] = new sack();
+ JSTreeObj.ajaxObjects[ajaxIndex].method = "GET";
+ JSTreeObj.ajaxObjects[ajaxIndex].setVar("renameId", inputObj.parentNode.id.replace(/[^0-9]/gi,''));
+ JSTreeObj.ajaxObjects[ajaxIndex].setVar("newName", inputObj.value);
+ JSTreeObj.__addAdditionalRequestParameters(JSTreeObj.ajaxObjects[ajaxIndex], JSTreeObj.additionalRenameRequestParameters);
+ JSTreeObj.ajaxObjects[ajaxIndex].requestFile = JSTreeObj.filePathRenameItem; // Specifying which file to get
+ JSTreeObj.ajaxObjects[ajaxIndex].onCompletion = function() { JSTreeObj.__renameComplete(ajaxIndex); } ; // Specify function that will be executed after file has been found
+ JSTreeObj.ajaxObjects[ajaxIndex].runAJAX(); // Execute AJAX function
+
+ document.all.renameId.value=inputObj.parentNode.id.replace(/[^0-9]/gi,'');
+ document.all.newName.value= inputObj.value;
+ renameMyTree_byForm();
+
+ }
+ }
+ ,
+ __cancelRename : function(e,inputObj)
+ {
+ JSTreeObj.renameState = JSTreeObj.RENAME_STATE_CANCELD;
+ if(!inputObj && this)inputObj = this;
+ inputObj.value = JSTreeObj.helpObj.innerHTML;
+ inputObj.nextSibling.innerHTML = JSTreeObj.helpObj.innerHTML;
+ inputObj.style.display = 'none';
+ inputObj.nextSibling.style.visibility = 'visible';
+ }
+ ,
+ __renameCheckKeyCode : function(e)
+ {
+ if(document.all)e = event;
+ if(e.keyCode==13){ // Enter pressed
+ JSTreeObj.__saveTextBoxChanges(false,this);
+ }
+ if(e.keyCode==27){ // ESC pressed
+ JSTreeObj.__cancelRename(false,this);
+ }
+ }
+ ,
+ __createTextBox : function(obj)
+ {
+ var textBox = document.createElement('INPUT');
+ textBox.className = 'folderTreeTextBox';
+ textBox.value = obj.innerHTML;
+ obj.parentNode.insertBefore(textBox,obj);
+ textBox.id = 'textBox' + obj.parentNode.id.replace(/[^0-9]/gi,'');
+ textBox.onblur = this.__saveTextBoxChanges;
+ textBox.onkeydown = this.__renameCheckKeyCode;
+ textBox.style.height="16px";
+ this.__renameEnableTextBox(obj);
+ }
+ ,
+ __renameEnableTextBox : function(obj)
+ {
+ JSTreeObj.renameState = JSTreeObj.RENAME_STATE_BEGIN;
+ obj.style.visibility = 'hidden';
+ obj.previousSibling.value = obj.innerHTML;
+ obj.previousSibling.style.display = 'inline';
+ obj.previousSibling.select();
+ }
+ ,
+ renameItem : function(obj1,obj2)
+ {
+ currentItemToEdit = obj2.parentNode; // Reference to the <li> tag.
+ if(!obj2.previousSibling || obj2.previousSibling.tagName.toLowerCase()!='input'){
+ this.__createTextBox(obj2);
+ }else{
+ this.__renameEnableTextBox(obj2);
+ }
+ this.helpObj.innerHTML = obj2.innerHTML;
+
+ }
+ ,
+ initTree : function(selectedItemId)
+ {
+ JSTreeObj = this;
+ JSTreeObj.createDropIndicator();
+ document.documentElement.onselectstart = JSTreeObj.cancelSelectionEvent;
+ document.documentElement.ondragstart = JSTreeObj.cancelEvent;
+ document.documentElement.onmousedown = JSTreeObj.removeHighlight;
+
+ /* Creating help object for storage of values */
+ this.helpObj = document.createElement('DIV');
+ this.helpObj.style.display = 'none';
+ document.body.appendChild(this.helpObj);
+ /* Create context menu */
+ if(this.deleteAllowed || this.renameAllowed || this.addAllowed){
+ try{
+ /* Creating menu model for the context menu, i.e. the datasource */
+ var menuModel = new DHTMLGoodies_menuModel();
+ if(this.deleteAllowed)menuModel.addItem(1,'Delete Folder','','',false,'JSTreeObj.deleteItem');
+ if(this.deleteAllowed)menuModel.addItem(2,'Rename Folder','','',false,'JSTreeObj.renameItem');
+ if(this.addAllowed)menuModel.addItem(3,'New Folder','','',false,'JSTreeObj.addItem');
+ menuModel.addItem(4,'Create Report','','',false,'JSTreeObj.createMenuReport');
+ menuModel.init();
+
+ /*For Reports*/
+ var menuReportNoRights = new DHTMLGoodies_menuModel();
+ menuReportNoRights.addItem(3,'Run','','',false,'JSTreeObj.runItem');
+ menuReportNoRights.init();
+
+ var menuReportWithRights = new DHTMLGoodies_menuModel();
+ menuReportWithRights.addItem(1,'Run','','',false,'JSTreeObj.runMenuReport');
+ menuReportWithRights.addItem(2,'Edit','','',false,'JSTreeObj.editMenuReport');
+ menuReportWithRights.addItem(3,'Delete','','',false,'JSTreeObj.deleteMenuReport');
+ menuReportWithRights.init();
+
+
+ var menuModelRenameOnly = new DHTMLGoodies_menuModel();
+ if(this.renameAllowed)menuModelRenameOnly.addItem(3,'Rename Folder','','',false,'JSTreeObj.renameItem');
+ menuModelRenameOnly.init();
+
+ var menuModelDeleteOnly = new DHTMLGoodies_menuModel();
+ if(this.deleteAllowed)menuModelDeleteOnly.addItem(4,'Delete Folder','','',false,'JSTreeObj.deleteItem');
+ menuModelDeleteOnly.init();
+
+ var menuModelAddOnly = new DHTMLGoodies_menuModel();
+ menuModelAddOnly.addItem(1,'New Folder','','',false,'JSTreeObj.addItem');
+ menuModelAddOnly.init();
+
+ window.refToDragDropTree = this;
+
+ this.contextMenu = new DHTMLGoodies_contextMenu();
+ this.contextMenu.setWidth(120);
+ referenceToDHTMLSuiteContextMenu = this.contextMenu;
+ }catch(e){
+
+ }
+ }
+
+
+ var nodeId = 0;
+ var dhtmlgoodies_tree = document.getElementById(this.idOfTree);
+ var menuItems = dhtmlgoodies_tree.getElementsByTagName('LI'); // Get an array of all menu items
+ for(var no=0;no<menuItems.length;no++){
+ // No children var set ?
+ var noChildren = false;
+ var tmpVar = menuItems[no].getAttribute('noChildren');
+ if(!tmpVar)tmpVar = menuItems[no].noChildren;
+ if(tmpVar=='true')noChildren=true;
+ // No drag var set ?
+ var noDrag = false;
+ var tmpVar = menuItems[no].getAttribute('noDrag');
+ if(!tmpVar)tmpVar = menuItems[no].noDrag;
+ if(tmpVar=='true')noDrag=true;
+
+ nodeId++;
+ var subItems = menuItems[no].getElementsByTagName('UL');
+ var img = document.createElement('IMG');
+ img.src = this.imageFolder + this.plusImage;
+ img.onclick = JSTreeObj.showHideNode;
+
+ if(subItems.length==0)img.style.visibility='hidden';else{
+ subItems[0].id = 'tree_ul_' + treeUlCounter;
+ treeUlCounter++;
+ }
+ var aTag = menuItems[no].getElementsByTagName('A')[0];
+ aTag.id = 'nodeATag' + menuItems[no].id.replace(/[^0-9]/gi,'');
+ //aTag.onclick = JSTreeObj.showHideNode;
+ if(!noDrag)aTag.onmousedown = JSTreeObj.initDrag;
+ if(!noChildren)aTag.onmousemove = JSTreeObj.moveDragableNodes;
+ menuItems[no].insertBefore(img,aTag);
+ //menuItems[no].id = 'dhtmlgoodies_treeNode' + nodeId;
+ var folderImg = document.createElement('IMG');
+ if(!noDrag)folderImg.onmousedown = JSTreeObj.initDrag;
+ folderImg.onmousemove = JSTreeObj.moveDragableNodes;
+ if(menuItems[no].className){
+ folderImg.src = this.imageFolder + menuItems[no].className;
+ } else if (menuItems[no].getAttribute('imgFile')){
+ folderImg.src = this.imageFolder + menuItems[no].getAttribute('imgFile');
+ } else{
+ folderImg.src = this.imageFolder + this.folderImage;
+ }
+ menuItems[no].insertBefore(folderImg,aTag);
+
+ if(this.contextMenu){
+ var noDelete = menuItems[no].getAttribute('noDelete');
+ if(!noDelete)noDelete = menuItems[no].noDelete;
+ var noRename = menuItems[no].getAttribute('noRename');
+ if(!noRename)noRename = menuItems[no].noRename;
+ var noAdd = menuItems[no].getAttribute('noChild');
+ if(!noAdd)noAdd = menuItems[no].noChild;
+
+
+ if (menuItems[no].id.replace(/[^0-9]/gi,'').substr(0,3) != '000' ){//for folders
+ if(noRename=='true' && noDelete=='true'){
+ if (noAdd != 'true'){
+ this.contextMenu.attachToElement(aTag,false,menuModelAddOnly);
+ }
+ }else{
+ if(noDelete == 'true')this.contextMenu.attachToElement(aTag,false,menuModelRenameOnly);
+ else if(noRename == 'true')this.contextMenu.attachToElement(aTag,false,menuModelDeleteOnly);
+ else this.contextMenu.attachToElement(aTag,false,menuModel);
+
+ }
+ }else{//for reports
+ var noRights = menuItems[no].getAttribute('noReportRights');
+ if(!noRights)noRights = menuItems[no].noRights;
+ if(noRights=='true'){
+ this.contextMenu.attachToElement(aTag,false,menuReportNoRights);
+ }else{
+ this.contextMenu.attachToElement(aTag,false,menuReportWithRights);
+ }
+
+
+ }
+ }
+ //highlighting the selected item
+ if (selectedItemId != null && selectedItemId == menuItems[no].id.replace(/[^0-9]/gi,'')){
+ if(JSTreeObj.currentlyActiveItem) JSTreeObj.currentlyActiveItem.className = '';
+ aTag.className = 'highlightedNodeItem';
+ JSTreeObj.currentlyActiveItem = aTag;
+ JSTreeObj.selectedItem = aTag;
+ folderImg.tabindex="1";
+ //alert(1);
+ //folderImg.focus();
+ }
+ this.addEvent(aTag,'contextmenu',this.highlightItem);
+ this.addEvent(aTag,'click',this.clickItem);
+
+
+
+ }
+
+
+
+ initExpandedNodes = this.Get_Cookie('dhtmlgoodies_expandedNodes');
+ if(initExpandedNodes){
+ var nodes = initExpandedNodes.split(',');
+ for(var no=0;no<nodes.length;no++){
+ if(nodes[no])this.showHideNode(false,nodes[no]);
+ }
+ }
+
+
+
+
+ document.documentElement.onmousemove = JSTreeObj.moveDragableNodes;
+ document.documentElement.onmouseup = JSTreeObj.dropDragableNodes;
+ }
+ ,
+ __addAdditionalRequestParameters : function(ajax, parameters)
+ {
+ for (var parameter in parameters) {
+ ajax.setVar(parameter, parameters[parameter]);
+ }
+ }
+ } \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css
index 7f542422..7f542422 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.css
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot
index 15e42a56..15e42a56 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.eot
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js
new file mode 100644
index 00000000..80f2293d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js
@@ -0,0 +1,26735 @@
+/*!
+ * ui-grid - v3.0.7 - 2015-10-06
+ * Copyright (c) 2015 ; License: MIT
+ */
+
+(function () {
+ 'use strict';
+ angular.module('ui.grid.i18n', []);
+ angular.module('ui.grid', ['ui.grid.i18n']);
+})();
+(function () {
+ 'use strict';
+ angular.module('ui.grid').constant('uiGridConstants', {
+ LOG_DEBUG_MESSAGES: true,
+ LOG_WARN_MESSAGES: true,
+ LOG_ERROR_MESSAGES: true,
+ CUSTOM_FILTERS: /CUSTOM_FILTERS/g,
+ COL_FIELD: /COL_FIELD/g,
+ MODEL_COL_FIELD: /MODEL_COL_FIELD/g,
+ TOOLTIP: /title=\"TOOLTIP\"/g,
+ DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,
+ TEMPLATE_REGEXP: /<.+>/,
+ FUNC_REGEXP: /(\([^)]*\))?$/,
+ DOT_REGEXP: /\./g,
+ APOS_REGEXP: /'/g,
+ BRACKET_REGEXP: /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,
+ COL_CLASS_PREFIX: 'ui-grid-col',
+ events: {
+ GRID_SCROLL: 'uiGridScroll',
+ COLUMN_MENU_SHOWN: 'uiGridColMenuShown',
+ ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged
+ COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'
+ },
+ // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html
+ keymap: {
+ TAB: 9,
+ STRG: 17,
+ CAPSLOCK: 20,
+ CTRL: 17,
+ CTRLRIGHT: 18,
+ CTRLR: 18,
+ SHIFT: 16,
+ RETURN: 13,
+ ENTER: 13,
+ BACKSPACE: 8,
+ BCKSP: 8,
+ ALT: 18,
+ ALTR: 17,
+ ALTRIGHT: 17,
+ SPACE: 32,
+ WIN: 91,
+ MAC: 91,
+ FN: null,
+ PG_UP: 33,
+ PG_DOWN: 34,
+ UP: 38,
+ DOWN: 40,
+ LEFT: 37,
+ RIGHT: 39,
+ ESC: 27,
+ DEL: 46,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123
+ },
+ ASC: 'asc',
+ DESC: 'desc',
+ filter: {
+ STARTS_WITH: 2,
+ ENDS_WITH: 4,
+ EXACT: 8,
+ CONTAINS: 16,
+ GREATER_THAN: 32,
+ GREATER_THAN_OR_EQUAL: 64,
+ LESS_THAN: 128,
+ LESS_THAN_OR_EQUAL: 256,
+ NOT_EQUAL: 512,
+ SELECT: 'select',
+ INPUT: 'input'
+ },
+
+ aggregationTypes: {
+ sum: 2,
+ count: 4,
+ avg: 8,
+ min: 16,
+ max: 32
+ },
+
+ // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?
+ CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],
+
+ scrollDirection: {
+ UP: 'up',
+ DOWN: 'down',
+ LEFT: 'left',
+ RIGHT: 'right',
+ NONE: 'none'
+
+ },
+
+ dataChange: {
+ ALL: 'all',
+ EDIT: 'edit',
+ ROW: 'row',
+ COLUMN: 'column',
+ OPTIONS: 'options'
+ },
+ scrollbars: {
+ NEVER: 0,
+ ALWAYS: 1
+ //WHEN_NEEDED: 2
+ }
+ });
+
+})();
+angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {
+ var uiGridCell = {
+ priority: 0,
+ scope: false,
+ require: '?^uiGrid',
+ compile: function() {
+ return {
+ pre: function($scope, $elm, $attrs, uiGridCtrl) {
+ function compileTemplate() {
+ var compiledElementFn = $scope.col.compiledElementFn;
+
+ compiledElementFn($scope, function(clonedElement, scope) {
+ $elm.append(clonedElement);
+ });
+ }
+
+ // If the grid controller is present, use it to get the compiled cell template function
+ if (uiGridCtrl && $scope.col.compiledElementFn) {
+ compileTemplate();
+ }
+ // No controller, compile the element manually (for unit tests)
+ else {
+ if ( uiGridCtrl && !$scope.col.compiledElementFn ){
+ // gridUtil.logError('Render has been called before precompile. Please log a ui-grid issue');
+
+ $scope.col.getCompiledElementFn()
+ .then(function (compiledElementFn) {
+ compiledElementFn($scope, function(clonedElement, scope) {
+ $elm.append(clonedElement);
+ });
+ });
+ }
+ else {
+ var html = $scope.col.cellTemplate
+ .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))
+ .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var cellElement = $compile(html)($scope);
+ $elm.append(cellElement);
+ }
+ }
+ },
+ post: function($scope, $elm, $attrs, uiGridCtrl) {
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ var classAdded;
+ var updateClass = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.cellClass)) {
+ classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.cellClass;
+ }
+ contents.addClass(classAdded);
+ };
+
+ if ($scope.col.cellClass) {
+ updateClass();
+ }
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);
+
+ // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise
+ // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things
+ var cellChangeFunction = function( n, o ){
+ if ( n !== o ) {
+ if ( classAdded || $scope.col.cellClass ){
+ updateClass();
+ }
+
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ };
+
+ // TODO(c0bra): Turn this into a deep array watch
+/* shouldn't be needed any more given track by col.name
+ var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );
+*/
+ var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );
+
+
+ var deregisterFunction = function() {
+ dataChangeDereg();
+// colWatchDereg();
+ rowWatchDereg();
+ };
+
+ $scope.$on( '$destroy', deregisterFunction );
+ $elm.on( '$destroy', deregisterFunction );
+ }
+ };
+ }
+ };
+
+ return uiGridCell;
+}]);
+
+
+(function(){
+
+angular.module('ui.grid')
+.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',
+function ( i18nService, uiGridConstants, gridUtil ) {
+/**
+ * @ngdoc service
+ * @name ui.grid.service:uiGridColumnMenuService
+ *
+ * @description Services for working with column menus, factored out
+ * to make the code easier to understand
+ */
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name initialize
+ * @description Sets defaults, puts a reference to the $scope on
+ * the uiGridController
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {controller} uiGridCtrl the uiGridController for the grid
+ * we're on
+ *
+ */
+ initialize: function( $scope, uiGridCtrl ){
+ $scope.grid = uiGridCtrl.grid;
+
+ // Store a reference to this link/controller in the main uiGrid controller
+ // to allow showMenu later
+ uiGridCtrl.columnMenuScope = $scope;
+
+ // Save whether we're shown or not so the columns can check
+ $scope.menuShown = false;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name setColMenuItemWatch
+ * @description Setup a watch on $scope.col.menuItems, and update
+ * menuItems based on this. $scope.col needs to be set by the column
+ * before calling the menu.
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {controller} uiGridCtrl the uiGridController for the grid
+ * we're on
+ *
+ */
+ setColMenuItemWatch: function ( $scope ){
+ var deregFunction = $scope.$watch('col.menuItems', function (n, o) {
+ if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {
+ n.forEach(function (item) {
+ if (typeof(item.context) === 'undefined' || !item.context) {
+ item.context = {};
+ }
+ item.context.col = $scope.col;
+ });
+
+ $scope.menuItems = $scope.defaultMenuItems.concat(n);
+ }
+ else {
+ $scope.menuItems = $scope.defaultMenuItems;
+ }
+ });
+
+ $scope.$on( '$destroy', deregFunction );
+ },
+
+
+ /**
+ * @ngdoc boolean
+ * @name enableSorting
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) True by default. When enabled, this setting adds sort
+ * widgets to the column header, allowing sorting of the data in the individual column.
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name sortable
+ * @description determines whether this column is sortable
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ sortable: function( $scope ) {
+ if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name isActiveSort
+ * @description determines whether the requested sort direction is current active, to
+ * allow highlighting in the menu
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {string} direction the direction that we'd have selected for us to be active
+ *
+ */
+ isActiveSort: function( $scope, direction ){
+ return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&
+ typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);
+
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name suppressRemoveSort
+ * @description determines whether we should suppress the removeSort option
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ suppressRemoveSort: function( $scope ) {
+ if ($scope.col && $scope.col.suppressRemoveSort) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+
+ /**
+ * @ngdoc boolean
+ * @name enableHiding
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column
+ * using the column menu or the grid menu.
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name hideable
+ * @description determines whether a column can be hidden, by checking the enableHiding columnDef option
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ hideable: function( $scope ) {
+ if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name getDefaultMenuItems
+ * @description returns the default menu items for a column menu
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ *
+ */
+ getDefaultMenuItems: function( $scope ){
+ return [
+ {
+ title: i18nService.getSafeText('sort.ascending'),
+ icon: 'ui-grid-icon-sort-alt-up',
+ action: function($event) {
+ $event.stopPropagation();
+ $scope.sortColumn($event, uiGridConstants.ASC);
+ },
+ shown: function () {
+ return service.sortable( $scope );
+ },
+ active: function() {
+ return service.isActiveSort( $scope, uiGridConstants.ASC);
+ }
+ },
+ {
+ title: i18nService.getSafeText('sort.descending'),
+ icon: 'ui-grid-icon-sort-alt-down',
+ action: function($event) {
+ $event.stopPropagation();
+ $scope.sortColumn($event, uiGridConstants.DESC);
+ },
+ shown: function() {
+ return service.sortable( $scope );
+ },
+ active: function() {
+ return service.isActiveSort( $scope, uiGridConstants.DESC);
+ }
+ },
+ {
+ title: i18nService.getSafeText('sort.remove'),
+ icon: 'ui-grid-icon-cancel',
+ action: function ($event) {
+ $event.stopPropagation();
+ $scope.unsortColumn();
+ },
+ shown: function() {
+ return service.sortable( $scope ) &&
+ typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&
+ typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&
+ !service.suppressRemoveSort( $scope );
+ }
+ },
+ {
+ title: i18nService.getSafeText('column.hide'),
+ icon: 'ui-grid-icon-cancel',
+ shown: function() {
+ return service.hideable( $scope );
+ },
+ action: function ($event) {
+ $event.stopPropagation();
+ $scope.hideColumn();
+ }
+ },
+ {
+ title: i18nService.getSafeText('columnMenu.close'),
+ screenReaderOnly: true,
+ shown: function(){
+ return true;
+ },
+ action: function($event){
+ $event.stopPropagation();
+ }
+ }
+ ];
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name getColumnElementPosition
+ * @description gets the position information needed to place the column
+ * menu below the column header
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {GridCol} column the column we want to position below
+ * @param {element} $columnElement the column element we want to position below
+ * @returns {hash} containing left, top, offset, height, width
+ *
+ */
+ getColumnElementPosition: function( $scope, column, $columnElement ){
+ var positionData = {};
+ positionData.left = $columnElement[0].offsetLeft;
+ positionData.top = $columnElement[0].offsetTop;
+ positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;
+
+ // Get the grid scrollLeft
+ positionData.offset = 0;
+ if (column.grid.options.offsetLeft) {
+ positionData.offset = column.grid.options.offsetLeft;
+ }
+
+ positionData.height = gridUtil.elementHeight($columnElement, true);
+ positionData.width = gridUtil.elementWidth($columnElement, true);
+
+ return positionData;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:uiGridColumnMenuService
+ * @name repositionMenu
+ * @description Reposition the menu below the new column. If the menu has no child nodes
+ * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again
+ * later to fix it
+ * @param {$scope} $scope the $scope from the uiGridColumnMenu
+ * @param {GridCol} column the column we want to position below
+ * @param {hash} positionData a hash containing left, top, offset, height, width
+ * @param {element} $elm the column menu element that we want to reposition
+ * @param {element} $columnElement the column element that we want to reposition underneath
+ *
+ */
+ repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {
+ var menu = $elm[0].querySelectorAll('.ui-grid-menu');
+ var containerId = column.renderContainer ? column.renderContainer : 'body';
+ var renderContainer = column.grid.renderContainers[containerId];
+
+ // It's possible that the render container of the column we're attaching to is
+ // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft
+ // between the render container and the grid
+ var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');
+ var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;
+
+ var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;
+
+ // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170
+ var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);
+ var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
+
+ if ( menu.length !== 0 ){
+ var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');
+ if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {
+ myWidth = gridUtil.elementWidth(menu, true);
+ $scope.lastMenuWidth = myWidth;
+ column.lastMenuWidth = myWidth;
+
+ // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
+ // Get the column menu right padding
+ paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
+ $scope.lastMenuPaddingRight = paddingRight;
+ column.lastMenuPaddingRight = paddingRight;
+ }
+ }
+
+ var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight;
+ if (left < positionData.offset){
+ left = positionData.offset;
+ }
+
+ $elm.css('left', left + 'px');
+ $elm.css('top', (positionData.top + positionData.height) + 'px');
+ }
+
+ };
+
+ return service;
+}])
+
+
+.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',
+function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridColumnMenu
+ * @description Provides the column menu framework, leverages uiGridMenu underneath
+ *
+ */
+
+ var uiGridColumnMenu = {
+ priority: 0,
+ scope: true,
+ require: '^uiGrid',
+ templateUrl: 'ui-grid/uiGridColumnMenu',
+ replace: true,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var self = this;
+
+ uiGridColumnMenuService.initialize( $scope, uiGridCtrl );
+
+ $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );
+
+ // Set the menu items for use with the column menu. The user can later add additional items via the watch
+ $scope.menuItems = $scope.defaultMenuItems;
+ uiGridColumnMenuService.setColMenuItemWatch( $scope );
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.directive:uiGridColumnMenu
+ * @name showMenu
+ * @description Shows the column menu. If the menu is already displayed it
+ * calls the menu to ask it to hide (it will animate), then it repositions the menu
+ * to the right place whilst hidden (it will make an assumption on menu width),
+ * then it asks the menu to show (it will animate), then it repositions the menu again
+ * once we can calculate it's size.
+ * @param {GridCol} column the column we want to position below
+ * @param {element} $columnElement the column element we want to position below
+ */
+ $scope.showMenu = function(column, $columnElement, event) {
+ // Swap to this column
+ $scope.col = column;
+
+ // Get the position information for the column element
+ var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
+
+ if ($scope.menuShown) {
+ // we want to hide, then reposition, then show, but we want to wait for animations
+ // we set a variable, and then rely on the menu-hidden event to call the reposition and show
+ $scope.colElement = $columnElement;
+ $scope.colElementPosition = colElementPosition;
+ $scope.hideThenShow = true;
+
+ $scope.$broadcast('hide-menu', { originalEvent: event });
+ } else {
+ self.shown = $scope.menuShown = true;
+ uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
+
+ $scope.colElement = $columnElement;
+ $scope.colElementPosition = colElementPosition;
+ $scope.$broadcast('show-menu', { originalEvent: event });
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.directive:uiGridColumnMenu
+ * @name hideMenu
+ * @description Hides the column menu.
+ * @param {boolean} broadcastTrigger true if we were triggered by a broadcast
+ * from the menu itself - in which case don't broadcast again as we'll get
+ * an infinite loop
+ */
+ $scope.hideMenu = function( broadcastTrigger ) {
+ $scope.menuShown = false;
+ if ( !broadcastTrigger ){
+ $scope.$broadcast('hide-menu');
+ }
+ };
+
+
+ $scope.$on('menu-hidden', function() {
+ if ( $scope.hideThenShow ){
+ delete $scope.hideThenShow;
+
+ uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
+ $scope.$broadcast('show-menu');
+
+ $scope.menuShown = true;
+ } else {
+ $scope.hideMenu( true );
+
+ if ($scope.col) {
+ //Focus on the menu button
+ gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);
+ }
+ }
+ });
+
+ $scope.$on('menu-shown', function() {
+ $timeout( function() {
+ uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
+ delete $scope.colElementPosition;
+ delete $scope.columnElement;
+ }, 200);
+ });
+
+
+ /* Column methods */
+ $scope.sortColumn = function (event, dir) {
+ event.stopPropagation();
+
+ $scope.grid.sortColumn($scope.col, dir, true)
+ .then(function () {
+ $scope.grid.refresh();
+ $scope.hideMenu();
+ });
+ };
+
+ $scope.unsortColumn = function () {
+ $scope.col.unsort();
+
+ $scope.grid.refresh();
+ $scope.hideMenu();
+ };
+
+ //Since we are hiding this column the default hide action will fail so we need to focus somewhere else.
+ var setFocusOnHideColumn = function(){
+ $timeout(function(){
+ // Get the UID of the first
+ var focusToGridMenu = function(){
+ return gridUtil.focus.byId('grid-menu', $scope.grid);
+ };
+
+ var thisIndex;
+ $scope.grid.columns.some(function(element, index){
+ if (angular.equals(element, $scope.col)) {
+ thisIndex = index;
+ return true;
+ }
+ });
+
+ var previousVisibleCol;
+ // Try and find the next lower or nearest column to focus on
+ $scope.grid.columns.some(function(element, index){
+ if (!element.visible){
+ return false;
+ } // This columns index is below the current column index
+ else if ( index < thisIndex){
+ previousVisibleCol = element;
+ } // This elements index is above this column index and we haven't found one that is lower
+ else if ( index > thisIndex && !previousVisibleCol) {
+ // This is the next best thing
+ previousVisibleCol = element;
+ // We've found one so use it.
+ return true;
+ } // We've reached an element with an index above this column and the previousVisibleCol variable has been set
+ else if (index > thisIndex && previousVisibleCol) {
+ // We are done.
+ return true;
+ }
+ });
+ // If found then focus on it
+ if (previousVisibleCol){
+ var colClass = previousVisibleCol.getColClass();
+ gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason){
+ if (reason !== 'canceled'){ // If this is canceled then don't perform the action
+ //The fallback action is to focus on the grid menu
+ return focusToGridMenu();
+ }
+ });
+ } else {
+ // Fallback action to focus on the grid menu
+ focusToGridMenu();
+ }
+ });
+ };
+
+ $scope.hideColumn = function () {
+ $scope.col.colDef.visible = false;
+ $scope.col.visible = false;
+
+ $scope.grid.queueGridRefresh();
+ $scope.hideMenu();
+ $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );
+
+ // We are hiding so the default action of focusing on the button that opened this menu will fail.
+ setFocusOnHideColumn();
+ };
+ },
+
+
+
+ controller: ['$scope', function ($scope) {
+ var self = this;
+
+ $scope.$watch('menuItems', function (n, o) {
+ self.menuItems = n;
+ });
+ }]
+ };
+
+ return uiGridColumnMenu;
+
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {
+
+ return {
+ compile: function() {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ $scope.col.updateFilters = function( filterable ){
+ $elm.children().remove();
+ if ( filterable ){
+ var template = $scope.col.filterHeaderTemplate;
+
+ $elm.append($compile(template)($scope));
+ }
+ };
+
+ $scope.$on( '$destroy', function() {
+ delete $scope.col.updateFilters;
+ });
+ },
+ post: function ($scope, $elm, $attrs, controllers){
+ $scope.aria = i18nService.getSafeText('headerCell.aria');
+ $scope.removeFilter = function(colFilter, index){
+ colFilter.term = null;
+ //Set the focus to the filter input after the action disables the button
+ gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);
+ };
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',
+ function ($timeout, gridUtil, uiGridConstants, $compile) {
+ var uiGridFooterCell = {
+ priority: 0,
+ scope: {
+ col: '=',
+ row: '=',
+ renderIndex: '='
+ },
+ replace: true,
+ require: '^uiGrid',
+ compile: function compile(tElement, tAttrs, transclude) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var cellFooter = $compile($scope.col.footerCellTemplate)($scope);
+ $elm.append(cellFooter);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ //$elm.addClass($scope.col.getColClass(false));
+ $scope.grid = uiGridCtrl.grid;
+
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ // apply any footerCellClass
+ var classAdded;
+ var updateClass = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.footerCellClass)) {
+ classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.footerCellClass;
+ }
+ contents.addClass(classAdded);
+ };
+
+ if ($scope.col.footerCellClass) {
+ updateClass();
+ }
+
+ $scope.col.updateAggregationValue();
+
+ // Watch for column changes so we can alter the col cell class properly
+/* shouldn't be needed any more, given track by col.name
+ $scope.$watch('col', function (n, o) {
+ if (n !== o) {
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ });
+*/
+
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);
+ // listen for visible rows change and update aggregation values
+ $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );
+ $scope.grid.api.core.on.rowsRendered( $scope, updateClass );
+ $scope.$on( '$destroy', dataChangeDereg );
+ }
+ };
+ }
+ };
+
+ return uiGridFooterCell;
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ // priority: 1000,
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ containerCtrl.footer = $elm;
+
+ var footerTemplate = $scope.grid.options.footerTemplate;
+ gridUtil.getTemplate(footerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+
+ if (containerCtrl) {
+ // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
+ var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
+
+ if (footerViewport) {
+ containerCtrl.footerViewport = footerViewport;
+ }
+ }
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ // gridUtil.logDebug('ui-grid-footer link');
+
+ var grid = uiGridCtrl.grid;
+
+ // Don't animate footer cells
+ gridUtil.disableAnimations($elm);
+
+ containerCtrl.footer = $elm;
+
+ var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
+ if (footerViewport) {
+ containerCtrl.footerViewport = footerViewport;
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ // priority: 1000,
+ require: '^uiGrid',
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ $scope.grid = uiGridCtrl.grid;
+
+
+
+ var footerTemplate = $scope.grid.options.gridFooterTemplate;
+ gridUtil.getTemplate(footerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridGroupPanel', ["$compile", "uiGridConstants", "gridUtil", function($compile, uiGridConstants, gridUtil) {
+ var defaultTemplate = 'ui-grid/ui-grid-group-panel';
+
+ return {
+ restrict: 'EA',
+ replace: true,
+ require: '?^uiGrid',
+ scope: false,
+ compile: function($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var groupPanelTemplate = $scope.grid.options.groupPanelTemplate || defaultTemplate;
+
+ gridUtil.getTemplate(groupPanelTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ $elm.bind('$destroy', function() {
+ // scrollUnbinder();
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
+ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
+ // Do stuff after mouse has been down this many ms on the header cell
+ var mousedownTimeout = 500;
+ var changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa
+
+ var uiGridHeaderCell = {
+ priority: 0,
+ scope: {
+ col: '=',
+ row: '=',
+ renderIndex: '='
+ },
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ replace: true,
+ compile: function() {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
+ $elm.append(cellHeader);
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var renderContainerCtrl = controllers[1];
+
+ $scope.i18n = {
+ headerCell: i18nService.getSafeText('headerCell'),
+ sort: i18nService.getSafeText('sort')
+ };
+ $scope.getSortDirectionAriaLabel = function(){
+ var col = $scope.col;
+ //Trying to recreate this sort of thing but it was getting messy having it in the template.
+ //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
+ var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
+ var label = sortDirectionText;
+ //Append the priority if it exists
+ if (col.sort.priority) {
+ label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority;
+ }
+ return label;
+ };
+
+ $scope.grid = uiGridCtrl.grid;
+
+ $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];
+
+ var initColClass = $scope.col.getColClass(false);
+ $elm.addClass(initColClass);
+
+ // Hide the menu by default
+ $scope.menuShown = false;
+
+ // Put asc and desc sort directions in scope
+ $scope.asc = uiGridConstants.ASC;
+ $scope.desc = uiGridConstants.DESC;
+
+ // Store a reference to menu element
+ var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );
+
+ var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
+
+
+ // apply any headerCellClass
+ var classAdded;
+ var previousMouseX;
+
+ // filter watchers
+ var filterDeregisters = [];
+
+
+ /*
+ * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
+ * Once we have a down event, we need to work out whether we have a click, a drag, or a
+ * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so
+ * we ignore it. A hold would open the menu.
+ *
+ * So, on down event, we put in place handlers for move and up events, and a timer. If the
+ * timer expires before we see a move or up, then we have a long press and hence a column menu open.
+ * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
+ * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
+ * will handle it.
+ *
+ * To deal with touch enabled devices that also have mice, we only create our handlers when
+ * we get the down event, and we create the corresponding handlers - if we're touchstart then
+ * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
+ *
+ * We also suppress the click action whilst this is happening - otherwise after the mouseup there
+ * will be a click event and that can cause the column menu to close
+ *
+ */
+
+ $scope.downFn = function( event ){
+ event.stopPropagation();
+
+ if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
+ event = event.originalEvent;
+ }
+
+ // Don't show the menu if it's not the left button
+ if (event.button && event.button !== 0) {
+ return;
+ }
+ previousMouseX = event.pageX;
+
+ $scope.mousedownStartTime = (new Date()).getTime();
+ $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);
+
+ $scope.mousedownTimeout.then(function () {
+ if ( $scope.colMenu ) {
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
+ }
+ });
+
+ uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
+
+ $scope.offAllEvents();
+ if ( event.type === 'touchstart'){
+ $document.on('touchend', $scope.upFn);
+ $document.on('touchmove', $scope.moveFn);
+ } else if ( event.type === 'mousedown' ){
+ $document.on('mouseup', $scope.upFn);
+ $document.on('mousemove', $scope.moveFn);
+ }
+ };
+
+ $scope.upFn = function( event ){
+ event.stopPropagation();
+ $timeout.cancel($scope.mousedownTimeout);
+ $scope.offAllEvents();
+ $scope.onDownEvents(event.type);
+
+ var mousedownEndTime = (new Date()).getTime();
+ var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;
+
+ if (mousedownTime > mousedownTimeout) {
+ // long click, handled above with mousedown
+ }
+ else {
+ // short click
+ if ( $scope.sortable ){
+ $scope.handleClick(event);
+ }
+ }
+ };
+
+ $scope.moveFn = function( event ){
+ // Chrome is known to fire some bogus move events.
+ var changeValue = event.pageX - previousMouseX;
+ if ( changeValue === 0 ){ return; }
+
+ // we're a move, so do nothing and leave for column move (if enabled) to take over
+ $timeout.cancel($scope.mousedownTimeout);
+ $scope.offAllEvents();
+ $scope.onDownEvents(event.type);
+ };
+
+ $scope.clickFn = function ( event ){
+ event.stopPropagation();
+ $contentsElm.off('click', $scope.clickFn);
+ };
+
+
+ $scope.offAllEvents = function(){
+ $contentsElm.off('touchstart', $scope.downFn);
+ $contentsElm.off('mousedown', $scope.downFn);
+
+ $document.off('touchend', $scope.upFn);
+ $document.off('mouseup', $scope.upFn);
+
+ $document.off('touchmove', $scope.moveFn);
+ $document.off('mousemove', $scope.moveFn);
+
+ $contentsElm.off('click', $scope.clickFn);
+ };
+
+ $scope.onDownEvents = function( type ){
+ // If there is a previous event, then wait a while before
+ // activating the other mode - i.e. if the last event was a touch event then
+ // don't enable mouse events for a wee while (500ms or so)
+ // Avoids problems with devices that emulate mouse events when you have touch events
+
+ switch (type){
+ case 'touchmove':
+ case 'touchend':
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('touchstart', $scope.downFn);
+ $timeout(function(){
+ $contentsElm.on('mousedown', $scope.downFn);
+ }, changeModeTimeout);
+ break;
+ case 'mousemove':
+ case 'mouseup':
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('mousedown', $scope.downFn);
+ $timeout(function(){
+ $contentsElm.on('touchstart', $scope.downFn);
+ }, changeModeTimeout);
+ break;
+ default:
+ $contentsElm.on('click', $scope.clickFn);
+ $contentsElm.on('touchstart', $scope.downFn);
+ $contentsElm.on('mousedown', $scope.downFn);
+ }
+ };
+
+
+ var updateHeaderOptions = function( grid ){
+ var contents = $elm;
+ if ( classAdded ){
+ contents.removeClass( classAdded );
+ classAdded = null;
+ }
+
+ if (angular.isFunction($scope.col.headerCellClass)) {
+ classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
+ }
+ else {
+ classAdded = $scope.col.headerCellClass;
+ }
+ contents.addClass(classAdded);
+
+ var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
+ $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
+
+ // Figure out whether this column is sortable or not
+ if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {
+ $scope.sortable = true;
+ }
+ else {
+ $scope.sortable = false;
+ }
+
+ // Figure out whether this column is filterable or not
+ var oldFilterable = $scope.filterable;
+ if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
+ $scope.filterable = true;
+ }
+ else {
+ $scope.filterable = false;
+ }
+
+ if ( oldFilterable !== $scope.filterable){
+ if ( typeof($scope.col.updateFilters) !== 'undefined' ){
+ $scope.col.updateFilters($scope.filterable);
+ }
+
+ // if column is filterable add a filter watcher
+ if ($scope.filterable) {
+ $scope.col.filters.forEach( function(filter, i) {
+ filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
+ if (n !== o) {
+ uiGridCtrl.grid.api.core.raise.filterChanged();
+ uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ uiGridCtrl.grid.queueGridRefresh();
+ }
+ }));
+ });
+ $scope.$on('$destroy', function() {
+ filterDeregisters.forEach( function(filterDeregister) {
+ filterDeregister();
+ });
+ });
+ } else {
+ filterDeregisters.forEach( function(filterDeregister) {
+ filterDeregister();
+ });
+ }
+
+ }
+
+ // figure out whether we support column menus
+ if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
+ $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
+ $scope.colMenu = true;
+ } else {
+ $scope.colMenu = false;
+ }
+
+ /**
+ * @ngdoc property
+ * @name enableColumnMenu
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description if column menus are enabled, controls the column menus for this specific
+ * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
+ * using this option. If gridOptions.enableColumnMenus === false then you get no column
+ * menus irrespective of the value of this option ). Defaults to true.
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name enableColumnMenus
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Override for column menus everywhere - if set to false then you get no
+ * column menus. Defaults to true.
+ *
+ */
+
+ $scope.offAllEvents();
+
+ if ($scope.sortable || $scope.colMenu) {
+ $scope.onDownEvents();
+
+ $scope.$on('$destroy', function () {
+ $scope.offAllEvents();
+ });
+ }
+ };
+
+/*
+ $scope.$watch('col', function (n, o) {
+ if (n !== o) {
+ // See if the column's internal class has changed
+ var newColClass = $scope.col.getColClass(false);
+ if (newColClass !== initColClass) {
+ $elm.removeClass(initColClass);
+ $elm.addClass(newColClass);
+ initColClass = newColClass;
+ }
+ }
+ });
+*/
+ updateHeaderOptions();
+
+ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);
+
+ $scope.$on( '$destroy', dataChangeDereg );
+
+ $scope.handleClick = function(event) {
+ // If the shift key is being held down, add this column to the sort
+ var add = false;
+ if (event.shiftKey) {
+ add = true;
+ }
+
+ // Sort this column then rebuild the grid's rows
+ uiGridCtrl.grid.sortColumn($scope.col, add)
+ .then(function () {
+ if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
+ uiGridCtrl.grid.refresh();
+ });
+ };
+
+
+ $scope.toggleMenu = function(event) {
+ event.stopPropagation();
+
+ // If the menu is already showing...
+ if (uiGridCtrl.columnMenuScope.menuShown) {
+ // ... and we're the column the menu is on...
+ if (uiGridCtrl.columnMenuScope.col === $scope.col) {
+ // ... hide it
+ uiGridCtrl.columnMenuScope.hideMenu();
+ }
+ // ... and we're NOT the column the menu is on
+ else {
+ // ... move the menu to our column
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
+ }
+ }
+ // If the menu is NOT showing
+ else {
+ // ... show it on our column
+ uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
+ }
+ };
+ }
+ };
+ }
+ };
+
+ return uiGridHeaderCell;
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',
+ function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {
+ var defaultTemplate = 'ui-grid/ui-grid-header';
+ var emptyTemplate = 'ui-grid/ui-grid-no-header';
+
+ return {
+ restrict: 'EA',
+ // templateUrl: 'ui-grid/ui-grid-header',
+ replace: true,
+ // priority: 1000,
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: true,
+ compile: function($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ updateHeaderReferences();
+
+ var headerTemplate;
+ if (!$scope.grid.options.showHeader) {
+ headerTemplate = emptyTemplate;
+ }
+ else {
+ headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
+ }
+
+ gridUtil.getTemplate(headerTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.replaceWith(newElm);
+
+ // And update $elm to be the new element
+ $elm = newElm;
+
+ updateHeaderReferences();
+
+ if (containerCtrl) {
+ // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
+ var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
+
+
+ if (headerViewport) {
+ containerCtrl.headerViewport = headerViewport;
+ angular.element(headerViewport).on('scroll', scrollHandler);
+ $scope.$on('$destroy', function () {
+ angular.element(headerViewport).off('scroll', scrollHandler);
+ });
+ }
+ }
+
+ $scope.grid.queueRefresh();
+ });
+
+ function updateHeaderReferences() {
+ containerCtrl.header = containerCtrl.colContainer.header = $elm;
+
+ var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');
+
+ if (headerCanvases.length > 0) {
+ containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
+ }
+ else {
+ containerCtrl.headerCanvas = null;
+ }
+ }
+
+ function scrollHandler(evt) {
+ if (uiGridCtrl.grid.isScrollingHorizontally) {
+ return;
+ }
+ var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);
+ var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);
+
+ var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);
+ scrollEvent.newScrollLeft = newScrollLeft;
+ if ( horizScrollPercentage > -1 ){
+ scrollEvent.x = { percentage: horizScrollPercentage };
+ }
+
+ uiGridCtrl.grid.scrollContainers(null, scrollEvent);
+ }
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ // gridUtil.logDebug('ui-grid-header link');
+
+ var grid = uiGridCtrl.grid;
+
+ // Don't animate header cells
+ gridUtil.disableAnimations($elm);
+
+ function updateColumnWidths() {
+ // this styleBuilder always runs after the renderContainer, so we can rely on the column widths
+ // already being populated correctly
+
+ var columnCache = containerCtrl.colContainer.visibleColumnCache;
+
+ // Build the CSS
+ // uiGridCtrl.grid.columns.forEach(function (column) {
+ var ret = '';
+ var canvasWidth = 0;
+ columnCache.forEach(function (column) {
+ ret = ret + column.getColClassDefinition();
+ canvasWidth += column.drawnWidth;
+ });
+
+ containerCtrl.colContainer.canvasWidth = canvasWidth;
+
+ // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
+ return ret;
+ }
+
+ containerCtrl.header = $elm;
+
+ var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
+ if (headerViewport) {
+ containerCtrl.headerViewport = headerViewport;
+ }
+
+ //todo: remove this if by injecting gridCtrl into unit tests
+ if (uiGridCtrl) {
+ uiGridCtrl.grid.registerStyleComputation({
+ priority: 15,
+ func: updateColumnWidths
+ });
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {
+ /**
+ * @ngdoc service
+ * @name ui.grid.gridMenuService
+ *
+ * @description Methods for working with the grid menu
+ */
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name initialize
+ * @description Sets up the gridMenu. Most importantly, sets our
+ * scope onto the grid object as grid.gridMenuScope, allowing us
+ * to operate when passed only the grid. Second most importantly,
+ * we register the 'addToGridMenu' and 'removeFromGridMenu' methods
+ * on the core api.
+ * @param {$scope} $scope the scope of this gridMenu
+ * @param {Grid} grid the grid to which this gridMenu is associated
+ */
+ initialize: function( $scope, grid ){
+ grid.gridMenuScope = $scope;
+ $scope.grid = grid;
+ $scope.registeredMenuItems = [];
+
+ // not certain this is needed, but would be bad to create a memory leak
+ $scope.$on('$destroy', function() {
+ if ( $scope.grid && $scope.grid.gridMenuScope ){
+ $scope.grid.gridMenuScope = null;
+ }
+ if ( $scope.grid ){
+ $scope.grid = null;
+ }
+ if ( $scope.registeredMenuItems ){
+ $scope.registeredMenuItems = null;
+ }
+ });
+
+ $scope.registeredMenuItems = [];
+
+ /**
+ * @ngdoc function
+ * @name addToGridMenu
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description add items to the grid menu. Used by features
+ * to add their menu items if they are enabled, can also be used by
+ * end users to add menu items. This method has the advantage of allowing
+ * remove again, which can simplify management of which items are included
+ * in the menu when. (Noting that in most cases the shown and active functions
+ * provide a better way to handle visibility of menu items)
+ * @param {Grid} grid the grid on which we are acting
+ * @param {array} items menu items in the format as described in the tutorial, with
+ * the added note that if you want to use remove you must also specify an `id` field,
+ * which is provided when you want to remove an item. The id should be unique.
+ *
+ */
+ grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );
+
+ /**
+ * @ngdoc function
+ * @name removeFromGridMenu
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Remove an item from the grid menu based on a provided id. Assumes
+ * that the id is unique, removes only the last instance of that id. Does nothing if
+ * the specified id is not found
+ * @param {Grid} grid the grid on which we are acting
+ * @param {string} id the id we'd like to remove from the menu
+ *
+ */
+ grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToGridMenu
+ * @propertyOf ui.grid.gridMenuService
+ * @description add items to the grid menu. Used by features
+ * to add their menu items if they are enabled, can also be used by
+ * end users to add menu items. This method has the advantage of allowing
+ * remove again, which can simplify management of which items are included
+ * in the menu when. (Noting that in most cases the shown and active functions
+ * provide a better way to handle visibility of menu items)
+ * @param {Grid} grid the grid on which we are acting
+ * @param {array} items menu items in the format as described in the tutorial, with
+ * the added note that if you want to use remove you must also specify an `id` field,
+ * which is provided when you want to remove an item. The id should be unique.
+ *
+ */
+ addToGridMenu: function( grid, menuItems ) {
+ if ( !angular.isArray( menuItems ) ) {
+ gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');
+ } else {
+ if ( grid.gridMenuScope ){
+ grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];
+ grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );
+ } else {
+ gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid');
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name removeFromGridMenu
+ * @methodOf ui.grid.gridMenuService
+ * @description Remove an item from the grid menu based on a provided id. Assumes
+ * that the id is unique, removes only the last instance of that id. Does nothing if
+ * the specified id is not found. If there is no gridMenuScope or registeredMenuItems
+ * then do nothing silently - the desired result is those menu items not be present and they
+ * aren't.
+ * @param {Grid} grid the grid on which we are acting
+ * @param {string} id the id we'd like to remove from the menu
+ *
+ */
+ removeFromGridMenu: function( grid, id ){
+ var foundIndex = -1;
+
+ if ( grid && grid.gridMenuScope ){
+ grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {
+ if ( value.id === id ){
+ if (foundIndex > -1) {
+ gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );
+ } else {
+
+ foundIndex = index;
+ }
+ }
+ });
+ }
+
+ if ( foundIndex > -1 ){
+ grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );
+ }
+ },
+
+
+ /**
+ * @ngdoc array
+ * @name gridMenuCustomItems
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) An array of menu items that should be added to
+ * the gridMenu. Follow the format documented in the tutorial for column
+ * menu customisation. The context provided to the action function will
+ * include context.grid. An alternative if working with dynamic menus is to use the
+ * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles
+ * some of the management of items for you.
+ *
+ */
+ /**
+ * @ngdoc boolean
+ * @name gridMenuShowHideColumns
+ * @propertyOf ui.grid.class:GridOptions
+ * @description true by default, whether the grid menu should allow hide/show
+ * of columns
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name getMenuItems
+ * @description Decides the menu items to show in the menu. This is a
+ * combination of:
+ *
+ * - the default menu items that are always included,
+ * - any menu items that have been provided through the addMenuItem api. These
+ * are typically added by features within the grid
+ * - any menu items included in grid.options.gridMenuCustomItems. These can be
+ * changed dynamically, as they're always recalculated whenever we show the
+ * menu
+ * @param {$scope} $scope the scope of this gridMenu, from which we can find all
+ * the information that we need
+ * @returns {array} an array of menu items that can be shown
+ */
+ getMenuItems: function( $scope ) {
+ var menuItems = [
+ // this is where we add any menu items we want to always include
+ ];
+
+ if ( $scope.grid.options.gridMenuCustomItems ){
+ if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){
+ gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');
+ } else {
+ menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );
+ }
+ }
+
+ var clearFilters = [{
+ title: i18nService.getSafeText('gridMenu.clearAllFilters'),
+ action: function ($event) {
+ $scope.grid.clearAllFilters(undefined, true, undefined);
+ },
+ shown: function() {
+ return $scope.grid.options.enableFiltering;
+ },
+ order: 100
+ }];
+ menuItems = menuItems.concat( clearFilters );
+
+ menuItems = menuItems.concat( $scope.registeredMenuItems );
+
+ if ( $scope.grid.options.gridMenuShowHideColumns !== false ){
+ menuItems = menuItems.concat( service.showHideColumns( $scope ) );
+ }
+
+ menuItems.sort(function(a, b){
+ return a.order - b.order;
+ });
+
+ return menuItems;
+ },
+
+
+ /**
+ * @ngdoc array
+ * @name gridMenuTitleFilter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) A function that takes a title string
+ * (usually the col.displayName), and converts it into a display value. The function
+ * must return either a string or a promise.
+ *
+ * Used for internationalization of the grid menu column names - for angular-translate
+ * you can pass $translate as the function, for i18nService you can pass getSafeText as the
+ * function
+ * @example
+ * <pre>
+ * gridOptions = {
+ * gridMenuTitleFilter: $translate
+ * }
+ * </pre>
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name showHideColumns
+ * @description Adds two menu items for each of the columns in columnDefs. One
+ * menu item for hide, one menu item for show. Each is visible when appropriate
+ * (show when column is not visible, hide when column is visible). Each toggles
+ * the visible property on the columnDef using toggleColumnVisibility
+ * @param {$scope} $scope of a gridMenu, which contains a reference to the grid
+ */
+ showHideColumns: function( $scope ){
+ var showHideColumns = [];
+ if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {
+ return showHideColumns;
+ }
+
+ // add header for columns
+ showHideColumns.push({
+ title: i18nService.getSafeText('gridMenu.columns'),
+ order: 300
+ });
+
+ $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };
+
+ $scope.grid.options.columnDefs.forEach( function( colDef, index ){
+ if ( colDef.enableHiding !== false ){
+ // add hide menu item - shows an OK icon as we only show when column is already visible
+ var menuItem = {
+ icon: 'ui-grid-icon-ok',
+ action: function($event) {
+ $event.stopPropagation();
+ service.toggleColumnVisibility( this.context.gridCol );
+ },
+ shown: function() {
+ return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;
+ },
+ context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
+ leaveOpen: true,
+ order: 301 + index * 2
+ };
+ service.setMenuItemTitle( menuItem, colDef, $scope.grid );
+ showHideColumns.push( menuItem );
+
+ // add show menu item - shows no icon as we only show when column is invisible
+ menuItem = {
+ icon: 'ui-grid-icon-cancel',
+ action: function($event) {
+ $event.stopPropagation();
+ service.toggleColumnVisibility( this.context.gridCol );
+ },
+ shown: function() {
+ return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);
+ },
+ context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
+ leaveOpen: true,
+ order: 301 + index * 2 + 1
+ };
+ service.setMenuItemTitle( menuItem, colDef, $scope.grid );
+ showHideColumns.push( menuItem );
+ }
+ });
+ return showHideColumns;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name setMenuItemTitle
+ * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu
+ * item if it returns a string, otherwise waiting for the promise to resolve or reject then
+ * putting the result into the title
+ * @param {object} menuItem the menuItem we want to put the title on
+ * @param {object} colDef the colDef from which we can get displayName, name or field
+ * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter
+ *
+ */
+ setMenuItemTitle: function( menuItem, colDef, grid ){
+ var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );
+
+ if ( typeof(title) === 'string' ){
+ menuItem.title = title;
+ } else if ( title.then ){
+ // must be a promise
+ menuItem.title = "";
+ title.then( function( successValue ) {
+ menuItem.title = successValue;
+ }, function( errorValue ) {
+ menuItem.title = errorValue;
+ });
+ } else {
+ gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');
+ menuItem.title = 'badconfig';
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.gridMenuService
+ * @name toggleColumnVisibility
+ * @description Toggles the visibility of an individual column. Expects to be
+ * provided a context that has on it a gridColumn, which is the column that
+ * we'll operate upon. We change the visibility, and refresh the grid as appropriate
+ * @param {GridCol} gridCol the column that we want to toggle
+ *
+ */
+ toggleColumnVisibility: function( gridCol ) {
+ gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );
+
+ gridCol.grid.refresh();
+ gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );
+ }
+ };
+
+ return service;
+}])
+
+
+
+.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',
+function (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {
+
+ return {
+ priority: 0,
+ scope: true,
+ require: ['^uiGrid'],
+ templateUrl: 'ui-grid/ui-grid-menu-button',
+ replace: true,
+
+ link: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+
+ // For the aria label
+ $scope.i18n = {
+ aria: i18nService.getSafeText('gridMenu.aria')
+ };
+
+ uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
+
+ $scope.shown = false;
+
+ $scope.toggleMenu = function () {
+ if ( $scope.shown ){
+ $scope.$broadcast('hide-menu');
+ $scope.shown = false;
+ } else {
+ $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
+ $scope.$broadcast('show-menu');
+ $scope.shown = true;
+ }
+ };
+
+ $scope.$on('menu-hidden', function() {
+ $scope.shown = false;
+ gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
+ });
+ }
+ };
+
+}]);
+
+})();
+
+(function(){
+
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridMenu
+ * @element style
+ * @restrict A
+ *
+ * @description
+ * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div ui-grid-menu shown="true" ></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ </doc:scenario>
+ </doc:example>
+ */
+angular.module('ui.grid')
+
+.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',
+function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {
+ var uiGridMenu = {
+ priority: 0,
+ scope: {
+ // shown: '&',
+ menuItems: '=',
+ autoHide: '=?'
+ },
+ require: '?^uiGrid',
+ templateUrl: 'ui-grid/uiGridMenu',
+ replace: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var self = this;
+ var menuMid;
+ var $animate;
+
+ $scope.i18n = {
+ close: i18nService.getSafeText('columnMenu.close')
+ };
+
+ // *** Show/Hide functions ******
+ self.showMenu = $scope.showMenu = function(event, args) {
+ if ( !$scope.shown ){
+
+ /*
+ * In order to animate cleanly we remove the ng-if, wait a digest cycle, then
+ * animate the removal of the ng-hide. We can't successfully (so far as I can tell)
+ * animate removal of the ng-if, as the menu items aren't there yet. And we don't want
+ * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated
+ * on scroll events.
+ *
+ * Note when testing animation that animations don't run on the tutorials. When debugging it looks
+ * like they do, but angular has a default $animate provider that is just a stub, and that's what's
+ * being called. ALso don't be fooled by the fact that your browser has actually loaded the
+ * angular-translate.js, it's not using it. You need to test animations in an external application.
+ */
+ $scope.shown = true;
+
+ $timeout( function() {
+ $scope.shownMid = true;
+ $scope.$emit('menu-shown');
+ });
+ } else if ( !$scope.shownMid ) {
+ // we're probably doing a hide then show, so we don't need to wait for ng-if
+ $scope.shownMid = true;
+ $scope.$emit('menu-shown');
+ }
+
+ var docEventType = 'click';
+ if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {
+ docEventType = args.originalEvent.type;
+ }
+
+ // Turn off an existing document click handler
+ angular.element(document).off('click touchstart', applyHideMenu);
+
+ // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
+ $timeout(function() {
+ angular.element(document).on(docEventType, applyHideMenu);
+ });
+ //automatically set the focus to the first button element in the now open menu.
+ gridUtil.focus.bySelector($elm, 'button[type=button]', true);
+ };
+
+
+ self.hideMenu = $scope.hideMenu = function(event, args) {
+ if ( $scope.shown ){
+ /*
+ * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
+ * set the ng-if (shown = false) after the animation runs. In theory we can cascade off the
+ * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.
+ *
+ * The user may have clicked on the menu again whilst
+ * we're waiting, so we check that the mid isn't shown before applying the ng-if.
+ */
+ $scope.shownMid = false;
+ $timeout( function() {
+ if ( !$scope.shownMid ){
+ $scope.shown = false;
+ $scope.$emit('menu-hidden');
+ }
+ }, 200);
+ }
+
+ angular.element(document).off('click touchstart', applyHideMenu);
+ };
+
+ $scope.$on('hide-menu', function (event, args) {
+ $scope.hideMenu(event, args);
+ });
+
+ $scope.$on('show-menu', function (event, args) {
+ $scope.showMenu(event, args);
+ });
+
+
+ // *** Auto hide when click elsewhere ******
+ var applyHideMenu = function(){
+ if ($scope.shown) {
+ $scope.$apply(function () {
+ $scope.hideMenu();
+ });
+ }
+ };
+
+ if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
+ $scope.autoHide = true;
+ }
+
+ if ($scope.autoHide) {
+ angular.element($window).on('resize', applyHideMenu);
+ }
+
+ $scope.$on('$destroy', function () {
+ angular.element(document).off('click touchstart', applyHideMenu);
+ });
+
+
+ $scope.$on('$destroy', function() {
+ angular.element($window).off('resize', applyHideMenu);
+ });
+
+ if (uiGridCtrl) {
+ $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));
+ }
+
+ $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));
+ },
+
+
+ controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
+ var self = this;
+ }]
+ };
+
+ return uiGridMenu;
+}])
+
+.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {
+ var uiGridMenuItem = {
+ priority: 0,
+ scope: {
+ name: '=',
+ active: '=',
+ action: '=',
+ icon: '=',
+ shown: '=',
+ context: '=',
+ templateUrl: '=',
+ leaveOpen: '=',
+ screenReaderOnly: '='
+ },
+ require: ['?^uiGrid', '^uiGridMenu'],
+ templateUrl: 'ui-grid/uiGridMenuItem',
+ replace: false,
+ compile: function($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ uiGridMenuCtrl = controllers[1];
+
+ if ($scope.templateUrl) {
+ gridUtil.getTemplate($scope.templateUrl)
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+ $elm.replaceWith(newElm);
+ });
+ }
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ uiGridMenuCtrl = controllers[1];
+
+ // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
+ // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
+ // throw new TypeError("$scope.shown is defined but not a function");
+ // }
+ if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {
+ $scope.shown = function() { return true; };
+ }
+
+ $scope.itemShown = function () {
+ var context = {};
+ if ($scope.context) {
+ context.context = $scope.context;
+ }
+
+ if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
+ context.grid = uiGridCtrl.grid;
+ }
+
+ return $scope.shown.call(context);
+ };
+
+ $scope.itemAction = function($event,title) {
+ gridUtil.logDebug('itemAction');
+ $event.stopPropagation();
+
+ if (typeof($scope.action) === 'function') {
+ var context = {};
+
+ if ($scope.context) {
+ context.context = $scope.context;
+ }
+
+ // Add the grid to the function call context if the uiGrid controller is present
+ if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
+ context.grid = uiGridCtrl.grid;
+ }
+
+ $scope.action.call(context, $event, title);
+
+ if ( !$scope.leaveOpen ){
+ $scope.$emit('hide-menu');
+ } else {
+ /*
+ * XXX: Fix after column refactor
+ * Ideally the focus would remain on the item.
+ * However, since there are two menu items that have their 'show' property toggled instead. This is a quick fix.
+ */
+ gridUtil.focus.bySelector(angular.element(gridUtil.closestElm($elm, ".ui-grid-menu-items")), 'button[type=button]', true);
+ }
+ }
+ };
+
+ $scope.i18n = i18nService.get();
+ }
+ };
+ }
+ };
+
+ return uiGridMenuItem;
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.directive:uiGridOneBind
+ * @summary A group of directives that provide a one time bind to a dom element.
+ * @description A group of directives that provide a one time bind to a dom element.
+ * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.
+ * This is done to reduce the number of watchers on the dom.
+ * <br/>
+ * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>
+ * <pre>
+ <div ng-init="imageName = 'myImageDir.jpg'">
+ <img ui-grid-one-bind-src="imageName"></img>
+ </div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="imageName = 'myImageDir.jpg'">
+ <img ui-grid-one-bind-src="imageName" src="myImageDir.jpg"></img>
+ </div>
+ </pre>
+ </br>
+ <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-text="text"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-text="text">Add this text</div>
+ </pre>
+ </br>
+ * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}
+ * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.
+ *
+ */
+ //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js
+ var oneBinders = angular.module('ui.grid');
+ angular.forEach([
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindSrc
+ * @memberof ui.grid.directive:uiGridOneBind
+ * @element img
+ * @restrict A
+ * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the src dom tag.
+ *
+ */
+ {tag: 'Src', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindText
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the text dom tag.
+ */
+ {tag: 'Text', method: 'text'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindHref
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Href', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindClass
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.
+ * this is to prevent the watcher from being removed before the scope is initialized.
+ * @param {Array} uiGridOneBindClass An array of classes to bind to this element.
+ * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Class', method: 'addClass'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindHtml
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Html', method: 'html'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAlt
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Alt', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindStyle
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Style', method: 'css'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindValue
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Value', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindId
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Id', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindIdGrid
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the id dom tag.
+ * <h1>Important Note!</h1>
+ * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring
+ * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.
+ * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.
+ * This is done in order to ensure uniqueness of id tags across the grid.
+ * This is to prevent two grids in the same document having duplicate id tags.
+ */
+ {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindTitle
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ */
+ {tag: 'Title', method: 'attr'},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabel
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text" aria-label="Add this text"></div>
+ </pre>
+ */
+ {tag: 'Label', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabelledby
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId" aria-labelledby="gridID32"></div>
+ </pre>
+ */
+ {tag: 'Labelledby', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid
+ * @element div
+ * @restrict A
+ * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
+ * grid id to each one.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId"></div>
+ </pre>
+ * Will become ([grid.id] will be replaced by the actual grid id):
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId" aria-labelledby-Grid="[grid.id]-gridID32"></div>
+ </pre>
+ */
+ {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaDescribedby
+ * @element ANY
+ * @restrict A
+ * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId"></div>
+ </pre>
+ * Will become:
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId" aria-describedby="gridID32"></div>
+ </pre>
+ */
+ {tag: 'Describedby', method: 'attr', aria:true},
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid
+ * @element ANY
+ * @restrict A
+ * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
+ * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
+ * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
+ * grid id to each one.
+ *<br/>
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId"></div>
+ </pre>
+ * Will become ([grid.id] will be replaced by the actual grid id):
+ * <pre>
+ <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId" aria-describedby="[grid.id]-gridID32"></div>
+ </pre>
+ */
+ {tag: 'Describedby', directiveName:'DescribedbyGrid', appendGridId:true, method: 'attr', aria:true}],
+ function(v){
+
+ var baseDirectiveName = 'uiGridOneBind';
+ //If it is an aria tag then append the aria label seperately
+ //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.
+ //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up.
+ var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);
+ oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){
+ return {
+ restrict: 'A',
+ require: ['?uiGrid','?^uiGrid'],
+ link: function(scope, iElement, iAttrs, controllers){
+ /* Appends the grid id to the beginnig of the value. */
+ var appendGridId = function(val){
+ var grid; //Get an instance of the grid if its available
+ //If its available in the scope then we don't need to try to find it elsewhere
+ if (scope.grid) {
+ grid = scope.grid;
+ }
+ //Another possible location to try to find the grid
+ else if (scope.col && scope.col.grid){
+ grid = scope.col.grid;
+ }
+ //Last ditch effort: Search through the provided controllers.
+ else if (!controllers.some( //Go through the controllers till one has the element we need
+ function(controller){
+ if (controller && controller.grid) {
+ grid = controller.grid;
+ return true; //We've found the grid
+ }
+ })){
+ //We tried our best to find it for you
+ gridUtil.logError("["+directiveName+"] A valid grid could not be found to bind id. Are you using this directive " +
+ "within the correct scope? Trying to generate id: [gridID]-" + val);
+ throw new Error("No valid grid could be found");
+ }
+
+ if (grid){
+ var idRegex = new RegExp(grid.id.toString());
+ //If the grid id hasn't been appended already in the template declaration
+ if (!idRegex.test(val)){
+ val = grid.id.toString() + '-' + val;
+ }
+ }
+ return val;
+ };
+
+ // The watch returns a function to remove itself.
+ var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){
+ if (newV){
+ //If we are trying to add an id element then we also apply the grid id if it isn't already there
+ if (v.appendGridId) {
+ var newIdString = null;
+ //Append the id to all of the new ids.
+ angular.forEach( newV.split(' '), function(s){
+ newIdString = (newIdString ? (newIdString + ' ') : '') + appendGridId(s);
+ });
+ newV = newIdString;
+ }
+
+ // Append this newValue to the dom element.
+ switch (v.method) {
+ case 'attr': //The attr method takes two paraams the tag and the value
+ if (v.aria) {
+ //If it is an aria element then append the aria prefix
+ iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);
+ } else {
+ iElement[v.method](v.tag.toLowerCase(),newV);
+ }
+ break;
+ case 'addClass':
+ //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js
+ if (angular.isObject(newV) && !angular.isArray(newV)) {
+ var results = [];
+ var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined
+ angular.forEach(newV, function (value, index) {
+ if (value !== null && typeof(value) !== "undefined"){
+ nonNullFound = true; //A non null value for a key was found so the object must have been initialized
+ if (value) {results.push(index);}
+ }
+ });
+ //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized
+ if (!nonNullFound){
+ return; // If not initialized then the watcher should not be removed yet.
+ }
+ newV = results;
+ }
+
+ if (newV) {
+ iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);
+ } else {
+ return;
+ }
+ break;
+ default:
+ iElement[v.method](newV);
+ break;
+ }
+
+ //Removes the watcher on itself after the bind
+ rmWatcher();
+ }
+ // True ensures that equality is determined using angular.equals instead of ===
+ }, true); //End rm watchers
+ } //End compile function
+ }; //End directive return
+ } // End directive function
+ ]); //End directive
+ }); // End angular foreach
+})();
+
+(function () {
+ 'use strict';
+
+ var module = angular.module('ui.grid');
+
+ module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',
+ function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {
+ return {
+ replace: true,
+ transclude: true,
+ templateUrl: 'ui-grid/uiGridRenderContainer',
+ require: ['^uiGrid', 'uiGridRenderContainer'],
+ scope: {
+ containerId: '=',
+ rowContainerName: '=',
+ colContainerName: '=',
+ bindScrollHorizontal: '=',
+ bindScrollVertical: '=',
+ enableVerticalScrollbar: '=',
+ enableHorizontalScrollbar: '='
+ },
+ controller: 'uiGridRenderContainer as RenderContainer',
+ compile: function () {
+ return {
+ pre: function prelink($scope, $elm, $attrs, controllers) {
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+ var grid = $scope.grid = uiGridCtrl.grid;
+
+ // Verify that the render container for this element exists
+ if (!$scope.rowContainerName) {
+ throw "No row render container name specified";
+ }
+ if (!$scope.colContainerName) {
+ throw "No column render container name specified";
+ }
+
+ if (!grid.renderContainers[$scope.rowContainerName]) {
+ throw "Row render container '" + $scope.rowContainerName + "' is not registered.";
+ }
+ if (!grid.renderContainers[$scope.colContainerName]) {
+ throw "Column render container '" + $scope.colContainerName + "' is not registered.";
+ }
+
+ var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];
+ var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];
+
+ containerCtrl.containerId = $scope.containerId;
+ containerCtrl.rowContainer = rowContainer;
+ containerCtrl.colContainer = colContainer;
+ },
+ post: function postlink($scope, $elm, $attrs, controllers) {
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ var grid = uiGridCtrl.grid;
+ var rowContainer = containerCtrl.rowContainer;
+ var colContainer = containerCtrl.colContainer;
+ var scrollTop = null;
+ var scrollLeft = null;
+
+
+ var renderContainer = grid.renderContainers[$scope.containerId];
+
+ // Put the container name on this element as a class
+ $elm.addClass('ui-grid-render-container-' + $scope.containerId);
+
+ // Scroll the render container viewport when the mousewheel is used
+ gridUtil.on.mousewheel($elm, function (event) {
+ var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);
+ if (event.deltaY !== 0) {
+ var scrollYAmount = event.deltaY * -1 * event.deltaFactor;
+
+ scrollTop = containerCtrl.viewport[0].scrollTop;
+
+ // Get the scroll percentage
+ scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();
+ var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;
+
+ // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length
+ // Viewports that have "overflow: hidden" don't let the mousewheel scroll all the way to the bottom without this check
+ if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {
+ containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;
+ }
+
+ // Keep scrollPercentage within the range 0-1.
+ if (scrollYPercentage < 0) { scrollYPercentage = 0; }
+ else if (scrollYPercentage > 1) { scrollYPercentage = 1; }
+
+ scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };
+ }
+ if (event.deltaX !== 0) {
+ var scrollXAmount = event.deltaX * event.deltaFactor;
+
+ // Get the scroll percentage
+ scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);
+ scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
+ var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;
+
+ // Keep scrollPercentage within the range 0-1.
+ if (scrollXPercentage < 0) { scrollXPercentage = 0; }
+ else if (scrollXPercentage > 1) { scrollXPercentage = 1; }
+
+ scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };
+ }
+
+ // Let the parent container scroll if the grid is already at the top/bottom
+ if ((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||
+ (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft)))) {
+ //parent controller scrolls
+ }
+ else {
+ event.preventDefault();
+ event.stopPropagation();
+ scrollEvent.fireThrottledScrollingEvent('', scrollEvent);
+ }
+
+ });
+
+ $elm.bind('$destroy', function() {
+ $elm.unbind('keydown');
+
+ ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {
+ $elm.unbind(eventName);
+ });
+ });
+
+ // TODO(c0bra): Handle resizing the inner canvas based on the number of elements
+ function update() {
+ var ret = '';
+
+ var canvasWidth = colContainer.canvasWidth;
+ var viewportWidth = colContainer.getViewportWidth();
+
+ var canvasHeight = rowContainer.getCanvasHeight();
+
+ //add additional height for scrollbar on left and right container
+ //if ($scope.containerId !== 'body') {
+ // canvasHeight -= grid.scrollbarHeight;
+ //}
+
+ var viewportHeight = rowContainer.getViewportHeight();
+ //shorten the height to make room for a scrollbar placeholder
+ if (colContainer.needsHScrollbarPlaceholder()) {
+ viewportHeight -= grid.scrollbarHeight;
+ }
+
+ var headerViewportWidth,
+ footerViewportWidth;
+ headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();
+
+ // Set canvas dimensions
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
+
+ if (renderContainer.explicitHeaderCanvasHeight) {
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
+ }
+ else {
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: inherit; }';
+ }
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';
+
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
+ ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';
+
+ return ret;
+ }
+
+ uiGridCtrl.grid.registerStyleComputation({
+ priority: 6,
+ func: update
+ });
+ }
+ };
+ }
+ };
+
+ }]);
+
+ module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {
+
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {
+ return {
+ replace: true,
+ // priority: 2001,
+ // templateUrl: 'ui-grid/ui-grid-row',
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: {
+ row: '=uiGridRow',
+ //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it
+ rowRenderIndex: '='
+ },
+ compile: function() {
+ return {
+ pre: function($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ var grid = uiGridCtrl.grid;
+
+ $scope.grid = uiGridCtrl.grid;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ // Function for attaching the template to this scope
+ var clonedElement, cloneScope;
+ function compileTemplate() {
+ $scope.row.getRowTemplateFn.then(function (compiledElementFn) {
+ // var compiledElementFn = $scope.row.compiledElementFn;
+
+ // Create a new scope for the contents of this row, so we can destroy it later if need be
+ var newScope = $scope.$new();
+
+ compiledElementFn(newScope, function (newElm, scope) {
+ // If we already have a cloned element, we need to remove it and destroy its scope
+ if (clonedElement) {
+ clonedElement.remove();
+ cloneScope.$destroy();
+ }
+
+ // Empty the row and append the new element
+ $elm.empty().append(newElm);
+
+ // Save the new cloned element and scope
+ clonedElement = newElm;
+ cloneScope = newScope;
+ });
+ });
+ }
+
+ // Initially attach the compiled template to this scope
+ compileTemplate();
+
+ // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
+ $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {
+ if (newFunc !== oldFunc) {
+ compileTemplate();
+ }
+ });
+ },
+ post: function($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+(function(){
+// 'use strict';
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGridStyle
+ * @element style
+ * @restrict A
+ *
+ * @description
+ * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.myStyle = '.blah { border: 1px solid }';
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <style ui-grid-style>{{ myStyle }}</style>
+ <span class="blah">I am in a box.</span>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ it('should apply the right class to the element', function () {
+ element(by.css('.blah')).getCssValue('border-top-width')
+ .then(function(c) {
+ expect(c).toContain('1px');
+ });
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+
+
+ angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {
+ return {
+ // restrict: 'A',
+ // priority: 1000,
+ // require: '?^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ // gridUtil.logDebug('ui-grid-style link');
+ // if (uiGridCtrl === undefined) {
+ // gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');
+ // }
+
+ var interpolateFn = $interpolate($elm.text(), true);
+
+ if (interpolateFn) {
+ $scope.$watch(interpolateFn, function(value) {
+ $elm.text(value);
+ });
+ }
+
+ // uiGridCtrl.recalcRowStyles = function() {
+ // var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);
+ // var rowHeight = scope.options.rowHeight;
+
+ // var ret = '';
+ // var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);
+ // for (var i = 1; i <= rowStyleCount; i++) {
+ // ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';
+ // offset = offset + rowHeight;
+ // }
+
+ // scope.rowStyles = ret;
+ // };
+
+ // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);
+
+ }
+ };
+ }]);
+
+})();
+
+(function(){
+ 'use strict';
+
+ angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants', '$log',
+ function(gridUtil, ScrollEvent, uiGridConstants, $log) {
+ return {
+ replace: true,
+ scope: {},
+ controllerAs: 'Viewport',
+ templateUrl: 'ui-grid/uiGridViewport',
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ link: function($scope, $elm, $attrs, controllers) {
+ // gridUtil.logDebug('viewport post-link');
+
+ var uiGridCtrl = controllers[0];
+ var containerCtrl = controllers[1];
+
+ $scope.containerCtrl = containerCtrl;
+
+ var rowContainer = containerCtrl.rowContainer;
+ var colContainer = containerCtrl.colContainer;
+
+ var grid = uiGridCtrl.grid;
+
+ $scope.grid = uiGridCtrl.grid;
+
+ // Put the containers in scope so we can get rows and columns from them
+ $scope.rowContainer = containerCtrl.rowContainer;
+ $scope.colContainer = containerCtrl.colContainer;
+
+ // Register this viewport with its container
+ containerCtrl.viewport = $elm;
+
+
+ $elm.on('scroll', scrollHandler);
+
+ var ignoreScroll = false;
+
+ function scrollHandler(evt) {
+ //Leaving in this commented code in case it can someday be used
+ //It does improve performance, but because the horizontal scroll is normalized,
+ // using this code will lead to the column header getting slightly out of line with columns
+ //
+ //if (ignoreScroll && (grid.isScrollingHorizontally || grid.isScrollingHorizontally)) {
+ // //don't ask for scrollTop if we just set it
+ // ignoreScroll = false;
+ // return;
+ //}
+ //ignoreScroll = true;
+
+ var newScrollTop = $elm[0].scrollTop;
+ var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);
+
+ var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
+ var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);
+
+ var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
+ scrollEvent.newScrollLeft = newScrollLeft;
+ scrollEvent.newScrollTop = newScrollTop;
+ if ( horizScrollPercentage > -1 ){
+ scrollEvent.x = { percentage: horizScrollPercentage };
+ }
+
+ if ( vertScrollPercentage > -1 ){
+ scrollEvent.y = { percentage: vertScrollPercentage };
+ }
+
+ grid.scrollContainers($scope.$parent.containerId, scrollEvent);
+ }
+
+ if ($scope.$parent.bindScrollVertical) {
+ grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);
+ }
+
+ if ($scope.$parent.bindScrollHorizontal) {
+ grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);
+ grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);
+ grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);
+ }
+
+ function syncVerticalScroll(scrollEvent){
+ containerCtrl.prevScrollArgs = scrollEvent;
+ var newScrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);
+ $elm[0].scrollTop = newScrollTop;
+
+ }
+
+ function syncHorizontalScroll(scrollEvent){
+ containerCtrl.prevScrollArgs = scrollEvent;
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ $elm[0].scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+
+ function syncHorizontalHeader(scrollEvent){
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ if (containerCtrl.headerViewport) {
+ containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+ }
+
+ function syncHorizontalFooter(scrollEvent){
+ var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
+ if (containerCtrl.footerViewport) {
+ containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
+ }
+ }
+
+
+ },
+ controller: ['$scope', function ($scope) {
+ this.rowStyle = function (index) {
+ var rowContainer = $scope.rowContainer;
+ var colContainer = $scope.colContainer;
+
+ var styles = {};
+
+ if (index === 0 && rowContainer.currentTopRow !== 0) {
+ // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered
+ var hiddenRowWidth = (rowContainer.currentTopRow) * rowContainer.grid.options.rowHeight;
+
+ // return { 'margin-top': hiddenRowWidth + 'px' };
+ styles['margin-top'] = hiddenRowWidth + 'px';
+ }
+
+ if (colContainer.currentFirstColumn !== 0) {
+ if (colContainer.grid.isRTL()) {
+ styles['margin-right'] = colContainer.columnOffset + 'px';
+ }
+ else {
+ styles['margin-left'] = colContainer.columnOffset + 'px';
+ }
+ }
+
+ return styles;
+ };
+ }]
+ };
+ }
+ ]);
+
+})();
+
+(function() {
+
+angular.module('ui.grid')
+.directive('uiGridVisible', function uiGridVisibleAction() {
+ return function ($scope, $elm, $attr) {
+ $scope.$watch($attr.uiGridVisible, function (visible) {
+ // $elm.css('visibility', visible ? 'visible' : 'hidden');
+ $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');
+ });
+ };
+});
+
+})();
+(function () {
+ 'use strict';
+
+ angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',
+ '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile',
+ function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,
+ $templateCache, gridClassFactory, $timeout, $parse, $compile) {
+ // gridUtil.logDebug('ui-grid controller');
+
+ var self = this;
+
+ self.grid = gridClassFactory.createGrid($scope.uiGrid);
+
+ //assign $scope.$parent if appScope not already assigned
+ self.grid.appScope = self.grid.appScope || $scope.$parent;
+
+ $elm.addClass('grid' + self.grid.id);
+ self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';
+
+
+ // angular.extend(self.grid.options, );
+
+ //all properties of grid are available on scope
+ $scope.grid = self.grid;
+
+ if ($attrs.uiGridColumns) {
+ $attrs.$observe('uiGridColumns', function(value) {
+ self.grid.options.columnDefs = value;
+ self.grid.buildColumns()
+ .then(function(){
+ self.grid.preCompileCellTemplates();
+
+ self.grid.refreshCanvas(true);
+ });
+ });
+ }
+
+
+ // if fastWatch is set we watch only the length and the reference, not every individual object
+ var deregFunctions = [];
+ if (self.grid.options.fastWatch) {
+ self.uiGrid = $scope.uiGrid;
+ if (angular.isString($scope.uiGrid.data)) {
+ deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() {
+ if ( self.grid.appScope[$scope.uiGrid.data] ){
+ return self.grid.appScope[$scope.uiGrid.data].length;
+ } else {
+ return undefined;
+ }
+ }, dataWatchFunction) );
+ } else {
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data.length; }, dataWatchFunction) );
+ }
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
+ deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs.length; }, columnDefsWatchFunction) );
+ } else {
+ if (angular.isString($scope.uiGrid.data)) {
+ deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );
+ } else {
+ deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
+ }
+ deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
+ }
+
+
+ function columnDefsWatchFunction(n, o) {
+ if (n && n !== o) {
+ self.grid.options.columnDefs = n;
+ self.grid.buildColumns({ orderByColumnDefs: true })
+ .then(function(){
+
+ self.grid.preCompileCellTemplates();
+
+ self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);
+ });
+ }
+ }
+
+ function dataWatchFunction(newData) {
+ // gridUtil.logDebug('dataWatch fired');
+ var promises = [];
+
+ if ( self.grid.options.fastWatch ){
+ if (angular.isString($scope.uiGrid.data)) {
+ newData = self.grid.appScope[$scope.uiGrid.data];
+ } else {
+ newData = $scope.uiGrid.data;
+ }
+ }
+
+ if (newData) {
+ // columns length is greater than the number of row header columns, which don't count because they're created automatically
+ var hasColumns = self.grid.columns.length > (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0);
+
+ if (
+ // If we have no columns
+ !hasColumns &&
+ // ... and we don't have a ui-grid-columns attribute, which would define columns for us
+ !$attrs.uiGridColumns &&
+ // ... and we have no pre-defined columns
+ self.grid.options.columnDefs.length === 0 &&
+ // ... but we DO have data
+ newData.length > 0
+ ) {
+ // ... then build the column definitions from the data that we have
+ self.grid.buildColumnDefsFromData(newData);
+ }
+
+ // If we haven't built columns before and either have some columns defined or some data defined
+ if (!hasColumns && (self.grid.options.columnDefs.length > 0 || newData.length > 0)) {
+ // Build the column set, then pre-compile the column cell templates
+ promises.push(self.grid.buildColumns()
+ .then(function() {
+ self.grid.preCompileCellTemplates();
+ }));
+ }
+
+ $q.all(promises).then(function() {
+ self.grid.modifyRows(newData)
+ .then(function () {
+ // if (self.viewport) {
+ self.grid.redrawInPlace(true);
+ // }
+
+ $scope.$evalAsync(function() {
+ self.grid.refreshCanvas(true);
+ self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);
+ });
+ });
+ });
+ }
+ }
+
+ var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {
+ self.grid.refreshCanvas(true);
+ });
+
+ $scope.$on('$destroy', function() {
+ deregFunctions.forEach( function( deregFn ){ deregFn(); });
+ styleWatchDereg();
+ });
+
+ self.fireEvent = function(eventName, args) {
+ // Add the grid to the event arguments if it's not there
+ if (typeof(args) === 'undefined' || args === undefined) {
+ args = {};
+ }
+
+ if (typeof(args.grid) === 'undefined' || args.grid === undefined) {
+ args.grid = self.grid;
+ }
+
+ $scope.$broadcast(eventName, args);
+ };
+
+ self.innerCompile = function innerCompile(elm) {
+ $compile(elm)($scope);
+ };
+
+ }]);
+
+/**
+ * @ngdoc directive
+ * @name ui.grid.directive:uiGrid
+ * @element div
+ * @restrict EA
+ * @param {Object} uiGrid Options for the grid to use
+ *
+ * @description Create a very basic grid.
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data }"></div>
+ </div>
+ </file>
+ </example>
+ */
+angular.module('ui.grid').directive('uiGrid', uiGridDirective);
+
+uiGridDirective.$inject = ['$compile', '$templateCache', '$timeout', '$window', 'gridUtil', 'uiGridConstants'];
+function uiGridDirective($compile, $templateCache, $timeout, $window, gridUtil, uiGridConstants) {
+ return {
+ templateUrl: 'ui-grid/ui-grid',
+ scope: {
+ uiGrid: '='
+ },
+ replace: true,
+ transclude: true,
+ controller: 'uiGridController',
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var grid = uiGridCtrl.grid;
+ // Initialize scrollbars (TODO: move to controller??)
+ uiGridCtrl.scrollbars = [];
+ grid.element = $elm;
+
+
+ // See if the grid has a rendered width, if not, wait a bit and try again
+ var sizeCheckInterval = 100; // ms
+ var maxSizeChecks = 20; // 2 seconds total
+ var sizeChecks = 0;
+
+ // Setup (event listeners) the grid
+ setup();
+
+ // And initialize it
+ init();
+
+ // Mark rendering complete so API events can happen
+ grid.renderingComplete();
+
+ // If the grid doesn't have size currently, wait for a bit to see if it gets size
+ checkSize();
+
+ /*-- Methods --*/
+
+ function checkSize() {
+ // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds
+ if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {
+ setTimeout(checkSize, sizeCheckInterval);
+ sizeChecks++;
+ }
+ else {
+ $timeout(init);
+ }
+ }
+
+ // Setup event listeners and watchers
+ function setup() {
+ // Bind to window resize events
+ angular.element($window).on('resize', gridResize);
+
+ // Unbind from window resize events when the grid is destroyed
+ $elm.on('$destroy', function () {
+ angular.element($window).off('resize', gridResize);
+ });
+
+ // If we add a left container after render, we need to watch and react
+ $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {
+ if (newValue === oldValue) {
+ return;
+ }
+ grid.refreshCanvas(true);
+ });
+
+ // If we add a right container after render, we need to watch and react
+ $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {
+ if (newValue === oldValue) {
+ return;
+ }
+ grid.refreshCanvas(true);
+ });
+ }
+
+ // Initialize the directive
+ function init() {
+ grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
+
+ // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from
+ grid.canvasWidth = uiGridCtrl.grid.gridWidth;
+
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+
+ // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows
+ if (grid.gridHeight < grid.options.rowHeight && grid.options.enableMinHeightCheck) {
+ autoAdjustHeight();
+ }
+
+ // Run initial canvas refresh
+ grid.refreshCanvas(true);
+ }
+
+ // Set the grid's height ourselves in the case that its height would be unusably small
+ function autoAdjustHeight() {
+ // Figure out the new height
+ var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;
+ var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;
+ var footerHeight = grid.calcFooterHeight();
+
+ var scrollbarHeight = 0;
+ if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ scrollbarHeight = gridUtil.getScrollbarWidth();
+ }
+
+ var maxNumberOfFilters = 0;
+ // Calculates the maximum number of filters in the columns
+ angular.forEach(grid.options.columnDefs, function(col) {
+ if (col.hasOwnProperty('filter')) {
+ if (maxNumberOfFilters < 1) {
+ maxNumberOfFilters = 1;
+ }
+ }
+ else if (col.hasOwnProperty('filters')) {
+ if (maxNumberOfFilters < col.filters.length) {
+ maxNumberOfFilters = col.filters.length;
+ }
+ }
+ });
+
+ if (grid.options.enableFiltering) {
+ var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.every(function(col) {
+ return col.enableFiltering === false;
+ });
+
+ if (!allColumnsHaveFilteringTurnedOff) {
+ maxNumberOfFilters++;
+ }
+ }
+
+ var filterHeight = maxNumberOfFilters * headerHeight;
+
+ var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;
+
+ $elm.css('height', newHeight + 'px');
+
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+ }
+
+ // Resize the grid on window resize events
+ function gridResize($event) {
+ grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
+ grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
+
+ grid.refreshCanvas(true);
+ }
+ }
+ };
+ }
+ };
+}
+
+})();
+
+(function(){
+ 'use strict';
+
+ // TODO: rename this file to ui-grid-pinned-container.js
+
+ angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ template: '<div class="ui-grid-pinned-container"><div ui-grid-render-container container-id="side" row-container-name="\'body\'" col-container-name="side" bind-scroll-vertical="true" class="{{ side }} ui-grid-render-container-{{ side }}"></div></div>',
+ scope: {
+ side: '=uiGridPinnedContainer'
+ },
+ require: '^uiGrid',
+ compile: function compile() {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');
+
+ var grid = uiGridCtrl.grid;
+
+ var myWidth = 0;
+
+ $elm.addClass('ui-grid-pinned-container-' + $scope.side);
+
+ // Monkey-patch the viewport width function
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;
+ }
+
+ function monkeyPatchedGetViewportWidth() {
+ /*jshint validthis: true */
+ var self = this;
+
+ var viewportWidth = 0;
+ self.visibleColumnCache.forEach(function (column) {
+ viewportWidth += column.drawnWidth;
+ });
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewportWidth = viewportWidth + adjustment.width;
+
+ return viewportWidth;
+ }
+
+ function updateContainerWidth() {
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ var cols = grid.renderContainers[$scope.side].visibleColumnCache;
+ var width = 0;
+ for (var i = 0; i < cols.length; i++) {
+ var col = cols[i];
+ width += col.drawnWidth || col.width || 0;
+ }
+
+ return width;
+ }
+ }
+
+ function updateContainerDimensions() {
+ var ret = '';
+
+ // Column containers
+ if ($scope.side === 'left' || $scope.side === 'right') {
+ myWidth = updateContainerWidth();
+
+ // gridUtil.logDebug('myWidth', myWidth);
+
+ // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it
+ $elm.attr('style', null);
+
+ // var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;
+
+ ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';
+ }
+
+ return ret;
+ }
+
+ grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
+ myWidth = updateContainerWidth();
+
+ // Subtract our own width
+ adjustment.width -= myWidth;
+ adjustment.side = $scope.side;
+
+ return adjustment;
+ });
+
+ // Register style computation to adjust for columns in `side`'s render container
+ grid.registerStyleComputation({
+ priority: 15,
+ func: updateContainerDimensions
+ });
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',
+ function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.core.api:PublicApi
+ * @description Public Api for the core grid features
+ *
+ */
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:Grid
+ * @description Grid is the main viewModel. Any properties or methods needed to maintain state are defined in
+ * this prototype. One instance of Grid is created per Grid directive instance.
+ * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.
+ */
+ var Grid = function Grid(options) {
+ var self = this;
+ // Get the id out of the options, then remove it
+ if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {
+ if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {
+ throw new Error("Grid id '" + options.id + '" is invalid. It must follow CSS selector syntax rules.');
+ }
+ }
+ else {
+ throw new Error('No ID provided. An ID must be given when creating a grid.');
+ }
+
+ self.id = options.id;
+ delete options.id;
+
+ // Get default options
+ self.options = GridOptions.initialize( options );
+
+ /**
+ * @ngdoc object
+ * @name appScope
+ * @propertyOf ui.grid.class:Grid
+ * @description reference to the application scope (the parent scope of the ui-grid element). Assigned in ui-grid controller
+ * <br/>
+ * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference
+ */
+ self.appScope = self.options.appScopeProvider;
+
+ self.headerHeight = self.options.headerRowHeight;
+
+
+ /**
+ * @ngdoc object
+ * @name footerHeight
+ * @propertyOf ui.grid.class:Grid
+ * @description returns the total footer height gridFooter + columnFooter
+ */
+ self.footerHeight = self.calcFooterHeight();
+
+
+ /**
+ * @ngdoc object
+ * @name columnFooterHeight
+ * @propertyOf ui.grid.class:Grid
+ * @description returns the total column footer height
+ */
+ self.columnFooterHeight = self.calcColumnFooterHeight();
+
+ self.rtl = false;
+ self.gridHeight = 0;
+ self.gridWidth = 0;
+ self.columnBuilders = [];
+ self.rowBuilders = [];
+ self.rowsProcessors = [];
+ self.columnsProcessors = [];
+ self.styleComputations = [];
+ self.viewportAdjusters = [];
+ self.rowHeaderColumns = [];
+ self.dataChangeCallbacks = {};
+ self.verticalScrollSyncCallBackFns = {};
+ self.horizontalScrollSyncCallBackFns = {};
+
+ // self.visibleRowCache = [];
+
+ // Set of 'render' containers for self grid, which can render sets of rows
+ self.renderContainers = {};
+
+ // Create a
+ self.renderContainers.body = new GridRenderContainer('body', self);
+
+ self.cellValueGetterCache = {};
+
+ // Cached function to use with custom row templates
+ self.getRowTemplateFn = null;
+
+
+ //representation of the rows on the grid.
+ //these are wrapped references to the actual data rows (options.data)
+ self.rows = [];
+
+ //represents the columns on the grid
+ self.columns = [];
+
+ /**
+ * @ngdoc boolean
+ * @name isScrollingVertically
+ * @propertyOf ui.grid.class:Grid
+ * @description set to true when Grid is scrolling vertically. Set to false via debounced method
+ */
+ self.isScrollingVertically = false;
+
+ /**
+ * @ngdoc boolean
+ * @name isScrollingHorizontally
+ * @propertyOf ui.grid.class:Grid
+ * @description set to true when Grid is scrolling horizontally. Set to false via debounced method
+ */
+ self.isScrollingHorizontally = false;
+
+ /**
+ * @ngdoc property
+ * @name scrollDirection
+ * @propertyOf ui.grid.class:Grid
+ * @description set one of the uiGridConstants.scrollDirection values (UP, DOWN, LEFT, RIGHT, NONE), which tells
+ * us which direction we are scrolling. Set to NONE via debounced method
+ */
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+
+ //if true, grid will not respond to any scroll events
+ self.disableScrolling = false;
+
+
+ function vertical (scrollEvent) {
+ self.isScrollingVertically = false;
+ self.api.core.raise.scrollEnd(scrollEvent);
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+ }
+
+ var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);
+ var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);
+
+ function horizontal (scrollEvent) {
+ self.isScrollingHorizontally = false;
+ self.api.core.raise.scrollEnd(scrollEvent);
+ self.scrollDirection = uiGridConstants.scrollDirection.NONE;
+ }
+
+ var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);
+ var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);
+
+
+ /**
+ * @ngdoc function
+ * @name flagScrollingVertically
+ * @methodOf ui.grid.class:Grid
+ * @description sets isScrollingVertically to true and sets it to false in a debounced function
+ */
+ self.flagScrollingVertically = function(scrollEvent) {
+ if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
+ self.api.core.raise.scrollBegin(scrollEvent);
+ }
+ self.isScrollingVertically = true;
+ if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
+ debouncedVerticalMinDelay(scrollEvent);
+ }
+ else {
+ debouncedVertical(scrollEvent);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name flagScrollingHorizontally
+ * @methodOf ui.grid.class:Grid
+ * @description sets isScrollingHorizontally to true and sets it to false in a debounced function
+ */
+ self.flagScrollingHorizontally = function(scrollEvent) {
+ if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
+ self.api.core.raise.scrollBegin(scrollEvent);
+ }
+ self.isScrollingHorizontally = true;
+ if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
+ debouncedHorizontalMinDelay(scrollEvent);
+ }
+ else {
+ debouncedHorizontal(scrollEvent);
+ }
+ };
+
+ self.scrollbarHeight = 0;
+ self.scrollbarWidth = 0;
+ if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ self.scrollbarHeight = gridUtil.getScrollbarWidth();
+ }
+
+ if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
+ self.scrollbarWidth = gridUtil.getScrollbarWidth();
+ }
+
+
+
+ self.api = new GridApi(self);
+
+ /**
+ * @ngdoc function
+ * @name refresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Refresh the rendered grid on screen.
+ * The refresh method re-runs both the columnProcessors and the
+ * rowProcessors, as well as calling refreshCanvas to update all
+ * the grid sizing. In general you should prefer to use queueGridRefresh
+ * instead, which is basically a debounced version of refresh.
+ *
+ * If you only want to resize the grid, not regenerate all the rows
+ * and columns, you should consider directly calling refreshCanvas instead.
+ *
+ */
+ self.api.registerMethod( 'core', 'refresh', this.refresh );
+
+ /**
+ * @ngdoc function
+ * @name queueGridRefresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Request a refresh of the rendered grid on screen, if multiple
+ * calls to queueGridRefresh are made within a digest cycle only one will execute.
+ * The refresh method re-runs both the columnProcessors and the
+ * rowProcessors, as well as calling refreshCanvas to update all
+ * the grid sizing. In general you should prefer to use queueGridRefresh
+ * instead, which is basically a debounced version of refresh.
+ *
+ */
+ self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );
+
+ /**
+ * @ngdoc function
+ * @name refreshRows
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Runs only the rowProcessors, columns remain as they were.
+ * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );
+
+ /**
+ * @ngdoc function
+ * @name queueRefresh
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Requests execution of refreshCanvas, if multiple requests are made
+ * during a digest cycle only one will run. RefreshCanvas updates the grid sizing.
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );
+
+ /**
+ * @ngdoc function
+ * @name handleWindowResize
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Trigger a grid resize, normally this would be picked
+ * up by a watch on window size, but in some circumstances it is necessary
+ * to call this manually
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );
+
+
+ /**
+ * @ngdoc function
+ * @name addRowHeaderColumn
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description adds a row header column to the grid
+ * @param {object} column def
+ *
+ */
+ self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );
+
+ /**
+ * @ngdoc function
+ * @name scrollToIfNecessary
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Scrolls the grid to make a certain row and column combo visible,
+ * in the case that it is not completely visible on the screen already.
+ * @param {GridRow} gridRow row to make visible
+ * @param {GridCol} gridCol column to make visible
+ * @returns {promise} a promise that is resolved when scrolling is complete
+ *
+ */
+ self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );
+
+ /**
+ * @ngdoc function
+ * @name scrollTo
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Scroll the grid such that the specified
+ * row and column is in view
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible
+ * @param {object} colDef to make visible
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);} );
+
+ /**
+ * @ngdoc function
+ * @name registerRowsProcessor
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description
+ * Register a "rows processor" function. When the rows are updated,
+ * the grid calls each registered "rows processor", which has a chance
+ * to alter the set of rows (sorting, etc) as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated rows list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
+ *
+ * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,
+ * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ */
+ self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor );
+
+ /**
+ * @ngdoc function
+ * @name registerColumnsProcessor
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description
+ * Register a "columns processor" function. When the columns are updated,
+ * the grid calls each registered "columns processor", which has a chance
+ * to alter the set of columns as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated columns list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
+ *
+ * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ */
+ self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor );
+
+
+
+ /**
+ * @ngdoc function
+ * @name sortHandleNulls
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description A null handling method that can be used when building custom sort
+ * functions
+ * @example
+ * <pre>
+ * mySortFn = function(a, b) {
+ * var nulls = $scope.gridApi.core.sortHandleNulls(a, b);
+ * if ( nulls !== null ){
+ * return nulls;
+ * } else {
+ * // your code for sorting here
+ * };
+ * </pre>
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} null if there were no nulls/undefineds, otherwise returns
+ * a sort value that should be passed back from the sort function
+ *
+ */
+ self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );
+
+
+ /**
+ * @ngdoc function
+ * @name sortChanged
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description The sort criteria on one or more columns has
+ * changed. Provides as parameters the grid and the output of
+ * getColumnSorting, which is an array of gridColumns
+ * that have sorting on them, sorted in priority order.
+ *
+ * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
+ * @param {Function} callBack Will be called when the event is emited. The function passes back an array of columns with
+ * sorts on them, in priority order.
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.sortChanged( $scope, function(sortColumns){
+ * // do something
+ * });
+ * </pre>
+ */
+ self.api.registerEvent( 'core', 'sortChanged' );
+
+ /**
+ * @ngdoc function
+ * @name columnVisibilityChanged
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description The visibility of a column has changed,
+ * the column itself is passed out as a parameter of the event.
+ *
+ * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
+ * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.columnVisibilityChanged( $scope, function (column) {
+ * // do something
+ * } );
+ * </pre>
+ */
+ self.api.registerEvent( 'core', 'columnVisibilityChanged' );
+
+ /**
+ * @ngdoc method
+ * @name notifyDataChange
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Notify the grid that a data or config change has occurred,
+ * where that change isn't something the grid was otherwise noticing. This
+ * might be particularly relevant where you've changed values within the data
+ * and you'd like cell classes to be re-evaluated, or changed config within
+ * the columnDef and you'd like headerCellClasses to be re-evaluated.
+ * @param {string} type one of the
+ * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN), which tells
+ * us which refreshes to fire.
+ *
+ */
+ self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );
+
+ /**
+ * @ngdoc method
+ * @name clearAllFilters
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Clears all filters and optionally refreshes the visible rows.
+ * @param {object} refreshRows Defaults to true.
+ * @param {object} clearConditions Defaults to false.
+ * @param {object} clearFlags Defaults to false.
+ * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
+ */
+ self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);
+
+ self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);
+ self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);
+ self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);
+
+ self.registerStyleComputation({
+ priority: 10,
+ func: self.getFooterStyles
+ });
+ };
+
+ Grid.prototype.calcFooterHeight = function () {
+ if (!this.hasFooter()) {
+ return 0;
+ }
+
+ var height = 0;
+ if (this.options.showGridFooter) {
+ height += this.options.gridFooterHeight;
+ }
+
+ height += this.calcColumnFooterHeight();
+
+ return height;
+ };
+
+ Grid.prototype.calcColumnFooterHeight = function () {
+ var height = 0;
+
+ if (this.options.showColumnFooter) {
+ height += this.options.columnFooterHeight;
+ }
+
+ return height;
+ };
+
+ Grid.prototype.getFooterStyles = function () {
+ var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';
+ style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';
+ return style;
+ };
+
+ Grid.prototype.hasFooter = function () {
+ return this.options.showGridFooter || this.options.showColumnFooter;
+ };
+
+ /**
+ * @ngdoc function
+ * @name isRTL
+ * @methodOf ui.grid.class:Grid
+ * @description Returns true if grid is RightToLeft
+ */
+ Grid.prototype.isRTL = function () {
+ return this.rtl;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name registerColumnBuilder
+ * @methodOf ui.grid.class:Grid
+ * @description When the build creates columns from column definitions, the columnbuilders will be called to add
+ * additional properties to the column.
+ * @param {function(colDef, col, gridOptions)} columnBuilder function to be called
+ */
+ Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {
+ this.columnBuilders.push(columnBuilder);
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildColumnDefsFromData
+ * @methodOf ui.grid.class:Grid
+ * @description Populates columnDefs from the provided data
+ * @param {function(colDef, col, gridOptions)} rowBuilder function to be called
+ */
+ Grid.prototype.buildColumnDefsFromData = function (dataRows){
+ this.options.columnDefs = gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerRowBuilder
+ * @methodOf ui.grid.class:Grid
+ * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add
+ * additional properties to the row.
+ * @param {function(row, gridOptions)} rowBuilder function to be called
+ */
+ Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {
+ this.rowBuilders.push(rowBuilder);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name registerDataChangeCallback
+ * @methodOf ui.grid.class:Grid
+ * @description When a data change occurs, the data change callbacks of the specified type
+ * will be called. The rules are:
+ *
+ * - when the data watch fires, that is considered a ROW change (the data watch only notices
+ * added or removed rows)
+ * - when the api is called to inform us of a change, the declared type of that change is used
+ * - when a cell edit completes, the EDIT callbacks are triggered
+ * - when the columnDef watch fires, the COLUMN callbacks are triggered
+ * - when the options watch fires, the OPTIONS callbacks are triggered
+ *
+ * For a given event:
+ * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks
+ * - ROW calls ROW and ALL callbacks
+ * - EDIT calls EDIT and ALL callbacks
+ * - COLUMN calls COLUMN and ALL callbacks
+ * - OPTIONS calls OPTIONS and ALL callbacks
+ *
+ * @param {function(grid)} callback function to be called
+ * @param {array} types the types of data change you want to be informed of. Values from
+ * the uiGridConstants.dataChange values ( ALL, EDIT, ROW, COLUMN, OPTIONS ). Optional and defaults to
+ * ALL
+ * @returns {function} deregister function - a function that can be called to deregister this callback
+ */
+ Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {
+ var uid = gridUtil.nextUid();
+ if ( !types ){
+ types = [uiGridConstants.dataChange.ALL];
+ }
+ if ( !Array.isArray(types)){
+ gridUtil.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: " + types );
+ }
+ this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };
+
+ var self = this;
+ var deregisterFunction = function() {
+ delete self.dataChangeCallbacks[uid];
+ };
+ return deregisterFunction;
+ };
+
+ /**
+ * @ngdoc function
+ * @name callDataChangeCallbacks
+ * @methodOf ui.grid.class:Grid
+ * @description Calls the callbacks based on the type of data change that
+ * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the
+ * event type is matching, or if the type is ALL.
+ * @param {number} type the type of event that occurred - one of the
+ * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)
+ */
+ Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {
+ angular.forEach( this.dataChangeCallbacks, function( callback, uid ){
+ if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||
+ callback.types.indexOf( type ) !== -1 ||
+ type === uiGridConstants.dataChange.ALL ) {
+ if (callback._this) {
+ callback.callback.apply(callback._this,this);
+ }
+ else {
+ callback.callback( this );
+ }
+ }
+ }, this);
+ };
+
+ /**
+ * @ngdoc function
+ * @name notifyDataChange
+ * @methodOf ui.grid.class:Grid
+ * @description Notifies us that a data change has occurred, used in the public
+ * api for users to tell us when they've changed data or some other event that
+ * our watches cannot pick up
+ * @param {string} type the type of event that occurred - one of the
+ * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)
+ */
+ Grid.prototype.notifyDataChange = function notifyDataChange(type) {
+ var constants = uiGridConstants.dataChange;
+ if ( type === constants.ALL ||
+ type === constants.COLUMN ||
+ type === constants.EDIT ||
+ type === constants.ROW ||
+ type === constants.OPTIONS ){
+ this.callDataChangeCallbacks( type );
+ } else {
+ gridUtil.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: " + type);
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name columnRefreshCallback
+ * @methodOf ui.grid.class:Grid
+ * @description refreshes the grid when a column refresh
+ * is notified, which triggers handling of the visible flag.
+ * This is called on uiGridConstants.dataChange.COLUMN, and is
+ * registered as a dataChangeCallback in grid.js
+ * @param {string} name column name
+ */
+ Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){
+ grid.buildColumns();
+ grid.queueGridRefresh();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name processRowsCallback
+ * @methodOf ui.grid.class:Grid
+ * @description calls the row processors, specifically
+ * intended to reset the sorting when an edit is called,
+ * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT
+ * @param {string} name column name
+ */
+ Grid.prototype.processRowsCallback = function processRowsCallback( grid ){
+ grid.queueGridRefresh();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name updateFooterHeightCallback
+ * @methodOf ui.grid.class:Grid
+ * @description recalculates the footer height,
+ * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS
+ * @param {string} name column name
+ */
+ Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ){
+ grid.footerHeight = grid.calcFooterHeight();
+ grid.columnFooterHeight = grid.calcColumnFooterHeight();
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColumn
+ * @methodOf ui.grid.class:Grid
+ * @description returns a grid column for the column name
+ * @param {string} name column name
+ */
+ Grid.prototype.getColumn = function getColumn(name) {
+ var columns = this.columns.filter(function (column) {
+ return column.colDef.name === name;
+ });
+ return columns.length > 0 ? columns[0] : null;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getColDef
+ * @methodOf ui.grid.class:Grid
+ * @description returns a grid colDef for the column name
+ * @param {string} name column.field
+ */
+ Grid.prototype.getColDef = function getColDef(name) {
+ var colDefs = this.options.columnDefs.filter(function (colDef) {
+ return colDef.name === name;
+ });
+ return colDefs.length > 0 ? colDefs[0] : null;
+ };
+
+ /**
+ * @ngdoc function
+ * @name assignTypes
+ * @methodOf ui.grid.class:Grid
+ * @description uses the first row of data to assign colDef.type for any types not defined.
+ */
+ /**
+ * @ngdoc property
+ * @name type
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description the type of the column, used in sorting. If not provided then the
+ * grid will guess the type. Add this only if the grid guessing is not to your
+ * satisfaction. One of:
+ * - 'string'
+ * - 'boolean'
+ * - 'number'
+ * - 'date'
+ * - 'object'
+ * - 'numberStr'
+ * Note that if you choose date, your dates should be in a javascript date type
+ *
+ */
+ Grid.prototype.assignTypes = function(){
+ var self = this;
+ self.options.columnDefs.forEach(function (colDef, index) {
+
+ //Assign colDef type if not specified
+ if (!colDef.type) {
+ var col = new GridColumn(colDef, index, self);
+ var firstRow = self.rows.length > 0 ? self.rows[0] : null;
+ if (firstRow) {
+ colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));
+ }
+ else {
+ colDef.type = 'string';
+ }
+ }
+ });
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name isRowHeaderColumn
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if the column is a row Header
+ * @param {object} column column
+ */
+ Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {
+ return this.rowHeaderColumns.indexOf(column) !== -1;
+ };
+
+ /**
+ * @ngdoc function
+ * @name addRowHeaderColumn
+ * @methodOf ui.grid.class:Grid
+ * @description adds a row header column to the grid
+ * @param {object} column def
+ */
+ Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef) {
+ var self = this;
+ var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
+ rowHeaderCol.isRowHeader = true;
+ if (self.isRTL()) {
+ self.createRightContainer();
+ rowHeaderCol.renderContainer = 'right';
+ }
+ else {
+ self.createLeftContainer();
+ rowHeaderCol.renderContainer = 'left';
+ }
+
+ // relies on the default column builder being first in array, as it is instantiated
+ // as part of grid creation
+ self.columnBuilders[0](colDef,rowHeaderCol,self.options)
+ .then(function(){
+ rowHeaderCol.enableFiltering = false;
+ rowHeaderCol.enableSorting = false;
+ rowHeaderCol.enableHiding = false;
+ self.rowHeaderColumns.push(rowHeaderCol);
+ self.buildColumns()
+ .then( function() {
+ self.preCompileCellTemplates();
+ self.queueGridRefresh();
+ });
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getOnlyDataColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns all columns except for rowHeader columns
+ */
+ Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {
+ var self = this;
+ var cols = [];
+ self.columns.forEach(function (col) {
+ if (self.rowHeaderColumns.indexOf(col) === -1) {
+ cols.push(col);
+ }
+ });
+ return cols;
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildColumns
+ * @methodOf ui.grid.class:Grid
+ * @description creates GridColumn objects from the columnDefinition. Calls each registered
+ * columnBuilder to further process the column
+ * @param {object} options An object contains options to use when building columns
+ *
+ * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.
+ *
+ * @returns {Promise} a promise to load any needed column resources
+ */
+ Grid.prototype.buildColumns = function buildColumns(opts) {
+ var options = {
+ orderByColumnDefs: false
+ };
+
+ angular.extend(options, opts);
+
+ // gridUtil.logDebug('buildColumns');
+ var self = this;
+ var builderPromises = [];
+ var headerOffset = self.rowHeaderColumns.length;
+ var i;
+
+ // Remove any columns for which a columnDef cannot be found
+ // Deliberately don't use forEach, as it doesn't like splice being called in the middle
+ // Also don't cache columns.length, as it will change during this operation
+ for (i = 0; i < self.columns.length; i++){
+ if (!self.getColDef(self.columns[i].name)) {
+ self.columns.splice(i, 1);
+ i--;
+ }
+ }
+
+ //add row header columns to the grid columns array _after_ columns without columnDefs have been removed
+ self.rowHeaderColumns.forEach(function (rowHeaderColumn) {
+ self.columns.unshift(rowHeaderColumn);
+ });
+
+
+ // look at each column def, and update column properties to match. If the column def
+ // doesn't have a column, then splice in a new gridCol
+ self.options.columnDefs.forEach(function (colDef, index) {
+ self.preprocessColDef(colDef);
+ var col = self.getColumn(colDef.name);
+
+ if (!col) {
+ col = new GridColumn(colDef, gridUtil.nextUid(), self);
+ self.columns.splice(index + headerOffset, 0, col);
+ }
+ else {
+ // tell updateColumnDef that the column was pre-existing
+ col.updateColumnDef(colDef, false);
+ }
+
+ self.columnBuilders.forEach(function (builder) {
+ builderPromises.push(builder.call(self, colDef, col, self.options));
+ });
+ });
+
+ /*** Reorder columns if necessary ***/
+ if (!!options.orderByColumnDefs) {
+ // Create a shallow copy of the columns as a cache
+ var columnCache = self.columns.slice(0);
+
+ // We need to allow for the "row headers" when mapping from the column defs array to the columns array
+ // If we have a row header in columns[0] and don't account for it we'll overwrite it with the column in columnDefs[0]
+
+ // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then
+ // columns will be shorter than columnDefs. In this situation we'll avoid an error, but the user will still get an unexpected result
+ var len = Math.min(self.options.columnDefs.length, self.columns.length);
+ for (i = 0; i < len; i++) {
+ // If the column at this index has a different name than the column at the same index in the column defs...
+ if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {
+ // Replace the one in the cache with the appropriate column
+ columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);
+ }
+ else {
+ // Otherwise just copy over the one from the initial columns
+ columnCache[i + headerOffset] = self.columns[i + headerOffset];
+ }
+ }
+
+ // Empty out the columns array, non-destructively
+ self.columns.length = 0;
+
+ // And splice in the updated, ordered columns from the cache
+ Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));
+ }
+
+ return $q.all(builderPromises).then(function(){
+ if (self.rows.length > 0){
+ self.assignTypes();
+ }
+ });
+ };
+
+/**
+ * @ngdoc function
+ * @name preCompileCellTemplates
+ * @methodOf ui.grid.class:Grid
+ * @description precompiles all cell templates
+ */
+ Grid.prototype.preCompileCellTemplates = function() {
+ var self = this;
+
+ var preCompileTemplate = function( col ) {
+ var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));
+ html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var compiledElementFn = $compile(html);
+ col.compiledElementFn = compiledElementFn;
+
+ if (col.compiledElementFnDefer) {
+ col.compiledElementFnDefer.resolve(col.compiledElementFn);
+ }
+ };
+
+ this.columns.forEach(function (col) {
+ if ( col.cellTemplate ){
+ preCompileTemplate( col );
+ } else if ( col.cellTemplatePromise ){
+ col.cellTemplatePromise.then( function() {
+ preCompileTemplate( col );
+ });
+ }
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getGridQualifiedColField
+ * @methodOf ui.grid.class:Grid
+ * @description Returns the $parse-able accessor for a column within its $scope
+ * @param {GridColumn} col col object
+ */
+ Grid.prototype.getQualifiedColField = function (col) {
+ return 'row.entity.' + gridUtil.preEval(col.field);
+ };
+
+ /**
+ * @ngdoc function
+ * @name createLeftContainer
+ * @methodOf ui.grid.class:Grid
+ * @description creates the left render container if it doesn't already exist
+ */
+ Grid.prototype.createLeftContainer = function() {
+ if (!this.hasLeftContainer()) {
+ this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name createRightContainer
+ * @methodOf ui.grid.class:Grid
+ * @description creates the right render container if it doesn't already exist
+ */
+ Grid.prototype.createRightContainer = function() {
+ if (!this.hasRightContainer()) {
+ this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasLeftContainer
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if leftContainer exists
+ */
+ Grid.prototype.hasLeftContainer = function() {
+ return this.renderContainers.left !== undefined;
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasRightContainer
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if rightContainer exists
+ */
+ Grid.prototype.hasRightContainer = function() {
+ return this.renderContainers.right !== undefined;
+ };
+
+
+ /**
+ * undocumented function
+ * @name preprocessColDef
+ * @methodOf ui.grid.class:Grid
+ * @description defaults the name property from field to maintain backwards compatibility with 2.x
+ * validates that name or field is present
+ */
+ Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {
+ var self = this;
+
+ if (!colDef.field && !colDef.name) {
+ throw new Error('colDef.name or colDef.field property is required');
+ }
+
+ //maintain backwards compatibility with 2.x
+ //field was required in 2.x. now name is required
+ if (colDef.name === undefined && colDef.field !== undefined) {
+ // See if the column name already exists:
+ var newName = colDef.field,
+ counter = 2;
+ while (self.getColumn(newName)) {
+ newName = colDef.field + counter.toString();
+ counter++;
+ }
+ colDef.name = newName;
+ }
+ };
+
+ // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters
+ Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {
+ var self = this;
+
+ var t = [];
+ for (var i = 0; i < n.length; i++) {
+ var nV = nAccessor ? n[i][nAccessor] : n[i];
+
+ var found = false;
+ for (var j = 0; j < o.length; j++) {
+ var oV = oAccessor ? o[j][oAccessor] : o[j];
+ if (self.options.rowEquality(nV, oV)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ t.push(nV);
+ }
+ }
+
+ return t;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRow
+ * @methodOf ui.grid.class:Grid
+ * @description returns the GridRow that contains the rowEntity
+ * @param {object} rowEntity the gridOptions.data array element instance
+ * @param {array} rows [optional] the rows to look in - if not provided then
+ * looks in grid.rows
+ */
+ Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {
+ var self = this;
+
+ lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;
+
+ var rows = lookInRows.filter(function (row) {
+ return self.options.rowEquality(row.entity, rowEntity);
+ });
+ return rows.length > 0 ? rows[0] : null;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name modifyRows
+ * @methodOf ui.grid.class:Grid
+ * @description creates or removes GridRow objects from the newRawData array. Calls each registered
+ * rowBuilder to further process the row
+ * @param {array} newRawData Modified set of data
+ *
+ * This method aims to achieve three things:
+ * 1. the resulting rows array is in the same order as the newRawData, we'll call
+ * rowsProcessors immediately after to sort the data anyway
+ * 2. if we have row hashing available, we try to use the rowHash to find the row
+ * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected
+ *
+ * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates
+ * the newRows and newHash
+ *
+ * ```
+ * newRawData.forEach newEntity
+ * if (hashing enabled)
+ * check oldHash for newEntity
+ * else
+ * look for old row directly in oldRows
+ * if !oldRowFound // must be a new row
+ * create newRow
+ * append to the newRows and add to newHash
+ * run the processors
+ * ```
+ *
+ * Rows are identified using the hashKey if configured. If not configured, then rows
+ * are identified using the gridOptions.rowEquality function
+ *
+ * This method is useful when trying to select rows immediately after loading data without
+ * using a $timeout/$interval, e.g.:
+ *
+ * $scope.gridOptions.data = someData;
+ * $scope.gridApi.grid.modifyRows($scope.gridOptions.data);
+ * $scope.gridApi.selection.selectRow($scope.gridOptions.data[0]);
+ *
+ * OR to persist row selection after data update (e.g. rows selected, new data loaded, want
+ * originally selected rows to be re-selected))
+ */
+ Grid.prototype.modifyRows = function modifyRows(newRawData) {
+ var self = this;
+ var oldRows = self.rows.slice(0);
+ var oldRowHash = self.rowHashMap || self.createRowHashMap();
+ self.rowHashMap = self.createRowHashMap();
+ self.rows.length = 0;
+
+ newRawData.forEach( function( newEntity, i ) {
+ var newRow;
+ if ( self.options.enableRowHashing ){
+ // if hashing is enabled, then this row will be in the hash if we already know about it
+ newRow = oldRowHash.get( newEntity );
+ } else {
+ // otherwise, manually search the oldRows to see if we can find this row
+ newRow = self.getRow(newEntity, oldRows);
+ }
+
+ // if we didn't find the row, it must be new, so create it
+ if ( !newRow ){
+ newRow = self.processRowBuilders(new GridRow(newEntity, i, self));
+ }
+
+ self.rows.push( newRow );
+ self.rowHashMap.put( newEntity, newRow );
+ });
+
+ self.assignTypes();
+
+ var p1 = $q.when(self.processRowsProcessors(self.rows))
+ .then(function (renderableRows) {
+ return self.setVisibleRows(renderableRows);
+ });
+
+ var p2 = $q.when(self.processColumnsProcessors(self.columns))
+ .then(function (renderableColumns) {
+ return self.setVisibleColumns(renderableColumns);
+ });
+
+ return $q.all([p1, p2]);
+ };
+
+
+ /**
+ * Private Undocumented Method
+ * @name addRows
+ * @methodOf ui.grid.class:Grid
+ * @description adds the newRawData array of rows to the grid and calls all registered
+ * rowBuilders. this keyword will reference the grid
+ */
+ Grid.prototype.addRows = function addRows(newRawData) {
+ var self = this;
+
+ var existingRowCount = self.rows.length;
+ for (var i = 0; i < newRawData.length; i++) {
+ var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));
+
+ if (self.options.enableRowHashing) {
+ var found = self.rowHashMap.get(newRow.entity);
+ if (found) {
+ found.row = newRow;
+ }
+ }
+
+ self.rows.push(newRow);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name processRowBuilders
+ * @methodOf ui.grid.class:Grid
+ * @description processes all RowBuilders for the gridRow
+ * @param {GridRow} gridRow reference to gridRow
+ * @returns {GridRow} the gridRow with all additional behavior added
+ */
+ Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {
+ var self = this;
+
+ self.rowBuilders.forEach(function (builder) {
+ builder.call(self, gridRow, self.options);
+ });
+
+ return gridRow;
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerStyleComputation
+ * @methodOf ui.grid.class:Grid
+ * @description registered a styleComputation function
+ *
+ * If the function returns a value it will be appended into the grid's `<style>` block
+ * @param {function($scope)} styleComputation function
+ */
+ Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {
+ this.styleComputations.push(styleComputationInfo);
+ };
+
+
+ // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...
+ // Grid.prototype.registerRowFilter = function(filter) {
+ // // TODO(c0bra): validate filter?
+
+ // this.rowFilters.push(filter);
+ // };
+
+ // Grid.prototype.removeRowFilter = function(filter) {
+ // var idx = this.rowFilters.indexOf(filter);
+
+ // if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ // this.rowFilters.slice(idx, 1);
+ // }
+ // };
+
+ // Grid.prototype.processRowFilters = function(rows) {
+ // var self = this;
+ // self.rowFilters.forEach(function (filter) {
+ // filter.call(self, rows);
+ // });
+ // };
+
+
+ /**
+ * @ngdoc function
+ * @name registerRowsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @description
+ *
+ * Register a "rows processor" function. When the rows are updated,
+ * the grid calls each registered "rows processor", which has a chance
+ * to alter the set of rows (sorting, etc) as long as the count is not
+ * modified.
+ *
+ * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and must
+ * return the updated rows list, which is passed to the next processor in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
+ *
+ * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ *
+ */
+ Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {
+ if (!angular.isFunction(processor)) {
+ throw 'Attempt to register non-function rows processor: ' + processor;
+ }
+
+ this.rowsProcessors.push({processor: processor, priority: priority});
+ this.rowsProcessors.sort(function sortByPriority( a, b ){
+ return a.priority - b.priority;
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name removeRowsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @param {function(renderableRows)} rows processor function
+ * @description Remove a registered rows processor
+ */
+ Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {
+ var idx = -1;
+ this.rowsProcessors.forEach(function(rowsProcessor, index){
+ if ( rowsProcessor.processor === processor ){
+ idx = index;
+ }
+ });
+
+ if ( idx !== -1 ) {
+ this.rowsProcessors.splice(idx, 1);
+ }
+ };
+
+ /**
+ * Private Undocumented Method
+ * @name processRowsProcessors
+ * @methodOf ui.grid.class:Grid
+ * @param {Array[GridRow]} The array of "renderable" rows
+ * @param {Array[GridColumn]} The array of columns
+ * @description Run all the registered rows processors on the array of renderable rows
+ */
+ Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {
+ var self = this;
+
+ // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
+ var myRenderableRows = renderableRows.slice(0);
+
+ // Return myRenderableRows with no processing if we have no rows processors
+ if (self.rowsProcessors.length === 0) {
+ return $q.when(myRenderableRows);
+ }
+
+ // Counter for iterating through rows processors
+ var i = 0;
+
+ // Promise for when we're done with all the processors
+ var finished = $q.defer();
+
+ // This function will call the processor in self.rowsProcessors at index 'i', and then
+ // when done will call the next processor in the list, using the output from the processor
+ // at i as the argument for 'renderedRowsToProcess' on the next iteration.
+ //
+ // If we're at the end of the list of processors, we resolve our 'finished' callback with
+ // the result.
+ function startProcessor(i, renderedRowsToProcess) {
+ // Get the processor at 'i'
+ var processor = self.rowsProcessors[i].processor;
+
+ // Call the processor, passing in the rows to process and the current columns
+ // (note: it's wrapped in $q.when() in case the processor does not return a promise)
+ return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )
+ .then(function handleProcessedRows(processedRows) {
+ // Check for errors
+ if (!processedRows) {
+ throw "Processor at index " + i + " did not return a set of renderable rows";
+ }
+
+ if (!angular.isArray(processedRows)) {
+ throw "Processor at index " + i + " did not return an array";
+ }
+
+ // Processor is done, increment the counter
+ i++;
+
+ // If we're not done with the processors, call the next one
+ if (i <= self.rowsProcessors.length - 1) {
+ return startProcessor(i, processedRows);
+ }
+ // We're done! Resolve the 'finished' promise
+ else {
+ finished.resolve(processedRows);
+ }
+ });
+ }
+
+ // Start on the first processor
+ startProcessor(0, myRenderableRows);
+
+ return finished.promise;
+ };
+
+ Grid.prototype.setVisibleRows = function setVisibleRows(rows) {
+ var self = this;
+
+ // Reset all the render container row caches
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ container.canvasHeightShouldUpdate = true;
+
+ if ( typeof(container.visibleRowCache) === 'undefined' ){
+ container.visibleRowCache = [];
+ } else {
+ container.visibleRowCache.length = 0;
+ }
+ }
+
+ // rows.forEach(function (row) {
+ for (var ri = 0; ri < rows.length; ri++) {
+ var row = rows[ri];
+
+ var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';
+
+ // If the row is visible
+ if (row.visible) {
+ self.renderContainers[targetContainer].visibleRowCache.push(row);
+ }
+ }
+ self.api.core.raise.rowsRendered(this.api);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerColumnsProcessor
+ * @methodOf ui.grid.class:Grid
+ * @param {function(renderedColumnsToProcess, rows)} columnProcessor column processor function, which
+ * is run in the context of the grid (i.e. this for the function will be the grid), and
+ * which must return an updated renderedColumnsToProcess which can be passed to the next processor
+ * in the chain
+ * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
+ * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
+ *
+ * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
+ * @description
+
+ Register a "columns processor" function. When the columns are updated,
+ the grid calls each registered "columns processor", which has a chance
+ to alter the set of columns, as long as the count is not modified.
+ */
+ Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {
+ if (!angular.isFunction(processor)) {
+ throw 'Attempt to register non-function rows processor: ' + processor;
+ }
+
+ this.columnsProcessors.push({processor: processor, priority: priority});
+ this.columnsProcessors.sort(function sortByPriority( a, b ){
+ return a.priority - b.priority;
+ });
+ };
+
+ Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {
+ var idx = this.columnsProcessors.indexOf(processor);
+
+ if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ this.columnsProcessors.splice(idx, 1);
+ }
+ };
+
+ Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {
+ var self = this;
+
+ // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
+ var myRenderableColumns = renderableColumns.slice(0);
+
+ // Return myRenderableRows with no processing if we have no rows processors
+ if (self.columnsProcessors.length === 0) {
+ return $q.when(myRenderableColumns);
+ }
+
+ // Counter for iterating through rows processors
+ var i = 0;
+
+ // Promise for when we're done with all the processors
+ var finished = $q.defer();
+
+ // This function will call the processor in self.rowsProcessors at index 'i', and then
+ // when done will call the next processor in the list, using the output from the processor
+ // at i as the argument for 'renderedRowsToProcess' on the next iteration.
+ //
+ // If we're at the end of the list of processors, we resolve our 'finished' callback with
+ // the result.
+ function startProcessor(i, renderedColumnsToProcess) {
+ // Get the processor at 'i'
+ var processor = self.columnsProcessors[i].processor;
+
+ // Call the processor, passing in the rows to process and the current columns
+ // (note: it's wrapped in $q.when() in case the processor does not return a promise)
+ return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )
+ .then(function handleProcessedRows(processedColumns) {
+ // Check for errors
+ if (!processedColumns) {
+ throw "Processor at index " + i + " did not return a set of renderable rows";
+ }
+
+ if (!angular.isArray(processedColumns)) {
+ throw "Processor at index " + i + " did not return an array";
+ }
+
+ // Processor is done, increment the counter
+ i++;
+
+ // If we're not done with the processors, call the next one
+ if (i <= self.columnsProcessors.length - 1) {
+ return startProcessor(i, myRenderableColumns);
+ }
+ // We're done! Resolve the 'finished' promise
+ else {
+ finished.resolve(myRenderableColumns);
+ }
+ });
+ }
+
+ // Start on the first processor
+ startProcessor(0, myRenderableColumns);
+
+ return finished.promise;
+ };
+
+ Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {
+ // gridUtil.logDebug('setVisibleColumns');
+
+ var self = this;
+
+ // Reset all the render container row caches
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ container.visibleColumnCache.length = 0;
+ }
+
+ for (var ci = 0; ci < columns.length; ci++) {
+ var column = columns[ci];
+
+ // If the column is visible
+ if (column.visible) {
+ // If the column has a container specified
+ if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {
+ self.renderContainers[column.renderContainer].visibleColumnCache.push(column);
+ }
+ // If not, put it into the body container
+ else {
+ self.renderContainers.body.visibleColumnCache.push(column);
+ }
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name handleWindowResize
+ * @methodOf ui.grid.class:Grid
+ * @description Triggered when the browser window resizes; automatically resizes the grid
+ */
+ Grid.prototype.handleWindowResize = function handleWindowResize($event) {
+ var self = this;
+
+ self.gridWidth = gridUtil.elementWidth(self.element);
+ self.gridHeight = gridUtil.elementHeight(self.element);
+
+ self.queueRefresh();
+ };
+
+ /**
+ * @ngdoc function
+ * @name queueRefresh
+ * @methodOf ui.grid.class:Grid
+ * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue
+ */
+ Grid.prototype.queueRefresh = function queueRefresh() {
+ var self = this;
+
+ if (self.refreshCanceller) {
+ $timeout.cancel(self.refreshCanceller);
+ }
+
+ self.refreshCanceller = $timeout(function () {
+ self.refreshCanvas(true);
+ });
+
+ self.refreshCanceller.then(function () {
+ self.refreshCanceller = null;
+ });
+
+ return self.refreshCanceller;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name queueGridRefresh
+ * @methodOf ui.grid.class:Grid
+ * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue
+ */
+ Grid.prototype.queueGridRefresh = function queueGridRefresh() {
+ var self = this;
+
+ if (self.gridRefreshCanceller) {
+ $timeout.cancel(self.gridRefreshCanceller);
+ }
+
+ self.gridRefreshCanceller = $timeout(function () {
+ self.refresh(true);
+ });
+
+ self.gridRefreshCanceller.then(function () {
+ self.gridRefreshCanceller = null;
+ });
+
+ return self.gridRefreshCanceller;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name updateCanvasHeight
+ * @methodOf ui.grid.class:Grid
+ * @description flags all render containers to update their canvas height
+ */
+ Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {
+ var self = this;
+
+ for (var containerId in self.renderContainers) {
+ if (self.renderContainers.hasOwnProperty(containerId)) {
+ var container = self.renderContainers[containerId];
+ container.canvasHeightShouldUpdate = true;
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name buildStyles
+ * @methodOf ui.grid.class:Grid
+ * @description calls each styleComputation function
+ */
+ // TODO: this used to take $scope, but couldn't see that it was used
+ Grid.prototype.buildStyles = function buildStyles() {
+ // gridUtil.logDebug('buildStyles');
+
+ var self = this;
+
+ self.customStyles = '';
+
+ self.styleComputations
+ .sort(function(a, b) {
+ if (a.priority === null) { return 1; }
+ if (b.priority === null) { return -1; }
+ if (a.priority === null && b.priority === null) { return 0; }
+ return a.priority - b.priority;
+ })
+ .forEach(function (compInfo) {
+ // this used to provide $scope as a second parameter, but I couldn't find any
+ // style builders that used it, so removed it as part of moving to grid from controller
+ var ret = compInfo.func.call(self);
+
+ if (angular.isString(ret)) {
+ self.customStyles += '\n' + ret;
+ }
+ });
+ };
+
+
+ Grid.prototype.minColumnsToRender = function minColumnsToRender() {
+ var self = this;
+ var viewport = this.getViewportWidth();
+
+ var min = 0;
+ var totalWidth = 0;
+ self.columns.forEach(function(col, i) {
+ if (totalWidth < viewport) {
+ totalWidth += col.drawnWidth;
+ min++;
+ }
+ else {
+ var currWidth = 0;
+ for (var j = i; j >= i - min; j--) {
+ currWidth += self.columns[j].drawnWidth;
+ }
+ if (currWidth < viewport) {
+ min++;
+ }
+ }
+ });
+
+ return min;
+ };
+
+ Grid.prototype.getBodyHeight = function getBodyHeight() {
+ // Start with the viewportHeight
+ var bodyHeight = this.getViewportHeight();
+
+ // Add the horizontal scrollbar height if there is one
+ //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
+ // bodyHeight = bodyHeight + this.horizontalScrollbarHeight;
+ //}
+
+ return bodyHeight;
+ };
+
+ // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)
+ // TODO(c0bra): account for footer height
+ Grid.prototype.getViewportHeight = function getViewportHeight() {
+ var self = this;
+
+ var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;
+
+ // Account for native horizontal scrollbar, if present
+ //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
+ // viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;
+ //}
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortHeight = viewPortHeight + adjustment.height;
+
+ //gridUtil.logDebug('viewPortHeight', viewPortHeight);
+
+ return viewPortHeight;
+ };
+
+ Grid.prototype.getViewportWidth = function getViewportWidth() {
+ var self = this;
+
+ var viewPortWidth = this.gridWidth;
+
+ //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;
+ //}
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortWidth = viewPortWidth + adjustment.width;
+
+ //gridUtil.logDebug('getviewPortWidth', viewPortWidth);
+
+ return viewPortWidth;
+ };
+
+ Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
+ var viewPortWidth = this.getViewportWidth();
+
+ //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;
+ //}
+
+ return viewPortWidth;
+ };
+
+ Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {
+ this.verticalScrollSyncCallBackFns[containerId] = callBackFn;
+ };
+
+ Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {
+ this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;
+ };
+
+/**
+ * Scroll needed containers by calling their ScrollSyncs
+ * @param sourceContainerId the containerId that has already set it's top/left.
+ * can be empty string which means all containers need to set top/left
+ * @param scrollEvent
+ */
+ Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {
+
+ if (scrollEvent.y) {
+ //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
+ var verts = ['body','left', 'right'];
+
+ this.flagScrollingVertically(scrollEvent);
+
+ if (sourceContainerId === 'body') {
+ verts = ['left', 'right'];
+ }
+ else if (sourceContainerId === 'left') {
+ verts = ['body', 'right'];
+ }
+ else if (sourceContainerId === 'right') {
+ verts = ['body', 'left'];
+ }
+
+ for (var i = 0; i < verts.length; i++) {
+ var id = verts[i];
+ if (this.verticalScrollSyncCallBackFns[id]) {
+ this.verticalScrollSyncCallBackFns[id](scrollEvent);
+ }
+ }
+
+ }
+
+ if (scrollEvent.x) {
+ //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
+ var horizs = ['body','bodyheader', 'bodyfooter'];
+
+ this.flagScrollingHorizontally(scrollEvent);
+ if (sourceContainerId === 'body') {
+ horizs = ['bodyheader', 'bodyfooter'];
+ }
+
+ for (var j = 0; j < horizs.length; j++) {
+ var idh = horizs[j];
+ if (this.horizontalScrollSyncCallBackFns[idh]) {
+ this.horizontalScrollSyncCallBackFns[idh](scrollEvent);
+ }
+ }
+
+ }
+
+ };
+
+ Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
+ this.viewportAdjusters.push(func);
+ };
+
+ Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {
+ var idx = this.viewportAdjusters.indexOf(func);
+
+ if (typeof(idx) !== 'undefined' && idx !== undefined) {
+ this.viewportAdjusters.splice(idx, 1);
+ }
+ };
+
+ Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {
+ var self = this;
+
+ var adjustment = { height: 0, width: 0 };
+
+ self.viewportAdjusters.forEach(function (func) {
+ adjustment = func.call(this, adjustment);
+ });
+
+ return adjustment;
+ };
+
+ Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {
+ // var count = 0;
+
+ // this.rows.forEach(function (row) {
+ // if (row.visible) {
+ // count++;
+ // }
+ // });
+
+ // return this.visibleRowCache.length;
+ return this.renderContainers.body.visibleRowCache.length;
+ };
+
+ Grid.prototype.getVisibleRows = function getVisibleRows() {
+ return this.renderContainers.body.visibleRowCache;
+ };
+
+ Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {
+ // var count = 0;
+
+ // this.rows.forEach(function (row) {
+ // if (row.visible) {
+ // count++;
+ // }
+ // });
+
+ // return this.visibleRowCache.length;
+ return this.renderContainers.body.visibleColumnCache.length;
+ };
+
+
+ Grid.prototype.searchRows = function searchRows(renderableRows) {
+ return rowSearcher.search(this, renderableRows, this.columns);
+ };
+
+ Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {
+ return rowSorter.sort(this, renderableRows, this.columns);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getCellValue
+ * @methodOf ui.grid.class:Grid
+ * @description Gets the value of a cell for a particular row and column
+ * @param {GridRow} row Row to access
+ * @param {GridColumn} col Column to access
+ */
+ Grid.prototype.getCellValue = function getCellValue(row, col){
+ if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {
+ return row.entity[ '$$' + col.uid].rendered;
+ } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ){
+ return row.entity[col.field];
+ } else {
+ if (!col.cellValueGetterCache) {
+ col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));
+ }
+
+ return col.cellValueGetterCache(row);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name getCellDisplayValue
+ * @methodOf ui.grid.class:Grid
+ * @description Gets the displayed value of a cell after applying any the `cellFilter`
+ * @param {GridRow} row Row to access
+ * @param {GridColumn} col Column to access
+ */
+ Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {
+ if ( !col.cellDisplayGetterCache ) {
+ var custom_filter = col.cellFilter ? " | " + col.cellFilter : "";
+
+ if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {
+ col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);
+ } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {
+ col.cellDisplayGetterCache = $parse(row.entity[col.field] + custom_filter);
+ } else {
+ col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);
+ }
+ }
+
+ return col.cellDisplayGetterCache(row);
+ };
+
+
+ Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {
+ var self = this,
+ p = 0;
+
+ self.columns.forEach(function (col) {
+ if (col.sort && col.sort.priority && col.sort.priority > p) {
+ p = col.sort.priority;
+ }
+ });
+
+ return p + 1;
+ };
+
+ /**
+ * @ngdoc function
+ * @name resetColumnSorting
+ * @methodOf ui.grid.class:Grid
+ * @description Return the columns that the grid is currently being sorted by
+ * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset
+ */
+ Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {
+ var self = this;
+
+ self.columns.forEach(function (col) {
+ if (col !== excludeCol && !col.suppressRemoveSort) {
+ col.sort = {};
+ }
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name getColumnSorting
+ * @methodOf ui.grid.class:Grid
+ * @description Return the columns that the grid is currently being sorted by
+ * @returns {Array[GridColumn]} An array of GridColumn objects
+ */
+ Grid.prototype.getColumnSorting = function getColumnSorting() {
+ var self = this;
+
+ var sortedCols = [], myCols;
+
+ // Iterate through all the columns, sorted by priority
+ // Make local copy of column list, because sorting is in-place and we do not want to
+ // change the original sequence of columns
+ myCols = self.columns.slice(0);
+ myCols.sort(rowSorter.prioritySort).forEach(function (col) {
+ if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
+ sortedCols.push(col);
+ }
+ });
+
+ return sortedCols;
+ };
+
+ /**
+ * @ngdoc function
+ * @name sortColumn
+ * @methodOf ui.grid.class:Grid
+ * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.
+ * Emits the sortChanged event whenever the sort criteria are changed.
+ * @param {GridColumn} column Column to set the sorting on
+ * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.
+ * If not provided, the column will iterate through the sort directions
+ * specified in the {@link ui.grid.class:GridOptions.columnDef#sortDirectionCycle sortDirectionCycle} attribute.
+ * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort
+ * by this column only
+ * @returns {Promise} A resolved promise that supplies the column.
+ */
+
+ Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {
+ var self = this,
+ direction = null;
+
+ if (typeof(column) === 'undefined' || !column) {
+ throw new Error('No column parameter provided');
+ }
+
+ // Second argument can either be a direction or whether to add this column to the existing sort.
+ // If it's a boolean, it's an add, otherwise, it's a direction
+ if (typeof(directionOrAdd) === 'boolean') {
+ add = directionOrAdd;
+ }
+ else {
+ direction = directionOrAdd;
+ }
+
+ if (!add) {
+ self.resetColumnSorting(column);
+ column.sort.priority = 0;
+ // Get the actual priority since there may be columns which have suppressRemoveSort set
+ column.sort.priority = self.getNextColumnSortPriority();
+ }
+ else if (!column.sort.priority){
+ column.sort.priority = self.getNextColumnSortPriority();
+ }
+
+ if (!direction) {
+ // Find the current position in the cycle (or -1).
+ var i = column.sortDirectionCycle.indexOf(column.sort.direction ? column.sort.direction : null);
+ // Proceed to the next position in the cycle (or start at the beginning).
+ i = (i+1) % column.sortDirectionCycle.length;
+ // If suppressRemoveSort is set, and the next position in the cycle would
+ // remove the sort, skip it.
+ if (column.colDef && column.suppressRemoveSort && !column.sortDirectionCycle[i]) {
+ i = (i+1) % column.sortDirectionCycle.length;
+ }
+
+ if (column.sortDirectionCycle[i]) {
+ column.sort.direction = column.sortDirectionCycle[i];
+ } else {
+ column.sort = {};
+ }
+ }
+ else {
+ column.sort.direction = direction;
+ }
+
+ self.api.core.raise.sortChanged( self, self.getColumnSorting() );
+
+ return $q.when(column);
+ };
+
+ /**
+ * communicate to outside world that we are done with initial rendering
+ */
+ Grid.prototype.renderingComplete = function(){
+ if (angular.isFunction(this.options.onRegisterApi)) {
+ this.options.onRegisterApi(this.api);
+ }
+ this.api.core.raise.renderingComplete( this.api );
+ };
+
+ Grid.prototype.createRowHashMap = function createRowHashMap() {
+ var self = this;
+
+ var hashMap = new RowHashMap();
+ hashMap.grid = self;
+
+ return hashMap;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name refresh
+ * @methodOf ui.grid.class:Grid
+ * @description Refresh the rendered grid on screen.
+ * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.
+ */
+ Grid.prototype.refresh = function refresh(rowsAltered) {
+ var self = this;
+
+ var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {
+ self.setVisibleRows(renderableRows);
+ });
+
+ var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {
+ self.setVisibleColumns(renderableColumns);
+ });
+
+ return $q.all([p1, p2]).then(function () {
+ self.redrawInPlace(rowsAltered);
+
+ self.refreshCanvas(true);
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name refreshRows
+ * @methodOf ui.grid.class:Grid
+ * @description Refresh the rendered rows on screen? Note: not functional at present
+ * @returns {promise} promise that is resolved when render completes?
+ *
+ */
+ Grid.prototype.refreshRows = function refreshRows() {
+ var self = this;
+
+ return self.processRowsProcessors(self.rows)
+ .then(function (renderableRows) {
+ self.setVisibleRows(renderableRows);
+
+ self.redrawInPlace();
+
+ self.refreshCanvas( true );
+ });
+ };
+
+ /**
+ * @ngdoc function
+ * @name refreshCanvas
+ * @methodOf ui.grid.class:Grid
+ * @description Builds all styles and recalculates much of the grid sizing
+ * @param {object} buildStyles optional parameter. Use TBD
+ * @returns {promise} promise that is resolved when the canvas
+ * has been refreshed
+ *
+ */
+ Grid.prototype.refreshCanvas = function(buildStyles) {
+ var self = this;
+
+ if (buildStyles) {
+ self.buildStyles();
+ }
+
+ var p = $q.defer();
+
+ // Get all the header heights
+ var containerHeadersToRecalc = [];
+ for (var containerId in self.renderContainers) {
+ if (self.renderContainers.hasOwnProperty(containerId)) {
+ var container = self.renderContainers[containerId];
+
+ // Skip containers that have no canvasWidth set yet
+ if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
+ continue;
+ }
+
+ if (container.header || container.headerCanvas) {
+ container.explicitHeaderHeight = container.explicitHeaderHeight || null;
+ container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;
+
+ containerHeadersToRecalc.push(container);
+ }
+ }
+ }
+
+ /*
+ *
+ * Here we loop through the headers, measuring each element as well as any header "canvas" it has within it.
+ *
+ * If any header is less than the largest header height, it will be resized to that so that we don't have headers
+ * with different heights, which looks like a rendering problem
+ *
+ * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas
+ * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't
+ * appear shorter than other cells.
+ *
+ */
+ if (containerHeadersToRecalc.length > 0) {
+ // Build the styles without the explicit header heights
+ if (buildStyles) {
+ self.buildStyles();
+ }
+
+ // Putting in a timeout as it's not calculating after the grid element is rendered and filled out
+ $timeout(function() {
+ // var oldHeaderHeight = self.grid.headerHeight;
+ // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);
+
+ var rebuildStyles = false;
+
+ // Get all the header heights
+ var maxHeaderHeight = 0;
+ var maxHeaderCanvasHeight = 0;
+ var i, container;
+ var getHeight = function(oldVal, newVal){
+ if ( oldVal !== newVal){
+ rebuildStyles = true;
+ }
+ return newVal;
+ };
+ for (i = 0; i < containerHeadersToRecalc.length; i++) {
+ container = containerHeadersToRecalc[i];
+
+ // Skip containers that have no canvasWidth set yet
+ if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
+ continue;
+ }
+
+ if (container.header) {
+ var headerHeight = container.headerHeight = getHeight(container.headerHeight, parseInt(gridUtil.outerElementHeight(container.header), 10));
+
+ // Get the "inner" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height
+ var topBorder = gridUtil.getBorderSize(container.header, 'top');
+ var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');
+ var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);
+
+ innerHeaderHeight = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;
+
+ container.innerHeaderHeight = innerHeaderHeight;
+
+ // If the header doesn't have an explicit height set, save the largest header height for use later
+ // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
+ if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {
+ maxHeaderHeight = innerHeaderHeight;
+ }
+ }
+
+ if (container.headerCanvas) {
+ var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));
+
+
+ // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later
+ // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
+ if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {
+ maxHeaderCanvasHeight = headerCanvasHeight;
+ }
+ }
+ }
+
+ // Go through all the headers
+ for (i = 0; i < containerHeadersToRecalc.length; i++) {
+ container = containerHeadersToRecalc[i];
+
+ /* If:
+ 1. We have a max header height
+ 2. This container has a header height defined
+ 3. And either this container has an explicit header height set, OR its header height is less than the max
+
+ then:
+
+ Give this container's header an explicit height so it will line up with the tallest header
+ */
+ if (
+ maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&
+ (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)
+ ) {
+ container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);
+ }
+
+ // Do the same as above except for the header canvas
+ if (
+ maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&
+ (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)
+ ) {
+ container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);
+ }
+ }
+
+ // Rebuild styles if the header height has changed
+ // The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available
+ if (buildStyles && rebuildStyles) {
+ self.buildStyles();
+ }
+
+ p.resolve();
+ });
+ }
+ else {
+ // Timeout still needs to be here to trigger digest after styles have been rebuilt
+ $timeout(function() {
+ p.resolve();
+ });
+ }
+
+ return p.promise;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name redrawCanvas
+ * @methodOf ui.grid.class:Grid
+ * @description Redraw the rows and columns based on our current scroll position
+ * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated
+ *
+ */
+ Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {
+ // gridUtil.logDebug('redrawInPlace');
+
+ var self = this;
+
+ for (var i in self.renderContainers) {
+ var container = self.renderContainers[i];
+
+ // gridUtil.logDebug('redrawing container', i);
+
+ if (rowsAdded) {
+ container.adjustRows(container.prevScrollTop, null);
+ container.adjustColumns(container.prevScrollLeft, null);
+ }
+ else {
+ container.adjustRows(null, container.prevScrolltopPercentage);
+ container.adjustColumns(null, container.prevScrollleftPercentage);
+ }
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasLeftContainerColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if leftContainer has columns
+ */
+ Grid.prototype.hasLeftContainerColumns = function () {
+ return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;
+ };
+
+ /**
+ * @ngdoc function
+ * @name hasRightContainerColumns
+ * @methodOf ui.grid.class:Grid
+ * @description returns true if rightContainer has columns
+ */
+ Grid.prototype.hasRightContainerColumns = function () {
+ return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;
+ };
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:Grid
+ * @name scrollToIfNecessary
+ * @description Scrolls the grid to make a certain row and column combo visible,
+ * in the case that it is not completely visible on the screen already.
+ * @param {GridRow} gridRow row to make visible
+ * @param {GridCol} gridCol column to make visible
+ * @returns {promise} a promise that is resolved when scrolling is complete
+ */
+ Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {
+ var self = this;
+
+ var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');
+
+ // Alias the visible row and column caches
+ var visRowCache = self.renderContainers.body.visibleRowCache;
+ var visColCache = self.renderContainers.body.visibleColumnCache;
+
+ /*-- Get the top, left, right, and bottom "scrolled" edges of the grid --*/
+
+ // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards
+ var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;
+
+ // Don't the let top boundary be less than 0
+ topBound = (topBound < 0) ? 0 : topBound;
+
+ // The left boundary is the current X scroll position
+ var leftBound = self.renderContainers.body.prevScrollLeft;
+
+ // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.
+ // Basically this is the viewport height added on to the scroll position
+ var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight - self.scrollbarWidth;
+
+ // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows
+ //if (self.horizontalScrollbarHeight) {
+ // bottomBound = bottomBound - self.horizontalScrollbarHeight;
+ //}
+
+ // The right position is the current X scroll position minus the grid width
+ var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.renderContainers.body.getViewportWidth());
+
+ // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells
+ //if (self.verticalScrollbarWidth) {
+ // rightBound = rightBound - self.verticalScrollbarWidth;
+ //}
+
+ // We were given a row to scroll to
+ if (gridRow !== null) {
+ // This is the index of the row we want to scroll to, within the list of rows that can be visible
+ var seekRowIndex = visRowCache.indexOf(gridRow);
+
+ // Total vertical scroll length of the grid
+ var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());
+
+ // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
+ //if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {
+ // scrollLength = scrollLength + self.horizontalScrollbarHeight;
+ //}
+
+ // This is the minimum amount of pixels we need to scroll vertical in order to see this row.
+ var pixelsToSeeRow = ((seekRowIndex + 1) * self.options.rowHeight);
+
+ // Don't let the pixels required to see the row be less than zero
+ pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;
+
+ var scrollPixels, percentage;
+
+ // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
+ if (pixelsToSeeRow < topBound) {
+ // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
+ // to get the full position we need
+ scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ percentage = scrollPixels / scrollLength;
+ scrollEvent.y = { percentage: percentage };
+ }
+ // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
+ else if (pixelsToSeeRow > bottomBound) {
+ // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
+ // to get the full position we need
+ scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ percentage = scrollPixels / scrollLength;
+ scrollEvent.y = { percentage: percentage };
+ }
+ }
+
+ // We were given a column to scroll to
+ if (gridCol !== null) {
+ // This is the index of the row we want to scroll to, within the list of rows that can be visible
+ var seekColumnIndex = visColCache.indexOf(gridCol);
+
+ // Total vertical scroll length of the grid
+ var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());
+
+ // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
+ // if (self.verticalScrollbarWidth && self.verticalScrollbarWidth > 0) {
+ // horizScrollLength = horizScrollLength + self.verticalScrollbarWidth;
+ // }
+
+ // This is the minimum amount of pixels we need to scroll vertical in order to see this column
+ var columnLeftEdge = 0;
+ for (var i = 0; i < seekColumnIndex; i++) {
+ var col = visColCache[i];
+ columnLeftEdge += col.drawnWidth;
+ }
+ columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;
+
+ var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;
+
+ // Don't let the pixels required to see the column be less than zero
+ columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;
+
+ var horizScrollPixels, horizPercentage;
+
+ // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
+ if (columnLeftEdge < leftBound) {
+ // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
+ // to get the full position we need
+ horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ horizPercentage = horizScrollPixels / horizScrollLength;
+ horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
+ scrollEvent.x = { percentage: horizPercentage };
+ }
+ // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
+ else if (columnRightEdge > rightBound) {
+ // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
+ // to get the full position we need
+ horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;
+
+ // Turn the scroll position into a percentage and make it an argument for a scroll event
+ horizPercentage = horizScrollPixels / horizScrollLength;
+ horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
+ scrollEvent.x = { percentage: horizPercentage };
+ }
+ }
+
+ var deferred = $q.defer();
+
+ // If we need to scroll on either the x or y axes, fire a scroll event
+ if (scrollEvent.y || scrollEvent.x) {
+ scrollEvent.withDelay = false;
+ self.scrollContainers('',scrollEvent);
+ var dereg = self.api.core.on.scrollEnd(null,function() {
+ deferred.resolve(scrollEvent);
+ dereg();
+ });
+ }
+ else {
+ deferred.resolve();
+ }
+
+ return deferred.promise;
+ };
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:Grid
+ * @name scrollTo
+ * @description Scroll the grid such that the specified
+ * row and column is in view
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible
+ * @param {object} colDef to make visible
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ Grid.prototype.scrollTo = function (rowEntity, colDef) {
+ var gridRow = null, gridCol = null;
+
+ if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {
+ gridRow = this.getRow(rowEntity);
+ }
+
+ if (colDef !== null && typeof(colDef) !== 'undefined' ) {
+ gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);
+ }
+ return this.scrollToIfNecessary(gridRow, gridCol);
+ };
+
+ /**
+ * @ngdoc function
+ * @name clearAllFilters
+ * @methodOf ui.grid.class:Grid
+ * @description Clears all filters and optionally refreshes the visible rows.
+ * @param {object} refreshRows Defaults to true.
+ * @param {object} clearConditions Defaults to false.
+ * @param {object} clearFlags Defaults to false.
+ * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
+ */
+ Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {
+ // Default `refreshRows` to true because it will be the most commonly desired behaviour.
+ if (refreshRows === undefined) {
+ refreshRows = true;
+ }
+ if (clearConditions === undefined) {
+ clearConditions = false;
+ }
+ if (clearFlags === undefined) {
+ clearFlags = false;
+ }
+
+ this.columns.forEach(function(column) {
+ column.filters.forEach(function(filter) {
+ filter.term = undefined;
+
+ if (clearConditions) {
+ filter.condition = undefined;
+ }
+
+ if (clearFlags) {
+ filter.flags = undefined;
+ }
+ });
+ });
+
+ if (refreshRows) {
+ return this.refreshRows();
+ }
+ };
+
+
+ // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)
+ function RowHashMap() {}
+
+ RowHashMap.prototype = {
+ /**
+ * Store key value pair
+ * @param key key to store can be any type
+ * @param value value to store can be any type
+ */
+ put: function(key, value) {
+ this[this.grid.options.rowIdentity(key)] = value;
+ },
+
+ /**
+ * @param key
+ * @returns {Object} the value for the key
+ */
+ get: function(key) {
+ return this[this.grid.options.rowIdentity(key)];
+ },
+
+ /**
+ * Remove the key/value pair
+ * @param key
+ */
+ remove: function(key) {
+ var value = this[key = this.grid.options.rowIdentity(key)];
+ delete this[key];
+ return value;
+ }
+ };
+
+
+
+ return Grid;
+
+}]);
+
+})();
+
+(function () {
+
+ angular.module('ui.grid')
+ .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',
+ function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridApi
+ * @description GridApi provides the ability to register public methods events inside the grid and allow
+ * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.
+ * <br/>
+ * To listen to events, you must add a callback to gridOptions.onRegisterApi
+ * <pre>
+ * $scope.gridOptions.onRegisterApi = function(gridApi){
+ * gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){
+ * $log.log('navigation event');
+ * });
+ * };
+ * </pre>
+ * @param {object} grid grid that owns api
+ */
+ var GridApi = function GridApi(grid) {
+ this.grid = grid;
+ this.listeners = [];
+
+ /**
+ * @ngdoc function
+ * @name renderingComplete
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Rendering is complete, called at the same
+ * time as `onRegisterApi`, but provides a way to obtain
+ * that same event within features without stopping end
+ * users from getting at the onRegisterApi method.
+ *
+ * Included in gridApi so that it's always there - otherwise
+ * there is still a timing problem with when a feature can
+ * call this.
+ *
+ * @param {GridApi} gridApi the grid api, as normally
+ * returned in the onRegisterApi method
+ *
+ * @example
+ * <pre>
+ * gridApi.core.on.renderingComplete( grid );
+ * </pre>
+ */
+ this.registerEvent( 'core', 'renderingComplete' );
+
+ /**
+ * @ngdoc event
+ * @name filterChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the filter is changed. The nature
+ * of the watch expression doesn't allow notification of what changed,
+ * so the receiver of this event will need to re-extract the filter
+ * conditions from the columns.
+ *
+ */
+ this.registerEvent( 'core', 'filterChanged' );
+
+ /**
+ * @ngdoc function
+ * @name setRowInvisible
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Sets an override on the row to make it always invisible,
+ * which will override any filtering or other visibility calculations.
+ * If the row is currently visible then sets it to invisible and calls
+ * both grid refresh and emits the rowsVisibleChanged event
+ * @param {object} rowEntity gridOptions.data[] array instance
+ */
+ this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Clears any override on visibility for the row so that it returns to
+ * using normal filtering and other visibility calculations.
+ * If the row is currently invisible then sets it to visible and calls
+ * both grid refresh and emits the rowsVisibleChanged event
+ * TODO: if a filter is active then we can't just set it to visible?
+ * @param {object} rowEntity gridOptions.data[] array instance
+ */
+ this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );
+
+ /**
+ * @ngdoc function
+ * @name getVisibleRows
+ * @methodOf ui.grid.core.api:PublicApi
+ * @description Returns all visible rows
+ * @param {Grid} grid the grid you want to get visible rows from
+ * @returns {array} an array of gridRow
+ */
+ this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );
+
+ /**
+ * @ngdoc event
+ * @name rowsVisibleChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the rows that are visible
+ * change. The filtering is zero-based, so it isn't possible
+ * to say which rows changed (unlike in the selection feature).
+ * We can plausibly know which row was changed when setRowInvisible
+ * is called, but in that situation the user already knows which row
+ * they changed. When a filter runs we don't know what changed,
+ * and that is the one that would have been useful.
+ *
+ */
+ this.registerEvent( 'core', 'rowsVisibleChanged' );
+
+ /**
+ * @ngdoc event
+ * @name rowsRendered
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised after the cache of visible rows is changed.
+ */
+ this.registerEvent( 'core', 'rowsRendered' );
+
+
+ /**
+ * @ngdoc event
+ * @name scrollBegin
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when scroll begins. Is throttled, so won't be raised too frequently
+ */
+ this.registerEvent( 'core', 'scrollBegin' );
+
+ /**
+ * @ngdoc event
+ * @name scrollEnd
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when scroll has finished. Is throttled, so won't be raised too frequently
+ */
+ this.registerEvent( 'core', 'scrollEnd' );
+
+ /**
+ * @ngdoc event
+ * @name canvasHeightChanged
+ * @eventOf ui.grid.core.api:PublicApi
+ * @description is raised when the canvas height has changed
+ * <br/>
+ * arguments: oldHeight, newHeight
+ */
+ this.registerEvent( 'core', 'canvasHeightChanged');
+ };
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:suppressEvents
+ * @methodOf ui.grid.class:GridApi
+ * @description Used to execute a function while disabling the specified event listeners.
+ * Disables the listenerFunctions, executes the callbackFn, and then enables
+ * the listenerFunctions again
+ * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same
+ * functions that were used in the .on.eventName method
+ * @param {object} callBackFn function to execute
+ * @example
+ * <pre>
+ * var navigate = function (newRowCol, oldRowCol){
+ * //do something on navigate
+ * }
+ *
+ * gridApi.cellNav.on.navigate(scope,navigate);
+ *
+ *
+ * //call the scrollTo event and suppress our navigate listener
+ * //scrollTo will still raise the event for other listeners
+ * gridApi.suppressEvents(navigate, function(){
+ * gridApi.cellNav.scrollTo(aRow, aCol);
+ * });
+ *
+ * </pre>
+ */
+ GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {
+ var self = this;
+ var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];
+
+ //find all registered listeners
+ var foundListeners = self.listeners.filter(function(listener) {
+ return listeners.some(function(l) {
+ return listener.handler === l;
+ });
+ });
+
+ //deregister all the listeners
+ foundListeners.forEach(function(l){
+ l.dereg();
+ });
+
+ callBackFn();
+
+ //reregister all the listeners
+ foundListeners.forEach(function(l){
+ l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);
+ });
+
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerEvent
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers a new event for the given feature. The event will get a
+ * .raise and .on prepended to it
+ * <br>
+ * .raise.eventName() - takes no arguments
+ * <br/>
+ * <br/>
+ * .on.eventName(scope, callBackFn, _this)
+ * <br/>
+ * scope - a scope reference to add a deregister call to the scopes .$on('destroy'). Scope is optional and can be a null value,
+ * but in this case you must deregister it yourself via the returned deregister function
+ * <br/>
+ * callBackFn - The function to call
+ * <br/>
+ * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context
+ * <br/>
+ * .on.eventName returns a dereg funtion that will remove the listener. It's not necessary to use it as the listener
+ * will be removed when the scope is destroyed.
+ * @param {string} featureName name of the feature that raises the event
+ * @param {string} eventName name of the event
+ */
+ GridApi.prototype.registerEvent = function (featureName, eventName) {
+ var self = this;
+ if (!self[featureName]) {
+ self[featureName] = {};
+ }
+
+ var feature = self[featureName];
+ if (!feature.on) {
+ feature.on = {};
+ feature.raise = {};
+ }
+
+ var eventId = self.grid.id + featureName + eventName;
+
+ // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);
+ feature.raise[eventName] = function () {
+ $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));
+ };
+
+ // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);
+ feature.on[eventName] = function (scope, handler, _this) {
+ if ( scope !== null && typeof(scope.$on) === 'undefined' ){
+ gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\'t passed in the input parameters. It is legitimate to pass null, but you\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');
+ return;
+ }
+ var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);
+
+ //track our listener so we can turn off and on
+ var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};
+ self.listeners.push(listener);
+
+ var removeListener = function(){
+ listener.dereg();
+ var index = self.listeners.indexOf(listener);
+ self.listeners.splice(index,1);
+ };
+
+ //destroy tracking when scope is destroyed
+ if (scope) {
+ scope.$on('$destroy', function() {
+ removeListener();
+ });
+ }
+
+
+ return removeListener;
+ };
+ };
+
+ function registerEventWithAngular(eventId, handler, grid, _this) {
+ return $rootScope.$on(eventId, function (event) {
+ var args = Array.prototype.slice.call(arguments);
+ args.splice(0, 1); //remove evt argument
+ handler.apply(_this ? _this : grid.api, args);
+ });
+ }
+
+ /**
+ * @ngdoc function
+ * @name registerEventsFromObject
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers features and events from a simple objectMap.
+ * eventObjectMap must be in this format (multiple features allowed)
+ * <pre>
+ * {featureName:
+ * {
+ * eventNameOne:function(args){},
+ * eventNameTwo:function(args){}
+ * }
+ * }
+ * </pre>
+ * @param {object} eventObjectMap map of feature/event names
+ */
+ GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {
+ var self = this;
+ var features = [];
+ angular.forEach(eventObjectMap, function (featProp, featPropName) {
+ var feature = {name: featPropName, events: []};
+ angular.forEach(featProp, function (prop, propName) {
+ feature.events.push(propName);
+ });
+ features.push(feature);
+ });
+
+ features.forEach(function (feature) {
+ feature.events.forEach(function (event) {
+ self.registerEvent(feature.name, event);
+ });
+ });
+
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerMethod
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers a new event for the given feature
+ * @param {string} featureName name of the feature
+ * @param {string} methodName name of the method
+ * @param {object} callBackFn function to execute
+ * @param {object} _this binds callBackFn 'this' to _this. Defaults to gridApi.grid
+ */
+ GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {
+ if (!this[featureName]) {
+ this[featureName] = {};
+ }
+
+ var feature = this[featureName];
+
+ feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerMethodsFromObject
+ * @methodOf ui.grid.class:GridApi
+ * @description Registers features and methods from a simple objectMap.
+ * eventObjectMap must be in this format (multiple features allowed)
+ * <br>
+ * {featureName:
+ * {
+ * methodNameOne:function(args){},
+ * methodNameTwo:function(args){}
+ * }
+ * @param {object} eventObjectMap map of feature/event names
+ * @param {object} _this binds this to _this for all functions. Defaults to gridApi.grid
+ */
+ GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {
+ var self = this;
+ var features = [];
+ angular.forEach(methodMap, function (featProp, featPropName) {
+ var feature = {name: featPropName, methods: []};
+ angular.forEach(featProp, function (prop, propName) {
+ feature.methods.push({name: propName, fn: prop});
+ });
+ features.push(feature);
+ });
+
+ features.forEach(function (feature) {
+ feature.methods.forEach(function (method) {
+ self.registerMethod(feature.name, method.name, method.fn, _this);
+ });
+ });
+
+ };
+
+ return GridApi;
+
+ }]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {
+
+ /**
+ * ******************************************************************************************
+ * PaulL1: Ugly hack here in documentation. These properties are clearly properties of GridColumn,
+ * and need to be noted as such for those extending and building ui-grid itself.
+ * However, from an end-developer perspective, they interact with all these through columnDefs,
+ * and they really need to be documented there. I feel like they're relatively static, and
+ * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each
+ * comment block. Ugh.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name name
+ * @propertyOf ui.grid.class:GridColumn
+ * @description (mandatory) each column should have a name, although for backward
+ * compatibility with 2.x name can be omitted if field is present
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name name
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (mandatory) each column should have a name, although for backward
+ * compatibility with 2.x name can be omitted if field is present
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name displayName
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Column name that will be shown in the header. If displayName is not
+ * provided then one is generated using the name.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name displayName
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Column name that will be shown in the header. If displayName is not
+ * provided then one is generated using the name.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name field
+ * @propertyOf ui.grid.class:GridColumn
+ * @description field must be provided if you wish to bind to a
+ * property in the data source. Should be an angular expression that evaluates against grid.options.data
+ * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.
+ * See the angular docs on binding expressions.
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name field
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description field must be provided if you wish to bind to a
+ * property in the data source. Should be an angular expression that evaluates against grid.options.data
+ * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>. * See the angular docs on binding expressions. *
+ */
+
+ /**
+ * @ngdoc property
+ * @name filter
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Filter on this column.
+ * @example
+ * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text', flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>
+ *
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridColumn
+ * @description Represents the viewModel for each column. Any state or methods needed for a Grid Column
+ * are defined on this prototype
+ * @param {ColumnDef} colDef the column def to associate with this column
+ * @param {number} uid the unique and immutable uid we'd like to allocate to this column
+ * @param {Grid} grid the grid we'd like to create this column in
+ */
+ function GridColumn(colDef, uid, grid) {
+ var self = this;
+
+ self.grid = grid;
+ self.uid = uid;
+
+ self.updateColumnDef(colDef, true);
+
+ /**
+ * @ngdoc function
+ * @name hideColumn
+ * @methodOf ui.grid.class:GridColumn
+ * @description Hides the column by setting colDef.visible = false
+ */
+ GridColumn.prototype.hideColumn = function() {
+ this.colDef.visible = false;
+ };
+
+ self.aggregationValue = undefined;
+
+ // The footer cell registers to listen for the rowsRendered event, and calls this. Needed to be
+ // in something with a scope so that the dereg would get called
+ self.updateAggregationValue = function() {
+
+ // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);
+
+ /**
+ * @ngdoc property
+ * @name aggregationType
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description The aggregation that you'd like to show in the columnFooter for this
+ * column. Valid values are in uiGridConstants, and currently include `uiGridConstants.aggregationTypes.count`,
+ * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,
+ * `uiGridConstants.aggregationTypes.max`.
+ *
+ * You can also provide a function as the aggregation type, in this case your function needs to accept the full
+ * set of visible rows, and return a value that should be shown
+ */
+ if (!self.aggregationType) {
+ self.aggregationValue = undefined;
+ return;
+ }
+
+ var result = 0;
+ var visibleRows = self.grid.getVisibleRows();
+
+ var cellValues = function(){
+ var values = [];
+ visibleRows.forEach(function (row) {
+ var cellValue = self.grid.getCellValue(row, self);
+ var cellNumber = Number(cellValue);
+ if (!isNaN(cellNumber)) {
+ values.push(cellNumber);
+ }
+ });
+ return values;
+ };
+
+ if (angular.isFunction(self.aggregationType)) {
+ self.aggregationValue = self.aggregationType(visibleRows, self);
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {
+ self.aggregationValue = self.grid.getVisibleRowCount();
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {
+ cellValues().forEach(function (value) {
+ result += value;
+ });
+ self.aggregationValue = result;
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {
+ cellValues().forEach(function (value) {
+ result += value;
+ });
+ result = result / cellValues().length;
+ self.aggregationValue = result;
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {
+ self.aggregationValue = Math.min.apply(null, cellValues());
+ }
+ else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {
+ self.aggregationValue = Math.max.apply(null, cellValues());
+ }
+ else {
+ self.aggregationValue = '\u00A0';
+ }
+ };
+
+// var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });
+
+ /**
+ * @ngdoc function
+ * @name getAggregationValue
+ * @methodOf ui.grid.class:GridColumn
+ * @description gets the aggregation value based on the aggregation type for this column.
+ * Debounced using scrollDebounce option setting
+ */
+ this.getAggregationValue = function() {
+// if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
+// throttledUpdateAggregationValue();
+// }
+
+ return self.aggregationValue;
+ };
+ }
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:GridColumn
+ * @name setPropertyOrDefault
+ * @description Sets a property on the column using the passed in columnDef, and
+ * setting the defaultValue if the value cannot be found on the colDef
+ * @param {ColumnDef} colDef the column def to look in for the property value
+ * @param {string} propName the property name we'd like to set
+ * @param {object} defaultValue the value to use if the colDef doesn't provide the setting
+ */
+ GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {
+ var self = this;
+
+ // Use the column definition filter if we were passed it
+ if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {
+ self[propName] = colDef[propName];
+ }
+ // Otherwise use our own if it's set
+ else if (typeof(self[propName]) !== 'undefined') {
+ self[propName] = self[propName];
+ }
+ // Default to empty object for the filter
+ else {
+ self[propName] = defaultValue ? defaultValue : {};
+ }
+ };
+
+
+
+ /**
+ * @ngdoc property
+ * @name width
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the column width. Can be either
+ * a number or a percentage, or an * for auto.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},
+ * { field: 'field2', width: '20%'},
+ * { field: 'field3', width: '*' }]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name minWidth
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the minimum column width. Should be a number.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name maxWidth
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets the maximum column width. Should be a number.
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name visible
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description sets whether or not the column is visible
+ * </br>Default is true
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [
+ * { field: 'field1', visible: true},
+ * { field: 'field2', visible: false }
+ * ]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @name sort
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description An object of sort information, attributes are:
+ *
+ * - direction: values are uiGridConstants.ASC or uiGridConstants.DESC
+ * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)
+ * - priority: says what order to sort the columns in (lower priority gets sorted first).
+ * @example
+ * <pre>
+ * $scope.gridOptions.columnDefs = [{
+ * field: 'field1',
+ * sort: {
+ * direction: uiGridConstants.ASC,
+ * ignoreSort: true,
+ * priority: 0
+ * }
+ * }];
+ * </pre>
+ */
+
+
+ /**
+ * @ngdoc property
+ * @name sortingAlgorithm
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters
+ * like any normal sorting function with additional 'rowA', 'rowB', and 'direction' parameters
+ * that are the row objects and the current direction of the sort respectively.
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name filters
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Specify multiple filter fields.
+ * @example
+ * <pre>$scope.gridOptions.columnDefs = [
+ * {
+ * field: 'field1', filters: [
+ * {
+ * term: 'aa',
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Filter for field1',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
+ * },
+ * {
+ * condition: uiGridConstants.filter.ENDS_WITH,
+ * placeholder: 'ends with...'
+ * }
+ * ]
+ * }
+ * ]; </pre>
+ *
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name filters
+ * @propertyOf ui.grid.class:GridColumn
+ * @description Filters for this column. Includes 'term' property bound to filter input elements.
+ * @example
+ * <pre>[
+ * {
+ * term: 'foo', // ngModel for <input>
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Filter for foo',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
+ * },
+ * {
+ * term: 'baz',
+ * condition: uiGridConstants.filter.ENDS_WITH,
+ * placeholder: 'ends with...'
+ * }
+ * ] </pre>
+ *
+ *
+ */
+
+ /**
+ * @ngdoc array
+ * @name menuItems
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description used to add menu items to a column. Refer to the tutorial on this
+ * functionality. A number of settings are supported:
+ *
+ * - title: controls the title that is displayed in the menu
+ * - icon: the icon shown alongside that title
+ * - action: the method to call when the menu is clicked
+ * - shown: a function to evaluate to determine whether or not to show the item
+ * - active: a function to evaluate to determine whether or not the item is currently selected
+ * - context: context to pass to the action function, available in this.context in your handler
+ * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false
+ * @example
+ * <pre> $scope.gridOptions.columnDefs = [
+ * { field: 'field1', menuItems: [
+ * {
+ * title: 'Outer Scope Alert',
+ * icon: 'ui-grid-icon-info-circled',
+ * action: function($event) {
+ * this.context.blargh(); // $scope.blargh() would work too, this is just an example
+ * },
+ * shown: function() { return true; },
+ * active: function() { return true; },
+ * context: $scope
+ * },
+ * {
+ * title: 'Grid ID',
+ * action: function() {
+ * alert('Grid ID: ' + this.grid.id);
+ * }
+ * }
+ * ] }]; </pre>
+ *
+ */
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:GridColumn
+ * @name updateColumnDef
+ * @description Moves settings from the columnDef down onto the column,
+ * and sets properties as appropriate
+ * @param {ColumnDef} colDef the column def to look in for the property value
+ * @param {boolean} isNew whether the column is being newly created, if not
+ * we're updating an existing column, and some items such as the sort shouldn't
+ * be copied down
+ */
+ GridColumn.prototype.updateColumnDef = function(colDef, isNew) {
+ var self = this;
+
+ self.colDef = colDef;
+
+ if (colDef.name === undefined) {
+ throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));
+ }
+
+ self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
+
+ if (!angular.isNumber(self.width) || !self.hasCustomWidth || colDef.allowCustomWidthOverride) {
+ var colDefWidth = colDef.width;
+ var parseErrorMsg = "Cannot parse column width '" + colDefWidth + "' for column named '" + colDef.name + "'";
+ self.hasCustomWidth = false;
+
+ if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {
+ self.width = '*';
+ } else if (angular.isString(colDefWidth)) {
+ // See if it ends with a percent
+ if (gridUtil.endsWith(colDefWidth, '%')) {
+ // If so we should be able to parse the non-percent-sign part to a number
+ var percentStr = colDefWidth.replace(/%/g, '');
+ var percent = parseInt(percentStr, 10);
+ if (isNaN(percent)) {
+ throw new Error(parseErrorMsg);
+ }
+ self.width = colDefWidth;
+ }
+ // And see if it's a number string
+ else if (colDefWidth.match(/^(\d+)$/)) {
+ self.width = parseInt(colDefWidth.match(/^(\d+)$/)[1], 10);
+ }
+ // Otherwise it should be a string of asterisks
+ else if (colDefWidth.match(/^\*+$/)) {
+ self.width = colDefWidth;
+ }
+ // No idea, throw an Error
+ else {
+ throw new Error(parseErrorMsg);
+ }
+ }
+ // Is a number, use it as the width
+ else {
+ self.width = colDefWidth;
+ }
+ }
+
+ ['minWidth', 'maxWidth'].forEach(function (name) {
+ var minOrMaxWidth = colDef[name];
+ var parseErrorMsg = "Cannot parse column " + name + " '" + minOrMaxWidth + "' for column named '" + colDef.name + "'";
+
+ if (!angular.isString(minOrMaxWidth) && !angular.isNumber(minOrMaxWidth)) {
+ //Sets default minWidth and maxWidth values
+ self[name] = ((name === 'minWidth') ? 30 : 9000);
+ } else if (angular.isString(minOrMaxWidth)) {
+ if (minOrMaxWidth.match(/^(\d+)$/)) {
+ self[name] = parseInt(minOrMaxWidth.match(/^(\d+)$/)[1], 10);
+ } else {
+ throw new Error(parseErrorMsg);
+ }
+ } else {
+ self[name] = minOrMaxWidth;
+ }
+ });
+
+ //use field if it is defined; name if it is not
+ self.field = (colDef.field === undefined) ? colDef.name : colDef.field;
+
+ if ( typeof( self.field ) !== 'string' ){
+ gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );
+ }
+
+ self.name = colDef.name;
+
+ // Use colDef.displayName as long as it's not undefined, otherwise default to the field name
+ self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
+
+ //self.originalIndex = index;
+
+ self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;
+ self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;
+
+ /**
+ * @ngdoc property
+ * @name cellTooltip
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Whether or not to show a tooltip when a user hovers over the cell.
+ * If set to false, no tooltip. If true, the cell value is shown in the tooltip (useful
+ * if you have long values in your cells), if a function then that function is called
+ * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,
+ * if it is a static string then displays that static string.
+ *
+ * Defaults to false
+ *
+ */
+ if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {
+ self.cellTooltip = false;
+ } else if ( colDef.cellTooltip === true ){
+ self.cellTooltip = function(row, col) {
+ return self.grid.getCellValue( row, col );
+ };
+ } else if (typeof(colDef.cellTooltip) === 'function' ){
+ self.cellTooltip = colDef.cellTooltip;
+ } else {
+ self.cellTooltip = function ( row, col ){
+ return col.colDef.cellTooltip;
+ };
+ }
+
+ /**
+ * @ngdoc property
+ * @name headerTooltip
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Whether or not to show a tooltip when a user hovers over the header cell.
+ * If set to false, no tooltip. If true, the displayName is shown in the tooltip (useful
+ * if you have long values in your headers), if a function then that function is called
+ * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,
+ * if a static string then shows that static string.
+ *
+ * Defaults to false
+ *
+ */
+ if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {
+ self.headerTooltip = false;
+ } else if ( colDef.headerTooltip === true ){
+ self.headerTooltip = function(col) {
+ return col.displayName;
+ };
+ } else if (typeof(colDef.headerTooltip) === 'function' ){
+ self.headerTooltip = colDef.headerTooltip;
+ } else {
+ self.headerTooltip = function ( col ) {
+ return col.colDef.headerTooltip;
+ };
+ }
+
+
+ /**
+ * @ngdoc property
+ * @name footerCellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description footerCellClass can be a string specifying the class to append to a cell
+ * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
+ *
+ */
+ self.footerCellClass = colDef.footerCellClass;
+
+ /**
+ * @ngdoc property
+ * @name cellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description cellClass can be a string specifying the class to append to a cell
+ * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
+ *
+ */
+ self.cellClass = colDef.cellClass;
+
+ /**
+ * @ngdoc property
+ * @name headerCellClass
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description headerCellClass can be a string specifying the class to append to a cell
+ * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
+ *
+ */
+ self.headerCellClass = colDef.headerCellClass;
+
+ /**
+ * @ngdoc property
+ * @name cellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description cellFilter is a filter to apply to the content of each cell
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].cellFilter = 'date'
+ *
+ */
+ self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
+
+ /**
+ * @ngdoc boolean
+ * @name sortCellFiltered
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
+ * sorting the data. Note that when using this option uiGrid will assume that the displayed value is
+ * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible
+ * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}
+ * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`
+ * found in the {@link ui.grid.RowSorter rowSorter} service.
+ */
+ self.sortCellFiltered = colDef.sortCellFiltered ? true : false;
+
+ /**
+ * @ngdoc boolean
+ * @name filterCellFiltered
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
+ * applying "search" `filters`.
+ */
+ self.filterCellFiltered = colDef.filterCellFiltered ? true : false;
+
+ /**
+ * @ngdoc property
+ * @name headerCellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description headerCellFilter is a filter to apply to the content of the column header
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].headerCellFilter = 'translate'
+ *
+ */
+ self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : "";
+
+ /**
+ * @ngdoc property
+ * @name footerCellFilter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description footerCellFilter is a filter to apply to the content of the column footer
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].footerCellFilter = 'date'
+ *
+ */
+ self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : "";
+
+ self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;
+
+ self.headerClass = colDef.headerClass;
+ //self.cursor = self.sortable ? 'pointer' : 'default';
+
+ // Turn on sorting by default
+ self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;
+ self.sortingAlgorithm = colDef.sortingAlgorithm;
+
+ /**
+ * @ngdoc property
+ * @name sortDirectionCycle
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) An array of sort directions, specifying the order that they
+ * should cycle through as the user repeatedly clicks on the column heading.
+ * The default is `[null, uiGridConstants.ASC, uiGridConstants.DESC]`. Null
+ * refers to the unsorted state. This does not affect the initial sort
+ * direction; use the {@link ui.grid.class:GridOptions.columnDef#sort sort}
+ * property for that. If
+ * {@link ui.grid.class:GridOptions.columnDef#suppressRemoveSort suppressRemoveSort}
+ * is also set, the unsorted state will be skipped even if it is listed here.
+ * Each direction may not appear in the list more than once (e.g. `[ASC,
+ * DESC, DESC]` is not allowed), and the list may not be empty.
+ */
+ self.sortDirectionCycle = typeof(colDef.sortDirectionCycle) !== 'undefined' ?
+ colDef.sortDirectionCycle :
+ [null, uiGridConstants.ASC, uiGridConstants.DESC];
+
+ /**
+ * @ngdoc boolean
+ * @name suppressRemoveSort
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description (optional) False by default. When enabled, this setting hides the removeSort option
+ * in the menu, and prevents users from manually removing the sort
+ */
+ if ( typeof(self.suppressRemoveSort) === 'undefined'){
+ self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;
+ }
+
+ /**
+ * @ngdoc property
+ * @name enableFiltering
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description turn off filtering for an individual column, where
+ * you've turned on filtering for the overall grid
+ * @example
+ * <pre>
+ * gridOptions.columnDefs[0].enableFiltering = false;
+ *
+ */
+ // Turn on filtering by default (it's disabled by default at the Grid level)
+ self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;
+
+ // self.menuItems = colDef.menuItems;
+ self.setPropertyOrDefault(colDef, 'menuItems', []);
+
+ // Use the column definition sort if we were passed it, but only if this is a newly added column
+ if ( isNew ){
+ self.setPropertyOrDefault(colDef, 'sort');
+ }
+
+ // Set up default filters array for when one is not provided.
+ // In other words, this (in column def):
+ //
+ // filter: { term: 'something', flags: {}, condition: [CONDITION] }
+ //
+ // is just shorthand for this:
+ //
+ // filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]
+ //
+ var defaultFilters = [];
+ if (colDef.filter) {
+ defaultFilters.push(colDef.filter);
+ }
+ else if ( colDef.filters ){
+ defaultFilters = colDef.filters;
+ } else {
+ // Add an empty filter definition object, which will
+ // translate to a guessed condition and no pre-populated
+ // value for the filter <input>.
+ defaultFilters.push({});
+ }
+
+ /**
+ * @ngdoc property
+ * @name filter
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description Specify a single filter field on this column.
+ *
+ * A filter consists of a condition, a term, and a placeholder:
+ *
+ * - condition defines how rows are chosen as matching the filter term. This can be set to
+ * one of the constants in uiGridConstants.filter, or you can supply a custom filter function
+ * that gets passed the following arguments: [searchTerm, cellValue, row, column].
+ * - term: If set, the filter field will be pre-populated
+ * with this value.
+ * - placeholder: String that will be set to the `<input>.placeholder` attribute.
+ * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.
+ * - noTerm: set this to true if you have defined a custom function in condition, and
+ * your custom function doesn't require a term (so it can run even when the term is null)
+ * - flags: only flag currently available is `caseSensitive`, set to false if you don't want
+ * case sensitive matching
+ * - type: defaults to uiGridConstants.filter.INPUT, which gives a text box. If set to uiGridConstants.filter.SELECT
+ * then a select box will be shown with options selectOptions
+ * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`. No i18n filter is provided, you need
+ * to perform the i18n on the values before you provide them
+ * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter
+ * will not be shown.
+ * @example
+ * <pre>$scope.gridOptions.columnDefs = [
+ * {
+ * field: 'field1',
+ * filter: {
+ * term: 'xx',
+ * condition: uiGridConstants.filter.STARTS_WITH,
+ * placeholder: 'starts with...',
+ * ariaLabel: 'Starts with filter for field1',
+ * flags: { caseSensitive: false },
+ * type: uiGridConstants.filter.SELECT,
+ * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],
+ * disableCancelFilterButton: true
+ * }
+ * }
+ * ]; </pre>
+ *
+ */
+
+ /*
+
+
+ /*
+
+ self.filters = [
+ {
+ term: 'search term'
+ condition: uiGridConstants.filter.CONTAINS,
+ placeholder: 'my placeholder',
+ ariaLabel: 'Starts with filter for field1',
+ flags: {
+ caseSensitive: true
+ }
+ }
+ ]
+
+ */
+
+ // Only set filter if this is a newly added column, if we're updating an existing
+ // column then we don't want to put the default filter back if the user may have already
+ // removed it.
+ // However, we do want to keep the settings if they change, just not the term
+ if ( isNew ) {
+ self.setPropertyOrDefault(colDef, 'filter');
+ self.setPropertyOrDefault(colDef, 'filters', defaultFilters);
+ } else if ( self.filters.length === defaultFilters.length ) {
+ self.filters.forEach( function( filter, index ){
+ if (typeof(defaultFilters[index].placeholder) !== 'undefined') {
+ filter.placeholder = defaultFilters[index].placeholder;
+ }
+ if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {
+ filter.ariaLabel = defaultFilters[index].ariaLabel;
+ }
+ if (typeof(defaultFilters[index].flags) !== 'undefined') {
+ filter.flags = defaultFilters[index].flags;
+ }
+ if (typeof(defaultFilters[index].type) !== 'undefined') {
+ filter.type = defaultFilters[index].type;
+ }
+ if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {
+ filter.selectOptions = defaultFilters[index].selectOptions;
+ }
+ });
+ }
+
+ // Remove this column from the grid sorting, include inside build columns so has
+ // access to self - all seems a bit dodgy but doesn't work otherwise so have left
+ // as is
+ GridColumn.prototype.unsort = function () {
+ this.sort = {};
+ self.grid.api.core.raise.sortChanged( self.grid, self.grid.getColumnSorting() );
+ };
+
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColClass
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the class name for the column
+ * @param {bool} prefixDot if true, will return .className instead of className
+ */
+ GridColumn.prototype.getColClass = function (prefixDot) {
+ var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;
+
+ return prefixDot ? '.' + cls : cls;
+ };
+
+ /**
+ * @ngdoc function
+ * @name isPinnedLeft
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns true if column is in the left render container
+ */
+ GridColumn.prototype.isPinnedLeft = function () {
+ return this.renderContainer === 'left';
+ };
+
+ /**
+ * @ngdoc function
+ * @name isPinnedRight
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns true if column is in the right render container
+ */
+ GridColumn.prototype.isPinnedRight = function () {
+ return this.renderContainer === 'right';
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getColClassDefinition
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the class definition for th column
+ */
+ GridColumn.prototype.getColClassDefinition = function () {
+ return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRenderContainer
+ * @methodOf ui.grid.class:GridColumn
+ * @description Returns the render container object that this column belongs to.
+ *
+ * Columns will be default be in the `body` render container if they aren't allocated to one specifically.
+ */
+ GridColumn.prototype.getRenderContainer = function getRenderContainer() {
+ var self = this;
+
+ var containerId = self.renderContainer;
+
+ if (containerId === null || containerId === '' || containerId === undefined) {
+ containerId = 'body';
+ }
+
+ return self.grid.renderContainers[containerId];
+ };
+
+ /**
+ * @ngdoc function
+ * @name showColumn
+ * @methodOf ui.grid.class:GridColumn
+ * @description Makes the column visible by setting colDef.visible = true
+ */
+ GridColumn.prototype.showColumn = function() {
+ this.colDef.visible = true;
+ };
+
+
+ /**
+ * @ngdoc property
+ * @name aggregationHideLabel
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description defaults to false, if set to true hides the label text
+ * in the aggregation footer, so only the value is displayed.
+ *
+ */
+ /**
+ * @ngdoc function
+ * @name getAggregationText
+ * @methodOf ui.grid.class:GridColumn
+ * @description Gets the aggregation label from colDef.aggregationLabel if
+ * specified or by using i18n, including deciding whether or not to display
+ * based on colDef.aggregationHideLabel.
+ *
+ * @param {string} label the i18n lookup value to use for the column label
+ *
+ */
+ GridColumn.prototype.getAggregationText = function () {
+ var self = this;
+ if ( self.colDef.aggregationHideLabel ){
+ return '';
+ }
+ else if ( self.colDef.aggregationLabel ) {
+ return self.colDef.aggregationLabel;
+ }
+ else {
+ switch ( self.colDef.aggregationType ){
+ case uiGridConstants.aggregationTypes.count:
+ return i18nService.getSafeText('aggregation.count');
+ case uiGridConstants.aggregationTypes.sum:
+ return i18nService.getSafeText('aggregation.sum');
+ case uiGridConstants.aggregationTypes.avg:
+ return i18nService.getSafeText('aggregation.avg');
+ case uiGridConstants.aggregationTypes.min:
+ return i18nService.getSafeText('aggregation.min');
+ case uiGridConstants.aggregationTypes.max:
+ return i18nService.getSafeText('aggregation.max');
+ default:
+ return '';
+ }
+ }
+ };
+
+ GridColumn.prototype.getCellTemplate = function () {
+ var self = this;
+
+ return self.cellTemplatePromise;
+ };
+
+ GridColumn.prototype.getCompiledElementFn = function () {
+ var self = this;
+
+ return self.compiledElementFnDefer.promise;
+ };
+
+ return GridColumn;
+}]);
+
+})();
+
+ (function(){
+
+angular.module('ui.grid')
+.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridOptions
+ * @description Default GridOptions class. GridOptions are defined by the application developer and overlaid
+ * over this object. Setting gridOptions within your controller is the most common method for an application
+ * developer to configure the behaviour of their ui-grid
+ *
+ * @example To define your gridOptions within your controller:
+ * <pre>$scope.gridOptions = {
+ * data: $scope.myData,
+ * columnDefs: [
+ * { name: 'field1', displayName: 'pretty display name' },
+ * { name: 'field2', visible: false }
+ * ]
+ * };</pre>
+ *
+ * You can then use this within your html template, when you define your grid:
+ * <pre>&lt;div ui-grid="gridOptions"&gt;&lt;/div&gt;</pre>
+ *
+ * To provide default options for all of the grids within your application, use an angular
+ * decorator to modify the GridOptions factory.
+ * <pre>
+ * app.config(function($provide){
+ * $provide.decorator('GridOptions',function($delegate){
+ * var gridOptions;
+ * gridOptions = angular.copy($delegate);
+ * gridOptions.initialize = function(options) {
+ * var initOptions;
+ * initOptions = $delegate.initialize(options);
+ * initOptions.enableColumnMenus = false;
+ * return initOptions;
+ * };
+ * return gridOptions;
+ * });
+ * });
+ * </pre>
+ */
+ return {
+ initialize: function( baseOptions ){
+ /**
+ * @ngdoc function
+ * @name onRegisterApi
+ * @propertyOf ui.grid.class:GridOptions
+ * @description A callback that returns the gridApi once the grid is instantiated, which is
+ * then used to interact with the grid programatically.
+ *
+ * Note that the gridApi.core.renderingComplete event is identical to this
+ * callback, but has the advantage that it can be called from multiple places
+ * if needed
+ *
+ * @example
+ * <pre>
+ * $scope.gridOptions.onRegisterApi = function ( gridApi ) {
+ * $scope.gridApi = gridApi;
+ * $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );
+ * };
+ * </pre>
+ *
+ */
+ baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();
+
+ /**
+ * @ngdoc object
+ * @name data
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for
+ * the grid.
+ *
+ * Most commonly the data is an array of objects, where each object has a number of attributes.
+ * Each attribute automatically becomes a column in your grid. This array could, for example, be sourced from
+ * an angularJS $resource query request. The array can also contain complex objects, refer the binding tutorial
+ * for examples of that.
+ *
+ * The most flexible usage is to set your data on $scope:
+ *
+ * `$scope.data = data;`
+ *
+ * And then direct the grid to resolve whatever is in $scope.data:
+ *
+ * `$scope.gridOptions.data = 'data';`
+ *
+ * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without
+ * getting pointer issues.
+ *
+ * Alternatively you can directly set the data array:
+ *
+ * `$scope.gridOptions.data = [ ];`
+ * or
+ *
+ * `$http.get('/data/100.json')
+ * .success(function(data) {
+ * $scope.myData = data;
+ * $scope.gridOptions.data = $scope.myData;
+ * });`
+ *
+ * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other
+ * array, you need to update $scope.gridOptions.data to point to that new array as well.
+ *
+ */
+ baseOptions.data = baseOptions.data || [];
+
+ /**
+ * @ngdoc array
+ * @name columnDefs
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Array of columnDef objects. Only required property is name.
+ * The individual options available in columnDefs are documented in the
+ * {@link ui.grid.class:GridOptions.columnDef columnDef} section
+ * </br>_field property can be used in place of name for backwards compatibility with 2.x_
+ * @example
+ *
+ * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>
+ *
+ */
+ baseOptions.columnDefs = baseOptions.columnDefs || [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridOptions.columnDef
+ * @description Definition / configuration of an individual column, which would typically be
+ * one of many column definitions within the gridOptions.columnDefs array
+ * @example
+ * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>
+ *
+ */
+
+
+ /**
+ * @ngdoc array
+ * @name excludeProperties
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Array of property names in data to ignore when auto-generating column names. Provides the
+ * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns
+ * to exclude.
+ *
+ * If columnDefs is defined, this will be ignored.
+ *
+ * Defaults to ['$$hashKey']
+ */
+
+ baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];
+
+ /**
+ * @ngdoc boolean
+ * @name enableRowHashing
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting allows uiGrid to add
+ * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows
+ * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.
+ *
+ * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF
+ * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows
+ * and are altering the data set often.
+ */
+ baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;
+
+ /**
+ * @ngdoc function
+ * @name rowIdentity
+ * @methodOf ui.grid.class:GridOptions
+ * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).
+ *
+ * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one
+ */
+ baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {
+ return gridUtil.hashKey(row);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getRowIdentity
+ * @methodOf ui.grid.class:GridOptions
+ * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.
+ *
+ * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.
+ */
+ baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {
+ return row.$$hashKey;
+ };
+
+ /**
+ * @ngdoc property
+ * @name flatEntityAccess
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.
+ * each of your columns associate directly with a property on each of the entities in your data array.
+ *
+ * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,
+ * which can provide a significant speed improvement with large data sets when filtering or sorting.
+ *
+ * By default false
+ */
+ baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;
+
+ /**
+ * @ngdoc property
+ * @name showHeader
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When set to false, this setting will replace the
+ * standard header template with '<div></div>', resulting in no header being shown.
+ */
+ baseOptions.showHeader = typeof(baseOptions.showHeader) !== "undefined" ? baseOptions.showHeader : true;
+
+ /* (NOTE): Don't show this in the docs. We only use it internally
+ * @ngdoc property
+ * @name headerRowHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the header in pixels, defaults to 30
+ *
+ */
+ if (!baseOptions.showHeader) {
+ baseOptions.headerRowHeight = 0;
+ }
+ else {
+ baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== "undefined" ? baseOptions.headerRowHeight : 30;
+ }
+
+ /**
+ * @ngdoc property
+ * @name rowHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the row in pixels, defaults to 30
+ *
+ */
+ baseOptions.rowHeight = baseOptions.rowHeight || 30;
+
+ /**
+ * @ngdoc integer
+ * @name minRowsToShow
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to "10".
+ */
+ baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== "undefined" ? baseOptions.minRowsToShow : 10;
+
+ /**
+ * @ngdoc property
+ * @name showGridFooter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether or not to show the footer, defaults to false
+ * The footer display Total Rows and Visible Rows (filtered rows)
+ */
+ baseOptions.showGridFooter = baseOptions.showGridFooter === true;
+
+ /**
+ * @ngdoc property
+ * @name showColumnFooter
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether or not to show the column footer, defaults to false
+ * The column footer displays column aggregates
+ */
+ baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;
+
+ /**
+ * @ngdoc property
+ * @name columnFooterHeight
+ * @propertyOf ui.grid.class:GridOptions
+ * @description The height of the footer rows (column footer and grid footer) in pixels
+ *
+ */
+ baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== "undefined" ? baseOptions.columnFooterHeight : 30;
+ baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== "undefined" ? baseOptions.gridFooterHeight : 30;
+
+ baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== "undefined" ? baseOptions.columnWidth : 50;
+
+ /**
+ * @ngdoc property
+ * @name maxVisibleColumnCount
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 200
+ *
+ */
+ baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== "undefined" ? baseOptions.maxVisibleColumnCount : 200;
+
+ /**
+ * @ngdoc property
+ * @name virtualizationThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Turn virtualization on when number of data elements goes over this number, defaults to 20
+ */
+ baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== "undefined" ? baseOptions.virtualizationThreshold : 20;
+
+ /**
+ * @ngdoc property
+ * @name columnVirtualizationThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Turn virtualization on when number of columns goes over this number, defaults to 10
+ */
+ baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== "undefined" ? baseOptions.columnVirtualizationThreshold : 10;
+
+ /**
+ * @ngdoc property
+ * @name excessRows
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.
+ * Defaults to 4
+ */
+ baseOptions.excessRows = typeof(baseOptions.excessRows) !== "undefined" ? baseOptions.excessRows : 4;
+ /**
+ * @ngdoc property
+ * @name scrollThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 4
+ */
+ baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== "undefined" ? baseOptions.scrollThreshold : 4;
+
+ /**
+ * @ngdoc property
+ * @name excessColumns
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.
+ * Defaults to 4
+ */
+ baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== "undefined" ? baseOptions.excessColumns : 4;
+ /**
+ * @ngdoc property
+ * @name horizontalScrollThreshold
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Defaults to 4
+ */
+ baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== "undefined" ? baseOptions.horizontalScrollThreshold : 2;
+
+
+ /**
+ * @ngdoc property
+ * @name aggregationCalcThrottle
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms
+ */
+ baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== "undefined" ? baseOptions.aggregationCalcThrottle : 500;
+
+ /**
+ * @ngdoc property
+ * @name wheelScrollThrottle
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms
+ */
+ baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== "undefined" ? baseOptions.wheelScrollThrottle : 70;
+
+
+ /**
+ * @ngdoc property
+ * @name scrollDebounce
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Default time in milliseconds to debounce scroll events, defaults to 300ms
+ */
+ baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== "undefined" ? baseOptions.scrollDebounce : 300;
+
+ /**
+ * @ngdoc boolean
+ * @name enableSorting
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting adds sort
+ * widgets to the column headers, allowing sorting of the data for the entire grid.
+ * Sorting can then be disabled on individual columns using the columnDefs.
+ */
+ baseOptions.enableSorting = baseOptions.enableSorting !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name enableFiltering
+ * @propertyOf ui.grid.class:GridOptions
+ * @description False by default. When enabled, this setting adds filter
+ * boxes to each column header, allowing filtering within the column for the entire grid.
+ * Filtering can then be disabled on individual columns using the columnDefs.
+ */
+ baseOptions.enableFiltering = baseOptions.enableFiltering === true;
+
+ /**
+ * @ngdoc boolean
+ * @name enableColumnMenus
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, this setting displays a column
+ * menu within each column.
+ */
+ baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name enableVerticalScrollbar
+ * @propertyOf ui.grid.class:GridOptions
+ * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the vertical scrollbar for the grid.
+ * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
+ */
+ baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== "undefined" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;
+
+ /**
+ * @ngdoc boolean
+ * @name enableHorizontalScrollbar
+ * @propertyOf ui.grid.class:GridOptions
+ * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the horizontal scrollbar for the grid.
+ * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
+ */
+ baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== "undefined" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;
+
+ /**
+ * @ngdoc boolean
+ * @name enableMinHeightCheck
+ * @propertyOf ui.grid.class:GridOptions
+ * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display
+ * at least one row of data. If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number
+ * of rows.
+ */
+ baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;
+
+ /**
+ * @ngdoc boolean
+ * @name minimumColumnSize
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Columns can't be smaller than this, defaults to 10 pixels
+ */
+ baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== "undefined" ? baseOptions.minimumColumnSize : 10;
+
+ /**
+ * @ngdoc function
+ * @name rowEquality
+ * @methodOf ui.grid.class:GridOptions
+ * @description By default, rows are compared using object equality. This option can be overridden
+ * to compare on any data item property or function
+ * @param {object} entityA First Data Item to compare
+ * @param {object} entityB Second Data Item to compare
+ */
+ baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {
+ return entityA === entityB;
+ };
+
+ /**
+ * @ngdoc string
+ * @name headerTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Null by default. When provided, this setting uses a custom header
+ * template, rather than the default template. Can be set to either the name of a template file:
+ * <pre> $scope.gridOptions.headerTemplate = 'header_template.html';</pre>
+ * inline html
+ * <pre> $scope.gridOptions.headerTemplate = '<div class="ui-grid-top-panel" style="text-align: center">I am a Custom Grid Header</div>'</pre>
+ * or the id of a precompiled template (TBD how to use this).
+ * </br>Refer to the custom header tutorial for more information.
+ * If you want no header at all, you can set to an empty div:
+ * <pre> $scope.gridOptions.headerTemplate = '<div></div>';</pre>
+ *
+ * If you want to only have a static header, then you can set to static content. If
+ * you want to tailor the existing column headers, then you should look at the
+ * current 'ui-grid-header.html' template in github as your starting point.
+ *
+ */
+ baseOptions.headerTemplate = baseOptions.headerTemplate || null;
+
+ /**
+ * @ngdoc string
+ * @name footerTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) ui-grid/ui-grid-footer by default. This footer shows the per-column
+ * aggregation totals.
+ * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html
+ * <pre>'<div class="ui-grid-bottom-panel" style="text-align: center">I am a Custom Grid Footer</div>'</pre>, or the id
+ * of a precompiled template (TBD how to use this). Refer to the custom footer tutorial for more information.
+ */
+ baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';
+
+ /**
+ * @ngdoc string
+ * @name gridFooterTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the
+ * total items at the bottom of the grid, and the selected items if selection is enabled.
+ */
+ baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';
+
+ /**
+ * @ngdoc string
+ * @name rowTemplate
+ * @propertyOf ui.grid.class:GridOptions
+ * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a
+ * custom row template. Can be set to either the name of a template file:
+ * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>
+ * inline html
+ * <pre> $scope.gridOptions.rowTemplate = '<div style="background-color: aquamarine" ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ui-grid-cell></div>';</pre>
+ * or the id of a precompiled template (TBD how to use this) can be provided.
+ * </br>Refer to the custom row template tutorial for more information.
+ */
+ baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';
+
+ /**
+ * @ngdoc object
+ * @name appScopeProvider
+ * @propertyOf ui.grid.class:GridOptions
+ * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope
+ * this property allows you to assign any reference you want to grid.appScope
+ */
+ baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;
+
+ return baseOptions;
+ }
+ };
+
+
+}]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridRenderContainer
+ * @description The grid has render containers, allowing the ability to have pinned columns. If the grid
+ * is right-to-left then there may be a right render container, if left-to-right then there may
+ * be a left render container. There is always a body render container.
+ * @param {string} name The name of the render container ('body', 'left', or 'right')
+ * @param {Grid} grid the grid the render container is in
+ * @param {object} options the render container options
+ */
+.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
+ function GridRenderContainer(name, grid, options) {
+ var self = this;
+
+ // if (gridUtil.type(grid) !== 'Grid') {
+ // throw new Error('Grid argument is not a Grid object');
+ // }
+
+ self.name = name;
+
+ self.grid = grid;
+
+ // self.rowCache = [];
+ // self.columnCache = [];
+
+ self.visibleRowCache = [];
+ self.visibleColumnCache = [];
+
+ self.renderedRows = [];
+ self.renderedColumns = [];
+
+ self.prevScrollTop = 0;
+ self.prevScrolltopPercentage = 0;
+ self.prevRowScrollIndex = 0;
+
+ self.prevScrollLeft = 0;
+ self.prevScrollleftPercentage = 0;
+ self.prevColumnScrollIndex = 0;
+
+ self.columnStyles = "";
+
+ self.viewportAdjusters = [];
+
+ /**
+ * @ngdoc boolean
+ * @name hasHScrollbar
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container has a horizontal scrollbar
+ */
+ self.hasHScrollbar = false;
+
+ /**
+ * @ngdoc boolean
+ * @name hasVScrollbar
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container has a vertical scrollbar
+ */
+ self.hasVScrollbar = false;
+
+ /**
+ * @ngdoc boolean
+ * @name canvasHeightShouldUpdate
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description flag to signal that container should recalculate the canvas size
+ */
+ self.canvasHeightShouldUpdate = true;
+
+ /**
+ * @ngdoc boolean
+ * @name canvasHeight
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description last calculated canvas height value
+ */
+ self.$$canvasHeight = 0;
+
+ if (options && angular.isObject(options)) {
+ angular.extend(self, options);
+ }
+
+ grid.registerStyleComputation({
+ priority: 5,
+ func: function () {
+ self.updateColumnWidths();
+ return self.columnStyles;
+ }
+ });
+ }
+
+
+ GridRenderContainer.prototype.reset = function reset() {
+ // this.rowCache.length = 0;
+ // this.columnCache.length = 0;
+
+ this.visibleColumnCache.length = 0;
+ this.visibleRowCache.length = 0;
+
+ this.renderedRows.length = 0;
+ this.renderedColumns.length = 0;
+ };
+
+ // TODO(c0bra): calculate size?? Should this be in a stackable directive?
+
+
+ GridRenderContainer.prototype.containsColumn = function (col) {
+ return this.visibleColumnCache.indexOf(col) !== -1;
+ };
+
+ GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {
+ var self = this;
+ var minRows = 0;
+ var rowAddedHeight = 0;
+ var viewPortHeight = self.getViewportHeight();
+ for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {
+ rowAddedHeight += self.visibleRowCache[i].height;
+ minRows++;
+ }
+ return minRows;
+ };
+
+ GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {
+ var self = this;
+ var viewportWidth = this.getViewportWidth();
+
+ var min = 0;
+ var totalWidth = 0;
+ // self.columns.forEach(function(col, i) {
+ for (var i = 0; i < self.visibleColumnCache.length; i++) {
+ var col = self.visibleColumnCache[i];
+
+ if (totalWidth < viewportWidth) {
+ totalWidth += col.drawnWidth ? col.drawnWidth : 0;
+ min++;
+ }
+ else {
+ var currWidth = 0;
+ for (var j = i; j >= i - min; j--) {
+ currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;
+ }
+ if (currWidth < viewportWidth) {
+ min++;
+ }
+ }
+ }
+
+ return min;
+ };
+
+ GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {
+ return this.visibleRowCache.length;
+ };
+
+ /**
+ * @ngdoc function
+ * @name registerViewportAdjuster
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Registers an adjuster to the render container's available width or height. Adjusters are used
+ * to tell the render container that there is something else consuming space, and to adjust it's size
+ * appropriately.
+ * @param {function} func the adjuster function we want to register
+ */
+
+ GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
+ this.viewportAdjusters.push(func);
+ };
+
+ /**
+ * @ngdoc function
+ * @name removeViewportAdjuster
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Removes an adjuster, should be used when your element is destroyed
+ * @param {function} func the adjuster function we want to remove
+ */
+ GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {
+ var idx = this.viewportAdjusters.indexOf(func);
+
+ if (idx > -1) {
+ this.viewportAdjusters.splice(idx, 1);
+ }
+ };
+
+ /**
+ * @ngdoc function
+ * @name getViewportAdjustment
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Gets the adjustment based on the viewportAdjusters.
+ * @returns {object} a hash of { height: x, width: y }. Usually the values will be negative
+ */
+ GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {
+ var self = this;
+
+ var adjustment = { height: 0, width: 0 };
+
+ self.viewportAdjusters.forEach(function (func) {
+ adjustment = func.call(this, adjustment);
+ });
+
+ return adjustment;
+ };
+
+ GridRenderContainer.prototype.getMargin = function getMargin(side) {
+ var self = this;
+
+ var amount = 0;
+
+ self.viewportAdjusters.forEach(function (func) {
+ var adjustment = func.call(this, { height: 0, width: 0 });
+
+ if (adjustment.side && adjustment.side === side) {
+ amount += adjustment.width * -1;
+ }
+ });
+
+ return amount;
+ };
+
+ GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {
+ var self = this;
+
+ var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;
+
+ var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;
+
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewPortHeight = viewPortHeight + adjustment.height;
+
+ return viewPortHeight;
+ };
+
+ GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {
+ var self = this;
+
+ var viewportWidth = self.grid.gridWidth;
+
+ //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;
+ //}
+
+ // var viewportWidth = 0;\
+ // self.visibleColumnCache.forEach(function (column) {
+ // viewportWidth += column.drawnWidth;
+ // });
+
+ var adjustment = self.getViewportAdjustment();
+
+ viewportWidth = viewportWidth + adjustment.width;
+
+ return viewportWidth;
+ };
+
+ GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
+ var self = this;
+
+ var viewportWidth = this.getViewportWidth();
+
+ //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
+ // viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;
+ //}
+
+ // var adjustment = self.getViewportAdjustment();
+ // viewPortWidth = viewPortWidth + adjustment.width;
+
+ return viewportWidth;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getCanvasHeight
+ * @methodOf ui.grid.class:GridRenderContainer
+ * @description Returns the total canvas height. Only recalculates if canvasHeightShouldUpdate = false
+ * @returns {number} total height of all the visible rows in the container
+ */
+ GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {
+ var self = this;
+
+ if (!self.canvasHeightShouldUpdate) {
+ return self.$$canvasHeight;
+ }
+
+ var oldCanvasHeight = self.$$canvasHeight;
+
+ self.$$canvasHeight = 0;
+
+ self.visibleRowCache.forEach(function(row){
+ self.$$canvasHeight += row.height;
+ });
+
+
+ self.canvasHeightShouldUpdate = false;
+
+ self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);
+
+ return self.$$canvasHeight;
+ };
+
+ GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {
+ return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight;
+ };
+
+ GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {
+ var self = this;
+
+ var ret = self.canvasWidth;
+
+ return ret;
+ };
+
+ GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {
+ this.renderedRows.length = newRows.length;
+ for (var i = 0; i < newRows.length; i++) {
+ this.renderedRows[i] = newRows[i];
+ }
+ };
+
+ GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {
+ var self = this;
+
+ // OLD:
+ this.renderedColumns.length = newColumns.length;
+ for (var i = 0; i < newColumns.length; i++) {
+ this.renderedColumns[i] = newColumns[i];
+ }
+
+ this.updateColumnOffset();
+ };
+
+ GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {
+ // Calculate the width of the columns on the left side that are no longer rendered.
+ // That will be the offset for the columns as we scroll horizontally.
+ var hiddenColumnsWidth = 0;
+ for (var i = 0; i < this.currentFirstColumn; i++) {
+ hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;
+ }
+
+ this.columnOffset = hiddenColumnsWidth;
+ };
+
+ GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {
+ var vertScrollPercentage = -1;
+
+ if (newScrollTop !== this.prevScrollTop) {
+ var yDiff = newScrollTop - this.prevScrollTop;
+
+ if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }
+ if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }
+
+ var vertScrollLength = this.getVerticalScrollLength();
+
+ vertScrollPercentage = newScrollTop / vertScrollLength;
+
+ // console.log('vert', vertScrollPercentage, newScrollTop, vertScrollLength);
+
+ if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }
+ if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }
+
+ this.adjustScrollVertical(newScrollTop, vertScrollPercentage);
+ return vertScrollPercentage;
+ }
+ };
+
+ GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft){
+ var horizScrollPercentage = -1;
+
+ // Handle RTL here
+
+ if (newScrollLeft !== this.prevScrollLeft) {
+ var xDiff = newScrollLeft - this.prevScrollLeft;
+
+ if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }
+ if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }
+
+ var horizScrollLength = (this.canvasWidth - this.getViewportWidth());
+ if (horizScrollLength !== 0) {
+ horizScrollPercentage = newScrollLeft / horizScrollLength;
+ }
+ else {
+ horizScrollPercentage = 0;
+ }
+
+ this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);
+ return horizScrollPercentage;
+ }
+ };
+
+ GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {
+ if (this.prevScrollTop === scrollTop && !force) {
+ return;
+ }
+
+ if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {
+ scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;
+ }
+
+ this.adjustRows(scrollTop, scrollPercentage, false);
+
+ this.prevScrollTop = scrollTop;
+ this.prevScrolltopPercentage = scrollPercentage;
+
+ this.grid.queueRefresh();
+ };
+
+ GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {
+ if (this.prevScrollLeft === scrollLeft && !force) {
+ return;
+ }
+
+ if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {
+ scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;
+ }
+
+ this.adjustColumns(scrollLeft, scrollPercentage);
+
+ this.prevScrollLeft = scrollLeft;
+ this.prevScrollleftPercentage = scrollPercentage;
+
+ this.grid.queueRefresh();
+ };
+
+ GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {
+ var self = this;
+
+ var minRows = self.minRowsToRender();
+
+ var rowCache = self.visibleRowCache;
+
+ var maxRowIndex = rowCache.length - minRows;
+
+ // console.log('scroll%1', scrollPercentage);
+
+ // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided
+ if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {
+ scrollPercentage = scrollTop / self.getVerticalScrollLength();
+ }
+
+ var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));
+
+ // console.log('maxRowIndex / scroll%', maxRowIndex, scrollPercentage, rowIndex);
+
+ // Define a max row index that we can't scroll past
+ if (rowIndex > maxRowIndex) {
+ rowIndex = maxRowIndex;
+ }
+
+ var newRange = [];
+ if (rowCache.length > self.grid.options.virtualizationThreshold) {
+ if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {
+ // Have we hit the threshold going down?
+ if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
+ return;
+ }
+ //Have we hit the threshold going up?
+ if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
+ return;
+ }
+ }
+ var rangeStart = {};
+ var rangeEnd = {};
+
+ rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);
+ rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);
+
+ newRange = [rangeStart, rangeEnd];
+ }
+ else {
+ var maxLen = self.visibleRowCache.length;
+ newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];
+ }
+
+ self.updateViewableRowRange(newRange);
+
+ self.prevRowScrollIndex = rowIndex;
+ };
+
+ GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {
+ var self = this;
+
+ var minCols = self.minColumnsToRender();
+
+ var columnCache = self.visibleColumnCache;
+ var maxColumnIndex = columnCache.length - minCols;
+
+ // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided
+ if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {
+ var horizScrollLength = (self.getCanvasWidth() - self.getViewportWidth());
+ scrollPercentage = scrollLeft / horizScrollLength;
+ }
+
+ var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));
+
+ // Define a max row index that we can't scroll past
+ if (colIndex > maxColumnIndex) {
+ colIndex = maxColumnIndex;
+ }
+
+ var newRange = [];
+ if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {
+ /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position
+ * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it
+ // Have we hit the threshold going down?
+ if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
+ return;
+ }
+ //Have we hit the threshold going up?
+ if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
+ return;
+ }*/
+
+ var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);
+ var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);
+
+ newRange = [rangeStart, rangeEnd];
+ }
+ else {
+ var maxLen = self.visibleColumnCache.length;
+
+ newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];
+ }
+
+ self.updateViewableColumnRange(newRange);
+
+ self.prevColumnScrollIndex = colIndex;
+ };
+
+ // Method for updating the visible rows
+ GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {
+ // Slice out the range of rows from the data
+ // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);
+ var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);
+
+ // Define the top-most rendered row
+ this.currentTopRow = renderedRange[0];
+
+ this.setRenderedRows(rowArr);
+ };
+
+ // Method for updating the visible columns
+ GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {
+ // Slice out the range of rows from the data
+ // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);
+ var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);
+
+ // Define the left-most rendered columns
+ this.currentFirstColumn = renderedRange[0];
+
+ this.setRenderedColumns(columnArr);
+ };
+
+ GridRenderContainer.prototype.headerCellWrapperStyle = function () {
+ var self = this;
+
+ if (self.currentFirstColumn !== 0) {
+ var offset = self.columnOffset;
+
+ if (self.grid.isRTL()) {
+ return { 'margin-right': offset + 'px' };
+ }
+ else {
+ return { 'margin-left': offset + 'px' };
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * @ngdoc boolean
+ * @name updateColumnWidths
+ * @propertyOf ui.grid.class:GridRenderContainer
+ * @description Determine the appropriate column width of each column across all render containers.
+ *
+ * Column width is easy when each column has a specified width. When columns are variable width (i.e.
+ * have an * or % of the viewport) then we try to calculate so that things fit in. The problem is that
+ * we have multiple render containers, and we don't want one render container to just take the whole viewport
+ * when it doesn't need to - we want things to balance out across the render containers.
+ *
+ * To do this, we use this method to calculate all the renderContainers, recognising that in a given render
+ * cycle it'll get called once per render container, so it needs to return the same values each time.
+ *
+ * The constraints on this method are therefore:
+ * - must return the same value when called multiple times, to do this it needs to rely on properties of the
+ * columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)
+ *
+ * The general logic of this method is:
+ * - calculate our total available width
+ * - look at all the columns across all render containers, and work out which have widths and which have
+ * constraints such as % or * or something else
+ * - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array
+ * - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max
+ * - for those with manual width (in pixels) we set the drawnWidth to the specified width
+ * - we end up with an asterisks array still to process
+ * - we look at our remaining width. If it's greater than zero, we divide it up among the asterisk columns, then process
+ * them for min and max width constraints
+ * - if it's zero or less, we set the asterisk columns to their minimum widths
+ * - we use parseInt quite a bit, as we try to make all our column widths integers
+ */
+ GridRenderContainer.prototype.updateColumnWidths = function () {
+ var self = this;
+
+ var asterisksArray = [],
+ asteriskNum = 0,
+ usedWidthSum = 0,
+ ret = '';
+
+ // Get the width of the viewport
+ var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;
+
+ // get all the columns across all render containers, we have to calculate them all or one render container
+ // could consume the whole viewport
+ var columnCache = [];
+ angular.forEach(self.grid.renderContainers, function( container, name){
+ columnCache = columnCache.concat(container.visibleColumnCache);
+ });
+
+ // look at each column, process any manual values or %, put the * into an array to look at later
+ columnCache.forEach(function(column, i) {
+ var width = 0;
+ // Skip hidden columns
+ if (!column.visible) { return; }
+
+ if (angular.isNumber(column.width)) {
+ // pixel width, set to this value
+ width = parseInt(column.width, 10);
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+
+ } else if (gridUtil.endsWith(column.width, "%")) {
+ // percentage width, set to percentage of the viewport
+ width = parseInt(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);
+
+ if ( width > column.maxWidth ){
+ width = column.maxWidth;
+ }
+
+ if ( width < column.minWidth ){
+ width = column.minWidth;
+ }
+
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+ } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {
+ // is an asterisk column, the gridColumn already checked the string consists only of '****'
+ asteriskNum = asteriskNum + column.width.length;
+ asterisksArray.push(column);
+ }
+ });
+
+ // Get the remaining width (available width subtracted by the used widths sum)
+ var remainingWidth = availableWidth - usedWidthSum;
+
+ var i, column, colWidth;
+
+ if (asterisksArray.length > 0) {
+ // the width that each asterisk value would be assigned (this can be negative)
+ var asteriskVal = remainingWidth / asteriskNum;
+
+ asterisksArray.forEach(function( column ){
+ var width = parseInt(column.width.length * asteriskVal, 10);
+
+ if ( width > column.maxWidth ){
+ width = column.maxWidth;
+ }
+
+ if ( width < column.minWidth ){
+ width = column.minWidth;
+ }
+
+ usedWidthSum = usedWidthSum + width;
+ column.drawnWidth = width;
+ });
+ }
+
+ // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
+ // calculated widths would have the grid narrower than the available space,
+ // dole the remainder out one by one to make everything fit
+ var processColumnUpwards = function(column){
+ if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
+ column.drawnWidth++;
+ usedWidthSum++;
+ leftoverWidth--;
+ columnsToChange = true;
+ }
+ };
+
+ var leftoverWidth = availableWidth - usedWidthSum;
+ var columnsToChange = true;
+
+ while (leftoverWidth > 0 && columnsToChange) {
+ columnsToChange = false;
+ asterisksArray.forEach(processColumnUpwards);
+ }
+
+ // We can end up with too much width even though some columns aren't at their max width, in this situation
+ // we can trim the columns a little
+ var processColumnDownwards = function(column){
+ if ( column.drawnWidth > column.minWidth && excessWidth > 0) {
+ column.drawnWidth--;
+ usedWidthSum--;
+ excessWidth--;
+ columnsToChange = true;
+ }
+ };
+
+ var excessWidth = usedWidthSum - availableWidth;
+ columnsToChange = true;
+
+ while (excessWidth > 0 && columnsToChange) {
+ columnsToChange = false;
+ asterisksArray.forEach(processColumnDownwards);
+ }
+
+
+ // all that was across all the renderContainers, now we need to work out what that calculation decided for
+ // our renderContainer
+ var canvasWidth = 0;
+ self.visibleColumnCache.forEach(function(column){
+ if ( column.visible ){
+ canvasWidth = canvasWidth + column.drawnWidth;
+ }
+ });
+
+ // Build the CSS
+ columnCache.forEach(function (column) {
+ ret = ret + column.getColClassDefinition();
+ });
+
+ self.canvasWidth = canvasWidth;
+
+ // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
+ // return ret;
+
+ // Set this render container's column styles so they can be used in style computation
+ this.columnStyles = ret;
+ };
+
+ GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {
+ return this.grid.options.enableHorizontalScrollbar && !this.hasHScrollbar && !this.grid.disableScrolling;
+ };
+
+ GridRenderContainer.prototype.getViewportStyle = function () {
+ var self = this;
+ var styles = {};
+
+ self.hasHScrollbar = false;
+ self.hasVScrollbar = false;
+
+ if (self.grid.disableScrolling) {
+ styles['overflow-x'] = 'hidden';
+ styles['overflow-y'] = 'hidden';
+ return styles;
+ }
+
+ if (self.name === 'body') {
+ self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ if (!self.grid.isRTL()) {
+ if (!self.grid.hasRightContainerColumns()) {
+ self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ }
+ }
+ else {
+ if (!self.grid.hasLeftContainerColumns()) {
+ self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
+ }
+ }
+ }
+ else if (self.name === 'left') {
+ self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
+ }
+ else {
+ self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
+ }
+
+ styles['overflow-x'] = self.hasHScrollbar ? 'scroll' : 'hidden';
+ styles['overflow-y'] = self.hasVScrollbar ? 'scroll' : 'hidden';
+
+
+ return styles;
+
+
+ };
+
+ return GridRenderContainer;
+}]);
+
+})();
+
+(function(){
+
+angular.module('ui.grid')
+.factory('GridRow', ['gridUtil', function(gridUtil) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:GridRow
+ * @description GridRow is the viewModel for one logical row on the grid. A grid Row is not necessarily a one-to-one
+ * relation to gridOptions.data.
+ * @param {object} entity the array item from GridOptions.data
+ * @param {number} index the current position of the row in the array
+ * @param {Grid} reference to the parent grid
+ */
+ function GridRow(entity, index, grid) {
+
+ /**
+ * @ngdoc object
+ * @name grid
+ * @propertyOf ui.grid.class:GridRow
+ * @description A reference back to the grid
+ */
+ this.grid = grid;
+
+ /**
+ * @ngdoc object
+ * @name entity
+ * @propertyOf ui.grid.class:GridRow
+ * @description A reference to an item in gridOptions.data[]
+ */
+ this.entity = entity;
+
+ /**
+ * @ngdoc object
+ * @name uid
+ * @propertyOf ui.grid.class:GridRow
+ * @description UniqueId of row
+ */
+ this.uid = gridUtil.nextUid();
+
+ /**
+ * @ngdoc object
+ * @name visible
+ * @propertyOf ui.grid.class:GridRow
+ * @description If true, the row will be rendered
+ */
+ // Default to true
+ this.visible = true;
+
+
+ this.$$height = grid.options.rowHeight;
+
+ }
+
+ /**
+ * @ngdoc object
+ * @name height
+ * @propertyOf ui.grid.class:GridRow
+ * @description height of each individual row. changing the height will flag all
+ * row renderContainers to recalculate their canvas height
+ */
+ Object.defineProperty(GridRow.prototype, 'height', {
+ get: function() {
+ return this.$$height;
+ },
+ set: function(height) {
+ if (height !== this.$$height) {
+ this.grid.updateCanvasHeight();
+ this.$$height = height;
+ }
+ }
+ });
+
+ /**
+ * @ngdoc function
+ * @name getQualifiedColField
+ * @methodOf ui.grid.class:GridRow
+ * @description returns the qualified field name as it exists on scope
+ * ie: row.entity.fieldA
+ * @param {GridCol} col column instance
+ * @returns {string} resulting name that can be evaluated on scope
+ */
+ GridRow.prototype.getQualifiedColField = function(col) {
+ return 'row.' + this.getEntityQualifiedColField(col);
+ };
+
+ /**
+ * @ngdoc function
+ * @name getEntityQualifiedColField
+ * @methodOf ui.grid.class:GridRow
+ * @description returns the qualified field name minus the row path
+ * ie: entity.fieldA
+ * @param {GridCol} col column instance
+ * @returns {string} resulting name that can be evaluated against a row
+ */
+ GridRow.prototype.getEntityQualifiedColField = function(col) {
+ return gridUtil.preEval('entity.' + col.field);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Sets an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
+ *
+ * This method can be called from the api, passing in the gridRow we want
+ * altered. It should really work by calling gridRow.setRowInvisible, but that's
+ * not the way I coded it, and too late to change now. Changed to just call
+ * the internal function row.setThisRowInvisible().
+ *
+ * @param {GridRow} row the row we want to set to invisible
+ *
+ */
+ GridRow.prototype.setRowInvisible = function ( row ) {
+ if (row && row.setThisRowInvisible){
+ row.setThisRowInvisible( 'user' );
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Clears an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
+ *
+ * This method can be called from the api, passing in the gridRow we want
+ * altered. It should really work by calling gridRow.clearRowInvisible, but that's
+ * not the way I coded it, and too late to change now. Changed to just call
+ * the internal function row.clearThisRowInvisible().
+ *
+ * @param {GridRow} row the row we want to clear the invisible flag
+ *
+ */
+ GridRow.prototype.clearRowInvisible = function ( row ) {
+ if (row && row.clearThisRowInvisible){
+ row.clearThisRowInvisible( 'user' );
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setThisRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Sets an override on the row that forces it to always
+ * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility
+ *
+ * @param {string} reason the reason (usually the module) for the row to be invisible.
+ * E.g. grouping, user, filter
+ * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
+ */
+ GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {
+ if ( !this.invisibleReason ){
+ this.invisibleReason = {};
+ }
+ this.invisibleReason[reason] = true;
+ this.evaluateRowVisibility( fromRowsProcessor);
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name clearRowInvisible
+ * @methodOf ui.grid.class:GridRow
+ * @description Clears any override on the row visibility, returning it
+ * to normal visibility calculations. Emits the rowsVisibleChanged
+ * event
+ *
+ * @param {string} reason the reason (usually the module) for the row to be invisible.
+ * E.g. grouping, user, filter
+ * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
+ */
+ GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {
+ if (typeof(this.invisibleReason) !== 'undefined' ) {
+ delete this.invisibleReason[reason];
+ }
+ this.evaluateRowVisibility( fromRowsProcessor );
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name evaluateRowVisibility
+ * @methodOf ui.grid.class:GridRow
+ * @description Determines whether the row should be visible based on invisibleReason,
+ * and if it changes the row visibility, then emits the rowsVisibleChanged event.
+ *
+ * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.
+ * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the
+ * row processor does that already
+ */
+ GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {
+ var newVisibility = true;
+ if ( typeof(this.invisibleReason) !== 'undefined' ){
+ angular.forEach(this.invisibleReason, function( value, key ){
+ if ( value ){
+ newVisibility = false;
+ }
+ });
+ }
+
+ if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ){
+ this.visible = newVisibility;
+ if ( !fromRowProcessor ){
+ this.grid.queueGridRefresh();
+ this.grid.api.core.raise.rowsVisibleChanged(this);
+ }
+ }
+ };
+
+
+ return GridRow;
+}]);
+
+})();
+
+(function(){
+ 'use strict';
+ /**
+ * @ngdoc object
+ * @name ui.grid.class:GridRowColumn
+ * @param {GridRow} row The row for this pair
+ * @param {GridColumn} column The column for this pair
+ * @description A row and column pair that represents the intersection of these two entities.
+ * Must be instantiated as a constructor using the `new` keyword.
+ */
+ angular.module('ui.grid')
+ .factory('GridRowColumn', ['$parse', '$filter',
+ function GridRowColumnFactory($parse, $filter){
+ var GridRowColumn = function GridRowColumn(row, col) {
+ if ( !(this instanceof GridRowColumn)){
+ throw "Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";
+ }
+
+ /**
+ * @ngdoc object
+ * @name row
+ * @propertyOf ui.grid.class:GridRowColumn
+ * @description {@link ui.grid.class:GridRow }
+ */
+ this.row = row;
+ /**
+ * @ngdoc object
+ * @name col
+ * @propertyOf ui.grid.class:GridRowColumn
+ * @description {@link ui.grid.class:GridColumn }
+ */
+ this.col = col;
+ };
+
+ /**
+ * @ngdoc function
+ * @name getIntersectionValueRaw
+ * @methodOf ui.grid.class:GridRowColumn
+ * @description Gets the intersection of where the row and column meet.
+ * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
+ * If the column has a cellFilter this will NOT return the filtered value.
+ */
+ GridRowColumn.prototype.getIntersectionValueRaw = function(){
+ var getter = $parse(this.row.getEntityQualifiedColField(this.col));
+ var context = this.row;
+ return getter(context);
+ };
+ /**
+ * @ngdoc function
+ * @name getIntersectionValueFiltered
+ * @methodOf ui.grid.class:GridRowColumn
+ * @description Gets the intersection of where the row and column meet.
+ * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
+ * If the column has a cellFilter this will also apply the filter to it and return the value that the filter displays.
+ */
+ GridRowColumn.prototype.getIntersectionValueFiltered = function(){
+ var value = this.getIntersectionValueRaw();
+ if (this.col.cellFilter && this.col.cellFilter !== ''){
+ var getFilterIfExists = function(filterName){
+ try {
+ return $filter(filterName);
+ } catch (e){
+ return null;
+ }
+ };
+ var filter = getFilterIfExists(this.col.cellFilter);
+ if (filter) { // Check if this is filter name or a filter string
+ value = filter(value);
+ } else { // We have the template version of a filter so we need to parse it apart
+ // Get the filter params out using a regex
+ // Test out this regex here https://regex101.com/r/rC5eR5/2
+ var re = /([^:]*):([^:]*):?([\s\S]+)?/;
+ var matches;
+ if ((matches = re.exec(this.col.cellFilter)) !== null) {
+ // View your result using the matches-variable.
+ // eg matches[0] etc.
+ value = $filter(matches[1])(value, matches[2], matches[3]);
+ }
+ }
+ }
+ return value;
+ };
+ return GridRowColumn;
+ }
+ ]);
+})();
+
+(function () {
+ angular.module('ui.grid')
+ .factory('ScrollEvent', ['gridUtil', function (gridUtil) {
+
+ /**
+ * @ngdoc function
+ * @name ui.grid.class:ScrollEvent
+ * @description Model for all scrollEvents
+ * @param {Grid} grid that owns the scroll event
+ * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null
+ * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null
+ * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName
+ */
+ function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {
+ var self = this;
+ if (!grid) {
+ throw new Error("grid argument is required");
+ }
+
+ /**
+ * @ngdoc object
+ * @name grid
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description A reference back to the grid
+ */
+ self.grid = grid;
+
+
+
+ /**
+ * @ngdoc object
+ * @name source
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources
+ */
+ self.source = source;
+
+
+ /**
+ * @ngdoc object
+ * @name noDelay
+ * @propertyOf ui.grid.class:ScrollEvent
+ * @description most scroll events from the mouse or trackpad require delay to operate properly
+ * set to false to eliminate delay. Useful for scroll events that the grid causes, such as scrolling to make a row visible.
+ */
+ self.withDelay = true;
+
+ self.sourceRowContainer = sourceRowContainer;
+ self.sourceColContainer = sourceColContainer;
+
+ self.newScrollLeft = null;
+ self.newScrollTop = null;
+ self.x = null;
+ self.y = null;
+
+ self.verticalScrollLength = -9999999;
+ self.horizontalScrollLength = -999999;
+
+
+ /**
+ * @ngdoc function
+ * @name fireThrottledScrollingEvent
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description fires a throttled event using grid.api.core.raise.scrollEvent
+ */
+ self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {
+ self.grid.scrollContainers(sourceContainerId, self);
+ }, self.grid.options.wheelScrollThrottle, {trailing: true});
+
+ }
+
+
+ /**
+ * @ngdoc function
+ * @name getNewScrollLeft
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description returns newScrollLeft property if available; calculates a new value if it isn't
+ */
+ ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){
+ var self = this;
+
+ if (!self.newScrollLeft){
+ var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
+
+ var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);
+
+ var scrollXPercentage;
+ if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {
+ scrollXPercentage = self.x.percentage;
+ }
+ else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {
+ scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;
+ }
+ else {
+ throw new Error("No percentage or pixel value provided for scroll event X axis");
+ }
+
+ return Math.max(0, scrollXPercentage * scrollWidth);
+ }
+
+ return self.newScrollLeft;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name getNewScrollTop
+ * @methodOf ui.grid.class:ScrollEvent
+ * @description returns newScrollTop property if available; calculates a new value if it isn't
+ */
+ ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){
+ var self = this;
+
+
+ if (!self.newScrollTop){
+ var scrollLength = rowContainer.getVerticalScrollLength();
+
+ var oldScrollTop = viewport[0].scrollTop;
+
+ var scrollYPercentage;
+ if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {
+ scrollYPercentage = self.y.percentage;
+ }
+ else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {
+ scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;
+ }
+ else {
+ throw new Error("No percentage or pixel value provided for scroll event Y axis");
+ }
+
+ return Math.max(0, scrollYPercentage * scrollLength);
+ }
+
+ return self.newScrollTop;
+ };
+
+ ScrollEvent.prototype.atTop = function(scrollTop) {
+ return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
+ };
+
+ ScrollEvent.prototype.atBottom = function(scrollTop) {
+ return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
+ };
+
+ ScrollEvent.prototype.atLeft = function(scrollLeft) {
+ return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);
+ };
+
+ ScrollEvent.prototype.atRight = function(scrollLeft) {
+ return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);
+ };
+
+
+ ScrollEvent.Sources = {
+ ViewPortScroll: 'ViewPortScroll',
+ RenderContainerMouseWheel: 'RenderContainerMouseWheel',
+ RenderContainerTouchMove: 'RenderContainerTouchMove',
+ Other: 99
+ };
+
+ return ScrollEvent;
+ }]);
+
+
+
+})();
+
+(function () {
+ 'use strict';
+ /**
+ * @ngdoc object
+ * @name ui.grid.service:gridClassFactory
+ *
+ * @description factory to return dom specific instances of a grid
+ *
+ */
+ angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',
+ function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {
+
+ var service = {
+ /**
+ * @ngdoc method
+ * @name createGrid
+ * @methodOf ui.grid.service:gridClassFactory
+ * @description Creates a new grid instance. Each instance will have a unique id
+ * @param {object} options An object map of options to pass into the created grid instance.
+ * @returns {Grid} grid
+ */
+ createGrid : function(options) {
+ options = (typeof(options) !== 'undefined') ? options : {};
+ options.id = gridUtil.newId();
+ var grid = new Grid(options);
+
+ // NOTE/TODO: rowTemplate should always be defined...
+ if (grid.options.rowTemplate) {
+ var rowTemplateFnPromise = $q.defer();
+ grid.getRowTemplateFn = rowTemplateFnPromise.promise;
+
+ gridUtil.getTemplate(grid.options.rowTemplate)
+ .then(
+ function (template) {
+ var rowTemplateFn = $compile(template);
+ rowTemplateFnPromise.resolve(rowTemplateFn);
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use row template '" + grid.options.rowTemplate + "'");
+ });
+ }
+
+ grid.registerColumnBuilder(service.defaultColumnBuilder);
+
+ // Row builder for custom row templates
+ grid.registerRowBuilder(service.rowTemplateAssigner);
+
+ // Reset all rows to visible initially
+ grid.registerRowsProcessor(function allRowsVisible(rows) {
+ rows.forEach(function (row) {
+ row.evaluateRowVisibility( true );
+ }, 50);
+
+ return rows;
+ });
+
+ grid.registerColumnsProcessor(function allColumnsVisible(columns) {
+ columns.forEach(function (column) {
+ column.visible = true;
+ });
+
+ return columns;
+ }, 50);
+
+ grid.registerColumnsProcessor(function(renderableColumns) {
+ renderableColumns.forEach(function (column) {
+ if (column.colDef.visible === false) {
+ column.visible = false;
+ }
+ });
+
+ return renderableColumns;
+ }, 50);
+
+
+ grid.registerRowsProcessor(grid.searchRows, 100);
+
+ // Register the default row processor, it sorts rows by selected columns
+ if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {
+ grid.registerRowsProcessor(grid.options.externalSort, 200);
+ }
+ else {
+ grid.registerRowsProcessor(grid.sortByColumn, 200);
+ }
+
+ return grid;
+ },
+
+ /**
+ * @ngdoc function
+ * @name defaultColumnBuilder
+ * @methodOf ui.grid.service:gridClassFactory
+ * @description Processes designTime column definitions and applies them to col for the
+ * core grid features
+ * @param {object} colDef reference to column definition
+ * @param {GridColumn} col reference to gridCol
+ * @param {object} gridOptions reference to grid options
+ */
+ defaultColumnBuilder: function (colDef, col, gridOptions) {
+
+ var templateGetPromises = [];
+
+ // Abstracts the standard template processing we do for every template type.
+ var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {
+ if ( !colDef[templateType] ){
+ col[providedType] = defaultTemplate;
+ } else {
+ col[providedType] = colDef[templateType];
+ }
+
+ templateGetPromises.push(gridUtil.getTemplate(col[providedType])
+ .then(
+ function (template) {
+ if ( angular.isFunction(template) ) { template = template(); }
+ var tooltipCall = ( tooltipType === 'cellTooltip' ) ? 'col.cellTooltip(row,col)' : 'col.headerTooltip(col)';
+ if ( tooltipType && col[tooltipType] === false ){
+ template = template.replace(uiGridConstants.TOOLTIP, '');
+ } else if ( tooltipType && col[tooltipType] ){
+ template = template.replace(uiGridConstants.TOOLTIP, 'title="{{' + tooltipCall + ' CUSTOM_FILTERS }}"');
+ }
+
+ if ( filterType ){
+ col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {
+ return col[filterType] ? "|" + col[filterType] : "";
+ });
+ } else {
+ col[templateType] = template;
+ }
+ },
+ function (res) {
+ throw new Error("Couldn't fetch/use colDef." + templateType + " '" + colDef[templateType] + "'");
+ })
+ );
+
+ };
+
+
+ /**
+ * @ngdoc property
+ * @name cellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for each cell in this column. The default
+ * is ui-grid/uiGridCell. If you are using the cellNav feature, this template
+ * must contain a div that can receive focus.
+ *
+ */
+ processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );
+ col.cellTemplatePromise = templateGetPromises[0];
+
+ /**
+ * @ngdoc property
+ * @name headerCellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the header for this column. The default
+ * is ui-grid/uiGridHeaderCell
+ *
+ */
+ processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );
+
+ /**
+ * @ngdoc property
+ * @name footerCellTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the footer for this column. The default
+ * is ui-grid/uiGridFooterCell
+ *
+ */
+ processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );
+
+ /**
+ * @ngdoc property
+ * @name filterHeaderTemplate
+ * @propertyOf ui.grid.class:GridOptions.columnDef
+ * @description a custom template for the filter input. The default is ui-grid/ui-grid-filter
+ *
+ */
+ processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );
+
+ // Create a promise for the compiled element function
+ col.compiledElementFnDefer = $q.defer();
+
+ return $q.all(templateGetPromises);
+ },
+
+
+ rowTemplateAssigner: function rowTemplateAssigner(row) {
+ var grid = this;
+
+ // Row has no template assigned to it
+ if (!row.rowTemplate) {
+ // Use the default row template from the grid
+ row.rowTemplate = grid.options.rowTemplate;
+
+ // Use the grid's function for fetching the compiled row template function
+ row.getRowTemplateFn = grid.getRowTemplateFn;
+ }
+ // Row has its own template assigned
+ else {
+ // Create a promise for the compiled row template function
+ var perRowTemplateFnPromise = $q.defer();
+ row.getRowTemplateFn = perRowTemplateFnPromise.promise;
+
+ // Get the row template
+ gridUtil.getTemplate(row.rowTemplate)
+ .then(function (template) {
+ // Compile the template
+ var rowTemplateFn = $compile(template);
+
+ // Resolve the compiled template function promise
+ perRowTemplateFnPromise.resolve(rowTemplateFn);
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use row template '" + row.rowTemplate + "'");
+ });
+ }
+
+ return row.getRowTemplateFn;
+ }
+ };
+
+ //class definitions (moved to separate factories)
+
+ return service;
+ }]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+function escapeRegExp(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+}
+
+
+/**
+ * @ngdoc service
+ * @name ui.grid.service:rowSearcher
+ *
+ * @description Service for searching/filtering rows based on column value conditions.
+ */
+module.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {
+ var defaultCondition = uiGridConstants.filter.CONTAINS;
+
+ var rowSearcher = {};
+
+ /**
+ * @ngdoc function
+ * @name getTerm
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Get the term from a filter
+ * Trims leading and trailing whitespace
+ * @param {object} filter object to use
+ * @returns {object} Parsed term
+ */
+ rowSearcher.getTerm = function getTerm(filter) {
+ if (typeof(filter.term) === 'undefined') { return filter.term; }
+
+ var term = filter.term;
+
+ // Strip leading and trailing whitespace if the term is a string
+ if (typeof(term) === 'string') {
+ term = term.trim();
+ }
+
+ return term;
+ };
+
+ /**
+ * @ngdoc function
+ * @name stripTerm
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Remove leading and trailing asterisk (*) from the filter's term
+ * @param {object} filter object to use
+ * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
+ */
+ rowSearcher.stripTerm = function stripTerm(filter) {
+ var term = rowSearcher.getTerm(filter);
+
+ if (typeof(term) === 'string') {
+ return escapeRegExp(term.replace(/(^\*|\*$)/g, ''));
+ }
+ else {
+ return term;
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name guessCondition
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Guess the condition for a filter based on its term
+ * <br>
+ * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).
+ * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).
+ * @param {object} filter object to use
+ * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
+ */
+ rowSearcher.guessCondition = function guessCondition(filter) {
+ if (typeof(filter.term) === 'undefined' || !filter.term) {
+ return defaultCondition;
+ }
+
+ var term = rowSearcher.getTerm(filter);
+
+ if (/\*/.test(term)) {
+ var regexpFlags = '';
+ if (!filter.flags || !filter.flags.caseSensitive) {
+ regexpFlags += 'i';
+ }
+
+ var reText = term.replace(/(\\)?\*/g, function ($0, $1) { return $1 ? $0 : '[\\s\\S]*?'; });
+ return new RegExp('^' + reText + '$', regexpFlags);
+ }
+ // Otherwise default to default condition
+ else {
+ return defaultCondition;
+ }
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name setupFilters
+ * @methodOf ui.grid.service:rowSearcher
+ * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),
+ * do all the parsing and pre-processing and store that data into a new filters object. The object
+ * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.
+ *
+ * We could use a forEach in here, since it's much less performance sensitive, but since we're using
+ * for loops everywhere else in this module...
+ *
+ * @param {array} filters the filters from the column (col.filters or [col.filter])
+ * @returns {array} An array of parsed/preprocessed filters
+ */
+ rowSearcher.setupFilters = function setupFilters( filters ){
+ var newFilters = [];
+
+ var filtersLength = filters.length;
+ for ( var i = 0; i < filtersLength; i++ ){
+ var filter = filters[i];
+
+ if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ){
+ var newFilter = {};
+
+ var regexpFlags = '';
+ if (!filter.flags || !filter.flags.caseSensitive) {
+ regexpFlags += 'i';
+ }
+
+ if ( !gridUtil.isNullOrUndefined(filter.term) ){
+ // it is possible to have noTerm. We don't need to copy that across, it was just a flag to avoid
+ // getting the filter ignored if the filter was a function that didn't use a term
+ newFilter.term = rowSearcher.stripTerm(filter);
+ }
+
+ if ( filter.condition ){
+ newFilter.condition = filter.condition;
+ } else {
+ newFilter.condition = rowSearcher.guessCondition(filter);
+ }
+
+ newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );
+
+ if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {
+ newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {
+ newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.CONTAINS) {
+ newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);
+ }
+
+ if (newFilter.condition === uiGridConstants.filter.EXACT) {
+ newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);
+ }
+
+ newFilters.push(newFilter);
+ }
+ }
+ return newFilters;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name runColumnFilter
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Runs a single pre-parsed filter against a cell, returning true
+ * if the cell matches that one filter.
+ *
+ * @param {Grid} grid the grid we're working against
+ * @param {GridRow} row the row we're matching against
+ * @param {GridCol} column the column that we're working against
+ * @param {object} filter the specific, preparsed, filter that we want to test
+ * @returns {boolean} true if we match (row stays visible)
+ */
+ rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {
+ // Cache typeof condition
+ var conditionType = typeof(filter.condition);
+
+ // Term to search for.
+ var term = filter.term;
+
+ // Get the column value for this row
+ var value;
+ if ( column.filterCellFiltered ){
+ value = grid.getCellDisplayValue(row, column);
+ } else {
+ value = grid.getCellValue(row, column);
+ }
+
+
+ // If the filter's condition is a RegExp, then use it
+ if (filter.condition instanceof RegExp) {
+ return filter.condition.test(value);
+ }
+
+ // If the filter's condition is a function, run it
+ if (conditionType === 'function') {
+ return filter.condition(term, value, row, column);
+ }
+
+ if (filter.startswithRE) {
+ return filter.startswithRE.test(value);
+ }
+
+ if (filter.endswithRE) {
+ return filter.endswithRE.test(value);
+ }
+
+ if (filter.containsRE) {
+ return filter.containsRE.test(value);
+ }
+
+ if (filter.exactRE) {
+ return filter.exactRE.test(value);
+ }
+
+ if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {
+ var regex = new RegExp('^' + term + '$');
+ return !regex.exec(value);
+ }
+
+ if (typeof(value) === 'number' && typeof(term) === 'string' ){
+ // if the term has a decimal in it, it comes through as '9\.4', we need to take out the \
+ // the same for negative numbers
+ // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?
+ var tempFloat = parseFloat(term.replace(/\\\./,'.').replace(/\\\-/,'-'));
+ if (!isNaN(tempFloat)) {
+ term = tempFloat;
+ }
+ }
+
+ if (filter.flags.date === true) {
+ value = new Date(value);
+ // If the term has a dash in it, it comes through as '\-' -- we need to take out the '\'.
+ term = new Date(term.replace(/\\/g, ''));
+ }
+
+ if (filter.condition === uiGridConstants.filter.GREATER_THAN) {
+ return (value > term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {
+ return (value >= term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.LESS_THAN) {
+ return (value < term);
+ }
+
+ if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {
+ return (value <= term);
+ }
+
+ return true;
+ };
+
+
+ /**
+ * @ngdoc boolean
+ * @name useExternalFiltering
+ * @propertyOf ui.grid.class:GridOptions
+ * @description False by default. When enabled, this setting suppresses the internal filtering.
+ * All UI logic will still operate, allowing filter conditions to be set and modified.
+ *
+ * The external filter logic can listen for the `filterChange` event, which fires whenever
+ * a filter has been adjusted.
+ */
+ /**
+ * @ngdoc function
+ * @name searchColumn
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Process provided filters on provided column against a given row. If the row meets
+ * the conditions on all the filters, return true.
+ * @param {Grid} grid Grid to search in
+ * @param {GridRow} row Row to search on
+ * @param {GridCol} column Column with the filters to use
+ * @param {array} filters array of pre-parsed/preprocessed filters to apply
+ * @returns {boolean} Whether the column matches or not.
+ */
+ rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {
+ if (grid.options.useExternalFiltering) {
+ return true;
+ }
+
+ var filtersLength = filters.length;
+ for (var i = 0; i < filtersLength; i++) {
+ var filter = filters[i];
+
+ var ret = rowSearcher.runColumnFilter(grid, row, column, filter);
+ if (!ret) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+
+ /**
+ * @ngdoc function
+ * @name search
+ * @methodOf ui.grid.service:rowSearcher
+ * @description Run a search across the given rows and columns, marking any rows that don't
+ * match the stored col.filters or col.filter as invisible.
+ * @param {Grid} grid Grid instance to search inside
+ * @param {Array[GridRow]} rows GridRows to filter
+ * @param {Array[GridColumn]} columns GridColumns with filters to process
+ */
+ rowSearcher.search = function search(grid, rows, columns) {
+ /*
+ * Added performance optimisations into this code base, as this logic creates deeply nested
+ * loops and is therefore very performance sensitive. In particular, avoiding forEach as
+ * this impacts some browser optimisers (particularly Chrome), using iterators instead
+ */
+
+ // Don't do anything if we weren't passed any rows
+ if (!rows) {
+ return;
+ }
+
+ // don't filter if filtering currently disabled
+ if (!grid.options.enableFiltering){
+ return rows;
+ }
+
+ // Build list of filters to apply
+ var filterData = [];
+
+ var colsLength = columns.length;
+
+ var hasTerm = function( filters ) {
+ var hasTerm = false;
+
+ filters.forEach( function (filter) {
+ if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){
+ hasTerm = true;
+ }
+ });
+
+ return hasTerm;
+ };
+
+ for (var i = 0; i < colsLength; i++) {
+ var col = columns[i];
+
+ if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {
+ filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );
+ }
+ }
+
+ if (filterData.length > 0) {
+ // define functions outside the loop, performance optimisation
+ var foreachRow = function(grid, row, col, filters){
+ if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {
+ row.visible = false;
+ }
+ };
+
+ var foreachFilterCol = function(grid, filterData){
+ var rowsLength = rows.length;
+ for ( var i = 0; i < rowsLength; i++){
+ foreachRow(grid, rows[i], filterData.col, filterData.filters);
+ }
+ };
+
+ // nested loop itself - foreachFilterCol, which in turn calls foreachRow
+ var filterDataLength = filterData.length;
+ for ( var j = 0; j < filterDataLength; j++){
+ foreachFilterCol( grid, filterData[j] );
+ }
+
+ if (grid.api.core.raise.rowsVisibleChanged) {
+ grid.api.core.raise.rowsVisibleChanged();
+ }
+
+ // drop any invisible rows
+ // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter
+ // rows = rows.filter(function(row){ return row.visible; });
+
+ }
+
+ return rows;
+ };
+
+ return rowSearcher;
+}]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+/**
+ * @ngdoc object
+ * @name ui.grid.class:RowSorter
+ * @description RowSorter provides the default sorting mechanisms,
+ * including guessing column types and applying appropriate sort
+ * algorithms
+ *
+ */
+
+module.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {
+ var currencyRegexStr =
+ '(' +
+ uiGridConstants.CURRENCY_SYMBOLS
+ .map(function (a) { return '\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)
+ .join('|') + // Join all the symbols together with |s
+ ')?';
+
+ // /^[-+]?[£$¤¥]?[\d,.]+%?$/
+ var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\d,.]+' + currencyRegexStr + '%?$');
+
+ var rowSorter = {
+ // Cache of sorting functions. Once we create them, we don't want to keep re-doing it
+ // this takes a piece of data from the cell and tries to determine its type and what sorting
+ // function to use for it
+ colSortFnCache: {}
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name guessSortFn
+ * @description Assigns a sort function to use based on the itemType in the column
+ * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'. And
+ * error will be thrown for any other type.
+ * @returns {function} a sort function that will sort that type
+ */
+ rowSorter.guessSortFn = function guessSortFn(itemType) {
+ switch (itemType) {
+ case "number":
+ return rowSorter.sortNumber;
+ case "numberStr":
+ return rowSorter.sortNumberStr;
+ case "boolean":
+ return rowSorter.sortBool;
+ case "string":
+ return rowSorter.sortAlpha;
+ case "date":
+ return rowSorter.sortDate;
+ case "object":
+ return rowSorter.basicSort;
+ default:
+ throw new Error('No sorting function found for type:' + itemType);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name handleNulls
+ * @description Sorts nulls and undefined to the bottom (top when
+ * descending). Called by each of the internal sorters before
+ * attempting to sort. Note that this method is available on the core api
+ * via gridApi.core.sortHandleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} null if there were no nulls/undefineds, otherwise returns
+ * a sort value that should be passed back from the sort function
+ */
+ rowSorter.handleNulls = function handleNulls(a, b) {
+ // We want to allow zero values and false values to be evaluated in the sort function
+ if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {
+ // We want to force nulls and such to the bottom when we sort... which effectively is "greater than"
+ if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {
+ return 0;
+ }
+ else if (!a && a !== 0 && a !== false) {
+ return 1;
+ }
+ else if (!b && b !== 0 && b !== false) {
+ return -1;
+ }
+ }
+ return null;
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name basicSort
+ * @description Sorts any values that provide the < method, including strings
+ * or numbers. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.basicSort = function basicSort(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (a === b) {
+ return 0;
+ }
+ if (a < b) {
+ return -1;
+ }
+ return 1;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sortNumber
+ * @description Sorts numerical values. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortNumber = function sortNumber(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ return a - b;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sortNumberStr
+ * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).
+ * Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortNumberStr = function sortNumberStr(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ var numA, // The parsed number form of 'a'
+ numB, // The parsed number form of 'b'
+ badA = false,
+ badB = false;
+
+ // Try to parse 'a' to a float
+ numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
+
+ // If 'a' couldn't be parsed to float, flag it as bad
+ if (isNaN(numA)) {
+ badA = true;
+ }
+
+ // Try to parse 'b' to a float
+ numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
+
+ // If 'b' couldn't be parsed to float, flag it as bad
+ if (isNaN(numB)) {
+ badB = true;
+ }
+
+ // We want bad ones to get pushed to the bottom... which effectively is "greater than"
+ if (badA && badB) {
+ return 0;
+ }
+
+ if (badA) {
+ return 1;
+ }
+
+ if (badB) {
+ return -1;
+ }
+
+ return numA - numB;
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sortAlpha
+ * @description Sorts string values. Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortAlpha = function sortAlpha(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ var strA = a.toString().toLowerCase(),
+ strB = b.toString().toLowerCase();
+
+ return strA === strB ? 0 : (strA < strB ? -1 : 1);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sortDate
+ * @description Sorts date values. Handles nulls and undefined through calling handleNulls.
+ * Handles date strings by converting to Date object if not already an instance of Date
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortDate = function sortDate(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (!(a instanceof Date)) {
+ a = new Date(a);
+ }
+ if (!(b instanceof Date)){
+ b = new Date(b);
+ }
+ var timeA = a.getTime(),
+ timeB = b.getTime();
+
+ return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sortBool
+ * @description Sorts boolean values, true is considered larger than false.
+ * Handles nulls and undefined through calling handleNulls
+ * @param {object} a sort value a
+ * @param {object} b sort value b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.sortBool = function sortBool(a, b) {
+ var nulls = rowSorter.handleNulls(a, b);
+ if ( nulls !== null ){
+ return nulls;
+ } else {
+ if (a && b) {
+ return 0;
+ }
+
+ if (!a && !b) {
+ return 0;
+ }
+ else {
+ return a ? 1 : -1;
+ }
+ }
+ };
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name getSortFn
+ * @description Get the sort function for the column. Looks first in
+ * rowSorter.colSortFnCache using the column name, failing that it
+ * looks at col.sortingAlgorithm (and puts it in the cache), failing that
+ * it guesses the sort algorithm based on the data type.
+ *
+ * The cache currently seems a bit pointless, as none of the work we do is
+ * processor intensive enough to need caching. Presumably in future we might
+ * inspect the row data itself to guess the sort function, and in that case
+ * it would make sense to have a cache, the infrastructure is in place to allow
+ * that.
+ *
+ * @param {Grid} grid the grid to consider
+ * @param {GridCol} col the column to find a function for
+ * @param {array} rows an array of grid rows. Currently unused, but presumably in future
+ * we might inspect the rows themselves to decide what sort of data might be there
+ * @returns {function} the sort function chosen for the column
+ */
+ rowSorter.getSortFn = function getSortFn(grid, col, rows) {
+ var sortFn, item;
+
+ // See if we already figured out what to use to sort the column and have it in the cache
+ if (rowSorter.colSortFnCache[col.colDef.name]) {
+ sortFn = rowSorter.colSortFnCache[col.colDef.name];
+ }
+ // If the column has its OWN sorting algorithm, use that
+ else if (col.sortingAlgorithm !== undefined) {
+ sortFn = col.sortingAlgorithm;
+ rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;
+ }
+ // Always default to sortAlpha when sorting after a cellFilter
+ else if ( col.sortCellFiltered && col.cellFilter ){
+ sortFn = rowSorter.sortAlpha;
+ rowSorter.colSortFnCache[col.colDef.name] = sortFn;
+ }
+ // Try and guess what sort function to use
+ else {
+ // Guess the sort function
+ sortFn = rowSorter.guessSortFn(col.colDef.type);
+
+ // If we found a sort function, cache it
+ if (sortFn) {
+ rowSorter.colSortFnCache[col.colDef.name] = sortFn;
+ }
+ else {
+ // We assign the alpha sort because anything that is null/undefined will never get passed to
+ // the actual sorting function. It will get caught in our null check and returned to be sorted
+ // down to the bottom
+ sortFn = rowSorter.sortAlpha;
+ }
+ }
+
+ return sortFn;
+ };
+
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name prioritySort
+ * @description Used where multiple columns are present in the sort criteria,
+ * we determine which column should take precedence in the sort by sorting
+ * the columns based on their sort.priority
+ *
+ * @param {gridColumn} a column a
+ * @param {gridColumn} b column b
+ * @returns {number} normal sort function, returns -ve, 0, +ve
+ */
+ rowSorter.prioritySort = function (a, b) {
+ // Both columns have a sort priority
+ if (a.sort.priority !== undefined && b.sort.priority !== undefined) {
+ // A is higher priority
+ if (a.sort.priority < b.sort.priority) {
+ return -1;
+ }
+ // Equal
+ else if (a.sort.priority === b.sort.priority) {
+ return 0;
+ }
+ // B is higher
+ else {
+ return 1;
+ }
+ }
+ // Only A has a priority
+ else if (a.sort.priority || a.sort.priority === 0) {
+ return -1;
+ }
+ // Only B has a priority
+ else if (b.sort.priority || b.sort.priority === 0) {
+ return 1;
+ }
+ // Neither has a priority
+ else {
+ return 0;
+ }
+ };
+
+
+ /**
+ * @ngdoc object
+ * @name useExternalSorting
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Prevents the internal sorting from executing. Events will
+ * still be fired when the sort changes, and the sort information on
+ * the columns will be updated, allowing an external sorter (for example,
+ * server sorting) to be implemented. Defaults to false.
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.class:RowSorter
+ * @name sort
+ * @description sorts the grid
+ * @param {Object} grid the grid itself
+ * @param {array} rows the rows to be sorted
+ * @param {array} columns the columns in which to look
+ * for sort criteria
+ * @returns {array} sorted rows
+ */
+ rowSorter.sort = function rowSorterSort(grid, rows, columns) {
+ // first make sure we are even supposed to do work
+ if (!rows) {
+ return;
+ }
+
+ if (grid.options.useExternalSorting){
+ return rows;
+ }
+
+ // Build the list of columns to sort by
+ var sortCols = [];
+ columns.forEach(function (col) {
+ if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
+ sortCols.push(col);
+ }
+ });
+
+ // Sort the "sort columns" by their sort priority
+ sortCols = sortCols.sort(rowSorter.prioritySort);
+
+ // Now rows to sort by, maintain original order
+ if (sortCols.length === 0) {
+ return rows;
+ }
+
+ // Re-usable variables
+ var col, direction;
+
+ // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
+ var setIndex = function( row, idx ){
+ row.entity.$$uiGridIndex = idx;
+ };
+ rows.forEach(setIndex);
+
+ // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference
+ // var d = data.slice(0);
+ var r = rows.slice(0);
+
+ // Now actually sort the data
+ var rowSortFn = function (rowA, rowB) {
+ var tem = 0,
+ idx = 0,
+ sortFn;
+
+ while (tem === 0 && idx < sortCols.length) {
+ // grab the metadata for the rest of the logic
+ col = sortCols[idx];
+ direction = sortCols[idx].sort.direction;
+
+ sortFn = rowSorter.getSortFn(grid, col, r);
+
+ var propA, propB;
+
+ if ( col.sortCellFiltered ){
+ propA = grid.getCellDisplayValue(rowA, col);
+ propB = grid.getCellDisplayValue(rowB, col);
+ } else {
+ propA = grid.getCellValue(rowA, col);
+ propB = grid.getCellValue(rowB, col);
+ }
+
+ tem = sortFn(propA, propB, rowA, rowB, direction);
+
+ idx++;
+ }
+
+ // Chrome doesn't implement a stable sort function. If our sort returns 0
+ // (i.e. the items are equal), and we're at the last sort column in the list,
+ // then return the previous order using our custom
+ // index variable
+ if (tem === 0 ) {
+ return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;
+ }
+
+ // Made it this far, we don't have to worry about null & undefined
+ if (direction === uiGridConstants.ASC) {
+ return tem;
+ } else {
+ return 0 - tem;
+ }
+ };
+
+ var newRows = rows.sort(rowSortFn);
+
+ // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
+ var clearIndex = function( row, idx ){
+ delete row.entity.$$uiGridIndex;
+ };
+ rows.forEach(clearIndex);
+
+ return newRows;
+ };
+
+ return rowSorter;
+}]);
+
+})();
+
+(function() {
+
+var module = angular.module('ui.grid');
+
+var bindPolyfill;
+if (typeof Function.prototype.bind !== "function") {
+ bindPolyfill = function() {
+ var slice = Array.prototype.slice;
+ return function(context) {
+ var fn = this,
+ args = slice.call(arguments, 1);
+ if (args.length) {
+ return function() {
+ return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);
+ };
+ }
+ return function() {
+ return arguments.length ? fn.apply(context, arguments) : fn.call(context);
+ };
+ };
+ };
+}
+
+function getStyles (elem) {
+ var e = elem;
+ if (typeof(e.length) !== 'undefined' && e.length) {
+ e = elem[0];
+ }
+
+ return e.ownerDocument.defaultView.getComputedStyle(e, null);
+}
+
+var rnumnonpx = new RegExp( "^(" + (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source + ")(?!px)[a-z%]+$", "i" ),
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" };
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? 'border' : 'content' ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === 'width' ? 1 : 0,
+
+ val = 0;
+
+ var sides = ['Top', 'Right', 'Bottom', 'Left'];
+
+ for ( ; i < 4; i += 2 ) {
+ var side = sides[i];
+ // dump('side', side);
+
+ // both box models exclude margin, so add it if we want it
+ if ( extra === 'margin' ) {
+ var marg = parseFloat(styles[extra + side]);
+ if (!isNaN(marg)) {
+ val += marg;
+ }
+ }
+ // dump('val1', val);
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === 'content' ) {
+ var padd = parseFloat(styles['padding' + side]);
+ if (!isNaN(padd)) {
+ val -= padd;
+ // dump('val2', val);
+ }
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== 'margin' ) {
+ var bordermarg = parseFloat(styles['border' + side + 'Width']);
+ if (!isNaN(bordermarg)) {
+ val -= bordermarg;
+ // dump('val3', val);
+ }
+ }
+ }
+ else {
+ // at this point, extra isn't content, so add padding
+ var nocontentPad = parseFloat(styles['padding' + side]);
+ if (!isNaN(nocontentPad)) {
+ val += nocontentPad;
+ // dump('val4', val);
+ }
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== 'padding') {
+ var nocontentnopad = parseFloat(styles['border' + side + 'Width']);
+ if (!isNaN(nocontentnopad)) {
+ val += nocontentnopad;
+ // dump('val5', val);
+ }
+ }
+ }
+ }
+
+ // dump('augVal', val);
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles(elem),
+ isBorderBox = styles['boxSizing'] === 'border-box';
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = styles[name];
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ var ret = ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ );
+
+ // dump('ret', ret, val);
+ return ret;
+}
+
+function getLineHeight(elm) {
+ elm = angular.element(elm)[0];
+ var parent = elm.parentElement;
+
+ if (!parent) {
+ parent = document.getElementsByTagName('body')[0];
+ }
+
+ return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;
+}
+
+var uid = ['0', '0', '0', '0'];
+var uidPrefix = 'uiGrid-';
+
+/**
+ * @ngdoc service
+ * @name ui.grid.service:GridUtil
+ *
+ * @description Grid utility functions
+ */
+module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',
+ function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {
+ var s = {
+
+ augmentWidthOrHeight: augmentWidthOrHeight,
+
+ getStyles: getStyles,
+
+ /**
+ * @ngdoc method
+ * @name createBoundedWrapper
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {object} Object to bind 'this' to
+ * @param {method} Method to bind
+ * @returns {Function} The wrapper that performs the binding
+ *
+ * @description
+ * Binds given method to given object.
+ *
+ * By means of a wrapper, ensures that ``method`` is always bound to
+ * ``object`` regardless of its calling environment.
+ * Iow, inside ``method``, ``this`` always points to ``object``.
+ *
+ * See http://alistapart.com/article/getoutbindingsituations
+ *
+ */
+ createBoundedWrapper: function(object, method) {
+ return function() {
+ return method.apply(object, arguments);
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name readableColumnName
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {string} columnName Column name as a string
+ * @returns {string} Column name appropriately capitalized and split apart
+ *
+ @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid']);
+
+ app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {
+ $scope.name = 'firstName';
+ $scope.columnName = function(name) {
+ return gridUtil.readableColumnName(name);
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <strong>Column name:</strong> <input ng-model="name" />
+ <br>
+ <strong>Output:</strong> <span ng-bind="columnName(name)"></span>
+ </div>
+ </file>
+ </example>
+ */
+ readableColumnName: function (columnName) {
+ // Convert underscores to spaces
+ if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }
+
+ if (typeof(columnName) !== 'string') {
+ columnName = String(columnName);
+ }
+
+ return columnName.replace(/_+/g, ' ')
+ // Replace a completely all-capsed word with a first-letter-capitalized version
+ .replace(/^[A-Z]+$/, function (match) {
+ return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));
+ })
+ // Capitalize the first letter of words
+ .replace(/([\w\u00C0-\u017F]+)/g, function (match) {
+ return angular.uppercase(match.charAt(0)) + match.slice(1);
+ })
+ // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')
+ // .replace(/([A-Z]|[A-Z]\w+)([A-Z])/g, "$1 $2");
+ // .replace(/(\w+?|\w)([A-Z])/g, "$1 $2");
+ .replace(/(\w+?(?=[A-Z]))/g, '$1 ');
+ },
+
+ /**
+ * @ngdoc method
+ * @name getColumnsFromData
+ * @methodOf ui.grid.service:GridUtil
+ * @description Return a list of column names, given a data set
+ *
+ * @param {string} data Data array for grid
+ * @returns {Object} Column definitions with field accessor and column name
+ *
+ * @example
+ <pre>
+ var data = [
+ { firstName: 'Bob', lastName: 'Jones' },
+ { firstName: 'Frank', lastName: 'Smith' }
+ ];
+
+ var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);
+
+ columnDefs == [
+ {
+ field: 'firstName',
+ name: 'First Name'
+ },
+ {
+ field: 'lastName',
+ name: 'Last Name'
+ }
+ ];
+ </pre>
+ */
+ getColumnsFromData: function (data, excludeProperties) {
+ var columnDefs = [];
+
+ if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }
+ if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }
+
+ var item = data[0];
+
+ angular.forEach(item,function (prop, propName) {
+ if ( excludeProperties.indexOf(propName) === -1){
+ columnDefs.push({
+ name: propName
+ });
+ }
+ });
+
+ return columnDefs;
+ },
+
+ /**
+ * @ngdoc method
+ * @name newId
+ * @methodOf ui.grid.service:GridUtil
+ * @description Return a unique ID string
+ *
+ * @returns {string} Unique string
+ *
+ * @example
+ <pre>
+ var id = GridUtil.newId();
+
+ # 1387305700482;
+ </pre>
+ */
+ newId: (function() {
+ var seedId = new Date().getTime();
+ return function() {
+ return seedId += 1;
+ };
+ })(),
+
+
+ /**
+ * @ngdoc method
+ * @name getTemplate
+ * @methodOf ui.grid.service:GridUtil
+ * @description Get's template from cache / element / url
+ *
+ * @param {string|element|promise} Either a string representing the template id, a string representing the template url,
+ * an jQuery/Angualr element, or a promise that returns the template contents to use.
+ * @returns {object} a promise resolving to template contents
+ *
+ * @example
+ <pre>
+ GridUtil.getTemplate(url).then(function (contents) {
+ alert(contents);
+ })
+ </pre>
+ */
+ getTemplate: function (template) {
+ // Try to fetch the template out of the templateCache
+ if ($templateCache.get(template)) {
+ return s.postProcessTemplate($templateCache.get(template));
+ }
+
+ // See if the template is itself a promise
+ if (template.hasOwnProperty('then')) {
+ return template.then(s.postProcessTemplate);
+ }
+
+ // If the template is an element, return the element
+ try {
+ if (angular.element(template).length > 0) {
+ return $q.when(template).then(s.postProcessTemplate);
+ }
+ }
+ catch (err){
+ //do nothing; not valid html
+ }
+
+ s.logDebug('fetching url', template);
+
+ // Default to trying to fetch the template as a url with $http
+ return $http({ method: 'GET', url: template})
+ .then(
+ function (result) {
+ var templateHtml = result.data.trim();
+ //put in templateCache for next call
+ $templateCache.put(template, templateHtml);
+ return templateHtml;
+ },
+ function (err) {
+ throw new Error("Could not get template " + template + ": " + err);
+ }
+ )
+ .then(s.postProcessTemplate);
+ },
+
+ //
+ postProcessTemplate: function (template) {
+ var startSym = $interpolate.startSymbol(),
+ endSym = $interpolate.endSymbol();
+
+ // If either of the interpolation symbols have been changed, we need to alter this template
+ if (startSym !== '{{' || endSym !== '}}') {
+ template = template.replace(/\{\{/g, startSym);
+ template = template.replace(/\}\}/g, endSym);
+ }
+
+ return $q.when(template);
+ },
+
+ /**
+ * @ngdoc method
+ * @name guessType
+ * @methodOf ui.grid.service:GridUtil
+ * @description guesses the type of an argument
+ *
+ * @param {string/number/bool/object} item variable to examine
+ * @returns {string} one of the following
+ * - 'string'
+ * - 'boolean'
+ * - 'number'
+ * - 'date'
+ * - 'object'
+ */
+ guessType : function (item) {
+ var itemType = typeof(item);
+
+ // Check for numbers and booleans
+ switch (itemType) {
+ case "number":
+ case "boolean":
+ case "string":
+ return itemType;
+ default:
+ if (angular.isDate(item)) {
+ return "date";
+ }
+ return "object";
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @name elementWidth
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element DOM element
+ * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
+ *
+ * @returns {number} Element width in pixels, accounting for any borders, etc.
+ */
+ elementWidth: function (elem) {
+
+ },
+
+ /**
+ * @ngdoc method
+ * @name elementHeight
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element DOM element
+ * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
+ *
+ * @returns {number} Element height in pixels, accounting for any borders, etc.
+ */
+ elementHeight: function (elem) {
+
+ },
+
+ // Thanks to http://stackoverflow.com/a/13382873/888165
+ getScrollbarWidth: function() {
+ var outer = document.createElement("div");
+ outer.style.visibility = "hidden";
+ outer.style.width = "100px";
+ outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
+
+ document.body.appendChild(outer);
+
+ var widthNoScroll = outer.offsetWidth;
+ // force scrollbars
+ outer.style.overflow = "scroll";
+
+ // add innerdiv
+ var inner = document.createElement("div");
+ inner.style.width = "100%";
+ outer.appendChild(inner);
+
+ var widthWithScroll = inner.offsetWidth;
+
+ // remove divs
+ outer.parentNode.removeChild(outer);
+
+ return widthNoScroll - widthWithScroll;
+ },
+
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ },
+
+ fakeElement: function( elem, options, callback, args ) {
+ var ret, name,
+ newElement = angular.element(elem).clone()[0];
+
+ for ( name in options ) {
+ newElement.style[ name ] = options[ name ];
+ }
+
+ angular.element(document.body).append(newElement);
+
+ ret = callback.call( newElement, newElement );
+
+ angular.element(newElement).remove();
+
+ return ret;
+ },
+
+ /**
+ * @ngdoc method
+ * @name normalizeWheelEvent
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {event} event A mouse wheel event
+ *
+ * @returns {event} A normalized event
+ *
+ * @description
+ * Given an event from this list:
+ *
+ * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`
+ *
+ * "normalize" it
+ * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)
+ */
+ normalizeWheelEvent: function (event) {
+ // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
+ // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
+ var lowestDelta, lowestDeltaXY;
+
+ var orgEvent = event || window.event,
+ args = [].slice.call(arguments, 1),
+ delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ absDeltaXY = 0,
+ fn;
+
+ // event = $.event.fix(orgEvent);
+ // event.type = 'mousewheel';
+
+ // NOTE: jQuery masks the event and stores it in the event as originalEvent
+ if (orgEvent.originalEvent) {
+ orgEvent = orgEvent.originalEvent;
+ }
+
+ // Old school scrollwheel delta
+ if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
+ if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
+
+ // At a minimum, setup the deltaY to be delta
+ deltaY = delta;
+
+ // Firefox < 17 related to DOMMouseScroll event
+ if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
+ deltaY = 0;
+ deltaX = delta * -1;
+ }
+
+ // New school wheel delta (wheel event)
+ if ( orgEvent.deltaY ) {
+ deltaY = orgEvent.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( orgEvent.deltaX ) {
+ deltaX = orgEvent.deltaX;
+ delta = deltaX * -1;
+ }
+
+ // Webkit
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }
+
+ // Look for lowest delta to normalize the delta values
+ absDelta = Math.abs(delta);
+ if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
+ absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
+ if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
+
+ // Get a whole value for the deltas
+ fn = delta > 0 ? 'floor' : 'ceil';
+ delta = Math[fn](delta / lowestDelta);
+ deltaX = Math[fn](deltaX / lowestDeltaXY);
+ deltaY = Math[fn](deltaY / lowestDeltaXY);
+
+ return {
+ delta: delta,
+ deltaX: deltaX,
+ deltaY: deltaY
+ };
+ },
+
+ // Stolen from Modernizr
+ // TODO: make this, and everythign that flows from it, robust
+ //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
+ isTouchEnabled: function() {
+ var bool;
+
+ if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {
+ bool = true;
+ }
+
+ return bool;
+ },
+
+ isNullOrUndefined: function(obj) {
+ if (obj === undefined || obj === null) {
+ return true;
+ }
+ return false;
+ },
+
+ endsWith: function(str, suffix) {
+ if (!str || !suffix || typeof str !== "string") {
+ return false;
+ }
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ },
+
+ arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {
+ var found = false;
+ angular.forEach(array, function (object) {
+ if (object[propertyName] === propertyValue) {
+ found = true;
+ }
+ });
+ return found;
+ },
+
+ //// Shim requestAnimationFrame
+ //requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||
+ // $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||
+ // function(fn) {
+ // return $timeout(fn, 10, false);
+ // },
+
+ numericAndNullSort: function (a, b) {
+ if (a === null) { return 1; }
+ if (b === null) { return -1; }
+ if (a === null && b === null) { return 0; }
+ return a - b;
+ },
+
+ // Disable ngAnimate animations on an element
+ disableAnimations: function (element) {
+ var $animate;
+ try {
+ $animate = $injector.get('$animate');
+ // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
+ if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
+ $animate.enabled(element, false);
+ } else {
+ $animate.enabled(false, element);
+ }
+ }
+ catch (e) {}
+ },
+
+ enableAnimations: function (element) {
+ var $animate;
+ try {
+ $animate = $injector.get('$animate');
+ // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
+ if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
+ $animate.enabled(element, true);
+ } else {
+ $animate.enabled(true, element);
+ }
+ return $animate;
+ }
+ catch (e) {}
+ },
+
+ // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
+ nextUid: function nextUid() {
+ var index = uid.length;
+ var digit;
+
+ while (index) {
+ index--;
+ digit = uid[index].charCodeAt(0);
+ if (digit === 57 /*'9'*/) {
+ uid[index] = 'A';
+ return uidPrefix + uid.join('');
+ }
+ if (digit === 90 /*'Z'*/) {
+ uid[index] = '0';
+ } else {
+ uid[index] = String.fromCharCode(digit + 1);
+ return uidPrefix + uid.join('');
+ }
+ }
+ uid.unshift('0');
+
+ return uidPrefix + uid.join('');
+ },
+
+ // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
+ hashKey: function hashKey(obj) {
+ var objType = typeof obj,
+ key;
+
+ if (objType === 'object' && obj !== null) {
+ if (typeof (key = obj.$$hashKey) === 'function') {
+ // must invoke on object to keep the right this
+ key = obj.$$hashKey();
+ }
+ else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {
+ key = obj.$$hashKey;
+ }
+ else if (key === undefined) {
+ key = obj.$$hashKey = s.nextUid();
+ }
+ }
+ else {
+ key = obj;
+ }
+
+ return objType + ':' + key;
+ },
+
+ resetUids: function () {
+ uid = ['0', '0', '0'];
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logError
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true
+ * @param {string} logMessage message to be logged to the console
+ *
+ */
+ logError: function( logMessage ){
+ if ( uiGridConstants.LOG_ERROR_MESSAGES ){
+ $log.error( logMessage );
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logWarn
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true
+ * @param {string} logMessage message to be logged to the console
+ *
+ */
+ logWarn: function( logMessage ){
+ if ( uiGridConstants.LOG_WARN_MESSAGES ){
+ $log.warn( logMessage );
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil
+ * @name logDebug
+ * @description wraps the $log method, allowing us to choose different
+ * treatment within ui-grid if we so desired. At present we only log
+ * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true
+ *
+ */
+ logDebug: function() {
+ if ( uiGridConstants.LOG_DEBUG_MESSAGES ){
+ $log.debug.apply($log, arguments);
+ }
+ }
+
+ };
+
+ /**
+ * @ngdoc object
+ * @name focus
+ * @propertyOf ui.grid.service:GridUtil
+ * @description Provies a set of methods to set the document focus inside the grid.
+ * See {@link ui.grid.service:GridUtil.focus} for more information.
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.service:GridUtil.focus
+ * @description Provies a set of methods to set the document focus inside the grid.
+ * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.
+ * e.g. click events that need to run before the focus or
+ * inputs elements that are in a disabled state but are enabled when those events
+ * are triggered.
+ */
+ s.focus = {
+ queue: [],
+ //http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name byId
+ * @description Sets the focus of the document to the given id value.
+ * If provided with the grid object it will automatically append the grid id.
+ * This is done to encourage unique dom id's as it allows for multiple grids on a
+ * page.
+ * @param {String} id the id of the dom element to set the focus on
+ * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}
+ * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ byId: function (id, Grid) {
+ this._purgeQueue();
+ var promise = $timeout(function() {
+ var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;
+ var element = $window.document.getElementById(elementID);
+ if (element) {
+ element.focus();
+ } else {
+ s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');
+ }
+ });
+ this.queue.push(promise);
+ return promise;
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name byElement
+ * @description Sets the focus of the document to the given dom element.
+ * @param {(element|angular.element)} element the DOM element to set the focus on
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ byElement: function(element){
+ if (!angular.isElement(element)){
+ s.logWarn("Trying to focus on an element that isn\'t an element.");
+ return $q.reject('not-element');
+ }
+ element = angular.element(element);
+ this._purgeQueue();
+ var promise = $timeout(function(){
+ if (element){
+ element[0].focus();
+ }
+ });
+ this.queue.push(promise);
+ return promise;
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.service:GridUtil.focus
+ * @name bySelector
+ * @description Sets the focus of the document to the given dom element.
+ * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector
+ * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}
+ * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately
+ * then the focus will be called.
+ * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
+ * then the promise will fail with the `'canceled'` reason.
+ */
+ bySelector: function(parentElement, querySelector, aSync){
+ var self = this;
+ if (!angular.isElement(parentElement)){
+ throw new Error("The parent element is not an element.");
+ }
+ // Ensure that this is an angular element.
+ // It is fine if this is already an angular element.
+ parentElement = angular.element(parentElement);
+ var focusBySelector = function(){
+ var element = parentElement[0].querySelector(querySelector);
+ return self.byElement(element);
+ };
+ this._purgeQueue();
+ if (aSync){ //Do this asynchronysly
+ var promise = $timeout(focusBySelector);
+ this.queue.push($timeout(focusBySelector));
+ return promise;
+ } else {
+ return focusBySelector();
+ }
+ },
+ _purgeQueue: function(){
+ this.queue.forEach(function(element){
+ $timeout.cancel(element);
+ });
+ this.queue = [];
+ }
+ };
+
+
+ ['width', 'height'].forEach(function (name) {
+ var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);
+ s['element' + capsName] = function (elem, extra) {
+ var e = elem;
+ if (e && typeof(e.length) !== 'undefined' && e.length) {
+ e = elem[0];
+ }
+
+ if (e) {
+ var styles = getStyles(e);
+ return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?
+ s.swap(e, cssShow, function() {
+ return getWidthOrHeight(e, name, extra );
+ }) :
+ getWidthOrHeight( e, name, extra );
+ }
+ else {
+ return null;
+ }
+ };
+
+ s['outerElement' + capsName] = function (elem, margin) {
+ return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;
+ };
+ });
+
+ // http://stackoverflow.com/a/24107550/888165
+ s.closestElm = function closestElm(el, selector) {
+ if (typeof(el.length) !== 'undefined' && el.length) {
+ el = el[0];
+ }
+
+ var matchesFn;
+
+ // find vendor prefix
+ ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
+ if (typeof document.body[fn] === 'function') {
+ matchesFn = fn;
+ return true;
+ }
+ return false;
+ });
+
+ // traverse parents
+ var parent;
+ while (el !== null) {
+ parent = el.parentElement;
+ if (parent !== null && parent[matchesFn](selector)) {
+ return parent;
+ }
+ el = parent;
+ }
+
+ return null;
+ };
+
+ s.type = function (obj) {
+ var text = Function.prototype.toString.call(obj.constructor);
+ return text.match(/function (.*?)\(/)[1];
+ };
+
+ s.getBorderSize = function getBorderSize(elem, borderType) {
+ if (typeof(elem.length) !== 'undefined' && elem.length) {
+ elem = elem[0];
+ }
+
+ var styles = getStyles(elem);
+
+ // If a specific border is supplied, like 'top', read the 'borderTop' style property
+ if (borderType) {
+ borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);
+ }
+ else {
+ borderType = 'border';
+ }
+
+ borderType += 'Width';
+
+ var val = parseInt(styles[borderType], 10);
+
+ if (isNaN(val)) {
+ return 0;
+ }
+ else {
+ return val;
+ }
+ };
+
+ // http://stackoverflow.com/a/22948274/888165
+ // TODO: Opera? Mobile?
+ s.detectBrowser = function detectBrowser() {
+ var userAgent = $window.navigator.userAgent;
+
+ var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\//i};
+
+ for (var key in browsers) {
+ if (browsers[key].test(userAgent)) {
+ return key;
+ }
+ }
+
+ return 'unknown';
+ };
+
+ // Borrowed from https://github.com/othree/jquery.rtl-scroll-type
+ // Determine the scroll "type" this browser is using for RTL
+ s.rtlScrollType = function rtlScrollType() {
+ if (rtlScrollType.type) {
+ return rtlScrollType.type;
+ }
+
+ var definer = angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],
+ type = 'reverse';
+
+ document.body.appendChild(definer);
+
+ if (definer.scrollLeft > 0) {
+ type = 'default';
+ }
+ else {
+ definer.scrollLeft = 1;
+ if (definer.scrollLeft === 0) {
+ type = 'negative';
+ }
+ }
+
+ angular.element(definer).remove();
+ rtlScrollType.type = type;
+
+ return type;
+ };
+
+ /**
+ * @ngdoc method
+ * @name normalizeScrollLeft
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element The element to get the `scrollLeft` from.
+ * @param {grid} grid - grid used to normalize (uses the rtl property)
+ *
+ * @returns {number} A normalized scrollLeft value for the current browser.
+ *
+ * @description
+ * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them
+ */
+ s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {
+ if (typeof(element.length) !== 'undefined' && element.length) {
+ element = element[0];
+ }
+
+ var scrollLeft = element.scrollLeft;
+
+ if (grid.isRTL()) {
+ switch (s.rtlScrollType()) {
+ case 'default':
+ return element.scrollWidth - scrollLeft - element.clientWidth;
+ case 'negative':
+ return Math.abs(scrollLeft);
+ case 'reverse':
+ return scrollLeft;
+ }
+ }
+
+ return scrollLeft;
+ };
+
+ /**
+ * @ngdoc method
+ * @name denormalizeScrollLeft
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {element} element The element to normalize the `scrollLeft` value for
+ * @param {number} scrollLeft The `scrollLeft` value to denormalize.
+ * @param {grid} grid The grid that owns the scroll event.
+ *
+ * @returns {number} A normalized scrollLeft value for the current browser.
+ *
+ * @description
+ * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.
+ */
+ s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {
+ if (typeof(element.length) !== 'undefined' && element.length) {
+ element = element[0];
+ }
+
+ if (grid.isRTL()) {
+ switch (s.rtlScrollType()) {
+ case 'default':
+ // Get the max scroll for the element
+ var maxScrollLeft = element.scrollWidth - element.clientWidth;
+
+ // Subtract the current scroll amount from the max scroll
+ return maxScrollLeft - scrollLeft;
+ case 'negative':
+ return scrollLeft * -1;
+ case 'reverse':
+ return scrollLeft;
+ }
+ }
+
+ return scrollLeft;
+ };
+
+ /**
+ * @ngdoc method
+ * @name preEval
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {string} path Path to evaluate
+ *
+ * @returns {string} A path that is normalized.
+ *
+ * @description
+ * Takes a field path and converts it to bracket notation to allow for special characters in path
+ * @example
+ * <pre>
+ * gridUtil.preEval('property') == 'property'
+ * gridUtil.preEval('nested.deep.prop-erty') = "nested['deep']['prop-erty']"
+ * </pre>
+ */
+ s.preEval = function (path) {
+ var m = uiGridConstants.BRACKET_REGEXP.exec(path);
+ if (m) {
+ return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);
+ } else {
+ path = path.replace(uiGridConstants.APOS_REGEXP, '\\\'');
+ var parts = path.split(uiGridConstants.DOT_REGEXP);
+ var preparsed = [parts.shift()]; // first item must be var notation, thus skip
+ angular.forEach(parts, function (part) {
+ preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\']$1'));
+ });
+ return preparsed.join('[\'');
+ }
+ };
+
+ /**
+ * @ngdoc method
+ * @name debounce
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {function} func function to debounce
+ * @param {number} wait milliseconds to delay
+ * @param {boolean} immediate execute before delay
+ *
+ * @returns {function} A function that can be executed as debounced function
+ *
+ * @description
+ * Copied from https://github.com/shahata/angular-debounce
+ * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function
+ * @example
+ * <pre>
+ * var debouncedFunc = gridUtil.debounce(function(){alert('debounced');}, 500);
+ * debouncedFunc();
+ * debouncedFunc();
+ * debouncedFunc();
+ * </pre>
+ */
+ s.debounce = function (func, wait, immediate) {
+ var timeout, args, context, result;
+ function debounce() {
+ /* jshint validthis:true */
+ context = this;
+ args = arguments;
+ var later = function () {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ if (timeout) {
+ $timeout.cancel(timeout);
+ }
+ timeout = $timeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ }
+ return result;
+ }
+ debounce.cancel = function () {
+ $timeout.cancel(timeout);
+ timeout = null;
+ };
+ return debounce;
+ };
+
+ /**
+ * @ngdoc method
+ * @name throttle
+ * @methodOf ui.grid.service:GridUtil
+ *
+ * @param {function} func function to throttle
+ * @param {number} wait milliseconds to delay after first trigger
+ * @param {Object} params to use in throttle.
+ *
+ * @returns {function} A function that can be executed as throttled function
+ *
+ * @description
+ * Adapted from debounce function (above)
+ * Potential keys for Params Object are:
+ * trailing (bool) - whether to trigger after throttle time ends if called multiple times
+ * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,
+ * but not with $timeout
+ *
+ * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function
+ * return from that call each time you need to call throttle. If you call throttle itself repeatedly, the lastCall
+ * variable will get overwritten and the throttling won't work
+ *
+ * @example
+ * <pre>
+ * var throttledFunc = gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});
+ * throttledFunc(); //=> logs throttled
+ * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)
+ * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.
+ * </pre>
+ */
+ s.throttle = function(func, wait, options){
+ options = options || {};
+ var lastCall = 0, queued = null, context, args;
+
+ function runFunc(endDate){
+ lastCall = +new Date();
+ func.apply(context, args);
+ $interval(function(){ queued = null; }, 0, 1);
+ }
+
+ return function(){
+ /* jshint validthis:true */
+ context = this;
+ args = arguments;
+ if (queued === null){
+ var sinceLast = +new Date() - lastCall;
+ if (sinceLast > wait){
+ runFunc();
+ }
+ else if (options.trailing){
+ queued = $interval(runFunc, wait - sinceLast, 1);
+ }
+ }
+ };
+ };
+
+ s.on = {};
+ s.off = {};
+ s._events = {};
+
+ s.addOff = function (eventName) {
+ s.off[eventName] = function (elm, fn) {
+ var idx = s._events[eventName].indexOf(fn);
+ if (idx > 0) {
+ s._events[eventName].removeAt(idx);
+ }
+ };
+ };
+
+ var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
+ nullLowestDeltaTimeout,
+ lowestDelta;
+
+ s.on.mousewheel = function (elm, fn) {
+ if (!elm || !fn) { return; }
+
+ var $elm = angular.element(elm);
+
+ // Store the line height and page height for this particular element
+ $elm.data('mousewheel-line-height', getLineHeight($elm));
+ $elm.data('mousewheel-page-height', s.elementHeight($elm));
+ if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }
+
+ var cbs = $elm.data('mousewheel-callbacks');
+ cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);
+
+ // Bind all the mousew heel events
+ for ( var i = mouseWheeltoBind.length; i; ) {
+ $elm.on(mouseWheeltoBind[--i], cbs[fn]);
+ }
+ };
+ s.off.mousewheel = function (elm, fn) {
+ var $elm = angular.element(elm);
+
+ var cbs = $elm.data('mousewheel-callbacks');
+ var handler = cbs[fn];
+
+ if (handler) {
+ for ( var i = mouseWheeltoBind.length; i; ) {
+ $elm.off(mouseWheeltoBind[--i], handler);
+ }
+ }
+
+ delete cbs[fn];
+
+ if (Object.keys(cbs).length === 0) {
+ $elm.removeData('mousewheel-line-height');
+ $elm.removeData('mousewheel-page-height');
+ $elm.removeData('mousewheel-callbacks');
+ }
+ };
+
+ function mousewheelHandler(fn, event) {
+ var $elm = angular.element(this);
+
+ var delta = 0,
+ deltaX = 0,
+ deltaY = 0,
+ absDelta = 0,
+ offsetX = 0,
+ offsetY = 0;
+
+ // jQuery masks events
+ if (event.originalEvent) { event = event.originalEvent; }
+
+ if ( 'detail' in event ) { deltaY = event.detail * -1; }
+ if ( 'wheelDelta' in event ) { deltaY = event.wheelDelta; }
+ if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY; }
+ if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }
+
+ // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
+ if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
+ deltaX = deltaY * -1;
+ deltaY = 0;
+ }
+
+ // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
+ delta = deltaY === 0 ? deltaX : deltaY;
+
+ // New school wheel delta (wheel event)
+ if ( 'deltaY' in event ) {
+ deltaY = event.deltaY * -1;
+ delta = deltaY;
+ }
+ if ( 'deltaX' in event ) {
+ deltaX = event.deltaX;
+ if ( deltaY === 0 ) { delta = deltaX * -1; }
+ }
+
+ // No change actually happened, no reason to go any further
+ if ( deltaY === 0 && deltaX === 0 ) { return; }
+
+ // Need to convert lines and pages to pixels if we aren't already in pixels
+ // There are three delta modes:
+ // * deltaMode 0 is by pixels, nothing to do
+ // * deltaMode 1 is by lines
+ // * deltaMode 2 is by pages
+ if ( event.deltaMode === 1 ) {
+ var lineHeight = $elm.data('mousewheel-line-height');
+ delta *= lineHeight;
+ deltaY *= lineHeight;
+ deltaX *= lineHeight;
+ }
+ else if ( event.deltaMode === 2 ) {
+ var pageHeight = $elm.data('mousewheel-page-height');
+ delta *= pageHeight;
+ deltaY *= pageHeight;
+ deltaX *= pageHeight;
+ }
+
+ // Store lowest absolute delta to normalize the delta values
+ absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
+
+ if ( !lowestDelta || absDelta < lowestDelta ) {
+ lowestDelta = absDelta;
+
+ // Adjust older deltas if necessary
+ if ( shouldAdjustOldDeltas(event, absDelta) ) {
+ lowestDelta /= 40;
+ }
+ }
+
+ // Get a whole, normalized value for the deltas
+ delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
+ deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
+ deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
+
+ event.deltaMode = 0;
+
+ // Normalise offsetX and offsetY properties
+ // if ($elm[0].getBoundingClientRect ) {
+ // var boundingRect = $(elm)[0].getBoundingClientRect();
+ // offsetX = event.clientX - boundingRect.left;
+ // offsetY = event.clientY - boundingRect.top;
+ // }
+
+ // event.deltaX = deltaX;
+ // event.deltaY = deltaY;
+ // event.deltaFactor = lowestDelta;
+
+ var newEvent = {
+ originalEvent: event,
+ deltaX: deltaX,
+ deltaY: deltaY,
+ deltaFactor: lowestDelta,
+ preventDefault: function () { event.preventDefault(); },
+ stopPropagation: function () { event.stopPropagation(); }
+ };
+
+ // Clearout lowestDelta after sometime to better
+ // handle multiple device types that give
+ // a different lowestDelta
+ // Ex: trackpad = 3 and mouse wheel = 120
+ if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
+ nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
+
+ fn.call($elm[0], newEvent);
+ }
+
+ function nullLowestDelta() {
+ lowestDelta = null;
+ }
+
+ function shouldAdjustOldDeltas(orgEvent, absDelta) {
+ // If this is an older event and the delta is divisable by 120,
+ // then we are assuming that the browser is treating this as an
+ // older mouse wheel event and that we should divide the deltas
+ // by 40 to try and get a more usable deltaFactor.
+ // Side note, this actually impacts the reported scroll distance
+ // in older browsers and can cause scrolling to be slower than native.
+ // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
+ return orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
+ }
+
+ return s;
+}]);
+
+// Add 'px' to the end of a number string if it doesn't have it already
+module.filter('px', function() {
+ return function(str) {
+ if (str.match(/^[\d\.]+$/)) {
+ return str + 'px';
+ }
+ else {
+ return str;
+ }
+ };
+});
+
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ var lang = {
+ aggregate: {
+ label: 'položky'
+ },
+ groupPanel: {
+ description: 'Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce.'
+ },
+ search: {
+ placeholder: 'Hledat...',
+ showingItems: 'Zobrazuji položky:',
+ selectedItems: 'Vybrané položky:',
+ totalItems: 'Celkem položek:',
+ size: 'Velikost strany:',
+ first: 'První strana',
+ next: 'Další strana',
+ previous: 'Předchozí strana',
+ last: 'Poslední strana'
+ },
+ menu: {
+ text: 'Vyberte sloupec:'
+ },
+ sort: {
+ ascending: 'Seřadit od A-Z',
+ descending: 'Seřadit od Z-A',
+ remove: 'Odebrat seřazení'
+ },
+ column: {
+ hide: 'Schovat sloupec'
+ },
+ aggregation: {
+ count: 'celkem řádků: ',
+ sum: 'celkem: ',
+ avg: 'avg: ',
+ min: 'min.: ',
+ max: 'max.: '
+ },
+ pinning: {
+ pinLeft: 'Zamknout vlevo',
+ pinRight: 'Zamknout vpravo',
+ unpin: 'Odemknout'
+ },
+ gridMenu: {
+ columns: 'Sloupce:',
+ importerTitle: 'Importovat soubor',
+ exporterAllAsCsv: 'Exportovat všechna data do csv',
+ exporterVisibleAsCsv: 'Exportovat viditelná data do csv',
+ exporterSelectedAsCsv: 'Exportovat vybraná data do csv',
+ exporterAllAsPdf: 'Exportovat všechna data do pdf',
+ exporterVisibleAsPdf: 'Exportovat viditelná data do pdf',
+ exporterSelectedAsPdf: 'Exportovat vybraná data do pdf',
+ clearAllFilters: 'Odstranit všechny filtry'
+ },
+ importer: {
+ noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',
+ noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',
+ invalidCsv: 'Soubor nelze zpracovat, jedná se o CSV?',
+ invalidJson: 'Soubor nelze zpracovat, je to JSON?',
+ jsonNotArray: 'Soubor musí obsahovat json. UkonÄuji..'
+ },
+ pagination: {
+ sizes: 'položek na stránku',
+ totalItems: 'položek'
+ },
+ grouping: {
+ group: 'Seskupit',
+ ungroup: 'Odebrat seskupení',
+ aggregate_count: 'Agregace: Count',
+ aggregate_sum: 'Agregace: Sum',
+ aggregate_max: 'Agregace: Max',
+ aggregate_min: 'Agregace: Min',
+ aggregate_avg: 'Agregace: Avg',
+ aggregate_remove: 'Agregace: Odebrat'
+ }
+ };
+
+ // support varianty of different czech keys.
+ $delegate.add('cs', lang);
+ $delegate.add('cz', lang);
+ $delegate.add('cs-cz', lang);
+ $delegate.add('cs-CZ', lang);
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function(){
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('da', {
+ aggregate:{
+ label: 'artikler'
+ },
+ groupPanel:{
+ description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'
+ },
+ search:{
+ placeholder: 'Søg...',
+ showingItems: 'Viste rækker:',
+ selectedItems: 'Valgte rækker:',
+ totalItems: 'Rækker totalt:',
+ size: 'Side størrelse:',
+ first: 'Første side',
+ next: 'Næste side',
+ previous: 'Forrige side',
+ last: 'Sidste side'
+ },
+ menu:{
+ text: 'Vælg kolonner:'
+ },
+ column: {
+ hide: 'Skjul kolonne'
+ },
+ aggregation: {
+ count: 'samlede rækker: ',
+ sum: 'smalede: ',
+ avg: 'gns: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('de', {
+ aggregate: {
+ label: 'Eintrag'
+ },
+ groupPanel: {
+ description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'
+ },
+ search: {
+ placeholder: 'Suche...',
+ showingItems: 'Zeige Einträge:',
+ selectedItems: 'Ausgewählte Einträge:',
+ totalItems: 'Einträge gesamt:',
+ size: 'Einträge pro Seite:',
+ first: 'Erste Seite',
+ next: 'Nächste Seite',
+ previous: 'Vorherige Seite',
+ last: 'Letzte Seite'
+ },
+ menu: {
+ text: 'Spalten auswählen:'
+ },
+ sort: {
+ ascending: 'aufsteigend sortieren',
+ descending: 'absteigend sortieren',
+ remove: 'Sortierung zurücksetzen'
+ },
+ column: {
+ hide: 'Spalte ausblenden'
+ },
+ aggregation: {
+ count: 'Zeilen insgesamt: ',
+ sum: 'gesamt: ',
+ avg: 'Durchschnitt: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Links anheften',
+ pinRight: 'Rechts anheften',
+ unpin: 'Lösen'
+ },
+ gridMenu: {
+ columns: 'Spalten:',
+ importerTitle: 'Datei importieren',
+ exporterAllAsCsv: 'Alle Daten als CSV exportieren',
+ exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',
+ exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',
+ exporterAllAsPdf: 'Alle Daten als PDF exportieren',
+ exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',
+ exporterSelectedAsPdf: 'markierte Daten als CSV exportieren',
+ clearAllFilters: 'Alle filter reinigen'
+ },
+ importer: {
+ noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',
+ noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',
+ invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',
+ invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',
+ jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'
+ },
+ pagination: {
+ sizes: 'Einträge pro Seite',
+ totalItems: 'Einträge'
+ },
+ grouping: {
+ group: 'Gruppieren',
+ ungroup: 'Gruppierung aufheben',
+ aggregate_count: 'Agg: Anzahl',
+ aggregate_sum: 'Agg: Summe',
+ aggregate_max: 'Agg: Maximum',
+ aggregate_min: 'Agg: Minimum',
+ aggregate_avg: 'Agg: Mittelwert',
+ aggregate_remove: 'Aggregation entfernen'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('en', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: 'Filter for column',
+ removeFilter: 'Remove Filter',
+ columnMenuButtonLabel: 'Column Menu'
+ },
+ priority: 'Priority:',
+ filterLabel: "Filter for column: "
+ },
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Drag a column header here and drop it to group by that column.'
+ },
+ search: {
+ placeholder: 'Search...',
+ showingItems: 'Showing Items:',
+ selectedItems: 'Selected Items:',
+ totalItems: 'Total Items:',
+ size: 'Page Size:',
+ first: 'First Page',
+ next: 'Next Page',
+ previous: 'Previous Page',
+ last: 'Last Page'
+ },
+ menu: {
+ text: 'Choose Columns:'
+ },
+ sort: {
+ ascending: 'Sort Ascending',
+ descending: 'Sort Descending',
+ none: 'Sort None',
+ remove: 'Remove Sort'
+ },
+ column: {
+ hide: 'Hide Column'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Pin Left',
+ pinRight: 'Pin Right',
+ unpin: 'Unpin'
+ },
+ columnMenu: {
+ close: 'Close'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: 'Grid Menu'
+ },
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: 'Page to first',
+ pageBack: 'Page back',
+ pageSelected: 'Selected page',
+ pageForward: 'Page forward',
+ pageToLast: 'Page to last'
+ },
+ sizes: 'items per page',
+ totalItems: 'items',
+ through: 'through',
+ of: 'of'
+ },
+ grouping: {
+ group: 'Group',
+ ungroup: 'Ungroup',
+ aggregate_count: 'Agg: Count',
+ aggregate_sum: 'Agg: Sum',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Avg',
+ aggregate_remove: 'Agg: Remove'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('es', {
+ aggregate: {
+ label: 'Artículos'
+ },
+ groupPanel: {
+ description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'
+ },
+ search: {
+ placeholder: 'Buscar...',
+ showingItems: 'Artículos Mostrados:',
+ selectedItems: 'Artículos Seleccionados:',
+ totalItems: 'Artículos Totales:',
+ size: 'Tamaño de Página:',
+ first: 'Primera Página',
+ next: 'Página Siguiente',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Elegir columnas:'
+ },
+ sort: {
+ ascending: 'Orden Ascendente',
+ descending: 'Orden Descendente',
+ remove: 'Sin Ordenar'
+ },
+ column: {
+ hide: 'Ocultar la columna'
+ },
+ aggregation: {
+ count: 'filas totales: ',
+ sum: 'total: ',
+ avg: 'media: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fijar a la Izquierda',
+ pinRight: 'Fijar a la Derecha',
+ unpin: 'Quitar Fijación'
+ },
+ gridMenu: {
+ columns: 'Columnas:',
+ importerTitle: 'Importar archivo',
+ exporterAllAsCsv: 'Exportar todo como csv',
+ exporterVisibleAsCsv: 'Exportar vista como csv',
+ exporterSelectedAsCsv: 'Exportar selección como csv',
+ exporterAllAsPdf: 'Exportar todo como pdf',
+ exporterVisibleAsPdf: 'Exportar vista como pdf',
+ exporterSelectedAsPdf: 'Exportar selección como pdf',
+ clearAllFilters: 'Limpiar todos los filtros'
+ },
+ importer: {
+ noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',
+ noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',
+ invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',
+ invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',
+ jsonNotArray: 'El archivo json importado debe contener un array, abortando.'
+ },
+ pagination: {
+ sizes: 'registros por página',
+ totalItems: 'registros',
+ of: 'de'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Cont',
+ aggregate_sum: 'Agr: Sum',
+ aggregate_max: 'Agr: Máx',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Prom',
+ aggregate_remove: 'Agr: Quitar'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+/**
+ * Translated by: R. Salarmehr
+ * M. Hosseynzade
+ * Using Vajje.com online dictionary.
+ */
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('fa', {
+ aggregate: {
+ label: 'قلم'
+ },
+ groupPanel: {
+ description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'
+ },
+ search: {
+ placeholder: 'جستجو...',
+ showingItems: 'نمایش اقلام:',
+ selectedItems: 'قلم\u200cهای انتخاب شده:',
+ totalItems: 'مجموع اقلام:',
+ size: 'اندازه\u200cÛŒ صÙحه:',
+ first: 'اولین صÙحه',
+ next: 'صÙحه\u200cÛŒ\u200cبعدی',
+ previous: 'صÙحه\u200cÛŒ\u200c قبلی',
+ last: 'آخرین صÙحه'
+ },
+ menu: {
+ text: 'ستون\u200cهای انتخابی:'
+ },
+ sort: {
+ ascending: 'ترتیب صعودی',
+ descending: 'ترتیب نزولی',
+ remove: 'حذ٠مرتب کردن'
+ },
+ column: {
+ hide: 'پنهان\u200cکردن ستون'
+ },
+ aggregation: {
+ count: 'تعداد: ',
+ sum: 'مجموع: ',
+ avg: 'میانگین: ',
+ min: 'کمترین: ',
+ max: 'بیشترین: '
+ },
+ pinning: {
+ pinLeft: 'پین کردن سمت چپ',
+ pinRight: 'پین کردن سمت راست',
+ unpin: 'حذ٠پین'
+ },
+ gridMenu: {
+ columns: 'ستون\u200cها:',
+ importerTitle: 'وارد کردن Ùایل',
+ exporterAllAsCsv: 'خروجی تمام داده\u200cها در Ùایل csv',
+ exporterVisibleAsCsv: 'خروجی داده\u200cهای قابل مشاهده در Ùایل csv',
+ exporterSelectedAsCsv: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل csv',
+ exporterAllAsPdf: 'خروجی تمام داده\u200cها در Ùایل pdf',
+ exporterVisibleAsPdf: 'خروجی داده\u200cهای قابل مشاهده در Ùایل pdf',
+ exporterSelectedAsPdf: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل pdf',
+ clearAllFilters: 'پاک کردن تمام Ùیلتر'
+ },
+ importer: {
+ noHeaders: 'نام ستون قابل استخراج نیست. آیا Ùایل عنوان دارد؟',
+ noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\u200cها در Ùایل داده وجود دارد؟',
+ invalidCsv: 'Ùایل قابل پردازش نیست. آیا Ùرمت csv معتبر است؟',
+ invalidJson: 'Ùایل قابل پردازش نیست. آیا Ùرمت json معتبر است؟',
+ jsonNotArray: 'Ùایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'
+ },
+ pagination: {
+ sizes: 'اقلام در هر صÙحه',
+ totalItems: 'اقلام',
+ of: 'از'
+ },
+ grouping: {
+ group: 'گروه\u200cبندی',
+ ungroup: 'حذ٠گروه\u200cبندی',
+ aggregate_count: 'Agg: تعداد',
+ aggregate_sum: 'Agg: جمع',
+ aggregate_max: 'Agg: بیشینه',
+ aggregate_min: 'Agg: کمینه',
+ aggregate_avg: 'Agg: میانگین',
+ aggregate_remove: 'Agg: حذÙ'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('fi', {
+ aggregate: {
+ label: 'rivit'
+ },
+ groupPanel: {
+ description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'
+ },
+ search: {
+ placeholder: 'Hae...',
+ showingItems: 'Näytetään rivejä:',
+ selectedItems: 'Valitut rivit:',
+ totalItems: 'Rivejä yht.:',
+ size: 'Näytä:',
+ first: 'Ensimmäinen sivu',
+ next: 'Seuraava sivu',
+ previous: 'Edellinen sivu',
+ last: 'Viimeinen sivu'
+ },
+ menu: {
+ text: 'Valitse sarakkeet:'
+ },
+ sort: {
+ ascending: 'Järjestä nouseva',
+ descending: 'Järjestä laskeva',
+ remove: 'Poista järjestys'
+ },
+ column: {
+ hide: 'Piilota sarake'
+ },
+ aggregation: {
+ count: 'Rivejä yht.: ',
+ sum: 'Summa: ',
+ avg: 'K.a.: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Lukitse vasemmalle',
+ pinRight: 'Lukitse oikealle',
+ unpin: 'Poista lukitus'
+ },
+ gridMenu: {
+ columns: 'Sarakkeet:',
+ importerTitle: 'Tuo tiedosto',
+ exporterAllAsCsv: 'Vie tiedot csv-muodossa',
+ exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',
+ exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',
+ exporterAllAsPdf: 'Vie tiedot pdf-muodossa',
+ exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',
+ exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa',
+ clearAllFilters: 'Puhdista kaikki suodattimet'
+ },
+ importer: {
+ noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',
+ noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',
+ invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',
+ invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',
+ jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('fr', {
+ aggregate: {
+ label: 'éléments'
+ },
+ groupPanel: {
+ description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'
+ },
+ search: {
+ placeholder: 'Recherche...',
+ showingItems: 'Affichage des éléments :',
+ selectedItems: 'Éléments sélectionnés :',
+ totalItems: 'Nombre total d\'éléments:',
+ size: 'Taille de page:',
+ first: 'Première page',
+ next: 'Page Suivante',
+ previous: 'Page précédente',
+ last: 'Dernière page'
+ },
+ menu: {
+ text: 'Choisir des colonnes :'
+ },
+ sort: {
+ ascending: 'Trier par ordre croissant',
+ descending: 'Trier par ordre décroissant',
+ remove: 'Enlever le tri'
+ },
+ column: {
+ hide: 'Cacher la colonne'
+ },
+ aggregation: {
+ count: 'lignes totales: ',
+ sum: 'total: ',
+ avg: 'moy: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Épingler à gauche',
+ pinRight: 'Épingler à droite',
+ unpin: 'Détacher'
+ },
+ gridMenu: {
+ columns: 'Colonnes:',
+ importerTitle: 'Importer un fichier',
+ exporterAllAsCsv: 'Exporter toutes les données en CSV',
+ exporterVisibleAsCsv: 'Exporter les données visibles en CSV',
+ exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',
+ exporterAllAsPdf: 'Exporter toutes les données en PDF',
+ exporterVisibleAsPdf: 'Exporter les données visibles en PDF',
+ exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF',
+ clearAllFilters: 'Nettoyez tous les filtres'
+ },
+ importer: {
+ noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',
+ noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\'en-tête ?',
+ invalidCsv: 'Le fichier n\'a pas pu être traité, le CSV est-il valide ?',
+ invalidJson: 'Le fichier n\'a pas pu être traité, le JSON est-il valide ?',
+ jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'
+ },
+ pagination: {
+ sizes: 'éléments par page',
+ totalItems: 'éléments',
+ of: 'sur'
+ },
+ grouping: {
+ group: 'Grouper',
+ ungroup: 'Dégrouper',
+ aggregate_count: 'Agg: Compte',
+ aggregate_sum: 'Agg: Somme',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Moy',
+ aggregate_remove: 'Agg: Retirer'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function ($provide) {
+ $provide.decorator('i18nService', ['$delegate', function ($delegate) {
+ $delegate.add('he', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'גרור עמודה לכ×ן ושחרר בכדי לקבץ עמודה זו.'
+ },
+ search: {
+ placeholder: 'חפש...',
+ showingItems: 'מציג:',
+ selectedItems: 'סה"כ נבחרו:',
+ totalItems: 'סה"כ רשומות:',
+ size: 'תוצ×ות בדף:',
+ first: 'דף ר×שון',
+ next: 'דף הב×',
+ previous: 'דף קוד×',
+ last: 'דף ×חרון'
+ },
+ menu: {
+ text: 'בחר עמודות:'
+ },
+ sort: {
+ ascending: 'סדר עולה',
+ descending: 'סדר יורד',
+ remove: 'בטל'
+ },
+ column: {
+ hide: 'טור הסתר'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clean all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('hy', {
+ aggregate: {
+ label: 'Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€'
+ },
+ groupPanel: {
+ description: 'Ô¸Õ½Õ¿ Õ½ÕµÕ¡Õ¶ Õ­Õ´Õ¢Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö„Õ¡Õ·Õ¥Ö„ Ö‡ Õ£ÖÕ¥Ö„ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰'
+ },
+ search: {
+ placeholder: 'Õ“Õ¶Õ¿Ö€Õ¸Ö‚Õ´...',
+ showingItems: 'Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ',
+ selectedItems: 'Ô¸Õ¶Õ¿Ö€Õ¾Õ¡Õ®:',
+ totalItems: 'Ô¸Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ',
+ size: 'ÕÕ¸Õ²Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨ Õ§Õ»Õ¸Ö‚Õ´Õ',
+ first: 'Ô±Õ¼Õ¡Õ»Õ«Õ¶ Õ§Õ»',
+ next: 'Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ§Õ»',
+ previous: 'Õ†Õ¡Õ­Õ¸Ö€Õ¤ Õ§Õ»',
+ last: 'ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ§Õ»'
+ },
+ menu: {
+ text: 'Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¥Ö€Õ¨:'
+ },
+ sort: {
+ ascending: 'Ô±Õ³Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
+ descending: 'Õ†Õ¾Õ¡Õ¦Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
+ remove: 'Õ€Õ¡Õ¶Õ¥Õ¬ '
+ },
+ column: {
+ hide: 'Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¨'
+ },
+ aggregation: {
+ count: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨ Õ¿Õ¸Õ²Õ ',
+ sum: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ ',
+ avg: 'Õ´Õ«Õ»Õ«Õ¶Õ ',
+ min: 'Õ´Õ«Õ¶Õ ',
+ max: 'Õ´Õ¡Ö„Õ½Õ '
+ },
+ pinning: {
+ pinLeft: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ±Õ¡Õ­ Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
+ pinRight: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
+ unpin: 'Ô±Ö€Õ±Õ¡Õ¯Õ¥Õ¬'
+ },
+ gridMenu: {
+ columns: 'ÕÕµÕ¸Ö‚Õ¶Õ¥Ö€:',
+ importerTitle: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ Ö†Õ¡ÕµÕ¬',
+ exporterAllAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨ CSV',
+ exporterVisibleAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
+ exporterSelectedAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
+ exporterAllAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ PDF',
+ exporterVisibleAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
+ exporterSelectedAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
+ clearAllFilters: 'Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€Õ¨'
+ },
+ importer: {
+ noHeaders: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ½ÕµÕ¡Õ¶ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¨ Õ¸Ö‚Õ¶Õ« Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Ö‰',
+ noObjects: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰',
+ invalidCsv: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ CSV Õ§Ö‰',
+ invalidJson: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ Json Õ§Ö‰',
+ jsonNotArray: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¾Õ¡Õ® json Ö†Õ¡ÕµÕ¬Õ¨ ÕºÕ¥Õ¿Ö„ Õ§ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ« Õ¦Õ¡Õ¶Õ£Õ¾Õ¡Õ®, Õ¯Õ¡Õ½Õ¥ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('it', {
+ aggregate: {
+ label: 'elementi'
+ },
+ groupPanel: {
+ description: 'Trascina un\'intestazione all\'interno del gruppo della colonna.'
+ },
+ search: {
+ placeholder: 'Ricerca...',
+ showingItems: 'Mostra:',
+ selectedItems: 'Selezionati:',
+ totalItems: 'Totali:',
+ size: 'Tot Pagine:',
+ first: 'Prima',
+ next: 'Prossima',
+ previous: 'Precedente',
+ last: 'Ultima'
+ },
+ menu: {
+ text: 'Scegli le colonne:'
+ },
+ sort: {
+ ascending: 'Asc.',
+ descending: 'Desc.',
+ remove: 'Annulla ordinamento'
+ },
+ column: {
+ hide: 'Nascondi'
+ },
+ aggregation: {
+ count: 'righe totali: ',
+ sum: 'tot: ',
+ avg: 'media: ',
+ min: 'minimo: ',
+ max: 'massimo: '
+ },
+ pinning: {
+ pinLeft: 'Blocca a sx',
+ pinRight: 'Blocca a dx',
+ unpin: 'Blocca in alto'
+ },
+ gridMenu: {
+ columns: 'Colonne:',
+ importerTitle: 'Importa',
+ exporterAllAsCsv: 'Esporta tutti i dati in CSV',
+ exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',
+ exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',
+ exporterAllAsPdf: 'Esporta tutti i dati in PDF',
+ exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',
+ exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF',
+ clearAllFilters: 'Pulire tutti i filtri'
+ },
+ importer: {
+ noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\'interno del file?',
+ noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\'interno del file?',
+ invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',
+ invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',
+ jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'
+ },
+ grouping: {
+ group: 'Raggruppa',
+ ungroup: 'Separa',
+ aggregate_count: 'Agg: N. Elem.',
+ aggregate_sum: 'Agg: Somma',
+ aggregate_max: 'Agg: Massimo',
+ aggregate_min: 'Agg: Minimo',
+ aggregate_avg: 'Agg: Media',
+ aggregate_remove: 'Agg: Rimuovi'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ja', {
+ aggregate: {
+ label: 'é …ç›®'
+ },
+ groupPanel: {
+ description: 'ã“ã“ã«åˆ—ヘッダをドラッグアンドドロップã—ã¦ã€ãã®åˆ—ã§ã‚°ãƒ«ãƒ¼ãƒ—化ã—ã¾ã™ã€‚'
+ },
+ search: {
+ placeholder: '検索...',
+ showingItems: '表示中ã®é …ç›®:',
+ selectedItems: 'é¸æŠžã—ãŸé …ç›®:',
+ totalItems: 'é …ç›®ã®ç·æ•°:',
+ size: 'ページサイズ:',
+ first: '最åˆã®ãƒšãƒ¼ã‚¸',
+ next: '次ã®ãƒšãƒ¼ã‚¸',
+ previous: 'å‰ã®ãƒšãƒ¼ã‚¸',
+ last: 'å‰ã®ãƒšãƒ¼ã‚¸'
+ },
+ menu: {
+ text: '列ã®é¸æŠž:'
+ },
+ sort: {
+ ascending: '昇順ã«ä¸¦ã¹æ›¿ãˆ',
+ descending: 'é™é †ã«ä¸¦ã¹æ›¿ãˆ',
+ remove: '並ã¹æ›¿ãˆã®è§£é™¤'
+ },
+ column: {
+ hide: '列ã®éžè¡¨ç¤º'
+ },
+ aggregation: {
+ count: 'åˆè¨ˆè¡Œæ•°: ',
+ sum: 'åˆè¨ˆ: ',
+ avg: 'å¹³å‡: ',
+ min: '最å°: ',
+ max: '最大: '
+ },
+ pinning: {
+ pinLeft: 'å·¦ã«å›ºå®š',
+ pinRight: 'å³ã«å›ºå®š',
+ unpin: '固定解除'
+ },
+ gridMenu: {
+ columns: '列:',
+ importerTitle: 'ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ',
+ exporterAllAsCsv: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterVisibleAsCsv: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterSelectedAsCsv: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterAllAsPdf: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterVisibleAsPdf: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ exporterSelectedAsPdf: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
+ clearAllFilters: 'ã™ã¹ã¦ã®ãƒ•ã‚£ãƒ«ã‚¿ã‚’清掃ã—ã¦ãã ã•ã„'
+ },
+ importer: {
+ noHeaders: '列åã‚’å–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ noObjects: 'オブジェクトをå–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ä»¥å¤–ã®ãƒ‡ãƒ¼ã‚¿ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ invalidCsv: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªCSVå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ invalidJson: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªJSONå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
+ jsonNotArray: 'インãƒãƒ¼ãƒˆã—ãŸJSONファイルã«ã¯é…列ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚処ç†ã‚’中止ã—ã¾ã™ã€‚'
+ },
+ pagination: {
+ sizes: '項目/ページ',
+ totalItems: 'é …ç›®'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ko', {
+ aggregate: {
+ label: 'ì•„ì´í…œ'
+ },
+ groupPanel: {
+ description: '컬럼으로 그룹핑하기 위해서는 컬럼 í—¤ë”를 ëŒì–´ 떨어뜨려 주세요.'
+ },
+ search: {
+ placeholder: '검색...',
+ showingItems: '항목 보여주기:',
+ selectedItems: 'ì„ íƒ í•­ëª©:',
+ totalItems: '전체 항목:',
+ size: '페ì´ì§€ í¬ê¸°:',
+ first: '첫번째 페ì´ì§€',
+ next: 'ë‹¤ìŒ íŽ˜ì´ì§€',
+ previous: 'ì´ì „ 페ì´ì§€',
+ last: '마지막 페ì´ì§€'
+ },
+ menu: {
+ text: 'ì»¬ëŸ¼ì„ ì„ íƒí•˜ì„¸ìš”:'
+ },
+ sort: {
+ ascending: '오름차순 정렬',
+ descending: '내림차순 정렬',
+ remove: '소팅 제거'
+ },
+ column: {
+ hide: '컬럼 제거'
+ },
+ aggregation: {
+ count: '전체 갯수: ',
+ sum: 'ì „ì²´: ',
+ avg: 'í‰ê· : ',
+ min: '최소: ',
+ max: '최대: '
+ },
+ pinning: {
+ pinLeft: '왼쪽 핀',
+ pinRight: '오른쪽 핀',
+ unpin: '핀 제거'
+ },
+ gridMenu: {
+ columns: '컬럼:',
+ importerTitle: 'íŒŒì¼ ê°€ì ¸ì˜¤ê¸°',
+ exporterAllAsCsv: 'csvë¡œ 모든 ë°ì´í„° 내보내기',
+ exporterVisibleAsCsv: 'csvë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
+ exporterSelectedAsCsv: 'csvë¡œ ì„ íƒëœ ë°ì´í„° 내보내기',
+ exporterAllAsPdf: 'pdfë¡œ 모든 ë°ì´í„° 내보내기',
+ exporterVisibleAsPdf: 'pdfë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
+ exporterSelectedAsPdf: 'pdfë¡œ ì„ íƒ ë°ì´í„° 내보내기',
+ clearAllFilters: '모든 필터를 청소'
+ },
+ importer: {
+ noHeaders: 'ì»¬ëŸ¼ëª…ì´ ì§€ì •ë˜ì–´ 있지 않습니다. 파ì¼ì— í—¤ë”ê°€ 명시ë˜ì–´ 있는지 확ì¸í•´ 주세요.',
+ noObjects: 'ë°ì´í„°ê°€ 지정ë˜ì–´ 있지 않습니다. ë°ì´í„°ê°€ 파ì¼ì— 있는지 확ì¸í•´ 주세요.',
+ invalidCsv: '파ì¼ì„ 처리할 수 없습니다. 올바른 csvì¸ì§€ 확ì¸í•´ 주세요.',
+ invalidJson: '파ì¼ì„ 처리할 수 없습니다. 올바른 jsonì¸ì§€ 확ì¸í•´ 주세요.',
+ jsonNotArray: 'json 파ì¼ì€ ë°°ì—´ì„ í¬í•¨í•´ì•¼ 합니다.'
+ },
+ pagination: {
+ sizes: '페ì´ì§€ë‹¹ 항목',
+ totalItems: '전체 항목'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('nl', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Sleep hier een kolomnaam heen om op te groeperen.'
+ },
+ search: {
+ placeholder: 'Zoeken...',
+ showingItems: 'Getoonde items:',
+ selectedItems: 'Geselecteerde items:',
+ totalItems: 'Totaal aantal items:',
+ size: 'Items per pagina:',
+ first: 'Eerste pagina',
+ next: 'Volgende pagina',
+ previous: 'Vorige pagina',
+ last: 'Laatste pagina'
+ },
+ menu: {
+ text: 'Kies kolommen:'
+ },
+ sort: {
+ ascending: 'Sorteer oplopend',
+ descending: 'Sorteer aflopend',
+ remove: 'Verwijder sortering'
+ },
+ column: {
+ hide: 'Verberg kolom'
+ },
+ aggregation: {
+ count: 'Aantal rijen: ',
+ sum: 'Som: ',
+ avg: 'Gemiddelde: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Zet links vast',
+ pinRight: 'Zet rechts vast',
+ unpin: 'Maak los'
+ },
+ gridMenu: {
+ columns: 'Kolommen:',
+ importerTitle: 'Importeer bestand',
+ exporterAllAsCsv: 'Exporteer alle data als csv',
+ exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',
+ exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',
+ exporterAllAsPdf: 'Exporteer alle data als pdf',
+ exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',
+ exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf',
+ clearAllFilters: 'Reinig alle filters'
+ },
+ importer: {
+ noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',
+ noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',
+ invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',
+ invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',
+ jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'
+ },
+ pagination: {
+ sizes: 'items per pagina',
+ totalItems: 'items',
+ of: 'van de'
+ },
+ grouping: {
+ group: 'Groepeer',
+ ungroup: 'Groepering opheffen',
+ aggregate_count: 'Agg: Aantal',
+ aggregate_sum: 'Agg: Som',
+ aggregate_max: 'Agg: Max',
+ aggregate_min: 'Agg: Min',
+ aggregate_avg: 'Agg: Gem',
+ aggregate_remove: 'Agg: Verwijder'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('pt-br', {
+ aggregate: {
+ label: 'itens'
+ },
+ groupPanel: {
+ description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
+ },
+ search: {
+ placeholder: 'Procurar...',
+ showingItems: 'Mostrando os Itens:',
+ selectedItems: 'Items Selecionados:',
+ totalItems: 'Total de Itens:',
+ size: 'Tamanho da Página:',
+ first: 'Primeira Página',
+ next: 'Próxima Página',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Selecione as colunas:'
+ },
+ sort: {
+ ascending: 'Ordenar Ascendente',
+ descending: 'Ordenar Descendente',
+ remove: 'Remover Ordenação'
+ },
+ column: {
+ hide: 'Esconder coluna'
+ },
+ aggregation: {
+ count: 'total de linhas: ',
+ sum: 'total: ',
+ avg: 'med: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fixar Esquerda',
+ pinRight: 'Fixar Direita',
+ unpin: 'Desprender'
+ },
+ gridMenu: {
+ columns: 'Colunas:',
+ importerTitle: 'Importar arquivo',
+ exporterAllAsCsv: 'Exportar todos os dados como csv',
+ exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
+ exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
+ exporterAllAsPdf: 'Exportar todos os dados como pdf',
+ exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
+ exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
+ clearAllFilters: 'Limpar todos os filtros'
+ },
+ importer: {
+ noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',
+ noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',
+ invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',
+ invalidJson: 'Arquivo não pode ser processado. É um Json válido?',
+ jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'
+ },
+ pagination: {
+ sizes: 'itens por página',
+ totalItems: 'itens'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Contar',
+ aggregate_sum: 'Agr: Soma',
+ aggregate_max: 'Agr: Max',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Med',
+ aggregate_remove: 'Agr: Remover'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('pt', {
+ aggregate: {
+ label: 'itens'
+ },
+ groupPanel: {
+ description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
+ },
+ search: {
+ placeholder: 'Procurar...',
+ showingItems: 'Mostrando os Itens:',
+ selectedItems: 'Itens Selecionados:',
+ totalItems: 'Total de Itens:',
+ size: 'Tamanho da Página:',
+ first: 'Primeira Página',
+ next: 'Próxima Página',
+ previous: 'Página Anterior',
+ last: 'Última Página'
+ },
+ menu: {
+ text: 'Selecione as colunas:'
+ },
+ sort: {
+ ascending: 'Ordenar Ascendente',
+ descending: 'Ordenar Descendente',
+ remove: 'Remover Ordenação'
+ },
+ column: {
+ hide: 'Esconder coluna'
+ },
+ aggregation: {
+ count: 'total de linhas: ',
+ sum: 'total: ',
+ avg: 'med: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ pinning: {
+ pinLeft: 'Fixar Esquerda',
+ pinRight: 'Fixar Direita',
+ unpin: 'Desprender'
+ },
+ gridMenu: {
+ columns: 'Colunas:',
+ importerTitle: 'Importar ficheiro',
+ exporterAllAsCsv: 'Exportar todos os dados como csv',
+ exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
+ exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
+ exporterAllAsPdf: 'Exportar todos os dados como pdf',
+ exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
+ exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
+ clearAllFilters: 'Limpar todos os filtros'
+ },
+ importer: {
+ noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',
+ noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',
+ invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',
+ invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',
+ jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'
+ },
+ pagination: {
+ sizes: 'itens por página',
+ totalItems: 'itens',
+ of: 'de'
+ },
+ grouping: {
+ group: 'Agrupar',
+ ungroup: 'Desagrupar',
+ aggregate_count: 'Agr: Contar',
+ aggregate_sum: 'Agr: Soma',
+ aggregate_max: 'Agr: Max',
+ aggregate_min: 'Agr: Min',
+ aggregate_avg: 'Agr: Med',
+ aggregate_remove: 'Agr: Remover'
+ }
+ });
+ return $delegate;
+ }]);
+}]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ru', {
+ aggregate: {
+ label: 'Ñлементы'
+ },
+ groupPanel: {
+ description: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ по Ñтолбцу перетащите Ñюда его название.'
+ },
+ search: {
+ placeholder: 'ПоиÑк...',
+ showingItems: 'Показать Ñлементы:',
+ selectedItems: 'Выбранные Ñлементы:',
+ totalItems: 'Ð’Ñего Ñлементов:',
+ size: 'Размер Ñтраницы:',
+ first: 'ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница',
+ next: 'Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница',
+ previous: 'ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница',
+ last: 'ПоÑледнÑÑ Ñтраница'
+ },
+ menu: {
+ text: 'Выбрать Ñтолбцы:'
+ },
+ sort: {
+ ascending: 'По возраÑтанию',
+ descending: 'По убыванию',
+ remove: 'Убрать Ñортировку'
+ },
+ column: {
+ hide: 'СпрÑтать Ñтолбец'
+ },
+ aggregation: {
+ count: 'вÑего Ñтрок: ',
+ sum: 'итого: ',
+ avg: 'Ñреднее: ',
+ min: 'мин: ',
+ max: 'макÑ: '
+ },
+ pinning: {
+ pinLeft: 'Закрепить Ñлева',
+ pinRight: 'Закрепить Ñправа',
+ unpin: 'Открепить'
+ },
+ gridMenu: {
+ columns: 'Столбцы:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'ЭкÑпортировать вÑÑ‘ в CSV',
+ exporterVisibleAsCsv: 'ЭкÑпортировать видимые данные в CSV',
+ exporterSelectedAsCsv: 'ЭкÑпортировать выбранные данные в CSV',
+ exporterAllAsPdf: 'ЭкÑпортировать вÑÑ‘ в PDF',
+ exporterVisibleAsPdf: 'ЭкÑпортировать видимые данные в PDF',
+ exporterSelectedAsPdf: 'ЭкÑпортировать выбранные данные в PDF',
+ clearAllFilters: 'ОчиÑтите вÑе фильтры'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('sk', {
+ aggregate: {
+ label: 'items'
+ },
+ groupPanel: {
+ description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'
+ },
+ search: {
+ placeholder: 'Hľadaj...',
+ showingItems: 'Zobrazujem položky:',
+ selectedItems: 'Vybraté položky:',
+ totalItems: 'PoÄet položiek:',
+ size: 'PoÄet:',
+ first: 'Prvá strana',
+ next: 'Ďalšia strana',
+ previous: 'Predchádzajúca strana',
+ last: 'Posledná strana'
+ },
+ menu: {
+ text: 'Vyberte stĺpce:'
+ },
+ sort: {
+ ascending: 'Zotriediť vzostupne',
+ descending: 'Zotriediť zostupne',
+ remove: 'Vymazať triedenie'
+ },
+ aggregation: {
+ count: 'total rows: ',
+ sum: 'total: ',
+ avg: 'avg: ',
+ min: 'min: ',
+ max: 'max: '
+ },
+ gridMenu: {
+ columns: 'Columns:',
+ importerTitle: 'Import file',
+ exporterAllAsCsv: 'Export all data as csv',
+ exporterVisibleAsCsv: 'Export visible data as csv',
+ exporterSelectedAsCsv: 'Export selected data as csv',
+ exporterAllAsPdf: 'Export all data as pdf',
+ exporterVisibleAsPdf: 'Export visible data as pdf',
+ exporterSelectedAsPdf: 'Export selected data as pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'Column names were unable to be derived, does the file have a header?',
+ noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
+ invalidCsv: 'File was unable to be processed, is it valid CSV?',
+ invalidJson: 'File was unable to be processed, is it valid Json?',
+ jsonNotArray: 'Imported json file must contain an array, aborting.'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('sv', {
+ aggregate: {
+ label: 'Artiklar'
+ },
+ groupPanel: {
+ description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'
+ },
+ search: {
+ placeholder: 'Sök...',
+ showingItems: 'Visar artiklar:',
+ selectedItems: 'Valda artiklar:',
+ totalItems: 'Antal artiklar:',
+ size: 'Sidstorlek:',
+ first: 'Första sidan',
+ next: 'Nästa sida',
+ previous: 'Föregående sida',
+ last: 'Sista sidan'
+ },
+ menu: {
+ text: 'Välj kolumner:'
+ },
+ sort: {
+ ascending: 'Sortera stigande',
+ descending: 'Sortera fallande',
+ remove: 'Inaktivera sortering'
+ },
+ column: {
+ hide: 'Göm kolumn'
+ },
+ aggregation: {
+ count: 'Antal rader: ',
+ sum: 'Summa: ',
+ avg: 'Genomsnitt: ',
+ min: 'Min: ',
+ max: 'Max: '
+ },
+ pinning: {
+ pinLeft: 'Fäst vänster',
+ pinRight: 'Fäst höger',
+ unpin: 'Lösgör'
+ },
+ gridMenu: {
+ columns: 'Kolumner:',
+ importerTitle: 'Importera fil',
+ exporterAllAsCsv: 'Exportera all data som CSV',
+ exporterVisibleAsCsv: 'Exportera synlig data som CSV',
+ exporterSelectedAsCsv: 'Exportera markerad data som CSV',
+ exporterAllAsPdf: 'Exportera all data som PDF',
+ exporterVisibleAsPdf: 'Exportera synlig data som PDF',
+ exporterSelectedAsPdf: 'Exportera markerad data som PDF',
+ clearAllFilters: 'Rengör alla filter'
+ },
+ importer: {
+ noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',
+ noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',
+ invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',
+ invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',
+ jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'
+ },
+ pagination: {
+ sizes: 'Artiklar per sida',
+ totalItems: 'Artiklar'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function () {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('ta', {
+ aggregate: {
+ label: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯'
+ },
+ groupPanel: {
+ description: 'ஒர௠பதà¯à®¤à®¿à®¯à¯ˆ கà¯à®´à¯à®µà®¾à®• அமைகà¯à®• அபà¯à®ªà®¤à¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯ˆ இஙà¯à®•à¯‡ இழà¯à®¤à¯à®¤à¯ வரவà¯à®®à¯ '
+ },
+ search: {
+ placeholder: 'தேடல௠...',
+ showingItems: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ˆ காணà¯à®ªà®¿à®¤à¯à®¤à®²à¯:',
+ selectedItems: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
+ totalItems: 'மொதà¯à®¤ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
+ size: 'பகà¯à®• அளவà¯: ',
+ first: 'à®®à¯à®¤à®²à¯ பகà¯à®•à®®à¯',
+ next: 'அடà¯à®¤à¯à®¤ பகà¯à®•à®®à¯',
+ previous: 'à®®à¯à®¨à¯à®¤à¯ˆà®¯ பகà¯à®•à®®à¯ ',
+ last: 'இறà¯à®¤à®¿ பகà¯à®•à®®à¯'
+ },
+ menu: {
+ text: 'பதà¯à®¤à®¿à®•à®³à¯ˆ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯:'
+ },
+ sort: {
+ ascending: 'மேலிரà¯à®¨à¯à®¤à¯ கீழாக',
+ descending: 'கீழிரà¯à®¨à¯à®¤à¯ மேலாக',
+ remove: 'வரிசையை நீகà¯à®•à¯'
+ },
+ column: {
+ hide: 'பதà¯à®¤à®¿à®¯à¯ˆ மறைதà¯à®¤à¯ வை '
+ },
+ aggregation: {
+ count: 'மொதà¯à®¤ வரிகளà¯:',
+ sum: 'மொதà¯à®¤à®®à¯: ',
+ avg: 'சராசரி: ',
+ min: 'கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®š: ',
+ max: 'அதிகபடà¯à®š: '
+ },
+ pinning: {
+ pinLeft: 'இடதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®• ',
+ pinRight: 'வலதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®•',
+ unpin: 'பிரி'
+ },
+ gridMenu: {
+ columns: 'பதà¯à®¤à®¿à®•à®³à¯:',
+ importerTitle: 'கோபà¯à®ªà¯ : படிதà¯à®¤à®²à¯',
+ exporterAllAsCsv: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterVisibleAsCsv: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterSelectedAsCsv: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
+ exporterAllAsPdf: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ exporterVisibleAsPdf: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ exporterSelectedAsPdf: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
+ clearAllFilters: 'Clear all filters'
+ },
+ importer: {
+ noHeaders: 'பதà¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ பெற இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà®¿à®±à¯à®•à¯ தலைபà¯à®ªà¯ உளà¯à®³à®¤à®¾?',
+ noObjects: 'இலகà¯à®•à¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ, கோபà¯à®ªà®¿à®²à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ தவிர தரவ௠à®à®¤à¯‡à®©à¯à®®à¯ உளà¯à®³à®¤à®¾? ',
+ invalidCsv: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - csv',
+ invalidJson: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - json',
+ jsonNotArray: 'படிதà¯à®¤ கோபà¯à®ªà®¿à®²à¯ வரிசைகள௠உளà¯à®³à®¤à¯, நடைமà¯à®±à¯ˆ ரதà¯à®¤à¯ செய௠: json'
+ },
+ pagination: {
+ sizes : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ / பகà¯à®•à®®à¯',
+ totalItems : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ '
+ },
+ grouping: {
+ group : 'கà¯à®´à¯',
+ ungroup : 'பிரி',
+ aggregate_count : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : எணà¯à®£à¯',
+ aggregate_sum : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கூடà¯à®Ÿà®²à¯',
+ aggregate_max : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : அதிகபடà¯à®šà®®à¯',
+ aggregate_min : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯',
+ aggregate_avg : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : சராசரி',
+ aggregate_remove : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : நீகà¯à®•à¯'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+/**
+ * @ngdoc overview
+ * @name ui.grid.i18n
+ * @description
+ *
+ * # ui.grid.i18n
+ * This module provides i18n functions to ui.grid and any application that wants to use it
+
+ *
+ * <div doc-module-components="ui.grid.i18n"></div>
+ */
+
+(function () {
+ var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];
+ var FILTER_ALIASES = ['t', 'uiTranslate'];
+
+ var module = angular.module('ui.grid.i18n');
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.i18n.constant:i18nConstants
+ *
+ * @description constants available in i18n module
+ */
+ module.constant('i18nConstants', {
+ MISSING: '[MISSING]',
+ UPDATE_EVENT: '$uiI18n',
+
+ LOCALE_DIRECTIVE_ALIAS: 'uiI18n',
+ // default to english
+ DEFAULT_LANG: 'en'
+ });
+
+// module.config(['$provide', function($provide) {
+// $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.i18n.service:i18nService
+ *
+ * @description Services for i18n
+ */
+ module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',
+ function ($log, i18nConstants, $rootScope) {
+
+ var langCache = {
+ _langs: {},
+ current: null,
+ get: function (lang) {
+ return this._langs[lang.toLowerCase()];
+ },
+ add: function (lang, strings) {
+ var lower = lang.toLowerCase();
+ if (!this._langs[lower]) {
+ this._langs[lower] = {};
+ }
+ angular.extend(this._langs[lower], strings);
+ },
+ getAllLangs: function () {
+ var langs = [];
+ if (!this._langs) {
+ return langs;
+ }
+
+ for (var key in this._langs) {
+ langs.push(key);
+ }
+
+ return langs;
+ },
+ setCurrent: function (lang) {
+ this.current = lang.toLowerCase();
+ },
+ getCurrentLang: function () {
+ return this.current;
+ }
+ };
+
+ var service = {
+
+ /**
+ * @ngdoc service
+ * @name add
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description Adds the languages and strings to the cache. Decorate this service to
+ * add more translation strings
+ * @param {string} lang language to add
+ * @param {object} stringMaps of strings to add grouped by property names
+ * @example
+ * <pre>
+ * i18nService.add('en', {
+ * aggregate: {
+ * label1: 'items',
+ * label2: 'some more items'
+ * }
+ * },
+ * groupPanel: {
+ * description: 'Drag a column header here and drop it to group by that column.'
+ * }
+ * }
+ * </pre>
+ */
+ add: function (langs, stringMaps) {
+ if (typeof(langs) === 'object') {
+ angular.forEach(langs, function (lang) {
+ if (lang) {
+ langCache.add(lang, stringMaps);
+ }
+ });
+ } else {
+ langCache.add(langs, stringMaps);
+ }
+ },
+
+ /**
+ * @ngdoc service
+ * @name getAllLangs
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description return all currently loaded languages
+ * @returns {array} string
+ */
+ getAllLangs: function () {
+ return langCache.getAllLangs();
+ },
+
+ /**
+ * @ngdoc service
+ * @name get
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description return all currently loaded languages
+ * @param {string} lang to return. If not specified, returns current language
+ * @returns {object} the translation string maps for the language
+ */
+ get: function (lang) {
+ var language = lang ? lang : service.getCurrentLang();
+ return langCache.get(language);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getSafeText
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description returns the text specified in the path or a Missing text if text is not found
+ * @param {string} path property path to use for retrieving text from string map
+ * @param {string} lang to return. If not specified, returns current language
+ * @returns {object} the translation for the path
+ * @example
+ * <pre>
+ * i18nService.getSafeText('sort.ascending')
+ * </pre>
+ */
+ getSafeText: function (path, lang) {
+ var language = lang ? lang : service.getCurrentLang();
+ var trans = langCache.get(language);
+
+ if (!trans) {
+ return i18nConstants.MISSING;
+ }
+
+ var paths = path.split('.');
+ var current = trans;
+
+ for (var i = 0; i < paths.length; ++i) {
+ if (current[paths[i]] === undefined || current[paths[i]] === null) {
+ return i18nConstants.MISSING;
+ } else {
+ current = current[paths[i]];
+ }
+ }
+
+ return current;
+
+ },
+
+ /**
+ * @ngdoc service
+ * @name setCurrentLang
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description sets the current language to use in the application
+ * $broadcasts the Update_Event on the $rootScope
+ * @param {string} lang to set
+ * @example
+ * <pre>
+ * i18nService.setCurrentLang('fr');
+ * </pre>
+ */
+
+ setCurrentLang: function (lang) {
+ if (lang) {
+ langCache.setCurrent(lang);
+ $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);
+ }
+ },
+
+ /**
+ * @ngdoc service
+ * @name getCurrentLang
+ * @methodOf ui.grid.i18n.service:i18nService
+ * @description returns the current language used in the application
+ */
+ getCurrentLang: function () {
+ var lang = langCache.getCurrentLang();
+ if (!lang) {
+ lang = i18nConstants.DEFAULT_LANG;
+ langCache.setCurrent(lang);
+ }
+ return lang;
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ var localeDirective = function (i18nService, i18nConstants) {
+ return {
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;
+ // check for watchable property
+ var lang = $scope.$eval($attrs[alias]);
+ if (lang) {
+ $scope.$watch($attrs[alias], function () {
+ i18nService.setCurrentLang(lang);
+ });
+ } else if ($attrs.$$observers) {
+ $attrs.$observe(alias, function () {
+ i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);
+ });
+ }
+ }
+ };
+ }
+ };
+ };
+
+ module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);
+
+ // directive syntax
+ var uitDirective = function ($parse, i18nService, i18nConstants) {
+ return {
+ restrict: 'EA',
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+ var alias1 = DIRECTIVE_ALIASES[0],
+ alias2 = DIRECTIVE_ALIASES[1];
+ var token = $attrs[alias1] || $attrs[alias2] || $elm.html();
+ var missing = i18nConstants.MISSING + token;
+ var observer;
+ if ($attrs.$$observers) {
+ var prop = $attrs[alias1] ? alias1 : alias2;
+ observer = $attrs.$observe(prop, function (result) {
+ if (result) {
+ $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);
+ }
+ });
+ }
+ var getter = $parse(token);
+ var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {
+ if (observer) {
+ observer($attrs[alias1] || $attrs[alias2]);
+ } else {
+ // set text based on i18n current language
+ $elm.html(getter(i18nService.get()) || missing);
+ }
+ });
+ $scope.$on('$destroy', listener);
+
+ $elm.html(getter(i18nService.get()) || missing);
+ }
+ };
+ }
+ };
+ };
+
+ angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {
+ module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );
+ } );
+
+ // optional filter syntax
+ var uitFilter = function ($parse, i18nService, i18nConstants) {
+ return function (data) {
+ var getter = $parse(data);
+ // set text based on i18n current language
+ return getter(i18nService.get()) || i18nConstants.MISSING + data;
+ };
+ };
+
+ angular.forEach( FILTER_ALIASES, function ( alias ) {
+ module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );
+ } );
+
+
+})();
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('zh-cn', {
+ headerCell: {
+ aria: {
+ defaultFilterLabel: '列过滤器',
+ removeFilter: '移除过滤器',
+ columnMenuButtonLabel: '列èœå•'
+ },
+ priority: '优先级:',
+ filterLabel: "列过滤器: "
+ },
+ aggregate: {
+ label: '行'
+ },
+ groupPanel: {
+ description: '拖曳表头到此处进行分组'
+ },
+ search: {
+ placeholder: '查找',
+ showingItems: '已显示行数:',
+ selectedItems: '已选择行数:',
+ totalItems: '总行数:',
+ size: 'æ¯é¡µæ˜¾ç¤ºè¡Œæ•°ï¼š',
+ first: '首页',
+ next: '下一页',
+ previous: '上一页',
+ last: '末页'
+ },
+ menu: {
+ text: '选择列:'
+ },
+ sort: {
+ ascending: 'å‡åº',
+ descending: 'é™åº',
+ none: 'æ— åº',
+ remove: 'å–消排åº'
+ },
+ column: {
+ hide: 'éšè—列'
+ },
+ aggregation: {
+ count: '计数:',
+ sum: '求和:',
+ avg: 'å‡å€¼ï¼š',
+ min: '最å°å€¼ï¼š',
+ max: '最大值:'
+ },
+ pinning: {
+ pinLeft: '左侧固定',
+ pinRight: 'å³ä¾§å›ºå®š',
+ unpin: 'å–消固定'
+ },
+ columnMenu: {
+ close: '关闭'
+ },
+ gridMenu: {
+ aria: {
+ buttonLabel: '表格èœå•'
+ },
+ columns: '列:',
+ importerTitle: '导入文件',
+ exporterAllAsCsv: '导出全部数æ®åˆ°CSV',
+ exporterVisibleAsCsv: '导出å¯è§æ•°æ®åˆ°CSV',
+ exporterSelectedAsCsv: '导出已选数æ®åˆ°CSV',
+ exporterAllAsPdf: '导出全部数æ®åˆ°PDF',
+ exporterVisibleAsPdf: '导出å¯è§æ•°æ®åˆ°PDF',
+ exporterSelectedAsPdf: '导出已选数æ®åˆ°PDF',
+ clearAllFilters: '清除所有过滤器'
+ },
+ importer: {
+ noHeaders: '无法获å–列å,确定文件包å«è¡¨å¤´ï¼Ÿ',
+ noObjects: '无法获å–æ•°æ®ï¼Œç¡®å®šæ–‡ä»¶åŒ…å«æ•°æ®ï¼Ÿ',
+ invalidCsv: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„CSV文件?',
+ invalidJson: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„JSON文件?',
+ jsonNotArray: '导入的文件ä¸æ˜¯JSON数组ï¼'
+ },
+ pagination: {
+ aria: {
+ pageToFirst: '第一页',
+ pageBack: '上一页',
+ pageSelected: '当å‰é¡µ',
+ pageForward: '下一页',
+ pageToLast: '最åŽä¸€é¡µ'
+ },
+ sizes: 'è¡Œæ¯é¡µ',
+ totalItems: '行',
+ through: '至',
+ of: 'å…±'
+ },
+ grouping: {
+ group: '分组',
+ ungroup: 'å–消分组',
+ aggregate_count: 'åˆè®¡: 计数',
+ aggregate_sum: 'åˆè®¡: 求和',
+ aggregate_max: 'åˆè®¡: 最大',
+ aggregate_min: 'åˆè®¡: 最å°',
+ aggregate_avg: 'åˆè®¡: å¹³å‡',
+ aggregate_remove: 'åˆè®¡: 移除'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('i18nService', ['$delegate', function($delegate) {
+ $delegate.add('zh-tw', {
+ aggregate: {
+ label: '行'
+ },
+ groupPanel: {
+ description: '拖曳表頭到此處進行分組'
+ },
+ search: {
+ placeholder: '查找',
+ showingItems: '已顯示行數:',
+ selectedItems: 'å·²é¸æ“‡è¡Œæ•¸ï¼š',
+ totalItems: '總行數:',
+ size: 'æ¯é é¡¯ç¤ºè¡Œæ•¸ï¼š',
+ first: '首é ',
+ next: '下壹é ',
+ previous: '上壹é ',
+ last: '末é '
+ },
+ menu: {
+ text: 'é¸æ“‡åˆ—:'
+ },
+ sort: {
+ ascending: 'å‡åº',
+ descending: 'é™åº',
+ remove: 'å–消排åº'
+ },
+ column: {
+ hide: 'éš±è—列'
+ },
+ aggregation: {
+ count: '計數:',
+ sum: '求和:',
+ avg: 'å‡å€¼ï¼š',
+ min: '最å°å€¼ï¼š',
+ max: '最大值:'
+ },
+ pinning: {
+ pinLeft: 'å·¦å´å›ºå®š',
+ pinRight: 'å³å´å›ºå®š',
+ unpin: 'å–消固定'
+ },
+ gridMenu: {
+ columns: '列:',
+ importerTitle: '導入文件',
+ exporterAllAsCsv: '導出全部數據到CSV',
+ exporterVisibleAsCsv: '導出å¯è¦‹æ•¸æ“šåˆ°CSV',
+ exporterSelectedAsCsv: '導出已é¸æ•¸æ“šåˆ°CSV',
+ exporterAllAsPdf: '導出全部數據到PDF',
+ exporterVisibleAsPdf: '導出å¯è¦‹æ•¸æ“šåˆ°PDF',
+ exporterSelectedAsPdf: '導出已é¸æ•¸æ“šåˆ°PDF',
+ clearAllFilters: '清除所有过滤器'
+ },
+ importer: {
+ noHeaders: '無法ç²å–列å,確定文件包å«è¡¨é ­ï¼Ÿ',
+ noObjects: '無法ç²å–數據,確定文件包å«æ•¸æ“šï¼Ÿ',
+ invalidCsv: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„CSV文件?',
+ invalidJson: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„JSON文件?',
+ jsonNotArray: '導入的文件ä¸æ˜¯JSON數組ï¼'
+ },
+ pagination: {
+ sizes: 'è¡Œæ¯é ',
+ totalItems: '行'
+ }
+ });
+ return $delegate;
+ }]);
+ }]);
+})();
+
+(function() {
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.autoResize
+ *
+ * @description
+ *
+ * #ui.grid.autoResize
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides auto-resizing functionality to UI-Grid.
+ */
+ var module = angular.module('ui.grid.autoResize', ['ui.grid']);
+
+
+ module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {
+ return {
+ require: 'uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var prevGridWidth, prevGridHeight;
+
+ function getDimensions() {
+ prevGridHeight = gridUtil.elementHeight($elm);
+ prevGridWidth = gridUtil.elementWidth($elm);
+ }
+
+ // Initialize the dimensions
+ getDimensions();
+
+ var resizeTimeoutId;
+ function startTimeout() {
+ clearTimeout(resizeTimeoutId);
+
+ resizeTimeoutId = setTimeout(function () {
+ var newGridHeight = gridUtil.elementHeight($elm);
+ var newGridWidth = gridUtil.elementWidth($elm);
+
+ if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {
+ uiGridCtrl.grid.gridHeight = newGridHeight;
+ uiGridCtrl.grid.gridWidth = newGridWidth;
+
+ $scope.$apply(function () {
+ uiGridCtrl.grid.refresh()
+ .then(function () {
+ getDimensions();
+
+ startTimeout();
+ });
+ });
+ }
+ else {
+ startTimeout();
+ }
+ }, 250);
+ }
+
+ startTimeout();
+
+ $scope.$on('$destroy', function() {
+ clearTimeout(resizeTimeoutId);
+ });
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.cellNav
+ *
+ * @description
+
+ #ui.grid.cellNav
+
+ <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+
+ This module provides auto-resizing functionality to UI-Grid.
+ */
+ var module = angular.module('ui.grid.cellNav', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.constant:uiGridCellNavConstants
+ *
+ * @description constants available in cellNav
+ */
+ module.constant('uiGridCellNavConstants', {
+ FEATURE_NAME: 'gridCellNav',
+ CELL_NAV_EVENT: 'cellNav',
+ direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},
+ EVENT_TYPE: {
+ KEYDOWN: 0,
+ CLICK: 1,
+ CLEAR: 2
+ }
+ });
+
+
+ module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'GridRowColumn', '$q',
+ function (gridUtil, uiGridConstants, uiGridCellNavConstants, GridRowColumn, $q) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.object:CellNav
+ * @description returns a CellNav prototype function
+ * @param {object} rowContainer container for rows
+ * @param {object} colContainer parent column container
+ * @param {object} leftColContainer column container to the left of parent
+ * @param {object} rightColContainer column container to the right of parent
+ */
+ var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {
+ this.rows = rowContainer.visibleRowCache;
+ this.columns = colContainer.visibleColumnCache;
+ this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];
+ this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];
+ this.bodyContainer = rowContainer;
+ };
+
+ /** returns focusable columns of all containers */
+ UiGridCellNav.prototype.getFocusableCols = function () {
+ var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);
+
+ return allColumns.filter(function (col) {
+ return col.colDef.allowCellFocus;
+ });
+ };
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:GridRow
+ *
+ * @description GridRow settings for cellNav feature, these are available to be
+ * set only internally (for example, by other features)
+ */
+
+ /**
+ * @ngdoc object
+ * @name allowCellFocus
+ * @propertyOf ui.grid.cellNav.api:GridRow
+ * @description Enable focus on a cell within this row. If set to false then no cells
+ * in this row can be focused - group header rows as an example would set this to false.
+ * <br/>Defaults to true
+ */
+ /** returns focusable rows */
+ UiGridCellNav.prototype.getFocusableRows = function () {
+ return this.rows.filter(function(row) {
+ return row.allowCellFocus !== false;
+ });
+ };
+
+ UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {
+ switch (direction) {
+ case uiGridCellNavConstants.direction.LEFT:
+ return this.getRowColLeft(curRow, curCol);
+ case uiGridCellNavConstants.direction.RIGHT:
+ return this.getRowColRight(curRow, curCol);
+ case uiGridCellNavConstants.direction.UP:
+ return this.getRowColUp(curRow, curCol);
+ case uiGridCellNavConstants.direction.DOWN:
+ return this.getRowColDown(curRow, curCol);
+ case uiGridCellNavConstants.direction.PG_UP:
+ return this.getRowColPageUp(curRow, curCol);
+ case uiGridCellNavConstants.direction.PG_DOWN:
+ return this.getRowColPageDown(curRow, curCol);
+ }
+
+ };
+
+ UiGridCellNav.prototype.initializeSelection = function () {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ if (focusableCols.length === 0 || focusableRows.length === 0) {
+ return null;
+ }
+
+ var curRowIndex = 0;
+ var curColIndex = 0;
+ return new GridRowColumn(focusableRows[0], focusableCols[0]); //return same row
+ };
+
+ UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 1
+ if (curColIndex === -1) {
+ curColIndex = 1;
+ }
+
+ var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;
+
+ //get column to left
+ if (nextColIndex > curColIndex) {
+ // On the first row
+ // if (curRowIndex === 0 && curColIndex === 0) {
+ // return null;
+ // }
+ if (curRowIndex === 0) {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
+ }
+ else {
+ //up one row and far right column
+ return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);
+ }
+ }
+ else {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]);
+ }
+ };
+
+
+
+ UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+ var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;
+
+ if (nextColIndex < curColIndex) {
+ if (curRowIndex === focusableRows.length - 1) {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
+ }
+ else {
+ //down one row and far left column
+ return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);
+ }
+ }
+ else {
+ return new GridRowColumn(curRow, focusableCols[nextColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ if (curRowIndex === focusableRows.length - 1) {
+ return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
+ }
+ else {
+ //down one row
+ return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ var pageSize = this.bodyContainer.minRowsToRender();
+ if (curRowIndex >= focusableRows.length - pageSize) {
+ return new GridRowColumn(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row
+ }
+ else {
+ //down one page
+ return new GridRowColumn(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ if (curRowIndex === 0) {
+ return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
+ }
+ else {
+ //up one row
+ return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);
+ }
+ };
+
+ UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {
+ var focusableCols = this.getFocusableCols();
+ var focusableRows = this.getFocusableRows();
+ var curColIndex = focusableCols.indexOf(curCol);
+ var curRowIndex = focusableRows.indexOf(curRow);
+
+ //could not find column in focusable Columns so set it to 0
+ if (curColIndex === -1) {
+ curColIndex = 0;
+ }
+
+ var pageSize = this.bodyContainer.minRowsToRender();
+ if (curRowIndex - pageSize < 0) {
+ return new GridRowColumn(focusableRows[0], focusableCols[curColIndex]); //return first row
+ }
+ else {
+ //up one page
+ return new GridRowColumn(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);
+ }
+ };
+ return UiGridCellNav;
+ }]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.cellNav.service:uiGridCellNavService
+ *
+ * @description Services for cell navigation features. If you don't like the key maps we use,
+ * or the direction cells navigation, override with a service decorator (see angular docs)
+ */
+ module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'GridRowColumn', 'ScrollEvent',
+ function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, GridRowColumn, ScrollEvent) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+ grid.registerColumnBuilder(service.cellNavColumnBuilder);
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav:Grid.cellNav
+ * @description cellNav properties added to grid class
+ */
+ grid.cellNav = {};
+ grid.cellNav.lastRowCol = null;
+ grid.cellNav.focusedCells = [];
+
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:PublicApi
+ *
+ * @description Public Api for cellNav feature
+ */
+ var publicApi = {
+ events: {
+ cellNav: {
+ /**
+ * @ngdoc event
+ * @name navigate
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description raised when the active cell is changed
+ * <pre>
+ * gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})
+ * </pre>
+ * @param {object} newRowCol new position
+ * @param {object} oldRowCol old position
+ */
+ navigate: function (newRowCol, oldRowCol) {},
+ /**
+ * @ngdoc event
+ * @name viewPortKeyDown
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid
+ * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
+ * event whenever you need a keydown event on a cell
+ * <br/>
+ * @param {object} event keydown event
+ * @param {object} rowCol current rowCol position
+ */
+ viewPortKeyDown: function (event, rowCol) {},
+
+ /**
+ * @ngdoc event
+ * @name viewPortKeyPress
+ * @eventOf ui.grid.cellNav.api:PublicApi
+ * @description is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid
+ * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
+ * event whenever you need a keypress event on a cell
+ * <br/>
+ * @param {object} event keypress event
+ * @param {object} rowCol current rowCol position
+ */
+ viewPortKeyPress: function (event, rowCol) {}
+ }
+ },
+ methods: {
+ cellNav: {
+ /**
+ * @ngdoc function
+ * @name scrollToFocus
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description brings the specified row and column into view, and sets focus
+ * to that cell
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus
+ * @param {object} colDef to make visible and set focus
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ scrollToFocus: function (rowEntity, colDef) {
+ return service.scrollToFocus(grid, rowEntity, colDef);
+ },
+
+ /**
+ * @ngdoc function
+ * @name getFocusedCell
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns the current (or last if Grid does not have focus) focused row and column
+ * <br> value is null if no selection has occurred
+ */
+ getFocusedCell: function () {
+ return grid.cellNav.lastRowCol;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getCurrentSelection
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns an array containing the current selection
+ * <br> array is empty if no selection has occurred
+ */
+ getCurrentSelection: function () {
+ return grid.cellNav.focusedCells;
+ },
+
+ /**
+ * @ngdoc function
+ * @name rowColSelectIndex
+ * @methodOf ui.grid.cellNav.api:PublicApi
+ * @description returns the index in the order in which the GridRowColumn was selected, returns -1 if the GridRowColumn
+ * isn't selected
+ * @param {object} rowCol the rowCol to evaluate
+ */
+ rowColSelectIndex: function (rowCol) {
+ //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&
+ var index = -1;
+ for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {
+ if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&
+ grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:GridOptions
+ *
+ * @description GridOptions for cellNav feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name modifierKeysToMultiSelectCells
+ * @propertyOf ui.grid.cellNav.api:GridOptions
+ * @description Enable multiple cell selection only when using the ctrlKey or shiftKey.
+ * <br/>Defaults to false
+ */
+ gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;
+
+ },
+
+ /**
+ * @ngdoc service
+ * @name decorateRenderContainers
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description decorates grid renderContainers with cellNav functions
+ */
+ decorateRenderContainers: function (grid) {
+
+ var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;
+ var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;
+
+ if (leftContainer !== null) {
+ grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);
+ }
+ if (rightContainer !== null) {
+ grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);
+ }
+
+ grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);
+ },
+
+ /**
+ * @ngdoc service
+ * @name getDirection
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description determines which direction to for a given keyDown event
+ * @returns {uiGridCellNavConstants.direction} direction
+ */
+ getDirection: function (evt) {
+ if (evt.keyCode === uiGridConstants.keymap.LEFT ||
+ (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {
+ return uiGridCellNavConstants.direction.LEFT;
+ }
+ if (evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.TAB) {
+ return uiGridCellNavConstants.direction.RIGHT;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.UP ||
+ (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {
+ return uiGridCellNavConstants.direction.UP;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.PG_UP){
+ return uiGridCellNavConstants.direction.PG_UP;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.DOWN ||
+ evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {
+ return uiGridCellNavConstants.direction.DOWN;
+ }
+
+ if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){
+ return uiGridCellNavConstants.direction.PG_DOWN;
+ }
+
+ return null;
+ },
+
+ /**
+ * @ngdoc service
+ * @name cellNavColumnBuilder
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @description columnBuilder function that adds cell navigation properties to grid column
+ * @returns {promise} promise that will load any needed templates when resolved
+ */
+ cellNavColumnBuilder: function (colDef, col, gridOptions) {
+ var promises = [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.cellNav.api:ColumnDef
+ *
+ * @description Column Definitions for cellNav feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name allowCellFocus
+ * @propertyOf ui.grid.cellNav.api:ColumnDef
+ * @description Enable focus on a cell within this column.
+ * <br/>Defaults to true
+ */
+ colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;
+
+ return $q.all(promises);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @name scrollToFocus
+ * @description Scroll the grid such that the specified
+ * row and column is in view, and set focus to the cell in that row and column
+ * @param {Grid} grid the grid you'd like to act upon, usually available
+ * from gridApi.grid
+ * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to
+ * @param {object} colDef to make visible and set focus to
+ * @returns {promise} a promise that is resolved after any scrolling is finished
+ */
+ scrollToFocus: function (grid, rowEntity, colDef) {
+ var gridRow = null, gridCol = null;
+
+ if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {
+ gridRow = grid.getRow(rowEntity);
+ }
+
+ if (typeof(colDef) !== 'undefined' && colDef !== null) {
+ gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);
+ }
+ return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {
+ var rowCol = { row: gridRow, col: gridCol };
+
+ // Broadcast the navigation
+ if (gridRow !== null && gridCol !== null) {
+ grid.cellNav.broadcastCellNav(rowCol);
+ }
+ });
+
+
+
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.cellNav.service:uiGridCellNavService
+ * @name getLeftWidth
+ * @description Get the current drawn width of the columns in the
+ * grid up to the numbered column, and add an apportionment for the
+ * column that we're on. So if we are on column 0, we want to scroll
+ * 0% (i.e. exclude this column from calc). If we're on the last column
+ * we want to scroll to 100% (i.e. include this column in the calc). So
+ * we include (thisColIndex / totalNumberCols) % of this column width
+ * @param {Grid} grid the grid you'd like to act upon, usually available
+ * from gridApi.grid
+ * @param {gridCol} upToCol the column to total up to and including
+ */
+ getLeftWidth: function (grid, upToCol) {
+ var width = 0;
+
+ if (!upToCol) {
+ return width;
+ }
+
+ var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );
+
+ // total column widths up-to but not including the passed in column
+ grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {
+ if ( index < lastIndex ){
+ width += col.drawnWidth;
+ }
+ });
+
+ // pro-rata the final column based on % of total columns.
+ var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;
+ width += upToCol.drawnWidth * percentage;
+
+ return width;
+ }
+ };
+
+ return service;
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.cellNav.directive:uiCellNav
+ * @element div
+ * @restrict EA
+ *
+ * @description Adds cell navigation features to the grid columns
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'title'}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-cellnav></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn', '$timeout', '$compile',
+ function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, GridRowColumn, $timeout, $compile) {
+ return {
+ replace: true,
+ priority: -150,
+ require: '^uiGrid',
+ scope: false,
+ controller: function () {},
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var _scope = $scope;
+
+ var grid = uiGridCtrl.grid;
+ uiGridCellNavService.initializeGrid(grid);
+
+ uiGridCtrl.cellNav = {};
+
+ //Ensure that the object has all of the methods we expect it to
+ uiGridCtrl.cellNav.makeRowCol = function (obj) {
+ if (!(obj instanceof GridRowColumn)) {
+ obj = new GridRowColumn(obj.row, obj.col);
+ }
+ return obj;
+ };
+
+ uiGridCtrl.cellNav.getActiveCell = function () {
+ var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');
+ if (elms.length > 0){
+ return elms[0];
+ }
+
+ return undefined;
+ };
+
+ uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {
+ modifierDown = !(modifierDown === undefined || !modifierDown);
+
+ newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);
+
+ uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);
+ _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);
+ };
+
+ uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {
+ grid.cellNav.focusedCells = [];
+ _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);
+ };
+
+ uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {
+ modifierDown = !(modifierDown === undefined || !modifierDown);
+
+ rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);
+
+ var row = rowCol.row,
+ col = rowCol.col;
+
+ var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
+
+ if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {
+ var newRowCol = new GridRowColumn(row, col);
+
+ grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);
+ grid.cellNav.lastRowCol = newRowCol;
+ if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {
+ grid.cellNav.focusedCells.push(rowCol);
+ } else {
+ grid.cellNav.focusedCells = [rowCol];
+ }
+ } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&
+ rowColSelectIndex >= 0) {
+
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ }
+ };
+
+ uiGridCtrl.cellNav.handleKeyDown = function (evt) {
+ var direction = uiGridCellNavService.getDirection(evt);
+ if (direction === null) {
+ return null;
+ }
+
+ var containerId = 'body';
+ if (evt.uiGridTargetRenderContainerId) {
+ containerId = evt.uiGridTargetRenderContainerId;
+ }
+
+ // Get the last-focused row+col combo
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol) {
+ // Figure out which new row+combo we're navigating to
+ var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);
+ var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();
+ var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
+ // Shift+tab on top-left cell should exit cellnav on render container
+ if (
+ // Navigating left
+ direction === uiGridCellNavConstants.direction.LEFT &&
+ // New col is last col (i.e. wrap around)
+ rowCol.col === focusableCols[focusableCols.length - 1] &&
+ // Staying on same row, which means we're at first row
+ rowCol.row === lastRowCol.row &&
+ evt.keyCode === uiGridConstants.keymap.TAB &&
+ evt.shiftKey
+ ) {
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ uiGridCtrl.cellNav.clearFocus();
+ return true;
+ }
+ // Tab on bottom-right cell should exit cellnav on render container
+ else if (
+ direction === uiGridCellNavConstants.direction.RIGHT &&
+ // New col is first col (i.e. wrap around)
+ rowCol.col === focusableCols[0] &&
+ // Staying on same row, which means we're at first row
+ rowCol.row === lastRowCol.row &&
+ evt.keyCode === uiGridConstants.keymap.TAB &&
+ !evt.shiftKey
+ ) {
+ grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
+ uiGridCtrl.cellNav.clearFocus();
+ return true;
+ }
+
+ // Scroll to the new cell, if it's not completely visible within the render container's viewport
+ grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {
+ uiGridCtrl.cellNav.broadcastCellNav(rowCol);
+ });
+
+
+ evt.stopPropagation();
+ evt.preventDefault();
+
+ return false;
+ }
+ };
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var _scope = $scope;
+ var grid = uiGridCtrl.grid;
+
+ function addAriaLiveRegion(){
+ // Thanks to google docs for the inspiration behind how to do this
+ // XXX: Why is this entire mess nessasary?
+ // Because browsers take a lot of coercing to get them to read out live regions
+ //http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
+ var ariaNotifierDomElt = '<div ' +
+ 'id="' + grid.id +'-aria-speakable" ' +
+ 'class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" ' +
+ 'aria-live="assertive" ' +
+ 'role="region" ' +
+ 'aria-atomic="true" ' +
+ 'aria-hidden="false" ' +
+ 'aria-relevant="additions" ' +
+ '>' +
+ '&nbsp;' +
+ '</div>';
+
+ var ariaNotifier = $compile(ariaNotifierDomElt)($scope);
+ $elm.prepend(ariaNotifier);
+ $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {
+ /*
+ * If the cell nav event was because of a focus event then we don't want to
+ * change the notifier text.
+ * Reasoning: Voice Over fires a focus events when moving arround the grid.
+ * If the screen reader is handing the grid nav properly then we don't need to
+ * use the alert to notify the user of the movement.
+ * In all other cases we do want a notification event.
+ */
+ if (originEvt && originEvt.type === 'focus'){return;}
+
+ function setNotifyText(text){
+ if (text === ariaNotifier.text()){return;}
+ ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';
+ /*
+ * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''
+ */
+ ariaNotifier[0].innerHTML = "";
+ ariaNotifier[0].style.visibility = 'hidden';
+ ariaNotifier[0].style.visibility = 'visible';
+ if (text !== ''){
+ ariaNotifier[0].style.clip = 'auto';
+ /*
+ * The space after the text is something that google docs does.
+ */
+ ariaNotifier[0].appendChild(document.createTextNode(text + " "));
+ ariaNotifier[0].style.visibility = 'hidden';
+ ariaNotifier[0].style.visibility = 'visible';
+ }
+ }
+
+ var values = [];
+ var currentSelection = grid.api.cellNav.getCurrentSelection();
+ for (var i = 0; i < currentSelection.length; i++) {
+ values.push(currentSelection[i].getIntersectionValueFiltered());
+ }
+ var cellText = values.toString();
+ setNotifyText(cellText);
+
+ });
+ }
+ addAriaLiveRegion();
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',
+ function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {
+ return {
+ replace: true,
+ priority: -99999, //this needs to run very last
+ require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],
+ scope: false,
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ renderContainerCtrl = controllers[1],
+ uiGridCellnavCtrl = controllers[2];
+
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = renderContainerCtrl.containerId;
+
+ var grid = uiGridCtrl.grid;
+
+ //run each time a render container is created
+ uiGridCellNavService.decorateRenderContainers(grid);
+
+ // focusser only created for body
+ if (containerId !== 'body') {
+ return;
+ }
+
+
+
+ if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells){
+ $elm.attr('aria-multiselectable', true);
+ } else {
+ $elm.attr('aria-multiselectable', false);
+ }
+
+ //add an element with no dimensions that can be used to set focus and capture keystrokes
+ var focuser = $compile('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'" aria-owns="' + grid.id + '-grid-container' + '"></div>')($scope);
+ $elm.append(focuser);
+
+ focuser.on('focus', function (evt) {
+ evt.uiGridTargetRenderContainerId = containerId;
+ var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (rowCol === null) {
+ rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);
+ if (rowCol.row && rowCol.col) {
+ uiGridCtrl.cellNav.broadcastCellNav(rowCol);
+ }
+ }
+ });
+
+ uiGridCellnavCtrl.setAriaActivedescendant = function(id){
+ $elm.attr('aria-activedescendant', id);
+ };
+
+ uiGridCellnavCtrl.removeAriaActivedescendant = function(id){
+ if ($elm.attr('aria-activedescendant') === id){
+ $elm.attr('aria-activedescendant', '');
+ }
+ };
+
+
+ uiGridCtrl.focus = function () {
+ gridUtil.focus.byElement(focuser[0]);
+ //allow for first time grid focus
+ };
+
+ var viewPortKeyDownWasRaisedForRowCol = null;
+ // Bind to keydown events in the render container
+ focuser.on('keydown', function (evt) {
+ evt.uiGridTargetRenderContainerId = containerId;
+ var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ var result = uiGridCtrl.cellNav.handleKeyDown(evt);
+ if (result === null) {
+ uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol);
+ viewPortKeyDownWasRaisedForRowCol = rowCol;
+ }
+ });
+ //Bind to keypress events in the render container
+ //keypress events are needed by edit function so the key press
+ //that initiated an edit is not lost
+ //must fire the event in a timeout so the editor can
+ //initialize and subscribe to the event on another event loop
+ focuser.on('keypress', function (evt) {
+ if (viewPortKeyDownWasRaisedForRowCol) {
+ $timeout(function () {
+ uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);
+ },4);
+
+ viewPortKeyDownWasRaisedForRowCol = null;
+ }
+ });
+
+ $scope.$on('$destroy', function(){
+ //Remove all event handlers associated with this focuser.
+ focuser.off();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridViewport', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants','$log','$compile',
+ function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants, $log, $compile) {
+ return {
+ replace: true,
+ priority: -99999, //this needs to run very last
+ require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ renderContainerCtrl = controllers[1];
+
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = renderContainerCtrl.containerId;
+ //no need to process for other containers
+ if (containerId !== 'body') {
+ return;
+ }
+
+ var grid = uiGridCtrl.grid;
+
+ grid.api.core.on.scrollBegin($scope, function (args) {
+
+ // Skip if there's no currently-focused cell
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol === null) {
+ return;
+ }
+
+ //if not in my container, move on
+ //todo: worry about horiz scroll
+ if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
+ return;
+ }
+
+ uiGridCtrl.cellNav.clearFocus();
+
+ });
+
+ grid.api.core.on.scrollEnd($scope, function (args) {
+ // Skip if there's no currently-focused cell
+ var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
+ if (lastRowCol === null) {
+ return;
+ }
+
+ //if not in my container, move on
+ //todo: worry about horiz scroll
+ if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
+ return;
+ }
+
+ uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
+
+ });
+
+ grid.api.cellNav.on.navigate($scope, function () {
+ //focus again because it can be lost
+ uiGridCtrl.focus();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.cellNav.directive:uiGridCell
+ * @element div
+ * @restrict A
+ * @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
+ */
+ module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn',
+ function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, GridRowColumn) {
+ return {
+ priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
+ restrict: 'A',
+ require: ['^uiGrid', '?^uiGridCellnav'],
+ scope: false,
+ link: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0],
+ uiGridCellnavCtrl = controllers[1];
+ // Skip attaching cell-nav specific logic if the directive is not attached above us
+ if (!uiGridCtrl.grid.api.cellNav) { return; }
+
+ if (!$scope.col.colDef.allowCellFocus) {
+ return;
+ }
+
+ //Convinience local variables
+ var grid = uiGridCtrl.grid;
+ $scope.focused = false;
+
+ // Make this cell focusable but only with javascript/a mouse click
+ $elm.attr('tabindex', -1);
+
+ // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused
+ $elm.find('div').on('click', function (evt) {
+ uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);
+
+ evt.stopPropagation();
+ $scope.$apply();
+ });
+
+
+ /*
+ * XXX Hack for screen readers.
+ * This allows the grid to focus using only the screen reader cursor.
+ * Since the focus event doesn't include key press information we can't use it
+ * as our primary source of the event.
+ */
+ $elm.on('mousedown', preventMouseDown);
+
+ //turn on and off for edit events
+ if (uiGridCtrl.grid.api.edit) {
+ uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {
+ $elm.off('mousedown', preventMouseDown);
+ });
+
+ uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {
+ $elm.on('mousedown', preventMouseDown);
+ });
+
+ uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {
+ $elm.on('mousedown', preventMouseDown);
+ });
+ }
+
+ function preventMouseDown(evt) {
+ //Prevents the foucus event from firing if the click event is already going to fire.
+ //If both events fire it will cause bouncing behavior.
+ evt.preventDefault();
+ }
+
+ //You can only focus on elements with a tabindex value
+ $elm.on('focus', function (evt) {
+ uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), false, evt);
+ evt.stopPropagation();
+ $scope.$apply();
+ });
+
+ // This event is fired for all cells. If the cell matches, then focus is set
+ $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {
+ var isFocused = grid.cellNav.focusedCells.some(function(focusedRowCol, index){
+ return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);
+ });
+ if (isFocused){
+ setFocused();
+ } else {
+ clearFocus();
+ }
+ });
+
+ function setFocused() {
+ if (!$scope.focused){
+ var div = $elm.find('div');
+ div.addClass('ui-grid-cell-focus');
+ $elm.attr('aria-selected', true);
+ uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));
+ $scope.focused = true;
+ }
+ }
+
+ function clearFocus() {
+ if ($scope.focused){
+ var div = $elm.find('div');
+ div.removeClass('ui-grid-cell-focus');
+ $elm.attr('aria-selected', false);
+ uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));
+ $scope.focused = false;
+ }
+ }
+
+ $scope.$on('$destroy', function () {
+ //.off withouth paramaters removes all handlers
+ $elm.find('div').off();
+ $elm.off();
+ });
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.edit
+ * @description
+ *
+ * # ui.grid.edit
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via
+ * a keyboard.
+ * <br/>
+ * <br/>
+ * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the
+ * user to key data and then tab, arrow, or enter to the cells beside or below.
+ *
+ * <div doc-module-components="ui.grid.edit"></div>
+ */
+
+ var module = angular.module('ui.grid.edit', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.constant:uiGridEditConstants
+ *
+ * @description constants available in edit module
+ */
+ module.constant('uiGridEditConstants', {
+ EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,
+ //must be lowercase because template bulder converts to lower
+ EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,
+ events: {
+ BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',
+ END_CELL_EDIT: 'uiGridEventEndCellEdit',
+ CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.edit.service:uiGridEditService
+ *
+ * @description Services for editing features
+ */
+ module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',
+ function ($q, uiGridConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerColumnBuilder(service.editColumnBuilder);
+ grid.edit = {};
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:PublicApi
+ *
+ * @description Public Api for edit feature
+ */
+ var publicApi = {
+ events: {
+ edit: {
+ /**
+ * @ngdoc event
+ * @name afterCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing is complete
+ * <pre>
+ * gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ * @param {object} newValue new value
+ * @param {object} oldValue old value
+ */
+ afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {
+ },
+ /**
+ * @ngdoc event
+ * @name beginCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing starts on a cell
+ * <pre>
+ * gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ * @param {object} triggerEvent the event that triggered the edit. Useful to prevent losing keystrokes on some
+ * complex editors
+ */
+ beginCellEdit: function (rowEntity, colDef, triggerEvent) {
+ },
+ /**
+ * @ngdoc event
+ * @name cancelCellEdit
+ * @eventOf ui.grid.edit.api:PublicApi
+ * @description raised when cell editing is cancelled on a cell
+ * <pre>
+ * gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @param {object} colDef the column that was edited
+ */
+ cancelCellEdit: function (rowEntity, colDef) {
+ }
+ }
+ },
+ methods: {
+ edit: { }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ //grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:GridOptions
+ *
+ * @description Options for configuring the edit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If defined, sets the default value for the editable flag on each individual colDefs
+ * if their individual enableCellEdit configuration is not defined. Defaults to undefined.
+ */
+
+ /**
+ * @ngdoc object
+ * @name cellEditableCondition
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If specified, either a value or function to be used by all columns before editing.
+ * If falsy, then editing of cell is not allowed.
+ * @example
+ * <pre>
+ * function($scope){
+ * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
+ * return true;
+ * }
+ * </pre>
+ */
+ gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;
+
+ /**
+ * @ngdoc object
+ * @name editableCellTemplate
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If specified, cellTemplate to use as the editor for all columns.
+ * <br/> defaults to 'ui-grid/cellTextEditor'
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEditOnFocus
+ * @propertyOf ui.grid.edit.api:GridOptions
+ * @description If true, then editor is invoked as soon as cell receives focus. Default false.
+ * <br/>_requires cellNav feature and the edit feature to be enabled_
+ */
+ //enableCellEditOnFocus can only be used if cellnav module is used
+ gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;
+ },
+
+ /**
+ * @ngdoc service
+ * @name editColumnBuilder
+ * @methodOf ui.grid.edit.service:uiGridEditService
+ * @description columnBuilder function that adds edit properties to grid column
+ * @returns {promise} promise that will load any needed templates when resolved
+ */
+ editColumnBuilder: function (colDef, col, gridOptions) {
+
+ var promises = [];
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:ColumnDef
+ *
+ * @description Column Definition for edit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description enable editing on column
+ */
+ colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?
+ (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;
+
+ /**
+ * @ngdoc object
+ * @name cellEditableCondition
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description If specified, either a value or function evaluated before editing cell. If falsy, then editing of cell is not allowed.
+ * @example
+ * <pre>
+ * function($scope){
+ * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
+ * return true;
+ * }
+ * </pre>
+ */
+ colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition : colDef.cellEditableCondition;
+
+ /**
+ * @ngdoc object
+ * @name editableCellTemplate
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description cell template to be used when editing this column. Can be Url or text template
+ * <br/>Defaults to gridOptions.editableCellTemplate
+ */
+ if (colDef.enableCellEdit) {
+ colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';
+
+ promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)
+ .then(
+ function (template) {
+ col.editableCellTemplate = template;
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use colDef.editableCellTemplate '" + colDef.editableCellTemplate + "'");
+ }));
+ }
+
+ /**
+ * @ngdoc object
+ * @name enableCellEditOnFocus
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @requires ui.grid.cellNav
+ * @description If true, then editor is invoked as soon as cell receives focus. Default false.
+ * <br>_requires both the cellNav feature and the edit feature to be enabled_
+ */
+ //enableCellEditOnFocus can only be used if cellnav module is used
+ colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;
+
+
+ /**
+ * @ngdoc string
+ * @name editModelField
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description a bindable string value that is used when binding to edit controls instead of colDef.field
+ * <br/> example: You have a complex property on and object like state:{abbrev:'MS',name:'Mississippi'}. The
+ * grid should display state.name in the cell and sort/filter based on the state.name property but the editor
+ * requires the full state object.
+ * <br/>colDef.field = 'state.name'
+ * <br/>colDef.editModelField = 'state'
+ */
+ //colDef.editModelField
+
+ return $q.all(promises);
+ },
+
+ /**
+ * @ngdoc service
+ * @name isStartEditKey
+ * @methodOf ui.grid.edit.service:uiGridEditService
+ * @description Determines if a keypress should start editing. Decorate this service to override with your
+ * own key events. See service decorator in angular docs.
+ * @param {Event} evt keydown event
+ * @returns {boolean} true if an edit should start
+ */
+ isStartEditKey: function (evt) {
+ if (evt.metaKey ||
+ evt.keyCode === uiGridConstants.keymap.ESC ||
+ evt.keyCode === uiGridConstants.keymap.SHIFT ||
+ evt.keyCode === uiGridConstants.keymap.CTRL ||
+ evt.keyCode === uiGridConstants.keymap.ALT ||
+ evt.keyCode === uiGridConstants.keymap.WIN ||
+ evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||
+
+ evt.keyCode === uiGridConstants.keymap.LEFT ||
+ (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||
+
+ evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.TAB ||
+
+ evt.keyCode === uiGridConstants.keymap.UP ||
+ (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||
+
+ evt.keyCode === uiGridConstants.keymap.DOWN ||
+ evt.keyCode === uiGridConstants.keymap.ENTER) {
+ return false;
+
+ }
+ return true;
+ }
+
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEdit
+ * @element div
+ * @restrict A
+ *
+ * @description Adds editing features to the ui-grid directive.
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridEditService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridRenderContainer
+ * @element div
+ * @restrict A
+ *
+ * @description Adds keydown listeners to renderContainer element so we can capture when to begin edits
+ *
+ */
+ module.directive('uiGridViewport', [ 'uiGridEditConstants',
+ function ( uiGridEditConstants) {
+ return {
+ replace: true,
+ priority: -99998, //run before cellNav
+ require: ['^uiGrid', '^uiGridRenderContainer'],
+ scope: false,
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+
+ // Skip attaching if edit and cellNav is not enabled
+ if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }
+
+ var containerId = controllers[1].containerId;
+ //no need to process for other containers
+ if (containerId !== 'body') {
+ return;
+ }
+
+ //refocus on the grid
+ $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
+ uiGridCtrl.focus();
+ });
+ $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
+ uiGridCtrl.focus();
+ });
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell
+ * Editing Actions.
+ *
+ * Binds edit start events to the uiGridCell element. When the events fire, the gridCell element is appended
+ * with the columnDef.editableCellTemplate element ('cellEditor.html' by default).
+ *
+ * The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\_CELL\_EDIT angular event
+ * and do the initial steps needed to edit the cell (setfocus on input element, etc).
+ *
+ * When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)
+ * it should emit the uiGridEditConstants.events.END\_CELL\_EDIT event.
+ *
+ * If editableCellTemplate recognizes that the editing has been cancelled (esc key)
+ * it should emit the uiGridEditConstants.events.CANCEL\_CELL\_EDIT event. The original value
+ * will be set back on the model by the uiGridCell directive.
+ *
+ * Events that invoke editing:
+ * - dblclick
+ * - F2 keydown (when using cell selection)
+ *
+ * Events that end editing:
+ * - Dependent on the specific editableCellTemplate
+ * - Standards should be blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Dependent on the specific editableCellTemplate
+ * - Standards should be Esc keydown
+ *
+ * Grid Events that end editing:
+ * - uiGridConstants.events.GRID_SCROLL
+ *
+ */
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.edit.api:GridRow
+ *
+ * @description GridRow options for edit feature, these are available to be
+ * set internally only, by other features
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableCellEdit
+ * @propertyOf ui.grid.edit.api:GridRow
+ * @description enable editing on row, grouping for example might disable editing on group header rows
+ */
+
+ module.directive('uiGridCell',
+ ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope',
+ function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope) {
+ var touchstartTimeout = 500;
+ if ($injector.has('uiGridCellNavService')) {
+ var uiGridCellNavService = $injector.get('uiGridCellNavService');
+ }
+
+ return {
+ priority: -100, // run after default uiGridCell directive
+ restrict: 'A',
+ scope: false,
+ require: '?^uiGrid',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var html;
+ var origCellValue;
+ var inEdit = false;
+ var cellModel;
+ var cancelTouchstartTimeout;
+
+ var editCellScope;
+
+ if (!$scope.col.colDef.enableCellEdit) {
+ return;
+ }
+
+ var cellNavNavigateDereg = function() {};
+ var viewPortKeyDownDereg = function() {};
+
+
+ var setEditable = function() {
+ if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {
+ if (!$scope.beginEditEventsWired) { //prevent multiple attachments
+ registerBeginEditEvents();
+ }
+ } else {
+ if ($scope.beginEditEventsWired) {
+ cancelBeginEditEvents();
+ }
+ }
+ };
+
+ setEditable();
+
+ var rowWatchDereg = $scope.$watch('row', function (n, o) {
+ if (n !== o) {
+ setEditable();
+ }
+ });
+
+
+ $scope.$on( '$destroy', rowWatchDereg );
+
+ function registerBeginEditEvents() {
+ $elm.on('dblclick', beginEdit);
+
+ // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit
+ $elm.on('touchstart', touchStart);
+
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+
+ viewPortKeyDownDereg = uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
+ if (rowCol === null) {
+ return;
+ }
+
+ if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {
+ //important to do this before scrollToIfNecessary
+ beginEditKeyDown(evt);
+ }
+ });
+
+ cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {
+ if ($scope.col.colDef.enableCellEditOnFocus) {
+ // Don't begin edit if the cell hasn't changed
+ if ((!oldRowCol || newRowCol.row !== oldRowCol.row || newRowCol.col !== oldRowCol.col) &&
+ newRowCol.row === $scope.row && newRowCol.col === $scope.col) {
+ $timeout(function () {
+ beginEdit();
+ });
+ }
+ }
+ });
+ }
+
+ $scope.beginEditEventsWired = true;
+
+ }
+
+ function touchStart(event) {
+ // jQuery masks events
+ if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
+ event = event.originalEvent;
+ }
+
+ // Bind touchend handler
+ $elm.on('touchend', touchEnd);
+
+ // Start a timeout
+ cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);
+
+ // Timeout's done! Start the edit
+ cancelTouchstartTimeout.then(function () {
+ // Use setTimeout to start the edit because beginEdit expects to be outside of $digest
+ setTimeout(beginEdit, 0);
+
+ // Undbind the touchend handler, we don't need it anymore
+ $elm.off('touchend', touchEnd);
+ });
+ }
+
+ // Cancel any touchstart timeout
+ function touchEnd(event) {
+ $timeout.cancel(cancelTouchstartTimeout);
+ $elm.off('touchend', touchEnd);
+ }
+
+ function cancelBeginEditEvents() {
+ $elm.off('dblclick', beginEdit);
+ $elm.off('keydown', beginEditKeyDown);
+ $elm.off('touchstart', touchStart);
+ cellNavNavigateDereg();
+ viewPortKeyDownDereg();
+ $scope.beginEditEventsWired = false;
+ }
+
+ function beginEditKeyDown(evt) {
+ if (uiGridEditService.isStartEditKey(evt)) {
+ beginEdit(evt);
+ }
+ }
+
+ function shouldEdit(col, row) {
+ return !row.isSaving &&
+ ( angular.isFunction(col.colDef.cellEditableCondition) ?
+ col.colDef.cellEditableCondition($scope) :
+ col.colDef.cellEditableCondition );
+ }
+
+
+ function beginEdit(triggerEvent) {
+ //we need to scroll the cell into focus before invoking the editor
+ $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)
+ .then(function () {
+ beginEditAfterScroll(triggerEvent);
+ });
+ }
+
+ /**
+ * @ngdoc property
+ * @name editDropdownOptionsArray
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description an array of values in the format
+ * [ {id: xxx, value: xxx} ], which is populated
+ * into the edit dropdown
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownIdLabel
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description the label for the "id" field
+ * in the editDropdownOptionsArray. Defaults
+ * to 'id'
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownRowEntityOptionsArrayPath
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description a path to a property on row.entity containing an
+ * array of values in the format
+ * [ {id: xxx, value: xxx} ], which will be used to populate
+ * the edit dropdown. This can be used when the dropdown values are dependent on
+ * the backing row entity.
+ * If this property is set then editDropdownOptionsArray will be ignored.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownValueLabel
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description the label for the "value" field
+ * in the editDropdownOptionsArray. Defaults
+ * to 'value'
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
+ * ],
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc property
+ * @name editDropdownFilter
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description A filter that you would like to apply to the values in the options list
+ * of the dropdown. For example if you were using angular-translate you might set this
+ * to `'translate'`
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * columnDefs: [
+ * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
+ * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
+ * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }
+ * ],
+ * </pre>
+ *
+ */
+ function beginEditAfterScroll(triggerEvent) {
+ // If we are already editing, then just skip this so we don't try editing twice...
+ if (inEdit) {
+ return;
+ }
+
+ if (!shouldEdit($scope.col, $scope.row)) {
+ return;
+ }
+
+
+ cellModel = $parse($scope.row.getQualifiedColField($scope.col));
+ //get original value from the cell
+ origCellValue = cellModel($scope);
+
+ html = $scope.col.editableCellTemplate;
+
+ if ($scope.col.colDef.editModelField) {
+ html = html.replace(uiGridConstants.MODEL_COL_FIELD, gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField));
+ }
+ else {
+ html = html.replace(uiGridConstants.MODEL_COL_FIELD, $scope.row.getQualifiedColField($scope.col));
+ }
+
+ html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
+
+ var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';
+ html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);
+
+ var inputType = 'text';
+ switch ($scope.col.colDef.type){
+ case 'boolean':
+ inputType = 'checkbox';
+ break;
+ case 'number':
+ inputType = 'number';
+ break;
+ case 'date':
+ inputType = 'date';
+ break;
+ }
+ html = html.replace('INPUT_TYPE', inputType);
+
+ var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;
+ if (editDropdownRowEntityOptionsArrayPath) {
+ $scope.editDropdownOptionsArray = resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);
+ }
+ else {
+ $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;
+ }
+ $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';
+ $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';
+
+ var cellElement;
+ var createEditor = function(){
+ inEdit = true;
+ cancelBeginEditEvents();
+ var cellElement = angular.element(html);
+ $elm.append(cellElement);
+ editCellScope = $scope.$new();
+ $compile(cellElement)(editCellScope);
+ var gridCellContentsEl = angular.element($elm.children()[0]);
+ gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');
+ };
+ if (!$rootScope.$$phase) {
+ $scope.$apply(createEditor);
+ } else {
+ createEditor();
+ }
+
+ //stop editing when grid is scrolled
+ var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {
+ if ($scope.grid.disableScrolling) {
+ return;
+ }
+ endEdit();
+ $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
+ deregOnGridScroll();
+ deregOnEndCellEdit();
+ deregOnCancelCellEdit();
+ });
+
+ //end editing
+ var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
+ endEdit();
+ $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
+ deregOnEndCellEdit();
+ deregOnGridScroll();
+ deregOnCancelCellEdit();
+ });
+
+ //cancel editing
+ var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
+ cancelEdit();
+ deregOnCancelCellEdit();
+ deregOnGridScroll();
+ deregOnEndCellEdit();
+ });
+
+ $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);
+ $timeout(function () {
+ //execute in a timeout to give any complex editor templates a cycle to completely render
+ $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);
+ });
+ }
+
+ function endEdit() {
+ $scope.grid.disableScrolling = false;
+ if (!inEdit) {
+ return;
+ }
+
+ //sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus
+ //back to grid here. The focus call needs to be before the $destroy and removal of the control,
+ //otherwise ng-model-options of UpdateOn: 'blur' will not work.
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ uiGridCtrl.focus();
+ }
+
+ var gridCellContentsEl = angular.element($elm.children()[0]);
+ //remove edit element
+ editCellScope.$destroy();
+ angular.element($elm.children()[1]).remove();
+ gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');
+ inEdit = false;
+ registerBeginEditEvents();
+ $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );
+ }
+
+ function cancelEdit() {
+ $scope.grid.disableScrolling = false;
+ if (!inEdit) {
+ return;
+ }
+ cellModel.assign($scope, origCellValue);
+ $scope.$apply();
+
+ $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);
+ endEdit();
+ }
+
+ // resolves a string path against the given object
+ // shamelessly borrowed from
+ // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
+ function resolveObjectFromPath(object, path) {
+ path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+ path = path.replace(/^\./, ''); // strip a leading dot
+ var a = path.split('.');
+ while (a.length) {
+ var n = a.shift();
+ if (n in object) {
+ object = object[n];
+ } else {
+ return;
+ }
+ }
+ return object;
+ }
+
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditor
+ * @element div
+ * @restrict A
+ *
+ * @description input editor directive for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditor',
+ ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',
+ function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {
+ return {
+ scope: true,
+ require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl, renderContainerCtrl, ngModel;
+ if (controllers[0]) { uiGridCtrl = controllers[0]; }
+ if (controllers[1]) { renderContainerCtrl = controllers[1]; }
+ if (controllers[2]) { ngModel = controllers[2]; }
+
+ //set focus at start of edit
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function (evt,triggerEvent) {
+ $timeout(function () {
+ $elm[0].focus();
+ //only select text if it is not being replaced below in the cellNav viewPortKeyPress
+ if ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav)) {
+ $elm[0].select();
+ }
+ else {
+ //some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...
+ //fields should not allow setSelectionRange. We ignore the error for those browsers
+ //https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796
+ try {
+ $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);
+ }
+ catch (ex) {
+ //ignore
+ }
+ }
+ });
+
+ //set the keystroke that started the edit event
+ //we must do this because the BeginEdit is done in a different event loop than the intitial
+ //keydown event
+ //fire this event for the keypress that is received
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {
+ if (uiGridEditService.isStartEditKey(evt)) {
+ ngModel.$setViewValue(String.fromCharCode(evt.keyCode), evt);
+ ngModel.$render();
+ }
+ viewPortKeyDownUnregister();
+ });
+ }
+
+ $elm.on('blur', function (evt) {
+ $scope.stopEdit(evt);
+ });
+ });
+
+
+ $scope.deepEdit = false;
+
+ $scope.stopEdit = function (evt) {
+ if ($scope.inputForm && !$scope.inputForm.$valid) {
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ }
+ else {
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ }
+ $scope.deepEdit = false;
+ };
+
+
+ $elm.on('click', function (evt) {
+ if ($elm[0].type !== 'checkbox') {
+ $scope.deepEdit = true;
+ $timeout(function () {
+ $scope.grid.disableScrolling = true;
+ });
+ }
+ });
+
+ $elm.on('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ESC:
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ break;
+ }
+
+ if ($scope.deepEdit &&
+ (evt.keyCode === uiGridConstants.keymap.LEFT ||
+ evt.keyCode === uiGridConstants.keymap.RIGHT ||
+ evt.keyCode === uiGridConstants.keymap.UP ||
+ evt.keyCode === uiGridConstants.keymap.DOWN)) {
+ evt.stopPropagation();
+ }
+ // Pass the keydown event off to the cellNav service, if it exists
+ else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
+ if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
+ $scope.stopEdit(evt);
+ }
+ }
+ else {
+ //handle enter and tab for editing not using cellNav
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
+ case uiGridConstants.keymap.TAB:
+ evt.stopPropagation();
+ evt.preventDefault();
+ $scope.stopEdit(evt);
+ break;
+ }
+ }
+
+ return true;
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:input
+ * @element input
+ * @restrict E
+ *
+ * @description directive to provide binding between input[date] value and ng-model for angular 1.2
+ * It is similar to input[date] directive of angular 1.3
+ *
+ * Supported date format for input is 'yyyy-MM-dd'
+ * The directive will set the $valid property of input element and the enclosing form to false if
+ * model is invalid date or value of input is entered wrong.
+ *
+ */
+ module.directive('uiGridEditor', ['$filter', function ($filter) {
+ function parseDateString(dateString) {
+ if (typeof(dateString) === 'undefined' || dateString === '') {
+ return null;
+ }
+ var parts = dateString.split('-');
+ if (parts.length !== 3) {
+ return null;
+ }
+ var year = parseInt(parts[0], 10);
+ var month = parseInt(parts[1], 10);
+ var day = parseInt(parts[2], 10);
+
+ if (month < 1 || year < 1 || day < 1) {
+ return null;
+ }
+ return new Date(year, (month - 1), day);
+ }
+ return {
+ priority: -100, // run after default uiGridEditor directive
+ require: '?ngModel',
+ link: function (scope, element, attrs, ngModel) {
+
+ if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {
+
+ ngModel.$formatters.push(function (modelValue) {
+ ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));
+ return $filter('date')(modelValue, 'yyyy-MM-dd');
+ });
+
+ ngModel.$parsers.push(function (viewValue) {
+ if (viewValue && viewValue.length > 0) {
+ var dateValue = parseDateString(viewValue);
+ ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));
+ return dateValue;
+ }
+ else {
+ ngModel.$setValidity(null, true);
+ return null;
+ }
+ });
+ }
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditDropdown
+ * @element div
+ * @restrict A
+ *
+ * @description dropdown editor for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown, and any left/right nav
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditDropdown',
+ ['uiGridConstants', 'uiGridEditConstants',
+ function (uiGridConstants, uiGridEditConstants) {
+ return {
+ require: ['?^uiGrid', '?^uiGridRenderContainer'],
+ scope: true,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl = controllers[0];
+ var renderContainerCtrl = controllers[1];
+
+ //set focus at start of edit
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
+ $elm[0].focus();
+ $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';
+ $elm.on('blur', function (evt) {
+ $scope.stopEdit(evt);
+ });
+ });
+
+
+ $scope.stopEdit = function (evt) {
+ // no need to validate a dropdown - invalid values shouldn't be
+ // available in the list
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ };
+
+ $elm.on('keydown', function (evt) {
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ESC:
+ evt.stopPropagation();
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ break;
+ }
+ if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
+ evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
+ if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
+ $scope.stopEdit(evt);
+ }
+ }
+ else {
+ //handle enter and tab for editing not using cellNav
+ switch (evt.keyCode) {
+ case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
+ case uiGridConstants.keymap.TAB:
+ evt.stopPropagation();
+ evt.preventDefault();
+ $scope.stopEdit(evt);
+ break;
+ }
+ }
+ return true;
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.edit.directive:uiGridEditFileChooser
+ * @element div
+ * @restrict A
+ *
+ * @description input editor directive for editable fields.
+ * Provides EndEdit and CancelEdit events
+ *
+ * Events that end editing:
+ * blur and enter keydown
+ *
+ * Events that cancel editing:
+ * - Esc keydown
+ *
+ */
+ module.directive('uiGridEditFileChooser',
+ ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout',
+ function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout) {
+ return {
+ scope: true,
+ require: ['?^uiGrid', '?^uiGridRenderContainer'],
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ var uiGridCtrl, renderContainerCtrl;
+ if (controllers[0]) { uiGridCtrl = controllers[0]; }
+ if (controllers[1]) { renderContainerCtrl = controllers[1]; }
+ var grid = uiGridCtrl.grid;
+
+ var handleFileSelect = function( event ){
+ var target = event.srcElement || event.target;
+
+ if (target && target.files && target.files.length > 0) {
+ /**
+ * @ngdoc property
+ * @name editFileChooserCallback
+ * @propertyOf ui.grid.edit.api:ColumnDef
+ * @description A function that should be called when any files have been chosen
+ * by the user. You should use this to process the files appropriately for your
+ * application.
+ *
+ * It passes the gridCol, the gridRow (from which you can get gridRow.entity),
+ * and the files. The files are in the format as returned from the file chooser,
+ * an array of files, with each having useful information such as:
+ * - `files[0].lastModifiedDate`
+ * - `files[0].name`
+ * - `files[0].size` (appears to be in bytes)
+ * - `files[0].type` (MIME type by the looks)
+ *
+ * Typically you would do something with these files - most commonly you would
+ * use the filename or read the file itself in. The example function does both.
+ *
+ * @example
+ * <pre>
+ * editFileChooserCallBack: function(gridRow, gridCol, files ){
+ * // ignore all but the first file, it can only choose one anyway
+ * // set the filename into this column
+ * gridRow.entity.filename = file[0].name;
+ *
+ * // read the file and set it into a hidden column, which we may do stuff with later
+ * var setFile = function(fileContent){
+ * gridRow.entity.file = fileContent.currentTarget.result;
+ * };
+ * var reader = new FileReader();
+ * reader.onload = setFile;
+ * reader.readAsText( files[0] );
+ * }
+ * </pre>
+ */
+ if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {
+ $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);
+ } else {
+ gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');
+ }
+
+ target.form.reset();
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ } else {
+ $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
+ }
+ };
+
+ $elm[0].addEventListener('change', handleFileSelect, false); // TODO: why the false on the end? Google
+
+ $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
+ $elm[0].focus();
+ $elm[0].select();
+
+ $elm.on('blur', function (evt) {
+ $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
+ });
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.expandable
+ * @description
+ *
+ * # ui.grid.expandable
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides the ability to create subgrids with the ability to expand a row
+ * to show the subgrid.
+ *
+ * <div doc-module-components="ui.grid.expandable"></div>
+ */
+ var module = angular.module('ui.grid.expandable', ['ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.expandable.service:uiGridExpandableService
+ *
+ * @description Services for the expandable grid
+ */
+ module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {
+ var service = {
+ initializeGrid: function (grid) {
+
+ grid.expandable = {};
+ grid.expandable.expandedAll = false;
+
+ /**
+ * @ngdoc object
+ * @name enableExpandable
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids
+ * within your application, or in specific modes on _this_ grid. Defaults to true.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * enableExpandable: false
+ * }
+ * </pre>
+ */
+ grid.options.enableExpandable = grid.options.enableExpandable !== false;
+
+ /**
+ * @ngdoc object
+ * @name expandableRowHeight
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Height in pixels of the expanded subgrid. Defaults to
+ * 150
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowHeight: 150
+ * }
+ * </pre>
+ */
+ grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;
+
+ /**
+ * @ngdoc object
+ * @name
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Width in pixels of the expandable column. Defaults to 40
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowHeaderWidth: 40
+ * }
+ * </pre>
+ */
+ grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;
+
+ /**
+ * @ngdoc object
+ * @name expandableRowTemplate
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Mandatory. The template for your expanded row
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * expandableRowTemplate: 'expandableRowTemplate.html'
+ * }
+ * </pre>
+ */
+ if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){
+ gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );
+ grid.options.enableExpandable = false;
+ }
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.expandable.api:PublicApi
+ *
+ * @description Public Api for expandable feature
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.expandable.api:GridOptions
+ *
+ * @description Options for configuring the expandable feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ var publicApi = {
+ events: {
+ expandable: {
+ /**
+ * @ngdoc event
+ * @name rowExpandedStateChanged
+ * @eventOf ui.grid.expandable.api:PublicApi
+ * @description raised when cell editing is complete
+ * <pre>
+ * gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})
+ * </pre>
+ * @param {GridRow} row the row that was expanded
+ */
+ rowExpandedBeforeStateChanged: function(scope,row){
+ },
+ rowExpandedStateChanged: function (scope, row) {
+ }
+ }
+ },
+
+ methods: {
+ expandable: {
+ /**
+ * @ngdoc method
+ * @name toggleRowExpansion
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Toggle a specific row
+ * <pre>
+ * gridApi.expandable.toggleRowExpansion(rowEntity);
+ * </pre>
+ * @param {object} rowEntity the data entity for the row you want to expand
+ */
+ toggleRowExpansion: function (rowEntity) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null) {
+ service.toggleRowExpansion(grid, row);
+ }
+ },
+
+ /**
+ * @ngdoc method
+ * @name expandAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Expand all subgrids.
+ * <pre>
+ * gridApi.expandable.expandAllRows();
+ * </pre>
+ */
+ expandAllRows: function() {
+ service.expandAllRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @name collapseAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Collapse all subgrids.
+ * <pre>
+ * gridApi.expandable.collapseAllRows();
+ * </pre>
+ */
+ collapseAllRows: function() {
+ service.collapseAllRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @name toggleAllRows
+ * @methodOf ui.grid.expandable.api:PublicApi
+ * @description Toggle all subgrids.
+ * <pre>
+ * gridApi.expandable.toggleAllRows();
+ * </pre>
+ */
+ toggleAllRows: function() {
+ service.toggleAllRows(grid);
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+ toggleRowExpansion: function (grid, row) {
+ // trigger the "before change" event. Can change row height dynamically this way.
+ grid.api.expandable.raise.rowExpandedBeforeStateChanged(row);
+ row.isExpanded = !row.isExpanded;
+ if (angular.isUndefined(row.expandedRowHeight)){
+ row.expandedRowHeight = grid.options.expandableRowHeight;
+ }
+
+ if (row.isExpanded) {
+ row.height = row.grid.options.rowHeight + row.expandedRowHeight;
+ }
+ else {
+ row.height = row.grid.options.rowHeight;
+ grid.expandable.expandedAll = false;
+ }
+ grid.api.expandable.raise.rowExpandedStateChanged(row);
+ },
+
+ expandAllRows: function(grid, $scope) {
+ grid.renderContainers.body.visibleRowCache.forEach( function(row) {
+ if (!row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ });
+ grid.expandable.expandedAll = true;
+ grid.queueGridRefresh();
+ },
+
+ collapseAllRows: function(grid) {
+ grid.renderContainers.body.visibleRowCache.forEach( function(row) {
+ if (row.isExpanded) {
+ service.toggleRowExpansion(grid, row);
+ }
+ });
+ grid.expandable.expandedAll = false;
+ grid.queueGridRefresh();
+ },
+
+ toggleAllRows: function(grid) {
+ if (grid.expandable.expandedAll) {
+ service.collapseAllRows(grid);
+ }
+ else {
+ service.expandAllRows(grid);
+ }
+ }
+ };
+ return service;
+ }]);
+
+ /**
+ * @ngdoc object
+ * @name enableExpandableRowHeader
+ * @propertyOf ui.grid.expandable.api:GridOptions
+ * @description Show a rowHeader to provide the expandable buttons. If set to false then implies
+ * you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.
+ * @example
+ * <pre>
+ * $scope.gridOptions = {
+ * enableExpandableRowHeader: false
+ * }
+ * </pre>
+ */
+ module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',
+ function (uiGridExpandableService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if ( uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {
+ var expandableRowHeaderColDef = {
+ name: 'expandableButtons',
+ displayName: '',
+ exporterSuppressExport: true,
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40
+ };
+ expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');
+ expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');
+ uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef);
+ }
+ uiGridExpandableService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGrid
+ * @description stacks on the uiGrid directive to register child grid with parent row when child is created
+ */
+ module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',
+ function (uiGridExpandableService, $templateCache) {
+ return {
+ replace: true,
+ priority: 599,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {
+ //if a parent grid row is on the scope, then add the parentRow property to this childGrid
+ if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.class:Grid
+ * @description Additional Grid properties added by expandable module
+ */
+
+ /**
+ * @ngdoc object
+ * @name parentRow
+ * @propertyOf ui.grid.expandable.class:Grid
+ * @description reference to the expanded parent row that owns this grid
+ */
+ uiGridCtrl.grid.parentRow = $scope.row;
+
+ //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event
+ // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {
+ // uiGridCtrl.grid.parentRow = newHeight;
+ // });
+ }
+
+ });
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridExpandableRow
+ * @description directive to render the expandable row template
+ */
+ module.directive('uiGridExpandableRow',
+ ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',
+ function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {
+
+ return {
+ replace: false,
+ priority: 0,
+ scope: false,
+
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(
+ function (template) {
+ if ($scope.grid.options.expandableRowScope) {
+ var expandableRowScope = $scope.grid.options.expandableRowScope;
+ for (var property in expandableRowScope) {
+ if (expandableRowScope.hasOwnProperty(property)) {
+ $scope[property] = expandableRowScope[property];
+ }
+ }
+ }
+ var expandedRowElement = $compile(template)($scope);
+ $elm.append(expandedRowElement);
+ $scope.row.expandedRendered = true;
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ $scope.$on('$destroy', function() {
+ $scope.row.expandedRendered = false;
+ });
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridRow
+ * @description stacks on the uiGridRow directive to add support for expandable rows
+ */
+ module.directive('uiGridRow',
+ ['$compile', 'gridUtil', '$templateCache',
+ function ($compile, gridUtil, $templateCache) {
+ return {
+ priority: -200,
+ scope: false,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ $scope.expandableRow = {};
+
+ $scope.expandableRow.shouldRenderExpand = function () {
+ var ret = $scope.colContainer.name === 'body' && $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);
+ return ret;
+ };
+
+ $scope.expandableRow.shouldRenderFiller = function () {
+ var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));
+ return ret;
+ };
+
+ /*
+ * Commented out @PaulL1. This has no purpose that I can see, and causes #2964. If this code needs to be reinstated for some
+ * reason it needs to use drawnWidth, not width, and needs to check column visibility. It should really use render container
+ * visible column cache also instead of checking column.renderContainer.
+ function updateRowContainerWidth() {
+ var grid = $scope.grid;
+ var colWidth = 0;
+ grid.columns.forEach( function (column) {
+ if (column.renderContainer === 'left') {
+ colWidth += column.width;
+ }
+ });
+ colWidth = Math.floor(colWidth);
+ return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +
+ ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +
+ ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';
+ }
+
+ if ($scope.colContainer.name === 'left') {
+ $scope.grid.registerStyleComputation({
+ priority: 15,
+ func: updateRowContainerWidth
+ });
+ }*/
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.expandable.directive:uiGridViewport
+ * @description stacks on the uiGridViewport directive to append the expandable row html elements to the
+ * default gridRow template
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'gridUtil', '$templateCache',
+ function ($compile, gridUtil, $templateCache) {
+ return {
+ priority: -200,
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+ var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');
+ var expandedRowElement = $templateCache.get('ui-grid/expandableRow');
+ rowRepeatDiv.append(expandedRowElement);
+ rowRepeatDiv.append(expandedRowFillerElement);
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+/* global console */
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.exporter
+ * @description
+ *
+ * # ui.grid.exporter
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to exporter data from the grid.
+ *
+ * Data can be exported in a range of formats, and all data, visible
+ * data, or selected rows can be exported, with all columns or visible
+ * columns.
+ *
+ * No UI is provided, the caller should provide their own UI/buttons
+ * as appropriate, or enable the gridMenu
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.exporter"></div>
+ */
+
+ var module = angular.module('ui.grid.exporter', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.constant:uiGridExporterConstants
+ *
+ * @description constants available in exporter module
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name ALL
+ * @description export all data, including data not visible. Can
+ * be set for either rowTypes or colTypes
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name VISIBLE
+ * @description export only visible data, including data not visible. Can
+ * be set for either rowTypes or colTypes
+ */
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
+ * @name SELECTED
+ * @description export all data, including data not visible. Can
+ * be set only for rowTypes, selection of only some columns is
+ * not supported
+ */
+ module.constant('uiGridExporterConstants', {
+ featureName: 'exporter',
+ ALL: 'all',
+ VISIBLE: 'visible',
+ SELECTED: 'selected',
+ CSV_CONTENT: 'CSV_CONTENT',
+ BUTTON_LABEL: 'BUTTON_LABEL',
+ FILE_NAME: 'FILE_NAME'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.exporter.service:uiGridExporterService
+ *
+ * @description Services for exporter feature
+ */
+ module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',
+ function ($q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {
+
+ var service = {
+
+ delay: 100,
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.exporter = {};
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:PublicApi
+ *
+ * @description Public Api for exporter feature
+ */
+ var publicApi = {
+ events: {
+ exporter: {
+ }
+ },
+ methods: {
+ exporter: {
+ /**
+ * @ngdoc function
+ * @name csvExport
+ * @methodOf ui.grid.exporter.api:PublicApi
+ * @description Exports rows from the grid in csv format,
+ * the data exported is selected based on the provided options
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
+ */
+ csvExport: function (rowTypes, colTypes) {
+ service.csvExport(grid, rowTypes, colTypes);
+ },
+ /**
+ * @ngdoc function
+ * @name pdfExport
+ * @methodOf ui.grid.exporter.api:PublicApi
+ * @description Exports rows from the grid in pdf format,
+ * the data exported is selected based on the provided options
+ * Note that this function has a dependency on pdfMake, all
+ * going well this has been installed for you.
+ * The resulting pdf opens in a new browser window.
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
+ */
+ pdfExport: function (rowTypes, colTypes) {
+ service.pdfExport(grid, rowTypes, colTypes);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ } else {
+ // order of registration is not guaranteed, register in a little while
+ $interval( function() {
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ }
+ }, this.delay, 1);
+ }
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:GridOptions
+ *
+ * @description GridOptions for exporter feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:ColumnDef
+ * @description ColumnDef settings for exporter
+ */
+ /**
+ * @ngdoc object
+ * @name exporterSuppressMenu
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Don't show the export menu button, implying the user
+ * will roll their own UI for calling the exporter
+ * <br/>Defaults to false
+ */
+ gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;
+ /**
+ * @ngdoc object
+ * @name exporterMenuLabel
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The text to show on the exporter menu button
+ * link
+ * <br/>Defaults to 'Export'
+ */
+ gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';
+ /**
+ * @ngdoc object
+ * @name exporterSuppressColumns
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Columns that should not be exported. The selectionRowHeader is already automatically
+ * suppressed, but if you had a button column or some other "system" column that shouldn't be shown in the
+ * output then add it in this list. You should provide an array of column names.
+ * <br/>Defaults to: []
+ * <pre>
+ * gridOptions.exporterSuppressColumns = [ 'buttons' ];
+ * </pre>
+ */
+ gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];
+ /**
+ * @ngdoc object
+ * @name exporterCsvColumnSeparator
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The character to use as column separator
+ * link
+ * <br/>Defaults to ','
+ */
+ gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';
+ /**
+ * @ngdoc object
+ * @name exporterCsvFilename
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default filename to use when saving the downloaded csv.
+ * This will only work in some browsers.
+ * <br/>Defaults to 'download.csv'
+ */
+ gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';
+ /**
+ * @ngdoc object
+ * @name exporterPdfFilename
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)
+ * <br/>Defaults to 'download.pdf'
+ */
+ gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';
+ /**
+ * @ngdoc object
+ * @name exporterOlderExcelCompatibility
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes
+ * through as  in the first column header. Setting this option to false will suppress this, at the
+ * expense of proper utf-16 handling in applications that do recognise the BOM
+ * <br/>Defaults to false
+ */
+ gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;
+ /**
+ * @ngdoc object
+ * @name exporterPdfDefaultStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The default style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * fontSize: 11
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The table style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * margin: [0, 5, 0, 15]
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableHeaderStyle
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The tableHeader style in pdfMake format
+ * <br/>Defaults to:
+ * <pre>
+ * {
+ * bold: true,
+ * fontSize: 12,
+ * color: 'black'
+ * }
+ * </pre>
+ */
+ gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };
+ /**
+ * @ngdoc object
+ * @name exporterPdfHeader
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The header section for pdf exports. Can be
+ * simple text:
+ * <pre>
+ * gridOptions.exporterPdfHeader = 'My Header';
+ * </pre>
+ * Can be a more complex object in pdfMake format:
+ * <pre>
+ * gridOptions.exporterPdfHeader = {
+ * columns: [
+ * 'Left part',
+ * { text: 'Right part', alignment: 'right' }
+ * ]
+ * };
+ * </pre>
+ * Or can be a function, allowing page numbers and the like
+ * <pre>
+ * gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
+ * </pre>
+ */
+ gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;
+ /**
+ * @ngdoc object
+ * @name exporterPdfFooter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The header section for pdf exports. Can be
+ * simple text:
+ * <pre>
+ * gridOptions.exporterPdfFooter = 'My Footer';
+ * </pre>
+ * Can be a more complex object in pdfMake format:
+ * <pre>
+ * gridOptions.exporterPdfFooter = {
+ * columns: [
+ * 'Left part',
+ * { text: 'Right part', alignment: 'right' }
+ * ]
+ * };
+ * </pre>
+ * Or can be a function, allowing page numbers and the like
+ * <pre>
+ * gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
+ * </pre>
+ */
+ gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;
+ /**
+ * @ngdoc object
+ * @name exporterPdfOrientation
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The orientation, should be a valid pdfMake value,
+ * 'landscape' or 'portrait'
+ * <br/>Defaults to landscape
+ */
+ gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';
+ /**
+ * @ngdoc object
+ * @name exporterPdfPageSize
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The orientation, should be a valid pdfMake
+ * paper size, usually 'A4' or 'LETTER'
+ * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}
+ * <br/>Defaults to A4
+ */
+ gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';
+ /**
+ * @ngdoc object
+ * @name exporterPdfMaxGridWidth
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description The maxium grid width - the current grid width
+ * will be scaled to match this, with any fixed width columns
+ * being adjusted accordingly.
+ * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER
+ */
+ gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;
+ /**
+ * @ngdoc object
+ * @name exporterPdfTableLayout
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A tableLayout in pdfMake format,
+ * controls gridlines and the like. We use the default
+ * layout usually.
+ * <br/>Defaults to null, which means no layout
+ */
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuAllData
+ * @porpertyOf ui.grid.exporter.api:GridOptions
+ * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuCsv
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Add csv export menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterMenuPdf
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Add pdf export menu items to the ui-grid grid menu, if it's present. Defaults to true.
+ */
+ gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;
+
+ /**
+ * @ngdoc object
+ * @name exporterPdfCustomFormatter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A custom callback routine that changes the pdf document, adding any
+ * custom styling or content that is supported by pdfMake. Takes in the complete docDefinition, and
+ * must return an updated docDefinition ready for pdfMake.
+ * @example
+ * In this example we add a style to the style array, so that we can use it in our
+ * footer definition.
+ * <pre>
+ * gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {
+ * docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };
+ * return docDefinition;
+ * }
+ *
+ * gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }
+ * </pre>
+ */
+ gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };
+
+ /**
+ * @ngdoc object
+ * @name exporterHeaderFilterUseName
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.
+ * If set to true, then will pass `name` instead.
+ *
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterHeaderFilterUseName = true;
+ * </pre>
+ */
+ gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;
+
+ /**
+ * @ngdoc object
+ * @name exporterHeaderFilter
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A function to apply to the header displayNames before exporting. Useful for internationalisation,
+ * for example if you were using angular-translate you'd set this to `$translate.instant`. Note that this
+ * call must be synchronous, it cannot be a call that returns a promise.
+ *
+ * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };
+ * </pre>
+ * OR
+ * <pre>
+ * gridOptions.exporterHeaderFilter = $translate.instant;
+ * </pre>
+ */
+
+ /**
+ * @ngdoc function
+ * @name exporterFieldCallback
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description A function to call for each field before exporting it. Allows
+ * massaging of raw data into a display format, for example if you have applied
+ * filters to convert codes into decodes, or you require
+ * a specific date format in the exported content.
+ *
+ * The method is called once for each field exported, and provides the grid, the
+ * gridCol and the GridRow for you to use as context in massaging the data.
+ *
+ * @param {Grid} grid provides the grid in case you have need of it
+ * @param {GridRow} row the row from which the data comes
+ * @param {GridCol} col the column from which the data comes
+ * @param {object} value the value for your massaging
+ * @returns {object} you must return the massaged value ready for exporting
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterFieldCallback = function ( grid, row, col, value ){
+ * if ( col.name === 'status' ){
+ * value = decodeStatus( value );
+ * }
+ * return value;
+ * }
+ * </pre>
+ */
+ gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };
+
+ /**
+ * @ngdoc function
+ * @name exporterAllDataFn
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description This promise is needed when exporting all rows,
+ * and the data need to be provided by server side. Default is null.
+ * @returns {Promise} a promise to load all data from server
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterAllDataFn = function () {
+ * return $http.get('/data/100.json')
+ * }
+ * </pre>
+ */
+ gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;
+
+ /**
+ * @ngdoc function
+ * @name exporterAllDataPromise
+ * @propertyOf ui.grid.exporter.api:GridOptions
+ * @description DEPRECATED - exporterAllDataFn used to be
+ * called this, but it wasn't a promise, it was a function that returned
+ * a promise. Deprecated, but supported for backward compatibility, use
+ * exporterAllDataFn instead.
+ * @returns {Promise} a promise to load all data from server
+ *
+ * @example
+ * <pre>
+ * gridOptions.exporterAllDataFn = function () {
+ * return $http.get('/data/100.json')
+ * }
+ * </pre>
+ */
+ if ( gridOptions.exporterAllDataFn == null && gridOptions.exporterAllDataPromise ) {
+ gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToMenu
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Adds export items to the grid menu,
+ * allowing the user to select export options
+ * @param {Grid} grid the grid from which data should be exported
+ */
+ addToMenu: function ( grid ) {
+ grid.api.core.addToGridMenu( grid, [
+ {
+ title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuAllData;
+ },
+ order: 200
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv;
+ },
+ order: 201
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),
+ action: function ($event) {
+ this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuCsv &&
+ ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
+ },
+ order: 202
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuAllData;
+ },
+ order: 203
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf;
+ },
+ order: 204
+ },
+ {
+ title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),
+ action: function ($event) {
+ this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
+ },
+ shown: function() {
+ return this.grid.options.exporterMenuPdf &&
+ ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
+ },
+ order: 205
+ }
+ ]);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name csvExport
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Exports rows from the grid in csv format,
+ * the data exported is selected based on the provided options
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ csvExport: function (grid, rowTypes, colTypes) {
+ var self = this;
+ this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
+ var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
+ var exportData = self.getData(grid, rowTypes, colTypes);
+ var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);
+
+ self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterOlderExcelCompatibility);
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name loadAllDataIfNeeded
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description When using server side pagination, use exporterAllDataFn to
+ * load all data before continuing processing.
+ * When using client side pagination, return a resolved promise so processing
+ * continues immediately
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {
+ if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {
+ return grid.options.exporterAllDataFn()
+ .then(function() {
+ grid.modifyRows(grid.options.data);
+ });
+ } else {
+ var deferred = $q.defer();
+ deferred.resolve();
+ return deferred.promise;
+ }
+ },
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.api:ColumnDef
+ * @name exporterSuppressExport
+ * @description Suppresses export for this column. Used by selection and expandable.
+ */
+
+ /**
+ * @ngdoc function
+ * @name getColumnHeaders
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Gets the column headers from the grid to use
+ * as a title row for the exported file, all headers have
+ * headerCellFilters applied as appropriate.
+ *
+ * Column headers are an array of objects, each object has
+ * name, displayName, width and align attributes. Only name is
+ * used for csv, all attributes are used for pdf.
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ getColumnHeaders: function (grid, colTypes) {
+ var headers = [];
+ var columns;
+
+ if ( colTypes === uiGridExporterConstants.ALL ){
+ columns = grid.columns;
+ } else {
+ var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+
+ columns = leftColumns.concat(bodyColumns,rightColumns);
+ }
+
+ columns.forEach( function( gridCol, index ) {
+ if ( gridCol.colDef.exporterSuppressExport !== true &&
+ grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
+ headers.push({
+ name: gridCol.field,
+ displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,
+ width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,
+ align: gridCol.colDef.type === 'number' ? 'right' : 'left'
+ });
+ }
+ });
+
+ return headers;
+ },
+
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.exporter.api:ColumnDef
+ * @name exporterPdfAlign
+ * @description the alignment you'd like for this specific column when
+ * exported into a pdf. Can be 'left', 'right', 'center' or any other
+ * valid pdfMake alignment option.
+ */
+
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.exporter.api:GridRow
+ * @description GridRow settings for exporter
+ */
+ /**
+ * @ngdoc object
+ * @name exporterEnableExporting
+ * @propertyOf ui.grid.exporter.api:GridRow
+ * @description If set to false, then don't export this row, notwithstanding visible or
+ * other settings
+ * <br/>Defaults to true
+ */
+
+ /**
+ * @ngdoc function
+ * @name getData
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Gets data from the grid based on the provided options,
+ * all cells have cellFilters applied as appropriate. Any rows marked
+ * `exporterEnableExporting: false` will not be exported
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ getData: function (grid, rowTypes, colTypes) {
+ var data = [];
+ var rows;
+ var columns;
+
+ switch ( rowTypes ) {
+ case uiGridExporterConstants.ALL:
+ rows = grid.rows;
+ break;
+ case uiGridExporterConstants.VISIBLE:
+ rows = grid.getVisibleRows();
+ break;
+ case uiGridExporterConstants.SELECTED:
+ if ( grid.api.selection ){
+ rows = grid.api.selection.getSelectedGridRows();
+ } else {
+ gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');
+ }
+ break;
+ }
+
+ if ( colTypes === uiGridExporterConstants.ALL ){
+ columns = grid.columns;
+ } else {
+ var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+ var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
+
+ columns = leftColumns.concat(bodyColumns,rightColumns);
+ }
+
+ rows.forEach( function( row, index ) {
+
+ if (row.exporterEnableExporting !== false) {
+ var extractedRow = [];
+
+
+ columns.forEach( function( gridCol, index ) {
+ if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&
+ gridCol.colDef.exporterSuppressExport !== true &&
+ grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
+ var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, grid.getCellValue( row, gridCol ) ) };
+ if ( gridCol.colDef.exporterPdfAlign ) {
+ extractedField.alignment = gridCol.colDef.exporterPdfAlign;
+ }
+ extractedRow.push(extractedField);
+ }
+ });
+
+ data.push(extractedRow);
+ }
+ });
+
+ return data;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name formatAsCSV
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Formats the column headers and data as a CSV,
+ * and sends that data to the user
+ * @param {array} exportColumnHeaders an array of column headers,
+ * where each header is an object with name, width and maybe alignment
+ * @param {array} exportData an array of rows, where each row is
+ * an array of column data
+ * @returns {string} csv the formatted csv as a string
+ */
+ formatAsCsv: function (exportColumnHeaders, exportData, separator) {
+ var self = this;
+
+ var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});
+
+ var csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\n') : '';
+
+ csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\n');
+
+ return csv;
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatRowAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a csv field, including
+ * quotes around the value
+ * @param {exporterService} exporter pass in exporter
+ * @param {array} row the row to be turned into a csv string
+ * @returns {string} a csv-ified version of the row
+ */
+ formatRowAsCsv: function (exporter, separator) {
+ return function (row) {
+ return row.map(exporter.formatFieldAsCsv).join(separator);
+ };
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatFieldAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a csv field, including
+ * quotes around the value
+ * @param {field} field the field to be turned into a csv string,
+ * may be of any type
+ * @returns {string} a csv-ified version of the field
+ */
+ formatFieldAsCsv: function (field) {
+ if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
+ return '';
+ }
+ if (typeof(field.value) === 'number') {
+ return field.value;
+ }
+ if (typeof(field.value) === 'boolean') {
+ return (field.value ? 'TRUE' : 'FALSE') ;
+ }
+ if (typeof(field.value) === 'string') {
+ return '"' + field.value.replace(/"/g,'""') + '"';
+ }
+
+ return JSON.stringify(field.value);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name isIE
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Checks whether current browser is IE and returns it's version if it is
+ */
+ isIE: function () {
+ var match = navigator.userAgent.match(/(?:MSIE |Trident\/.*; rv:)(\d+)/);
+ return match ? parseInt(match[1]) : false;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name downloadFile
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Triggers download of a csv file. Logic provided
+ * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391
+ * @param {string} fileName the filename we'd like our file to be
+ * given
+ * @param {string} csvContent the csv content that we'd like to
+ * download as a file
+ * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\uFEFF)
+ */
+ downloadFile: function (fileName, csvContent, exporterOlderExcelCompatibility) {
+ var D = document;
+ var a = D.createElement('a');
+ var strMimeType = 'application/octet-stream;charset=utf-8';
+ var rawFile;
+ var ieVersion;
+
+ ieVersion = this.isIE();
+ if (ieVersion && ieVersion < 10) {
+ var frame = D.createElement('iframe');
+ document.body.appendChild(frame);
+
+ frame.contentWindow.document.open("text/html", "replace");
+ frame.contentWindow.document.write('sep=,\r\n' + csvContent);
+ frame.contentWindow.document.close();
+ frame.contentWindow.focus();
+ frame.contentWindow.document.execCommand('SaveAs', true, fileName);
+
+ document.body.removeChild(frame);
+ return true;
+ }
+
+ // IE10+
+ if (navigator.msSaveBlob) {
+ return navigator.msSaveOrOpenBlob(
+ new Blob(
+ [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
+ { type: strMimeType } ),
+ fileName
+ );
+ }
+
+ //html5 A[download]
+ if ('download' in a) {
+ var blob = new Blob(
+ [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
+ { type: strMimeType }
+ );
+ rawFile = URL.createObjectURL(blob);
+ a.setAttribute('download', fileName);
+ } else {
+ rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);
+ a.setAttribute('target', '_blank');
+ }
+
+ a.href = rawFile;
+ a.setAttribute('style', 'display:none;');
+ D.body.appendChild(a);
+ setTimeout(function() {
+ if (a.click) {
+ a.click();
+ // Workaround for Safari 5
+ } else if (document.createEvent) {
+ var eventObj = document.createEvent('MouseEvents');
+ eventObj.initEvent('click', true, true);
+ a.dispatchEvent(eventObj);
+ }
+ D.body.removeChild(a);
+
+ }, this.delay);
+ },
+
+ /**
+ * @ngdoc function
+ * @name pdfExport
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Exports rows from the grid in pdf format,
+ * the data exported is selected based on the provided options.
+ * Note that this function has a dependency on pdfMake, which must
+ * be installed. The resulting pdf opens in a new
+ * browser window.
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {string} rowTypes which rows to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ * @param {string} colTypes which columns to export, valid values are
+ * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
+ * uiGridExporterConstants.SELECTED
+ */
+ pdfExport: function (grid, rowTypes, colTypes) {
+ var self = this;
+ this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {
+ var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);
+ var exportData = self.getData(grid, rowTypes, colTypes);
+ var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);
+
+ if (self.isIE()) {
+ self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);
+ } else {
+ pdfMake.createPdf(docDefinition).open();
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name downloadPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Generates and retrieves the pdf as a blob, then downloads
+ * it as a file. Only used in IE, in all other browsers we use the native
+ * pdfMake.open function to just open the PDF
+ * @param {string} fileName the filename to give to the pdf, can be set
+ * through exporterPdfFilename
+ * @param {object} docDefinition a pdf docDefinition that we can generate
+ * and get a blob from
+ */
+ downloadPDF: function (fileName, docDefinition) {
+ var D = document;
+ var a = D.createElement('a');
+ var strMimeType = 'application/octet-stream;charset=utf-8';
+ var rawFile;
+ var ieVersion;
+
+ ieVersion = this.isIE();
+ var doc = pdfMake.createPdf(docDefinition);
+ var blob;
+
+ doc.getBuffer( function (buffer) {
+ blob = new Blob([buffer]);
+
+ if (ieVersion && ieVersion < 10) {
+ var frame = D.createElement('iframe');
+ document.body.appendChild(frame);
+
+ frame.contentWindow.document.open("text/html", "replace");
+ frame.contentWindow.document.write(blob);
+ frame.contentWindow.document.close();
+ frame.contentWindow.focus();
+ frame.contentWindow.document.execCommand('SaveAs', true, fileName);
+
+ document.body.removeChild(frame);
+ return true;
+ }
+
+ // IE10+
+ if (navigator.msSaveBlob) {
+ return navigator.msSaveBlob(
+ blob, fileName
+ );
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name renderAsPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders the data into a pdf, and opens that pdf.
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {array} exportColumnHeaders an array of column headers,
+ * where each header is an object with name, width and maybe alignment
+ * @param {array} exportData an array of rows, where each row is
+ * an array of column data
+ * @returns {object} a pdfMake format document definition, ready
+ * for generation
+ */
+ prepareAsPdf: function(grid, exportColumnHeaders, exportData) {
+ var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );
+
+ var headerColumns = exportColumnHeaders.map( function( header ) {
+ return { text: header.displayName, style: 'tableHeader' };
+ });
+
+ var stringData = exportData.map(this.formatRowAsPdf(this));
+
+ var allData = [headerColumns].concat(stringData);
+
+ var docDefinition = {
+ pageOrientation: grid.options.exporterPdfOrientation,
+ pageSize: grid.options.exporterPdfPageSize,
+ content: [{
+ style: 'tableStyle',
+ table: {
+ headerRows: 1,
+ widths: headerWidths,
+ body: allData
+ }
+ }],
+ styles: {
+ tableStyle: grid.options.exporterPdfTableStyle,
+ tableHeader: grid.options.exporterPdfTableHeaderStyle
+ },
+ defaultStyle: grid.options.exporterPdfDefaultStyle
+ };
+
+ if ( grid.options.exporterPdfLayout ){
+ docDefinition.layout = grid.options.exporterPdfLayout;
+ }
+
+ if ( grid.options.exporterPdfHeader ){
+ docDefinition.header = grid.options.exporterPdfHeader;
+ }
+
+ if ( grid.options.exporterPdfFooter ){
+ docDefinition.footer = grid.options.exporterPdfFooter;
+ }
+
+ if ( grid.options.exporterPdfCustomFormatter ){
+ docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );
+ }
+ return docDefinition;
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name calculatePdfHeaderWidths
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Determines the column widths base on the
+ * widths we got from the grid. If the column is drawn
+ * then we have a drawnWidth. If the column is not visible
+ * then we have '*', 'x%' or a width. When columns are
+ * not visible they don't contribute to the overall gridWidth,
+ * so we need to adjust to allow for extra columns
+ *
+ * Our basic heuristic is to take the current gridWidth, plus
+ * numeric columns and call this the base gridwidth.
+ *
+ * To that we add 100 for any '*' column, and x% of the base gridWidth
+ * for any column that is a %
+ *
+ * @param {Grid} grid the grid from which data should be exported
+ * @param {array} exportHeaders array of header information
+ * @returns {object} an array of header widths
+ */
+ calculatePdfHeaderWidths: function ( grid, exportHeaders ) {
+ var baseGridWidth = 0;
+ exportHeaders.forEach( function(value){
+ if (typeof(value.width) === 'number'){
+ baseGridWidth += value.width;
+ }
+ });
+
+ var extraColumns = 0;
+ exportHeaders.forEach( function(value){
+ if (value.width === '*'){
+ extraColumns += 100;
+ }
+ if (typeof(value.width) === 'string' && value.width.match(/(\d)*%/)) {
+ var percent = parseInt(value.width.match(/(\d)*%/)[0]);
+
+ value.width = baseGridWidth * percent / 100;
+ extraColumns += value.width;
+ }
+ });
+
+ var gridWidth = baseGridWidth + extraColumns;
+
+ return exportHeaders.map(function( header ) {
+ return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;
+ });
+
+ },
+
+ /**
+ * @ngdoc function
+ * @name formatRowAsPdf
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a row in a format consumable by PDF,
+ * mainly meaning casting everything to a string
+ * @param {exporterService} exporter pass in exporter
+ * @param {array} row the row to be turned into a csv string
+ * @returns {string} a csv-ified version of the row
+ */
+ formatRowAsPdf: function ( exporter ) {
+ return function( row ) {
+ return row.map(exporter.formatFieldAsPdfString);
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name formatFieldAsCsv
+ * @methodOf ui.grid.exporter.service:uiGridExporterService
+ * @description Renders a single field as a pdf-able field, which
+ * is different from a csv field only in that strings don't have quotes
+ * around them
+ * @param {field} field the field to be turned into a pdf string,
+ * may be of any type
+ * @returns {string} a string-ified version of the field
+ */
+ formatFieldAsPdfString: function (field) {
+ var returnVal;
+ if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
+ returnVal = '';
+ } else if (typeof(field.value) === 'number') {
+ returnVal = field.value.toString();
+ } else if (typeof(field.value) === 'boolean') {
+ returnVal = (field.value ? 'TRUE' : 'FALSE') ;
+ } else if (typeof(field.value) === 'string') {
+ returnVal = field.value.replace(/"/g,'""');
+ } else {
+ returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
+ }
+
+ if (field.alignment && typeof(field.alignment) === 'string' ){
+ returnVal = { text: returnVal, alignment: field.alignment };
+ }
+
+ return returnVal;
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.exporter.directive:uiGridExporter
+ * @element div
+ * @restrict A
+ *
+ * @description Adds exporter features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.gridOptions = {
+ enableGridMenu: true,
+ exporterMenuCsv: false,
+ columnDefs: [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ],
+ data: $scope.data
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-exporter></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',
+ function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridExporterService.initializeGrid(uiGridCtrl.grid);
+ uiGridCtrl.grid.exporter.$scope = $scope;
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.grouping
+ * @description
+ *
+ * # ui.grid.grouping
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides grouping of rows based on the data in them, similar
+ * in concept to excel grouping. You can group multiple columns, resulting in
+ * nested grouping.
+ *
+ * In concept this feature is similar to sorting + grid footer/aggregation, it
+ * sorts the data based on the grouped columns, then creates group rows that
+ * reflect a break in the data. Each of those group rows can have aggregations for
+ * the data within that group.
+ *
+ * This feature leverages treeBase to provide the tree functionality itself,
+ * the key thing this feature does therefore is to set treeLevels on the rows
+ * and insert the group headers.
+ *
+ * Design information:
+ * -------------------
+ *
+ * Each column will get new menu items - group by, and aggregate by. Group by
+ * will cause this column to be sorted (if not already), and will move this column
+ * to the front of the sorted columns (i.e. grouped columns take precedence over
+ * sorted columns). It will respect the sort order already set if there is one,
+ * and it will allow the sorting logic to change that sort order, it just forces
+ * the column to the front of the sorting. You can group by multiple columns, the
+ * logic will add this column to the sorting after any already grouped columns.
+ *
+ * Once a grouping is defined, grouping logic is added to the rowsProcessors. This
+ * will process the rows, identifying a break in the data value, and inserting a grouping row.
+ * Grouping rows have specific attributes on them:
+ *
+ * - internalRow = true: tells us that this isn't a real row, so we can ignore it
+ * from any processing that it looking at core data rows. This is used by the core
+ * logic (or will be one day), as it's not grouping specific
+ * - groupHeader = true: tells us this is a groupHeader. This is used by the grouping logic
+ * to know if this is a groupHeader row or not
+ *
+ * Since the logic is baked into the rowsProcessors, it should get triggered whenever
+ * row order or filtering or anything like that is changed. In order to avoid the row instantiation
+ * time, and to preserve state across invocations, we hold a cache of the rows that we created
+ * last time, and we use them again this time if we can.
+ *
+ * By default rows are collapsed, which means all data rows have their visible property
+ * set to false, and only level 0 group rows are set to visible.
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.grouping"></div>
+ */
+
+ var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.constant:uiGridGroupingConstants
+ *
+ * @description constants available in grouping module, this includes
+ * all the constants declared in the treeBase module (these are manually copied
+ * as there isn't an easy way to include constants in another constants file, and
+ * we don't want to make users include treeBase)
+ *
+ */
+ module.constant('uiGridGroupingConstants', {
+ featureName: "grouping",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.grouping.service:uiGridGroupingService
+ *
+ * @description Services for grouping features
+ */
+ module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',
+ function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+ uiGridTreeBaseService.initializeGrid( grid, $scope );
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.grid:grouping
+ *
+ * @description Grid properties and functions added for grouping
+ */
+ grid.grouping = {};
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.grouping.grid:grouping
+ * @name groupHeaderCache
+ *
+ * @description Cache that holds the group header rows we created last time, we'll
+ * reuse these next time, not least because they hold our expanded states.
+ *
+ * We need to take care with these that they don't become a memory leak, we
+ * create a new cache each time using the values from the old cache. This works
+ * so long as we're creating group rows for invisible rows as well.
+ *
+ * The cache is a nested hash, indexed on the value we grouped by. So if we
+ * grouped by gender then age, we'd maybe have something like:
+ * ```
+ * {
+ * male: {
+ * row: <pointer to the old row>,
+ * children: {
+ * 22: { row: <pointer to the old row> },
+ * 31: { row: <pointer to the old row> }
+ * },
+ * female: {
+ * row: <pointer to the old row>,
+ * children: {
+ * 28: { row: <pointer to the old row> },
+ * 55: { row: <pointer to the old row> }
+ * }
+ * }
+ * ```
+ *
+ * We create new rows for any missing rows, this means that they come in as collapsed.
+ *
+ */
+ grid.grouping.groupHeaderCache = {};
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerRowsProcessor(service.groupRows, 400);
+
+ grid.registerColumnBuilder( service.groupingColumnBuilder);
+
+ grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:PublicApi
+ *
+ * @description Public Api for grouping feature
+ */
+ var publicApi = {
+ events: {
+ grouping: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.grouping.api:PublicApi
+ * @name aggregationChanged
+ * @description raised whenever aggregation is changed, added or removed from a column
+ *
+ * <pre>
+ * gridApi.grouping.on.aggregationChanged(scope,function(col){})
+ * </pre>
+ * @param {gridCol} col the column which on which aggregation changed. The aggregation
+ * type is available as `col.treeAggregation.type`
+ */
+ aggregationChanged: {},
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.grouping.api:PublicApi
+ * @name groupingChanged
+ * @description raised whenever the grouped columns changes
+ *
+ * <pre>
+ * gridApi.grouping.on.groupingChanged(scope,function(col){})
+ * </pre>
+ * @param {gridCol} col the column which on which grouping changed. The new grouping is
+ * available as `col.grouping`
+ */
+ groupingChanged: {}
+ }
+ },
+ methods: {
+ grouping: {
+ /**
+ * @ngdoc function
+ * @name getGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Get the grouping configuration for this grid,
+ * used by the saveState feature. Adds expandedState to the information
+ * provided by the internal getGrouping, and removes any aggregations that have a source
+ * of grouping (i.e. will be automatically reapplied when we regroup the column)
+ * Returned grouping is an object
+ * `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`
+ * where grouping contains an array of objects:
+ * `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`
+ * and aggregations contains an array of objects:
+ * `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`
+ * and expandedState is a hash of the currently expanded nodes
+ *
+ * The groupArray will be sorted by groupPriority.
+ *
+ * @param {boolean} getExpanded whether or not to return the expanded state
+ * @returns {object} grouping configuration
+ */
+ getGrouping: function ( getExpanded ) {
+ var grouping = service.getGrouping(grid);
+
+ grouping.grouping.forEach( function( group ) {
+ group.colName = group.col.name;
+ delete group.col;
+ });
+
+ grouping.aggregations.forEach( function( aggregation ) {
+ aggregation.colName = aggregation.col.name;
+ delete aggregation.col;
+ });
+
+ grouping.aggregations = grouping.aggregations.filter( function( aggregation ){
+ return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';
+ });
+
+ if ( getExpanded ){
+ grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );
+ }
+
+ return grouping;
+ },
+
+ /**
+ * @ngdoc function
+ * @name setGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Set the grouping configuration for this grid,
+ * used by the saveState feature, but can also be used by any
+ * user to specify a combined grouping and aggregation configuration
+ * @param {object} config the config you want to apply, in the format
+ * provided out by getGrouping
+ */
+ setGrouping: function ( config ) {
+ service.setGrouping(grid, config);
+ },
+
+ /**
+ * @ngdoc function
+ * @name groupColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Adds this column to the existing grouping, at the end of the priority order.
+ * If the column doesn't have a sort, adds one, by default ASC
+ *
+ * This column will move to the left of any non-group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {string} columnName the name of the column we want to group
+ */
+ groupColumn: function( columnName ) {
+ var column = grid.getColumn(columnName);
+ service.groupColumn(grid, column);
+ },
+
+ /**
+ * @ngdoc function
+ * @name ungroupColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Removes the groupPriority from this column. If the
+ * column was previously aggregated the aggregation will come back.
+ * The sort will remain.
+ *
+ * This column will move to the right of any other group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {string} columnName the name of the column we want to ungroup
+ */
+ ungroupColumn: function( columnName ) {
+ var column = grid.getColumn(columnName);
+ service.ungroupColumn(grid, column);
+ },
+
+ /**
+ * @ngdoc function
+ * @name clearGrouping
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
+ * as we don't know whether that sorting was added by grouping or was there beforehand
+ *
+ */
+ clearGrouping: function() {
+ service.clearGrouping(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name aggregateColumn
+ * @methodOf ui.grid.grouping.api:PublicApi
+ * @description Sets the aggregation type on a column, if the
+ * column is currently grouped then it removes the grouping first.
+ * If the aggregationDef is null then will result in the aggregation
+ * being removed
+ *
+ * @param {string} columnName the column we want to aggregate
+ * @param {string} or {function} aggregationDef one of the recognised types
+ * from uiGridGroupingConstants or a custom aggregation function.
+ * @param {string} aggregationLabel (optional) The label to use for this aggregation.
+ */
+ aggregateColumn: function( columnName, aggregationDef, aggregationLabel){
+ var column = grid.getColumn(columnName);
+ service.aggregateColumn( grid, column, aggregationDef, aggregationLabel);
+ }
+
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ grid.api.core.on.sortChanged( $scope, service.tidyPriorities);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:GridOptions
+ *
+ * @description GridOptions for grouping feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableGrouping
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description Enable row grouping for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableGrouping = gridOptions.enableGrouping !== false;
+
+ /**
+ * @ngdoc object
+ * @name groupingShowCounts
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a
+ * sortingAlgorithm which relies on a specific format or data type, showing counts may cause that
+ * to break, since the group header rows will always be a string with groupingShowCounts enabled.
+ * <br/>Defaults to true except on columns of type 'date'
+ */
+ gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;
+
+ /**
+ * @ngdoc object
+ * @name groupingNullLabel
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.
+ * <br/>Defaults to "Null"
+ */
+ gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;
+
+ /**
+ * @ngdoc object
+ * @name enableGroupHeaderSelection
+ * @propertyOf ui.grid.grouping.api:GridOptions
+ * @description Allows group header rows to be selected.
+ * <br/>Defaults to false
+ */
+ gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupingColumnBuilder
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Sets the grouping defaults based on the columnDefs
+ *
+ * @param {object} colDef columnDef we're basing on
+ * @param {GridCol} col the column we're to update
+ * @param {object} gridOptions the options we should use
+ * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
+ */
+ groupingColumnBuilder: function (colDef, col, gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.grouping.api:ColumnDef
+ *
+ * @description ColumnDef for grouping feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableGrouping
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Enable grouping on this column
+ * <br/>Defaults to true.
+ */
+ if (colDef.enableGrouping === false){
+ return;
+ }
+
+ /**
+ * @ngdoc object
+ * @name grouping
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Set the grouping for a column. Format is:
+ * ```
+ * {
+ * groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>
+ * }
+ * ```
+ *
+ * **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation
+ * setting in treeBase**
+ *
+ * We group in the priority order given, this will also put these columns to the high order of the sort irrespective
+ * of the sort priority given them. If there is no sort defined then we sort ascending, if there is a sort defined then
+ * we use that sort.
+ *
+ * If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the
+ * aggregation types to determine what sort of aggregation we can do. Values are in the constants file, but
+ * include SUM, COUNT, MAX, MIN
+ *
+ * groupPriorities should generally be sequential, if they're not then the next time getGrouping is called
+ * we'll renumber them to be sequential.
+ * <br/>Defaults to undefined.
+ */
+
+ if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {
+ col.grouping = angular.copy(colDef.grouping);
+ if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ){
+ col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
+ col.treeAggregationFinalizerFn = service.groupedFinalizerFn;
+ }
+ } else if (typeof(col.grouping) === 'undefined'){
+ col.grouping = {};
+ }
+
+ if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0){
+ col.suppressRemoveSort = true;
+ }
+
+ var groupColumn = {
+ name: 'ui.grid.grouping.group',
+ title: i18nService.get().grouping.group,
+ icon: 'ui-grid-icon-indent-right',
+ shown: function () {
+ return typeof(this.context.col.grouping) === 'undefined' ||
+ typeof(this.context.col.grouping.groupPriority) === 'undefined' ||
+ this.context.col.grouping.groupPriority < 0;
+ },
+ action: function () {
+ service.groupColumn( this.context.col.grid, this.context.col );
+ }
+ };
+
+ var ungroupColumn = {
+ name: 'ui.grid.grouping.ungroup',
+ title: i18nService.get().grouping.ungroup,
+ icon: 'ui-grid-icon-indent-left',
+ shown: function () {
+ return typeof(this.context.col.grouping) !== 'undefined' &&
+ typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&
+ this.context.col.grouping.groupPriority >= 0;
+ },
+ action: function () {
+ service.ungroupColumn( this.context.col.grid, this.context.col );
+ }
+ };
+
+ var aggregateRemove = {
+ name: 'ui.grid.grouping.aggregateRemove',
+ title: i18nService.get().grouping.aggregate_remove,
+ shown: function () {
+ return typeof(this.context.col.treeAggregationFn) !== 'undefined';
+ },
+ action: function () {
+ service.aggregateColumn( this.context.col.grid, this.context.col, null);
+ }
+ };
+
+ // generic adder for the aggregation menus, which follow a pattern
+ var addAggregationMenu = function(type, title){
+ title = title || i18nService.get().grouping['aggregate_' + type] || type;
+ var menuItem = {
+ name: 'ui.grid.grouping.aggregate' + type,
+ title: title,
+ shown: function () {
+ return typeof(this.context.col.treeAggregation) === 'undefined' ||
+ typeof(this.context.col.treeAggregation.type) === 'undefined' ||
+ this.context.col.treeAggregation.type !== type;
+ },
+ action: function () {
+ service.aggregateColumn( this.context.col.grid, this.context.col, type);
+ }
+ };
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {
+ col.menuItems.push(menuItem);
+ }
+ };
+
+ /**
+ * @ngdoc object
+ * @name groupingShowGroupingMenu
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Show the grouping (group and ungroup items) menu on this column
+ * <br/>Defaults to true.
+ */
+ if ( col.colDef.groupingShowGroupingMenu !== false ){
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {
+ col.menuItems.push(groupColumn);
+ }
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {
+ col.menuItems.push(ungroupColumn);
+ }
+ }
+
+
+ /**
+ * @ngdoc object
+ * @name groupingShowAggregationMenu
+ * @propertyOf ui.grid.grouping.api:ColumnDef
+ * @description Show the aggregation menu on this column
+ * <br/>Defaults to true.
+ */
+ if ( col.colDef.groupingShowAggregationMenu !== false ){
+ angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name){
+ addAggregationMenu(name);
+ });
+ angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name){
+ addAggregationMenu(name, aggregationDef.menuTitle);
+ });
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {
+ col.menuItems.push(aggregateRemove);
+ }
+ }
+ },
+
+
+
+
+ /**
+ * @ngdoc function
+ * @name groupingColumnProcessor
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Moves the columns around based on which are grouped
+ *
+ * @param {array} columns the columns to consider rendering
+ * @param {array} rows the grid rows, which we don't use but are passed to us
+ * @returns {array} updated columns array
+ */
+ groupingColumnProcessor: function( columns, rows ) {
+ var grid = this;
+
+ columns = service.moveGroupColumns(this, columns, rows);
+ return columns;
+ },
+
+ /**
+ * @ngdoc function
+ * @name groupedFinalizerFn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Used on group columns to display the rendered value and optionally
+ * display the count of rows.
+ *
+ * @param {aggregation} the aggregation entity for a grouped column
+ */
+ groupedFinalizerFn: function( aggregation ){
+ var col = this;
+
+ if ( typeof(aggregation.groupVal) !== 'undefined') {
+ aggregation.rendered = aggregation.groupVal;
+ if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' ){
+ aggregation.rendered += (' (' + aggregation.value + ')');
+ }
+ } else {
+ aggregation.rendered = null;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name moveGroupColumns
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Moves the column order so that the grouped columns are lined up
+ * to the left (well, unless you're RTL, then it's the right). By doing this in
+ * the columnsProcessor, we make it transient - when the column is ungrouped it'll
+ * go back to where it was.
+ *
+ * Does nothing if the option `moveGroupColumns` is set to false.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} columns the columns that we should process/move
+ * @param {array} rows the grid rows
+ * @returns {array} updated columns
+ */
+ moveGroupColumns: function( grid, columns, rows ){
+ if ( grid.options.moveGroupColumns === false){
+ return columns;
+ }
+
+ columns.forEach( function(column, index){
+ // position used to make stable sort in moveGroupColumns
+ column.groupingPosition = index;
+ });
+
+ columns.sort(function(a, b){
+ var a_group, b_group;
+ if (a.isRowHeader){
+ a_group = -1000;
+ }
+ else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0){
+ a_group = null;
+ } else {
+ a_group = a.grouping.groupPriority;
+ }
+
+ if (b.isRowHeader){
+ b_group = -1000;
+ }
+ else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0){
+ b_group = null;
+ } else {
+ b_group = b.grouping.groupPriority;
+ }
+
+ // groups get sorted to the top
+ if ( a_group !== null && b_group === null) { return -1; }
+ if ( b_group !== null && a_group === null) { return 1; }
+ if ( a_group !== null && b_group !== null) {return a_group - b_group; }
+
+ return a.groupingPosition - b.groupingPosition;
+ });
+
+ columns.forEach( function(column, index) {
+ delete column.groupingPosition;
+ });
+
+ return columns;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Adds this column to the existing grouping, at the end of the priority order.
+ * If the column doesn't have a sort, adds one, by default ASC
+ *
+ * This column will move to the left of any non-group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to group
+ */
+ groupColumn: function( grid, column){
+ if ( typeof(column.grouping) === 'undefined' ){
+ column.grouping = {};
+ }
+
+ // set the group priority to the next number in the hierarchy
+ var existingGrouping = service.getGrouping( grid );
+ column.grouping.groupPriority = existingGrouping.grouping.length;
+
+ // add sort if not present
+ if ( !column.sort ){
+ column.sort = { direction: uiGridConstants.ASC };
+ } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ){
+ column.sort.direction = uiGridConstants.ASC;
+ }
+
+ column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };
+ column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
+ column.treeAggregationFinalizerFn = service.groupedFinalizerFn;
+
+ grid.api.grouping.raise.groupingChanged(column);
+ // This indirectly calls service.tidyPriorities( grid );
+ grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name ungroupColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Removes the groupPriority from this column. If the
+ * column was previously aggregated the aggregation will come back.
+ * The sort will remain.
+ *
+ * This column will move to the right of any other group columns, the
+ * move is handled in a columnProcessor, so gets called as part of refresh
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to ungroup
+ */
+ ungroupColumn: function( grid, column){
+ if ( typeof(column.grouping) === 'undefined' ){
+ return;
+ }
+
+ delete column.grouping.groupPriority;
+ delete column.treeAggregation;
+ delete column.customTreeAggregationFinalizer;
+
+ service.tidyPriorities( grid );
+
+ grid.api.grouping.raise.groupingChanged(column);
+
+ grid.queueGridRefresh();
+ },
+
+ /**
+ * @ngdoc function
+ * @name aggregateColumn
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Sets the aggregation type on a column, if the
+ * column is currently grouped then it removes the grouping first.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridCol} column the column we want to aggregate
+ * @param {string} one of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions
+ */
+ aggregateColumn: function( grid, column, aggregationType){
+
+ if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ service.ungroupColumn( grid, column );
+ }
+
+ var aggregationDef = {};
+ if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ){
+ aggregationDef = grid.options.treeCustomAggregations[aggregationType];
+ } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ){
+ aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];
+ }
+
+ column.treeAggregation = { type: aggregationType, label: i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };
+ column.treeAggregationFn = aggregationDef.aggregationFn;
+ column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;
+
+ grid.api.grouping.raise.aggregationChanged(column);
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Set the grouping based on a config object, used by the save state feature
+ * (more specifically, by the restore function in that feature )
+ *
+ * @param {Grid} grid grid object
+ * @param {object} config the config we want to set, same format as that returned by getGrouping
+ */
+ setGrouping: function ( grid, config ){
+ if ( typeof(config) === 'undefined' ){
+ return;
+ }
+
+ // first remove any existing grouping
+ service.clearGrouping(grid);
+
+ if ( config.grouping && config.grouping.length && config.grouping.length > 0 ){
+ config.grouping.forEach( function( group ) {
+ var col = grid.getColumn(group.colName);
+
+ if ( col ) {
+ service.groupColumn( grid, col );
+ }
+ });
+ }
+
+ if ( config.aggregations && config.aggregations.length ){
+ config.aggregations.forEach( function( aggregation ) {
+ var col = grid.getColumn(aggregation.colName);
+
+ if ( col ) {
+ service.aggregateColumn( grid, col, aggregation.aggregation.type );
+ }
+ });
+ }
+
+ if ( config.rowExpandedStates ){
+ service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name clearGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
+ * as we don't know whether that sorting was added by grouping or was there beforehand
+ *
+ * @param {Grid} grid grid object
+ */
+ clearGrouping: function( grid ) {
+ var currentGrouping = service.getGrouping(grid);
+
+ if ( currentGrouping.grouping.length > 0 ){
+ currentGrouping.grouping.forEach( function( group ) {
+ if (!group.col){
+ // should have a group.colName if there's no col
+ group.col = grid.getColumn(group.colName);
+ }
+ service.ungroupColumn(grid, group.col);
+ });
+ }
+
+ if ( currentGrouping.aggregations.length > 0 ){
+ currentGrouping.aggregations.forEach( function( aggregation ){
+ if (!aggregation.col){
+ // should have a group.colName if there's no col
+ aggregation.col = grid.getColumn(aggregation.colName);
+ }
+ service.aggregateColumn(grid, aggregation.col, null);
+ });
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name tidyPriorities
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Renumbers groupPriority and sortPriority such that
+ * groupPriority is contiguous, and sortPriority either matches
+ * groupPriority (for group columns), and otherwise is contiguous and
+ * higher than groupPriority.
+ *
+ * @param {Grid} grid grid object
+ */
+ tidyPriorities: function( grid ){
+ // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined
+ if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {
+ grid = this.grid;
+ }
+
+ var groupArray = [];
+ var sortArray = [];
+
+ grid.columns.forEach( function(column, index){
+ if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ groupArray.push(column);
+ } else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0){
+ sortArray.push(column);
+ }
+ });
+
+ groupArray.sort(function(a, b){ return a.grouping.groupPriority - b.grouping.groupPriority; });
+ groupArray.forEach( function(column, index){
+ column.grouping.groupPriority = index;
+ column.suppressRemoveSort = true;
+ if ( typeof(column.sort) === 'undefined'){
+ column.sort = {};
+ }
+ column.sort.priority = index;
+ });
+
+ var i = groupArray.length;
+ sortArray.sort(function(a, b){ return a.sort.priority - b.sort.priority; });
+ sortArray.forEach( function(column, index){
+ column.sort.priority = i;
+ column.suppressRemoveSort = column.colDef.suppressRemoveSort;
+ i++;
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name groupRows
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description The rowProcessor that creates the groupHeaders (i.e. does
+ * the actual grouping).
+ *
+ * Assumes it is always called after the sorting processor, guaranteed by the priority setting
+ *
+ * Processes all the rows in order, inserting a groupHeader row whenever there is a change
+ * in value of a grouped row, based on the sortAlgorithm used for the column. The group header row
+ * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset
+ * to {} if one is found.
+ *
+ * As it processes it maintains a `processingState` array. This records, for each level of grouping we're
+ * working with, the following information:
+ * ```
+ * {
+ * fieldName: name,
+ * col: col,
+ * initialised: boolean,
+ * currentValue: value,
+ * currentRow: gridRow,
+ * }
+ * ```
+ * We look for changes in the currentValue at any of the levels. Where we find a change we:
+ *
+ * - create a new groupHeader row in the array
+ *
+ * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
+ * @returns {array} the updated rows, including our new group rows
+ */
+ groupRows: function( renderableRows ) {
+ if (renderableRows.length === 0){
+ return renderableRows;
+ }
+
+ var grid = this;
+ grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};
+ grid.grouping.groupingHeaderCache = {};
+
+ var processingState = service.initialiseProcessingState( grid );
+
+ // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader
+ // Broken out as shouldn't create functions in a loop.
+ var updateProcessingState = function( groupFieldState, stateIndex ) {
+ var fieldValue = grid.getCellValue(row, groupFieldState.col);
+
+ // look for change of value - and insert a header
+ if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ){
+ service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );
+ i++;
+ }
+ };
+
+ // use a for loop because it's tolerant of the array length changing whilst we go - we can
+ // manipulate the iterator when we insert groupHeader rows
+ for (var i = 0; i < renderableRows.length; i++ ){
+ var row = renderableRows[i];
+
+ if ( row.visible ){
+ processingState.forEach( updateProcessingState );
+ }
+ }
+
+ delete grid.grouping.oldGroupingHeaderCache;
+ return renderableRows;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name initialiseProcessingState
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Creates the processing state array that is used
+ * for groupRows.
+ *
+ * @param {Grid} grid grid object
+ * @returns {array} an array in the format described in the groupRows method,
+ * initialised with blank values
+ */
+ initialiseProcessingState: function( grid ){
+ var processingState = [];
+ var columnSettings = service.getGrouping( grid );
+
+ columnSettings.grouping.forEach( function( groupItem, index){
+ processingState.push({
+ fieldName: groupItem.field,
+ col: groupItem.col,
+ initialised: false,
+ currentValue: null,
+ currentRow: null
+ });
+ });
+
+ return processingState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getGrouping
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Get the grouping settings from the columns. As a side effect
+ * this always renumbers the grouping starting at 0
+ * @param {Grid} grid grid object
+ * @returns {array} an array of the group fields, in order of priority
+ */
+ getGrouping: function( grid ){
+ var groupArray = [];
+ var aggregateArray = [];
+
+ // get all the grouping
+ grid.columns.forEach( function(column, columnIndex){
+ if ( column.grouping ){
+ if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
+ groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });
+ }
+ }
+ if ( column.treeAggregation && column.treeAggregation.type ){
+ aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });
+ }
+ });
+
+ // sort grouping into priority order
+ groupArray.sort( function(a, b){
+ return a.groupPriority - b.groupPriority;
+ });
+
+ // renumber the priority in case it was somewhat messed up, then remove the grouping reference
+ groupArray.forEach( function( group, index) {
+ group.grouping.groupPriority = index;
+ group.groupPriority = index;
+ delete group.grouping;
+ });
+
+ return { grouping: groupArray, aggregations: aggregateArray };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name insertGroupHeader
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Create a group header row, and link it to the various configuration
+ * items that we use.
+ *
+ * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} renderableRows the rows that we are processing
+ * @param {number} rowIndex the row we were up to processing
+ * @param {array} processingState the current processing state
+ * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -
+ * i.e. the column that we want to create a header for
+ */
+ insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {
+ // set the value that caused the end of a group into the header row and the processing state
+ var fieldName = processingState[stateIndex].fieldName;
+ var col = processingState[stateIndex].col;
+
+ var newValue = grid.getCellValue(renderableRows[rowIndex], col);
+ var newDisplayValue = newValue;
+ if ( typeof(newValue) === 'undefined' || newValue === null ) {
+ newDisplayValue = grid.options.groupingNullLabel;
+ }
+
+ var cacheItem = grid.grouping.oldGroupingHeaderCache;
+ for ( var i = 0; i < stateIndex; i++ ){
+ if ( cacheItem && cacheItem[processingState[i].currentValue] ){
+ cacheItem = cacheItem[processingState[i].currentValue].children;
+ }
+ }
+
+ var headerRow;
+ if ( cacheItem && cacheItem[newValue]){
+ headerRow = cacheItem[newValue].row;
+ headerRow.entity = {};
+ } else {
+ headerRow = new GridRow( {}, null, grid );
+ gridClassFactory.rowTemplateAssigner.call(grid, headerRow);
+ }
+
+ headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };
+ headerRow.treeLevel = stateIndex;
+ headerRow.groupHeader = true;
+ headerRow.internalRow = true;
+ headerRow.enableCellEdit = false;
+ headerRow.enableSelection = grid.options.enableGroupHeaderSelection;
+ processingState[stateIndex].initialised = true;
+ processingState[stateIndex].currentValue = newValue;
+ processingState[stateIndex].currentRow = headerRow;
+
+ // set all processing states below this one to not be initialised - change of this state
+ // means all those need to start again
+ service.finaliseProcessingState( processingState, stateIndex + 1);
+
+ // insert our new header row
+ renderableRows.splice(rowIndex, 0, headerRow);
+
+ // add our new header row to the cache
+ cacheItem = grid.grouping.groupingHeaderCache;
+ for ( i = 0; i < stateIndex; i++ ){
+ cacheItem = cacheItem[processingState[i].currentValue].children;
+ }
+ cacheItem[newValue] = { row: headerRow, children: {} };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name finaliseProcessingState
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Set all processing states lower than the one that had a break in value to
+ * no longer be initialised. Render the counts into the entity ready for display.
+ *
+ * @param {Grid} grid grid object
+ * @param {array} processingState the current processing state
+ * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all
+ * processing states after this need to be finalised
+ */
+ finaliseProcessingState: function( processingState, stateIndex ){
+ for ( var i = stateIndex; i < processingState.length; i++){
+ processingState[i].initialised = false;
+ processingState[i].currentRow = null;
+ processingState[i].currentValue = null;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getRowExpandedStates
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Extract the groupHeaderCache hash, pulling out only the states.
+ *
+ * The example below shows a grid that is grouped by gender then age
+ *
+ * <pre>
+ * {
+ * male: {
+ * state: 'expanded',
+ * children: {
+ * 22: { state: 'expanded' },
+ * 30: { state: 'collapsed' }
+ * }
+ * },
+ * female: {
+ * state: 'expanded',
+ * children: {
+ * 28: { state: 'expanded' },
+ * 55: { state: 'collapsed' }
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @param {Grid} grid grid object
+ * @returns {hash} the expanded states as a hash
+ */
+ getRowExpandedStates: function(treeChildren){
+ if ( typeof(treeChildren) === 'undefined' ){
+ return {};
+ }
+
+ var newChildren = {};
+
+ angular.forEach( treeChildren, function( value, key ){
+ newChildren[key] = { state: value.row.treeNode.state };
+ if ( value.children ){
+ newChildren[key].children = service.getRowExpandedStates( value.children );
+ } else {
+ newChildren[key].children = {};
+ }
+ });
+
+ return newChildren;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name applyRowExpandedStates
+ * @methodOf ui.grid.grouping.service:uiGridGroupingService
+ * @description Take a hash in the format as created by getRowExpandedStates,
+ * and apply it to the grid.grouping.groupHeaderCache.
+ *
+ * Takes a treeSubset, and applies to a treeSubset - so can be called
+ * recursively.
+ *
+ * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of
+ * the children of that hash
+ * @returns {hash} expandedStates can be the full expanded states, or children
+ * of that expanded states (which hopefully matches the subset of the groupHeaderCache)
+ */
+ applyRowExpandedStates: function( currentNode, expandedStates ){
+ if ( typeof(expandedStates) === 'undefined' ){
+ return;
+ }
+
+ angular.forEach(expandedStates, function( value, key ) {
+ if ( currentNode[key] ){
+ currentNode[key].row.treeNode.state = value.state;
+
+ if (value.children && currentNode[key].children){
+ service.applyRowExpandedStates( currentNode[key].children, value.children );
+ }
+ }
+ });
+ }
+
+
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.grouping.directive:uiGridGrouping
+ * @element div
+ * @restrict A
+ *
+ * @description Adds grouping features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+
+ $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-grouping></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService', '$templateCache',
+ function (uiGridGroupingConstants, uiGridGroupingService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if (uiGridCtrl.grid.options.enableGrouping !== false){
+ uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);
+ }
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.importer
+ * @description
+ *
+ * # ui.grid.importer
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to import data into the grid. It
+ * uses the column defs to work out which data belongs in which column,
+ * and creates entities from a configured class (typically a $resource).
+ *
+ * If the rowEdit feature is enabled, it also calls save on those newly
+ * created objects, and then displays any errors in the imported data.
+ *
+ * Currently the importer imports only CSV and json files, although provision has been
+ * made to process other file formats, and these can be added over time.
+ *
+ * For json files, the properties within each object in the json must match the column names
+ * (to put it another way, the importer doesn't process the json, it just copies the objects
+ * within the json into a new instance of the specified object type)
+ *
+ * For CSV import, the default column identification relies on each column in the
+ * header row matching a column.name or column.displayName. Optionally, a column identification
+ * callback can be used. This allows matching using other attributes, which is particularly
+ * useful if your application has internationalised column headings (i.e. the headings that
+ * the user sees don't match the column names).
+ *
+ * The importer makes use of the grid menu as the UI for requesting an
+ * import.
+ *
+ * <div ui-grid-importer></div>
+ */
+
+ var module = angular.module('ui.grid.importer', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.constant:uiGridImporterConstants
+ *
+ * @description constants available in importer module
+ */
+
+ module.constant('uiGridImporterConstants', {
+ featureName: 'importer'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.importer.service:uiGridImporterService
+ *
+ * @description Services for importer feature
+ */
+ module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',
+ function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {
+
+ var service = {
+
+ initializeGrid: function ($scope, grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.importer = {
+ $scope: $scope
+ };
+
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.api:PublicApi
+ *
+ * @description Public Api for importer feature
+ */
+ var publicApi = {
+ events: {
+ importer: {
+ }
+ },
+ methods: {
+ importer: {
+ /**
+ * @ngdoc function
+ * @name importFile
+ * @methodOf ui.grid.importer.api:PublicApi
+ * @description Imports a file into the grid using the file object
+ * provided. Bypasses the grid menu
+ * @param {File} fileObject the file we want to import, as a javascript
+ * File object
+ */
+ importFile: function ( fileObject ) {
+ service.importThisFile( grid, fileObject );
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ if ( grid.options.enableImporter && grid.options.importerShowMenu ){
+ if ( grid.api.core.addToGridMenu ){
+ service.addToMenu( grid );
+ } else {
+ // order of registration is not guaranteed, register in a little while
+ $interval( function() {
+ if (grid.api.core.addToGridMenu){
+ service.addToMenu( grid );
+ }
+ }, 100, 1);
+ }
+ }
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.importer.api:GridOptions
+ *
+ * @description GridOptions for importer feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @name enableImporter
+ * @description Whether or not importer is enabled. Automatically set
+ * to false if the user's browser does not support the required fileApi.
+ * Otherwise defaults to true.
+ *
+ */
+ if (gridOptions.enableImporter || gridOptions.enableImporter === undefined) {
+ if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {
+ gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');
+ gridOptions.enableImporter = false;
+ } else {
+ gridOptions.enableImporter = true;
+ }
+ } else {
+ gridOptions.enableImporter = false;
+ }
+
+ /**
+ * @ngdoc method
+ * @name importerProcessHeaders
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that will process headers using custom
+ * logic. Set this callback function if the headers that your user will provide in their
+ * import file don't necessarily match the grid header or field names. This might commonly
+ * occur where your application is internationalised, and therefore the field names
+ * that the user recognises are in a different language than the field names that
+ * ui-grid knows about.
+ *
+ * Defaults to the internal `processHeaders` method, which seeks to match using both
+ * displayName and column.name. Any non-matching columns are discarded.
+ *
+ * Your callback routine should respond by processing the header array, and returning an array
+ * of matching column names. A null value in any given position means "don't import this column"
+ *
+ * <pre>
+ * gridOptions.importerProcessHeaders: function( headerArray ) {
+ * var myHeaderColumns = [];
+ * var thisCol;
+ * headerArray.forEach( function( value, index ) {
+ * thisCol = mySpecialLookupFunction( value );
+ * myHeaderColumns.push( thisCol.name );
+ * });
+ *
+ * return myHeaderCols;
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerArray an array of the text from the first row of the csv file,
+ * which you need to match to column.names
+ * @returns {array} array of matching column names, in the same order as the headerArray
+ *
+ */
+ gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;
+
+ /**
+ * @ngdoc method
+ * @name importerHeaderFilter
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that will filter (usually translate) a single
+ * header. Used when you want to match the passed in column names to the column
+ * displayName after the header filter.
+ *
+ * Your callback routine needs to return the filtered header value.
+ * <pre>
+ * gridOptions.importerHeaderFilter: function( displayName ) {
+ * return $translate.instant( displayName );
+ * })
+ * </pre>
+ *
+ * or:
+ * <pre>
+ * gridOptions.importerHeaderFilter: $translate.instant
+ * </pre>
+ * @param {string} displayName the displayName that we'd like to translate
+ * @returns {string} the translated name
+ *
+ */
+ gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };
+
+ /**
+ * @ngdoc method
+ * @name importerErrorCallback
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A callback function that provides custom error handling, rather
+ * than the standard grid behaviour of an alert box and a console message. You
+ * might use this to internationalise the console log messages, or to write to a
+ * custom logging routine that returned errors to the server.
+ *
+ * <pre>
+ * gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {
+ * myUserDisplayRoutine( errorKey );
+ * myLoggingRoutine( consoleMessage, context );
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages
+ * in some way
+ * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,
+ * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray
+ * @param {string} consoleMessage the English console message that importer would have written
+ * @param {object} context the context data that importer would have appended to that console message,
+ * often the file content itself or the element that is in error
+ *
+ */
+ if ( !gridOptions.importerErrorCallback || typeof(gridOptions.importerErrorCallback) !== 'function' ){
+ delete gridOptions.importerErrorCallback;
+ }
+
+ /**
+ * @ngdoc method
+ * @name importerDataAddCallback
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @description A mandatory callback function that adds data to the source data array. The grid
+ * generally doesn't add rows to the source data array, it is tidier to handle this through a user
+ * callback.
+ *
+ * <pre>
+ * gridOptions.importerDataAddCallback: function( grid, newObjects ) {
+ * $scope.myData = $scope.myData.concat( newObjects );
+ * })
+ * </pre>
+ * @param {Grid} grid the grid we're importing into, may be useful in some way
+ * @param {array} newObjects an array of new objects that you should add to your data
+ *
+ */
+ if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {
+ gridUtil.logError("You have not set an importerDataAddCallback, importer is disabled");
+ gridOptions.enableImporter = false;
+ }
+
+ /**
+ * @ngdoc object
+ * @name importerNewObject
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @description An object on which we call `new` to create each new row before inserting it into
+ * the data array. Typically this would be a $resource entity, which means that if you're using
+ * the rowEdit feature, you can directly call save on this entity when the save event is triggered.
+ *
+ * Defaults to a vanilla javascript object
+ *
+ * @example
+ * <pre>
+ * gridOptions.importerNewObject = MyRes;
+ * </pre>
+ *
+ */
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.importer.api:GridOptions
+ * @name importerShowMenu
+ * @description Whether or not to show an item in the grid menu. Defaults to true.
+ *
+ */
+ gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.importer.api:GridOptions
+ * @name importerObjectCallback
+ * @description A callback that massages the data for each object. For example,
+ * you might have data stored as a code value, but display the decode. This callback
+ * can be used to change the decoded value back into a code. Defaults to doing nothing.
+ * @param {Grid} grid in case you need it
+ * @param {object} newObject the new object as importer has created it, modify it
+ * then return the modified version
+ * @returns {object} the modified object
+ * @example
+ * <pre>
+ * gridOptions.importerObjectCallback = function ( grid, newObject ) {
+ * switch newObject.status {
+ * case 'Active':
+ * newObject.status = 1;
+ * break;
+ * case 'Inactive':
+ * newObject.status = 2;
+ * break;
+ * }
+ * return newObject;
+ * };
+ * </pre>
+ */
+ gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addToMenu
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Adds import menu item to the grid menu,
+ * allowing the user to request import of a file
+ * @param {Grid} grid the grid into which data should be imported
+ */
+ addToMenu: function ( grid ) {
+ grid.api.core.addToGridMenu( grid, [
+ {
+ title: i18nService.getSafeText('gridMenu.importerTitle'),
+ order: 150
+ },
+ {
+ templateUrl: 'ui-grid/importerMenuItemContainer',
+ action: function ($event) {
+ this.grid.api.importer.importAFile( grid );
+ },
+ order: 151
+ }
+ ]);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name importThisFile
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Imports the provided file into the grid using the file object
+ * provided. Bypasses the grid menu
+ * @param {Grid} grid the grid we're importing into
+ * @param {File} fileObject the file we want to import, as returned from the File
+ * javascript object
+ */
+ importThisFile: function ( grid, fileObject ) {
+ if (!fileObject){
+ gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');
+ return;
+ }
+
+ var reader = new FileReader();
+
+ switch ( fileObject.type ){
+ case 'application/json':
+ reader.onload = service.importJsonClosure( grid );
+ break;
+ default:
+ reader.onload = service.importCsvClosure( grid );
+ break;
+ }
+
+ reader.readAsText( fileObject );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name importJson
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Creates a function that imports a json file into the grid.
+ * The json data is imported into new objects of type `gridOptions.importerNewObject`,
+ * and if the rowEdit feature is enabled the rows are marked as dirty
+ * @param {Grid} grid the grid we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a FileObject
+ */
+ importJsonClosure: function( grid ) {
+ return function( importFile ){
+ var newObjects = [];
+ var newObject;
+
+ var importArray = service.parseJson( grid, importFile );
+ if (importArray === null){
+ return;
+ }
+ importArray.forEach( function( value, index ) {
+ newObject = service.newObject( grid );
+ angular.extend( newObject, value );
+ newObject = grid.options.importerObjectCallback( grid, newObject );
+ newObjects.push( newObject );
+ });
+
+ service.addObjects( grid, newObjects );
+
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name parseJson
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Parses a json file, returns the parsed data.
+ * Displays an error if file doesn't parse
+ * @param {Grid} grid the grid that we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a FileObject
+ * @returns {array} array of objects from the imported json
+ */
+ parseJson: function( grid, importFile ){
+ var loadedObjects;
+ try {
+ loadedObjects = JSON.parse( importFile.target.result );
+ } catch (e) {
+ service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );
+ return;
+ }
+
+ if ( !Array.isArray( loadedObjects ) ){
+ service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );
+ return [];
+ } else {
+ return loadedObjects;
+ }
+ },
+
+
+
+ /**
+ * @ngdoc function
+ * @name importCsvClosure
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Creates a function that imports a csv file into the grid
+ * (allowing it to be used in the reader.onload event)
+ * @param {Grid} grid the grid that we want to import into
+ * @param {FileObject} importFile the file that we want to import, as
+ * a file object
+ */
+ importCsvClosure: function( grid ) {
+ return function( importFile ){
+ var importArray = service.parseCsv( importFile );
+ if ( !importArray || importArray.length < 1 ){
+ service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );
+ return;
+ }
+
+ var newObjects = service.createCsvObjects( grid, importArray );
+ if ( !newObjects || newObjects.length === 0 ){
+ service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );
+ return;
+ }
+
+ service.addObjects( grid, newObjects );
+ };
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name parseCsv
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Parses a csv file into an array of arrays, with the first
+ * array being the headers, and the remaining arrays being the data.
+ * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,
+ * which is noted as being under the MIT license. The code is modified to pass the jscs yoda condition
+ * checker
+ * @param {FileObject} importFile the file that we want to import, as a
+ * file object
+ */
+ parseCsv: function( importFile ) {
+ var csv = importFile.target.result;
+
+ // use the CSV-JS library to parse
+ return CSV.parse(csv);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createCsvObjects
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Converts an array of arrays (representing the csv file)
+ * into a set of objects. Uses the provided `gridOptions.importerNewObject`
+ * to create the objects, and maps the header row into the individual columns
+ * using either `gridOptions.importerProcessHeaders`, or by using a native method
+ * of matching to either the displayName, column name or column field of
+ * the columns in the column defs. The resulting objects will have attributes
+ * that are named based on the column.field or column.name, in that order.
+ * @param {Grid} grid the grid that we want to import into
+ * @param {Array} importArray the data that we want to import, as an array
+ */
+ createCsvObjects: function( grid, importArray ){
+ // pull off header row and turn into headers
+ var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );
+ if ( !headerMapping || headerMapping.length === 0 ){
+ service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );
+ return [];
+ }
+
+ var newObjects = [];
+ var newObject;
+ importArray.forEach( function( row, index ) {
+ newObject = service.newObject( grid );
+ if ( row !== null ){
+ row.forEach( function( field, index ){
+ if ( headerMapping[index] !== null ){
+ newObject[ headerMapping[index] ] = field;
+ }
+ });
+ }
+ newObject = grid.options.importerObjectCallback( grid, newObject );
+ newObjects.push( newObject );
+ });
+
+ return newObjects;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name processHeaders
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Determines the columns that the header row from
+ * a csv (or other) file represents.
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerRow the header row that we wish to match against
+ * the column definitions
+ * @returns {array} an array of the attribute names that should be used
+ * for that column, based on matching the headers or creating the headers
+ *
+ */
+ processHeaders: function( grid, headerRow ) {
+ var headers = [];
+ if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){
+ // we are going to create new columnDefs for all these columns, so just remove
+ // spaces from the names to create fields
+ headerRow.forEach( function( value, index ) {
+ headers.push( value.replace( /[^0-9a-zA-Z\-_]/g, '_' ) );
+ });
+ return headers;
+ } else {
+ var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );
+ headerRow.forEach( function( value, index ) {
+ if ( lookupHash[value] ) {
+ headers.push( lookupHash[value] );
+ } else if ( lookupHash[ value.toLowerCase() ] ) {
+ headers.push( lookupHash[ value.toLowerCase() ] );
+ } else {
+ headers.push( null );
+ }
+ });
+ return headers;
+ }
+ },
+
+
+ /**
+ * @name flattenColumnDefs
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Runs through the column defs and creates a hash of
+ * the displayName, name and field, and of each of those values forced to lower case,
+ * with each pointing to the field or name
+ * (whichever is present). Used to lookup column headers and decide what
+ * attribute name to give to the resulting field.
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} columnDefs the columnDefs that we should flatten
+ * @returns {hash} the flattened version of the column def information, allowing
+ * us to look up a value by `flattenedHash[ headerValue ]`
+ */
+ flattenColumnDefs: function( grid, columnDefs ){
+ var flattenedHash = {};
+ columnDefs.forEach( function( columnDef, index) {
+ if ( columnDef.name ){
+ flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.field ){
+ flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.displayName ){
+ flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;
+ flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+
+ if ( columnDef.displayName && grid.options.importerHeaderFilter ){
+ flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;
+ flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;
+ }
+ });
+
+ return flattenedHash;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addObjects
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Inserts our new objects into the grid data, and
+ * sets the rows to dirty if the rowEdit feature is being used
+ *
+ * Does this by registering a watch on dataChanges, which essentially
+ * is waiting on the result of the grid data watch, and downstream processing.
+ *
+ * When the callback is called, it deregisters itself - we don't want to run
+ * again next time data is added.
+ *
+ * If we never get called, we deregister on destroy.
+ *
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} newObjects the objects we want to insert into the grid data
+ * @returns {object} the new object
+ */
+ addObjects: function( grid, newObjects, $scope ){
+ if ( grid.api.rowEdit ){
+ var dataChangeDereg = grid.registerDataChangeCallback( function() {
+ grid.api.rowEdit.setRowsDirty( newObjects );
+ dataChangeDereg();
+ }, [uiGridConstants.dataChange.ROW] );
+
+ grid.importer.$scope.$on( '$destroy', dataChangeDereg );
+ }
+
+ grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name newObject
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Makes a new object based on `gridOptions.importerNewObject`,
+ * or based on an empty object if not present
+ * @param {Grid} grid the grid we're importing into
+ * @returns {object} the new object
+ */
+ newObject: function( grid ){
+ if ( typeof(grid.options) !== "undefined" && typeof(grid.options.importerNewObject) !== "undefined" ){
+ return new grid.options.importerNewObject();
+ } else {
+ return {};
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name alertError
+ * @methodOf ui.grid.importer.service:uiGridImporterService
+ * @description Provides an internationalised user alert for the failure,
+ * and logs a console message including diagnostic content.
+ * Optionally, if the the `gridOptions.importerErrorCallback` routine
+ * is defined, then calls that instead, allowing user specified error routines
+ * @param {Grid} grid the grid we're importing into
+ * @param {array} headerRow the header row that we wish to match against
+ * the column definitions
+ */
+ alertError: function( grid, alertI18nToken, consoleMessage, context ){
+ if ( grid.options.importerErrorCallback ){
+ grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );
+ } else {
+ $window.alert(i18nService.getSafeText( alertI18nToken ));
+ gridUtil.logError(consoleMessage + context );
+ }
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.importer.directive:uiGridImporter
+ * @element div
+ * @restrict A
+ *
+ * @description Adds importer features to grid
+ *
+ */
+ module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
+ function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);
+ }
+ };
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.importer.directive:uiGridImporterMenuItem
+ * @element div
+ * @restrict A
+ *
+ * @description Handles the processing from the importer menu item - once a file is
+ * selected
+ *
+ */
+ module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
+ function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ templateUrl: 'ui-grid/importerMenuItem',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var handleFileSelect = function( event ){
+ var target = event.srcElement || event.target;
+
+ if (target && target.files && target.files.length === 1) {
+ var fileObject = target.files[0];
+ uiGridImporterService.importThisFile( grid, fileObject );
+ target.form.reset();
+ }
+ };
+
+ var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');
+ var grid = uiGridCtrl.grid;
+
+ if ( fileChooser.length !== 1 ){
+ gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');
+ } else {
+ fileChooser[0].addEventListener('change', handleFileSelect, false); // TODO: why the false on the end? Google
+ }
+ }
+ };
+ }
+ ]);
+})();
+
+(function() {
+ 'use strict';
+ /**
+ * @ngdoc overview
+ * @name ui.grid.infiniteScroll
+ *
+ * @description
+ *
+ * #ui.grid.infiniteScroll
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides infinite scroll functionality to ui-grid
+ *
+ */
+ var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);
+ /**
+ * @ngdoc service
+ * @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ *
+ * @description Service for infinite scroll features
+ */
+ module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $timeout, uiGridConstants, ScrollEvent, $q) {
+
+ var service = {
+
+ /**
+ * @ngdoc function
+ * @name initializeGrid
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This method register events and methods into grid public API
+ */
+
+ initializeGrid: function(grid, $scope) {
+ service.defaultGridOptions(grid.options);
+
+ if (!grid.options.enableInfiniteScroll){
+ return;
+ }
+
+ grid.infiniteScroll = { dataLoading: false };
+ service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );
+ grid.api.core.on.scrollEnd($scope, service.handleScroll);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.infiniteScroll.api:PublicAPI
+ *
+ * @description Public API for infinite scroll feature
+ */
+ var publicApi = {
+ events: {
+ infiniteScroll: {
+
+ /**
+ * @ngdoc event
+ * @name needLoadMoreData
+ * @eventOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description This event fires when scroll reaches bottom percentage of grid
+ * and needs to load data
+ */
+
+ needLoadMoreData: function ($scope, fn) {
+ },
+
+ /**
+ * @ngdoc event
+ * @name needLoadMoreDataTop
+ * @eventOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description This event fires when scroll reaches top percentage of grid
+ * and needs to load data
+ */
+
+ needLoadMoreDataTop: function ($scope, fn) {
+ }
+ }
+ },
+ methods: {
+ infiniteScroll: {
+
+ /**
+ * @ngdoc function
+ * @name dataLoaded
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Call this function when you have loaded the additional data
+ * requested. You should set scrollUp and scrollDown to indicate
+ * whether there are still more pages in each direction.
+ *
+ * If you call dataLoaded without first calling `saveScrollPercentage` then we will
+ * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll
+ * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and
+ * on variable speed internet connections. Using `saveScrollPercentage` as demonstrated in the tutorial
+ * should give a smoother scrolling experience for users.
+ *
+ * See infinite_scroll tutorial for example of usage
+ * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire
+ * any more infinite scroll events upward
+ * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't
+ * fire any more infinite scroll events downward
+ * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted. If you're
+ * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning
+ */
+ dataLoaded: function( scrollUp, scrollDown ) {
+ service.setScrollDirections(grid, scrollUp, scrollDown);
+
+ var promise = service.adjustScroll(grid).then(function() {
+ grid.infiniteScroll.dataLoading = false;
+ });
+
+ return promise;
+ },
+
+ /**
+ * @ngdoc function
+ * @name resetScroll
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Call this function when you have taken some action that makes the current
+ * scroll position invalid. For example, if you're using external sorting and you've resorted
+ * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps
+ * you've reused an existing grid for a new data set
+ *
+ * You must tell us whether there is data upwards or downwards after the reset
+ *
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ * @returns {promise} promise that is resolved when the scroll reset is complete
+ */
+ resetScroll: function( scrollUp, scrollDown ) {
+ service.setScrollDirections( grid, scrollUp, scrollDown);
+
+ return service.adjustInfiniteScrollPosition(grid, 0);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveScrollPercentage
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Saves the scroll percentage and number of visible rows before you adjust the data,
+ * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`
+ */
+ saveScrollPercentage: function() {
+ grid.infiniteScroll.prevScrollTop = grid.renderContainers.body.prevScrollTop;
+ grid.infiniteScroll.previousVisibleRows = grid.getVisibleRowCount();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedTop
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the top
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedTop: function( scrollUp, scrollDown ) {
+ service.dataRemovedTop( grid, scrollUp, scrollDown );
+ },
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedBottom
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the bottom
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedBottom: function( scrollUp, scrollDown ) {
+ service.dataRemovedBottom( grid, scrollUp, scrollDown );
+ },
+
+ /**
+ * @ngdoc function
+ * @name setScrollDirections
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
+ * and also sets the grid.suppressParentScroll
+ * @param {boolean} scrollUp whether there are pages available up - defaults to false
+ * @param {boolean} scrollDown whether there are pages available down - defaults to true
+ */
+ setScrollDirections: function ( scrollUp, scrollDown ) {
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+ }
+
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.infiniteScroll.api:GridOptions
+ *
+ * @description GridOptions for infinite scroll feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableInfiniteScroll
+ * @propertyOf ui.grid.infiniteScroll.api:GridOptions
+ * @description Enable infinite scrolling for this grid
+ * <br/>Defaults to true
+ */
+ gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollRowsFromEnd
+ * @propertyOf ui.grid.class:GridOptions
+ * @description This setting controls how close to the end of the dataset a user gets before
+ * more data is requested by the infinite scroll, whether scrolling up or down. This allows you to
+ * 'prefetch' rows before the user actually runs out of scrolling.
+ *
+ * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting
+ * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll
+ * preserve that scroll position
+ *
+ * <br> Defaults to 20
+ */
+ gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollUp
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether you allow infinite scroll up, implying that the first page of data
+ * you have displayed is in the middle of your data set. If set to true then we trigger the
+ * needMoreDataTop event when the user hits the top of the scrollbar.
+ * <br> Defaults to false
+ */
+ gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;
+
+ /**
+ * @ngdoc property
+ * @name infiniteScrollDown
+ * @propertyOf ui.grid.class:GridOptions
+ * @description Whether you allow infinite scroll down, implying that the first page of data
+ * you have displayed is in the middle of your data set. If set to true then we trigger the
+ * needMoreData event when the user hits the bottom of the scrollbar.
+ * <br> Defaults to true
+ */
+ gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setScrollDirections
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
+ * and also sets the grid.suppressParentScroll
+ * @param {grid} grid the grid we're operating on
+ * @param {boolean} scrollUp whether there are pages available up - defaults to false
+ * @param {boolean} scrollDown whether there are pages available down - defaults to true
+ */
+ setScrollDirections: function ( grid, scrollUp, scrollDown ) {
+ grid.infiniteScroll.scrollUp = ( scrollUp === true );
+ grid.suppressParentScrollUp = ( scrollUp === true );
+
+ grid.infiniteScroll.scrollDown = ( scrollDown !== false);
+ grid.suppressParentScrollDown = ( scrollDown !== false);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name handleScroll
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Called whenever the grid scrolls, determines whether the scroll should
+ * trigger an infinite scroll request for more data
+ * @param {object} args the args from the event
+ */
+ handleScroll: function (args) {
+ // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function
+ if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ){
+ return;
+ }
+
+ if (args.y) {
+ var percentage;
+ var targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;
+ if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {
+ percentage = args.y.percentage;
+ if (percentage <= targetPercentage){
+ service.loadData(args.grid);
+ }
+ } else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {
+ percentage = 1 - args.y.percentage;
+ if (percentage <= targetPercentage){
+ service.loadData(args.grid);
+ }
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name loadData
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
+ * and whether there are more pages upwards or downwards. It also stores the number of rows that we had previously,
+ * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`
+ * @param {Grid} grid the grid we're working on
+ */
+ loadData: function (grid) {
+ // save number of currently visible rows to calculate new scroll position later - we know that we want
+ // to be at approximately the row we're currently at
+ grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;
+ grid.infiniteScroll.direction = grid.scrollDirection;
+ delete grid.infiniteScroll.prevScrollTop;
+
+ if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {
+ grid.infiniteScroll.dataLoading = true;
+ grid.api.infiniteScroll.raise.needLoadMoreDataTop();
+ } else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {
+ grid.infiniteScroll.dataLoading = true;
+ grid.api.infiniteScroll.raise.needLoadMoreData();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustScroll
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description Once we are informed that data has been loaded, adjust the scroll position to account for that
+ * addition and to make things look clean.
+ *
+ * If we're scrolling up we scroll to the first row of the old data set -
+ * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by
+ * the time the data comes back. If we're scrolling down we scoll to the last row of the old data set - so we're
+ * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time
+ * the data comes back.
+ *
+ * Neither of these are good assumptions, but making this a smoother experience really requires
+ * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end). Even then
+ * it'd be better still to actually run into the end. But if the data takes a while to come back, they may have scrolled
+ * somewhere else in the mean-time, in which case they'll get a jump back to the new data. Anyway, this will do for
+ * now, until someone wants to do better.
+ * @param {Grid} grid the grid we're working on
+ * @returns {promise} a promise that is resolved when scrolling has finished
+ */
+ adjustScroll: function(grid){
+ var promise = $q.defer();
+ $timeout(function () {
+ var newPercentage, viewportHeight, rowHeight, newVisibleRows, oldTop, newTop;
+
+ viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight;
+ rowHeight = grid.options.rowHeight;
+
+ if ( grid.infiniteScroll.direction === undefined ){
+ // called from initialize, tweak our scroll up a little
+ service.adjustInfiniteScrollPosition(grid, 0);
+ }
+
+ newVisibleRows = grid.getVisibleRowCount();
+
+ // in case not enough data is loaded to enable scroller - load more data
+ var canvasHeight = rowHeight * newVisibleRows;
+ if (grid.infiniteScroll.scrollDown && (viewportHeight > canvasHeight)) {
+ grid.api.infiniteScroll.raise.needLoadMoreData();
+ }
+
+ if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ){
+ oldTop = grid.infiniteScroll.prevScrollTop || 0;
+ newTop = oldTop + (newVisibleRows - grid.infiniteScroll.previousVisibleRows)*rowHeight;
+ service.adjustInfiniteScrollPosition(grid, newTop);
+ $timeout( function() {
+ promise.resolve();
+ });
+ }
+
+ if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ){
+ newTop = grid.infiniteScroll.prevScrollTop || (grid.infiniteScroll.previousVisibleRows*rowHeight - viewportHeight);
+ service.adjustInfiniteScrollPosition(grid, newTop);
+ $timeout( function() {
+ promise.resolve();
+ });
+ }
+ }, 0);
+
+ return promise.promise;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustInfiniteScrollPosition
+ * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
+ * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
+ * @param {Grid} grid the grid we're working on
+ * @param {number} scrollTop the position through the grid that we want to scroll to
+ * @returns {promise} a promise that is resolved when the scrolling finishes
+ */
+ adjustInfiniteScrollPosition: function (grid, scrollTop) {
+ var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition'),
+ visibleRows = grid.getVisibleRowCount(),
+ viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight,
+ rowHeight = grid.options.rowHeight,
+ scrollHeight = visibleRows*rowHeight-viewportHeight;
+
+ //for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active
+ if (scrollTop === 0 && grid.infiniteScroll.scrollUp) {
+ // using pixels results in a relative scroll, hence we have to use percentage
+ scrollEvent.y = {percentage: 1/scrollHeight};
+ }
+ else {
+ scrollEvent.y = {percentage: scrollTop/scrollHeight};
+ }
+ grid.scrollContainers('', scrollEvent);
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedTop
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the top. You should
+ * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
+ * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
+ * before you start removing data
+ * @param {Grid} grid the grid we're working on
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ * @returns {promise} a promise that is resolved when the scrolling finishes
+ */
+ dataRemovedTop: function( grid, scrollUp, scrollDown ) {
+ var newVisibleRows, oldTop, newTop, rowHeight;
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+
+ newVisibleRows = grid.renderContainers.body.visibleRowCache.length;
+ oldTop = grid.infiniteScroll.prevScrollTop;
+ rowHeight = grid.options.rowHeight;
+
+ // since we removed from the top, our new scroll row will be the old scroll row less the number
+ // of rows removed
+ newTop = oldTop - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows )*rowHeight;
+
+ return service.adjustInfiniteScrollPosition( grid, newTop );
+ },
+
+ /**
+ * @ngdoc function
+ * @name dataRemovedBottom
+ * @methodOf ui.grid.infiniteScroll.api:PublicAPI
+ * @description Adjusts the scroll position after you've removed data at the bottom. You should
+ * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
+ * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
+ * before you start removing data
+ * @param {Grid} grid the grid we're working on
+ * @param {boolean} scrollUp flag that there are pages upwards, fire
+ * infinite scroll events upward
+ * @param {boolean} scrollDown flag that there are pages downwards, so
+ * fire infinite scroll events downward
+ */
+ dataRemovedBottom: function( grid, scrollUp, scrollDown ) {
+ var newTop;
+ service.setScrollDirections( grid, scrollUp, scrollDown );
+
+ newTop = grid.infiniteScroll.prevScrollTop;
+
+ return service.adjustInfiniteScrollPosition( grid, newTop );
+ }
+ };
+ return service;
+ }]);
+ /**
+ * @ngdoc directive
+ * @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll
+ * @element div
+ * @restrict A
+ *
+ * @description Adds infinite scroll features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Alex', car: 'Toyota' },
+ { name: 'Sam', car: 'Lexus' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'car'}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-infinite-scroll="20"></div>
+ </div>
+ </file>
+ </example>
+ */
+
+ module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',
+ function (uiGridInfiniteScrollService) {
+ return {
+ priority: -200,
+ scope: false,
+ require: '^uiGrid',
+ compile: function($scope, $elm, $attr){
+ return {
+ pre: function($scope, $elm, $attr, uiGridCtrl) {
+ uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);
+ },
+ post: function($scope, $elm, $attr) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.moveColumns
+ * @description
+ *
+ * # ui.grid.moveColumns
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides column moving capability to ui.grid. It enables to change the position of columns.
+ * <div doc-module-components="ui.grid.moveColumns"></div>
+ */
+ var module = angular.module('ui.grid.moveColumns', ['ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.moveColumns.service:uiGridMoveColumnService
+ * @description Service for column moving feature.
+ */
+ module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $timeout, $log, ScrollEvent, uiGridConstants, gridUtil) {
+
+ var service = {
+ initializeGrid: function (grid) {
+ var self = this;
+ this.registerPublicApi(grid);
+ this.defaultGridOptions(grid.options);
+ grid.moveColumns = {orderCache: []}; // Used to cache the order before columns are rebuilt
+ grid.registerColumnBuilder(self.movableColumnBuilder);
+ grid.registerDataChangeCallback(self.verifyColumnOrder, [uiGridConstants.dataChange.COLUMN]);
+ },
+ registerPublicApi: function (grid) {
+ var self = this;
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:PublicApi
+ * @description Public Api for column moving feature.
+ */
+ var publicApi = {
+ events: {
+ /**
+ * @ngdoc event
+ * @name columnPositionChanged
+ * @eventOf ui.grid.moveColumns.api:PublicApi
+ * @description raised when column is moved
+ * <pre>
+ * gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})
+ * </pre>
+ * @param {object} colDef the column that was moved
+ * @param {integer} originalPosition of the column
+ * @param {integer} finalPosition of the column
+ */
+ colMovable: {
+ columnPositionChanged: function (colDef, originalPosition, newPosition) {
+ }
+ }
+ },
+ methods: {
+ /**
+ * @ngdoc method
+ * @name moveColumn
+ * @methodOf ui.grid.moveColumns.api:PublicApi
+ * @description Method can be used to change column position.
+ * <pre>
+ * gridApi.colMovable.moveColumn(oldPosition, newPosition)
+ * </pre>
+ * @param {integer} originalPosition of the column
+ * @param {integer} finalPosition of the column
+ */
+ colMovable: {
+ moveColumn: function (originalPosition, finalPosition) {
+ var columns = grid.columns;
+ if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {
+ gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');
+ return;
+ }
+ var nonMovableColumns = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {
+ nonMovableColumns++;
+ }
+ }
+ if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {
+ gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');
+ return;
+ }
+ var findPositionForRenderIndex = function (index) {
+ var position = index;
+ for (var i = 0; i <= position; i++) {
+ if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
+ position++;
+ }
+ }
+ return position;
+ };
+ self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:GridOptions
+ *
+ * @description Options for configuring the move column feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name enableColumnMoving
+ * @propertyOf ui.grid.moveColumns.api:GridOptions
+ * @description If defined, sets the default value for the colMovable flag on each individual colDefs
+ * if their individual enableColumnMoving configuration is not defined. Defaults to true.
+ */
+ gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;
+ },
+ movableColumnBuilder: function (colDef, col, gridOptions) {
+ var promises = [];
+ /**
+ * @ngdoc object
+ * @name ui.grid.moveColumns.api:ColumnDef
+ *
+ * @description Column Definition for move column feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+ /**
+ * @ngdoc object
+ * @name enableColumnMoving
+ * @propertyOf ui.grid.moveColumns.api:ColumnDef
+ * @description Enable column moving for the column.
+ */
+ colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving
+ : colDef.enableColumnMoving;
+ return $q.all(promises);
+ },
+ /**
+ * @ngdoc method
+ * @name updateColumnCache
+ * @methodOf ui.grid.moveColumns
+ * @description Cache the current order of columns, so we can restore them after new columnDefs are defined
+ */
+ updateColumnCache: function(grid){
+ grid.moveColumns.orderCache = grid.getOnlyDataColumns();
+ },
+ /**
+ * @ngdoc method
+ * @name verifyColumnOrder
+ * @methodOf ui.grid.moveColumns
+ * @description dataChangeCallback which uses the cached column order to restore the column order
+ * when it is reset by altering the columnDefs array.
+ */
+ verifyColumnOrder: function(grid){
+ var headerRowOffset = grid.rowHeaderColumns.length;
+ var newIndex;
+
+ angular.forEach(grid.moveColumns.orderCache, function(cacheCol, cacheIndex){
+ newIndex = grid.columns.indexOf(cacheCol);
+ if ( newIndex !== -1 && newIndex - headerRowOffset !== cacheIndex ){
+ var column = grid.columns.splice(newIndex, 1)[0];
+ grid.columns.splice(cacheIndex + headerRowOffset, 0, column);
+ }
+ });
+ },
+ redrawColumnAtPosition: function (grid, originalPosition, newPosition) {
+
+ var columns = grid.columns;
+
+ var originalColumn = columns[originalPosition];
+ if (originalColumn.colDef.enableColumnMoving) {
+ if (originalPosition > newPosition) {
+ for (var i1 = originalPosition; i1 > newPosition; i1--) {
+ columns[i1] = columns[i1 - 1];
+ }
+ }
+ else if (newPosition > originalPosition) {
+ for (var i2 = originalPosition; i2 < newPosition; i2++) {
+ columns[i2] = columns[i2 + 1];
+ }
+ }
+ columns[newPosition] = originalColumn;
+ service.updateColumnCache(grid);
+ grid.queueGridRefresh();
+ $timeout(function () {
+ grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
+ grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);
+ });
+ }
+ }
+ };
+ return service;
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.moveColumns.directive:uiGridMoveColumns
+ * @element div
+ * @restrict A
+ * @description Adds column moving features to the ui-grid directive.
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO', age: 45 },
+ { name: 'Frank', title: 'Lowly Developer', age: 25 },
+ { name: 'Jenny', title: 'Highly Developer', age: 35 }
+ ];
+ $scope.columnDefs = [
+ {name: 'name'},
+ {name: 'title'},
+ {name: 'age'}
+ ];
+ }]);
+ </file>
+ <file name="main.css">
+ .grid {
+ width: 100%;
+ height: 150px;
+ }
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div class="grid" ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-move-columns></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.moveColumns.directive:uiGridHeaderCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.
+ *
+ * On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.
+ * In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).
+ * On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.
+ *
+ * Events that invoke cloning of header cell:
+ * - mousedown
+ *
+ * Events that invoke movement of cloned header cell:
+ * - mousemove
+ *
+ * Events that invoke repositioning of column:
+ * - mouseup
+ */
+ module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',
+ function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {
+ return {
+ priority: -10,
+ require: '^uiGrid',
+ compile: function () {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ if ($scope.col.colDef.enableColumnMoving) {
+
+ /*
+ * Our general approach to column move is that we listen to a touchstart or mousedown
+ * event over the column header. When we hear one, then we wait for a move of the same type
+ * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for
+ * a mousemove (i.e. a drag) before we decide that there's a move underway. If there's never a move,
+ * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.
+ *
+ */
+ var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
+
+ var gridLeft;
+ var previousMouseX;
+ var totalMouseMovement;
+ var rightMoveLimit;
+ var elmCloned = false;
+ var movingElm;
+ var reducedWidth;
+ var moveOccurred = false;
+
+ var downFn = function( event ){
+ //Setting some variables required for calculations.
+ gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
+ if ( $scope.grid.hasLeftContainer() ){
+ gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;
+ }
+
+ previousMouseX = event.pageX;
+ totalMouseMovement = 0;
+ rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();
+
+ if ( event.type === 'mousedown' ){
+ $document.on('mousemove', moveFn);
+ $document.on('mouseup', upFn);
+ } else if ( event.type === 'touchstart' ){
+ $document.on('touchmove', moveFn);
+ $document.on('touchend', upFn);
+ }
+ };
+
+ var moveFn = function( event ) {
+ var changeValue = event.pageX - previousMouseX;
+ if ( changeValue === 0 ){ return; }
+ //Disable text selection in Chrome during column move
+ document.onselectstart = function() { return false; };
+
+ moveOccurred = true;
+
+ if (!elmCloned) {
+ cloneElement();
+ }
+ else if (elmCloned) {
+ moveElement(changeValue);
+ previousMouseX = event.pageX;
+ }
+ };
+
+ var upFn = function( event ){
+ //Re-enable text selection after column move
+ document.onselectstart = null;
+
+ //Remove the cloned element on mouse up.
+ if (movingElm) {
+ movingElm.remove();
+ elmCloned = false;
+ }
+
+ offAllEvents();
+ onDownEvents();
+
+ if (!moveOccurred){
+ return;
+ }
+
+ var columns = $scope.grid.columns;
+ var columnIndex = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if (columns[i].colDef.name !== $scope.col.colDef.name) {
+ columnIndex++;
+ }
+ else {
+ break;
+ }
+ }
+
+ //Case where column should be moved to a position on its left
+ if (totalMouseMovement < 0) {
+ var totalColumnsLeftWidth = 0;
+ for (var il = columnIndex - 1; il >= 0; il--) {
+ if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
+ totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
+ if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, il + 1);
+ break;
+ }
+ }
+ }
+ //Case where column should be moved to beginning of the grid.
+ if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, 0);
+ }
+ }
+
+ //Case where column should be moved to a position on its right
+ else if (totalMouseMovement > 0) {
+ var totalColumnsRightWidth = 0;
+ for (var ir = columnIndex + 1; ir < columns.length; ir++) {
+ if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
+ totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
+ if (totalColumnsRightWidth > totalMouseMovement) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, ir - 1);
+ break;
+ }
+ }
+ }
+ //Case where column should be moved to end of the grid.
+ if (totalColumnsRightWidth < totalMouseMovement) {
+ uiGridMoveColumnService.redrawColumnAtPosition
+ ($scope.grid, columnIndex, columns.length - 1);
+ }
+ }
+ };
+
+ var onDownEvents = function(){
+ $contentsElm.on('touchstart', downFn);
+ $contentsElm.on('mousedown', downFn);
+ };
+
+ var offAllEvents = function() {
+ $contentsElm.off('touchstart', downFn);
+ $contentsElm.off('mousedown', downFn);
+
+ $document.off('mousemove', moveFn);
+ $document.off('touchmove', moveFn);
+
+ $document.off('mouseup', upFn);
+ $document.off('touchend', upFn);
+ };
+
+ onDownEvents();
+
+
+ var cloneElement = function () {
+ elmCloned = true;
+
+ //Cloning header cell and appending to current header cell.
+ movingElm = $elm.clone();
+ $elm.parent().append(movingElm);
+
+ //Left of cloned element should be aligned to original header cell.
+ movingElm.addClass('movingColumn');
+ var movingElementStyles = {};
+ var elmLeft;
+ if (gridUtil.detectBrowser() === 'safari') {
+ //Correction for Safari getBoundingClientRect,
+ //which does not correctly compute when there is an horizontal scroll
+ elmLeft = $elm[0].offsetLeft + $elm[0].offsetWidth - $elm[0].getBoundingClientRect().width;
+ }
+ else {
+ elmLeft = $elm[0].getBoundingClientRect().left;
+ }
+ movingElementStyles.left = (elmLeft - gridLeft) + 'px';
+ var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
+ var elmRight = $elm[0].getBoundingClientRect().right;
+ if (elmRight > gridRight) {
+ reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
+ movingElementStyles.width = reducedWidth + 'px';
+ }
+ movingElm.css(movingElementStyles);
+ };
+
+ var moveElement = function (changeValue) {
+ //Calculate total column width
+ var columns = $scope.grid.columns;
+ var totalColumnWidth = 0;
+ for (var i = 0; i < columns.length; i++) {
+ if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {
+ totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;
+ }
+ }
+
+ //Calculate new position of left of column
+ var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
+ var currentElmRight = movingElm[0].getBoundingClientRect().right;
+ var newElementLeft;
+
+ newElementLeft = currentElmLeft - gridLeft + changeValue;
+ newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;
+
+ //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
+ if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
+ movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});
+ }
+ else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {
+ changeValue *= 8;
+ var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');
+ scrollEvent.x = {pixels: changeValue};
+ scrollEvent.grid.scrollContainers('',scrollEvent);
+ }
+
+ //Calculate total width of columns on the left of the moving column and the mouse movement
+ var totalColumnsLeftWidth = 0;
+ for (var il = 0; il < columns.length; il++) {
+ if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
+ if (columns[il].colDef.name !== $scope.col.colDef.name) {
+ totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if ($scope.newScrollLeft === undefined) {
+ totalMouseMovement += changeValue;
+ }
+ else {
+ totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;
+ }
+
+ //Increase width of moving column, in case the rightmost column was moved and its width was
+ //decreased because of overflow
+ if (reducedWidth < $scope.col.drawnWidth) {
+ reducedWidth += Math.abs(changeValue);
+ movingElm.css({'width': reducedWidth + 'px'});
+ }
+ };
+ }
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.pagination
+ *
+ * @description
+ *
+ * # ui.grid.pagination
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
+ *
+ * This module provides pagination support to ui-grid
+ */
+ var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.pagination.service:uiGridPaginationService
+ *
+ * @description Service for the pagination feature
+ */
+ module.service('uiGridPaginationService', ['gridUtil',
+ function (gridUtil) {
+ var service = {
+ /**
+ * @ngdoc method
+ * @name initializeGrid
+ * @methodOf ui.grid.pagination.service:uiGridPaginationService
+ * @description Attaches the service to a certain grid
+ * @param {Grid} grid The grid we want to work with
+ */
+ initializeGrid: function (grid) {
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pagination.api:PublicAPI
+ *
+ * @description Public API for the pagination feature
+ */
+ var publicApi = {
+ events: {
+ pagination: {
+ /**
+ * @ngdoc event
+ * @name paginationChanged
+ * @eventOf ui.grid.pagination.api:PublicAPI
+ * @description This event fires when the pageSize or currentPage changes
+ * @param {int} currentPage requested page number
+ * @param {int} pageSize requested page size
+ */
+ paginationChanged: function (currentPage, pageSize) { }
+ }
+ },
+ methods: {
+ pagination: {
+ /**
+ * @ngdoc method
+ * @name getPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the number of the current page
+ */
+ getPage: function () {
+ return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;
+ },
+ /**
+ * @ngdoc method
+ * @name getTotalPages
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Returns the total number of pages
+ */
+ getTotalPages: function () {
+ if (!grid.options.enablePagination) {
+ return null;
+ }
+
+ return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);
+ },
+ /**
+ * @ngdoc method
+ * @name nextPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the next page, if possible
+ */
+ nextPage: function () {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+
+ if (grid.options.totalItems > 0) {
+ grid.options.paginationCurrentPage = Math.min(
+ grid.options.paginationCurrentPage + 1,
+ publicApi.methods.pagination.getTotalPages()
+ );
+ } else {
+ grid.options.paginationCurrentPage++;
+ }
+ },
+ /**
+ * @ngdoc method
+ * @name previousPage
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the previous page, if we're not on the first page
+ */
+ previousPage: function () {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+
+ grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);
+ },
+ /**
+ * @ngdoc method
+ * @name seek
+ * @methodOf ui.grid.pagination.api:PublicAPI
+ * @description Moves to the requested page
+ * @param {int} page The number of the page that should be displayed
+ */
+ seek: function (page) {
+ if (!grid.options.enablePagination) {
+ return;
+ }
+ if (!angular.isNumber(page) || page < 1) {
+ throw 'Invalid page number: ' + page;
+ }
+
+ grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ var processPagination = function( renderableRows ){
+ if (grid.options.useExternalPagination || !grid.options.enablePagination) {
+ return renderableRows;
+ }
+ //client side pagination
+ var pageSize = parseInt(grid.options.paginationPageSize, 10);
+ var currentPage = parseInt(grid.options.paginationCurrentPage, 10);
+
+ var visibleRows = renderableRows.filter(function (row) { return row.visible; });
+ grid.options.totalItems = visibleRows.length;
+
+ var firstRow = (currentPage - 1) * pageSize;
+ if (firstRow > visibleRows.length) {
+ currentPage = grid.options.paginationCurrentPage = 1;
+ firstRow = (currentPage - 1) * pageSize;
+ }
+ return visibleRows.slice(firstRow, firstRow + pageSize);
+ };
+
+ grid.registerRowsProcessor(processPagination, 900 );
+
+ },
+ defaultGridOptions: function (gridOptions) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.pagination.api:GridOptions
+ *
+ * @description GridOptions for the pagination feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc property
+ * @name enablePagination
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Enables pagination, defaults to true
+ */
+ gridOptions.enablePagination = gridOptions.enablePagination !== false;
+ /**
+ * @ngdoc property
+ * @name enablePaginationControls
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Enables the paginator at the bottom of the grid. Turn this off, if you want to implement your
+ * own controls outside the grid.
+ */
+ gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;
+ /**
+ * @ngdoc property
+ * @name useExternalPagination
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Disables client side pagination. When true, handle the paginationChanged event and set data
+ * and totalItems, defaults to `false`
+ */
+ gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;
+ /**
+ * @ngdoc property
+ * @name totalItems
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Total number of items, set automatically when client side pagination, needs set by user
+ * for server side pagination
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {
+ gridOptions.totalItems = 0;
+ }
+ /**
+ * @ngdoc property
+ * @name paginationPageSizes
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Array of page sizes, defaults to `[250, 500, 1000]`
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {
+ gridOptions.paginationPageSizes = [250, 500, 1000];
+ }
+ /**
+ * @ngdoc property
+ * @name paginationPageSize
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {
+ if (gridOptions.paginationPageSizes.length > 0) {
+ gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];
+ } else {
+ gridOptions.paginationPageSize = 0;
+ }
+ }
+ /**
+ * @ngdoc property
+ * @name paginationCurrentPage
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description Current page number, defaults to 1
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {
+ gridOptions.paginationCurrentPage = 1;
+ }
+
+ /**
+ * @ngdoc property
+ * @name paginationTemplate
+ * @propertyOf ui.grid.pagination.api:GridOptions
+ * @description A custom template for the pager, defaults to `ui-grid/pagination`
+ */
+ if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {
+ gridOptions.paginationTemplate = 'ui-grid/pagination';
+ }
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.pagination.service:uiGridPaginationService
+ * @name uiGridPaginationService
+ * @description Raises paginationChanged and calls refresh for client side pagination
+ * @param {Grid} grid the grid for which the pagination changed
+ * @param {int} currentPage requested page number
+ * @param {int} pageSize requested page size
+ */
+ onPaginationChanged: function (grid, currentPage, pageSize) {
+ grid.api.pagination.raise.paginationChanged(currentPage, pageSize);
+ if (!grid.options.useExternalPagination) {
+ grid.queueGridRefresh(); //client side pagination
+ }
+ }
+ };
+
+ return service;
+ }
+ ]);
+ /**
+ * @ngdoc directive
+ * @name ui.grid.pagination.directive:uiGridPagination
+ * @element div
+ * @restrict A
+ *
+ * @description Adds pagination features to grid
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Alex', car: 'Toyota' },
+ { name: 'Sam', car: 'Lexus' },
+ { name: 'Joe', car: 'Dodge' },
+ { name: 'Bob', car: 'Buick' },
+ { name: 'Cindy', car: 'Ford' },
+ { name: 'Brian', car: 'Audi' },
+ { name: 'Malcom', car: 'Mercedes Benz' },
+ { name: 'Dave', car: 'Ford' },
+ { name: 'Stacey', car: 'Audi' },
+ { name: 'Amy', car: 'Acura' },
+ { name: 'Scott', car: 'Toyota' },
+ { name: 'Ryan', car: 'BMW' },
+ ];
+
+ $scope.gridOptions = {
+ data: 'data',
+ paginationPageSizes: [5, 10, 25],
+ paginationPageSize: 5,
+ columnDefs: [
+ {name: 'name'},
+ {name: 'car'}
+ ]
+ }
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-pagination></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',
+ function (gridUtil, uiGridPaginationService) {
+ return {
+ priority: -200,
+ scope: false,
+ require: 'uiGrid',
+ link: {
+ pre: function ($scope, $elm, $attr, uiGridCtrl) {
+ uiGridPaginationService.initializeGrid(uiGridCtrl.grid);
+
+ gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
+ .then(function (contents) {
+ var template = angular.element(contents);
+ $elm.append(template);
+ uiGridCtrl.innerCompile(template);
+ });
+ }
+ }
+ };
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.pagination.directive:uiGridPager
+ * @element div
+ *
+ * @description Panel for handling pagination
+ */
+ module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',
+ function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {
+ return {
+ priority: -200,
+ scope: true,
+ require: '^uiGrid',
+ link: function ($scope, $elm, $attr, uiGridCtrl) {
+ var defaultFocusElementSelector = '.ui-grid-pager-control-input';
+ $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels
+
+ $scope.paginationApi = uiGridCtrl.grid.api.pagination;
+ $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');
+ $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');
+ $scope.paginationOf = i18nService.getSafeText('pagination.of');
+ $scope.paginationThrough = i18nService.getSafeText('pagination.through');
+
+ var options = uiGridCtrl.grid.options;
+
+ uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
+ adjustment.height = adjustment.height - gridUtil.elementHeight($elm);
+ return adjustment;
+ });
+
+ var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
+ if (!grid.options.useExternalPagination) {
+ grid.options.totalItems = grid.rows.length;
+ }
+ }, [uiGridConstants.dataChange.ROW]);
+
+ $scope.$on('$destroy', dataChangeDereg);
+
+ var setShowing = function () {
+ $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;
+ $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);
+ };
+
+ var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);
+
+ var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {
+ if (newValues === oldValues || oldValues === undefined) {
+ return;
+ }
+
+ if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {
+ options.paginationCurrentPage = 1;
+ return;
+ }
+
+ if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {
+ options.paginationCurrentPage = $scope.paginationApi.getTotalPages();
+ return;
+ }
+
+ setShowing();
+ uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);
+ }
+ );
+
+ $scope.$on('$destroy', function() {
+ deregT();
+ deregP();
+ });
+
+ $scope.cantPageForward = function () {
+ if (options.totalItems > 0) {
+ return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();
+ } else {
+ return options.data.length < 1;
+ }
+ };
+
+ $scope.cantPageToLast = function () {
+ if (options.totalItems > 0) {
+ return $scope.cantPageForward();
+ } else {
+ return true;
+ }
+ };
+
+ $scope.cantPageBackward = function () {
+ return options.paginationCurrentPage <= 1;
+ };
+
+ var focusToInputIf = function(condition){
+ if (condition){
+ gridUtil.focus.bySelector($elm, defaultFocusElementSelector);
+ }
+ };
+
+ //Takes care of setting focus to the middle element when focus is lost
+ $scope.pageFirstPageClick = function () {
+ $scope.paginationApi.seek(1);
+ focusToInputIf($scope.cantPageBackward());
+ };
+
+ $scope.pagePreviousPageClick = function () {
+ $scope.paginationApi.previousPage();
+ focusToInputIf($scope.cantPageBackward());
+ };
+
+ $scope.pageNextPageClick = function () {
+ $scope.paginationApi.nextPage();
+ focusToInputIf($scope.cantPageForward());
+ };
+
+ $scope.pageLastPageClick = function () {
+ $scope.paginationApi.seek($scope.paginationApi.getTotalPages());
+ focusToInputIf($scope.cantPageToLast());
+ };
+
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.pinning
+ * @description
+ *
+ * # ui.grid.pinning
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides column pinning to the end user via menu options in the column header
+ *
+ * <div doc-module-components="ui.grid.pinning"></div>
+ */
+
+ var module = angular.module('ui.grid.pinning', ['ui.grid']);
+
+ module.constant('uiGridPinningConstants', {
+ container: {
+ LEFT: 'left',
+ RIGHT: 'right',
+ NONE: ''
+ }
+ });
+
+ module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {
+ var service = {
+
+ initializeGrid: function (grid) {
+ service.defaultGridOptions(grid.options);
+
+ // Register a column builder to add new menu items for pinning left and right
+ grid.registerColumnBuilder(service.pinningColumnBuilder);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:PublicApi
+ *
+ * @description Public Api for pinning feature
+ */
+ var publicApi = {
+ events: {
+ pinning: {
+ /**
+ * @ngdoc event
+ * @name columnPin
+ * @eventOf ui.grid.pinning.api:PublicApi
+ * @description raised when column pin state has changed
+ * <pre>
+ * gridApi.pinning.on.columnPinned(scope, function(colDef){})
+ * </pre>
+ * @param {object} colDef the column that was changed
+ * @param {string} container the render container the column is in ('left', 'right', '')
+ */
+ columnPinned: function(colDef, container) {
+ }
+ }
+ },
+ methods: {
+ pinning: {
+ /**
+ * @ngdoc function
+ * @name pinColumn
+ * @methodOf ui.grid.pinning.api:PublicApi
+ * @description pin column left, right, or none
+ * <pre>
+ * gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)
+ * </pre>
+ * @param {gridColumn} col the column being pinned
+ * @param {string} container one of the recognised types
+ * from uiGridPinningConstants
+ */
+ pinColumn: function(col, container) {
+ service.pinColumn(grid, col, container);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:GridOptions
+ *
+ * @description GridOptions for pinning feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enablePinning
+ * @propertyOf ui.grid.pinning.api:GridOptions
+ * @description Enable pinning for the entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enablePinning = gridOptions.enablePinning !== false;
+
+ },
+
+ pinningColumnBuilder: function (colDef, col, gridOptions) {
+ //default to true unless gridOptions or colDef is explicitly false
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.pinning.api:ColumnDef
+ *
+ * @description ColumnDef for pinning feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enablePinning
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Enable pinning for the individual column.
+ * <br/>Defaults to true
+ */
+ colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;
+
+
+ /**
+ * @ngdoc object
+ * @name pinnedLeft
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Column is pinned left when grid is rendered
+ * <br/>Defaults to false
+ */
+
+ /**
+ * @ngdoc object
+ * @name pinnedRight
+ * @propertyOf ui.grid.pinning.api:ColumnDef
+ * @description Column is pinned right when grid is rendered
+ * <br/>Defaults to false
+ */
+ if (colDef.pinnedLeft) {
+ col.renderContainer = 'left';
+ col.grid.createLeftContainer();
+ }
+ else if (colDef.pinnedRight) {
+ col.renderContainer = 'right';
+ col.grid.createRightContainer();
+ }
+
+ if (!colDef.enablePinning) {
+ return;
+ }
+
+ var pinColumnLeftAction = {
+ name: 'ui.grid.pinning.pinLeft',
+ title: i18nService.get().pinning.pinLeft,
+ icon: 'ui-grid-icon-left-open',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);
+ }
+ };
+
+ var pinColumnRightAction = {
+ name: 'ui.grid.pinning.pinRight',
+ title: i18nService.get().pinning.pinRight,
+ icon: 'ui-grid-icon-right-open',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);
+ }
+ };
+
+ var removePinAction = {
+ name: 'ui.grid.pinning.unpin',
+ title: i18nService.get().pinning.unpin,
+ icon: 'ui-grid-icon-cancel',
+ shown: function () {
+ return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';
+ },
+ action: function () {
+ service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.UNPIN);
+ }
+ };
+
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {
+ col.menuItems.push(pinColumnLeftAction);
+ }
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {
+ col.menuItems.push(pinColumnRightAction);
+ }
+ if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {
+ col.menuItems.push(removePinAction);
+ }
+ },
+
+ pinColumn: function(grid, col, container) {
+ if (container === uiGridPinningConstants.container.NONE) {
+ col.renderContainer = null;
+ }
+ else {
+ col.renderContainer = container;
+ if (container === uiGridPinningConstants.container.LEFT) {
+ grid.createLeftContainer();
+ }
+ else if (container === uiGridPinningConstants.container.RIGHT) {
+ grid.createRightContainer();
+ }
+ }
+
+ grid.refresh()
+ .then(function() {
+ grid.api.pinning.raise.columnPinned( col.colDef, container );
+ });
+ }
+ };
+
+ return service;
+ }]);
+
+ module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',
+ function (gridUtil, uiGridPinningService) {
+ return {
+ require: 'uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridPinningService.initializeGrid(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+
+})();
+
+(function(){
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.resizeColumns
+ * @description
+ *
+ * # ui.grid.resizeColumns
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module allows columns to be resized.
+ */
+ var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);
+
+ module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',
+ function (gridUtil, $q, $timeout) {
+
+ var service = {
+ defaultGridOptions: function(gridOptions){
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:GridOptions
+ *
+ * @description GridOptions for resizeColumns feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableColumnResizing
+ * @propertyOf ui.grid.resizeColumns.api:GridOptions
+ * @description Enable column resizing on the entire grid
+ * <br/>Defaults to true
+ */
+ gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;
+
+ //legacy support
+ //use old name if it is explicitly false
+ if (gridOptions.enableColumnResize === false){
+ gridOptions.enableColumnResizing = false;
+ }
+ },
+
+ colResizerColumnBuilder: function (colDef, col, gridOptions) {
+
+ var promises = [];
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:ColumnDef
+ *
+ * @description ColumnDef for resizeColumns feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableColumnResizing
+ * @propertyOf ui.grid.resizeColumns.api:ColumnDef
+ * @description Enable column resizing on an individual column
+ * <br/>Defaults to GridOptions.enableColumnResizing
+ */
+ //default to true unless gridOptions or colDef is explicitly false
+ colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;
+
+
+ //legacy support of old option name
+ if (colDef.enableColumnResize === false){
+ colDef.enableColumnResizing = false;
+ }
+
+ return $q.all(promises);
+ },
+
+ registerPublicApi: function (grid) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.resizeColumns.api:PublicApi
+ * @description Public Api for column resize feature.
+ */
+ var publicApi = {
+ events: {
+ /**
+ * @ngdoc event
+ * @name columnSizeChanged
+ * @eventOf ui.grid.resizeColumns.api:PublicApi
+ * @description raised when column is resized
+ * <pre>
+ * gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})
+ * </pre>
+ * @param {object} colDef the column that was resized
+ * @param {integer} delta of the column size change
+ */
+ colResizable: {
+ columnSizeChanged: function (colDef, deltaChange) {
+ }
+ }
+ }
+ };
+ grid.api.registerEventsFromObject(publicApi.events);
+ },
+
+ fireColumnSizeChanged: function (grid, colDef, deltaChange) {
+ $timeout(function () {
+ if ( grid.api.colResizable ){
+ grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);
+ } else {
+ gridUtil.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.");
+ }
+ });
+ },
+
+ // get either this column, or the column next to this column, to resize,
+ // returns the column we're going to resize
+ findTargetCol: function(col, position, rtlMultiplier){
+ var renderContainer = col.getRenderContainer();
+
+ if (position === 'left') {
+ // Get the column to the left of this one
+ var colIndex = renderContainer.visibleColumnCache.indexOf(col);
+ return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];
+ } else {
+ return col;
+ }
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.resizeColumns.directive:uiGridResizeColumns
+ * @element div
+ * @restrict A
+ * @description
+ * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the
+ * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.gridOpts = {
+ data: [
+ { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
+ { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
+ { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
+ { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
+ ]
+ };
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div class="testGrid" ui-grid="gridOpts" ui-grid-resize-columns ></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+
+ </doc:scenario>
+ </doc:example>
+ */
+ module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);
+ uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);
+ uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+ // Extend the uiGridHeaderCell directive
+ module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {
+ return {
+ // Run after the original uiGridHeaderCell
+ priority: -10,
+ require: '^uiGrid',
+ // scope: false,
+ compile: function() {
+ return {
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var grid = uiGridCtrl.grid;
+
+ if (grid.options.enableColumnResizing) {
+ var columnResizerElm = $templateCache.get('ui-grid/columnResizer');
+
+ var rtlMultiplier = 1;
+ //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
+ if (grid.isRTL()) {
+ $scope.position = 'left';
+ rtlMultiplier = -1;
+ }
+
+ var displayResizers = function(){
+
+ // remove any existing resizers.
+ var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');
+ for ( var i = 0; i < resizers.length; i++ ){
+ angular.element(resizers[i]).remove();
+ }
+
+ // get the target column for the left resizer
+ var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);
+ var renderContainer = $scope.col.getRenderContainer();
+
+ // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled
+ if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {
+ var resizerLeft = angular.element(columnResizerElm).clone();
+ resizerLeft.attr('position', 'left');
+
+ $elm.prepend(resizerLeft);
+ $compile(resizerLeft)($scope);
+ }
+
+ // Don't append the right resizer if this column has resizing disabled
+ if ($scope.col.colDef.enableColumnResizing !== false) {
+ var resizerRight = angular.element(columnResizerElm).clone();
+ resizerRight.attr('position', 'right');
+
+ $elm.append(resizerRight);
+ $compile(resizerRight)($scope);
+ }
+ };
+
+ displayResizers();
+
+ var waitDisplay = function(){
+ $timeout(displayResizers);
+ };
+
+ var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );
+
+ $scope.$on( '$destroy', dataChangeDereg );
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.resizeColumns.directive:uiGridColumnResizer
+ * @element div
+ * @restrict A
+ *
+ * @description
+ * Draggable handle that controls column resizing.
+ *
+ * @example
+ <doc:example module="app">
+ <doc:source>
+ <script>
+ var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.gridOpts = {
+ enableColumnResizing: true,
+ data: [
+ { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
+ { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
+ { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
+ { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
+ ]
+ };
+ }]);
+ </script>
+
+ <div ng-controller="MainCtrl">
+ <div class="testGrid" ui-grid="gridOpts"></div>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ // TODO: e2e specs?
+
+ // TODO: post-resize a horizontal scroll event should be fired
+ </doc:scenario>
+ </doc:example>
+ */
+ module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {
+ var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');
+
+ var resizer = {
+ priority: 0,
+ scope: {
+ col: '=',
+ position: '@',
+ renderIndex: '='
+ },
+ require: '?^uiGrid',
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ var startX = 0,
+ x = 0,
+ gridLeft = 0,
+ rtlMultiplier = 1;
+
+ //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
+ if (uiGridCtrl.grid.isRTL()) {
+ $scope.position = 'left';
+ rtlMultiplier = -1;
+ }
+
+ if ($scope.position === 'left') {
+ $elm.addClass('left');
+ }
+ else if ($scope.position === 'right') {
+ $elm.addClass('right');
+ }
+
+ // Refresh the grid canvas
+ // takes an argument representing the diff along the X-axis that the resize had
+ function refreshCanvas(xDiff) {
+ // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
+ uiGridCtrl.grid.refreshCanvas(true).then( function() {
+ uiGridCtrl.grid.queueGridRefresh();
+ });
+ }
+
+ // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
+ // Returns the new recommended with, after constraints applied
+ function constrainWidth(col, width){
+ var newWidth = width;
+
+ // If the new width would be less than the column's allowably minimum width, don't allow it
+ if (col.minWidth && newWidth < col.minWidth) {
+ newWidth = col.minWidth;
+ }
+ else if (col.maxWidth && newWidth > col.maxWidth) {
+ newWidth = col.maxWidth;
+ }
+
+ return newWidth;
+ }
+
+
+ /*
+ * Our approach to event handling aims to deal with both touch devices and mouse devices
+ * We register down handlers on both touch and mouse. When a touchstart or mousedown event
+ * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
+ *
+ * This way we can listen for both without worrying about the fact many touch devices also emulate
+ * mouse events - basically whichever one we hear first is what we'll go with.
+ */
+ function moveFunction(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.preventDefault();
+
+ x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
+
+ if (x < 0) { x = 0; }
+ else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
+ uiGridCtrl.grid.element.addClass('column-resizing');
+ }
+
+ // Get the diff along the X axis
+ var xDiff = x - startX;
+
+ // Get the width that this mouse would give the column
+ var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
+
+ // check we're not outside the allowable bounds for this column
+ x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;
+
+ resizeOverlay.css({ left: x + 'px' });
+
+ uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
+ }
+
+
+ function upFunction(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.preventDefault();
+
+ uiGridCtrl.grid.element.removeClass('column-resizing');
+
+ resizeOverlay.remove();
+
+ // Resize the column
+ x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
+ var xDiff = x - startX;
+
+ if (xDiff === 0) {
+ // no movement, so just reset event handlers, including turning back on both
+ // down events - we turned one off when this event started
+ offAllEvents();
+ onDownEvents();
+ return;
+ }
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ // Get the new width
+ var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
+
+ // check we're not outside the allowable bounds for this column
+ col.width = constrainWidth(col, newWidth);
+ col.hasCustomWidth = true;
+
+ refreshCanvas(xDiff);
+
+ uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
+
+ // stop listening of up and move events - wait for next down
+ // reset the down events - we will have turned one off when this event started
+ offAllEvents();
+ onDownEvents();
+ }
+
+
+ var downFunction = function(event, args) {
+ if (event.originalEvent) { event = event.originalEvent; }
+ event.stopPropagation();
+
+ // Get the left offset of the grid
+ // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
+ gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;
+
+ // Get the starting X position, which is the X coordinate of the click minus the grid's offset
+ startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
+
+ // Append the resizer overlay
+ uiGridCtrl.grid.element.append(resizeOverlay);
+
+ // Place the resizer overlay at the start position
+ resizeOverlay.css({ left: startX });
+
+ // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
+ // we were touchdown then we listen for touchmove and touchup. Also remove the handler for the equivalent
+ // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
+ // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
+ if ( event.type === 'touchstart' ){
+ $document.on('touchend', upFunction);
+ $document.on('touchmove', moveFunction);
+ $elm.off('mousedown', downFunction);
+ } else {
+ $document.on('mouseup', upFunction);
+ $document.on('mousemove', moveFunction);
+ $elm.off('touchstart', downFunction);
+ }
+ };
+
+ var onDownEvents = function() {
+ $elm.on('mousedown', downFunction);
+ $elm.on('touchstart', downFunction);
+ };
+
+ var offAllEvents = function() {
+ $document.off('mouseup', upFunction);
+ $document.off('touchend', upFunction);
+ $document.off('mousemove', moveFunction);
+ $document.off('touchmove', moveFunction);
+ $elm.off('mousedown', downFunction);
+ $elm.off('touchstart', downFunction);
+ };
+
+ onDownEvents();
+
+
+ // On doubleclick, resize to fit all rendered cells
+ var dblClickFn = function(event, args){
+ event.stopPropagation();
+
+ var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
+
+ // Don't resize if it's disabled on this column
+ if (col.colDef.enableColumnResizing === false) {
+ return;
+ }
+
+ // Go through the rendered rows and find out the max size for the data in this column
+ var maxWidth = 0;
+ var xDiff = 0;
+
+ // Get the parent render container element
+ var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');
+
+ // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present
+ var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');
+ Array.prototype.forEach.call(cells, function (cell) {
+ // Get the cell width
+ // gridUtil.logDebug('width', gridUtil.elementWidth(cell));
+
+ // Account for the menu button if it exists
+ var menuButton;
+ if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {
+ menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');
+ }
+
+ gridUtil.fakeElement(cell, {}, function(newElm) {
+ // Make the element float since it's a div and can expand to fill its container
+ var e = angular.element(newElm);
+ e.attr('style', 'float: left');
+
+ var width = gridUtil.elementWidth(e);
+
+ if (menuButton) {
+ var menuButtonWidth = gridUtil.elementWidth(menuButton);
+ width = width + menuButtonWidth;
+ }
+
+ if (width > maxWidth) {
+ maxWidth = width;
+ xDiff = maxWidth - width;
+ }
+ });
+ });
+
+ // check we're not outside the allowable bounds for this column
+ col.width = constrainWidth(col, maxWidth);
+ col.hasCustomWidth = true;
+
+ refreshCanvas(xDiff);
+
+ uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff); };
+ $elm.on('dblclick', dblClickFn);
+
+ $elm.on('$destroy', function() {
+ $elm.off('dblclick', dblClickFn);
+ offAllEvents();
+ });
+ }
+ };
+
+ return resizer;
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.rowEdit
+ * @description
+ *
+ * # ui.grid.rowEdit
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module extends the edit feature to provide tracking and saving of rows
+ * of data. The tutorial provides more information on how this feature is best
+ * used {@link tutorial/205_row_editable here}.
+ * <br/>
+ * This feature depends on usage of the ui-grid-edit feature, and also benefits
+ * from use of ui-grid-cellNav to provide the full spreadsheet-like editing
+ * experience
+ *
+ */
+
+ var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.constant:uiGridRowEditConstants
+ *
+ * @description constants available in row edit module
+ */
+ module.constant('uiGridRowEditConstants', {
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.rowEdit.service:uiGridRowEditService
+ *
+ * @description Services for row editing features
+ */
+ module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',
+ function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (scope, grid) {
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.api:PublicApi
+ *
+ * @description Public Api for rowEdit feature
+ */
+
+ grid.rowEdit = {};
+
+ var publicApi = {
+ events: {
+ rowEdit: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.rowEdit.api:PublicApi
+ * @name saveRow
+ * @description raised when a row is ready for saving. Once your
+ * row has saved you may need to use angular.extend to update the
+ * data entity with any changed data from your save (for example,
+ * lock version information if you're using optimistic locking,
+ * or last update time/user information).
+ *
+ * Your method should call setSavePromise somewhere in the body before
+ * returning control. The feature will then wait, with the gridRow greyed out
+ * whilst this promise is being resolved.
+ *
+ * <pre>
+ * gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})
+ * </pre>
+ * and somewhere within the event handler:
+ * <pre>
+ * gridApi.rowEdit.setSavePromise( rowEntity, savePromise)
+ * </pre>
+ * @param {object} rowEntity the options.data element that was edited
+ * @returns {promise} Your saveRow method should return a promise, the
+ * promise should either be resolved (implying successful save), or
+ * rejected (implying an error).
+ */
+ saveRow: function (rowEntity) {
+ }
+ }
+ },
+ methods: {
+ rowEdit: {
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setSavePromise
+ * @description Sets the promise associated with the row save, mandatory that
+ * the saveRow event handler calls this method somewhere before returning.
+ * <pre>
+ * gridApi.rowEdit.setSavePromise(rowEntity, savePromise)
+ * </pre>
+ * @param {object} rowEntity a data row from the grid for which a save has
+ * been initiated
+ * @param {promise} savePromise the promise that will be resolved when the
+ * save is successful, or rejected if the save fails
+ *
+ */
+ setSavePromise: function ( rowEntity, savePromise) {
+ service.setSavePromise(grid, rowEntity, savePromise);
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name getDirtyRows
+ * @description Returns all currently dirty rows
+ * <pre>
+ * gridApi.rowEdit.getDirtyRows(grid)
+ * </pre>
+ * @returns {array} An array of gridRows that are currently dirty
+ *
+ */
+ getDirtyRows: function () {
+ return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name getErrorRows
+ * @description Returns all currently errored rows
+ * <pre>
+ * gridApi.rowEdit.getErrorRows(grid)
+ * </pre>
+ * @returns {array} An array of gridRows that are currently in error
+ *
+ */
+ getErrorRows: function () {
+ return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];
+ },
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name flushDirtyRows
+ * @description Triggers a save event for all currently dirty rows, could
+ * be used where user presses a save button or navigates away from the page
+ * <pre>
+ * gridApi.rowEdit.flushDirtyRows(grid)
+ * </pre>
+ * @returns {promise} a promise that represents the aggregate of all
+ * of the individual save promises - i.e. it will be resolved when all
+ * the individual save promises have been resolved.
+ *
+ */
+ flushDirtyRows: function () {
+ return service.flushDirtyRows(grid);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setRowsDirty
+ * @description Sets each of the rows passed in dataRows
+ * to be dirty. note that if you have only just inserted the
+ * rows into your data you will need to wait for a $digest cycle
+ * before the gridRows are present - so often you would wrap this
+ * call in a $interval or $timeout
+ * <pre>
+ * $interval( function() {
+ * gridApi.rowEdit.setRowsDirty(myDataRows);
+ * }, 0, 1);
+ * </pre>
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set dirty.
+ *
+ */
+ setRowsDirty: function ( dataRows) {
+ service.setRowsDirty(grid, dataRows);
+ },
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.api:PublicApi
+ * @name setRowsClean
+ * @description Sets each of the rows passed in dataRows
+ * to be clean, removing them from the dirty cache and the error cache,
+ * and clearing the error flag and the dirty flag
+ * <pre>
+ * var gridRows = $scope.gridApi.rowEdit.getDirtyRows();
+ * var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });
+ * $scope.gridApi.rowEdit.setRowsClean( dataRows );
+ * </pre>
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set clean.
+ *
+ */
+ setRowsClean: function ( dataRows) {
+ service.setRowsClean(grid, dataRows);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ grid.api.core.on.renderingComplete( scope, function ( gridApi ) {
+ grid.api.edit.on.afterCellEdit( scope, service.endEditCell );
+ grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );
+ grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );
+
+ if ( grid.api.cellNav ) {
+ grid.api.cellNav.on.navigate( scope, service.navigate );
+ }
+ });
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.rowEdit.api:GridOptions
+ *
+ * @description Options for configuring the rowEdit feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name saveRow
+ * @description Returns a function that saves the specified row from the grid,
+ * and returns a promise
+ * @param {object} grid the grid for which dirty rows should be flushed
+ * @param {GridRow} gridRow the row that should be saved
+ * @returns {function} the saveRow function returns a function. That function
+ * in turn, when called, returns a promise relating to the save callback
+ */
+ saveRow: function ( grid, gridRow ) {
+ var self = this;
+
+ return function() {
+ gridRow.isSaving = true;
+
+ if ( gridRow.rowEditSavePromise ){
+ // don't save the row again if it's already saving - that causes stale object exceptions
+ return gridRow.rowEditSavePromise;
+ }
+
+ var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );
+
+ if ( gridRow.rowEditSavePromise ){
+ gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));
+ } else {
+ gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );
+ }
+ return promise;
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setSavePromise
+ * @description Sets the promise associated with the row save, mandatory that
+ * the saveRow event handler calls this method somewhere before returning.
+ * <pre>
+ * gridApi.rowEdit.setSavePromise(grid, rowEntity)
+ * </pre>
+ * @param {object} grid the grid for which dirty rows should be returned
+ * @param {object} rowEntity a data row from the grid for which a save has
+ * been initiated
+ * @param {promise} savePromise the promise that will be resolved when the
+ * save is successful, or rejected if the save fails
+ *
+ */
+ setSavePromise: function (grid, rowEntity, savePromise) {
+ var gridRow = grid.getRow( rowEntity );
+ gridRow.rowEditSavePromise = savePromise;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name processSuccessPromise
+ * @description Returns a function that processes the successful
+ * resolution of a save promise
+ * @param {object} grid the grid for which the promise should be processed
+ * @param {GridRow} gridRow the row that has been saved
+ * @returns {function} the success handling function
+ */
+ processSuccessPromise: function ( grid, gridRow ) {
+ var self = this;
+
+ return function() {
+ delete gridRow.isSaving;
+ delete gridRow.isDirty;
+ delete gridRow.isError;
+ delete gridRow.rowEditSaveTimer;
+ delete gridRow.rowEditSavePromise;
+ self.removeRow( grid.rowEdit.errorRows, gridRow );
+ self.removeRow( grid.rowEdit.dirtyRows, gridRow );
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name processErrorPromise
+ * @description Returns a function that processes the failed
+ * resolution of a save promise
+ * @param {object} grid the grid for which the promise should be processed
+ * @param {GridRow} gridRow the row that is now in error
+ * @returns {function} the error handling function
+ */
+ processErrorPromise: function ( grid, gridRow ) {
+ return function() {
+ delete gridRow.isSaving;
+ delete gridRow.rowEditSaveTimer;
+ delete gridRow.rowEditSavePromise;
+
+ gridRow.isError = true;
+
+ if (!grid.rowEdit.errorRows){
+ grid.rowEdit.errorRows = [];
+ }
+ if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){
+ grid.rowEdit.errorRows.push( gridRow );
+ }
+ };
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name removeRow
+ * @description Removes a row from a cache of rows - either
+ * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows. If the row
+ * is not present silently does nothing.
+ * @param {array} rowArray the array from which to remove the row
+ * @param {GridRow} gridRow the row that should be removed
+ */
+ removeRow: function( rowArray, removeGridRow ){
+ if (typeof(rowArray) === 'undefined' || rowArray === null){
+ return;
+ }
+
+ rowArray.forEach( function( gridRow, index ){
+ if ( gridRow.uid === removeGridRow.uid ){
+ rowArray.splice( index, 1);
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name isRowPresent
+ * @description Checks whether a row is already present
+ * in the given array
+ * @param {array} rowArray the array in which to look for the row
+ * @param {GridRow} gridRow the row that should be looked for
+ */
+ isRowPresent: function( rowArray, removeGridRow ){
+ var present = false;
+ rowArray.forEach( function( gridRow, index ){
+ if ( gridRow.uid === removeGridRow.uid ){
+ present = true;
+ }
+ });
+ return present;
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name flushDirtyRows
+ * @description Triggers a save event for all currently dirty rows, could
+ * be used where user presses a save button or navigates away from the page
+ * <pre>
+ * gridApi.rowEdit.flushDirtyRows(grid)
+ * </pre>
+ * @param {object} grid the grid for which dirty rows should be flushed
+ * @returns {promise} a promise that represents the aggregate of all
+ * of the individual save promises - i.e. it will be resolved when all
+ * the individual save promises have been resolved.
+ *
+ */
+ flushDirtyRows: function(grid){
+ var promises = [];
+ grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ){
+ service.saveRow( grid, gridRow )();
+ promises.push( gridRow.rowEditSavePromise );
+ });
+
+ return $q.all( promises );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name endEditCell
+ * @description Receives an afterCellEdit event from the edit function,
+ * and sets flags as appropriate. Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ * @param {object} rowEntity the data entity for which the cell
+ * was edited
+ */
+ endEditCell: function( rowEntity, colDef, newValue, previousValue ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }
+
+ if ( newValue !== previousValue || gridRow.isDirty ){
+ if ( !grid.rowEdit.dirtyRows ){
+ grid.rowEdit.dirtyRows = [];
+ }
+
+ if ( !gridRow.isDirty ){
+ gridRow.isDirty = true;
+ grid.rowEdit.dirtyRows.push( gridRow );
+ }
+
+ delete gridRow.isError;
+
+ service.considerSetTimer( grid, gridRow );
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name beginEditCell
+ * @description Receives a beginCellEdit event from the edit function,
+ * and cancels any rowEditSaveTimers if present, as the user is still editing
+ * this row. Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ * @param {object} rowEntity the data entity for which the cell
+ * editing has commenced
+ */
+ beginEditCell: function( rowEntity, colDef ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }
+
+ service.cancelTimer( grid, gridRow );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name cancelEditCell
+ * @description Receives a cancelCellEdit event from the edit function,
+ * and if the row was already dirty, restarts the save timer. If the row
+ * was not already dirty, then it's not dirty now either and does nothing.
+ *
+ * Only the rowEntity parameter
+ * is processed, although other params are available. Grid
+ * is automatically provided by the gridApi.
+ *
+ * @param {object} rowEntity the data entity for which the cell
+ * editing was cancelled
+ */
+ cancelEditCell: function( rowEntity, colDef ){
+ var grid = this.grid;
+ var gridRow = grid.getRow( rowEntity );
+ if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }
+
+ service.considerSetTimer( grid, gridRow );
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name navigate
+ * @description cellNav tells us that the selected cell has changed. If
+ * the new row had a timer running, then stop it similar to in a beginCellEdit
+ * call. If the old row is dirty and not the same as the new row, then
+ * start a timer on it.
+ * @param {object} newRowCol the row and column that were selected
+ * @param {object} oldRowCol the row and column that was left
+ *
+ */
+ navigate: function( newRowCol, oldRowCol ){
+ var grid = this.grid;
+ if ( newRowCol.row.rowEditSaveTimer ){
+ service.cancelTimer( grid, newRowCol.row );
+ }
+
+ if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){
+ service.considerSetTimer( grid, oldRowCol.row );
+ }
+ },
+
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.rowEdit.api:GridOptions
+ * @name rowEditWaitInterval
+ * @description How long the grid should wait for another change on this row
+ * before triggering a save (in milliseconds). If set to -1, then saves are
+ * never triggered by timer (implying that the user will call flushDirtyRows()
+ * manually)
+ *
+ * @example
+ * Setting the wait interval to 4 seconds
+ * <pre>
+ * $scope.gridOptions = { rowEditWaitInterval: 4000 }
+ * </pre>
+ *
+ */
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name considerSetTimer
+ * @description Consider setting a timer on this row (if it is dirty). if there is a timer running
+ * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is
+ * dirty and not currently saving then set a new timer
+ * @param {object} grid the grid for which we are processing
+ * @param {GridRow} gridRow the row for which the timer should be adjusted
+ *
+ */
+ considerSetTimer: function( grid, gridRow ){
+ service.cancelTimer( grid, gridRow );
+
+ if ( gridRow.isDirty && !gridRow.isSaving ){
+ if ( grid.options.rowEditWaitInterval !== -1 ){
+ var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;
+ gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name cancelTimer
+ * @description cancel the $interval for any timer running on this row
+ * then delete the timer itself
+ * @param {object} grid the grid for which we are processing
+ * @param {GridRow} gridRow the row for which the timer should be adjusted
+ *
+ */
+ cancelTimer: function( grid, gridRow ){
+ if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){
+ $interval.cancel(gridRow.rowEditSaveTimer);
+ delete gridRow.rowEditSaveTimer;
+ }
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setRowsDirty
+ * @description Sets each of the rows passed in dataRows
+ * to be dirty. note that if you have only just inserted the
+ * rows into your data you will need to wait for a $digest cycle
+ * before the gridRows are present - so often you would wrap this
+ * call in a $interval or $timeout
+ * <pre>
+ * $interval( function() {
+ * gridApi.rowEdit.setRowsDirty( myDataRows);
+ * }, 0, 1);
+ * </pre>
+ * @param {object} grid the grid for which rows should be set dirty
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set dirty.
+ *
+ */
+ setRowsDirty: function( grid, myDataRows ) {
+ var gridRow;
+ myDataRows.forEach( function( value, index ){
+ gridRow = grid.getRow( value );
+ if ( gridRow ){
+ if ( !grid.rowEdit.dirtyRows ){
+ grid.rowEdit.dirtyRows = [];
+ }
+
+ if ( !gridRow.isDirty ){
+ gridRow.isDirty = true;
+ grid.rowEdit.dirtyRows.push( gridRow );
+ }
+
+ delete gridRow.isError;
+
+ service.considerSetTimer( grid, gridRow );
+ } else {
+ gridUtil.logError( "requested row not found in rowEdit.setRowsDirty, row was: " + value );
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc method
+ * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
+ * @name setRowsClean
+ * @description Sets each of the rows passed in dataRows
+ * to be clean, clearing the dirty flag and the error flag, and removing
+ * the rows from the dirty and error caches.
+ * @param {object} grid the grid for which rows should be set clean
+ * @param {array} dataRows the data entities for which the gridRows
+ * should be set clean.
+ *
+ */
+ setRowsClean: function( grid, myDataRows ) {
+ var gridRow;
+
+ myDataRows.forEach( function( value, index ){
+ gridRow = grid.getRow( value );
+ if ( gridRow ){
+ delete gridRow.isDirty;
+ service.removeRow( grid.rowEdit.dirtyRows, gridRow );
+ service.cancelTimer( grid, gridRow );
+
+ delete gridRow.isError;
+ service.removeRow( grid.rowEdit.errorRows, gridRow );
+ } else {
+ gridUtil.logError( "requested row not found in rowEdit.setRowsClean, row was: " + value );
+ }
+ });
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.rowEdit.directive:uiGridEdit
+ * @element div
+ * @restrict A
+ *
+ * @description Adds row editing features to the ui-grid-edit directive.
+ *
+ */
+ module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',
+ function (gridUtil, uiGridRowEditService, uiGridEditConstants) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+ }
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.rowEdit.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
+ * for the grid row to allow coloring of saving and error rows
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
+ function ($compile, uiGridConstants, gridUtil, $parse) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
+ } else {
+ newNgClass = "{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.saveState
+ * @description
+ *
+ * # ui.grid.saveState
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * This module provides the ability to save the grid state, and restore
+ * it when the user returns to the page.
+ *
+ * No UI is provided, the caller should provide their own UI/buttons
+ * as appropriate. Usually the navigate events would be used to save
+ * the grid state and restore it.
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.save-state"></div>
+ */
+
+ var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.constant:uiGridSaveStateConstants
+ *
+ * @description constants available in save state module
+ */
+
+ module.constant('uiGridSaveStateConstants', {
+ featureName: 'saveState'
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.saveState.service:uiGridSaveStateService
+ *
+ * @description Services for saveState feature
+ */
+ module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',
+ function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed state
+ grid.saveState = {};
+ this.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.api:PublicApi
+ *
+ * @description Public Api for saveState feature
+ */
+ var publicApi = {
+ events: {
+ saveState: {
+ }
+ },
+ methods: {
+ saveState: {
+ /**
+ * @ngdoc function
+ * @name save
+ * @methodOf ui.grid.saveState.api:PublicApi
+ * @description Packages the current state of the grid into
+ * an object, and provides it to the user for saving
+ * @returns {object} the state as a javascript object that can be saved
+ */
+ save: function () {
+ return service.save(grid);
+ },
+ /**
+ * @ngdoc function
+ * @name restore
+ * @methodOf ui.grid.saveState.api:PublicApi
+ * @description Restores the provided state into the grid
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} state the state that should be restored into the grid
+ */
+ restore: function ( $scope, state) {
+ service.restore(grid, $scope, state);
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.saveState.api:GridOptions
+ *
+ * @description GridOptions for saveState feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+ /**
+ * @ngdoc object
+ * @name saveWidths
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current column widths. Note that unless
+ * you've provided the user with some way to resize their columns (say
+ * the resize columns feature), then this makes little sense.
+ * <br/>Defaults to true
+ */
+ gridOptions.saveWidths = gridOptions.saveWidths !== false;
+ /**
+ * @ngdoc object
+ * @name saveOrder
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Restore the current column order. Note that unless
+ * you've provided the user with some way to reorder their columns (for
+ * example the move columns feature), this makes little sense.
+ * <br/>Defaults to true
+ */
+ gridOptions.saveOrder = gridOptions.saveOrder !== false;
+ /**
+ * @ngdoc object
+ * @name saveScroll
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current scroll position. Note that this
+ * is saved as the percentage of the grid scrolled - so if your
+ * user returns to a grid with a significantly different number of
+ * rows (perhaps some data has been deleted) then the scroll won't
+ * actually show the same rows as before. If you want to scroll to
+ * a specific row then you should instead use the saveFocus option, which
+ * is the default.
+ *
+ * Note that this element will only be saved if the cellNav feature is
+ * enabled
+ * <br/>Defaults to false
+ */
+ gridOptions.saveScroll = gridOptions.saveScroll === true;
+ /**
+ * @ngdoc object
+ * @name saveFocus
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current focused cell. On returning
+ * to this focused cell we'll also scroll. This option is
+ * preferred to the saveScroll option, so is set to true by
+ * default. If saveScroll is set to true then this option will
+ * be disabled.
+ *
+ * By default this option saves the current row number and column
+ * number, and returns to that row and column. However, if you define
+ * a saveRowIdentity function, then it will return you to the currently
+ * selected column within that row (in a business sense - so if some
+ * rows have been deleted, it will still find the same data, presuming it
+ * still exists in the list. If it isn't in the list then it will instead
+ * return to the same row number - i.e. scroll percentage)
+ *
+ * Note that this option will do nothing if the cellNav
+ * feature is not enabled.
+ *
+ * <br/>Defaults to true (unless saveScroll is true)
+ */
+ gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;
+ /**
+ * @ngdoc object
+ * @name saveRowIdentity
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description A function that can be called, passing in a rowEntity,
+ * and that will return a unique id for that row. This might simply
+ * return the `id` field from that row (if you have one), or it might
+ * concatenate some fields within the row to make a unique value.
+ *
+ * This value will be used to find the same row again and set the focus
+ * to it, if it exists when we return.
+ *
+ * <br/>Defaults to undefined
+ */
+ /**
+ * @ngdoc object
+ * @name saveVisible
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save whether or not columns are visible.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveVisible = gridOptions.saveVisible !== false;
+ /**
+ * @ngdoc object
+ * @name saveSort
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current sort state for each column
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveSort = gridOptions.saveSort !== false;
+ /**
+ * @ngdoc object
+ * @name saveFilter
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the current filter state for each column
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveFilter = gridOptions.saveFilter !== false;
+ /**
+ * @ngdoc object
+ * @name saveSelection
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the currently selected rows. If the `saveRowIdentity` callback
+ * is defined, then it will save the id of the row and select that. If not, then
+ * it will attempt to select the rows by row number, which will give the wrong results
+ * if the data set has changed in the mean-time.
+ *
+ * Note that this option only does anything
+ * if the selection feature is enabled.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveSelection = gridOptions.saveSelection !== false;
+ /**
+ * @ngdoc object
+ * @name saveGrouping
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the grouping configuration. If set to true and the
+ * grouping feature is not enabled then does nothing.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveGrouping = gridOptions.saveGrouping !== false;
+ /**
+ * @ngdoc object
+ * @name saveGroupingExpandedStates
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the grouping row expanded states. If set to true and the
+ * grouping feature is not enabled then does nothing.
+ *
+ * This can be quite a bit of data, in many cases you wouldn't want to save this
+ * information.
+ *
+ * <br/>Defaults to false
+ */
+ gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;
+ /**
+ * @ngdoc object
+ * @name savePinning
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save pinning state for columns.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.savePinning = gridOptions.savePinning !== false;
+ /**
+ * @ngdoc object
+ * @name saveTreeView
+ * @propertyOf ui.grid.saveState.api:GridOptions
+ * @description Save the treeView configuration. If set to true and the
+ * treeView feature is not enabled then does nothing.
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.saveTreeView = gridOptions.saveTreeView !== false;
+ },
+
+
+
+ /**
+ * @ngdoc function
+ * @name save
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the current grid state into an object, and
+ * passes that object back to the caller
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the state ready to be saved
+ */
+ save: function (grid) {
+ var savedState = {};
+
+ savedState.columns = service.saveColumns( grid );
+ savedState.scrollFocus = service.saveScrollFocus( grid );
+ savedState.selection = service.saveSelection( grid );
+ savedState.grouping = service.saveGrouping( grid );
+ savedState.treeView = service.saveTreeView( grid );
+
+ return savedState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restore
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Applies the provided state to the grid
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} state the state we'd like to restore
+ */
+ restore: function( grid, $scope, state ){
+ if ( state.columns ) {
+ service.restoreColumns( grid, state.columns );
+ }
+
+ if ( state.scrollFocus ){
+ service.restoreScrollFocus( grid, $scope, state.scrollFocus );
+ }
+
+ if ( state.selection ){
+ service.restoreSelection( grid, state.selection );
+ }
+
+ if ( state.grouping ){
+ service.restoreGrouping( grid, state.grouping );
+ }
+
+ if ( state.treeView ){
+ service.restoreTreeView( grid, state.treeView );
+ }
+
+ grid.refresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveColumns
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the column setup, including sort, filters, ordering,
+ * pinning and column widths.
+ *
+ * Works through the current columns, storing them in order. Stores the
+ * column name, then the visible flag, width, sort and filters for each column.
+ *
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {array} the columns state ready to be saved
+ */
+ saveColumns: function( grid ) {
+ var columns = [];
+ grid.getOnlyDataColumns().forEach( function( column ) {
+ var savedColumn = {};
+ savedColumn.name = column.name;
+
+ if ( grid.options.saveVisible ){
+ savedColumn.visible = column.visible;
+ }
+
+ if ( grid.options.saveWidths ){
+ savedColumn.width = column.width;
+ }
+
+ // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state
+ if ( grid.options.saveSort ){
+ savedColumn.sort = angular.copy( column.sort );
+ }
+
+ if ( grid.options.saveFilter ){
+ savedColumn.filters = [];
+ column.filters.forEach( function( filter ){
+ var copiedFilter = {};
+ angular.forEach( filter, function( value, key) {
+ if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder'){
+ copiedFilter[key] = value;
+ }
+ });
+ savedColumn.filters.push(copiedFilter);
+ });
+ }
+
+ if ( !!grid.api.pinning && grid.options.savePinning ){
+ savedColumn.pinned = column.renderContainer ? column.renderContainer : '';
+ }
+
+ columns.push( savedColumn );
+ });
+
+ return columns;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveScrollFocus
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the currently scroll or focus.
+ *
+ * If cellNav isn't present then does nothing - we can't return
+ * to the scroll position without cellNav anyway.
+ *
+ * If the cellNav module is present, and saveFocus is true, then
+ * it saves the currently focused cell. If rowIdentity is present
+ * then saves using rowIdentity, otherwise saves visibleRowNum.
+ *
+ * If the cellNav module is not present, and saveScroll is true, then
+ * it approximates the current scroll row and column, and saves that.
+ *
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the selection state ready to be saved
+ */
+ saveScrollFocus: function( grid ){
+ if ( !grid.api.cellNav ){
+ return {};
+ }
+
+ var scrollFocus = {};
+ if ( grid.options.saveFocus ){
+ scrollFocus.focus = true;
+ var rowCol = grid.api.cellNav.getFocusedCell();
+ if ( rowCol !== null ) {
+ if ( rowCol.col !== null ){
+ scrollFocus.colName = rowCol.col.colDef.name;
+ }
+ if ( rowCol.row !== null ){
+ scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );
+ }
+ }
+ }
+
+ if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {
+ scrollFocus.focus = false;
+ if ( grid.renderContainers.body.prevRowScrollIndex ){
+ scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);
+ }
+
+ if ( grid.renderContainers.body.prevColScrollIndex ){
+ scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;
+ }
+ }
+
+ return scrollFocus;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveSelection
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the currently selected rows, if the selection feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {array} the selection state ready to be saved
+ */
+ saveSelection: function( grid ){
+ if ( !grid.api.selection || !grid.options.saveSelection ){
+ return [];
+ }
+
+ var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {
+ return service.getRowVal( grid, gridRow );
+ });
+
+ return selection;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveGrouping
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the grouping state, if the grouping feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the grouping state ready to be saved
+ */
+ saveGrouping: function( grid ){
+ if ( !grid.api.grouping || !grid.options.saveGrouping ){
+ return {};
+ }
+
+ return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name saveTreeView
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Saves the tree view state, if the tree feature is enabled
+ * @param {Grid} grid the grid whose state we'd like to save
+ * @returns {object} the tree view state ready to be saved
+ */
+ saveTreeView: function( grid ){
+ if ( !grid.api.treeView || !grid.options.saveTreeView ){
+ return {};
+ }
+
+ return grid.api.treeView.getTreeView();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name getRowVal
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Helper function that gets either the rowNum or
+ * the saveRowIdentity, given a gridRow
+ * @param {Grid} grid the grid the row is in
+ * @param {GridRow} gridRow the row we want the rowNum for
+ * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }
+ *
+ */
+ getRowVal: function( grid, gridRow ){
+ if ( !gridRow ) {
+ return null;
+ }
+
+ var rowVal = {};
+ if ( grid.options.saveRowIdentity ){
+ rowVal.identity = true;
+ rowVal.row = grid.options.saveRowIdentity( gridRow.entity );
+ } else {
+ rowVal.identity = false;
+ rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );
+ }
+ return rowVal;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreColumns
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the columns, including order, visible, width,
+ * pinning, sort and filters.
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} columnsState the list of columns we had before, with their state
+ */
+ restoreColumns: function( grid, columnsState ){
+ var isSortChanged = false;
+
+ columnsState.forEach( function( columnState, index ) {
+ var currentCol = grid.getColumn( columnState.name );
+
+ if ( currentCol && !grid.isRowHeaderColumn(currentCol) ){
+ if ( grid.options.saveVisible &&
+ ( currentCol.visible !== columnState.visible ||
+ currentCol.colDef.visible !== columnState.visible ) ){
+ currentCol.visible = columnState.visible;
+ currentCol.colDef.visible = columnState.visible;
+ grid.api.core.raise.columnVisibilityChanged(currentCol);
+ }
+
+ if ( grid.options.saveWidths ){
+ currentCol.width = columnState.width;
+ }
+
+ if ( grid.options.saveSort &&
+ !angular.equals(currentCol.sort, columnState.sort) &&
+ !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ){
+ currentCol.sort = angular.copy( columnState.sort );
+ isSortChanged = true;
+ }
+
+ if ( grid.options.saveFilter &&
+ !angular.equals(currentCol.filters, columnState.filters ) ){
+ columnState.filters.forEach( function( filter, index ){
+ angular.extend( currentCol.filters[index], filter );
+ if ( typeof(filter.term) === 'undefined' || filter.term === null ){
+ delete currentCol.filters[index].term;
+ }
+ });
+ grid.api.core.raise.filterChanged();
+ }
+
+ if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ){
+ grid.api.pinning.pinColumn(currentCol, columnState.pinned);
+ }
+
+ var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );
+ if (currentIndex !== -1) {
+ if (grid.options.saveOrder && currentIndex !== index) {
+ var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];
+ grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);
+ }
+ }
+ }
+ });
+
+ if ( isSortChanged ) {
+ grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreScrollFocus
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Scrolls to the position that was saved. If focus is true, then
+ * sets focus to the specified row/col. If focus is false, then scrolls to the
+ * specified row/col.
+ *
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {scope} $scope a scope that we can broadcast on
+ * @param {object} scrollFocusState the scroll/focus state ready to be restored
+ */
+ restoreScrollFocus: function( grid, $scope, scrollFocusState ){
+ if ( !grid.api.cellNav ){
+ return;
+ }
+
+ var colDef, row;
+ if ( scrollFocusState.colName ){
+ var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });
+ if ( colDefs.length > 0 ){
+ colDef = colDefs[0];
+ }
+ }
+
+ if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){
+ if ( scrollFocusState.rowVal.identity ){
+ row = service.findRowByIdentity( grid, scrollFocusState.rowVal );
+ } else {
+ row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];
+ }
+ }
+
+ var entity = row && row.entity ? row.entity : null ;
+
+ if ( colDef || entity ) {
+ if (scrollFocusState.focus ){
+ grid.api.cellNav.scrollToFocus( entity, colDef );
+ } else {
+ grid.scrollTo( entity, colDef );
+ }
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreSelection
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Selects the rows that are provided in the selection
+ * state. If you are using `saveRowIdentity` and more than one row matches the identity
+ * function then only the first is selected.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} selectionState the selection state ready to be restored
+ */
+ restoreSelection: function( grid, selectionState ){
+ if ( !grid.api.selection ){
+ return;
+ }
+
+ grid.api.selection.clearSelectedRows();
+
+ selectionState.forEach( function( rowVal ) {
+ if ( rowVal.identity ){
+ var foundRow = service.findRowByIdentity( grid, rowVal );
+
+ if ( foundRow ){
+ grid.api.selection.selectRow( foundRow.entity );
+ }
+
+ } else {
+ grid.api.selection.selectRowByVisibleIndex( rowVal.row );
+ }
+ });
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name restoreGrouping
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the grouping configuration, if the grouping feature
+ * is enabled.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} groupingState the grouping state ready to be restored
+ */
+ restoreGrouping: function( grid, groupingState ){
+ if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ){
+ return;
+ }
+
+ grid.api.grouping.setGrouping( groupingState );
+ },
+
+ /**
+ * @ngdoc function
+ * @name restoreTreeView
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Restores the tree view configuration, if the tree view feature
+ * is enabled.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} treeViewState the tree view state ready to be restored
+ */
+ restoreTreeView: function( grid, treeViewState ){
+ if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ){
+ return;
+ }
+
+ grid.api.treeView.setTreeView( treeViewState );
+ },
+
+ /**
+ * @ngdoc function
+ * @name findRowByIdentity
+ * @methodOf ui.grid.saveState.service:uiGridSaveStateService
+ * @description Finds a row given it's identity value, returns the first found row
+ * if any are found, otherwise returns null if no rows are found.
+ * @param {Grid} grid the grid whose state we'd like to restore
+ * @param {object} rowVal the row we'd like to find
+ * @returns {gridRow} the found row, or null if none found
+ */
+ findRowByIdentity: function( grid, rowVal ){
+ if ( !grid.options.saveRowIdentity ){
+ return null;
+ }
+
+ var filteredRows = grid.rows.filter( function( gridRow ) {
+ if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){
+ return true;
+ } else {
+ return false;
+ }
+ });
+
+ if ( filteredRows.length > 0 ){
+ return filteredRows[0];
+ } else {
+ return null;
+ }
+ }
+ };
+
+ return service;
+
+ }
+ ]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.saveState.directive:uiGridSaveState
+ * @element div
+ * @restrict A
+ *
+ * @description Adds saveState features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.gridOptions = {
+ columnDefs: [
+ {name: 'name'},
+ {name: 'title', enableCellEdit: true}
+ ],
+ data: $scope.data
+ };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-save-state></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',
+ function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);
+ }
+ };
+ }
+ ]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.selection
+ * @description
+ *
+ * # ui.grid.selection
+ * This module provides row selection
+ *
+ * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
+ *
+ * <div doc-module-components="ui.grid.selection"></div>
+ */
+
+ var module = angular.module('ui.grid.selection', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.constant:uiGridSelectionConstants
+ *
+ * @description constants available in selection module
+ */
+ module.constant('uiGridSelectionConstants', {
+ featureName: "selection",
+ selectionRowHeaderColName: 'selectionRowHeaderCol'
+ });
+
+ //add methods to GridRow
+ angular.module('ui.grid').config(['$provide', function($provide) {
+ $provide.decorator('GridRow', ['$delegate', function($delegate) {
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:GridRow
+ *
+ * @description GridRow prototype functions added for selection
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableSelection
+ * @propertyOf ui.grid.selection.api:GridRow
+ * @description Enable row selection for this row, only settable by internal code.
+ *
+ * The grouping feature, for example, might set group header rows to not be selectable.
+ * <br/>Defaults to true
+ */
+
+ /**
+ * @ngdoc object
+ * @name isSelected
+ * @propertyOf ui.grid.selection.api:GridRow
+ * @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
+ * <br/>Defaults to false
+ */
+
+
+ /**
+ * @ngdoc function
+ * @name setSelected
+ * @methodOf ui.grid.selection.api:GridRow
+ * @description Sets the isSelected property and updates the selectedCount
+ * Changes to isSelected state should only be made via this function
+ * @param {bool} selected value to set
+ */
+ $delegate.prototype.setSelected = function(selected) {
+ this.isSelected = selected;
+ if (selected) {
+ this.grid.selection.selectedCount++;
+ }
+ else {
+ this.grid.selection.selectedCount--;
+ }
+ };
+
+ return $delegate;
+ }]);
+ }]);
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.selection.service:uiGridSelectionService
+ *
+ * @description Services for selection features
+ */
+ module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',
+ function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {
+
+ var service = {
+
+ initializeGrid: function (grid) {
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.grid:selection
+ *
+ * @description Grid properties and functions added for selection
+ */
+ grid.selection = {};
+ grid.selection.lastSelectedRow = null;
+ grid.selection.selectAll = false;
+
+
+ /**
+ * @ngdoc object
+ * @name selectedCount
+ * @propertyOf ui.grid.selection.grid:selection
+ * @description Current count of selected rows
+ * @example
+ * var count = grid.selection.selectedCount
+ */
+ grid.selection.selectedCount = 0;
+
+ service.defaultGridOptions(grid.options);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:PublicApi
+ *
+ * @description Public Api for selection feature
+ */
+ var publicApi = {
+ events: {
+ selection: {
+ /**
+ * @ngdoc event
+ * @name rowSelectionChanged
+ * @eventOf ui.grid.selection.api:PublicApi
+ * @description is raised after the row.isSelected state is changed
+ * @param {GridRow} row the row that was selected/deselected
+ * @param {Event} event object if raised from an event
+ */
+ rowSelectionChanged: function (scope, row, evt) {
+ },
+ /**
+ * @ngdoc event
+ * @name rowSelectionChangedBatch
+ * @eventOf ui.grid.selection.api:PublicApi
+ * @description is raised after the row.isSelected state is changed
+ * in bulk, if the `enableSelectionBatchEvent` option is set to true
+ * (which it is by default). This allows more efficient processing
+ * of bulk events.
+ * @param {array} rows the rows that were selected/deselected
+ * @param {Event} event object if raised from an event
+ */
+ rowSelectionChangedBatch: function (scope, rows, evt) {
+ }
+ }
+ },
+ methods: {
+ selection: {
+ /**
+ * @ngdoc function
+ * @name toggleRowSelection
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Toggles data row as selected or unselected
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ toggleRowSelection: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectRow
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Select the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ selectRow: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && !row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectRowByVisibleIndex
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Select the specified row by visible index (i.e. if you
+ * specify row 0 you'll get the first visible row selected). In this context
+ * visible means of those rows that are theoretically visible (i.e. not filtered),
+ * rather than rows currently rendered on the screen.
+ * @param {number} index index within the rowsVisible array
+ * @param {Event} event object if raised from an event
+ */
+ selectRowByVisibleIndex: function ( rowNum, evt ) {
+ var row = grid.renderContainers.body.visibleRowCache[rowNum];
+ if (row !== null && typeof(row) !== 'undefined' && !row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name unSelectRow
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description UnSelect the data row
+ * @param {object} rowEntity gridOptions.data[] array instance
+ * @param {Event} event object if raised from an event
+ */
+ unSelectRow: function (rowEntity, evt) {
+ var row = grid.getRow(rowEntity);
+ if (row !== null && row.isSelected) {
+ service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name selectAllRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Selects all rows. Does nothing if multiSelect = false
+ * @param {Event} event object if raised from an event
+ */
+ selectAllRows: function (evt) {
+ if (grid.options.multiSelect === false) {
+ return;
+ }
+
+ var changedRows = [];
+ grid.rows.forEach(function (row) {
+ if ( !row.isSelected && row.enableSelection !== false ){
+ row.setSelected(true);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = true;
+ },
+ /**
+ * @ngdoc function
+ * @name selectAllVisibleRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Selects all visible rows. Does nothing if multiSelect = false
+ * @param {Event} event object if raised from an event
+ */
+ selectAllVisibleRows: function (evt) {
+ if (grid.options.multiSelect === false) {
+ return;
+ }
+
+ var changedRows = [];
+ grid.rows.forEach(function (row) {
+ if (row.visible) {
+ if (!row.isSelected && row.enableSelection !== false){
+ row.setSelected(true);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ } else {
+ if (row.isSelected){
+ row.setSelected(false);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = true;
+ },
+ /**
+ * @ngdoc function
+ * @name clearSelectedRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Unselects all rows
+ * @param {Event} event object if raised from an event
+ */
+ clearSelectedRows: function (evt) {
+ service.clearSelectedRows(grid, evt);
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description returns all selectedRow's entity references
+ */
+ getSelectedRows: function () {
+ return service.getSelectedRows(grid).map(function (gridRow) {
+ return gridRow.entity;
+ });
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedGridRows
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description returns all selectedRow's as gridRows
+ */
+ getSelectedGridRows: function () {
+ return service.getSelectedRows(grid);
+ },
+ /**
+ * @ngdoc function
+ * @name setMultiSelect
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Sets the current gridOption.multiSelect to true or false
+ * @param {bool} multiSelect true to allow multiple rows
+ */
+ setMultiSelect: function (multiSelect) {
+ grid.options.multiSelect = multiSelect;
+ },
+ /**
+ * @ngdoc function
+ * @name setModifierKeysToMultiSelect
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false
+ * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used
+ */
+ setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {
+ grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectAllState
+ * @methodOf ui.grid.selection.api:PublicApi
+ * @description Returns whether or not the selectAll checkbox is currently ticked. The
+ * grid doesn't automatically select rows when you add extra data - so when you add data
+ * you need to explicitly check whether the selectAll is set, and then call setVisible rows
+ * if it is
+ */
+ getSelectAllState: function () {
+ return grid.selection.selectAll;
+ }
+
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.selection.api:GridOptions
+ *
+ * @description GridOptions for selection feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableRowSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable row selection for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;
+ /**
+ * @ngdoc object
+ * @name multiSelect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable multiple row selection for entire grid
+ * <br/>Defaults to true
+ */
+ gridOptions.multiSelect = gridOptions.multiSelect !== false;
+ /**
+ * @ngdoc object
+ * @name noUnselect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Prevent a row from being unselected. Works in conjunction
+ * with `multiselect = false` and `gridApi.selection.selectRow()` to allow
+ * you to create a single selection only grid - a row is always selected, you
+ * can only select different rows, you can't unselect the row.
+ * <br/>Defaults to false
+ */
+ gridOptions.noUnselect = gridOptions.noUnselect === true;
+ /**
+ * @ngdoc object
+ * @name modifierKeysToMultiSelect
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.
+ * <br/>Defaults to false
+ */
+ gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;
+ /**
+ * @ngdoc object
+ * @name enableRowHeaderSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable a row header to be used for selection
+ * <br/>Defaults to true
+ */
+ gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;
+ /**
+ * @ngdoc object
+ * @name enableFullRowSelection
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable selection by clicking anywhere on the row. Defaults to
+ * false if `enableRowHeaderSelection` is true, otherwise defaults to false.
+ */
+ if ( typeof(gridOptions.enableFullRowSelection) === 'undefined' ){
+ gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
+ }
+ /**
+ * @ngdoc object
+ * @name enableSelectAll
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Enable the select all checkbox at the top of the selectionRowHeader
+ * <br/>Defaults to true
+ */
+ gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;
+ /**
+ * @ngdoc object
+ * @name enableSelectionBatchEvent
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description If selected rows are changed in bulk, either via the API or
+ * via the selectAll checkbox, then a separate event is fired. Setting this
+ * option to false will cause the rowSelectionChanged event to be called multiple times
+ * instead
+ * <br/>Defaults to true
+ */
+ gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;
+ /**
+ * @ngdoc object
+ * @name selectionRowHeaderWidth
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description can be used to set a custom width for the row header selection column
+ * <br/>Defaults to 30px
+ */
+ gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
+
+ /**
+ * @ngdoc object
+ * @name enableFooterTotalSelected
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Shows the total number of selected items in footer if true.
+ * <br/>Defaults to true.
+ * <br/>GridOptions.showGridFooter must also be set to true.
+ */
+ gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
+
+ /**
+ * @ngdoc object
+ * @name isRowSelectable
+ * @propertyOf ui.grid.selection.api:GridOptions
+ * @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
+ */
+
+ gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
+ },
+
+ /**
+ * @ngdoc function
+ * @name toggleRowSelection
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Toggles row as selected or unselected
+ * @param {Grid} grid grid object
+ * @param {GridRow} row row to select or deselect
+ * @param {Event} event object if resulting from event
+ * @param {bool} multiSelect if false, only one row at time can be selected
+ * @param {bool} noUnselect if true then rows cannot be unselected
+ */
+ toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
+ var selected = row.isSelected;
+
+ if ( row.enableSelection === false && !selected ){
+ return;
+ }
+
+ var selectedRows;
+ if (!multiSelect && !selected) {
+ service.clearSelectedRows(grid, evt);
+ } else if (!multiSelect && selected) {
+ selectedRows = service.getSelectedRows(grid);
+ if (selectedRows.length > 1) {
+ selected = false; // Enable reselect of the row
+ service.clearSelectedRows(grid, evt);
+ }
+ }
+
+ if (selected && noUnselect){
+ // don't deselect the row
+ } else {
+ row.setSelected(!selected);
+ if (row.isSelected === true) {
+ grid.selection.lastSelectedRow = row;
+ }
+
+ selectedRows = service.getSelectedRows(grid);
+ grid.selection.selectAll = grid.rows.length === selectedRows.length;
+
+ grid.api.selection.raise.rowSelectionChanged(row, evt);
+ }
+ },
+ /**
+ * @ngdoc function
+ * @name shiftSelect
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description selects a group of rows from the last selected row using the shift key
+ * @param {Grid} grid grid object
+ * @param {GridRow} clicked row
+ * @param {Event} event object if raised from an event
+ * @param {bool} multiSelect if false, does nothing this is for multiSelect only
+ */
+ shiftSelect: function (grid, row, evt, multiSelect) {
+ if (!multiSelect) {
+ return;
+ }
+ var selectedRows = service.getSelectedRows(grid);
+ var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;
+ var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);
+ //reverse select direction
+ if (fromRow > toRow) {
+ var tmp = fromRow;
+ fromRow = toRow;
+ toRow = tmp;
+ }
+
+ var changedRows = [];
+ for (var i = fromRow; i <= toRow; i++) {
+ var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
+ if (rowToSelect) {
+ if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){
+ rowToSelect.setSelected(true);
+ grid.selection.lastSelectedRow = rowToSelect;
+ service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );
+ }
+ }
+ }
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ },
+ /**
+ * @ngdoc function
+ * @name getSelectedRows
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Returns all the selected rows
+ * @param {Grid} grid grid object
+ */
+ getSelectedRows: function (grid) {
+ return grid.rows.filter(function (row) {
+ return row.isSelected;
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name clearSelectedRows
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Clears all selected rows
+ * @param {Grid} grid grid object
+ * @param {Event} event object if raised from an event
+ */
+ clearSelectedRows: function (grid, evt) {
+ var changedRows = [];
+ service.getSelectedRows(grid).forEach(function (row) {
+ if ( row.isSelected ){
+ row.setSelected(false);
+ service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
+ }
+ });
+ service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
+ grid.selection.selectAll = false;
+ grid.selection.selectedCount = 0;
+ },
+
+ /**
+ * @ngdoc function
+ * @name decideRaiseSelectionEvent
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Decides whether to raise a single event or a batch event
+ * @param {Grid} grid grid object
+ * @param {GridRow} row row that has changed
+ * @param {array} changedRows an array to which we can append the changed
+ * @param {Event} event object if raised from an event
+ * row if we're doing batch events
+ */
+ decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){
+ if ( !grid.options.enableSelectionBatchEvent ){
+ grid.api.selection.raise.rowSelectionChanged(row, evt);
+ } else {
+ changedRows.push(row);
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name raiseSelectionEvent
+ * @methodOf ui.grid.selection.service:uiGridSelectionService
+ * @description Decides whether we need to raise a batch event, and
+ * raises it if we do.
+ * @param {Grid} grid grid object
+ * @param {array} changedRows an array of changed rows, only populated
+ * @param {Event} event object if raised from an event
+ * if we're doing batch events
+ */
+ decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){
+ if ( changedRows.length > 0 ){
+ grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);
+ }
+ }
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridSelection
+ * @element div
+ * @restrict A
+ *
+ * @description Adds selection features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-selection></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache', 'uiGridConstants',
+ function (uiGridSelectionConstants, uiGridSelectionService, $templateCache, uiGridConstants) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ uiGridSelectionService.initializeGrid(uiGridCtrl.grid);
+ if (uiGridCtrl.grid.options.enableRowHeaderSelection) {
+ var selectionRowHeaderDef = {
+ name: uiGridSelectionConstants.selectionRowHeaderColName,
+ displayName: '',
+ width: uiGridCtrl.grid.options.selectionRowHeaderWidth,
+ minWidth: 10,
+ cellTemplate: 'ui-grid/selectionRowHeader',
+ headerCellTemplate: 'ui-grid/selectionHeaderCell',
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ exporterSuppressExport: true,
+ allowCellFocus: true
+ };
+
+ uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef);
+ }
+
+ var processorSet = false;
+
+ var processSelectableRows = function( rows ){
+ rows.forEach(function(row){
+ row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);
+ });
+ return rows;
+ };
+
+ var updateOptions = function(){
+ if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {
+ uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);
+ processorSet = true;
+ }
+ };
+
+ updateOptions();
+
+ var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback( updateOptions, [uiGridConstants.dataChange.OPTIONS] );
+
+ $scope.$on( '$destroy', dataChangeDereg);
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+ module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',
+ function ($templateCache, uiGridSelectionService, gridUtil) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),
+ scope: true,
+ require: '^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = uiGridCtrl.grid;
+ $scope.selectButtonClick = selectButtonClick;
+
+ // On IE, prevent mousedowns on the select button from starting a selection.
+ // If this is not done and you shift+click on another row, the browser will select a big chunk of text
+ if (gridUtil.detectBrowser() === 'ie') {
+ $elm.on('mousedown', selectButtonMouseDown);
+ }
+
+
+ function selectButtonClick(row, evt) {
+ evt.stopPropagation();
+
+ if (evt.shiftKey) {
+ uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
+ }
+ else if (evt.ctrlKey || evt.metaKey) {
+ uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
+ }
+ else {
+ uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
+ }
+ }
+
+ function selectButtonMouseDown(evt) {
+ if (evt.ctrlKey || evt.shiftKey) {
+ evt.target.onselectstart = function () { return false; };
+ window.setTimeout(function () { evt.target.onselectstart = null; }, 0);
+ }
+ }
+ }
+ };
+ }]);
+
+ module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',
+ function ($templateCache, uiGridSelectionService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/selectionSelectAllButtons'),
+ scope: false,
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = $scope.col.grid;
+
+ $scope.headerButtonClick = function(row, evt) {
+ if ( self.selection.selectAll ){
+ uiGridSelectionService.clearSelectedRows(self, evt);
+ if ( self.options.noUnselect ){
+ self.api.selection.selectRowByVisibleIndex(0, evt);
+ }
+ self.selection.selectAll = false;
+ } else {
+ if ( self.options.multiSelect ){
+ self.api.selection.selectAllVisibleRows(evt);
+ self.selection.selectAll = true;
+ }
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
+ * for the grid row
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',
+ function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-row-selected': row.isSelected}";
+ } else {
+ newNgClass = "{'ui-grid-row-selected': row.isSelected}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.selection.directive:uiGridCell
+ * @element div
+ * @restrict A
+ *
+ * @description Stacks on top of ui.grid.uiGridCell to provide selection feature
+ */
+ module.directive('uiGridCell',
+ ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService', '$timeout',
+ function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService, $timeout) {
+ return {
+ priority: -200, // run after default uiGridCell directive
+ restrict: 'A',
+ require: '?^uiGrid',
+ scope: false,
+ link: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ var touchStartTime = 0;
+ var touchTimeout = 300;
+
+ // Bind to keydown events in the render container
+ if (uiGridCtrl.grid.api.cellNav) {
+
+ uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
+ if (rowCol === null ||
+ rowCol.row !== $scope.row ||
+ rowCol.col !== $scope.col) {
+ return;
+ }
+
+ if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ $scope.$apply();
+ }
+
+ // uiGridCellNavService.scrollToIfNecessary(uiGridCtrl.grid, rowCol.row, rowCol.col);
+ });
+ }
+
+ //$elm.bind('keydown', function (evt) {
+ // if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
+ // uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ // $scope.$apply();
+ // }
+ //});
+
+ var selectCells = function(evt){
+ // if we get a click, then stop listening for touchend
+ $elm.off('touchend', touchEnd);
+
+ if (evt.shiftKey) {
+ uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
+ }
+ else if (evt.ctrlKey || evt.metaKey) {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
+ }
+ else {
+ uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
+ }
+ $scope.$apply();
+
+ // don't re-enable the touchend handler for a little while - some devices generate both, and it will
+ // take a little while to move your hand from the mouse to the screen if you have both modes of input
+ $timeout(function() {
+ $elm.on('touchend', touchEnd);
+ }, touchTimeout);
+ };
+
+ var touchStart = function(evt){
+ touchStartTime = (new Date()).getTime();
+
+ // if we get a touch event, then stop listening for click
+ $elm.off('click', selectCells);
+ };
+
+ var touchEnd = function(evt) {
+ var touchEndTime = (new Date()).getTime();
+ var touchTime = touchEndTime - touchStartTime;
+
+ if (touchTime < touchTimeout ) {
+ // short touch
+ selectCells(evt);
+ }
+
+ // don't re-enable the click handler for a little while - some devices generate both, and it will
+ // take a little while to move your hand from the screen to the mouse if you have both modes of input
+ $timeout(function() {
+ $elm.on('click', selectCells);
+ }, touchTimeout);
+ };
+
+ function registerRowSelectionEvents() {
+ if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection) {
+ $elm.addClass('ui-grid-disable-selection');
+ $elm.on('touchstart', touchStart);
+ $elm.on('touchend', touchEnd);
+ $elm.on('click', selectCells);
+
+ $scope.registered = true;
+ }
+ }
+
+ function deregisterRowSelectionEvents() {
+ if ($scope.registered){
+ $elm.removeClass('ui-grid-disable-selection');
+
+ $elm.off('touchstart', touchStart);
+ $elm.off('touchend', touchEnd);
+ $elm.off('click', selectCells);
+
+ $scope.registered = false;
+ }
+ }
+
+ registerRowSelectionEvents();
+ // register a dataChange callback so that we can change the selection configuration dynamically
+ // if the user changes the options
+ var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {
+ if ( $scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
+ !$scope.registered ){
+ registerRowSelectionEvents();
+ } else if ( ( !$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection ) &&
+ $scope.registered ){
+ deregisterRowSelectionEvents();
+ }
+ }, [uiGridConstants.dataChange.OPTIONS] );
+
+ $elm.on( '$destroy', dataChangeDereg);
+ }
+ };
+ }]);
+
+ module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ priority: -1000,
+ require: '^uiGrid',
+ scope: true,
+ compile: function ($elm, $attrs) {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ if (!uiGridCtrl.grid.options.showGridFooter) {
+ return;
+ }
+
+
+ gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
+ .then(function (contents) {
+ var template = angular.element(contents);
+
+ var newElm = $compile(template)($scope);
+
+ angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
+ });
+ },
+
+ post: function ($scope, $elm, $attrs, controllers) {
+
+ }
+ };
+ }
+ };
+ }]);
+
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.treeBase
+ * @description
+ *
+ * # ui.grid.treeBase
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides base tree handling functions that are shared by other features, notably grouping
+ * and treeView. It provides a tree view of the data, with nodes in that
+ * tree and leaves.
+ *
+ * Design information:
+ * -------------------
+ *
+ * The raw data that is provided must come with a $$treeLevel on any non-leaf node. Grouping will create
+ * these on all the group header rows, treeView will expect these to be set in the raw data by the user.
+ * TreeBase will run a rowsProcessor that:
+ * - builds `treeBase.tree` out of the provided rows
+ * - permits a recursive sort of the tree
+ * - maintains the expand/collapse state of each node
+ * - provides the expand/collapse all button and the expand/collapse buttons
+ * - maintains the count of children for each node
+ *
+ * Each row is updated with a link to the tree node that represents it. Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}
+ * for information.
+ *
+ * TreeBase adds information to the rows
+ * - treeLevel: if present and > -1 tells us the level (level 0 is the top level)
+ * - treeNode: pointer to the node in the grid.treeBase.tree that refers
+ * to this row, allowing us to manipulate the state
+ *
+ * Since the logic is baked into the rowsProcessors, it should get triggered whenever
+ * row order or filtering or anything like that is changed. We recall the expanded state
+ * across invocations of the rowsProcessors by the reference to the treeNode on the individual
+ * rows. We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to
+ * get the state, but we overwrite the other data in that treeNode.
+ *
+ * By default rows are collapsed, which means all data rows have their visible property
+ * set to false, and only level 0 group rows are set to visible.
+ *
+ * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into
+ * grid.treeBase.tree, then call refresh. This is because we can't easily change the visible
+ * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as
+ * well use it all the time.
+ *
+ * Tree base provides sorting (on non-grouped columns).
+ *
+ * Sorting works in two passes. The standard sorting is performed for any columns that are important to building
+ * the tree (for example, any grouped columns). Then after the tree is built, a recursive tree sort is performed
+ * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level
+ * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).
+ *
+ * To achieve this we make use of the `ignoreSort` property on the sort configuration. The parent feature (treeView or grouping)
+ * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets
+ * the `ignoreSort`on any sort that it wants to run on the tree. TreeBase will clear the ignoreSort on all sorts - so it
+ * will turn on any sorts that haven't run. It will then call a recursive sort on the tree.
+ *
+ * Tree base provides treeAggregation. It checks the treeAggregation configuration on each column, and aggregates based on
+ * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,
+ * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the
+ * treeAggregations in the column footer. Aggregation information will be collected in the format:
+ *
+ * ```
+ * {
+ * type: 'count',
+ * value: 4,
+ * label: 'count: ',
+ * rendered: 'count: 4'
+ * }
+ * ```
+ *
+ * A callback is provided to format the value once it is finalised (aka a valueFilter).
+ *
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.treeBase"></div>
+ */
+
+ var module = angular.module('ui.grid.treeBase', ['ui.grid']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.constant:uiGridTreeBaseConstants
+ *
+ * @description constants available in treeBase module.
+ *
+ * These constants are manually copied into grouping and treeView,
+ * as I haven't found a way to simply include them, and it's not worth
+ * investing time in for something that changes very infrequently.
+ *
+ */
+ module.constant('uiGridTreeBaseConstants', {
+ featureName: "treeBase",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.treeBase.service:uiGridTreeBaseService
+ *
+ * @description Services for treeBase feature
+ */
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:ColumnDef
+ *
+ * @description ColumnDef for tree feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
+ */
+
+ module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',
+ function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+
+ //add feature namespace and any properties to grid for needed
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.grid:treeBase
+ *
+ * @description Grid properties and functions added for treeBase
+ */
+ grid.treeBase = {};
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name numberLevels
+ *
+ * @description Total number of tree levels currently used, calculated by the rowsProcessor by
+ * retaining the highest tree level it sees
+ */
+ grid.treeBase.numberLevels = 0;
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name expandAll
+ *
+ * @description Whether or not the expandAll box is selected
+ */
+ grid.treeBase.expandAll = false;
+
+ /**
+ * @ngdoc property
+ * @propertyOf ui.grid.treeBase.grid:treeBase
+ * @name tree
+ *
+ * @description Tree represented as a nested array that holds the state of each node, along with a
+ * pointer to the row. The array order is material - we will display the children in the order
+ * they are stored in the array
+ *
+ * Each node stores:
+ *
+ * - the state of this node
+ * - an array of children of this node
+ * - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)
+ * - the number of children of this node
+ * - aggregation information calculated from the nodes
+ *
+ * ```
+ * [{
+ * state: 'expanded',
+ * row: <reference to row>,
+ * parentRow: null,
+ * aggregations: [{
+ * type: 'count',
+ * col: <gridCol>,
+ * value: 2,
+ * label: 'count: ',
+ * rendered: 'count: 2'
+ * }],
+ * children: [
+ * {
+ * state: 'expanded',
+ * row: <reference to row>,
+ * parentRow: <reference to row>,
+ * aggregations: [{
+ * type: 'count',
+ * col: '<gridCol>,
+ * value: 4,
+ * label: 'count: ',
+ * rendered: 'count: 4'
+ * }],
+ * children: [
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }
+ * ]
+ * },
+ * {
+ * state: 'collapsed',
+ * row: <reference to row>,
+ * parentRow: <reference to row>,
+ * aggregations: [{
+ * type: 'count',
+ * col: <gridCol>,
+ * value: 3,
+ * label: 'count: ',
+ * rendered: 'count: 3'
+ * }],
+ * children: [
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
+ * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }
+ * ]
+ * }
+ * ]
+ * }, {<another level 0 node maybe>} ]
+ * ```
+ * Missing state values are false - meaning they aren't expanded.
+ *
+ * This is used because the rowProcessors run every time the grid is refreshed, so
+ * we'd lose the expanded state every time the grid was refreshed. This instead gives
+ * us a reliable lookup that persists across rowProcessors.
+ *
+ * This tree is rebuilt every time we run the rowsProcessors. Since each row holds a pointer
+ * to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard
+ * all transient information on the tree (children, childCount) and recalculate it
+ *
+ */
+ grid.treeBase.tree = {};
+
+ service.defaultGridOptions(grid.options);
+
+ grid.registerRowsProcessor(service.treeRows, 410);
+
+ grid.registerColumnBuilder( service.treeBaseColumnBuilder );
+
+ service.createRowHeader( grid );
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:PublicApi
+ *
+ * @description Public Api for treeBase feature
+ */
+ var publicApi = {
+ events: {
+ treeBase: {
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.treeBase.api:PublicApi
+ * @name rowExpanded
+ * @description raised whenever a row is expanded. If you are dynamically
+ * rendering your tree you can listen to this event, and then retrieve
+ * the children of this row and load them into the grid data.
+ *
+ * When the data is loaded the grid will automatically refresh to show these new rows
+ *
+ * <pre>
+ * gridApi.treeBase.on.rowExpanded(scope,function(row){})
+ * </pre>
+ * @param {gridRow} row the row that was expanded. You can also
+ * retrieve the grid from this row with row.grid
+ */
+ rowExpanded: {},
+
+ /**
+ * @ngdoc event
+ * @eventOf ui.grid.treeBase.api:PublicApi
+ * @name rowCollapsed
+ * @description raised whenever a row is collapsed. Doesn't really have
+ * a purpose at the moment, included for symmetry
+ *
+ * <pre>
+ * gridApi.treeBase.on.rowCollapsed(scope,function(row){})
+ * </pre>
+ * @param {gridRow} row the row that was collapsed. You can also
+ * retrieve the grid from this row with row.grid
+ */
+ rowCollapsed: {}
+ }
+ },
+
+ methods: {
+ treeBase: {
+ /**
+ * @ngdoc function
+ * @name expandAllRows
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Expands all tree rows
+ */
+ expandAllRows: function () {
+ service.expandAllRows(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseAllRows
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse all tree rows
+ */
+ collapseAllRows: function () {
+ service.collapseAllRows(grid);
+ },
+
+ /**
+ * @ngdoc function
+ * @name toggleRowTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description call expand if the row is collapsed, collapse if it is expanded
+ * @param {gridRow} row the row you wish to toggle
+ */
+ toggleRowTreeState: function (row) {
+ service.toggleRowTreeState(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name expandRow
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description expand the immediate children of the specified row
+ * @param {gridRow} row the row you wish to expand
+ */
+ expandRow: function (row) {
+ service.expandRow(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name expandRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description expand all children of the specified row
+ * @param {gridRow} row the row you wish to expand
+ */
+ expandRowChildren: function (row) {
+ service.expandRowChildren(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseRow
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse the specified row. When
+ * you expand the row again, all grandchildren will retain their state
+ * @param {gridRow} row the row you wish to collapse
+ */
+ collapseRow: function ( row ) {
+ service.collapseRow(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name collapseRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description collapse all children of the specified row. When
+ * you expand the row again, all grandchildren will be collapsed
+ * @param {gridRow} row the row you wish to collapse children for
+ */
+ collapseRowChildren: function ( row ) {
+ service.collapseRowChildren(grid, row);
+ },
+
+ /**
+ * @ngdoc function
+ * @name getTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Get the tree state for this grid,
+ * used by the saveState feature
+ * Returned treeState as an object
+ * `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`
+ * where expandedState is a hash of row uid and the current expanded state
+ *
+ * @returns {object} tree state
+ *
+ * TODO - this needs work - we need an identifier that persists across instantiations,
+ * not uid. This really means we need a row identity defined, but that won't work for
+ * grouping. Perhaps this needs to be moved up to treeView and grouping, rather than
+ * being in base.
+ */
+ getTreeExpandedState: function () {
+ return { expandedState: service.getTreeState(grid) };
+ },
+
+ /**
+ * @ngdoc function
+ * @name setTreeState
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Set the expanded states of the tree
+ * @param {object} config the config you want to apply, in the format
+ * provided by getTreeState
+ */
+ setTreeState: function ( config ) {
+ service.setTreeState( grid, config );
+ },
+
+ /**
+ * @ngdoc function
+ * @name getRowChildren
+ * @methodOf ui.grid.treeBase.api:PublicApi
+ * @description Get the children of the specified row
+ * @param {GridRow} row the row you want the children of
+ * @returns {Array} array of children of this row, the children
+ * are all gridRows
+ */
+ getRowChildren: function ( row ){
+ return row.treeNode.children.map( function( childNode ){
+ return childNode.row;
+ });
+ }
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+ },
+
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeBase.api:GridOptions
+ *
+ * @description GridOptions for treeBase feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ */
+
+ /**
+ * @ngdoc object
+ * @name treeRowHeaderBaseWidth
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Base width of the tree header, provides for a single level of tree. This
+ * is incremented by `treeIndent` for each extra level
+ * <br/>Defaults to 30
+ */
+ gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;
+
+ /**
+ * @ngdoc object
+ * @name treeIndent
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,
+ * but will make the tree row header wider
+ * <br/>Defaults to 10
+ */
+ gridOptions.treeIndent = gridOptions.treeIndent || 10;
+
+ /**
+ * @ngdoc object
+ * @name showTreeRowHeader
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to false, don't create the row header. Youll need to programatically control the expand
+ * states
+ * <br/>Defaults to true
+ */
+ gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;
+
+ /**
+ * @ngdoc object
+ * @name showTreeExpandNoChildren
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to true, show the expand/collapse button even if there are no
+ * children of a node. You'd use this if you're planning to dynamically load the children
+ *
+ * <br/>Defaults to true, grouping overrides to false
+ */
+ gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;
+
+ /**
+ * @ngdoc object
+ * @name treeRowHeaderAlwaysVisible
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description If set to true, row header even if there are no tree nodes
+ *
+ * <br/>Defaults to true
+ */
+ gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;
+
+ /**
+ * @ngdoc object
+ * @name treeCustomAggregations
+ * @propertyOf ui.grid.treeBase.api:GridOptions
+ * @description Define custom aggregation functions. The properties of this object will be
+ * aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.
+ * If a function defined here uses the same name as one of the native aggregations, this one will take precedence.
+ * The object format is:
+ *
+ * <pre>
+ * {
+ * aggregationName: {
+ * label: (optional) string,
+ * aggregationFn: function( aggregation, fieldValue, numValue, row ){...},
+ * finalizerFn: (optional) function( aggregation ){...}
+ * },
+ * mean: {
+ * label: 'mean',
+ * aggregationFn: function( aggregation, fieldValue, numValue ){
+ * aggregation.count = (aggregation.count || 1) + 1;
+ * aggregation.sum = (aggregation.sum || 0) + numValue;
+ * },
+ * finalizerFn: function( aggregation ){
+ * aggregation.value = aggregation.sum / aggregation.count
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to
+ * apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be
+ * rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate
+ * the label and the value.
+ *
+ * <br/>Defaults to {}
+ */
+ gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name treeBaseColumnBuilder
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Sets the tree defaults based on the columnDefs
+ *
+ * @param {object} colDef columnDef we're basing on
+ * @param {GridCol} col the column we're to update
+ * @param {object} gridOptions the options we should use
+ * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
+ */
+ treeBaseColumnBuilder: function (colDef, col, gridOptions) {
+
+
+ /**
+ * @ngdoc object
+ * @name customTreeAggregationFn
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom function that aggregates rows into some form of
+ * total. Aggregations run row-by-row, the function needs to be capable of
+ * creating a running total.
+ *
+ * The function will be provided the aggregation item (in which you can store running
+ * totals), the row value that is to be aggregated, and that same row value converted to
+ * a number (most aggregations work on numbers)
+ * @example
+ * <pre>
+ * customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ){
+ * // calculates the average of the squares of the values
+ * if ( typeof(aggregation.count) === 'undefined' ){
+ * aggregation.count = 0;
+ * }
+ * aggregation.count++;
+ *
+ * if ( !isNaN(numValue) ){
+ * if ( typeof(aggregation.total) === 'undefined' ){
+ * aggregation.total = 0;
+ * }
+ * aggregation.total = aggregation.total + numValue * numValue;
+ * }
+ *
+ * aggregation.value = aggregation.total / aggregation.count;
+ * }
+ * </pre>
+ * <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.
+ */
+ if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ){
+ col.treeAggregationFn = colDef.customTreeAggregationFn;
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationType
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.
+ * Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the
+ * name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.
+ *
+ * <pre>
+ * treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,
+ * }
+ * </pre>
+ *
+ * If you are using aggregations you should either:
+ *
+ * - also use grouping, in which case the aggregations are displayed in the group header, OR
+ * - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and
+ * treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`
+ * in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations
+ *
+ * <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.
+ * <br/>Defaults to undefined.
+ */
+ if ( typeof(colDef.treeAggregationType) !== 'undefined' ){
+ col.treeAggregation = { type: colDef.treeAggregationType };
+ if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ){
+ col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;
+ col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;
+ col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;
+ } else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ){
+ col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;
+ col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;
+ }
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationLabel
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom label to use for this aggregation. If provided we don't use native i18n.
+ */
+ if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ){
+ if (typeof(col.treeAggregation) === 'undefined' ){
+ col.treeAggregation = {};
+ }
+ col.treeAggregation.label = colDef.treeAggregationLabel;
+ }
+
+ /**
+ * @ngdoc object
+ * @name treeAggregationUpdateEntity
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description Store calculated aggregations into the entity, allowing them
+ * to be displayed in the grid using a standard cellTemplate. This defaults to true,
+ * if you are using grouping then you shouldn't set it to false, as then the aggregations won't
+ * display.
+ *
+ * If you are using treeView in most cases you'll want to set this to true. This will result in
+ * getCellValue returning the aggregation rather than whatever was stored in the cell attribute on
+ * the entity. If you want to render the underlying entity value (and do something else with the aggregation)
+ * then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.
+ *
+ * <br/>Defaults to true
+ *
+ * @example
+ * <pre>
+ * gridOptions.columns = [{
+ * name: 'myCol',
+ * treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },
+ * treeAggregationUpdateEntity: true
+ * cellTemplate: '<div>{{row.entity.myCol + " " + row.treeNode.aggregations[0].rendered}}</div>'
+ * }];
+ * </pre>
+ */
+ col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;
+
+ /**
+ * @ngdoc object
+ * @name customTreeAggregationFinalizerFn
+ * @propertyOf ui.grid.treeBase.api:ColumnDef
+ * @description A custom function that populates aggregation.rendered, this is called when
+ * a particular aggregation has been fully calculated, and we want to render the value.
+ *
+ * With the native aggregation options we just concatenate `aggregation.label` and
+ * `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label
+ * or the value, you can do so with this function. This function will be called after the
+ * the default `finalizerFn`.
+ *
+ * @example
+ * <pre>
+ * customTreeAggregationFinalizerFn = function ( aggregation ){
+ * aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';
+ * }
+ * </pre>
+ * <br/>Defaults to undefined.
+ */
+ if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ){
+ col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;
+ }
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createRowHeader
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Create the rowHeader. If treeRowHeaderAlwaysVisible then
+ * set it to visible, otherwise set it to invisible
+ *
+ * @param {Grid} grid grid object
+ */
+ createRowHeader: function( grid ){
+ var rowHeaderColumnDef = {
+ name: uiGridTreeBaseConstants.rowHeaderColName,
+ displayName: '',
+ width: grid.options.treeRowHeaderBaseWidth,
+ minWidth: 10,
+ cellTemplate: 'ui-grid/treeBaseRowHeader',
+ headerCellTemplate: 'ui-grid/treeBaseHeaderCell',
+ enableColumnResizing: false,
+ enableColumnMenu: false,
+ exporterSuppressExport: true,
+ allowCellFocus: true
+ };
+
+ rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;
+ grid.addRowHeaderColumn( rowHeaderColumnDef );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandAllRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands all nodes in the tree
+ *
+ * @param {Grid} grid grid object
+ */
+ expandAllRows: function (grid) {
+ grid.treeBase.tree.forEach( function( node ) {
+ service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);
+ });
+ grid.treeBase.expandAll = true;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseAllRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses all nodes in the tree
+ *
+ * @param {Grid} grid grid object
+ */
+ collapseAllRows: function (grid) {
+ grid.treeBase.tree.forEach( function( node ) {
+ service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);
+ });
+ grid.treeBase.expandAll = false;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setAllNodes
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Works through a subset of grid.treeBase.rowExpandedStates, setting
+ * all child nodes (and their descendents) of the provided node to the given state.
+ *
+ * Calls itself recursively on all nodes so as to achieve this.
+ *
+ * @param {Grid} grid the grid we're operating on (so we can raise events)
+ * @param {object} treeNode a node in the tree that we want to update
+ * @param {string} targetState the state we want to set it to
+ */
+ setAllNodes: function (grid, treeNode, targetState) {
+ if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ){
+ treeNode.state = targetState;
+
+ if ( targetState === uiGridTreeBaseConstants.EXPANDED ){
+ grid.api.treeBase.raise.rowExpanded(treeNode.row);
+ } else {
+ grid.api.treeBase.raise.rowCollapsed(treeNode.row);
+ }
+ }
+
+ // set all child nodes
+ if ( treeNode.children ){
+ treeNode.children.forEach(function( childNode ){
+ service.setAllNodes(grid, childNode, targetState);
+ });
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name toggleRowTreeState
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Toggles the expand or collapse state of this grouped row, if
+ * it's a parent row
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to toggle
+ */
+ toggleRowTreeState: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED){
+ service.collapseRow(grid, row);
+ } else {
+ service.expandRow(grid, row);
+ }
+
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandRow
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands this specific row, showing only immediate children.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to expand
+ */
+ expandRow: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ){
+ row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;
+ grid.api.treeBase.raise.rowExpanded(row);
+ grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name expandRowChildren
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Expands this specific row, showing all children.
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to expand
+ */
+ expandRowChildren: function ( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);
+ grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseRow
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses this specific row
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to collapse
+ */
+ collapseRow: function( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ){
+ row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;
+ grid.treeBase.expandAll = false;
+ grid.api.treeBase.raise.rowCollapsed(row);
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name collapseRowChildren
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Collapses this specific row and all children
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to collapse
+ */
+ collapseRowChildren: function( grid, row ){
+ if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
+ return;
+ }
+
+ service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);
+ grid.treeBase.expandAll = false;
+ grid.queueGridRefresh();
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name allExpanded
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Returns true if all rows are expanded, false
+ * if they're not. Walks the tree to determine this. Used
+ * to set the expandAll state.
+ *
+ * If the node has no children, then return true (it's immaterial
+ * whether it is expanded). If the node has children, then return
+ * false if this node is collapsed, or if any child node is not all expanded
+ *
+ * @param {object} tree the grid to check
+ * @returns {boolean} whether or not the tree is all expanded
+ */
+ allExpanded: function( tree ){
+ var allExpanded = true;
+ tree.forEach( function( node ){
+ if ( !service.allExpandedInternal( node ) ){
+ allExpanded = false;
+ }
+ });
+ return allExpanded;
+ },
+
+ allExpandedInternal: function( treeNode ){
+ if ( treeNode.children && treeNode.children.length > 0 ){
+ if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
+ return false;
+ }
+ var allExpanded = true;
+ treeNode.children.forEach( function( node ){
+ if ( !service.allExpandedInternal( node ) ){
+ allExpanded = false;
+ }
+ });
+ return allExpanded;
+ } else {
+ return true;
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name treeRows
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description The rowProcessor that adds the nodes to the tree, and sets the visible
+ * state of each row based on it's parent state
+ *
+ * Assumes it is always called after the sorting processor, and the grouping processor if there is one.
+ * Performs any tree sorts itself after having built the tree
+ *
+ * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated
+ * entity, and setting the visible state based on the parent's state.
+ *
+ * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly
+ * sized.
+ *
+ * Aggregates if necessary along the way.
+ *
+ * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
+ * @returns {array} the updated rows
+ */
+ treeRows: function( renderableRows ) {
+ if (renderableRows.length === 0){
+ return renderableRows;
+ }
+
+ var grid = this;
+ var currentLevel = 0;
+ var currentState = uiGridTreeBaseConstants.EXPANDED;
+ var parents = [];
+
+ grid.treeBase.tree = service.createTree( grid, renderableRows );
+ service.updateRowHeaderWidth( grid );
+
+ service.sortTree( grid );
+ service.fixFilter( grid );
+
+ return service.renderTree( grid.treeBase.tree );
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createOrUpdateRowHeaderWidth
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Calculates the rowHeader width.
+ *
+ * If rowHeader is always present, updates the width.
+ *
+ * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there
+ * should be one, then creates or removes it as appropriate, with the created rowHeader having the
+ * right width.
+ *
+ * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`
+ *
+ * @param {Grid} grid the grid we want to set the row header on
+ */
+ updateRowHeaderWidth: function( grid ){
+ var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName);
+
+ var newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);
+ if ( rowHeader && newWidth !== rowHeader.width ){
+ rowHeader.width = newWidth;
+ grid.queueRefresh();
+ }
+
+ var newVisibility = true;
+ if ( grid.options.showTreeRowHeader === false ){
+ newVisibility = false;
+ }
+ if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ){
+ newVisibility = false;
+ }
+ if ( rowHeader.visible !== newVisibility ) {
+ rowHeader.visible = newVisibility;
+ rowHeader.colDef.visible = newVisibility;
+ grid.queueGridRefresh();
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name renderTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates an array of rows based on the tree, exporting only
+ * the visible nodes and leaves
+ *
+ * @param {array} nodeList the list of nodes - can be grid.treeBase.tree, or can be node.children when
+ * we're calling recursively
+ * @returns {array} renderable rows
+ */
+ renderTree: function( nodeList ){
+ var renderableRows = [];
+
+ nodeList.forEach( function ( node ){
+ if ( node.row.visible ){
+ renderableRows.push( node.row );
+ }
+ if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
+ renderableRows = renderableRows.concat( service.renderTree( node.children ) );
+ }
+ });
+ return renderableRows;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name createTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates a tree from the renderableRows
+ *
+ * @param {Grid} grid the grid
+ * @param {array} renderableRows the rows we want to create a tree from
+ * @returns {object} the tree we've build
+ */
+ createTree: function( grid, renderableRows ) {
+ var currentLevel = -1;
+ var parents = [];
+ var currentState;
+ grid.treeBase.tree = [];
+ grid.treeBase.numberLevels = 0;
+ var aggregations = service.getAggregations( grid );
+
+ var createNode = function( row ){
+ if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ){
+ row.treeLevel = row.entity.$$treeLevel;
+ }
+
+ if ( row.treeLevel <= currentLevel ){
+ // pop any levels that aren't parents of this level, formatting the aggregation at the same time
+ while ( row.treeLevel <= currentLevel ){
+ var lastParent = parents.pop();
+ service.finaliseAggregations( lastParent );
+ currentLevel--;
+ }
+
+ // reset our current state based on the new parent, set to expanded if this is a level 0 node
+ if ( parents.length > 0 ){
+ currentState = service.setCurrentState(parents);
+ } else {
+ currentState = uiGridTreeBaseConstants.EXPANDED;
+ }
+ }
+
+ // aggregate if this is a leaf node
+ if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible ){
+ service.aggregate( grid, row, parents );
+ }
+
+ // add this node to the tree
+ service.addOrUseNode(grid, row, parents, aggregations);
+
+ if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ){
+ parents.push(row);
+ currentLevel++;
+ currentState = service.setCurrentState(parents);
+ }
+
+ // update the tree number of levels, so we can set header width if we need to
+ if ( grid.treeBase.numberLevels < row.treeLevel + 1){
+ grid.treeBase.numberLevels = row.treeLevel + 1;
+ }
+ };
+
+ renderableRows.forEach( createNode );
+
+ // finalise remaining aggregations
+ while ( parents.length > 0 ){
+ var lastParent = parents.pop();
+ service.finaliseAggregations( lastParent );
+ }
+
+ return grid.treeBase.tree;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name addOrUseNode
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Creates a tree node for this row. If this row already has a treeNode
+ * recorded against it, preserves the state, but otherwise overwrites the data.
+ *
+ * @param {grid} grid the grid we're operating on
+ * @param {gridRow} row the row we want to set
+ * @param {array} parents an array of the parents this row should have
+ * @param {array} aggregationBase empty aggregation information
+ * @returns {undefined} updates the parents array, updates the row to have a treeNode, and updates the
+ * grid.treeBase.tree
+ */
+ addOrUseNode: function( grid, row, parents, aggregationBase ){
+ var newAggregations = [];
+ aggregationBase.forEach( function(aggregation){
+ newAggregations.push(service.buildAggregationObject(aggregation.col));
+ });
+
+ var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };
+ if ( row.treeNode ){
+ newNode.state = row.treeNode.state;
+ }
+ if ( parents.length > 0 ){
+ newNode.parentRow = parents[parents.length - 1];
+ }
+ row.treeNode = newNode;
+
+ if ( parents.length === 0 ){
+ grid.treeBase.tree.push( newNode );
+ } else {
+ parents[parents.length - 1].treeNode.children.push( newNode );
+ }
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name setCurrentState
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Looks at the parents array to determine our current state.
+ * If any node in the hierarchy is collapsed, then return collapsed, otherwise return
+ * expanded.
+ *
+ * @param {array} parents an array of the parents this row should have
+ * @returns {string} the state we should be setting to any nodes we see
+ */
+ setCurrentState: function( parents ){
+ var currentState = uiGridTreeBaseConstants.EXPANDED;
+ parents.forEach( function(parent){
+ if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
+ currentState = uiGridTreeBaseConstants.COLLAPSED;
+ }
+ });
+ return currentState;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name sortTree
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Performs a recursive sort on the tree nodes, sorting the
+ * children of each node and putting them back into the children array.
+ *
+ * Before doing this it turns back on all the sortIgnore - things that were previously
+ * ignored we process now. Since we're sorting within the nodes, presumably anything
+ * that was already sorted is how we derived the nodes, we can keep those sorts too.
+ *
+ * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed
+ * nodes
+ *
+ * @param {Grid} grid the grid to get the aggregation information from
+ * @returns {array} the aggregation information
+ */
+ sortTree: function( grid ){
+ grid.columns.forEach( function( column ) {
+ if ( column.sort && column.sort.ignoreSort ){
+ delete column.sort.ignoreSort;
+ }
+ });
+
+ grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );
+ },
+
+ sortInternal: function( grid, treeList ){
+ var rows = treeList.map( function( node ){
+ return node.row;
+ });
+
+ rows = rowSorter.sort( grid, rows, grid.columns );
+
+ var treeNodes = rows.map( function( row ){
+ return row.treeNode;
+ });
+
+ treeNodes.forEach( function( node ){
+ if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
+ node.children = service.sortInternal( grid, node.children );
+ }
+ });
+
+ return treeNodes;
+ },
+
+ /**
+ * @ngdoc function
+ * @name fixFilter
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description After filtering has run, we need to go back through the tree
+ * and make sure the parent rows are always visible if any of the child rows
+ * are visible (filtering may make a child visible, but the parent may not
+ * match the filter criteria)
+ *
+ * This has a risk of being computationally expensive, we do it by walking
+ * the tree and remembering whether there are any invisible nodes on the
+ * way down.
+ *
+ * @param {Grid} grid the grid to fix filters on
+ */
+ fixFilter: function( grid ){
+ var parentsVisible;
+
+ grid.treeBase.tree.forEach( function( node ){
+ if ( node.children && node.children.length > 0 ){
+ parentsVisible = node.row.visible;
+ service.fixFilterInternal( node.children, parentsVisible );
+ }
+ });
+ },
+
+ fixFilterInternal: function( nodes, parentsVisible) {
+ nodes.forEach( function( node ){
+ if ( node.row.visible && !parentsVisible ){
+ service.setParentsVisible( node );
+ parentsVisible = true;
+ }
+
+ if ( node.children && node.children.length > 0 ){
+ if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {
+ parentsVisible = true;
+ }
+ }
+ });
+
+ return parentsVisible;
+ },
+
+ setParentsVisible: function( node ){
+ while ( node.parentRow ){
+ node.parentRow.visible = true;
+ node = node.parentRow.treeNode;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name buildAggregationObject
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Build the object which is stored on the column for holding meta-data about the aggregation.
+ * This method should only be called with columns which have an aggregation.
+ *
+ * @param {Column} the column which this object relates to
+ * @returns {object} {col: Column object, label: string, type: string (optional)}
+ */
+ buildAggregationObject: function( column ){
+ var newAggregation = { col: column };
+
+ if ( column.treeAggregation && column.treeAggregation.type ){
+ newAggregation.type = column.treeAggregation.type;
+ }
+
+ if ( column.treeAggregation && column.treeAggregation.label ){
+ newAggregation.label = column.treeAggregation.label;
+ }
+
+ return newAggregation;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getAggregations
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Looks through the grid columns to find those with aggregations,
+ * and collates the aggregation information into an array, returns that array
+ *
+ * @param {Grid} grid the grid to get the aggregation information from
+ * @returns {array} the aggregation information
+ */
+ getAggregations: function( grid ){
+ var aggregateArray = [];
+
+ grid.columns.forEach( function(column){
+ if ( typeof(column.treeAggregationFn) !== 'undefined' ){
+ aggregateArray.push( service.buildAggregationObject(column) );
+
+ if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ){
+ // Add aggregation object for footer
+ column.treeFooterAggregation = service.buildAggregationObject(column);
+ column.aggregationType = service.treeFooterAggregationType;
+ }
+ }
+ });
+ return aggregateArray;
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name aggregate
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Accumulate the data from this row onto the aggregations for each parent
+ *
+ * Iterate over the parents, then iterate over the aggregations for each of those parents,
+ * and perform the aggregation for each individual aggregation
+ *
+ * @param {Grid} grid grid object
+ * @param {GridRow} row the row we want to set grouping visibility on
+ * @param {array} parents the parents that we would want to aggregate onto
+ */
+ aggregate: function( grid, row, parents ){
+ if ( parents.length === 0 && row.treeNode && row.treeNode.aggregations ){
+ row.treeNode.aggregations.forEach(function(aggregation){
+ // Calculate aggregations for footer even if there are no grouped rows
+ if ( typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ) {
+ var fieldValue = grid.getCellValue(row, aggregation.col);
+ var numValue = Number(fieldValue);
+ aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
+ }
+ });
+ }
+
+ parents.forEach( function( parent, index ){
+ if ( parent.treeNode.aggregations ){
+ parent.treeNode.aggregations.forEach( function( aggregation ){
+ var fieldValue = grid.getCellValue(row, aggregation.col);
+ var numValue = Number(fieldValue);
+ aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);
+
+ if ( index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ){
+ aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
+ }
+ });
+ }
+ });
+ },
+
+
+ // Aggregation routines - no doco needed as self evident
+ nativeAggregations: function() {
+ var nativeAggregations = {
+ count: {
+ label: i18nService.get().aggregation.count,
+ menuTitle: i18nService.get().grouping.aggregate_count,
+ aggregationFn: function (aggregation, fieldValue, numValue) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = 1;
+ } else {
+ aggregation.value++;
+ }
+ }
+ },
+
+ sum: {
+ label: i18nService.get().aggregation.sum,
+ menuTitle: i18nService.get().grouping.aggregate_sum,
+ aggregationFn: function( aggregation, fieldValue, numValue ) {
+ if (!isNaN(numValue)) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = numValue;
+ } else {
+ aggregation.value += numValue;
+ }
+ }
+ }
+ },
+
+ min: {
+ label: i18nService.get().aggregation.min,
+ menuTitle: i18nService.get().grouping.aggregate_min,
+ aggregationFn: function( aggregation, fieldValue, numValue ) {
+ if (typeof(aggregation.value) === 'undefined') {
+ aggregation.value = fieldValue;
+ } else {
+ if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {
+ aggregation.value = fieldValue;
+ }
+ }
+ }
+ },
+
+ max: {
+ label: i18nService.get().aggregation.max,
+ menuTitle: i18nService.get().grouping.aggregate_max,
+ aggregationFn: function( aggregation, fieldValue, numValue ){
+ if ( typeof(aggregation.value) === 'undefined' ){
+ aggregation.value = fieldValue;
+ } else {
+ if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)){
+ aggregation.value = fieldValue;
+ }
+ }
+ }
+ },
+
+ avg: {
+ label: i18nService.get().aggregation.avg,
+ menuTitle: i18nService.get().grouping.aggregate_avg,
+ aggregationFn: function( aggregation, fieldValue, numValue ){
+ if ( typeof(aggregation.count) === 'undefined' ){
+ aggregation.count = 1;
+ } else {
+ aggregation.count++;
+ }
+
+ if ( isNaN(numValue) ){
+ return;
+ }
+
+ if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ){
+ aggregation.value = numValue;
+ aggregation.sum = numValue;
+ } else {
+ aggregation.sum += numValue;
+ aggregation.value = aggregation.sum / aggregation.count;
+ }
+ }
+ }
+ };
+ return nativeAggregations;
+ },
+
+ /**
+ * @ngdoc function
+ * @name finaliseAggregation
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Helper function used to finalize aggregation nodes and footer cells
+ *
+ * @param {gridRow} row the parent we're finalising
+ * @param {aggregation} the aggregation object manipulated by the aggregationFn
+ */
+ finaliseAggregation: function(row, aggregation){
+ if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ){
+ angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);
+ }
+
+ if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ){
+ aggregation.col.treeAggregationFinalizerFn( aggregation );
+ }
+ if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ){
+ aggregation.col.customTreeAggregationFinalizerFn( aggregation );
+ }
+ if ( typeof(aggregation.rendered) === 'undefined' ){
+ aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name finaliseAggregations
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Format the data from the aggregation into the rendered text
+ * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.
+ *
+ * As part of this we call any formatting callback routines we've been provided.
+ *
+ * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is
+ * set on the column - we don't overwrite any information that's already there, we append
+ * to it so that grouping can have set the groupVal beforehand without us overwriting it.
+ *
+ * We need to copy the data from the row.entity first before we finalise the aggregation,
+ * we need that information for the finaliserFn
+ *
+ * @param {gridRow} row the parent we're finalising
+ */
+ finaliseAggregations: function( row ){
+ if ( typeof(row.treeNode.aggregations) === 'undefined' ){
+ return;
+ }
+
+ row.treeNode.aggregations.forEach( function( aggregation ) {
+ service.finaliseAggregation(row, aggregation);
+
+ if ( aggregation.col.treeAggregationUpdateEntity ){
+ var aggregationCopy = {};
+ angular.forEach( aggregation, function( value, key ){
+ if ( aggregation.hasOwnProperty(key) && key !== 'col' ){
+ aggregationCopy[key] = value;
+ }
+ });
+
+ row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;
+ }
+ });
+ },
+
+ /**
+ * @ngdoc function
+ * @name treeFooterAggregationType
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Uses the tree aggregation functions and finalizers to set the
+ * column footer aggregations.
+ *
+ * @param {rows} visible rows. not used, but accepted to match signature of GridColumn.aggregationType
+ * @param {gridColumn} the column we are finalizing
+ */
+ treeFooterAggregationType: function( rows, column ) {
+ service.finaliseAggregation(undefined, column.treeFooterAggregation);
+ if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ){
+ // The was apparently no aggregation performed (perhaps this is a grouped column
+ return '';
+ }
+ return column.treeFooterAggregation.rendered;
+ }
+ };
+
+ return service;
+
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons
+ * @element div
+ *
+ * @description Provides the expand/collapse button on rows
+ */
+ module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',
+ function ($templateCache, uiGridTreeBaseService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),
+ scope: true,
+ require: '^uiGrid',
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = uiGridCtrl.grid;
+ $scope.treeButtonClick = function(row, evt) {
+ uiGridTreeBaseService.toggleRowTreeState(self, row, evt);
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons
+ * @element div
+ *
+ * @description Provides the expand/collapse all button
+ */
+ module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',
+ function ($templateCache, uiGridTreeBaseService) {
+ return {
+ replace: true,
+ restrict: 'E',
+ template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),
+ scope: false,
+ link: function($scope, $elm, $attrs, uiGridCtrl) {
+ var self = $scope.col.grid;
+
+ $scope.headerButtonClick = function(row, evt) {
+ if ( self.treeBase.expandAll ){
+ uiGridTreeBaseService.collapseAllRows(self, evt);
+ } else {
+ uiGridTreeBaseService.expandAllRows(self, evt);
+ }
+ };
+ }
+ };
+ }]);
+
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeBase.directive:uiGridViewport
+ * @element div
+ *
+ * @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row
+ */
+ module.directive('uiGridViewport',
+ ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
+ function ($compile, uiGridConstants, gridUtil, $parse) {
+ return {
+ priority: -200, // run after default directive
+ scope: false,
+ compile: function ($elm, $attrs) {
+ var rowRepeatDiv = angular.element($elm.children().children()[0]);
+
+ var existingNgClass = rowRepeatDiv.attr("ng-class");
+ var newNgClass = '';
+ if ( existingNgClass ) {
+ newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-tree-header-row': row.treeLevel > -1}";
+ } else {
+ newNgClass = "{'ui-grid-tree-header-row': row.treeLevel > -1}";
+ }
+ rowRepeatDiv.attr("ng-class", newNgClass);
+
+ return {
+ pre: function ($scope, $elm, $attrs, controllers) {
+
+ },
+ post: function ($scope, $elm, $attrs, controllers) {
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+(function () {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @name ui.grid.treeView
+ * @description
+ *
+ * # ui.grid.treeView
+ *
+ * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
+ *
+ * This module provides a tree view of the data that it is provided, with nodes in that
+ * tree and leaves. Unlike grouping, the tree is an inherent property of the data and must
+ * be provided with your data array.
+ *
+ * Design information:
+ * -------------------
+ *
+ * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around
+ * that logic. Most of the design information has now moved to treebase.
+ * <br/>
+ * <br/>
+ *
+ * <div doc-module-components="ui.grid.treeView"></div>
+ */
+
+ var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.constant:uiGridTreeViewConstants
+ *
+ * @description constants available in treeView module, this includes
+ * all the constants declared in the treeBase module (these are manually copied
+ * as there isn't an easy way to include constants in another constants file, and
+ * we don't want to make users include treeBase)
+ *
+ */
+ module.constant('uiGridTreeViewConstants', {
+ featureName: "treeView",
+ rowHeaderColName: 'treeBaseRowHeaderCol',
+ EXPANDED: 'expanded',
+ COLLAPSED: 'collapsed',
+ aggregation: {
+ COUNT: 'count',
+ SUM: 'sum',
+ MAX: 'max',
+ MIN: 'min',
+ AVG: 'avg'
+ }
+ });
+
+ /**
+ * @ngdoc service
+ * @name ui.grid.treeView.service:uiGridTreeViewService
+ *
+ * @description Services for treeView features
+ */
+ module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',
+ function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {
+
+ var service = {
+
+ initializeGrid: function (grid, $scope) {
+ uiGridTreeBaseService.initializeGrid( grid, $scope );
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.grid:treeView
+ *
+ * @description Grid properties and functions added for treeView
+ */
+ grid.treeView = {};
+
+ grid.registerRowsProcessor(service.adjustSorting, 60);
+
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.api:PublicApi
+ *
+ * @description Public Api for treeView feature
+ */
+ var publicApi = {
+ events: {
+ treeView: {
+ }
+ },
+ methods: {
+ treeView: {
+ }
+ }
+ };
+
+ grid.api.registerEventsFromObject(publicApi.events);
+
+ grid.api.registerMethodsFromObject(publicApi.methods);
+
+ },
+
+ defaultGridOptions: function (gridOptions) {
+ //default option to true unless it was explicitly set to false
+ /**
+ * @ngdoc object
+ * @name ui.grid.treeView.api:GridOptions
+ *
+ * @description GridOptions for treeView feature, these are available to be
+ * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
+ *
+ * Many tree options are set on treeBase, make sure to look at that feature in
+ * conjunction with these options.
+ */
+
+ /**
+ * @ngdoc object
+ * @name enableTreeView
+ * @propertyOf ui.grid.treeView.api:GridOptions
+ * @description Enable row tree view for entire grid.
+ * <br/>Defaults to true
+ */
+ gridOptions.enableTreeView = gridOptions.enableTreeView !== false;
+
+ },
+
+
+ /**
+ * @ngdoc function
+ * @name adjustSorting
+ * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
+ * @description Trees cannot be sorted the same as flat lists of rows -
+ * trees are sorted recursively within each level - so the children of each
+ * node are sorted, but not the full set of rows.
+ *
+ * To achieve this, we suppress the normal sorting by setting ignoreSort on
+ * each of the sort columns. When the treeBase rowsProcessor runs it will then
+ * unignore these, and will perform a recursive sort against the tree that it builds.
+ *
+ * @param {array} renderableRows the rows that we need to pass on through
+ * @returns {array} renderableRows that we passed on through
+ */
+ adjustSorting: function( renderableRows ) {
+ var grid = this;
+
+ grid.columns.forEach( function( column ){
+ if ( column.sort ){
+ column.sort.ignoreSort = true;
+ }
+ });
+
+ return renderableRows;
+ }
+
+ };
+
+ return service;
+
+ }]);
+
+ /**
+ * @ngdoc directive
+ * @name ui.grid.treeView.directive:uiGridTreeView
+ * @element div
+ * @restrict A
+ *
+ * @description Adds treeView features to grid
+ *
+ * @example
+ <example module="app">
+ <file name="app.js">
+ var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);
+
+ app.controller('MainCtrl', ['$scope', function ($scope) {
+ $scope.data = [
+ { name: 'Bob', title: 'CEO' },
+ { name: 'Frank', title: 'Lowly Developer' }
+ ];
+
+ $scope.columnDefs = [
+ {name: 'name', enableCellEdit: true},
+ {name: 'title', enableCellEdit: true}
+ ];
+
+ $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="MainCtrl">
+ <div ui-grid="gridOptions" ui-grid-tree-view></div>
+ </div>
+ </file>
+ </example>
+ */
+ module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',
+ function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {
+ return {
+ replace: true,
+ priority: 0,
+ require: '^uiGrid',
+ scope: false,
+ compile: function () {
+ return {
+ pre: function ($scope, $elm, $attrs, uiGridCtrl) {
+ if (uiGridCtrl.grid.options.enableTreeView !== false){
+ uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);
+ }
+ },
+ post: function ($scope, $elm, $attrs, uiGridCtrl) {
+
+ }
+ };
+ }
+ };
+ }]);
+})();
+
+angular.module('ui.grid').run(['$templateCache', function($templateCache) {
+ 'use strict';
+
+ $templateCache.put('ui-grid/ui-grid-filter',
+ "<div class=\"ui-grid-filter-container\" ng-repeat=\"colFilter in col.filters\" ng-class=\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\"><div ng-if=\"colFilter.type !== 'select'\"><input type=\"text\" class=\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\" aria-label=\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\"><div role=\"button\" class=\"ui-grid-filter-button\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div><div ng-if=\"colFilter.type === 'select'\"><select class=\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || aria.defaultFilterLabel}}\" aria-label=\"{{colFilter.ariaLabel || ''}}\" ng-options=\"option.value as option.label for option in colFilter.selectOptions\"><option value=\"\"></option></select><div role=\"button\" class=\"ui-grid-filter-button-select\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term != null\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-footer',
+ "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\"><!-- tfooter --><div class=\"ui-grid-footer ui-grid-footer-viewport\"><div class=\"ui-grid-footer-canvas\"><div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-footer-cell-row\"><div ui-grid-footer-cell role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\"></div></div></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-grid-footer',
+ "<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-group-panel',
+ "<div class=\"ui-grid-group-panel\"><div ui-t=\"groupPanel.description\" class=\"description\" ng-show=\"groupings.length == 0\"></div><ul ng-show=\"groupings.length > 0\" class=\"ngGroupList\"><li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\"><span class=\"ngGroupElement\"><span class=\"ngGroupName\">{{group.displayName}} <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span></span> <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span></span></li></ul></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-header',
+ "<div role=\"rowgroup\" class=\"ui-grid-header\"><!-- theader --><div class=\"ui-grid-top-panel\"><div class=\"ui-grid-header-viewport\"><div class=\"ui-grid-header-canvas\"><div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-header-cell-row\"><div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div></div></div></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-menu-button',
+ "<div class=\"ui-grid-menu-button\"><div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-menu\" ui-grid-one-bind-aria-label=\"i18n.aria.buttonLabel\">&nbsp;</i></div><div ui-grid-menu menu-items=\"menuItems\"></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-no-header',
+ "<div class=\"ui-grid-top-panel\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid-row',
+ "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"
+ );
+
+
+ $templateCache.put('ui-grid/ui-grid',
+ "<div ui-i18n=\"en\" class=\"ui-grid\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\n" +
+ " /* Styles for the grid */\n" +
+ " }\n" +
+ "\n" +
+ " .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n" +
+ " height: {{ grid.options.rowHeight }}px;\n" +
+ " }\n" +
+ "\n" +
+ " .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n" +
+ " border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\n" +
+ " }\n" +
+ "\n" +
+ " {{ grid.verticalScrollbarStyles }}\n" +
+ " {{ grid.horizontalScrollbarStyles }}\n" +
+ "\n" +
+ " /*\n" +
+ " .ui-grid[dir=rtl] .ui-grid-viewport {\n" +
+ " padding-left: {{ grid.verticalScrollbarWidth }}px;\n" +
+ " }\n" +
+ " */\n" +
+ "\n" +
+ " {{ grid.customStyles }}</style><div class=\"ui-grid-contents-wrapper\"><div ui-grid-menu-button ng-if=\"grid.options.enableGridMenu\"></div><div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\"></div><div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\" enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div><div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\"></div><div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\"></div><div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\"></div><div ng-transclude></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridCell',
+ "<div class=\"ui-grid-cell-contents\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridColumnMenu',
+ "<div class=\"ui-grid-column-menu\"><div ui-grid-menu menu-items=\"menuItems\"><!-- <div class=\"ui-grid-column-menu\">\n" +
+ " <div class=\"inner\" ng-show=\"menuShown\">\n" +
+ " <ul>\n" +
+ " <div ng-show=\"grid.options.enableSorting\">\n" +
+ " <li ng-click=\"sortColumn($event, asc)\" ng-class=\"{ 'selected' : col.sort.direction == asc }\"><i class=\"ui-grid-icon-sort-alt-up\"></i> Sort Ascending</li>\n" +
+ " <li ng-click=\"sortColumn($event, desc)\" ng-class=\"{ 'selected' : col.sort.direction == desc }\"><i class=\"ui-grid-icon-sort-alt-down\"></i> Sort Descending</li>\n" +
+ " <li ng-show=\"col.sort.direction\" ng-click=\"unsortColumn()\"><i class=\"ui-grid-icon-cancel\"></i> Remove Sort</li>\n" +
+ " </div>\n" +
+ " </ul>\n" +
+ " </div>\n" +
+ " </div> --></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridFooterCell',
+ "<div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridHeaderCell',
+ "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\"><div role=\"button\" tabindex=\"0\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\"><span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\"><i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{col.sort.priority ? i18n.headerCell.priority + ' ' + col.sort.priority : null}}\" aria-hidden=\"true\"></i> <sub class=\"ui-grid-sort-priority-number\">{{col.sort.priority}}</sub></span></div><div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i></div><div ui-grid-filter></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridMenu',
+ "<div class=\"ui-grid-menu\" ng-if=\"shown\"><div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\"><div class=\"ui-grid-menu-inner\"><button type=\"button\" ng-focus=\"focus=true\" ng-blur=\"focus=false\" class=\"ui-grid-menu-close-button\" ng-class=\"{'ui-grid-sr-only': (!focus)}\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"i18n.close\"></i></button><ul role=\"menu\" class=\"ui-grid-menu-items\"><li ng-repeat=\"item in menuItems\" role=\"menuitem\" ui-grid-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\" action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" screen-reader-only=\"item.screenReaderOnly\"></li></ul></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridMenuItem',
+ "<button type=\"button\" class=\"ui-grid-menu-item\" ng-click=\"itemAction($event, title)\" ng-show=\"itemShown()\" ng-class=\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\" aria-pressed=\"{{active()}}\" tabindex=\"0\" ng-focus=\"focus=true\" ng-blur=\"focus=false\"><i ng-class=\"icon\" aria-hidden=\"true\">&nbsp;</i> {{ name }}</button>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridRenderContainer',
+ "<div role=\"grid\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"
+ );
+
+
+ $templateCache.put('ui-grid/uiGridViewport',
+ "<div role=\"rowgroup\" class=\"ui-grid-viewport\" ng-style=\"colContainer.getViewportStyle()\"><!-- tbody --><div class=\"ui-grid-canvas\"><div ng-repeat=\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\" class=\"ui-grid-row\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div role=\"row\" ui-grid-row=\"row\" row-render-index=\"rowRenderIndex\"></div></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/cellEditor',
+ "<div><form name=\"inputForm\"><input type=\"INPUT_TYPE\" ng-class=\"'colt' + col.uid\" ui-grid-editor ng-model=\"MODEL_COL_FIELD\"></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/dropdownEditor',
+ "<div><form name=\"inputForm\"><select ng-class=\"'colt' + col.uid\" ui-grid-edit-dropdown ng-model=\"MODEL_COL_FIELD\" ng-options=\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\"></select></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/fileChooserEditor',
+ "<div><form name=\"inputForm\"><input ng-class=\"'colt' + col.uid\" ui-grid-edit-file-chooser type=\"file\" id=\"files\" name=\"files[]\" ng-model=\"MODEL_COL_FIELD\"></form></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableRow',
+ "<div ui-grid-expandable-row ng-if=\"expandableRow.shouldRenderExpand()\" class=\"expandableRow\" style=\"float:left; margin-top: 1px; margin-bottom: 1px\" ng-style=\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: row.expandedRowHeight + 'px'}\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableRowHeader',
+ "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-class=\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\" ng-click=\"grid.api.expandable.toggleRowExpansion(row.entity)\"></i></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableScrollFiller',
+ "<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\"><i class=\"ui-grid-icon-spin5 ui-grid-animate-spin\" ng-style=\"{'margin-top': ( row.expandedRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\"></i></div>"
+ );
+
+
+ $templateCache.put('ui-grid/expandableTopRowHeader',
+ "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-class=\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\" ng-click=\"grid.api.expandable.toggleAllRows()\"></i></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/csvLink',
+ "<span class=\"ui-grid-exporter-csv-link-span\"><a href=\"data:text/csv;charset=UTF-8,CSV_CONTENT\" download=\"FILE_NAME\">LINK_LABEL</a></span>"
+ );
+
+
+ $templateCache.put('ui-grid/importerMenuItem',
+ "<li class=\"ui-grid-menu-item\"><form><input class=\"ui-grid-importer-file-chooser\" type=\"file\" id=\"files\" name=\"files[]\"></form></li>"
+ );
+
+
+ $templateCache.put('ui-grid/importerMenuItemContainer',
+ "<div ui-grid-importer-menu-item></div>"
+ );
+
+
+ $templateCache.put('ui-grid/pagination',
+ "<div role=\"contentinfo\" class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div role=\"menubar\" class=\"ui-grid-pager-control\"><button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle\"><div class=\"first-bar\"></div></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle prev-triangle\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div class=\"last-triangle next-triangle\"></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div class=\"last-triangle\"><div class=\"last-bar\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{showingLow}} <abbr ui-grid-one-bind-title=\"paginationThrough\">-</abbr> {{showingHigh}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/columnResizer',
+ "<div ui-grid-column-resizer ng-if=\"grid.options.enableColumnResizing\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/gridFooterSelectedItems',
+ "<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"search.selectedItems\" | t}} {{grid.selection.selectedCount}})</span>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionHeaderCell',
+ "<div><!-- <div class=\"ui-grid-vertical-bar\">&nbsp;</div> --><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-selection-select-all-buttons ng-if=\"grid.options.enableSelectAll\"></ui-grid-selection-select-all-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionRowHeader',
+ "<div class=\"ui-grid-disable-selection\"><div class=\"ui-grid-cell-contents\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionRowHeaderButtons',
+ "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ng-click=\"selectButtonClick(row, $event)\">&nbsp;</div>"
+ );
+
+
+ $templateCache.put('ui-grid/selectionSelectAllButtons',
+ "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-click=\"headerButtonClick($event)\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseExpandAllButtons',
+ "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-icon-minus-squared': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, 'ui-grid-icon-plus-squared': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}\" ng-click=\"headerButtonClick($event)\"></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseHeaderCell',
+ "<div><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-tree-base-expand-all-buttons></ui-grid-tree-base-expand-all-buttons></div></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseRowHeader',
+ "<div class=\"ui-grid-cell-contents\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>"
+ );
+
+
+ $templateCache.put('ui-grid/treeBaseRowHeaderButtons',
+ "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\" ng-click=\"treeButtonClick(row, $event)\"><i ng-class=\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\" ng-style=\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\"></i> &nbsp;</div>"
+ );
+
+}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg
index 3d675f63..3d675f63 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.svg
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf
index dbf56e98..dbf56e98 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.ttf
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff
index fb19c43c..fb19c43c 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.woff
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js
index f5fd30a8..f5fd30a8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/raptor/uigrid/vfs_fonts.js
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/flexslider.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/flexslider.css
new file mode 100644
index 00000000..c459ef44
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/flexslider.css
@@ -0,0 +1,275 @@
+/*
+ * jQuery FlexSlider v2.6.0
+ * http://www.woothemes.com/flexslider/
+ *
+ * Copyright 2012 WooThemes
+ * Free to use under the GPLv2 and later license.
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Contributing author: Tyler Smith (@mbmufffin)
+ *
+ */
+/* ====================================================================================================================
+ * FONT-FACE
+ * ====================================================================================================================*/
+@font-face {
+ font-family: 'flexslider-icon';
+ src: url('fonts/flexslider-icon.eot');
+ src: url('fonts/flexslider-icon.eot?#iefix') format('embedded-opentype'), url('fonts/flexslider-icon.woff') format('woff'), url('fonts/flexslider-icon.ttf') format('truetype'), url('fonts/flexslider-icon.svg#flexslider-icon') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+/* ====================================================================================================================
+ * RESETS
+ * ====================================================================================================================*/
+.flex-container a:hover,
+.flex-slider a:hover {
+ outline: none;
+}
+.slides,
+.slides > li,
+.flex-control-nav,
+.flex-direction-nav {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+.flex-pauseplay span {
+ text-transform: capitalize;
+}
+/* ====================================================================================================================
+ * BASE STYLES
+ * ====================================================================================================================*/
+.flexslider {
+ margin: 0;
+ padding: 0;
+}
+.flexslider .slides > li {
+ display: none;
+ -webkit-backface-visibility: hidden;
+}
+.flexslider .slides img {
+ width: 100%;
+ display: block;
+}
+.flexslider .slides:after {
+ content: "\0020";
+ display: block;
+ clear: both;
+ visibility: hidden;
+ line-height: 0;
+ height: 0;
+}
+html[xmlns] .flexslider .slides {
+ display: block;
+}
+* html .flexslider .slides {
+ height: 1%;
+}
+.no-js .flexslider .slides > li:first-child {
+ display: block;
+}
+/* ====================================================================================================================
+ * DEFAULT THEME
+ * ====================================================================================================================*/
+.flexslider {
+ margin: 0 0 60px;
+ background: #ffffff;
+ border: 4px solid #ffffff;
+ position: relative;
+ zoom: 1;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ -o-box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: '' 0 1px 4px rgba(0, 0, 0, 0.2);
+}
+.flexslider .slides {
+ zoom: 1;
+}
+.flexslider .slides img {
+ height: auto;
+ -moz-user-select: none;
+}
+.flex-viewport {
+ max-height: 2000px;
+ -webkit-transition: all 1s ease;
+ -moz-transition: all 1s ease;
+ -ms-transition: all 1s ease;
+ -o-transition: all 1s ease;
+ transition: all 1s ease;
+}
+.loading .flex-viewport {
+ max-height: 300px;
+}
+.carousel li {
+ margin-right: 5px;
+}
+.flex-direction-nav {
+ *height: 0;
+}
+.flex-direction-nav a {
+ text-decoration: none;
+ display: block;
+ width: 40px;
+ height: 40px;
+ margin: -20px 0 0;
+ position: absolute;
+ top: 50%;
+ z-index: 10;
+ overflow: hidden;
+ opacity: 0;
+ cursor: pointer;
+ color: rgba(0, 0, 0, 0.8);
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
+ -webkit-transition: all 0.3s ease-in-out;
+ -moz-transition: all 0.3s ease-in-out;
+ -ms-transition: all 0.3s ease-in-out;
+ -o-transition: all 0.3s ease-in-out;
+ transition: all 0.3s ease-in-out;
+}
+.flex-direction-nav a:before {
+ font-family: "flexslider-icon";
+ font-size: 40px;
+ display: inline-block;
+ content: '\f001';
+ color: rgba(0, 0, 0, 0.8);
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
+}
+.flex-direction-nav a.flex-next:before {
+ content: '\f002';
+}
+.flex-direction-nav .flex-prev {
+ left: -50px;
+}
+.flex-direction-nav .flex-next {
+ right: -50px;
+ text-align: right;
+}
+.flexslider:hover .flex-direction-nav .flex-prev {
+ opacity: 0.7;
+ left: 10px;
+}
+.flexslider:hover .flex-direction-nav .flex-prev:hover {
+ opacity: 1;
+}
+.flexslider:hover .flex-direction-nav .flex-next {
+ opacity: 0.7;
+ right: 10px;
+}
+.flexslider:hover .flex-direction-nav .flex-next:hover {
+ opacity: 1;
+}
+.flex-direction-nav .flex-disabled {
+ opacity: 0!important;
+ filter: alpha(opacity=0);
+ cursor: default;
+ z-index: -1;
+}
+.flex-pauseplay a {
+ display: block;
+ width: 20px;
+ height: 20px;
+ position: absolute;
+ bottom: 5px;
+ left: 10px;
+ opacity: 0.8;
+ z-index: 10;
+ overflow: hidden;
+ cursor: pointer;
+ color: #000;
+}
+.flex-pauseplay a:before {
+ font-family: "flexslider-icon";
+ font-size: 20px;
+ display: inline-block;
+ content: '\f004';
+}
+.flex-pauseplay a:hover {
+ opacity: 1;
+}
+.flex-pauseplay a.flex-play:before {
+ content: '\f003';
+}
+.flex-control-nav {
+ width: 100%;
+ position: absolute;
+ bottom: -40px;
+ text-align: center;
+}
+.flex-control-nav li {
+ margin: 0 6px;
+ display: inline-block;
+ zoom: 1;
+ *display: inline;
+}
+.flex-control-paging li a {
+ width: 11px;
+ height: 11px;
+ display: block;
+ background: #666;
+ background: rgba(0, 0, 0, 0.5);
+ cursor: pointer;
+ text-indent: -9999px;
+ -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -o-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3);
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ border-radius: 20px;
+}
+.flex-control-paging li a:hover {
+ background: #333;
+ background: rgba(0, 0, 0, 0.7);
+}
+.flex-control-paging li a.flex-active {
+ background: #000;
+ background: rgba(0, 0, 0, 0.9);
+ cursor: default;
+}
+.flex-control-thumbs {
+ margin: 5px 0 0;
+ position: static;
+ overflow: hidden;
+}
+.flex-control-thumbs li {
+ width: 25%;
+ float: left;
+ margin: 0;
+}
+.flex-control-thumbs img {
+ width: 100%;
+ height: auto;
+ display: block;
+ opacity: .7;
+ cursor: pointer;
+ -moz-user-select: none;
+ -webkit-transition: all 1s ease;
+ -moz-transition: all 1s ease;
+ -ms-transition: all 1s ease;
+ -o-transition: all 1s ease;
+ transition: all 1s ease;
+}
+.flex-control-thumbs img:hover {
+ opacity: 1;
+}
+.flex-control-thumbs .flex-active {
+ opacity: 1;
+ cursor: default;
+}
+/* ====================================================================================================================
+ * RESPONSIVE
+ * ====================================================================================================================*/
+@media screen and (max-width: 860px) {
+ .flex-direction-nav .flex-prev {
+ opacity: 1;
+ left: 10px;
+ }
+ .flex-direction-nav .flex-next {
+ opacity: 1;
+ right: 10px;
+ }
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot
new file mode 100644
index 00000000..97c4196f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.eot
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg
new file mode 100644
index 00000000..89fd1ab8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="14"></iconset>
+</metadata>
+<defs>
+<font id="flexslider-icon" horiz-adv-x="448" >
+<font-face units-per-em="448" ascent="384" descent="-64" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode="&#xf001;" d="M 185.50-9.25l-163.00,162.75q-9.25,9.25 -9.25,22.625t 9.25,22.625l 163.00,162.75q 9.25,9.25 22.625,9.25t 22.625-9.25l 18.75-18.75q 9.25-9.25 9.25-22.625t-9.25-22.625l-121.50-121.50l 121.50-121.25q 9.25-9.50 9.25-22.75t-9.25-22.50l-18.75-18.75q-9.25-9.25 -22.625-9.25t-22.625,9.25z" horiz-adv-x="288" />
+<glyph unicode="&#xf002;" d="M 274.75,176.00q0.00-13.00 -9.25-22.75l-163.00-162.75q-9.25-9.25 -22.50-9.25t-22.50,9.25l-19.00,18.75q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 121.50,121.50l-121.50,121.25q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 19.00,18.75q 9.00,9.50 22.50,9.50t 22.50-9.50l 163.00-162.75q 9.25-9.25 9.25-22.50z" horiz-adv-x="288" />
+<glyph unicode="&#xf003;" d="M 346.00,152.25l-332.00-184.50q-5.75-3.25 -9.875-0.75t-4.125,9.00l0.00,368.00 q0.00,6.50 4.125,9.00t 9.875-0.75l 332.00-184.50q 5.75-3.25 5.75-7.75t-5.75-7.75z" horiz-adv-x="352" />
+<glyph unicode="&#xf004;" d="M 384.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 160.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf005;" d="M 402.75,208.00q0.00-13.25 -9.25-22.50l-162.75-162.75q-9.50-9.50 -22.75-9.50q-13.50,0.00 -22.50,9.50l-162.75,162.75q-9.50,9.00 -9.50,22.50q0.00,13.25 9.50,22.75l 18.50,18.75q 9.75,9.25 22.75,9.25q 13.25,0.00 22.50-9.25l 121.50-121.50l 121.50,121.50q 9.25,9.25 22.50,9.25q 13.00,0.00 22.75-9.25l 18.75-18.75q 9.25-9.75 9.25-22.75z" horiz-adv-x="416" />
+<glyph unicode="&#x20;" horiz-adv-x="224" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
+</font></defs></svg> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf
new file mode 100644
index 00000000..05432986
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.ttf
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff
new file mode 100644
index 00000000..10c4eeb8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/fonts/flexslider-icon.woff
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/images/blank.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/images/blank.gif
new file mode 100644
index 00000000..75b945d2
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/images/blank.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/scribble.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/scribble.css
new file mode 100644
index 00000000..9986f2ac
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/scribble.css
@@ -0,0 +1,40 @@
+#scribble-pad {
+/* margin-left:auto;
+ margin-right:auto;
+ height: 475px;
+ width: 475px;*/
+ background:url(https://www.ibm.com/developerworks/mydeveloperworks/blogs/bobleah/resource/stickynote.jpg) no-repeat center center;
+ background-size: 110% 110%;
+}
+
+
+
+#scribble {
+ white-space: pre-wrap; /* css-3 */
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
+ max-width: 300px;
+ padding: 120px 100px 100px 75px;
+ color: #486891;
+ border-color: #ff0000 #0000ff;
+ border-color: transparent;
+ background-color:rgba(0, 0, 0, 0);
+ font-family: Arial,sans-serif;
+ font-size: 120%;
+ font-style: italic;
+ font-weight:bold;
+ line-height: 1.5em;
+}
+
+#scribble:focus {
+outline-width: 0;
+}
+.c-link {
+ color: #486891;
+ font-family: Arial,sans-serif;
+ font-size: 95%;
+ font-weight:bold;
+ text-decoration: none;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/slider.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/slider.css
new file mode 100644
index 00000000..f609403c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/slider.css
@@ -0,0 +1,142 @@
+div,span,p { margin:0; padding:0; border:0; outline:0; font-weight:inherit; font-style:inherit; font-size:100%; font-family:inherit; vertical-align:baseline; }
+
+
+#container {
+ width:580px;
+ padding:10px;
+ margin:0 auto;
+ position:relative;
+ z-index:0;
+}
+
+#example {
+ width:600px;
+ height:350px;
+ position:relative;
+}
+
+#ribbon {
+ position:absolute;
+ top:-3px;
+ left:-15px;
+ z-index:500;
+}
+
+#frame {
+ position:absolute;
+ z-index:0;
+ width:739px;
+ height:341px;
+ top:-3px;
+ left:-80px;
+}
+
+/*
+ Slideshow
+*/
+
+#slides {
+ position:absolute;
+ top:15px;
+ left:4px;
+ z-index:100;
+}
+
+/*
+ Slides container
+ Important:
+ Set the width of your slides container
+ Set to display none, prevents content flash
+*/
+
+.slides_container {
+ width:570px;
+ overflow:hidden;
+ position:relative;
+ display:none;
+}
+
+/*
+ Each slide
+ Important:
+ Set the width of your slides
+ If height not specified height will be set by the slide content
+ Set to display block
+*/
+
+.slides_container div.slide {
+ width:570px;
+ height:270px;
+ display:block;
+}
+
+
+/*
+ Next/prev buttons
+*/
+
+#slides .next,#slides .prev {
+ position:absolute;
+ top:107px;
+ left:-39px;
+ width:24px;
+ height:43px;
+ display:block;
+ z-index:101;
+}
+
+#slides .next {
+ left:585px;
+}
+
+/*
+ Pagination
+*/
+
+.pagination {
+ margin:26px auto 0;
+ width:100px;
+}
+
+.pagination li {
+ float:left;
+ margin:0 1px;
+ list-style:none;
+}
+
+.pagination li a {
+ display:block;
+ width:12px;
+ height:0;
+ padding-top:12px;
+ background-image:url(../images/pagination.png);
+ background-position:0 0;
+ float:left;
+ overflow:hidden;
+}
+
+.pagination li.current a {
+ background-position:0 -12px;
+}
+
+/*
+ Caption
+*/
+
+.caption {
+ z-index:500;
+ position:absolute;
+ bottom:-35px;
+ left:0;
+ height:30px;
+ padding:5px 20px 0 20px;
+ background:#000;
+ background:rgba(0,0,0,.5);
+ width:540px;
+ font-size:1.3em;
+ line-height:1.33;
+ color:#fff;
+ border-top:1px solid #000;
+ text-shadow:none;
+}
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/spacegallery.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/spacegallery.css
new file mode 100644
index 00000000..ce4fd57c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/spacegallery.css
@@ -0,0 +1,18 @@
+.spacegallery {
+ position: relative;
+ overflow: hidden;
+}
+.spacegallery img {
+ position: absolute;
+ left: 50%;
+}
+.spacegallery a {
+ position: absolute;
+ z-index: 1000;
+ display: block;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: url(images/blank.gif);
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/welcome.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/welcome.css
new file mode 100644
index 00000000..4e52d662
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/css/welcome.css
@@ -0,0 +1,173 @@
+/* Area Chart */
+
+#areaChart {
+ overflow: hidden;}
+
+#lineChart {
+ overflow: hidden;
+}
+
+#areaChart svg {
+ height: 200px;
+ width: 380px;
+ min-width: 100px;
+ min-height: 100px;
+}
+
+#lineChart svg {
+ height: 200px;
+ width: 380px;
+ min-width: 100px;
+ min-height: 100px;
+}
+
+#areaChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
+ background-color: rgb(255, 255, 255);
+}
+
+#lineChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
+ background-color: rgb(255, 255, 255);
+}
+
+#areaChart .nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height: 370px;
+ text-align: center;
+ vertical-align: middle;
+}
+
+#lineChart .nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height: 370px;
+ text-align: center;
+ vertical-align: middle;
+}
+
+#areaChart .nodatainner {
+ padding: 10px;
+}
+
+#lineChart .nodatainner {
+ padding: 10px;
+}
+
+/* Area Chart END */
+
+.button--small, [class*=bg-] .button--small {
+ font-size: 14px;
+ };
+
+/* Gridster (EBIZ) */
+
+.gridster-item-container .gridster-item-body{
+bottom:0px;
+}
+.gridster-item-container{
+min-height:50px;
+}
+.att-accordion {
+ border-width: 0px;
+}
+
+/* End Gridster */
+
+#myGallery {
+ width: 100%;
+ height: 400px;
+}
+
+#myGallery img {
+ border: 2px solid #52697E;
+}
+
+a.loading {
+ background: #fff url(../images/ajax_small.gif) no-repeat center;
+}
+
+.center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+
+#selectedTrafficDay ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#selectedTrafficDay li {
+ float: left;
+ border: 1px solid #000;
+ border-bottom-width: 0;
+ margin: 3px 3px 3px 3px;
+ padding: 5px 5px 5px 5px;
+ background-color: #F2F2F2;
+ color: #696969;
+}
+
+#SelectedTrafficeDayView {
+ padding: 0 1em;
+}
+
+#selectedTrafficDay .active1 {
+ background-color: #FFF;
+ color: #000;
+}
+
+#BusyHourTraffic ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#BusyHourTraffic li {
+ float: left;
+ border: 1px solid #000;
+ border-bottom-width: 0;
+ margin: 3px 3px 3px 3px;
+ padding: 5px 5px 5px 5px;
+ background-color: #F2F2F2;
+ color: #696969;
+}
+
+#BusyHourTrafficView {
+ padding: 0 1em;
+}
+
+#BusyHourTraffic .active2 {
+ background-color: #FFF;
+ color: #000;
+}
+
+#slider {
+ width: 600px;
+ margin: 0 auto;
+ clear: left;
+}
+
+@media only screen and (device-width: 768px) {
+ #slider {
+ width: 400px;
+ }
+}
+
+#container {
+
+}
+
+#title {
+ float:left;
+ width:100%;
+ height:30px;
+ margin:;
+ color:#222222;
+ text-shadow: 1px 1px 2px #A0A0A0;
+}
+.content{
+ margin-right:-230px;
+ top:50px;
+
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/area_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/area_chart.html
new file mode 100644
index 00000000..30ef2011
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/area_chart.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 175px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"line", "key": "AP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.13}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.36}, { "x":1388552400000 , "y":10.0}, { "x":1391230800000 , "y":3.15}, { "x":1391230800000 , "y":2.88}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":4.0}, { "x":1393650000000 , "y":8.0}, { "x":1393650000000 , "y":3.93}, { "x":1393650000000 , "y":4.27}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.25}, { "x":1396324800000 , "y":5.35}, { "x":1396324800000 , "y":5.92}, { "x":1396324800000 , "y":12.0}, { "x":1398916800000 , "y":5.55}, { "x":1398916800000 , "y":4.89}, { "x":1398916800000 , "y":5.01}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.27}, { "x":1401595200000 , "y":9.17}, { "x":1401595200000 , "y":9.31}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.37}, { "x":1404187200000 , "y":8.11}, { "x":1404187200000 , "y":8.84}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.79}, { "x":1406865600000 , "y":12.22}, { "x":1406865600000 , "y":12.6}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":15.27}, { "x":1409544000000 , "y":19.09}, { "x":1409544000000 , "y":16.09}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":18.4}, { "x":1412136000000 , "y":22.05}, { "x":1412136000000 , "y":21.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":19.13}, { "x":1414814400000 , "y":19.61}, { "x":1414814400000 , "y":17.61}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":19.0}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.67}, { "x":1420088400000 , "y":15.19}, { "x":1420088400000 , "y":15.02}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":16.95}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":12.9}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"line", "key": "ROUTER_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":3.0}, { "x":1388552400000 , "y":4.0}, { "x":1388552400000 , "y":4.89}, { "x":1388552400000 , "y":7.0}, { "x":1391230800000 , "y":4.57}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":7.0}, { "x":1393650000000 , "y":7.0}, { "x":1393650000000 , "y":4.18}, { "x":1393650000000 , "y":5.0}, { "x":1393650000000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.06}, { "x":1396324800000 , "y":6.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.09}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.0}, { "x":1404187200000 , "y":6.36}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1406865600000 , "y":7.0}, { "x":1406865600000 , "y":7.02}, { "x":1406865600000 , "y":7.24}, { "x":1406865600000 , "y":7.0}, { "x":1409544000000 , "y":8.23}, { "x":1409544000000 , "y":8.11}, { "x":1409544000000 , "y":8.12}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9.0}, { "x":1412136000000 , "y":8.93}, { "x":1412136000000 , "y":8.57}, { "x":1412136000000 , "y":9.0}, { "x":1414814400000 , "y":5.97}, { "x":1414814400000 , "y":6.0}, { "x":1414814400000 , "y":9.0}, { "x":1414814400000 , "y":9.0}, { "x":1417410000000 , "y":9.0}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":2.01}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2.67}, { "x":1422766800000 , "y":2.0}, { "x":1425186000000 , "y":2.8}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"line", "key": "SCTP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":7.0}, { "x":1388552400000 , "y":10.0}, { "x":1388552400000 , "y":8.27}, { "x":1388552400000 , "y":8.0}, { "x":1391230800000 , "y":10.02}, { "x":1391230800000 , "y":8.04}, { "x":1391230800000 , "y":9.0}, { "x":1391230800000 , "y":10.0}, { "x":1393650000000 , "y":12.0}, { "x":1393650000000 , "y":10.04}, { "x":1393650000000 , "y":11.16}, { "x":1393650000000 , "y":10.0}, { "x":1396324800000 , "y":10.7}, { "x":1396324800000 , "y":13.31}, { "x":1396324800000 , "y":12.73}, { "x":1396324800000 , "y":9.0}, { "x":1398916800000 , "y":12.41}, { "x":1398916800000 , "y":11.95}, { "x":1398916800000 , "y":12.82}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.28}, { "x":1401595200000 , "y":14.01}, { "x":1401595200000 , "y":14.63}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.06}, { "x":1404187200000 , "y":13.96}, { "x":1404187200000 , "y":14.66}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":16.6}, { "x":1406865600000 , "y":16.95}, { "x":1406865600000 , "y":17.11}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":19.86}, { "x":1409544000000 , "y":22.97}, { "x":1409544000000 , "y":21.56}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":22.66}, { "x":1412136000000 , "y":26.79}, { "x":1412136000000 , "y":26.54}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":21.0}, { "x":1414814400000 , "y":20.35}, { "x":1414814400000 , "y":21.93}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":24.0}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.63}, { "x":1420088400000 , "y":25.14}, { "x":1420088400000 , "y":21.85}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":26.3}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":23.3833333333333}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"line", "key": "DP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.0}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.17}, { "x":1388552400000 , "y":2.0}, { "x":1391230800000 , "y":3.01}, { "x":1391230800000 , "y":2.56}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":9.0}, { "x":1393650000000 , "y":10.0}, { "x":1393650000000 , "y":3.64}, { "x":1393650000000 , "y":4.06}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.04}, { "x":1396324800000 , "y":5.11}, { "x":1396324800000 , "y":5.9}, { "x":1396324800000 , "y":8.0}, { "x":1398916800000 , "y":5.08}, { "x":1398916800000 , "y":4.65}, { "x":1398916800000 , "y":4.74}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":6.13}, { "x":1401595200000 , "y":8.98}, { "x":1401595200000 , "y":9.22}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.12}, { "x":1404187200000 , "y":7.89}, { "x":1404187200000 , "y":8.41}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":11.06}, { "x":1406865600000 , "y":11.84}, { "x":1406865600000 , "y":11.92}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":14.58}, { "x":1409544000000 , "y":18.39}, { "x":1409544000000 , "y":15.5}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.01}, { "x":1412136000000 , "y":21.3}, { "x":1412136000000 , "y":21.11}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":18.59}, { "x":1414814400000 , "y":18.81}, { "x":1414814400000 , "y":17.13}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":18.0}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.16}, { "x":1420088400000 , "y":12.13}, { "x":1420088400000 , "y":11.76}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.47}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.2333333333333}, { "x":1425186000000 , "y":12.4} ] }
+];
+
+</script>
+<script src="js/area_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/bar_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/bar_chart.html
new file mode 100644
index 00000000..0be16ec1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/bar_chart.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 420px;
+ width: 700px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/tooltip.js"></script>
+<script src="../../d3/js/utils.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script src="../../d3/js/models/multiChart.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"bar", "key": "AP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":10}, { "x":1391230800000 , "y":4}, { "x":1393650000000 , "y":4}, { "x":1396324800000 , "y":12}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"bar", "key": "ROUTER_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":7}, { "x":1391230800000 , "y":7}, { "x":1393650000000 , "y":5}, { "x":1396324800000 , "y":6}, { "x":1398916800000 , "y":5}, { "x":1401595200000 , "y":6}, { "x":1404187200000 , "y":7}, { "x":1406865600000 , "y":7}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9}, { "x":1414814400000 , "y":9}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"bar", "key": "SCTP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":8}, { "x":1391230800000 , "y":10}, { "x":1393650000000 , "y":10}, { "x":1396324800000 , "y":9}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"bar", "key": "DP_CPU", "yAxis": "1", "values": [{ "x":1388552400000 , "y":2}, { "x":1391230800000 , "y":9}, { "x":1393650000000 , "y":4}, { "x":1396324800000 , "y":8}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.4} ] }
+];
+var chart;
+nv.addGraph(function() {
+ chart = nv.models.multiBarChart()
+ .margin({top: 30, right: 60, bottom: 50, left: 100})
+ .showLegend(true)
+ .reduceXTicks(false)
+ .forceY([0, 34.0])
+ .showControls(true)
+ .stacked(false)
+ .logScale(false)
+ .legendPos('top')
+ .color(d3.scale.category10().range());
+ chart.xAxis
+ .tickValues([1388552400000,1391230800000,1393650000000,1396324800000,1398916800000,1401595200000,1404187200000,1406865600000,1409544000000,1412136000000,1414814400000,1417410000000,1420088400000,1422766800000])
+ .staggerLabels(false)
+ .showMaxMin(false)
+ .rotateLabels(90)
+ .axisLabel('Timestamp')
+ .tickFormat(function(d) {
+ return d3.time.format('%b %y')(new Date(d)) });
+ chart.yAxis
+ .logScale(false)
+ .axisLabel('')
+ .tickFormat(d3.format(',.1f'));
+ d3.select('#chart461 svg')
+ .datum(historicalBarChart)
+ .transition().duration(1000)
+ .call(chart);
+nv.utils.windowResize(chart.update);
+return chart;
+});
+function redraw() {
+ d3.select('#chart461 svg')
+ .datum(historicalBarChart)
+ .transition().duration(500)
+ .call(chart);
+}
+
+ setInterval(function () {
+ redraw();
+ }, 1500)
+if(historicalBarChart.length <= 0 ) {
+ document.getElementById("chart461").innerHTML = "<div id='noData'><b>No Data Available</b></div>";
+ document.getElementById("chart461").className="nodatadiv";
+ document.getElementById("nodata").className="nodatainner";
+}
+</script> </body></html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html
new file mode 100644
index 00000000..94596e73
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/d3_gauges_demo.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>d3.js gauges</title>
+
+ <style>
+
+ body
+ {
+ font: 10px arial;
+ }
+
+ </style>
+
+ <script src="../../d3/js/d3.v3.min.js" charset="utf-8"></script>
+
+
+ <script>
+
+ var dataURL = "data/speedometer2.csv";
+ var gauges = [];
+ var recordLength = 0;
+ var dataset ;
+
+ </script>
+ <script type="text/javascript" src="js/gauges.min.js"></script>
+
+ </head>
+
+ <body onload="initialize()">
+ <span id="Bedminster"></span>
+ <span id="Piscataway"></span>
+ <br/>
+ <span id="Middletown"></span>
+ <span id="Paramus"></span>
+ </body>
+
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv
new file mode 100644
index 00000000..406143ea
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer2.csv
@@ -0,0 +1,16 @@
+"YEARMONTH","Bedminster","Piscataway","Middletown","Paramus"
+"201401",8.27,4.89,2.36,2.17
+"201402",10.02,4.57,3.15,3.01
+"201403",11.16,5.00,4.27,4.06
+"201404",13.31,5.00,5.35,5.11
+"201405",12.82,5.00,5.01,4.74
+"201406",14.01,6.09,9.17,8.98
+"201407",14.66,7.00,8.84,8.41
+"201408",16.95,7.02,12.22,11.84
+"201409",21.56,8.12,16.09,15.50
+"201410",25.35,9.00,19.04,18.37
+"201411",21.93,9.00,17.61,17.13
+"201412",24.00,9.00,19.00,18.00
+"201501",25.14,2.01,15.19,12.13
+"201502",26.30,2.67,16.95,13.47
+"201503",26.5833333333333,45.63333333333333,16.1166666666667,12.40
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv
new file mode 100644
index 00000000..046383e4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/speedometer3.csv
@@ -0,0 +1,2 @@
+"YEARMONTH","Bedminster","Piscataway","Middletown","Paramus"
+"201401",8.27,4.89,2.36,2.17 \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/worddata.csv b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/worddata.csv
new file mode 100644
index 00000000..762cb423
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/data/worddata.csv
@@ -0,0 +1 @@
+text,frequency service,98 portal,70 management,70 virtual,56 design,56 VNF,56 studio,42 operations,42 inventory,42 POLO,42 D2.0,42 ASDC,42 router,28 restart,28 process,28 platform,28 manage,28 loop,28 licensing,28 license,28 integrated,28 flow-through,28 enable,28 data,28 controller,28 control,28 configure,28 component,28 common,28 asset,28 application,28 ECOMP,28 workflow,14 waterfall,14 visual,14 view,14 vCTS,14 utilization,14 user,14 usage,14 troubleshoot,14 transformation,14 track,14 topolgies,14 topics,14 time,14 tickets,14 thresholds,14 templates,14 structures,14 standards-based,14 software,14 reuse,14 repository,14 reports,14 release,14 recipes,14 real-time,14 provisioning,14 properties,14 project-based,14 processes,14 physical,14 oversight,14 openl-loop,14 network,14 monitor,14 modeling,14 model-driven,14 model,14 message,14 maximize,14 manually,14 machine,14 layer,14 interact,14 instances,14 initiate,14 increase,14 imported,14 impacts,14 host,14 function,14 feeds,14 features,14 faults,14 extended,14 engines,14 engine,14 dynamic,14 document-driven,14 determine,14 dashboard,14 current,14 creation,14 created,14 create,14 configuration,14 composer,14 components,14 collective,14 certification,14 bus,14 basis,14 available,14 automation,14 automated,14 associated,14 assignment,14 appropriate,14 against,14 aervice,14 adminstrators,14 activation,14 action,14 VMs,14 VM,14 VLAN,14 SDN,14 SDK,14 SBG,14 SAM,14 RUBY,14 Policy,14 PODS,14 Ops,14 GFP,14 F5FW,14 DMaaP,14 DCAE,14 DBC,14 CPADS,14 AT&T,14 APP-C,14 AOTS-TM,14 ALTS,14 A&AI,14
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/donut_d3.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/donut_d3.html
new file mode 100644
index 00000000..afcac359
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/donut_d3.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+
+body {
+ font: 10px sans-serif;
+}
+
+svg {
+ padding: 10px 0 0 10px;
+}
+
+.arc {
+ stroke: #fff;
+}
+
+ .slice text {
+ font-size: 16pt;
+ font-family: Arial;
+ }
+</style>
+<body>
+<script src="../../d3/js/d3.js"></script>
+
+<script>
+
+var radius = 74,
+ padding = 10;
+
+var width = 200,
+ height = 200;
+
+var outerRadius = height / 2 - 20,
+ innerRadius = outerRadius / 3,
+ cornerRadius = 10;
+//var color = d3.scale.ordinal()
+ // .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
+ var color = d3.scale.category10();
+ var dataURL = "data/speedometer3.csv";
+
+
+</script>
+<script src="js/donut.min.js"></script> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js
new file mode 100644
index 00000000..9b3decb9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/area_chart.min.js
@@ -0,0 +1 @@
+function redrawAreaChart(){d3.select("#areaChart svg").datum(historicalBarChart).call(area_chart)}var area_chart;nv.addGraph(function(){return area_chart=nv.models.stackedAreaChart().showControls(!1).margin({top:30,right:60,bottom:50,left:100}).showLegend(!1).yAxisTooltipFormat(d3.format(",.1f")).x(function(a){return a.x}).y(function(a){return a.y}).color(d3.scale.category10().range()),area_chart.xAxis.axisLabel("").staggerLabels(!1).showMaxMin(!1).rotateLabels(90).tickFormat(function(a){return d3.time.format("%b %y")(new Date(a))}),area_chart.yAxis.axisLabel("").tickFormat(d3.format(",.1f")),d3.select("#areaChart svg").datum(historicalBarChart).call(area_chart),nv.utils.windowResize(area_chart.update),area_chart}),redrawAreaChart(),historicalBarChart.length<=0&&(document.getElementById("areaChart").innerHTML="<div id='noData'><b>No Data Available</b></div>",document.getElementById("areaChart").className="nodatadiv",document.getElementById("nodata").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/donut.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/donut.min.js
new file mode 100644
index 00000000..60c4fd4b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/donut.min.js
@@ -0,0 +1 @@
+function angle(t){var e=90*(t.startAngle+t.endAngle)/Math.PI-90;return e>90?e-180:e}function arcTween(t,e){return function(){d3.select(this).transition().delay(e).attrTween("d",function(e){var r=d3.interpolate(e.outerRadius,t);return function(t){return e.outerRadius=r(t),arc(e)}})}}var arc=d3.svg.arc().padRadius(outerRadius).innerRadius(innerRadius),pie=d3.layout.pie().sort(null).padAngle(.02).value(function(t){return t.performance});d3.csv(dataURL,function(t,e){color.domain(d3.keys(e[0]).filter(function(t){return"YEARMONTH"!==t})),e.forEach(function(t){t.performance=color.domain().map(function(e){return{name:e,performance:+t[e]}})});var r=d3.select("body").append("svg").attr("class","legend").attr("width",radius).attr("height",2*radius).selectAll("g").data(color.domain().slice().reverse()).enter().append("g").attr("transform",function(t,e){return"translate(0,"+20*e+")"});r.append("rect").attr("width",18).attr("height",18).style("fill",color),r.append("text").attr("x",24).attr("y",9).attr("dy",".35em").text(function(t){return t});var a=d3.select("body").append("svg").attr("width",width).attr("height",height).data(e).append("g").attr("transform","translate("+radius+","+height/2+")"),n=a.selectAll("g.slice").data(function(t){return pie(t.performance)}).enter().append("g").attr("class","slice");n.append("path").each(function(t){t.outerRadius=outerRadius-10}).attr("class","arc").attr("d",arc).style("fill",function(t){return color(t.data.name)}).on("mouseover",arcTween(outerRadius,0)).on("mouseout",arcTween(outerRadius-10,150)),n.append("text").attr("dy",".35em").attr("transform",function(t){return t.outerRadius=outerRadius,t.innerRadius=outerRadius/2,"translate("+arc.centroid(t)+")rotate("+angle(t)+")"}).attr("text-anchor","middle").style("fill","white").style("font","bold 12px Arial").text(function(t){return t.value}),a.append("text").attr("dy",".35em").style("text-anchor","middle").text(function(t){return t.YEARMONTH})}); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/gauges.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/gauges.min.js
new file mode 100644
index 00000000..c0fd7484
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/gauges.min.js
@@ -0,0 +1 @@
+function Gauge(t,i){this.placeholderName=t;var n=this;this.configure=function(t){this.config=t,this.config.size=.9*this.config.size,this.config.raduis=.97*this.config.size/2,this.config.cx=this.config.size/2,this.config.cy=this.config.size/2,this.config.min=void 0!=t.min?t.min:0,this.config.max=void 0!=t.max?t.max:100,this.config.range=this.config.max-this.config.min,this.config.majorTicks=t.majorTicks||5,this.config.minorTicks=t.minorTicks||2,this.config.greenColor=t.greenColor||"#109618",this.config.yellowColor=t.yellowColor||"#FF9900",this.config.redColor=t.redColor||"#DC3912",this.config.transitionDuration=t.transitionDuration||500},this.render=function(){this.body=d3.select("#"+this.placeholderName).append("svg:svg").attr("class","gauge").attr("width",this.config.size).attr("height",this.config.size),this.body.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",this.config.raduis).style("fill","#ccc").style("stroke","#000").style("stroke-width","0.5px"),this.body.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",.9*this.config.raduis).style("fill","#fff").style("stroke","#e0e0e0").style("stroke-width","2px");for(var t in this.config.greenZones)this.drawBand(this.config.greenZones[t].from,this.config.greenZones[t].to,n.config.greenColor);for(var t in this.config.yellowZones)this.drawBand(this.config.yellowZones[t].from,this.config.yellowZones[t].to,n.config.yellowColor);for(var t in this.config.redZones)this.drawBand(this.config.redZones[t].from,this.config.redZones[t].to,n.config.redColor);if(void 0!=this.config.label){var i=Math.round(this.config.size/12);this.body.append("svg:text").attr("x",this.config.cx).attr("y",this.config.cy/2+i/2).attr("dy",i/2).attr("text-anchor","middle").text(this.config.label).style("font-size",i+"px").style("fill","#333").style("stroke-width","0px")}for(var i=Math.round(this.config.size/16),e=this.config.range/(this.config.majorTicks-1),o=this.config.min;o<=this.config.max;o+=e){for(var a=e/this.config.minorTicks,r=o+a;r<Math.min(o+e,this.config.max);r+=a){var s=this.valueToPoint(r,.75),c=this.valueToPoint(r,.85);this.body.append("svg:line").attr("x1",s.x).attr("y1",s.y).attr("x2",c.x).attr("y2",c.y).style("stroke","#666").style("stroke-width","1px")}var s=this.valueToPoint(o,.7),c=this.valueToPoint(o,.85);if(this.body.append("svg:line").attr("x1",s.x).attr("y1",s.y).attr("x2",c.x).attr("y2",c.y).style("stroke","#333").style("stroke-width","2px"),o==this.config.min||o==this.config.max){var g=this.valueToPoint(o,.63);this.body.append("svg:text").attr("x",g.x).attr("y",g.y).attr("dy",i/3).attr("text-anchor",o==this.config.min?"start":"end").text(o).style("font-size",i+"px").style("fill","#333").style("stroke-width","0px")}}var f=this.body.append("svg:g").attr("class","pointerContainer"),h=(this.config.min+this.config.max)/2,l=this.buildPointerPath(h),d=d3.svg.line().x(function(t){return t.x}).y(function(t){return t.y}).interpolate("basis");f.selectAll("path").data([l]).enter().append("svg:path").attr("d",d).style("fill","#dc3912").style("stroke","#c63310").style("fill-opacity",.7),f.append("svg:circle").attr("cx",this.config.cx).attr("cy",this.config.cy).attr("r",.12*this.config.raduis).style("fill","#4684EE").style("stroke","#666").style("opacity",1);var i=Math.round(this.config.size/10);f.selectAll("text").data([h]).enter().append("svg:text").attr("x",this.config.cx).attr("y",this.config.size-this.config.cy/4-i).attr("dy",i/2).attr("text-anchor","middle").style("font-size",i+"px").style("fill","#000").style("stroke-width","0px"),this.redraw(this.config.min,0)},this.buildPointerPath=function(t){function i(t,i){var e=n.valueToPoint(t,i);return e.x-=n.config.cx,e.y-=n.config.cy,e}var e=this.config.range/13,o=i(t,.85),a=i(t-e,.12),r=i(t+e,.12),s=t-this.config.range*(1/.75)/2,c=i(s,.28),g=i(s-e,.12),f=i(s+e,.12);return[o,a,f,c,g,r,o]},this.drawBand=function(t,i,e){0>=i-t||this.body.append("svg:path").style("fill",e).attr("d",d3.svg.arc().startAngle(this.valueToRadians(t)).endAngle(this.valueToRadians(i)).innerRadius(.65*this.config.raduis).outerRadius(.85*this.config.raduis)).attr("transform",function(){return"translate("+n.config.cx+", "+n.config.cy+") rotate(270)"})},this.redraw=function(t,i,e){var o=this.body.select(".pointerContainer"),a=o.selectAll("text");y=a.attr("y"),dy=parseFloat(a.attr("dy")),a.selectAll("tspan").remove(),a.append("tspan").attr("x",45).attr("dy",0).text(Math.round(t)),a.append("tspan").attr("x",45).attr("dy",10).text(i),o.selectAll("text").style("fill",function(){var i=n.config.max-n.config.min;return Math.round(t)>.9*i?"#DC3912":Math.round(t)>.5*i&&Math.round(t)<.9*i?"#FF9900":"#000000"});var r=o.selectAll("path");r.transition().duration(void 0!=e?e:this.config.transitionDuration).attrTween("transform",function(){var i=t;t>n.config.max?i=n.config.max+.02*n.config.range:t<n.config.min&&(i=n.config.min-.02*n.config.range);var e=n.valueToDegrees(i)-90,o=n._currentRotation||e;return n._currentRotation=e,function(t){var i=o+(e-o)*t;return"translate("+n.config.cx+", "+n.config.cy+") rotate("+i+")"}})},this.valueToDegrees=function(t){return t/this.config.range*270-(this.config.min/this.config.range*270+45)},this.valueToRadians=function(t){return this.valueToDegrees(t)*Math.PI/180},this.valueToPoint=function(t,i){return{x:this.config.cx-this.config.raduis*i*Math.cos(this.valueToRadians(t)),y:this.config.cy-this.config.raduis*i*Math.sin(this.valueToRadians(t))}},this.configure(i)}function createGauge(t,i,n,e){var o={size:100,label:i,min:void 0!=n?n:0,max:void 0!=e?e:100,minorTicks:5},a=o.max-o.min;o.yellowZones=[{from:o.min+.5*a,to:o.min+.9*a}],o.redZones=[{from:o.min+.9*a,to:o.max}],gauges[t]=new Gauge(t,o),gauges[t].render()}function createGauges(){createGauge("Bedminster","Bedminster",0,50),createGauge("Piscataway","Piscataway",0,50),createGauge("Middletown","Middletown",0,50),createGauge("Paramus","Paramus",0,50)}function updateGauges(t){for(var i in gauges){var n=getValue(i,t),e=getDate1(i,t);n&&gauges[i].redraw(n,e,100)}}function getValue(gauge_id,index){var d=dataset[index];return eval("d."+gauge_id)}function getDate1(t,i){var n=dataset[i];return n.YEARMONTH}function getROUTER_CPU_Value(t){d3.csv(dataURL,function(i){i.forEach(function(i,n){return n==t?i.ROUTER_CPU:void 0})})}function getAP_CPU_Value(t){d3.csv(dataURL,function(i){i.forEach(function(i,n){return n==t?i.AP_CPU:void 0})})}function updateData(){for(var t=0;t<recordLength;t++);}function initialize(){createGauges(),d3.csv(dataURL,function(t){dataset=t,recordLength=t.length,dataset.some(function(t,i){return 1==i?(updateGauges(i),1==i):void 0});var i=1e3,n=2,e=function(){return function(){return updateGauges(n++),n<recordLength?(d3.timer(e(),i),!0):(n=0,d3.timer(e(),i),!0)}};d3.timer(e(),i)})} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js
new file mode 100644
index 00000000..e501260b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/line_chart.min.js
@@ -0,0 +1 @@
+function redrawLineChart(){d3.select("#lineChart svg").datum(historicalBarChart).call(line_chart)}var line_chart;nv.addGraph(function(){return line_chart=nv.models.multiChart().dualaxis(!1).legendPos("top").margin({top:30,right:60,bottom:50,left:100}).showLegend(!1).color(d3.scale.category10().range()),line_chart.lines1.forceY([0,34]),line_chart.lines2.forceY([0,1]),line_chart.xAxis.axisLabel("").staggerLabels(!1).showMaxMin(!1).rotateLabels(90).tickFormat(function(a){return d3.time.format("%b %y")(new Date(a))}),line_chart.yAxis1.axisLabel("").tickFormat(d3.format(",.1f")),d3.select("#lineChart svg").datum(historicalBarChart).call(line_chart),nv.utils.windowResize(line_chart.update),line_chart}),redrawLineChart(),historicalBarChart.length<=0&&(document.getElementById("lineChart").innerHTML="<div id='noData2'><b>No Data Available</b></div>",document.getElementById("lineChart").className="nodatadiv",document.getElementById("nodata2").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js
new file mode 100644
index 00000000..f78eec70
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/pie_chart.min.js
@@ -0,0 +1 @@
+function redraw(){d3.select("#chart423 svg").datum(historicalBarChart).transition().duration(500).call(chart)}var chart;nv.addGraph(function(){return chart=nv.models.pieChart().margin({top:30,right:60,bottom:50,left:100}).x(function(t){return t.key}).y(function(t){return t.y}),chart.showLegend(!1),d3.select("#chart423 svg").datum(historicalBarChart).transition().duration(1200).call(chart),nv.utils.windowResize(chart.update),chart}),setInterval(function(){redraw()},1500),historicalBarChart.length<=0&&(document.getElementById("chart423").innerHTML="<div id='noData'><b>No Data Available</b></div>",document.getElementById("chart423").className="nodatadiv",document.getElementById("nodata").className="nodatainner"); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/worddata.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/worddata.min.js
new file mode 100644
index 00000000..6b827460
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/js/worddata.min.js
@@ -0,0 +1 @@
+function dataViz(t){function e(t){var e=d3.select("svg").append("g").attr("id","wordCloudG").attr("transform","translate(210,175)");e.selectAll("text").data(t).enter().append("text").style("font-size",function(t){return 1*t.size+"px"}).style("fill",function(t){return keywords.indexOf(t.text)>-1?"red":"black"}).style("opacity",.75).attr("text-anchor","middle").attr("transform",function(t){return"translate("+[t.x,t.y]+")rotate("+t.rotate+")"}).text(function(t){return t.text})}d3.layout.cloud().size([420,350]).words(t).rotate(function(t){return t.text.length>5?0:90}).fontSize(function(t){return wordScale(t.frequency)}).on("end",e).start()}d3.csv(dataURL,function(t){dataViz(t)}),wordScale=d3.scale.linear().domain([0,100]).range([0,70]).clamp(!0); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/line_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/line_chart.html
new file mode 100644
index 00000000..d4ba57a4
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/line_chart.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ svg {
+ display: block;
+ }
+ #chart461 svg {
+ height: 175px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); }
+.nodatadiv {
+ display: table-cell;
+ width: 700px;
+ height:370px;
+ text-align:center;
+ vertical-align: middle;
+}
+.nodatainner {
+ padding: 10px;
+}
+ </style>
+<body>
+<div align="center"><H3></H3></div><div id="chart461"> <svg></svg> </div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/axis.min.js"></script>
+<script>
+historicalBarChart = [
+ { "type":"line", "key": "AP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.13}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.36}, { "x":1388552400000 , "y":10.0}, { "x":1391230800000 , "y":3.15}, { "x":1391230800000 , "y":2.88}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":4.0}, { "x":1393650000000 , "y":8.0}, { "x":1393650000000 , "y":3.93}, { "x":1393650000000 , "y":4.27}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.25}, { "x":1396324800000 , "y":5.35}, { "x":1396324800000 , "y":5.92}, { "x":1396324800000 , "y":12.0}, { "x":1398916800000 , "y":5.55}, { "x":1398916800000 , "y":4.89}, { "x":1398916800000 , "y":5.01}, { "x":1398916800000 , "y":3.27}, { "x":1401595200000 , "y":6.27}, { "x":1401595200000 , "y":9.17}, { "x":1401595200000 , "y":9.31}, { "x":1401595200000 , "y":6.07}, { "x":1404187200000 , "y":8.37}, { "x":1404187200000 , "y":8.11}, { "x":1404187200000 , "y":8.84}, { "x":1404187200000 , "y":8.93}, { "x":1406865600000 , "y":11.79}, { "x":1406865600000 , "y":12.22}, { "x":1406865600000 , "y":12.6}, { "x":1406865600000 , "y":11.61}, { "x":1409544000000 , "y":15.27}, { "x":1409544000000 , "y":19.09}, { "x":1409544000000 , "y":16.09}, { "x":1409544000000 , "y":18.66}, { "x":1412136000000 , "y":18.4}, { "x":1412136000000 , "y":22.05}, { "x":1412136000000 , "y":21.66}, { "x":1412136000000 , "y":19.04}, { "x":1414814400000 , "y":19.13}, { "x":1414814400000 , "y":19.61}, { "x":1414814400000 , "y":17.61}, { "x":1414814400000 , "y":17.5}, { "x":1417410000000 , "y":19.0}, { "x":1417410000000 , "y":15.73}, { "x":1420088400000 , "y":9.67}, { "x":1420088400000 , "y":15.19}, { "x":1420088400000 , "y":15.02}, { "x":1420088400000 , "y":9.62333333333333}, { "x":1422766800000 , "y":16.95}, { "x":1422766800000 , "y":14.29}, { "x":1425186000000 , "y":12.9}, { "x":1425186000000 , "y":16.1166666666667} ] } ,
+ { "type":"line", "key": "ROUTER_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":3.0}, { "x":1388552400000 , "y":4.0}, { "x":1388552400000 , "y":4.89}, { "x":1388552400000 , "y":7.0}, { "x":1391230800000 , "y":4.57}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":4.0}, { "x":1391230800000 , "y":7.0}, { "x":1393650000000 , "y":7.0}, { "x":1393650000000 , "y":4.18}, { "x":1393650000000 , "y":5.0}, { "x":1393650000000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.0}, { "x":1396324800000 , "y":5.06}, { "x":1396324800000 , "y":6.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1398916800000 , "y":5.0}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.09}, { "x":1401595200000 , "y":6.0}, { "x":1401595200000 , "y":6.0}, { "x":1404187200000 , "y":6.36}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1404187200000 , "y":7.0}, { "x":1406865600000 , "y":7.0}, { "x":1406865600000 , "y":7.02}, { "x":1406865600000 , "y":7.24}, { "x":1406865600000 , "y":7.0}, { "x":1409544000000 , "y":8.23}, { "x":1409544000000 , "y":8.11}, { "x":1409544000000 , "y":8.12}, { "x":1409544000000 , "y":8.03}, { "x":1412136000000 , "y":9.0}, { "x":1412136000000 , "y":8.93}, { "x":1412136000000 , "y":8.57}, { "x":1412136000000 , "y":9.0}, { "x":1414814400000 , "y":5.97}, { "x":1414814400000 , "y":6.0}, { "x":1414814400000 , "y":9.0}, { "x":1414814400000 , "y":9.0}, { "x":1417410000000 , "y":9.0}, { "x":1417410000000 , "y":8.78}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":2.01}, { "x":1420088400000 , "y":3.0}, { "x":1420088400000 , "y":3.01}, { "x":1422766800000 , "y":2.67}, { "x":1422766800000 , "y":2.0}, { "x":1425186000000 , "y":2.8}, { "x":1425186000000 , "y":3.63333333333333} ] } ,
+ { "type":"line", "key": "SCTP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":7.0}, { "x":1388552400000 , "y":10.0}, { "x":1388552400000 , "y":8.27}, { "x":1388552400000 , "y":8.0}, { "x":1391230800000 , "y":10.02}, { "x":1391230800000 , "y":8.04}, { "x":1391230800000 , "y":9.0}, { "x":1391230800000 , "y":10.0}, { "x":1393650000000 , "y":12.0}, { "x":1393650000000 , "y":10.04}, { "x":1393650000000 , "y":11.16}, { "x":1393650000000 , "y":10.0}, { "x":1396324800000 , "y":10.7}, { "x":1396324800000 , "y":13.31}, { "x":1396324800000 , "y":12.73}, { "x":1396324800000 , "y":9.0}, { "x":1398916800000 , "y":12.41}, { "x":1398916800000 , "y":11.95}, { "x":1398916800000 , "y":12.82}, { "x":1398916800000 , "y":9.58}, { "x":1401595200000 , "y":11.28}, { "x":1401595200000 , "y":14.01}, { "x":1401595200000 , "y":14.63}, { "x":1401595200000 , "y":11.83}, { "x":1404187200000 , "y":14.06}, { "x":1404187200000 , "y":13.96}, { "x":1404187200000 , "y":14.66}, { "x":1404187200000 , "y":14.36}, { "x":1406865600000 , "y":16.6}, { "x":1406865600000 , "y":16.95}, { "x":1406865600000 , "y":17.11}, { "x":1406865600000 , "y":15.94}, { "x":1409544000000 , "y":19.86}, { "x":1409544000000 , "y":22.97}, { "x":1409544000000 , "y":21.56}, { "x":1409544000000 , "y":24.55}, { "x":1412136000000 , "y":22.66}, { "x":1412136000000 , "y":26.79}, { "x":1412136000000 , "y":26.54}, { "x":1412136000000 , "y":25.35}, { "x":1414814400000 , "y":21.0}, { "x":1414814400000 , "y":20.35}, { "x":1414814400000 , "y":21.93}, { "x":1414814400000 , "y":23.63}, { "x":1417410000000 , "y":24.0}, { "x":1417410000000 , "y":21.43}, { "x":1420088400000 , "y":12.63}, { "x":1420088400000 , "y":25.14}, { "x":1420088400000 , "y":21.85}, { "x":1420088400000 , "y":12.5766666666667}, { "x":1422766800000 , "y":26.3}, { "x":1422766800000 , "y":24.4}, { "x":1425186000000 , "y":23.3833333333333}, { "x":1425186000000 , "y":24.5833333333333} ] } ,
+ { "type":"line", "key": "DP_CPU", "yAxis": "1","values": [{ "x":1388552400000 , "y":2.0}, { "x":1388552400000 , "y":5.0}, { "x":1388552400000 , "y":2.17}, { "x":1388552400000 , "y":2.0}, { "x":1391230800000 , "y":3.01}, { "x":1391230800000 , "y":2.56}, { "x":1391230800000 , "y":3.0}, { "x":1391230800000 , "y":9.0}, { "x":1393650000000 , "y":10.0}, { "x":1393650000000 , "y":3.64}, { "x":1393650000000 , "y":4.06}, { "x":1393650000000 , "y":4.0}, { "x":1396324800000 , "y":4.04}, { "x":1396324800000 , "y":5.11}, { "x":1396324800000 , "y":5.9}, { "x":1396324800000 , "y":8.0}, { "x":1398916800000 , "y":5.08}, { "x":1398916800000 , "y":4.65}, { "x":1398916800000 , "y":4.74}, { "x":1398916800000 , "y":2.98}, { "x":1401595200000 , "y":6.13}, { "x":1401595200000 , "y":8.98}, { "x":1401595200000 , "y":9.22}, { "x":1401595200000 , "y":5.84}, { "x":1404187200000 , "y":8.12}, { "x":1404187200000 , "y":7.89}, { "x":1404187200000 , "y":8.41}, { "x":1404187200000 , "y":8.47}, { "x":1406865600000 , "y":11.06}, { "x":1406865600000 , "y":11.84}, { "x":1406865600000 , "y":11.92}, { "x":1406865600000 , "y":10.8}, { "x":1409544000000 , "y":14.58}, { "x":1409544000000 , "y":18.39}, { "x":1409544000000 , "y":15.5}, { "x":1409544000000 , "y":18.33}, { "x":1412136000000 , "y":18.01}, { "x":1412136000000 , "y":21.3}, { "x":1412136000000 , "y":21.11}, { "x":1412136000000 , "y":18.37}, { "x":1414814400000 , "y":18.59}, { "x":1414814400000 , "y":18.81}, { "x":1414814400000 , "y":17.13}, { "x":1414814400000 , "y":16.92}, { "x":1417410000000 , "y":18.0}, { "x":1417410000000 , "y":15.18}, { "x":1420088400000 , "y":9.16}, { "x":1420088400000 , "y":12.13}, { "x":1420088400000 , "y":11.76}, { "x":1420088400000 , "y":9.31}, { "x":1422766800000 , "y":13.47}, { "x":1422766800000 , "y":13.41}, { "x":1425186000000 , "y":12.2333333333333}, { "x":1425186000000 , "y":12.4} ] }
+];
+
+</script>
+<script src="js/line_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/pie_chart.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/pie_chart.html
new file mode 100644
index 00000000..ebbdd9c0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/pie_chart.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv="content-type" content="text/html; charset=UTF8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge" />
+<link href="../../d3/css/nv.d3.css" rel="stylesheet" type="text/css">
+<style>
+ body {
+ overflow-y:scroll;
+ }
+ text {
+ font: 12px sans-serif;
+ }
+ tr.z-row-over > td.z-row-inner, tr.z-row-over > .z-cell { background-color: rgb(255, 255, 255); } svg { display: block; } #chart423 svg {
+ height: 275px;
+ width: 300px;
+ min-width: 100px;
+ min-height: 100px;
+ }
+ </style>
+<body>
+<div id="chart423"><svg></svg></div>
+<script src="../../d3/js/d3.v3.min.js"></script>
+<script src="../../d3/js/nv.d3.min.js"></script>
+<script src="../../d3/js/models/legend.js"></script>
+<script src="../../d3/js/models/pie.js"></script>
+<script src="../../d3/js/models/pieChart.js"></script>
+<script src="../../d3/js/utils.js"></script>
+<script>
+historicalBarChart = [
+{ "key":"Bedminster", "y":8.27},
+{ "key":"Middletown", "y":2.36},
+{ "key":"Paramus", "y":2.17},
+{ "key":"Piscataway", "y":4.89}
+];
+
+</script>
+<script src="js/pie_chart.min.js"></script>
+</body> </html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/wordcloud.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/wordcloud.html
new file mode 100644
index 00000000..6cf00079
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/html/wordcloud.html
@@ -0,0 +1,36 @@
+<html>
+<head>
+ <title>Word Cloud Example</title>
+ <meta charset="utf-8" />
+<script src="../../d3/js/d3.v3.min.js" type="text/JavaScript"></script>
+<script src="../../d3/js/colorbrewer.js" type="text/JavaScript"></script>
+<script src="../../d3/js/d3.layout.cloud.js" type="text/JavaScript"></script>
+
+</head>
+<style>
+ svg {
+ height: 350px;
+ width: 420px;
+ border: 1px solid gray;
+ }
+
+</style>
+<body>
+
+<div id="viz">
+ <svg>
+ </svg>
+</div>
+<div id="controls" />
+</body>
+ <footer>
+
+<script>
+var cloudSize = 200;
+var dataURL = "data/worddata.csv";
+var keywords = ["VNF", "portal", "D2.0", "service", "management", "ECOMP"];
+</script>
+<script src="js/worddata.min.js" type="text/JavaScript"></script>
+ </footer>
+
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png
new file mode 100644
index 00000000..ac970bda
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/Calendar-16x16.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-next.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-next.png
new file mode 100644
index 00000000..1a4f72c6
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-next.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-prev.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-prev.png
new file mode 100644
index 00000000..8211eba1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/arrow-prev.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png
new file mode 100644
index 00000000..78a8873b
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_drive_test_map.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png
new file mode 100644
index 00000000..df471d7d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_county.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png
new file mode 100644
index 00000000..e59fc189
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_eppt_regression.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png
new file mode 100644
index 00000000..76a2d2b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_ios_throughput.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png
new file mode 100644
index 00000000..174ef9b8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png
new file mode 100644
index 00000000..f7f2719a
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_lata_map_legend.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png
new file mode 100644
index 00000000..ee0ddef9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/carousel/slide_b_nova_sdn_map.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/copyicon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/copyicon.png
new file mode 100644
index 00000000..6c1c3c15
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/copyicon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/deleteicon.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/deleteicon.gif
new file mode 100644
index 00000000..4b07af82
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/deleteicon.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/example-frame.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/example-frame.png
new file mode 100644
index 00000000..31f2fe1c
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/example-frame.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/loading.gif b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/loading.gif
new file mode 100644
index 00000000..cccb0fc9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/loading.gif
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png
new file mode 100644
index 00000000..d46eee50
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/1_mon.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png
new file mode 100644
index 00000000..ed82aad3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/2_tue.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png
new file mode 100644
index 00000000..8f8c0328
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/3_wed.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png
new file mode 100644
index 00000000..750dca5d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/4_thu.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png
new file mode 100644
index 00000000..599e51f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/5_fri.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png
new file mode 100644
index 00000000..70323ea0
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/6_sat.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png
new file mode 100644
index 00000000..9d579d68
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/7_sun.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png
new file mode 100644
index 00000000..af1ac0a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_IN.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png
new file mode 100644
index 00000000..935b5386
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png
new file mode 100644
index 00000000..916a655f
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png
new file mode 100644
index 00000000..a8b516d9
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Def.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png
new file mode 100644
index 00000000..2cf81411
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/images/tunnels/BH_Nat_Priority.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/FusionCharts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/FusionCharts.js
new file mode 100644
index 00000000..4c174dfa
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/FusionCharts.js
@@ -0,0 +1,361 @@
+/**
+ * FusionCharts: Flash Player detection and Chart embedding.
+ * Version 1.2.3F ( 22 November 2008) - Specialized for FusionChartsFREE
+ * Checking Flash Version >=6 and added updateChartXML() for FREE Charts.
+ * Version: 1.2.3 (1st September, 2008) - Added Fix for % and & characters, scaled dimensions, fixes in to properly handling of double quotes and single quotes in setDataXML() function.
+ * Version: 1.2.2 (10th July, 2008) - Added Fix for % scaled dimensions, fixes in setDataXML() and setDataURL() functions
+ * Version: 1.2.1 (21st December, 2007) - Added setting up Transparent/opaque mode: setTransparent() function
+ * Version: 1.2 (1st November, 2007) - Added FORM fixes for IE
+ * Version: 1.1 (29th June, 2007) - Added Player detection, New conditional fixes for IE
+ *
+ * Morphed from SWFObject (http://blog.deconcept.com/swfobject/) under MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+if(typeof infosoftglobal == "undefined") var infosoftglobal = new Object();
+if(typeof infosoftglobal.FusionChartsUtil == "undefined") infosoftglobal.FusionChartsUtil = new Object();
+infosoftglobal.FusionCharts = function(swf, id, w, h, debugMode, registerWithJS, c, scaleMode, lang, detectFlashVersion, autoInstallRedirect){
+ if (!document.getElementById) { return; }
+
+ //Flag to see whether data has been set initially
+ this.initialDataSet = false;
+
+ //Create container objects
+ this.params = new Object();
+ this.variables = new Object();
+ this.attributes = new Array();
+
+ //Set attributes for the SWF
+ if(swf) { this.setAttribute('swf', swf); }
+ if(id) { this.setAttribute('id', id); }
+
+ w=w.toString().replace(/\%$/,"%25");
+ if(w) { this.setAttribute('width', w); }
+ h=h.toString().replace(/\%$/,"%25");
+ if(h) { this.setAttribute('height', h); }
+
+
+ //Set background color
+ if(c) { this.addParam('bgcolor', c); }
+
+ //Set Quality
+ this.addParam('quality', 'high');
+
+ //Add scripting access parameter
+ this.addParam('allowScriptAccess', 'always');
+
+ //Pass width and height to be appended as chartWidth and chartHeight
+ this.addVariable('chartWidth', w);
+ this.addVariable('chartHeight', h);
+
+ //Whether in debug mode
+ debugMode = debugMode ? debugMode : 0;
+ this.addVariable('debugMode', debugMode);
+ //Pass DOM ID to Chart
+ this.addVariable('DOMId', id);
+ //Whether to registed with JavaScript
+ registerWithJS = registerWithJS ? registerWithJS : 0;
+ this.addVariable('registerWithJS', registerWithJS);
+
+ //Scale Mode of chart
+ scaleMode = scaleMode ? scaleMode : 'noScale';
+ this.addVariable('scaleMode', scaleMode);
+
+ //Application Message Language
+ lang = lang ? lang : 'EN';
+ this.addVariable('lang', lang);
+
+ //Whether to auto detect and re-direct to Flash Player installation
+ this.detectFlashVersion = detectFlashVersion?detectFlashVersion:1;
+ this.autoInstallRedirect = autoInstallRedirect?autoInstallRedirect:1;
+
+ //Ger Flash Player version
+ this.installedVer = infosoftglobal.FusionChartsUtil.getPlayerVersion();
+
+ if (!window.opera && document.all && this.installedVer.major > 7) {
+ // Only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
+ infosoftglobal.FusionCharts.doPrepUnload = true;
+ }
+}
+
+infosoftglobal.FusionCharts.prototype = {
+ setAttribute: function(name, value){
+ this.attributes[name] = value;
+ },
+ getAttribute: function(name){
+ return this.attributes[name];
+ },
+ addParam: function(name, value){
+ this.params[name] = value;
+ },
+ getParams: function(){
+ return this.params;
+ },
+ addVariable: function(name, value){
+ this.variables[name] = value;
+ },
+ getVariable: function(name){
+ return this.variables[name];
+ },
+ getVariables: function(){
+ return this.variables;
+ },
+ getVariablePairs: function(){
+ var variablePairs = new Array();
+ var key;
+ var variables = this.getVariables();
+ for(key in variables){
+ variablePairs.push(key +"="+ variables[key]);
+ }
+ return variablePairs;
+ },
+ getSWFHTML: function() {
+ var swfNode = "";
+ if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
+ // netscape plugin architecture
+ swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" ';
+ swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
+ var params = this.getParams();
+ for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
+ var pairs = this.getVariablePairs().join("&");
+ if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
+ swfNode += '/>';
+ } else { // PC IE
+ swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
+ swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
+ var params = this.getParams();
+ for(var key in params) {
+ swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
+ }
+ var pairs = this.getVariablePairs().join("&");
+ if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
+ swfNode += "</object>";
+ }
+ return swfNode;
+ },
+ setDataURL: function(strDataURL){
+ //This method sets the data URL for the chart.
+ //If being set initially
+ if (this.initialDataSet==false){
+ this.addVariable('dataURL',strDataURL);
+ //Update flag
+ this.initialDataSet = true;
+ }else{
+ //Else, we update the chart data using External Interface
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(this.getAttribute('id'));
+
+ if (!chartObj.setDataURL)
+ {
+ __flash__addCallback(chartObj, "setDataURL");
+ }
+
+ chartObj.setDataURL(strDataURL);
+ }
+ },
+ //This function :
+ //fixes the double quoted attributes to single quotes
+ //Encodes all quotes inside attribute values
+ //Encodes % to %25 and & to %26;
+ encodeDataXML: function(strDataXML){
+
+ var regExpReservedCharacters=["\\$","\\+"];
+ var arrDQAtt=strDataXML.match(/=\s*\".*?\"/g);
+ if (arrDQAtt){
+ for(var i=0;i<arrDQAtt.length;i++){
+ var repStr=arrDQAtt[i].replace(/^=\s*\"|\"$/g,"");
+ repStr=repStr.replace(/\'/g,"%26apos;");
+ var strTo=strDataXML.indexOf(arrDQAtt[i]);
+ var repStrr="='"+repStr+"'";
+ var strStart=strDataXML.substring(0,strTo);
+ var strEnd=strDataXML.substring(strTo+arrDQAtt[i].length);
+ var strDataXML=strStart+repStrr+strEnd;
+ }
+ }
+
+ strDataXML=strDataXML.replace(/\"/g,"%26quot;");
+ strDataXML=strDataXML.replace(/%(?![\da-f]{2}|[\da-f]{4})/ig,"%25");
+ strDataXML=strDataXML.replace(/\&/g,"%26");
+
+ return strDataXML;
+
+ },
+ setDataXML: function(strDataXML){
+ //If being set initially
+ if (this.initialDataSet==false){
+ //This method sets the data XML for the chart INITIALLY.
+ this.addVariable('dataXML',this.encodeDataXML(strDataXML));
+ //Update flag
+ this.initialDataSet = true;
+ }else{
+ //Else, we update the chart data using External Interface
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(this.getAttribute('id'));
+ chartObj.setDataXML(strDataXML);
+ }
+ },
+ setTransparent: function(isTransparent){
+ //Sets chart to transparent mode when isTransparent is true (default)
+ //When no parameter is passed, we assume transparent to be true.
+ if(typeof isTransparent=="undefined") {
+ isTransparent=true;
+ }
+ //Set the property
+ if(isTransparent)
+ this.addParam('WMode', 'transparent');
+ else
+ this.addParam('WMode', 'Opaque');
+ },
+
+ render: function(elementId){
+ //First check for installed version of Flash Player - we need a minimum of 6
+ if((this.detectFlashVersion==1) && (this.installedVer.major < 6)){
+ if (this.autoInstallRedirect==1){
+ //If we can auto redirect to install the player?
+ var installationConfirm = window.confirm("You need Adobe Flash Player 6 (or above) to view the charts. It is a free and lightweight installation from Adobe.com. Please click on Ok to install the same.");
+ if (installationConfirm){
+ window.location = "http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash";
+ }else{
+ return false;
+ }
+ }else{
+ //Else, do not take an action. It means the developer has specified a message in the DIV (and probably a link).
+ //So, expect the developers to provide a course of way to their end users.
+ //window.alert("You need Adobe Flash Player 8 (or above) to view the charts. It is a free and lightweight installation from Adobe.com. ");
+ return false;
+ }
+ }else{
+ //Render the chart
+ var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
+ n.innerHTML = this.getSWFHTML();
+
+ //Added <FORM> compatibility
+ //Check if it's added in Mozilla embed array or if already exits
+ if(!document.embeds[this.getAttribute('id')] && !window[this.getAttribute('id')])
+ window[this.getAttribute('id')]=document.getElementById(this.getAttribute('id'));
+ //or else document.forms[formName/formIndex][chartId]
+ return true;
+ }
+ }
+}
+
+/* ---- detection functions ---- */
+infosoftglobal.FusionChartsUtil.getPlayerVersion = function(){
+ var PlayerVersion = new infosoftglobal.PlayerVersion([0,0,0]);
+ if(navigator.plugins && navigator.mimeTypes.length){
+ var x = navigator.plugins["Shockwave Flash"];
+ if(x && x.description) {
+ PlayerVersion = new infosoftglobal.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
+ }
+ }else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){
+ //If Windows CE
+ var axo = 1;
+ var counter = 3;
+ while(axo) {
+ try {
+ counter++;
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
+ PlayerVersion = new infosoftglobal.PlayerVersion([counter,0,0]);
+ } catch (e) {
+ axo = null;
+ }
+ }
+ } else {
+ // Win IE (non mobile)
+ // Do minor version lookup in IE, but avoid Flash Player 6 crashing issues
+ try{
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
+ }catch(e){
+ try {
+ var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
+ PlayerVersion = new infosoftglobal.PlayerVersion([6,0,21]);
+ axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
+ } catch(e) {
+ if (PlayerVersion.major == 6) {
+ return PlayerVersion;
+ }
+ }
+ try {
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+ } catch(e) {}
+ }
+ if (axo != null) {
+ PlayerVersion = new infosoftglobal.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
+ }
+ }
+ return PlayerVersion;
+}
+infosoftglobal.PlayerVersion = function(arrVersion){
+ this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
+ this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
+ this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
+}
+// ------------ Fix for Out of Memory Bug in IE in FP9 ---------------//
+/* Fix for video streaming bug */
+infosoftglobal.FusionChartsUtil.cleanupSWFs = function() {
+ var objects = document.getElementsByTagName("OBJECT");
+ for (var i = objects.length - 1; i >= 0; i--) {
+ objects[i].style.display = 'none';
+ for (var x in objects[i]) {
+ if (typeof objects[i][x] == 'function') {
+ objects[i][x] = function(){};
+ }
+ }
+ }
+}
+// Fixes bug in fp9
+if (infosoftglobal.FusionCharts.doPrepUnload) {
+ if (!infosoftglobal.unloadSet) {
+ infosoftglobal.FusionChartsUtil.prepUnload = function() {
+ __flash_unloadHandler = function(){};
+ __flash_savedUnloadHandler = function(){};
+ window.attachEvent("onunload", infosoftglobal.FusionChartsUtil.cleanupSWFs);
+ }
+ window.attachEvent("onbeforeunload", infosoftglobal.FusionChartsUtil.prepUnload);
+ infosoftglobal.unloadSet = true;
+ }
+}
+/* Add document.getElementById if needed (mobile IE < 5) */
+if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}
+/* Add Array.push if needed (ie5) */
+if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}
+
+/* Function to return Flash Object from ID */
+infosoftglobal.FusionChartsUtil.getChartObject = function(id)
+{
+ var chartRef=null;
+ if (navigator.appName.indexOf("Microsoft Internet")==-1) {
+ if (document.embeds && document.embeds[id])
+ chartRef = document.embeds[id];
+ else
+ chartRef = window.document[id];
+ }
+ else {
+ chartRef = window[id];
+ }
+ if (!chartRef)
+ chartRef = document.getElementById(id);
+
+ return chartRef;
+}
+/*
+ Function to update chart's data at client side (FOR FusionCharts vFREE and 2.x
+*/
+infosoftglobal.FusionChartsUtil.updateChartXML = function(chartId, strXML){
+ //Get reference to chart object
+ var chartObj = infosoftglobal.FusionChartsUtil.getChartObject(chartId);
+ //Set dataURL to null
+ chartObj.SetVariable("_root.dataURL","");
+ //Set the flag
+ chartObj.SetVariable("_root.isNewData","1");
+ //Set the actual data
+ chartObj.SetVariable("_root.newData",strXML);
+ //Go to the required frame
+ chartObj.TGotoLabel("/", "JavaScriptHandler");
+}
+
+
+/* Aliases for easy usage */
+var getChartFromId = infosoftglobal.FusionChartsUtil.getChartObject;
+var updateChartXML = infosoftglobal.FusionChartsUtil.updateChartXML;
+var FusionCharts = infosoftglobal.FusionCharts; \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/charts.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/charts.js
new file mode 100644
index 00000000..4bebbd36
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/charts.js
@@ -0,0 +1,132 @@
+
+function drawSingleSeriesChart(tabId, chartId, chartWidth, chartHeight, chartType, chartData,mme,yyyyMo) {
+ // define, set the data for each chart, and render them (if indicated)
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/" + chartType, "myChartId" + chartId, chartWidth, chartHeight);
+
+ var mmeLabel = "";//mme + "";
+
+ var chartCaptionId = tabId + "-chartdiv" + chartId + "-label";
+
+ document.getElementById(chartCaptionId).innerHTML = "Hosted Voice Usage in "+ yyyyMo;
+
+ myChart.setDataXML("<graph caption='"+mmeLabel + "' xAxisName='' yAxisName='# of Inbound/Outbound calls' showNames='1' decimalPrecision='0' formatNumberScale='0'>" + chartData + "</graph>");
+ myChart.setTransparent(true);
+ myChart.render(tabId + "-"+ "chartdiv" + chartId);
+
+
+ }
+
+
+ // gauge charts
+ function drawGaugeChart(chartId, gaugeIndex, value) {
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/AngularGauge.swf", "myChartId" + chartId, "300", "300", "0", "0");
+ //CPU for NYCMNYBWLT1 on 201301 : 12.63//
+ var chartData =
+ "<Chart showBorder='0' editMode='1' bgColor='FFFFFF' upperLimit='100' lowerLimit='0' label='CPU' baseFontColor='FFFFFF' majorTMNumber='11' majorTMColor='FFFFFF' majorTMHeight='8' minorTMNumber='5' minorTMColor='FFFFFF' minorTMHeight='3' toolTipBorderColor='FFFFFF' toolTipBgColor='333333' gaugeOuterRadius='100' gaugeOriginX='150' gaugeOriginY='150' gaugeScaleAngle='270' placeValuesInside='1' gaugeInnerRadius='80%25' annRenderDelay='0' gaugeFillMix='' pivotRadius='10' showPivotBorder='0' pivotFillMix='{CCCCCC},{333333}' pivotFillRatio='50,50' showShadow='0' >" +
+ "<colorRange>" +
+ "<color minValue='0' maxValue='50' code='C1E1C1' alpha='60'/>" +
+ "<color minValue='50' maxValue='85' code='F6F164' alpha='60'/>" +
+ "<color minValue='85' maxValue='120' code='F70118' alpha='60'/>" +
+ "</colorRange>" +
+ "<dials>" +
+ "<dial value='" + value + "' borderColor='FFFFFF' bgColor='000000,CCCCCC,000000' borderAlpha='0' baseWidth='10'/>" +
+ "</dials>" +
+ "<annotations>" +
+ "<annotationGroup xPos='150' yPos='150' showBelow='1'>" +
+ "<annotation type='circle' xPos='0' yPos='0' radius='120' startAngle='0' endAngle='360' fillColor='CCCCCC,111111' fillPattern='linear' fillAlpha='100,100' fillRatio='50,50' fillAngle='-45'/>" +
+ "<annotation type='circle' xPos='0' yPos='0' radius='110' startAngle='0' endAngle='360' fillColor='111111,cccccc' fillPattern='linear' fillAlpha='100,100' fillRatio='50,50' fillAngle='-45'/>" +
+ "<annotation type='text' label='CPU'/>" +
+ "</annotationGroup>" +
+ "</annotations>" +
+ "</Chart>";
+
+ myChart.setDataXML(chartData);
+ myChart.render("chartdiv" + chartId);
+ }
+
+
+ function updateGaugeChart(chartId, gaugeIndex, refreshCount) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ var val = 0;
+ if (gaugeIndex == "10") val = 12;
+ else if (gaugeIndex == "20") val = 15;
+ else if (gaugeIndex == "30") val = 52;
+ else if (gaugeIndex == "40") val = 42;
+ myChart.setData(1, val);
+ myChart.setData(2, val+20);
+ }
+
+ function updateGaugeChartWithMMEData(chartId, value) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ myChart.setData(1, value);
+ }
+
+
+ function updateGaugeChartWithMMEData(chartId, value, yyyyMo, mme) {
+ var myChart = getChartFromId("myChartId" + chartId);
+ myChart.setData(1, value);
+ document.getElementById("cpuYyyyMm").innerHTML = "Hosted Voice Utilization in "+ yyyyMo;
+
+ }
+
+ function drawMultiSeriesChart(tabId,chartId, chartWidth, chartHeight, chartType) {
+ var myChart = new FusionCharts("static/fusion/inc/fusionchart/" + chartType, "myChartId" + chartId, chartWidth, chartHeight, "0", "0");
+
+ myChart.setTransparent(true);
+
+ var chartData =
+ "<graph caption='Hosted Voice v Audited Communication' xAxisName='Month' yAxisName='Bandwidth Usage'" +
+ " showValues='0' decimalPrecision='0' bgcolor='ffffff' bgAlpha='70'" +
+ " showColumnShadow='1' divlinecolor='c5c5c5' divLineAlpha='60' showAlternateHGridColor='1'" +
+ " alternateHGridColor='f8f8f8' alternateHGridAlpha='60' >" +
+ "<categories>" +
+ "<category name='Jan' />" +
+ "<category name='Feb' />" +
+ "<category name='Mar' />" +
+ "<category name='Apr' />" +
+ "<category name='May' />" +
+ "<category name='Jun' />" +
+ "<category name='Jul' />" +
+ "<category name='Aug' />" +
+ "<category name='Sep' />" +
+ "<category name='Oct' />" +
+ "<category name='Nov' />" +
+ "<category name='Dec' />" +
+ "</categories>" +
+ "<dataset seriesName='Hosted Voice' color='c4e3f7' >" +
+ "<set value='7' />" +
+ "<set value='8.04' />" +
+ "<set value='10.04' />" +
+ "<set value='12.73' />" +
+ "<set value='12.41' />" +
+ "<set value='11.83' />" +
+ "<set value='14.06' />" +
+ "<set value='15.94' />" +
+ "<set value='22.97' />" +
+ "<set value='26.79' />" +
+ "<set value='20.35' />" +
+ "<set value='12.63' />" +
+ "</dataset>" +
+ "<dataset seriesName='Audited Communication' color='Fad35e' >" +
+ "<set value='5.49'/>" +
+ "<set value='8.05'/>" +
+ "<set value='15.36'/>" +
+ "<set value='21.23'/>" +
+ "<set value='23.48' />" +
+ "<set value='15.49' />" +
+ "<set value='26.8' />" +
+ "<set value='30.54' />" +
+ "<set value='64' />" +
+ "<set value='75' />" +
+ "<set value='63' />" +
+ "<set value='34' />" +
+ "</dataset>" +
+ "<trendlines>" +
+ "<line startValue='26000' color='91C728' displayValue='Target' showOnTop='1'/>" +
+ "</trendlines>" +
+ "</graph>";
+
+ myChart.setDataXML(chartData);
+ myChart.render(tabId + "-" + "chartdiv" + chartId);
+ }
+
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/eye.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/eye.js
new file mode 100644
index 00000000..8a281dc3
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/eye.js
@@ -0,0 +1,34 @@
+/**
+ *
+ * Zoomimage
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($){
+ var EYE = window.EYE = function() {
+ var _registered = {
+ init: []
+ };
+ return {
+ init: function() {
+ $.each(_registered.init, function(nr, fn){
+ fn.call();
+ });
+ },
+ extend: function(prop) {
+ for (var i in prop) {
+ if (prop[i] != undefined) {
+ this[i] = prop[i];
+ }
+ }
+ },
+ register: function(fn, type) {
+ if (!_registered[type]) {
+ _registered[type] = [];
+ }
+ _registered[type].push(fn);
+ }
+ };
+ }();
+ $(EYE.init);
+})(jQuery);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js
new file mode 100644
index 00000000..5ad6c377
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/jquery.flexslider-min.js
@@ -0,0 +1,5 @@
+/*
+ * jQuery FlexSlider v2.6.0
+ * Copyright 2012 WooThemes
+ * Contributing Author: Tyler Smith
+ */!function($){var e=!0;$.flexslider=function(t,a){var n=$(t);n.vars=$.extend({},$.flexslider.defaults,a);var i=n.vars.namespace,s=window.navigator&&window.navigator.msPointerEnabled&&window.MSGesture,r=("ontouchstart"in window||s||window.DocumentTouch&&document instanceof DocumentTouch)&&n.vars.touch,o="click touchend MSPointerUp keyup",l="",c,d="vertical"===n.vars.direction,u=n.vars.reverse,v=n.vars.itemWidth>0,p="fade"===n.vars.animation,m=""!==n.vars.asNavFor,f={};$.data(t,"flexslider",n),f={init:function(){n.animating=!1,n.currentSlide=parseInt(n.vars.startAt?n.vars.startAt:0,10),isNaN(n.currentSlide)&&(n.currentSlide=0),n.animatingTo=n.currentSlide,n.atEnd=0===n.currentSlide||n.currentSlide===n.last,n.containerSelector=n.vars.selector.substr(0,n.vars.selector.search(" ")),n.slides=$(n.vars.selector,n),n.container=$(n.containerSelector,n),n.count=n.slides.length,n.syncExists=$(n.vars.sync).length>0,"slide"===n.vars.animation&&(n.vars.animation="swing"),n.prop=d?"top":"marginLeft",n.args={},n.manualPause=!1,n.stopped=!1,n.started=!1,n.startTimeout=null,n.transitions=!n.vars.video&&!p&&n.vars.useCSS&&function(){var e=document.createElement("div"),t=["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"];for(var a in t)if(void 0!==e.style[t[a]])return n.pfx=t[a].replace("Perspective","").toLowerCase(),n.prop="-"+n.pfx+"-transform",!0;return!1}(),n.ensureAnimationEnd="",""!==n.vars.controlsContainer&&(n.controlsContainer=$(n.vars.controlsContainer).length>0&&$(n.vars.controlsContainer)),""!==n.vars.manualControls&&(n.manualControls=$(n.vars.manualControls).length>0&&$(n.vars.manualControls)),""!==n.vars.customDirectionNav&&(n.customDirectionNav=2===$(n.vars.customDirectionNav).length&&$(n.vars.customDirectionNav)),n.vars.randomize&&(n.slides.sort(function(){return Math.round(Math.random())-.5}),n.container.empty().append(n.slides)),n.doMath(),n.setup("init"),n.vars.controlNav&&f.controlNav.setup(),n.vars.directionNav&&f.directionNav.setup(),n.vars.keyboard&&(1===$(n.containerSelector).length||n.vars.multipleKeyboard)&&$(document).bind("keyup",function(e){var t=e.keyCode;if(!n.animating&&(39===t||37===t)){var a=39===t?n.getTarget("next"):37===t?n.getTarget("prev"):!1;n.flexAnimate(a,n.vars.pauseOnAction)}}),n.vars.mousewheel&&n.bind("mousewheel",function(e,t,a,i){e.preventDefault();var s=0>t?n.getTarget("next"):n.getTarget("prev");n.flexAnimate(s,n.vars.pauseOnAction)}),n.vars.pausePlay&&f.pausePlay.setup(),n.vars.slideshow&&n.vars.pauseInvisible&&f.pauseInvisible.init(),n.vars.slideshow&&(n.vars.pauseOnHover&&n.hover(function(){n.manualPlay||n.manualPause||n.pause()},function(){n.manualPause||n.manualPlay||n.stopped||n.play()}),n.vars.pauseInvisible&&f.pauseInvisible.isHidden()||(n.vars.initDelay>0?n.startTimeout=setTimeout(n.play,n.vars.initDelay):n.play())),m&&f.asNav.setup(),r&&n.vars.touch&&f.touch(),(!p||p&&n.vars.smoothHeight)&&$(window).bind("resize orientationchange focus",f.resize),n.find("img").attr("draggable","false"),setTimeout(function(){n.vars.start(n)},200)},asNav:{setup:function(){n.asNav=!0,n.animatingTo=Math.floor(n.currentSlide/n.move),n.currentItem=n.currentSlide,n.slides.removeClass(i+"active-slide").eq(n.currentItem).addClass(i+"active-slide"),s?(t._slider=n,n.slides.each(function(){var e=this;e._gesture=new MSGesture,e._gesture.target=e,e.addEventListener("MSPointerDown",function(e){e.preventDefault(),e.currentTarget._gesture&&e.currentTarget._gesture.addPointer(e.pointerId)},!1),e.addEventListener("MSGestureTap",function(e){e.preventDefault();var t=$(this),a=t.index();$(n.vars.asNavFor).data("flexslider").animating||t.hasClass("active")||(n.direction=n.currentItem<a?"next":"prev",n.flexAnimate(a,n.vars.pauseOnAction,!1,!0,!0))})})):n.slides.on(o,function(e){e.preventDefault();var t=$(this),a=t.index(),s=t.offset().left-$(n).scrollLeft();0>=s&&t.hasClass(i+"active-slide")?n.flexAnimate(n.getTarget("prev"),!0):$(n.vars.asNavFor).data("flexslider").animating||t.hasClass(i+"active-slide")||(n.direction=n.currentItem<a?"next":"prev",n.flexAnimate(a,n.vars.pauseOnAction,!1,!0,!0))})}},controlNav:{setup:function(){n.manualControls?f.controlNav.setupManual():f.controlNav.setupPaging()},setupPaging:function(){var e="thumbnails"===n.vars.controlNav?"control-thumbs":"control-paging",t=1,a,s;if(n.controlNavScaffold=$('<ol class="'+i+"control-nav "+i+e+'"></ol>'),n.pagingCount>1)for(var r=0;r<n.pagingCount;r++){if(s=n.slides.eq(r),void 0===s.attr("data-thumb-alt")&&s.attr("data-thumb-alt",""),altText=""!==s.attr("data-thumb-alt")?altText=' alt="'+s.attr("data-thumb-alt")+'"':"",a="thumbnails"===n.vars.controlNav?'<img src="'+s.attr("data-thumb")+'"'+altText+"/>":'<a href="#">'+t+"</a>","thumbnails"===n.vars.controlNav&&!0===n.vars.thumbCaptions){var c=s.attr("data-thumbcaption");""!==c&&void 0!==c&&(a+='<span class="'+i+'caption">'+c+"</span>")}n.controlNavScaffold.append("<li>"+a+"</li>"),t++}n.controlsContainer?$(n.controlsContainer).append(n.controlNavScaffold):n.append(n.controlNavScaffold),f.controlNav.set(),f.controlNav.active(),n.controlNavScaffold.delegate("a, img",o,function(e){if(e.preventDefault(),""===l||l===e.type){var t=$(this),a=n.controlNav.index(t);t.hasClass(i+"active")||(n.direction=a>n.currentSlide?"next":"prev",n.flexAnimate(a,n.vars.pauseOnAction))}""===l&&(l=e.type),f.setToClearWatchedEvent()})},setupManual:function(){n.controlNav=n.manualControls,f.controlNav.active(),n.controlNav.bind(o,function(e){if(e.preventDefault(),""===l||l===e.type){var t=$(this),a=n.controlNav.index(t);t.hasClass(i+"active")||(a>n.currentSlide?n.direction="next":n.direction="prev",n.flexAnimate(a,n.vars.pauseOnAction))}""===l&&(l=e.type),f.setToClearWatchedEvent()})},set:function(){var e="thumbnails"===n.vars.controlNav?"img":"a";n.controlNav=$("."+i+"control-nav li "+e,n.controlsContainer?n.controlsContainer:n)},active:function(){n.controlNav.removeClass(i+"active").eq(n.animatingTo).addClass(i+"active")},update:function(e,t){n.pagingCount>1&&"add"===e?n.controlNavScaffold.append($('<li><a href="#">'+n.count+"</a></li>")):1===n.pagingCount?n.controlNavScaffold.find("li").remove():n.controlNav.eq(t).closest("li").remove(),f.controlNav.set(),n.pagingCount>1&&n.pagingCount!==n.controlNav.length?n.update(t,e):f.controlNav.active()}},directionNav:{setup:function(){var e=$('<ul class="'+i+'direction-nav"><li class="'+i+'nav-prev"><a class="'+i+'prev" href="#">'+n.vars.prevText+'</a></li><li class="'+i+'nav-next"><a class="'+i+'next" href="#">'+n.vars.nextText+"</a></li></ul>");n.customDirectionNav?n.directionNav=n.customDirectionNav:n.controlsContainer?($(n.controlsContainer).append(e),n.directionNav=$("."+i+"direction-nav li a",n.controlsContainer)):(n.append(e),n.directionNav=$("."+i+"direction-nav li a",n)),f.directionNav.update(),n.directionNav.bind(o,function(e){e.preventDefault();var t;(""===l||l===e.type)&&(t=$(this).hasClass(i+"next")?n.getTarget("next"):n.getTarget("prev"),n.flexAnimate(t,n.vars.pauseOnAction)),""===l&&(l=e.type),f.setToClearWatchedEvent()})},update:function(){var e=i+"disabled";1===n.pagingCount?n.directionNav.addClass(e).attr("tabindex","-1"):n.vars.animationLoop?n.directionNav.removeClass(e).removeAttr("tabindex"):0===n.animatingTo?n.directionNav.removeClass(e).filter("."+i+"prev").addClass(e).attr("tabindex","-1"):n.animatingTo===n.last?n.directionNav.removeClass(e).filter("."+i+"next").addClass(e).attr("tabindex","-1"):n.directionNav.removeClass(e).removeAttr("tabindex")}},pausePlay:{setup:function(){var e=$('<div class="'+i+'pauseplay"><a href="#"></a></div>');n.controlsContainer?(n.controlsContainer.append(e),n.pausePlay=$("."+i+"pauseplay a",n.controlsContainer)):(n.append(e),n.pausePlay=$("."+i+"pauseplay a",n)),f.pausePlay.update(n.vars.slideshow?i+"pause":i+"play"),n.pausePlay.bind(o,function(e){e.preventDefault(),(""===l||l===e.type)&&($(this).hasClass(i+"pause")?(n.manualPause=!0,n.manualPlay=!1,n.pause()):(n.manualPause=!1,n.manualPlay=!0,n.play())),""===l&&(l=e.type),f.setToClearWatchedEvent()})},update:function(e){"play"===e?n.pausePlay.removeClass(i+"pause").addClass(i+"play").html(n.vars.playText):n.pausePlay.removeClass(i+"play").addClass(i+"pause").html(n.vars.pauseText)}},touch:function(){function e(e){e.stopPropagation(),n.animating?e.preventDefault():(n.pause(),t._gesture.addPointer(e.pointerId),T=0,c=d?n.h:n.w,f=Number(new Date),l=v&&u&&n.animatingTo===n.last?0:v&&u?n.limit-(n.itemW+n.vars.itemMargin)*n.move*n.animatingTo:v&&n.currentSlide===n.last?n.limit:v?(n.itemW+n.vars.itemMargin)*n.move*n.currentSlide:u?(n.last-n.currentSlide+n.cloneOffset)*c:(n.currentSlide+n.cloneOffset)*c)}function a(e){e.stopPropagation();var a=e.target._slider;if(a){var n=-e.translationX,i=-e.translationY;return T+=d?i:n,m=T,x=d?Math.abs(T)<Math.abs(-n):Math.abs(T)<Math.abs(-i),e.detail===e.MSGESTURE_FLAG_INERTIA?void setImmediate(function(){t._gesture.stop()}):void((!x||Number(new Date)-f>500)&&(e.preventDefault(),!p&&a.transitions&&(a.vars.animationLoop||(m=T/(0===a.currentSlide&&0>T||a.currentSlide===a.last&&T>0?Math.abs(T)/c+2:1)),a.setProps(l+m,"setTouch"))))}}function i(e){e.stopPropagation();var t=e.target._slider;if(t){if(t.animatingTo===t.currentSlide&&!x&&null!==m){var a=u?-m:m,n=a>0?t.getTarget("next"):t.getTarget("prev");t.canAdvance(n)&&(Number(new Date)-f<550&&Math.abs(a)>50||Math.abs(a)>c/2)?t.flexAnimate(n,t.vars.pauseOnAction):p||t.flexAnimate(t.currentSlide,t.vars.pauseOnAction,!0)}r=null,o=null,m=null,l=null,T=0}}var r,o,l,c,m,f,g,h,S,x=!1,y=0,b=0,T=0;s?(t.style.msTouchAction="none",t._gesture=new MSGesture,t._gesture.target=t,t.addEventListener("MSPointerDown",e,!1),t._slider=n,t.addEventListener("MSGestureChange",a,!1),t.addEventListener("MSGestureEnd",i,!1)):(g=function(e){n.animating?e.preventDefault():(window.navigator.msPointerEnabled||1===e.touches.length)&&(n.pause(),c=d?n.h:n.w,f=Number(new Date),y=e.touches[0].pageX,b=e.touches[0].pageY,l=v&&u&&n.animatingTo===n.last?0:v&&u?n.limit-(n.itemW+n.vars.itemMargin)*n.move*n.animatingTo:v&&n.currentSlide===n.last?n.limit:v?(n.itemW+n.vars.itemMargin)*n.move*n.currentSlide:u?(n.last-n.currentSlide+n.cloneOffset)*c:(n.currentSlide+n.cloneOffset)*c,r=d?b:y,o=d?y:b,t.addEventListener("touchmove",h,!1),t.addEventListener("touchend",S,!1))},h=function(e){y=e.touches[0].pageX,b=e.touches[0].pageY,m=d?r-b:r-y,x=d?Math.abs(m)<Math.abs(y-o):Math.abs(m)<Math.abs(b-o);var t=500;(!x||Number(new Date)-f>t)&&(e.preventDefault(),!p&&n.transitions&&(n.vars.animationLoop||(m/=0===n.currentSlide&&0>m||n.currentSlide===n.last&&m>0?Math.abs(m)/c+2:1),n.setProps(l+m,"setTouch")))},S=function(e){if(t.removeEventListener("touchmove",h,!1),n.animatingTo===n.currentSlide&&!x&&null!==m){var a=u?-m:m,i=a>0?n.getTarget("next"):n.getTarget("prev");n.canAdvance(i)&&(Number(new Date)-f<550&&Math.abs(a)>50||Math.abs(a)>c/2)?n.flexAnimate(i,n.vars.pauseOnAction):p||n.flexAnimate(n.currentSlide,n.vars.pauseOnAction,!0)}t.removeEventListener("touchend",S,!1),r=null,o=null,m=null,l=null},t.addEventListener("touchstart",g,!1))},resize:function(){!n.animating&&n.is(":visible")&&(v||n.doMath(),p?f.smoothHeight():v?(n.slides.width(n.computedW),n.update(n.pagingCount),n.setProps()):d?(n.viewport.height(n.h),n.setProps(n.h,"setTotal")):(n.vars.smoothHeight&&f.smoothHeight(),n.newSlides.width(n.computedW),n.setProps(n.computedW,"setTotal")))},smoothHeight:function(e){if(!d||p){var t=p?n:n.viewport;e?t.animate({height:n.slides.eq(n.animatingTo).height()},e):t.height(n.slides.eq(n.animatingTo).height())}},sync:function(e){var t=$(n.vars.sync).data("flexslider"),a=n.animatingTo;switch(e){case"animate":t.flexAnimate(a,n.vars.pauseOnAction,!1,!0);break;case"play":t.playing||t.asNav||t.play();break;case"pause":t.pause()}},uniqueID:function(e){return e.filter("[id]").add(e.find("[id]")).each(function(){var e=$(this);e.attr("id",e.attr("id")+"_clone")}),e},pauseInvisible:{visProp:null,init:function(){var e=f.pauseInvisible.getHiddenProp();if(e){var t=e.replace(/[H|h]idden/,"")+"visibilitychange";document.addEventListener(t,function(){f.pauseInvisible.isHidden()?n.startTimeout?clearTimeout(n.startTimeout):n.pause():n.started?n.play():n.vars.initDelay>0?setTimeout(n.play,n.vars.initDelay):n.play()})}},isHidden:function(){var e=f.pauseInvisible.getHiddenProp();return e?document[e]:!1},getHiddenProp:function(){var e=["webkit","moz","ms","o"];if("hidden"in document)return"hidden";for(var t=0;t<e.length;t++)if(e[t]+"Hidden"in document)return e[t]+"Hidden";return null}},setToClearWatchedEvent:function(){clearTimeout(c),c=setTimeout(function(){l=""},3e3)}},n.flexAnimate=function(e,t,a,s,o){if(n.vars.animationLoop||e===n.currentSlide||(n.direction=e>n.currentSlide?"next":"prev"),m&&1===n.pagingCount&&(n.direction=n.currentItem<e?"next":"prev"),!n.animating&&(n.canAdvance(e,o)||a)&&n.is(":visible")){if(m&&s){var l=$(n.vars.asNavFor).data("flexslider");if(n.atEnd=0===e||e===n.count-1,l.flexAnimate(e,!0,!1,!0,o),n.direction=n.currentItem<e?"next":"prev",l.direction=n.direction,Math.ceil((e+1)/n.visible)-1===n.currentSlide||0===e)return n.currentItem=e,n.slides.removeClass(i+"active-slide").eq(e).addClass(i+"active-slide"),!1;n.currentItem=e,n.slides.removeClass(i+"active-slide").eq(e).addClass(i+"active-slide"),e=Math.floor(e/n.visible)}if(n.animating=!0,n.animatingTo=e,t&&n.pause(),n.vars.before(n),n.syncExists&&!o&&f.sync("animate"),n.vars.controlNav&&f.controlNav.active(),v||n.slides.removeClass(i+"active-slide").eq(e).addClass(i+"active-slide"),n.atEnd=0===e||e===n.last,n.vars.directionNav&&f.directionNav.update(),e===n.last&&(n.vars.end(n),n.vars.animationLoop||n.pause()),p)r?(n.slides.eq(n.currentSlide).css({opacity:0,zIndex:1}),n.slides.eq(e).css({opacity:1,zIndex:2}),n.wrapup(c)):(n.slides.eq(n.currentSlide).css({zIndex:1}).animate({opacity:0},n.vars.animationSpeed,n.vars.easing),n.slides.eq(e).css({zIndex:2}).animate({opacity:1},n.vars.animationSpeed,n.vars.easing,n.wrapup));else{var c=d?n.slides.filter(":first").height():n.computedW,g,h,S;v?(g=n.vars.itemMargin,S=(n.itemW+g)*n.move*n.animatingTo,h=S>n.limit&&1!==n.visible?n.limit:S):h=0===n.currentSlide&&e===n.count-1&&n.vars.animationLoop&&"next"!==n.direction?u?(n.count+n.cloneOffset)*c:0:n.currentSlide===n.last&&0===e&&n.vars.animationLoop&&"prev"!==n.direction?u?0:(n.count+1)*c:u?(n.count-1-e+n.cloneOffset)*c:(e+n.cloneOffset)*c,n.setProps(h,"",n.vars.animationSpeed),n.transitions?(n.vars.animationLoop&&n.atEnd||(n.animating=!1,n.currentSlide=n.animatingTo),n.container.unbind("webkitTransitionEnd transitionend"),n.container.bind("webkitTransitionEnd transitionend",function(){clearTimeout(n.ensureAnimationEnd),n.wrapup(c)}),clearTimeout(n.ensureAnimationEnd),n.ensureAnimationEnd=setTimeout(function(){n.wrapup(c)},n.vars.animationSpeed+100)):n.container.animate(n.args,n.vars.animationSpeed,n.vars.easing,function(){n.wrapup(c)})}n.vars.smoothHeight&&f.smoothHeight(n.vars.animationSpeed)}},n.wrapup=function(e){p||v||(0===n.currentSlide&&n.animatingTo===n.last&&n.vars.animationLoop?n.setProps(e,"jumpEnd"):n.currentSlide===n.last&&0===n.animatingTo&&n.vars.animationLoop&&n.setProps(e,"jumpStart")),n.animating=!1,n.currentSlide=n.animatingTo,n.vars.after(n)},n.animateSlides=function(){!n.animating&&e&&n.flexAnimate(n.getTarget("next"))},n.pause=function(){clearInterval(n.animatedSlides),n.animatedSlides=null,n.playing=!1,n.vars.pausePlay&&f.pausePlay.update("play"),n.syncExists&&f.sync("pause")},n.play=function(){n.playing&&clearInterval(n.animatedSlides),n.animatedSlides=n.animatedSlides||setInterval(n.animateSlides,n.vars.slideshowSpeed),n.started=n.playing=!0,n.vars.pausePlay&&f.pausePlay.update("pause"),n.syncExists&&f.sync("play")},n.stop=function(){n.pause(),n.stopped=!0},n.canAdvance=function(e,t){var a=m?n.pagingCount-1:n.last;return t?!0:m&&n.currentItem===n.count-1&&0===e&&"prev"===n.direction?!0:m&&0===n.currentItem&&e===n.pagingCount-1&&"next"!==n.direction?!1:e!==n.currentSlide||m?n.vars.animationLoop?!0:n.atEnd&&0===n.currentSlide&&e===a&&"next"!==n.direction?!1:n.atEnd&&n.currentSlide===a&&0===e&&"next"===n.direction?!1:!0:!1},n.getTarget=function(e){return n.direction=e,"next"===e?n.currentSlide===n.last?0:n.currentSlide+1:0===n.currentSlide?n.last:n.currentSlide-1},n.setProps=function(e,t,a){var i=function(){var a=e?e:(n.itemW+n.vars.itemMargin)*n.move*n.animatingTo,i=function(){if(v)return"setTouch"===t?e:u&&n.animatingTo===n.last?0:u?n.limit-(n.itemW+n.vars.itemMargin)*n.move*n.animatingTo:n.animatingTo===n.last?n.limit:a;switch(t){case"setTotal":return u?(n.count-1-n.currentSlide+n.cloneOffset)*e:(n.currentSlide+n.cloneOffset)*e;case"setTouch":return u?e:e;case"jumpEnd":return u?e:n.count*e;case"jumpStart":return u?n.count*e:e;default:return e}}();return-1*i+"px"}();n.transitions&&(i=d?"translate3d(0,"+i+",0)":"translate3d("+i+",0,0)",a=void 0!==a?a/1e3+"s":"0s",n.container.css("-"+n.pfx+"-transition-duration",a),n.container.css("transition-duration",a)),n.args[n.prop]=i,(n.transitions||void 0===a)&&n.container.css(n.args),n.container.css("transform",i)},n.setup=function(e){if(p)n.slides.css({width:"100%","float":"left",marginRight:"-100%",position:"relative"}),"init"===e&&(r?n.slides.css({opacity:0,display:"block",webkitTransition:"opacity "+n.vars.animationSpeed/1e3+"s ease",zIndex:1}).eq(n.currentSlide).css({opacity:1,zIndex:2}):0==n.vars.fadeFirstSlide?n.slides.css({opacity:0,display:"block",zIndex:1}).eq(n.currentSlide).css({zIndex:2}).css({opacity:1}):n.slides.css({opacity:0,display:"block",zIndex:1}).eq(n.currentSlide).css({zIndex:2}).animate({opacity:1},n.vars.animationSpeed,n.vars.easing)),n.vars.smoothHeight&&f.smoothHeight();else{var t,a;"init"===e&&(n.viewport=$('<div class="'+i+'viewport"></div>').css({overflow:"hidden",position:"relative"}).appendTo(n).append(n.container),n.cloneCount=0,n.cloneOffset=0,u&&(a=$.makeArray(n.slides).reverse(),n.slides=$(a),n.container.empty().append(n.slides))),n.vars.animationLoop&&!v&&(n.cloneCount=2,n.cloneOffset=1,"init"!==e&&n.container.find(".clone").remove(),n.container.append(f.uniqueID(n.slides.first().clone().addClass("clone")).attr("aria-hidden","true")).prepend(f.uniqueID(n.slides.last().clone().addClass("clone")).attr("aria-hidden","true"))),n.newSlides=$(n.vars.selector,n),t=u?n.count-1-n.currentSlide+n.cloneOffset:n.currentSlide+n.cloneOffset,d&&!v?(n.container.height(200*(n.count+n.cloneCount)+"%").css("position","absolute").width("100%"),setTimeout(function(){n.newSlides.css({display:"block"}),n.doMath(),n.viewport.height(n.h),n.setProps(t*n.h,"init")},"init"===e?100:0)):(n.container.width(200*(n.count+n.cloneCount)+"%"),n.setProps(t*n.computedW,"init"),setTimeout(function(){n.doMath(),n.newSlides.css({width:n.computedW,marginRight:n.computedM,"float":"left",display:"block"}),n.vars.smoothHeight&&f.smoothHeight()},"init"===e?100:0))}v||n.slides.removeClass(i+"active-slide").eq(n.currentSlide).addClass(i+"active-slide"),n.vars.init(n)},n.doMath=function(){var e=n.slides.first(),t=n.vars.itemMargin,a=n.vars.minItems,i=n.vars.maxItems;n.w=void 0===n.viewport?n.width():n.viewport.width(),n.h=e.height(),n.boxPadding=e.outerWidth()-e.width(),v?(n.itemT=n.vars.itemWidth+t,n.itemM=t,n.minW=a?a*n.itemT:n.w,n.maxW=i?i*n.itemT-t:n.w,n.itemW=n.minW>n.w?(n.w-t*(a-1))/a:n.maxW<n.w?(n.w-t*(i-1))/i:n.vars.itemWidth>n.w?n.w:n.vars.itemWidth,n.visible=Math.floor(n.w/n.itemW),n.move=n.vars.move>0&&n.vars.move<n.visible?n.vars.move:n.visible,n.pagingCount=Math.ceil((n.count-n.visible)/n.move+1),n.last=n.pagingCount-1,n.limit=1===n.pagingCount?0:n.vars.itemWidth>n.w?n.itemW*(n.count-1)+t*(n.count-1):(n.itemW+t)*n.count-n.w-t):(n.itemW=n.w,n.itemM=t,n.pagingCount=n.count,n.last=n.count-1),n.computedW=n.itemW-n.boxPadding,n.computedM=n.itemM},n.update=function(e,t){n.doMath(),v||(e<n.currentSlide?n.currentSlide+=1:e<=n.currentSlide&&0!==e&&(n.currentSlide-=1),n.animatingTo=n.currentSlide),n.vars.controlNav&&!n.manualControls&&("add"===t&&!v||n.pagingCount>n.controlNav.length?f.controlNav.update("add"):("remove"===t&&!v||n.pagingCount<n.controlNav.length)&&(v&&n.currentSlide>n.last&&(n.currentSlide-=1,n.animatingTo-=1),f.controlNav.update("remove",n.last))),n.vars.directionNav&&f.directionNav.update()},n.addSlide=function(e,t){var a=$(e);n.count+=1,n.last=n.count-1,d&&u?void 0!==t?n.slides.eq(n.count-t).after(a):n.container.prepend(a):void 0!==t?n.slides.eq(t).before(a):n.container.append(a),n.update(t,"add"),n.slides=$(n.vars.selector+":not(.clone)",n),n.setup(),n.vars.added(n)},n.removeSlide=function(e){var t=isNaN(e)?n.slides.index($(e)):e;n.count-=1,n.last=n.count-1,isNaN(e)?$(e,n.slides).remove():d&&u?n.slides.eq(n.last).remove():n.slides.eq(e).remove(),n.doMath(),n.update(t,"remove"),n.slides=$(n.vars.selector+":not(.clone)",n),n.setup(),n.vars.removed(n)},f.init()},$(window).blur(function(t){e=!1}).focus(function(t){e=!0}),$.flexslider.defaults={namespace:"flex-",selector:".slides > li",animation:"fade",easing:"swing",direction:"horizontal",reverse:!1,animationLoop:!0,smoothHeight:!1,startAt:0,slideshow:!0,slideshowSpeed:7e3,animationSpeed:600,initDelay:0,randomize:!1,fadeFirstSlide:!0,thumbCaptions:!1,pauseOnAction:!0,pauseOnHover:!1,pauseInvisible:!0,useCSS:!0,touch:!0,video:!1,controlNav:!0,directionNav:!0,prevText:"Previous",nextText:"Next",keyboard:!0,multipleKeyboard:!1,mousewheel:!1,pausePlay:!1,pauseText:"Pause",playText:"Play",controlsContainer:"",manualControls:"",customDirectionNav:"",sync:"",asNavFor:"",itemWidth:0,itemMargin:0,minItems:1,maxItems:0,move:0,allowOneSlide:!0,start:function(){},before:function(){},after:function(){},end:function(){},added:function(){},removed:function(){},init:function(){}},$.fn.flexslider=function(e){if(void 0===e&&(e={}),"object"==typeof e)return this.each(function(){var t=$(this),a=e.selector?e.selector:".slides > li",n=t.find(a);1===n.length&&e.allowOneSlide===!0||0===n.length?(n.fadeIn(400),e.start&&e.start(t)):void 0===t.data("flexslider")&&new $.flexslider(this,e)});var t=$(this).data("flexslider");switch(e){case"play":t.play();break;case"pause":t.pause();break;case"stop":t.stop();break;case"next":t.flexAnimate(t.getTarget("next"),!0);break;case"prev":case"previous":t.flexAnimate(t.getTarget("prev"),!0);break;default:"number"==typeof e&&t.flexAnimate(e,!0)}}}(jQuery); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/scribble.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/scribble.js
new file mode 100644
index 00000000..5384b304
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/scribble.js
@@ -0,0 +1,19 @@
+ function storeUserScribble(id) {
+ var scribble = document.getElementById('scribble').innerHTML;
+ localStorage.setItem('userScribble',scribble);
+ }
+
+ function getUserScribble() {
+ if ( localStorage.getItem('userScribble')) {
+ var scribble = localStorage.getItem('userScribble');
+ }
+ else {
+ var scribble = 'You can scribble directly on this sticky... and I will also remember your message the next time you visit my blog!';
+ }
+ document.getElementById('scribble').innerHTML = scribble;
+ }
+
+ function clearLocal() {
+ clear: localStorage.clear();
+ return false;
+ }
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js
new file mode 100644
index 00000000..1a1fcdd8
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/slides.min.jquery.js
@@ -0,0 +1,20 @@
+/*
+* Slides, A Slideshow Plugin for jQuery
+* Intructions: http://slidesjs.com
+* By: Nathan Searles, http://nathansearles.com
+* Version: 1.1.9
+* Updated: September 5th, 2011
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+(function(a){a.fn.slides=function(b){return b=a.extend({},a.fn.slides.option,b),this.each(function(){function w(g,h,i){if(!p&&o){p=!0,b.animationStart(n+1);switch(g){case"next":l=n,k=n+1,k=e===k?0:k,r=f*2,g=-f*2,n=k;break;case"prev":l=n,k=n-1,k=k===-1?e-1:k,r=0,g=0,n=k;break;case"pagination":k=parseInt(i,10),l=a("."+b.paginationClass+" li."+b.currentClass+" a",c).attr("href").match("[^#/]+$"),k>l?(r=f*2,g=-f*2):(r=0,g=0),n=k}h==="fade"?b.crossfade?d.children(":eq("+k+")",c).css({zIndex:10}).fadeIn(b.fadeSpeed,b.fadeEasing,function(){b.autoHeight?d.animate({height:d.children(":eq("+k+")",c).outerHeight()},b.autoHeightSpeed,function(){d.children(":eq("+l+")",c).css({display:"none",zIndex:0}),d.children(":eq("+k+")",c).css({zIndex:0}),b.animationComplete(k+1),p=!1}):(d.children(":eq("+l+")",c).css({display:"none",zIndex:0}),d.children(":eq("+k+")",c).css({zIndex:0}),b.animationComplete(k+1),p=!1)}):d.children(":eq("+l+")",c).fadeOut(b.fadeSpeed,b.fadeEasing,function(){b.autoHeight?d.animate({height:d.children(":eq("+k+")",c).outerHeight()},b.autoHeightSpeed,function(){d.children(":eq("+k+")",c).fadeIn(b.fadeSpeed,b.fadeEasing)}):d.children(":eq("+k+")",c).fadeIn(b.fadeSpeed,b.fadeEasing,function(){a.browser.msie&&a(this).get(0).style.removeAttribute("filter")}),b.animationComplete(k+1),p=!1}):(d.children(":eq("+k+")").css({left:r,display:"block"}),b.autoHeight?d.animate({left:g,height:d.children(":eq("+k+")").outerHeight()},b.slideSpeed,b.slideEasing,function(){d.css({left:-f}),d.children(":eq("+k+")").css({left:f,zIndex:5}),d.children(":eq("+l+")").css({left:f,display:"none",zIndex:0}),b.animationComplete(k+1),p=!1}):d.animate({left:g},b.slideSpeed,b.slideEasing,function(){d.css({left:-f}),d.children(":eq("+k+")").css({left:f,zIndex:5}),d.children(":eq("+l+")").css({left:f,display:"none",zIndex:0}),b.animationComplete(k+1),p=!1})),b.pagination&&(a("."+b.paginationClass+" li."+b.currentClass,c).removeClass(b.currentClass),a("."+b.paginationClass+" li:eq("+k+")",c).addClass(b.currentClass))}}function x(){clearInterval(c.data("interval"))}function y(){b.pause?(clearTimeout(c.data("pause")),clearInterval(c.data("interval")),u=setTimeout(function(){clearTimeout(c.data("pause")),v=setInterval(function(){w("next",i)},b.play),c.data("interval",v)},b.pause),c.data("pause",u)):x()}a("."+b.container,a(this)).children().wrapAll('<div class="slides_control"/>');var c=a(this),d=a(".slides_control",c),e=d.children().size(),f=d.children().outerWidth(),g=d.children().outerHeight(),h=b.start-1,i=b.effect.indexOf(",")<0?b.effect:b.effect.replace(" ","").split(",")[0],j=b.effect.indexOf(",")<0?i:b.effect.replace(" ","").split(",")[1],k=0,l=0,m=0,n=0,o,p,q,r,s,t,u,v;if(e<2)return a("."+b.container,a(this)).fadeIn(b.fadeSpeed,b.fadeEasing,function(){o=!0,b.slidesLoaded()}),a("."+b.next+", ."+b.prev).fadeOut(0),!1;if(e<2)return;h<0&&(h=0),h>e&&(h=e-1),b.start&&(n=h),b.randomize&&d.randomize(),a("."+b.container,c).css({overflow:"hidden",position:"relative"}),d.children().css({position:"absolute",top:0,left:d.children().outerWidth(),zIndex:0,display:"none"}),d.css({position:"relative",width:f*3,height:g,left:-f}),a("."+b.container,c).css({display:"block"}),b.autoHeight&&(d.children().css({height:"auto"}),d.animate({height:d.children(":eq("+h+")").outerHeight()},b.autoHeightSpeed));if(b.preload&&d.find("img:eq("+h+")").length){a("."+b.container,c).css({background:"url("+b.preloadImage+") no-repeat 50% 50%"});var z=d.find("img:eq("+h+")").attr("src")+"?"+(new Date).getTime();a("img",c).parent().attr("class")!="slides_control"?t=d.children(":eq(0)")[0].tagName.toLowerCase():t=d.find("img:eq("+h+")"),d.find("img:eq("+h+")").attr("src",z).load(function(){d.find(t+":eq("+h+")").fadeIn(b.fadeSpeed,b.fadeEasing,function(){a(this).css({zIndex:5}),a("."+b.container,c).css({background:""}),o=!0,b.slidesLoaded()})})}else d.children(":eq("+h+")").fadeIn(b.fadeSpeed,b.fadeEasing,function(){o=!0,b.slidesLoaded()});b.bigTarget&&(d.children().css({cursor:"pointer"}),d.children().click(function(){return w("next",i),!1})),b.hoverPause&&b.play&&(d.bind("mouseover",function(){x()}),d.bind("mouseleave",function(){y()})),b.generateNextPrev&&(a("."+b.container,c).after('<a href="#" class="'+b.prev+'">Prev</a>'),a("."+b.prev,c).after('<a href="#" class="'+b.next+'">Next</a>')),a("."+b.next,c).click(function(a){a.preventDefault(),b.play&&y(),w("next",i)}),a("."+b.prev,c).click(function(a){a.preventDefault(),b.play&&y(),w("prev",i)}),b.generatePagination?(b.prependPagination?c.prepend("<ul class="+b.paginationClass+"></ul>"):c.append("<ul class="+b.paginationClass+"></ul>"),d.children().each(function(){a("."+b.paginationClass,c).append('<li><a href="#'+m+'">'+(m+1)+"</a></li>"),m++})):a("."+b.paginationClass+" li a",c).each(function(){a(this).attr("href","#"+m),m++}),a("."+b.paginationClass+" li:eq("+h+")",c).addClass(b.currentClass),a("."+b.paginationClass+" li a",c).click(function(){return b.play&&y(),q=a(this).attr("href").match("[^#/]+$"),n!=q&&w("pagination",j,q),!1}),a("a.link",c).click(function(){return b.play&&y(),q=a(this).attr("href").match("[^#/]+$")-1,n!=q&&w("pagination",j,q),!1}),b.play&&(v=setInterval(function(){w("next",i)},b.play),c.data("interval",v))})},a.fn.slides.option={preload:!1,preloadImage:"/img/loading.gif",container:"slides_container",generateNextPrev:!1,next:"next",prev:"prev",pagination:!0,generatePagination:!0,prependPagination:!1,paginationClass:"pagination",currentClass:"current",fadeSpeed:350,fadeEasing:"",slideSpeed:350,slideEasing:"",start:1,effect:"slide",crossfade:!1,randomize:!1,play:0,pause:0,hoverPause:!1,autoHeight:!1,autoHeightSpeed:350,bigTarget:!1,animationStart:function(){},animationComplete:function(){},slidesLoaded:function(){}},a.fn.randomize=function(b){function c(){return Math.round(Math.random())-.5}return a(this).each(function(){var d=a(this),e=d.children(),f=e.length;if(f>1){e.hide();var g=[];for(i=0;i<f;i++)g[g.length]=i;g=g.sort(c),a.each(g,function(a,c){var f=e.eq(c),g=f.clone(!0);g.show().appendTo(d),b!==undefined&&b(f,g),f.remove()})}})}})(jQuery) \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/spacegallery.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/spacegallery.js
new file mode 100644
index 00000000..69ab2ccc
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/spacegallery.js
@@ -0,0 +1,235 @@
+/**
+ *
+ * Spacegallery
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+
+(function($){
+ EYE.extend({
+
+ spacegallery: {
+
+ //default options (many options are controled via CSS)
+ defaults: {
+ border: 6, // border arround the image
+ perspective: 140, // perpective height
+ minScale: 0.2, // minimum scale for the image in the back
+ duration: 800, // aimation duration
+ loadingClass: null, // CSS class applied to the element while looading images
+ before: function(){return false},
+ after: function(){return false}
+ },
+
+ animated: false,
+
+ //position images
+ positionImages: function(el) {
+ var top = 0;
+ EYE.spacegallery.animated = false;
+ $(el)
+ .find('a')
+ .removeClass(el.spacegalleryCfg.loadingClass)
+ .end()
+ .find('img')
+ .removeAttr('height')
+ .each(function(nr){
+ var newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * el.spacegalleryCfg.asins[nr];
+ $(this)
+ .css({
+ top: el.spacegalleryCfg.tops[nr] + 'px',
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px',
+ opacity: 1 - el.spacegalleryCfg.asins[nr]
+ })
+ .attr('width', parseInt(newWidth));
+ this.spacegallery.next = el.spacegalleryCfg.asins[nr+1];
+ this.spacegallery.nextTop = el.spacegalleryCfg.tops[nr+1] - el.spacegalleryCfg.tops[nr];
+ this.spacegallery.origTop = el.spacegalleryCfg.tops[nr];
+ this.spacegallery.opacity = 1 - el.spacegalleryCfg.asins[nr];
+ this.spacegallery.increment = el.spacegalleryCfg.asins[nr] - this.spacegallery.next;
+ this.spacegallery.current = el.spacegalleryCfg.asins[nr];
+ this.spacegallery.width = newWidth;
+ })
+ },
+
+ //animate to nex image
+ next: function(e) {
+ if (EYE.spacegallery.animated === false) {
+ EYE.spacegallery.animated = true;
+ var el = this.parentNode;
+ el.spacegalleryCfg.before.apply(el);
+ $(el)
+ .css('spacegallery', 0)
+ .animate({
+ spacegallery: 100
+ },{
+ easing: 'easeOut',
+ duration: el.spacegalleryCfg.duration,
+ complete: function() {
+ $(el)
+ .find('img:last')
+ .prependTo(el);
+ EYE.spacegallery.positionImages(el);
+ el.spacegalleryCfg.after.apply(el);
+ },
+ step: function(now) {
+ $('img', this)
+ .each(function(nr){
+ var newWidth, top, next;
+ if (nr + 1 == el.spacegalleryCfg.images) {
+ top = this.spacegallery.origTop + this.spacegallery.nextTop * 4 * now /100;
+ newWidth = this.spacegallery.width * top / this.spacegallery.origTop;
+ $(this)
+ .css({
+ top: top + 'px',
+ opacity: 0.7 - now/100,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ } else {
+ next = this.spacegallery.current - this.spacegallery.increment * now /100;
+ newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * next;
+ $(this).css({
+ top: this.spacegallery.origTop + this.spacegallery.nextTop * now /100 + 'px',
+ opacity: 1 - next,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ }
+ });
+ }
+ });
+ }
+
+ this.blur();
+ return false;
+ },
+
+ autoNext: function(el) {
+
+ if (EYE.spacegallery.animated === false) {
+ EYE.spacegallery.animated = true;
+ el.spacegalleryCfg.before.apply(el); // run the "before" function
+ $(el)
+ .css('spacegallery', 0)
+ .animate({
+ spacegallery: 100
+ },{
+ easing: 'easeOut',
+ duration: el.spacegalleryCfg.duration,
+ complete: function() { // after animation is complete, move the front image to the back
+ $(el)
+ .find('img:last') // find the last image in this div
+ .prependTo(el); // and stick it at the beginning
+ EYE.spacegallery.positionImages(el); // run "position images"
+ el.spacegalleryCfg.after.apply(el); //run the "after" function
+ },
+ step: function(now) {
+ $('img', this)
+ .each(function(nr){
+ var newWidth, top, next;
+ if (nr + 1 == el.spacegalleryCfg.images) {
+ top = this.spacegallery.origTop + this.spacegallery.nextTop * 4 * now /100;
+ newWidth = this.spacegallery.width * top / this.spacegallery.origTop;
+ $(this)
+ .css({
+ top: top + 'px',
+ opacity: 0.7 - now/100,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ } else {
+ next = this.spacegallery.current - this.spacegallery.increment * now /100;
+ newWidth = this.spacegallery.origWidth - (this.spacegallery.origWidth - this.spacegallery.origWidth * el.spacegalleryCfg.minScale) * next;
+ $(this).css({
+ top: this.spacegallery.origTop + this.spacegallery.nextTop * now /100 + 'px',
+ opacity: 1 - next,
+ marginLeft: - parseInt((newWidth + el.spacegalleryCfg.border)/2, 10) + 'px'
+ })
+ .attr('width', newWidth);
+ }
+ });
+ }
+ });
+ }
+
+ return false;
+ },
+
+ //constructor
+ init: function(opt) {
+ opt = $.extend({}, EYE.spacegallery.defaults, opt||{});
+ return this.each(function(){
+ var el = this;
+ if ($(el).is('.spacegallery')) {
+ $('<a href="#"></a>')
+ .appendTo(this)
+ .addClass(opt.loadingClass)
+ .bind('click', EYE.spacegallery.next);
+ el.spacegalleryCfg = opt;
+ el.spacegalleryCfg.images = el.getElementsByTagName('img').length;
+ el.spacegalleryCfg.loaded = 0;
+ el.spacegalleryCfg.asin = Math.asin(1);
+ el.spacegalleryCfg.asins = {};
+ el.spacegalleryCfg.tops = {};
+ el.spacegalleryCfg.increment = parseInt(el.spacegalleryCfg.perspective/el.spacegalleryCfg.images, 10);
+ var top = 0;
+ $('img', el)
+ .each(function(nr){
+ var imgEl = new Image();
+ var elImg = this;
+ el.spacegalleryCfg.asins[nr] = 1 - Math.asin((nr+1)/el.spacegalleryCfg.images)/el.spacegalleryCfg.asin;
+ top += el.spacegalleryCfg.increment - el.spacegalleryCfg.increment * el.spacegalleryCfg.asins[nr];
+ el.spacegalleryCfg.tops[nr] = top;
+ elImg.spacegallery = {};
+ imgEl.src = this.src;
+ if (imgEl.complete) {
+ el.spacegalleryCfg.loaded ++;
+ elImg.spacegallery.origWidth = imgEl.width;
+ elImg.spacegallery.origHeight = imgEl.height
+ } else {
+ imgEl.onload = function() {
+ el.spacegalleryCfg.loaded ++;
+ elImg.spacegallery.origWidth = imgEl.width;
+ elImg.spacegallery.origHeight = imgEl.height
+ if (el.spacegalleryCfg.loaded == el.spacegalleryCfg.images) {
+
+ EYE.spacegallery.positionImages(el);
+ }
+ };
+ }
+ });
+ el.spacegalleryCfg.asins[el.spacegalleryCfg.images] = el.spacegalleryCfg.asins[el.spacegalleryCfg.images - 1] * 1.3;
+ el.spacegalleryCfg.tops[el.spacegalleryCfg.images] = el.spacegalleryCfg.tops[el.spacegalleryCfg.images - 1] * 1.3;
+ if (el.spacegalleryCfg.loaded == el.spacegalleryCfg.images) {
+ EYE.spacegallery.positionImages(el);
+ setInterval(function() { EYE.spacegallery.autoNext(el); }, 4000);
+ }
+ }
+ });
+ }
+ }
+ });
+
+ $.fn.extend({
+
+ /**
+ * Create a space gallery
+ * @name spacegallery
+ * @description create a space gallery
+ * @option int border Images' border. Default: 6
+ * @option int perspective Perpective height. Default: 140
+ * @option float minScale Minimum scale for the image in the back. Default: 0.2
+ * @option int duration Animation duration. Default: 800
+ * @option string loadingClass CSS class applied to the element while looading images. Default: null
+ * @option function before Callback function triggered before going to the next image
+ * @option function after Callback function triggered after going to the next image
+ */
+ spacegallery: EYE.spacegallery.init
+ });
+ $.extend($.easing,{
+ easeOut:function (x, t, b, c, d) {
+ return -c *(t/=d)*(t-2) + b;
+ }
+ });
+})(jQuery); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/utils.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/utils.js
new file mode 100644
index 00000000..d9be8532
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/js/utils.js
@@ -0,0 +1,252 @@
+/**
+ *
+ * Utilities
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($) {
+EYE.extend({
+ getPosition : function(e, forceIt)
+ {
+ var x = 0;
+ var y = 0;
+ var es = e.style;
+ var restoreStyles = false;
+ if (forceIt && jQuery.curCSS(e,'display') == 'none') {
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ restoreStyles = true;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ }
+ var el = e;
+ if (el.getBoundingClientRect) { // IE
+ var box = el.getBoundingClientRect();
+ x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
+ y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
+ } else {
+ x = el.offsetLeft;
+ y = el.offsetTop;
+ el = el.offsetParent;
+ if (e != el) {
+ while (el) {
+ x += el.offsetLeft;
+ y += el.offsetTop;
+ el = el.offsetParent;
+ }
+ }
+ if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
+ x -= document.body.offsetLeft;
+ y -= document.body.offsetTop;
+ }
+ el = e.parentNode;
+ while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML')
+ {
+ if (jQuery.curCSS(el, 'display') != 'inline') {
+ x -= el.scrollLeft;
+ y -= el.scrollTop;
+ }
+ el = el.parentNode;
+ }
+ }
+ if (restoreStyles == true) {
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {x:x, y:y};
+ },
+ getSize : function(e)
+ {
+ var w = parseInt(jQuery.curCSS(e,'width'), 10);
+ var h = parseInt(jQuery.curCSS(e,'height'), 10);
+ var wb = 0;
+ var hb = 0;
+ if (jQuery.curCSS(e, 'display') != 'none') {
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ } else {
+ var es = e.style;
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {w:w, h:h, wb:wb, hb:hb};
+ },
+ getClient : function(e)
+ {
+ var h, w;
+ if (e) {
+ w = e.clientWidth;
+ h = e.clientHeight;
+ } else {
+ var de = document.documentElement;
+ w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
+ h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
+ }
+ return {w:w,h:h};
+ },
+ getScroll : function (e)
+ {
+ var t=0, l=0, w=0, h=0, iw=0, ih=0;
+ if (e && e.nodeName.toLowerCase() != 'body') {
+ t = e.scrollTop;
+ l = e.scrollLeft;
+ w = e.scrollWidth;
+ h = e.scrollHeight;
+ } else {
+ if (document.documentElement) {
+ t = document.documentElement.scrollTop;
+ l = document.documentElement.scrollLeft;
+ w = document.documentElement.scrollWidth;
+ h = document.documentElement.scrollHeight;
+ } else if (document.body) {
+ t = document.body.scrollTop;
+ l = document.body.scrollLeft;
+ w = document.body.scrollWidth;
+ h = document.body.scrollHeight;
+ }
+ if (typeof pageYOffset != 'undefined') {
+ t = pageYOffset;
+ l = pageXOffset;
+ }
+ iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
+ ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
+ }
+ return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
+ },
+ getMargins : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'marginTop') || '';
+ var r = jQuery.curCSS(e,'marginRight') || '';
+ var b = jQuery.curCSS(e,'marginBottom') || '';
+ var l = jQuery.curCSS(e,'marginLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getPadding : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'paddingTop') || '';
+ var r = jQuery.curCSS(e,'paddingRight') || '';
+ var b = jQuery.curCSS(e,'paddingBottom') || '';
+ var l = jQuery.curCSS(e,'paddingLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getBorder : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'borderTopWidth') || '';
+ var r = jQuery.curCSS(e,'borderRightWidth') || '';
+ var b = jQuery.curCSS(e,'borderBottomWidth') || '';
+ var l = jQuery.curCSS(e,'borderLeftWidth') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)||0
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ traverseDOM : function(nodeEl, func)
+ {
+ func(nodeEl);
+ nodeEl = nodeEl.firstChild;
+ while(nodeEl){
+ EYE.traverseDOM(nodeEl, func);
+ nodeEl = nodeEl.nextSibling;
+ }
+ },
+ getInnerWidth : function(el, scroll) {
+ var offsetW = el.offsetWidth;
+ return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
+ },
+ getInnerHeight : function(el, scroll) {
+ var offsetH = el.offsetHeight;
+ return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
+ },
+ getExtraWidth : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingLeft'))||0)
+ + (parseInt($.curCSS(el, 'paddingRight'))||0)
+ + (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderRightWidth'))||0);
+ return 0;
+ },
+ getExtraHeight : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingTop'))||0)
+ + (parseInt($.curCSS(el, 'paddingBottom'))||0)
+ + (parseInt($.curCSS(el, 'borderTopWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
+ return 0;
+ },
+ isChildOf: function(parentEl, el, container) {
+ if (parentEl == el) {
+ return true;
+ }
+ if (!el || !el.nodeType || el.nodeType != 1) {
+ return false;
+ }
+ if (parentEl.contains && !$.browser.safari) {
+ return parentEl.contains(el);
+ }
+ if ( parentEl.compareDocumentPosition ) {
+ return !!(parentEl.compareDocumentPosition(el) & 16);
+ }
+ var prEl = el.parentNode;
+ while(prEl && prEl != container) {
+ if (prEl == parentEl)
+ return true;
+ prEl = prEl.parentNode;
+ }
+ return false;
+ },
+ centerEl : function(el, axis)
+ {
+ var clientScroll = EYE.getScroll();
+ var size = EYE.getSize(el);
+ if (!axis || axis == 'vertically')
+ $(el).css(
+ {
+ top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
+ }
+ );
+ if (!axis || axis == 'horizontally')
+ $(el).css(
+ {
+ left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
+ }
+ );
+ }
+});
+if (!$.easing.easeout) {
+ $.easing.easeout = function(p, n, firstNum, delta, duration) {
+ return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
+ };
+}
+
+})(jQuery); \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css
new file mode 100644
index 00000000..3424a5f1
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/bootstrap.min.css
@@ -0,0 +1,351 @@
+html,body{margin:0;padding:0;}
+h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,cite,code,del,dfn,em,img,q,s,samp,small,strike,strong,sub,sup,tt,var,dd,dl,dt,li,ol,ul,fieldset,form,label,legend,button,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;}
+ol,ul{list-style:none;}
+q:before,q:after,blockquote:before,blockquote:after{content:"";}
+html{overflow-y:scroll;font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
+a:focus{outline:thin dotted;}
+a:hover,a:active{outline:0;}
+article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
+audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
+audio:not([controls]){display:none;}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
+sup{top:-0.5em;}
+sub{bottom:-0.25em;}
+img{border:0;-ms-interpolation-mode:bicubic;}
+button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;}
+button,input{line-height:normal;*overflow:visible;}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
+button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
+input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
+input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
+textarea{overflow:auto;vertical-align:top;}
+body{background-color:#ffffff;margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;color:#404040;}
+.container{width:940px;margin-left:auto;margin-right:auto;zoom:1;}.container:before,.container:after{display:table;content:"";zoom:1;}
+.container:after{clear:both;}
+.container-fluid{position:relative;min-width:940px;padding-left:20px;padding-right:20px;zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";zoom:1;}
+.container-fluid:after{clear:both;}
+.container-fluid>.sidebar{position:absolute;top:0;left:20px;width:220px;}
+.container-fluid>.content{margin-left:240px;}
+a{color:#0069d6;text-decoration:none;line-height:inherit;font-weight:inherit;}a:hover{color:#00438a;text-decoration:underline;}
+.pull-right{float:right;}
+.pull-left{float:left;}
+.hide{display:none;}
+.show{display:block;}
+.row{zoom:1;margin-left:-20px;}.row:before,.row:after{display:table;content:"";zoom:1;}
+.row:after{clear:both;}
+.row>[class*="span"]{display:inline;float:left;margin-left:20px;}
+.span1{width:40px;}
+.span2{width:100px;}
+.span3{width:160px;}
+.span4{width:220px;}
+.span5{width:280px;}
+.span6{width:340px;}
+.span7{width:400px;}
+.span8{width:460px;}
+.span9{width:520px;}
+.span10{width:580px;}
+.span11{width:640px;}
+.span12{width:700px;}
+.span13{width:760px;}
+.span14{width:820px;}
+.span15{width:880px;}
+.span16{width:940px;}
+.span17{width:1000px;}
+.span18{width:1060px;}
+.span19{width:1120px;}
+.span20{width:1180px;}
+.span21{width:1240px;}
+.span22{width:1300px;}
+.span23{width:1360px;}
+.span24{width:1420px;}
+.row>.offset1{margin-left:80px;}
+.row>.offset2{margin-left:140px;}
+.row>.offset3{margin-left:200px;}
+.row>.offset4{margin-left:260px;}
+.row>.offset5{margin-left:320px;}
+.row>.offset6{margin-left:380px;}
+.row>.offset7{margin-left:440px;}
+.row>.offset8{margin-left:500px;}
+.row>.offset9{margin-left:560px;}
+.row>.offset10{margin-left:620px;}
+.row>.offset11{margin-left:680px;}
+.row>.offset12{margin-left:740px;}
+.span-one-third{width:300px;}
+.span-two-thirds{width:620px;}
+.offset-one-third{margin-left:340px;}
+.offset-two-thirds{margin-left:660px;}
+p{font-size:13px;font-weight:normal;line-height:18px;margin-bottom:9px;}p small{font-size:11px;color:#bfbfbf;}
+h1,h2,h3,h4,h5,h6{font-weight:bold;color:#404040;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#bfbfbf;}
+h1{margin-bottom:18px;font-size:30px;line-height:36px;}h1 small{font-size:18px;}
+h2{font-size:24px;line-height:36px;}h2 small{font-size:14px;}
+h3,h4,h5,h6{line-height:36px;}
+h3{font-size:18px;}h3 small{font-size:14px;}
+h4{font-size:16px;}h4 small{font-size:12px;}
+h5{font-size:14px;}
+h6{font-size:13px;color:#bfbfbf;text-transform:uppercase;}
+ul,ol{margin:0 0 18px 25px;}
+ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
+ul{list-style:disc;}
+ol{list-style:decimal;}
+li{line-height:18px;color:#808080;}
+ul.unstyled{list-style:none;margin-left:0;}
+dl{margin-bottom:18px;}dl dt,dl dd{line-height:18px;}
+dl dt{font-weight:bold;}
+dl dd{margin-left:9px;}
+hr{margin:20px 0 19px;border:0;border-bottom:1px solid #eee;}
+strong{font-style:inherit;font-weight:bold;}
+em{font-style:italic;font-weight:inherit;line-height:inherit;}
+.muted{color:#bfbfbf;}
+blockquote{margin-bottom:18px;border-left:5px solid #eee;padding-left:15px;}blockquote p{font-size:14px;font-weight:300;line-height:18px;margin-bottom:0;}
+blockquote small{display:block;font-size:12px;font-weight:300;line-height:18px;color:#bfbfbf;}blockquote small:before{content:'\2014 \00A0';}
+address{display:block;line-height:18px;margin-bottom:18px;}
+code,pre{padding:0 3px 2px;font-family:Monaco, Andale Mono, Courier New, monospace;font-size:12px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+code{background-color:#fee9cc;color:rgba(0, 0, 0, 0.75);padding:1px 3px;}
+pre{background-color:#f5f5f5;display:block;padding:8.5px;margin:0 0 18px;line-height:18px;font-size:12px;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;white-space:pre;white-space:pre-wrap;word-wrap:break-word;}
+form{margin-bottom:18px;}
+fieldset{margin-bottom:18px;padding-top:18px;}fieldset legend{display:block;padding-left:150px;font-size:19.5px;line-height:1;color:#404040;*padding:0 0 5px 145px;*line-height:1.5;}
+form .clearfix{margin-bottom:18px;zoom:1;}form .clearfix:before,form .clearfix:after{display:table;content:"";zoom:1;}
+form .clearfix:after{clear:both;}
+label,input,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:normal;}
+label{padding-top:6px;font-size:13px;line-height:18px;float:left;width:130px;text-align:right;color:#404040;}
+form .input{margin-left:150px;}
+input[type=checkbox],input[type=radio]{cursor:pointer;}
+input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;font-size:13px;line-height:18px;color:#808080;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+select{padding:initial;}
+input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:none;}
+input[type=file]{background-color:#ffffff;padding:initial;border:initial;line-height:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+input[type=button],input[type=reset],input[type=submit]{width:auto;height:auto;}
+select,input[type=file]{height:27px;*height:auto;line-height:27px;*margin-top:4px;}
+select[multiple]{height:inherit;background-color:#ffffff;}
+textarea{height:auto;}
+.uneditable-input{background-color:#ffffff;display:block;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
+:-moz-placeholder{color:#bfbfbf;}
+::-webkit-input-placeholder{color:#bfbfbf;}
+input,textarea{-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);}
+input:focus,textarea:focus{outline:0;border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);}
+input[type=file]:focus,input[type=checkbox]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:1px dotted #666;}
+form .clearfix.error>label,form .clearfix.error .help-block,form .clearfix.error .help-inline{color:#b94a48;}
+form .clearfix.error input,form .clearfix.error textarea{color:#b94a48;border-color:#ee5f5b;}form .clearfix.error input:focus,form .clearfix.error textarea:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
+form .clearfix.error .input-prepend .add-on,form .clearfix.error .input-append .add-on{color:#b94a48;background-color:#fce6e6;border-color:#b94a48;}
+form .clearfix.warning>label,form .clearfix.warning .help-block,form .clearfix.warning .help-inline{color:#c09853;}
+form .clearfix.warning input,form .clearfix.warning textarea{color:#c09853;border-color:#ccae64;}form .clearfix.warning input:focus,form .clearfix.warning textarea:focus{border-color:#be9a3f;-webkit-box-shadow:0 0 6px #e5d6b1;-moz-box-shadow:0 0 6px #e5d6b1;box-shadow:0 0 6px #e5d6b1;}
+form .clearfix.warning .input-prepend .add-on,form .clearfix.warning .input-append .add-on{color:#c09853;background-color:#d2b877;border-color:#c09853;}
+form .clearfix.success>label,form .clearfix.success .help-block,form .clearfix.success .help-inline{color:#468847;}
+form .clearfix.success input,form .clearfix.success textarea{color:#468847;border-color:#57a957;}form .clearfix.success input:focus,form .clearfix.success textarea:focus{border-color:#458845;-webkit-box-shadow:0 0 6px #9acc9a;-moz-box-shadow:0 0 6px #9acc9a;box-shadow:0 0 6px #9acc9a;}
+form .clearfix.success .input-prepend .add-on,form .clearfix.success .input-append .add-on{color:#468847;background-color:#bcddbc;border-color:#468847;}
+.input-mini,input.mini,textarea.mini,select.mini{width:60px;}
+.input-small,input.small,textarea.small,select.small{width:90px;}
+.input-medium,input.medium,textarea.medium,select.medium{width:150px;}
+.input-large,input.large,textarea.large,select.large{width:210px;}
+.input-xlarge,input.xlarge,textarea.xlarge,select.xlarge{width:270px;}
+.input-xxlarge,input.xxlarge,textarea.xxlarge,select.xxlarge{width:530px;}
+textarea.xxlarge{overflow-y:auto;}
+input.span1,textarea.span1{display:inline-block;float:none;width:30px;margin-left:0;}
+input.span2,textarea.span2{display:inline-block;float:none;width:90px;margin-left:0;}
+input.span3,textarea.span3{display:inline-block;float:none;width:150px;margin-left:0;}
+input.span4,textarea.span4{display:inline-block;float:none;width:210px;margin-left:0;}
+input.span5,textarea.span5{display:inline-block;float:none;width:270px;margin-left:0;}
+input.span6,textarea.span6{display:inline-block;float:none;width:330px;margin-left:0;}
+input.span7,textarea.span7{display:inline-block;float:none;width:390px;margin-left:0;}
+input.span8,textarea.span8{display:inline-block;float:none;width:450px;margin-left:0;}
+input.span9,textarea.span9{display:inline-block;float:none;width:510px;margin-left:0;}
+input.span10,textarea.span10{display:inline-block;float:none;width:570px;margin-left:0;}
+input.span11,textarea.span11{display:inline-block;float:none;width:630px;margin-left:0;}
+input.span12,textarea.span12{display:inline-block;float:none;width:690px;margin-left:0;}
+input.span13,textarea.span13{display:inline-block;float:none;width:750px;margin-left:0;}
+input.span14,textarea.span14{display:inline-block;float:none;width:810px;margin-left:0;}
+input.span15,textarea.span15{display:inline-block;float:none;width:870px;margin-left:0;}
+input.span16,textarea.span16{display:inline-block;float:none;width:930px;margin-left:0;}
+input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;}
+.actions{background:#f5f5f5;margin-top:18px;margin-bottom:18px;padding:17px 20px 18px 150px;border-top:1px solid #ddd;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;}.actions .secondary-action{float:right;}.actions .secondary-action a{line-height:30px;}.actions .secondary-action a:hover{text-decoration:underline;}
+.help-inline,.help-block{font-size:13px;line-height:18px;color:#bfbfbf;}
+.help-inline{padding-left:5px;*position:relative;*top:-5px;}
+.help-block{display:block;max-width:600px;}
+.inline-inputs{color:#808080;}.inline-inputs span{padding:0 2px 0 1px;}
+.input-prepend input,.input-append input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
+.input-prepend .add-on,.input-append .add-on{position:relative;background:#f5f5f5;border:1px solid #ccc;z-index:2;float:left;display:block;width:auto;min-width:16px;height:18px;padding:4px 4px 4px 5px;margin-right:-1px;font-weight:normal;line-height:18px;color:#bfbfbf;text-align:center;text-shadow:0 1px 0 #ffffff;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
+.input-prepend .active,.input-append .active{background:#a9dba9;border-color:#46a546;}
+.input-prepend .add-on{*margin-top:1px;}
+.input-append input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
+.input-append .add-on{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;margin-right:0;margin-left:-1px;}
+.inputs-list{margin:0 0 5px;width:100%;}.inputs-list li{display:block;padding:0;width:100%;}
+.inputs-list label{display:block;float:none;width:auto;padding:0;margin-left:20px;line-height:18px;text-align:left;white-space:normal;}.inputs-list label strong{color:#808080;}
+.inputs-list label small{font-size:11px;font-weight:normal;}
+.inputs-list .inputs-list{margin-left:25px;margin-bottom:10px;padding-top:0;}
+.inputs-list:first-child{padding-top:6px;}
+.inputs-list li+li{padding-top:2px;}
+.inputs-list input[type=radio],.inputs-list input[type=checkbox]{margin-bottom:0;margin-left:-20px;float:left;}
+.form-stacked{padding-left:20px;}.form-stacked fieldset{padding-top:9px;}
+.form-stacked legend{padding-left:0;}
+.form-stacked label{display:block;float:none;width:auto;font-weight:bold;text-align:left;line-height:20px;padding-top:0;}
+.form-stacked .clearfix{margin-bottom:9px;}.form-stacked .clearfix div.input{margin-left:0;}
+.form-stacked .inputs-list{margin-bottom:0;}.form-stacked .inputs-list li{padding-top:0;}.form-stacked .inputs-list li label{font-weight:normal;padding-top:0;}
+.form-stacked div.clearfix.error{padding-top:10px;padding-bottom:10px;padding-left:10px;margin-top:0;margin-left:-10px;}
+.form-stacked .actions{margin-left:-20px;padding-left:20px;}
+.condensed-table th,.condensed-table td{padding:5px 5px 4px;}
+.bordered-table{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.bordered-table th+th,.bordered-table td+td,.bordered-table th+td{border-left:1px solid #ddd;}
+.bordered-table thead tr:first-child th:first-child,.bordered-table tbody tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;}
+.bordered-table thead tr:first-child th:last-child,.bordered-table tbody tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;}
+.bordered-table tbody tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;}
+.bordered-table tbody tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;}
+table .span1{width:20px;}
+table .span2{width:60px;}
+table .span3{width:100px;}
+table .span4{width:140px;}
+table .span5{width:180px;}
+table .span6{width:220px;}
+table .span7{width:260px;}
+table .span8{width:300px;}
+table .span9{width:340px;}
+table .span10{width:380px;}
+table .span11{width:420px;}
+table .span12{width:460px;}
+table .span13{width:500px;}
+table .span14{width:540px;}
+table .span15{width:580px;}
+table .span16{width:620px;}
+.zebra-striped tbody tr:nth-child(odd) td,.zebra-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;}
+.zebra-striped tbody tr:hover td,.zebra-striped tbody tr:hover th{background-color:#f5f5f5;}
+table .header{cursor:pointer;}table .header:after{content:"";float:right;margin-top:7px;border-width:0 4px 4px;border-style:solid;border-color:#000 transparent;visibility:hidden;}
+table .headerSortUp,table .headerSortDown{background-color:rgba(141, 192, 219, 0.25);text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);}
+table .header:hover:after{visibility:visible;}
+table .headerSortDown:after,table .headerSortDown:hover:after{visibility:visible;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;}
+table .headerSortUp:after{border-bottom:none;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000;visibility:visible;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;}
+table .blue{color:#049cdb;border-bottom-color:#049cdb;}
+table .headerSortUp.blue,table .headerSortDown.blue{background-color:#ade6fe;}
+table .green{color:#46a546;border-bottom-color:#46a546;}
+table .headerSortUp.green,table .headerSortDown.green{background-color:#cdeacd;}
+table .red{color:#9d261d;border-bottom-color:#9d261d;}
+table .headerSortUp.red,table .headerSortDown.red{background-color:#f4c8c5;}
+table .yellow{color:#ffc40d;border-bottom-color:#ffc40d;}
+table .headerSortUp.yellow,table .headerSortDown.yellow{background-color:#fff6d9;}
+table .orange{color:#f89406;border-bottom-color:#f89406;}
+table .headerSortUp.orange,table .headerSortDown.orange{background-color:#fee9cc;}
+table .purple{color:#7a43b6;border-bottom-color:#7a43b6;}
+table .headerSortUp.purple,table .headerSortDown.purple{background-color:#e2d5f0;}
+.topbar{height:40px;position:fixed;top:0;left:0;right:0;z-index:10000;overflow:visible;}.topbar a{color:#bfbfbf;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}
+.topbar h3 a:hover,.topbar .brand:hover,.topbar ul .active>a{background-color:#333;background-color:rgba(255, 255, 255, 0.05);color:#ffffff;text-decoration:none;}
+.topbar h3{position:relative;}
+.topbar h3 a,.topbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;color:#ffffff;font-size:20px;font-weight:200;line-height:1;}
+.topbar p{margin:0;line-height:40px;}.topbar p a:hover{background-color:transparent;color:#ffffff;}
+.topbar form{float:left;margin:5px 0 0 0;position:relative;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
+.topbar form.pull-right{float:right;}
+.topbar input{background-color:#444;background-color:rgba(255, 255, 255, 0.3);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:normal;font-weight:13px;line-height:1;padding:4px 9px;color:#ffffff;color:rgba(255, 255, 255, 0.75);border:1px solid #111;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.topbar input:-moz-placeholder{color:#e6e6e6;}
+.topbar input::-webkit-input-placeholder{color:#e6e6e6;}
+.topbar input:hover{background-color:#bfbfbf;background-color:rgba(255, 255, 255, 0.5);color:#ffffff;}
+.topbar input:focus,.topbar input.focused{outline:0;background-color:#ffffff;color:#404040;text-shadow:0 1px 0 #ffffff;border:0;padding:5px 10px;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);}
+.topbar-inner,.topbar .fill{background-color:#222;background-color:#222222;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);}
+.topbar div>ul,.nav{display:block;float:left;margin:0 10px 0 0;position:relative;left:0;}.topbar div>ul>li,.nav>li{display:block;float:left;}
+.topbar div>ul a,.nav a{display:block;float:none;padding:10px 10px 11px;line-height:19px;text-decoration:none;}.topbar div>ul a:hover,.nav a:hover{color:#ffffff;text-decoration:none;}
+.topbar div>ul .active>a,.nav .active>a{background-color:#222;background-color:rgba(0, 0, 0, 0.5);}
+.topbar div>ul.secondary-nav,.nav.secondary-nav{float:right;margin-left:10px;margin-right:0;}.topbar div>ul.secondary-nav .menu-dropdown,.nav.secondary-nav .menu-dropdown,.topbar div>ul.secondary-nav .dropdown-menu,.nav.secondary-nav .dropdown-menu{right:0;border:0;}
+.topbar div>ul a.menu:hover,.nav a.menu:hover,.topbar div>ul li.open .menu,.nav li.open .menu,.topbar div>ul .dropdown-toggle:hover,.nav .dropdown-toggle:hover,.topbar div>ul .dropdown.open .dropdown-toggle,.nav .dropdown.open .dropdown-toggle{background:#444;background:rgba(255, 255, 255, 0.05);}
+.topbar div>ul .menu-dropdown,.nav .menu-dropdown,.topbar div>ul .dropdown-menu,.nav .dropdown-menu{background-color:#333;}.topbar div>ul .menu-dropdown a.menu,.nav .menu-dropdown a.menu,.topbar div>ul .dropdown-menu a.menu,.nav .dropdown-menu a.menu,.topbar div>ul .menu-dropdown .dropdown-toggle,.nav .menu-dropdown .dropdown-toggle,.topbar div>ul .dropdown-menu .dropdown-toggle,.nav .dropdown-menu .dropdown-toggle{color:#ffffff;}.topbar div>ul .menu-dropdown a.menu.open,.nav .menu-dropdown a.menu.open,.topbar div>ul .dropdown-menu a.menu.open,.nav .dropdown-menu a.menu.open,.topbar div>ul .menu-dropdown .dropdown-toggle.open,.nav .menu-dropdown .dropdown-toggle.open,.topbar div>ul .dropdown-menu .dropdown-toggle.open,.nav .dropdown-menu .dropdown-toggle.open{background:#444;background:rgba(255, 255, 255, 0.05);}
+.topbar div>ul .menu-dropdown li a,.nav .menu-dropdown li a,.topbar div>ul .dropdown-menu li a,.nav .dropdown-menu li a{color:#999;text-shadow:0 1px 0 rgba(0, 0, 0, 0.5);}.topbar div>ul .menu-dropdown li a:hover,.nav .menu-dropdown li a:hover,.topbar div>ul .dropdown-menu li a:hover,.nav .dropdown-menu li a:hover{background-color:#191919;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919));background-image:-moz-linear-gradient(top, #292929, #191919);background-image:-ms-linear-gradient(top, #292929, #191919);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919));background-image:-webkit-linear-gradient(top, #292929, #191919);background-image:-o-linear-gradient(top, #292929, #191919);background-image:linear-gradient(top, #292929, #191919);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0);color:#ffffff;}
+.topbar div>ul .menu-dropdown .active a,.nav .menu-dropdown .active a,.topbar div>ul .dropdown-menu .active a,.nav .dropdown-menu .active a{color:#ffffff;}
+.topbar div>ul .menu-dropdown .divider,.nav .menu-dropdown .divider,.topbar div>ul .dropdown-menu .divider,.nav .dropdown-menu .divider{background-color:#222;border-color:#444;}
+.topbar ul .menu-dropdown li a,.topbar ul .dropdown-menu li a{padding:4px 15px;}
+li.menu,.dropdown{position:relative;}
+a.menu:after,.dropdown-toggle:after{width:0;height:0;display:inline-block;content:"&darr;";text-indent:-99999px;vertical-align:top;margin-top:8px;margin-left:4px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
+.menu-dropdown,.dropdown-menu{background-color:#ffffff;float:left;display:none;position:absolute;top:40px;z-index:900;min-width:160px;max-width:220px;_width:160px;margin-left:0;margin-right:0;padding:6px 0;zoom:1;border-color:#999;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:0 1px 1px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.menu-dropdown li,.dropdown-menu li{float:none;display:block;background-color:none;}
+.menu-dropdown .divider,.dropdown-menu .divider{height:1px;margin:5px 0;overflow:hidden;background-color:#eee;border-bottom:1px solid #ffffff;}
+.topbar .dropdown-menu a,.dropdown-menu a{display:block;padding:4px 15px;clear:both;font-weight:normal;line-height:18px;color:#808080;text-shadow:0 1px 0 #ffffff;}.topbar .dropdown-menu a:hover,.dropdown-menu a:hover,.topbar .dropdown-menu a.hover,.dropdown-menu a.hover{background-color:#dddddd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));background-image:-moz-linear-gradient(top, #eeeeee, #dddddd);background-image:-ms-linear-gradient(top, #eeeeee, #dddddd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd));background-image:-webkit-linear-gradient(top, #eeeeee, #dddddd);background-image:-o-linear-gradient(top, #eeeeee, #dddddd);background-image:linear-gradient(top, #eeeeee, #dddddd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0);color:#404040;text-decoration:none;-webkit-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);}
+.open .menu,.dropdown.open .menu,.open .dropdown-toggle,.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);}
+.open .menu-dropdown,.dropdown.open .menu-dropdown,.open .dropdown-menu,.dropdown.open .dropdown-menu{display:block;}
+.tabs,.pills{margin:0 0 18px;padding:0;list-style:none;zoom:1;}.tabs:before,.pills:before,.tabs:after,.pills:after{display:table;content:"";zoom:1;}
+.tabs:after,.pills:after{clear:both;}
+.tabs>li,.pills>li{float:left;}.tabs>li>a,.pills>li>a{display:block;}
+.tabs{border-color:#ddd;border-style:solid;border-width:0 0 1px;}.tabs>li{position:relative;margin-bottom:-1px;}.tabs>li>a{padding:0 15px;margin-right:2px;line-height:34px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.tabs>li>a:hover{text-decoration:none;background-color:#eee;border-color:#eee #eee #ddd;}
+.tabs .active>a,.tabs .active>a:hover{color:#808080;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
+.tabs .menu-dropdown,.tabs .dropdown-menu{top:35px;border-width:1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
+.tabs a.menu:after,.tabs .dropdown-toggle:after{border-top-color:#999;margin-top:15px;margin-left:5px;}
+.tabs li.open.menu .menu,.tabs .open.dropdown .dropdown-toggle{border-color:#999;}
+.tabs li.open a.menu:after,.tabs .dropdown.open .dropdown-toggle:after{border-top-color:#555;}
+.pills a{margin:5px 3px 5px 0;padding:0 15px;line-height:30px;text-shadow:0 1px 1px #ffffff;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}.pills a:hover{color:#ffffff;text-decoration:none;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#00438a;}
+.pills .active a{color:#ffffff;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#0069d6;}
+.pills-vertical>li{float:none;}
+.tab-content>.tab-pane,.pill-content>.pill-pane,.tab-content>div,.pill-content>div{display:none;}
+.tab-content>.active,.pill-content>.active{display:block;}
+.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#f5f5f5;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;}
+.breadcrumb .divider{padding:0 5px;color:#bfbfbf;}
+.breadcrumb .active a{color:#404040;}
+.hero-unit{background-color:#f5f5f5;margin-bottom:30px;padding:60px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;}
+.hero-unit p{font-size:18px;font-weight:200;line-height:27px;}
+footer{margin-top:17px;padding-top:17px;border-top:1px solid #eee;}
+.page-header{margin-bottom:17px;border-bottom:1px solid #ddd;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}.page-header h1{margin-bottom:8px;}
+.btn.danger,.alert-message.danger,.btn.danger:hover,.alert-message.danger:hover,.btn.error,.alert-message.error,.btn.error:hover,.alert-message.error:hover,.btn.success,.alert-message.success,.btn.success:hover,.alert-message.success:hover,.btn.info,.alert-message.info,.btn.info:hover,.alert-message.info:hover{color:#ffffff;}
+.btn .close,.alert-message .close{font-family:Arial,sans-serif;line-height:18px;}
+.btn.danger,.alert-message.danger,.btn.error,.alert-message.error{background-color:#c43c35;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#c43c35 #c43c35 #882a25;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.success,.alert-message.success{background-color:#57a957;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#57a957 #57a957 #3d773d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.info,.alert-message.info{background-color:#339bb9;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#339bb9 #339bb9 #22697d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn{cursor:pointer;display:inline-block;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);padding:5px 14px 6px;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);color:#333;font-size:13px;line-height:normal;border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-webkit-transition:0.1s linear all;-moz-transition:0.1s linear all;-ms-transition:0.1s linear all;-o-transition:0.1s linear all;transition:0.1s linear all;}.btn:hover{background-position:0 -15px;color:#333;text-decoration:none;}
+.btn:focus{outline:1px dotted #666;}
+.btn.primary{color:#ffffff;background-color:#0064cd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));background-image:-moz-linear-gradient(top, #049cdb, #0064cd);background-image:-ms-linear-gradient(top, #049cdb, #0064cd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));background-image:-webkit-linear-gradient(top, #049cdb, #0064cd);background-image:-o-linear-gradient(top, #049cdb, #0064cd);background-image:linear-gradient(top, #049cdb, #0064cd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#0064cd #0064cd #003f81;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
+.btn.active,.btn :active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);}
+.btn.disabled{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn.large{font-size:15px;line-height:normal;padding:9px 14px 9px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
+.btn.small{padding:7px 9px 7px;font-size:11px;}
+:root .alert-message,:root .btn{border-radius:0 \0;}
+button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0;}
+.close{float:right;color:#000000;font-size:20px;font-weight:bold;line-height:13.5px;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;}.close:hover{color:#000000;text-decoration:none;filter:alpha(opacity=40);-khtml-opacity:0.4;-moz-opacity:0.4;opacity:0.4;}
+.alert-message{position:relative;padding:7px 15px;margin-bottom:18px;color:#404040;background-color:#eedc94;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));background-image:-moz-linear-gradient(top, #fceec1, #eedc94);background-image:-ms-linear-gradient(top, #fceec1, #eedc94);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));background-image:-webkit-linear-gradient(top, #fceec1, #eedc94);background-image:-o-linear-gradient(top, #fceec1, #eedc94);background-image:linear-gradient(top, #fceec1, #eedc94);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#eedc94 #eedc94 #e4c652;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);border-width:1px;border-style:solid;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);}.alert-message .close{margin-top:1px;*margin-top:0;}
+.alert-message a{font-weight:bold;color:#404040;}
+.alert-message.danger p a,.alert-message.error p a,.alert-message.success p a,.alert-message.info p a{color:#ffffff;}
+.alert-message h5{line-height:18px;}
+.alert-message p{margin-bottom:0;}
+.alert-message div{margin-top:5px;margin-bottom:2px;line-height:28px;}
+.alert-message .btn{-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);}
+.alert-message.block-message{background-image:none;background-color:#fdf5d9;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);padding:14px;border-color:#fceec1;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.alert-message.block-message ul,.alert-message.block-message p{margin-right:30px;}
+.alert-message.block-message ul{margin-bottom:0;}
+.alert-message.block-message li{color:#404040;}
+.alert-message.block-message .alert-actions{margin-top:5px;}
+.alert-message.block-message.error,.alert-message.block-message.success,.alert-message.block-message.info{color:#404040;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
+.alert-message.block-message.error{background-color:#fddfde;border-color:#fbc7c6;}
+.alert-message.block-message.success{background-color:#d1eed1;border-color:#bfe7bf;}
+.alert-message.block-message.info{background-color:#ddf4fb;border-color:#c6edf9;}
+.alert-message.block-message.danger p a,.alert-message.block-message.error p a,.alert-message.block-message.success p a,.alert-message.block-message.info p a{color:#404040;}
+.pagination{height:36px;margin:18px 0;}.pagination ul{float:left;margin:0;border:1px solid #ddd;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
+.pagination li{display:inline;}
+.pagination a{float:left;padding:0 14px;line-height:34px;border-right:1px solid;border-right-color:#ddd;border-right-color:rgba(0, 0, 0, 0.15);*border-right-color:#ddd;text-decoration:none;}
+.pagination a:hover,.pagination .active a{background-color:#c7eefe;}
+.pagination .disabled a,.pagination .disabled a:hover{background-color:transparent;color:#bfbfbf;}
+.pagination .next a{border:0;}
+.well{background-color:#f5f5f5;margin-bottom:20px;padding:19px;min-height:20px;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
+.modal-backdrop{background-color:#000000;position:fixed;top:0;left:0;right:0;bottom:0;z-index:10000;}.modal-backdrop.fade{opacity:0;}
+.modal-backdrop,.modal-backdrop.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}
+.modal{position:fixed;top:50%;left:50%;z-index:11000;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal .close{margin-top:7px;}
+.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
+.modal.fade.in{top:50%;}
+.modal-header{border-bottom:1px solid #eee;padding:5px 15px;}
+.modal-body{padding:15px;}
+.modal-body form{margin-bottom:0;}
+.modal-footer{background-color:#f5f5f5;padding:14px 15px 15px;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;zoom:1;margin-bottom:0;}.modal-footer:before,.modal-footer:after{display:table;content:"";zoom:1;}
+.modal-footer:after{clear:both;}
+.modal-footer .btn{float:right;margin-left:5px;}
+.modal .popover,.modal .twipsy{z-index:12000;}
+.twipsy{display:block;position:absolute;visibility:visible;padding:5px;font-size:11px;z-index:1000;filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}.twipsy.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}
+.twipsy.above .twipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
+.twipsy.left .twipsy-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
+.twipsy.below .twipsy-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
+.twipsy.right .twipsy-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
+.twipsy-inner{padding:3px 8px;background-color:#000000;color:white;text-align:center;max-width:200px;text-decoration:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.twipsy-arrow{position:absolute;width:0;height:0;}
+.popover{position:absolute;top:0;left:0;z-index:1000;padding:5px;display:none;}.popover.above .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
+.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
+.popover.below .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
+.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
+.popover .arrow{position:absolute;width:0;height:0;}
+.popover .inner{background:#000000;background:rgba(0, 0, 0, 0.8);padding:3px;overflow:hidden;width:280px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);}
+.popover .title{background-color:#f5f5f5;padding:9px 15px;line-height:1;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;border-bottom:1px solid #eee;}
+.popover .content{background-color:#ffffff;padding:14px;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover .content p,.popover .content ul,.popover .content ol{margin-bottom:0;}
+.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;}
+.label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;white-space:nowrap;background-color:#bfbfbf;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}.label.important{background-color:#c43c35;}
+.label.warning{background-color:#f89406;}
+.label.success{background-color:#46a546;}
+.label.notice{background-color:#62cffc;}
+.media-grid{margin-left:-20px;margin-bottom:0;zoom:1;}.media-grid:before,.media-grid:after{display:table;content:"";zoom:1;}
+.media-grid:after{clear:both;}
+.media-grid li{display:inline;}
+.media-grid a{float:left;padding:4px;margin:0 0 18px 20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}.media-grid a img{display:block;}
+.media-grid a:hover{border-color:#0069d6;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/custom.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/custom.css
new file mode 100644
index 00000000..b7df8c25
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/custom.css
@@ -0,0 +1,97 @@
+body, html, div, p, span, a, h1, h2, h3, h4, h5{
+ margin : 0;
+ padding : 0;
+}
+
+body, html{
+ width : 100%;
+}
+
+body{
+ color : white;
+ font-family : tahoma;
+ font-weight : lighter;
+ padding-top : 40px;
+}
+
+ body p{
+ font-size : 14px;
+ }
+
+ body p a{
+ font-size : 16px;
+ }
+
+h1 {
+ color : #E05E00;
+ font-style : italic;
+}
+
+a{
+ color : #E05E00;
+ text-decoration : none;
+}
+
+a:hover{
+ text-decoration : underline;
+}
+
+/* general */
+.clear {
+ clear: both;
+}
+
+/* Header */
+.brand{
+ color : #E05E00 !important;
+ font-family : georgia;
+ font-style : italic;
+}
+
+/* list stuff */
+#org{
+ background-color : white;
+ margin : 10px;
+ padding : 10px;
+}
+
+#show-list{
+ cursor : pointer;
+}
+
+/* bootstrap overrides */
+.alert-message{
+ margin: 2px 0;
+}
+
+.topbar{
+ position : absolute;
+}
+
+/* Custom chart styling */
+.jOrgChart {
+ margin : 10px;
+ padding : 20px;
+}
+
+/* Custom node styling */
+.jOrgChart .node {
+ font-weight : bold;
+ font-size : 14px;
+ background-color : #D5D6DB;
+ border-radius : 8px;
+ border : 5px solid gray;
+ color : #793a06;
+ -moz-border-radius : 8px;
+}
+ .node p{
+ font-family : tahoma;
+ font-size : 10px;
+ line-height : 11px;
+ padding : 2px;
+ }
+
+table {
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css
new file mode 100644
index 00000000..ffabe274
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/jquery.jOrgChart.css
@@ -0,0 +1,51 @@
+/* Basic styling */
+/* Draw the lines */
+.jOrgChart .line {
+ height : 20px;
+ width : 4px;
+}
+
+.jOrgChart .down {
+ background-color : black;
+ margin : 0px auto;
+}
+
+.jOrgChart .top {
+ border-top : 3px solid black;
+}
+
+.jOrgChart .left {
+ border-right : 2px solid black;
+}
+
+.jOrgChart .right {
+ border-left : 2px solid black;
+}
+
+/* node cell */
+.jOrgChart td {
+ text-align : center;
+ vertical-align : top;
+ padding : 0;
+}
+
+/* The node */
+.jOrgChart .node {
+ background-color : #35363B;
+ display : inline-block;
+ width : 120px;
+ height : 60px;
+ z-index : 10;
+ margin : 0 2px;
+}
+
+/* jQuery drag 'n drop */
+
+.drag-active {
+ border-style : dashed !important;
+}
+
+.drop-hover {
+ border-style : solid !important;
+ border-color : #E05E00 !important;
+}
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css
new file mode 100644
index 00000000..d44b3a22
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/css/prettify.css
@@ -0,0 +1 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example.html
new file mode 100644
index 00000000..543b0f92
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>jOrgChart - A jQuery OrgChart Plugin</title>
+ <link rel="stylesheet" href="css/bootstrap.min.css"/>
+ <link rel="stylesheet" href="css/jquery.jOrgChart.css"/>
+ <link rel="stylesheet" href="css/custom.css"/>
+ <link href="css/prettify.css" type="text/css" rel="stylesheet" />
+
+ <script type="text/javascript" src="prettify.js"></script>
+
+ <!-- jQuery includes -->
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
+
+ <script src="jquery.jOrgChart.js"></script>
+
+ <script>
+ jQuery(document).ready(function() {
+ $("#org").jOrgChart({
+ chartElement : '#chart',
+ dragAndDrop : true
+ });
+ });
+ </script>
+ </head>
+
+ <body onload="prettyPrint();">
+ <ul id="org" style="display:none">
+ <li>Product 1<br/>
+ <ul>
+ <li>Service 1<br/>
+ <ul>
+ <li>Resource 1<br/></li>
+ <li>Resource 2<br/></li>
+ <li>Resource 3<br/></li>
+ <li>Resource 4<br/></li>
+ <li>Resource 5<br/></li>
+ </ul>
+ </li>
+ <li>Service 6<br/></li>
+ <li>Service 7<br/>
+ <ul>
+ <li>Resource 8<br/></li>
+ <li>Resource 9<br/></li>
+ <li>Resource 10<br/></li>
+ <li>Resource 11<br/></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <div id="chart" class="orgChart"></div>
+
+ <script>
+ jQuery(document).ready(function() {
+
+ /* Custom jQuery for the example */
+ $("#show-list").click(function(e){
+ e.preventDefault();
+
+ $('#list-html').toggle('fast', function(){
+ if($(this).is(':visible')){
+ $('#show-list').text('Hide underlying list.');
+ $(".topbar").fadeTo('fast',0.9);
+ }else{
+ $('#show-list').text('Show underlying list.');
+ $(".topbar").fadeTo('fast',1);
+ }
+ });
+ });
+
+ $('#list-html').text($('#org').html());
+
+ $("#org").bind("DOMSubtreeModified", function() {
+ $('#list-html').text('');
+
+ $('#list-html').text($('#org').html());
+
+ prettyPrint();
+ });
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html
new file mode 100644
index 00000000..a2e3703d
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/example_vsp.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>jOrgChart - A jQuery OrgChart Plugin</title>
+ <link rel="stylesheet" href="css/bootstrap.min.css"/>
+ <link rel="stylesheet" href="css/jquery.jOrgChart.css"/>
+ <link rel="stylesheet" href="css/custom.css"/>
+ <link href="css/prettify.css" type="text/css" rel="stylesheet" />
+
+ <script type="text/javascript" src="prettify.js"></script>
+
+ <!-- jQuery includes -->
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
+
+ <script src="jquery.jOrgChart.js"></script>
+
+ <script>
+ jQuery(document).ready(function() {
+ $("#org").jOrgChart({
+ chartElement : '#chart',
+ dragAndDrop : true
+ });
+ });
+ </script>
+ </head>
+
+ <body onload="prettyPrint();">
+ <ul id="org" style="display:none">
+ <li>Trinity<br/>
+ <ul>
+ <li>Call Forwarding<br/>
+ <ul>
+ <li>Call Forwarding Busy<br/></li>
+ <li>Call Forwarding Always<br/></li>
+ <li>Call Forwarding Not Reachable<br/></li>
+ </ul>
+ </li>
+ <li>Dial Restrictions<br/>
+ <ul>
+ <li>Outgoing Calls<br/></li>
+ <li>Redirecting Calls<br/></li>
+ <li>Incoming Calls<br/></li>
+ </ul>
+ </li>
+ <li>Messaging<br/>
+ <ul>
+ <li>Voice Management<br/></li>
+ <li>Greetings<br/></li>
+ <li>Fax Messaging<br/></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+ <div id="chart" class="orgChart"></div>
+
+ <script>
+ jQuery(document).ready(function() {
+
+ /* Custom jQuery for the example */
+ $("#show-list").click(function(e){
+ e.preventDefault();
+
+ $('#list-html').toggle('fast', function(){
+ if($(this).is(':visible')){
+ $('#show-list').text('Hide underlying list.');
+ $(".topbar").fadeTo('fast',0.9);
+ }else{
+ $('#show-list').text('Show underlying list.');
+ $(".topbar").fadeTo('fast',1);
+ }
+ });
+ });
+
+ $('#list-html').text($('#org').html());
+
+ $("#org").bind("DOMSubtreeModified", function() {
+ $('#list-html').text('');
+
+ $('#list-html').text($('#org').html());
+
+ prettyPrint();
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png
new file mode 100644
index 00000000..3bbaf5ee
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/bkgd.png
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg
new file mode 100644
index 00000000..e79a0515
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/images/raspberry.jpg
Binary files differ
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js
new file mode 100644
index 00000000..89411b29
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/jquery.jOrgChart.js
@@ -0,0 +1,267 @@
+/**
+ * jQuery org-chart/tree plugin.
+ *
+ * Author: Wes Nolte
+ * http://twitter.com/wesnolte
+ *
+ * Based on the work of Mark Lee
+ * http://www.capricasoftware.co.uk
+ *
+ * Copyright (c) 2011 Wesley Nolte
+ * Dual licensed under the MIT and GPL licenses.
+ *
+ */
+(function($) {
+
+ $.fn.jOrgChart = function(options) {
+ var opts = $.extend({}, $.fn.jOrgChart.defaults, options);
+ var $appendTo = $(opts.chartElement);
+
+ // build the tree
+ $this = $(this);
+ var $container = $("<div class='" + opts.chartClass + "'/>");
+ if($this.is("ul")) {
+ buildNode($this.find("li:first"), $container, 0, opts);
+ }
+ else if($this.is("li")) {
+ buildNode($this, $container, 0, opts);
+ }
+ $appendTo.append($container);
+
+ // add drag and drop if enabled
+ if(opts.dragAndDrop){
+ $('div.node').draggable({
+ cursor : 'move',
+ distance : 40,
+ helper : 'clone',
+ opacity : 0.8,
+ revert : true,
+ revertDuration : 100,
+ snap : 'div.node.expanded',
+ snapMode : 'inner',
+ stack : 'div.node'
+ });
+
+ $('div.node').droppable({
+ accept : '.node',
+ activeClass : 'drag-active',
+ hoverClass : 'drop-hover'
+ });
+
+ // Drag start event handler for nodes
+ $('div.node').bind("dragstart", function handleDragStart( event, ui ){
+
+ var sourceNode = $(this);
+ sourceNode.parentsUntil('.node-container')
+ .find('*')
+ .filter('.node')
+ .droppable('disable');
+ });
+
+ // Drag stop event handler for nodes
+ $('div.node').bind("dragstop", function handleDragStop( event, ui ){
+
+ /* reload the plugin */
+ $(opts.chartElement).children().remove();
+ $this.jOrgChart(opts);
+ });
+
+ // Drop event handler for nodes
+ $('div.node').bind("drop", function handleDropEvent( event, ui ) {
+ var sourceNode = ui.draggable;
+ var targetNode = $(this);
+
+ // finding nodes based on plaintext and html
+ // content is hard!
+ var targetLi = $('li').filter(function(){
+
+ li = $(this).clone()
+ .children("ul,li")
+ .remove()
+ .end();
+ var attr = li.attr('id');
+ if (typeof attr !== 'undefined' && attr !== false) {
+ return li.attr("id") == targetNode.attr("id");
+ }
+ else {
+ return li.html() == targetNode.html();
+ }
+
+ });
+
+ var sourceLi = $('li').filter(function(){
+
+ li = $(this).clone()
+ .children("ul,li")
+ .remove()
+ .end();
+ var attr = li.attr('id');
+ if (typeof attr !== 'undefined' && attr !== false) {
+ return li.attr("id") == sourceNode.attr("id");
+ }
+ else {
+ return li.html() == sourceNode.html();
+ }
+
+ });
+
+ var sourceliClone = sourceLi.clone();
+ var sourceUl = sourceLi.parent('ul');
+
+ if(sourceUl.children('li').size() > 1){
+ sourceLi.remove();
+ }else{
+ sourceUl.remove();
+ }
+
+ var id = sourceLi.attr("id");
+
+ if(targetLi.children('ul').size() >0){
+ if (typeof id !== 'undefined' && id !== false) {
+ targetLi.children('ul').append('<li id="'+id+'">'+sourceliClone.html()+'</li>');
+ }else{
+ targetLi.children('ul').append('<li>'+sourceliClone.html()+'</li>');
+ }
+ }else{
+ if (typeof id !== 'undefined' && id !== false) {
+ targetLi.append('<ul><li id="'+id+'">'+sourceliClone.html()+'</li></ul>');
+ }else{
+ targetLi.append('<ul><li>'+sourceliClone.html()+'</li></ul>');
+ }
+ }
+
+ }); // handleDropEvent
+
+ } // Drag and drop
+ };
+
+ // Option defaults
+ $.fn.jOrgChart.defaults = {
+ chartElement : 'body',
+ depth : -1,
+ chartClass : "jOrgChart",
+ dragAndDrop: false
+ };
+
+ // Method that recursively builds the tree
+ function buildNode($node, $appendTo, level, opts) {
+ var $table = $("<table cellpadding='0' cellspacing='0' border='0'/>");
+ var $tbody = $("<tbody/>");
+
+ // Construct the node container(s)
+ var $nodeRow = $("<tr/>").addClass("node-cells");
+ var $nodeCell = $("<td/>").addClass("node-cell").attr("colspan", 2);
+ var $childNodes = $node.children("ul:first").children("li");
+ var $nodeDiv;
+
+ if($childNodes.length > 1) {
+ $nodeCell.attr("colspan", $childNodes.length * 2);
+ }
+ // Draw the node
+ // Get the contents - any markup except li and ul allowed
+ var $nodeContent = $node.clone()
+ .children("ul,li")
+ .remove()
+ .end()
+ .html();
+
+ var new_node_id = $node.attr("id");
+ if (typeof new_node_id !== 'undefined' && new_node_id !== false) {
+ $nodeDiv = $("<div>").addClass("node").attr("id", $node.attr("id")).append($nodeContent);
+ }else{
+ $nodeDiv = $("<div>").addClass("node").append($nodeContent);
+ }
+
+ // Expand and contract nodes
+ if ($childNodes.length > 0) {
+ $nodeDiv.click(function() {
+ var $this = $(this);
+ var $tr = $this.closest("tr");
+
+ if($tr.hasClass('contracted')){
+ $this.css('cursor','n-resize');
+ $tr.removeClass('contracted').addClass('expanded');
+ $tr.nextAll("tr").css('visibility', '');
+ }else{
+ $this.css('cursor','s-resize');
+ $tr.removeClass('expanded').addClass('contracted');
+ $tr.nextAll("tr").css('visibility', 'hidden');
+ }
+ });
+ }
+
+ $nodeCell.append($nodeDiv);
+ $nodeRow.append($nodeCell);
+ $tbody.append($nodeRow);
+
+ if($childNodes.length > 0) {
+ // if it can be expanded then change the cursor
+ $nodeDiv.css('cursor','n-resize').addClass('expanded');
+
+ // recurse until leaves found (-1) or to the level specified
+ if(opts.depth == -1 || (level+1 < opts.depth)) {
+ var $downLineRow = $("<tr/>");
+ var $downLineCell = $("<td/>").attr("colspan", $childNodes.length*2);
+ $downLineRow.append($downLineCell);
+
+ // draw the connecting line from the parent node to the horizontal line
+ $downLine = $("<div></div>").addClass("line down");
+ $downLineCell.append($downLine);
+ $tbody.append($downLineRow);
+
+ // Draw the horizontal lines
+ var $linesRow = $("<tr/>");
+ $childNodes.each(function() {
+ var $left = $("<td>&nbsp;</td>").addClass("line left top");
+ var $right = $("<td>&nbsp;</td>").addClass("line right top");
+ $linesRow.append($left).append($right);
+ });
+
+ // horizontal line shouldn't extend beyond the first and last child branches
+ $linesRow.find("td:first")
+ .removeClass("top")
+ .end()
+ .find("td:last")
+ .removeClass("top");
+
+ $tbody.append($linesRow);
+ var $childNodesRow = $("<tr/>");
+ $childNodes.each(function() {
+ var $td = $("<td class='node-container'/>");
+ $td.attr("colspan", 2);
+ // recurse through children lists and items
+ buildNode($(this), $td, level+1, opts);
+ $childNodesRow.append($td);
+ });
+
+ }
+ $tbody.append($childNodesRow);
+ }
+
+ // any classes on the LI element get copied to the relevant node in the tree
+ // apart from the special 'collapsed' class, which collapses the sub-tree at this point
+ if ($node.attr('class') != undefined) {
+ var classList = $node.attr('class').split(/\s+/);
+ $.each(classList, function(index,item) {
+ if (item == 'collapsed') {
+ $nodeRow.nextAll('tr').css('display', 'none');
+ $nodeRow.removeClass('expanded');
+ $nodeRow.addClass('contracted');
+ $nodeDiv.css('cursor','s-resize');
+ } else {
+ $nodeDiv.addClass(item);
+ }
+ });
+ }
+
+ $table.append($tbody);
+ $appendTo.append($table);
+
+ /* Prevent trees collapsing if a link inside a node is clicked */
+ $nodeDiv.children('a').click(function(e){
+ console.log(e);
+ e.stopPropagation();
+ });
+ };
+
+})(jQuery);
diff --git a/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/prettify.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/prettify.js
new file mode 100644
index 00000000..eef5ad7e
--- /dev/null
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/fusion/sample/org_chart/prettify.js
@@ -0,0 +1,28 @@
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
+f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
+(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
+{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
+t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
+"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
+l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
+q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
+q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
+"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
+a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
+for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
+m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
+a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
+j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
+H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
+J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
+I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
+["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
+/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
+["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
+hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
+!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
+250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
+PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-1.10.2.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-1.10.2.js
index c5c64825..c5c64825 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-1.10.2.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-1.10.2.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-ui.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-ui.js
index 31ee9cd8..31ee9cd8 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery-ui.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery-ui.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery.mask.min.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery.mask.min.js
index 984b5b02..984b5b02 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/js/jquery.mask.min.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/jquery.mask.min.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/js/modalService.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/modalService.js
index 69f01f42..69f01f42 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/js/modalService.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/modalService.js
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/js/search.js b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/search.js
index 70cb166b..c7b7ba65 100644
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/js/search.js
+++ b/ecomp-sdk/epsdk-app-overlay/src/main/webapp/static/js/search.js
@@ -1,5 +1,6 @@
-
+// var app=angular.module("abs", ["att.abs"]);
+
app.directive('afterRender', [ function() {
var def = {
diff --git a/ecomp-sdk/epsdk-core/.gitignore b/ecomp-sdk/epsdk-core/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-core/README.md b/ecomp-sdk/epsdk-core/README.md
new file mode 100644
index 00000000..d2320a3d
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/README.md
@@ -0,0 +1,168 @@
+# ECOMP Portal SDK Core
+
+## Overview
+
+This is the Maven project for the ECOMP Portal SDK Core library,
+which is distributed as epsdk-core-N.N.N.jar. This library
+requires Hibernate and Spring, and provides many features
+such as data access, session management, logging, on-boarding
+and more. Most of these features are demonstrated in the
+ECOMP SDK web application.
+
+## Release Notes
+
+### OpenECOMP Distributions
+
+Build 1.2.8, ?? ??? 2017
+* put new entries here *
+
+Build 1.2.7, 10 Apr 2017
+- Moved all annotated controllers to epsdk-common from epsdk-core
+- Update shared context service for revised Portal endpoint path; drop separate property
+
+Build 1.2.6, 23 Mar 2017
+- DE273039 Adjust MenuListController to get OrgUserID from session, not cookie
+
+Build 1.2.5, 16 Mar 2017
+- No changes
+
+Build 1.2.4, 10 Mar 2017
+- No changes
+
+Build 1.2.3, 8 Mar 2017
+- No changes
+
+Build 1.2.2, 6 Mar 2017
+- US872039 Revise Element Map feature to drop absolute filesystem path in property file
+
+Build 1.2.1, 2 Mar 2017
+- US845636 Extend user-import controller to detect and return message on failure
+- Move UEB/Cambria library and demonstration use classes into core (from FW)
+- Exclude all log4j dependencies in core pom file
+- Remove references to ATTUID in UserUtils.java comments
+- Remove logback.xml from src/main/resources
+- Extend HibernateMappingLocatable and HibernateConfiguration to allow config of packages to scan
+- Extend MenuListController.java to send content-type application/json
+
+Build 1.2.0, 9 Feb 2017
+- Change group to org.openecomp.ecompsdkos; restart version numbering for open-source distribution
+
+### Closed-Source Distributions
+
+The following history is preserved for the benefit of partner application teams.
+
+Version 4.3.5, 2 Feb 2017
+- DE260606 Extend role controller to check existing roles when creating a new one
+
+Version 4.3.4 13 Jan 2017
+- No changes
+
+Version 4.3.3, 11 Jan 2017
+- DE239065 Adjust fix that initializes the start & stop timestamp on first call to loggers
+
+Version 4.3.2, 9 Jan 2017
+- DE261061 Remove System.out.println() debug output statements
+
+Version 4.3.1, 3 Jan 2017
+- DE239065 Initialize the start & stop timestamp on first call to the audit and metrics loggers
+
+Version 4.2.1, 15 Dec 2016
+- DE255409 trim trailing space on values fetched from Portal, System properties
+- DE257028 add a constant value and modify the hibernate mapping to AuditLog class
+
+Version 4.1.4, 22 Nov 2016
+- DE250794 add trace-level logging methods to EELFLoggerDelegate
+- US811188 add constants to AuditLog class
+
+Version 4.1.3, 14 Nov 2016
+- DE250319 All controllers that require user info should be Restricted within session
+- Restore exclusion in pom to avoid pulling in outdated HttpServlet and other jars,
+ which cause compile errors in SDK-App depending on Maven repository contents.
+
+Version 4.1.2, 14 Nov 2016
+- US777777 enhance network map mime type in ElementModelController
+
+Version 4.1.1, 3 Nov 2016
+- No changes.
+
+Version 3.3.3, 13 Oct 2016
+- DE240192 show useful message if cache configuration file is missing
+- DE238612 new property app\_base\_url for apps using WebJunction address
+
+Version 3.3.2, 26 Sep 2016
+- US710856 remove stray System.out.println statement and minor logging improvements.
+
+Version 3.3.1, 22 Sep 2016
+- DE224872 fix errors shown in browser on profile page
+- Show Quantum license information at top-right of screen
+- Moved R Notebook controllers to SDK-Workflow project
+- US710856 updated aspect-oriented programming (AOP) logging support,
+ including the EELFLoggerDelegate and other classes.
+- Updated favorites, functional menu, menu list, and profile controllers.
+- Updated EELF Library to 0.0.5, the latest available version.
+- US772823 Introduce Audit Log
+- Remove some JFree code as open-source prep
+- DE224872 fix errors shown in browser on profile page
+- DE216279 fix behavior of pagination on profile page
+
+Version 3.2.2, 4 Aug 2016
+- New feature: R Cloud integration via a guard notebook
+- New feature: fetch functional menu via REST
+- Remove Spring annotation from OnBoardingApiServiceImpl class
+- Extend EELFLoggerDelegate with methods that accept a throwable
+- Revise logger to remove class name from MDC after logging
+- DE215237, fix script error on menu admin page
+- DE214174, refresh menu contents after edit
+- Moved MockApplicationContextTestSuite class into core, out of sdk-app
+- Support application name at top of left menu
+- DE210771, fix the multiple/invalid role assignment behavior
+- New class for the error message returned as JSON
+- Return error as JSON in case of unauthenticated request
+- Removed database creation scripts used by ECOMP Portal
+- Improved the shared context feature
+
+Version 3.2.1, 12 Jul 2016
+ - Use EELF loggers to be compliant with ECOMP project guidelines
+ - Log controller requests to the audit log
+ - Add alarm codes to the error log
+ - Correct popup issue in profile page
+ - Change the functional menu to show only user's first name
+ - Show 20 items by default in the functional menu
+ - Refresh the left menu after items are edited
+ - Correct problem that prevented deletion of a role
+ - Correct problem of missing country on Webphone import
+ - US693240, support link-only onboarding
+ - Extend logging to use instance_uuid from properties file
+ - Show favorites menu items
+ - Include logging ApplicationCodes.properties file in jar
+ - Use EELFLoggingDelegate to ensure class names are shown
+ - DE205174, correct problems in role functions
+ - Remove Apache commons logging
+ - Create new users as active (not inactive)
+ - Move database scripts for SDK-App out of core, into app
+ - Adjust OnBoardingApiServiceImpl to return null if user not found (for Portal)
+ - Fix ASE editor position
+ - Correct validation of menu entries
+
+Version 3.1.1, 15 Jun 2016
+ - Add custom logging filter to reduce UEB logging quantity
+ - Fix admin/menu popup behavior
+ - Correct hibernate mapping for user class and table
+
+Version 2.2.0, 14 Jun 2016
+ - Analytics and Workflow factored out of SDK-core library
+ - Add application logout feature
+ - Enhancements for DROOLS
+ - Move DROOLs files to core and add library to POM
+ - Revise logging for compliance with ECOMP guidelines
+ - Revise error responses from REST interface to be JSON
+ - Adjust HTML template for profile page
+ - Rename war directory to src/main/webapp
+ - Show error information if user is not found
+ - Split database scripts into Portal/SDK versions
+ - Add client for new shared context feature in Portal
+ - Revise favorites implementation to use app-to-app REST comms
+ - Exclude commons-logging and log4j libraries in POM
+ - Remove try/catch/discard block for exception in DataAccessServiceImpl
+
+
diff --git a/ecomp-sdk/epsdk-core/license/licenses.properties b/ecomp-sdk/epsdk-core/license/licenses.properties
new file mode 100644
index 00000000..4b0e28e7
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/license/licenses.properties
@@ -0,0 +1 @@
+my_license=My license
diff --git a/ecomp-sdk/epsdk-core/license/my_license/header.txt b/ecomp-sdk/epsdk-core/license/my_license/header.txt
new file mode 100644
index 00000000..c026b6b7
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/license/my_license/header.txt
@@ -0,0 +1,11 @@
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/ecomp-sdk/epsdk-core/license/my_license/license.txt b/ecomp-sdk/epsdk-core/license/my_license/license.txt
new file mode 100644
index 00000000..bf326153
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/license/my_license/license.txt
@@ -0,0 +1,4 @@
+name=my_license
+description=<null>
+licenseURL=<null>
+headerURL=<null> \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-core/pom.xml b/ecomp-sdk/epsdk-core/pom.xml
new file mode 100644
index 00000000..354f9bb7
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/pom.xml
@@ -0,0 +1,406 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-core</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>jar</packaging>
+ <name>ECOMP Portal SDK Core</name>
+ <description>Core SDK library with controllers, interceptors, utilities, etc.</description>
+ <url>https://wiki.onap.org/display/DW/Portal</url>
+
+ <!-- properties are inherited from parent -->
+ <properties>
+ <drools.version>6.4.0.Final</drools.version>
+ </properties>
+
+ <!-- repositories are inherited from parent -->
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <skipTests>${skiptests}</skipTests>
+ <includes>
+ <include>**/Test*.java</include>
+ <include>**/*Test.java</include>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <systemPropertyVariables>
+ <container.classpath>classpath:</container.classpath>
+ </systemPropertyVariables>
+ </configuration>
+
+ </plugin>
+
+ <!--
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>license-maven-plugin</artifactId>
+ <version>1.10</version>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ <licenseName>my_license</licenseName>
+ <licenseResolver>${project.baseUri}/license</licenseResolver>
+ <inceptionYear>2017</inceptionYear>
+ <organizationName>AT&amp;T Intellectual Property</organizationName>
+ <projectName>eCOMP Portal SDK</projectName>
+ <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage>
+ <processStartTag>================================================================================</processStartTag>
+ <sectionDelimiter>================================================================================</sectionDelimiter>
+ <processEndTag>================================================================================</processEndTag>
+ <roots>
+ <root>src/main</root>
+ <root>src/test</root>
+ </roots>
+ <excludes>
+ <exclude>*.png</exclude>
+ <exclude>*.drl</exclude>
+ <exclude>*.gif</exclude>
+ <exclude>*.jpeg</exclude>
+ <exclude>*.jpg</exclude>
+ <exclude>*.bmp</exclude>
+ <exclude>*.ico</exclude>
+ <exclude>*.svg</exclude>
+ </excludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>first</id>
+ <goals>
+ <goal>update-file-header</goal>
+ </goals>
+ <phase>process-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+
+ -->
+ </plugins>
+ </build>
+
+ <dependencies>
+
+ <!-- internal -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-fw</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- Drools -->
+ <dependency>
+ <groupId>org.drools</groupId>
+ <artifactId>drools-compiler</artifactId>
+ <version>${drools.version}</version>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${springframework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ <version>1.3.0.RELEASE</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ <version>1.8.9</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjweaver</artifactId>
+ <version>1.8.9</version>
+ </dependency>
+
+
+ <!-- Hibernate -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${hibernate.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>5.1.3.Final</version>
+ </dependency>
+ <!-- Servlet+JSP+JSTL -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <!-- bridge to implement commons-logging using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <!-- bridge to implement log4j using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ <version>0.9.5.2</version>
+ </dependency>
+ <!-- Apache Tiles -->
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-core</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-jsp</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ <!-- Yaml -->
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>1.15</version>
+ </dependency>
+ <!-- Mapper -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.22</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jcs</groupId>
+ <artifactId>jcs</artifactId>
+ <version>1.3</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-websocket</artifactId>
+ <version>8.0.28</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>concurrent</groupId>
+ <artifactId>concurrent</artifactId>
+ <version>1.3.2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+
+ <!-- Raptor required Libraries -->
+ <!-- for static charts -->
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.10</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <!-- Quartz -->
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>2.2.1</version>
+ <exclusions>
+ <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
+ <exclusion>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk16</artifactId>
+ <version>1.45</version>
+ </dependency>
+
+ <!-- Elastic Search -->
+ <dependency>
+ <groupId>org.elasticsearch</groupId>
+ <artifactId>elasticsearch</artifactId>
+ <version>2.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>io.searchbox</groupId>
+ <artifactId>jest</artifactId>
+ <version>2.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+
+ <!-- UEB was originally named Cambria -->
+ <dependency>
+ <groupId>com.att.nsa</groupId>
+ <artifactId>cambriaClient</artifactId>
+ <version>0.0.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>apache-log4j-extras</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+<!-- <dependency>
+ <groupId>com.att.nsa</groupId>
+ <artifactId>highlandParkCore</artifactId>
+ <version>0.3.2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency> -->
+
+ </dependencies>
+
+</project>
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/FusionObject.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/FusionObject.java
index 00866388..8258913f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/FusionObject.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/FusionObject.java
@@ -34,7 +34,6 @@ package org.openecomp.portalsdk.core;
* Copyright: Copyright (c) 2007
* </p>
*
- *
* @version 1.1
*/
public interface FusionObject {
@@ -63,7 +62,6 @@ public interface FusionObject {
* Copyright: Copyright (c) 2007
* </p>
*
- *
* @version 1.1
*/
public class Utilities {
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/auth/LoginStrategy.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/auth/LoginStrategy.java
new file mode 100644
index 00000000..0378101a
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/auth/LoginStrategy.java
@@ -0,0 +1,131 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.auth;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.portalsdk.core.command.LoginBean;
+import org.openecomp.portalsdk.core.menu.MenuProperties;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.service.LoginService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.AppUtils;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.util.WebUtils;
+
+public abstract class LoginStrategy {
+
+ public static final String DEFAULT_SUCCESS_VIEW = "welcome";
+ public static final String DEFAULT_FAILURE_VIEW = "login";
+ private static final String JSESSIONID = "JSESSIONID";
+
+ public static final String EP_SERVICE = "EPService";
+ public static final String USER_ID = "UserId";
+ public static final String ERROR_MESSAGE_KEY = "error";
+
+ @Autowired
+ private LoginService loginService;
+
+ public abstract ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception;
+
+ public abstract String getUserId(HttpServletRequest request) throws PortalAPIException;
+
+ public ModelAndView doExternalLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ invalidateExistingSession(request);
+
+ Map<String, String> model = new HashMap<String, String>();
+ LoginBean commandBean = new LoginBean();
+ String loginId = request.getParameter("loginId");
+ String password = request.getParameter("password");
+ commandBean.setLoginId(loginId);
+ commandBean.setLoginPwd(password);
+ HashMap additionalParamsMap = new HashMap();
+
+ // Get the client device type and pass it into LoginService for audit
+ // logging.
+ /**
+ * ClientDeviceType clientDevice = (ClientDeviceType)request.getAttribut
+ * (SystemProperties.getProperty(SystemProperties.CLIENT_DEVICE_ATTRIBUTE_NAME));
+ * additionalParamsMap.put(Parameters.PARAM_CLIENT_DEVICE,
+ * clientDevice);
+ **/
+ commandBean = loginService.findUser(commandBean,
+ (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), additionalParamsMap);
+
+ if (commandBean.getUser() == null) {
+ String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
+ : "login.error.external.invalid";
+ model.put("error", loginErrorMessage);
+
+ String[] errorCodes = new String[1];
+ errorCodes[0] = loginErrorMessage;
+
+ return new ModelAndView("login_external", "model", model);
+
+ } else {
+ // store the currently logged in user's information in the session
+ UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
+ commandBean.getBusinessDirectMenu(),
+ SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR));
+ initateSessionMgtHandler(request);
+
+ // user has been authenticated, now take them to the welcome page
+ // return new ModelAndView("redirect:/profile_search");
+ return new ModelAndView("redirect:welcome.htm");
+
+ }
+ }
+
+ protected void invalidateExistingSession(HttpServletRequest request){
+ request.getSession().invalidate();
+ }
+
+ protected String getJessionId(HttpServletRequest request) {
+ Cookie ep = WebUtils.getCookie(request, JSESSIONID);
+ if (ep == null) {
+ return request.getSession().getId();
+ }
+ return ep.getValue();
+
+ }
+
+ protected void initateSessionMgtHandler(HttpServletRequest request) {
+ String jSessionId = getJessionId(request);
+ PortalTimeoutHandler.sessionCreated(jSessionId, jSessionId, AppUtils.getSession(request));
+ }
+
+ public LoginService getLoginService() {
+ return loginService;
+ }
+
+ public void setLoginService(LoginService loginService) {
+ this.loginService = loginService;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java
new file mode 100644
index 00000000..37df8db1
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java
@@ -0,0 +1,193 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.command;
+
+import java.util.Set;
+
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.domain.support.FusionCommand;
+
+public class LoginBean extends FusionCommand {
+
+ private String loginId;
+ private String loginPwd;
+ private String hrid;
+ private String userid;
+ private String siteAccess;
+ private String loginErrorMessage;
+
+ private User user;
+ @SuppressWarnings("rawtypes")
+ private Set menu;
+ @SuppressWarnings("rawtypes")
+ private Set businessDirectMenu;
+
+ /**
+ * getLoginId
+ *
+ * @return String
+ */
+ public String getLoginId() {
+ return loginId;
+ }
+
+ /**
+ * getLoginPwd
+ *
+ * @return String
+ */
+ public String getLoginPwd() {
+ return loginPwd;
+ }
+
+ /**
+ * getMenu
+ *
+ * @return Set
+ */
+ @SuppressWarnings("rawtypes")
+ public Set getMenu() {
+ return menu;
+ }
+
+ /**
+ * getUser
+ *
+ * @return User
+ */
+ public User getUser() {
+ return user;
+ }
+
+ /**
+ * getHrid
+ *
+ * @return String
+ */
+ public String getHrid() {
+ return hrid;
+ }
+
+ /**
+ * getSiteAccess
+ *
+ * @return String
+ */
+ public String getSiteAccess() {
+ return siteAccess;
+ }
+
+ /**
+ * getBusinessDirectMenu
+ *
+ * @return Set
+ */
+ @SuppressWarnings("rawtypes")
+ public Set getBusinessDirectMenu() {
+ return businessDirectMenu;
+ }
+
+ /**
+ * getLoginErrorMessage
+ *
+ * @return String
+ */
+ public String getLoginErrorMessage() {
+ return loginErrorMessage;
+ }
+
+ /**
+ * setLoginId
+ *
+ * @param loginId String
+ */
+ public void setLoginId(String loginId) {
+ this.loginId = loginId;
+ }
+
+ /**
+ * setLoginPwd
+ *
+ * @param loginPwd String
+ */
+ public void setLoginPwd(String loginPwd) {
+ this.loginPwd = loginPwd;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void setMenu(Set menu) {
+ this.menu = menu;
+ }
+
+ /**
+ * setUser
+ *
+ * @param user User
+ */
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ /**
+ * setHrid
+ *
+ * @param hrid String
+ */
+ public void setHrid(String hrid) {
+ this.hrid = hrid;
+ }
+
+ /**
+ * setSiteAccess
+ *
+ * @param siteAccess String
+ */
+ public void setSiteAccess(String siteAccess) {
+ this.siteAccess = siteAccess;
+ }
+
+ /**
+ * setBusinessDirectMenu
+ *
+ * @param businessDirectMenu Set
+ */
+ @SuppressWarnings("rawtypes")
+ public void setBusinessDirectMenu(Set businessDirectMenu) {
+ this.businessDirectMenu = businessDirectMenu;
+ }
+
+ /**
+ * setLoginErrorMessage
+ *
+ * @param loginErrorMessage String
+ */
+ public void setLoginErrorMessage(String loginErrorMessage) {
+ this.loginErrorMessage = loginErrorMessage;
+ }
+
+ public String getUserid() {
+ return userid;
+ }
+
+ public void setUserid(String userid) {
+ this.userid = userid;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java
index 541d9f71..541d9f71 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostDroolsBean.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java
index b07b8fed..68806b39 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/PostSearchBean.java
@@ -61,12 +61,13 @@ public class PostSearchBean extends SearchBase {
private String[] postFinancialLocCode;
+ @SuppressWarnings("rawtypes")
public PostSearchBean() {
this(null);
} // PostSearchBean
@SuppressWarnings("rawtypes")
- public PostSearchBean(List items) {
+ public PostSearchBean(List items) {
super(items);
user = new User();
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java
index 7230add8..fb6c2eab 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/UserRowBean.java
@@ -23,11 +23,11 @@ import org.openecomp.portalsdk.core.domain.User;
public class UserRowBean extends User {
- /**
+ /**
*
*/
private static final long serialVersionUID = -2724597119083972190L;
- private String sessionId;
+ private String sessionId;
private String lastAccess;
private String remaining;
private String loginTime;
@@ -82,4 +82,4 @@ public class UserRowBean extends User {
public void setLastLoginTime(String lastLoginTime) {
LastLoginTime = lastLoginTime;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java
index 6fb60aa7..f2f5408b 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchBase.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.core.command.support;
-import java.util.List;
+import java.util.*;
import org.openecomp.portalsdk.core.domain.support.FusionCommand;
@@ -56,9 +56,10 @@ public abstract class SearchBase extends FusionCommand {
private String showResult = "Y";
private SearchResult searchResult = null;
-
+ private boolean sortingUpdated;
+
@SuppressWarnings("rawtypes")
- public SearchBase(List items) {
+ public SearchBase(List items) {
searchResult = (items == null) ? (new SearchResult()) : (new SearchResult(items));
} // SearchBase
@@ -227,6 +228,7 @@ public abstract class SearchBase extends FusionCommand {
}
public void setSortingUpdated(boolean sortingUpdated) {
+ this.sortingUpdated = sortingUpdated;
}
public void setPageNo(int pageNo) {
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java
new file mode 100644
index 00000000..286b39cb
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java
@@ -0,0 +1,67 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.command.support;
+
+import java.util.*;
+
+@SuppressWarnings("rawtypes")
+public class SearchResult extends ArrayList implements java.io.Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -451947878984459011L;
+ private int pageNo = 0;
+ private int pageSize = 50;
+ private int dataSize = -1;
+
+ private String accessType = null;
+
+ //private boolean empty = true; // Overrides collections [isEmpty] with searchResult present/not present logic
+
+
+ public SearchResult() {}
+
+ @SuppressWarnings("unchecked")
+ public SearchResult(List items) {
+ super(items);
+ } // SearchResult
+
+ /*public SearchResult(boolean empty) {
+ this();
+ this.empty = empty;
+ } // SearchResult*/
+
+
+ public int getPageNo() { return pageNo; }
+ public int getPageSize() { return pageSize; }
+ public int getDataSize() { return dataSize; }
+
+ public int getSize() { return size(); } // for Struts bean property access
+ //public boolean isEmpty() { return empty; }
+
+ public String getAccessType() { return accessType; }
+
+ public void setPageNo(int pageNo) { this.pageNo=pageNo; }
+ public void setPageSize(int pageSize) { this.dataSize=pageSize; }
+ public void setDataSize(int dataSize) { this.dataSize=dataSize; }
+
+ public void setAccessType(String accessType) { this.accessType = accessType; }
+
+} // SearchResult
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java
index 3a4753e3..118b0e56 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppConfig.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -26,13 +26,14 @@ import javax.sql.DataSource;
import org.openecomp.portalsdk.core.interceptor.ResourceInterceptor;
import org.openecomp.portalsdk.core.interceptor.SessionTimeoutInterceptor;
+import org.openecomp.portalsdk.core.lm.FusionLicenseManager;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.format.AppMessagesEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.menu.MenuBuilder;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
import org.openecomp.portalsdk.core.service.DataAccessService;
import org.openecomp.portalsdk.core.service.DataAccessServiceImpl;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.AppUtils;
import org.openecomp.portalsdk.core.web.support.UserUtils;
@@ -200,8 +201,6 @@ public class AppConfig extends WebMvcConfigurerAdapter implements Configurable,
.setMaxPoolSize(Integer.parseInt(SystemProperties.getProperty(SystemProperties.DB_MAX_POOL_SIZE)));
dataSource.setIdleConnectionTestPeriod(
Integer.parseInt(SystemProperties.getProperty(SystemProperties.IDLE_CONNECTION_TEST_PERIOD)));
- dataSource.setTestConnectionOnCheckout(true);
- dataSource.setPreferredTestQuery("SELECT 1");
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, "Error initializing database, verify database settings in properties file: "
+ UserUtils.getStackTrace(e),AlarmSeverityEnum.CRITICAL);
@@ -291,7 +290,20 @@ public class AppConfig extends WebMvcConfigurerAdapter implements Configurable,
this.excludeUrlPathsForSessionTimeout = excludeUrlPathsForSessionTimeout;
}
+ /**
+ * Creates and returns a new instance of a {@link FusionLicenseManager}.
+ *
+ * @return New instance of {@link FusionLicenseManager}.
+// @Bean
+ public FusionLicenseManager fusionLicenseManager() {
+ return new FusionLicenseManager(new LicenseableClassImpl());
+ }
+ */
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+ */
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
appApplicationContext = applicationContext;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java
index df0d56d6..82e449f1 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/AppInitializer.java
@@ -66,4 +66,4 @@ public abstract class AppInitializer extends AbstractAnnotationConfigDispatcherS
return new String[] { "/" };
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java
index 9585e45d..9585e45d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/Configurable.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java
new file mode 100644
index 00000000..8a3459d1
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java
@@ -0,0 +1,139 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.conf;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.hibernate.SessionFactory;
+import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.orm.hibernate4.HibernateTransactionManager;
+import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+@Configuration
+@EnableTransactionManagement
+public class HibernateConfiguration {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HibernateConfiguration.class);
+
+ @Autowired
+ private HibernateMappingLocatable hbMappingLocatable;
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+ LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(dataSource);
+ sessionFactory.setPackagesToScan(hbMappingLocatable.getPackagesToScan());
+ sessionFactory.setHibernateProperties(getHibernateProperties());
+ sessionFactory.setMappingLocations(hbMappingLocatable.getMappingLocations());
+ return sessionFactory;
+ }
+
+ /**
+ * Builds a properties object with Hibernate properties in te system.properties file.
+ *
+ * @return Properties object
+ */
+ private Properties getHibernateProperties() {
+ Properties properties = new Properties();
+ properties.put("hibernate.dialect", SystemProperties.getProperty(SystemProperties.HB_DIALECT));
+ properties.put("hibernate.show_sql", SystemProperties.getProperty(SystemProperties.HB_SHOW_SQL));
+ return properties;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Bean
+ public Map dataSourceMap() throws Exception {
+ Connection conn = null;
+ Statement stmt = null;
+ Map<String, ComboPooledDataSource> dataSourceMap = new HashMap<String, ComboPooledDataSource>();
+
+ try {
+ conn = dataSource.getConnection();
+ stmt = conn.createStatement();
+ String sql;
+ sql = "SELECT schema_id,datasource_type,connection_url,user_name,password,driver_class,min_pool_size,max_pool_size,idle_connection_test_period FROM schema_info";
+ ResultSet rs = stmt.executeQuery(sql);
+
+ while (rs.next()) {
+ ComboPooledDataSource dataSource = new ComboPooledDataSource();
+ dataSource.setDriverClass(rs.getString("driver_class"));
+ dataSource.setJdbcUrl(rs.getString("connection_url"));
+ dataSource.setUser(rs.getString("user_name"));
+ dataSource.setPassword(rs.getString("password"));
+ dataSource.setMinPoolSize(rs.getInt("min_pool_size"));
+ dataSource.setMaxPoolSize(rs.getInt("max_pool_size"));
+ dataSource.setIdleConnectionTestPeriod(rs.getInt("idle_connection_test_period"));
+ dataSourceMap.put(rs.getString("schema_id"), dataSource);
+ }
+ rs.close();
+ stmt.close();
+ conn.close();
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "Error initializing database, verify database settings in properties file: " + e.getMessage(),
+ AlarmSeverityEnum.CRITICAL);
+ e.printStackTrace();
+ dataSourceMap = null;
+ throw e;
+ } finally {
+ try {
+ if (stmt != null)
+ stmt.close();
+ } catch (SQLException se2) {
+ }
+ try {
+ if (conn != null)
+ conn.close();
+ } catch (SQLException se) {
+ se.printStackTrace();
+ }
+ }
+
+ return dataSourceMap;
+ }
+
+ @Bean
+ @Autowired
+ public HibernateTransactionManager transactionManager(SessionFactory s) {
+ HibernateTransactionManager txManager = new HibernateTransactionManager();
+ txManager.setSessionFactory(s);
+ return txManager;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java
new file mode 100644
index 00000000..94aed111
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java
@@ -0,0 +1,43 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.conf;
+
+import org.springframework.core.io.Resource;
+
+/**
+ * Defines methods used by developers to supply Hibernate configuration.
+ */
+public interface HibernateMappingLocatable {
+
+ /**
+ * Gets Hibernate mapping locations.
+ *
+ * @return Array of Resource objects (usually ClassPathResource that's a
+ * file) which contain Hibernate mapping information.
+ */
+ public Resource [] getMappingLocations();
+
+ /**
+ * Gets package names.
+ *
+ * @return Array of Java package names to scan for classes with Hibernate annotations.
+ */
+ public String [] getPackagesToScan();
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java
index c7820115..c7820115 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/FusionBaseController.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java
index 2b2e3426..2b2e3426 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedBaseController.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java
index d11c7d76..d11c7d76 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/RestrictedRESTfulBaseController.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java
index 78bf4c51..78bf4c51 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/controller/UnRestrictedBaseController.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java
index 0b274068..0b274068 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/AbstractDao.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java
index 0094072c..0094072c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDao.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java
index 8d8d0d6e..4dd2711e 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/ProfileDaoImpl.java
@@ -23,6 +23,7 @@ import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
+import org.openecomp.portalsdk.core.dao.AbstractDao;
import org.openecomp.portalsdk.core.domain.Profile;
import org.springframework.stereotype.Repository;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java
index cd9e644b..cd9e644b 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/hibernate/ModelOperationsCommon.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java
index 75b3c80b..086a8da0 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/dao/support/FusionDao.java
@@ -20,6 +20,7 @@
package org.openecomp.portalsdk.core.dao.support;
import org.hibernate.SessionFactory;
+
import org.openecomp.portalsdk.core.FusionObject;
public class FusionDao implements FusionObject {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/App.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/App.java
index 6e8e6c80..6e8e6c80 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/App.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/App.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java
new file mode 100644
index 00000000..1b1326b6
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java
@@ -0,0 +1,106 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.domain;
+
+import java.util.Date;
+
+import org.openecomp.portalsdk.core.domain.support.DomainVo;
+
+public class AuditLog extends DomainVo {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ public static final String CD_ACTIVITY_LOGIN = "login";
+ public static final String CD_ACTIVITY_LOGOUT = "logout";
+ public static final String CD_ACTIVITY_MOBILE_LOGIN = "mobile_login";
+ public static final String CD_ACTIVITY_MOBILE_LOGOUT = "mobile_logout";
+
+ /*-------Profile activities -----------*/
+ public static final String CD_ACTIVITY_ROLE_ADD = "add_role";
+ public static final String CD_ACTIVITY_ROLE_REMOVE = "remove_role";
+ public static final String CD_ACTIVITY_CHILD_ROLE_ADD = "add_child_role";
+ public static final String CD_ACTIVITY_CHILD_ROLE_REMOVE = "remove_child_role";
+ public static final String CD_ACTIVITY_ROLE_ADD_FUNCTION = "add_role_function";
+ public static final String CD_ACTIVITY_ROLE_REMOVE_FUNCTION = "remove_role_function";
+ public static final String CD_ACTIVITY_USER_ROLE_ADD = "add_user_role";
+ public static final String CD_ACTIVITY_USER_ROLE_REMOVE = "remove_user_role";
+
+ /*Audit activities*/
+ public static final String CD_ACTIVITY_FUNCTIONAL_ACCESS = "functional_access";
+ public static final String CD_ACTIVITY_TAB_ACCESS = "tab_access";
+ public static final String CD_ACTIVITY_APP_ACCESS = "app_access";
+ public static final String CD_ACTIVITY_LEFT_MENU_ACCESS = "left_menu_access";
+
+
+ private String activityCode;
+ private String affectedRecordId;
+ private String comments;
+ private Date auditDate;
+ private Long userId;
+
+ public AuditLog() {
+ setCreated(new Date());
+ }
+
+ public String getActivityCode() {
+ return activityCode;
+ }
+
+ public String getComments() {
+ return comments;
+ }
+
+ public String getAffectedRecordId() {
+ return affectedRecordId;
+ }
+
+ public void setActivityCode(String activityCode) {
+ this.activityCode = activityCode;
+ }
+
+ public void setComments(String comments) {
+ this.comments = comments;
+ }
+
+ public void setAffectedRecordId(String affectedRecordId) {
+ this.affectedRecordId = affectedRecordId;
+ }
+
+ public Date getAuditDate() {
+ return auditDate;
+ }
+
+ public void setAuditDate(Date auditDate) {
+ this.auditDate = auditDate;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java
new file mode 100644
index 00000000..42122dbd
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java
@@ -0,0 +1,124 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.domain;
+
+import java.util.*;
+
+import org.openecomp.portalsdk.core.domain.support.DomainVo;
+
+public class BroadcastMessage extends DomainVo {
+
+ /**
+ *
+ */
+
+ private static final long serialVersionUID = 1L;
+ public BroadcastMessage() {
+ }
+
+ public static final String ID_MESSAGE_LOCATION_LOGIN = "10";
+ public static final String ID_MESSAGE_LOCATION_WELCOME = "20";
+
+ private String messageText;
+ private Integer locationId;
+ private Date startDate;
+ private Date endDate;
+ private Integer sortOrder;
+ private Boolean active;
+ private String siteCd;
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public Date getEndDate() {
+ return endDate;
+ }
+
+ public Integer getLocationId() {
+ return locationId;
+ }
+
+ public String getMessageText() {
+ return messageText;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+ public Date getStartDate() {
+ return startDate;
+ }
+
+ public String getSiteCd() {
+ return siteCd;
+ }
+
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+
+ public void setEndDate(Date endDate) {
+ this.endDate = endDate;
+ }
+
+ public void setLocationId(Integer locationId) {
+ this.locationId = locationId;
+ }
+
+ public void setMessageText(String messageText) {
+ this.messageText = messageText;
+ }
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public void setStartDate(Date startDate) {
+ this.startDate = startDate;
+ }
+
+ public void setSiteCd(String siteCd) {
+ this.siteCd = siteCd;
+ }
+
+
+ public int compareTo(Object obj){
+ Integer c1 = getLocationId();
+ Integer c2 = ((BroadcastMessage)obj).getLocationId();
+
+ if (c1.compareTo(c2) == 0) {
+ c1 = getSortOrder();
+ c2 = ((BroadcastMessage)obj).getSortOrder();
+
+ if (c1.compareTo(c2) == 0) {
+ Long c3 = getId();
+ Long c4 = ((BroadcastMessage)obj).getId();
+
+ return c3.compareTo(c4);
+ }
+ }
+
+ return c1.compareTo(c2);
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java
index 9d173996..9d173996 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/DomainVo.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java
index e2c1f46d..d9aaf43d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FnMenu.java
@@ -30,12 +30,11 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
* @version 1.0
*/
public class FnMenu extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
-
- public FnMenu() {}
+ public FnMenu() {}
private Integer menuId;
private String label;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java
index dc1b8d4c..dc1b8d4c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/FusionVo.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java
new file mode 100644
index 00000000..f20eb4a8
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java
@@ -0,0 +1,187 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.domain;
+
+import java.util.Set;
+
+import org.openecomp.portalsdk.core.domain.support.FusionCommand;
+
+@SuppressWarnings("rawtypes")
+public class LoginBean extends FusionCommand {
+
+ private String loginId;
+ private String loginPwd;
+ private String hrid;
+ private String orgUserId;
+ private String siteAccess;
+ private String loginErrorMessage;
+
+ private User user;
+ private Set menu;
+ private Set businessDirectMenu;
+
+ /**
+ * getLoginId
+ *
+ * @return String
+ */
+ public String getLoginId() {
+ return loginId;
+ }
+
+ /**
+ * getLoginPwd
+ *
+ * @return String
+ */
+ public String getLoginPwd() {
+ return loginPwd;
+ }
+
+ /**
+ * getMenu
+ *
+ * @return Set
+ */
+ public Set getMenu() {
+ return menu;
+ }
+
+ /**
+ * getUser
+ *
+ * @return User
+ */
+ public User getUser() {
+ return user;
+ }
+
+ /**
+ * getHrid
+ *
+ * @return String
+ */
+ public String getHrid() {
+ return hrid;
+ }
+
+ /**
+ * getSiteAccess
+ *
+ * @return String
+ */
+ public String getSiteAccess() {
+ return siteAccess;
+ }
+
+ /**
+ * getBusinessDirectMenu
+ *
+ * @return Set
+ */
+ public Set getBusinessDirectMenu() {
+ return businessDirectMenu;
+ }
+
+ /**
+ * getLoginErrorMessage
+ *
+ * @return String
+ */
+ public String getLoginErrorMessage() {
+ return loginErrorMessage;
+ }
+
+ public String getOrgUserId() {
+ return orgUserId;
+ }
+
+ /**
+ * setLoginId
+ *
+ * @param loginId String
+ */
+ public void setLoginId(String loginId) {
+ this.loginId = loginId;
+ }
+
+ /**
+ * setLoginPwd
+ *
+ * @param loginPwd String
+ */
+ public void setLoginPwd(String loginPwd) {
+ this.loginPwd = loginPwd;
+ }
+
+ public void setMenu(Set menu) {
+ this.menu = menu;
+ }
+
+ /**
+ * setUser
+ *
+ * @param user User
+ */
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ /**
+ * setHrid
+ *
+ * @param hrid String
+ */
+ public void setHrid(String hrid) {
+ this.hrid = hrid;
+ }
+
+ /**
+ * setSiteAccess
+ *
+ * @param siteAccess String
+ */
+ public void setSiteAccess(String siteAccess) {
+ this.siteAccess = siteAccess;
+ }
+
+ /**
+ * setBusinessDirectMenu
+ *
+ * @param businessDirectMenu Set
+ */
+ public void setBusinessDirectMenu(Set businessDirectMenu) {
+ this.businessDirectMenu = businessDirectMenu;
+ }
+
+ /**
+ * setLoginErrorMessage
+ *
+ * @param loginErrorMessage String
+ */
+ public void setLoginErrorMessage(String loginErrorMessage) {
+ this.loginErrorMessage = loginErrorMessage;
+ }
+
+ public void setOrgUserId(String orgUserId) {
+ this.orgUserId = orgUserId;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java
new file mode 100644
index 00000000..aa7d036c
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java
@@ -0,0 +1,85 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.domain;
+
+import java.io.Serializable;
+
+import org.openecomp.portalsdk.core.domain.support.NameValueId;
+
+public class Lookup extends FusionVo implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private NameValueId nameValueId = new NameValueId();
+
+ public Lookup() {}
+
+ public Lookup(String label, String value) {
+ this();
+ setLabel(label);
+ setValue(value);
+ }
+
+ public String getValue() {
+ return getNameValueId().getVal();
+ }
+
+ public String getLabel() {
+ return getNameValueId().getLab();
+ }
+
+ public void setValue(String value) {
+ getNameValueId().setVal(value);
+ }
+
+ public void setLabel(String label) {
+ getNameValueId().setLab(label);
+ }
+
+ public NameValueId getNameValueId() {
+ return nameValueId;
+ }
+
+ public void setNameValueId(NameValueId nameValueId) {
+ this.nameValueId = nameValueId;
+ }
+
+ // required by ZK for to set the selectedItems of Listboxes (used heavily for <select>-style drop-downs)
+ public int hashCode() {
+ int hash = getValue().hashCode();
+ hash = hash + getLabel().hashCode();
+
+ return hash;
+ }
+
+ public boolean equals( Object obj ) {
+ boolean equivalent = false;
+
+ Lookup lookup = (Lookup)obj;
+ if( lookup.getValue().equals(getValue()) && lookup.getLabel().equals(getLabel())) {
+ equivalent = true;
+ }
+
+ return equivalent;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java
index 946df58a..f0237892 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuCountry.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.core.domain;
-import org.openecomp.portalsdk.core.domain.support.DomainVo;
+
+import org.openecomp.portalsdk.core.domain.support.*;
+
/**
* <p>luCountry.java</p>
@@ -28,14 +30,13 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
*
* @version 1.0
*/
-public class LuCountry extends DomainVo{
+public class LuCountry extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
-
- LuCountry() {}
+ LuCountry() {}
public String getCountry() {
return country;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java
index 283ab011..09d25b28 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuState.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.core.domain;
-import org.openecomp.portalsdk.core.domain.support.DomainVo;
+
+import org.openecomp.portalsdk.core.domain.support.*;
+
/**
* <p>State.java</p>
@@ -30,12 +32,12 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
*/
public class LuState extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- LuState() {}
+ LuState() {}
public String getState() {
return state;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java
index e1a7a474..bc0d9326 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/LuTimeZone.java
@@ -19,7 +19,9 @@
*/
package org.openecomp.portalsdk.core.domain;
-import org.openecomp.portalsdk.core.domain.support.DomainVo;
+
+import org.openecomp.portalsdk.core.domain.support.*;
+
/**
* <p>LuTimeZone.java</p>
@@ -30,12 +32,12 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
*/
public class LuTimeZone extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- LuTimeZone() {}
+ LuTimeZone() {}
public String getName() {
return name;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java
index 6d57e6d0..471edf86 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Menu.java
@@ -23,12 +23,12 @@ package org.openecomp.portalsdk.core.domain;
import org.openecomp.portalsdk.core.domain.support.DomainVo;
public class Menu extends DomainVo {
- /**
+
+ /**
*
*/
private static final long serialVersionUID = 1L;
-
- public Menu() {}
+ public Menu() {}
public String getAction() {
return action;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java
index a5758b80..c1cefb0b 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/MenuData.java
@@ -19,13 +19,11 @@
*/
package org.openecomp.portalsdk.core.domain;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
-@SuppressWarnings("rawtypes")
public class MenuData extends Menu {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
@@ -57,5 +55,18 @@ public class MenuData extends Menu {
return (c1 == null || c2 == null) ? 1 : ((c1.compareTo(c2) == 0) ? 1 : c1.compareTo(c2));
}
+
+ public String getActiveAsString(){
+ return String.valueOf(isActive());
+ }
+
+ public String getParentIdAsString(){
+ return String.valueOf(getParentId());
+ }
+
+ public String getSeparatorAsString(){
+ return String.valueOf(isSeparator());
+ }
+
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java
index b5592021..b5592021 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Profile.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Role.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Role.java
index 474bbb95..a56fe672 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Role.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/Role.java
@@ -34,14 +34,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
*
* @version 1.0
*/
-@SuppressWarnings("rawtypes")
public class Role extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- private String name;
+ private String name;
private boolean active;
private Integer priority;
@@ -93,6 +92,7 @@ public class Role extends DomainVo {
this.priority = priority;
}
+
public void setChildRoles(Set childRoles) {
this.childRoles = childRoles;
}
@@ -100,19 +100,19 @@ public class Role extends DomainVo {
public void setParentRoles(Set parentRoles) {
this.parentRoles = parentRoles;
}
-
+
@SuppressWarnings("unchecked")
- public void addRoleFunction(RoleFunction roleFunction) {
+ public void addRoleFunction(RoleFunction roleFunction) {
this.roleFunctions.add(roleFunction);
}
@SuppressWarnings("unchecked")
- public void addChildRole(Role role) {
+ public void addChildRole(Role role) {
this.childRoles.add(role);
}
@SuppressWarnings("unchecked")
- public void addParentRole(Role role) {
+ public void addParentRole(Role role) {
this.parentRoles.add(role);
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java
index c0387fda..e6735763 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/RoleFunction.java
@@ -30,11 +30,12 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
* @version 1.0
*/
public class RoleFunction extends DomainVo {
- /**
+
+ /**
*
*/
private static final long serialVersionUID = 1L;
- public RoleFunction() {}
+ public RoleFunction() {}
public String getName() {
return name;
@@ -64,6 +65,7 @@ public class RoleFunction extends DomainVo {
}
private String code;
- private String name;
+ private String name;
+ private String editUrl;
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java
index 53edefe4..e0f35db0 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessible.java
@@ -23,11 +23,11 @@ import java.io.Serializable;
public class UrlsAccessible extends FusionVo implements Serializable {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- private UrlsAccessibleKey urlsAccessibleKey = new UrlsAccessibleKey();
+ private UrlsAccessibleKey urlsAccessibleKey = new UrlsAccessibleKey();
public UrlsAccessible() {}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java
index f1cec496..fc0b36ce 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UrlsAccessibleKey.java
@@ -19,16 +19,16 @@
*/
package org.openecomp.portalsdk.core.domain;
-import java.io.Serializable;
+import java.io.*;
public class UrlsAccessibleKey implements Serializable {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- private String url;
+ private String url;
private String functionCd;
public UrlsAccessibleKey() {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/User.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/User.java
index e6c4a178..06c4d59e 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/User.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/User.java
@@ -35,14 +35,13 @@ import org.openecomp.portalsdk.core.domain.support.DomainVo;
*
* @version 1.0
*/
-@SuppressWarnings("rawtypes")
public class User extends DomainVo {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- private Long orgId;
+ private Long orgId;
private Long managerId;
private String firstName;
private String middleInitial;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java
index 5c2c383f..cfadd995 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserApp.java
@@ -19,6 +19,9 @@
*/
package org.openecomp.portalsdk.core.domain;
+import java.util.Set;
+import java.util.TreeSet;
+
// Generated Aug 27, 2014 5:51:36 PM by Hibernate Tools 3.4.0.CR1
/**
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java
index 9458b90a..9458b90a 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/UserAppId.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java
index 57e474c2..0f6c3876 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/sessionmgt/TimeoutVO.java
@@ -60,4 +60,4 @@ public class TimeoutVO implements Comparable<TimeoutVO>{
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java
index a78d7bfa..a78d7bfa 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Attribute.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java
index eaeab84d..eaeab84d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/CollaborateList.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java
index 7d52af40..88a9fa71 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Container.java
@@ -204,7 +204,7 @@ public class Container {
for (int i = 0; i < numOfRows; i++) {
if (containerRowCol!= null && containerRowCol.containsKey(i+String.valueOf(j))) {
height+=containerRowCol.get(i+String.valueOf(j)).computeSize().getHeight();
- System.out.println("My C name "+this.getName()+":"+containerRowCol.get(i+String.valueOf(j)).computeSize().getHeight());
+ //System.out.println("My C name "+this.getName()+":"+containerRowCol.get(i+String.valueOf(j)).computeSize().getHeight());
}
else if (elementRowCol!=null && elementRowCol.containsKey(i+String.valueOf(j)))
height+=elementRowCol.get(String.valueOf(i)+String.valueOf(j)).computeSize().getHeight();
@@ -224,8 +224,8 @@ public class Container {
}
size.setHeight(height);
// System.out.println("C name "+this.getName()+" height "+height);
- System.out.println("test C height "+this.getName()+" height "+height+" (numOfRows-1)*interEleH "+(numOfRows-1)*interEleH+
- " interEleToContainerH "+interEleToContainerH/2);
+ // System.out.println("test C height "+this.getName()+" height "+height+" (numOfRows-1)*interEleH "+(numOfRows-1)*interEleH+
+ // " interEleToContainerH "+interEleToContainerH/2);
return size;
}
@@ -281,8 +281,8 @@ public class Container {
p.x = j*interEleWd+xsum+this.getP().getX()+interEleToContainerWd-0.8;
}else {
p.x = j*interEleWd+xsum+this.getP().getX()+interEleToContainerWd;
- System.out.println("element name "+e.getName()+" j*interEleWd "+j*interEleWd
- +" xsum " +xsum+"this.getP().getX() "+this.getP().getX()+" interEleToContainerWd " +interEleToContainerWd+" p.x "+p.x);
+ //System.out.println("element name "+e.getName()+" j*interEleWd "+j*interEleWd
+ // +" xsum " +xsum+"this.getP().getX() "+this.getP().getX()+" interEleToContainerWd " +interEleToContainerWd+" p.x "+p.x);
}
ysum = 0;
for (int k=0; k<i; k++) {
@@ -311,8 +311,8 @@ public class Container {
// +" ysum " +ysum+" i*interEleH "+i*interEleH+" interEleToContainerH " +interEleToContainerH);
if (e.getName().equals("")) {
p.y = this.getP().getY()+ysum+i*interEleH+(interEleToContainerH);
- System.out.println("test element name "+this.getName()+" Container height "+this.computeSize().getHeight()+" this.getP().getY() "+this.getP().getY()
- +" ysum " +ysum+" i*interEleH "+i*interEleH+" interEleToContainerH-3 " +interEleToContainerH+" p.y "+p.y);
+ //System.out.println("test element name "+this.getName()+" Container height "+this.computeSize().getHeight()+" this.getP().getY() "+this.getP().getY()
+ // +" ysum " +ysum+" i*interEleH "+i*interEleH+" interEleToContainerH-3 " +interEleToContainerH+" p.y "+p.y);
}else
p.y = this.getP().getY()+ysum+i*interEleH+interEleToContainerH;
// System.out.println(e.getName()+"My contain this.getP().getY() "+this.getP().getY()
@@ -320,8 +320,8 @@ public class Container {
}
xsum+= e.computeSize().getWidth();
e.setP(p);
- System.out.println("my element name "+e.getName()+" e.getP().getX() "+e.getP().getX());
- System.out.println();
+ //System.out.println("my element name "+e.getName()+" e.getP().getX() "+e.getP().getX());
+ //System.out.println();
}
}
xsum = 0;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java
index 3e742785..a21ff395 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Domain.java
@@ -17,9 +17,9 @@
* limitations under the License.
* ================================================================================
*/
-
package org.openecomp.portalsdk.core.domain.support;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -234,12 +234,12 @@ public class Domain {
// System.out.println("Container height "+containerRowCol.get(String.valueOf(k)+ String.valueOf(j)).getName()+
// ":"+" "+containerRowCol.get(String.valueOf(k)+ String.valueOf(j)).computeSize().getHeight());
else if (j>0 && containerRowCol.containsKey(String.valueOf(k)+ String.valueOf(j-1)) &&
- !containerRowCol.get(String.valueOf(i)+ String.valueOf(j)).getName().equals("Alpharetta")) {
+ !containerRowCol.get(String.valueOf(i)+ String.valueOf(j)).getName().equals("AIC - Alpharetta")) {
ysum+= containerRowCol.get(String.valueOf(k)+ String.valueOf(j-1)).computeSize().getHeight();
}
}
- System.out.println("C name "+c.getName()+" ysum "+ysum+" domainToLayoutH "+domainToLayoutH+" this.computeSize().getHeight() "+
- this.computeSize().getHeight()+" domainToContH "+domainToContH+" interContH "+interContH);
+ //System.out.println("C name "+c.getName()+" ysum "+ysum+" domainToLayoutH "+domainToLayoutH+" this.computeSize().getHeight() "+
+ // this.computeSize().getHeight()+" domainToContH "+domainToContH+" interContH "+interContH);
p.y = domainToLayoutH+ysum+this.computeSize().getHeight()+
domainToContH+i*interContH;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java
index 645a9132..369cc4cd 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/DomainVo.java
@@ -31,14 +31,9 @@ import org.openecomp.portalsdk.core.domain.FusionVo;
/* Super class from which all data objects descend */
-@SuppressWarnings("rawtypes")
public class DomainVo extends FusionVo implements Serializable, Cloneable, Comparable {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- protected Long id;
+ protected Long id;
protected Date created;
protected Date modified;
protected Long createdId;
@@ -116,14 +111,6 @@ public class DomainVo extends FusionVo implements Serializable, Cloneable, Compa
return auditTrail;
}
-/* public void addAuditTrailLog(AuditLog auditLog) {
- if (getAuditTrail() == null) {
- setAuditTrail(new HashSet());
- }
-
- getAuditTrail().add(auditLog);
- }*/
-
public Object clone() throws CloneNotSupportedException {
return super.clone();
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java
index 84f929fd..567487de 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Element.java
@@ -19,6 +19,10 @@
*/
package org.openecomp.portalsdk.core.domain.support;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
public class Element {
public String id;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java
index cebaeddc..0e22d639 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/ElementDetails.java
@@ -19,6 +19,9 @@
*/
package org.openecomp.portalsdk.core.domain.support;
+import java.util.HashMap;
+import java.util.Map;
+
public class ElementDetails {
public String logical_group;
public String display_longname;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java
index 6ac85b6f..6ac85b6f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/FusionCommand.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java
new file mode 100644
index 00000000..0d78e5dd
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java
@@ -0,0 +1,1209 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.domain.support;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+public class Layout {
+ //width of the screen
+// double width;
+ //height of the screen;
+// double height;
+ // Total number of domains present on the screen and assume that
+
+ public Map<String,Domain> domainRowCol;
+
+ Map<String,Domain> originalDomainRowCol;
+
+ //Horizontal space between a pair of domains
+ double interDomainWd;
+ //Vertical space between a pair of domains
+ double interDomainH;
+ //Computing the co-ordinates of any domain
+ int numberofRowsofDomains;
+
+ int numberofColsofDomains;
+
+ Map<String, Domain> collapsedDomains;
+
+ List<Domain> collapsedDomainsNewList;
+
+ public List<Domain> getCollapsedDomainsNewList() {
+ return collapsedDomainsNewList;
+ }
+
+ public void setCollapsedDomainsNewList(List<Domain> collapsedDomainsNewList) {
+ this.collapsedDomainsNewList = collapsedDomainsNewList;
+ }
+
+ public void setCollapsedDomains(Map<String, Domain> collapsedDomains) {
+ this.collapsedDomains = collapsedDomains;
+ }
+
+ public Map<String, Domain> getCollapsedDomains() {
+ return collapsedDomains;
+ }
+
+ public int getNumberofColsofDomains() {
+ return numberofColsofDomains;
+ }
+
+ public void setNumberofColsofDomains(int numberofColsofDomains) {
+ this.numberofColsofDomains = numberofColsofDomains;
+ }
+
+ public Layout(Map<String,Domain> domainRowCol, double interDomainWd, double interDomainH,
+ int numberofRowsofDomains, int numberofColsofDomains) {
+
+ this.domainRowCol = domainRowCol;
+ this.interDomainWd = interDomainWd;
+ this.interDomainH = interDomainH;
+ this.numberofRowsofDomains = numberofRowsofDomains;
+ this.numberofColsofDomains = numberofColsofDomains;
+ this.collapsedDomains = new HashMap<String, Domain>();
+ this.originalDomainRowCol = new TreeMap<String,Domain>();
+ //nline
+ this.collapsedDomainsNewList = new ArrayList<Domain>();
+ }
+
+ public Map<String, Domain> getDomainRowCol() {
+ return domainRowCol;
+ }
+
+ public void setDomainRowCol(Map<String, Domain> domainRowCol) {
+ this.domainRowCol = domainRowCol;
+ }
+
+
+ public void computeDomainPositions() {
+ double xsum = 0;
+ double domainTolayout = 10.6;
+ for (int i=0; i< numberofRowsofDomains; i++){
+ for (int j=0; j<numberofColsofDomains; j++){
+ if (domainRowCol.containsKey(String.valueOf(i)+ String.valueOf(j))) {
+ Domain d = domainRowCol.get(String.valueOf(i)+ String.valueOf(j));
+ Position p = new Position();
+ if (j==0)
+ //p.x = (j+1)* (interDomainWd+2.6) + xsum;
+ p.x = domainTolayout;
+ else
+ // p.x = (j+1)* interDomainWd + xsum;
+ p.x = j*interDomainWd + xsum + domainTolayout;
+ if (getCollapsedDomainsNewList().size() > 0)
+ p.x+= accountForPlusSpaceBefore(d);
+ xsum+=d.computeSize().getWidth();
+ double ysum=0;
+ for (int k=0; k<i; k++) {
+ if (domainRowCol.containsKey(String.valueOf(k)+ String.valueOf(j)))
+ ysum+= domainRowCol.get(String.valueOf(k)+ String.valueOf(j)).computeSize().getHeight();
+ }
+ // p.y = domainToLayoutH+ysum+this.computeSize().getHeight()+
+ // domainToContH+i*interContH;
+ p.y = (i+1)* interDomainH + ysum;
+ d.setP(p);
+
+ }
+ }
+ xsum = 0;
+ }
+ }
+
+ public void computeDomainPositionsModified() {
+ //double xsum = 0;
+ // double domainTolayout = 10.6;
+ for (int i=0; i< numberofRowsofDomains; i++){
+ for (int j=0; j<numberofColsofDomains; j++){
+ if (domainRowCol.containsKey(String.valueOf(i)+ String.valueOf(j))) {
+ Domain d = domainRowCol.get(String.valueOf(i)+ String.valueOf(j));
+ Position p = new Position();
+ Map<String,Container> enclosedContainers = d.getContainerRowCol();
+ for (Map.Entry<String, Container> entry : enclosedContainers.entrySet()) {
+ if (entry.getKey().equals("00")) {
+ double containerX = entry.getValue().getP().getX();
+ p.x = containerX;
+ double ysum=0;
+ for (int k=0; k<i; k++) {
+ if (domainRowCol.containsKey(String.valueOf(k)+ String.valueOf(j)))
+ ysum+= domainRowCol.get(String.valueOf(k)+ String.valueOf(j)).computeSize().getHeight();
+ }
+ p.y = (i+1)* interDomainH + ysum;
+ d.setP(p);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+ public Layout collapseDomainModified(String domainsToCollapse) {
+
+ if(domainsToCollapse == null || domainsToCollapse.isEmpty())
+ return null;
+
+ Map<String,Domain> updatedRC = new HashMap<String, Domain>();
+
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
+ // System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
+
+ Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
+
+ List<Domain> collapsedDomainNewL = getCollapsedDomainsNewList();
+
+
+ if (collapsedDomainNewL.size() == 0) {
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
+ // System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+ }
+
+
+ Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
+
+ int colToDelete = 0;
+ for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
+ if (entry.getValue().getName().equals(domainsToCollapse)) {
+ if (entry.getValue().isIndexChanged()) {
+ collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
+
+ }
+ //Domain toRemove = entry.getValue();
+ else {
+ collapsedDomainMap.put(entry.getKey(),entry.getValue());
+ }
+
+ collapsedDomainNewL.add(entry.getValue());
+ setNumberofColsofDomains(getNumberofColsofDomains()-1);
+ updatedRC.remove(entry.getKey());
+ colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+
+ for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
+ updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
+ //System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
+ if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
+ updatedRCSortedTrunc.remove(rmv.getKey());
+ }
+ }
+
+
+ /* for (Map.Entry<String, Domain> entry : updatedRCSortedTrunc.entrySet()) {
+ System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }*/
+
+ for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
+ char update[] = updateOthers.getKey().toCharArray();
+ int charToupdate = Character.getNumericValue(update[1]);
+ --charToupdate;
+ String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
+ updateOthers.getValue().setIndexChanged(true);
+ updatedRC.put(resultRowCol, updateOthers.getValue());
+ updatedRC.remove(updateOthers.getKey());
+
+ }
+ setDomainRowCol(updatedRC);
+
+ /* for (Map.Entry<String, Domain> entry : updatedRC.entrySet()) {
+ System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }*/
+
+ double currDistFromLftM = 11.0;
+ int orgColofCollapsedd = -1;
+ int orgColofDisplayedd = -1;
+ for (Map.Entry<String,Domain> cd : updatedRC.entrySet()) {
+ /*for (Domain pl : collapsedDomainNewL) {
+ for (Map.Entry<String, Domain> colCheck : originalDomainRowCol.entrySet()) {
+ if (colCheck.getValue().getName().equals(pl.getName())) {
+ orgColofCollapsedd = Character.getNumericValue(colCheck.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+ for (Map.Entry<String, Domain> colCheckk : originalDomainRowCol.entrySet()) {
+ if (colCheckk.getValue().getName().equals(cd.getValue().getName())) {
+ orgColofDisplayedd = Character.getNumericValue(colCheckk.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+ if (orgColofCollapsedd < orgColofDisplayedd) {
+ currDistFromLftM+= 3;
+ }
+ }*/
+ Domain d = cd.getValue();
+ double accountPlus = accountForPlusSpaceBefore(d);
+ // currDistFromLftM+= accountForPlusSpaceBefore(d);
+ d.setDomainToLayoutWd(currDistFromLftM+accountPlus);
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ currDistFromLftM += d.computeSize().getWidth()+2;
+
+ }
+
+
+
+
+ //nline
+ // Insert method invocation
+ updatePlusPosition(collapsedDomainNewL, updatedRC);
+
+ //order changed
+ setCollapsedDomains(collapsedDomainMap);
+ setCollapsedDomainsNewList(collapsedDomainNewL);
+
+
+ computeDomainPositionsModified();
+ return this;
+ }
+
+
+
+ public Layout collapseDomainNew(String domainsToCollapse) {
+
+ if(domainsToCollapse == null || domainsToCollapse.isEmpty())
+ return null;
+
+ Map<String,Domain> updatedRC = new HashMap<String, Domain>();
+
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
+ //System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
+
+ Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
+
+ List<Domain> collapsedDomainNewL = getCollapsedDomainsNewList();
+
+
+ if (collapsedDomainNewL.size() == 0) {
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
+ // System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+ }
+
+
+ Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
+
+ int colToDelete = 0;
+ for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
+ if (entry.getValue().getName().equals(domainsToCollapse)) {
+ if (entry.getValue().isIndexChanged()) {
+ collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
+
+ }
+ //Domain toRemove = entry.getValue();
+ else {
+ collapsedDomainMap.put(entry.getKey(),entry.getValue());
+ }
+
+ collapsedDomainNewL.add(entry.getValue());
+ setNumberofColsofDomains(getNumberofColsofDomains()-1);
+ updatedRC.remove(entry.getKey());
+ colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+
+ for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
+ updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
+ //System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
+ if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
+ updatedRCSortedTrunc.remove(rmv.getKey());
+ }
+ }
+
+
+ /* for (Map.Entry<String, Domain> entry : updatedRCSortedTrunc.entrySet()) {
+ System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }*/
+
+ for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
+ char update[] = updateOthers.getKey().toCharArray();
+ int charToupdate = Character.getNumericValue(update[1]);
+ --charToupdate;
+ String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
+ updateOthers.getValue().setIndexChanged(true);
+ updatedRC.put(resultRowCol, updateOthers.getValue());
+ updatedRC.remove(updateOthers.getKey());
+
+ }
+ setDomainRowCol(updatedRC);
+
+ double currDistFromLftM = 11.0;
+
+ boolean isDisplayed;
+ for (Map.Entry<String,Domain> orgEntry : originalDomainRowCol.entrySet()) {
+ isDisplayed = false;
+ for (Map.Entry<String,Domain> cd : updatedRC.entrySet()) {
+ if (cd.getValue().getName().equals(orgEntry.getValue().getName())) {
+ Domain d = cd.getValue();
+ d.setDomainToLayoutWd(currDistFromLftM);
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ currDistFromLftM += d.computeSize().getWidth()+1;
+ isDisplayed = true;
+ break;
+ }
+ }
+
+ if (!isDisplayed) {
+ Domain myCollapsed = orgEntry.getValue();
+ myCollapsed.setNewXafterColl(currDistFromLftM);
+ myCollapsed.setYafterColl(myCollapsed.getP().getY());
+ currDistFromLftM += 4;
+ }
+ }
+
+ setCollapsedDomains(collapsedDomainMap);
+ setCollapsedDomainsNewList(collapsedDomainNewL);
+
+
+ computeDomainPositionsModified();
+ return this;
+
+ }
+
+
+ public Layout collapseDomain(String domainsToCollapse) {
+
+ Map<String,Domain> updatedRC = new HashMap<String, Domain>();
+
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
+ //System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
+
+ Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
+
+ if (collapsedDomainMap.size() == 0) {
+ for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
+ originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
+ // System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+ }
+
+
+ // List<Domain> collapsedDomainsList = getCollapsedDomains();
+
+ /* for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
+ System.out.println("Sorted Key: "+entry.getKey());
+ }*/
+
+ double prevDomXCordinate = 0.0;
+ Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
+ // for (String dToCollapse : domainsToCollapse) {
+ int colToDelete = 0;
+ for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
+ if (entry.getValue().getName().equals(domainsToCollapse)) {
+ if (entry.getValue().isIndexChanged())
+ collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
+ //Domain toRemove = entry.getValue();
+ else
+ collapsedDomainMap.put(entry.getKey(),entry.getValue());
+ prevDomXCordinate = entry.getValue().getP().getX();
+ entry.getValue().getP().setX(prevDomXCordinate-2);
+ // toRemove.setCollapsed(true);
+ setNumberofColsofDomains(getNumberofColsofDomains()-1);
+ updatedRC.remove(entry.getKey());
+ colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ // collapsedDomainList.put(entry.getKey(),entry.getValue());
+ break;
+ }
+ }
+
+ /* for (Map.Entry<String, Domain> entry : updatedRC.entrySet()) {
+ System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }*/
+
+ setCollapsedDomains(collapsedDomainMap);
+
+ for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
+ updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
+ //System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
+ }
+
+ for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
+ if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
+ updatedRCSortedTrunc.remove(rmv.getKey());
+ }
+ }
+
+
+ /* for (Map.Entry<String, Domain> entry : updatedRCSortedTrunc.entrySet()) {
+ System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }*/
+
+ for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
+ // if (!updateOthers.getValue().getName().equals(dToCollapse)) {
+ // if ((int)updateOthers.getKey().toCharArray()[1] > colToDelete) {
+ char update[] = updateOthers.getKey().toCharArray();
+ int charToupdate = Character.getNumericValue(update[1]);
+ --charToupdate;
+ String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
+ // update[1] = (char)charToupdate;
+ // updatedRC.put(String.valueOf(update), updateOthers.getValue());
+ updateOthers.getValue().setIndexChanged(true);
+ updatedRC.put(resultRowCol, updateOthers.getValue());
+ updatedRC.remove(updateOthers.getKey());
+ // }
+ // }
+ }
+
+ // }
+ setDomainRowCol(updatedRC);
+
+
+
+ for (Map.Entry<String, Domain> entry : updatedRCSortedTrunc.entrySet()) {
+ Domain d = entry.getValue();
+ // if (d.getName().equals("Datacenter with AIC") || d.getName().equals("VNI")) {
+ // d.setDomainToLayoutWd(d.getDomainToLayoutWd()-33);
+ if (collapsedDomains.size() == 2 && collapsedDomains.containsKey("00") && collapsedDomains.containsKey("01") && domainsToCollapse.equals("RAN")) {
+ if (d.getName().equals("USP"))
+ d.setDomainToLayoutWd(prevDomXCordinate);
+ else if (d.getName().equals("VNI"))
+ d.setDomainToLayoutWd(prevDomXCordinate+8);
+ else
+ d.setDomainToLayoutWd(prevDomXCordinate+10);
+ //System.out.println("Inside RAN EPC");
+ }
+ else if (domainsToCollapse.equals("RAN") && !d.getName().equals("EPC") && collapsedDomains.size() < 3)
+ d.setDomainToLayoutWd(prevDomXCordinate+11);
+ else if (domainsToCollapse.equals("RAN") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("04")) {
+ if (d.getName().equals("USP"))
+ d.setDomainToLayoutWd(prevDomXCordinate);
+ else
+ d.setDomainToLayoutWd(prevDomXCordinate+10);
+ }
+
+ else if (collapsedDomains.containsKey("00") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("02")) {
+ //System.out.println("Inside test");
+ if (d.getName().equals("VNI"))
+ d.setDomainToLayoutWd(prevDomXCordinate+10);
+ else
+ d.setDomainToLayoutWd(prevDomXCordinate);
+
+ }
+
+ else if (collapsedDomains.containsKey("00") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("03")) {
+ //System.out.println("Inside test");
+ if (d.getName().equals("VNI"))
+ d.setDomainToLayoutWd(prevDomXCordinate+10);
+ else
+ d.setDomainToLayoutWd(prevDomXCordinate);
+
+ }
+
+
+
+ else {
+ d.setDomainToLayoutWd(prevDomXCordinate);
+ }
+ d.computeConatinerPositions();
+ prevDomXCordinate = d.getP().getX();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ // }
+ // System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }
+ // setNumberofColsofDomains(getNumberofColsofDomains()-1);
+ computeDomainPositions();
+ return this;
+ /* CoordinateMain cm = new CoordinateMain();
+ try {
+ cm.convertToYAML(this);
+ } catch (Exception e) {
+
+ }*/
+
+ }
+
+ public Layout uncollapseDomainModified(String domainToUnCollapse) {
+ Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
+ Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
+ Map<String, Domain> collapsedDomainList = getCollapsedDomains();
+ Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
+
+ List<Domain> domainstoUpd = new ArrayList<Domain>();
+
+ int colToUnCollapse = 99;
+
+ Domain domainToInsert = null;
+
+ if (collapsedDomains.size() == 0) {
+ for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
+ Domain dm = unindexDomain.getValue();
+ dm.setIndexChanged(false);
+ }
+ }
+
+
+ for (Map.Entry<String, Domain> entry : collapsedDomainListSorted.entrySet()) {
+ if (entry.getValue().getName().equals(domainToUnCollapse)) {
+ colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ domainToInsert = entry.getValue();
+ collapsedDomainList.remove(entry.getKey());
+ break;
+ }
+ }
+
+ domainstoUpd.add(domainToInsert);
+
+ //for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
+ // System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
+
+ int lastKeyCol = -1;
+ for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
+ int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ if (currcol < colToUnCollapse) {
+ for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
+ if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
+ lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ } else {
+ String newKey = "0"+String.valueOf(lastKeyCol+1);
+ if (currcol == colToUnCollapse) {
+ updateDomains.put(newKey, domainToInsert);
+ ++lastKeyCol;
+ } else {
+ for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
+ if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(newKey, currDomainsEnt.getValue());
+ domainstoUpd.add(currDomainsEnt.getValue());
+ ++lastKeyCol;
+ // lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+ setNumberofColsofDomains(getNumberofColsofDomains()+1);
+ setDomainRowCol(updateDomains);
+ setCollapsedDomains(collapsedDomainList);
+
+ //for (Map.Entry<String, Domain> e : updateDomains.entrySet())
+ // System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
+
+ // for (int i = 1; i < domainstoUpd.size(); i++) {
+ for (int i = 0; i < domainstoUpd.size(); i++) {
+ Domain d = domainstoUpd.get(i);
+ double newX = 0.0;
+ if (i+1 < domainstoUpd.size())
+ // newX = domainstoUpd.get(i-1).getP().getX()+domainstoUpd.get(i-1).computeSize().getWidth()+5;
+ newX = domainstoUpd.get(i+1).getP().getX();
+ //d.setDomainToLayoutWd(domainstoUpd.get(i+1).getP().getX());
+ else
+ newX = domainstoUpd.get(i).getP().getX()+32;
+ // d.setDomainToLayoutWd(domainstoUpd.get(i).getP().getX()+38);
+ /* if (i > 0) {
+ if (d.getWidth() < domainstoUpd.get(i-1).getWidth())
+ newX+= domainstoUpd.get(i-1).getWidth() - d.getWidth();
+ else if (d.getWidth() > domainstoUpd.get(i-1).getWidth())
+ newX-= d.getWidth() - domainstoUpd.get(i-1).getWidth() ;
+ } else {
+ if (d.getWidth() < domainInserted.getWidth())
+ newX+= domainInserted.getWidth() - d.getWidth();
+ else if (d.getWidth() > domainInserted.getWidth())
+ newX-= d.getWidth() - domainInserted.getWidth() ;
+ }*/
+ if (d.getName().equals("Datacenter with AIC"))
+ newX+= 2;
+ d.setDomainToLayoutWd(newX);
+ /* if (i == 0)
+ d.setDomainToLayoutWd(domainInserted.getP().getX()+domainInserted.getWidth());
+ else
+ d.setDomainToLayoutWd(domainstoUpd.get(i-1).getP().getX()+domainstoUpd.get(i-1).getWidth());*/
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ // }
+ // System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }
+
+ computeDomainPositions();
+ return this;
+
+ }
+
+
+
+ public Layout uncollapseDomain(String domainToCollapse) {
+ Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
+ Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
+ Map<String, Domain> collapsedDomainList = getCollapsedDomains();
+ Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
+
+ List<Domain> domainstoUpd = new ArrayList<Domain>();
+ /* for (Map.Entry<String, Domain> entry : collapsedDomainListSorted.entrySet()) {
+ if (entry.getValue().getName().equals("domainToCollapse")) {
+ if (currentDomainsSorted != null) {
+ if (!currentDomainsSorted.containsKey(entry.getKey())) {
+ updateDomains.put(entry.getKey(), entry.getValue());
+ collapsedDomainList.remove(entry.getKey());
+ break;
+ } else {
+ int colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ for (Map.Entry<String, Domain> curr : currentDomainsSorted.entrySet()) {
+ if (Character.getNumericValue(curr.getKey().toCharArray()[1]) < colToUnCollapse) {
+ updateDomains.put(curr.getKey(),curr.getValue());
+ } else {
+ updateDomains.put(curr.getKey()+1,curr.getValue());
+
+ }
+ }
+ updateDomains.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+
+ }
+ }*/
+
+ Domain domainInserted = null;
+ for (Map.Entry<String, Domain> entry : collapsedDomainListSorted.entrySet()) {
+ if (entry.getValue().getName().equals(domainToCollapse)) {
+ domainInserted = entry.getValue();
+ if (currentDomainsSorted != null) {
+ int colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ for (Map.Entry<String, Domain> curr : currentDomainsSorted.entrySet()) {
+ if (Character.getNumericValue(curr.getKey().toCharArray()[1]) < colToUnCollapse) {
+ updateDomains.put(curr.getKey(),curr.getValue());
+ } else {
+ updateDomains.put("0"+String.valueOf(Integer.parseInt(curr.getKey())+1),curr.getValue());
+ domainstoUpd.add(curr.getValue());
+ }
+ }
+ }
+ updateDomains.put(entry.getKey(), entry.getValue());
+ collapsedDomainList.remove(entry.getKey());
+ break;
+
+ }
+ }
+ setNumberofColsofDomains(getNumberofColsofDomains()+1);
+ setDomainRowCol(updateDomains);
+ setCollapsedDomains(collapsedDomainList);
+
+ //for (Map.Entry<String, Domain> e : updateDomains.entrySet())
+ // System.out.println("Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
+
+
+ for (int i = 0; i < domainstoUpd.size(); i++) {
+ Domain d = domainstoUpd.get(i);
+ double newX = 0.0;
+ if (i+1 < domainstoUpd.size())
+ newX = domainstoUpd.get(i+1).getP().getX();
+ //d.setDomainToLayoutWd(domainstoUpd.get(i+1).getP().getX());
+ else
+ newX = domainstoUpd.get(i).getP().getX()+38;
+ // d.setDomainToLayoutWd(domainstoUpd.get(i).getP().getX()+38);
+ /* if (i > 0) {
+ if (d.getWidth() < domainstoUpd.get(i-1).getWidth())
+ newX+= domainstoUpd.get(i-1).getWidth() - d.getWidth();
+ else if (d.getWidth() > domainstoUpd.get(i-1).getWidth())
+ newX-= d.getWidth() - domainstoUpd.get(i-1).getWidth() ;
+ } else {
+ if (d.getWidth() < domainInserted.getWidth())
+ newX+= domainInserted.getWidth() - d.getWidth();
+ else if (d.getWidth() > domainInserted.getWidth())
+ newX-= d.getWidth() - domainInserted.getWidth() ;
+ }*/
+ if (d.getName().equals("Datacenter with AIC"))
+ newX+= 5;
+ d.setDomainToLayoutWd(newX);
+ /* if (i == 0)
+ d.setDomainToLayoutWd(domainInserted.getP().getX()+domainInserted.getWidth());
+ else
+ d.setDomainToLayoutWd(domainstoUpd.get(i-1).getP().getX()+domainstoUpd.get(i-1).getWidth());*/
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ // }
+ // System.out.println("Sorted key: "+entry.getKey()+" Sorted value: "+entry.getValue().getName());
+ }
+
+ computeDomainPositions();
+ return this;
+ }
+
+ public Layout uncollapseDomainNew(String domainToUnCollapse) {
+ Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
+ Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
+ Map<String, Domain> collapsedDomainList = getCollapsedDomains();
+ Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
+
+ List<Domain> domainstoUpd = new ArrayList<Domain>();
+
+ //nline
+ List<Domain> collapsedDomainNewLL = getCollapsedDomainsNewList();
+
+ int colToUnCollapse = 99;
+
+ Domain domainToInsert = null;
+
+ //nline
+ // if (collapsedDomains.size() == 0) {
+ if (collapsedDomainNewLL.size() == 0) {
+ for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
+ Domain dm = unindexDomain.getValue();
+ dm.setIndexChanged(false);
+ }
+ }
+
+
+ for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
+ if (entry.getValue().getName().equals(domainToUnCollapse)) {
+ colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ domainToInsert = entry.getValue();
+ collapsedDomainList.remove(entry.getKey());
+ //nline
+ collapsedDomainNewLL.remove(entry.getValue());
+ break;
+ }
+ }
+
+ domainstoUpd.add(domainToInsert);
+
+ // for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
+ // System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
+
+ int lastKeyCol = -1;
+ for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
+ int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ if (currcol < colToUnCollapse) {
+ for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
+ if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
+ lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ } else {
+ String newKey = "0"+String.valueOf(lastKeyCol+1);
+ if (currcol == colToUnCollapse) {
+ updateDomains.put(newKey, domainToInsert);
+ ++lastKeyCol;
+ } else {
+ for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
+ if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(newKey, currDomainsEnt.getValue());
+ domainstoUpd.add(currDomainsEnt.getValue());
+ ++lastKeyCol;
+ // lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+ setNumberofColsofDomains(getNumberofColsofDomains()+1);
+ setDomainRowCol(updateDomains);
+
+ //for (Map.Entry<String, Domain> e : updateDomains.entrySet())
+ // System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
+
+
+
+ double currDistFromLftMargin = 11.0;
+ for (Map.Entry<String,Domain> cd : updateDomains.entrySet()) {
+ Domain d = cd.getValue();
+ double accountPlus = accountForPlusSpaceBefore(d);
+ d.setDomainToLayoutWd(currDistFromLftMargin+accountPlus);
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ currDistFromLftMargin += d.computeSize().getWidth()+2;
+
+ }
+
+ //nline
+ updatePlusPosition(collapsedDomainNewLL, updateDomains);
+
+ //order changed
+ setCollapsedDomains(collapsedDomainList);
+
+ //nline
+ setCollapsedDomainsNewList(collapsedDomainNewLL);
+
+
+ computeDomainPositionsModified();
+ return this;
+
+ }
+
+ public Layout uncollapseDomainNew1(String domainToUnCollapse) {
+
+ if(domainToUnCollapse == null || domainToUnCollapse.isEmpty())
+ return null;
+
+ Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
+ Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
+ Map<String, Domain> collapsedDomainList = getCollapsedDomains();
+ Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
+
+ List<Domain> domainstoUpd = new ArrayList<Domain>();
+
+ //nline
+ List<Domain> collapsedDomainNewLL = getCollapsedDomainsNewList();
+
+ int colToUnCollapse = 99;
+
+ Domain domainToInsert = null;
+
+ //nline
+ // if (collapsedDomains.size() == 0) {
+ if (collapsedDomainNewLL.size() == 0) {
+ for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
+ Domain dm = unindexDomain.getValue();
+ dm.setIndexChanged(false);
+ }
+ }
+
+
+ for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
+ if (entry.getValue().getName().equals(domainToUnCollapse)) {
+ colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ domainToInsert = entry.getValue();
+ collapsedDomainList.remove(entry.getKey());
+ //nline
+ collapsedDomainNewLL.remove(entry.getValue());
+ break;
+ }
+ }
+
+ domainstoUpd.add(domainToInsert);
+
+ //for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
+ // System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
+
+ int lastKeyCol = -1;
+ for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
+ int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
+ if (currcol < colToUnCollapse) {
+ for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
+ if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
+ lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ } else {
+ String newKey = "0"+String.valueOf(lastKeyCol+1);
+ if (currcol == colToUnCollapse) {
+ updateDomains.put(newKey, domainToInsert);
+ ++lastKeyCol;
+ } else {
+ for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
+ if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
+ updateDomains.put(newKey, currDomainsEnt.getValue());
+ domainstoUpd.add(currDomainsEnt.getValue());
+ ++lastKeyCol;
+ // lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+ setNumberofColsofDomains(getNumberofColsofDomains()+1);
+ setDomainRowCol(updateDomains);
+
+ //for (Map.Entry<String, Domain> e : updateDomains.entrySet())
+ // System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
+
+
+
+
+ double currDistFromLftM = 11.0;
+
+ boolean isDisplayed;
+ for (Map.Entry<String,Domain> orgEntry : originalDomainRowCol.entrySet()) {
+ isDisplayed = false;
+ for (Map.Entry<String,Domain> cd : updateDomains.entrySet()) {
+ if (cd.getValue().getName().equals(orgEntry.getValue().getName())) {
+ Domain d = cd.getValue();
+ d.setDomainToLayoutWd(currDistFromLftM);
+ d.computeConatinerPositions();
+ for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
+ Container c = entry1.getValue();
+ c.computeSize();
+ c.computeElementPositions();
+ if (c.getContainerRowCol() != null) {
+ for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
+ Container inner = entryInner.getValue();
+ inner.computeElementPositions();
+ }
+ }
+ }
+ currDistFromLftM += d.computeSize().getWidth()+1;
+ isDisplayed = true;
+ break;
+ }
+ }
+
+ if (!isDisplayed) {
+ Domain myCollapsed = orgEntry.getValue();
+ myCollapsed.setNewXafterColl(currDistFromLftM);
+ currDistFromLftM += 4;
+ }
+ }
+
+ // plus.setNewXafterColl(distOfCollFrmLft+1.5);
+
+ //order changed
+ setCollapsedDomains(collapsedDomainList);
+
+ //nline
+ setCollapsedDomainsNewList(collapsedDomainNewLL);
+
+
+ computeDomainPositionsModified();
+ return this;
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private void updatePlusPosition(List<Domain> collapsedDNewL, Map<String, Domain> displayedDomainMap) {
+ List<Domain> copyCollapseList = new ArrayList<Domain>();
+
+ for (Domain copyCollapse : collapsedDNewL) {
+ copyCollapseList.add(copyCollapse);
+ }
+
+ //double distOfCollFrmLft = 0.0;
+ int orgColofCollapsed = -1;
+ int orgColofDisplayed = -1;
+ int orgColofDisplayedOtherPlus = -1;
+ int orgColofInterDomainPlus = -1;
+ List<Domain> dsplyList = new ArrayList<Domain>();
+
+ for (Domain plus : collapsedDNewL) {
+ double distOfCollFrmLft = 0.0;
+ for (Map.Entry<String, Domain> colCheck : originalDomainRowCol.entrySet()) {
+ if (colCheck.getValue().getName().equals(plus.getName())) {
+ orgColofCollapsed = Character.getNumericValue(colCheck.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ for (Map.Entry<String, Domain> displayedEntry : displayedDomainMap.entrySet()) {
+
+ for (Map.Entry<String, Domain> colCheck1 : originalDomainRowCol.entrySet()) {
+ if (colCheck1.getValue().getName().equals(displayedEntry.getValue().getName())) {
+ orgColofDisplayed = Character.getNumericValue(colCheck1.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ if (orgColofDisplayed < orgColofCollapsed) {
+ distOfCollFrmLft+= displayedEntry.getValue().computeSize().getWidth();
+
+
+ /* if (dsplyList.size() > 0) {
+ Domain lastAdded = dsplyList.get(dsplyList.size()-1);
+ int orgColofLastAdded = -1;
+ for (Map.Entry<String, Domain> colCh : originalDomainRowCol.entrySet()) {
+ if (colCh.getValue().getName().equals(lastAdded.getName())) {
+ orgColofLastAdded = Character.getNumericValue(colCh.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ if (Math.abs(orgColofDisplayed - orgColofLastAdded) == 1) {
+ boolean adjDomainsWithPlus = false;
+ for (Domain colp : copyCollapseList) {
+ if (!colp.getName().equals(plus.getName())) {
+ for (Map.Entry<String, Domain> colCk2 : originalDomainRowCol.entrySet()) {
+ if (colCk2.getValue().getName().equals(colp.getName())) {
+ orgColofInterDomainPlus = Character.getNumericValue(colCk2.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ if (orgColofInterDomainPlus > orgColofLastAdded && orgColofInterDomainPlus < orgColofDisplayed) {
+ adjDomainsWithPlus = true;
+ break;
+ }
+ }
+ }
+ if (!adjDomainsWithPlus)
+ distOfCollFrmLft+=interDomainWd;
+ }
+ }
+ dsplyList.add(displayedEntry.getValue()); */
+
+
+
+ }
+
+ }
+
+ for (Domain collp : copyCollapseList) {
+ if (!collp.getName().equals(plus.getName())) {
+ for (Map.Entry<String, Domain> colCheck2 : originalDomainRowCol.entrySet()) {
+ if (colCheck2.getValue().getName().equals(collp.getName())) {
+ orgColofDisplayedOtherPlus = Character.getNumericValue(colCheck2.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+ if (orgColofDisplayedOtherPlus < orgColofCollapsed) {
+ distOfCollFrmLft+=3.0;
+ }
+ }
+ }
+
+ plus.setNewXafterColl(distOfCollFrmLft+1.5);
+
+
+ }
+ }
+
+
+ private double accountForPlusSpaceBefore(Domain d) {
+
+ int orgColofCollapsed = 0;
+ int orgColofDisplayed = 0;
+ double distFromLftM = 0.0;
+
+ for (Map.Entry<String, Domain> colCheckk : originalDomainRowCol.entrySet()) {
+ if (colCheckk.getValue().getName().equals(d.getName())) {
+ orgColofDisplayed = Character.getNumericValue(colCheckk.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+ for (Domain collapsed : getCollapsedDomainsNewList()) {
+ for (Map.Entry<String, Domain> colCheck : originalDomainRowCol.entrySet()) {
+ if (colCheck.getValue().getName().equals(collapsed.getName())) {
+ orgColofCollapsed = Character.getNumericValue(colCheck.getKey().toCharArray()[1]);
+ break;
+ }
+ }
+
+ if (orgColofCollapsed < orgColofDisplayed) {
+ distFromLftM+= 2;
+ }
+ }
+ return distFromLftM;
+
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java
index 52d03c5f..fcb9f726 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/NameValueId.java
@@ -24,11 +24,11 @@ import java.io.Serializable;
public class NameValueId implements Serializable {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
- private String lab;
+ private String lab;
private String val;
public NameValueId() {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java
index db137c80..db137c80 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Position.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java
index 4ebfb962..4ebfb962 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/domain/support/Size.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java
index c556aa13..c556aa13 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java
index 7328c472..2aa0d1f2 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/drools/DroolsRuleServiceImpl.java
@@ -55,4 +55,4 @@ public class DroolsRuleServiceImpl implements DroolsRuleService{
public void setResultsString(String resultsString) {
this.resultsString = resultsString;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java
index f756d760..a2b4363a 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/FusionExceptionResolver.java
@@ -47,4 +47,4 @@ public class FusionExceptionResolver {
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java
index ba8f76bd..f4a19a9e 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/SessionExpiredException.java
@@ -22,11 +22,12 @@ package org.openecomp.portalsdk.core.exception;
import org.openecomp.portalsdk.core.exception.support.FusionRuntimeException;
public class SessionExpiredException extends FusionRuntimeException {
- /**
+
+ /**
*
*/
private static final long serialVersionUID = 1L;
- public static final String MESSAGE = "Your session has expired. Please login again.";
+ public static final String MESSAGE = "Your session has expired. Please login again.";
public SessionExpiredException() {
super(MESSAGE);
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java
index 39fe264a..adc56118 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/UrlAccessRestrictedException.java
@@ -22,11 +22,12 @@ package org.openecomp.portalsdk.core.exception;
import org.openecomp.portalsdk.core.exception.support.FusionRuntimeException;
public class UrlAccessRestrictedException extends FusionRuntimeException {
- /**
+
+ /**
*
*/
private static final long serialVersionUID = 1L;
- public static final String MESSAGE = "Authorization Denied";
+ public static final String MESSAGE = "Authorization Denied";
public UrlAccessRestrictedException() {
super(MESSAGE);
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java
index 135fc3e3..135fc3e3 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionException.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java
index f7ca61fa..91a733d4 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/exception/support/FusionRuntimeException.java
@@ -20,12 +20,11 @@
package org.openecomp.portalsdk.core.exception.support;
public class FusionRuntimeException extends RuntimeException implements FusionException {
- /**
+ /**
*
*/
private static final long serialVersionUID = 1L;
-
- public FusionRuntimeException() {
+ public FusionRuntimeException() {
this("");
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java
index 24088cdb..ec6e4b6c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/ResourceInterceptor.java
@@ -24,6 +24,7 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.openecomp.portalsdk.core.controller.FusionBaseController;
import org.openecomp.portalsdk.core.domain.App;
@@ -31,13 +32,13 @@ import org.openecomp.portalsdk.core.exception.UrlAccessRestrictedException;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.service.DataAccessService;
import org.openecomp.portalsdk.core.service.LoginService;
import org.openecomp.portalsdk.core.service.WebServiceCallService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -80,7 +81,9 @@ public class ResourceInterceptor extends HandlerInterceptorAdapter {
}
} catch (Exception e) {
logger.error(EELFLoggerDelegate.errorLogger, "Error authenticating RESTful service :" + e,AlarmSeverityEnum.MINOR);
- ((HttpServletResponse) response).setStatus(HttpURLConnection.HTTP_UNAUTHORIZED);
+ //throw new UrlAccessRestrictedException();
+ HttpSession httpSession = request.getSession();
+ ((HttpServletResponse) response).setStatus(HttpURLConnection.HTTP_UNAUTHORIZED);
return false;
}
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java
index e28ce866..e28ce866 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interceptor/SessionTimeoutInterceptor.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java
index b40c4713..b40c4713 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/interfaces/SecurityInterface.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java
index 10e2b2d9..0cc99f0e 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/ApplicationContextListener.java
@@ -22,6 +22,8 @@ package org.openecomp.portalsdk.core.listener;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
+import org.openecomp.portalsdk.core.lm.FusionLicenseManager;
+import org.openecomp.portalsdk.core.lm.FusionLicenseManagerUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
@@ -33,11 +35,15 @@ public class ApplicationContextListener implements ApplicationListener<ContextRe
@Autowired
ServletContext context;
-
+ @Autowired
+ FusionLicenseManager lm;
+ @Autowired
+ FusionLicenseManagerUtils fusionLicenseManagerUtils;
+
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent ) {
-
-// String contextPath = context.getContextPath();
+ int licenseStatus = fusionLicenseManagerUtils.verifyLicense(context);
+ context.setAttribute("licenseVerification", licenseStatus);
}
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java
index 9306aaf1..9306aaf1 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/CollaborateListBindingListener.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java
index adc84775..adc84775 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/listener/UserSessionListener.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManager.java
new file mode 100644
index 00000000..eb371575
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManager.java
@@ -0,0 +1,60 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.lm;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+//import de.schlichtherle.license.LicenseContent;
+
+public interface FusionLicenseManager {
+
+
+ public static final int DEVELOPER_LICENSE = 0;
+ public static final int EXPIRED_LICENSE = 1;
+ public static final int VALID_LICENSE = 2;
+ public static final int INVALID_LICENSE = 3;
+ public static final int OPENSOURCE_LICENSE = 4;
+
+ public void initKeyStoreParam();
+
+ public void initCipherParam();
+
+ public void initLicenseParam();
+
+ public void doInitWork();
+
+ public int installLicense();
+
+ public int verifyLicense(ServletContext context);
+
+ //public LicenseContent createLicenseContent(Map<String, String> clientInfoMap, List<String> ipAddressList);
+
+ public void generateLicense(Map<String, String> clientInfoMap, List<String> ipAddressList) throws Exception;
+
+ public String nvl(String s);
+
+ public Date getExpiredDate();
+
+ public void setExpiredDate(Date expiredDate);
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManagerUtils.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManagerUtils.java
new file mode 100644
index 00000000..538709e8
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/FusionLicenseManagerUtils.java
@@ -0,0 +1,74 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.lm;
+
+import java.util.Date;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.util.SystemProperties;
+//import org.openecomp.portalapp.lm.FusionLicenseManagerImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.support.RequestContextUtils;
+
+@Component
+public class FusionLicenseManagerUtils {
+
+ @Autowired
+ private FusionLicenseManager licenseManager;
+
+ @Autowired
+ private SystemProperties sysProps;
+ static {
+ }
+
+ public int verifyLicense(ServletContext context) {
+ if(sysProps == null) {
+ try {
+ sysProps = new SystemProperties();
+ sysProps.setServletContext(context);
+// sysProps.load();
+// licenseManager = new FusionLicenseManagerImpl(new LicenseableClassImpl());
+ System.out.println(licenseManager);
+ licenseManager.installLicense();
+ }
+ catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+
+
+// WebApplicationContext ctx =RequestContextUtils.getWebApplicationContext(request);
+// int flag = ((FusionLicenseManager)ctx.getBean("fusionLicenseManager")).verifyLicense(request);
+// logger.debug("****************FLAG ******************** " + flag);
+// return flag;
+// return 2;
+ return licenseManager.verifyLicense(context);
+ }
+
+ public static Date getLicenseExpiryDate(HttpServletRequest request) {
+ WebApplicationContext ctx =RequestContextUtils.getWebApplicationContext(request);
+ return ((FusionLicenseManager)ctx.getBean("fusionLicenseManager")).getExpiredDate();
+ }
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/LicenseableClass.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/LicenseableClass.java
new file mode 100644
index 00000000..296a1609
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/lm/LicenseableClass.java
@@ -0,0 +1,38 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.lm;
+
+import java.io.*;
+
+/**
+ * created by Alvin Alexander of http://devdaily.com.
+ * modified by Sundar Ramalingam
+ */
+public interface LicenseableClass
+{
+ public String getApplicationName();
+ public InputStream getPublicKeystoreAsInputStream() throws FileNotFoundException;
+ public String getAlias();
+ public String getPublicKeystorePassword();
+ public String getKeyPasswd();
+ public String getCipherParamPassword();
+ public Class getClassToLicense();
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java
new file mode 100644
index 00000000..6cb661b1
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java
@@ -0,0 +1,32 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.logging.aspect;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AuditLog {
+ String value() default "";
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java
new file mode 100644
index 00000000..da4e2aff
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java
@@ -0,0 +1,234 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.logging.aspect;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.logging.format.AuditLogFormatter;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.service.AppService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.util.SystemProperties.SecurityEventTypeEnum;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.att.eelf.configuration.Configuration;
+
+@org.springframework.context.annotation.Configuration
+public class EELFLoggerAdvice {
+
+ @Autowired
+ AppService appService;
+
+ EELFLoggerDelegate adviceLogger = EELFLoggerDelegate.getLogger(EELFLoggerAdvice.class);
+
+ // DateTime Format according to the ECOMP Application Logging Guidelines.
+ private static final SimpleDateFormat ecompLogDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+ /**
+ * Gets the current date and time in expected ECOMP log format.
+ *
+ * @return Current date and time
+ */
+ public static String getCurrentDateTimeUTC() {
+ String currentDateTime = ecompLogDateFormat.format(new Date());
+ return currentDateTime;
+ }
+
+ /**
+ *
+ * @param securityEventType
+ * @param args
+ * @param passOnArgs
+ * @return One-element array containing an empty String object.
+ */
+ public Object[] before(SecurityEventTypeEnum securityEventType, Object[] args, Object[] passOnArgs) {
+ try {
+ String className = "";
+ if (passOnArgs[0] != null) {
+ className = passOnArgs[0].toString();
+ }
+
+ String methodName = "";
+ if (passOnArgs[1] != null) {
+ methodName = passOnArgs[1].toString();
+ }
+
+ String appName = appService.getDefaultAppName();
+ if (appName == null || appName == "") {
+ appName = SystemProperties.SDK_NAME;
+ }
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
+
+ // Initialize Request defaults only for controller methods.
+ MDC.put(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, getCurrentDateTimeUTC());
+ MDC.put(SystemProperties.TARGET_ENTITY, appName + "_BE");
+ MDC.put(SystemProperties.TARGET_SERVICE_NAME, methodName);
+ if (securityEventType != null) {
+ MDC.put(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, getCurrentDateTimeUTC());
+ HttpServletRequest req = null;
+ if (args[0] != null && args[0] instanceof HttpServletRequest) {
+ req = (HttpServletRequest) args[0];
+ logger.setRequestBasedDefaultsIntoGlobalLoggingContext(req, appName);
+ }
+ }
+ logger.debug(EELFLoggerDelegate.debugLogger, (methodName + " was invoked."));
+ } catch (Exception e) {
+ adviceLogger.error(EELFLoggerDelegate.errorLogger,
+ "Exception occurred in EELFLoggerAdvice.before() method. Details: " + e.getMessage());
+ }
+
+ return new Object[] { "" };
+ }
+
+ /**
+ *
+ * @param securityEventType
+ * @param result
+ * @param args
+ * @param returnArgs
+ * @param passOnArgs
+ */
+ public void after(SecurityEventTypeEnum securityEventType, String result, Object[] args, Object[] returnArgs,
+ Object[] passOnArgs) {
+ try {
+ String className = "";
+ if (passOnArgs[0] != null) {
+ className = passOnArgs[0].toString();
+ }
+
+ String methodName = "";
+ if (passOnArgs[1] != null) {
+ methodName = passOnArgs[1].toString();
+ }
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
+
+ String appName = appService.getDefaultAppName();
+ if (appName == null || appName == "") {
+ appName = SystemProperties.SDK_NAME;
+ }
+
+ if (MDC.get(SystemProperties.TARGET_SERVICE_NAME) == null
+ || MDC.get(SystemProperties.TARGET_SERVICE_NAME) == "") {
+ MDC.put(SystemProperties.TARGET_SERVICE_NAME, methodName);
+ }
+
+ if (MDC.get(SystemProperties.TARGET_ENTITY) == null || MDC.get(SystemProperties.TARGET_ENTITY) == "") {
+ MDC.put(SystemProperties.TARGET_ENTITY, appName + "_BE");
+ }
+
+ MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP,
+ MDC.get(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP));
+ MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
+ this.calculateDateTimeDifference(MDC.get(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP),
+ MDC.get(SystemProperties.METRICSLOG_END_TIMESTAMP));
+
+ logger.info(EELFLoggerDelegate.metricsLogger, methodName + " operation is completed.");
+ logger.debug(EELFLoggerDelegate.debugLogger, "Finished executing " + methodName + ".");
+
+ if (securityEventType != null) {
+
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP,
+ MDC.get(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP));
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
+ this.calculateDateTimeDifference(MDC.get(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP),
+ MDC.get(SystemProperties.AUDITLOG_END_TIMESTAMP));
+
+ this.logSecurityMessage(logger, securityEventType, result, methodName);
+
+ // clear when finishes audit logging
+ MDC.remove(Configuration.MDC_KEY_REQUEST_ID);
+ MDC.remove(SystemProperties.PARTNER_NAME);
+ MDC.remove(SystemProperties.MDC_LOGIN_ID);
+ MDC.remove(SystemProperties.PROTOCOL);
+ MDC.remove(SystemProperties.FULL_URL);
+ MDC.remove(Configuration.MDC_SERVICE_NAME);
+ MDC.remove(SystemProperties.RESPONSE_CODE);
+ MDC.remove(SystemProperties.STATUS_CODE);
+ MDC.remove(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.AUDITLOG_END_TIMESTAMP);
+ }
+
+ MDC.remove(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.METRICSLOG_END_TIMESTAMP);
+ MDC.remove(SystemProperties.MDC_TIMER);
+ MDC.remove(SystemProperties.TARGET_ENTITY);
+ MDC.remove(SystemProperties.TARGET_SERVICE_NAME);
+ } catch (Exception e) {
+ adviceLogger.error(EELFLoggerDelegate.errorLogger,
+ "Exception occurred in EELFLoggerAdvice.after() method. Details: " + e.getMessage());
+ }
+ }
+
+ /**
+ *
+ * @param logger
+ * @param securityEventType
+ * @param result
+ * @param restMethod
+ */
+ private void logSecurityMessage(EELFLoggerDelegate logger, SecurityEventTypeEnum securityEventType, String result,
+ String restMethod) {
+ StringBuilder additionalInfoAppender = new StringBuilder();
+ String auditMessage = "";
+
+ additionalInfoAppender.append(String.format("%s request was received.", restMethod));
+
+ // Status code
+ MDC.put(SystemProperties.STATUS_CODE, result);
+
+ String fullURL = MDC.get(SystemProperties.FULL_URL);
+ if (fullURL != null && fullURL != "") {
+ additionalInfoAppender.append(" Request-URL:" + MDC.get(SystemProperties.FULL_URL));
+ }
+
+ auditMessage = AuditLogFormatter.getInstance().createMessage(MDC.get(SystemProperties.PROTOCOL),
+ securityEventType.name(), MDC.get(SystemProperties.MDC_LOGIN_ID), additionalInfoAppender.toString());
+
+ logger.info(EELFLoggerDelegate.auditLogger, auditMessage);
+ }
+
+ /**
+ *
+ * @param beginDateTime
+ * @param endDateTime
+ */
+ private void calculateDateTimeDifference(String beginDateTime, String endDateTime) {
+ if (beginDateTime != null && endDateTime != null) {
+ try {
+ Date beginDate = ecompLogDateFormat.parse(beginDateTime);
+ Date endDate = ecompLogDateFormat.parse(endDateTime);
+ String timeDifference = String.format("%d ms", endDate.getTime() - beginDate.getTime());
+ MDC.put(SystemProperties.MDC_TIMER, timeDifference);
+ } catch (Exception e) {
+ adviceLogger.error(EELFLoggerDelegate.errorLogger,
+ "Exception occurred in EELFLoggerAdvice.calculateDateTimeDifference() method. Details: "
+ + e.getMessage());
+ }
+ }
+ }
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java
index 3138d21a..3138d21a 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAspect.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java
index f795ffb1..f795ffb1 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/aspect/MetricsLog.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java
index 360d8d81..360d8d81 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AlarmSeverityEnum.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java
index a6924ba0..a6924ba0 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AppMessagesEnum.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties
index efd9ac24..efd9ac24 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ApplicationCodes.properties
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java
index 2cb336e2..2cb336e2 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/AuditLogFormatter.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java
index 59fe2bb7..549d3262 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorCodesEnum.java
@@ -83,5 +83,7 @@ public enum ErrorCodesEnum implements EELFResolvableErrorEnum {
* Static initializer to ensure the resource bundles for this class are loaded...
* Here this application loads messages from three bundles
*/
-
+ //static {
+ // EELFResourceManager.loadMessageBundle("com/att/fusion/core/logging/format/ApplicationCodes");
+ //}
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java
index 5908fda9..5908fda9 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorSeverityEnum.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java
index 8ce2d4dc..8ce2d4dc 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/format/ErrorTypeEnum.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java
new file mode 100644
index 00000000..319caf3c
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java
@@ -0,0 +1,484 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.logging.logic;
+
+import static com.att.eelf.configuration.Configuration.MDC_ALERT_SEVERITY;
+import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;
+import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
+
+import java.net.InetAddress;
+import java.text.MessageFormat;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.aspect.EELFLoggerAdvice;
+import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
+import org.openecomp.portalsdk.core.logging.format.AppMessagesEnum;
+import org.openecomp.portalsdk.core.logging.format.ErrorSeverityEnum;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
+import org.slf4j.MDC;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.eelf.configuration.SLF4jWrapper;
+
+public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger {
+
+ public static EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger();
+ public static EELFLogger applicationLogger = EELFManager.getInstance().getApplicationLogger();
+ public static EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ public static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger();
+ private String className;
+ private static ConcurrentMap<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<String, EELFLoggerDelegate>();
+
+ public EELFLoggerDelegate(String _className) {
+ super(_className);
+ className = _className;
+ }
+
+ /**
+ * Convenience method that gets a logger for the specified class.
+ *
+ * @see #getLogger(String)
+ *
+ * @param clazz
+ * @return Instance of EELFLoggerDelegate
+ */
+ public static EELFLoggerDelegate getLogger(Class<?> clazz) {
+ return getLogger(clazz.getName());
+ }
+
+ /**
+ * Gets a logger for the specified class name. If the logger does not
+ * already exist in the map, this creates a new logger.
+ *
+ * @param className
+ * If null or empty, uses EELFLoggerDelegate as the class name.
+ * @return Instance of EELFLoggerDelegate
+ */
+ public static EELFLoggerDelegate getLogger(String className) {
+ if (className == null || className == "")
+ className = EELFLoggerDelegate.class.getName();
+ EELFLoggerDelegate delegate = classMap.get(className);
+ if (delegate == null) {
+ delegate = new EELFLoggerDelegate(className);
+ classMap.put(className, delegate);
+ }
+ return delegate;
+ }
+
+ /**
+ * Logs a message at the lowest level: trace.
+ *
+ * @param logger
+ * @param msg
+ */
+ public void trace(EELFLogger logger, String msg) {
+ if (logger.isTraceEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.trace(msg);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message with parameters at the lowest level: trace.
+ *
+ * @param logger
+ * @param msg
+ * @param arguments
+ */
+ public void trace(EELFLogger logger, String msg, Object... arguments) {
+ if (logger.isTraceEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.trace(msg, arguments);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message and throwable at the lowest level: trace.
+ *
+ * @param logger
+ * @param msg
+ * @param th
+ */
+ public void trace(EELFLogger logger, String msg, Throwable th) {
+ if (logger.isTraceEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.trace(msg, th);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message at the second-lowest level: debug.
+ *
+ * @param logger
+ * @param msg
+ */
+ public void debug(EELFLogger logger, String msg) {
+ if (logger.isDebugEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.debug(msg);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message with parameters at the second-lowest level: debug.
+ *
+ * @param logger
+ * @param msg
+ * @param arguments
+ */
+ public void debug(EELFLogger logger, String msg, Object... arguments) {
+ if (logger.isDebugEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.debug(msg, arguments);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message and throwable at the second-lowest level: debug.
+ *
+ * @param logger
+ * @param msg
+ * @param th
+ */
+ public void debug(EELFLogger logger, String msg, Throwable th) {
+ if (logger.isDebugEnabled()) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.debug(msg, th);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+ }
+
+ /**
+ * Logs a message at info level.
+ *
+ * @param logger
+ * @param msg
+ */
+ public void info(EELFLogger logger, String msg) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.info(msg);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message with parameters at info level.
+ *
+ * @param logger
+ * @param msg
+ * @param arguments
+ */
+ public void info(EELFLogger logger, String msg, Object... arguments) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.info(msg, arguments);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message and throwable at info level.
+ *
+ * @param logger
+ * @param msg
+ * @param th
+ */
+ public void info(EELFLogger logger, String msg, Throwable th) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.info(msg, th);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message at warn level.
+ *
+ * @param logger
+ * @param msg
+ */
+ public void warn(EELFLogger logger, String msg) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.warn(msg);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message with parameters at warn level.
+ *
+ * @param logger
+ * @param msg
+ * @param arguments
+ */
+ public void warn(EELFLogger logger, String msg, Object... arguments) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.warn(msg, arguments);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message and throwable at warn level.
+ *
+ * @param logger
+ * @param msg
+ * @param th
+ */
+ public void warn(EELFLogger logger, String msg, Throwable th) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.warn(msg, th);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message at error level.
+ *
+ * @param logger
+ * @param msg
+ */
+ public void error(EELFLogger logger, String msg) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.error(msg);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message with parameters at error level.
+ *
+ * @param logger
+ * @param msg
+ * @param arguments
+ */
+ public void error(EELFLogger logger, String msg, Object... arguments) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.warn(msg, arguments);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message and throwable at error level.
+ *
+ * @param logger
+ * @param msg
+ * @param th
+ */
+ public void error(EELFLogger logger, String msg, Throwable th) {
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.warn(msg, th);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Logs a message with the associated alarm severity at error level.
+ *
+ * @param logger
+ * @param msg
+ * @param severtiy
+ */
+ public void error(EELFLogger logger, String msg, AlarmSeverityEnum severtiy) {
+ MDC.put(MDC_ALERT_SEVERITY, severtiy.name());
+ MDC.put(SystemProperties.MDC_CLASS_NAME, className);
+ logger.error(msg);
+ MDC.remove(MDC_ALERT_SEVERITY);
+ MDC.remove(SystemProperties.MDC_CLASS_NAME);
+ }
+
+ /**
+ * Initializes the logger context.
+ */
+ public void init() {
+ setGlobalLoggingContext();
+ final String msg = "############################ Logging is started. ############################";
+ // These loggers emit the current date-time without being told.
+ info(applicationLogger, msg);
+ error(errorLogger, msg);
+ debug(debugLogger, msg);
+ // Audit and metrics logger must be told start AND stop times
+ final String currentDateTime = EELFLoggerAdvice.getCurrentDateTimeUTC();
+ // Set the MDC with audit properties
+ MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, currentDateTime);
+ MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, currentDateTime);
+ info(auditLogger, msg);
+ MDC.remove(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.AUDITLOG_END_TIMESTAMP);
+ // Set the MDC with metrics properties
+ MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, currentDateTime);
+ MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, currentDateTime);
+ info(metricsLogger, msg);
+ MDC.remove(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
+ MDC.remove(SystemProperties.METRICSLOG_END_TIMESTAMP);
+ }
+
+ /**
+ * Logs a standard message identified by the specified enum, using the
+ * specified parameters, at error level. Alarm and error severity are taken
+ * from the specified enum argument.
+ *
+ * @param epMessageEnum
+ * @param param
+ */
+ public void logEcompError(AppMessagesEnum epMessageEnum, String... param) {
+ try {
+ AlarmSeverityEnum alarmSeverityEnum = epMessageEnum.getAlarmSeverity();
+ ErrorSeverityEnum errorSeverityEnum = epMessageEnum.getErrorSeverity();
+
+ MDC.put(MDC_ALERT_SEVERITY, alarmSeverityEnum.name());
+ MDC.put("ErrorCode", epMessageEnum.getErrorCode());
+ MDC.put("ErrorDescription", epMessageEnum.getErrorDescription());
+
+ String resolution = this.formatMessage(epMessageEnum.getDetails() + " " + epMessageEnum.getResolution(),
+ (Object[]) param);
+ if (errorSeverityEnum == ErrorSeverityEnum.WARN) {
+ errorLogger.warn(resolution);
+ } else if (errorSeverityEnum == ErrorSeverityEnum.INFO) {
+ errorLogger.info(resolution);
+ } else {
+ errorLogger.error(resolution);
+ }
+ } catch (Exception e) {
+ errorLogger.error("Failed to log the error code. Details: " + UserUtils.getStackTrace(e));
+ } finally {
+ MDC.remove("ErrorCode");
+ MDC.remove("ErrorDescription");
+ MDC.remove(MDC_ALERT_SEVERITY);
+ }
+ }
+
+ /**
+ * Builds a message using a template string and the arguments.
+ *
+ * @param message
+ * @param args
+ * @return
+ */
+ private String formatMessage(String message, Object... args) {
+ StringBuilder sbFormattedMessage = new StringBuilder();
+ if (args != null && args.length > 0 && message != null && message != "") {
+ MessageFormat mf = new MessageFormat(message);
+ sbFormattedMessage.append(mf.format(args));
+ } else {
+ sbFormattedMessage.append(message);
+ }
+
+ return sbFormattedMessage.toString();
+ }
+
+ /**
+ * Loads all the default logging fields into the MDC context.
+ */
+ private void setGlobalLoggingContext() {
+ MDC.put(MDC_SERVICE_INSTANCE_ID, "");
+ MDC.put(MDC_ALERT_SEVERITY, AlarmSeverityEnum.INFORMATIONAL.toString());
+ try {
+ MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
+ MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
+ MDC.put(MDC_INSTANCE_UUID, SystemProperties.getProperty(SystemProperties.INSTANCE_UUID));
+ } catch (Exception e) {
+ }
+ }
+
+ public static void mdcPut(String key, String value) {
+ MDC.put(key, value);
+ }
+
+ public static String mdcGet(String key) {
+ return MDC.get(key);
+ }
+
+ public static void mdcRemove(String key) {
+ MDC.remove(key);
+ }
+
+ /**
+ * Loads the RequestId/TransactionId into the MDC which it should be
+ * receiving with an each incoming REST API request. Also, configures few
+ * other request based logging fields into the MDC context.
+ *
+ * @param req
+ * @param appName
+ */
+ public void setRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest req, String appName) {
+ // Load the default fields
+ setGlobalLoggingContext();
+
+ // Load the request based fields
+ if (req != null) {
+ // Load the Request into MDC context.
+ String requestId = UserUtils.getRequestId(req);
+ MDC.put(MDC_KEY_REQUEST_ID, requestId);
+
+ // Load user agent into MDC context, if available.
+ String accessingClient = "Unknown";
+ accessingClient = req.getHeader(SystemProperties.USERAGENT_NAME);
+ if (accessingClient != null && accessingClient != "" && (accessingClient.contains("Mozilla")
+ || accessingClient.contains("Chrome") || accessingClient.contains("Safari"))) {
+ accessingClient = appName + "_FE";
+ }
+ MDC.put(SystemProperties.PARTNER_NAME, accessingClient);
+
+ // Protocol, Rest URL & Rest Path
+ String restURL = "";
+ MDC.put(SystemProperties.FULL_URL, SystemProperties.UNKNOWN);
+ MDC.put(SystemProperties.PROTOCOL, SystemProperties.HTTP);
+ restURL = UserUtils.getFullURL(req);
+ if (restURL != null && restURL != "") {
+ MDC.put(SystemProperties.FULL_URL, restURL);
+ if (restURL.toLowerCase().contains("https")) {
+ MDC.put(SystemProperties.PROTOCOL, SystemProperties.HTTPS);
+ }
+ }
+
+ // Rest Path
+ MDC.put(MDC_SERVICE_NAME, req.getServletPath());
+
+ // Client IPAddress i.e. IPAddress of the remote host who is making
+ // this request.
+ String clientIPAddress = "";
+ clientIPAddress = req.getHeader("X-FORWARDED-FOR");
+ if (clientIPAddress == null) {
+ clientIPAddress = req.getRemoteAddr();
+ }
+ MDC.put(SystemProperties.CLIENT_IP_ADDRESS, clientIPAddress);
+
+ // Load loginId into MDC context.
+ MDC.put(SystemProperties.MDC_LOGIN_ID, "Unknown");
+
+ String loginId = "";
+ User user = UserUtils.getUserSession(req);
+ if (user != null) {
+ loginId = user.getLoginId();
+ }
+
+ if (loginId != null && loginId != "") {
+ MDC.put(SystemProperties.MDC_LOGIN_ID, loginId);
+ }
+ }
+ }
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java
index aac57025..d856e7ee 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuBuilder.java
@@ -42,9 +42,8 @@ public class MenuBuilder implements FusionObject {
public MenuBuilder() {
}
-
@SuppressWarnings("unchecked")
- public Set getMenu(String menuSetName, DataAccessService dataAccessService) {
+ public Set getMenu(String menuSetName, DataAccessService dataAccessService) {
Set menu = null;
MenuData root = null;
@@ -66,7 +65,7 @@ public class MenuBuilder implements FusionObject {
}
@SuppressWarnings("unchecked")
- public Set getMenu(String menuSetName) {
+ public Set getMenu(String menuSetName) {
Set menu = null;
MenuData root = null;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java
index 007a7f30..e55baeb4 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/menu/MenuProperties.java
@@ -91,7 +91,7 @@ public class MenuProperties {
@SuppressWarnings("unchecked")
-public static void loadFromFile(ServletContext servletContext, String filename, String menuSetName) throws IOException {
+ public static void loadFromFile(ServletContext servletContext, String filename, String menuSetName) throws IOException {
Properties p = new Properties();
if (filename == null) {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java
index 6fb56d9d..7c553ad5 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/AbstractCacheManager.java
@@ -19,9 +19,9 @@
*/
package org.openecomp.portalsdk.core.objectcache;
-import java.io.IOException;
+import java.io.*;
-import org.openecomp.portalsdk.core.objectcache.support.FusionCacheManager;
+import org.openecomp.portalsdk.core.objectcache.support.*;
public abstract class AbstractCacheManager implements FusionCacheManager {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java
index 0695876f..0695876f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheEventHandler.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java
index 39b3f0cb..39b3f0cb 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/jcs/JCSCacheManager.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java
index 01cc9ce0..dee566e3 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/objectcache/support/FusionCacheManager.java
@@ -19,7 +19,7 @@
*/
package org.openecomp.portalsdk.core.objectcache.support;
-import java.io.IOException;
+import java.io.*;
import org.openecomp.portalsdk.core.FusionObject;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java
index 0e564457..1f54a8ec 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/client/AppContextManager.java
@@ -42,4 +42,4 @@ public class AppContextManager implements ApplicationContextAware{
public static ApplicationContext getAppContext(){
return _appCtx;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java
index 6bbf8c1d..6bbf8c1d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/session/TestClass.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java
index ccd903a9..ccd903a9 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/sso/TestClass.java
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java
index bb152294..e9921d18 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Consumer.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -27,18 +27,16 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import com.att.nsa.cambria.client.CambriaClientBuilders;
-import com.att.nsa.cambria.client.CambriaClientFactory;
import com.att.nsa.cambria.client.CambriaConsumer;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Provides a consumer that reads messages from a UEB topic. Intended to be
* passed to a separate thread as its runnable object.
- *
*/
public class Consumer implements Runnable {
@@ -92,25 +90,18 @@ public class Consumer implements Runnable {
* filter of "0" to prevent collisions with P2P messages with unique filter
* ids.
*/
- protected void consume() throws IOException, UebException {
+ protected void consume() throws IOException, UebException, GeneralSecurityException {
final String id = UUID.randomUUID().toString();
CambriaConsumer cc = null;
- try {
- cc = new CambriaClientBuilders.ConsumerBuilder()
- .usingHosts(urlList)
- .authenticatedBy(consumerKey, consumerSecret)
- .onTopic (topicName)
- .knownAs (consumerGroupName,id)
- .waitAtServer (15*1000)
- .receivingAtMost (1000)
- .build();
- } catch (GeneralSecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //CambriaClientFactory.createConsumer(urlList, topicName, consumerGroupName, id,
- //15 * 1000, 1000, null, consumerKey, consumerSecret);
+ cc = new CambriaClientBuilders.ConsumerBuilder()
+ .usingHosts(urlList)
+ .authenticatedBy(consumerKey, consumerSecret)
+ .onTopic (topicName)
+ .knownAs (consumerGroupName,id)
+ .waitAtServer (15*1000)
+ .receivingAtMost (1000)
+ .build();
while (true) {
for (String msg : cc.fetch()) {
@@ -161,4 +152,4 @@ public class Consumer implements Runnable {
}
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java
index 94ca4ee8..7cf3e91c 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/FunctionalMenu.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -58,4 +58,4 @@ public class FunctionalMenu {
return returnString;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java
index ce942341..6e6b4ae8 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Helper.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -23,8 +23,8 @@ import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
/**
* Provides utility methods.
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java
index a7e914c2..8dbdda2b 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/Publisher.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
import com.att.nsa.cambria.client.CambriaBatchingPublisher;
import com.att.nsa.cambria.client.CambriaClientBuilders;
@@ -38,6 +38,7 @@ import com.fasterxml.jackson.databind.ObjectWriter;
/**
* Provides a publisher that sends messages to a UEB topic.
*
+ * Utilizes AT&T's UEB/Cambria subscriber/publisher messaging service.
*/
public class Publisher {
@@ -82,16 +83,16 @@ public class Publisher {
public void send(UebMsg uebMsg) throws UebException {
String msg = null;
- CambriaBatchingPublisher pub = null;
+ CambriaBatchingPublisher pub;
try {
pub = new CambriaClientBuilders.PublisherBuilder()
.authenticatedBy(publisherKey, publisherSecret).usingHosts(urlList).onTopic(topicName).build();
} catch (MalformedURLException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
+ logger.error("pub.build Exception ", e1);
+ throw new UebException(PortalApiConstants.ECOMP_UEB_UNKNOWN_PUBLISH_ERROR, e1, topicName, null, msg);
} catch (GeneralSecurityException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
+ logger.error("pub.build Exception ", e1);
+ throw new UebException(PortalApiConstants.ECOMP_UEB_UNKNOWN_PUBLISH_ERROR, e1, topicName, null, msg);
}
try {
@@ -121,4 +122,4 @@ public class Publisher {
}
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java
index a3a00782..6919236f 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/PublisherList.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -74,4 +74,4 @@ public class PublisherList {
return this.map.size();
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java
index b9d730eb..8593b5bb 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/TopicManager.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -25,7 +25,9 @@ import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import com.att.nsa.apiClient.http.HttpClient;
import com.att.nsa.apiClient.http.HttpException;
import com.att.nsa.cambria.client.CambriaClient.CambriaApiException;
import com.att.nsa.cambria.client.CambriaClientBuilders;
@@ -36,6 +38,7 @@ import com.att.nsa.cambria.client.CambriaTopicManager;
* Provides methods to facilitate creating topics, and adding publishers and
* subscribers to existing topics.
*
+ * Utilizes UEB/Cambria subscriber/publisher messaging service.
*/
public class TopicManager {
@@ -64,8 +67,13 @@ public class TopicManager {
logger.info("topicName: " + topicName);
logger.info("topicDescription: " + topicDescription);
}
- final CambriaTopicManager tm = null; //to do for open source
- //CambriaClientFactory.createTopicManager(urlList, key, secret);
+ CambriaTopicManager tm =null;
+ try {
+ tm = CambriaClientFactory.createTopicManager(null, urlList, key, secret);
+ } catch (GeneralSecurityException e) {
+ logger.error("pub.build Exception ", e);
+ throw new CambriaApiException(topicName);
+ }
tm.createTopic(topicName, topicDescription, 1, 1);
}
@@ -88,7 +96,7 @@ public class TopicManager {
CambriaTopicManager tm = null;
try {
tm = new CambriaClientBuilders.TopicManagerBuilder().usingHosts(urlList).authenticatedBy(topicOwnerKey, topicOwnerSecret).build();
- } catch (GeneralSecurityException e) {
+ } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
@@ -109,13 +117,19 @@ public class TopicManager {
* @throws IOException
*/
+ @SuppressWarnings("deprecation")
public void addPublisher(String topicOwnerKey, String topicOwnerSecret, String publisherKey, String topicName)
throws HttpException, CambriaApiException, IOException {
logger.info("==> addPublisher to topic " + topicName);
final LinkedList<String> urlList = Helper.uebUrlList();
- final CambriaTopicManager tm = null;
- //CambriaClientFactory.createTopicManager(urlList, topicOwnerKey,
- //topicOwnerSecret);
+ CambriaTopicManager tm =null;
+ try {
+ tm = CambriaClientFactory.createTopicManager(HttpClient.ConnectionType.HTTPS, urlList, topicOwnerKey,
+ topicOwnerSecret);
+ } catch (GeneralSecurityException e) {
+ logger.error("pub.build Exception ", e);
+ throw new CambriaApiException(topicName);
+ }
tm.allowProducer(topicName, publisherKey);
}
}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java
index 62a80dd4..875ba58d 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebException.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java
index b38bcb79..7bf6de35 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebManager.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -27,8 +27,8 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
/**
* Manages UEB interactions and provides methods for publishing requests,
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java
index ff30840c..da18c4f8 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsg.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -24,8 +24,8 @@ import java.net.UnknownHostException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java
index 9e51fe5c..28ab327f 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/UebMsgTypes.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java
index d4063606..db0ee1b9 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/onboarding/ueb/WaitingRequestersQueueList.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java
index a8242234..a8242234 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/HttpStatusAndResponse.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java
index a7c517ec..b74d87c4 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/PortalRestClientBase.java
@@ -38,10 +38,10 @@ import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.openecomp.portalsdk.core.domain.App;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.service.AppService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java
index f017a7df..91f4652a 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/restful/client/SharedContextRestClient.java
@@ -25,8 +25,8 @@ import java.util.List;
import org.apache.http.client.utils.URIBuilder;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
import org.openecomp.portalsdk.core.restful.domain.SharedContext;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,8 +40,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Provides convenience methods to use the shared-context service at Portal.
- * This hides all JSON; instead it accepts and returns Java objects.
- * Usage caveats (repeated from superclass):
+ * This hides all JSON; instead it accepts and returns Java objects. Usage
+ * caveats (repeated from superclass):
* <OL>
* <LI>Must be auto-wired by Spring, because this in turn auto-wires a data
* access service to read application credentials from the FN_APP table.
@@ -55,8 +55,8 @@ public class SharedContextRestClient extends PortalRestClientBase {
@Autowired
SystemProperties systemProperties;
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SharedContextRestClient.class);
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SharedContextRestClient.class);
/**
* Reusable JSON (de)serializer
@@ -64,6 +64,21 @@ public class SharedContextRestClient extends PortalRestClientBase {
private final ObjectMapper mapper = new ObjectMapper();
/**
+ * Builds the URl for the shared context service using the portal.properties
+ * value for the AUXAPI endpoint.
+ *
+ * @throws Exception
+ * if the ECOMP_REST_URL property is not found
+ */
+ private String getSharedContextUrl() throws Exception {
+ String restUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
+ if (restUrl == null || restUrl.length() == 0)
+ throw new Exception("getSharedContextUrl: no property " + PortalApiConstants.ECOMP_REST_URL);
+ String contextUrl = restUrl + (restUrl.endsWith("/") ? "" : "/") + "context/";
+ return contextUrl;
+ }
+
+ /**
* Gets the shared-context value for the specified context ID and key.
*
* @param contextId
@@ -84,9 +99,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
try {
jsonObj = mapper.readValue(hsr.getResponse(), SharedContext.class);
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "getContextValue: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "getContextValue: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.info(EELFLoggerDelegate.applicationLogger, "getContextValue: failed to parse response" + ex.getMessage());
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "getContextValue: failed to parse response" + ex.getMessage());
}
if (jsonObj != null && jsonObj.getResponse() != null)
return null;
@@ -100,7 +117,8 @@ public class SharedContextRestClient extends PortalRestClientBase {
* An Ecomp Portal session ID
* @return List of SharedContext objects corresponding to the following
* keys: USER_FIRST_NAME, USER_LAST_NAME, USER_EMAIL and
- * USER_ORGUSERID; empty if none were found; null if an error happens.
+ * USER_ORGUSERID; empty if none were found; null if an error
+ * happens.
* @throws Exception
*/
public List<SharedContext> getUserContext(String contextId) throws Exception {
@@ -116,9 +134,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
};
jsonList = mapper.readValue(hsr.getResponse(), typeRef);
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "getUserContext: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "getUserContext: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "getUserContext: failed to parse response" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "getUserContext: failed to parse response" + ex.getMessage());
}
return jsonList;
}
@@ -146,9 +166,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
SharedContext jsonObj = mapper.readValue(hsr.getResponse(), SharedContext.class);
response = jsonObj.getResponse();
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "checkSharedContext: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "checkSharedContext: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "checkSharedContext: failed to parse response" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "checkSharedContext: failed to parse response" + ex.getMessage());
}
if (response == null)
return null;
@@ -176,9 +198,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
try {
jsonObj = mapper.readValue(hsr.getResponse(), SharedContext.class);
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "removeSharedContext: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "removeSharedContext: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "removeSharedContext: failed to parse response" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "removeSharedContext: failed to parse response" + ex.getMessage());
}
if (jsonObj == null)
return null;
@@ -207,9 +231,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
try {
jsonObj = mapper.readValue(hsr.getResponse(), SharedContext.class);
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "clearSharedContext: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "clearSharedContext: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "clearSharedContext: failed to parse response" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "clearSharedContext: failed to parse response" + ex.getMessage());
}
if (jsonObj == null)
return -1;
@@ -244,9 +270,11 @@ public class SharedContextRestClient extends PortalRestClientBase {
try {
jsonObj = mapper.readValue(hsr.getResponse(), SharedContext.class);
} catch (JsonMappingException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "setSharedContext: failed to map response onto object" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "setSharedContext: failed to map response onto object" + ex.getMessage());
} catch (JsonParseException ex) {
- logger.error(EELFLoggerDelegate.applicationLogger, "setSharedContext: failed to parse response" + ex.getMessage());
+ logger.error(EELFLoggerDelegate.applicationLogger,
+ "setSharedContext: failed to parse response" + ex.getMessage());
}
if (jsonObj == null)
return null;
@@ -264,14 +292,8 @@ public class SharedContextRestClient extends PortalRestClientBase {
* @return HttpStatusAndResponse object; may be null.
* @throws Exception
*/
- @SuppressWarnings("unused")
- private HttpStatusAndResponse getContext(String requestPath, String contextId, String contextKey) throws Exception{
- String restUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
- String portalDomain = restUrl.substring(0, restUrl.lastIndexOf('/'));
- String contextRestUrl = portalDomain + "/context";
- if (contextRestUrl == null)
- throw new Exception("getContext: failed to get property " + SystemProperties.ECOMP_SHARED_CONTEXT_REST_URL);
- URIBuilder uriBuilder = new URIBuilder(contextRestUrl + "/" + requestPath);
+ private HttpStatusAndResponse getContext(String requestPath, String contextId, String contextKey) throws Exception {
+ URIBuilder uriBuilder = new URIBuilder(getSharedContextUrl() + requestPath);
uriBuilder.addParameter("context_id", contextId);
if (contextKey != null)
uriBuilder.addParameter("ckey", contextKey);
@@ -290,10 +312,7 @@ public class SharedContextRestClient extends PortalRestClientBase {
* @throws Exception
*/
private HttpStatusAndResponse postContext(String requestPath, String json) throws Exception {
- String contextRestUrl = SystemProperties.getProperty(SystemProperties.ECOMP_SHARED_CONTEXT_REST_URL);
- if (contextRestUrl == null)
- throw new Exception("postContext: failed to get property " + SystemProperties.ECOMP_SHARED_CONTEXT_REST_URL);
- URIBuilder uriBuilder = new URIBuilder(contextRestUrl + "/" + requestPath);
+ URIBuilder uriBuilder = new URIBuilder(getSharedContextUrl() + requestPath);
URI uri = uriBuilder.build();
return postRestWithCredentials(uri, json);
}
@@ -321,7 +340,9 @@ public class SharedContextRestClient extends PortalRestClientBase {
// Simple test scaffold
public static void main(String[] args) throws Exception {
-
+ // ObjectMapper mapper = new ObjectMapper();
+ // SharedContext cxt = mapper.readValue("{ \"response\":\"foo\" }",
+ // SharedContext.class);
SharedContextRestClient client = new SharedContextRestClient();
SharedContext get = client.getContextValue("abc", "123");
System.out.println("Get yields " + get.toString());
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java
index 5f81308f..5f81308f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CoreRegister.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java
index fdfda984..dfd9a817 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/CronRegistry.java
@@ -25,6 +25,7 @@ import java.util.Map;
import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.quartz.CronTrigger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.QuartzJobBean;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java
index e2e4c385..e2e4c385 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/scheduler/Registerable.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppService.java
index 55180fd7..55180fd7 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java
index 30e566a2..b06b36fc 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AppServiceImpl.java
@@ -54,7 +54,7 @@ public class AppServiceImpl implements AppService{
/*
* (non-Javadoc)
- * @see org.openecomp.portalsdk.core.service.AppService#getApp(long)
+ * @see org.openecomp.portalsdk.service.AppService#getApp(long)
*/
@Override
public App getApp(Long appId) {
@@ -63,7 +63,7 @@ public class AppServiceImpl implements AppService{
/*
* (non-Javadoc)
- * @see org.openecomp.portalsdk.core.service.AppService#getApp()
+ * @see org.openecomp.portalsdk.service.AppService#getApp()
*/
@Override
public App getDefaultApp() {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java
index b632c92c..b228d1b1 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditService.java
@@ -31,6 +31,7 @@ public interface AuditService {
* @param auditLog
* @param additionalParams
*/
- @SuppressWarnings("rawtypes")
- void logActivity(AuditLog auditLog, HashMap additionalParams);
+
+ @SuppressWarnings("rawtypes")
+ void logActivity(AuditLog auditLog, HashMap additionalParams);
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java
index 8fbd550c..433cd2ac 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/AuditServiceImpl.java
@@ -35,7 +35,7 @@ public class AuditServiceImpl implements AuditService {
private DataAccessService dataAccessService;
@SuppressWarnings("rawtypes")
- public void logActivity(AuditLog auditLog, HashMap additionalParams) {
+ public void logActivity(AuditLog auditLog, HashMap additionalParams) {
getDataAccessService().saveDomainObject(auditLog, additionalParams);
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java
index 8d60e74b..66315b92 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastService.java
@@ -19,8 +19,7 @@
*/
package org.openecomp.portalsdk.core.service;
-import java.util.HashMap;
-import java.util.Hashtable;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java
index def1c1a6..92a77507 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/BroadcastServiceImpl.java
@@ -48,8 +48,8 @@ public class BroadcastServiceImpl extends FusionService implements BroadcastServ
public BroadcastServiceImpl() {
}
- @Autowired
- private DataAccessService dataAccessService;
+ @Autowired
+ private DataAccessService dataAccessService;
private static Hashtable broadcastMessages = new Hashtable();
@SuppressWarnings("unchecked")
@@ -64,7 +64,6 @@ public class BroadcastServiceImpl extends FusionService implements BroadcastServ
}
}
- @SuppressWarnings("unchecked")
public HashMap getBcModel(HttpServletRequest request){
HashMap bcModel = new HashMap();
@@ -131,14 +130,17 @@ public class BroadcastServiceImpl extends FusionService implements BroadcastServ
}
return messagesList;
- }
+ }
@SuppressWarnings("unchecked")
private List getPersistedBroadcastMessages(String locationId) {
-
HashMap params = new HashMap();
+
+
+
params.put("location_id", new Integer(locationId));
+
Calendar calInstanceToday = Calendar.getInstance();
calInstanceToday.set(Calendar.HOUR, 0);
calInstanceToday.set(Calendar.MINUTE, 0);
@@ -211,7 +213,7 @@ public class BroadcastServiceImpl extends FusionService implements BroadcastServ
}
public void setDataAccessService(DataAccessService dataAccessService) {
- this.dataAccessService = dataAccessService;
+ dataAccessService = dataAccessService;
}
public BroadcastMessage getBroadcastMessage(HttpServletRequest request) {
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java
index 26892b88..26892b88 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java
index a4644b72..9c52b1b4 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/DataAccessServiceImpl.java
@@ -99,13 +99,15 @@ public class DataAccessServiceImpl extends FusionService implements DataAccessSe
*/
@Override
public void deleteDomainObjects(Class domainClass, String whereClause, HashMap additionalParams) {
+ int rowsAffected = 0;
Session session = sessionFactory.getCurrentSession();
StringBuffer sql = new StringBuffer("delete from ");
sql.append(domainClass.getName()).append(" where ").append(whereClause);
- session.createQuery(sql.toString()).executeUpdate();
+ rowsAffected = session.createQuery(sql.toString()).executeUpdate();
+ /* return rowsAffected; */
}
/*
@@ -366,7 +368,7 @@ public class DataAccessServiceImpl extends FusionService implements DataAccessSe
* (non-Javadoc)
*
* @see
- * org.openecomp.portalsdk.core.service.DataAccessService#executeQuery(java.lang.
+ * org.openecomp.portalsdk.core.service.DataAccessService#executeQuery(java.lang.
* String, java.util.HashMap)
*/
@Override
@@ -474,7 +476,7 @@ public class DataAccessServiceImpl extends FusionService implements DataAccessSe
/*
* (non-Javadoc)
*
- * @see org.openecomp.portalsdk.core.service.DataAccessService#
+ * @see org.openecomp.portalsdk.core.service.DataAccessService#
* executeNamedQueryWithOrderBy(java.lang.Class, java.lang.String,
* java.util.Map, java.lang.String, boolean, java.lang.Integer,
* java.lang.Integer, java.util.HashMap)
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java
new file mode 100644
index 00000000..0cd90dc7
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java
@@ -0,0 +1,290 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.util.YamlUtils;
+
+public class ElementLinkService {
+
+ /**
+ * Builds renderable model of element links in the network map. Parses YAML
+ * files with metadata and builds input for JoinJS to render in the browser
+ * as SVG.
+ *
+ * @param args
+ * arg 0 - realPath; arg 1 - callFlowName; arg 2 - callFlowStep.
+ * @return Renderable model of element links
+ * @throws Exception
+ */
+ public String buildElementLinkYaml(String[] args) throws Exception {
+ String relFilePath;
+ if (args[1].startsWith("custom"))
+ relFilePath = SystemProperties.getProperty("customCallFlow_path");
+ else
+ relFilePath = SystemProperties.getProperty("element_map_file_path");
+ final String yamlDirPath = new File(args[0], relFilePath).getPath();
+
+ String callFlowBusinessYml = "";
+ String callFlowStep = "";
+
+ if (args != null && args.length > 0) {
+ if (args[1] != null)
+ callFlowBusinessYml = args[1] + ".yml";
+ if (args[2] != null)
+ callFlowStep = args[2];
+ }
+
+ ElementLinkService mapper = new ElementLinkService();
+ String linkYaml = mapper.createLinkFile(yamlDirPath, callFlowBusinessYml, callFlowStep);
+ return linkYaml;
+ }
+
+ /*
+ * public String main2(String[] args) throws Exception {
+ *
+ * String filePath = SystemProperties.getProperty("element_map_file_path") +
+ * File.separator; String callFlowBusinessYml = ""; String callFlowStep =
+ * "";
+ *
+ * if (args != null && args.length > 0) {
+ *
+ * if (args[0] != null) { callFlowBusinessYml = args[0] + "-Override.yml"; }
+ *
+ * if (args[1] != null) { callFlowStep = args[1]; } }
+ *
+ * ElementLinkService mapper = new ElementLinkService();
+ *
+ * return mapper.createLinkFileAdditional(filePath, callFlowBusinessYml,
+ * callFlowStep); }
+ */
+
+ public static void main(String[] args) throws Exception {
+
+ String filePath = "\\D2Platform\\war\\WEB-INF\\resources\\trisim_files";
+ String callFlowBusinessYml = "call_flow_hc-origination-termination-to-volteue-3.3.16-Override.yml";
+
+ ElementLinkService mapper = new ElementLinkService();
+
+ // System.out.print(mapper.createLinkFile(filePath, networkToscaYml,
+ // networkToscaUeYml, networkLayoutYml, callFlowBusinessYml,"Step_1"));
+ System.out.print(mapper.createLinkFileAdditional(filePath, callFlowBusinessYml, "Step_2"));
+ }
+
+ @SuppressWarnings("unchecked")
+ protected String createLinkFile(String resourceFilePath, String callFLowBsFileName, String callFlowStep)
+ throws Exception {
+
+ Map<String, Object> callFlowBs = YamlUtils.readYamlFile(resourceFilePath, callFLowBsFileName);
+
+ List<Map<String, Object>> callSteps = (List<Map<String, Object>>) callFlowBs.get("callSequenceSteps");
+ String callFlowName = (String) callFlowBs.get("shortName");
+ return addLinks(resourceFilePath, callFlowName, callSteps, callFlowStep);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ protected String createLinkFileAdditional(String resourceFilePath, String callFLowBsFileName, String callFlowStep)
+ throws Exception {
+
+ // Map<String, Object> callFlowBs =
+ // YamlUtils.readYamlFile(resourceFilePath, callFLowBsFileName);
+
+ // return YamlUtils.returnYaml(callFlowBs);
+
+ Map<String, Object> callFlowBs;
+
+ try {
+ callFlowBs = YamlUtils.readYamlFile(resourceFilePath, callFLowBsFileName);
+
+ List<Map<String, Object>> callSteps = (List<Map<String, Object>>) callFlowBs.get("callSequenceSteps");
+ String callFlowName = (String) callFlowBs.get("shortName");
+ return addLinksAdditional(resourceFilePath, callFlowName, callSteps, callFlowStep);
+
+ } catch (Exception e) {
+
+ return "";
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ protected String addLinks(String filePath, String callFlowName, List<Map<String, Object>> callSteps,
+ String callFlowStep) throws IOException {
+
+ Map<String, List<String>> checkDuplicateMap = new HashMap<String, List<String>>();
+
+ for (Map<String, Object> callStep : callSteps) {
+
+ if (((String) callStep.get("name")).split(":")[0].trim().replace(" ", "_").equals(callFlowStep)) {
+
+ // String callFlowStepName = callFlowName + "_" +
+ // ((String)callStep.get("name")).split("-")[0].trim().replace("
+ // ", "_")+".yml";
+
+ List<Map<String, Object>> links = new ArrayList<Map<String, Object>>();
+
+ List<Map<String, Object>> subSteps = (List<Map<String, Object>>) callStep.get("subSteps");
+
+ for (Map<String, Object> subStep : subSteps) {
+ Map<String, Object> link = new HashMap<String, Object>();
+
+ String source = (String) subStep.get("source_tosca_id");
+ String destination = (String) subStep.get("destination_tosca_id");
+
+ if ((checkDuplicateMap.get(source) == null || checkDuplicateMap.get(source).isEmpty()
+ || !checkDuplicateMap.get(source).contains(destination)) && !source.equals(destination)) {
+ if (checkDuplicateMap.get(destination) == null) {
+ List<String> toscaList = new ArrayList<String>();
+ checkDuplicateMap.put(destination, toscaList);
+ }
+
+ if (checkDuplicateMap.get(source) == null) {
+ List<String> toscaList = new ArrayList<String>();
+ checkDuplicateMap.put(source, toscaList);
+ }
+
+ List<String> toscaSourceList = checkDuplicateMap.get(destination);
+ toscaSourceList.add(source);
+
+ List<String> toscaDestinationList = checkDuplicateMap.get(source);
+ toscaDestinationList.add(destination);
+
+ link.put("s", source);
+ link.put("d", destination);
+ links.add(link);
+
+ /*
+ * may be needed in future but nnot currently
+ *
+ * if((String) subStep.get("link_visibility")!=null){
+ * if(((String)
+ * subStep.get("link_visibility")).equals("No")){
+ *
+ * } }else{
+ *
+ * links.add(link); }
+ */
+
+ }
+
+ }
+
+ Map<String, Object> callFlowUI = new HashMap<String, Object>();
+ callFlowUI.put("linkList", links);
+
+ return YamlUtils.returnYaml(callFlowUI);
+
+ // YamlUtils.writeYamlFile(filePath, callFlowStepName,
+ // callFlowUI);
+ }
+
+ }
+ return "";
+ }
+
+ protected String addLinksAdditional(String filePath, String callFlowName, List<Map<String, Object>> callSteps,
+ String callFlowStep) throws IOException {
+
+ for (Map<String, Object> callStep : callSteps) {
+
+ if (((String) callStep.get("name")).split(":")[0].trim().replace(" ", "_").equals(callFlowStep)) {
+
+ // String callFlowStepName = callFlowName + "_" +
+ // ((String)callStep.get("name")).split("-")[0].trim().replace("
+ // ", "_")+".yml";
+
+ Map<String, Object> callFlowUI = new HashMap<String, Object>();
+ try {
+ List<Map<String, Object>> links = addLinkVertices(callStep);
+ callFlowUI.put("linkList", links);
+ } catch (Exception e) {
+ }
+ try {
+ List<String> activeIds = addActiveNodes(callStep);
+ callFlowUI.put("activeIds", activeIds);
+ } catch (Exception e) {
+ }
+ try {
+ List<Map<String, Object>> disconnectLinks = addDisconnectLinks(callStep);
+ callFlowUI.put("disconnectLinks", disconnectLinks);
+ } catch (Exception e) {
+ }
+
+ return YamlUtils.returnYaml(callFlowUI);
+ }
+ }
+
+ return "";
+ }
+
+ @SuppressWarnings("unchecked")
+ List<String> addActiveNodes(Map<String, Object> callStep) {
+ List<String> activeIds = (List<String>) callStep.get("activeIds");
+ return activeIds;
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> addDisconnectLinks(Map<String, Object> callStep) {
+ List<Map<String, Object>> disconnectLinks = (List<Map<String, Object>>) callStep.get("disconnectLinks");
+ return disconnectLinks;
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> addLinkVertices(Map<String, Object> callStep) {
+ List<Map<String, Object>> links = new ArrayList<Map<String, Object>>();
+
+ List<Map<String, Object>> vertices = (List<Map<String, Object>>) callStep.get("vertices");
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Map<String, Object> vertex = (Map<String, Object>) vertices.get(i);
+ Map<String, Object> vertexNext = (Map<String, Object>) vertices.get(i + 1);
+
+ Integer sourceX = (Integer) vertex.get("x");
+ Integer sourceY = (Integer) vertex.get("y");
+ String sourceD = (String) vertex.get("D");
+ String sourceL = (vertex.get("L") != null) ? (String) vertex.get("L") : "-";
+
+ if (sourceX == -999) // there is a break in the linkage
+ continue;
+
+ Integer destinationX = (Integer) vertexNext.get("x");
+ Integer destinationY = (Integer) vertexNext.get("y");
+ String destinationD = (String) vertexNext.get("D");
+
+ if (destinationX == -999) // there is a break in the linkage
+ continue;
+
+ Map<String, Object> link = new HashMap<String, Object>();
+
+ link.put("s", sourceX + "," + sourceY + "," + sourceD + "," + sourceL);
+ link.put("d", destinationX + "," + destinationY + "," + destinationD);
+ links.add(link);
+ }
+ return links;
+ }
+}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java
new file mode 100644
index 00000000..8213a5ba
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java
@@ -0,0 +1,1029 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.portalsdk.core.domain.support.Container;
+import org.openecomp.portalsdk.core.domain.support.Domain;
+import org.openecomp.portalsdk.core.domain.support.Element;
+import org.openecomp.portalsdk.core.domain.support.ElementDetails;
+import org.openecomp.portalsdk.core.domain.support.Layout;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.openecomp.portalsdk.core.util.YamlUtils;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.nodes.Tag;
+import org.yaml.snakeyaml.representer.Representer;
+
+public class ElementMapService {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ElementMapService.class);
+
+ /**
+ *
+ * @param contextRealPath
+ * @param layout
+ * @return
+ * @throws Exception
+ */
+ private String convertToYAML(String contextRealPath, Layout layout) throws Exception {
+
+ // Used to build image file relative URLs
+ final String iconRelPath = SystemProperties.getProperty("element_map_icon_path"); // "static/img/map/icons/";
+
+ Map<String, Domain> resultAICDomain = layout.domainRowCol;
+ Map<String, List<Domain>> domainMap = new HashMap<String, List<Domain>>();
+ List<Domain> domainList = new ArrayList<Domain>();
+ for (Domain d : resultAICDomain.values()) {
+ d.setWidth(10 * d.computeSize().getWidth());
+ d.setHeight(10 * d.computeSize().getHeight());
+ d.setLeft(10 * d.getP().getX());
+ d.setTop(10 * d.getP().getY());
+
+ List<Container> containerList = new ArrayList<Container>();
+ for (Container c : d.getContainerRowCol().values()) {
+ c.setWidth(10 * c.computeSize().getWidth());
+ c.setHeight(10 * c.computeSize().getHeight());
+ c.setLeft(10 * c.getP().getX());
+ c.setTop(10 * c.getP().getY());
+ Element ue = (Element) c.getElementRowCol().values().toArray()[0];
+ if (ue.getName().equals("ue1") || ue.getName().equals("ue2") || ue.getName().equals("ue3")
+ || ue.getName().equals("ue4") || ue.getName().equals("ue5") || ue.getName().equals("ue6")) {
+ c.setVisibilityType("invisible");
+ }
+
+ if (c.getContainerRowCol() != null) {
+ List<Container> innerContainerList = new ArrayList<Container>();
+ for (Container innerC : c.getContainerRowCol().values()) {
+ innerC.setName(innerC.getName());
+ innerC.setWidth(10 * innerC.computeSize().getWidth());
+ innerC.setHeight(10 * innerC.computeSize().getHeight());
+ innerC.setLeft(10 * innerC.getP().getX());
+ innerC.setTop(10 * innerC.getP().getY());
+
+ if (innerC.getElementRowCol() != null) {
+ List<Element> innerContainerEList = new ArrayList<Element>();
+ for (Element ele : innerC.getElementRowCol().values()) {
+ // ele.setName(ele.getName());
+ ele.setWidth(10 * ele.computeSize().getWidth());
+ ele.setHeight(10 * ele.computeSize().getHeight());
+ ele.setLeft(10 * ele.getP().getX());
+ ele.setTop(10 * ele.getP().getY() - 10);
+ ele.setImgFileName(iconRelPath + "/" + ele.getImgFileName());
+ if (ele.getBorderType().equals("V"))
+ ele.setBorderType("dashed");
+ else
+ ele.setBorderType("solid");
+ innerContainerEList.add(ele);
+ }
+ innerC.setElementList(innerContainerEList);
+ }
+ innerContainerList.add(innerC);
+ }
+ c.setInnerCList(innerContainerList);
+ }
+
+ if (c.getElementRowCol() != null) {
+ List<Element> elementList = new ArrayList<Element>();
+ for (Element e : c.getElementRowCol().values()) {
+ // e.setName(e.getName());
+ e.setWidth(10 * e.computeSize().getWidth());
+ e.setHeight(10 * e.computeSize().getHeight());
+ e.setLeft(10 * e.getP().getX());
+ e.setTop(10 * e.getP().getY() - 10);
+ e.setImgFileName(iconRelPath + "/" + e.getImgFileName());
+
+ if (e.getBorderType().equals("V"))
+ e.setBorderType("dashed");
+ else
+ e.setBorderType("solid");
+
+ if (e.getName().equals("ue1") || e.getName().equals("ue2") || e.getName().equals("ue3")
+ || e.getName().equals("ue4") || e.getName().equals("ue5") || e.getName().equals("ue6"))
+ e.setBgColor("white");
+ elementList.add(e);
+ }
+ c.setElementList(elementList);
+ }
+ containerList.add(c);
+ }
+ d.setContainerList(containerList);
+ domainList.add(d);
+
+ }
+ domainMap.put("domainList", domainList);
+
+ List<Domain> collapsedDomains = new ArrayList<Domain>();
+
+ // nline
+ for (Domain collapsed : layout.getCollapsedDomainsNewList()) {
+ collapsed.setWidth(10 * collapsed.computeSize().getWidth());
+ collapsed.setHeight(10 * collapsed.computeSize().getHeight());
+ collapsed.setLeft(10 * collapsed.getP().getX());
+ collapsed.setTop(10 * collapsed.getP().getY());
+ // nline
+ collapsed.setNewXafterColl(10 * collapsed.getNewXafterColl());
+ collapsed.setYafterColl(10 * collapsed.getYafterColl());
+ collapsedDomains.add(collapsed);
+ }
+
+ domainMap.put("collapsedDomainList", collapsedDomains);
+
+ Representer representer = new Representer();
+ representer.addClassTag(Domain.class, Tag.MAP);
+
+ Yaml yaml = new Yaml(representer);
+ String output = yaml.dump(domainMap);
+
+ return output;
+
+ }
+
+ private static HashMap<String, Object> toscaElementsMap = new HashMap<String, Object>();
+ private static HashMap<String, Element> elementMap = new HashMap<String, Element>();
+ private static HashMap<String, Element> miscElementMap = new HashMap<String, Element>();
+ private static HashMap<String, Container> outercontainers = new HashMap<String, Container>();
+ private static HashMap<String, Container> innercontainers = new HashMap<String, Container>();
+ private static HashMap<String, Domain> domainMap = new HashMap<String, Domain>();
+
+ private static String filePath = SystemProperties.getProperty("element_map_file_path");
+ private static String networkToscaYml = null;// "NetworkMap_topology_composition.yml";
+ private static String networkLayoutYml = null;// "network_map_layout.yml";
+
+ /**
+ * Builds renderable model of elements in the network map. Parses YAML files
+ * with metadata and builds input for JoinJS to render in the browser as
+ * SVG.
+ *
+ * @param args
+ * arg 0 - collapsedDomains; arg 1 - expandedDomains; arg 2 -
+ * context real path; arg 3 - contentFileName; arg 4 -
+ * layoutFileName
+ * @return Renderable model of elements
+ * @throws Exception
+ */
+ public String buildElementMapYaml(String args[]) throws Exception {
+
+ final String yamlDirPath = new File(args[2], filePath).getPath();
+ if (args != null && args.length > 4) {
+ if (args[3] != null)
+ networkToscaYml = args[3] + ".yml";
+ if (args[4] != null)
+ networkLayoutYml = args[4] + ".yml";
+ }
+
+ Map<String, Object> toscaYaml = YamlUtils.readYamlFile(yamlDirPath, networkToscaYml);
+ Map<String, Object> networkMapLayoutYaml = YamlUtils.readYamlFile(yamlDirPath, networkLayoutYml);
+
+ toscaElementsMap = new HashMap<String, Object>();
+ elementMap = new HashMap<String, Element>();
+ domainMap = new HashMap<String, Domain>();
+ outercontainers = new HashMap<String, Container>();
+ innercontainers = new HashMap<String, Container>();
+ miscElementMap = new HashMap<String, Element>();
+
+ if (toscaYaml != null) {
+ for (String key : toscaYaml.keySet()) {
+ if ("topology_template".equalsIgnoreCase(key) && toscaYaml.get(key) instanceof HashMap) {
+ HashMap<String, Object> toscaTopologyDetails = (HashMap<String, Object>) toscaYaml.get(key);
+
+ for (String detailsKey : toscaTopologyDetails.keySet()) {
+
+ if ("node_templates".equalsIgnoreCase(detailsKey)
+ && toscaTopologyDetails.get(detailsKey) instanceof HashMap) {
+
+ toscaElementsMap = (HashMap<String, Object>) toscaTopologyDetails.get(detailsKey);
+
+ // for (String toscaElementKey :
+ // toscaElementsMap.keySet()) {
+ //// System.out.println("Element - "+ "key :" +
+ //// toscaElementKey);
+ // }
+
+ }
+ }
+ }
+
+ }
+ }
+
+ if (networkMapLayoutYaml != null) {
+ if (networkMapLayoutYaml.containsKey("toscaNetworkMapElementStyleList")
+ && networkMapLayoutYaml.get("toscaNetworkMapElementStyleList") instanceof ArrayList) {
+
+ ArrayList<Object> elementlist = (ArrayList<Object>) networkMapLayoutYaml
+ .get("toscaNetworkMapElementStyleList");
+ String elementName;
+ String elementID;
+ String imgPath;
+ String row;
+ String column;
+ String mapKey;
+ int i = 0;
+
+ if (elementlist != null) {
+ for (Object eachElement : elementlist) {
+ // System.out.println("toscaNetworkMapElementStyleList
+ // Container : " +eachElement);
+ if (eachElement != null && eachElement instanceof HashMap) {
+ HashMap<String, String> elementDetails = (HashMap<String, String>) eachElement;
+ if (elementDetails != null) {
+ elementName = "NA" + i;
+ elementID = "NA" + i;
+ imgPath = "NA" + i;
+ row = "0";
+ column = "0";
+ for (String detailsKey : elementDetails.keySet()) {
+ if ("tosca_id".equalsIgnoreCase(detailsKey))
+ elementName = elementDetails.get(detailsKey).toString();
+ if ("id".equalsIgnoreCase(detailsKey)) {
+ elementID = String.valueOf(elementDetails.get(detailsKey));
+ }
+ if ("row".equalsIgnoreCase(detailsKey)) {
+ row = String.valueOf(elementDetails.get(detailsKey));
+ }
+ if ("column".equalsIgnoreCase(detailsKey)) {
+ column = String.valueOf(elementDetails.get(detailsKey));
+ }
+ if ("icon".equalsIgnoreCase(detailsKey))
+ imgPath = elementDetails.get(detailsKey).toString();
+ }
+
+ if (elementMap.containsKey(elementName.concat("/").concat(row).concat(column))) {
+ if (elementMap.containsKey(elementName.concat("/").concat(String.valueOf(i))
+ .concat(String.valueOf(i)))) {
+ mapKey = elementName;
+ } else
+ mapKey = elementName.concat("/").concat(String.valueOf(i))
+ .concat(String.valueOf(i));
+
+ } else
+ mapKey = elementName.concat("/").concat(row).concat(column);
+
+ elementMap.put(mapKey, fetchElementObject(elementID, elementName, imgPath));
+ }
+ }
+ i++;
+ }
+ }
+
+ for (String elementkey : elementMap.keySet()) {
+ Element c = (Element) elementMap.get(elementkey);
+ // System.out.println("Element - "+ "key :" +elementkey +" -
+ // " + "value :" + c.getName());
+ }
+
+ if (!elementMap.isEmpty()) {
+ miscElementMap = new HashMap<String, Element>(elementMap);
+ }
+ }
+
+ if (networkMapLayoutYaml.containsKey("containerStyleList")
+ && networkMapLayoutYaml.get("containerStyleList") instanceof ArrayList) {
+
+ ArrayList<Object> containerstylelist = (ArrayList<Object>) networkMapLayoutYaml
+ .get("containerStyleList");
+ String containerName;
+ String containerID;
+ String domain;
+ String row;
+ String column;
+ String mapKey;
+ int i = 0;
+
+ if (containerstylelist != null) {
+ // Inner Containers
+ for (Object eachContainer : containerstylelist) {
+ if (eachContainer != null && eachContainer instanceof HashMap) {
+ HashMap<String, String> containerDetails = (HashMap<String, String>) eachContainer;
+ if (containerDetails != null) {
+ containerName = "NA" + i;
+ containerID = "NA" + i;
+ domain = "NA" + i;
+ row = "0";
+ column = "0";
+
+ for (String detailsKey : containerDetails.keySet()) {
+ if ("logical_group_name".equalsIgnoreCase(detailsKey))
+ containerName = containerDetails.get(detailsKey).toString();
+ if ("id".equalsIgnoreCase(detailsKey)) {
+ containerID = String.valueOf(containerDetails.get(detailsKey));
+ }
+ if ("domain".equalsIgnoreCase(detailsKey)) {
+ domain = containerDetails.get(detailsKey).toString();
+ }
+ if ("row".equalsIgnoreCase(detailsKey)) {
+ row = String.valueOf(containerDetails.get(detailsKey));
+ }
+ if ("column".equalsIgnoreCase(detailsKey)) {
+ column = String.valueOf(containerDetails.get(detailsKey));
+ }
+ }
+ if (containerName.contains("/")) {
+
+ if (innercontainers.containsKey(
+ (domain + ":" + containerName).concat("/").concat(row).concat(column))) {
+ if (elementMap.containsKey((domain + ":" + containerName).concat("/")
+ .concat(String.valueOf(i)).concat(String.valueOf(i)))) {
+ mapKey = (domain + ":" + containerName);
+ } else
+ mapKey = (domain + ":" + containerName).concat("/")
+ .concat(String.valueOf(i)).concat(String.valueOf(i));
+
+ } else
+ mapKey = (domain + ":" + containerName).concat("/").concat(row).concat(column);
+
+ innercontainers.put(mapKey,
+ fetchContainerObject(containerID,
+ containerName.substring(containerName.indexOf("/") + 1), true,
+ containerName, domain));
+ }
+ }
+ }
+ i++;
+ }
+
+ // OuterContainers
+ i = 0;
+ for (Object eachContainer : containerstylelist) {
+ if (eachContainer != null && eachContainer instanceof HashMap) {
+ HashMap<String, String> containerDetails = (HashMap<String, String>) eachContainer;
+ if (containerDetails != null) {
+ containerName = "NA" + i;
+ containerID = "NA" + i;
+ domain = "NA" + i;
+ row = "0";
+ column = "0";
+
+ for (String detailsKey : containerDetails.keySet()) {
+ if ("logical_group_name".equalsIgnoreCase(detailsKey))
+ containerName = containerDetails.get(detailsKey).toString();
+ if ("id".equalsIgnoreCase(detailsKey)) {
+ containerID = String.valueOf(containerDetails.get(detailsKey));
+ }
+ if ("domain".equalsIgnoreCase(detailsKey)) {
+ domain = containerDetails.get(detailsKey).toString();
+ }
+ if ("row".equalsIgnoreCase(detailsKey)) {
+ row = String.valueOf(containerDetails.get(detailsKey));
+ }
+ if ("column".equalsIgnoreCase(detailsKey)) {
+ column = String.valueOf(containerDetails.get(detailsKey));
+ }
+ }
+ if (!containerName.contains("/")) {
+ if (outercontainers.containsKey(
+ (domain + ":" + containerName).concat("/").concat(row).concat(column))) {
+ if (outercontainers.containsKey((domain + ":" + containerName).concat("/")
+ .concat(String.valueOf(i)).concat(String.valueOf(i)))) {
+ mapKey = (domain + ":" + containerName);
+ } else
+ mapKey = (domain + ":" + containerName).concat("/")
+ .concat(String.valueOf(i)).concat(String.valueOf(i));
+
+ } else
+ mapKey = (domain + ":" + containerName).concat("/").concat(row).concat(column);
+ outercontainers.put(mapKey, fetchContainerObject(containerID, containerName, false,
+ containerName, domain));
+ }
+ // else innercontainers.put(domain +":"+
+ // containerName,
+ // fetchContainerObject(containerID,containerName.substring(containerName.indexOf("/")+1),false,containerName,domain));
+
+ }
+ }
+ i++;
+ }
+ }
+
+ for (String innerContainerkey : innercontainers.keySet()) {
+ Container c = (Container) innercontainers.get(innerContainerkey);
+ }
+
+ for (String outerContainerkey : outercontainers.keySet()) {
+ Container c = (Container) outercontainers.get(outerContainerkey);
+ }
+
+ }
+
+ if (networkMapLayoutYaml.containsKey("domainList")
+ && networkMapLayoutYaml.get("domainList") instanceof ArrayList) {
+
+ ArrayList<Object> domainlist = (ArrayList<Object>) networkMapLayoutYaml.get("domainList");
+ String domainName;
+ String domainID;
+ String row;
+ String column;
+ String mapKey;
+ int i = 0;
+
+ if (domainlist != null) {
+
+ HashMap<String, String> domainStagingMap = new HashMap<String, String>();
+ for (Object eachDomain : domainlist) {
+ // System.out.println("domainlist Container : "
+ // +eachDomain);
+ if (eachDomain != null && eachDomain instanceof HashMap) {
+ HashMap<String, String> domainDetails = (HashMap<String, String>) eachDomain;
+ if (domainDetails != null) {
+ domainName = "NA" + i;
+ domainID = "NA" + i;
+ row = "0";
+ column = "0";
+ for (String detailsKey : domainDetails.keySet()) {
+ if ("name".equalsIgnoreCase(detailsKey))
+ domainName = domainDetails.get(detailsKey).toString();
+ if ("id".equalsIgnoreCase(detailsKey)) {
+ domainID = String.valueOf(domainDetails.get(detailsKey));
+ }
+ if ("row".equalsIgnoreCase(detailsKey)) {
+ row = String.valueOf(domainDetails.get(detailsKey));
+ }
+ if ("column".equalsIgnoreCase(detailsKey)) {
+ column = String.valueOf(domainDetails.get(detailsKey));
+ }
+ }
+
+ if (domainStagingMap.containsKey(row.concat(column))) {
+ mapKey = domainName;
+ } else
+ mapKey = row.concat(column);
+
+ domainStagingMap.put(mapKey, domainID + "%" + domainName);
+ }
+ }
+ i++;
+ }
+
+ if (domainStagingMap != null && !domainStagingMap.isEmpty()) {
+ for (String domainsKey : new TreeSet<String>(domainStagingMap.keySet())) {
+ String value = domainStagingMap.get(domainsKey);
+ if (value.contains("%")) {
+ domainMap.put(domainsKey, fetchDomainObject(value.substring(0, value.indexOf("%")),
+ value.substring(value.indexOf("%") + 1)));
+ }
+ }
+ }
+ }
+
+ // for (String domainkey : domainMap.keySet()) {
+ // Domain c = (Domain) domainMap.get(domainkey);
+ // System.out.println("Domain - "+ "key :" +domainkey +" - "
+ // + "value :" + c.getName());
+ // }
+ }
+
+ }
+
+ Layout dynamicLayout = new Layout(domainMap, 2, 10, 1, 5);
+ dynamicLayout.computeDomainPositionsModified();
+
+ /*
+ * Map<String, Domain> resultAICDomain2 = dynamicLayout.domainRowCol;
+ * for (String key : resultAICDomain2.keySet()) { if
+ * (resultAICDomain2.get(key).getP() != null) {
+ * System.out.println(resultAICDomain2.get(key).name+" "+"x:"+
+ * resultAICDomain2.get(key).getP().getX()+","+"y:"+
+ * resultAICDomain2.get(key).getP().getY()+","+"width:"+
+ * resultAICDomain2.get(key).computeSize().getWidth()
+ * +","+"height:"+resultAICDomain2.get(key).computeSize(). getHeight());
+ *
+ * } }
+ */
+
+ ElementMapService cm2 = new ElementMapService();
+ try {
+
+ if (args != null && args.length > 0) {
+
+ if (args[0] != null) {
+ String collapsedDomains[] = args[0].split(",");
+ for (String collapsedDomain : collapsedDomains)
+ // dynamicLayout.collapseDomainModified(collapsedDomain);
+ dynamicLayout.collapseDomainNew(collapsedDomain);
+ }
+
+ if (args[1] != null) {
+ String expandedDomains[] = args[1].split(",");
+ for (String expandedDomain : expandedDomains)
+ // dynamicLayout.uncollapseDomainNew(expandedDomain);
+ dynamicLayout.uncollapseDomainNew1(expandedDomain);
+ }
+
+ return cm2.convertToYAML(args[2], dynamicLayout);
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "buildElementMapYaml failed", e);
+ }
+
+ return "";
+ }
+
+ private static int computeRows(Set<String> keys) {
+ int i = 0;
+ if (keys != null && !keys.isEmpty()) {
+ for (String s : keys) {
+ String r = s.substring(0, 1);
+ if (StringUtils.isNumeric(r)) {
+ int j = Integer.parseInt(r);
+ if (i <= j) {
+ i = j;
+ }
+
+ }
+ }
+
+ return i + 1;
+ }
+
+ return 1;
+ }
+
+ private static int computeColumns(Set<String> keys) {
+ int i = 0;
+ if (keys != null && !keys.isEmpty()) {
+ for (String s : keys) {
+ String r = s.substring(1, 2);
+ if (StringUtils.isNumeric(r)) {
+ int j = Integer.parseInt(r);
+ if (i <= j) {
+ i = j;
+ }
+
+ }
+ }
+
+ return i + 1;
+ }
+
+ return 1;
+ }
+
+ private static Container fetchContainerObject(String id, String name, boolean isInner, String logicalGroupName,
+ String domain) {
+ Map<String, Element> containerElementsMap = new HashMap<String, Element>();
+
+ containerElementsMap = fetchElementsMapForContainer(name, isInner, logicalGroupName, domain);
+ int rows = 1;
+ int columns = 1;
+
+ if (isInner) {
+
+ if (containerElementsMap != null && !containerElementsMap.isEmpty()) {
+ rows = computeRows(containerElementsMap.keySet());
+ columns = computeColumns(containerElementsMap.keySet());
+ }
+
+ Container thisContainer = new Container(id, name, rows, columns, 1, 4, 8, 12, 1, 2);
+ thisContainer.setElements(containerElementsMap);
+ // thisContainer.setVisibilityType("");
+
+ return thisContainer;
+ } else {
+ Map<String, Container> innerContainersMap = fetchInnerContainersMapForOuter(name, isInner, logicalGroupName,
+ domain);
+
+ if (innerContainersMap != null && !innerContainersMap.isEmpty()) {
+ if (containerElementsMap != null && !containerElementsMap.isEmpty()) {
+ Set<String> keys = new HashSet<String>(innerContainersMap.keySet());
+ keys.addAll(containerElementsMap.keySet());
+ rows = computeRows(keys);
+ columns = computeColumns(keys);
+ } else {
+ rows = computeRows(innerContainersMap.keySet());
+ columns = computeColumns(innerContainersMap.keySet());
+ }
+ } else if (containerElementsMap != null && !containerElementsMap.isEmpty()) {
+ rows = computeRows(containerElementsMap.keySet());
+ columns = computeColumns(containerElementsMap.keySet());
+ }
+
+ Container thisContainer = new Container(id, name, rows, columns, 2, 6, 2, 5, 0, 0);
+ thisContainer.setElements(containerElementsMap);
+ thisContainer.setInnerContainer(innerContainersMap);
+
+ if (containerElementsMap != null && !containerElementsMap.isEmpty()) {
+ for (Element thisElement : containerElementsMap.values()) {
+ if (thisElement.getId() != null
+ ) {
+ thisContainer.setVisibilityType("invisible");
+ }
+ }
+ }
+ return thisContainer;
+ }
+
+ }
+
+ private static Domain fetchDomainObject(String id, String name) {
+ HashMap<String, Container> domainContainersMap = fetchContainersForDomain(name);
+
+ int rows = 1;
+ int columns = 1;
+ if (domainContainersMap != null && !domainContainersMap.isEmpty()) {
+ rows = computeRows(domainContainersMap.keySet());
+ columns = computeColumns(domainContainersMap.keySet());
+ }
+
+ double domainWidth = 11;
+ Domain thisDomain;
+
+ if (domainMap != null && !domainMap.isEmpty()) {
+ int domainsCountSoFar = domainMap.size();
+ switch (domainsCountSoFar) {
+ case 1: {
+ domainWidth = 12.1;
+ break;
+ }
+ case 2: {
+ domainWidth = 13.3;
+ break;
+ }
+ case 3: {
+ domainWidth = 14.5;
+ break;
+ }
+ case 4: {
+ domainWidth = 15.6;
+ break;
+ }
+ default: {
+ domainWidth = 11;
+ break;
+ }
+ }
+
+ for (String domainsKey : new TreeSet<String>(domainMap.keySet())) {
+ Domain eachDomain = domainMap.get(domainsKey);
+ domainWidth += eachDomain.computeSize().getWidth();
+ }
+ thisDomain = new Domain(id, name, 2, 2, domainWidth, 10, 3, rows, columns);
+ } else {
+
+ thisDomain = new Domain(id, name, 2, 1, 11, 10, 3, rows, columns);
+ }
+
+ // Domain thisDomain = new Domain(id, name, 2, 1, leftPosition, 10, 3,
+ // rows, columns);
+ thisDomain.setContainers(domainContainersMap);
+
+ thisDomain.computeConatinerPositions();
+ if (domainContainersMap != null && !domainContainersMap.isEmpty()) {
+ for (Container thisContainer : domainContainersMap.values()) {
+ thisContainer.computeSize();
+ thisContainer.computeElementPositions();
+ Map<String, Element> resultElementMap = thisContainer.elementRowCol;
+ for (String key : resultElementMap.keySet()) {
+ if (resultElementMap.get(key) == null || resultElementMap.get(key).getP() == null) {
+ // System.out.println("culprit " +key);
+ }
+ /*
+ * System.out.println(resultElementMap.get(key).name+" "
+ * +"x:"+resultElementMap.get(key).getP().getX()+","+"y:"+
+ * resultElementMap.get(key).getP().getY()+","+"width:"+
+ * resultElementMap.get(key).computeSize().getWidth()
+ * +","+"height:"+resultElementMap.get(key).computeSize().
+ * getHeight());
+ */
+
+ }
+
+ HashMap<String, Container> innerContainersMap = (HashMap<String, Container>) thisContainer
+ .getContainerRowCol();
+ if (innerContainersMap != null && !innerContainersMap.isEmpty()) {
+ for (Container thisInnerContainer : innerContainersMap.values()) {
+ // thisInnerContainer.computeSize();
+ thisInnerContainer.computeElementPositions();
+ /*
+ * Map<String,Element> resultInnerElementMap =
+ * thisContainer.elementRowCol; for (String key :
+ * resultElementMap.keySet()) { //
+ * System.out.println(resultElementMap.get(key).name+" "
+ * +"x:"+resultElementMap.get(key).getP().getX()+","+
+ * "y:"+
+ * resultElementMap.get(key).getP().getY()+","+"width:"+
+ * resultElementMap.get(key).computeSize().getWidth()
+ * +","+"height:"+resultElementMap.get(key).computeSize(
+ * ).getHeight());
+ *
+ * }
+ */
+ }
+ }
+ }
+ }
+
+ return thisDomain;
+ }
+
+ private static HashMap<String, Container> fetchContainersForDomain(String domain) {
+ HashMap<String, Container> domainContainersMap = new HashMap<String, Container>();
+
+ domainContainersMap = fetchFromOuterContainers(domain);
+
+ return domainContainersMap;
+
+ }
+
+ private static Element fetchElementObject(String id, String name, String imgPath) {
+ String bgColor = "bgColor";
+ String logical_group;
+ String display_longname;
+ String display_shortname;
+ String description;
+ String primary_function;
+ String key_interfaces;
+ String location;
+ String vendor;
+ String vendor_shortname;
+ String enclosingContainer;
+ String borderType;
+ String network_function;
+
+ if (toscaElementsMap.containsKey(name)) {
+
+ if (toscaElementsMap.get(name) != null && toscaElementsMap.get(name) instanceof HashMap) {
+ HashMap<String, Object> toscaElementDetails = (HashMap<String, Object>) toscaElementsMap.get(name);
+
+ for (String detailsKey : toscaElementDetails.keySet()) {
+ if ("properties".equalsIgnoreCase(detailsKey)
+ && toscaElementDetails.get(detailsKey) instanceof HashMap) {
+ HashMap<String, String> elementDetails = (HashMap<String, String>) toscaElementDetails
+ .get(detailsKey);
+
+ if (elementDetails != null) {
+ logical_group = elementDetails.get("logical_group") == null ? ""
+ : elementDetails.get("logical_group").toString();
+ display_longname = elementDetails.get("display_longname") == null ? ""
+ : elementDetails.get("display_longname").toString();
+ display_shortname = elementDetails.get("display_shortname") == null ? ""
+ : elementDetails.get("display_shortname").toString();
+ description = elementDetails.get("description") == null ? ""
+ : elementDetails.get("description").toString();
+ primary_function = elementDetails.get("primary_function") == null ? ""
+ : elementDetails.get("primary_function").toString();
+ key_interfaces = elementDetails.get("key_interfaces") == null ? ""
+ : elementDetails.get("key_interfaces").toString();
+ location = elementDetails.get("location") == null ? ""
+ : elementDetails.get("location").toString();
+ vendor = elementDetails.get("vendor") == null ? ""
+ : elementDetails.get("vendor").toString();
+ vendor_shortname = elementDetails.get("vendor_shortname") == null ? ""
+ : elementDetails.get("vendor_shortname").toString();
+ enclosingContainer = logical_group.replace("/", "-");
+ network_function = elementDetails.get("network_function");
+ borderType = elementDetails.get("network_function") == null ? "P"
+ : elementDetails.get("network_function").toString().toUpperCase();
+ bgColor = elementDetails.get("background_color") == null ? "bgColor"
+ : elementDetails.get("background_color").toString();
+
+ ElementDetails details = new ElementDetails(logical_group, display_longname, description,
+ primary_function, network_function, key_interfaces, location, vendor,
+ vendor_shortname, enclosingContainer);
+
+ return new Element(name, display_shortname, imgPath, bgColor, borderType, details);
+ }
+
+ }
+ }
+
+ }
+
+ // Element(id, name, imgPath, bgColor, logical_group,
+ // display_longname,
+ // description, primary_function, key_interfaces, location, vendor,
+ // vendor_shortname);
+ } else {
+ return new Element(id, name);
+ }
+
+ return new Element(id, name);
+ }
+
+ private static String fetchDomainNameOfElement(String name) {
+ if (toscaElementsMap.containsKey(name)) {
+
+ if (toscaElementsMap.get(name) != null && toscaElementsMap.get(name) instanceof HashMap) {
+ HashMap<String, Object> toscaElementDetails = (HashMap<String, Object>) toscaElementsMap.get(name);
+
+ for (String detailsKey : toscaElementDetails.keySet()) {
+ if ("properties".equalsIgnoreCase(detailsKey)
+ && toscaElementDetails.get(detailsKey) instanceof HashMap) {
+ HashMap<String, String> elementDetails = (HashMap<String, String>) toscaElementDetails
+ .get(detailsKey);
+
+ if (elementDetails != null) {
+ return elementDetails.get("domain") == null ? "" : elementDetails.get("domain").toString();
+ }
+
+ }
+ }
+
+ }
+
+ } else {
+ return "";
+ }
+
+ return "";
+ }
+
+ private static HashMap<String, Container> fetchInnerContainersMapForOuter(String name, boolean isInner,
+ String logicalGroupName, String domain) {
+ return fetchInnerContainersMap(name, logicalGroupName, domain);
+ }
+
+ private static HashMap<String, Element> fetchElementsMapForContainer(String name, boolean isInner,
+ String logicalGroupName, String domain) {
+ return fetchElementsMap(logicalGroupName, domain);
+ }
+
+ private static HashMap<String, Container> fetchInnerContainersMap(String name, String logicalGroupName,
+ String domain) {
+ HashMap<String, Container> containersMap = new HashMap<String, Container>();
+ String rowColumnKey = "";
+ int count = 0;
+
+ if (innercontainers != null && !innercontainers.isEmpty()) {
+ for (String key : innercontainers.keySet()) {
+
+ Container eachContainer = innercontainers.get(key);
+
+ if (key.toUpperCase().contains((domain + ":" + name).toUpperCase())) {
+ if (key.contains("/")) {
+ rowColumnKey = key.substring(key.lastIndexOf("/") + 1);
+ }
+
+ if (rowColumnKey.isEmpty() || containersMap.containsKey(rowColumnKey)) {
+ count = 0;
+ while (count <= 9) {
+ if (containersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))) {
+ count++;
+ } else {
+ rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
+ break;
+ }
+ }
+
+ }
+
+ containersMap.put(rowColumnKey, eachContainer);
+ }
+
+ }
+ }
+ return containersMap.isEmpty() ? null : containersMap;
+
+ }
+
+ private static HashMap<String, Container> fetchFromOuterContainers(String domain) {
+ HashMap<String, Container> thisContainersMap = new HashMap<String, Container>();
+ String rowColumnKey = "";
+ int count = 0;
+
+ if (outercontainers != null && !outercontainers.isEmpty()) {
+ for (String key : outercontainers.keySet()) {
+ Container eachContainer = outercontainers.get(key);
+
+ if (key.toUpperCase().contains((domain + ":").toUpperCase())) {
+ if (key.contains("/")) {
+ rowColumnKey = key.substring(key.lastIndexOf("/") + 1);
+ }
+
+ if (rowColumnKey.isEmpty() || thisContainersMap.containsKey(rowColumnKey)) {
+ count = 0;
+ while (count <= 9) {
+ if (thisContainersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))) {
+ count++;
+ } else {
+ rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
+ break;
+ }
+ }
+
+ }
+
+ thisContainersMap.put(rowColumnKey, eachContainer);
+ }
+ }
+
+ }
+
+ // Misc Elements Containers
+
+ if (miscElementMap != null && !miscElementMap.isEmpty()) {
+ for (String key : miscElementMap.keySet()) {
+ Element eachElement = miscElementMap.get(key);
+ String elementName = eachElement.getName();
+ String domainName = fetchDomainNameOfElement(elementName);
+
+ if (domain.equalsIgnoreCase(domainName)) {
+ Container eachContainer = new Container(domainName + ":" + elementName, elementName, 1, 1, 3, 6, 2,
+ 5, 0, 0);
+ count = 0;
+ while (count <= 9) {
+ if (thisContainersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))) {
+ count++;
+ } else {
+ rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
+ break;
+ }
+ }
+
+ thisContainersMap.put(rowColumnKey, eachContainer);
+ }
+
+ }
+
+ }
+
+ return thisContainersMap.isEmpty() ? null : thisContainersMap;
+ }
+
+ private static HashMap<String, Container> addOuterContainersForMiscElements(String domain) {
+ HashMap<String, Container> containerElementsMap = new HashMap<String, Container>();
+ if (miscElementMap != null && !miscElementMap.isEmpty()) {
+ for (String key : miscElementMap.keySet()) {
+ Element eachElement = miscElementMap.get(key);
+ String elementName = eachElement.getName();
+ String domainName = fetchDomainNameOfElement(elementName);
+
+ if (domain.equalsIgnoreCase(domainName)) {
+ Container newContainer = new Container(domainName + ":" + elementName, elementName, 1, 1, 3, 6, 2,
+ 5, 0, 0);
+ containerElementsMap.put(domainName + ":" + elementName, newContainer);
+ }
+
+ }
+
+ }
+ return containerElementsMap.isEmpty() ? null : containerElementsMap;
+ }
+
+ private static HashMap<String, Element> fetchElementsMap(String logicalGroupName, String domain) {
+ HashMap<String, Element> innerElementMap = new HashMap<String, Element>();
+ String rowColumnKey = "";
+ int count = 0;
+
+ if (elementMap != null && !elementMap.isEmpty()) {
+ for (String key : elementMap.keySet()) {
+ Element eachElement = elementMap.get(key);
+
+ String elementName = eachElement.getId();
+ String elementLogicalGroup = eachElement.details == null ? "" : eachElement.details.logical_group;
+ if (elementLogicalGroup.equalsIgnoreCase(logicalGroupName)
+ && domain.equalsIgnoreCase(fetchDomainNameOfElement(elementName))) {
+ if (key.contains("/")) {
+ rowColumnKey = key.substring(key.indexOf("/") + 1);
+ }
+
+ if (rowColumnKey.isEmpty() || innerElementMap.containsKey(rowColumnKey)) {
+ count = 0;
+ while (count <= 9) {
+ if (innerElementMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))) {
+ count++;
+ } else {
+ rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
+ break;
+ }
+ }
+
+ }
+
+ innerElementMap.put(rowColumnKey, eachElement);
+ miscElementMap.remove(key);
+ }
+
+ }
+ }
+
+ return innerElementMap.isEmpty() ? null : innerElementMap;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java
index 040c9d26..040c9d26 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java
index b17be180..ca73339d 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/FnMenuServiceImpl.java
@@ -21,15 +21,21 @@ package org.openecomp.portalsdk.core.service;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
+import org.openecomp.portalsdk.core.domain.FnMenu;
import org.openecomp.portalsdk.core.domain.Menu;
import org.openecomp.portalsdk.core.domain.MenuData;
+import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.domain.RoleFunction;
+import org.openecomp.portalsdk.core.service.DataAccessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -45,6 +51,7 @@ public class FnMenuServiceImpl implements FnMenuService{
@SuppressWarnings("unchecked")
public List<MenuData> getFnMenuItems() {
+ //List msgDB = getDataAccessService().getList(Profile.class, null);
return getDataAccessService().getList(MenuData.class, null, "1", null);
}
@@ -71,6 +78,9 @@ public class FnMenuServiceImpl implements FnMenuService{
@Override
public List<Long> getParentId(String label) {
// TODO Auto-generated method stub
+ //List<String> functioCDlist = new ArrayList<String>();
+ //functioCDlist.add("Mahdy1");
+ //functioCDlist.add("Mahdy2");
Map<String, String> params = new HashMap<String, String>();
params.put("paramLabel", label);
return getDataAccessService().executeNamedQuery("IdForLabelList", params, null);
@@ -80,18 +90,24 @@ public class FnMenuServiceImpl implements FnMenuService{
@Override
public List<List> getParentList() {
// TODO Auto-generated method stub
-
+ //List<String> functioCDlist = new ArrayList<String>();
+ //functioCDlist.add("Mahdy1");
+ //functioCDlist.add("Mahdy2");
return getDataAccessService().executeNamedQuery("parentList", null, null);
+ //return null;
}
@SuppressWarnings("unchecked")
@Override
public List<RoleFunction> getFunctionCDList() {
// TODO Auto-generated method stub
-
+ //List<String> functioCDlist = new ArrayList<String>();
+ //functioCDlist.add("Mahdy1");
+ //functioCDlist.add("Mahdy2");
return getDataAccessService().executeNamedQuery("functionCDlist", null, null);
+ //return null;
}
@Override
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java
index 9c790eb2..9c790eb2 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java
index d1176c1c..ba43e45f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LdapServiceImpl.java
@@ -49,8 +49,8 @@ public class LdapServiceImpl extends FusionService implements LdapService {
@Autowired
private ServiceLocator serviceLocator;
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public SearchResult searchPost(DomainVo searchCriteria, String sortBy1, String sortBy2, String sortBy3,
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public SearchResult searchPost(DomainVo searchCriteria, String sortBy1, String sortBy2, String sortBy3,
int pageNo, int dataSize, int userId) throws Exception {
// initialize the directory context to access POST
@@ -131,9 +131,8 @@ public class LdapServiceImpl extends FusionService implements LdapService {
return searchResult;
}
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private ArrayList processResults(NamingEnumeration e) throws NamingException {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private ArrayList processResults(NamingEnumeration e) throws NamingException {
ArrayList results = new ArrayList();
int count = 0;
@@ -151,14 +150,13 @@ public class LdapServiceImpl extends FusionService implements LdapService {
return results;
}
-
- @SuppressWarnings("rawtypes")
- private DomainVo processAttributes(Attributes resultAttributes) throws NamingException {
+ @SuppressWarnings("rawtypes")
+ private DomainVo processAttributes(Attributes resultAttributes) throws NamingException {
User user = new User();
try {
if (resultAttributes == null) {
- System.out.println("This result has no attributes");
+ // System.out.println("This result has no attributes");
} else {
for (NamingEnumeration e = resultAttributes.getAll(); e.hasMore();) { //why the nested loop?
Attribute attribute = (Attribute)e.next();
@@ -260,9 +258,9 @@ public class LdapServiceImpl extends FusionService implements LdapService {
} catch (NamingException e) {
logger.error(EELFLoggerDelegate.errorLogger, "An error occurred while processing the following user from POST with an ORGUSERID of " + user.getOrgUserId() + e.getMessage());
} finally {
-
+ return user;
}
- return user;
+
}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java
new file mode 100644
index 00000000..4f004108
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java
@@ -0,0 +1,36 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service;
+
+
+import java.util.*;
+
+import org.openecomp.portalsdk.core.command.*;
+
+
+public interface LoginService {
+
+ // validate user exists in the system
+ @SuppressWarnings("rawtypes")
+ LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams) throws Exception;
+
+ @SuppressWarnings("rawtypes")
+ LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams, boolean matchPassword) throws Exception;
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java
index 7da427ba..e0a4b7c6 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/LoginServiceImpl.java
@@ -29,6 +29,7 @@ import java.util.Set;
import org.openecomp.portalsdk.core.command.LoginBean;
import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.domain.UserApp;
import org.openecomp.portalsdk.core.menu.MenuBuilder;
import org.openecomp.portalsdk.core.service.support.FusionService;
import org.openecomp.portalsdk.core.util.SystemProperties;
@@ -42,20 +43,19 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public class LoginServiceImpl extends FusionService implements LoginService {
- @SuppressWarnings("unused")
- private MenuBuilder menuBuilder;
+ @SuppressWarnings("unused")
+ private MenuBuilder menuBuilder;
@Autowired
private DataAccessService dataAccessService;
-
@SuppressWarnings("rawtypes")
- public LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams ) throws Exception {
+ public LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams ) throws Exception {
return findUser(bean, menuPropertiesFilename, additionalParams, true);
}
-
+
@SuppressWarnings("rawtypes")
- public LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams, boolean matchPassword) throws Exception {
+ public LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams, boolean matchPassword) throws Exception {
User user = null;
User userCopy = null;
@@ -81,6 +81,20 @@ public class LoginServiceImpl extends FusionService implements LoginService {
bean.setLoginErrorMessage(SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_INACTIVE);
}
+ // raise an error if no active roles exist for the user
+// boolean hasActiveRole = false;
+// Iterator roles = user.getRoles().iterator();
+// while (roles.hasNext()) {
+// Role role = (Role)roles.next();
+// if (role.getActive()) {
+// hasActiveRole = true;
+// break;
+// }
+// }
+
+// if (!hasActiveRole) {
+// bean.setLoginErrorMessage(SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_INACTIVE);
+// }
if (!userHasActiveRoles(user)) {
bean.setLoginErrorMessage(SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_INACTIVE);
}
@@ -96,9 +110,13 @@ public class LoginServiceImpl extends FusionService implements LoginService {
// update the audit log of the user
//Check for the client device type and set log attributes appropriately
+
// save the above changes to the User and their audit trail
+
+
+
// create the application menu based on the user's privileges
Set appMenu = getMenuBuilder().getMenu(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_SET_NAME),dataAccessService);
bean.setMenu(appMenu != null?appMenu:new HashSet());
@@ -113,8 +131,7 @@ public class LoginServiceImpl extends FusionService implements LoginService {
return bean;
}
- @SuppressWarnings("rawtypes")
- private boolean userHasActiveRoles(User user) {
+ private boolean userHasActiveRoles(User user) {
boolean hasActiveRole = false;
Iterator roles = user.getRoles().iterator();
while (roles.hasNext()) {
@@ -127,9 +144,8 @@ public class LoginServiceImpl extends FusionService implements LoginService {
return hasActiveRole;
}
-
@SuppressWarnings("rawtypes")
- public User findUser(String loginId, String password) {
+ public User findUser(String loginId, String password) {
List list = null;
StringBuffer criteria = new StringBuffer();
@@ -142,7 +158,7 @@ public class LoginServiceImpl extends FusionService implements LoginService {
}
@SuppressWarnings("rawtypes")
- private User findUserWithoutPwd(String loginId) {
+ private User findUserWithoutPwd(String loginId) {
List list = null;
StringBuffer criteria = new StringBuffer();
@@ -153,9 +169,8 @@ public class LoginServiceImpl extends FusionService implements LoginService {
return (list == null || list.size() == 0) ? null : (User)list.get(0);
}
-
@SuppressWarnings("rawtypes")
- public User findUser(LoginBean bean) {
+ public User findUser(LoginBean bean) {
List list = null;
StringBuffer criteria = new StringBuffer();
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java
index 596ebed2..596ebed2 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java
index 726d8973..658de264 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostDroolsServiceImpl.java
@@ -47,7 +47,10 @@ import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.databind.ObjectMapper;
-
+/**
+ * TODO REFACTOR
+ *
+ */
@Service("postDroolsService")
@Transactional
public class PostDroolsServiceImpl implements PostDroolsService{
@@ -105,8 +108,12 @@ public class PostDroolsServiceImpl implements PostDroolsService{
// this will parse and compile in one step
kbuilder.add(ResourceFactory.newFileResource(SystemProperties.getProperty(SystemProperties.FILES_PATH) + File.separator + fileName),
+ //kbuilder.add(ResourceFactory.newClassPathResource(SystemProperties.getProperty(SystemProperties.FILES_PATH) + File.separator + drl_file_path, DroolsRuleService.class),
ResourceType.DRL);
-
+ // kbuilder.add(ResourceFactory.newClassPathResource("rules.drl",DroolsRuleService.class),
+ // ResourceType.DRL);
+
+ // Check the builder for errors
if (kbuilder.hasErrors()) {
logger.error(EELFLoggerDelegate.errorLogger, kbuilder.getErrors().toString());
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java
index 55c9db3f..cde9a370 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchService.java
@@ -25,6 +25,13 @@ import org.openecomp.portalsdk.core.command.PostSearchBean;
public interface PostSearchService {
- void process(HttpServletRequest request, PostSearchBean postSearch);
-
+ /**
+ * Imports the selected users in the search results as new users.
+ *
+ * @param request
+ * @param postSearch
+ * @return the number of users successfully imported
+ */
+ int process(HttpServletRequest request, PostSearchBean postSearch);
+
}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java
new file mode 100644
index 00000000..f2877d4d
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java
@@ -0,0 +1,207 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.FusionObject.Parameters;
+import org.openecomp.portalsdk.core.command.PostSearchBean;
+import org.openecomp.portalsdk.core.domain.Lookup;
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service("postSearchService")
+@Transactional
+public class PostSearchServiceImpl implements PostSearchService {
+
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PostSearchServiceImpl.class);
+
+ @Autowired
+ private DataAccessService dataAccessService;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public int process(HttpServletRequest request, PostSearchBean postSearch) {
+ HashMap additionalParams = new HashMap();
+ additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request);
+ int numUsersImported = 0;
+
+ if (postSearch.getSelected() != null) {
+ // sort the selected users for quick validation
+
+ Arrays.sort(postSearch.getSelected());
+ // import the users that have been selected
+ for (int i = 0; i < postSearch.getPostOrgUserId().length; i++) {
+ if (Arrays.binarySearch(postSearch.getSelected(), postSearch.getPostOrgUserId()[i]) >= 0) {
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "Adding ORGUSERID - " + postSearch.getPostOrgUserId()[i]);
+ logger.debug(EELFLoggerDelegate.auditLogger,
+ "Import new user from webphone " + postSearch.getPostOrgUserId()[i]);
+
+ User user = new User();
+ user.setLastName(postSearch.getPostLastName()[i]);
+ user.setFirstName(postSearch.getPostFirstName()[i]);
+
+ if (postSearch.getPostHrid() != null && postSearch.getPostHrid().length > 0) {
+ user.setHrid(postSearch.getPostHrid()[i]);
+ }
+
+ if (postSearch.getPostPhone() != null && postSearch.getPostPhone().length > 0) {
+ user.setPhone(postSearch.getPostPhone()[i]);
+ }
+
+ if (postSearch.getPostEmail() != null && postSearch.getPostEmail().length > 0) {
+ user.setEmail(postSearch.getPostEmail()[i]);
+ }
+
+ if (postSearch.getPostOrgUserId() != null && postSearch.getPostOrgUserId().length > 0) {
+ user.setOrgUserId(postSearch.getPostOrgUserId()[i]);
+ user.setLoginId(postSearch.getPostOrgUserId()[i]);
+ }
+
+ if (postSearch.getPostAddress1() != null && postSearch.getPostAddress1().length > 0) {
+ user.setAddress1(postSearch.getPostAddress1()[i]);
+ }
+
+ if (postSearch.getPostAddress2() != null && postSearch.getPostAddress2().length > 0) {
+ user.setAddress2(postSearch.getPostAddress2()[i]);
+ }
+
+ if (postSearch.getPostCity() != null && postSearch.getPostCity().length > 0) {
+ user.setCity(postSearch.getPostCity()[i]);
+ }
+
+ if (postSearch.getPostState() != null && postSearch.getPostState().length > 0) {
+ user.setState(postSearch.getPostState()[i]);
+ }
+
+ if (postSearch.getPostZipCode() != null && postSearch.getPostZipCode().length > 0) {
+ user.setZipCode(postSearch.getPostZipCode()[i]);
+ }
+
+ if (postSearch.getPostLocationClli() != null && postSearch.getPostLocationClli().length > 0) {
+ user.setLocationClli(postSearch.getPostLocationClli()[i]);
+ }
+
+ if (postSearch.getPostBusinessCountryCode() != null
+ && postSearch.getPostBusinessCountryCode().length > 0) {
+ user.setBusinessCountryCode(postSearch.getPostBusinessCountryCode()[i]);
+ }
+
+ if (postSearch.getPostBusinessCountryName() != null
+ && postSearch.getPostBusinessCountryName().length > 0) {
+
+ // find the country cd for the indicated country
+ List countries = dataAccessService.getLookupList("fn_lu_country", "country_cd", "country",
+ "country = '" + postSearch.getPostBusinessCountryName()[i] + "'", null, null);
+
+ if (countries != null && countries.size() == 1) {
+ Lookup country = (Lookup) countries.get(0);
+ user.setCountry(country.getValue());
+ } else {
+ logger.info(EELFLoggerDelegate.debugLogger,
+ "No countries or more than one country was found matching the country returned from WEBPHONE. "
+ + "Therefore, no country was set for this user.");
+ }
+
+ }
+
+ if (postSearch.getPostDepartment() != null && postSearch.getPostDepartment().length > 0) {
+ user.setDepartment(postSearch.getPostDepartment()[i]);
+ }
+
+ if (postSearch.getPostDepartmentName() != null && postSearch.getPostDepartmentName().length > 0) {
+ user.setDepartmentName(postSearch.getPostDepartmentName()[i]);
+ }
+
+ if (postSearch.getPostBusinessUnit() != null && postSearch.getPostBusinessUnit().length > 0) {
+ user.setBusinessUnit(postSearch.getPostBusinessUnit()[i]);
+ }
+
+ if (postSearch.getPostBusinessUnitName() != null
+ && postSearch.getPostBusinessUnitName().length > 0) {
+ user.setBusinessUnitName(postSearch.getPostBusinessUnitName()[i]);
+ }
+
+ if (postSearch.getPostJobTitle() != null && postSearch.getPostJobTitle().length > 0) {
+ user.setJobTitle(postSearch.getPostJobTitle()[i]);
+ }
+
+ if (postSearch.getPostOrgManagerUserId() != null
+ && postSearch.getPostOrgManagerUserId().length > 0) {
+ user.setOrgManagerUserId(postSearch.getPostOrgManagerUserId()[i]);
+ }
+
+ if (postSearch.getPostCommandChain() != null && postSearch.getPostCommandChain().length > 0) {
+ user.setCommandChain(postSearch.getPostCommandChain()[i]);
+ }
+
+ if (postSearch.getPostCompanyCode() != null && postSearch.getPostCompanyCode().length > 0) {
+ user.setCompanyCode(postSearch.getPostCompanyCode()[i]);
+ }
+
+ if (postSearch.getPostCompany() != null && postSearch.getPostCompany().length > 0) {
+ user.setCompany(postSearch.getPostCompany()[i]);
+ }
+
+ if (postSearch.getPostCostCenter() != null && postSearch.getPostCostCenter().length > 0) {
+ user.setCostCenter(postSearch.getPostCostCenter()[i]);
+ }
+
+ if (postSearch.getPostSiloStatus() != null && postSearch.getPostSiloStatus().length > 0) {
+ user.setSiloStatus(postSearch.getPostSiloStatus()[i]);
+ }
+
+ if (postSearch.getPostFinancialLocCode() != null
+ && postSearch.getPostFinancialLocCode().length > 0) {
+ user.setFinancialLocCode(postSearch.getPostFinancialLocCode()[i]);
+ }
+
+ user.setActive(true);
+
+ try {
+ dataAccessService.saveDomainObject(user, additionalParams);
+ Role role = (Role) dataAccessService.getDomainObject(Role.class,
+ Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID)),
+ null);
+ user.addRole(role);
+ numUsersImported++;
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "process: saveDomainObject failed on user " + user.getLoginId(), e);
+ }
+ }
+ }
+
+ }
+
+ return numUsersImported;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java
index 61bd3b6e..61bd3b6e 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java
index 3927d727..2d6fcfee 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/ProfileServiceImpl.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.openecomp.portalsdk.core.dao.ProfileDao;
import org.openecomp.portalsdk.core.domain.Profile;
import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.service.DataAccessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -40,6 +41,7 @@ public class ProfileServiceImpl implements ProfileService{
@SuppressWarnings("unchecked")
public List<Profile> findAll() {
+ //List msgDB = getDataAccessService().getList(Profile.class, null);
return getDataAccessService().getList(Profile.class, null);
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java
index 01367ecd..01367ecd 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java
index e71e0c58..2e780998 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceImpl.java
@@ -31,92 +31,93 @@ import javax.sql.DataSource;
import org.openecomp.portalsdk.core.domain.Role;
import org.openecomp.portalsdk.core.domain.RoleFunction;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("roleService")
@Transactional
-public class RoleServiceImpl implements RoleService{
+public class RoleServiceImpl implements RoleService {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleServiceImpl.class);
@Autowired
- private DataAccessService dataAccessService;
-
+ private DataAccessService dataAccessService;
+
DataSource dataSource;
-
+
public DataSource getDataSource() {
return dataSource;
}
-
@Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
-
- @SuppressWarnings("unchecked")
+
+ @SuppressWarnings("unchecked")
public List<RoleFunction> getRoleFunctions() {
- //List msgDB = getDataAccessService().getList(Profile.class, null);
+ // List msgDB = getDataAccessService().getList(Profile.class, null);
return getDataAccessService().getList(RoleFunction.class, null);
}
-
+
@SuppressWarnings("unchecked")
public List<Role> getAvailableChildRoles(Long roleId) {
- List<Role> availableChildRoles = (List<Role>)getDataAccessService().getList(Role.class,null);
- if(roleId==null || roleId==0){
+ List<Role> availableChildRoles = (List<Role>) getDataAccessService().getList(Role.class, null);
+ if (roleId == null || roleId == 0) {
return availableChildRoles;
}
-
- Role currentRole = (Role)getDataAccessService().getDomainObject(Role.class,roleId,null);
+
+ Role currentRole = (Role) getDataAccessService().getDomainObject(Role.class, roleId, null);
Set<Role> allParentRoles = new TreeSet<Role>();
allParentRoles = getAllParentRolesAsList(currentRole, allParentRoles);
-
Iterator<Role> availableChildRolesIterator = availableChildRoles.iterator();
while (availableChildRolesIterator.hasNext()) {
- Role role = availableChildRolesIterator.next();
- if(!role.getActive() || allParentRoles.contains(role) || role.getId().equals(roleId)){
+ Role role = availableChildRolesIterator.next();
+ if (!role.getActive() || allParentRoles.contains(role) || role.getId().equals(roleId)) {
availableChildRolesIterator.remove();
}
}
return availableChildRoles;
}
-
+
@SuppressWarnings("unchecked")
private Set<Role> getAllParentRolesAsList(Role role, Set<Role> allParentRoles) {
Set<Role> parentRoles = role.getParentRoles();
allParentRoles.addAll(parentRoles);
Iterator<Role> parentRolesIterator = parentRoles.iterator();
while (parentRolesIterator.hasNext()) {
- getAllParentRolesAsList(parentRolesIterator.next(),allParentRoles);
+ getAllParentRolesAsList(parentRolesIterator.next(), allParentRoles);
}
return allParentRoles;
}
-
+
public RoleFunction getRoleFunction(String code) {
- return (RoleFunction)getDataAccessService().getDomainObject(RoleFunction.class, code, null);
+ return (RoleFunction) getDataAccessService().getDomainObject(RoleFunction.class, code, null);
}
-
+
public void saveRoleFunction(RoleFunction domainRoleFunction) {
getDataAccessService().saveDomainObject(domainRoleFunction, null);
}
-
+
public void deleteRoleFunction(RoleFunction domainRoleFunction) {
getDataAccessService().deleteDomainObject(domainRoleFunction, null);
}
-
+
public Role getRole(Long id) {
- return (Role)getDataAccessService().getDomainObject(Role.class, id, null);
+ return (Role) getDataAccessService().getDomainObject(Role.class, id, null);
}
-
+
public void saveRole(Role domainRole) {
getDataAccessService().saveDomainObject(domainRole, null);
}
-
+
public void deleteRole(Role domainRole) {
getDataAccessService().deleteDomainObject(domainRole, null);
}
-
+
@SuppressWarnings("unchecked")
public List<Role> getAvailableRoles() {
return getDataAccessService().getList(Role.class, null);
@@ -126,24 +127,21 @@ public class RoleServiceImpl implements RoleService{
@Override
public List<Role> getActiveRoles() {
String filter = " where active_yn = 'Y' ";
- return getDataAccessService().getList(Role.class, filter, null,null);
+ return getDataAccessService().getList(Role.class, filter, null, null);
}
public DataAccessService getDataAccessService() {
return dataAccessService;
}
-
public void setDataAccessService(DataAccessService dataAccessService) {
this.dataAccessService = dataAccessService;
}
@Override
public void deleteDependcyRoleRecord(Long id) {
-
Connection conn = null;
Statement stmt = null;
-
try {
conn = getDataSource().getConnection();
stmt = conn.createStatement();
@@ -152,20 +150,22 @@ public class RoleServiceImpl implements RoleService{
stmt.close();
conn.close();
} catch (Exception e) {
- e.printStackTrace();
+ logger.error(EELFLoggerDelegate.errorLogger, "deleteDependcyRoleRecord failed", e);
} finally {
try {
if (stmt != null)
stmt.close();
- } catch (SQLException se2) {}
+ } catch (SQLException se2) {
+ logger.error(EELFLoggerDelegate.errorLogger, "deleteDependcyRoleRecord failed", se2);
+ }
try {
if (conn != null)
conn.close();
- } catch (SQLException se) { se.printStackTrace();}
+ } catch (SQLException se) {
+ logger.error(EELFLoggerDelegate.errorLogger, "deleteDependcyRoleRecord failed", se);
+ }
}
-
- }
+ }
-
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java
index bd6796c1..a7374d0c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/RoleServiceNonSpringImpl.java
@@ -119,4 +119,4 @@ public class RoleServiceNonSpringImpl implements RoleService{
}
-*/
+*/ \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java
index 0cf3986b..b844fb0c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileService.java
@@ -31,6 +31,4 @@ public interface UserProfileService {
void saveUser(User user);
public List<User> findAllUserWithOnOffline(String originOrgUserId);
List<User> findAllActive();
- List<User> searchPost(User user, String sortBy1, String sortBy2, String sortBy3, int pageNo, int newDataSize,
- int intValue);
}
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java
new file mode 100644
index 00000000..2d134725
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java
@@ -0,0 +1,116 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Restrictions;
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.domain.support.CollaborateList;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service("userProfileService")
+@Transactional
+public class UserProfileServiceImpl implements UserProfileService{
+
+
+ @Autowired
+ private DataAccessService dataAccessService;
+
+ public List<User> findAll() {
+ return getDataAccessService().getList(User.class, null);
+ }
+
+ public User getUser(String userId){
+ return (User) getDataAccessService().getDomainObject(User.class, Long.parseLong(userId), null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public User getUserByLoginId(String loginId){
+ User user=null;
+ List<Criterion> restrictionsList = new ArrayList<Criterion>();
+ Criterion criterion1= Restrictions.eq("loginId",loginId);
+ restrictionsList.add(criterion1);
+ List<User> users = (List<User>) getDataAccessService().getList(User.class,null, restrictionsList, null);
+ if(users!=null && users.size()==1)
+ user = users.get(0);
+ return user;
+ }
+
+ public void saveUser(User user){
+
+ getDataAccessService().saveDomainObject(user, null);
+ }
+
+ public DataAccessService getDataAccessService() {
+ return dataAccessService;
+ }
+
+
+ public void setDataAccessService(DataAccessService dataAccessService) {
+ this.dataAccessService = dataAccessService;
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<User> findAllUserWithOnOffline(String originOrgUserId) {
+ HashSet<String> onlineUser = CollaborateList.getInstance().getAllUserName();
+ List<User> users = getDataAccessService().getList(User.class, null);
+ for(User u:users){
+ if(onlineUser.contains(u.getOrgUserId()))
+ u.setOnline(true);
+ if(u.getOrgUserId()!=null){
+ if(originOrgUserId.compareTo(u.getOrgUserId()) > 0) {
+ u.setChatId(originOrgUserId + "-" + u.getOrgUserId());
+ } else u.setChatId(u.getOrgUserId() + "-" + originOrgUserId );
+ }
+ }
+ return users;
+
+ }
+
+ public List<User> findAllActive() {
+ List<User> users = getDataAccessService().getList(User.class, null);
+ Iterator<User> itr = users.iterator();
+ while(itr.hasNext()){
+ User u = (User) itr.next();
+ if(!u.getActive())
+ itr.remove();//if not active remove user from list
+ else {
+ SortedSet<Role> roles = u.getRoles();
+ Iterator<Role> itrRoles = roles.iterator();
+ while(itrRoles.hasNext()){
+ Role role = (Role) itrRoles.next();
+ if(!role.getActive())
+ u.removeRole(role.getId());//if not active remove role from list
+ }
+ }
+ }
+ return users;
+ }
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java
index a7a5ad07..a7a5ad07 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java
index 3e1a1a40..557af2dd 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/WebServiceCallServiceImpl.java
@@ -23,7 +23,7 @@ import java.util.List;
import org.openecomp.portalsdk.core.domain.App;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.util.CipherUtil;
+import org.openecomp.portalsdk.core.onboarding.util.CipherUtil;
import org.openecomp.portalsdk.core.util.SystemProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java
index 34649ee1..34649ee1 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/FusionService.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java
index 5858c3fa..5858c3fa 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocator.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java
new file mode 100644
index 00000000..97f4875d
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java
@@ -0,0 +1,105 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.service.support;
+
+import java.util.*;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.stereotype.Service;
+
+/**
+ * This class implements the J2EE service locator pattern. It provides lookup
+ * facilities for various services. Currenttly LDAP (pre-v3) is supported
+ */
+@Service("serviceLocator")
+public class ServiceLocatorImpl implements ServiceLocator {
+
+ //private static ServiceLocator locator; // The singleton instance
+
+ private Context context; // JNDI context (not currently in use)
+ private Context rootContext; // Java env root context (not currently in use)
+ private DirContext dirContext; // LDAP DIR context
+ private InitialLdapContext ldapContext; // LDAP context LDAPv3-style (not currently in use)
+
+
+ // cannot directly instantiate
+ public ServiceLocatorImpl() {}
+
+ /*public static ServiceLocator getLocator() {
+ if (locator == null)
+ locator = new ServiceLocator();
+ return locator;
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }*/
+
+
+ // Get an LDAP directory context
+ public DirContext getDirContext(String initialContextFactory, String providerUrl, String securityPrincipal) {
+
+ if (dirContext == null) {
+
+ Properties properties = new Properties();
+ properties.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
+ properties.put(Context.PROVIDER_URL, providerUrl);
+ properties.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
+
+ try {
+ dirContext = new InitialDirContext(properties);
+ }
+ catch (NamingException ne) {
+ logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while creating an Initial Directory Context: " + ne.getMessage());
+ logger.error(EELFLoggerDelegate.errorLogger, "Explanation: " + ne.getExplanation());
+ }
+ }
+
+ return dirContext;
+ }
+
+ // Get an LDAP directory context - LDAPv3-style
+ /*public InitialLdapContext getLdapContext() { //throws NamingException {
+ if (ldapContext == null) {
+ Properties properties = new Properties();
+ // @todo - need to parameterize context factoy class and url
+ properties.put(Context.INITIAL_CONTEXT_FACTORY, AttLdap.DIR_INITIAL_CONTEXT_FACTORY);
+ properties.put(Context.PROVIDER_URL, AttLdap.DIR_PROVIDER_URL);
+ properties.put(Context.SECURITY_PRINCIPAL, AttLdap.DIR_SECURITY_PRINCIPAL);
+ Control[] ctrl = null;
+ try {
+ ldapContext = new InitialLdapContext(properties, ctrl);
+ }
+ catch (NamingException ne) {
+ // MJ FIX log exception?
+ }
+ }
+ return ldapContext;
+ }*/
+
+
+ /** Logger for this class and subclasses */
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ServiceLocatorImpl.class);
+
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java
index e26ac884..e26ac884 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/CacheManager.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java
index 46a24533..23d90cc9 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/EncDecUtilTest.java
@@ -109,4 +109,4 @@ public class EncDecUtilTest {
String s = new String(bytes);
return s;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java
index 6b849e81..6b849e81 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/JSONUtil.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java
new file mode 100644
index 00000000..6a705aed
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java
@@ -0,0 +1,327 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.util;
+
+import javax.servlet.ServletContext;
+
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+
+/**
+ * SystemProperties contains a list of constants used throughout portions of the
+ * application. Populated by Spring from multiple configuration files.
+ *
+ * Should be used like this:
+ *
+ * <pre>
+ *
+ * &#64;Autowired
+ * SystemProperties systemProperties;
+ * </pre>
+ */
+@Configuration
+@PropertySource(value = { "${container.classpath:}/WEB-INF/conf/system.properties",
+ "${container.classpath:}/WEB-INF/fusion/conf/fusion.properties",
+ "${container.classpath:}/WEB-INF/conf/sql.properties" })
+public class SystemProperties {
+
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SystemProperties.class);
+
+ private static Environment environment;
+
+ private ServletContext servletContext;
+
+ public SystemProperties() {
+ }
+
+ protected Environment getEnvironment() {
+ return environment;
+ }
+
+ @Autowired
+ public void setEnvironment(Environment environment) {
+ SystemProperties.environment = environment;
+ }
+
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ /**
+ * Tests whether a property value is available for the specified key.
+ *
+ * @param key
+ * @return True if the key is known, otherwise false.
+ */
+ public static boolean containsProperty(String key) {
+ return environment.containsProperty(key);
+ }
+
+ /**
+ * Returns the property value associated with the given key (never
+ * {@code null}), after trimming any trailing space.
+ *
+ * @throws IllegalStateException
+ * if the key cannot be resolved
+ * @param key
+ * Property key
+ * @return Property value; the empty string if the environment was not
+ * autowired, which should never happen.
+ */
+ public static String getProperty(String key) {
+ String value = "";
+ if (environment == null) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getProperty: environment is null, should never happen!");
+ }
+ else {
+ value = environment.getRequiredProperty(key);
+ // java.util.Properties preserves trailing space
+ if (value != null)
+ value = value.trim();
+ }
+ return value;
+ }
+
+ /**
+ * Gets the property value for the key {@link #APPLICATION_NAME}.
+ *
+ * method created to get around JSTL 1.0 limitation of not being able to
+ * access a static method of a bean
+ *
+ * @return Application name
+ */
+ public String getApplicationName() {
+ return getProperty(APPLICATION_NAME);
+ }
+
+ /**
+ * Gets the property value for the key {@link #APP_DISPLAY_NAME}.
+ *
+ * @return Application display name
+ */
+ public String getAppDisplayName() {
+ return getProperty(APP_DISPLAY_NAME);
+ }
+
+ // keys used to reference values in the system properties file
+ public static final String DOMAIN_CLASS_LOCATION = "domain_class_location";
+ public static final String DEFAULT_ERROR_MESSAGE = "default_error_message";
+
+ public static final String CSP_COOKIE_NAME = "csp_cookie_name";
+ public static final String CSP_GATE_KEEPER_DATA_KEY = "csp_gate_keeper_data_key";
+ public static final String CSP_GATE_KEEPER_PROD_KEY = "csp_gate_keeper_prod_key";
+ public static final String CSP_LOGIN_URL = "csp_login_url";
+ public static final String CSP_LOGOUT_URL = "csp_logout_url";
+
+ public static final String WEB_JUNCTION_USER_ID_HEADER_NAME = "web_junction_user_id_header_name";
+
+ public static final String AUTHENTICATION_MECHANISM = "authentication_mechanism";
+
+ public static final String APPLICATION_NAME = "application_name";
+ public static final String HIBERNATE_CONFIG_FILE_PATH = "hibernate_config_file_path";
+ public static final String APPLICATION_USER_ID = "application_user_id";
+
+ public static final String POST_INITIAL_CONTEXT_FACTORY = "post_initial_context_factory";
+ public static final String POST_PROVIDER_URL = "post_provider_url";
+ public static final String POST_SECURITY_PRINCIPAL = "post_security_principal";
+ public static final String POST_MAX_RESULT_SIZE = "post_max_result_size";
+ public static final String POST_DEFAULT_ROLE_ID = "post_default_role_id";
+
+ public static final String FILES_PATH = "files_path";
+ public static final String TEMP_PATH = "temp_path";
+
+ public static final String NUM_UPLOAD_FILES = "num_upload_files";
+
+ public static final String SYS_ADMIN_ROLE_ID = "sys_admin_role_id";
+
+ public static final String SYS_ADMIN_ROLE_FUNCTION_DELETE_FROM_UI = "sys_admin_role_function_delete_from_ui";
+ public static final String USER_NAME = "user_name";
+ public static final String FIRST_NAME = "first_name";
+ public static final String LAST_NAME = "last_name";
+ public static final String APP_DISPLAY_NAME = "app_display_name";
+ // Application base URL is a proper prefix of the on-boarding URL
+ public static final String APP_BASE_URL = "app_base_url";
+
+ public static final String MENU_PROPERTIES_FILE_LOCATION = "menu_properties_file_location";
+ public static final String MENU_QUERY_NAME = "menu_query_name";
+ public static final String APPLICATION_MENU_SET_NAME = "application_menu_set_name";
+ public static final String APPLICATION_MENU_ATTRIBUTE_NAME = "application_menu_attribute_name";
+ public static final String APPLICATION_MENU_PROPERTIES_NAME = "application_menu_properties_name";
+ public static final String BUSINESS_DIRECT_MENU_SET_NAME = "business_direct_menu_set_name";
+ public static final String BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME = "business_direct_menu_attribute_name";
+ public static final String BUSINESS_DIRECT_MENU_PROPERTIES_NAME = "business_direct_menu_properties_name";
+ public static final String RAPTOR_CONFIG_FILE_PATH = "raptor_config_file_path";
+ public static final String HOMEPAGE_DATA_CALLBACK_CLASS = "homepage_data_callback_class";
+ public static final String ERROR_EMAIL_DISTRIBUTION = "error_email_distribution";
+ public static final String ERROR_EMAIL_SOURCE_ADDRESS = "error_email_source_address";
+ public static final String ERROR_EMAIL_SUBJECT_LINE = "error_email_subject_line";
+ public static final String PROFILE_SEARCH_REPORT_ID = "profile_search_report_id";
+ public static final String CALLABLE_PROFILE_SEARCH_REPORT_ID = "callable_profile_search_report_id";
+ public static final String CLUSTERED = "clustered";
+
+ public static final String USER_ATTRIBUTE_NAME = "user_attribute_name";
+ public static final String ROLES_ATTRIBUTE_NAME = "roles_attribute_name";
+ public static final String ROLE_FUNCTIONS_ATTRIBUTE_NAME = "role_functions_attribute_name";
+ public static final String CLIENT_DEVICE_ATTRIBUTE_NAME = "client_device_attribute_name";
+ public static final String CLIENT_DEVICE_EMULATION = "client_device_emulation";
+ public static final String CLIENT_DEVICE_TYPE_TO_EMULATE = "client_device_type_to_emulate";
+ // File generation - Document
+ public static final String TEMPLATES_PATH = "templates_path";
+ public static final String DOCUMENT_XML_ENCODING = "document_xml_encoding";
+
+ // Transaction
+ public static final String ROUTING_DATASOURCE_KEY = "routing_datasource_key";
+
+ // Document Library keys
+ public static final String DOCLIB_ADMIN_ROLE_ID = "doclib_admin_role_id";
+ public static final String DOCLIB_USER_ROLE_ID = "doclib_user_role_id";
+
+ public static final String SYSTEM_PROPERTIES_FILENAME = "system.properties";
+ public static final String FUSION_PROPERTIES_FILENAME = "fusion.properties";
+ public static final String SUCCESS_TASKS_PROPERTIES_FILENAME = "success_tasks.properties";
+
+ // login methods
+ public static final String LOGIN_METHOD_CSP = "login_method_csp";
+ public static final String LOGIN_METHOD_WEB_JUNCTION = "login_method_web_junction";
+ public static final String LOGIN_METHOD_BACKDOOR = "login_method_backdoor";
+ public static final String LOGIN_METHOD_ATTRIBUTE_NAME = "login_method_attribute_name";
+
+ // login error message keys
+ public static final String MESSAGE_KEY_LOGIN_ERROR_COOKIE_EMPTY = "login.error.hrid.empty";
+ public static final String MESSAGE_KEY_LOGIN_ERROR_HEADER_EMPTY = "login.error.header.empty";
+ public static final String MESSAGE_KEY_LOGIN_ERROR_USER_INACTIVE = "login.error.user.inactive";
+ public static final String MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND = "login.error.hrid.not-found";
+ public static final String MESSAGE_KEY_LOGIN_ERROR_APPLICATION_LOCKED = "login.error.application.locked";
+ public static final String MESSAGE_KEY_AUTOLOGIN_NONE = "webphone.autoimport.nouser";
+ public static final String MESSAGE_KEY_AUTOLOGIN_MULTIPLE = "webphone.autoimport.multiple";
+
+ // Application Mobile capability
+ public static final String MOBILE_ENABLE = "mobile_enable";
+
+ public static final String DATABASE_TIME_ZONE = "db.time_zone";
+
+ public static final String AUTO_USER_IMPORT_ENABLE = "auto_user_import_enable";
+ public static final String AUTO_USER_IMPORT_ROLE = "auto_user_import_role";
+
+ public static final String ITRACKER_EMAIL_SOURCE_ADDRESS = "itracker_email_source_address";
+ public static final String ITRACKER_EMAIL_DISTRIBUTION = "itracker_email_distribution";
+ public static final String ITRACKER_SYSTEM_USER = "itracker_system_user_id";
+
+ public static final String MAIL_SERVER_HOST = "mail_server_host";
+ public static final String MAIL_SERVER_PORT = "mail_server_port";
+
+ // Routing Data Source keys
+ public static final String ROUTING_DATASOURCE_KEY_NON_XA = "NON-XA";
+ public static final String ROUTING_DATASOURCE_KEY_XA = "XA";
+ public static final String QUARTZ_JOB_ENABLED = "quartz_job_enable";
+ public static final String WORKFLOW_EMAIL_SENDER = "workflow_email_sender";
+ public static final String DROOLS_GUVNOR_HOME = "drools.guvnor.home";
+
+ // Hibernate Config
+ public static final String HB_DIALECT = "hb.dialect";
+ public static final String HB_SHOW_SQL = "hb.show_sql";
+
+ // DataSource
+ public static final String DB_DRIVER = "db.driver";
+ public static final String DB_CONNECTIONURL = "db.connectionURL";
+ public static final String DB_USERNAME = "db.userName";
+ public static final String DB_PASSWOR = "db.password";
+ public static final String DB_MIN_POOL_SIZE = "db.min_pool_size";
+ public static final String DB_MAX_POOL_SIZE = "db.max_pool_size";
+ public static final String IDLE_CONNECTION_TEST_PERIOD = "hb.idle_connection_test_period";
+
+ public static final String MYLOGINS_FEED_CRON = "mylogins_feed_cron";
+ public static final String SESSIONTIMEOUT_FEED_CRON = "sessiontimeout_feed_cron";
+ public static final String LOG_CRON = "log_cron";
+
+ public static final String DB_ENCRYPT_FLAG = "db.encrypt_flag";
+
+ // Decryption Key
+ public static final String Decryption_Key = "decryption_key";
+
+ // Logging/Audit Fields
+ public static final String MDC_APPNAME = "AppName";
+ public static final String MDC_REST_PATH = "RestPath";
+ public static final String MDC_REST_METHOD = "RestMethod";
+ public static final String INSTANCE_UUID = "instance_uuid";
+ public static final String MDC_CLASS_NAME = "ClassName";
+ public static final String MDC_LOGIN_ID = "LoginId";
+ public static final String MDC_TIMER = "Timer";
+ public static final String SDK_NAME = "ECOMP_SDK";
+ public static final String ECOMP_REQUEST_ID = "X-ECOMP-RequestID";
+ public static final String PARTNER_NAME = "PartnerName";
+ public static final String FULL_URL = "Full-URL";
+ public static final String AUDITLOG_BEGIN_TIMESTAMP = "AuditLogBeginTimestamp";
+ public static final String AUDITLOG_END_TIMESTAMP = "AuditLogEndTimestamp";
+ public static final String METRICSLOG_BEGIN_TIMESTAMP = "MetricsLogBeginTimestamp";
+ public static final String METRICSLOG_END_TIMESTAMP = "MetricsLogEndTimestamp";
+ public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+ public static final String STATUS_CODE = "StatusCode";
+ public static final String RESPONSE_CODE = "ResponseCode";
+ // Component or sub component name
+ public static final String TARGET_ENTITY = "TargetEntity";
+ // API or operation name
+ public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
+ // Logging Compliance
+ public static final String DOUBLE_WHITESPACE_SEPARATOR = " ";
+ public static final String SINGLE_WHITESPACE_SEPARATOR = " ";
+ public static final String SINGLE_QUOTE = "'";
+ public static final String NA = "N/A";
+ public static final String UNKNOWN = "Unknown";
+ public static final String SECURITY_LOG_TEMPLATE = "Protocol:{0} Security-Event-Type:{1} Login-ID:{2} {3}";
+ public static final String ECOMP_PORTAL_BE = "ECOMP_PORTAL_BE";
+ public static final String PROTOCOL = "PROTOCOL";
+ public static final String SECURIRY_EVENT_TYPE = "SECURIRY_EVENT_TYPE";
+ public static final String LOGIN_ID = "LOGIN_ID";
+ public static final String ACCESSING_CLIENT = "ACCESSING_CLIENT";
+ public static final String RESULT_STR = "RESULT";
+ public static final String ECOMP_PORTAL_FE = "ECOMP_PORTAL_FE";
+ public static final String ADDITIONAL_INFO = "ADDITIONAL_INFO";
+ public static final String INTERFACE_NAME = "INTERFACE_NAME";
+ public static final String USERAGENT_NAME = "user-agent";
+
+ // Protocols
+ public static final String HTTP = "HTTP";
+ public static final String HTTPS = "HTTPS";
+ public static final String SSO_VALUE = "sso";
+
+ public enum RESULT_ENUM {
+ SUCCESS, FAILURE
+ }
+
+ public enum SecurityEventTypeEnum {
+ FE_LOGIN_ATTEMPT, FE_LOGOUT, SSO_LOGIN_ATTEMPT_PHASE_1, SSO_LOGIN_ATTEMPT_PHASE_2, SSO_LOGOUT, LDAP_PHONEBOOK_USER_SEARCH, INCOMING_REST_MESSAGE, OUTGOING_REST_MESSAGE, REST_AUTHORIZATION_CREDENTIALS_MODIFIED, ECOMP_PORTAL_USER_MODIFIED, ECOMP_PORTAL_USER_ADDED, ECOMP_PORTAL_USER_REMOVED, ECOMP_PORTAL_WIDGET, INCOMING_UEB_MESSAGE, ECOMP_PORTAL_HEALTHCHECK
+ }
+
+ // Menu
+ public static final String CONTACT_US_LINK = "contact_us_link";
+
+ // Left Menu
+ public static final String LEFT_MENU_PARENT = "parentList";
+ public static final String LEFT_MENU_CHILDREND = "childItemList";
+}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java
index a8cc7fd7..a8cc7fd7 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/UsageUtils.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java
index 58bcb252..da69b729 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/util/YamlUtils.java
@@ -36,7 +36,10 @@ public class YamlUtils {
static {
Representer representer = new Representer();
- yaml = new Yaml(representer);
+ //representer.addClassTag(Domain.class, Tag.MAP);
+
+
+ yaml = new Yaml(representer);
}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java
index ddf08c8f..ddf08c8f 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/PeerBroadcastSocket.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java
index 810cba5c..810cba5c 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/socket/WebRTCSocket.java
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java
new file mode 100644
index 00000000..295cff42
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java
@@ -0,0 +1,213 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.web.support;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.sql.DataSource;
+
+import org.hibernate.Session;
+import org.openecomp.portalsdk.core.exception.SessionExpiredException;
+import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
+import org.openecomp.portalsdk.core.service.DataAccessService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+
+public class AppUtils {
+
+
+
+ private static DataAccessService dataAccessService;
+
+ private static AbstractCacheManager cacheManager;
+
+ private static boolean applicationLocked;
+
+ private static Hashtable feedback = new Hashtable();
+
+ private static DataSource datasource;
+
+ public static DataSource getDatasource() {
+ return datasource;
+ }
+
+ @Autowired
+ public void setDatasource(DataSource datasource) {
+ AppUtils.datasource = datasource;
+ }
+
+ public AppUtils() {
+ }
+
+ public static HttpSession getSession(HttpServletRequest request) {
+ HttpSession session = null;
+ if (request != null) {
+ session = request.getSession(false);
+ if (session == null) {
+ throw new SessionExpiredException();
+ }
+ } else {
+ throw new SessionExpiredException();
+ }
+ return session;
+ }
+
+ public static List getLookupList(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy) {
+ return getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
+ } // getLookupList
+
+ public static List getLookupList(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy, Session session) {
+ String cacheKey = dbTable + "|" + dbValueCol + "|" + dbLabelCol + "|" + dbFilter + "|" + dbOrderBy;
+ List list = getLookupListFromCache(cacheKey);
+ if (list == null) {
+ list = getDataAccessService().getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
+ if (list != null) {
+ addLookupListToCache(cacheKey, list);
+ }
+ } // if
+ return list;
+ } // getLookupList
+
+ private static List getLookupListFromCache(String key) {
+ return (List)getObjectFromCache(key);
+ } // getLookupListFromCache
+
+ public static Object getObjectFromCache(String key) {
+ if (isCacheManagerAvailable()) {
+ return getCacheManager().getObject(key);
+ } else {
+ return null;
+ }
+ } // getObjectFromCache
+
+ private static void addLookupListToCache(String key, List list) {
+ addObjectToCache(key, list);
+ } // addLookupListToCache
+
+ public static void addObjectToCache(String key, Object o) {
+ if (isCacheManagerAvailable()) {
+ getCacheManager().putObject(key, o);
+ }
+ } // addObjectToCache
+
+ @Autowired
+ public void setCacheManager(AbstractCacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
+
+ public static AbstractCacheManager getCacheManager() {
+ return cacheManager;
+ }
+
+ public static boolean isCacheManagerAvailable() {
+ return (getCacheManager() != null);
+ }
+
+ public void setFeedback(Hashtable feedback) {
+ this.feedback = feedback;
+ }
+
+ public static boolean isApplicationLocked() {
+ return applicationLocked;
+ }
+
+ public static DataAccessService getDataAccessService() {
+ return dataAccessService;
+ }
+
+ @Autowired
+ public void setDataAccessService(DataAccessService dataAccessService) {
+ this.dataAccessService = dataAccessService;
+ }
+
+ public static void setApplicationLocked(boolean locked) {
+ applicationLocked = locked;
+ }
+
+ public static String getLookupValueByLabel(String label, String dbTable, String dbValueCol, String dbLabelCol) {
+ if (label == null || label.equals("")) {
+ return "";
+ }
+
+ List<org.openecomp.portalsdk.core.domain.Lookup> lstResult = getLookupListNoCache(dbTable, dbValueCol, dbLabelCol, dbLabelCol + "='" + label.replaceAll("'", "''") + "'", "");
+ if (lstResult == null) {
+ return "";
+ }
+ if (lstResult.size() > 0) {
+ return ((org.openecomp.portalsdk.core.domain.Lookup)lstResult.toArray()[0]).getValue();
+ } else {
+ return "";
+ }
+ }
+
+ public static String getLookupValueByLabel(String label, List lookupList) {
+ Iterator i = null;
+
+ if (label == null || label.equalsIgnoreCase("")) {
+ return "";
+ }
+
+ if (lookupList == null || lookupList.size() == 0) {
+ return "";
+ }
+
+ i = lookupList.iterator();
+ while (i.hasNext()) {
+ org.openecomp.portalsdk.core.domain.Lookup lookup = (org.openecomp.portalsdk.core.domain.Lookup)i.next();
+
+ if (lookup.getLabel().equals(label)) {
+ return lookup.getValue();
+ }
+ }
+
+ return "";
+}
+ public static List getLookupListNoCache(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy) {
+ return getLookupListNoCache(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
+ } // getLookupListNoCache
+
+
+ public static List getLookupListNoCache(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy, Session session) {
+ return getDataAccessService().getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
+ } // getLookupListNoCache
+
+
+
+} // AppUtils
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java
index 1d09eba0..1d09eba0 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/ControllerProperties.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java
index d8993b03..d8993b03 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/FeedbackMessage.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java
index 5566bf90..5566bf90 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/JsonMessage.java
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java
index 9ab956d0..0cf628aa 100644
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/MessagesList.java
@@ -19,8 +19,7 @@
*/
package org.openecomp.portalsdk.core.web.support;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
public class MessagesList {
diff --git a/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java
new file mode 100644
index 00000000..37eaccad
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java
@@ -0,0 +1,423 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.web.support;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.openecomp.portalsdk.core.domain.Role;
+import org.openecomp.portalsdk.core.domain.RoleFunction;
+import org.openecomp.portalsdk.core.domain.UrlsAccessible;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.exception.SessionExpiredException;
+import org.openecomp.portalsdk.core.lm.FusionLicenseManager;
+import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.openecomp.portalsdk.core.menu.MenuBuilder;
+import org.openecomp.portalsdk.core.restful.domain.EcompRole;
+import org.openecomp.portalsdk.core.restful.domain.EcompUser;
+import org.openecomp.portalsdk.core.service.DataAccessService;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@SuppressWarnings("rawtypes")
+public class UserUtils {
+
+ static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UserUtils.class);
+
+ public static final String KEY_USER_ROLES_CACHE = "userRoles";
+
+ private static DataAccessService dataAccessService;
+
+ public static void setUserSession(HttpServletRequest request, User user, Set applicationMenuData,
+ Set businessDirectMenuData, String loginMethod) {
+ HttpSession session = request.getSession(true);
+
+ UserUtils.clearUserSession(request); // let's clear the current user
+ // session to avoid any
+ // conflicts during the set
+
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME), user);
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_ATTRIBUTE_NAME), loginMethod);
+
+ getRoleFunctions(request);
+
+ // truncate the role (and therefore the role function) data to save
+ // memory in the session
+ user.setRoles(null);
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME), user.getFullName());
+ session.setAttribute(SystemProperties.FIRST_NAME, user.getFirstName());
+ session.setAttribute(SystemProperties.LAST_NAME, user.getLastName());
+ ServletContext context = session.getServletContext();
+ int licenseVarificationFlag = 3;
+ try {
+ licenseVarificationFlag = (Integer) context.getAttribute("licenseVerification");
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.debugLogger, "Error while get license varification " + e.getMessage());
+ }
+ String displayName = "";
+ if (SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) != null)
+ displayName = SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME);
+ switch (licenseVarificationFlag) {
+ case FusionLicenseManager.DEVELOPER_LICENSE:
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME),
+ displayName + " [Development Version]");
+ break;
+ case FusionLicenseManager.EXPIRED_LICENSE:
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME),
+ displayName + " [LICENSE EXPIRED]");
+ break;
+ case FusionLicenseManager.VALID_LICENSE:
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME), displayName);
+ break;
+ default:
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME),
+ displayName + " [INVALID LICENSE]");
+ break;
+ }
+
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME),
+ MenuBuilder.filterMenu(applicationMenuData, request));
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME),
+ MenuBuilder.filterMenu(businessDirectMenuData, request));
+ }
+
+ public static void clearUserSession(HttpServletRequest request) {
+ HttpSession session = AppUtils.getSession(request);
+
+ if (session == null) {
+ throw new SessionExpiredException();
+ }
+
+ // removes all stored attributes from the current user's session
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME));
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME));
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME));
+ session.removeAttribute(SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_ATTRIBUTE_NAME));
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Set getRoleFunctions(HttpServletRequest request) {
+ HashSet roleFunctions = null;
+
+ HttpSession session = request.getSession();
+ roleFunctions = (HashSet) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME));
+
+ if (roleFunctions == null) {
+ HashMap roles = getRoles(request);
+ roleFunctions = new HashSet();
+
+ Iterator i = roles.keySet().iterator();
+
+ while (i.hasNext()) {
+ Long roleKey = (Long) i.next();
+ Role role = (Role) roles.get(roleKey);
+
+ Iterator j = role.getRoleFunctions().iterator();
+
+ while (j.hasNext()) {
+ RoleFunction function = (RoleFunction) j.next();
+ roleFunctions.add(function.getCode());
+ }
+ }
+
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME),
+ roleFunctions);
+ }
+
+ return roleFunctions;
+ }
+
+ public static HashMap getRoles(HttpServletRequest request) {
+ HashMap roles = null;
+
+ // HttpSession session = request.getSession();
+ HttpSession session = AppUtils.getSession(request);
+ roles = (HashMap) session.getAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME));
+
+ // if roles are not already cached, let's grab them from the user
+ // session
+ if (roles == null) {
+ User user = getUserSession(request);
+
+ // get all user roles (including the tree of child roles)
+ roles = getAllUserRoles(user);
+
+ session.setAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME),
+ getAllUserRoles(user));
+ }
+
+ return roles;
+ }
+
+ public static User getUserSession(HttpServletRequest request) {
+ HttpSession session = AppUtils.getSession(request);
+
+ if (session == null) {
+ throw new SessionExpiredException();
+ }
+
+ return (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
+ }
+
+ @SuppressWarnings("unchecked")
+ public static HashMap getAllUserRoles(User user) {
+ HashMap roles = new HashMap();
+ Iterator i = user.getRoles().iterator();
+
+ while (i.hasNext()) {
+ Role role = (Role) i.next();
+
+ if (role.getActive()) {
+ roles.put(role.getId(), role);
+
+ // let's take a recursive trip down the tree to add all child
+ // roles
+ addChildRoles(role, roles);
+ }
+ }
+
+ return roles;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void addChildRoles(Role role, HashMap roles) {
+ Set childRoles = role.getChildRoles();
+ if (childRoles != null && childRoles.size() > 0) {
+ Iterator j = childRoles.iterator();
+ while (j.hasNext()) {
+ Role childRole = (Role) j.next();
+ if (childRole.getActive()) {
+ roles.put(childRole.getId(), childRole);
+ addChildRoles(childRole, roles);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Answers whether the specified URL is accessible.
+ *
+ * @param request
+ * @param currentUrl
+ * @return true if yes, false if no.
+ */
+ public static boolean isUrlAccessible(HttpServletRequest request, String currentUrl) {
+ boolean isAccessible = false;
+ Map<String,String> params = new HashMap<>();
+ params.put("current_url", currentUrl);
+ List list = getDataAccessService().executeNamedQuery("restrictedUrls", params, null);
+ // loop through the list of restricted URL's
+ if (list != null && list.size() > 0) {
+ for (int i = 0; i < list.size(); i++) {
+ /*
+ * Object[] restrictedUrl = (Object[])list.get(i);
+ *
+ * String url = (String)restrictedUrl[0]; String functionCd =
+ * (String)restrictedUrl[1];
+ */
+ UrlsAccessible urlFunctions = (UrlsAccessible) list.get(i);
+ // String url = (String) urlFunctions.getUrl();
+ String functionCd = (String) urlFunctions.getFunctionCd();
+ if (UserUtils.isAccessible(request, functionCd)) {
+ isAccessible = true;
+ }
+ }
+ return isAccessible;
+ }
+ return true;
+ }
+
+ public static boolean hasRole(HttpServletRequest request, String roleKey) {
+ return getRoles(request).keySet().contains(new Long(roleKey));
+ }
+
+ public static boolean hasRole(User user, String roleKey) {
+ return getAllUserRoles(user).keySet().contains(new Long(roleKey));
+ }
+
+ public static boolean isAccessible(HttpServletRequest request, String functionKey) {
+ return getRoleFunctions(request).contains(functionKey);
+ }
+
+ public static String getLoginMethod(HttpServletRequest request) {
+ HttpSession session = AppUtils.getSession(request);
+
+ if (session == null) {
+ throw new SessionExpiredException();
+ }
+
+ return (String) session
+ .getAttribute(SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_ATTRIBUTE_NAME));
+ }
+
+ public static DataAccessService getDataAccessService() {
+ return dataAccessService;
+ }
+
+ @Autowired
+ public void setDataAccessService(DataAccessService dataAccessService) {
+ UserUtils.dataAccessService = dataAccessService;
+ }
+
+ public static int getUserId(HttpServletRequest request) {
+ return getUserIdAsLong(request).intValue();
+ }
+
+ public static Long getUserIdAsLong(HttpServletRequest request) {
+ Long userId = new Long(SystemProperties.getProperty(SystemProperties.APPLICATION_USER_ID));
+
+ if (request != null) {
+ if (getUserSession(request) != null) {
+ userId = getUserSession(request).getId();
+ }
+ }
+ return userId;
+ }
+
+
+ private static final Object stackTraceLock = new Object();
+ /**
+ * Serializes a stack trace of the specified throwable and returns it as a string.
+ *
+ * TODO: why is synchronization required?
+ *
+ * @param t
+ * @return String version of stack trace
+ */
+ public static String getStackTrace(Throwable t) {
+ synchronized (stackTraceLock) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ return sw.toString();
+ }
+ }
+
+ /**
+ * Gets the full URL of the request by joining the request and any query string.
+ *
+ * @param request
+ * @return Full URL of the request including query parameters
+ */
+ public static String getFullURL(HttpServletRequest request) {
+ if (request != null) {
+ StringBuffer requestURL = request.getRequestURL();
+ String queryString = request.getQueryString();
+
+ if (queryString == null) {
+ return requestURL.toString();
+ } else {
+ return requestURL.append('?').append(queryString).toString();
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Gets or generates a request ID by searching for header X-ECOMP-RequestID.
+ * If not found, generates a new random UUID.
+ *
+ * @param request
+ * @return Request ID for the specified request
+ */
+ public static String getRequestId(HttpServletRequest request) {
+ Enumeration<String> headerNames = request.getHeaderNames();
+
+ String requestId = "";
+ try {
+ while (headerNames.hasMoreElements()) {
+ String headerName = (String) headerNames.nextElement();
+ if (logger.isTraceEnabled())
+ logger.trace(EELFLoggerDelegate.debugLogger,
+ "getRequestId: header {} = {}", headerName, request.getHeader(headerName));
+ if (headerName.equalsIgnoreCase(SystemProperties.ECOMP_REQUEST_ID)) {
+ requestId = request.getHeader(headerName);
+ break;
+ }
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.debugLogger, "getRequestId: failed to get headder", e);
+ }
+
+ if (requestId.isEmpty())
+ requestId = UUID.randomUUID().toString();
+ logger.debug(EELFLoggerDelegate.debugLogger, "getRequestId: result is {}", requestId);
+ return requestId;
+ }
+
+ /**
+ * Converts a Hibernate-mapped User object to a JSON-serializable EcompUser object.
+ *
+ * @param user
+ * @return EcompUser with a subset of fields.
+ */
+ public static EcompUser convertToEcompUser(User user) {
+ EcompUser userJson = new EcompUser();
+ userJson.setEmail(user.getEmail());
+ userJson.setFirstName(user.getFirstName());
+ userJson.setHrid(user.getHrid());
+ userJson.setJobTitle(user.getJobTitle());
+ userJson.setLastName(user.getLastName());
+ userJson.setLoginId(user.getLoginId());
+ userJson.setOrgManagerUserId(user.getOrgManagerUserId());
+ userJson.setMiddleInitial(user.getMiddleInitial());
+ userJson.setOrgCode(user.getOrgCode());
+ userJson.setOrgId(user.getOrgId());
+ userJson.setPhone(user.getPhone());
+ userJson.setOrgUserId(user.getOrgUserId());
+ Set<EcompRole> ecompRoles = new TreeSet<EcompRole>();
+ for (Role role : user.getRoles()) {
+ ecompRoles.add(convertToEcompRole(role));
+ }
+ userJson.setRoles(ecompRoles);
+ return userJson;
+ }
+
+ /**
+ * Converts a Hibernate-mapped Role object to a JSON-serializable EcompRole object.
+ *
+ * @param role
+ * @return EcompRole with a subset of fields: ID and name
+ */
+ public static EcompRole convertToEcompRole(Role role) {
+ EcompRole ecompRole = new EcompRole();
+ ecompRole.setId(role.getId());
+ ecompRole.setName(role.getName());
+ return ecompRole;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockApplicationContextTestSuite.java b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockApplicationContextTestSuite.java
new file mode 100644
index 00000000..0867f2a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockApplicationContextTestSuite.java
@@ -0,0 +1,114 @@
+package org.openecomp.fusion.core;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.openecomp.portalsdk.core.conf.AppConfig;
+import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
+import org.openecomp.portalsdk.core.util.CacheManager;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+
+/**
+ * In order to write a unit test, 1. inherit this class - See SanityTest.java 2.
+ * place the "war" folder on your test class's classpath 3. run the test with
+ * the following VM argument; This is important because when starting the
+ * application from Container, the System Properties file
+ * (SystemProperties.java) can have the direct path but, when running from the
+ * Mock Junit container, the path should be prefixed with "classpath" to enable
+ * the mock container to search for the file in the classpath
+ * -Dcontainer.classpath="classpath:"
+ *
+ */
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = { MockAppConfig.class })
+@ActiveProfiles(value = "test")
+public class MockApplicationContextTestSuite {
+
+ @Autowired
+ public WebApplicationContext wac;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void setup() {
+ if (mockMvc == null) {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+
+ }
+ }
+
+ public Object getBean(String name) {
+ return this.wac.getBean(name);
+ }
+
+ public MockMvc getMockMvc() {
+ return mockMvc;
+ }
+
+ public void setMockMvc(MockMvc mockMvc) {
+ this.mockMvc = mockMvc;
+ }
+
+ public WebApplicationContext getWebApplicationContext() {
+ return wac;
+ }
+
+}
+
+@Configuration
+@ComponentScan(basePackages = "org.openecomp", excludeFilters = {})
+@Profile("test")
+class MockAppConfig extends AppConfig {
+
+ @Bean
+ public SystemProperties systemProperties() {
+ return new MockSystemProperties();
+ }
+
+ @Bean
+ public AbstractCacheManager cacheManager() {
+ return new CacheManager() {
+
+ public void configure() throws IOException {
+
+ }
+ };
+ }
+
+ protected String[] tileDefinitions() {
+ return new String[] { "classpath:/WEB-INF/fusion/defs/definitions.xml",
+ "classpath:/WEB-INF/defs/definitions.xml" };
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // registry.addInterceptor(new
+ // SessionTimeoutInterceptor()).excludePathPatterns(getExcludeUrlPathsForSessionTimeout());
+ // registry.addInterceptor(resourceInterceptor());
+ }
+
+ public static class MockSystemProperties extends SystemProperties {
+
+ public MockSystemProperties() {
+ }
+
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockHibernateMappingLocations.java b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockHibernateMappingLocations.java
new file mode 100644
index 00000000..fea7cdda
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/fusion/core/MockHibernateMappingLocations.java
@@ -0,0 +1,23 @@
+package org.openecomp.fusion.core;
+
+import org.openecomp.portalsdk.core.conf.HibernateMappingLocatable;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+@Component
+@Profile("test")
+public class MockHibernateMappingLocations implements HibernateMappingLocatable{
+
+ @Override
+ public Resource[] getMappingLocations() {
+ return new Resource[]{new ClassPathResource("WEB-INF/fusion/orm/Fusion.hbm.xml"), new ClassPathResource("WEB-INF/fusion/orm/Workflow.hbm.xml")};
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ return new String[] { "org.openecomp" };
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockApplicationContextTestSuite.java b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockApplicationContextTestSuite.java
new file mode 100644
index 00000000..812d438a
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockApplicationContextTestSuite.java
@@ -0,0 +1,143 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.openecomp.portalsdk.core.conf.AppConfig;
+import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
+import org.openecomp.portalsdk.core.util.CacheManager;
+import org.openecomp.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+
+/**
+ *
+ *
+ *
+ * In order to write a unit test,
+ * 1. inherit this class - See SanityTest.java
+ * 2. place the "war" folder on your test class's classpath
+ * 3. run the test with the following VM argument; This is important because when starting the application from Container, the System Properties file (SystemProperties.java) can have the direct path
+ * but, when running from the Mock Junit container, the path should be prefixed with "classpath" to enable the mock container to search for the file in the classpath
+ * -Dcontainer.classpath="classpath:"
+ *
+ */
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {MockAppConfig.class})
+@ActiveProfiles(value="test")
+public class MockApplicationContextTestSuite {
+
+ @Autowired
+ public WebApplicationContext wac;
+
+ private MockMvc mockMvc;
+
+ @Before
+ public void setup() {
+ if(mockMvc == null) {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+
+ }
+ }
+
+ public Object getBean(String name) {
+ return this.wac.getBean(name);
+ }
+
+
+ public MockMvc getMockMvc() {
+ return mockMvc;
+ }
+
+ public void setMockMvc(MockMvc mockMvc) {
+ this.mockMvc = mockMvc;
+ }
+
+ public WebApplicationContext getWebApplicationContext() {
+ return wac;
+ }
+
+
+
+
+}
+
+
+ @Configuration
+ @ComponentScan(basePackages = "org.openecomp",
+ excludeFilters = { }
+ )
+ @Profile("test")
+ class MockAppConfig extends AppConfig {
+
+ @Bean
+ public SystemProperties systemProperties(){
+ return new MockSystemProperties();
+ }
+
+ @Bean
+ public AbstractCacheManager cacheManager() {
+ return new CacheManager() {
+
+ public void configure() throws IOException {
+
+ }
+ };
+ }
+
+ protected String[] tileDefinitions() {
+ return new String[] {"classpath:/WEB-INF/fusion/defs/definitions.xml", "classpath:/WEB-INF/defs/definitions.xml"};
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ //registry.addInterceptor(new SessionTimeoutInterceptor()).excludePathPatterns(getExcludeUrlPathsForSessionTimeout());
+ //registry.addInterceptor(resourceInterceptor());
+ }
+
+ public static class MockSystemProperties extends SystemProperties {
+
+ public MockSystemProperties() {
+ }
+
+ }
+
+ }
+
+
+
+
diff --git a/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockHibernateMappingLocations.java b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockHibernateMappingLocations.java
new file mode 100644
index 00000000..a9fdebb4
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/MockHibernateMappingLocations.java
@@ -0,0 +1,42 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk;
+
+import org.openecomp.portalsdk.core.conf.HibernateMappingLocatable;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+@Component
+@Profile("test")
+public class MockHibernateMappingLocations implements HibernateMappingLocatable {
+
+ public Resource[] getMappingLocations() {
+ return new Resource[] { new ClassPathResource("WEB-INF/fusion/orm/Fusion.hbm.xml"),
+ new ClassPathResource("WEB-INF/fusion/orm/Workflow.hbm.xml") };
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ return new String[] { "org.openecomp" };
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/controller/sessionmgt/PortalCommunicationTest.java b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/controller/sessionmgt/PortalCommunicationTest.java
new file mode 100644
index 00000000..6b87dbe4
--- /dev/null
+++ b/ecomp-sdk/epsdk-core/src/test/java/org/openecomp/portalsdk/controller/sessionmgt/PortalCommunicationTest.java
@@ -0,0 +1,75 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.controller.sessionmgt;
+/*package org.openecomp.portalsdk.controller.sessionmgt;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import org.openecomp.portalsdk.MockApplicationContextTestSuite;
+import org.openecomp.portalsdk.service.sessionmgt.CoreTimeoutHandler;
+
+public class PortalCommunicationTest extends MockApplicationContextTestSuite{
+
+
+ @Test
+ public void testGetTimeoutSessions() throws Exception {
+
+ MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/sessionTimeOuts");
+ MockHttpSession httpSession = new MockHttpSession(this.wac.getServletContext(),"1234");
+ CoreTimeoutHandler.sessionCreated("12", "1234", httpSession);
+
+ ResultActions ra = this.getMockMvc().perform(requestBuilder);
+
+ System.out.println(" %%%%%%%%%%%%%%%%%%%%%%%%% " + ra.andReturn().getResponse().getContentAsString());
+ System.out.println(" %%%%%%%%%%%%%%%%%%%%%%%%% " + "{\"12\":{\"jSessionId\":\"1234\",\"sessionTimOutMilliSec\":");
+
+ Assert.assertTrue(ra.andReturn().getResponse().getContentAsString().startsWith("{\"12\":{\"jSessionId\":\"1234\",\"sessionTimOutMilliSec\":"));
+
+ }
+
+ @Test
+ public void testUpdateTimeoutSessions() throws Exception {
+
+ // pre condition
+ MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/sessionTimeOuts");
+ MockHttpSession httpSession = new MockHttpSession(this.wac.getServletContext(),"1234");
+ CoreTimeoutHandler.sessionCreated("12", "1234", httpSession);
+ ResultActions ra = this.getMockMvc().perform(requestBuilder);
+
+ String responseSessMapStr = ra.andReturn().getResponse().getContentAsString();
+
+
+ // test
+ requestBuilder = MockMvcRequestBuilders.post("/api/updateSessionTimeOuts");
+ requestBuilder.param("sessionMap", responseSessMapStr);
+ ra = this.getMockMvc().perform(requestBuilder);
+
+
+ }
+
+
+
+}
+*/
diff --git a/ecomp-sdk/epsdk-fw/.gitignore b/ecomp-sdk/epsdk-fw/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-fw/README.md b/ecomp-sdk/epsdk-fw/README.md
new file mode 100644
index 00000000..af36ddc2
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/README.md
@@ -0,0 +1,111 @@
+# ECOMP Portal SDK Framework
+
+## Overview
+
+This is the Maven project for the ECOMP Portal SDK Framework library,
+which is distributed as epsdk-fw-N.N.N.jar. This library
+(once called third-party onboarding) provides features to
+partner applications that use a J2EE Servlet 3.0 container
+as Apache Tomcat. These features include:
+- REST endpoint for use by the ECOMP Portal aplication. This endpoint
+ answers queries about roles, users and user-role assignments.
+ The endpoint methods are defined by the Java interface class
+ IPortalRestAPIService. Application developers must provide a
+ class that implements this interface, and publish the name of
+ that class in the properties file as discussed below.
+- A session listener that updates a collection with current user sessions
+ as sessions are created and destroyed. This information is used to maintain
+ and extend user session timeouts across applications that are on-boarded to
+ the ECOMP portal.
+- Single sign-on to the application via either the AT&T Central Security Platform (SCP)
+ or WebSEAL Junction.
+- Communication with the ECOMP Portal to fetch a user-specific functional menu, either
+ via REST or UEB.
+
+Unlike the other ECOMP SDK libraries, this library does NOT require Hibernate,
+nor does it require Spring.
+
+## Release Notes
+
+### OpenECOMP Distributions
+
+Build 1.2.8, ?? ??? 2017
+* put new entries here *
+
+Build 1.2.7, 10 Apr 2017
+- No changes
+
+Build 1.2.6, 23 Mar 2017
+- No changes
+
+Build 1.2.5, 16 Mar 2017
+- Extended PortalTimeoutHandler to show method names in all exception output
+- US869765 Post OpenSource SDKs and ecompFW apps should listen to endpoint /api/v2 instead of just /api
+
+Build 1.2.4, 10 Mar 2017
+- No changes
+
+Build 1.2.3, 8 Mar 2017
+- No changes
+
+Build 1.2.2, 6 Mar 2017
+- No changes
+
+Build 1.2.1, 2 Mar 2017
+- Refactor to remove dependency on AT&T Global Log On single sign on (SSO) library.
+- Move UEB/Cambria library and demonstration use classes out of FW
+
+Build 1.2.0, 9 Feb 2017
+- Change group to org.openecomp.ecompsdkos; restart version numbering for open-source distribution
+
+### Closed-Source Distributions
+
+The following history is preserved for the benefit of partner application teams.
+
+Version 4.3.5, 2 Feb 2017
+- No changes
+
+Version 4.3.4 13 Jan 2017
+- No changes
+
+Version 4.3.3, 11 Jan 2017
+- US779882 Extend analytics servlet to use content type text/javascript for analytics script;
+ check for empty user ID when validating analytics GET/POST requests
+
+Version 4.3.2, 9 Jan 2017
+- US779882 Extend servlet to provide GET/POST endpoints for Web Analytics
+
+Version 4.3.1, 3 Jan 2017
+- No changes
+
+Version 4.2.1, 15 Dec 2016
+- DE255409 trim trailing space on values fetched from Portal, System properties
+
+Version 4.1.4, 22 Nov 2016
+ - No changes
+
+Version 4.1.3, 14 Nov 2016
+ - No changes
+
+Version 4.1.2, 14 Nov 2016
+ - No changes
+
+Version 4.1.1, 3 Nov 2016
+ - No changes
+
+Version 3.3.3, 13 Oct 2016
+ - No changes
+
+Version 3.3.2, 26 Sep 2016
+ - DE237818, fix bug that blocked return of session timeout information
+
+Version 3.3.1, 22 Sep 2016
+ - No changes
+
+Version 3.2.2, 4 Aug 2016
+
+Version 3.2.1, 12 July 2016
+
+Version 2.0.3, 13 June 2016
+
+Version 2.0.2, 27 May 2016
diff --git a/ecomp-sdk/epsdk-fw/pom.xml b/ecomp-sdk/epsdk-fw/pom.xml
new file mode 100644
index 00000000..504d768a
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-fw</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>jar</packaging>
+ <name>ECOMP Portal SDK Framework</name>
+
+ <!-- properties are inherited from parent -->
+
+ <!-- repositories are inherited from parent -->
+
+ <!-- profiles are inherited from parent -->
+
+ <build>
+
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/portal*.properties</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <plugins>
+
+ <!-- some plugins inherited from parent -->
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <archive-version>${project.version}</archive-version>
+ <internal-version>${sdk-internal.version}</internal-version>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+ <dependencies>
+
+ <!-- publicly available -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.10</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java
new file mode 100644
index 00000000..0efd1ce4
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java
@@ -0,0 +1,175 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.onboarding.crossapi;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+import org.openecomp.portalsdk.core.restful.domain.EcompRole;
+import org.openecomp.portalsdk.core.restful.domain.EcompUser;
+
+/**
+ * Defines the REST API Interface that an on-boarding application must implement
+ * to answer queries and accept updates from the ECOMP Portal about the
+ * application's users, roles and user-role assignments.
+ */
+public interface IPortalRestAPIService {
+
+ // EcompUser Interface
+
+ /**
+ * Creates a user with the specified details. If any error occurs, for
+ * example the user exists, the method should throw PortalApiException with
+ * an appropriate message. The FW library will catch the exception and send
+ * an appropriate response to Portal.
+ *
+ * @param user
+ * Model object with attributes of user to be created.
+ * @throws PortalAPIException
+ * If any error occurs while processing the request; for
+ * example, user exists.
+ */
+ public void pushUser(EcompUser user) throws PortalAPIException;
+
+ /**
+ * Updates details about the user with the specified loginId. For example,
+ * mark user as inactive. If any error occurs, the method should throw
+ * PortalApiException with an appropriate message. The FW library will catch
+ * the exception and send an appropriate response to Portal.
+ *
+ * @param loginId
+ * EcompUser ID to be updated.
+ * @param user
+ * Model object with attributes of user to be updated.
+ * @throws PortalAPIException
+ * If any error occurs while processing the request; for
+ * example, unknown user.
+ */
+ public void editUser(String loginId, EcompUser user) throws PortalAPIException;
+
+ /**
+ * Gets and returns the user object with the specified loginId. If any error
+ * occurs, the method should throw PortalApiException with an appropriate
+ * message. The FW library will catch the exception and send an appropriate
+ * response to Portal
+ *
+ * @param loginId
+ * EcompUser ID to be fetched
+ * @return Model object with user attributes.
+ * @throws PortalAPIException
+ * If any error occurs while processing the request; for
+ * example, unknown user.
+ */
+ public EcompUser getUser(String loginId) throws PortalAPIException;
+
+ /**
+ * Gets and returns a list of active users. If any error occurs, the method
+ * should throw PortalApiException with an appropriate message. The FW
+ * library will catch the exception and send an appropriate response to
+ * Portal.
+ *
+ * @return List of user attribute model objects; empty list if none are
+ * found.
+ * @throws PortalAPIException
+ * If any error occurs while processing the request.
+ */
+ public List<EcompUser> getUsers() throws PortalAPIException;
+
+ // Roles Interface
+
+ /**
+ * Gets and returns a list of active roles. If any error occurs, the method
+ * should throw PortalApiException with an appropriate message. The FW
+ * library will catch the exception and send an appropriate response to
+ * Portal.
+ *
+ * @return List of role attribute objects; empty list if none are found.
+ * @throws PortalAPIException
+ * If an unexpected error occurs while processing the request.
+ */
+ public List<EcompRole> getAvailableRoles() throws PortalAPIException;
+
+ /**
+ * Updates roles for the user with the specified loginId to the list of
+ * roles provided as the second argument. After this operation, the should
+ * have ONLY the roles provided in the list above. For example, if user had
+ * roles r1, r2 and r3; and a call was made to pushUserRole with a list
+ * containing only roles r3 and r4, this method should leave the user with
+ * roles r3 and r4 since those were the ONLY roles provided in second
+ * argument. If any error occurs, the method should throw PortalApiException
+ * with an appropriate message. The FW library will catch the exception and
+ * send an appropriate response to Portal.
+ *
+ * @param loginId
+ * EcompUser ID to be updated.
+ * @param roles
+ * List of role attribute objects
+ * @throws PortalAPIException
+ * If any error occurs while processing the request.
+ */
+ public void pushUserRole(String loginId, List<EcompRole> roles) throws PortalAPIException;
+
+ /**
+ * Gets and returns a list of roles for the user with the specified loginId.
+ * If any error occurs, the method should throw PortalApiException with an
+ * appropriate message. The FW library will catch the exception and send an
+ * appropriate response to Portal.
+ *
+ * @param loginId
+ * @return List of model objects; empty if no roles are found.
+ * @throws PortalAPIException
+ * If any error occurs while processing the request; e.g., user
+ * not found.
+ */
+ public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException;
+
+ // Security Interface
+
+ /**
+ * Should return true if the call should be allowed and false if not.
+ * Currently Portal sends two headers of username and password in each
+ * request which the app should check. If match, return true; else return
+ * false. If any error occurs, the method should throw PortalApiException
+ * with an appropriate message. The FW library will catch the exception and
+ * send an appropriate response to Portal.
+ *
+ * @param request
+ * @return true if the request contains appropriate credentials, else false.
+ * @throws PortalAPIException
+ * If an unexpected error occurs while processing the request.
+ */
+ public boolean isAppAuthenticated(HttpServletRequest request) throws PortalAPIException;
+
+ /**
+ * Gets and returns the userId for the logged-in user based on the request.
+ * If any error occurs, the method should throw PortalApiException with an
+ * appropriate message. The FW library will catch the exception and send an
+ * appropriate response to Portal.
+ *
+ * @param request
+ * @return true if the request contains appropriate credentials, else false.
+ * @throws PortalAPIException
+ * If an unexpected error occurs while processing the request.
+ */
+ public String getUserId(HttpServletRequest request) throws PortalAPIException;
+
+}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java
index 0b55a965..b6e0150e 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalUebAPIService.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -19,6 +19,7 @@
*/
package org.openecomp.portalsdk.core.onboarding.crossapi;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
/**
*
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java
index f8d73acc..ad1eae8d 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIResponse.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java
new file mode 100644
index 00000000..02d35ae9
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java
@@ -0,0 +1,618 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.onboarding.crossapi;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
+import org.openecomp.portalsdk.core.onboarding.rest.RestWebServiceClient;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.openecomp.portalsdk.core.restful.domain.EcompRole;
+import org.openecomp.portalsdk.core.restful.domain.EcompUser;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * This servlet performs the functions described below. It listens on a path
+ * like "/api" (see {@link PortalApiConstants#API_PREFIX}). The servlet checks
+ * for authorized access and rejects unauthorized requests.
+ * <OL>
+ * <LI>Proxies user (i.e., browser) requests for web analytics. The GET method
+ * fetches javascript from the Portal and returns it. The POST method forwards
+ * data sent by the browser on to Portal. These requests are checked for a valid
+ * User UID in a header; these requests do NOT use the application
+ * username-password header.</LI>
+ * <LI>Responds to ECOMP Portal API requests to query and update user, role and
+ * user-role information. The servlet proxies all requests on to a local Java
+ * class that implements {@link IPortalRestAPIService}. These requests must have
+ * the application username-password header.</LI>
+ * </OL>
+ * This servlet will not start if the required portal.properties file is not
+ * found on the classpath.
+ */
+
+@WebServlet(urlPatterns = { PortalApiConstants.API_PREFIX + "/*" })
+public class PortalRestAPIProxy extends HttpServlet implements IPortalRestAPIService {
+ private static final long serialVersionUID = 1L;
+
+ private static final String contentTypeAppJson = "application/json";
+
+ private final Log logger = LogFactory.getLog(getClass());
+
+ /**
+ * Mapper for JSON to object etc.
+ */
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * Client-supplied class that implements our interface.
+ */
+ private static IPortalRestAPIService portalRestApiServiceImpl;
+
+ public PortalRestAPIProxy() {
+ // Ensure that any additional fields sent by the Portal
+ // will be ignored when creating objects.
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ }
+
+ @Override
+ public void init() throws ServletException {
+ String className = PortalApiProperties.getProperty(PortalApiConstants.PORTAL_API_IMPL_CLASS);
+ if (className == null)
+ throw new ServletException(
+ "init: Failed to find class name property " + PortalApiConstants.PORTAL_API_IMPL_CLASS);
+ try {
+ logger.debug("init: creating instance of class " + className);
+ Class<?> implClass = Class.forName(className);
+ portalRestApiServiceImpl = (IPortalRestAPIService) (implClass.getConstructor().newInstance());
+ } catch (Exception ex) {
+ throw new ServletException("init: Failed to find or instantiate class " + className, ex);
+ }
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+
+ if (portalRestApiServiceImpl == null) {
+ // Should never happen due to checks in init()
+ logger.error("doPost: no service class instance");
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ response.getWriter().write(buildJsonResponse(false, "Misconfigured - no instance of service class"));
+ return;
+ }
+ String requestUri = request.getRequestURI();
+ String responseJson = "";
+ String storeAnalyticsContextPath = "/storeAnalytics";
+ if (requestUri.endsWith(PortalApiConstants.API_PREFIX + storeAnalyticsContextPath)) {
+ String userId;
+ try {
+ userId = getUserId(request);
+ } catch (PortalAPIException e) {
+ logger.error("Issue with invoking getUserId implemenation !!! ", e);
+ throw new ServletException(e);
+ }
+ if (userId == null || userId.length() == 0) {
+ logger.debug("doPost: userId is null or empty");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ responseJson = buildJsonResponse(false, "Not authorized for " + storeAnalyticsContextPath);
+ } else {
+ // User ID obtained from request
+ try {
+ String credential = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
+ // for now lets also pass uebkey as user name and password
+ String requestBody = readRequestBody(request);
+ @SuppressWarnings("unchecked")
+ Map<String, String> bodyMap = mapper.readValue(requestBody, Map.class);
+ // add user ID
+ bodyMap.put("userid", userId);
+ requestBody = mapper.writeValueAsString(bodyMap);
+ responseJson = RestWebServiceClient.getInstance().postPortalContent(storeAnalyticsContextPath,
+ userId, credential, null, credential, credential, "application/json", requestBody);
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: postPortalContent returns " + responseJson);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception ex) {
+ logger.error("doPost: " + storeAnalyticsContextPath + " caught exception", ex);
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+ writeAndFlush(response, contentTypeAppJson, responseJson);
+ return;
+ } // post analytics
+
+ boolean secure = false;
+ try {
+ secure = isAppAuthenticated(request);
+ } catch (PortalAPIException ex) {
+ logger.error("doPost: isAppAuthenticated threw exception", ex);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ response.getWriter().write(buildJsonResponse(false, "Failed to authenticate request"));
+ return;
+ }
+ if (!secure) {
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: isAppAuthenticated answered false");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ writeAndFlush(response, contentTypeAppJson, buildJsonResponse(false, "Not authorized"));
+ return;
+ }
+
+ try {
+ String requestBody = readRequestBody(request);
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: URI = " + requestUri + ", payload = " + requestBody);
+
+ /*
+ * All APIs:
+ *
+ * 1. /user <-- save user
+ *
+ * 2. /user/{loginId} <-- edit user
+ *
+ * 3. /user/{loginId}/roles <-- save roles for user
+ */
+
+ // On success return the empty string.
+
+ if (requestUri.endsWith("/updateSessionTimeOuts")) {
+ if (updateSessionTimeOuts(requestBody)) {
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: updated session timeouts");
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ String msg = "Failed to update session time outs";
+ logger.error("doPost: " + msg);
+ responseJson = buildJsonResponse(false, msg);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ } else if (requestUri.endsWith("/timeoutSession")) {
+ String portalJSessionId = request.getParameter("portalJSessionId");
+ if (portalJSessionId == null) {
+ portalJSessionId = "";
+ }
+ if (timeoutSession(portalJSessionId)) {
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: timed out session");
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ String msg = "Failed to timeout session";
+ logger.error("doPost: " + msg);
+ responseJson = buildJsonResponse(false, msg);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ } else
+ // Example: /user <-- create user
+ if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/user")) {
+ try {
+ EcompUser user = mapper.readValue(requestBody, EcompUser.class);
+ pushUser(user);
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: pushUser: success");
+ responseJson = buildJsonResponse(true, null);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doPost: pushUser: caught exception", ex);
+ }
+ } else
+ // Example: /user/fi241c <-- edit user fi241c
+ if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !(requestUri.endsWith("/roles"))) {
+ String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
+ try {
+ EcompUser user = mapper.readValue(requestBody, EcompUser.class);
+ editUser(loginId, user);
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: editUser: success");
+ responseJson = buildJsonResponse(true, null);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doPost: editUser: caught exception", ex);
+ }
+ } else
+ // Example: /user/{loginId}/roles <-- save roles for user
+ if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
+ String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
+ requestUri.lastIndexOf('/'));
+ try {
+ TypeReference<List<EcompRole>> typeRef = new TypeReference<List<EcompRole>>() {
+ };
+ List<EcompRole> roles = mapper.readValue(requestBody, typeRef);
+ pushUserRole(loginId, roles);
+ if (logger.isDebugEnabled())
+ logger.debug("doPost: pushUserRole: success");
+ responseJson = buildJsonResponse(true, null);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doPost: pushUserRole: caught exception", ex);
+ }
+ } else {
+ String msg = "doPost: no match for request " + requestUri;
+ logger.warn(msg);
+ responseJson = buildJsonResponse(false, msg);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ }
+ } catch (Exception ex) {
+ logger.error("doPost: Failed to process request " + requestUri, ex);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ responseJson = buildJsonResponse(ex);
+ }
+
+ writeAndFlush(response, contentTypeAppJson, responseJson);
+
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+
+ if (portalRestApiServiceImpl == null) {
+ // Should never happen due to checks in init()
+ logger.error("doGet: no service class instance");
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ writeAndFlush(response, contentTypeAppJson,
+ buildJsonResponse(false, "Misconfigured - no instance of service class"));
+ return;
+ }
+
+ String requestUri = request.getRequestURI();
+ String responseString = "";
+ String contentType = contentTypeAppJson;
+
+ String webAnalyticsContextPath = "/analytics";
+ if (requestUri.endsWith(PortalApiConstants.API_PREFIX + webAnalyticsContextPath)) {
+ String userId;
+ try {
+ userId = getUserId(request);
+ } catch (PortalAPIException e) {
+ logger.error("Issue with invoking getUserId implemenation !!! ", e);
+ throw new ServletException(e);
+ }
+ if (userId == null || userId.length() == 0) {
+ logger.debug("doGet: userId is null or empty");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ responseString = buildJsonResponse(false, "Not authorized for " + webAnalyticsContextPath);
+ } else {
+ // User ID obtained from request
+ try {
+ String credential = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
+ // for now lets also pass uebkey as user name and password
+ contentType = "text/javascript";
+ responseString = RestWebServiceClient.getInstance().getPortalContent(webAnalyticsContextPath,
+ userId, credential, null, credential, credential);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: " + webAnalyticsContextPath + ": " + responseString);
+ response.setStatus(HttpServletResponse.SC_OK);
+ } catch (Exception ex) {
+ responseString = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doGet: " + webAnalyticsContextPath + " caught exception", ex);
+ }
+ }
+ writeAndFlush(response, contentType, responseString);
+ return;
+ }
+
+ boolean secure = false;
+ try {
+ secure = isAppAuthenticated(request);
+ } catch (PortalAPIException ex) {
+ logger.error("doGet: isAppAuthenticated threw exception", ex);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ writeAndFlush(response, contentTypeAppJson, buildJsonResponse(false, "Failed to authenticate request"));
+ return;
+ }
+
+ if (!secure) {
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: isAppAuthenticated answered false");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ writeAndFlush(response, contentTypeAppJson, buildJsonResponse(false, "Not authorized"));
+ return;
+ }
+
+ String responseJson = null;
+ try {
+ // Ignore any request body in a GET.
+ // String requestBody = readRequestBody(request);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: URI = " + requestUri);
+
+ /*
+ * 1. /roles <-- get roles
+ *
+ * 2. /user/{loginId} <-- get user
+ *
+ * 3. /users <-- get all users
+ *
+ * 4. /user/{loginId}/roles <-- get roles for user
+ */
+
+ if (requestUri.endsWith("/sessionTimeOuts")) {
+ responseJson = getSessionTimeOuts();
+ if (responseJson != null && responseJson.length() > 0) {
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: got session timeouts");
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else {
+ String msg = "Failed to get session time outs";
+ logger.error("doGet: " + msg);
+ responseJson = buildJsonResponse(false, msg);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ } else
+ // Example: /users <-- get all users
+ if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/users")) {
+ try {
+ List<EcompUser> users = getUsers();
+ responseJson = mapper.writeValueAsString(users);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: getUsers: " + responseJson);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doGet: getUsers: caught exception", ex);
+ }
+ } else
+ // Example: /roles <-- get all roles
+ if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/roles")) {
+ try {
+ List<EcompRole> roles = getAvailableRoles();
+ responseJson = mapper.writeValueAsString(roles);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: getAvailableRoles: " + responseJson);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doGet: getAvailableRoles: caught exception", ex);
+ }
+ } else
+ // Example: /user/fi241c <-- get user fi241c
+ if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !requestUri.endsWith("/roles")) {
+ String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
+ try {
+ EcompUser user = getUser(loginId);
+ responseJson = mapper.writeValueAsString(user);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: getUser: " + responseJson);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doGet: getUser: caught exception", ex);
+ }
+ }
+ // Example: /user/fi241c/roles <-- get roles for user fi241c
+ else if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
+ String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
+ requestUri.lastIndexOf('/'));
+ try {
+ List<EcompRole> roles = getUserRoles(loginId);
+ responseJson = mapper.writeValueAsString(roles);
+ if (logger.isDebugEnabled())
+ logger.debug("doGet: getUserRoles: " + responseJson);
+ } catch (Exception ex) {
+ responseJson = buildJsonResponse(ex);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ logger.error("doGet: getUserRoles: caught exception", ex);
+ }
+ } else {
+ logger.warn("doGet: no match found for request");
+ responseJson = buildJsonResponse(false, "No match for request");
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ }
+ } catch (Exception ex) {
+ logger.error("doGet: Failed to process request", ex);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ responseJson = buildJsonResponse(ex);
+ }
+ writeAndFlush(response, contentTypeAppJson, responseJson);
+ }
+
+ public String getSessionTimeOuts() throws Exception {
+ return PortalTimeoutHandler.gatherSessionExtensions();
+ }
+
+ public boolean timeoutSession(String portalJSessionId) throws Exception {
+ return PortalTimeoutHandler.invalidateSession(portalJSessionId);
+ }
+
+ public boolean updateSessionTimeOuts(String sessionMap) throws Exception {
+ return PortalTimeoutHandler.updateSessionExtensions(sessionMap);
+ }
+
+ @Override
+ public void pushUser(EcompUser user) throws PortalAPIException {
+ portalRestApiServiceImpl.pushUser(user);
+ }
+
+ @Override
+ public void editUser(String loginId, EcompUser user) throws PortalAPIException {
+ portalRestApiServiceImpl.editUser(loginId, user);
+ }
+
+ @Override
+ public EcompUser getUser(String loginId) throws PortalAPIException {
+ return portalRestApiServiceImpl.getUser(loginId);
+ }
+
+ @Override
+ public List<EcompUser> getUsers() throws PortalAPIException {
+ return portalRestApiServiceImpl.getUsers();
+ }
+
+ @Override
+ public List<EcompRole> getAvailableRoles() throws PortalAPIException {
+ return portalRestApiServiceImpl.getAvailableRoles();
+ }
+
+ @Override
+ public void pushUserRole(String loginId, List<EcompRole> roles) throws PortalAPIException {
+ portalRestApiServiceImpl.pushUserRole(loginId, roles);
+ }
+
+ @Override
+ public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException {
+ return portalRestApiServiceImpl.getUserRoles(loginId);
+ }
+
+ @Override
+ public boolean isAppAuthenticated(HttpServletRequest request) throws PortalAPIException {
+ return portalRestApiServiceImpl.isAppAuthenticated(request);
+ }
+
+ /**
+ * Sets the content type and writes the response.
+ *
+ * @param response
+ * @param contentType
+ * @param responseBody
+ * @throws IOException
+ */
+ private void writeAndFlush(HttpServletResponse response, String contentType, String responseBody)
+ throws IOException {
+ response.setContentType(contentType);
+ PrintWriter out = response.getWriter();
+ out.print(responseBody);
+ out.flush();
+ }
+
+ /**
+ * Reads the request body and closes the input stream.
+ *
+ * @param request
+ * @return String read from the request, the empty string if nothing is
+ * read.
+ * @throws IOException
+ */
+ private static String readRequestBody(HttpServletRequest request) throws IOException {
+
+ String body = null;
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+ try {
+ InputStream inputStream = request.getInputStream();
+ if (inputStream != null) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[1024];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ } else {
+ stringBuilder.append("");
+ }
+ } finally {
+ if (bufferedReader != null) {
+ try {
+ bufferedReader.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+ }
+ body = stringBuilder.toString();
+ return body;
+ }
+
+ /**
+ * Builds JSON object with status + message response body.
+ *
+ * @param success
+ * True to indicate success, false to signal failure.
+ * @param msg
+ * Message to include in the response object; ignored if null.
+ * @return
+ *
+ * <pre>
+ * { "status" : "ok" (or "error"), "message": "some explanation" }
+ * </pre>
+ */
+ private String buildJsonResponse(boolean success, String msg) {
+ PortalAPIResponse response = new PortalAPIResponse(success, msg);
+ String json = null;
+ try {
+ json = mapper.writeValueAsString(response);
+ } catch (JsonProcessingException ex) {
+ // Truly should never, ever happen
+ json = "{ \"status\": \"error\",\"message\":\"" + ex.toString() + "\" }";
+ }
+ return json;
+ }
+
+ /**
+ * Builds JSON object with status of error and message containing stack
+ * trace for the specified throwable.
+ *
+ * @param t
+ * Throwable with stack trace to use as message
+ *
+ * @return
+ *
+ * <pre>
+ * { "status" : "error", "message": "some-big-stacktrace" }
+ * </pre>
+ */
+ private String buildJsonResponse(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ return buildJsonResponse(false, sw.toString());
+ }
+
+ @Override
+ public String getUserId(HttpServletRequest request) throws PortalAPIException {
+ return portalRestApiServiceImpl.getUserId(request);
+ }
+
+ public static IPortalRestAPIService getPortalRestApiServiceImpl() {
+ return portalRestApiServiceImpl;
+ }
+
+ public static void setPortalRestApiServiceImpl(IPortalRestAPIService portalRestApiServiceImpl) {
+ PortalRestAPIProxy.portalRestApiServiceImpl = portalRestApiServiceImpl;
+ }
+
+}
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunicationService.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunicationService.java
new file mode 100644
index 00000000..be3a7d54
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunicationService.java
@@ -0,0 +1,161 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.onboarding.crossapi;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class SessionCommunicationService {
+
+ protected static final Log logger = LogFactory.getLog(SessionCommunicationService.class);
+
+ /**
+ * Calls the ECOMP Portal to retrieve the session slot check interval.
+ *
+ * @param ecompRestURL
+ * @param userName
+ * application user name used for authentication at Portal
+ * @param password
+ * application password used for authentication at Portal
+ * @param uebKey
+ * application UEB key (basically application ID) used for
+ * authentication at Portal
+ * @return Content read from the remote REST endpoint
+ */
+ public static String getSessionSlotCheckInterval(String ecompRestURL, String userName, String password,
+ String uebKey) {
+ try {
+ String url = ecompRestURL + "/getSessionSlotCheckInterval";
+
+ URL obj = new URL(url);
+
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+
+ // optional default is GET
+ con.setRequestMethod("GET");
+ con.setConnectTimeout(3000);
+ con.setReadTimeout(8000);
+ // add request header
+ con.setRequestProperty("username", userName);
+ con.setRequestProperty("password", password);
+ con.setRequestProperty("uebkey", uebKey);
+
+ int responseCode = con.getResponseCode();
+ if (logger.isDebugEnabled()) {
+ logger.debug("getSessionSlotCheckInterval: Sending 'GET' request to URL : " + url);
+ logger.debug("getSessionSlotCheckInterval: Response Code : " + responseCode);
+ }
+
+ StringBuffer response = new StringBuffer();
+
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
+ String inputLine;
+ while ((inputLine = in.readLine()) != null)
+ response.append(inputLine);
+ } finally {
+ in.close();
+ }
+ return response.toString();
+ } catch (Exception e) {
+ logger.error("getSessionSlotCheckInterval: failed to fetch the session slot check", e);
+ return null;
+ }
+
+ }
+
+ /**
+ * Calls the ECOMP Portal to request an extension of the current session.
+ *
+ * @param ecompRestURL
+ * @param userName
+ * application user name used for authentication at Portal
+ * @param password
+ * application password used for authentication at Portal
+ * @param uebKey
+ * application UEB key (basically application ID) used for
+ * authentication at Portal
+ * @param sessionTimeoutMap
+ * @return Content read from the remote REST endpoint
+ * @throws Exception
+ */
+ public static String requestPortalSessionTimeoutExtension(String ecompRestURL, String userName, String password,
+ String uebKey, String sessionTimeoutMap) throws Exception {
+
+ try {
+
+ String url = ecompRestURL + "/extendSessionTimeOuts";
+ // String decreptedPwd =
+ // app.appPassword;//CipherUtil.decrypt(encriptedPwdDB,
+ // SystemProperties.getProperty(SystemProperties.SECRET_KEY));
+
+ URL obj = new URL(url);
+
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+
+ con.setRequestMethod("POST");
+ con.setConnectTimeout(3000);
+ con.setReadTimeout(15000);
+
+ // add request header
+ con.setRequestProperty("username", userName);
+ con.setRequestProperty("password", password);
+ con.setRequestProperty("uebkey", uebKey);
+ con.setRequestProperty("sessionMap", sessionTimeoutMap);
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.getOutputStream().write(sessionTimeoutMap.getBytes());
+ con.getOutputStream().flush();
+ con.getOutputStream().close();
+
+ // con.set
+
+ int responseCode = con.getResponseCode();
+ if (logger.isDebugEnabled()) {
+ logger.debug("requestPortalSessionTimeoutExtension: Sending 'GET' request to URL : " + url);
+ logger.debug("requestPortalSessionTimeoutExtension: Response Code : " + responseCode);
+ }
+
+ StringBuffer response = new StringBuffer();
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ }
+ } finally {
+ in.close();
+ }
+ return response.toString();
+ } catch (Exception e) {
+ logger.error("requestPortalSessionTimeoutExtension: failed to request Portal to extend time out ", e);
+ return null;
+ }
+
+ }
+
+}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIException.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/exception/PortalAPIException.java
index 8a4c9e4e..ea9b1c66 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalAPIException.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/exception/PortalAPIException.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,11 +17,8 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.exception;
-/**
- * @author Ikram Ikramullah
- */
public class PortalAPIException extends Exception{
private static final long serialVersionUID = 4854048794984375707L;
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutBindingListener.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutBindingListener.java
index 906b7e88..4a6b43bc 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutBindingListener.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutBindingListener.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.listener;
import java.io.Serializable;
@@ -27,6 +27,7 @@ import javax.servlet.http.HttpSessionBindingListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
public class PortalTimeoutBindingListener implements HttpSessionBindingListener, Serializable {
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutHandler.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutHandler.java
index 09166794..90a9121c 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutHandler.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/PortalTimeoutHandler.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.listener;
import java.util.Calendar;
import java.util.Hashtable;
@@ -28,6 +28,9 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.crossapi.SessionCommunicationService;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.restful.domain.PortalTimeoutVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
@@ -40,8 +43,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
public class PortalTimeoutHandler {
protected static final SessionCommInf sessionComm = new SessionComm();
-
-
public interface SessionCommInf {
public Integer fetchSessionSlotCheckInterval(String... params) throws Exception;
@@ -57,8 +58,9 @@ public class PortalTimeoutHandler {
String pwd = params[2];
String uebKey = params[3];
- String sessionSlot = SessionCommunication.getSessionSlotCheckInterval(ecompRestURL, userName, pwd, uebKey);
- if(sessionSlot == null)
+ String sessionSlot = SessionCommunicationService.getSessionSlotCheckInterval(ecompRestURL, userName, pwd,
+ uebKey);
+ if (sessionSlot == null)
return null;
return Integer.parseInt(sessionSlot);
}
@@ -71,12 +73,11 @@ public class PortalTimeoutHandler {
String uebKey = params[3];
String sessionTimeoutMap = params[4];
- SessionCommunication.requestPortalSessionTimeoutExtension(ecompRestURL, userName, pwd, uebKey, sessionTimeoutMap);
+ SessionCommunicationService.requestPortalSessionTimeoutExtension(ecompRestURL, userName, pwd, uebKey,
+ sessionTimeoutMap);
}
}
-
-
public static final Map<String, HttpSession> sessionMap = new Hashtable<String, HttpSession>();
public static final Integer repeatInterval = 15 * 60; // 15 minutes
protected static final Log logger = LogFactory.getLog(PortalTimeoutHandler.class);
@@ -104,14 +105,15 @@ public class PortalTimeoutHandler {
// this key is a combination of portal jsession id and app session id
String jSessionKey = jSessionKey(jSessionId, portalJSessionId);
Object jSessionKeySessionVal = session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID);
-
- // do not reset the attributes if the same values have already been set
- // because that will cause PortalTimeoutBindingListener to unbound the value from map
- if(jSessionKeySessionVal != null && jSessionKeySessionVal.equals(jSessionKey)) {
+
+ // do not reset the attributes if the same values have already been set
+ // because that will cause PortalTimeoutBindingListener to unbound the
+ // value from map
+ if (jSessionKeySessionVal != null && jSessionKeySessionVal.equals(jSessionKey)) {
logger.debug(" Session Values already exist in te map for sessionKey " + jSessionKey);
return;
}
-
+
session.setAttribute(PortalApiConstants.PORTAL_JSESSION_ID, jSessionKey);
// session binding listener will add this value to the static map
@@ -144,7 +146,7 @@ public class PortalTimeoutHandler {
session.removeAttribute(PortalApiConstants.PORTAL_JSESSION_BIND);
// sessionMap.remove((String)session.getAttribute(PortalApiConstants.PORTAL_JSESSION_ID));
} catch (Exception e) {
- logger.error("Error while destroy user session" + e.getMessage());
+ logger.error("sessionDestroyed failed", e);
}
}
@@ -165,7 +167,7 @@ public class PortalTimeoutHandler {
result = true;
}
} catch (Exception e) {
- logger.error("Session Management: Error when invalidating session", e);
+ logger.error("invalidateSession failed", e);
}
}
return result;
@@ -208,7 +210,7 @@ public class PortalTimeoutHandler {
jsonMap = mapper.writeValueAsString(sessionTimeoutMap);
} catch (Exception e) {
- logger.error("Session Management: Error during JsonSessionTimout conversion", e);
+ logger.error("gatherSessionExtensions failed", e);
}
}
@@ -235,7 +237,7 @@ public class PortalTimeoutHandler {
};
sessionTimeoutMap = mapper.readValue(sessionTimeoutMapStr, typeRef);
} catch (Exception e) {
- logger.error("Session Management:error when try to parse the sessionTimeoutMap from portal");
+ logger.error("updateSessionExtensions failed to parse the sessionTimeoutMap from portal", e);
return false;
}
@@ -264,7 +266,7 @@ public class PortalTimeoutHandler {
// (int)(maxTimeoutTimeMilliSec/1000));
}
} catch (Exception e) {
- logger.error("Session Management: error while updating the sessionTimeout" + e.getMessage());
+ logger.error("updateSessionExtensions failed to update session timeouts", e);
// Signal a problem if any one of them fails
result = false;
}
@@ -282,8 +284,8 @@ public class PortalTimeoutHandler {
* @param ecompRestURL
* @param _sessionComm
*/
- public static void handleSessionUpdatesNative(HttpServletRequest request, String userName, String pwd, String uebKey,
- String ecompRestURL, SessionCommInf _sessionComm) {
+ public static void handleSessionUpdatesNative(HttpServletRequest request, String userName, String pwd,
+ String uebKey, String ecompRestURL, SessionCommInf _sessionComm) {
if (_sessionComm == null) {
_sessionComm = sessionComm;
@@ -291,7 +293,7 @@ public class PortalTimeoutHandler {
try {
synchronizeSessionForLastMinuteRequests(request, ecompRestURL, userName, pwd, uebKey, _sessionComm);
} catch (Exception e) {
- logger.error(e);
+ logger.error("handleSesionUpdatesNative failed", e);
}
resetSessionMaxIdleTimeOut(request);
}
@@ -308,7 +310,8 @@ public class PortalTimeoutHandler {
* @throws Exception
*/
public static void synchronizeSessionForLastMinuteRequests(HttpServletRequest request, String ecompRestURL,
- String userName, String pwd, String uebKey, SessionCommInf _sessionComm) throws JsonProcessingException, Exception {
+ String userName, String pwd, String uebKey, SessionCommInf _sessionComm)
+ throws JsonProcessingException, Exception {
HttpSession session = request.getSession(false);
if (session == null)
@@ -366,14 +369,12 @@ public class PortalTimeoutHandler {
HttpSession session = request.getSession(false);
if (session == null)
return;
-
final Object maxIdleAttribute = session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME);
if (maxIdleAttribute != null) {
session.setMaxInactiveInterval(Integer.parseInt(maxIdleAttribute.toString()));
}
-
} catch (Exception e) {
- logger.error("Could not reset the session timeout", e);
+ logger.error("resetSessionMaxIdleTimeout failed", e);
}
}
@@ -416,4 +417,4 @@ public class PortalTimeoutHandler {
return jSessionKey.split("-")[1];
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserContextListener.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserContextListener.java
index ea346f1e..d4793d27 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserContextListener.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserContextListener.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.listener;
import java.util.HashMap;
@@ -27,6 +27,8 @@ import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+
@WebListener
public class UserContextListener implements ServletContextListener{
@@ -49,4 +51,4 @@ public class UserContextListener implements ServletContextListener{
// activeUsers HashMap. Then put code in the contextInitialized
// method that reads and reloads it if it exists...
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserSessionListener.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserSessionListener.java
index b468851d..88934282 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/UserSessionListener.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/listener/UserSessionListener.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.listener;
import java.util.HashMap;
import java.util.Hashtable;
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpSessionListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
/**
* Listens to session-create and session-destroy events.
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java
index 9dce0221..b4ca4755 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FavoritesClient.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -48,4 +48,4 @@ public class FavoritesClient {
return RestWebServiceClient.getInstance().getPortalContent("/getFavorites", userId, appName, requestId, appUserName,
appPassword);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java
index 8e12b33b..a3a320eb 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/FunctionalMenuClient.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -51,4 +51,4 @@ public class FunctionalMenuClient {
requestId, appUserName, appPassword);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java
new file mode 100644
index 00000000..f01590d4
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java
@@ -0,0 +1,342 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.onboarding.rest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
+import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
+
+/**
+ * Simple REST client for GET-ing content from and POST-ing content to the
+ * Portal application.
+ */
+public class RestWebServiceClient {
+
+ private final Log logger = LogFactory.getLog(RestWebServiceClient.class);
+
+ /**
+ * Singleton instance
+ */
+ private static RestWebServiceClient instance = null;
+
+ /**
+ * Constructor is private. Clients should obtain an instance via
+ * getInstance().
+ */
+ private RestWebServiceClient() {
+ }
+
+ /**
+ * Gets the static instance of RestWebServiceClient; creates it if
+ * necessary. Synchronized to be thread safe.
+ *
+ * @return Static instance of RestWebServiceClient.
+ */
+ public static synchronized RestWebServiceClient getInstance() {
+ if (instance == null)
+ instance = new RestWebServiceClient();
+ return instance;
+ }
+
+ /**
+ * Convenience method that fetches the URL for the Portal REST API endpoint
+ * and the application UEB key, then calls
+ * {@link #get(String, String, String, String, String, String, String)} to
+ * access the Portal's REST endpoint.
+ *
+ * @param restPath
+ * Partial path of the endpoint; e.g., "/specialRestService"
+ * @param userId
+ * userId for the user originating the request
+ * @param appName
+ * Application Name for logging.
+ * @param requestId
+ * 128-bit UUID value to uniquely identify the transaction.
+ * @param appUserName
+ * REST API user name for Portal to authenticate the request
+ * @param appPassword
+ * REST API password (in the clear, not encrypted) for Portal to
+ * authenticate the request
+ * @return Content from REST endpoint
+ * @throws Exception
+ * on any failure
+ */
+ public String getPortalContent(String restPath, String userId, String appName, String requestId, String appUserName,
+ String appPassword) throws Exception {
+ String restURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
+ if (restURL == null) {
+ // should never happen
+ String msg = "getPortalContent: failed to get property " + PortalApiConstants.ECOMP_REST_URL;
+ logger.error(msg);
+ throw new Exception(msg);
+ }
+ String appUebKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
+ if (appUebKey == null) {
+ // should never happen
+ String msg = "getPortalContent: failed to get property " + PortalApiConstants.UEB_APP_KEY;
+ logger.error(msg);
+ throw new Exception(msg);
+ }
+ final String restEndpointUrl = restURL + restPath;
+ return get(restEndpointUrl, userId, appName, requestId, appUebKey, appUserName, appPassword);
+
+ }
+
+ /**
+ * Makes a call to a Portal REST API using the specified URL and parameters.
+ *
+ * @param url
+ * Complete URL of the REST endpoint.
+ * @param loginId
+ * User that it should be fetching the data
+ * @param appName
+ * Application name for logging; if null or empty, defaulted to
+ * Unknown.
+ * @param requestId
+ * 128-bit UUID value to uniquely identify the transaction; if
+ * null or empty, one is generated.
+ * @param appUebKey
+ * Unique key for the application, used by Portal to authenticate
+ * the request
+ * @param appUserName
+ * REST API user name, used by Portal to authenticate the request
+ * @param appPassword
+ * REST API password, used by Portal to authenticate the request
+ * @return Content from REST endpoint
+ * @throws Exception
+ * On any failure; e.g., unknown host.
+ */
+ public String get(String url, String loginId, String appName, String requestId, String appUebKey,
+ String appUserName, String appPassword) throws Exception {
+
+ logger.debug("RestWebServiceClient.get (" + url + ") operation is started.");
+
+ if (appName == null || appName.trim().length() == 0)
+ appName = "Unknown";
+ if (requestId == null || requestId.trim().length() == 0)
+ requestId = UUID.randomUUID().toString();
+
+ URL obj = new URL(url);
+ // Create the connection object
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+ con.setRequestMethod("GET");
+ con.setConnectTimeout(3000);
+ con.setReadTimeout(8000);
+
+ // add request header
+ con.setRequestProperty("uebkey", appUebKey);
+ con.setRequestProperty("username", appUserName);
+ con.setRequestProperty("password", appPassword);
+ con.setRequestProperty("LoginId", loginId);
+ con.setRequestProperty("user-agent", appName);
+ con.setRequestProperty("X-ECOMP-RequestID", requestId);
+
+ int responseCode = con.getResponseCode();
+ logger.debug("get: received response code '" + responseCode + "' while getting the '" + url + "' for user: "
+ + loginId);
+
+ StringBuffer sb = new StringBuffer();
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
+ String inputLine = null;
+ while ((inputLine = in.readLine()) != null)
+ sb.append(inputLine);
+ } finally {
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException ex) {
+ logger.error("get: failed to close reader", ex);
+ }
+ }
+
+ final String response = sb.toString();
+ if (logger.isDebugEnabled())
+ logger.debug("get: url " + url + " yielded " + response);
+ return response;
+ }
+
+ /**
+ * Convenience method that fetches the URL for the Portal REST API endpoint
+ * and the application UEB key, then calls
+ * {@link #post(String, String, String, String, String, String, String, String, String)}
+ * to access the Portal's REST endpoint.
+ *
+ * @param restPath
+ * Partial path of the endpoint; e.g., "/specialRestService"
+ * @param userId
+ * ID for the user originating the request
+ * @param appName
+ * Application Name for logging.
+ * @param requestId
+ * 128-bit UUID value to uniquely identify the transaction.
+ * @param appUserName
+ * REST API user name for Portal to authenticate the request;
+ * ignored if null
+ * @param appPassword
+ * REST API password (in the clear, not encrypted) for Portal to
+ * authenticate the request; ignored if null
+ * @param contentType
+ * content type for header
+ * @param content
+ * String to post
+ * @return Content from REST endpoint
+ * @throws Exception
+ * on any failure
+ */
+ public String postPortalContent(String restPath, String userId, String appName, String requestId,
+ String appUserName, String appPassword, String contentType, String content) throws Exception {
+ String restURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
+ if (restURL == null) {
+ // should never happen
+ String msg = "getPortalContent: failed to get property " + PortalApiConstants.ECOMP_REST_URL;
+ logger.error(msg);
+ throw new Exception(msg);
+ }
+ String appUebKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
+ if (appUebKey == null) {
+ // should never happen
+ String msg = "getPortalContent: failed to get property " + PortalApiConstants.UEB_APP_KEY;
+ logger.error(msg);
+ throw new Exception(msg);
+ }
+ final String separator = restURL.endsWith("/") || restPath.startsWith("/") ? "" : "/";
+ final String restEndpointUrl = restURL + separator + restPath;
+ return post(restEndpointUrl, userId, appName, requestId, appUebKey, appUserName, appPassword, contentType,
+ content);
+ }
+
+ /**
+ * Makes a POST call to a Portal REST API using the specified URL and
+ * parameters.
+ *
+ * @param url
+ * Complete URL of the REST endpoint.
+ * @param loginId
+ * User who is fetching the data
+ * @param appName
+ * Application name for logging; if null or empty, defaulted to
+ * Unknown.
+ * @param requestId
+ * 128-bit UUID value to uniquely identify the transaction; if
+ * null or empty, one is generated.
+ * @param appUebKey
+ * Unique key for the application, used by Portal to authenticate
+ * the request
+ * @param appUserName
+ * REST API user name used by Portal to authenticate the request;
+ * ignored if null
+ * @param appPassword
+ * REST API password used by Portal to authenticate the request;
+ * ignored if null
+ * @param contentType
+ * MIME header
+ * @param content
+ * Content to POST
+ * @return Any content read from the endpoint
+ * @throws Exception
+ * On any error
+ */
+ public String post(String url, String loginId, String appName, String requestId, String appUebKey,
+ String appUserName, String appPassword, String contentType, String content) throws Exception {
+
+ if (logger.isDebugEnabled())
+ logger.debug("RestWebServiceClient.post to URL " + url);
+ if (appName == null || appName.trim().length() == 0)
+ appName = "Unknown";
+ if (requestId == null || requestId.trim().length() == 0)
+ requestId = UUID.randomUUID().toString();
+
+ URL obj = new URL(url);
+ // Create the connection object
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+ con.setRequestMethod("POST");
+ con.setConnectTimeout(3000);
+ con.setReadTimeout(15000);
+
+ // add request header
+ con.setRequestProperty("uebkey", appUebKey);
+ if (appUserName != null)
+ con.setRequestProperty("username", appUserName);
+ if (appPassword != null)
+ con.setRequestProperty("password", appPassword);
+ con.setRequestProperty("LoginId", loginId);
+ con.setRequestProperty("user-agent", appName);
+ con.setRequestProperty("X-ECOMP-RequestID", requestId);
+ con.setRequestProperty("Content-Type", contentType);
+
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.getOutputStream().write(content.getBytes());
+ con.getOutputStream().flush();
+ con.getOutputStream().close();
+
+ int responseCode = con.getResponseCode();
+ logger.debug("Response Code : " + responseCode);
+
+ StringBuffer sb = new StringBuffer();
+ InputStreamReader in = null;
+ char[] buf = new char[8196];
+ int bytes;
+ try {
+ in = new InputStreamReader(con.getInputStream(), "UTF-8");
+ while ((bytes = in.read(buf)) > 0)
+ sb.append(new String(buf, 0, bytes));
+ } finally {
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException ex) {
+ logger.warn("get: failed to close reader", ex);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Basic unit test for the client to call Portal app on localhost.
+ *
+ * @param args
+ * Ignored
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+ RestWebServiceClient client = RestWebServiceClient.getInstance();
+ final String getUrl = "http://www.ecomp.openecomp.org:8080/ecompportal/auxapi/analytics";
+ String get = client.get(getUrl, "userId", "appName", null, "appUebKey", "appUserName", "appPassword");
+ System.out.println("Get result:\n" + get);
+ final String postUrl = "http://www.ecomp.openecomp.org:8080/ecompportal/auxapi/storeAnalytics";
+ final String content = " { " + " \"action\" : \"test1\", " + " \"page\" : \"test2\", "
+ + " \"function\" : \"test3\", " + " \"userid\" : \"ab1234\" " + "}";
+ String post = client.post(postUrl, "userId", "appName", null, "appUebKey", "appUserName", "appPassword",
+ "application/json", content);
+ System.out.println("Post result:\n" + post);
+ }
+}
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/CipherUtil.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/CipherUtil.java
new file mode 100644
index 00000000..e376cd4c
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/CipherUtil.java
@@ -0,0 +1,125 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+package org.openecomp.portalsdk.core.onboarding.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+public class CipherUtil {
+
+ private final static String key = "AGLDdG4D04BKm2IxIWEr8o==!";
+
+ /**
+ * @param plainText
+ * @param secretKey
+ * @return encrypted version of plain text.
+ * @throws Exception
+ */
+ public static String encrypt(String plainText, String secretKey) throws Exception{
+ byte[] rawKey;
+ String encryptedString;
+ SecretKeySpec sKeySpec;
+ byte[] encryptText = plainText.getBytes("UTF-8");
+ Cipher cipher;
+ rawKey = Base64.decodeBase64(secretKey);
+ sKeySpec = new SecretKeySpec(rawKey, "AES");
+ cipher = Cipher.getInstance("AES");
+ cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
+ encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
+
+ return encryptedString;
+ }
+
+ /**
+ *
+ * @param plainText
+ * @return Encrypted Text
+ * @throws Exception
+ */
+ public static String encrypt(String plainText) throws Exception
+ {
+ return CipherUtil.encrypt(plainText,key);
+ }
+
+ /**
+ * @param encryptedText
+ * @param secretKey
+ * @return plain text version of encrypted text
+ * @throws Exception
+ */
+ public static String decrypt(String encryptedText, String secretKey) throws Exception {
+ Cipher cipher;
+ String encryptedString;
+ byte[] encryptText = null;
+ byte[] rawKey;
+ SecretKeySpec sKeySpec;
+
+ rawKey = Base64.decodeBase64(secretKey);
+ sKeySpec = new SecretKeySpec(rawKey, "AES");
+ encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8"));
+ cipher = Cipher.getInstance("AES");
+ cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
+ encryptedString = new String(cipher.doFinal(encryptText));
+
+ return encryptedString;
+ }
+
+ /**
+ * @param encryptedText
+ * @return Decrypted Text
+ * @throws Exception
+ */
+ public static String decrypt(String encryptedText) throws Exception
+ {
+ return CipherUtil.decrypt(encryptedText,key);
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ String password = "Welcome123";
+ String encrypted;
+ String decrypted;
+
+ if (args.length != 2) {
+ System.out.println("Default password testing... ");
+ System.out.println("Plain password: " + password);
+ encrypted = encrypt(password);
+ System.out.println("Encrypted password: " + encrypted);
+ decrypted = decrypt(encrypted);
+ System.out.println("Decrypted password: " + decrypted);
+ } else {
+ String whatToDo = args[0];
+ if (whatToDo.equalsIgnoreCase("d")) {
+ encrypted = args[1];
+ System.out.println("Encrypted Text: " + encrypted);
+ decrypted = decrypt(encrypted);
+ System.out.println("Decrypted Text: " + decrypted);
+ } else {
+ decrypted = args[1];
+ System.out.println("Plain Text: " + decrypted);
+ encrypted = encrypt(decrypted);
+ System.out.println("Encrypted Text" + encrypted);
+ }
+ }
+ }
+}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiConstants.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiConstants.java
index 667ad289..e706b7ec 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiConstants.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiConstants.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,10 +17,10 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.util;
public interface PortalApiConstants {
- public static final String API_PREFIX = "/api";
+ public static final String API_PREFIX = "/api/v2";
public static final String PORTAL_JSESSION_ID = "PORTAL_JSESSION_ID";
public static final String PORTAL_JSESSION_BIND = "PORTAL_JSESSION_BIND";
public static final String ACTIVE_USERS_NAME = "activeUsers";
@@ -37,6 +37,8 @@ public interface PortalApiConstants {
public static final String PORTAL_API_IMPL_CLASS = "portal.api.impl.class";
public static final String ECOMP_REDIRECT_URL = "ecomp_redirect_url";
public static final String ECOMP_REST_URL = "ecomp_rest_url";
+ public static final String CSP_COOKIE_NAME = "csp_cookie_name";
+ public static final String CSP_GATE_KEEPER_PROD_KEY = "csp_gate_keeper_prod_key";
// UEB related
public static final String UEB_URL_LIST = "ueb_url_list"; // In properties file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiProperties.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiProperties.java
index b9853a9a..93572ee9 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalApiProperties.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/PortalApiProperties.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.onboarding.util;
import java.io.IOException;
import java.io.InputStream;
@@ -49,7 +49,8 @@ public class PortalApiProperties {
}
/**
- * Gets the property value for the specified key.
+ * Gets the property value for the specified key. If a value is found,
+ * leading and trailing space is trimmed.
*
* @param property
* @return Value for the named property; null if the property file was not
@@ -69,20 +70,23 @@ public class PortalApiProperties {
}
}
}
- return properties.getProperty(property);
+ String value = properties.getProperty(property);
+ if (value != null)
+ value = value.trim();
+ return value;
}
/**
* Reads properties from a portal.properties file on the classpath.
*
- * Clients DO NOT need to call this method. Clients MAY call this method to
+ * Clients do NOT need to call this method. Clients MAY call this method to
* test whether the properties file can be loaded successfully.
*
* @return True if properties were successfully loaded, else false.
* @throws IOException
*/
public static boolean initialize() throws IOException {
- if (properties != null)
+ if (properties != null)
return true;
InputStream in = PortalApiProperties.class.getClassLoader().getResourceAsStream(propertyFileName);
if (in == null)
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOFilter.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOFilter.java
new file mode 100644
index 00000000..1d8a9620
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOFilter.java
@@ -0,0 +1,75 @@
+/* ================================================================================
+ * ECOMP Portal SDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ *
+ */
+
+package org.openecomp.portalsdk.core.onboarding.util;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openecomp.portalsdk.core.onboarding.crossapi.PortalRestAPIProxy;
+import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException;
+
+public class SSOFilter implements Filter {
+
+ private final Log logger = LogFactory.getLog(getClass());
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws java.io.IOException, ServletException {
+
+ try {
+ if (PortalRestAPIProxy.getPortalRestApiServiceImpl().getUserId((HttpServletRequest) request) == null) {
+ String redirectURL = SSOUtil.getECOMPSSORedirectURL(((HttpServletRequest) request),
+ ((HttpServletResponse) response),
+ (((HttpServletRequest) request).getRequestURI()
+ .substring(((HttpServletRequest) request).getContextPath().length() + 1)
+ + (((HttpServletRequest) request).getQueryString() != null
+ ? ("?" + ((HttpServletRequest) request).getQueryString()) : "")));
+
+ ((HttpServletResponse) response).sendRedirect(redirectURL);
+
+ } else {
+ // Pass request back down the filter chain
+ chain.doFilter(request, response);
+
+ }
+ } catch (PortalAPIException e) {
+ logger.error("Issue calling getUserId method ");
+ throw new ServletException(e);
+ }
+
+ }
+
+ public void destroy() {
+
+ }
+
+ public void init(FilterConfig arg0) throws ServletException {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOUtil.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOUtil.java
new file mode 100644
index 00000000..67ac567d
--- /dev/null
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/onboarding/util/SSOUtil.java
@@ -0,0 +1,45 @@
+package org.openecomp.portalsdk.core.onboarding.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class SSOUtil {
+
+ private static final Log logger = LogFactory.getLog(SSOUtil.class);
+
+ /**
+ * Constructs a path for this server, this app's context, etc.
+ *
+ * @param request
+ * @param response
+ * @param forwardPath
+ * @return
+ */
+ public static String getECOMPSSORedirectURL(HttpServletRequest request, HttpServletResponse response,
+ String forwardPath) {
+ String appURL = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":"
+ + request.getServerPort() + request.getContextPath() + "/" + forwardPath;
+ String encodedAppURL = null;
+ try {
+ encodedAppURL = URLEncoder.encode(appURL, "UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ logger.error("getECOMPSSORedirectURL: Failed to encode app URL "
+ + appURL);
+ }
+ String portalURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
+ if (portalURL == null || portalURL.length() == 0) {
+ logger.error("getECOMPSSORedirectURL: Failed to get property " +
+ PortalApiConstants.ECOMP_REDIRECT_URL);
+ return null;
+ }
+ String redirectURL = portalURL + "?redirectUrl=" + encodedAppURL;
+ return redirectURL;
+ }
+
+}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java
index a65d16f5..28b74a86 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompRole.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -84,4 +84,4 @@ public class EcompRole implements Comparable<EcompRole>{
return this.id.compareTo(o.id);
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java
index 732878e1..dde16df8 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/EcompUser.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutVO.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/PortalTimeoutVO.java
index af6eab8a..a8e100e5 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalTimeoutVO.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/PortalTimeoutVO.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -17,7 +17,7 @@
* limitations under the License.
* ================================================================================
*/
-package org.openecomp.portalsdk.core.onboarding.crossapi;
+package org.openecomp.portalsdk.core.restful.domain;
public class PortalTimeoutVO implements Comparable<PortalTimeoutVO>{
@@ -60,4 +60,4 @@ public class PortalTimeoutVO implements Comparable<PortalTimeoutVO>{
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java
index 4eeb12f4..80ed4859 100644
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java
+++ b/ecomp-sdk/epsdk-fw/src/main/java/org/openecomp/portalsdk/core/restful/domain/SharedContext.java
@@ -1,6 +1,6 @@
/*-
* ================================================================================
- * eCOMP Portal SDK
+ * ECOMP Portal SDK
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property
* ================================================================================
@@ -297,4 +297,4 @@ public class SharedContext {
return s;
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/epsdk-workflow/.gitignore b/ecomp-sdk/epsdk-workflow/.gitignore
new file mode 100644
index 00000000..aa0c881b
--- /dev/null
+++ b/ecomp-sdk/epsdk-workflow/.gitignore
@@ -0,0 +1,5 @@
+/target
+/bin/
+/.settings/
+.project
+.classpath
diff --git a/ecomp-sdk/epsdk-workflow/README.md b/ecomp-sdk/epsdk-workflow/README.md
new file mode 100644
index 00000000..0e919a47
--- /dev/null
+++ b/ecomp-sdk/epsdk-workflow/README.md
@@ -0,0 +1,18 @@
+# ECOMP Portal SDK Workflow
+
+## Overview
+
+This is the Maven project for the ECOMP Portal SDK Workflow library,
+which is distributed as epsdk-workflow-N.N.N.jar. This library
+requires Hibernate and Spring, and provides features including
+schedulers, workflows and R Cloud integration.
+
+## Release Notes
+
+### OpenECOMP Distributions
+
+Version 1.1.0
+- [Portal-7] Improvements added as part of the rebasing process
+
+Version 1.0.0
+- Initial release
diff --git a/ecomp-sdk/epsdk-workflow/pom.xml b/ecomp-sdk/epsdk-workflow/pom.xml
new file mode 100644
index 00000000..5ed229f2
--- /dev/null
+++ b/ecomp-sdk/epsdk-workflow/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-project</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- GroupId is inherited from parent -->
+ <artifactId>epsdk-workflow</artifactId>
+ <!-- Version is inherited from parent -->
+ <packaging>jar</packaging>
+ <name>ECOMP Portal SDK Workflow</name>
+ <description>Provides workflow features for SDK applications</description>
+
+ <!-- repositories are inherited from parent -->
+
+ <dependencies>
+ <!-- sdk-core -->
+ <dependency>
+ <groupId>org.openecomp.ecompsdkos</groupId>
+ <artifactId>epsdk-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${hibernate.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>5.1.3.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160212</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>2.2.1</version>
+ <exclusions>
+ <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
+ <exclusion>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- bridge to implement commons-logging using slf4j -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${springframework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java
index 037e80d5..8b8ad5c9 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookController.java
@@ -21,7 +21,6 @@ package org.openecomp.portalsdk.rnotebookintegration.controller;
import javax.servlet.http.HttpServletRequest;
-import org.openecomp.portalsdk.core.controller.CollaborateListController;
import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.UserProfileService;
@@ -36,7 +35,7 @@ import org.springframework.web.servlet.ModelAndView;
public class NotebookController extends RestrictedBaseController{
@Autowired
UserProfileService service;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CollaborateListController.class);
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(NotebookController.class);
@RequestMapping(value = {"/notebook" }, method = RequestMethod.GET)
public ModelAndView noteBook(HttpServletRequest request) {
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java
index 74d1ae51..ac56b6c6 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/NotebookTestController.java
@@ -23,7 +23,6 @@ package org.openecomp.portalsdk.rnotebookintegration.controller;
import javax.servlet.http.HttpServletRequest;
-import org.openecomp.portalsdk.core.controller.CollaborateListController;
import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.service.UserProfileService;
@@ -38,7 +37,7 @@ import org.springframework.web.servlet.ModelAndView;
public class NotebookTestController extends RestrictedBaseController{
@Autowired
UserProfileService service;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CollaborateListController.class);
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(NotebookTestController.class);
@RequestMapping(value = {"/nbooktest" }, method = RequestMethod.GET)
public ModelAndView noteBook(HttpServletRequest request) {
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java
index a53b0573..00d97268 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookController.java
@@ -19,18 +19,34 @@
*/
package org.openecomp.portalsdk.rnotebookintegration.controller;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyName;
+import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
import org.openecomp.portalsdk.core.controller.RestrictedRESTfulBaseController;
+import org.openecomp.portalsdk.core.domain.User;
+import org.openecomp.portalsdk.core.restful.domain.EcompUser;
+import org.openecomp.portalsdk.core.util.SystemProperties;
import org.openecomp.portalsdk.core.web.support.JsonMessage;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.openecomp.portalsdk.rnotebookintegration.exception.RNotebookIntegrationException;
import org.openecomp.portalsdk.rnotebookintegration.service.RNoteBookIntegrationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
@Controller
@RequestMapping("/rNotebook/")
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java
index 3b0fcc49..3b0fcc49 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/controller/RNoteBookFEController.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java
index 9298c5a2..d2928495 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/domain/RNoteBookCredentials.java
@@ -22,6 +22,7 @@ package org.openecomp.portalsdk.rnotebookintegration.domain;
import java.util.Date;
import java.util.Map;
+import org.openecomp.portalsdk.core.domain.User;
import org.openecomp.portalsdk.core.domain.support.DomainVo;
import org.openecomp.portalsdk.core.restful.domain.EcompUser;
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java
index b2742641..b2742641 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/exception/RNotebookIntegrationException.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java
index 2b1e3c9e..2b1e3c9e 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationService.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java
index 1d0972da..fe21cd13 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/rnotebookintegration/service/RNoteBookIntegrationServiceImpl.java
@@ -19,6 +19,7 @@
*/
package org.openecomp.portalsdk.rnotebookintegration.service;
+import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -27,6 +28,7 @@ import java.util.UUID;
import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.openecomp.portalsdk.core.restful.domain.EcompUser;
import org.openecomp.portalsdk.core.service.DataAccessService;
+import org.openecomp.portalsdk.core.web.support.UserUtils;
import org.openecomp.portalsdk.rnotebookintegration.domain.RNoteBookCredentials;
import org.openecomp.portalsdk.rnotebookintegration.exception.RNotebookIntegrationException;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java
index ca2b3885..ca2b3885 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/controllers/WorkflowController.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java
index 435ac9a6..435ac9a6 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAO.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java
index a3382dbb..a3382dbb 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/WorkflowDAOImpl.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java
index e8c619f5..e8c619f5 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/domain/WorkflowSchedule.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java
index 7f93c5ea..3193f9cd 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/Workflow.java
@@ -1,3 +1,4 @@
+
/*-
* ================================================================================
* eCOMP Portal SDK
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java
index c3b727d9..c3b727d9 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/models/WorkflowLite.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java
index d90ee05b..d90ee05b 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleJob.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java
index bf29f59a..bf29f59a 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/scheduler/WorkFlowScheduleRegistry.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java
index 8927e08b..ea04e69e 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleExecutor.java
@@ -105,4 +105,4 @@ public class WorkflowScheduleExecutor {
}
return jsonString.toString();
}
-}
+} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java
index d04b72be..d04b72be 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleService.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java
index 1d0c58a7..1d0c58a7 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowScheduleServiceImpl.java
diff --git a/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java
new file mode 100644
index 00000000..7bf133a7
--- /dev/null
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java
@@ -0,0 +1,16 @@
+package org.openecomp.portalsdk.workflow.services;
+
+import java.util.List;
+
+import org.openecomp.portalsdk.workflow.domain.WorkflowSchedule;
+import org.openecomp.portalsdk.workflow.models.Workflow;
+import org.openecomp.portalsdk.workflow.models.WorkflowLite;
+
+
+public interface WorkflowService {
+ public void saveCronJob(WorkflowSchedule domainCronJobData);
+ public Workflow addWorkflow(Workflow workflow, String creatorId);
+ public Workflow editWorkflow(WorkflowLite worklow, String creatorId);
+ public void deleteWorkflow(Long worklow);
+ public List<Workflow> getAllWorkflows();
+}
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java
index b27d2e2d..b27d2e2d 100644
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java
+++ b/ecomp-sdk/epsdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowServiceImpl.java
diff --git a/ecomp-sdk/sdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml b/ecomp-sdk/epsdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml
index 44b7986f..44b7986f 100644
--- a/ecomp-sdk/sdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml
+++ b/ecomp-sdk/epsdk-workflow/src/main/resources/RNoteBookIntegration.hbm.xml
diff --git a/ecomp-sdk/pom.xml b/ecomp-sdk/pom.xml
index 25a7a63e..e802cff2 100644
--- a/ecomp-sdk/pom.xml
+++ b/ecomp-sdk/pom.xml
@@ -1,82 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
+
+ <!-- ECOMP Portal SDK Maven parent project -->
<groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-project</artifactId>
- <packaging>pom</packaging>
- <!-- NOTE This value will not be picked from the property tag below, pass it as -Drelease.version="" when doing mvn deploy -->
+ <artifactId>epsdk-project</artifactId>
<version>1.1.0-SNAPSHOT</version>
- <name>Ecomp Portal SDK Project (parent)</name>
- <url>https://wiki/display/EcompPortal</url>
+ <packaging>pom</packaging>
+ <name>ECOMP Portal SDK Project (parent)</name>
+ <url>https://wiki.onap.org/display/DW/Portal</url>
<scm>
- <connection>scm:git:https://gitlab/scm/st_quantum/quantum.git</connection>
- <developerConnection>scm:git:ssh://git@gitlab/st_quantum/quantum.git</developerConnection>
- <tag>HEAD</tag>
+ <connection>scm:git:https://gitlab/scm/st_quantum/quantum.git</connection>
+ <developerConnection>scm:git:ssh://git@gitlab/st_quantum/quantum.git</developerConnection>
+ <tag>HEAD</tag>
</scm>
<modules>
- <!-- ecompFW -->
- <module>thirdparty</module>
- <!-- ecompSDK-core -->
- <module>quantum</module>
- <module>sdk-analytics</module>
- <module>sdk-workflow</module>
+ <module>epsdk-fw</module>
+ <module>epsdk-core</module>
+ <module>epsdk-analytics</module>
+ <module>epsdk-workflow</module>
+ <module>epsdk-app-common</module>
+ <module>epsdk-app-overlay</module>
+
</modules>
<properties>
<encoding>UTF-8</encoding>
- <sdk-internal.version>1.1.0-SNAPSHOT</sdk-internal.version>
<springframework.version>4.2.0.RELEASE</springframework.version>
<hibernate.version>4.3.11.Final</hibernate.version>
<!-- Tests usually require some setup that maven cannot do, so skip. -->
<skiptests>true</skiptests>
<nexusproxy>https://nexus.onap.org</nexusproxy>
- <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
- <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
- <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
- <sitePath>/content/sites/site/org/openecomp/ecompsdkos/${project.version}</sitePath>
+ <snapshotNexusPath>content/repositories/snapshots/</snapshotNexusPath>
+ <releaseNexusPath>content/repositories/releases/</releaseNexusPath>
+ <stagingNexusPath>content/repositories/staging/</stagingNexusPath>
</properties>
- <reporting>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>2.10.4</version>
- <configuration>
- <failOnError>false</failOnError>
- <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
- <docletArtifact>
- <groupId>org.umlgraph</groupId>
- <artifactId>umlgraph</artifactId>
- <version>5.6</version>
- </docletArtifact>
- <additionalparam>-views</additionalparam>
- <useStandardDocletOptions>true</useStandardDocletOptions>
- </configuration>
- </plugin>
- </plugins>
- </reporting>
-
<repositories>
<repository>
- <!-- Releases repository has ECOMP release artifacts -->
- <id>ecomp-releases</id>
- <name>OpenECOMP - Release Repository</name>
- <url>${nexusproxy}/${releaseNexusPath}</url>
+ <!-- Releases repository has ECOMP release artifacts -->
+ <id>ecomp-releases</id>
+ <name>OpenECOMP - Release Repository</name>
+ <url>${nexusproxy}/${releaseNexusPath}</url>
+ </repository>
+ <repository>
+ <!-- Snapshots repository has ECOMP snapshot artifacts -->
+ <id>ecomp-snapshots</id>
+ <name>OpenECOMP - Snapshot Repository</name>
+ <url>${nexusproxy}/${snapshotNexusPath}</url>
+ </repository>
+ <repository>
+ <id>ecomp-public</id>
+ <name>ecomp onap public Repository</name>
+ <url>https://nexus.onap.org/content/groups/public</url>
</repository>
- <repository>
- <!-- Snapshots repository has ECOMP snapshot artifacts -->
- <id>ecomp-snapshots</id>
- <name>OpenECOMP - Snapshot Repository</name>
- <url>${nexusproxy}/${snapshotNexusPath}</url>
- </repository>
- <repository>
- <id>oss-sonatype</id>
- <name>oss sonatype Central</name>
- <url>https://oss.sonatype.org/service/local/repositories/releases/content/</url>
- </repository>
-
</repositories>
<profiles>
@@ -103,34 +81,7 @@
<build>
<plugins>
- <plugin>
- <groupId>org.sonatype.plugins</groupId>
- <artifactId>nexus-staging-maven-plugin</artifactId>
- <version>1.6.7</version>
- <extensions>true</extensions>
- <configuration>
- <nexusUrl>${nexusproxy}</nexusUrl>
- <stagingProfileId>176c31dfe190a</stagingProfileId>
- <serverId>ecomp-staging</serverId>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>sonar-maven-plugin</artifactId>
- <version>3.2</version>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-site-plugin</artifactId>
- <version>3.6</version>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-webdav-jackrabbit</artifactId>
- <version>2.10</version>
- </dependency>
- </dependencies>
- </plugin>
+
<!-- Name the "master" branch -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -139,7 +90,7 @@
<configuration>
<connectionType>developerConnection</connectionType>
<scmVersionType>branch</scmVersionType>
- <scmVersion>feature/BRANCH_OS</scmVersion>
+ <scmVersion>feature/BRANCH_1707</scmVersion>
</configuration>
</plugin>
@@ -163,7 +114,6 @@
<archive>
<manifestEntries>
<archive-version>${project.version}</archive-version>
- <internal-version>${sdk-internal.version}</internal-version>
</manifestEntries>
</archive>
</configuration>
@@ -213,19 +163,20 @@
<!-- Publish jars to the Nexus Repository - public group -->
<!-- The id below must match your .m2/settings.xml/servers/server/id -->
<repository>
- <id>ecomp-releases</id>
- <name>OpenECOMP - Release Repository</name>
- <url>${nexusproxy}/${releaseNexusPath}</url>
+ <id>ecomp-releases</id>
+ <name>OpenECOMP - Release Repository</name>
+ <url>${nexusproxy}/${releaseNexusPath}</url>
</repository>
<snapshotRepository>
- <id>ecomp-snapshots</id>
- <name>OpenECOMP - Snapshot Repository</name>
- <url>${nexusproxy}/${snapshotNexusPath}</url>
+ <id>ecomp-snapshots</id>
+ <name>OpenECOMP - Snapshot Repository</name>
+ <url>${nexusproxy}/${snapshotNexusPath}</url>
</snapshotRepository>
-
+
<site>
- <id>ecomp-site</id>
- <url>dav:${nexusproxy}${sitePath}</url>
+ <id>ecomp-site</id>
+ <url>dav:${nexusproxy}${sitePath}</url>
</site>
</distributionManagement>
+
</project>
diff --git a/ecomp-sdk/quantum/.gitignore b/ecomp-sdk/quantum/.gitignore
deleted file mode 100644
index ea8c4bf7..00000000
--- a/ecomp-sdk/quantum/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
diff --git a/ecomp-sdk/quantum/README.md b/ecomp-sdk/quantum/README.md
deleted file mode 100644
index bf00b41d..00000000
--- a/ecomp-sdk/quantum/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-ECOMP Portal SDK Core
-=====================
-
-This is the Maven project for the ECOMP Portal SDK Core,
-which is distributed as ecompSDK-core-nnn.jar. This library
-requires Hibernate and Spring, and provides many features
-such as data access, session management, logging, on-boarding
-and more. Most of these features are used in the ECOMP SDK
-web application.
-
-
diff --git a/ecomp-sdk/quantum/pom.xml b/ecomp-sdk/quantum/pom.xml
deleted file mode 100644
index 2243be3d..00000000
--- a/ecomp-sdk/quantum/pom.xml
+++ /dev/null
@@ -1,330 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-project</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>ecompSDK-core</artifactId>
- <packaging>jar</packaging>
- <name>Ecomp Portal SDK Core (quantum)</name>
-
- <!-- properties are inherited from parent -->
- <properties>
- <drools.version>6.4.0.Final</drools.version>
- </properties>
-
- <!-- repositories are inherited from parent -->
-
- <build>
- <plugins>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.19.1</version>
- <configuration>
- <skipTests>${skiptests}</skipTests>
- <includes>
- <include>**/Test*.java</include>
- <include>**/*Test.java</include>
- <include>**/*TestCase.java</include>
- </includes>
- <systemPropertyVariables>
- <container.classpath>classpath:</container.classpath>
- </systemPropertyVariables>
- </configuration>
-
- </plugin>
-
- </plugins>
- </build>
-
- <dependencies>
-
- <!-- AT&T internal -->
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompFW</artifactId>
- <version>${project.version}</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>apache-log4j-extras</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
-
-
- <!-- Drools -->
- <dependency>
- <groupId>org.drools</groupId>
- <artifactId>drools-compiler</artifactId>
- <version>${drools.version}</version>
- </dependency>
-
- <!-- Spring -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${springframework.version}</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-orm</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- <version>1.3.0.RELEASE</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.8.9</version>
- </dependency>
-
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.8.9</version>
- </dependency>
-
-
- <!-- Hibernate -->
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>${hibernate.version}</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>5.1.3.Final</version>
- </dependency>
- <!-- Servlet+JSP+JSTL -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet.jsp</groupId>
- <artifactId>javax.servlet.jsp-api</artifactId>
- <version>2.3.1</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
- </dependency>
- <!-- bridge to implement commons-logging using slf4j -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <!-- bridge to implement log4j using slf4j -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.5.2</version>
- </dependency>
- <!-- Apache Tiles -->
- <dependency>
- <groupId>org.apache.tiles</groupId>
- <artifactId>tiles-core</artifactId>
- <version>3.0.5</version>
- </dependency>
- <dependency>
- <groupId>org.apache.tiles</groupId>
- <artifactId>tiles-jsp</artifactId>
- <version>3.0.5</version>
- </dependency>
- <!-- Yaml -->
- <dependency>
- <groupId>org.yaml</groupId>
- <artifactId>snakeyaml</artifactId>
- <version>1.15</version>
- </dependency>
- <!-- Mapper -->
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.22</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.jcs</groupId>
- <artifactId>jcs</artifactId>
- <version>1.3</version>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- <!-- -->
- </dependency>
-
- <dependency>
- <groupId>org.apache.tomcat</groupId>
- <artifactId>tomcat-websocket</artifactId>
- <version>8.0.28</version>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>concurrent</groupId>
- <artifactId>concurrent</artifactId>
- <version>1.3.2</version>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
-
- <!-- Raptor required Libraries -->
- <!-- for static charts -->
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.10</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
-
- <!-- Quartz -->
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.2.1</version>
- <exclusions>
- <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
- <exclusion>
- <groupId>c3p0</groupId>
- <artifactId>c3p0</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <!-- Elastic Search -->
- <dependency>
- <groupId>org.elasticsearch</groupId>
- <artifactId>elasticsearch</artifactId>
- <version>2.2.0</version>
- </dependency>
- <dependency>
- <groupId>io.searchbox</groupId>
- <artifactId>jest</artifactId>
- <version>2.0.0</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>com.att.eelf</groupId>
- <artifactId>eelf-core</artifactId>
- <version>0.0.1</version>
- </dependency>
- </dependencies>
-
-</project>
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java
deleted file mode 100644
index e5a58e82..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/LoginBean.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.command;
-
-import java.util.Set;
-
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.domain.support.FusionCommand;
-
-public class LoginBean extends FusionCommand {
-
- private String loginId;
- private String loginPwd;
- private String hrid;
- private String userid;
- private String siteAccess;
- private String loginErrorMessage;
-
- private User user;
- @SuppressWarnings("rawtypes")
- private Set menu;
- @SuppressWarnings("rawtypes")
- private Set businessDirectMenu;
-
- /**
- * getLoginId
- *
- * @return String
- */
- public String getLoginId() {
- return loginId;
- }
-
- /**
- * getLoginPwd
- *
- * @return String
- */
- public String getLoginPwd() {
- return loginPwd;
- }
-
- /**
- * getMenu
- *
- * @return Set
- */
- @SuppressWarnings("rawtypes")
- public Set getMenu() {
- return menu;
- }
-
- /**
- * getUser
- *
- * @return User
- */
- public User getUser() {
- return user;
- }
-
- /**
- * getHrid
- *
- * @return String
- */
- public String getHrid() {
- return hrid;
- }
-
- /**
- * getSiteAccess
- *
- * @return String
- */
- public String getSiteAccess() {
- return siteAccess;
- }
-
- /**
- * getBusinessDirectMenu
- *
- * @return Set
- */
- @SuppressWarnings("rawtypes")
- public Set getBusinessDirectMenu() {
- return businessDirectMenu;
- }
-
- /**
- * getLoginErrorMessage
- *
- * @return String
- */
- public String getLoginErrorMessage() {
- return loginErrorMessage;
- }
-
-
-
- /**
- * setLoginId
- *
- * @param loginId String
- */
- public void setLoginId(String loginId) {
- this.loginId = loginId;
- }
-
- /**
- * setLoginPwd
- *
- * @param loginPwd String
- */
- public void setLoginPwd(String loginPwd) {
- this.loginPwd = loginPwd;
- }
-
- @SuppressWarnings("rawtypes")
- public void setMenu(Set menu) {
- this.menu = menu;
- }
-
- /**
- * setUser
- *
- * @param user User
- */
- public void setUser(User user) {
- this.user = user;
- }
-
- /**
- * setHrid
- *
- * @param hrid String
- */
- public void setHrid(String hrid) {
- this.hrid = hrid;
- }
-
- /**
- * setSiteAccess
- *
- * @param siteAccess String
- */
- public void setSiteAccess(String siteAccess) {
- this.siteAccess = siteAccess;
- }
-
- /**
- * setBusinessDirectMenu
- *
- * @param businessDirectMenu Set
- */
- @SuppressWarnings("rawtypes")
- public void setBusinessDirectMenu(Set businessDirectMenu) {
- this.businessDirectMenu = businessDirectMenu;
- }
-
- /**
- * setLoginErrorMessage
- *
- * @param loginErrorMessage String
- */
- public void setLoginErrorMessage(String loginErrorMessage) {
- this.loginErrorMessage = loginErrorMessage;
- }
-
- public String getUserid() {
- return userid;
- }
-
- public void setUserid(String userid) {
- this.userid = userid;
- }
-
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java
deleted file mode 100644
index 4a2c05f1..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/command/support/SearchResult.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.command.support;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@SuppressWarnings("rawtypes")
-public class SearchResult extends ArrayList implements java.io.Serializable {
- /**
- *
- */
- private static final long serialVersionUID = -451947878984459011L;
- private int pageNo = 0;
- private int pageSize = 50;
- private int dataSize = -1;
-
- private String accessType = null;
-
- public SearchResult() {}
-
- @SuppressWarnings("unchecked")
- public SearchResult(List items) {
- super(items);
- }
-
- public int getPageNo() { return pageNo; }
- public int getPageSize() { return pageSize; }
- public int getDataSize() { return dataSize; }
-
- public int getSize() { return size(); } // for Struts bean property access
-
- public String getAccessType() { return accessType; }
-
- public void setPageNo(int pageNo) { this.pageNo=pageNo; }
- public void setPageSize(int pageSize) { this.dataSize=pageSize; }
- public void setDataSize(int dataSize) { this.dataSize=dataSize; }
-
- public void setAccessType(String accessType) { this.accessType = accessType; }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java
deleted file mode 100644
index b70ced48..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateConfiguration.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.conf;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.sql.DataSource;
-
-import org.hibernate.SessionFactory;
-import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.orm.hibernate4.HibernateTransactionManager;
-import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-import com.mchange.v2.c3p0.ComboPooledDataSource;
-
-@Configuration
-@EnableTransactionManagement
-public class HibernateConfiguration {
-
- @Autowired
- private SystemProperties systemProperties;
-
- @Autowired
- private HibernateMappingLocatable mappingLocate;
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HibernateConfiguration.class);
-
- DataSource dataSource;
-
-
- @Bean
- public LocalSessionFactoryBean sessionFactory() {
- LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
- sessionFactory.setDataSource(getDataSource());
- sessionFactory.setPackagesToScan(new String[] { "org.openecomp"});
- sessionFactory.setHibernateProperties(hibernateProperties());
- sessionFactory.setMappingLocations(mappingLocate.getMappingLocations());
- return sessionFactory;
- }
-
-
-
-
- @SuppressWarnings("rawtypes")
- @Bean
- public Map dataSourceMap() throws Exception {
- Connection conn = null;
- Statement stmt = null;
- Map<String, ComboPooledDataSource> dataSourceMap = new HashMap<String, ComboPooledDataSource>();
-
- try {
- conn = getDataSource().getConnection();
- stmt = conn.createStatement();
- String sql;
- sql = "SELECT schema_id,datasource_type,connection_url,user_name,password,driver_class,min_pool_size,max_pool_size,idle_connection_test_period FROM schema_info";
- ResultSet rs = stmt.executeQuery(sql);
-
- while (rs.next()) {
- ComboPooledDataSource dataSource = new ComboPooledDataSource();
- dataSource.setDriverClass(rs.getString("driver_class"));
- dataSource.setJdbcUrl(rs.getString("connection_url"));
- dataSource.setUser(rs.getString("user_name"));
- dataSource.setPassword(rs.getString("password"));
- dataSource.setMinPoolSize(rs.getInt("min_pool_size"));
- dataSource.setMaxPoolSize(rs.getInt("max_pool_size"));
- dataSource.setIdleConnectionTestPeriod(rs.getInt("idle_connection_test_period"));
- dataSourceMap.put(rs.getString("schema_id"), dataSource);
- }
- rs.close();
- stmt.close();
- conn.close();
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "Error initializing database, verify database settings in properties file: " + e.getMessage(),AlarmSeverityEnum.CRITICAL);
- e.printStackTrace();
- dataSourceMap = null;
- throw e;
- } finally {
- try {
- if (stmt != null)
- stmt.close();
- } catch (SQLException se2) {}
- try {
- if (conn != null)
- conn.close();
- } catch (SQLException se) { se.printStackTrace();}
- }
-
- return dataSourceMap;
- }
-
- private Properties hibernateProperties() {
- Properties properties = new Properties();
- properties.put("hibernate.dialect", SystemProperties.getProperty(SystemProperties.HB_DIALECT));
- properties.put("hibernate.show_sql", SystemProperties.getProperty(SystemProperties.HB_SHOW_SQL));
- return properties;
- }
-
- @Bean
- @Autowired
- public HibernateTransactionManager transactionManager(SessionFactory s) {
- HibernateTransactionManager txManager = new HibernateTransactionManager();
- txManager.setSessionFactory(s);
- return txManager;
- }
-
- public SystemProperties getSystemProperties() {
- return systemProperties;
- }
-
- public void setSystemProperties(SystemProperties systemProperties) {
- this.systemProperties = systemProperties;
- }
-
-
-
-
- public DataSource getDataSource() {
- return dataSource;
- }
-
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java
deleted file mode 100644
index a3bbe18d..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/conf/HibernateMappingLocatable.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.conf;
-
-import org.springframework.core.io.Resource;
-
-public interface HibernateMappingLocatable {
-
- public Resource[] getMappingLocations();
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AdminAuthGenericController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AdminAuthGenericController.java
deleted file mode 100644
index 8a1f1d2c..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/AdminAuthGenericController.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-/*package org.openecomp.portalsdk.core.controller;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import org.openecomp.portalsdk.core.domain.Role;
-import org.openecomp.portalsdk.core.onboarding.crossapi.IGenericRolesService;
-import org.openecomp.portalsdk.core.onboarding.crossapi.IGenericUsersService;
-import com.fasterxml.jackson.core.JsonProcessingException;
-
-
-@RestController
-@RequestMapping("/api")
-public class AdminAuthGenericController extends RestrictedRESTfulBaseController {
- protected final Log logger = LogFactory.getLog(getClass());
- @Autowired
- IGenericUsersService genericUserService;
-
- @Autowired
- IGenericRolesService genericRolesService;
-
- *//**
- * RESTful service method to fetch available roles
- * @return
- *//*
- @RequestMapping(value={"/roles"}, method = RequestMethod.GET, produces = "application/json")
- public String getAvailableRoles() throws Exception{
- return genericRolesService.getAvailableRoles();
- }
-
- *//**
- * RESTful service method to save user - expects user details in json string
- * @param userJson
- *//*
- @RequestMapping(value={"/user"}, method = RequestMethod.POST)
- public String pushUser(@RequestBody String userJson) throws Exception{
- return genericUserService.pushUser(userJson);
- }
-
- *//**
- * RESTful service method to edit user - expects user details in json string
- * @param userJson
- *//*
- @RequestMapping(value={"/user/{loginId}"}, method = RequestMethod.POST)
- public String editUser(@PathVariable("loginId") String loginId, @RequestBody String userJson) throws Exception{
- return genericUserService.editUser(loginId, userJson);
- }
-
- *//**
- * RESTful service method to save user role using user's login Id and details in role Json string
- * @param loginId
- * @param roleJson
- * @throws JsonProcessingException
- *//*
- @RequestMapping(value={"/user/{loginId}/roles"}, method = RequestMethod.POST)
- public String pushUserRole(@PathVariable("loginId") String loginId, @RequestBody String rolesJson) throws Exception{
- return genericRolesService.pushUserRole(loginId, rolesJson);
- }
-
-
- *//**
- * Below method is to retrieve user - TODO @Talasila - Created to test the fn_app relation to fn_user_role. If not needed, please remove this method.
- * @param id
- * @return
- * @throws Exception
- *//*
- @RequestMapping(value={"/user/{loginId}"}, method = RequestMethod.GET, produces = "application/json")
- public String getUser(@PathVariable("loginId") String loginId) throws Exception{
- return genericUserService.getUser(loginId);
- }
-
- @RequestMapping(value={"/users"}, method = RequestMethod.GET, produces = "application/json")
- public String getUsers() throws Exception{
- return genericUserService.getUsers();
- }
-
- *//**
- * RESTful service method to fetch individual user's roles using user's loginId
- * @param loginId
- * @return
- *//*
- @RequestMapping(value={"/user/{loginId}/roles"}, method = RequestMethod.GET, produces = "application/json")
- public String getUserRoles(@PathVariable("loginId") String loginId) throws Exception{
- return genericRolesService.getUserRoles(loginId);
- }
-
- *//**
- * RESTful service method to fetch available roles
- * @return
- *//*
-
- //Commenting this out as it depends on Role API - Ikram
- @RequestMapping(value={"/rolesFull"}, method = RequestMethod.GET, produces = "application/json")
- public List<Role> getAvailableFullRoles(){
- return genericRolesService.getAvailableFullRoles();
- }
-
- @ExceptionHandler(Exception.class)
- void handleBadRequests(Exception e, HttpServletResponse response) throws IOException {
- response.sendError(HttpStatus.BAD_REQUEST.value(),e.getMessage());
- }
-}
-*/
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CacheAdminController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CacheAdminController.java
deleted file mode 100644
index 095c41b6..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/CacheAdminController.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.jcs.JCS;
-import org.apache.jcs.admin.CacheRegionInfo;
-import org.apache.jcs.admin.JCSAdminBean;
-import org.apache.jcs.engine.behavior.ICacheElement;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-
-@Controller
-@RequestMapping("/")
-public class CacheAdminController extends RestrictedBaseController {
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CacheAdminController.class);
- private JCSAdminBean jcsAdminBean = new JCSAdminBean();
-
- @RequestMapping(value = {"/jcs_admin" }, method = RequestMethod.GET)
- public ModelAndView cacheAdmin(HttpServletRequest request) {
- Map<String, Object> model = new HashMap<String, Object>();
-
- model.put("model", getRegions());
-
- return new ModelAndView(getViewName(),model);
- }
-
- @RequestMapping(value = {"/get_regions" }, method = RequestMethod.GET)
- public void getRegions(HttpServletRequest request,HttpServletResponse response) {
- // ObjectMapper mapper = new ObjectMapper();
- try{
- JsonMessage msg = new JsonMessage(getRegions().toString());
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- }catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- @RequestMapping(value = {"/jcs_admin/clearRegion" }, method = RequestMethod.GET)
- public void clearRegion(HttpServletRequest request,HttpServletResponse response) throws Exception {
- String cacheName = (String) request.getParameter("cacheName");
- clearCacheRegion(cacheName);
-
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(getRegions().toString());
- }
-
- @RequestMapping(value = {"/jcs_admin/clearAll" }, method = RequestMethod.GET)
- public void clearAll(HttpServletRequest request,HttpServletResponse response) throws Exception {
- clearAllRegions();
-
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(getRegions().toString());
- }
-
- @RequestMapping(value = {"/jcs_admin/clearItem" }, method = RequestMethod.GET)
- public void clearItem(HttpServletRequest request,HttpServletResponse response) throws Exception {
- String keyName = (String) request.getParameter("keyName");
- String cacheName = (String) request.getParameter("cacheName");
- clearCacheRegionItem(cacheName, keyName);
-
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(getRegions().toString());
- }
-
- @RequestMapping(value = {"/jcs_admin/showItemDetails" }, method = RequestMethod.GET)
- public void showItemDetails(HttpServletRequest request,HttpServletResponse response) throws Exception {
- String cacheName = (String) request.getParameter("cacheName");
- String keyName = (String) request.getParameter("keyName");
- String details = null;
-
- try {
- details = getItemDetails(cacheName, keyName);
- } catch (Exception e) {
- details = "There was an error retrieving the region details. Please try again.";
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while retrieving the item details for the cache region - "
- + cacheName + e.getMessage());
-
- }
-
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(details);
- }
-
- @RequestMapping(value = {"/jcs_admin/showRegionDetails" }, method = RequestMethod.GET)
- public void showRegionDetails(HttpServletRequest request,HttpServletResponse response) throws Exception {
- String cacheName = (String) request.getParameter("cacheName");
- String details = null;
-
- try {
- details = getRegionStats(cacheName);
- } catch (Exception e) {
- details = "There was an error retrieving the region details. Please try again.";
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while retrieving the region details for the cache region - "
- + cacheName + e.getMessage());
-
- }
-
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(details);
- }
-
- @SuppressWarnings("unchecked")
- public JSONArray getRegions(){
- LinkedList<CacheRegionInfo> regions = null;
- JSONArray ja = new JSONArray();
- try {
- regions = getJcsAdminBean().buildCacheInfo();
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
- for (CacheRegionInfo cri : regions) {
- JSONObject jo = new JSONObject();
- jo.put("cacheName", cri.getCache().getCacheName());
- jo.put("size", cri.getCache().getSize());
- jo.put("byteCount", cri.getByteCount());
- jo.put("status", cri.getStatus());
- jo.put("hitCountRam", cri.getCache().getHitCountRam());
- jo.put("hitCountAux", cri.getCache().getHitCountAux());
- jo.put("missCountNotFound", cri.getCache().getMissCountNotFound());
- jo.put("missCountExpired", cri.getCache().getMissCountExpired());
- jo.put("items",new JSONArray(mapper.writeValueAsString(getRegionItems(cri.getCache().getCacheName()))));
- ja.put(jo);
- }
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while retrieving the list of cache regions" + e.getMessage());
-
- }
-
- return ja;
- }
-
- private String getRegionStats(String cacheName) throws Exception {
- String stats = "";
-
- JCS cache = JCS.getInstance(cacheName);
- stats = cache.getStats();
-
- return stats;
- }
-
- private String getItemDetails(String cacheName, String keyName)
- throws Exception {
- String details = "";
-
- JCS cache = JCS.getInstance(cacheName);
- ICacheElement element = cache.getCacheElement(keyName);
-
- if (element != null) {
- ObjectMapper mapper = new ObjectMapper();
- mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
- details = mapper.writeValueAsString(element);
- }
-
- return details;
- }
-
- @SuppressWarnings("rawtypes")
- private List getRegionItems(String cacheName) {
- List items = null;
-
- try {
- items = getJcsAdminBean().buildElementInfo(cacheName);
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while retrieving the list of items for cache region - "
- + cacheName + e.getMessage());
-
- }
-
- return items;
- }
-
- private void clearAllRegions() {
- try {
- getJcsAdminBean().clearAllRegions();
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while clearing all cache regions." + e.getMessage());
-
- }
- }
-
- private void clearCacheRegion(String cacheName) {
- try {
- getJcsAdminBean().clearRegion(cacheName);
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while clearing the cache region - "
- + cacheName + e.getMessage());
-
- }
- }
-
- private void clearCacheRegionItem(String cacheName, String keyName) {
- try {
- getJcsAdminBean().removeItem(cacheName, keyName);
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while removing cache region item - "
- + keyName + e.getMessage());
-
- }
- }
-
- public JCSAdminBean getJcsAdminBean() {
- return jcsAdminBean;
- }
-
- public void setJcsAdminBean(JCSAdminBean jcsAdminBean) {
- this.jcsAdminBean = jcsAdminBean;
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ElementModelController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ElementModelController.java
deleted file mode 100644
index a6e7b966..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ElementModelController.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.openecomp.portalsdk.core.service.ElementLinkService;
-import org.openecomp.portalsdk.core.service.ElementMapService;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-
-@Controller
-@RequestMapping("/")
-public class ElementModelController extends RestrictedBaseController{
-
- @RequestMapping(value = {"/elementMapLayout" }, method = RequestMethod.POST)
- public ModelAndView layout(HttpServletRequest request,
- HttpServletResponse response) throws Exception{
-
- Map<String, Object> model = new HashMap<String, Object>();
- String collapseDomains = request.getParameter("collapsedDomains");
- String expandDomains = request.getParameter("expandedDomains");
-
- String contentFileName = request.getParameter("contentFileName");
- String layoutFileName = request.getParameter("layoutFileName");
-
- ElementMapService main = new ElementMapService();
- String yamlString = main.main1(new String[]{collapseDomains,expandDomains, contentFileName, layoutFileName });
-
- //response.setContentType("application/json");
- //PrintWriter out = response.getWriter();
- //out.print(yamlString);
- //out.flush();
-
- //return null;
- model.put("output_string", yamlString);
- return new ModelAndView("data_out", "model", model);
- }
-
- @RequestMapping(value = {"/elementMapLink" }, method = RequestMethod.POST)
- public ModelAndView callflow(HttpServletRequest request,
- HttpServletResponse response) throws Exception{
-
- Map<String, Object> model = new HashMap<String, Object>();
- String callFlowName = request.getParameter("callFlowName");
- String callFlowStep = request.getParameter("callFlowStep");
-
- ElementLinkService main = new ElementLinkService();
- String yamlString = main.main1(new String[]{callFlowName,callFlowStep });
- model.put("output_string", yamlString);
- return new ModelAndView("data_out", "model", model);
- }
-
- public ModelAndView callflowAdditional(HttpServletRequest request,
- HttpServletResponse response) throws Exception{
-
- Map<String, Object> model = new HashMap<String, Object>();
- String callFlowName = request.getParameter("callFlowName");
- String callFlowStep = request.getParameter("callFlowStep");
-
- ElementLinkService main = new ElementLinkService();
- String yamlString = main.main2(new String[]{callFlowName,callFlowStep });
- model.put("output_string", yamlString);
- return new ModelAndView("data_out", "model", model);
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ExternalLoginController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ExternalLoginController.java
deleted file mode 100644
index 90e47d42..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ExternalLoginController.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.openecomp.portalsdk.core.command.LoginBean;
-import org.openecomp.portalsdk.core.menu.MenuProperties;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalTimeoutHandler;
-import org.openecomp.portalsdk.core.service.LoginService;
-import org.openecomp.portalsdk.core.service.ProfileService;
-import org.openecomp.portalsdk.core.web.support.AppUtils;
-import org.openecomp.portalsdk.core.web.support.UserUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
-
-@Controller
-@RequestMapping("/")
-public class ExternalLoginController extends UnRestrictedBaseController{
- @Autowired
- ProfileService service;
- @Autowired
- private LoginService loginService;
- String viewName;
-
- @RequestMapping(value = {"/login_external.htm" }, method = RequestMethod.GET)
- public ModelAndView ExternalLogin(HttpServletRequest request) {
- Map<String, Object> model = new HashMap<String, Object>();
- return new ModelAndView(getViewName(),"model", model);
- }
-
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @RequestMapping(value = {"/login_external/login" }, method = RequestMethod.POST)
- public @ResponseBody String ExternalLogin(HttpServletRequest request, HttpServletResponse response) throws Exception{
-
- Map model = new HashMap();
- LoginBean commandBean = new LoginBean();
- String loginId = request.getParameter("loginId");
- String password = request.getParameter("password");
- commandBean.setLoginId(loginId);
- commandBean.setLoginPwd(password);
- HashMap additionalParamsMap = new HashMap();
-
- commandBean = getLoginService().findUser(commandBean, (String)request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY),
- additionalParamsMap);
-
- if (commandBean.getUser() == null) {
- String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
- : "login.error.external.invalid";
- model.put("error", loginErrorMessage);
- String[] errorCodes = new String[1];
- errorCodes[0] = loginErrorMessage;
- return "failure";
-
- }
- else {
- // store the currently logged in user's information in the session
- UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(), commandBean.getBusinessDirectMenu(),
- null);
- initateSessionMgtHandler(request);
- // user has been authenticated, now take them to the welcome page
- return "success";
-
- }
-
-
- }
-
- public String getJessionId(HttpServletRequest request){
-
- return request.getSession().getId();
-
- }
-
- protected void initateSessionMgtHandler(HttpServletRequest request) {
- String jSessionId = getJessionId(request);
- PortalTimeoutHandler.sessionCreated(jSessionId, jSessionId, AppUtils.getSession(request));
- }
-
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
- public LoginService getLoginService() {
- return loginService;
- }
-
- public void setLoginService(LoginService loginService) {
- this.loginService = loginService;
- }
-
-}
-
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FnMenuController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FnMenuController.java
deleted file mode 100644
index f19a6f19..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/FnMenuController.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.domain.Menu;
-import org.openecomp.portalsdk.core.domain.MenuData;
-import org.openecomp.portalsdk.core.service.FnMenuService;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
- * Description: this java class is a controller for Admin to add/edit/delete menu items from FN_MENU
- */
-
-@Controller
-@RequestMapping("/")
-public class FnMenuController extends RestrictedBaseController {
- @Autowired
- FnMenuService service;
-
- String viewName;
-
- @RequestMapping(value = {"/admin_fn_menu/get_parent_list" }, method = RequestMethod.GET)
- public void getParentList(HttpServletRequest request,HttpServletResponse response) throws Exception {
- ObjectMapper mapper = new ObjectMapper();
- try{
-
- response.getWriter().write(mapper.writeValueAsString(service.getParentList()));
-
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
-
- }
-
- }
-
- @RequestMapping(value = {"/admin_fn_menu/get_function_cd_list" }, method = RequestMethod.GET)
- public void getFunctionCDList(HttpServletRequest request,HttpServletResponse response) throws Exception {
- ObjectMapper mapper = new ObjectMapper();
- try{
-
- response.getWriter().write(mapper.writeValueAsString(service.getFunctionCDList()));
-
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
-
- }
-
- }
-
- @RequestMapping(value = {"/admin_fn_menu" }, method = RequestMethod.GET)
- public void getFnMenuList(HttpServletRequest request,HttpServletResponse response) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
- List<MenuData> temp =null;
- List<List<MenuData>> childItemList = new ArrayList<List<MenuData>>();
- List<MenuData> parentList = new ArrayList<>();
-
- try {
- temp = service.getFnMenuItems();
- for(MenuData menu: temp){
- MenuData parentData = new MenuData();
- parentData.setId(menu.getId());
- parentData.setLabel(menu.getLabel());
- if(menu.getParentMenu()!=null){
- parentData.setParentId(menu.getParentMenu().getId());
- }
- parentData.setAction(menu.getAction());
- parentData.setFunctionCd(menu.getFunctionCd());
- parentData.setImageSrc(menu.getImageSrc());
- parentData.setSortOrder(menu.getSortOrder());
- parentData.setActive(menu.isActive());
- parentData.setServlet(menu.getServlet());
- parentData.setQueryString(menu.getQueryString());
- parentData.setExternalUrl(menu.getExternalUrl());
- parentData.setTarget(menu.getTarget());
- parentData.setMenuSetCode(menu.getMenuSetCode());
- parentData.setSeparator(menu.isSeparator());
- parentData.setImageSrc(menu.getImageSrc());
- parentList.add(parentData);
- List<MenuData> tempList = new ArrayList<MenuData>();
- childItemList.add(tempList);
- }
- model.put("fnMenuItems", parentList);
-
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
-
- @RequestMapping(value = {"/admin_fn_menu/updateFnMenu" }, method = RequestMethod.POST)
- public ModelAndView updateFnMenu(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- try {
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- Menu fnMenuItem = mapper.readValue(root.get("availableFnMenuItem").toString(), Menu.class);
-
- service.saveFnMenu(fnMenuItem);
- request.getSession().removeAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
- request.getSession().removeAttribute(SystemProperties.LEFT_MENU_CHILDREND);
- request.getSession().removeAttribute(SystemProperties.LEFT_MENU_PARENT);
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
- String responseString = mapper.writeValueAsString(service.getMenuItem(fnMenuItem.getId()));
-
- out.write(responseString);
-
- return null;
-
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
-
- }
- return null;
-
- }
-
- @RequestMapping(value = {"/admin_fn_menu/removeMenuItem" }, method = RequestMethod.POST)
- public ModelAndView removeFnMenu(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- try {
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- Menu fnMenuItem = mapper.readValue(root.get("fnMenuItem").toString(), Menu.class);
- Menu fnMenuItemRow = service.getMenuItemRow(fnMenuItem.getId());
-
- service.removeMenuItem(fnMenuItemRow);
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- String responseString = mapper.writeValueAsString(service.getMenuItem(fnMenuItem.getId()));
- out.write(responseString);
-
- return null;
-
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
-
-
- }
- return null;
-
- }
-
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
-
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/MenuListController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/MenuListController.java
deleted file mode 100644
index ee66a948..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/MenuListController.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.domain.MenuData;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
-import org.openecomp.portalsdk.core.restful.client.SharedContextRestClient;
-import org.openecomp.portalsdk.core.restful.domain.SharedContext;
-import org.openecomp.portalsdk.core.service.AppService;
-import org.openecomp.portalsdk.core.service.FnMenuService;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.openecomp.portalsdk.core.web.support.UserUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-
-@Controller
-@RequestMapping("/")
-public class MenuListController extends UnRestrictedBaseController{
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MenuListController.class);
- @Autowired
- AppService appService;
- @Autowired
- FnMenuService fnMenuService;
- @Autowired
- SharedContextRestClient sharedContextRestClient;
- /**
- *
- * Get Menu items and store into session.
- *
- * @param request
- * @param response
- */
- @SuppressWarnings("unchecked")
- @RequestMapping(value = {"/get_menu" }, method = RequestMethod.GET)
- public void ProfileSearch(HttpServletRequest request, HttpServletResponse response) {
- logger.info("calling /get_menu..");
- try {
- ObjectMapper mapper = new ObjectMapper();
- Set<MenuData> menuResult=null;
- HttpSession session = request.getSession();
- List<List<MenuData>> childItemList = (List<List<MenuData>>) session.getAttribute(SystemProperties.LEFT_MENU_CHILDREND);
- List<MenuData> parentList = (List<MenuData>) session.getAttribute(SystemProperties.LEFT_MENU_PARENT);
- if(parentList==null || childItemList==null || parentList.size()==0 || childItemList.size()==0){
- childItemList=new ArrayList<List<MenuData>>();
- parentList = new ArrayList<MenuData>();
- menuResult = (Set<MenuData>) session.getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
- fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
- logger.info("storing leftmenu items into session");
- session.setAttribute(SystemProperties.LEFT_MENU_PARENT, parentList);
- session.setAttribute(SystemProperties.LEFT_MENU_CHILDREND, childItemList);
- }
- String userName = (String) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME));
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(parentList),mapper.writeValueAsString(childItemList),userName);
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- logger.info("done with /get_menu call without any errors");
- } catch (Exception e) {
- logger.info("errors while calling /get_menu",e);
- }
- }
-
- /**
- *
- * Get app name from system.properties file.
- *
- * @param request
- * @param response
- */
-
- @RequestMapping(value = {"/get_app_name" }, method = RequestMethod.GET)
- public void getAppName(HttpServletRequest request, HttpServletResponse response) {
- logger.info("calling /get_app_name.");
- HttpSession session = request.getSession(true);
- try {
- // String appName = SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME);
- String appName = (String) session.getAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME));
- if(appName!=null && appName.equals("app_display_name")){
- appName = "";
- }
- JsonMessage msg = new JsonMessage(appName);
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- logger.info("done with /get_app_name call without any errors");
- } catch (Exception e) {
- logger.error("errors while calling /get_app_name",e);
- }
- }
-
- @SuppressWarnings("unchecked")
- @ModelAttribute("menu")
- public Map<String, Object> getLeftMenuJSP(HttpServletRequest request) {
- logger.info("invoking getting left menu");
- ObjectMapper mapper = new ObjectMapper();
- Map<String, Object> model = new HashMap<String, Object>();
- try {
- HttpSession session = request.getSession();
- List<List<MenuData>> childItemList = (List<List<MenuData>>) session.getAttribute(SystemProperties.LEFT_MENU_CHILDREND);
- List<MenuData> parentList = (List<MenuData>) session.getAttribute(SystemProperties.LEFT_MENU_PARENT);
- if(parentList==null || childItemList==null){
- childItemList=new ArrayList<List<MenuData>>();
- parentList = new ArrayList<MenuData>();
- Set<MenuData> menuResult = (Set<MenuData>) session.getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
- fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
- session.setAttribute(SystemProperties.LEFT_MENU_PARENT, parentList);
- session.setAttribute(SystemProperties.LEFT_MENU_CHILDREND, childItemList);
- }
- model.put("childItemList",mapper.writeValueAsString(childItemList));
- model.put("parentList",mapper.writeValueAsString(parentList));
- } catch (Exception e) {
- logger.info("errors while getting left menu",e);
- }
- logger.info("done with getting left menu without any errors");
- return model;
- }
-
- /**
- * Answers requests for user information, which is fetched from the shared context at Portal.
- *
- * @param request
- * @param response
- * @return JSON block with user information.
- */
- @RequestMapping(value = {"/get_userinfo" }, method = RequestMethod.GET)
- public String getUserInfo(HttpServletRequest request, HttpServletResponse response) {
- logger.info(EELFLoggerDelegate.debugLogger, "Getting shared context for user");
- try{
- String contextId= null;
- if(request.getCookies()!=null){
- for(Cookie ck :request.getCookies()){
- if(ck.getName().equalsIgnoreCase("EPService"))
- contextId = ck.getValue();
- }
- }
- logger.info(EELFLoggerDelegate.debugLogger, "ContextId is : " + contextId);
- List<SharedContext> sharedContextRes = sharedContextRestClient.getUserContext(contextId);
- logger.info(EELFLoggerDelegate.debugLogger, "Shared Context Response is : " + sharedContextRes);
- Map<String, Object> model = new HashMap<String, Object>();
- for(SharedContext sharedContext: sharedContextRes){
- model.put(sharedContext.getCkey(), sharedContext.getCvalue());
- }
- JSONObject j = new JSONObject(model);
- response.getWriter().write(j.toString());
- } catch(Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "Failed to get shared context for user" + e.getMessage());
- }
- return null;
- }
-
- /**
- * Get User information from app sessions
- * @param request
- * @param response
- */
- @RequestMapping(value = {"/get_topMenuInfo" }, method = RequestMethod.GET)
- public void getTopMenu(HttpServletRequest request, HttpServletResponse response) {
-
- HttpSession session = request.getSession();
- try {
- String userName = (String) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME));
- String firstName = (String) session.getAttribute(SystemProperties.FIRST_NAME);
- String lastName = (String) session.getAttribute(SystemProperties.LAST_NAME);
- User user = (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
- Map<String,String> map = new HashMap<String,String>();
- String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
- String portalDomain = redirectUrl.substring(0, redirectUrl.lastIndexOf('/'));
- String portalUrl = portalDomain + "/processSingleSignOn";
- String getAccessUrl = portalDomain + "/get_access";
- String email = user.getEmail();
- String contactUsLink = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
- String userId = UserUtils.getUserIdFromCookie(request);
-
- map.put("portalUrl", portalUrl);
- map.put("contactUsLink", contactUsLink);
- map.put("userName", userName);
- map.put("firstName", firstName);
- map.put("lastName", lastName);
- map.put("userid", userId);
- map.put("email", email);
- map.put("getAccessUrl",getAccessUrl);
- JSONObject j = new JSONObject(map);
- response.getWriter().write(j.toString());
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "Failed to serialize JSON" + e.getMessage());
- }
-
- }
-
- @RequestMapping(value = {"/page_redirect" }, method = RequestMethod.GET)
- public void pageRedirect(HttpServletRequest request, HttpServletResponse response) {
- String pageToURL=null;
- try {
- String pageTo = request.getParameter("page");
- if(pageTo.equals("contact"))
- pageToURL = SystemProperties.getProperty(SystemProperties.CONTACT_US_LINK);
- else if(pageTo.equals("access")){
- String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
- String portalDomain = redirectUrl.substring(0, redirectUrl.lastIndexOf('/'));
- pageToURL = portalDomain + "/get_access";
- }
- response.getWriter().write(pageToURL);
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "Failed to serialize JSON" + e.getMessage());
- }
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileSearchController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileSearchController.java
deleted file mode 100644
index 42ebd41e..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/ProfileSearchController.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.domain.MenuData;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.service.FnMenuService;
-import org.openecomp.portalsdk.core.service.UserProfileService;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-@Controller
-@RequestMapping("/")
-public class ProfileSearchController extends RestrictedBaseController{
- @Autowired
- UserProfileService service;
- @Autowired
- FnMenuService fnMenuService;
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProfileSearchController.class);
- @RequestMapping(value = {"/profile_search" }, method = RequestMethod.GET)
- public ModelAndView ProfileSearch(HttpServletRequest request) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
- List<User> profileList =null;
- logger.info(EELFLoggerDelegate.applicationLogger, "Initiating ProfileSearch in ProfileSearchController");
- try {
- profileList = service.findAll();
- model.putAll(setDashboardData(request));
- model.put("profileList", mapper.writeValueAsString(profileList));
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.applicationLogger, "error while profile_search process in ProfileSearchController" + e.getMessage());
- }
- return new ModelAndView(getViewName(),"model", model);
- }
-
- @RequestMapping(value = {"/get_user" }, method = RequestMethod.GET)
- public void GetUser(HttpServletRequest request, HttpServletResponse response) {
- logger.info(EELFLoggerDelegate.applicationLogger, "Initiating get_user in ProfileSearchController");
- ObjectMapper mapper = new ObjectMapper();
- List<User> profileList =null;
- try {
- profileList = service.findAll();
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(profileList));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
-
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.applicationLogger, "error while get_user process in ProfileSearchController" + e.getMessage());
- }
- }
-
- @RequestMapping(value = {"/get_user_pagination" }, method = RequestMethod.GET)
- public void getUserPagination(HttpServletRequest request, HttpServletResponse response) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
- logger.info(EELFLoggerDelegate.applicationLogger, "Initiating get_user_pagination in ProfileSearchController");
- int pageNum = Integer.parseInt(request.getParameter("pageNum"));
- int viewPerPage = Integer.parseInt(request.getParameter("viewPerPage"));
- List<User> profileList =null;
- try {
- profileList = service.findAll();
- model.put("totalPage",(int) Math.ceil((double)profileList.size() / viewPerPage));
- profileList = profileList.subList(viewPerPage*(pageNum-1)<profileList.size()?viewPerPage*(pageNum-1):profileList.size(), viewPerPage*pageNum<profileList.size()?viewPerPage*pageNum:profileList.size());
- model.put("profileList", mapper.writeValueAsString(profileList));
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
-
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.applicationLogger, "error while get_user_pagination process in ProfileSearchController" + e.getMessage());
- }
- }
-
-
- @SuppressWarnings("unchecked")
- public Map<String, Object>setDashboardData(HttpServletRequest request) throws Exception{
- ObjectMapper mapper = new ObjectMapper();
- Map<String, Object> model = new HashMap<String, Object>();
- List<List<MenuData>> childItemList = new ArrayList<List<MenuData>>();
- List<MenuData> parentList = new ArrayList<MenuData>();
- logger.info(EELFLoggerDelegate.applicationLogger, "Initiating setDashboardData in ProfileSearchController");
- HttpSession session = request.getSession();
- try{
- Set<MenuData> menuResult = (Set<MenuData>) session.getAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
- fnMenuService.setMenuDataStructure(childItemList, parentList, menuResult);
- }catch(Exception e){
- logger.error(EELFLoggerDelegate.applicationLogger, "error while setDashboardData process in ProfileSearchController" + e.getMessage());
- }
- model.put("childItemList",mapper.writeValueAsString(childItemList));
- model.put("parentList",mapper.writeValueAsString(parentList));
- return model;
- }
-
- @RequestMapping(value = {"/profile/toggleProfileActive" }, method = RequestMethod.GET)
- public void toggleProfileActive(HttpServletRequest request, HttpServletResponse response) throws IOException {
- try{
- logger.info(EELFLoggerDelegate.applicationLogger, "Initiating toggleProfileActive in ProfileSearchController");
- String userId = request.getParameter("profile_id");
- User user = (User)service.getUser(userId);
- user.setActive(!user.getActive());
- service.saveUser(user);
- logger.info(EELFLoggerDelegate.auditLogger, "Change active status for user " + user.getId() + " to " + user.getActive());
- ObjectMapper mapper = new ObjectMapper();
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.write(mapper.writeValueAsString(user.getActive()));
- }catch(Exception e){
- logger.error(EELFLoggerDelegate.applicationLogger, "error while toggleProfileActive process in ProfileSearchController" + e.getMessage());
- }
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleController.java
deleted file mode 100644
index 0419e2b8..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleController.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.domain.Role;
-import org.openecomp.portalsdk.core.domain.RoleFunction;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.service.RoleService;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.ServletRequestUtils;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.type.TypeFactory;
-
-@Controller
-@RequestMapping("/")
-public class RoleController extends RestrictedBaseController {
- @Autowired
- RoleService service;
-
- String viewName;
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleController.class);
-
- @RequestMapping(value = { "/role" }, method = RequestMethod.GET)
- public ModelAndView role(HttpServletRequest request) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
-
- Role role = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
- logger.info("role_id" + role.getId());
- try {
- model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
- model.put("availableRoles", mapper.writeValueAsString(service.getAvailableChildRoles(role.getId())));
- model.put("role", mapper.writeValueAsString(role));
- } catch (Exception e) {
- logger.error("role: failed", e);
- logger.error(EELFLoggerDelegate.errorLogger, "Unable to set the active profile" + e.getMessage());
- }
- return new ModelAndView(getViewName(), model);
- }
-
- @RequestMapping(value = { "/get_role" }, method = RequestMethod.GET)
- public void getRole(HttpServletRequest request, HttpServletResponse response) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
-
- Role role = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
- logger.info(EELFLoggerDelegate.applicationLogger, "role_id" + role.getId());
- try {
- model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
- model.put("availableRoles", mapper.writeValueAsString(service.getAvailableChildRoles(role.getId())));
- model.put("role", mapper.writeValueAsString(role));
-
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "getRole failed" + e.getMessage());
- }
-
- }
-
- @RequestMapping(value = { "/role/saveRole" }, method = RequestMethod.POST)
- public ModelAndView saveRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
-
- logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.save");
- logger.info(EELFLoggerDelegate.auditLogger, "RoleController.save");
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- Role role = mapper.readValue(root.get("role").toString(), Role.class);
-
- List<Role> childRoles = mapper.readValue(root.get("childRoles").toString(),
- TypeFactory.defaultInstance().constructCollectionType(List.class, Role.class));
-
- List<RoleFunction> roleFunctions = mapper.readValue(root.get("roleFunctions").toString(),
- TypeFactory.defaultInstance().constructCollectionType(List.class, RoleFunction.class));
-
- Role domainRole = null;
- if (role.getId() != null) {
- logger.info(EELFLoggerDelegate.auditLogger, "updating existing role " + role.getId());
- domainRole = service.getRole(role.getId());
-
- domainRole.setName(role.getName());
- domainRole.setPriority(role.getPriority());
- } else {
- logger.info(EELFLoggerDelegate.auditLogger, "saving as new role");
- domainRole = new Role();
- domainRole.setName(role.getName());
- domainRole.setPriority(role.getPriority());
- if (role.getChildRoles().size() > 0) {
- for (Object childRole : childRoles) {
- domainRole.addChildRole((Role) childRole);
- }
- }
- if (role.getRoleFunctions().size() > 0) {
- for (Object roleFunction : roleFunctions) {
- domainRole.addRoleFunction((RoleFunction) roleFunction);
- }
- }
- }
-
- service.saveRole(domainRole);
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
- String responseString = mapper.writeValueAsString(domainRole);
- JSONObject j = new JSONObject("{role: " + responseString + "}");
-
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "saveRole failed" + e.getMessage());
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- @RequestMapping(value = { "/role/removeRoleFunction" }, method = RequestMethod.POST)
- public ModelAndView removeRoleFunction(HttpServletRequest request, HttpServletResponse response) throws Exception {
-
- logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeRoleFunction");
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- RoleFunction roleFunction = mapper.readValue(root.get("roleFunction").toString(), RoleFunction.class);
-
- Role domainRole = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
- logger.info(EELFLoggerDelegate.auditLogger, "Remove role function " + roleFunction.getCode() + " from role " + ServletRequestUtils.getIntParameter(request, "role_id", 0));
-
- domainRole.removeRoleFunction(roleFunction.getCode());
-
- service.saveRole(domainRole);
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
-
- String responseString = mapper.writeValueAsString(domainRole);
- JSONObject j = new JSONObject("{role: " + responseString + "}");
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "removeRole failed" + e.getMessage());
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- @RequestMapping(value = { "/role/addRoleFunction" }, method = RequestMethod.POST)
- public ModelAndView addRoleFunction(HttpServletRequest request, HttpServletResponse response) throws Exception {
-
- logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeRoleFunction");
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- RoleFunction roleFunction = mapper.readValue(root.get("roleFunction").toString(), RoleFunction.class);
-
- Role domainRole = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
-
- domainRole.addRoleFunction(roleFunction);
-
- service.saveRole(domainRole);
- logger.info(EELFLoggerDelegate.auditLogger, "Add role function " + roleFunction.getCode() + " to role " + ServletRequestUtils.getIntParameter(request, "role_id", 0));
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
-
- String responseString = mapper.writeValueAsString(domainRole);
- JSONObject j = new JSONObject("{role: " + responseString + "}");
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "removeRoleFunction failed" + e.getMessage());
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- @RequestMapping(value = { "/role/removeChildRole" }, method = RequestMethod.POST)
- public ModelAndView removeChildRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
-
- logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.removeChileRole");
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- Role childRole = mapper.readValue(root.get("childRole").toString(), Role.class);
-
- Role domainRole = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
-
- domainRole.removeChildRole(childRole.getId());
- logger.info(EELFLoggerDelegate.auditLogger, "remove child role " + childRole.getId() + " from role " + ServletRequestUtils.getIntParameter(request, "role_id", 0));
-
-
- service.saveRole(domainRole);
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
-
- String responseString = mapper.writeValueAsString(domainRole);
- JSONObject j = new JSONObject("{role: " + responseString + "}");
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "removeChildRole failed" + e.getMessage());
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- @RequestMapping(value = { "/role/addChildRole" }, method = RequestMethod.POST)
- public ModelAndView addChildRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
-
- logger.info(EELFLoggerDelegate.applicationLogger, "RoleController.addChileRole");
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- Role childRole = mapper.readValue(root.get("childRole").toString(), Role.class);
-
- Role domainRole = service.getRole(new Long(ServletRequestUtils.getIntParameter(request, "role_id", 0)));
-
- domainRole.addChildRole(childRole);
-
- service.saveRole(domainRole);
- logger.info(EELFLoggerDelegate.auditLogger, "Add child role " + childRole.getId() + " to role " + ServletRequestUtils.getIntParameter(request, "role_id", 0));
-
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
-
- String responseString = mapper.writeValueAsString(domainRole);
- JSONObject j = new JSONObject("{role: " + responseString + "}");
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.errorLogger, "addChildRole failed" + e.getMessage());
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- public String getViewName() {
- return viewName;
- }
-
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleFunctionListController.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleFunctionListController.java
deleted file mode 100644
index 3b9eed62..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/controller/RoleFunctionListController.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.controller;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.domain.RoleFunction;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.service.RoleService;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-@Controller
-@RequestMapping("/")
-public class RoleFunctionListController extends RestrictedBaseController {
- @Autowired
- RoleService service;
-
- String viewName;
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RoleFunctionListController.class);
-
- @RequestMapping(value = {"/role_function_list" }, method = RequestMethod.GET)
- public ModelAndView welcome(HttpServletRequest request) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
-
- try {
- model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- return new ModelAndView(getViewName(),model);
- }
-
- @RequestMapping(value = {"/get_role_functions" }, method = RequestMethod.GET)
- public void getRoleFunctionList(HttpServletRequest request,HttpServletResponse response) {
- Map<String, Object> model = new HashMap<String, Object>();
- ObjectMapper mapper = new ObjectMapper();
-
- try {
- model.put("availableRoleFunctions", mapper.writeValueAsString(service.getRoleFunctions()));
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- @RequestMapping(value = {"/role_function_list/saveRoleFunction" }, method = RequestMethod.POST)
- public ModelAndView saveRoleFunction(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- RoleFunction availableRoleFunction = mapper.readValue(root.get("availableRoleFunction").toString(), RoleFunction.class);
-
- RoleFunction domainRoleFunction = service.getRoleFunction(availableRoleFunction.getCode());
-
- //role. toggle active ind
- domainRoleFunction.setName(availableRoleFunction.getName());
- domainRoleFunction.setCode(availableRoleFunction.getCode());
-
- service.saveRoleFunction(domainRoleFunction);
- logger.info(EELFLoggerDelegate.auditLogger, "Save role function " + domainRoleFunction.getName());
-
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
- String responseString = mapper.writeValueAsString(service.getRoleFunctions());
- JSONObject j = new JSONObject("{availableRoleFunctions: "+responseString+"}");
-
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- @RequestMapping(value = {"/role_function_list/removeRoleFunction" }, method = RequestMethod.POST)
- public ModelAndView removeRoleFunction(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- try {
-
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- RoleFunction availableRoleFunction = mapper.readValue(root.get("availableRoleFunction").toString(), RoleFunction.class);
-
- RoleFunction domainRoleFunction = service.getRoleFunction(availableRoleFunction.getCode());
-
- service.deleteRoleFunction(domainRoleFunction);
- logger.info(EELFLoggerDelegate.auditLogger, "Remove role function " + domainRoleFunction.getName());
-
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
-
- String responseString = mapper.writeValueAsString(service.getRoleFunctions());
- JSONObject j = new JSONObject("{availableRoleFunctions: "+responseString+"}");
- out.write(j.toString());
-
- return null;
- } catch (Exception e) {
- System.out.println(e);
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- PrintWriter out = response.getWriter();
- out.write(e.getMessage());
- return null;
- }
-
- }
-
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
-
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java
deleted file mode 100644
index f861232f..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/AuditLog.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.domain;
-
-import java.util.Date;
-
-import org.openecomp.portalsdk.core.domain.support.DomainVo;
-public class AuditLog extends DomainVo {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- public static final String CD_ACTIVITY_LOGIN = "login";
- public static final String CD_ACTIVITY_LOGOUT = "logout";
- public static final String CD_ACTIVITY_MOBILE_LOGIN = "mobile_login";
- public static final String CD_ACTIVITY_MOBILE_LOGOUT = "mobile_logout";
-
- /*-------Profile activities -----------*/
- public static final String CD_ACTIVITY_ROLE_ADD = "add_role";
- public static final String CD_ACTIVITY_ROLE_REMOVE = "remove_role";
- public static final String CD_ACTIVITY_CHILD_ROLE_ADD = "add_child_role";
- public static final String CD_ACTIVITY_CHILD_ROLE_REMOVE = "remove_child_role";
- public static final String CD_ACTIVITY_ROLE_ADD_FUNCTION = "add_role_function";
- public static final String CD_ACTIVITY_ROLE_REMOVE_FUNCTION = "remove_role_function";
- public static final String CD_ACTIVITY_USER_ROLE_ADD = "add_user_role";
- public static final String CD_ACTIVITY_USER_ROLE_REMOVE = "remove_user_role";
-
-
- private String activityCode;
- private String affectedRecordId;
- private String comments;
-
- public AuditLog() {
- setCreated(new Date());
- }
-
- public String getActivityCode() {
- return activityCode;
- }
-
- public String getComments() {
- return comments;
- }
-
- public String getAffectedRecordId() {
- return affectedRecordId;
- }
-
- public void setActivityCode(String activityCode) {
- this.activityCode = activityCode;
- }
-
- public void setComments(String comments) {
- this.comments = comments;
- }
-
- public void setAffectedRecordId(String affectedRecordId) {
- this.affectedRecordId = affectedRecordId;
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java
deleted file mode 100644
index e005df41..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/BroadcastMessage.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.domain;
-
-import java.util.Date;
-
-import org.openecomp.portalsdk.core.domain.support.DomainVo;
-
-public class BroadcastMessage extends DomainVo{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public BroadcastMessage() {
- }
-
- public static final String ID_MESSAGE_LOCATION_LOGIN = "10";
- public static final String ID_MESSAGE_LOCATION_WELCOME = "20";
-
- private String messageText;
- private Integer locationId;
- private Date startDate;
- private Date endDate;
- private Integer sortOrder;
- private Boolean active;
- private String siteCd;
-
- public Boolean getActive() {
- return active;
- }
-
- public Date getEndDate() {
- return endDate;
- }
-
- public Integer getLocationId() {
- return locationId;
- }
-
- public String getMessageText() {
- return messageText;
- }
-
- public Integer getSortOrder() {
- return sortOrder;
- }
-
- public Date getStartDate() {
- return startDate;
- }
-
- public String getSiteCd() {
- return siteCd;
- }
-
-
- public void setActive(Boolean active) {
- this.active = active;
- }
-
- public void setEndDate(Date endDate) {
- this.endDate = endDate;
- }
-
- public void setLocationId(Integer locationId) {
- this.locationId = locationId;
- }
-
- public void setMessageText(String messageText) {
- this.messageText = messageText;
- }
-
- public void setSortOrder(Integer sortOrder) {
- this.sortOrder = sortOrder;
- }
-
- public void setStartDate(Date startDate) {
- this.startDate = startDate;
- }
-
- public void setSiteCd(String siteCd) {
- this.siteCd = siteCd;
- }
-
-
- public int compareTo(Object obj){
- Integer c1 = getLocationId();
- Integer c2 = ((BroadcastMessage)obj).getLocationId();
-
- if (c1.compareTo(c2) == 0) {
- c1 = getSortOrder();
- c2 = ((BroadcastMessage)obj).getSortOrder();
-
- if (c1.compareTo(c2) == 0) {
- Long c3 = getId();
- Long c4 = ((BroadcastMessage)obj).getId();
-
- return c3.compareTo(c4);
- }
- }
-
- return c1.compareTo(c2);
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java
deleted file mode 100644
index 52c6d00e..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/LoginBean.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.domain;
-
-import java.util.Set;
-
-import org.openecomp.portalsdk.core.domain.support.FusionCommand;
-
-@SuppressWarnings("rawtypes")
-public class LoginBean extends FusionCommand {
-
- private String loginId;
- private String loginPwd;
- private String hrid;
- private String orgUserId;
- private String siteAccess;
- private String loginErrorMessage;
-
- private User user;
- private Set menu;
- private Set businessDirectMenu;
-
- /**
- * getLoginId
- *
- * @return String
- */
- public String getLoginId() {
- return loginId;
- }
-
- /**
- * getLoginPwd
- *
- * @return String
- */
- public String getLoginPwd() {
- return loginPwd;
- }
-
- /**
- * getMenu
- *
- * @return Set
- */
- public Set getMenu() {
- return menu;
- }
-
- /**
- * getUser
- *
- * @return User
- */
- public User getUser() {
- return user;
- }
-
- /**
- * getHrid
- *
- * @return String
- */
- public String getHrid() {
- return hrid;
- }
-
- /**
- * getSiteAccess
- *
- * @return String
- */
- public String getSiteAccess() {
- return siteAccess;
- }
-
- /**
- * getBusinessDirectMenu
- *
- * @return Set
- */
- public Set getBusinessDirectMenu() {
- return businessDirectMenu;
- }
-
- /**
- * getLoginErrorMessage
- *
- * @return String
- */
- public String getLoginErrorMessage() {
- return loginErrorMessage;
- }
-
- public String getOrgUserId() {
- return orgUserId;
- }
-
- /**
- * setLoginId
- *
- * @param loginId String
- */
- public void setLoginId(String loginId) {
- this.loginId = loginId;
- }
-
- /**
- * setLoginPwd
- *
- * @param loginPwd String
- */
- public void setLoginPwd(String loginPwd) {
- this.loginPwd = loginPwd;
- }
-
- public void setMenu(Set menu) {
- this.menu = menu;
- }
-
- /**
- * setUser
- *
- * @param user User
- */
- public void setUser(User user) {
- this.user = user;
- }
-
- /**
- * setHrid
- *
- * @param hrid String
- */
- public void setHrid(String hrid) {
- this.hrid = hrid;
- }
-
- /**
- * setSiteAccess
- *
- * @param siteAccess String
- */
- public void setSiteAccess(String siteAccess) {
- this.siteAccess = siteAccess;
- }
-
- /**
- * setBusinessDirectMenu
- *
- * @param businessDirectMenu Set
- */
- public void setBusinessDirectMenu(Set businessDirectMenu) {
- this.businessDirectMenu = businessDirectMenu;
- }
-
- /**
- * setLoginErrorMessage
- *
- * @param loginErrorMessage String
- */
- public void setLoginErrorMessage(String loginErrorMessage) {
- this.loginErrorMessage = loginErrorMessage;
- }
-
- public void setOrgUserId(String orgUserId) {
- this.orgUserId = orgUserId;
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java
deleted file mode 100644
index a71bdfc1..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/Lookup.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.domain;
-
-import java.io.Serializable;
-
-import org.openecomp.portalsdk.core.domain.support.NameValueId;
-
-public class Lookup extends FusionVo implements Serializable {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private NameValueId nameValueId = new NameValueId();
-
- public Lookup() {}
-
- public Lookup(String label, String value) {
- this();
- setLabel(label);
- setValue(value);
- }
-
- public String getValue() {
- return getNameValueId().getVal();
- }
-
- public String getLabel() {
- return getNameValueId().getLab();
- }
-
- public void setValue(String value) {
- getNameValueId().setVal(value);
- }
-
- public void setLabel(String label) {
- getNameValueId().setLab(label);
- }
-
- public NameValueId getNameValueId() {
- return nameValueId;
- }
-
- public void setNameValueId(NameValueId nameValueId) {
- this.nameValueId = nameValueId;
- }
-
- // required by ZK for to set the selectedItems of Listboxes (used heavily for <select>-style drop-downs)
- public int hashCode() {
- int hash = getValue().hashCode();
- hash = hash + getLabel().hashCode();
-
- return hash;
- }
-
- public boolean equals( Object obj ) {
- boolean equivalent = false;
-
- Lookup lookup = (Lookup)obj;
- if( lookup.getValue().equals(getValue()) && lookup.getLabel().equals(getLabel())) {
- equivalent = true;
- }
-
- return equivalent;
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java
deleted file mode 100644
index 58056232..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/domain/support/Layout.java
+++ /dev/null
@@ -1,991 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.domain.support;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class Layout {
-
- public Map<String,Domain> domainRowCol;
-
- Map<String,Domain> originalDomainRowCol;
-
- //Horizontal space between a pair of domains
- double interDomainWd;
- //Vertical space between a pair of domains
- double interDomainH;
- //Computing the co-ordinates of any domain
- int numberofRowsofDomains;
-
- int numberofColsofDomains;
-
- Map<String, Domain> collapsedDomains;
-
- List<Domain> collapsedDomainsNewList;
-
- public List<Domain> getCollapsedDomainsNewList() {
- return collapsedDomainsNewList;
- }
-
- public void setCollapsedDomainsNewList(List<Domain> collapsedDomainsNewList) {
- this.collapsedDomainsNewList = collapsedDomainsNewList;
- }
-
- public void setCollapsedDomains(Map<String, Domain> collapsedDomains) {
- this.collapsedDomains = collapsedDomains;
- }
-
- public Map<String, Domain> getCollapsedDomains() {
- return collapsedDomains;
- }
-
- public int getNumberofColsofDomains() {
- return numberofColsofDomains;
- }
-
- public void setNumberofColsofDomains(int numberofColsofDomains) {
- this.numberofColsofDomains = numberofColsofDomains;
- }
-
- public Layout(Map<String,Domain> domainRowCol, double interDomainWd, double interDomainH,
- int numberofRowsofDomains, int numberofColsofDomains) {
-
- this.domainRowCol = domainRowCol;
- this.interDomainWd = interDomainWd;
- this.interDomainH = interDomainH;
- this.numberofRowsofDomains = numberofRowsofDomains;
- this.numberofColsofDomains = numberofColsofDomains;
- this.collapsedDomains = new HashMap<String, Domain>();
- this.originalDomainRowCol = new TreeMap<String,Domain>();
- this.collapsedDomainsNewList = new ArrayList<Domain>();
- }
-
- public Map<String, Domain> getDomainRowCol() {
- return domainRowCol;
- }
-
- public void setDomainRowCol(Map<String, Domain> domainRowCol) {
- this.domainRowCol = domainRowCol;
- }
-
-
- public void computeDomainPositions() {
- double xsum = 0;
- double domainTolayout = 10.6;
- for (int i=0; i< numberofRowsofDomains; i++){
- for (int j=0; j<numberofColsofDomains; j++){
- if (domainRowCol.containsKey(String.valueOf(i)+ String.valueOf(j))) {
- Domain d = domainRowCol.get(String.valueOf(i)+ String.valueOf(j));
- Position p = new Position();
- if (j==0)
- p.x = domainTolayout;
- else
- p.x = j*interDomainWd + xsum + domainTolayout;
- if (getCollapsedDomainsNewList().size() > 0)
- p.x+= accountForPlusSpaceBefore(d);
- xsum+=d.computeSize().getWidth();
- double ysum=0;
- for (int k=0; k<i; k++) {
- if (domainRowCol.containsKey(String.valueOf(k)+ String.valueOf(j)))
- ysum+= domainRowCol.get(String.valueOf(k)+ String.valueOf(j)).computeSize().getHeight();
- }
- p.y = (i+1)* interDomainH + ysum;
- d.setP(p);
-
- }
- }
- xsum = 0;
- }
- }
-
- public void computeDomainPositionsModified() {
- for (int i=0; i< numberofRowsofDomains; i++){
- for (int j=0; j<numberofColsofDomains; j++){
- if (domainRowCol.containsKey(String.valueOf(i)+ String.valueOf(j))) {
- Domain d = domainRowCol.get(String.valueOf(i)+ String.valueOf(j));
- Position p = new Position();
- Map<String,Container> enclosedContainers = d.getContainerRowCol();
- for (Map.Entry<String, Container> entry : enclosedContainers.entrySet()) {
- if (entry.getKey().equals("00")) {
- double containerX = entry.getValue().getP().getX();
- p.x = containerX;
- double ysum=0;
- for (int k=0; k<i; k++) {
- if (domainRowCol.containsKey(String.valueOf(k)+ String.valueOf(j)))
- ysum+= domainRowCol.get(String.valueOf(k)+ String.valueOf(j)).computeSize().getHeight();
- }
- p.y = (i+1)* interDomainH + ysum;
- d.setP(p);
- break;
- }
- }
- }
- }
- }
-
-
- }
- public Layout collapseDomainModified(String domainsToCollapse) {
-
- if(domainsToCollapse == null || domainsToCollapse.isEmpty())
- return null;
-
- Map<String,Domain> updatedRC = new HashMap<String, Domain>();
-
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
-
- Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
-
- List<Domain> collapsedDomainNewL = getCollapsedDomainsNewList();
-
-
- if (collapsedDomainNewL.size() == 0) {
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
- }
- }
-
-
- Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
-
- int colToDelete = 0;
- for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
- if (entry.getValue().getName().equals(domainsToCollapse)) {
- if (entry.getValue().isIndexChanged()) {
- collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
-
- }
- else {
- collapsedDomainMap.put(entry.getKey(),entry.getValue());
- }
-
- collapsedDomainNewL.add(entry.getValue());
- setNumberofColsofDomains(getNumberofColsofDomains()-1);
- updatedRC.remove(entry.getKey());
- colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- break;
- }
- }
-
-
- for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
- updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
- if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
- updatedRCSortedTrunc.remove(rmv.getKey());
- }
- }
-
- for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
- char update[] = updateOthers.getKey().toCharArray();
- int charToupdate = Character.getNumericValue(update[1]);
- --charToupdate;
- String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
- updateOthers.getValue().setIndexChanged(true);
- updatedRC.put(resultRowCol, updateOthers.getValue());
- updatedRC.remove(updateOthers.getKey());
-
- }
- setDomainRowCol(updatedRC);
-
- double currDistFromLftM = 11.0;
- for (Map.Entry<String,Domain> cd : updatedRC.entrySet()) {
-
- Domain d = cd.getValue();
- double accountPlus = accountForPlusSpaceBefore(d);
- d.setDomainToLayoutWd(currDistFromLftM+accountPlus);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- currDistFromLftM += d.computeSize().getWidth()+2;
-
- }
-
-
-
-
- //nline
- // Insert method invocation
- updatePlusPosition(collapsedDomainNewL, updatedRC);
-
- //order changed
- setCollapsedDomains(collapsedDomainMap);
- setCollapsedDomainsNewList(collapsedDomainNewL);
-
-
- computeDomainPositionsModified();
- return this;
- }
-
-
-
- public Layout collapseDomainNew(String domainsToCollapse) {
-
- if(domainsToCollapse == null || domainsToCollapse.isEmpty())
- return null;
-
- Map<String,Domain> updatedRC = new HashMap<String, Domain>();
-
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
-
- Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
-
- List<Domain> collapsedDomainNewL = getCollapsedDomainsNewList();
-
-
- if (collapsedDomainNewL.size() == 0) {
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
- }
- }
-
-
- Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
-
- int colToDelete = 0;
- for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
- if (entry.getValue().getName().equals(domainsToCollapse)) {
- if (entry.getValue().isIndexChanged()) {
- collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
-
- }
- else {
- collapsedDomainMap.put(entry.getKey(),entry.getValue());
- }
-
- collapsedDomainNewL.add(entry.getValue());
- setNumberofColsofDomains(getNumberofColsofDomains()-1);
- updatedRC.remove(entry.getKey());
- colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- break;
- }
- }
-
-
- for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
- updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
- if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
- updatedRCSortedTrunc.remove(rmv.getKey());
- }
- }
-
- for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
- char update[] = updateOthers.getKey().toCharArray();
- int charToupdate = Character.getNumericValue(update[1]);
- --charToupdate;
- String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
- updateOthers.getValue().setIndexChanged(true);
- updatedRC.put(resultRowCol, updateOthers.getValue());
- updatedRC.remove(updateOthers.getKey());
-
- }
- setDomainRowCol(updatedRC);
-
- double currDistFromLftM = 11.0;
-
- boolean isDisplayed;
- for (Map.Entry<String,Domain> orgEntry : originalDomainRowCol.entrySet()) {
- isDisplayed = false;
- for (Map.Entry<String,Domain> cd : updatedRC.entrySet()) {
- if (cd.getValue().getName().equals(orgEntry.getValue().getName())) {
- Domain d = cd.getValue();
- d.setDomainToLayoutWd(currDistFromLftM);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- currDistFromLftM += d.computeSize().getWidth()+1;
- isDisplayed = true;
- break;
- }
- }
-
- if (!isDisplayed) {
- Domain myCollapsed = orgEntry.getValue();
- myCollapsed.setNewXafterColl(currDistFromLftM);
- myCollapsed.setYafterColl(myCollapsed.getP().getY());
- currDistFromLftM += 4;
- }
- }
-
- setCollapsedDomains(collapsedDomainMap);
- setCollapsedDomainsNewList(collapsedDomainNewL);
-
-
- computeDomainPositionsModified();
- return this;
-
- }
-
-
- public Layout collapseDomain(String domainsToCollapse) {
-
- Map<String,Domain> updatedRC = new HashMap<String, Domain>();
-
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- updatedRC.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- Map<String, Domain> updatedRCSorted = new TreeMap<String, Domain>(updatedRC);
-
- Map<String, Domain> collapsedDomainMap = getCollapsedDomains();
-
- if (collapsedDomainMap.size() == 0) {
- for (Map.Entry<String, Domain> copyEntry : domainRowCol.entrySet()) {
- originalDomainRowCol.put(copyEntry.getKey(), copyEntry.getValue());
- }
- }
-
-
- double prevDomXCordinate = 0.0;
- Map<String, Domain> updatedRCSortedTrunc = new TreeMap<String, Domain>();
- int colToDelete = 0;
- for (Map.Entry<String, Domain> entry : updatedRCSorted.entrySet()) {
- if (entry.getValue().getName().equals(domainsToCollapse)) {
- if (entry.getValue().isIndexChanged())
- collapsedDomainMap.put("0"+String.valueOf(Integer.parseInt(entry.getKey())+1), entry.getValue());
- else
- collapsedDomainMap.put(entry.getKey(),entry.getValue());
- prevDomXCordinate = entry.getValue().getP().getX();
- entry.getValue().getP().setX(prevDomXCordinate-2);
- setNumberofColsofDomains(getNumberofColsofDomains()-1);
- updatedRC.remove(entry.getKey());
- colToDelete = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- break;
- }
- }
-
- setCollapsedDomains(collapsedDomainMap);
-
- for (Map.Entry<String, Domain> copyEntry : updatedRCSorted.entrySet()) {
- updatedRCSortedTrunc.put(copyEntry.getKey(), copyEntry.getValue());
- System.out.println("copyEntry.getKey() "+copyEntry.getKey()+ " copyEntry.getValue() "+copyEntry.getValue());
- }
-
- for (Map.Entry<String, Domain> rmv : updatedRCSorted.entrySet()) {
- if (Character.getNumericValue(rmv.getKey().toCharArray()[1]) <= colToDelete) {
- updatedRCSortedTrunc.remove(rmv.getKey());
- }
- }
-
- for (Map.Entry<String, Domain> updateOthers : updatedRCSortedTrunc.entrySet()) {
- char update[] = updateOthers.getKey().toCharArray();
- int charToupdate = Character.getNumericValue(update[1]);
- --charToupdate;
- String resultRowCol = String.valueOf(update[0])+String.valueOf(charToupdate);
- updateOthers.getValue().setIndexChanged(true);
- updatedRC.put(resultRowCol, updateOthers.getValue());
- updatedRC.remove(updateOthers.getKey());
- }
-
- setDomainRowCol(updatedRC);
-
-
-
- for (Map.Entry<String, Domain> entry : updatedRCSortedTrunc.entrySet()) {
- Domain d = entry.getValue();
- if (collapsedDomains.size() == 2 && collapsedDomains.containsKey("00") && collapsedDomains.containsKey("01") && domainsToCollapse.equals("RAN")) {
- if (d.getName().equals("USP"))
- d.setDomainToLayoutWd(prevDomXCordinate);
- else if (d.getName().equals("VNI"))
- d.setDomainToLayoutWd(prevDomXCordinate+8);
- else
- d.setDomainToLayoutWd(prevDomXCordinate+10);
- }
- else if (domainsToCollapse.equals("RAN") && !d.getName().equals("EPC") && collapsedDomains.size() < 3)
- d.setDomainToLayoutWd(prevDomXCordinate+11);
- else if (domainsToCollapse.equals("RAN") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("04")) {
- if (d.getName().equals("USP"))
- d.setDomainToLayoutWd(prevDomXCordinate);
- else
- d.setDomainToLayoutWd(prevDomXCordinate+10);
- }
-
- else if (collapsedDomains.containsKey("00") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("02")) {
- if (d.getName().equals("VNI"))
- d.setDomainToLayoutWd(prevDomXCordinate+10);
- else
- d.setDomainToLayoutWd(prevDomXCordinate);
-
- }
-
- else if (collapsedDomains.containsKey("00") && collapsedDomains.size() == 3 && collapsedDomains.containsKey("01") && collapsedDomains.containsKey("03")) {
- if (d.getName().equals("VNI"))
- d.setDomainToLayoutWd(prevDomXCordinate+10);
- else
- d.setDomainToLayoutWd(prevDomXCordinate);
-
- }
-
-
-
- else {
- d.setDomainToLayoutWd(prevDomXCordinate);
- }
- d.computeConatinerPositions();
- prevDomXCordinate = d.getP().getX();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- }
- computeDomainPositions();
- return this;
-
- }
-
- public Layout uncollapseDomainModified(String domainToUnCollapse) {
- Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
- Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
- Map<String, Domain> collapsedDomainList = getCollapsedDomains();
- Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
-
- List<Domain> domainstoUpd = new ArrayList<Domain>();
-
- int colToUnCollapse = 99;
-
- Domain domainToInsert = null;
-
- if (collapsedDomains.size() == 0) {
- for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
- Domain dm = unindexDomain.getValue();
- dm.setIndexChanged(false);
- }
- }
-
-
- for (Map.Entry<String, Domain> entry : collapsedDomainListSorted.entrySet()) {
- if (entry.getValue().getName().equals(domainToUnCollapse)) {
- colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- domainToInsert = entry.getValue();
- collapsedDomainList.remove(entry.getKey());
- break;
- }
- }
-
- domainstoUpd.add(domainToInsert);
-
- for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
- System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
-
- int lastKeyCol = -1;
- for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
- int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- if (currcol < colToUnCollapse) {
- for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
- if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
- lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
- break;
- }
- }
- } else {
- String newKey = "0"+String.valueOf(lastKeyCol+1);
- if (currcol == colToUnCollapse) {
- updateDomains.put(newKey, domainToInsert);
- ++lastKeyCol;
- } else {
- for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
- if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(newKey, currDomainsEnt.getValue());
- domainstoUpd.add(currDomainsEnt.getValue());
- ++lastKeyCol;
- break;
- }
- }
- }
-
- }
- }
-
- setNumberofColsofDomains(getNumberofColsofDomains()+1);
- setDomainRowCol(updateDomains);
- setCollapsedDomains(collapsedDomainList);
-
- for (Map.Entry<String, Domain> e : updateDomains.entrySet())
- System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
-
- for (int i = 0; i < domainstoUpd.size(); i++) {
- Domain d = domainstoUpd.get(i);
- double newX = 0.0;
- if (i+1 < domainstoUpd.size())
- newX = domainstoUpd.get(i+1).getP().getX();
- else
- newX = domainstoUpd.get(i).getP().getX()+32;
-
- if (d.getName().equals("Datacenter"))
- newX+= 2;
- d.setDomainToLayoutWd(newX);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- }
-
- computeDomainPositions();
- return this;
-
- }
-
-
-
- public Layout uncollapseDomain(String domainToCollapse) {
- Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
- Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
- Map<String, Domain> collapsedDomainList = getCollapsedDomains();
- Map<String, Domain> collapsedDomainListSorted = new TreeMap<String, Domain>(collapsedDomainList);
-
- List<Domain> domainstoUpd = new ArrayList<Domain>();
-
-
- for (Map.Entry<String, Domain> entry : collapsedDomainListSorted.entrySet()) {
- if (entry.getValue().getName().equals(domainToCollapse)) {
- if (currentDomainsSorted != null) {
- int colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- for (Map.Entry<String, Domain> curr : currentDomainsSorted.entrySet()) {
- if (Character.getNumericValue(curr.getKey().toCharArray()[1]) < colToUnCollapse) {
- updateDomains.put(curr.getKey(),curr.getValue());
- } else {
- updateDomains.put("0"+String.valueOf(Integer.parseInt(curr.getKey())+1),curr.getValue());
- domainstoUpd.add(curr.getValue());
- }
- }
- }
- updateDomains.put(entry.getKey(), entry.getValue());
- collapsedDomainList.remove(entry.getKey());
- break;
-
- }
- }
- setNumberofColsofDomains(getNumberofColsofDomains()+1);
- setDomainRowCol(updateDomains);
- setCollapsedDomains(collapsedDomainList);
-
- for (Map.Entry<String, Domain> e : updateDomains.entrySet())
- System.out.println("Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
-
-
- for (int i = 0; i < domainstoUpd.size(); i++) {
- Domain d = domainstoUpd.get(i);
- double newX = 0.0;
- if (i+1 < domainstoUpd.size())
- newX = domainstoUpd.get(i+1).getP().getX();
- else
- newX = domainstoUpd.get(i).getP().getX()+38;
-
- if (d.getName().equals("Datacenter"))
- newX+= 5;
- d.setDomainToLayoutWd(newX);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- }
-
- computeDomainPositions();
- return this;
- }
-
- public Layout uncollapseDomainNew(String domainToUnCollapse) {
- Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
- Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
- Map<String, Domain> collapsedDomainList = getCollapsedDomains();
- List<Domain> domainstoUpd = new ArrayList<Domain>();
-
- //nline
- List<Domain> collapsedDomainNewLL = getCollapsedDomainsNewList();
-
- int colToUnCollapse = 99;
-
- Domain domainToInsert = null;
-
- //nline
- if (collapsedDomainNewLL.size() == 0) {
- for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
- Domain dm = unindexDomain.getValue();
- dm.setIndexChanged(false);
- }
- }
-
-
- for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
- if (entry.getValue().getName().equals(domainToUnCollapse)) {
- colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- domainToInsert = entry.getValue();
- collapsedDomainList.remove(entry.getKey());
- //nline
- collapsedDomainNewLL.remove(entry.getValue());
- break;
- }
- }
-
- domainstoUpd.add(domainToInsert);
-
- for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
- System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
-
- int lastKeyCol = -1;
- for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
- int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- if (currcol < colToUnCollapse) {
- for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
- if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
- lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
- break;
- }
- }
- } else {
- String newKey = "0"+String.valueOf(lastKeyCol+1);
- if (currcol == colToUnCollapse) {
- updateDomains.put(newKey, domainToInsert);
- ++lastKeyCol;
- } else {
- for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
- if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(newKey, currDomainsEnt.getValue());
- domainstoUpd.add(currDomainsEnt.getValue());
- ++lastKeyCol;
- break;
- }
- }
- }
-
- }
- }
-
- setNumberofColsofDomains(getNumberofColsofDomains()+1);
- setDomainRowCol(updateDomains);
-
- for (Map.Entry<String, Domain> e : updateDomains.entrySet())
- System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
-
-
-
- double currDistFromLftMargin = 11.0;
- for (Map.Entry<String,Domain> cd : updateDomains.entrySet()) {
- Domain d = cd.getValue();
- double accountPlus = accountForPlusSpaceBefore(d);
- d.setDomainToLayoutWd(currDistFromLftMargin+accountPlus);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- currDistFromLftMargin += d.computeSize().getWidth()+2;
-
- }
-
- //nline
- updatePlusPosition(collapsedDomainNewLL, updateDomains);
-
- //order changed
- setCollapsedDomains(collapsedDomainList);
-
- //nline
- setCollapsedDomainsNewList(collapsedDomainNewLL);
-
-
- computeDomainPositionsModified();
- return this;
-
- }
-
- public Layout uncollapseDomainNew1(String domainToUnCollapse) {
-
- if(domainToUnCollapse == null || domainToUnCollapse.isEmpty())
- return null;
-
- Map<String, Domain> currentDomainsSorted = new TreeMap<String,Domain>(domainRowCol);
- Map<String, Domain> updateDomains = new TreeMap<String,Domain>();
- Map<String, Domain> collapsedDomainList = getCollapsedDomains();
- List<Domain> domainstoUpd = new ArrayList<Domain>();
-
- //nline
- List<Domain> collapsedDomainNewLL = getCollapsedDomainsNewList();
-
- int colToUnCollapse = 99;
-
- Domain domainToInsert = null;
-
- //nline
- if (collapsedDomainNewLL.size() == 0) {
- for (Map.Entry<String, Domain> unindexDomain : originalDomainRowCol.entrySet()) {
- Domain dm = unindexDomain.getValue();
- dm.setIndexChanged(false);
- }
- }
-
-
- for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
- if (entry.getValue().getName().equals(domainToUnCollapse)) {
- colToUnCollapse = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- domainToInsert = entry.getValue();
- collapsedDomainList.remove(entry.getKey());
- //nline
- collapsedDomainNewLL.remove(entry.getValue());
- break;
- }
- }
-
- domainstoUpd.add(domainToInsert);
-
- for (Map.Entry<String, Domain> e : originalDomainRowCol.entrySet())
- System.out.println("Original key value"+e.getKey()+":"+e.getValue().getName());
-
- int lastKeyCol = -1;
- for (Map.Entry<String, Domain> entry : originalDomainRowCol.entrySet()) {
- int currcol = Character.getNumericValue(entry.getKey().toCharArray()[1]);
- if (currcol < colToUnCollapse) {
- for (Map.Entry<String, Domain> currDomainsEntry : currentDomainsSorted.entrySet()) {
- if (currDomainsEntry.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(currDomainsEntry.getKey(), currDomainsEntry.getValue());
- lastKeyCol = Character.getNumericValue(currDomainsEntry.getKey().toCharArray()[1]);
- break;
- }
- }
- } else {
- String newKey = "0"+String.valueOf(lastKeyCol+1);
- if (currcol == colToUnCollapse) {
- updateDomains.put(newKey, domainToInsert);
- ++lastKeyCol;
- } else {
- for (Map.Entry<String, Domain> currDomainsEnt : currentDomainsSorted.entrySet()) {
- if (currDomainsEnt.getValue().getName().equals(entry.getValue().getName())) {
- updateDomains.put(newKey, currDomainsEnt.getValue());
- domainstoUpd.add(currDomainsEnt.getValue());
- ++lastKeyCol;
- break;
- }
- }
- }
-
- }
- }
-
- setNumberofColsofDomains(getNumberofColsofDomains()+1);
- setDomainRowCol(updateDomains);
-
- for (Map.Entry<String, Domain> e : updateDomains.entrySet())
- System.out.println("me Updatedomains key value"+e.getKey()+":"+e.getValue().getName());
-
-
-
-
- double currDistFromLftM = 11.0;
-
- boolean isDisplayed;
- for (Map.Entry<String,Domain> orgEntry : originalDomainRowCol.entrySet()) {
- isDisplayed = false;
- for (Map.Entry<String,Domain> cd : updateDomains.entrySet()) {
- if (cd.getValue().getName().equals(orgEntry.getValue().getName())) {
- Domain d = cd.getValue();
- d.setDomainToLayoutWd(currDistFromLftM);
- d.computeConatinerPositions();
- for (Map.Entry<String, Container> entry1 : d.getContainerRowCol().entrySet()) {
- Container c = entry1.getValue();
- c.computeSize();
- c.computeElementPositions();
- if (c.getContainerRowCol() != null) {
- for (Map.Entry<String, Container> entryInner : c.getContainerRowCol().entrySet()) {
- Container inner = entryInner.getValue();
- inner.computeElementPositions();
- }
- }
- }
- currDistFromLftM += d.computeSize().getWidth()+1;
- isDisplayed = true;
- break;
- }
- }
-
- if (!isDisplayed) {
- Domain myCollapsed = orgEntry.getValue();
- myCollapsed.setNewXafterColl(currDistFromLftM);
- currDistFromLftM += 4;
- }
- }
-
-
- //order changed
- setCollapsedDomains(collapsedDomainList);
-
- //nline
- setCollapsedDomainsNewList(collapsedDomainNewLL);
-
-
- computeDomainPositionsModified();
- return this;
-
- }
-
- private void updatePlusPosition(List<Domain> collapsedDNewL, Map<String, Domain> displayedDomainMap) {
- List<Domain> copyCollapseList = new ArrayList<Domain>();
-
- for (Domain copyCollapse : collapsedDNewL) {
- copyCollapseList.add(copyCollapse);
- }
-
- int orgColofCollapsed = -1;
- int orgColofDisplayed = -1;
- int orgColofDisplayedOtherPlus = -1;
- for (Domain plus : collapsedDNewL) {
- double distOfCollFrmLft = 0.0;
- for (Map.Entry<String, Domain> colCheck : originalDomainRowCol.entrySet()) {
- if (colCheck.getValue().getName().equals(plus.getName())) {
- orgColofCollapsed = Character.getNumericValue(colCheck.getKey().toCharArray()[1]);
- break;
- }
- }
- for (Map.Entry<String, Domain> displayedEntry : displayedDomainMap.entrySet()) {
-
- for (Map.Entry<String, Domain> colCheck1 : originalDomainRowCol.entrySet()) {
- if (colCheck1.getValue().getName().equals(displayedEntry.getValue().getName())) {
- orgColofDisplayed = Character.getNumericValue(colCheck1.getKey().toCharArray()[1]);
- break;
- }
- }
- if (orgColofDisplayed < orgColofCollapsed) {
- distOfCollFrmLft+= displayedEntry.getValue().computeSize().getWidth();
-
- }
-
- }
-
- for (Domain collp : copyCollapseList) {
- if (!collp.getName().equals(plus.getName())) {
- for (Map.Entry<String, Domain> colCheck2 : originalDomainRowCol.entrySet()) {
- if (colCheck2.getValue().getName().equals(collp.getName())) {
- orgColofDisplayedOtherPlus = Character.getNumericValue(colCheck2.getKey().toCharArray()[1]);
- break;
- }
- }
- if (orgColofDisplayedOtherPlus < orgColofCollapsed) {
- distOfCollFrmLft+=3.0;
- }
- }
- }
-
- plus.setNewXafterColl(distOfCollFrmLft+1.5);
-
-
- }
- }
-
-
- private double accountForPlusSpaceBefore(Domain d) {
-
- int orgColofCollapsed = 0;
- int orgColofDisplayed = 0;
- double distFromLftM = 0.0;
-
- for (Map.Entry<String, Domain> colCheckk : originalDomainRowCol.entrySet()) {
- if (colCheckk.getValue().getName().equals(d.getName())) {
- orgColofDisplayed = Character.getNumericValue(colCheckk.getKey().toCharArray()[1]);
- break;
- }
- }
-
- for (Domain collapsed : getCollapsedDomainsNewList()) {
- for (Map.Entry<String, Domain> colCheck : originalDomainRowCol.entrySet()) {
- if (colCheck.getValue().getName().equals(collapsed.getName())) {
- orgColofCollapsed = Character.getNumericValue(colCheck.getKey().toCharArray()[1]);
- break;
- }
- }
-
- if (orgColofCollapsed < orgColofDisplayed) {
- distFromLftM+= 2;
- }
- }
- return distFromLftM;
-
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java
deleted file mode 100644
index 5a1a8640..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/AuditLog.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.logging.aspect;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface AuditLog {
- String value() default "";
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java
deleted file mode 100644
index 5264c70b..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/aspect/EELFLoggerAdvice.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.logging.aspect;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.core.logging.format.AuditLogFormatter;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.service.AppService;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.util.SystemProperties.SecurityEventTypeEnum;
-import org.slf4j.MDC;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.att.eelf.configuration.Configuration;
-
-@org.springframework.context.annotation.Configuration
-public class EELFLoggerAdvice {
-
- @Autowired
- AppService appService;
-
- EELFLoggerDelegate adviceLogger = EELFLoggerDelegate.getLogger(EELFLoggerAdvice.class);
-
- //DateTime Format according to the ECOMP Application Logging Guidelines.
- private static final SimpleDateFormat ecompLogDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
-
- public Object[] before(SecurityEventTypeEnum securityEventType, Object[] args, Object[] passOnArgs) {
- try {
- String className = "";
- if (passOnArgs[0]!=null) {
- className = passOnArgs[0].toString();
- }
-
- String methodName = "";
- if (passOnArgs[1]!=null) {
- methodName = passOnArgs[1].toString();
- }
-
- String appName = appService.getDefaultAppName();
- if (appName==null || appName=="") {
- appName = SystemProperties.SDK_NAME;
- }
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
-
- //Initialize Request defaults only for controller methods.
- MDC.put(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, getCurrentDateTimeUTC());
- MDC.put(SystemProperties.TARGET_ENTITY, appName + "_BE");
- MDC.put(SystemProperties.TARGET_SERVICE_NAME, methodName);
- if (securityEventType!=null) {
- MDC.put(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, getCurrentDateTimeUTC());
- HttpServletRequest req = null;
- if (args[0]!=null && args[0] instanceof HttpServletRequest ) {
- req = (HttpServletRequest)args[0];
- logger.setRequestBasedDefaultsIntoGlobalLoggingContext(req, appName);
- }
- }
- logger.debug(EELFLoggerDelegate.debugLogger, (methodName +" was invoked."));
- } catch(Exception e) {
- adviceLogger.error(EELFLoggerDelegate.errorLogger, "Exception occurred in EELFLoggerAdvice.before() method. Details: " + e.getMessage());
- }
-
- return new Object[] {""};
- }
-
- public void after(SecurityEventTypeEnum securityEventType, String result, Object[] args, Object[] returnArgs, Object[] passOnArgs) {
- try {
- String className = "";
- if (passOnArgs[0]!=null) {
- className = passOnArgs[0].toString();
- }
-
- String methodName = "";
- if (passOnArgs[1]!=null) {
- methodName = passOnArgs[1].toString();
- }
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
-
- String appName = appService.getDefaultAppName();
- if (appName==null || appName=="") {
- appName = SystemProperties.SDK_NAME;
- }
-
- if (MDC.get(SystemProperties.TARGET_SERVICE_NAME) == null || MDC.get(SystemProperties.TARGET_SERVICE_NAME) == "") {
- MDC.put(SystemProperties.TARGET_SERVICE_NAME, methodName);
- }
-
- if (MDC.get(SystemProperties.TARGET_ENTITY) == null || MDC.get(SystemProperties.TARGET_ENTITY) == "") {
- MDC.put(SystemProperties.TARGET_ENTITY, appName + "_BE");
- }
-
- MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, MDC.get(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP));
- MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
- this.calculateDateTimeDifference(MDC.get(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP), MDC.get(SystemProperties.METRICSLOG_END_TIMESTAMP));
-
- logger.info(EELFLoggerDelegate.metricsLogger, methodName + " operation is completed.");
- logger.debug(EELFLoggerDelegate.debugLogger, "Finished executing " + methodName + ".");
-
- if (securityEventType!=null) {
-
- MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, MDC.get(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP));
- MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, getCurrentDateTimeUTC());
- this.calculateDateTimeDifference(MDC.get(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP), MDC.get(SystemProperties.AUDITLOG_END_TIMESTAMP));
-
- this.logSecurityMessage(logger, securityEventType, result, methodName);
-
- //clear when finishes audit logging
- MDC.remove(Configuration.MDC_KEY_REQUEST_ID);
- MDC.remove(SystemProperties.PARTNER_NAME);
- MDC.remove(SystemProperties.MDC_LOGIN_ID);
- MDC.remove(SystemProperties.PROTOCOL);
- MDC.remove(SystemProperties.FULL_URL);
- MDC.remove(Configuration.MDC_SERVICE_NAME);
- MDC.remove(SystemProperties.RESPONSE_CODE);
- MDC.remove(SystemProperties.STATUS_CODE);
- MDC.remove(className + methodName + SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
- MDC.remove(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP);
- MDC.remove(SystemProperties.AUDITLOG_END_TIMESTAMP);
- }
-
- MDC.remove(className + methodName + SystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
- MDC.remove(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP);
- MDC.remove(SystemProperties.METRICSLOG_END_TIMESTAMP);
- MDC.remove(SystemProperties.MDC_TIMER);
- MDC.remove(SystemProperties.TARGET_ENTITY);
- MDC.remove(SystemProperties.TARGET_SERVICE_NAME);
- } catch(Exception e) {
- adviceLogger.error(EELFLoggerDelegate.errorLogger, "Exception occurred in EELFLoggerAdvice.after() method. Details: " + e.getMessage());
- }
- }
-
- private void logSecurityMessage(EELFLoggerDelegate logger, SecurityEventTypeEnum securityEventType, String result, String restMethod) {
- StringBuilder additionalInfoAppender = new StringBuilder();
- String auditMessage = "";
-
- additionalInfoAppender.append(String.format("%s request was received.", restMethod));
-
- //Status code
- MDC.put(SystemProperties.STATUS_CODE, result);
-
- String fullURL = MDC.get(SystemProperties.FULL_URL);
- if (fullURL!=null && fullURL!="") {
- additionalInfoAppender.append(" Request-URL:" + MDC.get(SystemProperties.FULL_URL));
- }
-
- auditMessage = AuditLogFormatter.getInstance().createMessage( MDC.get(SystemProperties.PROTOCOL),
- securityEventType.name(),
- MDC.get(SystemProperties.MDC_LOGIN_ID),
- additionalInfoAppender.toString());
-
- logger.info(EELFLoggerDelegate.auditLogger, auditMessage);
- }
-
- private String getCurrentDateTimeUTC() {
- String currentDateTime = ecompLogDateFormat.format(new Date());
- return currentDateTime;
- }
-
- private void calculateDateTimeDifference(String beginDateTime, String endDateTime) {
- if (beginDateTime!=null && endDateTime!=null) {
- try {
- Date beginDate = ecompLogDateFormat.parse(beginDateTime);
- Date endDate = ecompLogDateFormat.parse(endDateTime);
- String timeDifference = String.format("%d ms", endDate.getTime() - beginDate.getTime());
- MDC.put(SystemProperties.MDC_TIMER, timeDifference);
- } catch(Exception e) {
- adviceLogger.error(EELFLoggerDelegate.errorLogger, "Exception occurred in EELFLoggerAdvice.calculateDateTimeDifference() method. Details: " + e.getMessage());
- }
- }
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java
deleted file mode 100644
index 7cf5ee40..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/logging/logic/EELFLoggerDelegate.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.logging.logic;
-
-import static com.att.eelf.configuration.Configuration.MDC_ALERT_SEVERITY;
-import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;
-import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
-import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID;
-import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
-
-import java.net.InetAddress;
-import java.text.MessageFormat;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
-import org.openecomp.portalsdk.core.logging.format.AppMessagesEnum;
-import org.openecomp.portalsdk.core.logging.format.ErrorSeverityEnum;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.web.support.UserUtils;
-import org.slf4j.MDC;
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-import com.att.eelf.configuration.SLF4jWrapper;
-
-public class EELFLoggerDelegate extends SLF4jWrapper implements EELFLogger {
-
- public static EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger();
- public static EELFLogger applicationLogger = EELFManager.getInstance().getApplicationLogger();
- public static EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
- public static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
- public static EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger();
- private String className;
- private static ConcurrentMap<String, EELFLoggerDelegate> classMap = new ConcurrentHashMap<String, EELFLoggerDelegate>();
-
- public EELFLoggerDelegate(String _className) {
- super(_className);
- className = _className;
- }
-
- public static EELFLoggerDelegate getLogger(Class<?> clazz) {
-
- String className = clazz.getName();
- EELFLoggerDelegate delegate = classMap.get(className);
- if (delegate == null) {
- delegate = new EELFLoggerDelegate(className);
- classMap.put(className, delegate);
- }
-
- return delegate;
-
- }
-
- public static EELFLoggerDelegate getLogger(String className) {
- if (className==null || className=="") {
- className = EELFLoggerDelegate.class.getName();
- }
- EELFLoggerDelegate delegate = classMap.get(className);
- if (delegate == null) {
- delegate = new EELFLoggerDelegate(className);
- classMap.put(className, delegate);
- }
-
- return delegate;
- }
-
- public void debug(EELFLogger logger, String msg) {
- if (logger.isDebugEnabled()) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.debug(msg);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
- }
-
- public void debug(EELFLogger logger, String msg, Object... arguments) {
- if (logger.isDebugEnabled()) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.debug(msg, arguments);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
- }
-
- public void debug(EELFLogger logger, String msg, Throwable th) {
- if (logger.isDebugEnabled()) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.debug(msg, th);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
- }
-
- // does not solve the superfluous overhead of string append
- public void info(EELFLogger logger, String msg) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.info(msg);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void info(EELFLogger logger, String msg, Object... arguments) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.info(msg, arguments);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void info(EELFLogger logger, String msg, Throwable th) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.info(msg, th);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void warn(EELFLogger logger, String msg) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.warn(msg);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void warn(EELFLogger logger, String msg, Object... arguments) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.warn(msg, arguments);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void warn(EELFLogger logger, String msg, Throwable th) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.warn(msg, th);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void error(EELFLogger logger, String msg) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.error(msg);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void error(EELFLogger logger, String msg, Object... arguments) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.warn(msg, arguments);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void error(EELFLogger logger, String msg, Throwable th) {
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.warn(msg, th);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void error(EELFLogger logger, String msg, AlarmSeverityEnum severtiy) {
- MDC.put(MDC_ALERT_SEVERITY, severtiy.name());
- MDC.put(SystemProperties.MDC_CLASS_NAME, className);
- logger.error(msg);
- MDC.remove(MDC_ALERT_SEVERITY);
- MDC.remove(SystemProperties.MDC_CLASS_NAME);
- }
-
- public void init() {
- // Initialize the logger context
- setGlobalLoggingContext();
-
- String msg = "############################ Logging is started. ############################";
- info(applicationLogger, msg);
- error(errorLogger, msg);
- info(auditLogger, msg);
- info(metricsLogger, msg);
- debug(debugLogger, msg);
- info(errorLogger, "Successfully initialized the Global logger context.");
- }
-
- public void logEcompError(AppMessagesEnum epMessageEnum, String... param) {
- try {
- AlarmSeverityEnum alarmSeverityEnum = epMessageEnum.getAlarmSeverity();
- ErrorSeverityEnum errorSeverityEnum = epMessageEnum.getErrorSeverity();
-
- MDC.put(MDC_ALERT_SEVERITY, alarmSeverityEnum.name());
- MDC.put("ErrorCode", epMessageEnum.getErrorCode());
- MDC.put("ErrorDescription", epMessageEnum.getErrorDescription());
-
- String resolution = this.formatMessage(epMessageEnum.getDetails() + " " + epMessageEnum.getResolution(), (Object[]) param);
- if (errorSeverityEnum == ErrorSeverityEnum.WARN) {
- errorLogger.warn(resolution);
- } else if(errorSeverityEnum == ErrorSeverityEnum.INFO) {
- errorLogger.info(resolution);
- } else {
- errorLogger.error(resolution);
- }
- } catch(Exception e) {
- errorLogger.error("Failed to log the error code. Details: " + UserUtils.getStackTrace(e));
- } finally {
- MDC.remove("ErrorCode");
- MDC.remove("ErrorDescription");
- MDC.remove(MDC_ALERT_SEVERITY);
- }
- }
-
- private String formatMessage(String message, Object...args) {
- StringBuilder sbFormattedMessage = new StringBuilder();
- if (args!=null && args.length>0 && message!=null && message != "") {
- MessageFormat mf = new MessageFormat(message);
- sbFormattedMessage.append(mf.format(args));
- } else {
- sbFormattedMessage.append(message);
- }
-
- return sbFormattedMessage.toString();
- }
-
- /**
- * Loads all the default logging fields into the MDC context.
- */
- private void setGlobalLoggingContext() {
- MDC.put(MDC_SERVICE_INSTANCE_ID, "");
- MDC.put(MDC_ALERT_SEVERITY, AlarmSeverityEnum.INFORMATIONAL.toString());
- try {
- MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
- MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
- MDC.put(MDC_INSTANCE_UUID, SystemProperties.getProperty(SystemProperties.INSTANCE_UUID));
- } catch (Exception e) {
- }
- }
-
- public static void mdcPut(String key, String value) {
- MDC.put(key, value);
- }
-
- public static String mdcGet(String key) {
- return MDC.get(key);
- }
-
- public static void mdcRemove(String key) {
- MDC.remove(key);
- }
-
- /**
- * Loads the RequestId/TransactionId into the MDC which it should be receiving
- * with an each incoming REST API request. Also, configures few other request
- * based logging fields into the MDC context.
- * @param req
- */
- public void setRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest req, String appName) {
- //Load the default fields
- setGlobalLoggingContext();
-
- //Load the request based fields
- if (req!=null) {
- //Load the Request into MDC context.
- String requestId = UserUtils.getRequestId(req);
- MDC.put(MDC_KEY_REQUEST_ID, requestId);
-
- //Load user agent into MDC context, if available.
- String accessingClient = "Unknown";
- accessingClient = req.getHeader(SystemProperties.USERAGENT_NAME);
- if (accessingClient!=null && accessingClient!="" &&
- (accessingClient.contains("Mozilla") || accessingClient.contains("Chrome") || accessingClient.contains("Safari"))) {
- accessingClient = appName + "_FE";
- }
- MDC.put(SystemProperties.PARTNER_NAME, accessingClient);
-
- //Protocol, Rest URL & Rest Path
- String restURL = "";
- MDC.put(SystemProperties.FULL_URL, SystemProperties.UNKNOWN);
- MDC.put(SystemProperties.PROTOCOL, SystemProperties.HTTP);
- restURL = UserUtils.getFullURL(req);
- if (restURL!=null && restURL!="") {
- MDC.put(SystemProperties.FULL_URL, restURL);
- if (restURL.toLowerCase().contains("https")) {
- MDC.put(SystemProperties.PROTOCOL, SystemProperties.HTTPS);
- }
- }
-
- //Rest Path
- MDC.put(MDC_SERVICE_NAME, req.getServletPath());
-
- //Client IPAddress i.e. IPAddress of the remote host who is making this request.
- String clientIPAddress = "";
- clientIPAddress = req.getHeader("X-FORWARDED-FOR");
- if (clientIPAddress == null) {
- clientIPAddress = req.getRemoteAddr();
- }
- MDC.put(SystemProperties.CLIENT_IP_ADDRESS, clientIPAddress);
-
- //Load loginId into MDC context.
- MDC.put(SystemProperties.MDC_LOGIN_ID, "Unknown");
- String loginId = "";
- try {
- loginId = UserUtils.getUserIdFromCookie(req);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if (loginId == null || loginId == "") {
- User user = UserUtils.getUserSession(req);
- if (user != null) {
- loginId = user.getLoginId();
- }
- }
-
- if (loginId!=null && loginId!="") {
- MDC.put(SystemProperties.MDC_LOGIN_ID, loginId);
- }
- }
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java
deleted file mode 100644
index 948b635f..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementLinkService.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.util.YamlUtils;
-
-
-
-public class ElementLinkService {
-
-
- public String main1(String[] args) throws Exception{
- String filePath;
- if(args[0].startsWith("custom")){
- filePath = SystemProperties.getProperty("customCallFlow_path");
- }else{
- filePath = SystemProperties.getProperty("element_map_file_path") + File.separator;
- }
-
- String callFlowBusinessYml = "";
- String callFlowStep = "";
-
- if(args != null && args.length > 0 ) {
-
- if( args[0] != null) {
- callFlowBusinessYml = args[0] + ".yml";
- }
-
- if( args[1] != null) {
- callFlowStep = args[1];
- }
- }
-
-
- ElementLinkService mapper = new ElementLinkService();
-
- return mapper.createLinkFile(filePath, callFlowBusinessYml, callFlowStep);
- }
-
- public String main2(String[] args) throws Exception{
-
- String filePath = SystemProperties.getProperty("element_map_file_path") + File.separator;
- String callFlowBusinessYml = "";
- String callFlowStep = "";
-
- if(args != null && args.length > 0 ) {
-
- if( args[0] != null) {
- callFlowBusinessYml = args[0] + "-Override.yml";
- }
-
- if( args[1] != null) {
- callFlowStep = args[1];
- }
- }
-
-
- ElementLinkService mapper = new ElementLinkService();
-
- return mapper.createLinkFileAdditional(filePath, callFlowBusinessYml, callFlowStep);
- }
-
-
- public static void main(String[] args) throws Exception{
-
- String filePath = "C:\\Users\\statta\\git\\D2Platform\\war\\WEB-INF\\resources\\trisim_files";
- String callFlowBusinessYml = "call_flow_hc-origination-termination-to-volteue-3.3.16-Override.yml";
-
-
- ElementLinkService mapper = new ElementLinkService();
- System.out.print(mapper.createLinkFileAdditional(filePath, callFlowBusinessYml, "Step_2"));
- }
-
- @SuppressWarnings("unchecked")
- protected String createLinkFile(String resourceFilePath, String callFLowBsFileName, String callFlowStep) throws Exception {
-
- Map<String, Object> callFlowBs = YamlUtils.readYamlFile(resourceFilePath, callFLowBsFileName);
-
- List<Map<String,Object>> callSteps = (List<Map<String,Object>>) callFlowBs.get("callSequenceSteps");
- String callFlowName = (String) callFlowBs.get("shortName");
- return addLinks( resourceFilePath, callFlowName, callSteps, callFlowStep);
-
-
- }
-
- @SuppressWarnings("unchecked")
- protected String createLinkFileAdditional(String resourceFilePath, String callFLowBsFileName, String callFlowStep) throws Exception {
-
- Map<String, Object> callFlowBs;
-
- try{
- callFlowBs = YamlUtils.readYamlFile(resourceFilePath, callFLowBsFileName);
-
- List<Map<String,Object>> callSteps = (List<Map<String,Object>>) callFlowBs.get("callSequenceSteps");
- String callFlowName = (String) callFlowBs.get("shortName");
- return addLinksAdditional( resourceFilePath, callFlowName, callSteps, callFlowStep);
-
- } catch (Exception e) {
-
- return "";
- }
-
-
- }
-
- @SuppressWarnings("unchecked")
- protected String addLinks(String filePath, String callFlowName,
- List<Map<String, Object>> callSteps, String callFlowStep) throws IOException {
-
- Map<String,List<String>> checkDuplicateMap = new HashMap<String,List<String>>();
-
- for(Map<String,Object> callStep : callSteps) {
-
- if(((String)callStep.get("name")).split(":")[0].trim().replace(" ", "_").equals(callFlowStep)) {
-
- List<Map<String,Object>> links = new ArrayList<Map<String,Object>>();
-
- List<Map<String,Object>> subSteps = (List<Map<String,Object>>)callStep.get("subSteps");
-
- for(Map<String,Object> subStep : subSteps) {
- Map<String,Object> link = new HashMap<String,Object>();
-
- String source = (String) subStep.get("source_tosca_id");
- String destination = (String) subStep.get("destination_tosca_id");
-
- if((checkDuplicateMap.get(source) == null || checkDuplicateMap.get(source).isEmpty() || !checkDuplicateMap.get(source).contains(destination)) && !source.equals(destination)) {
- if(checkDuplicateMap.get(destination) == null) {
- List<String> toscaList = new ArrayList<String>();
- checkDuplicateMap.put(destination, toscaList);
- }
-
- if(checkDuplicateMap.get(source) == null) {
- List<String> toscaList = new ArrayList<String>();
- checkDuplicateMap.put(source, toscaList);
- }
-
-
- List<String> toscaSourceList = checkDuplicateMap.get(destination);
- toscaSourceList.add(source);
-
- List<String> toscaDestinationList = checkDuplicateMap.get(source);
- toscaDestinationList.add(destination);
-
- link.put("s", source);
- link.put("d", destination);
- links.add(link);
-
- }
-
- }
-
- Map<String,Object> callFlowUI = new HashMap<String,Object>();
- callFlowUI.put("linkList", links);
-
- return YamlUtils.returnYaml(callFlowUI);
-
- }
-
-
- }
- return "";
- }
-
- protected String addLinksAdditional(String filePath, String callFlowName,
- List<Map<String, Object>> callSteps, String callFlowStep) throws IOException {
-
-
- for(Map<String,Object> callStep : callSteps) {
-
- if(((String)callStep.get("name")).split(":")[0].trim().replace(" ", "_").equals(callFlowStep)) {
-
- Map<String,Object> callFlowUI = new HashMap<String,Object>();
- try{
- List<Map<String, Object>> links = addLinkVertices(callStep);
- callFlowUI.put("linkList", links); }
- catch(Exception e) {}
- try{
- List<String> activeIds = addActiveNodes(callStep);
- callFlowUI.put("activeIds", activeIds);}
- catch(Exception e) {}
- try{
- List<Map<String, Object>> disconnectLinks = addDisconnectLinks(callStep);
- callFlowUI.put("disconnectLinks", disconnectLinks); }
- catch(Exception e) {}
-
- return YamlUtils.returnYaml(callFlowUI);
- }
- }
-
- return "";
- }
-
- @SuppressWarnings("unchecked")
- List<String> addActiveNodes(Map<String, Object> callStep) {
-
- List<String> activeIds = (List<String>)callStep.get("activeIds");
-
- return activeIds;
- }
-
- @SuppressWarnings("unchecked")
- List<Map<String,Object>> addDisconnectLinks(Map<String, Object> callStep) {
-
- List<Map<String,Object>> disconnectLinks = (List<Map<String,Object>>)callStep.get("disconnectLinks");
-
- return disconnectLinks;
- }
-
- @SuppressWarnings("unchecked")
- List<Map<String, Object>> addLinkVertices(Map<String, Object> callStep) {
- List<Map<String,Object>> links = new ArrayList<Map<String,Object>>();
-
- List<Map<String,Object>> vertices = (List<Map<String,Object>>)callStep.get("vertices");
-
- for(int i=0; i< vertices.size()-1;i++) {
- Map<String,Object> vertex = (Map<String,Object>) vertices.get(i);
- Map<String,Object> vertexNext = (Map<String,Object>) vertices.get(i+1);
-
- Integer sourceX = (Integer) vertex.get("x");
- Integer sourceY = (Integer) vertex.get("y");
- String sourceD = (String) vertex.get("D");
- String sourceL = (vertex.get("L") != null) ? (String) vertex.get("L") : "-";
-
- if(sourceX == -999) // there is a break in the linkage
- continue;
-
- Integer destinationX = (Integer) vertexNext.get("x");
- Integer destinationY = (Integer) vertexNext.get("y");
- String destinationD = (String) vertexNext.get("D");
-
- if(destinationX == -999) // there is a break in the linkage
- continue;
-
- Map<String,Object> link = new HashMap<String,Object>();
-
- link.put("s", sourceX + "," + sourceY +","+sourceD + "," + sourceL);
- link.put("d", destinationX + "," + destinationY +"," + destinationD);
- links.add(link);
- }
- return links;
- }
-}
-
-
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java
deleted file mode 100644
index d88213f3..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/ElementMapService.java
+++ /dev/null
@@ -1,915 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.commons.lang.StringUtils;
-import org.openecomp.portalsdk.core.domain.support.Container;
-import org.openecomp.portalsdk.core.domain.support.Domain;
-import org.openecomp.portalsdk.core.domain.support.Element;
-import org.openecomp.portalsdk.core.domain.support.ElementDetails;
-import org.openecomp.portalsdk.core.domain.support.Layout;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.util.YamlUtils;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.nodes.Tag;
-import org.yaml.snakeyaml.representer.Representer;
-
-public class ElementMapService {
-
- public String convertToYAML(Layout layout) throws Exception{
- Map<String,Domain> resultDomain= layout.domainRowCol;
- Map<String,List<Domain>> domainMap = new HashMap<String, List<Domain>>();
- List<Domain> domainList = new ArrayList<Domain>();
- String pathToImg = SystemProperties.getProperty("element_map_icon_path"); //"static/img/map/icons/";
- for (Domain d : resultDomain.values()) {
-
- d.setWidth(10*d.computeSize().getWidth());
- d.setHeight(10*d.computeSize().getHeight());
- d.setLeft(10*d.getP().getX());
- d.setTop(10*d.getP().getY());
-
-
- List<Container> containerList = new ArrayList<Container>();
- for (Container c : d.getContainerRowCol().values()) {
- c.setWidth(10*c.computeSize().getWidth());
- c.setHeight(10*c.computeSize().getHeight());
- c.setLeft(10*c.getP().getX());
- c.setTop(10*c.getP().getY());
- Element ue = (Element)c.getElementRowCol().values().toArray()[0];
- if (ue.getName().equals("ue1") || ue.getName().equals("ue2") || ue.getName().equals("ue3") ||
- ue.getName().equals("ue4") || ue.getName().equals("ue5") || ue.getName().equals("ue6")) {
- c.setVisibilityType("invisible");
- }
-
- if (c.getContainerRowCol() != null) {
- List<Container> innerContainerList = new ArrayList<Container>();
- for (Container innerC : c.getContainerRowCol().values()) {
- innerC.setName(innerC.getName());
- innerC.setWidth(10*innerC.computeSize().getWidth());
- innerC.setHeight(10*innerC.computeSize().getHeight());
- innerC.setLeft(10*innerC.getP().getX());
- innerC.setTop(10*innerC.getP().getY());
-
- if (innerC.getElementRowCol() != null) {
- List<Element> innerContainerEList = new ArrayList<Element>();
- for (Element ele : innerC.getElementRowCol().values()) {
- ele.setWidth(10*ele.computeSize().getWidth());
- ele.setHeight(10*ele.computeSize().getHeight());
- ele.setLeft(10*ele.getP().getX());
- ele.setTop(10*ele.getP().getY()-10);
- ele.setImgFileName(pathToImg+ele.getImgFileName());
- if (ele.getBorderType().equals("V"))
- ele.setBorderType("dashed");
- else
- ele.setBorderType("solid");
-
- innerContainerEList.add(ele);
- }
- innerC.setElementList(innerContainerEList);
- }
- innerContainerList.add(innerC);
- }
- c.setInnerCList(innerContainerList);
- }
-
- if (c.getElementRowCol() != null) {
- List<Element> elementList = new ArrayList<Element>();
- for (Element e : c.getElementRowCol().values()) {
- e.setWidth(10*e.computeSize().getWidth());
- e.setHeight(10*e.computeSize().getHeight());
- e.setLeft(10*e.getP().getX());
- e.setTop(10*e.getP().getY()-10);
- e.setImgFileName(pathToImg+e.getImgFileName());
-
- if (e.getBorderType().equals("V"))
- e.setBorderType("dashed");
- else
- e.setBorderType("solid");
-
- if (e.getName().equals("ue1") || e.getName().equals("ue2") || e.getName().equals("ue3")
- || e.getName().equals("ue4") || e.getName().equals("ue5") || e.getName().equals("ue6"))
- e.setBgColor("white");
- elementList.add(e);
- }
- c.setElementList(elementList);
- }
- containerList.add(c);
- }
- d.setContainerList(containerList);
- domainList.add(d);
-
- }
- domainMap.put("domainList", domainList);
-
- List<Domain> collapsedDomains = new ArrayList<Domain>();
-
- //nline
- for (Domain collapsed : layout.getCollapsedDomainsNewList()) {
- collapsed.setWidth(10*collapsed.computeSize().getWidth());
- collapsed.setHeight(10*collapsed.computeSize().getHeight());
- collapsed.setLeft(10*collapsed.getP().getX());
- collapsed.setTop(10*collapsed.getP().getY());
- //nline
- collapsed.setNewXafterColl(10*collapsed.getNewXafterColl());
- collapsed.setYafterColl(10*collapsed.getYafterColl());
- collapsedDomains.add(collapsed);
- }
-
- domainMap.put("collapsedDomainList", collapsedDomains);
-
- Representer representer = new Representer();
- representer.addClassTag(Domain.class, Tag.MAP);
-
-
- Yaml yaml = new Yaml(representer);
- String output = yaml.dump(domainMap);
-
- return output;
-
-}
-
-
-
- public static HashMap<String, Object> toscaElementsMap = new HashMap<String, Object>();
- public static HashMap<String,Element> elementMap = new HashMap<String, Element>();
- public static HashMap<String,Element> miscElementMap = new HashMap<String, Element>();
- public static HashMap<String,Container> outercontainers = new HashMap<String, Container>();
- public static HashMap<String,Container> innercontainers = new HashMap<String, Container>();
- public static HashMap<String,Domain> domainMap = new HashMap<String, Domain>();
-
-
- static String filePath =
- SystemProperties.getProperty("element_map_file_path") ;
- static String callFlowBusinessYml = "call_flow_sip_digest.yml";
- static String networkToscaYml = null;//"NetworkMap_topology_composition.yml";
- static String networkLayoutYml = null;// "network_map_layout.yml";
-
-
- @SuppressWarnings({ "unchecked", "unused" })
- public String main1(String args[]) throws Exception{
-
-
- if(args != null && args.length > 0 ) {
-
- if( args[2] != null) {
- networkToscaYml = args[2] + ".yml";
- }
-
- if( args[3] != null) {
- networkLayoutYml = args[3] + ".yml";
- }
- }
-
- HashMap<String, Object> toscaYaml = (HashMap<String, Object>)YamlUtils.readYamlFile(filePath, networkToscaYml); //TrinityYAMLHelper.getToscaYaml();
- HashMap<String, Object> networkMapLayoutYaml = (HashMap<String, Object>)YamlUtils.readYamlFile(filePath, networkLayoutYml); //TrinityYAMLHelper.getNetworkMapLayoutYaml();
-
- toscaElementsMap = new HashMap<String, Object>();
- elementMap = new HashMap<String, Element>();
- domainMap = new HashMap<String, Domain>();
- outercontainers = new HashMap<String, Container>();
- innercontainers = new HashMap<String, Container>();
- miscElementMap = new HashMap<String, Element>();
-
- if(toscaYaml != null){
- for(String key : toscaYaml.keySet()){
- if("topology_template".equalsIgnoreCase(key) && toscaYaml.get(key) instanceof HashMap){
- HashMap<String, Object> toscaTopologyDetails = (HashMap<String, Object>) toscaYaml.get(key);
-
- for(String detailsKey: toscaTopologyDetails.keySet()){
-
- if("node_templates".equalsIgnoreCase(detailsKey) && toscaTopologyDetails.get(detailsKey) instanceof HashMap){
-
- toscaElementsMap = (HashMap<String, Object>) toscaTopologyDetails.get(detailsKey);
-
- for(String toscaElementKey: toscaElementsMap.keySet()){
- }
-
- }
- }
- }
-
- }
- }
-
- if(networkMapLayoutYaml != null){
- if(networkMapLayoutYaml.containsKey("toscaNetworkMapElementStyleList") && networkMapLayoutYaml.get("toscaNetworkMapElementStyleList") instanceof ArrayList){
-
- ArrayList<Object> elementlist = (ArrayList<Object>)networkMapLayoutYaml.get("toscaNetworkMapElementStyleList");
- String elementName;
- String elementID;
- String imgPath;
- String row;
- String column;
- String mapKey;
- int i=0;
-
- if(elementlist != null){
- for(Object eachElement: elementlist){
- if(eachElement != null && eachElement instanceof HashMap){
- HashMap<String, String> elementDetails = (HashMap<String, String>) eachElement;
- if(elementDetails != null){
- elementName = "NA"+i;
- elementID = "NA"+i;
- imgPath = "NA"+i;
- row = "0";
- column = "0";
- for(String detailsKey: elementDetails.keySet()){
- if ("tosca_id".equalsIgnoreCase(detailsKey)) elementName = elementDetails.get(detailsKey).toString();
- if ("id".equalsIgnoreCase(detailsKey)) {
- elementID = String.valueOf(elementDetails.get(detailsKey));
- }
- if ("row".equalsIgnoreCase(detailsKey)) {
- row = String.valueOf(elementDetails.get(detailsKey));
- }
- if ("column".equalsIgnoreCase(detailsKey)) {
- column = String.valueOf(elementDetails.get(detailsKey));
- }
- if ("icon".equalsIgnoreCase(detailsKey)) imgPath = elementDetails.get(detailsKey).toString();
- }
-
- if(elementMap.containsKey(elementName.concat("/").concat(row).concat(column))){
- if(elementMap.containsKey(elementName.concat("/").concat(String.valueOf(i)).concat(String.valueOf(i)))){
- mapKey = elementName;
- } else mapKey = elementName.concat("/").concat(String.valueOf(i)).concat(String.valueOf(i));
-
- } else mapKey = elementName.concat("/").concat(row).concat(column);
-
- elementMap.put(mapKey, fetchElementObject(elementID,elementName,imgPath));
- }
- }
- i++;
- }
- }
-
- for(String elementkey : elementMap.keySet()){
- Element c = (Element) elementMap.get(elementkey);
- }
-
- if(!elementMap.isEmpty()){
- miscElementMap = new HashMap<String, Element>(elementMap);
- }
- }
-
-
- if(networkMapLayoutYaml.containsKey("containerStyleList") && networkMapLayoutYaml.get("containerStyleList") instanceof ArrayList){
-
- ArrayList<Object> containerstylelist = (ArrayList<Object>)networkMapLayoutYaml.get("containerStyleList");
- String containerName;
- String containerID;
- String domain;
- String row;
- String column;
- String mapKey;
- int i=0;
-
- if(containerstylelist != null){
- //Inner Containers
- for(Object eachContainer: containerstylelist){
- if(eachContainer != null && eachContainer instanceof HashMap){
- HashMap<String, String> containerDetails = (HashMap<String, String>) eachContainer;
- if(containerDetails != null){
- containerName = "NA"+i;
- containerID = "NA"+i;
- domain = "NA"+i;
- row = "0";
- column = "0";
-
- for(String detailsKey: containerDetails.keySet()){
- if ("logical_group_name".equalsIgnoreCase(detailsKey)) containerName = containerDetails.get(detailsKey).toString();
- if ("id".equalsIgnoreCase(detailsKey)) {
- containerID = String.valueOf(containerDetails.get(detailsKey));
- }
- if("domain".equalsIgnoreCase(detailsKey)){
- domain = containerDetails.get(detailsKey).toString();
- }
- if ("row".equalsIgnoreCase(detailsKey)) {
- row = String.valueOf(containerDetails.get(detailsKey));
- }
- if ("column".equalsIgnoreCase(detailsKey)) {
- column = String.valueOf(containerDetails.get(detailsKey));
- }
- }
- if(containerName.contains("/")){
-
- if(innercontainers.containsKey((domain +":"+ containerName).concat("/").concat(row).concat(column))){
- if(elementMap.containsKey((domain +":"+ containerName).concat("/").concat(String.valueOf(i)).concat(String.valueOf(i)))){
- mapKey = (domain +":"+ containerName);
- } else mapKey = (domain +":"+ containerName).concat("/").concat(String.valueOf(i)).concat(String.valueOf(i));
-
- } else mapKey = (domain +":"+ containerName).concat("/").concat(row).concat(column);
-
- innercontainers.put(mapKey, fetchContainerObject(containerID,containerName.substring(containerName.indexOf("/")+1),true,containerName,domain));
- }
- }
- }
- i++;
- }
-
- //OuterContainers
- i=0;
- for(Object eachContainer: containerstylelist){
- if(eachContainer != null && eachContainer instanceof HashMap){
- HashMap<String, String> containerDetails = (HashMap<String, String>) eachContainer;
- if(containerDetails != null){
- containerName = "NA"+i;
- containerID = "NA"+i;
- domain = "NA"+i;
- row = "0";
- column = "0";
-
- for(String detailsKey: containerDetails.keySet()){
- if ("logical_group_name".equalsIgnoreCase(detailsKey)) containerName = containerDetails.get(detailsKey).toString();
- if ("id".equalsIgnoreCase(detailsKey)) {
- containerID = String.valueOf(containerDetails.get(detailsKey));
- }
- if("domain".equalsIgnoreCase(detailsKey)){
- domain = containerDetails.get(detailsKey).toString();
- }
- if ("row".equalsIgnoreCase(detailsKey)) {
- row = String.valueOf(containerDetails.get(detailsKey));
- }
- if ("column".equalsIgnoreCase(detailsKey)) {
- column = String.valueOf(containerDetails.get(detailsKey));
- }
- }
- if(!containerName.contains("/")){
- if(outercontainers.containsKey((domain +":"+ containerName).concat("/").concat(row).concat(column))){
- if(outercontainers.containsKey((domain +":"+ containerName).concat("/").concat(String.valueOf(i)).concat(String.valueOf(i)))){
- mapKey = (domain +":"+ containerName);
- } else mapKey = (domain +":"+ containerName).concat("/").concat(String.valueOf(i)).concat(String.valueOf(i));
-
- } else mapKey = (domain +":"+ containerName).concat("/").concat(row).concat(column);
- outercontainers.put(mapKey, fetchContainerObject(containerID,containerName,false,containerName,domain));
- }
-
- }
- }
- i++;
- }
- }
-
- for(String innerContainerkey : innercontainers.keySet()){
- Container c = (Container) innercontainers.get(innerContainerkey);
- }
-
- for(String outerContainerkey : outercontainers.keySet()){
- Container c = (Container) outercontainers.get(outerContainerkey);
- }
-
- }
-
- if(networkMapLayoutYaml.containsKey("domainList") && networkMapLayoutYaml.get("domainList") instanceof ArrayList){
-
- ArrayList<Object> domainlist = (ArrayList<Object>)networkMapLayoutYaml.get("domainList");
- String domainName;
- String domainID;
- String row;
- String column;
- String mapKey;
- int i=0;
-
- if(domainlist != null){
-
- Double leftPosition = 7d;
- HashMap<String,String> domainStagingMap = new HashMap<String, String>();
-
- for(Object eachDomain: domainlist){
- if(eachDomain != null && eachDomain instanceof HashMap){
- HashMap<String, String> domainDetails = (HashMap<String, String>) eachDomain;
- if(domainDetails != null){
- domainName = "NA"+i;
- domainID = "NA"+i;
- row = "0";
- column = "0";
- for(String detailsKey: domainDetails.keySet()){
- if ("name".equalsIgnoreCase(detailsKey)) domainName = domainDetails.get(detailsKey).toString();
- if ("id".equalsIgnoreCase(detailsKey)) {
- domainID = String.valueOf(domainDetails.get(detailsKey));
- }
- if ("row".equalsIgnoreCase(detailsKey)) {
- row = String.valueOf(domainDetails.get(detailsKey));
- }
- if ("column".equalsIgnoreCase(detailsKey)) {
- column = String.valueOf(domainDetails.get(detailsKey));
- }
- }
-
- if(domainStagingMap.containsKey(row.concat(column))){
- mapKey = domainName;
- } else mapKey = row.concat(column);
-
- domainStagingMap.put(mapKey, domainID+"%"+domainName);
- }
- }
- i++;
- }
-
- if(domainStagingMap != null && !domainStagingMap.isEmpty()){
- for(String domainsKey: new TreeSet<String>(domainStagingMap.keySet())){
- String value = domainStagingMap.get(domainsKey);
- if(value.contains("%")){
- domainMap.put(domainsKey, fetchDomainObject(value.substring(0,value.indexOf("%")),value.substring(value.indexOf("%")+1)));
- }
- }
- }
- }
-
- for(String domainkey : domainMap.keySet()){
- Domain c = (Domain) domainMap.get(domainkey);
- }
-
- }
-
-
- }
-
- Layout dynamicLayout = new Layout(domainMap, 2, 10, 1, 5);
-
- dynamicLayout.computeDomainPositionsModified();
- Map<String,Domain> resultDomain2= dynamicLayout.domainRowCol;
-
- for (String key : resultDomain2.keySet()) {
- if (resultDomain2.get(key).getP() !=null) {
-
- }
- }
-
- ElementMapService cm2 = new ElementMapService();
- try {
-
- if(args != null && args.length > 0 ) {
-
- if( args[0] != null) {
- String collapsedDomains[] = args[0].split(",");
- for(String collapsedDomain : collapsedDomains)
- dynamicLayout.collapseDomainNew(collapsedDomain);
- }
-
- if( args[1] != null) {
- String expandedDomains[] = args[1].split(",");
- for(String expandedDomain : expandedDomains)
- dynamicLayout.uncollapseDomainNew1(expandedDomain);
- }
-
- return cm2.convertToYAML(dynamicLayout);
-
- }
- }catch (Exception e) {
-
- e.printStackTrace();
- }
-
-
- return "";
-
-
- }
-
- private static int computeRows(Set<String> keys){
- int i = 0;
- if(keys!= null && !keys.isEmpty()){
- for(String s: keys){
- String r = s.substring(0, 1);
- if(StringUtils.isNumeric(r)){
- int j = Integer.parseInt(r);
- if(i<= j){
- i=j;
- }
-
- }
- }
-
- return i+1;
- }
-
- return 1;
- }
-
- private static int computeColumns(Set<String> keys){
- int i = 0;
- if(keys!= null && !keys.isEmpty()){
- for(String s: keys){
- String r = s.substring(1, 2);
- if(StringUtils.isNumeric(r)){
- int j = Integer.parseInt(r);
- if(i<= j){
- i=j;
- }
-
- }
- }
-
- return i+1;
- }
-
- return 1;
- }
-
- private static Container fetchContainerObject(String id, String name, boolean isInner, String logicalGroupName, String domain){
- Map<String,Element> containerElementsMap = new HashMap<String, Element>();
-
- containerElementsMap = fetchElementsMapForContainer(name, isInner, logicalGroupName, domain);
- int rows = 1;
- int columns = 1;
-
- if(isInner){
-
- if(containerElementsMap != null && !containerElementsMap.isEmpty()){
- rows = computeRows(containerElementsMap.keySet());
- columns = computeColumns(containerElementsMap.keySet());
- }
-
- Container thisContainer = new Container(id, name, rows, columns, 1, 4, 8, 12, 1, 2);
- thisContainer.setElements(containerElementsMap);
-
- return thisContainer;
- } else {
- Map<String,Container> innerContainersMap = fetchInnerContainersMapForOuter(name, isInner, logicalGroupName,domain);
-
- if(innerContainersMap != null && !innerContainersMap.isEmpty()){
- if(containerElementsMap != null && !containerElementsMap.isEmpty()){
- Set<String> keys = new HashSet<String>(innerContainersMap.keySet());
- keys.addAll(containerElementsMap.keySet());
- rows = computeRows(keys);
- columns = computeColumns(keys);
- } else {
- rows = computeRows(innerContainersMap.keySet());
- columns = computeColumns(innerContainersMap.keySet());
- }
- } else if(containerElementsMap != null && !containerElementsMap.isEmpty()){
- rows = computeRows(containerElementsMap.keySet());
- columns = computeColumns(containerElementsMap.keySet());
- }
-
- Container thisContainer = new Container(id, name, rows, columns,2 , 6, 2, 5, 0, 0);
- thisContainer.setElements(containerElementsMap);
- thisContainer.setInnerContainer(innerContainersMap);
-
-
- return thisContainer;
- }
-
- }
-
- private static Domain fetchDomainObject(String id, String name){
- HashMap<String,Container> domainContainersMap = fetchContainersForDomain(name);
-
- int rows = 1;
- int columns = 1;
- if(domainContainersMap != null && !domainContainersMap.isEmpty()){
- rows = computeRows(domainContainersMap.keySet());
- columns = computeColumns(domainContainersMap.keySet());
- }
-
- double domainWidth = 11;
- Domain thisDomain;
-
- if(domainMap != null && !domainMap.isEmpty()){
- int domainsCountSoFar = domainMap.size();
- switch(domainsCountSoFar){
- case 1: {domainWidth = 12.1; break;}
- case 2: {domainWidth = 13.3; break;}
- case 3: {domainWidth = 14.5; break;}
- case 4: {domainWidth = 15.6; break;}
- default: {domainWidth = 11; break;}
- }
-
- for(String domainsKey: new TreeSet<String>(domainMap.keySet())){
- Domain eachDomain = domainMap.get(domainsKey);
- domainWidth+= eachDomain.computeSize().getWidth();
- }
- thisDomain = new Domain(id, name, 2, 2, domainWidth, 10, 3, rows, columns);
- } else {
-
- thisDomain = new Domain(id, name, 2, 1, 11, 10, 3, rows, columns);
- }
-
- thisDomain.setContainers(domainContainersMap);
-
- thisDomain.computeConatinerPositions();
- if(domainContainersMap!= null && !domainContainersMap.isEmpty()){
- for(Container thisContainer : domainContainersMap.values()){
- thisContainer.computeSize();
- thisContainer.computeElementPositions();
- Map<String,Element> resultElementMap = thisContainer.elementRowCol;
- for (String key : resultElementMap.keySet()) {
- if(resultElementMap.get(key) == null || resultElementMap.get(key).getP() == null) {
- }
-
- }
-
- HashMap<String,Container> innerContainersMap = (HashMap<String, Container>) thisContainer.getContainerRowCol();
- if(innerContainersMap != null && !innerContainersMap.isEmpty()){
- for(Container thisInnerContainer : innerContainersMap.values()){
- thisInnerContainer.computeElementPositions();
- }
- }
- }
- }
-
- return thisDomain;
- }
-
- private static HashMap<String,Container> fetchContainersForDomain(String domain){
- HashMap<String,Container> domainContainersMap = new HashMap<String, Container>();
-
- domainContainersMap = fetchFromOuterContainers(domain);
-
- return domainContainersMap;
-
- }
-
- @SuppressWarnings("unchecked")
- private static Element fetchElementObject(String id, String name, String imgPath){
- String bgColor = "bgColor";
- String logical_group;
- String display_longname;
- String display_shortname;
- String description;
- String primary_function;
- String key_interfaces;
- String location;
- String vendor;
- String vendor_shortname;
- String enclosingContainer;
- String borderType;
- String network_function;
-
- if(toscaElementsMap.containsKey(name)){
-
- if(toscaElementsMap.get(name) != null && toscaElementsMap.get(name) instanceof HashMap){
- HashMap<String, Object> toscaElementDetails = (HashMap<String, Object>) toscaElementsMap.get(name);
-
- for(String detailsKey: toscaElementDetails.keySet()){
- if("properties".equalsIgnoreCase(detailsKey) && toscaElementDetails.get(detailsKey) instanceof HashMap){
- HashMap<String, String> elementDetails = (HashMap<String, String>) toscaElementDetails.get(detailsKey);
-
- if(elementDetails != null){
- logical_group = elementDetails.get("logical_group") == null? "" : elementDetails.get("logical_group").toString();
- display_longname = elementDetails.get("display_longname") == null? "" : elementDetails.get("display_longname").toString();
- display_shortname = elementDetails.get("display_shortname") == null? "" : elementDetails.get("display_shortname").toString();
- description = elementDetails.get("description") == null? "" : elementDetails.get("description").toString();
- primary_function = elementDetails.get("primary_function") == null? "" : elementDetails.get("primary_function").toString();
- key_interfaces = elementDetails.get("key_interfaces") == null? "" : elementDetails.get("key_interfaces").toString();
- location = elementDetails.get("location") == null? "" : elementDetails.get("location").toString();
- vendor = elementDetails.get("vendor") == null? "" : elementDetails.get("vendor").toString();
- vendor_shortname = elementDetails.get("vendor_shortname") == null? "" : elementDetails.get("vendor_shortname").toString();
- enclosingContainer = logical_group.replace("/", "-");
- network_function = elementDetails.get("network_function");
- borderType = elementDetails.get("network_function") == null? "P" : elementDetails.get("network_function").toString().toUpperCase();
- bgColor = elementDetails.get("background_color") == null? "bgColor" : elementDetails.get("background_color").toString();
-
- ElementDetails details = new ElementDetails(logical_group,display_longname,description,primary_function, network_function,
- key_interfaces,location,vendor,vendor_shortname,enclosingContainer);
-
- return new Element(name, display_shortname, imgPath, bgColor,borderType, details);
- }
-
- }
- }
-
- }
-
- } else {
- return new Element(id,name);
- }
-
- return new Element(id,name);
- }
-
- @SuppressWarnings("unchecked")
- private static String fetchDomainNameOfElement(String name){
- if(toscaElementsMap.containsKey(name)){
-
- if(toscaElementsMap.get(name) != null && toscaElementsMap.get(name) instanceof HashMap){
- HashMap<String, Object> toscaElementDetails = (HashMap<String, Object>) toscaElementsMap.get(name);
-
- for(String detailsKey: toscaElementDetails.keySet()){
- if("properties".equalsIgnoreCase(detailsKey) && toscaElementDetails.get(detailsKey) instanceof HashMap){
- HashMap<String, String> elementDetails = (HashMap<String, String>) toscaElementDetails.get(detailsKey);
-
- if(elementDetails != null){
- return elementDetails.get("domain") == null? "" : elementDetails.get("domain").toString();
- }
-
- }
- }
-
- }
-
- } else {
- return "";
- }
-
- return "";
- }
-
- private static HashMap<String, Container> fetchInnerContainersMapForOuter(String name, boolean isInner, String logicalGroupName, String domain){
- return fetchInnerContainersMap(name,logicalGroupName,domain);
- }
-
- private static HashMap<String, Element> fetchElementsMapForContainer(String name, boolean isInner, String logicalGroupName, String domain){
- return fetchElementsMap(logicalGroupName,domain);
- }
-
- private static HashMap<String, Container> fetchInnerContainersMap(String name, String logicalGroupName, String domain){
- HashMap<String,Container> containersMap = new HashMap<String, Container>();
- String rowColumnKey = "";
- int count = 0;
-
- if(innercontainers!=null && !innercontainers.isEmpty()){
- for(String key : innercontainers.keySet()){
-
-
- Container eachContainer = innercontainers.get(key);
-
- if(key.toUpperCase().contains((domain+":"+name).toUpperCase())){
- if(key.contains("/")){
- rowColumnKey = key.substring(key.lastIndexOf("/")+1);
- }
-
- if(rowColumnKey.isEmpty() || containersMap.containsKey(rowColumnKey)){
- count=0;
- while(count<=9){
- if(containersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))){
- count++;
- } else
- {
- rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
- break;
- }
- }
-
-
- }
-
- containersMap.put(rowColumnKey,eachContainer);
- }
-
-
- }
- }
- return containersMap.isEmpty()?null:containersMap;
-
- }
-
- private static HashMap<String, Container> fetchFromOuterContainers(String domain){
- HashMap<String,Container> thisContainersMap = new HashMap<String, Container>();
- String rowColumnKey = "";
- int count = 0;
-
- if(outercontainers!=null && !outercontainers.isEmpty()){
- for(String key : outercontainers.keySet()){
- Container eachContainer = outercontainers.get(key);
-
- if(key.toUpperCase().contains((domain+":").toUpperCase())){
- if(key.contains("/")){
- rowColumnKey = key.substring(key.lastIndexOf("/")+1);
- }
-
- if(rowColumnKey.isEmpty() || thisContainersMap.containsKey(rowColumnKey)){
- count=0;
- while(count<=9){
- if(thisContainersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))){
- count++;
- } else
- {
- rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
- break;
- }
- }
-
-
- }
-
- thisContainersMap.put(rowColumnKey,eachContainer);
- }
- }
-
- }
-
- //Misc Elements Containers
-
- if(miscElementMap!=null && !miscElementMap.isEmpty()){
- for(String key : miscElementMap.keySet()){
- Element eachElement = miscElementMap.get(key);
- String elementName = eachElement.getName();
- String domainName = fetchDomainNameOfElement(elementName);
-
- if(domain.equalsIgnoreCase(domainName)){
- Container eachContainer = new Container(domainName+":"+elementName, elementName, 1, 1, 3, 6, 2, 5, 0, 0);
- count=0;
- while(count<=9){
- if(thisContainersMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))){
- count++;
- } else
- {
- rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
- break;
- }
- }
-
- thisContainersMap.put(rowColumnKey,eachContainer);
- }
-
-
- }
-
- }
-
-
- return thisContainersMap.isEmpty()?null:thisContainersMap;
- }
-
-
-
- @SuppressWarnings("unused")
- private static HashMap<String,Container> addOuterContainersForMiscElements(String domain){
- HashMap<String,Container> containerElementsMap = new HashMap<String, Container>();
- if(miscElementMap!=null && !miscElementMap.isEmpty()){
- for(String key : miscElementMap.keySet()){
- Element eachElement = miscElementMap.get(key);
- String elementName = eachElement.getName();
- String domainName = fetchDomainNameOfElement(elementName);
-
- if(domain.equalsIgnoreCase(domainName)){
- Container newContainer = new Container(domainName+":"+elementName, elementName, 1, 1, 3, 6, 2, 5, 0, 0);
- containerElementsMap.put(domainName+":"+elementName, newContainer);
- }
-
-
- }
-
- }
- return containerElementsMap.isEmpty()? null:containerElementsMap;
- }
-
- private static HashMap<String, Element> fetchElementsMap(String logicalGroupName, String domain){
- HashMap<String,Element> innerElementMap = new HashMap<String, Element>();
- String rowColumnKey = "";
- int count = 0;
-
- if(elementMap!=null && !elementMap.isEmpty()){
- for(String key : elementMap.keySet()){
- Element eachElement = elementMap.get(key);
-
- String elementName = eachElement.getId();
- String elementLogicalGroup = eachElement.details == null ? "" : eachElement.details.logical_group;
- if(elementLogicalGroup.equalsIgnoreCase(logicalGroupName) && domain.equalsIgnoreCase(fetchDomainNameOfElement(elementName))){
- if(key.contains("/")){
- rowColumnKey = key.substring(key.indexOf("/")+1);
- }
-
- if(rowColumnKey.isEmpty() || innerElementMap.containsKey(rowColumnKey)){
- count=0;
- while(count<=9){
- if(innerElementMap.containsKey(String.valueOf(count).concat(String.valueOf(count)))){
- count++;
- } else
- {
- rowColumnKey = String.valueOf(count).concat(String.valueOf(count));
- break;
- }
- }
-
-
- }
-
- innerElementMap.put(rowColumnKey,eachElement);
- miscElementMap.remove(key);
- }
-
- }
- }
-
- return innerElementMap.isEmpty()?null:innerElementMap;
- }
-
-
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java
deleted file mode 100644
index 113833bf..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/LoginService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service;
-
-
-import java.util.HashMap;
-
-import org.openecomp.portalsdk.core.command.LoginBean;
-
-
-public interface LoginService {
-
- // validate user exists in the system
- @SuppressWarnings("rawtypes")
- LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams) throws Exception;
-
- @SuppressWarnings("rawtypes")
- LoginBean findUser(LoginBean bean, String menuPropertiesFilename, HashMap additionalParams, boolean matchPassword) throws Exception;
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java
deleted file mode 100644
index 2ecedbea..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/PostSearchServiceImpl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.core.FusionObject.Parameters;
-import org.openecomp.portalsdk.core.command.PostSearchBean;
-import org.openecomp.portalsdk.core.domain.Lookup;
-import org.openecomp.portalsdk.core.domain.Role;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.openecomp.portalsdk.core.web.support.FeedbackMessage;
-import org.openecomp.portalsdk.core.web.support.MessagesList;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-@Service("postSearchService")
-@Transactional
-public class PostSearchServiceImpl implements PostSearchService{
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PostSearchServiceImpl.class);
-
- @Autowired
- private DataAccessService dataAccessService;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public void process(HttpServletRequest request, PostSearchBean postSearch) {
- HashMap additionalParams = new HashMap();
- additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request);
-
- if (postSearch.getSelected() != null) {
- //sort the selected users for quick validation
-
- Arrays.sort(postSearch.getSelected());
- System.out.println("list - " + postSearch.getPostOrgUserId().length);
- // import the users that have been selected
- for(int i=0; i < postSearch.getPostOrgUserId().length; i++){
- if (Arrays.binarySearch(postSearch.getSelected(), postSearch.getPostOrgUserId()[i]) >= 0) {
- logger.info(EELFLoggerDelegate.debugLogger, "Adding ORGUSERID - " + postSearch.getPostOrgUserId()[i]);
- logger.info(EELFLoggerDelegate.auditLogger, "Import new user from webphone " + postSearch.getPostOrgUserId()[i]);
-
- User user = new User();
- user.setLastName(postSearch.getPostLastName()[i]);
- user.setFirstName(postSearch.getPostFirstName()[i]);
-
- if (postSearch.getPostHrid() != null && postSearch.getPostHrid().length > 0) {
- user.setHrid(postSearch.getPostHrid()[i]);
- }
-
- if (postSearch.getPostPhone() != null && postSearch.getPostPhone().length > 0) {
- user.setPhone(postSearch.getPostPhone()[i]);
- }
-
- if (postSearch.getPostEmail() != null && postSearch.getPostEmail().length > 0) {
- user.setEmail(postSearch.getPostEmail()[i]);
- }
-
- if (postSearch.getPostOrgUserId() != null && postSearch.getPostOrgUserId().length > 0) {
- user.setOrgUserId(postSearch.getPostOrgUserId()[i]);
- user.setLoginId(postSearch.getPostOrgUserId()[i]);
- }
-
- if (postSearch.getPostAddress1() != null && postSearch.getPostAddress1().length > 0) {
- user.setAddress1(postSearch.getPostAddress1()[i]);
- }
-
- if (postSearch.getPostAddress2() != null && postSearch.getPostAddress2().length > 0) {
- user.setAddress2(postSearch.getPostAddress2()[i]);
- }
-
- if (postSearch.getPostCity() != null && postSearch.getPostCity().length > 0) {
- user.setCity(postSearch.getPostCity()[i]);
- }
-
- if (postSearch.getPostState() != null && postSearch.getPostState().length > 0) {
- user.setState(postSearch.getPostState()[i]);
- }
-
- if (postSearch.getPostZipCode() != null && postSearch.getPostZipCode().length > 0) {
- user.setZipCode(postSearch.getPostZipCode()[i]);
- }
-
- if (postSearch.getPostLocationClli() != null && postSearch.getPostLocationClli().length > 0) {
- user.setLocationClli(postSearch.getPostLocationClli()[i]);
- }
-
- if (postSearch.getPostBusinessCountryCode() != null && postSearch.getPostBusinessCountryCode().length > 0) {
- user.setBusinessCountryCode(postSearch.getPostBusinessCountryCode()[i]);
- }
-
- if (postSearch.getPostBusinessCountryName() != null && postSearch.getPostBusinessCountryName().length > 0) {
-
- // find the country cd for the indicated country
- List countries = dataAccessService.getLookupList("fn_lu_country", "country_cd", "country", "country = '"
- + postSearch.getPostBusinessCountryName()[i] + "'", null, null);
-
- if (countries!=null&&countries.size() == 1) {
- Lookup country = (Lookup)countries.get(0);
- user.setCountry(country.getValue());
- }
- else {
- logger.info(EELFLoggerDelegate.debugLogger, "No countries or more than one country was found matching the country returned from WEBPHONE. " +
- "Therefore, no country was set for this user.");
- }
-
- }
-
- if (postSearch.getPostDepartment() != null && postSearch.getPostDepartment().length > 0) {
- user.setDepartment(postSearch.getPostDepartment()[i]);
- }
-
- if (postSearch.getPostDepartmentName() != null && postSearch.getPostDepartmentName().length > 0) {
- user.setDepartmentName(postSearch.getPostDepartmentName()[i]);
- }
-
- if (postSearch.getPostBusinessUnit() != null && postSearch.getPostBusinessUnit().length > 0) {
- user.setBusinessUnit(postSearch.getPostBusinessUnit()[i]);
- }
-
- if (postSearch.getPostBusinessUnitName() != null && postSearch.getPostBusinessUnitName().length > 0) {
- user.setBusinessUnitName(postSearch.getPostBusinessUnitName()[i]);
- }
-
- if (postSearch.getPostJobTitle() != null && postSearch.getPostJobTitle().length > 0) {
- user.setJobTitle(postSearch.getPostJobTitle()[i]);
- }
-
- if (postSearch.getPostOrgManagerUserId() != null && postSearch.getPostOrgManagerUserId().length > 0) {
- user.setOrgManagerUserId(postSearch.getPostOrgManagerUserId()[i]);
- }
-
- if (postSearch.getPostCommandChain() != null && postSearch.getPostCommandChain().length > 0) {
- user.setCommandChain(postSearch.getPostCommandChain()[i]);
- }
-
- if (postSearch.getPostCompanyCode() != null && postSearch.getPostCompanyCode().length > 0) {
- user.setCompanyCode(postSearch.getPostCompanyCode()[i]);
- }
-
- if (postSearch.getPostCompany() != null && postSearch.getPostCompany().length > 0) {
- user.setCompany(postSearch.getPostCompany()[i]);
- }
-
- if (postSearch.getPostCostCenter() != null && postSearch.getPostCostCenter().length > 0) {
- user.setCostCenter(postSearch.getPostCostCenter()[i]);
- }
-
- if (postSearch.getPostSiloStatus() != null && postSearch.getPostSiloStatus().length > 0) {
- user.setSiloStatus(postSearch.getPostSiloStatus()[i]);
- }
-
- if (postSearch.getPostFinancialLocCode() != null && postSearch.getPostFinancialLocCode().length > 0) {
- user.setFinancialLocCode(postSearch.getPostFinancialLocCode()[i]);
- }
-
- user.setActive(true);
-
- try {
- dataAccessService.saveDomainObject(user, additionalParams);
-
- Role role = (Role)dataAccessService.getDomainObject(Role.class,Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID)), null);
- user.addRole(role);
- }
- catch (Exception e) {
- MessagesList messages = new MessagesList();
- messages.addExceptionMessage(new FeedbackMessage("An error occurred while attempting to import " + user.getFirstName() + " "
- + user.getLastName() + ": " + e.getMessage(), FeedbackMessage.MESSAGE_TYPE_ERROR));
-
- }
- }
- }
-
- }
-
- }
-
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java
deleted file mode 100644
index e0899917..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/UserProfileServiceImpl.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-
-import org.hibernate.criterion.Criterion;
-import org.hibernate.criterion.Restrictions;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.FusionObject.Utilities;
-import org.openecomp.portalsdk.core.domain.Role;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.domain.support.CollaborateList;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-@Service("userProfileService")
-@Transactional
-public class UserProfileServiceImpl implements UserProfileService{
-
-
- @Autowired
- private DataAccessService dataAccessService;
-
- @SuppressWarnings("unchecked")
- public List<User> findAll() {
- return getDataAccessService().getList(User.class, null);
- }
-
- public User getUser(String userId){
- return (User) getDataAccessService().getDomainObject(User.class, Long.parseLong(userId), null);
- }
-
- @SuppressWarnings("unchecked")
- public User getUserByLoginId(String loginId){
- User user=null;
- List<Criterion> restrictionsList = new ArrayList<Criterion>();
- Criterion criterion1= Restrictions.eq("loginId",loginId);
- restrictionsList.add(criterion1);
- List<User> users = (List<User>) getDataAccessService().getList(User.class,null, restrictionsList, null);
- if(users!=null && users.size()==1)
- user = users.get(0);
- return user;
- }
-
- public void saveUser(User user){
-
- getDataAccessService().saveDomainObject(user, null);
- }
-
- public DataAccessService getDataAccessService() {
- return dataAccessService;
- }
-
-
- public void setDataAccessService(DataAccessService dataAccessService) {
- this.dataAccessService = dataAccessService;
- }
-
- @SuppressWarnings("unchecked")
- public List<User> findAllUserWithOnOffline(String originOrgUserId) {
- HashSet<String> onlineUser = CollaborateList.getInstance().getAllUserName();
- List<User> users = getDataAccessService().getList(User.class, null);
- for(User u:users){
- if(onlineUser.contains(u.getOrgUserId()))
- u.setOnline(true);
- if(u.getOrgUserId()!=null){
- if(originOrgUserId.compareTo(u.getOrgUserId()) > 0) {
- u.setChatId(originOrgUserId + "-" + u.getOrgUserId());
- } else u.setChatId(u.getOrgUserId() + "-" + originOrgUserId );
- }
- }
- return users;
-
- }
-
- @SuppressWarnings("unchecked")
- public List<User> findAllActive() {
- List<User> users = getDataAccessService().getList(User.class, null);
- Iterator<User> itr = users.iterator();
- while(itr.hasNext()){
- User u = (User) itr.next();
- if(!u.getActive())
- itr.remove();//if not active remove user from list
- else {
- SortedSet<Role> roles = u.getRoles();
- Iterator<Role> itrRoles = roles.iterator();
- while(itrRoles.hasNext()){
- Role role = (Role) itrRoles.next();
- if(!role.getActive())
- u.removeRole(role.getId());//if not active remove role from list
- }
- }
- }
- return users;
- }
-
-
- @Override
- public List<User> searchPost(User user, String sortBy1, String sortBy2, String sortBy3, int pageNo,
- int newDataSize, int intValue) {
-
- List<User> users=new ArrayList<User>();
- List<User> filterdUsers=new ArrayList<User>();
- BufferedReader in = null;
-
- try{
- String url = SystemProperties.getProperty(SystemProperties.AUTH_USER_SERVER);
- URL obj = new URL(url);
-
- HttpURLConnection con = (HttpURLConnection) obj.openConnection();
-
- // optional default is GET
- con.setRequestMethod("GET");
- con.setConnectTimeout(3000);
- con.setReadTimeout(8000);
-
- StringBuffer response = new StringBuffer();
-
-
-
- in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
- String inputLine;
- while ((inputLine = in.readLine()) != null)
- response.append(inputLine);
-
- JSONObject jObject = new JSONObject(response.toString()); // json
- JSONArray jsonUsers = jObject.getJSONArray("response"); // get data object
- for (int i = 0; i < jsonUsers.length(); i++) {
- JSONObject eachObject = jsonUsers.getJSONObject(i);
- User eachUser = new User();
- eachUser.setOrgUserId(eachObject.get("id").toString());// getString("id"));
- eachUser.setFirstName(eachObject.get("givenName").toString());
- eachUser.setLastName(eachObject.get("familyName").toString());
- eachUser.setEmail(eachObject.get("email").toString());
-
- users.add(eachUser);
- }
-
- for(int i = 0 ; i < users.size(); i ++){
-
- if(Utilities.nvl(user.getFirstName()).length() > 0){
- if(!user.getFirstName().equalsIgnoreCase(users.get(i).getFirstName())){
- continue;
- }
- }
- if(Utilities.nvl(user.getLastName()).length() > 0){
- if(!user.getLastName().equalsIgnoreCase(users.get(i).getLastName())){
- continue;
- }
- }
- if(Utilities.nvl(user.getOrgUserId()).length() > 0){
- if(!user.getOrgUserId().equalsIgnoreCase(users.get(i).getOrgUserId())){
- continue;
- }
- }
- if(Utilities.nvl(user.getEmail()).length() > 0){
- if(!user.getEmail().equalsIgnoreCase(users.get(i).getEmail())){
- continue;
- }
- }
-
- filterdUsers.add(users.get(i));
-
- }
-
- }catch (Exception e){
-
- }finally{
- try {
- in.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- return filterdUsers;
- }
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java
deleted file mode 100644
index e7437835..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/service/support/ServiceLocatorImpl.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.service.support;
-
-import java.util.Properties;
-
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.naming.ldap.InitialLdapContext;
-
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.springframework.stereotype.Service;
-
-/**
- * This class implements the J2EE service locator pattern. It provides lookup
- * facilities for various services. Currenttly LDAP (pre-v3) is supported
- */
-@Service("serviceLocator")
-public class ServiceLocatorImpl implements ServiceLocator {
-
- private Context context; // JNDI context (not currently in use)
- private Context rootContext; // Java env root context (not currently in use)
- private DirContext dirContext; // LDAP DIR context
- private InitialLdapContext ldapContext; // LDAP context LDAPv3-style (not currently in use)
-
-
- // cannot directly instantiate
- public ServiceLocatorImpl() {}
-
- // Get an LDAP directory context
- public DirContext getDirContext(String initialContextFactory, String providerUrl, String securityPrincipal) {
-
- if (dirContext == null) {
-
- Properties properties = new Properties();
- properties.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
- properties.put(Context.PROVIDER_URL, providerUrl);
- properties.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
-
- try {
- dirContext = new InitialDirContext(properties);
- }
- catch (NamingException ne) {
- logger.error(EELFLoggerDelegate.errorLogger, "An error has occurred while creating an Initial Directory Context: " + ne.getMessage());
- logger.error(EELFLoggerDelegate.errorLogger, "Explanation: " + ne.getExplanation());
- }
- }
-
- return dirContext;
- }
-
- /** Logger for this class and subclasses */
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ServiceLocatorImpl.class);
-
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CipherUtil.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CipherUtil.java
deleted file mode 100644
index 0eec9295..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/CipherUtil.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.util;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.commons.codec.binary.Base64;
-
-public class CipherUtil {
-
- private final static String key = "AGLDdG4D04BKm2IxIWEr8o==!";
-
- /**
- * @param plainText
- * @param secretKey
- * @return encrypted version of plain text.
- * @throws Exception
- */
- public static String encrypt(String plainText, String secretKey) throws Exception{
- byte[] rawKey;
- String encryptedString;
- SecretKeySpec sKeySpec;
- byte[] encryptText = plainText.getBytes("UTF-8");
- Cipher cipher;
- rawKey = Base64.decodeBase64(secretKey);
- sKeySpec = new SecretKeySpec(rawKey, "AES");
- cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
- encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
-
- return encryptedString;
- }
-
- /**
- *
- * @param plainText
- * @return Encrypted Text
- * @throws Exception
- */
- public static String encrypt(String plainText) throws Exception
- {
- return CipherUtil.encrypt(plainText,key);
- }
-
- /**
- * @param encryptedText
- * @param secretKey
- * @return plain text version of encrypted text
- * @throws Exception
- */
- public static String decrypt(String encryptedText, String secretKey) throws Exception {
- Cipher cipher;
- String encryptedString;
- byte[] encryptText = null;
- byte[] rawKey;
- SecretKeySpec sKeySpec;
-
- rawKey = Base64.decodeBase64(secretKey);
- sKeySpec = new SecretKeySpec(rawKey, "AES");
- encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8"));
- cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
- encryptedString = new String(cipher.doFinal(encryptText));
-
- return encryptedString;
- }
-
- /**
- * @param encryptedText
- * @return Decrypted Text
- * @throws Exception
- */
- public static String decrypt(String encryptedText) throws Exception
- {
- return CipherUtil.decrypt(encryptedText,key);
- }
-
-
- public static void main(String[] args) throws Exception {
-
- String password = "Welcome123";
- String encrypted;
- String decrypted;
-
- if (args.length != 2) {
- System.out.println("Default password testing... ");
- System.out.println("Plain password: " + password);
- encrypted = encrypt(password);
- System.out.println("Encrypted password: " + encrypted);
- decrypted = decrypt(encrypted);
- System.out.println("Decrypted password: " + decrypted);
- } else {
- String whatToDo = args[0];
- if (whatToDo.equalsIgnoreCase("d")) {
- encrypted = args[1];
- System.out.println("Encrypted Text: " + encrypted);
- decrypted = decrypt(encrypted);
- System.out.println("Decrypted Text: " + decrypted);
- } else {
- decrypted = args[1];
- System.out.println("Plain Text: " + decrypted);
- encrypted = encrypt(decrypted);
- System.out.println("Encrypted Text" + encrypted);
- }
- }
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncTest.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncTest.java
deleted file mode 100644
index 865731db..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/EncTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.util;
-
-public class EncTest {
-
-
- public static void main(String[] args) {
- String secretKey = "AGLDdG4D04BKm2IxIWEr8o==";
- String value1= "AppPassword!1";
- try {
- String encryptedValue1= CipherUtil.encrypt(value1, secretKey);
- System.out.println(encryptedValue1);
- String decryptedValue1 = CipherUtil.decrypt(encryptedValue1, secretKey);
- System.out.println(decryptedValue1);
- } catch (Exception e) {
- // Invalid key would throw an exception.
- e.printStackTrace();
- }
-
- }
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java
deleted file mode 100644
index 8bc6d7a1..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/util/SystemProperties.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.util;
-
-import javax.servlet.ServletContext;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.core.env.Environment;
-
-/**
- * SystemProperties contains a list of constants used throughout portions of the
- * application. Populated by Spring from multiple configuration files.
- *
- * Should be used like this:
- *
- * <pre>
- *
- * &#64;Autowired
- * SystemProperties systemProperties;
- * </pre>
- */
-@Configuration
-@PropertySource(value = { "${container.classpath:}/WEB-INF/conf/system.properties",
- "${container.classpath:}/WEB-INF/fusion/conf/fusion.properties",
- "${container.classpath:}/WEB-INF/conf/sql.properties" })
-public class SystemProperties {
-
- private static Environment environment;
-
- public SystemProperties() {
- }
-
- protected Environment getEnvironment() {
- return environment;
- }
-
- @Autowired
- public void setEnvironment(Environment environment) {
- SystemProperties.environment = environment;
- }
-
- public ServletContext getServletContext() {
- return servletContext;
- }
-
- public void setServletContext(ServletContext servletContext) {
- this.servletContext = servletContext;
- }
-
-
- public static boolean containsProperty(String key) {
- return environment.containsProperty(key);
- }
-
- public static String getProperty(String key) {
- if (environment!=null) {
- return environment.getRequiredProperty(key);
- } else {
- return "";
- }
- }
-
- // method created to get around JSTL 1.0 limitation of not being able to
- // access a static method of a bean
- public String getApplicationName() {
- return getProperty(APPLICATION_NAME);
- }
-
- public String getAppDisplayName() {
- return getProperty(APP_DISPLAY_NAME);
- }
-
- private ServletContext servletContext;
-
- // keys used to reference values in the system properties file
- public static final String DOMAIN_CLASS_LOCATION = "domain_class_location";
- public static final String DEFAULT_ERROR_MESSAGE = "default_error_message";
-
- public static final String AUTHENTICATION_MECHANISM = "authentication_mechanism";
-
- public static final String APPLICATION_NAME = "application_name";
- public static final String HIBERNATE_CONFIG_FILE_PATH = "hibernate_config_file_path";
- public static final String APPLICATION_USER_ID = "application_user_id";
-
- public static final String POST_INITIAL_CONTEXT_FACTORY = "post_initial_context_factory";
- public static final String POST_PROVIDER_URL = "post_provider_url";
- public static final String POST_SECURITY_PRINCIPAL = "post_security_principal";
- public static final String POST_MAX_RESULT_SIZE = "post_max_result_size";
- public static final String POST_DEFAULT_ROLE_ID = "post_default_role_id";
-
- public static final String FILES_PATH = "files_path";
- public static final String TEMP_PATH = "temp_path";
-
- public static final String NUM_UPLOAD_FILES = "num_upload_files";
-
- public static final String SYS_ADMIN_ROLE_ID = "sys_admin_role_id";
-
- public static final String SYS_ADMIN_ROLE_FUNCTION_DELETE_FROM_UI = "sys_admin_role_function_delete_from_ui";
- public static final String USER_NAME = "user_name";
- public static final String FIRST_NAME = "first_name";
- public static final String LAST_NAME = "last_name";
- public static final String APP_DISPLAY_NAME = "app_display_name";
- // Application base URL is a proper prefix of the on-boarding URL
- public static final String APP_BASE_URL = "app_base_url";
-
- public static final String MENU_PROPERTIES_FILE_LOCATION = "menu_properties_file_location";
- public static final String MENU_QUERY_NAME = "menu_query_name";
- public static final String APPLICATION_MENU_SET_NAME = "application_menu_set_name";
- public static final String APPLICATION_MENU_ATTRIBUTE_NAME = "application_menu_attribute_name";
- public static final String APPLICATION_MENU_PROPERTIES_NAME = "application_menu_properties_name";
- public static final String BUSINESS_DIRECT_MENU_SET_NAME = "business_direct_menu_set_name";
- public static final String BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME = "business_direct_menu_attribute_name";
- public static final String BUSINESS_DIRECT_MENU_PROPERTIES_NAME = "business_direct_menu_properties_name";
- public static final String RAPTOR_CONFIG_FILE_PATH = "raptor_config_file_path";
- public static final String HOMEPAGE_DATA_CALLBACK_CLASS = "homepage_data_callback_class";
- public static final String ERROR_EMAIL_DISTRIBUTION = "error_email_distribution";
- public static final String ERROR_EMAIL_SOURCE_ADDRESS = "error_email_source_address";
- public static final String ERROR_EMAIL_SUBJECT_LINE = "error_email_subject_line";
- public static final String PROFILE_SEARCH_REPORT_ID = "profile_search_report_id";
- public static final String CALLABLE_PROFILE_SEARCH_REPORT_ID = "callable_profile_search_report_id";
- public static final String CLUSTERED = "clustered";
-
- public static final String USER_ATTRIBUTE_NAME = "user_attribute_name";
- public static final String ROLES_ATTRIBUTE_NAME = "roles_attribute_name";
- public static final String ROLE_FUNCTIONS_ATTRIBUTE_NAME = "role_functions_attribute_name";
- public static final String CLIENT_DEVICE_ATTRIBUTE_NAME = "client_device_attribute_name";
- public static final String CLIENT_DEVICE_EMULATION = "client_device_emulation";
- public static final String CLIENT_DEVICE_TYPE_TO_EMULATE = "client_device_type_to_emulate";
- // File generation - Document
- public static final String TEMPLATES_PATH = "templates_path";
- public static final String DOCUMENT_XML_ENCODING = "document_xml_encoding";
-
- // Transaction
- public static final String ROUTING_DATASOURCE_KEY = "routing_datasource_key";
-
- // Document Library keys
- public static final String DOCLIB_ADMIN_ROLE_ID = "doclib_admin_role_id";
- public static final String DOCLIB_USER_ROLE_ID = "doclib_user_role_id";
-
- public static final String SYSTEM_PROPERTIES_FILENAME = "system.properties";
- public static final String FUSION_PROPERTIES_FILENAME = "fusion.properties";
- public static final String SUCCESS_TASKS_PROPERTIES_FILENAME = "success_tasks.properties";
-
- // login error message keys
- public static final String MESSAGE_KEY_LOGIN_ERROR_COOKIE_EMPTY = "login.error.hrid.empty";
- public static final String MESSAGE_KEY_LOGIN_ERROR_HEADER_EMPTY = "login.error.header.empty";
- public static final String MESSAGE_KEY_LOGIN_ERROR_USER_INACTIVE = "login.error.user.inactive";
- public static final String MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND = "login.error.hrid.not-found";
- public static final String MESSAGE_KEY_LOGIN_ERROR_APPLICATION_LOCKED = "login.error.application.locked";
- public static final String MESSAGE_KEY_AUTOLOGIN_NONE = "webphone.autoimport.nouser";
- public static final String MESSAGE_KEY_AUTOLOGIN_MULTIPLE = "webphone.autoimport.multiple";
-
- // Application Mobile capability
- public static final String MOBILE_ENABLE = "mobile_enable";
-
- public static final String DATABASE_TIME_ZONE = "db.time_zone";
-
- public static final String AUTO_USER_IMPORT_ENABLE = "auto_user_import_enable";
- public static final String AUTO_USER_IMPORT_ROLE = "auto_user_import_role";
-
- public static final String ITRACKER_EMAIL_SOURCE_ADDRESS = "itracker_email_source_address";
- public static final String ITRACKER_EMAIL_DISTRIBUTION = "itracker_email_distribution";
- public static final String ITRACKER_SYSTEM_USER = "itracker_system_user_id";
-
- public static final String MAIL_SERVER_HOST = "mail_server_host";
- public static final String MAIL_SERVER_PORT = "mail_server_port";
-
- // Routing Data Source keys
- public static final String ROUTING_DATASOURCE_KEY_NON_XA = "NON-XA";
- public static final String ROUTING_DATASOURCE_KEY_XA = "XA";
- public static final String QUARTZ_JOB_ENABLED = "quartz_job_enable";
- public static final String WORKFLOW_EMAIL_SENDER = "workflow_email_sender";
- public static final String DROOLS_GUVNOR_HOME = "drools.guvnor.home";
-
- // Hibernate Config
- public static final String HB_DIALECT = "hb.dialect";
- public static final String HB_SHOW_SQL = "hb.show_sql";
- // DataSource
- public static final String DB_DRIVER = "db.driver";
- public static final String DB_CONNECTIONURL = "db.connectionURL";
- public static final String DB_USERNAME = "db.userName";
- public static final String DB_PASSWOR = "db.password";
- public static final String DB_MIN_POOL_SIZE = "db.min_pool_size";
- public static final String DB_MAX_POOL_SIZE = "db.max_pool_size";
- public static final String IDLE_CONNECTION_TEST_PERIOD = "hb.idle_connection_test_period";
-
- public static final String MYLOGINS_FEED_CRON = "mylogins_feed_cron";
- public static final String SESSIONTIMEOUT_FEED_CRON = "sessiontimeout_feed_cron";
- public static final String LOG_CRON = "log_cron";
-
- public static final String DB_ENCRYPT_FLAG = "db.encrypt_flag";
-
- // Decryption Key
- public static final String Decryption_Key = "decryption_key";
-
- // Logging/Audit Fields
- public static final String MDC_APPNAME = "AppName";
- public static final String MDC_REST_PATH = "RestPath";
- public static final String MDC_REST_METHOD = "RestMethod";
- public static final String INSTANCE_UUID = "instance_uuid";
- public static final String MDC_CLASS_NAME = "ClassName";
- public static final String MDC_LOGIN_ID = "LoginId";
- public static final String MDC_TIMER = "Timer";
- public static final String SDK_NAME = "ECOMP_SDK";
- public static final String ECOMP_REQUEST_ID = "X-ECOMP-RequestID";
- public static final String PARTNER_NAME = "PartnerName";
- public static final String FULL_URL = "Full-URL";
- public static final String AUDITLOG_BEGIN_TIMESTAMP = "AuditLogBeginTimestamp";
- public static final String AUDITLOG_END_TIMESTAMP = "AuditLogEndTimestamp";
- public static final String METRICSLOG_BEGIN_TIMESTAMP = "MetricsLogBeginTimestamp";
- public static final String METRICSLOG_END_TIMESTAMP = "MetricsLogEndTimestamp";
- public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
- public static final String STATUS_CODE = "StatusCode";
- public static final String RESPONSE_CODE = "ResponseCode";
- public static final String TARGET_ENTITY = "TargetEntity"; //Component or sub component name
- public static final String TARGET_SERVICE_NAME = "TargetServiceName"; //API or operation name
-
- // Logging Compliance
- public static final String DOUBLE_WHITESPACE_SEPARATOR = " ";
- public static final String SINGLE_WHITESPACE_SEPARATOR = " ";
- public static final String SINGLE_QUOTE = "'";
- public static final String NA = "N/A";
- public static final String UNKNOWN = "Unknown";
- public static final String SECURITY_LOG_TEMPLATE = "Protocol:{0} Security-Event-Type:{1} Login-ID:{2} {3}";
- public static final String ECOMP_PORTAL_BE = "ECOMP_PORTAL_BE";
- public static final String PROTOCOL = "PROTOCOL";
- public static final String SECURIRY_EVENT_TYPE = "SECURIRY_EVENT_TYPE";
- public static final String LOGIN_ID = "LOGIN_ID";
- public static final String ACCESSING_CLIENT = "ACCESSING_CLIENT";
- public static final String RESULT_STR = "RESULT";
- public static final String ECOMP_PORTAL_FE = "ECOMP_PORTAL_FE";
- public static final String ADDITIONAL_INFO = "ADDITIONAL_INFO";
- public static final String INTERFACE_NAME = "INTERFACE_NAME";
- public static final String USERAGENT_NAME = "user-agent";
-
- // Protocols
- public static final String HTTP = "HTTP";
- public static final String HTTPS = "HTTPS";
- public static final String SSO_VALUE = "sso";
-
- public enum RESULT_ENUM {
- SUCCESS, FAILURE
- }
-
- public enum SecurityEventTypeEnum {
- FE_LOGIN_ATTEMPT, FE_LOGOUT, SSO_LOGIN_ATTEMPT_PHASE_1, SSO_LOGIN_ATTEMPT_PHASE_2, SSO_LOGOUT, LDAP_PHONEBOOK_USER_SEARCH, INCOMING_REST_MESSAGE, OUTGOING_REST_MESSAGE, REST_AUTHORIZATION_CREDENTIALS_MODIFIED, ECOMP_PORTAL_USER_MODIFIED, ECOMP_PORTAL_USER_ADDED, ECOMP_PORTAL_USER_REMOVED, ECOMP_PORTAL_WIDGET, INCOMING_UEB_MESSAGE, ECOMP_PORTAL_HEALTHCHECK
- }
-
- // Menu
- public static final String CONTACT_US_LINK = "contact_us_link";
-
- //Left Menu
- public static final String LEFT_MENU_PARENT = "parentList";
- public static final String LEFT_MENU_CHILDREND = "childItemList";
-
- // URL of the portal site that provides the shared-context REST service
- public static final String ECOMP_SHARED_CONTEXT_REST_URL = "ecomp_shared_context_rest_url";
-
- public static final String AUTH_USER_SERVER = "authenticate_user_server";
-}
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java
deleted file mode 100644
index 170d87cb..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/AppUtils.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.web.support;
-
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import javax.sql.DataSource;
-
-import org.hibernate.Session;
-import org.openecomp.portalsdk.core.exception.SessionExpiredException;
-import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
-import org.openecomp.portalsdk.core.service.DataAccessService;
-import org.springframework.beans.factory.annotation.Autowired;
-
-
-public class AppUtils {
-
- private static DataAccessService dataAccessService;
-
- private static AbstractCacheManager cacheManager;
-
- private static boolean applicationLocked;
-
- private static Hashtable feedback = new Hashtable();
-
- private static DataSource datasource;
-
- public static DataSource getDatasource() {
- return datasource;
- }
-
- @Autowired
- public void setDatasource(DataSource datasource) {
- AppUtils.datasource = datasource;
- }
-
- public AppUtils() {
- }
-
- public static HttpSession getSession(HttpServletRequest request) {
- HttpSession session = null;
- if (request != null) {
- session = request.getSession(false);
- if (session == null) {
- throw new SessionExpiredException();
- }
- } else {
- throw new SessionExpiredException();
- }
- return session;
- }
-
- public static List getLookupList(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy) {
- return getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
- } // getLookupList
-
- public static List getLookupList(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy, Session session) {
- String cacheKey = dbTable + "|" + dbValueCol + "|" + dbLabelCol + "|" + dbFilter + "|" + dbOrderBy;
- List list = getLookupListFromCache(cacheKey);
- if (list == null) {
- list = getDataAccessService().getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
- if (list != null) {
- addLookupListToCache(cacheKey, list);
- }
- } // if
- return list;
- } // getLookupList
-
- private static List getLookupListFromCache(String key) {
- return (List)getObjectFromCache(key);
- } // getLookupListFromCache
-
- public static Object getObjectFromCache(String key) {
- if (isCacheManagerAvailable()) {
- return getCacheManager().getObject(key);
- } else {
- return null;
- }
- } // getObjectFromCache
-
- private static void addLookupListToCache(String key, List list) {
- addObjectToCache(key, list);
- } // addLookupListToCache
-
- public static void addObjectToCache(String key, Object o) {
- if (isCacheManagerAvailable()) {
- getCacheManager().putObject(key, o);
- }
- } // addObjectToCache
-
- @Autowired
- public void setCacheManager(AbstractCacheManager cacheManager) {
- this.cacheManager = cacheManager;
- }
-
- public static AbstractCacheManager getCacheManager() {
- return cacheManager;
- }
-
- public static boolean isCacheManagerAvailable() {
- return (getCacheManager() != null);
- }
-
- public void setFeedback(Hashtable feedback) {
- this.feedback = feedback;
- }
-
- public static boolean isApplicationLocked() {
- return applicationLocked;
- }
-
- public static DataAccessService getDataAccessService() {
- return dataAccessService;
- }
-
- @Autowired
- public void setDataAccessService(DataAccessService dataAccessService) {
- this.dataAccessService = dataAccessService;
- }
-
- public static void setApplicationLocked(boolean locked) {
- applicationLocked = locked;
- }
-
- public static String getLookupValueByLabel(String label, String dbTable, String dbValueCol, String dbLabelCol) {
- if (label == null || label.equals("")) {
- return "";
- }
-
- List<org.openecomp.portalsdk.core.domain.Lookup> lstResult = getLookupListNoCache(dbTable, dbValueCol, dbLabelCol, dbLabelCol + "='" + label.replaceAll("'", "''") + "'", "");
- if (lstResult == null) {
- return "";
- }
- if (lstResult.size() > 0) {
- return ((org.openecomp.portalsdk.core.domain.Lookup)lstResult.toArray()[0]).getValue();
- } else {
- return "";
- }
- }
-
- public static String getLookupValueByLabel(String label, List lookupList) {
- Iterator i = null;
-
- if (label == null || label.equalsIgnoreCase("")) {
- return "";
- }
-
- if (lookupList == null || lookupList.size() == 0) {
- return "";
- }
-
- i = lookupList.iterator();
- while (i.hasNext()) {
- org.openecomp.portalsdk.core.domain.Lookup lookup = (org.openecomp.portalsdk.core.domain.Lookup)i.next();
-
- if (lookup.getLabel().equals(label)) {
- return lookup.getValue();
- }
- }
-
- return "";
-}
- public static List getLookupListNoCache(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy) {
- return getLookupListNoCache(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
- } // getLookupListNoCache
-
-
- public static List getLookupListNoCache(String dbTable, String dbValueCol, String dbLabelCol, String dbFilter, String dbOrderBy, Session session) {
- return getDataAccessService().getLookupList(dbTable, dbValueCol, dbLabelCol, dbFilter, dbOrderBy, null);
- } // getLookupListNoCache
-
-
-
-} // AppUtils
diff --git a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java b/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java
deleted file mode 100644
index 7f974574..00000000
--- a/ecomp-sdk/quantum/src/main/java/org/openecomp/portalsdk/core/web/support/UserUtils.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.web.support;
-
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.openecomp.portalsdk.core.FusionObject;
-import org.openecomp.portalsdk.core.domain.Role;
-import org.openecomp.portalsdk.core.domain.RoleFunction;
-import org.openecomp.portalsdk.core.domain.UrlsAccessible;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.exception.SessionExpiredException;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.menu.MenuBuilder;
-import org.openecomp.portalsdk.core.restful.domain.EcompRole;
-import org.openecomp.portalsdk.core.restful.domain.EcompUser;
-import org.openecomp.portalsdk.core.service.DataAccessService;
-import org.openecomp.portalsdk.core.util.CipherUtil;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-
-@SuppressWarnings("rawtypes")
-public class UserUtils implements Serializable, FusionObject {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private static final String USER_ID = "UserId";
-
- static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UserUtils.class);
-
- public static final String KEY_USER_ROLES_CACHE = "userRoles";
-
- public static final String WJ_HEADER_USER_NAME = "iv-user";
- public static final String WJ_HEADER_USER_GROUP = "iv-groups";
-
- private static DataAccessService dataAccessService;
-
- public static void setUserSession(HttpServletRequest request, User user, Set applicationMenuData, Set businessDirectMenuData, String loginMethod) {
- HttpSession session = request.getSession(true);
-
- UserUtils.clearUserSession(request); // let's clear the current user session to avoid any conflicts during the set
-
- session.setAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME), user);
-
- getRoleFunctions(request);
-
- // truncate the role (and therefore the role function) data to save memory in the session
- user.setRoles(null);
- session.setAttribute(SystemProperties.getProperty(SystemProperties.USER_NAME), user.getFullName());
- session.setAttribute(SystemProperties.FIRST_NAME, user.getFirstName());
- session.setAttribute(SystemProperties.LAST_NAME, user.getLastName());
- String displayName = "";
- if (SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) != null)
- displayName = SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME);
- session.setAttribute(SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME), displayName);
-
- session.setAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME), MenuBuilder.filterMenu(applicationMenuData, request));
- session.setAttribute(SystemProperties.getProperty(SystemProperties.BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME), MenuBuilder.filterMenu(businessDirectMenuData, request));
- }
-
- public static void clearUserSession(HttpServletRequest request) {
- HttpSession session = AppUtils.getSession(request);
-
- if (session == null) {
- throw new SessionExpiredException();
- }
-
- // removes all stored attributes from the current user's session
- session.removeAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
- session.removeAttribute(SystemProperties.getProperty(SystemProperties.APPLICATION_MENU_ATTRIBUTE_NAME));
- session.removeAttribute(SystemProperties.getProperty(SystemProperties.BUSINESS_DIRECT_MENU_ATTRIBUTE_NAME));
- session.removeAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME));
- session.removeAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME));
- }
-
- @SuppressWarnings("unchecked")
- public static Set getRoleFunctions(HttpServletRequest request) {
- HashSet roleFunctions = null;
-
- HttpSession session = request.getSession();
- roleFunctions = (HashSet)session.getAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME));
-
- if (roleFunctions == null) {
- HashMap roles = getRoles(request);
- roleFunctions = new HashSet();
-
- Iterator i = roles.keySet().iterator();
-
- while (i.hasNext()) {
- Long roleKey = (Long)i.next();
- Role role = (Role)roles.get(roleKey);
-
- Iterator j = role.getRoleFunctions().iterator();
-
- while (j.hasNext()) {
- RoleFunction function = (RoleFunction) j.next();
- roleFunctions.add(function.getCode());
- }
- }
-
- session.setAttribute(SystemProperties.getProperty(SystemProperties.ROLE_FUNCTIONS_ATTRIBUTE_NAME), roleFunctions);
- }
-
- return roleFunctions;
- }
-
- public static HashMap getRoles(HttpServletRequest request) {
- HashMap roles = null;
-
- //HttpSession session = request.getSession();
- HttpSession session = AppUtils.getSession(request);
- roles = (HashMap)session.getAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME));
-
- // if roles are not already cached, let's grab them from the user session
- if (roles == null) {
- User user = getUserSession(request);
-
- // get all user roles (including the tree of child roles)
- roles = getAllUserRoles(user);
-
- session.setAttribute(SystemProperties.getProperty(SystemProperties.ROLES_ATTRIBUTE_NAME), getAllUserRoles(user));
- }
-
- return roles;
- }
-
- public static User getUserSession(HttpServletRequest request) {
- HttpSession session = AppUtils.getSession(request);
-
- if (session == null) {
- throw new SessionExpiredException();
- }
-
- return (User)session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME));
- }
-
- @SuppressWarnings("unchecked")
- public static HashMap getAllUserRoles(User user) {
- HashMap roles = new HashMap();
- Iterator i = user.getRoles().iterator();
-
- while (i.hasNext()) {
- Role role = (Role)i.next();
-
- if (role.getActive()) {
- roles.put(role.getId(), role);
-
- // let's take a recursive trip down the tree to add all child roles
- addChildRoles(role, roles);
- }
- }
-
- return roles;
- }
-
- @SuppressWarnings("unchecked")
- private static void addChildRoles(Role role, HashMap roles) {
- Set childRoles = role.getChildRoles();
-
- if (childRoles != null && childRoles.size() > 0) {
- Iterator j = childRoles.iterator();
- while (j.hasNext()) {
- Role childRole = (Role)j.next();
-
- if (childRole.getActive()) {
- roles.put(childRole.getId(), childRole);
-
- addChildRoles(childRole, roles);
- }
- }
- }
-
- }
-
- @SuppressWarnings("unchecked")
- public static boolean isUrlAccessible(HttpServletRequest request, String currentUrl) {
- boolean isAccessible = false;
-
- Map params = new HashMap();
- params.put("current_url", currentUrl);
-
- List list = getDataAccessService().executeNamedQuery("restrictedUrls", params, null);
-
- // loop through the list of restricted URL's
- if (list != null && list.size() > 0) {
- for (int i=0; i < list.size(); i++) {
-
- UrlsAccessible urlFunctions = (UrlsAccessible) list.get(i);
- String functionCd = (String)urlFunctions.getFunctionCd();
-
- if (UserUtils.isAccessible(request, functionCd)) {
- isAccessible = true;
- }
- }
- return isAccessible;
- }
-
- return true;
- }
-
- public static boolean hasRole(HttpServletRequest request, String roleKey) {
- return getRoles(request).keySet().contains(new Long(roleKey));
- }
-
-
- public static boolean hasRole(User user, String roleKey) {
- return getAllUserRoles(user).keySet().contains(new Long(roleKey));
- }
-
- public static boolean isAccessible(HttpServletRequest request, String functionKey) {
- return getRoleFunctions(request).contains(functionKey);
- }
-
- public static DataAccessService getDataAccessService() {
- return dataAccessService;
- }
-
- @Autowired
- public void setDataAccessService(DataAccessService dataAccessService) {
- UserUtils.dataAccessService = dataAccessService;
- }
-
- public static int getUserId(HttpServletRequest request) {
- return getUserIdAsLong(request).intValue();
- }
-
- public static Long getUserIdAsLong(HttpServletRequest request) {
- Long userId = new Long(SystemProperties.getProperty(SystemProperties.APPLICATION_USER_ID));
-
- if (request != null) {
- if (getUserSession(request) != null) {
- userId = getUserSession(request).getId();
- }
- }
-
- return userId;
- }
-
-
- private static final Object stackTraceLock = new Object();
- public static String getStackTrace(Throwable t) {
- synchronized(stackTraceLock) {
- StringWriter sw = new StringWriter ();
- PrintWriter pw = new PrintWriter (sw);
- t.printStackTrace (pw);
- return sw.toString ();
- }
- }
-
- public static String getFullURL(HttpServletRequest request) {
- if (request!=null) {
- StringBuffer requestURL = request.getRequestURL();
- String queryString = request.getQueryString();
-
- if (queryString == null) {
- return requestURL.toString();
- } else {
- return requestURL.append('?').append(queryString).toString();
- }
- }
-
- return "";
- }
-
- public static String getRequestId(HttpServletRequest request) {
- Enumeration<String> headerNames = request.getHeaderNames();
-
- String requestId = "";
- try {
- while (headerNames.hasMoreElements()) {
- String headerName = (String) headerNames.nextElement();
- logger.info(EELFLoggerDelegate.debugLogger, "One header is " + headerName + " : " + request.getHeader(headerName));
- if (headerName.equalsIgnoreCase(SystemProperties.ECOMP_REQUEST_ID)) {
- requestId = request.getHeader(headerName);
- break;
- }
- }
- } catch (Exception e) {
- logger.error(EELFLoggerDelegate.debugLogger, "HEADER!!!! Exception : " + UserUtils.getStackTrace(e));
- }
-
- return (requestId.isEmpty() ? UUID.randomUUID().toString() : requestId);
- }
-
-
- public static EcompUser convertToEcompUser (User user){
- EcompUser userJson = new EcompUser();
-
-
- userJson.setEmail(user.getEmail());
- userJson.setFirstName(user.getFirstName());
- userJson.setHrid(user.getHrid());
- userJson.setJobTitle(user.getJobTitle());
- userJson.setLastName(user.getLastName());
- userJson.setLoginId(user.getLoginId());
- userJson.setOrgManagerUserId(user.getOrgManagerUserId());
- userJson.setMiddleInitial(user.getMiddleInitial());
- userJson.setOrgCode(user.getOrgCode());
- userJson.setOrgId(user.getOrgId());
- userJson.setPhone(user.getPhone());
- userJson.setOrgUserId(user.getOrgUserId());
-
-
- Set<EcompRole> ecompRoles = new TreeSet<EcompRole>();
-
- for(Role role : user.getRoles()){
- ecompRoles.add(convertToEcompRole(role));
- }
-
- userJson.setRoles(ecompRoles);
-
- return userJson;
- }
-
- public static EcompRole convertToEcompRole(Role role){
-
- EcompRole ecompRole = new EcompRole();
- ecompRole.setId(role.getId());
- ecompRole.setName(role.getName());
-
- return ecompRole;
- }
-
- public static String getUserIdFromCookie(HttpServletRequest request) throws Exception {
- String userId = "";
- Cookie[] cookies = request.getCookies();
- Cookie userIdcookie = null;
- if (cookies != null)
- for (Cookie cookie : cookies)
- if (cookie.getName().equals(USER_ID))
- userIdcookie = cookie;
- if(userIdcookie!=null){
- userId = CipherUtil.decrypt(userIdcookie.getValue(),
- SystemProperties.getProperty(SystemProperties.Decryption_Key));
- }
- return userId;
-
- }
-}
diff --git a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java b/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java
deleted file mode 100644
index 0f918f6b..00000000
--- a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.openecomp.portalsdk.core;
-
-import java.io.IOException;
-
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.openecomp.portalsdk.core.conf.AppConfig;
-import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
-import org.openecomp.portalsdk.core.util.CacheManager;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
-import org.springframework.test.context.web.WebAppConfiguration;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-
-
-/**
- *
- *
- *
- * In order to write a unit test,
- * 1. inherit this class - See SanityTest.java
- * 2. place the "war" folder on your test class's classpath
- * 3. run the test with the following VM argument; This is important because when starting the application from Container, the System Properties file (SystemProperties.java) can have the direct path
- * but, when running from the Mock Junit container, the path should be prefixed with "classpath" to enable the mock container to search for the file in the classpath
- * -Dcontainer.classpath="classpath:"
- *
- */
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {MockAppConfig.class})
-@ActiveProfiles(value="test")
-public class MockApplicationContextTestSuite {
-
- @Autowired
- public WebApplicationContext wac;
-
- private MockMvc mockMvc;
-
- @Before
- public void setup() {
- if(mockMvc == null) {
- this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
-
- }
- }
-
- public Object getBean(String name) {
- return this.wac.getBean(name);
- }
-
-
- public MockMvc getMockMvc() {
- return mockMvc;
- }
-
- public void setMockMvc(MockMvc mockMvc) {
- this.mockMvc = mockMvc;
- }
-
- public WebApplicationContext getWebApplicationContext() {
- return wac;
- }
-
-
-
-
-}
-
-
- @Configuration
- @ComponentScan(basePackages = "org.openecomp",
- excludeFilters = {
-
- }
- )
- @Profile("test")
- class MockAppConfig extends AppConfig {
-
- @Bean
- public SystemProperties systemProperties(){
- return new MockSystemProperties();
- }
-
- @Bean
- public AbstractCacheManager cacheManager() {
- return new CacheManager() {
-
- public void configure() throws IOException {
-
- }
- };
- }
-
- protected String[] tileDefinitions() {
- return new String[] {"classpath:/WEB-INF/fusion/defs/definitions.xml", "classpath:/WEB-INF/defs/definitions.xml"};
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //registry.addInterceptor(new SessionTimeoutInterceptor()).excludePathPatterns(getExcludeUrlPathsForSessionTimeout());
- //registry.addInterceptor(resourceInterceptor());
- }
-
- public static class MockSystemProperties extends SystemProperties {
-
- public MockSystemProperties() {
- }
-
- }
-
- }
-
-
-
-
diff --git a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockHibernateMappingLocations.java b/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockHibernateMappingLocations.java
deleted file mode 100644
index a7de5159..00000000
--- a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/MockHibernateMappingLocations.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.openecomp.portalsdk.core;
-
-
-
-import org.openecomp.portalsdk.core.conf.HibernateMappingLocatable;
-import org.springframework.context.annotation.Profile;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-@Profile("test")
-public class MockHibernateMappingLocations implements HibernateMappingLocatable{
-
- public Resource[] getMappingLocations() {
- return new Resource[]{new ClassPathResource("WEB-INF/fusion/orm/Fusion.hbm.xml"), new ClassPathResource("WEB-INF/fusion/orm/Workflow.hbm.xml")};
- }
-
-
-}
diff --git a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/controller/sessionmgt/PortalCommunicationTest.java b/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/controller/sessionmgt/PortalCommunicationTest.java
deleted file mode 100644
index 3e14becb..00000000
--- a/ecomp-sdk/quantum/src/test/java/org/openecomp/portalsdk/core/controller/sessionmgt/PortalCommunicationTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.openecomp.portalsdk.core.controller.sessionmgt;
-/*package org.openecomp.portalsdk.core.controller.sessionmgt;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.springframework.mock.web.MockHttpSession;
-import org.springframework.test.web.servlet.ResultActions;
-import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-
-import org.openecomp.portalsdk.core.MockApplicationContextTestSuite;
-import org.openecomp.portalsdk.core.service.sessionmgt.CoreTimeoutHandler;
-
-public class PortalCommunicationTest extends MockApplicationContextTestSuite{
-
-
- @Test
- public void testGetTimeoutSessions() throws Exception {
-
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/sessionTimeOuts");
- MockHttpSession httpSession = new MockHttpSession(this.wac.getServletContext(),"1234");
- CoreTimeoutHandler.sessionCreated("12", "1234", httpSession);
-
- ResultActions ra = this.getMockMvc().perform(requestBuilder);
-
- System.out.println(" %%%%%%%%%%%%%%%%%%%%%%%%% " + ra.andReturn().getResponse().getContentAsString());
- System.out.println(" %%%%%%%%%%%%%%%%%%%%%%%%% " + "{\"12\":{\"jSessionId\":\"1234\",\"sessionTimOutMilliSec\":");
-
- Assert.assertTrue(ra.andReturn().getResponse().getContentAsString().startsWith("{\"12\":{\"jSessionId\":\"1234\",\"sessionTimOutMilliSec\":"));
-
- }
-
- @Test
- public void testUpdateTimeoutSessions() throws Exception {
-
- // pre condition
- MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/sessionTimeOuts");
- MockHttpSession httpSession = new MockHttpSession(this.wac.getServletContext(),"1234");
- CoreTimeoutHandler.sessionCreated("12", "1234", httpSession);
- ResultActions ra = this.getMockMvc().perform(requestBuilder);
-
- String responseSessMapStr = ra.andReturn().getResponse().getContentAsString();
-
-
- // test
- requestBuilder = MockMvcRequestBuilders.post("/api/updateSessionTimeOuts");
- requestBuilder.param("sessionMap", responseSessMapStr);
- ra = this.getMockMvc().perform(requestBuilder);
-
-
- }
-
-
-
-}
-*/ \ No newline at end of file
diff --git a/ecomp-sdk/sdk-analytics/.gitignore b/ecomp-sdk/sdk-analytics/.gitignore
deleted file mode 100644
index d4111ffd..00000000
--- a/ecomp-sdk/sdk-analytics/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/.settings/
-/target/
diff --git a/ecomp-sdk/sdk-analytics/README.md b/ecomp-sdk/sdk-analytics/README.md
deleted file mode 100644
index e7a5d130..00000000
--- a/ecomp-sdk/sdk-analytics/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-ECOMP Portal SDK Analytics
-==========================
-
-This is the Maven project for the ECOMP Portal SDK Analytics,
-which is distributed as ecompSDK-analytics-nnn.jar. This library
-requires Hibernate and Spring, and provides features including
-charts, maps and reports.
-
diff --git a/ecomp-sdk/sdk-analytics/pom.xml b/ecomp-sdk/sdk-analytics/pom.xml
deleted file mode 100644
index 5209c94f..00000000
--- a/ecomp-sdk/sdk-analytics/pom.xml
+++ /dev/null
@@ -1,160 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-project</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>ecompSDK-analytics</artifactId>
- <name>Ecomp Portal SDK Analytics</name>
- <description>Provides reporting features for SDK applications</description>
- <packaging>jar</packaging>
-
-
- <!-- repositories are inherited from parent -->
-
- <dependencies>
-
- <!-- sdk-core -->
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-core</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.6.3</version>
- </dependency>
- <!-- Raptor required Libraries -->
- <!-- for static charts -->
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.10</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- </dependency>
- <!-- for generating PDF -->
- <dependency>
- <groupId>com.lowagie</groupId>
- <artifactId>itext</artifactId>
- <version>2.0.8</version>
- </dependency>
- <!-- bridge to implement commons-logging using slf4j -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${springframework.version}</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-orm</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <!-- for generating excel/csv/excelx -->
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi</artifactId>
- <version>3.5-FINAL</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-ooxml</artifactId>
- <version>3.5-FINAL</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-scratchpad</artifactId>
- <version>3.5-FINAL</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-contrib</artifactId>
- <version>3.5-FINAL</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-
-</project>
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java
deleted file mode 100644
index eeb2b605..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/AntBuild.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-
-/**
- * This class is used to get version and Build information when
- * user run "java -jar raptor_classes.jar" command.
- */
-public class AntBuild {
-
- public static String buildNum = "";
-
- public static void main(String[] args) {
- System.out.println("Jar (raptor_classes.jar) Information: ");
- readManifest();
- }
-
- public static void readManifest() {
- try {
- Class clazz = AntBuild.class;
- String classContainer = clazz.getProtectionDomain().getCodeSource().getLocation().toString();
- URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF");
- Manifest manifest = new Manifest(manifestUrl.openStream());
-
- //JarFile jar = new JarFile("../lib/raptor_classes.jar");
- //Manifest manifest = jar.getManifest();
-
- Attributes attribs = manifest.getMainAttributes();
- Iterator it = attribs.entrySet().iterator();
- while(it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- Attributes.Name attributeName = (Attributes.Name) entry.getKey();
- String attributeValue = (String) entry.getValue();
- if (attributeName.toString().equals("Created-By"))
- System.out.println("Java HotSpot(TM) Client VM " + " : " + attributeValue);
- else if (attributeName.toString().equals("Java-Version"))
- System.out.println("Java Version " + " : " + attributeValue);
- else if (attributeName.toString().equals("Java-Runtime-Version"))
- System.out.println("Java Runtime Version " + " : " + attributeValue);
- else if (attributeName.toString().equals("Ant-Version"))
- System.out.println(attributeName.toString() + " : " + attributeValue);
- else {
- if(attributeName.toString().startsWith("Raptor")) {
- if (attributeName.toString().startsWith("Raptor-Build-Version"))
- buildNum = attributeValue;
- System.out.println(attributeName.toString() + " : " + attributeValue);
- }
- }
- }
-
- } catch (IOException e) {
- System.err.println("Cannot read jar-file manifest: "
- + e.getMessage());
- }
- }
-
- public static String getBuildNum() {
- if (buildNum.length()>0)
- return buildNum;
- else {
- readManifest();
- return buildNum;
- }
- }
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java
deleted file mode 100644
index bca56955..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/controller/ErrorHandler.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.controller;
-
-import java.util.ArrayList;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.error.ReportSQLException;
-import org.openecomp.portalsdk.analytics.model.definition.ReportDefinition;
-import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-
-public class ErrorHandler extends org.openecomp.portalsdk.analytics.RaptorObject {
-
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ErrorHandler.class);
-
- public ErrorHandler() {
- }
-
- public void processError(HttpServletRequest request, String errorMsg) {
- //Log.write(errorMsg, 2);
- logger.error(EELFLoggerDelegate.debugLogger, (errorMsg));
- ArrayList error_list = (ArrayList) request.getAttribute(AppConstants.RI_ERROR_LIST);
- if (error_list == null)
- error_list = new ArrayList(1);
- error_list.add(errorMsg);
- request.setAttribute(AppConstants.RI_ERROR_LIST, error_list);
- } // processError
-
- public void processError(HttpServletRequest request, RaptorException e) {
- processError(request, "Exception: " + e.getMessage());
- } // processError
-
- private String getSessionLog(HttpServletRequest request) {
- String[] sessionVariablesToLog = Globals.getLogVariablesInSession().split(",");
- StringBuffer sessionLogStrBuf = new StringBuffer("\n");
- sessionLogStrBuf.append("***** ADDITIONAL INFORMATION ******");
- HttpSession session = request.getSession();
- ReportRuntime rr = (ReportRuntime) session.getAttribute(AppConstants.SI_REPORT_RUNTIME);
- ReportDefinition rdef = (ReportDefinition) session.getAttribute(AppConstants.SI_REPORT_DEFINITION);
- if(rr!=null) {
- sessionLogStrBuf.append("\nWHILE RUNNING");
- sessionLogStrBuf.append("\nReport Id="+rr.getReportID()+";\t");
- sessionLogStrBuf.append("Report Name="+rr.getReportName()+";\t\n");
- } else if (rdef != null) {
- sessionLogStrBuf.append("\nWHILE CREATING/UPDATING");
- sessionLogStrBuf.append("\nReport Id="+rdef.getReportID()+";\t");
- sessionLogStrBuf.append("Report Name="+rdef.getReportName()+";\t\n");
- }
- for (int i = 0; i < sessionVariablesToLog.length; i++) {
- if(session.getAttribute(sessionVariablesToLog[i])!=null)
- sessionLogStrBuf.append(sessionVariablesToLog[i]+"="+(String)session.getAttribute(sessionVariablesToLog[i])+";\t");
- }
- sessionLogStrBuf.append("\n***********************************");
- sessionLogStrBuf.append("\n");
- return sessionLogStrBuf.toString();
- }
- public String processFatalError(HttpServletRequest request, RaptorException e) {
- //Log.write("Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage()), 1);
- logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage())+" "+ getSessionLog(request) + e.getMessage()),AlarmSeverityEnum.MAJOR);
- if (e instanceof ReportSQLException) {
- String errorSQL = ((ReportSQLException) e).getReportSQL();
- if (nvl(errorSQL).length() > 0)
- request.setAttribute("c_error_sql", errorSQL);
- } // if
- AppUtils.processErrorNotification(request, e);
-
- request.setAttribute(AppConstants.RI_EXCEPTION, e);
- return AppUtils.getErrorPage();
- } // processFatalError
-
- public String processFatalErrorWMenu(HttpServletRequest request, RaptorException e) {
- //Log.write("Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage()), 1);
- logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] Fatal error [" + e.getClass().getName() + "]: " + nvl(e.getMessage())+" "+ getSessionLog(request) + e.getMessage()),AlarmSeverityEnum.MAJOR);
- if (e instanceof ReportSQLException) {
- String errorSQL = ((ReportSQLException) e).getReportSQL();
- if (nvl(errorSQL).length() > 0)
- request.setAttribute("c_error_sql", errorSQL);
- } // if
- AppUtils.processErrorNotification(request, e);
-
- request.setAttribute(AppConstants.RI_EXCEPTION, e);
- return AppUtils.getErrorPageWMenu();
- } // processFatalError
-
-} // ErrorHandler
-
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java
deleted file mode 100644
index 450349c7..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/definition/ReportMap.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.model.definition;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openecomp.portalsdk.analytics.RaptorObject;
-
-public class ReportMap extends RaptorObject {
- String markerColor = "";
- String addressColumn = "";
- String dataColumn = "";
- String isMapAllowedYN = "";
- String addAddressInDataYN = "";
- List markers = new ArrayList();
-
- public String getIsMapAllowedYN() {
- return isMapAllowedYN;
- }
- public void setIsMapAllowedYN(String isMapAllowedYN) {
- this.isMapAllowedYN = isMapAllowedYN;
- }
- public ReportMap(String markerColor, String addressColumn, String dataColumn, String isMapAllowed, String addAddressInDataYN){
- this.setMarkerColor(markerColor);
- this.setAddressColumn(addressColumn);
- this.setDataColumn(dataColumn);
- this.setIsMapAllowedYN(isMapAllowed);
- this.setAddAddressInDataYN(addAddressInDataYN);
- }
- public String getAddressColumn() {
- return addressColumn;
- }
- public void setAddressColumn(String addressColumn) {
- this.addressColumn = addressColumn;
- }
- public String getDataColumn() {
- return dataColumn;
- }
- public void setDataColumn(String dataColumn) {
- this.dataColumn = dataColumn;
- }
- public String getMarkerColor() {
- return markerColor;
- }
- public void setMarkerColor(String markerColor) {
- this.markerColor = markerColor;
- }
- public List getMarkers() {
- return markers;
- }
- public void setMarkers(List markers) {
- this.markers = markers;
- }
- public String getAddAddressInDataYN() {
- return addAddressInDataYN;
- }
- public void setAddAddressInDataYN(String addAddressInDataYN) {
- this.addAddressInDataYN = addAddressInDataYN;
- }
-
-
-
-
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartGen.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartGen.java
deleted file mode 100644
index c395000e..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ChartGen.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.model.runtime;
-
-import java.io.PrintWriter;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.List;
-
-import javax.servlet.http.HttpSession;
-
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.util.Log;
-
-public class ChartGen extends org.openecomp.portalsdk.analytics.RaptorObject {
-
- public static String generateChart(String chartType, HttpSession session, DataSet ds,
- String xText, String yLabelLeftAxis, String yLabelRightAxis, List yTextSeries,
- List yTextColor, List yTextSeriesAxis, String groupText, String chartTitle,
- PrintWriter pw,List columnValuesList, boolean hasCategoryAxis, boolean isMultiSeries,
- List allColumnsList, String downloadFileName, boolean totalOnlyChart, int deviceType, HashMap additionalChartOptionsMap) {
- return generateChart(chartType, session, ds, xText, yLabelLeftAxis, yLabelRightAxis,
- yTextSeries, yTextColor, yTextSeriesAxis, groupText, chartTitle, pw, Globals
- .getDefaultChartWidth(), Globals.getDefaultChartHeight(), columnValuesList, hasCategoryAxis, isMultiSeries, allColumnsList, downloadFileName,totalOnlyChart, deviceType, additionalChartOptionsMap);
- } // generateChart
-
- public static String generateChart(String chartType, HttpSession session, DataSet ds,
- String xText, String yLabelLeftAxis, String yLabelRightAxis, List yTextSeries,
- List yTextColor, List yTextSeriesAxis, String groupText, String chartTitle,
- PrintWriter pw, int width, int height, List columnValuesList, boolean hasCategoryAxis, boolean isMultiSeries,
- List allColumnsList, String downloadFileName,boolean totalOnlyChart, int deviceType, HashMap additionalChartOptionsMap) {
- try {
- Class chartGenClass = null;
-
-
- Class[] argumentTypes = { String.class, HttpSession.class, DataSet.class,
- String.class, String.class, String.class, List.class, List.class,
- List.class, String.class, String.class, PrintWriter.class, int.class,
- int.class, List.class, boolean.class, boolean.class, List.class,
- String.class, boolean.class, int.class, HashMap.class };
-
- Method method = chartGenClass.getMethod("generateChart", argumentTypes);
- Object[] arguments = { chartType, session, ds, xText, yLabelLeftAxis,
- yLabelRightAxis, yTextSeries, yTextColor, yTextSeriesAxis, groupText,
- chartTitle, pw, new Integer(width), new Integer(height), columnValuesList, new Boolean(hasCategoryAxis), new Boolean(isMultiSeries), allColumnsList, downloadFileName, new Boolean(totalOnlyChart), new Integer(deviceType), additionalChartOptionsMap };
-
- return (String) method.invoke(chartGenClass, arguments);
- } catch (Exception e) {
- e.printStackTrace();
- Log.write("ERROR [ChartGen.generateChart] " + e.getMessage());
- return null;
- }
- } // generateChart
-
-} // ChartGen
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java
deleted file mode 100644
index d619c4e0..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/runtime/ErrorJSONRuntime.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.model.runtime;
-
-public class ErrorJSONRuntime {
-
- private String errormessage;
- private String stacktrace;
-
- public String getErrormessage() {
- return errormessage;
- }
- public void setErrormessage(String errormessage) {
- this.errormessage = errormessage;
- }
- public String getStacktrace() {
- return stacktrace;
- }
- public void setStacktrace(String stacktrace) {
- this.stacktrace = stacktrace;
- }
-
-
-
-
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java
deleted file mode 100644
index 5ab75590..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/model/search/SearchResult.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.model.search;
-
-import java.util.ArrayList;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-
-public class SearchResult{
- private int pageNo = -1;
-
- private int pageSize = 50;
-
- private int dataSize = -1;
-
- private int writeAccessColIndex = -1;
-
- private int ownerIndicatorColIndex = -1;
-
- private String csvPageFileName = null;
-
-
-
- private String csvAllRowsFileName = null;
-
- private String excelAllRowsFileName = null;
-
- public ArrayList searchResultColumns = new ArrayList();
-
- public ArrayList searchResultRows = new ArrayList();
-
- public SearchResult(int pageNo) {
- this(pageNo, Globals.getDefaultPageSize());
- } // SearchResult
-
- public SearchResult(int pageNo, int pageSize) {
- this(pageNo, pageSize, -1, -1);
- } // SearchResult
-
- public SearchResult(int pageNo, int pageSize, int writeAccessColIndex,
- int ownerIndicatorColIndex) {
- super();
-
- this.pageNo = pageNo;
- this.pageSize = pageSize;
-
- this.writeAccessColIndex = writeAccessColIndex;
- this.ownerIndicatorColIndex = ownerIndicatorColIndex;
- } // SearchResult
-
- public int getPageNo() {
- return pageNo;
- }
-
- public int getPageSize() {
- return pageSize;
- }
-
- public int getDataSize() {
- return dataSize;
- }
-
- public String getCsvPageFileName() {
- return csvPageFileName;
- }
-
- public String getCsvAllRowsFileName() {
- return csvAllRowsFileName;
- }
-
- public String getExcelAllRowsFileName() {
- return excelAllRowsFileName;
- }
-
- private void setDataSize(int dataSize) {
- this.dataSize = dataSize;
- }
-
- public void setCsvPageFileName(String csvPageFileName) {
- this.csvPageFileName = csvPageFileName;
- }
-
-
-
- public void setCsvAllRowsFileName(String csvAllRowsFileName) {
- this.csvAllRowsFileName = csvAllRowsFileName;
- }
-
-
-
- public void addColumn(SearchResultColumn column) {
- searchResultColumns.add(column);
- } // addColumn
-
- public SearchResultColumn getColumn(int index) {
- return (SearchResultColumn) searchResultColumns.get(index);
- } // getColumn
-
- public int getNumColumns() {
- return searchResultColumns.size();
- } // getNumColumns
-
- public int getNumRows() {
- return searchResultRows.size();
- } // getNumRows
-
- public SearchResultRow getRow(int index) {
- return (SearchResultRow) searchResultRows.get(index);
- } // getRow
-
- public void parseData(DataSet ds, HttpServletRequest request) throws RaptorException {
- // Presumes single ID field in the first column of the DataSet and row
- // number in the first SearchResultColumn
- String userID = AppUtils.getUserID(request);
- setDataSize(ds.getRowCount());
-
- int startRow = (pageNo >= 0) ? (pageNo * pageSize) : 0;
- int endRow = (pageNo >= 0) ? Math.min(startRow + pageSize, ds.getRowCount()) : ds
- .getRowCount();
- for (int r = startRow; r < endRow; r++) {
- SearchResultRow row = new SearchResultRow();
- searchResultRows.add(row);
-
- String idValue = ds.getString(r, 0);
-
- boolean bCanEdit = true;
- if (writeAccessColIndex >= 0) {
- String isReadOnlyValue = nvl(ds.getString(r, writeAccessColIndex), "Y");
- bCanEdit = AppUtils.isSuperUser(request) || AppUtils.isAdminUser(request)
- || isReadOnlyValue.equals("N");
- }
-
- boolean bCanDelete = bCanEdit;
- if (Globals.getDeleteOnlyByOwner() && ownerIndicatorColIndex >= 0) {
- String isOwnedByUserRecord = nvl(ds.getString(r, ownerIndicatorColIndex), "N");
- bCanDelete = AppUtils.isSuperUser(request) || isOwnedByUserRecord.equals("Y");
- }
-
- boolean bCanSchedule = ds.getString(r, getNumColumns()-3).equals("Y");
-
- row.addSearchResultField(new SearchResultField("" + (r + 1), idValue,
- getColumn(0), true));
- boolean isAuthorized = true;
- for (int c = 1; c < getNumColumns(); c++) {
- SearchResultColumn column = getColumn(c);
- isAuthorized = true;
-
- if(column.isCopyLink())
- isAuthorized = Globals.getCanCopyOnReadOnly()? true:bCanEdit;
- else if (column.isDeleteLink())
- isAuthorized = bCanDelete;
- else if (column.isEditLink())
- isAuthorized = bCanEdit;
- else if (column.isScheduleLink())
- isAuthorized = bCanSchedule;
-
- row.addSearchResultField(new SearchResultField(
- (column.getLinkURL() == null) ? ds.getString(r, c) : column
- .getLinkTitle(), idValue, column, isAuthorized
- ));
- } // for
- } // for
- } // parseData
-
- public void truncateToPage(int pageNo) {
- if (this.pageNo >= 0 || pageNo < 0)
- return;
-
- this.pageNo = pageNo;
-
- int startRow = pageNo * pageSize;
- int endRow = Math.min(startRow + pageSize, dataSize);
-
- for (int r = getNumRows() - 1; r >= endRow; r--)
- searchResultRows.remove(r);
-
- for (int r = startRow - 1; r >= 0; r--)
- searchResultRows.remove(r);
- } // truncateToPage
-
- /** *********************************************************************** */
-
- private String nvl(String s) {
- return (s == null) ? "" : s;
- }
-
- private String nvl(String s, String sDefault) {
- return nvl(s).equals("") ? sDefault : s;
- }
-
-} // SearchResult
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java
deleted file mode 100644
index ce070c3a..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/AppUtils.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Vector;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.util.HtmlStripper;
-
-public class AppUtils /* implements IAppUtils */{
- private static String baseURL = null;
-
- private AppUtils() {
- }
-
- /** ******************************************************** */
-
- public static String generateFileName(HttpServletRequest request, String fileTypeExtension) {
- return AppConstants.FILE_PREFIX + getUserID(request) + fileTypeExtension;
- } // generateFileName
-
- public static String generateUniqueFileName(HttpServletRequest request, String reportName, String fileTypeExtension) {
- String formattedReportName = new HtmlStripper().stripSpecialCharacters(reportName);
- String formattedDate = new SimpleDateFormat("MMddyyyyHHmm").format(new Date());
- return formattedReportName+formattedDate+getUserID(request)+fileTypeExtension;
- } // generateFileName
-
- public static String getRequestValue(HttpServletRequest request, String valueID) {
- String value = (String) request.getAttribute(valueID);
- if (value == null)
- value = request.getParameter(valueID);
- return value;
- } // getRequestValue
-
- public static String getRequestNvlValue(HttpServletRequest request, String valueID) {
- String value = getRequestValue(request, valueID);
- return (value == null) ? "" : value;
- } // getRequestValue
-
- public static boolean getRequestFlag(HttpServletRequest request, String valueID) {
- String value = getRequestNvlValue(request, valueID);
- return value.toLowerCase().equals("true") || value.toUpperCase().startsWith("Y");
- } // getRequestFlag
-
- /** ******************************************************** */
-
- public static String getUserID(HttpServletRequest request) {
- return Globals.getAppUtils().getUserID(request);
- } // getUserID
-
- public static String getUserName(HttpServletRequest request) {
- return Globals.getAppUtils().getUserName(request);
- } // getUserName
-
- public static String getUserName(String userId) {
- return Globals.getAppUtils().getUserName(userId);
- } // getUserName
-
- public static String getUserEmail(String userId) {
- return Globals.getAppUtils().getUserEmail(userId);
- } // getUserEmail
-
- public static String getUserEmail(HttpServletRequest request) {
- return Globals.getAppUtils().getUserEmail(request);
- } // getUserEmail
-
- public static String getUserLoginId(HttpServletRequest request) {
- return Globals.getAppUtils().getUserLoginId(request);
- } // getUserLoginId
-
- public static String getUserLoginId(String userId) {
- return Globals.getAppUtils().getUserLoginId(userId);
- } // getUserLoginId
-
- public static String getUserBackdoorLoginId(HttpServletRequest request) {
- return Globals.getAppUtils().getUserBackdoorLoginId(request);
- } // getUserBackdoorLoginId
-
- public static Vector getAllUsers(String customizedQuery, String param, boolean isAdmin) {
- return Globals.getAppUtils().getAllUsers(customizedQuery, param, isAdmin);
- } // getAllUsers
-
- public static String getRoleName(String roleId) {
- return Globals.getAppUtils().getRoleName(roleId);
- } // getRoleName
-
- public static Vector getAllRoles(String customizedQuery, String param, boolean isAdmin) {
- return Globals.getAppUtils().getAllRoles(customizedQuery, param, isAdmin);
- } // getAllRoles
-
- public static boolean isUserInRole(HttpServletRequest request, String roleId) throws RaptorException {
- return Globals.getAppUtils().isUserInRole(request,roleId);
- } // isUserInRole
-
-// public static boolean isUserInRole(String userId, String roleId) throws RaptorException {
-// return Globals.getAppUtils().isUserInRole(userId, roleId);
-// } // isUserInRole
-
- public static Vector getUserRoles(HttpServletRequest request) throws RaptorException {
- return Globals.getAppUtils().getUserRoles(request);
- } // getUserRoles
-
- public static Vector getUserRoles(String userID) throws RaptorException {
- return Globals.getAppUtils().getUserRoles(userID);
- } // getUserRoles
-
-// public static Vector getUserRoles(HttpServletRequest request) throws RaptorException {
-// return Globals.getAppUtils().getUserRoles(request);
-// } // getUserRoles
-
- public static void resetUserCache() {
- Globals.getAppUtils().resetUserCache();
- } // resetUserCache
-
- public static String getSuperRoleID() {
- return Globals.getAppUtils().getSuperRoleID();
- } // getSuperRoleID
-
- public static Vector getAdminRoleIDs() {
- return Globals.getAppUtils().getAdminRoleIDs();
- } // getAdminRoleIDs
-
- // This is changed to check for Admin User as admin user also need super user privilege if explicitly specified in properties file.
- public static boolean isSuperUser(HttpServletRequest request)throws RaptorException {
- if(Globals.isAdminRoleEquivalenttoSuperRole()) return isAdminUser(request);
- else return isUserInRole(request, getSuperRoleID());
- } // isSuperUser
-
- /*public static boolean isSuperUser(String userId) throws RaptorException {
- if(Globals.isAdminRoleEquivalenttoSuperRole()) return isAdminUser(userId);
- else return isUserInRole(userId, getSuperRoleID());
- } // isSuperUser
- */
-
- public static boolean isAdminUser(HttpServletRequest request) throws RaptorException {
- if (isSuperUser(request))
- return true;
- for (int i = 0; i < getAdminRoleIDs().size(); i++)
- if (isUserInRole(request, (String) getAdminRoleIDs().get(i)))
- return true;
-
- return false;
- } // isAdminUser
-
- /*public static boolean isAdminUser(String userId) throws RaptorException {
- if (isSuperUser(userId))
- return true;
-
- for (int i = 0; i < getAdminRoleIDs().size(); i++)
- if (isUserInRole(userId, (String) getAdminRoleIDs().get(i)))
- return true;
-
- return false;
- } // isAdminUser
- */
-
- public static String getTempFolderPath() {
- String path = Globals.getAppUtils().getTempFolderPath();
- if (path.endsWith(File.separator) || path.endsWith("/")){
- return path;
- } else {
- path = path + File.separator;
- return path;
- }
- } // getTempFolderPath
-
- public static String getUploadFolderPath() {
- String path = Globals.getAppUtils().getUploadFolderPath();
- if (path.endsWith(File.separator)){
- return path;
- } else {
- path = path + File.separator;
- return path;
- }
- } // getUploadFolderPath
-
- public static String getTempFolderURL() {
- return Globals.getAppUtils().getTempFolderURL();
- } // getTempFolderURL
-
- public static String getUploadFolderURL() {
- return Globals.getAppUtils().getUploadFolderURL();
- } // getUploadFolderURL
-
- public static String getSMTPServer()throws Exception {
- return Globals.getAppUtils().getSMTPServer();
- } // getSMTPServer
-
- public static String getDefaultEmailSender() throws RaptorException {
- return Globals.getAppUtils().getDefaultEmailSender();
- } // getDefaultEmailSender
-
- public static String getErrorPage() {
- return getJspContextPath() + Globals.getAppUtils().getErrorPage();
- } // getErrorPage
-
- public static String getErrorPageWMenu() {
- return getJspContextPath() + Globals.getAppUtils().getErrorPageWMenu();
- } // getErrorPage
-
- public static String getJspContextPath() {
- return Globals.getAppUtils().getJspContextPath();
- } // getJspContextPath
-
- public static String getImgFolderURL() {
- return Globals.getAppUtils().getImgFolderURL();
- } // getImgFolderURL
-
- public static String getBaseFolderURL() {
- return Globals.getAppUtils().getBaseFolderURL();
- } // getBaseFolderURL
-
- /*
- * public static String getReportExecuteActionURL() { return
- * Globals.getAppUtils().getReportExecuteActionURL(); } //
- * getReportExecuteActionURL
- *
- * public static String getDataViewActionURL() { return
- * Globals.getAppUtils().getDataViewActionURL(); } // getDataViewActionURL
- *
- * public static String getDataViewActionParam() { return
- * Globals.getAppUtils().getDataViewActionParam(); } //
- * getDataViewActionParam
- */
- public static String getDirectAccessURL() {
- return Globals.getAppUtils().getDirectAccessURL();
- } // getDirectAccessURL
-
- public static String getBaseURL() {
- if (baseURL == null) {
- baseURL = getBaseActionURL();
- if (baseURL.indexOf("?") > 0)
- baseURL = baseURL.substring(0, baseURL.indexOf("?"));
- } // if
-
- return baseURL;
- } // getBaseURL
-
- public static String getBaseActionURL() {
- return Globals.getAppUtils().getBaseActionURL();
- } // getBaseActionURL
-
- public static String getDrillActionURL() {
- return Globals.getAppUtils().getDrillActionURL();
- } // getBaseActionURL
-
- public static String getRaptorActionURL() {
- return Globals.getAppUtils().getBaseActionURL() + "raptor&" + AppConstants.RI_ACTION
- + "=";
- } // getRaptorActionURL
-
- public static String getRaptorActionURLNG() {
- return Globals.getAppUtils().getBaseActionURLNG();
- } // getRaptorActionURL
-
- public static String getReportExecuteActionURL() {
- return getRaptorActionURL() + "report.run.container&" + AppConstants.RI_REPORT_ID + "="; // getBaseActionParam();
- } // getReportExecuteActionURL
-
- public static String getReportExecuteActionURLNG() {
- return getRaptorActionURLNG() + "report_run/"; // getBaseActionParam();
- } // getReportExecuteActionURL
-
- public static String getBaseActionParam() {
- return Globals.getAppUtils().getBaseActionParam();
- } // getBaseActionParam
-
- public static Vector getQuickLinksMenuIDs() {
- return Globals.getAppUtils().getQuickLinksMenuIDs();
- } // getQuickLinksMenuIDs
-
- public static String getMenuLabel(String menuId) {
- return Globals.getAppUtils().getMenuLabel(menuId);
- } // getMenuLabel
-
- public static String getReportDbColsMaskSQL() {
- return Globals.getAppUtils().getReportDbColsMaskSQL();
- } // getReportDbColsMaskSQL
-
- public static String getReportDbLookupsSQL() {
- return Globals.getAppUtils().getReportDbLookupsSQL();
- } // getReportDbLookupsSQL
-
- public static void processErrorNotification(HttpServletRequest request, RaptorException e) {
- Globals.getAppUtils().processErrorNotification(request, e);
- } // processErrorNotification
-
- public static String getExcelTemplatePath() {
- String path = Globals.getAppUtils().getExcelTemplatePath();
- if (path.endsWith(File.separator)){
- return path;
- } else {
- path = path + File.separator;
- return path;
- }
- } // getTempFolderPath
-
- public static String nvl(String s) {
- return (s == null) ? "" : s;
- }
-
- public static boolean isNotEmpty(String s) {
- return nvl(s).length()>0;
- }
- public static String nvls(String s, String sDefault) {
- return nvl(s).equals("") ? sDefault : s;
- }
-
-} // AppUtils
-
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java
deleted file mode 100644
index 859931f9..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/DbUtils.java
+++ /dev/null
@@ -1,1298 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system;
-
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
-
-import javax.sql.DataSource;
-
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.error.ReportSQLException;
-import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
-import org.openecomp.portalsdk.analytics.util.DataSet;
-import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.web.support.AppUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class DbUtils /* implements IDbUtils */{
-
- static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DbUtils.class);
-
-
-
- private static DataSource dataSource;
-
-
- public DbUtils() {
- }
-
- public static Connection getConnection() throws ReportSQLException {
- try {
- return AppUtils.getDatasource().getConnection();
- } catch(SQLException ex) {
- ex.printStackTrace();
- }
- return null;
- //return Globals.getDbUtils().getConnection();
- } // getConnection
-
- public static void clearConnection(Connection con) throws ReportSQLException {
- try {
- if ((con != null) && !con.isClosed())
- Globals.getDbUtils().clearConnection(con);
- } catch (SQLException ex) {
- throw new ReportSQLException(ex.getMessage(), ex.getCause());
- } catch (Exception ex2 ) {
- throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
- }
- } // clearConnection
-
- public static Connection startTransaction() throws ReportSQLException {
- Connection con = null;
- try {
- con = getConnection();
- con.setAutoCommit(false);
- } catch (SQLException ex) {
- throw new ReportSQLException (ex.getMessage(), ex.getCause());
- } catch (Exception ex2 ) {
- throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
- }
- return con;
- } // startTransaction
-
- public static void commitTransaction(Connection con) throws ReportSQLException {
- try {
- con.commit();
- } catch (SQLException ex) {
- throw new ReportSQLException (ex.getMessage(), ex.getCause());
- } catch (Exception ex2 ) {
- throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
- }
-
- //clearConnection(con);
- } // commitTransaction
-
- public static void rollbackTransaction(Connection con) throws ReportSQLException {
- try {
- con.rollback();
- clearConnection(con);
- } catch (SQLException ex) {
- throw new ReportSQLException (ex.getMessage(), ex.getCause());
- } catch (Exception ex2 ) {
- throw new ReportSQLException (ex2.getMessage(), ex2.getCause());
- }
- } // rollbackTransaction
-
- public static String executeCall(Connection con, String sql, boolean expectResult)
- throws ReportSQLException {
- String result = null;
-
- try {
- if(con.isClosed()) con = getConnection();
- logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL Call] " + sql));
- CallableStatement stmt = con.prepareCall(sql);
- if (expectResult)
- stmt.registerOutParameter(1, Types.CHAR);
- stmt.executeUpdate();
- if (expectResult)
- result = stmt.getString(1);
- stmt.close();
- con.commit();
- } catch (SQLException e) {
- throw new ReportSQLException(e.getMessage(), sql);
- } finally {
- clearConnection(con);
- }
-
- return result;
- } // executeCall
-
- public static String executeCall(String sql, boolean expectResult)
- throws RaptorException {
- Connection con = null;
- con = getConnection();
- String result = executeCall(con, sql, expectResult);
- //con.commit();
- return result;
- } // executeCall
-
- public static int executeUpdate(Connection con, String sql) throws ReportSQLException {
- int rcode = -1;
- try {
- Statement stmt = con.createStatement();
- logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL Update] " + sql));
- rcode = stmt.executeUpdate(sql);
- stmt.close();
- //con.commit();
- } catch (SQLException e) {
- //e.printStackTrace();
- throw new ReportSQLException(e.getMessage(), sql);
- }
- return rcode;
- } // executeUpdate
-
- /* public static int batchUpdate(Connection con, String sql) throws ReportSQLException, Exception {
- int rcode = -1;
- try {
- Statement stmt = con.createStatement();
- debugLogger.debug("[SQL CALL FROM RAPTOR] [SQL Update] " + sql, 4);
- rcode = stmt.executeUpdate(sql);
- stmt.close();
- } catch (SQLException e) {
- e.printStackTrace();
- throw new ReportSQLException(e.getMessage(), sql);
- }
- return rcode;
- } // batchUpdate
-*/
-
- public static int executeUpdate(String sql) throws ReportSQLException {
- Connection con = null;
- try {
- con = getConnection();
- int rcode = executeUpdate(con, sql);
- if(Globals.getDBType().equals("oracle"))
- con.commit();
-
- return rcode;
- } catch (SQLException e) {
- throw new ReportSQLException(e.getMessage(), sql);
- } finally {
- clearConnection(con);
- }
- } // executeUpdate
-
- public static DataSet executeQuery(Connection con, String sql) throws ReportSQLException {
- return executeQuery(con, sql, Integer.MAX_VALUE);
- } // executeQuery
-
- public static DataSet executeQuery(Connection con, String sql, int maxRowLimit)
- throws ReportSQLException {
- try {
- if(con.isClosed()) con = getConnection();
- //con.
- Statement stmt = con.createStatement();
-
- logger.debug(EELFLoggerDelegate.debugLogger, ("[SQL CALL FROM RAPTOR] [SQL] " + sql));
- ResultSet rs = stmt.executeQuery(sql);
- DataSet ds = new DataSet(rs, maxRowLimit);
-
- if(rs!=null)
- rs.close();
- if(stmt!=null)
- stmt.close();
-
- return ds;
- } catch (SQLException e) {
- throw new ReportSQLException(e.getMessage(), sql);
- }
- } // executeQuery
-
- public static DataSet executeQuery(String sql) throws ReportSQLException {
- return executeQuery(sql, Integer.MAX_VALUE);
- } // executeQuery
-
- public static DataSet executeQuery(String sql, int maxRowLimit) throws ReportSQLException {
- Connection con = null;
- try {
- con = getConnection();
- return executeQuery(con, sql, maxRowLimit);
- }catch (ReportSQLException ex) {
- logger.error(EELFLoggerDelegate.debugLogger, ("Error " + sql));
- throw new ReportSQLException(ex.getMessage(), ex);
- }catch(Exception ex1) {
- throw new ReportSQLException(ex1.getMessage(), ex1.getCause());
- } finally {
- clearConnection(con);
- }
- } // executeQuery
-
- //For ZK Support
-
- public static int executeQuery(ReportRuntime rr, int dateOption) {
- Connection con = null;
- int rowCount = 0;
- try {
- con = ConnectionUtils.getConnection(rr.getDBInfo());
- String wholeSql = rr.getWholeSQL();
-
- DataColumnType dc = rr.getColumnWhichNeedEnhancedPagination();
- String date_ColId = dc.getColId();
- String dataFormat = dc.getColFormat();
- if(dataFormat!=null && dataFormat.length()>0)
- date_ColId = "to_date("+date_ColId+", '"+ dataFormat +"')";
- String sql = "";
- if(dateOption == 1)
- sql = "select count(distinct to_char("+date_ColId+", 'YYYY/MM')) from ("+wholeSql+")";
- else if (dateOption == 3)
- sql = "select count(distinct to_char("+date_ColId+", 'YYYY/MM/DD')) from ("+wholeSql+")";
- else if (dateOption == 2)
- sql = "select count(distinct to_char("+date_ColId+", 'YYYY')) from ("+wholeSql+")";
- DataSet ds = executeQuery(con, sql.toString());
- rowCount = ds.getInt(0,0);
- } catch (ReportSQLException ex) {
- ex.printStackTrace();
- }catch(Exception ex1) {
- ex1.printStackTrace();
- } finally {
- try {
- clearConnection(con);
- } catch (ReportSQLException ex2) {
- ex2.printStackTrace();
- }
- }
- return rowCount;
- }
-
-// public static List executeQuery(ReportRuntime rr, String filterClause, int itemStartNumber, int itemEndNumber, boolean topDown, String _orderBy, boolean asc, RaptorRunHandler raptorRunHandler) {
-// Connection con = null;
-// List rowList = new ArrayList();
-// String totalSql = raptorRunHandler.getTotalSql();
-// ReportData rd = null;
-// boolean totalAvailable = false;
-// if(nvls(totalSql).length()>0) totalAvailable = true;
-// /*if(totalAvailable) {
-// if(itemStartNumber > 0) itemStartNumber--;
-// itemEndNumber--;
-// //if(itemEndNumber > 2) itemEndNumber = itemEndNumber - 2;
-// }*/
-// try {
-//
-//
-//
-// con = ConnectionUtils.getConnection(rr.getDBInfo());
-// //if client side sorting is needed we could disable the comment line below for quicker development
-// // until we do it in "client" end.
-// //StringBuffer sql = new StringBuffer(rr.getReportSQLWithRowNum());
-// StringBuffer sql = new StringBuffer("");
-// String dbType = raptorRunHandler.getDbType();
-// if(rr.getDateOption() == -1) {
-// if (!dbType.equals("DAYTONA")) {
-// sql = new StringBuffer(rr.getReportSQLWithRowNum(_orderBy, asc));
-// //if( /*itemEndNumber > 1 &&*/ itemEndNumber > itemStartNumber)
-// if(topDown) {
-// sql.append(")"+ (Globals.isPostgreSQL()?" AS ":"") +" y");
-//
-// if(Globals.getDBType().equals("postgresql"))
-// sql.append(" WHERE RNUM < " + (itemEndNumber));
-// else
-// sql.append(" WHERE ROWNUM < " + (itemEndNumber));
-// }
-// else {
-// //sql.append(" WHERE ROWNUM <= " + (itemEndNumber));
-// String a_sql = Globals.getReportSqlOnlySecondPartA();
-// a_sql = a_sql.replace("[endRow]", String.valueOf(itemEndNumber));
-// String b_sql = Globals.getReportSqlOnlySecondPartBNoOrderBy();
-// b_sql = b_sql.replace("[startRow]", String.valueOf(itemStartNumber));
-// sql.append(") "+ (Globals.isPostgreSQL()?" AS ":"") +" a ");
-// sql.append(a_sql);
-// sql.append(b_sql);
-//
-// }
-// // sql.append(" ) y WHERE rnum >= " + (topDown?itemStartNumber:(itemStartNumber+1)));
-// if(nvls(_orderBy).length()>0)
-// sql.append(" ORDER BY "+ _orderBy + " "+ (asc ? "ASC" : "DESC"));
-// else
-// sql.append(" ORDER BY rnum");
-// // sql = String.format(sql, _orderBy, asc ? "ASC" : "DESC");
-// } else {
-// sql = new StringBuffer(rr.getWholeSQL());
-// if( sql.toString().trim().toUpperCase().startsWith("SELECT")) {
-// sql.append(" LIMIT TO "+ (itemStartNumber+1)+"->"+itemEndNumber);
-// }
-// //return sql;
-// }
-// System.out.println("ZK RAPTOR RUN " + sql);
-// } else {
-// String wholeSql = rr.getWholeSQL();
-// DataColumnType dc = rr.getColumnWhichNeedEnhancedPagination();
-// String date_ColId = dc.getColId();
-// String dataFormat = dc.getColFormat();
-// if(dataFormat!=null && dataFormat.length()>0)
-// date_ColId = "to_date("+date_ColId+", '"+ dataFormat +"')";
-// StringBuffer dateSql = new StringBuffer(" select y.rownum1, y.datetime from (select rownum rownum1, datetime from ");
-// if(rr.getDateOption() == 1) {
-// dateSql.append( "(select distinct to_char("+date_ColId+", 'YYYY/MM') datetime from ( " + wholeSql + ") order by 1 desc");
-// } else if (rr.getDateOption() == 2) {
-// dateSql.append( "(select distinct to_char("+date_ColId+", 'YYYY') datetime from ( " + wholeSql + ") order by 1 desc");
-// } else if (rr.getDateOption() == 3) {
-// dateSql.append( "(select distinct to_char("+date_ColId+", 'YYYY/MM/DD') datetime from ( " + wholeSql + ") order by 1 desc");
-// }
-// dateSql.append(")) y where y.rownum1 = "+ (itemStartNumber+1));
-// DataSet ds = executeQuery(con, dateSql.toString());
-// String dateStr = "";
-// if(ds.getRowCount() > 0)
-// dateStr = ds.getString(0,1);
-//
-// sql = new StringBuffer(rr.getReportSQLWithRowNum(_orderBy, asc));
-// if(rr.getDateOption() == 1) {
-// sql.append(" WHERE to_char("+ date_ColId + ", 'YYYY/MM') = '"+ dateStr +"')");
-// } else if (rr.getDateOption() == 2) {
-// sql.append(" WHERE to_char("+ date_ColId + ", 'YYYY') = '"+ dateStr +"')");
-// } else if (rr.getDateOption() == 3) {
-// sql.append(" WHERE to_char("+ date_ColId + ", 'YYYY/MM/DD') = '"+ dateStr +"')");
-// }
-// if(nvls(_orderBy).length()>0)
-// sql.append(" ORDER BY "+ _orderBy + " "+ (asc ? "ASC" : "DESC"));
-// else
-// sql.append(" ORDER BY rnum");
-// System.out.println("ZK RAPTOR RUN MONTHLY " + sql);
-// }
-//
-// debugLogger.error(" ************** just a test **************** ");
-// debugLogger.error(" SQL " + sql);
-// debugLogger.error(" ******************************************* ");
-//
-// DataSet ds = ConnectionUtils.getDataSet(sql.toString(), rr.getDBInfo());
-// DataSet ds1 = null;
-// //DataSet ds = executeQuery(sql.toString());
-// List reportCols = rr.getAllColumns();
-// Vector formatProcessors = new Vector(reportCols.size());
-//
-// String oldValue = "";
-// String value = "";
-// String groupByColValue = "";
-// int subTotalFlag = -1;
-// //String newValue = "";
-// for (int r = 0; r < ds.getRowCount(); r++) {
-// DataRow dr = new DataRow();
-// //rd.reportDataRows.addDataRow(dr);
-// //rd = raptorRunHandler.getReportData();
-// //RowHeaderCol rhc = new RowHeaderCol();
-// //reportRowHeaderCols.addRowHeaderCol(0, rhc);
-// //rhc.setColumnWidth("5%");
-// int formatCount = -1; //added for auxillary head check
-// String drillDownURL = "";
-//
-// int changedFlag = 0;
-// for (int c = 0; c < reportCols.size(); c++) {
-// if(reportCols.get(c)!=null) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// else formatCount++;
-// //
-// formatProcessors.add(formatCount,new FormatProcessor(
-// rr.getSemaphoreById(dct.getSemaphoreId()), dct.getColType(), dct
-// .getColFormat(), rr.getReportDefType().equals(
-// AppConstants.RD_SQL_BASED)));
-// //
-// if(!(dct.getColName().startsWith("[") && dct.getDisplayName() == null)) {
-// value = "";
-//
-// if(ds.getColumnIndex(dct.getColId())!= -1) {
-// value = ds.getString(r, dct.getColId());
-// if(dct.getGroupByPos()!=null && dct.getGroupByPos()>0) {
-// groupByColValue = ds.getString(r, dct.getColId());
-// if(oldValue.length()> 0 && !oldValue.equals(groupByColValue)) {
-// //newValue = value;
-// if(subTotalFlag > 0) {
-// changedFlag = -1;
-// oldValue = groupByColValue;
-// subTotalFlag = 0;
-// } else {
-// changedFlag = 1;
-// //oldValue = groupByColValue;
-// r--;
-// }
-// } else if (oldValue.length()<=0) {
-// oldValue = groupByColValue;
-// changedFlag = -1;
-// } else if (oldValue.equals(groupByColValue)) {
-// //oldValue = value;
-// changedFlag = 0;
-// }
-// }
-// }
-//
-// if(changedFlag > 0) {
-// StringBuffer subTotalSql = new StringBuffer(" select ");
-// StringBuffer whereClause = new StringBuffer("");
-// //get all colids
-// for (int d = 0; d < reportCols.size(); d++) {
-// if(reportCols.get(d)!=null) {
-// DataColumnType dct1 = (DataColumnType) reportCols.get(d);
-// if(dct1.getGroupByPos()!=null && dct1.getGroupByPos()>0){
-// subTotalSql.append(dct1.getColId() + " " );
-// whereClause.append(" where "+ dct1.getColId() + " = '" + oldValue + "' " + " group by "+ dct1.getColId() );
-// }
-// if(dct1.getDisplayTotal()!=null && dct1.getDisplayTotal().length() > 0) {
-// subTotalSql.append(", sum("+dct1.getColId()+")");
-// }
-// }
-// }
-//
-// subTotalSql.append(" from (");
-// subTotalSql.append(rr.getWholeSQL());
-// subTotalSql.append (")");
-// subTotalSql.append(whereClause);
-// ds1 = ConnectionUtils.getDataSet(subTotalSql.toString(),rr.getDbInfo());
-// dr = new DataRow();
-// DataValue dv = new DataValue();
-// int count = 0;
-// //dv.setColName("#");
-// for (int c1 = 0; c1 < reportCols.size(); c1++) {
-// dct = (DataColumnType) reportCols.get(c1);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// if ( dct != null && dct.isVisible()) {
-// count++;
-//
-// dv = new DataValue();
-// //if(count==1) {
-// if(dct.getGroupByPos()!=null && dct.getGroupByPos()>0) {
-// dr.addDataValue(dv);
-// if(AppUtils.nvl(dct.getSubTotalCustomText()).length()>0) {
-// dv.setDisplayValue(dct.getSubTotalCustomText());
-// } else {
-// dv.setDisplayValue("Sub Total");
-// }
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setBold(true);
-// } else {
-// if(dct.getDisplayTotal()!=null && dct.getDisplayTotal().length() > 0) {
-// dr.addDataValue(dv);
-// String subtotalValue = "";
-// if (ds1 != null) {
-// subtotalValue = ds1.getString(0, "sum("+dct.getColId()+")");
-// dv.setDisplayValue(Utils.truncateTotalDecimals(subtotalValue));
-// } else {
-// dv.setDisplayValue("");
-// }
-// } else {
-// if(dv.isVisible())
-// dr.addDataValue(dv);
-// dv.setDisplayValue("");
-// }
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setBold(true);
-// }
-// } // dct check
-// } // for
-// //if(!topDown) {
-// //rowList.add(dr);
-// //}
-// //oldValue = value;
-// if(changedFlag == 1) changedFlag = 0;
-// subTotalFlag = 1;
-// } else {
-//
-// if(nvls(value).length()>0 && !nvls(value).equals("'")) {
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// if(dct.getGroupByPos()!=null && dct.getGroupByPos()>0) {
-// if(changedFlag == 0) {
-// dv.setDisplayValue("");
-// } else {
-// dv.setDisplayValue(nvls(value));
-// }
-// } else {
-// dv.setDisplayValue(nvls(value));
-// }
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.getColType().equals(AppConstants.CT_HYPERLINK)) {
-// dv.setHyperlinkURL(dct.getHyperlinkURL());
-// dv.setDisplayType(dct.getHyperlinkType());
-// if(dct.getHyperlinkType().equals("IMAGE"))
-// dv.setActionImg(dct.getActionImg());
-// }
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// //dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// if(dct.isVisible()) {
-//
-// dv.setVisible(true);
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// //Add Drilldown URL to dv
-// if (nvls(dct.getDrillDownURL()).length() > 0) {
-//
-// if(dv.getDisplayValue().length() > 0) {
-// dv.setDrillDownURL(raptorRunHandler.parseDrillDownURL(r, /* c, */ds, dct,null));
-// dv.setDrillDowninPoPUp(dct.isDrillinPoPUp()!=null?dct.isDrillinPoPUp():false);
-// }
-//
-// if (dv.getDisplayValue().length() == 0) {
-// //dv.setDisplayValue("[NULL]");
-// dv.setDisplayValue("");
-// }
-// } // if
-//
-// } else {
-// dv.setVisible(false);
-// dv.setHidden(true);
-// }
-// //System.out.println("in Linear report b4" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// /* if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);
-// */
-//
-// //System.out.println("in Linear report After" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// /* DataValue dvInner = new DataValue();
-// dvInner.setDisplayValue(ds.getString(r, c));
-// dvInner.setColName(dct.getColName());
-// dvInner.setColId(dct.getColId());
-// rowList.add(dvInner);
-// */ dv.setDisplayCalculatedValue(ds.getString(r, dctInner.getColId()));
-// }
-// }
-// }
-// }
-// } else { //dv value check
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// dv.setDisplayValue(nvls(value));
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.isVisible())
-// dv.setVisible(true);
-// else
-// dv.setVisible(false);
-// /* if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);
-// */
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// dv.setDisplayCalculatedValue(ds.getString(r, cInner));
-// }
-// }
-// }
-// }
-// }
-// } //changedFlag > 1
-// }
-// } // if reportCols
-//
-//
-// } // for
-//
-// //format
-//
-// for (int c = 0; c < reportCols.size(); c++) {
-// if(reportCols.get(c)!=null) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// //Modified since ds is null.
-// DataValue dv = new DataValue();
-// dv = dr.getDataValue(c);
-// if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(c)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(c)).setHtmlFormatters(dv, dr, false);
-// }
-// }
-// //add dr to rowList after all column is done.
-// if(!topDown) {
-// rowList.add(dr);
-// }
-// } // for
-//
-///* //rd.addRowNumbers(pageNo, getPageSize());
-// rd = raptorRunHandler.getReportData();
-// RowHeaderCol rhc = new RowHeaderCol();
-// rd.reportRowHeaderCols.addRowHeaderCol(0, rhc);
-// rhc.setColumnWidth("5%");
-// rhc.add(new RowHeader(""#, "15"));
-//*/
-//
-// //String totalSql = raptorRunHandler.getTotalSql();
-//
-// if(subTotalFlag >=0) {
-// StringBuffer subTotalSql = new StringBuffer(" select ");
-// StringBuffer whereClause = new StringBuffer("");
-// //get all colids
-// for (int d = 0; d < reportCols.size(); d++) {
-// if(reportCols.get(d)!=null) {
-// DataColumnType dct1 = (DataColumnType) reportCols.get(d);
-// if(dct1.getGroupByPos()!=null && dct1.getGroupByPos()>0){
-// subTotalSql.append(dct1.getColId() + " " );
-// whereClause.append(" where "+ dct1.getColId() + " = '" + oldValue + "' " + " group by "+ dct1.getColId() );
-// }
-// if(dct1.getDisplayTotal()!=null && dct1.getDisplayTotal().length() > 0) {
-// subTotalSql.append(", sum("+dct1.getColId()+")");
-// }
-// }
-// }
-//
-// subTotalSql.append(" from (");
-// subTotalSql.append(rr.getWholeSQL());
-// subTotalSql.append (")");
-// subTotalSql.append(whereClause);
-// ds1 = ConnectionUtils.getDataSet(subTotalSql.toString(),rr.getDbInfo());
-// DataRow dr = new DataRow();
-// DataValue dv = new DataValue();
-// int count = 0;
-// //dv.setColName("#");
-// DataColumnType dct = null;
-// for (int c1 = 0; c1 < reportCols.size(); c1++) {
-// dct = (DataColumnType) reportCols.get(c1);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// if ( dct != null && dct.isVisible()) {
-// count++;
-//
-// dv = new DataValue();
-// //if(count==1) {
-// if(dct.getGroupByPos()!=null && dct.getGroupByPos()>0) {
-// dr.addDataValue(dv);
-// if(AppUtils.nvl(dct.getSubTotalCustomText()).length()>0) {
-// dv.setDisplayValue(dct.getSubTotalCustomText());
-// } else {
-// dv.setDisplayValue("Sub Total");
-// }
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setBold(true);
-// } else {
-// if(dct.getDisplayTotal()!=null && dct.getDisplayTotal().length() > 0) {
-// dr.addDataValue(dv);
-// String subtotalValue = "";
-// if (ds1 != null) {
-// subtotalValue = ds1.getString(0, "sum("+dct.getColId()+")");
-// dv.setDisplayValue(Utils.truncateTotalDecimals(subtotalValue));
-// } else {
-// dv.setDisplayValue("");
-// }
-// } else {
-// if(dv.isVisible())
-// dr.addDataValue(dv);
-// dv.setDisplayValue("");
-// }
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setBold(true);
-// }
-// } // dct check
-// } // for
-// if(!topDown) {
-// rowList.add(dr);
-// }
-// }
-// if(nvls(totalSql).length()>0) {
-// ds = ConnectionUtils.getDataSet(totalSql,rr.getDbInfo());
-// DataRow dr = new DataRow();
-// DataValue dv = new DataValue();
-// int count = 0;
-// //dv.setColName("#");
-// for (int c = 0; c < reportCols.size(); c++) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// if ( dct != null && dct.isVisible()) {
-// count++;
-//
-// dv = new DataValue();
-// if(count==1) {
-// dr.addDataValue(dv);
-// dv.setDisplayValue("Total (for all Records)");
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setBold(true);
-// } else {
-// if(dv.isVisible())
-// dr.addDataValue(dv);
-//
-// String totalValue = "";
-// if (ds != null)
-// totalValue = ds.getString(0, "TOTAL_"+dct.getColId());
-// if (nvls(dct.getDisplayTotal()).length() > 0
-// && (!dct.getDisplayTotal().equals(AppConstants.TOTAL_SUM_ID)))
-// totalValue = nvls(AppConstants.TOTAL_FUNCTIONS.getNameById(dct
-// .getDisplayTotal()))
-// + ": " + totalValue;
-// dv.setDisplayValue(Utils.truncateTotalDecimals(totalValue));
-//
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// /*StringBuffer indentation = new StringBuffer("");
-// if(dct.getIndentation()!=null && dct.getIndentation()>0) {
-// for (int indent=0; indent< dct.getIndentation(); indent++) {
-// indentation.append("\t");
-// }
-// dv.setNowrap("true");
-// }
-// dv.setIndentation(indentation.toString());*/
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setBold(true);
-// }
-// } // dct check
-// } // for
-// if(!topDown) {
-// rowList.add(dr);
-// }
-//
-// }
-//
-//
-//
-// } catch (ReportSQLException ex) {
-// ex.printStackTrace();
-// }catch(Exception ex1) {
-// ex1.printStackTrace();
-// } finally {
-// try {
-// clearConnection(con);
-// } catch (ReportSQLException ex2) {
-// ex2.printStackTrace();
-// }
-// }
-// return rowList;
-// }
-
-
- //For ZK Support
-
-// public static List executeQuery(ReportRuntime rr, String filterClause, int itemStartNumber, int itemEndNumber, boolean topDown, String _orderBy, boolean asc, DashboardReportRunHandler dashboardReportRunHandler) {
-// Connection con = null;
-// List rowList = new ArrayList();
-// String totalSql = rr.getTotalSql();
-// boolean totalAvailable = false;
-// if(nvls(totalSql).length()>0) totalAvailable = true;
-// if(totalAvailable) {
-// itemStartNumber--;
-// itemEndNumber--;
-// }
-// try {
-// con = ConnectionUtils.getConnection(rr.getDBInfo());
-// //if client side sorting is needed we could disable the comment line below for quicker development
-// // until we do it in "client" end.
-// //StringBuffer sql = new StringBuffer(rr.getReportSQLWithRowNum());
-// StringBuffer sql = new StringBuffer("");
-// if (!rr.getReportType().equals(AppConstants.RT_HIVE)) {
-// sql = new StringBuffer(rr.getReportSQLWithRowNum(_orderBy, asc));
-// //if( /*itemEndNumber > 1 &&*/ itemEndNumber > itemStartNumber)
-//
-// if(topDown) {
-// sql.append(") "+ (Globals.isPostgreSQL()?" AS ":"") +" y");
-// if(Globals.getDBType().equals("postgresql"))
-// sql.append(" WHERE RNUM < " + (itemEndNumber));
-// else
-// sql.append(" WHERE ROWNUM < " + (itemEndNumber));
-// }
-// else {
-// //sql.append(" WHERE ROWNUM <= " + (itemEndNumber));
-// String a_sql = Globals.getReportSqlOnlySecondPartA();
-// a_sql = a_sql.replace("[endRow]", String.valueOf(itemEndNumber));
-// String b_sql = Globals.getReportSqlOnlySecondPartBNoOrderBy();
-// b_sql = b_sql.replace("[startRow]", String.valueOf(itemStartNumber));
-// sql.append(") "+ (Globals.isPostgreSQL()?" AS ":"") +" a ");
-// sql.append(a_sql);
-// sql.append(b_sql);
-// }
-//
-// // sql.append(" ) y WHERE rnum >= " + (topDown?itemStartNumber:(itemStartNumber+1)));
-// if(nvls(_orderBy).length()>0)
-// sql.append(" ORDER BY "+ _orderBy + " "+ (asc ? "ASC" : "DESC"));
-// else
-// sql.append(" ORDER BY rnum");
-// // sql = String.format(sql, _orderBy, asc ? "ASC" : "DESC");
-//
-// /*//sql.append(" WHERE ROWNUM <= " + (topDown?itemEndNumber:(itemEndNumber)));
-// sql.append(" ) y WHERE rnum >= " + (topDown?itemStartNumber:(itemStartNumber+1)));
-// if(nvls(_orderBy).length()>0)
-// sql.append(" ORDER BY "+ _orderBy + " "+ (asc ? "ASC" : "DESC"));
-// else
-// sql.append(" ORDER BY rnum");
-// // sql = String.format(sql, _orderBy, asc ? "ASC" : "DESC");*/
-// itemStartNumber = 0;
-// } else {
-// sql.append(rr.getWholeSQL());
-// int count = rr.getReportDataSize();
-// System.out.println("Count "+ count+ " " + itemEndNumber);
-// if(count < itemEndNumber)
-// sql.append(" " + "limit "+ count);
-// else
-// sql.append(" " + "limit "+ itemEndNumber);
-// }
-// System.out.println("ZK RAPTOR RUN " + sql);
-// DataSet ds = null;
-// if (!rr.getReportType().equals(AppConstants.RT_HIVE)) {
-// ds = executeQuery(con, sql.toString());
-// } else {
-// String dbInfo = rr.getDBInfo();
-// ds = ConnectionUtils.getDataSet(sql.toString(), dbInfo);
-// }
-// List reportCols = rr.getAllColumns();
-// Vector formatProcessors = new Vector(reportCols.size());
-//
-// for (int r = itemStartNumber; r < ds.getRowCount(); r++) {
-// DataRow dr = new DataRow();
-// //rd.reportDataRows.addDataRow(dr);
-//
-// int formatCount = -1; //added for auxillary head check
-// for (int c = 0; c < reportCols.size(); c++) {
-// if(reportCols.get(c)!=null) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// else formatCount++;
-// //
-// formatProcessors.add(formatCount,new FormatProcessor(
-// rr.getSemaphoreById(dct.getSemaphoreId()), dct.getColType(), dct
-// .getColFormat(), rr.getReportDefType().equals(
-// AppConstants.RD_SQL_BASED)));
-// //
-// if(!(dct.getColName().startsWith("[") && dct.getDisplayName() == null)) {
-// String value = "";
-// if(ds.getColumnIndex(dct.getColId())!= -1) {
-// value = ds.getString(r, dct.getColId());
-// }
-// if(nvls(value).length()>0 && !nvls(value).equals("'")) {
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// dv.setDisplayValue(nvls(value));
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.getColType().equals(AppConstants.CT_HYPERLINK)) {
-// dv.setHyperlinkURL(dct.getHyperlinkURL());
-// dv.setDisplayType(dct.getHyperlinkType());
-// if(dct.getHyperlinkType().equals("IMAGE"))
-// dv.setActionImg(dct.getActionImg());
-// }
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// //dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// if(dct.isVisible()) {
-//
-// dv.setVisible(true);
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setDisplayName(dct.getDisplayName());
-//
-// //Add Drilldown URL to dv
-// if (nvls(dct.getDrillDownURL()).length() > 0) {
-//
-// if(dv.getDisplayValue().length() > 0) {
-// dv.setDrillDownURL(dashboardReportRunHandler.parseDrillDownURL(r, /* c, */ds, dct,null,rr));
-// dv.setDrillDowninPoPUp(dct.isDrillinPoPUp()!=null?dct.isDrillinPoPUp():false);
-// }
-//
-// if (dv.getDisplayValue().length() == 0) {
-// //dv.setDisplayValue("[NULL]");
-// dv.setDisplayValue("");
-// }
-// } // if
-//
-// } else {
-// dv.setVisible(false);
-// dv.setHidden(true);
-// }
-// //System.out.println("in Linear report b4" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// /* if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);*/
-//
-// //System.out.println("in Linear report After" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// /* DataValue dvInner = new DataValue();
-// dvInner.setDisplayValue(ds.getString(r, c));
-// dvInner.setColName(dct.getColName());
-// dvInner.setColId(dct.getColId());
-// rowList.add(dvInner);
-// */ dv.setDisplayCalculatedValue(ds.getString(r, dctInner.getColId()));
-// }
-// }
-// }
-// }
-// } else { //dv value check
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// dv.setDisplayValue(nvls(value));
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.isVisible())
-// dv.setVisible(true);
-// else
-// dv.setVisible(false);
-// /*if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);*/
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// dv.setDisplayCalculatedValue(ds.getString(r, dctInner.getColId()));
-// }
-// }
-// }
-// }
-// }
-// }
-// } // if reportCols
-//
-//
-// } // for
-// for (int c = 0; c < reportCols.size(); c++) {
-// if(reportCols.get(c)!=null) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// //Modified since ds is null.
-// DataValue dv = new DataValue();
-// dv = dr.getDataValue(c);
-// if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(c)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(c)).setHtmlFormatters(dv, dr, false);
-// }
-// }
-// //add dr to rowList after all column is done.
-// if(!topDown) {
-// rowList.add(dr);
-// }
-// } // for
-//
-// //String totalSql = raptorRunHandler.getTotalSql();
-// if(nvls(totalSql).length()>0) {
-// ds = ConnectionUtils.getDataSet(totalSql,rr.getDbInfo());
-// DataRow dr = new DataRow();
-// DataValue dv = new DataValue();
-//
-// //dv.setColName("#");
-// int count = 0;
-// for (int c = 0; c < reportCols.size(); c++) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// if ( dct != null && dct.isVisible()) {
-// count++;
-//
-// dv = new DataValue();
-// dv.setVisible(dct.isVisible());
-//
-// if(count==1) {
-// dr.addDataValue(dv);
-// dv.setDisplayValue("Total (for all Records)");
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setBold(true);
-// } else {
-// if(dv.isVisible())
-// dr.addDataValue(dv);
-//
-// String totalValue = "";
-// if (ds != null)
-// totalValue = ds.getString(0, "TOTAL_"+dct.getColId());
-// if (nvls(dct.getDisplayTotal()).length() > 0
-// && (!dct.getDisplayTotal().equals(AppConstants.TOTAL_SUM_ID)))
-// totalValue = nvls(AppConstants.TOTAL_FUNCTIONS.getNameById(dct
-// .getDisplayTotal()))
-// + ": " + totalValue;
-// dv.setDisplayValue(Utils.truncateTotalDecimals(totalValue));
-//
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setColName(dct.getColName());
-// dv.setDisplayName(dct.getDisplayName());
-// dv.setColId(dct.getColId());
-// dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// /*StringBuffer indentation = new StringBuffer("");
-// if(dct.getIndentation()!=null && dct.getIndentation()>0) {
-// for (int indent=0; indent< dct.getIndentation(); indent++) {
-// indentation.append("\t");
-// }
-// dv.setNowrap("true");
-// }
-// dv.setIndentation(indentation.toString());*/
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setBold(true) ;
-// }
-// } // dct check
-// } // for
-// if(!topDown) {
-// rowList.add(dr);
-// }
-//
-// }
-//
-//
-// } catch (ReportSQLException ex) {
-// ex.printStackTrace();
-// }catch(Exception ex1) {
-// ex1.printStackTrace();
-// } finally {
-// try {
-// clearConnection(con);
-// } catch (ReportSQLException ex2) {
-// ex2.printStackTrace();
-// }
-// }
-// return rowList;
-// }
-
- public String nvl(String s) {
- return (s == null) ? "" : s;
- }
-
- public static String nvls(String s) {
- return (s == null) ? "" : s;
- }
-
- public static String nvl(String s, String sDefault) {
- return nvls(s).equals("") ? sDefault : s;
- }
-
-
-
- public static DataSource getDataSource() {
- return dataSource;
- }
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- dataSource = dataSource;
- }
-
-
-// public static List executeQuery(ReportRuntime rr, String filterClause, int itemStartNumber, int itemEndNumber, boolean topDown, String _orderBy, boolean asc, RaptorHiveRunHandler raptorHiveRunHandler) {
-// Connection con = null;
-// List rowList = new ArrayList();
-// ReportData rd = null;
-//
-// try {
-//
-//
-//
-// con = ConnectionUtils.getConnection(rr.getDBInfo());
-// //if client side sorting is needed we could disable the comment line below for quicker development
-// // until we do it in "client" end.
-// //StringBuffer sql = new StringBuffer(rr.getReportSQLWithRowNum());
-// StringBuffer sql = new StringBuffer("");
-// sql.append(rr.getWholeSQL());
-// int count = rr.getReportDataSize();
-// System.out.println("Count "+ count+ " " + itemEndNumber);
-// if(count < itemEndNumber)
-// sql.append(" " + "limit "+ count);
-// else
-// sql.append(" " + "limit "+ itemEndNumber);
-// //sql = new StringBuffer(raptorHiveRunHandler.getReportSQLWithRowNum(_orderBy, asc));
-// //if( /*itemEndNumber > 1 &&*/ itemEndNumber > itemStartNumber)
-// //sql.append(" WHERE ROWNUM <= " + (topDown?itemEndNumber:(itemEndNumber+1)));
-// //sql.append(" ) y WHERE rnum >= " + (topDown?itemStartNumber:(itemStartNumber+1)));
-// //if(nvls(_orderBy).length()>0)
-// //sql.append(" ORDER BY "+ _orderBy + " "+ (asc ? "ASC" : "DESC"));
-// //else
-// //sql.append(" ORDER BY rnum");
-// // sql = String.format(sql, _orderBy, asc ? "ASC" : "DESC");
-//
-// System.out.println("ZK RAPTOR RUN " + sql);
-//
-// String dbInfo = rr.getDBInfo();
-// DataSet ds = null;
-// ds = ConnectionUtils.getDataSet(sql.toString(), dbInfo);
-// List reportCols = rr.getAllColumns();
-// Vector formatProcessors = new Vector(reportCols.size());
-//
-// for (int r = itemStartNumber; r < ds.getRowCount(); r++) {
-// DataRow dr = new DataRow();
-// //rd.reportDataRows.addDataRow(dr);
-// //rd = raptorRunHandler.getReportData();
-// //RowHeaderCol rhc = new RowHeaderCol();
-// //reportRowHeaderCols.addRowHeaderCol(0, rhc);
-// //rhc.setColumnWidth("5%");
-//
-// int formatCount = -1; //added for auxillary head check
-// for (int c = 0; c < reportCols.size(); c++) {
-// if(reportCols.get(c)!=null) {
-// DataColumnType dct = (DataColumnType) reportCols.get(c);
-// if(dct.getLevel()!=null && dct.getLevel() > 0) continue;
-// else formatCount++;
-// //
-// formatProcessors.add(formatCount,new FormatProcessor(
-// rr.getSemaphoreById(dct.getSemaphoreId()), dct.getColType(), dct
-// .getColFormat(), rr.getReportDefType().equals(
-// AppConstants.RD_SQL_BASED)));
-// //
-// if(!(dct.getColName().startsWith("[") && dct.getDisplayName() == null)) {
-// String value = "";
-// if(ds.getColumnIndex(dct.getColId())!= -1) {
-// value = ds.getString(r, dct.getColId());
-// }
-// if(nvls(value).length()>0 && !nvls(value).equals("'")) {
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// dv.setDisplayValue(nvls(value));
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.getColType().equals(AppConstants.CT_HYPERLINK)) {
-// dv.setHyperlinkURL(dct.getHyperlinkURL());
-// dv.setDisplayType(dct.getHyperlinkType());
-// if(dct.getHyperlinkType().equals("IMAGE"))
-// dv.setActionImg(dct.getActionImg());
-// }
-// dv.setIndentation(new Integer((dct.getIndentation()==null)?new Integer("0"):dct.getIndentation()).toString());
-// //dv.setNowrap(nvl(dct.getNowrap(),"null").equals("false")?"null":nvl(dct.getNowrap(),"null"));
-// if(dct.isVisible()) {
-//
-// dv.setVisible(true);
-// dv.setAlignment(dct.getDisplayAlignment());
-// dv.setDisplayTotal(dct.getDisplayTotal());
-// dv.setDisplayName(dct.getDisplayName());
-//
-// //Add Drilldown URL to dv
-// if (nvls(dct.getDrillDownURL()).length() > 0) {
-//
-// if(dv.getDisplayValue().length() > 0) {
-// dv.setDrillDownURL(raptorHiveRunHandler.parseDrillDownURL(r, /* c, */ds, dct,null));
-// dv.setDrillDowninPoPUp(dct.isDrillinPoPUp()!=null?dct.isDrillinPoPUp():false);
-// }
-//
-// if (dv.getDisplayValue().length() == 0) {
-// //dv.setDisplayValue("[NULL]");
-// dv.setDisplayValue("");
-// }
-// } // if
-//
-// } else {
-// dv.setVisible(false);
-// dv.setHidden(true);
-// }
-// //System.out.println("in Linear report b4" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);
-//
-// //System.out.println("in Linear report After" + dr.getFormatId() + dr.getBgColorHtml() + dv.getDisplayValue());
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// /* DataValue dvInner = new DataValue();
-// dvInner.setDisplayValue(ds.getString(r, c));
-// dvInner.setColName(dct.getColName());
-// dvInner.setColId(dct.getColId());
-// rowList.add(dvInner);
-// */ dv.setDisplayCalculatedValue(ds.getString(r, dctInner.getColId()));
-// }
-// }
-// }
-// }
-// } else { //dv value check
-// DataValue dv = new DataValue();
-// dr.addDataValue(dv);
-// dv.setDisplayValue(nvls(value));
-// dv.setColName(dct.getColName());
-// dv.setColId(dct.getColId());
-// if(dct.isVisible())
-// dv.setVisible(true);
-// else
-// dv.setVisible(false);
-// if(dr.getFormatId()!=null)
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, true);
-// else
-// ((FormatProcessor) formatProcessors.get(formatCount)).setHtmlFormatters(dv, dr, false);
-//
-// if(topDown) {
-// if(!dv.getColId().endsWith("_calc") && dv.isVisible())
-// rowList.add(dv);
-// for (int cInner = 0; cInner < reportCols.size(); cInner++) {
-// if(reportCols.get(cInner)!=null) {
-// DataColumnType dctInner = (DataColumnType) reportCols.get(cInner);
-// if((dv.getColId()+"_calc").equals(dctInner.getColId())) {
-// dv.setDisplayCalculatedValue(ds.getString(r, cInner));
-// }
-// }
-// }
-// }
-// }
-// }
-// } // if reportCols
-//
-//
-// } // for
-// //add dr to rowList after all column is done.
-// if(!topDown) {
-// rowList.add(dr);
-// }
-// } // for
-// } catch (ReportSQLException ex) {
-// ex.printStackTrace();
-// }catch(Exception ex1) {
-// ex1.printStackTrace();
-// } finally {
-// try {
-// clearConnection(con);
-// } catch (ReportSQLException ex2) {
-// ex2.printStackTrace();
-// }
-// }
-// return rowList;
-// }
-
-
-} // DbUtils
-
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java
deleted file mode 100644
index 724a07d3..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AntBuild.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-
-/**
- * This class is used to get version and Build information when
- * user run "java -jar raptor_fusion.jar" command.
- */
-public class AntBuild {
-
- public static void main(String[] args) {
- System.out.println("Jar (raptor_fusion.jar) Information: ");
- readManifest();
- }
-
- public static void readManifest() {
- try {
- JarFile jar = new JarFile("./raptor_fusion.jar");
- Manifest manifest = jar.getManifest();
-
- Attributes attribs = manifest.getMainAttributes();
- Iterator it = attribs.entrySet().iterator();
- while(it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- Attributes.Name attributeName = (Attributes.Name) entry.getKey();
- String attributeValue = (String) entry.getValue();
- if (attributeName.toString().equals("Created-By"))
- System.out.println("JDK Version " + " : " + attributeValue);
- else if (attributeName.toString().equals("Ant-Version"))
- System.out.println(attributeName.toString() + " : " + attributeValue);
- else {
- if(attributeName.toString().startsWith("Raptor"))
- System.out.println(attributeName.toString() + " : " + attributeValue);
- }
- }
-
- } catch (IOException e) {
- System.err.println("Cannot read jar-file manifest: "
- + e.getMessage());
- }
- }
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java
deleted file mode 100644
index 008a1d8c..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/AppUtils.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.analytics.config.ConfigLoader;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.model.base.IdNameValue;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.system.IAppUtils;
-import org.openecomp.portalsdk.analytics.system.fusion.adapter.RaptorAdapter;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;;
-
-public class AppUtils extends org.openecomp.portalsdk.analytics.RaptorObject implements IAppUtils {
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AppUtils.class);
-
-
- private static String tempFolderPath = "/artemis/PROJECT1/MSA/databank/WEB-INF/temp/";
- private static String uploadFolderPath = "/artemis/PROJECT1/MSA/databank/WEB-INF/upload/";
- private static String tempFolderURL = "temp/";
- private static String uploadFolderURL = "upload/";
- private static String SMTPServer = "todo.smtp.server.com";
- private static String defaultEmailSender = "todo.email.sender.com";
- private static String errorPage = "error_page";
- private static String errorPageWMenu = "error_page_wmenu";
- private static String jspContextPath = "raptor/";
- private static String imgFolderURL = "raptor/images/";
- private static String baseFolderURL = "raptor/";
- //private static String reportExecuteActionURL = "dispatcher?action=raptor&r_action=report.run&c_master=";
- //private static String dataViewActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID
- //private static String dataViewActionParam = "c_master=";
- private static String directAccessURL = "http://localhost:8082/databank/dispatcher?direct.access=raptor&r_action=report.run&show=";
- private static String baseActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
- private static String baseActionURLNG = "report#/"; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
- private static String drillActionURL = "dispatcher?action="; // dispatcher?action=ACTION_ID&c_master=REC_ID or dispatcher?action=raptor&r_action=RAPTOR_ACTION_ID&c_master=REC_ID
- private static String baseActionParam = "c_master=";
- private static String superRoleID = "1";
- private static Vector adminRoleIDs = new Vector();
- private static Vector quickLinksMenuIDs = new Vector();
-
- private static Properties raptorAppProperties;
-
- private static String encryptedSMTPServer = "";
- public AppUtils() {}
-
- public void initializeAppUtils(ServletContext servletContext) {
- try {
- Properties appProperties = ConfigLoader.getProperties(servletContext, ConfigLoader.APP_PROPERTIES, Globals.getSystemType());
- raptorAppProperties = appProperties;
- tempFolderPath = appProperties.getProperty("temp_folder_path");
- uploadFolderPath = appProperties.getProperty("upload_folder_path");
- tempFolderURL = appProperties.getProperty("temp_folder_url");
- uploadFolderURL = appProperties.getProperty("upload_folder_url");
- SMTPServer = appProperties.getProperty("smtp_server");
- encryptedSMTPServer = appProperties.getProperty("encrypted_smtp_server");
- defaultEmailSender = appProperties.getProperty("default_email_sender");
- errorPage = appProperties.getProperty("error_page");
- jspContextPath = appProperties.getProperty("jsp_context_path");
- imgFolderURL = appProperties.getProperty("img_folder_url");
- baseFolderURL = appProperties.getProperty("base_folder_url");
-/* reportExecuteActionURL = appProperties.getProperty("report_execute_action_url");
- dataViewActionURL = appProperties.getProperty("data_view_action_url");
- dataViewActionParam = appProperties.getProperty("data_view_action_param");*/
- directAccessURL = appProperties.getProperty("direct_access_url");
- baseActionURL = appProperties.getProperty("base_action_url");
- baseActionURLNG = appProperties.getProperty("base_action_url_ng");
- drillActionURL = appProperties.getProperty("drill_action_url");
- baseActionParam = appProperties.getProperty("base_action_param");
- superRoleID = appProperties.getProperty("super_role_id");
-
- adminRoleIDs.removeAllElements();
- StringTokenizer st = new StringTokenizer(appProperties.getProperty("admin_role_ids"), ",");
- while(st.hasMoreTokens())
- adminRoleIDs.add(st.nextToken());
-
- quickLinksMenuIDs.removeAllElements();
- st = new StringTokenizer(appProperties.getProperty("quick_links_menu_ids"), ",");
- while(st.hasMoreTokens())
- quickLinksMenuIDs.add(st.nextToken());
- } catch(Exception e) {
- logger.error(EELFLoggerDelegate.debugLogger, ("[EXCEPTION ENCOUNTERED IN RAPTOR] AppUtils.initializeAppUtils: Unable to load properties ["+Globals.getSystemType()+"_"+ConfigLoader.APP_PROPERTIES+"]. Exception: "+e.getMessage()));
- //throw new RuntimeException(e.getMessage());
- }
- } // initializeAppUtils
-
- public static void getFullURL(HttpServletRequest req) {
- String applicationBase = "";
- if (applicationBase == null) {
- applicationBase = req.getScheme() + "://" + req.getServerName() +
- getPort(req) + req.getContextPath();
- }
- }
-
- private static String getPort(HttpServletRequest req) {
- if ("http".equalsIgnoreCase(req.getScheme()) && req.getServerPort() != 80 ||
- "https".equalsIgnoreCase(req.getScheme()) && req.getServerPort() != 443 ) {
- return (":" + req.getServerPort());
- } else {
- return "";
- }
- }
- public String getUserID(HttpServletRequest request) {
- String pdfAttachmentKey = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "pdfAttachmentKey");
- String report_email_sent_log_id = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "log_id");
- boolean isEmailAttachment = false;
- if(pdfAttachmentKey != null && report_email_sent_log_id !=null)
- isEmailAttachment = true;
- if(isEmailAttachment) {
- return RaptorAdapter.getUserID(org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "user_id"));
- } else
- return RaptorAdapter.getUserID(request);
- } // getUserID
-
- public Vector getAllUsers(String customizedQuery, String param, boolean isAdmin) {
- Map map = RaptorAdapter.getAllUsers(customizedQuery, param, isAdmin);
-
- Vector vector = new Vector(map.size());
- for(Iterator iter=map.keySet().iterator(); iter.hasNext(); ) {
- Long key = (Long) iter.next();
- vector.add(new IdNameValue(""+key, (String) map.get(key)));
- } // for
-
- return vector;
- } // getAllUsers
-
- public String getRoleName(String roleId) {
- return RaptorAdapter.getRoleName(roleId);
- } // getRoleName
-
- public Vector getAllRoles(String customizedQuery, String param, boolean isAdmin) {
- Map map = RaptorAdapter.getAllRolesUsingCustomizedQuery(customizedQuery, param, isAdmin);
-
- Vector vector = new Vector(map.size());
- for(Iterator iter=map.keySet().iterator(); iter.hasNext(); ) {
- Long key = (Long) iter.next();
- vector.add(new IdNameValue(""+key, (String) map.get(key)));
- } // for
-
- return vector;
- } // getAllRoles
-
- public String getUserName(HttpServletRequest request) {
- return RaptorAdapter.getUserName(request);
- } // getUserName
-
- public String getUserName(String userId) {
- return RaptorAdapter.getUserName(userId);
- } // getUserName
-
- public String getUserEmail(String userId) {
- return RaptorAdapter.getUserEmail(userId);
- } // getUserEmail
-
- public String getUserEmail(HttpServletRequest request) {
- return RaptorAdapter.getUserEmail(request);
- } // getUserEmail
-
- public String getUserLoginId(HttpServletRequest request) {
- return RaptorAdapter.getUserLoginId(request);
- } // getUserLoginId
-
- public String getUserLoginId(String userId) {
- return RaptorAdapter.getUserLoginId(userId);
- } // getUserLoginId
-
- public String getUserBackdoorLoginId(HttpServletRequest request) {
- String pdfAttachmentKey = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "pdfAttachmentKey");
- String report_email_sent_log_id = org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "log_id");
- boolean isEmailAttachment = false;
- if(pdfAttachmentKey != null && report_email_sent_log_id !=null)
- isEmailAttachment = true;
- if(isEmailAttachment) {
- return RaptorAdapter.getUserBackdoorLoginId(org.openecomp.portalsdk.analytics.system.AppUtils.getRequestValue(request, "user_id"));
- } else
- return RaptorAdapter.getUserBackdoorLoginId(request);
- } // getUserBackdoorLoginId
-
- public boolean isUserInRole(HttpServletRequest request, String roleId) {
- return RaptorAdapter.isCurrentUserInRole(request, roleId);
- } // isUserInRole
-
- public Vector getUserRoles(HttpServletRequest request) {
-// Map map = RaptorAdapter.getAllRoles(userId);
- Set set = RaptorAdapter.getUserRoles(request);
-
- Vector vector = new Vector(set.size());
- for(Iterator iter=set.iterator(); iter.hasNext(); ) {
- Long key = (Long) iter.next();
- vector.add(""+key);
- //vector.add(new IdNameValue(""+key, (String) map.get(key)));
- } // for
-
- return vector;
- } // getUserRoles
-
- public Vector getUserRoles(String userId) {
- Set set = RaptorAdapter.getUserRoles(userId);
-
- Vector vector = new Vector(set.size());
- for(Iterator iter=set.iterator(); iter.hasNext(); ) {
- Long key = (Long) iter.next();
- vector.add(""+key);
- //vector.add(new IdNameValue(""+key, (String) map.get(key)));
- } // for
-
- return vector;
- //return null;
- } // getUserRoles
-
- public void resetUserCache() {
- //org.openecomp.portalsdk.core.web.support.AppUtils.removeObjectFromCache(RaptorAdapter.KEY_USER_ROLES_CACHE);
- } // resetUserCache
-
- public String getSuperRoleID(){
- return superRoleID;
- } // getSuperRoleID
-
- public Vector getAdminRoleIDs(){
- return adminRoleIDs;
- } // getAdminRoleIDs
-
-
- public String getTempFolderPath() {
- return tempFolderPath;
- } // getTempFolderPath
-
- public String getUploadFolderPath() {
- return uploadFolderPath;
- } // getUploadFolderPath
-
- public String getTempFolderURL() {
- return tempFolderURL;
- } // getTempFolderURL
-
- public String getUploadFolderURL() {
- return uploadFolderURL;
- } // getUploadFolderURL
-
- public String getSMTPServer() {
- return SMTPServer;
- } // getSMTPServer
-
- public String getDefaultEmailSender() {
- return defaultEmailSender;
- } // getDefaultEmailSender
-
- public String getErrorPage() {
- return errorPage;
- } // getErrorPage
-
- public String getJspContextPath() {
- return jspContextPath;
- } // getJspContextPath
-
- public String getImgFolderURL() {
- return imgFolderURL;
- } // getImgFolderURL
-
- public String getBaseFolderURL() {
- return baseFolderURL;
- } // getBaseFolderURL
-
-/* public String getReportExecuteActionURL() {
- return reportExecuteActionURL;
- } // getReportExecuteActionURL
-
- public String getDataViewActionURL() {
- return dataViewActionURL;
- } // getDataViewActionURL
-
- public String getDataViewActionParam() {
- return dataViewActionParam;
- } // getDataViewActionParam
-*/
- public String getDirectAccessURL() {
- return directAccessURL.trim();
- } // getDirectAccessURL
-
- public String getBaseActionURL() {
- return baseActionURL;
- } // getBaseActionURL
-
- public String getBaseActionURLNG() {
- return baseActionURLNG;
- } // getBaseActionURLNG
-
- public String getDrillActionURL() {
- return drillActionURL;
- } // getBaseActionURL
-
- public String getBaseActionParam() {
- return baseActionParam;
- } // getBaseActionParam
-
- public Vector getQuickLinksMenuIDs(){
- return quickLinksMenuIDs;
- } // getQuickLinksMenuIDs
-
- public String getMenuLabel(String menuId) {
- //return menuId.substring(0, 1).toUpperCase()+menuId.substring(1).toLowerCase();
- return menuId;
- } // getMenuLabel
-
- public String getReportDbColsMaskSQL() {
- return null;
-/* Example:
- return "SELECT f.table_name, UPPER(f.column_name) column_name, f.label "+
- "FROM fields f WHERE f.active_yn = 'Y'"; */
- } // getReportDbColsMaskSQL
-
- public String getReportDbLookupsSQL() {
- return null;
-/* Example:
- return "SELECT DISTINCT f.table_name, UPPER(f.column_name) column_name, f.lookup_table, f.lookup_id_field, f.lookup_name_field "+
- "FROM fields f WHERE f.active_yn = 'Y'"; */
- } // getReportDbLookupsSQL
-
- public void processErrorNotification(HttpServletRequest request, RaptorException e) {
- //RaptorAdapter.processErrorNotification(request, e);
-} // processErrorNotification
-
- public String getErrorPageWMenu() {
- return errorPageWMenu;
- }
-
- public String getExcelTemplatePath() {
- return nvls(raptorAppProperties.getProperty("excel_template_path"), "");
- }
- /**
- * @return the encryptedSMTPServer
- */
- public String getEncryptedSMTPServer() {
- return encryptedSMTPServer;
- }
-
-} // AppUtils
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java
deleted file mode 100644
index 4638f3e3..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/DbUtils.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion;
-
-import java.sql.Connection;
-
-import javax.servlet.ServletContext;
-
-import org.openecomp.portalsdk.analytics.system.IDbUtils;
-import org.openecomp.portalsdk.analytics.system.fusion.adapter.FusionAdapter;
-import org.openecomp.portalsdk.analytics.system.fusion.adapter.RaptorAdapter;
-import org.openecomp.portalsdk.analytics.system.fusion.adapter.SpringContext;
-import org.springframework.beans.factory.annotation.Autowired;
-
-
-
-public class DbUtils implements IDbUtils {
-
- @Autowired
- public RaptorAdapter raptorAdapter;
- @Autowired
- public FusionAdapter fusionAdapter;
-
- public DbUtils() {}
-
- public void initializeDbUtils(ServletContext servletContext) {
- raptorAdapter = (RaptorAdapter)SpringContext.getApplicationContext().getBean("raptorAdapter");
- } // initializeDbUtils
-
- public Connection getConnection() {
- return raptorAdapter.getConnection();
- } // getConnection
-
- public void clearConnection(Connection con) {
- raptorAdapter.releaseConnection(con);
- } // clearConnection
-
- public RaptorAdapter getRaptorAdapter() {
- return raptorAdapter;
- }
-
- public void setRaptorAdapter(RaptorAdapter raptorAdapter) {
- this.raptorAdapter = raptorAdapter;
- }
-
- public FusionAdapter getFusionAdapter() {
- return fusionAdapter;
- }
-
- public void setFusionAdapter(FusionAdapter fusionAdapter) {
- this.fusionAdapter = fusionAdapter;
- }
-
-
-
-
-
-} // DbUtils
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java
deleted file mode 100644
index ac6cd16c..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/adapter/Lookup.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion.adapter;
-
-
-import java.io.Serializable;
-
-import org.openecomp.portalsdk.core.domain.FusionVo;
-import org.openecomp.portalsdk.core.domain.support.NameValueId;
-
-
-
-public class Lookup extends FusionVo implements Serializable {
-
- private NameValueId nameValueId = new NameValueId();
-
- public Lookup() {}
-
- public Lookup(String label, String value) {
- this();
- setLabel(label);
- setValue(value);
- }
-
- public String getValue() {
- return getNameValueId().getVal();
- }
-
- public String getLabel() {
- return getNameValueId().getLab();
- }
-
- public void setValue(String value) {
- getNameValueId().setVal(value);
- }
-
- public void setLabel(String label) {
- getNameValueId().setLab(label);
- }
-
- public NameValueId getNameValueId() {
- return nameValueId;
- }
-
- public void setNameValueId(NameValueId nameValueId) {
- this.nameValueId = nameValueId;
- }
-
- // required by ZK for to set the selectedItems of Listboxes (used heavily for <select>-style drop-downs)
- public int hashCode() {
- int hash = getValue().hashCode();
- hash = hash + getLabel().hashCode();
-
- return hash;
- }
-
- public boolean equals( Object obj ) {
- boolean equivalent = false;
-
- Lookup lookup = (Lookup)obj;
- if( lookup.getValue().equals(getValue()) && lookup.getLabel().equals(getLabel())) {
- equivalent = true;
- }
-
- return equivalent;
- }
-
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java
deleted file mode 100644
index 417a8e19..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorController.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion.web;
-
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.openecomp.portalsdk.analytics.controller.Action;
-import org.openecomp.portalsdk.analytics.controller.ErrorHandler;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-@Controller
-@RequestMapping("/")
-public class RaptorController extends RestrictedBaseController{
- String viewName;
- //static org.apache.log4j.Logger s_logger = org.apache.log4j.Logger.getLogger(RaptorController.class.getName());
-
- @RequestMapping(value = {"/report" }, method = RequestMethod.GET)
- public ModelAndView report(HttpServletRequest request) {
- request.getSession().setAttribute("isEmbedded", false);
- viewName = "report";
- return new ModelAndView(getViewName());
- }
-
- @RequestMapping(value = {"/report_embedded" }, method = RequestMethod.GET)
- public ModelAndView embededReport(HttpServletRequest request) {
- request.getSession().setAttribute("isEmbedded", true);
- viewName = "report_embedded";
- return new ModelAndView(getViewName());
- }
-
- @RequestMapping(value = {"/report_sample" }, method = RequestMethod.GET)
- public ModelAndView reportSample(HttpServletRequest request) {
- viewName = "report_sample";
- return new ModelAndView(getViewName());
- }
-
- @RequestMapping(value = {"/report_import.htm" }, method = RequestMethod.GET)
-
- public ModelAndView RaptorWizard1(HttpServletRequest request, HttpServletResponse response) throws IOException {
- viewName = "report_import";
- Action action = null;
- String actionKey = "report.import";
- ServletContext servletContext = request.getSession().getServletContext();
- if( !Globals.isSystemInitialized()) {
- Globals.initializeSystem(servletContext);
- }
- try {
- action = Globals.getRaptorActionMapping().getAction(actionKey);
- if (action == null)
- throw new RaptorRuntimeException("Action not found");
- } catch (RaptorException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. RaptorException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. Exception: " + e.getMessage()));
- }
- return new ModelAndView(getViewName(), "model", null);
- }
-
-
- @RequestMapping(value = {"/report_wizard.htm" }, method = {RequestMethod.POST, RequestMethod.GET})
- public ModelAndView RaptorWizard(HttpServletRequest request, HttpServletResponse response) throws IOException {
-
-
- viewName = "";
- String actionKey = nvl(request.getParameter(AppConstants.RI_ACTION), request.getParameter("action"));
- actionKey = nvl(actionKey, "report.run");
- Action action = null;
- ServletContext servletContext = request.getSession().getServletContext();
- if( !Globals.isSystemInitialized()) {
- Globals.initializeSystem(servletContext);
- }
- try {
- action = Globals.getRaptorActionMapping().getAction(actionKey);
- if (action == null)
- throw new RaptorRuntimeException("Action not found");
- } catch (RaptorException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. RaptorException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. Exception: " + e.getMessage()));
- }
-
- try {
- Class[] paramTypes = new Class[2];
- paramTypes[0] = Class.forName("javax.servlet.http.HttpServletRequest");
- paramTypes[1] = Class.forName("java.lang.String");
-
- Class handlerClass = Class.forName(action.getControllerClass());
- Object handler = handlerClass.newInstance();
- Method handlerMethod = handlerClass.getMethod(action.getControllerMethod(),
- paramTypes);
-
- Object[] paramValues = new Object[2];
- paramValues[0] = request;
- paramValues[1] = action.getJspName();;
-
- viewName = (String) handlerMethod.invoke(handler, paramValues);
- //ObjectMapper mapper = new ObjectMapper();
- //response.setContentType("application/json");
- //PrintWriter out = response.getWriter();
- //out.write(viewName);
-
- } catch (ClassNotFoundException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. ClassNotFoundException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- } catch (IllegalAccessException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. IllegalAccessException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (InstantiationException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("Ocurring during Schedule "));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (NoSuchMethodException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. NoSuchMethodException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (InvocationTargetException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. InvocationTargetException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }
- return new ModelAndView(getViewName(), "model", null);
- }
-
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
-
- public String nvl(String s) {
- return (s == null) ? "" : s;
- }
-
- public String nvl(String s, String sDefault) {
- return nvl(s).equals("") ? sDefault : s;
- }
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RaptorController.class);
-
-
-
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java
deleted file mode 100644
index bd3fdce3..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/system/fusion/web/RaptorControllerAsync.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.analytics.system.fusion.web;
-
-
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.openecomp.portalsdk.analytics.controller.Action;
-import org.openecomp.portalsdk.analytics.controller.ErrorHandler;
-import org.openecomp.portalsdk.analytics.error.RaptorException;
-import org.openecomp.portalsdk.analytics.error.RaptorRuntimeException;
-import org.openecomp.portalsdk.analytics.model.ReportHandler;
-import org.openecomp.portalsdk.analytics.model.pdf.PdfReportHandler;
-import org.openecomp.portalsdk.analytics.model.runtime.CategoryAxisJSON;
-import org.openecomp.portalsdk.analytics.model.runtime.ChartJSON;
-import org.openecomp.portalsdk.analytics.model.runtime.RangeAxisJSON;
-import org.openecomp.portalsdk.analytics.model.runtime.ReportRuntime;
-import org.openecomp.portalsdk.analytics.system.AppUtils;
-import org.openecomp.portalsdk.analytics.system.Globals;
-import org.openecomp.portalsdk.analytics.util.AppConstants;
-import org.openecomp.portalsdk.analytics.view.ReportData;
-import org.openecomp.portalsdk.analytics.xmlobj.DataColumnType;
-import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController;
-import org.openecomp.portalsdk.core.domain.User;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.web.support.UserUtils;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-@Controller
-@RequestMapping("/")
-public class RaptorControllerAsync extends UnRestrictedBaseController{
- String viewName;
-
- @RequestMapping(value = {"/raptor.htm" }, method = RequestMethod.GET)
- public void RaptorSearch(HttpServletRequest request, HttpServletResponse response) throws IOException {
-
- /* List items = null;
- int reportId = ServletRequestUtils.getIntParameter(request, "report_id", 0);
- //String task = ServletRequestUtils.getStringParameter(request, "task", TASK_GET);
-
- HashMap additionalParams = new HashMap();
- additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request);
-
- return new ModelAndView(getViewName(), "model", null);
-
- //return new ModelAndView(getViewName(), "model", null);
- //System.out.println("Fill with proper code");
- //return null;*/
- viewName = "";
- String actionKey = nvl(request.getParameter(AppConstants.RI_ACTION), request.getParameter("action"));
- actionKey = nvl(actionKey, "report.run");
-
- HttpSession session = request.getSession();
- User user = UserUtils.getUserSession(request);
-
- if(actionKey.equals("report.download.excel2007.session") || actionKey.equals("report.download.csv.session") || actionKey.equals("report.download.excel.session") || actionKey.equals("report.download.pdf.session") ) {
- if(session!=null && user!=null){
- ServletContext servletContext = request.getSession().getServletContext();
- if( !Globals.isSystemInitialized()) {
- Globals.initializeSystem(servletContext);
- }
- ReportRuntime rr = null;
- ReportData rd = null;
- String parent = "";
- int parentFlag = 0;
- if(!nvl(request.getParameter("parent"), "").equals("N")) parent = nvl(request.getParameter("parent"), "");
- if(parent.startsWith("parent_")) parentFlag = 1;
- if(parentFlag == 1) {
- rr = (ReportRuntime) request.getSession().getAttribute(parent+"_rr");
- rd = (ReportData) request.getSession().getAttribute(parent+"_rd");
- }
-
- boolean isEmbedded = false;
- Object temp = request.getSession().getAttribute("isEmbedded");
- if(temp!=null){
- isEmbedded = (boolean)temp;
- }
- if(isEmbedded){
- String reportID = AppUtils.getRequestValue(request, AppConstants.RI_REPORT_ID);
- if(rr==null) rr = (ReportRuntime) ((HashMap)request.getSession().getAttribute(AppConstants.EMBEDDED_REPORTRUNTIME_MAP)).get(reportID);
- if(rd==null) rd = (ReportData) ((HashMap)request.getSession().getAttribute(AppConstants.EMBEDDED_REPORTDATA_MAP)).get(reportID);
- } else {
- if(rr==null) rr = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME);
- if(rd==null) rd = (ReportData) request.getSession().getAttribute(AppConstants.RI_REPORT_DATA);
- }
- String user_id = AppUtils.getUserID(request);
- try {
- OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream());
-
- if(actionKey.equals("report.download.pdf.session")) {
- new PdfReportHandler().createPdfFileContent(request,response, 3);
- } else if (actionKey.equals("report.download.csv.session")) {
- (new ReportHandler()).createCSVFileContent(out, rd, rr, request, response);
- } else if (actionKey.equals("report.download.excel.session")) {
- new ReportHandler().createExcelFileContent(out, rd, rr, request, response, user_id, 3); //3 whole
- } else {
-
- new ReportHandler().createExcel2007FileContent(out, rd, rr, request, response, user_id, 3); //3 whole
- }
- } catch(Exception e) {
- e.printStackTrace();
- //Log.write("Fatal error [report_download_xlsx.jsp]: "+e.getMessage());
- }
- } else {
- response.sendRedirect("login.htm");
- }
- } else {
- if(session!=null && user!=null){
- Action action = null;
- ServletContext servletContext = request.getSession().getServletContext();
- if( !Globals.isSystemInitialized()) {
- Globals.initializeSystem(servletContext);
- }
- try {
- action = Globals.getRaptorActionMapping().getAction(actionKey);
- if (action == null)
- throw new RaptorRuntimeException("Action not found");
- } catch (RaptorException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. RaptorException: " + e.getMessage()));
-
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. Exception: " + e.getMessage()));
- }
-
- try {
- Class[] paramTypes = new Class[2];
- paramTypes[0] = Class.forName("javax.servlet.http.HttpServletRequest");
- paramTypes[1] = Class.forName("java.lang.String");
-
- Class handlerClass = Class.forName(action.getControllerClass());
- Object handler = handlerClass.newInstance();
- Method handlerMethod = handlerClass.getMethod(action.getControllerMethod(),
- paramTypes);
-
- Object[] paramValues = new Object[2];
- paramValues[0] = request;
- paramValues[1] = action.getJspName();;
-
- viewName = (String) handlerMethod.invoke(handler, paramValues);
- //ObjectMapper mapper = new ObjectMapper();
- if(!actionKey.equals("chart.run"))
- response.setContentType("application/json");
- else
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.write(viewName);
-
- } catch (ClassNotFoundException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. ClassNotFoundException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- } catch (IllegalAccessException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. IllegalAccessException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (InstantiationException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. InstantiationException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (NoSuchMethodException e) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. NoSuchMethodException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }catch (InvocationTargetException e) {
- e.printStackTrace();
- logger.debug(EELFLoggerDelegate.debugLogger, ("[Controller.processRequest]Invalid raptor action [" + actionKey
- + "]. InvocationTargetException: " + e.getMessage()));
- viewName = (new ErrorHandler()).processFatalError(request, new RaptorRuntimeException(
- "[Controller.processRequest] Unable to instantiate and invoke action handler. Exception: "
- + e.getMessage()));
- }
- //return new ModelAndView(getViewName(), "model", null);
- } else {
- PrintWriter out = response.getWriter();
- out.write("session has timed out for user");
- }
-
- }
- }
-
- @RequestMapping(value = "save_chart", method = RequestMethod.POST)
- public void reportChartReceive(@RequestBody ChartJSON chartJSON, HttpServletRequest request, HttpServletResponse response) throws IOException {
- ReportRuntime reportRuntime;
- System.out.println("*****Hit RaptorChart******");
- reportRuntime = (ReportRuntime) request.getSession().getAttribute(AppConstants.SI_REPORT_RUNTIME); //changing session to request
- String reportID = request.getParameter("c_master");
- if (reportRuntime == null && AppUtils.nvl(reportID).length() > 0) {
- try {
- ReportHandler rh = new ReportHandler();
- reportRuntime = rh.loadReportRuntime(request, reportID);
- } catch (RaptorException ex) {
- ex.printStackTrace();
-
- }
- }
-
- if (reportRuntime != null) {
- String chartType = chartJSON.getChartType();
- reportRuntime.setChartType(chartJSON.getChartType());
- reportRuntime.setChartAnimate(chartJSON.isAnimation());
- reportRuntime.setChartWidth(chartJSON.getWidth());
- reportRuntime.setChartHeight(chartJSON.getHeight());
- reportRuntime.setShowChartTitle(chartJSON.isShowTitle());
-
-
- String domainAxis = null;
- domainAxis = chartJSON.getDomainAxis();
-
- List < DataColumnType > reportCols = reportRuntime.getAllColumns();
-
- for (Iterator < DataColumnType > iter = reportCols.iterator(); iter
- .hasNext();) {
- DataColumnType dct = (DataColumnType) iter.next();
- if (dct.getColId().equals(domainAxis)) {
- dct.setColOnChart(AppConstants.GC_LEGEND);
- } else {
- dct.setColOnChart(null);
- }
- }
-
- CategoryAxisJSON categoryAxisJSON = chartJSON.getCategoryAxisJSON();
- String categoryAxis = null;
-
- categoryAxis = (categoryAxisJSON!=null?categoryAxisJSON.getValue():"");
-
- reportCols = reportRuntime.getAllColumns();
-
- for (Iterator < DataColumnType > iter = reportCols.iterator(); iter
- .hasNext();) {
- DataColumnType dct = (DataColumnType) iter.next();
- if (dct.getColId().equals(categoryAxis)) {
- dct.setChartSeries(true);
- } else {
- dct.setChartSeries(false);
- }
- }
-
-
- ArrayList < RangeAxisJSON > rangeAxisList = chartJSON.getRangeAxisList();
- int r = 0;
- for (int i = 0; i < rangeAxisList.size(); i++) {
- RangeAxisJSON rangeAxisJSON = rangeAxisList.get(i);
- String rangeAxis = rangeAxisJSON.getRangeAxis();
- String rangeYAxis = AppUtils.nvl(rangeAxisJSON.getRangeYAxis());
- String rangeChartGroup = AppUtils.nvl(rangeAxisJSON.getRangeChartGroup());
- String rangeColor = AppUtils.nvl(rangeAxisJSON.getRangeColor());
- String rangeLineType = AppUtils.nvl(rangeAxisJSON.getRangeLineType());
-
- rangefor:
- for (Iterator < DataColumnType > iterator = reportCols.iterator(); iterator.hasNext();) {
- DataColumnType dct = (DataColumnType) iterator.next();
- if (dct.getColId().equals(rangeAxis)) {
- dct.setChartSeq(++r);
- dct.setColOnChart("0");
- dct.setYAxis(rangeYAxis); //+"|"+dct.getColId());
- dct.setChartGroup(rangeChartGroup); //+"|"+dct.getColId());
- dct.setChartColor(rangeColor);
- dct.setChartLineType(rangeLineType);
-
- if (chartType.equals(AppConstants.GT_ANNOTATION_CHART) || chartType.equals(AppConstants.GT_FLEX_TIME_CHARTS)) {
- if (rangeAxisJSON.isShowAsArea()) {
- dct.setIsRangeAxisFilled(true);
- } else {
- dct.setIsRangeAxisFilled(false);
- }
- }
- break rangefor;
- }
- }
-
- }
-
-
- reportRuntime.setChartLeftAxisLabel(chartJSON.getPrimaryAxisLabel());
- reportRuntime.setChartRightAxisLabel(chartJSON.getSecondaryAxisLabel());
-
- reportRuntime.setRangeAxisLowerLimit(chartJSON.getMinRange());
- reportRuntime.setRangeAxisUpperLimit(chartJSON.getMaxRange());
-
-
-
- if (chartType.equals(AppConstants.GT_ANNOTATION_CHART) || chartType.equals(AppConstants.GT_FLEX_TIME_CHARTS)) {
- if (chartJSON.getFlexTimeSeriesChartOptions() != null) {
- reportRuntime.setZoomIn(chartJSON.getFlexTimeSeriesChartOptions().getZoomIn());
- reportRuntime.setTimeAxisType(chartJSON.getFlexTimeSeriesChartOptions().getTimeAxisType());
- }
-
- }
-
- if (chartType.equals(AppConstants.GT_TIME_SERIES)) {
- if (chartJSON.getTimeSeriesChartOptions() != null) {
- reportRuntime.setTimeSeriesRender(chartJSON.getTimeSeriesChartOptions().getLineChartRenderer());
- reportRuntime.setShowXAxisLabel(chartJSON.getTimeSeriesChartOptions().isShowXAxisLabel());
- reportRuntime.setAddXAxisTickers(chartJSON.getTimeSeriesChartOptions().isAddXAxisTicker());
- reportRuntime.setTimeAxis(chartJSON.getTimeSeriesChartOptions().isNonTimeAxis());
- reportRuntime.setMultiSeries(chartJSON.getTimeSeriesChartOptions().isMultiSeries());
- }
-
- }
-
- if (chartType.equals(AppConstants.GT_BAR_3D)) {
- if (chartJSON.getBarChartOptions() != null) {
- reportRuntime.setChartOrientation(chartJSON.getBarChartOptions().isVerticalOrientation() ? "vertical" : "horizontal");
- reportRuntime.setChartStacked(chartJSON.getBarChartOptions().isStackedChart());
- reportRuntime.setBarControls(chartJSON.getBarChartOptions().isDisplayBarControls());
- reportRuntime.setXAxisDateType(chartJSON.getBarChartOptions().isxAxisDateType());
- reportRuntime.setLessXaxisTickers(chartJSON.getBarChartOptions().isMinimizeXAxisTickers());
- reportRuntime.setTimeAxis(chartJSON.getBarChartOptions().isTimeAxis());
- reportRuntime.setLogScale(chartJSON.getBarChartOptions().isyAxisLogScale());
- }
- }
-
-
- reportRuntime.setLegendLabelAngle(chartJSON.getCommonChartOptions().getLegendLabelAngle());
- reportRuntime.setChartLegendDisplay(chartJSON.getCommonChartOptions().isHideLegend() ? "Y" : "N");
- reportRuntime.setAnimateAnimatedChart(chartJSON.getCommonChartOptions().isAnimateAnimatedChart());
-
- reportRuntime.setTopMargin(chartJSON.getCommonChartOptions().getTopMargin());
- reportRuntime.setBottomMargin(chartJSON.getCommonChartOptions().getBottomMargin());
- reportRuntime.setLeftMargin(chartJSON.getCommonChartOptions().getLeftMargin());
- reportRuntime.setRightMargin(chartJSON.getCommonChartOptions().getRightMargin());
-
-
-
- for (Iterator < DataColumnType > iterator = reportCols.iterator(); iterator.hasNext();) {
- DataColumnType dct = (DataColumnType) iterator.next();
- if (!(AppUtils.nvl(dct.getColOnChart()).equals(AppConstants.GC_LEGEND) || (dct.getChartSeq()!=null && dct.getChartSeq()>0) || dct.isChartSeries()) ) {
- dct.setChartSeq(-1);
- dct.setChartColor(null);
- dct.setColOnChart(null);
- dct.setCreateInNewChart(false);
- dct.setChartGroup(null);
- dct.setYAxis(null);
- }
- }
-
-
- try {
- reportRuntime.persistLinearReport(request);
- } catch (Exception ex) {
- ex.printStackTrace();
- logger.error("While SAVING CHART", ex);
- }
- }
-
- }
-
- public String getViewName() {
- return viewName;
- }
- public void setViewName(String viewName) {
- this.viewName = viewName;
- }
-
- public String nvl(String s) {
- return (s == null) ? "" : s;
- }
-
- public String nvl(String s, String sDefault) {
- return nvl(s).equals("") ? sDefault : s;
- }
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RaptorControllerAsync.class);
-
-
-
-}
diff --git a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java b/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java
deleted file mode 100644
index c57ab581..00000000
--- a/ecomp-sdk/sdk-analytics/src/main/java/org/openecomp/portalsdk/analytics/xmlobj/ReportMap.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.5-2
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2016.06.07 at 02:07:29 PM EDT
-//
-
-
-package org.openecomp.portalsdk.analytics.xmlobj;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for ReportMap complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * &lt;complexType name="ReportMap">
- * &lt;complexContent>
- * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * &lt;sequence>
- * &lt;element name="markerColor" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="useDefaultSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="height" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="width" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="isMapAllowedYN" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="addAddressInDataYN" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="addressColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="dataColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="defaultMapType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="latColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="longColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="colorColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="legendColumn" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * &lt;element name="markers" type="{}Marker" maxOccurs="unbounded" minOccurs="0"/>
- * &lt;/sequence>
- * &lt;/restriction>
- * &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "ReportMap", propOrder = {
- "markerColor",
- "useDefaultSize",
- "height",
- "width",
- "isMapAllowedYN",
- "addAddressInDataYN",
- "addressColumn",
- "dataColumn",
- "defaultMapType",
- "latColumn",
- "longColumn",
- "colorColumn",
- "legendColumn",
- "markers"
-})
-public class ReportMap {
-
- protected String markerColor;
- protected String useDefaultSize;
- protected String height;
- protected String width;
- protected String isMapAllowedYN;
- protected String addAddressInDataYN;
- protected String addressColumn;
- protected String dataColumn;
- protected String defaultMapType;
- protected String latColumn;
- protected String longColumn;
- protected String colorColumn;
- protected String legendColumn;
- protected List<Marker> markers;
-
- /**
- * Gets the value of the markerColor property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getMarkerColor() {
- return markerColor;
- }
-
- /**
- * Sets the value of the markerColor property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setMarkerColor(String value) {
- this.markerColor = value;
- }
-
- /**
- * Gets the value of the useDefaultSize property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getUseDefaultSize() {
- return useDefaultSize;
- }
-
- /**
- * Sets the value of the useDefaultSize property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setUseDefaultSize(String value) {
- this.useDefaultSize = value;
- }
-
- /**
- * Gets the value of the height property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getHeight() {
- return height;
- }
-
- /**
- * Sets the value of the height property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setHeight(String value) {
- this.height = value;
- }
-
- /**
- * Gets the value of the width property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getWidth() {
- return width;
- }
-
- /**
- * Sets the value of the width property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setWidth(String value) {
- this.width = value;
- }
-
- /**
- * Gets the value of the isMapAllowedYN property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getIsMapAllowedYN() {
- return isMapAllowedYN;
- }
-
- /**
- * Sets the value of the isMapAllowedYN property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setIsMapAllowedYN(String value) {
- this.isMapAllowedYN = value;
- }
-
- /**
- * Gets the value of the addAddressInDataYN property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getAddAddressInDataYN() {
- return addAddressInDataYN;
- }
-
- /**
- * Sets the value of the addAddressInDataYN property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setAddAddressInDataYN(String value) {
- this.addAddressInDataYN = value;
- }
-
- /**
- * Gets the value of the addressColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getAddressColumn() {
- return addressColumn;
- }
-
- /**
- * Sets the value of the addressColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setAddressColumn(String value) {
- this.addressColumn = value;
- }
-
- /**
- * Gets the value of the dataColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getDataColumn() {
- return dataColumn;
- }
-
- /**
- * Sets the value of the dataColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setDataColumn(String value) {
- this.dataColumn = value;
- }
-
- /**
- * Gets the value of the defaultMapType property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getDefaultMapType() {
- return defaultMapType;
- }
-
- /**
- * Sets the value of the defaultMapType property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setDefaultMapType(String value) {
- this.defaultMapType = value;
- }
-
- /**
- * Gets the value of the latColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLatColumn() {
- return latColumn;
- }
-
- /**
- * Sets the value of the latColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLatColumn(String value) {
- this.latColumn = value;
- }
-
- /**
- * Gets the value of the longColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLongColumn() {
- return longColumn;
- }
-
- /**
- * Sets the value of the longColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLongColumn(String value) {
- this.longColumn = value;
- }
-
- /**
- * Gets the value of the colorColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getColorColumn() {
- return colorColumn;
- }
-
- /**
- * Sets the value of the colorColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setColorColumn(String value) {
- this.colorColumn = value;
- }
-
- /**
- * Gets the value of the legendColumn property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLegendColumn() {
- return legendColumn;
- }
-
- /**
- * Sets the value of the legendColumn property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLegendColumn(String value) {
- this.legendColumn = value;
- }
-
- /**
- * Gets the value of the markers property.
- *
- * <p>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the markers property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getMarkers().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link Marker }
- *
- *
- */
- public List<Marker> getMarkers() {
- if (markers == null) {
- markers = new ArrayList<Marker>();
- }
- return this.markers;
- }
-
-}
diff --git a/ecomp-sdk/sdk-app/.gitignore b/ecomp-sdk/sdk-app/.gitignore
deleted file mode 100644
index b83d2226..00000000
--- a/ecomp-sdk/sdk-app/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/ecomp-sdk/sdk-app/README.md b/ecomp-sdk/sdk-app/README.md
deleted file mode 100644
index bdaf8a42..00000000
--- a/ecomp-sdk/sdk-app/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-Ecomp SDK Web App
-=================
-
-This is the ECOMP SDK web application. It includes java source files,
-as well as CSS, JavaScript, JSP and HTML files. The java code depends
-on the following ECOMP SDK libraries that are developed by the ECOMP
-Portal:
-
-* ECOMP SDK Framework library
-* ECOMP SDK Core library
-* ECOMP SDK Analytics library
-* ECOMP SDK Workflow library
-
-Use Apache Maven to build and package this webapp.
diff --git a/ecomp-sdk/sdk-app/db-scripts/EcompSdkDDLMySql_1610_Complete_OS.sql b/ecomp-sdk/sdk-app/db-scripts/EcompSdkDDLMySql_1610_Complete_OS.sql
deleted file mode 100644
index a792b735..00000000
--- a/ecomp-sdk/sdk-app/db-scripts/EcompSdkDDLMySql_1610_Complete_OS.sql
+++ /dev/null
@@ -1,1402 +0,0 @@
-
--- ---------------------------------------------------------------------------------------------------------------
--- This is for the 1610 Version of SDK database called ecomp_sdk for Open Source
-
--- Note to : Database Admin, set the MySQL system variable called lower_case_table_names
-
--- It can be set 3 different ways:
--- command-line options (Cmd-line),
--- options valid in configuration files (Option file), or
--- server system variables (System Var).
-
--- It needs to be set to 1, then table names are stored in lowercase on disk and comparisons are not case sensitive.
-
--- MySql/MariaDB Version compatibility information
--- $ mysql --version
--- mysql Ver 15.1 Distrib 5.5.35-MariaDB, for Linux (x86_64) using readline 5.1
-
--- bash-4.2$ mysql --version – cluster version
--- mysql Ver 15.1 Distrib 10.1.17-MariaDB, for Linux (x86_64) using readline 5.1
-
--- All versions newer or older than these DO NOT necessarily mean they are compatible.
--- ------------------------------------------------------------------------------------------------------------------
-
-SET FOREIGN_KEY_CHECKS=1;
-
-CREATE DATABASE ecomp_sdk_os;
-
-USE ecomp_sdk_os;
-
--- ---------- create table SECTION
---
--- NAME: CR_FAVORITE_REPORTS; TYPE: TABLE
---
-create table cr_favorite_reports (
- USER_ID INTEGER NOT NULL,
- REP_ID INTEGER NOT NULL
-);
-
---
--- NAME: CR_FILEHIST_LOG; TYPE: TABLE
---
-create table cr_filehist_log (
- SCHEDULE_ID NUMERIC(11,0) NOT NULL,
- URL CHARACTER VARYING(4000),
- NOTES CHARACTER VARYING(3500),
- RUN_TIME TIMESTAMP
-);
-
---
--- NAME: CR_FOLDER; TYPE: TABLE
---
-create table cr_folder (
- FOLDER_ID INTEGER NOT NULL,
- FOLDER_NAME CHARACTER VARYING(50) NOT NULL,
- DESCR CHARACTER VARYING(500),
- CREATE_ID INTEGER NOT NULL,
- CREATE_DATE TIMESTAMP NOT NULL,
- PARENT_FOLDER_ID INTEGER,
- PUBLIC_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
-);
-
---
--- NAME: CR_FOLDER_ACCESS; TYPE: TABLE
---
-create table cr_folder_access (
- FOLDER_ACCESS_ID NUMERIC(11,0) NOT NULL,
- FOLDER_ID NUMERIC(11,0) NOT NULL,
- ORDER_NO NUMERIC(11,0) NOT NULL,
- ROLE_ID NUMERIC(11,0),
- USER_ID NUMERIC(11,0),
- READ_ONLY_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
-);
-
---
--- NAME: CR_HIST_USER_MAP; TYPE: TABLE
---
-create table cr_hist_user_map (
- HIST_ID INT(11) NOT NULL,
- USER_ID INT(11) NOT NULL
-);
-
---
--- NAME: CR_LU_FILE_TYPE; TYPE: TABLE
---
-create table cr_lu_file_type (
- LOOKUP_ID NUMERIC(2,0) NOT NULL,
- LOOKUP_DESCR CHARACTER VARYING(255) NOT NULL,
- ACTIVE_YN CHARACTER(1) DEFAULT 'Y',
- ERROR_CODE NUMERIC(11,0)
-);
-
---
--- NAME: CR_RAPTOR_ACTION_IMG; TYPE: TABLE
---
-create table cr_raptor_action_img (
- IMAGE_ID CHARACTER VARYING(100) NOT NULL,
- IMAGE_LOC CHARACTER VARYING(400)
-);
-
---
--- NAME: CR_RAPTOR_PDF_IMG; TYPE: TABLE
---
-create table cr_raptor_pdf_img (
- IMAGE_ID CHARACTER VARYING(100) NOT NULL,
- IMAGE_LOC CHARACTER VARYING(400)
-);
-
---
--- NAME: CR_REMOTE_SCHEMA_INFO; TYPE: TABLE
---
-create table cr_remote_schema_info (
- SCHEMA_PREFIX CHARACTER VARYING(5) NOT NULL,
- SCHEMA_DESC CHARACTER VARYING(75) NOT NULL,
- DATASOURCE_TYPE CHARACTER VARYING(100)
-);
-
---
--- NAME: CR_REPORT; TYPE: TABLE
---
-create table cr_report (
- REP_ID NUMERIC(11,0) NOT NULL,
- TITLE CHARACTER VARYING(100) NOT NULL,
- DESCR CHARACTER VARYING(255),
- PUBLIC_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
- REPORT_XML TEXT,
- CREATE_ID NUMERIC(11,0),
- CREATE_DATE TIMESTAMP default now(),
- MAINT_ID NUMERIC(11,0),
- MAINT_DATE TIMESTAMP DEFAULT NOW(),
- MENU_ID CHARACTER VARYING(500),
- MENU_APPROVED_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
- OWNER_ID NUMERIC(11,0),
- FOLDER_ID INTEGER DEFAULT 0,
- DASHBOARD_TYPE_YN CHARACTER VARYING(1) DEFAULT 'N',
- DASHBOARD_YN CHARACTER VARYING(1) DEFAULT 'N'
-);
-
---
--- NAME: CR_REPORT_ACCESS; TYPE: TABLE
---
-create table cr_report_access (
- REP_ID NUMERIC(11,0) NOT NULL,
- ORDER_NO NUMERIC(11,0) NOT NULL,
- ROLE_ID NUMERIC(11,0),
- USER_ID NUMERIC(11,0),
- READ_ONLY_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL
-);
-
---
--- NAME: CR_REPORT_DWNLD_LOG; TYPE: TABLE
---
-create table cr_report_dwnld_log (
- USER_ID NUMERIC(11,0) NOT NULL,
- REP_ID INTEGER NOT NULL,
- FILE_NAME CHARACTER VARYING(100) NOT NULL,
- DWNLD_START_TIME TIMESTAMP DEFAULT NOW() NOT NULL,
- RECORD_READY_TIME TIMESTAMP DEFAULT NOW(),
- FILTER_PARAMS CHARACTER VARYING(2000)
-);
-
---
--- NAME: CR_REPORT_EMAIL_SENT_LOG; TYPE: TABLE
---
-create table cr_report_email_sent_log (
- LOG_ID INTEGER NOT NULL,
- SCHEDULE_ID NUMERIC(11,0),
- GEN_KEY CHARACTER VARYING(25) NOT NULL,
- REP_ID NUMERIC(11,0) NOT NULL,
- USER_ID NUMERIC(11,0),
- SENT_DATE TIMESTAMP DEFAULT NOW(),
- ACCESS_FLAG CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
- TOUCH_DATE TIMESTAMP DEFAULT NOW()
-);
-
---
--- NAME: CR_REPORT_FILE_HISTORY; TYPE: TABLE
---
-create table cr_report_file_history (
- HIST_ID INT(11) NOT NULL,
- SCHED_USER_ID NUMERIC(11,0) NOT NULL,
- SCHEDULE_ID NUMERIC(11,0) NOT NULL,
- USER_ID NUMERIC(11,0) NOT NULL,
- REP_ID NUMERIC(11,0),
- RUN_DATE TIMESTAMP,
- RECURRENCE CHARACTER VARYING(50),
- FILE_TYPE_ID NUMERIC(2,0),
- FILE_NAME CHARACTER VARYING(80),
- FILE_BLOB BLOB,
- FILE_SIZE NUMERIC(11,0),
- RAPTOR_URL CHARACTER VARYING(4000),
- ERROR_YN CHARACTER(1) DEFAULT 'N',
- ERROR_CODE NUMERIC(11,0),
- DELETED_YN CHARACTER(1) DEFAULT 'N',
- DELETED_BY NUMERIC(38,0)
-);
-
---
--- NAME: CR_REPORT_LOG; TYPE: TABLE
---
-create table cr_report_log (
- REP_ID NUMERIC(11,0) NOT NULL,
- LOG_TIME TIMESTAMP NOT NULL,
- USER_ID NUMERIC(11,0) NOT NULL,
- ACTION CHARACTER VARYING(2000) NOT NULL,
- ACTION_VALUE CHARACTER VARYING(50),
- FORM_FIELDS CHARACTER VARYING(4000)
-);
-
---
--- NAME: CR_REPORT_SCHEDULE; TYPE: TABLE
---
-create table cr_report_schedule (
- SCHEDULE_ID NUMERIC(11,0) NOT NULL,
- SCHED_USER_ID NUMERIC(11,0) NOT NULL,
- REP_ID NUMERIC(11,0) NOT NULL,
- ENABLED_YN CHARACTER VARYING(1) NOT NULL,
- START_DATE TIMESTAMP DEFAULT NOW(),
- END_DATE TIMESTAMP DEFAULT NOW(),
- RUN_DATE TIMESTAMP DEFAULT NOW(),
- RECURRENCE CHARACTER VARYING(50),
- CONDITIONAL_YN CHARACTER VARYING(1) NOT NULL,
- CONDITION_SQL CHARACTER VARYING(4000),
- NOTIFY_TYPE INTEGER DEFAULT 0,
- MAX_ROW INTEGER DEFAULT 1000,
- INITIAL_FORMFIELDS CHARACTER VARYING(3500),
- PROCESSED_FORMFIELDS CHARACTER VARYING(3500),
- FORMFIELDS CHARACTER VARYING(3500),
- CONDITION_LARGE_SQL TEXT,
- ENCRYPT_YN CHARACTER(1) DEFAULT 'N',
- ATTACHMENT_YN CHARACTER(1) DEFAULT 'Y'
-);
-
---
--- NAME: CR_REPORT_SCHEDULE_USERS; TYPE: TABLE
---
-create table cr_report_schedule_users (
- SCHEDULE_ID NUMERIC(11,0) NOT NULL,
- REP_ID NUMERIC(11,0) NOT NULL,
- USER_ID NUMERIC(11,0) NOT NULL,
- ROLE_ID NUMERIC(11,0),
- ORDER_NO NUMERIC(11,0) NOT NULL
-);
-
---
--- NAME: CR_REPORT_TEMPLATE_MAP; TYPE: TABLE
---
-create table cr_report_template_map (
- REPORT_ID INTEGER NOT NULL,
- TEMPLATE_FILE CHARACTER VARYING(200)
-);
-
---
--- NAME: CR_SCHEDULE_ACTIVITY_LOG; TYPE: TABLE
---
-create table cr_schedule_activity_log (
- SCHEDULE_ID NUMERIC(11,0) NOT NULL,
- URL CHARACTER VARYING(4000),
- NOTES CHARACTER VARYING(2000),
- RUN_TIME TIMESTAMP
-);
-
---
--- NAME: CR_TABLE_JOIN; TYPE: TABLE
---
-create table cr_table_join (
- SRC_TABLE_NAME CHARACTER VARYING(30) NOT NULL,
- DEST_TABLE_NAME CHARACTER VARYING(30) NOT NULL,
- JOIN_EXPR CHARACTER VARYING(500) NOT NULL
-);
-
---
--- NAME: CR_TABLE_ROLE; TYPE: TABLE
---
-create table cr_table_role (
- TABLE_NAME CHARACTER VARYING(30) NOT NULL,
- ROLE_ID NUMERIC(11,0) NOT NULL
-);
-
---
--- NAME: CR_TABLE_SOURCE; TYPE: TABLE
---
-create table cr_table_source (
- TABLE_NAME CHARACTER VARYING(30) NOT NULL,
- DISPLAY_NAME CHARACTER VARYING(30) NOT NULL,
- PK_FIELDS CHARACTER VARYING(200),
- WEB_VIEW_ACTION CHARACTER VARYING(50),
- LARGE_DATA_SOURCE_YN CHARACTER VARYING(1) DEFAULT 'N' NOT NULL,
- FILTER_SQL CHARACTER VARYING(4000),
- SOURCE_DB CHARACTER VARYING(50)
-);
-
---
--- NAME: FN_LU_TIMEZONE; TYPE: TABLE
---
-create table fn_lu_timezone (
- TIMEZONE_ID INT(11) NOT NULL,
- TIMEZONE_NAME CHARACTER VARYING(100) NOT NULL,
- TIMEZONE_VALUE CHARACTER VARYING(100) NOT NULL
-);
-
-create table fn_user (
- USER_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
- ORG_ID INT(11),
- MANAGER_ID INT(11),
- FIRST_NAME CHARACTER VARYING(25),
- MIDDLE_NAME CHARACTER VARYING(25),
- LAST_NAME CHARACTER VARYING(25),
- PHONE CHARACTER VARYING(25),
- FAX CHARACTER VARYING(25),
- CELLULAR CHARACTER VARYING(25),
- EMAIL CHARACTER VARYING(50),
- ADDRESS_ID NUMERIC(11,0),
- ALERT_METHOD_CD CHARACTER VARYING(10),
- HRID CHARACTER VARYING(20),
- ORG_USER_ID CHARACTER VARYING(20),
- ORG_CODE CHARACTER VARYING(30),
- LOGIN_ID CHARACTER VARYING(25),
- LOGIN_PWD CHARACTER VARYING(25),
- LAST_LOGIN_DATE TIMESTAMP,
- ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
- CREATED_ID INT(11),
- CREATED_DATE TIMESTAMP DEFAULT NOW(),
- MODIFIED_ID INT(11),
- MODIFIED_DATE TIMESTAMP default now(),
- IS_INTERNAL_YN CHARACTER(1) DEFAULT 'N' NOT NULL,
- ADDRESS_LINE_1 CHARACTER VARYING(100),
- ADDRESS_LINE_2 CHARACTER VARYING(100),
- CITY CHARACTER VARYING(50),
- STATE_CD CHARACTER VARYING(3),
- ZIP_CODE CHARACTER VARYING(11),
- COUNTRY_CD CHARACTER VARYING(3),
- LOCATION_CLLI CHARACTER VARYING(8),
- ORG_MANAGER_USERID CHARACTER VARYING(20),
- COMPANY CHARACTER VARYING(100),
- DEPARTMENT_NAME CHARACTER VARYING(100),
- JOB_TITLE CHARACTER VARYING(100),
- TIMEZONE INT(11),
- DEPARTMENT CHARACTER VARYING(25),
- BUSINESS_UNIT CHARACTER VARYING(25),
- BUSINESS_UNIT_NAME CHARACTER VARYING(100),
- COST_CENTER CHARACTER VARYING(25),
- FIN_LOC_CODE CHARACTER VARYING(10),
- SILO_STATUS CHARACTER VARYING(10)
-);
-
---
--- NAME: FN_ROLE; TYPE: TABLE
---
-create table fn_role (
- ROLE_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
- ROLE_NAME CHARACTER VARYING(50) NOT NULL,
- ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
- PRIORITY NUMERIC(4,0)
-);
-
---
--- NAME: FN_AUDIT_ACTION; TYPE: TABLE
---
-create table fn_audit_action (
- AUDIT_ACTION_ID INTEGER NOT NULL,
- CLASS_NAME CHARACTER VARYING(500) NOT NULL,
- METHOD_NAME CHARACTER VARYING(50) NOT NULL,
- AUDIT_ACTION_CD CHARACTER VARYING(20) NOT NULL,
- AUDIT_ACTION_DESC CHARACTER VARYING(200),
- ACTIVE_YN CHARACTER VARYING(1)
-);
-
---
--- NAME: FN_AUDIT_ACTION_LOG; TYPE: TABLE
---
-create table fn_audit_action_log (
- AUDIT_LOG_ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
- AUDIT_ACTION_CD CHARACTER VARYING(200),
- ACTION_TIME TIMESTAMP,
- USER_ID NUMERIC(11,0),
- CLASS_NAME CHARACTER VARYING(100),
- METHOD_NAME CHARACTER VARYING(50),
- SUCCESS_MSG CHARACTER VARYING(20),
- ERROR_MSG CHARACTER VARYING(500)
-);
-
---
--- NAME: FN_LU_ACTIVITY; TYPE: TABLE
---
-create table fn_lu_activity (
- ACTIVITY_CD CHARACTER VARYING(50) NOT NULL PRIMARY KEY,
- ACTIVITY CHARACTER VARYING(50) NOT NULL
-);
-
---
--- NAME: FN_AUDIT_LOG; TYPE: TABLE
---
-create table fn_audit_log (
- LOG_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
- USER_ID INT(11) NOT NULL,
- ACTIVITY_CD CHARACTER VARYING(50) NOT NULL,
- AUDIT_DATE TIMESTAMP DEFAULT NOW() NOT NULL,
- COMMENTS CHARACTER VARYING(1000),
- AFFECTED_RECORD_ID_BK CHARACTER VARYING(500),
- AFFECTED_RECORD_ID CHARACTER VARYING(4000),
- CONSTRAINT FK_FN_AUDIT_REF_209_FN_USER FOREIGN KEY (USER_ID) REFERENCES FN_USER(USER_ID)
-);
-
---
--- NAME: FN_BROADCAST_MESSAGE; TYPE: TABLE
---
-create table fn_broadcast_message (
- MESSAGE_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
- MESSAGE_TEXT CHARACTER VARYING(1000) NOT NULL,
- MESSAGE_LOCATION_ID NUMERIC(11,0) NOT NULL,
- BROADCAST_START_DATE TIMESTAMP NOT NULL DEFAULT NOW(),
- BROADCAST_END_DATE TIMESTAMP NOT NULL DEFAULT NOW(),
- ACTIVE_YN CHARACTER(1) DEFAULT 'Y' NOT NULL,
- SORT_ORDER NUMERIC(4,0) NOT NULL,
- BROADCAST_SITE_CD CHARACTER VARYING(50)
-);
-
---
--- NAME: FN_CHAT_LOGS; TYPE: TABLE
---
-create table fn_chat_logs (
- CHAT_LOG_ID INTEGER NOT NULL,
- CHAT_ROOM_ID INTEGER,
- USER_ID INTEGER,
- MESSAGE CHARACTER VARYING(1000),
- MESSAGE_DATE_TIME TIMESTAMP
-);
-
---
--- NAME: FN_CHAT_ROOM; TYPE: TABLE
---
-create table fn_chat_room (
- CHAT_ROOM_ID INTEGER NOT NULL,
- NAME CHARACTER VARYING(50) NOT NULL,
- DESCRIPTION CHARACTER VARYING(500),
- OWNER_ID INTEGER,
- CREATED_DATE TIMESTAMP DEFAULT NOW(),
- UPDATED_DATE TIMESTAMP DEFAULT NOW()
-);
-
---
--- NAME: FN_CHAT_USERS; TYPE: TABLE
---
-create table fn_chat_users (
- CHAT_ROOM_ID INTEGER,
- USER_ID INTEGER,
- LAST_ACTIVITY_DATE_TIME TIMESTAMP,
- CHAT_STATUS CHARACTER VARYING(20),
- ID INTEGER NOT NULL
-);
-
---
--- NAME: FN_DATASOURCE; TYPE: TABLE
---
-create table fn_datasource (
- ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
- NAME CHARACTER VARYING(50),
- DRIVER_NAME CHARACTER VARYING(256),
- SERVER CHARACTER VARYING(256),
- PORT INTEGER,
- USER_NAME CHARACTER VARYING(256),
- PASSWORD CHARACTER VARYING(256),
- URL CHARACTER VARYING(256),
- MIN_POOL_SIZE INTEGER,
- MAX_POOL_SIZE INTEGER,
- ADAPTER_ID INTEGER,
- DS_TYPE CHARACTER VARYING(20)
-);
-
---
--- NAME: FN_FUNCTION; TYPE: TABLE
---
-create table fn_function (
- FUNCTION_CD CHARACTER VARYING(30) NOT NULL PRIMARY KEY,
- FUNCTION_NAME CHARACTER VARYING(50) NOT NULL
-);
-
---
--- NAME: FN_LU_ALERT_METHOD; TYPE: TABLE
---
-create table fn_lu_alert_method (
- ALERT_METHOD_CD CHARACTER VARYING(10) NOT NULL,
- ALERT_METHOD CHARACTER VARYING(50) NOT NULL
-);
-
---
--- NAME: FN_LU_BROADCAST_SITE; TYPE: TABLE
---
-create table fn_lu_broadcast_site (
- BROADCAST_SITE_CD CHARACTER VARYING(50) NOT NULL,
- BROADCAST_SITE_DESCR CHARACTER VARYING(100)
-);
---
--- NAME: FN_LU_MENU_SET; TYPE: TABLE
---
-create table fn_lu_menu_set (
- MENU_SET_CD CHARACTER VARYING(10) NOT NULL PRIMARY KEY,
- MENU_SET_NAME CHARACTER VARYING(50) NOT NULL
-);
-
---
--- NAME: FN_LU_PRIORITY; TYPE: TABLE
---
-create table fn_lu_priority (
- PRIORITY_ID NUMERIC(11,0) NOT NULL,
- PRIORITY CHARACTER VARYING(50) NOT NULL,
- ACTIVE_YN CHARACTER(1) NOT NULL,
- SORT_ORDER NUMERIC(5,0)
-);
-
---
--- NAME: FN_LU_ROLE_TYPE; TYPE: TABLE
---
-create table fn_lu_role_type (
- ROLE_TYPE_ID NUMERIC(11,0) NOT NULL,
- ROLE_TYPE CHARACTER VARYING(50) NOT NULL
-);
---
--- NAME: FN_LU_TAB_SET; TYPE: TABLE
---
-create table fn_lu_tab_set (
- TAB_SET_CD CHARACTER VARYING(30) NOT NULL,
- TAB_SET_NAME CHARACTER VARYING(50) NOT NULL
-);
-
---
--- NAME: FN_MENU; TYPE: TABLE
---
-create table fn_menu (
- MENU_ID INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
- LABEL CHARACTER VARYING(100),
- PARENT_ID INT(11),
- SORT_ORDER NUMERIC(4,0),
- ACTION CHARACTER VARYING(200),
- FUNCTION_CD CHARACTER VARYING(30),
- ACTIVE_YN CHARACTER VARYING(1) DEFAULT 'Y' NOT NULL,
- SERVLET CHARACTER VARYING(50),
- QUERY_STRING CHARACTER VARYING(200),
- EXTERNAL_URL CHARACTER VARYING(200),
- TARGET CHARACTER VARYING(25),
- MENU_SET_CD CHARACTER VARYING(10) DEFAULT 'APP',
- SEPARATOR_YN CHARACTER(1) DEFAULT 'N',
- IMAGE_SRC CHARACTER VARYING(100),
- CONSTRAINT FK_FN_MENU_REF_196_FN_MENU FOREIGN KEY (PARENT_ID) REFERENCES FN_MENU(MENU_ID),
- CONSTRAINT FK_FN_MENU_MENU_SET_CD FOREIGN KEY (MENU_SET_CD) REFERENCES FN_LU_MENU_SET(MENU_SET_CD),
- CONSTRAINT FK_FN_MENU_REF_223_FN_FUNCT FOREIGN KEY (FUNCTION_CD) REFERENCES FN_FUNCTION(FUNCTION_CD)
-);
-
---
--- NAME: FN_ORG; TYPE: TABLE
---
-create table fn_org (
- ORG_ID INT(11) NOT NULL,
- ORG_NAME CHARACTER VARYING(50) NOT NULL,
- ACCESS_CD CHARACTER VARYING(10)
-);
-
---
--- NAME: FN_RESTRICTED_URL; TYPE: TABLE
---
-create table fn_restricted_url (
- RESTRICTED_URL CHARACTER VARYING(250) NOT NULL,
- FUNCTION_CD CHARACTER VARYING(30) NOT NULL
-);
-
---
--- NAME: FN_ROLE_COMPOSITE; TYPE: TABLE
---
-create table fn_role_composite (
- PARENT_ROLE_ID INT(11) NOT NULL,
- CHILD_ROLE_ID INT(11) NOT NULL,
- CONSTRAINT FK_FN_ROLE_COMPOSITE_CHILD FOREIGN KEY (CHILD_ROLE_ID) REFERENCES FN_ROLE(ROLE_ID),
- CONSTRAINT FK_FN_ROLE_COMPOSITE_PARENT FOREIGN KEY (PARENT_ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
-);
-
---
--- NAME: FN_ROLE_FUNCTION; TYPE: TABLE
---
-create table fn_role_function (
- ROLE_ID INT(11) NOT NULL,
- FUNCTION_CD CHARACTER VARYING(30) NOT NULL,
- CONSTRAINT FK_FN_ROLE__REF_198_FN_ROLE FOREIGN KEY (ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
-);
-
---
--- NAME: FN_TAB; TYPE: TABLE
---
-create table fn_tab (
- TAB_CD CHARACTER VARYING(30) NOT NULL,
- TAB_NAME CHARACTER VARYING(50) NOT NULL,
- TAB_DESCR CHARACTER VARYING(100),
- ACTION CHARACTER VARYING(100) NOT NULL,
- FUNCTION_CD CHARACTER VARYING(30) NOT NULL,
- ACTIVE_YN CHARACTER(1) NOT NULL,
- SORT_ORDER NUMERIC(11,0) NOT NULL,
- PARENT_TAB_CD CHARACTER VARYING(30),
- TAB_SET_CD CHARACTER VARYING(30)
-);
-
---
--- NAME: FN_TAB_SELECTED; TYPE: TABLE
---
-create table fn_tab_selected (
- SELECTED_TAB_CD CHARACTER VARYING(30) NOT NULL,
- TAB_URI CHARACTER VARYING(40) NOT NULL
-);
-
---
--- NAME: FN_USER_PSEUDO_ROLE; TYPE: TABLE
---
-create table fn_user_pseudo_role (
- PSEUDO_ROLE_ID INT(11) NOT NULL,
- USER_ID INT(11) NOT NULL
-);
-
---
--- NAME: FN_USER_ROLE; TYPE: TABLE
---
-create table fn_user_role (
- USER_ID INT(10) NOT NULL,
- ROLE_ID INT(10) NOT NULL,
- PRIORITY NUMERIC(4,0),
- APP_ID INT(11) DEFAULT 1,
- CONSTRAINT FK_FN_USER__REF_172_FN_USER FOREIGN KEY (USER_ID) REFERENCES FN_USER(USER_ID),
- CONSTRAINT FK_FN_USER__REF_175_FN_ROLE FOREIGN KEY (ROLE_ID) REFERENCES FN_ROLE(ROLE_ID)
-);
---
--- NAME: SCHEMA_INFO; TYPE: TABLE
---
-create table schema_info (
- SCHEMA_ID CHARACTER VARYING(25) NOT NULL,
- SCHEMA_DESC CHARACTER VARYING(75) NOT NULL,
- DATASOURCE_TYPE CHARACTER VARYING(100),
- CONNECTION_URL VARCHAR(200) NOT NULL,
- USER_NAME VARCHAR(45) NOT NULL,
- PASSWORD VARCHAR(45) NULL DEFAULT NULL,
- DRIVER_CLASS VARCHAR(100) NOT NULL,
- MIN_POOL_SIZE INT NOT NULL,
- MAX_POOL_SIZE INT NOT NULL,
- IDLE_CONNECTION_TEST_PERIOD INT NOT NULL
-
-);
-
--- ----------------------------------------------------------
--- NAME: FN_APP; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_app (
- APP_ID int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
- APP_NAME varchar(100) NOT NULL DEFAULT '?',
- APP_IMAGE_URL varchar(256) DEFAULT NULL,
- APP_DESCRIPTION varchar(512) DEFAULT NULL,
- APP_NOTES varchar(4096) DEFAULT NULL,
- APP_URL varchar(256) DEFAULT NULL,
- APP_ALTERNATE_URL varchar(256) DEFAULT NULL,
- APP_REST_ENDPOINT varchar(2000) DEFAULT NULL,
- ML_APP_NAME varchar(50) NOT NULL DEFAULT '?',
- ML_APP_ADMIN_ID varchar(7) NOT NULL DEFAULT '?',
- MOTS_ID int(11) DEFAULT NULL,
- APP_PASSWORD varchar(256) NOT NULL DEFAULT '?',
- OPEN char(1) DEFAULT 'N',
- ENABLED char(1) DEFAULT 'Y',
- THUMBNAIL mediumblob,
- APP_USERNAME varchar(50),
- UEB_KEY VARCHAR(256) DEFAULT NULL,
- UEB_SECRET VARCHAR(256) DEFAULT NULL,
- UEB_TOPIC_NAME VARCHAR(256) DEFAULT NULL
-
-);
-
--- ----------------------------------------------------------
--- NAME: FN_FN_WORKFLOW; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_workflow (
- id mediumint(9) NOT NULL AUTO_INCREMENT,
- name varchar(20) NOT NULL,
- description varchar(500) DEFAULT NULL,
- run_link varchar(300) DEFAULT NULL,
- suspend_link varchar(300) DEFAULT NULL,
- modified_link varchar(300) DEFAULT NULL,
- active_yn varchar(300) DEFAULT NULL,
- created varchar(300) DEFAULT NULL,
- created_by int(11) DEFAULT NULL,
- modified varchar(300) DEFAULT NULL,
- modified_by int(11) DEFAULT NULL,
- workflow_key varchar(50) DEFAULT NULL,
- PRIMARY KEY (id),
- UNIQUE KEY name (name)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_SCHEDULE_WORKFLOWS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_schedule_workflows (
- id_schedule_workflows bigint(25) PRIMARY KEY NOT NULL AUTO_INCREMENT,
- workflow_server_url varchar(45) DEFAULT NULL,
- workflow_key varchar(45) NOT NULL,
- workflow_arguments varchar(45) DEFAULT NULL,
- startDateTimeCron varchar(45) DEFAULT NULL,
- endDateTime TIMESTAMP DEFAULT NOW(),
- start_date_time TIMESTAMP DEFAULT NOW(),
- recurrence varchar(45) DEFAULT NULL
- );
-
--- For demo reporting application add : demo_bar_chart, demo_bar_chart_inter, demo_line_chart, demo_pie_chart and demo_util_chart
--- demo_scatter_chart, demo_scatter_plot
--- ----------------------------------------------------------
--- NAME: DEMO_BAR_CHART; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_bar_chart (
- label varchar(20),
- value numeric(25,15)
- );
-
--- ----------------------------------------------------------
--- NAME: DEMO_BAR_CHART_INTER; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_bar_chart_inter (
- spam_date date,
- num_rpt_sources numeric(10,0),
- num_det_sources numeric(10,0)
- );
-
--- ----------------------------------------------------------
--- NAME: DEMO_LINE_CHART; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_line_chart (
- series varchar(20),
- log_date date,
- data_value numeric(10,5)
- );
-
--- ----------------------------------------------------------
--- NAME: DEMO_PIE_CHART; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_pie_chart (
- legend varchar(20),
- data_value numeric(10,5)
- );
-
--- ----------------------------------------------------------
--- NAME: DEMO_UTIL_CHART; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_util_chart (
- traffic_date date,
- util_perc numeric(10,5)
- );
-
--- ----------------------------------------------------------
--- NAME: DEMO_SCATTER_CHART; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_scatter_chart (
- rainfall numeric(10,2),
- key_value varchar(20),
- measurements numeric(10,2)
-);
-
--- ----------------------------------------------------------
--- NAME: DEMO_SCATTER_PLOT; TYPE: TABLE
--- ----------------------------------------------------------
-create table demo_scatter_plot
-(
- SERIES VARCHAR(20),
- VALUEX numeric(25,15),
- VALUEY numeric(25,15)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_JOB_DETAILS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_job_details (
-SCHED_NAME VARCHAR(120) NOT NULL,
-JOB_NAME VARCHAR(200) NOT NULL,
-JOB_GROUP VARCHAR(200) NOT NULL,
-DESCRIPTION VARCHAR(250) NULL,
-JOB_CLASS_NAME VARCHAR(250) NOT NULL,
-IS_DURABLE VARCHAR(1) NOT NULL,
-IS_NONCONCURRENT VARCHAR(1) NOT NULL,
-IS_UPDATE_DATA VARCHAR(1) NOT NULL,
-REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
-JOB_DATA BLOB NULL,
-PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_triggers (
-SCHED_NAME VARCHAR(120) NOT NULL,
-TRIGGER_NAME VARCHAR(200) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-JOB_NAME VARCHAR(200) NOT NULL,
-JOB_GROUP VARCHAR(200) NOT NULL,
-DESCRIPTION VARCHAR(250) NULL,
-NEXT_FIRE_TIME BIGINT(13) NULL,
-PREV_FIRE_TIME BIGINT(13) NULL,
-PRIORITY INTEGER NULL,
-TRIGGER_STATE VARCHAR(16) NOT NULL,
-TRIGGER_TYPE VARCHAR(8) NOT NULL,
-START_TIME BIGINT(13) NOT NULL,
-END_TIME BIGINT(13) NULL,
-CALENDAR_NAME VARCHAR(200) NULL,
-MISFIRE_INSTR SMALLINT(2) NULL,
-JOB_DATA BLOB NULL,
-PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
-FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
-REFERENCES FN_QZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_SIMPLE_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_simple_triggers (
-SCHED_NAME VARCHAR(120) NOT NULL,
-TRIGGER_NAME VARCHAR(200) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-REPEAT_COUNT BIGINT(7) NOT NULL,
-REPEAT_INTERVAL BIGINT(12) NOT NULL,
-TIMES_TRIGGERED BIGINT(10) NOT NULL,
-PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
-FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_CRON_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_cron_triggers (
-SCHED_NAME VARCHAR(120) NOT NULL,
-TRIGGER_NAME VARCHAR(200) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-CRON_EXPRESSION VARCHAR(120) NOT NULL,
-TIME_ZONE_ID VARCHAR(80),
-PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
-FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_SIMPROP_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_simprop_triggers
- (
- SCHED_NAME VARCHAR(120) NOT NULL,
- TRIGGER_NAME VARCHAR(200) NOT NULL,
- TRIGGER_GROUP VARCHAR(200) NOT NULL,
- STR_PROP_1 VARCHAR(512) NULL,
- STR_PROP_2 VARCHAR(512) NULL,
- STR_PROP_3 VARCHAR(512) NULL,
- INT_PROP_1 INT NULL,
- INT_PROP_2 INT NULL,
- LONG_PROP_1 BIGINT NULL,
- LONG_PROP_2 BIGINT NULL,
- DEC_PROP_1 NUMERIC(13,4) NULL,
- DEC_PROP_2 NUMERIC(13,4) NULL,
- BOOL_PROP_1 VARCHAR(1) NULL,
- BOOL_PROP_2 VARCHAR(1) NULL,
- PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
- FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
- REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_BLOB_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_blob_triggers (
-SCHED_NAME VARCHAR(120) NOT NULL,
-TRIGGER_NAME VARCHAR(200) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-BLOB_DATA BLOB NULL,
-PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
-INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
-FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-REFERENCES FN_QZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_CALENDARS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_calendars (
-SCHED_NAME VARCHAR(120) NOT NULL,
-CALENDAR_NAME VARCHAR(200) NOT NULL,
-CALENDAR BLOB NOT NULL,
-PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_PAUSED_TRIGGER_GRPS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_paused_trigger_grps (
-SCHED_NAME VARCHAR(120) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_FIRED_TRIGGERS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_fired_triggers (
-SCHED_NAME VARCHAR(120) NOT NULL,
-ENTRY_ID VARCHAR(95) NOT NULL,
-TRIGGER_NAME VARCHAR(200) NOT NULL,
-TRIGGER_GROUP VARCHAR(200) NOT NULL,
-INSTANCE_NAME VARCHAR(200) NOT NULL,
-FIRED_TIME BIGINT(13) NOT NULL,
-SCHED_TIME BIGINT(13) NOT NULL,
-PRIORITY INTEGER NOT NULL,
-STATE VARCHAR(16) NOT NULL,
-JOB_NAME VARCHAR(200) NULL,
-JOB_GROUP VARCHAR(200) NULL,
-IS_NONCONCURRENT VARCHAR(1) NULL,
-REQUESTS_RECOVERY VARCHAR(1) NULL,
-PRIMARY KEY (SCHED_NAME,ENTRY_ID)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_SCHEDULER_STATE; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_scheduler_state (
-SCHED_NAME VARCHAR(120) NOT NULL,
-INSTANCE_NAME VARCHAR(200) NOT NULL,
-LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
-CHECKIN_INTERVAL BIGINT(13) NOT NULL,
-PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
-);
-
--- ----------------------------------------------------------
--- NAME: FN_QZ_LOCKS; TYPE: TABLE
--- ----------------------------------------------------------
-create table fn_qz_locks (
-SCHED_NAME VARCHAR(120) NOT NULL,
-LOCK_NAME VARCHAR(40) NOT NULL,
-PRIMARY KEY (SCHED_NAME,LOCK_NAME)
-);
-
---
--- name: rcloudinvocation; type: table
---
-create table rcloudinvocation (
- id varchar(128) not null primary key,
- created timestamp not null,
- userinfo varchar(2048) not null,
- notebookid varchar(128) not null,
- parameters varchar(2048) default null,
- tokenreaddate timestamp null
-);
-
---
--- name: rcloudnotebook; type: table
---
-create table rcloudnotebook (
- notebookname varchar(128) not null primary key,
- notebookid varchar(128) not null
-);
-
---
--- Name: fn_lu_message_location; Type: TABLE
---
-
-CREATE TABLE fn_lu_message_location (
- message_location_id numeric(11,0) NOT NULL,
- message_location_descr character varying(30) NOT NULL
-);
-
--- ------------------ CREATE VIEW SECTION
---
--- NAME: V_URL_ACCESS; TYPE: VIEW
---
-CREATE VIEW v_url_access AS
- SELECT DISTINCT M.ACTION AS URL,
- M.FUNCTION_CD
- FROM FN_MENU M
- WHERE (M.ACTION IS NOT NULL)
-UNION
- SELECT DISTINCT T.ACTION AS URL,
- T.FUNCTION_CD
- FROM FN_TAB T
- WHERE (T.ACTION IS NOT NULL)
-UNION
- SELECT R.RESTRICTED_URL AS URL,
- R.FUNCTION_CD
- FROM FN_RESTRICTED_URL R;
-
--- ------------------ ALTER TABLE ADD CONSTRAINT PRIMARY KEY SECTION
---
--- NAME: CR_FAVORITE_REPORTS_USER_IDREP_ID; TYPE: CONSTRAINT
---
-alter table cr_favorite_reports
- add constraint cr_favorite_reports_user_idrep_id primary key (user_id, rep_id);
---
--- NAME: CR_FOLDER_FOLDER_ID; TYPE: CONSTRAINT
---
-alter table cr_folder
- add constraint cr_folder_folder_id primary key (folder_id);
---
--- NAME: CR_FOLDER_ACCESS_FOLDER_ACCESS_ID; TYPE: CONSTRAINT
---
-alter table cr_folder_access
- add constraint cr_folder_access_folder_access_id primary key (folder_access_id);
---
--- NAME: CR_HIST_USER_MAP_HIST_IDUSER_ID; TYPE: CONSTRAINT
---
-alter table cr_hist_user_map
- add constraint cr_hist_user_map_hist_iduser_id primary key (hist_id, user_id);
---
--- NAME: CR_LU_FILE_TYPE_LOOKUP_ID; TYPE: CONSTRAINT
---
-alter table cr_lu_file_type
- add constraint cr_lu_file_type_lookup_id primary key (lookup_id);
---
--- NAME: CR_RAPTOR_ACTION_IMG_IMAGE_ID; TYPE: CONSTRAINT
---
-alter table cr_raptor_action_img
- add constraint cr_raptor_action_img_image_id primary key (image_id);
---
--- NAME: CR_RAPTOR_PDF_IMG_IMAGE_ID; TYPE: CONSTRAINT
---
-alter table cr_raptor_pdf_img
- add constraint cr_raptor_pdf_img_image_id primary key (image_id);
---
--- NAME: CR_REMOTE_SCHEMA_INFO_SCHEMA_PREFIX; TYPE: CONSTRAINT
---
-alter table cr_remote_schema_info
- add constraint cr_remote_schema_info_schema_prefix primary key (schema_prefix);
---
--- NAME: CR_REPORT_REP_ID; TYPE: CONSTRAINT
---
-alter table cr_report
- add constraint cr_report_rep_id primary key (rep_id);
---
--- NAME: CR_REPORT_ACCESS_REP_IDORDER_NO; TYPE: CONSTRAINT
---
-alter table cr_report_access
- add constraint cr_report_access_rep_idorder_no primary key (rep_id, order_no);
---
--- NAME: CR_REPORT_EMAIL_SENT_LOG_LOG_ID; TYPE: CONSTRAINT
---
-alter table cr_report_email_sent_log
- add constraint cr_report_email_sent_log_log_id primary key (log_id);
---
--- NAME: CR_REPORT_FILE_HISTORY_HIST_ID; TYPE: CONSTRAINT
---
-alter table cr_report_file_history
- add constraint cr_report_file_history_hist_id primary key (hist_id);
---
--- NAME: CR_REPORT_SCHEDULE_SCHEDULE_ID; TYPE: CONSTRAINT
---
-alter table cr_report_schedule
- add constraint cr_report_schedule_schedule_id primary key (schedule_id);
---
--- NAME: CR_REPORT_SCHEDULE_USERS_SCHEDULE_IDREP_IDUSER_IDORDER_NO; TYPE: CONSTRAINT
---
-alter table cr_report_schedule_users
- add constraint cr_report_schedule_users_schedule_idrep_iduser_idorder_no primary key (schedule_id, rep_id, user_id, order_no);
---
--- NAME: CR_REPORT_TEMPLATE_MAP_REPORT_ID; TYPE: CONSTRAINT
---
-alter table cr_report_template_map
- add constraint cr_report_template_map_report_id primary key (report_id);
---
--- NAME: CR_TABLE_ROLE_TABLE_NAMEROLE_ID; TYPE: CONSTRAINT
---
-alter table cr_table_role
- add constraint cr_table_role_table_namerole_id primary key (table_name, role_id);
---
--- NAME: CR_TABLE_SOURCE_TABLE_NAME; TYPE: CONSTRAINT
---
-alter table cr_table_source
- add constraint cr_table_source_table_name primary key (table_name);
---
--- NAME: FN_AUDIT_ACTION_AUDIT_ACTION_ID; TYPE: CONSTRAINT
---
-alter table fn_audit_action
- add constraint fn_audit_action_audit_action_id primary key (audit_action_id);
---
--- NAME: FN_CHAT_LOGS_CHAT_LOG_ID; TYPE: CONSTRAINT
---
-alter table fn_chat_logs
- add constraint fn_chat_logs_chat_log_id primary key (chat_log_id);
---
--- NAME: FN_CHAT_ROOM_CHAT_ROOM_ID; TYPE: CONSTRAINT
---
-alter table fn_chat_room
- add constraint fn_chat_room_chat_room_id primary key (chat_room_id);
---
--- NAME: FN_CHAT_USERS_ID; TYPE: CONSTRAINT
---
-alter table fn_chat_users
- add constraint fn_chat_users_id primary key (id);
---
--- NAME: FN_LU_ALERT_METHOD_ALERT_METHOD_CD; TYPE: CONSTRAINT
---
-alter table fn_lu_alert_method
- add constraint fn_lu_alert_method_alert_method_cd primary key (alert_method_cd);
---
--- NAME: FN_LU_BROADCAST_SITE_BROADCAST_SITE_CD; TYPE: CONSTRAINT
---
-alter table fn_lu_broadcast_site
- add constraint fn_lu_broadcast_site_broadcast_site_cd primary key (broadcast_site_cd);
---
--- NAME: FN_LU_PRIORITY_PRIORITY_ID; TYPE: CONSTRAINT
---
-alter table fn_lu_priority
- add constraint fn_lu_priority_priority_id primary key (priority_id);
---
--- NAME: FN_LU_ROLE_TYPE_ROLE_TYPE_ID; TYPE: CONSTRAINT
---
-alter table fn_lu_role_type
- add constraint fn_lu_role_type_role_type_id primary key (role_type_id);
---
--- NAME: FN_LU_TAB_SET_TAB_SET_CD; TYPE: CONSTRAINT
---
-alter table fn_lu_tab_set
- add constraint fn_lu_tab_set_tab_set_cd primary key (tab_set_cd);
---
--- NAME: FN_LU_TIMEZONE_TIMEZONE_ID; TYPE: CONSTRAINT
---
-alter table fn_lu_timezone
- add constraint fn_lu_timezone_timezone_id primary key (timezone_id);
---
--- NAME: FN_ORG_ORG_ID; TYPE: CONSTRAINT
---
-alter table fn_org
- add constraint fn_org_org_id primary key (org_id);
---
--- NAME: FN_RESTRICTED_URL_RESTRICTED_URLFUNCTION_CD; TYPE: CONSTRAINT
---
-alter table fn_restricted_url
- add constraint fn_restricted_url_restricted_urlfunction_cd primary key (restricted_url, function_cd);
---
--- NAME: FN_ROLE_COMPOSITE_PARENT_ROLE_IDCHILD_ROLE_ID; TYPE: CONSTRAINT
---
-alter table fn_role_composite
- add constraint fn_role_composite_parent_role_idchild_role_id primary key (parent_role_id, child_role_id);
---
--- NAME: FN_ROLE_FUNCTION_ROLE_IDFUNCTION_CD; TYPE: CONSTRAINT
---
-alter table fn_role_function
- add constraint fn_role_function_role_idfunction_cd primary key (role_id, function_cd);
---
--- NAME: FN_TAB_TAB_CD; TYPE: CONSTRAINT
---
-alter table fn_tab
- add constraint fn_tab_tab_cd primary key (tab_cd);
---
--- NAME: FN_TAB_SELECTED_SELECTED_TAB_CDTAB_URI; TYPE: CONSTRAINT
---
-alter table fn_tab_selected
- add constraint fn_tab_selected_selected_tab_cdtab_uri primary key (selected_tab_cd, tab_uri);
---
--- NAME: FN_USER_PSEUDO_ROLE_PSEUDO_ROLE_IDUSER_ID; TYPE: CONSTRAINT
---
-alter table fn_user_pseudo_role
- add constraint fn_user_pseudo_role_pseudo_role_iduser_id primary key (pseudo_role_id, user_id);
---
--- NAME: FN_USER_ROLE_USER_IDROLE_ID; TYPE: CONSTRAINT
---
-alter table fn_user_role
- add constraint fn_user_role_user_idrole_id primary key (user_id, role_id, app_id);
---
--- Name: fn_lu_message_location_MESSAGE_LOCATION_ID; Type: CONSTRAINT
---
-
-ALTER TABLE fn_lu_message_location
- ADD CONSTRAINT fn_lu_message_location_MESSAGE_LOCATION_ID PRIMARY KEY (message_location_id);
-
--- ------------------ CREATE INDEX SECTION
---
--- NAME: CR_REPORT_CREATE_IDPUBLIC_YNTITLE; TYPE: INDEX
---
-create index cr_report_create_idpublic_yntitle using btree on cr_report (create_id, public_yn, title);
---
--- NAME: CR_TABLE_JOIN_DEST_TABLE_NAME; TYPE: INDEX
---
-create index cr_table_join_dest_table_name using btree on cr_table_join (dest_table_name);
---
--- NAME: CR_TABLE_JOIN_SRC_TABLE_NAME; TYPE: INDEX
---
-create index cr_table_join_src_table_name using btree on cr_table_join (src_table_name);
---
--- NAME: FN_AUDIT_LOG_ACTIVITY_CD; TYPE: INDEX
---
-create index fn_audit_log_activity_cd using btree on fn_audit_log (activity_cd);
---
--- NAME: FN_AUDIT_LOG_USER_ID; TYPE: INDEX
---
-create index fn_audit_log_user_id using btree on fn_audit_log (user_id);
---
--- NAME: FN_MENU_FUNCTION_CD; TYPE: INDEX
---
-create index fn_menu_function_cd using btree on fn_menu (function_cd);
---
--- NAME: FN_ORG_ACCESS_CD; TYPE: INDEX
---
-create index fn_org_access_cd using btree on fn_org (access_cd);
---
--- NAME: FN_ROLE_FUNCTION_FUNCTION_CD; TYPE: INDEX
---
-create index fn_role_function_function_cd using btree on fn_role_function (function_cd);
---
--- NAME: FN_ROLE_FUNCTION_ROLE_ID; TYPE: INDEX
---
-create index fn_role_function_role_id using btree on fn_role_function (role_id);
---
--- NAME: FN_USER_ADDRESS_ID; TYPE: INDEX
---
-create index fn_user_address_id using btree on fn_user (address_id);
---
--- NAME: FN_USER_ALERT_METHOD_CD; TYPE: INDEX
---
-create index fn_user_alert_method_cd using btree on fn_user (alert_method_cd);
---
--- NAME: FN_USER_HRID; TYPE: INDEX
---
-create unique index fn_user_hrid using btree on fn_user (hrid);
---
--- NAME: FN_USER_LOGIN_ID; TYPE: INDEX
---
-create unique index fn_user_login_id using btree on fn_user (login_id);
---
--- NAME: FN_USER_ORG_ID; TYPE: INDEX
---
-create index fn_user_org_id using btree on fn_user (org_id);
---
--- NAME: FN_USER_ROLE_ROLE_ID; TYPE: INDEX
---
-create index fn_user_role_role_id using btree on fn_user_role (role_id);
---
--- NAME: FN_USER_ROLE_USER_ID; TYPE: INDEX
---
-create index fn_user_role_user_id using btree on fn_user_role (user_id);
---
--- NAME: FK_FN_USER__REF_178_FN_APP_idx; TYPE: INDEX
---
-create index fk_fn_user__ref_178_fn_app_IDX on fn_user_role (app_id);
-
--- ----------------------------------------------------------
--- NAME: QUARTZ TYPE: INDEXES
--- ----------------------------------------------------------
-create index idx_fn_qz_j_req_recovery on fn_qz_job_details(sched_name,requests_recovery);
-create index idx_fn_qz_j_grp on fn_qz_job_details(sched_name,job_group);
-create index idx_fn_qz_t_j on fn_qz_triggers(sched_name,job_name,job_group);
-create index idx_fn_qz_t_jg on fn_qz_triggers(sched_name,job_group);
-create index idx_fn_qz_t_c on fn_qz_triggers(sched_name,calendar_name);
-create index idx_fn_qz_t_g on fn_qz_triggers(sched_name,trigger_group);
-create index idx_fn_qz_t_state on fn_qz_triggers(sched_name,trigger_state);
-create index idx_fn_qz_t_n_state on fn_qz_triggers(sched_name,trigger_name,trigger_group,trigger_state);
-create index idx_fn_qz_t_n_g_state on fn_qz_triggers(sched_name,trigger_group,trigger_state);
-create index idx_fn_qz_t_next_fire_time on fn_qz_triggers(sched_name,next_fire_time);
-create index idx_fn_qz_t_nft_st on fn_qz_triggers(sched_name,trigger_state,next_fire_time);
-create index idx_fn_qz_t_nft_misfire on fn_qz_triggers(sched_name,misfire_instr,next_fire_time);
-create index idx_fn_qz_t_nft_st_misfire on fn_qz_triggers(sched_name,misfire_instr,next_fire_time,trigger_state);
-create index idx_fn_qz_t_nft_st_misfire_grp on fn_qz_triggers(sched_name,misfire_instr,next_fire_time,trigger_group,trigger_state);
-create index idx_fn_qz_ft_trig_inst_name on fn_qz_fired_triggers(sched_name,instance_name);
-create index idx_fn_qz_ft_inst_job_req_rcvry on fn_qz_fired_triggers(sched_name,instance_name,requests_recovery);
-create index idx_fn_qz_ft_j_g on fn_qz_fired_triggers(sched_name,job_name,job_group);
-create index idx_fn_qz_ft_jg on fn_qz_fired_triggers(sched_name,job_group);
-create index idx_fn_qz_ft_t_g on fn_qz_fired_triggers(sched_name,trigger_name,trigger_group);
-create index idx_fn_qz_ft_tg on fn_qz_fired_triggers(sched_name,trigger_group);
-
--- ------------------ ALTER TABLE ADD CONSTRAINT FOREIGN KEY SECTION
---
--- NAME: FK_FN_AUDIT_REF_205_FN_LU_AC; TYPE: CONSTRAINT
---
-alter table fn_audit_log
- add constraint fk_fn_audit_ref_205_fn_lu_ac foreign key (activity_cd) references fn_lu_activity(activity_cd);
---
--- NAME: FK_FN_ROLE__REF_201_FN_FUNCT; TYPE: CONSTRAINT
---
-alter table fn_role_function
- add constraint fk_fn_role__ref_201_fn_funct foreign key (function_cd) references fn_function(function_cd);
---
--- NAME: FK_FN_USER__REF_178_FN_APP; TYPE: FK CONSTRAINT
---
-alter table fn_user_role
- add constraint fk_fn_user__ref_178_fn_app foreign key (app_id) references fn_app(app_id);
---
--- NAME: FK_CR_REPOR_REF_14707_CR_REPOR; TYPE: FK CONSTRAINT
---
-alter table cr_report_schedule
- add constraint fk_cr_repor_ref_14707_cr_repor foreign key (rep_id) references cr_report(rep_id);
---
--- NAME: FK_CR_REPOR_REF_14716_CR_REPOR; TYPE: FK CONSTRAINT
---
-alter table cr_report_schedule_users
- add constraint fk_cr_repor_ref_14716_cr_repor foreign key (schedule_id) references cr_report_schedule(schedule_id);
---
--- NAME: FK_CR_REPOR_REF_17645_CR_REPOR; TYPE: FK CONSTRAINT
---
-alter table cr_report_log
- add constraint fk_cr_repor_ref_17645_cr_repor foreign key (rep_id) references cr_report(rep_id);
---
--- NAME: FK_CR_REPOR_REF_8550_CR_REPOR; TYPE: FK CONSTRAINT
---
-alter table cr_report_access
- add constraint fk_cr_repor_ref_8550_cr_repor foreign key (rep_id) references cr_report(rep_id);
---
--- NAME: FK_CR_REPORT_REP_ID; TYPE: FK CONSTRAINT
---
-alter table cr_report_email_sent_log
- add constraint fk_cr_report_rep_id foreign key (rep_id) references cr_report(rep_id);
---
--- NAME: FK_CR_TABLE_REF_311_CR_TAB; TYPE: FK CONSTRAINT
---
-alter table cr_table_join
- add constraint fk_cr_table_ref_311_cr_tab foreign key (src_table_name) references cr_table_source(table_name);
---
--- NAME: FK_CR_TABLE_REF_315_CR_TAB; TYPE: FK CONSTRAINT
---
-alter table cr_table_join
- add constraint fk_cr_table_ref_315_cr_tab foreign key (dest_table_name) references cr_table_source(table_name);
---
--- NAME: FK_CR_TABLE_REF_32384_CR_TABLE; TYPE: FK CONSTRAINT
---
-alter table cr_table_role
- add constraint fk_cr_table_ref_32384_cr_table foreign key (table_name) references cr_table_source(table_name);
---
--- NAME: FK_FN_TAB_FUNCTION_CD; TYPE: FK CONSTRAINT
---
-alter table fn_tab
- add constraint fk_fn_tab_function_cd foreign key (function_cd) references fn_function(function_cd);
---
--- NAME: FK_FN_TAB_SELECTED_TAB_CD; TYPE: FK CONSTRAINT
---
-alter table fn_tab_selected
- add constraint fk_fn_tab_selected_tab_cd foreign key (selected_tab_cd) references fn_tab(tab_cd);
---
--- NAME: FK_FN_TAB_SET_CD; TYPE: FK CONSTRAINT
---
-alter table fn_tab
- add constraint fk_fn_tab_set_cd foreign key (tab_set_cd) references fn_lu_tab_set(tab_set_cd);
---
--- NAME: FK_FN_USER_REF_110_FN_ORG; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_fn_user_ref_110_fn_org foreign key (org_id) references fn_org(org_id);
---
--- NAME: FK_FN_USER_REF_123_FN_LU_AL; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_fn_user_ref_123_fn_lu_al foreign key (alert_method_cd) references fn_lu_alert_method(alert_method_cd);
---
--- NAME: FK_FN_USER_REF_197_FN_USER; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_fn_user_ref_197_fn_user foreign key (manager_id) references fn_user(user_id);
---
--- NAME: FK_FN_USER_REF_198_FN_USER; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_fn_user_ref_198_fn_user foreign key (created_id) references fn_user(user_id);
---
--- NAME: FK_FN_USER_REF_199_FN_USER; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_fn_user_ref_199_fn_user foreign key (modified_id) references fn_user(user_id);
---
--- NAME: FK_PARENT_KEY_CR_FOLDER; TYPE: FK CONSTRAINT
---
-alter table cr_folder
- add constraint fk_parent_key_cr_folder foreign key (parent_folder_id) references cr_folder(folder_id);
---
--- NAME: FK_PSEUDO_ROLE_PSEUDO_ROLE_ID; TYPE: FK CONSTRAINT
---
-alter table fn_user_pseudo_role
- add constraint fk_pseudo_role_pseudo_role_id foreign key (pseudo_role_id) references fn_role(role_id);
---
--- NAME: FK_PSEUDO_ROLE_USER_ID; TYPE: FK CONSTRAINT
---
-alter table fn_user_pseudo_role
- add constraint fk_pseudo_role_user_id foreign key (user_id) references fn_user(user_id);
---
--- NAME: FK_RESTRICTED_URL_FUNCTION_CD; TYPE: FK CONSTRAINT
---
-alter table fn_restricted_url
- add constraint fk_restricted_url_function_cd foreign key (function_cd) references fn_function(function_cd);
---
--- NAME: FK_TIMEZONE; TYPE: FK CONSTRAINT
---
-alter table fn_user
- add constraint fk_timezone foreign key (timezone) references fn_lu_timezone(timezone_id);
---
--- NAME: SYS_C0014614; TYPE: FK CONSTRAINT
---
-alter table cr_report_file_history
- add constraint sys_c0014614 foreign key (file_type_id) references cr_lu_file_type(lookup_id);
---
--- NAME: SYS_C0014615; TYPE: FK CONSTRAINT
---
-alter table cr_report_file_history
- add constraint sys_c0014615 foreign key (rep_id) references cr_report(rep_id);
---
--- NAME: SYS_C0014616; TYPE: FK CONSTRAINT
---
-alter table cr_hist_user_map
- add constraint sys_c0014616 foreign key (hist_id) references cr_report_file_history(hist_id);
---
--- NAME: SYS_C0014617; TYPE: FK CONSTRAINT
---
-alter table cr_hist_user_map
- add constraint sys_c0014617 foreign key (user_id) references fn_user(user_id);
-
-commit;
diff --git a/ecomp-sdk/sdk-app/db-scripts/EcompSdkDMLMySql_1610_Complete_OS.sql b/ecomp-sdk/sdk-app/db-scripts/EcompSdkDMLMySql_1610_Complete_OS.sql
deleted file mode 100644
index 64c94516..00000000
--- a/ecomp-sdk/sdk-app/db-scripts/EcompSdkDMLMySql_1610_Complete_OS.sql
+++ /dev/null
@@ -1,2891 +0,0 @@
--- ---------------------------------------------------------------------------------------------------------------
--- This is for the default data for 1610 Version of SDK database for Open Source called ecomp_sdk
-
-USE ecomp_sdk_os;
-
-set foreign_key_checks=1;
-
--- fn_function
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_process','Process List');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('1','test role function');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job','Job Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job_create','Job Create');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_job_designer','Process in Designer view');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_task','Task Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_task_search','Task Search');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_map','Map Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_sample','Sample Pages Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_test','Test Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('login','Login');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_home','Home Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_customer','Customer Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_reports','Reports Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile','Profile Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_admin','Admin Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_feedback','Feedback Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_help','Help Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_logout','Logout Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_doclib','Document Library Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('doclib','Document Library');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('doclib_admin','Document Library Admin');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_notes','Notes Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_ajax','Ajax Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_customer_create','Customer Create');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile_create','Profile Create');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_profile_import','Profile Import');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_tab','Sample Tab Menu');
--- Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_concept','CoNCEPT');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_itracker','iTracker Menu');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('view_reports','View Raptor reports');
-Insert into fn_function (FUNCTION_CD,FUNCTION_NAME) values ('menu_itracker_admin','Itracker Admin/Support menu');
-
--- fn_lu_activity
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_role','add_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_role','remove_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_user_role','add_user_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_user_role','remove_user_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_role_function','add_role_function');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_role_function','remove_role_function');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('add_child_role','add_child_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('remove_child_role','remove_child_role');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('mobile_login','Mobile Login');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('mobile_logout','Mobile Logout');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('login','Login');
-Insert into fn_lu_activity (ACTIVITY_CD,ACTIVITY) values ('logout','Logout');
-
--- fn_lu_alert_method
-Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('PHONE','Phone');
-Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('FAX','Fax');
-Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('PAGER','Pager');
-Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('EMAIL','Email');
-Insert into fn_lu_alert_method (ALERT_METHOD_CD,ALERT_METHOD) values ('SMS','SMS');
-
--- fn_lu_menu_set
-Insert into fn_lu_menu_set (MENU_SET_CD,MENU_SET_NAME) values ('APP','Application Menu');
-
--- fn_lu_priority
-Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (10,'Low','Y',10);
-Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (20,'Normal','Y',20);
-Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (30,'High','Y',30);
-Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (40,'Urgent','Y',40);
-Insert into fn_lu_priority (PRIORITY_ID,PRIORITY,ACTIVE_YN,SORT_ORDER) values (50,'Fatal','Y',50);
-
--- fn_lu_tab_set
-Insert into fn_lu_tab_set (TAB_SET_CD,TAB_SET_NAME) values ('APP','Application Tabs');
-
--- fn_lu_timezone
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (10,'US/Eastern','US/Eastern');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (20,'US/Central','US/Central');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (30,'US/Mountain','US/Mountain');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (40,'US/Arizona','America/Phoenix');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (50,'US/Pacific','US/Pacific');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (60,'US/Alaska','US/Alaska');
-Insert into fn_lu_timezone (TIMEZONE_ID,TIMEZONE_NAME,TIMEZONE_VALUE) values (70,'US/Hawaii','US/Hawaii');
-
--- fn_menu
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (1, 'Root', NULL, 10, NULL, 'menu_home', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', NULL); -- we need even though it's inactive
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (5000, 'Sample Pages', 1, 30, 'sample.htm', 'menu_sample', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-android-apps');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (2, 'Home', 1, 10, 'welcome.htm', 'menu_home', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-home');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (8, 'Reports', 1, 40, 'report.htm', 'menu_reports', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-ios-paper');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (9, 'Profile', 1, 90, 'userProfile', 'menu_profile', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-person');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (10, 'Admin', 1, 110, 'role_list.htm', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-gear-a');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (13, 'Application Logout', 1, 130, 'app_logout.htm', 'menu_logout', 'N', NULL, NULL, NULL, NULL, 'APP', 'N', 'ion-android-exit');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (84, 'All Reports', 8, 50, 'report', 'menu_reports', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/reports.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) values (87, 'Create Reports', 8, 120, 'report_wizard.htm?r_action=report.create', 'menu_reports', 'Y', NULL, 'r_action=report.create', NULL, NULL, 'APP', 'N', NULL);
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) values (88, 'Sample Dashboard', 8, 130, 'report_sample', 'menu_reports', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (92, 'Import User', 9, 30, 'userProfile#/post_search', 'menu_profile_import', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (94, 'Self', 9, 40, 'userProfile#/self_profile', 'menu_profile', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/profile.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (101, 'Roles', 10, 20, 'admin', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/users.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (102, 'Role Functions', 10, 30, 'admin#/role_function_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', NULL);
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (103, 'Broadcast Messages', 10, 50, 'admin#/broadcast_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/bubble.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (105, 'Cache Admin', 10, 40, 'admin#/jcs_admin', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/cache.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (108, 'Usage', 10, 80, 'admin#/usage_list', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/users.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (121, 'Collaboration', 5000, 100, 'collaborate_list.htm', 'menu_sample', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/bubble.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (930, 'Search', 9, 15, 'userProfile', 'menu_admin', 'Y', NULL, NULL, NULL, NULL, 'APP', 'N', '/static/fusion/images/search_profile.png');
-INSERT INTO fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) VALUES (150038,'Notebook',5000,135,'notebook.htm','menu_sample','Y',NULL,NULL,NULL,NULL,'APP','N',NULL);
-
--- fn_restricted_url
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('attachment.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('broadcast.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('file_upload.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('job.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('role.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('role_function.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('test.htm','menu_admin');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('async_test.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('chatWindow.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('contact_list.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('customer_dynamic_list.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('event.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('event_list.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('mobile_welcome.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map.htm','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('template.jsp','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('zkau','menu_home');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('itracker_assign.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('itracker_byassignee.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('itracker_create.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('itracker_update.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('manage_license.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('support_ticket.htm','menu_itracker');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('jbpm_designer.htm','menu_job_create'); -- check
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('jbpm_drools.htm','menu_job_create'); -- check
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('process_job.htm','menu_job_create');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('profile.htm','menu_profile_create');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor2.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_blob_extract.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_email_attachment.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_search.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('report_list.htm','menu_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gauge.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gmap_controller.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('gmap_frame.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map_download.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('map_grid_search.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_animated_map.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map_2.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('sample_map_3.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub1.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub2_link1.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub2_link2.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab2_sub3.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab3.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('tab4.htm','menu_tab');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor.htm','view_reports');
-INSERT INTO fn_restricted_url (restricted_url, function_cd) VALUES ('raptor_blob_extract.htm','view_reports');
-
--- fn_role
-Insert into fn_role (ROLE_ID,ROLE_NAME,ACTIVE_YN,PRIORITY) values (16,'Standard User','Y',5);
-Insert into fn_role (ROLE_ID,ROLE_NAME,ACTIVE_YN,PRIORITY) values (1,'System Administrator','Y',1);
-
--- fn_role_composite
-Insert into fn_role_composite (PARENT_ROLE_ID,CHILD_ROLE_ID) values (1,16);
-
--- fn_role_function
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'doclib');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'doclib_admin');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'login');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_admin');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_ajax');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_customer');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_customer_create');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_feedback');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_help');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_home');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_itracker');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_itracker_admin');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_job');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_job_create');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_logout');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_notes');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_process');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile_create');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_profile_import');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_reports');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_sample');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_tab');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_test');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'login');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_ajax');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_customer');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_customer_create');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_home');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_itracker');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_logout');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_map');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_profile');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_reports');
-Insert into fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_tab');
-
--- fn_tab
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB1_S1','Left Tab 1','Sub - Sub Tab 1 Information','tab2_sub1.htm','menu_tab','Y',10,'TAB2_SUB1','APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB1','Tab 1','Tab 1 Information','tab1.htm','menu_tab','Y',10,null,'APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2','Tab 2','Tab 2 Information','tab2_sub1.htm','menu_tab','Y',20,null,'APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB3','Tab 3','Tab 3 Information','tab3.htm','menu_tab','Y',30,null,'APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB4','Tab 4','Tab 4 Information','tab4.htm','menu_tab','Y',40,null,'APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB1','Sub Tab 1','Sub Tab 1 Information','tab2_sub1.htm','menu_tab','Y',10,'TAB2','APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB2','Sub Tab 2','Sub Tab 2 Information','tab2_sub2.htm','menu_tab','Y',20,'TAB2','APP');
-Insert into fn_tab (TAB_CD,TAB_NAME,TAB_DESCR,ACTION,FUNCTION_CD,ACTIVE_YN,SORT_ORDER,PARENT_TAB_CD,TAB_SET_CD) values ('TAB2_SUB3','Sub Tab 3','Sub Tab 3 Information','tab2_sub3.htm','menu_tab','Y',30,'TAB2','APP');
-
--- fn_tab_selected
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB1','tab1');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub1');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub2');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2','tab2_sub3');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB1','tab2_sub1');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB1_S1','tab2_sub1');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB2','tab2_sub2');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB2_SUB3','tab2_sub3');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB3','tab3');
-Insert into fn_tab_selected (SELECTED_TAB_CD,TAB_URI) values ('TAB4','tab4');
-
--- fn_user
-Insert into fn_user (USER_ID,ORG_ID,MANAGER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,PHONE,FAX,CELLULAR,EMAIL,ADDRESS_ID,ALERT_METHOD_CD,HRID,ORG_USER_ID,ORG_CODE,LOGIN_ID,LOGIN_PWD,LAST_LOGIN_DATE,ACTIVE_YN,CREATED_ID,CREATED_DATE,MODIFIED_ID,MODIFIED_DATE,IS_INTERNAL_YN,ADDRESS_LINE_1,ADDRESS_LINE_2,CITY,STATE_CD,ZIP_CODE,COUNTRY_CD,LOCATION_CLLI,ORG_MANAGER_USERID,COMPANY,DEPARTMENT_NAME,JOB_TITLE,TIMEZONE,DEPARTMENT,BUSINESS_UNIT,BUSINESS_UNIT_NAME,COST_CENTER,FIN_LOC_CODE,SILO_STATUS) values (1,null,null,'Demo',null,'User',null,null,null,'demo@email.com',null,null,null,'demo',null,'demo','Kp8bJ4SXszM0WXlhak3eHlcse',str_to_date('24-OCT-16','%d-%M-%Y'),'Y',null,str_to_date('17-OCT-16','%d-%M-%Y'),1,str_to_date('24-OCT-16','%d-%M-%Y'),'N',null,null,null,'NJ',null,'US',null,null,null,null,null,10,null,null,null,null,null,null);
-
--- cr_raptor_action_img
-Insert into cr_raptor_action_img (IMAGE_ID, IMAGE_LOC) Values ('DELETE', '/static/fusion/raptor/img/deleteicon.gif');
-Insert into cr_raptor_action_img (IMAGE_ID, IMAGE_LOC) Values ('CALENDAR', '/static/fusion/raptor/img/Calendar-16x16.png');
-
--- fn_app
-Insert into fn_app (APP_ID,APP_NAME,APP_IMAGE_URL,APP_DESCRIPTION,APP_NOTES,APP_URL,APP_ALTERNATE_URL,APP_REST_ENDPOINT,ML_APP_NAME,ML_APP_ADMIN_ID,MOTS_ID,APP_PASSWORD,OPEN,ENABLED,THUMBNAIL,APP_USERNAME,UEB_KEY,UEB_SECRET,UEB_TOPIC_NAME) VALUES (1,'Default',null,'Some Default Description','Some Default Note',null,null,null,'ECPP','?','1','okYTaDrhzibcbGVq5mjkVQ==','N','N',null,'Default',null,null,'ECOMP-PORTAL-INBOX');
-
--- fn_user_role
-Insert into fn_user_role (USER_ID,ROLE_ID,PRIORITY,APP_ID) values (1,1,null,1);
-
--- DEMO_BAR_CHART
-Insert into demo_bar_chart (label, value) values ('A', 29.765957771107);
-Insert into demo_bar_chart (label, value) values ('B', 0);
-Insert into demo_bar_chart (label, value) values ('C', 32.807804682612);
-Insert into demo_bar_chart (label, value) values ('D', 196.45946739256);
-Insert into demo_bar_chart (label, value) values ('E', 0.19434030906893);
-Insert into demo_bar_chart (label, value) values ('F', 98.079782601442);
-Insert into demo_bar_chart (label, value) values ('G', 13.925743130903);
-Insert into demo_bar_chart (label, value) values ('H', 5.1387322875705);
-
--- DEMO_BAR_CHART_INTER
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('6-Mar-13','%e-%b-%y'), 198, 220);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('5-Mar-13','%e-%b-%y'), 198, 220);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('4-Mar-13','%e-%b-%y'), 238, 235);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('3-Mar-13','%e-%b-%y'), 238, 235);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('2-Mar-13','%e-%b-%y'), 256, 275);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('1-Mar-13','%e-%b-%y'), 239, 260);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('28-Feb-13','%e-%b-%y'), 247, 255);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('27-Feb-13','%e-%b-%y'), 252, 265);
-Insert into demo_bar_chart_inter (spam_date, num_rpt_sources, num_det_sources) values (STR_TO_DATE('26-Feb-13','%e-%b-%y'), 198, 220);
-
--- DEMO_LINE_CHART
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-May-12','%e-%b-%y'),582.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Apr-12','%e-%b-%y'),583.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Apr-12','%e-%b-%y'),603);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Apr-12','%e-%b-%y'),607.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Apr-12','%e-%b-%y'),610);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Apr-12','%e-%b-%y'),560.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Apr-12','%e-%b-%y'),571.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Apr-12','%e-%b-%y'),572.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Apr-12','%e-%b-%y'),587.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Apr-12','%e-%b-%y'),608.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Apr-12','%e-%b-%y'),609.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Apr-12','%e-%b-%y'),580.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Apr-12','%e-%b-%y'),605.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Apr-12','%e-%b-%y'),622.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Apr-12','%e-%b-%y'),626.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Apr-12','%e-%b-%y'),628.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Apr-12','%e-%b-%y'),636.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Apr-12','%e-%b-%y'),633.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Apr-12','%e-%b-%y'),624.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-12','%e-%b-%y'),629.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Apr-12','%e-%b-%y'),618.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-12','%e-%b-%y'),599.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Mar-12','%e-%b-%y'),609.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Mar-12','%e-%b-%y'),617.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Mar-12','%e-%b-%y'),614.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-12','%e-%b-%y'),606.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-12','%e-%b-%y'),596.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Mar-12','%e-%b-%y'),599.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Mar-12','%e-%b-%y'),602.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Mar-12','%e-%b-%y'),605.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-12','%e-%b-%y'),601.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-12','%e-%b-%y'),585.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Mar-12','%e-%b-%y'),585.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Mar-12','%e-%b-%y'),589.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Mar-12','%e-%b-%y'),568.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-12','%e-%b-%y'),552);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-12','%e-%b-%y'),545.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Mar-12','%e-%b-%y'),541.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Mar-12','%e-%b-%y'),530.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Mar-12','%e-%b-%y'),530.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Mar-12','%e-%b-%y'),533.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-12','%e-%b-%y'),545.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Mar-12','%e-%b-%y'),544.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Feb-12','%e-%b-%y'),542.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Feb-12','%e-%b-%y'),535.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Feb-12','%e-%b-%y'),525.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Feb-12','%e-%b-%y'),522.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Feb-12','%e-%b-%y'),516.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Feb-12','%e-%b-%y'),513.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Feb-12','%e-%b-%y'),514.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-12','%e-%b-%y'),502.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-12','%e-%b-%y'),502.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-12','%e-%b-%y'),497.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Feb-12','%e-%b-%y'),509.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Feb-12','%e-%b-%y'),502.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-12','%e-%b-%y'),493.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-12','%e-%b-%y'),493.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-12','%e-%b-%y'),476.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Feb-12','%e-%b-%y'),468.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Feb-12','%e-%b-%y'),463.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-12','%e-%b-%y'),459.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-12','%e-%b-%y'),455.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-12','%e-%b-%y'),456.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jan-12','%e-%b-%y'),456.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jan-12','%e-%b-%y'),453.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-12','%e-%b-%y'),447.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-12','%e-%b-%y'),444.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-12','%e-%b-%y'),446.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jan-12','%e-%b-%y'),420.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jan-12','%e-%b-%y'),427.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-12','%e-%b-%y'),420.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-12','%e-%b-%y'),427.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-12','%e-%b-%y'),429.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jan-12','%e-%b-%y'),424.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jan-12','%e-%b-%y'),419.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jan-12','%e-%b-%y'),421.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jan-12','%e-%b-%y'),422.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jan-12','%e-%b-%y'),423.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Jan-12','%e-%b-%y'),421.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jan-12','%e-%b-%y'),422.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jan-12','%e-%b-%y'),418.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jan-12','%e-%b-%y'),413.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jan-12','%e-%b-%y'),411.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-11','%e-%b-%y'),405);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Dec-11','%e-%b-%y'),405.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Dec-11','%e-%b-%y'),402.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Dec-11','%e-%b-%y'),406.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Dec-11','%e-%b-%y'),403.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Dec-11','%e-%b-%y'),398.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Dec-11','%e-%b-%y'),396.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Dec-11','%e-%b-%y'),395.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Dec-11','%e-%b-%y'),382.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Dec-11','%e-%b-%y'),381.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Dec-11','%e-%b-%y'),378.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Dec-11','%e-%b-%y'),380.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Dec-11','%e-%b-%y'),388.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Dec-11','%e-%b-%y'),391.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Dec-11','%e-%b-%y'),393.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Dec-11','%e-%b-%y'),390.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Dec-11','%e-%b-%y'),389.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Dec-11','%e-%b-%y'),390.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Dec-11','%e-%b-%y'),393.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Dec-11','%e-%b-%y'),389.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Dec-11','%e-%b-%y'),387.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Nov-11','%e-%b-%y'),382.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Nov-11','%e-%b-%y'),373.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Nov-11','%e-%b-%y'),376.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Nov-11','%e-%b-%y'),363.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Nov-11','%e-%b-%y'),366.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Nov-11','%e-%b-%y'),376.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Nov-11','%e-%b-%y'),369.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-11','%e-%b-%y'),374.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Nov-11','%e-%b-%y'),377.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Nov-11','%e-%b-%y'),384.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Nov-11','%e-%b-%y'),388.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Nov-11','%e-%b-%y'),379.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Nov-11','%e-%b-%y'),384.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-11','%e-%b-%y'),385.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Nov-11','%e-%b-%y'),395.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Nov-11','%e-%b-%y'),406.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Nov-11','%e-%b-%y'),399.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-11','%e-%b-%y'),400.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Nov-11','%e-%b-%y'),403.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Nov-11','%e-%b-%y'),397.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Nov-11','%e-%b-%y'),396.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Oct-11','%e-%b-%y'),404.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Oct-11','%e-%b-%y'),404.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-11','%e-%b-%y'),404.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Oct-11','%e-%b-%y'),400.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Oct-11','%e-%b-%y'),397.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Oct-11','%e-%b-%y'),405.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-11','%e-%b-%y'),392.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Oct-11','%e-%b-%y'),395.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Oct-11','%e-%b-%y'),398.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Oct-11','%e-%b-%y'),422.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Oct-11','%e-%b-%y'),419.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Oct-11','%e-%b-%y'),422);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-11','%e-%b-%y'),408.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Oct-11','%e-%b-%y'),402.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Oct-11','%e-%b-%y'),400.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Oct-11','%e-%b-%y'),388.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-11','%e-%b-%y'),369.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Oct-11','%e-%b-%y'),377.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Oct-11','%e-%b-%y'),378.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Oct-11','%e-%b-%y'),372.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Oct-11','%e-%b-%y'),374.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Sep-11','%e-%b-%y'),381.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-11','%e-%b-%y'),390.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Sep-11','%e-%b-%y'),397.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Sep-11','%e-%b-%y'),399.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Sep-11','%e-%b-%y'),403.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-11','%e-%b-%y'),404.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Sep-11','%e-%b-%y'),401.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Sep-11','%e-%b-%y'),412.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Sep-11','%e-%b-%y'),413.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Sep-11','%e-%b-%y'),411.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Sep-11','%e-%b-%y'),400.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-11','%e-%b-%y'),392.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Sep-11','%e-%b-%y'),389.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Sep-11','%e-%b-%y'),384.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Sep-11','%e-%b-%y'),379.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-11','%e-%b-%y'),377.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Sep-11','%e-%b-%y'),384.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Sep-11','%e-%b-%y'),383.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Sep-11','%e-%b-%y'),379.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-11','%e-%b-%y'),374.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Sep-11','%e-%b-%y'),381.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-11','%e-%b-%y'),384.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Aug-11','%e-%b-%y'),389.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Aug-11','%e-%b-%y'),389.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Aug-11','%e-%b-%y'),383.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-11','%e-%b-%y'),373.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Aug-11','%e-%b-%y'),376.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Aug-11','%e-%b-%y'),373.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Aug-11','%e-%b-%y'),356.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-11','%e-%b-%y'),356.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Aug-11','%e-%b-%y'),366.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-11','%e-%b-%y'),380.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Aug-11','%e-%b-%y'),380.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Aug-11','%e-%b-%y'),383.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Aug-11','%e-%b-%y'),376.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-11','%e-%b-%y'),373.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Aug-11','%e-%b-%y'),363.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Aug-11','%e-%b-%y'),374.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Aug-11','%e-%b-%y'),353.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-11','%e-%b-%y'),373.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Aug-11','%e-%b-%y'),377.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Aug-11','%e-%b-%y'),392.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Aug-11','%e-%b-%y'),388.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Aug-11','%e-%b-%y'),396.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-11','%e-%b-%y'),390.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-11','%e-%b-%y'),391.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jul-11','%e-%b-%y'),392.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jul-11','%e-%b-%y'),403.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jul-11','%e-%b-%y'),398.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-11','%e-%b-%y'),393.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-11','%e-%b-%y'),387.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jul-11','%e-%b-%y'),386.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Jul-11','%e-%b-%y'),376.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jul-11','%e-%b-%y'),373.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Jul-11','%e-%b-%y'),364.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-11','%e-%b-%y'),357.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Jul-11','%e-%b-%y'),358.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jul-11','%e-%b-%y'),353.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jul-11','%e-%b-%y'),354);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-11','%e-%b-%y'),359.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Jul-11','%e-%b-%y'),357.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jul-11','%e-%b-%y'),351.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Jul-11','%e-%b-%y'),349.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-11','%e-%b-%y'),343.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jun-11','%e-%b-%y'),335.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jun-11','%e-%b-%y'),334.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Jun-11','%e-%b-%y'),335.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jun-11','%e-%b-%y'),332.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jun-11','%e-%b-%y'),326.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-11','%e-%b-%y'),331.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jun-11','%e-%b-%y'),322.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jun-11','%e-%b-%y'),325.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jun-11','%e-%b-%y'),315.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-11','%e-%b-%y'),320.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jun-11','%e-%b-%y'),325.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jun-11','%e-%b-%y'),326.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jun-11','%e-%b-%y'),332.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jun-11','%e-%b-%y'),326.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jun-11','%e-%b-%y'),325.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-11','%e-%b-%y'),331.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jun-11','%e-%b-%y'),332.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jun-11','%e-%b-%y'),332.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jun-11','%e-%b-%y'),338.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-11','%e-%b-%y'),343.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jun-11','%e-%b-%y'),346.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jun-11','%e-%b-%y'),345.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-May-11','%e-%b-%y'),347.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-May-11','%e-%b-%y'),337.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-May-11','%e-%b-%y'),335);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-May-11','%e-%b-%y'),336.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-May-11','%e-%b-%y'),332.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-May-11','%e-%b-%y'),334.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-May-11','%e-%b-%y'),335.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-11','%e-%b-%y'),340.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-11','%e-%b-%y'),339.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-May-11','%e-%b-%y'),336.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-May-11','%e-%b-%y'),333.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-11','%e-%b-%y'),340.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-May-11','%e-%b-%y'),346.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-11','%e-%b-%y'),347.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-May-11','%e-%b-%y'),349.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-May-11','%e-%b-%y'),347.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-May-11','%e-%b-%y'),346.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-11','%e-%b-%y'),346.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-May-11','%e-%b-%y'),349.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-May-11','%e-%b-%y'),348.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-May-11','%e-%b-%y'),346.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-11','%e-%b-%y'),350.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Apr-11','%e-%b-%y'),346.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-11','%e-%b-%y'),350.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Apr-11','%e-%b-%y'),350.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Apr-11','%e-%b-%y'),353.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Apr-11','%e-%b-%y'),350.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Apr-11','%e-%b-%y'),342.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Apr-11','%e-%b-%y'),337.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Apr-11','%e-%b-%y'),331.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Apr-11','%e-%b-%y'),327.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Apr-11','%e-%b-%y'),332.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Apr-11','%e-%b-%y'),336.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Apr-11','%e-%b-%y'),332.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Apr-11','%e-%b-%y'),330.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Apr-11','%e-%b-%y'),335.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Apr-11','%e-%b-%y'),338.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Apr-11','%e-%b-%y'),338.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Apr-11','%e-%b-%y'),338.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Apr-11','%e-%b-%y'),341.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Apr-11','%e-%b-%y'),344.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Mar-11','%e-%b-%y'),348.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Mar-11','%e-%b-%y'),348.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Mar-11','%e-%b-%y'),350.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Mar-11','%e-%b-%y'),350.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Mar-11','%e-%b-%y'),351.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Mar-11','%e-%b-%y'),344.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Mar-11','%e-%b-%y'),339.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Mar-11','%e-%b-%y'),341.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Mar-11','%e-%b-%y'),339.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Mar-11','%e-%b-%y'),330.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Mar-11','%e-%b-%y'),334.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Mar-11','%e-%b-%y'),330.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Mar-11','%e-%b-%y'),345.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Mar-11','%e-%b-%y'),353.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Mar-11','%e-%b-%y'),351.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Mar-11','%e-%b-%y'),346.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Mar-11','%e-%b-%y'),352.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Mar-11','%e-%b-%y'),355.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Mar-11','%e-%b-%y'),355.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Mar-11','%e-%b-%y'),360);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Mar-11','%e-%b-%y'),359.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Mar-11','%e-%b-%y'),352.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Mar-11','%e-%b-%y'),349.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Feb-11','%e-%b-%y'),353.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Feb-11','%e-%b-%y'),348.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Feb-11','%e-%b-%y'),342.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Feb-11','%e-%b-%y'),342.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Feb-11','%e-%b-%y'),338.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-11','%e-%b-%y'),350.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-11','%e-%b-%y'),358.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-11','%e-%b-%y'),363.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-11','%e-%b-%y'),359.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Feb-11','%e-%b-%y'),359.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Feb-11','%e-%b-%y'),356.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-11','%e-%b-%y'),354.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-11','%e-%b-%y'),358.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-11','%e-%b-%y'),355.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Feb-11','%e-%b-%y'),351.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Feb-11','%e-%b-%y'),346.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-11','%e-%b-%y'),343.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-11','%e-%b-%y'),344.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-11','%e-%b-%y'),345.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jan-11','%e-%b-%y'),339.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Jan-11','%e-%b-%y'),336.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-11','%e-%b-%y'),343.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-11','%e-%b-%y'),343.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-11','%e-%b-%y'),341.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jan-11','%e-%b-%y'),337.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jan-11','%e-%b-%y'),326.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-11','%e-%b-%y'),332.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-11','%e-%b-%y'),338.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-11','%e-%b-%y'),340.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jan-11','%e-%b-%y'),348.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jan-11','%e-%b-%y'),345.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jan-11','%e-%b-%y'),344.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jan-11','%e-%b-%y'),341.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jan-11','%e-%b-%y'),342.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jan-11','%e-%b-%y'),336.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jan-11','%e-%b-%y'),333.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jan-11','%e-%b-%y'),334);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jan-11','%e-%b-%y'),331.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jan-11','%e-%b-%y'),329.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Dec-10','%e-%b-%y'),322.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Dec-10','%e-%b-%y'),323.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Dec-10','%e-%b-%y'),325.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Dec-10','%e-%b-%y'),325.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Dec-10','%e-%b-%y'),324.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-10','%e-%b-%y'),323.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-10','%e-%b-%y'),325.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Dec-10','%e-%b-%y'),324.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Dec-10','%e-%b-%y'),322.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Dec-10','%e-%b-%y'),320.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-10','%e-%b-%y'),321.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-10','%e-%b-%y'),320.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-10','%e-%b-%y'),320.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Dec-10','%e-%b-%y'),321.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-10','%e-%b-%y'),320.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Dec-10','%e-%b-%y'),319.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-10','%e-%b-%y'),321.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-10','%e-%b-%y'),318.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Dec-10','%e-%b-%y'),320.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Dec-10','%e-%b-%y'),317.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-10','%e-%b-%y'),318.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Dec-10','%e-%b-%y'),316.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-10','%e-%b-%y'),311.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Nov-10','%e-%b-%y'),316.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-10','%e-%b-%y'),315);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Nov-10','%e-%b-%y'),314.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Nov-10','%e-%b-%y'),308.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Nov-10','%e-%b-%y'),313.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Nov-10','%e-%b-%y'),306.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Nov-10','%e-%b-%y'),308.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Nov-10','%e-%b-%y'),300.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Nov-10','%e-%b-%y'),301.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Nov-10','%e-%b-%y'),307.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Nov-10','%e-%b-%y'),308.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Nov-10','%e-%b-%y'),316.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Nov-10','%e-%b-%y'),318.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Nov-10','%e-%b-%y'),316.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Nov-10','%e-%b-%y'),318.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Nov-10','%e-%b-%y'),317.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Nov-10','%e-%b-%y'),318.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Nov-10','%e-%b-%y'),312.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Nov-10','%e-%b-%y'),309.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Nov-10','%e-%b-%y'),304.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Oct-10','%e-%b-%y'),300.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Oct-10','%e-%b-%y'),305.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Oct-10','%e-%b-%y'),307.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Oct-10','%e-%b-%y'),308.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Oct-10','%e-%b-%y'),308.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Oct-10','%e-%b-%y'),307.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Oct-10','%e-%b-%y'),309.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Oct-10','%e-%b-%y'),310.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Oct-10','%e-%b-%y'),309.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Oct-10','%e-%b-%y'),318);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Oct-10','%e-%b-%y'),314.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Oct-10','%e-%b-%y'),302.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Oct-10','%e-%b-%y'),300.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Oct-10','%e-%b-%y'),298.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Oct-10','%e-%b-%y'),295.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Oct-10','%e-%b-%y'),294.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Oct-10','%e-%b-%y'),289.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Oct-10','%e-%b-%y'),289.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Oct-10','%e-%b-%y'),288.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Oct-10','%e-%b-%y'),278.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Oct-10','%e-%b-%y'),282.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Sep-10','%e-%b-%y'),283.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Sep-10','%e-%b-%y'),287.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Sep-10','%e-%b-%y'),286.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Sep-10','%e-%b-%y'),291.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Sep-10','%e-%b-%y'),292.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Sep-10','%e-%b-%y'),288.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Sep-10','%e-%b-%y'),287.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Sep-10','%e-%b-%y'),283.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Sep-10','%e-%b-%y'),283.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Sep-10','%e-%b-%y'),275.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Sep-10','%e-%b-%y'),276.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Sep-10','%e-%b-%y'),270.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Sep-10','%e-%b-%y'),268.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Sep-10','%e-%b-%y'),267.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Sep-10','%e-%b-%y'),263.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Sep-10','%e-%b-%y'),263.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Sep-10','%e-%b-%y'),262.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Sep-10','%e-%b-%y'),257.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Sep-10','%e-%b-%y'),258.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Sep-10','%e-%b-%y'),258.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-10','%e-%b-%y'),252.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Sep-10','%e-%b-%y'),250.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-10','%e-%b-%y'),243.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Aug-10','%e-%b-%y'),242.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-10','%e-%b-%y'),241.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-10','%e-%b-%y'),240.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-10','%e-%b-%y'),242.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Aug-10','%e-%b-%y'),239.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Aug-10','%e-%b-%y'),245.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Aug-10','%e-%b-%y'),249.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-10','%e-%b-%y'),249.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-10','%e-%b-%y'),253.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-10','%e-%b-%y'),251.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Aug-10','%e-%b-%y'),247.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-10','%e-%b-%y'),249.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Aug-10','%e-%b-%y'),251.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-10','%e-%b-%y'),250.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Aug-10','%e-%b-%y'),259.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Aug-10','%e-%b-%y'),261.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Aug-10','%e-%b-%y'),260.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-10','%e-%b-%y'),261.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Aug-10','%e-%b-%y'),262.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Aug-10','%e-%b-%y'),261.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Aug-10','%e-%b-%y'),261.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jul-10','%e-%b-%y'),257.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-10','%e-%b-%y'),258.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-10','%e-%b-%y'),260.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Jul-10','%e-%b-%y'),264.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jul-10','%e-%b-%y'),259.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jul-10','%e-%b-%y'),259.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-10','%e-%b-%y'),259.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-10','%e-%b-%y'),254.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jul-10','%e-%b-%y'),251.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Jul-10','%e-%b-%y'),245.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jul-10','%e-%b-%y'),249.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jul-10','%e-%b-%y'),251.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-10','%e-%b-%y'),252.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Jul-10','%e-%b-%y'),251.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jul-10','%e-%b-%y'),257.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Jul-10','%e-%b-%y'),259.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-10','%e-%b-%y'),258.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jul-10','%e-%b-%y'),258.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jul-10','%e-%b-%y'),248.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Jul-10','%e-%b-%y'),246.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jul-10','%e-%b-%y'),246.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Jul-10','%e-%b-%y'),248.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jun-10','%e-%b-%y'),251.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jun-10','%e-%b-%y'),256.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jun-10','%e-%b-%y'),268.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Jun-10','%e-%b-%y'),266.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jun-10','%e-%b-%y'),269);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Jun-10','%e-%b-%y'),270.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jun-10','%e-%b-%y'),273.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jun-10','%e-%b-%y'),270.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jun-10','%e-%b-%y'),274.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Jun-10','%e-%b-%y'),271.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jun-10','%e-%b-%y'),267.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Jun-10','%e-%b-%y'),259.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jun-10','%e-%b-%y'),254.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jun-10','%e-%b-%y'),253.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jun-10','%e-%b-%y'),250.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Jun-10','%e-%b-%y'),243.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jun-10','%e-%b-%y'),249.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Jun-10','%e-%b-%y'),250.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jun-10','%e-%b-%y'),255.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jun-10','%e-%b-%y'),263.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jun-10','%e-%b-%y'),263.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Jun-10','%e-%b-%y'),260.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-May-10','%e-%b-%y'),256.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-May-10','%e-%b-%y'),256.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-May-10','%e-%b-%y'),253.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-May-10','%e-%b-%y'),244.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-May-10','%e-%b-%y'),245.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-May-10','%e-%b-%y'),246.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-10','%e-%b-%y'),242.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-May-10','%e-%b-%y'),237.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-10','%e-%b-%y'),248.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-10','%e-%b-%y'),252.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-May-10','%e-%b-%y'),254.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-10','%e-%b-%y'),253.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-10','%e-%b-%y'),258.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-May-10','%e-%b-%y'),262.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-10','%e-%b-%y'),256.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-May-10','%e-%b-%y'),253.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-10','%e-%b-%y'),235.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-10','%e-%b-%y'),246.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-10','%e-%b-%y'),255.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-May-10','%e-%b-%y'),258.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-May-10','%e-%b-%y'),266.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Apr-10','%e-%b-%y'),261.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-10','%e-%b-%y'),268.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-10','%e-%b-%y'),261.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-10','%e-%b-%y'),262.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Apr-10','%e-%b-%y'),269.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-10','%e-%b-%y'),270.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Apr-10','%e-%b-%y'),266.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-10','%e-%b-%y'),259.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Apr-10','%e-%b-%y'),244.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Apr-10','%e-%b-%y'),247.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Apr-10','%e-%b-%y'),247.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-10','%e-%b-%y'),248.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Apr-10','%e-%b-%y'),245.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Apr-10','%e-%b-%y'),242.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Apr-10','%e-%b-%y'),242.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-10','%e-%b-%y'),241.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Apr-10','%e-%b-%y'),239.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-10','%e-%b-%y'),240.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Apr-10','%e-%b-%y'),239.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Apr-10','%e-%b-%y'),238.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-10','%e-%b-%y'),235.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-10','%e-%b-%y'),235.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('31-Mar-10','%e-%b-%y'),235);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-10','%e-%b-%y'),235.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Mar-10','%e-%b-%y'),232.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-10','%e-%b-%y'),230.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-10','%e-%b-%y'),226.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-10','%e-%b-%y'),229.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-10','%e-%b-%y'),228.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Mar-10','%e-%b-%y'),224.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-10','%e-%b-%y'),222.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Mar-10','%e-%b-%y'),224.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Mar-10','%e-%b-%y'),224.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-10','%e-%b-%y'),224.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('15-Mar-10','%e-%b-%y'),223.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-10','%e-%b-%y'),226.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Mar-10','%e-%b-%y'),225.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Mar-10','%e-%b-%y'),224.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-10','%e-%b-%y'),223.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Mar-10','%e-%b-%y'),219.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Mar-10','%e-%b-%y'),218.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Mar-10','%e-%b-%y'),210.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Mar-10','%e-%b-%y'),209.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-10','%e-%b-%y'),208.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Mar-10','%e-%b-%y'),208.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-10','%e-%b-%y'),204.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Feb-10','%e-%b-%y'),202);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Feb-10','%e-%b-%y'),200.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Feb-10','%e-%b-%y'),197.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Feb-10','%e-%b-%y'),200.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-10','%e-%b-%y'),201.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-10','%e-%b-%y'),202.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-10','%e-%b-%y'),202.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Feb-10','%e-%b-%y'),203.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Feb-10','%e-%b-%y'),200.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Feb-10','%e-%b-%y'),200.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Feb-10','%e-%b-%y'),198.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Feb-10','%e-%b-%y'),195.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Feb-10','%e-%b-%y'),196.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Feb-10','%e-%b-%y'),194.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Feb-10','%e-%b-%y'),195.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Feb-10','%e-%b-%y'),192.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Feb-10','%e-%b-%y'),199.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Feb-10','%e-%b-%y'),195.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Feb-10','%e-%b-%y'),194.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jan-10','%e-%b-%y'),192.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Jan-10','%e-%b-%y'),199.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jan-10','%e-%b-%y'),207.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jan-10','%e-%b-%y'),205.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jan-10','%e-%b-%y'),203.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Jan-10','%e-%b-%y'),197.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jan-10','%e-%b-%y'),208.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jan-10','%e-%b-%y'),211.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jan-10','%e-%b-%y'),215.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-10','%e-%b-%y'),205.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-10','%e-%b-%y'),205.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Jan-10','%e-%b-%y'),209.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jan-10','%e-%b-%y'),210.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jan-10','%e-%b-%y'),207.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jan-10','%e-%b-%y'),210.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jan-10','%e-%b-%y'),211.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-10','%e-%b-%y'),210.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Jan-10','%e-%b-%y'),210.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jan-10','%e-%b-%y'),214.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jan-10','%e-%b-%y'),214.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jan-10','%e-%b-%y'),210.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Dec-09','%e-%b-%y'),210.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-09','%e-%b-%y'),211.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Dec-09','%e-%b-%y'),209.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Dec-09','%e-%b-%y'),211.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Dec-09','%e-%b-%y'),209.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-09','%e-%b-%y'),209.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-09','%e-%b-%y'),202.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-09','%e-%b-%y'),200.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Dec-09','%e-%b-%y'),198.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-09','%e-%b-%y'),195.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Dec-09','%e-%b-%y'),191.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-09','%e-%b-%y'),195.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-09','%e-%b-%y'),194.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-09','%e-%b-%y'),196.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Dec-09','%e-%b-%y'),194.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-09','%e-%b-%y'),196.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Dec-09','%e-%b-%y'),197.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-09','%e-%b-%y'),189.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-09','%e-%b-%y'),188.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-09','%e-%b-%y'),193.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Dec-09','%e-%b-%y'),196.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-09','%e-%b-%y'),196.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Dec-09','%e-%b-%y'),196.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-09','%e-%b-%y'),199.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-09','%e-%b-%y'),200.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-09','%e-%b-%y'),204.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Nov-09','%e-%b-%y'),204.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Nov-09','%e-%b-%y'),204.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Nov-09','%e-%b-%y'),205.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Nov-09','%e-%b-%y'),199.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Nov-09','%e-%b-%y'),200.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-09','%e-%b-%y'),205.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Nov-09','%e-%b-%y'),207);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Nov-09','%e-%b-%y'),206.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Nov-09','%e-%b-%y'),204.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Nov-09','%e-%b-%y'),201.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Nov-09','%e-%b-%y'),203.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-09','%e-%b-%y'),202.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Nov-09','%e-%b-%y'),201.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Nov-09','%e-%b-%y'),194.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Nov-09','%e-%b-%y'),194.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-09','%e-%b-%y'),190.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Nov-09','%e-%b-%y'),188.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Nov-09','%e-%b-%y'),189.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Oct-09','%e-%b-%y'),188.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Oct-09','%e-%b-%y'),196.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Oct-09','%e-%b-%y'),192.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-09','%e-%b-%y'),197.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Oct-09','%e-%b-%y'),202.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Oct-09','%e-%b-%y'),203.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Oct-09','%e-%b-%y'),205.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-09','%e-%b-%y'),204.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Oct-09','%e-%b-%y'),198.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Oct-09','%e-%b-%y'),189.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Oct-09','%e-%b-%y'),188.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Oct-09','%e-%b-%y'),190.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Oct-09','%e-%b-%y'),191.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-09','%e-%b-%y'),190.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Oct-09','%e-%b-%y'),190.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Oct-09','%e-%b-%y'),190.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Oct-09','%e-%b-%y'),189.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-09','%e-%b-%y'),190.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Oct-09','%e-%b-%y'),190.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Oct-09','%e-%b-%y'),186.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Oct-09','%e-%b-%y'),184.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Oct-09','%e-%b-%y'),180.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Sep-09','%e-%b-%y'),185.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-09','%e-%b-%y'),185.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Sep-09','%e-%b-%y'),186.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Sep-09','%e-%b-%y'),182.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Sep-09','%e-%b-%y'),183.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-09','%e-%b-%y'),185.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Sep-09','%e-%b-%y'),184.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Sep-09','%e-%b-%y'),184.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Sep-09','%e-%b-%y'),185.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Sep-09','%e-%b-%y'),184.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Sep-09','%e-%b-%y'),181.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-09','%e-%b-%y'),175.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Sep-09','%e-%b-%y'),173.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Sep-09','%e-%b-%y'),172.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Sep-09','%e-%b-%y'),172.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-09','%e-%b-%y'),171.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Sep-09','%e-%b-%y'),172.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Sep-09','%e-%b-%y'),170.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Sep-09','%e-%b-%y'),166.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Sep-09','%e-%b-%y'),165.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Sep-09','%e-%b-%y'),165.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Aug-09','%e-%b-%y'),168.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Aug-09','%e-%b-%y'),170.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-09','%e-%b-%y'),169.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-09','%e-%b-%y'),167.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-09','%e-%b-%y'),169.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Aug-09','%e-%b-%y'),169.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Aug-09','%e-%b-%y'),169.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Aug-09','%e-%b-%y'),166.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-09','%e-%b-%y'),164.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-09','%e-%b-%y'),164);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Aug-09','%e-%b-%y'),159.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Aug-09','%e-%b-%y'),166.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-09','%e-%b-%y'),168.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Aug-09','%e-%b-%y'),165.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Aug-09','%e-%b-%y'),164.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Aug-09','%e-%b-%y'),165.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Aug-09','%e-%b-%y'),163.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Aug-09','%e-%b-%y'),165.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Aug-09','%e-%b-%y'),165.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Aug-09','%e-%b-%y'),166.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jul-09','%e-%b-%y'),163.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jul-09','%e-%b-%y'),162.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jul-09','%e-%b-%y'),160.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Jul-09','%e-%b-%y'),160);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jul-09','%e-%b-%y'),160.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jul-09','%e-%b-%y'),159.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jul-09','%e-%b-%y'),157.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jul-09','%e-%b-%y'),156.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Jul-09','%e-%b-%y'),151.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jul-09','%e-%b-%y'),152.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jul-09','%e-%b-%y'),151.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jul-09','%e-%b-%y'),147.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jul-09','%e-%b-%y'),146.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jul-09','%e-%b-%y'),142.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jul-09','%e-%b-%y'),142.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jul-09','%e-%b-%y'),138.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jul-09','%e-%b-%y'),136.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jul-09','%e-%b-%y'),137.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jul-09','%e-%b-%y'),135.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jul-09','%e-%b-%y'),138.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jul-09','%e-%b-%y'),140.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jul-09','%e-%b-%y'),140.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-09','%e-%b-%y'),142.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jun-09','%e-%b-%y'),142.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Jun-09','%e-%b-%y'),141.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jun-09','%e-%b-%y'),142.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jun-09','%e-%b-%y'),139.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Jun-09','%e-%b-%y'),136.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-09','%e-%b-%y'),134.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Jun-09','%e-%b-%y'),137.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jun-09','%e-%b-%y'),139.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jun-09','%e-%b-%y'),135.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-09','%e-%b-%y'),135.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Jun-09','%e-%b-%y'),136.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jun-09','%e-%b-%y'),136.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jun-09','%e-%b-%y'),136.97);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jun-09','%e-%b-%y'),139.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jun-09','%e-%b-%y'),140.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-09','%e-%b-%y'),142.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Jun-09','%e-%b-%y'),143.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jun-09','%e-%b-%y'),144.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jun-09','%e-%b-%y'),143.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-09','%e-%b-%y'),140.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jun-09','%e-%b-%y'),139.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jun-09','%e-%b-%y'),139.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-May-09','%e-%b-%y'),135.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-May-09','%e-%b-%y'),135.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-May-09','%e-%b-%y'),133.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-May-09','%e-%b-%y'),130.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-May-09','%e-%b-%y'),122.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-09','%e-%b-%y'),124.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-May-09','%e-%b-%y'),125.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-09','%e-%b-%y'),127.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-May-09','%e-%b-%y'),126.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-May-09','%e-%b-%y'),122.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-09','%e-%b-%y'),122.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-09','%e-%b-%y'),119.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-May-09','%e-%b-%y'),124.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-May-09','%e-%b-%y'),129.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-May-09','%e-%b-%y'),129.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-09','%e-%b-%y'),129.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-09','%e-%b-%y'),132.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-09','%e-%b-%y'),132.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-May-09','%e-%b-%y'),132.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-May-09','%e-%b-%y'),127.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Apr-09','%e-%b-%y'),125.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-09','%e-%b-%y'),125.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-09','%e-%b-%y'),123.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Apr-09','%e-%b-%y'),124.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Apr-09','%e-%b-%y'),123.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-09','%e-%b-%y'),125.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Apr-09','%e-%b-%y'),121.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-09','%e-%b-%y'),121.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Apr-09','%e-%b-%y'),120.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Apr-09','%e-%b-%y'),123.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Apr-09','%e-%b-%y'),121.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-09','%e-%b-%y'),117.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Apr-09','%e-%b-%y'),118.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Apr-09','%e-%b-%y'),120.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Apr-09','%e-%b-%y'),119.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-09','%e-%b-%y'),119.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Apr-09','%e-%b-%y'),116.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-09','%e-%b-%y'),115);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Apr-09','%e-%b-%y'),118.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-09','%e-%b-%y'),115.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-09','%e-%b-%y'),112.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-09','%e-%b-%y'),108.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('31-Mar-09','%e-%b-%y'),105.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Mar-09','%e-%b-%y'),104.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Mar-09','%e-%b-%y'),106.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-09','%e-%b-%y'),109.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-09','%e-%b-%y'),106.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-09','%e-%b-%y'),106.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Mar-09','%e-%b-%y'),107.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Mar-09','%e-%b-%y'),101.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Mar-09','%e-%b-%y'),101.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Mar-09','%e-%b-%y'),101.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Mar-09','%e-%b-%y'),99.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Mar-09','%e-%b-%y'),95.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Mar-09','%e-%b-%y'),95.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Mar-09','%e-%b-%y'),96.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Mar-09','%e-%b-%y'),92.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Mar-09','%e-%b-%y'),88.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Mar-09','%e-%b-%y'),83.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Mar-09','%e-%b-%y'),85.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Mar-09','%e-%b-%y'),88.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Mar-09','%e-%b-%y'),91.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Mar-09','%e-%b-%y'),88.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Mar-09','%e-%b-%y'),87.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Feb-09','%e-%b-%y'),89.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-09','%e-%b-%y'),89.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Feb-09','%e-%b-%y'),91.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Feb-09','%e-%b-%y'),90.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Feb-09','%e-%b-%y'),86.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Feb-09','%e-%b-%y'),91.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-09','%e-%b-%y'),90.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Feb-09','%e-%b-%y'),94.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Feb-09','%e-%b-%y'),94.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Feb-09','%e-%b-%y'),99.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Feb-09','%e-%b-%y'),99.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Feb-09','%e-%b-%y'),96.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Feb-09','%e-%b-%y'),97.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Feb-09','%e-%b-%y'),102.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Feb-09','%e-%b-%y'),99.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Feb-09','%e-%b-%y'),96.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Feb-09','%e-%b-%y'),93.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Feb-09','%e-%b-%y'),92.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Feb-09','%e-%b-%y'),91.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jan-09','%e-%b-%y'),90.13);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Jan-09','%e-%b-%y'),93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jan-09','%e-%b-%y'),94.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jan-09','%e-%b-%y'),90.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jan-09','%e-%b-%y'),89.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jan-09','%e-%b-%y'),88.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jan-09','%e-%b-%y'),88.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Jan-09','%e-%b-%y'),82.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jan-09','%e-%b-%y'),78.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jan-09','%e-%b-%y'),82.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-09','%e-%b-%y'),83.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jan-09','%e-%b-%y'),85.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jan-09','%e-%b-%y'),87.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Jan-09','%e-%b-%y'),88.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jan-09','%e-%b-%y'),90.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Jan-09','%e-%b-%y'),92.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-09','%e-%b-%y'),91.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jan-09','%e-%b-%y'),93.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jan-09','%e-%b-%y'),94.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Jan-09','%e-%b-%y'),90.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jan-09','%e-%b-%y'),85.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Dec-08','%e-%b-%y'),85.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Dec-08','%e-%b-%y'),86.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Dec-08','%e-%b-%y'),86.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Dec-08','%e-%b-%y'),85.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Dec-08','%e-%b-%y'),85.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-08','%e-%b-%y'),85.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Dec-08','%e-%b-%y'),86.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Dec-08','%e-%b-%y'),85.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Dec-08','%e-%b-%y'),90);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-08','%e-%b-%y'),89.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Dec-08','%e-%b-%y'),89.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Dec-08','%e-%b-%y'),95.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Dec-08','%e-%b-%y'),94.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Dec-08','%e-%b-%y'),98.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Dec-08','%e-%b-%y'),95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-08','%e-%b-%y'),98.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Dec-08','%e-%b-%y'),100.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Dec-08','%e-%b-%y'),99.72);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Dec-08','%e-%b-%y'),94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-08','%e-%b-%y'),91.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Dec-08','%e-%b-%y'),95.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Dec-08','%e-%b-%y'),92.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-Dec-08','%e-%b-%y'),88.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Nov-08','%e-%b-%y'),92.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-08','%e-%b-%y'),95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-08','%e-%b-%y'),95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Nov-08','%e-%b-%y'),90.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Nov-08','%e-%b-%y'),92.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Nov-08','%e-%b-%y'),82.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Nov-08','%e-%b-%y'),80.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Nov-08','%e-%b-%y'),86.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Nov-08','%e-%b-%y'),89.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Nov-08','%e-%b-%y'),88.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Nov-08','%e-%b-%y'),90.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Nov-08','%e-%b-%y'),96.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Nov-08','%e-%b-%y'),90.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Nov-08','%e-%b-%y'),94.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Nov-08','%e-%b-%y'),95.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Nov-08','%e-%b-%y'),98.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Nov-08','%e-%b-%y'),99.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Nov-08','%e-%b-%y'),103.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Nov-08','%e-%b-%y'),110.99);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Nov-08','%e-%b-%y'),106.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Oct-08','%e-%b-%y'),107.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Oct-08','%e-%b-%y'),111.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Oct-08','%e-%b-%y'),104.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Oct-08','%e-%b-%y'),99.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Oct-08','%e-%b-%y'),92.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Oct-08','%e-%b-%y'),96.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Oct-08','%e-%b-%y'),98.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Oct-08','%e-%b-%y'),96.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Oct-08','%e-%b-%y'),91.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Oct-08','%e-%b-%y'),98.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Oct-08','%e-%b-%y'),97.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Oct-08','%e-%b-%y'),101.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Oct-08','%e-%b-%y'),97.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Oct-08','%e-%b-%y'),104.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Oct-08','%e-%b-%y'),110.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Oct-08','%e-%b-%y'),96.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Oct-08','%e-%b-%y'),88.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Oct-08','%e-%b-%y'),89.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Oct-08','%e-%b-%y'),89.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Oct-08','%e-%b-%y'),98.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Oct-08','%e-%b-%y'),97.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('2-Oct-08','%e-%b-%y'),100.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Oct-08','%e-%b-%y'),109.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Sep-08','%e-%b-%y'),113.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Sep-08','%e-%b-%y'),105.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Sep-08','%e-%b-%y'),128.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Sep-08','%e-%b-%y'),131.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('24-Sep-08','%e-%b-%y'),128.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Sep-08','%e-%b-%y'),126.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Sep-08','%e-%b-%y'),131.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Sep-08','%e-%b-%y'),140.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Sep-08','%e-%b-%y'),134.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Sep-08','%e-%b-%y'),127.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Sep-08','%e-%b-%y'),139.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Sep-08','%e-%b-%y'),140.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Sep-08','%e-%b-%y'),148.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Sep-08','%e-%b-%y'),152.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Sep-08','%e-%b-%y'),151.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Sep-08','%e-%b-%y'),151.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Sep-08','%e-%b-%y'),157.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Sep-08','%e-%b-%y'),160.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Sep-08','%e-%b-%y'),161.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Sep-08','%e-%b-%y'),166.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Sep-08','%e-%b-%y'),166.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Aug-08','%e-%b-%y'),169.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Aug-08','%e-%b-%y'),173.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Aug-08','%e-%b-%y'),174.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Aug-08','%e-%b-%y'),173.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Aug-08','%e-%b-%y'),172.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-Aug-08','%e-%b-%y'),176.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Aug-08','%e-%b-%y'),174.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Aug-08','%e-%b-%y'),175.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Aug-08','%e-%b-%y'),173.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Aug-08','%e-%b-%y'),175.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Aug-08','%e-%b-%y'),175.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Aug-08','%e-%b-%y'),179.32);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Aug-08','%e-%b-%y'),179.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Aug-08','%e-%b-%y'),176.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Aug-08','%e-%b-%y'),173.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Aug-08','%e-%b-%y'),169.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Aug-08','%e-%b-%y'),163.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Aug-08','%e-%b-%y'),164.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Aug-08','%e-%b-%y'),160.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Aug-08','%e-%b-%y'),153.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Aug-08','%e-%b-%y'),156.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Jul-08','%e-%b-%y'),158.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jul-08','%e-%b-%y'),159.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jul-08','%e-%b-%y'),157.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jul-08','%e-%b-%y'),154.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jul-08','%e-%b-%y'),162.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jul-08','%e-%b-%y'),159.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jul-08','%e-%b-%y'),166.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jul-08','%e-%b-%y'),162.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Jul-08','%e-%b-%y'),166.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jul-08','%e-%b-%y'),165.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Jul-08','%e-%b-%y'),171.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Jul-08','%e-%b-%y'),172.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jul-08','%e-%b-%y'),169.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jul-08','%e-%b-%y'),173.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jul-08','%e-%b-%y'),172.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Jul-08','%e-%b-%y'),176.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-Jul-08','%e-%b-%y'),174.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jul-08','%e-%b-%y'),179.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jul-08','%e-%b-%y'),175.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jul-08','%e-%b-%y'),170.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jul-08','%e-%b-%y'),168.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Jul-08','%e-%b-%y'),174.68);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Jun-08','%e-%b-%y'),167.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jun-08','%e-%b-%y'),170.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Jun-08','%e-%b-%y'),168.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jun-08','%e-%b-%y'),177.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jun-08','%e-%b-%y'),173.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jun-08','%e-%b-%y'),173.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('20-Jun-08','%e-%b-%y'),175.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jun-08','%e-%b-%y'),180.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jun-08','%e-%b-%y'),178.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jun-08','%e-%b-%y'),181.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jun-08','%e-%b-%y'),176.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jun-08','%e-%b-%y'),172.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Jun-08','%e-%b-%y'),173.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jun-08','%e-%b-%y'),180.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jun-08','%e-%b-%y'),185.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jun-08','%e-%b-%y'),181.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jun-08','%e-%b-%y'),185.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jun-08','%e-%b-%y'),189.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Jun-08','%e-%b-%y'),185.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jun-08','%e-%b-%y'),185.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jun-08','%e-%b-%y'),186.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-May-08','%e-%b-%y'),188.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-May-08','%e-%b-%y'),186.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-May-08','%e-%b-%y'),187.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-May-08','%e-%b-%y'),186.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-May-08','%e-%b-%y'),181.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('22-May-08','%e-%b-%y'),177.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-May-08','%e-%b-%y'),178.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-May-08','%e-%b-%y'),185.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-May-08','%e-%b-%y'),183.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-May-08','%e-%b-%y'),187.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-May-08','%e-%b-%y'),189.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-May-08','%e-%b-%y'),186.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-May-08','%e-%b-%y'),189.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-May-08','%e-%b-%y'),188.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-May-08','%e-%b-%y'),183.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-May-08','%e-%b-%y'),185.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-May-08','%e-%b-%y'),182.59);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-May-08','%e-%b-%y'),186.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-May-08','%e-%b-%y'),184.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-May-08','%e-%b-%y'),180.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-May-08','%e-%b-%y'),180);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('30-Apr-08','%e-%b-%y'),173.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-Apr-08','%e-%b-%y'),175.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('28-Apr-08','%e-%b-%y'),172.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Apr-08','%e-%b-%y'),169.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Apr-08','%e-%b-%y'),168.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Apr-08','%e-%b-%y'),162.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('22-Apr-08','%e-%b-%y'),160.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Apr-08','%e-%b-%y'),168.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Apr-08','%e-%b-%y'),161.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Apr-08','%e-%b-%y'),154.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Apr-08','%e-%b-%y'),153.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Apr-08','%e-%b-%y'),148.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Apr-08','%e-%b-%y'),147.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Apr-08','%e-%b-%y'),147.14);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Apr-08','%e-%b-%y'),154.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Apr-08','%e-%b-%y'),151.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Apr-08','%e-%b-%y'),152.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Apr-08','%e-%b-%y'),155.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Apr-08','%e-%b-%y'),153.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Apr-08','%e-%b-%y'),151.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Apr-08','%e-%b-%y'),147.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Apr-08','%e-%b-%y'),149.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Mar-08','%e-%b-%y'),143.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Mar-08','%e-%b-%y'),143.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('27-Mar-08','%e-%b-%y'),140.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Mar-08','%e-%b-%y'),145.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Mar-08','%e-%b-%y'),140.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Mar-08','%e-%b-%y'),139.53);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Mar-08','%e-%b-%y'),133.27);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Mar-08','%e-%b-%y'),129.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Mar-08','%e-%b-%y'),132.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Mar-08','%e-%b-%y'),126.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Mar-08','%e-%b-%y'),126.61);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Mar-08','%e-%b-%y'),127.94);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Mar-08','%e-%b-%y'),126.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Mar-08','%e-%b-%y'),127.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Mar-08','%e-%b-%y'),119.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Mar-08','%e-%b-%y'),122.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Mar-08','%e-%b-%y'),120.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Mar-08','%e-%b-%y'),124.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Mar-08','%e-%b-%y'),124.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Mar-08','%e-%b-%y'),121.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Feb-08','%e-%b-%y'),125.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Feb-08','%e-%b-%y'),129.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Feb-08','%e-%b-%y'),122.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Feb-08','%e-%b-%y'),119.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Feb-08','%e-%b-%y'),119.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Feb-08','%e-%b-%y'),119.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Feb-08','%e-%b-%y'),121.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Feb-08','%e-%b-%y'),123.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Feb-08','%e-%b-%y'),122.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Feb-08','%e-%b-%y'),124.63);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Feb-08','%e-%b-%y'),127.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Feb-08','%e-%b-%y'),129.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('12-Feb-08','%e-%b-%y'),124.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Feb-08','%e-%b-%y'),129.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Feb-08','%e-%b-%y'),125.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Feb-08','%e-%b-%y'),121.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Feb-08','%e-%b-%y'),122);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Feb-08','%e-%b-%y'),129.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('4-Feb-08','%e-%b-%y'),131.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Feb-08','%e-%b-%y'),133.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Jan-08','%e-%b-%y'),135.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Jan-08','%e-%b-%y'),132.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Jan-08','%e-%b-%y'),131.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jan-08','%e-%b-%y'),130.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Jan-08','%e-%b-%y'),130.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Jan-08','%e-%b-%y'),135.6);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Jan-08','%e-%b-%y'),139.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jan-08','%e-%b-%y'),155.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('18-Jan-08','%e-%b-%y'),161.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jan-08','%e-%b-%y'),160.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('16-Jan-08','%e-%b-%y'),159.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Jan-08','%e-%b-%y'),169.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('14-Jan-08','%e-%b-%y'),178.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jan-08','%e-%b-%y'),172.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('10-Jan-08','%e-%b-%y'),178.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jan-08','%e-%b-%y'),179.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('8-Jan-08','%e-%b-%y'),171.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Jan-08','%e-%b-%y'),177.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('4-Jan-08','%e-%b-%y'),180.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('3-Jan-08','%e-%b-%y'),194.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Jan-08','%e-%b-%y'),194.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Dec-07','%e-%b-%y'),198.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('28-Dec-07','%e-%b-%y'),199.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Dec-07','%e-%b-%y'),198.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('26-Dec-07','%e-%b-%y'),198.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Dec-07','%e-%b-%y'),198.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Dec-07','%e-%b-%y'),193.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Dec-07','%e-%b-%y'),187.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Dec-07','%e-%b-%y'),183.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Dec-07','%e-%b-%y'),182.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Dec-07','%e-%b-%y'),184.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Dec-07','%e-%b-%y'),190.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Dec-07','%e-%b-%y'),191.83);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Dec-07','%e-%b-%y'),190.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Dec-07','%e-%b-%y'),188.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Dec-07','%e-%b-%y'),194.21);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Dec-07','%e-%b-%y'),194.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Dec-07','%e-%b-%y'),189.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Dec-07','%e-%b-%y'),185.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Dec-07','%e-%b-%y'),179.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Dec-07','%e-%b-%y'),178.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Nov-07','%e-%b-%y'),182.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('29-Nov-07','%e-%b-%y'),184.29);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Nov-07','%e-%b-%y'),180.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Nov-07','%e-%b-%y'),174.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Nov-07','%e-%b-%y'),172.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('23-Nov-07','%e-%b-%y'),171.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('21-Nov-07','%e-%b-%y'),168.46);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Nov-07','%e-%b-%y'),168.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Nov-07','%e-%b-%y'),163.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Nov-07','%e-%b-%y'),166.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('15-Nov-07','%e-%b-%y'),164.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('14-Nov-07','%e-%b-%y'),166.11);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Nov-07','%e-%b-%y'),169.96);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Nov-07','%e-%b-%y'),153.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Nov-07','%e-%b-%y'),165.37);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('8-Nov-07','%e-%b-%y'),175.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('7-Nov-07','%e-%b-%y'),186.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('6-Nov-07','%e-%b-%y'),191.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Nov-07','%e-%b-%y'),186.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('2-Nov-07','%e-%b-%y'),187.87);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('1-Nov-07','%e-%b-%y'),187.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Oct-07','%e-%b-%y'),189.95);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Oct-07','%e-%b-%y'),187);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Oct-07','%e-%b-%y'),185.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Oct-07','%e-%b-%y'),184.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Oct-07','%e-%b-%y'),182.78);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Oct-07','%e-%b-%y'),185.93);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Oct-07','%e-%b-%y'),186.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Oct-07','%e-%b-%y'),174.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('19-Oct-07','%e-%b-%y'),170.42);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Oct-07','%e-%b-%y'),173.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Oct-07','%e-%b-%y'),172.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Oct-07','%e-%b-%y'),169.58);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Oct-07','%e-%b-%y'),166.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Oct-07','%e-%b-%y'),167.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('11-Oct-07','%e-%b-%y'),162.23);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Oct-07','%e-%b-%y'),166.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Oct-07','%e-%b-%y'),167.86);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Oct-07','%e-%b-%y'),167.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Oct-07','%e-%b-%y'),161.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Oct-07','%e-%b-%y'),156.24);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Oct-07','%e-%b-%y'),157.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Oct-07','%e-%b-%y'),158.45);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Oct-07','%e-%b-%y'),156.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Sep-07','%e-%b-%y'),153.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Sep-07','%e-%b-%y'),154.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Sep-07','%e-%b-%y'),152.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-Sep-07','%e-%b-%y'),153.18);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Sep-07','%e-%b-%y'),148.28);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-Sep-07','%e-%b-%y'),144.15);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Sep-07','%e-%b-%y'),140.31);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Sep-07','%e-%b-%y'),140.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Sep-07','%e-%b-%y'),140.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-Sep-07','%e-%b-%y'),138.41);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Sep-07','%e-%b-%y'),138.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('13-Sep-07','%e-%b-%y'),137.2);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Sep-07','%e-%b-%y'),136.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Sep-07','%e-%b-%y'),135.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Sep-07','%e-%b-%y'),136.71);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('7-Sep-07','%e-%b-%y'),131.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Sep-07','%e-%b-%y'),135.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('5-Sep-07','%e-%b-%y'),136.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Sep-07','%e-%b-%y'),144.16);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('31-Aug-07','%e-%b-%y'),138.48);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Aug-07','%e-%b-%y'),136.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Aug-07','%e-%b-%y'),134.08);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Aug-07','%e-%b-%y'),126.82);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Aug-07','%e-%b-%y'),132.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Aug-07','%e-%b-%y'),135.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-Aug-07','%e-%b-%y'),131.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Aug-07','%e-%b-%y'),132.51);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Aug-07','%e-%b-%y'),127.57);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Aug-07','%e-%b-%y'),122.22);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('17-Aug-07','%e-%b-%y'),122.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-Aug-07','%e-%b-%y'),117.05);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Aug-07','%e-%b-%y'),119.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Aug-07','%e-%b-%y'),124.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Aug-07','%e-%b-%y'),127.79);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-Aug-07','%e-%b-%y'),125);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('9-Aug-07','%e-%b-%y'),126.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Aug-07','%e-%b-%y'),134.01);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Aug-07','%e-%b-%y'),135.03);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Aug-07','%e-%b-%y'),135.25);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('3-Aug-07','%e-%b-%y'),131.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Aug-07','%e-%b-%y'),136.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Aug-07','%e-%b-%y'),135);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-Jul-07','%e-%b-%y'),131.76);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-Jul-07','%e-%b-%y'),141.43);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('27-Jul-07','%e-%b-%y'),143.85);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('26-Jul-07','%e-%b-%y'),146);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('25-Jul-07','%e-%b-%y'),137.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('24-Jul-07','%e-%b-%y'),134.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('23-Jul-07','%e-%b-%y'),143.7);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('20-Jul-07','%e-%b-%y'),143.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('19-Jul-07','%e-%b-%y'),140);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('18-Jul-07','%e-%b-%y'),138.12);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('17-Jul-07','%e-%b-%y'),138.91);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('16-Jul-07','%e-%b-%y'),138.1);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('13-Jul-07','%e-%b-%y'),137.73);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('12-Jul-07','%e-%b-%y'),134.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('11-Jul-07','%e-%b-%y'),132.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('10-Jul-07','%e-%b-%y'),132.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('9-Jul-07','%e-%b-%y'),130.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('6-Jul-07','%e-%b-%y'),132.3);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('5-Jul-07','%e-%b-%y'),132.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-Jul-07','%e-%b-%y'),127.17);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-Jul-07','%e-%b-%y'),121.26);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('29-Jun-07','%e-%b-%y'),122.04);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('28-Jun-07','%e-%b-%y'),120.56);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Jun-07','%e-%b-%y'),121.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Jun-07','%e-%b-%y'),119.65);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Jun-07','%e-%b-%y'),122.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-Jun-07','%e-%b-%y'),123);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('21-Jun-07','%e-%b-%y'),123.9);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('20-Jun-07','%e-%b-%y'),121.55);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('19-Jun-07','%e-%b-%y'),123.66);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-Jun-07','%e-%b-%y'),125.09);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-Jun-07','%e-%b-%y'),120.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-Jun-07','%e-%b-%y'),118.75);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('13-Jun-07','%e-%b-%y'),117.5);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('12-Jun-07','%e-%b-%y'),120.38);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-Jun-07','%e-%b-%y'),120.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-Jun-07','%e-%b-%y'),124.49);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-Jun-07','%e-%b-%y'),124.07);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('6-Jun-07','%e-%b-%y'),123.64);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('5-Jun-07','%e-%b-%y'),122.67);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-Jun-07','%e-%b-%y'),121.33);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('1-Jun-07','%e-%b-%y'),118.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('31-May-07','%e-%b-%y'),121.19);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('30-May-07','%e-%b-%y'),118.77);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('29-May-07','%e-%b-%y'),114.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('25-May-07','%e-%b-%y'),113.62);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-May-07','%e-%b-%y'),110.69);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('23-May-07','%e-%b-%y'),112.89);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('22-May-07','%e-%b-%y'),113.54);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('21-May-07','%e-%b-%y'),111.98);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('18-May-07','%e-%b-%y'),110.02);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('17-May-07','%e-%b-%y'),109.44);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('16-May-07','%e-%b-%y'),107.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('15-May-07','%e-%b-%y'),107.52);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('14-May-07','%e-%b-%y'),109.36);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('11-May-07','%e-%b-%y'),108.74);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('10-May-07','%e-%b-%y'),107.34);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('9-May-07','%e-%b-%y'),106.88);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('8-May-07','%e-%b-%y'),105.06);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('7-May-07','%e-%b-%y'),103.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('4-May-07','%e-%b-%y'),100.81);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('3-May-07','%e-%b-%y'),100.4);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('2-May-07','%e-%b-%y'),100.39);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series3',STR_TO_DATE('1-May-07','%e-%b-%y'),99.47);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('30-Apr-07','%e-%b-%y'),99.8);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('27-Apr-07','%e-%b-%y'),99.92);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('26-Apr-07','%e-%b-%y'),98.84);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series2',STR_TO_DATE('25-Apr-07','%e-%b-%y'),95.35);
-Insert into demo_line_chart (series, log_date, data_value) values ('Series1',STR_TO_DATE('24-Apr-07','%e-%b-%y'),93.24);
-
--- DEMO_PIE_CHART
-Insert into demo_pie_chart (legend, data_value) values ('One', 5);
-Insert into demo_pie_chart (legend, data_value) values ('Two', 2);
-Insert into demo_pie_chart (legend, data_value) values ('Three', 9);
-Insert into demo_pie_chart (legend, data_value) values ('Four', 7);
-Insert into demo_pie_chart (legend, data_value) values ('Five', 4);
-Insert into demo_pie_chart (legend, data_value) values ('Six', 3);
-Insert into demo_pie_chart (legend, data_value) values ('Seven', .5);
-
-
--- DEMO_SCATTER_CHART
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.1, 'Particulate', 122);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.3, 'Particulate', 117);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.7, 'Particulate', 112);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.4, 'Particulate', 114);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.9, 'Particulate', 110);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (5.0, 'Particulate', 114);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (3.6, 'Particulate', 128);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (1.9, 'Particulate', 137);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.3, 'Particulate', 104);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (6.9, 'Humidity', 119);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.9, 'Humidity', 118);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (9.8, 'Humidity', 103);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.9, 'Humidity', 137);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (6.8, 'Humidity', 102);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (4.7, 'Humidity', 89);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (2.7, 'Humidity', 98);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (3.7, 'Humidity', 145);
-Insert into demo_scatter_chart (rainfall, key_value, measurements) values (7.4, 'Humidity', 118);
-
--- DEMO_SCATTER_PLOT
-
--- SET DEFINE OFF;
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -46.5901128883449, -464.477370615131);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -85.0293361247543, -362.252178232471);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 70.9700275365898, 402.214363675566);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -50.1110580054506, -310.108907443154);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 85.043005750476, 813.481841353449);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -14.2356123424179, -134.200903707809);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -66.7014933188071, -445.754374526706);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -79.941582021797, -694.089097548454);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -64.4665101305822, -431.660620986243);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 13.718818366452, 100.010719918027);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 35.457456199233, 223.254643848734);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 55.2326402548387, 268.940835852805);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -32.9989160276248, -237.280626944034);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -0.464911506111831, -2.65656324666862);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -59.0205101710777, -498.895652307826);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 28.0939970575828, 117.200615553207);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 31.7305239061572, 186.662624012256);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 50.9035126419798, 440.937283203403);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 58.3875046571053, 547.879249694999);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 76.7846997917459, 525.020578968308);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 1.73485745801611, 7.28149474936192);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 15.304841061276, 71.2374666595537);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 75.1342455000693, 381.145932349436);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -58.2087417684623, -573.630956069476);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 76.7977837302114, 624.733726327778);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 56.3295585433654, 309.697529902676);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -9.27601440680639, -49.5126219388194);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 98.3002030040236, 765.653589829535);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -25.0987502451517, -174.651201240269);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 39.9215299020147, 337.889176256456);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 77.9225832868337, 356.183903852096);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 75.4311841137638, 14.5258766665983);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 58.9445375968278, 376.359576288564);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', 46.9521897141796, 3.5679984193934);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -49.0378307695689, -230.816092788509);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -96.2461776340861, -863.765255159092);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -96.3388912796447, -538.147283544646);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -21.4684477767032, -200.140077054848);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -30.3532837083366, -226.462637188158);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample0', -17.5055590488884, -118.709622452841);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 56.6394671790491, 385.48951169801);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 70.4622912302344, 356.986529538635);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 58.2647422222769, 489.418744916999);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -92.16093253903, -425.576081634713);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -2.64574970943097, -26.190027661226);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -16.7568654181289, -117.460886096034);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 68.215377945908, 606.917788617984);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 53.7387814434413, 367.53491797949);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -51.8861573715238, -289.998186955562);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -15.9721784074351, -75.335027134323);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 63.2540648905791, 602.546517566905);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -53.376167960458, -470.921238684285);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 40.8307443439851, 276.112653117961);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -13.0540977188468, -127.648158921993);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -43.7358336047599, -435.080470107322);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -74.5673321340732, -617.960236798371);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -6.47907144443936, -55.654651151187);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 68.1915507628225, 352.320728639801);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -23.5393521654339, -137.714557244391);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 28.3621412621467, 141.103859877604);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -99.5615230664525, -974.857161307048);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -77.7132553058204, -736.182131225006);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 95.9321864873013, 478.286112499176);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 97.7451855292708, 940.301427763062);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -10.2483179758141, -70.1145330070458);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -24.0750124187893, -113.523998470537);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -5.5721118558967, -43.8516395203455);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -55.5378338160537, -368.506951528332);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 52.6669516338013, 38.2926120131942);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -74.1981412067658, -436.990411988621);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -8.70511941690364, -71.3277811558721);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 63.2921735621378, 534.825008407329);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 97.9066635843841, 678.994971737474);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -83.1613916743288, -494.53303650568);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 23.4730547863992, 223.031148353333);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 40.6105099506845, 199.937366405274);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 35.4473225526307, 331.61786915261);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 27.2050975460142, 146.277993239147);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', -1.54684302938646, -12.6706471561247);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample1', 45.8386162291745, 401.780882699918);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 43.4241956158593, 228.71488367607);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -23.4517134254585, -165.958577325218);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -98.8954664030229, -829.964553125469);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 48.0527046113198, 451.527720751234);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -77.8912947988124, -416.867729852279);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 23.8325471824168, 206.907438743452);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 83.2787398847467, 814.01250022556);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 49.1572992549647, 451.03037365466);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -11.1351768833872, -57.3863334655361);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 71.1980242104626, 572.745863967841);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 15.0952976022392, 103.30274980367);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 75.0300005037414, 406.581640027236);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -82.0092720309019, -690.340287049552);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 40.2433497232209, 363.579616486762);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 26.8157962678174, 262.150124949525);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -83.9563210001448, -432.739081022174);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -20.6480437627346, -161.330015497217);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 37.1388896882226, 161.352404658606);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 20.2126667486174, 168.833789818416);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 58.3723632769494, 293.206814023827);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -20.2876832456236, -88.0090685884954);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 72.9768050433371, 691.684023528398);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -21.6612128833675, -130.834158714088);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 97.4870524045038, 806.47904449193);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 60.6688063197852, 255.749289305775);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -44.235772358471, -336.262226570567);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -47.39573087854, -321.133647936626);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -24.7522484346097, -204.548308435727);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -42.903238078129, -239.651563752902);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 20.4656734934697, 172.700213789797);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 56.0665747085147, 365.360390019834);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 31.9979219049038, 237.490140339893);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -29.9884426739069, -203.821484170813);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 13.5011085362703, 79.4784314297668);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 41.8402945507358, 297.04934398378);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -84.9323678979223, -345.2331996232);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', -42.2469964847455, -361.468816319656);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 98.1057699772752, 445.181262282444);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 95.5327901766563, 522.663100406047);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample2', 35.0916611161316, 246.796980313209);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 99.3987950082867, 401.97428571655);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -3.0419413965969, -14.5325761725203);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -79.388026451666, -701.817589967372);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -88.451242397524, -668.370526000304);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 34.3131838963851, 254.418322223563);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -61.518208630511, -347.521623572776);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 45.6124480237487, 356.33565541369);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -1.0716036518037, -7.80544934354423);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 31.7371714687412, 283.925868763573);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -76.771029786315, -626.268489584739);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -67.913690110843, -614.736930677921);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 34.9311671860034, 171.384205820777);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 94.3264454603021, 914.267819214392);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 76.7493996267558, 705.649611960615);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -87.795202856922, -749.505178721718);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 2.10914716736019, 15.4036733330536);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -50.456669557937, -318.410608422062);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -94.646644883092, -734.660992935541);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 34.9170862075359, 347.583881438806);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 44.3524585090071, 294.615219199443);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -67.191016143335, -609.956472872497);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -78.826443879164, -369.129912603377);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -50.427554400015, -418.144241602024);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -70.371769526721, -307.02193189609);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 16.3220947890044, 97.0997346831135);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -47.067245718878, -398.27032236792);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 5.91206661301702, 24.7239863780181);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -99.621681801868, -843.593457399484);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 87.4503492670535, 695.345037859433);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -91.176921118057, -683.305064255346);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -0.6632900001386, -5.34157539224209);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 2.98188785882178, 12.1181973600389);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 30.6008700087597, 205.922863867274);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 7.90348761612496, 65.5271597329641);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 40.3565229854156, 268.058138389501);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 37.6892733312091, 247.519083233639);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 16.4759733864001, 107.72661087278);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -53.578492311122, -369.768816039059);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', 77.1292326560541, 765.262108306778);
-Insert into demo_scatter_plot
- (SERIES, VALUEX, VALUEY)
- Values
- ('Sample3', -79.566811593352, -677.545127214159);
-
--- DEMO_UTIL_CHART
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-17','%Y-%m-%d'),53.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-10','%Y-%m-%d'),62.95747);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-21','%Y-%m-%d'),48.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-22','%Y-%m-%d'),51.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-11','%Y-%m-%d'),56.13373);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-23','%Y-%m-%d'),53.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-12','%Y-%m-%d'),57.05287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-24','%Y-%m-%d'),51.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-13','%Y-%m-%d'),55.78947);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-25','%Y-%m-%d'),54.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-14','%Y-%m-%d'),63.34907);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-26','%Y-%m-%d'),50.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-15','%Y-%m-%d'),52.21327);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-27','%Y-%m-%d'),48.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-16','%Y-%m-%d'),51.32080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-28','%Y-%m-%d'),50.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-17','%Y-%m-%d'),58.35720);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-29','%Y-%m-%d'),51.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-18','%Y-%m-%d'),57.62293);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-04-30','%Y-%m-%d'),67.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-19','%Y-%m-%d'),55.25000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-01','%Y-%m-%d'),59.89393);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-20','%Y-%m-%d'),58.79573);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-02','%Y-%m-%d'),61.20753);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-21','%Y-%m-%d'),54.09720);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-03','%Y-%m-%d'),58.98340);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-22','%Y-%m-%d'),59.95813);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-04','%Y-%m-%d'),59.55873);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-23','%Y-%m-%d'),62.03067);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-05','%Y-%m-%d'),58.73680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-24','%Y-%m-%d'),61.97620);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-06','%Y-%m-%d'),59.89967);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-25','%Y-%m-%d'),58.00207);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-07','%Y-%m-%d'),60.67973);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-26','%Y-%m-%d'),59.95440);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-08','%Y-%m-%d'),60.85913);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-27','%Y-%m-%d'),55.43747);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-09','%Y-%m-%d'),60.62460);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-28','%Y-%m-%d'),52.53933);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-10','%Y-%m-%d'),59.51887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-29','%Y-%m-%d'),57.46260);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-11','%Y-%m-%d'),61.57187);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-30','%Y-%m-%d'),60.04787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-12','%Y-%m-%d'),60.70000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-31','%Y-%m-%d'),58.79480);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-13','%Y-%m-%d'),69.85133);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-01','%Y-%m-%d'),54.40107);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-14','%Y-%m-%d'),68.99620);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-02','%Y-%m-%d'),62.26007);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-15','%Y-%m-%d'),67.64080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-03','%Y-%m-%d'),60.72360);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-16','%Y-%m-%d'),59.71433);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-04','%Y-%m-%d'),60.95847);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-17','%Y-%m-%d'),59.99667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-05','%Y-%m-%d'),59.45920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-18','%Y-%m-%d'),63.27207);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-06','%Y-%m-%d'),60.58620);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-19','%Y-%m-%d'),60.32080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-07','%Y-%m-%d'),61.94207);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-20','%Y-%m-%d'),57.32907);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-08','%Y-%m-%d'),59.03327);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-21','%Y-%m-%d'),59.76933);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-09','%Y-%m-%d'),62.83087);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-22','%Y-%m-%d'),59.12453);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-10','%Y-%m-%d'),59.36840);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-23','%Y-%m-%d'),57.10167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-11','%Y-%m-%d'),56.11480);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-24','%Y-%m-%d'),58.45820);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-12','%Y-%m-%d'),62.23393);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-25','%Y-%m-%d'),59.45440);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-13','%Y-%m-%d'),59.72313);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-26','%Y-%m-%d'),60.12807);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-14','%Y-%m-%d'),53.37093);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-27','%Y-%m-%d'),59.11760);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-15','%Y-%m-%d'),52.99233);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-28','%Y-%m-%d'),57.32020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-16','%Y-%m-%d'),55.99080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-29','%Y-%m-%d'),59.80360);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-17','%Y-%m-%d'),53.93853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-30','%Y-%m-%d'),66.73280);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-18','%Y-%m-%d'),55.99313);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-05-31','%Y-%m-%d'),58.78673);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-19','%Y-%m-%d'),68.23393);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-01','%Y-%m-%d'),58.82773);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-20','%Y-%m-%d'),61.86213);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-02','%Y-%m-%d'),63.12100);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-21','%Y-%m-%d'),61.20307);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-03','%Y-%m-%d'),59.70467);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-22','%Y-%m-%d'),61.05900);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-04','%Y-%m-%d'),58.85173);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-23','%Y-%m-%d'),58.41040);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-05','%Y-%m-%d'),61.21880);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-24','%Y-%m-%d'),59.15967);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-06','%Y-%m-%d'),58.99920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-25','%Y-%m-%d'),56.42153);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-07','%Y-%m-%d'),59.94693);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-26','%Y-%m-%d'),60.46580);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-08','%Y-%m-%d'),66.27293);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-27','%Y-%m-%d'),57.44333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-09','%Y-%m-%d'),61.46773);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-28','%Y-%m-%d'),56.88887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-10','%Y-%m-%d'),59.70467);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-29','%Y-%m-%d'),61.85773);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-11','%Y-%m-%d'),60.16000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-09-30','%Y-%m-%d'),61.96400);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-12','%Y-%m-%d'),61.20300);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-01','%Y-%m-%d'),65.88833);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-13','%Y-%m-%d'),60.95673);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-02','%Y-%m-%d'),62.67920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-14','%Y-%m-%d'),60.70207);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-03','%Y-%m-%d'),63.52047);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-15','%Y-%m-%d'),61.02520);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-04','%Y-%m-%d'),58.60280);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-16','%Y-%m-%d'),60.33953);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-05','%Y-%m-%d'),63.74487);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-17','%Y-%m-%d'),61.20300);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-06','%Y-%m-%d'),59.94880);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-18','%Y-%m-%d'),63.12100);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-07','%Y-%m-%d'),59.44380);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-23','%Y-%m-%d'),61.09153);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-08','%Y-%m-%d'),59.16320);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-24','%Y-%m-%d'),61.28867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-09','%Y-%m-%d'),60.84593);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-25','%Y-%m-%d'),60.95673);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-10','%Y-%m-%d'),58.84113);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-26','%Y-%m-%d'),60.61100);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-11','%Y-%m-%d'),62.59827);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-27','%Y-%m-%d'),61.22913);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-12','%Y-%m-%d'),60.94660);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-28','%Y-%m-%d'),58.88507);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-13','%Y-%m-%d'),59.37593);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-29','%Y-%m-%d'),59.73693);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-14','%Y-%m-%d'),67.21840);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-06-30','%Y-%m-%d'),62.45307);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-15','%Y-%m-%d'),68.56020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-01','%Y-%m-%d'),61.30167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-16','%Y-%m-%d'),57.56493);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-02','%Y-%m-%d'),62.92727);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-17','%Y-%m-%d'),57.02280);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-03','%Y-%m-%d'),60.05887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-18','%Y-%m-%d'),56.20947);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-06','%Y-%m-%d'),61.20100);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-19','%Y-%m-%d'),55.69353);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-07','%Y-%m-%d'),60.66120);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-20','%Y-%m-%d'),57.17640);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-08','%Y-%m-%d'),59.78180);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-21','%Y-%m-%d'),57.50867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-09','%Y-%m-%d'),58.74653);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-22','%Y-%m-%d'),61.67860);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-10','%Y-%m-%d'),59.77893);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-23','%Y-%m-%d'),57.34867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-11','%Y-%m-%d'),67.34500);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-24','%Y-%m-%d'),61.68080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-12','%Y-%m-%d'),57.07293);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-25','%Y-%m-%d'),55.55793);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-13','%Y-%m-%d'),57.37567);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-26','%Y-%m-%d'),55.81013);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-14','%Y-%m-%d'),63.97820);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-27','%Y-%m-%d'),59.85540);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-15','%Y-%m-%d'),56.06647);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-28','%Y-%m-%d'),61.05073);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-16','%Y-%m-%d'),53.66347);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-29','%Y-%m-%d'),59.81253);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-23','%Y-%m-%d'),56.50813);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-30','%Y-%m-%d'),61.02047);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-24','%Y-%m-%d'),53.19667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-10-31','%Y-%m-%d'),60.60413);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-25','%Y-%m-%d'),51.57133);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-01','%Y-%m-%d'),57.43067);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-26','%Y-%m-%d'),45.98160);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-02','%Y-%m-%d'),58.63027);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-27','%Y-%m-%d'),49.21113);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-03','%Y-%m-%d'),59.08127);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-28','%Y-%m-%d'),49.67213);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-04','%Y-%m-%d'),59.37373);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-29','%Y-%m-%d'),52.94053);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-05','%Y-%m-%d'),58.13413);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-30','%Y-%m-%d'),57.55727);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-06','%Y-%m-%d'),57.18893);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-07-31','%Y-%m-%d'),61.76900);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-07','%Y-%m-%d'),56.72853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-01','%Y-%m-%d'),56.51953);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-08','%Y-%m-%d'),56.47340);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-02','%Y-%m-%d'),61.04853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-09','%Y-%m-%d'),62.02333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-03','%Y-%m-%d'),70.06067);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-10','%Y-%m-%d'),61.21787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-04','%Y-%m-%d'),60.97787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-11','%Y-%m-%d'),62.01087);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-05','%Y-%m-%d'),59.25967);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-12','%Y-%m-%d'),62.67573);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-06','%Y-%m-%d'),56.12287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-13','%Y-%m-%d'),59.23993);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-07','%Y-%m-%d'),63.99913);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-14','%Y-%m-%d'),67.34973);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-08','%Y-%m-%d'),58.71127);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-15','%Y-%m-%d'),60.93753);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-08-09','%Y-%m-%d'),64.01913);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-16','%Y-%m-%d'),54.52607);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-17','%Y-%m-%d'),57.81127);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-18','%Y-%m-%d'),63.53027);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-19','%Y-%m-%d'),58.13000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-20','%Y-%m-%d'),58.46827);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-21','%Y-%m-%d'),65.27807);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-22','%Y-%m-%d'),53.74513);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-23','%Y-%m-%d'),60.99107);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-24','%Y-%m-%d'),60.45427);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-25','%Y-%m-%d'),56.16847);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-26','%Y-%m-%d'),59.04040);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-27','%Y-%m-%d'),54.62040);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-28','%Y-%m-%d'),56.34687);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-29','%Y-%m-%d'),54.81560);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-11-30','%Y-%m-%d'),60.22753);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-01','%Y-%m-%d'),59.07307);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-02','%Y-%m-%d'),59.73553);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-03','%Y-%m-%d'),68.69447);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-04','%Y-%m-%d'),68.91767);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-05','%Y-%m-%d'),67.86460);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-06','%Y-%m-%d'),64.43120);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-01','%Y-%m-%d'),61.22507);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-07','%Y-%m-%d'),60.67793);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-02','%Y-%m-%d'),63.27533);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-08','%Y-%m-%d'),62.47060);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-03','%Y-%m-%d'),69.88087);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-09','%Y-%m-%d'),58.26053);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-04','%Y-%m-%d'),66.84920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-10','%Y-%m-%d'),61.03340);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-05','%Y-%m-%d'),61.57367);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-11','%Y-%m-%d'),57.32620);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-06','%Y-%m-%d'),60.52293);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-12','%Y-%m-%d'),63.10353);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-07','%Y-%m-%d'),62.21027);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-13','%Y-%m-%d'),61.73167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-08','%Y-%m-%d'),63.20380);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-14','%Y-%m-%d'),65.31080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-09','%Y-%m-%d'),62.72427);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-15','%Y-%m-%d'),64.67620);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-10','%Y-%m-%d'),61.59373);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-16','%Y-%m-%d'),62.87287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-11','%Y-%m-%d'),61.21280);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-17','%Y-%m-%d'),60.14680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-12','%Y-%m-%d'),60.79787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-18','%Y-%m-%d'),63.01007);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-13','%Y-%m-%d'),60.00080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-19','%Y-%m-%d'),57.82680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-14','%Y-%m-%d'),60.82333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-20','%Y-%m-%d'),62.59173);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-15','%Y-%m-%d'),59.62020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-21','%Y-%m-%d'),61.65607);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-16','%Y-%m-%d'),60.27420);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-23','%Y-%m-%d'),61.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-17','%Y-%m-%d'),60.06200);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-24','%Y-%m-%d'),59.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-18','%Y-%m-%d'),60.88900);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-25','%Y-%m-%d'),50.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-19','%Y-%m-%d'),59.92547);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-26','%Y-%m-%d'),60.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-20','%Y-%m-%d'),59.99853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-27','%Y-%m-%d'),62.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-21','%Y-%m-%d'),58.65873);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-28','%Y-%m-%d'),61.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-22','%Y-%m-%d'),60.61000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-29','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-23','%Y-%m-%d'),59.92280);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-30','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-24','%Y-%m-%d'),59.52427);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2014-12-31','%Y-%m-%d'),62.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-25','%Y-%m-%d'),59.44887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-01','%Y-%m-%d'),60.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-26','%Y-%m-%d'),60.23540);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-02','%Y-%m-%d'),62.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-27','%Y-%m-%d'),61.18333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-03','%Y-%m-%d'),62.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-28','%Y-%m-%d'),60.88133);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-04','%Y-%m-%d'),60.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-29','%Y-%m-%d'),61.74160);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-06','%Y-%m-%d'),62.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-30','%Y-%m-%d'),60.25647);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-08','%Y-%m-%d'),61.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-03-31','%Y-%m-%d'),60.41220);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-09','%Y-%m-%d'),63.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-01','%Y-%m-%d'),59.21053);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-10','%Y-%m-%d'),61.82227);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-02','%Y-%m-%d'),55.04713);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-11','%Y-%m-%d'),61.89553);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-03','%Y-%m-%d'),56.08473);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-12','%Y-%m-%d'),60.90127);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-04','%Y-%m-%d'),64.51107);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-13','%Y-%m-%d'),62.23660);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-05','%Y-%m-%d'),56.75193);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-14','%Y-%m-%d'),61.76947);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-06','%Y-%m-%d'),61.64240);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-15','%Y-%m-%d'),63.08853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-07','%Y-%m-%d'),61.33653);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-16','%Y-%m-%d'),60.12627);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-08','%Y-%m-%d'),69.28867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-17','%Y-%m-%d'),60.60020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-09','%Y-%m-%d'),60.87507);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-18','%Y-%m-%d'),60.43440);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-10','%Y-%m-%d'),68.08707);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-19','%Y-%m-%d'),65.02820);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-11','%Y-%m-%d'),60.57680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-20','%Y-%m-%d'),62.95593);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-12','%Y-%m-%d'),61.52467);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-21','%Y-%m-%d'),61.23967);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-13','%Y-%m-%d'),58.06567);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-22','%Y-%m-%d'),62.61853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-14','%Y-%m-%d'),59.80807);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-23','%Y-%m-%d'),63.64227);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-15','%Y-%m-%d'),79.90007);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-24','%Y-%m-%d'),63.42147);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-16','%Y-%m-%d'),54.75020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-25','%Y-%m-%d'),60.82687);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-17','%Y-%m-%d'),65.69500);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-26','%Y-%m-%d'),60.66260);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-18','%Y-%m-%d'),68.56247);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-27','%Y-%m-%d'),60.12767);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-19','%Y-%m-%d'),72.67153);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-28','%Y-%m-%d'),60.51513);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-20','%Y-%m-%d'),71.30720);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-29','%Y-%m-%d'),61.71520);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-21','%Y-%m-%d'),57.75233);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-30','%Y-%m-%d'),60.89553);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-22','%Y-%m-%d'),59.04200);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-01-31','%Y-%m-%d'),63.50540);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-23','%Y-%m-%d'),62.30153);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-01','%Y-%m-%d'),62.37533);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-24','%Y-%m-%d'),67.68287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-02','%Y-%m-%d'),60.31400);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-25','%Y-%m-%d'),69.21800);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-03','%Y-%m-%d'),63.43920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-26','%Y-%m-%d'),69.75993);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-04','%Y-%m-%d'),61.20487);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-27','%Y-%m-%d'),64.64113);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-05','%Y-%m-%d'),62.11167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-28','%Y-%m-%d'),60.10053);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-06','%Y-%m-%d'),59.96140);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-29','%Y-%m-%d'),58.67653);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-07','%Y-%m-%d'),62.60727);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-04-30','%Y-%m-%d'),58.29180);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-08','%Y-%m-%d'),61.95493);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-01','%Y-%m-%d'),60.56173);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-09','%Y-%m-%d'),58.89653);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-02','%Y-%m-%d'),57.15840);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-10','%Y-%m-%d'),66.20167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-03','%Y-%m-%d'),54.49167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-11','%Y-%m-%d'),64.76873);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-04','%Y-%m-%d'),61.54087);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-12','%Y-%m-%d'),69.90680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-05','%Y-%m-%d'),63.86073);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-13','%Y-%m-%d'),68.49253);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-06','%Y-%m-%d'),64.13460);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-14','%Y-%m-%d'),63.19360);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-07','%Y-%m-%d'),65.30087);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-15','%Y-%m-%d'),63.35453);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-08','%Y-%m-%d'),64.46353);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-16','%Y-%m-%d'),59.78020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-09','%Y-%m-%d'),62.81193);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-17','%Y-%m-%d'),60.70760);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-10','%Y-%m-%d'),56.14480);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-18','%Y-%m-%d'),58.05167);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-11','%Y-%m-%d'),61.47853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-19','%Y-%m-%d'),57.12700);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-12','%Y-%m-%d'),63.39287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-20','%Y-%m-%d'),59.49013);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-13','%Y-%m-%d'),64.30640);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-21','%Y-%m-%d'),59.18607);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-14','%Y-%m-%d'),64.29447);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-22','%Y-%m-%d'),60.94680);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-15','%Y-%m-%d'),65.63307);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-23','%Y-%m-%d'),59.85807);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-16','%Y-%m-%d'),62.32887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-24','%Y-%m-%d'),60.06767);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-17','%Y-%m-%d'),56.52853);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-25','%Y-%m-%d'),61.60267);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-18','%Y-%m-%d'),70.26520);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-26','%Y-%m-%d'),60.94220);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-19','%Y-%m-%d'),64.38267);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-27','%Y-%m-%d'),59.99040);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-20','%Y-%m-%d'),63.01447);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-02-28','%Y-%m-%d'),63.05567);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-21','%Y-%m-%d'),61.89200);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-22','%Y-%m-%d'),62.06920);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-23','%Y-%m-%d'),68.49253);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-24','%Y-%m-%d'),69.98867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-25','%Y-%m-%d'),60.26940);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-26','%Y-%m-%d'),62.91493);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-09','%Y-%m-%d'),62.28433);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-27','%Y-%m-%d'),62.36827);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-10','%Y-%m-%d'),64.38787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-11','%Y-%m-%d'),61.17093);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-28','%Y-%m-%d'),60.33887);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-12','%Y-%m-%d'),57.17713);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-29','%Y-%m-%d'),83.89220);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-13','%Y-%m-%d'),57.69653);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-30','%Y-%m-%d'),60.96747);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-14','%Y-%m-%d'),55.97980);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-05-31','%Y-%m-%d'),57.80627);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-15','%Y-%m-%d'),62.08940);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-01','%Y-%m-%d'),61.60173);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-16','%Y-%m-%d'),83.81047);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-02','%Y-%m-%d'),63.23627);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-17','%Y-%m-%d'),61.32540);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-03','%Y-%m-%d'),58.39987);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-18','%Y-%m-%d'),61.08900);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-04','%Y-%m-%d'),69.51947);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-19','%Y-%m-%d'),67.26267);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-05','%Y-%m-%d'),69.67787);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-20','%Y-%m-%d'),58.71120);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-06','%Y-%m-%d'),62.40513);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-21','%Y-%m-%d'),55.77320);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-07','%Y-%m-%d'),61.01893);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-22','%Y-%m-%d'),59.99420);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-08','%Y-%m-%d'),61.34813);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-23','%Y-%m-%d'),60.83867);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-24','%Y-%m-%d'),59.57020);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-25','%Y-%m-%d'),63.20393);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-17','%Y-%m-%d'),67.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-26','%Y-%m-%d'),58.30480);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-18','%Y-%m-%d'),64.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-27','%Y-%m-%d'),58.79667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-19','%Y-%m-%d'),60.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-28','%Y-%m-%d'),54.04967);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-20','%Y-%m-%d'),57.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-29','%Y-%m-%d'),57.88313);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-21','%Y-%m-%d'),58.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-06-30','%Y-%m-%d'),56.94940);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-22','%Y-%m-%d'),59.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-01','%Y-%m-%d'),65.01080);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-23','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-02','%Y-%m-%d'),64.97013);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-24','%Y-%m-%d'),59.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-03','%Y-%m-%d'),65.06647);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-25','%Y-%m-%d'),59.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-04','%Y-%m-%d'),64.08287);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-26','%Y-%m-%d'),76.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-05','%Y-%m-%d'),65.40367);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-27','%Y-%m-%d'),59.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-06','%Y-%m-%d'),72.61373);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-28','%Y-%m-%d'),59.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-07','%Y-%m-%d'),72.53120);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-29','%Y-%m-%d'),58.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-08','%Y-%m-%d'),72.54133);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-26','%Y-%m-%d'),58.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-30','%Y-%m-%d'),54.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-01','%Y-%m-%d'),58.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-02','%Y-%m-%d'),59.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-03','%Y-%m-%d'),58.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-04','%Y-%m-%d'),60.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-05','%Y-%m-%d'),101.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-06','%Y-%m-%d'),58.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-07','%Y-%m-%d'),59.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-08','%Y-%m-%d'),56.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-09','%Y-%m-%d'),57.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-10','%Y-%m-%d'),65.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-11','%Y-%m-%d'),56.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-12','%Y-%m-%d'),54.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-13','%Y-%m-%d'),68.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-14','%Y-%m-%d'),69.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-15','%Y-%m-%d'),66.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-16','%Y-%m-%d'),58.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-17','%Y-%m-%d'),60.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-18','%Y-%m-%d'),58.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-19','%Y-%m-%d'),55.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-20','%Y-%m-%d'),55.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-21','%Y-%m-%d'),57.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-22','%Y-%m-%d'),57.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-23','%Y-%m-%d'),58.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-24','%Y-%m-%d'),57.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-25','%Y-%m-%d'),58.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-26','%Y-%m-%d'),61.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-27','%Y-%m-%d'),57.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-28','%Y-%m-%d'),58.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-29','%Y-%m-%d'),59.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-30','%Y-%m-%d'),55.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-10-31','%Y-%m-%d'),53.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-01','%Y-%m-%d'),56.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-02','%Y-%m-%d'),57.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-03','%Y-%m-%d'),55.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-04','%Y-%m-%d'),57.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-05','%Y-%m-%d'),65.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-06','%Y-%m-%d'),55.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-07','%Y-%m-%d'),57.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-08','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-09','%Y-%m-%d'),60.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-10','%Y-%m-%d'),58.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-11','%Y-%m-%d'),58.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-12','%Y-%m-%d'),57.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-13','%Y-%m-%d'),57.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-14','%Y-%m-%d'),55.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-15','%Y-%m-%d'),55.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-16','%Y-%m-%d'),58.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-17','%Y-%m-%d'),58.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-18','%Y-%m-%d'),64.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-19','%Y-%m-%d'),59.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-20','%Y-%m-%d'),57.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-21','%Y-%m-%d'),57.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-22','%Y-%m-%d'),59.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-23','%Y-%m-%d'),56.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-24','%Y-%m-%d'),58.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-25','%Y-%m-%d'),57.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-26','%Y-%m-%d'),57.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-27','%Y-%m-%d'),53.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-28','%Y-%m-%d'),58.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-29','%Y-%m-%d'),56.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-11-30','%Y-%m-%d'),58.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-01','%Y-%m-%d'),60.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-02','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-03','%Y-%m-%d'),58.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-04','%Y-%m-%d'),77.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-05','%Y-%m-%d'),56.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-06','%Y-%m-%d'),55.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-07','%Y-%m-%d'),57.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-08','%Y-%m-%d'),57.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-09','%Y-%m-%d'),71.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-10','%Y-%m-%d'),62.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-11','%Y-%m-%d'),59.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-12','%Y-%m-%d'),59.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-13','%Y-%m-%d'),62.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-14','%Y-%m-%d'),59.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-15','%Y-%m-%d'),59.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-16','%Y-%m-%d'),62.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-17','%Y-%m-%d'),66.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-18','%Y-%m-%d'),59.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-19','%Y-%m-%d'),60.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-20','%Y-%m-%d'),57.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-21','%Y-%m-%d'),60.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-22','%Y-%m-%d'),59.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-23','%Y-%m-%d'),61.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-24','%Y-%m-%d'),57.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-25','%Y-%m-%d'),52.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-09','%Y-%m-%d'),70.77980);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-10','%Y-%m-%d'),70.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-11','%Y-%m-%d'),60.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-12','%Y-%m-%d'),58.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-13','%Y-%m-%d'),58.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-14','%Y-%m-%d'),58.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-15','%Y-%m-%d'),68.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-16','%Y-%m-%d'),84.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-17','%Y-%m-%d'),61.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-18','%Y-%m-%d'),64.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-19','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-20','%Y-%m-%d'),77.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-21','%Y-%m-%d'),60.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-22','%Y-%m-%d'),65.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-23','%Y-%m-%d'),68.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-24','%Y-%m-%d'),58.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-25','%Y-%m-%d'),56.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-26','%Y-%m-%d'),58.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-27','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-28','%Y-%m-%d'),59.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-29','%Y-%m-%d'),58.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-30','%Y-%m-%d'),59.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-27','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-07-31','%Y-%m-%d'),57.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-28','%Y-%m-%d'),305.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-01','%Y-%m-%d'),59.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-29','%Y-%m-%d'),62.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-02','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-30','%Y-%m-%d'),60.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-03','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-12-31','%Y-%m-%d'),60.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-04','%Y-%m-%d'),83.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-01','%Y-%m-%d'),55.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-05','%Y-%m-%d'),59.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-02','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-06','%Y-%m-%d'),58.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-03','%Y-%m-%d'),61.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-07','%Y-%m-%d'),59.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-04','%Y-%m-%d'),62.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-08','%Y-%m-%d'),57.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-05','%Y-%m-%d'),61.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-09','%Y-%m-%d'),58.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-06','%Y-%m-%d'),61.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-10','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-07','%Y-%m-%d'),62.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-11','%Y-%m-%d'),58.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-08','%Y-%m-%d'),100.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-12','%Y-%m-%d'),57.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-09','%Y-%m-%d'),62.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-13','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-10','%Y-%m-%d'),66.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-14','%Y-%m-%d'),58.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-11','%Y-%m-%d'),61.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-15','%Y-%m-%d'),59.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-12','%Y-%m-%d'),60.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-16','%Y-%m-%d'),61.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-13','%Y-%m-%d'),61.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-17','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-14','%Y-%m-%d'),60.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-18','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-15','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-19','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-16','%Y-%m-%d'),61.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-20','%Y-%m-%d'),60.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-17','%Y-%m-%d'),70.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-21','%Y-%m-%d'),63.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-18','%Y-%m-%d'),61.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-22','%Y-%m-%d'),58.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-19','%Y-%m-%d'),61.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-23','%Y-%m-%d'),59.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-20','%Y-%m-%d'),61.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-24','%Y-%m-%d'),59.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-21','%Y-%m-%d'),61.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-25','%Y-%m-%d'),63.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-22','%Y-%m-%d'),60.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-26','%Y-%m-%d'),61.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-23','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-27','%Y-%m-%d'),60.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-24','%Y-%m-%d'),60.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-28','%Y-%m-%d'),57.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-25','%Y-%m-%d'),61.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-29','%Y-%m-%d'),59.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-26','%Y-%m-%d'),61.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-30','%Y-%m-%d'),57.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-27','%Y-%m-%d'),61.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-08-31','%Y-%m-%d'),59.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-28','%Y-%m-%d'),61.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-01','%Y-%m-%d'),58.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-29','%Y-%m-%d'),61.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-02','%Y-%m-%d'),61.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-30','%Y-%m-%d'),61.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-03','%Y-%m-%d'),59.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-01-31','%Y-%m-%d'),59.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-04','%Y-%m-%d'),59.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-01','%Y-%m-%d'),60.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-05','%Y-%m-%d'),59.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-02','%Y-%m-%d'),60.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-06','%Y-%m-%d'),61.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-03','%Y-%m-%d'),60.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-07','%Y-%m-%d'),59.20000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-04','%Y-%m-%d'),61.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-08','%Y-%m-%d'),61.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-05','%Y-%m-%d'),60.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-09','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-06','%Y-%m-%d'),60.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-10','%Y-%m-%d'),60.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-07','%Y-%m-%d'),60.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-11','%Y-%m-%d'),58.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-08','%Y-%m-%d'),61.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-12','%Y-%m-%d'),58.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-09','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-13','%Y-%m-%d'),58.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-10','%Y-%m-%d'),60.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-14','%Y-%m-%d'),60.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-11','%Y-%m-%d'),60.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-15','%Y-%m-%d'),62.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-12','%Y-%m-%d'),59.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2015-09-16','%Y-%m-%d'),65.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-13','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-14','%Y-%m-%d'),69.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-15','%Y-%m-%d'),59.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-16','%Y-%m-%d'),59.80000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-17','%Y-%m-%d'),60.46667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-18','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-19','%Y-%m-%d'),62.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-20','%Y-%m-%d'),60.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-21','%Y-%m-%d'),59.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-22','%Y-%m-%d'),61.40000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-23','%Y-%m-%d'),60.93333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-24','%Y-%m-%d'),64.13333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-25','%Y-%m-%d'),61.53333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-26','%Y-%m-%d'),59.06667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-27','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-28','%Y-%m-%d'),60.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-02-29','%Y-%m-%d'),61.00000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-01','%Y-%m-%d'),61.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-02','%Y-%m-%d'),61.66667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-03','%Y-%m-%d'),60.73333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-04','%Y-%m-%d'),61.26667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-05','%Y-%m-%d'),61.60000);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-06','%Y-%m-%d'),61.33333);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-07','%Y-%m-%d'),61.86667);
-INSERT INTO demo_util_chart (TRAFFIC_DATE,UTIL_PERC ) VALUES (str_to_date('2016-03-08','%Y-%m-%d'),62.00000);
-
-commit; \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/distribution.xml b/ecomp-sdk/sdk-app/distribution.xml
deleted file mode 100644
index d5c20cd7..00000000
--- a/ecomp-sdk/sdk-app/distribution.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<assembly
- xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
- <id>os-distribution</id>
- <formats>
- <format>zip</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${basedir}</directory>
- <outputDirectory />
- <excludes>
- <exclude>target/</exclude>
- <exclude>.settings/</exclude>
- <exclude>distribution.xml</exclude>
- </excludes>
- </fileSet>
- </fileSets>
-</assembly> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/pom.xml b/ecomp-sdk/sdk-app/pom.xml
deleted file mode 100644
index c2192c11..00000000
--- a/ecomp-sdk/sdk-app/pom.xml
+++ /dev/null
@@ -1,361 +0,0 @@
-<?xml version="1.0"?>
-<project
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
- xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
-
- <!-- This is the Maven project object model (POM) file for a web application
- based on the ECOMP SDK distribution. This file stands alone; it does not
- inherit from a parent maven module. -->
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ep-sdk-app</artifactId>
- <!-- This version number is appended to the distribution (war and zip).
- There is an implicit mapping between this string and the epsdk.version. -->
- <version>1.1.0-SNAPSHOT</version>
- <packaging>war</packaging>
- <name>Ecomp SDK Webapp</name>
- <description>Ecomp SDK Webapp based on the Ecomp SDK</description>
- <scm>
- <connection>scm:git:https://todourl/</connection>
- </scm>
-
- <properties>
- <encoding>UTF-8</encoding>
- <epsdk.version>1.1.0-SNAPSHOT</epsdk.version>
- <springframework.version>4.2.0.RELEASE</springframework.version>
- <hibernate.version>4.3.11.Final</hibernate.version>
- <!-- Skip assembling the zip by default; turn on like this: mvn -Dskipassembly=false
- package -->
- <skipassembly>true</skipassembly>
- <!-- Tests usually require some setup that maven cannot do, so skip. -->
- <skiptests>true</skiptests>
- <sonar.exclusions>**.js</sonar.exclusions>
- <nexusproxy>https://nexus.onap.org</nexusproxy>
- <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
- <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
- <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
- </properties>
- <reporting>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>2.10.4</version>
- <configuration>
- <failOnError>false</failOnError>
- <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
- <docletArtifact>
- <groupId>org.umlgraph</groupId>
- <artifactId>umlgraph</artifactId>
- <version>5.6</version>
- </docletArtifact>
- <additionalparam>-views</additionalparam>
- <useStandardDocletOptions>true</useStandardDocletOptions>
- </configuration>
- </plugin>
- </plugins>
- </reporting>
- <distributionManagement>
- <site>
- <id>nexus</id>
- <url>dav:https://ecomp-nexus:8443/repository/portalsdkapp-javadoc/${epsdk.version}</url>
- </site>
- </distributionManagement>
- <repositories>
- <repository>
- <!-- Releases repository has ECOMP release artifacts -->
- <id>ecomp-releases</id>
- <name>OpenECOMP - Release Repository</name>
- <url>${nexusproxy}/${releaseNexusPath}</url>
- </repository>
- <repository>
- <!-- Snapshots repository has ECOMP snapshot artifacts -->
- <id>ecomp-snapshots</id>
- <name>OpenECOMP - Snapshot Repository</name>
- <url>${nexusproxy}/${snapshotNexusPath}</url>
- </repository>
- <repository>
- <!-- Staging repository has ECOMP staging artifacts -->
- <id>ecomp-staging</id>
- <name>OpenECOMP - Staging Repository</name>
- <url>${nexusproxy}/${stagingNexusPath}</url>
- </repository>
- <repository>
- <!-- Snapshots repository has ECOMP snapshot artifacts -->
- <id>oss-snapshots</id>
- <name>oss Central - Snapshots</name>
- <url>https://oss.sonatype.org/service/local/repositories/releases/content/</url>
- </repository>
-
- </repositories>
-
- <profiles>
- <!-- disable doclint, a new feature in Java 8, when generating javadoc -->
- <profile>
- <id>doclint-java8-disable</id>
- <activation>
- <jdk>[1.8,)</jdk>
- </activation>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>2.10.4</version>
- <configuration>
- <additionalparam>-Xdoclint:none</additionalparam>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-site-plugin</artifactId>
- <version>3.6</version>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-webdav-jackrabbit</artifactId>
- <version>2.10</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>sonar-maven-plugin</artifactId>
- <version>3.2</version>
- </plugin>
- <!-- Compile to Java 1.8 class output format -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.19.1</version>
- <configuration>
- <skipTests>${skiptests}</skipTests>
- <includes>
- <include>**/Test*.java</include>
- <include>**/*Test.java</include>
- <include>**/*TestCase.java</include>
- </includes>
- <additionalClasspathElements>
- <additionalClasspathElement>${basedir}/war</additionalClasspathElement>
- </additionalClasspathElements>
- <systemPropertyVariables>
- <container.classpath>classpath:</container.classpath>
- </systemPropertyVariables>
- </configuration>
- </plugin>
-
- <!-- Fetch SCM info as variable buildNumber -->
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>buildnumber-maven-plugin</artifactId>
- <version>1.4</version>
- <executions>
- <execution>
- <phase>validate</phase>
- <goals>
- <goal>create</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <!-- don't complain about modified files -->
- <doCheck>false</doCheck>
- <!-- don't push anything to git -->
- <doUpdate>false</doUpdate>
- </configuration>
- </plugin>
-
- <!-- Add build and SCM info to manifest -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.0.2</version>
- <configuration>
- <archive>
- <manifest>
- <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
- </manifest>
- <manifestEntries>
- <Build-Time>${maven.build.timestamp}</Build-Time>
- <SCM-Branch>${scmBranch}</SCM-Branch>
- <SCM-Commit>${buildNumber}</SCM-Commit>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
-
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <skipAssembly>${skipassembly}</skipAssembly>
- <descriptors>
- <descriptor>${basedir}/distribution.xml</descriptor>
- </descriptors>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <!-- SDK components -->
-
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-core</artifactId>
- <version>${epsdk.version}</version>
- </dependency>
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-analytics</artifactId>
- <version>${epsdk.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.oracle</groupId>
- <artifactId>ojdbc6</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-workflow</artifactId>
- <version>${epsdk.version}</version>
- </dependency>
- <dependency>
- <groupId>com.att.eelf</groupId>
- <artifactId>eelf-core</artifactId>
- <version>0.0.1</version>
- </dependency>
- <!-- Mapper -->
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.5.2</version>
- </dependency>
- <dependency>
- <groupId>io.searchbox</groupId>
- <artifactId>jest</artifactId>
- <version>2.0.0</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- <!-- Elastic Search -->
- <dependency>
- <groupId>org.elasticsearch</groupId>
- <artifactId>elasticsearch</artifactId>
- <version>2.2.0</version>
- </dependency>
- <dependency>
- <groupId>org.json</groupId>
- <artifactId>json</artifactId>
- <version>20160212</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.2.1</version>
- <exclusions>
- <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
- <exclusion>
- <groupId>c3p0</groupId>
- <artifactId>c3p0</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- bridge to implement commons-logging using slf4j -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${springframework.version}</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java
deleted file mode 100644
index dfdfcade..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/ExternalAppInitializer.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.conf;
-
-import java.util.Arrays;
-
-import org.openecomp.portalsdk.core.conf.AppInitializer;
-
-public class ExternalAppInitializer extends AppInitializer{
-
-
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return super.getRootConfigClasses();
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
-// Class<?>[] configClasses = super.getServletConfigClasses();
-// Class<?>[] additionalConfigClasses = Arrays.copyOf(configClasses, configClasses.length);
-// addConfigClass(additionalConfigClasses, ExternalAppConfig.class);
-// return additionalConfigClasses;
-//
- return new Class[] {ExternalAppConfig.class};
- }
-
- static Class<?>[] addConfigClass(Class<?>[] a, Class<?> e) {
- a = Arrays.copyOf(a, a.length + 1);
- a[a.length - 1] = e;
- return a;
- }
-
- /*
- * URL request will direct to the Spring dispatcher for processing
- */
- @Override
- protected String[] getServletMappings() {
- return super.getServletMappings();
- }
-
-}
-
-
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java
deleted file mode 100644
index 3e1d89d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/conf/HibernateMappingLocations.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.conf;
-
-import org.openecomp.portalsdk.core.conf.HibernateMappingLocatable;
-import org.springframework.context.annotation.Profile;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.stereotype.Component;
-
-@Component
-@Profile("src")
-public class HibernateMappingLocations implements HibernateMappingLocatable {
-
- public Resource[] getMappingLocations() {
- return new Resource[]{new ClassPathResource("../fusion/orm/Fusion.hbm.xml"), new ClassPathResource("../fusion/orm/Workflow.hbm.xml"), new ClassPathResource("../fusion/orm/RNoteBookIntegration.hbm.xml")};
- }
-
-
-}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/PostDroolsController.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/PostDroolsController.java
deleted file mode 100644
index 2729e873..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/controller/PostDroolsController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.controller;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONObject;
-import org.openecomp.portalsdk.core.command.PostDroolsBean;
-import org.openecomp.portalsdk.core.controller.RestrictedBaseController;
-import org.openecomp.portalsdk.core.service.PostDroolsService;
-import org.openecomp.portalsdk.core.web.support.JsonMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-@Controller
-@RequestMapping("/")
-public class PostDroolsController extends RestrictedBaseController{
-
- @Autowired
- private PostDroolsService postDroolsService;
-
- @RequestMapping(value = {"/drools" }, method = RequestMethod.GET)
- public ModelAndView drools(HttpServletRequest request) {
-
- return new ModelAndView(getViewName());
- }
-
-
- @RequestMapping(value = {"/getDrools" }, method = RequestMethod.GET)
- public void getDrools(HttpServletRequest request, HttpServletResponse response) {
- // Map<String, Object> model = new HashMap<String, Object>();
-
- ObjectMapper mapper = new ObjectMapper();
- try {
- List<PostDroolsBean> beanList = postDroolsService.fetchDroolBeans();
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(beanList));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
-
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @RequestMapping(value = {"/getDroolDetails" }, method = RequestMethod.GET)
- public void getDroolDetails(HttpServletRequest request, HttpServletResponse response) {
-
- ObjectMapper mapper = new ObjectMapper();
- try {
-
- PostDroolsBean postDroolsBean = new PostDroolsBean();
- String selectedFile = request.getParameter("selectedFile");
- postDroolsBean.setDroolsFile(selectedFile);//sample populated
- //postDroolsBean.setSelectedRules("[\"NJ\",\"NY\",\"KY\"]");
- postDroolsBean.setClassName(postDroolsService.retrieveClass(selectedFile));
-
- JsonMessage msg = new JsonMessage(mapper.writeValueAsString(postDroolsBean));
- JSONObject j = new JSONObject(msg);
- response.getWriter().write(j.toString());
-
- } catch (JsonGenerationException e) {
- e.printStackTrace();
- } catch (JsonMappingException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @RequestMapping(value = {"/post_drools/execute" }, method = RequestMethod.POST)
- public ModelAndView search(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- try {
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- JsonNode root = mapper.readTree(request.getReader());
- PostDroolsBean postDroolsBean = mapper.readValue(root.get("postDroolsBean").toString(), PostDroolsBean.class);
-
- String resultsString = postDroolsService.execute(postDroolsBean.getDroolsFile(), postDroolsBean.getClassName(), postDroolsBean.getSelectedRules());
-
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application / json");
- request.setCharacterEncoding("UTF-8");
-
- PrintWriter out = response.getWriter();
- //String responseString = mapper.writeValueAsString(resultsString);
- JSONObject j = new JSONObject("{resultsString: "+resultsString+"}");
-
- out.write(j.toString());
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return null;
- }
-
-
-}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java
deleted file mode 100644
index c4a36c61..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/service/AdminAuthExtension.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.service;
-
-import org.openecomp.portalsdk.core.domain.User;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-@Service("adminAuthExtension")
-@Transactional
-public class AdminAuthExtension {
-
- public void saveUserExtension(User user){
- //app's developer implement their own logic here, like updating app's related tables
- }
-
-}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/InitUebHandler.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/InitUebHandler.java
deleted file mode 100644
index c052187a..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/InitUebHandler.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.uebhandler;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import javax.annotation.PostConstruct;
-
-import org.openecomp.portalsdk.core.logging.format.AlarmSeverityEnum;
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
-import org.openecomp.portalsdk.core.onboarding.ueb.UebManager;
-import org.openecomp.portalsdk.core.onboarding.ueb.UebMsg;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-
-//
-// Adding this class for the sole purpose of insuring that the MainUebHandler really
-// honors @Async and kicks off a thread. For more info google @Async and read about
-// @Async only working if called from different class.
-//
-@Configuration
-public class InitUebHandler {
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(InitUebHandler.class);
-
-
- @Autowired
- MainUebHandler mainUebHandler;
-
- public InitUebHandler() {
-
- }
-
- @PostConstruct
- public void initUeb() {
-
- try {
- String enableListenerThread = PortalApiProperties.getProperty(PortalApiConstants.UEB_LISTENERS_ENABLE);
- if (enableListenerThread.equalsIgnoreCase("true")) {
- ConcurrentLinkedQueue<UebMsg> inboxQueue = new ConcurrentLinkedQueue<UebMsg>();
- UebManager.getInstance().initListener(inboxQueue);
- mainUebHandler.runHandler(inboxQueue);
- logger.info(EELFLoggerDelegate.debugLogger, ("Returned from initiating mainUebHandler..."));
- }
- else {
- logger.info(EELFLoggerDelegate.debugLogger, ("Not starting UEB listening thread because ueb_listeners_enable is not set to true in the properties file."));
- }
- }
- catch (Exception e) {
- logger.error(EELFLoggerDelegate.debugLogger, ("Not starting UEB listening thread because property could not be read " + PortalApiConstants.UEB_LISTENERS_ENABLE),AlarmSeverityEnum.MAJOR);
- }
-
- }
-}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/MainUebHandler.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/MainUebHandler.java
deleted file mode 100644
index 7ff07dd4..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/MainUebHandler.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.uebhandler;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.ueb.UebMsg;
-import org.openecomp.portalsdk.core.onboarding.ueb.UebMsgTypes;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-
-//-------------------------------------------------------------------------
-// Listens for received UEB messages and handles the messages
-//
-// Note: To implement a synchronous reply call getMsgId on the request
-// and putMsgId on the reply (echoing the request MsgId).
-//
-//-------------------------------------------------------------------------
-@Component("MainUebHandler")
-public class MainUebHandler {
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MainUebHandler.class);
-
-
- ConcurrentLinkedQueue<UebMsg> inboxQueue = null;
-
- @Autowired
- WidgetNotificationHandler widgetNotificationHandler;
-
- @Async
- public void runHandler(ConcurrentLinkedQueue<UebMsg> queue) {
- inboxQueue = queue;
-
- logger.info(EELFLoggerDelegate.debugLogger, ("==> MainUebHandler started"));
-
- while (true) {
- UebMsg msg = null;
- while ((msg = inboxQueue.poll()) != null) {
- if (msg.getMsgType() != null) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("<== Received UEB message : " + msg.toString()));
-
- switch (msg.getMsgType()) {
- /*
- * Add your own defined handler objects, use @Component for
- * the class. See WidgetNotificationHandler as an example.
- *
- * Use @Async on methods for performance
- *
- * For syncronous replies use UebManager publishReply and
- * echo back the msgId in your response ie
- * msg.putMsgId(requestMsg.getMsgId())
- *
- * case UebMsgTypes.UEB_MSG_TYPE_XYZ: {
- * XYZHandler.handleMsg(msg); break; }
- */
- case UebMsgTypes.UEB_MSG_TYPE_WIDGET_NOTIFICATION: {
- widgetNotificationHandler.handleWidgetNotification(msg);
- break;
- }
- default: {
-
- logger.info(EELFLoggerDelegate.debugLogger, ("Unknown message type [" + msg.getMsgType() + "] from " + msg.getSourceTopicName()));
-
- break;
- }
- }
- }
- }
-
- if (Thread.interrupted()) {
-
- logger.info(EELFLoggerDelegate.debugLogger, ("==> UebMainHandler exiting"));
-
- break;
- }
-
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- logger.info(EELFLoggerDelegate.debugLogger, ("UebMainHandler interrupted during sleep" + e.getMessage()));
-
- }
- }
- }
-}
diff --git a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/WidgetNotificationHandler.java b/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/WidgetNotificationHandler.java
deleted file mode 100644
index dd2213da..00000000
--- a/ecomp-sdk/sdk-app/src/main/java/org/openecomp/portalapp/uebhandler/WidgetNotificationHandler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalapp.uebhandler;
-
-import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.openecomp.portalsdk.core.onboarding.ueb.UebMsg;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-
-@Component
-public class WidgetNotificationHandler {
-
- EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(WidgetNotificationHandler.class);
-
-
- public WidgetNotificationHandler() {
- }
-
- @Async
- public void handleWidgetNotification(UebMsg requestMsg) {
- logger.debug(EELFLoggerDelegate.debugLogger, ("handleWidgetNotification received notification: " + requestMsg.toString()));
- /*
- * Here the notification msg can be handled
- *
- * requestMsg.getPayload() - returns string that contains the
- * Application defined content
- */
- }
-}
diff --git a/ecomp-sdk/sdk-app/src/main/resources/portal.properties b/ecomp-sdk/sdk-app/src/main/resources/portal.properties
deleted file mode 100644
index fb59dfbb..00000000
--- a/ecomp-sdk/sdk-app/src/main/resources/portal.properties
+++ /dev/null
@@ -1,69 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
-# Properties read by ECOMP Framework library, ecompFW.jar
-
-##########################################################################
-# The following properties should NOT be changed by partner applications.
-##########################################################################
-
-portal.api.prefix = /api
-max.idle.time = 5
-user.attribute.name = user_attribute
-
-testing=testing
-
-#Use REST API instead of UEB to fetch the functional menu data
-use_rest_for_functional_menu=true
-
-##########################################################################
-# The following properties MUST be changed by partner applications.
-##########################################################################
-
-# Name of java class that implements the OnBoardingApiService interface.
-portal.api.impl.class = org.openecomp.portalsdk.core.onboarding.client.OnBoardingApiServiceImpl
-
-# CSP Global Log On for single sign on
-ecomp_redirect_url = http://todo_enter_portal_hostname:8080/ecompportal/login.htm
-
-# URL of the ECOMP Portal REST API
-
-ecomp_rest_url = TODO_Portal_URL
-
-# Applications do not need to run a UEB listener in 1610.
-ueb_listeners_enable = false
-
-# UEB Configuration
-# In release 1607, all 6 entries below were required.
-# In release 1610, if key ueb_listeners_enable is set to false,
-# then only the ueb_app_key is required.
-# UEB servers
-ueb_url_list = todo_ueb_url_list
-# ECOMP Portal listens on this UEB topic
-ecomp_portal_inbox_name = ECOMP-PORTAL-INBOX-TEST-DEMETER
-# Replace these 3 default values with the ones for your specific App,
-# as shown on the on-boarding page on the ECOMP Portal web application.
-ueb_app_key = ZOicEniw7BWDL1pM
-ueb_app_secret = PJIsBErHfo2RGKzuu03CZKgV
-ueb_app_mailbox_name = ECOMP-PORTAL-OUTBOX-TEST-32756
-# Consumer group name for UEB topic.
-# Use the special tag '{UUID}' to generate a unique one for each sdk-app server.
-ueb_app_consumer_group_name = {UUID}
-
-decryption_key = AGLDdG4D04BKm2IxIWEr8o==
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties
deleted file mode 100644
index ce9d57c3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_app_fusion.properties
+++ /dev/null
@@ -1,39 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
-temp_folder_path=/demeter/WebApps/dev/ECOMP_PORTAL/temp/
-upload_folder_path=/demeter/WebApps/dev/ECOMP_PORTAL/files/
-excel_template_path=/demeter/WebApps/dev/ECOMP_PORTAL/files/raptor_template/
-temp_folder_url=temp/
-upload_folder_url=upload/
-smtp_server=todo.smtp.com
-default_email_sender=email-name@email.com
-error_page=error_page.jsp
-jsp_context_path=raptor/
-img_folder_url=static/fusion/raptor/images/
-base_folder_url=static/fusion/raptor/
-direct_access_url=http://localhost:8080/quantum/raptor_email_attachment.htm?action=raptor&source_page=report_run&display_content=y
-#base_action_url=report.htm#/report_run/
-drill_action_url=report.htm#/report_run/c_master=
-base_action_url=report_wizard.htm?action=
-base_action_url_ng=report#/
-base_action_param=c_master=
-super_role_id=1
-admin_role_ids=1
-quick_links_menu_ids=HOME,CUSTOMER,REPORTS
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties
deleted file mode 100644
index 8b987068..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_db_fusion.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_pdf.properties b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_pdf.properties
deleted file mode 100644
index d98a47cd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/raptor_pdf.properties
+++ /dev/null
@@ -1,49 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
-## pdf file specific properties
-pdf_data_font_size=9
-pdf_data_font_family=Arial
-#reduce the font size from html config
-pdf_data_font_size_offset=2
-pdf_data_alternate_color=true
-#data row background(white), alternate(light light blue/gray)
-pdf_data_background_alternate_hex_code=#EDEDED
-pdf_data_default_background_hex_code=#FFFFFF
-#header font (white) background (gray)
-pdf_data_table_header_font_hex_code=#FFFFFF
-pdf_data_table_header_background_hex_code=#8A9BB3
-#footer header
-pdf_footer_font_size=9
-pdf_footer_font_family=Arial
-pdf_att_proprietary=Proprietary\nUse Pursuant to Company Instructions
-pdf_att_proprierary_font_size=7
-pdf_date_timezone=GMT
-pdf_date_pattern=MM/dd/yyyy hh:mm:ss a
-##page number position at 1 - footer middle, 0 -- header right, 2 - both
-pdf_page_number_position=1
-pdf_word_before_page_number=Page
-pdf_word_after_page_number=
-pdf_coverpage_firstcolumn_size=0.3
-pdf_image_auto_rotate=false
-display_create_owner_info=true
-#session_info=customer,customerId
-display_loginid_for_downloaded_by=false
-# please use false if you want landscape to be default.
-is_default_orientation_portrait=true
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/system.properties b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/system.properties
deleted file mode 100644
index 84e641b7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/conf/system.properties
+++ /dev/null
@@ -1,86 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
-# Properties read by ECOMP Core library, ecompSDK-core.jar
-
-##########################################################################
-# The following properties should NOT be changed by partner applications.
-##########################################################################
-
-application_user_id = 30000
-post_default_role_id = 16
-clustered = true
-
-#Enable Fusion Mobile capabilities for the application
-mobile_enable = false
-
-# Cache config file is needed on the classpath
-cache_config_file_path = /WEB-INF/classes/cache.ccf
-cache_switch = 199
-cache_load_on_startup = false
-
-user_name = fullName
-decryption_key = AGLDdG4D04BKm2IxIWEr8o==
-
-##########################################################################
-# The following properties MAY require changes by partner applications.
-##########################################################################
-
-#Mysql
-db.driver = com.mysql.jdbc.Driver
-db.connectionURL = jdbc:mysql://localhost:3306/ecomp_sdk_os
-db.userName = xxxx
-db.password = xxxxxxxx
-db.min_pool_size = 5
-db.max_pool_size = 10
-hb.dialect = org.hibernate.dialect.MySQLDialect
-# SQL statements are logged to stdout
-hb.show_sql = true
-hb.idle_connection_test_period = 3600
-
-app_display_name = Demo App
-files_path = /tmp
-
-#element map files
-element_map_file_path = /tmp
-element_map_icon_path = app/fusionapp/icons/
-
-#Cron Schedules
-log_cron = 0 0/1 * * * ?;
-mylogins_feed_cron = 0 0/60 * * * ?;
-#sessiontimeout_feed_cron = 0 * * * * ? *
-my_login_feed_output_dir = /tmp/MyLogins
-
-# ECOMP Portal Shared Context REST API URL
-ecomp_shared_context_rest_url= http://todo_enter_be_hostname:9000/ecompportal/context
-# Link shown in Help menu
-contact_us_link = https://todo_contact_us_link.com
-
-# An Unique 128-bit value defined to identify a specific version
-# of an application deployed on a specific virtual machine.
-# This value must be generated and updated by the application
-# which is using the ECOMP SDK at the time of its deployment.
-# Online Unique UUID generator - https://www.uuidgenerator.net/
-instance_uuid=8da691c9-987d-43ed-a358-00ac2f35685d
-
-# R Cloud feature - configure this property to enable notebook feature - for more details on RCloud please visit https://rcloud.social/index.html
-guard_notebook_url=
-
-#authenticate user server
-authenticate_user_server=http://todo_enter_auth_server_hostname:8383/openid-connect-server-webapp/allUsers
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/defs/definitions.xml b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/defs/definitions.xml
deleted file mode 100644
index 6c582777..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/defs/definitions.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE tiles-definitions PUBLIC
- "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
- "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
-
-<!-- This tiles definitions file is defs/definitions.xml. It maps
- tokens used by example SDK-app controllers to JSP file paths.
- Applications that use JSP pages should modify this file. -->
-
-<tiles-definitions>
-
- <definition extends="ebz_template" name="leafletMap">
- <put-attribute name="body" value="/WEB-INF/jsp/leafletMap.jsp"></put-attribute>
- </definition>
-
- <definition name="drools"
- template="/app/fusionapp/drools/view-models/droolsSinglePage.html" />
-
- <definition name="single_page_sample"
- template="/app/fusionapp/scripts/view-models/singlePageSample.html" />
-
-</tiles-definitions>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/conf/fusion.properties b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
deleted file mode 100644
index b2cef9f8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/conf/fusion.properties
+++ /dev/null
@@ -1,61 +0,0 @@
-###
-# ================================================================================
-# eCOMP Portal SDK
-# ================================================================================
-# Copyright (C) 2017 AT&T Intellectual Property
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ================================================================================
-###
-
-
-# validator settings
-#default_error_message = Default error message
-
-#login message
-login.error.hrid.empty = Login failed, please contact system administrator.
-login.error.hrid.not-found = User not found, please contact system administrator.
-login.error.user.inactive = Account is disabled, please contact system administrator.
-
-authentication_mechanism = BOTH
-
-user_attribute_name = user
-
-# User Session settings
-#user_attribute_name = user
-roles_attribute_name = roles
-role_functions_attribute_name = role_functions
-#client_device_attribute_name = client_device
-#client_device_emulation = false
-
-
-# menu settings
-menu_query_name = menuData
-#menu_properties_file_location = /WEB-INF/fusion/menu/
-application_menu_set_name = APP
-application_menu_attribute_name = applicationMenuData
-#application_menu_properties_name = menu.properties
-business_direct_menu_set_name = BD
-#business_direct_menu_properties_name = bd.menu.properties
-business_direct_menu_attribute_name = businessDirectMenuData
-
-# RAPTOR config settings
-#raptor_config_file_path = /WEB-INF/conf/
-
-# Role settings
-sys_admin_role_id = 1
-#sys_admin_role_function_delete_from_ui = true
-
-# Profile Search settings
-#profile_search_report_id=181
-#callable_profile_search_report_id=386
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/defs/definitions.xml b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/defs/definitions.xml
deleted file mode 100644
index fb18cb79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/defs/definitions.xml
+++ /dev/null
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE tiles-definitions PUBLIC
- "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
- "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
-
-<!-- This tiles definitions file is fusion/defs/definitions.xml. It maps
- tokens used by SDK-core controllers to JSP file paths. To minimize upgrade
- effort, this file should not be changed by on-boarding applications. -->
-
-<tiles-definitions>
-
- <definition name="ebz_template" template="/WEB-INF/fusion/jsp/ebz_template.jsp">
- <put-attribute name="title" value=""></put-attribute>
- <put-attribute name="header"
- value="/WEB-INF/fusion/jsp/ebz/ebz_header.jsp"></put-attribute>
- <put-attribute name="body" value=""></put-attribute>
- <put-attribute name="footer"
- value="/WEB-INF/fusion/jsp/ebz/ebz_footer.jsp"></put-attribute>
- </definition>
-
- <definition name="ebz_template_noheader_nofooter"
- template="/WEB-INF/fusion/jsp/ebz_template_noheader_nofooter.jsp">
- <put-attribute name="body" value=""></put-attribute>
- </definition>
-
- <definition name="ebz_template_report_embedded"
- template="/WEB-INF/fusion/jsp/ebz_template_report_embedded.jsp">
- <put-attribute name="body" value=""></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="es_search_demo">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/es_search_demo.jsp"></put-attribute>
- <put-attribute name="viewName" value="elastic_search"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="es_suggest_demo">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/es_suggest_demo.jsp"></put-attribute>
- <put-attribute name="viewName" value="elastic_search"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="user_profile">
- <put-attribute name="body" value="/WEB-INF/jsp/user_profile.jsp"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="profile_search">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/profile_search.jsp"></put-attribute>
- <put-attribute name="viewName" value="profile_search"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="profile">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/profile.jsp"></put-attribute>
- <put-attribute name="viewName" value="profile"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="menu">
- <put-attribute name="body" value="/WEB-INF/jsp/menu.jsp"></put-attribute>
- <put-attribute name="viewName" value="menu"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="welcome">
- <put-attribute name="body" value="/WEB-INF/jsp/welcome.jsp"></put-attribute>
- <put-attribute name="viewName" value="welcome"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="role_list">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/role_list.jsp"></put-attribute>
- <put-attribute name="viewName" value="role_list"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="role">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/role.jsp"></put-attribute>
- <put-attribute name="viewName" value="role"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="role_function_list">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/role_function_list.jsp"></put-attribute>
- <put-attribute name="viewName" value="role_function_list"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="post_search">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/post_search.jsp"></put-attribute>
- <put-attribute name="viewName" value="post_search"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="error">
- <put-attribute name="body" value="/WEB-INF/jsp/error.jsp"></put-attribute>
- <put-attribute name="viewName" value="error"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="collaborate_list">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/collaborateList.jsp"></put-attribute>
- </definition>
-
- <!-- <definition extends="ebz_template" name="notebook">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/notebook.jsp"></put-attribute>
- </definition> -->
-
- <definition name="notebook"
- template="app/fusion/notebook-integration/scripts/view-models/notebook.htm" />
-
-
- <definition name="nbooktest"
- template="app/fusion/notebook-integration/scripts/view-models/notebook-frame.html"/>
-
-
- <definition extends="ebz_template" name="jcs_admin">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/jcs_admin.jsp"></put-attribute>
- <put-attribute name="viewName" value="jcs_admin"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="usage_list">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/usage_list.jsp"></put-attribute>
- <put-attribute name="viewName" value="usage_list"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="broadcast_list">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/broadcast_list.jsp"></put-attribute>
- <put-attribute name="viewName" value="broadcast_list"></put-attribute>
- </definition>
- <definition extends="ebz_template" name="broadcast">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/broadcast.jsp"></put-attribute>
- <put-attribute name="viewName" value="broadcast"></put-attribute>
- </definition>
-
-
- <definition extends="ebz_template" name="chart_wizard">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/chart_wizard.jsp"></put-attribute>
- <put-attribute name="viewName" value="chart_wizard"></put-attribute>
- </definition>
-
- <!-- <definition extends="ebz_template_noheader_nofooter" name="collaboration">
- <put-attribute name="body" value="/WEB-INF/fusion/jsp/webrtc/collaboration.jsp"></put-attribute>
- </definition> -->
- <definition name="collaboration"
- template="/WEB-INF/fusion/jsp/webrtc/collaboration.jsp" />
- <definition name="user_profile_list"
- template="/app/fusion/scripts/view-models/admin-page/profile.html" />
- <definition name="admin"
- template="/app/fusion/scripts/view-models/admin-page/admin.html" />
- <definition name="workflows"
- template="/app/fusion/scripts/view-models/workflows/workflow-landing.html" />
-
- <definition extends="ebz_template" name="report_wizard">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/report_wizard.jsp"></put-attribute>
- <put-attribute name="viewName" value="report_wizard"></put-attribute>
- </definition>
- <definition extends="ebz_template" name="wizard_schedule_only">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/wizard_schedule_only.jsp"></put-attribute>
- <put-attribute name="viewName" value="wizard_schedule_only"></put-attribute>
- </definition>
-
- <definition extends="ebz_template" name="report_import">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/report_import.jsp"></put-attribute>
- <put-attribute name="viewName" value="report_import"></put-attribute>
- </definition>
-
-
- <definition extends="ebz_template" name="report">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/report_ebz.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_report_embedded" name="report_embedded">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/report_ebz.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template" name="report_sample">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/report_sample.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="test_run_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/test_run_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="date_start_field_run_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/date_start_field_run_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="date_end_field_run_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/date_end_field_run_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="test_field_run_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/test_field_run_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="default_field_run_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/default_field_run_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_testrun_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_testrun_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_semaphore">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_semaphore.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_import_semaphore">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_import_semaphore.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_table_cols">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_table_cols.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_drill_down_report">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_drill_down_report.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template_noheader_nofooter" name="popup_sql">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/popup_sql.jsp"></put-attribute>
- </definition>
- <definition extends="ebz_template" name="error_page">
- <put-attribute name="body"
- value="/WEB-INF/fusion/raptor/error_page.jsp"></put-attribute>
- </definition>
- <definition name="data_out" template="/WEB-INF/fusion/jsp/data_out.jsp" />
-
- <definition extends="ebz_template" name="frame_insert">
- <put-attribute name="body"
- value="/WEB-INF/fusion/jsp/frame_insert.jsp"></put-attribute>
- </definition>
-
- <!-- <definition name="test_field_run_sql" template="/WEB-INF/fusion/raptor/test_field_run_sql.jsp"/>
- <definition name="popup_testrun_sql" template="/WEB-INF/fusion/raptor/popup_testrun_sql.jsp"/> -->
-
-</tiles-definitions>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/collaborateList.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/collaborateList.jsp
deleted file mode 100644
index b1fbfab1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/collaborateList.jsp
+++ /dev/null
@@ -1,146 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<div>
-<a href="JavaScript:void(0);" style= "color:#00547A" onClick="downloadScreenCaptureExtenstion()" id="install-button">
- Please download the extension for ScreenCapture and refresh page</a>
- </div>
-<div ng-controller="collaborateListController" id="collaborate_ctrl">
- <div>
- <h1 class="heading1" style="margin-top:20px;">User List</h1>
- <div style="margin-top:30px">
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">User ID</th>
- <th att-table-header key="lastName">Last Name</th>
- <th att-table-header key="firstName">First Name</th>
- <th att-table-header key="email">Email</th>
- <th att-table-header key="orgUserId">UserId</th>
- <th att-table-header key="online" default-sort="d">Online/Offline</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body ng-bind="rowData['id']"></td>
- <td att-table-body ng-bind="rowData['lastName']"></td>
- <td att-table-body ng-bind="rowData['firstName']"></td>
- <td att-table-body ng-bind="rowData['email']"></td>
- <td att-table-body ng-bind="rowData['orgUserId']"></td>
- <td att-table-body >
- <tag-badges ng-hide="rowData.online" style-type="color" class="lred" ng-click="rowData.isActive=true;openCollaboration(rowData.chatId)">Offline</tag-badges>
- <tag-badges ng-show="rowData.online" style-type="color" class="lgreen" ng-click="rowData.isActive=false;openCollaboration(rowData.chatId)">Online</tag-badges>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage" size="5" readonly="true" style="width: 47px;">
- </div>
-
-
-</div>
-
-
-<!-- handling websocket peer broadcast session -->
- <script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
- <script type="text/javascript" src="app/fusion/external/utils/js/browserCheck.js"></script>
- <script>
-
- var initialPageVisit = "${sessionScope.initialPageVisit}";
- var userId = "${sessionScope.user.orgUserId}";
- socketSetup(initialPageVisit, userId, null, "socketSend");
-
-
- </script>
-
-<script>
-var popupModalService;
-app.controller("collaborateListController", function ($scope,$http,modalService, $modal) {
- // Table Data
- $scope.tableData=${model.profileList};
- $scope.viewPerPage = 20;
- $scope.scrollViewsPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- popupModalService = modalService;
- setPopupService(modalService);
- /* modalService.showSuccess('','Modal Sample') ; */
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- $scope.openCollaboration = function(chatId){
- openInNewTab('collaboration?chat_id=' + chatId);
-
- }
-
- $scope.toggleProfileActive = function(profileId) {
- if (confirm("You are about to change user's active status. Do you want to continue?")) {
- $http.get("profile/toggleProfileActive?profile_id="+profileId).success(function(){});
- }
- };
-
-});
-
-function openInNewTab(url) {
-
- //popupModalService.popupConfirmWin("Confirm","");
- var win = window.open(url, '_blank');
- win.popupService = popupModalService;
- win.focus();
-};
-
-function downloadScreenCaptureExtenstion() {
-
- var chromeURL = 'https://chrome.google.com/webstore/detail/icgmlogfeajbfdffajhoebcfbibfhaen';
- var firefoxURL = 'https://addons.mozilla.org/en-US/firefox/addon/screen-capturing-capability';
- var url;
-
- if(isChrome)
- url = chromeURL;
- else if(isFirefox)
- url = firefoxURL;
-
- var win = window.open(url);
- win.focus();
-};
-
-</script>
-
-
-
- <div id="peerBroadcastSection"> </div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html
deleted file mode 100644
index 0f29ee77..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/ebz/loginSnippet.html
+++ /dev/null
@@ -1,120 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<script type="text/ng-template" id="loginSnippet.html">
- <div style="line-height: normal; right: 167px; min-height: 200px; height: auto; width: auto; " ng-controller="loginSnippetCtrl" >
- <div id="reg-header-snippet">
- <div class="reg-profilePicture" style="min-height: 215px; width: auto; " id="reg-profile-links">
- <div id="reg-profileImage">
- <div style="clear: both; height: 80px; position: relative; width: 80px;">
-
- <span style=" background-position: -1px -1px; height: 81px;left: 0;position: absolute;top: 0;width: 81px;">&nbsp;</span>
- </div>
- </div>
- <div id="reg-logout-div">
- <a class="reg-logout-btn" href="logout.htm">Log Out</a>
- </div>
- </div>
- <div tabindex="0" class="reg-profileDetails" id="reg-profiledetails-id">
- <ul class="reg-Details-table" style="list-style: none;">
- <li><div class="reg-userName-table"><div id="reg-userName-table-row"><div id="reg-userName-table-cell"><h3 class="att-global-fonts" id="reg-userName" ng-bind="userProfile.fullName"></h3><span class="visuallyhidden">.</span></div></div></div></li>
- <li><div class="reg-userEmail-label"><span class="reg-userEmail-label-spn">EMAIL<span class="visuallyhidden">:</span></span></div></li>
- <li><div class="reg-userEmail-value"><span class="reg-userEmail-value-spn" ng-bind="userProfile.email"><span class="visuallyhidden">.</span></span></div></li>
- <li><div class="reg-userRole-label"><span class="reg-userRole-label-spn">User ID<span class="visuallyhidden">:</span></span></div></li>
- <li><div class="reg-userRole-value"><span class="reg-userRole-value-spn" ng-bind="userProfile.orgUserId"><span class="visuallyhidden"></span></span></div></li>
- </ul>
- </div>
- </div>
- </div>
- </script>
- <script type="text/ng-template" id="chat_box.html">
-
- <div style="width: auto;">
-
- <div style="font-size: 24px; font-family: omnes_attregular;line-height: 26px;color: #444444;text-align: center;">
- <span>Live Chat</span>
- </div>
- <div style="line-height:15px; padding-left:20px; padding-right:20px;">
- Chat is currently unavailable.<br><br>
-
- </div>
- </div>
- </script>
-
-<script>
-var loginSnippetCtrl = function ($scope,$http, $log,UserInfoService){
- /*Define fields*/
- $scope.userProfile={
- firstName:'',
- lastName:'',
- fullName:'',
- email:''
- }
- /*Put user info into fields*/
- $scope.inputUserInfo = function(userInfo){
- if (typeof(userInfo) != "undefined" && userInfo!=null && userInfo!=''){
- if (typeof(userInfo.USER_FIRST_NAME) != "undefined" && userInfo.USER_FIRST_NAME!=null && userInfo.USER_FIRST_NAME!='')
- $scope.userProfile.firstName = userInfo.USER_FIRST_NAME;
- if (typeof(userInfo.USER_LAST_NAME) != "undefined" && userInfo.USER_LAST_NAME!=null && userInfo.USER_LAST_NAME!='')
- $scope.userProfile.lastName = userInfo.USER_LAST_NAME;
- if (typeof(userInfo.USER_EMAIL) != "undefined" && userInfo.USER_EMAIL!=null && userInfo.USER_EMAIL!='')
- $scope.userProfile.email = userInfo.USER_EMAIL;
- if (typeof(userInfo.USER_ORGUSERID) != "undefined" && userInfo.USER_ORGUSERID!=null && userInfo.USER_ORGUSERID!='')
- $scope.userProfile.orgUserId = userInfo.USER_ORGUSERID;
- }
- }
- /*getting user info from session*/
- $scope.getUserNameFromSession = function(){
- UserInfoService.getFunctionalMenuStaticDetailSession()
- .then(function (response) {
- var j = response;
- console.log(response);
- $scope.userProfile.fullName = response.userName;
- $scope.userProfile.orgUserId = response.orgUserId;
- $scope.userProfile.email = response.email;
- });
- }
- /*getting user info from shared context*/
- $scope.getUserName=function() {
- var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
- promise.then(
- function(res) {
- if(res==null || res==''){
- $log.info('Getting User information from session');
- $scope.getUserNameFromSession();
- }else{
- $log.info('Received User information from shared context',res);
- var resData = res;
- $scope.inputUserInfo(resData);
- $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
- }
- },
- function(err) {
- console.log('error');
- }
- );
- };
- /*call the get user info function*/
- try{
- $scope.getUserName();
- }catch(err){
- $log.info('Error while getting User information',err);
- }
-}
- </script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/jcs_admin.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/jcs_admin.jsp
deleted file mode 100644
index 845beac2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/jcs_admin.jsp
+++ /dev/null
@@ -1,144 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%-- <%@ include file="/WEB-INF/fusion/jsp/include.jsp"%> --%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-
-<div align="left" ng-controller="cacheAdminController">
- <div class="pageTitle"><h3>Cache Regions</h3></div>
- These are the regions which are currently defined in the cache. 'Items' and 'Bytes' refer to the elements currently in memory (not spooled).
- You can clear all items for a region by clicking on the Clear icon next to the desired region below. You can also <a href="#" ng-click="clearAll();">clear all regions</a> which
- empties the entire cache. <br /><br />
-
- <div style="width: 97%; border-top: 1px solid #c4c4c4; margin-top: 0px; background-color: #fff; padding: 10px 0; color: #646464s">
- <div style="margin: 0 20px 10px 0px; font-size: 80%; float: left; width: 97%;">
- <div class="col-md-4"><b>Cache Name</b></div>
- <div class="col-md-2"><b># of Items</b></div>
- <div class="col-md-2"><b>Bytes</b></div>
- <div class="col-md-2"><b>Status</b></div>
- <div class="col-md-3"><b>Memory Hits</b></div>
- <div class="col-md-3"><b>Aux Hits</b></div>
- <div class="col-md-3"><b>Not Found Misses</b></div>
- <div class="col-md-3"><b>Expired Misses</b></div>
- <div class="col-md-1"><b>Clear?</b></div>
- <div class="col-md-1"><b>Items</b></div>
- </div>
- <div ng-repeat="region in regions">
- <div style="margin: 0 20px 10px 0px; font-size: 80%; float: left; width: 97%;">
- <div class="col-md-4"><a href="#" tooltip="Click to Show Region Details" ng-click="showRegionDetails(region.cacheName);">{{region.cacheName}}</a></div>
- <div class="col-md-2">{{region.size}}</div>
- <div class="col-md-2">{{region.byteCount}}</div>
- <div class="col-md-2">{{region.status}}</div>
- <div class="col-md-3">{{region.hitCountRam}}</div>
- <div class="col-md-3">{{region.hitCountAux}}</div>
- <div class="col-md-3">{{region.missCountNotFound}}</div>
- <div class="col-md-3">{{region.missCountExpired}}</div>
- <div class="col-md-1">
- <div ng-click="clearRegion(region.cacheName);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </div>
- <div class="col-md-1"><span class="att--tree__plus col-md-1" ng-class="{minus: bling$index}" ng-click="bling$index = !bling$index" style="display: block;"></span></div>
- </div>
- <div style="margin: 0px 20px 0px 30px; font-size: 80%; float: left; width: 95%; border-top: 1px solid #e4e4e4; padding-top: 10px"
- ng-show="bling$index">
- <span class="att--tree__arrow" style="height: 20px; width: 20px; display: inline-block; float: left"></span>
- <div class="col-md-12"><b>Key</b></div>
- <div class="col-md-2"><b>Eternal?</b></div>
- <div class="col-md-4"><b>Created</b></div>
- <div class="col-md-2"><b>Max Life</b></div>
- <div class="col-md-2"><b>Expires</b></div>
- <div class="col-md-1"><b>Clear?</b></div>
- </div>
- <div ng-repeat="item in region.items">
- <div style="margin: 0px 20px 0px 30px; font-size: 80%; float: left; width: 95%;" ng-show="bling$index">
- <span class="att--tree__arrow" style="height: 20px; width: 20px; display: inline-block; float: left"></span>
- <div class="col-md-12"><a href="#" tooltip="Click to Show Item Details" ng-click="showItemDetails(region.cacheName,item.key);">{{item.key}}</a></div>
- <div class="col-md-2">{{item.eternal}}</div>
- <div class="col-md-4">{{item.createTime}}</div>
- <div class="col-md-2">{{item.maxLifeSeconds}}</div>
- <div class="col-md-2">{{item.expiresInSeconds}}</div>
- <div class="col-md-1">
- <div ng-click="clearItem(region.cacheName,item.key);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </div>
- </div>
- </div>
- <div style="clear: both"></div>
- </div>
- </div>
-</div>
-
-<script>
-app.controller('cacheAdminController', function ($scope,$interval,$http,$modal,modalService){
- $scope.regions=${model};
-
- $scope.clearAll = function() {
- modalService.popupConfirmWin("Confirm",'You are about to clear all of the items for all cache regions. Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearAll").success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.clearRegion = function(cacheName) {
- modalService.popupConfirmWin("Confirm",'You are about to clear all of the items in the cache region "' + cacheName + '". Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearRegion?cacheName="+cacheName).success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.clearItem = function(cacheName,key) {
- modalService.popupConfirmWin("Confirm",'You are about to clear this item from the cache region "' + cacheName + '". Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearItem?keyName="+key+"&cacheName="+cacheName).success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.showRegionDetails = function(cacheName) {
- $http.get("jcs_admin/showRegionDetails?cacheName="+cacheName).success(function(response){modalService.showSuccess('',response);});
- };
-
- $scope.showItemDetails = function(cacheName,key) {
- $http.get("jcs_admin/showItemDetails?keyName="+key+"&cacheName="+cacheName).success(function(response){
- var message = "CacheName: "+ response.cacheName
- +"\nkey: "+response.key
- +"\nIS_SPOOL: "+response.attr.IS_SPOOL
- +"\nIS_LATERAL: "+response.attr.IS_LATERAL
- +"\nIS_REMOTE: "+response.attr.IS_REMOTE
- +"\nIS_ETERNAL: "+response.attr.IS_ETERNAL
- +"\nversion: "+response.attr.version
- +"\nmaxLifeSeconds: "+response.attr.maxLifeSeconds
- +"\nmaxIdleTimeSeconds: "+response.attr.maxIdleTimeSeconds
- +"\nsize: "+response.attr.size
- +"\ncreateTime: "+response.attr.createTime
- +"\nlastAccessTime: "+response.attr.lastAccessTime
- +"\nidleTime: "+response.attr.idleTime
- +"\ntimeToLiveSeconds: "+response.attr.timeToLiveSeconds
- +"\nisSpool: "+response.attr.isSpool
- +"\nisLateral: "+response.attr.isLateral
- +"\nisRemote: "+response.attr.isRemote
- +"\nisEternal: "+response.attr.isEternal;
- modalService.showSuccess('',message);});
- };
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/post_search.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/post_search.jsp
deleted file mode 100644
index 94d4b0bf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/post_search.jsp
+++ /dev/null
@@ -1,356 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ page import="java.util.*" %>
-<%@ page import="com.fasterxml.jackson.databind.ObjectMapper" %>
-<%@ page import="org.json.JSONObject" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal_rolefunction.html" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal_role.html" %>
-<link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
-
-<div ng-controller="postSearchController" >
-
-<h1 class="heading1" style="margin-top:20px;">WEBPHONE Search</h1>
- <br>
- Please enter search criteria below:<br/>
-
- <div class="fn-ebz-container">
- Last Name:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.lastName" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- First Name:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.firstName" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- UserId:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgUserId" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Manager OrgUserId:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgManagerUserId" value="" size="25">
- </div>
- <br>
- <div class="fn-ebz-container">
- Organization:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgCode" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Email:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.email" value="" size="25">
- </div>
- <br>
-<!-- Sort By: <br/>
- <div class="fn-ebz-container" >
-
- <div class="fn-ebz-container">
- <div class="form-field" att-select="sortByList" ng-model="postSearchBean.sortBy1"></div>
- </div>
- </div>
-
-
-
-
- <div class="fn-ebz-container" >
- <br/>
- &nbsp;
-
- <div class="fn-ebz-container">
- <div class="form-field" att-select="sortByList" ng-model="postSearchBean.sortBy2"></div>
- </div>
- </div>
-
-
- <div class="fn-ebz-container" >
- <br/> &nbsp;
-
- <div class="fn-ebz-container">
- <div class="form-field" att-select="sortByList" ng-model="postSearchBean.sortBy3"></div>
- </div>
- </div> -->
- <div>
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Search" ng-click="search(postSearchBean);" />
-
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Reset" ng-click="reset();"/>
- </div>
- <br>
- {{noResultsString}}
- <div ng-if="profileList.length != 0">
- <table att-table table-data="profileList" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header" >
- <tr>
- <th att-table-header width="5%" align="left">No</th>
- <th att-table-header width="30%" key="lastName" align="left">Name</th>
- <th att-table-header width="5%" key="orgUserId" align="left">OrgUserId</th>
- <th att-table-header width="10%" key="orgCode" align="left">Organization</th>
- <th att-table-header width="20%" align="left">Phone</th>
- <th att-table-header width="20%" key="email" align="left">Email</th>
- <th att-table-header width="10%" align="left">Import?</th>
- </tr>
- </thead>
-
- <tbody att-table-row type="body" row-repeat="profile in profileList" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr >
- <td att-table-body width="5%" align="left">
- {{$index + 1}}
- </td>
- <td att-table-body width="30%" align="left">
- <div ng-if="ngexistingUsers[profile.orgUserId] == null">
- {{profile.lastName}},&nbsp;{{profile.firstName}}
- </div>
- <div ng-if="ngexistingUsers[profile.orgUserId] != null">
- <a href="profile.htm?profile_id={{ngexistingUsers[profile.orgUserId]}}" alt="View/Edit Profile">
- {{profile.lastName}},&nbsp;{{profile.firstName}}
- </a>
- </div>
-
- </td>
- <td att-table-body width="5%" align="left">
- {{profile.orgUserId}}
- </td>
- <td att-table-body width="10%" align="left">
- {{profile.orgCode}}
- </td>
- <td att-table-body width="20%" align="left">
- {{profile.phone}}
- </td>
- <td att-table-body width="20%" align="left">
- {{profile.email}}
- </td>
-
- <td att-table-body width="10%" align="left">
- <div ng-if="ngexistingUsers[profile.orgUserId] == null">
- <div ng-click="toggleSelection(profile);">
- <input name="selected" type="checkbox" ng-model="profile.selected" att-checkbox/>
- </div>
- </div>
- <div ng-if="ngexistingUsers[profile.orgUserId] != null">
- Exists
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage" size="5" readonly="true" style="width: 47px;">
- </div>
-
- <div ng-if="profileList.length != 0">
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Import" ng-click="process();"/>
- </div>
-
- </div>
-
-
-
-
-</div>
-<script>
- app.controller('postSearchController', function ($scope,modalService){
-
- $scope.viewPerPage = 200;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
-
- $scope.noResultsString = "";
-
- $scope.postSearchBean=${postSearchBean};
- $scope.profileList=${profileList};
- //console.log($scope.postSearchBean);
-
- $scope.ngexistingUsers=${existingUsers};
- console.log($scope.ngexistingUsers);
-
- $scope.ocisortByList=${sortByList};
- $scope.sortByList = [];
- if($scope.ocisortByList)
- $.each($scope.ocisortByList, function(i, a){
- var sortBy = {"index":i, "value":a.value, "title":a.label};
- $scope.sortByList.push(sortBy);
- });
- ;
-
- $scope.search = function(postSearchBean) {
- console.log(postSearchBean);
- var uuu = "post_search/search";
- var postData={postSearchBean:postSearchBean};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profileList=data.postSearchBean.searchResult;
- //$scope.postSearchBean={};
- console.log($scope.profileList);
- if($scope.profileList.length == 0)
- $scope.noResultsString = "There is currently no one in WEBPHONE matching your search criteria.";
- else
- $scope.noResultsString = "";
- });
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while searching: "+ data.responseText);
- }
- });
-
- };
-
- $scope.reset = function() {
- $scope.postSearchBean={};
- $scope.profileList=[];
- $scope.noResultsString = "";
- //console.log($scope.postSearchBean);
- };
-
- $scope.process = function() {
- $scope.prepareProfileSelection();
- var uuu = "post_search/process";
- var postData={postSearchBean:$scope.postSearchBean};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profileList=data.postSearchBean.searchResult;
- //$scope.postSearchBean={};
- $scope.ngexistingUsers=data.existingUsers;
- $scope.postSearchBean.selected=null;
- });
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while searching: "+ data.responseText);
- }
- });
-
- };
- $scope.importProfileList=[];
- $scope.toggleSelection = function(profile) {
- if(profile.selected)
- $scope.importProfileList.push(profile);
- else{
- var index = $scope.importProfileList.indexOf(profile);
- if(index>=0)
- $scope.importProfileList.splice(index, 1);
- }
- };
-
- $scope.prepareProfileSelection = function() {
- if($scope.importProfileList)
- $.each($scope.importProfileList, function(i, profile){
- $scope.preparePostSearchBean(profile);
- });
- ;
- }
-
- $scope.preparePostSearchBean = function(profile) {
- //console.log('Importing: '+profile.orgUserId);
- //console.log('ngexistinguser:'+$scope.ngexistingUsers[profile.orgUserId])
- if($scope.postSearchBean.selected==null){
- $scope.postSearchBean.selected=[];
- $scope.postSearchBean.postOrgUserId=[];
- $scope.postSearchBean.postHrid=[];
- $scope.postSearchBean.postFirstName=[];
- $scope.postSearchBean.postLastName=[];
- $scope.postSearchBean.postOrgCode=[];
- $scope.postSearchBean.postPhone=[];
- $scope.postSearchBean.postEmail=[];
- $scope.postSearchBean.postAddress1=[];
- $scope.postSearchBean.postAddress2=[];
- $scope.postSearchBean.postCity=[];
- $scope.postSearchBean.postState=[];
- $scope.postSearchBean.postZipCode=[];
- $scope.postSearchBean.postLocationClli=[];
- $scope.postSearchBean.postBusinessCountryCode=[];
- $scope.postSearchBean.postBusinessCountryName=[];
- $scope.postSearchBean.postDepartment=[];
- $scope.postSearchBean.postDepartmentName=[];
- $scope.postSearchBean.postBusinessUnit=[];
- $scope.postSearchBean.postBusinessUnitName=[];
- $scope.postSearchBean.postJobTitle=[];
- $scope.postSearchBean.postOrgManagerUserId=[];
- $scope.postSearchBean.postCommandChain=[];
- $scope.postSearchBean.postCompanyCode=[];
- $scope.postSearchBean.postCompany=[];
- $scope.postSearchBean.postCostCenter=[];
- $scope.postSearchBean.postSiloStatus=[];
- $scope.postSearchBean.postFinancialLocCode=[];
- }
-
- $scope.postSearchBean.selected.push(profile.orgUserId);
- $scope.postSearchBean.postOrgUserId.push(profile.orgUserId);
- $scope.postSearchBean.postHrid.push(profile.hrid);
- $scope.postSearchBean.postFirstName.push(profile.firstName);
- $scope.postSearchBean.postLastName.push(profile.lastName);
- $scope.postSearchBean.postOrgCode.push(profile.orgCode);
- $scope.postSearchBean.postPhone.push(profile.phone);
- $scope.postSearchBean.postEmail.push(profile.email);
- $scope.postSearchBean.postAddress1.push(profile.address1);
- $scope.postSearchBean.postAddress2.push(profile.address2);
- $scope.postSearchBean.postCity.push(profile.city);
- $scope.postSearchBean.postState.push(profile.state);
- if(profile.zipCodeSuffix==null)
- $scope.postSearchBean.postZipCode.push(profile.zipCode);
- else
- $scope.postSearchBean.postZipCode.push(profile.zipCode+'-'+profile.zipCodeSuffix);
- $scope.postSearchBean.postLocationClli.push(profile.locationClli);
- $scope.postSearchBean.postBusinessCountryCode.push(profile.businessCountryCode);
- $scope.postSearchBean.postBusinessCountryName.push(profile.businessCountryName);
- $scope.postSearchBean.postDepartment.push(profile.department);
- $scope.postSearchBean.postDepartmentName.push(profile.departmentName);
- $scope.postSearchBean.postBusinessUnit.push(profile.businessUnit);
- $scope.postSearchBean.postBusinessUnitName.push(profile.businessUnitName);
- $scope.postSearchBean.postJobTitle.push(profile.jobTitle);
- $scope.postSearchBean.postOrgManagerUserId.push(profile.orgManagerUserId);
- $scope.postSearchBean.postCommandChain.push(profile.commandChain);
- $scope.postSearchBean.postCompanyCode.push(profile.companyCode);
- $scope.postSearchBean.postCompany.push(profile.company);
- $scope.postSearchBean.postCostCenter.push(profile.costCenter);
- $scope.postSearchBean.postSiloStatus.push(profile.siloStatus);
- $scope.postSearchBean.postFinancialLocCode.push(profile.financialLocCode);
- };
-
- });
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile.jsp
deleted file mode 100644
index b01fa6b8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile.jsp
+++ /dev/null
@@ -1,442 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ page import="org.openecomp.portalsdk.core.domain.User"%>
-<%@ page import="org.openecomp.portalsdk.core.web.support.UserUtils"%>
-
-<%@page import="org.openecomp.portalsdk.core.web.support.ControllerProperties"%>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
-<link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
-<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-
-<%@ include file="/WEB-INF/fusion/jsp/include.jsp"%>
-
-<div class="pageTitle">
- <h3>
- <c:choose>
- <c:when test="${!empty profileId}">
- <h1 class="heading1" style="margin-top:20px;">Profile Edit</h1>
- </c:when>
- <c:otherwise>
- <h1 class="heading1" style="margin-top:20px;">Profile Edit</h1>
- </c:otherwise>
- </c:choose>
- </h3>
-</div>
-
-<div ng-controller="profileController" >
-
- Please edit the profile details below:&nbsp;<br><br>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>First Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.firstName"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Last Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.lastName"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">OrgUserId:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgUserId"
- maxlength="30" style="margin-right:0px;"/>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Manager OrgUserId:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgManagerUserId"
- maxlength="30" style="margin-right:0px;"/>
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Login Id:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.loginId"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" style="margin-right:20px">
- <label class="fn-ebz-text-label">Password:</label><BR>
- <input type="password" ng-model="profile.loginPwd"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Phone:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.phone"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Fax:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.fax"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Cellular:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.cellular"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Email:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.email"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 1:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address1"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 2:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address2"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">City:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.city"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">State:</label><BR>
- <div class="form-field" att-select="stateList.options" ng-model="stateList.selected"></div>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Zip Code:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.zipCode"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Country:</label><BR>
- <div class="form-field" att-select="countries" ng-model="selectedCountry"></div>
- </div>
- <BR>
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Time Zone:</label><BR>
- <div class="form-field" att-select="timeZones" ng-model="selectedTimeZone"></div>
- </div>
-
- <div align="left" >
- <button type="submit" ng-click="saveProfile();" att-button
- btn-type="primary" size="small">Save</button>
- </div>
-
-<br>
- <div class="pageTitle">
- <label>Roles</label>
- <a ng-click="addNewRolePopup();" class="ion-plus-round" size="small"></a>
-
- </div>
-
- <table att-table table-data="profile.roles" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-<!-- <table border="1" class="hovertable_1"> -->
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="role in profile.roles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
-<!-- <tr ng-repeat="role in profile.roles track by role.id"> -->
- <tr>
- <td att-table-body width="90%" >{{ role.name }}</td>
- <td att-table-body width="10%">
- <a ng-click="removeRole(role);" ><img src="static/fusion/images/deleteicon.gif"></a>
- </td>
- </tr>
- </tbody>
- </table>
-
- <div id="dialog" style="overflow:scroll" class="modal__informative font-showcase" >
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="color:#157BB2">Select Roles</h2>
- </div>
- <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- <div class="divider-container"><hr></div>
- <div class="modal__content">
- <table table-data="availableRoles" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
-
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-
-</div>
-
-
-
-<script>
-app.controller('profileController', function ($scope,modalService){
-
- $scope.profile=${model.profile};
- $scope.profileId = $scope.profile.id;
- $scope.orgUserId=$scope.profile.orgUserId;
- $scope.orgManagerUserId=$scope.profile.orgManagerUserId;
-
- $scope.viewPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
-
- $( "#dialog" ).hide();
-
- $scope.ociavailableRoles=${model.availableRoles};
- //modalService.showFailure('Error','') ;
- $scope.availableRoles = [];
- if($scope.ociavailableRoles)
- $.each($scope.ociavailableRoles, function(i, a){
- var availableRole = a;
- availableRole.selected = false;
- $.each($scope.profile.roles, function(j, b){
- if(a.id === b.id) {
- availableRole.selected = true;
- }
- });
- $scope.availableRoles.push(availableRole);
- });
- ;
-
- $scope.ociTimeZones = ${model.timeZones};
- $scope.timeZones = [];
- $scope.selectedTimeZone = null;
- if($scope.ociTimeZones){
- $.each($scope.ociTimeZones, function(i, a){
- var timeZone = {"index":i, "value":a.value, "title":a.label};
- $scope.timeZones.push(timeZone);
- if($scope.profile.timeZoneId !== null && a.value === $scope.profile.timeZoneId.toString()){
- $scope.selectedTimeZone = timeZone;
- }
- });
- };
-
- $scope.ociCountries = ${model.countries};
- $scope.countries = [];
- $scope.selectedCountry = null;
- //alert($scope.ociCountries[0].label);
- if($scope.ociCountries)
- $.each($scope.ociCountries, function(i, a){
- var country = {"index":i, "value":a.value, "title":a.label};
- $scope.countries.push(country);
- if(a.value === $scope.profile.country){
- $scope.selectedCountry = country;
- }
- });
- ;
-
- var stateList=${model.stateList};
- //alert(stateList[0].label);
- stateList = stateList== null? []: stateList;
- var selectedState= $scope.profile.state ? $scope.profile.state:"";
- $scope.stateList = initDropdownWithLookUp(stateList,selectedState );
-
- $scope.saveProfile = function() {
- var uuu = "profile/saveProfile?profile_id="+$scope.profileId;
- var postData={profile: $scope.profile,
- selectedCountry:$scope.selectedCountry!=null?$scope.selectedCountry.value:"",
- selectedState:$scope.stateList.selected!=null?$scope.stateList.selected.value:"",
- selectedTimeZone:$scope.selectedTimeZone!=null?$scope.selectedTimeZone.value:""
- };
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- modalService.showSuccess("Success","Update Successful.");
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
- $scope.addNewRolePopup = function(role) {
- $( "#dialog" ).dialog({
- modal: true,
- width: 500,
- height:600
- });
- $(".ui-dialog-titlebar").hide();
- };
-
- $scope.toggleRole = function(selected,availableRole) {
- //alert('toggleRole: '+selected);
- if(!selected) {
- //remove role
- var uuu = "profile/removeRole?profile_id=" + $scope.profileId;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to remove the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- },
- function(){
- availableRole.selected=!availableRole.selected;
- });
-
- } else {
- //add role
- var uuu = "profile/addNewRole?profile_id=" + $scope.profileId;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to add the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },function(){
- availableRole.selected=!availableRole.selected;
- })
- }
-
-
- };
-
- $scope.removeRole = function(role) {
- modalService.popupConfirmWin("Confirm","You are about to remove the role "+role.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var uuu = "profile/removeRole?profile_id=" + $scope.profileId;
- var postData={role:role};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profile=data;
- $.each($scope.availableRoles, function(k, c){
- if(c.id === role.id) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
- };
-
- function initDropdownWithLookUp(arr,selectedValue){
- var dropdownArray=[];
- var selected = null;
- if(arr){
- for(var i = 0,l = arr.length; i < l; i++) {
- var option = {
- "index" : i ,
- "value" : arr[i].value,
- "title" : arr[i].label
- };
- dropdownArray.push(option);
- if(arr[i].value === selectedValue){
- selected = option;
- }
- }
- }
- var dropDown={};
- dropDown.options = dropdownArray;
- dropDown.selected = selected;
- return dropDown;
- };
-
- $scope.doRolePopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'roles_popup.html',
- controller: 'rolepopupController',
- resolve: {
- message: function () {
- var message ={
- availableRoles: $scope.availableRoles
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function (opts) {
- if(opts!=null){
- $scope.profile=opts.profile;
- }
- });
- }
-
- $scope.close = function(){
- $('#dialog').dialog('close');
- }
-
-
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile_search.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile_search.jsp
deleted file mode 100644
index 295faf03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/profile_search.jsp
+++ /dev/null
@@ -1,104 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<div ng-controller="profileSearchController">
- <div>
- <h1 class="heading1" style="margin-top:20px;">Profile Search</h1>
- <div style="margin-top:30px">
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">User ID</th>
- <th att-table-header key="last_name">Last Name</th>
- <th att-table-header key="first_name">First Name</th>
- <th att-table-header key="email">Email</th>
- <th att-table-header key="orgUserId">OrgUserId</th>
- <th att-table-header key="org_manager_userid">Manager OrgUserId</th>
- <th att-table-header >Edit</th>
- <th att-table-header key="active">Active?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body >{{rowData.id}}</td>
- <td att-table-body >{{rowData.lastName}}</td>
- <td att-table-body >{{rowData.firstName}}</td>
- <td att-table-body >{{rowData.email}}</td>
- <td att-table-body >{{rowData.orgUserId}}</td>
- <td att-table-body >{{rowData.managerId}}</td>
- <td att-table-body ><a href="" ng-click="editRow(rowData.id)" class="ion-edit" style="color: #888;font-size:20px;"></a></td>
- <td att-table-body >
- <div ng-click="toggleProfileActive(rowData)">
- <input type="checkbox" ng-model="rowData.active" att-toggle-main>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage" size="5" readonly="true" style="width: 47px;">
- </div>
-</div>
-
-<script>
-app.controller("profileSearchController", function ($scope,$http,modalService, $modal) {
- // Table Data
- $scope.tableData=${model.profileList};
- $scope.viewPerPage = 20;
- $scope.scrollViewsPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- // modalService.showSuccess('','Modal Sample') ;
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- $scope.editRow = function(profileId){
- window.location = 'profile?profile_id=' + profileId;
- }
-
- $scope.toggleProfileActive = function(rowData) {
- modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?",
- function(){
- $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){});
- },
- function(){
- rowData.active=!rowData.active;
- })
- };
-
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role.jsp
deleted file mode 100644
index d8e2a01b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role.jsp
+++ /dev/null
@@ -1,286 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal_rolefunction.html" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal_role.html" %>
-<style type="text/css">
- .bc-style{
- margin: 20px;
- align: left;
- }
-</style>
-<div class="bc-style">
- <ul class="breadcrumb" >
- <li><a href="welcome">Home</a></li>
- <li><a href="role_list">Roles</a></li>
- <li class="active">Role</li>
- </ul>
-</div>
-<div class="pageTitle">
-<h3>
- <c:choose>
- <c:when test="${!empty param.role_id}">
- <h1 class="heading1" style="margin-top:20px;">Role Edit</h1>
- </c:when>
- <c:otherwise>
- <h1 class="heading1" style="margin-top:20px;">Role Create</h1>
- </c:otherwise>
- </c:choose>
- </h3>
-</div>
-
-<div ng-controller="roleController" >
-
- <br>
- Please edit the role details below:&nbsp;<br>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="role.name"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Priority:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="role.priority"
- maxlength="30" />
- </div>
-
- <div align="left" >
- <button type="submit" ng-click="saveRole();" att-button
- btn-type="primary" size="small">Save</button>
- </div>
-
- <br>
- <div class="pageTitle">
- <label>Role Functions</label>
- <a ng-click="addNewRoleFunctionModalPopup();" class="ion-plus-round" size="small"></a>
- </div>
-
- <table table-data="role.roleFunctions" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="roleFunction in role.roleFunctions" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="90%" >{{ roleFunction.name }}</td>
- <td att-table-body width="10%">
- <div ng-click="removeRoleFunction(roleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- <a href="role_function_list.htm">Manage Role Functions</a><br><br>
-
- <div class="pageTitle">
- <label>Child Roles</label>
- <a ng-click="addNewChildRoleModalPopup();" class="ion-plus-round" size="small"></a>
- </div>
-
- <table table-data="role.childRoles" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="role in role.childRoles" style="max-height: 980px;" >
- <tr>
- <td att-table-body width="90%" >{{ role.name }}</td>
- <td att-table-body width="10%">
- <div ng-click="removeChildRole(role);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
-
- <div id="dialogChildRole" title="Select Child Roles">
- <table table-data="availableRoles" att-table>
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleChildRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
-
- </tr>
- </tbody>
- </table>
- </div>
-</div>
-
-
-
-<script>
-app.controller('roleController', function ($scope, modalService, $modal){
- $scope.role=${role};
- console.log($scope.role.roleFunctions);
-
- $( "#dialogRoleFunction" ).hide();
- $( "#dialogChildRole" ).hide();
-
- $scope.ociavailableRoleFunctions=${availableRoleFunctions};
-
- $scope.availableRoleFunctions = [];
- if($scope.ociavailableRoleFunctions)
- $.each($scope.ociavailableRoleFunctions, function(i, a){
- var availableRoleFunction = a;
- availableRoleFunction.selected = false;
- $.each($scope.role.roleFunctions, function(j, b){
- if(a.code === b.code) {
- availableRoleFunction.selected = true;
- }
- });
- $scope.availableRoleFunctions.push(availableRoleFunction);
- });
- ;
-
- $scope.saveRole = function() {
- var uuu = "role/saveRole.htm?role_id=${param.role_id}";
- var postData={role: $scope.role, childRoles: $scope.role.childRoles, roleFunctions : $scope.role.roleFunctions};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- modalService.showSuccess("Success","Update Successful.");
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
- $scope.addNewRoleFunctionModalPopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'role_functions_popup.html',
- controller: 'rolepopupController',
- backdrop: 'static',
- resolve: {
- role: function () {
- return $scope.role;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.role=response.role;
- });
- };
-
- $scope.addNewChildRoleModalPopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'child_roles_popup.html',
- controller: 'rolepopupController',
- backdrop: 'static',
- resolve: {
- role: function () {
- return $scope.role;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.role=response.role;
- });
- };
-
-
-
- $scope.removeRoleFunction = function(roleFunction) {
- modalService.popupConfirmWin("Confirm","You are about to remove the role function "+roleFunction.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var uuu = "role/removeRoleFunction.htm?role_id=${param.role_id}";
- var postData={roleFunction:roleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.role=data.role;
- $.each($scope.availableRoleFunctions, function(k, c){
- if(c.code === roleFunction.code) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
- };
-
- $scope.removeChildRole = function(childRole) {
- modalService.popupConfirmWin("Confirm","You are about to remove the child role "+childRole.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var uuu = "role/removeChildRole.htm?role_id=${param.role_id}";
- var postData={childRole:childRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.role=data.role;
- $.each($scope.availableRoles, function(k, c){
- if(c.id === childRole.id) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
- };
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_function_list.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_function_list.jsp
deleted file mode 100644
index b957337c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_function_list.jsp
+++ /dev/null
@@ -1,213 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-
-<%-- <%@ include file="/WEB-INF/fusion/jsp/include.jsp" %> --%>
-
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal_rolefunction.html" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<div ng-controller="roleFunctionListController" >
- <div class="pageTitle">
-
- <h1 class="heading1" style="margin-top:20px;">Role Functions</h1>
-
- <a ng-click="addNewRoleFunctionModalPopup();" class="ion-plus-round" size="small" ></a>
- <br><br>
-
- </div>
-
- <br>
- Click on the edit icon to update a role function, the plus icon to add additional role functions, or the delete icon to remove them.
- <br>
- <div id="rolesTable" title="Role Functions">
- <table att-table table-data="availableRoleFunctions" current-page="1">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header width="70%">Name</th>
- <th att-table-header width="10%">Code</th>
- <th att-table-header width="10%">Edit?</th>
- <th att-table-header width="10%">Delete?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRoleFunction in availableRoleFunctions" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="70%">{{ availableRoleFunction.name }}</td>
- <td att-table-body width="10%">{{ availableRoleFunction.code }}</td>
- <td att-table-body width="10%">
- <!-- <a ng-click="editRoleFunctionPopup(availableRoleFunction);" >
- <img src="static/fusion/images/editicon.gif">
- </a> -->
- <div ng-click="editRoleFunctionModalPopup(availableRoleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-edit"></a></div>
- </td>
- <td att-table-body width="10%">
- <!-- <a ng-click="removeRole(availableRoleFunction);" ><img src="static/fusion/images/deleteicon.gif"></a> -->
- <div ng-click="removeRole(availableRoleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-
-<!-- <div align="left" style="marin-bottom: 50px;"> -->
-<!-- <button type="submit" onClick="window.location='role_function.htm';" att-button -->
-<!-- btn-type="primary" size="small">Create</button> -->
-<!-- </div> -->
-
- <div id="dialog" title="Add Role Function">
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.name"
- maxlength="30" />
- </div>
- <br/>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Code:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.code" ng-disabled="editRoleFunction.code!=null"
- maxlength="30" />
- </div>
- <br/>
- <button type="submit" ng-click="saveRoleFunction(editRoleFunction);" att-button
- btn-type="primary" size="small">Save</button>
-
- </div>
-
-</div>
-
-
-
-
-<script>
-app.controller('roleFunctionListController', function ($scope, modalService, $modal){
- $( "#dialog" ).hide();
- $scope.availableRoleFunctions=${availableRoleFunctions};
-
-
- $scope.editRoleFunction = null;
- var dialog = null;
- $scope.editRoleFunctionPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.editRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- });
- };
-
- $scope.addNewRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = null;
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- });
- };
-
- $scope.addNewRoleFunctionPopup = function() {
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.saveRoleFunction = function(availableRoleFunction) {
- var uuu = "role_function_list/saveRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.availableRoleFunctions=[];$scope.$apply();
- $scope.availableRoleFunctions=data.availableRoleFunctions;});
- //alert("Update Successful.") ;
- console.log($scope.availableRoleFunctions);
-
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog("close");
- },
- error : function(data){
- alert("Error while saving.");
- }
- });
- };
-
-
- $scope.removeRole = function(availableRoleFunction) {
- modalService.popupConfirmWin("Confirm","You are about to delete the role function "+availableRoleFunction.name+". Do you want to continue?",
- function(){
- var uuu = "role_function_list/removeRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.availableRoleFunctions=data.availableRoleFunctions;});
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
- };
-
-
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_list.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_list.jsp
deleted file mode 100644
index c27c360b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/role_list.jsp
+++ /dev/null
@@ -1,139 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-
-<%-- <%@ include file="/WEB-INF/fusion/jsp/include.jsp" %> --%>
-
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-
-<div class="pageTitle">
- <h1 class="heading1" style="margin-top:20px;">Roles</h1>
-</div>
-<br>
-Click on a Role to view its details.
-
-<div ng-controller="roleListController" >
- <div id="dialog" title="Roles">
- <table att-table table-data="availableRoles" current-page="1">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header width="70%">Name</th>
- <th att-table-header width="10%">Priority</th>
- <th att-table-header width="10%">Active?</th>
- <th att-table-header width="10%">Delete?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
-<!-- <tr ng-repeat="availableRole in availableRoles track by availableRole.id"> -->
- <tr>
- <td width="70%"><a href="role.htm?role_id={{availableRole.id}}">{{ availableRole.name }}</a></td>
- <td width="10%">{{ availableRole.priority }}</td>
- <td width="10%">
- <div ng-click="toggleRole(availableRole.active,availableRole);">
- <input type="checkbox" ng-model="availableRole.active" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="10%">
- <div ng-click="removeRole(availableRole);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-
- <div align="left" style="marin-bottom: 50px;">
- <button type="submit" onClick="window.location='role.htm';" att-button
- btn-type="primary" size="small">Create</button>
- </div>
-
-</div>
-
-
-
-
-<script>
-app.controller('roleListController', function ($scope,modalService){
-
- $scope.availableRoles=${availableRoles};
- //console.log($scope.availableRoles);
- $scope.toggleRole = function(selected,availableRole) {
- //alert('toggleRole: '+selected);
- var toggleType = null;
- if(selected) {
- toggleType = "activate";
- } else {
- toggleType = "inactivate";
- }
-
- modalService.popupConfirmWinWithCancel("Confirm","You are about to "+toggleType+" the test role "+availableRole.name+". Do you want to continue?",
- function(){
- var uuu = "role_list/toggleRole";
-
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- console.log(data);
- $scope.$apply(function(){$scope.availableRoles=data.availableRoles;});
- console.log($scope.availableRoles);
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRole.active=!availableRole.active;
- })
-
- };
-
- $scope.removeRole = function(role) {
- modalService.popupConfirmWin("Confirm","You are about to delete the role "+role.name+". Do you want to continue?",
- function(){
- var uuu = "role_list/removeRole";
- var postData={role:role};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.availableRoles=data.availableRoles;});
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
- };
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/usage_list.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/usage_list.jsp
deleted file mode 100644
index 699c1ce6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/fusion/jsp/usage_list.jsp
+++ /dev/null
@@ -1,87 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-
-<%-- <%@ include file="/WEB-INF/fusion/jsp/include.jsp" %> --%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-
-<div ng-controller="usageListController" >
- <div class="pageTitle">
- <h3>
- Usage
- </h3>
- </div>
- <br/>
- The following shows all users currently logged into the application. Click the icon to expel a user from the application.
-
- <div title="Current User Sessions">
- <table att-table table-data="users" current-page="1">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%" align="left">Current User Sessions</th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- </tr>
- <tr>
- <th att-table-header sortable="false" width="10%" align="center">User Id</th>
- <th att-table-header sortable="false" width="10%" align="center">User Name</th>
- <th att-table-header sortable="false" width="10%" align="center">Email</th>
- <th att-table-header sortable="false" width="10%" align="center">Last Access Time (minutes)</th>
- <th att-table-header sortable="false" width="10%" align="center">Time Remaining (minutes)</th>
- <th att-table-header sortable="false" width="10%" align="center">Expel?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="user in users" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">{{user.id}}</td>
- <td att-table-body width="10%">{{user.lastName}}</td>
- <td att-table-body width="10%">{{user.email}}</td>
- <td att-table-body width="10%">{{user.lastAccess}}</td>
- <td att-table-body width="10%">{{user.remaining}}</td>
- <td att-table-body width="10%"><div ng-hide="user.delete=='yes'">Current Session</div>
- <div ng-click="removeSession(user.sessionId);" ng-hide="user.delete=='no'" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-</div>
-
-
-
-
-<script>
-app.controller('usageListController', function ($scope,$interval,$http,$modal,modalService){
-
- $scope.users=${model};console.log($scope.users);
- $scope.removeSession = function(sessionId) {
- modalService.popupConfirmWin("Confirm","You are about to expel this user from the application. All of their unsaved data will be lost. Do you want to continue?",
- function(){
- $http.get("usage_list/removeSession?deleteSessionId="+sessionId).success(function(response){$scope.users=response;});
- });
- }
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/leafletMap.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/leafletMap.jsp
deleted file mode 100644
index 77981f73..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/leafletMap.jsp
+++ /dev/null
@@ -1,288 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<!DOCTYPE html>
-
-<html>
-<head>
-
- <meta charset="UTF-8">
-
- <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
- <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
- <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
-
- <style>
- #map {
- height: 450px;
- width: 800px;
- }
- .animateOff {
- color: red;
- }
- .animateOn {
- color: green;
- }
- </style>
-
- <script>
-
- var siteData = [
- {"id": "cb1ma", "name": "Cambridge, MA", "title": "100G", "lat": 42.3736, "lon": -71.11},
- {"id": "st6wa", "name": "Seattle, WA", "title": "40G", "lat": 47.6097, "lon": -122.33},
- {"id": "cgcil", "name": "Chicago, IL", "title": "310G", "lat": 41.8819, "lon": -87.627},
- {"id": "n54ny", "name": "New York, NY", "title": "160G", "lat": 40.7127, "lon": -74.005},
- {"id": "cl2oh", "name": "Columbus, OH", "title": "300G", "lat": 39.9833, "lon": -82.983},
- {"id": "phlpa", "name": "Philadelphia, PA", "title": "210G", "lat": 39.95, "lon": -75.166},
- {"id": "ptdor", "name": "Portland, OR", "title": "90G", "lat": 45.52, "lon": -122.68},
- {"id": "dvmco", "name": "Denver, CO", "title": "170G", "lat": 39.7391, "lon": -104.98},
- {"id": "kc9mo", "name": "Kansas City, MO", "title": "100G", "lat": 39.0997, "lon": -94.578},
- {"id": "sffca", "name": "San Fransisco, CA", "title": "130G", "lat": 37.7833, "lon": -122.41},
- {"id": "sl9mo", "name": "St Louis, MO", "title": "330G", "lat": 38.6272, "lon": -90.197},
- {"id": "wswdc", "name": "Washington, DC", "title": "210G", "lat": 38.8951, "lon": -77.036},
- {"id": "sc1ca", "name": "Sacramento, CA", "title": "250G", "lat": 38.5555, "lon": -121.46},
- {"id": "slkut", "name": "Salt Lake City, UT", "title": "250G", "lat": 40.75, "lon": -111.88},
- {"id": "rlgnc", "name": "Raleigh, NC", "title": "180G", "lat": 35.8188, "lon": -78.644},
- {"id": "nsvtn", "name": "Nashville, TN", "title": "210G", "lat": 36.1666, "lon": -86.783},
- {"id": "la2ca", "name": "Los Angeles, CA", "title": "180G", "lat": 34.05, "lon": -118.25},
- {"id": "dlstx", "name": "Dallas, TX", "title": "330G", "lat": 32.7758, "lon": -96.796},
- {"id": "attga", "name": "Atlanta, GA", "title": "280G", "lat": 33.755, "lon": -84.39},
- {"id": "nwrla", "name": "New Orleans, LA", "title": "180G", "lat": 29.9647, "lon": -90.07},
- {"id": "sd2ca", "name": "San Diego, CA", "title": "150G", "lat": 32.715, "lon": -117.16},
- {"id": "phmaz", "name": "Phoenix, AZ", "title": "210G", "lat": 33.45, "lon": -112.06},
- {"id": "santx", "name": "San Antonio, TX", "title": "220G", "lat": 29.4166, "lon": -98.5},
- {"id": "hs1tx", "name": "Houston, TX", "title": "290G", "lat": 29.7627, "lon": -95.383},
- {"id": "ormfl", "name": "Orlando, FL", "title": "130G", "lat": 28.4158, "lon": -81.298},
- ];
-
- var pipeData = [
- {"id_a": "st6wa", "id_z": "ptdor", "name": "Seattle, WA to Portland, OR", "title": "60G", "lat_a": 47.6097, "lon_a": -122.33, "lat_z": 45.52, "lon_z": -122.68},
- {"id_a": "sc1ca", "id_z": "slkut", "name": "Sacramento, CA to Salt Lake City, UT", "title": "200G", "lat_a": 38.5555, "lon_a": -121.46, "lat_z": 40.75, "lon_z": -111.88},
- {"id_a": "hs1tx", "id_z": "ormfl", "name": "Houston, TX to Orlando, FL", "title": "130G", "lat_a": 29.7627, "lon_a": -95.383, "lat_z": 28.4158, "lon_z": -81.298},
- {"id_a": "nwrla", "id_z": "ormfl", "name": "New Orleans, LA to Orlando, FL", "title": "90G", "lat_a": 29.9647, "lon_a": -90.07, "lat_z": 28.4158, "lon_z": -81.298},
- {"id_a": "n54ny", "id_z": "phlpa", "name": "New York, NY to Philadelphia, PA", "title": "240G", "lat_a": 40.7127, "lon_a": -74.005, "lat_z": 39.95, "lon_z": -75.166},
- {"id_a": "n54ny", "id_z": "wswdc", "name": "New York, NY to Washington, DC", "title": "380G", "lat_a": 40.7127, "lon_a": -74.005, "lat_z": 38.8951, "lon_z": -77.036},
- {"id_a": "rlgnc", "id_z": "attga", "name": "Raleigh, NC to Atlanta, GA", "title": "160G", "lat_a": 35.8188, "lon_a": -78.644, "lat_z": 33.755, "lon_z": -84.39},
-// {"id_a": "st6wa", "id_z": "sffca", "name": "Seattle, WA to San Fransisco, CA", "title": "40G", "lat_a": 47.6097, "lon_a": -122.33, "lat_z": 37.7833, "lon_z": -122.41},
- {"id_a": "la2ca", "id_z": "sd2ca", "name": "Los Angeles, CA to San Diego, CA", "title": "160G", "lat_a": 34.05, "lon_a": -118.25, "lat_z": 32.715, "lon_z": -117.16},
- {"id_a": "sd2ca", "id_z": "phmaz", "name": "San Diego, CA to Phoenix, AZ", "title": "200G", "lat_a": 32.715, "lon_a": -117.16, "lat_z": 33.45, "lon_z": -112.06},
- {"id_a": "ptdor", "id_z": "sffca", "name": "Portland, OR to San Fransisco, CA", "title": "70G", "lat_a": 45.52, "lon_a": -122.68, "lat_z": 37.7833, "lon_z": -122.41},
- {"id_a": "sffca", "id_z": "sc1ca", "name": "San Fransisco, CA to Sacramento, CA", "title": "80G", "lat_a": 37.7833, "lon_a": -122.41, "lat_z": 38.5555, "lon_z": -121.46},
- {"id_a": "la2ca", "id_z": "slkut", "name": "Los Angeles, CA to Salt Lake City, UT", "title": "200G", "lat_a": 34.05, "lon_a": -118.25, "lat_z": 40.75, "lon_z": -111.88},
- {"id_a": "cgcil", "id_z": "cl2oh", "name": "Chicago, IL to Columbus, OH", "title": "200G", "lat_a": 41.8819, "lon_a": -87.627, "lat_z": 39.9833, "lon_z": -82.983},
- {"id_a": "cl2oh", "id_z": "phlpa", "name": "Columbus, OH to Philadelphia, PA", "title": "240G", "lat_a": 39.9833, "lon_a": -82.983, "lat_z": 39.95, "lon_z": -75.166},
- {"id_a": "phlpa", "id_z": "wswdc", "name": "Philadelphia, PA to Washington, DC", "title": "240G", "lat_a": 39.95, "lon_a": -75.166, "lat_z": 38.8951, "lon_z": -77.036},
- {"id_a": "sffca", "id_z": "la2ca", "name": "San Fransisco, CA to Los Angeles, CA", "title": "280G", "lat_a": 37.7833, "lon_a": -122.41, "lat_z": 34.05, "lon_z": -118.25},
- {"id_a": "dvmco", "id_z": "cgcil", "name": "Denver, CO to Chicago, IL", "title": "200G", "lat_a": 39.7391, "lon_a": -104.98, "lat_z": 41.8819, "lon_z": -87.627},
- {"id_a": "dlstx", "id_z": "hs1tx", "name": "Dallas, TX to Houston, TX", "title": "360G", "lat_a": 32.7758, "lon_a": -96.796, "lat_z": 29.7627, "lon_z": -95.383},
- {"id_a": "nsvtn", "id_z": "cl2oh", "name": "Nashville, TN to Columbus, OH", "title": "200G", "lat_a": 36.1666, "lon_a": -86.783, "lat_z": 39.9833, "lon_z": -82.983},
- {"id_a": "cb1ma", "id_z": "phlpa", "name": "Cambridge, MA to Philadelphia, PA", "title": "110G", "lat_a": 42.3736, "lon_a": -71.11, "lat_z": 39.95, "lon_z": -75.166},
-// {"id_a": "sffca", "id_z": "cgcil", "name": "San Fransisco, CA to Chicago, IL", "title": "170G", "lat_a": 37.7833, "lon_a": -122.41, "lat_z": 41.8819, "lon_z": -87.627},
- {"id_a": "sffca", "id_z": "dvmco", "name": "San Fransisco, CA to Denver, CO", "title": "90G", "lat_a": 37.7833, "lon_a": -122.41, "lat_z": 39.7391, "lon_z": -104.98},
- {"id_a": "sffca", "id_z": "sl9mo", "name": "San Fransisco, CA to St Louis, MO", "title": "80G", "lat_a": 37.7833, "lon_a": -122.41, "lat_z": 38.6272, "lon_z": -90.197},
- {"id_a": "santx", "id_z": "dlstx", "name": "San Antonio, TX to Dallas, TX", "title": "180G", "lat_a": 29.4166, "lon_a": -98.5, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "santx", "id_z": "hs1tx", "name": "San Antonio, TX to Houston, TX", "title": "240G", "lat_a": 29.4166, "lon_a": -98.5, "lat_z": 29.7627, "lon_z": -95.383},
- {"id_a": "sl9mo", "id_z": "wswdc", "name": "St Louis, MO to Washington, DC", "title": "280G", "lat_a": 38.6272, "lon_a": -90.197, "lat_z": 38.8951, "lon_z": -77.036},
- {"id_a": "nwrla", "id_z": "attga", "name": "New Orleans, LA to Atlanta, GA", "title": "200G", "lat_a": 29.9647, "lon_a": -90.07, "lat_z": 33.755, "lon_z": -84.39},
- {"id_a": "la2ca", "id_z": "dlstx", "name": "Los Angeles, CA to Dallas, TX", "title": "280G", "lat_a": 34.05, "lon_a": -118.25, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "slkut", "id_z": "dvmco", "name": "Salt Lake City, UT to Denver, CO", "title": "200G", "lat_a": 40.75, "lon_a": -111.88, "lat_z": 39.7391, "lon_z": -104.98},
- {"id_a": "dvmco", "id_z": "dlstx", "name": "Denver, CO to Dallas, TX", "title": "200G", "lat_a": 39.7391, "lon_a": -104.98, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "kc9mo", "id_z": "sl9mo", "name": "Kansas City, MO to St Louis, MO", "title": "280G", "lat_a": 39.0997, "lon_a": -94.578, "lat_z": 38.6272, "lon_z": -90.197},
- {"id_a": "kc9mo", "id_z": "dlstx", "name": "Kansas City, MO to Dallas, TX", "title": "280G", "lat_a": 39.0997, "lon_a": -94.578, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "cgcil", "id_z": "wswdc", "name": "Chicago, IL to Washington, DC", "title": "200G", "lat_a": 41.8819, "lon_a": -87.627, "lat_z": 38.8951, "lon_z": -77.036},
- {"id_a": "cgcil", "id_z": "sl9mo", "name": "Chicago, IL to St Louis, MO", "title": "370G", "lat_a": 41.8819, "lon_a": -87.627, "lat_z": 38.6272, "lon_z": -90.197},
- {"id_a": "n54ny", "id_z": "cb1ma", "name": "New York, NY to Cambridge, MA", "title": "80G", "lat_a": 40.7127, "lon_a": -74.005, "lat_z": 42.3736, "lon_z": -71.11},
- {"id_a": "st6wa", "id_z": "dvmco", "name": "Seattle, WA to Denver, CO", "title": "40G", "lat_a": 47.6097, "lon_a": -122.33, "lat_z": 39.7391, "lon_z": -104.98},
- {"id_a": "la2ca", "id_z": "phmaz", "name": "Los Angeles, CA to Phoenix, AZ", "title": "260G", "lat_a": 34.05, "lon_a": -118.25, "lat_z": 33.45, "lon_z": -112.06},
- {"id_a": "phmaz", "id_z": "santx", "name": "Phoenix, AZ to San Antonio, TX", "title": "160G", "lat_a": 33.45, "lon_a": -112.06, "lat_z": 29.4166, "lon_z": -98.5},
- {"id_a": "sl9mo", "id_z": "dlstx", "name": "St Louis, MO to Dallas, TX", "title": "200G", "lat_a": 38.6272, "lon_a": -90.197, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "dlstx", "id_z": "nsvtn", "name": "Dallas, TX to Nashville, TN", "title": "160G", "lat_a": 32.7758, "lon_a": -96.796, "lat_z": 36.1666, "lon_z": -86.783},
- {"id_a": "wswdc", "id_z": "attga", "name": "Washington, DC to Atlanta, GA", "title": "380G", "lat_a": 38.8951, "lon_a": -77.036, "lat_z": 33.755, "lon_z": -84.39},
- {"id_a": "st6wa", "id_z": "cgcil", "name": "Seattle, WA to Chicago, IL", "title": "70G", "lat_a": 47.6097, "lon_a": -122.33, "lat_z": 41.8819, "lon_z": -87.627},
- {"id_a": "dvmco", "id_z": "kc9mo", "name": "Denver, CO to Kansas City, MO", "title": "100G", "lat_a": 39.7391, "lon_a": -104.98, "lat_z": 39.0997, "lon_z": -94.578},
- {"id_a": "phmaz", "id_z": "dlstx", "name": "Phoenix, AZ to Dallas, TX", "title": "210G", "lat_a": 33.45, "lon_a": -112.06, "lat_z": 32.7758, "lon_z": -96.796},
- {"id_a": "cgcil", "id_z": "n54ny", "name": "Chicago, IL to New York, NY", "title": "280G", "lat_a": 41.8819, "lon_a": -87.627, "lat_z": 40.7127, "lon_z": -74.005},
- {"id_a": "sl9mo", "id_z": "nsvtn", "name": "St Louis, MO to Nashville, TN", "title": "170G", "lat_a": 38.6272, "lon_a": -90.197, "lat_z": 36.1666, "lon_z": -86.783},
- {"id_a": "dlstx", "id_z": "attga", "name": "Dallas, TX to Atlanta, GA", "title": "240G", "lat_a": 32.7758, "lon_a": -96.796, "lat_z": 33.755, "lon_z": -84.39},
- {"id_a": "hs1tx", "id_z": "nwrla", "name": "Houston, TX to New Orleans, LA", "title": "170G", "lat_a": 29.7627, "lon_a": -95.383, "lat_z": 29.9647, "lon_z": -90.07},
- {"id_a": "ormfl", "id_z": "attga", "name": "Orlando, FL to Atlanta, GA", "title": "210G", "lat_a": 28.4158, "lon_a": -81.298, "lat_z": 33.755, "lon_z": -84.39},
- {"id_a": "nsvtn", "id_z": "attga", "name": "Nashville, TN to Atlanta, GA", "title": "240G", "lat_a": 36.1666, "lon_a": -86.783, "lat_z": 33.755, "lon_z": -84.39},
- {"id_a": "wswdc", "id_z": "rlgnc", "name": "Washington, DC to Raleigh, NC", "title": "200G", "lat_a": 38.8951, "lon_a": -77.036, "lat_z": 35.8188, "lon_z": -78.644}
- ];
- </script>
-
-
-</head>
-<body>
- <div id="map"></div>
- <button id="forwardButton" onclick="stepForward();">Step Forward</button>
- <button id="playPause" onclick="playPause();">Play</button>
- <div>
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">Site</th>
- <th att-table-header key="lastName">Usage</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" id="topTenSites">
- </tbody>
- </table>
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">Link</th>
- <th att-table-header key="lastName">Usage</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" id="topTenLinks">
- </tbody>
- </table>
- </div>
-
- <script>
- var map = L.map('map').setView([40, -96], 4);
- L.tileLayer('', {maxZoom:18}).addTo(map); //TODO configure
-
- var dataLayer = addDataLayers(map, null);
-
- function addDataLayers(map, dataLayer) {
- if (dataLayer!=null) {
- map.removeLayer(dataLayer);
- }
-
- dataLayer = L.layerGroup();
-
- var siteInfo = [];
-
- var pipeLayer = L.layerGroup();
- for (var i=0; i<pipeData.length; i++) {
- var pipe = pipeData[i];
-
- var usage = pipe.usage;
- if (!usage || Math.random()<0.05) {
- //console.log("Rerolling " + pipe.name);
- usage = Math.floor(Math.random()*33 + Math.random()*33 + Math.random()*34);
- } else {
- //console.log("Adjusting " + pipe.name);
- usage = Math.floor(usage + Math.random()*15 - Math.random()*15);
- }
- if (usage<0) usage = 0;
- while (usage>100) usage -= Math.floor(20*Math.random());
- if (usage>90) usage -= Math.floor(20*Math.random());
-
- pipe.usage = usage;
-
- var color = "black";
- if (usage>60) color = "yellow";
- if (usage>70) color = "orange";
- if (usage>80) color = "red";
- pipeLayer.addLayer(L.polyline([[pipe.lat_a, pipe.lon_a], [pipe.lat_z, pipe.lon_z]], {"color": color, "title": pipe.name}).bindPopup(pipe.name + "<br/>" + pipe.title + "<br/>" + usage + "% usage"));
-
- var siteA = siteInfo[pipe.id_a];
- if (siteA) {
- siteA.usage += usage;
- siteA.maxUsage += 100;
- //console.log("Site a id = " + pipe.id_a + ", object existed = " + siteA + ", usage = " + siteA.usage + ", max = " + siteA.maxUsage);
- } else {
- siteA = {};
- siteA.usage = usage;
- siteA.maxUsage = 100;
- siteInfo[pipe.id_a] = siteA;
- //console.log("Site a id = " + pipe.id_a + ", object is new = " + siteA + ", usage = " + siteA.usage + ", max = " + siteA.maxUsage);
- }
-
- var siteZ = siteInfo[pipe.id_z];
- if (siteZ) {
- siteZ.usage += usage;
- siteZ.maxUsage += 100;
- //console.log("Site z id = " + pipe.id_z + ", object existed = " + siteZ + ", usage = " + siteZ.usage + ", max = " + siteZ.maxUsage);
- } else {
- siteZ = {};
- siteZ.usage = usage;
- siteZ.maxUsage = 100;
- siteInfo[pipe.id_z] = siteZ;
- //console.log("Site z id = " + pipe.id_z + ", object is new = " + siteZ + ", usage = " + siteZ.usage + ", max = " + siteZ.maxUsage);
- }
- }
- dataLayer.addLayer(pipeLayer);
-
- var dataCenterLayer = L.layerGroup();
- for (var i=0; i<siteData.length; i++) {
- var site = siteData[i];
-// {"id": "slkut", "name": "Salt Lake City, UT", "title": "250G", "lat": 40.75, "lon": -111.88},
- var info = siteInfo[site.id];
- var color = "black";
- if (info.usage/info.maxUsage>.6) color = "yellow";
- if (info.usage/info.maxUsage>.7) color = "orange";
- if (info.usage/info.maxUsage>.8) color = "red";
- var pct = Math.floor(100*info.usage/info.maxUsage);
- site.usage = pct;
-// dataCenterLayer.addLayer(L.marker([site.lat, site.lon], {"title": site.name}).bindPopup(site.name + "<br/>" + pipe.title + "<br/>" + info.usage + "/" + info.maxUsage));
- dataCenterLayer.addLayer(L.circleMarker([site.lat, site.lon], {"color": color, "title": site.name, "fillOpacity": .5}).bindPopup(site.name + "<br/>" + pipe.title + "<br/>" + pct + "%"));
- }
- dataLayer.addLayer(dataCenterLayer);
-
- dataLayer.addTo(map);
-
- siteData.sort(function(a,b){return b.usage-a.usage});
- var topTenHtml = "";
- for (var i=0; i<10; i++) {
- topTenHtml = topTenHtml + "<tr><td att-table-body>" + siteData[i].name + "</td><td att-table-body>" + siteData[i].usage + "%</td></tr>";
- }
- document.getElementById("topTenSites").innerHTML = topTenHtml;
-
- pipeData.sort(function(a,b){return b.usage-a.usage});
- topTenHtml = "";
- for (var i=0; i<10; i++) {
- topTenHtml = topTenHtml + "<tr><td att-table-body>" + pipeData[i].name + "</td><td att-table-body>" + pipeData[i].usage + "%</td></tr>";
- }
- document.getElementById("topTenLinks").innerHTML = topTenHtml;
-
- return dataLayer;
- }
-
- function stepForward() {
- dataLayer = addDataLayers(map, dataLayer);
- }
-
- var intervalObj = null;
- function playPause() {
- if (intervalObj==null) {
- document.getElementById('playPause').innerHTML = "Pause";
- document.getElementById('forwardButton').disabled = true;
- intervalObj = window.setInterval(function(){dataLayer = addDataLayers(map, dataLayer);},1500);
- } else {
- document.getElementById('playPause').innerHTML = "Play";
- document.getElementById('forwardButton').disabled = false;
- clearInterval(intervalObj);
- intervalObj = null;
- }
- }
-
- function onMapClick(e) {
- //alert("You clicked the map at " + e.latlng);
- dataLayer = addDataLayers(map, dataLayer);
- }
-
- map.on('click', onMapClick);
- </script>
-
-</body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/login_external.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/login_external.jsp
deleted file mode 100644
index b4e3c093..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/login_external.jsp
+++ /dev/null
@@ -1,154 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ page import="org.openecomp.portalsdk.core.util.SystemProperties" %>
-<c:set var="title" value="Login" />
-<c:set var="isMobileEnabled"
- value="<%=(SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE)!= null && SystemProperties.getProperty(SystemProperties.MOBILE_ENABLE).trim().equals(\"true\"))%>" />
-
-<!DOCTYPE html>
-<html ng-app="abs">
- <head>
-
- <title>
- Login
- </title>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
- <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
- <script src="static/js/jquery-1.10.2.js" type="text/javascript"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
- <script src="app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script>
- <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
- <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
- <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
- <script src="static/js/modalService.js"></script>
- <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
-
- <style>
- .terms {
- font-family: Verdana,Arial,Helvetica, sans-serif;
- font-size: 9px;
- }
-
- </style>
- </head>
- <body style="padding-top: 15px;">
- <div ng-controller="externalLoginController">
- <div class="centered style="-webkit-transform: translateZ(0);background:white, z-index:0;">
- <div align="center" id="errorInfo" style="display:none;float:left;font-size:12px;margin-left:5px"><span style="color:red">Invaild username or password, Please try again</span></div>
- <br/>
- <div align="center" style="margin-left:auto;margin-right:auto;width:40%;padding:6px;opacity:0.7;background-color:white">
- <img src="static/fusion/images/ecomp_trans.png"/>
- <h2> ECOMP Portal </h2>
- <label>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<label class="form-field__label">Login ID:</label>
- </label>
- <input type="text" class="fn-ebz-text" ng-model="loginId" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
- maxlength="30" />
- <br/>
- <br/>
- <label >&nbsp;Password:</label>
- <input type="password" class="span3" ng-model="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
- maxlength="30" onkeydown="if (event.keyCode == 13) document.getElementById('loginBtn').click()"/>
- <br />
- <br />
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- <input id="loginBtn" type="image" ng-click="loginExternal();" src="static/fusion/images/login_button.gif" alt="Login" />
- <br>
- </div>
- </div>
- <br/><br/><br/><br/><br/><br/><br/>
- <div id="footer">
- </div>
- </div>
- </body>
-<script>
-app.controller("externalLoginController", function ($scope) {
- // Table Data
-
- $scope.viewPerPage = 200;
- $scope.currentPage = 2;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- $scope.loginId="";
- $scope.password="";
- $scope.loginError=true;
- $scope.viewPerPage = 200;
- $scope.currentPage = 2;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- $scope.loginId="";
- $scope.password="";
-
-
- $scope.loginExternal = function() {
-
- $.ajax({
- url: "login_external/login?"+"loginId="+$scope.loginId+"&password="+$scope.password,
- type : "POST",
- success:function (response){
- if(response=="success"){
- window.location.href = 'welcome.htm';
- }else{
- $("#errorInfo").show();
- }
- },
- error:function( jqXHR, status,error ){
- $("#errorInfo").show();
- }
-
- });
-
- };
-
-
- /**
- $scope.loginExternal = function() {
-
-
- var redirectUrl = "login_external/login";
- var form = $('<form action="' + redirectUrl + '" method="post">' +
- '<input type="hidden" name="loginId" value='+$scope.loginId+' />' +
- '<input type="hidden" name="password" value='+$scope.password+' />' +
- '</form>');
-
- $('body').append(form);
- $(form).submit();
-
-
- };
- */
-
-});
-</script>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/user_profile.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/user_profile.jsp
deleted file mode 100644
index cb5c4e3b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/user_profile.jsp
+++ /dev/null
@@ -1,84 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ include file="/WEB-INF/fusion/jsp/popup_modal.html" %>
-<div ng-controller="userProfileSampleController">
- <div>
- <h1 class="heading1" style="margin-top:20px;">Profile Search</h1>
- <div style="margin-top:30px">
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">User ID</th>
- <th att-table-header key="last_name">Last Name</th>
- <th att-table-header key="first_name">First Name</th>
- <th att-table-header key="email">Email</th>
- <th att-table-header key="org_user_id">OrgUserId</th>
- <th att-table-header key="org_manager_userid">Manager OrgUserId</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body >{{rowData.id}}</td>
- <td att-table-body >{{rowData.last_name}}</td>
- <td att-table-body >{{rowData.first_name}}</td>
- <td att-table-body >{{rowData.email}}</td>
- <td att-table-body >{{rowData.orgUserId}}</td>
- <td att-table-body >{{rowData.org_manager_userid}}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage" size="5" readonly="true" style="width: 47px;">
- </div>
-</div>
-
-<script>
-app.controller("userProfileSampleController", function ($scope,$http,modalService, $modal) {
- // Table Data
- $scope.tableData=${model.customerInfo};
- console.log($scope.tableData);
- $scope.viewPerPage = 20;
- $scope.scrollViewsPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- // modalService.showSuccess('','Modal Sample') ;
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
-
-});
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/welcome.jsp b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/welcome.jsp
deleted file mode 100644
index a6096215..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/jsp/welcome.jsp
+++ /dev/null
@@ -1,630 +0,0 @@
-<%--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- --%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
-<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
-<link rel="stylesheet" type="text/css" href="static/fusion/sample/css/scribble.css" />
-
-<link rel="stylesheet" type="text/css" href="static/fusion/sample/css/welcome.css" />
-
-<script src="static/js/jquery-1.10.2.js"></script>
-<script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
-
-<!-- <script src="static/fusion/js/jquery.resize.js"></script> -->
-<link rel="stylesheet" href="static/fusion/css/att_angular_gridster/ui-gridster.css"/>
-<link rel="stylesheet" href="static/fusion/css/att_angular_gridster/sandbox-gridster.css"/>
-<script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
-<script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
-<script src="app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
-
-<!--for line Chart and Area Chart-->
-<script src="static/fusion/d3/js/d3.v3.min.js"></script>
-<script src="static/fusion/d3/js/nv.d3.min.js"></script>
-<script src="static/fusion/d3/js/models/axis.min.js"></script>
-
-<!-- Style for line Chart and area chart -->
-<link rel="stylesheet" type="text/css" href="static/fusion/d3/css/nv.d3.css">
-
-
-<script type="text/javascript" src="static/fusion/sample/js/FusionCharts.js"></script> <!-- Charts -->
-<script type="text/javascript" src="static/fusion/sample/js/charts.js"></script> <!-- Charts -->
-<script type="text/javascript" src="static/fusion/sample/js/scribble.js"></script> <!-- Scribble -->
-
-<!-- Data for Line and Area Charts -->
-<script>
-historicalBarChart=[{"type":"line","key":"AP_CPU","yAxis":"1","values":[{"x":1388552400000,"y":2.13},{"x":1388552400000,"y":5.0},{"x":1388552400000,"y":2.36},{"x":1388552400000,"y":10.0},{"x":1391230800000,"y":3.15},{"x":1391230800000,"y":2.88},{"x":1391230800000,"y":3.0},{"x":1391230800000,"y":4.0},{"x":1393650000000,"y":8.0},{"x":1393650000000,"y":3.93},{"x":1393650000000,"y":4.27},{"x":1393650000000,"y":4.0},{"x":1396324800000,"y":4.25},{"x":1396324800000,"y":5.35},{"x":1396324800000,"y":5.92},{"x":1396324800000,"y":12.0},{"x":1398916800000,"y":5.55},{"x":1398916800000,"y":4.89},{"x":1398916800000,"y":5.01},{"x":1398916800000,"y":3.27},{"x":1401595200000,"y":6.27},{"x":1401595200000,"y":9.17},{"x":1401595200000,"y":9.31},{"x":1401595200000,"y":6.07},{"x":1404187200000,"y":8.37},{"x":1404187200000,"y":8.11},{"x":1404187200000,"y":8.84},{"x":1404187200000,"y":8.93},{"x":1406865600000,"y":11.79},{"x":1406865600000,"y":12.22},{"x":1406865600000,"y":12.6},{"x":1406865600000,"y":11.61},{"x":1409544000000,"y":15.27},{"x":1409544000000,"y":19.09},{"x":1409544000000,"y":16.09},{"x":1409544000000,"y":18.66},{"x":1412136000000,"y":18.4},{"x":1412136000000,"y":22.05},{"x":1412136000000,"y":21.66},{"x":1412136000000,"y":19.04},{"x":1414814400000,"y":19.13},{"x":1414814400000,"y":19.61},{"x":1414814400000,"y":17.61},{"x":1414814400000,"y":17.5},{"x":1417410000000,"y":19.0},{"x":1417410000000,"y":15.73},{"x":1420088400000,"y":9.67},{"x":1420088400000,"y":15.19},{"x":1420088400000,"y":15.02},{"x":1420088400000,"y":9.62333333333333},{"x":1422766800000,"y":16.95},{"x":1422766800000,"y":14.29},{"x":1425186000000,"y":12.9},{"x":1425186000000,"y":16.1166666666667}]},{"type":"line","key":"ROUTER_CPU","yAxis":"1","values":[{"x":1388552400000,"y":3.0},{"x":1388552400000,"y":4.0},{"x":1388552400000,"y":4.89},{"x":1388552400000,"y":7.0},{"x":1391230800000,"y":4.57},{"x":1391230800000,"y":4.0},{"x":1391230800000,"y":4.0},{"x":1391230800000,"y":7.0},{"x":1393650000000,"y":7.0},{"x":1393650000000,"y":4.18},{"x":1393650000000,"y":5.0},{"x":1393650000000,"y":5.0},{"x":1396324800000,"y":5.0},{"x":1396324800000,"y":5.0},{"x":1396324800000,"y":5.06},{"x":1396324800000,"y":6.0},{"x":1398916800000,"y":5.0},{"x":1398916800000,"y":5.0},{"x":1398916800000,"y":5.0},{"x":1398916800000,"y":5.0},{"x":1401595200000,"y":6.0},{"x":1401595200000,"y":6.09},{"x":1401595200000,"y":6.0},{"x":1401595200000,"y":6.0},{"x":1404187200000,"y":6.36},{"x":1404187200000,"y":7.0},{"x":1404187200000,"y":7.0},{"x":1404187200000,"y":7.0},{"x":1406865600000,"y":7.0},{"x":1406865600000,"y":7.02},{"x":1406865600000,"y":7.24},{"x":1406865600000,"y":7.0},{"x":1409544000000,"y":8.23},{"x":1409544000000,"y":8.11},{"x":1409544000000,"y":8.12},{"x":1409544000000,"y":8.03},{"x":1412136000000,"y":9.0},{"x":1412136000000,"y":8.93},{"x":1412136000000,"y":8.57},{"x":1412136000000,"y":9.0},{"x":1414814400000,"y":5.97},{"x":1414814400000,"y":6.0},{"x":1414814400000,"y":9.0},{"x":1414814400000,"y":9.0},{"x":1417410000000,"y":9.0},{"x":1417410000000,"y":8.78},{"x":1420088400000,"y":3.0},{"x":1420088400000,"y":2.01},{"x":1420088400000,"y":3.0},{"x":1420088400000,"y":3.01},{"x":1422766800000,"y":2.67},{"x":1422766800000,"y":2.0},{"x":1425186000000,"y":2.8},{"x":1425186000000,"y":3.63333333333333}]},{"type":"line","key":"SCTP_CPU","yAxis":"1","values":[{"x":1388552400000,"y":7.0},{"x":1388552400000,"y":10.0},{"x":1388552400000,"y":8.27},{"x":1388552400000,"y":8.0},{"x":1391230800000,"y":10.02},{"x":1391230800000,"y":8.04},{"x":1391230800000,"y":9.0},{"x":1391230800000,"y":10.0},{"x":1393650000000,"y":12.0},{"x":1393650000000,"y":10.04},{"x":1393650000000,"y":11.16},{"x":1393650000000,"y":10.0},{"x":1396324800000,"y":10.7},{"x":1396324800000,"y":13.31},{"x":1396324800000,"y":12.73},{"x":1396324800000,"y":9.0},{"x":1398916800000,"y":12.41},{"x":1398916800000,"y":11.95},{"x":1398916800000,"y":12.82},{"x":1398916800000,"y":9.58},{"x":1401595200000,"y":11.28},{"x":1401595200000,"y":14.01},{"x":1401595200000,"y":14.63},{"x":1401595200000,"y":11.83},{"x":1404187200000,"y":14.06},{"x":1404187200000,"y":13.96},{"x":1404187200000,"y":14.66},{"x":1404187200000,"y":14.36},{"x":1406865600000,"y":16.6},{"x":1406865600000,"y":16.95},{"x":1406865600000,"y":17.11},{"x":1406865600000,"y":15.94},{"x":1409544000000,"y":19.86},{"x":1409544000000,"y":22.97},{"x":1409544000000,"y":21.56},{"x":1409544000000,"y":24.55},{"x":1412136000000,"y":22.66},{"x":1412136000000,"y":26.79},{"x":1412136000000,"y":26.54},{"x":1412136000000,"y":25.35},{"x":1414814400000,"y":21.0},{"x":1414814400000,"y":20.35},{"x":1414814400000,"y":21.93},{"x":1414814400000,"y":23.63},{"x":1417410000000,"y":24.0},{"x":1417410000000,"y":21.43},{"x":1420088400000,"y":12.63},{"x":1420088400000,"y":25.14},{"x":1420088400000,"y":21.85},{"x":1420088400000,"y":12.5766666666667},{"x":1422766800000,"y":26.3},{"x":1422766800000,"y":24.4},{"x":1425186000000,"y":23.3833333333333},{"x":1425186000000,"y":24.5833333333333}]},{"type":"line","key":"DP_CPU","yAxis":"1","values":[{"x":1388552400000,"y":2.0},{"x":1388552400000,"y":5.0},{"x":1388552400000,"y":2.17},{"x":1388552400000,"y":2.0},{"x":1391230800000,"y":3.01},{"x":1391230800000,"y":2.56},{"x":1391230800000,"y":3.0},{"x":1391230800000,"y":9.0},{"x":1393650000000,"y":10.0},{"x":1393650000000,"y":3.64},{"x":1393650000000,"y":4.06},{"x":1393650000000,"y":4.0},{"x":1396324800000,"y":4.04},{"x":1396324800000,"y":5.11},{"x":1396324800000,"y":5.9},{"x":1396324800000,"y":8.0},{"x":1398916800000,"y":5.08},{"x":1398916800000,"y":4.65},{"x":1398916800000,"y":4.74},{"x":1398916800000,"y":2.98},{"x":1401595200000,"y":6.13},{"x":1401595200000,"y":8.98},{"x":1401595200000,"y":9.22},{"x":1401595200000,"y":5.84},{"x":1404187200000,"y":8.12},{"x":1404187200000,"y":7.89},{"x":1404187200000,"y":8.41},{"x":1404187200000,"y":8.47},{"x":1406865600000,"y":11.06},{"x":1406865600000,"y":11.84},{"x":1406865600000,"y":11.92},{"x":1406865600000,"y":10.8},{"x":1409544000000,"y":14.58},{"x":1409544000000,"y":18.39},{"x":1409544000000,"y":15.5},{"x":1409544000000,"y":18.33},{"x":1412136000000,"y":18.01},{"x":1412136000000,"y":21.3},{"x":1412136000000,"y":21.11},{"x":1412136000000,"y":18.37},{"x":1414814400000,"y":18.59},{"x":1414814400000,"y":18.81},{"x":1414814400000,"y":17.13},{"x":1414814400000,"y":16.92},{"x":1417410000000,"y":18.0},{"x":1417410000000,"y":15.18},{"x":1420088400000,"y":9.16},{"x":1420088400000,"y":12.13},{"x":1420088400000,"y":11.76},{"x":1420088400000,"y":9.31},{"x":1422766800000,"y":13.47},{"x":1422766800000,"y":13.41},{"x":1425186000000,"y":12.2333333333333},{"x":1425186000000,"y":12.4}]}];
-</script>
-
- <script>
- $(function(){
-
-
- /* area chart and line chart titles */
- d3.select("#areaChart svg").append("text").attr("x", 200).attr("y", 15)
- .attr("text-anchor", "middle").style("font-size", "16px").text(
- "Data Usage in NJ Locations");
-
- d3.select("#lineChart svg").append("text").attr("x", 200).attr("y", 15)
- .attr("text-anchor", "middle").style("font-size", "16px").text(
- "Data Usage in NJ Locations");
- });
-</script>
-
-<div ng-controller="welcomeController">
- <fmt:message key="general.home" var="title" />
- <div>
- <span style="font-weight:bold;font-size:11pt;">Welcome ${sessionScope.user.firstName} ${sessionScope.user.lastName}</span>&nbsp;
- (Last Login:&nbsp;<fmt:formatDate value="${sessionScope.user.lastLoginDate}" type="date" pattern="dd MMM yyyy hh:mma zzz" var="lastLogin" /> ${lastLogin})
- </div>
-
- <div id="gridDiv" class="center">
- <div class="gridster-container">
- <div att-gridster att-gridster-options='gridsterOpts'>
- <div att-gridster-item='item' ng-repeat="item in standardItems">
- <div att-gridster-item-header
- header-text={{item.headerText}}
- sub-header-text={{item.subHeaderText}}>
- <!--ICON BUTTONS PLACEHOLDER START-->
- <div class="tileMinMaxBtn" ng-click="toggleMinMax($index,'')">
- <span class="tileMinMaxIcon">
- <i class="ion-chevron-up" style="color:gray" ng-show="item.max"></i>
- <i class="ion-chevron-down" style="color:gray" ng-hide="item.max"></i>
- </span>
- </div>
- <!--ICON BUTTONS PLACEHOLDER END-->
- </div>
- <div att-gridster-item-body >
- <!--ACTUAL BODY CONTENT START-->
- <div align="center" style="margin-top:10px;">
- <div align="left" ng-if="item.headerText=='Dashboard' && item.max">
- <label>&nbsp; Sample Charts</label><BR>
- <iframe scrolling="no" frameBorder="0" style="width: 430px; height: 360px;" src="static/fusion/sample/html/wordcloud.html"></iframe>
- </div>
- <div ng-if="item.headerText=='Donut Chart' && item.max">
- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/donut_d3.html"></iframe>
- </div>
- <!-- <div ng-if="item.headerText=='Area Chart' && item.max">
- <div id="areaChart">
- <div> <svg></svg> </div>
- <script src="static/fusion/sample/html/js/area_chart.min.js"></script>
- </div>
- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/area_chart.html"></iframe>
- </div> -->
- <div ng-if="item.headerText=='Pie Chart' && item.max">
- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/pie_chart.html"></iframe>
- </div>
- <!-- <div ng-if="item.headerText=='Line Chart' && item.max">
- <div id="lineChart">
- <div> <svg></svg> </div>
- <script src="static/fusion/sample/html/js/line_chart.min.js"></script>
- </div>
-
- <iframe scrolling="no" frameBorder="0" style="width: 310px; height: 210px;" src="static/fusion/sample/html/line_chart.html"></iframe>
- </div> -->
- <div ng-if="item.headerText=='Gauges' && item.max">
- <iframe scrolling="no" frameBorder="0" style="width: 310pxx; height: 210px;" src="static/fusion/sample/html/d3_gauges_demo.html"></iframe>
- </div>
-
- <div align="left" ng-if="item.headerText=='Traffic distribution by day of week' && item.max">
- <div id = "selectedTrafficDay">
- <ul>
- <li ng-repeat="Daytab in selectedTrafficDay"
- ng-class="{active1:isActiveTab1(Daytab.url)}"
- ng-click="onClickTab1(Daytab)">{{Daytab.title}}</li>
- </ul>
- <div id = "SelectedTrafficeDayView">
- <div ng-include="currentSelectedDayTab"></div>
- </div>
- <script type="text/ng-template" id="#Monday">
- <div id="Monday" align="centers"><img src="static/fusion/sample/images/tunnels/1_mon.png" width=100% height=100% alt="Monday"></div>
- </script>
- <script type="text/ng-template" id="#Tuesday">
- <div id="Tuesday" align="center"><img src="static/fusion/sample/images/tunnels/2_tue.png" width=100% height=100% alt="Tuesday"></div>
- </script>
- <script type="text/ng-template" id="#Wednesday">
- <div id="Wednesday" align="center"><img src="static/fusion/sample/images/tunnels/3_wed.png" width=100% height=100% alt="Wednesday"></div>
- </script>
- <script type="text/ng-template" id="#Thursday">
- <div id="Thursday" align="center"><img src="static/fusion/sample/images/tunnels/4_thu.png" width=100% height=100% alt="Thursday"></div>
- </script>
- <script type="text/ng-template" id="#Friday">
- <div id="Friday" align="center"><img src="static/fusion/sample/images/tunnels/5_fri.png" width=100% height=100% alt="Friday"></div>
- </script>
- <script type="text/ng-template" id="#Saturday">
- <div id="Saturday" align="center"><img src="static/fusion/sample/images/tunnels/6_sat.png" width=100% height=100% alt="Saturday"></div>
- </script>
- <script type="text/ng-template" id="#Sunday">
- <div id="Sunday" align="center"><img src="static/fusion/sample/images/tunnels/7_sun.png" width=100% height=100% alt="Sunday"></div>
- </script>
- </div>
- </div>
-
- <div align="left" ng-if="item.headerText=='Busy hour traffic analysis by day of week' && item.max">
- <div id = "BusyHourTraffic">
- <ul>
- <li ng-repeat="TrafficTab in BusyHourTraffic"
- ng-class="{active2:isActiveTab2(TrafficTab.url)}"
- ng-click="onClickTab2(TrafficTab)">{{TrafficTab.title}}</li>
- </ul>
- <div id = "BusyHourTrafficView">
- <div ng-include="currentSelectedBusyHourTraffic"></div>
- </div>
- <script type="text/ng-template" id="#Incoming">
- <div id="Incoming" align="left"><img src="static/fusion/sample/images/tunnels/BH_DLSTX_IN.png" width=100% height=100%></div>
- </script>
- <script type="text/ng-template" id="#Outgoing">
- <div id="Outgoing" align="center"><img src="static/fusion/sample/images/tunnels/BH_DLSTX_OUT.png" width=100% height=100%></div>
- </script>
- <script type="text/ng-template" id="#Default">
- <div id="Default" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat_Def.png" width=100% height=100%></div>
- </script>
- <script type="text/ng-template" id="#Priority">
- <div id="Priority" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat_Priority.png" width=100% height=100%></div>
- </script>
- <script type="text/ng-template" id="#BHNational">
- <div id="BHNational" align="center"><img src="static/fusion/sample/images/tunnels/BH_Nat.png" width=100% height=100%></div>
- </script>
- </div>
- </div>
-
- <div align="left" ng-if="item.headerText=='Additional Samples' && item.max">
- <label>&nbsp;Quick Links</label>
- <table att-table>
-
-
- <tr>
- <td att-table-body width="90%" ><a href="http://jquery.com" target="_blank">JQuery</a></td>
- <td att-table-body width="10%">
- <a ng-click="removeRole();" ><img src="static/fusion/sample/images/deleteicon.gif"></a>
- </td>
- </tr>
-
- <!-- <tr>
- <td att-table-body width="90%" ><a href="sample_heat_map.htm" target="">Heat Map</a></td>
- <td att-table-body width="10%">
- <a ng-click="removeRole();" ><img src="static/fusion/sample/images/deleteicon.gif"></a>
- </td>
- </tr> -->
- <tr>
- <td att-table-body width="90%" ><a href="leafletMap.htm" target="">Animated Map</a></td>
- <td att-table-body width="10%">
- <a ng-click="removeRole();" ><img src="static/fusion/sample/images/deleteicon.gif"></a>
- </td>
- </tr>
- <tr>
- <td att-table-body width="90%" ><a href="collaborate_list.htm">Chat Session</a></td>
- <td att-table-body width="10%">
- <a ng-click="removeRole();" ><img src="static/fusion/sample/images/deleteicon.gif"></a>
- </td>
- </tr>
- </table>
- </div>
- <div ng-if="item.headerText=='Sticky Notes' && item.max">
- <div style="width:100%; height:400px" id="scribble-pad"><pre id="scribble" contenteditable="true" onkeyup="storeUserScribble(this.id);"></pre></div>
- </div>
-
- <div ng-if="item.headerText=='Service Configuration' && item.max">
- <accordion close-others="true" css="att-accordion">
- <accordion-group heading="Service Configuration" is-open="group11.open">
- <iframe style="overflow:auto" frameBorder="0" align="center" width="100%" height="400px" src="static/fusion/sample/org_chart/example.html" ></iframe>
- </accordion-group>
- <accordion-group heading="VSP Service Configuration" is-open="group12.open">
- <iframe style="overflow:auto" frameBorder="0" align="center" width="100%" height="400px" src="static/fusion/sample/org_chart/example_vsp.html" ></iframe>
- </accordion-group>
- </accordion>
-
- </div>
-
- </div>
-
- <!--ACTUAL BODY CONTENT END-->
- </div>
-
- </div>
- </div>
- </div>
- </div> <!-- End gridDiv -->
-
-</div>
-
-<script>
- $(document).ready(function() {
- $("#rightIcon").hide();
- $("#leftIcon").show();
- });
-
- app.controller('welcomeController',function($scope, modalService, $modal) {
-
- $scope.gridsterOpts = {
- columns : 3, // the width of the grid, in columns
- pushing : true, // whether to push other items out of the way on move or resize
- floating : true, // whether to automatically float items up so they stack (you can temporarily disable if you are adding unsorted items with ng-repeat)
- width : 'auto', // can be an integer or 'auto'. 'auto' scales gridster to be the full width of its containing element
- colWidth : 'auto', // can be an integer or 'auto'. 'auto' uses the pixel width of the element divided by 'columns'
- rowHeight : 60, // can be an integer or 'match'. Match uses the colWidth, giving you square widgets.
- margins : [ 10, 10 ], // the pixel distance between each widget
- outerMargin : true, // whether margins apply to outer edges of the grid
- swapping : true,
- draggable : {
- enabled : true, // whether dragging items is supported
- stop: function(event, uiWidget, $element) {$scope.setCookie();} // optional callback fired when item is finished dragging
- }
-
- };
-
- /* $scope.gridsterOpts = {
- columns: 6,
- width: 'auto',
- colWidth: '230',
- rowHeight: '120',
- margins: [10, 10],
- outerMargin: true,
- pushing: true,
- floating: true,
- swapping: true
- }; */
-
- $scope.toggleMinMax = function(index, tileName) {
- if (tileName == '') {
- $scope.standardItems[index].max = !$scope.standardItems[index].max;
- if ($scope.standardItems[index].max)
- $scope.standardItems[index].sizeY = $scope.standardItems[index].maxHeight;
- else
- $scope.standardItems[index].sizeY = 0;
- } else {
- $scope.tileTemp = $scope.$eval(tileName);
- var tileMax = $parse(tileName + '.max');
- tileMax.assign($scope,!$scope.$eval(tileName).max);
- var tileSizeY = $parse(tileName + '.sizeY');
- if ($scope.tileTemp.max)
- tileSizeY.assign($scope,$scope.tileTemp.maxHeight);
- else
- tileSizeY.assign($scope, 0);
- }
- };
-
-
-
- // These map directly to gridsterItem options
- // IMPORTANT: Items should be placed in the grid in the order in which
- // they should appear.
- // In most cases the sorting should be by row ASC, col ASC
- $scope.standardItems = [{
- sizeX : 1,
- sizeY : 8,
- maxHeight : 8,
- row : 0,
- col : 0,
- headerText : 'Dashboard',
- max : false
-
- },
- {
- sizeX : 1,
- sizeY : 5,
- maxHeight : 5,
- row : 0,
- col : 1,
- headerText : 'Donut Chart',
- max : false
-
- },
- /* {
- sizeX : 1,
- sizeY : 5,
- maxHeight : 5,
- row : 0,
- col : 2,
- headerText : 'Area Chart',
- max : false
- }, */
- {
- sizeX : 1,
- sizeY : 5,
- maxHeight : 5,
- row : 8,
- col : 0,
- headerText : 'Pie Chart',
- max : false
- },
- /* {
- sizeX : 1,
- sizeY : 5,
- maxHeight : 5,
- row : 8,
- col : 1,
- headerText : 'Line Chart',
- max : false
- }, */
- {
- sizeX : 1,
- sizeY : 5,
- maxHeight : 5,
- row : 8,
- col : 2,
- headerText : 'Gauges',
- max : false
- },
- {
- sizeX : 1,
- sizeY : 8,
- maxHeight : 8,
- row : 16,
- col : 0,
- headerText : 'Traffic distribution by day of week',
- max : false
- },
- {
- sizeX : 1,
- sizeY : 8,
- maxHeight : 8,
- row : 16,
- col : 1,
- headerText : 'Busy hour traffic analysis by day of week',
- max : false
- },
- {
- sizeX : 1,
- sizeY : 6,
- maxHeight : 6,
- row : 24,
- col : 0,
- headerText : 'Additional Samples',
- max : false
- },
- {
- sizeX : 1,
- sizeY : 8,
- maxHeight : 8,
- row : 24,
- col : 1,
- headerText : 'Sticky Notes',
- max : false
- },
- {
- sizeX : 3,
- sizeY : 10,
- maxHeight : 10,
- row : 32,
- col : 0,
- headerText : 'Service Configuration',
- max : false
- } ];
-
- $.each($scope.standardItems, function(i, a) {
- $scope.toggleMinMax(i, '');
- });
- $scope.activeTabId = 'Monday';
- //for generic tabs
-
- $scope.selectedTrafficDay = [{
- title : 'Mon',
- url : '#Monday'
- }, {
- title : 'Tue',
- url : '#Tuesday'
- }, {
- title : 'Wed',
- url : '#Wednesday'
- }, {
- title : 'Thu',
- url : '#Thursday'
- }, {
- title : 'Fri',
- url : '#Friday'
- }, {
- title : 'Sat',
- url : '#Saturday'
- }, {
- title : 'Sun',
- url : '#Sunday'
- }];
-
- $scope.currentSelectedDayTab = '#Monday';
-
- $scope.onClickTab1 = function (Daytab) {
- $scope.currentSelectedDayTab = Daytab.url;
- }
-
- $scope.isActiveTab1 = function(tabUrl) {
- return tabUrl == $scope.currentSelectedDayTab;
- }
-
-
- $scope.gTabs = [ {
- title : 'Monday',
- id : 'Monday',
- url : '#Monday',
- selected : true
- }, {
- title : 'Tuesday',
- id : 'Tuesday',
- url : '#Tuesday'
- }, {
- title : 'Wednesday',
- id : 'Wednesday',
- url : '#Wednesday'
- }, {
- title : 'Thursday',
- id : 'Thursday',
- url : '#Thursday'
- }, {
- title : 'Friday',
- id : 'Friday',
- url : '#Friday'
- }, {
- title : 'Saturday',
- id : 'Saturday',
- url : '#Saturday'
- }, {
- title : 'Sunday',
- id : 'Sunday',
- url : '#Sunday'
- }
- ];
-
-
-
-
-
- $scope.BusyHourTraffic = [ {
- title : 'BH SNRC DLSTX - Incoming',
- url : '#Incoming'
- }, {
- title : 'BH SNRC DLSTX - Outgoing',
- url : '#Outgoing'
- }, {
- title : 'BH National - Default',
- url : '#Default'
- }, {
- title : 'BH National - Priority',
- url : '#Priority'
- }, {
- title : 'BH National',
- url : '#BHNational'
- }
-
- ];
-
- $scope.currentSelectedBusyHourTraffic = '#Incoming';
-
- $scope.onClickTab2 = function (TrafficTab) {
- $scope.currentSelectedBusyHourTraffic = TrafficTab.url;
- }
-
- $scope.isActiveTab2 = function(tabUrl) {
- return tabUrl == $scope.currentSelectedBusyHourTraffic;
- }
-
-
- $scope.activeTabId2 = 'Incoming';
- //for generic tabs
- $scope.gTabs2 = [ {
- title : 'BH SNRC DLSTX - Incoming',
- id : 'Incoming',
- url : '#Incoming',
- selected : true
- }, {
- title : 'BH SNRC DLSTX - Outgoing',
- id : 'Outgoing',
- url : '#Outgoing'
- }, {
- title : 'BH National - Default',
- id : 'Default',
- url : '#Default'
- }, {
- title : 'BH National - Priority',
- id : 'Priority',
- url : '#Priority'
- }, {
- title : 'BH National',
- id : 'BHNational',
- url : '#BHNational'
- }
- ];
-
- $scope.activeTabId3 = 'Incoming';
- //for generic tabs
- $scope.gTabs3 = [ {
- title : 'BH SNRC DLSTX - Incoming',
- id: 'Incoming',
- url : '#Incoming',
- selected : true
- }, {
- title : 'BH SNRC DLSTX - Outgoing',
- id : 'Outgoing',
- url : '#Outgoing'
- }, {
- title : 'BH National - Default',
- id : 'Default',
- url : '#Default'
- }, {
- title : 'BH National - Priority',
- id : 'Priority',
- url : '#Priority'
- }, {
- title : 'BH National',
- id : 'BHNational',
- url : '#BHNational'
- }
- ];
-
- /* $scope.$watch('activeTabId', function(newVal) {
- alert(newval);
- $('#'+newval).show();
- }, true); */
-
- $scope.toggleEastToWest = function() {
- $("#toggle").toggle('slide');
- if ($("#leftIcon").is(":visible")) {
- $("#rightIcon").show();
- $("#leftIcon").hide();
- }
- else if ($("#rightIcon").is(":visible")) {
- $("#rightIcon").hide();
- $("#leftIcon").show();
- }
- };
-
- $scope.group1 = {
- open : true
- };
- $scope.group2 = {
- open : true
- };
- $scope.group3 = {
- open : true
- };
- $scope.group4 = {
- open : true
- };
- $scope.group5 = {
- open : true
- };
- $scope.group6 = {
- open : true
- };
- $scope.group7 = {
- open : true
- };
- $scope.group71 = {
- open : true
- };
- $scope.group8 = {
- open : true
- };
- $scope.group9 = {
- open : true
- };
- $scope.group10 = {
- open : true
- };
- $scope.group11 = {
- open : true
- };
- $scope.group12 = {
- open : false
- };
- });
-</script>
-
-<!-- Select the Slider control by default -->
- <script>$('input[name=viewer]:eq(1)').click();</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/web.xml b/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index fcbe8407..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee">
-
- <display-name>ecomp-sdk-app</display-name>
-
- <!-- The app can function on a HA cluster -->
- <distributable />
-
- <session-config>
- <session-timeout>7</session-timeout>
- <tracking-mode>COOKIE</tracking-mode>
- </session-config>
-
-</web-app>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.js
deleted file mode 100644
index 2778fc56..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.js
+++ /dev/null
@@ -1,4121 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/* jshint ignore:start */
-var noop = angular.noop;
-var copy = angular.copy;
-var extend = angular.extend;
-var jqLite = angular.element;
-var forEach = angular.forEach;
-var isArray = angular.isArray;
-var isString = angular.isString;
-var isObject = angular.isObject;
-var isUndefined = angular.isUndefined;
-var isDefined = angular.isDefined;
-var isFunction = angular.isFunction;
-var isElement = angular.isElement;
-
-var ELEMENT_NODE = 1;
-var COMMENT_NODE = 8;
-
-var ADD_CLASS_SUFFIX = '-add';
-var REMOVE_CLASS_SUFFIX = '-remove';
-var EVENT_CLASS_PREFIX = 'ng-';
-var ACTIVE_CLASS_SUFFIX = '-active';
-var PREPARE_CLASS_SUFFIX = '-prepare';
-
-var NG_ANIMATE_CLASSNAME = 'ng-animate';
-var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren';
-
-// Detect proper transitionend/animationend event names.
-var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
-
-// If unprefixed events are not supported but webkit-prefixed are, use the latter.
-// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
-// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
-// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
-// Register both events in case `window.onanimationend` is not supported because of that,
-// do the same for `transitionend` as Safari is likely to exhibit similar behavior.
-// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
-// therefore there is no reason to test anymore for other vendor prefixes:
-// http://caniuse.com/#search=transition
-if (isUndefined(window.ontransitionend) && isDefined(window.onwebkittransitionend)) {
- CSS_PREFIX = '-webkit-';
- TRANSITION_PROP = 'WebkitTransition';
- TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
-} else {
- TRANSITION_PROP = 'transition';
- TRANSITIONEND_EVENT = 'transitionend';
-}
-
-if (isUndefined(window.onanimationend) && isDefined(window.onwebkitanimationend)) {
- CSS_PREFIX = '-webkit-';
- ANIMATION_PROP = 'WebkitAnimation';
- ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
-} else {
- ANIMATION_PROP = 'animation';
- ANIMATIONEND_EVENT = 'animationend';
-}
-
-var DURATION_KEY = 'Duration';
-var PROPERTY_KEY = 'Property';
-var DELAY_KEY = 'Delay';
-var TIMING_KEY = 'TimingFunction';
-var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
-var ANIMATION_PLAYSTATE_KEY = 'PlayState';
-var SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
-
-var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
-var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
-var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
-var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
-
-var isPromiseLike = function(p) {
- return p && p.then ? true : false;
-};
-
-var ngMinErr = angular.$$minErr('ng');
-function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
-}
-
-function mergeClasses(a,b) {
- if (!a && !b) return '';
- if (!a) return b;
- if (!b) return a;
- if (isArray(a)) a = a.join(' ');
- if (isArray(b)) b = b.join(' ');
- return a + ' ' + b;
-}
-
-function packageStyles(options) {
- var styles = {};
- if (options && (options.to || options.from)) {
- styles.to = options.to;
- styles.from = options.from;
- }
- return styles;
-}
-
-function pendClasses(classes, fix, isPrefix) {
- var className = '';
- classes = isArray(classes)
- ? classes
- : classes && isString(classes) && classes.length
- ? classes.split(/\s+/)
- : [];
- forEach(classes, function(klass, i) {
- if (klass && klass.length > 0) {
- className += (i > 0) ? ' ' : '';
- className += isPrefix ? fix + klass
- : klass + fix;
- }
- });
- return className;
-}
-
-function removeFromArray(arr, val) {
- var index = arr.indexOf(val);
- if (val >= 0) {
- arr.splice(index, 1);
- }
-}
-
-function stripCommentsFromElement(element) {
- if (element instanceof jqLite) {
- switch (element.length) {
- case 0:
- return [];
- break;
-
- case 1:
- // there is no point of stripping anything if the element
- // is the only element within the jqLite wrapper.
- // (it's important that we retain the element instance.)
- if (element[0].nodeType === ELEMENT_NODE) {
- return element;
- }
- break;
-
- default:
- return jqLite(extractElementNode(element));
- break;
- }
- }
-
- if (element.nodeType === ELEMENT_NODE) {
- return jqLite(element);
- }
-}
-
-function extractElementNode(element) {
- if (!element[0]) return element;
- for (var i = 0; i < element.length; i++) {
- var elm = element[i];
- if (elm.nodeType == ELEMENT_NODE) {
- return elm;
- }
- }
-}
-
-function $$addClass($$jqLite, element, className) {
- forEach(element, function(elm) {
- $$jqLite.addClass(elm, className);
- });
-}
-
-function $$removeClass($$jqLite, element, className) {
- forEach(element, function(elm) {
- $$jqLite.removeClass(elm, className);
- });
-}
-
-function applyAnimationClassesFactory($$jqLite) {
- return function(element, options) {
- if (options.addClass) {
- $$addClass($$jqLite, element, options.addClass);
- options.addClass = null;
- }
- if (options.removeClass) {
- $$removeClass($$jqLite, element, options.removeClass);
- options.removeClass = null;
- }
- }
-}
-
-function prepareAnimationOptions(options) {
- options = options || {};
- if (!options.$$prepared) {
- var domOperation = options.domOperation || noop;
- options.domOperation = function() {
- options.$$domOperationFired = true;
- domOperation();
- domOperation = noop;
- };
- options.$$prepared = true;
- }
- return options;
-}
-
-function applyAnimationStyles(element, options) {
- applyAnimationFromStyles(element, options);
- applyAnimationToStyles(element, options);
-}
-
-function applyAnimationFromStyles(element, options) {
- if (options.from) {
- element.css(options.from);
- options.from = null;
- }
-}
-
-function applyAnimationToStyles(element, options) {
- if (options.to) {
- element.css(options.to);
- options.to = null;
- }
-}
-
-function mergeAnimationDetails(element, oldAnimation, newAnimation) {
- var target = oldAnimation.options || {};
- var newOptions = newAnimation.options || {};
-
- var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
- var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
- var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
-
- if (newOptions.preparationClasses) {
- target.preparationClasses = concatWithSpace(newOptions.preparationClasses, target.preparationClasses);
- delete newOptions.preparationClasses;
- }
-
- // noop is basically when there is no callback; otherwise something has been set
- var realDomOperation = target.domOperation !== noop ? target.domOperation : null;
-
- extend(target, newOptions);
-
- // TODO(matsko or sreeramu): proper fix is to maintain all animation callback in array and call at last,but now only leave has the callback so no issue with this.
- if (realDomOperation) {
- target.domOperation = realDomOperation;
- }
-
- if (classes.addClass) {
- target.addClass = classes.addClass;
- } else {
- target.addClass = null;
- }
-
- if (classes.removeClass) {
- target.removeClass = classes.removeClass;
- } else {
- target.removeClass = null;
- }
-
- oldAnimation.addClass = target.addClass;
- oldAnimation.removeClass = target.removeClass;
-
- return target;
-}
-
-function resolveElementClasses(existing, toAdd, toRemove) {
- var ADD_CLASS = 1;
- var REMOVE_CLASS = -1;
-
- var flags = {};
- existing = splitClassesToLookup(existing);
-
- toAdd = splitClassesToLookup(toAdd);
- forEach(toAdd, function(value, key) {
- flags[key] = ADD_CLASS;
- });
-
- toRemove = splitClassesToLookup(toRemove);
- forEach(toRemove, function(value, key) {
- flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
- });
-
- var classes = {
- addClass: '',
- removeClass: ''
- };
-
- forEach(flags, function(val, klass) {
- var prop, allow;
- if (val === ADD_CLASS) {
- prop = 'addClass';
- allow = !existing[klass];
- } else if (val === REMOVE_CLASS) {
- prop = 'removeClass';
- allow = existing[klass];
- }
- if (allow) {
- if (classes[prop].length) {
- classes[prop] += ' ';
- }
- classes[prop] += klass;
- }
- });
-
- function splitClassesToLookup(classes) {
- if (isString(classes)) {
- classes = classes.split(' ');
- }
-
- var obj = {};
- forEach(classes, function(klass) {
- // sometimes the split leaves empty string values
- // incase extra spaces were applied to the options
- if (klass.length) {
- obj[klass] = true;
- }
- });
- return obj;
- }
-
- return classes;
-}
-
-function getDomNode(element) {
- return (element instanceof angular.element) ? element[0] : element;
-}
-
-function applyGeneratedPreparationClasses(element, event, options) {
- var classes = '';
- if (event) {
- classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
- }
- if (options.addClass) {
- classes = concatWithSpace(classes, pendClasses(options.addClass, ADD_CLASS_SUFFIX));
- }
- if (options.removeClass) {
- classes = concatWithSpace(classes, pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX));
- }
- if (classes.length) {
- options.preparationClasses = classes;
- element.addClass(classes);
- }
-}
-
-function clearGeneratedClasses(element, options) {
- if (options.preparationClasses) {
- element.removeClass(options.preparationClasses);
- options.preparationClasses = null;
- }
- if (options.activeClasses) {
- element.removeClass(options.activeClasses);
- options.activeClasses = null;
- }
-}
-
-function blockTransitions(node, duration) {
- // we use a negative delay value since it performs blocking
- // yet it doesn't kill any existing transitions running on the
- // same element which makes this safe for class-based animations
- var value = duration ? '-' + duration + 's' : '';
- applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
- return [TRANSITION_DELAY_PROP, value];
-}
-
-function blockKeyframeAnimations(node, applyBlock) {
- var value = applyBlock ? 'paused' : '';
- var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
- applyInlineStyle(node, [key, value]);
- return [key, value];
-}
-
-function applyInlineStyle(node, styleTuple) {
- var prop = styleTuple[0];
- var value = styleTuple[1];
- node.style[prop] = value;
-}
-
-function concatWithSpace(a,b) {
- if (!a) return b;
- if (!b) return a;
- return a + ' ' + b;
-}
-
-var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
- var queue, cancelFn;
-
- function scheduler(tasks) {
- // we make a copy since RAFScheduler mutates the state
- // of the passed in array variable and this would be difficult
- // to track down on the outside code
- queue = queue.concat(tasks);
- nextTick();
- }
-
- queue = scheduler.queue = [];
-
- /* waitUntilQuiet does two things:
- * 1. It will run the FINAL `fn` value only when an uncanceled RAF has passed through
- * 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
- *
- * The motivation here is that animation code can request more time from the scheduler
- * before the next wave runs. This allows for certain DOM properties such as classes to
- * be resolved in time for the next animation to run.
- */
- scheduler.waitUntilQuiet = function(fn) {
- if (cancelFn) cancelFn();
-
- cancelFn = $$rAF(function() {
- cancelFn = null;
- fn();
- nextTick();
- });
- };
-
- return scheduler;
-
- function nextTick() {
- if (!queue.length) return;
-
- var items = queue.shift();
- for (var i = 0; i < items.length; i++) {
- items[i]();
- }
-
- if (!cancelFn) {
- $$rAF(function() {
- if (!cancelFn) nextTick();
- });
- }
- }
-}];
-
-/**
- * @ngdoc directive
- * @name ngAnimateChildren
- * @restrict AE
- * @element ANY
- *
- * @description
- *
- * ngAnimateChildren allows you to specify that children of this element should animate even if any
- * of the children's parents are currently animating. By default, when an element has an active `enter`, `leave`, or `move`
- * (structural) animation, child elements that also have an active structural animation are not animated.
- *
- * Note that even if `ngAnimteChildren` is set, no child animations will run when the parent element is removed from the DOM (`leave` animation).
- *
- *
- * @param {string} ngAnimateChildren If the value is empty, `true` or `on`,
- * then child animations are allowed. If the value is `false`, child animations are not allowed.
- *
- * @example
- * <example module="ngAnimateChildren" name="ngAnimateChildren" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="mainController as main">
- <label>Show container? <input type="checkbox" ng-model="main.enterElement" /></label>
- <label>Animate children? <input type="checkbox" ng-model="main.animateChildren" /></label>
- <hr>
- <div ng-animate-children="{{main.animateChildren}}">
- <div ng-if="main.enterElement" class="container">
- List of items:
- <div ng-repeat="item in [0, 1, 2, 3]" class="item">Item {{item}}</div>
- </div>
- </div>
- </div>
- </file>
- <file name="animations.css">
-
- .container.ng-enter,
- .container.ng-leave {
- transition: all ease 1.5s;
- }
-
- .container.ng-enter,
- .container.ng-leave-active {
- opacity: 0;
- }
-
- .container.ng-leave,
- .container.ng-enter-active {
- opacity: 1;
- }
-
- .item {
- background: firebrick;
- color: #FFF;
- margin-bottom: 10px;
- }
-
- .item.ng-enter,
- .item.ng-leave {
- transition: transform 1.5s ease;
- }
-
- .item.ng-enter {
- transform: translateX(50px);
- }
-
- .item.ng-enter-active {
- transform: translateX(0);
- }
- </file>
- <file name="script.js">
- angular.module('ngAnimateChildren', ['ngAnimate'])
- .controller('mainController', function() {
- this.animateChildren = false;
- this.enterElement = false;
- });
- </file>
- </example>
- */
-var $$AnimateChildrenDirective = ['$interpolate', function($interpolate) {
- return {
- link: function(scope, element, attrs) {
- var val = attrs.ngAnimateChildren;
- if (angular.isString(val) && val.length === 0) { //empty attribute
- element.data(NG_ANIMATE_CHILDREN_DATA, true);
- } else {
- // Interpolate and set the value, so that it is available to
- // animations that run right after compilation
- setData($interpolate(val)(scope));
- attrs.$observe('ngAnimateChildren', setData);
- }
-
- function setData(value) {
- value = value === 'on' || value === 'true';
- element.data(NG_ANIMATE_CHILDREN_DATA, value);
- }
- }
- };
-}];
-
-var ANIMATE_TIMER_KEY = '$$animateCss';
-
-/**
- * @ngdoc service
- * @name $animateCss
- * @kind object
- *
- * @description
- * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes
- * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT
- * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or
- * directives to create more complex animations that can be purely driven using CSS code.
- *
- * Note that only browsers that support CSS transitions and/or keyframe animations are capable of
- * rendering animations triggered via `$animateCss` (bad news for IE9 and lower).
- *
- * ## Usage
- * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
- * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
- * any automatic control over cancelling animations and/or preventing animations from being run on
- * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to
- * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
- * the CSS animation.
- *
- * The example below shows how we can create a folding animation on an element using `ng-if`:
- *
- * ```html
- * <!-- notice the `fold-animation` CSS class -->
- * <div ng-if="onOff" class="fold-animation">
- * This element will go BOOM
- * </div>
- * <button ng-click="onOff=true">Fold In</button>
- * ```
- *
- * Now we create the **JavaScript animation** that will trigger the CSS transition:
- *
- * ```js
- * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
- * var height = element[0].offsetHeight;
- * return $animateCss(element, {
- * from: { height:'0px' },
- * to: { height:height + 'px' },
- * duration: 1 // one second
- * });
- * }
- * }
- * }]);
- * ```
- *
- * ## More Advanced Uses
- *
- * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks
- * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code.
- *
- * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation,
- * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with
- * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order
- * to provide a working animation that will run in CSS.
- *
- * The example below showcases a more advanced version of the `.fold-animation` from the example above:
- *
- * ```js
- * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
- * var height = element[0].offsetHeight;
- * return $animateCss(element, {
- * addClass: 'red large-text pulse-twice',
- * easing: 'ease-out',
- * from: { height:'0px' },
- * to: { height:height + 'px' },
- * duration: 1 // one second
- * });
- * }
- * }
- * }]);
- * ```
- *
- * Since we're adding/removing CSS classes then the CSS transition will also pick those up:
- *
- * ```css
- * /&#42; since a hardcoded duration value of 1 was provided in the JavaScript animation code,
- * the CSS classes below will be transitioned despite them being defined as regular CSS classes &#42;/
- * .red { background:red; }
- * .large-text { font-size:20px; }
- *
- * /&#42; we can also use a keyframe animation and $animateCss will make it work alongside the transition &#42;/
- * .pulse-twice {
- * animation: 0.5s pulse linear 2;
- * -webkit-animation: 0.5s pulse linear 2;
- * }
- *
- * @keyframes pulse {
- * from { transform: scale(0.5); }
- * to { transform: scale(1.5); }
- * }
- *
- * @-webkit-keyframes pulse {
- * from { -webkit-transform: scale(0.5); }
- * to { -webkit-transform: scale(1.5); }
- * }
- * ```
- *
- * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen.
- *
- * ## How the Options are handled
- *
- * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation
- * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline
- * styles using the `from` and `to` properties.
- *
- * ```js
- * var animator = $animateCss(element, {
- * from: { background:'red' },
- * to: { background:'blue' }
- * });
- * animator.start();
- * ```
- *
- * ```css
- * .rotating-animation {
- * animation:0.5s rotate linear;
- * -webkit-animation:0.5s rotate linear;
- * }
- *
- * @keyframes rotate {
- * from { transform: rotate(0deg); }
- * to { transform: rotate(360deg); }
- * }
- *
- * @-webkit-keyframes rotate {
- * from { -webkit-transform: rotate(0deg); }
- * to { -webkit-transform: rotate(360deg); }
- * }
- * ```
- *
- * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is
- * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition
- * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition
- * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied
- * and spread across the transition and keyframe animation.
- *
- * ## What is returned
- *
- * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually
- * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are
- * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties:
- *
- * ```js
- * var animator = $animateCss(element, { ... });
- * ```
- *
- * Now what do the contents of our `animator` variable look like:
- *
- * ```js
- * {
- * // starts the animation
- * start: Function,
- *
- * // ends (aborts) the animation
- * end: Function
- * }
- * ```
- *
- * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends.
- * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and styles may have been
- * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
- * and that changing them will not reconfigure the parameters of the animation.
- *
- * ### runner.done() vs runner.then()
- * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
- * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
- * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
- * unless you really need a digest to kick off afterwards.
- *
- * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
- * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code).
- * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works.
- *
- * @param {DOMElement} element the element that will be animated
- * @param {object} options the animation-related options that will be applied during the animation
- *
- * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
- * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
- * * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and
- * `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted.
- * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
- * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
- * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
- * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
- * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
- * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation.
- * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation.
- * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0`
- * is provided then the animation will be skipped entirely.
- * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is
- * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value
- * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same
- * CSS delay value.
- * * `stagger` - A numeric time value representing the delay between successively animated elements
- * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
- * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a
- * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
- * * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occurring on the classes being added and removed.)
- * * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
- * the animation is closed. This is useful for when the styles are used purely for the sake of
- * the animation and do not have a lasting visual effect on the element (e.g. a collapse and open animation).
- * By default this value is set to `false`.
- *
- * @return {object} an object with start and end methods and details about the animation.
- *
- * * `start` - The method to start the animation. This will return a `Promise` when called.
- * * `end` - This method will cancel the animation and remove all applied CSS classes and styles.
- */
-var ONE_SECOND = 1000;
-var BASE_TEN = 10;
-
-var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
-var CLOSING_TIME_BUFFER = 1.5;
-
-var DETECT_CSS_PROPERTIES = {
- transitionDuration: TRANSITION_DURATION_PROP,
- transitionDelay: TRANSITION_DELAY_PROP,
- transitionProperty: TRANSITION_PROP + PROPERTY_KEY,
- animationDuration: ANIMATION_DURATION_PROP,
- animationDelay: ANIMATION_DELAY_PROP,
- animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY
-};
-
-var DETECT_STAGGER_CSS_PROPERTIES = {
- transitionDuration: TRANSITION_DURATION_PROP,
- transitionDelay: TRANSITION_DELAY_PROP,
- animationDuration: ANIMATION_DURATION_PROP,
- animationDelay: ANIMATION_DELAY_PROP
-};
-
-function getCssKeyframeDurationStyle(duration) {
- return [ANIMATION_DURATION_PROP, duration + 's'];
-}
-
-function getCssDelayStyle(delay, isKeyframeAnimation) {
- var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP;
- return [prop, delay + 's'];
-}
-
-function computeCssStyles($window, element, properties) {
- var styles = Object.create(null);
- var detectedStyles = $window.getComputedStyle(element) || {};
- forEach(properties, function(formalStyleName, actualStyleName) {
- var val = detectedStyles[formalStyleName];
- if (val) {
- var c = val.charAt(0);
-
- // only numerical-based values have a negative sign or digit as the first value
- if (c === '-' || c === '+' || c >= 0) {
- val = parseMaxTime(val);
- }
-
- // by setting this to null in the event that the delay is not set or is set directly as 0
- // then we can still allow for negative values to be used later on and not mistake this
- // value for being greater than any other negative value.
- if (val === 0) {
- val = null;
- }
- styles[actualStyleName] = val;
- }
- });
-
- return styles;
-}
-
-function parseMaxTime(str) {
- var maxValue = 0;
- var values = str.split(/\s*,\s*/);
- forEach(values, function(value) {
- // it's always safe to consider only second values and omit `ms` values since
- // getComputedStyle will always handle the conversion for us
- if (value.charAt(value.length - 1) == 's') {
- value = value.substring(0, value.length - 1);
- }
- value = parseFloat(value) || 0;
- maxValue = maxValue ? Math.max(value, maxValue) : value;
- });
- return maxValue;
-}
-
-function truthyTimingValue(val) {
- return val === 0 || val != null;
-}
-
-function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
- var style = TRANSITION_PROP;
- var value = duration + 's';
- if (applyOnlyDuration) {
- style += DURATION_KEY;
- } else {
- value += ' linear all';
- }
- return [style, value];
-}
-
-function createLocalCacheLookup() {
- var cache = Object.create(null);
- return {
- flush: function() {
- cache = Object.create(null);
- },
-
- count: function(key) {
- var entry = cache[key];
- return entry ? entry.total : 0;
- },
-
- get: function(key) {
- var entry = cache[key];
- return entry && entry.value;
- },
-
- put: function(key, value) {
- if (!cache[key]) {
- cache[key] = { total: 1, value: value };
- } else {
- cache[key].total++;
- }
- }
- };
-}
-
-// we do not reassign an already present style value since
-// if we detect the style property value again we may be
-// detecting styles that were added via the `from` styles.
-// We make use of `isDefined` here since an empty string
-// or null value (which is what getPropertyValue will return
-// for a non-existing style) will still be marked as a valid
-// value for the style (a falsy value implies that the style
-// is to be removed at the end of the animation). If we had a simple
-// "OR" statement then it would not be enough to catch that.
-function registerRestorableStyles(backup, node, properties) {
- forEach(properties, function(prop) {
- backup[prop] = isDefined(backup[prop])
- ? backup[prop]
- : node.style.getPropertyValue(prop);
- });
-}
-
-var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
- var gcsLookup = createLocalCacheLookup();
- var gcsStaggerLookup = createLocalCacheLookup();
-
- this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
- '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
- function($window, $$jqLite, $$AnimateRunner, $timeout,
- $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- var parentCounter = 0;
- function gcsHashFn(node, extraClasses) {
- var KEY = "$$ngAnimateParentKey";
- var parentNode = node.parentNode;
- var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
- return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
- }
-
- function computeCachedCssStyles(node, className, cacheKey, properties) {
- var timings = gcsLookup.get(cacheKey);
-
- if (!timings) {
- timings = computeCssStyles($window, node, properties);
- if (timings.animationIterationCount === 'infinite') {
- timings.animationIterationCount = 1;
- }
- }
-
- // we keep putting this in multiple times even though the value and the cacheKey are the same
- // because we're keeping an internal tally of how many duplicate animations are detected.
- gcsLookup.put(cacheKey, timings);
- return timings;
- }
-
- function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
- var stagger;
-
- // if we have one or more existing matches of matching elements
- // containing the same parent + CSS styles (which is how cacheKey works)
- // then staggering is possible
- if (gcsLookup.count(cacheKey) > 0) {
- stagger = gcsStaggerLookup.get(cacheKey);
-
- if (!stagger) {
- var staggerClassName = pendClasses(className, '-stagger');
-
- $$jqLite.addClass(node, staggerClassName);
-
- stagger = computeCssStyles($window, node, properties);
-
- // force the conversion of a null value to zero incase not set
- stagger.animationDuration = Math.max(stagger.animationDuration, 0);
- stagger.transitionDuration = Math.max(stagger.transitionDuration, 0);
-
- $$jqLite.removeClass(node, staggerClassName);
-
- gcsStaggerLookup.put(cacheKey, stagger);
- }
- }
-
- return stagger || {};
- }
-
- var cancelLastRAFRequest;
- var rafWaitQueue = [];
- function waitUntilQuiet(callback) {
- rafWaitQueue.push(callback);
- $$rAFScheduler.waitUntilQuiet(function() {
- gcsLookup.flush();
- gcsStaggerLookup.flush();
-
- // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
- // PLEASE EXAMINE THE `$$forceReflow` service to understand why.
- var pageWidth = $$forceReflow();
-
- // we use a for loop to ensure that if the queue is changed
- // during this looping then it will consider new requests
- for (var i = 0; i < rafWaitQueue.length; i++) {
- rafWaitQueue[i](pageWidth);
- }
- rafWaitQueue.length = 0;
- });
- }
-
- function computeTimings(node, className, cacheKey) {
- var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
- var aD = timings.animationDelay;
- var tD = timings.transitionDelay;
- timings.maxDelay = aD && tD
- ? Math.max(aD, tD)
- : (aD || tD);
- timings.maxDuration = Math.max(
- timings.animationDuration * timings.animationIterationCount,
- timings.transitionDuration);
-
- return timings;
- }
-
- return function init(element, initialOptions) {
- // all of the animation functions should create
- // a copy of the options data, however, if a
- // parent service has already created a copy then
- // we should stick to using that
- var options = initialOptions || {};
- if (!options.$$prepared) {
- options = prepareAnimationOptions(copy(options));
- }
-
- var restoreStyles = {};
- var node = getDomNode(element);
- if (!node
- || !node.parentNode
- || !$$animateQueue.enabled()) {
- return closeAndReturnNoopAnimator();
- }
-
- var temporaryStyles = [];
- var classes = element.attr('class');
- var styles = packageStyles(options);
- var animationClosed;
- var animationPaused;
- var animationCompleted;
- var runner;
- var runnerHost;
- var maxDelay;
- var maxDelayTime;
- var maxDuration;
- var maxDurationTime;
- var startTime;
- var events = [];
-
- if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
- return closeAndReturnNoopAnimator();
- }
-
- var method = options.event && isArray(options.event)
- ? options.event.join(' ')
- : options.event;
-
- var isStructural = method && options.structural;
- var structuralClassName = '';
- var addRemoveClassName = '';
-
- if (isStructural) {
- structuralClassName = pendClasses(method, EVENT_CLASS_PREFIX, true);
- } else if (method) {
- structuralClassName = method;
- }
-
- if (options.addClass) {
- addRemoveClassName += pendClasses(options.addClass, ADD_CLASS_SUFFIX);
- }
-
- if (options.removeClass) {
- if (addRemoveClassName.length) {
- addRemoveClassName += ' ';
- }
- addRemoveClassName += pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX);
- }
-
- // there may be a situation where a structural animation is combined together
- // with CSS classes that need to resolve before the animation is computed.
- // However this means that there is no explicit CSS code to block the animation
- // from happening (by setting 0s none in the class name). If this is the case
- // we need to apply the classes before the first rAF so we know to continue if
- // there actually is a detected transition or keyframe animation
- if (options.applyClassesEarly && addRemoveClassName.length) {
- applyAnimationClasses(element, options);
- }
-
- var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
- var fullClassName = classes + ' ' + preparationClasses;
- var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
- var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
- var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
-
- // there is no way we can trigger an animation if no styles and
- // no classes are being applied which would then trigger a transition,
- // unless there a is raw keyframe value that is applied to the element.
- if (!containsKeyframeAnimation
- && !hasToStyles
- && !preparationClasses) {
- return closeAndReturnNoopAnimator();
- }
-
- var cacheKey, stagger;
- if (options.stagger > 0) {
- var staggerVal = parseFloat(options.stagger);
- stagger = {
- transitionDelay: staggerVal,
- animationDelay: staggerVal,
- transitionDuration: 0,
- animationDuration: 0
- };
- } else {
- cacheKey = gcsHashFn(node, fullClassName);
- stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
- }
-
- if (!options.$$skipPreparationClasses) {
- $$jqLite.addClass(element, preparationClasses);
- }
-
- var applyOnlyDuration;
-
- if (options.transitionStyle) {
- var transitionStyle = [TRANSITION_PROP, options.transitionStyle];
- applyInlineStyle(node, transitionStyle);
- temporaryStyles.push(transitionStyle);
- }
-
- if (options.duration >= 0) {
- applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
- var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration);
-
- // we set the duration so that it will be picked up by getComputedStyle later
- applyInlineStyle(node, durationStyle);
- temporaryStyles.push(durationStyle);
- }
-
- if (options.keyframeStyle) {
- var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle];
- applyInlineStyle(node, keyframeStyle);
- temporaryStyles.push(keyframeStyle);
- }
-
- var itemIndex = stagger
- ? options.staggerIndex >= 0
- ? options.staggerIndex
- : gcsLookup.count(cacheKey)
- : 0;
-
- var isFirst = itemIndex === 0;
-
- // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
- // without causing any combination of transitions to kick in. By adding a negative delay value
- // it forces the setup class' transition to end immediately. We later then remove the negative
- // transition delay to allow for the transition to naturally do it's thing. The beauty here is
- // that if there is no transition defined then nothing will happen and this will also allow
- // other transitions to be stacked on top of each other without any chopping them out.
- if (isFirst && !options.skipBlocking) {
- blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
- }
-
- var timings = computeTimings(node, fullClassName, cacheKey);
- var relativeDelay = timings.maxDelay;
- maxDelay = Math.max(relativeDelay, 0);
- maxDuration = timings.maxDuration;
-
- var flags = {};
- flags.hasTransitions = timings.transitionDuration > 0;
- flags.hasAnimations = timings.animationDuration > 0;
- flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all';
- flags.applyTransitionDuration = hasToStyles && (
- (flags.hasTransitions && !flags.hasTransitionAll)
- || (flags.hasAnimations && !flags.hasTransitions));
- flags.applyAnimationDuration = options.duration && flags.hasAnimations;
- flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions);
- flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations;
- flags.recalculateTimingStyles = addRemoveClassName.length > 0;
-
- if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
- maxDuration = options.duration ? parseFloat(options.duration) : maxDuration;
-
- if (flags.applyTransitionDuration) {
- flags.hasTransitions = true;
- timings.transitionDuration = maxDuration;
- applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
- temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration));
- }
-
- if (flags.applyAnimationDuration) {
- flags.hasAnimations = true;
- timings.animationDuration = maxDuration;
- temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration));
- }
- }
-
- if (maxDuration === 0 && !flags.recalculateTimingStyles) {
- return closeAndReturnNoopAnimator();
- }
-
- if (options.delay != null) {
- var delayStyle;
- if (typeof options.delay !== "boolean") {
- delayStyle = parseFloat(options.delay);
- // number in options.delay means we have to recalculate the delay for the closing timeout
- maxDelay = Math.max(delayStyle, 0);
- }
-
- if (flags.applyTransitionDelay) {
- temporaryStyles.push(getCssDelayStyle(delayStyle));
- }
-
- if (flags.applyAnimationDelay) {
- temporaryStyles.push(getCssDelayStyle(delayStyle, true));
- }
- }
-
- // we need to recalculate the delay value since we used a pre-emptive negative
- // delay value and the delay value is required for the final event checking. This
- // property will ensure that this will happen after the RAF phase has passed.
- if (options.duration == null && timings.transitionDuration > 0) {
- flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst;
- }
-
- maxDelayTime = maxDelay * ONE_SECOND;
- maxDurationTime = maxDuration * ONE_SECOND;
- if (!options.skipBlocking) {
- flags.blockTransition = timings.transitionDuration > 0;
- flags.blockKeyframeAnimation = timings.animationDuration > 0 &&
- stagger.animationDelay > 0 &&
- stagger.animationDuration === 0;
- }
-
- if (options.from) {
- if (options.cleanupStyles) {
- registerRestorableStyles(restoreStyles, node, Object.keys(options.from));
- }
- applyAnimationFromStyles(element, options);
- }
-
- if (flags.blockTransition || flags.blockKeyframeAnimation) {
- applyBlocking(maxDuration);
- } else if (!options.skipBlocking) {
- blockTransitions(node, false);
- }
-
- // TODO(matsko): for 1.5 change this code to have an animator object for better debugging
- return {
- $$willAnimate: true,
- end: endFn,
- start: function() {
- if (animationClosed) return;
-
- runnerHost = {
- end: endFn,
- cancel: cancelFn,
- resume: null, //this will be set during the start() phase
- pause: null
- };
-
- runner = new $$AnimateRunner(runnerHost);
-
- waitUntilQuiet(start);
-
- // we don't have access to pause/resume the animation
- // since it hasn't run yet. AnimateRunner will therefore
- // set noop functions for resume and pause and they will
- // later be overridden once the animation is triggered
- return runner;
- }
- };
-
- function endFn() {
- close();
- }
-
- function cancelFn() {
- close(true);
- }
-
- function close(rejected) { // jshint ignore:line
- // if the promise has been called already then we shouldn't close
- // the animation again
- if (animationClosed || (animationCompleted && animationPaused)) return;
- animationClosed = true;
- animationPaused = false;
-
- if (!options.$$skipPreparationClasses) {
- $$jqLite.removeClass(element, preparationClasses);
- }
- $$jqLite.removeClass(element, activeClasses);
-
- blockKeyframeAnimations(node, false);
- blockTransitions(node, false);
-
- forEach(temporaryStyles, function(entry) {
- // There is only one way to remove inline style properties entirely from elements.
- // By using `removeProperty` this works, but we need to convert camel-cased CSS
- // styles down to hyphenated values.
- node.style[entry[0]] = '';
- });
-
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
-
- if (Object.keys(restoreStyles).length) {
- forEach(restoreStyles, function(value, prop) {
- value ? node.style.setProperty(prop, value)
- : node.style.removeProperty(prop);
- });
- }
-
- // the reason why we have this option is to allow a synchronous closing callback
- // that is fired as SOON as the animation ends (when the CSS is removed) or if
- // the animation never takes off at all. A good example is a leave animation since
- // the element must be removed just after the animation is over or else the element
- // will appear on screen for one animation frame causing an overbearing flicker.
- if (options.onDone) {
- options.onDone();
- }
-
- if (events && events.length) {
- // Remove the transitionend / animationend listener(s)
- element.off(events.join(' '), onAnimationProgress);
- }
-
- //Cancel the fallback closing timeout and remove the timer data
- var animationTimerData = element.data(ANIMATE_TIMER_KEY);
- if (animationTimerData) {
- $timeout.cancel(animationTimerData[0].timer);
- element.removeData(ANIMATE_TIMER_KEY);
- }
-
- // if the preparation function fails then the promise is not setup
- if (runner) {
- runner.complete(!rejected);
- }
- }
-
- function applyBlocking(duration) {
- if (flags.blockTransition) {
- blockTransitions(node, duration);
- }
-
- if (flags.blockKeyframeAnimation) {
- blockKeyframeAnimations(node, !!duration);
- }
- }
-
- function closeAndReturnNoopAnimator() {
- runner = new $$AnimateRunner({
- end: endFn,
- cancel: cancelFn
- });
-
- // should flush the cache animation
- waitUntilQuiet(noop);
- close();
-
- return {
- $$willAnimate: false,
- start: function() {
- return runner;
- },
- end: endFn
- };
- }
-
- function onAnimationProgress(event) {
- event.stopPropagation();
- var ev = event.originalEvent || event;
-
- // we now always use `Date.now()` due to the recent changes with
- // event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
- var timeStamp = ev.$manualTimeStamp || Date.now();
-
- /* Firefox (or possibly just Gecko) likes to not round values up
- * when a ms measurement is used for the animation */
- var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
-
- /* $manualTimeStamp is a mocked timeStamp value which is set
- * within browserTrigger(). This is only here so that tests can
- * mock animations properly. Real events fallback to event.timeStamp,
- * or, if they don't, then a timeStamp is automatically created for them.
- * We're checking to see if the timeStamp surpasses the expected delay,
- * but we're using elapsedTime instead of the timeStamp on the 2nd
- * pre-condition since animationPauseds sometimes close off early */
- if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
- // we set this flag to ensure that if the transition is paused then, when resumed,
- // the animation will automatically close itself since transitions cannot be paused.
- animationCompleted = true;
- close();
- }
- }
-
- function start() {
- if (animationClosed) return;
- if (!node.parentNode) {
- close();
- return;
- }
-
- // even though we only pause keyframe animations here the pause flag
- // will still happen when transitions are used. Only the transition will
- // not be paused since that is not possible. If the animation ends when
- // paused then it will not complete until unpaused or cancelled.
- var playPause = function(playAnimation) {
- if (!animationCompleted) {
- animationPaused = !playAnimation;
- if (timings.animationDuration) {
- var value = blockKeyframeAnimations(node, animationPaused);
- animationPaused
- ? temporaryStyles.push(value)
- : removeFromArray(temporaryStyles, value);
- }
- } else if (animationPaused && playAnimation) {
- animationPaused = false;
- close();
- }
- };
-
- // checking the stagger duration prevents an accidentally cascade of the CSS delay style
- // being inherited from the parent. If the transition duration is zero then we can safely
- // rely that the delay value is an intentional stagger delay style.
- var maxStagger = itemIndex > 0
- && ((timings.transitionDuration && stagger.transitionDuration === 0) ||
- (timings.animationDuration && stagger.animationDuration === 0))
- && Math.max(stagger.animationDelay, stagger.transitionDelay);
- if (maxStagger) {
- $timeout(triggerAnimationStart,
- Math.floor(maxStagger * itemIndex * ONE_SECOND),
- false);
- } else {
- triggerAnimationStart();
- }
-
- // this will decorate the existing promise runner with pause/resume methods
- runnerHost.resume = function() {
- playPause(true);
- };
-
- runnerHost.pause = function() {
- playPause(false);
- };
-
- function triggerAnimationStart() {
- // just incase a stagger animation kicks in when the animation
- // itself was cancelled entirely
- if (animationClosed) return;
-
- applyBlocking(false);
-
- forEach(temporaryStyles, function(entry) {
- var key = entry[0];
- var value = entry[1];
- node.style[key] = value;
- });
-
- applyAnimationClasses(element, options);
- $$jqLite.addClass(element, activeClasses);
-
- if (flags.recalculateTimingStyles) {
- fullClassName = node.className + ' ' + preparationClasses;
- cacheKey = gcsHashFn(node, fullClassName);
-
- timings = computeTimings(node, fullClassName, cacheKey);
- relativeDelay = timings.maxDelay;
- maxDelay = Math.max(relativeDelay, 0);
- maxDuration = timings.maxDuration;
-
- if (maxDuration === 0) {
- close();
- return;
- }
-
- flags.hasTransitions = timings.transitionDuration > 0;
- flags.hasAnimations = timings.animationDuration > 0;
- }
-
- if (flags.applyAnimationDelay) {
- relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay)
- ? parseFloat(options.delay)
- : relativeDelay;
-
- maxDelay = Math.max(relativeDelay, 0);
- timings.animationDelay = relativeDelay;
- delayStyle = getCssDelayStyle(relativeDelay, true);
- temporaryStyles.push(delayStyle);
- node.style[delayStyle[0]] = delayStyle[1];
- }
-
- maxDelayTime = maxDelay * ONE_SECOND;
- maxDurationTime = maxDuration * ONE_SECOND;
-
- if (options.easing) {
- var easeProp, easeVal = options.easing;
- if (flags.hasTransitions) {
- easeProp = TRANSITION_PROP + TIMING_KEY;
- temporaryStyles.push([easeProp, easeVal]);
- node.style[easeProp] = easeVal;
- }
- if (flags.hasAnimations) {
- easeProp = ANIMATION_PROP + TIMING_KEY;
- temporaryStyles.push([easeProp, easeVal]);
- node.style[easeProp] = easeVal;
- }
- }
-
- if (timings.transitionDuration) {
- events.push(TRANSITIONEND_EVENT);
- }
-
- if (timings.animationDuration) {
- events.push(ANIMATIONEND_EVENT);
- }
-
- startTime = Date.now();
- var timerTime = maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime;
- var endTime = startTime + timerTime;
-
- var animationsData = element.data(ANIMATE_TIMER_KEY) || [];
- var setupFallbackTimer = true;
- if (animationsData.length) {
- var currentTimerData = animationsData[0];
- setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
- if (setupFallbackTimer) {
- $timeout.cancel(currentTimerData.timer);
- } else {
- animationsData.push(close);
- }
- }
-
- if (setupFallbackTimer) {
- var timer = $timeout(onAnimationExpired, timerTime, false);
- animationsData[0] = {
- timer: timer,
- expectedEndTime: endTime
- };
- animationsData.push(close);
- element.data(ANIMATE_TIMER_KEY, animationsData);
- }
-
- if (events.length) {
- element.on(events.join(' '), onAnimationProgress);
- }
-
- if (options.to) {
- if (options.cleanupStyles) {
- registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
- }
- applyAnimationToStyles(element, options);
- }
- }
-
- function onAnimationExpired() {
- var animationsData = element.data(ANIMATE_TIMER_KEY);
-
- // this will be false in the event that the element was
- // removed from the DOM (via a leave animation or something
- // similar)
- if (animationsData) {
- for (var i = 1; i < animationsData.length; i++) {
- animationsData[i]();
- }
- element.removeData(ANIMATE_TIMER_KEY);
- }
- }
- }
- };
- }];
-}];
-
-var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) {
- $$animationProvider.drivers.push('$$animateCssDriver');
-
- var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim';
- var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor';
-
- var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
- var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
-
- function isDocumentFragment(node) {
- return node.parentNode && node.parentNode.nodeType === 11;
- }
-
- this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document',
- function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) {
-
- // only browsers that support these properties can render animations
- if (!$sniffer.animations && !$sniffer.transitions) return noop;
-
- var bodyNode = $document[0].body;
- var rootNode = getDomNode($rootElement);
-
- var rootBodyElement = jqLite(
- // this is to avoid using something that exists outside of the body
- // we also special case the doc fragment case because our unit test code
- // appends the $rootElement to the body after the app has been bootstrapped
- isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
- );
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- return function initDriverFn(animationDetails) {
- return animationDetails.from && animationDetails.to
- ? prepareFromToAnchorAnimation(animationDetails.from,
- animationDetails.to,
- animationDetails.classes,
- animationDetails.anchors)
- : prepareRegularAnimation(animationDetails);
- };
-
- function filterCssClasses(classes) {
- //remove all the `ng-` stuff
- return classes.replace(/\bng-\S+\b/g, '');
- }
-
- function getUniqueValues(a, b) {
- if (isString(a)) a = a.split(' ');
- if (isString(b)) b = b.split(' ');
- return a.filter(function(val) {
- return b.indexOf(val) === -1;
- }).join(' ');
- }
-
- function prepareAnchoredAnimation(classes, outAnchor, inAnchor) {
- var clone = jqLite(getDomNode(outAnchor).cloneNode(true));
- var startingClasses = filterCssClasses(getClassVal(clone));
-
- outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
- inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
-
- clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME);
-
- rootBodyElement.append(clone);
-
- var animatorIn, animatorOut = prepareOutAnimation();
-
- // the user may not end up using the `out` animation and
- // only making use of the `in` animation or vice-versa.
- // In either case we should allow this and not assume the
- // animation is over unless both animations are not used.
- if (!animatorOut) {
- animatorIn = prepareInAnimation();
- if (!animatorIn) {
- return end();
- }
- }
-
- var startingAnimator = animatorOut || animatorIn;
-
- return {
- start: function() {
- var runner;
-
- var currentAnimation = startingAnimator.start();
- currentAnimation.done(function() {
- currentAnimation = null;
- if (!animatorIn) {
- animatorIn = prepareInAnimation();
- if (animatorIn) {
- currentAnimation = animatorIn.start();
- currentAnimation.done(function() {
- currentAnimation = null;
- end();
- runner.complete();
- });
- return currentAnimation;
- }
- }
- // in the event that there is no `in` animation
- end();
- runner.complete();
- });
-
- runner = new $$AnimateRunner({
- end: endFn,
- cancel: endFn
- });
-
- return runner;
-
- function endFn() {
- if (currentAnimation) {
- currentAnimation.end();
- }
- }
- }
- };
-
- function calculateAnchorStyles(anchor) {
- var styles = {};
-
- var coords = getDomNode(anchor).getBoundingClientRect();
-
- // we iterate directly since safari messes up and doesn't return
- // all the keys for the coords object when iterated
- forEach(['width','height','top','left'], function(key) {
- var value = coords[key];
- switch (key) {
- case 'top':
- value += bodyNode.scrollTop;
- break;
- case 'left':
- value += bodyNode.scrollLeft;
- break;
- }
- styles[key] = Math.floor(value) + 'px';
- });
- return styles;
- }
-
- function prepareOutAnimation() {
- var animator = $animateCss(clone, {
- addClass: NG_OUT_ANCHOR_CLASS_NAME,
- delay: true,
- from: calculateAnchorStyles(outAnchor)
- });
-
- // read the comment within `prepareRegularAnimation` to understand
- // why this check is necessary
- return animator.$$willAnimate ? animator : null;
- }
-
- function getClassVal(element) {
- return element.attr('class') || '';
- }
-
- function prepareInAnimation() {
- var endingClasses = filterCssClasses(getClassVal(inAnchor));
- var toAdd = getUniqueValues(endingClasses, startingClasses);
- var toRemove = getUniqueValues(startingClasses, endingClasses);
-
- var animator = $animateCss(clone, {
- to: calculateAnchorStyles(inAnchor),
- addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd,
- removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove,
- delay: true
- });
-
- // read the comment within `prepareRegularAnimation` to understand
- // why this check is necessary
- return animator.$$willAnimate ? animator : null;
- }
-
- function end() {
- clone.remove();
- outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
- inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
- }
- }
-
- function prepareFromToAnchorAnimation(from, to, classes, anchors) {
- var fromAnimation = prepareRegularAnimation(from, noop);
- var toAnimation = prepareRegularAnimation(to, noop);
-
- var anchorAnimations = [];
- forEach(anchors, function(anchor) {
- var outElement = anchor['out'];
- var inElement = anchor['in'];
- var animator = prepareAnchoredAnimation(classes, outElement, inElement);
- if (animator) {
- anchorAnimations.push(animator);
- }
- });
-
- // no point in doing anything when there are no elements to animate
- if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return;
-
- return {
- start: function() {
- var animationRunners = [];
-
- if (fromAnimation) {
- animationRunners.push(fromAnimation.start());
- }
-
- if (toAnimation) {
- animationRunners.push(toAnimation.start());
- }
-
- forEach(anchorAnimations, function(animation) {
- animationRunners.push(animation.start());
- });
-
- var runner = new $$AnimateRunner({
- end: endFn,
- cancel: endFn // CSS-driven animations cannot be cancelled, only ended
- });
-
- $$AnimateRunner.all(animationRunners, function(status) {
- runner.complete(status);
- });
-
- return runner;
-
- function endFn() {
- forEach(animationRunners, function(runner) {
- runner.end();
- });
- }
- }
- };
- }
-
- function prepareRegularAnimation(animationDetails) {
- var element = animationDetails.element;
- var options = animationDetails.options || {};
-
- if (animationDetails.structural) {
- options.event = animationDetails.event;
- options.structural = true;
- options.applyClassesEarly = true;
-
- // we special case the leave animation since we want to ensure that
- // the element is removed as soon as the animation is over. Otherwise
- // a flicker might appear or the element may not be removed at all
- if (animationDetails.event === 'leave') {
- options.onDone = options.domOperation;
- }
- }
-
- // We assign the preparationClasses as the actual animation event since
- // the internals of $animateCss will just suffix the event token values
- // with `-active` to trigger the animation.
- if (options.preparationClasses) {
- options.event = concatWithSpace(options.event, options.preparationClasses);
- }
-
- var animator = $animateCss(element, options);
-
- // the driver lookup code inside of $$animation attempts to spawn a
- // driver one by one until a driver returns a.$$willAnimate animator object.
- // $animateCss will always return an object, however, it will pass in
- // a flag as a hint as to whether an animation was detected or not
- return animator.$$willAnimate ? animator : null;
- }
- }];
-}];
-
-// TODO(matsko): use caching here to speed things up for detection
-// TODO(matsko): add documentation
-// by the time...
-
-var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
- this.$get = ['$injector', '$$AnimateRunner', '$$jqLite',
- function($injector, $$AnimateRunner, $$jqLite) {
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
- // $animateJs(element, 'enter');
- return function(element, event, classes, options) {
- var animationClosed = false;
-
- // the `classes` argument is optional and if it is not used
- // then the classes will be resolved from the element's className
- // property as well as options.addClass/options.removeClass.
- if (arguments.length === 3 && isObject(classes)) {
- options = classes;
- classes = null;
- }
-
- options = prepareAnimationOptions(options);
- if (!classes) {
- classes = element.attr('class') || '';
- if (options.addClass) {
- classes += ' ' + options.addClass;
- }
- if (options.removeClass) {
- classes += ' ' + options.removeClass;
- }
- }
-
- var classesToAdd = options.addClass;
- var classesToRemove = options.removeClass;
-
- // the lookupAnimations function returns a series of animation objects that are
- // matched up with one or more of the CSS classes. These animation objects are
- // defined via the module.animation factory function. If nothing is detected then
- // we don't return anything which then makes $animation query the next driver.
- var animations = lookupAnimations(classes);
- var before, after;
- if (animations.length) {
- var afterFn, beforeFn;
- if (event == 'leave') {
- beforeFn = 'leave';
- afterFn = 'afterLeave'; // TODO(matsko): get rid of this
- } else {
- beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1);
- afterFn = event;
- }
-
- if (event !== 'enter' && event !== 'move') {
- before = packageAnimations(element, event, options, animations, beforeFn);
- }
- after = packageAnimations(element, event, options, animations, afterFn);
- }
-
- // no matching animations
- if (!before && !after) return;
-
- function applyOptions() {
- options.domOperation();
- applyAnimationClasses(element, options);
- }
-
- function close() {
- animationClosed = true;
- applyOptions();
- applyAnimationStyles(element, options);
- }
-
- var runner;
-
- return {
- $$willAnimate: true,
- end: function() {
- if (runner) {
- runner.end();
- } else {
- close();
- runner = new $$AnimateRunner();
- runner.complete(true);
- }
- return runner;
- },
- start: function() {
- if (runner) {
- return runner;
- }
-
- runner = new $$AnimateRunner();
- var closeActiveAnimations;
- var chain = [];
-
- if (before) {
- chain.push(function(fn) {
- closeActiveAnimations = before(fn);
- });
- }
-
- if (chain.length) {
- chain.push(function(fn) {
- applyOptions();
- fn(true);
- });
- } else {
- applyOptions();
- }
-
- if (after) {
- chain.push(function(fn) {
- closeActiveAnimations = after(fn);
- });
- }
-
- runner.setHost({
- end: function() {
- endAnimations();
- },
- cancel: function() {
- endAnimations(true);
- }
- });
-
- $$AnimateRunner.chain(chain, onComplete);
- return runner;
-
- function onComplete(success) {
- close(success);
- runner.complete(success);
- }
-
- function endAnimations(cancelled) {
- if (!animationClosed) {
- (closeActiveAnimations || noop)(cancelled);
- onComplete(cancelled);
- }
- }
- }
- };
-
- function executeAnimationFn(fn, element, event, options, onDone) {
- var args;
- switch (event) {
- case 'animate':
- args = [element, options.from, options.to, onDone];
- break;
-
- case 'setClass':
- args = [element, classesToAdd, classesToRemove, onDone];
- break;
-
- case 'addClass':
- args = [element, classesToAdd, onDone];
- break;
-
- case 'removeClass':
- args = [element, classesToRemove, onDone];
- break;
-
- default:
- args = [element, onDone];
- break;
- }
-
- args.push(options);
-
- var value = fn.apply(fn, args);
- if (value) {
- if (isFunction(value.start)) {
- value = value.start();
- }
-
- if (value instanceof $$AnimateRunner) {
- value.done(onDone);
- } else if (isFunction(value)) {
- // optional onEnd / onCancel callback
- return value;
- }
- }
-
- return noop;
- }
-
- function groupEventedAnimations(element, event, options, animations, fnName) {
- var operations = [];
- forEach(animations, function(ani) {
- var animation = ani[fnName];
- if (!animation) return;
-
- // note that all of these animations will run in parallel
- operations.push(function() {
- var runner;
- var endProgressCb;
-
- var resolved = false;
- var onAnimationComplete = function(rejected) {
- if (!resolved) {
- resolved = true;
- (endProgressCb || noop)(rejected);
- runner.complete(!rejected);
- }
- };
-
- runner = new $$AnimateRunner({
- end: function() {
- onAnimationComplete();
- },
- cancel: function() {
- onAnimationComplete(true);
- }
- });
-
- endProgressCb = executeAnimationFn(animation, element, event, options, function(result) {
- var cancelled = result === false;
- onAnimationComplete(cancelled);
- });
-
- return runner;
- });
- });
-
- return operations;
- }
-
- function packageAnimations(element, event, options, animations, fnName) {
- var operations = groupEventedAnimations(element, event, options, animations, fnName);
- if (operations.length === 0) {
- var a,b;
- if (fnName === 'beforeSetClass') {
- a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass');
- b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass');
- } else if (fnName === 'setClass') {
- a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass');
- b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass');
- }
-
- if (a) {
- operations = operations.concat(a);
- }
- if (b) {
- operations = operations.concat(b);
- }
- }
-
- if (operations.length === 0) return;
-
- // TODO(matsko): add documentation
- return function startAnimation(callback) {
- var runners = [];
- if (operations.length) {
- forEach(operations, function(animateFn) {
- runners.push(animateFn());
- });
- }
-
- runners.length ? $$AnimateRunner.all(runners, callback) : callback();
-
- return function endFn(reject) {
- forEach(runners, function(runner) {
- reject ? runner.cancel() : runner.end();
- });
- };
- };
- }
- };
-
- function lookupAnimations(classes) {
- classes = isArray(classes) ? classes : classes.split(' ');
- var matches = [], flagMap = {};
- for (var i=0; i < classes.length; i++) {
- var klass = classes[i],
- animationFactory = $animateProvider.$$registeredAnimations[klass];
- if (animationFactory && !flagMap[klass]) {
- matches.push($injector.get(animationFactory));
- flagMap[klass] = true;
- }
- }
- return matches;
- }
- }];
-}];
-
-var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) {
- $$animationProvider.drivers.push('$$animateJsDriver');
- this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) {
- return function initDriverFn(animationDetails) {
- if (animationDetails.from && animationDetails.to) {
- var fromAnimation = prepareAnimation(animationDetails.from);
- var toAnimation = prepareAnimation(animationDetails.to);
- if (!fromAnimation && !toAnimation) return;
-
- return {
- start: function() {
- var animationRunners = [];
-
- if (fromAnimation) {
- animationRunners.push(fromAnimation.start());
- }
-
- if (toAnimation) {
- animationRunners.push(toAnimation.start());
- }
-
- $$AnimateRunner.all(animationRunners, done);
-
- var runner = new $$AnimateRunner({
- end: endFnFactory(),
- cancel: endFnFactory()
- });
-
- return runner;
-
- function endFnFactory() {
- return function() {
- forEach(animationRunners, function(runner) {
- // at this point we cannot cancel animations for groups just yet. 1.5+
- runner.end();
- });
- };
- }
-
- function done(status) {
- runner.complete(status);
- }
- }
- };
- } else {
- return prepareAnimation(animationDetails);
- }
- };
-
- function prepareAnimation(animationDetails) {
- // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations
- var element = animationDetails.element;
- var event = animationDetails.event;
- var options = animationDetails.options;
- var classes = animationDetails.classes;
- return $$animateJs(element, event, classes, options);
- }
- }];
-}];
-
-var NG_ANIMATE_ATTR_NAME = 'data-ng-animate';
-var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
-var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
- var PRE_DIGEST_STATE = 1;
- var RUNNING_STATE = 2;
- var ONE_SPACE = ' ';
-
- var rules = this.rules = {
- skip: [],
- cancel: [],
- join: []
- };
-
- function makeTruthyCssClassMap(classString) {
- if (!classString) {
- return null;
- }
-
- var keys = classString.split(ONE_SPACE);
- var map = Object.create(null);
-
- forEach(keys, function(key) {
- map[key] = true;
- });
- return map;
- }
-
- function hasMatchingClasses(newClassString, currentClassString) {
- if (newClassString && currentClassString) {
- var currentClassMap = makeTruthyCssClassMap(currentClassString);
- return newClassString.split(ONE_SPACE).some(function(className) {
- return currentClassMap[className];
- });
- }
- }
-
- function isAllowed(ruleType, element, currentAnimation, previousAnimation) {
- return rules[ruleType].some(function(fn) {
- return fn(element, currentAnimation, previousAnimation);
- });
- }
-
- function hasAnimationClasses(animation, and) {
- var a = (animation.addClass || '').length > 0;
- var b = (animation.removeClass || '').length > 0;
- return and ? a && b : a || b;
- }
-
- rules.join.push(function(element, newAnimation, currentAnimation) {
- // if the new animation is class-based then we can just tack that on
- return !newAnimation.structural && hasAnimationClasses(newAnimation);
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // there is no need to animate anything if no classes are being added and
- // there is no structural animation that will be triggered
- return !newAnimation.structural && !hasAnimationClasses(newAnimation);
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // why should we trigger a new structural animation if the element will
- // be removed from the DOM anyway?
- return currentAnimation.event == 'leave' && newAnimation.structural;
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // if there is an ongoing current animation then don't even bother running the class-based animation
- return currentAnimation.structural && currentAnimation.state === RUNNING_STATE && !newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- // there can never be two structural animations running at the same time
- return currentAnimation.structural && newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- // if the previous animation is already running, but the new animation will
- // be triggered, but the new animation is structural
- return currentAnimation.state === RUNNING_STATE && newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- var nA = newAnimation.addClass;
- var nR = newAnimation.removeClass;
- var cA = currentAnimation.addClass;
- var cR = currentAnimation.removeClass;
-
- // early detection to save the global CPU shortage :)
- if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) {
- return false;
- }
-
- return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
- });
-
- this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
- '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', '$$forceReflow',
- function($$rAF, $rootScope, $rootElement, $document, $$HashMap,
- $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) {
-
- var activeAnimationsLookup = new $$HashMap();
- var disabledElementsLookup = new $$HashMap();
- var animationsEnabled = null;
-
- function postDigestTaskFactory() {
- var postDigestCalled = false;
- return function(fn) {
- // we only issue a call to postDigest before
- // it has first passed. This prevents any callbacks
- // from not firing once the animation has completed
- // since it will be out of the digest cycle.
- if (postDigestCalled) {
- fn();
- } else {
- $rootScope.$$postDigest(function() {
- postDigestCalled = true;
- fn();
- });
- }
- };
- }
-
- // Wait until all directive and route-related templates are downloaded and
- // compiled. The $templateRequest.totalPendingRequests variable keeps track of
- // all of the remote templates being currently downloaded. If there are no
- // templates currently downloading then the watcher will still fire anyway.
- var deregisterWatch = $rootScope.$watch(
- function() { return $templateRequest.totalPendingRequests === 0; },
- function(isEmpty) {
- if (!isEmpty) return;
- deregisterWatch();
-
- // Now that all templates have been downloaded, $animate will wait until
- // the post digest queue is empty before enabling animations. By having two
- // calls to $postDigest calls we can ensure that the flag is enabled at the
- // very end of the post digest queue. Since all of the animations in $animate
- // use $postDigest, it's important that the code below executes at the end.
- // This basically means that the page is fully downloaded and compiled before
- // any animations are triggered.
- $rootScope.$$postDigest(function() {
- $rootScope.$$postDigest(function() {
- // we check for null directly in the event that the application already called
- // .enabled() with whatever arguments that it provided it with
- if (animationsEnabled === null) {
- animationsEnabled = true;
- }
- });
- });
- }
- );
-
- var callbackRegistry = {};
-
- // remember that the classNameFilter is set during the provider/config
- // stage therefore we can optimize here and setup a helper function
- var classNameFilter = $animateProvider.classNameFilter();
- var isAnimatableClassName = !classNameFilter
- ? function() { return true; }
- : function(className) {
- return classNameFilter.test(className);
- };
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- function normalizeAnimationDetails(element, animation) {
- return mergeAnimationDetails(element, animation, {});
- }
-
- // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
- var contains = Node.prototype.contains || function(arg) {
- // jshint bitwise: false
- return this === arg || !!(this.compareDocumentPosition(arg) & 16);
- // jshint bitwise: true
- };
-
- function findCallbacks(parent, element, event) {
- var targetNode = getDomNode(element);
- var targetParentNode = getDomNode(parent);
-
- var matches = [];
- var entries = callbackRegistry[event];
- if (entries) {
- forEach(entries, function(entry) {
- if (contains.call(entry.node, targetNode)) {
- matches.push(entry.callback);
- } else if (event === 'leave' && contains.call(entry.node, targetParentNode)) {
- matches.push(entry.callback);
- }
- });
- }
-
- return matches;
- }
-
- return {
- on: function(event, container, callback) {
- var node = extractElementNode(container);
- callbackRegistry[event] = callbackRegistry[event] || [];
- callbackRegistry[event].push({
- node: node,
- callback: callback
- });
- },
-
- off: function(event, container, callback) {
- var entries = callbackRegistry[event];
- if (!entries) return;
-
- callbackRegistry[event] = arguments.length === 1
- ? null
- : filterFromRegistry(entries, container, callback);
-
- function filterFromRegistry(list, matchContainer, matchCallback) {
- var containerNode = extractElementNode(matchContainer);
- return list.filter(function(entry) {
- var isMatch = entry.node === containerNode &&
- (!matchCallback || entry.callback === matchCallback);
- return !isMatch;
- });
- }
- },
-
- pin: function(element, parentElement) {
- assertArg(isElement(element), 'element', 'not an element');
- assertArg(isElement(parentElement), 'parentElement', 'not an element');
- element.data(NG_ANIMATE_PIN_DATA, parentElement);
- },
-
- push: function(element, event, options, domOperation) {
- options = options || {};
- options.domOperation = domOperation;
- return queueAnimation(element, event, options);
- },
-
- // this method has four signatures:
- // () - global getter
- // (bool) - global setter
- // (element) - element getter
- // (element, bool) - element setter<F37>
- enabled: function(element, bool) {
- var argCount = arguments.length;
-
- if (argCount === 0) {
- // () - Global getter
- bool = !!animationsEnabled;
- } else {
- var hasElement = isElement(element);
-
- if (!hasElement) {
- // (bool) - Global setter
- bool = animationsEnabled = !!element;
- } else {
- var node = getDomNode(element);
- var recordExists = disabledElementsLookup.get(node);
-
- if (argCount === 1) {
- // (element) - Element getter
- bool = !recordExists;
- } else {
- // (element, bool) - Element setter
- disabledElementsLookup.put(node, !bool);
- }
- }
- }
-
- return bool;
- }
- };
-
- function queueAnimation(element, event, initialOptions) {
- // we always make a copy of the options since
- // there should never be any side effects on
- // the input data when running `$animateCss`.
- var options = copy(initialOptions);
-
- var node, parent;
- element = stripCommentsFromElement(element);
- if (element) {
- node = getDomNode(element);
- parent = element.parent();
- }
-
- options = prepareAnimationOptions(options);
-
- // we create a fake runner with a working promise.
- // These methods will become available after the digest has passed
- var runner = new $$AnimateRunner();
-
- // this is used to trigger callbacks in postDigest mode
- var runInNextPostDigestOrNow = postDigestTaskFactory();
-
- if (isArray(options.addClass)) {
- options.addClass = options.addClass.join(' ');
- }
-
- if (options.addClass && !isString(options.addClass)) {
- options.addClass = null;
- }
-
- if (isArray(options.removeClass)) {
- options.removeClass = options.removeClass.join(' ');
- }
-
- if (options.removeClass && !isString(options.removeClass)) {
- options.removeClass = null;
- }
-
- if (options.from && !isObject(options.from)) {
- options.from = null;
- }
-
- if (options.to && !isObject(options.to)) {
- options.to = null;
- }
-
- // there are situations where a directive issues an animation for
- // a jqLite wrapper that contains only comment nodes... If this
- // happens then there is no way we can perform an animation
- if (!node) {
- close();
- return runner;
- }
-
- var className = [node.className, options.addClass, options.removeClass].join(' ');
- if (!isAnimatableClassName(className)) {
- close();
- return runner;
- }
-
- var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
-
- // this is a hard disable of all animations for the application or on
- // the element itself, therefore there is no need to continue further
- // past this point if not enabled
- // Animations are also disabled if the document is currently hidden (page is not visible
- // to the user), because browsers slow down or do not flush calls to requestAnimationFrame
- var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
- var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
- var hasExistingAnimation = !!existingAnimation.state;
-
- // there is no point in traversing the same collection of parent ancestors if a followup
- // animation will be run on the same element that already did all that checking work
- if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) {
- skipAnimations = !areAnimationsAllowed(element, parent, event);
- }
-
- if (skipAnimations) {
- close();
- return runner;
- }
-
- if (isStructural) {
- closeChildAnimations(element);
- }
-
- var newAnimation = {
- structural: isStructural,
- element: element,
- event: event,
- addClass: options.addClass,
- removeClass: options.removeClass,
- close: close,
- options: options,
- runner: runner
- };
-
- if (hasExistingAnimation) {
- var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation);
- if (skipAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- close();
- return runner;
- } else {
- mergeAnimationDetails(element, existingAnimation, newAnimation);
- return existingAnimation.runner;
- }
- }
- var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation);
- if (cancelAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- // this will end the animation right away and it is safe
- // to do so since the animation is already running and the
- // runner callback code will run in async
- existingAnimation.runner.end();
- } else if (existingAnimation.structural) {
- // this means that the animation is queued into a digest, but
- // hasn't started yet. Therefore it is safe to run the close
- // method which will call the runner methods in async.
- existingAnimation.close();
- } else {
- // this will merge the new animation options into existing animation options
- mergeAnimationDetails(element, existingAnimation, newAnimation);
-
- return existingAnimation.runner;
- }
- } else {
- // a joined animation means that this animation will take over the existing one
- // so an example would involve a leave animation taking over an enter. Then when
- // the postDigest kicks in the enter will be ignored.
- var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
- if (joinAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- normalizeAnimationDetails(element, newAnimation);
- } else {
- applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
-
- event = newAnimation.event = existingAnimation.event;
- options = mergeAnimationDetails(element, existingAnimation, newAnimation);
-
- //we return the same runner since only the option values of this animation will
- //be fed into the `existingAnimation`.
- return existingAnimation.runner;
- }
- }
- }
- } else {
- // normalization in this case means that it removes redundant CSS classes that
- // already exist (addClass) or do not exist (removeClass) on the element
- normalizeAnimationDetails(element, newAnimation);
- }
-
- // when the options are merged and cleaned up we may end up not having to do
- // an animation at all, therefore we should check this before issuing a post
- // digest callback. Structural animations will always run no matter what.
- var isValidAnimation = newAnimation.structural;
- if (!isValidAnimation) {
- // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
- isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
- || hasAnimationClasses(newAnimation);
- }
-
- if (!isValidAnimation) {
- close();
- clearElementAnimationState(element);
- return runner;
- }
-
- // the counter keeps track of cancelled animations
- var counter = (existingAnimation.counter || 0) + 1;
- newAnimation.counter = counter;
-
- markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation);
-
- $rootScope.$$postDigest(function() {
- var animationDetails = activeAnimationsLookup.get(node);
- var animationCancelled = !animationDetails;
- animationDetails = animationDetails || {};
-
- // if addClass/removeClass is called before something like enter then the
- // registered parent element may not be present. The code below will ensure
- // that a final value for parent element is obtained
- var parentElement = element.parent() || [];
-
- // animate/structural/class-based animations all have requirements. Otherwise there
- // is no point in performing an animation. The parent node must also be set.
- var isValidAnimation = parentElement.length > 0
- && (animationDetails.event === 'animate'
- || animationDetails.structural
- || hasAnimationClasses(animationDetails));
-
- // this means that the previous animation was cancelled
- // even if the follow-up animation is the same event
- if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) {
- // if another animation did not take over then we need
- // to make sure that the domOperation and options are
- // handled accordingly
- if (animationCancelled) {
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- }
-
- // if the event changed from something like enter to leave then we do
- // it, otherwise if it's the same then the end result will be the same too
- if (animationCancelled || (isStructural && animationDetails.event !== event)) {
- options.domOperation();
- runner.end();
- }
-
- // in the event that the element animation was not cancelled or a follow-up animation
- // isn't allowed to animate from here then we need to clear the state of the element
- // so that any future animations won't read the expired animation data.
- if (!isValidAnimation) {
- clearElementAnimationState(element);
- }
-
- return;
- }
-
- // this combined multiple class to addClass / removeClass into a setClass event
- // so long as a structural event did not take over the animation
- event = !animationDetails.structural && hasAnimationClasses(animationDetails, true)
- ? 'setClass'
- : animationDetails.event;
-
- markElementAnimationState(element, RUNNING_STATE);
- var realRunner = $$animation(element, event, animationDetails.options);
-
- realRunner.done(function(status) {
- close(!status);
- var animationDetails = activeAnimationsLookup.get(node);
- if (animationDetails && animationDetails.counter === counter) {
- clearElementAnimationState(getDomNode(element));
- }
- notifyProgress(runner, event, 'close', {});
- });
-
- // this will update the runner's flow-control events based on
- // the `realRunner` object.
- runner.setHost(realRunner);
- notifyProgress(runner, event, 'start', {});
- });
-
- return runner;
-
- function notifyProgress(runner, event, phase, data) {
- runInNextPostDigestOrNow(function() {
- var callbacks = findCallbacks(parent, element, event);
- if (callbacks.length) {
- // do not optimize this call here to RAF because
- // we don't know how heavy the callback code here will
- // be and if this code is buffered then this can
- // lead to a performance regression.
- $$rAF(function() {
- forEach(callbacks, function(callback) {
- callback(element, phase, data);
- });
- });
- }
- });
- runner.progress(event, phase, data);
- }
-
- function close(reject) { // jshint ignore:line
- clearGeneratedClasses(element, options);
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- options.domOperation();
- runner.complete(!reject);
- }
- }
-
- function closeChildAnimations(element) {
- var node = getDomNode(element);
- var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']');
- forEach(children, function(child) {
- var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME));
- var animationDetails = activeAnimationsLookup.get(child);
- if (animationDetails) {
- switch (state) {
- case RUNNING_STATE:
- animationDetails.runner.end();
- /* falls through */
- case PRE_DIGEST_STATE:
- activeAnimationsLookup.remove(child);
- break;
- }
- }
- });
- }
-
- function clearElementAnimationState(element) {
- var node = getDomNode(element);
- node.removeAttribute(NG_ANIMATE_ATTR_NAME);
- activeAnimationsLookup.remove(node);
- }
-
- function isMatchingElement(nodeOrElmA, nodeOrElmB) {
- return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
- }
-
- /**
- * This fn returns false if any of the following is true:
- * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
- * b) a parent element has an ongoing structural animation, and animateChildren is false
- * c) the element is not a child of the body
- * d) the element is not a child of the $rootElement
- */
- function areAnimationsAllowed(element, parentElement, event) {
- var bodyElement = jqLite($document[0].body);
- var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
- var rootElementDetected = isMatchingElement(element, $rootElement);
- var parentAnimationDetected = false;
- var animateChildren;
- var elementDisabled = disabledElementsLookup.get(getDomNode(element));
-
- var parentHost = element.data(NG_ANIMATE_PIN_DATA);
- if (parentHost) {
- parentElement = parentHost;
- }
-
- while (parentElement && parentElement.length) {
- if (!rootElementDetected) {
- // angular doesn't want to attempt to animate elements outside of the application
- // therefore we need to ensure that the rootElement is an ancestor of the current element
- rootElementDetected = isMatchingElement(parentElement, $rootElement);
- }
-
- var parentNode = parentElement[0];
- if (parentNode.nodeType !== ELEMENT_NODE) {
- // no point in inspecting the #document element
- break;
- }
-
- var details = activeAnimationsLookup.get(parentNode) || {};
- // either an enter, leave or move animation will commence
- // therefore we can't allow any animations to take place
- // but if a parent animation is class-based then that's ok
- if (!parentAnimationDetected) {
- var parentElementDisabled = disabledElementsLookup.get(parentNode);
-
- if (parentElementDisabled === true && elementDisabled !== false) {
- // disable animations if the user hasn't explicitly enabled animations on the
- // current element
- elementDisabled = true;
- // element is disabled via parent element, no need to check anything else
- break;
- } else if (parentElementDisabled === false) {
- elementDisabled = false;
- }
- parentAnimationDetected = details.structural;
- }
-
- if (isUndefined(animateChildren) || animateChildren === true) {
- var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA);
- if (isDefined(value)) {
- animateChildren = value;
- }
- }
-
- // there is no need to continue traversing at this point
- if (parentAnimationDetected && animateChildren === false) break;
-
- if (!bodyElementDetected) {
- // we also need to ensure that the element is or will be a part of the body element
- // otherwise it is pointless to even issue an animation to be rendered
- bodyElementDetected = isMatchingElement(parentElement, bodyElement);
- }
-
- if (bodyElementDetected && rootElementDetected) {
- // If both body and root have been found, any other checks are pointless,
- // as no animation data should live outside the application
- break;
- }
-
- if (!rootElementDetected) {
- // If no rootElement is detected, check if the parentElement is pinned to another element
- parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
- if (parentHost) {
- // The pin target element becomes the next parent element
- parentElement = parentHost;
- continue;
- }
- }
-
- parentElement = parentElement.parent();
- }
-
- var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true;
- return allowAnimation && rootElementDetected && bodyElementDetected;
- }
-
- function markElementAnimationState(element, state, details) {
- details = details || {};
- details.state = state;
-
- var node = getDomNode(element);
- node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
-
- var oldValue = activeAnimationsLookup.get(node);
- var newValue = oldValue
- ? extend(oldValue, details)
- : details;
- activeAnimationsLookup.put(node, newValue);
- }
- }];
-}];
-
-var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
- var NG_ANIMATE_REF_ATTR = 'ng-animate-ref';
-
- var drivers = this.drivers = [];
-
- var RUNNER_STORAGE_KEY = '$$animationRunner';
-
- function setRunner(element, runner) {
- element.data(RUNNER_STORAGE_KEY, runner);
- }
-
- function removeRunner(element) {
- element.removeData(RUNNER_STORAGE_KEY);
- }
-
- function getRunner(element) {
- return element.data(RUNNER_STORAGE_KEY);
- }
-
- this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$HashMap', '$$rAFScheduler',
- function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap, $$rAFScheduler) {
-
- var animationQueue = [];
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- function sortAnimations(animations) {
- var tree = { children: [] };
- var i, lookup = new $$HashMap();
-
- // this is done first beforehand so that the hashmap
- // is filled with a list of the elements that will be animated
- for (i = 0; i < animations.length; i++) {
- var animation = animations[i];
- lookup.put(animation.domNode, animations[i] = {
- domNode: animation.domNode,
- fn: animation.fn,
- children: []
- });
- }
-
- for (i = 0; i < animations.length; i++) {
- processNode(animations[i]);
- }
-
- return flatten(tree);
-
- function processNode(entry) {
- if (entry.processed) return entry;
- entry.processed = true;
-
- var elementNode = entry.domNode;
- var parentNode = elementNode.parentNode;
- lookup.put(elementNode, entry);
-
- var parentEntry;
- while (parentNode) {
- parentEntry = lookup.get(parentNode);
- if (parentEntry) {
- if (!parentEntry.processed) {
- parentEntry = processNode(parentEntry);
- }
- break;
- }
- parentNode = parentNode.parentNode;
- }
-
- (parentEntry || tree).children.push(entry);
- return entry;
- }
-
- function flatten(tree) {
- var result = [];
- var queue = [];
- var i;
-
- for (i = 0; i < tree.children.length; i++) {
- queue.push(tree.children[i]);
- }
-
- var remainingLevelEntries = queue.length;
- var nextLevelEntries = 0;
- var row = [];
-
- for (i = 0; i < queue.length; i++) {
- var entry = queue[i];
- if (remainingLevelEntries <= 0) {
- remainingLevelEntries = nextLevelEntries;
- nextLevelEntries = 0;
- result.push(row);
- row = [];
- }
- row.push(entry.fn);
- entry.children.forEach(function(childEntry) {
- nextLevelEntries++;
- queue.push(childEntry);
- });
- remainingLevelEntries--;
- }
-
- if (row.length) {
- result.push(row);
- }
-
- return result;
- }
- }
-
- // TODO(matsko): document the signature in a better way
- return function(element, event, options) {
- options = prepareAnimationOptions(options);
- var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
-
- // there is no animation at the current moment, however
- // these runner methods will get later updated with the
- // methods leading into the driver's end/cancel methods
- // for now they just stop the animation from starting
- var runner = new $$AnimateRunner({
- end: function() { close(); },
- cancel: function() { close(true); }
- });
-
- if (!drivers.length) {
- close();
- return runner;
- }
-
- setRunner(element, runner);
-
- var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
- var tempClasses = options.tempClasses;
- if (tempClasses) {
- classes += ' ' + tempClasses;
- options.tempClasses = null;
- }
-
- var prepareClassName;
- if (isStructural) {
- prepareClassName = 'ng-' + event + PREPARE_CLASS_SUFFIX;
- $$jqLite.addClass(element, prepareClassName);
- }
-
- animationQueue.push({
- // this data is used by the postDigest code and passed into
- // the driver step function
- element: element,
- classes: classes,
- event: event,
- structural: isStructural,
- options: options,
- beforeStart: beforeStart,
- close: close
- });
-
- element.on('$destroy', handleDestroyedElement);
-
- // we only want there to be one function called within the post digest
- // block. This way we can group animations for all the animations that
- // were apart of the same postDigest flush call.
- if (animationQueue.length > 1) return runner;
-
- $rootScope.$$postDigest(function() {
- var animations = [];
- forEach(animationQueue, function(entry) {
- // the element was destroyed early on which removed the runner
- // form its storage. This means we can't animate this element
- // at all and it already has been closed due to destruction.
- if (getRunner(entry.element)) {
- animations.push(entry);
- } else {
- entry.close();
- }
- });
-
- // now any future animations will be in another postDigest
- animationQueue.length = 0;
-
- var groupedAnimations = groupAnimations(animations);
- var toBeSortedAnimations = [];
-
- forEach(groupedAnimations, function(animationEntry) {
- toBeSortedAnimations.push({
- domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element),
- fn: function triggerAnimationStart() {
- // it's important that we apply the `ng-animate` CSS class and the
- // temporary classes before we do any driver invoking since these
- // CSS classes may be required for proper CSS detection.
- animationEntry.beforeStart();
-
- var startAnimationFn, closeFn = animationEntry.close;
-
- // in the event that the element was removed before the digest runs or
- // during the RAF sequencing then we should not trigger the animation.
- var targetElement = animationEntry.anchors
- ? (animationEntry.from.element || animationEntry.to.element)
- : animationEntry.element;
-
- if (getRunner(targetElement)) {
- var operation = invokeFirstDriver(animationEntry);
- if (operation) {
- startAnimationFn = operation.start;
- }
- }
-
- if (!startAnimationFn) {
- closeFn();
- } else {
- var animationRunner = startAnimationFn();
- animationRunner.done(function(status) {
- closeFn(!status);
- });
- updateAnimationRunners(animationEntry, animationRunner);
- }
- }
- });
- });
-
- // we need to sort each of the animations in order of parent to child
- // relationships. This ensures that the child classes are applied at the
- // right time.
- $$rAFScheduler(sortAnimations(toBeSortedAnimations));
- });
-
- return runner;
-
- // TODO(matsko): change to reference nodes
- function getAnchorNodes(node) {
- var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']';
- var items = node.hasAttribute(NG_ANIMATE_REF_ATTR)
- ? [node]
- : node.querySelectorAll(SELECTOR);
- var anchors = [];
- forEach(items, function(node) {
- var attr = node.getAttribute(NG_ANIMATE_REF_ATTR);
- if (attr && attr.length) {
- anchors.push(node);
- }
- });
- return anchors;
- }
-
- function groupAnimations(animations) {
- var preparedAnimations = [];
- var refLookup = {};
- forEach(animations, function(animation, index) {
- var element = animation.element;
- var node = getDomNode(element);
- var event = animation.event;
- var enterOrMove = ['enter', 'move'].indexOf(event) >= 0;
- var anchorNodes = animation.structural ? getAnchorNodes(node) : [];
-
- if (anchorNodes.length) {
- var direction = enterOrMove ? 'to' : 'from';
-
- forEach(anchorNodes, function(anchor) {
- var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR);
- refLookup[key] = refLookup[key] || {};
- refLookup[key][direction] = {
- animationID: index,
- element: jqLite(anchor)
- };
- });
- } else {
- preparedAnimations.push(animation);
- }
- });
-
- var usedIndicesLookup = {};
- var anchorGroups = {};
- forEach(refLookup, function(operations, key) {
- var from = operations.from;
- var to = operations.to;
-
- if (!from || !to) {
- // only one of these is set therefore we can't have an
- // anchor animation since all three pieces are required
- var index = from ? from.animationID : to.animationID;
- var indexKey = index.toString();
- if (!usedIndicesLookup[indexKey]) {
- usedIndicesLookup[indexKey] = true;
- preparedAnimations.push(animations[index]);
- }
- return;
- }
-
- var fromAnimation = animations[from.animationID];
- var toAnimation = animations[to.animationID];
- var lookupKey = from.animationID.toString();
- if (!anchorGroups[lookupKey]) {
- var group = anchorGroups[lookupKey] = {
- structural: true,
- beforeStart: function() {
- fromAnimation.beforeStart();
- toAnimation.beforeStart();
- },
- close: function() {
- fromAnimation.close();
- toAnimation.close();
- },
- classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes),
- from: fromAnimation,
- to: toAnimation,
- anchors: [] // TODO(matsko): change to reference nodes
- };
-
- // the anchor animations require that the from and to elements both have at least
- // one shared CSS class which effectively marries the two elements together to use
- // the same animation driver and to properly sequence the anchor animation.
- if (group.classes.length) {
- preparedAnimations.push(group);
- } else {
- preparedAnimations.push(fromAnimation);
- preparedAnimations.push(toAnimation);
- }
- }
-
- anchorGroups[lookupKey].anchors.push({
- 'out': from.element, 'in': to.element
- });
- });
-
- return preparedAnimations;
- }
-
- function cssClassesIntersection(a,b) {
- a = a.split(' ');
- b = b.split(' ');
- var matches = [];
-
- for (var i = 0; i < a.length; i++) {
- var aa = a[i];
- if (aa.substring(0,3) === 'ng-') continue;
-
- for (var j = 0; j < b.length; j++) {
- if (aa === b[j]) {
- matches.push(aa);
- break;
- }
- }
- }
-
- return matches.join(' ');
- }
-
- function invokeFirstDriver(animationDetails) {
- // we loop in reverse order since the more general drivers (like CSS and JS)
- // may attempt more elements, but custom drivers are more particular
- for (var i = drivers.length - 1; i >= 0; i--) {
- var driverName = drivers[i];
- if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check
-
- var factory = $injector.get(driverName);
- var driver = factory(animationDetails);
- if (driver) {
- return driver;
- }
- }
- }
-
- function beforeStart() {
- element.addClass(NG_ANIMATE_CLASSNAME);
- if (tempClasses) {
- $$jqLite.addClass(element, tempClasses);
- }
- if (prepareClassName) {
- $$jqLite.removeClass(element, prepareClassName);
- prepareClassName = null;
- }
- }
-
- function updateAnimationRunners(animation, newRunner) {
- if (animation.from && animation.to) {
- update(animation.from.element);
- update(animation.to.element);
- } else {
- update(animation.element);
- }
-
- function update(element) {
- getRunner(element).setHost(newRunner);
- }
- }
-
- function handleDestroyedElement() {
- var runner = getRunner(element);
- if (runner && (event !== 'leave' || !options.$$domOperationFired)) {
- runner.end();
- }
- }
-
- function close(rejected) { // jshint ignore:line
- element.off('$destroy', handleDestroyedElement);
- removeRunner(element);
-
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- options.domOperation();
-
- if (tempClasses) {
- $$jqLite.removeClass(element, tempClasses);
- }
-
- element.removeClass(NG_ANIMATE_CLASSNAME);
- runner.complete(!rejected);
- }
- };
- }];
-}];
-
-/**
- * @ngdoc directive
- * @name ngAnimateSwap
- * @restrict A
- * @scope
- *
- * @description
- *
- * ngAnimateSwap is a animation-oriented directive that allows for the container to
- * be removed and entered in whenever the associated expression changes. A
- * common usecase for this directive is a rotating banner component which
- * contains one image being present at a time. When the active image changes
- * then the old image will perform a `leave` animation and the new element
- * will be inserted via an `enter` animation.
- *
- * @example
- * <example name="ngAnimateSwap-directive" module="ngAnimateSwapExample"
- * deps="angular-animate.js"
- * animations="true" fixBase="true">
- * <file name="index.html">
- * <div class="container" ng-controller="AppCtrl">
- * <div ng-animate-swap="number" class="cell swap-animation" ng-class="colorClass(number)">
- * {{ number }}
- * </div>
- * </div>
- * </file>
- * <file name="script.js">
- * angular.module('ngAnimateSwapExample', ['ngAnimate'])
- * .controller('AppCtrl', ['$scope', '$interval', function($scope, $interval) {
- * $scope.number = 0;
- * $interval(function() {
- * $scope.number++;
- * }, 1000);
- *
- * var colors = ['red','blue','green','yellow','orange'];
- * $scope.colorClass = function(number) {
- * return colors[number % colors.length];
- * };
- * }]);
- * </file>
- * <file name="animations.css">
- * .container {
- * height:250px;
- * width:250px;
- * position:relative;
- * overflow:hidden;
- * border:2px solid black;
- * }
- * .container .cell {
- * font-size:150px;
- * text-align:center;
- * line-height:250px;
- * position:absolute;
- * top:0;
- * left:0;
- * right:0;
- * border-bottom:2px solid black;
- * }
- * .swap-animation.ng-enter, .swap-animation.ng-leave {
- * transition:0.5s linear all;
- * }
- * .swap-animation.ng-enter {
- * top:-250px;
- * }
- * .swap-animation.ng-enter-active {
- * top:0px;
- * }
- * .swap-animation.ng-leave {
- * top:0px;
- * }
- * .swap-animation.ng-leave-active {
- * top:250px;
- * }
- * .red { background:red; }
- * .green { background:green; }
- * .blue { background:blue; }
- * .yellow { background:yellow; }
- * .orange { background:orange; }
- * </file>
- * </example>
- */
-var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $rootScope) {
- return {
- restrict: 'A',
- transclude: 'element',
- terminal: true,
- priority: 600, // we use 600 here to ensure that the directive is caught before others
- link: function(scope, $element, attrs, ctrl, $transclude) {
- var previousElement, previousScope;
- scope.$watchCollection(attrs.ngAnimateSwap || attrs['for'], function(value) {
- if (previousElement) {
- $animate.leave(previousElement);
- }
- if (previousScope) {
- previousScope.$destroy();
- previousScope = null;
- }
- if (value || value === 0) {
- previousScope = scope.$new();
- $transclude(previousScope, function(element) {
- previousElement = element;
- $animate.enter(element, null, $element);
- });
- }
- });
- }
- };
-}];
-
-/* global angularAnimateModule: true,
-
- ngAnimateSwapDirective,
- $$AnimateAsyncRunFactory,
- $$rAFSchedulerFactory,
- $$AnimateChildrenDirective,
- $$AnimateQueueProvider,
- $$AnimationProvider,
- $AnimateCssProvider,
- $$AnimateCssDriverProvider,
- $$AnimateJsProvider,
- $$AnimateJsDriverProvider,
-*/
-
-/**
- * @ngdoc module
- * @name ngAnimate
- * @description
- *
- * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
- * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an Angular app.
- *
- * <div doc-module-components="ngAnimate"></div>
- *
- * # Usage
- * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
- * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For
- * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within
- * the HTML element that the animation will be triggered on.
- *
- * ## Directive Support
- * The following directives are "animation aware":
- *
- * | Directive | Supported Animations |
- * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
- * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
- * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
- * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
- * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
- * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
- * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
- * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
- * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
- * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
- * | {@link module:ngMessages#animations ngMessage} | enter and leave |
- *
- * (More information can be found by visiting each the documentation associated with each directive.)
- *
- * ## CSS-based Animations
- *
- * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
- * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation.
- *
- * The example below shows how an `enter` animation can be made possible on an element using `ng-if`:
- *
- * ```html
- * <div ng-if="bool" class="fade">
- * Fade me in out
- * </div>
- * <button ng-click="bool=true">Fade In!</button>
- * <button ng-click="bool=false">Fade Out!</button>
- * ```
- *
- * Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
- *
- * ```css
- * /&#42; The starting CSS styles for the enter animation &#42;/
- * .fade.ng-enter {
- * transition:0.5s linear all;
- * opacity:0;
- * }
- *
- * /&#42; The finishing CSS styles for the enter animation &#42;/
- * .fade.ng-enter.ng-enter-active {
- * opacity:1;
- * }
- * ```
- *
- * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two
- * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition
- * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards.
- *
- * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions:
- *
- * ```css
- * /&#42; now the element will fade out before it is removed from the DOM &#42;/
- * .fade.ng-leave {
- * transition:0.5s linear all;
- * opacity:1;
- * }
- * .fade.ng-leave.ng-leave-active {
- * opacity:0;
- * }
- * ```
- *
- * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class:
- *
- * ```css
- * /&#42; there is no need to define anything inside of the destination
- * CSS class since the keyframe will take charge of the animation &#42;/
- * .fade.ng-leave {
- * animation: my_fade_animation 0.5s linear;
- * -webkit-animation: my_fade_animation 0.5s linear;
- * }
- *
- * @keyframes my_fade_animation {
- * from { opacity:1; }
- * to { opacity:0; }
- * }
- *
- * @-webkit-keyframes my_fade_animation {
- * from { opacity:1; }
- * to { opacity:0; }
- * }
- * ```
- *
- * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element.
- *
- * ### CSS Class-based Animations
- *
- * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different
- * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added
- * and removed.
- *
- * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class:
- *
- * ```html
- * <div ng-show="bool" class="fade">
- * Show and hide me
- * </div>
- * <button ng-click="bool=true">Toggle</button>
- *
- * <style>
- * .fade.ng-hide {
- * transition:0.5s linear all;
- * opacity:0;
- * }
- * </style>
- * ```
- *
- * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since
- * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest.
- *
- * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation
- * with CSS styles.
- *
- * ```html
- * <div ng-class="{on:onOff}" class="highlight">
- * Highlight this box
- * </div>
- * <button ng-click="onOff=!onOff">Toggle</button>
- *
- * <style>
- * .highlight {
- * transition:0.5s linear all;
- * }
- * .highlight.on-add {
- * background:white;
- * }
- * .highlight.on {
- * background:yellow;
- * }
- * .highlight.on-remove {
- * background:black;
- * }
- * </style>
- * ```
- *
- * We can also make use of CSS keyframes by placing them within the CSS classes.
- *
- *
- * ### CSS Staggering Animations
- * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
- * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
- * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
- * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
- * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
- *
- * ```css
- * .my-animation.ng-enter {
- * /&#42; standard transition code &#42;/
- * transition: 1s linear all;
- * opacity:0;
- * }
- * .my-animation.ng-enter-stagger {
- * /&#42; this will have a 100ms delay between each successive leave animation &#42;/
- * transition-delay: 0.1s;
- *
- * /&#42; As of 1.4.4, this must always be set: it signals ngAnimate
- * to not accidentally inherit a delay property from another CSS class &#42;/
- * transition-duration: 0s;
- * }
- * .my-animation.ng-enter.ng-enter-active {
- * /&#42; standard transition styles &#42;/
- * opacity:1;
- * }
- * ```
- *
- * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
- * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
- * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
- * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired.
- *
- * The following code will issue the **ng-leave-stagger** event on the element provided:
- *
- * ```js
- * var kids = parent.children();
- *
- * $animate.leave(kids[0]); //stagger index=0
- * $animate.leave(kids[1]); //stagger index=1
- * $animate.leave(kids[2]); //stagger index=2
- * $animate.leave(kids[3]); //stagger index=3
- * $animate.leave(kids[4]); //stagger index=4
- *
- * window.requestAnimationFrame(function() {
- * //stagger has reset itself
- * $animate.leave(kids[5]); //stagger index=0
- * $animate.leave(kids[6]); //stagger index=1
- *
- * $scope.$digest();
- * });
- * ```
- *
- * Stagger animations are currently only supported within CSS-defined animations.
- *
- * ### The `ng-animate` CSS class
- *
- * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation.
- * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations).
- *
- * Therefore, animations can be applied to an element using this temporary class directly via CSS.
- *
- * ```css
- * .zipper.ng-animate {
- * transition:0.5s linear all;
- * }
- * .zipper.ng-enter {
- * opacity:0;
- * }
- * .zipper.ng-enter.ng-enter-active {
- * opacity:1;
- * }
- * .zipper.ng-leave {
- * opacity:1;
- * }
- * .zipper.ng-leave.ng-leave-active {
- * opacity:0;
- * }
- * ```
- *
- * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove
- * the CSS class once an animation has completed.)
- *
- *
- * ### The `ng-[event]-prepare` class
- *
- * This is a special class that can be used to prevent unwanted flickering / flash of content before
- * the actual animation starts. The class is added as soon as an animation is initialized, but removed
- * before the actual animation starts (after waiting for a $digest).
- * It is also only added for *structural* animations (`enter`, `move`, and `leave`).
- *
- * In practice, flickering can appear when nesting elements with structural animations such as `ngIf`
- * into elements that have class-based animations such as `ngClass`.
- *
- * ```html
- * <div ng-class="{red: myProp}">
- * <div ng-class="{blue: myProp}">
- * <div class="message" ng-if="myProp"></div>
- * </div>
- * </div>
- * ```
- *
- * It is possible that during the `enter` animation, the `.message` div will be briefly visible before it starts animating.
- * In that case, you can add styles to the CSS that make sure the element stays hidden before the animation starts:
- *
- * ```css
- * .message.ng-enter-prepare {
- * opacity: 0;
- * }
- *
- * ```
- *
- * ## JavaScript-based Animations
- *
- * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
- * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
- * `module.animation()` module function we can register the animation.
- *
- * Let's see an example of a enter/leave animation using `ngRepeat`:
- *
- * ```html
- * <div ng-repeat="item in items" class="slide">
- * {{ item }}
- * </div>
- * ```
- *
- * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`:
- *
- * ```js
- * myModule.animation('.slide', [function() {
- * return {
- * // make note that other events (like addClass/removeClass)
- * // have different function input parameters
- * enter: function(element, doneFn) {
- * jQuery(element).fadeIn(1000, doneFn);
- *
- * // remember to call doneFn so that angular
- * // knows that the animation has concluded
- * },
- *
- * move: function(element, doneFn) {
- * jQuery(element).fadeIn(1000, doneFn);
- * },
- *
- * leave: function(element, doneFn) {
- * jQuery(element).fadeOut(1000, doneFn);
- * }
- * }
- * }]);
- * ```
- *
- * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
- * greensock.js and velocity.js.
- *
- * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define
- * our animations inside of the same registered animation, however, the function input arguments are a bit different:
- *
- * ```html
- * <div ng-class="color" class="colorful">
- * this box is moody
- * </div>
- * <button ng-click="color='red'">Change to red</button>
- * <button ng-click="color='blue'">Change to blue</button>
- * <button ng-click="color='green'">Change to green</button>
- * ```
- *
- * ```js
- * myModule.animation('.colorful', [function() {
- * return {
- * addClass: function(element, className, doneFn) {
- * // do some cool animation and call the doneFn
- * },
- * removeClass: function(element, className, doneFn) {
- * // do some cool animation and call the doneFn
- * },
- * setClass: function(element, addedClass, removedClass, doneFn) {
- * // do some cool animation and call the doneFn
- * }
- * }
- * }]);
- * ```
- *
- * ## CSS + JS Animations Together
- *
- * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
- * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
- * charge of the animation**:
- *
- * ```html
- * <div ng-if="bool" class="slide">
- * Slide in and out
- * </div>
- * ```
- *
- * ```js
- * myModule.animation('.slide', [function() {
- * return {
- * enter: function(element, doneFn) {
- * jQuery(element).slideIn(1000, doneFn);
- * }
- * }
- * }]);
- * ```
- *
- * ```css
- * .slide.ng-enter {
- * transition:0.5s linear all;
- * transform:translateY(-100px);
- * }
- * .slide.ng-enter.ng-enter-active {
- * transform:translateY(0);
- * }
- * ```
- *
- * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the
- * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from
- * our own JS-based animation code:
- *
- * ```js
- * myModule.animation('.slide', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element) {
-* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
- * return $animateCss(element, {
- * event: 'enter',
- * structural: true
- * });
- * }
- * }
- * }]);
- * ```
- *
- * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
- *
- * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or
- * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that
- * data into `$animateCss` directly:
- *
- * ```js
- * myModule.animation('.slide', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element) {
- * return $animateCss(element, {
- * event: 'enter',
- * structural: true,
- * addClass: 'maroon-setting',
- * from: { height:0 },
- * to: { height: 200 }
- * });
- * }
- * }
- * }]);
- * ```
- *
- * Now we can fill in the rest via our transition CSS code:
- *
- * ```css
- * /&#42; the transition tells ngAnimate to make the animation happen &#42;/
- * .slide.ng-enter { transition:0.5s linear all; }
- *
- * /&#42; this extra CSS class will be absorbed into the transition
- * since the $animateCss code is adding the class &#42;/
- * .maroon-setting { background:red; }
- * ```
- *
- * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over.
- *
- * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
- *
- * ## Animation Anchoring (via `ng-animate-ref`)
- *
- * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
- * structural areas of an application (like views) by pairing up elements using an attribute
- * called `ng-animate-ref`.
- *
- * Let's say for example we have two views that are managed by `ng-view` and we want to show
- * that there is a relationship between two components situated in within these views. By using the
- * `ng-animate-ref` attribute we can identify that the two components are paired together and we
- * can then attach an animation, which is triggered when the view changes.
- *
- * Say for example we have the following template code:
- *
- * ```html
- * <!-- index.html -->
- * <div ng-view class="view-animation">
- * </div>
- *
- * <!-- home.html -->
- * <a href="#/banner-page">
- * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
- * </a>
- *
- * <!-- banner-page.html -->
- * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
- * ```
- *
- * Now, when the view changes (once the link is clicked), ngAnimate will examine the
- * HTML contents to see if there is a match reference between any components in the view
- * that is leaving and the view that is entering. It will scan both the view which is being
- * removed (leave) and inserted (enter) to see if there are any paired DOM elements that
- * contain a matching ref value.
- *
- * The two images match since they share the same ref value. ngAnimate will now create a
- * transport element (which is a clone of the first image element) and it will then attempt
- * to animate to the position of the second image element in the next view. For the animation to
- * work a special CSS class called `ng-anchor` will be added to the transported element.
- *
- * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then
- * ngAnimate will handle the entire transition for us as well as the addition and removal of
- * any changes of CSS classes between the elements:
- *
- * ```css
- * .banner.ng-anchor {
- * /&#42; this animation will last for 1 second since there are
- * two phases to the animation (an `in` and an `out` phase) &#42;/
- * transition:0.5s linear all;
- * }
- * ```
- *
- * We also **must** include animations for the views that are being entered and removed
- * (otherwise anchoring wouldn't be possible since the new view would be inserted right away).
- *
- * ```css
- * .view-animation.ng-enter, .view-animation.ng-leave {
- * transition:0.5s linear all;
- * position:fixed;
- * left:0;
- * top:0;
- * width:100%;
- * }
- * .view-animation.ng-enter {
- * transform:translateX(100%);
- * }
- * .view-animation.ng-leave,
- * .view-animation.ng-enter.ng-enter-active {
- * transform:translateX(0%);
- * }
- * .view-animation.ng-leave.ng-leave-active {
- * transform:translateX(-100%);
- * }
- * ```
- *
- * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur:
- * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away
- * from its origin. Once that animation is over then the `in` stage occurs which animates the
- * element to its destination. The reason why there are two animations is to give enough time
- * for the enter animation on the new element to be ready.
- *
- * The example above sets up a transition for both the in and out phases, but we can also target the out or
- * in phases directly via `ng-anchor-out` and `ng-anchor-in`.
- *
- * ```css
- * .banner.ng-anchor-out {
- * transition: 0.5s linear all;
- *
- * /&#42; the scale will be applied during the out animation,
- * but will be animated away when the in animation runs &#42;/
- * transform: scale(1.2);
- * }
- *
- * .banner.ng-anchor-in {
- * transition: 1s linear all;
- * }
- * ```
- *
- *
- *
- *
- * ### Anchoring Demo
- *
- <example module="anchoringExample"
- name="anchoringExample"
- id="anchoringExample"
- deps="angular-animate.js;angular-route.js"
- animations="true">
- <file name="index.html">
- <a href="#/">Home</a>
- <hr />
- <div class="view-container">
- <div ng-view class="view"></div>
- </div>
- </file>
- <file name="script.js">
- angular.module('anchoringExample', ['ngAnimate', 'ngRoute'])
- .config(['$routeProvider', function($routeProvider) {
- $routeProvider.when('/', {
- templateUrl: 'home.html',
- controller: 'HomeController as home'
- });
- $routeProvider.when('/profile/:id', {
- templateUrl: 'profile.html',
- controller: 'ProfileController as profile'
- });
- }])
- .run(['$rootScope', function($rootScope) {
- $rootScope.records = [
- { id:1, title: "Miss Beulah Roob" },
- { id:2, title: "Trent Morissette" },
- { id:3, title: "Miss Ava Pouros" },
- { id:4, title: "Rod Pouros" },
- { id:5, title: "Abdul Rice" },
- { id:6, title: "Laurie Rutherford Sr." },
- { id:7, title: "Nakia McLaughlin" },
- { id:8, title: "Jordon Blanda DVM" },
- { id:9, title: "Rhoda Hand" },
- { id:10, title: "Alexandrea Sauer" }
- ];
- }])
- .controller('HomeController', [function() {
- //empty
- }])
- .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) {
- var index = parseInt($routeParams.id, 10);
- var record = $rootScope.records[index - 1];
-
- this.title = record.title;
- this.id = record.id;
- }]);
- </file>
- <file name="home.html">
- <h2>Welcome to the home page</h1>
- <p>Please click on an element</p>
- <a class="record"
- ng-href="#/profile/{{ record.id }}"
- ng-animate-ref="{{ record.id }}"
- ng-repeat="record in records">
- {{ record.title }}
- </a>
- </file>
- <file name="profile.html">
- <div class="profile record" ng-animate-ref="{{ profile.id }}">
- {{ profile.title }}
- </div>
- </file>
- <file name="animations.css">
- .record {
- display:block;
- font-size:20px;
- }
- .profile {
- background:black;
- color:white;
- font-size:100px;
- }
- .view-container {
- position:relative;
- }
- .view-container > .view.ng-animate {
- position:absolute;
- top:0;
- left:0;
- width:100%;
- min-height:500px;
- }
- .view.ng-enter, .view.ng-leave,
- .record.ng-anchor {
- transition:0.5s linear all;
- }
- .view.ng-enter {
- transform:translateX(100%);
- }
- .view.ng-enter.ng-enter-active, .view.ng-leave {
- transform:translateX(0%);
- }
- .view.ng-leave.ng-leave-active {
- transform:translateX(-100%);
- }
- .record.ng-anchor-out {
- background:red;
- }
- </file>
- </example>
- *
- * ### How is the element transported?
- *
- * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
- * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
- * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
- * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
- * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
- * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
- * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
- * will become visible since the shim class will be removed.
- *
- * ### How is the morphing handled?
- *
- * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
- * what CSS classes differ between the starting element and the destination element. These different CSS classes
- * will be added/removed on the anchor element and a transition will be applied (the transition that is provided
- * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
- * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
- * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
- * the cloned element is placed inside of root element which is likely close to the body element).
- *
- * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body.
- *
- *
- * ## Using $animate in your directive code
- *
- * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
- * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
- * imagine we have a greeting box that shows and hides itself when the data changes
- *
- * ```html
- * <greeting-box active="onOrOff">Hi there</greeting-box>
- * ```
- *
- * ```js
- * ngModule.directive('greetingBox', ['$animate', function($animate) {
- * return function(scope, element, attrs) {
- * attrs.$observe('active', function(value) {
- * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
- * });
- * });
- * }]);
- * ```
- *
- * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element
- * in our HTML code then we can trigger a CSS or JS animation to happen.
- *
- * ```css
- * /&#42; normally we would create a CSS class to reference on the element &#42;/
- * greeting-box.on { transition:0.5s linear all; background:green; color:white; }
- * ```
- *
- * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's
- * possible be sure to visit the {@link ng.$animate $animate service API page}.
- *
- *
- * ### Preventing Collisions With Third Party Libraries
- *
- * Some third-party frameworks place animation duration defaults across many element or className
- * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
- * is expecting actual animations on these elements and has to wait for their completion.
- *
- * You can prevent this unwanted behavior by using a prefix on all your animation classes:
- *
- * ```css
- * /&#42; prefixed with animate- &#42;/
- * .animate-fade-add.animate-fade-add-active {
- * transition:1s linear all;
- * opacity:0;
- * }
- * ```
- *
- * You then configure `$animate` to enforce this prefix:
- *
- * ```js
- * $animateProvider.classNameFilter(/animate-/);
- * ```
- *
- * This also may provide your application with a speed boost since only specific elements containing CSS class prefix
- * will be evaluated for animation when any DOM changes occur in the application.
- *
- * ## Callbacks and Promises
- *
- * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger
- * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has
- * ended by chaining onto the returned promise that animation method returns.
- *
- * ```js
- * // somewhere within the depths of the directive
- * $animate.enter(element, parent).then(function() {
- * //the animation has completed
- * });
- * ```
- *
- * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
- * anymore.)
- *
- * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
- * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view
- * routing controller to hook into that:
- *
- * ```js
- * ngModule.controller('HomePageController', ['$animate', function($animate) {
- * $animate.on('enter', ngViewElement, function(element) {
- * // the animation for this route has completed
- * }]);
- * }])
- * ```
- *
- * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
- */
-
-/**
- * @ngdoc service
- * @name $animate
- * @kind object
- *
- * @description
- * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
- *
- * Click here {@link ng.$animate to learn more about animations with `$animate`}.
- */
-angular.module('ngAnimate', [])
- .directive('ngAnimateSwap', ngAnimateSwapDirective)
-
- .directive('ngAnimateChildren', $$AnimateChildrenDirective)
- .factory('$$rAFScheduler', $$rAFSchedulerFactory)
-
- .provider('$$animateQueue', $$AnimateQueueProvider)
- .provider('$$animation', $$AnimationProvider)
-
- .provider('$animateCss', $AnimateCssProvider)
- .provider('$$animateCssDriver', $$AnimateCssDriverProvider)
-
- .provider('$$animateJs', $$AnimateJsProvider)
- .provider('$$animateJsDriver', $$AnimateJsDriverProvider);
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js
deleted file mode 100644
index 8e8e41df..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(D,r,Va){'use strict';function ya(a,b,c){if(!a)throw Ka("areq",b||"?",c||"required");return a}function za(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;ba(a)&&(a=a.join(" "));ba(b)&&(b=b.join(" "));return a+" "+b}function La(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function X(a,b,c){var d="";a=ba(a)?a:a&&R(a)&&a.length?a.split(/\s+/):[];s(a,function(a,g){a&&0<a.length&&(d+=0<g?" ":"",d+=c?b+a:a+b)});return d}function Ma(a){if(a instanceof I)switch(a.length){case 0:return[];
-case 1:if(1===a[0].nodeType)return a;break;default:return I(oa(a))}if(1===a.nodeType)return I(a)}function oa(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Na(a,b,c){s(b,function(b){a.addClass(b,c)})}function Oa(a,b,c){s(b,function(b){a.removeClass(b,c)})}function U(a){return function(b,c){c.addClass&&(Na(a,b,c.addClass),c.addClass=null);c.removeClass&&(Oa(a,b,c.removeClass),c.removeClass=null)}}function ka(a){a=a||{};if(!a.$$prepared){var b=a.domOperation||
-Q;a.domOperation=function(){a.$$domOperationFired=!0;b();b=Q};a.$$prepared=!0}return a}function fa(a,b){Aa(a,b);Ba(a,b)}function Aa(a,b){b.from&&(a.css(b.from),b.from=null)}function Ba(a,b){b.to&&(a.css(b.to),b.to=null)}function V(a,b,c){var d=b.options||{};c=c.options||{};var e=(d.addClass||"")+" "+(c.addClass||""),g=(d.removeClass||"")+" "+(c.removeClass||"");a=Pa(a.attr("class"),e,g);c.preparationClasses&&(d.preparationClasses=ca(c.preparationClasses,d.preparationClasses),delete c.preparationClasses);
-e=d.domOperation!==Q?d.domOperation:null;Ca(d,c);e&&(d.domOperation=e);d.addClass=a.addClass?a.addClass:null;d.removeClass=a.removeClass?a.removeClass:null;b.addClass=d.addClass;b.removeClass=d.removeClass;return d}function Pa(a,b,c){function d(a){R(a)&&(a=a.split(" "));var b={};s(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);s(b,function(a,b){e[b]=1});c=d(c);s(c,function(a,b){e[b]=1===e[b]?null:-1});var g={addClass:"",removeClass:""};s(e,function(b,c){var d,e;1===b?(d="addClass",
-e=!a[c]):-1===b&&(d="removeClass",e=a[c]);e&&(g[d].length&&(g[d]+=" "),g[d]+=c)});return g}function G(a){return a instanceof r.element?a[0]:a}function Qa(a,b,c){var d="";b&&(d=X(b,"ng-",!0));c.addClass&&(d=ca(d,X(c.addClass,"-add")));c.removeClass&&(d=ca(d,X(c.removeClass,"-remove")));d.length&&(c.preparationClasses=d,a.addClass(d))}function la(a,b){var c=b?"-"+b+"s":"";ha(a,[ia,c]);return[ia,c]}function pa(a,b){var c=b?"paused":"",d=Y+"PlayState";ha(a,[d,c]);return[d,c]}function ha(a,b){a.style[b[0]]=
-b[1]}function ca(a,b){return a?b?a+" "+b:a:b}function Da(a,b,c){var d=Object.create(null),e=a.getComputedStyle(b)||{};s(c,function(a,b){var c=e[a];if(c){var C=c.charAt(0);if("-"===C||"+"===C||0<=C)c=Ra(c);0===c&&(c=null);d[b]=c}});return d}function Ra(a){var b=0;a=a.split(/\s*,\s*/);s(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function qa(a){return 0===a||null!=a}function Ea(a,b){var c=S,d=a+"s";b?c+="Duration":d+=" linear all";
-return[c,d]}function Fa(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}function Ga(a,b,c){s(c,function(c){a[c]=Z(a[c])?a[c]:b.style.getPropertyValue(c)})}var Q=r.noop,Ha=r.copy,Ca=r.extend,I=r.element,s=r.forEach,ba=r.isArray,R=r.isString,ra=r.isObject,P=r.isUndefined,Z=r.isDefined,Ia=r.isFunction,sa=r.isElement,S,ta,Y,ua;P(D.ontransitionend)&&
-Z(D.onwebkittransitionend)?(S="WebkitTransition",ta="webkitTransitionEnd transitionend"):(S="transition",ta="transitionend");P(D.onanimationend)&&Z(D.onwebkitanimationend)?(Y="WebkitAnimation",ua="webkitAnimationEnd animationend"):(Y="animation",ua="animationend");var ma=Y+"Delay",va=Y+"Duration",ia=S+"Delay";D=S+"Duration";var Ka=r.$$minErr("ng"),Sa={transitionDuration:D,transitionDelay:ia,transitionProperty:S+"Property",animationDuration:va,animationDelay:ma,animationIterationCount:Y+"IterationCount"},
-Ta={transitionDuration:D,transitionDelay:ia,animationDuration:va,animationDelay:ma};r.module("ngAnimate",[]).directive("ngAnimateSwap",["$animate","$rootScope",function(a,b){return{restrict:"A",transclude:"element",terminal:!0,priority:600,link:function(b,d,e,g,H){var A,C;b.$watchCollection(e.ngAnimateSwap||e["for"],function(e){A&&a.leave(A);C&&(C.$destroy(),C=null);if(e||0===e)C=b.$new(),H(C,function(b){A=b;a.enter(b,null,d)})})}}}]).directive("ngAnimateChildren",["$interpolate",function(a){return{link:function(b,
-c,d){function e(a){c.data("$$ngAnimateChildren","on"===a||"true"===a)}var g=d.ngAnimateChildren;r.isString(g)&&0===g.length?c.data("$$ngAnimateChildren",!0):(e(a(g)(b)),d.$observe("ngAnimateChildren",e))}}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d=d.concat(a);c()}function c(){if(d.length){for(var b=d.shift(),H=0;H<b.length;H++)b[H]();e||a(function(){e||c()})}}var d,e;d=b.queue=[];b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=null;b();c()})};return b}]).provider("$$animateQueue",
-["$animateProvider",function(a){function b(a){if(!a)return null;a=a.split(" ");var b=Object.create(null);s(a,function(a){b[a]=!0});return b}function c(a,c){if(a&&c){var d=b(c);return a.split(" ").some(function(a){return d[a]})}}function d(a,b,c,d){return g[a].some(function(a){return a(b,c,d)})}function e(a,b){var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var g=this.rules={skip:[],cancel:[],join:[]};g.join.push(function(a,b,c){return!b.structural&&e(b)});g.skip.push(function(a,
-b,c){return!b.structural&&!e(b)});g.skip.push(function(a,b,c){return"leave"==c.event&&b.structural});g.skip.push(function(a,b,c){return c.structural&&2===c.state&&!b.structural});g.cancel.push(function(a,b,c){return c.structural&&b.structural});g.cancel.push(function(a,b,c){return 2===c.state&&b.structural});g.cancel.push(function(a,b,d){a=b.addClass;b=b.removeClass;var e=d.addClass;d=d.removeClass;return P(a)&&P(b)||P(e)&&P(d)?!1:c(a,d)||c(b,e)});this.$get=["$$rAF","$rootScope","$rootElement","$document",
-"$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite","$$forceReflow",function(b,c,g,m,M,r,u,na,v,z){function K(){var a=!1;return function(b){a?b():c.$$postDigest(function(){a=!0;b()})}}function J(a,b,c){var f=G(b),d=G(a),h=[];(a=x[c])&&s(a,function(a){y.call(a.node,f)?h.push(a.callback):"leave"===c&&y.call(a.node,d)&&h.push(a.callback)});return h}function h(a,f,h){function l(c,f,d,h){g(function(){var c=J(y,a,f);c.length&&b(function(){s(c,function(b){b(a,d,h)})})});c.progress(f,
-d,h)}function x(b){var c=a,f=n;f.preparationClasses&&(c.removeClass(f.preparationClasses),f.preparationClasses=null);f.activeClasses&&(c.removeClass(f.activeClasses),f.activeClasses=null);Ja(a,n);fa(a,n);n.domOperation();k.complete(!b)}var n=Ha(h),z,y;if(a=Ma(a))z=G(a),y=a.parent();var n=ka(n),k=new u,g=K();ba(n.addClass)&&(n.addClass=n.addClass.join(" "));n.addClass&&!R(n.addClass)&&(n.addClass=null);ba(n.removeClass)&&(n.removeClass=n.removeClass.join(" "));n.removeClass&&!R(n.removeClass)&&(n.removeClass=
-null);n.from&&!ra(n.from)&&(n.from=null);n.to&&!ra(n.to)&&(n.to=null);if(!z)return x(),k;h=[z.className,n.addClass,n.removeClass].join(" ");if(!Ua(h))return x(),k;var C=0<=["enter","move","leave"].indexOf(f),w=!L||m[0].hidden||E.get(z);h=!w&&B.get(z)||{};var v=!!h.state;w||v&&1==h.state||(w=!q(a,y,f));if(w)return x(),k;C&&xa(a);w={structural:C,element:a,event:f,addClass:n.addClass,removeClass:n.removeClass,close:x,options:n,runner:k};if(v){if(d("skip",a,w,h)){if(2===h.state)return x(),k;V(a,h,w);
-return h.runner}if(d("cancel",a,w,h))if(2===h.state)h.runner.end();else if(h.structural)h.close();else return V(a,h,w),h.runner;else if(d("join",a,w,h))if(2===h.state)V(a,w,{});else return Qa(a,C?f:null,n),f=w.event=h.event,n=V(a,h,w),h.runner}else V(a,w,{});(v=w.structural)||(v="animate"===w.event&&0<Object.keys(w.options.to||{}).length||e(w));if(!v)return x(),N(a),k;var M=(h.counter||0)+1;w.counter=M;t(a,1,w);c.$$postDigest(function(){var b=B.get(z),c=!b,b=b||{},d=0<(a.parent()||[]).length&&("animate"===
-b.event||b.structural||e(b));if(c||b.counter!==M||!d){c&&(Ja(a,n),fa(a,n));if(c||C&&b.event!==f)n.domOperation(),k.end();d||N(a)}else f=!b.structural&&e(b,!0)?"setClass":b.event,t(a,2),b=r(a,f,b.options),b.done(function(b){x(!b);(b=B.get(z))&&b.counter===M&&N(G(a));l(k,f,"close",{})}),k.setHost(b),l(k,f,"start",{})});return k}function xa(a){a=G(a).querySelectorAll("[data-ng-animate]");s(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=B.get(a);if(c)switch(b){case 2:c.runner.end();
-case 1:B.remove(a)}})}function N(a){a=G(a);a.removeAttribute("data-ng-animate");B.remove(a)}function k(a,b){return G(a)===G(b)}function q(a,b,c){c=I(m[0].body);var f=k(a,c)||"HTML"===a[0].nodeName,d=k(a,g),h=!1,l,e=E.get(G(a));for((a=a.data("$ngAnimatePin"))&&(b=a);b&&b.length;){d||(d=k(b,g));var x=b[0];if(1!==x.nodeType)break;a=B.get(x)||{};if(!h){x=E.get(x);if(!0===x&&!1!==e){e=!0;break}else!1===x&&(e=!1);h=a.structural}if(P(l)||!0===l)a=b.data("$$ngAnimateChildren"),Z(a)&&(l=a);if(h&&!1===l)break;
-f||(f=k(b,c));if(f&&d)break;if(!d&&(a=b.data("$ngAnimatePin"))){b=a;continue}b=b.parent()}return(!h||l)&&!0!==e&&d&&f}function t(a,b,c){c=c||{};c.state=b;a=G(a);a.setAttribute("data-ng-animate",b);c=(b=B.get(a))?Ca(b,c):c;B.put(a,c)}var B=new M,E=new M,L=null,f=c.$watch(function(){return 0===na.totalPendingRequests},function(a){a&&(f(),c.$$postDigest(function(){c.$$postDigest(function(){null===L&&(L=!0)})}))}),x={},l=a.classNameFilter(),Ua=l?function(a){return l.test(a)}:function(){return!0},Ja=U(v),
-y=Node.prototype.contains||function(a){return this===a||!!(this.compareDocumentPosition(a)&16)};return{on:function(a,b,c){b=oa(b);x[a]=x[a]||[];x[a].push({node:b,callback:c})},off:function(a,b,c){function f(a,b,c){var d=oa(b);return a.filter(function(a){return!(a.node===d&&(!c||a.callback===c))})}var d=x[a];d&&(x[a]=1===arguments.length?null:f(d,b,c))},pin:function(a,b){ya(sa(a),"element","not an element");ya(sa(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=
-c||{};c.domOperation=f;return h(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!L;else if(sa(a)){var f=G(a),d=E.get(f);1===c?b=!d:E.put(f,!b)}else b=L=!!a;return b}}}]}]).provider("$$animation",["$animateProvider",function(a){function b(a){return a.data("$$animationRunner")}var c=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(a,e,g,H,A,C){function m(a){function b(a){if(a.processed)return a;a.processed=!0;var d=
-a.domNode,N=d.parentNode;e.put(d,a);for(var k;N;){if(k=e.get(N)){k.processed||(k=b(k));break}N=N.parentNode}(k||c).children.push(a);return a}var c={children:[]},d,e=new A;for(d=0;d<a.length;d++){var g=a[d];e.put(g.domNode,a[d]={domNode:g.domNode,fn:g.fn,children:[]})}for(d=0;d<a.length;d++)b(a[d]);return function(a){var b=[],c=[],d;for(d=0;d<a.children.length;d++)c.push(a.children[d]);a=c.length;var e=0,t=[];for(d=0;d<c.length;d++){var g=c[d];0>=a&&(a=e,e=0,b.push(t),t=[]);t.push(g.fn);g.children.forEach(function(a){e++;
-c.push(a)});a--}t.length&&b.push(t);return b}(c)}var M=[],r=U(a);return function(u,A,v){function z(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];s(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}function K(a){var b=[],c={};s(a,function(a,f){var d=G(a.element),h=0<=["enter","move"].indexOf(a.event),d=a.structural?z(d):[];if(d.length){var e=h?"to":"from";s(d,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||
-{};c[b][e]={animationID:f,element:I(a)}})}else b.push(a)});var d={},h={};s(c,function(c,e){var l=c.from,t=c.to;if(l&&t){var g=a[l.animationID],E=a[t.animationID],k=l.animationID.toString();if(!h[k]){var z=h[k]={structural:!0,beforeStart:function(){g.beforeStart();E.beforeStart()},close:function(){g.close();E.close()},classes:J(g.classes,E.classes),from:g,to:E,anchors:[]};z.classes.length?b.push(z):(b.push(g),b.push(E))}h[k].anchors.push({out:l.element,"in":t.element})}else l=l?l.animationID:t.animationID,
-t=l.toString(),d[t]||(d[t]=!0,b.push(a[l]))});return b}function J(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],d=0;d<a.length;d++){var h=a[d];if("ng-"!==h.substring(0,3))for(var e=0;e<b.length;e++)if(h===b[e]){c.push(h);break}}return c.join(" ")}function h(a){for(var b=c.length-1;0<=b;b--){var d=c[b];if(g.has(d)&&(d=g.get(d)(a)))return d}}function xa(a,c){a.from&&a.to?(b(a.from.element).setHost(c),b(a.to.element).setHost(c)):b(a.element).setHost(c)}function N(){var a=b(u);!a||"leave"===A&&v.$$domOperationFired||
-a.end()}function k(b){u.off("$destroy",N);u.removeData("$$animationRunner");r(u,v);fa(u,v);v.domOperation();E&&a.removeClass(u,E);u.removeClass("ng-animate");t.complete(!b)}v=ka(v);var q=0<=["enter","move","leave"].indexOf(A),t=new H({end:function(){k()},cancel:function(){k(!0)}});if(!c.length)return k(),t;u.data("$$animationRunner",t);var B=za(u.attr("class"),za(v.addClass,v.removeClass)),E=v.tempClasses;E&&(B+=" "+E,v.tempClasses=null);var L;q&&(L="ng-"+A+"-prepare",a.addClass(u,L));M.push({element:u,
-classes:B,event:A,structural:q,options:v,beforeStart:function(){u.addClass("ng-animate");E&&a.addClass(u,E);L&&(a.removeClass(u,L),L=null)},close:k});u.on("$destroy",N);if(1<M.length)return t;e.$$postDigest(function(){var a=[];s(M,function(c){b(c.element)?a.push(c):c.close()});M.length=0;var c=K(a),d=[];s(c,function(a){d.push({domNode:G(a.from?a.from.element:a.element),fn:function(){a.beforeStart();var c,d=a.close;if(b(a.anchors?a.from.element||a.to.element:a.element)){var f=h(a);f&&(c=f.start)}c?
-(c=c(),c.done(function(a){d(!a)}),xa(a,c)):d()}})});C(m(d))});return t}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Fa(),c=Fa();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$$animateQueue",function(a,e,g,H,A,C,m,M){function r(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||(c.$$ngAnimateParentKey=++K))+"-"+a.getAttribute("class")+"-"+b}function u(h,g,z,k){var q;0<b.count(z)&&(q=c.get(z),q||(g=X(g,"-stagger"),
-e.addClass(h,g),q=Da(a,h,k),q.animationDuration=Math.max(q.animationDuration,0),q.transitionDuration=Math.max(q.transitionDuration,0),e.removeClass(h,g),c.put(z,q)));return q||{}}function na(a){J.push(a);m.waitUntilQuiet(function(){b.flush();c.flush();for(var a=A(),d=0;d<J.length;d++)J[d](a);J.length=0})}function v(c,e,g){e=b.get(g);e||(e=Da(a,c,Sa),"infinite"===e.animationIterationCount&&(e.animationIterationCount=1));b.put(g,e);c=e;g=c.animationDelay;e=c.transitionDelay;c.maxDelay=g&&e?Math.max(g,
-e):g||e;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var z=U(e),K=0,J=[];return function(a,c){function d(){q()}function k(){q(!0)}function q(b){if(!(A||wa&&K)){A=!0;K=!1;f.$$skipPreparationClasses||e.removeClass(a,da);e.removeClass(a,ca);pa(l,!1);la(l,!1);s(m,function(a){l.style[a[0]]=""});z(a,f);fa(a,f);Object.keys(x).length&&s(x,function(a,b){a?l.style.setProperty(b,a):l.style.removeProperty(b)});if(f.onDone)f.onDone();ea&&ea.length&&a.off(ea.join(" "),
-E);var c=a.data("$$animateCss");c&&(H.cancel(c[0].timer),a.removeData("$$animateCss"));D&&D.complete(!b)}}function t(a){p.blockTransition&&la(l,a);p.blockKeyframeAnimation&&pa(l,!!a)}function B(){D=new g({end:d,cancel:k});na(Q);q();return{$$willAnimate:!1,start:function(){return D},end:d}}function E(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-U,0)>=P&&b>=O&&(wa=!0,q())}function L(){function b(){if(!A){t(!1);s(m,
-function(a){l.style[a[0]]=a[1]});z(a,f);e.addClass(a,ca);if(p.recalculateTimingStyles){ja=l.className+" "+da;ga=r(l,ja);F=v(l,ja,ga);$=F.maxDelay;n=Math.max($,0);O=F.maxDuration;if(0===O){q();return}p.hasTransitions=0<F.transitionDuration;p.hasAnimations=0<F.animationDuration}p.applyAnimationDelay&&($="boolean"!==typeof f.delay&&qa(f.delay)?parseFloat(f.delay):$,n=Math.max($,0),F.animationDelay=$,aa=[ma,$+"s"],m.push(aa),l.style[aa[0]]=aa[1]);P=1E3*n;R=1E3*O;if(f.easing){var d,g=f.easing;p.hasTransitions&&
-(d=S+"TimingFunction",m.push([d,g]),l.style[d]=g);p.hasAnimations&&(d=Y+"TimingFunction",m.push([d,g]),l.style[d]=g)}F.transitionDuration&&ea.push(ta);F.animationDuration&&ea.push(ua);U=Date.now();var k=P+1.5*R;d=U+k;var g=a.data("$$animateCss")||[],L=!0;if(g.length){var B=g[0];(L=d>B.expectedEndTime)?H.cancel(B.timer):g.push(q)}L&&(k=H(c,k,!1),g[0]={timer:k,expectedEndTime:d},g.push(q),a.data("$$animateCss",g));if(ea.length)a.on(ea.join(" "),E);f.to&&(f.cleanupStyles&&Ga(x,l,Object.keys(f.to)),Ba(a,
-f))}}function c(){var b=a.data("$$animateCss");if(b){for(var d=1;d<b.length;d++)b[d]();a.removeData("$$animateCss")}}if(!A)if(l.parentNode){var d=function(a){if(wa)K&&a&&(K=!1,q());else if(K=!a,F.animationDuration)if(a=pa(l,K),K)m.push(a);else{var b=m,c=b.indexOf(a);0<=a&&b.splice(c,1)}},g=0<Z&&(F.transitionDuration&&0===W.transitionDuration||F.animationDuration&&0===W.animationDuration)&&Math.max(W.animationDelay,W.transitionDelay);g?H(b,Math.floor(g*Z*1E3),!1):b();I.resume=function(){d(!0)};I.pause=
-function(){d(!1)}}else q()}var f=c||{};f.$$prepared||(f=ka(Ha(f)));var x={},l=G(a);if(!l||!l.parentNode||!M.enabled())return B();var m=[],J=a.attr("class"),y=La(f),A,K,wa,D,I,n,P,O,R,U,ea=[];if(0===f.duration||!C.animations&&!C.transitions)return B();var w=f.event&&ba(f.event)?f.event.join(" "):f.event,V="",T="";w&&f.structural?V=X(w,"ng-",!0):w&&(V=w);f.addClass&&(T+=X(f.addClass,"-add"));f.removeClass&&(T.length&&(T+=" "),T+=X(f.removeClass,"-remove"));f.applyClassesEarly&&T.length&&z(a,f);var da=
-[V,T].join(" ").trim(),ja=J+" "+da,ca=X(da,"-active"),J=y.to&&0<Object.keys(y.to).length;if(!(0<(f.keyframeStyle||"").length||J||da))return B();var ga,W;0<f.stagger?(y=parseFloat(f.stagger),W={transitionDelay:y,animationDelay:y,transitionDuration:0,animationDuration:0}):(ga=r(l,ja),W=u(l,da,ga,Ta));f.$$skipPreparationClasses||e.addClass(a,da);f.transitionStyle&&(y=[S,f.transitionStyle],ha(l,y),m.push(y));0<=f.duration&&(y=0<l.style[S].length,y=Ea(f.duration,y),ha(l,y),m.push(y));f.keyframeStyle&&
-(y=[Y,f.keyframeStyle],ha(l,y),m.push(y));var Z=W?0<=f.staggerIndex?f.staggerIndex:b.count(ga):0;(w=0===Z)&&!f.skipBlocking&&la(l,9999);var F=v(l,ja,ga),$=F.maxDelay;n=Math.max($,0);O=F.maxDuration;var p={};p.hasTransitions=0<F.transitionDuration;p.hasAnimations=0<F.animationDuration;p.hasTransitionAll=p.hasTransitions&&"all"==F.transitionProperty;p.applyTransitionDuration=J&&(p.hasTransitions&&!p.hasTransitionAll||p.hasAnimations&&!p.hasTransitions);p.applyAnimationDuration=f.duration&&p.hasAnimations;
-p.applyTransitionDelay=qa(f.delay)&&(p.applyTransitionDuration||p.hasTransitions);p.applyAnimationDelay=qa(f.delay)&&p.hasAnimations;p.recalculateTimingStyles=0<T.length;if(p.applyTransitionDuration||p.applyAnimationDuration)O=f.duration?parseFloat(f.duration):O,p.applyTransitionDuration&&(p.hasTransitions=!0,F.transitionDuration=O,y=0<l.style[S+"Property"].length,m.push(Ea(O,y))),p.applyAnimationDuration&&(p.hasAnimations=!0,F.animationDuration=O,m.push([va,O+"s"]));if(0===O&&!p.recalculateTimingStyles)return B();
-if(null!=f.delay){var aa;"boolean"!==typeof f.delay&&(aa=parseFloat(f.delay),n=Math.max(aa,0));p.applyTransitionDelay&&m.push([ia,aa+"s"]);p.applyAnimationDelay&&m.push([ma,aa+"s"])}null==f.duration&&0<F.transitionDuration&&(p.recalculateTimingStyles=p.recalculateTimingStyles||w);P=1E3*n;R=1E3*O;f.skipBlocking||(p.blockTransition=0<F.transitionDuration,p.blockKeyframeAnimation=0<F.animationDuration&&0<W.animationDelay&&0===W.animationDuration);f.from&&(f.cleanupStyles&&Ga(x,l,Object.keys(f.from)),
-Aa(a,f));p.blockTransition||p.blockKeyframeAnimation?t(O):f.skipBlocking||la(l,!1);return{$$willAnimate:!0,end:d,start:function(){if(!A)return I={end:d,cancel:k,resume:null,pause:null},D=new g(I),na(L),D}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(a,c,d,e,g,H,A){function C(a){return a.replace(/\bng-\S+\b/g,"")}function m(a,
-b){R(a)&&(a=a.split(" "));R(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}function M(c,e,g){function h(a){var b={},c=G(a).getBoundingClientRect();s(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=D.scrollTop;break;case "left":d+=D.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function A(){var c=C(g.attr("class")||""),d=m(c,q),c=m(q,c),d=a(k,{to:h(g),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?
-d:null}function H(){k.remove();e.removeClass("ng-animate-shim");g.removeClass("ng-animate-shim")}var k=I(G(e).cloneNode(!0)),q=C(k.attr("class")||"");e.addClass("ng-animate-shim");g.addClass("ng-animate-shim");k.addClass("ng-anchor");v.append(k);var t;c=function(){var c=a(k,{addClass:"ng-anchor-out",delay:!0,from:h(e)});return c.$$willAnimate?c:null}();if(!c&&(t=A(),!t))return H();var B=c||t;return{start:function(){function a(){c&&c.end()}var b,c=B.start();c.done(function(){c=null;if(!t&&(t=A()))return c=
-t.start(),c.done(function(){c=null;H();b.complete()}),c;H();b.complete()});return b=new d({end:a,cancel:a})}}}function r(a,b,c,e){var g=u(a,Q),m=u(b,Q),k=[];s(e,function(a){(a=M(c,a.out,a["in"]))&&k.push(a)});if(g||m||0!==k.length)return{start:function(){function a(){s(b,function(a){a.end()})}var b=[];g&&b.push(g.start());m&&b.push(m.start());s(k,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function u(c){var d=c.element,e=c.options||
-{};c.structural&&(e.event=c.event,e.structural=!0,e.applyClassesEarly=!0,"leave"===c.event&&(e.onDone=e.domOperation));e.preparationClasses&&(e.event=ca(e.event,e.preparationClasses));c=a(d,e);return c.$$willAnimate?c:null}if(!g.animations&&!g.transitions)return Q;var D=A[0].body;c=G(e);var v=I(c.parentNode&&11===c.parentNode.nodeType||D.contains(c)?c:D);U(H);return function(a){return a.from&&a.to?r(a.from,a.to,a.classes,a.anchors):u(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=
-["$injector","$$AnimateRunner","$$jqLite",function(b,c,d){function e(c){c=ba(c)?c:c.split(" ");for(var d=[],e={},g=0;g<c.length;g++){var s=c[g],r=a.$$registeredAnimations[s];r&&!e[s]&&(d.push(b.get(r)),e[s]=!0)}return d}var g=U(d);return function(a,b,d,m){function r(){m.domOperation();g(a,m)}function D(a,b,d,e,f){switch(d){case "animate":b=[b,e.from,e.to,f];break;case "setClass":b=[b,z,K,f];break;case "addClass":b=[b,z,f];break;case "removeClass":b=[b,K,f];break;default:b=[b,f]}b.push(e);if(a=a.apply(a,
-b))if(Ia(a.start)&&(a=a.start()),a instanceof c)a.done(f);else if(Ia(a))return a;return Q}function u(a,b,d,e,f){var g=[];s(e,function(e){var h=e[f];h&&g.push(function(){var e,f,g=!1,k=function(a){g||(g=!0,(f||Q)(a),e.complete(!a))};e=new c({end:function(){k()},cancel:function(){k(!0)}});f=D(h,a,b,d,function(a){k(!1===a)});return e})});return g}function G(a,b,d,e,f){var g=u(a,b,d,e,f);if(0===g.length){var h,k;"beforeSetClass"===f?(h=u(a,"removeClass",d,e,"beforeRemoveClass"),k=u(a,"addClass",d,e,"beforeAddClass")):
-"setClass"===f&&(h=u(a,"removeClass",d,e,"removeClass"),k=u(a,"addClass",d,e,"addClass"));h&&(g=g.concat(h));k&&(g=g.concat(k))}if(0!==g.length)return function(a){var b=[];g.length&&s(g,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){s(b,function(b){a?b.cancel():b.end()})}}}var v=!1;3===arguments.length&&ra(d)&&(m=d,d=null);m=ka(m);d||(d=a.attr("class")||"",m.addClass&&(d+=" "+m.addClass),m.removeClass&&(d+=" "+m.removeClass));var z=m.addClass,K=m.removeClass,J=e(d),h,I;if(J.length){var N,
-k;"leave"==b?(k="leave",N="afterLeave"):(k="before"+b.charAt(0).toUpperCase()+b.substr(1),N=b);"enter"!==b&&"move"!==b&&(h=G(a,b,m,J,k));I=G(a,b,m,J,N)}if(h||I){var q;return{$$willAnimate:!0,end:function(){q?q.end():(v=!0,r(),fa(a,m),q=new c,q.complete(!0));return q},start:function(){function b(c){v=!0;r();fa(a,m);q.complete(c)}if(q)return q;q=new c;var d,e=[];h&&e.push(function(a){d=h(a)});e.length?e.push(function(a){r();a(!0)}):r();I&&e.push(function(a){d=I(a)});q.setHost({end:function(){v||((d||
-Q)(void 0),b(void 0))},cancel:function(){v||((d||Q)(!0),b(!0))}});c.chain(e,b);return q}}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)}return function(a){if(a.from&&a.to){var b=d(a.from),r=d(a.to);if(b||r)return{start:function(){function a(){return function(){s(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());r&&
-d.push(r.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular);
-//# sourceMappingURL=angular-animate.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js.map
deleted file mode 100644
index 1d4f7a68..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-animate.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-animate.min.js",
-"lineCount":55,
-"mappings":"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",
-"sources":["angular-animate.js"],
-"names":["window","angular","undefined","assertArg","arg","name","reason","ngMinErr","mergeClasses","a","b","isArray","join","packageStyles","options","styles","to","from","pendClasses","classes","fix","isPrefix","className","isString","length","split","forEach","klass","i","stripCommentsFromElement","element","jqLite","ELEMENT_NODE","nodeType","extractElementNode","elm","$$addClass","$$jqLite","addClass","$$removeClass","removeClass","applyAnimationClassesFactory","prepareAnimationOptions","$$prepared","domOperation","noop","options.domOperation","$$domOperationFired","applyAnimationStyles","applyAnimationFromStyles","applyAnimationToStyles","css","mergeAnimationDetails","oldAnimation","newAnimation","target","newOptions","toAdd","toRemove","resolveElementClasses","attr","preparationClasses","concatWithSpace","realDomOperation","extend","existing","splitClassesToLookup","obj","flags","value","key","ADD_CLASS","REMOVE_CLASS","val","prop","allow","getDomNode","applyGeneratedPreparationClasses","event","EVENT_CLASS_PREFIX","ADD_CLASS_SUFFIX","REMOVE_CLASS_SUFFIX","blockTransitions","node","duration","applyInlineStyle","TRANSITION_DELAY_PROP","blockKeyframeAnimations","applyBlock","ANIMATION_PROP","ANIMATION_PLAYSTATE_KEY","styleTuple","style","computeCssStyles","$window","properties","Object","create","detectedStyles","getComputedStyle","formalStyleName","actualStyleName","c","charAt","parseMaxTime","str","maxValue","values","substring","parseFloat","Math","max","truthyTimingValue","getCssTransitionDurationStyle","applyOnlyDuration","TRANSITION_PROP","DURATION_KEY","createLocalCacheLookup","cache","flush","count","entry","total","get","put","registerRestorableStyles","backup","isDefined","getPropertyValue","copy","isObject","isUndefined","isFunction","isElement","TRANSITIONEND_EVENT","ANIMATIONEND_EVENT","ontransitionend","onwebkittransitionend","onanimationend","onwebkitanimationend","ANIMATION_DELAY_PROP","DELAY_KEY","ANIMATION_DURATION_PROP","TRANSITION_DURATION_PROP","$$minErr","DETECT_CSS_PROPERTIES","transitionDuration","transitionDelay","transitionProperty","PROPERTY_KEY","animationDuration","animationDelay","animationIterationCount","ANIMATION_ITERATION_COUNT_KEY","DETECT_STAGGER_CSS_PROPERTIES","module","directive","ngAnimateSwapDirective","$animate","$rootScope","restrict","transclude","terminal","priority","link","scope","$element","attrs","ctrl","$transclude","previousElement","previousScope","$watchCollection","ngAnimateSwap","leave","$destroy","$new","enter","$$AnimateChildrenDirective","$interpolate","setData","data","NG_ANIMATE_CHILDREN_DATA","ngAnimateChildren","$observe","factory","$$rAFSchedulerFactory","$$rAF","scheduler","tasks","queue","concat","nextTick","items","shift","cancelFn","waitUntilQuiet","scheduler.waitUntilQuiet","fn","provider","$$AnimateQueueProvider","$animateProvider","makeTruthyCssClassMap","classString","keys","ONE_SPACE","map","hasMatchingClasses","newClassString","currentClassString","currentClassMap","some","isAllowed","ruleType","currentAnimation","previousAnimation","rules","hasAnimationClasses","animation","and","skip","cancel","push","structural","RUNNING_STATE","state","nA","nR","cA","cR","$get","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$forceReflow","postDigestTaskFactory","postDigestCalled","$$postDigest","findCallbacks","parent","targetNode","targetParentNode","matches","entries","callbackRegistry","contains","call","callback","queueAnimation","initialOptions","notifyProgress","runner","phase","runInNextPostDigestOrNow","callbacks","progress","close","reject","activeClasses","applyAnimationClasses","complete","isAnimatableClassName","isStructural","indexOf","skipAnimations","animationsEnabled","hidden","disabledElementsLookup","existingAnimation","activeAnimationsLookup","hasExistingAnimation","PRE_DIGEST_STATE","areAnimationsAllowed","closeChildAnimations","skipAnimationFlag","cancelAnimationFlag","end","joinAnimationFlag","isValidAnimation","clearElementAnimationState","counter","markElementAnimationState","animationDetails","animationCancelled","realRunner","done","status","setHost","children","querySelectorAll","child","parseInt","getAttribute","NG_ANIMATE_ATTR_NAME","remove","removeAttribute","isMatchingElement","nodeOrElmA","nodeOrElmB","parentElement","bodyElement","body","bodyElementDetected","nodeName","rootElementDetected","parentAnimationDetected","animateChildren","elementDisabled","parentHost","NG_ANIMATE_PIN_DATA","parentNode","details","parentElementDisabled","setAttribute","newValue","oldValue","deregisterWatch","$watch","totalPendingRequests","isEmpty","classNameFilter","test","Node","prototype","compareDocumentPosition","on","container","off","filterFromRegistry","list","matchContainer","matchCallback","containerNode","filter","arguments","pin","enabled","bool","argCount","hasElement","recordExists","$$AnimationProvider","getRunner","RUNNER_STORAGE_KEY","drivers","$injector","$$rAFScheduler","sortAnimations","animations","processNode","processed","elementNode","domNode","lookup","parentEntry","tree","flatten","result","remainingLevelEntries","nextLevelEntries","row","childEntry","animationQueue","getAnchorNodes","hasAttribute","NG_ANIMATE_REF_ATTR","SELECTOR","anchors","groupAnimations","preparedAnimations","refLookup","index","enterOrMove","anchorNodes","direction","anchor","animationID","usedIndicesLookup","anchorGroups","operations","fromAnimation","toAnimation","lookupKey","toString","group","beforeStart","cssClassesIntersection","indexKey","aa","j","invokeFirstDriver","driverName","has","driver","updateAnimationRunners","newRunner","handleDestroyedElement","rejected","removeData","tempClasses","NG_ANIMATE_CLASSNAME","prepareClassName","PREPARE_CLASS_SUFFIX","groupedAnimations","toBeSortedAnimations","animationEntry","triggerAnimationStart","startAnimationFn","closeFn","targetElement","operation","start","animationRunner","$AnimateCssProvider","gcsLookup","gcsStaggerLookup","$timeout","$sniffer","$$animateQueue","gcsHashFn","extraClasses","parentCounter","computeCachedCssStaggerStyles","cacheKey","stagger","staggerClassName","rafWaitQueue","pageWidth","computeTimings","timings","aD","tD","maxDelay","maxDuration","init","endFn","animationClosed","animationCompleted","animationPaused","$$skipPreparationClasses","temporaryStyles","restoreStyles","setProperty","removeProperty","onDone","events","onAnimationProgress","animationTimerData","ANIMATE_TIMER_KEY","timer","applyBlocking","blockTransition","blockKeyframeAnimation","closeAndReturnNoopAnimator","$$willAnimate","stopPropagation","ev","originalEvent","timeStamp","$manualTimeStamp","Date","now","elapsedTime","toFixed","ELAPSED_TIME_MAX_DECIMAL_PLACES","startTime","maxDelayTime","recalculateTimingStyles","fullClassName","relativeDelay","hasTransitions","hasAnimations","applyAnimationDelay","delay","delayStyle","ONE_SECOND","maxDurationTime","easing","easeProp","easeVal","TIMING_KEY","timerTime","CLOSING_TIME_BUFFER","endTime","animationsData","setupFallbackTimer","currentTimerData","expectedEndTime","onAnimationExpired","cleanupStyles","playPause","playAnimation","arr","splice","maxStagger","itemIndex","floor","runnerHost","resume","runnerHost.resume","pause","runnerHost.pause","transitions","method","structuralClassName","addRemoveClassName","applyClassesEarly","trim","ACTIVE_CLASS_SUFFIX","hasToStyles","keyframeStyle","staggerVal","transitionStyle","durationStyle","staggerIndex","isFirst","skipBlocking","SAFE_FAST_FORWARD_DURATION_VALUE","hasTransitionAll","applyTransitionDuration","applyAnimationDuration","applyTransitionDelay","$$AnimateCssDriverProvider","$$animationProvider","$animateCss","filterCssClasses","replace","getUniqueValues","prepareAnchoredAnimation","outAnchor","inAnchor","calculateAnchorStyles","coords","getBoundingClientRect","bodyNode","scrollTop","scrollLeft","prepareInAnimation","endingClasses","startingClasses","animator","clone","NG_ANIMATE_SHIM_CLASS_NAME","cloneNode","NG_ANIMATE_ANCHOR_CLASS_NAME","rootBodyElement","append","animatorIn","animatorOut","prepareOutAnimation","NG_OUT_ANCHOR_CLASS_NAME","startingAnimator","prepareFromToAnchorAnimation","prepareRegularAnimation","anchorAnimations","outElement","inElement","animationRunners","all","rootNode","initDriverFn","$$AnimateJsProvider","lookupAnimations","flagMap","animationFactory","$$registeredAnimations","applyOptions","executeAnimationFn","args","classesToAdd","classesToRemove","apply","groupEventedAnimations","fnName","ani","endProgressCb","resolved","onAnimationComplete","packageAnimations","startAnimation","runners","animateFn","before","after","afterFn","beforeFn","toUpperCase","substr","onComplete","success","closeActiveAnimations","chain","cancelled","$$AnimateJsDriverProvider","$$animateJs","prepareAnimation","endFnFactory"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js
deleted file mode 100644
index cf0fd742..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(s,q,t){'use strict';var f="BUTTON A INPUT TEXTAREA SELECT DETAILS SUMMARY".split(" "),l=function(a,c){if(-1!==c.indexOf(a[0].nodeName))return!0};q.module("ngAria",["ng"]).provider("$aria",function(){function a(a,h,p,n){return function(d,e,b){var g=b.$normalize(h);!c[g]||l(e,p)||b[g]||d.$watch(b[a],function(b){b=n?!b:!!b;e.attr(h,b)})}}var c={ariaHidden:!0,ariaChecked:!0,ariaDisabled:!0,ariaRequired:!0,ariaInvalid:!0,ariaValue:!0,tabindex:!0,bindKeypress:!0,bindRoleForClick:!0};this.config=
-function(a){c=q.extend(c,a)};this.$get=function(){return{config:function(a){return c[a]},$$watchExpr:a}}}).directive("ngShow",["$aria",function(a){return a.$$watchExpr("ngShow","aria-hidden",[],!0)}]).directive("ngHide",["$aria",function(a){return a.$$watchExpr("ngHide","aria-hidden",[],!1)}]).directive("ngValue",["$aria",function(a){return a.$$watchExpr("ngValue","aria-checked",f,!1)}]).directive("ngChecked",["$aria",function(a){return a.$$watchExpr("ngChecked","aria-checked",f,!1)}]).directive("ngRequired",
-["$aria",function(a){return a.$$watchExpr("ngRequired","aria-required",f,!1)}]).directive("ngModel",["$aria",function(a){function c(c,n,d,e){return a.config(n)&&!d.attr(c)&&(e||!l(d,f))}function m(a,c){return!c.attr("role")&&c.attr("type")===a&&"INPUT"!==c[0].nodeName}function h(a,c){var d=a.type,e=a.role;return"checkbox"===(d||e)||"menuitemcheckbox"===e?"checkbox":"radio"===(d||e)||"menuitemradio"===e?"radio":"range"===d||"progressbar"===e||"slider"===e?"range":""}return{restrict:"A",require:"ngModel",
-priority:200,compile:function(f,n){var d=h(n,f);return{pre:function(a,b,c,k){"checkbox"===d&&(k.$isEmpty=function(a){return!1===a})},post:function(e,b,g,k){function f(){return k.$modelValue}function h(a){b.attr("aria-checked",g.value==k.$viewValue)}function n(){b.attr("aria-checked",!k.$isEmpty(k.$viewValue))}var l=c("tabindex","tabindex",b,!1);switch(d){case "radio":case "checkbox":m(d,b)&&b.attr("role",d);c("aria-checked","ariaChecked",b,!1)&&e.$watch(f,"radio"===d?h:n);l&&b.attr("tabindex",0);
-break;case "range":m(d,b)&&b.attr("role","slider");if(a.config("ariaValue")){var p=!b.attr("aria-valuemin")&&(g.hasOwnProperty("min")||g.hasOwnProperty("ngMin")),q=!b.attr("aria-valuemax")&&(g.hasOwnProperty("max")||g.hasOwnProperty("ngMax")),r=!b.attr("aria-valuenow");p&&g.$observe("min",function(a){b.attr("aria-valuemin",a)});q&&g.$observe("max",function(a){b.attr("aria-valuemax",a)});r&&e.$watch(f,function(a){b.attr("aria-valuenow",a)})}l&&b.attr("tabindex",0)}!g.hasOwnProperty("ngRequired")&&
-k.$validators.required&&c("aria-required","ariaRequired",b,!1)&&g.$observe("required",function(){b.attr("aria-required",!!g.required)});c("aria-invalid","ariaInvalid",b,!0)&&e.$watch(function(){return k.$invalid},function(a){b.attr("aria-invalid",!!a)})}}}}}]).directive("ngDisabled",["$aria",function(a){return a.$$watchExpr("ngDisabled","aria-disabled",f,!1)}]).directive("ngMessages",function(){return{restrict:"A",require:"?ngMessages",link:function(a,c,f,h){c.attr("aria-live")||c.attr("aria-live",
-"assertive")}}}).directive("ngClick",["$aria","$parse",function(a,c){return{restrict:"A",compile:function(m,h){var p=c(h.ngClick,null,!0);return function(c,d,e){if(!l(d,f)&&(a.config("bindRoleForClick")&&!d.attr("role")&&d.attr("role","button"),a.config("tabindex")&&!d.attr("tabindex")&&d.attr("tabindex",0),a.config("bindKeypress")&&!e.ngKeypress))d.on("keypress",function(a){function d(){p(c,{$event:a})}var e=a.which||a.keyCode;32!==e&&13!==e||c.$apply(d)})}}}}]).directive("ngDblclick",["$aria",function(a){return function(c,
-m,h){!a.config("tabindex")||m.attr("tabindex")||l(m,f)||m.attr("tabindex",0)}}])})(window,window.angular);
-//# sourceMappingURL=angular-aria.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js.map
deleted file mode 100644
index b1db15b5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-aria.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-aria.min.js",
-"lineCount":13,
-"mappings":"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",
-"sources":["angular-aria.js"],
-"names":["window","angular","undefined","nodeBlackList","isNodeOneOf","elem","nodeTypeArray","indexOf","nodeName","module","provider","ngAriaModule","$AriaProvider","watchExpr","attrName","ariaAttr","negate","scope","attr","ariaCamelName","$normalize","config","$watch","boolVal","ariaHidden","ariaChecked","ariaDisabled","ariaRequired","ariaInvalid","ariaValue","tabindex","bindKeypress","bindRoleForClick","this.config","newConfig","extend","$get","this.$get","key","$$watchExpr","directive","$aria","shouldAttachAttr","normalizedAttr","allowBlacklistEls","shouldAttachRole","role","getShape","type","restrict","require","priority","compile","shape","pre","ngModel","$isEmpty","ngModel.$isEmpty","value","post","ngAriaWatchModelValue","$modelValue","getRadioReaction","newVal","$viewValue","getCheckboxReaction","needsTabIndex","needsAriaValuemin","hasOwnProperty","needsAriaValuemax","needsAriaValuenow","$observe","ngAriaValueMinReaction","ngAriaValueNowReaction","$validators","required","ngAriaInvalidWatch","$invalid","ngAriaInvalidReaction","link","ngMessages","$parse","fn","ngClick","ngKeypress","on","event","callback","$event","keyCode","which","$apply"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.js
deleted file mode 100644
index 2157ef03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-cookies.js
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngCookies
- * @description
- *
- * # ngCookies
- *
- * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
- *
- *
- * <div doc-module-components="ngCookies"></div>
- *
- * See {@link ngCookies.$cookies `$cookies`} for usage.
- */
-
-
-angular.module('ngCookies', ['ng']).
- /**
- * @ngdoc provider
- * @name $cookiesProvider
- * @description
- * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
- * */
- provider('$cookies', [function $CookiesProvider() {
- /**
- * @ngdoc property
- * @name $cookiesProvider#defaults
- * @description
- *
- * Object containing default options to pass when setting cookies.
- *
- * The object may have following properties:
- *
- * - **path** - `{string}` - The cookie will be available only for this path and its
- * sub-paths. By default, this is the URL that appears in your `<base>` tag.
- * - **domain** - `{string}` - The cookie will be available only for this domain and
- * its sub-domains. For security reasons the user agent will not accept the cookie
- * if the current domain is not a sub-domain of this domain or equal to it.
- * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
- * or a Date object indicating the exact date/time this cookie will expire.
- * - **secure** - `{boolean}` - If `true`, then the cookie will only be available through a
- * secured connection.
- *
- * Note: By default, the address that appears in your `<base>` tag will be used as the path.
- * This is important so that cookies will be visible for all routes when html5mode is enabled.
- *
- **/
- var defaults = this.defaults = {};
-
- function calcOptions(options) {
- return options ? angular.extend({}, defaults, options) : defaults;
- }
-
- /**
- * @ngdoc service
- * @name $cookies
- *
- * @description
- * Provides read/write access to browser's cookies.
- *
- * <div class="alert alert-info">
- * Up until Angular 1.3, `$cookies` exposed properties that represented the
- * current browser cookie values. In version 1.4, this behavior has changed, and
- * `$cookies` now provides a standard api of getters, setters etc.
- * </div>
- *
- * Requires the {@link ngCookies `ngCookies`} module to be installed.
- *
- * @example
- *
- * ```js
- * angular.module('cookiesExample', ['ngCookies'])
- * .controller('ExampleController', ['$cookies', function($cookies) {
- * // Retrieving a cookie
- * var favoriteCookie = $cookies.get('myFavorite');
- * // Setting a cookie
- * $cookies.put('myFavorite', 'oatmeal');
- * }]);
- * ```
- */
- this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
- return {
- /**
- * @ngdoc method
- * @name $cookies#get
- *
- * @description
- * Returns the value of given cookie key
- *
- * @param {string} key Id to use for lookup.
- * @returns {string} Raw cookie value.
- */
- get: function(key) {
- return $$cookieReader()[key];
- },
-
- /**
- * @ngdoc method
- * @name $cookies#getObject
- *
- * @description
- * Returns the deserialized value of given cookie key
- *
- * @param {string} key Id to use for lookup.
- * @returns {Object} Deserialized cookie value.
- */
- getObject: function(key) {
- var value = this.get(key);
- return value ? angular.fromJson(value) : value;
- },
-
- /**
- * @ngdoc method
- * @name $cookies#getAll
- *
- * @description
- * Returns a key value object with all the cookies
- *
- * @returns {Object} All cookies
- */
- getAll: function() {
- return $$cookieReader();
- },
-
- /**
- * @ngdoc method
- * @name $cookies#put
- *
- * @description
- * Sets a value for given cookie key
- *
- * @param {string} key Id for the `value`.
- * @param {string} value Raw value to be stored.
- * @param {Object=} options Options object.
- * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
- */
- put: function(key, value, options) {
- $$cookieWriter(key, value, calcOptions(options));
- },
-
- /**
- * @ngdoc method
- * @name $cookies#putObject
- *
- * @description
- * Serializes and sets a value for given cookie key
- *
- * @param {string} key Id for the `value`.
- * @param {Object} value Value to be stored.
- * @param {Object=} options Options object.
- * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
- */
- putObject: function(key, value, options) {
- this.put(key, angular.toJson(value), options);
- },
-
- /**
- * @ngdoc method
- * @name $cookies#remove
- *
- * @description
- * Remove given cookie
- *
- * @param {string} key Id of the key-value pair to delete.
- * @param {Object=} options Options object.
- * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
- */
- remove: function(key, options) {
- $$cookieWriter(key, undefined, calcOptions(options));
- }
- };
- }];
- }]);
-
-angular.module('ngCookies').
-/**
- * @ngdoc service
- * @name $cookieStore
- * @deprecated
- * @requires $cookies
- *
- * @description
- * Provides a key-value (string-object) storage, that is backed by session cookies.
- * Objects put or retrieved from this storage are automatically serialized or
- * deserialized by angular's toJson/fromJson.
- *
- * Requires the {@link ngCookies `ngCookies`} module to be installed.
- *
- * <div class="alert alert-danger">
- * **Note:** The $cookieStore service is **deprecated**.
- * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
- * </div>
- *
- * @example
- *
- * ```js
- * angular.module('cookieStoreExample', ['ngCookies'])
- * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
- * // Put cookie
- * $cookieStore.put('myFavorite','oatmeal');
- * // Get cookie
- * var favoriteCookie = $cookieStore.get('myFavorite');
- * // Removing a cookie
- * $cookieStore.remove('myFavorite');
- * }]);
- * ```
- */
- factory('$cookieStore', ['$cookies', function($cookies) {
-
- return {
- /**
- * @ngdoc method
- * @name $cookieStore#get
- *
- * @description
- * Returns the value of given cookie key
- *
- * @param {string} key Id to use for lookup.
- * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
- */
- get: function(key) {
- return $cookies.getObject(key);
- },
-
- /**
- * @ngdoc method
- * @name $cookieStore#put
- *
- * @description
- * Sets a value for given cookie key
- *
- * @param {string} key Id for the `value`.
- * @param {Object} value Value to be stored.
- */
- put: function(key, value) {
- $cookies.putObject(key, value);
- },
-
- /**
- * @ngdoc method
- * @name $cookieStore#remove
- *
- * @description
- * Remove given cookie
- *
- * @param {string} key Id of the key-value pair to delete.
- */
- remove: function(key) {
- $cookies.remove(key);
- }
- };
-
- }]);
-
-/**
- * @name $$cookieWriter
- * @requires $document
- *
- * @description
- * This is a private service for writing cookies
- *
- * @param {string} name Cookie name
- * @param {string=} value Cookie value (if undefined, cookie will be deleted)
- * @param {Object=} options Object with options that need to be stored for the cookie.
- */
-function $$CookieWriter($document, $log, $browser) {
- var cookiePath = $browser.baseHref();
- var rawDocument = $document[0];
-
- function buildCookieString(name, value, options) {
- var path, expires;
- options = options || {};
- expires = options.expires;
- path = angular.isDefined(options.path) ? options.path : cookiePath;
- if (angular.isUndefined(value)) {
- expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
- value = '';
- }
- if (angular.isString(expires)) {
- expires = new Date(expires);
- }
-
- var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
- str += path ? ';path=' + path : '';
- str += options.domain ? ';domain=' + options.domain : '';
- str += expires ? ';expires=' + expires.toUTCString() : '';
- str += options.secure ? ';secure' : '';
-
- // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
- // - 300 cookies
- // - 20 cookies per unique domain
- // - 4096 bytes per cookie
- var cookieLength = str.length + 1;
- if (cookieLength > 4096) {
- $log.warn("Cookie '" + name +
- "' possibly not set or overflowed because it was too large (" +
- cookieLength + " > 4096 bytes)!");
- }
-
- return str;
- }
-
- return function(name, value, options) {
- rawDocument.cookie = buildCookieString(name, value, options);
- };
-}
-
-$$CookieWriter.$inject = ['$document', '$log', '$browser'];
-
-angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
- this.$get = $$CookieWriter;
-});
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js
deleted file mode 100644
index 19f59cc8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(A,d,B){'use strict';function l(){return["$animate",function(v){return{restrict:"AE",transclude:"element",priority:1,terminal:!0,require:"^^ngMessages",link:function(n,r,a,b,m){var k=r[0],f,p=a.ngMessage||a.when;a=a.ngMessageExp||a.whenExp;var d=function(a){f=a?w(a)?a:a.split(/[\s,]+/):null;b.reRender()};a?(d(n.$eval(a)),n.$watchCollection(a,d)):d(p);var e,q;b.register(k,q={test:function(a){var g=f;a=g?w(g)?0<=g.indexOf(a):g.hasOwnProperty(a):void 0;return a},attach:function(){e||m(n,function(a){v.enter(a,
-null,r);e=a;var g=e.$$attachId=b.getAttachId();e.on("$destroy",function(){e&&e.$$attachId===g&&(b.deregister(k),q.detach())})})},detach:function(){if(e){var a=e;e=null;v.leave(a)}}})}}}]}var w=d.isArray,x=d.forEach,y=d.isString,z=d.element;d.module("ngMessages",[]).directive("ngMessages",["$animate",function(d){function n(a,b){return y(b)&&0===b.length||r(a.$eval(b))}function r(a){return y(a)?a.length:!!a}return{require:"ngMessages",restrict:"AE",controller:["$element","$scope","$attrs",function(a,
-b,m){function k(a,b){for(var c=b,f=[];c&&c!==a;){var h=c.$$ngMessageNode;if(h&&h.length)return e[h];c.childNodes.length&&-1==f.indexOf(c)?(f.push(c),c=c.childNodes[c.childNodes.length-1]):c=c.previousSibling||c.parentNode}}var f=this,p=0,l=0;this.getAttachId=function(){return l++};var e=this.messages={},q,s;this.render=function(g){g=g||{};q=!1;s=g;for(var e=n(b,m.ngMessagesMultiple)||n(b,m.multiple),c=[],k={},h=f.head,p=!1,l=0;null!=h;){l++;var t=h.message,u=!1;p||x(g,function(a,c){!u&&r(a)&&t.test(c)&&
-!k[c]&&(u=k[c]=!0,t.attach())});u?p=!e:c.push(t);h=h.next}x(c,function(a){a.detach()});c.length!==l?d.setClass(a,"ng-active","ng-inactive"):d.setClass(a,"ng-inactive","ng-active")};b.$watchCollection(m.ngMessages||m["for"],f.render);this.reRender=function(){q||(q=!0,b.$evalAsync(function(){q&&s&&f.render(s)}))};this.register=function(g,b){var c=p.toString();e[c]={message:b};var d=a[0],h=e[c];f.head?(d=k(d,g))?(h.next=d.next,d.next=h):(h.next=f.head,f.head=h):f.head=h;g.$$ngMessageNode=c;p++;f.reRender()};
-this.deregister=function(b){var d=b.$$ngMessageNode;delete b.$$ngMessageNode;var c=e[d];(b=k(a[0],b))?b.next=c.next:f.head=c.next;delete e[d];f.reRender()}}]}}]).directive("ngMessagesInclude",["$templateRequest","$document","$compile",function(d,n,l){return{restrict:"AE",require:"^^ngMessages",link:function(a,b,m){var k=m.ngMessagesInclude||m.src;d(k).then(function(d){l(d)(a,function(a){b.after(a);a=z(n[0].createComment(" ngMessagesInclude: "+k+" "));b.after(a);b.remove()})})}}}]).directive("ngMessage",
-l()).directive("ngMessageExp",l())})(window,window.angular);
-//# sourceMappingURL=angular-messages.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js.map
deleted file mode 100644
index 0cb2a943..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-messages.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-messages.min.js",
-"lineCount":11,
-"mappings":"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",
-"sources":["angular-messages.js"],
-"names":["window","angular","undefined","ngMessageDirectiveFactory","$animate","restrict","transclude","priority","terminal","require","link","scope","element","attrs","ngMessagesCtrl","$transclude","commentNode","records","staticExp","ngMessage","when","dynamicExp","ngMessageExp","whenExp","assignRecords","items","isArray","split","reRender","$eval","$watchCollection","currentElement","messageCtrl","register","test","name","collection","indexOf","hasOwnProperty","attach","elm","enter","$$attachId","getAttachId","on","deregister","detach","leave","forEach","isString","jqLite","module","directive","isAttrTruthy","attr","length","truthy","val","controller","$element","$scope","$attrs","findPreviousMessage","parent","comment","prevNode","parentLookup","prevKey","$$ngMessageNode","messages","childNodes","push","previousSibling","parentNode","ctrl","latestKey","nextAttachId","this.getAttachId","renderLater","cachedCollection","render","this.render","multiple","ngMessagesMultiple","unmatchedMessages","matchedKeys","messageItem","head","messageFound","totalMessages","message","messageUsed","value","key","next","setClass","ACTIVE_CLASS","INACTIVE_CLASS","ngMessages","this.reRender","$evalAsync","this.register","nextKey","toString","messageNode","match","this.deregister","$templateRequest","$document","$compile","src","ngMessagesInclude","then","html","contents","after","anchor","createComment","remove"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js
deleted file mode 100644
index 306657dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(Q,d,G){'use strict';function H(t,g){g=g||{};d.forEach(g,function(d,q){delete g[q]});for(var q in t)!t.hasOwnProperty(q)||"$"===q.charAt(0)&&"$"===q.charAt(1)||(g[q]=t[q]);return g}var z=d.$$minErr("$resource"),N=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var t=/^https?:\/\/[^\/]*/,g=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}};
-this.$get=["$http","$log","$q","$timeout",function(q,M,I,J){function A(d,h){return encodeURIComponent(d).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,h?"%20":"+")}function B(d,h){this.template=d;this.defaults=v({},g.defaults,h);this.urlParams={}}function K(e,h,n,k){function c(a,b){var c={};b=v({},h,b);u(b,function(b,h){x(b)&&(b=b());var f;if(b&&b.charAt&&"@"==b.charAt(0)){f=a;var l=b.substr(1);if(null==l||""===l||"hasOwnProperty"===l||!N.test("."+
-l))throw z("badmember",l);for(var l=l.split("."),m=0,k=l.length;m<k&&d.isDefined(f);m++){var r=l[m];f=null!==f?f[r]:G}}else f=b;c[h]=f});return c}function O(a){return a.resource}function m(a){H(a||{},this)}var t=new B(e,k);n=v({},g.defaults.actions,n);m.prototype.toJSON=function(){var a=v({},this);delete a.$promise;delete a.$resolved;return a};u(n,function(a,b){var h=/^(POST|PUT|PATCH)$/i.test(a.method),e=a.timeout,E=d.isDefined(a.cancellable)?a.cancellable:k&&d.isDefined(k.cancellable)?k.cancellable:
-g.defaults.cancellable;e&&!d.isNumber(e)&&(M.debug("ngResource:\n Only numeric values are allowed as `timeout`.\n Promises are not supported in $resource, because the same value would be used for multiple requests. If you are looking for a way to cancel requests, you should use the `cancellable` option."),delete a.timeout,e=null);m[b]=function(f,l,k,g){var r={},n,w,C;switch(arguments.length){case 4:C=g,w=k;case 3:case 2:if(x(l)){if(x(f)){w=f;C=l;break}w=l;C=k}else{r=f;n=l;w=k;break}case 1:x(f)?
-w=f:h?n=f:r=f;break;case 0:break;default:throw z("badargs",arguments.length);}var D=this instanceof m,p=D?n:a.isArray?[]:new m(n),s={},A=a.interceptor&&a.interceptor.response||O,B=a.interceptor&&a.interceptor.responseError||G,y,F;u(a,function(a,b){switch(b){default:s[b]=P(a);case "params":case "isArray":case "interceptor":case "cancellable":}});!D&&E&&(y=I.defer(),s.timeout=y.promise,e&&(F=J(y.resolve,e)));h&&(s.data=n);t.setUrlParams(s,v({},c(n,a.params||{}),r),a.url);r=q(s).then(function(f){var c=
-f.data;if(c){if(d.isArray(c)!==!!a.isArray)throw z("badcfg",b,a.isArray?"array":"object",d.isArray(c)?"array":"object",s.method,s.url);if(a.isArray)p.length=0,u(c,function(b){"object"===typeof b?p.push(new m(b)):p.push(b)});else{var l=p.$promise;H(c,p);p.$promise=l}}f.resource=p;return f},function(b){(C||L)(b);return I.reject(b)});r.finally(function(){p.$resolved=!0;!D&&E&&(p.$cancelRequest=d.noop,J.cancel(F),y=F=s.timeout=null)});r=r.then(function(b){var a=A(b);(w||L)(a,b.headers);return a},B);return D?
-r:(p.$promise=r,p.$resolved=!1,E&&(p.$cancelRequest=y.resolve),p)};m.prototype["$"+b]=function(a,c,d){x(a)&&(d=c,c=a,a={});a=m[b].call(this,a,this,c,d);return a.$promise||a}});m.bind=function(a){return K(e,v({},h,a),n)};return m}var L=d.noop,u=d.forEach,v=d.extend,P=d.copy,x=d.isFunction;B.prototype={setUrlParams:function(e,h,n){var k=this,c=n||k.template,g,m,q="",a=k.urlParams={};u(c.split(/\W/),function(b){if("hasOwnProperty"===b)throw z("badname");!/^\d+$/.test(b)&&b&&(new RegExp("(^|[^\\\\]):"+
-b+"(\\W|$)")).test(c)&&(a[b]={isQueryParamValue:(new RegExp("\\?.*=:"+b+"(?:\\W|$)")).test(c)})});c=c.replace(/\\:/g,":");c=c.replace(t,function(a){q=a;return""});h=h||{};u(k.urlParams,function(a,e){g=h.hasOwnProperty(e)?h[e]:k.defaults[e];d.isDefined(g)&&null!==g?(m=a.isQueryParamValue?A(g,!0):A(g,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(new RegExp(":"+e+"(\\W|$)","g"),function(a,b){return m+b})):c=c.replace(new RegExp("(/?):"+e+"(\\W|$)","g"),function(a,b,c){return"/"==
-c.charAt(0)?c:b+c})});k.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");e.url=q+c.replace(/\/\\\./,"/.");u(h,function(a,c){k.urlParams[c]||(e.params=e.params||{},e.params[c]=a)})}};return K}]})})(window,window.angular);
-//# sourceMappingURL=angular-resource.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js.map
deleted file mode 100644
index 5174e18b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-resource.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-resource.min.js",
-"lineCount":14,
-"mappings":"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",
-"sources":["angular-resource.js"],
-"names":["window","angular","undefined","shallowClearAndCopy","src","dst","forEach","value","key","hasOwnProperty","charAt","$resourceMinErr","$$minErr","MEMBER_NAME_REGEX","module","provider","PROTOCOL_AND_DOMAIN_REGEX","defaults","stripTrailingSlashes","actions","method","isArray","$get","$http","$log","$q","$timeout","encodeUriQuery","val","pctEncodeSpaces","encodeURIComponent","replace","Route","template","extend","urlParams","resourceFactory","url","paramDefaults","options","extractParams","data","actionParams","ids","isFunction","path","test","keys","split","i","ii","length","isDefined","obj","defaultResponseInterceptor","response","resource","Resource","route","prototype","toJSON","Resource.prototype.toJSON","$promise","$resolved","action","name","hasBody","numericTimeout","timeout","cancellable","isNumber","debug","a1","a2","a3","a4","params","success","error","arguments","isInstanceCall","httpConfig","responseInterceptor","interceptor","responseErrorInterceptor","responseError","timeoutDeferred","numericTimeoutPromise","copy","defer","promise","resolve","setUrlParams","then","item","push","noop","reject","finally","$cancelRequest","cancel","headers","result","call","bind","Resource.bind","additionalParamDefaults","config","actionUrl","self","encodedVal","protocolAndDomain","param","RegExp","isQueryParamValue","match","paramInfo","urlParam","p1","leadingSlashes","tail"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.js
deleted file mode 100644
index 45ac238e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.js
+++ /dev/null
@@ -1,1016 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngRoute
- * @description
- *
- * # ngRoute
- *
- * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- *
- * <div doc-module-components="ngRoute"></div>
- */
- /* global -ngRouteModule */
-var ngRouteModule = angular.module('ngRoute', ['ng']).
- provider('$route', $RouteProvider),
- $routeMinErr = angular.$$minErr('ngRoute');
-
-/**
- * @ngdoc provider
- * @name $routeProvider
- *
- * @description
- *
- * Used for configuring routes.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- * ## Dependencies
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- */
-function $RouteProvider() {
- function inherit(parent, extra) {
- return angular.extend(Object.create(parent), extra);
- }
-
- var routes = {};
-
- /**
- * @ngdoc method
- * @name $routeProvider#when
- *
- * @param {string} path Route path (matched against `$location.path`). If `$location.path`
- * contains redundant trailing slash or is missing one, the route will still match and the
- * `$location.path` will be updated to add or drop the trailing slash to exactly match the
- * route definition.
- *
- * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
- * to the next slash are matched and stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain named groups starting with a colon and ending with a star:
- * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
- *
- * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
- * `/color/brown/largecode/code/with/slashes/edit` and extract:
- *
- * * `color: brown`
- * * `largecode: code/with/slashes`.
- *
- *
- * @param {Object} route Mapping information to be assigned to `$route.current` on route
- * match.
- *
- * Object properties:
- *
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
- * newly created scope or the name of a {@link angular.Module#controller registered
- * controller} if passed as a string.
- * - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
- * If present, the controller will be published to scope under the `controllerAs` name.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used by {@link
- * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
- * This property takes precedence over `templateUrl`.
- *
- * If `template` is a function, it will be called with the following parameters:
- *
- * - `{Array.<Object>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route
- *
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
- * template that should be used by {@link ngRoute.directive:ngView ngView}.
- *
- * If `templateUrl` is a function, it will be called with the following parameters:
- *
- * - `{Array.<Object>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route
- *
- * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
- * be injected into the controller. If any of these dependencies are promises, the router
- * will wait for them all to be resolved or one to be rejected before the controller is
- * instantiated.
- * If all the promises are resolved successfully, the values of the resolved promises are
- * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
- * fired. If any of the promises are rejected the
- * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired.
- * For easier access to the resolved dependencies from the template, the `resolve` map will
- * be available on the scope of the route, under `$resolve` (by default) or a custom name
- * specified by the `resolveAs` property (see below). This can be particularly useful, when
- * working with {@link angular.Module#component components} as route templates.<br />
- * <div class="alert alert-warning">
- * **Note:** If your scope already contains a property with this name, it will be hidden
- * or overwritten. Make sure, you specify an appropriate name for this property, that
- * does not collide with other properties on the scope.
- * </div>
- * The map object is:
- *
- * - `key` – `{string}`: a name of a dependency to be injected into the controller.
- * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
- * Otherwise if function, then it is {@link auto.$injector#invoke injected}
- * and the return value is treated as the dependency. If the result is a promise, it is
- * resolved before its value is injected into the controller. Be aware that
- * `ngRoute.$routeParams` will still refer to the previous route within these resolve
- * functions. Use `$route.current.params` to access the new route parameters, instead.
- *
- * - `resolveAs` - `{string=}` - The name under which the `resolve` map will be available on
- * the scope of the route. If omitted, defaults to `$resolve`.
- *
- * - `redirectTo` – `{(string|function())=}` – value to update
- * {@link ng.$location $location} path with and trigger route redirection.
- *
- * If `redirectTo` is a function, it will be called with the following parameters:
- *
- * - `{Object.<string>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route templateUrl.
- * - `{string}` - current `$location.path()`
- * - `{Object}` - current `$location.search()`
- *
- * The custom `redirectTo` function is expected to return a string which will be used
- * to update `$location.path()` and `$location.search()`.
- *
- * - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()`
- * or `$location.hash()` changes.
- *
- * If the option is set to `false` and url in the browser changes, then
- * `$routeUpdate` event is broadcasted on the root scope.
- *
- * - `[caseInsensitiveMatch=false]` - `{boolean=}` - match routes without being case sensitive
- *
- * If the option is set to `true`, then the particular route can be matched without being
- * case sensitive
- *
- * @returns {Object} self
- *
- * @description
- * Adds a new route definition to the `$route` service.
- */
- this.when = function(path, route) {
- //copy original route object to preserve params inherited from proto chain
- var routeCopy = angular.copy(route);
- if (angular.isUndefined(routeCopy.reloadOnSearch)) {
- routeCopy.reloadOnSearch = true;
- }
- if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
- routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
- }
- routes[path] = angular.extend(
- routeCopy,
- path && pathRegExp(path, routeCopy)
- );
-
- // create redirection for trailing slashes
- if (path) {
- var redirectPath = (path[path.length - 1] == '/')
- ? path.substr(0, path.length - 1)
- : path + '/';
-
- routes[redirectPath] = angular.extend(
- {redirectTo: path},
- pathRegExp(redirectPath, routeCopy)
- );
- }
-
- return this;
- };
-
- /**
- * @ngdoc property
- * @name $routeProvider#caseInsensitiveMatch
- * @description
- *
- * A boolean property indicating if routes defined
- * using this provider should be matched using a case insensitive
- * algorithm. Defaults to `false`.
- */
- this.caseInsensitiveMatch = false;
-
- /**
- * @param path {string} path
- * @param opts {Object} options
- * @return {?Object}
- *
- * @description
- * Normalizes the given path, returning a regular expression
- * and the original path.
- *
- * Inspired by pathRexp in visionmedia/express/lib/utils.js.
- */
- function pathRegExp(path, opts) {
- var insensitive = opts.caseInsensitiveMatch,
- ret = {
- originalPath: path,
- regexp: path
- },
- keys = ret.keys = [];
-
- path = path
- .replace(/([().])/g, '\\$1')
- .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
- var optional = option === '?' ? option : null;
- var star = option === '*' ? option : null;
- keys.push({ name: key, optional: !!optional });
- slash = slash || '';
- return ''
- + (optional ? '' : slash)
- + '(?:'
- + (optional ? slash : '')
- + (star && '(.+?)' || '([^/]+)')
- + (optional || '')
- + ')'
- + (optional || '');
- })
- .replace(/([\/$\*])/g, '\\$1');
-
- ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
- return ret;
- }
-
- /**
- * @ngdoc method
- * @name $routeProvider#otherwise
- *
- * @description
- * Sets route definition that will be used on route change when no other route definition
- * is matched.
- *
- * @param {Object|string} params Mapping information to be assigned to `$route.current`.
- * If called with a string, the value maps to `redirectTo`.
- * @returns {Object} self
- */
- this.otherwise = function(params) {
- if (typeof params === 'string') {
- params = {redirectTo: params};
- }
- this.when(null, params);
- return this;
- };
-
-
- this.$get = ['$rootScope',
- '$location',
- '$routeParams',
- '$q',
- '$injector',
- '$templateRequest',
- '$sce',
- function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
-
- /**
- * @ngdoc service
- * @name $route
- * @requires $location
- * @requires $routeParams
- *
- * @property {Object} current Reference to the current route definition.
- * The route definition contains:
- *
- * - `controller`: The controller constructor as defined in the route definition.
- * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
- * controller instantiation. The `locals` contain
- * the resolved values of the `resolve` map. Additionally the `locals` also contain:
- *
- * - `$scope` - The current route scope.
- * - `$template` - The current route template HTML.
- *
- * The `locals` will be assigned to the route scope's `$resolve` property. You can override
- * the property name, using `resolveAs` in the route definition. See
- * {@link ngRoute.$routeProvider $routeProvider} for more info.
- *
- * @property {Object} routes Object with all route configuration Objects as its properties.
- *
- * @description
- * `$route` is used for deep-linking URLs to controllers and views (HTML partials).
- * It watches `$location.url()` and tries to map the path to an existing route definition.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
- *
- * The `$route` service is typically used in conjunction with the
- * {@link ngRoute.directive:ngView `ngView`} directive and the
- * {@link ngRoute.$routeParams `$routeParams`} service.
- *
- * @example
- * This example shows how changing the URL hash causes the `$route` to match a route against the
- * URL, and the `ngView` pulls in the partial.
- *
- * <example name="$route-service" module="ngRouteExample"
- * deps="angular-route.js" fixBase="true">
- * <file name="index.html">
- * <div ng-controller="MainController">
- * Choose:
- * <a href="Book/Moby">Moby</a> |
- * <a href="Book/Moby/ch/1">Moby: Ch1</a> |
- * <a href="Book/Gatsby">Gatsby</a> |
- * <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
- * <a href="Book/Scarlet">Scarlet Letter</a><br/>
- *
- * <div ng-view></div>
- *
- * <hr />
- *
- * <pre>$location.path() = {{$location.path()}}</pre>
- * <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
- * <pre>$route.current.params = {{$route.current.params}}</pre>
- * <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
- * <pre>$routeParams = {{$routeParams}}</pre>
- * </div>
- * </file>
- *
- * <file name="book.html">
- * controller: {{name}}<br />
- * Book Id: {{params.bookId}}<br />
- * </file>
- *
- * <file name="chapter.html">
- * controller: {{name}}<br />
- * Book Id: {{params.bookId}}<br />
- * Chapter Id: {{params.chapterId}}
- * </file>
- *
- * <file name="script.js">
- * angular.module('ngRouteExample', ['ngRoute'])
- *
- * .controller('MainController', function($scope, $route, $routeParams, $location) {
- * $scope.$route = $route;
- * $scope.$location = $location;
- * $scope.$routeParams = $routeParams;
- * })
- *
- * .controller('BookController', function($scope, $routeParams) {
- * $scope.name = "BookController";
- * $scope.params = $routeParams;
- * })
- *
- * .controller('ChapterController', function($scope, $routeParams) {
- * $scope.name = "ChapterController";
- * $scope.params = $routeParams;
- * })
- *
- * .config(function($routeProvider, $locationProvider) {
- * $routeProvider
- * .when('/Book/:bookId', {
- * templateUrl: 'book.html',
- * controller: 'BookController',
- * resolve: {
- * // I will cause a 1 second delay
- * delay: function($q, $timeout) {
- * var delay = $q.defer();
- * $timeout(delay.resolve, 1000);
- * return delay.promise;
- * }
- * }
- * })
- * .when('/Book/:bookId/ch/:chapterId', {
- * templateUrl: 'chapter.html',
- * controller: 'ChapterController'
- * });
- *
- * // configure html5 to get links working on jsfiddle
- * $locationProvider.html5Mode(true);
- * });
- *
- * </file>
- *
- * <file name="protractor.js" type="protractor">
- * it('should load and compile correct template', function() {
- * element(by.linkText('Moby: Ch1')).click();
- * var content = element(by.css('[ng-view]')).getText();
- * expect(content).toMatch(/controller\: ChapterController/);
- * expect(content).toMatch(/Book Id\: Moby/);
- * expect(content).toMatch(/Chapter Id\: 1/);
- *
- * element(by.partialLinkText('Scarlet')).click();
- *
- * content = element(by.css('[ng-view]')).getText();
- * expect(content).toMatch(/controller\: BookController/);
- * expect(content).toMatch(/Book Id\: Scarlet/);
- * });
- * </file>
- * </example>
- */
-
- /**
- * @ngdoc event
- * @name $route#$routeChangeStart
- * @eventType broadcast on root scope
- * @description
- * Broadcasted before a route change. At this point the route services starts
- * resolving all of the dependencies needed for the route change to occur.
- * Typically this involves fetching the view template as well as any dependencies
- * defined in `resolve` route property. Once all of the dependencies are resolved
- * `$routeChangeSuccess` is fired.
- *
- * The route change (and the `$location` change that triggered it) can be prevented
- * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
- * for more details about event object.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {Route} next Future route information.
- * @param {Route} current Current route information.
- */
-
- /**
- * @ngdoc event
- * @name $route#$routeChangeSuccess
- * @eventType broadcast on root scope
- * @description
- * Broadcasted after a route change has happened successfully.
- * The `resolve` dependencies are now available in the `current.locals` property.
- *
- * {@link ngRoute.directive:ngView ngView} listens for the directive
- * to instantiate the controller and render the view.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {Route} current Current route information.
- * @param {Route|Undefined} previous Previous route information, or undefined if current is
- * first route entered.
- */
-
- /**
- * @ngdoc event
- * @name $route#$routeChangeError
- * @eventType broadcast on root scope
- * @description
- * Broadcasted if any of the resolve promises are rejected.
- *
- * @param {Object} angularEvent Synthetic event object
- * @param {Route} current Current route information.
- * @param {Route} previous Previous route information.
- * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
- */
-
- /**
- * @ngdoc event
- * @name $route#$routeUpdate
- * @eventType broadcast on root scope
- * @description
- * The `reloadOnSearch` property has been set to false, and we are reusing the same
- * instance of the Controller.
- *
- * @param {Object} angularEvent Synthetic event object
- * @param {Route} current Current/previous route information.
- */
-
- var forceReload = false,
- preparedRoute,
- preparedRouteIsUpdateOnly,
- $route = {
- routes: routes,
-
- /**
- * @ngdoc method
- * @name $route#reload
- *
- * @description
- * Causes `$route` service to reload the current route even if
- * {@link ng.$location $location} hasn't changed.
- *
- * As a result of that, {@link ngRoute.directive:ngView ngView}
- * creates new scope and reinstantiates the controller.
- */
- reload: function() {
- forceReload = true;
-
- var fakeLocationEvent = {
- defaultPrevented: false,
- preventDefault: function fakePreventDefault() {
- this.defaultPrevented = true;
- forceReload = false;
- }
- };
-
- $rootScope.$evalAsync(function() {
- prepareRoute(fakeLocationEvent);
- if (!fakeLocationEvent.defaultPrevented) commitRoute();
- });
- },
-
- /**
- * @ngdoc method
- * @name $route#updateParams
- *
- * @description
- * Causes `$route` service to update the current URL, replacing
- * current route parameters with those specified in `newParams`.
- * Provided property names that match the route's path segment
- * definitions will be interpolated into the location's path, while
- * remaining properties will be treated as query params.
- *
- * @param {!Object<string, string>} newParams mapping of URL parameter names to values
- */
- updateParams: function(newParams) {
- if (this.current && this.current.$$route) {
- newParams = angular.extend({}, this.current.params, newParams);
- $location.path(interpolate(this.current.$$route.originalPath, newParams));
- // interpolate modifies newParams, only query params are left
- $location.search(newParams);
- } else {
- throw $routeMinErr('norout', 'Tried updating route when with no current route');
- }
- }
- };
-
- $rootScope.$on('$locationChangeStart', prepareRoute);
- $rootScope.$on('$locationChangeSuccess', commitRoute);
-
- return $route;
-
- /////////////////////////////////////////////////////
-
- /**
- * @param on {string} current url
- * @param route {Object} route regexp to match the url against
- * @return {?Object}
- *
- * @description
- * Check if the route matches the current url.
- *
- * Inspired by match in
- * visionmedia/express/lib/router/router.js.
- */
- function switchRouteMatcher(on, route) {
- var keys = route.keys,
- params = {};
-
- if (!route.regexp) return null;
-
- var m = route.regexp.exec(on);
- if (!m) return null;
-
- for (var i = 1, len = m.length; i < len; ++i) {
- var key = keys[i - 1];
-
- var val = m[i];
-
- if (key && val) {
- params[key.name] = val;
- }
- }
- return params;
- }
-
- function prepareRoute($locationEvent) {
- var lastRoute = $route.current;
-
- preparedRoute = parseRoute();
- preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
- && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
- && !preparedRoute.reloadOnSearch && !forceReload;
-
- if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
- if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
- if ($locationEvent) {
- $locationEvent.preventDefault();
- }
- }
- }
- }
-
- function commitRoute() {
- var lastRoute = $route.current;
- var nextRoute = preparedRoute;
-
- if (preparedRouteIsUpdateOnly) {
- lastRoute.params = nextRoute.params;
- angular.copy(lastRoute.params, $routeParams);
- $rootScope.$broadcast('$routeUpdate', lastRoute);
- } else if (nextRoute || lastRoute) {
- forceReload = false;
- $route.current = nextRoute;
- if (nextRoute) {
- if (nextRoute.redirectTo) {
- if (angular.isString(nextRoute.redirectTo)) {
- $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
- .replace();
- } else {
- $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
- .replace();
- }
- }
- }
-
- $q.when(nextRoute).
- then(function() {
- if (nextRoute) {
- var locals = angular.extend({}, nextRoute.resolve),
- template, templateUrl;
-
- angular.forEach(locals, function(value, key) {
- locals[key] = angular.isString(value) ?
- $injector.get(value) : $injector.invoke(value, null, null, key);
- });
-
- if (angular.isDefined(template = nextRoute.template)) {
- if (angular.isFunction(template)) {
- template = template(nextRoute.params);
- }
- } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
- if (angular.isFunction(templateUrl)) {
- templateUrl = templateUrl(nextRoute.params);
- }
- if (angular.isDefined(templateUrl)) {
- nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
- template = $templateRequest(templateUrl);
- }
- }
- if (angular.isDefined(template)) {
- locals['$template'] = template;
- }
- return $q.all(locals);
- }
- }).
- then(function(locals) {
- // after route change
- if (nextRoute == $route.current) {
- if (nextRoute) {
- nextRoute.locals = locals;
- angular.copy(nextRoute.params, $routeParams);
- }
- $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
- }
- }, function(error) {
- if (nextRoute == $route.current) {
- $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
- }
- });
- }
- }
-
-
- /**
- * @returns {Object} the current active route, by matching it against the URL
- */
- function parseRoute() {
- // Match a route
- var params, match;
- angular.forEach(routes, function(route, path) {
- if (!match && (params = switchRouteMatcher($location.path(), route))) {
- match = inherit(route, {
- params: angular.extend({}, $location.search(), params),
- pathParams: params});
- match.$$route = route;
- }
- });
- // No route matched; fallback to "otherwise" route
- return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
- }
-
- /**
- * @returns {string} interpolation of the redirect path with the parameters
- */
- function interpolate(string, params) {
- var result = [];
- angular.forEach((string || '').split(':'), function(segment, i) {
- if (i === 0) {
- result.push(segment);
- } else {
- var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
- var key = segmentMatch[1];
- result.push(params[key]);
- result.push(segmentMatch[2] || '');
- delete params[key];
- }
- });
- return result.join('');
- }
- }];
-}
-
-ngRouteModule.provider('$routeParams', $RouteParamsProvider);
-
-
-/**
- * @ngdoc service
- * @name $routeParams
- * @requires $route
- *
- * @description
- * The `$routeParams` service allows you to retrieve the current set of route parameters.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * The route parameters are a combination of {@link ng.$location `$location`}'s
- * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
- * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
- *
- * In case of parameter name collision, `path` params take precedence over `search` params.
- *
- * The service guarantees that the identity of the `$routeParams` object will remain unchanged
- * (but its properties will likely change) even when a route change occurs.
- *
- * Note that the `$routeParams` are only updated *after* a route change completes successfully.
- * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
- * Instead you can use `$route.current.params` to access the new route's parameters.
- *
- * @example
- * ```js
- * // Given:
- * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
- * // Route: /Chapter/:chapterId/Section/:sectionId
- * //
- * // Then
- * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
- * ```
- */
-function $RouteParamsProvider() {
- this.$get = function() { return {}; };
-}
-
-ngRouteModule.directive('ngView', ngViewFactory);
-ngRouteModule.directive('ngView', ngViewFillContentFactory);
-
-
-/**
- * @ngdoc directive
- * @name ngView
- * @restrict ECA
- *
- * @description
- * # Overview
- * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
- * including the rendered template of the current route into the main layout (`index.html`) file.
- * Every time the current route changes, the included view changes with it according to the
- * configuration of the `$route` service.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * @animations
- * enter - animation is used to bring new content into the browser.
- * leave - animation is used to animate existing content away.
- *
- * The enter and leave animation occur concurrently.
- *
- * @scope
- * @priority 400
- * @param {string=} onload Expression to evaluate whenever the view updates.
- *
- * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
- * $anchorScroll} to scroll the viewport after the view is updated.
- *
- * - If the attribute is not set, disable scrolling.
- * - If the attribute is set without value, enable scrolling.
- * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
- * as an expression yields a truthy value.
- * @example
- <example name="ngView-directive" module="ngViewExample"
- deps="angular-route.js;angular-animate.js"
- animations="true" fixBase="true">
- <file name="index.html">
- <div ng-controller="MainCtrl as main">
- Choose:
- <a href="Book/Moby">Moby</a> |
- <a href="Book/Moby/ch/1">Moby: Ch1</a> |
- <a href="Book/Gatsby">Gatsby</a> |
- <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
- <a href="Book/Scarlet">Scarlet Letter</a><br/>
-
- <div class="view-animate-container">
- <div ng-view class="view-animate"></div>
- </div>
- <hr />
-
- <pre>$location.path() = {{main.$location.path()}}</pre>
- <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
- <pre>$route.current.params = {{main.$route.current.params}}</pre>
- <pre>$routeParams = {{main.$routeParams}}</pre>
- </div>
- </file>
-
- <file name="book.html">
- <div>
- controller: {{book.name}}<br />
- Book Id: {{book.params.bookId}}<br />
- </div>
- </file>
-
- <file name="chapter.html">
- <div>
- controller: {{chapter.name}}<br />
- Book Id: {{chapter.params.bookId}}<br />
- Chapter Id: {{chapter.params.chapterId}}
- </div>
- </file>
-
- <file name="animations.css">
- .view-animate-container {
- position:relative;
- height:100px!important;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .view-animate {
- padding:10px;
- }
-
- .view-animate.ng-enter, .view-animate.ng-leave {
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-
- display:block;
- width:100%;
- border-left:1px solid black;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- padding:10px;
- }
-
- .view-animate.ng-enter {
- left:100%;
- }
- .view-animate.ng-enter.ng-enter-active {
- left:0;
- }
- .view-animate.ng-leave.ng-leave-active {
- left:-100%;
- }
- </file>
-
- <file name="script.js">
- angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
- .config(['$routeProvider', '$locationProvider',
- function($routeProvider, $locationProvider) {
- $routeProvider
- .when('/Book/:bookId', {
- templateUrl: 'book.html',
- controller: 'BookCtrl',
- controllerAs: 'book'
- })
- .when('/Book/:bookId/ch/:chapterId', {
- templateUrl: 'chapter.html',
- controller: 'ChapterCtrl',
- controllerAs: 'chapter'
- });
-
- $locationProvider.html5Mode(true);
- }])
- .controller('MainCtrl', ['$route', '$routeParams', '$location',
- function($route, $routeParams, $location) {
- this.$route = $route;
- this.$location = $location;
- this.$routeParams = $routeParams;
- }])
- .controller('BookCtrl', ['$routeParams', function($routeParams) {
- this.name = "BookCtrl";
- this.params = $routeParams;
- }])
- .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
- this.name = "ChapterCtrl";
- this.params = $routeParams;
- }]);
-
- </file>
-
- <file name="protractor.js" type="protractor">
- it('should load and compile correct template', function() {
- element(by.linkText('Moby: Ch1')).click();
- var content = element(by.css('[ng-view]')).getText();
- expect(content).toMatch(/controller\: ChapterCtrl/);
- expect(content).toMatch(/Book Id\: Moby/);
- expect(content).toMatch(/Chapter Id\: 1/);
-
- element(by.partialLinkText('Scarlet')).click();
-
- content = element(by.css('[ng-view]')).getText();
- expect(content).toMatch(/controller\: BookCtrl/);
- expect(content).toMatch(/Book Id\: Scarlet/);
- });
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc event
- * @name ngView#$viewContentLoaded
- * @eventType emit on the current ngView scope
- * @description
- * Emitted every time the ngView content is reloaded.
- */
-ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
-function ngViewFactory($route, $anchorScroll, $animate) {
- return {
- restrict: 'ECA',
- terminal: true,
- priority: 400,
- transclude: 'element',
- link: function(scope, $element, attr, ctrl, $transclude) {
- var currentScope,
- currentElement,
- previousLeaveAnimation,
- autoScrollExp = attr.autoscroll,
- onloadExp = attr.onload || '';
-
- scope.$on('$routeChangeSuccess', update);
- update();
-
- function cleanupLastView() {
- if (previousLeaveAnimation) {
- $animate.cancel(previousLeaveAnimation);
- previousLeaveAnimation = null;
- }
-
- if (currentScope) {
- currentScope.$destroy();
- currentScope = null;
- }
- if (currentElement) {
- previousLeaveAnimation = $animate.leave(currentElement);
- previousLeaveAnimation.then(function() {
- previousLeaveAnimation = null;
- });
- currentElement = null;
- }
- }
-
- function update() {
- var locals = $route.current && $route.current.locals,
- template = locals && locals.$template;
-
- if (angular.isDefined(template)) {
- var newScope = scope.$new();
- var current = $route.current;
-
- // Note: This will also link all children of ng-view that were contained in the original
- // html. If that content contains controllers, ... they could pollute/change the scope.
- // However, using ng-view on an element with additional content does not make sense...
- // Note: We can't remove them in the cloneAttchFn of $transclude as that
- // function is called before linking the content, which would apply child
- // directives to non existing elements.
- var clone = $transclude(newScope, function(clone) {
- $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
- if (angular.isDefined(autoScrollExp)
- && (!autoScrollExp || scope.$eval(autoScrollExp))) {
- $anchorScroll();
- }
- });
- cleanupLastView();
- });
-
- currentElement = clone;
- currentScope = current.scope = newScope;
- currentScope.$emit('$viewContentLoaded');
- currentScope.$eval(onloadExp);
- } else {
- cleanupLastView();
- }
- }
- }
- };
-}
-
-// This directive is called during the $transclude call of the first `ngView` directive.
-// It will replace and compile the content of the element with the loaded template.
-// We need this directive so that the element content is already filled when
-// the link function of another directive on the same element as ngView
-// is called.
-ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
-function ngViewFillContentFactory($compile, $controller, $route) {
- return {
- restrict: 'ECA',
- priority: -400,
- link: function(scope, $element) {
- var current = $route.current,
- locals = current.locals;
-
- $element.html(locals.$template);
-
- var link = $compile($element.contents());
-
- if (current.controller) {
- locals.$scope = scope;
- var controller = $controller(current.controller, locals);
- if (current.controllerAs) {
- scope[current.controllerAs] = controller;
- }
- $element.data('$ngControllerController', controller);
- $element.children().data('$ngControllerController', controller);
- }
- scope[current.resolveAs || '$resolve'] = locals;
-
- link(scope);
- }
- };
-}
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js
deleted file mode 100644
index 4d0d0187..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(r,d,C){'use strict';function x(s,h,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,y){function k(){n&&(g.cancel(n),n=null);l&&(l.$destroy(),l=null);m&&(n=g.leave(m),n.then(function(){n=null}),m=null)}function z(){var b=s.current&&s.current.locals;if(d.isDefined(b&&b.$template)){var b=a.$new(),f=s.current;m=y(b,function(b){g.enter(b,null,m||c).then(function(){!d.isDefined(u)||u&&!a.$eval(u)||h()});k()});l=f.scope=b;l.$emit("$viewContentLoaded");
-l.$eval(v)}else k()}var l,m,n,u=b.autoscroll,v=b.onload||"";a.$on("$routeChangeSuccess",z);z()}}}function A(d,h,g){return{restrict:"ECA",priority:-400,link:function(a,c){var b=g.current,f=b.locals;c.html(f.$template);var y=d(c.contents());if(b.controller){f.$scope=a;var k=h(b.controller,f);b.controllerAs&&(a[b.controllerAs]=k);c.data("$ngControllerController",k);c.children().data("$ngControllerController",k)}a[b.resolveAs||"$resolve"]=f;y(a)}}}r=d.module("ngRoute",["ng"]).provider("$route",function(){function s(a,
-c){return d.extend(Object.create(a),c)}function h(a,d){var b=d.caseInsensitiveMatch,f={originalPath:a,regexp:a},g=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,d,b,c){a="?"===c?c:null;c="*"===c?c:null;g.push({name:b,optional:!!a});d=d||"";return""+(a?"":d)+"(?:"+(a?d:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=new RegExp("^"+a+"$",b?"i":"");return f}var g={};this.when=function(a,c){var b=d.copy(c);d.isUndefined(b.reloadOnSearch)&&
-(b.reloadOnSearch=!0);d.isUndefined(b.caseInsensitiveMatch)&&(b.caseInsensitiveMatch=this.caseInsensitiveMatch);g[a]=d.extend(b,a&&h(a,b));if(a){var f="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";g[f]=d.extend({redirectTo:a},h(f,b))}return this};this.caseInsensitiveMatch=!1;this.otherwise=function(a){"string"===typeof a&&(a={redirectTo:a});this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(a,c,b,f,h,k,r){function l(b){var e=
-t.current;(x=(p=n())&&e&&p.$$route===e.$$route&&d.equals(p.pathParams,e.pathParams)&&!p.reloadOnSearch&&!v)||!e&&!p||a.$broadcast("$routeChangeStart",p,e).defaultPrevented&&b&&b.preventDefault()}function m(){var w=t.current,e=p;if(x)w.params=e.params,d.copy(w.params,b),a.$broadcast("$routeUpdate",w);else if(e||w)v=!1,(t.current=e)&&e.redirectTo&&(d.isString(e.redirectTo)?c.path(u(e.redirectTo,e.params)).search(e.params).replace():c.url(e.redirectTo(e.pathParams,c.path(),c.search())).replace()),f.when(e).then(function(){if(e){var a=
-d.extend({},e.resolve),b,c;d.forEach(a,function(b,e){a[e]=d.isString(b)?h.get(b):h.invoke(b,null,null,e)});d.isDefined(b=e.template)?d.isFunction(b)&&(b=b(e.params)):d.isDefined(c=e.templateUrl)&&(d.isFunction(c)&&(c=c(e.params)),d.isDefined(c)&&(e.loadedTemplateUrl=r.valueOf(c),b=k(c)));d.isDefined(b)&&(a.$template=b);return f.all(a)}}).then(function(c){e==t.current&&(e&&(e.locals=c,d.copy(e.params,b)),a.$broadcast("$routeChangeSuccess",e,w))},function(b){e==t.current&&a.$broadcast("$routeChangeError",
-e,w,b)})}function n(){var a,b;d.forEach(g,function(f,g){var q;if(q=!b){var h=c.path();q=f.keys;var l={};if(f.regexp)if(h=f.regexp.exec(h)){for(var k=1,n=h.length;k<n;++k){var m=q[k-1],p=h[k];m&&p&&(l[m.name]=p)}q=l}else q=null;else q=null;q=a=q}q&&(b=s(f,{params:d.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||g[null]&&s(g[null],{params:{},pathParams:{}})}function u(a,b){var c=[];d.forEach((a||"").split(":"),function(a,d){if(0===d)c.push(a);else{var f=a.match(/(\w+)(?:[?*])?(.*)/),
-g=f[1];c.push(b[g]);c.push(f[2]||"");delete b[g]}});return c.join("")}var v=!1,p,x,t={routes:g,reload:function(){v=!0;var b={defaultPrevented:!1,preventDefault:function(){this.defaultPrevented=!0;v=!1}};a.$evalAsync(function(){l(b);b.defaultPrevented||m()})},updateParams:function(a){if(this.current&&this.current.$$route)a=d.extend({},this.current.params,a),c.path(u(this.current.$$route.originalPath,a)),c.search(a);else throw B("norout");}};a.$on("$locationChangeStart",l);a.$on("$locationChangeSuccess",
-m);return t}]});var B=d.$$minErr("ngRoute");r.provider("$routeParams",function(){this.$get=function(){return{}}});r.directive("ngView",x);r.directive("ngView",A);x.$inject=["$route","$anchorScroll","$animate"];A.$inject=["$compile","$controller","$route"]})(window,window.angular);
-//# sourceMappingURL=angular-route.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js.map
deleted file mode 100644
index fb5cffce..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-route.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-route.min.js",
-"lineCount":14,
-"mappings":"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",
-"sources":["angular-route.js"],
-"names":["window","angular","undefined","ngViewFactory","$route","$anchorScroll","$animate","restrict","terminal","priority","transclude","link","scope","$element","attr","ctrl","$transclude","cleanupLastView","previousLeaveAnimation","cancel","currentScope","$destroy","currentElement","leave","then","update","locals","current","isDefined","$template","newScope","$new","clone","enter","onNgViewEnter","autoScrollExp","$eval","$emit","onloadExp","autoscroll","onload","$on","ngViewFillContentFactory","$compile","$controller","html","contents","controller","$scope","controllerAs","data","children","resolveAs","ngRouteModule","module","provider","$RouteProvider","inherit","parent","extra","extend","Object","create","pathRegExp","path","opts","insensitive","caseInsensitiveMatch","ret","originalPath","regexp","keys","replace","_","slash","key","option","optional","star","push","name","RegExp","routes","when","this.when","route","routeCopy","copy","isUndefined","reloadOnSearch","redirectPath","length","substr","redirectTo","otherwise","this.otherwise","params","$get","$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce","prepareRoute","$locationEvent","lastRoute","preparedRouteIsUpdateOnly","preparedRoute","parseRoute","$$route","equals","pathParams","forceReload","$broadcast","defaultPrevented","preventDefault","commitRoute","nextRoute","isString","interpolate","search","url","resolve","template","templateUrl","forEach","value","get","invoke","isFunction","loadedTemplateUrl","valueOf","all","error","match","m","exec","on","i","len","val","string","result","split","segment","segmentMatch","join","reload","fakeLocationEvent","fakePreventDefault","$evalAsync","updateParams","newParams","$routeMinErr","$$minErr","$RouteParamsProvider","this.$get","directive","$inject"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.js
deleted file mode 100644
index 8b610c76..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.js
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-var $sanitizeMinErr = angular.$$minErr('$sanitize');
-
-/**
- * @ngdoc module
- * @name ngSanitize
- * @description
- *
- * # ngSanitize
- *
- * The `ngSanitize` module provides functionality to sanitize HTML.
- *
- *
- * <div doc-module-components="ngSanitize"></div>
- *
- * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
- */
-
-/**
- * @ngdoc service
- * @name $sanitize
- * @kind function
- *
- * @description
- * Sanitizes an html string by stripping all potentially dangerous tokens.
- *
- * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
- * then serialized back to properly escaped html string. This means that no unsafe input can make
- * it into the returned string.
- *
- * The whitelist for URL sanitization of attribute values is configured using the functions
- * `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider
- * `$compileProvider`}.
- *
- * The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
- *
- * @param {string} html HTML input.
- * @returns {string} Sanitized HTML.
- *
- * @example
- <example module="sanitizeExample" deps="angular-sanitize.js">
- <file name="index.html">
- <script>
- angular.module('sanitizeExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
- $scope.snippet =
- '<p style="color:blue">an html\n' +
- '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
- 'snippet</p>';
- $scope.deliberatelyTrustDangerousSnippet = function() {
- return $sce.trustAsHtml($scope.snippet);
- };
- }]);
- </script>
- <div ng-controller="ExampleController">
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
- <table>
- <tr>
- <td>Directive</td>
- <td>How</td>
- <td>Source</td>
- <td>Rendered</td>
- </tr>
- <tr id="bind-html-with-sanitize">
- <td>ng-bind-html</td>
- <td>Automatically uses $sanitize</td>
- <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
- <td><div ng-bind-html="snippet"></div></td>
- </tr>
- <tr id="bind-html-with-trust">
- <td>ng-bind-html</td>
- <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
- <td>
- <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
-&lt;/div&gt;</pre>
- </td>
- <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
- </tr>
- <tr id="bind-default">
- <td>ng-bind</td>
- <td>Automatically escapes</td>
- <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
- <td><div ng-bind="snippet"></div></td>
- </tr>
- </table>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should sanitize the html snippet by default', function() {
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
- toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
- });
-
- it('should inline raw snippet if bound to a trusted value', function() {
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
- toBe("<p style=\"color:blue\">an html\n" +
- "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
- "snippet</p>");
- });
-
- it('should escape snippet without any filter', function() {
- expect(element(by.css('#bind-default div')).getInnerHtml()).
- toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
- "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
- "snippet&lt;/p&gt;");
- });
-
- it('should update', function() {
- element(by.model('snippet')).clear();
- element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
- toBe('new <b>text</b>');
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
- 'new <b onclick="alert(1)">text</b>');
- expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
- "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
- });
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc provider
- * @name $sanitizeProvider
- *
- * @description
- * Creates and configures {@link $sanitize} instance.
- */
-function $SanitizeProvider() {
- var svgEnabled = false;
-
- this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
- if (svgEnabled) {
- angular.extend(validElements, svgElements);
- }
- return function(html) {
- var buf = [];
- htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
- return !/^unsafe:/.test($$sanitizeUri(uri, isImage));
- }));
- return buf.join('');
- };
- }];
-
-
- /**
- * @ngdoc method
- * @name $sanitizeProvider#enableSvg
- * @kind function
- *
- * @description
- * Enables a subset of svg to be supported by the sanitizer.
- *
- * <div class="alert alert-warning">
- * <p>By enabling this setting without taking other precautions, you might expose your
- * application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned
- * outside of the containing element and be rendered over other elements on the page (e.g. a login
- * link). Such behavior can then result in phishing incidents.</p>
- *
- * <p>To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg
- * tags within the sanitized content:</p>
- *
- * <br>
- *
- * <pre><code>
- * .rootOfTheIncludedContent svg {
- * overflow: hidden !important;
- * }
- * </code></pre>
- * </div>
- *
- * @param {boolean=} regexp New regexp to whitelist urls with.
- * @returns {boolean|ng.$sanitizeProvider} Returns the currently configured value if called
- * without an argument or self for chaining otherwise.
- */
- this.enableSvg = function(enableSvg) {
- if (angular.isDefined(enableSvg)) {
- svgEnabled = enableSvg;
- return this;
- } else {
- return svgEnabled;
- }
- };
-}
-
-function sanitizeText(chars) {
- var buf = [];
- var writer = htmlSanitizeWriter(buf, angular.noop);
- writer.chars(chars);
- return buf.join('');
-}
-
-
-// Regular Expressions for parsing tags and attributes
-var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- // Match everything outside of normal chars and " (quote character)
- NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
-
-
-// Good source of info about elements and attributes
-// http://dev.w3.org/html5/spec/Overview.html#semantics
-// http://simon.html5.org/html-elements
-
-// Safe Void Elements - HTML5
-// http://dev.w3.org/html5/spec/Overview.html#void-elements
-var voidElements = toMap("area,br,col,hr,img,wbr");
-
-// Elements that you can, intentionally, leave open (and which close themselves)
-// http://dev.w3.org/html5/spec/Overview.html#optional-tags
-var optionalEndTagBlockElements = toMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
- optionalEndTagInlineElements = toMap("rp,rt"),
- optionalEndTagElements = angular.extend({},
- optionalEndTagInlineElements,
- optionalEndTagBlockElements);
-
-// Safe Block Elements - HTML5
-var blockElements = angular.extend({}, optionalEndTagBlockElements, toMap("address,article," +
- "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
- "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul"));
-
-// Inline Elements - HTML5
-var inlineElements = angular.extend({}, optionalEndTagInlineElements, toMap("a,abbr,acronym,b," +
- "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
- "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
-
-// SVG Elements
-// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
-// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
-// They can potentially allow for arbitrary javascript to be executed. See #11290
-var svgElements = toMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
- "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
- "radialGradient,rect,stop,svg,switch,text,title,tspan");
-
-// Blocked Elements (will be stripped)
-var blockedElements = toMap("script,style");
-
-var validElements = angular.extend({},
- voidElements,
- blockElements,
- inlineElements,
- optionalEndTagElements);
-
-//Attributes that have href and hence need to be sanitized
-var uriAttrs = toMap("background,cite,href,longdesc,src,xlink:href");
-
-var htmlAttrs = toMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
- 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
- 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
- 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
- 'valign,value,vspace,width');
-
-// SVG attributes (without "id" and "name" attributes)
-// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
-var svgAttrs = toMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
- 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
- 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
- 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
- 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
- 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
- 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
- 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
- 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
- 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
- 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
- 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
- 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
- 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
- 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
-
-var validAttrs = angular.extend({},
- uriAttrs,
- svgAttrs,
- htmlAttrs);
-
-function toMap(str, lowercaseKeys) {
- var obj = {}, items = str.split(','), i;
- for (i = 0; i < items.length; i++) {
- obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true;
- }
- return obj;
-}
-
-var inertBodyElement;
-(function(window) {
- var doc;
- if (window.document && window.document.implementation) {
- doc = window.document.implementation.createHTMLDocument("inert");
- } else {
- throw $sanitizeMinErr('noinert', "Can't create an inert html document");
- }
- var docElement = doc.documentElement || doc.getDocumentElement();
- var bodyElements = docElement.getElementsByTagName('body');
-
- // usually there should be only one body element in the document, but IE doesn't have any, so we need to create one
- if (bodyElements.length === 1) {
- inertBodyElement = bodyElements[0];
- } else {
- var html = doc.createElement('html');
- inertBodyElement = doc.createElement('body');
- html.appendChild(inertBodyElement);
- doc.appendChild(html);
- }
-})(window);
-
-/**
- * @example
- * htmlParser(htmlString, {
- * start: function(tag, attrs) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * });
- *
- * @param {string} html string
- * @param {object} handler
- */
-function htmlParser(html, handler) {
- if (html === null || html === undefined) {
- html = '';
- } else if (typeof html !== 'string') {
- html = '' + html;
- }
- inertBodyElement.innerHTML = html;
-
- //mXSS protection
- var mXSSAttempts = 5;
- do {
- if (mXSSAttempts === 0) {
- throw $sanitizeMinErr('uinput', "Failed to sanitize html because the input is unstable");
- }
- mXSSAttempts--;
-
- // strip custom-namespaced attributes on IE<=11
- if (document.documentMode <= 11) {
- stripCustomNsAttrs(inertBodyElement);
- }
- html = inertBodyElement.innerHTML; //trigger mXSS
- inertBodyElement.innerHTML = html;
- } while (html !== inertBodyElement.innerHTML);
-
- var node = inertBodyElement.firstChild;
- while (node) {
- switch (node.nodeType) {
- case 1: // ELEMENT_NODE
- handler.start(node.nodeName.toLowerCase(), attrToMap(node.attributes));
- break;
- case 3: // TEXT NODE
- handler.chars(node.textContent);
- break;
- }
-
- var nextNode;
- if (!(nextNode = node.firstChild)) {
- if (node.nodeType == 1) {
- handler.end(node.nodeName.toLowerCase());
- }
- nextNode = node.nextSibling;
- if (!nextNode) {
- while (nextNode == null) {
- node = node.parentNode;
- if (node === inertBodyElement) break;
- nextNode = node.nextSibling;
- if (node.nodeType == 1) {
- handler.end(node.nodeName.toLowerCase());
- }
- }
- }
- }
- node = nextNode;
- }
-
- while (node = inertBodyElement.firstChild) {
- inertBodyElement.removeChild(node);
- }
-}
-
-function attrToMap(attrs) {
- var map = {};
- for (var i = 0, ii = attrs.length; i < ii; i++) {
- var attr = attrs[i];
- map[attr.name] = attr.value;
- }
- return map;
-}
-
-
-/**
- * Escapes all potentially dangerous characters, so that the
- * resulting string can be safely inserted into attribute or
- * element text.
- * @param value
- * @returns {string} escaped text
- */
-function encodeEntities(value) {
- return value.
- replace(/&/g, '&amp;').
- replace(SURROGATE_PAIR_REGEXP, function(value) {
- var hi = value.charCodeAt(0);
- var low = value.charCodeAt(1);
- return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
- }).
- replace(NON_ALPHANUMERIC_REGEXP, function(value) {
- return '&#' + value.charCodeAt(0) + ';';
- }).
- replace(/</g, '&lt;').
- replace(/>/g, '&gt;');
-}
-
-/**
- * create an HTML/XML writer which writes to buffer
- * @param {Array} buf use buf.join('') to get out sanitized html string
- * @returns {object} in the form of {
- * start: function(tag, attrs) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * }
- */
-function htmlSanitizeWriter(buf, uriValidator) {
- var ignoreCurrentElement = false;
- var out = angular.bind(buf, buf.push);
- return {
- start: function(tag, attrs) {
- tag = angular.lowercase(tag);
- if (!ignoreCurrentElement && blockedElements[tag]) {
- ignoreCurrentElement = tag;
- }
- if (!ignoreCurrentElement && validElements[tag] === true) {
- out('<');
- out(tag);
- angular.forEach(attrs, function(value, key) {
- var lkey=angular.lowercase(key);
- var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
- if (validAttrs[lkey] === true &&
- (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
- out(' ');
- out(key);
- out('="');
- out(encodeEntities(value));
- out('"');
- }
- });
- out('>');
- }
- },
- end: function(tag) {
- tag = angular.lowercase(tag);
- if (!ignoreCurrentElement && validElements[tag] === true && voidElements[tag] !== true) {
- out('</');
- out(tag);
- out('>');
- }
- if (tag == ignoreCurrentElement) {
- ignoreCurrentElement = false;
- }
- },
- chars: function(chars) {
- if (!ignoreCurrentElement) {
- out(encodeEntities(chars));
- }
- }
- };
-}
-
-
-/**
- * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' attribute to declare
- * ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). This is undesirable since we don't want
- * to allow any of these custom attributes. This method strips them all.
- *
- * @param node Root element to process
- */
-function stripCustomNsAttrs(node) {
- if (node.nodeType === Node.ELEMENT_NODE) {
- var attrs = node.attributes;
- for (var i = 0, l = attrs.length; i < l; i++) {
- var attrNode = attrs[i];
- var attrName = attrNode.name.toLowerCase();
- if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
- node.removeAttributeNode(attrNode);
- i--;
- l--;
- }
- }
- }
-
- var nextNode = node.firstChild;
- if (nextNode) {
- stripCustomNsAttrs(nextNode);
- }
-
- nextNode = node.nextSibling;
- if (nextNode) {
- stripCustomNsAttrs(nextNode);
- }
-}
-
-
-
-// define ngSanitize module and register $sanitize service
-angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
-
-/* global sanitizeText: false */
-
-/**
- * @ngdoc filter
- * @name linky
- * @kind function
- *
- * @description
- * Finds links in text input and turns them into html links. Supports `http/https/ftp/mailto` and
- * plain email address links.
- *
- * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
- *
- * @param {string} text Input text.
- * @param {string} target Window (`_blank|_self|_parent|_top`) or named frame to open links in.
- * @param {object|function(url)} [attributes] Add custom attributes to the link element.
- *
- * Can be one of:
- *
- * - `object`: A map of attributes
- * - `function`: Takes the url as a parameter and returns a map of attributes
- *
- * If the map of attributes contains a value for `target`, it overrides the value of
- * the target parameter.
- *
- *
- * @returns {string} Html-linkified and {@link $sanitize sanitized} text.
- *
- * @usage
- <span ng-bind-html="linky_expression | linky"></span>
- *
- * @example
- <example module="linkyExample" deps="angular-sanitize.js">
- <file name="index.html">
- <div ng-controller="ExampleController">
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
- <table>
- <tr>
- <th>Filter</th>
- <th>Source</th>
- <th>Rendered</th>
- </tr>
- <tr id="linky-filter">
- <td>linky filter</td>
- <td>
- <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
- </td>
- <td>
- <div ng-bind-html="snippet | linky"></div>
- </td>
- </tr>
- <tr id="linky-target">
- <td>linky target</td>
- <td>
- <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
- </td>
- <td>
- <div ng-bind-html="snippetWithSingleURL | linky:'_blank'"></div>
- </td>
- </tr>
- <tr id="linky-custom-attributes">
- <td>linky custom attributes</td>
- <td>
- <pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"&gt;<br>&lt;/div&gt;</pre>
- </td>
- <td>
- <div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"></div>
- </td>
- </tr>
- <tr id="escaped-html">
- <td>no filter</td>
- <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
- <td><div ng-bind="snippet"></div></td>
- </tr>
- </table>
- </file>
- <file name="script.js">
- angular.module('linkyExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.snippet =
- 'Pretty text with some links:\n'+
- 'http://angularjs.org/,\n'+
- 'mailto:us@somewhere.org,\n'+
- 'another@somewhere.org,\n'+
- 'and one more: ftp://127.0.0.1/.';
- $scope.snippetWithSingleURL = 'http://angularjs.org/';
- }]);
- </file>
- <file name="protractor.js" type="protractor">
- it('should linkify the snippet with urls', function() {
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
- toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
- });
-
- it('should not linkify snippet without the linky filter', function() {
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
- toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
- expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
- });
-
- it('should update', function() {
- element(by.model('snippet')).clear();
- element(by.model('snippet')).sendKeys('new http://link.');
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
- toBe('new http://link.');
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
- .toBe('new http://link.');
- });
-
- it('should work with the target property', function() {
- expect(element(by.id('linky-target')).
- element(by.binding("snippetWithSingleURL | linky:'_blank'")).getText()).
- toBe('http://angularjs.org/');
- expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
- });
-
- it('should optionally add custom attributes', function() {
- expect(element(by.id('linky-custom-attributes')).
- element(by.binding("snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}")).getText()).
- toBe('http://angularjs.org/');
- expect(element(by.css('#linky-custom-attributes a')).getAttribute('rel')).toEqual('nofollow');
- });
- </file>
- </example>
- */
-angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
- var LINKY_URL_REGEXP =
- /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
- MAILTO_REGEXP = /^mailto:/i;
-
- var linkyMinErr = angular.$$minErr('linky');
- var isString = angular.isString;
-
- return function(text, target, attributes) {
- if (text == null || text === '') return text;
- if (!isString(text)) throw linkyMinErr('notstring', 'Expected string but received: {0}', text);
-
- var match;
- var raw = text;
- var html = [];
- var url;
- var i;
- while ((match = raw.match(LINKY_URL_REGEXP))) {
- // We can not end in these as they are sometimes found at the end of the sentence
- url = match[0];
- // if we did not match ftp/http/www/mailto then assume mailto
- if (!match[2] && !match[4]) {
- url = (match[3] ? 'http://' : 'mailto:') + url;
- }
- i = match.index;
- addText(raw.substr(0, i));
- addLink(url, match[0].replace(MAILTO_REGEXP, ''));
- raw = raw.substring(i + match[0].length);
- }
- addText(raw);
- return $sanitize(html.join(''));
-
- function addText(text) {
- if (!text) {
- return;
- }
- html.push(sanitizeText(text));
- }
-
- function addLink(url, text) {
- var key;
- html.push('<a ');
- if (angular.isFunction(attributes)) {
- attributes = attributes(url);
- }
- if (angular.isObject(attributes)) {
- for (key in attributes) {
- html.push(key + '="' + attributes[key] + '" ');
- }
- } else {
- attributes = {};
- }
- if (angular.isDefined(target) && !('target' in attributes)) {
- html.push('target="',
- target,
- '" ');
- }
- html.push('href="',
- url.replace(/"/g, '&quot;'),
- '">');
- addText(text);
- html.push('</a>');
- }
- };
-}]);
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js
deleted file mode 100644
index 135d5a0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(A,e,B){'use strict';function C(a){var c=[];v(c,e.noop).chars(a);return c.join("")}function h(a,c){var b={},d=a.split(","),l;for(l=0;l<d.length;l++)b[c?e.lowercase(d[l]):d[l]]=!0;return b}function D(a,c){null===a||a===B?a="":"string"!==typeof a&&(a=""+a);g.innerHTML=a;var b=5;do{if(0===b)throw w("uinput");b--;11>=document.documentMode&&n(g);a=g.innerHTML;g.innerHTML=a}while(a!==g.innerHTML);for(b=g.firstChild;b;){switch(b.nodeType){case 1:c.start(b.nodeName.toLowerCase(),E(b.attributes));
-break;case 3:c.chars(b.textContent)}var d;if(!(d=b.firstChild)&&(1==b.nodeType&&c.end(b.nodeName.toLowerCase()),d=b.nextSibling,!d))for(;null==d;){b=b.parentNode;if(b===g)break;d=b.nextSibling;1==b.nodeType&&c.end(b.nodeName.toLowerCase())}b=d}for(;b=g.firstChild;)g.removeChild(b)}function E(a){for(var c={},b=0,d=a.length;b<d;b++){var l=a[b];c[l.name]=l.value}return c}function x(a){return a.replace(/&/g,"&amp;").replace(F,function(a){var b=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(b-55296)+
-(a-56320)+65536)+";"}).replace(G,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function v(a,c){var b=!1,d=e.bind(a,a.push);return{start:function(a,f){a=e.lowercase(a);!b&&H[a]&&(b=a);b||!0!==t[a]||(d("<"),d(a),e.forEach(f,function(b,f){var g=e.lowercase(f),h="img"===a&&"src"===g||"background"===g;!0!==I[g]||!0===y[g]&&!c(b,h)||(d(" "),d(f),d('="'),d(x(b)),d('"'))}),d(">"))},end:function(a){a=e.lowercase(a);b||!0!==t[a]||!0===z[a]||(d("</"),d(a),d(">"));a==
-b&&(b=!1)},chars:function(a){b||d(x(a))}}}function n(a){if(a.nodeType===Node.ELEMENT_NODE)for(var c=a.attributes,b=0,d=c.length;b<d;b++){var e=c[b],f=e.name.toLowerCase();if("xmlns:ns1"===f||0===f.indexOf("ns1:"))a.removeAttributeNode(e),b--,d--}(c=a.firstChild)&&n(c);(c=a.nextSibling)&&n(c)}var w=e.$$minErr("$sanitize"),F=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,G=/([^\#-~ |!])/g,z=h("area,br,col,hr,img,wbr"),q=h("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),k=h("rp,rt"),u=e.extend({},k,q),q=e.extend({},
-q,h("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul")),k=e.extend({},k,h("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),J=h("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan"),
-H=h("script,style"),t=e.extend({},z,q,k,u),y=h("background,cite,href,longdesc,src,xlink:href"),u=h("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"),k=h("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan",
-!0),I=e.extend({},y,k,u),g;(function(a){if(a.document&&a.document.implementation)a=a.document.implementation.createHTMLDocument("inert");else throw w("noinert");var c=(a.documentElement||a.getDocumentElement()).getElementsByTagName("body");1===c.length?g=c[0]:(c=a.createElement("html"),g=a.createElement("body"),c.appendChild(g),a.appendChild(c))})(A);e.module("ngSanitize",[]).provider("$sanitize",function(){var a=!1;this.$get=["$$sanitizeUri",function(c){a&&e.extend(t,J);return function(a){var d=
-[];D(a,v(d,function(a,b){return!/^unsafe:/.test(c(a,b))}));return d.join("")}}];this.enableSvg=function(c){return e.isDefined(c)?(a=c,this):a}});e.module("ngSanitize").filter("linky",["$sanitize",function(a){var c=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,b=/^mailto:/i,d=e.$$minErr("linky"),g=e.isString;return function(f,h,m){function k(a){a&&p.push(C(a))}function q(a,b){var c;p.push("<a ");e.isFunction(m)&&(m=m(a));if(e.isObject(m))for(c in m)p.push(c+
-'="'+m[c]+'" ');else m={};!e.isDefined(h)||"target"in m||p.push('target="',h,'" ');p.push('href="',a.replace(/"/g,"&quot;"),'">');k(b);p.push("</a>")}if(null==f||""===f)return f;if(!g(f))throw d("notstring",f);for(var r=f,p=[],s,n;f=r.match(c);)s=f[0],f[2]||f[4]||(s=(f[3]?"http://":"mailto:")+s),n=f.index,k(r.substr(0,n)),q(s,f[0].replace(b,"")),r=r.substring(n+f[0].length);k(r);return a(p.join(""))}}])})(window,window.angular);
-//# sourceMappingURL=angular-sanitize.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js.map
deleted file mode 100644
index 7276abd2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-sanitize.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-sanitize.min.js",
-"lineCount":14,
-"mappings":"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",
-"sources":["angular-sanitize.js"],
-"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","toMap","str","lowercaseKeys","obj","items","split","i","length","lowercase","htmlParser","html","handler","inertBodyElement","innerHTML","mXSSAttempts","$sanitizeMinErr","document","documentMode","stripCustomNsAttrs","node","firstChild","nodeType","start","nodeName","toLowerCase","attrToMap","attributes","textContent","nextNode","end","nextSibling","parentNode","removeChild","attrs","map","ii","attr","name","value","encodeEntities","replace","SURROGATE_PAIR_REGEXP","hi","charCodeAt","low","NON_ALPHANUMERIC_REGEXP","uriValidator","ignoreCurrentElement","out","bind","push","tag","blockedElements","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","voidElements","Node","ELEMENT_NODE","l","attrNode","attrName","indexOf","removeAttributeNode","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","optionalEndTagElements","extend","blockElements","inlineElements","svgElements","htmlAttrs","svgAttrs","implementation","doc","createHTMLDocument","bodyElements","getElementsByTagName","documentElement","getDocumentElement","createElement","appendChild","module","provider","$SanitizeProvider","svgEnabled","$get","$$sanitizeUri","uri","test","enableSvg","this.enableSvg","isDefined","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","linkyMinErr","isString","text","target","addText","addLink","url","isFunction","isObject","raw","match","index","substr","substring"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.js
deleted file mode 100644
index fc1cf7da..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.js
+++ /dev/null
@@ -1,729 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/* global ngTouchClickDirectiveFactory: false,
- */
-
-/**
- * @ngdoc module
- * @name ngTouch
- * @description
- *
- * # ngTouch
- *
- * The `ngTouch` module provides touch events and other helpers for touch-enabled devices.
- * The implementation is based on jQuery Mobile touch event handling
- * ([jquerymobile.com](http://jquerymobile.com/)).
- *
- *
- * See {@link ngTouch.$swipe `$swipe`} for usage.
- *
- * <div doc-module-components="ngTouch"></div>
- *
- */
-
-// define ngTouch module
-/* global -ngTouch */
-var ngTouch = angular.module('ngTouch', []);
-
-ngTouch.provider('$touch', $TouchProvider);
-
-function nodeName_(element) {
- return angular.lowercase(element.nodeName || (element[0] && element[0].nodeName));
-}
-
-/**
- * @ngdoc provider
- * @name $touchProvider
- *
- * @description
- * The `$touchProvider` allows enabling / disabling {@link ngTouch.ngClick ngTouch's ngClick directive}.
- */
-$TouchProvider.$inject = ['$provide', '$compileProvider'];
-function $TouchProvider($provide, $compileProvider) {
-
- /**
- * @ngdoc method
- * @name $touchProvider#ngClickOverrideEnabled
- *
- * @param {boolean=} enabled update the ngClickOverrideEnabled state if provided, otherwise just return the
- * current ngClickOverrideEnabled state
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- *
- * @kind function
- *
- * @description
- * Call this method to enable/disable {@link ngTouch.ngClick ngTouch's ngClick directive}. If enabled,
- * the default ngClick directive will be replaced by a version that eliminates the 300ms delay for
- * click events on browser for touch-devices.
- *
- * The default is `false`.
- *
- */
- var ngClickOverrideEnabled = false;
- var ngClickDirectiveAdded = false;
- this.ngClickOverrideEnabled = function(enabled) {
- if (angular.isDefined(enabled)) {
-
- if (enabled && !ngClickDirectiveAdded) {
- ngClickDirectiveAdded = true;
-
- // Use this to identify the correct directive in the delegate
- ngTouchClickDirectiveFactory.$$moduleName = 'ngTouch';
- $compileProvider.directive('ngClick', ngTouchClickDirectiveFactory);
-
- $provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
- if (ngClickOverrideEnabled) {
- // drop the default ngClick directive
- $delegate.shift();
- } else {
- // drop the ngTouch ngClick directive if the override has been re-disabled (because
- // we cannot de-register added directives)
- var i = $delegate.length - 1;
- while (i >= 0) {
- if ($delegate[i].$$moduleName === 'ngTouch') {
- $delegate.splice(i, 1);
- break;
- }
- i--;
- }
- }
-
- return $delegate;
- }]);
- }
-
- ngClickOverrideEnabled = enabled;
- return this;
- }
-
- return ngClickOverrideEnabled;
- };
-
- /**
- * @ngdoc service
- * @name $touch
- * @kind object
- *
- * @description
- * Provides the {@link ngTouch.$touch#ngClickOverrideEnabled `ngClickOverrideEnabled`} method.
- *
- */
- this.$get = function() {
- return {
- /**
- * @ngdoc method
- * @name $touch#ngClickOverrideEnabled
- *
- * @returns {*} current value of `ngClickOverrideEnabled` set in the {@link ngTouch.$touchProvider $touchProvider},
- * i.e. if {@link ngTouch.ngClick ngTouch's ngClick} directive is enabled.
- *
- * @kind function
- */
- ngClickOverrideEnabled: function() {
- return ngClickOverrideEnabled;
- }
- };
- };
-
-}
-
-/* global ngTouch: false */
-
- /**
- * @ngdoc service
- * @name $swipe
- *
- * @description
- * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe
- * behavior, to make implementing swipe-related directives more convenient.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`.
- *
- * # Usage
- * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
- * which is to be watched for swipes, and an object with four handler functions. See the
- * documentation for `bind` below.
- */
-
-ngTouch.factory('$swipe', [function() {
- // The total distance in any direction before we make the call on swipe vs. scroll.
- var MOVE_BUFFER_RADIUS = 10;
-
- var POINTER_EVENTS = {
- 'mouse': {
- start: 'mousedown',
- move: 'mousemove',
- end: 'mouseup'
- },
- 'touch': {
- start: 'touchstart',
- move: 'touchmove',
- end: 'touchend',
- cancel: 'touchcancel'
- }
- };
-
- function getCoordinates(event) {
- var originalEvent = event.originalEvent || event;
- var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
- var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];
-
- return {
- x: e.clientX,
- y: e.clientY
- };
- }
-
- function getEvents(pointerTypes, eventType) {
- var res = [];
- angular.forEach(pointerTypes, function(pointerType) {
- var eventName = POINTER_EVENTS[pointerType][eventType];
- if (eventName) {
- res.push(eventName);
- }
- });
- return res.join(' ');
- }
-
- return {
- /**
- * @ngdoc method
- * @name $swipe#bind
- *
- * @description
- * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
- * object containing event handlers.
- * The pointer types that should be used can be specified via the optional
- * third argument, which is an array of strings `'mouse'` and `'touch'`. By default,
- * `$swipe` will listen for `mouse` and `touch` events.
- *
- * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
- * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
- * `event`. `cancel` receives the raw `event` as its single parameter.
- *
- * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
- * watching for `touchmove` or `mousemove` events. These events are ignored until the total
- * distance moved in either dimension exceeds a small threshold.
- *
- * Once this threshold is exceeded, either the horizontal or vertical delta is greater.
- * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.
- * - If the vertical distance is greater, this is a scroll, and we let the browser take over.
- * A `cancel` event is sent.
- *
- * `move` is called on `mousemove` and `touchmove` after the above logic has determined that
- * a swipe is in progress.
- *
- * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.
- *
- * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling
- * as described above.
- *
- */
- bind: function(element, eventHandlers, pointerTypes) {
- // Absolute total movement, used to control swipe vs. scroll.
- var totalX, totalY;
- // Coordinates of the start position.
- var startCoords;
- // Last event's position.
- var lastPos;
- // Whether a swipe is active.
- var active = false;
-
- pointerTypes = pointerTypes || ['mouse', 'touch'];
- element.on(getEvents(pointerTypes, 'start'), function(event) {
- startCoords = getCoordinates(event);
- active = true;
- totalX = 0;
- totalY = 0;
- lastPos = startCoords;
- eventHandlers['start'] && eventHandlers['start'](startCoords, event);
- });
- var events = getEvents(pointerTypes, 'cancel');
- if (events) {
- element.on(events, function(event) {
- active = false;
- eventHandlers['cancel'] && eventHandlers['cancel'](event);
- });
- }
-
- element.on(getEvents(pointerTypes, 'move'), function(event) {
- if (!active) return;
-
- // Android will send a touchcancel if it thinks we're starting to scroll.
- // So when the total distance (+ or - or both) exceeds 10px in either direction,
- // we either:
- // - On totalX > totalY, we send preventDefault() and treat this as a swipe.
- // - On totalY > totalX, we let the browser handle it as a scroll.
-
- if (!startCoords) return;
- var coords = getCoordinates(event);
-
- totalX += Math.abs(coords.x - lastPos.x);
- totalY += Math.abs(coords.y - lastPos.y);
-
- lastPos = coords;
-
- if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
- return;
- }
-
- // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.
- if (totalY > totalX) {
- // Allow native scrolling to take over.
- active = false;
- eventHandlers['cancel'] && eventHandlers['cancel'](event);
- return;
- } else {
- // Prevent the browser from scrolling.
- event.preventDefault();
- eventHandlers['move'] && eventHandlers['move'](coords, event);
- }
- });
-
- element.on(getEvents(pointerTypes, 'end'), function(event) {
- if (!active) return;
- active = false;
- eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
- });
- }
- };
-}]);
-
-/* global ngTouch: false,
- nodeName_: false
-*/
-
-/**
- * @ngdoc directive
- * @name ngClick
- * @deprecated
- *
- * @description
- * <div class="alert alert-danger">
- * **DEPRECATION NOTICE**: Beginning with Angular 1.5, this directive is deprecated and by default **disabled**.
- * The directive will receive no further support and might be removed from future releases.
- * If you need the directive, you can enable it with the {@link ngTouch.$touchProvider $touchProvider#ngClickOverrideEnabled}
- * function. We also recommend that you migrate to [FastClick](https://github.com/ftlabs/fastclick).
- * To learn more about the 300ms delay, this [Telerik article](http://developer.telerik.com/featured/300-ms-click-delay-ios-8/)
- * gives a good overview.
- * </div>
- * A more powerful replacement for the default ngClick designed to be used on touchscreen
- * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
- * the click event. This version handles them immediately, and then prevents the
- * following click event from propagating.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * This directive can fall back to using an ordinary click event, and so works on desktop
- * browsers as well as mobile.
- *
- * This directive also sets the CSS class `ng-click-active` while the element is being held
- * down (by a mouse click or touch) so you can restyle the depressed element if you wish.
- *
- * @element ANY
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate
- * upon tap. (Event object is available as `$event`)
- *
- * @example
- <example module="ngClickExample" deps="angular-touch.js">
- <file name="index.html">
- <button ng-click="count = count + 1" ng-init="count=0">
- Increment
- </button>
- count: {{ count }}
- </file>
- <file name="script.js">
- angular.module('ngClickExample', ['ngTouch']);
- </file>
- </example>
- */
-
-var ngTouchClickDirectiveFactory = ['$parse', '$timeout', '$rootElement',
- function($parse, $timeout, $rootElement) {
- var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
- var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
- var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
- var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
-
- var ACTIVE_CLASS_NAME = 'ng-click-active';
- var lastPreventedTime;
- var touchCoordinates;
- var lastLabelClickCoordinates;
-
-
- // TAP EVENTS AND GHOST CLICKS
- //
- // Why tap events?
- // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
- // double-tapping, and then fire a click event.
- //
- // This delay sucks and makes mobile apps feel unresponsive.
- // So we detect touchstart, touchcancel and touchend ourselves and determine when
- // the user has tapped on something.
- //
- // What happens when the browser then generates a click event?
- // The browser, of course, also detects the tap and fires a click after a delay. This results in
- // tapping/clicking twice. We do "clickbusting" to prevent it.
- //
- // How does it work?
- // We attach global touchstart and click handlers, that run during the capture (early) phase.
- // So the sequence for a tap is:
- // - global touchstart: Sets an "allowable region" at the point touched.
- // - element's touchstart: Starts a touch
- // (- touchcancel ends the touch, no click follows)
- // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
- // too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
- // - preventGhostClick() removes the allowable region the global touchstart created.
- // - The browser generates a click event.
- // - The global click handler catches the click, and checks whether it was in an allowable region.
- // - If preventGhostClick was called, the region will have been removed, the click is busted.
- // - If the region is still there, the click proceeds normally. Therefore clicks on links and
- // other elements without ngTap on them work normally.
- //
- // This is an ugly, terrible hack!
- // Yeah, tell me about it. The alternatives are using the slow click events, or making our users
- // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
- // encapsulates this ugly logic away from the user.
- //
- // Why not just put click handlers on the element?
- // We do that too, just to be sure. If the tap event caused the DOM to change,
- // it is possible another element is now in that position. To take account for these possibly
- // distinct elements, the handlers are global and care only about coordinates.
-
- // Checks if the coordinates are close enough to be within the region.
- function hit(x1, y1, x2, y2) {
- return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
- }
-
- // Checks a list of allowable regions against a click location.
- // Returns true if the click should be allowed.
- // Splices out the allowable region from the list after it has been used.
- function checkAllowableRegions(touchCoordinates, x, y) {
- for (var i = 0; i < touchCoordinates.length; i += 2) {
- if (hit(touchCoordinates[i], touchCoordinates[i + 1], x, y)) {
- touchCoordinates.splice(i, i + 2);
- return true; // allowable region
- }
- }
- return false; // No allowable region; bust it.
- }
-
- // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
- // was called recently.
- function onClick(event) {
- if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
- return; // Too old.
- }
-
- var touches = event.touches && event.touches.length ? event.touches : [event];
- var x = touches[0].clientX;
- var y = touches[0].clientY;
- // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
- // and on the input element). Depending on the exact browser, this second click we don't want
- // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label
- // click event
- if (x < 1 && y < 1) {
- return; // offscreen
- }
- if (lastLabelClickCoordinates &&
- lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) {
- return; // input click triggered by label click
- }
- // reset label click coordinates on first subsequent click
- if (lastLabelClickCoordinates) {
- lastLabelClickCoordinates = null;
- }
- // remember label click coordinates to prevent click busting of trigger click event on input
- if (nodeName_(event.target) === 'label') {
- lastLabelClickCoordinates = [x, y];
- }
-
- // Look for an allowable region containing this click.
- // If we find one, that means it was created by touchstart and not removed by
- // preventGhostClick, so we don't bust it.
- if (checkAllowableRegions(touchCoordinates, x, y)) {
- return;
- }
-
- // If we didn't find an allowable region, bust the click.
- event.stopPropagation();
- event.preventDefault();
-
- // Blur focused form elements
- event.target && event.target.blur && event.target.blur();
- }
-
-
- // Global touchstart handler that creates an allowable region for a click event.
- // This allowable region can be removed by preventGhostClick if we want to bust it.
- function onTouchStart(event) {
- var touches = event.touches && event.touches.length ? event.touches : [event];
- var x = touches[0].clientX;
- var y = touches[0].clientY;
- touchCoordinates.push(x, y);
-
- $timeout(function() {
- // Remove the allowable region.
- for (var i = 0; i < touchCoordinates.length; i += 2) {
- if (touchCoordinates[i] == x && touchCoordinates[i + 1] == y) {
- touchCoordinates.splice(i, i + 2);
- return;
- }
- }
- }, PREVENT_DURATION, false);
- }
-
- // On the first call, attaches some event handlers. Then whenever it gets called, it creates a
- // zone around the touchstart where clicks will get busted.
- function preventGhostClick(x, y) {
- if (!touchCoordinates) {
- $rootElement[0].addEventListener('click', onClick, true);
- $rootElement[0].addEventListener('touchstart', onTouchStart, true);
- touchCoordinates = [];
- }
-
- lastPreventedTime = Date.now();
-
- checkAllowableRegions(touchCoordinates, x, y);
- }
-
- // Actual linking function.
- return function(scope, element, attr) {
- var clickHandler = $parse(attr.ngClick),
- tapping = false,
- tapElement, // Used to blur the element after a tap.
- startTime, // Used to check if the tap was held too long.
- touchStartX,
- touchStartY;
-
- function resetState() {
- tapping = false;
- element.removeClass(ACTIVE_CLASS_NAME);
- }
-
- element.on('touchstart', function(event) {
- tapping = true;
- tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
- // Hack for Safari, which can target text nodes instead of containers.
- if (tapElement.nodeType == 3) {
- tapElement = tapElement.parentNode;
- }
-
- element.addClass(ACTIVE_CLASS_NAME);
-
- startTime = Date.now();
-
- // Use jQuery originalEvent
- var originalEvent = event.originalEvent || event;
- var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
- var e = touches[0];
- touchStartX = e.clientX;
- touchStartY = e.clientY;
- });
-
- element.on('touchcancel', function(event) {
- resetState();
- });
-
- element.on('touchend', function(event) {
- var diff = Date.now() - startTime;
-
- // Use jQuery originalEvent
- var originalEvent = event.originalEvent || event;
- var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
- originalEvent.changedTouches :
- ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
- var e = touches[0];
- var x = e.clientX;
- var y = e.clientY;
- var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));
-
- if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
- // Call preventGhostClick so the clickbuster will catch the corresponding click.
- preventGhostClick(x, y);
-
- // Blur the focused element (the button, probably) before firing the callback.
- // This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
- // I couldn't get anything to work reliably on Android Chrome.
- if (tapElement) {
- tapElement.blur();
- }
-
- if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
- element.triggerHandler('click', [event]);
- }
- }
-
- resetState();
- });
-
- // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
- // something else nearby.
- element.onclick = function(event) { };
-
- // Actual click handler.
- // There are three different kinds of clicks, only two of which reach this point.
- // - On desktop browsers without touch events, their clicks will always come here.
- // - On mobile browsers, the simulated "fast" click will call this.
- // - But the browser's follow-up slow click will be "busted" before it reaches this handler.
- // Therefore it's safe to use this directive on both mobile and desktop.
- element.on('click', function(event, touchend) {
- scope.$apply(function() {
- clickHandler(scope, {$event: (touchend || event)});
- });
- });
-
- element.on('mousedown', function(event) {
- element.addClass(ACTIVE_CLASS_NAME);
- });
-
- element.on('mousemove mouseup', function(event) {
- element.removeClass(ACTIVE_CLASS_NAME);
- });
-
- };
-}];
-
-/* global ngTouch: false */
-
-/**
- * @ngdoc directive
- * @name ngSwipeLeft
- *
- * @description
- * Specify custom behavior when an element is swiped to the left on a touchscreen device.
- * A leftward swipe is a quick, right-to-left slide of the finger.
- * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag
- * too.
- *
- * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to
- * the `ng-swipe-left` or `ng-swipe-right` DOM Element.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * @element ANY
- * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate
- * upon left swipe. (Event object is available as `$event`)
- *
- * @example
- <example module="ngSwipeLeftExample" deps="angular-touch.js">
- <file name="index.html">
- <div ng-show="!showActions" ng-swipe-left="showActions = true">
- Some list content, like an email in the inbox
- </div>
- <div ng-show="showActions" ng-swipe-right="showActions = false">
- <button ng-click="reply()">Reply</button>
- <button ng-click="delete()">Delete</button>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngSwipeLeftExample', ['ngTouch']);
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngSwipeRight
- *
- * @description
- * Specify custom behavior when an element is swiped to the right on a touchscreen device.
- * A rightward swipe is a quick, left-to-right slide of the finger.
- * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag
- * too.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * @element ANY
- * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate
- * upon right swipe. (Event object is available as `$event`)
- *
- * @example
- <example module="ngSwipeRightExample" deps="angular-touch.js">
- <file name="index.html">
- <div ng-show="!showActions" ng-swipe-left="showActions = true">
- Some list content, like an email in the inbox
- </div>
- <div ng-show="showActions" ng-swipe-right="showActions = false">
- <button ng-click="reply()">Reply</button>
- <button ng-click="delete()">Delete</button>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngSwipeRightExample', ['ngTouch']);
- </file>
- </example>
- */
-
-function makeSwipeDirective(directiveName, direction, eventName) {
- ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {
- // The maximum vertical delta for a swipe should be less than 75px.
- var MAX_VERTICAL_DISTANCE = 75;
- // Vertical distance should not be more than a fraction of the horizontal distance.
- var MAX_VERTICAL_RATIO = 0.3;
- // At least a 30px lateral motion is necessary for a swipe.
- var MIN_HORIZONTAL_DISTANCE = 30;
-
- return function(scope, element, attr) {
- var swipeHandler = $parse(attr[directiveName]);
-
- var startCoords, valid;
-
- function validSwipe(coords) {
- // Check that it's within the coordinates.
- // Absolute vertical distance must be within tolerances.
- // Horizontal distance, we take the current X - the starting X.
- // This is negative for leftward swipes and positive for rightward swipes.
- // After multiplying by the direction (-1 for left, +1 for right), legal swipes
- // (ie. same direction as the directive wants) will have a positive delta and
- // illegal ones a negative delta.
- // Therefore this delta must be positive, and larger than the minimum.
- if (!startCoords) return false;
- var deltaY = Math.abs(coords.y - startCoords.y);
- var deltaX = (coords.x - startCoords.x) * direction;
- return valid && // Short circuit for already-invalidated swipes.
- deltaY < MAX_VERTICAL_DISTANCE &&
- deltaX > 0 &&
- deltaX > MIN_HORIZONTAL_DISTANCE &&
- deltaY / deltaX < MAX_VERTICAL_RATIO;
- }
-
- var pointerTypes = ['touch'];
- if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
- pointerTypes.push('mouse');
- }
- $swipe.bind(element, {
- 'start': function(coords, event) {
- startCoords = coords;
- valid = true;
- },
- 'cancel': function(event) {
- valid = false;
- },
- 'end': function(coords, event) {
- if (validSwipe(coords)) {
- scope.$apply(function() {
- element.triggerHandler(eventName);
- swipeHandler(scope, {$event: event});
- });
- }
- }
- }, pointerTypes);
- };
- }]);
-}
-
-// Left is negative X-coordinate, right is positive.
-makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');
-makeSwipeDirective('ngSwipeRight', 1, 'swiperight');
-
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js
deleted file mode 100644
index d17a0328..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(x,n,y){'use strict';function s(f,k){var e=!1,a=!1;this.ngClickOverrideEnabled=function(b){return n.isDefined(b)?(b&&!a&&(a=!0,t.$$moduleName="ngTouch",k.directive("ngClick",t),f.decorator("ngClickDirective",["$delegate",function(a){if(e)a.shift();else for(var b=a.length-1;0<=b;){if("ngTouch"===a[b].$$moduleName){a.splice(b,1);break}b--}return a}])),e=b,this):e};this.$get=function(){return{ngClickOverrideEnabled:function(){return e}}}}function v(f,k,e){p.directive(f,["$parse","$swipe",function(a,
-b){return function(l,u,g){function h(c){if(!d)return!1;var a=Math.abs(c.y-d.y);c=(c.x-d.x)*k;return r&&75>a&&0<c&&30<c&&.3>a/c}var m=a(g[f]),d,r,c=["touch"];n.isDefined(g.ngSwipeDisableMouse)||c.push("mouse");b.bind(u,{start:function(c,a){d=c;r=!0},cancel:function(c){r=!1},end:function(c,d){h(c)&&l.$apply(function(){u.triggerHandler(e);m(l,{$event:d})})}},c)}}])}var p=n.module("ngTouch",[]);p.provider("$touch",s);s.$inject=["$provide","$compileProvider"];p.factory("$swipe",[function(){function f(a){a=
-a.originalEvent||a;var b=a.touches&&a.touches.length?a.touches:[a];a=a.changedTouches&&a.changedTouches[0]||b[0];return{x:a.clientX,y:a.clientY}}function k(a,b){var l=[];n.forEach(a,function(a){(a=e[a][b])&&l.push(a)});return l.join(" ")}var e={mouse:{start:"mousedown",move:"mousemove",end:"mouseup"},touch:{start:"touchstart",move:"touchmove",end:"touchend",cancel:"touchcancel"}};return{bind:function(a,b,l){var e,g,h,m,d=!1;l=l||["mouse","touch"];a.on(k(l,"start"),function(c){h=f(c);d=!0;g=e=0;m=
-h;b.start&&b.start(h,c)});var r=k(l,"cancel");if(r)a.on(r,function(c){d=!1;b.cancel&&b.cancel(c)});a.on(k(l,"move"),function(c){if(d&&h){var a=f(c);e+=Math.abs(a.x-m.x);g+=Math.abs(a.y-m.y);m=a;10>e&&10>g||(g>e?(d=!1,b.cancel&&b.cancel(c)):(c.preventDefault(),b.move&&b.move(a,c)))}});a.on(k(l,"end"),function(c){d&&(d=!1,b.end&&b.end(f(c),c))})}}}]);var t=["$parse","$timeout","$rootElement",function(f,k,e){function a(a,d,b){for(var c=0;c<a.length;c+=2){var g=a[c+1],e=b;if(25>Math.abs(a[c]-d)&&25>Math.abs(g-
-e))return a.splice(c,c+2),!0}return!1}function b(b){if(!(2500<Date.now()-u)){var d=b.touches&&b.touches.length?b.touches:[b],e=d[0].clientX,d=d[0].clientY;if(!(1>e&&1>d||h&&h[0]===e&&h[1]===d)){h&&(h=null);var c=b.target;"label"===n.lowercase(c.nodeName||c[0]&&c[0].nodeName)&&(h=[e,d]);a(g,e,d)||(b.stopPropagation(),b.preventDefault(),b.target&&b.target.blur&&b.target.blur())}}}function l(a){a=a.touches&&a.touches.length?a.touches:[a];var b=a[0].clientX,e=a[0].clientY;g.push(b,e);k(function(){for(var a=
-0;a<g.length;a+=2)if(g[a]==b&&g[a+1]==e){g.splice(a,a+2);break}},2500,!1)}var u,g,h;return function(h,d,k){var c=f(k.ngClick),w=!1,q,p,s,t;d.on("touchstart",function(a){w=!0;q=a.target?a.target:a.srcElement;3==q.nodeType&&(q=q.parentNode);d.addClass("ng-click-active");p=Date.now();a=a.originalEvent||a;a=(a.touches&&a.touches.length?a.touches:[a])[0];s=a.clientX;t=a.clientY});d.on("touchcancel",function(a){w=!1;d.removeClass("ng-click-active")});d.on("touchend",function(c){var h=Date.now()-p,f=c.originalEvent||
-c,m=(f.changedTouches&&f.changedTouches.length?f.changedTouches:f.touches&&f.touches.length?f.touches:[f])[0],f=m.clientX,m=m.clientY,v=Math.sqrt(Math.pow(f-s,2)+Math.pow(m-t,2));w&&750>h&&12>v&&(g||(e[0].addEventListener("click",b,!0),e[0].addEventListener("touchstart",l,!0),g=[]),u=Date.now(),a(g,f,m),q&&q.blur(),n.isDefined(k.disabled)&&!1!==k.disabled||d.triggerHandler("click",[c]));w=!1;d.removeClass("ng-click-active")});d.onclick=function(a){};d.on("click",function(a,b){h.$apply(function(){c(h,
-{$event:b||a})})});d.on("mousedown",function(a){d.addClass("ng-click-active")});d.on("mousemove mouseup",function(a){d.removeClass("ng-click-active")})}}];v("ngSwipeLeft",-1,"swipeleft");v("ngSwipeRight",1,"swiperight")})(window,window.angular);
-//# sourceMappingURL=angular-touch.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js.map
deleted file mode 100644
index 9267ec82..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular-touch.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular-touch.min.js",
-"lineCount":13,
-"mappings":"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",
-"sources":["angular-touch.js"],
-"names":["window","angular","undefined","$TouchProvider","$provide","$compileProvider","ngClickOverrideEnabled","ngClickDirectiveAdded","this.ngClickOverrideEnabled","enabled","isDefined","ngTouchClickDirectiveFactory","$$moduleName","directive","decorator","$delegate","shift","i","length","splice","$get","this.$get","makeSwipeDirective","directiveName","direction","eventName","ngTouch","$parse","$swipe","scope","element","attr","validSwipe","coords","startCoords","deltaY","Math","abs","y","deltaX","x","valid","MAX_VERTICAL_DISTANCE","MIN_HORIZONTAL_DISTANCE","MAX_VERTICAL_RATIO","swipeHandler","pointerTypes","push","bind","start","event","cancel","end","$apply","triggerHandler","$event","module","provider","$inject","factory","getCoordinates","originalEvent","touches","e","changedTouches","clientX","clientY","getEvents","eventType","res","forEach","pointerType","POINTER_EVENTS","join","move","eventHandlers","totalX","totalY","lastPos","active","on","events","MOVE_BUFFER_RADIUS","preventDefault","$timeout","$rootElement","checkAllowableRegions","touchCoordinates","CLICKBUSTER_THRESHOLD","x1","y1","y2","onClick","PREVENT_DURATION","Date","now","lastPreventedTime","lastLabelClickCoordinates","target","lowercase","nodeName","stopPropagation","blur","onTouchStart","clickHandler","ngClick","tapping","tapElement","startTime","touchStartX","touchStartY","srcElement","nodeType","parentNode","addClass","ACTIVE_CLASS_NAME","removeClass","diff","dist","sqrt","pow","TAP_DURATION","MOVE_TOLERANCE","addEventListener","disabled","onclick","element.onclick","touchend"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.js
deleted file mode 100644
index a8aad46a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.js
+++ /dev/null
@@ -1,30428 +0,0 @@
-/**
- * @license AngularJS v1.5.0
- * (c) 2010-2016 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, document, undefined) {'use strict';
-
-/**
- * @description
- *
- * This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
- *
- * var exampleMinErr = minErr('example');
- * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
- *
- * The above creates an instance of minErr in the example namespace. The
- * resulting error will have a namespaced error code of example.one. The
- * resulting error will replace {0} with the value of foo, and {1} with the
- * value of bar. The object is not restricted in the number of arguments it can
- * take.
- *
- * If fewer arguments are specified than necessary for interpolation, the extra
- * interpolation markers will be preserved in the final string.
- *
- * Since data will be parsed statically during a build step, some restrictions
- * are applied with respect to how minErr instances are created and called.
- * Instances should have names of the form namespaceMinErr for a minErr created
- * using minErr('namespace') . Error codes, namespaces and template strings
- * should all be static strings, not variables or general expressions.
- *
- * @param {string} module The namespace to use for the new minErr instance.
- * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
- * error from returned function, for cases when a particular type of error is useful.
- * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
- */
-
-function minErr(module, ErrorConstructor) {
- ErrorConstructor = ErrorConstructor || Error;
- return function() {
- var SKIP_INDEXES = 2;
-
- var templateArgs = arguments,
- code = templateArgs[0],
- message = '[' + (module ? module + ':' : '') + code + '] ',
- template = templateArgs[1],
- paramPrefix, i;
-
- message += template.replace(/\{\d+\}/g, function(match) {
- var index = +match.slice(1, -1),
- shiftedIndex = index + SKIP_INDEXES;
-
- if (shiftedIndex < templateArgs.length) {
- return toDebugString(templateArgs[shiftedIndex]);
- }
-
- return match;
- });
-
- message += '\nhttp://errors.angularjs.org/1.5.0/' +
- (module ? module + '/' : '') + code;
-
- for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
- message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
- encodeURIComponent(toDebugString(templateArgs[i]));
- }
-
- return new ErrorConstructor(message);
- };
-}
-
-/* We need to tell jshint what variables are being exported */
-/* global angular: true,
- msie: true,
- jqLite: true,
- jQuery: true,
- slice: true,
- splice: true,
- push: true,
- toString: true,
- ngMinErr: true,
- angularModule: true,
- uid: true,
- REGEX_STRING_REGEXP: true,
- VALIDITY_STATE_PROPERTY: true,
-
- lowercase: true,
- uppercase: true,
- manualLowercase: true,
- manualUppercase: true,
- nodeName_: true,
- isArrayLike: true,
- forEach: true,
- forEachSorted: true,
- reverseParams: true,
- nextUid: true,
- setHashKey: true,
- extend: true,
- toInt: true,
- inherit: true,
- merge: true,
- noop: true,
- identity: true,
- valueFn: true,
- isUndefined: true,
- isDefined: true,
- isObject: true,
- isBlankObject: true,
- isString: true,
- isNumber: true,
- isDate: true,
- isArray: true,
- isFunction: true,
- isRegExp: true,
- isWindow: true,
- isScope: true,
- isFile: true,
- isFormData: true,
- isBlob: true,
- isBoolean: true,
- isPromiseLike: true,
- trim: true,
- escapeForRegexp: true,
- isElement: true,
- makeMap: true,
- includes: true,
- arrayRemove: true,
- copy: true,
- shallowCopy: true,
- equals: true,
- csp: true,
- jq: true,
- concat: true,
- sliceArgs: true,
- bind: true,
- toJsonReplacer: true,
- toJson: true,
- fromJson: true,
- convertTimezoneToLocal: true,
- timezoneToOffset: true,
- startingTag: true,
- tryDecodeURIComponent: true,
- parseKeyValue: true,
- toKeyValue: true,
- encodeUriSegment: true,
- encodeUriQuery: true,
- angularInit: true,
- bootstrap: true,
- getTestability: true,
- snake_case: true,
- bindJQuery: true,
- assertArg: true,
- assertArgFn: true,
- assertNotHasOwnProperty: true,
- getter: true,
- getBlockNodes: true,
- hasOwnProperty: true,
- createMap: true,
-
- NODE_TYPE_ELEMENT: true,
- NODE_TYPE_ATTRIBUTE: true,
- NODE_TYPE_TEXT: true,
- NODE_TYPE_COMMENT: true,
- NODE_TYPE_DOCUMENT: true,
- NODE_TYPE_DOCUMENT_FRAGMENT: true,
-*/
-
-////////////////////////////////////
-
-/**
- * @ngdoc module
- * @name ng
- * @module ng
- * @description
- *
- * # ng (core module)
- * The ng module is loaded by default when an AngularJS application is started. The module itself
- * contains the essential components for an AngularJS application to function. The table below
- * lists a high level breakdown of each of the services/factories, filters, directives and testing
- * components available within this core module.
- *
- * <div doc-module-components="ng"></div>
- */
-
-var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
-
-// The name of a form control's ValidityState property.
-// This is used so that it's possible for internal tests to create mock ValidityStates.
-var VALIDITY_STATE_PROPERTY = 'validity';
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
-var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
-
-
-var manualLowercase = function(s) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
- : s;
-};
-var manualUppercase = function(s) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
- : s;
-};
-
-
-// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
-// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
-// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
-if ('i' !== 'I'.toLowerCase()) {
- lowercase = manualLowercase;
- uppercase = manualUppercase;
-}
-
-
-var
- msie, // holds major version number for IE, or NaN if UA is not IE.
- jqLite, // delay binding since jQuery could be loaded after us.
- jQuery, // delay binding
- slice = [].slice,
- splice = [].splice,
- push = [].push,
- toString = Object.prototype.toString,
- getPrototypeOf = Object.getPrototypeOf,
- ngMinErr = minErr('ng'),
-
- /** @name angular */
- angular = window.angular || (window.angular = {}),
- angularModule,
- uid = 0;
-
-/**
- * documentMode is an IE-only property
- * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
- */
-msie = document.documentMode;
-
-
-/**
- * @private
- * @param {*} obj
- * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
- * String ...)
- */
-function isArrayLike(obj) {
-
- // `null`, `undefined` and `window` are not array-like
- if (obj == null || isWindow(obj)) return false;
-
- // arrays, strings and jQuery/jqLite objects are array like
- // * jqLite is either the jQuery or jqLite constructor function
- // * we have to check the existence of jqLite first as this method is called
- // via the forEach method when constructing the jqLite object in the first place
- if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;
-
- // Support: iOS 8.2 (not reproducible in simulator)
- // "length" in obj used to prevent JIT error (gh-11508)
- var length = "length" in Object(obj) && obj.length;
-
- // NodeList objects (with `item` method) and
- // other objects with suitable length characteristics are array-like
- return isNumber(length) &&
- (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function');
-
-}
-
-/**
- * @ngdoc function
- * @name angular.forEach
- * @module ng
- * @kind function
- *
- * @description
- * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
- * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
- * is the value of an object property or an array element, `key` is the object property key or
- * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
- *
- * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
- * using the `hasOwnProperty` method.
- *
- * Unlike ES262's
- * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
- * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
- * return the value provided.
- *
- ```js
- var values = {name: 'misko', gender: 'male'};
- var log = [];
- angular.forEach(values, function(value, key) {
- this.push(key + ': ' + value);
- }, log);
- expect(log).toEqual(['name: misko', 'gender: male']);
- ```
- *
- * @param {Object|Array} obj Object to iterate over.
- * @param {Function} iterator Iterator function.
- * @param {Object=} context Object to become context (`this`) for the iterator function.
- * @returns {Object|Array} Reference to `obj`.
- */
-
-function forEach(obj, iterator, context) {
- var key, length;
- if (obj) {
- if (isFunction(obj)) {
- for (key in obj) {
- // Need to check if hasOwnProperty exists,
- // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
- if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- } else if (isArray(obj) || isArrayLike(obj)) {
- var isPrimitive = typeof obj !== 'object';
- for (key = 0, length = obj.length; key < length; key++) {
- if (isPrimitive || key in obj) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- } else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context, obj);
- } else if (isBlankObject(obj)) {
- // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
- for (key in obj) {
- iterator.call(context, obj[key], key, obj);
- }
- } else if (typeof obj.hasOwnProperty === 'function') {
- // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- } else {
- // Slow path for objects which do not have a method `hasOwnProperty`
- for (key in obj) {
- if (hasOwnProperty.call(obj, key)) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- }
- }
- return obj;
-}
-
-function forEachSorted(obj, iterator, context) {
- var keys = Object.keys(obj).sort();
- for (var i = 0; i < keys.length; i++) {
- iterator.call(context, obj[keys[i]], keys[i]);
- }
- return keys;
-}
-
-
-/**
- * when using forEach the params are value, key, but it is often useful to have key, value.
- * @param {function(string, *)} iteratorFn
- * @returns {function(*, string)}
- */
-function reverseParams(iteratorFn) {
- return function(value, key) {iteratorFn(key, value);};
-}
-
-/**
- * A consistent way of creating unique IDs in angular.
- *
- * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
- * we hit number precision issues in JavaScript.
- *
- * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
- *
- * @returns {number} an unique alpha-numeric string
- */
-function nextUid() {
- return ++uid;
-}
-
-
-/**
- * Set or clear the hashkey for an object.
- * @param obj object
- * @param h the hashkey (!truthy to delete the hashkey)
- */
-function setHashKey(obj, h) {
- if (h) {
- obj.$$hashKey = h;
- } else {
- delete obj.$$hashKey;
- }
-}
-
-
-function baseExtend(dst, objs, deep) {
- var h = dst.$$hashKey;
-
- for (var i = 0, ii = objs.length; i < ii; ++i) {
- var obj = objs[i];
- if (!isObject(obj) && !isFunction(obj)) continue;
- var keys = Object.keys(obj);
- for (var j = 0, jj = keys.length; j < jj; j++) {
- var key = keys[j];
- var src = obj[key];
-
- if (deep && isObject(src)) {
- if (isDate(src)) {
- dst[key] = new Date(src.valueOf());
- } else if (isRegExp(src)) {
- dst[key] = new RegExp(src);
- } else if (src.nodeName) {
- dst[key] = src.cloneNode(true);
- } else if (isElement(src)) {
- dst[key] = src.clone();
- } else {
- if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
- baseExtend(dst[key], [src], true);
- }
- } else {
- dst[key] = src;
- }
- }
- }
-
- setHashKey(dst, h);
- return dst;
-}
-
-/**
- * @ngdoc function
- * @name angular.extend
- * @module ng
- * @kind function
- *
- * @description
- * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
- * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
- * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
- *
- * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
- * {@link angular.merge} for this.
- *
- * @param {Object} dst Destination object.
- * @param {...Object} src Source object(s).
- * @returns {Object} Reference to `dst`.
- */
-function extend(dst) {
- return baseExtend(dst, slice.call(arguments, 1), false);
-}
-
-
-/**
-* @ngdoc function
-* @name angular.merge
-* @module ng
-* @kind function
-*
-* @description
-* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
-* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
-* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
-*
-* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
-* objects, performing a deep copy.
-*
-* @param {Object} dst Destination object.
-* @param {...Object} src Source object(s).
-* @returns {Object} Reference to `dst`.
-*/
-function merge(dst) {
- return baseExtend(dst, slice.call(arguments, 1), true);
-}
-
-
-
-function toInt(str) {
- return parseInt(str, 10);
-}
-
-
-function inherit(parent, extra) {
- return extend(Object.create(parent), extra);
-}
-
-/**
- * @ngdoc function
- * @name angular.noop
- * @module ng
- * @kind function
- *
- * @description
- * A function that performs no operations. This function can be useful when writing code in the
- * functional style.
- ```js
- function foo(callback) {
- var result = calculateResult();
- (callback || angular.noop)(result);
- }
- ```
- */
-function noop() {}
-noop.$inject = [];
-
-
-/**
- * @ngdoc function
- * @name angular.identity
- * @module ng
- * @kind function
- *
- * @description
- * A function that returns its first argument. This function is useful when writing code in the
- * functional style.
- *
- ```js
- function transformer(transformationFn, value) {
- return (transformationFn || angular.identity)(value);
- };
- ```
- * @param {*} value to be returned.
- * @returns {*} the value passed in.
- */
-function identity($) {return $;}
-identity.$inject = [];
-
-
-function valueFn(value) {return function() {return value;};}
-
-function hasCustomToString(obj) {
- return isFunction(obj.toString) && obj.toString !== toString;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isUndefined
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is undefined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is undefined.
- */
-function isUndefined(value) {return typeof value === 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDefined
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is defined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is defined.
- */
-function isDefined(value) {return typeof value !== 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isObject
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
- * considered to be objects. Note that JavaScript arrays are objects.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Object` but not `null`.
- */
-function isObject(value) {
- // http://jsperf.com/isobject4
- return value !== null && typeof value === 'object';
-}
-
-
-/**
- * Determine if a value is an object with a null prototype
- *
- * @returns {boolean} True if `value` is an `Object` with a null prototype
- */
-function isBlankObject(value) {
- return value !== null && typeof value === 'object' && !getPrototypeOf(value);
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isString
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `String`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `String`.
- */
-function isString(value) {return typeof value === 'string';}
-
-
-/**
- * @ngdoc function
- * @name angular.isNumber
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `Number`.
- *
- * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
- *
- * If you wish to exclude these then you can use the native
- * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
- * method.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Number`.
- */
-function isNumber(value) {return typeof value === 'number';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDate
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a value is a date.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Date`.
- */
-function isDate(value) {
- return toString.call(value) === '[object Date]';
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isArray
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is an `Array`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Array`.
- */
-var isArray = Array.isArray;
-
-/**
- * @ngdoc function
- * @name angular.isFunction
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `Function`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Function`.
- */
-function isFunction(value) {return typeof value === 'function';}
-
-
-/**
- * Determines if a value is a regular expression object.
- *
- * @private
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `RegExp`.
- */
-function isRegExp(value) {
- return toString.call(value) === '[object RegExp]';
-}
-
-
-/**
- * Checks if `obj` is a window object.
- *
- * @private
- * @param {*} obj Object to check
- * @returns {boolean} True if `obj` is a window obj.
- */
-function isWindow(obj) {
- return obj && obj.window === obj;
-}
-
-
-function isScope(obj) {
- return obj && obj.$evalAsync && obj.$watch;
-}
-
-
-function isFile(obj) {
- return toString.call(obj) === '[object File]';
-}
-
-
-function isFormData(obj) {
- return toString.call(obj) === '[object FormData]';
-}
-
-
-function isBlob(obj) {
- return toString.call(obj) === '[object Blob]';
-}
-
-
-function isBoolean(value) {
- return typeof value === 'boolean';
-}
-
-
-function isPromiseLike(obj) {
- return obj && isFunction(obj.then);
-}
-
-
-var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
-function isTypedArray(value) {
- return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
-}
-
-function isArrayBuffer(obj) {
- return toString.call(obj) === '[object ArrayBuffer]';
-}
-
-
-var trim = function(value) {
- return isString(value) ? value.trim() : value;
-};
-
-// Copied from:
-// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
-// Prereq: s is a string.
-var escapeForRegexp = function(s) {
- return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
- replace(/\x08/g, '\\x08');
-};
-
-
-/**
- * @ngdoc function
- * @name angular.isElement
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a DOM element (or wrapped jQuery element).
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
- */
-function isElement(node) {
- return !!(node &&
- (node.nodeName // we are a direct element
- || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
-}
-
-/**
- * @param str 'key1,key2,...'
- * @returns {object} in the form of {key1:true, key2:true, ...}
- */
-function makeMap(str) {
- var obj = {}, items = str.split(','), i;
- for (i = 0; i < items.length; i++) {
- obj[items[i]] = true;
- }
- return obj;
-}
-
-
-function nodeName_(element) {
- return lowercase(element.nodeName || (element[0] && element[0].nodeName));
-}
-
-function includes(array, obj) {
- return Array.prototype.indexOf.call(array, obj) != -1;
-}
-
-function arrayRemove(array, value) {
- var index = array.indexOf(value);
- if (index >= 0) {
- array.splice(index, 1);
- }
- return index;
-}
-
-/**
- * @ngdoc function
- * @name angular.copy
- * @module ng
- * @kind function
- *
- * @description
- * Creates a deep copy of `source`, which should be an object or an array.
- *
- * * If no destination is supplied, a copy of the object or array is created.
- * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
- * are deleted and then all elements/properties from the source are copied to it.
- * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
- * * If `source` is identical to 'destination' an exception will be thrown.
- *
- * @param {*} source The source that will be used to make a copy.
- * Can be any type, including primitives, `null`, and `undefined`.
- * @param {(Object|Array)=} destination Destination into which the source is copied. If
- * provided, must be of the same type as `source`.
- * @returns {*} The copy or updated `destination`, if `destination` was specified.
- *
- * @example
- <example module="copyExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form novalidate class="simple-form">
- Name: <input type="text" ng-model="user.name" /><br />
- E-mail: <input type="email" ng-model="user.email" /><br />
- Gender: <input type="radio" ng-model="user.gender" value="male" />male
- <input type="radio" ng-model="user.gender" value="female" />female<br />
- <button ng-click="reset()">RESET</button>
- <button ng-click="update(user)">SAVE</button>
- </form>
- <pre>form = {{user | json}}</pre>
- <pre>master = {{master | json}}</pre>
- </div>
-
- <script>
- angular.module('copyExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.master= {};
-
- $scope.update = function(user) {
- // Example with 1 argument
- $scope.master= angular.copy(user);
- };
-
- $scope.reset = function() {
- // Example with 2 arguments
- angular.copy($scope.master, $scope.user);
- };
-
- $scope.reset();
- }]);
- </script>
- </file>
- </example>
- */
-function copy(source, destination) {
- var stackSource = [];
- var stackDest = [];
-
- if (destination) {
- if (isTypedArray(destination) || isArrayBuffer(destination)) {
- throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
- }
- if (source === destination) {
- throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
- }
-
- // Empty the destination object
- if (isArray(destination)) {
- destination.length = 0;
- } else {
- forEach(destination, function(value, key) {
- if (key !== '$$hashKey') {
- delete destination[key];
- }
- });
- }
-
- stackSource.push(source);
- stackDest.push(destination);
- return copyRecurse(source, destination);
- }
-
- return copyElement(source);
-
- function copyRecurse(source, destination) {
- var h = destination.$$hashKey;
- var result, key;
- if (isArray(source)) {
- for (var i = 0, ii = source.length; i < ii; i++) {
- destination.push(copyElement(source[i]));
- }
- } else if (isBlankObject(source)) {
- // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
- for (key in source) {
- destination[key] = copyElement(source[key]);
- }
- } else if (source && typeof source.hasOwnProperty === 'function') {
- // Slow path, which must rely on hasOwnProperty
- for (key in source) {
- if (source.hasOwnProperty(key)) {
- destination[key] = copyElement(source[key]);
- }
- }
- } else {
- // Slowest path --- hasOwnProperty can't be called as a method
- for (key in source) {
- if (hasOwnProperty.call(source, key)) {
- destination[key] = copyElement(source[key]);
- }
- }
- }
- setHashKey(destination, h);
- return destination;
- }
-
- function copyElement(source) {
- // Simple values
- if (!isObject(source)) {
- return source;
- }
-
- // Already copied values
- var index = stackSource.indexOf(source);
- if (index !== -1) {
- return stackDest[index];
- }
-
- if (isWindow(source) || isScope(source)) {
- throw ngMinErr('cpws',
- "Can't copy! Making copies of Window or Scope instances is not supported.");
- }
-
- var needsRecurse = false;
- var destination = copyType(source);
-
- if (destination === undefined) {
- destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
- needsRecurse = true;
- }
-
- stackSource.push(source);
- stackDest.push(destination);
-
- return needsRecurse
- ? copyRecurse(source, destination)
- : destination;
- }
-
- function copyType(source) {
- switch (toString.call(source)) {
- case '[object Int8Array]':
- case '[object Int16Array]':
- case '[object Int32Array]':
- case '[object Float32Array]':
- case '[object Float64Array]':
- case '[object Uint8Array]':
- case '[object Uint8ClampedArray]':
- case '[object Uint16Array]':
- case '[object Uint32Array]':
- return new source.constructor(copyElement(source.buffer));
-
- case '[object ArrayBuffer]':
- //Support: IE10
- if (!source.slice) {
- var copied = new ArrayBuffer(source.byteLength);
- new Uint8Array(copied).set(new Uint8Array(source));
- return copied;
- }
- return source.slice(0);
-
- case '[object Boolean]':
- case '[object Number]':
- case '[object String]':
- case '[object Date]':
- return new source.constructor(source.valueOf());
-
- case '[object RegExp]':
- var re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
- re.lastIndex = source.lastIndex;
- return re;
- }
-
- if (isFunction(source.cloneNode)) {
- return source.cloneNode(true);
- }
- }
-}
-
-/**
- * Creates a shallow copy of an object, an array or a primitive.
- *
- * Assumes that there are no proto properties for objects.
- */
-function shallowCopy(src, dst) {
- if (isArray(src)) {
- dst = dst || [];
-
- for (var i = 0, ii = src.length; i < ii; i++) {
- dst[i] = src[i];
- }
- } else if (isObject(src)) {
- dst = dst || {};
-
- for (var key in src) {
- if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
- dst[key] = src[key];
- }
- }
- }
-
- return dst || src;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.equals
- * @module ng
- * @kind function
- *
- * @description
- * Determines if two objects or two values are equivalent. Supports value types, regular
- * expressions, arrays and objects.
- *
- * Two objects or values are considered equivalent if at least one of the following is true:
- *
- * * Both objects or values pass `===` comparison.
- * * Both objects or values are of the same type and all of their properties are equal by
- * comparing them with `angular.equals`.
- * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- * * Both values represent the same regular expression (In JavaScript,
- * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
- * representation matches).
- *
- * During a property comparison, properties of `function` type and properties with names
- * that begin with `$` are ignored.
- *
- * Scope and DOMWindow objects are being compared only by identify (`===`).
- *
- * @param {*} o1 Object or value to compare.
- * @param {*} o2 Object or value to compare.
- * @returns {boolean} True if arguments are equal.
- */
-function equals(o1, o2) {
- if (o1 === o2) return true;
- if (o1 === null || o2 === null) return false;
- if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
- var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2 && t1 == 'object') {
- if (isArray(o1)) {
- if (!isArray(o2)) return false;
- if ((length = o1.length) == o2.length) {
- for (key = 0; key < length; key++) {
- if (!equals(o1[key], o2[key])) return false;
- }
- return true;
- }
- } else if (isDate(o1)) {
- if (!isDate(o2)) return false;
- return equals(o1.getTime(), o2.getTime());
- } else if (isRegExp(o1)) {
- if (!isRegExp(o2)) return false;
- return o1.toString() == o2.toString();
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
- isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
- keySet = createMap();
- for (key in o1) {
- if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
- if (!equals(o1[key], o2[key])) return false;
- keySet[key] = true;
- }
- for (key in o2) {
- if (!(key in keySet) &&
- key.charAt(0) !== '$' &&
- isDefined(o2[key]) &&
- !isFunction(o2[key])) return false;
- }
- return true;
- }
- }
- return false;
-}
-
-var csp = function() {
- if (!isDefined(csp.rules)) {
-
-
- var ngCspElement = (document.querySelector('[ng-csp]') ||
- document.querySelector('[data-ng-csp]'));
-
- if (ngCspElement) {
- var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
- ngCspElement.getAttribute('data-ng-csp');
- csp.rules = {
- noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),
- noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)
- };
- } else {
- csp.rules = {
- noUnsafeEval: noUnsafeEval(),
- noInlineStyle: false
- };
- }
- }
-
- return csp.rules;
-
- function noUnsafeEval() {
- try {
- /* jshint -W031, -W054 */
- new Function('');
- /* jshint +W031, +W054 */
- return false;
- } catch (e) {
- return true;
- }
- }
-};
-
-/**
- * @ngdoc directive
- * @module ng
- * @name ngJq
- *
- * @element ANY
- * @param {string=} ngJq the name of the library available under `window`
- * to be used for angular.element
- * @description
- * Use this directive to force the angular.element library. This should be
- * used to force either jqLite by leaving ng-jq blank or setting the name of
- * the jquery variable under window (eg. jQuery).
- *
- * Since angular looks for this directive when it is loaded (doesn't wait for the
- * DOMContentLoaded event), it must be placed on an element that comes before the script
- * which loads angular. Also, only the first instance of `ng-jq` will be used and all
- * others ignored.
- *
- * @example
- * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
- ```html
- <!doctype html>
- <html ng-app ng-jq>
- ...
- ...
- </html>
- ```
- * @example
- * This example shows how to use a jQuery based library of a different name.
- * The library name must be available at the top most 'window'.
- ```html
- <!doctype html>
- <html ng-app ng-jq="jQueryLib">
- ...
- ...
- </html>
- ```
- */
-var jq = function() {
- if (isDefined(jq.name_)) return jq.name_;
- var el;
- var i, ii = ngAttrPrefixes.length, prefix, name;
- for (i = 0; i < ii; ++i) {
- prefix = ngAttrPrefixes[i];
- if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
- name = el.getAttribute(prefix + 'jq');
- break;
- }
- }
-
- return (jq.name_ = name);
-};
-
-function concat(array1, array2, index) {
- return array1.concat(slice.call(array2, index));
-}
-
-function sliceArgs(args, startIndex) {
- return slice.call(args, startIndex || 0);
-}
-
-
-/* jshint -W101 */
-/**
- * @ngdoc function
- * @name angular.bind
- * @module ng
- * @kind function
- *
- * @description
- * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
- * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
- * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
- *
- * @param {Object} self Context which `fn` should be evaluated in.
- * @param {function()} fn Function to be bound.
- * @param {...*} args Optional arguments to be prebound to the `fn` function call.
- * @returns {function()} Function that wraps the `fn` with all the specified bindings.
- */
-/* jshint +W101 */
-function bind(self, fn) {
- var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
- if (isFunction(fn) && !(fn instanceof RegExp)) {
- return curryArgs.length
- ? function() {
- return arguments.length
- ? fn.apply(self, concat(curryArgs, arguments, 0))
- : fn.apply(self, curryArgs);
- }
- : function() {
- return arguments.length
- ? fn.apply(self, arguments)
- : fn.call(self);
- };
- } else {
- // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
- return fn;
- }
-}
-
-
-function toJsonReplacer(key, value) {
- var val = value;
-
- if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
- val = undefined;
- } else if (isWindow(value)) {
- val = '$WINDOW';
- } else if (value && document === value) {
- val = '$DOCUMENT';
- } else if (isScope(value)) {
- val = '$SCOPE';
- }
-
- return val;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.toJson
- * @module ng
- * @kind function
- *
- * @description
- * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
- * stripped since angular uses this notation internally.
- *
- * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
- * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
- * If set to an integer, the JSON output will contain that many spaces per indentation.
- * @returns {string|undefined} JSON-ified string representing `obj`.
- */
-function toJson(obj, pretty) {
- if (isUndefined(obj)) return undefined;
- if (!isNumber(pretty)) {
- pretty = pretty ? 2 : null;
- }
- return JSON.stringify(obj, toJsonReplacer, pretty);
-}
-
-
-/**
- * @ngdoc function
- * @name angular.fromJson
- * @module ng
- * @kind function
- *
- * @description
- * Deserializes a JSON string.
- *
- * @param {string} json JSON string to deserialize.
- * @returns {Object|Array|string|number} Deserialized JSON string.
- */
-function fromJson(json) {
- return isString(json)
- ? JSON.parse(json)
- : json;
-}
-
-
-var ALL_COLONS = /:/g;
-function timezoneToOffset(timezone, fallback) {
- // IE/Edge do not "understand" colon (`:`) in timezone
- timezone = timezone.replace(ALL_COLONS, '');
- var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
- return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
-}
-
-
-function addDateMinutes(date, minutes) {
- date = new Date(date.getTime());
- date.setMinutes(date.getMinutes() + minutes);
- return date;
-}
-
-
-function convertTimezoneToLocal(date, timezone, reverse) {
- reverse = reverse ? -1 : 1;
- var dateTimezoneOffset = date.getTimezoneOffset();
- var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
- return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
-}
-
-
-/**
- * @returns {string} Returns the string representation of the element.
- */
-function startingTag(element) {
- element = jqLite(element).clone();
- try {
- // turns out IE does not let you set .html() on elements which
- // are not allowed to have children. So we just ignore it.
- element.empty();
- } catch (e) {}
- var elemHtml = jqLite('<div>').append(element).html();
- try {
- return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
- elemHtml.
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});
- } catch (e) {
- return lowercase(elemHtml);
- }
-
-}
-
-
-/////////////////////////////////////////////////
-
-/**
- * Tries to decode the URI component without throwing an exception.
- *
- * @private
- * @param str value potential URI component to check.
- * @returns {boolean} True if `value` can be decoded
- * with the decodeURIComponent function.
- */
-function tryDecodeURIComponent(value) {
- try {
- return decodeURIComponent(value);
- } catch (e) {
- // Ignore any invalid uri component
- }
-}
-
-
-/**
- * Parses an escaped url query string into key-value pairs.
- * @returns {Object.<string,boolean|Array>}
- */
-function parseKeyValue(/**string*/keyValue) {
- var obj = {};
- forEach((keyValue || "").split('&'), function(keyValue) {
- var splitPoint, key, val;
- if (keyValue) {
- key = keyValue = keyValue.replace(/\+/g,'%20');
- splitPoint = keyValue.indexOf('=');
- if (splitPoint !== -1) {
- key = keyValue.substring(0, splitPoint);
- val = keyValue.substring(splitPoint + 1);
- }
- key = tryDecodeURIComponent(key);
- if (isDefined(key)) {
- val = isDefined(val) ? tryDecodeURIComponent(val) : true;
- if (!hasOwnProperty.call(obj, key)) {
- obj[key] = val;
- } else if (isArray(obj[key])) {
- obj[key].push(val);
- } else {
- obj[key] = [obj[key],val];
- }
- }
- }
- });
- return obj;
-}
-
-function toKeyValue(obj) {
- var parts = [];
- forEach(obj, function(value, key) {
- if (isArray(value)) {
- forEach(value, function(arrayValue) {
- parts.push(encodeUriQuery(key, true) +
- (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
- });
- } else {
- parts.push(encodeUriQuery(key, true) +
- (value === true ? '' : '=' + encodeUriQuery(value, true)));
- }
- });
- return parts.length ? parts.join('&') : '';
-}
-
-
-/**
- * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
- * segments:
- * segment = *pchar
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * pct-encoded = "%" HEXDIG HEXDIG
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
-function encodeUriSegment(val) {
- return encodeUriQuery(val, true).
- replace(/%26/gi, '&').
- replace(/%3D/gi, '=').
- replace(/%2B/gi, '+');
-}
-
-
-/**
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
- * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
- * encoded per http://tools.ietf.org/html/rfc3986:
- * query = *( pchar / "/" / "?" )
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * pct-encoded = "%" HEXDIG HEXDIG
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
-function encodeUriQuery(val, pctEncodeSpaces) {
- return encodeURIComponent(val).
- replace(/%40/gi, '@').
- replace(/%3A/gi, ':').
- replace(/%24/g, '$').
- replace(/%2C/gi, ',').
- replace(/%3B/gi, ';').
- replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
-}
-
-var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
-
-function getNgAttribute(element, ngAttr) {
- var attr, i, ii = ngAttrPrefixes.length;
- for (i = 0; i < ii; ++i) {
- attr = ngAttrPrefixes[i] + ngAttr;
- if (isString(attr = element.getAttribute(attr))) {
- return attr;
- }
- }
- return null;
-}
-
-/**
- * @ngdoc directive
- * @name ngApp
- * @module ng
- *
- * @element ANY
- * @param {angular.Module} ngApp an optional application
- * {@link angular.module module} name to load.
- * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
- * created in "strict-di" mode. This means that the application will fail to invoke functions which
- * do not use explicit function annotation (and are thus unsuitable for minification), as described
- * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
- * tracking down the root of these bugs.
- *
- * @description
- *
- * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
- * designates the **root element** of the application and is typically placed near the root element
- * of the page - e.g. on the `<body>` or `<html>` tags.
- *
- * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
- * found in the document will be used to define the root element to auto-bootstrap as an
- * application. To run multiple applications in an HTML document you must manually bootstrap them using
- * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
- *
- * You can specify an **AngularJS module** to be used as the root module for the application. This
- * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
- * should contain the application code needed or have dependencies on other modules that will
- * contain the code. See {@link angular.module} for more information.
- *
- * In the example below if the `ngApp` directive were not placed on the `html` element then the
- * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
- * would not be resolved to `3`.
- *
- * `ngApp` is the easiest, and most common way to bootstrap an application.
- *
- <example module="ngAppDemo">
- <file name="index.html">
- <div ng-controller="ngAppDemoController">
- I can add: {{a}} + {{b}} = {{ a+b }}
- </div>
- </file>
- <file name="script.js">
- angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
- $scope.a = 1;
- $scope.b = 2;
- });
- </file>
- </example>
- *
- * Using `ngStrictDi`, you would see something like this:
- *
- <example ng-app-included="true">
- <file name="index.html">
- <div ng-app="ngAppStrictDemo" ng-strict-di>
- <div ng-controller="GoodController1">
- I can add: {{a}} + {{b}} = {{ a+b }}
-
- <p>This renders because the controller does not fail to
- instantiate, by using explicit annotation style (see
- script.js for details)
- </p>
- </div>
-
- <div ng-controller="GoodController2">
- Name: <input ng-model="name"><br />
- Hello, {{name}}!
-
- <p>This renders because the controller does not fail to
- instantiate, by using explicit annotation style
- (see script.js for details)
- </p>
- </div>
-
- <div ng-controller="BadController">
- I can add: {{a}} + {{b}} = {{ a+b }}
-
- <p>The controller could not be instantiated, due to relying
- on automatic function annotations (which are disabled in
- strict mode). As such, the content of this section is not
- interpolated, and there should be an error in your web console.
- </p>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngAppStrictDemo', [])
- // BadController will fail to instantiate, due to relying on automatic function annotation,
- // rather than an explicit annotation
- .controller('BadController', function($scope) {
- $scope.a = 1;
- $scope.b = 2;
- })
- // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
- // due to using explicit annotations using the array style and $inject property, respectively.
- .controller('GoodController1', ['$scope', function($scope) {
- $scope.a = 1;
- $scope.b = 2;
- }])
- .controller('GoodController2', GoodController2);
- function GoodController2($scope) {
- $scope.name = "World";
- }
- GoodController2.$inject = ['$scope'];
- </file>
- <file name="style.css">
- div[ng-controller] {
- margin-bottom: 1em;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- border: 1px solid;
- padding: .5em;
- }
- div[ng-controller^=Good] {
- border-color: #d6e9c6;
- background-color: #dff0d8;
- color: #3c763d;
- }
- div[ng-controller^=Bad] {
- border-color: #ebccd1;
- background-color: #f2dede;
- color: #a94442;
- margin-bottom: 0;
- }
- </file>
- </example>
- */
-function angularInit(element, bootstrap) {
- var appElement,
- module,
- config = {};
-
- // The element `element` has priority over any other element
- forEach(ngAttrPrefixes, function(prefix) {
- var name = prefix + 'app';
-
- if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
- appElement = element;
- module = element.getAttribute(name);
- }
- });
- forEach(ngAttrPrefixes, function(prefix) {
- var name = prefix + 'app';
- var candidate;
-
- if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
- appElement = candidate;
- module = candidate.getAttribute(name);
- }
- });
- if (appElement) {
- config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
- bootstrap(appElement, module ? [module] : [], config);
- }
-}
-
-/**
- * @ngdoc function
- * @name angular.bootstrap
- * @module ng
- * @description
- * Use this function to manually start up angular application.
- *
- * See: {@link guide/bootstrap Bootstrap}
- *
- * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
- * They must use {@link ng.directive:ngApp ngApp}.
- *
- * Angular will detect if it has been loaded into the browser more than once and only allow the
- * first loaded script to be bootstrapped and will report a warning to the browser console for
- * each of the subsequent scripts. This prevents strange results in applications, where otherwise
- * multiple instances of Angular try to work on the DOM.
- *
- * ```html
- * <!doctype html>
- * <html>
- * <body>
- * <div ng-controller="WelcomeController">
- * {{greeting}}
- * </div>
- *
- * <script src="angular.js"></script>
- * <script>
- * var app = angular.module('demo', [])
- * .controller('WelcomeController', function($scope) {
- * $scope.greeting = 'Welcome!';
- * });
- * angular.bootstrap(document, ['demo']);
- * </script>
- * </body>
- * </html>
- * ```
- *
- * @param {DOMElement} element DOM element which is the root of angular application.
- * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
- * Each item in the array should be the name of a predefined module or a (DI annotated)
- * function that will be invoked by the injector as a `config` block.
- * See: {@link angular.module modules}
- * @param {Object=} config an object for defining configuration options for the application. The
- * following keys are supported:
- *
- * * `strictDi` - disable automatic function annotation for the application. This is meant to
- * assist in finding bugs which break minified code. Defaults to `false`.
- *
- * @returns {auto.$injector} Returns the newly created injector for this app.
- */
-function bootstrap(element, modules, config) {
- if (!isObject(config)) config = {};
- var defaultConfig = {
- strictDi: false
- };
- config = extend(defaultConfig, config);
- var doBootstrap = function() {
- element = jqLite(element);
-
- if (element.injector()) {
- var tag = (element[0] === document) ? 'document' : startingTag(element);
- //Encode angle brackets to prevent input from being sanitized to empty string #8683
- throw ngMinErr(
- 'btstrpd',
- "App Already Bootstrapped with this Element '{0}'",
- tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
- }
-
- modules = modules || [];
- modules.unshift(['$provide', function($provide) {
- $provide.value('$rootElement', element);
- }]);
-
- if (config.debugInfoEnabled) {
- // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
- modules.push(['$compileProvider', function($compileProvider) {
- $compileProvider.debugInfoEnabled(true);
- }]);
- }
-
- modules.unshift('ng');
- var injector = createInjector(modules, config.strictDi);
- injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
- function bootstrapApply(scope, element, compile, injector) {
- scope.$apply(function() {
- element.data('$injector', injector);
- compile(element)(scope);
- });
- }]
- );
- return injector;
- };
-
- var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
- var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
-
- if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
- config.debugInfoEnabled = true;
- window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
- }
-
- if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
- return doBootstrap();
- }
-
- window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
- angular.resumeBootstrap = function(extraModules) {
- forEach(extraModules, function(module) {
- modules.push(module);
- });
- return doBootstrap();
- };
-
- if (isFunction(angular.resumeDeferredBootstrap)) {
- angular.resumeDeferredBootstrap();
- }
-}
-
-/**
- * @ngdoc function
- * @name angular.reloadWithDebugInfo
- * @module ng
- * @description
- * Use this function to reload the current application with debug information turned on.
- * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
- *
- * See {@link ng.$compileProvider#debugInfoEnabled} for more.
- */
-function reloadWithDebugInfo() {
- window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
- window.location.reload();
-}
-
-/**
- * @name angular.getTestability
- * @module ng
- * @description
- * Get the testability service for the instance of Angular on the given
- * element.
- * @param {DOMElement} element DOM element which is the root of angular application.
- */
-function getTestability(rootElement) {
- var injector = angular.element(rootElement).injector();
- if (!injector) {
- throw ngMinErr('test',
- 'no injector found for element argument to getTestability');
- }
- return injector.get('$$testability');
-}
-
-var SNAKE_CASE_REGEXP = /[A-Z]/g;
-function snake_case(name, separator) {
- separator = separator || '_';
- return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
- return (pos ? separator : '') + letter.toLowerCase();
- });
-}
-
-var bindJQueryFired = false;
-function bindJQuery() {
- var originalCleanData;
-
- if (bindJQueryFired) {
- return;
- }
-
- // bind to jQuery if present;
- var jqName = jq();
- jQuery = isUndefined(jqName) ? window.jQuery : // use jQuery (if present)
- !jqName ? undefined : // use jqLite
- window[jqName]; // use jQuery specified by `ngJq`
-
- // Use jQuery if it exists with proper functionality, otherwise default to us.
- // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
- // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
- // versions. It will not work for sure with jQuery <1.7, though.
- if (jQuery && jQuery.fn.on) {
- jqLite = jQuery;
- extend(jQuery.fn, {
- scope: JQLitePrototype.scope,
- isolateScope: JQLitePrototype.isolateScope,
- controller: JQLitePrototype.controller,
- injector: JQLitePrototype.injector,
- inheritedData: JQLitePrototype.inheritedData
- });
-
- // All nodes removed from the DOM via various jQuery APIs like .remove()
- // are passed through jQuery.cleanData. Monkey-patch this method to fire
- // the $destroy event on all removed nodes.
- originalCleanData = jQuery.cleanData;
- jQuery.cleanData = function(elems) {
- var events;
- for (var i = 0, elem; (elem = elems[i]) != null; i++) {
- events = jQuery._data(elem, "events");
- if (events && events.$destroy) {
- jQuery(elem).triggerHandler('$destroy');
- }
- }
- originalCleanData(elems);
- };
- } else {
- jqLite = JQLite;
- }
-
- angular.element = jqLite;
-
- // Prevent double-proxying.
- bindJQueryFired = true;
-}
-
-/**
- * throw error if the argument is falsy.
- */
-function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
-}
-
-function assertArgFn(arg, name, acceptArrayAnnotation) {
- if (acceptArrayAnnotation && isArray(arg)) {
- arg = arg[arg.length - 1];
- }
-
- assertArg(isFunction(arg), name, 'not a function, got ' +
- (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
- return arg;
-}
-
-/**
- * throw error if the name given is hasOwnProperty
- * @param {String} name the name to test
- * @param {String} context the context in which the name is used, such as module or directive
- */
-function assertNotHasOwnProperty(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
- }
-}
-
-/**
- * Return the value accessible from the object by path. Any undefined traversals are ignored
- * @param {Object} obj starting object
- * @param {String} path path to traverse
- * @param {boolean} [bindFnToScope=true]
- * @returns {Object} value as accessible by path
- */
-//TODO(misko): this function needs to be removed
-function getter(obj, path, bindFnToScope) {
- if (!path) return obj;
- var keys = path.split('.');
- var key;
- var lastInstance = obj;
- var len = keys.length;
-
- for (var i = 0; i < len; i++) {
- key = keys[i];
- if (obj) {
- obj = (lastInstance = obj)[key];
- }
- }
- if (!bindFnToScope && isFunction(obj)) {
- return bind(lastInstance, obj);
- }
- return obj;
-}
-
-/**
- * Return the DOM siblings between the first and last node in the given array.
- * @param {Array} array like object
- * @returns {Array} the inputted object or a jqLite collection containing the nodes
- */
-function getBlockNodes(nodes) {
- // TODO(perf): update `nodes` instead of creating a new object?
- var node = nodes[0];
- var endNode = nodes[nodes.length - 1];
- var blockNodes;
-
- for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {
- if (blockNodes || nodes[i] !== node) {
- if (!blockNodes) {
- blockNodes = jqLite(slice.call(nodes, 0, i));
- }
- blockNodes.push(node);
- }
- }
-
- return blockNodes || nodes;
-}
-
-
-/**
- * Creates a new object without a prototype. This object is useful for lookup without having to
- * guard against prototypically inherited properties via hasOwnProperty.
- *
- * Related micro-benchmarks:
- * - http://jsperf.com/object-create2
- * - http://jsperf.com/proto-map-lookup/2
- * - http://jsperf.com/for-in-vs-object-keys2
- *
- * @returns {Object}
- */
-function createMap() {
- return Object.create(null);
-}
-
-var NODE_TYPE_ELEMENT = 1;
-var NODE_TYPE_ATTRIBUTE = 2;
-var NODE_TYPE_TEXT = 3;
-var NODE_TYPE_COMMENT = 8;
-var NODE_TYPE_DOCUMENT = 9;
-var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
-
-/**
- * @ngdoc type
- * @name angular.Module
- * @module ng
- * @description
- *
- * Interface for configuring angular {@link angular.module modules}.
- */
-
-function setupModuleLoader(window) {
-
- var $injectorMinErr = minErr('$injector');
- var ngMinErr = minErr('ng');
-
- function ensure(obj, name, factory) {
- return obj[name] || (obj[name] = factory());
- }
-
- var angular = ensure(window, 'angular', Object);
-
- // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
- angular.$$minErr = angular.$$minErr || minErr;
-
- return ensure(angular, 'module', function() {
- /** @type {Object.<string, angular.Module>} */
- var modules = {};
-
- /**
- * @ngdoc function
- * @name angular.module
- * @module ng
- * @description
- *
- * The `angular.module` is a global place for creating, registering and retrieving Angular
- * modules.
- * All modules (angular core or 3rd party) that should be available to an application must be
- * registered using this mechanism.
- *
- * Passing one argument retrieves an existing {@link angular.Module},
- * whereas passing more than one argument creates a new {@link angular.Module}
- *
- *
- * # Module
- *
- * A module is a collection of services, directives, controllers, filters, and configuration information.
- * `angular.module` is used to configure the {@link auto.$injector $injector}.
- *
- * ```js
- * // Create a new module
- * var myModule = angular.module('myModule', []);
- *
- * // register a new service
- * myModule.value('appName', 'MyCoolApp');
- *
- * // configure existing services inside initialization blocks.
- * myModule.config(['$locationProvider', function($locationProvider) {
- * // Configure existing providers
- * $locationProvider.hashPrefix('!');
- * }]);
- * ```
- *
- * Then you can create an injector and load your modules like this:
- *
- * ```js
- * var injector = angular.injector(['ng', 'myModule'])
- * ```
- *
- * However it's more likely that you'll just use
- * {@link ng.directive:ngApp ngApp} or
- * {@link angular.bootstrap} to simplify this process for you.
- *
- * @param {!string} name The name of the module to create or retrieve.
- * @param {!Array.<string>=} requires If specified then new module is being created. If
- * unspecified then the module is being retrieved for further configuration.
- * @param {Function=} configFn Optional configuration function for the module. Same as
- * {@link angular.Module#config Module#config()}.
- * @returns {angular.Module} new module with the {@link angular.Module} api.
- */
- return function module(name, requires, configFn) {
- var assertNotHasOwnProperty = function(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
- }
- };
-
- assertNotHasOwnProperty(name, 'module');
- if (requires && modules.hasOwnProperty(name)) {
- modules[name] = null;
- }
- return ensure(modules, name, function() {
- if (!requires) {
- throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
- "the module name or forgot to load it. If registering a module ensure that you " +
- "specify the dependencies as the second argument.", name);
- }
-
- /** @type {!Array.<Array.<*>>} */
- var invokeQueue = [];
-
- /** @type {!Array.<Function>} */
- var configBlocks = [];
-
- /** @type {!Array.<Function>} */
- var runBlocks = [];
-
- var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
-
- /** @type {angular.Module} */
- var moduleInstance = {
- // Private state
- _invokeQueue: invokeQueue,
- _configBlocks: configBlocks,
- _runBlocks: runBlocks,
-
- /**
- * @ngdoc property
- * @name angular.Module#requires
- * @module ng
- *
- * @description
- * Holds the list of modules which the injector will load before the current module is
- * loaded.
- */
- requires: requires,
-
- /**
- * @ngdoc property
- * @name angular.Module#name
- * @module ng
- *
- * @description
- * Name of the module.
- */
- name: name,
-
-
- /**
- * @ngdoc method
- * @name angular.Module#provider
- * @module ng
- * @param {string} name service name
- * @param {Function} providerType Construction function for creating new instance of the
- * service.
- * @description
- * See {@link auto.$provide#provider $provide.provider()}.
- */
- provider: invokeLaterAndSetModuleName('$provide', 'provider'),
-
- /**
- * @ngdoc method
- * @name angular.Module#factory
- * @module ng
- * @param {string} name service name
- * @param {Function} providerFunction Function for creating new instance of the service.
- * @description
- * See {@link auto.$provide#factory $provide.factory()}.
- */
- factory: invokeLaterAndSetModuleName('$provide', 'factory'),
-
- /**
- * @ngdoc method
- * @name angular.Module#service
- * @module ng
- * @param {string} name service name
- * @param {Function} constructor A constructor function that will be instantiated.
- * @description
- * See {@link auto.$provide#service $provide.service()}.
- */
- service: invokeLaterAndSetModuleName('$provide', 'service'),
-
- /**
- * @ngdoc method
- * @name angular.Module#value
- * @module ng
- * @param {string} name service name
- * @param {*} object Service instance object.
- * @description
- * See {@link auto.$provide#value $provide.value()}.
- */
- value: invokeLater('$provide', 'value'),
-
- /**
- * @ngdoc method
- * @name angular.Module#constant
- * @module ng
- * @param {string} name constant name
- * @param {*} object Constant value.
- * @description
- * Because the constants are fixed, they get applied before other provide methods.
- * See {@link auto.$provide#constant $provide.constant()}.
- */
- constant: invokeLater('$provide', 'constant', 'unshift'),
-
- /**
- * @ngdoc method
- * @name angular.Module#decorator
- * @module ng
- * @param {string} The name of the service to decorate.
- * @param {Function} This function will be invoked when the service needs to be
- * instantiated and should return the decorated service instance.
- * @description
- * See {@link auto.$provide#decorator $provide.decorator()}.
- */
- decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
-
- /**
- * @ngdoc method
- * @name angular.Module#animation
- * @module ng
- * @param {string} name animation name
- * @param {Function} animationFactory Factory function for creating new instance of an
- * animation.
- * @description
- *
- * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
- *
- *
- * Defines an animation hook that can be later used with
- * {@link $animate $animate} service and directives that use this service.
- *
- * ```js
- * module.animation('.animation-name', function($inject1, $inject2) {
- * return {
- * eventName : function(element, done) {
- * //code to run the animation
- * //once complete, then run done()
- * return function cancellationFunction(element) {
- * //code to cancel the animation
- * }
- * }
- * }
- * })
- * ```
- *
- * See {@link ng.$animateProvider#register $animateProvider.register()} and
- * {@link ngAnimate ngAnimate module} for more information.
- */
- animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#filter
- * @module ng
- * @param {string} name Filter name - this must be a valid angular expression identifier
- * @param {Function} filterFactory Factory function for creating new instance of filter.
- * @description
- * See {@link ng.$filterProvider#register $filterProvider.register()}.
- *
- * <div class="alert alert-warning">
- * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
- * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
- * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
- * (`myapp_subsection_filterx`).
- * </div>
- */
- filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#controller
- * @module ng
- * @param {string|Object} name Controller name, or an object map of controllers where the
- * keys are the names and the values are the constructors.
- * @param {Function} constructor Controller constructor function.
- * @description
- * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
- */
- controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#directive
- * @module ng
- * @param {string|Object} name Directive name, or an object map of directives where the
- * keys are the names and the values are the factories.
- * @param {Function} directiveFactory Factory function for creating new instance of
- * directives.
- * @description
- * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
- */
- directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
-
- /**
- * @ngdoc method
- * @name angular.Module#component
- * @module ng
- * @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
- * @param {Object} options Component definition object (a simplified
- * {@link ng.$compile#directive-definition-object directive definition object})
- *
- * @description
- * See {@link ng.$compileProvider#component $compileProvider.component()}.
- */
- component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
-
- /**
- * @ngdoc method
- * @name angular.Module#config
- * @module ng
- * @param {Function} configFn Execute this function on module load. Useful for service
- * configuration.
- * @description
- * Use this method to register work which needs to be performed on module loading.
- * For more about how to configure services, see
- * {@link providers#provider-recipe Provider Recipe}.
- */
- config: config,
-
- /**
- * @ngdoc method
- * @name angular.Module#run
- * @module ng
- * @param {Function} initializationFn Execute this function after injector creation.
- * Useful for application initialization.
- * @description
- * Use this method to register work which should be performed when the injector is done
- * loading all modules.
- */
- run: function(block) {
- runBlocks.push(block);
- return this;
- }
- };
-
- if (configFn) {
- config(configFn);
- }
-
- return moduleInstance;
-
- /**
- * @param {string} provider
- * @param {string} method
- * @param {String=} insertMethod
- * @returns {angular.Module}
- */
- function invokeLater(provider, method, insertMethod, queue) {
- if (!queue) queue = invokeQueue;
- return function() {
- queue[insertMethod || 'push']([provider, method, arguments]);
- return moduleInstance;
- };
- }
-
- /**
- * @param {string} provider
- * @param {string} method
- * @returns {angular.Module}
- */
- function invokeLaterAndSetModuleName(provider, method) {
- return function(recipeName, factoryFunction) {
- if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
- invokeQueue.push([provider, method, arguments]);
- return moduleInstance;
- };
- }
- });
- };
- });
-
-}
-
-/* global: toDebugString: true */
-
-function serializeObject(obj) {
- var seen = [];
-
- return JSON.stringify(obj, function(key, val) {
- val = toJsonReplacer(key, val);
- if (isObject(val)) {
-
- if (seen.indexOf(val) >= 0) return '...';
-
- seen.push(val);
- }
- return val;
- });
-}
-
-function toDebugString(obj) {
- if (typeof obj === 'function') {
- return obj.toString().replace(/ \{[\s\S]*$/, '');
- } else if (isUndefined(obj)) {
- return 'undefined';
- } else if (typeof obj !== 'string') {
- return serializeObject(obj);
- }
- return obj;
-}
-
-/* global angularModule: true,
- version: true,
-
- $CompileProvider,
-
- htmlAnchorDirective,
- inputDirective,
- inputDirective,
- formDirective,
- scriptDirective,
- selectDirective,
- styleDirective,
- optionDirective,
- ngBindDirective,
- ngBindHtmlDirective,
- ngBindTemplateDirective,
- ngClassDirective,
- ngClassEvenDirective,
- ngClassOddDirective,
- ngCloakDirective,
- ngControllerDirective,
- ngFormDirective,
- ngHideDirective,
- ngIfDirective,
- ngIncludeDirective,
- ngIncludeFillContentDirective,
- ngInitDirective,
- ngNonBindableDirective,
- ngPluralizeDirective,
- ngRepeatDirective,
- ngShowDirective,
- ngStyleDirective,
- ngSwitchDirective,
- ngSwitchWhenDirective,
- ngSwitchDefaultDirective,
- ngOptionsDirective,
- ngTranscludeDirective,
- ngModelDirective,
- ngListDirective,
- ngChangeDirective,
- patternDirective,
- patternDirective,
- requiredDirective,
- requiredDirective,
- minlengthDirective,
- minlengthDirective,
- maxlengthDirective,
- maxlengthDirective,
- ngValueDirective,
- ngModelOptionsDirective,
- ngAttributeAliasDirectives,
- ngEventDirectives,
-
- $AnchorScrollProvider,
- $AnimateProvider,
- $CoreAnimateCssProvider,
- $$CoreAnimateJsProvider,
- $$CoreAnimateQueueProvider,
- $$AnimateRunnerFactoryProvider,
- $$AnimateAsyncRunFactoryProvider,
- $BrowserProvider,
- $CacheFactoryProvider,
- $ControllerProvider,
- $DateProvider,
- $DocumentProvider,
- $ExceptionHandlerProvider,
- $FilterProvider,
- $$ForceReflowProvider,
- $InterpolateProvider,
- $IntervalProvider,
- $$HashMapProvider,
- $HttpProvider,
- $HttpParamSerializerProvider,
- $HttpParamSerializerJQLikeProvider,
- $HttpBackendProvider,
- $xhrFactoryProvider,
- $LocationProvider,
- $LogProvider,
- $ParseProvider,
- $RootScopeProvider,
- $QProvider,
- $$QProvider,
- $$SanitizeUriProvider,
- $SceProvider,
- $SceDelegateProvider,
- $SnifferProvider,
- $TemplateCacheProvider,
- $TemplateRequestProvider,
- $$TestabilityProvider,
- $TimeoutProvider,
- $$RAFProvider,
- $WindowProvider,
- $$jqLiteProvider,
- $$CookieReaderProvider
-*/
-
-
-/**
- * @ngdoc object
- * @name angular.version
- * @module ng
- * @description
- * An object that contains information about the current AngularJS version.
- *
- * This object has the following properties:
- *
- * - `full` – `{string}` – Full version string, such as "0.9.18".
- * - `major` – `{number}` – Major version number, such as "0".
- * - `minor` – `{number}` – Minor version number, such as "9".
- * - `dot` – `{number}` – Dot version number, such as "18".
- * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
- */
-var version = {
- full: '1.5.0', // all of these placeholder strings will be replaced by grunt's
- major: 1, // package task
- minor: 5,
- dot: 0,
- codeName: 'ennoblement-facilitation'
-};
-
-
-function publishExternalAPI(angular) {
- extend(angular, {
- 'bootstrap': bootstrap,
- 'copy': copy,
- 'extend': extend,
- 'merge': merge,
- 'equals': equals,
- 'element': jqLite,
- 'forEach': forEach,
- 'injector': createInjector,
- 'noop': noop,
- 'bind': bind,
- 'toJson': toJson,
- 'fromJson': fromJson,
- 'identity': identity,
- 'isUndefined': isUndefined,
- 'isDefined': isDefined,
- 'isString': isString,
- 'isFunction': isFunction,
- 'isObject': isObject,
- 'isNumber': isNumber,
- 'isElement': isElement,
- 'isArray': isArray,
- 'version': version,
- 'isDate': isDate,
- 'lowercase': lowercase,
- 'uppercase': uppercase,
- 'callbacks': {counter: 0},
- 'getTestability': getTestability,
- '$$minErr': minErr,
- '$$csp': csp,
- 'reloadWithDebugInfo': reloadWithDebugInfo
- });
-
- angularModule = setupModuleLoader(window);
-
- angularModule('ng', ['ngLocale'], ['$provide',
- function ngModule($provide) {
- // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
- $provide.provider({
- $$sanitizeUri: $$SanitizeUriProvider
- });
- $provide.provider('$compile', $CompileProvider).
- directive({
- a: htmlAnchorDirective,
- input: inputDirective,
- textarea: inputDirective,
- form: formDirective,
- script: scriptDirective,
- select: selectDirective,
- style: styleDirective,
- option: optionDirective,
- ngBind: ngBindDirective,
- ngBindHtml: ngBindHtmlDirective,
- ngBindTemplate: ngBindTemplateDirective,
- ngClass: ngClassDirective,
- ngClassEven: ngClassEvenDirective,
- ngClassOdd: ngClassOddDirective,
- ngCloak: ngCloakDirective,
- ngController: ngControllerDirective,
- ngForm: ngFormDirective,
- ngHide: ngHideDirective,
- ngIf: ngIfDirective,
- ngInclude: ngIncludeDirective,
- ngInit: ngInitDirective,
- ngNonBindable: ngNonBindableDirective,
- ngPluralize: ngPluralizeDirective,
- ngRepeat: ngRepeatDirective,
- ngShow: ngShowDirective,
- ngStyle: ngStyleDirective,
- ngSwitch: ngSwitchDirective,
- ngSwitchWhen: ngSwitchWhenDirective,
- ngSwitchDefault: ngSwitchDefaultDirective,
- ngOptions: ngOptionsDirective,
- ngTransclude: ngTranscludeDirective,
- ngModel: ngModelDirective,
- ngList: ngListDirective,
- ngChange: ngChangeDirective,
- pattern: patternDirective,
- ngPattern: patternDirective,
- required: requiredDirective,
- ngRequired: requiredDirective,
- minlength: minlengthDirective,
- ngMinlength: minlengthDirective,
- maxlength: maxlengthDirective,
- ngMaxlength: maxlengthDirective,
- ngValue: ngValueDirective,
- ngModelOptions: ngModelOptionsDirective
- }).
- directive({
- ngInclude: ngIncludeFillContentDirective
- }).
- directive(ngAttributeAliasDirectives).
- directive(ngEventDirectives);
- $provide.provider({
- $anchorScroll: $AnchorScrollProvider,
- $animate: $AnimateProvider,
- $animateCss: $CoreAnimateCssProvider,
- $$animateJs: $$CoreAnimateJsProvider,
- $$animateQueue: $$CoreAnimateQueueProvider,
- $$AnimateRunner: $$AnimateRunnerFactoryProvider,
- $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
- $browser: $BrowserProvider,
- $cacheFactory: $CacheFactoryProvider,
- $controller: $ControllerProvider,
- $document: $DocumentProvider,
- $exceptionHandler: $ExceptionHandlerProvider,
- $filter: $FilterProvider,
- $$forceReflow: $$ForceReflowProvider,
- $interpolate: $InterpolateProvider,
- $interval: $IntervalProvider,
- $http: $HttpProvider,
- $httpParamSerializer: $HttpParamSerializerProvider,
- $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
- $httpBackend: $HttpBackendProvider,
- $xhrFactory: $xhrFactoryProvider,
- $location: $LocationProvider,
- $log: $LogProvider,
- $parse: $ParseProvider,
- $rootScope: $RootScopeProvider,
- $q: $QProvider,
- $$q: $$QProvider,
- $sce: $SceProvider,
- $sceDelegate: $SceDelegateProvider,
- $sniffer: $SnifferProvider,
- $templateCache: $TemplateCacheProvider,
- $templateRequest: $TemplateRequestProvider,
- $$testability: $$TestabilityProvider,
- $timeout: $TimeoutProvider,
- $window: $WindowProvider,
- $$rAF: $$RAFProvider,
- $$jqLite: $$jqLiteProvider,
- $$HashMap: $$HashMapProvider,
- $$cookieReader: $$CookieReaderProvider
- });
- }
- ]);
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/* global JQLitePrototype: true,
- addEventListenerFn: true,
- removeEventListenerFn: true,
- BOOLEAN_ATTR: true,
- ALIASED_ATTR: true,
-*/
-
-//////////////////////////////////
-//JQLite
-//////////////////////////////////
-
-/**
- * @ngdoc function
- * @name angular.element
- * @module ng
- * @kind function
- *
- * @description
- * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
- *
- * If jQuery is available, `angular.element` is an alias for the
- * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
- * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or **jqLite**.
- *
- * jqLite is a tiny, API-compatible subset of jQuery that allows
- * Angular to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most
- * commonly needed functionality with the goal of having a very small footprint.
- *
- * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the
- * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a
- * specific version of jQuery if multiple versions exist on the page.
- *
- * <div class="alert alert-info">**Note:** All element references in Angular are always wrapped with jQuery or
- * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>
- *
- * <div class="alert alert-warning">**Note:** Keep in mind that this function will not find elements
- * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`
- * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>
- *
- * ## Angular's jqLite
- * jqLite provides only the following jQuery methods:
- *
- * - [`addClass()`](http://api.jquery.com/addClass/)
- * - [`after()`](http://api.jquery.com/after/)
- * - [`append()`](http://api.jquery.com/append/)
- * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
- * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
- * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
- * - [`clone()`](http://api.jquery.com/clone/)
- * - [`contents()`](http://api.jquery.com/contents/)
- * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.
- * As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.
- * - [`data()`](http://api.jquery.com/data/)
- * - [`detach()`](http://api.jquery.com/detach/)
- * - [`empty()`](http://api.jquery.com/empty/)
- * - [`eq()`](http://api.jquery.com/eq/)
- * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
- * - [`hasClass()`](http://api.jquery.com/hasClass/)
- * - [`html()`](http://api.jquery.com/html/)
- * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
- * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
- * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter
- * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
- * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
- * - [`prepend()`](http://api.jquery.com/prepend/)
- * - [`prop()`](http://api.jquery.com/prop/)
- * - [`ready()`](http://api.jquery.com/ready/)
- * - [`remove()`](http://api.jquery.com/remove/)
- * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
- * - [`removeClass()`](http://api.jquery.com/removeClass/)
- * - [`removeData()`](http://api.jquery.com/removeData/)
- * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
- * - [`text()`](http://api.jquery.com/text/)
- * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
- * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
- * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces or event object as parameter
- * - [`val()`](http://api.jquery.com/val/)
- * - [`wrap()`](http://api.jquery.com/wrap/)
- *
- * ## jQuery/jqLite Extras
- * Angular also provides the following additional methods and events to both jQuery and jqLite:
- *
- * ### Events
- * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
- * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
- * element before it is removed.
- *
- * ### Methods
- * - `controller(name)` - retrieves the controller of the current element or its parent. By default
- * retrieves controller associated with the `ngController` directive. If `name` is provided as
- * camelCase directive name, then the controller for this directive will be retrieved (e.g.
- * `'ngModel'`).
- * - `injector()` - retrieves the injector of the current element or its parent.
- * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
- * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
- * be enabled.
- * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
- * current element. This getter should be used only on elements that contain a directive which starts a new isolate
- * scope. Calling `scope()` on this element always returns the original non-isolate scope.
- * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
- * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
- * parent element is reached.
- *
- * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
- * @returns {Object} jQuery object.
- */
-
-JQLite.expando = 'ng339';
-
-var jqCache = JQLite.cache = {},
- jqId = 1,
- addEventListenerFn = function(element, type, fn) {
- element.addEventListener(type, fn, false);
- },
- removeEventListenerFn = function(element, type, fn) {
- element.removeEventListener(type, fn, false);
- };
-
-/*
- * !!! This is an undocumented "private" function !!!
- */
-JQLite._data = function(node) {
- //jQuery always returns an object on cache miss
- return this.cache[node[this.expando]] || {};
-};
-
-function jqNextId() { return ++jqId; }
-
-
-var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
-var MOZ_HACK_REGEXP = /^moz([A-Z])/;
-var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
-var jqLiteMinErr = minErr('jqLite');
-
-/**
- * Converts snake_case to camelCase.
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function camelCase(name) {
- return name.
- replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
- return offset ? letter.toUpperCase() : letter;
- }).
- replace(MOZ_HACK_REGEXP, 'Moz$1');
-}
-
-var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/;
-var HTML_REGEXP = /<|&#?\w+;/;
-var TAG_NAME_REGEXP = /<([\w:-]+)/;
-var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi;
-
-var wrapMap = {
- 'option': [1, '<select multiple="multiple">', '</select>'],
-
- 'thead': [1, '<table>', '</table>'],
- 'col': [2, '<table><colgroup>', '</colgroup></table>'],
- 'tr': [2, '<table><tbody>', '</tbody></table>'],
- 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
- '_default': [0, "", ""]
-};
-
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-
-function jqLiteIsTextNode(html) {
- return !HTML_REGEXP.test(html);
-}
-
-function jqLiteAcceptsData(node) {
- // The window object can accept data but has no nodeType
- // Otherwise we are only interested in elements (1) and documents (9)
- var nodeType = node.nodeType;
- return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
-}
-
-function jqLiteHasData(node) {
- for (var key in jqCache[node.ng339]) {
- return true;
- }
- return false;
-}
-
-function jqLiteCleanData(nodes) {
- for (var i = 0, ii = nodes.length; i < ii; i++) {
- jqLiteRemoveData(nodes[i]);
- }
-}
-
-function jqLiteBuildFragment(html, context) {
- var tmp, tag, wrap,
- fragment = context.createDocumentFragment(),
- nodes = [], i;
-
- if (jqLiteIsTextNode(html)) {
- // Convert non-html into a text node
- nodes.push(context.createTextNode(html));
- } else {
- // Convert html into DOM nodes
- tmp = tmp || fragment.appendChild(context.createElement("div"));
- tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
- wrap = wrapMap[tag] || wrapMap._default;
- tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
-
- // Descend through wrappers to the right content
- i = wrap[0];
- while (i--) {
- tmp = tmp.lastChild;
- }
-
- nodes = concat(nodes, tmp.childNodes);
-
- tmp = fragment.firstChild;
- tmp.textContent = "";
- }
-
- // Remove wrapper from fragment
- fragment.textContent = "";
- fragment.innerHTML = ""; // Clear inner HTML
- forEach(nodes, function(node) {
- fragment.appendChild(node);
- });
-
- return fragment;
-}
-
-function jqLiteParseHTML(html, context) {
- context = context || document;
- var parsed;
-
- if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
- return [context.createElement(parsed[1])];
- }
-
- if ((parsed = jqLiteBuildFragment(html, context))) {
- return parsed.childNodes;
- }
-
- return [];
-}
-
-function jqLiteWrapNode(node, wrapper) {
- var parent = node.parentNode;
-
- if (parent) {
- parent.replaceChild(wrapper, node);
- }
-
- wrapper.appendChild(node);
-}
-
-
-// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
-var jqLiteContains = Node.prototype.contains || function(arg) {
- // jshint bitwise: false
- return !!(this.compareDocumentPosition(arg) & 16);
- // jshint bitwise: true
-};
-
-/////////////////////////////////////////////
-function JQLite(element) {
- if (element instanceof JQLite) {
- return element;
- }
-
- var argIsString;
-
- if (isString(element)) {
- element = trim(element);
- argIsString = true;
- }
- if (!(this instanceof JQLite)) {
- if (argIsString && element.charAt(0) != '<') {
- throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
- }
- return new JQLite(element);
- }
-
- if (argIsString) {
- jqLiteAddNodes(this, jqLiteParseHTML(element));
- } else {
- jqLiteAddNodes(this, element);
- }
-}
-
-function jqLiteClone(element) {
- return element.cloneNode(true);
-}
-
-function jqLiteDealoc(element, onlyDescendants) {
- if (!onlyDescendants) jqLiteRemoveData(element);
-
- if (element.querySelectorAll) {
- var descendants = element.querySelectorAll('*');
- for (var i = 0, l = descendants.length; i < l; i++) {
- jqLiteRemoveData(descendants[i]);
- }
- }
-}
-
-function jqLiteOff(element, type, fn, unsupported) {
- if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
-
- var expandoStore = jqLiteExpandoStore(element);
- var events = expandoStore && expandoStore.events;
- var handle = expandoStore && expandoStore.handle;
-
- if (!handle) return; //no listeners registered
-
- if (!type) {
- for (type in events) {
- if (type !== '$destroy') {
- removeEventListenerFn(element, type, handle);
- }
- delete events[type];
- }
- } else {
-
- var removeHandler = function(type) {
- var listenerFns = events[type];
- if (isDefined(fn)) {
- arrayRemove(listenerFns || [], fn);
- }
- if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {
- removeEventListenerFn(element, type, handle);
- delete events[type];
- }
- };
-
- forEach(type.split(' '), function(type) {
- removeHandler(type);
- if (MOUSE_EVENT_MAP[type]) {
- removeHandler(MOUSE_EVENT_MAP[type]);
- }
- });
- }
-}
-
-function jqLiteRemoveData(element, name) {
- var expandoId = element.ng339;
- var expandoStore = expandoId && jqCache[expandoId];
-
- if (expandoStore) {
- if (name) {
- delete expandoStore.data[name];
- return;
- }
-
- if (expandoStore.handle) {
- if (expandoStore.events.$destroy) {
- expandoStore.handle({}, '$destroy');
- }
- jqLiteOff(element);
- }
- delete jqCache[expandoId];
- element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
- }
-}
-
-
-function jqLiteExpandoStore(element, createIfNecessary) {
- var expandoId = element.ng339,
- expandoStore = expandoId && jqCache[expandoId];
-
- if (createIfNecessary && !expandoStore) {
- element.ng339 = expandoId = jqNextId();
- expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
- }
-
- return expandoStore;
-}
-
-
-function jqLiteData(element, key, value) {
- if (jqLiteAcceptsData(element)) {
-
- var isSimpleSetter = isDefined(value);
- var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
- var massGetter = !key;
- var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
- var data = expandoStore && expandoStore.data;
-
- if (isSimpleSetter) { // data('key', value)
- data[key] = value;
- } else {
- if (massGetter) { // data()
- return data;
- } else {
- if (isSimpleGetter) { // data('key')
- // don't force creation of expandoStore if it doesn't exist yet
- return data && data[key];
- } else { // mass-setter: data({key1: val1, key2: val2})
- extend(data, key);
- }
- }
- }
- }
-}
-
-function jqLiteHasClass(element, selector) {
- if (!element.getAttribute) return false;
- return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
- indexOf(" " + selector + " ") > -1);
-}
-
-function jqLiteRemoveClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- forEach(cssClasses.split(' '), function(cssClass) {
- element.setAttribute('class', trim(
- (" " + (element.getAttribute('class') || '') + " ")
- .replace(/[\n\t]/g, " ")
- .replace(" " + trim(cssClass) + " ", " "))
- );
- });
- }
-}
-
-function jqLiteAddClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
- .replace(/[\n\t]/g, " ");
-
- forEach(cssClasses.split(' '), function(cssClass) {
- cssClass = trim(cssClass);
- if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
- existingClasses += cssClass + ' ';
- }
- });
-
- element.setAttribute('class', trim(existingClasses));
- }
-}
-
-
-function jqLiteAddNodes(root, elements) {
- // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
-
- if (elements) {
-
- // if a Node (the most common case)
- if (elements.nodeType) {
- root[root.length++] = elements;
- } else {
- var length = elements.length;
-
- // if an Array or NodeList and not a Window
- if (typeof length === 'number' && elements.window !== elements) {
- if (length) {
- for (var i = 0; i < length; i++) {
- root[root.length++] = elements[i];
- }
- }
- } else {
- root[root.length++] = elements;
- }
- }
- }
-}
-
-
-function jqLiteController(element, name) {
- return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
-}
-
-function jqLiteInheritedData(element, name, value) {
- // if element is the document object work with the html element instead
- // this makes $(document).scope() possible
- if (element.nodeType == NODE_TYPE_DOCUMENT) {
- element = element.documentElement;
- }
- var names = isArray(name) ? name : [name];
-
- while (element) {
- for (var i = 0, ii = names.length; i < ii; i++) {
- if (isDefined(value = jqLite.data(element, names[i]))) return value;
- }
-
- // If dealing with a document fragment node with a host element, and no parent, use the host
- // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
- // to lookup parent controllers.
- element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
- }
-}
-
-function jqLiteEmpty(element) {
- jqLiteDealoc(element, true);
- while (element.firstChild) {
- element.removeChild(element.firstChild);
- }
-}
-
-function jqLiteRemove(element, keepData) {
- if (!keepData) jqLiteDealoc(element);
- var parent = element.parentNode;
- if (parent) parent.removeChild(element);
-}
-
-
-function jqLiteDocumentLoaded(action, win) {
- win = win || window;
- if (win.document.readyState === 'complete') {
- // Force the action to be run async for consistent behavior
- // from the action's point of view
- // i.e. it will definitely not be in a $apply
- win.setTimeout(action);
- } else {
- // No need to unbind this handler as load is only ever called once
- jqLite(win).on('load', action);
- }
-}
-
-//////////////////////////////////////////
-// Functions which are declared directly.
-//////////////////////////////////////////
-var JQLitePrototype = JQLite.prototype = {
- ready: function(fn) {
- var fired = false;
-
- function trigger() {
- if (fired) return;
- fired = true;
- fn();
- }
-
- // check if document is already loaded
- if (document.readyState === 'complete') {
- setTimeout(trigger);
- } else {
- this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
- // we can not use jqLite since we are not done loading and jQuery could be loaded later.
- // jshint -W064
- JQLite(window).on('load', trigger); // fallback to window.onload for others
- // jshint +W064
- }
- },
- toString: function() {
- var value = [];
- forEach(this, function(e) { value.push('' + e);});
- return '[' + value.join(', ') + ']';
- },
-
- eq: function(index) {
- return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
- },
-
- length: 0,
- push: push,
- sort: [].sort,
- splice: [].splice
-};
-
-//////////////////////////////////////////
-// Functions iterating getter/setters.
-// these functions return self on setter and
-// value on get.
-//////////////////////////////////////////
-var BOOLEAN_ATTR = {};
-forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
- BOOLEAN_ATTR[lowercase(value)] = value;
-});
-var BOOLEAN_ELEMENTS = {};
-forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
- BOOLEAN_ELEMENTS[value] = true;
-});
-var ALIASED_ATTR = {
- 'ngMinlength': 'minlength',
- 'ngMaxlength': 'maxlength',
- 'ngMin': 'min',
- 'ngMax': 'max',
- 'ngPattern': 'pattern'
-};
-
-function getBooleanAttrName(element, name) {
- // check dom last since we will most likely fail on name
- var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
-
- // booleanAttr is here twice to minimize DOM access
- return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
-}
-
-function getAliasedAttrName(name) {
- return ALIASED_ATTR[name];
-}
-
-forEach({
- data: jqLiteData,
- removeData: jqLiteRemoveData,
- hasData: jqLiteHasData,
- cleanData: jqLiteCleanData
-}, function(fn, name) {
- JQLite[name] = fn;
-});
-
-forEach({
- data: jqLiteData,
- inheritedData: jqLiteInheritedData,
-
- scope: function(element) {
- // Can't use jqLiteData here directly so we stay compatible with jQuery!
- return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
- },
-
- isolateScope: function(element) {
- // Can't use jqLiteData here directly so we stay compatible with jQuery!
- return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
- },
-
- controller: jqLiteController,
-
- injector: function(element) {
- return jqLiteInheritedData(element, '$injector');
- },
-
- removeAttr: function(element, name) {
- element.removeAttribute(name);
- },
-
- hasClass: jqLiteHasClass,
-
- css: function(element, name, value) {
- name = camelCase(name);
-
- if (isDefined(value)) {
- element.style[name] = value;
- } else {
- return element.style[name];
- }
- },
-
- attr: function(element, name, value) {
- var nodeType = element.nodeType;
- if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
- return;
- }
- var lowercasedName = lowercase(name);
- if (BOOLEAN_ATTR[lowercasedName]) {
- if (isDefined(value)) {
- if (!!value) {
- element[name] = true;
- element.setAttribute(name, lowercasedName);
- } else {
- element[name] = false;
- element.removeAttribute(lowercasedName);
- }
- } else {
- return (element[name] ||
- (element.attributes.getNamedItem(name) || noop).specified)
- ? lowercasedName
- : undefined;
- }
- } else if (isDefined(value)) {
- element.setAttribute(name, value);
- } else if (element.getAttribute) {
- // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
- // some elements (e.g. Document) don't have get attribute, so return undefined
- var ret = element.getAttribute(name, 2);
- // normalize non-existing attributes to undefined (as jQuery)
- return ret === null ? undefined : ret;
- }
- },
-
- prop: function(element, name, value) {
- if (isDefined(value)) {
- element[name] = value;
- } else {
- return element[name];
- }
- },
-
- text: (function() {
- getText.$dv = '';
- return getText;
-
- function getText(element, value) {
- if (isUndefined(value)) {
- var nodeType = element.nodeType;
- return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
- }
- element.textContent = value;
- }
- })(),
-
- val: function(element, value) {
- if (isUndefined(value)) {
- if (element.multiple && nodeName_(element) === 'select') {
- var result = [];
- forEach(element.options, function(option) {
- if (option.selected) {
- result.push(option.value || option.text);
- }
- });
- return result.length === 0 ? null : result;
- }
- return element.value;
- }
- element.value = value;
- },
-
- html: function(element, value) {
- if (isUndefined(value)) {
- return element.innerHTML;
- }
- jqLiteDealoc(element, true);
- element.innerHTML = value;
- },
-
- empty: jqLiteEmpty
-}, function(fn, name) {
- /**
- * Properties: writes return selection, reads return first value
- */
- JQLite.prototype[name] = function(arg1, arg2) {
- var i, key;
- var nodeCount = this.length;
-
- // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
- // in a way that survives minification.
- // jqLiteEmpty takes no arguments but is a setter.
- if (fn !== jqLiteEmpty &&
- (isUndefined((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {
- if (isObject(arg1)) {
-
- // we are a write, but the object properties are the key/values
- for (i = 0; i < nodeCount; i++) {
- if (fn === jqLiteData) {
- // data() takes the whole object in jQuery
- fn(this[i], arg1);
- } else {
- for (key in arg1) {
- fn(this[i], key, arg1[key]);
- }
- }
- }
- // return self for chaining
- return this;
- } else {
- // we are a read, so read the first child.
- // TODO: do we still need this?
- var value = fn.$dv;
- // Only if we have $dv do we iterate over all, otherwise it is just the first element.
- var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;
- for (var j = 0; j < jj; j++) {
- var nodeValue = fn(this[j], arg1, arg2);
- value = value ? value + nodeValue : nodeValue;
- }
- return value;
- }
- } else {
- // we are a write, so apply to all children
- for (i = 0; i < nodeCount; i++) {
- fn(this[i], arg1, arg2);
- }
- // return self for chaining
- return this;
- }
- };
-});
-
-function createEventHandler(element, events) {
- var eventHandler = function(event, type) {
- // jQuery specific api
- event.isDefaultPrevented = function() {
- return event.defaultPrevented;
- };
-
- var eventFns = events[type || event.type];
- var eventFnsLength = eventFns ? eventFns.length : 0;
-
- if (!eventFnsLength) return;
-
- if (isUndefined(event.immediatePropagationStopped)) {
- var originalStopImmediatePropagation = event.stopImmediatePropagation;
- event.stopImmediatePropagation = function() {
- event.immediatePropagationStopped = true;
-
- if (event.stopPropagation) {
- event.stopPropagation();
- }
-
- if (originalStopImmediatePropagation) {
- originalStopImmediatePropagation.call(event);
- }
- };
- }
-
- event.isImmediatePropagationStopped = function() {
- return event.immediatePropagationStopped === true;
- };
-
- // Some events have special handlers that wrap the real handler
- var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;
-
- // Copy event handlers in case event handlers array is modified during execution.
- if ((eventFnsLength > 1)) {
- eventFns = shallowCopy(eventFns);
- }
-
- for (var i = 0; i < eventFnsLength; i++) {
- if (!event.isImmediatePropagationStopped()) {
- handlerWrapper(element, event, eventFns[i]);
- }
- }
- };
-
- // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
- // events on `element`
- eventHandler.elem = element;
- return eventHandler;
-}
-
-function defaultHandlerWrapper(element, event, handler) {
- handler.call(element, event);
-}
-
-function specialMouseHandlerWrapper(target, event, handler) {
- // Refer to jQuery's implementation of mouseenter & mouseleave
- // Read about mouseenter and mouseleave:
- // http://www.quirksmode.org/js/events_mouse.html#link8
- var related = event.relatedTarget;
- // For mousenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if (!related || (related !== target && !jqLiteContains.call(target, related))) {
- handler.call(target, event);
- }
-}
-
-//////////////////////////////////////////
-// Functions iterating traversal.
-// These functions chain results into a single
-// selector.
-//////////////////////////////////////////
-forEach({
- removeData: jqLiteRemoveData,
-
- on: function jqLiteOn(element, type, fn, unsupported) {
- if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
-
- // Do not add event handlers to non-elements because they will not be cleaned up.
- if (!jqLiteAcceptsData(element)) {
- return;
- }
-
- var expandoStore = jqLiteExpandoStore(element, true);
- var events = expandoStore.events;
- var handle = expandoStore.handle;
-
- if (!handle) {
- handle = expandoStore.handle = createEventHandler(element, events);
- }
-
- // http://jsperf.com/string-indexof-vs-split
- var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
- var i = types.length;
-
- var addHandler = function(type, specialHandlerWrapper, noEventListener) {
- var eventFns = events[type];
-
- if (!eventFns) {
- eventFns = events[type] = [];
- eventFns.specialHandlerWrapper = specialHandlerWrapper;
- if (type !== '$destroy' && !noEventListener) {
- addEventListenerFn(element, type, handle);
- }
- }
-
- eventFns.push(fn);
- };
-
- while (i--) {
- type = types[i];
- if (MOUSE_EVENT_MAP[type]) {
- addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);
- addHandler(type, undefined, true);
- } else {
- addHandler(type);
- }
- }
- },
-
- off: jqLiteOff,
-
- one: function(element, type, fn) {
- element = jqLite(element);
-
- //add the listener twice so that when it is called
- //you can remove the original function and still be
- //able to call element.off(ev, fn) normally
- element.on(type, function onFn() {
- element.off(type, fn);
- element.off(type, onFn);
- });
- element.on(type, fn);
- },
-
- replaceWith: function(element, replaceNode) {
- var index, parent = element.parentNode;
- jqLiteDealoc(element);
- forEach(new JQLite(replaceNode), function(node) {
- if (index) {
- parent.insertBefore(node, index.nextSibling);
- } else {
- parent.replaceChild(node, element);
- }
- index = node;
- });
- },
-
- children: function(element) {
- var children = [];
- forEach(element.childNodes, function(element) {
- if (element.nodeType === NODE_TYPE_ELEMENT) {
- children.push(element);
- }
- });
- return children;
- },
-
- contents: function(element) {
- return element.contentDocument || element.childNodes || [];
- },
-
- append: function(element, node) {
- var nodeType = element.nodeType;
- if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
-
- node = new JQLite(node);
-
- for (var i = 0, ii = node.length; i < ii; i++) {
- var child = node[i];
- element.appendChild(child);
- }
- },
-
- prepend: function(element, node) {
- if (element.nodeType === NODE_TYPE_ELEMENT) {
- var index = element.firstChild;
- forEach(new JQLite(node), function(child) {
- element.insertBefore(child, index);
- });
- }
- },
-
- wrap: function(element, wrapNode) {
- jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);
- },
-
- remove: jqLiteRemove,
-
- detach: function(element) {
- jqLiteRemove(element, true);
- },
-
- after: function(element, newElement) {
- var index = element, parent = element.parentNode;
- newElement = new JQLite(newElement);
-
- for (var i = 0, ii = newElement.length; i < ii; i++) {
- var node = newElement[i];
- parent.insertBefore(node, index.nextSibling);
- index = node;
- }
- },
-
- addClass: jqLiteAddClass,
- removeClass: jqLiteRemoveClass,
-
- toggleClass: function(element, selector, condition) {
- if (selector) {
- forEach(selector.split(' '), function(className) {
- var classCondition = condition;
- if (isUndefined(classCondition)) {
- classCondition = !jqLiteHasClass(element, className);
- }
- (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
- });
- }
- },
-
- parent: function(element) {
- var parent = element.parentNode;
- return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
- },
-
- next: function(element) {
- return element.nextElementSibling;
- },
-
- find: function(element, selector) {
- if (element.getElementsByTagName) {
- return element.getElementsByTagName(selector);
- } else {
- return [];
- }
- },
-
- clone: jqLiteClone,
-
- triggerHandler: function(element, event, extraParameters) {
-
- var dummyEvent, eventFnsCopy, handlerArgs;
- var eventName = event.type || event;
- var expandoStore = jqLiteExpandoStore(element);
- var events = expandoStore && expandoStore.events;
- var eventFns = events && events[eventName];
-
- if (eventFns) {
- // Create a dummy event to pass to the handlers
- dummyEvent = {
- preventDefault: function() { this.defaultPrevented = true; },
- isDefaultPrevented: function() { return this.defaultPrevented === true; },
- stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
- isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
- stopPropagation: noop,
- type: eventName,
- target: element
- };
-
- // If a custom event was provided then extend our dummy event with it
- if (event.type) {
- dummyEvent = extend(dummyEvent, event);
- }
-
- // Copy event handlers in case event handlers array is modified during execution.
- eventFnsCopy = shallowCopy(eventFns);
- handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
-
- forEach(eventFnsCopy, function(fn) {
- if (!dummyEvent.isImmediatePropagationStopped()) {
- fn.apply(element, handlerArgs);
- }
- });
- }
- }
-}, function(fn, name) {
- /**
- * chaining functions
- */
- JQLite.prototype[name] = function(arg1, arg2, arg3) {
- var value;
-
- for (var i = 0, ii = this.length; i < ii; i++) {
- if (isUndefined(value)) {
- value = fn(this[i], arg1, arg2, arg3);
- if (isDefined(value)) {
- // any function which returns a value needs to be wrapped
- value = jqLite(value);
- }
- } else {
- jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
- }
- }
- return isDefined(value) ? value : this;
- };
-
- // bind legacy bind/unbind to on/off
- JQLite.prototype.bind = JQLite.prototype.on;
- JQLite.prototype.unbind = JQLite.prototype.off;
-});
-
-
-// Provider for private $$jqLite service
-function $$jqLiteProvider() {
- this.$get = function $$jqLite() {
- return extend(JQLite, {
- hasClass: function(node, classes) {
- if (node.attr) node = node[0];
- return jqLiteHasClass(node, classes);
- },
- addClass: function(node, classes) {
- if (node.attr) node = node[0];
- return jqLiteAddClass(node, classes);
- },
- removeClass: function(node, classes) {
- if (node.attr) node = node[0];
- return jqLiteRemoveClass(node, classes);
- }
- });
- };
-}
-
-/**
- * Computes a hash of an 'obj'.
- * Hash of a:
- * string is string
- * number is number as string
- * object is either result of calling $$hashKey function on the object or uniquely generated id,
- * that is also assigned to the $$hashKey property of the object.
- *
- * @param obj
- * @returns {string} hash string such that the same input will have the same hash string.
- * The resulting string key is in 'type:hashKey' format.
- */
-function hashKey(obj, nextUidFn) {
- var key = obj && obj.$$hashKey;
-
- if (key) {
- if (typeof key === 'function') {
- key = obj.$$hashKey();
- }
- return key;
- }
-
- var objType = typeof obj;
- if (objType == 'function' || (objType == 'object' && obj !== null)) {
- key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
- } else {
- key = objType + ':' + obj;
- }
-
- return key;
-}
-
-/**
- * HashMap which can use objects as keys
- */
-function HashMap(array, isolatedUid) {
- if (isolatedUid) {
- var uid = 0;
- this.nextUid = function() {
- return ++uid;
- };
- }
- forEach(array, this.put, this);
-}
-HashMap.prototype = {
- /**
- * Store key value pair
- * @param key key to store can be any type
- * @param value value to store can be any type
- */
- put: function(key, value) {
- this[hashKey(key, this.nextUid)] = value;
- },
-
- /**
- * @param key
- * @returns {Object} the value for the key
- */
- get: function(key) {
- return this[hashKey(key, this.nextUid)];
- },
-
- /**
- * Remove the key/value pair
- * @param key
- */
- remove: function(key) {
- var value = this[key = hashKey(key, this.nextUid)];
- delete this[key];
- return value;
- }
-};
-
-var $$HashMapProvider = [function() {
- this.$get = [function() {
- return HashMap;
- }];
-}];
-
-/**
- * @ngdoc function
- * @module ng
- * @name angular.injector
- * @kind function
- *
- * @description
- * Creates an injector object that can be used for retrieving services as well as for
- * dependency injection (see {@link guide/di dependency injection}).
- *
- * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
- * {@link angular.module}. The `ng` module must be explicitly added.
- * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
- * disallows argument name annotation inference.
- * @returns {injector} Injector object. See {@link auto.$injector $injector}.
- *
- * @example
- * Typical usage
- * ```js
- * // create an injector
- * var $injector = angular.injector(['ng']);
- *
- * // use the injector to kick off your application
- * // use the type inference to auto inject arguments, or use implicit injection
- * $injector.invoke(function($rootScope, $compile, $document) {
- * $compile($document)($rootScope);
- * $rootScope.$digest();
- * });
- * ```
- *
- * Sometimes you want to get access to the injector of a currently running Angular app
- * from outside Angular. Perhaps, you want to inject and compile some markup after the
- * application has been bootstrapped. You can do this using the extra `injector()` added
- * to JQuery/jqLite elements. See {@link angular.element}.
- *
- * *This is fairly rare but could be the case if a third party library is injecting the
- * markup.*
- *
- * In the following example a new block of HTML containing a `ng-controller`
- * directive is added to the end of the document body by JQuery. We then compile and link
- * it into the current AngularJS scope.
- *
- * ```js
- * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
- * $(document.body).append($div);
- *
- * angular.element(document).injector().invoke(function($compile) {
- * var scope = angular.element($div).scope();
- * $compile($div)(scope);
- * });
- * ```
- */
-
-
-/**
- * @ngdoc module
- * @name auto
- * @description
- *
- * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
- */
-
-var ARROW_ARG = /^([^\(]+?)=>/;
-var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;
-var FN_ARG_SPLIT = /,/;
-var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
-var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
-var $injectorMinErr = minErr('$injector');
-
-function extractArgs(fn) {
- var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
- args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
- return args;
-}
-
-function anonFn(fn) {
- // For anonymous functions, showing at the very least the function signature can help in
- // debugging.
- var args = extractArgs(fn);
- if (args) {
- return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
- }
- return 'fn';
-}
-
-function annotate(fn, strictDi, name) {
- var $inject,
- argDecl,
- last;
-
- if (typeof fn === 'function') {
- if (!($inject = fn.$inject)) {
- $inject = [];
- if (fn.length) {
- if (strictDi) {
- if (!isString(name) || !name) {
- name = fn.name || anonFn(fn);
- }
- throw $injectorMinErr('strictdi',
- '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
- }
- argDecl = extractArgs(fn);
- forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
- arg.replace(FN_ARG, function(all, underscore, name) {
- $inject.push(name);
- });
- });
- }
- fn.$inject = $inject;
- }
- } else if (isArray(fn)) {
- last = fn.length - 1;
- assertArgFn(fn[last], 'fn');
- $inject = fn.slice(0, last);
- } else {
- assertArgFn(fn, 'fn', true);
- }
- return $inject;
-}
-
-///////////////////////////////////////
-
-/**
- * @ngdoc service
- * @name $injector
- *
- * @description
- *
- * `$injector` is used to retrieve object instances as defined by
- * {@link auto.$provide provider}, instantiate types, invoke methods,
- * and load modules.
- *
- * The following always holds true:
- *
- * ```js
- * var $injector = angular.injector();
- * expect($injector.get('$injector')).toBe($injector);
- * expect($injector.invoke(function($injector) {
- * return $injector;
- * })).toBe($injector);
- * ```
- *
- * # Injection Function Annotation
- *
- * JavaScript does not have annotations, and annotations are needed for dependency injection. The
- * following are all valid ways of annotating function with injection arguments and are equivalent.
- *
- * ```js
- * // inferred (only works if code not minified/obfuscated)
- * $injector.invoke(function(serviceA){});
- *
- * // annotated
- * function explicit(serviceA) {};
- * explicit.$inject = ['serviceA'];
- * $injector.invoke(explicit);
- *
- * // inline
- * $injector.invoke(['serviceA', function(serviceA){}]);
- * ```
- *
- * ## Inference
- *
- * In JavaScript calling `toString()` on a function returns the function definition. The definition
- * can then be parsed and the function arguments can be extracted. This method of discovering
- * annotations is disallowed when the injector is in strict mode.
- * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
- * argument names.
- *
- * ## `$inject` Annotation
- * By adding an `$inject` property onto a function the injection parameters can be specified.
- *
- * ## Inline
- * As an array of injection names, where the last item in the array is the function to call.
- */
-
-/**
- * @ngdoc method
- * @name $injector#get
- *
- * @description
- * Return an instance of the service.
- *
- * @param {string} name The name of the instance to retrieve.
- * @param {string=} caller An optional string to provide the origin of the function call for error messages.
- * @return {*} The instance.
- */
-
-/**
- * @ngdoc method
- * @name $injector#invoke
- *
- * @description
- * Invoke the method and supply the method arguments from the `$injector`.
- *
- * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
- * injected according to the {@link guide/di $inject Annotation} rules.
- * @param {Object=} self The `this` for the invoked method.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- * object first, before the `$injector` is consulted.
- * @returns {*} the value returned by the invoked `fn` function.
- */
-
-/**
- * @ngdoc method
- * @name $injector#has
- *
- * @description
- * Allows the user to query if the particular service exists.
- *
- * @param {string} name Name of the service to query.
- * @returns {boolean} `true` if injector has given service.
- */
-
-/**
- * @ngdoc method
- * @name $injector#instantiate
- * @description
- * Create a new instance of JS type. The method takes a constructor function, invokes the new
- * operator, and supplies all of the arguments to the constructor function as specified by the
- * constructor annotation.
- *
- * @param {Function} Type Annotated constructor function.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- * object first, before the `$injector` is consulted.
- * @returns {Object} new instance of `Type`.
- */
-
-/**
- * @ngdoc method
- * @name $injector#annotate
- *
- * @description
- * Returns an array of service names which the function is requesting for injection. This API is
- * used by the injector to determine which services need to be injected into the function when the
- * function is invoked. There are three ways in which the function can be annotated with the needed
- * dependencies.
- *
- * # Argument names
- *
- * The simplest form is to extract the dependencies from the arguments of the function. This is done
- * by converting the function into a string using `toString()` method and extracting the argument
- * names.
- * ```js
- * // Given
- * function MyController($scope, $route) {
- * // ...
- * }
- *
- * // Then
- * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
- *
- * You can disallow this method by using strict injection mode.
- *
- * This method does not work with code minification / obfuscation. For this reason the following
- * annotation strategies are supported.
- *
- * # The `$inject` property
- *
- * If a function has an `$inject` property and its value is an array of strings, then the strings
- * represent names of services to be injected into the function.
- * ```js
- * // Given
- * var MyController = function(obfuscatedScope, obfuscatedRoute) {
- * // ...
- * }
- * // Define function dependencies
- * MyController['$inject'] = ['$scope', '$route'];
- *
- * // Then
- * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
- *
- * # The array notation
- *
- * It is often desirable to inline Injected functions and that's when setting the `$inject` property
- * is very inconvenient. In these situations using the array notation to specify the dependencies in
- * a way that survives minification is a better choice:
- *
- * ```js
- * // We wish to write this (not minification / obfuscation safe)
- * injector.invoke(function($compile, $rootScope) {
- * // ...
- * });
- *
- * // We are forced to write break inlining
- * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
- * // ...
- * };
- * tmpFn.$inject = ['$compile', '$rootScope'];
- * injector.invoke(tmpFn);
- *
- * // To better support inline function the inline annotation is supported
- * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
- * // ...
- * }]);
- *
- * // Therefore
- * expect(injector.annotate(
- * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
- * ).toEqual(['$compile', '$rootScope']);
- * ```
- *
- * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
- * be retrieved as described above.
- *
- * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
- *
- * @returns {Array.<string>} The names of the services which the function requires.
- */
-
-
-
-
-/**
- * @ngdoc service
- * @name $provide
- *
- * @description
- *
- * The {@link auto.$provide $provide} service has a number of methods for registering components
- * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
- * {@link angular.Module}.
- *
- * An Angular **service** is a singleton object created by a **service factory**. These **service
- * factories** are functions which, in turn, are created by a **service provider**.
- * The **service providers** are constructor functions. When instantiated they must contain a
- * property called `$get`, which holds the **service factory** function.
- *
- * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
- * correct **service provider**, instantiating it and then calling its `$get` **service factory**
- * function to get the instance of the **service**.
- *
- * Often services have no configuration options and there is no need to add methods to the service
- * provider. The provider will be no more than a constructor function with a `$get` property. For
- * these cases the {@link auto.$provide $provide} service has additional helper methods to register
- * services without specifying a provider.
- *
- * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
- * {@link auto.$injector $injector}
- * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
- * providers and services.
- * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
- * services, not providers.
- * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
- * that will be wrapped in a **service provider** object, whose `$get` property will contain the
- * given factory function.
- * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
- * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
- * a new object using the given constructor function.
- *
- * See the individual methods for more information and examples.
- */
-
-/**
- * @ngdoc method
- * @name $provide#provider
- * @description
- *
- * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
- * are constructor functions, whose instances are responsible for "providing" a factory for a
- * service.
- *
- * Service provider names start with the name of the service they provide followed by `Provider`.
- * For example, the {@link ng.$log $log} service has a provider called
- * {@link ng.$logProvider $logProvider}.
- *
- * Service provider objects can have additional methods which allow configuration of the provider
- * and its service. Importantly, you can configure what kind of service is created by the `$get`
- * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
- * method {@link ng.$logProvider#debugEnabled debugEnabled}
- * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
- * console or not.
- *
- * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
- 'Provider'` key.
- * @param {(Object|function())} provider If the provider is:
- *
- * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
- * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
- * - `Constructor`: a new instance of the provider will be created using
- * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
- *
- * @returns {Object} registered provider instance
-
- * @example
- *
- * The following example shows how to create a simple event tracking service and register it using
- * {@link auto.$provide#provider $provide.provider()}.
- *
- * ```js
- * // Define the eventTracker provider
- * function EventTrackerProvider() {
- * var trackingUrl = '/track';
- *
- * // A provider method for configuring where the tracked events should been saved
- * this.setTrackingUrl = function(url) {
- * trackingUrl = url;
- * };
- *
- * // The service factory function
- * this.$get = ['$http', function($http) {
- * var trackedEvents = {};
- * return {
- * // Call this to track an event
- * event: function(event) {
- * var count = trackedEvents[event] || 0;
- * count += 1;
- * trackedEvents[event] = count;
- * return count;
- * },
- * // Call this to save the tracked events to the trackingUrl
- * save: function() {
- * $http.post(trackingUrl, trackedEvents);
- * }
- * };
- * }];
- * }
- *
- * describe('eventTracker', function() {
- * var postSpy;
- *
- * beforeEach(module(function($provide) {
- * // Register the eventTracker provider
- * $provide.provider('eventTracker', EventTrackerProvider);
- * }));
- *
- * beforeEach(module(function(eventTrackerProvider) {
- * // Configure eventTracker provider
- * eventTrackerProvider.setTrackingUrl('/custom-track');
- * }));
- *
- * it('tracks events', inject(function(eventTracker) {
- * expect(eventTracker.event('login')).toEqual(1);
- * expect(eventTracker.event('login')).toEqual(2);
- * }));
- *
- * it('saves to the tracking url', inject(function(eventTracker, $http) {
- * postSpy = spyOn($http, 'post');
- * eventTracker.event('login');
- * eventTracker.save();
- * expect(postSpy).toHaveBeenCalled();
- * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
- * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
- * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
- * }));
- * });
- * ```
- */
-
-/**
- * @ngdoc method
- * @name $provide#factory
- * @description
- *
- * Register a **service factory**, which will be called to return the service instance.
- * This is short for registering a service where its provider consists of only a `$get` property,
- * which is the given service factory function.
- * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
- * configure your service in a provider.
- *
- * @param {string} name The name of the instance.
- * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
- * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service
- * ```js
- * $provide.factory('ping', ['$http', function($http) {
- * return function ping() {
- * return $http.send('/ping');
- * };
- * }]);
- * ```
- * You would then inject and use this service like this:
- * ```js
- * someModule.controller('Ctrl', ['ping', function(ping) {
- * ping();
- * }]);
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#service
- * @description
- *
- * Register a **service constructor**, which will be invoked with `new` to create the service
- * instance.
- * This is short for registering a service where its provider's `$get` property is a factory
- * function that returns an instance instantiated by the injector from the service constructor
- * function.
- *
- * Internally it looks a bit like this:
- *
- * ```
- * {
- * $get: function() {
- * return $injector.instantiate(constructor);
- * }
- * }
- * ```
- *
- *
- * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
- * as a type/class.
- *
- * @param {string} name The name of the instance.
- * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
- * that will be instantiated.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service using
- * {@link auto.$provide#service $provide.service(class)}.
- * ```js
- * var Ping = function($http) {
- * this.$http = $http;
- * };
- *
- * Ping.$inject = ['$http'];
- *
- * Ping.prototype.send = function() {
- * return this.$http.get('/ping');
- * };
- * $provide.service('ping', Ping);
- * ```
- * You would then inject and use this service like this:
- * ```js
- * someModule.controller('Ctrl', ['ping', function(ping) {
- * ping.send();
- * }]);
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#value
- * @description
- *
- * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
- * number, an array, an object or a function. This is short for registering a service where its
- * provider's `$get` property is a factory function that takes no arguments and returns the **value
- * service**.
- *
- * Value services are similar to constant services, except that they cannot be injected into a
- * module configuration function (see {@link angular.Module#config}) but they can be overridden by
- * an Angular
- * {@link auto.$provide#decorator decorator}.
- *
- * @param {string} name The name of the instance.
- * @param {*} value The value.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here are some examples of creating value services.
- * ```js
- * $provide.value('ADMIN_USER', 'admin');
- *
- * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
- *
- * $provide.value('halfOf', function(value) {
- * return value / 2;
- * });
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#constant
- * @description
- *
- * Register a **constant service**, such as a string, a number, an array, an object or a function,
- * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
- * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
- * be overridden by an Angular {@link auto.$provide#decorator decorator}.
- *
- * @param {string} name The name of the constant.
- * @param {*} value The constant value.
- * @returns {Object} registered instance
- *
- * @example
- * Here a some examples of creating constants:
- * ```js
- * $provide.constant('SHARD_HEIGHT', 306);
- *
- * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
- *
- * $provide.constant('double', function(value) {
- * return value * 2;
- * });
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#decorator
- * @description
- *
- * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
- * intercepts the creation of a service, allowing it to override or modify the behavior of the
- * service. The object returned by the decorator may be the original service, or a new service
- * object which replaces or wraps and delegates to the original service.
- *
- * @param {string} name The name of the service to decorate.
- * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
- * instantiated and should return the decorated service instance. The function is called using
- * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
- * Local injection arguments:
- *
- * * `$delegate` - The original service instance, which can be monkey patched, configured,
- * decorated or delegated to.
- *
- * @example
- * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
- * calls to {@link ng.$log#error $log.warn()}.
- * ```js
- * $provide.decorator('$log', ['$delegate', function($delegate) {
- * $delegate.warn = $delegate.error;
- * return $delegate;
- * }]);
- * ```
- */
-
-
-function createInjector(modulesToLoad, strictDi) {
- strictDi = (strictDi === true);
- var INSTANTIATING = {},
- providerSuffix = 'Provider',
- path = [],
- loadedModules = new HashMap([], true),
- providerCache = {
- $provide: {
- provider: supportObject(provider),
- factory: supportObject(factory),
- service: supportObject(service),
- value: supportObject(value),
- constant: supportObject(constant),
- decorator: decorator
- }
- },
- providerInjector = (providerCache.$injector =
- createInternalInjector(providerCache, function(serviceName, caller) {
- if (angular.isString(caller)) {
- path.push(caller);
- }
- throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
- })),
- instanceCache = {},
- protoInstanceInjector =
- createInternalInjector(instanceCache, function(serviceName, caller) {
- var provider = providerInjector.get(serviceName + providerSuffix, caller);
- return instanceInjector.invoke(
- provider.$get, provider, undefined, serviceName);
- }),
- instanceInjector = protoInstanceInjector;
-
- providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };
- var runBlocks = loadModules(modulesToLoad);
- instanceInjector = protoInstanceInjector.get('$injector');
- instanceInjector.strictDi = strictDi;
- forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });
-
- return instanceInjector;
-
- ////////////////////////////////////
- // $provider
- ////////////////////////////////////
-
- function supportObject(delegate) {
- return function(key, value) {
- if (isObject(key)) {
- forEach(key, reverseParams(delegate));
- } else {
- return delegate(key, value);
- }
- };
- }
-
- function provider(name, provider_) {
- assertNotHasOwnProperty(name, 'service');
- if (isFunction(provider_) || isArray(provider_)) {
- provider_ = providerInjector.instantiate(provider_);
- }
- if (!provider_.$get) {
- throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
- }
- return providerCache[name + providerSuffix] = provider_;
- }
-
- function enforceReturnValue(name, factory) {
- return function enforcedReturnValue() {
- var result = instanceInjector.invoke(factory, this);
- if (isUndefined(result)) {
- throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
- }
- return result;
- };
- }
-
- function factory(name, factoryFn, enforce) {
- return provider(name, {
- $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
- });
- }
-
- function service(name, constructor) {
- return factory(name, ['$injector', function($injector) {
- return $injector.instantiate(constructor);
- }]);
- }
-
- function value(name, val) { return factory(name, valueFn(val), false); }
-
- function constant(name, value) {
- assertNotHasOwnProperty(name, 'constant');
- providerCache[name] = value;
- instanceCache[name] = value;
- }
-
- function decorator(serviceName, decorFn) {
- var origProvider = providerInjector.get(serviceName + providerSuffix),
- orig$get = origProvider.$get;
-
- origProvider.$get = function() {
- var origInstance = instanceInjector.invoke(orig$get, origProvider);
- return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
- };
- }
-
- ////////////////////////////////////
- // Module Loading
- ////////////////////////////////////
- function loadModules(modulesToLoad) {
- assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');
- var runBlocks = [], moduleFn;
- forEach(modulesToLoad, function(module) {
- if (loadedModules.get(module)) return;
- loadedModules.put(module, true);
-
- function runInvokeQueue(queue) {
- var i, ii;
- for (i = 0, ii = queue.length; i < ii; i++) {
- var invokeArgs = queue[i],
- provider = providerInjector.get(invokeArgs[0]);
-
- provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
- }
- }
-
- try {
- if (isString(module)) {
- moduleFn = angularModule(module);
- runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
- runInvokeQueue(moduleFn._invokeQueue);
- runInvokeQueue(moduleFn._configBlocks);
- } else if (isFunction(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else if (isArray(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else {
- assertArgFn(module, 'module');
- }
- } catch (e) {
- if (isArray(module)) {
- module = module[module.length - 1];
- }
- if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
- // Safari & FF's stack traces don't contain error.message content
- // unlike those of Chrome and IE
- // So if stack doesn't contain message, we create a new string that contains both.
- // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
- /* jshint -W022 */
- e = e.message + '\n' + e.stack;
- }
- throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
- module, e.stack || e.message || e);
- }
- });
- return runBlocks;
- }
-
- ////////////////////////////////////
- // internal Injector
- ////////////////////////////////////
-
- function createInternalInjector(cache, factory) {
-
- function getService(serviceName, caller) {
- if (cache.hasOwnProperty(serviceName)) {
- if (cache[serviceName] === INSTANTIATING) {
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
- serviceName + ' <- ' + path.join(' <- '));
- }
- return cache[serviceName];
- } else {
- try {
- path.unshift(serviceName);
- cache[serviceName] = INSTANTIATING;
- return cache[serviceName] = factory(serviceName, caller);
- } catch (err) {
- if (cache[serviceName] === INSTANTIATING) {
- delete cache[serviceName];
- }
- throw err;
- } finally {
- path.shift();
- }
- }
- }
-
-
- function injectionArgs(fn, locals, serviceName) {
- var args = [],
- $inject = createInjector.$$annotate(fn, strictDi, serviceName);
-
- for (var i = 0, length = $inject.length; i < length; i++) {
- var key = $inject[i];
- if (typeof key !== 'string') {
- throw $injectorMinErr('itkn',
- 'Incorrect injection token! Expected service name as string, got {0}', key);
- }
- args.push(locals && locals.hasOwnProperty(key) ? locals[key] :
- getService(key, serviceName));
- }
- return args;
- }
-
- function isClass(func) {
- // IE 9-11 do not support classes and IE9 leaks with the code below.
- if (msie <= 11) {
- return false;
- }
- // Workaround for MS Edge.
- // Check https://connect.microsoft.com/IE/Feedback/Details/2211653
- return typeof func === 'function'
- && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func));
- }
-
- function invoke(fn, self, locals, serviceName) {
- if (typeof locals === 'string') {
- serviceName = locals;
- locals = null;
- }
-
- var args = injectionArgs(fn, locals, serviceName);
- if (isArray(fn)) {
- fn = fn[fn.length - 1];
- }
-
- if (!isClass(fn)) {
- // http://jsperf.com/angularjs-invoke-apply-vs-switch
- // #5388
- return fn.apply(self, args);
- } else {
- args.unshift(null);
- return new (Function.prototype.bind.apply(fn, args))();
- }
- }
-
-
- function instantiate(Type, locals, serviceName) {
- // Check if Type is annotated and use just the given function at n-1 as parameter
- // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
- var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
- var args = injectionArgs(Type, locals, serviceName);
- // Empty object at position 0 is ignored for invocation with `new`, but required.
- args.unshift(null);
- return new (Function.prototype.bind.apply(ctor, args))();
- }
-
-
- return {
- invoke: invoke,
- instantiate: instantiate,
- get: getService,
- annotate: createInjector.$$annotate,
- has: function(name) {
- return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
- }
- };
- }
-}
-
-createInjector.$$annotate = annotate;
-
-/**
- * @ngdoc provider
- * @name $anchorScrollProvider
- *
- * @description
- * Use `$anchorScrollProvider` to disable automatic scrolling whenever
- * {@link ng.$location#hash $location.hash()} changes.
- */
-function $AnchorScrollProvider() {
-
- var autoScrollingEnabled = true;
-
- /**
- * @ngdoc method
- * @name $anchorScrollProvider#disableAutoScrolling
- *
- * @description
- * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
- * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
- * Use this method to disable automatic scrolling.
- *
- * If automatic scrolling is disabled, one must explicitly call
- * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
- * current hash.
- */
- this.disableAutoScrolling = function() {
- autoScrollingEnabled = false;
- };
-
- /**
- * @ngdoc service
- * @name $anchorScroll
- * @kind function
- * @requires $window
- * @requires $location
- * @requires $rootScope
- *
- * @description
- * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
- * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
- * in the
- * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#the-indicated-part-of-the-document).
- *
- * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
- * match any anchor whenever it changes. This can be disabled by calling
- * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
- *
- * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
- * vertical scroll-offset (either fixed or dynamic).
- *
- * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
- * {@link ng.$location#hash $location.hash()} will be used.
- *
- * @property {(number|function|jqLite)} yOffset
- * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
- * positioned elements at the top of the page, such as navbars, headers etc.
- *
- * `yOffset` can be specified in various ways:
- * - **number**: A fixed number of pixels to be used as offset.<br /><br />
- * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
- * a number representing the offset (in pixels).<br /><br />
- * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
- * the top of the page to the element's bottom will be used as offset.<br />
- * **Note**: The element will be taken into account only as long as its `position` is set to
- * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
- * their height and/or positioning according to the viewport's size.
- *
- * <br />
- * <div class="alert alert-warning">
- * In order for `yOffset` to work properly, scrolling should take place on the document's root and
- * not some child element.
- * </div>
- *
- * @example
- <example module="anchorScrollExample">
- <file name="index.html">
- <div id="scrollArea" ng-controller="ScrollController">
- <a ng-click="gotoBottom()">Go to bottom</a>
- <a id="bottom"></a> You're at the bottom!
- </div>
- </file>
- <file name="script.js">
- angular.module('anchorScrollExample', [])
- .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
- function ($scope, $location, $anchorScroll) {
- $scope.gotoBottom = function() {
- // set the location.hash to the id of
- // the element you wish to scroll to.
- $location.hash('bottom');
-
- // call $anchorScroll()
- $anchorScroll();
- };
- }]);
- </file>
- <file name="style.css">
- #scrollArea {
- height: 280px;
- overflow: auto;
- }
-
- #bottom {
- display: block;
- margin-top: 2000px;
- }
- </file>
- </example>
- *
- * <hr />
- * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
- * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
- *
- * @example
- <example module="anchorScrollOffsetExample">
- <file name="index.html">
- <div class="fixed-header" ng-controller="headerCtrl">
- <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
- Go to anchor {{x}}
- </a>
- </div>
- <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
- Anchor {{x}} of 5
- </div>
- </file>
- <file name="script.js">
- angular.module('anchorScrollOffsetExample', [])
- .run(['$anchorScroll', function($anchorScroll) {
- $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
- }])
- .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
- function ($anchorScroll, $location, $scope) {
- $scope.gotoAnchor = function(x) {
- var newHash = 'anchor' + x;
- if ($location.hash() !== newHash) {
- // set the $location.hash to `newHash` and
- // $anchorScroll will automatically scroll to it
- $location.hash('anchor' + x);
- } else {
- // call $anchorScroll() explicitly,
- // since $location.hash hasn't changed
- $anchorScroll();
- }
- };
- }
- ]);
- </file>
- <file name="style.css">
- body {
- padding-top: 50px;
- }
-
- .anchor {
- border: 2px dashed DarkOrchid;
- padding: 10px 10px 200px 10px;
- }
-
- .fixed-header {
- background-color: rgba(0, 0, 0, 0.2);
- height: 50px;
- position: fixed;
- top: 0; left: 0; right: 0;
- }
-
- .fixed-header > a {
- display: inline-block;
- margin: 5px 15px;
- }
- </file>
- </example>
- */
- this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
- var document = $window.document;
-
- // Helper function to get first anchor from a NodeList
- // (using `Array#some()` instead of `angular#forEach()` since it's more performant
- // and working in all supported browsers.)
- function getFirstAnchor(list) {
- var result = null;
- Array.prototype.some.call(list, function(element) {
- if (nodeName_(element) === 'a') {
- result = element;
- return true;
- }
- });
- return result;
- }
-
- function getYOffset() {
-
- var offset = scroll.yOffset;
-
- if (isFunction(offset)) {
- offset = offset();
- } else if (isElement(offset)) {
- var elem = offset[0];
- var style = $window.getComputedStyle(elem);
- if (style.position !== 'fixed') {
- offset = 0;
- } else {
- offset = elem.getBoundingClientRect().bottom;
- }
- } else if (!isNumber(offset)) {
- offset = 0;
- }
-
- return offset;
- }
-
- function scrollTo(elem) {
- if (elem) {
- elem.scrollIntoView();
-
- var offset = getYOffset();
-
- if (offset) {
- // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
- // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
- // top of the viewport.
- //
- // IF the number of pixels from the top of `elem` to the end of the page's content is less
- // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
- // way down the page.
- //
- // This is often the case for elements near the bottom of the page.
- //
- // In such cases we do not need to scroll the whole `offset` up, just the difference between
- // the top of the element and the offset, which is enough to align the top of `elem` at the
- // desired position.
- var elemTop = elem.getBoundingClientRect().top;
- $window.scrollBy(0, elemTop - offset);
- }
- } else {
- $window.scrollTo(0, 0);
- }
- }
-
- function scroll(hash) {
- hash = isString(hash) ? hash : $location.hash();
- var elm;
-
- // empty hash, scroll to the top of the page
- if (!hash) scrollTo(null);
-
- // element with given id
- else if ((elm = document.getElementById(hash))) scrollTo(elm);
-
- // first anchor with given name :-D
- else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
-
- // no element and hash == 'top', scroll to the top of the page
- else if (hash === 'top') scrollTo(null);
- }
-
- // does not scroll when user clicks on anchor link that is currently on
- // (no url change, no $location.hash() change), browser native does scroll
- if (autoScrollingEnabled) {
- $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
- function autoScrollWatchAction(newVal, oldVal) {
- // skip the initial scroll if $location.hash is empty
- if (newVal === oldVal && newVal === '') return;
-
- jqLiteDocumentLoaded(function() {
- $rootScope.$evalAsync(scroll);
- });
- });
- }
-
- return scroll;
- }];
-}
-
-var $animateMinErr = minErr('$animate');
-var ELEMENT_NODE = 1;
-var NG_ANIMATE_CLASSNAME = 'ng-animate';
-
-function mergeClasses(a,b) {
- if (!a && !b) return '';
- if (!a) return b;
- if (!b) return a;
- if (isArray(a)) a = a.join(' ');
- if (isArray(b)) b = b.join(' ');
- return a + ' ' + b;
-}
-
-function extractElementNode(element) {
- for (var i = 0; i < element.length; i++) {
- var elm = element[i];
- if (elm.nodeType === ELEMENT_NODE) {
- return elm;
- }
- }
-}
-
-function splitClasses(classes) {
- if (isString(classes)) {
- classes = classes.split(' ');
- }
-
- // Use createMap() to prevent class assumptions involving property names in
- // Object.prototype
- var obj = createMap();
- forEach(classes, function(klass) {
- // sometimes the split leaves empty string values
- // incase extra spaces were applied to the options
- if (klass.length) {
- obj[klass] = true;
- }
- });
- return obj;
-}
-
-// if any other type of options value besides an Object value is
-// passed into the $animate.method() animation then this helper code
-// will be run which will ignore it. While this patch is not the
-// greatest solution to this, a lot of existing plugins depend on
-// $animate to either call the callback (< 1.2) or return a promise
-// that can be changed. This helper function ensures that the options
-// are wiped clean incase a callback function is provided.
-function prepareAnimateOptions(options) {
- return isObject(options)
- ? options
- : {};
-}
-
-var $$CoreAnimateJsProvider = function() {
- this.$get = function() {};
-};
-
-// this is prefixed with Core since it conflicts with
-// the animateQueueProvider defined in ngAnimate/animateQueue.js
-var $$CoreAnimateQueueProvider = function() {
- var postDigestQueue = new HashMap();
- var postDigestElements = [];
-
- this.$get = ['$$AnimateRunner', '$rootScope',
- function($$AnimateRunner, $rootScope) {
- return {
- enabled: noop,
- on: noop,
- off: noop,
- pin: noop,
-
- push: function(element, event, options, domOperation) {
- domOperation && domOperation();
-
- options = options || {};
- options.from && element.css(options.from);
- options.to && element.css(options.to);
-
- if (options.addClass || options.removeClass) {
- addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
- }
-
- var runner = new $$AnimateRunner(); // jshint ignore:line
-
- // since there are no animations to run the runner needs to be
- // notified that the animation call is complete.
- runner.complete();
- return runner;
- }
- };
-
-
- function updateData(data, classes, value) {
- var changed = false;
- if (classes) {
- classes = isString(classes) ? classes.split(' ') :
- isArray(classes) ? classes : [];
- forEach(classes, function(className) {
- if (className) {
- changed = true;
- data[className] = value;
- }
- });
- }
- return changed;
- }
-
- function handleCSSClassChanges() {
- forEach(postDigestElements, function(element) {
- var data = postDigestQueue.get(element);
- if (data) {
- var existing = splitClasses(element.attr('class'));
- var toAdd = '';
- var toRemove = '';
- forEach(data, function(status, className) {
- var hasClass = !!existing[className];
- if (status !== hasClass) {
- if (status) {
- toAdd += (toAdd.length ? ' ' : '') + className;
- } else {
- toRemove += (toRemove.length ? ' ' : '') + className;
- }
- }
- });
-
- forEach(element, function(elm) {
- toAdd && jqLiteAddClass(elm, toAdd);
- toRemove && jqLiteRemoveClass(elm, toRemove);
- });
- postDigestQueue.remove(element);
- }
- });
- postDigestElements.length = 0;
- }
-
-
- function addRemoveClassesPostDigest(element, add, remove) {
- var data = postDigestQueue.get(element) || {};
-
- var classesAdded = updateData(data, add, true);
- var classesRemoved = updateData(data, remove, false);
-
- if (classesAdded || classesRemoved) {
-
- postDigestQueue.put(element, data);
- postDigestElements.push(element);
-
- if (postDigestElements.length === 1) {
- $rootScope.$$postDigest(handleCSSClassChanges);
- }
- }
- }
- }];
-};
-
-/**
- * @ngdoc provider
- * @name $animateProvider
- *
- * @description
- * Default implementation of $animate that doesn't perform any animations, instead just
- * synchronously performs DOM updates and resolves the returned runner promise.
- *
- * In order to enable animations the `ngAnimate` module has to be loaded.
- *
- * To see the functional implementation check out `src/ngAnimate/animate.js`.
- */
-var $AnimateProvider = ['$provide', function($provide) {
- var provider = this;
-
- this.$$registeredAnimations = Object.create(null);
-
- /**
- * @ngdoc method
- * @name $animateProvider#register
- *
- * @description
- * Registers a new injectable animation factory function. The factory function produces the
- * animation object which contains callback functions for each event that is expected to be
- * animated.
- *
- * * `eventFn`: `function(element, ... , doneFunction, options)`
- * The element to animate, the `doneFunction` and the options fed into the animation. Depending
- * on the type of animation additional arguments will be injected into the animation function. The
- * list below explains the function signatures for the different animation methods:
- *
- * - setClass: function(element, addedClasses, removedClasses, doneFunction, options)
- * - addClass: function(element, addedClasses, doneFunction, options)
- * - removeClass: function(element, removedClasses, doneFunction, options)
- * - enter, leave, move: function(element, doneFunction, options)
- * - animate: function(element, fromStyles, toStyles, doneFunction, options)
- *
- * Make sure to trigger the `doneFunction` once the animation is fully complete.
- *
- * ```js
- * return {
- * //enter, leave, move signature
- * eventFn : function(element, done, options) {
- * //code to run the animation
- * //once complete, then run done()
- * return function endFunction(wasCancelled) {
- * //code to cancel the animation
- * }
- * }
- * }
- * ```
- *
- * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
- * @param {Function} factory The factory function that will be executed to return the animation
- * object.
- */
- this.register = function(name, factory) {
- if (name && name.charAt(0) !== '.') {
- throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
- }
-
- var key = name + '-animation';
- provider.$$registeredAnimations[name.substr(1)] = key;
- $provide.factory(key, factory);
- };
-
- /**
- * @ngdoc method
- * @name $animateProvider#classNameFilter
- *
- * @description
- * Sets and/or returns the CSS class regular expression that is checked when performing
- * an animation. Upon bootstrap the classNameFilter value is not set at all and will
- * therefore enable $animate to attempt to perform an animation on any element that is triggered.
- * When setting the `classNameFilter` value, animations will only be performed on elements
- * that successfully match the filter expression. This in turn can boost performance
- * for low-powered devices as well as applications containing a lot of structural operations.
- * @param {RegExp=} expression The className expression which will be checked against all animations
- * @return {RegExp} The current CSS className expression value. If null then there is no expression value
- */
- this.classNameFilter = function(expression) {
- if (arguments.length === 1) {
- this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
- if (this.$$classNameFilter) {
- var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
- if (reservedRegex.test(this.$$classNameFilter.toString())) {
- throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
-
- }
- }
- }
- return this.$$classNameFilter;
- };
-
- this.$get = ['$$animateQueue', function($$animateQueue) {
- function domInsert(element, parentElement, afterElement) {
- // if for some reason the previous element was removed
- // from the dom sometime before this code runs then let's
- // just stick to using the parent element as the anchor
- if (afterElement) {
- var afterNode = extractElementNode(afterElement);
- if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
- afterElement = null;
- }
- }
- afterElement ? afterElement.after(element) : parentElement.prepend(element);
- }
-
- /**
- * @ngdoc service
- * @name $animate
- * @description The $animate service exposes a series of DOM utility methods that provide support
- * for animation hooks. The default behavior is the application of DOM operations, however,
- * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
- * to ensure that animation runs with the triggered DOM operation.
- *
- * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't
- * included and only when it is active then the animation hooks that `$animate` triggers will be
- * functional. Once active then all structural `ng-` directives will trigger animations as they perform
- * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
- * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
- *
- * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
- *
- * To learn more about enabling animation support, click here to visit the
- * {@link ngAnimate ngAnimate module page}.
- */
- return {
- // we don't call it directly since non-existant arguments may
- // be interpreted as null within the sub enabled function
-
- /**
- *
- * @ngdoc method
- * @name $animate#on
- * @kind function
- * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
- * has fired on the given element or among any of its children. Once the listener is fired, the provided callback
- * is fired with the following params:
- *
- * ```js
- * $animate.on('enter', container,
- * function callback(element, phase) {
- * // cool we detected an enter animation within the container
- * }
- * );
- * ```
- *
- * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
- * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
- * as well as among its children
- * @param {Function} callback the callback function that will be fired when the listener is triggered
- *
- * The arguments present in the callback function are:
- * * `element` - The captured DOM element that the animation was fired on.
- * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
- */
- on: $$animateQueue.on,
-
- /**
- *
- * @ngdoc method
- * @name $animate#off
- * @kind function
- * @description Deregisters an event listener based on the event which has been associated with the provided element. This method
- * can be used in three different ways depending on the arguments:
- *
- * ```js
- * // remove all the animation event listeners listening for `enter`
- * $animate.off('enter');
- *
- * // remove all the animation event listeners listening for `enter` on the given element and its children
- * $animate.off('enter', container);
- *
- * // remove the event listener function provided by `callback` that is set
- * // to listen for `enter` on the given `container` as well as its children
- * $animate.off('enter', container, callback);
- * ```
- *
- * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
- * @param {DOMElement=} container the container element the event listener was placed on
- * @param {Function=} callback the callback function that was registered as the listener
- */
- off: $$animateQueue.off,
-
- /**
- * @ngdoc method
- * @name $animate#pin
- * @kind function
- * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
- * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
- * element despite being outside the realm of the application or within another application. Say for example if the application
- * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated
- * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
- * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
- *
- * Note that this feature is only active when the `ngAnimate` module is used.
- *
- * @param {DOMElement} element the external element that will be pinned
- * @param {DOMElement} parentElement the host parent element that will be associated with the external element
- */
- pin: $$animateQueue.pin,
-
- /**
- *
- * @ngdoc method
- * @name $animate#enabled
- * @kind function
- * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
- * function can be called in four ways:
- *
- * ```js
- * // returns true or false
- * $animate.enabled();
- *
- * // changes the enabled state for all animations
- * $animate.enabled(false);
- * $animate.enabled(true);
- *
- * // returns true or false if animations are enabled for an element
- * $animate.enabled(element);
- *
- * // changes the enabled state for an element and its children
- * $animate.enabled(element, true);
- * $animate.enabled(element, false);
- * ```
- *
- * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
- * @param {boolean=} enabled whether or not the animations will be enabled for the element
- *
- * @return {boolean} whether or not animations are enabled
- */
- enabled: $$animateQueue.enabled,
-
- /**
- * @ngdoc method
- * @name $animate#cancel
- * @kind function
- * @description Cancels the provided animation.
- *
- * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
- */
- cancel: function(runner) {
- runner.end && runner.end();
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#enter
- * @kind function
- * @description Inserts the element into the DOM either after the `after` element (if provided) or
- * as the first child within the `parent` element and then triggers an animation.
- * A promise is returned that will be resolved during the next digest once the animation
- * has completed.
- *
- * @param {DOMElement} element the element which will be inserted into the DOM
- * @param {DOMElement} parent the parent element which will append the element as
- * a child (so long as the after element is not present)
- * @param {DOMElement=} after the sibling element after which the element will be appended
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- enter: function(element, parent, after, options) {
- parent = parent && jqLite(parent);
- after = after && jqLite(after);
- parent = parent || after.parent();
- domInsert(element, parent, after);
- return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#move
- * @kind function
- * @description Inserts (moves) the element into its new position in the DOM either after
- * the `after` element (if provided) or as the first child within the `parent` element
- * and then triggers an animation. A promise is returned that will be resolved
- * during the next digest once the animation has completed.
- *
- * @param {DOMElement} element the element which will be moved into the new DOM position
- * @param {DOMElement} parent the parent element which will append the element as
- * a child (so long as the after element is not present)
- * @param {DOMElement=} after the sibling element after which the element will be appended
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- move: function(element, parent, after, options) {
- parent = parent && jqLite(parent);
- after = after && jqLite(after);
- parent = parent || after.parent();
- domInsert(element, parent, after);
- return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
- },
-
- /**
- * @ngdoc method
- * @name $animate#leave
- * @kind function
- * @description Triggers an animation and then removes the element from the DOM.
- * When the function is called a promise is returned that will be resolved during the next
- * digest once the animation has completed.
- *
- * @param {DOMElement} element the element which will be removed from the DOM
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- leave: function(element, options) {
- return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
- element.remove();
- });
- },
-
- /**
- * @ngdoc method
- * @name $animate#addClass
- * @kind function
- *
- * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
- * execution, the addClass operation will only be handled after the next digest and it will not trigger an
- * animation if element already contains the CSS class or if the class is removed at a later step.
- * Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- addClass: function(element, className, options) {
- options = prepareAnimateOptions(options);
- options.addClass = mergeClasses(options.addclass, className);
- return $$animateQueue.push(element, 'addClass', options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#removeClass
- * @kind function
- *
- * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
- * execution, the removeClass operation will only be handled after the next digest and it will not trigger an
- * animation if element does not contain the CSS class or if the class is added at a later step.
- * Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- removeClass: function(element, className, options) {
- options = prepareAnimateOptions(options);
- options.removeClass = mergeClasses(options.removeClass, className);
- return $$animateQueue.push(element, 'removeClass', options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#setClass
- * @kind function
- *
- * @description Performs both the addition and removal of a CSS classes on an element and (during the process)
- * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
- * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
- * passed. Note that class-based animations are treated differently compared to structural animations
- * (like enter, move and leave) since the CSS classes may be added/removed at different points
- * depending if CSS or JavaScript animations are used.
- *
- * @param {DOMElement} element the element which the CSS classes will be applied to
- * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
- * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- setClass: function(element, add, remove, options) {
- options = prepareAnimateOptions(options);
- options.addClass = mergeClasses(options.addClass, add);
- options.removeClass = mergeClasses(options.removeClass, remove);
- return $$animateQueue.push(element, 'setClass', options);
- },
-
- /**
- * @ngdoc method
- * @name $animate#animate
- * @kind function
- *
- * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
- * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take
- * on the provided styles. For example, if a transition animation is set for the given classNamem, then the provided `from` and
- * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding
- * style in `to`, the style in `from` is applied immediately, and no animation is run.
- * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`
- * method (or as part of the `options` parameter):
- *
- * ```js
- * ngModule.animation('.my-inline-animation', function() {
- * return {
- * animate : function(element, from, to, done, options) {
- * //animation
- * done();
- * }
- * }
- * });
- * ```
- *
- * @param {DOMElement} element the element which the CSS styles will be applied to
- * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
- * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
- * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
- * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
- * (Note that if no animation is detected then this value will not be applied to the element.)
- * @param {object=} options an optional collection of options/styles that will be applied to the element
- *
- * @return {Promise} the animation callback promise
- */
- animate: function(element, from, to, className, options) {
- options = prepareAnimateOptions(options);
- options.from = options.from ? extend(options.from, from) : from;
- options.to = options.to ? extend(options.to, to) : to;
-
- className = className || 'ng-inline-animate';
- options.tempClasses = mergeClasses(options.tempClasses, className);
- return $$animateQueue.push(element, 'animate', options);
- }
- };
- }];
-}];
-
-var $$AnimateAsyncRunFactoryProvider = function() {
- this.$get = ['$$rAF', function($$rAF) {
- var waitQueue = [];
-
- function waitForTick(fn) {
- waitQueue.push(fn);
- if (waitQueue.length > 1) return;
- $$rAF(function() {
- for (var i = 0; i < waitQueue.length; i++) {
- waitQueue[i]();
- }
- waitQueue = [];
- });
- }
-
- return function() {
- var passed = false;
- waitForTick(function() {
- passed = true;
- });
- return function(callback) {
- passed ? callback() : waitForTick(callback);
- };
- };
- }];
-};
-
-var $$AnimateRunnerFactoryProvider = function() {
- this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
- function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {
-
- var INITIAL_STATE = 0;
- var DONE_PENDING_STATE = 1;
- var DONE_COMPLETE_STATE = 2;
-
- AnimateRunner.chain = function(chain, callback) {
- var index = 0;
-
- next();
- function next() {
- if (index === chain.length) {
- callback(true);
- return;
- }
-
- chain[index](function(response) {
- if (response === false) {
- callback(false);
- return;
- }
- index++;
- next();
- });
- }
- };
-
- AnimateRunner.all = function(runners, callback) {
- var count = 0;
- var status = true;
- forEach(runners, function(runner) {
- runner.done(onProgress);
- });
-
- function onProgress(response) {
- status = status && response;
- if (++count === runners.length) {
- callback(status);
- }
- }
- };
-
- function AnimateRunner(host) {
- this.setHost(host);
-
- var rafTick = $$animateAsyncRun();
- var timeoutTick = function(fn) {
- $timeout(fn, 0, false);
- };
-
- this._doneCallbacks = [];
- this._tick = function(fn) {
- var doc = $document[0];
-
- // the document may not be ready or attached
- // to the module for some internal tests
- if (doc && doc.hidden) {
- timeoutTick(fn);
- } else {
- rafTick(fn);
- }
- };
- this._state = 0;
- }
-
- AnimateRunner.prototype = {
- setHost: function(host) {
- this.host = host || {};
- },
-
- done: function(fn) {
- if (this._state === DONE_COMPLETE_STATE) {
- fn();
- } else {
- this._doneCallbacks.push(fn);
- }
- },
-
- progress: noop,
-
- getPromise: function() {
- if (!this.promise) {
- var self = this;
- this.promise = $q(function(resolve, reject) {
- self.done(function(status) {
- status === false ? reject() : resolve();
- });
- });
- }
- return this.promise;
- },
-
- then: function(resolveHandler, rejectHandler) {
- return this.getPromise().then(resolveHandler, rejectHandler);
- },
-
- 'catch': function(handler) {
- return this.getPromise()['catch'](handler);
- },
-
- 'finally': function(handler) {
- return this.getPromise()['finally'](handler);
- },
-
- pause: function() {
- if (this.host.pause) {
- this.host.pause();
- }
- },
-
- resume: function() {
- if (this.host.resume) {
- this.host.resume();
- }
- },
-
- end: function() {
- if (this.host.end) {
- this.host.end();
- }
- this._resolve(true);
- },
-
- cancel: function() {
- if (this.host.cancel) {
- this.host.cancel();
- }
- this._resolve(false);
- },
-
- complete: function(response) {
- var self = this;
- if (self._state === INITIAL_STATE) {
- self._state = DONE_PENDING_STATE;
- self._tick(function() {
- self._resolve(response);
- });
- }
- },
-
- _resolve: function(response) {
- if (this._state !== DONE_COMPLETE_STATE) {
- forEach(this._doneCallbacks, function(fn) {
- fn(response);
- });
- this._doneCallbacks.length = 0;
- this._state = DONE_COMPLETE_STATE;
- }
- }
- };
-
- return AnimateRunner;
- }];
-};
-
-/**
- * @ngdoc service
- * @name $animateCss
- * @kind object
- *
- * @description
- * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,
- * then the `$animateCss` service will actually perform animations.
- *
- * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
- */
-var $CoreAnimateCssProvider = function() {
- this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
-
- return function(element, initialOptions) {
- // all of the animation functions should create
- // a copy of the options data, however, if a
- // parent service has already created a copy then
- // we should stick to using that
- var options = initialOptions || {};
- if (!options.$$prepared) {
- options = copy(options);
- }
-
- // there is no point in applying the styles since
- // there is no animation that goes on at all in
- // this version of $animateCss.
- if (options.cleanupStyles) {
- options.from = options.to = null;
- }
-
- if (options.from) {
- element.css(options.from);
- options.from = null;
- }
-
- /* jshint newcap: false */
- var closed, runner = new $$AnimateRunner();
- return {
- start: run,
- end: run
- };
-
- function run() {
- $$rAF(function() {
- applyAnimationContents();
- if (!closed) {
- runner.complete();
- }
- closed = true;
- });
- return runner;
- }
-
- function applyAnimationContents() {
- if (options.addClass) {
- element.addClass(options.addClass);
- options.addClass = null;
- }
- if (options.removeClass) {
- element.removeClass(options.removeClass);
- options.removeClass = null;
- }
- if (options.to) {
- element.css(options.to);
- options.to = null;
- }
- }
- };
- }];
-};
-
-/* global stripHash: true */
-
-/**
- * ! This is a private undocumented service !
- *
- * @name $browser
- * @requires $log
- * @description
- * This object has two goals:
- *
- * - hide all the global state in the browser caused by the window object
- * - abstract away all the browser specific features and inconsistencies
- *
- * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
- * service, which can be used for convenient testing of the application without the interaction with
- * the real browser apis.
- */
-/**
- * @param {object} window The global window object.
- * @param {object} document jQuery wrapped document.
- * @param {object} $log window.console or an object with the same interface.
- * @param {object} $sniffer $sniffer service
- */
-function Browser(window, document, $log, $sniffer) {
- var self = this,
- rawDocument = document[0],
- location = window.location,
- history = window.history,
- setTimeout = window.setTimeout,
- clearTimeout = window.clearTimeout,
- pendingDeferIds = {};
-
- self.isMock = false;
-
- var outstandingRequestCount = 0;
- var outstandingRequestCallbacks = [];
-
- // TODO(vojta): remove this temporary api
- self.$$completeOutstandingRequest = completeOutstandingRequest;
- self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
-
- /**
- * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
- * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
- */
- function completeOutstandingRequest(fn) {
- try {
- fn.apply(null, sliceArgs(arguments, 1));
- } finally {
- outstandingRequestCount--;
- if (outstandingRequestCount === 0) {
- while (outstandingRequestCallbacks.length) {
- try {
- outstandingRequestCallbacks.pop()();
- } catch (e) {
- $log.error(e);
- }
- }
- }
- }
- }
-
- function getHash(url) {
- var index = url.indexOf('#');
- return index === -1 ? '' : url.substr(index);
- }
-
- /**
- * @private
- * Note: this method is used only by scenario runner
- * TODO(vojta): prefix this method with $$ ?
- * @param {function()} callback Function that will be called when no outstanding request
- */
- self.notifyWhenNoOutstandingRequests = function(callback) {
- if (outstandingRequestCount === 0) {
- callback();
- } else {
- outstandingRequestCallbacks.push(callback);
- }
- };
-
- //////////////////////////////////////////////////////////////
- // URL API
- //////////////////////////////////////////////////////////////
-
- var cachedState, lastHistoryState,
- lastBrowserUrl = location.href,
- baseElement = document.find('base'),
- pendingLocation = null;
-
- cacheState();
- lastHistoryState = cachedState;
-
- /**
- * @name $browser#url
- *
- * @description
- * GETTER:
- * Without any argument, this method just returns current value of location.href.
- *
- * SETTER:
- * With at least one argument, this method sets url to new value.
- * If html5 history api supported, pushState/replaceState is used, otherwise
- * location.href/location.replace is used.
- * Returns its own instance to allow chaining
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link ng.$location $location service} to change url.
- *
- * @param {string} url New url (when used as setter)
- * @param {boolean=} replace Should new url replace current history record?
- * @param {object=} state object to use with pushState/replaceState
- */
- self.url = function(url, replace, state) {
- // In modern browsers `history.state` is `null` by default; treating it separately
- // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
- // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
- if (isUndefined(state)) {
- state = null;
- }
-
- // Android Browser BFCache causes location, history reference to become stale.
- if (location !== window.location) location = window.location;
- if (history !== window.history) history = window.history;
-
- // setter
- if (url) {
- var sameState = lastHistoryState === state;
-
- // Don't change anything if previous and current URLs and states match. This also prevents
- // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
- // See https://github.com/angular/angular.js/commit/ffb2701
- if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
- return self;
- }
- var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
- lastBrowserUrl = url;
- lastHistoryState = state;
- // Don't use history API if only the hash changed
- // due to a bug in IE10/IE11 which leads
- // to not firing a `hashchange` nor `popstate` event
- // in some cases (see #9143).
- if ($sniffer.history && (!sameBase || !sameState)) {
- history[replace ? 'replaceState' : 'pushState'](state, '', url);
- cacheState();
- // Do the assignment again so that those two variables are referentially identical.
- lastHistoryState = cachedState;
- } else {
- if (!sameBase || pendingLocation) {
- pendingLocation = url;
- }
- if (replace) {
- location.replace(url);
- } else if (!sameBase) {
- location.href = url;
- } else {
- location.hash = getHash(url);
- }
- if (location.href !== url) {
- pendingLocation = url;
- }
- }
- return self;
- // getter
- } else {
- // - pendingLocation is needed as browsers don't allow to read out
- // the new location.href if a reload happened or if there is a bug like in iOS 9 (see
- // https://openradar.appspot.com/22186109).
- // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
- return pendingLocation || location.href.replace(/%27/g,"'");
- }
- };
-
- /**
- * @name $browser#state
- *
- * @description
- * This method is a getter.
- *
- * Return history.state or null if history.state is undefined.
- *
- * @returns {object} state
- */
- self.state = function() {
- return cachedState;
- };
-
- var urlChangeListeners = [],
- urlChangeInit = false;
-
- function cacheStateAndFireUrlChange() {
- pendingLocation = null;
- cacheState();
- fireUrlChange();
- }
-
- function getCurrentState() {
- try {
- return history.state;
- } catch (e) {
- // MSIE can reportedly throw when there is no state (UNCONFIRMED).
- }
- }
-
- // This variable should be used *only* inside the cacheState function.
- var lastCachedState = null;
- function cacheState() {
- // This should be the only place in $browser where `history.state` is read.
- cachedState = getCurrentState();
- cachedState = isUndefined(cachedState) ? null : cachedState;
-
- // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
- if (equals(cachedState, lastCachedState)) {
- cachedState = lastCachedState;
- }
- lastCachedState = cachedState;
- }
-
- function fireUrlChange() {
- if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
- return;
- }
-
- lastBrowserUrl = self.url();
- lastHistoryState = cachedState;
- forEach(urlChangeListeners, function(listener) {
- listener(self.url(), cachedState);
- });
- }
-
- /**
- * @name $browser#onUrlChange
- *
- * @description
- * Register callback function that will be called, when url changes.
- *
- * It's only called when the url is changed from outside of angular:
- * - user types different url into address bar
- * - user clicks on history (forward/back) button
- * - user clicks on a link
- *
- * It's not called when url is changed by $browser.url() method
- *
- * The listener gets called with new url as parameter.
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link ng.$location $location service} to monitor url changes in angular apps.
- *
- * @param {function(string)} listener Listener function to be called when url changes.
- * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
- */
- self.onUrlChange = function(callback) {
- // TODO(vojta): refactor to use node's syntax for events
- if (!urlChangeInit) {
- // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
- // don't fire popstate when user change the address bar and don't fire hashchange when url
- // changed by push/replaceState
-
- // html5 history api - popstate event
- if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
- // hashchange event
- jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
-
- urlChangeInit = true;
- }
-
- urlChangeListeners.push(callback);
- return callback;
- };
-
- /**
- * @private
- * Remove popstate and hashchange handler from window.
- *
- * NOTE: this api is intended for use only by $rootScope.
- */
- self.$$applicationDestroyed = function() {
- jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
- };
-
- /**
- * Checks whether the url has changed outside of Angular.
- * Needs to be exported to be able to check for changes that have been done in sync,
- * as hashchange/popstate events fire in async.
- */
- self.$$checkUrlChange = fireUrlChange;
-
- //////////////////////////////////////////////////////////////
- // Misc API
- //////////////////////////////////////////////////////////////
-
- /**
- * @name $browser#baseHref
- *
- * @description
- * Returns current <base href>
- * (always relative - without domain)
- *
- * @returns {string} The current base href
- */
- self.baseHref = function() {
- var href = baseElement.attr('href');
- return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
- };
-
- /**
- * @name $browser#defer
- * @param {function()} fn A function, who's execution should be deferred.
- * @param {number=} [delay=0] of milliseconds to defer the function execution.
- * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
- *
- * @description
- * Executes a fn asynchronously via `setTimeout(fn, delay)`.
- *
- * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
- * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
- * via `$browser.defer.flush()`.
- *
- */
- self.defer = function(fn, delay) {
- var timeoutId;
- outstandingRequestCount++;
- timeoutId = setTimeout(function() {
- delete pendingDeferIds[timeoutId];
- completeOutstandingRequest(fn);
- }, delay || 0);
- pendingDeferIds[timeoutId] = true;
- return timeoutId;
- };
-
-
- /**
- * @name $browser#defer.cancel
- *
- * @description
- * Cancels a deferred task identified with `deferId`.
- *
- * @param {*} deferId Token returned by the `$browser.defer` function.
- * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
- * canceled.
- */
- self.defer.cancel = function(deferId) {
- if (pendingDeferIds[deferId]) {
- delete pendingDeferIds[deferId];
- clearTimeout(deferId);
- completeOutstandingRequest(noop);
- return true;
- }
- return false;
- };
-
-}
-
-function $BrowserProvider() {
- this.$get = ['$window', '$log', '$sniffer', '$document',
- function($window, $log, $sniffer, $document) {
- return new Browser($window, $document, $log, $sniffer);
- }];
-}
-
-/**
- * @ngdoc service
- * @name $cacheFactory
- *
- * @description
- * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
- * them.
- *
- * ```js
- *
- * var cache = $cacheFactory('cacheId');
- * expect($cacheFactory.get('cacheId')).toBe(cache);
- * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
- *
- * cache.put("key", "value");
- * cache.put("another key", "another value");
- *
- * // We've specified no options on creation
- * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
- *
- * ```
- *
- *
- * @param {string} cacheId Name or id of the newly created cache.
- * @param {object=} options Options object that specifies the cache behavior. Properties:
- *
- * - `{number=}` `capacity` — turns the cache into LRU cache.
- *
- * @returns {object} Newly created cache object with the following set of methods:
- *
- * - `{object}` `info()` — Returns id, size, and options of cache.
- * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
- * it.
- * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
- * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
- * - `{void}` `removeAll()` — Removes all cached values.
- * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
- *
- * @example
- <example module="cacheExampleApp">
- <file name="index.html">
- <div ng-controller="CacheController">
- <input ng-model="newCacheKey" placeholder="Key">
- <input ng-model="newCacheValue" placeholder="Value">
- <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
-
- <p ng-if="keys.length">Cached Values</p>
- <div ng-repeat="key in keys">
- <span ng-bind="key"></span>
- <span>: </span>
- <b ng-bind="cache.get(key)"></b>
- </div>
-
- <p>Cache Info</p>
- <div ng-repeat="(key, value) in cache.info()">
- <span ng-bind="key"></span>
- <span>: </span>
- <b ng-bind="value"></b>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('cacheExampleApp', []).
- controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
- $scope.keys = [];
- $scope.cache = $cacheFactory('cacheId');
- $scope.put = function(key, value) {
- if (angular.isUndefined($scope.cache.get(key))) {
- $scope.keys.push(key);
- }
- $scope.cache.put(key, angular.isUndefined(value) ? null : value);
- };
- }]);
- </file>
- <file name="style.css">
- p {
- margin: 10px 0 3px;
- }
- </file>
- </example>
- */
-function $CacheFactoryProvider() {
-
- this.$get = function() {
- var caches = {};
-
- function cacheFactory(cacheId, options) {
- if (cacheId in caches) {
- throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
- }
-
- var size = 0,
- stats = extend({}, options, {id: cacheId}),
- data = createMap(),
- capacity = (options && options.capacity) || Number.MAX_VALUE,
- lruHash = createMap(),
- freshEnd = null,
- staleEnd = null;
-
- /**
- * @ngdoc type
- * @name $cacheFactory.Cache
- *
- * @description
- * A cache object used to store and retrieve data, primarily used by
- * {@link $http $http} and the {@link ng.directive:script script} directive to cache
- * templates and other data.
- *
- * ```js
- * angular.module('superCache')
- * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
- * return $cacheFactory('super-cache');
- * }]);
- * ```
- *
- * Example test:
- *
- * ```js
- * it('should behave like a cache', inject(function(superCache) {
- * superCache.put('key', 'value');
- * superCache.put('another key', 'another value');
- *
- * expect(superCache.info()).toEqual({
- * id: 'super-cache',
- * size: 2
- * });
- *
- * superCache.remove('another key');
- * expect(superCache.get('another key')).toBeUndefined();
- *
- * superCache.removeAll();
- * expect(superCache.info()).toEqual({
- * id: 'super-cache',
- * size: 0
- * });
- * }));
- * ```
- */
- return caches[cacheId] = {
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#put
- * @kind function
- *
- * @description
- * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
- * retrieved later, and incrementing the size of the cache if the key was not already
- * present in the cache. If behaving like an LRU cache, it will also remove stale
- * entries from the set.
- *
- * It will not insert undefined values into the cache.
- *
- * @param {string} key the key under which the cached data is stored.
- * @param {*} value the value to store alongside the key. If it is undefined, the key
- * will not be stored.
- * @returns {*} the value stored.
- */
- put: function(key, value) {
- if (isUndefined(value)) return;
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
-
- refresh(lruEntry);
- }
-
- if (!(key in data)) size++;
- data[key] = value;
-
- if (size > capacity) {
- this.remove(staleEnd.key);
- }
-
- return value;
- },
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#get
- * @kind function
- *
- * @description
- * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
- *
- * @param {string} key the key of the data to be retrieved
- * @returns {*} the value stored.
- */
- get: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
-
- if (!lruEntry) return;
-
- refresh(lruEntry);
- }
-
- return data[key];
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#remove
- * @kind function
- *
- * @description
- * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
- *
- * @param {string} key the key of the entry to be removed
- */
- remove: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
-
- if (!lruEntry) return;
-
- if (lruEntry == freshEnd) freshEnd = lruEntry.p;
- if (lruEntry == staleEnd) staleEnd = lruEntry.n;
- link(lruEntry.n,lruEntry.p);
-
- delete lruHash[key];
- }
-
- if (!(key in data)) return;
-
- delete data[key];
- size--;
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#removeAll
- * @kind function
- *
- * @description
- * Clears the cache object of any entries.
- */
- removeAll: function() {
- data = createMap();
- size = 0;
- lruHash = createMap();
- freshEnd = staleEnd = null;
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#destroy
- * @kind function
- *
- * @description
- * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
- * removing it from the {@link $cacheFactory $cacheFactory} set.
- */
- destroy: function() {
- data = null;
- stats = null;
- lruHash = null;
- delete caches[cacheId];
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#info
- * @kind function
- *
- * @description
- * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
- *
- * @returns {object} an object with the following properties:
- * <ul>
- * <li>**id**: the id of the cache instance</li>
- * <li>**size**: the number of entries kept in the cache instance</li>
- * <li>**...**: any additional properties from the options object when creating the
- * cache.</li>
- * </ul>
- */
- info: function() {
- return extend({}, stats, {size: size});
- }
- };
-
-
- /**
- * makes the `entry` the freshEnd of the LRU linked list
- */
- function refresh(entry) {
- if (entry != freshEnd) {
- if (!staleEnd) {
- staleEnd = entry;
- } else if (staleEnd == entry) {
- staleEnd = entry.n;
- }
-
- link(entry.n, entry.p);
- link(entry, freshEnd);
- freshEnd = entry;
- freshEnd.n = null;
- }
- }
-
-
- /**
- * bidirectionally links two entries of the LRU linked list
- */
- function link(nextEntry, prevEntry) {
- if (nextEntry != prevEntry) {
- if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
- if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
- }
- }
- }
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory#info
- *
- * @description
- * Get information about all the caches that have been created
- *
- * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
- */
- cacheFactory.info = function() {
- var info = {};
- forEach(caches, function(cache, cacheId) {
- info[cacheId] = cache.info();
- });
- return info;
- };
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory#get
- *
- * @description
- * Get access to a cache object by the `cacheId` used when it was created.
- *
- * @param {string} cacheId Name or id of a cache to access.
- * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
- */
- cacheFactory.get = function(cacheId) {
- return caches[cacheId];
- };
-
-
- return cacheFactory;
- };
-}
-
-/**
- * @ngdoc service
- * @name $templateCache
- *
- * @description
- * The first time a template is used, it is loaded in the template cache for quick retrieval. You
- * can load templates directly into the cache in a `script` tag, or by consuming the
- * `$templateCache` service directly.
- *
- * Adding via the `script` tag:
- *
- * ```html
- * <script type="text/ng-template" id="templateId.html">
- * <p>This is the content of the template</p>
- * </script>
- * ```
- *
- * **Note:** the `script` tag containing the template does not need to be included in the `head` of
- * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
- * element with ng-app attribute), otherwise the template will be ignored.
- *
- * Adding via the `$templateCache` service:
- *
- * ```js
- * var myApp = angular.module('myApp', []);
- * myApp.run(function($templateCache) {
- * $templateCache.put('templateId.html', 'This is the content of the template');
- * });
- * ```
- *
- * To retrieve the template later, simply use it in your HTML:
- * ```html
- * <div ng-include=" 'templateId.html' "></div>
- * ```
- *
- * or get it via Javascript:
- * ```js
- * $templateCache.get('templateId.html')
- * ```
- *
- * See {@link ng.$cacheFactory $cacheFactory}.
- *
- */
-function $TemplateCacheProvider() {
- this.$get = ['$cacheFactory', function($cacheFactory) {
- return $cacheFactory('templates');
- }];
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
- *
- * DOM-related variables:
- *
- * - "node" - DOM Node
- * - "element" - DOM Element or Node
- * - "$node" or "$element" - jqLite-wrapped node or element
- *
- *
- * Compiler related stuff:
- *
- * - "linkFn" - linking fn of a single directive
- * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
- * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
- * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
- */
-
-
-/**
- * @ngdoc service
- * @name $compile
- * @kind function
- *
- * @description
- * Compiles an HTML string or DOM into a template and produces a template function, which
- * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
- *
- * The compilation is a process of walking the DOM tree and matching DOM elements to
- * {@link ng.$compileProvider#directive directives}.
- *
- * <div class="alert alert-warning">
- * **Note:** This document is an in-depth reference of all directive options.
- * For a gentle introduction to directives with examples of common use cases,
- * see the {@link guide/directive directive guide}.
- * </div>
- *
- * ## Comprehensive Directive API
- *
- * There are many different options for a directive.
- *
- * The difference resides in the return value of the factory function.
- * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
- * or just the `postLink` function (all other properties will have the default values).
- *
- * <div class="alert alert-success">
- * **Best Practice:** It's recommended to use the "directive definition object" form.
- * </div>
- *
- * Here's an example directive declared with a Directive Definition Object:
- *
- * ```js
- * var myModule = angular.module(...);
- *
- * myModule.directive('directiveName', function factory(injectables) {
- * var directiveDefinitionObject = {
- * priority: 0,
- * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
- * // or
- * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
- * transclude: false,
- * restrict: 'A',
- * templateNamespace: 'html',
- * scope: false,
- * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
- * controllerAs: 'stringIdentifier',
- * bindToController: false,
- * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
- * compile: function compile(tElement, tAttrs, transclude) {
- * return {
- * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- * post: function postLink(scope, iElement, iAttrs, controller) { ... }
- * }
- * // or
- * // return function postLink( ... ) { ... }
- * },
- * // or
- * // link: {
- * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
- * // }
- * // or
- * // link: function postLink( ... ) { ... }
- * };
- * return directiveDefinitionObject;
- * });
- * ```
- *
- * <div class="alert alert-warning">
- * **Note:** Any unspecified options will use the default value. You can see the default values below.
- * </div>
- *
- * Therefore the above can be simplified as:
- *
- * ```js
- * var myModule = angular.module(...);
- *
- * myModule.directive('directiveName', function factory(injectables) {
- * var directiveDefinitionObject = {
- * link: function postLink(scope, iElement, iAttrs) { ... }
- * };
- * return directiveDefinitionObject;
- * // or
- * // return function postLink(scope, iElement, iAttrs) { ... }
- * });
- * ```
- *
- *
- *
- * ### Directive Definition Object
- *
- * The directive definition object provides instructions to the {@link ng.$compile
- * compiler}. The attributes are:
- *
- * #### `multiElement`
- * When this property is set to true, the HTML compiler will collect DOM nodes between
- * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
- * together as the directive elements. It is recommended that this feature be used on directives
- * which are not strictly behavioral (such as {@link ngClick}), and which
- * do not manipulate or replace child nodes (such as {@link ngInclude}).
- *
- * #### `priority`
- * When there are multiple directives defined on a single DOM element, sometimes it
- * is necessary to specify the order in which the directives are applied. The `priority` is used
- * to sort the directives before their `compile` functions get called. Priority is defined as a
- * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
- * are also run in priority order, but post-link functions are run in reverse order. The order
- * of directives with the same priority is undefined. The default priority is `0`.
- *
- * #### `terminal`
- * If set to true then the current `priority` will be the last set of directives
- * which will execute (any directives at the current priority will still execute
- * as the order of execution on same `priority` is undefined). Note that expressions
- * and other directives used in the directive's template will also be excluded from execution.
- *
- * #### `scope`
- * The scope property can be `true`, an object or a falsy value:
- *
- * * **falsy:** No scope will be created for the directive. The directive will use its parent's scope.
- *
- * * **`true`:** A new child scope that prototypically inherits from its parent will be created for
- * the directive's element. If multiple directives on the same element request a new scope,
- * only one new scope is created. The new scope rule does not apply for the root of the template
- * since the root of the template always gets a new scope.
- *
- * * **`{...}` (an object hash):** A new "isolate" scope is created for the directive's element. The
- * 'isolate' scope differs from normal scope in that it does not prototypically inherit from its parent
- * scope. This is useful when creating reusable components, which should not accidentally read or modify
- * data in the parent scope.
- *
- * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the
- * directive's element. These local properties are useful for aliasing values for templates. The keys in
- * the object hash map to the name of the property on the isolate scope; the values define how the property
- * is bound to the parent scope, via matching attributes on the directive's element:
- *
- * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
- * always a string since DOM attributes are strings. If no `attr` name is specified then the
- * attribute name is assumed to be the same as the local name. Given `<my-component
- * my-attr="hello {{name}}">` and the isolate scope definition `scope: { localName:'@myAttr' }`,
- * the directive's scope property `localName` will reflect the interpolated value of `hello
- * {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's
- * scope. The `name` is read from the parent scope (not the directive's scope).
- *
- * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression
- * passed via the attribute `attr`. The expression is evaluated in the context of the parent scope.
- * If no `attr` name is specified then the attribute name is assumed to be the same as the local
- * name. Given `<my-component my-attr="parentModel">` and the isolate scope definition `scope: {
- * localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the
- * value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in
- * `localModel` and vice versa. Optional attributes should be marked as such with a question mark:
- * `=?` or `=?attr`. If the binding expression is non-assignable, or if the attribute isn't
- * optional and doesn't exist, an exception ({@link error/$compile/nonassign `$compile:nonassign`})
- * will be thrown upon discovering changes to the local value, since it will be impossible to sync
- * them back to the parent scope. By default, the {@link ng.$rootScope.Scope#$watch `$watch`}
- * method is used for tracking changes, and the equality check is based on object identity.
- * However, if an object literal or an array literal is passed as the binding expression, the
- * equality check is done by value (using the {@link angular.equals} function). It's also possible
- * to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection
- * `$watchCollection`}: use `=*` or `=*attr` (`=*?` or `=*?attr` if the attribute is optional).
- *
- * * `<` or `<attr` - set up a one-way (one-directional) binding between a local scope property and an
- * expression passed via the attribute `attr`. The expression is evaluated in the context of the
- * parent scope. If no `attr` name is specified then the attribute name is assumed to be the same as the
- * local name. You can also make the binding optional by adding `?`: `<?` or `<?attr`.
- *
- * For example, given `<my-component my-attr="parentModel">` and directive definition of
- * `scope: { localModel:'<myAttr' }`, then the isolated scope property `localModel` will reflect the
- * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
- * in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however
- * two caveats:
- * 1. one-way binding does not copy the value from the parent to the isolate scope, it simply
- * sets the same value. That means if your bound value is an object, changes to its properties
- * in the isolated scope will be reflected in the parent scope (because both reference the same object).
- * 2. one-way binding watches changes to the **identity** of the parent value. That means the
- * {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference
- * to the value has changed. In most cases, this should not be of concern, but can be important
- * to know if you one-way bind to an object, and then replace that object in the isolated scope.
- * If you now change a property of the object in your parent scope, the change will not be
- * propagated to the isolated scope, because the identity of the object on the parent scope
- * has not changed. Instead you must assign a new object.
- *
- * One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings
- * back to the parent. However, it does not make this completely impossible.
- *
- * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If
- * no `attr` name is specified then the attribute name is assumed to be the same as the local name.
- * Given `<my-component my-attr="count = count + value">` and the isolate scope definition `scope: {
- * localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for
- * the `count = count + value` expression. Often it's desirable to pass data from the isolated scope
- * via an expression to the parent scope. This can be done by passing a map of local variable names
- * and values into the expression wrapper fn. For example, if the expression is `increment(amount)`
- * then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`.
- *
- * In general it's possible to apply more than one directive to one element, but there might be limitations
- * depending on the type of scope required by the directives. The following points will help explain these limitations.
- * For simplicity only two directives are taken into account, but it is also applicable for several directives:
- *
- * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope
- * * **child scope** + **no scope** => Both directives will share one single child scope
- * * **child scope** + **child scope** => Both directives will share one single child scope
- * * **isolated scope** + **no scope** => The isolated directive will use it's own created isolated scope. The other directive will use
- * its parent's scope
- * * **isolated scope** + **child scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives cannot
- * be applied to the same element.
- * * **isolated scope** + **isolated scope** => **Won't work!** Only one scope can be related to one element. Therefore these directives
- * cannot be applied to the same element.
- *
- *
- * #### `bindToController`
- * This property is used to bind scope properties directly to the controller. It can be either
- * `true` or an object hash with the same format as the `scope` property. Additionally, a controller
- * alias must be set, either by using `controllerAs: 'myAlias'` or by specifying the alias in the controller
- * definition: `controller: 'myCtrl as myAlias'`.
- *
- * When an isolate scope is used for a directive (see above), `bindToController: true` will
- * allow a component to have its properties bound to the controller, rather than to scope.
- *
- * After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller
- * properties. You can access these bindings once they have been initialized by providing a controller method called
- * `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings
- * initialized.
- *
- * <div class="alert alert-warning">
- * **Deprecation warning:** although bindings for non-ES6 class controllers are currently
- * bound to `this` before the controller constructor is called, this use is now deprecated. Please place initialization
- * code that relies upon bindings inside a `$onInit` method on the controller, instead.
- * </div>
- *
- * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.
- * This will set up the scope bindings to the controller directly. Note that `scope` can still be used
- * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate
- * scope (useful for component directives).
- *
- * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`.
- *
- *
- * #### `controller`
- * Controller constructor function. The controller is instantiated before the
- * pre-linking phase and can be accessed by other directives (see
- * `require` attribute). This allows the directives to communicate with each other and augment
- * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
- *
- * * `$scope` - Current scope associated with the element
- * * `$element` - Current element
- * * `$attrs` - Current attributes object for the element
- * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
- * `function([scope], cloneLinkingFn, futureParentElement, slotName)`:
- * * `scope`: (optional) override the scope.
- * * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content.
- * * `futureParentElement` (optional):
- * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
- * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
- * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
- * and when the `cloneLinkinFn` is passed,
- * as those elements need to created and cloned in a special way when they are defined outside their
- * usual containers (e.g. like `<svg>`).
- * * See also the `directive.templateNamespace` property.
- * * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`)
- * then the default translusion is provided.
- * The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns
- * `true` if the specified slot contains content (i.e. one or more DOM nodes).
- *
- * The controller can provide the following methods that act as life-cycle hooks:
- * * `$onInit` - Called on each controller after all the controllers on an element have been constructed and
- * had their bindings initialized (and before the pre &amp; post linking functions for the directives on
- * this element). This is a good place to put initialization code for your controller.
- *
- * #### `require`
- * Require another directive and inject its controller as the fourth argument to the linking function. The
- * `require` property can be a string, an array or an object:
- * * a **string** containing the name of the directive to pass to the linking function
- * * an **array** containing the names of directives to pass to the linking function. The argument passed to the
- * linking function will be an array of controllers in the same order as the names in the `require` property
- * * an **object** whose property values are the names of the directives to pass to the linking function. The argument
- * passed to the linking function will also be an object with matching keys, whose values will hold the corresponding
- * controllers.
- *
- * If the `require` property is an object and `bindToController` is truthy, then the required controllers are
- * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers
- * have been constructed but before `$onInit` is called.
- * See the {@link $compileProvider#component} helper for an example of how this can be used.
- *
- * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is
- * raised (unless no link function is specified and the required controllers are not being bound to the directive
- * controller, in which case error checking is skipped). The name can be prefixed with:
- *
- * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
- * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
- * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
- * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
- * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
- * `null` to the `link` fn if not found.
- * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
- * `null` to the `link` fn if not found.
- *
- *
- * #### `controllerAs`
- * Identifier name for a reference to the controller in the directive's scope.
- * This allows the controller to be referenced from the directive template. This is especially
- * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible
- * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the
- * `controllerAs` reference might overwrite a property that already exists on the parent scope.
- *
- *
- * #### `restrict`
- * String of subset of `EACM` which restricts the directive to a specific directive
- * declaration style. If omitted, the defaults (elements and attributes) are used.
- *
- * * `E` - Element name (default): `<my-directive></my-directive>`
- * * `A` - Attribute (default): `<div my-directive="exp"></div>`
- * * `C` - Class: `<div class="my-directive: exp;"></div>`
- * * `M` - Comment: `<!-- directive: my-directive exp -->`
- *
- *
- * #### `templateNamespace`
- * String representing the document type used by the markup in the template.
- * AngularJS needs this information as those elements need to be created and cloned
- * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
- *
- * * `html` - All root nodes in the template are HTML. Root nodes may also be
- * top-level elements such as `<svg>` or `<math>`.
- * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
- * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
- *
- * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
- *
- * #### `template`
- * HTML markup that may:
- * * Replace the contents of the directive's element (default).
- * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
- * * Wrap the contents of the directive's element (if `transclude` is true).
- *
- * Value may be:
- *
- * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
- * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
- * function api below) and returns a string value.
- *
- *
- * #### `templateUrl`
- * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
- *
- * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
- * for later when the template has been resolved. In the meantime it will continue to compile and link
- * sibling and parent elements as though this element had not contained any directives.
- *
- * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
- * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
- * case when only one deeply nested directive has `templateUrl`.
- *
- * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
- *
- * You can specify `templateUrl` as a string representing the URL or as a function which takes two
- * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
- * a string value representing the url. In either case, the template URL is passed through {@link
- * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
- *
- *
- * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
- * specify what the template should replace. Defaults to `false`.
- *
- * * `true` - the template will replace the directive's element.
- * * `false` - the template will replace the contents of the directive's element.
- *
- * The replacement process migrates all of the attributes / classes from the old element to the new
- * one. See the {@link guide/directive#template-expanding-directive
- * Directives Guide} for an example.
- *
- * There are very few scenarios where element replacement is required for the application function,
- * the main one being reusable custom components that are used within SVG contexts
- * (because SVG doesn't work with custom elements in the DOM tree).
- *
- * #### `transclude`
- * Extract the contents of the element where the directive appears and make it available to the directive.
- * The contents are compiled and provided to the directive as a **transclusion function**. See the
- * {@link $compile#transclusion Transclusion} section below.
- *
- *
- * #### `compile`
- *
- * ```js
- * function compile(tElement, tAttrs, transclude) { ... }
- * ```
- *
- * The compile function deals with transforming the template DOM. Since most directives do not do
- * template transformation, it is not used often. The compile function takes the following arguments:
- *
- * * `tElement` - template element - The element where the directive has been declared. It is
- * safe to do template transformation on the element and child elements only.
- *
- * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
- * between all directive compile functions.
- *
- * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
- *
- * <div class="alert alert-warning">
- * **Note:** The template instance and the link instance may be different objects if the template has
- * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
- * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
- * should be done in a linking function rather than in a compile function.
- * </div>
-
- * <div class="alert alert-warning">
- * **Note:** The compile function cannot handle directives that recursively use themselves in their
- * own templates or compile functions. Compiling these directives results in an infinite loop and
- * stack overflow errors.
- *
- * This can be avoided by manually using $compile in the postLink function to imperatively compile
- * a directive's template instead of relying on automatic template compilation via `template` or
- * `templateUrl` declaration or manual compilation inside the compile function.
- * </div>
- *
- * <div class="alert alert-danger">
- * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
- * e.g. does not know about the right outer scope. Please use the transclude function that is passed
- * to the link function instead.
- * </div>
-
- * A compile function can have a return value which can be either a function or an object.
- *
- * * returning a (post-link) function - is equivalent to registering the linking function via the
- * `link` property of the config object when the compile function is empty.
- *
- * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
- * control when a linking function should be called during the linking phase. See info about
- * pre-linking and post-linking functions below.
- *
- *
- * #### `link`
- * This property is used only if the `compile` property is not defined.
- *
- * ```js
- * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
- * ```
- *
- * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
- * executed after the template has been cloned. This is where most of the directive logic will be
- * put.
- *
- * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
- * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
- *
- * * `iElement` - instance element - The element where the directive is to be used. It is safe to
- * manipulate the children of the element only in `postLink` function since the children have
- * already been linked.
- *
- * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
- * between all directive linking functions.
- *
- * * `controller` - the directive's required controller instance(s) - Instances are shared
- * among all directives, which allows the directives to use the controllers as a communication
- * channel. The exact value depends on the directive's `require` property:
- * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
- * * `string`: the controller instance
- * * `array`: array of controller instances
- *
- * If a required controller cannot be found, and it is optional, the instance is `null`,
- * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
- *
- * Note that you can also require the directive's own controller - it will be made available like
- * any other controller.
- *
- * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
- * This is the same as the `$transclude`
- * parameter of directive controllers, see there for details.
- * `function([scope], cloneLinkingFn, futureParentElement)`.
- *
- * #### Pre-linking function
- *
- * Executed before the child elements are linked. Not safe to do DOM transformation since the
- * compiler linking function will fail to locate the correct elements for linking.
- *
- * #### Post-linking function
- *
- * Executed after the child elements are linked.
- *
- * Note that child elements that contain `templateUrl` directives will not have been compiled
- * and linked since they are waiting for their template to load asynchronously and their own
- * compilation and linking has been suspended until that occurs.
- *
- * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
- * for their async templates to be resolved.
- *
- *
- * ### Transclusion
- *
- * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and
- * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
- * scope from where they were taken.
- *
- * Transclusion is used (often with {@link ngTransclude}) to insert the
- * original contents of a directive's element into a specified place in the template of the directive.
- * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
- * content has access to the properties on the scope from which it was taken, even if the directive
- * has isolated scope.
- * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
- *
- * This makes it possible for the widget to have private state for its template, while the transcluded
- * content has access to its originating scope.
- *
- * <div class="alert alert-warning">
- * **Note:** When testing an element transclude directive you must not place the directive at the root of the
- * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
- * Testing Transclusion Directives}.
- * </div>
- *
- * There are three kinds of transclusion depending upon whether you want to transclude just the contents of the
- * directive's element, the entire element or multiple parts of the element contents:
- *
- * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
- * * `'element'` - transclude the whole of the directive's element including any directives on this
- * element that defined at a lower priority than this directive. When used, the `template`
- * property is ignored.
- * * **`{...}` (an object hash):** - map elements of the content onto transclusion "slots" in the template.
- *
- * **Mult-slot transclusion** is declared by providing an object for the `transclude` property.
- *
- * This object is a map where the keys are the name of the slot to fill and the value is an element selector
- * used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`)
- * and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc).
- *
- * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
- *
- * If the element selector is prefixed with a `?` then that slot is optional.
- *
- * For example, the transclude object `{ slotA: '?myCustomElement' }` maps `<my-custom-element>` elements to
- * the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive.
- *
- * Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements
- * in the transclude content. If you wish to know if an optional slot was filled with content, then you can call
- * `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and
- * injectable into the directive's controller.
- *
- *
- * #### Transclusion Functions
- *
- * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
- * function** to the directive's `link` function and `controller`. This transclusion function is a special
- * **linking function** that will return the compiled contents linked to a new transclusion scope.
- *
- * <div class="alert alert-info">
- * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
- * ngTransclude will deal with it for us.
- * </div>
- *
- * If you want to manually control the insertion and removal of the transcluded content in your directive
- * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
- * object that contains the compiled DOM, which is linked to the correct transclusion scope.
- *
- * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
- * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
- * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
- *
- * <div class="alert alert-info">
- * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function
- * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
- * </div>
- *
- * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
- * attach function**:
- *
- * ```js
- * var transcludedContent, transclusionScope;
- *
- * $transclude(function(clone, scope) {
- * element.append(clone);
- * transcludedContent = clone;
- * transclusionScope = scope;
- * });
- * ```
- *
- * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
- * associated transclusion scope:
- *
- * ```js
- * transcludedContent.remove();
- * transclusionScope.$destroy();
- * ```
- *
- * <div class="alert alert-info">
- * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
- * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it),
- * then you are also responsible for calling `$destroy` on the transclusion scope.
- * </div>
- *
- * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
- * automatically destroy their transcluded clones as necessary so you do not need to worry about this if
- * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
- *
- *
- * #### Transclusion Scopes
- *
- * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
- * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
- * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
- * was taken.
- *
- * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
- * like this:
- *
- * ```html
- * <div ng-app>
- * <div isolate>
- * <div transclusion>
- * </div>
- * </div>
- * </div>
- * ```
- *
- * The `$parent` scope hierarchy will look like this:
- *
- ```
- - $rootScope
- - isolate
- - transclusion
- ```
- *
- * but the scopes will inherit prototypically from different scopes to their `$parent`.
- *
- ```
- - $rootScope
- - transclusion
- - isolate
- ```
- *
- *
- * ### Attributes
- *
- * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
- * `link()` or `compile()` functions. It has a variety of uses.
- *
- * * *Accessing normalized attribute names:* Directives like 'ngBind' can be expressed in many ways:
- * 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. The attributes object allows for normalized access
- * to the attributes.
- *
- * * *Directive inter-communication:* All directives share the same instance of the attributes
- * object which allows the directives to use the attributes object as inter directive
- * communication.
- *
- * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
- * allowing other directives to read the interpolated value.
- *
- * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
- * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
- * the only way to easily get the actual value because during the linking phase the interpolation
- * hasn't been evaluated yet and so the value is at this time set to `undefined`.
- *
- * ```js
- * function linkingFn(scope, elm, attrs, ctrl) {
- * // get the attribute value
- * console.log(attrs.ngModel);
- *
- * // change the attribute
- * attrs.$set('ngModel', 'new value');
- *
- * // observe changes to interpolated attribute
- * attrs.$observe('ngModel', function(value) {
- * console.log('ngModel has changed value to ' + value);
- * });
- * }
- * ```
- *
- * ## Example
- *
- * <div class="alert alert-warning">
- * **Note**: Typically directives are registered with `module.directive`. The example below is
- * to illustrate how `$compile` works.
- * </div>
- *
- <example module="compileExample">
- <file name="index.html">
- <script>
- angular.module('compileExample', [], function($compileProvider) {
- // configure new 'compile' directive by passing a directive
- // factory function. The factory function injects the '$compile'
- $compileProvider.directive('compile', function($compile) {
- // directive factory creates a link function
- return function(scope, element, attrs) {
- scope.$watch(
- function(scope) {
- // watch the 'compile' expression for changes
- return scope.$eval(attrs.compile);
- },
- function(value) {
- // when the 'compile' expression changes
- // assign it into the current DOM
- element.html(value);
-
- // compile the new DOM and link it to the current
- // scope.
- // NOTE: we only compile .childNodes so that
- // we don't get into infinite loop compiling ourselves
- $compile(element.contents())(scope);
- }
- );
- };
- });
- })
- .controller('GreeterController', ['$scope', function($scope) {
- $scope.name = 'Angular';
- $scope.html = 'Hello {{name}}';
- }]);
- </script>
- <div ng-controller="GreeterController">
- <input ng-model="name"> <br/>
- <textarea ng-model="html"></textarea> <br/>
- <div compile="html"></div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should auto compile', function() {
- var textarea = $('textarea');
- var output = $('div[compile]');
- // The initial state reads 'Hello Angular'.
- expect(output.getText()).toBe('Hello Angular');
- textarea.clear();
- textarea.sendKeys('{{name}}!');
- expect(output.getText()).toBe('Angular!');
- });
- </file>
- </example>
-
- *
- *
- * @param {string|DOMElement} element Element or HTML string to compile into a template function.
- * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
- *
- * <div class="alert alert-danger">
- * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
- * e.g. will not use the right outer scope. Please pass the transclude function as a
- * `parentBoundTranscludeFn` to the link function instead.
- * </div>
- *
- * @param {number} maxPriority only apply directives lower than given priority (Only effects the
- * root element(s), not their children)
- * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
- * (a DOM element/tree) to a scope. Where:
- *
- * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
- * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
- * `template` and call the `cloneAttachFn` function allowing the caller to attach the
- * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
- * called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
- *
- * * `clonedElement` - is a clone of the original `element` passed into the compiler.
- * * `scope` - is the current scope with which the linking function is working with.
- *
- * * `options` - An optional object hash with linking options. If `options` is provided, then the following
- * keys may be used to control linking behavior:
- *
- * * `parentBoundTranscludeFn` - the transclude function made available to
- * directives; if given, it will be passed through to the link functions of
- * directives found in `element` during compilation.
- * * `transcludeControllers` - an object hash with keys that map controller names
- * to a hash with the key `instance`, which maps to the controller instance;
- * if given, it will make the controllers available to directives on the compileNode:
- * ```
- * {
- * parent: {
- * instance: parentControllerInstance
- * }
- * }
- * ```
- * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
- * the cloned elements; only needed for transcludes that are allowed to contain non html
- * elements (e.g. SVG elements). See also the directive.controller property.
- *
- * Calling the linking function returns the element of the template. It is either the original
- * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
- *
- * After linking the view is not updated until after a call to $digest which typically is done by
- * Angular automatically.
- *
- * If you need access to the bound view, there are two ways to do it:
- *
- * - If you are not asking the linking function to clone the template, create the DOM element(s)
- * before you send them to the compiler and keep this reference around.
- * ```js
- * var element = $compile('<p>{{total}}</p>')(scope);
- * ```
- *
- * - if on the other hand, you need the element to be cloned, the view reference from the original
- * example would not point to the clone, but rather to the original template that was cloned. In
- * this case, you can access the clone via the cloneAttachFn:
- * ```js
- * var templateElement = angular.element('<p>{{total}}</p>'),
- * scope = ....;
- *
- * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
- * //attach the clone to DOM document at the right place
- * });
- *
- * //now we have reference to the cloned DOM via `clonedElement`
- * ```
- *
- *
- * For information on how the compiler works, see the
- * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
- */
-
-var $compileMinErr = minErr('$compile');
-
-/**
- * @ngdoc provider
- * @name $compileProvider
- *
- * @description
- */
-$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
-function $CompileProvider($provide, $$sanitizeUriProvider) {
- var hasDirectives = {},
- Suffix = 'Directive',
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
- ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
- REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
-
- // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
- // The assumption is that future DOM event attribute names will begin with
- // 'on' and be composed of only English letters.
- var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
-
- function parseIsolateBindings(scope, directiveName, isController) {
- var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
-
- var bindings = {};
-
- forEach(scope, function(definition, scopeName) {
- var match = definition.match(LOCAL_REGEXP);
-
- if (!match) {
- throw $compileMinErr('iscp',
- "Invalid {3} for directive '{0}'." +
- " Definition: {... {1}: '{2}' ...}",
- directiveName, scopeName, definition,
- (isController ? "controller bindings definition" :
- "isolate scope definition"));
- }
-
- bindings[scopeName] = {
- mode: match[1][0],
- collection: match[2] === '*',
- optional: match[3] === '?',
- attrName: match[4] || scopeName
- };
- });
-
- return bindings;
- }
-
- function parseDirectiveBindings(directive, directiveName) {
- var bindings = {
- isolateScope: null,
- bindToController: null
- };
- if (isObject(directive.scope)) {
- if (directive.bindToController === true) {
- bindings.bindToController = parseIsolateBindings(directive.scope,
- directiveName, true);
- bindings.isolateScope = {};
- } else {
- bindings.isolateScope = parseIsolateBindings(directive.scope,
- directiveName, false);
- }
- }
- if (isObject(directive.bindToController)) {
- bindings.bindToController =
- parseIsolateBindings(directive.bindToController, directiveName, true);
- }
- if (isObject(bindings.bindToController)) {
- var controller = directive.controller;
- var controllerAs = directive.controllerAs;
- if (!controller) {
- // There is no controller, there may or may not be a controllerAs property
- throw $compileMinErr('noctrl',
- "Cannot bind to controller without directive '{0}'s controller.",
- directiveName);
- } else if (!identifierForController(controller, controllerAs)) {
- // There is a controller, but no identifier or controllerAs property
- throw $compileMinErr('noident',
- "Cannot bind to controller without identifier for directive '{0}'.",
- directiveName);
- }
- }
- return bindings;
- }
-
- function assertValidDirectiveName(name) {
- var letter = name.charAt(0);
- if (!letter || letter !== lowercase(letter)) {
- throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
- }
- if (name !== name.trim()) {
- throw $compileMinErr('baddir',
- "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
- name);
- }
- }
-
- /**
- * @ngdoc method
- * @name $compileProvider#directive
- * @kind function
- *
- * @description
- * Register a new directive with the compiler.
- *
- * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
- * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
- * names and the values are the factories.
- * @param {Function|Array} directiveFactory An injectable directive factory function. See the
- * {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
- * @returns {ng.$compileProvider} Self for chaining.
- */
- this.directive = function registerDirective(name, directiveFactory) {
- assertNotHasOwnProperty(name, 'directive');
- if (isString(name)) {
- assertValidDirectiveName(name);
- assertArg(directiveFactory, 'directiveFactory');
- if (!hasDirectives.hasOwnProperty(name)) {
- hasDirectives[name] = [];
- $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
- function($injector, $exceptionHandler) {
- var directives = [];
- forEach(hasDirectives[name], function(directiveFactory, index) {
- try {
- var directive = $injector.invoke(directiveFactory);
- if (isFunction(directive)) {
- directive = { compile: valueFn(directive) };
- } else if (!directive.compile && directive.link) {
- directive.compile = valueFn(directive.link);
- }
- directive.priority = directive.priority || 0;
- directive.index = index;
- directive.name = directive.name || name;
- directive.require = directive.require || (directive.controller && directive.name);
- directive.restrict = directive.restrict || 'EA';
- var bindings = directive.$$bindings =
- parseDirectiveBindings(directive, directive.name);
- if (isObject(bindings.isolateScope)) {
- directive.$$isolateBindings = bindings.isolateScope;
- }
- directive.$$moduleName = directiveFactory.$$moduleName;
- directives.push(directive);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- return directives;
- }]);
- }
- hasDirectives[name].push(directiveFactory);
- } else {
- forEach(name, reverseParams(registerDirective));
- }
- return this;
- };
-
- /**
- * @ngdoc method
- * @name $compileProvider#component
- * @module ng
- * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`)
- * @param {Object} options Component definition object (a simplified
- * {@link ng.$compile#directive-definition-object directive definition object}),
- * with the following properties (all optional):
- *
- * - `controller` – `{(string|function()=}` – controller constructor function that should be
- * associated with newly created scope or the name of a {@link ng.$compile#-controller-
- * registered controller} if passed as a string. An empty `noop` function by default.
- * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
- * If present, the controller will be published to scope under the `controllerAs` name.
- * If not present, this will default to be `$ctrl`.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used as the contents of this component.
- * Empty string by default.
- *
- * If `template` is a function, then it is {@link auto.$injector#invoke injected} with
- * the following locals:
- *
- * - `$element` - Current element
- * - `$attrs` - Current attributes object for the element
- *
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
- * template that should be used as the contents of this component.
- *
- * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
- * the following locals:
- *
- * - `$element` - Current element
- * - `$attrs` - Current attributes object for the element
- *
- * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
- * Component properties are always bound to the component controller and not to the scope.
- * See {@link ng.$compile#-bindtocontroller- `bindToController`}.
- * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.
- * Disabled by default.
- * - `$...` – `{function()=}` – additional annotations to provide to the directive factory function.
- *
- * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls.
- * @description
- * Register a **component definition** with the compiler. This is a shorthand for registering a special
- * type of directive, which represents a self-contained UI component in your application. Such components
- * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`).
- *
- * Component definitions are very simple and do not require as much configuration as defining general
- * directives. Component definitions usually consist only of a template and a controller backing it.
- *
- * In order to make the definition easier, components enforce best practices like use of `controllerAs`,
- * `bindToController`. They always have **isolate scope** and are restricted to elements.
- *
- * Here are a few examples of how you would usually define components:
- *
- * ```js
- * var myMod = angular.module(...);
- * myMod.component('myComp', {
- * template: '<div>My name is {{$ctrl.name}}</div>',
- * controller: function() {
- * this.name = 'shahar';
- * }
- * });
- *
- * myMod.component('myComp', {
- * template: '<div>My name is {{$ctrl.name}}</div>',
- * bindings: {name: '@'}
- * });
- *
- * myMod.component('myComp', {
- * templateUrl: 'views/my-comp.html',
- * controller: 'MyCtrl as ctrl',
- * bindings: {name: '@'}
- * });
- *
- * ```
- * For more examples, and an in-depth guide, see the {@link guide/component component guide}.
- *
- * <br />
- * See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
- */
- this.component = function registerComponent(name, options) {
- var controller = options.controller || function() {};
-
- function factory($injector) {
- function makeInjectable(fn) {
- if (isFunction(fn) || isArray(fn)) {
- return function(tElement, tAttrs) {
- return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
- };
- } else {
- return fn;
- }
- }
-
- var template = (!options.template && !options.templateUrl ? '' : options.template);
- return {
- controller: controller,
- controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
- template: makeInjectable(template),
- templateUrl: makeInjectable(options.templateUrl),
- transclude: options.transclude,
- scope: {},
- bindToController: options.bindings || {},
- restrict: 'E',
- require: options.require
- };
- }
-
- // Copy any annotation properties (starting with $) over to the factory function
- // These could be used by libraries such as the new component router
- forEach(options, function(val, key) {
- if (key.charAt(0) === '$') {
- factory[key] = val;
- }
- });
-
- factory.$inject = ['$injector'];
-
- return this.directive(name, factory);
- };
-
-
- /**
- * @ngdoc method
- * @name $compileProvider#aHrefSanitizationWhitelist
- * @kind function
- *
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during a[href] sanitization.
- *
- * The sanitization is a security measure aimed at preventing XSS attacks via html links.
- *
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
- }
- };
-
-
- /**
- * @ngdoc method
- * @name $compileProvider#imgSrcSanitizationWhitelist
- * @kind function
- *
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during img[src] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
- }
- };
-
- /**
- * @ngdoc method
- * @name $compileProvider#debugInfoEnabled
- *
- * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
- * current debugInfoEnabled state
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- *
- * @kind function
- *
- * @description
- * Call this method to enable/disable various debug runtime information in the compiler such as adding
- * binding information and a reference to the current scope on to DOM elements.
- * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
- * * `ng-binding` CSS class
- * * `$binding` data property containing an array of the binding expressions
- *
- * You may want to disable this in production for a significant performance boost. See
- * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
- *
- * The default value is true.
- */
- var debugInfoEnabled = true;
- this.debugInfoEnabled = function(enabled) {
- if (isDefined(enabled)) {
- debugInfoEnabled = enabled;
- return this;
- }
- return debugInfoEnabled;
- };
-
- this.$get = [
- '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
- '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
- function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
- $controller, $rootScope, $sce, $animate, $$sanitizeUri) {
-
- var SIMPLE_ATTR_NAME = /^\w/;
- var specialAttrHolder = document.createElement('div');
- var Attributes = function(element, attributesToCopy) {
- if (attributesToCopy) {
- var keys = Object.keys(attributesToCopy);
- var i, l, key;
-
- for (i = 0, l = keys.length; i < l; i++) {
- key = keys[i];
- this[key] = attributesToCopy[key];
- }
- } else {
- this.$attr = {};
- }
-
- this.$$element = element;
- };
-
- Attributes.prototype = {
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$normalize
- * @kind function
- *
- * @description
- * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
- * `data-`) to its normalized, camelCase form.
- *
- * Also there is special case for Moz prefix starting with upper case letter.
- *
- * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
- *
- * @param {string} name Name to normalize
- */
- $normalize: directiveNormalize,
-
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$addClass
- * @kind function
- *
- * @description
- * Adds the CSS class value specified by the classVal parameter to the element. If animations
- * are enabled then an animation will be triggered for the class addition.
- *
- * @param {string} classVal The className value that will be added to the element
- */
- $addClass: function(classVal) {
- if (classVal && classVal.length > 0) {
- $animate.addClass(this.$$element, classVal);
- }
- },
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$removeClass
- * @kind function
- *
- * @description
- * Removes the CSS class value specified by the classVal parameter from the element. If
- * animations are enabled then an animation will be triggered for the class removal.
- *
- * @param {string} classVal The className value that will be removed from the element
- */
- $removeClass: function(classVal) {
- if (classVal && classVal.length > 0) {
- $animate.removeClass(this.$$element, classVal);
- }
- },
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$updateClass
- * @kind function
- *
- * @description
- * Adds and removes the appropriate CSS class values to the element based on the difference
- * between the new and old CSS class values (specified as newClasses and oldClasses).
- *
- * @param {string} newClasses The current CSS className value
- * @param {string} oldClasses The former CSS className value
- */
- $updateClass: function(newClasses, oldClasses) {
- var toAdd = tokenDifference(newClasses, oldClasses);
- if (toAdd && toAdd.length) {
- $animate.addClass(this.$$element, toAdd);
- }
-
- var toRemove = tokenDifference(oldClasses, newClasses);
- if (toRemove && toRemove.length) {
- $animate.removeClass(this.$$element, toRemove);
- }
- },
-
- /**
- * Set a normalized attribute on the element in a way such that all directives
- * can share the attribute. This function properly handles boolean attributes.
- * @param {string} key Normalized key. (ie ngAttribute)
- * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
- * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
- * Defaults to true.
- * @param {string=} attrName Optional none normalized name. Defaults to key.
- */
- $set: function(key, value, writeAttr, attrName) {
- // TODO: decide whether or not to throw an error if "class"
- //is set through this function since it may cause $updateClass to
- //become unstable.
-
- var node = this.$$element[0],
- booleanKey = getBooleanAttrName(node, key),
- aliasedKey = getAliasedAttrName(key),
- observer = key,
- nodeName;
-
- if (booleanKey) {
- this.$$element.prop(key, value);
- attrName = booleanKey;
- } else if (aliasedKey) {
- this[aliasedKey] = value;
- observer = aliasedKey;
- }
-
- this[key] = value;
-
- // translate normalized key to actual key
- if (attrName) {
- this.$attr[key] = attrName;
- } else {
- attrName = this.$attr[key];
- if (!attrName) {
- this.$attr[key] = attrName = snake_case(key, '-');
- }
- }
-
- nodeName = nodeName_(this.$$element);
-
- if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||
- (nodeName === 'img' && key === 'src')) {
- // sanitize a[href] and img[src] values
- this[key] = value = $$sanitizeUri(value, key === 'src');
- } else if (nodeName === 'img' && key === 'srcset') {
- // sanitize img[srcset] values
- var result = "";
-
- // first check if there are spaces because it's not the same pattern
- var trimmedSrcset = trim(value);
- // ( 999x ,| 999w ,| ,|, )
- var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
- var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
-
- // split srcset into tuple of uri and descriptor except for the last item
- var rawUris = trimmedSrcset.split(pattern);
-
- // for each tuples
- var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
- for (var i = 0; i < nbrUrisWith2parts; i++) {
- var innerIdx = i * 2;
- // sanitize the uri
- result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
- // add the descriptor
- result += (" " + trim(rawUris[innerIdx + 1]));
- }
-
- // split the last item into uri and descriptor
- var lastTuple = trim(rawUris[i * 2]).split(/\s/);
-
- // sanitize the last uri
- result += $$sanitizeUri(trim(lastTuple[0]), true);
-
- // and add the last descriptor if any
- if (lastTuple.length === 2) {
- result += (" " + trim(lastTuple[1]));
- }
- this[key] = value = result;
- }
-
- if (writeAttr !== false) {
- if (value === null || isUndefined(value)) {
- this.$$element.removeAttr(attrName);
- } else {
- if (SIMPLE_ATTR_NAME.test(attrName)) {
- this.$$element.attr(attrName, value);
- } else {
- setSpecialAttr(this.$$element[0], attrName, value);
- }
- }
- }
-
- // fire observers
- var $$observers = this.$$observers;
- $$observers && forEach($$observers[observer], function(fn) {
- try {
- fn(value);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- },
-
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$observe
- * @kind function
- *
- * @description
- * Observes an interpolated attribute.
- *
- * The observer function will be invoked once during the next `$digest` following
- * compilation. The observer is then invoked whenever the interpolated value
- * changes.
- *
- * @param {string} key Normalized key. (ie ngAttribute) .
- * @param {function(interpolatedValue)} fn Function that will be called whenever
- the interpolated value of the attribute changes.
- * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation
- * guide} for more info.
- * @returns {function()} Returns a deregistration function for this observer.
- */
- $observe: function(key, fn) {
- var attrs = this,
- $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
- listeners = ($$observers[key] || ($$observers[key] = []));
-
- listeners.push(fn);
- $rootScope.$evalAsync(function() {
- if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {
- // no one registered attribute interpolation function, so lets call it manually
- fn(attrs[key]);
- }
- });
-
- return function() {
- arrayRemove(listeners, fn);
- };
- }
- };
-
- function setSpecialAttr(element, attrName, value) {
- // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute`
- // so we have to jump through some hoops to get such an attribute
- // https://github.com/angular/angular.js/pull/13318
- specialAttrHolder.innerHTML = "<span " + attrName + ">";
- var attributes = specialAttrHolder.firstChild.attributes;
- var attribute = attributes[0];
- // We have to remove the attribute from its container element before we can add it to the destination element
- attributes.removeNamedItem(attribute.name);
- attribute.value = value;
- element.attributes.setNamedItem(attribute);
- }
-
- function safeAddClass($element, className) {
- try {
- $element.addClass(className);
- } catch (e) {
- // ignore, since it means that we are trying to set class on
- // SVG element, where class name is read-only.
- }
- }
-
-
- var startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}')
- ? identity
- : function denormalizeTemplate(template) {
- return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
- },
- NG_ATTR_BINDING = /^ngAttr[A-Z]/;
- var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;
-
- compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
- var bindings = $element.data('$binding') || [];
-
- if (isArray(binding)) {
- bindings = bindings.concat(binding);
- } else {
- bindings.push(binding);
- }
-
- $element.data('$binding', bindings);
- } : noop;
-
- compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
- safeAddClass($element, 'ng-binding');
- } : noop;
-
- compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
- var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
- $element.data(dataName, scope);
- } : noop;
-
- compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
- safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
- } : noop;
-
- return compile;
-
- //================================
-
- function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
- previousCompileContext) {
- if (!($compileNodes instanceof jqLite)) {
- // jquery always rewraps, whereas we need to preserve the original selector so that we can
- // modify it.
- $compileNodes = jqLite($compileNodes);
- }
-
- var NOT_EMPTY = /\S+/;
-
- // We can not compile top level text elements since text nodes can be merged and we will
- // not be able to attach scope data to them, so we will wrap them in <span>
- for (var i = 0, len = $compileNodes.length; i < len; i++) {
- var domNode = $compileNodes[i];
-
- if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {
- jqLiteWrapNode(domNode, $compileNodes[i] = document.createElement('span'));
- }
- }
-
- var compositeLinkFn =
- compileNodes($compileNodes, transcludeFn, $compileNodes,
- maxPriority, ignoreDirective, previousCompileContext);
- compile.$$addScopeClass($compileNodes);
- var namespace = null;
- return function publicLinkFn(scope, cloneConnectFn, options) {
- assertArg(scope, 'scope');
-
- if (previousCompileContext && previousCompileContext.needsNewScope) {
- // A parent directive did a replace and a directive on this element asked
- // for transclusion, which caused us to lose a layer of element on which
- // we could hold the new transclusion scope, so we will create it manually
- // here.
- scope = scope.$parent.$new();
- }
-
- options = options || {};
- var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
- transcludeControllers = options.transcludeControllers,
- futureParentElement = options.futureParentElement;
-
- // When `parentBoundTranscludeFn` is passed, it is a
- // `controllersBoundTransclude` function (it was previously passed
- // as `transclude` to directive.link) so we must unwrap it to get
- // its `boundTranscludeFn`
- if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
- parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
- }
-
- if (!namespace) {
- namespace = detectNamespaceForChildElements(futureParentElement);
- }
- var $linkNode;
- if (namespace !== 'html') {
- // When using a directive with replace:true and templateUrl the $compileNodes
- // (or a child element inside of them)
- // might change, so we need to recreate the namespace adapted compileNodes
- // for call to the link function.
- // Note: This will already clone the nodes...
- $linkNode = jqLite(
- wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
- );
- } else if (cloneConnectFn) {
- // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
- // and sometimes changes the structure of the DOM.
- $linkNode = JQLitePrototype.clone.call($compileNodes);
- } else {
- $linkNode = $compileNodes;
- }
-
- if (transcludeControllers) {
- for (var controllerName in transcludeControllers) {
- $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
- }
- }
-
- compile.$$addScopeInfo($linkNode, scope);
-
- if (cloneConnectFn) cloneConnectFn($linkNode, scope);
- if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
- return $linkNode;
- };
- }
-
- function detectNamespaceForChildElements(parentElement) {
- // TODO: Make this detect MathML as well...
- var node = parentElement && parentElement[0];
- if (!node) {
- return 'html';
- } else {
- return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html';
- }
- }
-
- /**
- * Compile function matches each node in nodeList against the directives. Once all directives
- * for a particular node are collected their compile functions are executed. The compile
- * functions return values - the linking functions - are combined into a composite linking
- * function, which is the a linking function for the node.
- *
- * @param {NodeList} nodeList an array of nodes or NodeList to compile
- * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
- * scope argument is auto-generated to the new child of the transcluded parent scope.
- * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
- * the rootElement must be set the jqLite collection of the compile root. This is
- * needed so that the jqLite collection items can be replaced with widgets.
- * @param {number=} maxPriority Max directive priority.
- * @returns {Function} A composite linking function of all of the matched directives or null.
- */
- function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
- previousCompileContext) {
- var linkFns = [],
- attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
-
- for (var i = 0; i < nodeList.length; i++) {
- attrs = new Attributes();
-
- // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
- directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
- ignoreDirective);
-
- nodeLinkFn = (directives.length)
- ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
- null, [], [], previousCompileContext)
- : null;
-
- if (nodeLinkFn && nodeLinkFn.scope) {
- compile.$$addScopeClass(attrs.$$element);
- }
-
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
- !(childNodes = nodeList[i].childNodes) ||
- !childNodes.length)
- ? null
- : compileNodes(childNodes,
- nodeLinkFn ? (
- (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
- && nodeLinkFn.transclude) : transcludeFn);
-
- if (nodeLinkFn || childLinkFn) {
- linkFns.push(i, nodeLinkFn, childLinkFn);
- linkFnFound = true;
- nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
- }
-
- //use the previous context only for the first element in the virtual group
- previousCompileContext = null;
- }
-
- // return a linking function if we have found anything, null otherwise
- return linkFnFound ? compositeLinkFn : null;
-
- function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
- var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
- var stableNodeList;
-
-
- if (nodeLinkFnFound) {
- // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
- // offsets don't get screwed up
- var nodeListLength = nodeList.length;
- stableNodeList = new Array(nodeListLength);
-
- // create a sparse array by only copying the elements which have a linkFn
- for (i = 0; i < linkFns.length; i+=3) {
- idx = linkFns[i];
- stableNodeList[idx] = nodeList[idx];
- }
- } else {
- stableNodeList = nodeList;
- }
-
- for (i = 0, ii = linkFns.length; i < ii;) {
- node = stableNodeList[linkFns[i++]];
- nodeLinkFn = linkFns[i++];
- childLinkFn = linkFns[i++];
-
- if (nodeLinkFn) {
- if (nodeLinkFn.scope) {
- childScope = scope.$new();
- compile.$$addScopeInfo(jqLite(node), childScope);
- } else {
- childScope = scope;
- }
-
- if (nodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(
- scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
-
- } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
- childBoundTranscludeFn = parentBoundTranscludeFn;
-
- } else if (!parentBoundTranscludeFn && transcludeFn) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
-
- } else {
- childBoundTranscludeFn = null;
- }
-
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
-
- } else if (childLinkFn) {
- childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
- }
- }
- }
- }
-
- function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
-
- var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
-
- if (!transcludedScope) {
- transcludedScope = scope.$new(false, containingScope);
- transcludedScope.$$transcluded = true;
- }
-
- return transcludeFn(transcludedScope, cloneFn, {
- parentBoundTranscludeFn: previousBoundTranscludeFn,
- transcludeControllers: controllers,
- futureParentElement: futureParentElement
- });
- };
-
- // We need to attach the transclusion slots onto the `boundTranscludeFn`
- // so that they are available inside the `controllersBoundTransclude` function
- var boundSlots = boundTranscludeFn.$$slots = createMap();
- for (var slotName in transcludeFn.$$slots) {
- if (transcludeFn.$$slots[slotName]) {
- boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);
- } else {
- boundSlots[slotName] = null;
- }
- }
-
- return boundTranscludeFn;
- }
-
- /**
- * Looks for directives on the given node and adds them to the directive collection which is
- * sorted.
- *
- * @param node Node to search.
- * @param directives An array to which the directives are added to. This array is sorted before
- * the function returns.
- * @param attrs The shared attrs object which is used to populate the normalized attributes.
- * @param {number=} maxPriority Max directive priority.
- */
- function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
- var nodeType = node.nodeType,
- attrsMap = attrs.$attr,
- match,
- className;
-
- switch (nodeType) {
- case NODE_TYPE_ELEMENT: /* Element */
- // use the node name: <directive>
- addDirective(directives,
- directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
-
- // iterate over the attributes
- for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
- j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
- var attrStartName = false;
- var attrEndName = false;
-
- attr = nAttrs[j];
- name = attr.name;
- value = trim(attr.value);
-
- // support ngAttr attribute binding
- ngAttrName = directiveNormalize(name);
- if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
- name = name.replace(PREFIX_REGEXP, '')
- .substr(8).replace(/_(.)/g, function(match, letter) {
- return letter.toUpperCase();
- });
- }
-
- var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);
- if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {
- attrStartName = name;
- attrEndName = name.substr(0, name.length - 5) + 'end';
- name = name.substr(0, name.length - 6);
- }
-
- nName = directiveNormalize(name.toLowerCase());
- attrsMap[nName] = name;
- if (isNgAttr || !attrs.hasOwnProperty(nName)) {
- attrs[nName] = value;
- if (getBooleanAttrName(node, nName)) {
- attrs[nName] = true; // presence means true
- }
- }
- addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
- addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
- attrEndName);
- }
-
- // use class as directive
- className = node.className;
- if (isObject(className)) {
- // Maybe SVGAnimatedString
- className = className.animVal;
- }
- if (isString(className) && className !== '') {
- while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
- nName = directiveNormalize(match[2]);
- if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[3]);
- }
- className = className.substr(match.index + match[0].length);
- }
- }
- break;
- case NODE_TYPE_TEXT: /* Text Node */
- if (msie === 11) {
- // Workaround for #11781
- while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
- node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
- node.parentNode.removeChild(node.nextSibling);
- }
- }
- addTextInterpolateDirective(directives, node.nodeValue);
- break;
- case NODE_TYPE_COMMENT: /* Comment */
- try {
- match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
- if (match) {
- nName = directiveNormalize(match[1]);
- if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[2]);
- }
- }
- } catch (e) {
- // turns out that under some circumstances IE9 throws errors when one attempts to read
- // comment's node value.
- // Just ignore it and continue. (Can't seem to reproduce in test case.)
- }
- break;
- }
-
- directives.sort(byPriority);
- return directives;
- }
-
- /**
- * Given a node with an directive-start it collects all of the siblings until it finds
- * directive-end.
- * @param node
- * @param attrStart
- * @param attrEnd
- * @returns {*}
- */
- function groupScan(node, attrStart, attrEnd) {
- var nodes = [];
- var depth = 0;
- if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
- do {
- if (!node) {
- throw $compileMinErr('uterdir',
- "Unterminated attribute, found '{0}' but no matching '{1}' found.",
- attrStart, attrEnd);
- }
- if (node.nodeType == NODE_TYPE_ELEMENT) {
- if (node.hasAttribute(attrStart)) depth++;
- if (node.hasAttribute(attrEnd)) depth--;
- }
- nodes.push(node);
- node = node.nextSibling;
- } while (depth > 0);
- } else {
- nodes.push(node);
- }
-
- return jqLite(nodes);
- }
-
- /**
- * Wrapper for linking function which converts normal linking function into a grouped
- * linking function.
- * @param linkFn
- * @param attrStart
- * @param attrEnd
- * @returns {Function}
- */
- function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
- return function(scope, element, attrs, controllers, transcludeFn) {
- element = groupScan(element[0], attrStart, attrEnd);
- return linkFn(scope, element, attrs, controllers, transcludeFn);
- };
- }
-
- /**
- * A function generator that is used to support both eager and lazy compilation
- * linking function.
- * @param eager
- * @param $compileNodes
- * @param transcludeFn
- * @param maxPriority
- * @param ignoreDirective
- * @param previousCompileContext
- * @returns {Function}
- */
- function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {
- if (eager) {
- return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
- }
-
- var compiled;
-
- return function() {
- if (!compiled) {
- compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);
-
- // Null out all of these references in order to make them eligible for garbage collection
- // since this is a potentially long lived closure
- $compileNodes = transcludeFn = previousCompileContext = null;
- }
-
- return compiled.apply(this, arguments);
- };
- }
-
- /**
- * Once the directives have been collected, their compile functions are executed. This method
- * is responsible for inlining directive templates as well as terminating the application
- * of the directives if the terminal directive has been reached.
- *
- * @param {Array} directives Array of collected directives to execute their compile function.
- * this needs to be pre-sorted by priority order.
- * @param {Node} compileNode The raw DOM node to apply the compile functions to
- * @param {Object} templateAttrs The shared attribute function
- * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
- * scope argument is auto-generated to the new
- * child of the transcluded parent scope.
- * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
- * argument has the root jqLite array so that we can replace nodes
- * on it.
- * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
- * compiling the transclusion.
- * @param {Array.<Function>} preLinkFns
- * @param {Array.<Function>} postLinkFns
- * @param {Object} previousCompileContext Context used for previous compilation of the current
- * node
- * @returns {Function} linkFn
- */
- function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
- jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
- previousCompileContext) {
- previousCompileContext = previousCompileContext || {};
-
- var terminalPriority = -Number.MAX_VALUE,
- newScopeDirective = previousCompileContext.newScopeDirective,
- controllerDirectives = previousCompileContext.controllerDirectives,
- newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
- templateDirective = previousCompileContext.templateDirective,
- nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
- hasTranscludeDirective = false,
- hasTemplate = false,
- hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
- $compileNode = templateAttrs.$$element = jqLite(compileNode),
- directive,
- directiveName,
- $template,
- replaceDirective = originalReplaceDirective,
- childTranscludeFn = transcludeFn,
- linkFn,
- didScanForMultipleTransclusion = false,
- mightHaveMultipleTransclusionError = false,
- directiveValue;
-
- // executes all directives on the current element
- for (var i = 0, ii = directives.length; i < ii; i++) {
- directive = directives[i];
- var attrStart = directive.$$start;
- var attrEnd = directive.$$end;
-
- // collect multiblock sections
- if (attrStart) {
- $compileNode = groupScan(compileNode, attrStart, attrEnd);
- }
- $template = undefined;
-
- if (terminalPriority > directive.priority) {
- break; // prevent further processing of directives
- }
-
- if (directiveValue = directive.scope) {
-
- // skip the check for directives with async templates, we'll check the derived sync
- // directive when the template arrives
- if (!directive.templateUrl) {
- if (isObject(directiveValue)) {
- // This directive is trying to add an isolated scope.
- // Check that there is no scope of any kind already
- assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
- directive, $compileNode);
- newIsolateScopeDirective = directive;
- } else {
- // This directive is trying to add a child scope.
- // Check that there is no isolated scope already
- assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
- $compileNode);
- }
- }
-
- newScopeDirective = newScopeDirective || directive;
- }
-
- directiveName = directive.name;
-
- // If we encounter a condition that can result in transclusion on the directive,
- // then scan ahead in the remaining directives for others that may cause a multiple
- // transclusion error to be thrown during the compilation process. If a matching directive
- // is found, then we know that when we encounter a transcluded directive, we need to eagerly
- // compile the `transclude` function rather than doing it lazily in order to throw
- // exceptions at the correct time
- if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))
- || (directive.transclude && !directive.$$tlb))) {
- var candidateDirective;
-
- for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {
- if ((candidateDirective.transclude && !candidateDirective.$$tlb)
- || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {
- mightHaveMultipleTransclusionError = true;
- break;
- }
- }
-
- didScanForMultipleTransclusion = true;
- }
-
- if (!directive.templateUrl && directive.controller) {
- directiveValue = directive.controller;
- controllerDirectives = controllerDirectives || createMap();
- assertNoDuplicate("'" + directiveName + "' controller",
- controllerDirectives[directiveName], directive, $compileNode);
- controllerDirectives[directiveName] = directive;
- }
-
- if (directiveValue = directive.transclude) {
- hasTranscludeDirective = true;
-
- // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
- // This option should only be used by directives that know how to safely handle element transclusion,
- // where the transcluded nodes are added or replaced after linking.
- if (!directive.$$tlb) {
- assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
- nonTlbTranscludeDirective = directive;
- }
-
- if (directiveValue == 'element') {
- hasElementTranscludeDirective = true;
- terminalPriority = directive.priority;
- $template = $compileNode;
- $compileNode = templateAttrs.$$element =
- jqLite(document.createComment(' ' + directiveName + ': ' +
- templateAttrs[directiveName] + ' '));
- compileNode = $compileNode[0];
- replaceWith(jqCollection, sliceArgs($template), compileNode);
-
- childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,
- replaceDirective && replaceDirective.name, {
- // Don't pass in:
- // - controllerDirectives - otherwise we'll create duplicates controllers
- // - newIsolateScopeDirective or templateDirective - combining templates with
- // element transclusion doesn't make sense.
- //
- // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
- // on the same element more than once.
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- } else {
-
- var slots = createMap();
-
- $template = jqLite(jqLiteClone(compileNode)).contents();
-
- if (isObject(directiveValue)) {
-
- // We have transclusion slots,
- // collect them up, compile them and store their transclusion functions
- $template = [];
-
- var slotMap = createMap();
- var filledSlots = createMap();
-
- // Parse the element selectors
- forEach(directiveValue, function(elementSelector, slotName) {
- // If an element selector starts with a ? then it is optional
- var optional = (elementSelector.charAt(0) === '?');
- elementSelector = optional ? elementSelector.substring(1) : elementSelector;
-
- slotMap[elementSelector] = slotName;
-
- // We explicitly assign `null` since this implies that a slot was defined but not filled.
- // Later when calling boundTransclusion functions with a slot name we only error if the
- // slot is `undefined`
- slots[slotName] = null;
-
- // filledSlots contains `true` for all slots that are either optional or have been
- // filled. This is used to check that we have not missed any required slots
- filledSlots[slotName] = optional;
- });
-
- // Add the matching elements into their slot
- forEach($compileNode.contents(), function(node) {
- var slotName = slotMap[directiveNormalize(nodeName_(node))];
- if (slotName) {
- filledSlots[slotName] = true;
- slots[slotName] = slots[slotName] || [];
- slots[slotName].push(node);
- } else {
- $template.push(node);
- }
- });
-
- // Check for required slots that were not filled
- forEach(filledSlots, function(filled, slotName) {
- if (!filled) {
- throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);
- }
- });
-
- for (var slotName in slots) {
- if (slots[slotName]) {
- // Only define a transclusion function if the slot was filled
- slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);
- }
- }
- }
-
- $compileNode.empty(); // clear contents
- childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,
- undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
- childTranscludeFn.$$slots = slots;
- }
- }
-
- if (directive.template) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
-
- directiveValue = (isFunction(directive.template))
- ? directive.template($compileNode, templateAttrs)
- : directive.template;
-
- directiveValue = denormalizeTemplate(directiveValue);
-
- if (directive.replace) {
- replaceDirective = directive;
- if (jqLiteIsTextNode(directiveValue)) {
- $template = [];
- } else {
- $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
- }
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- directiveName, '');
- }
-
- replaceWith(jqCollection, $compileNode, compileNode);
-
- var newTemplateAttrs = {$attr: {}};
-
- // combine directives from the original node and from the template:
- // - take the array of directives for this element
- // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
- // - collect directives from the template and sort them by priority
- // - combine directives as: processed + template + unprocessed
- var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
- var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
-
- if (newIsolateScopeDirective || newScopeDirective) {
- // The original directive caused the current element to be replaced but this element
- // also needs to have a new scope, so we need to tell the template directives
- // that they would need to get their scope from further up, if they require transclusion
- markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
- }
- directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
- mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
-
- ii = directives.length;
- } else {
- $compileNode.html(directiveValue);
- }
- }
-
- if (directive.templateUrl) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
-
- if (directive.replace) {
- replaceDirective = directive;
- }
-
- nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
- templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
- controllerDirectives: controllerDirectives,
- newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
- newIsolateScopeDirective: newIsolateScopeDirective,
- templateDirective: templateDirective,
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- ii = directives.length;
- } else if (directive.compile) {
- try {
- linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
- if (isFunction(linkFn)) {
- addLinkFns(null, linkFn, attrStart, attrEnd);
- } else if (linkFn) {
- addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
- }
- } catch (e) {
- $exceptionHandler(e, startingTag($compileNode));
- }
- }
-
- if (directive.terminal) {
- nodeLinkFn.terminal = true;
- terminalPriority = Math.max(terminalPriority, directive.priority);
- }
-
- }
-
- nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
- nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
- nodeLinkFn.templateOnThisElement = hasTemplate;
- nodeLinkFn.transclude = childTranscludeFn;
-
- previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
-
- // might be normal or delayed nodeLinkFn depending on if templateUrl is present
- return nodeLinkFn;
-
- ////////////////////
-
- function addLinkFns(pre, post, attrStart, attrEnd) {
- if (pre) {
- if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
- pre.require = directive.require;
- pre.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- pre = cloneAndAnnotateFn(pre, {isolateScope: true});
- }
- preLinkFns.push(pre);
- }
- if (post) {
- if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
- post.require = directive.require;
- post.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- post = cloneAndAnnotateFn(post, {isolateScope: true});
- }
- postLinkFns.push(post);
- }
- }
-
-
- function getControllers(directiveName, require, $element, elementControllers) {
- var value;
-
- if (isString(require)) {
- var match = require.match(REQUIRE_PREFIX_REGEXP);
- var name = require.substring(match[0].length);
- var inheritType = match[1] || match[3];
- var optional = match[2] === '?';
-
- //If only parents then start at the parent element
- if (inheritType === '^^') {
- $element = $element.parent();
- //Otherwise attempt getting the controller from elementControllers in case
- //the element is transcluded (and has no data) and to avoid .data if possible
- } else {
- value = elementControllers && elementControllers[name];
- value = value && value.instance;
- }
-
- if (!value) {
- var dataName = '$' + name + 'Controller';
- value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
- }
-
- if (!value && !optional) {
- throw $compileMinErr('ctreq',
- "Controller '{0}', required by directive '{1}', can't be found!",
- name, directiveName);
- }
- } else if (isArray(require)) {
- value = [];
- for (var i = 0, ii = require.length; i < ii; i++) {
- value[i] = getControllers(directiveName, require[i], $element, elementControllers);
- }
- } else if (isObject(require)) {
- value = {};
- forEach(require, function(controller, property) {
- value[property] = getControllers(directiveName, controller, $element, elementControllers);
- });
- }
-
- return value || null;
- }
-
- function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) {
- var elementControllers = createMap();
- for (var controllerKey in controllerDirectives) {
- var directive = controllerDirectives[controllerKey];
- var locals = {
- $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
- $element: $element,
- $attrs: attrs,
- $transclude: transcludeFn
- };
-
- var controller = directive.controller;
- if (controller == '@') {
- controller = attrs[directive.name];
- }
-
- var controllerInstance = $controller(controller, locals, true, directive.controllerAs);
-
- // For directives with element transclusion the element is a comment,
- // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
- // clean up (http://bugs.jquery.com/ticket/8335).
- // Instead, we save the controllers for the element in a local hash and attach to .data
- // later, once we have the actual element.
- elementControllers[directive.name] = controllerInstance;
- if (!hasElementTranscludeDirective) {
- $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
- }
- }
- return elementControllers;
- }
-
- function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
- var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,
- attrs, removeScopeBindingWatches, removeControllerBindingWatches;
-
- if (compileNode === linkNode) {
- attrs = templateAttrs;
- $element = templateAttrs.$$element;
- } else {
- $element = jqLite(linkNode);
- attrs = new Attributes($element, templateAttrs);
- }
-
- controllerScope = scope;
- if (newIsolateScopeDirective) {
- isolateScope = scope.$new(true);
- } else if (newScopeDirective) {
- controllerScope = scope.$parent;
- }
-
- if (boundTranscludeFn) {
- // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
- // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
- transcludeFn = controllersBoundTransclude;
- transcludeFn.$$boundTransclude = boundTranscludeFn;
- // expose the slots on the `$transclude` function
- transcludeFn.isSlotFilled = function(slotName) {
- return !!boundTranscludeFn.$$slots[slotName];
- };
- }
-
- if (controllerDirectives) {
- elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope);
- }
-
- if (newIsolateScopeDirective) {
- // Initialize isolate scope bindings for new isolate scope directive.
- compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
- templateDirective === newIsolateScopeDirective.$$originalDirective)));
- compile.$$addScopeClass($element, true);
- isolateScope.$$isolateBindings =
- newIsolateScopeDirective.$$isolateBindings;
- removeScopeBindingWatches = initializeDirectiveBindings(scope, attrs, isolateScope,
- isolateScope.$$isolateBindings,
- newIsolateScopeDirective);
- if (removeScopeBindingWatches) {
- isolateScope.$on('$destroy', removeScopeBindingWatches);
- }
- }
-
- // Initialize bindToController bindings
- for (var name in elementControllers) {
- var controllerDirective = controllerDirectives[name];
- var controller = elementControllers[name];
- var bindings = controllerDirective.$$bindings.bindToController;
-
- if (controller.identifier && bindings) {
- removeControllerBindingWatches =
- initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- }
-
- var controllerResult = controller();
- if (controllerResult !== controller.instance) {
- // If the controller constructor has a return value, overwrite the instance
- // from setupControllers
- controller.instance = controllerResult;
- $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
- removeControllerBindingWatches && removeControllerBindingWatches();
- removeControllerBindingWatches =
- initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- }
- }
-
- // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
- forEach(controllerDirectives, function(controllerDirective, name) {
- var require = controllerDirective.require;
- if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {
- extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));
- }
- });
-
- // Trigger the `$onInit` method on all controllers that have one
- forEach(elementControllers, function(controller) {
- if (isFunction(controller.instance.$onInit)) {
- controller.instance.$onInit();
- }
- });
-
- // PRELINKING
- for (i = 0, ii = preLinkFns.length; i < ii; i++) {
- linkFn = preLinkFns[i];
- invokeLinkFn(linkFn,
- linkFn.isolateScope ? isolateScope : scope,
- $element,
- attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
- transcludeFn
- );
- }
-
- // RECURSION
- // We only pass the isolate scope, if the isolate directive has a template,
- // otherwise the child elements do not belong to the isolate directive.
- var scopeToChild = scope;
- if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
- scopeToChild = isolateScope;
- }
- childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
-
- // POSTLINKING
- for (i = postLinkFns.length - 1; i >= 0; i--) {
- linkFn = postLinkFns[i];
- invokeLinkFn(linkFn,
- linkFn.isolateScope ? isolateScope : scope,
- $element,
- attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
- transcludeFn
- );
- }
-
- // This is the function that is injected as `$transclude`.
- // Note: all arguments are optional!
- function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
- var transcludeControllers;
- // No scope passed in:
- if (!isScope(scope)) {
- slotName = futureParentElement;
- futureParentElement = cloneAttachFn;
- cloneAttachFn = scope;
- scope = undefined;
- }
-
- if (hasElementTranscludeDirective) {
- transcludeControllers = elementControllers;
- }
- if (!futureParentElement) {
- futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
- }
- if (slotName) {
- // slotTranscludeFn can be one of three things:
- // * a transclude function - a filled slot
- // * `null` - an optional slot that was not filled
- // * `undefined` - a slot that was not declared (i.e. invalid)
- var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
- if (slotTranscludeFn) {
- return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
- } else if (isUndefined(slotTranscludeFn)) {
- throw $compileMinErr('noslot',
- 'No parent directive that requires a transclusion with slot name "{0}". ' +
- 'Element: {1}',
- slotName, startingTag($element));
- }
- } else {
- return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
- }
- }
- }
- }
-
- // Depending upon the context in which a directive finds itself it might need to have a new isolated
- // or child scope created. For instance:
- // * if the directive has been pulled into a template because another directive with a higher priority
- // asked for element transclusion
- // * if the directive itself asks for transclusion but it is at the root of a template and the original
- // element was replaced. See https://github.com/angular/angular.js/issues/12936
- function markDirectiveScope(directives, isolateScope, newScope) {
- for (var j = 0, jj = directives.length; j < jj; j++) {
- directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
- }
- }
-
- /**
- * looks up the directive and decorates it with exception handling and proper parameters. We
- * call this the boundDirective.
- *
- * @param {string} name name of the directive to look up.
- * @param {string} location The directive must be found in specific format.
- * String containing any of theses characters:
- *
- * * `E`: element name
- * * `A': attribute
- * * `C`: class
- * * `M`: comment
- * @returns {boolean} true if directive was added.
- */
- function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
- endAttrName) {
- if (name === ignoreDirective) return null;
- var match = null;
- if (hasDirectives.hasOwnProperty(name)) {
- for (var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i < ii; i++) {
- try {
- directive = directives[i];
- if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
- directive.restrict.indexOf(location) != -1) {
- if (startAttrName) {
- directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
- }
- tDirectives.push(directive);
- match = directive;
- }
- } catch (e) { $exceptionHandler(e); }
- }
- }
- return match;
- }
-
-
- /**
- * looks up the directive and returns true if it is a multi-element directive,
- * and therefore requires DOM nodes between -start and -end markers to be grouped
- * together.
- *
- * @param {string} name name of the directive to look up.
- * @returns true if directive was registered as multi-element.
- */
- function directiveIsMultiElement(name) {
- if (hasDirectives.hasOwnProperty(name)) {
- for (var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i < ii; i++) {
- directive = directives[i];
- if (directive.multiElement) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * When the element is replaced with HTML template then the new attributes
- * on the template need to be merged with the existing attributes in the DOM.
- * The desired effect is to have both of the attributes present.
- *
- * @param {object} dst destination attributes (original DOM)
- * @param {object} src source attributes (from the directive template)
- */
- function mergeTemplateAttributes(dst, src) {
- var srcAttr = src.$attr,
- dstAttr = dst.$attr,
- $element = dst.$$element;
-
- // reapply the old attributes to the new element
- forEach(dst, function(value, key) {
- if (key.charAt(0) != '$') {
- if (src[key] && src[key] !== value) {
- value += (key === 'style' ? ';' : ' ') + src[key];
- }
- dst.$set(key, value, true, srcAttr[key]);
- }
- });
-
- // copy the new attributes on the old attrs object
- forEach(src, function(value, key) {
- if (key == 'class') {
- safeAddClass($element, value);
- dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
- } else if (key == 'style') {
- $element.attr('style', $element.attr('style') + ';' + value);
- dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
- // `dst` will never contain hasOwnProperty as DOM parser won't let it.
- // You will get an "InvalidCharacterError: DOM Exception 5" error if you
- // have an attribute like "has-own-property" or "data-has-own-property", etc.
- } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
- dst[key] = value;
- dstAttr[key] = srcAttr[key];
- }
- });
- }
-
-
- function compileTemplateUrl(directives, $compileNode, tAttrs,
- $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
- var linkQueue = [],
- afterTemplateNodeLinkFn,
- afterTemplateChildLinkFn,
- beforeTemplateCompileNode = $compileNode[0],
- origAsyncDirective = directives.shift(),
- derivedSyncDirective = inherit(origAsyncDirective, {
- templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
- }),
- templateUrl = (isFunction(origAsyncDirective.templateUrl))
- ? origAsyncDirective.templateUrl($compileNode, tAttrs)
- : origAsyncDirective.templateUrl,
- templateNamespace = origAsyncDirective.templateNamespace;
-
- $compileNode.empty();
-
- $templateRequest(templateUrl)
- .then(function(content) {
- var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
-
- content = denormalizeTemplate(content);
-
- if (origAsyncDirective.replace) {
- if (jqLiteIsTextNode(content)) {
- $template = [];
- } else {
- $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
- }
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- origAsyncDirective.name, templateUrl);
- }
-
- tempTemplateAttrs = {$attr: {}};
- replaceWith($rootElement, $compileNode, compileNode);
- var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
-
- if (isObject(origAsyncDirective.scope)) {
- // the original directive that caused the template to be loaded async required
- // an isolate scope
- markDirectiveScope(templateDirectives, true);
- }
- directives = templateDirectives.concat(directives);
- mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
- } else {
- compileNode = beforeTemplateCompileNode;
- $compileNode.html(content);
- }
-
- directives.unshift(derivedSyncDirective);
-
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
- childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
- previousCompileContext);
- forEach($rootElement, function(node, i) {
- if (node == compileNode) {
- $rootElement[i] = $compileNode[0];
- }
- });
- afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
-
- while (linkQueue.length) {
- var scope = linkQueue.shift(),
- beforeTemplateLinkNode = linkQueue.shift(),
- linkRootElement = linkQueue.shift(),
- boundTranscludeFn = linkQueue.shift(),
- linkNode = $compileNode[0];
-
- if (scope.$$destroyed) continue;
-
- if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
- var oldClasses = beforeTemplateLinkNode.className;
-
- if (!(previousCompileContext.hasElementTranscludeDirective &&
- origAsyncDirective.replace)) {
- // it was cloned therefore we have to clone as well.
- linkNode = jqLiteClone(compileNode);
- }
- replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
-
- // Copy in CSS classes from original node
- safeAddClass(jqLite(linkNode), oldClasses);
- }
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- } else {
- childBoundTranscludeFn = boundTranscludeFn;
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
- childBoundTranscludeFn);
- }
- linkQueue = null;
- });
-
- return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
- var childBoundTranscludeFn = boundTranscludeFn;
- if (scope.$$destroyed) return;
- if (linkQueue) {
- linkQueue.push(scope,
- node,
- rootElement,
- childBoundTranscludeFn);
- } else {
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
- }
- };
- }
-
-
- /**
- * Sorting function for bound directives.
- */
- function byPriority(a, b) {
- var diff = b.priority - a.priority;
- if (diff !== 0) return diff;
- if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
- return a.index - b.index;
- }
-
- function assertNoDuplicate(what, previousDirective, directive, element) {
-
- function wrapModuleNameIfDefined(moduleName) {
- return moduleName ?
- (' (module: ' + moduleName + ')') :
- '';
- }
-
- if (previousDirective) {
- throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
- previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
- directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
- }
- }
-
-
- function addTextInterpolateDirective(directives, text) {
- var interpolateFn = $interpolate(text, true);
- if (interpolateFn) {
- directives.push({
- priority: 0,
- compile: function textInterpolateCompileFn(templateNode) {
- var templateNodeParent = templateNode.parent(),
- hasCompileParent = !!templateNodeParent.length;
-
- // When transcluding a template that has bindings in the root
- // we don't have a parent and thus need to add the class during linking fn.
- if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
-
- return function textInterpolateLinkFn(scope, node) {
- var parent = node.parent();
- if (!hasCompileParent) compile.$$addBindingClass(parent);
- compile.$$addBindingInfo(parent, interpolateFn.expressions);
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
- node[0].nodeValue = value;
- });
- };
- }
- });
- }
- }
-
-
- function wrapTemplate(type, template) {
- type = lowercase(type || 'html');
- switch (type) {
- case 'svg':
- case 'math':
- var wrapper = document.createElement('div');
- wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
- return wrapper.childNodes[0].childNodes;
- default:
- return template;
- }
- }
-
-
- function getTrustedContext(node, attrNormalizedName) {
- if (attrNormalizedName == "srcdoc") {
- return $sce.HTML;
- }
- var tag = nodeName_(node);
- // maction[xlink:href] can source SVG. It's not limited to <maction>.
- if (attrNormalizedName == "xlinkHref" ||
- (tag == "form" && attrNormalizedName == "action") ||
- (tag != "img" && (attrNormalizedName == "src" ||
- attrNormalizedName == "ngSrc"))) {
- return $sce.RESOURCE_URL;
- }
- }
-
-
- function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
- var trustedContext = getTrustedContext(node, name);
- allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
-
- var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
-
- // no interpolation found -> ignore
- if (!interpolateFn) return;
-
-
- if (name === "multiple" && nodeName_(node) === "select") {
- throw $compileMinErr("selmulti",
- "Binding to the 'multiple' attribute is not supported. Element: {0}",
- startingTag(node));
- }
-
- directives.push({
- priority: 100,
- compile: function() {
- return {
- pre: function attrInterpolatePreLinkFn(scope, element, attr) {
- var $$observers = (attr.$$observers || (attr.$$observers = createMap()));
-
- if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
- throw $compileMinErr('nodomevents',
- "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
- "ng- versions (such as ng-click instead of onclick) instead.");
- }
-
- // If the attribute has changed since last $interpolate()ed
- var newValue = attr[name];
- if (newValue !== value) {
- // we need to interpolate again since the attribute value has been updated
- // (e.g. by another directive's compile function)
- // ensure unset/empty values make interpolateFn falsy
- interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
- value = newValue;
- }
-
- // if attribute was updated so that there is no interpolation going on we don't want to
- // register any observers
- if (!interpolateFn) return;
-
- // initialize attr object so that it's ready in case we need the value for isolate
- // scope initialization, otherwise the value would not be available from isolate
- // directive's linking fn during linking phase
- attr[name] = interpolateFn(scope);
-
- ($$observers[name] || ($$observers[name] = [])).$$inter = true;
- (attr.$$observers && attr.$$observers[name].$$scope || scope).
- $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
- //special case for class attribute addition + removal
- //so that class changes can tap into the animation
- //hooks provided by the $animate service. Be sure to
- //skip animations when the first digest occurs (when
- //both the new and the old values are the same) since
- //the CSS classes are the non-interpolated values
- if (name === 'class' && newValue != oldValue) {
- attr.$updateClass(newValue, oldValue);
- } else {
- attr.$set(name, newValue);
- }
- });
- }
- };
- }
- });
- }
-
-
- /**
- * This is a special jqLite.replaceWith, which can replace items which
- * have no parents, provided that the containing jqLite collection is provided.
- *
- * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
- * in the root of the tree.
- * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
- * the shell, but replace its DOM node reference.
- * @param {Node} newNode The new DOM node.
- */
- function replaceWith($rootElement, elementsToRemove, newNode) {
- var firstElementToRemove = elementsToRemove[0],
- removeCount = elementsToRemove.length,
- parent = firstElementToRemove.parentNode,
- i, ii;
-
- if ($rootElement) {
- for (i = 0, ii = $rootElement.length; i < ii; i++) {
- if ($rootElement[i] == firstElementToRemove) {
- $rootElement[i++] = newNode;
- for (var j = i, j2 = j + removeCount - 1,
- jj = $rootElement.length;
- j < jj; j++, j2++) {
- if (j2 < jj) {
- $rootElement[j] = $rootElement[j2];
- } else {
- delete $rootElement[j];
- }
- }
- $rootElement.length -= removeCount - 1;
-
- // If the replaced element is also the jQuery .context then replace it
- // .context is a deprecated jQuery api, so we should set it only when jQuery set it
- // http://api.jquery.com/context/
- if ($rootElement.context === firstElementToRemove) {
- $rootElement.context = newNode;
- }
- break;
- }
- }
- }
-
- if (parent) {
- parent.replaceChild(newNode, firstElementToRemove);
- }
-
- // Append all the `elementsToRemove` to a fragment. This will...
- // - remove them from the DOM
- // - allow them to still be traversed with .nextSibling
- // - allow a single fragment.qSA to fetch all elements being removed
- var fragment = document.createDocumentFragment();
- for (i = 0; i < removeCount; i++) {
- fragment.appendChild(elementsToRemove[i]);
- }
-
- if (jqLite.hasData(firstElementToRemove)) {
- // Copy over user data (that includes Angular's $scope etc.). Don't copy private
- // data here because there's no public interface in jQuery to do that and copying over
- // event listeners (which is the main use of private data) wouldn't work anyway.
- jqLite.data(newNode, jqLite.data(firstElementToRemove));
-
- // Remove $destroy event listeners from `firstElementToRemove`
- jqLite(firstElementToRemove).off('$destroy');
- }
-
- // Cleanup any data/listeners on the elements and children.
- // This includes invoking the $destroy event on any elements with listeners.
- jqLite.cleanData(fragment.querySelectorAll('*'));
-
- // Update the jqLite collection to only contain the `newNode`
- for (i = 1; i < removeCount; i++) {
- delete elementsToRemove[i];
- }
- elementsToRemove[0] = newNode;
- elementsToRemove.length = 1;
- }
-
-
- function cloneAndAnnotateFn(fn, annotation) {
- return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
- }
-
-
- function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
- try {
- linkFn(scope, $element, attrs, controllers, transcludeFn);
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
-
- // Set up $watches for isolate scope and controller bindings. This process
- // only occurs for isolate scopes and new scopes with controllerAs.
- function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {
- var removeWatchCollection = [];
- forEach(bindings, function(definition, scopeName) {
- var attrName = definition.attrName,
- optional = definition.optional,
- mode = definition.mode, // @, =, or &
- lastValue,
- parentGet, parentSet, compare, removeWatch;
-
- switch (mode) {
-
- case '@':
- if (!optional && !hasOwnProperty.call(attrs, attrName)) {
- destination[scopeName] = attrs[attrName] = void 0;
- }
- attrs.$observe(attrName, function(value) {
- if (isString(value)) {
- destination[scopeName] = value;
- }
- });
- attrs.$$observers[attrName].$$scope = scope;
- lastValue = attrs[attrName];
- if (isString(lastValue)) {
- // If the attribute has been provided then we trigger an interpolation to ensure
- // the value is there for use in the link fn
- destination[scopeName] = $interpolate(lastValue)(scope);
- } else if (isBoolean(lastValue)) {
- // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted
- // the value to boolean rather than a string, so we special case this situation
- destination[scopeName] = lastValue;
- }
- break;
-
- case '=':
- if (!hasOwnProperty.call(attrs, attrName)) {
- if (optional) break;
- attrs[attrName] = void 0;
- }
- if (optional && !attrs[attrName]) break;
-
- parentGet = $parse(attrs[attrName]);
- if (parentGet.literal) {
- compare = equals;
- } else {
- compare = function(a, b) { return a === b || (a !== a && b !== b); };
- }
- parentSet = parentGet.assign || function() {
- // reset the change, or we will throw this exception on every $digest
- lastValue = destination[scopeName] = parentGet(scope);
- throw $compileMinErr('nonassign',
- "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
- attrs[attrName], attrName, directive.name);
- };
- lastValue = destination[scopeName] = parentGet(scope);
- var parentValueWatch = function parentValueWatch(parentValue) {
- if (!compare(parentValue, destination[scopeName])) {
- // we are out of sync and need to copy
- if (!compare(parentValue, lastValue)) {
- // parent changed and it has precedence
- destination[scopeName] = parentValue;
- } else {
- // if the parent can be assigned then do so
- parentSet(scope, parentValue = destination[scopeName]);
- }
- }
- return lastValue = parentValue;
- };
- parentValueWatch.$stateful = true;
- if (definition.collection) {
- removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
- } else {
- removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
- }
- removeWatchCollection.push(removeWatch);
- break;
-
- case '<':
- if (!hasOwnProperty.call(attrs, attrName)) {
- if (optional) break;
- attrs[attrName] = void 0;
- }
- if (optional && !attrs[attrName]) break;
-
- parentGet = $parse(attrs[attrName]);
-
- destination[scopeName] = parentGet(scope);
-
- removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newParentValue) {
- destination[scopeName] = newParentValue;
- }, parentGet.literal);
-
- removeWatchCollection.push(removeWatch);
- break;
-
- case '&':
- // Don't assign Object.prototype method to scope
- parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
-
- // Don't assign noop to destination if expression is not valid
- if (parentGet === noop && optional) break;
-
- destination[scopeName] = function(locals) {
- return parentGet(scope, locals);
- };
- break;
- }
- });
-
- return removeWatchCollection.length && function removeWatches() {
- for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {
- removeWatchCollection[i]();
- }
- };
- }
- }];
-}
-
-var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
-/**
- * Converts all accepted directives format into proper directive name.
- * @param name Name to normalize
- */
-function directiveNormalize(name) {
- return camelCase(name.replace(PREFIX_REGEXP, ''));
-}
-
-/**
- * @ngdoc type
- * @name $compile.directive.Attributes
- *
- * @description
- * A shared object between directive compile / linking functions which contains normalized DOM
- * element attributes. The values reflect current binding state `{{ }}`. The normalization is
- * needed since all of these are treated as equivalent in Angular:
- *
- * ```
- * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
- * ```
- */
-
-/**
- * @ngdoc property
- * @name $compile.directive.Attributes#$attr
- *
- * @description
- * A map of DOM element attribute names to the normalized name. This is
- * needed to do reverse lookup from normalized name back to actual name.
- */
-
-
-/**
- * @ngdoc method
- * @name $compile.directive.Attributes#$set
- * @kind function
- *
- * @description
- * Set DOM element attribute value.
- *
- *
- * @param {string} name Normalized element attribute name of the property to modify. The name is
- * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
- * property to the original name.
- * @param {string} value Value to set the attribute to. The value can be an interpolated string.
- */
-
-
-
-/**
- * Closure compiler type information
- */
-
-function nodesetLinkingFn(
- /* angular.Scope */ scope,
- /* NodeList */ nodeList,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-) {}
-
-function directiveLinkingFn(
- /* nodesetLinkingFn */ nodesetLinkingFn,
- /* angular.Scope */ scope,
- /* Node */ node,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-) {}
-
-function tokenDifference(str1, str2) {
- var values = '',
- tokens1 = str1.split(/\s+/),
- tokens2 = str2.split(/\s+/);
-
- outer:
- for (var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for (var j = 0; j < tokens2.length; j++) {
- if (token == tokens2[j]) continue outer;
- }
- values += (values.length > 0 ? ' ' : '') + token;
- }
- return values;
-}
-
-function removeComments(jqNodes) {
- jqNodes = jqLite(jqNodes);
- var i = jqNodes.length;
-
- if (i <= 1) {
- return jqNodes;
- }
-
- while (i--) {
- var node = jqNodes[i];
- if (node.nodeType === NODE_TYPE_COMMENT) {
- splice.call(jqNodes, i, 1);
- }
- }
- return jqNodes;
-}
-
-var $controllerMinErr = minErr('$controller');
-
-
-var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/;
-function identifierForController(controller, ident) {
- if (ident && isString(ident)) return ident;
- if (isString(controller)) {
- var match = CNTRL_REG.exec(controller);
- if (match) return match[3];
- }
-}
-
-
-/**
- * @ngdoc provider
- * @name $controllerProvider
- * @description
- * The {@link ng.$controller $controller service} is used by Angular to create new
- * controllers.
- *
- * This provider allows controller registration via the
- * {@link ng.$controllerProvider#register register} method.
- */
-function $ControllerProvider() {
- var controllers = {},
- globals = false;
-
- /**
- * @ngdoc method
- * @name $controllerProvider#register
- * @param {string|Object} name Controller name, or an object map of controllers where the keys are
- * the names and the values are the constructors.
- * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
- * annotations in the array notation).
- */
- this.register = function(name, constructor) {
- assertNotHasOwnProperty(name, 'controller');
- if (isObject(name)) {
- extend(controllers, name);
- } else {
- controllers[name] = constructor;
- }
- };
-
- /**
- * @ngdoc method
- * @name $controllerProvider#allowGlobals
- * @description If called, allows `$controller` to find controller constructors on `window`
- */
- this.allowGlobals = function() {
- globals = true;
- };
-
-
- this.$get = ['$injector', '$window', function($injector, $window) {
-
- /**
- * @ngdoc service
- * @name $controller
- * @requires $injector
- *
- * @param {Function|string} constructor If called with a function then it's considered to be the
- * controller constructor function. Otherwise it's considered to be a string which is used
- * to retrieve the controller constructor using the following steps:
- *
- * * check if a controller with given name is registered via `$controllerProvider`
- * * check if evaluating the string on the current scope returns a constructor
- * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
- * `window` object (not recommended)
- *
- * The string can use the `controller as property` syntax, where the controller instance is published
- * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
- * to work correctly.
- *
- * @param {Object} locals Injection locals for Controller.
- * @return {Object} Instance of given controller.
- *
- * @description
- * `$controller` service is responsible for instantiating controllers.
- *
- * It's just a simple call to {@link auto.$injector $injector}, but extracted into
- * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
- */
- return function(expression, locals, later, ident) {
- // PRIVATE API:
- // param `later` --- indicates that the controller's constructor is invoked at a later time.
- // If true, $controller will allocate the object with the correct
- // prototype chain, but will not invoke the controller until a returned
- // callback is invoked.
- // param `ident` --- An optional label which overrides the label parsed from the controller
- // expression, if any.
- var instance, match, constructor, identifier;
- later = later === true;
- if (ident && isString(ident)) {
- identifier = ident;
- }
-
- if (isString(expression)) {
- match = expression.match(CNTRL_REG);
- if (!match) {
- throw $controllerMinErr('ctrlfmt',
- "Badly formed controller string '{0}'. " +
- "Must match `__name__ as __id__` or `__name__`.", expression);
- }
- constructor = match[1],
- identifier = identifier || match[3];
- expression = controllers.hasOwnProperty(constructor)
- ? controllers[constructor]
- : getter(locals.$scope, constructor, true) ||
- (globals ? getter($window, constructor, true) : undefined);
-
- assertArgFn(expression, constructor, true);
- }
-
- if (later) {
- // Instantiate controller later:
- // This machinery is used to create an instance of the object before calling the
- // controller's constructor itself.
- //
- // This allows properties to be added to the controller before the constructor is
- // invoked. Primarily, this is used for isolate scope bindings in $compile.
- //
- // This feature is not intended for use by applications, and is thus not documented
- // publicly.
- // Object creation: http://jsperf.com/create-constructor/2
- var controllerPrototype = (isArray(expression) ?
- expression[expression.length - 1] : expression).prototype;
- instance = Object.create(controllerPrototype || null);
-
- if (identifier) {
- addIdentifier(locals, identifier, instance, constructor || expression.name);
- }
-
- var instantiate;
- return instantiate = extend(function() {
- var result = $injector.invoke(expression, instance, locals, constructor);
- if (result !== instance && (isObject(result) || isFunction(result))) {
- instance = result;
- if (identifier) {
- // If result changed, re-assign controllerAs value to scope.
- addIdentifier(locals, identifier, instance, constructor || expression.name);
- }
- }
- return instance;
- }, {
- instance: instance,
- identifier: identifier
- });
- }
-
- instance = $injector.instantiate(expression, locals, constructor);
-
- if (identifier) {
- addIdentifier(locals, identifier, instance, constructor || expression.name);
- }
-
- return instance;
- };
-
- function addIdentifier(locals, identifier, instance, name) {
- if (!(locals && isObject(locals.$scope))) {
- throw minErr('$controller')('noscp',
- "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
- name, identifier);
- }
-
- locals.$scope[identifier] = instance;
- }
- }];
-}
-
-/**
- * @ngdoc service
- * @name $document
- * @requires $window
- *
- * @description
- * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
- *
- * @example
- <example module="documentExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p>$document title: <b ng-bind="title"></b></p>
- <p>window.document title: <b ng-bind="windowTitle"></b></p>
- </div>
- </file>
- <file name="script.js">
- angular.module('documentExample', [])
- .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
- $scope.title = $document[0].title;
- $scope.windowTitle = angular.element(window.document)[0].title;
- }]);
- </file>
- </example>
- */
-function $DocumentProvider() {
- this.$get = ['$window', function(window) {
- return jqLite(window.document);
- }];
-}
-
-/**
- * @ngdoc service
- * @name $exceptionHandler
- * @requires ng.$log
- *
- * @description
- * Any uncaught exception in angular expressions is delegated to this service.
- * The default implementation simply delegates to `$log.error` which logs it into
- * the browser console.
- *
- * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
- * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
- *
- * ## Example:
- *
- * ```js
- * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
- * return function(exception, cause) {
- * exception.message += ' (caused by "' + cause + '")';
- * throw exception;
- * };
- * });
- * ```
- *
- * This example will override the normal action of `$exceptionHandler`, to make angular
- * exceptions fail hard when they happen, instead of just logging to the console.
- *
- * <hr />
- * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
- * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
- * (unless executed during a digest).
- *
- * If you wish, you can manually delegate exceptions, e.g.
- * `try { ... } catch(e) { $exceptionHandler(e); }`
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- * the error was thrown.
- *
- */
-function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log) {
- return function(exception, cause) {
- $log.error.apply($log, arguments);
- };
- }];
-}
-
-var $$ForceReflowProvider = function() {
- this.$get = ['$document', function($document) {
- return function(domNode) {
- //the line below will force the browser to perform a repaint so
- //that all the animated elements within the animation frame will
- //be properly updated and drawn on screen. This is required to
- //ensure that the preparation animation is properly flushed so that
- //the active state picks up from there. DO NOT REMOVE THIS LINE.
- //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
- //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
- //WILL TAKE YEARS AWAY FROM YOUR LIFE.
- if (domNode) {
- if (!domNode.nodeType && domNode instanceof jqLite) {
- domNode = domNode[0];
- }
- } else {
- domNode = $document[0].body;
- }
- return domNode.offsetWidth + 1;
- };
- }];
-};
-
-var APPLICATION_JSON = 'application/json';
-var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
-var JSON_START = /^\[|^\{(?!\{)/;
-var JSON_ENDS = {
- '[': /]$/,
- '{': /}$/
-};
-var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
-var $httpMinErr = minErr('$http');
-var $httpMinErrLegacyFn = function(method) {
- return function() {
- throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method);
- };
-};
-
-function serializeValue(v) {
- if (isObject(v)) {
- return isDate(v) ? v.toISOString() : toJson(v);
- }
- return v;
-}
-
-
-function $HttpParamSerializerProvider() {
- /**
- * @ngdoc service
- * @name $httpParamSerializer
- * @description
- *
- * Default {@link $http `$http`} params serializer that converts objects to strings
- * according to the following rules:
- *
- * * `{'foo': 'bar'}` results in `foo=bar`
- * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
- * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
- * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
- *
- * Note that serializer will sort the request parameters alphabetically.
- * */
-
- this.$get = function() {
- return function ngParamSerializer(params) {
- if (!params) return '';
- var parts = [];
- forEachSorted(params, function(value, key) {
- if (value === null || isUndefined(value)) return;
- if (isArray(value)) {
- forEach(value, function(v, k) {
- parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v)));
- });
- } else {
- parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
- }
- });
-
- return parts.join('&');
- };
- };
-}
-
-function $HttpParamSerializerJQLikeProvider() {
- /**
- * @ngdoc service
- * @name $httpParamSerializerJQLike
- * @description
- *
- * Alternative {@link $http `$http`} params serializer that follows
- * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
- * The serializer will also sort the params alphabetically.
- *
- * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
- *
- * ```js
- * $http({
- * url: myUrl,
- * method: 'GET',
- * params: myParams,
- * paramSerializer: '$httpParamSerializerJQLike'
- * });
- * ```
- *
- * It is also possible to set it as the default `paramSerializer` in the
- * {@link $httpProvider#defaults `$httpProvider`}.
- *
- * Additionally, you can inject the serializer and use it explicitly, for example to serialize
- * form data for submission:
- *
- * ```js
- * .controller(function($http, $httpParamSerializerJQLike) {
- * //...
- *
- * $http({
- * url: myUrl,
- * method: 'POST',
- * data: $httpParamSerializerJQLike(myData),
- * headers: {
- * 'Content-Type': 'application/x-www-form-urlencoded'
- * }
- * });
- *
- * });
- * ```
- *
- * */
- this.$get = function() {
- return function jQueryLikeParamSerializer(params) {
- if (!params) return '';
- var parts = [];
- serialize(params, '', true);
- return parts.join('&');
-
- function serialize(toSerialize, prefix, topLevel) {
- if (toSerialize === null || isUndefined(toSerialize)) return;
- if (isArray(toSerialize)) {
- forEach(toSerialize, function(value, index) {
- serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
- });
- } else if (isObject(toSerialize) && !isDate(toSerialize)) {
- forEachSorted(toSerialize, function(value, key) {
- serialize(value, prefix +
- (topLevel ? '' : '[') +
- key +
- (topLevel ? '' : ']'));
- });
- } else {
- parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
- }
- }
- };
- };
-}
-
-function defaultHttpResponseTransform(data, headers) {
- if (isString(data)) {
- // Strip json vulnerability protection prefix and trim whitespace
- var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
-
- if (tempData) {
- var contentType = headers('Content-Type');
- if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
- data = fromJson(tempData);
- }
- }
- }
-
- return data;
-}
-
-function isJsonLike(str) {
- var jsonStart = str.match(JSON_START);
- return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
-}
-
-/**
- * Parse headers into key value object
- *
- * @param {string} headers Raw headers as a string
- * @returns {Object} Parsed headers as key value object
- */
-function parseHeaders(headers) {
- var parsed = createMap(), i;
-
- function fillInParsed(key, val) {
- if (key) {
- parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
- }
- }
-
- if (isString(headers)) {
- forEach(headers.split('\n'), function(line) {
- i = line.indexOf(':');
- fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));
- });
- } else if (isObject(headers)) {
- forEach(headers, function(headerVal, headerKey) {
- fillInParsed(lowercase(headerKey), trim(headerVal));
- });
- }
-
- return parsed;
-}
-
-
-/**
- * Returns a function that provides access to parsed headers.
- *
- * Headers are lazy parsed when first requested.
- * @see parseHeaders
- *
- * @param {(string|Object)} headers Headers to provide access to.
- * @returns {function(string=)} Returns a getter function which if called with:
- *
- * - if called with single an argument returns a single header value or null
- * - if called with no arguments returns an object containing all headers.
- */
-function headersGetter(headers) {
- var headersObj;
-
- return function(name) {
- if (!headersObj) headersObj = parseHeaders(headers);
-
- if (name) {
- var value = headersObj[lowercase(name)];
- if (value === void 0) {
- value = null;
- }
- return value;
- }
-
- return headersObj;
- };
-}
-
-
-/**
- * Chain all given functions
- *
- * This function is used for both request and response transforming
- *
- * @param {*} data Data to transform.
- * @param {function(string=)} headers HTTP headers getter fn.
- * @param {number} status HTTP status code of the response.
- * @param {(Function|Array.<Function>)} fns Function or an array of functions.
- * @returns {*} Transformed data.
- */
-function transformData(data, headers, status, fns) {
- if (isFunction(fns)) {
- return fns(data, headers, status);
- }
-
- forEach(fns, function(fn) {
- data = fn(data, headers, status);
- });
-
- return data;
-}
-
-
-function isSuccess(status) {
- return 200 <= status && status < 300;
-}
-
-
-/**
- * @ngdoc provider
- * @name $httpProvider
- * @description
- * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
- * */
-function $HttpProvider() {
- /**
- * @ngdoc property
- * @name $httpProvider#defaults
- * @description
- *
- * Object containing default values for all {@link ng.$http $http} requests.
- *
- * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
- * that will provide the cache for all requests who set their `cache` property to `true`.
- * If you set the `defaults.cache = false` then only requests that specify their own custom
- * cache object will be cached. See {@link $http#caching $http Caching} for more information.
- *
- * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
- * Defaults value is `'XSRF-TOKEN'`.
- *
- * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
- * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
- *
- * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
- * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
- * setting default headers.
- * - **`defaults.headers.common`**
- * - **`defaults.headers.post`**
- * - **`defaults.headers.put`**
- * - **`defaults.headers.patch`**
- *
- *
- * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
- * used to the prepare string representation of request parameters (specified as an object).
- * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
- * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
- *
- **/
- var defaults = this.defaults = {
- // transform incoming response data
- transformResponse: [defaultHttpResponseTransform],
-
- // transform outgoing request data
- transformRequest: [function(d) {
- return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
- }],
-
- // default headers
- headers: {
- common: {
- 'Accept': 'application/json, text/plain, */*'
- },
- post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
- },
-
- xsrfCookieName: 'XSRF-TOKEN',
- xsrfHeaderName: 'X-XSRF-TOKEN',
-
- paramSerializer: '$httpParamSerializer'
- };
-
- var useApplyAsync = false;
- /**
- * @ngdoc method
- * @name $httpProvider#useApplyAsync
- * @description
- *
- * Configure $http service to combine processing of multiple http responses received at around
- * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
- * significant performance improvement for bigger applications that make many HTTP requests
- * concurrently (common during application bootstrap).
- *
- * Defaults to false. If no value is specified, returns the current configured value.
- *
- * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
- * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
- * to load and share the same digest cycle.
- *
- * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
- * otherwise, returns the current configured value.
- **/
- this.useApplyAsync = function(value) {
- if (isDefined(value)) {
- useApplyAsync = !!value;
- return this;
- }
- return useApplyAsync;
- };
-
- var useLegacyPromise = true;
- /**
- * @ngdoc method
- * @name $httpProvider#useLegacyPromiseExtensions
- * @description
- *
- * Configure `$http` service to return promises without the shorthand methods `success` and `error`.
- * This should be used to make sure that applications work without these methods.
- *
- * Defaults to true. If no value is specified, returns the current configured value.
- *
- * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.
- *
- * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
- * otherwise, returns the current configured value.
- **/
- this.useLegacyPromiseExtensions = function(value) {
- if (isDefined(value)) {
- useLegacyPromise = !!value;
- return this;
- }
- return useLegacyPromise;
- };
-
- /**
- * @ngdoc property
- * @name $httpProvider#interceptors
- * @description
- *
- * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
- * pre-processing of request or postprocessing of responses.
- *
- * These service factories are ordered by request, i.e. they are applied in the same order as the
- * array, on request, but reverse order, on response.
- *
- * {@link ng.$http#interceptors Interceptors detailed info}
- **/
- var interceptorFactories = this.interceptors = [];
-
- this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
- function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
-
- var defaultCache = $cacheFactory('$http');
-
- /**
- * Make sure that default param serializer is exposed as a function
- */
- defaults.paramSerializer = isString(defaults.paramSerializer) ?
- $injector.get(defaults.paramSerializer) : defaults.paramSerializer;
-
- /**
- * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
- * The reversal is needed so that we can build up the interception chain around the
- * server request.
- */
- var reversedInterceptors = [];
-
- forEach(interceptorFactories, function(interceptorFactory) {
- reversedInterceptors.unshift(isString(interceptorFactory)
- ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
- });
-
- /**
- * @ngdoc service
- * @kind function
- * @name $http
- * @requires ng.$httpBackend
- * @requires $cacheFactory
- * @requires $rootScope
- * @requires $q
- * @requires $injector
- *
- * @description
- * The `$http` service is a core Angular service that facilitates communication with the remote
- * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
- * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
- *
- * For unit testing applications that use `$http` service, see
- * {@link ngMock.$httpBackend $httpBackend mock}.
- *
- * For a higher level of abstraction, please check out the {@link ngResource.$resource
- * $resource} service.
- *
- * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
- * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
- * it is important to familiarize yourself with these APIs and the guarantees they provide.
- *
- *
- * ## General usage
- * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —
- * that is used to generate an HTTP request and returns a {@link ng.$q promise}.
- *
- * ```js
- * // Simple GET request example:
- * $http({
- * method: 'GET',
- * url: '/someUrl'
- * }).then(function successCallback(response) {
- * // this callback will be called asynchronously
- * // when the response is available
- * }, function errorCallback(response) {
- * // called asynchronously if an error occurs
- * // or server returns response with an error status.
- * });
- * ```
- *
- * The response object has these properties:
- *
- * - **data** – `{string|Object}` – The response body transformed with the transform
- * functions.
- * - **status** – `{number}` – HTTP status code of the response.
- * - **headers** – `{function([headerName])}` – Header getter function.
- * - **config** – `{Object}` – The configuration object that was used to generate the request.
- * - **statusText** – `{string}` – HTTP status text of the response.
- *
- * A response status code between 200 and 299 is considered a success status and
- * will result in the success callback being called. Note that if the response is a redirect,
- * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
- * called for such responses.
- *
- *
- * ## Shortcut methods
- *
- * Shortcut methods are also available. All shortcut methods require passing in the URL, and
- * request data must be passed in for POST/PUT requests. An optional config can be passed as the
- * last argument.
- *
- * ```js
- * $http.get('/someUrl', config).then(successCallback, errorCallback);
- * $http.post('/someUrl', data, config).then(successCallback, errorCallback);
- * ```
- *
- * Complete list of shortcut methods:
- *
- * - {@link ng.$http#get $http.get}
- * - {@link ng.$http#head $http.head}
- * - {@link ng.$http#post $http.post}
- * - {@link ng.$http#put $http.put}
- * - {@link ng.$http#delete $http.delete}
- * - {@link ng.$http#jsonp $http.jsonp}
- * - {@link ng.$http#patch $http.patch}
- *
- *
- * ## Writing Unit Tests that use $http
- * When unit testing (using {@link ngMock ngMock}), it is necessary to call
- * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
- * request using trained responses.
- *
- * ```
- * $httpBackend.expectGET(...);
- * $http.get(...);
- * $httpBackend.flush();
- * ```
- *
- * ## Deprecation Notice
- * <div class="alert alert-danger">
- * The `$http` legacy promise methods `success` and `error` have been deprecated.
- * Use the standard `then` method instead.
- * If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to
- * `false` then these methods will throw {@link $http:legacy `$http/legacy`} error.
- * </div>
- *
- * ## Setting HTTP Headers
- *
- * The $http service will automatically add certain HTTP headers to all requests. These defaults
- * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
- * object, which currently contains this default configuration:
- *
- * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
- * - `Accept: application/json, text/plain, * / *`
- * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
- * - `Content-Type: application/json`
- * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
- * - `Content-Type: application/json`
- *
- * To add or overwrite these defaults, simply add or remove a property from these configuration
- * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
- * with the lowercased HTTP method name as the key, e.g.
- * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.
- *
- * The defaults can also be set at runtime via the `$http.defaults` object in the same
- * fashion. For example:
- *
- * ```
- * module.run(function($http) {
- * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
- * });
- * ```
- *
- * In addition, you can supply a `headers` property in the config object passed when
- * calling `$http(config)`, which overrides the defaults without changing them globally.
- *
- * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
- * Use the `headers` property, setting the desired header to `undefined`. For example:
- *
- * ```js
- * var req = {
- * method: 'POST',
- * url: 'http://example.com',
- * headers: {
- * 'Content-Type': undefined
- * },
- * data: { test: 'test' }
- * }
- *
- * $http(req).then(function(){...}, function(){...});
- * ```
- *
- * ## Transforming Requests and Responses
- *
- * Both requests and responses can be transformed using transformation functions: `transformRequest`
- * and `transformResponse`. These properties can be a single function that returns
- * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
- * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
- *
- * ### Default Transformations
- *
- * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
- * `defaults.transformResponse` properties. If a request does not provide its own transformations
- * then these will be applied.
- *
- * You can augment or replace the default transformations by modifying these properties by adding to or
- * replacing the array.
- *
- * Angular provides the following default transformations:
- *
- * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
- *
- * - If the `data` property of the request configuration object contains an object, serialize it
- * into JSON format.
- *
- * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
- *
- * - If XSRF prefix is detected, strip it (see Security Considerations section below).
- * - If JSON response is detected, deserialize it using a JSON parser.
- *
- *
- * ### Overriding the Default Transformations Per Request
- *
- * If you wish override the request/response transformations only for a single request then provide
- * `transformRequest` and/or `transformResponse` properties on the configuration object passed
- * into `$http`.
- *
- * Note that if you provide these properties on the config object the default transformations will be
- * overwritten. If you wish to augment the default transformations then you must include them in your
- * local transformation array.
- *
- * The following code demonstrates adding a new response transformation to be run after the default response
- * transformations have been run.
- *
- * ```js
- * function appendTransform(defaults, transform) {
- *
- * // We can't guarantee that the default transformation is an array
- * defaults = angular.isArray(defaults) ? defaults : [defaults];
- *
- * // Append the new transformation to the defaults
- * return defaults.concat(transform);
- * }
- *
- * $http({
- * url: '...',
- * method: 'GET',
- * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
- * return doTransform(value);
- * })
- * });
- * ```
- *
- *
- * ## Caching
- *
- * To enable caching, set the request configuration `cache` property to `true` (to use default
- * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
- * When the cache is enabled, `$http` stores the response from the server in the specified
- * cache. The next time the same request is made, the response is served from the cache without
- * sending a request to the server.
- *
- * Note that even if the response is served from cache, delivery of the data is asynchronous in
- * the same way that real requests are.
- *
- * If there are multiple GET requests for the same URL that should be cached using the same
- * cache, but the cache is not populated yet, only one request to the server will be made and
- * the remaining requests will be fulfilled using the response from the first request.
- *
- * You can change the default cache to a new object (built with
- * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
- * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
- * their `cache` property to `true` will now use this cache object.
- *
- * If you set the default cache to `false` then only requests that specify their own custom
- * cache object will be cached.
- *
- * ## Interceptors
- *
- * Before you start creating interceptors, be sure to understand the
- * {@link ng.$q $q and deferred/promise APIs}.
- *
- * For purposes of global error handling, authentication, or any kind of synchronous or
- * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
- * able to intercept requests before they are handed to the server and
- * responses before they are handed over to the application code that
- * initiated these requests. The interceptors leverage the {@link ng.$q
- * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
- *
- * The interceptors are service factories that are registered with the `$httpProvider` by
- * adding them to the `$httpProvider.interceptors` array. The factory is called and
- * injected with dependencies (if specified) and returns the interceptor.
- *
- * There are two kinds of interceptors (and two kinds of rejection interceptors):
- *
- * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to
- * modify the `config` object or create a new one. The function needs to return the `config`
- * object directly, or a promise containing the `config` or a new `config` object.
- * * `requestError`: interceptor gets called when a previous interceptor threw an error or
- * resolved with a rejection.
- * * `response`: interceptors get called with http `response` object. The function is free to
- * modify the `response` object or create a new one. The function needs to return the `response`
- * object directly, or as a promise containing the `response` or a new `response` object.
- * * `responseError`: interceptor gets called when a previous interceptor threw an error or
- * resolved with a rejection.
- *
- *
- * ```js
- * // register the interceptor as a service
- * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
- * return {
- * // optional method
- * 'request': function(config) {
- * // do something on success
- * return config;
- * },
- *
- * // optional method
- * 'requestError': function(rejection) {
- * // do something on error
- * if (canRecover(rejection)) {
- * return responseOrNewPromise
- * }
- * return $q.reject(rejection);
- * },
- *
- *
- *
- * // optional method
- * 'response': function(response) {
- * // do something on success
- * return response;
- * },
- *
- * // optional method
- * 'responseError': function(rejection) {
- * // do something on error
- * if (canRecover(rejection)) {
- * return responseOrNewPromise
- * }
- * return $q.reject(rejection);
- * }
- * };
- * });
- *
- * $httpProvider.interceptors.push('myHttpInterceptor');
- *
- *
- * // alternatively, register the interceptor via an anonymous factory
- * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
- * return {
- * 'request': function(config) {
- * // same as above
- * },
- *
- * 'response': function(response) {
- * // same as above
- * }
- * };
- * });
- * ```
- *
- * ## Security Considerations
- *
- * When designing web applications, consider security threats from:
- *
- * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
- * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
- *
- * Both server and the client must cooperate in order to eliminate these threats. Angular comes
- * pre-configured with strategies that address these issues, but for this to work backend server
- * cooperation is required.
- *
- * ### JSON Vulnerability Protection
- *
- * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
- * allows third party website to turn your JSON resource URL into
- * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
- * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
- * Angular will automatically strip the prefix before processing it as JSON.
- *
- * For example if your server needs to return:
- * ```js
- * ['one','two']
- * ```
- *
- * which is vulnerable to attack, your server can return:
- * ```js
- * )]}',
- * ['one','two']
- * ```
- *
- * Angular will strip the prefix, before processing the JSON.
- *
- *
- * ### Cross Site Request Forgery (XSRF) Protection
- *
- * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by
- * which the attacker can trick an authenticated user into unknowingly executing actions on your
- * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
- * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
- * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
- * cookie, your server can be assured that the XHR came from JavaScript running on your domain.
- * The header will not be set for cross-domain requests.
- *
- * To take advantage of this, your server needs to set a token in a JavaScript readable session
- * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
- * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
- * that only JavaScript running on your domain could have sent the request. The token must be
- * unique for each user and must be verifiable by the server (to prevent the JavaScript from
- * making up its own tokens). We recommend that the token is a digest of your site's
- * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
- * for added security.
- *
- * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
- * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
- * or the per-request config object.
- *
- * In order to prevent collisions in environments where multiple Angular apps share the
- * same domain or subdomain, we recommend that each application uses unique cookie name.
- *
- * @param {object} config Object describing the request to be made and how it should be
- * processed. The object has following properties:
- *
- * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
- * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
- * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
- * with the `paramSerializer` and appended as GET parameters.
- * - **data** – `{string|Object}` – Data to be sent as the request message data.
- * - **headers** – `{Object}` – Map of strings or functions which return strings representing
- * HTTP headers to send to the server. If the return value of a function is null, the
- * header will not be sent. Functions accept a config object as an argument.
- * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
- * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
- * - **transformRequest** –
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
- * transform function or an array of such functions. The transform function takes the http
- * request body and headers and returns its transformed (typically serialized) version.
- * See {@link ng.$http#overriding-the-default-transformations-per-request
- * Overriding the Default Transformations}
- * - **transformResponse** –
- * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
- * transform function or an array of such functions. The transform function takes the http
- * response body, headers and status and returns its transformed (typically deserialized) version.
- * See {@link ng.$http#overriding-the-default-transformations-per-request
- * Overriding the Default TransformationjqLiks}
- * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
- * prepare the string representation of request parameters (specified as an object).
- * If specified as string, it is interpreted as function registered with the
- * {@link $injector $injector}, which means you can create your own serializer
- * by registering it as a {@link auto.$provide#service service}.
- * The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
- * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
- * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
- * GET request, otherwise if a cache instance built with
- * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
- * caching.
- * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
- * that should abort the request when resolved.
- * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
- * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
- * for more information.
- * - **responseType** - `{string}` - see
- * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
- *
- * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
- * when the request succeeds or fails.
- *
- *
- * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
- * requests. This is primarily meant to be used for debugging purposes.
- *
- *
- * @example
-<example module="httpExample">
-<file name="index.html">
- <div ng-controller="FetchController">
- <select ng-model="method" aria-label="Request method">
- <option>GET</option>
- <option>JSONP</option>
- </select>
- <input type="text" ng-model="url" size="80" aria-label="URL" />
- <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
- <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
- <button id="samplejsonpbtn"
- ng-click="updateModel('JSONP',
- 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
- Sample JSONP
- </button>
- <button id="invalidjsonpbtn"
- ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
- Invalid JSONP
- </button>
- <pre>http status code: {{status}}</pre>
- <pre>http response data: {{data}}</pre>
- </div>
-</file>
-<file name="script.js">
- angular.module('httpExample', [])
- .controller('FetchController', ['$scope', '$http', '$templateCache',
- function($scope, $http, $templateCache) {
- $scope.method = 'GET';
- $scope.url = 'http-hello.html';
-
- $scope.fetch = function() {
- $scope.code = null;
- $scope.response = null;
-
- $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
- then(function(response) {
- $scope.status = response.status;
- $scope.data = response.data;
- }, function(response) {
- $scope.data = response.data || "Request failed";
- $scope.status = response.status;
- });
- };
-
- $scope.updateModel = function(method, url) {
- $scope.method = method;
- $scope.url = url;
- };
- }]);
-</file>
-<file name="http-hello.html">
- Hello, $http!
-</file>
-<file name="protractor.js" type="protractor">
- var status = element(by.binding('status'));
- var data = element(by.binding('data'));
- var fetchBtn = element(by.id('fetchbtn'));
- var sampleGetBtn = element(by.id('samplegetbtn'));
- var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
- var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
-
- it('should make an xhr GET request', function() {
- sampleGetBtn.click();
- fetchBtn.click();
- expect(status.getText()).toMatch('200');
- expect(data.getText()).toMatch(/Hello, \$http!/);
- });
-
-// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
-// it('should make a JSONP request to angularjs.org', function() {
-// sampleJsonpBtn.click();
-// fetchBtn.click();
-// expect(status.getText()).toMatch('200');
-// expect(data.getText()).toMatch(/Super Hero!/);
-// });
-
- it('should make JSONP request to invalid URL and invoke the error handler',
- function() {
- invalidJsonpBtn.click();
- fetchBtn.click();
- expect(status.getText()).toMatch('0');
- expect(data.getText()).toMatch('Request failed');
- });
-</file>
-</example>
- */
- function $http(requestConfig) {
-
- if (!isObject(requestConfig)) {
- throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
- }
-
- if (!isString(requestConfig.url)) {
- throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);
- }
-
- var config = extend({
- method: 'get',
- transformRequest: defaults.transformRequest,
- transformResponse: defaults.transformResponse,
- paramSerializer: defaults.paramSerializer
- }, requestConfig);
-
- config.headers = mergeHeaders(requestConfig);
- config.method = uppercase(config.method);
- config.paramSerializer = isString(config.paramSerializer) ?
- $injector.get(config.paramSerializer) : config.paramSerializer;
-
- var serverRequest = function(config) {
- var headers = config.headers;
- var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
-
- // strip content-type if data is undefined
- if (isUndefined(reqData)) {
- forEach(headers, function(value, header) {
- if (lowercase(header) === 'content-type') {
- delete headers[header];
- }
- });
- }
-
- if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
- config.withCredentials = defaults.withCredentials;
- }
-
- // send request
- return sendReq(config, reqData).then(transformResponse, transformResponse);
- };
-
- var chain = [serverRequest, undefined];
- var promise = $q.when(config);
-
- // apply interceptors
- forEach(reversedInterceptors, function(interceptor) {
- if (interceptor.request || interceptor.requestError) {
- chain.unshift(interceptor.request, interceptor.requestError);
- }
- if (interceptor.response || interceptor.responseError) {
- chain.push(interceptor.response, interceptor.responseError);
- }
- });
-
- while (chain.length) {
- var thenFn = chain.shift();
- var rejectFn = chain.shift();
-
- promise = promise.then(thenFn, rejectFn);
- }
-
- if (useLegacyPromise) {
- promise.success = function(fn) {
- assertArgFn(fn, 'fn');
-
- promise.then(function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
-
- promise.error = function(fn) {
- assertArgFn(fn, 'fn');
-
- promise.then(null, function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
- } else {
- promise.success = $httpMinErrLegacyFn('success');
- promise.error = $httpMinErrLegacyFn('error');
- }
-
- return promise;
-
- function transformResponse(response) {
- // make a copy since the response must be cacheable
- var resp = extend({}, response);
- resp.data = transformData(response.data, response.headers, response.status,
- config.transformResponse);
- return (isSuccess(response.status))
- ? resp
- : $q.reject(resp);
- }
-
- function executeHeaderFns(headers, config) {
- var headerContent, processedHeaders = {};
-
- forEach(headers, function(headerFn, header) {
- if (isFunction(headerFn)) {
- headerContent = headerFn(config);
- if (headerContent != null) {
- processedHeaders[header] = headerContent;
- }
- } else {
- processedHeaders[header] = headerFn;
- }
- });
-
- return processedHeaders;
- }
-
- function mergeHeaders(config) {
- var defHeaders = defaults.headers,
- reqHeaders = extend({}, config.headers),
- defHeaderName, lowercaseDefHeaderName, reqHeaderName;
-
- defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
-
- // using for-in instead of forEach to avoid unnecessary iteration after header has been found
- defaultHeadersIteration:
- for (defHeaderName in defHeaders) {
- lowercaseDefHeaderName = lowercase(defHeaderName);
-
- for (reqHeaderName in reqHeaders) {
- if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
- continue defaultHeadersIteration;
- }
- }
-
- reqHeaders[defHeaderName] = defHeaders[defHeaderName];
- }
-
- // execute if header value is a function for merged headers
- return executeHeaderFns(reqHeaders, shallowCopy(config));
- }
- }
-
- $http.pendingRequests = [];
-
- /**
- * @ngdoc method
- * @name $http#get
- *
- * @description
- * Shortcut method to perform `GET` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#delete
- *
- * @description
- * Shortcut method to perform `DELETE` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#head
- *
- * @description
- * Shortcut method to perform `HEAD` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#jsonp
- *
- * @description
- * Shortcut method to perform `JSONP` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request.
- * The name of the callback should be the string `JSON_CALLBACK`.
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
- createShortMethods('get', 'delete', 'head', 'jsonp');
-
- /**
- * @ngdoc method
- * @name $http#post
- *
- * @description
- * Shortcut method to perform `POST` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {*} data Request content
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#put
- *
- * @description
- * Shortcut method to perform `PUT` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {*} data Request content
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#patch
- *
- * @description
- * Shortcut method to perform `PATCH` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {*} data Request content
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
- createShortMethodsWithData('post', 'put', 'patch');
-
- /**
- * @ngdoc property
- * @name $http#defaults
- *
- * @description
- * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
- * default headers, withCredentials as well as request and response transformations.
- *
- * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
- */
- $http.defaults = defaults;
-
-
- return $http;
-
-
- function createShortMethods(names) {
- forEach(arguments, function(name) {
- $http[name] = function(url, config) {
- return $http(extend({}, config || {}, {
- method: name,
- url: url
- }));
- };
- });
- }
-
-
- function createShortMethodsWithData(name) {
- forEach(arguments, function(name) {
- $http[name] = function(url, data, config) {
- return $http(extend({}, config || {}, {
- method: name,
- url: url,
- data: data
- }));
- };
- });
- }
-
-
- /**
- * Makes the request.
- *
- * !!! ACCESSES CLOSURE VARS:
- * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
- */
- function sendReq(config, reqData) {
- var deferred = $q.defer(),
- promise = deferred.promise,
- cache,
- cachedResp,
- reqHeaders = config.headers,
- url = buildUrl(config.url, config.paramSerializer(config.params));
-
- $http.pendingRequests.push(config);
- promise.then(removePendingReq, removePendingReq);
-
-
- if ((config.cache || defaults.cache) && config.cache !== false &&
- (config.method === 'GET' || config.method === 'JSONP')) {
- cache = isObject(config.cache) ? config.cache
- : isObject(defaults.cache) ? defaults.cache
- : defaultCache;
- }
-
- if (cache) {
- cachedResp = cache.get(url);
- if (isDefined(cachedResp)) {
- if (isPromiseLike(cachedResp)) {
- // cached request has already been sent, but there is no response yet
- cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
- } else {
- // serving from cache
- if (isArray(cachedResp)) {
- resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
- } else {
- resolvePromise(cachedResp, 200, {}, 'OK');
- }
- }
- } else {
- // put the promise for the non-transformed response into cache as a placeholder
- cache.put(url, promise);
- }
- }
-
-
- // if we won't have the response in cache, set the xsrf headers and
- // send the request to the backend
- if (isUndefined(cachedResp)) {
- var xsrfValue = urlIsSameOrigin(config.url)
- ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
- : undefined;
- if (xsrfValue) {
- reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
- }
-
- $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
- config.withCredentials, config.responseType);
- }
-
- return promise;
-
-
- /**
- * Callback registered to $httpBackend():
- * - caches the response if desired
- * - resolves the raw $http promise
- * - calls $apply
- */
- function done(status, response, headersString, statusText) {
- if (cache) {
- if (isSuccess(status)) {
- cache.put(url, [status, response, parseHeaders(headersString), statusText]);
- } else {
- // remove promise from the cache
- cache.remove(url);
- }
- }
-
- function resolveHttpPromise() {
- resolvePromise(response, status, headersString, statusText);
- }
-
- if (useApplyAsync) {
- $rootScope.$applyAsync(resolveHttpPromise);
- } else {
- resolveHttpPromise();
- if (!$rootScope.$$phase) $rootScope.$apply();
- }
- }
-
-
- /**
- * Resolves the raw $http promise.
- */
- function resolvePromise(response, status, headers, statusText) {
- //status: HTTP response status code, 0, -1 (aborted by timeout / promise)
- status = status >= -1 ? status : 0;
-
- (isSuccess(status) ? deferred.resolve : deferred.reject)({
- data: response,
- status: status,
- headers: headersGetter(headers),
- config: config,
- statusText: statusText
- });
- }
-
- function resolvePromiseWithResult(result) {
- resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
- }
-
- function removePendingReq() {
- var idx = $http.pendingRequests.indexOf(config);
- if (idx !== -1) $http.pendingRequests.splice(idx, 1);
- }
- }
-
-
- function buildUrl(url, serializedParams) {
- if (serializedParams.length > 0) {
- url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams;
- }
- return url;
- }
- }];
-}
-
-/**
- * @ngdoc service
- * @name $xhrFactory
- *
- * @description
- * Factory function used to create XMLHttpRequest objects.
- *
- * Replace or decorate this service to create your own custom XMLHttpRequest objects.
- *
- * ```
- * angular.module('myApp', [])
- * .factory('$xhrFactory', function() {
- * return function createXhr(method, url) {
- * return new window.XMLHttpRequest({mozSystem: true});
- * };
- * });
- * ```
- *
- * @param {string} method HTTP method of the request (GET, POST, PUT, ..)
- * @param {string} url URL of the request.
- */
-function $xhrFactoryProvider() {
- this.$get = function() {
- return function createXhr() {
- return new window.XMLHttpRequest();
- };
- };
-}
-
-/**
- * @ngdoc service
- * @name $httpBackend
- * @requires $window
- * @requires $document
- * @requires $xhrFactory
- *
- * @description
- * HTTP backend used by the {@link ng.$http service} that delegates to
- * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
- *
- * You should never need to use this service directly, instead use the higher-level abstractions:
- * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
- *
- * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
- * $httpBackend} which can be trained with responses.
- */
-function $HttpBackendProvider() {
- this.$get = ['$browser', '$window', '$document', '$xhrFactory', function($browser, $window, $document, $xhrFactory) {
- return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]);
- }];
-}
-
-function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
- // TODO(vojta): fix the signature
- return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
- $browser.$$incOutstandingRequestCount();
- url = url || $browser.url();
-
- if (lowercase(method) == 'jsonp') {
- var callbackId = '_' + (callbacks.counter++).toString(36);
- callbacks[callbackId] = function(data) {
- callbacks[callbackId].data = data;
- callbacks[callbackId].called = true;
- };
-
- var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
- callbackId, function(status, text) {
- completeRequest(callback, status, callbacks[callbackId].data, "", text);
- callbacks[callbackId] = noop;
- });
- } else {
-
- var xhr = createXhr(method, url);
-
- xhr.open(method, url, true);
- forEach(headers, function(value, key) {
- if (isDefined(value)) {
- xhr.setRequestHeader(key, value);
- }
- });
-
- xhr.onload = function requestLoaded() {
- var statusText = xhr.statusText || '';
-
- // responseText is the old-school way of retrieving response (supported by IE9)
- // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
- var response = ('response' in xhr) ? xhr.response : xhr.responseText;
-
- // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
- var status = xhr.status === 1223 ? 204 : xhr.status;
-
- // fix status code when it is 0 (0 status is undocumented).
- // Occurs when accessing file resources or on Android 4.1 stock browser
- // while retrieving files from application cache.
- if (status === 0) {
- status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
- }
-
- completeRequest(callback,
- status,
- response,
- xhr.getAllResponseHeaders(),
- statusText);
- };
-
- var requestError = function() {
- // The response is always empty
- // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
- completeRequest(callback, -1, null, null, '');
- };
-
- xhr.onerror = requestError;
- xhr.onabort = requestError;
-
- if (withCredentials) {
- xhr.withCredentials = true;
- }
-
- if (responseType) {
- try {
- xhr.responseType = responseType;
- } catch (e) {
- // WebKit added support for the json responseType value on 09/03/2013
- // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
- // known to throw when setting the value "json" as the response type. Other older
- // browsers implementing the responseType
- //
- // The json response type can be ignored if not supported, because JSON payloads are
- // parsed on the client-side regardless.
- if (responseType !== 'json') {
- throw e;
- }
- }
- }
-
- xhr.send(isUndefined(post) ? null : post);
- }
-
- if (timeout > 0) {
- var timeoutId = $browserDefer(timeoutRequest, timeout);
- } else if (isPromiseLike(timeout)) {
- timeout.then(timeoutRequest);
- }
-
-
- function timeoutRequest() {
- jsonpDone && jsonpDone();
- xhr && xhr.abort();
- }
-
- function completeRequest(callback, status, response, headersString, statusText) {
- // cancel timeout and subsequent timeout promise resolution
- if (isDefined(timeoutId)) {
- $browserDefer.cancel(timeoutId);
- }
- jsonpDone = xhr = null;
-
- callback(status, response, headersString, statusText);
- $browser.$$completeOutstandingRequest(noop);
- }
- };
-
- function jsonpReq(url, callbackId, done) {
- // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
- // - fetches local scripts via XHR and evals them
- // - adds and immediately removes script elements from the document
- var script = rawDocument.createElement('script'), callback = null;
- script.type = "text/javascript";
- script.src = url;
- script.async = true;
-
- callback = function(event) {
- removeEventListenerFn(script, "load", callback);
- removeEventListenerFn(script, "error", callback);
- rawDocument.body.removeChild(script);
- script = null;
- var status = -1;
- var text = "unknown";
-
- if (event) {
- if (event.type === "load" && !callbacks[callbackId].called) {
- event = { type: "error" };
- }
- text = event.type;
- status = event.type === "error" ? 404 : 200;
- }
-
- if (done) {
- done(status, text);
- }
- };
-
- addEventListenerFn(script, "load", callback);
- addEventListenerFn(script, "error", callback);
- rawDocument.body.appendChild(script);
- return callback;
- }
-}
-
-var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');
-$interpolateMinErr.throwNoconcat = function(text) {
- throw $interpolateMinErr('noconcat',
- "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
- "interpolations that concatenate multiple expressions when a trusted value is " +
- "required. See http://docs.angularjs.org/api/ng.$sce", text);
-};
-
-$interpolateMinErr.interr = function(text, err) {
- return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
-};
-
-/**
- * @ngdoc provider
- * @name $interpolateProvider
- *
- * @description
- *
- * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
- *
- * <div class="alert alert-danger">
- * This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular
- * template within a Python Jinja template (or any other template language). Mixing templating
- * languages is **very dangerous**. The embedding template language will not safely escape Angular
- * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)
- * security bugs!
- * </div>
- *
- * @example
-<example name="custom-interpolation-markup" module="customInterpolationApp">
-<file name="index.html">
-<script>
- var customInterpolationApp = angular.module('customInterpolationApp', []);
-
- customInterpolationApp.config(function($interpolateProvider) {
- $interpolateProvider.startSymbol('//');
- $interpolateProvider.endSymbol('//');
- });
-
-
- customInterpolationApp.controller('DemoController', function() {
- this.label = "This binding is brought you by // interpolation symbols.";
- });
-</script>
-<div ng-controller="DemoController as demo">
- //demo.label//
-</div>
-</file>
-<file name="protractor.js" type="protractor">
- it('should interpolate binding with custom symbols', function() {
- expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
- });
-</file>
-</example>
- */
-function $InterpolateProvider() {
- var startSymbol = '{{';
- var endSymbol = '}}';
-
- /**
- * @ngdoc method
- * @name $interpolateProvider#startSymbol
- * @description
- * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
- *
- * @param {string=} value new value to set the starting symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.startSymbol = function(value) {
- if (value) {
- startSymbol = value;
- return this;
- } else {
- return startSymbol;
- }
- };
-
- /**
- * @ngdoc method
- * @name $interpolateProvider#endSymbol
- * @description
- * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
- *
- * @param {string=} value new value to set the ending symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.endSymbol = function(value) {
- if (value) {
- endSymbol = value;
- return this;
- } else {
- return endSymbol;
- }
- };
-
-
- this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
- var startSymbolLength = startSymbol.length,
- endSymbolLength = endSymbol.length,
- escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
- escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
-
- function escape(ch) {
- return '\\\\\\' + ch;
- }
-
- function unescapeText(text) {
- return text.replace(escapedStartRegexp, startSymbol).
- replace(escapedEndRegexp, endSymbol);
- }
-
- function stringify(value) {
- if (value == null) { // null || undefined
- return '';
- }
- switch (typeof value) {
- case 'string':
- break;
- case 'number':
- value = '' + value;
- break;
- default:
- value = toJson(value);
- }
-
- return value;
- }
-
- //TODO: this is the same as the constantWatchDelegate in parse.js
- function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {
- var unwatch;
- return unwatch = scope.$watch(function constantInterpolateWatch(scope) {
- unwatch();
- return constantInterp(scope);
- }, listener, objectEquality);
- }
-
- /**
- * @ngdoc service
- * @name $interpolate
- * @kind function
- *
- * @requires $parse
- * @requires $sce
- *
- * @description
- *
- * Compiles a string with markup into an interpolation function. This service is used by the
- * HTML {@link ng.$compile $compile} service for data binding. See
- * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
- * interpolation markup.
- *
- *
- * ```js
- * var $interpolate = ...; // injected
- * var exp = $interpolate('Hello {{name | uppercase}}!');
- * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');
- * ```
- *
- * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
- * `true`, the interpolation function will return `undefined` unless all embedded expressions
- * evaluate to a value other than `undefined`.
- *
- * ```js
- * var $interpolate = ...; // injected
- * var context = {greeting: 'Hello', name: undefined };
- *
- * // default "forgiving" mode
- * var exp = $interpolate('{{greeting}} {{name}}!');
- * expect(exp(context)).toEqual('Hello !');
- *
- * // "allOrNothing" mode
- * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
- * expect(exp(context)).toBeUndefined();
- * context.name = 'Angular';
- * expect(exp(context)).toEqual('Hello Angular!');
- * ```
- *
- * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
- *
- * ####Escaped Interpolation
- * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
- * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
- * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
- * or binding.
- *
- * This enables web-servers to prevent script injection attacks and defacing attacks, to some
- * degree, while also enabling code examples to work without relying on the
- * {@link ng.directive:ngNonBindable ngNonBindable} directive.
- *
- * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
- * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
- * interpolation start/end markers with their escaped counterparts.**
- *
- * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
- * output when the $interpolate service processes the text. So, for HTML elements interpolated
- * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
- * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
- * this is typically useful only when user-data is used in rendering a template from the server, or
- * when otherwise untrusted data is used by a directive.
- *
- * <example>
- * <file name="index.html">
- * <div ng-init="username='A user'">
- * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
- * </p>
- * <p><strong>{{username}}</strong> attempts to inject code which will deface the
- * application, but fails to accomplish their task, because the server has correctly
- * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
- * characters.</p>
- * <p>Instead, the result of the attempted script injection is visible, and can be removed
- * from the database by an administrator.</p>
- * </div>
- * </file>
- * </example>
- *
- * @param {string} text The text with markup to interpolate.
- * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
- * embedded expression in order to return an interpolation function. Strings with no
- * embedded expression will return null for the interpolation function.
- * @param {string=} trustedContext when provided, the returned function passes the interpolated
- * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
- * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
- * provides Strict Contextual Escaping for details.
- * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
- * unless all embedded expressions evaluate to a value other than `undefined`.
- * @returns {function(context)} an interpolation function which is used to compute the
- * interpolated string. The function has these parameters:
- *
- * - `context`: evaluation context for all expressions embedded in the interpolated text
- */
- function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
- // Provide a quick exit and simplified result function for text with no interpolation
- if (!text.length || text.indexOf(startSymbol) === -1) {
- var constantInterp;
- if (!mustHaveExpression) {
- var unescapedText = unescapeText(text);
- constantInterp = valueFn(unescapedText);
- constantInterp.exp = text;
- constantInterp.expressions = [];
- constantInterp.$$watchDelegate = constantWatchDelegate;
- }
- return constantInterp;
- }
-
- allOrNothing = !!allOrNothing;
- var startIndex,
- endIndex,
- index = 0,
- expressions = [],
- parseFns = [],
- textLength = text.length,
- exp,
- concat = [],
- expressionPositions = [];
-
- while (index < textLength) {
- if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
- ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
- if (index !== startIndex) {
- concat.push(unescapeText(text.substring(index, startIndex)));
- }
- exp = text.substring(startIndex + startSymbolLength, endIndex);
- expressions.push(exp);
- parseFns.push($parse(exp, parseStringifyInterceptor));
- index = endIndex + endSymbolLength;
- expressionPositions.push(concat.length);
- concat.push('');
- } else {
- // we did not find an interpolation, so we have to add the remainder to the separators array
- if (index !== textLength) {
- concat.push(unescapeText(text.substring(index)));
- }
- break;
- }
- }
-
- // Concatenating expressions makes it hard to reason about whether some combination of
- // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
- // single expression be used for iframe[src], object[src], etc., we ensure that the value
- // that's used is assigned or constructed by some JS code somewhere that is more testable or
- // make it obvious that you bound the value to some user controlled value. This helps reduce
- // the load when auditing for XSS issues.
- if (trustedContext && concat.length > 1) {
- $interpolateMinErr.throwNoconcat(text);
- }
-
- if (!mustHaveExpression || expressions.length) {
- var compute = function(values) {
- for (var i = 0, ii = expressions.length; i < ii; i++) {
- if (allOrNothing && isUndefined(values[i])) return;
- concat[expressionPositions[i]] = values[i];
- }
- return concat.join('');
- };
-
- var getValue = function(value) {
- return trustedContext ?
- $sce.getTrusted(trustedContext, value) :
- $sce.valueOf(value);
- };
-
- return extend(function interpolationFn(context) {
- var i = 0;
- var ii = expressions.length;
- var values = new Array(ii);
-
- try {
- for (; i < ii; i++) {
- values[i] = parseFns[i](context);
- }
-
- return compute(values);
- } catch (err) {
- $exceptionHandler($interpolateMinErr.interr(text, err));
- }
-
- }, {
- // all of these properties are undocumented for now
- exp: text, //just for compatibility with regular watchers created via $watch
- expressions: expressions,
- $$watchDelegate: function(scope, listener) {
- var lastValue;
- return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
- var currValue = compute(values);
- if (isFunction(listener)) {
- listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
- }
- lastValue = currValue;
- });
- }
- });
- }
-
- function parseStringifyInterceptor(value) {
- try {
- value = getValue(value);
- return allOrNothing && !isDefined(value) ? value : stringify(value);
- } catch (err) {
- $exceptionHandler($interpolateMinErr.interr(text, err));
- }
- }
- }
-
-
- /**
- * @ngdoc method
- * @name $interpolate#startSymbol
- * @description
- * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
- *
- * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
- * the symbol.
- *
- * @returns {string} start symbol.
- */
- $interpolate.startSymbol = function() {
- return startSymbol;
- };
-
-
- /**
- * @ngdoc method
- * @name $interpolate#endSymbol
- * @description
- * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
- *
- * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
- * the symbol.
- *
- * @returns {string} end symbol.
- */
- $interpolate.endSymbol = function() {
- return endSymbol;
- };
-
- return $interpolate;
- }];
-}
-
-function $IntervalProvider() {
- this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser',
- function($rootScope, $window, $q, $$q, $browser) {
- var intervals = {};
-
-
- /**
- * @ngdoc service
- * @name $interval
- *
- * @description
- * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
- * milliseconds.
- *
- * The return value of registering an interval function is a promise. This promise will be
- * notified upon each tick of the interval, and will be resolved after `count` iterations, or
- * run indefinitely if `count` is not defined. The value of the notification will be the
- * number of iterations that have run.
- * To cancel an interval, call `$interval.cancel(promise)`.
- *
- * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
- * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
- * time.
- *
- * <div class="alert alert-warning">
- * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
- * with them. In particular they are not automatically destroyed when a controller's scope or a
- * directive's element are destroyed.
- * You should take this into consideration and make sure to always cancel the interval at the
- * appropriate moment. See the example below for more details on how and when to do this.
- * </div>
- *
- * @param {function()} fn A function that should be called repeatedly.
- * @param {number} delay Number of milliseconds between each function call.
- * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
- * indefinitely.
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
- * @param {...*=} Pass additional parameters to the executed function.
- * @returns {promise} A promise which will be notified on each iteration.
- *
- * @example
- * <example module="intervalExample">
- * <file name="index.html">
- * <script>
- * angular.module('intervalExample', [])
- * .controller('ExampleController', ['$scope', '$interval',
- * function($scope, $interval) {
- * $scope.format = 'M/d/yy h:mm:ss a';
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
- *
- * var stop;
- * $scope.fight = function() {
- * // Don't start a new fight if we are already fighting
- * if ( angular.isDefined(stop) ) return;
- *
- * stop = $interval(function() {
- * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
- * $scope.blood_1 = $scope.blood_1 - 3;
- * $scope.blood_2 = $scope.blood_2 - 4;
- * } else {
- * $scope.stopFight();
- * }
- * }, 100);
- * };
- *
- * $scope.stopFight = function() {
- * if (angular.isDefined(stop)) {
- * $interval.cancel(stop);
- * stop = undefined;
- * }
- * };
- *
- * $scope.resetFight = function() {
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
- * };
- *
- * $scope.$on('$destroy', function() {
- * // Make sure that the interval is destroyed too
- * $scope.stopFight();
- * });
- * }])
- * // Register the 'myCurrentTime' directive factory method.
- * // We inject $interval and dateFilter service since the factory method is DI.
- * .directive('myCurrentTime', ['$interval', 'dateFilter',
- * function($interval, dateFilter) {
- * // return the directive link function. (compile function not needed)
- * return function(scope, element, attrs) {
- * var format, // date format
- * stopTime; // so that we can cancel the time updates
- *
- * // used to update the UI
- * function updateTime() {
- * element.text(dateFilter(new Date(), format));
- * }
- *
- * // watch the expression, and update the UI on change.
- * scope.$watch(attrs.myCurrentTime, function(value) {
- * format = value;
- * updateTime();
- * });
- *
- * stopTime = $interval(updateTime, 1000);
- *
- * // listen on DOM destroy (removal) event, and cancel the next UI update
- * // to prevent updating time after the DOM element was removed.
- * element.on('$destroy', function() {
- * $interval.cancel(stopTime);
- * });
- * }
- * }]);
- * </script>
- *
- * <div>
- * <div ng-controller="ExampleController">
- * <label>Date format: <input ng-model="format"></label> <hr/>
- * Current time is: <span my-current-time="format"></span>
- * <hr/>
- * Blood 1 : <font color='red'>{{blood_1}}</font>
- * Blood 2 : <font color='red'>{{blood_2}}</font>
- * <button type="button" data-ng-click="fight()">Fight</button>
- * <button type="button" data-ng-click="stopFight()">StopFight</button>
- * <button type="button" data-ng-click="resetFight()">resetFight</button>
- * </div>
- * </div>
- *
- * </file>
- * </example>
- */
- function interval(fn, delay, count, invokeApply) {
- var hasParams = arguments.length > 4,
- args = hasParams ? sliceArgs(arguments, 4) : [],
- setInterval = $window.setInterval,
- clearInterval = $window.clearInterval,
- iteration = 0,
- skipApply = (isDefined(invokeApply) && !invokeApply),
- deferred = (skipApply ? $$q : $q).defer(),
- promise = deferred.promise;
-
- count = isDefined(count) ? count : 0;
-
- promise.$$intervalId = setInterval(function tick() {
- if (skipApply) {
- $browser.defer(callback);
- } else {
- $rootScope.$evalAsync(callback);
- }
- deferred.notify(iteration++);
-
- if (count > 0 && iteration >= count) {
- deferred.resolve(iteration);
- clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- }
-
- if (!skipApply) $rootScope.$apply();
-
- }, delay);
-
- intervals[promise.$$intervalId] = deferred;
-
- return promise;
-
- function callback() {
- if (!hasParams) {
- fn(iteration);
- } else {
- fn.apply(null, args);
- }
- }
- }
-
-
- /**
- * @ngdoc method
- * @name $interval#cancel
- *
- * @description
- * Cancels a task associated with the `promise`.
- *
- * @param {Promise=} promise returned by the `$interval` function.
- * @returns {boolean} Returns `true` if the task was successfully canceled.
- */
- interval.cancel = function(promise) {
- if (promise && promise.$$intervalId in intervals) {
- intervals[promise.$$intervalId].reject('canceled');
- $window.clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- return true;
- }
- return false;
- };
-
- return interval;
- }];
-}
-
-/**
- * @ngdoc service
- * @name $locale
- *
- * @description
- * $locale service provides localization rules for various Angular components. As of right now the
- * only public api is:
- *
- * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
- */
-
-var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
- DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
-var $locationMinErr = minErr('$location');
-
-
-/**
- * Encode path using encodeUriSegment, ignoring forward slashes
- *
- * @param {string} path Path to encode
- * @returns {string}
- */
-function encodePath(path) {
- var segments = path.split('/'),
- i = segments.length;
-
- while (i--) {
- segments[i] = encodeUriSegment(segments[i]);
- }
-
- return segments.join('/');
-}
-
-function parseAbsoluteUrl(absoluteUrl, locationObj) {
- var parsedUrl = urlResolve(absoluteUrl);
-
- locationObj.$$protocol = parsedUrl.protocol;
- locationObj.$$host = parsedUrl.hostname;
- locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
-}
-
-
-function parseAppUrl(relativeUrl, locationObj) {
- var prefixed = (relativeUrl.charAt(0) !== '/');
- if (prefixed) {
- relativeUrl = '/' + relativeUrl;
- }
- var match = urlResolve(relativeUrl);
- locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
- match.pathname.substring(1) : match.pathname);
- locationObj.$$search = parseKeyValue(match.search);
- locationObj.$$hash = decodeURIComponent(match.hash);
-
- // make sure path starts with '/';
- if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
- locationObj.$$path = '/' + locationObj.$$path;
- }
-}
-
-
-/**
- *
- * @param {string} begin
- * @param {string} whole
- * @returns {string} returns text from whole after begin or undefined if it does not begin with
- * expected string.
- */
-function beginsWith(begin, whole) {
- if (whole.indexOf(begin) === 0) {
- return whole.substr(begin.length);
- }
-}
-
-
-function stripHash(url) {
- var index = url.indexOf('#');
- return index == -1 ? url : url.substr(0, index);
-}
-
-function trimEmptyHash(url) {
- return url.replace(/(#.+)|#$/, '$1');
-}
-
-
-function stripFile(url) {
- return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
-}
-
-/* return the server only (scheme://host:port) */
-function serverBase(url) {
- return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
-}
-
-
-/**
- * LocationHtml5Url represents an url
- * This object is exposed as $location service when HTML5 mode is enabled and supported
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} appBaseNoFile application base URL stripped of any filename
- * @param {string} basePrefix url path prefix
- */
-function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
- this.$$html5 = true;
- basePrefix = basePrefix || '';
- parseAbsoluteUrl(appBase, this);
-
-
- /**
- * Parse given html5 (regular) url string into properties
- * @param {string} url HTML5 url
- * @private
- */
- this.$$parse = function(url) {
- var pathUrl = beginsWith(appBaseNoFile, url);
- if (!isString(pathUrl)) {
- throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
- appBaseNoFile);
- }
-
- parseAppUrl(pathUrl, this);
-
- if (!this.$$path) {
- this.$$path = '/';
- }
-
- this.$$compose();
- };
-
- /**
- * Compose url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
- };
-
- this.$$parseLinkUrl = function(url, relHref) {
- if (relHref && relHref[0] === '#') {
- // special case for links to hash fragments:
- // keep the old url and only replace the hash fragment
- this.hash(relHref.slice(1));
- return true;
- }
- var appUrl, prevAppUrl;
- var rewrittenUrl;
-
- if (isDefined(appUrl = beginsWith(appBase, url))) {
- prevAppUrl = appUrl;
- if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
- rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
- } else {
- rewrittenUrl = appBase + prevAppUrl;
- }
- } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
- rewrittenUrl = appBaseNoFile + appUrl;
- } else if (appBaseNoFile == url + '/') {
- rewrittenUrl = appBaseNoFile;
- }
- if (rewrittenUrl) {
- this.$$parse(rewrittenUrl);
- }
- return !!rewrittenUrl;
- };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when developer doesn't opt into html5 mode.
- * It also serves as the base class for html5 mode fallback on legacy browsers.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} appBaseNoFile application base URL stripped of any filename
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
-
- parseAbsoluteUrl(appBase, this);
-
-
- /**
- * Parse given hashbang url into properties
- * @param {string} url Hashbang url
- * @private
- */
- this.$$parse = function(url) {
- var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
- var withoutHashUrl;
-
- if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
-
- // The rest of the url starts with a hash so we have
- // got either a hashbang path or a plain hash fragment
- withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
- if (isUndefined(withoutHashUrl)) {
- // There was no hashbang prefix so we just have a hash fragment
- withoutHashUrl = withoutBaseUrl;
- }
-
- } else {
- // There was no hashbang path nor hash fragment:
- // If we are in HTML5 mode we use what is left as the path;
- // Otherwise we ignore what is left
- if (this.$$html5) {
- withoutHashUrl = withoutBaseUrl;
- } else {
- withoutHashUrl = '';
- if (isUndefined(withoutBaseUrl)) {
- appBase = url;
- this.replace();
- }
- }
- }
-
- parseAppUrl(withoutHashUrl, this);
-
- this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
-
- this.$$compose();
-
- /*
- * In Windows, on an anchor node on documents loaded from
- * the filesystem, the browser will return a pathname
- * prefixed with the drive name ('/C:/path') when a
- * pathname without a drive is set:
- * * a.setAttribute('href', '/foo')
- * * a.pathname === '/C:/foo' //true
- *
- * Inside of Angular, we're always using pathnames that
- * do not include drive names for routing.
- */
- function removeWindowsDriveName(path, url, base) {
- /*
- Matches paths for file protocol on windows,
- such as /C:/foo/bar, and captures only /foo/bar.
- */
- var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
-
- var firstPathSegmentMatch;
-
- //Get the relative path from the input URL.
- if (url.indexOf(base) === 0) {
- url = url.replace(base, '');
- }
-
- // The input URL intentionally contains a first path segment that ends with a colon.
- if (windowsFilePathExp.exec(url)) {
- return path;
- }
-
- firstPathSegmentMatch = windowsFilePathExp.exec(path);
- return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
- }
- };
-
- /**
- * Compose hashbang url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
- };
-
- this.$$parseLinkUrl = function(url, relHref) {
- if (stripHash(appBase) == stripHash(url)) {
- this.$$parse(url);
- return true;
- }
- return false;
- };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when html5 history api is enabled but the browser
- * does not support it.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} appBaseNoFile application base URL stripped of any filename
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
- this.$$html5 = true;
- LocationHashbangUrl.apply(this, arguments);
-
- this.$$parseLinkUrl = function(url, relHref) {
- if (relHref && relHref[0] === '#') {
- // special case for links to hash fragments:
- // keep the old url and only replace the hash fragment
- this.hash(relHref.slice(1));
- return true;
- }
-
- var rewrittenUrl;
- var appUrl;
-
- if (appBase == stripHash(url)) {
- rewrittenUrl = url;
- } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
- rewrittenUrl = appBase + hashPrefix + appUrl;
- } else if (appBaseNoFile === url + '/') {
- rewrittenUrl = appBaseNoFile;
- }
- if (rewrittenUrl) {
- this.$$parse(rewrittenUrl);
- }
- return !!rewrittenUrl;
- };
-
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'
- this.$$absUrl = appBase + hashPrefix + this.$$url;
- };
-
-}
-
-
-var locationPrototype = {
-
- /**
- * Are we in html5 mode?
- * @private
- */
- $$html5: false,
-
- /**
- * Has any change been replacing?
- * @private
- */
- $$replace: false,
-
- /**
- * @ngdoc method
- * @name $location#absUrl
- *
- * @description
- * This method is getter only.
- *
- * Return full url representation with all segments encoded according to rules specified in
- * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var absUrl = $location.absUrl();
- * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
- * ```
- *
- * @return {string} full url
- */
- absUrl: locationGetter('$$absUrl'),
-
- /**
- * @ngdoc method
- * @name $location#url
- *
- * @description
- * This method is getter / setter.
- *
- * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
- *
- * Change path, search and hash, when called with parameter and return `$location`.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var url = $location.url();
- * // => "/some/path?foo=bar&baz=xoxo"
- * ```
- *
- * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
- * @return {string} url
- */
- url: function(url) {
- if (isUndefined(url)) {
- return this.$$url;
- }
-
- var match = PATH_MATCH.exec(url);
- if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
- if (match[2] || match[1] || url === '') this.search(match[3] || '');
- this.hash(match[5] || '');
-
- return this;
- },
-
- /**
- * @ngdoc method
- * @name $location#protocol
- *
- * @description
- * This method is getter only.
- *
- * Return protocol of current url.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var protocol = $location.protocol();
- * // => "http"
- * ```
- *
- * @return {string} protocol of current url
- */
- protocol: locationGetter('$$protocol'),
-
- /**
- * @ngdoc method
- * @name $location#host
- *
- * @description
- * This method is getter only.
- *
- * Return host of current url.
- *
- * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var host = $location.host();
- * // => "example.com"
- *
- * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
- * host = $location.host();
- * // => "example.com"
- * host = location.host;
- * // => "example.com:8080"
- * ```
- *
- * @return {string} host of current url.
- */
- host: locationGetter('$$host'),
-
- /**
- * @ngdoc method
- * @name $location#port
- *
- * @description
- * This method is getter only.
- *
- * Return port of current url.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var port = $location.port();
- * // => 80
- * ```
- *
- * @return {Number} port
- */
- port: locationGetter('$$port'),
-
- /**
- * @ngdoc method
- * @name $location#path
- *
- * @description
- * This method is getter / setter.
- *
- * Return path of current url when called without any parameter.
- *
- * Change path when called with parameter and return `$location`.
- *
- * Note: Path should always begin with forward slash (/), this method will add the forward slash
- * if it is missing.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var path = $location.path();
- * // => "/some/path"
- * ```
- *
- * @param {(string|number)=} path New path
- * @return {string} path
- */
- path: locationGetterSetter('$$path', function(path) {
- path = path !== null ? path.toString() : '';
- return path.charAt(0) == '/' ? path : '/' + path;
- }),
-
- /**
- * @ngdoc method
- * @name $location#search
- *
- * @description
- * This method is getter / setter.
- *
- * Return search part (as object) of current url when called without any parameter.
- *
- * Change search part when called with parameter and return `$location`.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var searchObject = $location.search();
- * // => {foo: 'bar', baz: 'xoxo'}
- *
- * // set foo to 'yipee'
- * $location.search('foo', 'yipee');
- * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
- * ```
- *
- * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
- * hash object.
- *
- * When called with a single argument the method acts as a setter, setting the `search` component
- * of `$location` to the specified value.
- *
- * If the argument is a hash object containing an array of values, these values will be encoded
- * as duplicate search parameters in the url.
- *
- * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
- * will override only a single search property.
- *
- * If `paramValue` is an array, it will override the property of the `search` component of
- * `$location` specified via the first argument.
- *
- * If `paramValue` is `null`, the property specified via the first argument will be deleted.
- *
- * If `paramValue` is `true`, the property specified via the first argument will be added with no
- * value nor trailing equal sign.
- *
- * @return {Object} If called with no arguments returns the parsed `search` object. If called with
- * one or more arguments returns `$location` object itself.
- */
- search: function(search, paramValue) {
- switch (arguments.length) {
- case 0:
- return this.$$search;
- case 1:
- if (isString(search) || isNumber(search)) {
- search = search.toString();
- this.$$search = parseKeyValue(search);
- } else if (isObject(search)) {
- search = copy(search, {});
- // remove object undefined or null properties
- forEach(search, function(value, key) {
- if (value == null) delete search[key];
- });
-
- this.$$search = search;
- } else {
- throw $locationMinErr('isrcharg',
- 'The first argument of the `$location#search()` call must be a string or an object.');
- }
- break;
- default:
- if (isUndefined(paramValue) || paramValue === null) {
- delete this.$$search[search];
- } else {
- this.$$search[search] = paramValue;
- }
- }
-
- this.$$compose();
- return this;
- },
-
- /**
- * @ngdoc method
- * @name $location#hash
- *
- * @description
- * This method is getter / setter.
- *
- * Returns the hash fragment when called without any parameters.
- *
- * Changes the hash fragment when called with a parameter and returns `$location`.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
- * var hash = $location.hash();
- * // => "hashValue"
- * ```
- *
- * @param {(string|number)=} hash New hash fragment
- * @return {string} hash
- */
- hash: locationGetterSetter('$$hash', function(hash) {
- return hash !== null ? hash.toString() : '';
- }),
-
- /**
- * @ngdoc method
- * @name $location#replace
- *
- * @description
- * If called, all changes to $location during the current `$digest` will replace the current history
- * record, instead of adding a new one.
- */
- replace: function() {
- this.$$replace = true;
- return this;
- }
-};
-
-forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
- Location.prototype = Object.create(locationPrototype);
-
- /**
- * @ngdoc method
- * @name $location#state
- *
- * @description
- * This method is getter / setter.
- *
- * Return the history state object when called without any parameter.
- *
- * Change the history state object when called with one parameter and return `$location`.
- * The state object is later passed to `pushState` or `replaceState`.
- *
- * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
- * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
- * older browsers (like IE9 or Android < 4.0), don't use this method.
- *
- * @param {object=} state State object for pushState or replaceState
- * @return {object} state
- */
- Location.prototype.state = function(state) {
- if (!arguments.length) {
- return this.$$state;
- }
-
- if (Location !== LocationHtml5Url || !this.$$html5) {
- throw $locationMinErr('nostate', 'History API state support is available only ' +
- 'in HTML5 mode and only in browsers supporting HTML5 History API');
- }
- // The user might modify `stateObject` after invoking `$location.state(stateObject)`
- // but we're changing the $$state reference to $browser.state() during the $digest
- // so the modification window is narrow.
- this.$$state = isUndefined(state) ? null : state;
-
- return this;
- };
-});
-
-
-function locationGetter(property) {
- return function() {
- return this[property];
- };
-}
-
-
-function locationGetterSetter(property, preprocess) {
- return function(value) {
- if (isUndefined(value)) {
- return this[property];
- }
-
- this[property] = preprocess(value);
- this.$$compose();
-
- return this;
- };
-}
-
-
-/**
- * @ngdoc service
- * @name $location
- *
- * @requires $rootElement
- *
- * @description
- * The $location service parses the URL in the browser address bar (based on the
- * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
- * available to your application. Changes to the URL in the address bar are reflected into
- * $location service and changes to $location are reflected into the browser address bar.
- *
- * **The $location service:**
- *
- * - Exposes the current URL in the browser address bar, so you can
- * - Watch and observe the URL.
- * - Change the URL.
- * - Synchronizes the URL with the browser when the user
- * - Changes the address bar.
- * - Clicks the back or forward button (or clicks a History link).
- * - Clicks on a link.
- * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
- *
- * For more information see {@link guide/$location Developer Guide: Using $location}
- */
-
-/**
- * @ngdoc provider
- * @name $locationProvider
- * @description
- * Use the `$locationProvider` to configure how the application deep linking paths are stored.
- */
-function $LocationProvider() {
- var hashPrefix = '',
- html5Mode = {
- enabled: false,
- requireBase: true,
- rewriteLinks: true
- };
-
- /**
- * @ngdoc method
- * @name $locationProvider#hashPrefix
- * @description
- * @param {string=} prefix Prefix for hash part (containing path and search)
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.hashPrefix = function(prefix) {
- if (isDefined(prefix)) {
- hashPrefix = prefix;
- return this;
- } else {
- return hashPrefix;
- }
- };
-
- /**
- * @ngdoc method
- * @name $locationProvider#html5Mode
- * @description
- * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
- * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
- * properties:
- * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
- * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
- * support `pushState`.
- * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
- * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
- * true, and a base tag is not present, an error will be thrown when `$location` is injected.
- * See the {@link guide/$location $location guide for more information}
- * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
- * enables/disables url rewriting for relative links.
- *
- * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
- */
- this.html5Mode = function(mode) {
- if (isBoolean(mode)) {
- html5Mode.enabled = mode;
- return this;
- } else if (isObject(mode)) {
-
- if (isBoolean(mode.enabled)) {
- html5Mode.enabled = mode.enabled;
- }
-
- if (isBoolean(mode.requireBase)) {
- html5Mode.requireBase = mode.requireBase;
- }
-
- if (isBoolean(mode.rewriteLinks)) {
- html5Mode.rewriteLinks = mode.rewriteLinks;
- }
-
- return this;
- } else {
- return html5Mode;
- }
- };
-
- /**
- * @ngdoc event
- * @name $location#$locationChangeStart
- * @eventType broadcast on root scope
- * @description
- * Broadcasted before a URL will change.
- *
- * This change can be prevented by calling
- * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
- * details about event object. Upon successful change
- * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
- *
- * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
- * the browser supports the HTML5 History API.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {string} newUrl New URL
- * @param {string=} oldUrl URL that was before it was changed.
- * @param {string=} newState New history state object
- * @param {string=} oldState History state object that was before it was changed.
- */
-
- /**
- * @ngdoc event
- * @name $location#$locationChangeSuccess
- * @eventType broadcast on root scope
- * @description
- * Broadcasted after a URL was changed.
- *
- * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
- * the browser supports the HTML5 History API.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {string} newUrl New URL
- * @param {string=} oldUrl URL that was before it was changed.
- * @param {string=} newState New history state object
- * @param {string=} oldState History state object that was before it was changed.
- */
-
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
- function($rootScope, $browser, $sniffer, $rootElement, $window) {
- var $location,
- LocationMode,
- baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
- initialUrl = $browser.url(),
- appBase;
-
- if (html5Mode.enabled) {
- if (!baseHref && html5Mode.requireBase) {
- throw $locationMinErr('nobase',
- "$location in HTML5 mode requires a <base> tag to be present!");
- }
- appBase = serverBase(initialUrl) + (baseHref || '/');
- LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
- } else {
- appBase = stripHash(initialUrl);
- LocationMode = LocationHashbangUrl;
- }
- var appBaseNoFile = stripFile(appBase);
-
- $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
- $location.$$parseLinkUrl(initialUrl, initialUrl);
-
- $location.$$state = $browser.state();
-
- var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
-
- function setBrowserUrlWithFallback(url, replace, state) {
- var oldUrl = $location.url();
- var oldState = $location.$$state;
- try {
- $browser.url(url, replace, state);
-
- // Make sure $location.state() returns referentially identical (not just deeply equal)
- // state object; this makes possible quick checking if the state changed in the digest
- // loop. Checking deep equality would be too expensive.
- $location.$$state = $browser.state();
- } catch (e) {
- // Restore old values if pushState fails
- $location.url(oldUrl);
- $location.$$state = oldState;
-
- throw e;
- }
- }
-
- $rootElement.on('click', function(event) {
- // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
- // currently we open nice url link and redirect then
-
- if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
-
- var elm = jqLite(event.target);
-
- // traverse the DOM up to find first A tag
- while (nodeName_(elm[0]) !== 'a') {
- // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
- if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
- }
-
- var absHref = elm.prop('href');
- // get the actual href attribute - see
- // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
- var relHref = elm.attr('href') || elm.attr('xlink:href');
-
- if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
- // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
- // an animation.
- absHref = urlResolve(absHref.animVal).href;
- }
-
- // Ignore when url is started with javascript: or mailto:
- if (IGNORE_URI_REGEXP.test(absHref)) return;
-
- if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
- if ($location.$$parseLinkUrl(absHref, relHref)) {
- // We do a preventDefault for all urls that are part of the angular application,
- // in html5mode and also without, so that we are able to abort navigation without
- // getting double entries in the location history.
- event.preventDefault();
- // update location manually
- if ($location.absUrl() != $browser.url()) {
- $rootScope.$apply();
- // hack to work around FF6 bug 684208 when scenario runner clicks on links
- $window.angular['ff-684208-preventDefault'] = true;
- }
- }
- }
- });
-
-
- // rewrite hashbang url <> html5 url
- if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
- $browser.url($location.absUrl(), true);
- }
-
- var initializing = true;
-
- // update $location when $browser url changes
- $browser.onUrlChange(function(newUrl, newState) {
-
- if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
- // If we are navigating outside of the app then force a reload
- $window.location.href = newUrl;
- return;
- }
-
- $rootScope.$evalAsync(function() {
- var oldUrl = $location.absUrl();
- var oldState = $location.$$state;
- var defaultPrevented;
- newUrl = trimEmptyHash(newUrl);
- $location.$$parse(newUrl);
- $location.$$state = newState;
-
- defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
- newState, oldState).defaultPrevented;
-
- // if the location was changed by a `$locationChangeStart` handler then stop
- // processing this location change
- if ($location.absUrl() !== newUrl) return;
-
- if (defaultPrevented) {
- $location.$$parse(oldUrl);
- $location.$$state = oldState;
- setBrowserUrlWithFallback(oldUrl, false, oldState);
- } else {
- initializing = false;
- afterLocationChange(oldUrl, oldState);
- }
- });
- if (!$rootScope.$$phase) $rootScope.$digest();
- });
-
- // update browser
- $rootScope.$watch(function $locationWatch() {
- var oldUrl = trimEmptyHash($browser.url());
- var newUrl = trimEmptyHash($location.absUrl());
- var oldState = $browser.state();
- var currentReplace = $location.$$replace;
- var urlOrStateChanged = oldUrl !== newUrl ||
- ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
-
- if (initializing || urlOrStateChanged) {
- initializing = false;
-
- $rootScope.$evalAsync(function() {
- var newUrl = $location.absUrl();
- var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
- $location.$$state, oldState).defaultPrevented;
-
- // if the location was changed by a `$locationChangeStart` handler then stop
- // processing this location change
- if ($location.absUrl() !== newUrl) return;
-
- if (defaultPrevented) {
- $location.$$parse(oldUrl);
- $location.$$state = oldState;
- } else {
- if (urlOrStateChanged) {
- setBrowserUrlWithFallback(newUrl, currentReplace,
- oldState === $location.$$state ? null : $location.$$state);
- }
- afterLocationChange(oldUrl, oldState);
- }
- });
- }
-
- $location.$$replace = false;
-
- // we don't need to return anything because $evalAsync will make the digest loop dirty when
- // there is a change
- });
-
- return $location;
-
- function afterLocationChange(oldUrl, oldState) {
- $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
- $location.$$state, oldState);
- }
-}];
-}
-
-/**
- * @ngdoc service
- * @name $log
- * @requires $window
- *
- * @description
- * Simple service for logging. Default implementation safely writes the message
- * into the browser's console (if present).
- *
- * The main purpose of this service is to simplify debugging and troubleshooting.
- *
- * The default is to log `debug` messages. You can use
- * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
- *
- * @example
- <example module="logExample">
- <file name="script.js">
- angular.module('logExample', [])
- .controller('LogController', ['$scope', '$log', function($scope, $log) {
- $scope.$log = $log;
- $scope.message = 'Hello World!';
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="LogController">
- <p>Reload this page with open console, enter text and hit the log button...</p>
- <label>Message:
- <input type="text" ng-model="message" /></label>
- <button ng-click="$log.log(message)">log</button>
- <button ng-click="$log.warn(message)">warn</button>
- <button ng-click="$log.info(message)">info</button>
- <button ng-click="$log.error(message)">error</button>
- <button ng-click="$log.debug(message)">debug</button>
- </div>
- </file>
- </example>
- */
-
-/**
- * @ngdoc provider
- * @name $logProvider
- * @description
- * Use the `$logProvider` to configure how the application logs messages
- */
-function $LogProvider() {
- var debug = true,
- self = this;
-
- /**
- * @ngdoc method
- * @name $logProvider#debugEnabled
- * @description
- * @param {boolean=} flag enable or disable debug level messages
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.debugEnabled = function(flag) {
- if (isDefined(flag)) {
- debug = flag;
- return this;
- } else {
- return debug;
- }
- };
-
- this.$get = ['$window', function($window) {
- return {
- /**
- * @ngdoc method
- * @name $log#log
- *
- * @description
- * Write a log message
- */
- log: consoleLog('log'),
-
- /**
- * @ngdoc method
- * @name $log#info
- *
- * @description
- * Write an information message
- */
- info: consoleLog('info'),
-
- /**
- * @ngdoc method
- * @name $log#warn
- *
- * @description
- * Write a warning message
- */
- warn: consoleLog('warn'),
-
- /**
- * @ngdoc method
- * @name $log#error
- *
- * @description
- * Write an error message
- */
- error: consoleLog('error'),
-
- /**
- * @ngdoc method
- * @name $log#debug
- *
- * @description
- * Write a debug message
- */
- debug: (function() {
- var fn = consoleLog('debug');
-
- return function() {
- if (debug) {
- fn.apply(self, arguments);
- }
- };
- }())
- };
-
- function formatError(arg) {
- if (arg instanceof Error) {
- if (arg.stack) {
- arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
- ? 'Error: ' + arg.message + '\n' + arg.stack
- : arg.stack;
- } else if (arg.sourceURL) {
- arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
- }
- }
- return arg;
- }
-
- function consoleLog(type) {
- var console = $window.console || {},
- logFn = console[type] || console.log || noop,
- hasApply = false;
-
- // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
- // The reason behind this is that console.log has type "object" in IE8...
- try {
- hasApply = !!logFn.apply;
- } catch (e) {}
-
- if (hasApply) {
- return function() {
- var args = [];
- forEach(arguments, function(arg) {
- args.push(formatError(arg));
- });
- return logFn.apply(console, args);
- };
- }
-
- // we are IE which either doesn't have window.console => this is noop and we do nothing,
- // or we are IE where console.log doesn't have apply so we log at least first 2 args
- return function(arg1, arg2) {
- logFn(arg1, arg2 == null ? '' : arg2);
- };
- }
- }];
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-var $parseMinErr = minErr('$parse');
-
-// Sandboxing Angular Expressions
-// ------------------------------
-// Angular expressions are generally considered safe because these expressions only have direct
-// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
-// obtaining a reference to native JS functions such as the Function constructor.
-//
-// As an example, consider the following Angular expression:
-//
-// {}.toString.constructor('alert("evil JS code")')
-//
-// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
-// against the expression language, but not to prevent exploits that were enabled by exposing
-// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
-// practice and therefore we are not even trying to protect against interaction with an object
-// explicitly exposed in this way.
-//
-// In general, it is not possible to access a Window object from an angular expression unless a
-// window or some DOM object that has a reference to window is published onto a Scope.
-// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
-// native objects.
-//
-// See https://docs.angularjs.org/guide/security
-
-
-function ensureSafeMemberName(name, fullExpression) {
- if (name === "__defineGetter__" || name === "__defineSetter__"
- || name === "__lookupGetter__" || name === "__lookupSetter__"
- || name === "__proto__") {
- throw $parseMinErr('isecfld',
- 'Attempting to access a disallowed field in Angular expressions! '
- + 'Expression: {0}', fullExpression);
- }
- return name;
-}
-
-function getStringValue(name) {
- // Property names must be strings. This means that non-string objects cannot be used
- // as keys in an object. Any non-string object, including a number, is typecasted
- // into a string via the toString method.
- // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names
- //
- // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it
- // to a string. It's not always possible. If `name` is an object and its `toString` method is
- // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown:
- //
- // TypeError: Cannot convert object to primitive value
- //
- // For performance reasons, we don't catch this error here and allow it to propagate up the call
- // stack. Note that you'll get the same error in JavaScript if you try to access a property using
- // such a 'broken' object as a key.
- return name + '';
-}
-
-function ensureSafeObject(obj, fullExpression) {
- // nifty check if obj is Function that is fast and works across iframes and other contexts
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// isWindow(obj)
- obj.window === obj) {
- throw $parseMinErr('isecwindow',
- 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// isElement(obj)
- obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
- throw $parseMinErr('isecdom',
- 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// block Object so that we can't get hold of dangerous Object.* methods
- obj === Object) {
- throw $parseMinErr('isecobj',
- 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
- return obj;
-}
-
-var CALL = Function.prototype.call;
-var APPLY = Function.prototype.apply;
-var BIND = Function.prototype.bind;
-
-function ensureSafeFunction(obj, fullExpression) {
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (obj === CALL || obj === APPLY || obj === BIND) {
- throw $parseMinErr('isecff',
- 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
-}
-
-function ensureSafeAssignContext(obj, fullExpression) {
- if (obj) {
- if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||
- obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {
- throw $parseMinErr('isecaf',
- 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);
- }
- }
-}
-
-var OPERATORS = createMap();
-forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
-var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
-
-
-/////////////////////////////////////////
-
-
-/**
- * @constructor
- */
-var Lexer = function(options) {
- this.options = options;
-};
-
-Lexer.prototype = {
- constructor: Lexer,
-
- lex: function(text) {
- this.text = text;
- this.index = 0;
- this.tokens = [];
-
- while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- if (ch === '"' || ch === "'") {
- this.readString(ch);
- } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
- this.readNumber();
- } else if (this.isIdent(ch)) {
- this.readIdent();
- } else if (this.is(ch, '(){}[].,;:?')) {
- this.tokens.push({index: this.index, text: ch});
- this.index++;
- } else if (this.isWhitespace(ch)) {
- this.index++;
- } else {
- var ch2 = ch + this.peek();
- var ch3 = ch2 + this.peek(2);
- var op1 = OPERATORS[ch];
- var op2 = OPERATORS[ch2];
- var op3 = OPERATORS[ch3];
- if (op1 || op2 || op3) {
- var token = op3 ? ch3 : (op2 ? ch2 : ch);
- this.tokens.push({index: this.index, text: token, operator: true});
- this.index += token.length;
- } else {
- this.throwError('Unexpected next character ', this.index, this.index + 1);
- }
- }
- }
- return this.tokens;
- },
-
- is: function(ch, chars) {
- return chars.indexOf(ch) !== -1;
- },
-
- peek: function(i) {
- var num = i || 1;
- return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
- },
-
- isNumber: function(ch) {
- return ('0' <= ch && ch <= '9') && typeof ch === "string";
- },
-
- isWhitespace: function(ch) {
- // IE treats non-breaking space as \u00A0
- return (ch === ' ' || ch === '\r' || ch === '\t' ||
- ch === '\n' || ch === '\v' || ch === '\u00A0');
- },
-
- isIdent: function(ch) {
- return ('a' <= ch && ch <= 'z' ||
- 'A' <= ch && ch <= 'Z' ||
- '_' === ch || ch === '$');
- },
-
- isExpOperator: function(ch) {
- return (ch === '-' || ch === '+' || this.isNumber(ch));
- },
-
- throwError: function(error, start, end) {
- end = end || this.index;
- var colStr = (isDefined(start)
- ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
- : ' ' + end);
- throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
- error, colStr, this.text);
- },
-
- readNumber: function() {
- var number = '';
- var start = this.index;
- while (this.index < this.text.length) {
- var ch = lowercase(this.text.charAt(this.index));
- if (ch == '.' || this.isNumber(ch)) {
- number += ch;
- } else {
- var peekCh = this.peek();
- if (ch == 'e' && this.isExpOperator(peekCh)) {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- peekCh && this.isNumber(peekCh) &&
- number.charAt(number.length - 1) == 'e') {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- (!peekCh || !this.isNumber(peekCh)) &&
- number.charAt(number.length - 1) == 'e') {
- this.throwError('Invalid exponent');
- } else {
- break;
- }
- }
- this.index++;
- }
- this.tokens.push({
- index: start,
- text: number,
- constant: true,
- value: Number(number)
- });
- },
-
- readIdent: function() {
- var start = this.index;
- while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- if (!(this.isIdent(ch) || this.isNumber(ch))) {
- break;
- }
- this.index++;
- }
- this.tokens.push({
- index: start,
- text: this.text.slice(start, this.index),
- identifier: true
- });
- },
-
- readString: function(quote) {
- var start = this.index;
- this.index++;
- var string = '';
- var rawString = quote;
- var escape = false;
- while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- rawString += ch;
- if (escape) {
- if (ch === 'u') {
- var hex = this.text.substring(this.index + 1, this.index + 5);
- if (!hex.match(/[\da-f]{4}/i)) {
- this.throwError('Invalid unicode escape [\\u' + hex + ']');
- }
- this.index += 4;
- string += String.fromCharCode(parseInt(hex, 16));
- } else {
- var rep = ESCAPE[ch];
- string = string + (rep || ch);
- }
- escape = false;
- } else if (ch === '\\') {
- escape = true;
- } else if (ch === quote) {
- this.index++;
- this.tokens.push({
- index: start,
- text: rawString,
- constant: true,
- value: string
- });
- return;
- } else {
- string += ch;
- }
- this.index++;
- }
- this.throwError('Unterminated quote', start);
- }
-};
-
-var AST = function(lexer, options) {
- this.lexer = lexer;
- this.options = options;
-};
-
-AST.Program = 'Program';
-AST.ExpressionStatement = 'ExpressionStatement';
-AST.AssignmentExpression = 'AssignmentExpression';
-AST.ConditionalExpression = 'ConditionalExpression';
-AST.LogicalExpression = 'LogicalExpression';
-AST.BinaryExpression = 'BinaryExpression';
-AST.UnaryExpression = 'UnaryExpression';
-AST.CallExpression = 'CallExpression';
-AST.MemberExpression = 'MemberExpression';
-AST.Identifier = 'Identifier';
-AST.Literal = 'Literal';
-AST.ArrayExpression = 'ArrayExpression';
-AST.Property = 'Property';
-AST.ObjectExpression = 'ObjectExpression';
-AST.ThisExpression = 'ThisExpression';
-AST.LocalsExpression = 'LocalsExpression';
-
-// Internal use only
-AST.NGValueParameter = 'NGValueParameter';
-
-AST.prototype = {
- ast: function(text) {
- this.text = text;
- this.tokens = this.lexer.lex(text);
-
- var value = this.program();
-
- if (this.tokens.length !== 0) {
- this.throwError('is an unexpected token', this.tokens[0]);
- }
-
- return value;
- },
-
- program: function() {
- var body = [];
- while (true) {
- if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
- body.push(this.expressionStatement());
- if (!this.expect(';')) {
- return { type: AST.Program, body: body};
- }
- }
- },
-
- expressionStatement: function() {
- return { type: AST.ExpressionStatement, expression: this.filterChain() };
- },
-
- filterChain: function() {
- var left = this.expression();
- var token;
- while ((token = this.expect('|'))) {
- left = this.filter(left);
- }
- return left;
- },
-
- expression: function() {
- return this.assignment();
- },
-
- assignment: function() {
- var result = this.ternary();
- if (this.expect('=')) {
- result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
- }
- return result;
- },
-
- ternary: function() {
- var test = this.logicalOR();
- var alternate;
- var consequent;
- if (this.expect('?')) {
- alternate = this.expression();
- if (this.consume(':')) {
- consequent = this.expression();
- return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};
- }
- }
- return test;
- },
-
- logicalOR: function() {
- var left = this.logicalAND();
- while (this.expect('||')) {
- left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };
- }
- return left;
- },
-
- logicalAND: function() {
- var left = this.equality();
- while (this.expect('&&')) {
- left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};
- }
- return left;
- },
-
- equality: function() {
- var left = this.relational();
- var token;
- while ((token = this.expect('==','!=','===','!=='))) {
- left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };
- }
- return left;
- },
-
- relational: function() {
- var left = this.additive();
- var token;
- while ((token = this.expect('<', '>', '<=', '>='))) {
- left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };
- }
- return left;
- },
-
- additive: function() {
- var left = this.multiplicative();
- var token;
- while ((token = this.expect('+','-'))) {
- left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };
- }
- return left;
- },
-
- multiplicative: function() {
- var left = this.unary();
- var token;
- while ((token = this.expect('*','/','%'))) {
- left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };
- }
- return left;
- },
-
- unary: function() {
- var token;
- if ((token = this.expect('+', '-', '!'))) {
- return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };
- } else {
- return this.primary();
- }
- },
-
- primary: function() {
- var primary;
- if (this.expect('(')) {
- primary = this.filterChain();
- this.consume(')');
- } else if (this.expect('[')) {
- primary = this.arrayDeclaration();
- } else if (this.expect('{')) {
- primary = this.object();
- } else if (this.constants.hasOwnProperty(this.peek().text)) {
- primary = copy(this.constants[this.consume().text]);
- } else if (this.peek().identifier) {
- primary = this.identifier();
- } else if (this.peek().constant) {
- primary = this.constant();
- } else {
- this.throwError('not a primary expression', this.peek());
- }
-
- var next;
- while ((next = this.expect('(', '[', '.'))) {
- if (next.text === '(') {
- primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };
- this.consume(')');
- } else if (next.text === '[') {
- primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };
- this.consume(']');
- } else if (next.text === '.') {
- primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };
- } else {
- this.throwError('IMPOSSIBLE');
- }
- }
- return primary;
- },
-
- filter: function(baseExpression) {
- var args = [baseExpression];
- var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};
-
- while (this.expect(':')) {
- args.push(this.expression());
- }
-
- return result;
- },
-
- parseArguments: function() {
- var args = [];
- if (this.peekToken().text !== ')') {
- do {
- args.push(this.expression());
- } while (this.expect(','));
- }
- return args;
- },
-
- identifier: function() {
- var token = this.consume();
- if (!token.identifier) {
- this.throwError('is not a valid identifier', token);
- }
- return { type: AST.Identifier, name: token.text };
- },
-
- constant: function() {
- // TODO check that it is a constant
- return { type: AST.Literal, value: this.consume().value };
- },
-
- arrayDeclaration: function() {
- var elements = [];
- if (this.peekToken().text !== ']') {
- do {
- if (this.peek(']')) {
- // Support trailing commas per ES5.1.
- break;
- }
- elements.push(this.expression());
- } while (this.expect(','));
- }
- this.consume(']');
-
- return { type: AST.ArrayExpression, elements: elements };
- },
-
- object: function() {
- var properties = [], property;
- if (this.peekToken().text !== '}') {
- do {
- if (this.peek('}')) {
- // Support trailing commas per ES5.1.
- break;
- }
- property = {type: AST.Property, kind: 'init'};
- if (this.peek().constant) {
- property.key = this.constant();
- } else if (this.peek().identifier) {
- property.key = this.identifier();
- } else {
- this.throwError("invalid key", this.peek());
- }
- this.consume(':');
- property.value = this.expression();
- properties.push(property);
- } while (this.expect(','));
- }
- this.consume('}');
-
- return {type: AST.ObjectExpression, properties: properties };
- },
-
- throwError: function(msg, token) {
- throw $parseMinErr('syntax',
- 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
- token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
- },
-
- consume: function(e1) {
- if (this.tokens.length === 0) {
- throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
- }
-
- var token = this.expect(e1);
- if (!token) {
- this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
- }
- return token;
- },
-
- peekToken: function() {
- if (this.tokens.length === 0) {
- throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
- }
- return this.tokens[0];
- },
-
- peek: function(e1, e2, e3, e4) {
- return this.peekAhead(0, e1, e2, e3, e4);
- },
-
- peekAhead: function(i, e1, e2, e3, e4) {
- if (this.tokens.length > i) {
- var token = this.tokens[i];
- var t = token.text;
- if (t === e1 || t === e2 || t === e3 || t === e4 ||
- (!e1 && !e2 && !e3 && !e4)) {
- return token;
- }
- }
- return false;
- },
-
- expect: function(e1, e2, e3, e4) {
- var token = this.peek(e1, e2, e3, e4);
- if (token) {
- this.tokens.shift();
- return token;
- }
- return false;
- },
-
-
- /* `undefined` is not a constant, it is an identifier,
- * but using it as an identifier is not supported
- */
- constants: {
- 'true': { type: AST.Literal, value: true },
- 'false': { type: AST.Literal, value: false },
- 'null': { type: AST.Literal, value: null },
- 'undefined': {type: AST.Literal, value: undefined },
- 'this': {type: AST.ThisExpression },
- '$locals': {type: AST.LocalsExpression }
- }
-};
-
-function ifDefined(v, d) {
- return typeof v !== 'undefined' ? v : d;
-}
-
-function plusFn(l, r) {
- if (typeof l === 'undefined') return r;
- if (typeof r === 'undefined') return l;
- return l + r;
-}
-
-function isStateless($filter, filterName) {
- var fn = $filter(filterName);
- return !fn.$stateful;
-}
-
-function findConstantAndWatchExpressions(ast, $filter) {
- var allConstants;
- var argsToWatch;
- switch (ast.type) {
- case AST.Program:
- allConstants = true;
- forEach(ast.body, function(expr) {
- findConstantAndWatchExpressions(expr.expression, $filter);
- allConstants = allConstants && expr.expression.constant;
- });
- ast.constant = allConstants;
- break;
- case AST.Literal:
- ast.constant = true;
- ast.toWatch = [];
- break;
- case AST.UnaryExpression:
- findConstantAndWatchExpressions(ast.argument, $filter);
- ast.constant = ast.argument.constant;
- ast.toWatch = ast.argument.toWatch;
- break;
- case AST.BinaryExpression:
- findConstantAndWatchExpressions(ast.left, $filter);
- findConstantAndWatchExpressions(ast.right, $filter);
- ast.constant = ast.left.constant && ast.right.constant;
- ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
- break;
- case AST.LogicalExpression:
- findConstantAndWatchExpressions(ast.left, $filter);
- findConstantAndWatchExpressions(ast.right, $filter);
- ast.constant = ast.left.constant && ast.right.constant;
- ast.toWatch = ast.constant ? [] : [ast];
- break;
- case AST.ConditionalExpression:
- findConstantAndWatchExpressions(ast.test, $filter);
- findConstantAndWatchExpressions(ast.alternate, $filter);
- findConstantAndWatchExpressions(ast.consequent, $filter);
- ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;
- ast.toWatch = ast.constant ? [] : [ast];
- break;
- case AST.Identifier:
- ast.constant = false;
- ast.toWatch = [ast];
- break;
- case AST.MemberExpression:
- findConstantAndWatchExpressions(ast.object, $filter);
- if (ast.computed) {
- findConstantAndWatchExpressions(ast.property, $filter);
- }
- ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);
- ast.toWatch = [ast];
- break;
- case AST.CallExpression:
- allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
- argsToWatch = [];
- forEach(ast.arguments, function(expr) {
- findConstantAndWatchExpressions(expr, $filter);
- allConstants = allConstants && expr.constant;
- if (!expr.constant) {
- argsToWatch.push.apply(argsToWatch, expr.toWatch);
- }
- });
- ast.constant = allConstants;
- ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
- break;
- case AST.AssignmentExpression:
- findConstantAndWatchExpressions(ast.left, $filter);
- findConstantAndWatchExpressions(ast.right, $filter);
- ast.constant = ast.left.constant && ast.right.constant;
- ast.toWatch = [ast];
- break;
- case AST.ArrayExpression:
- allConstants = true;
- argsToWatch = [];
- forEach(ast.elements, function(expr) {
- findConstantAndWatchExpressions(expr, $filter);
- allConstants = allConstants && expr.constant;
- if (!expr.constant) {
- argsToWatch.push.apply(argsToWatch, expr.toWatch);
- }
- });
- ast.constant = allConstants;
- ast.toWatch = argsToWatch;
- break;
- case AST.ObjectExpression:
- allConstants = true;
- argsToWatch = [];
- forEach(ast.properties, function(property) {
- findConstantAndWatchExpressions(property.value, $filter);
- allConstants = allConstants && property.value.constant;
- if (!property.value.constant) {
- argsToWatch.push.apply(argsToWatch, property.value.toWatch);
- }
- });
- ast.constant = allConstants;
- ast.toWatch = argsToWatch;
- break;
- case AST.ThisExpression:
- ast.constant = false;
- ast.toWatch = [];
- break;
- case AST.LocalsExpression:
- ast.constant = false;
- ast.toWatch = [];
- break;
- }
-}
-
-function getInputs(body) {
- if (body.length != 1) return;
- var lastExpression = body[0].expression;
- var candidate = lastExpression.toWatch;
- if (candidate.length !== 1) return candidate;
- return candidate[0] !== lastExpression ? candidate : undefined;
-}
-
-function isAssignable(ast) {
- return ast.type === AST.Identifier || ast.type === AST.MemberExpression;
-}
-
-function assignableAST(ast) {
- if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
- return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};
- }
-}
-
-function isLiteral(ast) {
- return ast.body.length === 0 ||
- ast.body.length === 1 && (
- ast.body[0].expression.type === AST.Literal ||
- ast.body[0].expression.type === AST.ArrayExpression ||
- ast.body[0].expression.type === AST.ObjectExpression);
-}
-
-function isConstant(ast) {
- return ast.constant;
-}
-
-function ASTCompiler(astBuilder, $filter) {
- this.astBuilder = astBuilder;
- this.$filter = $filter;
-}
-
-ASTCompiler.prototype = {
- compile: function(expression, expensiveChecks) {
- var self = this;
- var ast = this.astBuilder.ast(expression);
- this.state = {
- nextId: 0,
- filters: {},
- expensiveChecks: expensiveChecks,
- fn: {vars: [], body: [], own: {}},
- assign: {vars: [], body: [], own: {}},
- inputs: []
- };
- findConstantAndWatchExpressions(ast, self.$filter);
- var extra = '';
- var assignable;
- this.stage = 'assign';
- if ((assignable = assignableAST(ast))) {
- this.state.computing = 'assign';
- var result = this.nextId();
- this.recurse(assignable, result);
- this.return_(result);
- extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
- }
- var toWatch = getInputs(ast.body);
- self.stage = 'inputs';
- forEach(toWatch, function(watch, key) {
- var fnKey = 'fn' + key;
- self.state[fnKey] = {vars: [], body: [], own: {}};
- self.state.computing = fnKey;
- var intoId = self.nextId();
- self.recurse(watch, intoId);
- self.return_(intoId);
- self.state.inputs.push(fnKey);
- watch.watchId = key;
- });
- this.state.computing = 'fn';
- this.stage = 'main';
- this.recurse(ast);
- var fnString =
- // The build and minification steps remove the string "use strict" from the code, but this is done using a regex.
- // This is a workaround for this until we do a better job at only removing the prefix only when we should.
- '"' + this.USE + ' ' + this.STRICT + '";\n' +
- this.filterPrefix() +
- 'var fn=' + this.generateFunction('fn', 's,l,a,i') +
- extra +
- this.watchFns() +
- 'return fn;';
-
- /* jshint -W054 */
- var fn = (new Function('$filter',
- 'ensureSafeMemberName',
- 'ensureSafeObject',
- 'ensureSafeFunction',
- 'getStringValue',
- 'ensureSafeAssignContext',
- 'ifDefined',
- 'plus',
- 'text',
- fnString))(
- this.$filter,
- ensureSafeMemberName,
- ensureSafeObject,
- ensureSafeFunction,
- getStringValue,
- ensureSafeAssignContext,
- ifDefined,
- plusFn,
- expression);
- /* jshint +W054 */
- this.state = this.stage = undefined;
- fn.literal = isLiteral(ast);
- fn.constant = isConstant(ast);
- return fn;
- },
-
- USE: 'use',
-
- STRICT: 'strict',
-
- watchFns: function() {
- var result = [];
- var fns = this.state.inputs;
- var self = this;
- forEach(fns, function(name) {
- result.push('var ' + name + '=' + self.generateFunction(name, 's'));
- });
- if (fns.length) {
- result.push('fn.inputs=[' + fns.join(',') + '];');
- }
- return result.join('');
- },
-
- generateFunction: function(name, params) {
- return 'function(' + params + '){' +
- this.varsPrefix(name) +
- this.body(name) +
- '};';
- },
-
- filterPrefix: function() {
- var parts = [];
- var self = this;
- forEach(this.state.filters, function(id, filter) {
- parts.push(id + '=$filter(' + self.escape(filter) + ')');
- });
- if (parts.length) return 'var ' + parts.join(',') + ';';
- return '';
- },
-
- varsPrefix: function(section) {
- return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';
- },
-
- body: function(section) {
- return this.state[section].body.join('');
- },
-
- recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
- var left, right, self = this, args, expression;
- recursionFn = recursionFn || noop;
- if (!skipWatchIdCheck && isDefined(ast.watchId)) {
- intoId = intoId || this.nextId();
- this.if_('i',
- this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),
- this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)
- );
- return;
- }
- switch (ast.type) {
- case AST.Program:
- forEach(ast.body, function(expression, pos) {
- self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });
- if (pos !== ast.body.length - 1) {
- self.current().body.push(right, ';');
- } else {
- self.return_(right);
- }
- });
- break;
- case AST.Literal:
- expression = this.escape(ast.value);
- this.assign(intoId, expression);
- recursionFn(expression);
- break;
- case AST.UnaryExpression:
- this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });
- expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';
- this.assign(intoId, expression);
- recursionFn(expression);
- break;
- case AST.BinaryExpression:
- this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });
- this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });
- if (ast.operator === '+') {
- expression = this.plus(left, right);
- } else if (ast.operator === '-') {
- expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);
- } else {
- expression = '(' + left + ')' + ast.operator + '(' + right + ')';
- }
- this.assign(intoId, expression);
- recursionFn(expression);
- break;
- case AST.LogicalExpression:
- intoId = intoId || this.nextId();
- self.recurse(ast.left, intoId);
- self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));
- recursionFn(intoId);
- break;
- case AST.ConditionalExpression:
- intoId = intoId || this.nextId();
- self.recurse(ast.test, intoId);
- self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));
- recursionFn(intoId);
- break;
- case AST.Identifier:
- intoId = intoId || this.nextId();
- if (nameId) {
- nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');
- nameId.computed = false;
- nameId.name = ast.name;
- }
- ensureSafeMemberName(ast.name);
- self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),
- function() {
- self.if_(self.stage === 'inputs' || 's', function() {
- if (create && create !== 1) {
- self.if_(
- self.not(self.nonComputedMember('s', ast.name)),
- self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));
- }
- self.assign(intoId, self.nonComputedMember('s', ast.name));
- });
- }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))
- );
- if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) {
- self.addEnsureSafeObject(intoId);
- }
- recursionFn(intoId);
- break;
- case AST.MemberExpression:
- left = nameId && (nameId.context = this.nextId()) || this.nextId();
- intoId = intoId || this.nextId();
- self.recurse(ast.object, left, undefined, function() {
- self.if_(self.notNull(left), function() {
- if (create && create !== 1) {
- self.addEnsureSafeAssignContext(left);
- }
- if (ast.computed) {
- right = self.nextId();
- self.recurse(ast.property, right);
- self.getStringValue(right);
- self.addEnsureSafeMemberName(right);
- if (create && create !== 1) {
- self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
- }
- expression = self.ensureSafeObject(self.computedMember(left, right));
- self.assign(intoId, expression);
- if (nameId) {
- nameId.computed = true;
- nameId.name = right;
- }
- } else {
- ensureSafeMemberName(ast.property.name);
- if (create && create !== 1) {
- self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
- }
- expression = self.nonComputedMember(left, ast.property.name);
- if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) {
- expression = self.ensureSafeObject(expression);
- }
- self.assign(intoId, expression);
- if (nameId) {
- nameId.computed = false;
- nameId.name = ast.property.name;
- }
- }
- }, function() {
- self.assign(intoId, 'undefined');
- });
- recursionFn(intoId);
- }, !!create);
- break;
- case AST.CallExpression:
- intoId = intoId || this.nextId();
- if (ast.filter) {
- right = self.filter(ast.callee.name);
- args = [];
- forEach(ast.arguments, function(expr) {
- var argument = self.nextId();
- self.recurse(expr, argument);
- args.push(argument);
- });
- expression = right + '(' + args.join(',') + ')';
- self.assign(intoId, expression);
- recursionFn(intoId);
- } else {
- right = self.nextId();
- left = {};
- args = [];
- self.recurse(ast.callee, right, left, function() {
- self.if_(self.notNull(right), function() {
- self.addEnsureSafeFunction(right);
- forEach(ast.arguments, function(expr) {
- self.recurse(expr, self.nextId(), undefined, function(argument) {
- args.push(self.ensureSafeObject(argument));
- });
- });
- if (left.name) {
- if (!self.state.expensiveChecks) {
- self.addEnsureSafeObject(left.context);
- }
- expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';
- } else {
- expression = right + '(' + args.join(',') + ')';
- }
- expression = self.ensureSafeObject(expression);
- self.assign(intoId, expression);
- }, function() {
- self.assign(intoId, 'undefined');
- });
- recursionFn(intoId);
- });
- }
- break;
- case AST.AssignmentExpression:
- right = this.nextId();
- left = {};
- if (!isAssignable(ast.left)) {
- throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');
- }
- this.recurse(ast.left, undefined, left, function() {
- self.if_(self.notNull(left.context), function() {
- self.recurse(ast.right, right);
- self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
- self.addEnsureSafeAssignContext(left.context);
- expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
- self.assign(intoId, expression);
- recursionFn(intoId || expression);
- });
- }, 1);
- break;
- case AST.ArrayExpression:
- args = [];
- forEach(ast.elements, function(expr) {
- self.recurse(expr, self.nextId(), undefined, function(argument) {
- args.push(argument);
- });
- });
- expression = '[' + args.join(',') + ']';
- this.assign(intoId, expression);
- recursionFn(expression);
- break;
- case AST.ObjectExpression:
- args = [];
- forEach(ast.properties, function(property) {
- self.recurse(property.value, self.nextId(), undefined, function(expr) {
- args.push(self.escape(
- property.key.type === AST.Identifier ? property.key.name :
- ('' + property.key.value)) +
- ':' + expr);
- });
- });
- expression = '{' + args.join(',') + '}';
- this.assign(intoId, expression);
- recursionFn(expression);
- break;
- case AST.ThisExpression:
- this.assign(intoId, 's');
- recursionFn('s');
- break;
- case AST.LocalsExpression:
- this.assign(intoId, 'l');
- recursionFn('l');
- break;
- case AST.NGValueParameter:
- this.assign(intoId, 'v');
- recursionFn('v');
- break;
- }
- },
-
- getHasOwnProperty: function(element, property) {
- var key = element + '.' + property;
- var own = this.current().own;
- if (!own.hasOwnProperty(key)) {
- own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');
- }
- return own[key];
- },
-
- assign: function(id, value) {
- if (!id) return;
- this.current().body.push(id, '=', value, ';');
- return id;
- },
-
- filter: function(filterName) {
- if (!this.state.filters.hasOwnProperty(filterName)) {
- this.state.filters[filterName] = this.nextId(true);
- }
- return this.state.filters[filterName];
- },
-
- ifDefined: function(id, defaultValue) {
- return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';
- },
-
- plus: function(left, right) {
- return 'plus(' + left + ',' + right + ')';
- },
-
- return_: function(id) {
- this.current().body.push('return ', id, ';');
- },
-
- if_: function(test, alternate, consequent) {
- if (test === true) {
- alternate();
- } else {
- var body = this.current().body;
- body.push('if(', test, '){');
- alternate();
- body.push('}');
- if (consequent) {
- body.push('else{');
- consequent();
- body.push('}');
- }
- }
- },
-
- not: function(expression) {
- return '!(' + expression + ')';
- },
-
- notNull: function(expression) {
- return expression + '!=null';
- },
-
- nonComputedMember: function(left, right) {
- return left + '.' + right;
- },
-
- computedMember: function(left, right) {
- return left + '[' + right + ']';
- },
-
- member: function(left, right, computed) {
- if (computed) return this.computedMember(left, right);
- return this.nonComputedMember(left, right);
- },
-
- addEnsureSafeObject: function(item) {
- this.current().body.push(this.ensureSafeObject(item), ';');
- },
-
- addEnsureSafeMemberName: function(item) {
- this.current().body.push(this.ensureSafeMemberName(item), ';');
- },
-
- addEnsureSafeFunction: function(item) {
- this.current().body.push(this.ensureSafeFunction(item), ';');
- },
-
- addEnsureSafeAssignContext: function(item) {
- this.current().body.push(this.ensureSafeAssignContext(item), ';');
- },
-
- ensureSafeObject: function(item) {
- return 'ensureSafeObject(' + item + ',text)';
- },
-
- ensureSafeMemberName: function(item) {
- return 'ensureSafeMemberName(' + item + ',text)';
- },
-
- ensureSafeFunction: function(item) {
- return 'ensureSafeFunction(' + item + ',text)';
- },
-
- getStringValue: function(item) {
- this.assign(item, 'getStringValue(' + item + ')');
- },
-
- ensureSafeAssignContext: function(item) {
- return 'ensureSafeAssignContext(' + item + ',text)';
- },
-
- lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
- var self = this;
- return function() {
- self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);
- };
- },
-
- lazyAssign: function(id, value) {
- var self = this;
- return function() {
- self.assign(id, value);
- };
- },
-
- stringEscapeRegex: /[^ a-zA-Z0-9]/g,
-
- stringEscapeFn: function(c) {
- return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);
- },
-
- escape: function(value) {
- if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'";
- if (isNumber(value)) return value.toString();
- if (value === true) return 'true';
- if (value === false) return 'false';
- if (value === null) return 'null';
- if (typeof value === 'undefined') return 'undefined';
-
- throw $parseMinErr('esc', 'IMPOSSIBLE');
- },
-
- nextId: function(skip, init) {
- var id = 'v' + (this.state.nextId++);
- if (!skip) {
- this.current().vars.push(id + (init ? '=' + init : ''));
- }
- return id;
- },
-
- current: function() {
- return this.state[this.state.computing];
- }
-};
-
-
-function ASTInterpreter(astBuilder, $filter) {
- this.astBuilder = astBuilder;
- this.$filter = $filter;
-}
-
-ASTInterpreter.prototype = {
- compile: function(expression, expensiveChecks) {
- var self = this;
- var ast = this.astBuilder.ast(expression);
- this.expression = expression;
- this.expensiveChecks = expensiveChecks;
- findConstantAndWatchExpressions(ast, self.$filter);
- var assignable;
- var assign;
- if ((assignable = assignableAST(ast))) {
- assign = this.recurse(assignable);
- }
- var toWatch = getInputs(ast.body);
- var inputs;
- if (toWatch) {
- inputs = [];
- forEach(toWatch, function(watch, key) {
- var input = self.recurse(watch);
- watch.input = input;
- inputs.push(input);
- watch.watchId = key;
- });
- }
- var expressions = [];
- forEach(ast.body, function(expression) {
- expressions.push(self.recurse(expression.expression));
- });
- var fn = ast.body.length === 0 ? function() {} :
- ast.body.length === 1 ? expressions[0] :
- function(scope, locals) {
- var lastValue;
- forEach(expressions, function(exp) {
- lastValue = exp(scope, locals);
- });
- return lastValue;
- };
- if (assign) {
- fn.assign = function(scope, value, locals) {
- return assign(scope, locals, value);
- };
- }
- if (inputs) {
- fn.inputs = inputs;
- }
- fn.literal = isLiteral(ast);
- fn.constant = isConstant(ast);
- return fn;
- },
-
- recurse: function(ast, context, create) {
- var left, right, self = this, args, expression;
- if (ast.input) {
- return this.inputs(ast.input, ast.watchId);
- }
- switch (ast.type) {
- case AST.Literal:
- return this.value(ast.value, context);
- case AST.UnaryExpression:
- right = this.recurse(ast.argument);
- return this['unary' + ast.operator](right, context);
- case AST.BinaryExpression:
- left = this.recurse(ast.left);
- right = this.recurse(ast.right);
- return this['binary' + ast.operator](left, right, context);
- case AST.LogicalExpression:
- left = this.recurse(ast.left);
- right = this.recurse(ast.right);
- return this['binary' + ast.operator](left, right, context);
- case AST.ConditionalExpression:
- return this['ternary?:'](
- this.recurse(ast.test),
- this.recurse(ast.alternate),
- this.recurse(ast.consequent),
- context
- );
- case AST.Identifier:
- ensureSafeMemberName(ast.name, self.expression);
- return self.identifier(ast.name,
- self.expensiveChecks || isPossiblyDangerousMemberName(ast.name),
- context, create, self.expression);
- case AST.MemberExpression:
- left = this.recurse(ast.object, false, !!create);
- if (!ast.computed) {
- ensureSafeMemberName(ast.property.name, self.expression);
- right = ast.property.name;
- }
- if (ast.computed) right = this.recurse(ast.property);
- return ast.computed ?
- this.computedMember(left, right, context, create, self.expression) :
- this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression);
- case AST.CallExpression:
- args = [];
- forEach(ast.arguments, function(expr) {
- args.push(self.recurse(expr));
- });
- if (ast.filter) right = this.$filter(ast.callee.name);
- if (!ast.filter) right = this.recurse(ast.callee, true);
- return ast.filter ?
- function(scope, locals, assign, inputs) {
- var values = [];
- for (var i = 0; i < args.length; ++i) {
- values.push(args[i](scope, locals, assign, inputs));
- }
- var value = right.apply(undefined, values, inputs);
- return context ? {context: undefined, name: undefined, value: value} : value;
- } :
- function(scope, locals, assign, inputs) {
- var rhs = right(scope, locals, assign, inputs);
- var value;
- if (rhs.value != null) {
- ensureSafeObject(rhs.context, self.expression);
- ensureSafeFunction(rhs.value, self.expression);
- var values = [];
- for (var i = 0; i < args.length; ++i) {
- values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression));
- }
- value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression);
- }
- return context ? {value: value} : value;
- };
- case AST.AssignmentExpression:
- left = this.recurse(ast.left, true, 1);
- right = this.recurse(ast.right);
- return function(scope, locals, assign, inputs) {
- var lhs = left(scope, locals, assign, inputs);
- var rhs = right(scope, locals, assign, inputs);
- ensureSafeObject(lhs.value, self.expression);
- ensureSafeAssignContext(lhs.context);
- lhs.context[lhs.name] = rhs;
- return context ? {value: rhs} : rhs;
- };
- case AST.ArrayExpression:
- args = [];
- forEach(ast.elements, function(expr) {
- args.push(self.recurse(expr));
- });
- return function(scope, locals, assign, inputs) {
- var value = [];
- for (var i = 0; i < args.length; ++i) {
- value.push(args[i](scope, locals, assign, inputs));
- }
- return context ? {value: value} : value;
- };
- case AST.ObjectExpression:
- args = [];
- forEach(ast.properties, function(property) {
- args.push({key: property.key.type === AST.Identifier ?
- property.key.name :
- ('' + property.key.value),
- value: self.recurse(property.value)
- });
- });
- return function(scope, locals, assign, inputs) {
- var value = {};
- for (var i = 0; i < args.length; ++i) {
- value[args[i].key] = args[i].value(scope, locals, assign, inputs);
- }
- return context ? {value: value} : value;
- };
- case AST.ThisExpression:
- return function(scope) {
- return context ? {value: scope} : scope;
- };
- case AST.LocalsExpression:
- return function(scope, locals) {
- return context ? {value: locals} : locals;
- };
- case AST.NGValueParameter:
- return function(scope, locals, assign, inputs) {
- return context ? {value: assign} : assign;
- };
- }
- },
-
- 'unary+': function(argument, context) {
- return function(scope, locals, assign, inputs) {
- var arg = argument(scope, locals, assign, inputs);
- if (isDefined(arg)) {
- arg = +arg;
- } else {
- arg = 0;
- }
- return context ? {value: arg} : arg;
- };
- },
- 'unary-': function(argument, context) {
- return function(scope, locals, assign, inputs) {
- var arg = argument(scope, locals, assign, inputs);
- if (isDefined(arg)) {
- arg = -arg;
- } else {
- arg = 0;
- }
- return context ? {value: arg} : arg;
- };
- },
- 'unary!': function(argument, context) {
- return function(scope, locals, assign, inputs) {
- var arg = !argument(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary+': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var lhs = left(scope, locals, assign, inputs);
- var rhs = right(scope, locals, assign, inputs);
- var arg = plusFn(lhs, rhs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary-': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var lhs = left(scope, locals, assign, inputs);
- var rhs = right(scope, locals, assign, inputs);
- var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);
- return context ? {value: arg} : arg;
- };
- },
- 'binary*': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary/': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary%': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary===': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary!==': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary==': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary!=': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary<': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary>': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary<=': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary>=': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary&&': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'binary||': function(left, right, context) {
- return function(scope, locals, assign, inputs) {
- var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- 'ternary?:': function(test, alternate, consequent, context) {
- return function(scope, locals, assign, inputs) {
- var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);
- return context ? {value: arg} : arg;
- };
- },
- value: function(value, context) {
- return function() { return context ? {context: undefined, name: undefined, value: value} : value; };
- },
- identifier: function(name, expensiveChecks, context, create, expression) {
- return function(scope, locals, assign, inputs) {
- var base = locals && (name in locals) ? locals : scope;
- if (create && create !== 1 && base && !(base[name])) {
- base[name] = {};
- }
- var value = base ? base[name] : undefined;
- if (expensiveChecks) {
- ensureSafeObject(value, expression);
- }
- if (context) {
- return {context: base, name: name, value: value};
- } else {
- return value;
- }
- };
- },
- computedMember: function(left, right, context, create, expression) {
- return function(scope, locals, assign, inputs) {
- var lhs = left(scope, locals, assign, inputs);
- var rhs;
- var value;
- if (lhs != null) {
- rhs = right(scope, locals, assign, inputs);
- rhs = getStringValue(rhs);
- ensureSafeMemberName(rhs, expression);
- if (create && create !== 1) {
- ensureSafeAssignContext(lhs);
- if (lhs && !(lhs[rhs])) {
- lhs[rhs] = {};
- }
- }
- value = lhs[rhs];
- ensureSafeObject(value, expression);
- }
- if (context) {
- return {context: lhs, name: rhs, value: value};
- } else {
- return value;
- }
- };
- },
- nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
- return function(scope, locals, assign, inputs) {
- var lhs = left(scope, locals, assign, inputs);
- if (create && create !== 1) {
- ensureSafeAssignContext(lhs);
- if (lhs && !(lhs[right])) {
- lhs[right] = {};
- }
- }
- var value = lhs != null ? lhs[right] : undefined;
- if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
- ensureSafeObject(value, expression);
- }
- if (context) {
- return {context: lhs, name: right, value: value};
- } else {
- return value;
- }
- };
- },
- inputs: function(input, watchId) {
- return function(scope, value, locals, inputs) {
- if (inputs) return inputs[watchId];
- return input(scope, value, locals);
- };
- }
-};
-
-/**
- * @constructor
- */
-var Parser = function(lexer, $filter, options) {
- this.lexer = lexer;
- this.$filter = $filter;
- this.options = options;
- this.ast = new AST(this.lexer);
- this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :
- new ASTCompiler(this.ast, $filter);
-};
-
-Parser.prototype = {
- constructor: Parser,
-
- parse: function(text) {
- return this.astCompiler.compile(text, this.options.expensiveChecks);
- }
-};
-
-function isPossiblyDangerousMemberName(name) {
- return name == 'constructor';
-}
-
-var objectValueOf = Object.prototype.valueOf;
-
-function getValueOf(value) {
- return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
-}
-
-///////////////////////////////////
-
-/**
- * @ngdoc service
- * @name $parse
- * @kind function
- *
- * @description
- *
- * Converts Angular {@link guide/expression expression} into a function.
- *
- * ```js
- * var getter = $parse('user.name');
- * var setter = getter.assign;
- * var context = {user:{name:'angular'}};
- * var locals = {user:{name:'local'}};
- *
- * expect(getter(context)).toEqual('angular');
- * setter(context, 'newValue');
- * expect(context.user.name).toEqual('newValue');
- * expect(getter(context, locals)).toEqual('local');
- * ```
- *
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- *
- * The returned function also has the following properties:
- * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
- * literal.
- * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
- * constant literals.
- * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
- * set to a function to change its value on the given context.
- *
- */
-
-
-/**
- * @ngdoc provider
- * @name $parseProvider
- *
- * @description
- * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
- * service.
- */
-function $ParseProvider() {
- var cacheDefault = createMap();
- var cacheExpensive = createMap();
-
- this.$get = ['$filter', function($filter) {
- var noUnsafeEval = csp().noUnsafeEval;
- var $parseOptions = {
- csp: noUnsafeEval,
- expensiveChecks: false
- },
- $parseOptionsExpensive = {
- csp: noUnsafeEval,
- expensiveChecks: true
- };
- var runningChecksEnabled = false;
-
- $parse.$$runningExpensiveChecks = function() {
- return runningChecksEnabled;
- };
-
- return $parse;
-
- function $parse(exp, interceptorFn, expensiveChecks) {
- var parsedExpression, oneTime, cacheKey;
-
- expensiveChecks = expensiveChecks || runningChecksEnabled;
-
- switch (typeof exp) {
- case 'string':
- exp = exp.trim();
- cacheKey = exp;
-
- var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
- parsedExpression = cache[cacheKey];
-
- if (!parsedExpression) {
- if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
- oneTime = true;
- exp = exp.substring(2);
- }
- var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
- var lexer = new Lexer(parseOptions);
- var parser = new Parser(lexer, $filter, parseOptions);
- parsedExpression = parser.parse(exp);
- if (parsedExpression.constant) {
- parsedExpression.$$watchDelegate = constantWatchDelegate;
- } else if (oneTime) {
- parsedExpression.$$watchDelegate = parsedExpression.literal ?
- oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
- } else if (parsedExpression.inputs) {
- parsedExpression.$$watchDelegate = inputsWatchDelegate;
- }
- if (expensiveChecks) {
- parsedExpression = expensiveChecksInterceptor(parsedExpression);
- }
- cache[cacheKey] = parsedExpression;
- }
- return addInterceptor(parsedExpression, interceptorFn);
-
- case 'function':
- return addInterceptor(exp, interceptorFn);
-
- default:
- return addInterceptor(noop, interceptorFn);
- }
- }
-
- function expensiveChecksInterceptor(fn) {
- if (!fn) return fn;
- expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate;
- expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign);
- expensiveCheckFn.constant = fn.constant;
- expensiveCheckFn.literal = fn.literal;
- for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) {
- fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]);
- }
- expensiveCheckFn.inputs = fn.inputs;
-
- return expensiveCheckFn;
-
- function expensiveCheckFn(scope, locals, assign, inputs) {
- var expensiveCheckOldValue = runningChecksEnabled;
- runningChecksEnabled = true;
- try {
- return fn(scope, locals, assign, inputs);
- } finally {
- runningChecksEnabled = expensiveCheckOldValue;
- }
- }
- }
-
- function expressionInputDirtyCheck(newValue, oldValueOfValue) {
-
- if (newValue == null || oldValueOfValue == null) { // null/undefined
- return newValue === oldValueOfValue;
- }
-
- if (typeof newValue === 'object') {
-
- // attempt to convert the value to a primitive type
- // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
- // be cheaply dirty-checked
- newValue = getValueOf(newValue);
-
- if (typeof newValue === 'object') {
- // objects/arrays are not supported - deep-watching them would be too expensive
- return false;
- }
-
- // fall-through to the primitive equality check
- }
-
- //Primitive or NaN
- return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
- }
-
- function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
- var inputExpressions = parsedExpression.inputs;
- var lastResult;
-
- if (inputExpressions.length === 1) {
- var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
- inputExpressions = inputExpressions[0];
- return scope.$watch(function expressionInputWatch(scope) {
- var newInputValue = inputExpressions(scope);
- if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
- lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
- oldInputValueOf = newInputValue && getValueOf(newInputValue);
- }
- return lastResult;
- }, listener, objectEquality, prettyPrintExpression);
- }
-
- var oldInputValueOfValues = [];
- var oldInputValues = [];
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
- oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
- oldInputValues[i] = null;
- }
-
- return scope.$watch(function expressionInputsWatch(scope) {
- var changed = false;
-
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
- var newInputValue = inputExpressions[i](scope);
- if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
- oldInputValues[i] = newInputValue;
- oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
- }
- }
-
- if (changed) {
- lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
- }
-
- return lastResult;
- }, listener, objectEquality, prettyPrintExpression);
- }
-
- function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
- var unwatch, lastValue;
- return unwatch = scope.$watch(function oneTimeWatch(scope) {
- return parsedExpression(scope);
- }, function oneTimeListener(value, old, scope) {
- lastValue = value;
- if (isFunction(listener)) {
- listener.apply(this, arguments);
- }
- if (isDefined(value)) {
- scope.$$postDigest(function() {
- if (isDefined(lastValue)) {
- unwatch();
- }
- });
- }
- }, objectEquality);
- }
-
- function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
- var unwatch, lastValue;
- return unwatch = scope.$watch(function oneTimeWatch(scope) {
- return parsedExpression(scope);
- }, function oneTimeListener(value, old, scope) {
- lastValue = value;
- if (isFunction(listener)) {
- listener.call(this, value, old, scope);
- }
- if (isAllDefined(value)) {
- scope.$$postDigest(function() {
- if (isAllDefined(lastValue)) unwatch();
- });
- }
- }, objectEquality);
-
- function isAllDefined(value) {
- var allDefined = true;
- forEach(value, function(val) {
- if (!isDefined(val)) allDefined = false;
- });
- return allDefined;
- }
- }
-
- function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
- var unwatch;
- return unwatch = scope.$watch(function constantWatch(scope) {
- unwatch();
- return parsedExpression(scope);
- }, listener, objectEquality);
- }
-
- function addInterceptor(parsedExpression, interceptorFn) {
- if (!interceptorFn) return parsedExpression;
- var watchDelegate = parsedExpression.$$watchDelegate;
- var useInputs = false;
-
- var regularWatch =
- watchDelegate !== oneTimeLiteralWatchDelegate &&
- watchDelegate !== oneTimeWatchDelegate;
-
- var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
- var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
- return interceptorFn(value, scope, locals);
- } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
- var value = parsedExpression(scope, locals, assign, inputs);
- var result = interceptorFn(value, scope, locals);
- // we only return the interceptor's result if the
- // initial value is defined (for bind-once)
- return isDefined(value) ? result : value;
- };
-
- // Propagate $$watchDelegates other then inputsWatchDelegate
- if (parsedExpression.$$watchDelegate &&
- parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
- fn.$$watchDelegate = parsedExpression.$$watchDelegate;
- } else if (!interceptorFn.$stateful) {
- // If there is an interceptor, but no watchDelegate then treat the interceptor like
- // we treat filters - it is assumed to be a pure function unless flagged with $stateful
- fn.$$watchDelegate = inputsWatchDelegate;
- useInputs = !parsedExpression.inputs;
- fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
- }
-
- return fn;
- }
- }];
-}
-
-/**
- * @ngdoc service
- * @name $q
- * @requires $rootScope
- *
- * @description
- * A service that helps you run functions asynchronously, and use their return values (or exceptions)
- * when they are done processing.
- *
- * This is an implementation of promises/deferred objects inspired by
- * [Kris Kowal's Q](https://github.com/kriskowal/q).
- *
- * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
- * implementations, and the other which resembles ES6 promises to some degree.
- *
- * # $q constructor
- *
- * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
- * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
- * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
- *
- * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
- * available yet.
- *
- * It can be used like so:
- *
- * ```js
- * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
- * // are available in the current lexical scope (they could have been injected or passed in).
- *
- * function asyncGreet(name) {
- * // perform some asynchronous operation, resolve or reject the promise when appropriate.
- * return $q(function(resolve, reject) {
- * setTimeout(function() {
- * if (okToGreet(name)) {
- * resolve('Hello, ' + name + '!');
- * } else {
- * reject('Greeting ' + name + ' is not allowed.');
- * }
- * }, 1000);
- * });
- * }
- *
- * var promise = asyncGreet('Robin Hood');
- * promise.then(function(greeting) {
- * alert('Success: ' + greeting);
- * }, function(reason) {
- * alert('Failed: ' + reason);
- * });
- * ```
- *
- * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
- *
- * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise.
- *
- * However, the more traditional CommonJS-style usage is still available, and documented below.
- *
- * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
- * interface for interacting with an object that represents the result of an action that is
- * performed asynchronously, and may or may not be finished at any given point in time.
- *
- * From the perspective of dealing with error handling, deferred and promise APIs are to
- * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
- *
- * ```js
- * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
- * // are available in the current lexical scope (they could have been injected or passed in).
- *
- * function asyncGreet(name) {
- * var deferred = $q.defer();
- *
- * setTimeout(function() {
- * deferred.notify('About to greet ' + name + '.');
- *
- * if (okToGreet(name)) {
- * deferred.resolve('Hello, ' + name + '!');
- * } else {
- * deferred.reject('Greeting ' + name + ' is not allowed.');
- * }
- * }, 1000);
- *
- * return deferred.promise;
- * }
- *
- * var promise = asyncGreet('Robin Hood');
- * promise.then(function(greeting) {
- * alert('Success: ' + greeting);
- * }, function(reason) {
- * alert('Failed: ' + reason);
- * }, function(update) {
- * alert('Got notification: ' + update);
- * });
- * ```
- *
- * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
- * comes in the way of guarantees that promise and deferred APIs make, see
- * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
- *
- * Additionally the promise api allows for composition that is very hard to do with the
- * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
- * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
- * section on serial or parallel joining of promises.
- *
- * # The Deferred API
- *
- * A new instance of deferred is constructed by calling `$q.defer()`.
- *
- * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
- * that can be used for signaling the successful or unsuccessful completion, as well as the status
- * of the task.
- *
- * **Methods**
- *
- * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
- * constructed via `$q.reject`, the promise will be rejected instead.
- * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
- * resolving it with a rejection constructed via `$q.reject`.
- * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
- * multiple times before the promise is either resolved or rejected.
- *
- * **Properties**
- *
- * - promise – `{Promise}` – promise object associated with this deferred.
- *
- *
- * # The Promise API
- *
- * A new promise instance is created when a deferred instance is created and can be retrieved by
- * calling `deferred.promise`.
- *
- * The purpose of the promise object is to allow for interested parties to get access to the result
- * of the deferred task when it completes.
- *
- * **Methods**
- *
- * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
- * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
- * as soon as the result is available. The callbacks are called with a single argument: the result
- * or rejection reason. Additionally, the notify callback may be called zero or more times to
- * provide a progress indication, before the promise is resolved or rejected.
- *
- * This method *returns a new promise* which is resolved or rejected via the return value of the
- * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved
- * with the value which is resolved in that promise using
- * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).
- * It also notifies via the return value of the `notifyCallback` method. The promise cannot be
- * resolved or rejected from the notifyCallback method.
- *
- * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
- *
- * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
- * but to do so without modifying the final value. This is useful to release resources or do some
- * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
- * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
- * more information.
- *
- * # Chaining promises
- *
- * Because calling the `then` method of a promise returns a new derived promise, it is easily
- * possible to create a chain of promises:
- *
- * ```js
- * promiseB = promiseA.then(function(result) {
- * return result + 1;
- * });
- *
- * // promiseB will be resolved immediately after promiseA is resolved and its value
- * // will be the result of promiseA incremented by 1
- * ```
- *
- * It is possible to create chains of any length and since a promise can be resolved with another
- * promise (which will defer its resolution further), it is possible to pause/defer resolution of
- * the promises at any point in the chain. This makes it possible to implement powerful APIs like
- * $http's response interceptors.
- *
- *
- * # Differences between Kris Kowal's Q and $q
- *
- * There are two main differences:
- *
- * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
- * mechanism in angular, which means faster propagation of resolution or rejection into your
- * models and avoiding unnecessary browser repaints, which would result in flickering UI.
- * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
- * all the important functionality needed for common async tasks.
- *
- * # Testing
- *
- * ```js
- * it('should simulate promise', inject(function($q, $rootScope) {
- * var deferred = $q.defer();
- * var promise = deferred.promise;
- * var resolvedValue;
- *
- * promise.then(function(value) { resolvedValue = value; });
- * expect(resolvedValue).toBeUndefined();
- *
- * // Simulate resolving of promise
- * deferred.resolve(123);
- * // Note that the 'then' function does not get called synchronously.
- * // This is because we want the promise API to always be async, whether or not
- * // it got called synchronously or asynchronously.
- * expect(resolvedValue).toBeUndefined();
- *
- * // Propagate promise resolution to 'then' functions using $apply().
- * $rootScope.$apply();
- * expect(resolvedValue).toEqual(123);
- * }));
- * ```
- *
- * @param {function(function, function)} resolver Function which is responsible for resolving or
- * rejecting the newly created promise. The first parameter is a function which resolves the
- * promise, the second parameter is a function which rejects the promise.
- *
- * @returns {Promise} The newly created promise.
- */
-function $QProvider() {
-
- this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
- return qFactory(function(callback) {
- $rootScope.$evalAsync(callback);
- }, $exceptionHandler);
- }];
-}
-
-function $$QProvider() {
- this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
- return qFactory(function(callback) {
- $browser.defer(callback);
- }, $exceptionHandler);
- }];
-}
-
-/**
- * Constructs a promise manager.
- *
- * @param {function(function)} nextTick Function for executing functions in the next turn.
- * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
- * debugging purposes.
- * @returns {object} Promise manager.
- */
-function qFactory(nextTick, exceptionHandler) {
- var $qMinErr = minErr('$q', TypeError);
-
- /**
- * @ngdoc method
- * @name ng.$q#defer
- * @kind function
- *
- * @description
- * Creates a `Deferred` object which represents a task which will finish in the future.
- *
- * @returns {Deferred} Returns a new instance of deferred.
- */
- var defer = function() {
- var d = new Deferred();
- //Necessary to support unbound execution :/
- d.resolve = simpleBind(d, d.resolve);
- d.reject = simpleBind(d, d.reject);
- d.notify = simpleBind(d, d.notify);
- return d;
- };
-
- function Promise() {
- this.$$state = { status: 0 };
- }
-
- extend(Promise.prototype, {
- then: function(onFulfilled, onRejected, progressBack) {
- if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
- return this;
- }
- var result = new Deferred();
-
- this.$$state.pending = this.$$state.pending || [];
- this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
- if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
-
- return result.promise;
- },
-
- "catch": function(callback) {
- return this.then(null, callback);
- },
-
- "finally": function(callback, progressBack) {
- return this.then(function(value) {
- return handleCallback(value, true, callback);
- }, function(error) {
- return handleCallback(error, false, callback);
- }, progressBack);
- }
- });
-
- //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
- function simpleBind(context, fn) {
- return function(value) {
- fn.call(context, value);
- };
- }
-
- function processQueue(state) {
- var fn, deferred, pending;
-
- pending = state.pending;
- state.processScheduled = false;
- state.pending = undefined;
- for (var i = 0, ii = pending.length; i < ii; ++i) {
- deferred = pending[i][0];
- fn = pending[i][state.status];
- try {
- if (isFunction(fn)) {
- deferred.resolve(fn(state.value));
- } else if (state.status === 1) {
- deferred.resolve(state.value);
- } else {
- deferred.reject(state.value);
- }
- } catch (e) {
- deferred.reject(e);
- exceptionHandler(e);
- }
- }
- }
-
- function scheduleProcessQueue(state) {
- if (state.processScheduled || !state.pending) return;
- state.processScheduled = true;
- nextTick(function() { processQueue(state); });
- }
-
- function Deferred() {
- this.promise = new Promise();
- }
-
- extend(Deferred.prototype, {
- resolve: function(val) {
- if (this.promise.$$state.status) return;
- if (val === this.promise) {
- this.$$reject($qMinErr(
- 'qcycle',
- "Expected promise to be resolved with value other than itself '{0}'",
- val));
- } else {
- this.$$resolve(val);
- }
-
- },
-
- $$resolve: function(val) {
- var then;
- var that = this;
- var done = false;
- try {
- if ((isObject(val) || isFunction(val))) then = val && val.then;
- if (isFunction(then)) {
- this.promise.$$state.status = -1;
- then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify));
- } else {
- this.promise.$$state.value = val;
- this.promise.$$state.status = 1;
- scheduleProcessQueue(this.promise.$$state);
- }
- } catch (e) {
- rejectPromise(e);
- exceptionHandler(e);
- }
-
- function resolvePromise(val) {
- if (done) return;
- done = true;
- that.$$resolve(val);
- }
- function rejectPromise(val) {
- if (done) return;
- done = true;
- that.$$reject(val);
- }
- },
-
- reject: function(reason) {
- if (this.promise.$$state.status) return;
- this.$$reject(reason);
- },
-
- $$reject: function(reason) {
- this.promise.$$state.value = reason;
- this.promise.$$state.status = 2;
- scheduleProcessQueue(this.promise.$$state);
- },
-
- notify: function(progress) {
- var callbacks = this.promise.$$state.pending;
-
- if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
- nextTick(function() {
- var callback, result;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- result = callbacks[i][0];
- callback = callbacks[i][3];
- try {
- result.notify(isFunction(callback) ? callback(progress) : progress);
- } catch (e) {
- exceptionHandler(e);
- }
- }
- });
- }
- }
- });
-
- /**
- * @ngdoc method
- * @name $q#reject
- * @kind function
- *
- * @description
- * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
- * used to forward rejection in a chain of promises. If you are dealing with the last promise in
- * a promise chain, you don't need to worry about it.
- *
- * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
- * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
- * a promise error callback and you want to forward the error to the promise derived from the
- * current promise, you have to "rethrow" the error by returning a rejection constructed via
- * `reject`.
- *
- * ```js
- * promiseB = promiseA.then(function(result) {
- * // success: do something and resolve promiseB
- * // with the old or a new result
- * return result;
- * }, function(reason) {
- * // error: handle the error if possible and
- * // resolve promiseB with newPromiseOrValue,
- * // otherwise forward the rejection to promiseB
- * if (canHandle(reason)) {
- * // handle the error and recover
- * return newPromiseOrValue;
- * }
- * return $q.reject(reason);
- * });
- * ```
- *
- * @param {*} reason Constant, message, exception or an object representing the rejection reason.
- * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
- */
- var reject = function(reason) {
- var result = new Deferred();
- result.reject(reason);
- return result.promise;
- };
-
- var makePromise = function makePromise(value, resolved) {
- var result = new Deferred();
- if (resolved) {
- result.resolve(value);
- } else {
- result.reject(value);
- }
- return result.promise;
- };
-
- var handleCallback = function handleCallback(value, isResolved, callback) {
- var callbackOutput = null;
- try {
- if (isFunction(callback)) callbackOutput = callback();
- } catch (e) {
- return makePromise(e, false);
- }
- if (isPromiseLike(callbackOutput)) {
- return callbackOutput.then(function() {
- return makePromise(value, isResolved);
- }, function(error) {
- return makePromise(error, false);
- });
- } else {
- return makePromise(value, isResolved);
- }
- };
-
- /**
- * @ngdoc method
- * @name $q#when
- * @kind function
- *
- * @description
- * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
- * This is useful when you are dealing with an object that might or might not be a promise, or if
- * the promise comes from a source that can't be trusted.
- *
- * @param {*} value Value or a promise
- * @param {Function=} successCallback
- * @param {Function=} errorCallback
- * @param {Function=} progressCallback
- * @returns {Promise} Returns a promise of the passed value or promise
- */
-
-
- var when = function(value, callback, errback, progressBack) {
- var result = new Deferred();
- result.resolve(value);
- return result.promise.then(callback, errback, progressBack);
- };
-
- /**
- * @ngdoc method
- * @name $q#resolve
- * @kind function
- *
- * @description
- * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
- *
- * @param {*} value Value or a promise
- * @param {Function=} successCallback
- * @param {Function=} errorCallback
- * @param {Function=} progressCallback
- * @returns {Promise} Returns a promise of the passed value or promise
- */
- var resolve = when;
-
- /**
- * @ngdoc method
- * @name $q#all
- * @kind function
- *
- * @description
- * Combines multiple promises into a single promise that is resolved when all of the input
- * promises are resolved.
- *
- * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
- * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
- * each value corresponding to the promise at the same index/key in the `promises` array/hash.
- * If any of the promises is resolved with a rejection, this resulting promise will be rejected
- * with the same rejection value.
- */
-
- function all(promises) {
- var deferred = new Deferred(),
- counter = 0,
- results = isArray(promises) ? [] : {};
-
- forEach(promises, function(promise, key) {
- counter++;
- when(promise).then(function(value) {
- if (results.hasOwnProperty(key)) return;
- results[key] = value;
- if (!(--counter)) deferred.resolve(results);
- }, function(reason) {
- if (results.hasOwnProperty(key)) return;
- deferred.reject(reason);
- });
- });
-
- if (counter === 0) {
- deferred.resolve(results);
- }
-
- return deferred.promise;
- }
-
- var $Q = function Q(resolver) {
- if (!isFunction(resolver)) {
- throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
- }
-
- var deferred = new Deferred();
-
- function resolveFn(value) {
- deferred.resolve(value);
- }
-
- function rejectFn(reason) {
- deferred.reject(reason);
- }
-
- resolver(resolveFn, rejectFn);
-
- return deferred.promise;
- };
-
- // Let's make the instanceof operator work for promises, so that
- // `new $q(fn) instanceof $q` would evaluate to true.
- $Q.prototype = Promise.prototype;
-
- $Q.defer = defer;
- $Q.reject = reject;
- $Q.when = when;
- $Q.resolve = resolve;
- $Q.all = all;
-
- return $Q;
-}
-
-function $$RAFProvider() { //rAF
- this.$get = ['$window', '$timeout', function($window, $timeout) {
- var requestAnimationFrame = $window.requestAnimationFrame ||
- $window.webkitRequestAnimationFrame;
-
- var cancelAnimationFrame = $window.cancelAnimationFrame ||
- $window.webkitCancelAnimationFrame ||
- $window.webkitCancelRequestAnimationFrame;
-
- var rafSupported = !!requestAnimationFrame;
- var raf = rafSupported
- ? function(fn) {
- var id = requestAnimationFrame(fn);
- return function() {
- cancelAnimationFrame(id);
- };
- }
- : function(fn) {
- var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
- return function() {
- $timeout.cancel(timer);
- };
- };
-
- raf.supported = rafSupported;
-
- return raf;
- }];
-}
-
-/**
- * DESIGN NOTES
- *
- * The design decisions behind the scope are heavily favored for speed and memory consumption.
- *
- * The typical use of scope is to watch the expressions, which most of the time return the same
- * value as last time so we optimize the operation.
- *
- * Closures construction is expensive in terms of speed as well as memory:
- * - No closures, instead use prototypical inheritance for API
- * - Internal state needs to be stored on scope directly, which means that private state is
- * exposed as $$____ properties
- *
- * Loop operations are optimized by using while(count--) { ... }
- * - This means that in order to keep the same order of execution as addition we have to add
- * items to the array at the beginning (unshift) instead of at the end (push)
- *
- * Child scopes are created and removed often
- * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists
- *
- * There are fewer watches than observers. This is why you don't want the observer to be implemented
- * in the same way as watch. Watch requires return of the initialization function which is expensive
- * to construct.
- */
-
-
-/**
- * @ngdoc provider
- * @name $rootScopeProvider
- * @description
- *
- * Provider for the $rootScope service.
- */
-
-/**
- * @ngdoc method
- * @name $rootScopeProvider#digestTtl
- * @description
- *
- * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
- * assuming that the model is unstable.
- *
- * The current default is 10 iterations.
- *
- * In complex applications it's possible that the dependencies between `$watch`s will result in
- * several digest iterations. However if an application needs more than the default 10 digest
- * iterations for its model to stabilize then you should investigate what is causing the model to
- * continuously change during the digest.
- *
- * Increasing the TTL could have performance implications, so you should not change it without
- * proper justification.
- *
- * @param {number} limit The number of digest iterations.
- */
-
-
-/**
- * @ngdoc service
- * @name $rootScope
- * @description
- *
- * Every application has a single root {@link ng.$rootScope.Scope scope}.
- * All other scopes are descendant scopes of the root scope. Scopes provide separation
- * between the model and the view, via a mechanism for watching the model for changes.
- * They also provide event emission/broadcast and subscription facility. See the
- * {@link guide/scope developer guide on scopes}.
- */
-function $RootScopeProvider() {
- var TTL = 10;
- var $rootScopeMinErr = minErr('$rootScope');
- var lastDirtyWatch = null;
- var applyAsyncId = null;
-
- this.digestTtl = function(value) {
- if (arguments.length) {
- TTL = value;
- }
- return TTL;
- };
-
- function createChildScopeClass(parent) {
- function ChildScope() {
- this.$$watchers = this.$$nextSibling =
- this.$$childHead = this.$$childTail = null;
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$$watchersCount = 0;
- this.$id = nextUid();
- this.$$ChildScope = null;
- }
- ChildScope.prototype = parent;
- return ChildScope;
- }
-
- this.$get = ['$exceptionHandler', '$parse', '$browser',
- function($exceptionHandler, $parse, $browser) {
-
- function destroyChildScope($event) {
- $event.currentScope.$$destroyed = true;
- }
-
- function cleanUpScope($scope) {
-
- if (msie === 9) {
- // There is a memory leak in IE9 if all child scopes are not disconnected
- // completely when a scope is destroyed. So this code will recurse up through
- // all this scopes children
- //
- // See issue https://github.com/angular/angular.js/issues/10706
- $scope.$$childHead && cleanUpScope($scope.$$childHead);
- $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);
- }
-
- // The code below works around IE9 and V8's memory leaks
- //
- // See:
- // - https://code.google.com/p/v8/issues/detail?id=2073#c26
- // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
- // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
-
- $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
- $scope.$$childTail = $scope.$root = $scope.$$watchers = null;
- }
-
- /**
- * @ngdoc type
- * @name $rootScope.Scope
- *
- * @description
- * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
- * {@link auto.$injector $injector}. Child scopes are created using the
- * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
- * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for
- * an in-depth introduction and usage examples.
- *
- *
- * # Inheritance
- * A scope can inherit from a parent scope, as in this example:
- * ```js
- var parent = $rootScope;
- var child = parent.$new();
-
- parent.salutation = "Hello";
- expect(child.salutation).toEqual('Hello');
-
- child.salutation = "Welcome";
- expect(child.salutation).toEqual('Welcome');
- expect(parent.salutation).toEqual('Hello');
- * ```
- *
- * When interacting with `Scope` in tests, additional helper methods are available on the
- * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
- * details.
- *
- *
- * @param {Object.<string, function()>=} providers Map of service factory which need to be
- * provided for the current scope. Defaults to {@link ng}.
- * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
- * append/override services provided by `providers`. This is handy
- * when unit-testing and having the need to override a default
- * service.
- * @returns {Object} Newly created scope.
- *
- */
- function Scope() {
- this.$id = nextUid();
- this.$$phase = this.$parent = this.$$watchers =
- this.$$nextSibling = this.$$prevSibling =
- this.$$childHead = this.$$childTail = null;
- this.$root = this;
- this.$$destroyed = false;
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$$watchersCount = 0;
- this.$$isolateBindings = null;
- }
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$id
- *
- * @description
- * Unique scope ID (monotonically increasing) useful for debugging.
- */
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$parent
- *
- * @description
- * Reference to the parent scope.
- */
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$root
- *
- * @description
- * Reference to the root scope.
- */
-
- Scope.prototype = {
- constructor: Scope,
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$new
- * @kind function
- *
- * @description
- * Creates a new child {@link ng.$rootScope.Scope scope}.
- *
- * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
- * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
- *
- * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
- * desired for the scope and its child scopes to be permanently detached from the parent and
- * thus stop participating in model change detection and listener notification by invoking.
- *
- * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
- * parent scope. The scope is isolated, as it can not see parent scope properties.
- * When creating widgets, it is useful for the widget to not accidentally read parent
- * state.
- *
- * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
- * of the newly created scope. Defaults to `this` scope if not provided.
- * This is used when creating a transclude scope to correctly place it
- * in the scope hierarchy while maintaining the correct prototypical
- * inheritance.
- *
- * @returns {Object} The newly created child scope.
- *
- */
- $new: function(isolate, parent) {
- var child;
-
- parent = parent || this;
-
- if (isolate) {
- child = new Scope();
- child.$root = this.$root;
- } else {
- // Only create a child scope class if somebody asks for one,
- // but cache it to allow the VM to optimize lookups.
- if (!this.$$ChildScope) {
- this.$$ChildScope = createChildScopeClass(this);
- }
- child = new this.$$ChildScope();
- }
- child.$parent = parent;
- child.$$prevSibling = parent.$$childTail;
- if (parent.$$childHead) {
- parent.$$childTail.$$nextSibling = child;
- parent.$$childTail = child;
- } else {
- parent.$$childHead = parent.$$childTail = child;
- }
-
- // When the new scope is not isolated or we inherit from `this`, and
- // the parent scope is destroyed, the property `$$destroyed` is inherited
- // prototypically. In all other cases, this property needs to be set
- // when the parent scope is destroyed.
- // The listener needs to be added after the parent is set
- if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
-
- return child;
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$watch
- * @kind function
- *
- * @description
- * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
- *
- * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
- * $digest()} and should return the value that will be watched. (`watchExpression` should not change
- * its value when executed multiple times with the same input because it may be executed multiple
- * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be
- * [idempotent](http://en.wikipedia.org/wiki/Idempotence).
- * - The `listener` is called only when the value from the current `watchExpression` and the
- * previous call to `watchExpression` are not equal (with the exception of the initial run,
- * see below). Inequality is determined according to reference inequality,
- * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
- * via the `!==` Javascript operator, unless `objectEquality == true`
- * (see next point)
- * - When `objectEquality == true`, inequality of the `watchExpression` is determined
- * according to the {@link angular.equals} function. To save the value of the object for
- * later comparison, the {@link angular.copy} function is used. This therefore means that
- * watching complex objects will have adverse memory and performance implications.
- * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
- * This is achieved by rerunning the watchers until no changes are detected. The rerun
- * iteration limit is 10 to prevent an infinite loop deadlock.
- *
- *
- * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
- * you can register a `watchExpression` function with no `listener`. (Be prepared for
- * multiple calls to your `watchExpression` because it will execute multiple times in a
- * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)
- *
- * After a watcher is registered with the scope, the `listener` fn is called asynchronously
- * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
- * watcher. In rare cases, this is undesirable because the listener is called when the result
- * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
- * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
- * listener was called due to initialization.
- *
- *
- *
- * # Example
- * ```js
- // let's assume that scope was dependency injected as the $rootScope
- var scope = $rootScope;
- scope.name = 'misko';
- scope.counter = 0;
-
- expect(scope.counter).toEqual(0);
- scope.$watch('name', function(newValue, oldValue) {
- scope.counter = scope.counter + 1;
- });
- expect(scope.counter).toEqual(0);
-
- scope.$digest();
- // the listener is always called during the first $digest loop after it was registered
- expect(scope.counter).toEqual(1);
-
- scope.$digest();
- // but now it will not be called unless the value changes
- expect(scope.counter).toEqual(1);
-
- scope.name = 'adam';
- scope.$digest();
- expect(scope.counter).toEqual(2);
-
-
-
- // Using a function as a watchExpression
- var food;
- scope.foodCounter = 0;
- expect(scope.foodCounter).toEqual(0);
- scope.$watch(
- // This function returns the value being watched. It is called for each turn of the $digest loop
- function() { return food; },
- // This is the change listener, called when the value returned from the above function changes
- function(newValue, oldValue) {
- if ( newValue !== oldValue ) {
- // Only increment the counter if the value changed
- scope.foodCounter = scope.foodCounter + 1;
- }
- }
- );
- // No digest has been run so the counter will be zero
- expect(scope.foodCounter).toEqual(0);
-
- // Run the digest but since food has not changed count will still be zero
- scope.$digest();
- expect(scope.foodCounter).toEqual(0);
-
- // Update food and run digest. Now the counter will increment
- food = 'cheeseburger';
- scope.$digest();
- expect(scope.foodCounter).toEqual(1);
-
- * ```
- *
- *
- *
- * @param {(function()|string)} watchExpression Expression that is evaluated on each
- * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
- * a call to the `listener`.
- *
- * - `string`: Evaluated as {@link guide/expression expression}
- * - `function(scope)`: called with current `scope` as a parameter.
- * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
- * of `watchExpression` changes.
- *
- * - `newVal` contains the current value of the `watchExpression`
- * - `oldVal` contains the previous value of the `watchExpression`
- * - `scope` refers to the current scope
- * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of
- * comparing for reference equality.
- * @returns {function()} Returns a deregistration function for this listener.
- */
- $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {
- var get = $parse(watchExp);
-
- if (get.$$watchDelegate) {
- return get.$$watchDelegate(this, listener, objectEquality, get, watchExp);
- }
- var scope = this,
- array = scope.$$watchers,
- watcher = {
- fn: listener,
- last: initWatchVal,
- get: get,
- exp: prettyPrintExpression || watchExp,
- eq: !!objectEquality
- };
-
- lastDirtyWatch = null;
-
- if (!isFunction(listener)) {
- watcher.fn = noop;
- }
-
- if (!array) {
- array = scope.$$watchers = [];
- }
- // we use unshift since we use a while loop in $digest for speed.
- // the while loop reads in reverse order.
- array.unshift(watcher);
- incrementWatchersCount(this, 1);
-
- return function deregisterWatch() {
- if (arrayRemove(array, watcher) >= 0) {
- incrementWatchersCount(scope, -1);
- }
- lastDirtyWatch = null;
- };
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$watchGroup
- * @kind function
- *
- * @description
- * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
- * If any one expression in the collection changes the `listener` is executed.
- *
- * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
- * call to $digest() to see if any items changes.
- * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
- *
- * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
- * watched using {@link ng.$rootScope.Scope#$watch $watch()}
- *
- * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
- * expression in `watchExpressions` changes
- * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
- * those of `watchExpression`
- * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
- * those of `watchExpression`
- * The `scope` refers to the current scope.
- * @returns {function()} Returns a de-registration function for all listeners.
- */
- $watchGroup: function(watchExpressions, listener) {
- var oldValues = new Array(watchExpressions.length);
- var newValues = new Array(watchExpressions.length);
- var deregisterFns = [];
- var self = this;
- var changeReactionScheduled = false;
- var firstRun = true;
-
- if (!watchExpressions.length) {
- // No expressions means we call the listener ASAP
- var shouldCall = true;
- self.$evalAsync(function() {
- if (shouldCall) listener(newValues, newValues, self);
- });
- return function deregisterWatchGroup() {
- shouldCall = false;
- };
- }
-
- if (watchExpressions.length === 1) {
- // Special case size of one
- return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
- newValues[0] = value;
- oldValues[0] = oldValue;
- listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
- });
- }
-
- forEach(watchExpressions, function(expr, i) {
- var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
- newValues[i] = value;
- oldValues[i] = oldValue;
- if (!changeReactionScheduled) {
- changeReactionScheduled = true;
- self.$evalAsync(watchGroupAction);
- }
- });
- deregisterFns.push(unwatchFn);
- });
-
- function watchGroupAction() {
- changeReactionScheduled = false;
-
- if (firstRun) {
- firstRun = false;
- listener(newValues, newValues, self);
- } else {
- listener(newValues, oldValues, self);
- }
- }
-
- return function deregisterWatchGroup() {
- while (deregisterFns.length) {
- deregisterFns.shift()();
- }
- };
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$watchCollection
- * @kind function
- *
- * @description
- * Shallow watches the properties of an object and fires whenever any of the properties change
- * (for arrays, this implies watching the array items; for object maps, this implies watching
- * the properties). If a change is detected, the `listener` callback is fired.
- *
- * - The `obj` collection is observed via standard $watch operation and is examined on every
- * call to $digest() to see if any items have been added, removed, or moved.
- * - The `listener` is called whenever anything within the `obj` has changed. Examples include
- * adding, removing, and moving items belonging to an object or array.
- *
- *
- * # Example
- * ```js
- $scope.names = ['igor', 'matias', 'misko', 'james'];
- $scope.dataCount = 4;
-
- $scope.$watchCollection('names', function(newNames, oldNames) {
- $scope.dataCount = newNames.length;
- });
-
- expect($scope.dataCount).toEqual(4);
- $scope.$digest();
-
- //still at 4 ... no changes
- expect($scope.dataCount).toEqual(4);
-
- $scope.names.pop();
- $scope.$digest();
-
- //now there's been a change
- expect($scope.dataCount).toEqual(3);
- * ```
- *
- *
- * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
- * expression value should evaluate to an object or an array which is observed on each
- * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
- * collection will trigger a call to the `listener`.
- *
- * @param {function(newCollection, oldCollection, scope)} listener a callback function called
- * when a change is detected.
- * - The `newCollection` object is the newly modified data obtained from the `obj` expression
- * - The `oldCollection` object is a copy of the former collection data.
- * Due to performance considerations, the`oldCollection` value is computed only if the
- * `listener` function declares two or more arguments.
- * - The `scope` argument refers to the current scope.
- *
- * @returns {function()} Returns a de-registration function for this listener. When the
- * de-registration function is executed, the internal watch operation is terminated.
- */
- $watchCollection: function(obj, listener) {
- $watchCollectionInterceptor.$stateful = true;
-
- var self = this;
- // the current value, updated on each dirty-check run
- var newValue;
- // a shallow copy of the newValue from the last dirty-check run,
- // updated to match newValue during dirty-check run
- var oldValue;
- // a shallow copy of the newValue from when the last change happened
- var veryOldValue;
- // only track veryOldValue if the listener is asking for it
- var trackVeryOldValue = (listener.length > 1);
- var changeDetected = 0;
- var changeDetector = $parse(obj, $watchCollectionInterceptor);
- var internalArray = [];
- var internalObject = {};
- var initRun = true;
- var oldLength = 0;
-
- function $watchCollectionInterceptor(_value) {
- newValue = _value;
- var newLength, key, bothNaN, newItem, oldItem;
-
- // If the new value is undefined, then return undefined as the watch may be a one-time watch
- if (isUndefined(newValue)) return;
-
- if (!isObject(newValue)) { // if primitive
- if (oldValue !== newValue) {
- oldValue = newValue;
- changeDetected++;
- }
- } else if (isArrayLike(newValue)) {
- if (oldValue !== internalArray) {
- // we are transitioning from something which was not an array into array.
- oldValue = internalArray;
- oldLength = oldValue.length = 0;
- changeDetected++;
- }
-
- newLength = newValue.length;
-
- if (oldLength !== newLength) {
- // if lengths do not match we need to trigger change notification
- changeDetected++;
- oldValue.length = oldLength = newLength;
- }
- // copy the items to oldValue and look for changes.
- for (var i = 0; i < newLength; i++) {
- oldItem = oldValue[i];
- newItem = newValue[i];
-
- bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
- if (!bothNaN && (oldItem !== newItem)) {
- changeDetected++;
- oldValue[i] = newItem;
- }
- }
- } else {
- if (oldValue !== internalObject) {
- // we are transitioning from something which was not an object into object.
- oldValue = internalObject = {};
- oldLength = 0;
- changeDetected++;
- }
- // copy the items to oldValue and look for changes.
- newLength = 0;
- for (key in newValue) {
- if (hasOwnProperty.call(newValue, key)) {
- newLength++;
- newItem = newValue[key];
- oldItem = oldValue[key];
-
- if (key in oldValue) {
- bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
- if (!bothNaN && (oldItem !== newItem)) {
- changeDetected++;
- oldValue[key] = newItem;
- }
- } else {
- oldLength++;
- oldValue[key] = newItem;
- changeDetected++;
- }
- }
- }
- if (oldLength > newLength) {
- // we used to have more keys, need to find them and destroy them.
- changeDetected++;
- for (key in oldValue) {
- if (!hasOwnProperty.call(newValue, key)) {
- oldLength--;
- delete oldValue[key];
- }
- }
- }
- }
- return changeDetected;
- }
-
- function $watchCollectionAction() {
- if (initRun) {
- initRun = false;
- listener(newValue, newValue, self);
- } else {
- listener(newValue, veryOldValue, self);
- }
-
- // make a copy for the next time a collection is changed
- if (trackVeryOldValue) {
- if (!isObject(newValue)) {
- //primitive
- veryOldValue = newValue;
- } else if (isArrayLike(newValue)) {
- veryOldValue = new Array(newValue.length);
- for (var i = 0; i < newValue.length; i++) {
- veryOldValue[i] = newValue[i];
- }
- } else { // if object
- veryOldValue = {};
- for (var key in newValue) {
- if (hasOwnProperty.call(newValue, key)) {
- veryOldValue[key] = newValue[key];
- }
- }
- }
- }
- }
-
- return this.$watch(changeDetector, $watchCollectionAction);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$digest
- * @kind function
- *
- * @description
- * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
- * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
- * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
- * until no more listeners are firing. This means that it is possible to get into an infinite
- * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
- * iterations exceeds 10.
- *
- * Usually, you don't call `$digest()` directly in
- * {@link ng.directive:ngController controllers} or in
- * {@link ng.$compileProvider#directive directives}.
- * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
- * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
- *
- * If you want to be notified whenever `$digest()` is called,
- * you can register a `watchExpression` function with
- * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
- *
- * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
- *
- * # Example
- * ```js
- var scope = ...;
- scope.name = 'misko';
- scope.counter = 0;
-
- expect(scope.counter).toEqual(0);
- scope.$watch('name', function(newValue, oldValue) {
- scope.counter = scope.counter + 1;
- });
- expect(scope.counter).toEqual(0);
-
- scope.$digest();
- // the listener is always called during the first $digest loop after it was registered
- expect(scope.counter).toEqual(1);
-
- scope.$digest();
- // but now it will not be called unless the value changes
- expect(scope.counter).toEqual(1);
-
- scope.name = 'adam';
- scope.$digest();
- expect(scope.counter).toEqual(2);
- * ```
- *
- */
- $digest: function() {
- var watch, value, last, fn, get,
- watchers,
- length,
- dirty, ttl = TTL,
- next, current, target = this,
- watchLog = [],
- logIdx, logMsg, asyncTask;
-
- beginPhase('$digest');
- // Check for changes to browser url that happened in sync before the call to $digest
- $browser.$$checkUrlChange();
-
- if (this === $rootScope && applyAsyncId !== null) {
- // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
- // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
- $browser.defer.cancel(applyAsyncId);
- flushApplyAsync();
- }
-
- lastDirtyWatch = null;
-
- do { // "while dirty" loop
- dirty = false;
- current = target;
-
- while (asyncQueue.length) {
- try {
- asyncTask = asyncQueue.shift();
- asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
- } catch (e) {
- $exceptionHandler(e);
- }
- lastDirtyWatch = null;
- }
-
- traverseScopesLoop:
- do { // "traverse the scopes" loop
- if ((watchers = current.$$watchers)) {
- // process our watches
- length = watchers.length;
- while (length--) {
- try {
- watch = watchers[length];
- // Most common watches are on primitives, in which case we can short
- // circuit it with === operator, only when === fails do we use .equals
- if (watch) {
- get = watch.get;
- if ((value = get(current)) !== (last = watch.last) &&
- !(watch.eq
- ? equals(value, last)
- : (typeof value === 'number' && typeof last === 'number'
- && isNaN(value) && isNaN(last)))) {
- dirty = true;
- lastDirtyWatch = watch;
- watch.last = watch.eq ? copy(value, null) : value;
- fn = watch.fn;
- fn(value, ((last === initWatchVal) ? value : last), current);
- if (ttl < 5) {
- logIdx = 4 - ttl;
- if (!watchLog[logIdx]) watchLog[logIdx] = [];
- watchLog[logIdx].push({
- msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
- newVal: value,
- oldVal: last
- });
- }
- } else if (watch === lastDirtyWatch) {
- // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
- // have already been tested.
- dirty = false;
- break traverseScopesLoop;
- }
- }
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- }
-
- // Insanity Warning: scope depth-first traversal
- // yes, this code is a bit crazy, but it works and we have tests to prove it!
- // this piece should be kept in sync with the traversal in $broadcast
- if (!(next = ((current.$$watchersCount && current.$$childHead) ||
- (current !== target && current.$$nextSibling)))) {
- while (current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- } while ((current = next));
-
- // `break traverseScopesLoop;` takes us to here
-
- if ((dirty || asyncQueue.length) && !(ttl--)) {
- clearPhase();
- throw $rootScopeMinErr('infdig',
- '{0} $digest() iterations reached. Aborting!\n' +
- 'Watchers fired in the last 5 iterations: {1}',
- TTL, watchLog);
- }
-
- } while (dirty || asyncQueue.length);
-
- clearPhase();
-
- while (postDigestQueue.length) {
- try {
- postDigestQueue.shift()();
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- },
-
-
- /**
- * @ngdoc event
- * @name $rootScope.Scope#$destroy
- * @eventType broadcast on scope being destroyed
- *
- * @description
- * Broadcasted when a scope and its children are being destroyed.
- *
- * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
- * clean up DOM bindings before an element is removed from the DOM.
- */
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$destroy
- * @kind function
- *
- * @description
- * Removes the current scope (and all of its children) from the parent scope. Removal implies
- * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
- * propagate to the current scope and its children. Removal also implies that the current
- * scope is eligible for garbage collection.
- *
- * The `$destroy()` is usually used by directives such as
- * {@link ng.directive:ngRepeat ngRepeat} for managing the
- * unrolling of the loop.
- *
- * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
- * Application code can register a `$destroy` event handler that will give it a chance to
- * perform any necessary cleanup.
- *
- * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
- * clean up DOM bindings before an element is removed from the DOM.
- */
- $destroy: function() {
- // We can't destroy a scope that has been already destroyed.
- if (this.$$destroyed) return;
- var parent = this.$parent;
-
- this.$broadcast('$destroy');
- this.$$destroyed = true;
-
- if (this === $rootScope) {
- //Remove handlers attached to window when $rootScope is removed
- $browser.$$applicationDestroyed();
- }
-
- incrementWatchersCount(this, -this.$$watchersCount);
- for (var eventName in this.$$listenerCount) {
- decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
- }
-
- // sever all the references to parent scopes (after this cleanup, the current scope should
- // not be retained by any of our references and should be eligible for garbage collection)
- if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
- if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
- if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
- if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
-
- // Disable listeners, watchers and apply/digest methods
- this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
- this.$on = this.$watch = this.$watchGroup = function() { return noop; };
- this.$$listeners = {};
-
- // Disconnect the next sibling to prevent `cleanUpScope` destroying those too
- this.$$nextSibling = null;
- cleanUpScope(this);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$eval
- * @kind function
- *
- * @description
- * Executes the `expression` on the current scope and returns the result. Any exceptions in
- * the expression are propagated (uncaught). This is useful when evaluating Angular
- * expressions.
- *
- * # Example
- * ```js
- var scope = ng.$rootScope.Scope();
- scope.a = 1;
- scope.b = 2;
-
- expect(scope.$eval('a+b')).toEqual(3);
- expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
- * ```
- *
- * @param {(string|function())=} expression An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with the current `scope` parameter.
- *
- * @param {(object)=} locals Local variables object, useful for overriding values in scope.
- * @returns {*} The result of evaluating the expression.
- */
- $eval: function(expr, locals) {
- return $parse(expr)(this, locals);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$evalAsync
- * @kind function
- *
- * @description
- * Executes the expression on the current scope at a later point in time.
- *
- * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
- * that:
- *
- * - it will execute after the function that scheduled the evaluation (preferably before DOM
- * rendering).
- * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
- * `expression` execution.
- *
- * Any exceptions from the execution of the expression are forwarded to the
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
- * will be scheduled. However, it is encouraged to always call code that changes the model
- * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
- *
- * @param {(string|function())=} expression An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with the current `scope` parameter.
- *
- * @param {(object)=} locals Local variables object, useful for overriding values in scope.
- */
- $evalAsync: function(expr, locals) {
- // if we are outside of an $digest loop and this is the first time we are scheduling async
- // task also schedule async auto-flush
- if (!$rootScope.$$phase && !asyncQueue.length) {
- $browser.defer(function() {
- if (asyncQueue.length) {
- $rootScope.$digest();
- }
- });
- }
-
- asyncQueue.push({scope: this, expression: $parse(expr), locals: locals});
- },
-
- $$postDigest: function(fn) {
- postDigestQueue.push(fn);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$apply
- * @kind function
- *
- * @description
- * `$apply()` is used to execute an expression in angular from outside of the angular
- * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
- * Because we are calling into the angular framework we need to perform proper scope life
- * cycle of {@link ng.$exceptionHandler exception handling},
- * {@link ng.$rootScope.Scope#$digest executing watches}.
- *
- * ## Life cycle
- *
- * # Pseudo-Code of `$apply()`
- * ```js
- function $apply(expr) {
- try {
- return $eval(expr);
- } catch (e) {
- $exceptionHandler(e);
- } finally {
- $root.$digest();
- }
- }
- * ```
- *
- *
- * Scope's `$apply()` method transitions through the following stages:
- *
- * 1. The {@link guide/expression expression} is executed using the
- * {@link ng.$rootScope.Scope#$eval $eval()} method.
- * 2. Any exceptions from the execution of the expression are forwarded to the
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
- * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
- *
- *
- * @param {(string|function())=} exp An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with current `scope` parameter.
- *
- * @returns {*} The result of evaluating the expression.
- */
- $apply: function(expr) {
- try {
- beginPhase('$apply');
- try {
- return this.$eval(expr);
- } finally {
- clearPhase();
- }
- } catch (e) {
- $exceptionHandler(e);
- } finally {
- try {
- $rootScope.$digest();
- } catch (e) {
- $exceptionHandler(e);
- throw e;
- }
- }
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$applyAsync
- * @kind function
- *
- * @description
- * Schedule the invocation of $apply to occur at a later time. The actual time difference
- * varies across browsers, but is typically around ~10 milliseconds.
- *
- * This can be used to queue up multiple expressions which need to be evaluated in the same
- * digest.
- *
- * @param {(string|function())=} exp An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with current `scope` parameter.
- */
- $applyAsync: function(expr) {
- var scope = this;
- expr && applyAsyncQueue.push($applyAsyncExpression);
- expr = $parse(expr);
- scheduleApplyAsync();
-
- function $applyAsyncExpression() {
- scope.$eval(expr);
- }
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$on
- * @kind function
- *
- * @description
- * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
- * discussion of event life cycle.
- *
- * The event listener function format is: `function(event, args...)`. The `event` object
- * passed into the listener has the following attributes:
- *
- * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
- * `$broadcast`-ed.
- * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
- * event propagates through the scope hierarchy, this property is set to null.
- * - `name` - `{string}`: name of the event.
- * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
- * further event propagation (available only for events that were `$emit`-ed).
- * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
- * to true.
- * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
- *
- * @param {string} name Event name to listen on.
- * @param {function(event, ...args)} listener Function to call when the event is emitted.
- * @returns {function()} Returns a deregistration function for this listener.
- */
- $on: function(name, listener) {
- var namedListeners = this.$$listeners[name];
- if (!namedListeners) {
- this.$$listeners[name] = namedListeners = [];
- }
- namedListeners.push(listener);
-
- var current = this;
- do {
- if (!current.$$listenerCount[name]) {
- current.$$listenerCount[name] = 0;
- }
- current.$$listenerCount[name]++;
- } while ((current = current.$parent));
-
- var self = this;
- return function() {
- var indexOfListener = namedListeners.indexOf(listener);
- if (indexOfListener !== -1) {
- namedListeners[indexOfListener] = null;
- decrementListenerCount(self, 1, name);
- }
- };
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$emit
- * @kind function
- *
- * @description
- * Dispatches an event `name` upwards through the scope hierarchy notifying the
- * registered {@link ng.$rootScope.Scope#$on} listeners.
- *
- * The event life cycle starts at the scope on which `$emit` was called. All
- * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
- * notified. Afterwards, the event traverses upwards toward the root scope and calls all
- * registered listeners along the way. The event will stop propagating if one of the listeners
- * cancels it.
- *
- * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
- * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * @param {string} name Event name to emit.
- * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
- * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
- */
- $emit: function(name, args) {
- var empty = [],
- namedListeners,
- scope = this,
- stopPropagation = false,
- event = {
- name: name,
- targetScope: scope,
- stopPropagation: function() {stopPropagation = true;},
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- },
- listenerArgs = concat([event], arguments, 1),
- i, length;
-
- do {
- namedListeners = scope.$$listeners[name] || empty;
- event.currentScope = scope;
- for (i = 0, length = namedListeners.length; i < length; i++) {
-
- // if listeners were deregistered, defragment the array
- if (!namedListeners[i]) {
- namedListeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
- try {
- //allow all listeners attached to the current scope to run
- namedListeners[i].apply(null, listenerArgs);
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- //if any listener on the current scope stops propagation, prevent bubbling
- if (stopPropagation) {
- event.currentScope = null;
- return event;
- }
- //traverse upwards
- scope = scope.$parent;
- } while (scope);
-
- event.currentScope = null;
-
- return event;
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$broadcast
- * @kind function
- *
- * @description
- * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
- * registered {@link ng.$rootScope.Scope#$on} listeners.
- *
- * The event life cycle starts at the scope on which `$broadcast` was called. All
- * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
- * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
- * scope and calls all registered listeners along the way. The event cannot be canceled.
- *
- * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
- * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * @param {string} name Event name to broadcast.
- * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
- * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
- */
- $broadcast: function(name, args) {
- var target = this,
- current = target,
- next = target,
- event = {
- name: name,
- targetScope: target,
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- };
-
- if (!target.$$listenerCount[name]) return event;
-
- var listenerArgs = concat([event], arguments, 1),
- listeners, i, length;
-
- //down while you can, then up and next sibling or up and next sibling until back at root
- while ((current = next)) {
- event.currentScope = current;
- listeners = current.$$listeners[name] || [];
- for (i = 0, length = listeners.length; i < length; i++) {
- // if listeners were deregistered, defragment the array
- if (!listeners[i]) {
- listeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
-
- try {
- listeners[i].apply(null, listenerArgs);
- } catch (e) {
- $exceptionHandler(e);
- }
- }
-
- // Insanity Warning: scope depth-first traversal
- // yes, this code is a bit crazy, but it works and we have tests to prove it!
- // this piece should be kept in sync with the traversal in $digest
- // (though it differs due to having the extra check for $$listenerCount)
- if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
- (current !== target && current.$$nextSibling)))) {
- while (current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- }
-
- event.currentScope = null;
- return event;
- }
- };
-
- var $rootScope = new Scope();
-
- //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
- var asyncQueue = $rootScope.$$asyncQueue = [];
- var postDigestQueue = $rootScope.$$postDigestQueue = [];
- var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
-
- return $rootScope;
-
-
- function beginPhase(phase) {
- if ($rootScope.$$phase) {
- throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
- }
-
- $rootScope.$$phase = phase;
- }
-
- function clearPhase() {
- $rootScope.$$phase = null;
- }
-
- function incrementWatchersCount(current, count) {
- do {
- current.$$watchersCount += count;
- } while ((current = current.$parent));
- }
-
- function decrementListenerCount(current, count, name) {
- do {
- current.$$listenerCount[name] -= count;
-
- if (current.$$listenerCount[name] === 0) {
- delete current.$$listenerCount[name];
- }
- } while ((current = current.$parent));
- }
-
- /**
- * function used as an initial value for watchers.
- * because it's unique we can easily tell it apart from other values
- */
- function initWatchVal() {}
-
- function flushApplyAsync() {
- while (applyAsyncQueue.length) {
- try {
- applyAsyncQueue.shift()();
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- applyAsyncId = null;
- }
-
- function scheduleApplyAsync() {
- if (applyAsyncId === null) {
- applyAsyncId = $browser.defer(function() {
- $rootScope.$apply(flushApplyAsync);
- });
- }
- }
- }];
-}
-
-/**
- * @ngdoc service
- * @name $rootElement
- *
- * @description
- * The root element of Angular application. This is either the element where {@link
- * ng.directive:ngApp ngApp} was declared or the element passed into
- * {@link angular.bootstrap}. The element represents the root element of application. It is also the
- * location where the application's {@link auto.$injector $injector} service gets
- * published, and can be retrieved using `$rootElement.injector()`.
- */
-
-
-// the implementation is in angular.bootstrap
-
-/**
- * @description
- * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
- */
-function $$SanitizeUriProvider() {
- var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
- imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
-
- /**
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during a[href] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- aHrefSanitizationWhitelist = regexp;
- return this;
- }
- return aHrefSanitizationWhitelist;
- };
-
-
- /**
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during img[src] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- imgSrcSanitizationWhitelist = regexp;
- return this;
- }
- return imgSrcSanitizationWhitelist;
- };
-
- this.$get = function() {
- return function sanitizeUri(uri, isImage) {
- var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
- var normalizedVal;
- normalizedVal = urlResolve(uri).href;
- if (normalizedVal !== '' && !normalizedVal.match(regex)) {
- return 'unsafe:' + normalizedVal;
- }
- return uri;
- };
- };
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Any commits to this file should be reviewed with security in mind. *
- * Changes to this file can potentially create security vulnerabilities. *
- * An approval from 2 Core members with history of modifying *
- * this file is required. *
- * *
- * Does the change somehow allow for arbitrary javascript to be executed? *
- * Or allows for someone to change the prototype of built-in objects? *
- * Or gives undesired access to variables likes document or window? *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-var $sceMinErr = minErr('$sce');
-
-var SCE_CONTEXTS = {
- HTML: 'html',
- CSS: 'css',
- URL: 'url',
- // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
- // url. (e.g. ng-include, script src, templateUrl)
- RESOURCE_URL: 'resourceUrl',
- JS: 'js'
-};
-
-// Helper functions follow.
-
-function adjustMatcher(matcher) {
- if (matcher === 'self') {
- return matcher;
- } else if (isString(matcher)) {
- // Strings match exactly except for 2 wildcards - '*' and '**'.
- // '*' matches any character except those from the set ':/.?&'.
- // '**' matches any character (like .* in a RegExp).
- // More than 2 *'s raises an error as it's ill defined.
- if (matcher.indexOf('***') > -1) {
- throw $sceMinErr('iwcard',
- 'Illegal sequence *** in string matcher. String: {0}', matcher);
- }
- matcher = escapeForRegexp(matcher).
- replace('\\*\\*', '.*').
- replace('\\*', '[^:/.?&;]*');
- return new RegExp('^' + matcher + '$');
- } else if (isRegExp(matcher)) {
- // The only other type of matcher allowed is a Regexp.
- // Match entire URL / disallow partial matches.
- // Flags are reset (i.e. no global, ignoreCase or multiline)
- return new RegExp('^' + matcher.source + '$');
- } else {
- throw $sceMinErr('imatcher',
- 'Matchers may only be "self", string patterns or RegExp objects');
- }
-}
-
-
-function adjustMatchers(matchers) {
- var adjustedMatchers = [];
- if (isDefined(matchers)) {
- forEach(matchers, function(matcher) {
- adjustedMatchers.push(adjustMatcher(matcher));
- });
- }
- return adjustedMatchers;
-}
-
-
-/**
- * @ngdoc service
- * @name $sceDelegate
- * @kind function
- *
- * @description
- *
- * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
- * Contextual Escaping (SCE)} services to AngularJS.
- *
- * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
- * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
- * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
- * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
- * work because `$sce` delegates to `$sceDelegate` for these operations.
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
- *
- * The default instance of `$sceDelegate` should work out of the box with little pain. While you
- * can override it completely to change the behavior of `$sce`, the common case would
- * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
- * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
- * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
- * $sceDelegateProvider.resourceUrlWhitelist} and {@link
- * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- */
-
-/**
- * @ngdoc provider
- * @name $sceDelegateProvider
- * @description
- *
- * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
- * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
- * that the URLs used for sourcing Angular templates are safe. Refer {@link
- * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
- * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- *
- * For the general details about this service in Angular, read the main page for {@link ng.$sce
- * Strict Contextual Escaping (SCE)}.
- *
- * **Example**: Consider the following case. <a name="example"></a>
- *
- * - your app is hosted at url `http://myapp.example.com/`
- * - but some of your templates are hosted on other domains you control such as
- * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
- * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
- *
- * Here is what a secure configuration for this scenario might look like:
- *
- * ```
- * angular.module('myApp', []).config(function($sceDelegateProvider) {
- * $sceDelegateProvider.resourceUrlWhitelist([
- * // Allow same origin resource loads.
- * 'self',
- * // Allow loading from our assets domain. Notice the difference between * and **.
- * 'http://srv*.assets.example.com/**'
- * ]);
- *
- * // The blacklist overrides the whitelist so the open redirect here is blocked.
- * $sceDelegateProvider.resourceUrlBlacklist([
- * 'http://myapp.example.com/clickThru**'
- * ]);
- * });
- * ```
- */
-
-function $SceDelegateProvider() {
- this.SCE_CONTEXTS = SCE_CONTEXTS;
-
- // Resource URLs can also be trusted by policy.
- var resourceUrlWhitelist = ['self'],
- resourceUrlBlacklist = [];
-
- /**
- * @ngdoc method
- * @name $sceDelegateProvider#resourceUrlWhitelist
- * @kind function
- *
- * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
- *
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
- *
- * <div class="alert alert-warning">
- * **Note:** an empty whitelist array will block all URLs!
- * </div>
- *
- * @return {Array} the currently set whitelist array.
- *
- * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
- * same origin resource requests.
- *
- * @description
- * Sets/Gets the whitelist of trusted resource URLs.
- */
- this.resourceUrlWhitelist = function(value) {
- if (arguments.length) {
- resourceUrlWhitelist = adjustMatchers(value);
- }
- return resourceUrlWhitelist;
- };
-
- /**
- * @ngdoc method
- * @name $sceDelegateProvider#resourceUrlBlacklist
- * @kind function
- *
- * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
- *
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
- *
- * The typical usage for the blacklist is to **block
- * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
- * these would otherwise be trusted but actually return content from the redirected domain.
- *
- * Finally, **the blacklist overrides the whitelist** and has the final say.
- *
- * @return {Array} the currently set blacklist array.
- *
- * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
- * is no blacklist.)
- *
- * @description
- * Sets/Gets the blacklist of trusted resource URLs.
- */
-
- this.resourceUrlBlacklist = function(value) {
- if (arguments.length) {
- resourceUrlBlacklist = adjustMatchers(value);
- }
- return resourceUrlBlacklist;
- };
-
- this.$get = ['$injector', function($injector) {
-
- var htmlSanitizer = function htmlSanitizer(html) {
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- };
-
- if ($injector.has('$sanitize')) {
- htmlSanitizer = $injector.get('$sanitize');
- }
-
-
- function matchUrl(matcher, parsedUrl) {
- if (matcher === 'self') {
- return urlIsSameOrigin(parsedUrl);
- } else {
- // definitely a regex. See adjustMatchers()
- return !!matcher.exec(parsedUrl.href);
- }
- }
-
- function isResourceUrlAllowedByPolicy(url) {
- var parsedUrl = urlResolve(url.toString());
- var i, n, allowed = false;
- // Ensure that at least one item from the whitelist allows this url.
- for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
- if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
- allowed = true;
- break;
- }
- }
- if (allowed) {
- // Ensure that no item from the blacklist blocked this url.
- for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
- if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
- allowed = false;
- break;
- }
- }
- }
- return allowed;
- }
-
- function generateHolderType(Base) {
- var holderType = function TrustedValueHolderType(trustedValue) {
- this.$$unwrapTrustedValue = function() {
- return trustedValue;
- };
- };
- if (Base) {
- holderType.prototype = new Base();
- }
- holderType.prototype.valueOf = function sceValueOf() {
- return this.$$unwrapTrustedValue();
- };
- holderType.prototype.toString = function sceToString() {
- return this.$$unwrapTrustedValue().toString();
- };
- return holderType;
- }
-
- var trustedValueHolderBase = generateHolderType(),
- byType = {};
-
- byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
-
- /**
- * @ngdoc method
- * @name $sceDelegate#trustAs
- *
- * @description
- * Returns an object that is trusted by angular for use in specified strict
- * contextual escaping contexts (such as ng-bind-html, ng-include, any src
- * attribute interpolation, any dom event binding attribute interpolation
- * such as for onclick, etc.) that uses the provided value.
- * See {@link ng.$sce $sce} for enabling strict contextual escaping.
- *
- * @param {string} type The kind of context in which this value is safe for use. e.g. url,
- * resourceUrl, html, js and css.
- * @param {*} value The value that that should be considered trusted/safe.
- * @returns {*} A value that can be used to stand in for the provided `value` in places
- * where Angular expects a $sce.trustAs() return value.
- */
- function trustAs(type, trustedValue) {
- var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (!Constructor) {
- throw $sceMinErr('icontext',
- 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
- type, trustedValue);
- }
- if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
- return trustedValue;
- }
- // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
- // mutable objects, we ensure here that the value passed in is actually a string.
- if (typeof trustedValue !== 'string') {
- throw $sceMinErr('itype',
- 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
- type);
- }
- return new Constructor(trustedValue);
- }
-
- /**
- * @ngdoc method
- * @name $sceDelegate#valueOf
- *
- * @description
- * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
- * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
- *
- * If the passed parameter is not a value that had been returned by {@link
- * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
- *
- * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
- * call or anything else.
- * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
- * `value` unchanged.
- */
- function valueOf(maybeTrusted) {
- if (maybeTrusted instanceof trustedValueHolderBase) {
- return maybeTrusted.$$unwrapTrustedValue();
- } else {
- return maybeTrusted;
- }
- }
-
- /**
- * @ngdoc method
- * @name $sceDelegate#getTrusted
- *
- * @description
- * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
- * returns the originally supplied value if the queried context type is a supertype of the
- * created type. If this condition isn't satisfied, throws an exception.
- *
- * <div class="alert alert-danger">
- * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting
- * (XSS) vulnerability in your application.
- * </div>
- *
- * @param {string} type The kind of context in which this value is to be used.
- * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} call.
- * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
- */
- function getTrusted(type, maybeTrusted) {
- if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {
- return maybeTrusted;
- }
- var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (constructor && maybeTrusted instanceof constructor) {
- return maybeTrusted.$$unwrapTrustedValue();
- }
- // If we get here, then we may only take one of two actions.
- // 1. sanitize the value for the requested type, or
- // 2. throw an exception.
- if (type === SCE_CONTEXTS.RESOURCE_URL) {
- if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
- return maybeTrusted;
- } else {
- throw $sceMinErr('insecurl',
- 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
- maybeTrusted.toString());
- }
- } else if (type === SCE_CONTEXTS.HTML) {
- return htmlSanitizer(maybeTrusted);
- }
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- }
-
- return { trustAs: trustAs,
- getTrusted: getTrusted,
- valueOf: valueOf };
- }];
-}
-
-
-/**
- * @ngdoc provider
- * @name $sceProvider
- * @description
- *
- * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
- * - enable/disable Strict Contextual Escaping (SCE) in a module
- * - override the default implementation with a custom delegate
- *
- * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
- */
-
-/* jshint maxlen: false*/
-
-/**
- * @ngdoc service
- * @name $sce
- * @kind function
- *
- * @description
- *
- * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
- *
- * # Strict Contextual Escaping
- *
- * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
- * contexts to result in a value that is marked as safe to use for that context. One example of
- * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
- * to these contexts as privileged or SCE contexts.
- *
- * As of version 1.2, Angular ships with SCE enabled by default.
- *
- * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
- * one to execute arbitrary javascript by the use of the expression() syntax. Refer
- * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
- * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
- * to the top of your HTML document.
- *
- * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
- * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
- *
- * Here's an example of a binding in a privileged context:
- *
- * ```
- * <input ng-model="userHtml" aria-label="User input">
- * <div ng-bind-html="userHtml"></div>
- * ```
- *
- * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
- * disabled, this application allows the user to render arbitrary HTML into the DIV.
- * In a more realistic example, one may be rendering user comments, blog articles, etc. via
- * bindings. (HTML is just one example of a context where rendering user controlled input creates
- * security vulnerabilities.)
- *
- * For the case of HTML, you might use a library, either on the client side, or on the server side,
- * to sanitize unsafe HTML before binding to the value and rendering it in the document.
- *
- * How would you ensure that every place that used these types of bindings was bound to a value that
- * was sanitized by your library (or returned as safe for rendering by your server?) How can you
- * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
- * properties/fields and forgot to update the binding to the sanitized value?
- *
- * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
- * determine that something explicitly says it's safe to use a value for binding in that
- * context. You can then audit your code (a simple grep would do) to ensure that this is only done
- * for those values that you can easily tell are safe - because they were received from your server,
- * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
- * allowing only the files in a specific directory to do this. Ensuring that the internal API
- * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
- *
- * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
- * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
- * obtain values that will be accepted by SCE / privileged contexts.
- *
- *
- * ## How does it work?
- *
- * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
- * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
- * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
- * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
- *
- * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
- * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
- * simplified):
- *
- * ```
- * var ngBindHtmlDirective = ['$sce', function($sce) {
- * return function(scope, element, attr) {
- * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
- * element.html(value || '');
- * });
- * };
- * }];
- * ```
- *
- * ## Impact on loading templates
- *
- * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
- * `templateUrl`'s specified by {@link guide/directive directives}.
- *
- * By default, Angular only loads templates from the same domain and protocol as the application
- * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
- * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
- * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
- *
- * *Please note*:
- * The browser's
- * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
- * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
- * policy apply in addition to this and may further restrict whether the template is successfully
- * loaded. This means that without the right CORS policy, loading templates from a different domain
- * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
- * browsers.
- *
- * ## This feels like too much overhead
- *
- * It's important to remember that SCE only applies to interpolation expressions.
- *
- * If your expressions are constant literals, they're automatically trusted and you don't need to
- * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
- * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
- *
- * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
- * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
- *
- * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
- * templates in `ng-include` from your application's domain without having to even know about SCE.
- * It blocks loading templates from other domains or loading templates over http from an https
- * served document. You can change these by setting your own custom {@link
- * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
- * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
- *
- * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
- * application that's secure and can be audited to verify that with much more ease than bolting
- * security onto an application later.
- *
- * <a name="contexts"></a>
- * ## What trusted context types are supported?
- *
- * | Context | Notes |
- * |---------------------|----------------|
- * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
- * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
- * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
- * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
- * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
- *
- * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
- *
- * Each element in these arrays must be one of the following:
- *
- * - **'self'**
- * - The special **string**, `'self'`, can be used to match against all URLs of the **same
- * domain** as the application document using the **same protocol**.
- * - **String** (except the special value `'self'`)
- * - The string is matched against the full *normalized / absolute URL* of the resource
- * being tested (substring matches are not good enough.)
- * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
- * match themselves.
- * - `*`: matches zero or more occurrences of any character other than one of the following 6
- * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use
- * in a whitelist.
- * - `**`: matches zero or more occurrences of *any* character. As such, it's not
- * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.
- * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
- * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
- * http://foo.example.com/templates/**).
- * - **RegExp** (*see caveat below*)
- * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
- * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
- * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
- * have good test coverage). For instance, the use of `.` in the regex is correct only in a
- * small number of cases. A `.` character in the regex used when matching the scheme or a
- * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
- * is highly recommended to use the string patterns and only fall back to regular expressions
- * as a last resort.
- * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
- * matched against the **entire** *normalized / absolute URL* of the resource being tested
- * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
- * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
- * - If you are generating your JavaScript from some other templating engine (not
- * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
- * remember to escape your regular expression (and be aware that you might need more than
- * one level of escaping depending on your templating engine and the way you interpolated
- * the value.) Do make use of your platform's escaping mechanism as it might be good
- * enough before coding your own. E.g. Ruby has
- * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
- * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
- * Javascript lacks a similar built in function for escaping. Take a look at Google
- * Closure library's [goog.string.regExpEscape(s)](
- * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
- *
- * ## Show me an example using SCE.
- *
- * <example module="mySceApp" deps="angular-sanitize.js">
- * <file name="index.html">
- * <div ng-controller="AppController as myCtrl">
- * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
- * <b>User comments</b><br>
- * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
- * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
- * exploit.
- * <div class="well">
- * <div ng-repeat="userComment in myCtrl.userComments">
- * <b>{{userComment.name}}</b>:
- * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
- * <br>
- * </div>
- * </div>
- * </div>
- * </file>
- *
- * <file name="script.js">
- * angular.module('mySceApp', ['ngSanitize'])
- * .controller('AppController', ['$http', '$templateCache', '$sce',
- * function($http, $templateCache, $sce) {
- * var self = this;
- * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
- * self.userComments = userComments;
- * });
- * self.explicitlyTrustedHtml = $sce.trustAsHtml(
- * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
- * 'sanitization.&quot;">Hover over this text.</span>');
- * }]);
- * </file>
- *
- * <file name="test_data.json">
- * [
- * { "name": "Alice",
- * "htmlComment":
- * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
- * },
- * { "name": "Bob",
- * "htmlComment": "<i>Yes!</i> Am I the only other one?"
- * }
- * ]
- * </file>
- *
- * <file name="protractor.js" type="protractor">
- * describe('SCE doc demo', function() {
- * it('should sanitize untrusted values', function() {
- * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
- * .toBe('<span>Is <i>anyone</i> reading this?</span>');
- * });
- *
- * it('should NOT sanitize explicitly trusted values', function() {
- * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
- * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
- * 'sanitization.&quot;">Hover over this text.</span>');
- * });
- * });
- * </file>
- * </example>
- *
- *
- *
- * ## Can I disable SCE completely?
- *
- * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
- * for little coding overhead. It will be much harder to take an SCE disabled application and
- * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
- * for cases where you have a lot of existing code that was written before SCE was introduced and
- * you're migrating them a module at a time.
- *
- * That said, here's how you can completely disable SCE:
- *
- * ```
- * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
- * // Completely disable SCE. For demonstration purposes only!
- * // Do not use in new projects.
- * $sceProvider.enabled(false);
- * });
- * ```
- *
- */
-/* jshint maxlen: 100 */
-
-function $SceProvider() {
- var enabled = true;
-
- /**
- * @ngdoc method
- * @name $sceProvider#enabled
- * @kind function
- *
- * @param {boolean=} value If provided, then enables/disables SCE.
- * @return {boolean} true if SCE is enabled, false otherwise.
- *
- * @description
- * Enables/disables SCE and returns the current value.
- */
- this.enabled = function(value) {
- if (arguments.length) {
- enabled = !!value;
- }
- return enabled;
- };
-
-
- /* Design notes on the default implementation for SCE.
- *
- * The API contract for the SCE delegate
- * -------------------------------------
- * The SCE delegate object must provide the following 3 methods:
- *
- * - trustAs(contextEnum, value)
- * This method is used to tell the SCE service that the provided value is OK to use in the
- * contexts specified by contextEnum. It must return an object that will be accepted by
- * getTrusted() for a compatible contextEnum and return this value.
- *
- * - valueOf(value)
- * For values that were not produced by trustAs(), return them as is. For values that were
- * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
- * trustAs is wrapping the given values into some type, this operation unwraps it when given
- * such a value.
- *
- * - getTrusted(contextEnum, value)
- * This function should return the a value that is safe to use in the context specified by
- * contextEnum or throw and exception otherwise.
- *
- * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
- * opaque or wrapped in some holder object. That happens to be an implementation detail. For
- * instance, an implementation could maintain a registry of all trusted objects by context. In
- * such a case, trustAs() would return the same object that was passed in. getTrusted() would
- * return the same object passed in if it was found in the registry under a compatible context or
- * throw an exception otherwise. An implementation might only wrap values some of the time based
- * on some criteria. getTrusted() might return a value and not throw an exception for special
- * constants or objects even if not wrapped. All such implementations fulfill this contract.
- *
- *
- * A note on the inheritance model for SCE contexts
- * ------------------------------------------------
- * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
- * is purely an implementation details.
- *
- * The contract is simply this:
- *
- * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
- * will also succeed.
- *
- * Inheritance happens to capture this in a natural way. In some future, we
- * may not use inheritance anymore. That is OK because no code outside of
- * sce.js and sceSpecs.js would need to be aware of this detail.
- */
-
- this.$get = ['$parse', '$sceDelegate', function(
- $parse, $sceDelegate) {
- // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
- // the "expression(javascript expression)" syntax which is insecure.
- if (enabled && msie < 8) {
- throw $sceMinErr('iequirks',
- 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
- 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
- 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
- }
-
- var sce = shallowCopy(SCE_CONTEXTS);
-
- /**
- * @ngdoc method
- * @name $sce#isEnabled
- * @kind function
- *
- * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
- * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
- *
- * @description
- * Returns a boolean indicating if SCE is enabled.
- */
- sce.isEnabled = function() {
- return enabled;
- };
- sce.trustAs = $sceDelegate.trustAs;
- sce.getTrusted = $sceDelegate.getTrusted;
- sce.valueOf = $sceDelegate.valueOf;
-
- if (!enabled) {
- sce.trustAs = sce.getTrusted = function(type, value) { return value; };
- sce.valueOf = identity;
- }
-
- /**
- * @ngdoc method
- * @name $sce#parseAs
- *
- * @description
- * Converts Angular {@link guide/expression expression} into a function. This is like {@link
- * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
- * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
- * *result*)}
- *
- * @param {string} type The kind of SCE context in which this result will be used.
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
- sce.parseAs = function sceParseAs(type, expr) {
- var parsed = $parse(expr);
- if (parsed.literal && parsed.constant) {
- return parsed;
- } else {
- return $parse(expr, function(value) {
- return sce.getTrusted(type, value);
- });
- }
- };
-
- /**
- * @ngdoc method
- * @name $sce#trustAs
- *
- * @description
- * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
- * returns an object that is trusted by angular for use in specified strict contextual
- * escaping contexts (such as ng-bind-html, ng-include, any src attribute
- * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
- * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
- * escaping.
- *
- * @param {string} type The kind of context in which this value is safe for use. e.g. url,
- * resourceUrl, html, js and css.
- * @param {*} value The value that that should be considered trusted/safe.
- * @returns {*} A value that can be used to stand in for the provided `value` in places
- * where Angular expects a $sce.trustAs() return value.
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsHtml
- *
- * @description
- * Shorthand method. `$sce.trustAsHtml(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
- * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsUrl
- *
- * @description
- * Shorthand method. `$sce.trustAsUrl(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
- * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsResourceUrl
- *
- * @description
- * Shorthand method. `$sce.trustAsResourceUrl(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the return
- * value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsJs
- *
- * @description
- * Shorthand method. `$sce.trustAsJs(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
- * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrusted
- *
- * @description
- * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
- * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
- * originally supplied value if the queried context type is a supertype of the created type.
- * If this condition isn't satisfied, throws an exception.
- *
- * @param {string} type The kind of context in which this value is to be used.
- * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
- * call.
- * @returns {*} The value the was originally provided to
- * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
- * Otherwise, throws an exception.
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedHtml
- *
- * @description
- * Shorthand method. `$sce.getTrustedHtml(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedCss
- *
- * @description
- * Shorthand method. `$sce.getTrustedCss(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedUrl
- *
- * @description
- * Shorthand method. `$sce.getTrustedUrl(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedResourceUrl
- *
- * @description
- * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
- *
- * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedJs
- *
- * @description
- * Shorthand method. `$sce.getTrustedJs(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsHtml
- *
- * @description
- * Shorthand method. `$sce.parseAsHtml(expression string)` →
- * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsCss
- *
- * @description
- * Shorthand method. `$sce.parseAsCss(value)` →
- * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsUrl
- *
- * @description
- * Shorthand method. `$sce.parseAsUrl(value)` →
- * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsResourceUrl
- *
- * @description
- * Shorthand method. `$sce.parseAsResourceUrl(value)` →
- * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsJs
- *
- * @description
- * Shorthand method. `$sce.parseAsJs(value)` →
- * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- // Shorthand delegations.
- var parse = sce.parseAs,
- getTrusted = sce.getTrusted,
- trustAs = sce.trustAs;
-
- forEach(SCE_CONTEXTS, function(enumValue, name) {
- var lName = lowercase(name);
- sce[camelCase("parse_as_" + lName)] = function(expr) {
- return parse(enumValue, expr);
- };
- sce[camelCase("get_trusted_" + lName)] = function(value) {
- return getTrusted(enumValue, value);
- };
- sce[camelCase("trust_as_" + lName)] = function(value) {
- return trustAs(enumValue, value);
- };
- });
-
- return sce;
- }];
-}
-
-/**
- * !!! This is an undocumented "private" service !!!
- *
- * @name $sniffer
- * @requires $window
- * @requires $document
- *
- * @property {boolean} history Does the browser support html5 history api ?
- * @property {boolean} transitions Does the browser support CSS transition events ?
- * @property {boolean} animations Does the browser support CSS animation events ?
- *
- * @description
- * This is very simple implementation of testing browser's features.
- */
-function $SnifferProvider() {
- this.$get = ['$window', '$document', function($window, $document) {
- var eventSupport = {},
- android =
- toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
- boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
- document = $document[0] || {},
- vendorPrefix,
- vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
- bodyStyle = document.body && document.body.style,
- transitions = false,
- animations = false,
- match;
-
- if (bodyStyle) {
- for (var prop in bodyStyle) {
- if (match = vendorRegex.exec(prop)) {
- vendorPrefix = match[0];
- vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
- break;
- }
- }
-
- if (!vendorPrefix) {
- vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
- }
-
- transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
- animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
-
- if (android && (!transitions || !animations)) {
- transitions = isString(bodyStyle.webkitTransition);
- animations = isString(bodyStyle.webkitAnimation);
- }
- }
-
-
- return {
- // Android has history.pushState, but it does not update location correctly
- // so let's not use the history API at all.
- // http://code.google.com/p/android/issues/detail?id=17471
- // https://github.com/angular/angular.js/issues/904
-
- // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
- // so let's not use the history API also
- // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
- // jshint -W018
- history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
- // jshint +W018
- hasEvent: function(event) {
- // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
- // it. In particular the event is not fired when backspace or delete key are pressed or
- // when cut operation is performed.
- // IE10+ implements 'input' event but it erroneously fires under various situations,
- // e.g. when placeholder changes, or a form is focused.
- if (event === 'input' && msie <= 11) return false;
-
- if (isUndefined(eventSupport[event])) {
- var divElm = document.createElement('div');
- eventSupport[event] = 'on' + event in divElm;
- }
-
- return eventSupport[event];
- },
- csp: csp(),
- vendorPrefix: vendorPrefix,
- transitions: transitions,
- animations: animations,
- android: android
- };
- }];
-}
-
-var $compileMinErr = minErr('$compile');
-
-/**
- * @ngdoc provider
- * @name $templateRequestProvider
- * @description
- * Used to configure the options passed to the {@link $http} service when making a template request.
- *
- * For example, it can be used for specifying the "Accept" header that is sent to the server, when
- * requesting a template.
- */
-function $TemplateRequestProvider() {
-
- var httpOptions;
-
- /**
- * @ngdoc method
- * @name $templateRequestProvider#httpOptions
- * @description
- * The options to be passed to the {@link $http} service when making the request.
- * You can use this to override options such as the "Accept" header for template requests.
- *
- * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the
- * options if not overridden here.
- *
- * @param {string=} value new value for the {@link $http} options.
- * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter.
- */
- this.httpOptions = function(val) {
- if (val) {
- httpOptions = val;
- return this;
- }
- return httpOptions;
- };
-
- /**
- * @ngdoc service
- * @name $templateRequest
- *
- * @description
- * The `$templateRequest` service runs security checks then downloads the provided template using
- * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
- * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
- * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
- * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
- * when `tpl` is of type string and `$templateCache` has the matching entry.
- *
- * If you want to pass custom options to the `$http` service, such as setting the Accept header you
- * can configure this via {@link $templateRequestProvider#httpOptions}.
- *
- * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
- * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
- *
- * @return {Promise} a promise for the HTTP response data of the given URL.
- *
- * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
- */
- this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
-
- function handleRequestFn(tpl, ignoreRequestError) {
- handleRequestFn.totalPendingRequests++;
-
- // We consider the template cache holds only trusted templates, so
- // there's no need to go through whitelisting again for keys that already
- // are included in there. This also makes Angular accept any script
- // directive, no matter its name. However, we still need to unwrap trusted
- // types.
- if (!isString(tpl) || !$templateCache.get(tpl)) {
- tpl = $sce.getTrustedResourceUrl(tpl);
- }
-
- var transformResponse = $http.defaults && $http.defaults.transformResponse;
-
- if (isArray(transformResponse)) {
- transformResponse = transformResponse.filter(function(transformer) {
- return transformer !== defaultHttpResponseTransform;
- });
- } else if (transformResponse === defaultHttpResponseTransform) {
- transformResponse = null;
- }
-
- return $http.get(tpl, extend({
- cache: $templateCache,
- transformResponse: transformResponse
- }, httpOptions))
- ['finally'](function() {
- handleRequestFn.totalPendingRequests--;
- })
- .then(function(response) {
- $templateCache.put(tpl, response.data);
- return response.data;
- }, handleError);
-
- function handleError(resp) {
- if (!ignoreRequestError) {
- throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})',
- tpl, resp.status, resp.statusText);
- }
- return $q.reject(resp);
- }
- }
-
- handleRequestFn.totalPendingRequests = 0;
-
- return handleRequestFn;
- }];
-}
-
-function $$TestabilityProvider() {
- this.$get = ['$rootScope', '$browser', '$location',
- function($rootScope, $browser, $location) {
-
- /**
- * @name $testability
- *
- * @description
- * The private $$testability service provides a collection of methods for use when debugging
- * or by automated test and debugging tools.
- */
- var testability = {};
-
- /**
- * @name $$testability#findBindings
- *
- * @description
- * Returns an array of elements that are bound (via ng-bind or {{}})
- * to expressions matching the input.
- *
- * @param {Element} element The element root to search from.
- * @param {string} expression The binding expression to match.
- * @param {boolean} opt_exactMatch If true, only returns exact matches
- * for the expression. Filters and whitespace are ignored.
- */
- testability.findBindings = function(element, expression, opt_exactMatch) {
- var bindings = element.getElementsByClassName('ng-binding');
- var matches = [];
- forEach(bindings, function(binding) {
- var dataBinding = angular.element(binding).data('$binding');
- if (dataBinding) {
- forEach(dataBinding, function(bindingName) {
- if (opt_exactMatch) {
- var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
- if (matcher.test(bindingName)) {
- matches.push(binding);
- }
- } else {
- if (bindingName.indexOf(expression) != -1) {
- matches.push(binding);
- }
- }
- });
- }
- });
- return matches;
- };
-
- /**
- * @name $$testability#findModels
- *
- * @description
- * Returns an array of elements that are two-way found via ng-model to
- * expressions matching the input.
- *
- * @param {Element} element The element root to search from.
- * @param {string} expression The model expression to match.
- * @param {boolean} opt_exactMatch If true, only returns exact matches
- * for the expression.
- */
- testability.findModels = function(element, expression, opt_exactMatch) {
- var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
- for (var p = 0; p < prefixes.length; ++p) {
- var attributeEquals = opt_exactMatch ? '=' : '*=';
- var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
- var elements = element.querySelectorAll(selector);
- if (elements.length) {
- return elements;
- }
- }
- };
-
- /**
- * @name $$testability#getLocation
- *
- * @description
- * Shortcut for getting the location in a browser agnostic way. Returns
- * the path, search, and hash. (e.g. /path?a=b#hash)
- */
- testability.getLocation = function() {
- return $location.url();
- };
-
- /**
- * @name $$testability#setLocation
- *
- * @description
- * Shortcut for navigating to a location without doing a full page reload.
- *
- * @param {string} url The location url (path, search and hash,
- * e.g. /path?a=b#hash) to go to.
- */
- testability.setLocation = function(url) {
- if (url !== $location.url()) {
- $location.url(url);
- $rootScope.$digest();
- }
- };
-
- /**
- * @name $$testability#whenStable
- *
- * @description
- * Calls the callback when $timeout and $http requests are completed.
- *
- * @param {function} callback
- */
- testability.whenStable = function(callback) {
- $browser.notifyWhenNoOutstandingRequests(callback);
- };
-
- return testability;
- }];
-}
-
-function $TimeoutProvider() {
- this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
- function($rootScope, $browser, $q, $$q, $exceptionHandler) {
-
- var deferreds = {};
-
-
- /**
- * @ngdoc service
- * @name $timeout
- *
- * @description
- * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
- * block and delegates any exceptions to
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * The return value of calling `$timeout` is a promise, which will be resolved when
- * the delay has passed and the timeout function, if provided, is executed.
- *
- * To cancel a timeout request, call `$timeout.cancel(promise)`.
- *
- * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
- * synchronously flush the queue of deferred functions.
- *
- * If you only want a promise that will be resolved after some specified delay
- * then you can call `$timeout` without the `fn` function.
- *
- * @param {function()=} fn A function, whose execution should be delayed.
- * @param {number=} [delay=0] Delay in milliseconds.
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
- * @param {...*=} Pass additional parameters to the executed function.
- * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise
- * will be resolved with the return value of the `fn` function.
- *
- */
- function timeout(fn, delay, invokeApply) {
- if (!isFunction(fn)) {
- invokeApply = delay;
- delay = fn;
- fn = noop;
- }
-
- var args = sliceArgs(arguments, 3),
- skipApply = (isDefined(invokeApply) && !invokeApply),
- deferred = (skipApply ? $$q : $q).defer(),
- promise = deferred.promise,
- timeoutId;
-
- timeoutId = $browser.defer(function() {
- try {
- deferred.resolve(fn.apply(null, args));
- } catch (e) {
- deferred.reject(e);
- $exceptionHandler(e);
- }
- finally {
- delete deferreds[promise.$$timeoutId];
- }
-
- if (!skipApply) $rootScope.$apply();
- }, delay);
-
- promise.$$timeoutId = timeoutId;
- deferreds[timeoutId] = deferred;
-
- return promise;
- }
-
-
- /**
- * @ngdoc method
- * @name $timeout#cancel
- *
- * @description
- * Cancels a task associated with the `promise`. As a result of this, the promise will be
- * resolved with a rejection.
- *
- * @param {Promise=} promise Promise returned by the `$timeout` function.
- * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
- * canceled.
- */
- timeout.cancel = function(promise) {
- if (promise && promise.$$timeoutId in deferreds) {
- deferreds[promise.$$timeoutId].reject('canceled');
- delete deferreds[promise.$$timeoutId];
- return $browser.defer.cancel(promise.$$timeoutId);
- }
- return false;
- };
-
- return timeout;
- }];
-}
-
-// NOTE: The usage of window and document instead of $window and $document here is
-// deliberate. This service depends on the specific behavior of anchor nodes created by the
-// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
-// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
-// doesn't know about mocked locations and resolves URLs to the real document - which is
-// exactly the behavior needed here. There is little value is mocking these out for this
-// service.
-var urlParsingNode = document.createElement("a");
-var originUrl = urlResolve(window.location.href);
-
-
-/**
- *
- * Implementation Notes for non-IE browsers
- * ----------------------------------------
- * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
- * results both in the normalizing and parsing of the URL. Normalizing means that a relative
- * URL will be resolved into an absolute URL in the context of the application document.
- * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
- * properties are all populated to reflect the normalized URL. This approach has wide
- * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
- * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- *
- * Implementation Notes for IE
- * ---------------------------
- * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
- * browsers. However, the parsed components will not be set if the URL assigned did not specify
- * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
- * work around that by performing the parsing in a 2nd step by taking a previously normalized
- * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
- * properties such as protocol, hostname, port, etc.
- *
- * References:
- * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
- * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- * http://url.spec.whatwg.org/#urlutils
- * https://github.com/angular/angular.js/pull/2902
- * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
- *
- * @kind function
- * @param {string} url The URL to be parsed.
- * @description Normalizes and parses a URL.
- * @returns {object} Returns the normalized URL as a dictionary.
- *
- * | member name | Description |
- * |---------------|----------------|
- * | href | A normalized version of the provided URL if it was not an absolute URL |
- * | protocol | The protocol including the trailing colon |
- * | host | The host and port (if the port is non-default) of the normalizedUrl |
- * | search | The search params, minus the question mark |
- * | hash | The hash string, minus the hash symbol
- * | hostname | The hostname
- * | port | The port, without ":"
- * | pathname | The pathname, beginning with "/"
- *
- */
-function urlResolve(url) {
- var href = url;
-
- if (msie) {
- // Normalize before parse. Refer Implementation Notes on why this is
- // done in two steps on IE.
- urlParsingNode.setAttribute("href", href);
- href = urlParsingNode.href;
- }
-
- urlParsingNode.setAttribute('href', href);
-
- // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
- return {
- href: urlParsingNode.href,
- protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
- host: urlParsingNode.host,
- search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
- hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
- hostname: urlParsingNode.hostname,
- port: urlParsingNode.port,
- pathname: (urlParsingNode.pathname.charAt(0) === '/')
- ? urlParsingNode.pathname
- : '/' + urlParsingNode.pathname
- };
-}
-
-/**
- * Parse a request URL and determine whether this is a same-origin request as the application document.
- *
- * @param {string|object} requestUrl The url of the request as a string that will be resolved
- * or a parsed URL object.
- * @returns {boolean} Whether the request is for the same origin as the application document.
- */
-function urlIsSameOrigin(requestUrl) {
- var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
- return (parsed.protocol === originUrl.protocol &&
- parsed.host === originUrl.host);
-}
-
-/**
- * @ngdoc service
- * @name $window
- *
- * @description
- * A reference to the browser's `window` object. While `window`
- * is globally available in JavaScript, it causes testability problems, because
- * it is a global variable. In angular we always refer to it through the
- * `$window` service, so it may be overridden, removed or mocked for testing.
- *
- * Expressions, like the one defined for the `ngClick` directive in the example
- * below, are evaluated with respect to the current scope. Therefore, there is
- * no risk of inadvertently coding in a dependency on a global value in such an
- * expression.
- *
- * @example
- <example module="windowExample">
- <file name="index.html">
- <script>
- angular.module('windowExample', [])
- .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
- $scope.greeting = 'Hello, World!';
- $scope.doGreeting = function(greeting) {
- $window.alert(greeting);
- };
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input type="text" ng-model="greeting" aria-label="greeting" />
- <button ng-click="doGreeting(greeting)">ALERT</button>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should display the greeting in the input box', function() {
- element(by.model('greeting')).sendKeys('Hello, E2E Tests');
- // If we click the button it will block the test runner
- // element(':button').click();
- });
- </file>
- </example>
- */
-function $WindowProvider() {
- this.$get = valueFn(window);
-}
-
-/**
- * @name $$cookieReader
- * @requires $document
- *
- * @description
- * This is a private service for reading cookies used by $http and ngCookies
- *
- * @return {Object} a key/value map of the current cookies
- */
-function $$CookieReader($document) {
- var rawDocument = $document[0] || {};
- var lastCookies = {};
- var lastCookieString = '';
-
- function safeDecodeURIComponent(str) {
- try {
- return decodeURIComponent(str);
- } catch (e) {
- return str;
- }
- }
-
- return function() {
- var cookieArray, cookie, i, index, name;
- var currentCookieString = rawDocument.cookie || '';
-
- if (currentCookieString !== lastCookieString) {
- lastCookieString = currentCookieString;
- cookieArray = lastCookieString.split('; ');
- lastCookies = {};
-
- for (i = 0; i < cookieArray.length; i++) {
- cookie = cookieArray[i];
- index = cookie.indexOf('=');
- if (index > 0) { //ignore nameless cookies
- name = safeDecodeURIComponent(cookie.substring(0, index));
- // the first value that is seen for a cookie is the most
- // specific one. values for the same cookie name that
- // follow are for less specific paths.
- if (isUndefined(lastCookies[name])) {
- lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
- }
- }
- }
- }
- return lastCookies;
- };
-}
-
-$$CookieReader.$inject = ['$document'];
-
-function $$CookieReaderProvider() {
- this.$get = $$CookieReader;
-}
-
-/* global currencyFilter: true,
- dateFilter: true,
- filterFilter: true,
- jsonFilter: true,
- limitToFilter: true,
- lowercaseFilter: true,
- numberFilter: true,
- orderByFilter: true,
- uppercaseFilter: true,
- */
-
-/**
- * @ngdoc provider
- * @name $filterProvider
- * @description
- *
- * Filters are just functions which transform input to an output. However filters need to be
- * Dependency Injected. To achieve this a filter definition consists of a factory function which is
- * annotated with dependencies and is responsible for creating a filter function.
- *
- * <div class="alert alert-warning">
- * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
- * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
- * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
- * (`myapp_subsection_filterx`).
- * </div>
- *
- * ```js
- * // Filter registration
- * function MyModule($provide, $filterProvider) {
- * // create a service to demonstrate injection (not always needed)
- * $provide.value('greet', function(name){
- * return 'Hello ' + name + '!';
- * });
- *
- * // register a filter factory which uses the
- * // greet service to demonstrate DI.
- * $filterProvider.register('greet', function(greet){
- * // return the filter function which uses the greet service
- * // to generate salutation
- * return function(text) {
- * // filters need to be forgiving so check input validity
- * return text && greet(text) || text;
- * };
- * });
- * }
- * ```
- *
- * The filter function is registered with the `$injector` under the filter name suffix with
- * `Filter`.
- *
- * ```js
- * it('should be the same instance', inject(
- * function($filterProvider) {
- * $filterProvider.register('reverse', function(){
- * return ...;
- * });
- * },
- * function($filter, reverseFilter) {
- * expect($filter('reverse')).toBe(reverseFilter);
- * });
- * ```
- *
- *
- * For more information about how angular filters work, and how to create your own filters, see
- * {@link guide/filter Filters} in the Angular Developer Guide.
- */
-
-/**
- * @ngdoc service
- * @name $filter
- * @kind function
- * @description
- * Filters are used for formatting data displayed to the user.
- *
- * The general syntax in templates is as follows:
- *
- * {{ expression [| filter_name[:parameter_value] ... ] }}
- *
- * @param {String} name Name of the filter function to retrieve
- * @return {Function} the filter function
- * @example
- <example name="$filter" module="filterExample">
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <h3>{{ originalText }}</h3>
- <h3>{{ filteredText }}</h3>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('filterExample', [])
- .controller('MainCtrl', function($scope, $filter) {
- $scope.originalText = 'hello';
- $scope.filteredText = $filter('uppercase')($scope.originalText);
- });
- </file>
- </example>
- */
-$FilterProvider.$inject = ['$provide'];
-function $FilterProvider($provide) {
- var suffix = 'Filter';
-
- /**
- * @ngdoc method
- * @name $filterProvider#register
- * @param {string|Object} name Name of the filter function, or an object map of filters where
- * the keys are the filter names and the values are the filter factories.
- *
- * <div class="alert alert-warning">
- * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
- * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
- * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
- * (`myapp_subsection_filterx`).
- * </div>
- * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.
- * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
- * of the registered filter instances.
- */
- function register(name, factory) {
- if (isObject(name)) {
- var filters = {};
- forEach(name, function(filter, key) {
- filters[key] = register(key, filter);
- });
- return filters;
- } else {
- return $provide.factory(name + suffix, factory);
- }
- }
- this.register = register;
-
- this.$get = ['$injector', function($injector) {
- return function(name) {
- return $injector.get(name + suffix);
- };
- }];
-
- ////////////////////////////////////////
-
- /* global
- currencyFilter: false,
- dateFilter: false,
- filterFilter: false,
- jsonFilter: false,
- limitToFilter: false,
- lowercaseFilter: false,
- numberFilter: false,
- orderByFilter: false,
- uppercaseFilter: false,
- */
-
- register('currency', currencyFilter);
- register('date', dateFilter);
- register('filter', filterFilter);
- register('json', jsonFilter);
- register('limitTo', limitToFilter);
- register('lowercase', lowercaseFilter);
- register('number', numberFilter);
- register('orderBy', orderByFilter);
- register('uppercase', uppercaseFilter);
-}
-
-/**
- * @ngdoc filter
- * @name filter
- * @kind function
- *
- * @description
- * Selects a subset of items from `array` and returns it as a new array.
- *
- * @param {Array} array The source array.
- * @param {string|Object|function()} expression The predicate to be used for selecting items from
- * `array`.
- *
- * Can be one of:
- *
- * - `string`: The string is used for matching against the contents of the `array`. All strings or
- * objects with string properties in `array` that match this string will be returned. This also
- * applies to nested object properties.
- * The predicate can be negated by prefixing the string with `!`.
- *
- * - `Object`: A pattern object can be used to filter specific properties on objects contained
- * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
- * which have property `name` containing "M" and property `phone` containing "1". A special
- * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
- * property of the object or its nested object properties. That's equivalent to the simple
- * substring match with a `string` as described above. The predicate can be negated by prefixing
- * the string with `!`.
- * For example `{name: "!M"}` predicate will return an array of items which have property `name`
- * not containing "M".
- *
- * Note that a named property will match properties on the same level only, while the special
- * `$` property will match properties on the same level or deeper. E.g. an array item like
- * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
- * **will** be matched by `{$: 'John'}`.
- *
- * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
- * The function is called for each element of the array, with the element, its index, and
- * the entire array itself as arguments.
- *
- * The final result is an array of those elements that the predicate returned true for.
- *
- * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
- * determining if the expected value (from the filter expression) and actual value (from
- * the object in the array) should be considered a match.
- *
- * Can be one of:
- *
- * - `function(actual, expected)`:
- * The function will be given the object value and the predicate value to compare and
- * should return true if both values should be considered equal.
- *
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
- * This is essentially strict comparison of expected and actual.
- *
- * - `false|undefined`: A short hand for a function which will look for a substring match in case
- * insensitive way.
- *
- * Primitive values are converted to strings. Objects are not compared against primitives,
- * unless they have a custom `toString` method (e.g. `Date` objects).
- *
- * @example
- <example>
- <file name="index.html">
- <div ng-init="friends = [{name:'John', phone:'555-1276'},
- {name:'Mary', phone:'800-BIG-MARY'},
- {name:'Mike', phone:'555-4321'},
- {name:'Adam', phone:'555-5678'},
- {name:'Julie', phone:'555-8765'},
- {name:'Juliette', phone:'555-5678'}]"></div>
-
- <label>Search: <input ng-model="searchText"></label>
- <table id="searchTextResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friend in friends | filter:searchText">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- </tr>
- </table>
- <hr>
- <label>Any: <input ng-model="search.$"></label> <br>
- <label>Name only <input ng-model="search.name"></label><br>
- <label>Phone only <input ng-model="search.phone"></label><br>
- <label>Equality <input type="checkbox" ng-model="strict"></label><br>
- <table id="searchObjResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friendObj in friends | filter:search:strict">
- <td>{{friendObj.name}}</td>
- <td>{{friendObj.phone}}</td>
- </tr>
- </table>
- </file>
- <file name="protractor.js" type="protractor">
- var expectFriendNames = function(expectedNames, key) {
- element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
- arr.forEach(function(wd, i) {
- expect(wd.getText()).toMatch(expectedNames[i]);
- });
- });
- };
-
- it('should search across all fields when filtering with a string', function() {
- var searchText = element(by.model('searchText'));
- searchText.clear();
- searchText.sendKeys('m');
- expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
-
- searchText.clear();
- searchText.sendKeys('76');
- expectFriendNames(['John', 'Julie'], 'friend');
- });
-
- it('should search in specific fields when filtering with a predicate object', function() {
- var searchAny = element(by.model('search.$'));
- searchAny.clear();
- searchAny.sendKeys('i');
- expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
- });
- it('should use a equal comparison when comparator is true', function() {
- var searchName = element(by.model('search.name'));
- var strict = element(by.model('strict'));
- searchName.clear();
- searchName.sendKeys('Julie');
- strict.click();
- expectFriendNames(['Julie'], 'friendObj');
- });
- </file>
- </example>
- */
-function filterFilter() {
- return function(array, expression, comparator) {
- if (!isArrayLike(array)) {
- if (array == null) {
- return array;
- } else {
- throw minErr('filter')('notarray', 'Expected array but received: {0}', array);
- }
- }
-
- var expressionType = getTypeForFilter(expression);
- var predicateFn;
- var matchAgainstAnyProp;
-
- switch (expressionType) {
- case 'function':
- predicateFn = expression;
- break;
- case 'boolean':
- case 'null':
- case 'number':
- case 'string':
- matchAgainstAnyProp = true;
- //jshint -W086
- case 'object':
- //jshint +W086
- predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
- break;
- default:
- return array;
- }
-
- return Array.prototype.filter.call(array, predicateFn);
- };
-}
-
-// Helper functions for `filterFilter`
-function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
- var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
- var predicateFn;
-
- if (comparator === true) {
- comparator = equals;
- } else if (!isFunction(comparator)) {
- comparator = function(actual, expected) {
- if (isUndefined(actual)) {
- // No substring matching against `undefined`
- return false;
- }
- if ((actual === null) || (expected === null)) {
- // No substring matching against `null`; only match against `null`
- return actual === expected;
- }
- if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {
- // Should not compare primitives against objects, unless they have custom `toString` method
- return false;
- }
-
- actual = lowercase('' + actual);
- expected = lowercase('' + expected);
- return actual.indexOf(expected) !== -1;
- };
- }
-
- predicateFn = function(item) {
- if (shouldMatchPrimitives && !isObject(item)) {
- return deepCompare(item, expression.$, comparator, false);
- }
- return deepCompare(item, expression, comparator, matchAgainstAnyProp);
- };
-
- return predicateFn;
-}
-
-function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
- var actualType = getTypeForFilter(actual);
- var expectedType = getTypeForFilter(expected);
-
- if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
- return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
- } else if (isArray(actual)) {
- // In case `actual` is an array, consider it a match
- // if ANY of it's items matches `expected`
- return actual.some(function(item) {
- return deepCompare(item, expected, comparator, matchAgainstAnyProp);
- });
- }
-
- switch (actualType) {
- case 'object':
- var key;
- if (matchAgainstAnyProp) {
- for (key in actual) {
- if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
- return true;
- }
- }
- return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
- } else if (expectedType === 'object') {
- for (key in expected) {
- var expectedVal = expected[key];
- if (isFunction(expectedVal) || isUndefined(expectedVal)) {
- continue;
- }
-
- var matchAnyProperty = key === '$';
- var actualVal = matchAnyProperty ? actual : actual[key];
- if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
- return false;
- }
- }
- return true;
- } else {
- return comparator(actual, expected);
- }
- break;
- case 'function':
- return false;
- default:
- return comparator(actual, expected);
- }
-}
-
-// Used for easily differentiating between `null` and actual `object`
-function getTypeForFilter(val) {
- return (val === null) ? 'null' : typeof val;
-}
-
-var MAX_DIGITS = 22;
-var DECIMAL_SEP = '.';
-var ZERO_CHAR = '0';
-
-/**
- * @ngdoc filter
- * @name currency
- * @kind function
- *
- * @description
- * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
- * symbol for current locale is used.
- *
- * @param {number} amount Input to filter.
- * @param {string=} symbol Currency symbol or identifier to be displayed.
- * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
- * @returns {string} Formatted number.
- *
- *
- * @example
- <example module="currencyExample">
- <file name="index.html">
- <script>
- angular.module('currencyExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.amount = 1234.56;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input type="number" ng-model="amount" aria-label="amount"> <br>
- default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
- custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
- no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should init with 1234.56', function() {
- expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
- expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
- expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
- });
- it('should update', function() {
- if (browser.params.browser == 'safari') {
- // Safari does not understand the minus key. See
- // https://github.com/angular/protractor/issues/481
- return;
- }
- element(by.model('amount')).clear();
- element(by.model('amount')).sendKeys('-1234');
- expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');
- expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');
- expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');
- });
- </file>
- </example>
- */
-currencyFilter.$inject = ['$locale'];
-function currencyFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(amount, currencySymbol, fractionSize) {
- if (isUndefined(currencySymbol)) {
- currencySymbol = formats.CURRENCY_SYM;
- }
-
- if (isUndefined(fractionSize)) {
- fractionSize = formats.PATTERNS[1].maxFrac;
- }
-
- // if null or undefined pass it through
- return (amount == null)
- ? amount
- : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
- replace(/\u00A4/g, currencySymbol);
- };
-}
-
-/**
- * @ngdoc filter
- * @name number
- * @kind function
- *
- * @description
- * Formats a number as text.
- *
- * If the input is null or undefined, it will just be returned.
- * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
- * If the input is not a number an empty string is returned.
- *
- *
- * @param {number|string} number Number to format.
- * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
- * If this is not provided then the fraction size is computed from the current locale's number
- * formatting pattern. In the case of the default locale, it will be 3.
- * @returns {string} Number rounded to fractionSize and places a “,†after each third digit.
- *
- * @example
- <example module="numberFilterExample">
- <file name="index.html">
- <script>
- angular.module('numberFilterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.val = 1234.56789;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <label>Enter number: <input ng-model='val'></label><br>
- Default formatting: <span id='number-default'>{{val | number}}</span><br>
- No fractions: <span>{{val | number:0}}</span><br>
- Negative number: <span>{{-val | number:4}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format numbers', function() {
- expect(element(by.id('number-default')).getText()).toBe('1,234.568');
- expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
- });
-
- it('should update', function() {
- element(by.model('val')).clear();
- element(by.model('val')).sendKeys('3374.333');
- expect(element(by.id('number-default')).getText()).toBe('3,374.333');
- expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
- });
- </file>
- </example>
- */
-numberFilter.$inject = ['$locale'];
-function numberFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(number, fractionSize) {
-
- // if null or undefined pass it through
- return (number == null)
- ? number
- : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
- fractionSize);
- };
-}
-
-/**
- * Parse a number (as a string) into three components that can be used
- * for formatting the number.
- *
- * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)
- *
- * @param {string} numStr The number to parse
- * @return {object} An object describing this number, containing the following keys:
- * - d : an array of digits containing leading zeros as necessary
- * - i : the number of the digits in `d` that are to the left of the decimal point
- * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`
- *
- */
-function parse(numStr) {
- var exponent = 0, digits, numberOfIntegerDigits;
- var i, j, zeros;
-
- // Decimal point?
- if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
- numStr = numStr.replace(DECIMAL_SEP, '');
- }
-
- // Exponential form?
- if ((i = numStr.search(/e/i)) > 0) {
- // Work out the exponent.
- if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
- numberOfIntegerDigits += +numStr.slice(i + 1);
- numStr = numStr.substring(0, i);
- } else if (numberOfIntegerDigits < 0) {
- // There was no decimal point or exponent so it is an integer.
- numberOfIntegerDigits = numStr.length;
- }
-
- // Count the number of leading zeros.
- for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++);
-
- if (i == (zeros = numStr.length)) {
- // The digits are all zero.
- digits = [0];
- numberOfIntegerDigits = 1;
- } else {
- // Count the number of trailing zeros
- zeros--;
- while (numStr.charAt(zeros) == ZERO_CHAR) zeros--;
-
- // Trailing zeros are insignificant so ignore them
- numberOfIntegerDigits -= i;
- digits = [];
- // Convert string to array of digits without leading/trailing zeros.
- for (j = 0; i <= zeros; i++, j++) {
- digits[j] = +numStr.charAt(i);
- }
- }
-
- // If the number overflows the maximum allowed digits then use an exponent.
- if (numberOfIntegerDigits > MAX_DIGITS) {
- digits = digits.splice(0, MAX_DIGITS - 1);
- exponent = numberOfIntegerDigits - 1;
- numberOfIntegerDigits = 1;
- }
-
- return { d: digits, e: exponent, i: numberOfIntegerDigits };
-}
-
-/**
- * Round the parsed number to the specified number of decimal places
- * This function changed the parsedNumber in-place
- */
-function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
- var digits = parsedNumber.d;
- var fractionLen = digits.length - parsedNumber.i;
-
- // determine fractionSize if it is not specified; `+fractionSize` converts it to a number
- fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
-
- // The index of the digit to where rounding is to occur
- var roundAt = fractionSize + parsedNumber.i;
- var digit = digits[roundAt];
-
- if (roundAt > 0) {
- digits.splice(roundAt);
- } else {
- // We rounded to zero so reset the parsedNumber
- parsedNumber.i = 1;
- digits.length = roundAt = fractionSize + 1;
- for (var i=0; i < roundAt; i++) digits[i] = 0;
- }
-
- if (digit >= 5) digits[roundAt - 1]++;
-
- // Pad out with zeros to get the required fraction length
- for (; fractionLen < fractionSize; fractionLen++) digits.push(0);
-
-
- // Do any carrying, e.g. a digit was rounded up to 10
- var carry = digits.reduceRight(function(carry, d, i, digits) {
- d = d + carry;
- digits[i] = d % 10;
- return Math.floor(d / 10);
- }, 0);
- if (carry) {
- digits.unshift(carry);
- parsedNumber.i++;
- }
-}
-
-/**
- * Format a number into a string
- * @param {number} number The number to format
- * @param {{
- * minFrac, // the minimum number of digits required in the fraction part of the number
- * maxFrac, // the maximum number of digits required in the fraction part of the number
- * gSize, // number of digits in each group of separated digits
- * lgSize, // number of digits in the last group of digits before the decimal separator
- * negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
- * posPre, // the string to go in front of a positive number
- * negSuf, // the string to go after a negative number (e.g. `)`)
- * posSuf // the string to go after a positive number
- * }} pattern
- * @param {string} groupSep The string to separate groups of number (e.g. `,`)
- * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
- * @param {[type]} fractionSize The size of the fractional part of the number
- * @return {string} The number formatted as a string
- */
-function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
-
- if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
-
- var isInfinity = !isFinite(number);
- var isZero = false;
- var numStr = Math.abs(number) + '',
- formattedText = '',
- parsedNumber;
-
- if (isInfinity) {
- formattedText = '\u221e';
- } else {
- parsedNumber = parse(numStr);
-
- roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
-
- var digits = parsedNumber.d;
- var integerLen = parsedNumber.i;
- var exponent = parsedNumber.e;
- var decimals = [];
- isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);
-
- // pad zeros for small numbers
- while (integerLen < 0) {
- digits.unshift(0);
- integerLen++;
- }
-
- // extract decimals digits
- if (integerLen > 0) {
- decimals = digits.splice(integerLen);
- } else {
- decimals = digits;
- digits = [0];
- }
-
- // format the integer digits with grouping separators
- var groups = [];
- if (digits.length > pattern.lgSize) {
- groups.unshift(digits.splice(-pattern.lgSize).join(''));
- }
- while (digits.length > pattern.gSize) {
- groups.unshift(digits.splice(-pattern.gSize).join(''));
- }
- if (digits.length) {
- groups.unshift(digits.join(''));
- }
- formattedText = groups.join(groupSep);
-
- // append the decimal digits
- if (decimals.length) {
- formattedText += decimalSep + decimals.join('');
- }
-
- if (exponent) {
- formattedText += 'e+' + exponent;
- }
- }
- if (number < 0 && !isZero) {
- return pattern.negPre + formattedText + pattern.negSuf;
- } else {
- return pattern.posPre + formattedText + pattern.posSuf;
- }
-}
-
-function padNumber(num, digits, trim) {
- var neg = '';
- if (num < 0) {
- neg = '-';
- num = -num;
- }
- num = '' + num;
- while (num.length < digits) num = ZERO_CHAR + num;
- if (trim) {
- num = num.substr(num.length - digits);
- }
- return neg + num;
-}
-
-
-function dateGetter(name, size, offset, trim) {
- offset = offset || 0;
- return function(date) {
- var value = date['get' + name]();
- if (offset > 0 || value > -offset) {
- value += offset;
- }
- if (value === 0 && offset == -12) value = 12;
- return padNumber(value, size, trim);
- };
-}
-
-function dateStrGetter(name, shortForm) {
- return function(date, formats) {
- var value = date['get' + name]();
- var get = uppercase(shortForm ? ('SHORT' + name) : name);
-
- return formats[get][value];
- };
-}
-
-function timeZoneGetter(date, formats, offset) {
- var zone = -1 * offset;
- var paddedZone = (zone >= 0) ? "+" : "";
-
- paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
- padNumber(Math.abs(zone % 60), 2);
-
- return paddedZone;
-}
-
-function getFirstThursdayOfYear(year) {
- // 0 = index of January
- var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
- // 4 = index of Thursday (+1 to account for 1st = 5)
- // 11 = index of *next* Thursday (+1 account for 1st = 12)
- return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
-}
-
-function getThursdayThisWeek(datetime) {
- return new Date(datetime.getFullYear(), datetime.getMonth(),
- // 4 = index of Thursday
- datetime.getDate() + (4 - datetime.getDay()));
-}
-
-function weekGetter(size) {
- return function(date) {
- var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
- thisThurs = getThursdayThisWeek(date);
-
- var diff = +thisThurs - +firstThurs,
- result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
-
- return padNumber(result, size);
- };
-}
-
-function ampmGetter(date, formats) {
- return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
-}
-
-function eraGetter(date, formats) {
- return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
-}
-
-function longEraGetter(date, formats) {
- return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
-}
-
-var DATE_FORMATS = {
- yyyy: dateGetter('FullYear', 4),
- yy: dateGetter('FullYear', 2, 0, true),
- y: dateGetter('FullYear', 1),
- MMMM: dateStrGetter('Month'),
- MMM: dateStrGetter('Month', true),
- MM: dateGetter('Month', 2, 1),
- M: dateGetter('Month', 1, 1),
- dd: dateGetter('Date', 2),
- d: dateGetter('Date', 1),
- HH: dateGetter('Hours', 2),
- H: dateGetter('Hours', 1),
- hh: dateGetter('Hours', 2, -12),
- h: dateGetter('Hours', 1, -12),
- mm: dateGetter('Minutes', 2),
- m: dateGetter('Minutes', 1),
- ss: dateGetter('Seconds', 2),
- s: dateGetter('Seconds', 1),
- // while ISO 8601 requires fractions to be prefixed with `.` or `,`
- // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
- sss: dateGetter('Milliseconds', 3),
- EEEE: dateStrGetter('Day'),
- EEE: dateStrGetter('Day', true),
- a: ampmGetter,
- Z: timeZoneGetter,
- ww: weekGetter(2),
- w: weekGetter(1),
- G: eraGetter,
- GG: eraGetter,
- GGG: eraGetter,
- GGGG: longEraGetter
-};
-
-var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
- NUMBER_STRING = /^\-?\d+$/;
-
-/**
- * @ngdoc filter
- * @name date
- * @kind function
- *
- * @description
- * Formats `date` to a string based on the requested `format`.
- *
- * `format` string can be composed of the following elements:
- *
- * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
- * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
- * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
- * * `'MMMM'`: Month in year (January-December)
- * * `'MMM'`: Month in year (Jan-Dec)
- * * `'MM'`: Month in year, padded (01-12)
- * * `'M'`: Month in year (1-12)
- * * `'dd'`: Day in month, padded (01-31)
- * * `'d'`: Day in month (1-31)
- * * `'EEEE'`: Day in Week,(Sunday-Saturday)
- * * `'EEE'`: Day in Week, (Sun-Sat)
- * * `'HH'`: Hour in day, padded (00-23)
- * * `'H'`: Hour in day (0-23)
- * * `'hh'`: Hour in AM/PM, padded (01-12)
- * * `'h'`: Hour in AM/PM, (1-12)
- * * `'mm'`: Minute in hour, padded (00-59)
- * * `'m'`: Minute in hour (0-59)
- * * `'ss'`: Second in minute, padded (00-59)
- * * `'s'`: Second in minute (0-59)
- * * `'sss'`: Millisecond in second, padded (000-999)
- * * `'a'`: AM/PM marker
- * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
- * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
- * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
- * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
- * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
- *
- * `format` string can also be one of the following predefined
- * {@link guide/i18n localizable formats}:
- *
- * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
- * (e.g. Sep 3, 2010 12:05:08 PM)
- * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)
- * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
- * (e.g. Friday, September 3, 2010)
- * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
- * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
- * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
- * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
- * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
- *
- * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
- * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
- * (e.g. `"h 'o''clock'"`).
- *
- * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
- * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
- * specified in the string input, the time is considered to be in the local timezone.
- * @param {string=} format Formatting rules (see Description). If not specified,
- * `mediumDate` is used.
- * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the
- * continental US time zone abbreviations, but for general use, use a time zone offset, for
- * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
- * If not specified, the timezone of the browser will be used.
- * @returns {string} Formatted string or the input if input is not recognized as date/millis.
- *
- * @example
- <example>
- <file name="index.html">
- <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
- <span>{{1288323623006 | date:'medium'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
- <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
- <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
- <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format date', function() {
- expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
- toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
- expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
- expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
- toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
- expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
- toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
- });
- </file>
- </example>
- */
-dateFilter.$inject = ['$locale'];
-function dateFilter($locale) {
-
-
- var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
- // 1 2 3 4 5 6 7 8 9 10 11
- function jsonStringToDate(string) {
- var match;
- if (match = string.match(R_ISO8601_STR)) {
- var date = new Date(0),
- tzHour = 0,
- tzMin = 0,
- dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
- timeSetter = match[8] ? date.setUTCHours : date.setHours;
-
- if (match[9]) {
- tzHour = toInt(match[9] + match[10]);
- tzMin = toInt(match[9] + match[11]);
- }
- dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
- var h = toInt(match[4] || 0) - tzHour;
- var m = toInt(match[5] || 0) - tzMin;
- var s = toInt(match[6] || 0);
- var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
- timeSetter.call(date, h, m, s, ms);
- return date;
- }
- return string;
- }
-
-
- return function(date, format, timezone) {
- var text = '',
- parts = [],
- fn, match;
-
- format = format || 'mediumDate';
- format = $locale.DATETIME_FORMATS[format] || format;
- if (isString(date)) {
- date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);
- }
-
- if (isNumber(date)) {
- date = new Date(date);
- }
-
- if (!isDate(date) || !isFinite(date.getTime())) {
- return date;
- }
-
- while (format) {
- match = DATE_FORMATS_SPLIT.exec(format);
- if (match) {
- parts = concat(parts, match, 1);
- format = parts.pop();
- } else {
- parts.push(format);
- format = null;
- }
- }
-
- var dateTimezoneOffset = date.getTimezoneOffset();
- if (timezone) {
- dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
- date = convertTimezoneToLocal(date, timezone, true);
- }
- forEach(parts, function(value) {
- fn = DATE_FORMATS[value];
- text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
- : value === "''" ? "'" : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
- });
-
- return text;
- };
-}
-
-
-/**
- * @ngdoc filter
- * @name json
- * @kind function
- *
- * @description
- * Allows you to convert a JavaScript object into JSON string.
- *
- * This filter is mostly useful for debugging. When using the double curly {{value}} notation
- * the binding is automatically converted to JSON.
- *
- * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
- * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
- * @returns {string} JSON string.
- *
- *
- * @example
- <example>
- <file name="index.html">
- <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
- <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
- </file>
- <file name="protractor.js" type="protractor">
- it('should jsonify filtered objects', function() {
- expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
- expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
- });
- </file>
- </example>
- *
- */
-function jsonFilter() {
- return function(object, spacing) {
- if (isUndefined(spacing)) {
- spacing = 2;
- }
- return toJson(object, spacing);
- };
-}
-
-
-/**
- * @ngdoc filter
- * @name lowercase
- * @kind function
- * @description
- * Converts string to lowercase.
- * @see angular.lowercase
- */
-var lowercaseFilter = valueFn(lowercase);
-
-
-/**
- * @ngdoc filter
- * @name uppercase
- * @kind function
- * @description
- * Converts string to uppercase.
- * @see angular.uppercase
- */
-var uppercaseFilter = valueFn(uppercase);
-
-/**
- * @ngdoc filter
- * @name limitTo
- * @kind function
- *
- * @description
- * Creates a new array or string containing only a specified number of elements. The elements
- * are taken from either the beginning or the end of the source array, string or number, as specified by
- * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
- * converted to a string.
- *
- * @param {Array|string|number} input Source array, string or number to be limited.
- * @param {string|number} limit The length of the returned array or string. If the `limit` number
- * is positive, `limit` number of items from the beginning of the source array/string are copied.
- * If the number is negative, `limit` number of items from the end of the source array/string
- * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
- * the input will be returned unchanged.
- * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
- * indicates an offset from the end of `input`. Defaults to `0`.
- * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
- * had less than `limit` elements.
- *
- * @example
- <example module="limitToExample">
- <file name="index.html">
- <script>
- angular.module('limitToExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.numbers = [1,2,3,4,5,6,7,8,9];
- $scope.letters = "abcdefghi";
- $scope.longNumber = 2345432342;
- $scope.numLimit = 3;
- $scope.letterLimit = 3;
- $scope.longNumberLimit = 3;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <label>
- Limit {{numbers}} to:
- <input type="number" step="1" ng-model="numLimit">
- </label>
- <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
- <label>
- Limit {{letters}} to:
- <input type="number" step="1" ng-model="letterLimit">
- </label>
- <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
- <label>
- Limit {{longNumber}} to:
- <input type="number" step="1" ng-model="longNumberLimit">
- </label>
- <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- var numLimitInput = element(by.model('numLimit'));
- var letterLimitInput = element(by.model('letterLimit'));
- var longNumberLimitInput = element(by.model('longNumberLimit'));
- var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
- var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
- var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
-
- it('should limit the number array to first three items', function() {
- expect(numLimitInput.getAttribute('value')).toBe('3');
- expect(letterLimitInput.getAttribute('value')).toBe('3');
- expect(longNumberLimitInput.getAttribute('value')).toBe('3');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
- expect(limitedLetters.getText()).toEqual('Output letters: abc');
- expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
- });
-
- // There is a bug in safari and protractor that doesn't like the minus key
- // it('should update the output when -3 is entered', function() {
- // numLimitInput.clear();
- // numLimitInput.sendKeys('-3');
- // letterLimitInput.clear();
- // letterLimitInput.sendKeys('-3');
- // longNumberLimitInput.clear();
- // longNumberLimitInput.sendKeys('-3');
- // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
- // expect(limitedLetters.getText()).toEqual('Output letters: ghi');
- // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
- // });
-
- it('should not exceed the maximum size of input array', function() {
- numLimitInput.clear();
- numLimitInput.sendKeys('100');
- letterLimitInput.clear();
- letterLimitInput.sendKeys('100');
- longNumberLimitInput.clear();
- longNumberLimitInput.sendKeys('100');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
- expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
- expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
- });
- </file>
- </example>
-*/
-function limitToFilter() {
- return function(input, limit, begin) {
- if (Math.abs(Number(limit)) === Infinity) {
- limit = Number(limit);
- } else {
- limit = toInt(limit);
- }
- if (isNaN(limit)) return input;
-
- if (isNumber(input)) input = input.toString();
- if (!isArray(input) && !isString(input)) return input;
-
- begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
- begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
-
- if (limit >= 0) {
- return input.slice(begin, begin + limit);
- } else {
- if (begin === 0) {
- return input.slice(limit, input.length);
- } else {
- return input.slice(Math.max(0, begin + limit), begin);
- }
- }
- };
-}
-
-/**
- * @ngdoc filter
- * @name orderBy
- * @kind function
- *
- * @description
- * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
- * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
- * as expected, make sure they are actually being saved as numbers and not strings.
- * Array-like values (e.g. NodeLists, jQuery objects, TypedArrays, Strings, etc) are also supported.
- *
- * @param {Array} array The array (or array-like object) to sort.
- * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
- * used by the comparator to determine the order of elements.
- *
- * Can be one of:
- *
- * - `function`: Getter function. The result of this function will be sorted using the
- * `<`, `===`, `>` operator.
- * - `string`: An Angular expression. The result of this expression is used to compare elements
- * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
- * 3 first characters of a property called `name`). The result of a constant expression
- * is interpreted as a property name to be used in comparisons (for example `"special name"`
- * to sort object by the value of their `special name` property). An expression can be
- * optionally prefixed with `+` or `-` to control ascending or descending sort order
- * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
- * element itself is used to compare where sorting.
- * - `Array`: An array of function or string predicates. The first predicate in the array
- * is used for sorting, but when two items are equivalent, the next predicate is used.
- *
- * If the predicate is missing or empty then it defaults to `'+'`.
- *
- * @param {boolean=} reverse Reverse the order of the array.
- * @returns {Array} Sorted copy of the source array.
- *
- *
- * @example
- * The example below demonstrates a simple ngRepeat, where the data is sorted
- * by age in descending order (predicate is set to `'-age'`).
- * `reverse` is not set, which means it defaults to `false`.
- <example module="orderByExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <table class="friend">
- <tr>
- <th>Name</th>
- <th>Phone Number</th>
- <th>Age</th>
- </tr>
- <tr ng-repeat="friend in friends | orderBy:'-age'">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- }]);
- </file>
- </example>
- *
- * The predicate and reverse parameters can be controlled dynamically through scope properties,
- * as shown in the next example.
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
- <hr/>
- <button ng-click="predicate=''">Set to unsorted</button>
- <table class="friend">
- <tr>
- <th>
- <button ng-click="order('name')">Name</button>
- <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('phone')">Phone Number</button>
- <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('age')">Age</button>
- <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
- </th>
- </tr>
- <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- $scope.predicate = 'age';
- $scope.reverse = true;
- $scope.order = function(predicate) {
- $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
- $scope.predicate = predicate;
- };
- }]);
- </file>
- <file name="style.css">
- .sortorder:after {
- content: '\25b2';
- }
- .sortorder.reverse:after {
- content: '\25bc';
- }
- </file>
- </example>
- *
- * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
- * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
- * desired parameters.
- *
- * Example:
- *
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
- <table class="friend">
- <tr>
- <th>
- <button ng-click="order('name')">Name</button>
- <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('phone')">Phone Number</button>
- <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
- </th>
- <th>
- <button ng-click="order('age')">Age</button>
- <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
- </th>
- </tr>
- <tr ng-repeat="friend in friends">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
- var orderBy = $filter('orderBy');
- $scope.friends = [
- { name: 'John', phone: '555-1212', age: 10 },
- { name: 'Mary', phone: '555-9876', age: 19 },
- { name: 'Mike', phone: '555-4321', age: 21 },
- { name: 'Adam', phone: '555-5678', age: 35 },
- { name: 'Julie', phone: '555-8765', age: 29 }
- ];
- $scope.order = function(predicate) {
- $scope.predicate = predicate;
- $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
- $scope.friends = orderBy($scope.friends, predicate, $scope.reverse);
- };
- $scope.order('age', true);
- }]);
- </file>
-
- <file name="style.css">
- .sortorder:after {
- content: '\25b2';
- }
- .sortorder.reverse:after {
- content: '\25bc';
- }
- </file>
-</example>
- */
-orderByFilter.$inject = ['$parse'];
-function orderByFilter($parse) {
- return function(array, sortPredicate, reverseOrder) {
-
- if (array == null) return array;
- if (!isArrayLike(array)) {
- throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array);
- }
-
- if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
- if (sortPredicate.length === 0) { sortPredicate = ['+']; }
-
- var predicates = processPredicates(sortPredicate, reverseOrder);
- // Add a predicate at the end that evaluates to the element index. This makes the
- // sort stable as it works as a tie-breaker when all the input predicates cannot
- // distinguish between two elements.
- predicates.push({ get: function() { return {}; }, descending: reverseOrder ? -1 : 1});
-
- // The next three lines are a version of a Swartzian Transform idiom from Perl
- // (sometimes called the Decorate-Sort-Undecorate idiom)
- // See https://en.wikipedia.org/wiki/Schwartzian_transform
- var compareValues = Array.prototype.map.call(array, getComparisonObject);
- compareValues.sort(doComparison);
- array = compareValues.map(function(item) { return item.value; });
-
- return array;
-
- function getComparisonObject(value, index) {
- return {
- value: value,
- predicateValues: predicates.map(function(predicate) {
- return getPredicateValue(predicate.get(value), index);
- })
- };
- }
-
- function doComparison(v1, v2) {
- var result = 0;
- for (var index=0, length = predicates.length; index < length; ++index) {
- result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
- if (result) break;
- }
- return result;
- }
- };
-
- function processPredicates(sortPredicate, reverseOrder) {
- reverseOrder = reverseOrder ? -1 : 1;
- return sortPredicate.map(function(predicate) {
- var descending = 1, get = identity;
-
- if (isFunction(predicate)) {
- get = predicate;
- } else if (isString(predicate)) {
- if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
- descending = predicate.charAt(0) == '-' ? -1 : 1;
- predicate = predicate.substring(1);
- }
- if (predicate !== '') {
- get = $parse(predicate);
- if (get.constant) {
- var key = get();
- get = function(value) { return value[key]; };
- }
- }
- }
- return { get: get, descending: descending * reverseOrder };
- });
- }
-
- function isPrimitive(value) {
- switch (typeof value) {
- case 'number': /* falls through */
- case 'boolean': /* falls through */
- case 'string':
- return true;
- default:
- return false;
- }
- }
-
- function objectValue(value, index) {
- // If `valueOf` is a valid function use that
- if (typeof value.valueOf === 'function') {
- value = value.valueOf();
- if (isPrimitive(value)) return value;
- }
- // If `toString` is a valid function and not the one from `Object.prototype` use that
- if (hasCustomToString(value)) {
- value = value.toString();
- if (isPrimitive(value)) return value;
- }
- // We have a basic object so we use the position of the object in the collection
- return index;
- }
-
- function getPredicateValue(value, index) {
- var type = typeof value;
- if (value === null) {
- type = 'string';
- value = 'null';
- } else if (type === 'string') {
- value = value.toLowerCase();
- } else if (type === 'object') {
- value = objectValue(value, index);
- }
- return { value: value, type: type };
- }
-
- function compare(v1, v2) {
- var result = 0;
- if (v1.type === v2.type) {
- if (v1.value !== v2.value) {
- result = v1.value < v2.value ? -1 : 1;
- }
- } else {
- result = v1.type < v2.type ? -1 : 1;
- }
- return result;
- }
-}
-
-function ngDirective(directive) {
- if (isFunction(directive)) {
- directive = {
- link: directive
- };
- }
- directive.restrict = directive.restrict || 'AC';
- return valueFn(directive);
-}
-
-/**
- * @ngdoc directive
- * @name a
- * @restrict E
- *
- * @description
- * Modifies the default behavior of the html A tag so that the default action is prevented when
- * the href attribute is empty.
- *
- * This change permits the easy creation of action links with the `ngClick` directive
- * without changing the location or causing page reloads, e.g.:
- * `<a href="" ng-click="list.addItem()">Add Item</a>`
- */
-var htmlAnchorDirective = valueFn({
- restrict: 'E',
- compile: function(element, attr) {
- if (!attr.href && !attr.xlinkHref) {
- return function(scope, element) {
- // If the linked element is not an anchor tag anymore, do nothing
- if (element[0].nodeName.toLowerCase() !== 'a') return;
-
- // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
- var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
- 'xlink:href' : 'href';
- element.on('click', function(event) {
- // if we have no href url, then don't navigate anywhere.
- if (!element.attr(href)) {
- event.preventDefault();
- }
- });
- };
- }
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngHref
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in an href attribute will
- * make the link go to the wrong URL if the user clicks it before
- * Angular has a chance to replace the `{{hash}}` markup with its
- * value. Until Angular replaces the markup the link will be broken
- * and will most likely return a 404 error. The `ngHref` directive
- * solves this problem.
- *
- * The wrong way to write it:
- * ```html
- * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
- * ```
- *
- * @element A
- * @param {template} ngHref any string which can contain `{{}}` markup.
- *
- * @example
- * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
- * in links and their different behaviors:
- <example>
- <file name="index.html">
- <input ng-model="value" /><br />
- <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
- <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
- <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
- <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
- <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
- <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
- </file>
- <file name="protractor.js" type="protractor">
- it('should execute ng-click but not reload when href without value', function() {
- element(by.id('link-1')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('1');
- expect(element(by.id('link-1')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click but not reload when href empty string', function() {
- element(by.id('link-2')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('2');
- expect(element(by.id('link-2')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click and change url when ng-href specified', function() {
- expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
-
- element(by.id('link-3')).click();
-
- // At this point, we navigate away from an Angular page, so we need
- // to use browser.driver to get the base webdriver.
-
- browser.wait(function() {
- return browser.driver.getCurrentUrl().then(function(url) {
- return url.match(/\/123$/);
- });
- }, 5000, 'page should navigate to /123');
- });
-
- it('should execute ng-click but not reload when href empty string and name specified', function() {
- element(by.id('link-4')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('4');
- expect(element(by.id('link-4')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click but not reload when no href but name specified', function() {
- element(by.id('link-5')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('5');
- expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
- });
-
- it('should only change url when only ng-href', function() {
- element(by.model('value')).clear();
- element(by.model('value')).sendKeys('6');
- expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
-
- element(by.id('link-6')).click();
-
- // At this point, we navigate away from an Angular page, so we need
- // to use browser.driver to get the base webdriver.
- browser.wait(function() {
- return browser.driver.getCurrentUrl().then(function(url) {
- return url.match(/\/6$/);
- });
- }, 5000, 'page should navigate to /6');
- });
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngSrc
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrc` directive solves this problem.
- *
- * The buggy way to write it:
- * ```html
- * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
- * ```
- *
- * @element IMG
- * @param {template} ngSrc any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ngSrcset
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrcset` directive solves this problem.
- *
- * The buggy way to write it:
- * ```html
- * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
- * ```
- *
- * @element IMG
- * @param {template} ngSrcset any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ngDisabled
- * @restrict A
- * @priority 100
- *
- * @description
- *
- * This directive sets the `disabled` attribute on the element if the
- * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `disabled`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
- * @example
- <example>
- <file name="index.html">
- <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/>
- <button ng-model="button" ng-disabled="checked">Button</button>
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle button', function() {
- expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
- element(by.model('checked')).click();
- expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
- * then the `disabled` attribute will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngChecked
- * @restrict A
- * @priority 100
- *
- * @description
- * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
- *
- * Note that this directive should not be used together with {@link ngModel `ngModel`},
- * as this can lead to unexpected behavior.
- *
- * A special directive is necessary because we cannot use interpolation inside the `checked`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
- * @example
- <example>
- <file name="index.html">
- <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/>
- <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input">
- </file>
- <file name="protractor.js" type="protractor">
- it('should check both checkBoxes', function() {
- expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
- element(by.model('master')).click();
- expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
- * then the `checked` attribute will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngReadonly
- * @restrict A
- * @priority 100
- *
- * @description
- *
- * Sets the `readOnly` attribute on the element, if the expression inside `ngReadonly` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `readOnly`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
- * @example
- <example>
- <file name="index.html">
- <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/>
- <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" />
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle readonly attr', function() {
- expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
- element(by.model('checked')).click();
- expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
- * then special attribute "readonly" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngSelected
- * @restrict A
- * @priority 100
- *
- * @description
- *
- * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `selected`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
- * @example
- <example>
- <file name="index.html">
- <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/>
- <select aria-label="ngSelected demo">
- <option>Hello!</option>
- <option id="greet" ng-selected="selected">Greetings!</option>
- </select>
- </file>
- <file name="protractor.js" type="protractor">
- it('should select Greetings!', function() {
- expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
- element(by.model('selected')).click();
- expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element OPTION
- * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
- * then special attribute "selected" will be set on the element
- */
-
-/**
- * @ngdoc directive
- * @name ngOpen
- * @restrict A
- * @priority 100
- *
- * @description
- *
- * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.
- *
- * A special directive is necessary because we cannot use interpolation inside the `open`
- * attribute. See the {@link guide/interpolation interpolation guide} for more info.
- *
- * @example
- <example>
- <file name="index.html">
- <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/>
- <details id="details" ng-open="open">
- <summary>Show/Hide me</summary>
- </details>
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle open', function() {
- expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
- element(by.model('open')).click();
- expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element DETAILS
- * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
- * then special attribute "open" will be set on the element
- */
-
-var ngAttributeAliasDirectives = {};
-
-// boolean attrs are evaluated
-forEach(BOOLEAN_ATTR, function(propName, attrName) {
- // binding to multiple is not supported
- if (propName == "multiple") return;
-
- function defaultLinkFn(scope, element, attr) {
- scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
- attr.$set(attrName, !!value);
- });
- }
-
- var normalized = directiveNormalize('ng-' + attrName);
- var linkFn = defaultLinkFn;
-
- if (propName === 'checked') {
- linkFn = function(scope, element, attr) {
- // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
- if (attr.ngModel !== attr[normalized]) {
- defaultLinkFn(scope, element, attr);
- }
- };
- }
-
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- restrict: 'A',
- priority: 100,
- link: linkFn
- };
- };
-});
-
-// aliased input attrs are evaluated
-forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
- ngAttributeAliasDirectives[ngAttr] = function() {
- return {
- priority: 100,
- link: function(scope, element, attr) {
- //special case ngPattern when a literal regular expression value
- //is used as the expression (this way we don't have to watch anything).
- if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
- var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
- if (match) {
- attr.$set("ngPattern", new RegExp(match[1], match[2]));
- return;
- }
- }
-
- scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
- attr.$set(ngAttr, value);
- });
- }
- };
- };
-});
-
-// ng-src, ng-srcset, ng-href are interpolated
-forEach(['src', 'srcset', 'href'], function(attrName) {
- var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- priority: 99, // it needs to run after the attributes are interpolated
- link: function(scope, element, attr) {
- var propName = attrName,
- name = attrName;
-
- if (attrName === 'href' &&
- toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
- name = 'xlinkHref';
- attr.$attr[name] = 'xlink:href';
- propName = null;
- }
-
- attr.$observe(normalized, function(value) {
- if (!value) {
- if (attrName === 'href') {
- attr.$set(name, null);
- }
- return;
- }
-
- attr.$set(name, value);
-
- // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
- // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
- // to set the property as well to achieve the desired effect.
- // we use attr[attrName] value since $set can sanitize the url.
- if (msie && propName) element.prop(propName, attr[name]);
- });
- }
- };
- };
-});
-
-/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
- */
-var nullFormCtrl = {
- $addControl: noop,
- $$renameControl: nullFormRenameControl,
- $removeControl: noop,
- $setValidity: noop,
- $setDirty: noop,
- $setPristine: noop,
- $setSubmitted: noop
-},
-SUBMITTED_CLASS = 'ng-submitted';
-
-function nullFormRenameControl(control, name) {
- control.$name = name;
-}
-
-/**
- * @ngdoc type
- * @name form.FormController
- *
- * @property {boolean} $pristine True if user has not interacted with the form yet.
- * @property {boolean} $dirty True if user has already interacted with the form.
- * @property {boolean} $valid True if all of the containing forms and controls are valid.
- * @property {boolean} $invalid True if at least one containing control or form is invalid.
- * @property {boolean} $pending True if at least one containing control or form is pending.
- * @property {boolean} $submitted True if user has submitted the form even if its invalid.
- *
- * @property {Object} $error Is an object hash, containing references to controls or
- * forms with failing validators, where:
- *
- * - keys are validation tokens (error names),
- * - values are arrays of controls or forms that have a failing validator for given error name.
- *
- * Built-in validation tokens:
- *
- * - `email`
- * - `max`
- * - `maxlength`
- * - `min`
- * - `minlength`
- * - `number`
- * - `pattern`
- * - `required`
- * - `url`
- * - `date`
- * - `datetimelocal`
- * - `time`
- * - `week`
- * - `month`
- *
- * @description
- * `FormController` keeps track of all its controls and nested forms as well as the state of them,
- * such as being valid/invalid or dirty/pristine.
- *
- * Each {@link ng.directive:form form} directive creates an instance
- * of `FormController`.
- *
- */
-//asks for $scope to fool the BC controller module
-FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
-function FormController(element, attrs, $scope, $animate, $interpolate) {
- var form = this,
- controls = [];
-
- // init state
- form.$error = {};
- form.$$success = {};
- form.$pending = undefined;
- form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
- form.$dirty = false;
- form.$pristine = true;
- form.$valid = true;
- form.$invalid = false;
- form.$submitted = false;
- form.$$parentForm = nullFormCtrl;
-
- /**
- * @ngdoc method
- * @name form.FormController#$rollbackViewValue
- *
- * @description
- * Rollback all form controls pending updates to the `$modelValue`.
- *
- * Updates may be pending by a debounced event or because the input is waiting for a some future
- * event defined in `ng-model-options`. This method is typically needed by the reset button of
- * a form that uses `ng-model-options` to pend updates.
- */
- form.$rollbackViewValue = function() {
- forEach(controls, function(control) {
- control.$rollbackViewValue();
- });
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$commitViewValue
- *
- * @description
- * Commit all form controls pending updates to the `$modelValue`.
- *
- * Updates may be pending by a debounced event or because the input is waiting for a some future
- * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
- * usually handles calling this in response to input events.
- */
- form.$commitViewValue = function() {
- forEach(controls, function(control) {
- control.$commitViewValue();
- });
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$addControl
- * @param {object} control control object, either a {@link form.FormController} or an
- * {@link ngModel.NgModelController}
- *
- * @description
- * Register a control with the form. Input elements using ngModelController do this automatically
- * when they are linked.
- *
- * Note that the current state of the control will not be reflected on the new parent form. This
- * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`
- * state.
- *
- * However, if the method is used programmatically, for example by adding dynamically created controls,
- * or controls that have been previously removed without destroying their corresponding DOM element,
- * it's the developers responsibility to make sure the current state propagates to the parent form.
- *
- * For example, if an input control is added that is already `$dirty` and has `$error` properties,
- * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.
- */
- form.$addControl = function(control) {
- // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
- // and not added to the scope. Now we throw an error.
- assertNotHasOwnProperty(control.$name, 'input');
- controls.push(control);
-
- if (control.$name) {
- form[control.$name] = control;
- }
-
- control.$$parentForm = form;
- };
-
- // Private API: rename a form control
- form.$$renameControl = function(control, newName) {
- var oldName = control.$name;
-
- if (form[oldName] === control) {
- delete form[oldName];
- }
- form[newName] = control;
- control.$name = newName;
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$removeControl
- * @param {object} control control object, either a {@link form.FormController} or an
- * {@link ngModel.NgModelController}
- *
- * @description
- * Deregister a control from the form.
- *
- * Input elements using ngModelController do this automatically when they are destroyed.
- *
- * Note that only the removed control's validation state (`$errors`etc.) will be removed from the
- * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be
- * different from case to case. For example, removing the only `$dirty` control from a form may or
- * may not mean that the form is still `$dirty`.
- */
- form.$removeControl = function(control) {
- if (control.$name && form[control.$name] === control) {
- delete form[control.$name];
- }
- forEach(form.$pending, function(value, name) {
- form.$setValidity(name, null, control);
- });
- forEach(form.$error, function(value, name) {
- form.$setValidity(name, null, control);
- });
- forEach(form.$$success, function(value, name) {
- form.$setValidity(name, null, control);
- });
-
- arrayRemove(controls, control);
- control.$$parentForm = nullFormCtrl;
- };
-
-
- /**
- * @ngdoc method
- * @name form.FormController#$setValidity
- *
- * @description
- * Sets the validity of a form control.
- *
- * This method will also propagate to parent forms.
- */
- addSetValidityMethod({
- ctrl: this,
- $element: element,
- set: function(object, property, controller) {
- var list = object[property];
- if (!list) {
- object[property] = [controller];
- } else {
- var index = list.indexOf(controller);
- if (index === -1) {
- list.push(controller);
- }
- }
- },
- unset: function(object, property, controller) {
- var list = object[property];
- if (!list) {
- return;
- }
- arrayRemove(list, controller);
- if (list.length === 0) {
- delete object[property];
- }
- },
- $animate: $animate
- });
-
- /**
- * @ngdoc method
- * @name form.FormController#$setDirty
- *
- * @description
- * Sets the form to a dirty state.
- *
- * This method can be called to add the 'ng-dirty' class and set the form to a dirty
- * state (ng-dirty class). This method will also propagate to parent forms.
- */
- form.$setDirty = function() {
- $animate.removeClass(element, PRISTINE_CLASS);
- $animate.addClass(element, DIRTY_CLASS);
- form.$dirty = true;
- form.$pristine = false;
- form.$$parentForm.$setDirty();
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setPristine
- *
- * @description
- * Sets the form to its pristine state.
- *
- * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
- * state (ng-pristine class). This method will also propagate to all the controls contained
- * in this form.
- *
- * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
- * saving or resetting it.
- */
- form.$setPristine = function() {
- $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
- form.$dirty = false;
- form.$pristine = true;
- form.$submitted = false;
- forEach(controls, function(control) {
- control.$setPristine();
- });
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setUntouched
- *
- * @description
- * Sets the form to its untouched state.
- *
- * This method can be called to remove the 'ng-touched' class and set the form controls to their
- * untouched state (ng-untouched class).
- *
- * Setting a form controls back to their untouched state is often useful when setting the form
- * back to its pristine state.
- */
- form.$setUntouched = function() {
- forEach(controls, function(control) {
- control.$setUntouched();
- });
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setSubmitted
- *
- * @description
- * Sets the form to its submitted state.
- */
- form.$setSubmitted = function() {
- $animate.addClass(element, SUBMITTED_CLASS);
- form.$submitted = true;
- form.$$parentForm.$setSubmitted();
- };
-}
-
-/**
- * @ngdoc directive
- * @name ngForm
- * @restrict EAC
- *
- * @description
- * Nestable alias of {@link ng.directive:form `form`} directive. HTML
- * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
- * sub-group of controls needs to be determined.
- *
- * Note: the purpose of `ngForm` is to group controls,
- * but not to be a replacement for the `<form>` tag with all of its capabilities
- * (e.g. posting to the server, ...).
- *
- * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
- * related scope, under this name.
- *
- */
-
- /**
- * @ngdoc directive
- * @name form
- * @restrict E
- *
- * @description
- * Directive that instantiates
- * {@link form.FormController FormController}.
- *
- * If the `name` attribute is specified, the form controller is published onto the current scope under
- * this name.
- *
- * # Alias: {@link ng.directive:ngForm `ngForm`}
- *
- * In Angular, forms can be nested. This means that the outer form is valid when all of the child
- * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
- * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
- * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
- * of controls needs to be determined.
- *
- * # CSS classes
- * - `ng-valid` is set if the form is valid.
- * - `ng-invalid` is set if the form is invalid.
- * - `ng-pending` is set if the form is pending.
- * - `ng-pristine` is set if the form is pristine.
- * - `ng-dirty` is set if the form is dirty.
- * - `ng-submitted` is set if the form was submitted.
- *
- * Keep in mind that ngAnimate can detect each of these classes when added and removed.
- *
- *
- * # Submitting a form and preventing the default action
- *
- * Since the role of forms in client-side Angular applications is different than in classical
- * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
- * page reload that sends the data to the server. Instead some javascript logic should be triggered
- * to handle the form submission in an application-specific way.
- *
- * For this reason, Angular prevents the default action (form submission to the server) unless the
- * `<form>` element has an `action` attribute specified.
- *
- * You can use one of the following two ways to specify what javascript method should be called when
- * a form is submitted:
- *
- * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
- * - {@link ng.directive:ngClick ngClick} directive on the first
- * button or input field of type submit (input[type=submit])
- *
- * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
- * or {@link ng.directive:ngClick ngClick} directives.
- * This is because of the following form submission rules in the HTML specification:
- *
- * - If a form has only one input field then hitting enter in this field triggers form submit
- * (`ngSubmit`)
- * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
- * doesn't trigger submit
- * - if a form has one or more input fields and one or more buttons or input[type=submit] then
- * hitting enter in any of the input fields will trigger the click handler on the *first* button or
- * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
- *
- * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
- * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
- * to have access to the updated model.
- *
- * ## Animation Hooks
- *
- * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
- * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
- * other validations that are performed within the form. Animations in ngForm are similar to how
- * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
- * as JS animations.
- *
- * The following example shows a simple way to utilize CSS transitions to style a form element
- * that has been rendered as invalid after it has been validated:
- *
- * <pre>
- * //be sure to include ngAnimate as a module to hook into more
- * //advanced animations
- * .my-form {
- * transition:0.5s linear all;
- * background: white;
- * }
- * .my-form.ng-invalid {
- * background: red;
- * color:white;
- * }
- * </pre>
- *
- * @example
- <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
- <file name="index.html">
- <script>
- angular.module('formExample', [])
- .controller('FormController', ['$scope', function($scope) {
- $scope.userType = 'guest';
- }]);
- </script>
- <style>
- .my-form {
- transition:all linear 0.5s;
- background: transparent;
- }
- .my-form.ng-invalid {
- background: red;
- }
- </style>
- <form name="myForm" ng-controller="FormController" class="my-form">
- userType: <input name="input" ng-model="userType" required>
- <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
- <code>userType = {{userType}}</code><br>
- <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
- <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
- <code>myForm.$valid = {{myForm.$valid}}</code><br>
- <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should initialize to model', function() {
- var userType = element(by.binding('userType'));
- var valid = element(by.binding('myForm.input.$valid'));
-
- expect(userType.getText()).toContain('guest');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- var userType = element(by.binding('userType'));
- var valid = element(by.binding('myForm.input.$valid'));
- var userInput = element(by.model('userType'));
-
- userInput.clear();
- userInput.sendKeys('');
-
- expect(userType.getText()).toEqual('userType =');
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- *
- * @param {string=} name Name of the form. If specified, the form controller will be published into
- * related scope, under this name.
- */
-var formDirectiveFactory = function(isNgForm) {
- return ['$timeout', '$parse', function($timeout, $parse) {
- var formDirective = {
- name: 'form',
- restrict: isNgForm ? 'EAC' : 'E',
- require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form
- controller: FormController,
- compile: function ngFormCompile(formElement, attr) {
- // Setup initial state of the control
- formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
-
- var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
-
- return {
- pre: function ngFormPreLink(scope, formElement, attr, ctrls) {
- var controller = ctrls[0];
-
- // if `action` attr is not present on the form, prevent the default action (submission)
- if (!('action' in attr)) {
- // we can't use jq events because if a form is destroyed during submission the default
- // action is not prevented. see #1238
- //
- // IE 9 is not affected because it doesn't fire a submit event and try to do a full
- // page reload if the form was destroyed by submission of the form via a click handler
- // on a button in the form. Looks like an IE9 specific bug.
- var handleFormSubmission = function(event) {
- scope.$apply(function() {
- controller.$commitViewValue();
- controller.$setSubmitted();
- });
-
- event.preventDefault();
- };
-
- addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
-
- // unregister the preventDefault listener so that we don't not leak memory but in a
- // way that will achieve the prevention of the default action.
- formElement.on('$destroy', function() {
- $timeout(function() {
- removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
- }, 0, false);
- });
- }
-
- var parentFormCtrl = ctrls[1] || controller.$$parentForm;
- parentFormCtrl.$addControl(controller);
-
- var setter = nameAttr ? getSetter(controller.$name) : noop;
-
- if (nameAttr) {
- setter(scope, controller);
- attr.$observe(nameAttr, function(newValue) {
- if (controller.$name === newValue) return;
- setter(scope, undefined);
- controller.$$parentForm.$$renameControl(controller, newValue);
- setter = getSetter(controller.$name);
- setter(scope, controller);
- });
- }
- formElement.on('$destroy', function() {
- controller.$$parentForm.$removeControl(controller);
- setter(scope, undefined);
- extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
- });
- }
- };
- }
- };
-
- return formDirective;
-
- function getSetter(expression) {
- if (expression === '') {
- //create an assignable expression, so forms with an empty name can be renamed later
- return $parse('this[""]').assign;
- }
- return $parse(expression).assign || noop;
- }
- }];
-};
-
-var formDirective = formDirectiveFactory();
-var ngFormDirective = formDirectiveFactory(true);
-
-/* global VALID_CLASS: false,
- INVALID_CLASS: false,
- PRISTINE_CLASS: false,
- DIRTY_CLASS: false,
- UNTOUCHED_CLASS: false,
- TOUCHED_CLASS: false,
- ngModelMinErr: false,
-*/
-
-// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
-var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
-// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
-// Note: We are being more lenient, because browsers are too.
-// 1. Scheme
-// 2. Slashes
-// 3. Username
-// 4. Password
-// 5. Hostname
-// 6. Port
-// 7. Path
-// 8. Query
-// 9. Fragment
-// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999
-var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i;
-var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
-var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
-var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
-var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
-var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
-var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
-var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
-
-var inputType = {
-
- /**
- * @ngdoc input
- * @name input[text]
- *
- * @description
- * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
- *
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Adds `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
- * any length.
- * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
- * that contains the regular expression body that will be converted to a regular expression
- * as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- * This parameter is ignored for input[type=password] controls, which will never trim the
- * input.
- *
- * @example
- <example name="text-input-directive" module="textInputExample">
- <file name="index.html">
- <script>
- angular.module('textInputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.example = {
- text: 'guest',
- word: /^\s*\w*\s*$/
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>Single word:
- <input type="text" name="input" ng-model="example.text"
- ng-pattern="example.word" required ng-trim="false">
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.pattern">
- Single word only!</span>
- </div>
- <tt>text = {{example.text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('example.text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('guest');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
-
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if multi word', function() {
- input.clear();
- input.sendKeys('hello world');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'text': textInputType,
-
- /**
- * @ngdoc input
- * @name input[date]
- *
- * @description
- * Input with date validation and transformation. In browsers that do not yet support
- * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
- * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
- * modern browsers do not yet support this input type, it is important to provide cues to users on the
- * expected input format via a placeholder or label.
- *
- * The model must always be a Date object, otherwise Angular will throw an error.
- * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
- *
- * The timezone to be used to read/write the `Date` instance in the model can be defined using
- * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
- * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
- * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5
- * constraint validation.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
- * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute
- * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5
- * constraint validation.
- * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string
- * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
- * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string
- * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="date-input-directive" module="dateInputExample">
- <file name="index.html">
- <script>
- angular.module('dateInputExample', [])
- .controller('DateController', ['$scope', function($scope) {
- $scope.example = {
- value: new Date(2013, 9, 22)
- };
- }]);
- </script>
- <form name="myForm" ng-controller="DateController as dateCtrl">
- <label for="exampleInput">Pick a date in 2013:</label>
- <input type="date" id="exampleInput" name="input" ng-model="example.value"
- placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.date">
- Not a valid date!</span>
- </div>
- <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- // currently protractor/webdriver does not support
- // sending keys to all known HTML5 input controls
- // for various browsers (see https://github.com/angular/protractor/issues/562).
- function setInput(val) {
- // set the value of the element and force validation.
- var scr = "var ipt = document.getElementById('exampleInput'); " +
- "ipt.value = '" + val + "';" +
- "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
- browser.executeScript(scr);
- }
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('2013-10-22');
- expect(valid.getText()).toContain('myForm.input.$valid = true');
- });
-
- it('should be invalid if empty', function() {
- setInput('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
-
- it('should be invalid if over max', function() {
- setInput('2015-01-01');
- expect(value.getText()).toContain('');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
- </file>
- </example>
- */
- 'date': createDateInputType('date', DATE_REGEXP,
- createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
- 'yyyy-MM-dd'),
-
- /**
- * @ngdoc input
- * @name input[datetime-local]
- *
- * @description
- * Input with datetime validation and transformation. In browsers that do not yet support
- * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
- * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
- *
- * The model must always be a Date object, otherwise Angular will throw an error.
- * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
- *
- * The timezone to be used to read/write the `Date` instance in the model can be defined using
- * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
- * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
- * Note that `min` will also add native HTML5 constraint validation.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation
- * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`).
- * Note that `max` will also add native HTML5 constraint validation.
- * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string
- * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
- * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string
- * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="datetimelocal-input-directive" module="dateExample">
- <file name="index.html">
- <script>
- angular.module('dateExample', [])
- .controller('DateController', ['$scope', function($scope) {
- $scope.example = {
- value: new Date(2010, 11, 28, 14, 57)
- };
- }]);
- </script>
- <form name="myForm" ng-controller="DateController as dateCtrl">
- <label for="exampleInput">Pick a date between in 2013:</label>
- <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
- placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.datetimelocal">
- Not a valid date!</span>
- </div>
- <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- // currently protractor/webdriver does not support
- // sending keys to all known HTML5 input controls
- // for various browsers (https://github.com/angular/protractor/issues/562).
- function setInput(val) {
- // set the value of the element and force validation.
- var scr = "var ipt = document.getElementById('exampleInput'); " +
- "ipt.value = '" + val + "';" +
- "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
- browser.executeScript(scr);
- }
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('2010-12-28T14:57:00');
- expect(valid.getText()).toContain('myForm.input.$valid = true');
- });
-
- it('should be invalid if empty', function() {
- setInput('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
-
- it('should be invalid if over max', function() {
- setInput('2015-01-01T23:59:00');
- expect(value.getText()).toContain('');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
- </file>
- </example>
- */
- 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
- createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
- 'yyyy-MM-ddTHH:mm:ss.sss'),
-
- /**
- * @ngdoc input
- * @name input[time]
- *
- * @description
- * Input with time validation and transformation. In browsers that do not yet support
- * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
- * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
- * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
- *
- * The model must always be a Date object, otherwise Angular will throw an error.
- * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
- *
- * The timezone to be used to read/write the `Date` instance in the model can be defined using
- * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
- * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add
- * native HTML5 constraint validation.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this
- * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add
- * native HTML5 constraint validation.
- * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the
- * `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
- * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the
- * `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="time-input-directive" module="timeExample">
- <file name="index.html">
- <script>
- angular.module('timeExample', [])
- .controller('DateController', ['$scope', function($scope) {
- $scope.example = {
- value: new Date(1970, 0, 1, 14, 57, 0)
- };
- }]);
- </script>
- <form name="myForm" ng-controller="DateController as dateCtrl">
- <label for="exampleInput">Pick a between 8am and 5pm:</label>
- <input type="time" id="exampleInput" name="input" ng-model="example.value"
- placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.time">
- Not a valid date!</span>
- </div>
- <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value | date: "HH:mm:ss"'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- // currently protractor/webdriver does not support
- // sending keys to all known HTML5 input controls
- // for various browsers (https://github.com/angular/protractor/issues/562).
- function setInput(val) {
- // set the value of the element and force validation.
- var scr = "var ipt = document.getElementById('exampleInput'); " +
- "ipt.value = '" + val + "';" +
- "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
- browser.executeScript(scr);
- }
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('14:57:00');
- expect(valid.getText()).toContain('myForm.input.$valid = true');
- });
-
- it('should be invalid if empty', function() {
- setInput('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
-
- it('should be invalid if over max', function() {
- setInput('23:59:00');
- expect(value.getText()).toContain('');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
- </file>
- </example>
- */
- 'time': createDateInputType('time', TIME_REGEXP,
- createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
- 'HH:mm:ss.sss'),
-
- /**
- * @ngdoc input
- * @name input[week]
- *
- * @description
- * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
- * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
- * week format (yyyy-W##), for example: `2013-W02`.
- *
- * The model must always be a Date object, otherwise Angular will throw an error.
- * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
- *
- * The timezone to be used to read/write the `Date` instance in the model can be defined using
- * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
- * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add
- * native HTML5 constraint validation.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this
- * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add
- * native HTML5 constraint validation.
- * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
- * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
- * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
- * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="week-input-directive" module="weekExample">
- <file name="index.html">
- <script>
- angular.module('weekExample', [])
- .controller('DateController', ['$scope', function($scope) {
- $scope.example = {
- value: new Date(2013, 0, 3)
- };
- }]);
- </script>
- <form name="myForm" ng-controller="DateController as dateCtrl">
- <label>Pick a date between in 2013:
- <input id="exampleInput" type="week" name="input" ng-model="example.value"
- placeholder="YYYY-W##" min="2012-W32"
- max="2013-W52" required />
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.week">
- Not a valid date!</span>
- </div>
- <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value | date: "yyyy-Www"'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- // currently protractor/webdriver does not support
- // sending keys to all known HTML5 input controls
- // for various browsers (https://github.com/angular/protractor/issues/562).
- function setInput(val) {
- // set the value of the element and force validation.
- var scr = "var ipt = document.getElementById('exampleInput'); " +
- "ipt.value = '" + val + "';" +
- "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
- browser.executeScript(scr);
- }
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('2013-W01');
- expect(valid.getText()).toContain('myForm.input.$valid = true');
- });
-
- it('should be invalid if empty', function() {
- setInput('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
-
- it('should be invalid if over max', function() {
- setInput('2015-W01');
- expect(value.getText()).toContain('');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
- </file>
- </example>
- */
- 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
-
- /**
- * @ngdoc input
- * @name input[month]
- *
- * @description
- * Input with month validation and transformation. In browsers that do not yet support
- * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
- * month format (yyyy-MM), for example: `2009-01`.
- *
- * The model must always be a Date object, otherwise Angular will throw an error.
- * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
- * If the model is not set to the first of the month, the next view to model update will set it
- * to the first of the month.
- *
- * The timezone to be used to read/write the `Date` instance in the model can be defined using
- * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
- * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add
- * native HTML5 constraint validation.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this
- * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add
- * native HTML5 constraint validation.
- * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string
- * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.
- * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string
- * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.
-
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="month-input-directive" module="monthExample">
- <file name="index.html">
- <script>
- angular.module('monthExample', [])
- .controller('DateController', ['$scope', function($scope) {
- $scope.example = {
- value: new Date(2013, 9, 1)
- };
- }]);
- </script>
- <form name="myForm" ng-controller="DateController as dateCtrl">
- <label for="exampleInput">Pick a month in 2013:</label>
- <input id="exampleInput" type="month" name="input" ng-model="example.value"
- placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.month">
- Not a valid month!</span>
- </div>
- <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value | date: "yyyy-MM"'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- // currently protractor/webdriver does not support
- // sending keys to all known HTML5 input controls
- // for various browsers (https://github.com/angular/protractor/issues/562).
- function setInput(val) {
- // set the value of the element and force validation.
- var scr = "var ipt = document.getElementById('exampleInput'); " +
- "ipt.value = '" + val + "';" +
- "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
- browser.executeScript(scr);
- }
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('2013-10');
- expect(valid.getText()).toContain('myForm.input.$valid = true');
- });
-
- it('should be invalid if empty', function() {
- setInput('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
-
- it('should be invalid if over max', function() {
- setInput('2015-01');
- expect(value.getText()).toContain('');
- expect(valid.getText()).toContain('myForm.input.$valid = false');
- });
- </file>
- </example>
- */
- 'month': createDateInputType('month', MONTH_REGEXP,
- createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
- 'yyyy-MM'),
-
- /**
- * @ngdoc input
- * @name input[number]
- *
- * @description
- * Text input with number validation and transformation. Sets the `number` validation
- * error if not a valid number.
- *
- * <div class="alert alert-warning">
- * The model must always be of type `number` otherwise Angular will throw an error.
- * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
- * error docs for more information and an example of how to convert your model if necessary.
- * </div>
- *
- * ## Issues with HTML5 constraint validation
- *
- * In browsers that follow the
- * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
- * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
- * If a non-number is entered in the input, the browser will report the value as an empty string,
- * which means the view / model values in `ngModel` and subsequently the scope value
- * will also be an empty string.
- *
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
- * any length.
- * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
- * that contains the regular expression body that will be converted to a regular expression
- * as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="number-input-directive" module="numberExample">
- <file name="index.html">
- <script>
- angular.module('numberExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.example = {
- value: 12
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>Number:
- <input type="number" name="input" ng-model="example.value"
- min="0" max="99" required>
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.number">
- Not valid number!</span>
- </div>
- <tt>value = {{example.value}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('example.value'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('example.value'));
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('12');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if over max', function() {
- input.clear();
- input.sendKeys('123');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'number': numberInputType,
-
-
- /**
- * @ngdoc input
- * @name input[url]
- *
- * @description
- * Text input with URL validation. Sets the `url` validation error key if the content is not a
- * valid URL.
- *
- * <div class="alert alert-warning">
- * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
- * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
- * the built-in validators (see the {@link guide/forms Forms guide})
- * </div>
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
- * any length.
- * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
- * that contains the regular expression body that will be converted to a regular expression
- * as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="url-input-directive" module="urlExample">
- <file name="index.html">
- <script>
- angular.module('urlExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.url = {
- text: 'http://google.com'
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>URL:
- <input type="url" name="input" ng-model="url.text" required>
- <label>
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.url">
- Not valid url!</span>
- </div>
- <tt>text = {{url.text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('url.text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('url.text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('http://google.com');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
-
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if not url', function() {
- input.clear();
- input.sendKeys('box');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'url': urlInputType,
-
-
- /**
- * @ngdoc input
- * @name input[email]
- *
- * @description
- * Text input with email validation. Sets the `email` validation error key if not a valid email
- * address.
- *
- * <div class="alert alert-warning">
- * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
- * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
- * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
- * </div>
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
- * any length.
- * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
- * that contains the regular expression body that will be converted to a regular expression
- * as in the ngPattern directive.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="email-input-directive" module="emailExample">
- <file name="index.html">
- <script>
- angular.module('emailExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.email = {
- text: 'me@example.com'
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>Email:
- <input type="email" name="input" ng-model="email.text" required>
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.email">
- Not valid email!</span>
- </div>
- <tt>text = {{email.text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('email.text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('email.text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('me@example.com');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if not email', function() {
- input.clear();
- input.sendKeys('xxx');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'email': emailInputType,
-
-
- /**
- * @ngdoc input
- * @name input[radio]
- *
- * @description
- * HTML radio button.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string} value The value to which the `ngModel` expression should be set when selected.
- * Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
- * too. Use `ngValue` if you need complex models (`number`, `object`, ...).
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
- * is selected. Should be used instead of the `value` attribute if you need
- * a non-string `ngModel` (`boolean`, `array`, ...).
- *
- * @example
- <example name="radio-input-directive" module="radioExample">
- <file name="index.html">
- <script>
- angular.module('radioExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.color = {
- name: 'blue'
- };
- $scope.specialValue = {
- "id": "12345",
- "value": "green"
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>
- <input type="radio" ng-model="color.name" value="red">
- Red
- </label><br/>
- <label>
- <input type="radio" ng-model="color.name" ng-value="specialValue">
- Green
- </label><br/>
- <label>
- <input type="radio" ng-model="color.name" value="blue">
- Blue
- </label><br/>
- <tt>color = {{color.name | json}}</tt><br/>
- </form>
- Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
- </file>
- <file name="protractor.js" type="protractor">
- it('should change state', function() {
- var color = element(by.binding('color.name'));
-
- expect(color.getText()).toContain('blue');
-
- element.all(by.model('color.name')).get(0).click();
-
- expect(color.getText()).toContain('red');
- });
- </file>
- </example>
- */
- 'radio': radioInputType,
-
-
- /**
- * @ngdoc input
- * @name input[checkbox]
- *
- * @description
- * HTML checkbox.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
- * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="checkbox-input-directive" module="checkboxExample">
- <file name="index.html">
- <script>
- angular.module('checkboxExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.checkboxModel = {
- value1 : true,
- value2 : 'YES'
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <label>Value1:
- <input type="checkbox" ng-model="checkboxModel.value1">
- </label><br/>
- <label>Value2:
- <input type="checkbox" ng-model="checkboxModel.value2"
- ng-true-value="'YES'" ng-false-value="'NO'">
- </label><br/>
- <tt>value1 = {{checkboxModel.value1}}</tt><br/>
- <tt>value2 = {{checkboxModel.value2}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should change state', function() {
- var value1 = element(by.binding('checkboxModel.value1'));
- var value2 = element(by.binding('checkboxModel.value2'));
-
- expect(value1.getText()).toContain('true');
- expect(value2.getText()).toContain('YES');
-
- element(by.model('checkboxModel.value1')).click();
- element(by.model('checkboxModel.value2')).click();
-
- expect(value1.getText()).toContain('false');
- expect(value2.getText()).toContain('NO');
- });
- </file>
- </example>
- */
- 'checkbox': checkboxInputType,
-
- 'hidden': noop,
- 'button': noop,
- 'submit': noop,
- 'reset': noop,
- 'file': noop
-};
-
-function stringBasedInputType(ctrl) {
- ctrl.$formatters.push(function(value) {
- return ctrl.$isEmpty(value) ? value : value.toString();
- });
-}
-
-function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
- stringBasedInputType(ctrl);
-}
-
-function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- var type = lowercase(element[0].type);
-
- // In composition mode, users are still inputing intermediate text buffer,
- // hold the listener until composition is done.
- // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
- if (!$sniffer.android) {
- var composing = false;
-
- element.on('compositionstart', function(data) {
- composing = true;
- });
-
- element.on('compositionend', function() {
- composing = false;
- listener();
- });
- }
-
- var listener = function(ev) {
- if (timeout) {
- $browser.defer.cancel(timeout);
- timeout = null;
- }
- if (composing) return;
- var value = element.val(),
- event = ev && ev.type;
-
- // By default we will trim the value
- // If the attribute ng-trim exists we will avoid trimming
- // If input type is 'password', the value is never trimmed
- if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
- value = trim(value);
- }
-
- // If a control is suffering from bad input (due to native validators), browsers discard its
- // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
- // control's value is the same empty value twice in a row.
- if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
- ctrl.$setViewValue(value, event);
- }
- };
-
- // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
- // input event on backspace, delete or cut
- if ($sniffer.hasEvent('input')) {
- element.on('input', listener);
- } else {
- var timeout;
-
- var deferListener = function(ev, input, origValue) {
- if (!timeout) {
- timeout = $browser.defer(function() {
- timeout = null;
- if (!input || input.value !== origValue) {
- listener(ev);
- }
- });
- }
- };
-
- element.on('keydown', function(event) {
- var key = event.keyCode;
-
- // ignore
- // command modifiers arrows
- if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
-
- deferListener(event, this, this.value);
- });
-
- // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
- if ($sniffer.hasEvent('paste')) {
- element.on('paste cut', deferListener);
- }
- }
-
- // if user paste into input using mouse on older browser
- // or form autocomplete on newer browser, we need "change" event to catch it
- element.on('change', listener);
-
- ctrl.$render = function() {
- // Workaround for Firefox validation #12102.
- var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
- if (element.val() !== value) {
- element.val(value);
- }
- };
-}
-
-function weekParser(isoWeek, existingDate) {
- if (isDate(isoWeek)) {
- return isoWeek;
- }
-
- if (isString(isoWeek)) {
- WEEK_REGEXP.lastIndex = 0;
- var parts = WEEK_REGEXP.exec(isoWeek);
- if (parts) {
- var year = +parts[1],
- week = +parts[2],
- hours = 0,
- minutes = 0,
- seconds = 0,
- milliseconds = 0,
- firstThurs = getFirstThursdayOfYear(year),
- addDays = (week - 1) * 7;
-
- if (existingDate) {
- hours = existingDate.getHours();
- minutes = existingDate.getMinutes();
- seconds = existingDate.getSeconds();
- milliseconds = existingDate.getMilliseconds();
- }
-
- return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
- }
- }
-
- return NaN;
-}
-
-function createDateParser(regexp, mapping) {
- return function(iso, date) {
- var parts, map;
-
- if (isDate(iso)) {
- return iso;
- }
-
- if (isString(iso)) {
- // When a date is JSON'ified to wraps itself inside of an extra
- // set of double quotes. This makes the date parsing code unable
- // to match the date string and parse it as a date.
- if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
- iso = iso.substring(1, iso.length - 1);
- }
- if (ISO_DATE_REGEXP.test(iso)) {
- return new Date(iso);
- }
- regexp.lastIndex = 0;
- parts = regexp.exec(iso);
-
- if (parts) {
- parts.shift();
- if (date) {
- map = {
- yyyy: date.getFullYear(),
- MM: date.getMonth() + 1,
- dd: date.getDate(),
- HH: date.getHours(),
- mm: date.getMinutes(),
- ss: date.getSeconds(),
- sss: date.getMilliseconds() / 1000
- };
- } else {
- map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
- }
-
- forEach(parts, function(part, index) {
- if (index < mapping.length) {
- map[mapping[index]] = +part;
- }
- });
- return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
- }
- }
-
- return NaN;
- };
-}
-
-function createDateInputType(type, regexp, parseDate, format) {
- return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
- badInputChecker(scope, element, attr, ctrl);
- baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
- var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
- var previousDate;
-
- ctrl.$$parserName = type;
- ctrl.$parsers.push(function(value) {
- if (ctrl.$isEmpty(value)) return null;
- if (regexp.test(value)) {
- // Note: We cannot read ctrl.$modelValue, as there might be a different
- // parser/formatter in the processing chain so that the model
- // contains some different data format!
- var parsedDate = parseDate(value, previousDate);
- if (timezone) {
- parsedDate = convertTimezoneToLocal(parsedDate, timezone);
- }
- return parsedDate;
- }
- return undefined;
- });
-
- ctrl.$formatters.push(function(value) {
- if (value && !isDate(value)) {
- throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
- }
- if (isValidDate(value)) {
- previousDate = value;
- if (previousDate && timezone) {
- previousDate = convertTimezoneToLocal(previousDate, timezone, true);
- }
- return $filter('date')(value, format, timezone);
- } else {
- previousDate = null;
- return '';
- }
- });
-
- if (isDefined(attr.min) || attr.ngMin) {
- var minVal;
- ctrl.$validators.min = function(value) {
- return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
- };
- attr.$observe('min', function(val) {
- minVal = parseObservedDateValue(val);
- ctrl.$validate();
- });
- }
-
- if (isDefined(attr.max) || attr.ngMax) {
- var maxVal;
- ctrl.$validators.max = function(value) {
- return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
- };
- attr.$observe('max', function(val) {
- maxVal = parseObservedDateValue(val);
- ctrl.$validate();
- });
- }
-
- function isValidDate(value) {
- // Invalid Date: getTime() returns NaN
- return value && !(value.getTime && value.getTime() !== value.getTime());
- }
-
- function parseObservedDateValue(val) {
- return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
- }
- };
-}
-
-function badInputChecker(scope, element, attr, ctrl) {
- var node = element[0];
- var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
- if (nativeValidation) {
- ctrl.$parsers.push(function(value) {
- var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
- return validity.badInput || validity.typeMismatch ? undefined : value;
- });
- }
-}
-
-function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- badInputChecker(scope, element, attr, ctrl);
- baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
- ctrl.$$parserName = 'number';
- ctrl.$parsers.push(function(value) {
- if (ctrl.$isEmpty(value)) return null;
- if (NUMBER_REGEXP.test(value)) return parseFloat(value);
- return undefined;
- });
-
- ctrl.$formatters.push(function(value) {
- if (!ctrl.$isEmpty(value)) {
- if (!isNumber(value)) {
- throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
- }
- value = value.toString();
- }
- return value;
- });
-
- if (isDefined(attr.min) || attr.ngMin) {
- var minVal;
- ctrl.$validators.min = function(value) {
- return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
- };
-
- attr.$observe('min', function(val) {
- if (isDefined(val) && !isNumber(val)) {
- val = parseFloat(val, 10);
- }
- minVal = isNumber(val) && !isNaN(val) ? val : undefined;
- // TODO(matsko): implement validateLater to reduce number of validations
- ctrl.$validate();
- });
- }
-
- if (isDefined(attr.max) || attr.ngMax) {
- var maxVal;
- ctrl.$validators.max = function(value) {
- return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
- };
-
- attr.$observe('max', function(val) {
- if (isDefined(val) && !isNumber(val)) {
- val = parseFloat(val, 10);
- }
- maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
- // TODO(matsko): implement validateLater to reduce number of validations
- ctrl.$validate();
- });
- }
-}
-
-function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- // Note: no badInputChecker here by purpose as `url` is only a validation
- // in browsers, i.e. we can always read out input.value even if it is not valid!
- baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
- stringBasedInputType(ctrl);
-
- ctrl.$$parserName = 'url';
- ctrl.$validators.url = function(modelValue, viewValue) {
- var value = modelValue || viewValue;
- return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
- };
-}
-
-function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- // Note: no badInputChecker here by purpose as `url` is only a validation
- // in browsers, i.e. we can always read out input.value even if it is not valid!
- baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
- stringBasedInputType(ctrl);
-
- ctrl.$$parserName = 'email';
- ctrl.$validators.email = function(modelValue, viewValue) {
- var value = modelValue || viewValue;
- return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
- };
-}
-
-function radioInputType(scope, element, attr, ctrl) {
- // make the name unique, if not defined
- if (isUndefined(attr.name)) {
- element.attr('name', nextUid());
- }
-
- var listener = function(ev) {
- if (element[0].checked) {
- ctrl.$setViewValue(attr.value, ev && ev.type);
- }
- };
-
- element.on('click', listener);
-
- ctrl.$render = function() {
- var value = attr.value;
- element[0].checked = (value == ctrl.$viewValue);
- };
-
- attr.$observe('value', ctrl.$render);
-}
-
-function parseConstantExpr($parse, context, name, expression, fallback) {
- var parseFn;
- if (isDefined(expression)) {
- parseFn = $parse(expression);
- if (!parseFn.constant) {
- throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +
- '`{1}`.', name, expression);
- }
- return parseFn(context);
- }
- return fallback;
-}
-
-function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
- var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
- var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
-
- var listener = function(ev) {
- ctrl.$setViewValue(element[0].checked, ev && ev.type);
- };
-
- element.on('click', listener);
-
- ctrl.$render = function() {
- element[0].checked = ctrl.$viewValue;
- };
-
- // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
- // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
- // it to a boolean.
- ctrl.$isEmpty = function(value) {
- return value === false;
- };
-
- ctrl.$formatters.push(function(value) {
- return equals(value, trueValue);
- });
-
- ctrl.$parsers.push(function(value) {
- return value ? trueValue : falseValue;
- });
-}
-
-
-/**
- * @ngdoc directive
- * @name textarea
- * @restrict E
- *
- * @description
- * HTML textarea element control with angular data-binding. The data-binding and validation
- * properties of this element are exactly the same as those of the
- * {@link ng.directive:input input element}.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
- * length.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- */
-
-
-/**
- * @ngdoc directive
- * @name input
- * @restrict E
- *
- * @description
- * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
- * input state control, and validation.
- * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
- *
- * <div class="alert alert-warning">
- * **Note:** Not every feature offered is available for all input types.
- * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
- * </div>
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {boolean=} ngRequired Sets `required` attribute if set to true
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
- * length.
- * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}
- * value does not match a RegExp found by evaluating the Angular expression given in the attribute value.
- * If the expression evaluates to a RegExp object, then this is used directly.
- * If the expression evaluates to a string, then it will be converted to a RegExp
- * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
- * `new RegExp('^abc$')`.<br />
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- * This parameter is ignored for input[type=password] controls, which will never trim the
- * input.
- *
- * @example
- <example name="input-directive" module="inputExample">
- <file name="index.html">
- <script>
- angular.module('inputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = {name: 'guest', last: 'visitor'};
- }]);
- </script>
- <div ng-controller="ExampleController">
- <form name="myForm">
- <label>
- User name:
- <input type="text" name="userName" ng-model="user.name" required>
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.userName.$error.required">
- Required!</span>
- </div>
- <label>
- Last name:
- <input type="text" name="lastName" ng-model="user.last"
- ng-minlength="3" ng-maxlength="10">
- </label>
- <div role="alert">
- <span class="error" ng-show="myForm.lastName.$error.minlength">
- Too short!</span>
- <span class="error" ng-show="myForm.lastName.$error.maxlength">
- Too long!</span>
- </div>
- </form>
- <hr>
- <tt>user = {{user}}</tt><br/>
- <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>
- <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>
- <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>
- <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>
- <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- var user = element(by.exactBinding('user'));
- var userNameValid = element(by.binding('myForm.userName.$valid'));
- var lastNameValid = element(by.binding('myForm.lastName.$valid'));
- var lastNameError = element(by.binding('myForm.lastName.$error'));
- var formValid = element(by.binding('myForm.$valid'));
- var userNameInput = element(by.model('user.name'));
- var userLastInput = element(by.model('user.last'));
-
- it('should initialize to model', function() {
- expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
- expect(userNameValid.getText()).toContain('true');
- expect(formValid.getText()).toContain('true');
- });
-
- it('should be invalid if empty when required', function() {
- userNameInput.clear();
- userNameInput.sendKeys('');
-
- expect(user.getText()).toContain('{"last":"visitor"}');
- expect(userNameValid.getText()).toContain('false');
- expect(formValid.getText()).toContain('false');
- });
-
- it('should be valid if empty when min length is set', function() {
- userLastInput.clear();
- userLastInput.sendKeys('');
-
- expect(user.getText()).toContain('{"name":"guest","last":""}');
- expect(lastNameValid.getText()).toContain('true');
- expect(formValid.getText()).toContain('true');
- });
-
- it('should be invalid if less than required min length', function() {
- userLastInput.clear();
- userLastInput.sendKeys('xx');
-
- expect(user.getText()).toContain('{"name":"guest"}');
- expect(lastNameValid.getText()).toContain('false');
- expect(lastNameError.getText()).toContain('minlength');
- expect(formValid.getText()).toContain('false');
- });
-
- it('should be invalid if longer than max length', function() {
- userLastInput.clear();
- userLastInput.sendKeys('some ridiculously long name');
-
- expect(user.getText()).toContain('{"name":"guest"}');
- expect(lastNameValid.getText()).toContain('false');
- expect(lastNameError.getText()).toContain('maxlength');
- expect(formValid.getText()).toContain('false');
- });
- </file>
- </example>
- */
-var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
- function($browser, $sniffer, $filter, $parse) {
- return {
- restrict: 'E',
- require: ['?ngModel'],
- link: {
- pre: function(scope, element, attr, ctrls) {
- if (ctrls[0]) {
- (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
- $browser, $filter, $parse);
- }
- }
- }
- };
-}];
-
-
-
-var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
-/**
- * @ngdoc directive
- * @name ngValue
- *
- * @description
- * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
- * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
- * the bound value.
- *
- * `ngValue` is useful when dynamically generating lists of radio buttons using
- * {@link ngRepeat `ngRepeat`}, as shown below.
- *
- * Likewise, `ngValue` can be used to generate `<option>` elements for
- * the {@link select `select`} element. In that case however, only strings are supported
- * for the `value `attribute, so the resulting `ngModel` will always be a string.
- * Support for `select` models with non-string values is available via `ngOptions`.
- *
- * @element input
- * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
- * of the `input` element
- *
- * @example
- <example name="ngValue-directive" module="valueExample">
- <file name="index.html">
- <script>
- angular.module('valueExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.names = ['pizza', 'unicorns', 'robots'];
- $scope.my = { favorite: 'unicorns' };
- }]);
- </script>
- <form ng-controller="ExampleController">
- <h2>Which is your favorite?</h2>
- <label ng-repeat="name in names" for="{{name}}">
- {{name}}
- <input type="radio"
- ng-model="my.favorite"
- ng-value="name"
- id="{{name}}"
- name="favorite">
- </label>
- <div>You chose {{my.favorite}}</div>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var favorite = element(by.binding('my.favorite'));
-
- it('should initialize to model', function() {
- expect(favorite.getText()).toContain('unicorns');
- });
- it('should bind the values to the inputs', function() {
- element.all(by.model('my.favorite')).get(0).click();
- expect(favorite.getText()).toContain('pizza');
- });
- </file>
- </example>
- */
-var ngValueDirective = function() {
- return {
- restrict: 'A',
- priority: 100,
- compile: function(tpl, tplAttr) {
- if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
- return function ngValueConstantLink(scope, elm, attr) {
- attr.$set('value', scope.$eval(attr.ngValue));
- };
- } else {
- return function ngValueLink(scope, elm, attr) {
- scope.$watch(attr.ngValue, function valueWatchAction(value) {
- attr.$set('value', value);
- });
- };
- }
- }
- };
-};
-
-/**
- * @ngdoc directive
- * @name ngBind
- * @restrict AC
- *
- * @description
- * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
- * with the value of a given expression, and to update the text content when the value of that
- * expression changes.
- *
- * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
- * `{{ expression }}` which is similar but less verbose.
- *
- * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
- * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
- * element attribute, it makes the bindings invisible to the user while the page is loading.
- *
- * An alternative solution to this problem would be using the
- * {@link ng.directive:ngCloak ngCloak} directive.
- *
- *
- * @element ANY
- * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
- *
- * @example
- * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.name = 'Whirled';
- }]);
- </script>
- <div ng-controller="ExampleController">
- <label>Enter name: <input type="text" ng-model="name"></label><br>
- Hello <span ng-bind="name"></span>!
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var nameInput = element(by.model('name'));
-
- expect(element(by.binding('name')).getText()).toBe('Whirled');
- nameInput.clear();
- nameInput.sendKeys('world');
- expect(element(by.binding('name')).getText()).toBe('world');
- });
- </file>
- </example>
- */
-var ngBindDirective = ['$compile', function($compile) {
- return {
- restrict: 'AC',
- compile: function ngBindCompile(templateElement) {
- $compile.$$addBindingClass(templateElement);
- return function ngBindLink(scope, element, attr) {
- $compile.$$addBindingInfo(element, attr.ngBind);
- element = element[0];
- scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
- element.textContent = isUndefined(value) ? '' : value;
- });
- };
- }
- };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngBindTemplate
- *
- * @description
- * The `ngBindTemplate` directive specifies that the element
- * text content should be replaced with the interpolation of the template
- * in the `ngBindTemplate` attribute.
- * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
- * expressions. This directive is needed since some HTML elements
- * (such as TITLE and OPTION) cannot contain SPAN elements.
- *
- * @element ANY
- * @param {string} ngBindTemplate template of form
- * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
- *
- * @example
- * Try it here: enter text in text box and watch the greeting change.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.salutation = 'Hello';
- $scope.name = 'World';
- }]);
- </script>
- <div ng-controller="ExampleController">
- <label>Salutation: <input type="text" ng-model="salutation"></label><br>
- <label>Name: <input type="text" ng-model="name"></label><br>
- <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var salutationElem = element(by.binding('salutation'));
- var salutationInput = element(by.model('salutation'));
- var nameInput = element(by.model('name'));
-
- expect(salutationElem.getText()).toBe('Hello World!');
-
- salutationInput.clear();
- salutationInput.sendKeys('Greetings');
- nameInput.clear();
- nameInput.sendKeys('user');
-
- expect(salutationElem.getText()).toBe('Greetings user!');
- });
- </file>
- </example>
- */
-var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
- return {
- compile: function ngBindTemplateCompile(templateElement) {
- $compile.$$addBindingClass(templateElement);
- return function ngBindTemplateLink(scope, element, attr) {
- var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
- $compile.$$addBindingInfo(element, interpolateFn.expressions);
- element = element[0];
- attr.$observe('ngBindTemplate', function(value) {
- element.textContent = isUndefined(value) ? '' : value;
- });
- };
- }
- };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngBindHtml
- *
- * @description
- * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
- * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
- * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
- * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
- * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
- *
- * You may also bypass sanitization for values you know are safe. To do so, bind to
- * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
- * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
- *
- * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
- * will have an exception (instead of an exploit.)
- *
- * @element ANY
- * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
- *
- * @example
-
- <example module="bindHtmlExample" deps="angular-sanitize.js">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p ng-bind-html="myHTML"></p>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('bindHtmlExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.myHTML =
- 'I am an <code>HTML</code>string with ' +
- '<a href="#">links!</a> and other <em>stuff</em>';
- }]);
- </file>
-
- <file name="protractor.js" type="protractor">
- it('should check ng-bind-html', function() {
- expect(element(by.binding('myHTML')).getText()).toBe(
- 'I am an HTMLstring with links! and other stuff');
- });
- </file>
- </example>
- */
-var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
- return {
- restrict: 'A',
- compile: function ngBindHtmlCompile(tElement, tAttrs) {
- var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
- var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
- return (value || '').toString();
- });
- $compile.$$addBindingClass(tElement);
-
- return function ngBindHtmlLink(scope, element, attr) {
- $compile.$$addBindingInfo(element, attr.ngBindHtml);
-
- scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
- // we re-evaluate the expr because we want a TrustedValueHolderType
- // for $sce, not a string
- element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
- });
- };
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngChange
- *
- * @description
- * Evaluate the given expression when the user changes the input.
- * The expression is evaluated immediately, unlike the JavaScript onchange event
- * which only triggers at the end of a change (usually, when the user leaves the
- * form element or presses the return key).
- *
- * The `ngChange` expression is only evaluated when a change in the input value causes
- * a new value to be committed to the model.
- *
- * It will not be evaluated:
- * * if the value returned from the `$parsers` transformation pipeline has not changed
- * * if the input has continued to be invalid since the model will stay `null`
- * * if the model is changed programmatically and not by a change to the input value
- *
- *
- * Note, this directive requires `ngModel` to be present.
- *
- * @element input
- * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
- * in input value.
- *
- * @example
- * <example name="ngChange-directive" module="changeExample">
- * <file name="index.html">
- * <script>
- * angular.module('changeExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.counter = 0;
- * $scope.change = function() {
- * $scope.counter++;
- * };
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
- * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
- * <label for="ng-change-example2">Confirmed</label><br />
- * <tt>debug = {{confirmed}}</tt><br/>
- * <tt>counter = {{counter}}</tt><br/>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- * var counter = element(by.binding('counter'));
- * var debug = element(by.binding('confirmed'));
- *
- * it('should evaluate the expression if changing from view', function() {
- * expect(counter.getText()).toContain('0');
- *
- * element(by.id('ng-change-example1')).click();
- *
- * expect(counter.getText()).toContain('1');
- * expect(debug.getText()).toContain('true');
- * });
- *
- * it('should not evaluate the expression if changing from model', function() {
- * element(by.id('ng-change-example2')).click();
-
- * expect(counter.getText()).toContain('0');
- * expect(debug.getText()).toContain('true');
- * });
- * </file>
- * </example>
- */
-var ngChangeDirective = valueFn({
- restrict: 'A',
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- ctrl.$viewChangeListeners.push(function() {
- scope.$eval(attr.ngChange);
- });
- }
-});
-
-function classDirective(name, selector) {
- name = 'ngClass' + name;
- return ['$animate', function($animate) {
- return {
- restrict: 'AC',
- link: function(scope, element, attr) {
- var oldVal;
-
- scope.$watch(attr[name], ngClassWatchAction, true);
-
- attr.$observe('class', function(value) {
- ngClassWatchAction(scope.$eval(attr[name]));
- });
-
-
- if (name !== 'ngClass') {
- scope.$watch('$index', function($index, old$index) {
- // jshint bitwise: false
- var mod = $index & 1;
- if (mod !== (old$index & 1)) {
- var classes = arrayClasses(scope.$eval(attr[name]));
- mod === selector ?
- addClasses(classes) :
- removeClasses(classes);
- }
- });
- }
-
- function addClasses(classes) {
- var newClasses = digestClassCounts(classes, 1);
- attr.$addClass(newClasses);
- }
-
- function removeClasses(classes) {
- var newClasses = digestClassCounts(classes, -1);
- attr.$removeClass(newClasses);
- }
-
- function digestClassCounts(classes, count) {
- // Use createMap() to prevent class assumptions involving property
- // names in Object.prototype
- var classCounts = element.data('$classCounts') || createMap();
- var classesToUpdate = [];
- forEach(classes, function(className) {
- if (count > 0 || classCounts[className]) {
- classCounts[className] = (classCounts[className] || 0) + count;
- if (classCounts[className] === +(count > 0)) {
- classesToUpdate.push(className);
- }
- }
- });
- element.data('$classCounts', classCounts);
- return classesToUpdate.join(' ');
- }
-
- function updateClasses(oldClasses, newClasses) {
- var toAdd = arrayDifference(newClasses, oldClasses);
- var toRemove = arrayDifference(oldClasses, newClasses);
- toAdd = digestClassCounts(toAdd, 1);
- toRemove = digestClassCounts(toRemove, -1);
- if (toAdd && toAdd.length) {
- $animate.addClass(element, toAdd);
- }
- if (toRemove && toRemove.length) {
- $animate.removeClass(element, toRemove);
- }
- }
-
- function ngClassWatchAction(newVal) {
- if (selector === true || scope.$index % 2 === selector) {
- var newClasses = arrayClasses(newVal || []);
- if (!oldVal) {
- addClasses(newClasses);
- } else if (!equals(newVal,oldVal)) {
- var oldClasses = arrayClasses(oldVal);
- updateClasses(oldClasses, newClasses);
- }
- }
- oldVal = shallowCopy(newVal);
- }
- }
- };
-
- function arrayDifference(tokens1, tokens2) {
- var values = [];
-
- outer:
- for (var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for (var j = 0; j < tokens2.length; j++) {
- if (token == tokens2[j]) continue outer;
- }
- values.push(token);
- }
- return values;
- }
-
- function arrayClasses(classVal) {
- var classes = [];
- if (isArray(classVal)) {
- forEach(classVal, function(v) {
- classes = classes.concat(arrayClasses(v));
- });
- return classes;
- } else if (isString(classVal)) {
- return classVal.split(' ');
- } else if (isObject(classVal)) {
- forEach(classVal, function(v, k) {
- if (v) {
- classes = classes.concat(k.split(' '));
- }
- });
- return classes;
- }
- return classVal;
- }
- }];
-}
-
-/**
- * @ngdoc directive
- * @name ngClass
- * @restrict AC
- *
- * @description
- * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
- * an expression that represents all classes to be added.
- *
- * The directive operates in three different ways, depending on which of three types the expression
- * evaluates to:
- *
- * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
- * names.
- *
- * 2. If the expression evaluates to an object, then for each key-value pair of the
- * object with a truthy value the corresponding key is used as a class name.
- *
- * 3. If the expression evaluates to an array, each element of the array should either be a string as in
- * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array
- * to give you more control over what CSS classes appear. See the code below for an example of this.
- *
- *
- * The directive won't add duplicate classes if a particular class was already set.
- *
- * When the expression changes, the previously added classes are removed and only then are the
- * new classes added.
- *
- * @animations
- * **add** - happens just before the class is applied to the elements
- *
- * **remove** - happens just before the class is removed from the element
- *
- * @element ANY
- * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class
- * names, an array, or a map of class names to boolean values. In the case of a map, the
- * names of the properties whose values are truthy will be added as css classes to the
- * element.
- *
- * @example Example that demonstrates basic bindings via ngClass directive.
- <example>
- <file name="index.html">
- <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
- <label>
- <input type="checkbox" ng-model="deleted">
- deleted (apply "strike" class)
- </label><br>
- <label>
- <input type="checkbox" ng-model="important">
- important (apply "bold" class)
- </label><br>
- <label>
- <input type="checkbox" ng-model="error">
- error (apply "has-error" class)
- </label>
- <hr>
- <p ng-class="style">Using String Syntax</p>
- <input type="text" ng-model="style"
- placeholder="Type: bold strike red" aria-label="Type: bold strike red">
- <hr>
- <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
- <input ng-model="style1"
- placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br>
- <input ng-model="style2"
- placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br>
- <input ng-model="style3"
- placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br>
- <hr>
- <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p>
- <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br>
- <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label>
- </file>
- <file name="style.css">
- .strike {
- text-decoration: line-through;
- }
- .bold {
- font-weight: bold;
- }
- .red {
- color: red;
- }
- .has-error {
- color: red;
- background-color: yellow;
- }
- .orange {
- color: orange;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var ps = element.all(by.css('p'));
-
- it('should let you toggle the class', function() {
-
- expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
- expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
-
- element(by.model('important')).click();
- expect(ps.first().getAttribute('class')).toMatch(/bold/);
-
- element(by.model('error')).click();
- expect(ps.first().getAttribute('class')).toMatch(/has-error/);
- });
-
- it('should let you toggle string example', function() {
- expect(ps.get(1).getAttribute('class')).toBe('');
- element(by.model('style')).clear();
- element(by.model('style')).sendKeys('red');
- expect(ps.get(1).getAttribute('class')).toBe('red');
- });
-
- it('array example should have 3 classes', function() {
- expect(ps.get(2).getAttribute('class')).toBe('');
- element(by.model('style1')).sendKeys('bold');
- element(by.model('style2')).sendKeys('strike');
- element(by.model('style3')).sendKeys('red');
- expect(ps.get(2).getAttribute('class')).toBe('bold strike red');
- });
-
- it('array with map example should have 2 classes', function() {
- expect(ps.last().getAttribute('class')).toBe('');
- element(by.model('style4')).sendKeys('bold');
- element(by.model('warning')).click();
- expect(ps.last().getAttribute('class')).toBe('bold orange');
- });
- </file>
- </example>
-
- ## Animations
-
- The example below demonstrates how to perform animations using ngClass.
-
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
- <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
- <br>
- <span class="base-class" ng-class="myVar">Sample Text</span>
- </file>
- <file name="style.css">
- .base-class {
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- }
-
- .base-class.my-class {
- color: red;
- font-size:3em;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class', function() {
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
-
- element(by.id('setbtn')).click();
-
- expect(element(by.css('.base-class')).getAttribute('class')).
- toMatch(/my-class/);
-
- element(by.id('clearbtn')).click();
-
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
- });
- </file>
- </example>
-
-
- ## ngClass and pre-existing CSS3 Transitions/Animations
- The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
- Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
- any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
- to view the step by step details of {@link $animate#addClass $animate.addClass} and
- {@link $animate#removeClass $animate.removeClass}.
- */
-var ngClassDirective = classDirective('', true);
-
-/**
- * @ngdoc directive
- * @name ngClassOdd
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}}
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
-var ngClassOddDirective = classDirective('Odd', 0);
-
-/**
- * @ngdoc directive
- * @name ngClassEven
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
- * result of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}} &nbsp; &nbsp; &nbsp;
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
-var ngClassEvenDirective = classDirective('Even', 1);
-
-/**
- * @ngdoc directive
- * @name ngCloak
- * @restrict AC
- *
- * @description
- * The `ngCloak` directive is used to prevent the Angular html template from being briefly
- * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
- * directive to avoid the undesirable flicker effect caused by the html template display.
- *
- * The directive can be applied to the `<body>` element, but the preferred usage is to apply
- * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
- * of the browser view.
- *
- * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
- * `angular.min.js`.
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```css
- * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- * display: none !important;
- * }
- * ```
- *
- * When this css rule is loaded by the browser, all html elements (including their children) that
- * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
- * during the compilation of the template it deletes the `ngCloak` element attribute, making
- * the compiled element visible.
- *
- * For the best result, the `angular.js` script must be loaded in the head section of the html
- * document; alternatively, the css rule above must be included in the external stylesheet of the
- * application.
- *
- * @element ANY
- *
- * @example
- <example>
- <file name="index.html">
- <div id="template1" ng-cloak>{{ 'hello' }}</div>
- <div id="template2" class="ng-cloak">{{ 'world' }}</div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should remove the template directive and css class', function() {
- expect($('#template1').getAttribute('ng-cloak')).
- toBeNull();
- expect($('#template2').getAttribute('ng-cloak')).
- toBeNull();
- });
- </file>
- </example>
- *
- */
-var ngCloakDirective = ngDirective({
- compile: function(element, attr) {
- attr.$set('ngCloak', undefined);
- element.removeClass('ng-cloak');
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngController
- *
- * @description
- * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
- * supports the principles behind the Model-View-Controller design pattern.
- *
- * MVC components in angular:
- *
- * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
- * are accessed through bindings.
- * * View — The template (HTML with data bindings) that is rendered into the View.
- * * Controller — The `ngController` directive specifies a Controller class; the class contains business
- * logic behind the application to decorate the scope with functions and values
- *
- * Note that you can also attach controllers to the DOM by declaring it in a route definition
- * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
- * again using `ng-controller` in the template itself. This will cause the controller to be attached
- * and executed twice.
- *
- * @element ANY
- * @scope
- * @priority 500
- * @param {expression} ngController Name of a constructor function registered with the current
- * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
- * that on the current scope evaluates to a constructor function.
- *
- * The controller instance can be published into a scope property by specifying
- * `ng-controller="as propertyName"`.
- *
- * If the current `$controllerProvider` is configured to use globals (via
- * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
- * also be the name of a globally accessible constructor function (not recommended).
- *
- * @example
- * Here is a simple form for editing user contact information. Adding, removing, clearing, and
- * greeting are methods declared on the controller (see source tab). These methods can
- * easily be called from the angular markup. Any changes to the data are automatically reflected
- * in the View without the need for a manual update.
- *
- * Two different declaration styles are included below:
- *
- * * one binds methods and properties directly onto the controller using `this`:
- * `ng-controller="SettingsController1 as settings"`
- * * one injects `$scope` into the controller:
- * `ng-controller="SettingsController2"`
- *
- * The second option is more common in the Angular community, and is generally used in boilerplates
- * and in this guide. However, there are advantages to binding properties directly to the controller
- * and avoiding scope.
- *
- * * Using `controller as` makes it obvious which controller you are accessing in the template when
- * multiple controllers apply to an element.
- * * If you are writing your controllers as classes you have easier access to the properties and
- * methods, which will appear on the scope, from inside the controller code.
- * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
- * inheritance masking primitives.
- *
- * This example demonstrates the `controller as` syntax.
- *
- * <example name="ngControllerAs" module="controllerAsExample">
- * <file name="index.html">
- * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
- * <label>Name: <input type="text" ng-model="settings.name"/></label>
- * <button ng-click="settings.greet()">greet</button><br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in settings.contacts">
- * <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
- * <button ng-click="settings.clearContact(contact)">clear</button>
- * <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button>
- * </li>
- * <li><button ng-click="settings.addContact()">add</button></li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerAsExample', [])
- * .controller('SettingsController1', SettingsController1);
- *
- * function SettingsController1() {
- * this.name = "John Smith";
- * this.contacts = [
- * {type: 'phone', value: '408 555 1212'},
- * {type: 'email', value: 'john.smith@example.org'} ];
- * }
- *
- * SettingsController1.prototype.greet = function() {
- * alert(this.name);
- * };
- *
- * SettingsController1.prototype.addContact = function() {
- * this.contacts.push({type: 'email', value: 'yourname@example.org'});
- * };
- *
- * SettingsController1.prototype.removeContact = function(contactToRemove) {
- * var index = this.contacts.indexOf(contactToRemove);
- * this.contacts.splice(index, 1);
- * };
- *
- * SettingsController1.prototype.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller as', function() {
- * var container = element(by.id('ctrl-as-exmpl'));
- * expect(container.element(by.model('settings.name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- *
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.buttonText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.buttonText('add')).click();
- *
- * expect(container.element(by.repeater('contact in settings.contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- * </example>
- *
- * This example demonstrates the "attach to `$scope`" style of controller.
- *
- * <example name="ngController" module="controllerExample">
- * <file name="index.html">
- * <div id="ctrl-exmpl" ng-controller="SettingsController2">
- * <label>Name: <input type="text" ng-model="name"/></label>
- * <button ng-click="greet()">greet</button><br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in contacts">
- * <select ng-model="contact.type" id="select_{{$index}}">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
- * <button ng-click="clearContact(contact)">clear</button>
- * <button ng-click="removeContact(contact)">X</button>
- * </li>
- * <li>[ <button ng-click="addContact()">add</button> ]</li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerExample', [])
- * .controller('SettingsController2', ['$scope', SettingsController2]);
- *
- * function SettingsController2($scope) {
- * $scope.name = "John Smith";
- * $scope.contacts = [
- * {type:'phone', value:'408 555 1212'},
- * {type:'email', value:'john.smith@example.org'} ];
- *
- * $scope.greet = function() {
- * alert($scope.name);
- * };
- *
- * $scope.addContact = function() {
- * $scope.contacts.push({type:'email', value:'yourname@example.org'});
- * };
- *
- * $scope.removeContact = function(contactToRemove) {
- * var index = $scope.contacts.indexOf(contactToRemove);
- * $scope.contacts.splice(index, 1);
- * };
- *
- * $scope.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * }
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller', function() {
- * var container = element(by.id('ctrl-exmpl'));
- *
- * expect(container.element(by.model('name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.buttonText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.buttonText('add')).click();
- *
- * expect(container.element(by.repeater('contact in contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- *</example>
-
- */
-var ngControllerDirective = [function() {
- return {
- restrict: 'A',
- scope: true,
- controller: '@',
- priority: 500
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngCsp
- *
- * @element html
- * @description
- *
- * Angular has some features that can break certain
- * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.
- *
- * If you intend to implement these rules then you must tell Angular not to use these features.
- *
- * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
- *
- *
- * The following rules affect Angular:
- *
- * * `unsafe-eval`: this rule forbids apps to use `eval` or `Function(string)` generated functions
- * (among other things). Angular makes use of this in the {@link $parse} service to provide a 30%
- * increase in the speed of evaluating Angular expressions.
- *
- * * `unsafe-inline`: this rule forbids apps from inject custom styles into the document. Angular
- * makes use of this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}).
- * To make these directives work when a CSP rule is blocking inline styles, you must link to the
- * `angular-csp.css` in your HTML manually.
- *
- * If you do not provide `ngCsp` then Angular tries to autodetect if CSP is blocking unsafe-eval
- * and automatically deactivates this feature in the {@link $parse} service. This autodetection,
- * however, triggers a CSP error to be logged in the console:
- *
- * ```
- * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
- * script in the following Content Security Policy directive: "default-src 'self'". Note that
- * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
- * ```
- *
- * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
- * directive on an element of the HTML document that appears before the `<script>` tag that loads
- * the `angular.js` file.
- *
- * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
- *
- * You can specify which of the CSP related Angular features should be deactivated by providing
- * a value for the `ng-csp` attribute. The options are as follows:
- *
- * * no-inline-style: this stops Angular from injecting CSS styles into the DOM
- *
- * * no-unsafe-eval: this stops Angular from optimizing $parse with unsafe eval of strings
- *
- * You can use these values in the following combinations:
- *
- *
- * * No declaration means that Angular will assume that you can do inline styles, but it will do
- * a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous versions
- * of Angular.
- *
- * * A simple `ng-csp` (or `data-ng-csp`) attribute will tell Angular to deactivate both inline
- * styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous versions
- * of Angular.
- *
- * * Specifying only `no-unsafe-eval` tells Angular that we must not use eval, but that we can inject
- * inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
- *
- * * Specifying only `no-inline-style` tells Angular that we must not inject styles, but that we can
- * run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
- *
- * * Specifying both `no-unsafe-eval` and `no-inline-style` tells Angular that we must not inject
- * styles nor use eval, which is the same as an empty: ng-csp.
- * E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">`
- *
- * @example
- * This example shows how to apply the `ngCsp` directive to the `html` tag.
- ```html
- <!doctype html>
- <html ng-app ng-csp>
- ...
- ...
- </html>
- ```
- * @example
- // Note: the suffix `.csp` in the example name triggers
- // csp mode in our http server!
- <example name="example.csp" module="cspExample" ng-csp="true">
- <file name="index.html">
- <div ng-controller="MainController as ctrl">
- <div>
- <button ng-click="ctrl.inc()" id="inc">Increment</button>
- <span id="counter">
- {{ctrl.counter}}
- </span>
- </div>
-
- <div>
- <button ng-click="ctrl.evil()" id="evil">Evil</button>
- <span id="evilError">
- {{ctrl.evilError}}
- </span>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('cspExample', [])
- .controller('MainController', function() {
- this.counter = 0;
- this.inc = function() {
- this.counter++;
- };
- this.evil = function() {
- // jshint evil:true
- try {
- eval('1+2');
- } catch (e) {
- this.evilError = e.message;
- }
- };
- });
- </file>
- <file name="protractor.js" type="protractor">
- var util, webdriver;
-
- var incBtn = element(by.id('inc'));
- var counter = element(by.id('counter'));
- var evilBtn = element(by.id('evil'));
- var evilError = element(by.id('evilError'));
-
- function getAndClearSevereErrors() {
- return browser.manage().logs().get('browser').then(function(browserLog) {
- return browserLog.filter(function(logEntry) {
- return logEntry.level.value > webdriver.logging.Level.WARNING.value;
- });
- });
- }
-
- function clearErrors() {
- getAndClearSevereErrors();
- }
-
- function expectNoErrors() {
- getAndClearSevereErrors().then(function(filteredLog) {
- expect(filteredLog.length).toEqual(0);
- if (filteredLog.length) {
- console.log('browser console errors: ' + util.inspect(filteredLog));
- }
- });
- }
-
- function expectError(regex) {
- getAndClearSevereErrors().then(function(filteredLog) {
- var found = false;
- filteredLog.forEach(function(log) {
- if (log.message.match(regex)) {
- found = true;
- }
- });
- if (!found) {
- throw new Error('expected an error that matches ' + regex);
- }
- });
- }
-
- beforeEach(function() {
- util = require('util');
- webdriver = require('protractor/node_modules/selenium-webdriver');
- });
-
- // For now, we only test on Chrome,
- // as Safari does not load the page with Protractor's injected scripts,
- // and Firefox webdriver always disables content security policy (#6358)
- if (browser.params.browser !== 'chrome') {
- return;
- }
-
- it('should not report errors when the page is loaded', function() {
- // clear errors so we are not dependent on previous tests
- clearErrors();
- // Need to reload the page as the page is already loaded when
- // we come here
- browser.driver.getCurrentUrl().then(function(url) {
- browser.get(url);
- });
- expectNoErrors();
- });
-
- it('should evaluate expressions', function() {
- expect(counter.getText()).toEqual('0');
- incBtn.click();
- expect(counter.getText()).toEqual('1');
- expectNoErrors();
- });
-
- it('should throw and report an error when using "eval"', function() {
- evilBtn.click();
- expect(evilError.getText()).toMatch(/Content Security Policy/);
- expectError(/Content Security Policy/);
- });
- </file>
- </example>
- */
-
-// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
-// bootstrap the system (before $parse is instantiated), for this reason we just have
-// the csp() fn that looks for the `ng-csp` attribute anywhere in the current doc
-
-/**
- * @ngdoc directive
- * @name ngClick
- *
- * @description
- * The ngClick directive allows you to specify custom behavior when
- * an element is clicked.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
- * click. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-click="count = count + 1" ng-init="count=0">
- Increment
- </button>
- <span>
- count: {{count}}
- </span>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-click', function() {
- expect(element(by.binding('count')).getText()).toMatch('0');
- element(by.css('button')).click();
- expect(element(by.binding('count')).getText()).toMatch('1');
- });
- </file>
- </example>
- */
-/*
- * A collection of directives that allows creation of custom event handlers that are defined as
- * angular expressions and are compiled and executed within the current scope.
- */
-var ngEventDirectives = {};
-
-// For events that might fire synchronously during DOM manipulation
-// we need to execute their event handlers asynchronously using $evalAsync,
-// so that they are not executed in an inconsistent state.
-var forceAsyncEvents = {
- 'blur': true,
- 'focus': true
-};
-forEach(
- 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
- function(eventName) {
- var directiveName = directiveNormalize('ng-' + eventName);
- ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
- return {
- restrict: 'A',
- compile: function($element, attr) {
- // We expose the powerful $event object on the scope that provides access to the Window,
- // etc. that isn't protected by the fast paths in $parse. We explicitly request better
- // checks at the cost of speed since event handler expressions are not executed as
- // frequently as regular change detection.
- var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
- return function ngEventHandler(scope, element) {
- element.on(eventName, function(event) {
- var callback = function() {
- fn(scope, {$event:event});
- };
- if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
- scope.$evalAsync(callback);
- } else {
- scope.$apply(callback);
- }
- });
- };
- }
- };
- }];
- }
-);
-
-/**
- * @ngdoc directive
- * @name ngDblclick
- *
- * @description
- * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
- * a dblclick. (The Event object is available as `$event`)
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-dblclick="count = count + 1" ng-init="count=0">
- Increment (on double click)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMousedown
- *
- * @description
- * The ngMousedown directive allows you to specify custom behavior on mousedown event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
- * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mousedown="count = count + 1" ng-init="count=0">
- Increment (on mouse down)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseup
- *
- * @description
- * Specify custom behavior on mouseup event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
- * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseup="count = count + 1" ng-init="count=0">
- Increment (on mouse up)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngMouseover
- *
- * @description
- * Specify custom behavior on mouseover event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
- * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseover="count = count + 1" ng-init="count=0">
- Increment (when mouse is over)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseenter
- *
- * @description
- * Specify custom behavior on mouseenter event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
- * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseenter="count = count + 1" ng-init="count=0">
- Increment (when mouse enters)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseleave
- *
- * @description
- * Specify custom behavior on mouseleave event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
- * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseleave="count = count + 1" ng-init="count=0">
- Increment (when mouse leaves)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMousemove
- *
- * @description
- * Specify custom behavior on mousemove event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
- * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mousemove="count = count + 1" ng-init="count=0">
- Increment (when mouse moves)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeydown
- *
- * @description
- * Specify custom behavior on keydown event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
- * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-keydown="count = count + 1" ng-init="count=0">
- key down count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeyup
- *
- * @description
- * Specify custom behavior on keyup event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
- * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <p>Typing in the input box below updates the key count</p>
- <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
-
- <p>Typing in the input box below updates the keycode</p>
- <input ng-keyup="event=$event">
- <p>event keyCode: {{ event.keyCode }}</p>
- <p>event altKey: {{ event.altKey }}</p>
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeypress
- *
- * @description
- * Specify custom behavior on keypress event.
- *
- * @element ANY
- * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
- * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
- * and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-keypress="count = count + 1" ng-init="count=0">
- key press count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngSubmit
- *
- * @description
- * Enables binding angular expressions to onsubmit events.
- *
- * Additionally it prevents the default action (which for form means sending the request to the
- * server and reloading the current page), but only if the form does not contain `action`,
- * `data-action`, or `x-action` attributes.
- *
- * <div class="alert alert-warning">
- * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
- * `ngSubmit` handlers together. See the
- * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
- * for a detailed discussion of when `ngSubmit` may be triggered.
- * </div>
- *
- * @element form
- * @priority 0
- * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
- * ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example module="submitExample">
- <file name="index.html">
- <script>
- angular.module('submitExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.list = [];
- $scope.text = 'hello';
- $scope.submit = function() {
- if ($scope.text) {
- $scope.list.push(this.text);
- $scope.text = '';
- }
- };
- }]);
- </script>
- <form ng-submit="submit()" ng-controller="ExampleController">
- Enter text and hit enter:
- <input type="text" ng-model="text" name="text" />
- <input type="submit" id="submit" value="Submit" />
- <pre>list={{list}}</pre>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-submit', function() {
- expect(element(by.binding('list')).getText()).toBe('list=[]');
- element(by.css('#submit')).click();
- expect(element(by.binding('list')).getText()).toContain('hello');
- expect(element(by.model('text')).getAttribute('value')).toBe('');
- });
- it('should ignore empty strings', function() {
- expect(element(by.binding('list')).getText()).toBe('list=[]');
- element(by.css('#submit')).click();
- element(by.css('#submit')).click();
- expect(element(by.binding('list')).getText()).toContain('hello');
- });
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngFocus
- *
- * @description
- * Specify custom behavior on focus event.
- *
- * Note: As the `focus` event is executed synchronously when calling `input.focus()`
- * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
- * during an `$apply` to ensure a consistent state.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
- * focus. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ngBlur
- *
- * @description
- * Specify custom behavior on blur event.
- *
- * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
- * an element has lost focus.
- *
- * Note: As the `blur` event is executed synchronously also during DOM manipulations
- * (e.g. removing a focussed input),
- * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
- * during an `$apply` to ensure a consistent state.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
- * blur. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ngCopy
- *
- * @description
- * Specify custom behavior on copy event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
- * copy. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
- copied: {{copied}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngCut
- *
- * @description
- * Specify custom behavior on cut event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
- * cut. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
- cut: {{cut}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngPaste
- *
- * @description
- * Specify custom behavior on paste event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
- * paste. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
- pasted: {{paste}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngIf
- * @restrict A
- * @multiElement
- *
- * @description
- * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
- * {expression}. If the expression assigned to `ngIf` evaluates to a false
- * value then the element is removed from the DOM, otherwise a clone of the
- * element is reinserted into the DOM.
- *
- * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
- * element in the DOM rather than changing its visibility via the `display` css property. A common
- * case when this difference is significant is when using css selectors that rely on an element's
- * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
- *
- * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
- * is created when the element is restored. The scope created within `ngIf` inherits from
- * its parent scope using
- * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
- * An important implication of this is if `ngModel` is used within `ngIf` to bind to
- * a javascript primitive defined in the parent scope. In this case any modifications made to the
- * variable within the child scope will override (hide) the value in the parent scope.
- *
- * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
- * is if an element's class attribute is directly modified after it's compiled, using something like
- * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
- * the added class will be lost because the original compiled state is used to regenerate the element.
- *
- * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
- * and `leave` effects.
- *
- * @animations
- * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
- * leave - happens just before the `ngIf` contents are removed from the DOM
- *
- * @element ANY
- * @scope
- * @priority 600
- * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
- * the element is removed from the DOM tree. If it is truthy a copy of the compiled
- * element is added to the DOM tree.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/>
- Show when checked:
- <span ng-if="checked" class="animate-if">
- This is removed when the checkbox is unchecked.
- </span>
- </file>
- <file name="animations.css">
- .animate-if {
- background:white;
- border:1px solid black;
- padding:10px;
- }
-
- .animate-if.ng-enter, .animate-if.ng-leave {
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- }
-
- .animate-if.ng-enter,
- .animate-if.ng-leave.ng-leave-active {
- opacity:0;
- }
-
- .animate-if.ng-leave,
- .animate-if.ng-enter.ng-enter-active {
- opacity:1;
- }
- </file>
- </example>
- */
-var ngIfDirective = ['$animate', function($animate) {
- return {
- multiElement: true,
- transclude: 'element',
- priority: 600,
- terminal: true,
- restrict: 'A',
- $$tlb: true,
- link: function($scope, $element, $attr, ctrl, $transclude) {
- var block, childScope, previousElements;
- $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
-
- if (value) {
- if (!childScope) {
- $transclude(function(clone, newScope) {
- childScope = newScope;
- clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
- // Note: We only need the first/last node of the cloned nodes.
- // However, we need to keep the reference to the jqlite wrapper as it might be changed later
- // by a directive with templateUrl when its template arrives.
- block = {
- clone: clone
- };
- $animate.enter(clone, $element.parent(), $element);
- });
- }
- } else {
- if (previousElements) {
- previousElements.remove();
- previousElements = null;
- }
- if (childScope) {
- childScope.$destroy();
- childScope = null;
- }
- if (block) {
- previousElements = getBlockNodes(block.clone);
- $animate.leave(previousElements).then(function() {
- previousElements = null;
- });
- block = null;
- }
- }
- });
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngInclude
- * @restrict ECA
- *
- * @description
- * Fetches, compiles and includes an external HTML fragment.
- *
- * By default, the template URL is restricted to the same domain and protocol as the
- * application document. This is done by calling {@link $sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
- * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
- * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
- * ng.$sce Strict Contextual Escaping}.
- *
- * In addition, the browser's
- * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
- * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
- * policy may further restrict whether the template is successfully loaded.
- * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
- * access on some browsers.
- *
- * @animations
- * enter - animation is used to bring new content into the browser.
- * leave - animation is used to animate existing content away.
- *
- * The enter and leave animation occur concurrently.
- *
- * @scope
- * @priority 400
- *
- * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
- * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
- * @param {string=} onload Expression to evaluate when a new partial is loaded.
- * <div class="alert alert-warning">
- * **Note:** When using onload on SVG elements in IE11, the browser will try to call
- * a function with the name on the window element, which will usually throw a
- * "function is undefined" error. To fix this, you can instead use `data-onload` or a
- * different form that {@link guide/directive#normalization matches} `onload`.
- * </div>
- *
- * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
- * $anchorScroll} to scroll the viewport after the content is loaded.
- *
- * - If the attribute is not set, disable scrolling.
- * - If the attribute is set without value, enable scrolling.
- * - Otherwise enable scrolling only if the expression evaluates to truthy value.
- *
- * @example
- <example module="includeExample" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <select ng-model="template" ng-options="t.name for t in templates">
- <option value="">(blank)</option>
- </select>
- url of the template: <code>{{template.url}}</code>
- <hr/>
- <div class="slide-animate-container">
- <div class="slide-animate" ng-include="template.url"></div>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('includeExample', ['ngAnimate'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.templates =
- [ { name: 'template1.html', url: 'template1.html'},
- { name: 'template2.html', url: 'template2.html'} ];
- $scope.template = $scope.templates[0];
- }]);
- </file>
- <file name="template1.html">
- Content of template1.html
- </file>
- <file name="template2.html">
- Content of template2.html
- </file>
- <file name="animations.css">
- .slide-animate-container {
- position:relative;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .slide-animate {
- padding:10px;
- }
-
- .slide-animate.ng-enter, .slide-animate.ng-leave {
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- display:block;
- padding:10px;
- }
-
- .slide-animate.ng-enter {
- top:-50px;
- }
- .slide-animate.ng-enter.ng-enter-active {
- top:0;
- }
-
- .slide-animate.ng-leave {
- top:0;
- }
- .slide-animate.ng-leave.ng-leave-active {
- top:50px;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var templateSelect = element(by.model('template'));
- var includeElem = element(by.css('[ng-include]'));
-
- it('should load template1.html', function() {
- expect(includeElem.getText()).toMatch(/Content of template1.html/);
- });
-
- it('should load template2.html', function() {
- if (browser.params.browser == 'firefox') {
- // Firefox can't handle using selects
- // See https://github.com/angular/protractor/issues/480
- return;
- }
- templateSelect.click();
- templateSelect.all(by.css('option')).get(2).click();
- expect(includeElem.getText()).toMatch(/Content of template2.html/);
- });
-
- it('should change to blank', function() {
- if (browser.params.browser == 'firefox') {
- // Firefox can't handle using selects
- return;
- }
- templateSelect.click();
- templateSelect.all(by.css('option')).get(0).click();
- expect(includeElem.isPresent()).toBe(false);
- });
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc event
- * @name ngInclude#$includeContentRequested
- * @eventType emit on the scope ngInclude was declared in
- * @description
- * Emitted every time the ngInclude content is requested.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {String} src URL of content to load.
- */
-
-
-/**
- * @ngdoc event
- * @name ngInclude#$includeContentLoaded
- * @eventType emit on the current ngInclude scope
- * @description
- * Emitted every time the ngInclude content is reloaded.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {String} src URL of content to load.
- */
-
-
-/**
- * @ngdoc event
- * @name ngInclude#$includeContentError
- * @eventType emit on the scope ngInclude was declared in
- * @description
- * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {String} src URL of content to load.
- */
-var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
- function($templateRequest, $anchorScroll, $animate) {
- return {
- restrict: 'ECA',
- priority: 400,
- terminal: true,
- transclude: 'element',
- controller: angular.noop,
- compile: function(element, attr) {
- var srcExp = attr.ngInclude || attr.src,
- onloadExp = attr.onload || '',
- autoScrollExp = attr.autoscroll;
-
- return function(scope, $element, $attr, ctrl, $transclude) {
- var changeCounter = 0,
- currentScope,
- previousElement,
- currentElement;
-
- var cleanupLastIncludeContent = function() {
- if (previousElement) {
- previousElement.remove();
- previousElement = null;
- }
- if (currentScope) {
- currentScope.$destroy();
- currentScope = null;
- }
- if (currentElement) {
- $animate.leave(currentElement).then(function() {
- previousElement = null;
- });
- previousElement = currentElement;
- currentElement = null;
- }
- };
-
- scope.$watch(srcExp, function ngIncludeWatchAction(src) {
- var afterAnimation = function() {
- if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
- $anchorScroll();
- }
- };
- var thisChangeId = ++changeCounter;
-
- if (src) {
- //set the 2nd param to true to ignore the template request error so that the inner
- //contents and scope can be cleaned up.
- $templateRequest(src, true).then(function(response) {
- if (scope.$$destroyed) return;
-
- if (thisChangeId !== changeCounter) return;
- var newScope = scope.$new();
- ctrl.template = response;
-
- // Note: This will also link all children of ng-include that were contained in the original
- // html. If that content contains controllers, ... they could pollute/change the scope.
- // However, using ng-include on an element with additional content does not make sense...
- // Note: We can't remove them in the cloneAttchFn of $transclude as that
- // function is called before linking the content, which would apply child
- // directives to non existing elements.
- var clone = $transclude(newScope, function(clone) {
- cleanupLastIncludeContent();
- $animate.enter(clone, null, $element).then(afterAnimation);
- });
-
- currentScope = newScope;
- currentElement = clone;
-
- currentScope.$emit('$includeContentLoaded', src);
- scope.$eval(onloadExp);
- }, function() {
- if (scope.$$destroyed) return;
-
- if (thisChangeId === changeCounter) {
- cleanupLastIncludeContent();
- scope.$emit('$includeContentError', src);
- }
- });
- scope.$emit('$includeContentRequested', src);
- } else {
- cleanupLastIncludeContent();
- ctrl.template = null;
- }
- });
- };
- }
- };
-}];
-
-// This directive is called during the $transclude call of the first `ngInclude` directive.
-// It will replace and compile the content of the element with the loaded template.
-// We need this directive so that the element content is already filled when
-// the link function of another directive on the same element as ngInclude
-// is called.
-var ngIncludeFillContentDirective = ['$compile',
- function($compile) {
- return {
- restrict: 'ECA',
- priority: -400,
- require: 'ngInclude',
- link: function(scope, $element, $attr, ctrl) {
- if (toString.call($element[0]).match(/SVG/)) {
- // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
- // support innerHTML, so detect this here and try to generate the contents
- // specially.
- $element.empty();
- $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
- function namespaceAdaptedClone(clone) {
- $element.append(clone);
- }, {futureParentElement: $element});
- return;
- }
-
- $element.html(ctrl.template);
- $compile($element.contents())(scope);
- }
- };
- }];
-
-/**
- * @ngdoc directive
- * @name ngInit
- * @restrict AC
- *
- * @description
- * The `ngInit` directive allows you to evaluate an expression in the
- * current scope.
- *
- * <div class="alert alert-danger">
- * This directive can be abused to add unnecessary amounts of logic into your templates.
- * There are only a few appropriate uses of `ngInit`, such as for aliasing special properties of
- * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below; and for injecting data via
- * server side scripting. Besides these few cases, you should use {@link guide/controller controllers}
- * rather than `ngInit` to initialize values on a scope.
- * </div>
- *
- * <div class="alert alert-warning">
- * **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make
- * sure you have parentheses to ensure correct operator precedence:
- * <pre class="prettyprint">
- * `<div ng-init="test1 = ($index | toString)"></div>`
- * </pre>
- * </div>
- *
- * @priority 450
- *
- * @element ANY
- * @param {expression} ngInit {@link guide/expression Expression} to eval.
- *
- * @example
- <example module="initExample">
- <file name="index.html">
- <script>
- angular.module('initExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.list = [['a', 'b'], ['c', 'd']];
- }]);
- </script>
- <div ng-controller="ExampleController">
- <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
- <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
- <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
- </div>
- </div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should alias index positions', function() {
- var elements = element.all(by.css('.example-init'));
- expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
- expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
- expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
- expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
- });
- </file>
- </example>
- */
-var ngInitDirective = ngDirective({
- priority: 450,
- compile: function() {
- return {
- pre: function(scope, element, attrs) {
- scope.$eval(attrs.ngInit);
- }
- };
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngList
- *
- * @description
- * Text input that converts between a delimited string and an array of strings. The default
- * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
- * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
- *
- * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
- * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
- * list item is respected. This implies that the user of the directive is responsible for
- * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
- * tab or newline character.
- * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
- * when joining the list items back together) and whitespace around each list item is stripped
- * before it is added to the model.
- *
- * ### Example with Validation
- *
- * <example name="ngList-directive" module="listExample">
- * <file name="app.js">
- * angular.module('listExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.names = ['morpheus', 'neo', 'trinity'];
- * }]);
- * </file>
- * <file name="index.html">
- * <form name="myForm" ng-controller="ExampleController">
- * <label>List: <input name="namesInput" ng-model="names" ng-list required></label>
- * <span role="alert">
- * <span class="error" ng-show="myForm.namesInput.$error.required">
- * Required!</span>
- * </span>
- * <br>
- * <tt>names = {{names}}</tt><br/>
- * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
- * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
- * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- * </form>
- * </file>
- * <file name="protractor.js" type="protractor">
- * var listInput = element(by.model('names'));
- * var names = element(by.exactBinding('names'));
- * var valid = element(by.binding('myForm.namesInput.$valid'));
- * var error = element(by.css('span.error'));
- *
- * it('should initialize to model', function() {
- * expect(names.getText()).toContain('["morpheus","neo","trinity"]');
- * expect(valid.getText()).toContain('true');
- * expect(error.getCssValue('display')).toBe('none');
- * });
- *
- * it('should be invalid if empty', function() {
- * listInput.clear();
- * listInput.sendKeys('');
- *
- * expect(names.getText()).toContain('');
- * expect(valid.getText()).toContain('false');
- * expect(error.getCssValue('display')).not.toBe('none');
- * });
- * </file>
- * </example>
- *
- * ### Example - splitting on newline
- * <example name="ngList-directive-newlines">
- * <file name="index.html">
- * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
- * <pre>{{ list | json }}</pre>
- * </file>
- * <file name="protractor.js" type="protractor">
- * it("should split the text by newlines", function() {
- * var listInput = element(by.model('list'));
- * var output = element(by.binding('list | json'));
- * listInput.sendKeys('abc\ndef\nghi');
- * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]');
- * });
- * </file>
- * </example>
- *
- * @element input
- * @param {string=} ngList optional delimiter that should be used to split the value.
- */
-var ngListDirective = function() {
- return {
- restrict: 'A',
- priority: 100,
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- // We want to control whitespace trimming so we use this convoluted approach
- // to access the ngList attribute, which doesn't pre-trim the attribute
- var ngList = element.attr(attr.$attr.ngList) || ', ';
- var trimValues = attr.ngTrim !== 'false';
- var separator = trimValues ? trim(ngList) : ngList;
-
- var parse = function(viewValue) {
- // If the viewValue is invalid (say required but empty) it will be `undefined`
- if (isUndefined(viewValue)) return;
-
- var list = [];
-
- if (viewValue) {
- forEach(viewValue.split(separator), function(value) {
- if (value) list.push(trimValues ? trim(value) : value);
- });
- }
-
- return list;
- };
-
- ctrl.$parsers.push(parse);
- ctrl.$formatters.push(function(value) {
- if (isArray(value)) {
- return value.join(ngList);
- }
-
- return undefined;
- });
-
- // Override the standard $isEmpty because an empty array means the input is empty.
- ctrl.$isEmpty = function(value) {
- return !value || !value.length;
- };
- }
- };
-};
-
-/* global VALID_CLASS: true,
- INVALID_CLASS: true,
- PRISTINE_CLASS: true,
- DIRTY_CLASS: true,
- UNTOUCHED_CLASS: true,
- TOUCHED_CLASS: true,
-*/
-
-var VALID_CLASS = 'ng-valid',
- INVALID_CLASS = 'ng-invalid',
- PRISTINE_CLASS = 'ng-pristine',
- DIRTY_CLASS = 'ng-dirty',
- UNTOUCHED_CLASS = 'ng-untouched',
- TOUCHED_CLASS = 'ng-touched',
- PENDING_CLASS = 'ng-pending',
- EMPTY_CLASS = 'ng-empty',
- NOT_EMPTY_CLASS = 'ng-not-empty';
-
-var ngModelMinErr = minErr('ngModel');
-
-/**
- * @ngdoc type
- * @name ngModel.NgModelController
- *
- * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a
- * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue
- * is set.
- * @property {*} $modelValue The value in the model that the control is bound to.
- * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
- the control reads value from the DOM. The functions are called in array order, each passing
- its return value through to the next. The last return value is forwarded to the
- {@link ngModel.NgModelController#$validators `$validators`} collection.
-
-Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
-`$viewValue`}.
-
-Returning `undefined` from a parser means a parse error occurred. In that case,
-no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
-will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
-is set to `true`. The parse error is stored in `ngModel.$error.parse`.
-
- *
- * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
- the model value changes. The functions are called in reverse array order, each passing the value through to the
- next. The last return value is used as the actual DOM value.
- Used to format / convert values for display in the control.
- * ```js
- * function formatter(value) {
- * if (value) {
- * return value.toUpperCase();
- * }
- * }
- * ngModel.$formatters.push(formatter);
- * ```
- *
- * @property {Object.<string, function>} $validators A collection of validators that are applied
- * whenever the model value changes. The key value within the object refers to the name of the
- * validator while the function refers to the validation operation. The validation operation is
- * provided with the model value as an argument and must return a true or false value depending
- * on the response of that validation.
- *
- * ```js
- * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
- * var value = modelValue || viewValue;
- * return /[0-9]+/.test(value) &&
- * /[a-z]+/.test(value) &&
- * /[A-Z]+/.test(value) &&
- * /\W+/.test(value);
- * };
- * ```
- *
- * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
- * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
- * is expected to return a promise when it is run during the model validation process. Once the promise
- * is delivered then the validation status will be set to true when fulfilled and false when rejected.
- * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
- * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
- * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
- * will only run once all synchronous validators have passed.
- *
- * Please note that if $http is used then it is important that the server returns a success HTTP response code
- * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
- *
- * ```js
- * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
- * var value = modelValue || viewValue;
- *
- * // Lookup user by username
- * return $http.get('/api/users/' + value).
- * then(function resolved() {
- * //username exists, this means validation fails
- * return $q.reject('exists');
- * }, function rejected() {
- * //username does not exist, therefore this validation passes
- * return true;
- * });
- * };
- * ```
- *
- * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
- * view value has changed. It is called with no arguments, and its return value is ignored.
- * This can be used in place of additional $watches against the model value.
- *
- * @property {Object} $error An object hash with all failing validator ids as keys.
- * @property {Object} $pending An object hash with all pending validator ids as keys.
- *
- * @property {boolean} $untouched True if control has not lost focus yet.
- * @property {boolean} $touched True if control has lost focus.
- * @property {boolean} $pristine True if user has not interacted with the control yet.
- * @property {boolean} $dirty True if user has already interacted with the control.
- * @property {boolean} $valid True if there is no error.
- * @property {boolean} $invalid True if at least one error on the control.
- * @property {string} $name The name attribute of the control.
- *
- * @description
- *
- * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
- * The controller contains services for data-binding, validation, CSS updates, and value formatting
- * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
- * listening to DOM events.
- * Such DOM related logic should be provided by other directives which make use of
- * `NgModelController` for data-binding to control elements.
- * Angular provides this DOM logic for most {@link input `input`} elements.
- * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
- * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
- *
- * @example
- * ### Custom Control Example
- * This example shows how to use `NgModelController` with a custom control to achieve
- * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
- * collaborate together to achieve the desired result.
- *
- * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
- * contents be edited in place by the user.
- *
- * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
- * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
- * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
- * that content using the `$sce` service.
- *
- * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
- <file name="style.css">
- [contenteditable] {
- border: 1px solid black;
- background-color: white;
- min-height: 20px;
- }
-
- .ng-invalid {
- border: 1px solid red;
- }
-
- </file>
- <file name="script.js">
- angular.module('customControl', ['ngSanitize']).
- directive('contenteditable', ['$sce', function($sce) {
- return {
- restrict: 'A', // only activate on element attribute
- require: '?ngModel', // get a hold of NgModelController
- link: function(scope, element, attrs, ngModel) {
- if (!ngModel) return; // do nothing if no ng-model
-
- // Specify how UI should be updated
- ngModel.$render = function() {
- element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
- };
-
- // Listen for change events to enable binding
- element.on('blur keyup change', function() {
- scope.$evalAsync(read);
- });
- read(); // initialize
-
- // Write data to the model
- function read() {
- var html = element.html();
- // When we clear the content editable the browser leaves a <br> behind
- // If strip-br attribute is provided then we strip this out
- if ( attrs.stripBr && html == '<br>' ) {
- html = '';
- }
- ngModel.$setViewValue(html);
- }
- }
- };
- }]);
- </file>
- <file name="index.html">
- <form name="myForm">
- <div contenteditable
- name="myWidget" ng-model="userContent"
- strip-br="true"
- required>Change me!</div>
- <span ng-show="myForm.myWidget.$error.required">Required!</span>
- <hr>
- <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should data-bind and become invalid', function() {
- if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
- // SafariDriver can't handle contenteditable
- // and Firefox driver can't clear contenteditables very well
- return;
- }
- var contentEditable = element(by.css('[contenteditable]'));
- var content = 'Change me!';
-
- expect(contentEditable.getText()).toEqual(content);
-
- contentEditable.clear();
- contentEditable.sendKeys(protractor.Key.BACK_SPACE);
- expect(contentEditable.getText()).toEqual('');
- expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
- });
- </file>
- * </example>
- *
- *
- */
-var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
- function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
- this.$viewValue = Number.NaN;
- this.$modelValue = Number.NaN;
- this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
- this.$validators = {};
- this.$asyncValidators = {};
- this.$parsers = [];
- this.$formatters = [];
- this.$viewChangeListeners = [];
- this.$untouched = true;
- this.$touched = false;
- this.$pristine = true;
- this.$dirty = false;
- this.$valid = true;
- this.$invalid = false;
- this.$error = {}; // keep invalid keys here
- this.$$success = {}; // keep valid keys here
- this.$pending = undefined; // keep pending keys here
- this.$name = $interpolate($attr.name || '', false)($scope);
- this.$$parentForm = nullFormCtrl;
-
- var parsedNgModel = $parse($attr.ngModel),
- parsedNgModelAssign = parsedNgModel.assign,
- ngModelGet = parsedNgModel,
- ngModelSet = parsedNgModelAssign,
- pendingDebounce = null,
- parserValid,
- ctrl = this;
-
- this.$$setOptions = function(options) {
- ctrl.$options = options;
- if (options && options.getterSetter) {
- var invokeModelGetter = $parse($attr.ngModel + '()'),
- invokeModelSetter = $parse($attr.ngModel + '($$$p)');
-
- ngModelGet = function($scope) {
- var modelValue = parsedNgModel($scope);
- if (isFunction(modelValue)) {
- modelValue = invokeModelGetter($scope);
- }
- return modelValue;
- };
- ngModelSet = function($scope, newValue) {
- if (isFunction(parsedNgModel($scope))) {
- invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
- } else {
- parsedNgModelAssign($scope, ctrl.$modelValue);
- }
- };
- } else if (!parsedNgModel.assign) {
- throw ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
- $attr.ngModel, startingTag($element));
- }
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$render
- *
- * @description
- * Called when the view needs to be updated. It is expected that the user of the ng-model
- * directive will implement this method.
- *
- * The `$render()` method is invoked in the following situations:
- *
- * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
- * committed value then `$render()` is called to update the input control.
- * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
- * the `$viewValue` are different from last time.
- *
- * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
- * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue`
- * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
- * invoked if you only change a property on the objects.
- */
- this.$render = noop;
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$isEmpty
- *
- * @description
- * This is called when we need to determine if the value of an input is empty.
- *
- * For instance, the required directive does this to work out if the input has data or not.
- *
- * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
- *
- * You can override this for input directives whose concept of being empty is different from the
- * default. The `checkboxInputType` directive does this because in its case a value of `false`
- * implies empty.
- *
- * @param {*} value The value of the input to check for emptiness.
- * @returns {boolean} True if `value` is "empty".
- */
- this.$isEmpty = function(value) {
- return isUndefined(value) || value === '' || value === null || value !== value;
- };
-
- this.$$updateEmptyClasses = function(value) {
- if (ctrl.$isEmpty(value)) {
- $animate.removeClass($element, NOT_EMPTY_CLASS);
- $animate.addClass($element, EMPTY_CLASS);
- } else {
- $animate.removeClass($element, EMPTY_CLASS);
- $animate.addClass($element, NOT_EMPTY_CLASS);
- }
- };
-
-
- var currentValidationRunId = 0;
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setValidity
- *
- * @description
- * Change the validity state, and notify the form.
- *
- * This method can be called within $parsers/$formatters or a custom validation implementation.
- * However, in most cases it should be sufficient to use the `ngModel.$validators` and
- * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
- *
- * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
- * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
- * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
- * The `validationErrorKey` should be in camelCase and will get converted into dash-case
- * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
- * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
- * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
- * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
- * Skipped is used by Angular when validators do not run because of parse errors and
- * when `$asyncValidators` do not run because any of the `$validators` failed.
- */
- addSetValidityMethod({
- ctrl: this,
- $element: $element,
- set: function(object, property) {
- object[property] = true;
- },
- unset: function(object, property) {
- delete object[property];
- },
- $animate: $animate
- });
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setPristine
- *
- * @description
- * Sets the control to its pristine state.
- *
- * This method can be called to remove the `ng-dirty` class and set the control to its pristine
- * state (`ng-pristine` class). A model is considered to be pristine when the control
- * has not been changed from when first compiled.
- */
- this.$setPristine = function() {
- ctrl.$dirty = false;
- ctrl.$pristine = true;
- $animate.removeClass($element, DIRTY_CLASS);
- $animate.addClass($element, PRISTINE_CLASS);
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setDirty
- *
- * @description
- * Sets the control to its dirty state.
- *
- * This method can be called to remove the `ng-pristine` class and set the control to its dirty
- * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
- * from when first compiled.
- */
- this.$setDirty = function() {
- ctrl.$dirty = true;
- ctrl.$pristine = false;
- $animate.removeClass($element, PRISTINE_CLASS);
- $animate.addClass($element, DIRTY_CLASS);
- ctrl.$$parentForm.$setDirty();
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setUntouched
- *
- * @description
- * Sets the control to its untouched state.
- *
- * This method can be called to remove the `ng-touched` class and set the control to its
- * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
- * by default, however this function can be used to restore that state if the model has
- * already been touched by the user.
- */
- this.$setUntouched = function() {
- ctrl.$touched = false;
- ctrl.$untouched = true;
- $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setTouched
- *
- * @description
- * Sets the control to its touched state.
- *
- * This method can be called to remove the `ng-untouched` class and set the control to its
- * touched state (`ng-touched` class). A model is considered to be touched when the user has
- * first focused the control element and then shifted focus away from the control (blur event).
- */
- this.$setTouched = function() {
- ctrl.$touched = true;
- ctrl.$untouched = false;
- $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$rollbackViewValue
- *
- * @description
- * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
- * which may be caused by a pending debounced event or because the input is waiting for a some
- * future event.
- *
- * If you have an input that uses `ng-model-options` to set up debounced updates or updates that
- * depend on special events such as blur, you can have a situation where there is a period when
- * the `$viewValue` is out of sync with the ngModel's `$modelValue`.
- *
- * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update
- * and reset the input to the last committed view value.
- *
- * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue`
- * programmatically before these debounced/future events have resolved/occurred, because Angular's
- * dirty checking mechanism is not able to tell whether the model has actually changed or not.
- *
- * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
- * input which may have such events pending. This is important in order to make sure that the
- * input field will be updated with the new model value and any pending operations are cancelled.
- *
- * <example name="ng-model-cancel-update" module="cancel-update-example">
- * <file name="app.js">
- * angular.module('cancel-update-example', [])
- *
- * .controller('CancelUpdateController', ['$scope', function($scope) {
- * $scope.model = {};
- *
- * $scope.setEmpty = function(e, value, rollback) {
- * if (e.keyCode == 27) {
- * e.preventDefault();
- * if (rollback) {
- * $scope.myForm[value].$rollbackViewValue();
- * }
- * $scope.model[value] = '';
- * }
- * };
- * }]);
- * </file>
- * <file name="index.html">
- * <div ng-controller="CancelUpdateController">
- * <p>Both of these inputs are only updated if they are blurred. Hitting escape should
- * empty them. Follow these steps and observe the difference:</p>
- * <ol>
- * <li>Type something in the input. You will see that the model is not yet updated</li>
- * <li>Press the Escape key.
- * <ol>
- * <li> In the first example, nothing happens, because the model is already '', and no
- * update is detected. If you blur the input, the model will be set to the current view.
- * </li>
- * <li> In the second example, the pending update is cancelled, and the input is set back
- * to the last committed view value (''). Blurring the input does nothing.
- * </li>
- * </ol>
- * </li>
- * </ol>
- *
- * <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
- * <div>
- * <p id="inputDescription1">Without $rollbackViewValue():</p>
- * <input name="value1" aria-describedby="inputDescription1" ng-model="model.value1"
- * ng-keydown="setEmpty($event, 'value1')">
- * value1: "{{ model.value1 }}"
- * </div>
- *
- * <div>
- * <p id="inputDescription2">With $rollbackViewValue():</p>
- * <input name="value2" aria-describedby="inputDescription2" ng-model="model.value2"
- * ng-keydown="setEmpty($event, 'value2', true)">
- * value2: "{{ model.value2 }}"
- * </div>
- * </form>
- * </div>
- * </file>
- <file name="style.css">
- div {
- display: table-cell;
- }
- div:nth-child(1) {
- padding-right: 30px;
- }
-
- </file>
- * </example>
- */
- this.$rollbackViewValue = function() {
- $timeout.cancel(pendingDebounce);
- ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
- ctrl.$render();
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$validate
- *
- * @description
- * Runs each of the registered validators (first synchronous validators and then
- * asynchronous validators).
- * If the validity changes to invalid, the model will be set to `undefined`,
- * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
- * If the validity changes to valid, it will set the model to the last available valid
- * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
- */
- this.$validate = function() {
- // ignore $validate before model is initialized
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
- return;
- }
-
- var viewValue = ctrl.$$lastCommittedViewValue;
- // Note: we use the $$rawModelValue as $modelValue might have been
- // set to undefined during a view -> model update that found validation
- // errors. We can't parse the view here, since that could change
- // the model although neither viewValue nor the model on the scope changed
- var modelValue = ctrl.$$rawModelValue;
-
- var prevValid = ctrl.$valid;
- var prevModelValue = ctrl.$modelValue;
-
- var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
-
- ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
- // If there was no change in validity, don't update the model
- // This prevents changing an invalid modelValue to undefined
- if (!allowInvalid && prevValid !== allValid) {
- // Note: Don't check ctrl.$valid here, as we could have
- // external validators (e.g. calculated on the server),
- // that just call $setValidity and need the model value
- // to calculate their validity.
- ctrl.$modelValue = allValid ? modelValue : undefined;
-
- if (ctrl.$modelValue !== prevModelValue) {
- ctrl.$$writeModelToScope();
- }
- }
- });
-
- };
-
- this.$$runValidators = function(modelValue, viewValue, doneCallback) {
- currentValidationRunId++;
- var localValidationRunId = currentValidationRunId;
-
- // check parser error
- if (!processParseErrors()) {
- validationDone(false);
- return;
- }
- if (!processSyncValidators()) {
- validationDone(false);
- return;
- }
- processAsyncValidators();
-
- function processParseErrors() {
- var errorKey = ctrl.$$parserName || 'parse';
- if (isUndefined(parserValid)) {
- setValidity(errorKey, null);
- } else {
- if (!parserValid) {
- forEach(ctrl.$validators, function(v, name) {
- setValidity(name, null);
- });
- forEach(ctrl.$asyncValidators, function(v, name) {
- setValidity(name, null);
- });
- }
- // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
- setValidity(errorKey, parserValid);
- return parserValid;
- }
- return true;
- }
-
- function processSyncValidators() {
- var syncValidatorsValid = true;
- forEach(ctrl.$validators, function(validator, name) {
- var result = validator(modelValue, viewValue);
- syncValidatorsValid = syncValidatorsValid && result;
- setValidity(name, result);
- });
- if (!syncValidatorsValid) {
- forEach(ctrl.$asyncValidators, function(v, name) {
- setValidity(name, null);
- });
- return false;
- }
- return true;
- }
-
- function processAsyncValidators() {
- var validatorPromises = [];
- var allValid = true;
- forEach(ctrl.$asyncValidators, function(validator, name) {
- var promise = validator(modelValue, viewValue);
- if (!isPromiseLike(promise)) {
- throw ngModelMinErr('nopromise',
- "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
- }
- setValidity(name, undefined);
- validatorPromises.push(promise.then(function() {
- setValidity(name, true);
- }, function(error) {
- allValid = false;
- setValidity(name, false);
- }));
- });
- if (!validatorPromises.length) {
- validationDone(true);
- } else {
- $q.all(validatorPromises).then(function() {
- validationDone(allValid);
- }, noop);
- }
- }
-
- function setValidity(name, isValid) {
- if (localValidationRunId === currentValidationRunId) {
- ctrl.$setValidity(name, isValid);
- }
- }
-
- function validationDone(allValid) {
- if (localValidationRunId === currentValidationRunId) {
-
- doneCallback(allValid);
- }
- }
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$commitViewValue
- *
- * @description
- * Commit a pending update to the `$modelValue`.
- *
- * Updates may be pending by a debounced event or because the input is waiting for a some future
- * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
- * usually handles calling this in response to input events.
- */
- this.$commitViewValue = function() {
- var viewValue = ctrl.$viewValue;
-
- $timeout.cancel(pendingDebounce);
-
- // If the view value has not changed then we should just exit, except in the case where there is
- // a native validator on the element. In this case the validation state may have changed even though
- // the viewValue has stayed empty.
- if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
- return;
- }
- ctrl.$$updateEmptyClasses(viewValue);
- ctrl.$$lastCommittedViewValue = viewValue;
-
- // change to dirty
- if (ctrl.$pristine) {
- this.$setDirty();
- }
- this.$$parseAndValidate();
- };
-
- this.$$parseAndValidate = function() {
- var viewValue = ctrl.$$lastCommittedViewValue;
- var modelValue = viewValue;
- parserValid = isUndefined(modelValue) ? undefined : true;
-
- if (parserValid) {
- for (var i = 0; i < ctrl.$parsers.length; i++) {
- modelValue = ctrl.$parsers[i](modelValue);
- if (isUndefined(modelValue)) {
- parserValid = false;
- break;
- }
- }
- }
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
- // ctrl.$modelValue has not been touched yet...
- ctrl.$modelValue = ngModelGet($scope);
- }
- var prevModelValue = ctrl.$modelValue;
- var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
- ctrl.$$rawModelValue = modelValue;
-
- if (allowInvalid) {
- ctrl.$modelValue = modelValue;
- writeToModelIfNeeded();
- }
-
- // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
- // This can happen if e.g. $setViewValue is called from inside a parser
- ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
- if (!allowInvalid) {
- // Note: Don't check ctrl.$valid here, as we could have
- // external validators (e.g. calculated on the server),
- // that just call $setValidity and need the model value
- // to calculate their validity.
- ctrl.$modelValue = allValid ? modelValue : undefined;
- writeToModelIfNeeded();
- }
- });
-
- function writeToModelIfNeeded() {
- if (ctrl.$modelValue !== prevModelValue) {
- ctrl.$$writeModelToScope();
- }
- }
- };
-
- this.$$writeModelToScope = function() {
- ngModelSet($scope, ctrl.$modelValue);
- forEach(ctrl.$viewChangeListeners, function(listener) {
- try {
- listener();
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setViewValue
- *
- * @description
- * Update the view value.
- *
- * This method should be called when a control wants to change the view value; typically,
- * this is done from within a DOM event handler. For example, the {@link ng.directive:input input}
- * directive calls it when the value of the input changes and {@link ng.directive:select select}
- * calls it when an option is selected.
- *
- * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`
- * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
- * value sent directly for processing, finally to be applied to `$modelValue` and then the
- * **expression** specified in the `ng-model` attribute. Lastly, all the registered change listeners,
- * in the `$viewChangeListeners` list, are called.
- *
- * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
- * and the `default` trigger is not listed, all those actions will remain pending until one of the
- * `updateOn` events is triggered on the DOM element.
- * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
- * directive is used with a custom debounce for this particular event.
- * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`
- * is specified, once the timer runs out.
- *
- * When used with standard inputs, the view value will always be a string (which is in some cases
- * parsed into another type, such as a `Date` object for `input[date]`.)
- * However, custom controls might also pass objects to this method. In this case, we should make
- * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not
- * perform a deep watch of objects, it only looks for a change of identity. If you only change
- * the property of the object then ngModel will not realize that the object has changed and
- * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should
- * not change properties of the copy once it has been passed to `$setViewValue`.
- * Otherwise you may cause the model value on the scope to change incorrectly.
- *
- * <div class="alert alert-info">
- * In any case, the value passed to the method should always reflect the current value
- * of the control. For example, if you are calling `$setViewValue` for an input element,
- * you should pass the input DOM value. Otherwise, the control and the scope model become
- * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change
- * the control's DOM value in any way. If we want to change the control's DOM value
- * programmatically, we should update the `ngModel` scope expression. Its new value will be
- * picked up by the model controller, which will run it through the `$formatters`, `$render` it
- * to update the DOM, and finally call `$validate` on it.
- * </div>
- *
- * @param {*} value value from the view.
- * @param {string} trigger Event that triggered the update.
- */
- this.$setViewValue = function(value, trigger) {
- ctrl.$viewValue = value;
- if (!ctrl.$options || ctrl.$options.updateOnDefault) {
- ctrl.$$debounceViewValueCommit(trigger);
- }
- };
-
- this.$$debounceViewValueCommit = function(trigger) {
- var debounceDelay = 0,
- options = ctrl.$options,
- debounce;
-
- if (options && isDefined(options.debounce)) {
- debounce = options.debounce;
- if (isNumber(debounce)) {
- debounceDelay = debounce;
- } else if (isNumber(debounce[trigger])) {
- debounceDelay = debounce[trigger];
- } else if (isNumber(debounce['default'])) {
- debounceDelay = debounce['default'];
- }
- }
-
- $timeout.cancel(pendingDebounce);
- if (debounceDelay) {
- pendingDebounce = $timeout(function() {
- ctrl.$commitViewValue();
- }, debounceDelay);
- } else if ($rootScope.$$phase) {
- ctrl.$commitViewValue();
- } else {
- $scope.$apply(function() {
- ctrl.$commitViewValue();
- });
- }
- };
-
- // model -> value
- // Note: we cannot use a normal scope.$watch as we want to detect the following:
- // 1. scope value is 'a'
- // 2. user enters 'b'
- // 3. ng-change kicks in and reverts scope value to 'a'
- // -> scope value did not change since the last digest as
- // ng-change executes in apply phase
- // 4. view should be changed back to 'a'
- $scope.$watch(function ngModelWatch() {
- var modelValue = ngModelGet($scope);
-
- // if scope model value and ngModel value are out of sync
- // TODO(perf): why not move this to the action fn?
- if (modelValue !== ctrl.$modelValue &&
- // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
- (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
- ) {
- ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
- parserValid = undefined;
-
- var formatters = ctrl.$formatters,
- idx = formatters.length;
-
- var viewValue = modelValue;
- while (idx--) {
- viewValue = formatters[idx](viewValue);
- }
- if (ctrl.$viewValue !== viewValue) {
- ctrl.$$updateEmptyClasses(viewValue);
- ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
- ctrl.$render();
-
- ctrl.$$runValidators(modelValue, viewValue, noop);
- }
- }
-
- return modelValue;
- });
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngModel
- *
- * @element input
- * @priority 1
- *
- * @description
- * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
- * property on the scope using {@link ngModel.NgModelController NgModelController},
- * which is created and exposed by this directive.
- *
- * `ngModel` is responsible for:
- *
- * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
- * require.
- * - Providing validation behavior (i.e. required, number, email, url).
- * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
- * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,
- * `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations.
- * - Registering the control with its parent {@link ng.directive:form form}.
- *
- * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
- * current scope. If the property doesn't already exist on this scope, it will be created
- * implicitly and added to the scope.
- *
- * For best practices on using `ngModel`, see:
- *
- * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
- *
- * For basic examples, how to use `ngModel`, see:
- *
- * - {@link ng.directive:input input}
- * - {@link input[text] text}
- * - {@link input[checkbox] checkbox}
- * - {@link input[radio] radio}
- * - {@link input[number] number}
- * - {@link input[email] email}
- * - {@link input[url] url}
- * - {@link input[date] date}
- * - {@link input[datetime-local] datetime-local}
- * - {@link input[time] time}
- * - {@link input[month] month}
- * - {@link input[week] week}
- * - {@link ng.directive:select select}
- * - {@link ng.directive:textarea textarea}
- *
- * # Complex Models (objects or collections)
- *
- * By default, `ngModel` watches the model by reference, not value. This is important to know when
- * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the
- * object or collection change, `ngModel` will not be notified and so the input will not be re-rendered.
- *
- * The model must be assigned an entirely new object or collection before a re-rendering will occur.
- *
- * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression
- * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or
- * if the select is given the `multiple` attribute.
- *
- * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the
- * first level of the object (or only changing the properties of an item in the collection if it's an array) will still
- * not trigger a re-rendering of the model.
- *
- * # CSS classes
- * The following CSS classes are added and removed on the associated input/select/textarea element
- * depending on the validity of the model.
- *
- * - `ng-valid`: the model is valid
- * - `ng-invalid`: the model is invalid
- * - `ng-valid-[key]`: for each valid key added by `$setValidity`
- * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
- * - `ng-pristine`: the control hasn't been interacted with yet
- * - `ng-dirty`: the control has been interacted with
- * - `ng-touched`: the control has been blurred
- * - `ng-untouched`: the control hasn't been blurred
- * - `ng-pending`: any `$asyncValidators` are unfulfilled
- * - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined
- * by the {@link ngModel.NgModelController#$isEmpty} method
- * - `ng-not-empty`: the view contains a non-empty value
- *
- * Keep in mind that ngAnimate can detect each of these classes when added and removed.
- *
- * ## Animation Hooks
- *
- * Animations within models are triggered when any of the associated CSS classes are added and removed
- * on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`,
- * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
- * The animations that are triggered within ngModel are similar to how they work in ngClass and
- * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
- *
- * The following example shows a simple way to utilize CSS transitions to style an input element
- * that has been rendered as invalid after it has been validated:
- *
- * <pre>
- * //be sure to include ngAnimate as a module to hook into more
- * //advanced animations
- * .my-input {
- * transition:0.5s linear all;
- * background: white;
- * }
- * .my-input.ng-invalid {
- * background: red;
- * color:white;
- * }
- * </pre>
- *
- * @example
- * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
- <file name="index.html">
- <script>
- angular.module('inputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.val = '1';
- }]);
- </script>
- <style>
- .my-input {
- transition:all linear 0.5s;
- background: transparent;
- }
- .my-input.ng-invalid {
- color:white;
- background: red;
- }
- </style>
- <p id="inputDescription">
- Update input to see transitions when valid/invalid.
- Integer is a valid value.
- </p>
- <form name="testForm" ng-controller="ExampleController">
- <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input"
- aria-describedby="inputDescription" />
- </form>
- </file>
- * </example>
- *
- * ## Binding to a getter/setter
- *
- * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
- * function that returns a representation of the model when called with zero arguments, and sets
- * the internal state of a model when called with an argument. It's sometimes useful to use this
- * for models that have an internal representation that's different from what the model exposes
- * to the view.
- *
- * <div class="alert alert-success">
- * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
- * frequently than other parts of your code.
- * </div>
- *
- * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
- * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
- * a `<form>`, which will enable this behavior for all `<input>`s within it. See
- * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
- *
- * The following example shows how to use `ngModel` with a getter/setter:
- *
- * @example
- * <example name="ngModel-getter-setter" module="getterSetterExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form name="userForm">
- <label>Name:
- <input type="text" name="userName"
- ng-model="user.name"
- ng-model-options="{ getterSetter: true }" />
- </label>
- </form>
- <pre>user.name = <span ng-bind="user.name()"></span></pre>
- </div>
- </file>
- <file name="app.js">
- angular.module('getterSetterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- var _name = 'Brian';
- $scope.user = {
- name: function(newName) {
- // Note that newName can be undefined for two reasons:
- // 1. Because it is called as a getter and thus called with no arguments
- // 2. Because the property should actually be set to undefined. This happens e.g. if the
- // input is invalid
- return arguments.length ? (_name = newName) : _name;
- }
- };
- }]);
- </file>
- * </example>
- */
-var ngModelDirective = ['$rootScope', function($rootScope) {
- return {
- restrict: 'A',
- require: ['ngModel', '^?form', '^?ngModelOptions'],
- controller: NgModelController,
- // Prelink needs to run before any input directive
- // so that we can set the NgModelOptions in NgModelController
- // before anyone else uses it.
- priority: 1,
- compile: function ngModelCompile(element) {
- // Setup initial state of the control
- element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
-
- return {
- pre: function ngModelPreLink(scope, element, attr, ctrls) {
- var modelCtrl = ctrls[0],
- formCtrl = ctrls[1] || modelCtrl.$$parentForm;
-
- modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
-
- // notify others, especially parent forms
- formCtrl.$addControl(modelCtrl);
-
- attr.$observe('name', function(newValue) {
- if (modelCtrl.$name !== newValue) {
- modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);
- }
- });
-
- scope.$on('$destroy', function() {
- modelCtrl.$$parentForm.$removeControl(modelCtrl);
- });
- },
- post: function ngModelPostLink(scope, element, attr, ctrls) {
- var modelCtrl = ctrls[0];
- if (modelCtrl.$options && modelCtrl.$options.updateOn) {
- element.on(modelCtrl.$options.updateOn, function(ev) {
- modelCtrl.$$debounceViewValueCommit(ev && ev.type);
- });
- }
-
- element.on('blur', function(ev) {
- if (modelCtrl.$touched) return;
-
- if ($rootScope.$$phase) {
- scope.$evalAsync(modelCtrl.$setTouched);
- } else {
- scope.$apply(modelCtrl.$setTouched);
- }
- });
- }
- };
- }
- };
-}];
-
-var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
-
-/**
- * @ngdoc directive
- * @name ngModelOptions
- *
- * @description
- * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
- * events that will trigger a model update and/or a debouncing delay so that the actual update only
- * takes place when a timer expires; this timer will be reset after another change takes place.
- *
- * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
- * be different from the value in the actual model. This means that if you update the model you
- * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
- * order to make sure it is synchronized with the model and that any debounced action is canceled.
- *
- * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
- * method is by making sure the input is placed inside a form that has a `name` attribute. This is
- * important because `form` controllers are published to the related scope under the name in their
- * `name` attribute.
- *
- * Any pending changes will take place immediately when an enclosing form is submitted via the
- * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
- * to have access to the updated model.
- *
- * `ngModelOptions` has an effect on the element it's declared on and its descendants.
- *
- * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
- * - `updateOn`: string specifying which event should the input be bound to. You can set several
- * events using an space delimited list. There is a special event called `default` that
- * matches the default events belonging of the control.
- * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
- * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
- * custom value for each event. For example:
- * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
- * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
- * not validate correctly instead of the default behavior of setting the model to undefined.
- * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
- `ngModel` as getters/setters.
- * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
- * `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the
- * continental US time zone abbreviations, but for general use, use a time zone offset, for
- * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
- * If not specified, the timezone of the browser will be used.
- *
- * @example
-
- The following example shows how to override immediate updates. Changes on the inputs within the
- form will update the model only when the control loses focus (blur event). If `escape` key is
- pressed while the input field is focused, the value is reset to the value in the current model.
-
- <example name="ngModelOptions-directive-blur" module="optionsExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form name="userForm">
- <label>Name:
- <input type="text" name="userName"
- ng-model="user.name"
- ng-model-options="{ updateOn: 'blur' }"
- ng-keyup="cancel($event)" />
- </label><br />
- <label>Other data:
- <input type="text" ng-model="user.data" />
- </label><br />
- </form>
- <pre>user.name = <span ng-bind="user.name"></span></pre>
- <pre>user.data = <span ng-bind="user.data"></span></pre>
- </div>
- </file>
- <file name="app.js">
- angular.module('optionsExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = { name: 'John', data: '' };
-
- $scope.cancel = function(e) {
- if (e.keyCode == 27) {
- $scope.userForm.userName.$rollbackViewValue();
- }
- };
- }]);
- </file>
- <file name="protractor.js" type="protractor">
- var model = element(by.binding('user.name'));
- var input = element(by.model('user.name'));
- var other = element(by.model('user.data'));
-
- it('should allow custom events', function() {
- input.sendKeys(' Doe');
- input.click();
- expect(model.getText()).toEqual('John');
- other.click();
- expect(model.getText()).toEqual('John Doe');
- });
-
- it('should $rollbackViewValue when model changes', function() {
- input.sendKeys(' Doe');
- expect(input.getAttribute('value')).toEqual('John Doe');
- input.sendKeys(protractor.Key.ESCAPE);
- expect(input.getAttribute('value')).toEqual('John');
- other.click();
- expect(model.getText()).toEqual('John');
- });
- </file>
- </example>
-
- This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
- If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
-
- <example name="ngModelOptions-directive-debounce" module="optionsExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form name="userForm">
- <label>Name:
- <input type="text" name="userName"
- ng-model="user.name"
- ng-model-options="{ debounce: 1000 }" />
- </label>
- <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button>
- <br />
- </form>
- <pre>user.name = <span ng-bind="user.name"></span></pre>
- </div>
- </file>
- <file name="app.js">
- angular.module('optionsExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = { name: 'Igor' };
- }]);
- </file>
- </example>
-
- This one shows how to bind to getter/setters:
-
- <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form name="userForm">
- <label>Name:
- <input type="text" name="userName"
- ng-model="user.name"
- ng-model-options="{ getterSetter: true }" />
- </label>
- </form>
- <pre>user.name = <span ng-bind="user.name()"></span></pre>
- </div>
- </file>
- <file name="app.js">
- angular.module('getterSetterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- var _name = 'Brian';
- $scope.user = {
- name: function(newName) {
- // Note that newName can be undefined for two reasons:
- // 1. Because it is called as a getter and thus called with no arguments
- // 2. Because the property should actually be set to undefined. This happens e.g. if the
- // input is invalid
- return arguments.length ? (_name = newName) : _name;
- }
- };
- }]);
- </file>
- </example>
- */
-var ngModelOptionsDirective = function() {
- return {
- restrict: 'A',
- controller: ['$scope', '$attrs', function($scope, $attrs) {
- var that = this;
- this.$options = copy($scope.$eval($attrs.ngModelOptions));
- // Allow adding/overriding bound events
- if (isDefined(this.$options.updateOn)) {
- this.$options.updateOnDefault = false;
- // extract "default" pseudo-event from list of events that can trigger a model update
- this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
- that.$options.updateOnDefault = true;
- return ' ';
- }));
- } else {
- this.$options.updateOnDefault = true;
- }
- }]
- };
-};
-
-
-
-// helper methods
-function addSetValidityMethod(context) {
- var ctrl = context.ctrl,
- $element = context.$element,
- classCache = {},
- set = context.set,
- unset = context.unset,
- $animate = context.$animate;
-
- classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
-
- ctrl.$setValidity = setValidity;
-
- function setValidity(validationErrorKey, state, controller) {
- if (isUndefined(state)) {
- createAndSet('$pending', validationErrorKey, controller);
- } else {
- unsetAndCleanup('$pending', validationErrorKey, controller);
- }
- if (!isBoolean(state)) {
- unset(ctrl.$error, validationErrorKey, controller);
- unset(ctrl.$$success, validationErrorKey, controller);
- } else {
- if (state) {
- unset(ctrl.$error, validationErrorKey, controller);
- set(ctrl.$$success, validationErrorKey, controller);
- } else {
- set(ctrl.$error, validationErrorKey, controller);
- unset(ctrl.$$success, validationErrorKey, controller);
- }
- }
- if (ctrl.$pending) {
- cachedToggleClass(PENDING_CLASS, true);
- ctrl.$valid = ctrl.$invalid = undefined;
- toggleValidationCss('', null);
- } else {
- cachedToggleClass(PENDING_CLASS, false);
- ctrl.$valid = isObjectEmpty(ctrl.$error);
- ctrl.$invalid = !ctrl.$valid;
- toggleValidationCss('', ctrl.$valid);
- }
-
- // re-read the state as the set/unset methods could have
- // combined state in ctrl.$error[validationError] (used for forms),
- // where setting/unsetting only increments/decrements the value,
- // and does not replace it.
- var combinedState;
- if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
- combinedState = undefined;
- } else if (ctrl.$error[validationErrorKey]) {
- combinedState = false;
- } else if (ctrl.$$success[validationErrorKey]) {
- combinedState = true;
- } else {
- combinedState = null;
- }
-
- toggleValidationCss(validationErrorKey, combinedState);
- ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
- }
-
- function createAndSet(name, value, controller) {
- if (!ctrl[name]) {
- ctrl[name] = {};
- }
- set(ctrl[name], value, controller);
- }
-
- function unsetAndCleanup(name, value, controller) {
- if (ctrl[name]) {
- unset(ctrl[name], value, controller);
- }
- if (isObjectEmpty(ctrl[name])) {
- ctrl[name] = undefined;
- }
- }
-
- function cachedToggleClass(className, switchValue) {
- if (switchValue && !classCache[className]) {
- $animate.addClass($element, className);
- classCache[className] = true;
- } else if (!switchValue && classCache[className]) {
- $animate.removeClass($element, className);
- classCache[className] = false;
- }
- }
-
- function toggleValidationCss(validationErrorKey, isValid) {
- validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
-
- cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
- cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
- }
-}
-
-function isObjectEmpty(obj) {
- if (obj) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- return false;
- }
- }
- }
- return true;
-}
-
-/**
- * @ngdoc directive
- * @name ngNonBindable
- * @restrict AC
- * @priority 1000
- *
- * @description
- * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
- * DOM element. This is useful if the element contains what appears to be Angular directives and
- * bindings but which should be ignored by Angular. This could be the case if you have a site that
- * displays snippets of code, for instance.
- *
- * @element ANY
- *
- * @example
- * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
- * but the one wrapped in `ngNonBindable` is left alone.
- *
- * @example
- <example>
- <file name="index.html">
- <div>Normal: {{1 + 2}}</div>
- <div ng-non-bindable>Ignored: {{1 + 2}}</div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-non-bindable', function() {
- expect(element(by.binding('1 + 2')).getText()).toContain('3');
- expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
- });
- </file>
- </example>
- */
-var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
-
-/* global jqLiteRemove */
-
-var ngOptionsMinErr = minErr('ngOptions');
-
-/**
- * @ngdoc directive
- * @name ngOptions
- * @restrict A
- *
- * @description
- *
- * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
- * elements for the `<select>` element using the array or object obtained by evaluating the
- * `ngOptions` comprehension expression.
- *
- * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
- * similar result. However, `ngOptions` provides some benefits such as reducing memory and
- * increasing speed by not creating a new scope for each repeated instance, as well as providing
- * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
- * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
- * to a non-string value. This is because an option element can only be bound to string values at
- * present.
- *
- * When an item in the `<select>` menu is selected, the array element or object property
- * represented by the selected option will be bound to the model identified by the `ngModel`
- * directive.
- *
- * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
- * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
- * option. See example below for demonstration.
- *
- * ## Complex Models (objects or collections)
- *
- * By default, `ngModel` watches the model by reference, not value. This is important to know when
- * binding the select to a model that is an object or a collection.
- *
- * One issue occurs if you want to preselect an option. For example, if you set
- * the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,
- * because the objects are not identical. So by default, you should always reference the item in your collection
- * for preselections, e.g.: `$scope.selected = $scope.collection[3]`.
- *
- * Another solution is to use a `track by` clause, because then `ngOptions` will track the identity
- * of the item not by reference, but by the result of the `track by` expression. For example, if your
- * collection items have an id property, you would `track by item.id`.
- *
- * A different issue with objects or collections is that ngModel won't detect if an object property or
- * a collection item changes. For that reason, `ngOptions` additionally watches the model using
- * `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.
- * This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection
- * has not changed identity, but only a property on the object or an item in the collection changes.
- *
- * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
- * if the model is an array). This means that changing a property deeper than the first level inside the
- * object/collection will not trigger a re-rendering.
- *
- * ## `select` **`as`**
- *
- * Using `select` **`as`** will bind the result of the `select` expression to the model, but
- * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
- * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
- * is used, the result of that expression will be set as the value of the `option` and `select` elements.
- *
- *
- * ### `select` **`as`** and **`track by`**
- *
- * <div class="alert alert-warning">
- * Be careful when using `select` **`as`** and **`track by`** in the same expression.
- * </div>
- *
- * Given this array of items on the $scope:
- *
- * ```js
- * $scope.items = [{
- * id: 1,
- * label: 'aLabel',
- * subItem: { name: 'aSubItem' }
- * }, {
- * id: 2,
- * label: 'bLabel',
- * subItem: { name: 'bSubItem' }
- * }];
- * ```
- *
- * This will work:
- *
- * ```html
- * <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
- * ```
- * ```js
- * $scope.selected = $scope.items[0];
- * ```
- *
- * but this will not work:
- *
- * ```html
- * <select ng-options="item.subItem as item.label for item in items track by item.id" ng-model="selected"></select>
- * ```
- * ```js
- * $scope.selected = $scope.items[0].subItem;
- * ```
- *
- * In both examples, the **`track by`** expression is applied successfully to each `item` in the
- * `items` array. Because the selected option has been set programmatically in the controller, the
- * **`track by`** expression is also applied to the `ngModel` value. In the first example, the
- * `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with
- * no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**
- * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value
- * is not matched against any `<option>` and the `<select>` appears as having no selected value.
- *
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required The control is considered valid only if value is entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {comprehension_expression=} ngOptions in one of the following forms:
- *
- * * for array data sources:
- * * `label` **`for`** `value` **`in`** `array`
- * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
- * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
- * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
- * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
- * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
- * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
- * (for including a filter with `track by`)
- * * for object data sources:
- * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
- * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
- * * `select` **`as`** `label` **`group by`** `group`
- * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
- * * `select` **`as`** `label` **`disable when`** `disable`
- * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
- *
- * Where:
- *
- * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
- * * `value`: local variable which will refer to each item in the `array` or each property value
- * of `object` during iteration.
- * * `key`: local variable which will refer to a property name in `object` during iteration.
- * * `label`: The result of this expression will be the label for `<option>` element. The
- * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
- * * `select`: The result of this expression will be bound to the model of the parent `<select>`
- * element. If not specified, `select` expression will default to `value`.
- * * `group`: The result of this expression will be used to group options using the `<optgroup>`
- * DOM element.
- * * `disable`: The result of this expression will be used to disable the rendered `<option>`
- * element. Return `true` to disable.
- * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
- * used to identify the objects in the array. The `trackexpr` will most likely refer to the
- * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
- * even when the options are recreated (e.g. reloaded from the server).
- *
- * @example
- <example module="selectExample">
- <file name="index.html">
- <script>
- angular.module('selectExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.colors = [
- {name:'black', shade:'dark'},
- {name:'white', shade:'light', notAnOption: true},
- {name:'red', shade:'dark'},
- {name:'blue', shade:'dark', notAnOption: true},
- {name:'yellow', shade:'light', notAnOption: false}
- ];
- $scope.myColor = $scope.colors[2]; // red
- }]);
- </script>
- <div ng-controller="ExampleController">
- <ul>
- <li ng-repeat="color in colors">
- <label>Name: <input ng-model="color.name"></label>
- <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label>
- <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button>
- </li>
- <li>
- <button ng-click="colors.push({})">add</button>
- </li>
- </ul>
- <hr/>
- <label>Color (null not allowed):
- <select ng-model="myColor" ng-options="color.name for color in colors"></select>
- </label><br/>
- <label>Color (null allowed):
- <span class="nullable">
- <select ng-model="myColor" ng-options="color.name for color in colors">
- <option value="">-- choose color --</option>
- </select>
- </span></label><br/>
-
- <label>Color grouped by shade:
- <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
- </select>
- </label><br/>
-
- <label>Color grouped by shade, with some disabled:
- <select ng-model="myColor"
- ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
- </select>
- </label><br/>
-
-
-
- Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>.
- <br/>
- <hr/>
- Currently selected: {{ {selected_color:myColor} }}
- <div style="border:solid 1px black; height:20px"
- ng-style="{'background-color':myColor.name}">
- </div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-options', function() {
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
- element.all(by.model('myColor')).first().click();
- element.all(by.css('select[ng-model="myColor"] option')).first().click();
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
- element(by.css('.nullable select[ng-model="myColor"]')).click();
- element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
- });
- </file>
- </example>
- */
-
-// jshint maxlen: false
-// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
-var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
- // 1: value expression (valueFn)
- // 2: label expression (displayFn)
- // 3: group by expression (groupByFn)
- // 4: disable when expression (disableWhenFn)
- // 5: array item variable name
- // 6: object item key variable name
- // 7: object item value variable name
- // 8: collection expression
- // 9: track by expression
-// jshint maxlen: 100
-
-
-var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
-
- function parseOptionsExpression(optionsExp, selectElement, scope) {
-
- var match = optionsExp.match(NG_OPTIONS_REGEXP);
- if (!(match)) {
- throw ngOptionsMinErr('iexp',
- "Expected expression in form of " +
- "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
- " but got '{0}'. Element: {1}",
- optionsExp, startingTag(selectElement));
- }
-
- // Extract the parts from the ngOptions expression
-
- // The variable name for the value of the item in the collection
- var valueName = match[5] || match[7];
- // The variable name for the key of the item in the collection
- var keyName = match[6];
-
- // An expression that generates the viewValue for an option if there is a label expression
- var selectAs = / as /.test(match[0]) && match[1];
- // An expression that is used to track the id of each object in the options collection
- var trackBy = match[9];
- // An expression that generates the viewValue for an option if there is no label expression
- var valueFn = $parse(match[2] ? match[1] : valueName);
- var selectAsFn = selectAs && $parse(selectAs);
- var viewValueFn = selectAsFn || valueFn;
- var trackByFn = trackBy && $parse(trackBy);
-
- // Get the value by which we are going to track the option
- // if we have a trackFn then use that (passing scope and locals)
- // otherwise just hash the given viewValue
- var getTrackByValueFn = trackBy ?
- function(value, locals) { return trackByFn(scope, locals); } :
- function getHashOfValue(value) { return hashKey(value); };
- var getTrackByValue = function(value, key) {
- return getTrackByValueFn(value, getLocals(value, key));
- };
-
- var displayFn = $parse(match[2] || match[1]);
- var groupByFn = $parse(match[3] || '');
- var disableWhenFn = $parse(match[4] || '');
- var valuesFn = $parse(match[8]);
-
- var locals = {};
- var getLocals = keyName ? function(value, key) {
- locals[keyName] = key;
- locals[valueName] = value;
- return locals;
- } : function(value) {
- locals[valueName] = value;
- return locals;
- };
-
-
- function Option(selectValue, viewValue, label, group, disabled) {
- this.selectValue = selectValue;
- this.viewValue = viewValue;
- this.label = label;
- this.group = group;
- this.disabled = disabled;
- }
-
- function getOptionValuesKeys(optionValues) {
- var optionValuesKeys;
-
- if (!keyName && isArrayLike(optionValues)) {
- optionValuesKeys = optionValues;
- } else {
- // if object, extract keys, in enumeration order, unsorted
- optionValuesKeys = [];
- for (var itemKey in optionValues) {
- if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
- optionValuesKeys.push(itemKey);
- }
- }
- }
- return optionValuesKeys;
- }
-
- return {
- trackBy: trackBy,
- getTrackByValue: getTrackByValue,
- getWatchables: $parse(valuesFn, function(optionValues) {
- // Create a collection of things that we would like to watch (watchedArray)
- // so that they can all be watched using a single $watchCollection
- // that only runs the handler once if anything changes
- var watchedArray = [];
- optionValues = optionValues || [];
-
- var optionValuesKeys = getOptionValuesKeys(optionValues);
- var optionValuesLength = optionValuesKeys.length;
- for (var index = 0; index < optionValuesLength; index++) {
- var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
- var value = optionValues[key];
-
- var locals = getLocals(optionValues[key], key);
- var selectValue = getTrackByValueFn(optionValues[key], locals);
- watchedArray.push(selectValue);
-
- // Only need to watch the displayFn if there is a specific label expression
- if (match[2] || match[1]) {
- var label = displayFn(scope, locals);
- watchedArray.push(label);
- }
-
- // Only need to watch the disableWhenFn if there is a specific disable expression
- if (match[4]) {
- var disableWhen = disableWhenFn(scope, locals);
- watchedArray.push(disableWhen);
- }
- }
- return watchedArray;
- }),
-
- getOptions: function() {
-
- var optionItems = [];
- var selectValueMap = {};
-
- // The option values were already computed in the `getWatchables` fn,
- // which must have been called to trigger `getOptions`
- var optionValues = valuesFn(scope) || [];
- var optionValuesKeys = getOptionValuesKeys(optionValues);
- var optionValuesLength = optionValuesKeys.length;
-
- for (var index = 0; index < optionValuesLength; index++) {
- var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
- var value = optionValues[key];
- var locals = getLocals(value, key);
- var viewValue = viewValueFn(scope, locals);
- var selectValue = getTrackByValueFn(viewValue, locals);
- var label = displayFn(scope, locals);
- var group = groupByFn(scope, locals);
- var disabled = disableWhenFn(scope, locals);
- var optionItem = new Option(selectValue, viewValue, label, group, disabled);
-
- optionItems.push(optionItem);
- selectValueMap[selectValue] = optionItem;
- }
-
- return {
- items: optionItems,
- selectValueMap: selectValueMap,
- getOptionFromViewValue: function(value) {
- return selectValueMap[getTrackByValue(value)];
- },
- getViewValueFromOption: function(option) {
- // If the viewValue could be an object that may be mutated by the application,
- // we need to make a copy and not return the reference to the value on the option.
- return trackBy ? angular.copy(option.viewValue) : option.viewValue;
- }
- };
- }
- };
- }
-
-
- // we can't just jqLite('<option>') since jqLite is not smart enough
- // to create it in <select> and IE barfs otherwise.
- var optionTemplate = document.createElement('option'),
- optGroupTemplate = document.createElement('optgroup');
-
- function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
-
- var selectCtrl = ctrls[0];
- var ngModelCtrl = ctrls[1];
- var multiple = attr.multiple;
-
- // The emptyOption allows the application developer to provide their own custom "empty"
- // option when the viewValue does not match any of the option values.
- var emptyOption;
- for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) {
- if (children[i].value === '') {
- emptyOption = children.eq(i);
- break;
- }
- }
-
- var providedEmptyOption = !!emptyOption;
-
- var unknownOption = jqLite(optionTemplate.cloneNode(false));
- unknownOption.val('?');
-
- var options;
- var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);
-
-
- var renderEmptyOption = function() {
- if (!providedEmptyOption) {
- selectElement.prepend(emptyOption);
- }
- selectElement.val('');
- emptyOption.prop('selected', true); // needed for IE
- emptyOption.attr('selected', true);
- };
-
- var removeEmptyOption = function() {
- if (!providedEmptyOption) {
- emptyOption.remove();
- }
- };
-
-
- var renderUnknownOption = function() {
- selectElement.prepend(unknownOption);
- selectElement.val('?');
- unknownOption.prop('selected', true); // needed for IE
- unknownOption.attr('selected', true);
- };
-
- var removeUnknownOption = function() {
- unknownOption.remove();
- };
-
- // Update the controller methods for multiple selectable options
- if (!multiple) {
-
- selectCtrl.writeValue = function writeNgOptionsValue(value) {
- var option = options.getOptionFromViewValue(value);
-
- if (option && !option.disabled) {
- if (selectElement[0].value !== option.selectValue) {
- removeUnknownOption();
- removeEmptyOption();
-
- selectElement[0].value = option.selectValue;
- option.element.selected = true;
- option.element.setAttribute('selected', 'selected');
- }
- } else {
- if (value === null || providedEmptyOption) {
- removeUnknownOption();
- renderEmptyOption();
- } else {
- removeEmptyOption();
- renderUnknownOption();
- }
- }
- };
-
- selectCtrl.readValue = function readNgOptionsValue() {
-
- var selectedOption = options.selectValueMap[selectElement.val()];
-
- if (selectedOption && !selectedOption.disabled) {
- removeEmptyOption();
- removeUnknownOption();
- return options.getViewValueFromOption(selectedOption);
- }
- return null;
- };
-
- // If we are using `track by` then we must watch the tracked value on the model
- // since ngModel only watches for object identity change
- if (ngOptions.trackBy) {
- scope.$watch(
- function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },
- function() { ngModelCtrl.$render(); }
- );
- }
-
- } else {
-
- ngModelCtrl.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
-
-
- selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
- options.items.forEach(function(option) {
- option.element.selected = false;
- });
-
- if (value) {
- value.forEach(function(item) {
- var option = options.getOptionFromViewValue(item);
- if (option && !option.disabled) option.element.selected = true;
- });
- }
- };
-
-
- selectCtrl.readValue = function readNgOptionsMultiple() {
- var selectedValues = selectElement.val() || [],
- selections = [];
-
- forEach(selectedValues, function(value) {
- var option = options.selectValueMap[value];
- if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));
- });
-
- return selections;
- };
-
- // If we are using `track by` then we must watch these tracked values on the model
- // since ngModel only watches for object identity change
- if (ngOptions.trackBy) {
-
- scope.$watchCollection(function() {
- if (isArray(ngModelCtrl.$viewValue)) {
- return ngModelCtrl.$viewValue.map(function(value) {
- return ngOptions.getTrackByValue(value);
- });
- }
- }, function() {
- ngModelCtrl.$render();
- });
-
- }
- }
-
-
- if (providedEmptyOption) {
-
- // we need to remove it before calling selectElement.empty() because otherwise IE will
- // remove the label from the element. wtf?
- emptyOption.remove();
-
- // compile the element since there might be bindings in it
- $compile(emptyOption)(scope);
-
- // remove the class, which is added automatically because we recompile the element and it
- // becomes the compilation root
- emptyOption.removeClass('ng-scope');
- } else {
- emptyOption = jqLite(optionTemplate.cloneNode(false));
- }
-
- // We need to do this here to ensure that the options object is defined
- // when we first hit it in writeNgOptionsValue
- updateOptions();
-
- // We will re-render the option elements if the option values or labels change
- scope.$watchCollection(ngOptions.getWatchables, updateOptions);
-
- // ------------------------------------------------------------------ //
-
-
- function updateOptionElement(option, element) {
- option.element = element;
- element.disabled = option.disabled;
- // NOTE: The label must be set before the value, otherwise IE10/11/EDGE create unresponsive
- // selects in certain circumstances when multiple selects are next to each other and display
- // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
- // See https://github.com/angular/angular.js/issues/11314 for more info.
- // This is unfortunately untestable with unit / e2e tests
- if (option.label !== element.label) {
- element.label = option.label;
- element.textContent = option.label;
- }
- if (option.value !== element.value) element.value = option.selectValue;
- }
-
- function addOrReuseElement(parent, current, type, templateElement) {
- var element;
- // Check whether we can reuse the next element
- if (current && lowercase(current.nodeName) === type) {
- // The next element is the right type so reuse it
- element = current;
- } else {
- // The next element is not the right type so create a new one
- element = templateElement.cloneNode(false);
- if (!current) {
- // There are no more elements so just append it to the select
- parent.appendChild(element);
- } else {
- // The next element is not a group so insert the new one
- parent.insertBefore(element, current);
- }
- }
- return element;
- }
-
-
- function removeExcessElements(current) {
- var next;
- while (current) {
- next = current.nextSibling;
- jqLiteRemove(current);
- current = next;
- }
- }
-
-
- function skipEmptyAndUnknownOptions(current) {
- var emptyOption_ = emptyOption && emptyOption[0];
- var unknownOption_ = unknownOption && unknownOption[0];
-
- // We cannot rely on the extracted empty option being the same as the compiled empty option,
- // because the compiled empty option might have been replaced by a comment because
- // it had an "element" transclusion directive on it (such as ngIf)
- if (emptyOption_ || unknownOption_) {
- while (current &&
- (current === emptyOption_ ||
- current === unknownOption_ ||
- current.nodeType === NODE_TYPE_COMMENT ||
- (nodeName_(current) === 'option' && current.value === ''))) {
- current = current.nextSibling;
- }
- }
- return current;
- }
-
-
- function updateOptions() {
-
- var previousValue = options && selectCtrl.readValue();
-
- options = ngOptions.getOptions();
-
- var groupMap = {};
- var currentElement = selectElement[0].firstChild;
-
- // Ensure that the empty option is always there if it was explicitly provided
- if (providedEmptyOption) {
- selectElement.prepend(emptyOption);
- }
-
- currentElement = skipEmptyAndUnknownOptions(currentElement);
-
- options.items.forEach(function updateOption(option) {
- var group;
- var groupElement;
- var optionElement;
-
- if (isDefined(option.group)) {
-
- // This option is to live in a group
- // See if we have already created this group
- group = groupMap[option.group];
-
- if (!group) {
-
- // We have not already created this group
- groupElement = addOrReuseElement(selectElement[0],
- currentElement,
- 'optgroup',
- optGroupTemplate);
- // Move to the next element
- currentElement = groupElement.nextSibling;
-
- // Update the label on the group element
- groupElement.label = option.group;
-
- // Store it for use later
- group = groupMap[option.group] = {
- groupElement: groupElement,
- currentOptionElement: groupElement.firstChild
- };
-
- }
-
- // So now we have a group for this option we add the option to the group
- optionElement = addOrReuseElement(group.groupElement,
- group.currentOptionElement,
- 'option',
- optionTemplate);
- updateOptionElement(option, optionElement);
- // Move to the next element
- group.currentOptionElement = optionElement.nextSibling;
-
- } else {
-
- // This option is not in a group
- optionElement = addOrReuseElement(selectElement[0],
- currentElement,
- 'option',
- optionTemplate);
- updateOptionElement(option, optionElement);
- // Move to the next element
- currentElement = optionElement.nextSibling;
- }
- });
-
-
- // Now remove all excess options and group
- Object.keys(groupMap).forEach(function(key) {
- removeExcessElements(groupMap[key].currentOptionElement);
- });
- removeExcessElements(currentElement);
-
- ngModelCtrl.$render();
-
- // Check to see if the value has changed due to the update to the options
- if (!ngModelCtrl.$isEmpty(previousValue)) {
- var nextValue = selectCtrl.readValue();
- var isNotPrimitive = ngOptions.trackBy || multiple;
- if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
- ngModelCtrl.$setViewValue(nextValue);
- ngModelCtrl.$render();
- }
- }
-
- }
- }
-
- return {
- restrict: 'A',
- terminal: true,
- require: ['select', 'ngModel'],
- link: {
- pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
- // Deactivate the SelectController.register method to prevent
- // option directives from accidentally registering themselves
- // (and unwanted $destroy handlers etc.)
- ctrls[0].registerOption = noop;
- },
- post: ngOptionsPostLink
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngPluralize
- * @restrict EA
- *
- * @description
- * `ngPluralize` is a directive that displays messages according to en-US localization rules.
- * These rules are bundled with angular.js, but can be overridden
- * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
- * by specifying the mappings between
- * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
- * and the strings to be displayed.
- *
- * # Plural categories and explicit number rules
- * There are two
- * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
- * in Angular's default en-US locale: "one" and "other".
- *
- * While a plural category may match many numbers (for example, in en-US locale, "other" can match
- * any number that is not 1), an explicit number rule can only match one number. For example, the
- * explicit number rule for "3" matches the number 3. There are examples of plural categories
- * and explicit number rules throughout the rest of this documentation.
- *
- * # Configuring ngPluralize
- * You configure ngPluralize by providing 2 attributes: `count` and `when`.
- * You can also provide an optional attribute, `offset`.
- *
- * The value of the `count` attribute can be either a string or an {@link guide/expression
- * Angular expression}; these are evaluated on the current scope for its bound value.
- *
- * The `when` attribute specifies the mappings between plural categories and the actual
- * string to be displayed. The value of the attribute should be a JSON object.
- *
- * The following example shows how to configure ngPluralize:
- *
- * ```html
- * <ng-pluralize count="personCount"
- when="{'0': 'Nobody is viewing.',
- * 'one': '1 person is viewing.',
- * 'other': '{} people are viewing.'}">
- * </ng-pluralize>
- *```
- *
- * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
- * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
- * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
- * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
- * show "a dozen people are viewing".
- *
- * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
- * into pluralized strings. In the previous example, Angular will replace `{}` with
- * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
- * for <span ng-non-bindable>{{numberExpression}}</span>.
- *
- * If no rule is defined for a category, then an empty string is displayed and a warning is generated.
- * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`.
- *
- * # Configuring ngPluralize with offset
- * The `offset` attribute allows further customization of pluralized text, which can result in
- * a better user experience. For example, instead of the message "4 people are viewing this document",
- * you might display "John, Kate and 2 others are viewing this document".
- * The offset attribute allows you to offset a number by any desired value.
- * Let's take a look at an example:
- *
- * ```html
- * <ng-pluralize count="personCount" offset=2
- * when="{'0': 'Nobody is viewing.',
- * '1': '{{person1}} is viewing.',
- * '2': '{{person1}} and {{person2}} are viewing.',
- * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
- * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
- * </ng-pluralize>
- * ```
- *
- * Notice that we are still using two plural categories(one, other), but we added
- * three explicit number rules 0, 1 and 2.
- * When one person, perhaps John, views the document, "John is viewing" will be shown.
- * When three people view the document, no explicit number rule is found, so
- * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
- * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
- * is shown.
- *
- * Note that when you specify offsets, you must provide explicit number rules for
- * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
- * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
- * plural categories "one" and "other".
- *
- * @param {string|expression} count The variable to be bound to.
- * @param {string} when The mapping between plural category to its corresponding strings.
- * @param {number=} offset Offset to deduct from the total number.
- *
- * @example
- <example module="pluralizeExample">
- <file name="index.html">
- <script>
- angular.module('pluralizeExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.person1 = 'Igor';
- $scope.person2 = 'Misko';
- $scope.personCount = 1;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/>
- <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/>
- <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/>
-
- <!--- Example with simple pluralization rules for en locale --->
- Without Offset:
- <ng-pluralize count="personCount"
- when="{'0': 'Nobody is viewing.',
- 'one': '1 person is viewing.',
- 'other': '{} people are viewing.'}">
- </ng-pluralize><br>
-
- <!--- Example with offset --->
- With Offset(2):
- <ng-pluralize count="personCount" offset=2
- when="{'0': 'Nobody is viewing.',
- '1': '{{person1}} is viewing.',
- '2': '{{person1}} and {{person2}} are viewing.',
- 'one': '{{person1}}, {{person2}} and one other person are viewing.',
- 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
- </ng-pluralize>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should show correct pluralized string', function() {
- var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
- var withOffset = element.all(by.css('ng-pluralize')).get(1);
- var countInput = element(by.model('personCount'));
-
- expect(withoutOffset.getText()).toEqual('1 person is viewing.');
- expect(withOffset.getText()).toEqual('Igor is viewing.');
-
- countInput.clear();
- countInput.sendKeys('0');
-
- expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
- expect(withOffset.getText()).toEqual('Nobody is viewing.');
-
- countInput.clear();
- countInput.sendKeys('2');
-
- expect(withoutOffset.getText()).toEqual('2 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
-
- countInput.clear();
- countInput.sendKeys('3');
-
- expect(withoutOffset.getText()).toEqual('3 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
-
- countInput.clear();
- countInput.sendKeys('4');
-
- expect(withoutOffset.getText()).toEqual('4 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
- });
- it('should show data-bound names', function() {
- var withOffset = element.all(by.css('ng-pluralize')).get(1);
- var personCount = element(by.model('personCount'));
- var person1 = element(by.model('person1'));
- var person2 = element(by.model('person2'));
- personCount.clear();
- personCount.sendKeys('4');
- person1.clear();
- person1.sendKeys('Di');
- person2.clear();
- person2.sendKeys('Vojta');
- expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
- });
- </file>
- </example>
- */
-var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {
- var BRACE = /{}/g,
- IS_WHEN = /^when(Minus)?(.+)$/;
-
- return {
- link: function(scope, element, attr) {
- var numberExp = attr.count,
- whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
- offset = attr.offset || 0,
- whens = scope.$eval(whenExp) || {},
- whensExpFns = {},
- startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
- watchRemover = angular.noop,
- lastCount;
-
- forEach(attr, function(expression, attributeName) {
- var tmpMatch = IS_WHEN.exec(attributeName);
- if (tmpMatch) {
- var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
- whens[whenKey] = element.attr(attr.$attr[attributeName]);
- }
- });
- forEach(whens, function(expression, key) {
- whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
-
- });
-
- scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
- var count = parseFloat(newVal);
- var countIsNaN = isNaN(count);
-
- if (!countIsNaN && !(count in whens)) {
- // If an explicit number rule such as 1, 2, 3... is defined, just use it.
- // Otherwise, check it against pluralization rules in $locale service.
- count = $locale.pluralCat(count - offset);
- }
-
- // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
- // In JS `NaN !== NaN`, so we have to explicitly check.
- if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
- watchRemover();
- var whenExpFn = whensExpFns[count];
- if (isUndefined(whenExpFn)) {
- if (newVal != null) {
- $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp);
- }
- watchRemover = noop;
- updateElementText();
- } else {
- watchRemover = scope.$watch(whenExpFn, updateElementText);
- }
- lastCount = count;
- }
- });
-
- function updateElementText(newText) {
- element.text(newText || '');
- }
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngRepeat
- * @multiElement
- *
- * @description
- * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
- * instance gets its own scope, where the given loop variable is set to the current collection item,
- * and `$index` is set to the item index or key.
- *
- * Special properties are exposed on the local scope of each template instance, including:
- *
- * | Variable | Type | Details |
- * |-----------|-----------------|-----------------------------------------------------------------------------|
- * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
- * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
- * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
- * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
- * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
- * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
- *
- * <div class="alert alert-info">
- * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
- * This may be useful when, for instance, nesting ngRepeats.
- * </div>
- *
- *
- * # Iterating over object properties
- *
- * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
- * syntax:
- *
- * ```js
- * <div ng-repeat="(key, value) in myObj"> ... </div>
- * ```
- *
- * You need to be aware that the JavaScript specification does not define the order of keys
- * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive
- * used to sort the keys alphabetically.)
- *
- * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
- * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
- * keys in the order in which they were defined, although there are exceptions when keys are deleted
- * and reinstated. See the [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).
- *
- * If this is not desired, the recommended workaround is to convert your object into an array
- * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
- * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
- * or implement a `$watch` on the object yourself.
- *
- *
- * # Tracking and Duplicates
- *
- * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in
- * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:
- *
- * * When an item is added, a new instance of the template is added to the DOM.
- * * When an item is removed, its template instance is removed from the DOM.
- * * When items are reordered, their respective templates are reordered in the DOM.
- *
- * To minimize creation of DOM elements, `ngRepeat` uses a function
- * to "keep track" of all items in the collection and their corresponding DOM elements.
- * For example, if an item is added to the collection, ngRepeat will know that all other items
- * already have DOM elements, and will not re-render them.
- *
- * The default tracking function (which tracks items by their identity) does not allow
- * duplicate items in arrays. This is because when there are duplicates, it is not possible
- * to maintain a one-to-one mapping between collection items and DOM elements.
- *
- * If you do need to repeat duplicate items, you can substitute the default tracking behavior
- * with your own using the `track by` expression.
- *
- * For example, you may track items by the index of each item in the collection, using the
- * special scope property `$index`:
- * ```html
- * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
- * {{n}}
- * </div>
- * ```
- *
- * You may also use arbitrary expressions in `track by`, including references to custom functions
- * on the scope:
- * ```html
- * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
- * {{n}}
- * </div>
- * ```
- *
- * <div class="alert alert-success">
- * If you are working with objects that have an identifier property, you should track
- * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
- * will not have to rebuild the DOM elements for items it has already rendered, even if the
- * JavaScript objects in the collection have been substituted for new ones. For large collections,
- * this significantly improves rendering performance. If you don't have a unique identifier,
- * `track by $index` can also provide a performance boost.
- * </div>
- * ```html
- * <div ng-repeat="model in collection track by model.id">
- * {{model.name}}
- * </div>
- * ```
- *
- * When no `track by` expression is provided, it is equivalent to tracking by the built-in
- * `$id` function, which tracks items by their identity:
- * ```html
- * <div ng-repeat="obj in collection track by $id(obj)">
- * {{obj.prop}}
- * </div>
- * ```
- *
- * <div class="alert alert-warning">
- * **Note:** `track by` must always be the last expression:
- * </div>
- * ```
- * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
- * {{model.name}}
- * </div>
- * ```
- *
- * # Special repeat start and end points
- * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
- * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
- * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
- * up to and including the ending HTML tag where **ng-repeat-end** is placed.
- *
- * The example below makes use of this feature:
- * ```html
- * <header ng-repeat-start="item in items">
- * Header {{ item }}
- * </header>
- * <div class="body">
- * Body {{ item }}
- * </div>
- * <footer ng-repeat-end>
- * Footer {{ item }}
- * </footer>
- * ```
- *
- * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
- * ```html
- * <header>
- * Header A
- * </header>
- * <div class="body">
- * Body A
- * </div>
- * <footer>
- * Footer A
- * </footer>
- * <header>
- * Header B
- * </header>
- * <div class="body">
- * Body B
- * </div>
- * <footer>
- * Footer B
- * </footer>
- * ```
- *
- * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
- * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
- *
- * @animations
- * **.enter** - when a new item is added to the list or when an item is revealed after a filter
- *
- * **.leave** - when an item is removed from the list or when an item is filtered out
- *
- * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
- *
- * See the example below for defining CSS animations with ngRepeat.
- *
- * @element ANY
- * @scope
- * @priority 1000
- * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
- * formats are currently supported:
- *
- * * `variable in expression` – where variable is the user defined loop variable and `expression`
- * is a scope expression giving the collection to enumerate.
- *
- * For example: `album in artist.albums`.
- *
- * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
- * and `expression` is the scope expression giving the collection to enumerate.
- *
- * For example: `(name, age) in {'adam':10, 'amalie':12}`.
- *
- * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
- * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
- * is specified, ng-repeat associates elements by identity. It is an error to have
- * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
- * mapped to the same DOM element, which is not possible.)
- *
- * Note that the tracking expression must come last, after any filters, and the alias expression.
- *
- * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
- * will be associated by item identity in the array.
- *
- * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
- * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
- * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
- * element in the same way in the DOM.
- *
- * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
- * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
- * property is same.
- *
- * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
- * to items in conjunction with a tracking expression.
- *
- * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
- * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
- * when a filter is active on the repeater, but the filtered result set is empty.
- *
- * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
- * the items have been processed through the filter.
- *
- * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
- * (and not as operator, inside an expression).
- *
- * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
- *
- * @example
- * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed
- * results by name. New (entering) and removed (leaving) items are animated.
- <example module="ngRepeat" name="ngRepeat" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="repeatController">
- I have {{friends.length}} friends. They are:
- <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
- <ul class="example-animate-container">
- <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
- [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
- </li>
- <li class="animate-repeat" ng-if="results.length == 0">
- <strong>No results found...</strong>
- </li>
- </ul>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {
- $scope.friends = [
- {name:'John', age:25, gender:'boy'},
- {name:'Jessie', age:30, gender:'girl'},
- {name:'Johanna', age:28, gender:'girl'},
- {name:'Joy', age:15, gender:'girl'},
- {name:'Mary', age:28, gender:'girl'},
- {name:'Peter', age:95, gender:'boy'},
- {name:'Sebastian', age:50, gender:'boy'},
- {name:'Erika', age:27, gender:'girl'},
- {name:'Patrick', age:40, gender:'boy'},
- {name:'Samantha', age:60, gender:'girl'}
- ];
- });
- </file>
- <file name="animations.css">
- .example-animate-container {
- background:white;
- border:1px solid black;
- list-style:none;
- margin:0;
- padding:0 10px;
- }
-
- .animate-repeat {
- line-height:30px;
- list-style:none;
- box-sizing:border-box;
- }
-
- .animate-repeat.ng-move,
- .animate-repeat.ng-enter,
- .animate-repeat.ng-leave {
- transition:all linear 0.5s;
- }
-
- .animate-repeat.ng-leave.ng-leave-active,
- .animate-repeat.ng-move,
- .animate-repeat.ng-enter {
- opacity:0;
- max-height:0;
- }
-
- .animate-repeat.ng-leave,
- .animate-repeat.ng-move.ng-move-active,
- .animate-repeat.ng-enter.ng-enter-active {
- opacity:1;
- max-height:30px;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var friends = element.all(by.repeater('friend in friends'));
-
- it('should render initial data set', function() {
- expect(friends.count()).toBe(10);
- expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
- expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
- expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
- expect(element(by.binding('friends.length')).getText())
- .toMatch("I have 10 friends. They are:");
- });
-
- it('should update repeater when filter predicate changes', function() {
- expect(friends.count()).toBe(10);
-
- element(by.model('q')).sendKeys('ma');
-
- expect(friends.count()).toBe(2);
- expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
- expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
- });
- </file>
- </example>
- */
-var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
- var NG_REMOVED = '$$NG_REMOVED';
- var ngRepeatMinErr = minErr('ngRepeat');
-
- var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
- // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
- scope[valueIdentifier] = value;
- if (keyIdentifier) scope[keyIdentifier] = key;
- scope.$index = index;
- scope.$first = (index === 0);
- scope.$last = (index === (arrayLength - 1));
- scope.$middle = !(scope.$first || scope.$last);
- // jshint bitwise: false
- scope.$odd = !(scope.$even = (index&1) === 0);
- // jshint bitwise: true
- };
-
- var getBlockStart = function(block) {
- return block.clone[0];
- };
-
- var getBlockEnd = function(block) {
- return block.clone[block.clone.length - 1];
- };
-
-
- return {
- restrict: 'A',
- multiElement: true,
- transclude: 'element',
- priority: 1000,
- terminal: true,
- $$tlb: true,
- compile: function ngRepeatCompile($element, $attr) {
- var expression = $attr.ngRepeat;
- var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
-
- var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
-
- if (!match) {
- throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
- expression);
- }
-
- var lhs = match[1];
- var rhs = match[2];
- var aliasAs = match[3];
- var trackByExp = match[4];
-
- match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
-
- if (!match) {
- throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
- lhs);
- }
- var valueIdentifier = match[3] || match[1];
- var keyIdentifier = match[2];
-
- if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
- /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
- throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
- aliasAs);
- }
-
- var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
- var hashFnLocals = {$id: hashKey};
-
- if (trackByExp) {
- trackByExpGetter = $parse(trackByExp);
- } else {
- trackByIdArrayFn = function(key, value) {
- return hashKey(value);
- };
- trackByIdObjFn = function(key) {
- return key;
- };
- }
-
- return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
-
- if (trackByExpGetter) {
- trackByIdExpFn = function(key, value, index) {
- // assign key, value, and $index to the locals so that they can be used in hash functions
- if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
- hashFnLocals[valueIdentifier] = value;
- hashFnLocals.$index = index;
- return trackByExpGetter($scope, hashFnLocals);
- };
- }
-
- // Store a list of elements from previous run. This is a hash where key is the item from the
- // iterator, and the value is objects with following properties.
- // - scope: bound scope
- // - element: previous element.
- // - index: position
- //
- // We are using no-proto object so that we don't need to guard against inherited props via
- // hasOwnProperty.
- var lastBlockMap = createMap();
-
- //watch props
- $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
- var index, length,
- previousNode = $element[0], // node that cloned nodes should be inserted after
- // initialized to the comment node anchor
- nextNode,
- // Same as lastBlockMap but it has the current state. It will become the
- // lastBlockMap on the next iteration.
- nextBlockMap = createMap(),
- collectionLength,
- key, value, // key/value of iteration
- trackById,
- trackByIdFn,
- collectionKeys,
- block, // last object information {scope, element, id}
- nextBlockOrder,
- elementsToRemove;
-
- if (aliasAs) {
- $scope[aliasAs] = collection;
- }
-
- if (isArrayLike(collection)) {
- collectionKeys = collection;
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
- } else {
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
- // if object, extract keys, in enumeration order, unsorted
- collectionKeys = [];
- for (var itemKey in collection) {
- if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {
- collectionKeys.push(itemKey);
- }
- }
- }
-
- collectionLength = collectionKeys.length;
- nextBlockOrder = new Array(collectionLength);
-
- // locate existing items
- for (index = 0; index < collectionLength; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- trackById = trackByIdFn(key, value, index);
- if (lastBlockMap[trackById]) {
- // found previously seen block
- block = lastBlockMap[trackById];
- delete lastBlockMap[trackById];
- nextBlockMap[trackById] = block;
- nextBlockOrder[index] = block;
- } else if (nextBlockMap[trackById]) {
- // if collision detected. restore lastBlockMap and throw an error
- forEach(nextBlockOrder, function(block) {
- if (block && block.scope) lastBlockMap[block.id] = block;
- });
- throw ngRepeatMinErr('dupes',
- "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
- expression, trackById, value);
- } else {
- // new never before seen block
- nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
- nextBlockMap[trackById] = true;
- }
- }
-
- // remove leftover items
- for (var blockKey in lastBlockMap) {
- block = lastBlockMap[blockKey];
- elementsToRemove = getBlockNodes(block.clone);
- $animate.leave(elementsToRemove);
- if (elementsToRemove[0].parentNode) {
- // if the element was not removed yet because of pending animation, mark it as deleted
- // so that we can ignore it later
- for (index = 0, length = elementsToRemove.length; index < length; index++) {
- elementsToRemove[index][NG_REMOVED] = true;
- }
- }
- block.scope.$destroy();
- }
-
- // we are not using forEach for perf reasons (trying to avoid #call)
- for (index = 0; index < collectionLength; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- block = nextBlockOrder[index];
-
- if (block.scope) {
- // if we have already seen this object, then we need to reuse the
- // associated scope/element
-
- nextNode = previousNode;
-
- // skip nodes that are already pending removal via leave animation
- do {
- nextNode = nextNode.nextSibling;
- } while (nextNode && nextNode[NG_REMOVED]);
-
- if (getBlockStart(block) != nextNode) {
- // existing item which got moved
- $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
- }
- previousNode = getBlockEnd(block);
- updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
- } else {
- // new item which we don't know about
- $transclude(function ngRepeatTransclude(clone, scope) {
- block.scope = scope;
- // http://jsperf.com/clone-vs-createcomment
- var endNode = ngRepeatEndComment.cloneNode(false);
- clone[clone.length++] = endNode;
-
- // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
- $animate.enter(clone, null, jqLite(previousNode));
- previousNode = endNode;
- // Note: We only need the first/last node of the cloned nodes.
- // However, we need to keep the reference to the jqlite wrapper as it might be changed later
- // by a directive with templateUrl when its template arrives.
- block.clone = clone;
- nextBlockMap[block.id] = block;
- updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
- });
- }
- }
- lastBlockMap = nextBlockMap;
- });
- };
- }
- };
-}];
-
-var NG_HIDE_CLASS = 'ng-hide';
-var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
-/**
- * @ngdoc directive
- * @name ngShow
- * @multiElement
- *
- * @description
- * The `ngShow` directive shows or hides the given HTML element based on the expression
- * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
- * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```html
- * <!-- when $scope.myValue is truthy (element is visible) -->
- * <div ng-show="myValue"></div>
- *
- * <!-- when $scope.myValue is falsy (element is hidden) -->
- * <div ng-show="myValue" class="ng-hide"></div>
- * ```
- *
- * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
- * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding `.ng-hide`
- *
- * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
- * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
- * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
- * with extra animation classes that can be added.
- *
- * ```css
- * .ng-hide:not(.ng-hide-animate) {
- * /&#42; this is just another form of hiding an element &#42;/
- * display: block!important;
- * position: absolute;
- * top: -9999px;
- * left: -9999px;
- * }
- * ```
- *
- * By default you don't need to override in CSS anything and the animations will work around the display style.
- *
- * ## A note about animations with `ngShow`
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass except that
- * you must also include the !important flag to override the display property
- * so that you can perform an animation when the element is hidden during the time of the animation.
- *
- * ```css
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- * /&#42; this is required as of 1.3x to properly
- * apply all styling in a show/hide animation &#42;/
- * transition: 0s linear all;
- * }
- *
- * .my-element.ng-hide-add-active,
- * .my-element.ng-hide-remove-active {
- * /&#42; the transition is defined in the active class &#42;/
- * transition: 1s linear all;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * ```
- *
- * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
- * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
- *
- * @animations
- * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
- * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
- *
- * @element ANY
- * @param {expression} ngShow If the {@link guide/expression expression} is truthy
- * then the element is shown or hidden respectively.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/>
- <div>
- Show:
- <div class="check-element animate-show" ng-show="checked">
- <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
- </div>
- </div>
- <div>
- Hide:
- <div class="check-element animate-show" ng-hide="checked">
- <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
- </div>
- </div>
- </file>
- <file name="glyphicons.css">
- @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
- </file>
- <file name="animations.css">
- .animate-show {
- line-height: 20px;
- opacity: 1;
- padding: 10px;
- border: 1px solid black;
- background: white;
- }
-
- .animate-show.ng-hide-add, .animate-show.ng-hide-remove {
- transition: all linear 0.5s;
- }
-
- .animate-show.ng-hide {
- line-height: 0;
- opacity: 0;
- padding: 0 10px;
- }
-
- .check-element {
- padding: 10px;
- border: 1px solid black;
- background: white;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
- var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
-
- it('should check ng-show / ng-hide', function() {
- expect(thumbsUp.isDisplayed()).toBeFalsy();
- expect(thumbsDown.isDisplayed()).toBeTruthy();
-
- element(by.model('checked')).click();
-
- expect(thumbsUp.isDisplayed()).toBeTruthy();
- expect(thumbsDown.isDisplayed()).toBeFalsy();
- });
- </file>
- </example>
- */
-var ngShowDirective = ['$animate', function($animate) {
- return {
- restrict: 'A',
- multiElement: true,
- link: function(scope, element, attr) {
- scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
- // we're adding a temporary, animation-specific class for ng-hide since this way
- // we can control when the element is actually displayed on screen without having
- // to have a global/greedy CSS selector that breaks when other animations are run.
- // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
- $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
- tempClasses: NG_HIDE_IN_PROGRESS_CLASS
- });
- });
- }
- };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngHide
- * @multiElement
- *
- * @description
- * The `ngHide` directive shows or hides the given HTML element based on the expression
- * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
- * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```html
- * <!-- when $scope.myValue is truthy (element is hidden) -->
- * <div ng-hide="myValue" class="ng-hide"></div>
- *
- * <!-- when $scope.myValue is falsy (element is visible) -->
- * <div ng-hide="myValue"></div>
- * ```
- *
- * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
- * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding `.ng-hide`
- *
- * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
- * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
- * class in CSS:
- *
- * ```css
- * .ng-hide {
- * /&#42; this is just another form of hiding an element &#42;/
- * display: block!important;
- * position: absolute;
- * top: -9999px;
- * left: -9999px;
- * }
- * ```
- *
- * By default you don't need to override in CSS anything and the animations will work around the display style.
- *
- * ## A note about animations with `ngHide`
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
- * CSS class is added and removed for you instead of your own CSS class.
- *
- * ```css
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- * transition: 0.5s linear all;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * ```
- *
- * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
- * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
- *
- * @animations
- * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
- * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
- *
- * @element ANY
- * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
- * the element is shown or hidden respectively.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/>
- <div>
- Show:
- <div class="check-element animate-hide" ng-show="checked">
- <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
- </div>
- </div>
- <div>
- Hide:
- <div class="check-element animate-hide" ng-hide="checked">
- <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
- </div>
- </div>
- </file>
- <file name="glyphicons.css">
- @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
- </file>
- <file name="animations.css">
- .animate-hide {
- transition: all linear 0.5s;
- line-height: 20px;
- opacity: 1;
- padding: 10px;
- border: 1px solid black;
- background: white;
- }
-
- .animate-hide.ng-hide {
- line-height: 0;
- opacity: 0;
- padding: 0 10px;
- }
-
- .check-element {
- padding: 10px;
- border: 1px solid black;
- background: white;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
- var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
-
- it('should check ng-show / ng-hide', function() {
- expect(thumbsUp.isDisplayed()).toBeFalsy();
- expect(thumbsDown.isDisplayed()).toBeTruthy();
-
- element(by.model('checked')).click();
-
- expect(thumbsUp.isDisplayed()).toBeTruthy();
- expect(thumbsDown.isDisplayed()).toBeFalsy();
- });
- </file>
- </example>
- */
-var ngHideDirective = ['$animate', function($animate) {
- return {
- restrict: 'A',
- multiElement: true,
- link: function(scope, element, attr) {
- scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
- // The comment inside of the ngShowDirective explains why we add and
- // remove a temporary class for the show/hide animation
- $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
- tempClasses: NG_HIDE_IN_PROGRESS_CLASS
- });
- });
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngStyle
- * @restrict AC
- *
- * @description
- * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
- *
- * @element ANY
- * @param {expression} ngStyle
- *
- * {@link guide/expression Expression} which evals to an
- * object whose keys are CSS style names and values are corresponding values for those CSS
- * keys.
- *
- * Since some CSS style names are not valid keys for an object, they must be quoted.
- * See the 'background-color' style in the example below.
- *
- * @example
- <example>
- <file name="index.html">
- <input type="button" value="set color" ng-click="myStyle={color:'red'}">
- <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
- <input type="button" value="clear" ng-click="myStyle={}">
- <br/>
- <span ng-style="myStyle">Sample Text</span>
- <pre>myStyle={{myStyle}}</pre>
- </file>
- <file name="style.css">
- span {
- color: black;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var colorSpan = element(by.css('span'));
-
- it('should check ng-style', function() {
- expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
- element(by.css('input[value=\'set color\']')).click();
- expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
- element(by.css('input[value=clear]')).click();
- expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
- });
- </file>
- </example>
- */
-var ngStyleDirective = ngDirective(function(scope, element, attr) {
- scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
- if (oldStyles && (newStyles !== oldStyles)) {
- forEach(oldStyles, function(val, style) { element.css(style, '');});
- }
- if (newStyles) element.css(newStyles);
- }, true);
-});
-
-/**
- * @ngdoc directive
- * @name ngSwitch
- * @restrict EA
- *
- * @description
- * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
- * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
- * as specified in the template.
- *
- * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
- * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
- * matches the value obtained from the evaluated expression. In other words, you define a container element
- * (where you place the directive), place an expression on the **`on="..."` attribute**
- * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
- * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
- * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
- * attribute is displayed.
- *
- * <div class="alert alert-info">
- * Be aware that the attribute values to match against cannot be expressions. They are interpreted
- * as literal string values to match against.
- * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
- * value of the expression `$scope.someVal`.
- * </div>
-
- * @animations
- * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
- * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
- *
- * @usage
- *
- * ```
- * <ANY ng-switch="expression">
- * <ANY ng-switch-when="matchValue1">...</ANY>
- * <ANY ng-switch-when="matchValue2">...</ANY>
- * <ANY ng-switch-default>...</ANY>
- * </ANY>
- * ```
- *
- *
- * @scope
- * @priority 1200
- * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
- * On child elements add:
- *
- * * `ngSwitchWhen`: the case statement to match against. If match then this
- * case will be displayed. If the same match appears multiple times, all the
- * elements will be displayed.
- * * `ngSwitchDefault`: the default case when no other case match. If there
- * are multiple default cases, all of them will be displayed when no other
- * case match.
- *
- *
- * @example
- <example module="switchExample" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <select ng-model="selection" ng-options="item for item in items">
- </select>
- <code>selection={{selection}}</code>
- <hr/>
- <div class="animate-switch-container"
- ng-switch on="selection">
- <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
- <div class="animate-switch" ng-switch-when="home">Home Span</div>
- <div class="animate-switch" ng-switch-default>default</div>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('switchExample', ['ngAnimate'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.items = ['settings', 'home', 'other'];
- $scope.selection = $scope.items[0];
- }]);
- </file>
- <file name="animations.css">
- .animate-switch-container {
- position:relative;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .animate-switch {
- padding:10px;
- }
-
- .animate-switch.ng-animate {
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- }
-
- .animate-switch.ng-leave.ng-leave-active,
- .animate-switch.ng-enter {
- top:-50px;
- }
- .animate-switch.ng-leave,
- .animate-switch.ng-enter.ng-enter-active {
- top:0;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var switchElem = element(by.css('[ng-switch]'));
- var select = element(by.model('selection'));
-
- it('should start in settings', function() {
- expect(switchElem.getText()).toMatch(/Settings Div/);
- });
- it('should change to home', function() {
- select.all(by.css('option')).get(1).click();
- expect(switchElem.getText()).toMatch(/Home Span/);
- });
- it('should select default', function() {
- select.all(by.css('option')).get(2).click();
- expect(switchElem.getText()).toMatch(/default/);
- });
- </file>
- </example>
- */
-var ngSwitchDirective = ['$animate', function($animate) {
- return {
- require: 'ngSwitch',
-
- // asks for $scope to fool the BC controller module
- controller: ['$scope', function ngSwitchController() {
- this.cases = {};
- }],
- link: function(scope, element, attr, ngSwitchController) {
- var watchExpr = attr.ngSwitch || attr.on,
- selectedTranscludes = [],
- selectedElements = [],
- previousLeaveAnimations = [],
- selectedScopes = [];
-
- var spliceFactory = function(array, index) {
- return function() { array.splice(index, 1); };
- };
-
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
- var i, ii;
- for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
- $animate.cancel(previousLeaveAnimations[i]);
- }
- previousLeaveAnimations.length = 0;
-
- for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
- var selected = getBlockNodes(selectedElements[i].clone);
- selectedScopes[i].$destroy();
- var promise = previousLeaveAnimations[i] = $animate.leave(selected);
- promise.then(spliceFactory(previousLeaveAnimations, i));
- }
-
- selectedElements.length = 0;
- selectedScopes.length = 0;
-
- if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
- forEach(selectedTranscludes, function(selectedTransclude) {
- selectedTransclude.transclude(function(caseElement, selectedScope) {
- selectedScopes.push(selectedScope);
- var anchor = selectedTransclude.element;
- caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
- var block = { clone: caseElement };
-
- selectedElements.push(block);
- $animate.enter(caseElement, anchor.parent(), anchor);
- });
- });
- }
- });
- }
- };
-}];
-
-var ngSwitchWhenDirective = ngDirective({
- transclude: 'element',
- priority: 1200,
- require: '^ngSwitch',
- multiElement: true,
- link: function(scope, element, attrs, ctrl, $transclude) {
- ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
- ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
- }
-});
-
-var ngSwitchDefaultDirective = ngDirective({
- transclude: 'element',
- priority: 1200,
- require: '^ngSwitch',
- multiElement: true,
- link: function(scope, element, attr, ctrl, $transclude) {
- ctrl.cases['?'] = (ctrl.cases['?'] || []);
- ctrl.cases['?'].push({ transclude: $transclude, element: element });
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngTransclude
- * @restrict EAC
- *
- * @description
- * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
- *
- * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name
- * as the value of the `ng-transclude` or `ng-transclude-slot` attribute.
- *
- * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing
- * content of this element will be removed before the transcluded content is inserted.
- * If the transcluded content is empty, the existing content is left intact. This lets you provide fallback content in the case
- * that no transcluded content is provided.
- *
- * @element ANY
- *
- * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty
- * or its value is the same as the name of the attribute then the default slot is used.
- *
- * @example
- * ### Basic transclusion
- * This example demonstrates basic transclusion of content into a component directive.
- * <example name="simpleTranscludeExample" module="transcludeExample">
- * <file name="index.html">
- * <script>
- * angular.module('transcludeExample', [])
- * .directive('pane', function(){
- * return {
- * restrict: 'E',
- * transclude: true,
- * scope: { title:'@' },
- * template: '<div style="border: 1px solid black;">' +
- * '<div style="background-color: gray">{{title}}</div>' +
- * '<ng-transclude></ng-transclude>' +
- * '</div>'
- * };
- * })
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.title = 'Lorem Ipsum';
- * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <input ng-model="title" aria-label="title"> <br/>
- * <textarea ng-model="text" aria-label="text"></textarea> <br/>
- * <pane title="{{title}}">{{text}}</pane>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have transcluded', function() {
- * var titleElement = element(by.model('title'));
- * titleElement.clear();
- * titleElement.sendKeys('TITLE');
- * var textElement = element(by.model('text'));
- * textElement.clear();
- * textElement.sendKeys('TEXT');
- * expect(element(by.binding('title')).getText()).toEqual('TITLE');
- * expect(element(by.binding('text')).getText()).toEqual('TEXT');
- * });
- * </file>
- * </example>
- *
- * @example
- * ### Transclude fallback content
- * This example shows how to use `NgTransclude` with fallback content, that
- * is displayed if no transcluded content is provided.
- *
- * <example module="transcludeFallbackContentExample">
- * <file name="index.html">
- * <script>
- * angular.module('transcludeFallbackContentExample', [])
- * .directive('myButton', function(){
- * return {
- * restrict: 'E',
- * transclude: true,
- * scope: true,
- * template: '<button style="cursor: pointer;">' +
- * '<ng-transclude>' +
- * '<b style="color: red;">Button1</b>' +
- * '</ng-transclude>' +
- * '</button>'
- * };
- * });
- * </script>
- * <!-- fallback button content -->
- * <my-button id="fallback"></my-button>
- * <!-- modified button content -->
- * <my-button id="modified">
- * <i style="color: green;">Button2</i>
- * </my-button>
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have different transclude element content', function() {
- * expect(element(by.id('fallback')).getText()).toBe('Button1');
- * expect(element(by.id('modified')).getText()).toBe('Button2');
- * });
- * </file>
- * </example>
- *
- * @example
- * ### Multi-slot transclusion
- * This example demonstrates using multi-slot transclusion in a component directive.
- * <example name="multiSlotTranscludeExample" module="multiSlotTranscludeExample">
- * <file name="index.html">
- * <style>
- * .title, .footer {
- * background-color: gray
- * }
- * </style>
- * <div ng-controller="ExampleController">
- * <input ng-model="title" aria-label="title"> <br/>
- * <textarea ng-model="text" aria-label="text"></textarea> <br/>
- * <pane>
- * <pane-title><a ng-href="{{link}}">{{title}}</a></pane-title>
- * <pane-body><p>{{text}}</p></pane-body>
- * </pane>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('multiSlotTranscludeExample', [])
- * .directive('pane', function(){
- * return {
- * restrict: 'E',
- * transclude: {
- * 'title': '?paneTitle',
- * 'body': 'paneBody',
- * 'footer': '?paneFooter'
- * },
- * template: '<div style="border: 1px solid black;">' +
- * '<div class="title" ng-transclude="title">Fallback Title</div>' +
- * '<div ng-transclude="body"></div>' +
- * '<div class="footer" ng-transclude="footer">Fallback Footer</div>' +
- * '</div>'
- * };
- * })
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.title = 'Lorem Ipsum';
- * $scope.link = "https://google.com";
- * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- * }]);
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should have transcluded the title and the body', function() {
- * var titleElement = element(by.model('title'));
- * titleElement.clear();
- * titleElement.sendKeys('TITLE');
- * var textElement = element(by.model('text'));
- * textElement.clear();
- * textElement.sendKeys('TEXT');
- * expect(element(by.css('.title')).getText()).toEqual('TITLE');
- * expect(element(by.binding('text')).getText()).toEqual('TEXT');
- * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer');
- * });
- * </file>
- * </example>
- */
-var ngTranscludeMinErr = minErr('ngTransclude');
-var ngTranscludeDirective = ngDirective({
- restrict: 'EAC',
- link: function($scope, $element, $attrs, controller, $transclude) {
-
- if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {
- // If the attribute is of the form: `ng-transclude="ng-transclude"`
- // then treat it like the default
- $attrs.ngTransclude = '';
- }
-
- function ngTranscludeCloneAttachFn(clone) {
- if (clone.length) {
- $element.empty();
- $element.append(clone);
- }
- }
-
- if (!$transclude) {
- throw ngTranscludeMinErr('orphan',
- 'Illegal use of ngTransclude directive in the template! ' +
- 'No parent directive that requires a transclusion found. ' +
- 'Element: {0}',
- startingTag($element));
- }
-
- // If there is no slot name defined or the slot name is not optional
- // then transclude the slot
- var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;
- $transclude(ngTranscludeCloneAttachFn, null, slotName);
- }
-});
-
-/**
- * @ngdoc directive
- * @name script
- * @restrict E
- *
- * @description
- * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
- * template can be used by {@link ng.directive:ngInclude `ngInclude`},
- * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
- * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
- * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
- *
- * @param {string} type Must be set to `'text/ng-template'`.
- * @param {string} id Cache name of the template.
- *
- * @example
- <example>
- <file name="index.html">
- <script type="text/ng-template" id="/tpl.html">
- Content of the template.
- </script>
-
- <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
- <div id="tpl-content" ng-include src="currentTpl"></div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should load template defined inside script tag', function() {
- element(by.css('#tpl-link')).click();
- expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
- });
- </file>
- </example>
- */
-var scriptDirective = ['$templateCache', function($templateCache) {
- return {
- restrict: 'E',
- terminal: true,
- compile: function(element, attr) {
- if (attr.type == 'text/ng-template') {
- var templateUrl = attr.id,
- text = element[0].text;
-
- $templateCache.put(templateUrl, text);
- }
- }
- };
-}];
-
-var noopNgModelController = { $setViewValue: noop, $render: noop };
-
-function chromeHack(optionElement) {
- // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
- // Adding an <option selected="selected"> element to a <select required="required"> should
- // automatically select the new element
- if (optionElement[0].hasAttribute('selected')) {
- optionElement[0].selected = true;
- }
-}
-
-/**
- * @ngdoc type
- * @name select.SelectController
- * @description
- * The controller for the `<select>` directive. This provides support for reading
- * and writing the selected value(s) of the control and also coordinates dynamically
- * added `<option>` elements, perhaps by an `ngRepeat` directive.
- */
-var SelectController =
- ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
-
- var self = this,
- optionsMap = new HashMap();
-
- // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
- self.ngModelCtrl = noopNgModelController;
-
- // The "unknown" option is one that is prepended to the list if the viewValue
- // does not match any of the options. When it is rendered the value of the unknown
- // option is '? XXX ?' where XXX is the hashKey of the value that is not known.
- //
- // We can't just jqLite('<option>') since jqLite is not smart enough
- // to create it in <select> and IE barfs otherwise.
- self.unknownOption = jqLite(document.createElement('option'));
- self.renderUnknownOption = function(val) {
- var unknownVal = '? ' + hashKey(val) + ' ?';
- self.unknownOption.val(unknownVal);
- $element.prepend(self.unknownOption);
- $element.val(unknownVal);
- };
-
- $scope.$on('$destroy', function() {
- // disable unknown option so that we don't do work when the whole select is being destroyed
- self.renderUnknownOption = noop;
- });
-
- self.removeUnknownOption = function() {
- if (self.unknownOption.parent()) self.unknownOption.remove();
- };
-
-
- // Read the value of the select control, the implementation of this changes depending
- // upon whether the select can have multiple values and whether ngOptions is at work.
- self.readValue = function readSingleValue() {
- self.removeUnknownOption();
- return $element.val();
- };
-
-
- // Write the value to the select control, the implementation of this changes depending
- // upon whether the select can have multiple values and whether ngOptions is at work.
- self.writeValue = function writeSingleValue(value) {
- if (self.hasOption(value)) {
- self.removeUnknownOption();
- $element.val(value);
- if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy
- } else {
- if (value == null && self.emptyOption) {
- self.removeUnknownOption();
- $element.val('');
- } else {
- self.renderUnknownOption(value);
- }
- }
- };
-
-
- // Tell the select control that an option, with the given value, has been added
- self.addOption = function(value, element) {
- // Skip comment nodes, as they only pollute the `optionsMap`
- if (element[0].nodeType === NODE_TYPE_COMMENT) return;
-
- assertNotHasOwnProperty(value, '"option value"');
- if (value === '') {
- self.emptyOption = element;
- }
- var count = optionsMap.get(value) || 0;
- optionsMap.put(value, count + 1);
- self.ngModelCtrl.$render();
- chromeHack(element);
- };
-
- // Tell the select control that an option, with the given value, has been removed
- self.removeOption = function(value) {
- var count = optionsMap.get(value);
- if (count) {
- if (count === 1) {
- optionsMap.remove(value);
- if (value === '') {
- self.emptyOption = undefined;
- }
- } else {
- optionsMap.put(value, count - 1);
- }
- }
- };
-
- // Check whether the select control has an option matching the given value
- self.hasOption = function(value) {
- return !!optionsMap.get(value);
- };
-
-
- self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
-
- if (interpolateValueFn) {
- // The value attribute is interpolated
- var oldVal;
- optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {
- if (isDefined(oldVal)) {
- self.removeOption(oldVal);
- }
- oldVal = newVal;
- self.addOption(newVal, optionElement);
- });
- } else if (interpolateTextFn) {
- // The text content is interpolated
- optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {
- optionAttrs.$set('value', newVal);
- if (oldVal !== newVal) {
- self.removeOption(oldVal);
- }
- self.addOption(newVal, optionElement);
- });
- } else {
- // The value attribute is static
- self.addOption(optionAttrs.value, optionElement);
- }
-
- optionElement.on('$destroy', function() {
- self.removeOption(optionAttrs.value);
- self.ngModelCtrl.$render();
- });
- };
-}];
-
-/**
- * @ngdoc directive
- * @name select
- * @restrict E
- *
- * @description
- * HTML `SELECT` element with angular data-binding.
- *
- * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding
- * between the scope and the `<select>` control (including setting default values).
- * It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or
- * {@link ngOptions `ngOptions`} directives.
- *
- * When an item in the `<select>` menu is selected, the value of the selected option will be bound
- * to the model identified by the `ngModel` directive. With static or repeated options, this is
- * the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.
- * If you want dynamic value attributes, you can use interpolation inside the value attribute.
- *
- * <div class="alert alert-warning">
- * Note that the value of a `select` directive used without `ngOptions` is always a string.
- * When the model needs to be bound to a non-string value, you must either explicitly convert it
- * using a directive (see example below) or use `ngOptions` to specify the set of options.
- * This is because an option element can only be bound to string values at present.
- * </div>
- *
- * If the viewValue of `ngModel` does not match any of the options, then the control
- * will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
- *
- * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
- * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
- * option. See example below for demonstration.
- *
- * <div class="alert alert-info">
- * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
- * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits, such as
- * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
- * comprehension expression, and additionally in reducing memory and increasing speed by not creating
- * a new scope for each repeated instance.
- * </div>
- *
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} multiple Allows multiple options to be selected. The selected values will be
- * bound to the model as an array.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds required attribute and required validation constraint to
- * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required
- * when you want to data-bind to the required attribute.
- * @param {string=} ngChange Angular expression to be executed when selected option(s) changes due to user
- * interaction with the select element.
- * @param {string=} ngOptions sets the options that the select is populated with and defines what is
- * set on the model on selection. See {@link ngOptions `ngOptions`}.
- *
- * @example
- * ### Simple `select` elements with static options
- *
- * <example name="static-select" module="staticSelect">
- * <file name="index.html">
- * <div ng-controller="ExampleController">
- * <form name="myForm">
- * <label for="singleSelect"> Single select: </label><br>
- * <select name="singleSelect" ng-model="data.singleSelect">
- * <option value="option-1">Option 1</option>
- * <option value="option-2">Option 2</option>
- * </select><br>
- *
- * <label for="singleSelect"> Single select with "not selected" option and dynamic option values: </label><br>
- * <select name="singleSelect" id="singleSelect" ng-model="data.singleSelect">
- * <option value="">---Please select---</option> <!-- not selected / blank option -->
- * <option value="{{data.option1}}">Option 1</option> <!-- interpolation -->
- * <option value="option-2">Option 2</option>
- * </select><br>
- * <button ng-click="forceUnknownOption()">Force unknown option</button><br>
- * <tt>singleSelect = {{data.singleSelect}}</tt>
- *
- * <hr>
- * <label for="multipleSelect"> Multiple select: </label><br>
- * <select name="multipleSelect" id="multipleSelect" ng-model="data.multipleSelect" multiple>
- * <option value="option-1">Option 1</option>
- * <option value="option-2">Option 2</option>
- * <option value="option-3">Option 3</option>
- * </select><br>
- * <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>
- * </form>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('staticSelect', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.data = {
- * singleSelect: null,
- * multipleSelect: [],
- * option1: 'option-1',
- * };
- *
- * $scope.forceUnknownOption = function() {
- * $scope.data.singleSelect = 'nonsense';
- * };
- * }]);
- * </file>
- *</example>
- *
- * ### Using `ngRepeat` to generate `select` options
- * <example name="ngrepeat-select" module="ngrepeatSelect">
- * <file name="index.html">
- * <div ng-controller="ExampleController">
- * <form name="myForm">
- * <label for="repeatSelect"> Repeat select: </label>
- * <select name="repeatSelect" id="repeatSelect" ng-model="data.repeatSelect">
- * <option ng-repeat="option in data.availableOptions" value="{{option.id}}">{{option.name}}</option>
- * </select>
- * </form>
- * <hr>
- * <tt>repeatSelect = {{data.repeatSelect}}</tt><br/>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('ngrepeatSelect', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.data = {
- * repeatSelect: null,
- * availableOptions: [
- * {id: '1', name: 'Option A'},
- * {id: '2', name: 'Option B'},
- * {id: '3', name: 'Option C'}
- * ],
- * };
- * }]);
- * </file>
- *</example>
- *
- *
- * ### Using `select` with `ngOptions` and setting a default value
- * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.
- *
- * <example name="select-with-default-values" module="defaultValueSelect">
- * <file name="index.html">
- * <div ng-controller="ExampleController">
- * <form name="myForm">
- * <label for="mySelect">Make a choice:</label>
- * <select name="mySelect" id="mySelect"
- * ng-options="option.name for option in data.availableOptions track by option.id"
- * ng-model="data.selectedOption"></select>
- * </form>
- * <hr>
- * <tt>option = {{data.selectedOption}}</tt><br/>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('defaultValueSelect', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.data = {
- * availableOptions: [
- * {id: '1', name: 'Option A'},
- * {id: '2', name: 'Option B'},
- * {id: '3', name: 'Option C'}
- * ],
- * selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui
- * };
- * }]);
- * </file>
- *</example>
- *
- *
- * ### Binding `select` to a non-string value via `ngModel` parsing / formatting
- *
- * <example name="select-with-non-string-options" module="nonStringSelect">
- * <file name="index.html">
- * <select ng-model="model.id" convert-to-number>
- * <option value="0">Zero</option>
- * <option value="1">One</option>
- * <option value="2">Two</option>
- * </select>
- * {{ model }}
- * </file>
- * <file name="app.js">
- * angular.module('nonStringSelect', [])
- * .run(function($rootScope) {
- * $rootScope.model = { id: 2 };
- * })
- * .directive('convertToNumber', function() {
- * return {
- * require: 'ngModel',
- * link: function(scope, element, attrs, ngModel) {
- * ngModel.$parsers.push(function(val) {
- * return parseInt(val, 10);
- * });
- * ngModel.$formatters.push(function(val) {
- * return '' + val;
- * });
- * }
- * };
- * });
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should initialize to model', function() {
- * var select = element(by.css('select'));
- * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');
- * });
- * </file>
- * </example>
- *
- */
-var selectDirective = function() {
-
- return {
- restrict: 'E',
- require: ['select', '?ngModel'],
- controller: SelectController,
- priority: 1,
- link: {
- pre: selectPreLink,
- post: selectPostLink
- }
- };
-
- function selectPreLink(scope, element, attr, ctrls) {
-
- // if ngModel is not defined, we don't need to do anything
- var ngModelCtrl = ctrls[1];
- if (!ngModelCtrl) return;
-
- var selectCtrl = ctrls[0];
-
- selectCtrl.ngModelCtrl = ngModelCtrl;
-
- // When the selected item(s) changes we delegate getting the value of the select control
- // to the `readValue` method, which can be changed if the select can have multiple
- // selected values or if the options are being generated by `ngOptions`
- element.on('change', function() {
- scope.$apply(function() {
- ngModelCtrl.$setViewValue(selectCtrl.readValue());
- });
- });
-
- // If the select allows multiple values then we need to modify how we read and write
- // values from and to the control; also what it means for the value to be empty and
- // we have to add an extra watch since ngModel doesn't work well with arrays - it
- // doesn't trigger rendering if only an item in the array changes.
- if (attr.multiple) {
-
- // Read value now needs to check each option to see if it is selected
- selectCtrl.readValue = function readMultipleValue() {
- var array = [];
- forEach(element.find('option'), function(option) {
- if (option.selected) {
- array.push(option.value);
- }
- });
- return array;
- };
-
- // Write value now needs to set the selected property of each matching option
- selectCtrl.writeValue = function writeMultipleValue(value) {
- var items = new HashMap(value);
- forEach(element.find('option'), function(option) {
- option.selected = isDefined(items.get(option.value));
- });
- };
-
- // we have to do it on each watch since ngModel watches reference, but
- // we need to work of an array, so we need to see if anything was inserted/removed
- var lastView, lastViewRef = NaN;
- scope.$watch(function selectMultipleWatch() {
- if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {
- lastView = shallowCopy(ngModelCtrl.$viewValue);
- ngModelCtrl.$render();
- }
- lastViewRef = ngModelCtrl.$viewValue;
- });
-
- // If we are a multiple select then value is now a collection
- // so the meaning of $isEmpty changes
- ngModelCtrl.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
-
- }
- }
-
- function selectPostLink(scope, element, attrs, ctrls) {
- // if ngModel is not defined, we don't need to do anything
- var ngModelCtrl = ctrls[1];
- if (!ngModelCtrl) return;
-
- var selectCtrl = ctrls[0];
-
- // We delegate rendering to the `writeValue` method, which can be changed
- // if the select can have multiple selected values or if the options are being
- // generated by `ngOptions`.
- // This must be done in the postLink fn to prevent $render to be called before
- // all nodes have been linked correctly.
- ngModelCtrl.$render = function() {
- selectCtrl.writeValue(ngModelCtrl.$viewValue);
- };
- }
-};
-
-
-// The option directive is purely designed to communicate the existence (or lack of)
-// of dynamically created (and destroyed) option elements to their containing select
-// directive via its controller.
-var optionDirective = ['$interpolate', function($interpolate) {
- return {
- restrict: 'E',
- priority: 100,
- compile: function(element, attr) {
- if (isDefined(attr.value)) {
- // If the value attribute is defined, check if it contains an interpolation
- var interpolateValueFn = $interpolate(attr.value, true);
- } else {
- // If the value attribute is not defined then we fall back to the
- // text content of the option element, which may be interpolated
- var interpolateTextFn = $interpolate(element.text(), true);
- if (!interpolateTextFn) {
- attr.$set('value', element.text());
- }
- }
-
- return function(scope, element, attr) {
- // This is an optimization over using ^^ since we don't want to have to search
- // all the way to the root of the DOM for every single option element
- var selectCtrlName = '$selectController',
- parent = element.parent(),
- selectCtrl = parent.data(selectCtrlName) ||
- parent.parent().data(selectCtrlName); // in case we are in optgroup
-
- if (selectCtrl) {
- selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);
- }
- };
- }
- };
-}];
-
-var styleDirective = valueFn({
- restrict: 'E',
- terminal: false
-});
-
-/**
- * @ngdoc directive
- * @name ngRequired
- *
- * @description
- *
- * ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be
- * applied to custom controls.
- *
- * The directive sets the `required` attribute on the element if the Angular expression inside
- * `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we
- * cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}
- * for more info.
- *
- * The validator will set the `required` error key to true if the `required` attribute is set and
- * calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the
- * {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the
- * `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing
- * custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.
- *
- * @example
- * <example name="ngRequiredDirective" module="ngRequiredExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngRequiredExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.required = true;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="required">Toggle required: </label>
- * <input type="checkbox" ng-model="required" id="required" />
- * <br>
- * <label for="input">This input must be filled if `required` is true: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-required="required" /><br>
- * <hr>
- * required error set? = <code>{{form.input.$error.required}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var required = element(by.binding('form.input.$error.required'));
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should set the required error', function() {
- expect(required.getText()).toContain('true');
-
- input.sendKeys('123');
- expect(required.getText()).not.toContain('true');
- expect(model.getText()).toContain('123');
- });
- * </file>
- * </example>
- */
-var requiredDirective = function() {
- return {
- restrict: 'A',
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
- attr.required = true; // force truthy in case we are on non input element
-
- ctrl.$validators.required = function(modelValue, viewValue) {
- return !attr.required || !ctrl.$isEmpty(viewValue);
- };
-
- attr.$observe('required', function() {
- ctrl.$validate();
- });
- }
- };
-};
-
-/**
- * @ngdoc directive
- * @name ngPattern
- *
- * @description
- *
- * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * does not match a RegExp which is obtained by evaluating the Angular expression given in the
- * `ngPattern` attribute value:
- * * If the expression evaluates to a RegExp object, then this is used directly.
- * * If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it
- * in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
- *
- * <div class="alert alert-info">
- * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
- * start at the index of the last search's match, thus not taking the whole input value into
- * account.
- * </div>
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `pattern` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is
- * not available.
- * </li>
- * <li>
- * The `ngPattern` attribute must be an expression, while the `pattern` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngPatternDirective" module="ngPatternExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngPatternExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.regex = '\\d+';
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="regex">Set a pattern (regex string): </label>
- * <input type="text" ng-model="regex" id="regex" />
- * <br>
- * <label for="input">This input is restricted by the current pattern: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-pattern="regex" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default pattern', function() {
- input.sendKeys('aaa');
- expect(model.getText()).not.toContain('aaa');
-
- input.clear().then(function() {
- input.sendKeys('123');
- expect(model.getText()).toContain('123');
- });
- });
- * </file>
- * </example>
- */
-var patternDirective = function() {
- return {
- restrict: 'A',
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
-
- var regexp, patternExp = attr.ngPattern || attr.pattern;
- attr.$observe('pattern', function(regex) {
- if (isString(regex) && regex.length > 0) {
- regex = new RegExp('^' + regex + '$');
- }
-
- if (regex && !regex.test) {
- throw minErr('ngPattern')('noregexp',
- 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
- regex, startingTag(elm));
- }
-
- regexp = regex || undefined;
- ctrl.$validate();
- });
-
- ctrl.$validators.pattern = function(modelValue, viewValue) {
- // HTML5 pattern constraint validates the input value, so we validate the viewValue
- return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
- };
- }
- };
-};
-
-/**
- * @ngdoc directive
- * @name ngMaxlength
- *
- * @description
- *
- * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * is longer than the integer obtained by evaluating the Angular expression given in the
- * `ngMaxlength` attribute value.
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint
- * validation is not available.
- * </li>
- * <li>
- * The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngMaxlengthDirective" module="ngMaxlengthExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngMaxlengthExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.maxlength = 5;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="maxlength">Set a maxlength: </label>
- * <input type="number" ng-model="maxlength" id="maxlength" />
- * <br>
- * <label for="input">This input is restricted by the current maxlength: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-maxlength="maxlength" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default maxlength', function() {
- input.sendKeys('abcdef');
- expect(model.getText()).not.toContain('abcdef');
-
- input.clear().then(function() {
- input.sendKeys('abcde');
- expect(model.getText()).toContain('abcde');
- });
- });
- * </file>
- * </example>
- */
-var maxlengthDirective = function() {
- return {
- restrict: 'A',
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
-
- var maxlength = -1;
- attr.$observe('maxlength', function(value) {
- var intVal = toInt(value);
- maxlength = isNaN(intVal) ? -1 : intVal;
- ctrl.$validate();
- });
- ctrl.$validators.maxlength = function(modelValue, viewValue) {
- return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
- };
- }
- };
-};
-
-/**
- * @ngdoc directive
- * @name ngMinlength
- *
- * @description
- *
- * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
- * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.
- *
- * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
- * is shorter than the integer obtained by evaluating the Angular expression given in the
- * `ngMinlength` attribute value.
- *
- * <div class="alert alert-info">
- * **Note:** This directive is also added when the plain `minlength` attribute is used, with two
- * differences:
- * <ol>
- * <li>
- * `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint
- * validation is not available.
- * </li>
- * <li>
- * The `ngMinlength` value must be an expression, while the `minlength` value must be
- * interpolated.
- * </li>
- * </ol>
- * </div>
- *
- * @example
- * <example name="ngMinlengthDirective" module="ngMinlengthExample">
- * <file name="index.html">
- * <script>
- * angular.module('ngMinlengthExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.minlength = 3;
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <form name="form">
- * <label for="minlength">Set a minlength: </label>
- * <input type="number" ng-model="minlength" id="minlength" />
- * <br>
- * <label for="input">This input is restricted by the current minlength: </label>
- * <input type="text" ng-model="model" id="input" name="input" ng-minlength="minlength" /><br>
- * <hr>
- * input valid? = <code>{{form.input.$valid}}</code><br>
- * model = <code>{{model}}</code>
- * </form>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- var model = element(by.binding('model'));
- var input = element(by.id('input'));
-
- it('should validate the input with the default minlength', function() {
- input.sendKeys('ab');
- expect(model.getText()).not.toContain('ab');
-
- input.sendKeys('abc');
- expect(model.getText()).toContain('abc');
- });
- * </file>
- * </example>
- */
-var minlengthDirective = function() {
- return {
- restrict: 'A',
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
-
- var minlength = 0;
- attr.$observe('minlength', function(value) {
- minlength = toInt(value) || 0;
- ctrl.$validate();
- });
- ctrl.$validators.minlength = function(modelValue, viewValue) {
- return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
- };
- }
- };
-};
-
-if (window.angular.bootstrap) {
- //AngularJS is already loaded, so we can return here...
- console.log('WARNING: Tried to load angular more than once.');
- return;
-}
-
-//try to bind to jquery now so that one can write jqLite(document).ready()
-//but we will rebind on bootstrap again.
-bindJQuery();
-
-publishExternalAPI(angular);
-
-angular.module("ngLocale", [], ["$provide", function($provide) {
-var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
-function getDecimals(n) {
- n = n + '';
- var i = n.indexOf('.');
- return (i == -1) ? 0 : n.length - i - 1;
-}
-
-function getVF(n, opt_precision) {
- var v = opt_precision;
-
- if (undefined === v) {
- v = Math.min(getDecimals(n), 3);
- }
-
- var base = Math.pow(10, v);
- var f = ((n * base) | 0) % base;
- return {v: v, f: f};
-}
-
-$provide.value("$locale", {
- "DATETIME_FORMATS": {
- "AMPMS": [
- "AM",
- "PM"
- ],
- "DAY": [
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday"
- ],
- "ERANAMES": [
- "Before Christ",
- "Anno Domini"
- ],
- "ERAS": [
- "BC",
- "AD"
- ],
- "FIRSTDAYOFWEEK": 6,
- "MONTH": [
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- ],
- "SHORTDAY": [
- "Sun",
- "Mon",
- "Tue",
- "Wed",
- "Thu",
- "Fri",
- "Sat"
- ],
- "SHORTMONTH": [
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec"
- ],
- "STANDALONEMONTH": [
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- ],
- "WEEKENDRANGE": [
- 5,
- 6
- ],
- "fullDate": "EEEE, MMMM d, y",
- "longDate": "MMMM d, y",
- "medium": "MMM d, y h:mm:ss a",
- "mediumDate": "MMM d, y",
- "mediumTime": "h:mm:ss a",
- "short": "M/d/yy h:mm a",
- "shortDate": "M/d/yy",
- "shortTime": "h:mm a"
- },
- "NUMBER_FORMATS": {
- "CURRENCY_SYM": "$",
- "DECIMAL_SEP": ".",
- "GROUP_SEP": ",",
- "PATTERNS": [
- {
- "gSize": 3,
- "lgSize": 3,
- "maxFrac": 3,
- "minFrac": 0,
- "minInt": 1,
- "negPre": "-",
- "negSuf": "",
- "posPre": "",
- "posSuf": ""
- },
- {
- "gSize": 3,
- "lgSize": 3,
- "maxFrac": 2,
- "minFrac": 2,
- "minInt": 1,
- "negPre": "-\u00a4",
- "negSuf": "",
- "posPre": "\u00a4",
- "posSuf": ""
- }
- ]
- },
- "id": "en-us",
- "localeID": "en_US",
- "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
-});
-}]);
-
- jqLite(document).ready(function() {
- angularInit(document, bootstrap);
- });
-
-})(window, document);
-
-!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js
deleted file mode 100644
index dcb1a136..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- AngularJS v1.5.0
- (c) 2010-2016 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(O,W,v){'use strict';function H(a){return function(){var b=arguments[0],d;d="["+(a?a+":":"")+b+"] http://errors.angularjs.org/1.5.0/"+(a?a+"/":"")+b;for(b=1;b<arguments.length;b++){d=d+(1==b?"?":"&")+"p"+(b-1)+"=";var c=encodeURIComponent,e;e=arguments[b];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;d+=c(e)}return Error(d)}}function Ca(a){if(null==a||Za(a))return!1;if(L(a)||F(a)||C&&a instanceof C)return!0;
-var b="length"in Object(a)&&a.length;return N(b)&&(0<=b&&(b-1 in a||a instanceof Array)||"function"==typeof a.item)}function n(a,b,d){var c,e;if(a)if(D(a))for(c in a)"prototype"==c||"length"==c||"name"==c||a.hasOwnProperty&&!a.hasOwnProperty(c)||b.call(d,a[c],c,a);else if(L(a)||Ca(a)){var f="object"!==typeof a;c=0;for(e=a.length;c<e;c++)(f||c in a)&&b.call(d,a[c],c,a)}else if(a.forEach&&a.forEach!==n)a.forEach(b,d,a);else if(qc(a))for(c in a)b.call(d,a[c],c,a);else if("function"===typeof a.hasOwnProperty)for(c in a)a.hasOwnProperty(c)&&
-b.call(d,a[c],c,a);else for(c in a)sa.call(a,c)&&b.call(d,a[c],c,a);return a}function rc(a,b,d){for(var c=Object.keys(a).sort(),e=0;e<c.length;e++)b.call(d,a[c[e]],c[e]);return c}function sc(a){return function(b,d){a(d,b)}}function Yd(){return++pb}function Qb(a,b,d){for(var c=a.$$hashKey,e=0,f=b.length;e<f;++e){var g=b[e];if(E(g)||D(g))for(var h=Object.keys(g),k=0,l=h.length;k<l;k++){var m=h[k],r=g[m];d&&E(r)?V(r)?a[m]=new Date(r.valueOf()):$a(r)?a[m]=new RegExp(r):r.nodeName?a[m]=r.cloneNode(!0):
-Rb(r)?a[m]=r.clone():(E(a[m])||(a[m]=L(r)?[]:{}),Qb(a[m],[r],!0)):a[m]=r}}c?a.$$hashKey=c:delete a.$$hashKey;return a}function T(a){return Qb(a,wa.call(arguments,1),!1)}function Zd(a){return Qb(a,wa.call(arguments,1),!0)}function ca(a){return parseInt(a,10)}function Sb(a,b){return T(Object.create(a),b)}function B(){}function ab(a){return a}function ba(a){return function(){return a}}function tc(a){return D(a.toString)&&a.toString!==ga}function x(a){return"undefined"===typeof a}function y(a){return"undefined"!==
-typeof a}function E(a){return null!==a&&"object"===typeof a}function qc(a){return null!==a&&"object"===typeof a&&!uc(a)}function F(a){return"string"===typeof a}function N(a){return"number"===typeof a}function V(a){return"[object Date]"===ga.call(a)}function D(a){return"function"===typeof a}function $a(a){return"[object RegExp]"===ga.call(a)}function Za(a){return a&&a.window===a}function bb(a){return a&&a.$evalAsync&&a.$watch}function Na(a){return"boolean"===typeof a}function $d(a){return a&&N(a.length)&&
-ae.test(ga.call(a))}function Rb(a){return!(!a||!(a.nodeName||a.prop&&a.attr&&a.find))}function be(a){var b={};a=a.split(",");var d;for(d=0;d<a.length;d++)b[a[d]]=!0;return b}function ra(a){return G(a.nodeName||a[0]&&a[0].nodeName)}function cb(a,b){var d=a.indexOf(b);0<=d&&a.splice(d,1);return d}function Oa(a,b){function d(a,b){var d=b.$$hashKey,e;if(L(a)){e=0;for(var f=a.length;e<f;e++)b.push(c(a[e]))}else if(qc(a))for(e in a)b[e]=c(a[e]);else if(a&&"function"===typeof a.hasOwnProperty)for(e in a)a.hasOwnProperty(e)&&
-(b[e]=c(a[e]));else for(e in a)sa.call(a,e)&&(b[e]=c(a[e]));d?b.$$hashKey=d:delete b.$$hashKey;return b}function c(a){if(!E(a))return a;var b=f.indexOf(a);if(-1!==b)return g[b];if(Za(a)||bb(a))throw Da("cpws");var b=!1,c=e(a);c===v&&(c=L(a)?[]:Object.create(uc(a)),b=!0);f.push(a);g.push(c);return b?d(a,c):c}function e(a){switch(ga.call(a)){case "[object Int8Array]":case "[object Int16Array]":case "[object Int32Array]":case "[object Float32Array]":case "[object Float64Array]":case "[object Uint8Array]":case "[object Uint8ClampedArray]":case "[object Uint16Array]":case "[object Uint32Array]":return new a.constructor(c(a.buffer));
-case "[object ArrayBuffer]":if(!a.slice){var b=new ArrayBuffer(a.byteLength);(new Uint8Array(b)).set(new Uint8Array(a));return b}return a.slice(0);case "[object Boolean]":case "[object Number]":case "[object String]":case "[object Date]":return new a.constructor(a.valueOf());case "[object RegExp]":return b=new RegExp(a.source,a.toString().match(/[^\/]*$/)[0]),b.lastIndex=a.lastIndex,b}if(D(a.cloneNode))return a.cloneNode(!0)}var f=[],g=[];if(b){if($d(b)||"[object ArrayBuffer]"===ga.call(b))throw Da("cpta");
-if(a===b)throw Da("cpi");L(b)?b.length=0:n(b,function(a,c){"$$hashKey"!==c&&delete b[c]});f.push(a);g.push(b);return d(a,b)}return c(a)}function na(a,b){if(L(a)){b=b||[];for(var d=0,c=a.length;d<c;d++)b[d]=a[d]}else if(E(a))for(d in b=b||{},a)if("$"!==d.charAt(0)||"$"!==d.charAt(1))b[d]=a[d];return b||a}function oa(a,b){if(a===b)return!0;if(null===a||null===b)return!1;if(a!==a&&b!==b)return!0;var d=typeof a,c;if(d==typeof b&&"object"==d)if(L(a)){if(!L(b))return!1;if((d=a.length)==b.length){for(c=
-0;c<d;c++)if(!oa(a[c],b[c]))return!1;return!0}}else{if(V(a))return V(b)?oa(a.getTime(),b.getTime()):!1;if($a(a))return $a(b)?a.toString()==b.toString():!1;if(bb(a)||bb(b)||Za(a)||Za(b)||L(b)||V(b)||$a(b))return!1;d=Z();for(c in a)if("$"!==c.charAt(0)&&!D(a[c])){if(!oa(a[c],b[c]))return!1;d[c]=!0}for(c in b)if(!(c in d)&&"$"!==c.charAt(0)&&y(b[c])&&!D(b[c]))return!1;return!0}return!1}function db(a,b,d){return a.concat(wa.call(b,d))}function vc(a,b){var d=2<arguments.length?wa.call(arguments,2):[];
-return!D(b)||b instanceof RegExp?b:d.length?function(){return arguments.length?b.apply(a,db(d,arguments,0)):b.apply(a,d)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}}function ce(a,b){var d=b;"string"===typeof a&&"$"===a.charAt(0)&&"$"===a.charAt(1)?d=v:Za(b)?d="$WINDOW":b&&W===b?d="$DOCUMENT":bb(b)&&(d="$SCOPE");return d}function eb(a,b){if(x(a))return v;N(b)||(b=b?2:null);return JSON.stringify(a,ce,b)}function wc(a){return F(a)?JSON.parse(a):a}function xc(a,b){a=a.replace(de,
-"");var d=Date.parse("Jan 01, 1970 00:00:00 "+a)/6E4;return isNaN(d)?b:d}function Tb(a,b,d){d=d?-1:1;var c=a.getTimezoneOffset();b=xc(b,c);d*=b-c;a=new Date(a.getTime());a.setMinutes(a.getMinutes()+d);return a}function ta(a){a=C(a).clone();try{a.empty()}catch(b){}var d=C("<div>").append(a).html();try{return a[0].nodeType===Pa?G(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+G(b)})}catch(c){return G(d)}}function yc(a){try{return decodeURIComponent(a)}catch(b){}}function zc(a){var b=
-{};n((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=yc(e),y(e)&&(f=y(f)?yc(f):!0,sa.call(b,e)?L(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Ub(a){var b=[];n(a,function(a,c){L(a)?n(a,function(a){b.push(ha(c,!0)+(!0===a?"":"="+ha(a,!0)))}):b.push(ha(c,!0)+(!0===a?"":"="+ha(a,!0)))});return b.length?b.join("&"):""}function qb(a){return ha(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,
-"+")}function ha(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function ee(a,b){var d,c,e=Qa.length;for(c=0;c<e;++c)if(d=Qa[c]+b,F(d=a.getAttribute(d)))return d;return null}function fe(a,b){var d,c,e={};n(Qa,function(b){b+="app";!d&&a.hasAttribute&&a.hasAttribute(b)&&(d=a,c=a.getAttribute(b))});n(Qa,function(b){b+="app";var e;!d&&(e=a.querySelector("["+b.replace(":","\\:")+"]"))&&
-(d=e,c=e.getAttribute(b))});d&&(e.strictDi=null!==ee(d,"strict-di"),b(d,c?[c]:[],e))}function Ac(a,b,d){E(d)||(d={});d=T({strictDi:!1},d);var c=function(){a=C(a);if(a.injector()){var c=a[0]===W?"document":ta(a);throw Da("btstrpd",c.replace(/</,"&lt;").replace(/>/,"&gt;"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=fb(b,d.strictDi);c.invoke(["$rootScope","$rootElement",
-"$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(d.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return c();O.name=O.name.replace(f,"");ia.resumeBootstrap=function(a){n(a,function(a){b.push(a)});return c()};D(ia.resumeDeferredBootstrap)&&ia.resumeDeferredBootstrap()}function ge(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function he(a){a=
-ia.element(a).injector();if(!a)throw Da("test");return a.get("$$testability")}function Bc(a,b){b=b||"_";return a.replace(ie,function(a,c){return(c?b:"")+a.toLowerCase()})}function je(){var a;if(!Cc){var b=rb();(ua=x(b)?O.jQuery:b?O[b]:v)&&ua.fn.on?(C=ua,T(ua.fn,{scope:Ra.scope,isolateScope:Ra.isolateScope,controller:Ra.controller,injector:Ra.injector,inheritedData:Ra.inheritedData}),a=ua.cleanData,ua.cleanData=function(b){for(var c,e=0,f;null!=(f=b[e]);e++)(c=ua._data(f,"events"))&&c.$destroy&&ua(f).triggerHandler("$destroy");
-a(b)}):C=U;ia.element=C;Cc=!0}}function sb(a,b,d){if(!a)throw Da("areq",b||"?",d||"required");return a}function Sa(a,b,d){d&&L(a)&&(a=a[a.length-1]);sb(D(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ta(a,b){if("hasOwnProperty"===a)throw Da("badname",b);}function Dc(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g<f;g++)c=b[g],a&&(a=(e=a)[c]);return!d&&D(a)?vc(e,a):a}function tb(a){for(var b=a[0],d=a[a.length-1],c,
-e=1;b!==d&&(b=b.nextSibling);e++)if(c||a[e]!==b)c||(c=C(wa.call(a,0,e))),c.push(b);return c||a}function Z(){return Object.create(null)}function ke(a){function b(a,b,c){return a[b]||(a[b]=c())}var d=H("$injector"),c=H("ng");a=b(a,"angular",Object);a.$$minErr=a.$$minErr||H;return b(a,"module",function(){var a={};return function(f,g,h){if("hasOwnProperty"===f)throw c("badname","module");g&&a.hasOwnProperty(f)&&(a[f]=null);return b(a,f,function(){function a(b,d,e,f){f||(f=c);return function(){f[e||"push"]([b,
-d,arguments]);return K}}function b(a,d){return function(b,e){e&&D(e)&&(e.$$moduleName=f);c.push([a,d,arguments]);return K}}if(!g)throw d("nomod",f);var c=[],e=[],s=[],I=a("$injector","invoke","push",e),K={_invokeQueue:c,_configBlocks:e,_runBlocks:s,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider",
-"register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider","register"),directive:b("$compileProvider","directive"),component:b("$compileProvider","component"),config:I,run:function(a){s.push(a);return this}};h&&I(h);return K})}})}function le(a){T(a,{bootstrap:Ac,copy:Oa,extend:T,merge:Zd,equals:oa,element:C,forEach:n,injector:fb,noop:B,bind:vc,toJson:eb,fromJson:wc,identity:ab,isUndefined:x,isDefined:y,isString:F,isFunction:D,isObject:E,isNumber:N,isElement:Rb,isArray:L,
-version:me,isDate:V,lowercase:G,uppercase:ub,callbacks:{counter:0},getTestability:he,$$minErr:H,$$csp:Ea,reloadWithDebugInfo:ge});Vb=ke(O);Vb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:ne});a.provider("$compile",Ec).directive({a:oe,input:Fc,textarea:Fc,form:pe,script:qe,select:re,style:se,option:te,ngBind:ue,ngBindHtml:ve,ngBindTemplate:we,ngClass:xe,ngClassEven:ye,ngClassOdd:ze,ngCloak:Ae,ngController:Be,ngForm:Ce,ngHide:De,ngIf:Ee,ngInclude:Fe,ngInit:Ge,ngNonBindable:He,
-ngPluralize:Ie,ngRepeat:Je,ngShow:Ke,ngStyle:Le,ngSwitch:Me,ngSwitchWhen:Ne,ngSwitchDefault:Oe,ngOptions:Pe,ngTransclude:Qe,ngModel:Re,ngList:Se,ngChange:Te,pattern:Gc,ngPattern:Gc,required:Hc,ngRequired:Hc,minlength:Ic,ngMinlength:Ic,maxlength:Jc,ngMaxlength:Jc,ngValue:Ue,ngModelOptions:Ve}).directive({ngInclude:We}).directive(vb).directive(Kc);a.provider({$anchorScroll:Xe,$animate:Ye,$animateCss:Ze,$$animateJs:$e,$$animateQueue:af,$$AnimateRunner:bf,$$animateAsyncRun:cf,$browser:df,$cacheFactory:ef,
-$controller:ff,$document:gf,$exceptionHandler:hf,$filter:Lc,$$forceReflow:jf,$interpolate:kf,$interval:lf,$http:mf,$httpParamSerializer:nf,$httpParamSerializerJQLike:of,$httpBackend:pf,$xhrFactory:qf,$location:rf,$log:sf,$parse:tf,$rootScope:uf,$q:vf,$$q:wf,$sce:xf,$sceDelegate:yf,$sniffer:zf,$templateCache:Af,$templateRequest:Bf,$$testability:Cf,$timeout:Df,$window:Ef,$$rAF:Ff,$$jqLite:Gf,$$HashMap:Hf,$$cookieReader:If})}])}function gb(a){return a.replace(Jf,function(a,d,c,e){return e?c.toUpperCase():
-c}).replace(Kf,"Moz$1")}function Mc(a){a=a.nodeType;return 1===a||!a||9===a}function Nc(a,b){var d,c,e=b.createDocumentFragment(),f=[];if(Wb.test(a)){d=d||e.appendChild(b.createElement("div"));c=(Lf.exec(a)||["",""])[1].toLowerCase();c=da[c]||da._default;d.innerHTML=c[1]+a.replace(Mf,"<$1></$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=db(f,d.childNodes);d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";n(f,function(a){e.appendChild(a)});return e}function Oc(a,
-b){var d=a.parentNode;d&&d.replaceChild(b,a);b.appendChild(a)}function U(a){if(a instanceof U)return a;var b;F(a)&&(a=X(a),b=!0);if(!(this instanceof U)){if(b&&"<"!=a.charAt(0))throw Xb("nosel");return new U(a)}if(b){b=W;var d;a=(d=Nf.exec(a))?[b.createElement(d[1])]:(d=Nc(a,b))?d.childNodes:[]}Pc(this,a)}function Yb(a){return a.cloneNode(!0)}function wb(a,b){b||hb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;c<e;c++)hb(d[c])}function Qc(a,b,d,c){if(y(c))throw Xb("offargs");
-var e=(c=xb(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];y(d)&&cb(c||[],d);y(d)&&c&&0<c.length||(a.removeEventListener(b,f,!1),delete e[b])};n(b.split(" "),function(a){g(a);yb[a]&&g(yb[a])})}else for(b in e)"$destroy"!==b&&a.removeEventListener(b,f,!1),delete e[b]}function hb(a,b){var d=a.ng339,c=d&&ib[d];c&&(b?delete c.data[b]:(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),Qc(a)),delete ib[d],a.ng339=v))}function xb(a,b){var d=a.ng339,d=d&&ib[d];b&&!d&&(a.ng339=d=++Of,
-d=ib[d]={events:{},data:{},handle:v});return d}function Zb(a,b,d){if(Mc(a)){var c=y(d),e=!c&&b&&!E(b),f=!b;a=(a=xb(a,!e))&&a.data;if(c)a[b]=d;else{if(f)return a;if(e)return a&&a[b];T(a,b)}}}function zb(a,b){return a.getAttribute?-1<(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+b+" "):!1}function Ab(a,b){b&&a.setAttribute&&n(b.split(" "),function(b){a.setAttribute("class",X((" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+X(b)+" "," ")))})}function Bb(a,
-b){if(b&&a.setAttribute){var d=(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");n(b.split(" "),function(a){a=X(a);-1===d.indexOf(" "+a+" ")&&(d+=a+" ")});a.setAttribute("class",X(d))}}function Pc(a,b){if(b)if(b.nodeType)a[a.length++]=b;else{var d=b.length;if("number"===typeof d&&b.window!==b){if(d)for(var c=0;c<d;c++)a[a.length++]=b[c]}else a[a.length++]=b}}function Rc(a,b){return Cb(a,"$"+(b||"ngController")+"Controller")}function Cb(a,b,d){9==a.nodeType&&(a=a.documentElement);for(b=
-L(b)?b:[b];a;){for(var c=0,e=b.length;c<e;c++)if(y(d=C.data(a,b[c])))return d;a=a.parentNode||11===a.nodeType&&a.host}}function Sc(a){for(wb(a,!0);a.firstChild;)a.removeChild(a.firstChild)}function $b(a,b){b||wb(a);var d=a.parentNode;d&&d.removeChild(a)}function Pf(a,b){b=b||O;if("complete"===b.document.readyState)b.setTimeout(a);else C(b).on("load",a)}function Tc(a,b){var d=Db[b.toLowerCase()];return d&&Uc[ra(a)]&&d}function Qf(a,b){var d=function(c,d){c.isDefaultPrevented=function(){return c.defaultPrevented};
-var f=b[d||c.type],g=f?f.length:0;if(g){if(x(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};var k=f.specialHandlerWrapper||Rf;1<g&&(f=na(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||k(a,c,f[l])}};d.elem=a;return d}function Rf(a,b,d){d.call(a,b)}function Sf(a,b,
-d){var c=b.relatedTarget;c&&(c===a||Tf.call(a,c))||d.call(a,b)}function Gf(){this.$get=function(){return T(U,{hasClass:function(a,b){a.attr&&(a=a[0]);return zb(a,b)},addClass:function(a,b){a.attr&&(a=a[0]);return Bb(a,b)},removeClass:function(a,b){a.attr&&(a=a[0]);return Ab(a,b)}})}}function Fa(a,b){var d=a&&a.$$hashKey;if(d)return"function"===typeof d&&(d=a.$$hashKey()),d;d=typeof a;return d="function"==d||"object"==d&&null!==a?a.$$hashKey=d+":"+(b||Yd)():d+":"+a}function Ua(a,b){if(b){var d=0;this.nextUid=
-function(){return++d}}n(a,this.put,this)}function Vc(a){a=a.toString().replace(Uf,"");return a.match(Vf)||a.match(Wf)}function Xf(a){return(a=Vc(a))?"function("+(a[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function fb(a,b){function d(a){return function(b,c){if(E(b))n(b,sc(a));else return a(b,c)}}function c(a,b){Ta(a,"service");if(D(b)||L(b))b=s.instantiate(b);if(!b.$get)throw Ga("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=t.invoke(b,this);if(x(c))throw Ga("undef",a);
-return c}}function f(a,b,d){return c(a,{$get:!1!==d?e(a,b):b})}function g(a){sb(x(a)||L(a),"modulesToLoad","not an array");var b=[],c;n(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=s.get(e[0]);f[e[1]].apply(f,e[2])}}if(!m.get(a)){m.put(a,!0);try{F(a)?(c=Vb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):D(a)?b.push(s.invoke(a)):L(a)?b.push(s.invoke(a)):Sa(a,"module")}catch(e){throw L(a)&&(a=a[a.length-1]),e.message&&e.stack&&
--1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ga("modulerr",a,e.stack||e.message||e);}}});return b}function h(a,c){function d(b,e){if(a.hasOwnProperty(b)){if(a[b]===k)throw Ga("cdep",b+" <- "+l.join(" <- "));return a[b]}try{return l.unshift(b),a[b]=k,a[b]=c(b,e)}catch(f){throw a[b]===k&&delete a[b],f;}finally{l.shift()}}function e(a,c,f){var g=[];a=fb.$$annotate(a,b,f);for(var h=0,k=a.length;h<k;h++){var l=a[h];if("string"!==typeof l)throw Ga("itkn",l);g.push(c&&c.hasOwnProperty(l)?c[l]:
-d(l,f))}return g}return{invoke:function(a,b,c,d){"string"===typeof c&&(d=c,c=null);c=e(a,c,d);L(a)&&(a=a[a.length-1]);d=11>=xa?!1:"function"===typeof a&&/^(?:class\s|constructor\()/.test(Function.prototype.toString.call(a));return d?(c.unshift(null),new (Function.prototype.bind.apply(a,c))):a.apply(b,c)},instantiate:function(a,b,c){var d=L(a)?a[a.length-1]:a;a=e(a,b,c);a.unshift(null);return new (Function.prototype.bind.apply(d,a))},get:d,annotate:fb.$$annotate,has:function(b){return r.hasOwnProperty(b+
-"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var k={},l=[],m=new Ua([],!0),r={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,ba(b),!1)}),constant:d(function(a,b){Ta(a,"constant");r[a]=b;I[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=t.invoke(d,c);return t.invoke(b,null,{$delegate:a})}}}},s=r.$injector=h(r,function(a,b){ia.isString(b)&&l.push(b);
-throw Ga("unpr",l.join(" <- "));}),I={},K=h(I,function(a,b){var c=s.get(a+"Provider",b);return t.invoke(c.$get,c,v,a)}),t=K;r.$injectorProvider={$get:ba(K)};var p=g(a),t=K.get("$injector");t.strictDi=b;n(p,function(a){a&&t.invoke(a)});return t}function Xe(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window","$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ra(a))return b=a,!0});return b}function f(a){if(a){a.scrollIntoView();
-var c;c=g.yOffset;D(c)?c=c():Rb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):N(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=F(a)?a:d.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=b.document;a&&c.$watch(function(){return d.hash()},function(a,b){a===b&&""===a||Pf(function(){c.$evalAsync(g)})});return g}]}function jb(a,b){if(!a&&!b)return"";
-if(!a)return b;if(!b)return a;L(a)&&(a=a.join(" "));L(b)&&(b=b.join(" "));return a+" "+b}function Yf(a){F(a)&&(a=a.split(" "));var b=Z();n(a,function(a){a.length&&(b[a]=!0)});return b}function Ha(a){return E(a)?a:{}}function Zf(a,b,d,c){function e(a){try{a.apply(null,wa.call(arguments,1))}finally{if(K--,0===K)for(;t.length;)try{t.pop()()}catch(b){d.error(b)}}}function f(){z=null;g();h()}function g(){a:{try{p=m.state;break a}catch(a){}p=void 0}p=x(p)?null:p;oa(p,$)&&(p=$);$=p}function h(){if(u!==k.url()||
-w!==p)u=k.url(),w=p,n(A,function(a){a(k.url(),p)})}var k=this,l=a.location,m=a.history,r=a.setTimeout,s=a.clearTimeout,I={};k.isMock=!1;var K=0,t=[];k.$$completeOutstandingRequest=e;k.$$incOutstandingRequestCount=function(){K++};k.notifyWhenNoOutstandingRequests=function(a){0===K?a():t.push(a)};var p,w,u=l.href,la=b.find("base"),z=null;g();w=p;k.url=function(b,d,e){x(e)&&(e=null);l!==a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=w===e;if(u===b&&(!c.history||f))return k;var h=
-u&&Ia(u)===Ia(b);u=b;w=e;if(!c.history||h&&f){if(!h||z)z=b;d?l.replace(b):h?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b;l.href!==b&&(z=b)}else m[d?"replaceState":"pushState"](e,"",b),g(),w=p;return k}return z||l.href.replace(/%27/g,"'")};k.state=function(){return p};var A=[],Q=!1,$=null;k.onUrlChange=function(b){if(!Q){if(c.history)C(a).on("popstate",f);C(a).on("hashchange",f);Q=!0}A.push(b);return b};k.$$applicationDestroyed=function(){C(a).off("hashchange popstate",f)};k.$$checkUrlChange=
-h;k.baseHref=function(){var a=la.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};k.defer=function(a,b){var c;K++;c=r(function(){delete I[c];e(a)},b||0);I[c]=!0;return c};k.defer.cancel=function(a){return I[a]?(delete I[a],s(a),e(B),!0):!1}}function df(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new Zf(a,c,b,d)}]}function ef(){this.$get=function(){function a(a,c){function e(a){a!=r&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,r),r=a,r.n=null)}function f(a,
-b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw H("$cacheFactory")("iid",a);var g=0,h=T({},c,{id:a}),k=Z(),l=c&&c.capacity||Number.MAX_VALUE,m=Z(),r=null,s=null;return b[a]={put:function(a,b){if(!x(b)){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}a in k||g++;k[a]=b;g>l&&this.remove(s.key);return b}},get:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return k[a]},remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b==r&&(r=b.p);b==s&&(s=b.n);f(b.n,b.p);delete m[a]}a in
-k&&(delete k[a],g--)},removeAll:function(){k=Z();g=0;m=Z();r=s=null},destroy:function(){m=h=k=null;delete b[a]},info:function(){return T({},h,{size:g})}}}var b={};a.info=function(){var a={};n(b,function(b,e){a[e]=b.info()});return a};a.get=function(a){return b[a]};return a}}function Af(){this.$get=["$cacheFactory",function(a){return a("templates")}]}function Ec(a,b){function d(a,b,c){var d=/^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/,e={};n(a,function(a,f){var g=a.match(d);if(!g)throw ja("iscp",b,f,a,c?
-"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function c(a){var b=a.charAt(0);if(!b||b!==G(b))throw ja("baddir",a);if(a!==a.trim())throw ja("baddir",a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=be("ngSrc,ngSrcset,src,srcset"),k=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function s(b,f){Ta(b,"directive");F(b)?(c(b),sb(f,"directiveFactory"),
-e.hasOwnProperty(b)||(e[b]=[],a.factory(b+"Directive",["$injector","$exceptionHandler",function(a,c){var f=[];n(e[b],function(e,g){try{var h=a.invoke(e);D(h)?h={compile:ba(h)}:!h.compile&&h.link&&(h.compile=ba(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||b;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,m=h.name,s={isolateScope:null,bindToController:null};E(l.scope)&&(!0===l.bindToController?(s.bindToController=d(l.scope,m,!0),s.isolateScope={}):s.isolateScope=
-d(l.scope,m,!1));E(l.bindToController)&&(s.bindToController=d(l.bindToController,m,!0));if(E(s.bindToController)){var P=l.controller,S=l.controllerAs;if(!P)throw ja("noctrl",m);if(!Wc(P,S))throw ja("noident",m);}var ma=k.$$bindings=s;E(ma.isolateScope)&&(h.$$isolateBindings=ma.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(K){c(K)}});return f}])),e[b].push(f)):n(b,sc(s));return this};this.component=function(a,b){function c(a){function e(b){return D(b)||L(b)?function(c,d){return a.invoke(b,
-this,{$element:c,$attrs:d})}:b}var f=b.template||b.templateUrl?b.template:"";return{controller:d,controllerAs:Wc(b.controller)||b.controllerAs||"$ctrl",template:e(f),templateUrl:e(b.templateUrl),transclude:b.transclude,scope:{},bindToController:b.bindings||{},restrict:"E",require:b.require}}var d=b.controller||function(){};n(b,function(a,b){"$"===b.charAt(0)&&(c[b]=a)});c.$inject=["$injector"];return this.directive(a,c)};this.aHrefSanitizationWhitelist=function(a){return y(a)?(b.aHrefSanitizationWhitelist(a),
-this):b.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(a){return y(a)?(b.imgSrcSanitizationWhitelist(a),this):b.imgSrcSanitizationWhitelist()};var m=!0;this.debugInfoEnabled=function(a){return y(a)?(m=a,this):m};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$sce","$animate","$$sanitizeUri",function(a,b,c,d,p,w,u,la,z,A){function Q(a,b,c){ba.innerHTML="<span "+b+">";b=ba.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);
-d.value=c;a.attributes.setNamedItem(d)}function $(a,b){try{a.addClass(b)}catch(c){}}function M(a,b,c,d,e){a instanceof C||(a=C(a));for(var f=/\S+/,g=0,h=a.length;g<h;g++){var k=a[g];k.nodeType===Pa&&k.nodeValue.match(f)&&Oc(k,a[g]=W.createElement("span"))}var l=P(a,b,a,c,d,e);M.$$addScopeClass(a);var m=null;return function(b,c,d){sb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var f=d.parentBoundTranscludeFn,g=d.transcludeControllers;d=d.futureParentElement;f&&f.$$boundTransclude&&
-(f=f.$$boundTransclude);m||(m=(d=d&&d[0])?"foreignobject"!==ra(d)&&ga.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==m?C(U(m,C("<div>").append(a).html())):c?Ra.clone.call(a):a;if(g)for(var h in g)d.data("$"+h+"Controller",g[h].instance);M.$$addScopeInfo(d,b);c&&c(d,b);l&&l(b,d,d,f);return d}}function P(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,m,p,s,u;if(A)for(u=Array(c.length),m=0;m<h.length;m+=3)f=h[m],u[f]=c[f];else u=c;m=0;for(p=h.length;m<p;)k=u[h[m++]],c=h[m++],f=h[m++],c?(c.scope?(l=
-a.$new(),M.$$addScopeInfo(C(k),l)):l=a,s=c.transcludeOnThisElement?S(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?S(a,b):null,c(f,l,k,d,s)):f&&f(a,k.childNodes,v,e)}for(var h=[],k,l,m,p,A,s=0;s<a.length;s++){k=new na;l=ma(a[s],[],k,0===s?d:v,e);(f=l.length?y(l,a[s],k,b,c,null,[],[],f):null)&&f.scope&&M.$$addScopeClass(k.$$element);k=f&&f.terminal||!(m=a[s].childNodes)||!m.length?null:P(m,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(s,f,k),p=!0,A=
-A||f;f=null}return p?g:null}function S(a,b,c){var d=function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})},e=d.$$slots=Z(),f;for(f in b.$$slots)e[f]=b.$$slots[f]?S(a,b.$$slots[f],c):null;return d}function ma(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case 1:H(b,va(ra(a)),"E",d,e);for(var l,m,p,s=a.attributes,A=0,u=s&&s.length;A<u;A++){var t=!1,w=!1;l=s[A];k=l.name;m=X(l.value);l=va(k);if(p=pa.test(l))k=
-k.replace(Xc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});(l=l.match(ua))&&O(l[1])&&(t=k,w=k.substr(0,k.length-5)+"end",k=k.substr(0,k.length-6));l=va(k.toLowerCase());h[l]=k;if(p||!c.hasOwnProperty(l))c[l]=m,Tc(a,l)&&(c[l]=!0);Y(a,b,m,l,p);H(b,l,"A",d,e,t,w)}a=a.className;E(a)&&(a=a.animVal);if(F(a)&&""!==a)for(;k=g.exec(a);)l=va(k[2]),H(b,l,"C",d,e)&&(c[l]=X(k[3])),a=a.substr(k.index+k[0].length);break;case Pa:if(11===xa)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===
-Pa;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);N(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=va(k[1]),H(b,l,"M",d,e)&&(c[l]=X(k[2]))}catch(M){}}b.sort(ya);return b}function q(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ja("uterdir",b,c);1==a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return C(d)}function Yc(a,b,c){return function(d,e,f,g,h){e=q(e[0],b,
-c);return a(d,e,f,g,h)}}function ac(a,b,c,d,e,f){if(a)return M(b,c,d,e,f);var g;return function(){g||(g=M(b,c,d,e,f),b=c=f=null);return g.apply(this,arguments)}}function y(a,b,d,e,f,g,h,l,m){function p(a,b,c,d){if(a){c&&(a=Yc(a,c,d));a.require=J.require;a.directiveName=H;if(P===J||J.$$isolateScope)a=ca(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Yc(b,c,d));b.require=J.require;b.directiveName=H;if(P===J||J.$$isolateScope)b=ca(b,{isolateScope:!0});l.push(b)}}function s(a,b,c,d){var e;if(F(b)){var f=
-b.match(k);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;if(!e){var h="$"+b+"Controller";e=g?c.inheritedData(h):c.data(h)}if(!e&&!f)throw ja("ctreq",b,a);}else if(L(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=s(a,b[g],c,d);else E(b)&&(e={},n(b,function(b,f){e[f]=s(a,b,c,d)}));return e||null}function A(a,b,c,d,e,f){var g=Z(),h;for(h in d){var k=d[h],l={$scope:k===P||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},m=k.controller;"@"==m&&
-(m=b[k.name]);l=w(m,l,!0,k.controllerAs);g[k.name]=l;B||a.data("$"+k.name+"Controller",l.instance)}return g}function u(a,c,e,f,g){function k(a,b,c,d){var e;bb(a)||(d=c,c=b,b=a,a=v);B&&(e=ma);c||(c=B?z.parent():z);if(d){var f=g.$$slots[d];if(f)return f(a,b,e,c,Eb);if(x(f))throw ja("noslot",d,ta(z));}else return g(a,b,e,c,Eb)}var m,p,t,w,ma,S,z,Ja;b===e?(f=d,z=d.$$element):(z=C(e),f=new na(z,d));t=c;P?w=c.$new(!0):Q&&(t=c.$parent);g&&(S=k,S.$$boundTransclude=g,S.isSlotFilled=function(a){return!!g.$$slots[a]});
-I&&(ma=A(z,f,S,I,w,c));P&&(M.$$addScopeInfo(z,w,!0,!($&&($===P||$===P.$$originalDirective))),M.$$addScopeClass(z,!0),w.$$isolateBindings=P.$$isolateBindings,(Ja=ia(c,f,w,w.$$isolateBindings,P))&&w.$on("$destroy",Ja));for(p in ma){Ja=I[p];var K=ma[p],la=Ja.$$bindings.bindToController;K.identifier&&la&&(m=ia(t,f,K.instance,la,Ja));var q=K();q!==K.instance&&(K.instance=q,z.data("$"+Ja.name+"Controller",q),m&&m(),m=ia(t,f,K.instance,la,Ja))}n(I,function(a,b){var c=a.require;a.bindToController&&!L(c)&&
-E(c)&&T(ma[b].instance,s(b,c,z,ma))});n(ma,function(a){D(a.instance.$onInit)&&a.instance.$onInit()});m=0;for(p=h.length;m<p;m++)t=h[m],ka(t,t.isolateScope?w:c,z,f,t.require&&s(t.directiveName,t.require,z,ma),S);var Eb=c;P&&(P.template||null===P.templateUrl)&&(Eb=w);a&&a(Eb,e.childNodes,v,g);for(m=l.length-1;0<=m;m--)t=l[m],ka(t,t.isolateScope?w:c,z,f,t.require&&s(t.directiveName,t.require,z,ma),S)}m=m||{};for(var t=-Number.MAX_VALUE,Q=m.newScopeDirective,I=m.controllerDirectives,P=m.newIsolateScopeDirective,
-$=m.templateDirective,S=m.nonTlbTranscludeDirective,z=!1,la=!1,B=m.hasElementTranscludeDirective,ea=d.$$element=C(b),J,H,G,ya=e,O,N=!1,Fb=!1,fa,R=0,Va=a.length;R<Va;R++){J=a[R];var Y=J.$$start,ba=J.$$end;Y&&(ea=q(b,Y,ba));G=v;if(t>J.priority)break;if(fa=J.scope)J.templateUrl||(E(fa)?(Wa("new/isolated scope",P||Q,J,ea),P=J):Wa("new/isolated scope",P,J,ea)),Q=Q||J;H=J.name;if(!N&&(J.replace&&(J.templateUrl||J.template)||J.transclude&&!J.$$tlb)){for(fa=R+1;N=a[fa++];)if(N.transclude&&!N.$$tlb||N.replace&&
-(N.templateUrl||N.template)){Fb=!0;break}N=!0}!J.templateUrl&&J.controller&&(fa=J.controller,I=I||Z(),Wa("'"+H+"' controller",I[H],J,ea),I[H]=J);if(fa=J.transclude)if(z=!0,J.$$tlb||(Wa("transclusion",S,J,ea),S=J),"element"==fa)B=!0,t=J.priority,G=ea,ea=d.$$element=C(W.createComment(" "+H+": "+d[H]+" ")),b=ea[0],aa(f,wa.call(G,0),b),ya=ac(Fb,G,e,t,g&&g.name,{nonTlbTranscludeDirective:S});else{var V=Z();G=C(Yb(b)).contents();if(E(fa)){G=[];var ha=Z(),da=Z();n(fa,function(a,b){var c="?"===a.charAt(0);
-a=c?a.substring(1):a;ha[a]=b;V[b]=null;da[b]=c});n(ea.contents(),function(a){var b=ha[va(ra(a))];b?(da[b]=!0,V[b]=V[b]||[],V[b].push(a)):G.push(a)});n(da,function(a,b){if(!a)throw ja("reqslot",b);});for(var ga in V)V[ga]&&(V[ga]=ac(Fb,V[ga],e))}ea.empty();ya=ac(Fb,G,e,v,v,{needsNewScope:J.$$isolateScope||J.$$newScope});ya.$$slots=V}if(J.template)if(la=!0,Wa("template",$,J,ea),$=J,fa=D(J.template)?J.template(ea,d):J.template,fa=qa(fa),J.replace){g=J;G=Wb.test(fa)?Zc(U(J.templateNamespace,X(fa))):[];
-b=G[0];if(1!=G.length||1!==b.nodeType)throw ja("tplrt",H,"");aa(f,ea,b);Va={$attr:{}};fa=ma(b,[],Va);var oa=a.splice(R+1,a.length-(R+1));(P||Q)&&$c(fa,P,Q);a=a.concat(fa).concat(oa);ad(d,Va);Va=a.length}else ea.html(fa);if(J.templateUrl)la=!0,Wa("template",$,J,ea),$=J,J.replace&&(g=J),u=$f(a.splice(R,a.length-R),ea,d,f,z&&ya,h,l,{controllerDirectives:I,newScopeDirective:Q!==J&&Q,newIsolateScopeDirective:P,templateDirective:$,nonTlbTranscludeDirective:S}),Va=a.length;else if(J.compile)try{O=J.compile(ea,
-d,ya),D(O)?p(null,O,Y,ba):O&&p(O.pre,O.post,Y,ba)}catch(pa){c(pa,ta(ea))}J.terminal&&(u.terminal=!0,t=Math.max(t,J.priority))}u.scope=Q&&!0===Q.scope;u.transcludeOnThisElement=z;u.templateOnThisElement=la;u.transclude=ya;m.hasElementTranscludeDirective=B;return u}function $c(a,b,c){for(var d=0,e=a.length;d<e;d++)a[d]=Sb(a[d],{$$isolateScope:b,$$newScope:c})}function H(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var m;d=a.get(d+"Directive");for(var p=0,A=d.length;p<A;p++)try{m=
-d[p],(x(g)||g>m.priority)&&-1!=m.restrict.indexOf(f)&&(k&&(m=Sb(m,{$$start:k,$$end:l})),b.push(m),h=m)}catch(t){c(t)}}return h}function O(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=c[d],b.multiElement)return!0;return!1}function ad(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;n(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});n(b,function(b,f){"class"==f?($(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+
-b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function $f(a,b,c,e,f,g,h,k){var l=[],m,p,s=b[0],A=a.shift(),u=Sb(A,{templateUrl:null,transclude:null,replace:null,$$originalDirective:A}),w=D(A.templateUrl)?A.templateUrl(b,c):A.templateUrl,Q=A.templateNamespace;b.empty();d(w).then(function(d){var t,I;d=qa(d);if(A.replace){d=Wb.test(d)?Zc(U(Q,X(d))):[];t=d[0];if(1!=d.length||1!==t.nodeType)throw ja("tplrt",
-A.name,w);d={$attr:{}};aa(e,b,t);var M=ma(t,[],d);E(A.scope)&&$c(M,!0);a=M.concat(a);ad(c,d)}else t=s,b.html(d);a.unshift(u);m=y(a,t,c,f,b,A,g,h,k);n(e,function(a,c){a==t&&(e[c]=b[0])});for(p=P(b[0].childNodes,f);l.length;){d=l.shift();I=l.shift();var z=l.shift(),K=l.shift(),M=b[0];if(!d.$$destroyed){if(I!==s){var la=I.className;k.hasElementTranscludeDirective&&A.replace||(M=Yb(t));aa(z,C(I),M);$(C(M),la)}I=m.transcludeOnThisElement?S(d,m.transclude,K):K;m(p,d,M,e,I)}}l=null});return function(a,b,
-c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(m.transcludeOnThisElement&&(a=S(b,m.transclude,e)),m(p,b,c,d,a)))}}function ya(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Wa(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ja("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ta(d));}function N(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&M.$$addBindingClass(a);
-return function(a,c){var e=c.parent();b||M.$$addBindingClass(e);M.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function U(a,b){a=G(a||"html");switch(a){case "svg":case "math":var c=W.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==b)return la.HTML;var c=ra(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return la.RESOURCE_URL}function Y(a,c,d,e,
-f){var g=R(a,e);f=h[e]||f;var k=b(d,!0,g,f);if(k){if("multiple"===e&&"select"===ra(a))throw ja("selmulti",ta(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers=Z());if(l.test(e))throw ja("nodomevents");var m=h[e];m!==d&&(k=m&&b(m,!0,g,f),d=m);k&&(h[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(k,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e,a)}))}}}})}}function aa(a,b,c){var d=b[0],e=b.length,
-f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=W.createDocumentFragment();for(g=0;g<e;g++)a.appendChild(b[g]);C.hasData(d)&&(C.data(c,C.data(d)),C(d).off("$destroy"));C.cleanData(a.querySelectorAll("*"));for(g=1;g<e;g++)delete b[g];b[0]=c;b.length=1}function ca(a,b){return T(function(){return a.apply(null,arguments)},a,b)}function ka(a,
-b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ta(d))}}function ia(a,c,d,e,f){var g=[];n(e,function(e,h){var k=e.attrName,l=e.optional,m,A,s,t;switch(e.mode){case "@":l||sa.call(c,k)||(d[h]=c[k]=void 0);c.$observe(k,function(a){F(a)&&(d[h]=a)});c.$$observers[k].$$scope=a;m=c[k];F(m)?d[h]=b(m)(a):Na(m)&&(d[h]=m);break;case "=":if(!sa.call(c,k)){if(l)break;c[k]=void 0}if(l&&!c[k])break;A=p(c[k]);t=A.literal?oa:function(a,b){return a===b||a!==a&&b!==b};s=A.assign||function(){m=d[h]=A(a);throw ja("nonassign",
-c[k],k,f.name);};m=d[h]=A(a);l=function(b){t(b,d[h])||(t(b,m)?s(a,b=d[h]):d[h]=b);return m=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(p(c[k],l),null,A.literal);g.push(l);break;case "<":if(!sa.call(c,k)){if(l)break;c[k]=void 0}if(l&&!c[k])break;A=p(c[k]);d[h]=A(a);l=a.$watch(A,function(a){d[h]=a},A.literal);g.push(l);break;case "&":A=c.hasOwnProperty(k)?p(c[k]):B;if(A===B&&l)break;d[h]=function(b){return A(a,b)}}});return g.length&&function(){for(var a=0,b=g.length;a<b;++a)g[a]()}}
-var V=/^\w/,ba=W.createElement("div"),na=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};na.prototype={$normalize:va,$addClass:function(a){a&&0<a.length&&z.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&z.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&z.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&z.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=
-Tc(this.$$element[0],a),g=cd[a],h=a;f?(this.$$element.prop(a,b),e=f):g&&(this[g]=b,h=g);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Bc(a,"-"));f=ra(this.$$element);if("a"===f&&("href"===a||"xlinkHref"===a)||"img"===f&&"src"===a)this[a]=b=A(b,"src"===a);else if("img"===f&&"srcset"===a){for(var f="",g=X(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(g)?k:/(,)/,g=g.split(k),k=Math.floor(g.length/2),l=0;l<k;l++)var m=2*l,f=f+A(X(g[m]),!0),f=f+(" "+X(g[m+1]));g=X(g[2*l]).split(/\s/);
-f+=A(X(g[0]),!0);2===g.length&&(f+=" "+X(g[1]));this[a]=b=f}!1!==d&&(null===b||x(b)?this.$$element.removeAttr(e):V.test(e)?this.$$element.attr(e,b):Q(this.$$element[0],e,b));(a=this.$$observers)&&n(a[h],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=Z()),e=d[a]||(d[a]=[]);e.push(b);u.$evalAsync(function(){e.$$inter||!c.hasOwnProperty(a)||x(c[a])||b(c[a])});return function(){cb(e,b)}}};var ha=b.startSymbol(),da=b.endSymbol(),qa="{{"==ha&&"}}"==
-da?ab:function(a){return a.replace(/\{\{/g,ha).replace(/}}/g,da)},pa=/^ngAttr[A-Z]/,ua=/^(.+)Start$/;M.$$addBindingInfo=m?function(a,b){var c=a.data("$binding")||[];L(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:B;M.$$addBindingClass=m?function(a){$(a,"ng-binding")}:B;M.$$addScopeInfo=m?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:B;M.$$addScopeClass=m?function(a,b){$(a,b?"ng-isolate-scope":"ng-scope")}:B;return M}]}function va(a){return gb(a.replace(Xc,
-""))}function bd(a,b){var d="",c=a.split(/\s+/),e=b.split(/\s+/),f=0;a:for(;f<c.length;f++){for(var g=c[f],h=0;h<e.length;h++)if(g==e[h])continue a;d+=(0<d.length?" ":"")+g}return d}function Zc(a){a=C(a);var b=a.length;if(1>=b)return a;for(;b--;)8===a[b].nodeType&&ag.call(a,b,1);return a}function Wc(a,b){if(b&&F(b))return b;if(F(a)){var d=dd.exec(a);if(d)return d[3]}}function ff(){var a={},b=!1;this.register=function(b,c){Ta(b,"controller");E(b)?T(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=
-["$injector","$window",function(d,c){function e(a,b,c,d){if(!a||!E(a.$scope))throw H("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,r;h=!0===h;k&&F(k)&&(r=k);if(F(f)){k=f.match(dd);if(!k)throw bg("ctrlfmt",f);m=k[1];r=r||k[3];f=a.hasOwnProperty(m)?a[m]:Dc(g.$scope,m,!0)||(b?Dc(c,m,!0):v);Sa(f,m,!0)}if(h)return h=(L(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),r&&e(g,r,l,m||f.name),T(function(){var a=d.invoke(f,l,g,m);a!==l&&(E(a)||D(a))&&(l=a,r&&e(g,r,l,m||f.name));
-return l},{instance:l,identifier:r});l=d.instantiate(f,g,m);r&&e(g,r,l,m||f.name);return l}}]}function gf(){this.$get=["$window",function(a){return C(a.document)}]}function hf(){this.$get=["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function bc(a){return E(a)?V(a)?a.toISOString():eb(a):a}function nf(){this.$get=function(){return function(a){if(!a)return"";var b=[];rc(a,function(a,c){null===a||x(a)||(L(a)?n(a,function(a,d){b.push(ha(c)+"="+ha(bc(a)))}):b.push(ha(c)+"="+ha(bc(a))))});
-return b.join("&")}}}function of(){this.$get=function(){return function(a){function b(a,e,f){null===a||x(a)||(L(a)?n(a,function(a,c){b(a,e+"["+(E(a)?c:"")+"]")}):E(a)&&!V(a)?rc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ha(e)+"="+ha(bc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function cc(a,b){if(F(a)){var d=a.replace(cg,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf(ed))||(c=(c=d.match(dg))&&eg[c[0]].test(d));c&&(a=wc(d))}}return a}function fd(a){var b=
-Z(),d;F(a)?n(a.split("\n"),function(a){d=a.indexOf(":");var e=G(X(a.substr(0,d)));a=X(a.substr(d+1));e&&(b[e]=b[e]?b[e]+", "+a:a)}):E(a)&&n(a,function(a,d){var f=G(d),g=X(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function gd(a){var b;return function(d){b||(b=fd(a));return d?(d=b[G(d)],void 0===d&&(d=null),d):b}}function hd(a,b,d,c){if(D(c))return c(a,b,d);n(c,function(c){a=c(a,b,d)});return a}function mf(){var a=this.defaults={transformResponse:[cc],transformRequest:[function(a){return E(a)&&"[object File]"!==
-ga.call(a)&&"[object Blob]"!==ga.call(a)&&"[object FormData]"!==ga.call(a)?eb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:na(dc),put:na(dc),patch:na(dc)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return y(a)?(b=!!a,this):b};var d=!0;this.useLegacyPromiseExtensions=function(a){return y(a)?(d=!!a,this):d};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory",
-"$rootScope","$q","$injector",function(e,f,g,h,k,l){function m(b){function c(a){var b=T({},a);b.data=hd(a.data,a.headers,a.status,f.transformResponse);a=a.status;return 200<=a&&300>a?b:k.reject(b)}function e(a,b){var c,d={};n(a,function(a,e){D(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}if(!E(b))throw H("$http")("badreq",b);if(!F(b.url))throw H("$http")("badreq",b.url);var f=T({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},
-b);f.headers=function(b){var c=a.headers,d=T({},b.headers),f,g,h,c=T({},c.common,c[G(b.method)]);a:for(f in c){g=G(f);for(h in d)if(G(h)===g)continue a;d[f]=c[f]}return e(d,na(b))}(b);f.method=ub(f.method);f.paramSerializer=F(f.paramSerializer)?l.get(f.paramSerializer):f.paramSerializer;var g=[function(b){var d=b.headers,e=hd(b.data,gd(d),v,b.transformRequest);x(e)&&n(d,function(a,b){"content-type"===G(b)&&delete d[b]});x(b.withCredentials)&&!x(a.withCredentials)&&(b.withCredentials=a.withCredentials);
-return r(b,e).then(c,c)},v],h=k.when(f);for(n(K,function(a){(a.request||a.requestError)&&g.unshift(a.request,a.requestError);(a.response||a.responseError)&&g.push(a.response,a.responseError)});g.length;){b=g.shift();var m=g.shift(),h=h.then(b,m)}d?(h.success=function(a){Sa(a,"fn");h.then(function(b){a(b.data,b.status,b.headers,f)});return h},h.error=function(a){Sa(a,"fn");h.then(null,function(b){a(b.data,b.status,b.headers,f)});return h}):(h.success=id("success"),h.error=id("error"));return h}function r(c,
-d){function g(a,c,d,e){function f(){l(c,a,d,e)}K&&(200<=a&&300>a?K.put(S,[a,c,fd(d),e]):K.remove(S));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function l(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?A.resolve:A.reject)({data:a,status:b,headers:gd(d),config:c,statusText:e})}function r(a){l(a.data,a.status,na(a.headers()),a.statusText)}function z(){var a=m.pendingRequests.indexOf(c);-1!==a&&m.pendingRequests.splice(a,1)}var A=k.defer(),Q=A.promise,K,M,P=c.headers,S=s(c.url,c.paramSerializer(c.params));
-m.pendingRequests.push(c);Q.then(z,z);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(K=E(c.cache)?c.cache:E(a.cache)?a.cache:I);K&&(M=K.get(S),y(M)?M&&D(M.then)?M.then(r,r):L(M)?l(M[1],M[0],na(M[2]),M[3]):l(M,200,{},"OK"):K.put(S,Q));x(M)&&((M=jd(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:v)&&(P[c.xsrfHeaderName||a.xsrfHeaderName]=M),e(c.method,S,d,g,P,c.timeout,c.withCredentials,c.responseType));return Q}function s(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);
-return a}var I=g("$http");a.paramSerializer=F(a.paramSerializer)?l.get(a.paramSerializer):a.paramSerializer;var K=[];n(c,function(a){K.unshift(F(a)?l.get(a):l.invoke(a))});m.pendingRequests=[];(function(a){n(arguments,function(a){m[a]=function(b,c){return m(T({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){n(arguments,function(a){m[a]=function(b,c,d){return m(T({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");m.defaults=a;return m}]}function qf(){this.$get=
-function(){return function(){return new O.XMLHttpRequest}}}function pf(){this.$get=["$browser","$window","$document","$xhrFactory",function(a,b,d,c){return fg(a,c,a.defer,b.angular.callbacks,d[0])}]}function fg(a,b,d,c,e){function f(a,b,d){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,I="unknown";a&&("load"!==a.type||c[b].called||(a={type:"error"}),
-I=a.type,g="error"===a.type?404:200);d&&d(g,I)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,k,l,m,r,s,I){function K(){w&&w();u&&u.abort()}function t(b,c,e,f,g){y(z)&&d.cancel(z);w=u=null;b(c,e,f,g);a.$$completeOutstandingRequest(B)}a.$$incOutstandingRequestCount();h=h||a.url();if("jsonp"==G(e)){var p="_"+(c.counter++).toString(36);c[p]=function(a){c[p].data=a;c[p].called=!0};var w=f(h.replace("JSON_CALLBACK","angular.callbacks."+
-p),p,function(a,b){t(l,a,c[p].data,"",b);c[p]=B})}else{var u=b(e,h);u.open(e,h,!0);n(m,function(a,b){y(a)&&u.setRequestHeader(b,a)});u.onload=function(){var a=u.statusText||"",b="response"in u?u.response:u.responseText,c=1223===u.status?204:u.status;0===c&&(c=b?200:"file"==za(h).protocol?404:0);t(l,c,b,u.getAllResponseHeaders(),a)};e=function(){t(l,-1,null,null,"")};u.onerror=e;u.onabort=e;s&&(u.withCredentials=!0);if(I)try{u.responseType=I}catch(la){if("json"!==I)throw la;}u.send(x(k)?null:k)}if(0<
-r)var z=d(K,r);else r&&D(r.then)&&r.then(K)}}function kf(){var a="{{",b="}}";this.startSymbol=function(b){return b?(a=b,this):a};this.endSymbol=function(a){return a?(b=a,this):b};this.$get=["$parse","$exceptionHandler","$sce",function(d,c,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(r,a).replace(s,b)}function h(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function k(f,k,r,p){function s(a){try{var b=a;a=r?e.getTrusted(r,b):e.valueOf(b);var d;if(p&&!y(a))d=
-a;else if(null==a)d="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=eb(a)}d=a}return d}catch(g){c(Ka.interr(f,g))}}if(!f.length||-1===f.indexOf(a)){var u;k||(k=g(f),u=ba(k),u.exp=f,u.expressions=[],u.$$watchDelegate=h);return u}p=!!p;var n,z,A=0,Q=[],$=[];u=f.length;for(var M=[],P=[];A<u;)if(-1!=(n=f.indexOf(a,A))&&-1!=(z=f.indexOf(b,n+l)))A!==n&&M.push(g(f.substring(A,n))),A=f.substring(n+l,z),Q.push(A),$.push(d(A,s)),A=z+m,P.push(M.length),M.push("");else{A!==u&&
-M.push(g(f.substring(A)));break}r&&1<M.length&&Ka.throwNoconcat(f);if(!k||Q.length){var S=function(a){for(var b=0,c=Q.length;b<c;b++){if(p&&x(a[b]))return;M[P[b]]=a[b]}return M.join("")};return T(function(a){var b=0,d=Q.length,e=Array(d);try{for(;b<d;b++)e[b]=$[b](a);return S(e)}catch(g){c(Ka.interr(f,g))}},{exp:f,expressions:Q,$$watchDelegate:function(a,b){var c;return a.$watchGroup($,function(d,e){var f=S(d);D(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=a.length,m=b.length,r=new RegExp(a.replace(/./g,
-f),"g"),s=new RegExp(b.replace(/./g,f),"g");k.startSymbol=function(){return a};k.endSymbol=function(){return b};return k}]}function lf(){this.$get=["$rootScope","$window","$q","$$q","$browser",function(a,b,d,c,e){function f(f,k,l,m){function r(){s?f.apply(null,I):f(p)}var s=4<arguments.length,I=s?wa.call(arguments,4):[],K=b.setInterval,t=b.clearInterval,p=0,w=y(m)&&!m,u=(w?c:d).defer(),n=u.promise;l=y(l)?l:0;n.$$intervalId=K(function(){w?e.defer(r):a.$evalAsync(r);u.notify(p++);0<l&&p>=l&&(u.resolve(p),
-t(n.$$intervalId),delete g[n.$$intervalId]);w||a.$apply()},k);g[n.$$intervalId]=u;return n}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete g[a.$$intervalId],!0):!1};return f}]}function ec(a){a=a.split("/");for(var b=a.length;b--;)a[b]=qb(a[b]);return a.join("/")}function kd(a,b){var d=za(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=ca(d.port)||gg[d.protocol]||null}function ld(a,b){var d="/"!==a.charAt(0);
-d&&(a="/"+a);var c=za(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=zc(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function pa(a,b){if(0===b.indexOf(a))return b.substr(a.length)}function Ia(a){var b=a.indexOf("#");return-1==b?a:a.substr(0,b)}function kb(a){return a.replace(/(#.+)|#$/,"$1")}function fc(a,b,d){this.$$html5=!0;d=d||"";kd(a,this);this.$$parse=function(a){var d=pa(b,
-a);if(!F(d))throw Gb("ipthprfx",a,b);ld(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Ub(this.$$search),d=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ec(this.$$path)+(a?"?"+a:"")+d;this.$$absUrl=b+this.$$url.substr(1)};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;y(f=pa(a,c))?(g=f,g=y(f=pa(d,f))?b+(pa("/",f)||f):a+g):y(f=pa(b,c))?g=b+f:b==c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function gc(a,b,d){kd(a,this);
-this.$$parse=function(c){var e=pa(a,c)||pa(b,c),f;x(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",x(e)&&(a=c,this.replace())):(f=pa(d,e),x(f)&&(f=e));ld(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=Ub(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ec(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"")};this.$$parseLinkUrl=
-function(b,d){return Ia(a)==Ia(b)?(this.$$parse(b),!0):!1}}function md(a,b,d){this.$$html5=!0;gc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a==Ia(c)?f=c:(g=pa(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Ub(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ec(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url}}function Hb(a){return function(){return this[a]}}function nd(a,
-b){return function(d){if(x(d))return this[a];this[a]=b(d);this.$$compose();return this}}function rf(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return y(b)?(a=b,this):a};this.html5Mode=function(a){return Na(a)?(b.enabled=a,this):E(a)?(Na(a.enabled)&&(b.enabled=a.enabled),Na(a.requireBase)&&(b.requireBase=a.requireBase),Na(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(d,
-c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state=f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,b)}var l,m;m=c.baseHref();var r=c.url(),s;if(b.enabled){if(!m&&b.requireBase)throw Gb("nobase");s=r.substring(0,r.indexOf("/",r.indexOf("//")+2))+(m||"/");m=e.history?fc:md}else s=Ia(r),m=gc;var I=s.substr(0,Ia(s).lastIndexOf("/")+1);l=new m(s,I,"#"+a);l.$$parseLinkUrl(r,r);l.$$state=c.state();
-var n=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=C(a.target);"a"!==ra(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),k=e.attr("href")||e.attr("xlink:href");E(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=za(h.animVal).href);n.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(h,k)||(a.preventDefault(),l.absUrl()!=c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=
-!0))}});kb(l.absUrl())!=kb(r)&&c.url(l.absUrl(),!0);var t=!0;c.onUrlChange(function(a,b){x(pa(I,a))?g.location.href=a:(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=kb(a);l.$$parse(a);l.$$state=b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=e,h(c,!1,e)):(t=!1,k(c,e)))}),d.$$phase||d.$digest())});d.$watch(function(){var a=kb(c.url()),b=kb(l.absUrl()),f=c.state(),g=l.$$replace,m=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(t||
-m)t=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(m&&h(b,g,f===l.$$state?null:l.$$state),k(a,f)))});l.$$replace=!1});return l}]}function sf(){var a=!0,b=this;this.debugEnabled=function(b){return y(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&
-(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||B;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];n(arguments,function(b){a.push(c(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Xa(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===
-a||"__proto__"===a)throw ka("isecfld",b);return a}function hg(a){return a+""}function Aa(a,b){if(a){if(a.constructor===a)throw ka("isecfn",b);if(a.window===a)throw ka("isecwindow",b);if(a.children&&(a.nodeName||a.prop&&a.attr&&a.find))throw ka("isecdom",b);if(a===Object)throw ka("isecobj",b);}return a}function od(a,b){if(a){if(a.constructor===a)throw ka("isecfn",b);if(a===ig||a===jg||a===kg)throw ka("isecff",b);}}function Ib(a,b){if(a&&(a===(0).constructor||a===(!1).constructor||a==="".constructor||
-a==={}.constructor||a===[].constructor||a===Function.constructor))throw ka("isecaf",b);}function lg(a,b){return"undefined"!==typeof a?a:b}function pd(a,b){return"undefined"===typeof a?b:"undefined"===typeof b?a:a+b}function R(a,b){var d,c;switch(a.type){case q.Program:d=!0;n(a.body,function(a){R(a.expression,b);d=d&&a.expression.constant});a.constant=d;break;case q.Literal:a.constant=!0;a.toWatch=[];break;case q.UnaryExpression:R(a.argument,b);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;
-break;case q.BinaryExpression:R(a.left,b);R(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case q.LogicalExpression:R(a.left,b);R(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case q.ConditionalExpression:R(a.test,b);R(a.alternate,b);R(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case q.Identifier:a.constant=!1;a.toWatch=
-[a];break;case q.MemberExpression:R(a.object,b);a.computed&&R(a.property,b);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=[a];break;case q.CallExpression:d=a.filter?!b(a.callee.name).$stateful:!1;c=[];n(a.arguments,function(a){R(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=a.filter&&!b(a.callee.name).$stateful?c:[a];break;case q.AssignmentExpression:R(a.left,b);R(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];
-break;case q.ArrayExpression:d=!0;c=[];n(a.elements,function(a){R(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=c;break;case q.ObjectExpression:d=!0;c=[];n(a.properties,function(a){R(a.value,b);d=d&&a.value.constant;a.value.constant||c.push.apply(c,a.value.toWatch)});a.constant=d;a.toWatch=c;break;case q.ThisExpression:a.constant=!1;a.toWatch=[];break;case q.LocalsExpression:a.constant=!1,a.toWatch=[]}}function qd(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;
-return 1!==b.length?b:b[0]!==a?b:v}}function rd(a){return a.type===q.Identifier||a.type===q.MemberExpression}function sd(a){if(1===a.body.length&&rd(a.body[0].expression))return{type:q.AssignmentExpression,left:a.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function td(a){return 0===a.body.length||1===a.body.length&&(a.body[0].expression.type===q.Literal||a.body[0].expression.type===q.ArrayExpression||a.body[0].expression.type===q.ObjectExpression)}function ud(a,b){this.astBuilder=
-a;this.$filter=b}function vd(a,b){this.astBuilder=a;this.$filter=b}function Jb(a){return"constructor"==a}function hc(a){return D(a.valueOf)?a.valueOf():mg.call(a)}function tf(){var a=Z(),b=Z();this.$get=["$filter",function(d){function c(c,f,r){var u,n,z;r=r||K;switch(typeof c){case "string":z=c=c.trim();var A=r?b:a;u=A[z];if(!u){":"===c.charAt(0)&&":"===c.charAt(1)&&(n=!0,c=c.substring(2));u=r?I:s;var Q=new ic(u);u=(new jc(Q,d,u)).parse(c);u.constant?u.$$watchDelegate=l:n?u.$$watchDelegate=u.literal?
-k:h:u.inputs&&(u.$$watchDelegate=g);r&&(u=e(u));A[z]=u}return m(u,f);case "function":return m(c,f);default:return m(B,f)}}function e(a){function b(c,d,e,f){var g=K;K=!0;try{return a(c,d,e,f)}finally{K=g}}if(!a)return a;b.$$watchDelegate=a.$$watchDelegate;b.assign=e(a.assign);b.constant=a.constant;b.literal=a.literal;for(var c=0;a.inputs&&c<a.inputs.length;++c)a.inputs[c]=e(a.inputs[c]);b.inputs=a.inputs;return b}function f(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=hc(a),"object"===
-typeof a)?!1:a===b||a!==a&&b!==b}function g(a,b,c,d,e){var g=d.inputs,h;if(1===g.length){var k=f,g=g[0];return a.$watch(function(a){var b=g(a);f(b,k)||(h=d(a,v,v,[b]),k=b&&hc(b));return h},b,c,e)}for(var l=[],m=[],r=0,s=g.length;r<s;r++)l[r]=f,m[r]=null;return a.$watch(function(a){for(var b=!1,c=0,e=g.length;c<e;c++){var k=g[c](a);if(b||(b=!f(k,l[c])))m[c]=k,l[c]=k&&hc(k)}b&&(h=d(a,v,v,m));return h},b,c,e)}function h(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;
-D(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function k(a,b,c,d){function e(a){var b=!0;n(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;D(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function l(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function m(a,b){if(!b)return a;var c=a.$$watchDelegate,d=!1,c=c!==k&&c!==h?function(c,e,f,g){f=d&&g?g[0]:a(c,e,f,g);return b(f,
-c,e)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return y(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==g?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=g,d=!a.inputs,c.inputs=a.inputs?a.inputs:[a]);return c}var r=Ea().noUnsafeEval,s={csp:r,expensiveChecks:!1},I={csp:r,expensiveChecks:!0},K=!1;c.$$runningExpensiveChecks=function(){return K};return c}]}function vf(){this.$get=["$rootScope","$exceptionHandler",function(a,b){return wd(function(b){a.$evalAsync(b)},b)}]}function wf(){this.$get=
-["$browser","$exceptionHandler",function(a,b){return wd(function(b){a.defer(b)},b)}]}function wd(a,b){function d(){this.$$state={status:0}}function c(a,b){return function(c){b.call(a,c)}}function e(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,a(function(){var a,d,e;e=c.pending;c.processScheduled=!1;c.pending=v;for(var f=0,g=e.length;f<g;++f){d=e[f][0];a=e[f][c.status];try{D(a)?d.resolve(a(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),b(h)}}}))}function f(){this.promise=
-new d}var g=H("$q",TypeError);T(d.prototype,{then:function(a,b,c){if(x(a)&&x(b)&&x(c))return this;var d=new f;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&e(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}});T(f.prototype,{resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(g("qcycle",
-a)):this.$$resolve(a))},$$resolve:function(a){function d(a){k||(k=!0,h.$$resolve(a))}function f(a){k||(k=!0,h.$$reject(a))}var g,h=this,k=!1;try{if(E(a)||D(a))g=a&&a.then;D(g)?(this.promise.$$state.status=-1,g.call(a,d,f,c(this,this.notify))):(this.promise.$$state.value=a,this.promise.$$state.status=1,e(this.promise.$$state))}catch(l){f(l),b(l)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;e(this.promise.$$state)},
-notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;f<g;f++){e=d[f][0];a=d[f][3];try{e.notify(D(a)?a(c):c)}catch(h){b(h)}}})}});var h=function(a,b){var c=new f;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{D(c)&&(d=c())}catch(e){return h(e,!1)}return d&&D(d.then)?d.then(function(){return h(a,b)},function(a){return h(a,!1)}):h(a,b)},l=function(a,b,c,d){var e=new f;e.resolve(a);return e.promise.then(b,
-c,d)},m=function(a){if(!D(a))throw g("norslvr",a);var b=new f;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};m.prototype=d.prototype;m.defer=function(){var a=new f;a.resolve=c(a,a.resolve);a.reject=c(a,a.reject);a.notify=c(a,a.notify);return a};m.reject=function(a){var b=new f;b.reject(a);return b.promise};m.when=l;m.resolve=l;m.all=function(a){var b=new f,c=0,d=L(a)?[]:{};n(a,function(a,e){c++;l(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||
-b.reject(a)})});0===c&&b.resolve(d);return b.promise};return m}function Ff(){this.$get=["$window","$timeout",function(a,b){var d=a.requestAnimationFrame||a.webkitRequestAnimationFrame,c=a.cancelAnimationFrame||a.webkitCancelAnimationFrame||a.webkitCancelRequestAnimationFrame,e=!!d,f=e?function(a){var b=d(a);return function(){c(b)}}:function(a){var c=b(a,16.66,!1);return function(){b.cancel(c)}};f.supported=e;return f}]}function uf(){function a(a){function b(){this.$$watchers=this.$$nextSibling=this.$$childHead=
-this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++pb;this.$$ChildScope=null}b.prototype=a;return b}var b=10,d=H("$rootScope"),c=null,e=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$exceptionHandler","$parse","$browser",function(f,g,h){function k(a){a.currentScope.$$destroyed=!0}function l(a){9===xa&&(a.$$childHead&&l(a.$$childHead),a.$$nextSibling&&l(a.$$nextSibling));a.$parent=a.$$nextSibling=a.$$prevSibling=a.$$childHead=
-a.$$childTail=a.$root=a.$$watchers=null}function m(){this.$id=++pb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function r(a){if(w.$$phase)throw d("inprog",w.$$phase);w.$$phase=a}function s(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function I(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&
-delete a.$$listenerCount[c];while(a=a.$parent)}function q(){}function t(){for(;z.length;)try{z.shift()()}catch(a){f(a)}e=null}function p(){null===e&&(e=h.defer(function(){w.$apply(t)}))}m.prototype={constructor:m,$new:function(b,c){var d;c=c||this;b?(d=new m,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=a(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(b||c!=this)&&d.$on("$destroy",
-k);return d},$watch:function(a,b,d,e){var f=g(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,d,f,a);var h=this,k=h.$$watchers,l={fn:b,last:q,get:f,exp:e||a,eq:!!d};c=null;D(b)||(l.fn=B);k||(k=h.$$watchers=[]);k.unshift(l);s(this,1);return function(){0<=cb(k,l)&&s(h,-1);c=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=
-!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});n(a,function(a,b){var k=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!x(e)){if(E(e))if(Ca(e))for(f!==r&&(f=r,u=f.length=0,l++),a=e.length,u!==a&&(l++,f.length=u=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==s&&(f=s={},u=0,l++);a=0;for(b in e)sa.call(e,
-b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(u++,f[b]=g,l++));if(u>a)for(b in l++,f)sa.call(e,b)||(u--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1<b.length,l=0,m=g(a,c),r=[],s={},p=!0,u=0;return this.$watch(m,function(){p?(p=!1,b(e,e,d)):b(e,h,d);if(k)if(E(e))if(Ca(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)sa.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var a,g,k,l,m,s,p,n,I=b,z,y=[],x,C;
-r("$digest");h.$$checkUrlChange();this===w&&null!==e&&(h.defer.cancel(e),t());c=null;do{n=!1;for(z=this;u.length;){try{C=u.shift(),C.scope.$eval(C.expression,C.locals)}catch(B){f(B)}c=null}a:do{if(s=z.$$watchers)for(p=s.length;p--;)try{if(a=s[p])if(m=a.get,(g=m(z))!==(k=a.last)&&!(a.eq?oa(g,k):"number"===typeof g&&"number"===typeof k&&isNaN(g)&&isNaN(k)))n=!0,c=a,a.last=a.eq?Oa(g,null):g,l=a.fn,l(g,k===q?g:k,z),5>I&&(x=4-I,y[x]||(y[x]=[]),y[x].push({msg:D(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):
-a.exp,newVal:g,oldVal:k}));else if(a===c){n=!1;break a}}catch(E){f(E)}if(!(s=z.$$watchersCount&&z.$$childHead||z!==this&&z.$$nextSibling))for(;z!==this&&!(s=z.$$nextSibling);)z=z.$parent}while(z=s);if((n||u.length)&&!I--)throw w.$$phase=null,d("infdig",b,y);}while(n||u.length);for(w.$$phase=null;v.length;)try{v.shift()()}catch(H){f(H)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===w&&h.$$applicationDestroyed();s(this,-this.$$watchersCount);
-for(var b in this.$$listenerCount)I(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=B;this.$on=this.$watch=this.$watchGroup=function(){return B};this.$$listeners={};this.$$nextSibling=
-null;l(this)}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){w.$$phase||u.length||h.defer(function(){u.length&&w.$digest()});u.push({scope:this,expression:g(a),locals:b})},$$postDigest:function(a){v.push(a)},$apply:function(a){try{r("$apply");try{return this.$eval(a)}finally{w.$$phase=null}}catch(b){f(b)}finally{try{w.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&z.push(b);a=g(a);p()},$on:function(a,b){var c=this.$$listeners[a];
-c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,I(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=db([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,
-k)}catch(r){f(r)}else d.splice(l,1),l--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var g=db([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,g)}catch(l){f(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&
-c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var w=new m,u=w.$$asyncQueue=[],v=w.$$postDigestQueue=[],z=w.$$applyAsyncQueue=[];return w}]}function ne(){var a=/^\s*(https?|ftp|mailto|tel|file):/,b=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.imgSrcSanitizationWhitelist=function(a){return y(a)?(b=a,this):b};this.$get=function(){return function(d,c){var e=
-c?b:a,f;f=za(d).href;return""===f||f.match(e)?d:"unsafe:"+f}}}function ng(a){if("self"===a)return a;if(F(a)){if(-1<a.indexOf("***"))throw Ba("iwcard",a);a=xd(a).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+a+"$")}if($a(a))return new RegExp("^"+a.source+"$");throw Ba("imatcher");}function yd(a){var b=[];y(a)&&n(a,function(a){b.push(ng(a))});return b}function yf(){this.SCE_CONTEXTS=qa;var a=["self"],b=[];this.resourceUrlWhitelist=function(b){arguments.length&&(a=yd(b));return a};
-this.resourceUrlBlacklist=function(a){arguments.length&&(b=yd(a));return b};this.$get=["$injector",function(d){function c(a,b){return"self"===a?jd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Ba("unsafe");};d.has("$sanitize")&&(f=d.get("$sanitize"));
-var g=e(),h={};h[qa.HTML]=e(g);h[qa.CSS]=e(g);h[qa.URL]=e(g);h[qa.JS]=e(g);h[qa.RESOURCE_URL]=e(h[qa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ba("icontext",a,b);if(null===b||x(b)||""===b)return b;if("string"!==typeof b)throw Ba("itype",a);return new c(b)},getTrusted:function(d,e){if(null===e||x(e)||""===e)return e;var g=h.hasOwnProperty(d)?h[d]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(d===qa.RESOURCE_URL){var g=za(e.toString()),r,s,n=!1;
-r=0;for(s=a.length;r<s;r++)if(c(a[r],g)){n=!0;break}if(n)for(r=0,s=b.length;r<s;r++)if(c(b[r],g)){n=!1;break}if(n)return e;throw Ba("insecurl",e.toString());}if(d===qa.HTML)return f(e);throw Ba("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function xf(){var a=!0;this.enabled=function(b){arguments.length&&(a=!!b);return a};this.$get=["$parse","$sceDelegate",function(b,d){if(a&&8>xa)throw Ba("iequirks");var c=na(qa);c.isEnabled=function(){return a};c.trustAs=d.trustAs;
-c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=ab);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs,f=c.getTrusted,g=c.trustAs;n(qa,function(a,b){var d=G(b);c[gb("parse_as_"+d)]=function(b){return e(a,b)};c[gb("get_trusted_"+d)]=function(b){return f(a,b)};c[gb("trust_as_"+d)]=function(b){return g(a,b)}});return c}]}function zf(){this.$get=["$window","$document",
-function(a,b){var d={},c=ca((/android (\d+)/.exec(G((a.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((a.navigator||{}).userAgent),f=b[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,k=f.body&&f.body.style,l=!1,m=!1;if(k){for(var r in k)if(l=h.exec(r)){g=l[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||g+"Transition"in k);m=!!("animation"in k||g+"Animation"in k);!c||l&&m||(l=F(k.webkitTransition),m=F(k.webkitAnimation))}return{history:!(!a.history||
-!a.history.pushState||4>c||e),hasEvent:function(a){if("input"===a&&11>=xa)return!1;if(x(d[a])){var b=f.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ea(),vendorPrefix:g,transitions:l,animations:m,android:c}}]}function Bf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$templateCache","$http","$q","$sce",function(b,d,c,e){function f(g,h){f.totalPendingRequests++;F(g)&&b.get(g)||(g=e.getTrustedResourceUrl(g));var k=d.defaults&&d.defaults.transformResponse;L(k)?k=k.filter(function(a){return a!==
-cc}):k===cc&&(k=null);return d.get(g,T({cache:b,transformResponse:k},a))["finally"](function(){f.totalPendingRequests--}).then(function(a){b.put(g,a.data);return a.data},function(a){if(!h)throw ja("tpload",g,a.status,a.statusText);return c.reject(a)})}f.totalPendingRequests=0;return f}]}function Cf(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];n(a,function(a){var c=ia.element(a).data("$binding");
-c&&n(c,function(c){d?(new RegExp("(^|\\s)"+xd(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!=c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var k=a.querySelectorAll("["+g[h]+"model"+(d?"=":"*=")+'"'+b+'"]');if(k.length)return k}},getLocation:function(){return d.url()},setLocation:function(b){b!==d.url()&&(d.url(b),a.$digest())},whenStable:function(a){b.notifyWhenNoOutstandingRequests(a)}}}]}function Df(){this.$get=["$rootScope",
-"$browser","$q","$$q","$exceptionHandler",function(a,b,d,c,e){function f(f,k,l){D(f)||(l=k,k=f,f=B);var m=wa.call(arguments,3),r=y(l)&&!l,s=(r?c:d).defer(),n=s.promise,q;q=b.defer(function(){try{s.resolve(f.apply(null,m))}catch(b){s.reject(b),e(b)}finally{delete g[n.$$timeoutId]}r||a.$apply()},k);n.$$timeoutId=q;g[q]=s;return n}var g={};f.cancel=function(a){return a&&a.$$timeoutId in g?(g[a.$$timeoutId].reject("canceled"),delete g[a.$$timeoutId],b.defer.cancel(a.$$timeoutId)):!1};return f}]}function za(a){xa&&
-(Y.setAttribute("href",a),a=Y.href);Y.setAttribute("href",a);return{href:Y.href,protocol:Y.protocol?Y.protocol.replace(/:$/,""):"",host:Y.host,search:Y.search?Y.search.replace(/^\?/,""):"",hash:Y.hash?Y.hash.replace(/^#/,""):"",hostname:Y.hostname,port:Y.port,pathname:"/"===Y.pathname.charAt(0)?Y.pathname:"/"+Y.pathname}}function jd(a){a=F(a)?za(a):a;return a.protocol===zd.protocol&&a.host===zd.host}function Ef(){this.$get=ba(O)}function Ad(a){function b(a){try{return decodeURIComponent(a)}catch(b){return a}}
-var d=a[0]||{},c={},e="";return function(){var a,g,h,k,l;a=d.cookie||"";if(a!==e)for(e=a,a=e.split("; "),c={},h=0;h<a.length;h++)g=a[h],k=g.indexOf("="),0<k&&(l=b(g.substring(0,k)),x(c[l])&&(c[l]=b(g.substring(k+1))));return c}}function If(){this.$get=Ad}function Lc(a){function b(d,c){if(E(d)){var e={};n(d,function(a,c){e[c]=b(c,a)});return e}return a.factory(d+"Filter",c)}this.register=b;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];b("currency",Bd);b("date",Cd);
-b("filter",og);b("json",pg);b("limitTo",qg);b("lowercase",rg);b("number",Dd);b("orderBy",Ed);b("uppercase",sg)}function og(){return function(a,b,d){if(!Ca(a)){if(null==a)return a;throw H("filter")("notarray",a);}var c;switch(kc(b)){case "function":break;case "boolean":case "null":case "number":case "string":c=!0;case "object":b=tg(b,d,c);break;default:return a}return Array.prototype.filter.call(a,b)}}function tg(a,b,d){var c=E(a)&&"$"in a;!0===b?b=oa:D(b)||(b=function(a,b){if(x(a))return!1;if(null===
-a||null===b)return a===b;if(E(b)||E(a)&&!tc(a))return!1;a=G(""+a);b=G(""+b);return-1!==a.indexOf(b)});return function(e){return c&&!E(e)?La(e,a.$,b,!1):La(e,a,b,d)}}function La(a,b,d,c,e){var f=kc(a),g=kc(b);if("string"===g&&"!"===b.charAt(0))return!La(a,b.substring(1),d,c);if(L(a))return a.some(function(a){return La(a,b,d,c)});switch(f){case "object":var h;if(c){for(h in a)if("$"!==h.charAt(0)&&La(a[h],b,d,!0))return!0;return e?!1:La(a,b,d,!1)}if("object"===g){for(h in b)if(e=b[h],!D(e)&&!x(e)&&
-(f="$"===h,!La(f?a:a[h],e,d,f,f)))return!1;return!0}return d(a,b);case "function":return!1;default:return d(a,b)}}function kc(a){return null===a?"null":typeof a}function Bd(a){var b=a.NUMBER_FORMATS;return function(a,c,e){x(c)&&(c=b.CURRENCY_SYM);x(e)&&(e=b.PATTERNS[1].maxFrac);return null==a?a:Fd(a,b.PATTERNS[1],b.GROUP_SEP,b.DECIMAL_SEP,e).replace(/\u00A4/g,c)}}function Dd(a){var b=a.NUMBER_FORMATS;return function(a,c){return null==a?a:Fd(a,b.PATTERNS[0],b.GROUP_SEP,b.DECIMAL_SEP,c)}}function ug(a){var b=
-0,d,c,e,f,g;-1<(c=a.indexOf(Gd))&&(a=a.replace(Gd,""));0<(e=a.search(/e/i))?(0>c&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)==lc;e++);if(e==(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)==lc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Hd&&(d=d.splice(0,Hd-1),b=c-1,c=1);return{d:d,e:b,i:c}}function vg(a,b,d,c){var e=a.d,f=e.length-a.i;b=x(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0<d)e.splice(d);else{a.i=1;e.length=d=b+1;for(var g=0;g<d;g++)e[g]=
-0}for(5<=c&&e[d-1]++;f<b;f++)e.push(0);if(b=e.reduceRight(function(a,b,c,d){b+=a;d[c]=b%10;return Math.floor(b/10)},0))e.unshift(b),a.i++}function Fd(a,b,d,c,e){if(!F(a)&&!N(a)||isNaN(a))return"";var f=!isFinite(a),g=!1,h=Math.abs(a)+"",k="";if(f)k="\u221e";else{g=ug(h);vg(g,e,b.minFrac,b.maxFrac);k=g.d;h=g.i;e=g.e;f=[];for(g=k.reduce(function(a,b){return a&&!b},!0);0>h;)k.unshift(0),h++;0<h?f=k.splice(h):(f=k,k=[0]);h=[];for(k.length>b.lgSize&&h.unshift(k.splice(-b.lgSize).join(""));k.length>b.gSize;)h.unshift(k.splice(-b.gSize).join(""));
-k.length&&h.unshift(k.join(""));k=h.join(d);f.length&&(k+=c+f.join(""));e&&(k+="e+"+e)}return 0>a&&!g?b.negPre+k+b.negSuf:b.posPre+k+b.posSuf}function Kb(a,b,d){var c="";0>a&&(c="-",a=-a);for(a=""+a;a.length<b;)a=lc+a;d&&(a=a.substr(a.length-b));return c+a}function aa(a,b,d,c){d=d||0;return function(e){e=e["get"+a]();if(0<d||e>-d)e+=d;0===e&&-12==d&&(e=12);return Kb(e,b,c)}}function Lb(a,b){return function(d,c){var e=d["get"+a](),f=ub(b?"SHORT"+a:a);return c[f][e]}}function Id(a){var b=(new Date(a,
-0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Jd(a){return function(b){var d=Id(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Kb(b,a)}}function mc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Cd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=ca(b[9]+b[10]),g=ca(b[9]+b[11]));h.call(a,ca(b[1]),ca(b[2])-
-1,ca(b[3]));f=ca(b[4]||0)-f;g=ca(b[5]||0)-g;h=ca(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;F(c)&&(c=wg.test(c)?ca(c):b(c));N(c)&&(c=new Date(c));if(!V(c)||!isFinite(c.getTime()))return c;for(;d;)(l=xg.exec(d))?(h=db(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();
-f&&(m=xc(f,m),c=Tb(c,f,!0));n(h,function(b){k=yg[b];g+=k?k(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function pg(){return function(a,b){x(b)&&(b=2);return eb(a,b)}}function qg(){return function(a,b,d){b=Infinity===Math.abs(Number(b))?Number(b):ca(b);if(isNaN(b))return a;N(a)&&(a=a.toString());if(!L(a)&&!F(a))return a;d=!d||isNaN(d)?0:ca(d);d=0>d?Math.max(0,a.length+d):d;return 0<=b?a.slice(d,d+b):0===d?a.slice(b,a.length):a.slice(Math.max(0,d+b),
-d)}}function Ed(a){function b(b,d){d=d?-1:1;return b.map(function(b){var c=1,h=ab;if(D(b))h=b;else if(F(b)){if("+"==b.charAt(0)||"-"==b.charAt(0))c="-"==b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(h=a(b),h.constant))var k=h(),h=function(a){return a[k]}}return{get:h,descending:c*d}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(a,e,f){if(null==a)return a;if(!Ca(a))throw H("orderBy")("notarray",a);L(e)||(e=[e]);0===e.length&&
-(e=["+"]);var g=b(e,f);g.push({get:function(){return{}},descending:f?-1:1});a=Array.prototype.map.call(a,function(a,b){return{value:a,predicateValues:g.map(function(c){var e=c.get(a);c=typeof e;if(null===e)c="string",e="null";else if("string"===c)e=e.toLowerCase();else if("object"===c)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),d(e)))break a;if(tc(e)&&(e=e.toString(),d(e)))break a;e=b}return{value:e,type:c}})}});a.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],
-f=b.predicateValues[d],n=0;c.type===f.type?c.value!==f.value&&(n=c.value<f.value?-1:1):n=c.type<f.type?-1:1;if(c=n*g[d].descending)break}return c});return a=a.map(function(a){return a.value})}}function Ma(a){D(a)&&(a={link:a});a.restrict=a.restrict||"AC";return ba(a)}function Kd(a,b,d,c,e){var f=this,g=[];f.$error={};f.$$success={};f.$pending=v;f.$name=e(b.name||b.ngForm||"")(d);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;f.$$parentForm=Mb;f.$rollbackViewValue=function(){n(g,
-function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){n(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ta(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a);a.$$parentForm=f};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];n(f.$pending,function(b,c){f.$setValidity(c,null,a)});n(f.$error,function(b,c){f.$setValidity(c,null,a)});n(f.$$success,function(b,c){f.$setValidity(c,
-null,a)});cb(g,a);a.$$parentForm=Mb};Ld({ctrl:this,$element:a,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(cb(d,c),0===d.length&&delete a[b])},$animate:c});f.$setDirty=function(){c.removeClass(a,Ya);c.addClass(a,Nb);f.$dirty=!0;f.$pristine=!1;f.$$parentForm.$setDirty()};f.$setPristine=function(){c.setClass(a,Ya,Nb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;n(g,function(a){a.$setPristine()})};f.$setUntouched=function(){n(g,
-function(a){a.$setUntouched()})};f.$setSubmitted=function(){c.addClass(a,"ng-submitted");f.$submitted=!0;f.$$parentForm.$setSubmitted()}}function nc(a){a.$formatters.push(function(b){return a.$isEmpty(b)?b:b.toString()})}function lb(a,b,d,c,e,f){var g=G(b[0].type);if(!e.android){var h=!1;b.on("compositionstart",function(a){h=!0});b.on("compositionend",function(){h=!1;k()})}var k=function(a){l&&(f.defer.cancel(l),l=null);if(!h){var e=b.val();a=a&&a.type;"password"===g||d.ngTrim&&"false"===d.ngTrim||
-(e=X(e));(c.$viewValue!==e||""===e&&c.$$hasNativeValidators)&&c.$setViewValue(e,a)}};if(e.hasEvent("input"))b.on("input",k);else{var l,m=function(a,b,c){l||(l=f.defer(function(){l=null;b&&b.value===c||k(a)}))};b.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",m)}b.on("change",k);c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Ob(a,b){return function(d,c){var e,
-f;if(V(d))return d;if(F(d)){'"'==d.charAt(0)&&'"'==d.charAt(d.length-1)&&(d=d.substring(1,d.length-1));if(zg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},n(e,function(a,c){c<b.length&&(f[b[c]]=+a)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function mb(a,b,d,c){return function(e,
-f,g,h,k,l,m){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return y(a)&&!V(a)?d(a)||v:a}Md(e,f,g,h);lb(e,f,g,h,k,l);var n=h&&h.$options&&h.$options.timezone,q;h.$$parserName=a;h.$parsers.push(function(a){return h.$isEmpty(a)?null:b.test(a)?(a=d(a,q),n&&(a=Tb(a,n)),a):v});h.$formatters.push(function(a){if(a&&!V(a))throw nb("datefmt",a);if(r(a))return(q=a)&&n&&(q=Tb(q,n,!0)),m("date")(a,c,n);q=null;return""});if(y(g.min)||g.ngMin){var t;h.$validators.min=function(a){return!r(a)||
-x(t)||d(a)>=t};g.$observe("min",function(a){t=s(a);h.$validate()})}if(y(g.max)||g.ngMax){var p;h.$validators.max=function(a){return!r(a)||x(p)||d(a)<=p};g.$observe("max",function(a){p=s(a);h.$validate()})}}}function Md(a,b,d,c){(c.$$hasNativeValidators=E(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?v:a})}function Nd(a,b,d,c,e){if(y(c)){a=a(c);if(!a.constant)throw nb("constexpr",d,c);return a(b)}return e}function oc(a,b){a="ngClass"+a;
-return["$animate",function(d){function c(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){var b=[];return L(a)?(n(a,function(a){b=b.concat(e(a))}),b):F(a)?a.split(" "):E(a)?(n(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function k(a,b){var c=g.data("$classCounts")||Z(),d=[];n(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",
-c);return d.join(" ")}function l(a){if(!0===b||f.$index%2===b){var l=e(a||[]);if(!m){var n=k(l,1);h.$addClass(n)}else if(!oa(a,m)){var q=e(m),n=c(l,q),l=c(q,l),n=k(n,1),l=k(l,-1);n&&n.length&&d.addClass(g,n);l&&l.length&&d.removeClass(g,l)}}m=na(a)}var m;f.$watch(h[a],l,!0);h.$observe("class",function(b){l(f.$eval(h[a]))});"ngClass"!==a&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var l=e(f.$eval(h[a]));g===b?(g=k(l,1),h.$addClass(g)):(g=k(l,-1),h.$removeClass(g))}})}}}]}function Ld(a){function b(a,
-b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function d(a,c){a=a?"-"+Bc(a,"-"):"";b(ob+a,!0===c);b(Od+a,!1===c)}var c=a.ctrl,e=a.$element,f={},g=a.set,h=a.unset,k=a.$animate;f[Od]=!(f[ob]=e.hasClass(ob));c.$setValidity=function(a,e,f){x(e)?(c.$pending||(c.$pending={}),g(c.$pending,a,f)):(c.$pending&&h(c.$pending,a,f),Pd(c.$pending)&&(c.$pending=v));Na(e)?e?(h(c.$error,a,f),g(c.$$success,a,f)):(g(c.$error,a,f),h(c.$$success,a,f)):(h(c.$error,a,f),h(c.$$success,a,f));
-c.$pending?(b(Qd,!0),c.$valid=c.$invalid=v,d("",null)):(b(Qd,!1),c.$valid=Pd(c.$error),c.$invalid=!c.$valid,d("",c.$valid));e=c.$pending&&c.$pending[a]?v:c.$error[a]?!1:c.$$success[a]?!0:null;d(a,e);c.$$parentForm.$setValidity(a,e,c)}}function Pd(a){if(a)for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}var Ag=/^\/(.+)\/([a-z]*)$/,sa=Object.prototype.hasOwnProperty,G=function(a){return F(a)?a.toLowerCase():a},ub=function(a){return F(a)?a.toUpperCase():a},xa,C,ua,wa=[].slice,ag=[].splice,Bg=
-[].push,ga=Object.prototype.toString,uc=Object.getPrototypeOf,Da=H("ng"),ia=O.angular||(O.angular={}),Vb,pb=0;xa=W.documentMode;B.$inject=[];ab.$inject=[];var L=Array.isArray,ae=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,X=function(a){return F(a)?a.trim():a},xd=function(a){return a.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},Ea=function(){if(!y(Ea.rules)){var a=W.querySelector("[ng-csp]")||W.querySelector("[data-ng-csp]");
-if(a){var b=a.getAttribute("ng-csp")||a.getAttribute("data-ng-csp");Ea.rules={noUnsafeEval:!b||-1!==b.indexOf("no-unsafe-eval"),noInlineStyle:!b||-1!==b.indexOf("no-inline-style")}}else{a=Ea;try{new Function(""),b=!1}catch(d){b=!0}a.rules={noUnsafeEval:b,noInlineStyle:!1}}}return Ea.rules},rb=function(){if(y(rb.name_))return rb.name_;var a,b,d=Qa.length,c,e;for(b=0;b<d;++b)if(c=Qa[b],a=W.querySelector("["+c.replace(":","\\:")+"jq]")){e=a.getAttribute(c+"jq");break}return rb.name_=e},de=/:/g,Qa=["ng-",
-"data-ng-","ng:","x-ng-"],ie=/[A-Z]/g,Cc=!1,Pa=3,me={full:"1.5.0",major:1,minor:5,dot:0,codeName:"ennoblement-facilitation"};U.expando="ng339";var ib=U.cache={},Of=1;U._data=function(a){return this.cache[a[this.expando]]||{}};var Jf=/([\:\-\_]+(.))/g,Kf=/^moz([A-Z])/,yb={mouseleave:"mouseout",mouseenter:"mouseover"},Xb=H("jqLite"),Nf=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Wb=/<|&#?\w+;/,Lf=/<([\w:-]+)/,Mf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,da={option:[1,'<select multiple="multiple">',
-"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};da.optgroup=da.option;da.tbody=da.tfoot=da.colgroup=da.caption=da.thead;da.th=da.td;var Tf=Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&16)},Ra=U.prototype={ready:function(a){function b(){d||(d=!0,a())}var d=!1;"complete"===W.readyState?setTimeout(b):(this.on("DOMContentLoaded",
-b),U(O).on("load",b))},toString:function(){var a=[];n(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?C(this[a]):C(this[this.length+a])},length:0,push:Bg,sort:[].sort,splice:[].splice},Db={};n("multiple selected checked disabled readOnly required open".split(" "),function(a){Db[G(a)]=a});var Uc={};n("input select option textarea button form details".split(" "),function(a){Uc[a]=!0});var cd={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",
-ngPattern:"pattern"};n({data:Zb,removeData:hb,hasData:function(a){for(var b in ib[a.ng339])return!0;return!1},cleanData:function(a){for(var b=0,d=a.length;b<d;b++)hb(a[b])}},function(a,b){U[b]=a});n({data:Zb,inheritedData:Cb,scope:function(a){return C.data(a,"$scope")||Cb(a.parentNode||a,["$isolateScope","$scope"])},isolateScope:function(a){return C.data(a,"$isolateScope")||C.data(a,"$isolateScopeNoTemplate")},controller:Rc,injector:function(a){return Cb(a,"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},
-hasClass:zb,css:function(a,b,d){b=gb(b);if(y(d))a.style[b]=d;else return a.style[b]},attr:function(a,b,d){var c=a.nodeType;if(c!==Pa&&2!==c&&8!==c)if(c=G(b),Db[c])if(y(d))d?(a[b]=!0,a.setAttribute(b,c)):(a[b]=!1,a.removeAttribute(c));else return a[b]||(a.attributes.getNamedItem(b)||B).specified?c:v;else if(y(d))a.setAttribute(b,d);else if(a.getAttribute)return a=a.getAttribute(b,2),null===a?v:a},prop:function(a,b,d){if(y(d))a[b]=d;else return a[b]},text:function(){function a(a,d){if(x(d)){var c=a.nodeType;
-return 1===c||c===Pa?a.textContent:""}a.textContent=d}a.$dv="";return a}(),val:function(a,b){if(x(b)){if(a.multiple&&"select"===ra(a)){var d=[];n(a.options,function(a){a.selected&&d.push(a.value||a.text)});return 0===d.length?null:d}return a.value}a.value=b},html:function(a,b){if(x(b))return a.innerHTML;wb(a,!0);a.innerHTML=b},empty:Sc},function(a,b){U.prototype[b]=function(b,c){var e,f,g=this.length;if(a!==Sc&&x(2==a.length&&a!==zb&&a!==Rc?b:c)){if(E(b)){for(e=0;e<g;e++)if(a===Zb)a(this[e],b);else for(f in b)a(this[e],
-f,b[f]);return this}e=a.$dv;g=x(e)?Math.min(g,1):g;for(f=0;f<g;f++){var h=a(this[f],b,c);e=e?e+h:h}return e}for(e=0;e<g;e++)a(this[e],b,c);return this}});n({removeData:hb,on:function(a,b,d,c){if(y(c))throw Xb("onargs");if(Mc(a)){c=xb(a,!0);var e=c.events,f=c.handle;f||(f=c.handle=Qf(a,e));c=0<=b.indexOf(" ")?b.split(" "):[b];for(var g=c.length,h=function(b,c,g){var h=e[b];h||(h=e[b]=[],h.specialHandlerWrapper=c,"$destroy"===b||g||a.addEventListener(b,f,!1));h.push(d)};g--;)b=c[g],yb[b]?(h(yb[b],Sf),
-h(b,v,!0)):h(b)}},off:Qc,one:function(a,b,d){a=C(a);a.on(b,function e(){a.off(b,d);a.off(b,e)});a.on(b,d)},replaceWith:function(a,b){var d,c=a.parentNode;wb(a);n(new U(b),function(b){d?c.insertBefore(b,d.nextSibling):c.replaceChild(b,a);d=b})},children:function(a){var b=[];n(a.childNodes,function(a){1===a.nodeType&&b.push(a)});return b},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,b){var d=a.nodeType;if(1===d||11===d){b=new U(b);for(var d=0,c=b.length;d<c;d++)a.appendChild(b[d])}},
-prepend:function(a,b){if(1===a.nodeType){var d=a.firstChild;n(new U(b),function(b){a.insertBefore(b,d)})}},wrap:function(a,b){Oc(a,C(b).eq(0).clone()[0])},remove:$b,detach:function(a){$b(a,!0)},after:function(a,b){var d=a,c=a.parentNode;b=new U(b);for(var e=0,f=b.length;e<f;e++){var g=b[e];c.insertBefore(g,d.nextSibling);d=g}},addClass:Bb,removeClass:Ab,toggleClass:function(a,b,d){b&&n(b.split(" "),function(b){var e=d;x(e)&&(e=!zb(a,b));(e?Bb:Ab)(a,b)})},parent:function(a){return(a=a.parentNode)&&
-11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,b){return a.getElementsByTagName?a.getElementsByTagName(b):[]},clone:Yb,triggerHandler:function(a,b,d){var c,e,f=b.type||b,g=xb(a);if(g=(g=g&&g.events)&&g[f])c={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},
-stopPropagation:B,type:f,target:a},b.type&&(c=T(c,b)),b=na(g),e=d?[c].concat(d):[c],n(b,function(b){c.isImmediatePropagationStopped()||b.apply(a,e)})}},function(a,b){U.prototype[b]=function(b,c,e){for(var f,g=0,h=this.length;g<h;g++)x(f)?(f=a(this[g],b,c,e),y(f)&&(f=C(f))):Pc(f,a(this[g],b,c,e));return y(f)?f:this};U.prototype.bind=U.prototype.on;U.prototype.unbind=U.prototype.off});Ua.prototype={put:function(a,b){this[Fa(a,this.nextUid)]=b},get:function(a){return this[Fa(a,this.nextUid)]},remove:function(a){var b=
-this[a=Fa(a,this.nextUid)];delete this[a];return b}};var Hf=[function(){this.$get=[function(){return Ua}]}],Vf=/^([^\(]+?)=>/,Wf=/^[^\(]*\(\s*([^\)]*)\)/m,Cg=/,/,Dg=/^\s*(_?)(\S+?)\1\s*$/,Uf=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ga=H("$injector");fb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw F(d)&&d||(d=a.name||Xf(a)),Ga("strictdi",d);b=Vc(a);n(b[1].split(Cg),function(a){a.replace(Dg,function(a,b,d){c.push(d)})})}a.$inject=c}}else L(a)?
-(b=a.length-1,Sa(a[b],"fn"),c=a.slice(0,b)):Sa(a,"fn",!0);return c};var Rd=H("$animate"),$e=function(){this.$get=function(){}},af=function(){var a=new Ua,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=F(b)?b.split(" "):L(b)?b:[],n(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){n(b,function(b){var c=a.get(b);if(c){var d=Yf(b.attr("class")),e="",f="";n(c,function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});n(b,function(a){e&&
-Bb(a,e);f&&Ab(a,f)});a.remove(b)}});b.length=0}return{enabled:B,on:B,off:B,pin:B,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.put(g,k),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},Ye=["$provide",function(a){var b=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,c){if(d&&"."!==d.charAt(0))throw Rd("notcsel",
-d);var e=d+"-animation";b.$$registeredAnimations[d.substr(1)]=e;a.factory(e,c)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Rd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var h;a:{for(h=0;h<d.length;h++){var k=d[h];if(1===k.nodeType){h=k;break a}}h=void 0}!h||h.parentNode||h.previousElementSibling||
-(d=null)}d?d.after(a):c.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(e,f,g,h){f=f&&C(f);g=g&&C(g);f=f||g.parent();b(e,f,g);return a.push(e,"enter",Ha(h))},move:function(e,f,g,h){f=f&&C(f);g=g&&C(g);f=f||g.parent();b(e,f,g);return a.push(e,"move",Ha(h))},leave:function(b,c){return a.push(b,"leave",Ha(c),function(){b.remove()})},addClass:function(b,c,g){g=Ha(g);g.addClass=jb(g.addclass,c);return a.push(b,"addClass",g)},removeClass:function(b,
-c,g){g=Ha(g);g.removeClass=jb(g.removeClass,c);return a.push(b,"removeClass",g)},setClass:function(b,c,g,h){h=Ha(h);h.addClass=jb(h.addClass,c);h.removeClass=jb(h.removeClass,g);return a.push(b,"setClass",h)},animate:function(b,c,g,h,k){k=Ha(k);k.from=k.from?T(k.from,c):c;k.to=k.to?T(k.to,g):g;k.tempClasses=jb(k.tempClasses,h||"ng-inline-animate");return a.push(b,"animate",k)}}}]}],cf=function(){this.$get=["$$rAF",function(a){function b(b){d.push(b);1<d.length||a(function(){for(var a=0;a<d.length;a++)d[a]();
-d=[]})}var d=[];return function(){var a=!1;b(function(){a=!0});return function(d){a?d():b(d)}}}]},bf=function(){this.$get=["$q","$sniffer","$$animateAsyncRun","$document","$timeout",function(a,b,d,c,e){function f(a){this.setHost(a);var b=d();this._doneCallbacks=[];this._tick=function(a){var d=c[0];d&&d.hidden?e(a,0,!1):b(a)};this._state=0}f.chain=function(a,b){function c(){if(d===a.length)b(!0);else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};f.all=function(a,b){function c(f){e=e&&f;++d===
-a.length&&b(e)}var d=0,e=!0;n(a,function(a){a.done(c)})};f.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?a():this._doneCallbacks.push(a)},progress:B,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&
-this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._tick(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(n(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return f}]},Ze=function(){this.$get=["$$rAF","$q","$$AnimateRunner",
-function(a,b,d){return function(b,e){function f(){a(function(){g.addClass&&(b.addClass(g.addClass),g.addClass=null);g.removeClass&&(b.removeClass(g.removeClass),g.removeClass=null);g.to&&(b.css(g.to),g.to=null);h||k.complete();h=!0});return k}var g=e||{};g.$$prepared||(g=Oa(g));g.cleanupStyles&&(g.from=g.to=null);g.from&&(b.css(g.from),g.from=null);var h,k=new d;return{start:f,end:f}}}]},ja=H("$compile");Ec.$inject=["$provide","$$sanitizeUriProvider"];var Xc=/^((?:x|data)[\:\-_])/i,bg=H("$controller"),
-dd=/^(\S+)(\s+as\s+([\w$]+))?$/,jf=function(){this.$get=["$document",function(a){return function(b){b?!b.nodeType&&b instanceof C&&(b=b[0]):b=a[0].body;return b.offsetWidth+1}}]},ed="application/json",dc={"Content-Type":ed+";charset=utf-8"},dg=/^\[|^\{(?!\{)/,eg={"[":/]$/,"{":/}$/},cg=/^\)\]\}',?\n/,Eg=H("$http"),id=function(a){return function(){throw Eg("legacy",a);}},Ka=ia.$interpolateMinErr=H("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,b){return Ka("interr",
-a,b.toString())};var Fg=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,gg={http:80,https:443,ftp:21},Gb=H("$location"),Gg={$$html5:!1,$$replace:!1,absUrl:Hb("$$absUrl"),url:function(a){if(x(a))return this.$$url;var b=Fg.exec(a);(b[1]||""===a)&&this.path(decodeURIComponent(b[1]));(b[2]||b[1]||""===a)&&this.search(b[3]||"");this.hash(b[5]||"");return this},protocol:Hb("$$protocol"),host:Hb("$$host"),port:Hb("$$port"),path:nd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,
-b){switch(arguments.length){case 0:return this.$$search;case 1:if(F(a)||N(a))a=a.toString(),this.$$search=zc(a);else if(E(a))a=Oa(a,{}),n(a,function(b,c){null==b&&delete a[c]}),this.$$search=a;else throw Gb("isrcharg");break;default:x(b)||null===b?delete this.$$search[a]:this.$$search[a]=b}this.$$compose();return this},hash:nd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};n([md,gc,fc],function(a){a.prototype=Object.create(Gg);a.prototype.state=
-function(b){if(!arguments.length)return this.$$state;if(a!==fc||!this.$$html5)throw Gb("nostate");this.$$state=x(b)?null:b;return this}});var ka=H("$parse"),ig=Function.prototype.call,jg=Function.prototype.apply,kg=Function.prototype.bind,Pb=Z();n("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Pb[a]=!0});var Hg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},ic=function(a){this.options=a};ic.prototype={constructor:ic,lex:function(a){this.text=a;this.index=0;for(this.tokens=
-[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var b=a+this.peek(),d=b+this.peek(2),c=Pb[b],e=Pb[d];Pb[a]||c||e?(a=e?d:c?b:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=
-a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,b){return-1!==b.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===
-a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=y(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw ka("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index<this.text.length;){var d=G(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var c=this.peek();if("e"==d&&this.isExpOperator(c))a+=d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||
-c&&this.isNumber(c)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var b=this.text.charAt(this.index);if(!this.isIdent(b)&&!this.isNumber(b))break;this.index++}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;for(var d="",c=a,e=!1;this.index<this.text.length;){var f=
-this.text.charAt(this.index),c=c+f;if(e)"u"===f?(e=this.text.substring(this.index+1,this.index+5),e.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+e+"]"),this.index+=4,d+=String.fromCharCode(parseInt(e,16))):d+=Hg[f]||f,e=!1;else if("\\"===f)e=!0;else{if(f===a){this.index++;this.tokens.push({index:b,text:c,constant:!0,value:d});return}d+=f}this.index++}this.throwError("Unterminated quote",b)}};var q=function(a,b){this.lexer=a;this.options=b};q.Program="Program";q.ExpressionStatement=
-"ExpressionStatement";q.AssignmentExpression="AssignmentExpression";q.ConditionalExpression="ConditionalExpression";q.LogicalExpression="LogicalExpression";q.BinaryExpression="BinaryExpression";q.UnaryExpression="UnaryExpression";q.CallExpression="CallExpression";q.MemberExpression="MemberExpression";q.Identifier="Identifier";q.Literal="Literal";q.ArrayExpression="ArrayExpression";q.Property="Property";q.ObjectExpression="ObjectExpression";q.ThisExpression="ThisExpression";q.LocalsExpression="LocalsExpression";
-q.NGValueParameter="NGValueParameter";q.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:q.Program,body:a}},expressionStatement:function(){return{type:q.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=
-this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:q.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),b,d;return this.expect("?")&&(b=this.expression(),this.consume(":"))?(d=this.expression(),{type:q.ConditionalExpression,test:a,alternate:b,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a=
-{type:q.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:q.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),b;b=this.expect("==","!=","===","!==");)a={type:q.BinaryExpression,operator:b.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),b;b=this.expect("<",">","<=",">=");)a={type:q.BinaryExpression,
-operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:q.BinaryExpression,operator:b.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:
-this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=Oa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},
-this.consume(")")):"["===b.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:q.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());
-while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;
-b={type:q.Property,kind:"init"};this.peek().constant?b.key=this.constant():this.peek().identifier?b.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");b.value=this.expression();a.push(b)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}},throwError:function(a,b){throw ka("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw ka("ueoe",this.text);var b=this.expect(a);
-b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw ka("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},
-"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:v},"this":{type:q.ThisExpression},$locals:{type:q.LocalsExpression}}};ud.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};R(c,d.$filter);var e="",f;this.stage="assign";if(f=sd(c))this.state.computing="assign",e=this.nextId(),this.recurse(f,e),this.return_(e),
-e="fn.assign="+this.generateFunction("assign","s,v,l");f=qd(c.body);d.stage="inputs";n(f,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}};d.state.computing=c;var e=d.nextId();d.recurse(a,e);d.return_(e);d.state.inputs.push(c);a.watchId=b});this.state.computing="fn";this.stage="main";this.recurse(c);e='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+e+this.watchFns()+"return fn;";e=(new Function("$filter","ensureSafeMemberName","ensureSafeObject",
-"ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",e))(this.$filter,Xa,Aa,od,hg,Ib,lg,pd,a);this.state=this.stage=v;e.literal=td(c);e.constant=c.constant;return e},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;n(b,function(b){a.push("var "+b+"="+d.generateFunction(b,"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];");return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+
-"};"},filterPrefix:function(){var a=[],b=this;n(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,c,e,f){var g,h,k=this,l,m;c=c||B;if(!f&&y(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,
-c,e,!0));else switch(a.type){case q.Program:n(a.body,function(b,c){k.recurse(b.expression,v,v,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case q.Literal:m=this.escape(a.value);this.assign(b,m);c(m);break;case q.UnaryExpression:this.recurse(a.argument,v,v,function(a){h=a});m=a.operator+"("+this.ifDefined(h,0)+")";this.assign(b,m);c(m);break;case q.BinaryExpression:this.recurse(a.left,v,v,function(a){g=a});this.recurse(a.right,v,v,function(a){h=a});m="+"===
-a.operator?this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case q.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right,b));c(b);break;case q.ConditionalExpression:b=b||this.nextId();k.recurse(a.test,b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case q.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?
-"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Xa(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s",a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Jb(a.name))&&k.addEnsureSafeObject(b);c(b);
-break;case q.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,v,function(){k.if_(k.notNull(g),function(){e&&1!==e&&k.addEnsureSafeAssignContext(g);if(a.computed)h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),k.addEnsureSafeMemberName(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g,h),"{}")),m=k.ensureSafeObject(k.computedMember(g,h)),k.assign(b,m),d&&(d.computed=!0,d.name=h);else{Xa(a.property.name);e&&
-1!==e&&k.if_(k.not(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}"));m=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Jb(a.property.name))m=k.ensureSafeObject(m);k.assign(b,m);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(b,"undefined")});c(b)},!!e);break;case q.CallExpression:b=b||this.nextId();a.filter?(h=k.filter(a.callee.name),l=[],n(a.arguments,function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+
-l.join(",")+")",k.assign(b,m),c(b)):(h=k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){k.addEnsureSafeFunction(h);n(a.arguments,function(a){k.recurse(a,k.nextId(),v,function(a){l.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),m=k.member(g.context,g.name,g.computed)+"("+l.join(",")+")"):m=h+"("+l.join(",")+")";m=k.ensureSafeObject(m);k.assign(b,m)},function(){k.assign(b,"undefined")});c(b)}));break;case q.AssignmentExpression:h=
-this.nextId();g={};if(!rd(a.left))throw ka("lval");this.recurse(a.left,v,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);m=k.member(g.context,g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case q.ArrayExpression:l=[];n(a.elements,function(a){k.recurse(a,k.nextId(),v,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(m);break;case q.ObjectExpression:l=
-[];n(a.properties,function(a){k.recurse(a.value,k.nextId(),v,function(b){l.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+b)})});m="{"+l.join(",")+"}";this.assign(b,m);c(m);break;case q.ThisExpression:this.assign(b,"s");c("s");break;case q.LocalsExpression:this.assign(b,"l");c("l");break;case q.NGValueParameter:this.assign(b,"v"),c("v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+
-a+")"));return c[d]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");
-d&&(c.push("else{"),d(),c.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){return a+"."+b},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),
-";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+a+",text)"},lazyRecurse:function(a,b,d,c,e,f){var g=
-this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(F(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(N(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw ka("esc");},nextId:function(a,
-b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};vd.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=b;R(c,d.$filter);var e,f;if(e=sd(c))f=this.recurse(e);e=qd(c.body);var g;e&&(g=[],n(e,function(a,b){var c=d.recurse(a);a.input=c;g.push(c);a.watchId=b}));var h=[];n(c.body,function(a){h.push(d.recurse(a.expression))});e=0===c.body.length?function(){}:
-1===c.body.length?h[0]:function(a,b){var c;n(h,function(d){c=d(a,b)});return c};f&&(e.assign=function(a,b,c){return f(a,c,b)});g&&(e.inputs=g);e.literal=td(c);e.constant=c.constant;return e},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,b);case q.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case q.BinaryExpression:return c=this.recurse(a.left),e=this.recurse(a.right),
-this["binary"+a.operator](c,e,b);case q.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case q.Identifier:return Xa(a.name,f.expression),f.identifier(a.name,f.expensiveChecks||Jb(a.name),b,d,f.expression);case q.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(Xa(a.property.name,f.expression),
-e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d,f.expression):this.nonComputedMember(c,e,f.expensiveChecks,b,d,f.expression);case q.CallExpression:return g=[],n(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var r=[],n=0;n<g.length;++n)r.push(g[n](a,c,d,f));a=e.apply(v,r,f);return b?{context:v,name:v,value:a}:a}:function(a,c,d,m){var r=
-e(a,c,d,m),n;if(null!=r.value){Aa(r.context,f.expression);od(r.value,f.expression);n=[];for(var q=0;q<g.length;++q)n.push(Aa(g[q](a,c,d,m),f.expression));n=Aa(r.value.apply(r.context,n),f.expression)}return b?{value:n}:n};case q.AssignmentExpression:return c=this.recurse(a.left,!0,1),e=this.recurse(a.right),function(a,d,g,m){var r=c(a,d,g,m);a=e(a,d,g,m);Aa(r.value,f.expression);Ib(r.context);r.context[r.name]=a;return b?{value:a}:a};case q.ArrayExpression:return g=[],n(a.elements,function(a){g.push(f.recurse(a))}),
-function(a,c,d,e){for(var f=[],n=0;n<g.length;++n)f.push(g[n](a,c,d,e));return b?{value:f}:f};case q.ObjectExpression:return g=[],n(a.properties,function(a){g.push({key:a.key.type===q.Identifier?a.key.name:""+a.key.value,value:f.recurse(a.value)})}),function(a,c,d,e){for(var f={},n=0;n<g.length;++n)f[g[n].key]=g[n].value(a,c,d,e);return b?{value:f}:f};case q.ThisExpression:return function(a){return b?{value:a}:a};case q.LocalsExpression:return function(a,c){return b?{value:c}:c};case q.NGValueParameter:return function(a,
-c,d,e){return b?{value:d}:d}}},"unary+":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=y(d)?+d:0;return b?{value:d}:d}},"unary-":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=y(d)?-d:0;return b?{value:d}:d}},"unary!":function(a,b){return function(d,c,e,f){d=!a(d,c,e,f);return b?{value:d}:d}},"binary+":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=pd(h,c);return d?{value:h}:h}},"binary-":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);
-h=(y(h)?h:0)-(y(c)?c:0);return d?{value:h}:h}},"binary*":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)*b(c,e,f,g);return d?{value:c}:c}},"binary/":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)/b(c,e,f,g);return d?{value:c}:c}},"binary%":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)%b(c,e,f,g);return d?{value:c}:c}},"binary===":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)===b(c,e,f,g);return d?{value:c}:c}},"binary!==":function(a,b,d){return function(c,e,f,g){c=a(c,
-e,f,g)!==b(c,e,f,g);return d?{value:c}:c}},"binary==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)==b(c,e,f,g);return d?{value:c}:c}},"binary!=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!=b(c,e,f,g);return d?{value:c}:c}},"binary<":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<b(c,e,f,g);return d?{value:c}:c}},"binary>":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,
-g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:v,
-name:v,value:a}:a}},identifier:function(a,b,d,c,e){return function(f,g,h,k){f=g&&a in g?g:f;c&&1!==c&&f&&!f[a]&&(f[a]={});g=f?f[a]:v;b&&Aa(g,e);return d?{context:f,name:a,value:g}:g}},computedMember:function(a,b,d,c,e){return function(f,g,h,k){var l=a(f,g,h,k),m,n;null!=l&&(m=b(f,g,h,k),m+="",Xa(m,e),c&&1!==c&&(Ib(l),l&&!l[m]&&(l[m]={})),n=l[m],Aa(n,e));return d?{context:l,name:m,value:n}:n}},nonComputedMember:function(a,b,d,c,e,f){return function(g,h,k,l){g=a(g,h,k,l);e&&1!==e&&(Ib(g),g&&!g[b]&&
-(g[b]={}));h=null!=g?g[b]:v;(d||Jb(b))&&Aa(h,f);return c?{context:g,name:b,value:h}:h}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};var jc=function(a,b,d){this.lexer=a;this.$filter=b;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new vd(this.ast,b):new ud(this.ast,b)};jc.prototype={constructor:jc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};var mg=Object.prototype.valueOf,Ba=H("$sce"),qa={HTML:"html",CSS:"css",URL:"url",
-RESOURCE_URL:"resourceUrl",JS:"js"},ja=H("$compile"),Y=W.createElement("a"),zd=za(O.location.href);Ad.$inject=["$document"];Lc.$inject=["$provide"];var Hd=22,Gd=".",lc="0";Bd.$inject=["$locale"];Dd.$inject=["$locale"];var yg={yyyy:aa("FullYear",4),yy:aa("FullYear",2,0,!0),y:aa("FullYear",1),MMMM:Lb("Month"),MMM:Lb("Month",!0),MM:aa("Month",2,1),M:aa("Month",1,1),dd:aa("Date",2),d:aa("Date",1),HH:aa("Hours",2),H:aa("Hours",1),hh:aa("Hours",2,-12),h:aa("Hours",1,-12),mm:aa("Minutes",2),m:aa("Minutes",
-1),ss:aa("Seconds",2),s:aa("Seconds",1),sss:aa("Milliseconds",3),EEEE:Lb("Day"),EEE:Lb("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Kb(Math[0<a?"floor":"ceil"](a/60),2)+Kb(Math.abs(a%60),2))},ww:Jd(2),w:Jd(1),G:mc,GG:mc,GGG:mc,GGGG:function(a,b){return 0>=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},xg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,wg=/^\-?\d+$/;Cd.$inject=["$locale"];
-var rg=ba(G),sg=ba(ub);Ed.$inject=["$parse"];var oe=ba({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ga.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),vb={};n(Db,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!=a){var c=va("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,
-e)});vb[c]=function(){return{restrict:"A",priority:100,link:e}}}});n(cd,function(a,b){vb[b]=function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"==e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Ag))){e.$set("ngPattern",new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});n(["src","srcset","href"],function(a){var b=va("ng-"+a);vb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===ga.call(c.prop("href"))&&
-(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),xa&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Mb={$addControl:B,$$renameControl:function(a,b){a.$name=b},$removeControl:B,$setValidity:B,$setDirty:B,$setPristine:B,$setSubmitted:B};Kd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Sd=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||B}return{name:"form",restrict:a?
-"EAC":"E",require:["form","^^?form"],controller:Kd,compile:function(d,f){d.addClass(Ya).addClass(ob);var g=f.name?"name":a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var s=function(b){a.$apply(function(){n.$commitViewValue();n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",s,!1);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",s,!1)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var q=g?c(n.$name):B;g&&(q(a,n),e.$observe(g,
-function(b){n.$name!==b&&(q(a,v),n.$$parentForm.$$renameControl(n,b),q=c(n.$name),q(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);q(a,v);T(n,Mb)})}}}}}]},pe=Sd(),Ce=Sd(!0),zg=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,Ig=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Jg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,Kg=
-/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Td=/^(\d{4})-(\d{2})-(\d{2})$/,Ud=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,pc=/^(\d{4})-W(\d\d)$/,Vd=/^(\d{4})-(\d\d)$/,Wd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Xd={text:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);nc(c)},date:mb("date",Td,Ob(Td,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Ud,Ob(Ud,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Wd,Ob(Wd,["HH","mm","ss",
-"sss"]),"HH:mm:ss.sss"),week:mb("week",pc,function(a,b){if(V(a))return a;if(F(a)){pc.lastIndex=0;var d=pc.exec(a);if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Id(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:mb("month",Vd,Ob(Vd,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Md(a,b,d,c);lb(a,b,d,c,e,f);c.$$parserName="number";c.$parsers.push(function(a){return c.$isEmpty(a)?null:
-Kg.test(a)?parseFloat(a):v});c.$formatters.push(function(a){if(!c.$isEmpty(a)){if(!N(a))throw nb("numfmt",a);a=a.toString()}return a});if(y(d.min)||d.ngMin){var g;c.$validators.min=function(a){return c.$isEmpty(a)||x(g)||a>=g};d.$observe("min",function(a){y(a)&&!N(a)&&(a=parseFloat(a,10));g=N(a)&&!isNaN(a)?a:v;c.$validate()})}if(y(d.max)||d.ngMax){var h;c.$validators.max=function(a){return c.$isEmpty(a)||x(h)||a<=h};d.$observe("max",function(a){y(a)&&!N(a)&&(a=parseFloat(a,10));h=N(a)&&!isNaN(a)?
-a:v;c.$validate()})}},url:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);nc(c);c.$$parserName="url";c.$validators.url=function(a,b){var d=a||b;return c.$isEmpty(d)||Ig.test(d)}},email:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);nc(c);c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||Jg.test(d)}},radio:function(a,b,d,c){x(d.name)&&b.attr("name",++pb);b.on("click",function(a){b[0].checked&&c.$setViewValue(d.value,a&&a.type)});c.$render=function(){b[0].checked=d.value==c.$viewValue};
-d.$observe("value",c.$render)},checkbox:function(a,b,d,c,e,f,g,h){var k=Nd(h,a,"ngTrueValue",d.ngTrueValue,!0),l=Nd(h,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return oa(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:B,button:B,submit:B,reset:B,file:B},Fc=["$browser","$sniffer","$filter","$parse",function(a,b,d,
-c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Xd[G(g.type)]||Xd.text)(e,f,g,h[0],b,a,d,c)}}}}],Lg=/^(true|false|\d+)$/,Ue=function(){return{restrict:"A",priority:100,compile:function(a,b){return Lg.test(b.ngValue)?function(a,b,e){e.$set("value",a.$eval(e.ngValue))}:function(a,b,e){a.$watch(e.ngValue,function(a){e.$set("value",a)})}}}},ue=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,
-e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=x(a)?"":a})}}}}],we=["$interpolate","$compile",function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=x(a)?"":a})}}}}],ve=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(a){return(a||"").toString()});
-d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){c.html(a.getTrustedHtml(f(b))||"")})}}}}],Te=ba({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),xe=oc("",!0),ze=oc("Odd",0),ye=oc("Even",1),Ae=Ma({compile:function(a,b){b.$set("ngCloak",v);a.removeClass("ng-cloak")}}),Be=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},Mg={blur:!0,focus:!0};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
-function(a){var b=va("ng-"+a);Kc[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b],null,!0);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};Mg[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var Ee=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(b,d,c,e,f){var g,h,k;b.$watch(c.ngIf,function(b){b?h||f(function(b,e){h=e;b[b.length++]=W.createComment(" end ngIf: "+
-c.ngIf+" ");g={clone:b};a.enter(b,d.parent(),d)}):(k&&(k.remove(),k=null),h&&(h.$destroy(),h=null),g&&(k=tb(g.clone),a.leave(k).then(function(){k=null}),g=null))})}}}],Fe=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ia.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,s){var q=0,v,t,p,w=function(){t&&(t.remove(),t=null);v&&(v.$destroy(),v=null);p&&
-(d.leave(p).then(function(){t=null}),t=p,p=null)};c.$watch(f,function(f){var m=function(){!y(h)||h&&!c.$eval(h)||b()},z=++q;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&z===q){var b=c.$new();n.template=a;a=s(b,function(a){w();d.enter(a,null,e).then(m)});v=b;p=a;v.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){c.$$destroyed||z!==q||(w(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(w(),n.template=null)})}}}}],We=["$compile",function(a){return{restrict:"ECA",
-priority:-400,require:"ngInclude",link:function(b,d,c,e){ga.call(d[0]).match(/SVG/)?(d.empty(),a(Nc(e.template,W).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],Ge=Ma({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),Se=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=b.attr(d.$attr.ngList)||", ",f="false"!==d.ngTrim,g=f?X(e):e;c.$parsers.push(function(a){if(!x(a)){var b=
-[];a&&n(a.split(g),function(a){a&&b.push(f?X(a):a)});return b}});c.$formatters.push(function(a){return L(a)?a.join(e):v});c.$isEmpty=function(a){return!a||!a.length}}}},ob="ng-valid",Od="ng-invalid",Ya="ng-pristine",Nb="ng-dirty",Qd="ng-pending",nb=H("ngModel"),Ng=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,c,e,f,g,h,k,l){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=v;this.$validators={};this.$asyncValidators=
-{};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=v;this.$name=l(d.name||"",!1)(a);this.$$parentForm=Mb;var m=e(d.ngModel),r=m.assign,q=m,I=r,K=null,t,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var b=e(d.ngModel+"()"),f=e(d.ngModel+"($$$p)");q=function(a){var c=m(a);D(c)&&(c=b(a));return c};I=function(a,
-b){D(m(a))?f(a,{$$$p:p.$modelValue}):r(a,p.$modelValue)}}else if(!m.assign)throw nb("nonassign",d.ngModel,ta(c));};this.$render=B;this.$isEmpty=function(a){return x(a)||""===a||null===a||a!==a};this.$$updateEmptyClasses=function(a){p.$isEmpty(a)?(f.removeClass(c,"ng-not-empty"),f.addClass(c,"ng-empty")):(f.removeClass(c,"ng-empty"),f.addClass(c,"ng-not-empty"))};var w=0;Ld({ctrl:this,$element:c,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:f});this.$setPristine=function(){p.$dirty=
-!1;p.$pristine=!0;f.removeClass(c,Nb);f.addClass(c,Ya)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;f.removeClass(c,Ya);f.addClass(c,Nb);p.$$parentForm.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;f.setClass(c,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=!0;p.$untouched=!1;f.setClass(c,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){g.cancel(K);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!N(p.$modelValue)||
-!isNaN(p.$modelValue)){var a=p.$$rawModelValue,b=p.$valid,c=p.$modelValue,d=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(e){d||b===e||(p.$modelValue=e?a:v,p.$modelValue!==c&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,b,c){function d(){var c=!0;n(p.$validators,function(d,e){var g=d(a,b);c=c&&g;f(e,g)});return c?!0:(n(p.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;n(p.$asyncValidators,function(e,g){var h=e(a,
-b);if(!h||!D(h.then))throw nb("nopromise",h);f(g,v);c.push(h.then(function(){f(g,!0)},function(a){d=!1;f(g,!1)}))});c.length?k.all(c).then(function(){g(d)},B):g(!0)}function f(a,b){h===w&&p.$setValidity(a,b)}function g(a){h===w&&c(a)}w++;var h=w;(function(){var a=p.$$parserName||"parse";if(x(t))f(a,null);else return t||(n(p.$validators,function(a,b){f(b,null)}),n(p.$asyncValidators,function(a,b){f(b,null)})),f(a,t),t;return!0})()?d()?e():g(!1):g(!1)};this.$commitViewValue=function(){var a=p.$viewValue;
-g.cancel(K);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$updateEmptyClasses(a),p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var b=p.$$lastCommittedViewValue;if(t=x(b)?v:!0)for(var c=0;c<p.$parsers.length;c++)if(b=p.$parsers[c](b),x(b)){t=!1;break}N(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=q(a));var d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=b;e&&(p.$modelValue=
-b,p.$modelValue!==d&&p.$$writeModelToScope());p.$$runValidators(b,p.$$lastCommittedViewValue,function(a){e||(p.$modelValue=a?b:v,p.$modelValue!==d&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){I(a,p.$modelValue);n(p.$viewChangeListeners,function(a){try{a()}catch(c){b(c)}})};this.$setViewValue=function(a,b){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(b)};this.$$debounceViewValueCommit=function(b){var c=0,d=p.$options;d&&y(d.debounce)&&(d=d.debounce,
-N(d)?c=d:N(d[b])?c=d[b]:N(d["default"])&&(c=d["default"]));g.cancel(K);c?K=g(function(){p.$commitViewValue()},c):h.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var b=q(a);if(b!==p.$modelValue&&(p.$modelValue===p.$modelValue||b===b)){p.$modelValue=p.$$rawModelValue=b;t=v;for(var c=p.$formatters,d=c.length,e=b;d--;)e=c[d](e);p.$viewValue!==e&&(p.$$updateEmptyClasses(e),p.$viewValue=p.$$lastCommittedViewValue=e,p.$render(),p.$$runValidators(b,e,B))}return b})}],
-Re=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:Ng,priority:1,compile:function(b){b.addClass(Ya).addClass("ng-untouched").addClass(ob);return{pre:function(a,b,e,f){var g=f[0];b=f[1]||g.$$parentForm;g.$$setOptions(f[2]&&f[2].$options);b.$addControl(g);e.$observe("name",function(a){g.$name!==a&&g.$$parentForm.$$renameControl(g,a)});a.$on("$destroy",function(){g.$$parentForm.$removeControl(g)})},post:function(b,c,e,f){var g=f[0];if(g.$options&&
-g.$options.updateOn)c.on(g.$options.updateOn,function(a){g.$$debounceViewValueCommit(a&&a.type)});c.on("blur",function(c){g.$touched||(a.$$phase?b.$evalAsync(g.$setTouched):b.$apply(g.$setTouched))})}}}}}],Og=/(\s+|^)default(\s+|$)/,Ve=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,b){var d=this;this.$options=Oa(a.$eval(b.ngModelOptions));y(this.$options.updateOn)?(this.$options.updateOnDefault=!1,this.$options.updateOn=X(this.$options.updateOn.replace(Og,function(){d.$options.updateOnDefault=
-!0;return" "}))):this.$options.updateOnDefault=!0}]}},He=Ma({terminal:!0,priority:1E3}),Pg=H("ngOptions"),Qg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,Pe=["$compile","$parse",function(a,b){function d(a,c,d){function e(a,b,c,d,f){this.selectValue=a;this.viewValue=b;this.label=c;this.group=d;this.disabled=f}
-function l(a){var b;if(!q&&Ca(a))b=a;else{b=[];for(var c in a)a.hasOwnProperty(c)&&"$"!==c.charAt(0)&&b.push(c)}return b}var m=a.match(Qg);if(!m)throw Pg("iexp",a,ta(c));var n=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var v=m[9];c=b(m[2]?m[1]:n);var y=a&&b(a)||c,t=v&&b(v),p=v?function(a,b){return t(d,b)}:function(a){return Fa(a)},w=function(a,b){return p(a,B(a,b))},u=b(m[2]||m[1]),x=b(m[3]||""),z=b(m[4]||""),A=b(m[8]),C={},B=q?function(a,b){C[q]=b;C[n]=a;return C}:function(a){C[n]=a;return C};return{trackBy:v,
-getTrackByValue:w,getWatchables:b(A,function(a){var b=[];a=a||[];for(var c=l(a),e=c.length,f=0;f<e;f++){var g=a===c?f:c[f],k=B(a[g],g),g=p(a[g],k);b.push(g);if(m[2]||m[1])g=u(d,k),b.push(g);m[4]&&(k=z(d,k),b.push(k))}return b}),getOptions:function(){for(var a=[],b={},c=A(d)||[],f=l(c),g=f.length,m=0;m<g;m++){var n=c===f?m:f[m],r=B(c[n],n),q=y(d,r),n=p(q,r),s=u(d,r),t=x(d,r),r=z(d,r),q=new e(n,q,s,t,r);a.push(q);b[n]=q}return{items:a,selectValueMap:b,getOptionFromViewValue:function(a){return b[w(a)]},
-getViewValueFromOption:function(a){return v?ia.copy(a.viewValue):a.viewValue}}}}}var c=W.createElement("option"),e=W.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","ngModel"],link:{pre:function(a,b,c,d){d[0].registerOption=B},post:function(b,g,h,k){function l(a,b){a.element=b;b.disabled=a.disabled;a.label!==b.label&&(b.label=a.label,b.textContent=a.label);a.value!==b.value&&(b.value=a.selectValue)}function m(a,b,c,d){b&&G(b.nodeName)===c?c=b:(c=d.cloneNode(!1),b?a.insertBefore(c,
-b):a.appendChild(c));return c}function r(a){for(var b;a;)b=a.nextSibling,$b(a),a=b}function q(a){var b=w&&w[0],c=A&&A[0];if(b||c)for(;a&&(a===b||a===c||8===a.nodeType||"option"===ra(a)&&""===a.value);)a=a.nextSibling;return a}function v(){var a=D&&x.readValue();D=E.getOptions();var b={},d=g[0].firstChild;z&&g.prepend(w);d=q(d);D.items.forEach(function(a){var f,h;y(a.group)?(f=b[a.group],f||(f=m(g[0],d,"optgroup",e),d=f.nextSibling,f.label=a.group,f=b[a.group]={groupElement:f,currentOptionElement:f.firstChild}),
-h=m(f.groupElement,f.currentOptionElement,"option",c),l(a,h),f.currentOptionElement=h.nextSibling):(h=m(g[0],d,"option",c),l(a,h),d=h.nextSibling)});Object.keys(b).forEach(function(a){r(b[a].currentOptionElement)});r(d);t.$render();if(!t.$isEmpty(a)){var f=x.readValue();(E.trackBy||p?oa(a,f):a===f)||(t.$setViewValue(f),t.$render())}}var x=k[0],t=k[1],p=h.multiple,w;k=0;for(var u=g.children(),B=u.length;k<B;k++)if(""===u[k].value){w=u.eq(k);break}var z=!!w,A=C(c.cloneNode(!1));A.val("?");var D,E=d(h.ngOptions,
-g,b);p?(t.$isEmpty=function(a){return!a||0===a.length},x.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},x.readValue=function(){var a=g.val()||[],b=[];n(a,function(a){(a=D.selectValueMap[a])&&!a.disabled&&b.push(D.getViewValueFromOption(a))});return b},E.trackBy&&b.$watchCollection(function(){if(L(t.$viewValue))return t.$viewValue.map(function(a){return E.getTrackByValue(a)})},
-function(){t.$render()})):(x.writeValue=function(a){var b=D.getOptionFromViewValue(a);b&&!b.disabled?g[0].value!==b.selectValue&&(A.remove(),z||w.remove(),g[0].value=b.selectValue,b.element.selected=!0,b.element.setAttribute("selected","selected")):null===a||z?(A.remove(),z||g.prepend(w),g.val(""),w.prop("selected",!0),w.attr("selected",!0)):(z||w.remove(),g.prepend(A),g.val("?"),A.prop("selected",!0),A.attr("selected",!0))},x.readValue=function(){var a=D.selectValueMap[g.val()];return a&&!a.disabled?
-(z||w.remove(),A.remove(),D.getViewValueFromOption(a)):null},E.trackBy&&b.$watch(function(){return E.getTrackByValue(t.$viewValue)},function(){t.$render()}));z?(w.remove(),a(w)(b),w.removeClass("ng-scope")):w=C(c.cloneNode(!1));v();b.$watchCollection(E.getWatchables,v)}}}}],Ie=["$locale","$interpolate","$log",function(a,b,d){var c=/{}/g,e=/^when(Minus)?(.+)$/;return{link:function(f,g,h){function k(a){g.text(a||"")}var l=h.count,m=h.$attr.when&&g.attr(h.$attr.when),r=h.offset||0,q=f.$eval(m)||{},v=
-{},y=b.startSymbol(),t=b.endSymbol(),p=y+l+"-"+r+t,w=ia.noop,u;n(h,function(a,b){var c=e.exec(b);c&&(c=(c[1]?"-":"")+G(c[2]),q[c]=g.attr(h.$attr[b]))});n(q,function(a,d){v[d]=b(a.replace(c,p))});f.$watch(l,function(b){var c=parseFloat(b),e=isNaN(c);e||c in q||(c=a.pluralCat(c-r));c===u||e&&N(u)&&isNaN(u)||(w(),e=v[c],x(e)?(null!=b&&d.debug("ngPluralize: no rule defined for '"+c+"' in "+m),w=B,k()):w=f.$watch(e,k),u=c)})}}}],Je=["$parse","$animate",function(a,b){var d=H("ngRepeat"),c=function(a,b,
-c,d,k,l,m){a[c]=d;k&&(a[k]=l);a.$index=b;a.$first=0===b;a.$last=b===m-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(b&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(e,f){var g=f.ngRepeat,h=W.createComment(" end ngRepeat: "+g+" "),k=g.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",g);var l=k[1],m=k[2],r=k[3],q=k[4],k=l.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
-if(!k)throw d("iidexp",l);var x=k[3]||k[1],y=k[2];if(r&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(r)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(r)))throw d("badident",r);var t,p,w,u,B={$id:Fa};q?t=a(q):(w=function(a,b){return Fa(b)},u=function(a){return a});return function(a,e,f,k,l){t&&(p=function(b,c,d){y&&(B[y]=b);B[x]=c;B.$index=d;return t(a,B)});var q=Z();a.$watchCollection(m,function(f){var k,m,s=e[0],t,B=Z(),D,E,H,F,L,G,N;r&&(a[r]=f);if(Ca(f))L=
-f,m=p||w;else for(N in m=p||u,L=[],f)sa.call(f,N)&&"$"!==N.charAt(0)&&L.push(N);D=L.length;N=Array(D);for(k=0;k<D;k++)if(E=f===L?k:L[k],H=f[E],F=m(E,H,k),q[F])G=q[F],delete q[F],B[F]=G,N[k]=G;else{if(B[F])throw n(N,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",g,F,H);N[k]={id:F,scope:v,clone:v};B[F]=!0}for(t in q){G=q[t];F=tb(G.clone);b.leave(F);if(F[0].parentNode)for(k=0,m=F.length;k<m;k++)F[k].$$NG_REMOVED=!0;G.scope.$destroy()}for(k=0;k<D;k++)if(E=f===L?k:L[k],H=f[E],G=N[k],G.scope){t=s;do t=
-t.nextSibling;while(t&&t.$$NG_REMOVED);G.clone[0]!=t&&b.move(tb(G.clone),null,C(s));s=G.clone[G.clone.length-1];c(G.scope,k,x,H,y,E,D)}else l(function(a,d){G.scope=d;var e=h.cloneNode(!1);a[a.length++]=e;b.enter(a,null,C(s));s=e;G.clone=a;B[G.id]=G;c(G.scope,k,x,H,y,E,D)});q=B})}}}}],Ke=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngShow,function(b){a[b?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],De=["$animate",function(a){return{restrict:"A",
-multiElement:!0,link:function(b,d,c){b.$watch(c.ngHide,function(b){a[b?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Le=Ma(function(a,b,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&n(d,function(a,c){b.css(c,"")});a&&b.css(a)},!0)}),Me=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(b,d,c,e){var f=[],g=[],h=[],k=[],l=function(a,b){return function(){a.splice(b,1)}};b.$watch(c.ngSwitch||c.on,function(b){var c,
-d;c=0;for(d=h.length;c<d;++c)a.cancel(h[c]);c=h.length=0;for(d=k.length;c<d;++c){var q=tb(g[c].clone);k[c].$destroy();(h[c]=a.leave(q)).then(l(h,c))}g.length=0;k.length=0;(f=e.cases["!"+b]||e.cases["?"])&&n(f,function(b){b.transclude(function(c,d){k.push(d);var e=b.element;c[c.length++]=W.createComment(" end ngSwitchWhen: ");g.push({clone:c});a.enter(c,e.parent(),e)})})})}}}],Ne=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["!"+d.ngSwitchWhen]=
-c.cases["!"+d.ngSwitchWhen]||[];c.cases["!"+d.ngSwitchWhen].push({transclude:e,element:b})}}),Oe=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["?"]=c.cases["?"]||[];c.cases["?"].push({transclude:e,element:b})}}),Rg=H("ngTransclude"),Qe=Ma({restrict:"EAC",link:function(a,b,d,c,e){d.ngTransclude===d.$attr.ngTransclude&&(d.ngTransclude="");if(!e)throw Rg("orphan",ta(b));e(function(a){a.length&&(b.empty(),b.append(a))},null,d.ngTransclude||
-d.ngTranscludeSlot)}}),qe=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(b,d){"text/ng-template"==d.type&&a.put(d.id,b[0].text)}}}],Sg={$setViewValue:B,$render:B},Tg=["$element","$scope","$attrs",function(a,b,d){var c=this,e=new Ua;c.ngModelCtrl=Sg;c.unknownOption=C(W.createElement("option"));c.renderUnknownOption=function(b){b="? "+Fa(b)+" ?";c.unknownOption.val(b);a.prepend(c.unknownOption);a.val(b)};b.$on("$destroy",function(){c.renderUnknownOption=B});c.removeUnknownOption=
-function(){c.unknownOption.parent()&&c.unknownOption.remove()};c.readValue=function(){c.removeUnknownOption();return a.val()};c.writeValue=function(b){c.hasOption(b)?(c.removeUnknownOption(),a.val(b),""===b&&c.emptyOption.prop("selected",!0)):null==b&&c.emptyOption?(c.removeUnknownOption(),a.val("")):c.renderUnknownOption(b)};c.addOption=function(a,b){if(8!==b[0].nodeType){Ta(a,'"option value"');""===a&&(c.emptyOption=b);var d=e.get(a)||0;e.put(a,d+1);c.ngModelCtrl.$render();b[0].hasAttribute("selected")&&
-(b[0].selected=!0)}};c.removeOption=function(a){var b=e.get(a);b&&(1===b?(e.remove(a),""===a&&(c.emptyOption=v)):e.put(a,b-1))};c.hasOption=function(a){return!!e.get(a)};c.registerOption=function(a,b,d,e,l){if(e){var m;d.$observe("value",function(a){y(m)&&c.removeOption(m);m=a;c.addOption(a,b)})}else l?a.$watch(l,function(a,e){d.$set("value",a);e!==a&&c.removeOption(e);c.addOption(a,b)}):c.addOption(d.value,b);b.on("$destroy",function(){c.removeOption(d.value);c.ngModelCtrl.$render()})}}],re=function(){return{restrict:"E",
-require:["select","?ngModel"],controller:Tg,priority:1,link:{pre:function(a,b,d,c){var e=c[1];if(e){var f=c[0];f.ngModelCtrl=e;b.on("change",function(){a.$apply(function(){e.$setViewValue(f.readValue())})});if(d.multiple){f.readValue=function(){var a=[];n(b.find("option"),function(b){b.selected&&a.push(b.value)});return a};f.writeValue=function(a){var c=new Ua(a);n(b.find("option"),function(a){a.selected=y(c.get(a.value))})};var g,h=NaN;a.$watch(function(){h!==e.$viewValue||oa(g,e.$viewValue)||(g=
-na(e.$viewValue),e.$render());h=e.$viewValue});e.$isEmpty=function(a){return!a||0===a.length}}}},post:function(a,b,d,c){var e=c[1];if(e){var f=c[0];e.$render=function(){f.writeValue(e.$viewValue)}}}}}},te=["$interpolate",function(a){return{restrict:"E",priority:100,compile:function(b,d){if(y(d.value))var c=a(d.value,!0);else{var e=a(b.text(),!0);e||d.$set("value",b.text())}return function(a,b,d){var k=b.parent();(k=k.data("$selectController")||k.parent().data("$selectController"))&&k.registerOption(a,
-b,d,c,e)}}}}],se=ba({restrict:"E",terminal:!1}),Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){c&&(d.required=!0,c.$validators.required=function(a,b){return!d.required||!c.$isEmpty(b)},d.$observe("required",function(){c.$validate()}))}}},Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e,f=d.ngPattern||d.pattern;d.$observe("pattern",function(a){F(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw H("ngPattern")("noregexp",
-f,a,ta(b));e=a||v;c.$validate()});c.$validators.pattern=function(a,b){return c.$isEmpty(b)||x(e)||e.test(b)}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=-1;d.$observe("maxlength",function(a){a=ca(a);e=isNaN(a)?-1:a;c.$validate()});c.$validators.maxlength=function(a,b){return 0>e||c.$isEmpty(b)||b.length<=e}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=ca(a)||0;c.$validate()});
-c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(je(),le(ia),ia.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),
-SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",
-PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,c){var e=a|0,f=c;v===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),C(W).ready(function(){fe(W,Ac)}))})(window,document);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
-//# sourceMappingURL=angular.min.js.map
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js.map b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js.map
deleted file mode 100644
index 07fc1ce3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/angular.min.js.map
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-"version":3,
-"file":"angular.min.js",
-"lineCount":306,
-"mappings":"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",
-"sources":["angular.js"],
-"names":["window","document","undefined","minErr","isArrayLike","obj","isWindow","isArray","isString","jqLite","length","Object","isNumber","Array","item","forEach","iterator","context","key","isFunction","hasOwnProperty","call","isPrimitive","isBlankObject","forEachSorted","keys","sort","i","reverseParams","iteratorFn","value","nextUid","uid","baseExtend","dst","objs","deep","h","$$hashKey","ii","isObject","j","jj","src","isDate","Date","valueOf","isRegExp","RegExp","nodeName","cloneNode","isElement","clone","extend","slice","arguments","merge","toInt","str","parseInt","inherit","parent","extra","create","noop","identity","$","valueFn","hasCustomToString","toString","isUndefined","isDefined","getPrototypeOf","isScope","$evalAsync","$watch","isBoolean","isTypedArray","TYPED_ARRAY_REGEXP","test","node","prop","attr","find","makeMap","items","split","nodeName_","element","lowercase","arrayRemove","array","index","indexOf","splice","copy","source","destination","copyRecurse","push","copyElement","stackSource","stackDest","ngMinErr","needsRecurse","copyType","constructor","buffer","copied","ArrayBuffer","byteLength","set","Uint8Array","re","match","lastIndex","shallowCopy","charAt","equals","o1","o2","t1","t2","getTime","keySet","createMap","concat","array1","array2","bind","self","fn","curryArgs","startIndex","apply","toJsonReplacer","val","toJson","pretty","JSON","stringify","fromJson","json","parse","timezoneToOffset","timezone","fallback","replace","ALL_COLONS","requestedTimezoneOffset","isNaN","convertTimezoneToLocal","date","reverse","dateTimezoneOffset","getTimezoneOffset","timezoneOffset","setMinutes","getMinutes","minutes","startingTag","empty","e","elemHtml","append","html","nodeType","NODE_TYPE_TEXT","tryDecodeURIComponent","decodeURIComponent","parseKeyValue","keyValue","splitPoint","substring","toKeyValue","parts","arrayValue","encodeUriQuery","join","encodeUriSegment","pctEncodeSpaces","encodeURIComponent","getNgAttribute","ngAttr","ngAttrPrefixes","getAttribute","angularInit","bootstrap","appElement","module","config","prefix","name","hasAttribute","candidate","querySelector","strictDi","modules","defaultConfig","doBootstrap","injector","tag","unshift","$provide","debugInfoEnabled","$compileProvider","createInjector","invoke","bootstrapApply","scope","compile","$apply","data","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","angular","resumeBootstrap","angular.resumeBootstrap","extraModules","resumeDeferredBootstrap","reloadWithDebugInfo","location","reload","getTestability","rootElement","get","snake_case","separator","SNAKE_CASE_REGEXP","letter","pos","toLowerCase","bindJQuery","originalCleanData","bindJQueryFired","jqName","jq","jQuery","on","JQLitePrototype","isolateScope","controller","inheritedData","cleanData","jQuery.cleanData","elems","events","elem","_data","$destroy","triggerHandler","JQLite","assertArg","arg","reason","assertArgFn","acceptArrayAnnotation","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","nextSibling","setupModuleLoader","ensure","factory","$injectorMinErr","$$minErr","requires","configFn","invokeLater","provider","method","insertMethod","queue","invokeQueue","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","configBlocks","runBlocks","_invokeQueue","_configBlocks","_runBlocks","service","constant","decorator","animation","filter","directive","component","run","block","publishExternalAPI","version","uppercase","counter","csp","angularModule","ngModule","$$sanitizeUri","$$SanitizeUriProvider","$CompileProvider","a","htmlAnchorDirective","input","inputDirective","textarea","form","formDirective","script","scriptDirective","select","selectDirective","style","styleDirective","option","optionDirective","ngBind","ngBindDirective","ngBindHtml","ngBindHtmlDirective","ngBindTemplate","ngBindTemplateDirective","ngClass","ngClassDirective","ngClassEven","ngClassEvenDirective","ngClassOdd","ngClassOddDirective","ngCloak","ngCloakDirective","ngController","ngControllerDirective","ngForm","ngFormDirective","ngHide","ngHideDirective","ngIf","ngIfDirective","ngInclude","ngIncludeDirective","ngInit","ngInitDirective","ngNonBindable","ngNonBindableDirective","ngPluralize","ngPluralizeDirective","ngRepeat","ngRepeatDirective","ngShow","ngShowDirective","ngStyle","ngStyleDirective","ngSwitch","ngSwitchDirective","ngSwitchWhen","ngSwitchWhenDirective","ngSwitchDefault","ngSwitchDefaultDirective","ngOptions","ngOptionsDirective","ngTransclude","ngTranscludeDirective","ngModel","ngModelDirective","ngList","ngListDirective","ngChange","ngChangeDirective","pattern","patternDirective","ngPattern","required","requiredDirective","ngRequired","minlength","minlengthDirective","ngMinlength","maxlength","maxlengthDirective","ngMaxlength","ngValue","ngValueDirective","ngModelOptions","ngModelOptionsDirective","ngIncludeFillContentDirective","ngAttributeAliasDirectives","ngEventDirectives","$anchorScroll","$AnchorScrollProvider","$animate","$AnimateProvider","$animateCss","$CoreAnimateCssProvider","$$animateJs","$$CoreAnimateJsProvider","$$animateQueue","$$CoreAnimateQueueProvider","$$AnimateRunner","$$AnimateRunnerFactoryProvider","$$animateAsyncRun","$$AnimateAsyncRunFactoryProvider","$browser","$BrowserProvider","$cacheFactory","$CacheFactoryProvider","$controller","$ControllerProvider","$document","$DocumentProvider","$exceptionHandler","$ExceptionHandlerProvider","$filter","$FilterProvider","$$forceReflow","$$ForceReflowProvider","$interpolate","$InterpolateProvider","$interval","$IntervalProvider","$http","$HttpProvider","$httpParamSerializer","$HttpParamSerializerProvider","$httpParamSerializerJQLike","$HttpParamSerializerJQLikeProvider","$httpBackend","$HttpBackendProvider","$xhrFactory","$xhrFactoryProvider","$location","$LocationProvider","$log","$LogProvider","$parse","$ParseProvider","$rootScope","$RootScopeProvider","$q","$QProvider","$$q","$$QProvider","$sce","$SceProvider","$sceDelegate","$SceDelegateProvider","$sniffer","$SnifferProvider","$templateCache","$TemplateCacheProvider","$templateRequest","$TemplateRequestProvider","$$testability","$$TestabilityProvider","$timeout","$TimeoutProvider","$window","$WindowProvider","$$rAF","$$RAFProvider","$$jqLite","$$jqLiteProvider","$$HashMap","$$HashMapProvider","$$cookieReader","$$CookieReaderProvider","camelCase","SPECIAL_CHARS_REGEXP","_","offset","toUpperCase","MOZ_HACK_REGEXP","jqLiteAcceptsData","NODE_TYPE_ELEMENT","NODE_TYPE_DOCUMENT","jqLiteBuildFragment","tmp","fragment","createDocumentFragment","HTML_REGEXP","appendChild","createElement","TAG_NAME_REGEXP","exec","wrap","wrapMap","_default","innerHTML","XHTML_TAG_REGEXP","lastChild","childNodes","firstChild","textContent","createTextNode","jqLiteWrapNode","wrapper","parentNode","replaceChild","argIsString","trim","jqLiteMinErr","parsed","SINGLE_TAG_REGEXP","jqLiteAddNodes","jqLiteClone","jqLiteDealoc","onlyDescendants","jqLiteRemoveData","querySelectorAll","descendants","l","jqLiteOff","type","unsupported","expandoStore","jqLiteExpandoStore","handle","removeHandler","listenerFns","removeEventListener","MOUSE_EVENT_MAP","expandoId","ng339","jqCache","createIfNecessary","jqId","jqLiteData","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","setAttribute","cssClass","jqLiteAddClass","existingClasses","root","elements","jqLiteController","jqLiteInheritedData","documentElement","names","NODE_TYPE_DOCUMENT_FRAGMENT","host","jqLiteEmpty","removeChild","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","readyState","setTimeout","getBooleanAttrName","booleanAttr","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","createEventHandler","eventHandler","event","isDefaultPrevented","event.isDefaultPrevented","defaultPrevented","eventFns","eventFnsLength","immediatePropagationStopped","originalStopImmediatePropagation","stopImmediatePropagation","event.stopImmediatePropagation","stopPropagation","isImmediatePropagationStopped","event.isImmediatePropagationStopped","handlerWrapper","specialHandlerWrapper","defaultHandlerWrapper","handler","specialMouseHandlerWrapper","target","related","relatedTarget","jqLiteContains","$get","this.$get","hasClass","classes","addClass","removeClass","hashKey","nextUidFn","objType","HashMap","isolatedUid","this.nextUid","put","extractArgs","fnText","STRIP_COMMENTS","ARROW_ARG","FN_ARGS","anonFn","args","modulesToLoad","supportObject","delegate","provider_","providerInjector","instantiate","providerCache","providerSuffix","enforceReturnValue","enforcedReturnValue","result","instanceInjector","factoryFn","enforce","loadModules","moduleFn","runInvokeQueue","invokeArgs","loadedModules","message","stack","createInternalInjector","cache","getService","serviceName","caller","INSTANTIATING","err","shift","injectionArgs","locals","$inject","$$annotate","msie","Function","prototype","Type","ctor","annotate","has","$injector","instanceCache","decorFn","origProvider","orig$get","origProvider.$get","origInstance","$delegate","protoInstanceInjector","autoScrollingEnabled","disableAutoScrolling","this.disableAutoScrolling","getFirstAnchor","list","some","scrollTo","scrollIntoView","scroll","yOffset","getComputedStyle","position","getBoundingClientRect","bottom","elemTop","top","scrollBy","hash","elm","getElementById","getElementsByName","autoScrollWatch","autoScrollWatchAction","newVal","oldVal","mergeClasses","b","splitClasses","klass","prepareAnimateOptions","options","Browser","completeOutstandingRequest","outstandingRequestCount","outstandingRequestCallbacks","pop","error","cacheStateAndFireUrlChange","pendingLocation","cacheState","fireUrlChange","history","state","cachedState","lastCachedState","lastBrowserUrl","url","lastHistoryState","urlChangeListeners","listener","clearTimeout","pendingDeferIds","isMock","$$completeOutstandingRequest","$$incOutstandingRequestCount","self.$$incOutstandingRequestCount","notifyWhenNoOutstandingRequests","self.notifyWhenNoOutstandingRequests","callback","href","baseElement","self.url","sameState","sameBase","stripHash","substr","self.state","urlChangeInit","onUrlChange","self.onUrlChange","$$applicationDestroyed","self.$$applicationDestroyed","off","$$checkUrlChange","baseHref","self.baseHref","defer","self.defer","delay","timeoutId","cancel","self.defer.cancel","deferId","cacheFactory","cacheId","refresh","entry","freshEnd","staleEnd","n","link","p","nextEntry","prevEntry","caches","size","stats","id","capacity","Number","MAX_VALUE","lruHash","lruEntry","remove","removeAll","destroy","info","cacheFactory.info","cacheFactory.get","$$sanitizeUriProvider","parseIsolateBindings","directiveName","isController","LOCAL_REGEXP","bindings","definition","scopeName","$compileMinErr","mode","collection","optional","attrName","assertValidDirectiveName","hasDirectives","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","REQUIRE_PREFIX_REGEXP","EVENT_HANDLER_ATTR_REGEXP","this.directive","registerDirective","directiveFactory","Suffix","directives","priority","require","restrict","bindToController","controllerAs","identifierForController","$$bindings","$$isolateBindings","this.component","makeInjectable","tElement","tAttrs","$element","$attrs","template","templateUrl","transclude","aHrefSanitizationWhitelist","this.aHrefSanitizationWhitelist","regexp","imgSrcSanitizationWhitelist","this.imgSrcSanitizationWhitelist","this.debugInfoEnabled","enabled","setSpecialAttr","specialAttrHolder","attributes","attribute","removeNamedItem","setNamedItem","safeAddClass","className","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","NOT_EMPTY","domNode","nodeValue","compositeLinkFn","compileNodes","$$addScopeClass","namespace","publicLinkFn","cloneConnectFn","needsNewScope","$parent","$new","parentBoundTranscludeFn","transcludeControllers","futureParentElement","$$boundTransclude","$linkNode","wrapTemplate","controllerName","instance","$$addScopeInfo","nodeList","$rootElement","childLinkFn","childScope","childBoundTranscludeFn","stableNodeList","nodeLinkFnFound","linkFns","idx","nodeLinkFn","transcludeOnThisElement","createBoundTranscludeFn","templateOnThisElement","attrs","linkFnFound","Attributes","collectDirectives","applyDirectivesToNode","$$element","terminal","previousBoundTranscludeFn","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","$$transcluded","boundSlots","$$slots","slotName","attrsMap","$attr","addDirective","directiveNormalize","isNgAttr","nAttrs","attrStartName","attrEndName","ngAttrName","NG_ATTR_BINDING","PREFIX_REGEXP","multiElementMatch","MULTI_ELEMENT_DIR_RE","directiveIsMultiElement","nName","addAttrInterpolateDirective","animVal","addTextInterpolateDirective","NODE_TYPE_COMMENT","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","compilationGenerator","eager","compiled","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","addLinkFns","pre","post","newIsolateScopeDirective","$$isolateScope","cloneAndAnnotateFn","getControllers","elementControllers","inheritType","dataName","property","setupControllers","controllerDirectives","controllerKey","$scope","$transclude","controllerInstance","hasElementTranscludeDirective","linkNode","controllersBoundTransclude","cloneAttachFn","slotTranscludeFn","scopeToChild","removeScopeBindingWatches","controllerScope","newScopeDirective","isSlotFilled","transcludeFn.isSlotFilled","templateDirective","$$originalDirective","initializeDirectiveBindings","$on","controllerDirective","identifier","removeControllerBindingWatches","controllerResult","$onInit","invokeLinkFn","terminalPriority","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","$compileNode","$template","childTranscludeFn","didScanForMultipleTransclusion","mightHaveMultipleTransclusionError","directiveValue","$$start","$$end","assertNoDuplicate","$$tlb","scanningIndex","candidateDirective","createComment","replaceWith","replaceDirective","slots","contents","slotMap","filledSlots","elementSelector","filled","$$newScope","denormalizeTemplate","removeComments","templateNamespace","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectiveScope","mergeTemplateAttributes","compileTemplateUrl","Math","max","newScope","tDirectives","startAttrName","endAttrName","multiElement","srcAttr","dstAttr","$set","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","then","content","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","$$destroyed","oldClasses","delayedNodeLinkFn","ignoreChildLinkFn","diff","what","previousDirective","wrapModuleNameIfDefined","moduleName","text","interpolateFn","textInterpolateCompileFn","templateNode","templateNodeParent","hasCompileParent","$$addBindingClass","textInterpolateLinkFn","$$addBindingInfo","expressions","interpolateFnWatchAction","getTrustedContext","attrNormalizedName","HTML","RESOURCE_URL","allOrNothing","trustedContext","attrInterpolatePreLinkFn","$$observers","newValue","$$inter","$$scope","oldValue","$updateClass","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","hasData","annotation","removeWatchCollection","lastValue","parentGet","parentSet","compare","$observe","literal","assign","parentValueWatch","parentValue","$stateful","removeWatch","$watchCollection","parentValueWatchAction","newParentValue","removeWatches","SIMPLE_ATTR_NAME","attributesToCopy","$normalize","$addClass","classVal","$removeClass","newClasses","toAdd","tokenDifference","toRemove","writeAttr","booleanKey","aliasedKey","ALIASED_ATTR","observer","trimmedSrcset","srcPattern","rawUris","nbrUrisWith2parts","floor","innerIdx","lastTuple","removeAttr","listeners","startSymbol","endSymbol","binding","isolated","noTemplate","str1","str2","values","tokens1","tokens2","token","jqNodes","ident","CNTRL_REG","globals","register","this.register","allowGlobals","this.allowGlobals","addIdentifier","expression","later","$controllerMinErr","controllerPrototype","exception","cause","serializeValue","v","toISOString","ngParamSerializer","params","k","jQueryLikeParamSerializer","serialize","toSerialize","topLevel","defaultHttpResponseTransform","headers","tempData","JSON_PROTECTION_PREFIX","contentType","jsonStart","JSON_START","JSON_ENDS","parseHeaders","line","headerVal","headerKey","headersGetter","headersObj","transformData","status","fns","defaults","transformResponse","transformRequest","d","common","CONTENT_TYPE_APPLICATION_JSON","patch","xsrfCookieName","xsrfHeaderName","paramSerializer","useApplyAsync","this.useApplyAsync","useLegacyPromise","useLegacyPromiseExtensions","this.useLegacyPromiseExtensions","interceptorFactories","interceptors","requestConfig","response","resp","reject","executeHeaderFns","headerContent","processedHeaders","headerFn","header","mergeHeaders","defHeaders","reqHeaders","defHeaderName","lowercaseDefHeaderName","reqHeaderName","chain","serverRequest","reqData","withCredentials","sendReq","promise","when","reversedInterceptors","interceptor","request","requestError","responseError","thenFn","rejectFn","success","promise.success","promise.error","$httpMinErrLegacyFn","done","headersString","statusText","resolveHttpPromise","resolvePromise","$applyAsync","$$phase","deferred","resolve","resolvePromiseWithResult","removePendingReq","pendingRequests","cachedResp","buildUrl","defaultCache","xsrfValue","urlIsSameOrigin","timeout","responseType","serializedParams","interceptorFactory","createShortMethods","createShortMethodsWithData","createXhr","XMLHttpRequest","createHttpBackend","callbacks","$browserDefer","rawDocument","jsonpReq","callbackId","async","body","called","addEventListener","timeoutRequest","jsonpDone","xhr","abort","completeRequest","open","setRequestHeader","onload","xhr.onload","responseText","urlResolve","protocol","getAllResponseHeaders","onerror","onabort","send","this.startSymbol","this.endSymbol","escape","ch","unescapeText","escapedStartRegexp","escapedEndRegexp","constantWatchDelegate","objectEquality","constantInterp","unwatch","constantInterpolateWatch","mustHaveExpression","parseStringifyInterceptor","getTrusted","$interpolateMinErr","interr","unescapedText","exp","$$watchDelegate","endIndex","parseFns","textLength","expressionPositions","startSymbolLength","endSymbolLength","throwNoconcat","compute","interpolationFn","$watchGroup","interpolateFnWatcher","oldValues","currValue","$interpolate.startSymbol","$interpolate.endSymbol","interval","count","invokeApply","hasParams","iteration","setInterval","clearInterval","skipApply","$$intervalId","tick","notify","intervals","interval.cancel","encodePath","segments","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","$$protocol","$$host","hostname","$$port","port","DEFAULT_PORTS","parseAppUrl","relativeUrl","prefixed","$$path","pathname","$$search","search","$$hash","beginsWith","begin","whole","trimEmptyHash","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","$$html5","$$parse","this.$$parse","pathUrl","$locationMinErr","$$compose","this.$$compose","$$url","$$absUrl","$$parseLinkUrl","this.$$parseLinkUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","windowsFilePathExp","base","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationGetter","locationGetterSetter","preprocess","html5Mode","requireBase","rewriteLinks","this.hashPrefix","this.html5Mode","setBrowserUrlWithFallback","oldUrl","oldState","$$state","afterLocationChange","$broadcast","absUrl","LocationMode","initialUrl","lastIndexOf","IGNORE_URI_REGEXP","ctrlKey","metaKey","shiftKey","which","button","absHref","preventDefault","initializing","newUrl","newState","$digest","$locationWatch","currentReplace","$$replace","urlOrStateChanged","debug","debugEnabled","this.debugEnabled","flag","formatError","Error","sourceURL","consoleLog","console","logFn","log","hasApply","arg1","arg2","warn","ensureSafeMemberName","fullExpression","$parseMinErr","getStringValue","ensureSafeObject","children","ensureSafeFunction","CALL","APPLY","BIND","ensureSafeAssignContext","ifDefined","plusFn","r","findConstantAndWatchExpressions","ast","allConstants","argsToWatch","AST","Program","expr","Literal","toWatch","UnaryExpression","argument","BinaryExpression","left","right","LogicalExpression","ConditionalExpression","alternate","consequent","Identifier","MemberExpression","object","computed","CallExpression","callee","AssignmentExpression","ArrayExpression","ObjectExpression","properties","ThisExpression","LocalsExpression","getInputs","lastExpression","isAssignable","assignableAST","NGValueParameter","operator","isLiteral","ASTCompiler","astBuilder","ASTInterpreter","isPossiblyDangerousMemberName","getValueOf","objectValueOf","cacheDefault","cacheExpensive","interceptorFn","expensiveChecks","parsedExpression","oneTime","cacheKey","runningChecksEnabled","parseOptions","$parseOptionsExpensive","$parseOptions","lexer","Lexer","parser","Parser","oneTimeLiteralWatchDelegate","oneTimeWatchDelegate","inputs","inputsWatchDelegate","expensiveChecksInterceptor","addInterceptor","expensiveCheckFn","expensiveCheckOldValue","expressionInputDirtyCheck","oldValueOfValue","prettyPrintExpression","inputExpressions","lastResult","oldInputValueOf","expressionInputWatch","newInputValue","oldInputValueOfValues","oldInputValues","expressionInputsWatch","changed","oneTimeWatch","oneTimeListener","old","$$postDigest","isAllDefined","allDefined","constantWatch","watchDelegate","useInputs","regularInterceptedExpression","oneTimeInterceptedExpression","noUnsafeEval","$$runningExpensiveChecks","$parse.$$runningExpensiveChecks","qFactory","nextTick","exceptionHandler","Promise","simpleBind","scheduleProcessQueue","processScheduled","pending","Deferred","$qMinErr","TypeError","onFulfilled","onRejected","progressBack","catch","finally","handleCallback","$$reject","$$resolve","that","rejectPromise","progress","makePromise","resolved","isResolved","callbackOutput","errback","$Q","resolver","resolveFn","all","promises","results","requestAnimationFrame","webkitRequestAnimationFrame","cancelAnimationFrame","webkitCancelAnimationFrame","webkitCancelRequestAnimationFrame","rafSupported","raf","timer","supported","createChildScopeClass","ChildScope","$$watchers","$$nextSibling","$$childHead","$$childTail","$$listeners","$$listenerCount","$$watchersCount","$id","$$ChildScope","TTL","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","digestTtl","this.digestTtl","destroyChildScope","$event","currentScope","cleanUpScope","$$prevSibling","$root","Scope","beginPhase","phase","incrementWatchersCount","current","decrementListenerCount","initWatchVal","flushApplyAsync","applyAsyncQueue","scheduleApplyAsync","isolate","child","watchExp","watcher","last","eq","deregisterWatch","watchExpressions","watchGroupAction","changeReactionScheduled","firstRun","newValues","deregisterFns","shouldCall","deregisterWatchGroup","unwatchFn","watchGroupSubAction","$watchCollectionInterceptor","_value","bothNaN","newItem","oldItem","internalArray","oldLength","changeDetected","newLength","internalObject","veryOldValue","trackVeryOldValue","changeDetector","initRun","$watchCollectionAction","watch","watchers","dirty","ttl","watchLog","logIdx","asyncTask","asyncQueue","$eval","msg","next","postDigestQueue","eventName","this.$watchGroup","$applyAsyncExpression","namedListeners","indexOfListener","$emit","targetScope","listenerArgs","$$asyncQueue","$$postDigestQueue","$$applyAsyncQueue","sanitizeUri","uri","isImage","regex","normalizedVal","adjustMatcher","matcher","$sceMinErr","escapeForRegexp","adjustMatchers","matchers","adjustedMatchers","SCE_CONTEXTS","resourceUrlWhitelist","resourceUrlBlacklist","this.resourceUrlWhitelist","this.resourceUrlBlacklist","matchUrl","generateHolderType","Base","holderType","trustedValue","$$unwrapTrustedValue","this.$$unwrapTrustedValue","holderType.prototype.valueOf","holderType.prototype.toString","htmlSanitizer","trustedValueHolderBase","byType","CSS","URL","JS","trustAs","Constructor","maybeTrusted","allowed","this.enabled","sce","isEnabled","sce.isEnabled","sce.getTrusted","parseAs","sce.parseAs","enumValue","lName","eventSupport","android","userAgent","navigator","boxee","vendorPrefix","vendorRegex","bodyStyle","transitions","animations","webkitTransition","webkitAnimation","pushState","hasEvent","divElm","httpOptions","this.httpOptions","handleRequestFn","tpl","ignoreRequestError","totalPendingRequests","getTrustedResourceUrl","transformer","handleError","testability","testability.findBindings","opt_exactMatch","getElementsByClassName","matches","dataBinding","bindingName","testability.findModels","prefixes","attributeEquals","testability.getLocation","testability.setLocation","testability.whenStable","deferreds","$$timeoutId","timeout.cancel","urlParsingNode","requestUrl","originUrl","$$CookieReader","safeDecodeURIComponent","lastCookies","lastCookieString","cookieArray","cookie","currentCookieString","filters","suffix","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","matchAgainstAnyProp","getTypeForFilter","expressionType","predicateFn","createPredicateFn","shouldMatchPrimitives","actual","expected","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","$locale","formats","NUMBER_FORMATS","amount","currencySymbol","fractionSize","CURRENCY_SYM","PATTERNS","maxFrac","formatNumber","GROUP_SEP","DECIMAL_SEP","number","numStr","exponent","digits","numberOfIntegerDigits","zeros","ZERO_CHAR","MAX_DIGITS","roundNumber","parsedNumber","minFrac","fractionLen","min","roundAt","digit","carry","reduceRight","groupSep","decimalSep","isInfinity","isFinite","isZero","abs","formattedText","integerLen","decimals","reduce","groups","lgSize","gSize","negPre","negSuf","posPre","posSuf","padNumber","num","neg","dateGetter","dateStrGetter","shortForm","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getDay","weekGetter","firstThurs","getFullYear","thisThurs","getMonth","getDate","round","eraGetter","ERAS","jsonStringToDate","string","R_ISO8601_STR","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","m","s","ms","parseFloat","format","DATETIME_FORMATS","NUMBER_STRING","DATE_FORMATS_SPLIT","DATE_FORMATS","spacing","limit","Infinity","processPredicates","sortPredicate","reverseOrder","map","predicate","descending","predicates","compareValues","getComparisonObject","predicateValues","doComparison","v1","v2","ngDirective","FormController","controls","$error","$$success","$pending","$name","$dirty","$pristine","$valid","$invalid","$submitted","$$parentForm","nullFormCtrl","$rollbackViewValue","form.$rollbackViewValue","control","$commitViewValue","form.$commitViewValue","$addControl","form.$addControl","$$renameControl","form.$$renameControl","newName","oldName","$removeControl","form.$removeControl","$setValidity","addSetValidityMethod","ctrl","unset","$setDirty","form.$setDirty","PRISTINE_CLASS","DIRTY_CLASS","$setPristine","form.$setPristine","setClass","SUBMITTED_CLASS","$setUntouched","form.$setUntouched","$setSubmitted","form.$setSubmitted","stringBasedInputType","$formatters","$isEmpty","baseInputType","composing","ev","ngTrim","$viewValue","$$hasNativeValidators","$setViewValue","deferListener","origValue","keyCode","$render","ctrl.$render","createDateParser","mapping","iso","ISO_DATE_REGEXP","yyyy","MM","dd","HH","getHours","mm","ss","getSeconds","sss","getMilliseconds","part","NaN","createDateInputType","parseDate","dynamicDateInputType","isValidDate","parseObservedDateValue","badInputChecker","$options","previousDate","$$parserName","$parsers","parsedDate","ngModelMinErr","ngMin","minVal","$validators","ctrl.$validators.min","$validate","ngMax","maxVal","ctrl.$validators.max","validity","VALIDITY_STATE_PROPERTY","badInput","typeMismatch","parseConstantExpr","parseFn","classDirective","arrayDifference","arrayClasses","digestClassCounts","classCounts","classesToUpdate","ngClassWatchAction","$index","old$index","mod","cachedToggleClass","switchValue","classCache","toggleValidationCss","validationErrorKey","isValid","VALID_CLASS","INVALID_CLASS","setValidity","isObjectEmpty","PENDING_CLASS","combinedState","REGEX_STRING_REGEXP","documentMode","rules","ngCspElement","ngCspAttribute","noInlineStyle","name_","el","full","major","minor","dot","codeName","expando","JQLite._data","mouseleave","mouseenter","optgroup","tbody","tfoot","colgroup","caption","thead","th","td","Node","contains","compareDocumentPosition","ready","trigger","fired","removeData","jqLiteHasData","jqLiteCleanData","removeAttribute","css","NODE_TYPE_ATTRIBUTE","lowercasedName","specified","getNamedItem","ret","getText","$dv","multiple","selected","nodeCount","jqLiteOn","types","addHandler","noEventListener","one","onFn","replaceNode","insertBefore","contentDocument","prepend","wrapNode","detach","after","newElement","toggleClass","condition","classCondition","nextElementSibling","getElementsByTagName","extraParameters","dummyEvent","handlerArgs","eventFnsCopy","arg3","unbind","FN_ARG_SPLIT","FN_ARG","argDecl","underscore","$animateMinErr","postDigestElements","updateData","handleCSSClassChanges","existing","pin","domOperation","from","to","classesAdded","add","classesRemoved","runner","complete","$$registeredAnimations","classNameFilter","this.classNameFilter","$$classNameFilter","reservedRegex","NG_ANIMATE_CLASSNAME","domInsert","parentElement","afterElement","afterNode","ELEMENT_NODE","previousElementSibling","end","enter","move","leave","addclass","animate","tempClasses","waitForTick","waitQueue","passed","AnimateRunner","setHost","rafTick","_doneCallbacks","_tick","this._tick","doc","hidden","_state","AnimateRunner.chain","AnimateRunner.all","runners","onProgress","DONE_COMPLETE_STATE","getPromise","resolveHandler","rejectHandler","pause","resume","_resolve","INITIAL_STATE","DONE_PENDING_STATE","initialOptions","closed","$$prepared","cleanupStyles","start","offsetWidth","APPLICATION_JSON","$httpMinErr","$interpolateMinErr.throwNoconcat","$interpolateMinErr.interr","PATH_MATCH","locationPrototype","paramValue","Location","Location.prototype.state","OPERATORS","ESCAPE","lex","tokens","readString","peek","readNumber","isIdent","readIdent","is","isWhitespace","ch2","ch3","op2","op3","op1","throwError","chars","isExpOperator","colStr","peekCh","quote","rawString","hex","String","fromCharCode","rep","ExpressionStatement","Property","program","expressionStatement","expect","filterChain","assignment","ternary","logicalOR","consume","logicalAND","equality","relational","additive","multiplicative","unary","primary","arrayDeclaration","constants","parseArguments","baseExpression","peekToken","kind","e1","e2","e3","e4","peekAhead","t","nextId","vars","own","assignable","stage","computing","recurse","return_","generateFunction","fnKey","intoId","watchId","fnString","USE","STRICT","filterPrefix","watchFns","varsPrefix","section","nameId","recursionFn","skipWatchIdCheck","if_","lazyAssign","computedMember","lazyRecurse","plus","not","getHasOwnProperty","nonComputedMember","addEnsureSafeObject","notNull","addEnsureSafeAssignContext","addEnsureSafeMemberName","addEnsureSafeFunction","member","filterName","defaultValue","stringEscapeRegex","stringEscapeFn","c","charCodeAt","skip","init","fn.assign","rhs","lhs","unary+","unary-","unary!","binary+","binary-","binary*","binary/","binary%","binary===","binary!==","binary==","binary!=","binary<","binary>","binary<=","binary>=","binary&&","binary||","ternary?:","astCompiler","yy","y","MMMM","MMM","M","H","hh","EEEE","EEE","ampmGetter","AMPMS","Z","timeZoneGetter","zone","paddedZone","ww","w","G","GG","GGG","GGGG","longEraGetter","ERANAMES","xlinkHref","propName","defaultLinkFn","normalized","ngBooleanAttrWatchAction","htmlAttr","ngAttrAliasWatchAction","nullFormRenameControl","formDirectiveFactory","isNgForm","getSetter","ngFormCompile","formElement","nameAttr","ngFormPreLink","ctrls","handleFormSubmission","setter","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","inputType","textInputType","weekParser","isoWeek","existingDate","week","hours","seconds","milliseconds","addDays","numberInputType","urlInputType","ctrl.$validators.url","modelValue","viewValue","emailInputType","email","ctrl.$validators.email","radioInputType","checked","checkboxInputType","trueValue","ngTrueValue","falseValue","ngFalseValue","ctrl.$isEmpty","CONSTANT_VALUE_REGEXP","tplAttr","ngValueConstantLink","ngValueLink","valueWatchAction","$compile","ngBindCompile","templateElement","ngBindLink","ngBindWatchAction","ngBindTemplateCompile","ngBindTemplateLink","ngBindHtmlCompile","ngBindHtmlGetter","ngBindHtmlWatch","ngBindHtmlLink","ngBindHtmlWatchAction","getTrustedHtml","$viewChangeListeners","forceAsyncEvents","ngEventHandler","previousElements","ngIfWatchAction","srcExp","onloadExp","autoScrollExp","autoscroll","changeCounter","previousElement","currentElement","cleanupLastIncludeContent","ngIncludeWatchAction","afterAnimation","thisChangeId","namespaceAdaptedClone","trimValues","NgModelController","$modelValue","$$rawModelValue","$asyncValidators","$untouched","$touched","parsedNgModel","parsedNgModelAssign","ngModelGet","ngModelSet","pendingDebounce","parserValid","$$setOptions","this.$$setOptions","getterSetter","invokeModelGetter","invokeModelSetter","$$$p","this.$isEmpty","$$updateEmptyClasses","this.$$updateEmptyClasses","NOT_EMPTY_CLASS","EMPTY_CLASS","currentValidationRunId","this.$setPristine","this.$setDirty","this.$setUntouched","UNTOUCHED_CLASS","TOUCHED_CLASS","$setTouched","this.$setTouched","this.$rollbackViewValue","$$lastCommittedViewValue","this.$validate","prevValid","prevModelValue","allowInvalid","$$runValidators","allValid","$$writeModelToScope","this.$$runValidators","doneCallback","processSyncValidators","syncValidatorsValid","validator","processAsyncValidators","validatorPromises","validationDone","localValidationRunId","processParseErrors","errorKey","this.$commitViewValue","$$parseAndValidate","this.$$parseAndValidate","this.$$writeModelToScope","this.$setViewValue","updateOnDefault","$$debounceViewValueCommit","this.$$debounceViewValueCommit","debounceDelay","debounce","ngModelWatch","formatters","ngModelCompile","ngModelPreLink","modelCtrl","formCtrl","ngModelPostLink","updateOn","DEFAULT_REGEXP","ngOptionsMinErr","NG_OPTIONS_REGEXP","parseOptionsExpression","optionsExp","selectElement","Option","selectValue","label","group","disabled","getOptionValuesKeys","optionValues","optionValuesKeys","keyName","itemKey","valueName","selectAs","trackBy","viewValueFn","trackByFn","getTrackByValueFn","getHashOfValue","getTrackByValue","getLocals","displayFn","groupByFn","disableWhenFn","valuesFn","getWatchables","watchedArray","optionValuesLength","disableWhen","getOptions","optionItems","selectValueMap","optionItem","getOptionFromViewValue","getViewValueFromOption","optionTemplate","optGroupTemplate","ngOptionsPreLink","registerOption","ngOptionsPostLink","updateOptionElement","addOrReuseElement","removeExcessElements","skipEmptyAndUnknownOptions","emptyOption_","emptyOption","unknownOption_","unknownOption","updateOptions","previousValue","selectCtrl","readValue","groupMap","providedEmptyOption","updateOption","optionElement","groupElement","currentOptionElement","ngModelCtrl","nextValue","ngModelCtrl.$isEmpty","writeValue","selectCtrl.writeValue","selectCtrl.readValue","selectedValues","selections","selectedOption","BRACE","IS_WHEN","updateElementText","newText","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","ngPluralizeWatchAction","countIsNaN","pluralCat","whenExpFn","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","$first","$last","$middle","$odd","$even","ngRepeatCompile","ngRepeatEndComment","aliasAs","trackByExp","trackByExpGetter","trackByIdExpFn","trackByIdArrayFn","trackByIdObjFn","hashFnLocals","ngRepeatLink","lastBlockMap","ngRepeatAction","previousNode","nextNode","nextBlockMap","collectionLength","trackById","collectionKeys","nextBlockOrder","trackByIdFn","blockKey","ngRepeatTransclude","ngShowWatchAction","NG_HIDE_CLASS","NG_HIDE_IN_PROGRESS_CLASS","ngHideWatchAction","ngStyleWatchAction","newStyles","oldStyles","ngSwitchController","cases","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","ngSwitchWatchAction","selectedTransclude","caseElement","selectedScope","anchor","ngTranscludeMinErr","ngTranscludeCloneAttachFn","ngTranscludeSlot","noopNgModelController","SelectController","optionsMap","renderUnknownOption","self.renderUnknownOption","unknownVal","removeUnknownOption","self.removeUnknownOption","self.readValue","self.writeValue","hasOption","addOption","self.addOption","removeOption","self.removeOption","self.hasOption","self.registerOption","optionScope","optionAttrs","interpolateValueFn","interpolateTextFn","valueAttributeObserveAction","interpolateWatchAction","selectPreLink","lastView","lastViewRef","selectMultipleWatch","selectPostLink","ngModelCtrl.$render","selectCtrlName","ctrl.$validators.required","patternExp","ctrl.$validators.pattern","intVal","ctrl.$validators.maxlength","ctrl.$validators.minlength","getDecimals","opt_precision","pow","ONE","OTHER","$$csp","head"]
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/errors.json b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/errors.json
deleted file mode 100644
index abb6b943..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/errors.json
+++ /dev/null
@@ -1 +0,0 @@
-{"id":"ng","generated":"Fri Feb 05 2016 03:40:34 GMT-0800 (PST)","errors":{"ng":{"areq":"Argument '{0}' is {1}","cpta":"Can't copy! TypedArray destination cannot be mutated.","test":"no injector found for element argument to getTestability","cpws":"Can't copy! Making copies of Window or Scope instances is not supported.","btstrpd":"App Already Bootstrapped with this Element '{0}'","cpi":"Can't copy! Source and destination are identical.","badname":"hasOwnProperty is not a valid {0} name"},"$http":{"legacy":"The method `{0}` on the promise returned from `$http` has been disabled.","badreq":"Http request configuration url must be a string. Received: {0}"},"ngRepeat":{"badident":"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.","iexp":"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.","dupes":"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}","iidexp":"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'."},"$sce":{"imatcher":"Matchers may only be \"self\", string patterns or RegExp objects","icontext":"Attempted to trust a value in invalid context. Context: {0}; Value: {1}","iwcard":"Illegal sequence *** in string matcher. String: {0}","insecurl":"Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}","iequirks":"Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks mode. You can fix this by adding the text <!doctype html> to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.","unsafe":"Attempting to use an unsafe value in a safe context.","itype":"Attempted to trust a non-string value in a content requiring a string: Context: {0}"},"ngPattern":{"noregexp":"Expected {0} to be a RegExp but was {1}. Element: {2}"},"$controller":{"ctrlfmt":"Badly formed controller string '{0}'. Must match `__name__ as __id__` or `__name__`.","noscp":"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`."},"$parse":{"isecfn":"Referencing Function in Angular expressions is disallowed! Expression: {0}","isecwindow":"Referencing the Window in Angular expressions is disallowed! Expression: {0}","ueoe":"Unexpected end of expression: {0}","isecdom":"Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}","lexerr":"Lexer Error: {0} at column{1} in expression [{2}].","esc":"IMPOSSIBLE","isecobj":"Referencing Object in Angular expressions is disallowed! Expression: {0}","lval":"Trying to assign a value to a non l-value","isecff":"Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}","syntax":"Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].","isecaf":"Assigning to a constructor is disallowed! Expression: {0}","isecfld":"Attempting to access a disallowed field in Angular expressions! Expression: {0}"},"orderBy":{"notarray":"Expected array but received: {0}"},"jqLite":{"offargs":"jqLite#off() does not support the `selector` argument","onargs":"jqLite#on() does not support the `selector` or `eventData` parameters","nosel":"Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"},"$animate":{"notcsel":"Expecting class selector starting with '.' got '{0}'.","nongcls":"$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the \"{0}\" CSS class."},"$q":{"norslvr":"Expected resolverFn, got '{0}'","qcycle":"Expected promise to be resolved with value other than itself '{0}'"},"$injector":{"pget":"Provider '{0}' must define $get factory method.","cdep":"Circular dependency found: {0}","nomod":"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.","strictdi":"{0} is not using explicit annotation and cannot be invoked in strict mode","modulerr":"Failed to instantiate module {0} due to:\n{1}","undef":"Provider '{0}' must return a value from $get factory method.","unpr":"Unknown provider: {0}","itkn":"Incorrect injection token! Expected service name as string, got {0}"},"filter":{"notarray":"Expected array but received: {0}"},"ngTransclude":{"orphan":"Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: {0}"},"ngModel":{"nopromise":"Expected asynchronous validator to return a promise but got '{0}' instead.","nonassign":"Expression '{0}' is non-assignable. Element: {1}","datefmt":"Expected `{0}` to be a date","constexpr":"Expected constant expression for `{0}`, but saw `{1}`.","numfmt":"Expected `{0}` to be a number"},"$location":{"nostate":"History API state support is available only in HTML5 mode and only in browsers supporting HTML5 History API","ipthprfx":"Invalid url \"{0}\", missing path prefix \"{1}\".","isrcharg":"The first argument of the `$location#search()` call must be a string or an object.","nobase":"$location in HTML5 mode requires a <base> tag to be present!"},"$cacheFactory":{"iid":"CacheId '{0}' is already taken!"},"$interpolate":{"noconcat":"Error while interpolating: {0}\nStrict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce","interr":"Can't interpolate: {0}\n{1}","nochgmustache":"angular-message-format.js currently does not allow you to use custom start and end symbols for interpolation.","reqcomma":"Expected a comma after the keyword “{0}†at line {1}, column {2} of text “{3}â€","untermstr":"The string beginning at line {0}, column {1} is unterminated in text “{2}â€","badexpr":"Unexpected operator “{0}†at line {1}, column {2} in text. Was expecting “{3}â€. Text: “{4}â€","dupvalue":"The choice “{0}†is specified more than once. Duplicate key is at line {1}, column {2} in text “{3}â€","unsafe":"Use of select/plural MessageFormat syntax is currently disallowed in a secure context ({0}). At line {1}, column {2} of text “{3}â€","reqother":"“other†is a required option.","reqendinterp":"Expecting end of interpolation symbol, “{0}â€, at line {1}, column {2} in text “{3}â€","reqarg":"Expected one of “plural†or “select†at line {0}, column {1} of text “{2}â€","wantstring":"Expected the beginning of a string at line {0}, column {1} in text “{2}â€","logicbug":"The messageformat parser has encountered an internal error. Please file a github issue against the AngularJS project and provide this message text that triggers the bug. Text: “{0}â€","reqopenbrace":"The plural choice “{0}†must be followed by a message in braces at line {1}, column {2} in text “{3}â€","unknarg":"Unsupported keyword “{0}†at line {0}, column {1}. Only “plural†and “select†are currently supported. Text: “{3}â€","reqendbrace":"The plural/select choice “{0}†message starting at line {1}, column {2} does not have an ending closing brace. Text “{3}â€"},"ngOptions":{"iexp":"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}"},"$rootScope":{"inprog":"{0} already in progress","infdig":"{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}"},"$compile":{"noident":"Cannot bind to controller without identifier for directive '{0}'.","selmulti":"Binding to the 'multiple' attribute is not supported. Element: {0}","ctreq":"Controller '{0}', required by directive '{1}', can't be found!","tplrt":"Template for directive '{0}' must have exactly one root element. {1}","iscp":"Invalid {3} for directive '{0}'. Definition: {... {1}: '{2}' ...}","baddir":"Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces","noctrl":"Cannot bind to controller without directive '{0}'s controller.","multidir":"Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}","tpload":"Failed to load template: {0} (HTTP status: {1} {2})","uterdir":"Unterminated attribute, found '{0}' but no matching '{1}' found.","reqslot":"Required transclusion slot `{0}` was not filled.","nodomevents":"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.","nonassign":"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!","noslot":"No parent directive that requires a transclusion with slot name \"{0}\". Element: {1}"},"$resource":{"badargs":"Expected up to 4 arguments [params, data, success, error], got {0} arguments","badmember":"Dotted member path \"@{0}\" is invalid.","badname":"hasOwnProperty is not a valid parameter name.","badcfg":"Error in resource configuration for action `{0}`. Expected response to contain an {1} but got an {2} (Request: {3} {4})"},"$route":{"norout":"Tried updating route when with no current route"},"linky":{"notstring":"Expected string but received: {0}"},"$sanitize":{"noinert":"Can't create an inert html document","uinput":"Failed to sanitize html because the input is unstable"}}} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.json b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.json
deleted file mode 100644
index ff1ac645..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.json
+++ /dev/null
@@ -1 +0,0 @@
-{"raw":"v1.5.0","major":1,"minor":5,"patch":0,"prerelease":[],"build":[],"version":"1.5.0","codeName":"ennoblement-facilitation","full":"1.5.0","branch":"v1.5.x","cdn":{"raw":"v1.5.0-rc.2","major":1,"minor":5,"patch":0,"prerelease":["rc",2],"build":[],"version":"1.5.0-rc.2","docsUrl":"http://code.angularjs.org/1.5.0-rc.2/docs"}} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.txt b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.txt
deleted file mode 100644
index 3e1ad720..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/angular-1.5/version.txt
+++ /dev/null
@@ -1 +0,0 @@
-1.5.0 \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-animate.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-animate.js
deleted file mode 100644
index fc0e217f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-animate.js
+++ /dev/null
@@ -1,3721 +0,0 @@
-/**
- * @license AngularJS v1.4.3
- * (c) 2010-2015 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/* jshint ignore:start */
-var noop = angular.noop;
-var extend = angular.extend;
-var jqLite = angular.element;
-var forEach = angular.forEach;
-var isArray = angular.isArray;
-var isString = angular.isString;
-var isObject = angular.isObject;
-var isUndefined = angular.isUndefined;
-var isDefined = angular.isDefined;
-var isFunction = angular.isFunction;
-var isElement = angular.isElement;
-
-var ELEMENT_NODE = 1;
-var COMMENT_NODE = 8;
-
-var NG_ANIMATE_CLASSNAME = 'ng-animate';
-var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren';
-
-var isPromiseLike = function(p) {
- return p && p.then ? true : false;
-}
-
-function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
-}
-
-function mergeClasses(a,b) {
- if (!a && !b) return '';
- if (!a) return b;
- if (!b) return a;
- if (isArray(a)) a = a.join(' ');
- if (isArray(b)) b = b.join(' ');
- return a + ' ' + b;
-}
-
-function packageStyles(options) {
- var styles = {};
- if (options && (options.to || options.from)) {
- styles.to = options.to;
- styles.from = options.from;
- }
- return styles;
-}
-
-function pendClasses(classes, fix, isPrefix) {
- var className = '';
- classes = isArray(classes)
- ? classes
- : classes && isString(classes) && classes.length
- ? classes.split(/\s+/)
- : [];
- forEach(classes, function(klass, i) {
- if (klass && klass.length > 0) {
- className += (i > 0) ? ' ' : '';
- className += isPrefix ? fix + klass
- : klass + fix;
- }
- });
- return className;
-}
-
-function removeFromArray(arr, val) {
- var index = arr.indexOf(val);
- if (val >= 0) {
- arr.splice(index, 1);
- }
-}
-
-function stripCommentsFromElement(element) {
- if (element instanceof jqLite) {
- switch (element.length) {
- case 0:
- return [];
- break;
-
- case 1:
- // there is no point of stripping anything if the element
- // is the only element within the jqLite wrapper.
- // (it's important that we retain the element instance.)
- if (element[0].nodeType === ELEMENT_NODE) {
- return element;
- }
- break;
-
- default:
- return jqLite(extractElementNode(element));
- break;
- }
- }
-
- if (element.nodeType === ELEMENT_NODE) {
- return jqLite(element);
- }
-}
-
-function extractElementNode(element) {
- if (!element[0]) return element;
- for (var i = 0; i < element.length; i++) {
- var elm = element[i];
- if (elm.nodeType == ELEMENT_NODE) {
- return elm;
- }
- }
-}
-
-function $$addClass($$jqLite, element, className) {
- forEach(element, function(elm) {
- $$jqLite.addClass(elm, className);
- });
-}
-
-function $$removeClass($$jqLite, element, className) {
- forEach(element, function(elm) {
- $$jqLite.removeClass(elm, className);
- });
-}
-
-function applyAnimationClassesFactory($$jqLite) {
- return function(element, options) {
- if (options.addClass) {
- $$addClass($$jqLite, element, options.addClass);
- options.addClass = null;
- }
- if (options.removeClass) {
- $$removeClass($$jqLite, element, options.removeClass);
- options.removeClass = null;
- }
- }
-}
-
-function prepareAnimationOptions(options) {
- options = options || {};
- if (!options.$$prepared) {
- var domOperation = options.domOperation || noop;
- options.domOperation = function() {
- options.$$domOperationFired = true;
- domOperation();
- domOperation = noop;
- };
- options.$$prepared = true;
- }
- return options;
-}
-
-function applyAnimationStyles(element, options) {
- applyAnimationFromStyles(element, options);
- applyAnimationToStyles(element, options);
-}
-
-function applyAnimationFromStyles(element, options) {
- if (options.from) {
- element.css(options.from);
- options.from = null;
- }
-}
-
-function applyAnimationToStyles(element, options) {
- if (options.to) {
- element.css(options.to);
- options.to = null;
- }
-}
-
-function mergeAnimationOptions(element, target, newOptions) {
- var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
- var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
- var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
-
- extend(target, newOptions);
-
- if (classes.addClass) {
- target.addClass = classes.addClass;
- } else {
- target.addClass = null;
- }
-
- if (classes.removeClass) {
- target.removeClass = classes.removeClass;
- } else {
- target.removeClass = null;
- }
-
- return target;
-}
-
-function resolveElementClasses(existing, toAdd, toRemove) {
- var ADD_CLASS = 1;
- var REMOVE_CLASS = -1;
-
- var flags = {};
- existing = splitClassesToLookup(existing);
-
- toAdd = splitClassesToLookup(toAdd);
- forEach(toAdd, function(value, key) {
- flags[key] = ADD_CLASS;
- });
-
- toRemove = splitClassesToLookup(toRemove);
- forEach(toRemove, function(value, key) {
- flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
- });
-
- var classes = {
- addClass: '',
- removeClass: ''
- };
-
- forEach(flags, function(val, klass) {
- var prop, allow;
- if (val === ADD_CLASS) {
- prop = 'addClass';
- allow = !existing[klass];
- } else if (val === REMOVE_CLASS) {
- prop = 'removeClass';
- allow = existing[klass];
- }
- if (allow) {
- if (classes[prop].length) {
- classes[prop] += ' ';
- }
- classes[prop] += klass;
- }
- });
-
- function splitClassesToLookup(classes) {
- if (isString(classes)) {
- classes = classes.split(' ');
- }
-
- var obj = {};
- forEach(classes, function(klass) {
- // sometimes the split leaves empty string values
- // incase extra spaces were applied to the options
- if (klass.length) {
- obj[klass] = true;
- }
- });
- return obj;
- }
-
- return classes;
-}
-
-function getDomNode(element) {
- return (element instanceof angular.element) ? element[0] : element;
-}
-
-var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
- var tickQueue = [];
- var cancelFn;
-
- function scheduler(tasks) {
- // we make a copy since RAFScheduler mutates the state
- // of the passed in array variable and this would be difficult
- // to track down on the outside code
- tickQueue.push([].concat(tasks));
- nextTick();
- }
-
- /* waitUntilQuiet does two things:
- * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through
- * 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
- *
- * The motivation here is that animation code can request more time from the scheduler
- * before the next wave runs. This allows for certain DOM properties such as classes to
- * be resolved in time for the next animation to run.
- */
- scheduler.waitUntilQuiet = function(fn) {
- if (cancelFn) cancelFn();
-
- cancelFn = $$rAF(function() {
- cancelFn = null;
- fn();
- nextTick();
- });
- };
-
- return scheduler;
-
- function nextTick() {
- if (!tickQueue.length) return;
-
- var updatedQueue = [];
- for (var i = 0; i < tickQueue.length; i++) {
- var innerQueue = tickQueue[i];
- runNextTask(innerQueue);
- if (innerQueue.length) {
- updatedQueue.push(innerQueue);
- }
- }
- tickQueue = updatedQueue;
-
- if (!cancelFn) {
- $$rAF(function() {
- if (!cancelFn) nextTick();
- });
- }
- }
-
- function runNextTask(tasks) {
- var nextTask = tasks.shift();
- nextTask();
- }
-}];
-
-var $$AnimateChildrenDirective = [function() {
- return function(scope, element, attrs) {
- var val = attrs.ngAnimateChildren;
- if (angular.isString(val) && val.length === 0) { //empty attribute
- element.data(NG_ANIMATE_CHILDREN_DATA, true);
- } else {
- attrs.$observe('ngAnimateChildren', function(value) {
- value = value === 'on' || value === 'true';
- element.data(NG_ANIMATE_CHILDREN_DATA, value);
- });
- }
- };
-}];
-
-/**
- * @ngdoc service
- * @name $animateCss
- * @kind object
- *
- * @description
- * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes
- * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT
- * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or
- * directives to create more complex animations that can be purely driven using CSS code.
- *
- * Note that only browsers that support CSS transitions and/or keyframe animations are capable of
- * rendering animations triggered via `$animateCss` (bad news for IE9 and lower).
- *
- * ## Usage
- * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
- * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
- * any automatic control over cancelling animations and/or preventing animations from being run on
- * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to
- * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
- * the CSS animation.
- *
- * The example below shows how we can create a folding animation on an element using `ng-if`:
- *
- * ```html
- * <!-- notice the `fold-animation` CSS class -->
- * <div ng-if="onOff" class="fold-animation">
- * This element will go BOOM
- * </div>
- * <button ng-click="onOff=true">Fold In</button>
- * ```
- *
- * Now we create the **JavaScript animation** that will trigger the CSS transition:
- *
- * ```js
- * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
- * var height = element[0].offsetHeight;
- * return $animateCss(element, {
- * from: { height:'0px' },
- * to: { height:height + 'px' },
- * duration: 1 // one second
- * });
- * }
- * }
- * }]);
- * ```
- *
- * ## More Advanced Uses
- *
- * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks
- * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code.
- *
- * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation,
- * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with
- * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order
- * to provide a working animation that will run in CSS.
- *
- * The example below showcases a more advanced version of the `.fold-animation` from the example above:
- *
- * ```js
- * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
- * var height = element[0].offsetHeight;
- * return $animateCss(element, {
- * addClass: 'red large-text pulse-twice',
- * easing: 'ease-out',
- * from: { height:'0px' },
- * to: { height:height + 'px' },
- * duration: 1 // one second
- * });
- * }
- * }
- * }]);
- * ```
- *
- * Since we're adding/removing CSS classes then the CSS transition will also pick those up:
- *
- * ```css
- * /&#42; since a hardcoded duration value of 1 was provided in the JavaScript animation code,
- * the CSS classes below will be transitioned despite them being defined as regular CSS classes &#42;/
- * .red { background:red; }
- * .large-text { font-size:20px; }
- *
- * /&#42; we can also use a keyframe animation and $animateCss will make it work alongside the transition &#42;/
- * .pulse-twice {
- * animation: 0.5s pulse linear 2;
- * -webkit-animation: 0.5s pulse linear 2;
- * }
- *
- * @keyframes pulse {
- * from { transform: scale(0.5); }
- * to { transform: scale(1.5); }
- * }
- *
- * @-webkit-keyframes pulse {
- * from { -webkit-transform: scale(0.5); }
- * to { -webkit-transform: scale(1.5); }
- * }
- * ```
- *
- * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen.
- *
- * ## How the Options are handled
- *
- * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation
- * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline
- * styles using the `from` and `to` properties.
- *
- * ```js
- * var animator = $animateCss(element, {
- * from: { background:'red' },
- * to: { background:'blue' }
- * });
- * animator.start();
- * ```
- *
- * ```css
- * .rotating-animation {
- * animation:0.5s rotate linear;
- * -webkit-animation:0.5s rotate linear;
- * }
- *
- * @keyframes rotate {
- * from { transform: rotate(0deg); }
- * to { transform: rotate(360deg); }
- * }
- *
- * @-webkit-keyframes rotate {
- * from { -webkit-transform: rotate(0deg); }
- * to { -webkit-transform: rotate(360deg); }
- * }
- * ```
- *
- * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is
- * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition
- * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition
- * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied
- * and spread across the transition and keyframe animation.
- *
- * ## What is returned
- *
- * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually
- * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are
- * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties:
- *
- * ```js
- * var animator = $animateCss(element, { ... });
- * ```
- *
- * Now what do the contents of our `animator` variable look like:
- *
- * ```js
- * {
- * // starts the animation
- * start: Function,
- *
- * // ends (aborts) the animation
- * end: Function
- * }
- * ```
- *
- * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends.
- * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been
- * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
- * and that changing them will not reconfigure the parameters of the animation.
- *
- * ### runner.done() vs runner.then()
- * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
- * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
- * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
- * unless you really need a digest to kick off afterwards.
- *
- * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
- * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code).
- * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works.
- *
- * @param {DOMElement} element the element that will be animated
- * @param {object} options the animation-related options that will be applied during the animation
- *
- * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
- * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
- * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
- * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`).
- * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
- * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
- * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
- * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation.
- * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation.
- * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0`
- * is provided then the animation will be skipped entirely.
- * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is
- * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value
- * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same
- * CSS delay value.
- * * `stagger` - A numeric time value representing the delay between successively animated elements
- * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
- * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a
- * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
- * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.)
- *
- * @return {object} an object with start and end methods and details about the animation.
- *
- * * `start` - The method to start the animation. This will return a `Promise` when called.
- * * `end` - This method will cancel the animation and remove all applied CSS classes and styles.
- */
-
-// Detect proper transitionend/animationend event names.
-var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT;
-
-// If unprefixed events are not supported but webkit-prefixed are, use the latter.
-// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
-// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
-// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
-// Register both events in case `window.onanimationend` is not supported because of that,
-// do the same for `transitionend` as Safari is likely to exhibit similar behavior.
-// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
-// therefore there is no reason to test anymore for other vendor prefixes:
-// http://caniuse.com/#search=transition
-if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
- CSS_PREFIX = '-webkit-';
- TRANSITION_PROP = 'WebkitTransition';
- TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
-} else {
- TRANSITION_PROP = 'transition';
- TRANSITIONEND_EVENT = 'transitionend';
-}
-
-if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
- CSS_PREFIX = '-webkit-';
- ANIMATION_PROP = 'WebkitAnimation';
- ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
-} else {
- ANIMATION_PROP = 'animation';
- ANIMATIONEND_EVENT = 'animationend';
-}
-
-var DURATION_KEY = 'Duration';
-var PROPERTY_KEY = 'Property';
-var DELAY_KEY = 'Delay';
-var TIMING_KEY = 'TimingFunction';
-var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
-var ANIMATION_PLAYSTATE_KEY = 'PlayState';
-var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
-var CLOSING_TIME_BUFFER = 1.5;
-var ONE_SECOND = 1000;
-var BASE_TEN = 10;
-
-var SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
-
-var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
-var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
-
-var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
-var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
-
-var DETECT_CSS_PROPERTIES = {
- transitionDuration: TRANSITION_DURATION_PROP,
- transitionDelay: TRANSITION_DELAY_PROP,
- transitionProperty: TRANSITION_PROP + PROPERTY_KEY,
- animationDuration: ANIMATION_DURATION_PROP,
- animationDelay: ANIMATION_DELAY_PROP,
- animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY
-};
-
-var DETECT_STAGGER_CSS_PROPERTIES = {
- transitionDuration: TRANSITION_DURATION_PROP,
- transitionDelay: TRANSITION_DELAY_PROP,
- animationDuration: ANIMATION_DURATION_PROP,
- animationDelay: ANIMATION_DELAY_PROP
-};
-
-function computeCssStyles($window, element, properties) {
- var styles = Object.create(null);
- var detectedStyles = $window.getComputedStyle(element) || {};
- forEach(properties, function(formalStyleName, actualStyleName) {
- var val = detectedStyles[formalStyleName];
- if (val) {
- var c = val.charAt(0);
-
- // only numerical-based values have a negative sign or digit as the first value
- if (c === '-' || c === '+' || c >= 0) {
- val = parseMaxTime(val);
- }
-
- // by setting this to null in the event that the delay is not set or is set directly as 0
- // then we can still allow for zegative values to be used later on and not mistake this
- // value for being greater than any other negative value.
- if (val === 0) {
- val = null;
- }
- styles[actualStyleName] = val;
- }
- });
-
- return styles;
-}
-
-function parseMaxTime(str) {
- var maxValue = 0;
- var values = str.split(/\s*,\s*/);
- forEach(values, function(value) {
- // it's always safe to consider only second values and omit `ms` values since
- // getComputedStyle will always handle the conversion for us
- if (value.charAt(value.length - 1) == 's') {
- value = value.substring(0, value.length - 1);
- }
- value = parseFloat(value) || 0;
- maxValue = maxValue ? Math.max(value, maxValue) : value;
- });
- return maxValue;
-}
-
-function truthyTimingValue(val) {
- return val === 0 || val != null;
-}
-
-function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
- var style = TRANSITION_PROP;
- var value = duration + 's';
- if (applyOnlyDuration) {
- style += DURATION_KEY;
- } else {
- value += ' linear all';
- }
- return [style, value];
-}
-
-function getCssKeyframeDurationStyle(duration) {
- return [ANIMATION_DURATION_PROP, duration + 's'];
-}
-
-function getCssDelayStyle(delay, isKeyframeAnimation) {
- var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP;
- return [prop, delay + 's'];
-}
-
-function blockTransitions(node, duration) {
- // we use a negative delay value since it performs blocking
- // yet it doesn't kill any existing transitions running on the
- // same element which makes this safe for class-based animations
- var value = duration ? '-' + duration + 's' : '';
- applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
- return [TRANSITION_DELAY_PROP, value];
-}
-
-function blockKeyframeAnimations(node, applyBlock) {
- var value = applyBlock ? 'paused' : '';
- var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
- applyInlineStyle(node, [key, value]);
- return [key, value];
-}
-
-function applyInlineStyle(node, styleTuple) {
- var prop = styleTuple[0];
- var value = styleTuple[1];
- node.style[prop] = value;
-}
-
-function createLocalCacheLookup() {
- var cache = Object.create(null);
- return {
- flush: function() {
- cache = Object.create(null);
- },
-
- count: function(key) {
- var entry = cache[key];
- return entry ? entry.total : 0;
- },
-
- get: function(key) {
- var entry = cache[key];
- return entry && entry.value;
- },
-
- put: function(key, value) {
- if (!cache[key]) {
- cache[key] = { total: 1, value: value };
- } else {
- cache[key].total++;
- }
- }
- };
-}
-
-var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
- var gcsLookup = createLocalCacheLookup();
- var gcsStaggerLookup = createLocalCacheLookup();
-
- this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
- '$document', '$sniffer', '$$rAFScheduler',
- function($window, $$jqLite, $$AnimateRunner, $timeout,
- $document, $sniffer, $$rAFScheduler) {
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- var parentCounter = 0;
- function gcsHashFn(node, extraClasses) {
- var KEY = "$$ngAnimateParentKey";
- var parentNode = node.parentNode;
- var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
- return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
- }
-
- function computeCachedCssStyles(node, className, cacheKey, properties) {
- var timings = gcsLookup.get(cacheKey);
-
- if (!timings) {
- timings = computeCssStyles($window, node, properties);
- if (timings.animationIterationCount === 'infinite') {
- timings.animationIterationCount = 1;
- }
- }
-
- // we keep putting this in multiple times even though the value and the cacheKey are the same
- // because we're keeping an interal tally of how many duplicate animations are detected.
- gcsLookup.put(cacheKey, timings);
- return timings;
- }
-
- function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
- var stagger;
-
- // if we have one or more existing matches of matching elements
- // containing the same parent + CSS styles (which is how cacheKey works)
- // then staggering is possible
- if (gcsLookup.count(cacheKey) > 0) {
- stagger = gcsStaggerLookup.get(cacheKey);
-
- if (!stagger) {
- var staggerClassName = pendClasses(className, '-stagger');
-
- $$jqLite.addClass(node, staggerClassName);
-
- stagger = computeCssStyles($window, node, properties);
-
- // force the conversion of a null value to zero incase not set
- stagger.animationDuration = Math.max(stagger.animationDuration, 0);
- stagger.transitionDuration = Math.max(stagger.transitionDuration, 0);
-
- $$jqLite.removeClass(node, staggerClassName);
-
- gcsStaggerLookup.put(cacheKey, stagger);
- }
- }
-
- return stagger || {};
- }
-
- var bod = getDomNode($document).body;
- var rafWaitQueue = [];
- function waitUntilQuiet(callback) {
- rafWaitQueue.push(callback);
- $$rAFScheduler.waitUntilQuiet(function() {
- gcsLookup.flush();
- gcsStaggerLookup.flush();
-
- //the line below will force the browser to perform a repaint so
- //that all the animated elements within the animation frame will
- //be properly updated and drawn on screen. This is required to
- //ensure that the preparation animation is properly flushed so that
- //the active state picks up from there. DO NOT REMOVE THIS LINE.
- //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
- //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
- //WILL TAKE YEARS AWAY FROM YOUR LIFE.
- var width = bod.offsetWidth + 1;
-
- // we use a for loop to ensure that if the queue is changed
- // during this looping then it will consider new requests
- for (var i = 0; i < rafWaitQueue.length; i++) {
- rafWaitQueue[i](width);
- }
- rafWaitQueue.length = 0;
- });
- }
-
- return init;
-
- function computeTimings(node, className, cacheKey) {
- var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
- var aD = timings.animationDelay;
- var tD = timings.transitionDelay;
- timings.maxDelay = aD && tD
- ? Math.max(aD, tD)
- : (aD || tD);
- timings.maxDuration = Math.max(
- timings.animationDuration * timings.animationIterationCount,
- timings.transitionDuration);
-
- return timings;
- }
-
- function init(element, options) {
- var node = getDomNode(element);
- if (!node || !node.parentNode) {
- return closeAndReturnNoopAnimator();
- }
-
- options = prepareAnimationOptions(options);
-
- var temporaryStyles = [];
- var classes = element.attr('class');
- var styles = packageStyles(options);
- var animationClosed;
- var animationPaused;
- var animationCompleted;
- var runner;
- var runnerHost;
- var maxDelay;
- var maxDelayTime;
- var maxDuration;
- var maxDurationTime;
-
- if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
- return closeAndReturnNoopAnimator();
- }
-
- var method = options.event && isArray(options.event)
- ? options.event.join(' ')
- : options.event;
-
- var isStructural = method && options.structural;
- var structuralClassName = '';
- var addRemoveClassName = '';
-
- if (isStructural) {
- structuralClassName = pendClasses(method, 'ng-', true);
- } else if (method) {
- structuralClassName = method;
- }
-
- if (options.addClass) {
- addRemoveClassName += pendClasses(options.addClass, '-add');
- }
-
- if (options.removeClass) {
- if (addRemoveClassName.length) {
- addRemoveClassName += ' ';
- }
- addRemoveClassName += pendClasses(options.removeClass, '-remove');
- }
-
- // there may be a situation where a structural animation is combined together
- // with CSS classes that need to resolve before the animation is computed.
- // However this means that there is no explicit CSS code to block the animation
- // from happening (by setting 0s none in the class name). If this is the case
- // we need to apply the classes before the first rAF so we know to continue if
- // there actually is a detected transition or keyframe animation
- if (options.applyClassesEarly && addRemoveClassName.length) {
- applyAnimationClasses(element, options);
- addRemoveClassName = '';
- }
-
- var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
- var fullClassName = classes + ' ' + setupClasses;
- var activeClasses = pendClasses(setupClasses, '-active');
- var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
- var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
-
- // there is no way we can trigger an animation if no styles and
- // no classes are being applied which would then trigger a transition,
- // unless there a is raw keyframe value that is applied to the element.
- if (!containsKeyframeAnimation
- && !hasToStyles
- && !setupClasses) {
- return closeAndReturnNoopAnimator();
- }
-
- var cacheKey, stagger;
- if (options.stagger > 0) {
- var staggerVal = parseFloat(options.stagger);
- stagger = {
- transitionDelay: staggerVal,
- animationDelay: staggerVal,
- transitionDuration: 0,
- animationDuration: 0
- };
- } else {
- cacheKey = gcsHashFn(node, fullClassName);
- stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
- }
-
- $$jqLite.addClass(element, setupClasses);
-
- var applyOnlyDuration;
-
- if (options.transitionStyle) {
- var transitionStyle = [TRANSITION_PROP, options.transitionStyle];
- applyInlineStyle(node, transitionStyle);
- temporaryStyles.push(transitionStyle);
- }
-
- if (options.duration >= 0) {
- applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
- var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration);
-
- // we set the duration so that it will be picked up by getComputedStyle later
- applyInlineStyle(node, durationStyle);
- temporaryStyles.push(durationStyle);
- }
-
- if (options.keyframeStyle) {
- var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle];
- applyInlineStyle(node, keyframeStyle);
- temporaryStyles.push(keyframeStyle);
- }
-
- var itemIndex = stagger
- ? options.staggerIndex >= 0
- ? options.staggerIndex
- : gcsLookup.count(cacheKey)
- : 0;
-
- var isFirst = itemIndex === 0;
-
- // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
- // without causing any combination of transitions to kick in. By adding a negative delay value
- // it forces the setup class' transition to end immediately. We later then remove the negative
- // transition delay to allow for the transition to naturally do it's thing. The beauty here is
- // that if there is no transition defined then nothing will happen and this will also allow
- // other transitions to be stacked on top of each other without any chopping them out.
- if (isFirst) {
- blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
- }
-
- var timings = computeTimings(node, fullClassName, cacheKey);
- var relativeDelay = timings.maxDelay;
- maxDelay = Math.max(relativeDelay, 0);
- maxDuration = timings.maxDuration;
-
- var flags = {};
- flags.hasTransitions = timings.transitionDuration > 0;
- flags.hasAnimations = timings.animationDuration > 0;
- flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all';
- flags.applyTransitionDuration = hasToStyles && (
- (flags.hasTransitions && !flags.hasTransitionAll)
- || (flags.hasAnimations && !flags.hasTransitions));
- flags.applyAnimationDuration = options.duration && flags.hasAnimations;
- flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions);
- flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations;
- flags.recalculateTimingStyles = addRemoveClassName.length > 0;
-
- if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
- maxDuration = options.duration ? parseFloat(options.duration) : maxDuration;
-
- if (flags.applyTransitionDuration) {
- flags.hasTransitions = true;
- timings.transitionDuration = maxDuration;
- applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
- temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration));
- }
-
- if (flags.applyAnimationDuration) {
- flags.hasAnimations = true;
- timings.animationDuration = maxDuration;
- temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration));
- }
- }
-
- if (maxDuration === 0 && !flags.recalculateTimingStyles) {
- return closeAndReturnNoopAnimator();
- }
-
- // we need to recalculate the delay value since we used a pre-emptive negative
- // delay value and the delay value is required for the final event checking. This
- // property will ensure that this will happen after the RAF phase has passed.
- if (options.duration == null && timings.transitionDuration > 0) {
- flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst;
- }
-
- maxDelayTime = maxDelay * ONE_SECOND;
- maxDurationTime = maxDuration * ONE_SECOND;
- if (!options.skipBlocking) {
- flags.blockTransition = timings.transitionDuration > 0;
- flags.blockKeyframeAnimation = timings.animationDuration > 0 &&
- stagger.animationDelay > 0 &&
- stagger.animationDuration === 0;
- }
-
- applyAnimationFromStyles(element, options);
- if (!flags.blockTransition) {
- blockTransitions(node, false);
- }
-
- applyBlocking(maxDuration);
-
- // TODO(matsko): for 1.5 change this code to have an animator object for better debugging
- return {
- $$willAnimate: true,
- end: endFn,
- start: function() {
- if (animationClosed) return;
-
- runnerHost = {
- end: endFn,
- cancel: cancelFn,
- resume: null, //this will be set during the start() phase
- pause: null
- };
-
- runner = new $$AnimateRunner(runnerHost);
-
- waitUntilQuiet(start);
-
- // we don't have access to pause/resume the animation
- // since it hasn't run yet. AnimateRunner will therefore
- // set noop functions for resume and pause and they will
- // later be overridden once the animation is triggered
- return runner;
- }
- };
-
- function endFn() {
- close();
- }
-
- function cancelFn() {
- close(true);
- }
-
- function close(rejected) { // jshint ignore:line
- // if the promise has been called already then we shouldn't close
- // the animation again
- if (animationClosed || (animationCompleted && animationPaused)) return;
- animationClosed = true;
- animationPaused = false;
-
- $$jqLite.removeClass(element, setupClasses);
- $$jqLite.removeClass(element, activeClasses);
-
- blockKeyframeAnimations(node, false);
- blockTransitions(node, false);
-
- forEach(temporaryStyles, function(entry) {
- // There is only one way to remove inline style properties entirely from elements.
- // By using `removeProperty` this works, but we need to convert camel-cased CSS
- // styles down to hyphenated values.
- node.style[entry[0]] = '';
- });
-
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
-
- // the reason why we have this option is to allow a synchronous closing callback
- // that is fired as SOON as the animation ends (when the CSS is removed) or if
- // the animation never takes off at all. A good example is a leave animation since
- // the element must be removed just after the animation is over or else the element
- // will appear on screen for one animation frame causing an overbearing flicker.
- if (options.onDone) {
- options.onDone();
- }
-
- // if the preparation function fails then the promise is not setup
- if (runner) {
- runner.complete(!rejected);
- }
- }
-
- function applyBlocking(duration) {
- if (flags.blockTransition) {
- blockTransitions(node, duration);
- }
-
- if (flags.blockKeyframeAnimation) {
- blockKeyframeAnimations(node, !!duration);
- }
- }
-
- function closeAndReturnNoopAnimator() {
- runner = new $$AnimateRunner({
- end: endFn,
- cancel: cancelFn
- });
-
- close();
-
- return {
- $$willAnimate: false,
- start: function() {
- return runner;
- },
- end: endFn
- };
- }
-
- function start() {
- if (animationClosed) return;
- if (!node.parentNode) {
- close();
- return;
- }
-
- var startTime, events = [];
-
- // even though we only pause keyframe animations here the pause flag
- // will still happen when transitions are used. Only the transition will
- // not be paused since that is not possible. If the animation ends when
- // paused then it will not complete until unpaused or cancelled.
- var playPause = function(playAnimation) {
- if (!animationCompleted) {
- animationPaused = !playAnimation;
- if (timings.animationDuration) {
- var value = blockKeyframeAnimations(node, animationPaused);
- animationPaused
- ? temporaryStyles.push(value)
- : removeFromArray(temporaryStyles, value);
- }
- } else if (animationPaused && playAnimation) {
- animationPaused = false;
- close();
- }
- };
-
- // checking the stagger duration prevents an accidently cascade of the CSS delay style
- // being inherited from the parent. If the transition duration is zero then we can safely
- // rely that the delay value is an intential stagger delay style.
- var maxStagger = itemIndex > 0
- && ((timings.transitionDuration && stagger.transitionDuration === 0) ||
- (timings.animationDuration && stagger.animationDuration === 0))
- && Math.max(stagger.animationDelay, stagger.transitionDelay);
- if (maxStagger) {
- $timeout(triggerAnimationStart,
- Math.floor(maxStagger * itemIndex * ONE_SECOND),
- false);
- } else {
- triggerAnimationStart();
- }
-
- // this will decorate the existing promise runner with pause/resume methods
- runnerHost.resume = function() {
- playPause(true);
- };
-
- runnerHost.pause = function() {
- playPause(false);
- };
-
- function triggerAnimationStart() {
- // just incase a stagger animation kicks in when the animation
- // itself was cancelled entirely
- if (animationClosed) return;
-
- applyBlocking(false);
-
- forEach(temporaryStyles, function(entry) {
- var key = entry[0];
- var value = entry[1];
- node.style[key] = value;
- });
-
- applyAnimationClasses(element, options);
- $$jqLite.addClass(element, activeClasses);
-
- if (flags.recalculateTimingStyles) {
- fullClassName = node.className + ' ' + setupClasses;
- cacheKey = gcsHashFn(node, fullClassName);
-
- timings = computeTimings(node, fullClassName, cacheKey);
- relativeDelay = timings.maxDelay;
- maxDelay = Math.max(relativeDelay, 0);
- maxDuration = timings.maxDuration;
-
- if (maxDuration === 0) {
- close();
- return;
- }
-
- flags.hasTransitions = timings.transitionDuration > 0;
- flags.hasAnimations = timings.animationDuration > 0;
- }
-
- if (flags.applyTransitionDelay || flags.applyAnimationDelay) {
- relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay)
- ? parseFloat(options.delay)
- : relativeDelay;
-
- maxDelay = Math.max(relativeDelay, 0);
-
- var delayStyle;
- if (flags.applyTransitionDelay) {
- timings.transitionDelay = relativeDelay;
- delayStyle = getCssDelayStyle(relativeDelay);
- temporaryStyles.push(delayStyle);
- node.style[delayStyle[0]] = delayStyle[1];
- }
-
- if (flags.applyAnimationDelay) {
- timings.animationDelay = relativeDelay;
- delayStyle = getCssDelayStyle(relativeDelay, true);
- temporaryStyles.push(delayStyle);
- node.style[delayStyle[0]] = delayStyle[1];
- }
- }
-
- maxDelayTime = maxDelay * ONE_SECOND;
- maxDurationTime = maxDuration * ONE_SECOND;
-
- if (options.easing) {
- var easeProp, easeVal = options.easing;
- if (flags.hasTransitions) {
- easeProp = TRANSITION_PROP + TIMING_KEY;
- temporaryStyles.push([easeProp, easeVal]);
- node.style[easeProp] = easeVal;
- }
- if (flags.hasAnimations) {
- easeProp = ANIMATION_PROP + TIMING_KEY;
- temporaryStyles.push([easeProp, easeVal]);
- node.style[easeProp] = easeVal;
- }
- }
-
- if (timings.transitionDuration) {
- events.push(TRANSITIONEND_EVENT);
- }
-
- if (timings.animationDuration) {
- events.push(ANIMATIONEND_EVENT);
- }
-
- startTime = Date.now();
- element.on(events.join(' '), onAnimationProgress);
- $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime);
-
- applyAnimationToStyles(element, options);
- }
-
- function onAnimationExpired() {
- // although an expired animation is a failed animation, getting to
- // this outcome is very easy if the CSS code screws up. Therefore we
- // should still continue normally as if the animation completed correctly.
- close();
- }
-
- function onAnimationProgress(event) {
- event.stopPropagation();
- var ev = event.originalEvent || event;
- var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
-
- /* Firefox (or possibly just Gecko) likes to not round values up
- * when a ms measurement is used for the animation */
- var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
-
- /* $manualTimeStamp is a mocked timeStamp value which is set
- * within browserTrigger(). This is only here so that tests can
- * mock animations properly. Real events fallback to event.timeStamp,
- * or, if they don't, then a timeStamp is automatically created for them.
- * We're checking to see if the timeStamp surpasses the expected delay,
- * but we're using elapsedTime instead of the timeStamp on the 2nd
- * pre-condition since animations sometimes close off early */
- if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
- // we set this flag to ensure that if the transition is paused then, when resumed,
- // the animation will automatically close itself since transitions cannot be paused.
- animationCompleted = true;
- close();
- }
- }
- }
- }
- }];
-}];
-
-var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) {
- $$animationProvider.drivers.push('$$animateCssDriver');
-
- var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim';
- var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor';
-
- var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
- var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
-
- this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer',
- function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) {
-
- // only browsers that support these properties can render animations
- if (!$sniffer.animations && !$sniffer.transitions) return noop;
-
- var bodyNode = getDomNode($document).body;
- var rootNode = getDomNode($rootElement);
-
- var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode);
-
- return function initDriverFn(animationDetails) {
- return animationDetails.from && animationDetails.to
- ? prepareFromToAnchorAnimation(animationDetails.from,
- animationDetails.to,
- animationDetails.classes,
- animationDetails.anchors)
- : prepareRegularAnimation(animationDetails);
- };
-
- function filterCssClasses(classes) {
- //remove all the `ng-` stuff
- return classes.replace(/\bng-\S+\b/g, '');
- }
-
- function getUniqueValues(a, b) {
- if (isString(a)) a = a.split(' ');
- if (isString(b)) b = b.split(' ');
- return a.filter(function(val) {
- return b.indexOf(val) === -1;
- }).join(' ');
- }
-
- function prepareAnchoredAnimation(classes, outAnchor, inAnchor) {
- var clone = jqLite(getDomNode(outAnchor).cloneNode(true));
- var startingClasses = filterCssClasses(getClassVal(clone));
-
- outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
- inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME);
-
- clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME);
-
- rootBodyElement.append(clone);
-
- var animatorIn, animatorOut = prepareOutAnimation();
-
- // the user may not end up using the `out` animation and
- // only making use of the `in` animation or vice-versa.
- // In either case we should allow this and not assume the
- // animation is over unless both animations are not used.
- if (!animatorOut) {
- animatorIn = prepareInAnimation();
- if (!animatorIn) {
- return end();
- }
- }
-
- var startingAnimator = animatorOut || animatorIn;
-
- return {
- start: function() {
- var runner;
-
- var currentAnimation = startingAnimator.start();
- currentAnimation.done(function() {
- currentAnimation = null;
- if (!animatorIn) {
- animatorIn = prepareInAnimation();
- if (animatorIn) {
- currentAnimation = animatorIn.start();
- currentAnimation.done(function() {
- currentAnimation = null;
- end();
- runner.complete();
- });
- return currentAnimation;
- }
- }
- // in the event that there is no `in` animation
- end();
- runner.complete();
- });
-
- runner = new $$AnimateRunner({
- end: endFn,
- cancel: endFn
- });
-
- return runner;
-
- function endFn() {
- if (currentAnimation) {
- currentAnimation.end();
- }
- }
- }
- };
-
- function calculateAnchorStyles(anchor) {
- var styles = {};
-
- var coords = getDomNode(anchor).getBoundingClientRect();
-
- // we iterate directly since safari messes up and doesn't return
- // all the keys for the coods object when iterated
- forEach(['width','height','top','left'], function(key) {
- var value = coords[key];
- switch (key) {
- case 'top':
- value += bodyNode.scrollTop;
- break;
- case 'left':
- value += bodyNode.scrollLeft;
- break;
- }
- styles[key] = Math.floor(value) + 'px';
- });
- return styles;
- }
-
- function prepareOutAnimation() {
- var animator = $animateCss(clone, {
- addClass: NG_OUT_ANCHOR_CLASS_NAME,
- delay: true,
- from: calculateAnchorStyles(outAnchor)
- });
-
- // read the comment within `prepareRegularAnimation` to understand
- // why this check is necessary
- return animator.$$willAnimate ? animator : null;
- }
-
- function getClassVal(element) {
- return element.attr('class') || '';
- }
-
- function prepareInAnimation() {
- var endingClasses = filterCssClasses(getClassVal(inAnchor));
- var toAdd = getUniqueValues(endingClasses, startingClasses);
- var toRemove = getUniqueValues(startingClasses, endingClasses);
-
- var animator = $animateCss(clone, {
- to: calculateAnchorStyles(inAnchor),
- addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd,
- removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove,
- delay: true
- });
-
- // read the comment within `prepareRegularAnimation` to understand
- // why this check is necessary
- return animator.$$willAnimate ? animator : null;
- }
-
- function end() {
- clone.remove();
- outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
- inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME);
- }
- }
-
- function prepareFromToAnchorAnimation(from, to, classes, anchors) {
- var fromAnimation = prepareRegularAnimation(from);
- var toAnimation = prepareRegularAnimation(to);
-
- var anchorAnimations = [];
- forEach(anchors, function(anchor) {
- var outElement = anchor['out'];
- var inElement = anchor['in'];
- var animator = prepareAnchoredAnimation(classes, outElement, inElement);
- if (animator) {
- anchorAnimations.push(animator);
- }
- });
-
- // no point in doing anything when there are no elements to animate
- if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return;
-
- return {
- start: function() {
- var animationRunners = [];
-
- if (fromAnimation) {
- animationRunners.push(fromAnimation.start());
- }
-
- if (toAnimation) {
- animationRunners.push(toAnimation.start());
- }
-
- forEach(anchorAnimations, function(animation) {
- animationRunners.push(animation.start());
- });
-
- var runner = new $$AnimateRunner({
- end: endFn,
- cancel: endFn // CSS-driven animations cannot be cancelled, only ended
- });
-
- $$AnimateRunner.all(animationRunners, function(status) {
- runner.complete(status);
- });
-
- return runner;
-
- function endFn() {
- forEach(animationRunners, function(runner) {
- runner.end();
- });
- }
- }
- };
- }
-
- function prepareRegularAnimation(animationDetails) {
- var element = animationDetails.element;
- var options = animationDetails.options || {};
-
- if (animationDetails.structural) {
- // structural animations ensure that the CSS classes are always applied
- // before the detection starts.
- options.structural = options.applyClassesEarly = true;
-
- // we special case the leave animation since we want to ensure that
- // the element is removed as soon as the animation is over. Otherwise
- // a flicker might appear or the element may not be removed at all
- options.event = animationDetails.event;
- if (options.event === 'leave') {
- options.onDone = options.domOperation;
- }
- } else {
- options.event = null;
- }
-
- var animator = $animateCss(element, options);
-
- // the driver lookup code inside of $$animation attempts to spawn a
- // driver one by one until a driver returns a.$$willAnimate animator object.
- // $animateCss will always return an object, however, it will pass in
- // a flag as a hint as to whether an animation was detected or not
- return animator.$$willAnimate ? animator : null;
- }
- }];
-}];
-
-// TODO(matsko): use caching here to speed things up for detection
-// TODO(matsko): add documentation
-// by the time...
-
-var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
- this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite',
- function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) {
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
- // $animateJs(element, 'enter');
- return function(element, event, classes, options) {
- // the `classes` argument is optional and if it is not used
- // then the classes will be resolved from the element's className
- // property as well as options.addClass/options.removeClass.
- if (arguments.length === 3 && isObject(classes)) {
- options = classes;
- classes = null;
- }
-
- options = prepareAnimationOptions(options);
- if (!classes) {
- classes = element.attr('class') || '';
- if (options.addClass) {
- classes += ' ' + options.addClass;
- }
- if (options.removeClass) {
- classes += ' ' + options.removeClass;
- }
- }
-
- var classesToAdd = options.addClass;
- var classesToRemove = options.removeClass;
-
- // the lookupAnimations function returns a series of animation objects that are
- // matched up with one or more of the CSS classes. These animation objects are
- // defined via the module.animation factory function. If nothing is detected then
- // we don't return anything which then makes $animation query the next driver.
- var animations = lookupAnimations(classes);
- var before, after;
- if (animations.length) {
- var afterFn, beforeFn;
- if (event == 'leave') {
- beforeFn = 'leave';
- afterFn = 'afterLeave'; // TODO(matsko): get rid of this
- } else {
- beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1);
- afterFn = event;
- }
-
- if (event !== 'enter' && event !== 'move') {
- before = packageAnimations(element, event, options, animations, beforeFn);
- }
- after = packageAnimations(element, event, options, animations, afterFn);
- }
-
- // no matching animations
- if (!before && !after) return;
-
- function applyOptions() {
- options.domOperation();
- applyAnimationClasses(element, options);
- }
-
- return {
- start: function() {
- var closeActiveAnimations;
- var chain = [];
-
- if (before) {
- chain.push(function(fn) {
- closeActiveAnimations = before(fn);
- });
- }
-
- if (chain.length) {
- chain.push(function(fn) {
- applyOptions();
- fn(true);
- });
- } else {
- applyOptions();
- }
-
- if (after) {
- chain.push(function(fn) {
- closeActiveAnimations = after(fn);
- });
- }
-
- var animationClosed = false;
- var runner = new $$AnimateRunner({
- end: function() {
- endAnimations();
- },
- cancel: function() {
- endAnimations(true);
- }
- });
-
- $$AnimateRunner.chain(chain, onComplete);
- return runner;
-
- function onComplete(success) {
- animationClosed = true;
- applyOptions();
- applyAnimationStyles(element, options);
- runner.complete(success);
- }
-
- function endAnimations(cancelled) {
- if (!animationClosed) {
- (closeActiveAnimations || noop)(cancelled);
- onComplete(cancelled);
- }
- }
- }
- };
-
- function executeAnimationFn(fn, element, event, options, onDone) {
- var args;
- switch (event) {
- case 'animate':
- args = [element, options.from, options.to, onDone];
- break;
-
- case 'setClass':
- args = [element, classesToAdd, classesToRemove, onDone];
- break;
-
- case 'addClass':
- args = [element, classesToAdd, onDone];
- break;
-
- case 'removeClass':
- args = [element, classesToRemove, onDone];
- break;
-
- default:
- args = [element, onDone];
- break;
- }
-
- args.push(options);
-
- var value = fn.apply(fn, args);
- if (value) {
- if (isFunction(value.start)) {
- value = value.start();
- }
-
- if (value instanceof $$AnimateRunner) {
- value.done(onDone);
- } else if (isFunction(value)) {
- // optional onEnd / onCancel callback
- return value;
- }
- }
-
- return noop;
- }
-
- function groupEventedAnimations(element, event, options, animations, fnName) {
- var operations = [];
- forEach(animations, function(ani) {
- var animation = ani[fnName];
- if (!animation) return;
-
- // note that all of these animations will run in parallel
- operations.push(function() {
- var runner;
- var endProgressCb;
-
- var resolved = false;
- var onAnimationComplete = function(rejected) {
- if (!resolved) {
- resolved = true;
- (endProgressCb || noop)(rejected);
- runner.complete(!rejected);
- }
- };
-
- runner = new $$AnimateRunner({
- end: function() {
- onAnimationComplete();
- },
- cancel: function() {
- onAnimationComplete(true);
- }
- });
-
- endProgressCb = executeAnimationFn(animation, element, event, options, function(result) {
- var cancelled = result === false;
- onAnimationComplete(cancelled);
- });
-
- return runner;
- });
- });
-
- return operations;
- }
-
- function packageAnimations(element, event, options, animations, fnName) {
- var operations = groupEventedAnimations(element, event, options, animations, fnName);
- if (operations.length === 0) {
- var a,b;
- if (fnName === 'beforeSetClass') {
- a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass');
- b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass');
- } else if (fnName === 'setClass') {
- a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass');
- b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass');
- }
-
- if (a) {
- operations = operations.concat(a);
- }
- if (b) {
- operations = operations.concat(b);
- }
- }
-
- if (operations.length === 0) return;
-
- // TODO(matsko): add documentation
- return function startAnimation(callback) {
- var runners = [];
- if (operations.length) {
- forEach(operations, function(animateFn) {
- runners.push(animateFn());
- });
- }
-
- runners.length ? $$AnimateRunner.all(runners, callback) : callback();
-
- return function endFn(reject) {
- forEach(runners, function(runner) {
- reject ? runner.cancel() : runner.end();
- });
- };
- };
- }
- };
-
- function lookupAnimations(classes) {
- classes = isArray(classes) ? classes : classes.split(' ');
- var matches = [], flagMap = {};
- for (var i=0; i < classes.length; i++) {
- var klass = classes[i],
- animationFactory = $animateProvider.$$registeredAnimations[klass];
- if (animationFactory && !flagMap[klass]) {
- matches.push($injector.get(animationFactory));
- flagMap[klass] = true;
- }
- }
- return matches;
- }
- }];
-}];
-
-var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) {
- $$animationProvider.drivers.push('$$animateJsDriver');
- this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) {
- return function initDriverFn(animationDetails) {
- if (animationDetails.from && animationDetails.to) {
- var fromAnimation = prepareAnimation(animationDetails.from);
- var toAnimation = prepareAnimation(animationDetails.to);
- if (!fromAnimation && !toAnimation) return;
-
- return {
- start: function() {
- var animationRunners = [];
-
- if (fromAnimation) {
- animationRunners.push(fromAnimation.start());
- }
-
- if (toAnimation) {
- animationRunners.push(toAnimation.start());
- }
-
- $$AnimateRunner.all(animationRunners, done);
-
- var runner = new $$AnimateRunner({
- end: endFnFactory(),
- cancel: endFnFactory()
- });
-
- return runner;
-
- function endFnFactory() {
- return function() {
- forEach(animationRunners, function(runner) {
- // at this point we cannot cancel animations for groups just yet. 1.5+
- runner.end();
- });
- };
- }
-
- function done(status) {
- runner.complete(status);
- }
- }
- };
- } else {
- return prepareAnimation(animationDetails);
- }
- };
-
- function prepareAnimation(animationDetails) {
- // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations
- var element = animationDetails.element;
- var event = animationDetails.event;
- var options = animationDetails.options;
- var classes = animationDetails.classes;
- return $$animateJs(element, event, classes, options);
- }
- }];
-}];
-
-var NG_ANIMATE_ATTR_NAME = 'data-ng-animate';
-var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
-var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
- var PRE_DIGEST_STATE = 1;
- var RUNNING_STATE = 2;
-
- var rules = this.rules = {
- skip: [],
- cancel: [],
- join: []
- };
-
- function isAllowed(ruleType, element, currentAnimation, previousAnimation) {
- return rules[ruleType].some(function(fn) {
- return fn(element, currentAnimation, previousAnimation);
- });
- }
-
- function hasAnimationClasses(options, and) {
- options = options || {};
- var a = (options.addClass || '').length > 0;
- var b = (options.removeClass || '').length > 0;
- return and ? a && b : a || b;
- }
-
- rules.join.push(function(element, newAnimation, currentAnimation) {
- // if the new animation is class-based then we can just tack that on
- return !newAnimation.structural && hasAnimationClasses(newAnimation.options);
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // there is no need to animate anything if no classes are being added and
- // there is no structural animation that will be triggered
- return !newAnimation.structural && !hasAnimationClasses(newAnimation.options);
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // why should we trigger a new structural animation if the element will
- // be removed from the DOM anyway?
- return currentAnimation.event == 'leave' && newAnimation.structural;
- });
-
- rules.skip.push(function(element, newAnimation, currentAnimation) {
- // if there is a current animation then skip the class-based animation
- return currentAnimation.structural && !newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- // there can never be two structural animations running at the same time
- return currentAnimation.structural && newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- // if the previous animation is already running, but the new animation will
- // be triggered, but the new animation is structural
- return currentAnimation.state === RUNNING_STATE && newAnimation.structural;
- });
-
- rules.cancel.push(function(element, newAnimation, currentAnimation) {
- var nO = newAnimation.options;
- var cO = currentAnimation.options;
-
- // if the exact same CSS class is added/removed then it's safe to cancel it
- return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
- });
-
- this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
- '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite',
- function($$rAF, $rootScope, $rootElement, $document, $$HashMap,
- $$animation, $$AnimateRunner, $templateRequest, $$jqLite) {
-
- var activeAnimationsLookup = new $$HashMap();
- var disabledElementsLookup = new $$HashMap();
-
- var animationsEnabled = null;
-
- // Wait until all directive and route-related templates are downloaded and
- // compiled. The $templateRequest.totalPendingRequests variable keeps track of
- // all of the remote templates being currently downloaded. If there are no
- // templates currently downloading then the watcher will still fire anyway.
- var deregisterWatch = $rootScope.$watch(
- function() { return $templateRequest.totalPendingRequests === 0; },
- function(isEmpty) {
- if (!isEmpty) return;
- deregisterWatch();
-
- // Now that all templates have been downloaded, $animate will wait until
- // the post digest queue is empty before enabling animations. By having two
- // calls to $postDigest calls we can ensure that the flag is enabled at the
- // very end of the post digest queue. Since all of the animations in $animate
- // use $postDigest, it's important that the code below executes at the end.
- // This basically means that the page is fully downloaded and compiled before
- // any animations are triggered.
- $rootScope.$$postDigest(function() {
- $rootScope.$$postDigest(function() {
- // we check for null directly in the event that the application already called
- // .enabled() with whatever arguments that it provided it with
- if (animationsEnabled === null) {
- animationsEnabled = true;
- }
- });
- });
- }
- );
-
- var bodyElement = jqLite($document[0].body);
-
- var callbackRegistry = {};
-
- // remember that the classNameFilter is set during the provider/config
- // stage therefore we can optimize here and setup a helper function
- var classNameFilter = $animateProvider.classNameFilter();
- var isAnimatableClassName = !classNameFilter
- ? function() { return true; }
- : function(className) {
- return classNameFilter.test(className);
- };
-
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- function normalizeAnimationOptions(element, options) {
- return mergeAnimationOptions(element, options, {});
- }
-
- function findCallbacks(element, event) {
- var targetNode = getDomNode(element);
-
- var matches = [];
- var entries = callbackRegistry[event];
- if (entries) {
- forEach(entries, function(entry) {
- if (entry.node.contains(targetNode)) {
- matches.push(entry.callback);
- }
- });
- }
-
- return matches;
- }
-
- function triggerCallback(event, element, phase, data) {
- $$rAF(function() {
- forEach(findCallbacks(element, event), function(callback) {
- callback(element, phase, data);
- });
- });
- }
-
- return {
- on: function(event, container, callback) {
- var node = extractElementNode(container);
- callbackRegistry[event] = callbackRegistry[event] || [];
- callbackRegistry[event].push({
- node: node,
- callback: callback
- });
- },
-
- off: function(event, container, callback) {
- var entries = callbackRegistry[event];
- if (!entries) return;
-
- callbackRegistry[event] = arguments.length === 1
- ? null
- : filterFromRegistry(entries, container, callback);
-
- function filterFromRegistry(list, matchContainer, matchCallback) {
- var containerNode = extractElementNode(matchContainer);
- return list.filter(function(entry) {
- var isMatch = entry.node === containerNode &&
- (!matchCallback || entry.callback === matchCallback);
- return !isMatch;
- });
- }
- },
-
- pin: function(element, parentElement) {
- assertArg(isElement(element), 'element', 'not an element');
- assertArg(isElement(parentElement), 'parentElement', 'not an element');
- element.data(NG_ANIMATE_PIN_DATA, parentElement);
- },
-
- push: function(element, event, options, domOperation) {
- options = options || {};
- options.domOperation = domOperation;
- return queueAnimation(element, event, options);
- },
-
- // this method has four signatures:
- // () - global getter
- // (bool) - global setter
- // (element) - element getter
- // (element, bool) - element setter<F37>
- enabled: function(element, bool) {
- var argCount = arguments.length;
-
- if (argCount === 0) {
- // () - Global getter
- bool = !!animationsEnabled;
- } else {
- var hasElement = isElement(element);
-
- if (!hasElement) {
- // (bool) - Global setter
- bool = animationsEnabled = !!element;
- } else {
- var node = getDomNode(element);
- var recordExists = disabledElementsLookup.get(node);
-
- if (argCount === 1) {
- // (element) - Element getter
- bool = !recordExists;
- } else {
- // (element, bool) - Element setter
- bool = !!bool;
- if (!bool) {
- disabledElementsLookup.put(node, true);
- } else if (recordExists) {
- disabledElementsLookup.remove(node);
- }
- }
- }
- }
-
- return bool;
- }
- };
-
- function queueAnimation(element, event, options) {
- var node, parent;
- element = stripCommentsFromElement(element);
- if (element) {
- node = getDomNode(element);
- parent = element.parent();
- }
-
- options = prepareAnimationOptions(options);
-
- // we create a fake runner with a working promise.
- // These methods will become available after the digest has passed
- var runner = new $$AnimateRunner();
-
- // there are situations where a directive issues an animation for
- // a jqLite wrapper that contains only comment nodes... If this
- // happens then there is no way we can perform an animation
- if (!node) {
- close();
- return runner;
- }
-
- if (isArray(options.addClass)) {
- options.addClass = options.addClass.join(' ');
- }
-
- if (isArray(options.removeClass)) {
- options.removeClass = options.removeClass.join(' ');
- }
-
- if (options.from && !isObject(options.from)) {
- options.from = null;
- }
-
- if (options.to && !isObject(options.to)) {
- options.to = null;
- }
-
- var className = [node.className, options.addClass, options.removeClass].join(' ');
- if (!isAnimatableClassName(className)) {
- close();
- return runner;
- }
-
- var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
-
- // this is a hard disable of all animations for the application or on
- // the element itself, therefore there is no need to continue further
- // past this point if not enabled
- var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
- var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
- var hasExistingAnimation = !!existingAnimation.state;
-
- // there is no point in traversing the same collection of parent ancestors if a followup
- // animation will be run on the same element that already did all that checking work
- if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) {
- skipAnimations = !areAnimationsAllowed(element, parent, event);
- }
-
- if (skipAnimations) {
- close();
- return runner;
- }
-
- if (isStructural) {
- closeChildAnimations(element);
- }
-
- var newAnimation = {
- structural: isStructural,
- element: element,
- event: event,
- close: close,
- options: options,
- runner: runner
- };
-
- if (hasExistingAnimation) {
- var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation);
- if (skipAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- close();
- return runner;
- } else {
- mergeAnimationOptions(element, existingAnimation.options, options);
- return existingAnimation.runner;
- }
- }
-
- var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation);
- if (cancelAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- // this will end the animation right away and it is safe
- // to do so since the animation is already running and the
- // runner callback code will run in async
- existingAnimation.runner.end();
- } else if (existingAnimation.structural) {
- // this means that the animation is queued into a digest, but
- // hasn't started yet. Therefore it is safe to run the close
- // method which will call the runner methods in async.
- existingAnimation.close();
- } else {
- // this will merge the existing animation options into this new follow-up animation
- mergeAnimationOptions(element, newAnimation.options, existingAnimation.options);
- }
- } else {
- // a joined animation means that this animation will take over the existing one
- // so an example would involve a leave animation taking over an enter. Then when
- // the postDigest kicks in the enter will be ignored.
- var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
- if (joinAnimationFlag) {
- if (existingAnimation.state === RUNNING_STATE) {
- normalizeAnimationOptions(element, options);
- } else {
- event = newAnimation.event = existingAnimation.event;
- options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
- return runner;
- }
- }
- }
- } else {
- // normalization in this case means that it removes redundant CSS classes that
- // already exist (addClass) or do not exist (removeClass) on the element
- normalizeAnimationOptions(element, options);
- }
-
- // when the options are merged and cleaned up we may end up not having to do
- // an animation at all, therefore we should check this before issuing a post
- // digest callback. Structural animations will always run no matter what.
- var isValidAnimation = newAnimation.structural;
- if (!isValidAnimation) {
- // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
- isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
- || hasAnimationClasses(newAnimation.options);
- }
-
- if (!isValidAnimation) {
- close();
- clearElementAnimationState(element);
- return runner;
- }
-
- if (isStructural) {
- closeParentClassBasedAnimations(parent);
- }
-
- // the counter keeps track of cancelled animations
- var counter = (existingAnimation.counter || 0) + 1;
- newAnimation.counter = counter;
-
- markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation);
-
- $rootScope.$$postDigest(function() {
- var animationDetails = activeAnimationsLookup.get(node);
- var animationCancelled = !animationDetails;
- animationDetails = animationDetails || {};
-
- // if addClass/removeClass is called before something like enter then the
- // registered parent element may not be present. The code below will ensure
- // that a final value for parent element is obtained
- var parentElement = element.parent() || [];
-
- // animate/structural/class-based animations all have requirements. Otherwise there
- // is no point in performing an animation. The parent node must also be set.
- var isValidAnimation = parentElement.length > 0
- && (animationDetails.event === 'animate'
- || animationDetails.structural
- || hasAnimationClasses(animationDetails.options));
-
- // this means that the previous animation was cancelled
- // even if the follow-up animation is the same event
- if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) {
- // if another animation did not take over then we need
- // to make sure that the domOperation and options are
- // handled accordingly
- if (animationCancelled) {
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- }
-
- // if the event changed from something like enter to leave then we do
- // it, otherwise if it's the same then the end result will be the same too
- if (animationCancelled || (isStructural && animationDetails.event !== event)) {
- options.domOperation();
- runner.end();
- }
-
- // in the event that the element animation was not cancelled or a follow-up animation
- // isn't allowed to animate from here then we need to clear the state of the element
- // so that any future animations won't read the expired animation data.
- if (!isValidAnimation) {
- clearElementAnimationState(element);
- }
-
- return;
- }
-
- // this combined multiple class to addClass / removeClass into a setClass event
- // so long as a structural event did not take over the animation
- event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true)
- ? 'setClass'
- : animationDetails.event;
-
- if (animationDetails.structural) {
- closeParentClassBasedAnimations(parentElement);
- }
-
- markElementAnimationState(element, RUNNING_STATE);
- var realRunner = $$animation(element, event, animationDetails.options);
- realRunner.done(function(status) {
- close(!status);
- var animationDetails = activeAnimationsLookup.get(node);
- if (animationDetails && animationDetails.counter === counter) {
- clearElementAnimationState(getDomNode(element));
- }
- notifyProgress(runner, event, 'close', {});
- });
-
- // this will update the runner's flow-control events based on
- // the `realRunner` object.
- runner.setHost(realRunner);
- notifyProgress(runner, event, 'start', {});
- });
-
- return runner;
-
- function notifyProgress(runner, event, phase, data) {
- triggerCallback(event, element, phase, data);
- runner.progress(event, phase, data);
- }
-
- function close(reject) { // jshint ignore:line
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- options.domOperation();
- runner.complete(!reject);
- }
- }
-
- function closeChildAnimations(element) {
- var node = getDomNode(element);
- var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']');
- forEach(children, function(child) {
- var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME));
- var animationDetails = activeAnimationsLookup.get(child);
- switch (state) {
- case RUNNING_STATE:
- animationDetails.runner.end();
- /* falls through */
- case PRE_DIGEST_STATE:
- if (animationDetails) {
- activeAnimationsLookup.remove(child);
- }
- break;
- }
- });
- }
-
- function clearElementAnimationState(element) {
- var node = getDomNode(element);
- node.removeAttribute(NG_ANIMATE_ATTR_NAME);
- activeAnimationsLookup.remove(node);
- }
-
- function isMatchingElement(nodeOrElmA, nodeOrElmB) {
- return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
- }
-
- function closeParentClassBasedAnimations(startingElement) {
- var parentNode = getDomNode(startingElement);
- do {
- if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break;
-
- var animationDetails = activeAnimationsLookup.get(parentNode);
- if (animationDetails) {
- examineParentAnimation(parentNode, animationDetails);
- }
-
- parentNode = parentNode.parentNode;
- } while (true);
-
- // since animations are detected from CSS classes, we need to flush all parent
- // class-based animations so that the parent classes are all present for child
- // animations to properly function (otherwise any CSS selectors may not work)
- function examineParentAnimation(node, animationDetails) {
- // enter/leave/move always have priority
- if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return;
-
- if (animationDetails.state === RUNNING_STATE) {
- animationDetails.runner.end();
- }
- clearElementAnimationState(node);
- }
- }
-
- function areAnimationsAllowed(element, parentElement, event) {
- var bodyElementDetected = false;
- var rootElementDetected = false;
- var parentAnimationDetected = false;
- var animateChildren;
-
- var parentHost = element.data(NG_ANIMATE_PIN_DATA);
- if (parentHost) {
- parentElement = parentHost;
- }
-
- while (parentElement && parentElement.length) {
- if (!rootElementDetected) {
- // angular doesn't want to attempt to animate elements outside of the application
- // therefore we need to ensure that the rootElement is an ancestor of the current element
- rootElementDetected = isMatchingElement(parentElement, $rootElement);
- }
-
- var parentNode = parentElement[0];
- if (parentNode.nodeType !== ELEMENT_NODE) {
- // no point in inspecting the #document element
- break;
- }
-
- var details = activeAnimationsLookup.get(parentNode) || {};
- // either an enter, leave or move animation will commence
- // therefore we can't allow any animations to take place
- // but if a parent animation is class-based then that's ok
- if (!parentAnimationDetected) {
- parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode);
- }
-
- if (isUndefined(animateChildren) || animateChildren === true) {
- var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA);
- if (isDefined(value)) {
- animateChildren = value;
- }
- }
-
- // there is no need to continue traversing at this point
- if (parentAnimationDetected && animateChildren === false) break;
-
- if (!rootElementDetected) {
- // angular doesn't want to attempt to animate elements outside of the application
- // therefore we need to ensure that the rootElement is an ancestor of the current element
- rootElementDetected = isMatchingElement(parentElement, $rootElement);
- if (!rootElementDetected) {
- parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
- if (parentHost) {
- parentElement = parentHost;
- }
- }
- }
-
- if (!bodyElementDetected) {
- // we also need to ensure that the element is or will be apart of the body element
- // otherwise it is pointless to even issue an animation to be rendered
- bodyElementDetected = isMatchingElement(parentElement, bodyElement);
- }
-
- parentElement = parentElement.parent();
- }
-
- var allowAnimation = !parentAnimationDetected || animateChildren;
- return allowAnimation && rootElementDetected && bodyElementDetected;
- }
-
- function markElementAnimationState(element, state, details) {
- details = details || {};
- details.state = state;
-
- var node = getDomNode(element);
- node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
-
- var oldValue = activeAnimationsLookup.get(node);
- var newValue = oldValue
- ? extend(oldValue, details)
- : details;
- activeAnimationsLookup.put(node, newValue);
- }
- }];
-}];
-
-var $$rAFMutexFactory = ['$$rAF', function($$rAF) {
- return function() {
- var passed = false;
- $$rAF(function() {
- passed = true;
- });
- return function(fn) {
- passed ? fn() : $$rAF(fn);
- };
- };
-}];
-
-var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) {
- var INITIAL_STATE = 0;
- var DONE_PENDING_STATE = 1;
- var DONE_COMPLETE_STATE = 2;
-
- AnimateRunner.chain = function(chain, callback) {
- var index = 0;
-
- next();
- function next() {
- if (index === chain.length) {
- callback(true);
- return;
- }
-
- chain[index](function(response) {
- if (response === false) {
- callback(false);
- return;
- }
- index++;
- next();
- });
- }
- };
-
- AnimateRunner.all = function(runners, callback) {
- var count = 0;
- var status = true;
- forEach(runners, function(runner) {
- runner.done(onProgress);
- });
-
- function onProgress(response) {
- status = status && response;
- if (++count === runners.length) {
- callback(status);
- }
- }
- };
-
- function AnimateRunner(host) {
- this.setHost(host);
-
- this._doneCallbacks = [];
- this._runInAnimationFrame = $$rAFMutex();
- this._state = 0;
- }
-
- AnimateRunner.prototype = {
- setHost: function(host) {
- this.host = host || {};
- },
-
- done: function(fn) {
- if (this._state === DONE_COMPLETE_STATE) {
- fn();
- } else {
- this._doneCallbacks.push(fn);
- }
- },
-
- progress: noop,
-
- getPromise: function() {
- if (!this.promise) {
- var self = this;
- this.promise = $q(function(resolve, reject) {
- self.done(function(status) {
- status === false ? reject() : resolve();
- });
- });
- }
- return this.promise;
- },
-
- then: function(resolveHandler, rejectHandler) {
- return this.getPromise().then(resolveHandler, rejectHandler);
- },
-
- 'catch': function(handler) {
- return this.getPromise()['catch'](handler);
- },
-
- 'finally': function(handler) {
- return this.getPromise()['finally'](handler);
- },
-
- pause: function() {
- if (this.host.pause) {
- this.host.pause();
- }
- },
-
- resume: function() {
- if (this.host.resume) {
- this.host.resume();
- }
- },
-
- end: function() {
- if (this.host.end) {
- this.host.end();
- }
- this._resolve(true);
- },
-
- cancel: function() {
- if (this.host.cancel) {
- this.host.cancel();
- }
- this._resolve(false);
- },
-
- complete: function(response) {
- var self = this;
- if (self._state === INITIAL_STATE) {
- self._state = DONE_PENDING_STATE;
- self._runInAnimationFrame(function() {
- self._resolve(response);
- });
- }
- },
-
- _resolve: function(response) {
- if (this._state !== DONE_COMPLETE_STATE) {
- forEach(this._doneCallbacks, function(fn) {
- fn(response);
- });
- this._doneCallbacks.length = 0;
- this._state = DONE_COMPLETE_STATE;
- }
- }
- };
-
- return AnimateRunner;
-}];
-
-var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
- var NG_ANIMATE_REF_ATTR = 'ng-animate-ref';
-
- var drivers = this.drivers = [];
-
- var RUNNER_STORAGE_KEY = '$$animationRunner';
-
- function setRunner(element, runner) {
- element.data(RUNNER_STORAGE_KEY, runner);
- }
-
- function removeRunner(element) {
- element.removeData(RUNNER_STORAGE_KEY);
- }
-
- function getRunner(element) {
- return element.data(RUNNER_STORAGE_KEY);
- }
-
- this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$rAFScheduler',
- function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$rAFScheduler) {
-
- var animationQueue = [];
- var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
-
- var totalPendingClassBasedAnimations = 0;
- var totalActiveClassBasedAnimations = 0;
- var classBasedAnimationsQueue = [];
-
- // TODO(matsko): document the signature in a better way
- return function(element, event, options) {
- options = prepareAnimationOptions(options);
- var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
-
- // there is no animation at the current moment, however
- // these runner methods will get later updated with the
- // methods leading into the driver's end/cancel methods
- // for now they just stop the animation from starting
- var runner = new $$AnimateRunner({
- end: function() { close(); },
- cancel: function() { close(true); }
- });
-
- if (!drivers.length) {
- close();
- return runner;
- }
-
- setRunner(element, runner);
-
- var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
- var tempClasses = options.tempClasses;
- if (tempClasses) {
- classes += ' ' + tempClasses;
- options.tempClasses = null;
- }
-
- var classBasedIndex;
- if (!isStructural) {
- classBasedIndex = totalPendingClassBasedAnimations;
- totalPendingClassBasedAnimations += 1;
- }
-
- animationQueue.push({
- // this data is used by the postDigest code and passed into
- // the driver step function
- element: element,
- classes: classes,
- event: event,
- classBasedIndex: classBasedIndex,
- structural: isStructural,
- options: options,
- beforeStart: beforeStart,
- close: close
- });
-
- element.on('$destroy', handleDestroyedElement);
-
- // we only want there to be one function called within the post digest
- // block. This way we can group animations for all the animations that
- // were apart of the same postDigest flush call.
- if (animationQueue.length > 1) return runner;
-
- $rootScope.$$postDigest(function() {
- totalActiveClassBasedAnimations = totalPendingClassBasedAnimations;
- totalPendingClassBasedAnimations = 0;
- classBasedAnimationsQueue.length = 0;
-
- var animations = [];
- forEach(animationQueue, function(entry) {
- // the element was destroyed early on which removed the runner
- // form its storage. This means we can't animate this element
- // at all and it already has been closed due to destruction.
- if (getRunner(entry.element)) {
- animations.push(entry);
- }
- });
-
- // now any future animations will be in another postDigest
- animationQueue.length = 0;
-
- forEach(groupAnimations(animations), function(animationEntry) {
- if (animationEntry.structural) {
- triggerAnimationStart();
- } else {
- classBasedAnimationsQueue.push({
- node: getDomNode(animationEntry.element),
- fn: triggerAnimationStart
- });
-
- if (animationEntry.classBasedIndex === totalActiveClassBasedAnimations - 1) {
- // we need to sort each of the animations in order of parent to child
- // relationships. This ensures that the child classes are applied at the
- // right time.
- classBasedAnimationsQueue = classBasedAnimationsQueue.sort(function(a,b) {
- return b.node.contains(a.node);
- }).map(function(entry) {
- return entry.fn;
- });
-
- $$rAFScheduler(classBasedAnimationsQueue);
- }
- }
-
- function triggerAnimationStart() {
- // it's important that we apply the `ng-animate` CSS class and the
- // temporary classes before we do any driver invoking since these
- // CSS classes may be required for proper CSS detection.
- animationEntry.beforeStart();
-
- var startAnimationFn, closeFn = animationEntry.close;
-
- // in the event that the element was removed before the digest runs or
- // during the RAF sequencing then we should not trigger the animation.
- var targetElement = animationEntry.anchors
- ? (animationEntry.from.element || animationEntry.to.element)
- : animationEntry.element;
-
- if (getRunner(targetElement) && getDomNode(targetElement).parentNode) {
- var operation = invokeFirstDriver(animationEntry);
- if (operation) {
- startAnimationFn = operation.start;
- }
- }
-
- if (!startAnimationFn) {
- closeFn();
- } else {
- var animationRunner = startAnimationFn();
- animationRunner.done(function(status) {
- closeFn(!status);
- });
- updateAnimationRunners(animationEntry, animationRunner);
- }
- }
- });
- });
-
- return runner;
-
- // TODO(matsko): change to reference nodes
- function getAnchorNodes(node) {
- var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']';
- var items = node.hasAttribute(NG_ANIMATE_REF_ATTR)
- ? [node]
- : node.querySelectorAll(SELECTOR);
- var anchors = [];
- forEach(items, function(node) {
- var attr = node.getAttribute(NG_ANIMATE_REF_ATTR);
- if (attr && attr.length) {
- anchors.push(node);
- }
- });
- return anchors;
- }
-
- function groupAnimations(animations) {
- var preparedAnimations = [];
- var refLookup = {};
- forEach(animations, function(animation, index) {
- var element = animation.element;
- var node = getDomNode(element);
- var event = animation.event;
- var enterOrMove = ['enter', 'move'].indexOf(event) >= 0;
- var anchorNodes = animation.structural ? getAnchorNodes(node) : [];
-
- if (anchorNodes.length) {
- var direction = enterOrMove ? 'to' : 'from';
-
- forEach(anchorNodes, function(anchor) {
- var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR);
- refLookup[key] = refLookup[key] || {};
- refLookup[key][direction] = {
- animationID: index,
- element: jqLite(anchor)
- };
- });
- } else {
- preparedAnimations.push(animation);
- }
- });
-
- var usedIndicesLookup = {};
- var anchorGroups = {};
- forEach(refLookup, function(operations, key) {
- var from = operations.from;
- var to = operations.to;
-
- if (!from || !to) {
- // only one of these is set therefore we can't have an
- // anchor animation since all three pieces are required
- var index = from ? from.animationID : to.animationID;
- var indexKey = index.toString();
- if (!usedIndicesLookup[indexKey]) {
- usedIndicesLookup[indexKey] = true;
- preparedAnimations.push(animations[index]);
- }
- return;
- }
-
- var fromAnimation = animations[from.animationID];
- var toAnimation = animations[to.animationID];
- var lookupKey = from.animationID.toString();
- if (!anchorGroups[lookupKey]) {
- var group = anchorGroups[lookupKey] = {
- structural: true,
- beforeStart: function() {
- fromAnimation.beforeStart();
- toAnimation.beforeStart();
- },
- close: function() {
- fromAnimation.close();
- toAnimation.close();
- },
- classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes),
- from: fromAnimation,
- to: toAnimation,
- anchors: [] // TODO(matsko): change to reference nodes
- };
-
- // the anchor animations require that the from and to elements both have at least
- // one shared CSS class which effictively marries the two elements together to use
- // the same animation driver and to properly sequence the anchor animation.
- if (group.classes.length) {
- preparedAnimations.push(group);
- } else {
- preparedAnimations.push(fromAnimation);
- preparedAnimations.push(toAnimation);
- }
- }
-
- anchorGroups[lookupKey].anchors.push({
- 'out': from.element, 'in': to.element
- });
- });
-
- return preparedAnimations;
- }
-
- function cssClassesIntersection(a,b) {
- a = a.split(' ');
- b = b.split(' ');
- var matches = [];
-
- for (var i = 0; i < a.length; i++) {
- var aa = a[i];
- if (aa.substring(0,3) === 'ng-') continue;
-
- for (var j = 0; j < b.length; j++) {
- if (aa === b[j]) {
- matches.push(aa);
- break;
- }
- }
- }
-
- return matches.join(' ');
- }
-
- function invokeFirstDriver(animationDetails) {
- // we loop in reverse order since the more general drivers (like CSS and JS)
- // may attempt more elements, but custom drivers are more particular
- for (var i = drivers.length - 1; i >= 0; i--) {
- var driverName = drivers[i];
- if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check
-
- var factory = $injector.get(driverName);
- var driver = factory(animationDetails);
- if (driver) {
- return driver;
- }
- }
- }
-
- function beforeStart() {
- element.addClass(NG_ANIMATE_CLASSNAME);
- if (tempClasses) {
- $$jqLite.addClass(element, tempClasses);
- }
- }
-
- function updateAnimationRunners(animation, newRunner) {
- if (animation.from && animation.to) {
- update(animation.from.element);
- update(animation.to.element);
- } else {
- update(animation.element);
- }
-
- function update(element) {
- getRunner(element).setHost(newRunner);
- }
- }
-
- function handleDestroyedElement() {
- var runner = getRunner(element);
- if (runner && (event !== 'leave' || !options.$$domOperationFired)) {
- runner.end();
- }
- }
-
- function close(rejected) { // jshint ignore:line
- element.off('$destroy', handleDestroyedElement);
- removeRunner(element);
-
- applyAnimationClasses(element, options);
- applyAnimationStyles(element, options);
- options.domOperation();
-
- if (tempClasses) {
- $$jqLite.removeClass(element, tempClasses);
- }
-
- element.removeClass(NG_ANIMATE_CLASSNAME);
- runner.complete(!rejected);
- }
- };
- }];
-}];
-
-/* global angularAnimateModule: true,
-
- $$rAFMutexFactory,
- $$rAFSchedulerFactory,
- $$AnimateChildrenDirective,
- $$AnimateRunnerFactory,
- $$AnimateQueueProvider,
- $$AnimationProvider,
- $AnimateCssProvider,
- $$AnimateCssDriverProvider,
- $$AnimateJsProvider,
- $$AnimateJsDriverProvider,
-*/
-
-/**
- * @ngdoc module
- * @name ngAnimate
- * @description
- *
- * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
- * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app.
- *
- * <div doc-module-components="ngAnimate"></div>
- *
- * # Usage
- * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
- * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For
- * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within
- * the HTML element that the animation will be triggered on.
- *
- * ## Directive Support
- * The following directives are "animation aware":
- *
- * | Directive | Supported Animations |
- * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
- * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
- * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
- * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
- * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
- * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
- * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
- * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
- * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
- * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
- * | {@link module:ngMessages#animations ngMessage} | enter and leave |
- *
- * (More information can be found by visiting each the documentation associated with each directive.)
- *
- * ## CSS-based Animations
- *
- * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
- * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation.
- *
- * The example below shows how an `enter` animation can be made possible on a element using `ng-if`:
- *
- * ```html
- * <div ng-if="bool" class="fade">
- * Fade me in out
- * </div>
- * <button ng-click="bool=true">Fade In!</button>
- * <button ng-click="bool=false">Fade Out!</button>
- * ```
- *
- * Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
- *
- * ```css
- * /&#42; The starting CSS styles for the enter animation &#42;/
- * .fade.ng-enter {
- * transition:0.5s linear all;
- * opacity:0;
- * }
- *
- * /&#42; The finishing CSS styles for the enter animation &#42;/
- * .fade.ng-enter.ng-enter-active {
- * opacity:1;
- * }
- * ```
- *
- * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two
- * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition
- * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards.
- *
- * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions:
- *
- * ```css
- * /&#42; now the element will fade out before it is removed from the DOM &#42;/
- * .fade.ng-leave {
- * transition:0.5s linear all;
- * opacity:1;
- * }
- * .fade.ng-leave.ng-leave-active {
- * opacity:0;
- * }
- * ```
- *
- * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class:
- *
- * ```css
- * /&#42; there is no need to define anything inside of the destination
- * CSS class since the keyframe will take charge of the animation &#42;/
- * .fade.ng-leave {
- * animation: my_fade_animation 0.5s linear;
- * -webkit-animation: my_fade_animation 0.5s linear;
- * }
- *
- * @keyframes my_fade_animation {
- * from { opacity:1; }
- * to { opacity:0; }
- * }
- *
- * @-webkit-keyframes my_fade_animation {
- * from { opacity:1; }
- * to { opacity:0; }
- * }
- * ```
- *
- * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element.
- *
- * ### CSS Class-based Animations
- *
- * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different
- * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added
- * and removed.
- *
- * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class:
- *
- * ```html
- * <div ng-show="bool" class="fade">
- * Show and hide me
- * </div>
- * <button ng-click="bool=true">Toggle</button>
- *
- * <style>
- * .fade.ng-hide {
- * transition:0.5s linear all;
- * opacity:0;
- * }
- * </style>
- * ```
- *
- * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since
- * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest.
- *
- * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation
- * with CSS styles.
- *
- * ```html
- * <div ng-class="{on:onOff}" class="highlight">
- * Highlight this box
- * </div>
- * <button ng-click="onOff=!onOff">Toggle</button>
- *
- * <style>
- * .highlight {
- * transition:0.5s linear all;
- * }
- * .highlight.on-add {
- * background:white;
- * }
- * .highlight.on {
- * background:yellow;
- * }
- * .highlight.on-remove {
- * background:black;
- * }
- * </style>
- * ```
- *
- * We can also make use of CSS keyframes by placing them within the CSS classes.
- *
- *
- * ### CSS Staggering Animations
- * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
- * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
- * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
- * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
- * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
- *
- * ```css
- * .my-animation.ng-enter {
- * /&#42; standard transition code &#42;/
- * transition: 1s linear all;
- * opacity:0;
- * }
- * .my-animation.ng-enter-stagger {
- * /&#42; this will have a 100ms delay between each successive leave animation &#42;/
- * transition-delay: 0.1s;
- *
- * /&#42; in case the stagger doesn't work then the duration value
- * must be set to 0 to avoid an accidental CSS inheritance &#42;/
- * transition-duration: 0s;
- * }
- * .my-animation.ng-enter.ng-enter-active {
- * /&#42; standard transition styles &#42;/
- * opacity:1;
- * }
- * ```
- *
- * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
- * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
- * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
- * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired.
- *
- * The following code will issue the **ng-leave-stagger** event on the element provided:
- *
- * ```js
- * var kids = parent.children();
- *
- * $animate.leave(kids[0]); //stagger index=0
- * $animate.leave(kids[1]); //stagger index=1
- * $animate.leave(kids[2]); //stagger index=2
- * $animate.leave(kids[3]); //stagger index=3
- * $animate.leave(kids[4]); //stagger index=4
- *
- * window.requestAnimationFrame(function() {
- * //stagger has reset itself
- * $animate.leave(kids[5]); //stagger index=0
- * $animate.leave(kids[6]); //stagger index=1
- *
- * $scope.$digest();
- * });
- * ```
- *
- * Stagger animations are currently only supported within CSS-defined animations.
- *
- * ### The `ng-animate` CSS class
- *
- * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation.
- * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations).
- *
- * Therefore, animations can be applied to an element using this temporary class directly via CSS.
- *
- * ```css
- * .zipper.ng-animate {
- * transition:0.5s linear all;
- * }
- * .zipper.ng-enter {
- * opacity:0;
- * }
- * .zipper.ng-enter.ng-enter-active {
- * opacity:1;
- * }
- * .zipper.ng-leave {
- * opacity:1;
- * }
- * .zipper.ng-leave.ng-leave-active {
- * opacity:0;
- * }
- * ```
- *
- * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove
- * the CSS class once an animation has completed.)
- *
- *
- * ## JavaScript-based Animations
- *
- * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
- * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
- * `module.animation()` module function we can register the ainmation.
- *
- * Let's see an example of a enter/leave animation using `ngRepeat`:
- *
- * ```html
- * <div ng-repeat="item in items" class="slide">
- * {{ item }}
- * </div>
- * ```
- *
- * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`:
- *
- * ```js
- * myModule.animation('.slide', [function() {
- * return {
- * // make note that other events (like addClass/removeClass)
- * // have different function input parameters
- * enter: function(element, doneFn) {
- * jQuery(element).fadeIn(1000, doneFn);
- *
- * // remember to call doneFn so that angular
- * // knows that the animation has concluded
- * },
- *
- * move: function(element, doneFn) {
- * jQuery(element).fadeIn(1000, doneFn);
- * },
- *
- * leave: function(element, doneFn) {
- * jQuery(element).fadeOut(1000, doneFn);
- * }
- * }
- * }]
- * ```
- *
- * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
- * greensock.js and velocity.js.
- *
- * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define
- * our animations inside of the same registered animation, however, the function input arguments are a bit different:
- *
- * ```html
- * <div ng-class="color" class="colorful">
- * this box is moody
- * </div>
- * <button ng-click="color='red'">Change to red</button>
- * <button ng-click="color='blue'">Change to blue</button>
- * <button ng-click="color='green'">Change to green</button>
- * ```
- *
- * ```js
- * myModule.animation('.colorful', [function() {
- * return {
- * addClass: function(element, className, doneFn) {
- * // do some cool animation and call the doneFn
- * },
- * removeClass: function(element, className, doneFn) {
- * // do some cool animation and call the doneFn
- * },
- * setClass: function(element, addedClass, removedClass, doneFn) {
- * // do some cool animation and call the doneFn
- * }
- * }
- * }]
- * ```
- *
- * ## CSS + JS Animations Together
- *
- * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
- * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
- * charge of the animation**:
- *
- * ```html
- * <div ng-if="bool" class="slide">
- * Slide in and out
- * </div>
- * ```
- *
- * ```js
- * myModule.animation('.slide', [function() {
- * return {
- * enter: function(element, doneFn) {
- * jQuery(element).slideIn(1000, doneFn);
- * }
- * }
- * }]
- * ```
- *
- * ```css
- * .slide.ng-enter {
- * transition:0.5s linear all;
- * transform:translateY(-100px);
- * }
- * .slide.ng-enter.ng-enter-active {
- * transform:translateY(0);
- * }
- * ```
- *
- * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the
- * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from
- * our own JS-based animation code:
- *
- * ```js
- * myModule.animation('.slide', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
-* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
- * var runner = $animateCss(element, {
- * event: 'enter',
- * structural: true
- * }).start();
-* runner.done(doneFn);
- * }
- * }
- * }]
- * ```
- *
- * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
- *
- * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or
- * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that
- * data into `$animateCss` directly:
- *
- * ```js
- * myModule.animation('.slide', ['$animateCss', function($animateCss) {
- * return {
- * enter: function(element, doneFn) {
- * var runner = $animateCss(element, {
- * event: 'enter',
- * addClass: 'maroon-setting',
- * from: { height:0 },
- * to: { height: 200 }
- * }).start();
- *
- * runner.done(doneFn);
- * }
- * }
- * }]
- * ```
- *
- * Now we can fill in the rest via our transition CSS code:
- *
- * ```css
- * /&#42; the transition tells ngAnimate to make the animation happen &#42;/
- * .slide.ng-enter { transition:0.5s linear all; }
- *
- * /&#42; this extra CSS class will be absorbed into the transition
- * since the $animateCss code is adding the class &#42;/
- * .maroon-setting { background:red; }
- * ```
- *
- * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over.
- *
- * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
- *
- * ## Animation Anchoring (via `ng-animate-ref`)
- *
- * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
- * structural areas of an application (like views) by pairing up elements using an attribute
- * called `ng-animate-ref`.
- *
- * Let's say for example we have two views that are managed by `ng-view` and we want to show
- * that there is a relationship between two components situated in within these views. By using the
- * `ng-animate-ref` attribute we can identify that the two components are paired together and we
- * can then attach an animation, which is triggered when the view changes.
- *
- * Say for example we have the following template code:
- *
- * ```html
- * <!-- index.html -->
- * <div ng-view class="view-animation">
- * </div>
- *
- * <!-- home.html -->
- * <a href="#/banner-page">
- * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
- * </a>
- *
- * <!-- banner-page.html -->
- * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
- * ```
- *
- * Now, when the view changes (once the link is clicked), ngAnimate will examine the
- * HTML contents to see if there is a match reference between any components in the view
- * that is leaving and the view that is entering. It will scan both the view which is being
- * removed (leave) and inserted (enter) to see if there are any paired DOM elements that
- * contain a matching ref value.
- *
- * The two images match since they share the same ref value. ngAnimate will now create a
- * transport element (which is a clone of the first image element) and it will then attempt
- * to animate to the position of the second image element in the next view. For the animation to
- * work a special CSS class called `ng-anchor` will be added to the transported element.
- *
- * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then
- * ngAnimate will handle the entire transition for us as well as the addition and removal of
- * any changes of CSS classes between the elements:
- *
- * ```css
- * .banner.ng-anchor {
- * /&#42; this animation will last for 1 second since there are
- * two phases to the animation (an `in` and an `out` phase) &#42;/
- * transition:0.5s linear all;
- * }
- * ```
- *
- * We also **must** include animations for the views that are being entered and removed
- * (otherwise anchoring wouldn't be possible since the new view would be inserted right away).
- *
- * ```css
- * .view-animation.ng-enter, .view-animation.ng-leave {
- * transition:0.5s linear all;
- * position:fixed;
- * left:0;
- * top:0;
- * width:100%;
- * }
- * .view-animation.ng-enter {
- * transform:translateX(100%);
- * }
- * .view-animation.ng-leave,
- * .view-animation.ng-enter.ng-enter-active {
- * transform:translateX(0%);
- * }
- * .view-animation.ng-leave.ng-leave-active {
- * transform:translateX(-100%);
- * }
- * ```
- *
- * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur:
- * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away
- * from its origin. Once that animation is over then the `in` stage occurs which animates the
- * element to its destination. The reason why there are two animations is to give enough time
- * for the enter animation on the new element to be ready.
- *
- * The example above sets up a transition for both the in and out phases, but we can also target the out or
- * in phases directly via `ng-anchor-out` and `ng-anchor-in`.
- *
- * ```css
- * .banner.ng-anchor-out {
- * transition: 0.5s linear all;
- *
- * /&#42; the scale will be applied during the out animation,
- * but will be animated away when the in animation runs &#42;/
- * transform: scale(1.2);
- * }
- *
- * .banner.ng-anchor-in {
- * transition: 1s linear all;
- * }
- * ```
- *
- *
- *
- *
- * ### Anchoring Demo
- *
- <example module="anchoringExample"
- name="anchoringExample"
- id="anchoringExample"
- deps="angular-animate.js;angular-route.js"
- animations="true">
- <file name="index.html">
- <a href="#/">Home</a>
- <hr />
- <div class="view-container">
- <div ng-view class="view"></div>
- </div>
- </file>
- <file name="script.js">
- angular.module('anchoringExample', ['ngAnimate', 'ngRoute'])
- .config(['$routeProvider', function($routeProvider) {
- $routeProvider.when('/', {
- templateUrl: 'home.html',
- controller: 'HomeController as home'
- });
- $routeProvider.when('/profile/:id', {
- templateUrl: 'profile.html',
- controller: 'ProfileController as profile'
- });
- }])
- .run(['$rootScope', function($rootScope) {
- $rootScope.records = [
- { id:1, title: "Miss Beulah Roob" },
- { id:2, title: "Trent Morissette" },
- { id:3, title: "Miss Ava Pouros" },
- { id:4, title: "Rod Pouros" },
- { id:5, title: "Abdul Rice" },
- { id:6, title: "Laurie Rutherford Sr." },
- { id:7, title: "Nakia McLaughlin" },
- { id:8, title: "Jordon Blanda DVM" },
- { id:9, title: "Rhoda Hand" },
- { id:10, title: "Alexandrea Sauer" }
- ];
- }])
- .controller('HomeController', [function() {
- //empty
- }])
- .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) {
- var index = parseInt($routeParams.id, 10);
- var record = $rootScope.records[index - 1];
-
- this.title = record.title;
- this.id = record.id;
- }]);
- </file>
- <file name="home.html">
- <h2>Welcome to the home page</h1>
- <p>Please click on an element</p>
- <a class="record"
- ng-href="#/profile/{{ record.id }}"
- ng-animate-ref="{{ record.id }}"
- ng-repeat="record in records">
- {{ record.title }}
- </a>
- </file>
- <file name="profile.html">
- <div class="profile record" ng-animate-ref="{{ profile.id }}">
- {{ profile.title }}
- </div>
- </file>
- <file name="animations.css">
- .record {
- display:block;
- font-size:20px;
- }
- .profile {
- background:black;
- color:white;
- font-size:100px;
- }
- .view-container {
- position:relative;
- }
- .view-container > .view.ng-animate {
- position:absolute;
- top:0;
- left:0;
- width:100%;
- min-height:500px;
- }
- .view.ng-enter, .view.ng-leave,
- .record.ng-anchor {
- transition:0.5s linear all;
- }
- .view.ng-enter {
- transform:translateX(100%);
- }
- .view.ng-enter.ng-enter-active, .view.ng-leave {
- transform:translateX(0%);
- }
- .view.ng-leave.ng-leave-active {
- transform:translateX(-100%);
- }
- .record.ng-anchor-out {
- background:red;
- }
- </file>
- </example>
- *
- * ### How is the element transported?
- *
- * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
- * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
- * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
- * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
- * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
- * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
- * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
- * will become visible since the shim class will be removed.
- *
- * ### How is the morphing handled?
- *
- * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
- * what CSS classes differ between the starting element and the destination element. These different CSS classes
- * will be added/removed on the anchor element and a transition will be applied (the transition that is provided
- * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
- * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
- * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
- * the cloned element is placed inside of root element which is likely close to the body element).
- *
- * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body.
- *
- *
- * ## Using $animate in your directive code
- *
- * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
- * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
- * imagine we have a greeting box that shows and hides itself when the data changes
- *
- * ```html
- * <greeting-box active="onOrOff">Hi there</greeting-box>
- * ```
- *
- * ```js
- * ngModule.directive('greetingBox', ['$animate', function($animate) {
- * return function(scope, element, attrs) {
- * attrs.$observe('active', function(value) {
- * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
- * });
- * });
- * }]);
- * ```
- *
- * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element
- * in our HTML code then we can trigger a CSS or JS animation to happen.
- *
- * ```css
- * /&#42; normally we would create a CSS class to reference on the element &#42;/
- * greeting-box.on { transition:0.5s linear all; background:green; color:white; }
- * ```
- *
- * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's
- * possible be sure to visit the {@link ng.$animate $animate service API page}.
- *
- *
- * ### Preventing Collisions With Third Party Libraries
- *
- * Some third-party frameworks place animation duration defaults across many element or className
- * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
- * is expecting actual animations on these elements and has to wait for their completion.
- *
- * You can prevent this unwanted behavior by using a prefix on all your animation classes:
- *
- * ```css
- * /&#42; prefixed with animate- &#42;/
- * .animate-fade-add.animate-fade-add-active {
- * transition:1s linear all;
- * opacity:0;
- * }
- * ```
- *
- * You then configure `$animate` to enforce this prefix:
- *
- * ```js
- * $animateProvider.classNameFilter(/animate-/);
- * ```
- *
- * This also may provide your application with a speed boost since only specific elements containing CSS class prefix
- * will be evaluated for animation when any DOM changes occur in the application.
- *
- * ## Callbacks and Promises
- *
- * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger
- * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has
- * ended by chaining onto the returned promise that animation method returns.
- *
- * ```js
- * // somewhere within the depths of the directive
- * $animate.enter(element, parent).then(function() {
- * //the animation has completed
- * });
- * ```
- *
- * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
- * anymore.)
- *
- * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
- * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view
- * routing controller to hook into that:
- *
- * ```js
- * ngModule.controller('HomePageController', ['$animate', function($animate) {
- * $animate.on('enter', ngViewElement, function(element) {
- * // the animation for this route has completed
- * }]);
- * }])
- * ```
- *
- * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
- */
-
-/**
- * @ngdoc service
- * @name $animate
- * @kind object
- *
- * @description
- * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
- *
- * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}.
- */
-angular.module('ngAnimate', [])
- .directive('ngAnimateChildren', $$AnimateChildrenDirective)
-
- .factory('$$rAFMutex', $$rAFMutexFactory)
- .factory('$$rAFScheduler', $$rAFSchedulerFactory)
-
- .factory('$$AnimateRunner', $$AnimateRunnerFactory)
-
- .provider('$$animateQueue', $$AnimateQueueProvider)
- .provider('$$animation', $$AnimationProvider)
-
- .provider('$animateCss', $AnimateCssProvider)
- .provider('$$animateCssDriver', $$AnimateCssDriverProvider)
-
- .provider('$$animateJs', $$AnimateJsProvider)
- .provider('$$animateJsDriver', $$AnimateJsDriverProvider);
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-cookies.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-cookies.js
deleted file mode 100644
index c50d54c5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-cookies.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * @license AngularJS v1.2.25
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngCookies
- * @description
- *
- * # ngCookies
- *
- * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
- *
- *
- * <div doc-module-components="ngCookies"></div>
- *
- * See {@link ngCookies.$cookies `$cookies`} and
- * {@link ngCookies.$cookieStore `$cookieStore`} for usage.
- */
-
-
-angular.module('ngCookies', ['ng']).
- /**
- * @ngdoc service
- * @name $cookies
- *
- * @description
- * Provides read/write access to browser's cookies.
- *
- * Only a simple Object is exposed and by adding or removing properties to/from this object, new
- * cookies are created/deleted at the end of current $eval.
- * The object's properties can only be strings.
- *
- * Requires the {@link ngCookies `ngCookies`} module to be installed.
- *
- * @example
- *
- * ```js
- * angular.module('cookiesExample', ['ngCookies'])
- * .controller('ExampleController', ['$cookies', function($cookies) {
- * // Retrieving a cookie
- * var favoriteCookie = $cookies.myFavorite;
- * // Setting a cookie
- * $cookies.myFavorite = 'oatmeal';
- * }]);
- * ```
- */
- factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
- var cookies = {},
- lastCookies = {},
- lastBrowserCookies,
- runEval = false,
- copy = angular.copy,
- isUndefined = angular.isUndefined;
-
- //creates a poller fn that copies all cookies from the $browser to service & inits the service
- $browser.addPollFn(function() {
- var currentCookies = $browser.cookies();
- if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
- lastBrowserCookies = currentCookies;
- copy(currentCookies, lastCookies);
- copy(currentCookies, cookies);
- if (runEval) $rootScope.$apply();
- }
- })();
-
- runEval = true;
-
- //at the end of each eval, push cookies
- //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
- // strings or browser refuses to store some cookies, we update the model in the push fn.
- $rootScope.$watch(push);
-
- return cookies;
-
-
- /**
- * Pushes all the cookies from the service to the browser and verifies if all cookies were
- * stored.
- */
- function push() {
- var name,
- value,
- browserCookies,
- updated;
-
- //delete any cookies deleted in $cookies
- for (name in lastCookies) {
- if (isUndefined(cookies[name])) {
- $browser.cookies(name, undefined);
- }
- }
-
- //update all cookies updated in $cookies
- for(name in cookies) {
- value = cookies[name];
- if (!angular.isString(value)) {
- value = '' + value;
- cookies[name] = value;
- }
- if (value !== lastCookies[name]) {
- $browser.cookies(name, value);
- updated = true;
- }
- }
-
- //verify what was actually stored
- if (updated){
- updated = false;
- browserCookies = $browser.cookies();
-
- for (name in cookies) {
- if (cookies[name] !== browserCookies[name]) {
- //delete or reset all cookies that the browser dropped from $cookies
- if (isUndefined(browserCookies[name])) {
- delete cookies[name];
- } else {
- cookies[name] = browserCookies[name];
- }
- updated = true;
- }
- }
- }
- }
- }]).
-
-
- /**
- * @ngdoc service
- * @name $cookieStore
- * @requires $cookies
- *
- * @description
- * Provides a key-value (string-object) storage, that is backed by session cookies.
- * Objects put or retrieved from this storage are automatically serialized or
- * deserialized by angular's toJson/fromJson.
- *
- * Requires the {@link ngCookies `ngCookies`} module to be installed.
- *
- * @example
- *
- * ```js
- * angular.module('cookieStoreExample', ['ngCookies'])
- * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
- * // Put cookie
- * $cookieStore.put('myFavorite','oatmeal');
- * // Get cookie
- * var favoriteCookie = $cookieStore.get('myFavorite');
- * // Removing a cookie
- * $cookieStore.remove('myFavorite');
- * }]);
- * ```
- */
- factory('$cookieStore', ['$cookies', function($cookies) {
-
- return {
- /**
- * @ngdoc method
- * @name $cookieStore#get
- *
- * @description
- * Returns the value of given cookie key
- *
- * @param {string} key Id to use for lookup.
- * @returns {Object} Deserialized cookie value.
- */
- get: function(key) {
- var value = $cookies[key];
- return value ? angular.fromJson(value) : value;
- },
-
- /**
- * @ngdoc method
- * @name $cookieStore#put
- *
- * @description
- * Sets a value for given cookie key
- *
- * @param {string} key Id for the `value`.
- * @param {Object} value Value to be stored.
- */
- put: function(key, value) {
- $cookies[key] = angular.toJson(value);
- },
-
- /**
- * @ngdoc method
- * @name $cookieStore#remove
- *
- * @description
- * Remove given cookie
- *
- * @param {string} key Id of the key-value pair to delete.
- */
- remove: function(key) {
- delete $cookies[key];
- }
- };
-
- }]);
-
-
-})(window, window.angular); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.js
deleted file mode 100644
index dbe6eca1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.js
+++ /dev/null
@@ -1,911 +0,0 @@
-/**
- * @license AngularJS v1.2.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc overview
- * @name ngRoute
- * @description
- *
- * # ngRoute
- *
- * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- * {@installModule route}
- *
- * <div doc-module-components="ngRoute"></div>
- */
- /* global -ngRouteModule */
-var ngRouteModule = angular.module('ngRoute', ['ng']).
- provider('$route', $RouteProvider);
-
-/**
- * @ngdoc object
- * @name ngRoute.$routeProvider
- * @function
- *
- * @description
- *
- * Used for configuring routes.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- * ## Dependencies
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- */
-function $RouteProvider(){
- function inherit(parent, extra) {
- return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);
- }
-
- var routes = {};
-
- /**
- * @ngdoc method
- * @name ngRoute.$routeProvider#when
- * @methodOf ngRoute.$routeProvider
- *
- * @param {string} path Route path (matched against `$location.path`). If `$location.path`
- * contains redundant trailing slash or is missing one, the route will still match and the
- * `$location.path` will be updated to add or drop the trailing slash to exactly match the
- * route definition.
- *
- * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
- * to the next slash are matched and stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain named groups starting with a colon and ending with a star:
- * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
- *
- * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
- * `/color/brown/largecode/code/with/slashs/edit` and extract:
- *
- * * `color: brown`
- * * `largecode: code/with/slashs`.
- *
- *
- * @param {Object} route Mapping information to be assigned to `$route.current` on route
- * match.
- *
- * Object properties:
- *
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
- * newly created scope or the name of a {@link angular.Module#controller registered
- * controller} if passed as a string.
- * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
- * published to scope under the `controllerAs` name.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used by {@link
- * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
- * This property takes precedence over `templateUrl`.
- *
- * If `template` is a function, it will be called with the following parameters:
- *
- * - `{Array.<Object>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route
- *
- * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
- * template that should be used by {@link ngRoute.directive:ngView ngView}.
- *
- * If `templateUrl` is a function, it will be called with the following parameters:
- *
- * - `{Array.<Object>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route
- *
- * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
- * be injected into the controller. If any of these dependencies are promises, the router
- * will wait for them all to be resolved or one to be rejected before the controller is
- * instantiated.
- * If all the promises are resolved successfully, the values of the resolved promises are
- * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
- * fired. If any of the promises are rejected the
- * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
- * is:
- *
- * - `key` – `{string}`: a name of a dependency to be injected into the controller.
- * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
- * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
- * and the return value is treated as the dependency. If the result is a promise, it is
- * resolved before its value is injected into the controller. Be aware that
- * `ngRoute.$routeParams` will still refer to the previous route within these resolve
- * functions. Use `$route.current.params` to access the new route parameters, instead.
- *
- * - `redirectTo` – {(string|function())=} – value to update
- * {@link ng.$location $location} path with and trigger route redirection.
- *
- * If `redirectTo` is a function, it will be called with the following parameters:
- *
- * - `{Object.<string>}` - route parameters extracted from the current
- * `$location.path()` by applying the current route templateUrl.
- * - `{string}` - current `$location.path()`
- * - `{Object}` - current `$location.search()`
- *
- * The custom `redirectTo` function is expected to return a string which will be used
- * to update `$location.path()` and `$location.search()`.
- *
- * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
- * or `$location.hash()` changes.
- *
- * If the option is set to `false` and url in the browser changes, then
- * `$routeUpdate` event is broadcasted on the root scope.
- *
- * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
- *
- * If the option is set to `true`, then the particular route can be matched without being
- * case sensitive
- *
- * @returns {Object} self
- *
- * @description
- * Adds a new route definition to the `$route` service.
- */
- this.when = function(path, route) {
- routes[path] = angular.extend(
- {reloadOnSearch: true},
- route,
- path && pathRegExp(path, route)
- );
-
- // create redirection for trailing slashes
- if (path) {
- var redirectPath = (path[path.length-1] == '/')
- ? path.substr(0, path.length-1)
- : path +'/';
-
- routes[redirectPath] = angular.extend(
- {redirectTo: path},
- pathRegExp(redirectPath, route)
- );
- }
-
- return this;
- };
-
- /**
- * @param path {string} path
- * @param opts {Object} options
- * @return {?Object}
- *
- * @description
- * Normalizes the given path, returning a regular expression
- * and the original path.
- *
- * Inspired by pathRexp in visionmedia/express/lib/utils.js.
- */
- function pathRegExp(path, opts) {
- var insensitive = opts.caseInsensitiveMatch,
- ret = {
- originalPath: path,
- regexp: path
- },
- keys = ret.keys = [];
-
- path = path
- .replace(/([().])/g, '\\$1')
- .replace(/(\/)?:(\w+)([\?|\*])?/g, function(_, slash, key, option){
- var optional = option === '?' ? option : null;
- var star = option === '*' ? option : null;
- keys.push({ name: key, optional: !!optional });
- slash = slash || '';
- return ''
- + (optional ? '' : slash)
- + '(?:'
- + (optional ? slash : '')
- + (star && '(.+?)' || '([^/]+)')
- + (optional || '')
- + ')'
- + (optional || '');
- })
- .replace(/([\/$\*])/g, '\\$1');
-
- ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
- return ret;
- }
-
- /**
- * @ngdoc method
- * @name ngRoute.$routeProvider#otherwise
- * @methodOf ngRoute.$routeProvider
- *
- * @description
- * Sets route definition that will be used on route change when no other route definition
- * is matched.
- *
- * @param {Object} params Mapping information to be assigned to `$route.current`.
- * @returns {Object} self
- */
- this.otherwise = function(params) {
- this.when(null, params);
- return this;
- };
-
-
- this.$get = ['$rootScope',
- '$location',
- '$routeParams',
- '$q',
- '$injector',
- '$http',
- '$templateCache',
- '$sce',
- function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {
-
- /**
- * @ngdoc object
- * @name ngRoute.$route
- * @requires $location
- * @requires $routeParams
- *
- * @property {Object} current Reference to the current route definition.
- * The route definition contains:
- *
- * - `controller`: The controller constructor as define in route definition.
- * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
- * controller instantiation. The `locals` contain
- * the resolved values of the `resolve` map. Additionally the `locals` also contain:
- *
- * - `$scope` - The current route scope.
- * - `$template` - The current route template HTML.
- *
- * @property {Array.<Object>} routes Array of all configured routes.
- *
- * @description
- * `$route` is used for deep-linking URLs to controllers and views (HTML partials).
- * It watches `$location.url()` and tries to map the path to an existing route definition.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
- *
- * The `$route` service is typically used in conjunction with the
- * {@link ngRoute.directive:ngView `ngView`} directive and the
- * {@link ngRoute.$routeParams `$routeParams`} service.
- *
- * @example
- This example shows how changing the URL hash causes the `$route` to match a route against the
- URL, and the `ngView` pulls in the partial.
-
- Note that this example is using {@link ng.directive:script inlined templates}
- to get it working on jsfiddle as well.
-
- <example module="ngViewExample" deps="angular-route.js">
- <file name="index.html">
- <div ng-controller="MainCntl">
- Choose:
- <a href="Book/Moby">Moby</a> |
- <a href="Book/Moby/ch/1">Moby: Ch1</a> |
- <a href="Book/Gatsby">Gatsby</a> |
- <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
- <a href="Book/Scarlet">Scarlet Letter</a><br/>
-
- <div ng-view></div>
- <hr />
-
- <pre>$location.path() = {{$location.path()}}</pre>
- <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
- <pre>$route.current.params = {{$route.current.params}}</pre>
- <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
- <pre>$routeParams = {{$routeParams}}</pre>
- </div>
- </file>
-
- <file name="book.html">
- controller: {{name}}<br />
- Book Id: {{params.bookId}}<br />
- </file>
-
- <file name="chapter.html">
- controller: {{name}}<br />
- Book Id: {{params.bookId}}<br />
- Chapter Id: {{params.chapterId}}
- </file>
-
- <file name="script.js">
- angular.module('ngViewExample', ['ngRoute'])
-
- .config(function($routeProvider, $locationProvider) {
- $routeProvider.when('/Book/:bookId', {
- templateUrl: 'book.html',
- controller: BookCntl,
- resolve: {
- // I will cause a 1 second delay
- delay: function($q, $timeout) {
- var delay = $q.defer();
- $timeout(delay.resolve, 1000);
- return delay.promise;
- }
- }
- });
- $routeProvider.when('/Book/:bookId/ch/:chapterId', {
- templateUrl: 'chapter.html',
- controller: ChapterCntl
- });
-
- // configure html5 to get links working on jsfiddle
- $locationProvider.html5Mode(true);
- });
-
- function MainCntl($scope, $route, $routeParams, $location) {
- $scope.$route = $route;
- $scope.$location = $location;
- $scope.$routeParams = $routeParams;
- }
-
- function BookCntl($scope, $routeParams) {
- $scope.name = "BookCntl";
- $scope.params = $routeParams;
- }
-
- function ChapterCntl($scope, $routeParams) {
- $scope.name = "ChapterCntl";
- $scope.params = $routeParams;
- }
- </file>
-
- <file name="scenario.js">
- it('should load and compile correct template', function() {
- element('a:contains("Moby: Ch1")').click();
- var content = element('.doc-example-live [ng-view]').text();
- expect(content).toMatch(/controller\: ChapterCntl/);
- expect(content).toMatch(/Book Id\: Moby/);
- expect(content).toMatch(/Chapter Id\: 1/);
-
- element('a:contains("Scarlet")').click();
- sleep(2); // promises are not part of scenario waiting
- content = element('.doc-example-live [ng-view]').text();
- expect(content).toMatch(/controller\: BookCntl/);
- expect(content).toMatch(/Book Id\: Scarlet/);
- });
- </file>
- </example>
- */
-
- /**
- * @ngdoc event
- * @name ngRoute.$route#$routeChangeStart
- * @eventOf ngRoute.$route
- * @eventType broadcast on root scope
- * @description
- * Broadcasted before a route change. At this point the route services starts
- * resolving all of the dependencies needed for the route change to occurs.
- * Typically this involves fetching the view template as well as any dependencies
- * defined in `resolve` route property. Once all of the dependencies are resolved
- * `$routeChangeSuccess` is fired.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {Route} next Future route information.
- * @param {Route} current Current route information.
- */
-
- /**
- * @ngdoc event
- * @name ngRoute.$route#$routeChangeSuccess
- * @eventOf ngRoute.$route
- * @eventType broadcast on root scope
- * @description
- * Broadcasted after a route dependencies are resolved.
- * {@link ngRoute.directive:ngView ngView} listens for the directive
- * to instantiate the controller and render the view.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {Route} current Current route information.
- * @param {Route|Undefined} previous Previous route information, or undefined if current is
- * first route entered.
- */
-
- /**
- * @ngdoc event
- * @name ngRoute.$route#$routeChangeError
- * @eventOf ngRoute.$route
- * @eventType broadcast on root scope
- * @description
- * Broadcasted if any of the resolve promises are rejected.
- *
- * @param {Object} angularEvent Synthetic event object
- * @param {Route} current Current route information.
- * @param {Route} previous Previous route information.
- * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
- */
-
- /**
- * @ngdoc event
- * @name ngRoute.$route#$routeUpdate
- * @eventOf ngRoute.$route
- * @eventType broadcast on root scope
- * @description
- *
- * The `reloadOnSearch` property has been set to false, and we are reusing the same
- * instance of the Controller.
- */
-
- var forceReload = false,
- $route = {
- routes: routes,
-
- /**
- * @ngdoc method
- * @name ngRoute.$route#reload
- * @methodOf ngRoute.$route
- *
- * @description
- * Causes `$route` service to reload the current route even if
- * {@link ng.$location $location} hasn't changed.
- *
- * As a result of that, {@link ngRoute.directive:ngView ngView}
- * creates new scope, reinstantiates the controller.
- */
- reload: function() {
- forceReload = true;
- $rootScope.$evalAsync(updateRoute);
- }
- };
-
- $rootScope.$on('$locationChangeSuccess', updateRoute);
-
- return $route;
-
- /////////////////////////////////////////////////////
-
- /**
- * @param on {string} current url
- * @param route {Object} route regexp to match the url against
- * @return {?Object}
- *
- * @description
- * Check if the route matches the current url.
- *
- * Inspired by match in
- * visionmedia/express/lib/router/router.js.
- */
- function switchRouteMatcher(on, route) {
- var keys = route.keys,
- params = {};
-
- if (!route.regexp) return null;
-
- var m = route.regexp.exec(on);
- if (!m) return null;
-
- for (var i = 1, len = m.length; i < len; ++i) {
- var key = keys[i - 1];
-
- var val = 'string' == typeof m[i]
- ? decodeURIComponent(m[i])
- : m[i];
-
- if (key && val) {
- params[key.name] = val;
- }
- }
- return params;
- }
-
- function updateRoute() {
- var next = parseRoute(),
- last = $route.current;
-
- if (next && last && next.$$route === last.$$route
- && angular.equals(next.pathParams, last.pathParams)
- && !next.reloadOnSearch && !forceReload) {
- last.params = next.params;
- angular.copy(last.params, $routeParams);
- $rootScope.$broadcast('$routeUpdate', last);
- } else if (next || last) {
- forceReload = false;
- $rootScope.$broadcast('$routeChangeStart', next, last);
- $route.current = next;
- if (next) {
- if (next.redirectTo) {
- if (angular.isString(next.redirectTo)) {
- $location.path(interpolate(next.redirectTo, next.params)).search(next.params)
- .replace();
- } else {
- $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))
- .replace();
- }
- }
- }
-
- $q.when(next).
- then(function() {
- if (next) {
- var locals = angular.extend({}, next.resolve),
- template, templateUrl;
-
- angular.forEach(locals, function(value, key) {
- locals[key] = angular.isString(value) ?
- $injector.get(value) : $injector.invoke(value);
- });
-
- if (angular.isDefined(template = next.template)) {
- if (angular.isFunction(template)) {
- template = template(next.params);
- }
- } else if (angular.isDefined(templateUrl = next.templateUrl)) {
- if (angular.isFunction(templateUrl)) {
- templateUrl = templateUrl(next.params);
- }
- templateUrl = $sce.getTrustedResourceUrl(templateUrl);
- if (angular.isDefined(templateUrl)) {
- next.loadedTemplateUrl = templateUrl;
- template = $http.get(templateUrl, {cache: $templateCache}).
- then(function(response) { return response.data; });
- }
- }
- if (angular.isDefined(template)) {
- locals['$template'] = template;
- }
- return $q.all(locals);
- }
- }).
- // after route change
- then(function(locals) {
- if (next == $route.current) {
- if (next) {
- next.locals = locals;
- angular.copy(next.params, $routeParams);
- }
- $rootScope.$broadcast('$routeChangeSuccess', next, last);
- }
- }, function(error) {
- if (next == $route.current) {
- $rootScope.$broadcast('$routeChangeError', next, last, error);
- }
- });
- }
- }
-
-
- /**
- * @returns the current active route, by matching it against the URL
- */
- function parseRoute() {
- // Match a route
- var params, match;
- angular.forEach(routes, function(route, path) {
- if (!match && (params = switchRouteMatcher($location.path(), route))) {
- match = inherit(route, {
- params: angular.extend({}, $location.search(), params),
- pathParams: params});
- match.$$route = route;
- }
- });
- // No route matched; fallback to "otherwise" route
- return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
- }
-
- /**
- * @returns interpolation of the redirect path with the parameters
- */
- function interpolate(string, params) {
- var result = [];
- angular.forEach((string||'').split(':'), function(segment, i) {
- if (i === 0) {
- result.push(segment);
- } else {
- var segmentMatch = segment.match(/(\w+)(.*)/);
- var key = segmentMatch[1];
- result.push(params[key]);
- result.push(segmentMatch[2] || '');
- delete params[key];
- }
- });
- return result.join('');
- }
- }];
-}
-
-ngRouteModule.provider('$routeParams', $RouteParamsProvider);
-
-
-/**
- * @ngdoc object
- * @name ngRoute.$routeParams
- * @requires $route
- *
- * @description
- * The `$routeParams` service allows you to retrieve the current set of route parameters.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * The route parameters are a combination of {@link ng.$location `$location`}'s
- * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}.
- * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
- *
- * In case of parameter name collision, `path` params take precedence over `search` params.
- *
- * The service guarantees that the identity of the `$routeParams` object will remain unchanged
- * (but its properties will likely change) even when a route change occurs.
- *
- * Note that the `$routeParams` are only updated *after* a route change completes successfully.
- * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
- * Instead you can use `$route.current.params` to access the new route's parameters.
- *
- * @example
- * <pre>
- * // Given:
- * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
- * // Route: /Chapter/:chapterId/Section/:sectionId
- * //
- * // Then
- * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
- * </pre>
- */
-function $RouteParamsProvider() {
- this.$get = function() { return {}; };
-}
-
-ngRouteModule.directive('ngView', ngViewFactory);
-ngRouteModule.directive('ngView', ngViewFillContentFactory);
-
-
-/**
- * @ngdoc directive
- * @name ngRoute.directive:ngView
- * @restrict ECA
- *
- * @description
- * # Overview
- * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
- * including the rendered template of the current route into the main layout (`index.html`) file.
- * Every time the current route changes, the included view changes with it according to the
- * configuration of the `$route` service.
- *
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- *
- * @animations
- * enter - animation is used to bring new content into the browser.
- * leave - animation is used to animate existing content away.
- *
- * The enter and leave animation occur concurrently.
- *
- * @scope
- * @priority 400
- * @example
- <example module="ngViewExample" deps="angular-route.js" animations="true">
- <file name="index.html">
- <div ng-controller="MainCntl as main">
- Choose:
- <a href="Book/Moby">Moby</a> |
- <a href="Book/Moby/ch/1">Moby: Ch1</a> |
- <a href="Book/Gatsby">Gatsby</a> |
- <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
- <a href="Book/Scarlet">Scarlet Letter</a><br/>
-
- <div class="view-animate-container">
- <div ng-view class="view-animate"></div>
- </div>
- <hr />
-
- <pre>$location.path() = {{main.$location.path()}}</pre>
- <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
- <pre>$route.current.params = {{main.$route.current.params}}</pre>
- <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
- <pre>$routeParams = {{main.$routeParams}}</pre>
- </div>
- </file>
-
- <file name="book.html">
- <div>
- controller: {{book.name}}<br />
- Book Id: {{book.params.bookId}}<br />
- </div>
- </file>
-
- <file name="chapter.html">
- <div>
- controller: {{chapter.name}}<br />
- Book Id: {{chapter.params.bookId}}<br />
- Chapter Id: {{chapter.params.chapterId}}
- </div>
- </file>
-
- <file name="animations.css">
- .view-animate-container {
- position:relative;
- height:100px!important;
- position:relative;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .view-animate {
- padding:10px;
- }
-
- .view-animate.ng-enter, .view-animate.ng-leave {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
-
- display:block;
- width:100%;
- border-left:1px solid black;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- padding:10px;
- }
-
- .view-animate.ng-enter {
- left:100%;
- }
- .view-animate.ng-enter.ng-enter-active {
- left:0;
- }
- .view-animate.ng-leave.ng-leave-active {
- left:-100%;
- }
- </file>
-
- <file name="script.js">
- angular.module('ngViewExample', ['ngRoute', 'ngAnimate'],
- function($routeProvider, $locationProvider) {
- $routeProvider.when('/Book/:bookId', {
- templateUrl: 'book.html',
- controller: BookCntl,
- controllerAs: 'book'
- });
- $routeProvider.when('/Book/:bookId/ch/:chapterId', {
- templateUrl: 'chapter.html',
- controller: ChapterCntl,
- controllerAs: 'chapter'
- });
-
- // configure html5 to get links working on jsfiddle
- $locationProvider.html5Mode(true);
- });
-
- function MainCntl($route, $routeParams, $location) {
- this.$route = $route;
- this.$location = $location;
- this.$routeParams = $routeParams;
- }
-
- function BookCntl($routeParams) {
- this.name = "BookCntl";
- this.params = $routeParams;
- }
-
- function ChapterCntl($routeParams) {
- this.name = "ChapterCntl";
- this.params = $routeParams;
- }
- </file>
-
- <file name="scenario.js">
- it('should load and compile correct template', function() {
- element('a:contains("Moby: Ch1")').click();
- var content = element('.doc-example-live [ng-view]').text();
- expect(content).toMatch(/controller\: ChapterCntl/);
- expect(content).toMatch(/Book Id\: Moby/);
- expect(content).toMatch(/Chapter Id\: 1/);
-
- element('a:contains("Scarlet")').click();
- content = element('.doc-example-live [ng-view]').text();
- expect(content).toMatch(/controller\: BookCntl/);
- expect(content).toMatch(/Book Id\: Scarlet/);
- });
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc event
- * @name ngRoute.directive:ngView#$viewContentLoaded
- * @eventOf ngRoute.directive:ngView
- * @eventType emit on the current ngView scope
- * @description
- * Emitted every time the ngView content is reloaded.
- */
-ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
-function ngViewFactory( $route, $anchorScroll, $animate) {
- return {
- restrict: 'ECA',
- terminal: true,
- priority: 400,
- transclude: 'element',
- link: function(scope, $element, attr, ctrl, $transclude) {
- var currentScope,
- currentElement,
- autoScrollExp = attr.autoscroll,
- onloadExp = attr.onload || '';
-
- scope.$on('$routeChangeSuccess', update);
- update();
-
- function cleanupLastView() {
- if (currentScope) {
- currentScope.$destroy();
- currentScope = null;
- }
- if(currentElement) {
- $animate.leave(currentElement);
- currentElement = null;
- }
- }
-
- function update() {
- var locals = $route.current && $route.current.locals,
- template = locals && locals.$template;
-
- if (template) {
- var newScope = scope.$new();
- var current = $route.current;
-
- // Note: This will also link all children of ng-view that were contained in the original
- // html. If that content contains controllers, ... they could pollute/change the scope.
- // However, using ng-view on an element with additional content does not make sense...
- // Note: We can't remove them in the cloneAttchFn of $transclude as that
- // function is called before linking the content, which would apply child
- // directives to non existing elements.
- var clone = $transclude(newScope, function(clone) {
- $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
- if (angular.isDefined(autoScrollExp)
- && (!autoScrollExp || scope.$eval(autoScrollExp))) {
- $anchorScroll();
- }
- });
- cleanupLastView();
- });
-
- currentElement = clone;
- currentScope = current.scope = newScope;
- currentScope.$emit('$viewContentLoaded');
- currentScope.$eval(onloadExp);
- } else {
- cleanupLastView();
- }
- }
- }
- };
-}
-
-// This directive is called during the $transclude call of the first `ngView` directive.
-// It will replace and compile the content of the element with the loaded template.
-// We need this directive so that the element content is already filled when
-// the link function of another directive on the same element as ngView
-// is called.
-ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
-function ngViewFillContentFactory($compile, $controller, $route) {
- return {
- restrict: 'ECA',
- priority: -400,
- link: function(scope, $element) {
- var current = $route.current,
- locals = current.locals;
-
- $element.html(locals.$template);
-
- var link = $compile($element.contents());
-
- if (current.controller) {
- locals.$scope = scope;
- var controller = $controller(current.controller, locals);
- if (current.controllerAs) {
- scope[current.controllerAs] = controller;
- }
- $element.data('$ngControllerController', controller);
- $element.children().data('$ngControllerController', controller);
- }
-
- link(scope);
- }
- };
-}
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.min.js
deleted file mode 100644
index 67158fbf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-route.min.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- AngularJS v1.2.25
- (c) 2010-2014 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(n,e,A){'use strict';function x(s,g,h){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);k&&(k.$destroy(),k=null);l&&(h.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){h.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});k=d.scope=b;k.$emit("$viewContentLoaded");k.$eval(u)}else y()}
-var k,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,h){return{restrict:"ECA",priority:-400,link:function(a,c){var b=h.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){},
-{prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var h={};this.when=function(a,c){h[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b=
-"/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";h[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,k){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart",
-d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=k.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
-b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(h,function(f,h){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var k=1,p=g.length;k<p;++k){var n=q[k-1],r=g[k];n&&r&&(l[n.name]=r)}q=l}else q=null;
-else q=null;q=a=q}q&&(b=s(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||h[null]&&s(h[null],{params:{},pathParams:{}})}function t(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var u=!1,r={routes:h,reload:function(){u=!0;a.$evalAsync(l)}};a.$on("$locationChangeSuccess",l);return r}]});n.provider("$routeParams",function(){this.$get=function(){return{}}});
-n.directive("ngView",x);n.directive("ngView",z);x.$inject=["$route","$anchorScroll","$animate"];z.$inject=["$compile","$controller","$route"]})(window,window.angular);
-//# sourceMappingURL=angular-route.min.js.map \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-sanitize.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-sanitize.js
deleted file mode 100644
index 87100fdb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-sanitize.js
+++ /dev/null
@@ -1,647 +0,0 @@
-/**
- * @license AngularJS v1.2.25
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-var $sanitizeMinErr = angular.$$minErr('$sanitize');
-
-/**
- * @ngdoc module
- * @name ngSanitize
- * @description
- *
- * # ngSanitize
- *
- * The `ngSanitize` module provides functionality to sanitize HTML.
- *
- *
- * <div doc-module-components="ngSanitize"></div>
- *
- * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
- */
-
-/*
- * HTML Parser By Misko Hevery (misko@hevery.com)
- * based on: HTML Parser By John Resig (ejohn.org)
- * Original code by Erik Arvidsson, Mozilla Public License
- * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
- *
- * // Use like so:
- * htmlParser(htmlString, {
- * start: function(tag, attrs, unary) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * });
- *
- */
-
-
-/**
- * @ngdoc service
- * @name $sanitize
- * @kind function
- *
- * @description
- * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
- * then serialized back to properly escaped html string. This means that no unsafe input can make
- * it into the returned string, however, since our parser is more strict than a typical browser
- * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
- * browser, won't make it through the sanitizer.
- * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
- * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
- *
- * @param {string} html Html input.
- * @returns {string} Sanitized html.
- *
- * @example
- <example module="sanitizeExample" deps="angular-sanitize.js">
- <file name="index.html">
- <script>
- angular.module('sanitizeExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
- $scope.snippet =
- '<p style="color:blue">an html\n' +
- '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
- 'snippet</p>';
- $scope.deliberatelyTrustDangerousSnippet = function() {
- return $sce.trustAsHtml($scope.snippet);
- };
- }]);
- </script>
- <div ng-controller="ExampleController">
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
- <table>
- <tr>
- <td>Directive</td>
- <td>How</td>
- <td>Source</td>
- <td>Rendered</td>
- </tr>
- <tr id="bind-html-with-sanitize">
- <td>ng-bind-html</td>
- <td>Automatically uses $sanitize</td>
- <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
- <td><div ng-bind-html="snippet"></div></td>
- </tr>
- <tr id="bind-html-with-trust">
- <td>ng-bind-html</td>
- <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
- <td>
- <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
-&lt;/div&gt;</pre>
- </td>
- <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
- </tr>
- <tr id="bind-default">
- <td>ng-bind</td>
- <td>Automatically escapes</td>
- <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
- <td><div ng-bind="snippet"></div></td>
- </tr>
- </table>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should sanitize the html snippet by default', function() {
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
- toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
- });
-
- it('should inline raw snippet if bound to a trusted value', function() {
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
- toBe("<p style=\"color:blue\">an html\n" +
- "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
- "snippet</p>");
- });
-
- it('should escape snippet without any filter', function() {
- expect(element(by.css('#bind-default div')).getInnerHtml()).
- toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
- "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
- "snippet&lt;/p&gt;");
- });
-
- it('should update', function() {
- element(by.model('snippet')).clear();
- element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
- toBe('new <b>text</b>');
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
- 'new <b onclick="alert(1)">text</b>');
- expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
- "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
- });
- </file>
- </example>
- */
-function $SanitizeProvider() {
- this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
- return function(html) {
- var buf = [];
- htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
- return !/^unsafe/.test($$sanitizeUri(uri, isImage));
- }));
- return buf.join('');
- };
- }];
-}
-
-function sanitizeText(chars) {
- var buf = [];
- var writer = htmlSanitizeWriter(buf, angular.noop);
- writer.chars(chars);
- return buf.join('');
-}
-
-
-// Regular Expressions for parsing tags and attributes
-var START_TAG_REGEXP =
- /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
- END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
- ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
- BEGIN_TAG_REGEXP = /^</,
- BEGING_END_TAGE_REGEXP = /^<\//,
- COMMENT_REGEXP = /<!--(.*?)-->/g,
- DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
- CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
- SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- // Match everything outside of normal chars and " (quote character)
- NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
-
-
-// Good source of info about elements and attributes
-// http://dev.w3.org/html5/spec/Overview.html#semantics
-// http://simon.html5.org/html-elements
-
-// Safe Void Elements - HTML5
-// http://dev.w3.org/html5/spec/Overview.html#void-elements
-var voidElements = makeMap("area,br,col,hr,img,wbr");
-
-// Elements that you can, intentionally, leave open (and which close themselves)
-// http://dev.w3.org/html5/spec/Overview.html#optional-tags
-var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
- optionalEndTagInlineElements = makeMap("rp,rt"),
- optionalEndTagElements = angular.extend({},
- optionalEndTagInlineElements,
- optionalEndTagBlockElements);
-
-// Safe Block Elements - HTML5
-var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
- "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
- "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
-
-// Inline Elements - HTML5
-var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
- "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
- "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
-
-
-// Special Elements (can contain anything)
-var specialElements = makeMap("script,style");
-
-var validElements = angular.extend({},
- voidElements,
- blockElements,
- inlineElements,
- optionalEndTagElements);
-
-//Attributes that have href and hence need to be sanitized
-var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
-var validAttrs = angular.extend({}, uriAttrs, makeMap(
- 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
- 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
- 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
- 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+
- 'valign,value,vspace,width'));
-
-function makeMap(str) {
- var obj = {}, items = str.split(','), i;
- for (i = 0; i < items.length; i++) obj[items[i]] = true;
- return obj;
-}
-
-
-/**
- * @example
- * htmlParser(htmlString, {
- * start: function(tag, attrs, unary) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * });
- *
- * @param {string} html string
- * @param {object} handler
- */
-function htmlParser( html, handler ) {
- if (typeof html !== 'string') {
- if (html === null || typeof html === 'undefined') {
- html = '';
- } else {
- html = '' + html;
- }
- }
- var index, chars, match, stack = [], last = html, text;
- stack.last = function() { return stack[ stack.length - 1 ]; };
-
- while ( html ) {
- text = '';
- chars = true;
-
- // Make sure we're not in a script or style element
- if ( !stack.last() || !specialElements[ stack.last() ] ) {
-
- // Comment
- if ( html.indexOf("<!--") === 0 ) {
- // comments containing -- are not allowed unless they terminate the comment
- index = html.indexOf("--", 4);
-
- if ( index >= 0 && html.lastIndexOf("-->", index) === index) {
- if (handler.comment) handler.comment( html.substring( 4, index ) );
- html = html.substring( index + 3 );
- chars = false;
- }
- // DOCTYPE
- } else if ( DOCTYPE_REGEXP.test(html) ) {
- match = html.match( DOCTYPE_REGEXP );
-
- if ( match ) {
- html = html.replace( match[0], '');
- chars = false;
- }
- // end tag
- } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
- match = html.match( END_TAG_REGEXP );
-
- if ( match ) {
- html = html.substring( match[0].length );
- match[0].replace( END_TAG_REGEXP, parseEndTag );
- chars = false;
- }
-
- // start tag
- } else if ( BEGIN_TAG_REGEXP.test(html) ) {
- match = html.match( START_TAG_REGEXP );
-
- if ( match ) {
- // We only have a valid start-tag if there is a '>'.
- if ( match[4] ) {
- html = html.substring( match[0].length );
- match[0].replace( START_TAG_REGEXP, parseStartTag );
- }
- chars = false;
- } else {
- // no ending tag found --- this piece should be encoded as an entity.
- text += '<';
- html = html.substring(1);
- }
- }
-
- if ( chars ) {
- index = html.indexOf("<");
-
- text += index < 0 ? html : html.substring( 0, index );
- html = index < 0 ? "" : html.substring( index );
-
- if (handler.chars) handler.chars( decodeEntities(text) );
- }
-
- } else {
- html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
- function(all, text){
- text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
-
- if (handler.chars) handler.chars( decodeEntities(text) );
-
- return "";
- });
-
- parseEndTag( "", stack.last() );
- }
-
- if ( html == last ) {
- throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
- "of html: {0}", html);
- }
- last = html;
- }
-
- // Clean up any remaining tags
- parseEndTag();
-
- function parseStartTag( tag, tagName, rest, unary ) {
- tagName = angular.lowercase(tagName);
- if ( blockElements[ tagName ] ) {
- while ( stack.last() && inlineElements[ stack.last() ] ) {
- parseEndTag( "", stack.last() );
- }
- }
-
- if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
- parseEndTag( "", tagName );
- }
-
- unary = voidElements[ tagName ] || !!unary;
-
- if ( !unary )
- stack.push( tagName );
-
- var attrs = {};
-
- rest.replace(ATTR_REGEXP,
- function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
- var value = doubleQuotedValue
- || singleQuotedValue
- || unquotedValue
- || '';
-
- attrs[name] = decodeEntities(value);
- });
- if (handler.start) handler.start( tagName, attrs, unary );
- }
-
- function parseEndTag( tag, tagName ) {
- var pos = 0, i;
- tagName = angular.lowercase(tagName);
- if ( tagName )
- // Find the closest opened tag of the same type
- for ( pos = stack.length - 1; pos >= 0; pos-- )
- if ( stack[ pos ] == tagName )
- break;
-
- if ( pos >= 0 ) {
- // Close all the open elements, up the stack
- for ( i = stack.length - 1; i >= pos; i-- )
- if (handler.end) handler.end( stack[ i ] );
-
- // Remove the open elements from the stack
- stack.length = pos;
- }
- }
-}
-
-var hiddenPre=document.createElement("pre");
-var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
-/**
- * decodes all entities into regular string
- * @param value
- * @returns {string} A string with decoded entities.
- */
-function decodeEntities(value) {
- if (!value) { return ''; }
-
- // Note: IE8 does not preserve spaces at the start/end of innerHTML
- // so we must capture them and reattach them afterward
- var parts = spaceRe.exec(value);
- var spaceBefore = parts[1];
- var spaceAfter = parts[3];
- var content = parts[2];
- if (content) {
- hiddenPre.innerHTML=content.replace(/</g,"&lt;");
- // innerText depends on styling as it doesn't display hidden elements.
- // Therefore, it's better to use textContent not to cause unnecessary
- // reflows. However, IE<9 don't support textContent so the innerText
- // fallback is necessary.
- content = 'textContent' in hiddenPre ?
- hiddenPre.textContent : hiddenPre.innerText;
- }
- return spaceBefore + content + spaceAfter;
-}
-
-/**
- * Escapes all potentially dangerous characters, so that the
- * resulting string can be safely inserted into attribute or
- * element text.
- * @param value
- * @returns {string} escaped text
- */
-function encodeEntities(value) {
- return value.
- replace(/&/g, '&amp;').
- replace(SURROGATE_PAIR_REGEXP, function (value) {
- var hi = value.charCodeAt(0);
- var low = value.charCodeAt(1);
- return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
- }).
- replace(NON_ALPHANUMERIC_REGEXP, function(value){
- return '&#' + value.charCodeAt(0) + ';';
- }).
- replace(/</g, '&lt;').
- replace(/>/g, '&gt;');
-}
-
-/**
- * create an HTML/XML writer which writes to buffer
- * @param {Array} buf use buf.jain('') to get out sanitized html string
- * @returns {object} in the form of {
- * start: function(tag, attrs, unary) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * }
- */
-function htmlSanitizeWriter(buf, uriValidator){
- var ignore = false;
- var out = angular.bind(buf, buf.push);
- return {
- start: function(tag, attrs, unary){
- tag = angular.lowercase(tag);
- if (!ignore && specialElements[tag]) {
- ignore = tag;
- }
- if (!ignore && validElements[tag] === true) {
- out('<');
- out(tag);
- angular.forEach(attrs, function(value, key){
- var lkey=angular.lowercase(key);
- var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
- if (validAttrs[lkey] === true &&
- (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
- out(' ');
- out(key);
- out('="');
- out(encodeEntities(value));
- out('"');
- }
- });
- out(unary ? '/>' : '>');
- }
- },
- end: function(tag){
- tag = angular.lowercase(tag);
- if (!ignore && validElements[tag] === true) {
- out('</');
- out(tag);
- out('>');
- }
- if (tag == ignore) {
- ignore = false;
- }
- },
- chars: function(chars){
- if (!ignore) {
- out(encodeEntities(chars));
- }
- }
- };
-}
-
-
-// define ngSanitize module and register $sanitize service
-angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
-
-/* global sanitizeText: false */
-
-/**
- * @ngdoc filter
- * @name linky
- * @kind function
- *
- * @description
- * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
- * plain email address links.
- *
- * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
- *
- * @param {string} text Input text.
- * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
- * @returns {string} Html-linkified text.
- *
- * @usage
- <span ng-bind-html="linky_expression | linky"></span>
- *
- * @example
- <example module="linkyExample" deps="angular-sanitize.js">
- <file name="index.html">
- <script>
- angular.module('linkyExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.snippet =
- 'Pretty text with some links:\n'+
- 'http://angularjs.org/,\n'+
- 'mailto:us@somewhere.org,\n'+
- 'another@somewhere.org,\n'+
- 'and one more: ftp://127.0.0.1/.';
- $scope.snippetWithTarget = 'http://angularjs.org/';
- }]);
- </script>
- <div ng-controller="ExampleController">
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
- <table>
- <tr>
- <td>Filter</td>
- <td>Source</td>
- <td>Rendered</td>
- </tr>
- <tr id="linky-filter">
- <td>linky filter</td>
- <td>
- <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
- </td>
- <td>
- <div ng-bind-html="snippet | linky"></div>
- </td>
- </tr>
- <tr id="linky-target">
- <td>linky target</td>
- <td>
- <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
- </td>
- <td>
- <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
- </td>
- </tr>
- <tr id="escaped-html">
- <td>no filter</td>
- <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
- <td><div ng-bind="snippet"></div></td>
- </tr>
- </table>
- </file>
- <file name="protractor.js" type="protractor">
- it('should linkify the snippet with urls', function() {
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
- toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
- });
-
- it('should not linkify snippet without the linky filter', function() {
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
- toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
- expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
- });
-
- it('should update', function() {
- element(by.model('snippet')).clear();
- element(by.model('snippet')).sendKeys('new http://link.');
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
- toBe('new http://link.');
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
- .toBe('new http://link.');
- });
-
- it('should work with the target property', function() {
- expect(element(by.id('linky-target')).
- element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
- toBe('http://angularjs.org/');
- expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
- });
- </file>
- </example>
- */
-angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
- var LINKY_URL_REGEXP =
- /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"]/,
- MAILTO_REGEXP = /^mailto:/;
-
- return function(text, target) {
- if (!text) return text;
- var match;
- var raw = text;
- var html = [];
- var url;
- var i;
- while ((match = raw.match(LINKY_URL_REGEXP))) {
- // We can not end in these as they are sometimes found at the end of the sentence
- url = match[0];
- // if we did not match ftp/http/mailto then assume mailto
- if (match[2] == match[3]) url = 'mailto:' + url;
- i = match.index;
- addText(raw.substr(0, i));
- addLink(url, match[0].replace(MAILTO_REGEXP, ''));
- raw = raw.substring(i + match[0].length);
- }
- addText(raw);
- return $sanitize(html.join(''));
-
- function addText(text) {
- if (!text) {
- return;
- }
- html.push(sanitizeText(text));
- }
-
- function addLink(url, text) {
- html.push('<a ');
- if (angular.isDefined(target)) {
- html.push('target="');
- html.push(target);
- html.push('" ');
- }
- html.push('href="');
- html.push(url);
- html.push('">');
- addText(text);
- html.push('</a>');
- }
- };
-}]);
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-touch.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-touch.js
deleted file mode 100644
index fd416a35..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular-touch.js
+++ /dev/null
@@ -1,628 +0,0 @@
-/**
- * @license AngularJS v1.4.3
- * (c) 2010-2015 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngTouch
- * @description
- *
- * # ngTouch
- *
- * The `ngTouch` module provides touch events and other helpers for touch-enabled devices.
- * The implementation is based on jQuery Mobile touch event handling
- * ([jquerymobile.com](http://jquerymobile.com/)).
- *
- *
- * See {@link ngTouch.$swipe `$swipe`} for usage.
- *
- * <div doc-module-components="ngTouch"></div>
- *
- */
-
-// define ngTouch module
-/* global -ngTouch */
-var ngTouch = angular.module('ngTouch', []);
-
-function nodeName_(element) {
- return angular.lowercase(element.nodeName || (element[0] && element[0].nodeName));
-}
-
-/* global ngTouch: false */
-
- /**
- * @ngdoc service
- * @name $swipe
- *
- * @description
- * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe
- * behavior, to make implementing swipe-related directives more convenient.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by
- * `ngCarousel` in a separate component.
- *
- * # Usage
- * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
- * which is to be watched for swipes, and an object with four handler functions. See the
- * documentation for `bind` below.
- */
-
-ngTouch.factory('$swipe', [function() {
- // The total distance in any direction before we make the call on swipe vs. scroll.
- var MOVE_BUFFER_RADIUS = 10;
-
- var POINTER_EVENTS = {
- 'mouse': {
- start: 'mousedown',
- move: 'mousemove',
- end: 'mouseup'
- },
- 'touch': {
- start: 'touchstart',
- move: 'touchmove',
- end: 'touchend',
- cancel: 'touchcancel'
- }
- };
-
- function getCoordinates(event) {
- var originalEvent = event.originalEvent || event;
- var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
- var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];
-
- return {
- x: e.clientX,
- y: e.clientY
- };
- }
-
- function getEvents(pointerTypes, eventType) {
- var res = [];
- angular.forEach(pointerTypes, function(pointerType) {
- var eventName = POINTER_EVENTS[pointerType][eventType];
- if (eventName) {
- res.push(eventName);
- }
- });
- return res.join(' ');
- }
-
- return {
- /**
- * @ngdoc method
- * @name $swipe#bind
- *
- * @description
- * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
- * object containing event handlers.
- * The pointer types that should be used can be specified via the optional
- * third argument, which is an array of strings `'mouse'` and `'touch'`. By default,
- * `$swipe` will listen for `mouse` and `touch` events.
- *
- * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
- * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
- * `event`. `cancel` receives the raw `event` as its single parameter.
- *
- * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
- * watching for `touchmove` or `mousemove` events. These events are ignored until the total
- * distance moved in either dimension exceeds a small threshold.
- *
- * Once this threshold is exceeded, either the horizontal or vertical delta is greater.
- * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.
- * - If the vertical distance is greater, this is a scroll, and we let the browser take over.
- * A `cancel` event is sent.
- *
- * `move` is called on `mousemove` and `touchmove` after the above logic has determined that
- * a swipe is in progress.
- *
- * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.
- *
- * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling
- * as described above.
- *
- */
- bind: function(element, eventHandlers, pointerTypes) {
- // Absolute total movement, used to control swipe vs. scroll.
- var totalX, totalY;
- // Coordinates of the start position.
- var startCoords;
- // Last event's position.
- var lastPos;
- // Whether a swipe is active.
- var active = false;
-
- pointerTypes = pointerTypes || ['mouse', 'touch'];
- element.on(getEvents(pointerTypes, 'start'), function(event) {
- startCoords = getCoordinates(event);
- active = true;
- totalX = 0;
- totalY = 0;
- lastPos = startCoords;
- eventHandlers['start'] && eventHandlers['start'](startCoords, event);
- });
- var events = getEvents(pointerTypes, 'cancel');
- if (events) {
- element.on(events, function(event) {
- active = false;
- eventHandlers['cancel'] && eventHandlers['cancel'](event);
- });
- }
-
- element.on(getEvents(pointerTypes, 'move'), function(event) {
- if (!active) return;
-
- // Android will send a touchcancel if it thinks we're starting to scroll.
- // So when the total distance (+ or - or both) exceeds 10px in either direction,
- // we either:
- // - On totalX > totalY, we send preventDefault() and treat this as a swipe.
- // - On totalY > totalX, we let the browser handle it as a scroll.
-
- if (!startCoords) return;
- var coords = getCoordinates(event);
-
- totalX += Math.abs(coords.x - lastPos.x);
- totalY += Math.abs(coords.y - lastPos.y);
-
- lastPos = coords;
-
- if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
- return;
- }
-
- // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.
- if (totalY > totalX) {
- // Allow native scrolling to take over.
- active = false;
- eventHandlers['cancel'] && eventHandlers['cancel'](event);
- return;
- } else {
- // Prevent the browser from scrolling.
- event.preventDefault();
- eventHandlers['move'] && eventHandlers['move'](coords, event);
- }
- });
-
- element.on(getEvents(pointerTypes, 'end'), function(event) {
- if (!active) return;
- active = false;
- eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
- });
- }
- };
-}]);
-
-/* global ngTouch: false,
- nodeName_: false
-*/
-
-/**
- * @ngdoc directive
- * @name ngClick
- *
- * @description
- * A more powerful replacement for the default ngClick designed to be used on touchscreen
- * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
- * the click event. This version handles them immediately, and then prevents the
- * following click event from propagating.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * This directive can fall back to using an ordinary click event, and so works on desktop
- * browsers as well as mobile.
- *
- * This directive also sets the CSS class `ng-click-active` while the element is being held
- * down (by a mouse click or touch) so you can restyle the depressed element if you wish.
- *
- * @element ANY
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate
- * upon tap. (Event object is available as `$event`)
- *
- * @example
- <example module="ngClickExample" deps="angular-touch.js">
- <file name="index.html">
- <button ng-click="count = count + 1" ng-init="count=0">
- Increment
- </button>
- count: {{ count }}
- </file>
- <file name="script.js">
- angular.module('ngClickExample', ['ngTouch']);
- </file>
- </example>
- */
-
-ngTouch.config(['$provide', function($provide) {
- $provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
- // drop the default ngClick directive
- $delegate.shift();
- return $delegate;
- }]);
-}]);
-
-ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
- function($parse, $timeout, $rootElement) {
- var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
- var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
- var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
- var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.
-
- var ACTIVE_CLASS_NAME = 'ng-click-active';
- var lastPreventedTime;
- var touchCoordinates;
- var lastLabelClickCoordinates;
-
-
- // TAP EVENTS AND GHOST CLICKS
- //
- // Why tap events?
- // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
- // double-tapping, and then fire a click event.
- //
- // This delay sucks and makes mobile apps feel unresponsive.
- // So we detect touchstart, touchcancel and touchend ourselves and determine when
- // the user has tapped on something.
- //
- // What happens when the browser then generates a click event?
- // The browser, of course, also detects the tap and fires a click after a delay. This results in
- // tapping/clicking twice. We do "clickbusting" to prevent it.
- //
- // How does it work?
- // We attach global touchstart and click handlers, that run during the capture (early) phase.
- // So the sequence for a tap is:
- // - global touchstart: Sets an "allowable region" at the point touched.
- // - element's touchstart: Starts a touch
- // (- touchcancel ends the touch, no click follows)
- // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
- // too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
- // - preventGhostClick() removes the allowable region the global touchstart created.
- // - The browser generates a click event.
- // - The global click handler catches the click, and checks whether it was in an allowable region.
- // - If preventGhostClick was called, the region will have been removed, the click is busted.
- // - If the region is still there, the click proceeds normally. Therefore clicks on links and
- // other elements without ngTap on them work normally.
- //
- // This is an ugly, terrible hack!
- // Yeah, tell me about it. The alternatives are using the slow click events, or making our users
- // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
- // encapsulates this ugly logic away from the user.
- //
- // Why not just put click handlers on the element?
- // We do that too, just to be sure. If the tap event caused the DOM to change,
- // it is possible another element is now in that position. To take account for these possibly
- // distinct elements, the handlers are global and care only about coordinates.
-
- // Checks if the coordinates are close enough to be within the region.
- function hit(x1, y1, x2, y2) {
- return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
- }
-
- // Checks a list of allowable regions against a click location.
- // Returns true if the click should be allowed.
- // Splices out the allowable region from the list after it has been used.
- function checkAllowableRegions(touchCoordinates, x, y) {
- for (var i = 0; i < touchCoordinates.length; i += 2) {
- if (hit(touchCoordinates[i], touchCoordinates[i + 1], x, y)) {
- touchCoordinates.splice(i, i + 2);
- return true; // allowable region
- }
- }
- return false; // No allowable region; bust it.
- }
-
- // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
- // was called recently.
- function onClick(event) {
- if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
- return; // Too old.
- }
-
- var touches = event.touches && event.touches.length ? event.touches : [event];
- var x = touches[0].clientX;
- var y = touches[0].clientY;
- // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
- // and on the input element). Depending on the exact browser, this second click we don't want
- // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label
- // click event
- if (x < 1 && y < 1) {
- return; // offscreen
- }
- if (lastLabelClickCoordinates &&
- lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) {
- return; // input click triggered by label click
- }
- // reset label click coordinates on first subsequent click
- if (lastLabelClickCoordinates) {
- lastLabelClickCoordinates = null;
- }
- // remember label click coordinates to prevent click busting of trigger click event on input
- if (nodeName_(event.target) === 'label') {
- lastLabelClickCoordinates = [x, y];
- }
-
- // Look for an allowable region containing this click.
- // If we find one, that means it was created by touchstart and not removed by
- // preventGhostClick, so we don't bust it.
- if (checkAllowableRegions(touchCoordinates, x, y)) {
- return;
- }
-
- // If we didn't find an allowable region, bust the click.
- event.stopPropagation();
- event.preventDefault();
-
- // Blur focused form elements
- event.target && event.target.blur && event.target.blur();
- }
-
-
- // Global touchstart handler that creates an allowable region for a click event.
- // This allowable region can be removed by preventGhostClick if we want to bust it.
- function onTouchStart(event) {
- var touches = event.touches && event.touches.length ? event.touches : [event];
- var x = touches[0].clientX;
- var y = touches[0].clientY;
- touchCoordinates.push(x, y);
-
- $timeout(function() {
- // Remove the allowable region.
- for (var i = 0; i < touchCoordinates.length; i += 2) {
- if (touchCoordinates[i] == x && touchCoordinates[i + 1] == y) {
- touchCoordinates.splice(i, i + 2);
- return;
- }
- }
- }, PREVENT_DURATION, false);
- }
-
- // On the first call, attaches some event handlers. Then whenever it gets called, it creates a
- // zone around the touchstart where clicks will get busted.
- function preventGhostClick(x, y) {
- if (!touchCoordinates) {
- $rootElement[0].addEventListener('click', onClick, true);
- $rootElement[0].addEventListener('touchstart', onTouchStart, true);
- touchCoordinates = [];
- }
-
- lastPreventedTime = Date.now();
-
- checkAllowableRegions(touchCoordinates, x, y);
- }
-
- // Actual linking function.
- return function(scope, element, attr) {
- var clickHandler = $parse(attr.ngClick),
- tapping = false,
- tapElement, // Used to blur the element after a tap.
- startTime, // Used to check if the tap was held too long.
- touchStartX,
- touchStartY;
-
- function resetState() {
- tapping = false;
- element.removeClass(ACTIVE_CLASS_NAME);
- }
-
- element.on('touchstart', function(event) {
- tapping = true;
- tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
- // Hack for Safari, which can target text nodes instead of containers.
- if (tapElement.nodeType == 3) {
- tapElement = tapElement.parentNode;
- }
-
- element.addClass(ACTIVE_CLASS_NAME);
-
- startTime = Date.now();
-
- // Use jQuery originalEvent
- var originalEvent = event.originalEvent || event;
- var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
- var e = touches[0];
- touchStartX = e.clientX;
- touchStartY = e.clientY;
- });
-
- element.on('touchcancel', function(event) {
- resetState();
- });
-
- element.on('touchend', function(event) {
- var diff = Date.now() - startTime;
-
- // Use jQuery originalEvent
- var originalEvent = event.originalEvent || event;
- var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
- originalEvent.changedTouches :
- ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
- var e = touches[0];
- var x = e.clientX;
- var y = e.clientY;
- var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));
-
- if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
- // Call preventGhostClick so the clickbuster will catch the corresponding click.
- preventGhostClick(x, y);
-
- // Blur the focused element (the button, probably) before firing the callback.
- // This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
- // I couldn't get anything to work reliably on Android Chrome.
- if (tapElement) {
- tapElement.blur();
- }
-
- if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
- element.triggerHandler('click', [event]);
- }
- }
-
- resetState();
- });
-
- // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
- // something else nearby.
- element.onclick = function(event) { };
-
- // Actual click handler.
- // There are three different kinds of clicks, only two of which reach this point.
- // - On desktop browsers without touch events, their clicks will always come here.
- // - On mobile browsers, the simulated "fast" click will call this.
- // - But the browser's follow-up slow click will be "busted" before it reaches this handler.
- // Therefore it's safe to use this directive on both mobile and desktop.
- element.on('click', function(event, touchend) {
- scope.$apply(function() {
- clickHandler(scope, {$event: (touchend || event)});
- });
- });
-
- element.on('mousedown', function(event) {
- element.addClass(ACTIVE_CLASS_NAME);
- });
-
- element.on('mousemove mouseup', function(event) {
- element.removeClass(ACTIVE_CLASS_NAME);
- });
-
- };
-}]);
-
-/* global ngTouch: false */
-
-/**
- * @ngdoc directive
- * @name ngSwipeLeft
- *
- * @description
- * Specify custom behavior when an element is swiped to the left on a touchscreen device.
- * A leftward swipe is a quick, right-to-left slide of the finger.
- * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag
- * too.
- *
- * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to
- * the `ng-swipe-left` or `ng-swipe-right` DOM Element.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * @element ANY
- * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate
- * upon left swipe. (Event object is available as `$event`)
- *
- * @example
- <example module="ngSwipeLeftExample" deps="angular-touch.js">
- <file name="index.html">
- <div ng-show="!showActions" ng-swipe-left="showActions = true">
- Some list content, like an email in the inbox
- </div>
- <div ng-show="showActions" ng-swipe-right="showActions = false">
- <button ng-click="reply()">Reply</button>
- <button ng-click="delete()">Delete</button>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngSwipeLeftExample', ['ngTouch']);
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngSwipeRight
- *
- * @description
- * Specify custom behavior when an element is swiped to the right on a touchscreen device.
- * A rightward swipe is a quick, left-to-right slide of the finger.
- * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag
- * too.
- *
- * Requires the {@link ngTouch `ngTouch`} module to be installed.
- *
- * @element ANY
- * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate
- * upon right swipe. (Event object is available as `$event`)
- *
- * @example
- <example module="ngSwipeRightExample" deps="angular-touch.js">
- <file name="index.html">
- <div ng-show="!showActions" ng-swipe-left="showActions = true">
- Some list content, like an email in the inbox
- </div>
- <div ng-show="showActions" ng-swipe-right="showActions = false">
- <button ng-click="reply()">Reply</button>
- <button ng-click="delete()">Delete</button>
- </div>
- </file>
- <file name="script.js">
- angular.module('ngSwipeRightExample', ['ngTouch']);
- </file>
- </example>
- */
-
-function makeSwipeDirective(directiveName, direction, eventName) {
- ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {
- // The maximum vertical delta for a swipe should be less than 75px.
- var MAX_VERTICAL_DISTANCE = 75;
- // Vertical distance should not be more than a fraction of the horizontal distance.
- var MAX_VERTICAL_RATIO = 0.3;
- // At least a 30px lateral motion is necessary for a swipe.
- var MIN_HORIZONTAL_DISTANCE = 30;
-
- return function(scope, element, attr) {
- var swipeHandler = $parse(attr[directiveName]);
-
- var startCoords, valid;
-
- function validSwipe(coords) {
- // Check that it's within the coordinates.
- // Absolute vertical distance must be within tolerances.
- // Horizontal distance, we take the current X - the starting X.
- // This is negative for leftward swipes and positive for rightward swipes.
- // After multiplying by the direction (-1 for left, +1 for right), legal swipes
- // (ie. same direction as the directive wants) will have a positive delta and
- // illegal ones a negative delta.
- // Therefore this delta must be positive, and larger than the minimum.
- if (!startCoords) return false;
- var deltaY = Math.abs(coords.y - startCoords.y);
- var deltaX = (coords.x - startCoords.x) * direction;
- return valid && // Short circuit for already-invalidated swipes.
- deltaY < MAX_VERTICAL_DISTANCE &&
- deltaX > 0 &&
- deltaX > MIN_HORIZONTAL_DISTANCE &&
- deltaY / deltaX < MAX_VERTICAL_RATIO;
- }
-
- var pointerTypes = ['touch'];
- if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
- pointerTypes.push('mouse');
- }
- $swipe.bind(element, {
- 'start': function(coords, event) {
- startCoords = coords;
- valid = true;
- },
- 'cancel': function(event) {
- valid = false;
- },
- 'end': function(coords, event) {
- if (validSwipe(coords)) {
- scope.$apply(function() {
- element.triggerHandler(eventName);
- swipeHandler(scope, {$event: event});
- });
- }
- }
- }, pointerTypes);
- };
- }]);
-}
-
-// Left is negative X-coordinate, right is positive.
-makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');
-makeSwipeDirective('ngSwipeRight', 1, 'swiperight');
-
-
-
-})(window, window.angular);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular.js
deleted file mode 100644
index 132234b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/angular.js
+++ /dev/null
@@ -1,22024 +0,0 @@
-/**
- * @license AngularJS v1.2.25
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, document, undefined) {'use strict';
-
-/**
- * @description
- *
- * This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
- *
- * var exampleMinErr = minErr('example');
- * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
- *
- * The above creates an instance of minErr in the example namespace. The
- * resulting error will have a namespaced error code of example.one. The
- * resulting error will replace {0} with the value of foo, and {1} with the
- * value of bar. The object is not restricted in the number of arguments it can
- * take.
- *
- * If fewer arguments are specified than necessary for interpolation, the extra
- * interpolation markers will be preserved in the final string.
- *
- * Since data will be parsed statically during a build step, some restrictions
- * are applied with respect to how minErr instances are created and called.
- * Instances should have names of the form namespaceMinErr for a minErr created
- * using minErr('namespace') . Error codes, namespaces and template strings
- * should all be static strings, not variables or general expressions.
- *
- * @param {string} module The namespace to use for the new minErr instance.
- * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
- */
-
-function minErr(module) {
- return function () {
- var code = arguments[0],
- prefix = '[' + (module ? module + ':' : '') + code + '] ',
- template = arguments[1],
- templateArgs = arguments,
- stringify = function (obj) {
- if (typeof obj === 'function') {
- return obj.toString().replace(/ \{[\s\S]*$/, '');
- } else if (typeof obj === 'undefined') {
- return 'undefined';
- } else if (typeof obj !== 'string') {
- return JSON.stringify(obj);
- }
- return obj;
- },
- message, i;
-
- message = prefix + template.replace(/\{\d+\}/g, function (match) {
- var index = +match.slice(1, -1), arg;
-
- if (index + 2 < templateArgs.length) {
- arg = templateArgs[index + 2];
- if (typeof arg === 'function') {
- return arg.toString().replace(/ ?\{[\s\S]*$/, '');
- } else if (typeof arg === 'undefined') {
- return 'undefined';
- } else if (typeof arg !== 'string') {
- return toJson(arg);
- }
- return arg;
- }
- return match;
- });
-
- message = message + '\nhttp://errors.angularjs.org/1.2.25/' +
- (module ? module + '/' : '') + code;
- for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
- encodeURIComponent(stringify(arguments[i]));
- }
-
- return new Error(message);
- };
-}
-
-/* We need to tell jshint what variables are being exported */
-/* global angular: true,
- msie: true,
- jqLite: true,
- jQuery: true,
- slice: true,
- push: true,
- toString: true,
- ngMinErr: true,
- angularModule: true,
- nodeName_: true,
- uid: true,
- VALIDITY_STATE_PROPERTY: true,
-
- lowercase: true,
- uppercase: true,
- manualLowercase: true,
- manualUppercase: true,
- nodeName_: true,
- isArrayLike: true,
- forEach: true,
- sortedKeys: true,
- forEachSorted: true,
- reverseParams: true,
- nextUid: true,
- setHashKey: true,
- extend: true,
- int: true,
- inherit: true,
- noop: true,
- identity: true,
- valueFn: true,
- isUndefined: true,
- isDefined: true,
- isObject: true,
- isString: true,
- isNumber: true,
- isDate: true,
- isArray: true,
- isFunction: true,
- isRegExp: true,
- isWindow: true,
- isScope: true,
- isFile: true,
- isBlob: true,
- isBoolean: true,
- isPromiseLike: true,
- trim: true,
- isElement: true,
- makeMap: true,
- map: true,
- size: true,
- includes: true,
- indexOf: true,
- arrayRemove: true,
- isLeafNode: true,
- copy: true,
- shallowCopy: true,
- equals: true,
- csp: true,
- concat: true,
- sliceArgs: true,
- bind: true,
- toJsonReplacer: true,
- toJson: true,
- fromJson: true,
- toBoolean: true,
- startingTag: true,
- tryDecodeURIComponent: true,
- parseKeyValue: true,
- toKeyValue: true,
- encodeUriSegment: true,
- encodeUriQuery: true,
- angularInit: true,
- bootstrap: true,
- snake_case: true,
- bindJQuery: true,
- assertArg: true,
- assertArgFn: true,
- assertNotHasOwnProperty: true,
- getter: true,
- getBlockElements: true,
- hasOwnProperty: true,
-*/
-
-////////////////////////////////////
-
-/**
- * @ngdoc module
- * @name ng
- * @module ng
- * @description
- *
- * # ng (core module)
- * The ng module is loaded by default when an AngularJS application is started. The module itself
- * contains the essential components for an AngularJS application to function. The table below
- * lists a high level breakdown of each of the services/factories, filters, directives and testing
- * components available within this core module.
- *
- * <div doc-module-components="ng"></div>
- */
-
-// The name of a form control's ValidityState property.
-// This is used so that it's possible for internal tests to create mock ValidityStates.
-var VALIDITY_STATE_PROPERTY = 'validity';
-
-/**
- * @ngdoc function
- * @name angular.lowercase
- * @module ng
- * @kind function
- *
- * @description Converts the specified string to lowercase.
- * @param {string} string String to be converted to lowercase.
- * @returns {string} Lowercased string.
- */
-var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-/**
- * @ngdoc function
- * @name angular.uppercase
- * @module ng
- * @kind function
- *
- * @description Converts the specified string to uppercase.
- * @param {string} string String to be converted to uppercase.
- * @returns {string} Uppercased string.
- */
-var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
-
-
-var manualLowercase = function(s) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
- : s;
-};
-var manualUppercase = function(s) {
- /* jshint bitwise: false */
- return isString(s)
- ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
- : s;
-};
-
-
-// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
-// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
-// with correct but slower alternatives.
-if ('i' !== 'I'.toLowerCase()) {
- lowercase = manualLowercase;
- uppercase = manualUppercase;
-}
-
-
-var /** holds major version number for IE or NaN for real browsers */
- msie,
- jqLite, // delay binding since jQuery could be loaded after us.
- jQuery, // delay binding
- slice = [].slice,
- push = [].push,
- toString = Object.prototype.toString,
- ngMinErr = minErr('ng'),
-
- /** @name angular */
- angular = window.angular || (window.angular = {}),
- angularModule,
- nodeName_,
- uid = ['0', '0', '0'];
-
-/**
- * IE 11 changed the format of the UserAgent string.
- * See http://msdn.microsoft.com/en-us/library/ms537503.aspx
- */
-msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
-if (isNaN(msie)) {
- msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
-}
-
-
-/**
- * @private
- * @param {*} obj
- * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
- * String ...)
- */
-function isArrayLike(obj) {
- if (obj == null || isWindow(obj)) {
- return false;
- }
-
- var length = obj.length;
-
- if (obj.nodeType === 1 && length) {
- return true;
- }
-
- return isString(obj) || isArray(obj) || length === 0 ||
- typeof length === 'number' && length > 0 && (length - 1) in obj;
-}
-
-/**
- * @ngdoc function
- * @name angular.forEach
- * @module ng
- * @kind function
- *
- * @description
- * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
- * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
- * is the value of an object property or an array element and `key` is the object property key or
- * array element index. Specifying a `context` for the function is optional.
- *
- * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
- * using the `hasOwnProperty` method.
- *
- ```js
- var values = {name: 'misko', gender: 'male'};
- var log = [];
- angular.forEach(values, function(value, key) {
- this.push(key + ': ' + value);
- }, log);
- expect(log).toEqual(['name: misko', 'gender: male']);
- ```
- *
- * @param {Object|Array} obj Object to iterate over.
- * @param {Function} iterator Iterator function.
- * @param {Object=} context Object to become context (`this`) for the iterator function.
- * @returns {Object|Array} Reference to `obj`.
- */
-function forEach(obj, iterator, context) {
- var key;
- if (obj) {
- if (isFunction(obj)) {
- for (key in obj) {
- // Need to check if hasOwnProperty exists,
- // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
- if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
- iterator.call(context, obj[key], key);
- }
- }
- } else if (isArray(obj) || isArrayLike(obj)) {
- for (key = 0; key < obj.length; key++) {
- iterator.call(context, obj[key], key);
- }
- } else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context);
- } else {
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key);
- }
- }
- }
- }
- return obj;
-}
-
-function sortedKeys(obj) {
- var keys = [];
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- keys.push(key);
- }
- }
- return keys.sort();
-}
-
-function forEachSorted(obj, iterator, context) {
- var keys = sortedKeys(obj);
- for ( var i = 0; i < keys.length; i++) {
- iterator.call(context, obj[keys[i]], keys[i]);
- }
- return keys;
-}
-
-
-/**
- * when using forEach the params are value, key, but it is often useful to have key, value.
- * @param {function(string, *)} iteratorFn
- * @returns {function(*, string)}
- */
-function reverseParams(iteratorFn) {
- return function(value, key) { iteratorFn(key, value); };
-}
-
-/**
- * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
- * characters such as '012ABC'. The reason why we are not using simply a number counter is that
- * the number string gets longer over time, and it can also overflow, where as the nextId
- * will grow much slower, it is a string, and it will never overflow.
- *
- * @returns {string} an unique alpha-numeric string
- */
-function nextUid() {
- var index = uid.length;
- var digit;
-
- while(index) {
- index--;
- digit = uid[index].charCodeAt(0);
- if (digit == 57 /*'9'*/) {
- uid[index] = 'A';
- return uid.join('');
- }
- if (digit == 90 /*'Z'*/) {
- uid[index] = '0';
- } else {
- uid[index] = String.fromCharCode(digit + 1);
- return uid.join('');
- }
- }
- uid.unshift('0');
- return uid.join('');
-}
-
-
-/**
- * Set or clear the hashkey for an object.
- * @param obj object
- * @param h the hashkey (!truthy to delete the hashkey)
- */
-function setHashKey(obj, h) {
- if (h) {
- obj.$$hashKey = h;
- }
- else {
- delete obj.$$hashKey;
- }
-}
-
-/**
- * @ngdoc function
- * @name angular.extend
- * @module ng
- * @kind function
- *
- * @description
- * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
- * to `dst`. You can specify multiple `src` objects.
- *
- * @param {Object} dst Destination object.
- * @param {...Object} src Source object(s).
- * @returns {Object} Reference to `dst`.
- */
-function extend(dst) {
- var h = dst.$$hashKey;
- forEach(arguments, function(obj) {
- if (obj !== dst) {
- forEach(obj, function(value, key) {
- dst[key] = value;
- });
- }
- });
-
- setHashKey(dst,h);
- return dst;
-}
-
-function int(str) {
- return parseInt(str, 10);
-}
-
-
-function inherit(parent, extra) {
- return extend(new (extend(function() {}, {prototype:parent}))(), extra);
-}
-
-/**
- * @ngdoc function
- * @name angular.noop
- * @module ng
- * @kind function
- *
- * @description
- * A function that performs no operations. This function can be useful when writing code in the
- * functional style.
- ```js
- function foo(callback) {
- var result = calculateResult();
- (callback || angular.noop)(result);
- }
- ```
- */
-function noop() {}
-noop.$inject = [];
-
-
-/**
- * @ngdoc function
- * @name angular.identity
- * @module ng
- * @kind function
- *
- * @description
- * A function that returns its first argument. This function is useful when writing code in the
- * functional style.
- *
- ```js
- function transformer(transformationFn, value) {
- return (transformationFn || angular.identity)(value);
- };
- ```
- */
-function identity($) {return $;}
-identity.$inject = [];
-
-
-function valueFn(value) {return function() {return value;};}
-
-/**
- * @ngdoc function
- * @name angular.isUndefined
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is undefined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is undefined.
- */
-function isUndefined(value){return typeof value === 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDefined
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is defined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is defined.
- */
-function isDefined(value){return typeof value !== 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isObject
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
- * considered to be objects. Note that JavaScript arrays are objects.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Object` but not `null`.
- */
-function isObject(value){return value != null && typeof value === 'object';}
-
-
-/**
- * @ngdoc function
- * @name angular.isString
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `String`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `String`.
- */
-function isString(value){return typeof value === 'string';}
-
-
-/**
- * @ngdoc function
- * @name angular.isNumber
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `Number`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Number`.
- */
-function isNumber(value){return typeof value === 'number';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDate
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a value is a date.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Date`.
- */
-function isDate(value) {
- return toString.call(value) === '[object Date]';
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isArray
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is an `Array`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Array`.
- */
-var isArray = (function() {
- if (!isFunction(Array.isArray)) {
- return function(value) {
- return toString.call(value) === '[object Array]';
- };
- }
- return Array.isArray;
-})();
-
-/**
- * @ngdoc function
- * @name angular.isFunction
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a `Function`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Function`.
- */
-function isFunction(value){return typeof value === 'function';}
-
-
-/**
- * Determines if a value is a regular expression object.
- *
- * @private
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `RegExp`.
- */
-function isRegExp(value) {
- return toString.call(value) === '[object RegExp]';
-}
-
-
-/**
- * Checks if `obj` is a window object.
- *
- * @private
- * @param {*} obj Object to check
- * @returns {boolean} True if `obj` is a window obj.
- */
-function isWindow(obj) {
- return obj && obj.document && obj.location && obj.alert && obj.setInterval;
-}
-
-
-function isScope(obj) {
- return obj && obj.$evalAsync && obj.$watch;
-}
-
-
-function isFile(obj) {
- return toString.call(obj) === '[object File]';
-}
-
-
-function isBlob(obj) {
- return toString.call(obj) === '[object Blob]';
-}
-
-
-function isBoolean(value) {
- return typeof value === 'boolean';
-}
-
-
-function isPromiseLike(obj) {
- return obj && isFunction(obj.then);
-}
-
-
-var trim = (function() {
- // native trim is way faster: http://jsperf.com/angular-trim-test
- // but IE doesn't have it... :-(
- // TODO: we should move this into IE/ES5 polyfill
- if (!String.prototype.trim) {
- return function(value) {
- return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
- };
- }
- return function(value) {
- return isString(value) ? value.trim() : value;
- };
-})();
-
-
-/**
- * @ngdoc function
- * @name angular.isElement
- * @module ng
- * @kind function
- *
- * @description
- * Determines if a reference is a DOM element (or wrapped jQuery element).
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
- */
-function isElement(node) {
- return !!(node &&
- (node.nodeName // we are a direct element
- || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
-}
-
-/**
- * @param str 'key1,key2,...'
- * @returns {object} in the form of {key1:true, key2:true, ...}
- */
-function makeMap(str) {
- var obj = {}, items = str.split(","), i;
- for ( i = 0; i < items.length; i++ )
- obj[ items[i] ] = true;
- return obj;
-}
-
-
-if (msie < 9) {
- nodeName_ = function(element) {
- element = element.nodeName ? element : element[0];
- return (element.scopeName && element.scopeName != 'HTML')
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
- };
-} else {
- nodeName_ = function(element) {
- return element.nodeName ? element.nodeName : element[0].nodeName;
- };
-}
-
-
-function map(obj, iterator, context) {
- var results = [];
- forEach(obj, function(value, index, list) {
- results.push(iterator.call(context, value, index, list));
- });
- return results;
-}
-
-
-/**
- * @description
- * Determines the number of elements in an array, the number of properties an object has, or
- * the length of a string.
- *
- * Note: This function is used to augment the Object type in Angular expressions. See
- * {@link angular.Object} for more information about Angular arrays.
- *
- * @param {Object|Array|string} obj Object, array, or string to inspect.
- * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
- * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
- */
-function size(obj, ownPropsOnly) {
- var count = 0, key;
-
- if (isArray(obj) || isString(obj)) {
- return obj.length;
- } else if (isObject(obj)) {
- for (key in obj)
- if (!ownPropsOnly || obj.hasOwnProperty(key))
- count++;
- }
-
- return count;
-}
-
-
-function includes(array, obj) {
- return indexOf(array, obj) != -1;
-}
-
-function indexOf(array, obj) {
- if (array.indexOf) return array.indexOf(obj);
-
- for (var i = 0; i < array.length; i++) {
- if (obj === array[i]) return i;
- }
- return -1;
-}
-
-function arrayRemove(array, value) {
- var index = indexOf(array, value);
- if (index >=0)
- array.splice(index, 1);
- return value;
-}
-
-function isLeafNode (node) {
- if (node) {
- switch (node.nodeName) {
- case "OPTION":
- case "PRE":
- case "TITLE":
- return true;
- }
- }
- return false;
-}
-
-/**
- * @ngdoc function
- * @name angular.copy
- * @module ng
- * @kind function
- *
- * @description
- * Creates a deep copy of `source`, which should be an object or an array.
- *
- * * If no destination is supplied, a copy of the object or array is created.
- * * If a destination is provided, all of its elements (for array) or properties (for objects)
- * are deleted and then all elements/properties from the source are copied to it.
- * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
- * * If `source` is identical to 'destination' an exception will be thrown.
- *
- * @param {*} source The source that will be used to make a copy.
- * Can be any type, including primitives, `null`, and `undefined`.
- * @param {(Object|Array)=} destination Destination into which the source is copied. If
- * provided, must be of the same type as `source`.
- * @returns {*} The copy or updated `destination`, if `destination` was specified.
- *
- * @example
- <example module="copyExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <form novalidate class="simple-form">
- Name: <input type="text" ng-model="user.name" /><br />
- E-mail: <input type="email" ng-model="user.email" /><br />
- Gender: <input type="radio" ng-model="user.gender" value="male" />male
- <input type="radio" ng-model="user.gender" value="female" />female<br />
- <button ng-click="reset()">RESET</button>
- <button ng-click="update(user)">SAVE</button>
- </form>
- <pre>form = {{user | json}}</pre>
- <pre>master = {{master | json}}</pre>
- </div>
-
- <script>
- angular.module('copyExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.master= {};
-
- $scope.update = function(user) {
- // Example with 1 argument
- $scope.master= angular.copy(user);
- };
-
- $scope.reset = function() {
- // Example with 2 arguments
- angular.copy($scope.master, $scope.user);
- };
-
- $scope.reset();
- }]);
- </script>
- </file>
- </example>
- */
-function copy(source, destination, stackSource, stackDest) {
- if (isWindow(source) || isScope(source)) {
- throw ngMinErr('cpws',
- "Can't copy! Making copies of Window or Scope instances is not supported.");
- }
-
- if (!destination) {
- destination = source;
- if (source) {
- if (isArray(source)) {
- destination = copy(source, [], stackSource, stackDest);
- } else if (isDate(source)) {
- destination = new Date(source.getTime());
- } else if (isRegExp(source)) {
- destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
- destination.lastIndex = source.lastIndex;
- } else if (isObject(source)) {
- destination = copy(source, {}, stackSource, stackDest);
- }
- }
- } else {
- if (source === destination) throw ngMinErr('cpi',
- "Can't copy! Source and destination are identical.");
-
- stackSource = stackSource || [];
- stackDest = stackDest || [];
-
- if (isObject(source)) {
- var index = indexOf(stackSource, source);
- if (index !== -1) return stackDest[index];
-
- stackSource.push(source);
- stackDest.push(destination);
- }
-
- var result;
- if (isArray(source)) {
- destination.length = 0;
- for ( var i = 0; i < source.length; i++) {
- result = copy(source[i], null, stackSource, stackDest);
- if (isObject(source[i])) {
- stackSource.push(source[i]);
- stackDest.push(result);
- }
- destination.push(result);
- }
- } else {
- var h = destination.$$hashKey;
- if (isArray(destination)) {
- destination.length = 0;
- } else {
- forEach(destination, function(value, key) {
- delete destination[key];
- });
- }
- for ( var key in source) {
- result = copy(source[key], null, stackSource, stackDest);
- if (isObject(source[key])) {
- stackSource.push(source[key]);
- stackDest.push(result);
- }
- destination[key] = result;
- }
- setHashKey(destination,h);
- }
-
- }
- return destination;
-}
-
-/**
- * Creates a shallow copy of an object, an array or a primitive
- */
-function shallowCopy(src, dst) {
- if (isArray(src)) {
- dst = dst || [];
-
- for ( var i = 0; i < src.length; i++) {
- dst[i] = src[i];
- }
- } else if (isObject(src)) {
- dst = dst || {};
-
- for (var key in src) {
- if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
- dst[key] = src[key];
- }
- }
- }
-
- return dst || src;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.equals
- * @module ng
- * @kind function
- *
- * @description
- * Determines if two objects or two values are equivalent. Supports value types, regular
- * expressions, arrays and objects.
- *
- * Two objects or values are considered equivalent if at least one of the following is true:
- *
- * * Both objects or values pass `===` comparison.
- * * Both objects or values are of the same type and all of their properties are equal by
- * comparing them with `angular.equals`.
- * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- * * Both values represent the same regular expression (In JavaScript,
- * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
- * representation matches).
- *
- * During a property comparison, properties of `function` type and properties with names
- * that begin with `$` are ignored.
- *
- * Scope and DOMWindow objects are being compared only by identify (`===`).
- *
- * @param {*} o1 Object or value to compare.
- * @param {*} o2 Object or value to compare.
- * @returns {boolean} True if arguments are equal.
- */
-function equals(o1, o2) {
- if (o1 === o2) return true;
- if (o1 === null || o2 === null) return false;
- if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
- var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2) {
- if (t1 == 'object') {
- if (isArray(o1)) {
- if (!isArray(o2)) return false;
- if ((length = o1.length) == o2.length) {
- for(key=0; key<length; key++) {
- if (!equals(o1[key], o2[key])) return false;
- }
- return true;
- }
- } else if (isDate(o1)) {
- if (!isDate(o2)) return false;
- return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());
- } else if (isRegExp(o1) && isRegExp(o2)) {
- return o1.toString() == o2.toString();
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
- keySet = {};
- for(key in o1) {
- if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
- if (!equals(o1[key], o2[key])) return false;
- keySet[key] = true;
- }
- for(key in o2) {
- if (!keySet.hasOwnProperty(key) &&
- key.charAt(0) !== '$' &&
- o2[key] !== undefined &&
- !isFunction(o2[key])) return false;
- }
- return true;
- }
- }
- }
- return false;
-}
-
-var csp = function() {
- if (isDefined(csp.isActive_)) return csp.isActive_;
-
- var active = !!(document.querySelector('[ng-csp]') ||
- document.querySelector('[data-ng-csp]'));
-
- if (!active) {
- try {
- /* jshint -W031, -W054 */
- new Function('');
- /* jshint +W031, +W054 */
- } catch (e) {
- active = true;
- }
- }
-
- return (csp.isActive_ = active);
-};
-
-
-
-function concat(array1, array2, index) {
- return array1.concat(slice.call(array2, index));
-}
-
-function sliceArgs(args, startIndex) {
- return slice.call(args, startIndex || 0);
-}
-
-
-/* jshint -W101 */
-/**
- * @ngdoc function
- * @name angular.bind
- * @module ng
- * @kind function
- *
- * @description
- * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
- * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
- * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
- *
- * @param {Object} self Context which `fn` should be evaluated in.
- * @param {function()} fn Function to be bound.
- * @param {...*} args Optional arguments to be prebound to the `fn` function call.
- * @returns {function()} Function that wraps the `fn` with all the specified bindings.
- */
-/* jshint +W101 */
-function bind(self, fn) {
- var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
- if (isFunction(fn) && !(fn instanceof RegExp)) {
- return curryArgs.length
- ? function() {
- return arguments.length
- ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
- : fn.apply(self, curryArgs);
- }
- : function() {
- return arguments.length
- ? fn.apply(self, arguments)
- : fn.call(self);
- };
- } else {
- // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
- return fn;
- }
-}
-
-
-function toJsonReplacer(key, value) {
- var val = value;
-
- if (typeof key === 'string' && key.charAt(0) === '$') {
- val = undefined;
- } else if (isWindow(value)) {
- val = '$WINDOW';
- } else if (value && document === value) {
- val = '$DOCUMENT';
- } else if (isScope(value)) {
- val = '$SCOPE';
- }
-
- return val;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.toJson
- * @module ng
- * @kind function
- *
- * @description
- * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
- * stripped since angular uses this notation internally.
- *
- * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
- * @returns {string|undefined} JSON-ified string representing `obj`.
- */
-function toJson(obj, pretty) {
- if (typeof obj === 'undefined') return undefined;
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
-}
-
-
-/**
- * @ngdoc function
- * @name angular.fromJson
- * @module ng
- * @kind function
- *
- * @description
- * Deserializes a JSON string.
- *
- * @param {string} json JSON string to deserialize.
- * @returns {Object|Array|string|number} Deserialized thingy.
- */
-function fromJson(json) {
- return isString(json)
- ? JSON.parse(json)
- : json;
-}
-
-
-function toBoolean(value) {
- if (typeof value === 'function') {
- value = true;
- } else if (value && value.length !== 0) {
- var v = lowercase("" + value);
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
- } else {
- value = false;
- }
- return value;
-}
-
-/**
- * @returns {string} Returns the string representation of the element.
- */
-function startingTag(element) {
- element = jqLite(element).clone();
- try {
- // turns out IE does not let you set .html() on elements which
- // are not allowed to have children. So we just ignore it.
- element.empty();
- } catch(e) {}
- // As Per DOM Standards
- var TEXT_NODE = 3;
- var elemHtml = jqLite('<div>').append(element).html();
- try {
- return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
- elemHtml.
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
- } catch(e) {
- return lowercase(elemHtml);
- }
-
-}
-
-
-/////////////////////////////////////////////////
-
-/**
- * Tries to decode the URI component without throwing an exception.
- *
- * @private
- * @param str value potential URI component to check.
- * @returns {boolean} True if `value` can be decoded
- * with the decodeURIComponent function.
- */
-function tryDecodeURIComponent(value) {
- try {
- return decodeURIComponent(value);
- } catch(e) {
- // Ignore any invalid uri component
- }
-}
-
-
-/**
- * Parses an escaped url query string into key-value pairs.
- * @returns {Object.<string,boolean|Array>}
- */
-function parseKeyValue(/**string*/keyValue) {
- var obj = {}, key_value, key;
- forEach((keyValue || "").split('&'), function(keyValue) {
- if ( keyValue ) {
- key_value = keyValue.replace(/\+/g,'%20').split('=');
- key = tryDecodeURIComponent(key_value[0]);
- if ( isDefined(key) ) {
- var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!hasOwnProperty.call(obj, key)) {
- obj[key] = val;
- } else if(isArray(obj[key])) {
- obj[key].push(val);
- } else {
- obj[key] = [obj[key],val];
- }
- }
- }
- });
- return obj;
-}
-
-function toKeyValue(obj) {
- var parts = [];
- forEach(obj, function(value, key) {
- if (isArray(value)) {
- forEach(value, function(arrayValue) {
- parts.push(encodeUriQuery(key, true) +
- (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
- });
- } else {
- parts.push(encodeUriQuery(key, true) +
- (value === true ? '' : '=' + encodeUriQuery(value, true)));
- }
- });
- return parts.length ? parts.join('&') : '';
-}
-
-
-/**
- * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
- * segments:
- * segment = *pchar
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * pct-encoded = "%" HEXDIG HEXDIG
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
-function encodeUriSegment(val) {
- return encodeUriQuery(val, true).
- replace(/%26/gi, '&').
- replace(/%3D/gi, '=').
- replace(/%2B/gi, '+');
-}
-
-
-/**
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
- * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
- * encoded per http://tools.ietf.org/html/rfc3986:
- * query = *( pchar / "/" / "?" )
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * pct-encoded = "%" HEXDIG HEXDIG
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- * / "*" / "+" / "," / ";" / "="
- */
-function encodeUriQuery(val, pctEncodeSpaces) {
- return encodeURIComponent(val).
- replace(/%40/gi, '@').
- replace(/%3A/gi, ':').
- replace(/%24/g, '$').
- replace(/%2C/gi, ',').
- replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
-}
-
-
-/**
- * @ngdoc directive
- * @name ngApp
- * @module ng
- *
- * @element ANY
- * @param {angular.Module} ngApp an optional application
- * {@link angular.module module} name to load.
- *
- * @description
- *
- * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
- * designates the **root element** of the application and is typically placed near the root element
- * of the page - e.g. on the `<body>` or `<html>` tags.
- *
- * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
- * found in the document will be used to define the root element to auto-bootstrap as an
- * application. To run multiple applications in an HTML document you must manually bootstrap them using
- * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
- *
- * You can specify an **AngularJS module** to be used as the root module for the application. This
- * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
- * should contain the application code needed or have dependencies on other modules that will
- * contain the code. See {@link angular.module} for more information.
- *
- * In the example below if the `ngApp` directive were not placed on the `html` element then the
- * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
- * would not be resolved to `3`.
- *
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
- *
- <example module="ngAppDemo">
- <file name="index.html">
- <div ng-controller="ngAppDemoController">
- I can add: {{a}} + {{b}} = {{ a+b }}
- </div>
- </file>
- <file name="script.js">
- angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
- $scope.a = 1;
- $scope.b = 2;
- });
- </file>
- </example>
- *
- */
-function angularInit(element, bootstrap) {
- var elements = [element],
- appElement,
- module,
- names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
- NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
-
- function append(element) {
- element && elements.push(element);
- }
-
- forEach(names, function(name) {
- names[name] = true;
- append(document.getElementById(name));
- name = name.replace(':', '\\:');
- if (element.querySelectorAll) {
- forEach(element.querySelectorAll('.' + name), append);
- forEach(element.querySelectorAll('.' + name + '\\:'), append);
- forEach(element.querySelectorAll('[' + name + ']'), append);
- }
- });
-
- forEach(elements, function(element) {
- if (!appElement) {
- var className = ' ' + element.className + ' ';
- var match = NG_APP_CLASS_REGEXP.exec(className);
- if (match) {
- appElement = element;
- module = (match[2] || '').replace(/\s+/g, ',');
- } else {
- forEach(element.attributes, function(attr) {
- if (!appElement && names[attr.name]) {
- appElement = element;
- module = attr.value;
- }
- });
- }
- }
- });
- if (appElement) {
- bootstrap(appElement, module ? [module] : []);
- }
-}
-
-/**
- * @ngdoc function
- * @name angular.bootstrap
- * @module ng
- * @description
- * Use this function to manually start up angular application.
- *
- * See: {@link guide/bootstrap Bootstrap}
- *
- * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
- * They must use {@link ng.directive:ngApp ngApp}.
- *
- * Angular will detect if it has been loaded into the browser more than once and only allow the
- * first loaded script to be bootstrapped and will report a warning to the browser console for
- * each of the subsequent scripts. This prevents strange results in applications, where otherwise
- * multiple instances of Angular try to work on the DOM.
- *
- * <example name="multi-bootstrap" module="multi-bootstrap">
- * <file name="index.html">
- * <script src="../../../angular.js"></script>
- * <div ng-controller="BrokenTable">
- * <table>
- * <tr>
- * <th ng-repeat="heading in headings">{{heading}}</th>
- * </tr>
- * <tr ng-repeat="filling in fillings">
- * <td ng-repeat="fill in filling">{{fill}}</td>
- * </tr>
- * </table>
- * </div>
- * </file>
- * <file name="controller.js">
- * var app = angular.module('multi-bootstrap', [])
- *
- * .controller('BrokenTable', function($scope) {
- * $scope.headings = ['One', 'Two', 'Three'];
- * $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];
- * });
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should only insert one table cell for each item in $scope.fillings', function() {
- * expect(element.all(by.css('td')).count())
- * .toBe(9);
- * });
- * </file>
- * </example>
- *
- * @param {DOMElement} element DOM element which is the root of angular application.
- * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
- * Each item in the array should be the name of a predefined module or a (DI annotated)
- * function that will be invoked by the injector as a run block.
- * See: {@link angular.module modules}
- * @returns {auto.$injector} Returns the newly created injector for this app.
- */
-function bootstrap(element, modules) {
- var doBootstrap = function() {
- element = jqLite(element);
-
- if (element.injector()) {
- var tag = (element[0] === document) ? 'document' : startingTag(element);
- //Encode angle brackets to prevent input from being sanitized to empty string #8683
- throw ngMinErr(
- 'btstrpd',
- "App Already Bootstrapped with this Element '{0}'",
- tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
- }
-
- modules = modules || [];
- modules.unshift(['$provide', function($provide) {
- $provide.value('$rootElement', element);
- }]);
- modules.unshift('ng');
- var injector = createInjector(modules);
- injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
- function(scope, element, compile, injector, animate) {
- scope.$apply(function() {
- element.data('$injector', injector);
- compile(element)(scope);
- });
- }]
- );
- return injector;
- };
-
- var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
-
- if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
- return doBootstrap();
- }
-
- window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
- angular.resumeBootstrap = function(extraModules) {
- forEach(extraModules, function(module) {
- modules.push(module);
- });
- doBootstrap();
- };
-}
-
-var SNAKE_CASE_REGEXP = /[A-Z]/g;
-function snake_case(name, separator) {
- separator = separator || '_';
- return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
- return (pos ? separator : '') + letter.toLowerCase();
- });
-}
-
-function bindJQuery() {
- // bind to jQuery if present;
- jQuery = window.jQuery;
- // Use jQuery if it exists with proper functionality, otherwise default to us.
- // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
- if (jQuery && jQuery.fn.on) {
- jqLite = jQuery;
- extend(jQuery.fn, {
- scope: JQLitePrototype.scope,
- isolateScope: JQLitePrototype.isolateScope,
- controller: JQLitePrototype.controller,
- injector: JQLitePrototype.injector,
- inheritedData: JQLitePrototype.inheritedData
- });
- // Method signature:
- // jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
- jqLitePatchJQueryRemove('remove', true, true, false);
- jqLitePatchJQueryRemove('empty', false, false, false);
- jqLitePatchJQueryRemove('html', false, false, true);
- } else {
- jqLite = JQLite;
- }
- angular.element = jqLite;
-}
-
-/**
- * throw error if the argument is falsy.
- */
-function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
-}
-
-function assertArgFn(arg, name, acceptArrayAnnotation) {
- if (acceptArrayAnnotation && isArray(arg)) {
- arg = arg[arg.length - 1];
- }
-
- assertArg(isFunction(arg), name, 'not a function, got ' +
- (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
- return arg;
-}
-
-/**
- * throw error if the name given is hasOwnProperty
- * @param {String} name the name to test
- * @param {String} context the context in which the name is used, such as module or directive
- */
-function assertNotHasOwnProperty(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
- }
-}
-
-/**
- * Return the value accessible from the object by path. Any undefined traversals are ignored
- * @param {Object} obj starting object
- * @param {String} path path to traverse
- * @param {boolean} [bindFnToScope=true]
- * @returns {Object} value as accessible by path
- */
-//TODO(misko): this function needs to be removed
-function getter(obj, path, bindFnToScope) {
- if (!path) return obj;
- var keys = path.split('.');
- var key;
- var lastInstance = obj;
- var len = keys.length;
-
- for (var i = 0; i < len; i++) {
- key = keys[i];
- if (obj) {
- obj = (lastInstance = obj)[key];
- }
- }
- if (!bindFnToScope && isFunction(obj)) {
- return bind(lastInstance, obj);
- }
- return obj;
-}
-
-/**
- * Return the DOM siblings between the first and last node in the given array.
- * @param {Array} array like object
- * @returns {DOMElement} object containing the elements
- */
-function getBlockElements(nodes) {
- var startNode = nodes[0],
- endNode = nodes[nodes.length - 1];
- if (startNode === endNode) {
- return jqLite(startNode);
- }
-
- var element = startNode;
- var elements = [element];
-
- do {
- element = element.nextSibling;
- if (!element) break;
- elements.push(element);
- } while (element !== endNode);
-
- return jqLite(elements);
-}
-
-/**
- * @ngdoc type
- * @name angular.Module
- * @module ng
- * @description
- *
- * Interface for configuring angular {@link angular.module modules}.
- */
-
-function setupModuleLoader(window) {
-
- var $injectorMinErr = minErr('$injector');
- var ngMinErr = minErr('ng');
-
- function ensure(obj, name, factory) {
- return obj[name] || (obj[name] = factory());
- }
-
- var angular = ensure(window, 'angular', Object);
-
- // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
- angular.$$minErr = angular.$$minErr || minErr;
-
- return ensure(angular, 'module', function() {
- /** @type {Object.<string, angular.Module>} */
- var modules = {};
-
- /**
- * @ngdoc function
- * @name angular.module
- * @module ng
- * @description
- *
- * The `angular.module` is a global place for creating, registering and retrieving Angular
- * modules.
- * All modules (angular core or 3rd party) that should be available to an application must be
- * registered using this mechanism.
- *
- * When passed two or more arguments, a new module is created. If passed only one argument, an
- * existing module (the name passed as the first argument to `module`) is retrieved.
- *
- *
- * # Module
- *
- * A module is a collection of services, directives, controllers, filters, and configuration information.
- * `angular.module` is used to configure the {@link auto.$injector $injector}.
- *
- * ```js
- * // Create a new module
- * var myModule = angular.module('myModule', []);
- *
- * // register a new service
- * myModule.value('appName', 'MyCoolApp');
- *
- * // configure existing services inside initialization blocks.
- * myModule.config(['$locationProvider', function($locationProvider) {
- * // Configure existing providers
- * $locationProvider.hashPrefix('!');
- * }]);
- * ```
- *
- * Then you can create an injector and load your modules like this:
- *
- * ```js
- * var injector = angular.injector(['ng', 'myModule'])
- * ```
- *
- * However it's more likely that you'll just use
- * {@link ng.directive:ngApp ngApp} or
- * {@link angular.bootstrap} to simplify this process for you.
- *
- * @param {!string} name The name of the module to create or retrieve.
- * @param {!Array.<string>=} requires If specified then new module is being created. If
- * unspecified then the module is being retrieved for further configuration.
- * @param {Function=} configFn Optional configuration function for the module. Same as
- * {@link angular.Module#config Module#config()}.
- * @returns {module} new module with the {@link angular.Module} api.
- */
- return function module(name, requires, configFn) {
- var assertNotHasOwnProperty = function(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
- }
- };
-
- assertNotHasOwnProperty(name, 'module');
- if (requires && modules.hasOwnProperty(name)) {
- modules[name] = null;
- }
- return ensure(modules, name, function() {
- if (!requires) {
- throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
- "the module name or forgot to load it. If registering a module ensure that you " +
- "specify the dependencies as the second argument.", name);
- }
-
- /** @type {!Array.<Array.<*>>} */
- var invokeQueue = [];
-
- /** @type {!Array.<Function>} */
- var runBlocks = [];
-
- var config = invokeLater('$injector', 'invoke');
-
- /** @type {angular.Module} */
- var moduleInstance = {
- // Private state
- _invokeQueue: invokeQueue,
- _runBlocks: runBlocks,
-
- /**
- * @ngdoc property
- * @name angular.Module#requires
- * @module ng
- *
- * @description
- * Holds the list of modules which the injector will load before the current module is
- * loaded.
- */
- requires: requires,
-
- /**
- * @ngdoc property
- * @name angular.Module#name
- * @module ng
- *
- * @description
- * Name of the module.
- */
- name: name,
-
-
- /**
- * @ngdoc method
- * @name angular.Module#provider
- * @module ng
- * @param {string} name service name
- * @param {Function} providerType Construction function for creating new instance of the
- * service.
- * @description
- * See {@link auto.$provide#provider $provide.provider()}.
- */
- provider: invokeLater('$provide', 'provider'),
-
- /**
- * @ngdoc method
- * @name angular.Module#factory
- * @module ng
- * @param {string} name service name
- * @param {Function} providerFunction Function for creating new instance of the service.
- * @description
- * See {@link auto.$provide#factory $provide.factory()}.
- */
- factory: invokeLater('$provide', 'factory'),
-
- /**
- * @ngdoc method
- * @name angular.Module#service
- * @module ng
- * @param {string} name service name
- * @param {Function} constructor A constructor function that will be instantiated.
- * @description
- * See {@link auto.$provide#service $provide.service()}.
- */
- service: invokeLater('$provide', 'service'),
-
- /**
- * @ngdoc method
- * @name angular.Module#value
- * @module ng
- * @param {string} name service name
- * @param {*} object Service instance object.
- * @description
- * See {@link auto.$provide#value $provide.value()}.
- */
- value: invokeLater('$provide', 'value'),
-
- /**
- * @ngdoc method
- * @name angular.Module#constant
- * @module ng
- * @param {string} name constant name
- * @param {*} object Constant value.
- * @description
- * Because the constant are fixed, they get applied before other provide methods.
- * See {@link auto.$provide#constant $provide.constant()}.
- */
- constant: invokeLater('$provide', 'constant', 'unshift'),
-
- /**
- * @ngdoc method
- * @name angular.Module#animation
- * @module ng
- * @param {string} name animation name
- * @param {Function} animationFactory Factory function for creating new instance of an
- * animation.
- * @description
- *
- * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
- *
- *
- * Defines an animation hook that can be later used with
- * {@link ngAnimate.$animate $animate} service and directives that use this service.
- *
- * ```js
- * module.animation('.animation-name', function($inject1, $inject2) {
- * return {
- * eventName : function(element, done) {
- * //code to run the animation
- * //once complete, then run done()
- * return function cancellationFunction(element) {
- * //code to cancel the animation
- * }
- * }
- * }
- * })
- * ```
- *
- * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
- * {@link ngAnimate ngAnimate module} for more information.
- */
- animation: invokeLater('$animateProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#filter
- * @module ng
- * @param {string} name Filter name.
- * @param {Function} filterFactory Factory function for creating new instance of filter.
- * @description
- * See {@link ng.$filterProvider#register $filterProvider.register()}.
- */
- filter: invokeLater('$filterProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#controller
- * @module ng
- * @param {string|Object} name Controller name, or an object map of controllers where the
- * keys are the names and the values are the constructors.
- * @param {Function} constructor Controller constructor function.
- * @description
- * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
- */
- controller: invokeLater('$controllerProvider', 'register'),
-
- /**
- * @ngdoc method
- * @name angular.Module#directive
- * @module ng
- * @param {string|Object} name Directive name, or an object map of directives where the
- * keys are the names and the values are the factories.
- * @param {Function} directiveFactory Factory function for creating new instance of
- * directives.
- * @description
- * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
- */
- directive: invokeLater('$compileProvider', 'directive'),
-
- /**
- * @ngdoc method
- * @name angular.Module#config
- * @module ng
- * @param {Function} configFn Execute this function on module load. Useful for service
- * configuration.
- * @description
- * Use this method to register work which needs to be performed on module loading.
- * For more about how to configure services, see
- * {@link providers#providers_provider-recipe Provider Recipe}.
- */
- config: config,
-
- /**
- * @ngdoc method
- * @name angular.Module#run
- * @module ng
- * @param {Function} initializationFn Execute this function after injector creation.
- * Useful for application initialization.
- * @description
- * Use this method to register work which should be performed when the injector is done
- * loading all modules.
- */
- run: function(block) {
- runBlocks.push(block);
- return this;
- }
- };
-
- if (configFn) {
- config(configFn);
- }
-
- return moduleInstance;
-
- /**
- * @param {string} provider
- * @param {string} method
- * @param {String=} insertMethod
- * @returns {angular.Module}
- */
- function invokeLater(provider, method, insertMethod) {
- return function() {
- invokeQueue[insertMethod || 'push']([provider, method, arguments]);
- return moduleInstance;
- };
- }
- });
- };
- });
-
-}
-
-/* global angularModule: true,
- version: true,
-
- $LocaleProvider,
- $CompileProvider,
-
- htmlAnchorDirective,
- inputDirective,
- inputDirective,
- formDirective,
- scriptDirective,
- selectDirective,
- styleDirective,
- optionDirective,
- ngBindDirective,
- ngBindHtmlDirective,
- ngBindTemplateDirective,
- ngClassDirective,
- ngClassEvenDirective,
- ngClassOddDirective,
- ngCspDirective,
- ngCloakDirective,
- ngControllerDirective,
- ngFormDirective,
- ngHideDirective,
- ngIfDirective,
- ngIncludeDirective,
- ngIncludeFillContentDirective,
- ngInitDirective,
- ngNonBindableDirective,
- ngPluralizeDirective,
- ngRepeatDirective,
- ngShowDirective,
- ngStyleDirective,
- ngSwitchDirective,
- ngSwitchWhenDirective,
- ngSwitchDefaultDirective,
- ngOptionsDirective,
- ngTranscludeDirective,
- ngModelDirective,
- ngListDirective,
- ngChangeDirective,
- requiredDirective,
- requiredDirective,
- ngValueDirective,
- ngAttributeAliasDirectives,
- ngEventDirectives,
-
- $AnchorScrollProvider,
- $AnimateProvider,
- $BrowserProvider,
- $CacheFactoryProvider,
- $ControllerProvider,
- $DocumentProvider,
- $ExceptionHandlerProvider,
- $FilterProvider,
- $InterpolateProvider,
- $IntervalProvider,
- $HttpProvider,
- $HttpBackendProvider,
- $LocationProvider,
- $LogProvider,
- $ParseProvider,
- $RootScopeProvider,
- $QProvider,
- $$SanitizeUriProvider,
- $SceProvider,
- $SceDelegateProvider,
- $SnifferProvider,
- $TemplateCacheProvider,
- $TimeoutProvider,
- $$RAFProvider,
- $$AsyncCallbackProvider,
- $WindowProvider
-*/
-
-
-/**
- * @ngdoc object
- * @name angular.version
- * @module ng
- * @description
- * An object that contains information about the current AngularJS version. This object has the
- * following properties:
- *
- * - `full` – `{string}` – Full version string, such as "0.9.18".
- * - `major` – `{number}` – Major version number, such as "0".
- * - `minor` – `{number}` – Minor version number, such as "9".
- * - `dot` – `{number}` – Dot version number, such as "18".
- * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
- */
-var version = {
- full: '1.2.25', // all of these placeholder strings will be replaced by grunt's
- major: 1, // package task
- minor: 2,
- dot: 25,
- codeName: 'hypnotic-gesticulation'
-};
-
-
-function publishExternalAPI(angular){
- extend(angular, {
- 'bootstrap': bootstrap,
- 'copy': copy,
- 'extend': extend,
- 'equals': equals,
- 'element': jqLite,
- 'forEach': forEach,
- 'injector': createInjector,
- 'noop': noop,
- 'bind': bind,
- 'toJson': toJson,
- 'fromJson': fromJson,
- 'identity': identity,
- 'isUndefined': isUndefined,
- 'isDefined': isDefined,
- 'isString': isString,
- 'isFunction': isFunction,
- 'isObject': isObject,
- 'isNumber': isNumber,
- 'isElement': isElement,
- 'isArray': isArray,
- 'version': version,
- 'isDate': isDate,
- 'lowercase': lowercase,
- 'uppercase': uppercase,
- 'callbacks': {counter: 0},
- '$$minErr': minErr,
- '$$csp': csp
- });
-
- angularModule = setupModuleLoader(window);
- try {
- angularModule('ngLocale');
- } catch (e) {
- angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
- }
-
- angularModule('ng', ['ngLocale'], ['$provide',
- function ngModule($provide) {
- // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
- $provide.provider({
- $$sanitizeUri: $$SanitizeUriProvider
- });
- $provide.provider('$compile', $CompileProvider).
- directive({
- a: htmlAnchorDirective,
- input: inputDirective,
- textarea: inputDirective,
- form: formDirective,
- script: scriptDirective,
- select: selectDirective,
- style: styleDirective,
- option: optionDirective,
- ngBind: ngBindDirective,
- ngBindHtml: ngBindHtmlDirective,
- ngBindTemplate: ngBindTemplateDirective,
- ngClass: ngClassDirective,
- ngClassEven: ngClassEvenDirective,
- ngClassOdd: ngClassOddDirective,
- ngCloak: ngCloakDirective,
- ngController: ngControllerDirective,
- ngForm: ngFormDirective,
- ngHide: ngHideDirective,
- ngIf: ngIfDirective,
- ngInclude: ngIncludeDirective,
- ngInit: ngInitDirective,
- ngNonBindable: ngNonBindableDirective,
- ngPluralize: ngPluralizeDirective,
- ngRepeat: ngRepeatDirective,
- ngShow: ngShowDirective,
- ngStyle: ngStyleDirective,
- ngSwitch: ngSwitchDirective,
- ngSwitchWhen: ngSwitchWhenDirective,
- ngSwitchDefault: ngSwitchDefaultDirective,
- ngOptions: ngOptionsDirective,
- ngTransclude: ngTranscludeDirective,
- ngModel: ngModelDirective,
- ngList: ngListDirective,
- ngChange: ngChangeDirective,
- required: requiredDirective,
- ngRequired: requiredDirective,
- ngValue: ngValueDirective
- }).
- directive({
- ngInclude: ngIncludeFillContentDirective
- }).
- directive(ngAttributeAliasDirectives).
- directive(ngEventDirectives);
- $provide.provider({
- $anchorScroll: $AnchorScrollProvider,
- $animate: $AnimateProvider,
- $browser: $BrowserProvider,
- $cacheFactory: $CacheFactoryProvider,
- $controller: $ControllerProvider,
- $document: $DocumentProvider,
- $exceptionHandler: $ExceptionHandlerProvider,
- $filter: $FilterProvider,
- $interpolate: $InterpolateProvider,
- $interval: $IntervalProvider,
- $http: $HttpProvider,
- $httpBackend: $HttpBackendProvider,
- $location: $LocationProvider,
- $log: $LogProvider,
- $parse: $ParseProvider,
- $rootScope: $RootScopeProvider,
- $q: $QProvider,
- $sce: $SceProvider,
- $sceDelegate: $SceDelegateProvider,
- $sniffer: $SnifferProvider,
- $templateCache: $TemplateCacheProvider,
- $timeout: $TimeoutProvider,
- $window: $WindowProvider,
- $$rAF: $$RAFProvider,
- $$asyncCallback : $$AsyncCallbackProvider
- });
- }
- ]);
-}
-
-/* global JQLitePrototype: true,
- addEventListenerFn: true,
- removeEventListenerFn: true,
- BOOLEAN_ATTR: true
-*/
-
-//////////////////////////////////
-//JQLite
-//////////////////////////////////
-
-/**
- * @ngdoc function
- * @name angular.element
- * @module ng
- * @kind function
- *
- * @description
- * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
- *
- * If jQuery is available, `angular.element` is an alias for the
- * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
- * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
- *
- * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
- * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
- * commonly needed functionality with the goal of having a very small footprint.</div>
- *
- * To use jQuery, simply load it before `DOMContentLoaded` event fired.
- *
- * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
- * jqLite; they are never raw DOM references.</div>
- *
- * ## Angular's jqLite
- * jqLite provides only the following jQuery methods:
- *
- * - [`addClass()`](http://api.jquery.com/addClass/)
- * - [`after()`](http://api.jquery.com/after/)
- * - [`append()`](http://api.jquery.com/append/)
- * - [`attr()`](http://api.jquery.com/attr/)
- * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
- * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
- * - [`clone()`](http://api.jquery.com/clone/)
- * - [`contents()`](http://api.jquery.com/contents/)
- * - [`css()`](http://api.jquery.com/css/)
- * - [`data()`](http://api.jquery.com/data/)
- * - [`empty()`](http://api.jquery.com/empty/)
- * - [`eq()`](http://api.jquery.com/eq/)
- * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
- * - [`hasClass()`](http://api.jquery.com/hasClass/)
- * - [`html()`](http://api.jquery.com/html/)
- * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
- * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
- * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
- * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
- * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
- * - [`prepend()`](http://api.jquery.com/prepend/)
- * - [`prop()`](http://api.jquery.com/prop/)
- * - [`ready()`](http://api.jquery.com/ready/)
- * - [`remove()`](http://api.jquery.com/remove/)
- * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
- * - [`removeClass()`](http://api.jquery.com/removeClass/)
- * - [`removeData()`](http://api.jquery.com/removeData/)
- * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
- * - [`text()`](http://api.jquery.com/text/)
- * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
- * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
- * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
- * - [`val()`](http://api.jquery.com/val/)
- * - [`wrap()`](http://api.jquery.com/wrap/)
- *
- * ## jQuery/jqLite Extras
- * Angular also provides the following additional methods and events to both jQuery and jqLite:
- *
- * ### Events
- * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
- * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
- * element before it is removed.
- *
- * ### Methods
- * - `controller(name)` - retrieves the controller of the current element or its parent. By default
- * retrieves controller associated with the `ngController` directive. If `name` is provided as
- * camelCase directive name, then the controller for this directive will be retrieved (e.g.
- * `'ngModel'`).
- * - `injector()` - retrieves the injector of the current element or its parent.
- * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
- * element or its parent.
- * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
- * current element. This getter should be used only on elements that contain a directive which starts a new isolate
- * scope. Calling `scope()` on this element always returns the original non-isolate scope.
- * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
- * parent element is reached.
- *
- * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
- * @returns {Object} jQuery object.
- */
-
-JQLite.expando = 'ng339';
-
-var jqCache = JQLite.cache = {},
- jqId = 1,
- addEventListenerFn = (window.document.addEventListener
- ? function(element, type, fn) {element.addEventListener(type, fn, false);}
- : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
- removeEventListenerFn = (window.document.removeEventListener
- ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
- : function(element, type, fn) {element.detachEvent('on' + type, fn); });
-
-/*
- * !!! This is an undocumented "private" function !!!
- */
-var jqData = JQLite._data = function(node) {
- //jQuery always returns an object on cache miss
- return this.cache[node[this.expando]] || {};
-};
-
-function jqNextId() { return ++jqId; }
-
-
-var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
-var MOZ_HACK_REGEXP = /^moz([A-Z])/;
-var jqLiteMinErr = minErr('jqLite');
-
-/**
- * Converts snake_case to camelCase.
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function camelCase(name) {
- return name.
- replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
- return offset ? letter.toUpperCase() : letter;
- }).
- replace(MOZ_HACK_REGEXP, 'Moz$1');
-}
-
-/////////////////////////////////////////////
-// jQuery mutation patch
-//
-// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
-// $destroy event on all DOM nodes being removed.
-//
-/////////////////////////////////////////////
-
-function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
- var originalJqFn = jQuery.fn[name];
- originalJqFn = originalJqFn.$original || originalJqFn;
- removePatch.$original = originalJqFn;
- jQuery.fn[name] = removePatch;
-
- function removePatch(param) {
- // jshint -W040
- var list = filterElems && param ? [this.filter(param)] : [this],
- fireEvent = dispatchThis,
- set, setIndex, setLength,
- element, childIndex, childLength, children;
-
- if (!getterIfNoArguments || param != null) {
- while(list.length) {
- set = list.shift();
- for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
- element = jqLite(set[setIndex]);
- if (fireEvent) {
- element.triggerHandler('$destroy');
- } else {
- fireEvent = !fireEvent;
- }
- for(childIndex = 0, childLength = (children = element.children()).length;
- childIndex < childLength;
- childIndex++) {
- list.push(jQuery(children[childIndex]));
- }
- }
- }
- }
- return originalJqFn.apply(this, arguments);
- }
-}
-
-var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
-var HTML_REGEXP = /<|&#?\w+;/;
-var TAG_NAME_REGEXP = /<([\w:]+)/;
-var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
-
-var wrapMap = {
- 'option': [1, '<select multiple="multiple">', '</select>'],
-
- 'thead': [1, '<table>', '</table>'],
- 'col': [2, '<table><colgroup>', '</colgroup></table>'],
- 'tr': [2, '<table><tbody>', '</tbody></table>'],
- 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
- '_default': [0, "", ""]
-};
-
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-function jqLiteIsTextNode(html) {
- return !HTML_REGEXP.test(html);
-}
-
-function jqLiteBuildFragment(html, context) {
- var elem, tmp, tag, wrap,
- fragment = context.createDocumentFragment(),
- nodes = [], i, j, jj;
-
- if (jqLiteIsTextNode(html)) {
- // Convert non-html into a text node
- nodes.push(context.createTextNode(html));
- } else {
- tmp = fragment.appendChild(context.createElement('div'));
- // Convert html into DOM nodes
- tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
- wrap = wrapMap[tag] || wrapMap._default;
- tmp.innerHTML = '<div>&#160;</div>' +
- wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
- tmp.removeChild(tmp.firstChild);
-
- // Descend through wrappers to the right content
- i = wrap[0];
- while (i--) {
- tmp = tmp.lastChild;
- }
-
- for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);
-
- tmp = fragment.firstChild;
- tmp.textContent = "";
- }
-
- // Remove wrapper from fragment
- fragment.textContent = "";
- fragment.innerHTML = ""; // Clear inner HTML
- return nodes;
-}
-
-function jqLiteParseHTML(html, context) {
- context = context || document;
- var parsed;
-
- if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
- return [context.createElement(parsed[1])];
- }
-
- return jqLiteBuildFragment(html, context);
-}
-
-/////////////////////////////////////////////
-function JQLite(element) {
- if (element instanceof JQLite) {
- return element;
- }
- if (isString(element)) {
- element = trim(element);
- }
- if (!(this instanceof JQLite)) {
- if (isString(element) && element.charAt(0) != '<') {
- throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
- }
- return new JQLite(element);
- }
-
- if (isString(element)) {
- jqLiteAddNodes(this, jqLiteParseHTML(element));
- var fragment = jqLite(document.createDocumentFragment());
- fragment.append(this);
- } else {
- jqLiteAddNodes(this, element);
- }
-}
-
-function jqLiteClone(element) {
- return element.cloneNode(true);
-}
-
-function jqLiteDealoc(element){
- jqLiteRemoveData(element);
- for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
- jqLiteDealoc(children[i]);
- }
-}
-
-function jqLiteOff(element, type, fn, unsupported) {
- if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
-
- var events = jqLiteExpandoStore(element, 'events'),
- handle = jqLiteExpandoStore(element, 'handle');
-
- if (!handle) return; //no listeners registered
-
- if (isUndefined(type)) {
- forEach(events, function(eventHandler, type) {
- removeEventListenerFn(element, type, eventHandler);
- delete events[type];
- });
- } else {
- forEach(type.split(' '), function(type) {
- if (isUndefined(fn)) {
- removeEventListenerFn(element, type, events[type]);
- delete events[type];
- } else {
- arrayRemove(events[type] || [], fn);
- }
- });
- }
-}
-
-function jqLiteRemoveData(element, name) {
- var expandoId = element.ng339,
- expandoStore = jqCache[expandoId];
-
- if (expandoStore) {
- if (name) {
- delete jqCache[expandoId].data[name];
- return;
- }
-
- if (expandoStore.handle) {
- expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
- jqLiteOff(element);
- }
- delete jqCache[expandoId];
- element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
- }
-}
-
-function jqLiteExpandoStore(element, key, value) {
- var expandoId = element.ng339,
- expandoStore = jqCache[expandoId || -1];
-
- if (isDefined(value)) {
- if (!expandoStore) {
- element.ng339 = expandoId = jqNextId();
- expandoStore = jqCache[expandoId] = {};
- }
- expandoStore[key] = value;
- } else {
- return expandoStore && expandoStore[key];
- }
-}
-
-function jqLiteData(element, key, value) {
- var data = jqLiteExpandoStore(element, 'data'),
- isSetter = isDefined(value),
- keyDefined = !isSetter && isDefined(key),
- isSimpleGetter = keyDefined && !isObject(key);
-
- if (!data && !isSimpleGetter) {
- jqLiteExpandoStore(element, 'data', data = {});
- }
-
- if (isSetter) {
- data[key] = value;
- } else {
- if (keyDefined) {
- if (isSimpleGetter) {
- // don't create data in this case.
- return data && data[key];
- } else {
- extend(data, key);
- }
- } else {
- return data;
- }
- }
-}
-
-function jqLiteHasClass(element, selector) {
- if (!element.getAttribute) return false;
- return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
- indexOf( " " + selector + " " ) > -1);
-}
-
-function jqLiteRemoveClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- forEach(cssClasses.split(' '), function(cssClass) {
- element.setAttribute('class', trim(
- (" " + (element.getAttribute('class') || '') + " ")
- .replace(/[\n\t]/g, " ")
- .replace(" " + trim(cssClass) + " ", " "))
- );
- });
- }
-}
-
-function jqLiteAddClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
- .replace(/[\n\t]/g, " ");
-
- forEach(cssClasses.split(' '), function(cssClass) {
- cssClass = trim(cssClass);
- if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
- existingClasses += cssClass + ' ';
- }
- });
-
- element.setAttribute('class', trim(existingClasses));
- }
-}
-
-function jqLiteAddNodes(root, elements) {
- if (elements) {
- elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
- ? elements
- : [ elements ];
- for(var i=0; i < elements.length; i++) {
- root.push(elements[i]);
- }
- }
-}
-
-function jqLiteController(element, name) {
- return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
-}
-
-function jqLiteInheritedData(element, name, value) {
- // if element is the document object work with the html element instead
- // this makes $(document).scope() possible
- if(element.nodeType == 9) {
- element = element.documentElement;
- }
- var names = isArray(name) ? name : [name];
-
- while (element) {
- for (var i = 0, ii = names.length; i < ii; i++) {
- if ((value = jqLite.data(element, names[i])) !== undefined) return value;
- }
-
- // If dealing with a document fragment node with a host element, and no parent, use the host
- // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
- // to lookup parent controllers.
- element = element.parentNode || (element.nodeType === 11 && element.host);
- }
-}
-
-function jqLiteEmpty(element) {
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
- while (element.firstChild) {
- element.removeChild(element.firstChild);
- }
-}
-
-//////////////////////////////////////////
-// Functions which are declared directly.
-//////////////////////////////////////////
-var JQLitePrototype = JQLite.prototype = {
- ready: function(fn) {
- var fired = false;
-
- function trigger() {
- if (fired) return;
- fired = true;
- fn();
- }
-
- // check if document already is loaded
- if (document.readyState === 'complete'){
- setTimeout(trigger);
- } else {
- this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
- // we can not use jqLite since we are not done loading and jQuery could be loaded later.
- // jshint -W064
- JQLite(window).on('load', trigger); // fallback to window.onload for others
- // jshint +W064
- }
- },
- toString: function() {
- var value = [];
- forEach(this, function(e){ value.push('' + e);});
- return '[' + value.join(', ') + ']';
- },
-
- eq: function(index) {
- return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
- },
-
- length: 0,
- push: push,
- sort: [].sort,
- splice: [].splice
-};
-
-//////////////////////////////////////////
-// Functions iterating getter/setters.
-// these functions return self on setter and
-// value on get.
-//////////////////////////////////////////
-var BOOLEAN_ATTR = {};
-forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
- BOOLEAN_ATTR[lowercase(value)] = value;
-});
-var BOOLEAN_ELEMENTS = {};
-forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
- BOOLEAN_ELEMENTS[uppercase(value)] = true;
-});
-
-function getBooleanAttrName(element, name) {
- // check dom last since we will most likely fail on name
- var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
-
- // booleanAttr is here twice to minimize DOM access
- return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
-}
-
-forEach({
- data: jqLiteData,
- removeData: jqLiteRemoveData
-}, function(fn, name) {
- JQLite[name] = fn;
-});
-
-forEach({
- data: jqLiteData,
- inheritedData: jqLiteInheritedData,
-
- scope: function(element) {
- // Can't use jqLiteData here directly so we stay compatible with jQuery!
- return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
- },
-
- isolateScope: function(element) {
- // Can't use jqLiteData here directly so we stay compatible with jQuery!
- return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
- },
-
- controller: jqLiteController,
-
- injector: function(element) {
- return jqLiteInheritedData(element, '$injector');
- },
-
- removeAttr: function(element,name) {
- element.removeAttribute(name);
- },
-
- hasClass: jqLiteHasClass,
-
- css: function(element, name, value) {
- name = camelCase(name);
-
- if (isDefined(value)) {
- element.style[name] = value;
- } else {
- var val;
-
- if (msie <= 8) {
- // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
- val = element.currentStyle && element.currentStyle[name];
- if (val === '') val = 'auto';
- }
-
- val = val || element.style[name];
-
- if (msie <= 8) {
- // jquery weirdness :-/
- val = (val === '') ? undefined : val;
- }
-
- return val;
- }
- },
-
- attr: function(element, name, value){
- var lowercasedName = lowercase(name);
- if (BOOLEAN_ATTR[lowercasedName]) {
- if (isDefined(value)) {
- if (!!value) {
- element[name] = true;
- element.setAttribute(name, lowercasedName);
- } else {
- element[name] = false;
- element.removeAttribute(lowercasedName);
- }
- } else {
- return (element[name] ||
- (element.attributes.getNamedItem(name)|| noop).specified)
- ? lowercasedName
- : undefined;
- }
- } else if (isDefined(value)) {
- element.setAttribute(name, value);
- } else if (element.getAttribute) {
- // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
- // some elements (e.g. Document) don't have get attribute, so return undefined
- var ret = element.getAttribute(name, 2);
- // normalize non-existing attributes to undefined (as jQuery)
- return ret === null ? undefined : ret;
- }
- },
-
- prop: function(element, name, value) {
- if (isDefined(value)) {
- element[name] = value;
- } else {
- return element[name];
- }
- },
-
- text: (function() {
- var NODE_TYPE_TEXT_PROPERTY = [];
- if (msie < 9) {
- NODE_TYPE_TEXT_PROPERTY[1] = 'innerText'; /** Element **/
- NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue'; /** Text **/
- } else {
- NODE_TYPE_TEXT_PROPERTY[1] = /** Element **/
- NODE_TYPE_TEXT_PROPERTY[3] = 'textContent'; /** Text **/
- }
- getText.$dv = '';
- return getText;
-
- function getText(element, value) {
- var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
- if (isUndefined(value)) {
- return textProp ? element[textProp] : '';
- }
- element[textProp] = value;
- }
- })(),
-
- val: function(element, value) {
- if (isUndefined(value)) {
- if (nodeName_(element) === 'SELECT' && element.multiple) {
- var result = [];
- forEach(element.options, function (option) {
- if (option.selected) {
- result.push(option.value || option.text);
- }
- });
- return result.length === 0 ? null : result;
- }
- return element.value;
- }
- element.value = value;
- },
-
- html: function(element, value) {
- if (isUndefined(value)) {
- return element.innerHTML;
- }
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
- element.innerHTML = value;
- },
-
- empty: jqLiteEmpty
-}, function(fn, name){
- /**
- * Properties: writes return selection, reads return first value
- */
- JQLite.prototype[name] = function(arg1, arg2) {
- var i, key;
- var nodeCount = this.length;
-
- // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
- // in a way that survives minification.
- // jqLiteEmpty takes no arguments but is a setter.
- if (fn !== jqLiteEmpty &&
- (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
- if (isObject(arg1)) {
-
- // we are a write, but the object properties are the key/values
- for (i = 0; i < nodeCount; i++) {
- if (fn === jqLiteData) {
- // data() takes the whole object in jQuery
- fn(this[i], arg1);
- } else {
- for (key in arg1) {
- fn(this[i], key, arg1[key]);
- }
- }
- }
- // return self for chaining
- return this;
- } else {
- // we are a read, so read the first child.
- // TODO: do we still need this?
- var value = fn.$dv;
- // Only if we have $dv do we iterate over all, otherwise it is just the first element.
- var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
- for (var j = 0; j < jj; j++) {
- var nodeValue = fn(this[j], arg1, arg2);
- value = value ? value + nodeValue : nodeValue;
- }
- return value;
- }
- } else {
- // we are a write, so apply to all children
- for (i = 0; i < nodeCount; i++) {
- fn(this[i], arg1, arg2);
- }
- // return self for chaining
- return this;
- }
- };
-});
-
-function createEventHandler(element, events) {
- var eventHandler = function (event, type) {
- if (!event.preventDefault) {
- event.preventDefault = function() {
- event.returnValue = false; //ie
- };
- }
-
- if (!event.stopPropagation) {
- event.stopPropagation = function() {
- event.cancelBubble = true; //ie
- };
- }
-
- if (!event.target) {
- event.target = event.srcElement || document;
- }
-
- if (isUndefined(event.defaultPrevented)) {
- var prevent = event.preventDefault;
- event.preventDefault = function() {
- event.defaultPrevented = true;
- prevent.call(event);
- };
- event.defaultPrevented = false;
- }
-
- event.isDefaultPrevented = function() {
- return event.defaultPrevented || event.returnValue === false;
- };
-
- // Copy event handlers in case event handlers array is modified during execution.
- var eventHandlersCopy = shallowCopy(events[type || event.type] || []);
-
- forEach(eventHandlersCopy, function(fn) {
- fn.call(element, event);
- });
-
- // Remove monkey-patched methods (IE),
- // as they would cause memory leaks in IE8.
- if (msie <= 8) {
- // IE7/8 does not allow to delete property on native object
- event.preventDefault = null;
- event.stopPropagation = null;
- event.isDefaultPrevented = null;
- } else {
- // It shouldn't affect normal browsers (native methods are defined on prototype).
- delete event.preventDefault;
- delete event.stopPropagation;
- delete event.isDefaultPrevented;
- }
- };
- eventHandler.elem = element;
- return eventHandler;
-}
-
-//////////////////////////////////////////
-// Functions iterating traversal.
-// These functions chain results into a single
-// selector.
-//////////////////////////////////////////
-forEach({
- removeData: jqLiteRemoveData,
-
- dealoc: jqLiteDealoc,
-
- on: function onFn(element, type, fn, unsupported){
- if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
-
- var events = jqLiteExpandoStore(element, 'events'),
- handle = jqLiteExpandoStore(element, 'handle');
-
- if (!events) jqLiteExpandoStore(element, 'events', events = {});
- if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
-
- forEach(type.split(' '), function(type){
- var eventFns = events[type];
-
- if (!eventFns) {
- if (type == 'mouseenter' || type == 'mouseleave') {
- var contains = document.body.contains || document.body.compareDocumentPosition ?
- function( a, b ) {
- // jshint bitwise: false
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
-
- events[type] = [];
-
- // Refer to jQuery's implementation of mouseenter & mouseleave
- // Read about mouseenter and mouseleave:
- // http://www.quirksmode.org/js/events_mouse.html#link8
- var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};
-
- onFn(element, eventmap[type], function(event) {
- var target = this, related = event.relatedTarget;
- // For mousenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || (related !== target && !contains(target, related)) ){
- handle(event, type);
- }
- });
-
- } else {
- addEventListenerFn(element, type, handle);
- events[type] = [];
- }
- eventFns = events[type];
- }
- eventFns.push(fn);
- });
- },
-
- off: jqLiteOff,
-
- one: function(element, type, fn) {
- element = jqLite(element);
-
- //add the listener twice so that when it is called
- //you can remove the original function and still be
- //able to call element.off(ev, fn) normally
- element.on(type, function onFn() {
- element.off(type, fn);
- element.off(type, onFn);
- });
- element.on(type, fn);
- },
-
- replaceWith: function(element, replaceNode) {
- var index, parent = element.parentNode;
- jqLiteDealoc(element);
- forEach(new JQLite(replaceNode), function(node){
- if (index) {
- parent.insertBefore(node, index.nextSibling);
- } else {
- parent.replaceChild(node, element);
- }
- index = node;
- });
- },
-
- children: function(element) {
- var children = [];
- forEach(element.childNodes, function(element){
- if (element.nodeType === 1)
- children.push(element);
- });
- return children;
- },
-
- contents: function(element) {
- return element.contentDocument || element.childNodes || [];
- },
-
- append: function(element, node) {
- forEach(new JQLite(node), function(child){
- if (element.nodeType === 1 || element.nodeType === 11) {
- element.appendChild(child);
- }
- });
- },
-
- prepend: function(element, node) {
- if (element.nodeType === 1) {
- var index = element.firstChild;
- forEach(new JQLite(node), function(child){
- element.insertBefore(child, index);
- });
- }
- },
-
- wrap: function(element, wrapNode) {
- wrapNode = jqLite(wrapNode)[0];
- var parent = element.parentNode;
- if (parent) {
- parent.replaceChild(wrapNode, element);
- }
- wrapNode.appendChild(element);
- },
-
- remove: function(element) {
- jqLiteDealoc(element);
- var parent = element.parentNode;
- if (parent) parent.removeChild(element);
- },
-
- after: function(element, newElement) {
- var index = element, parent = element.parentNode;
- forEach(new JQLite(newElement), function(node){
- parent.insertBefore(node, index.nextSibling);
- index = node;
- });
- },
-
- addClass: jqLiteAddClass,
- removeClass: jqLiteRemoveClass,
-
- toggleClass: function(element, selector, condition) {
- if (selector) {
- forEach(selector.split(' '), function(className){
- var classCondition = condition;
- if (isUndefined(classCondition)) {
- classCondition = !jqLiteHasClass(element, className);
- }
- (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
- });
- }
- },
-
- parent: function(element) {
- var parent = element.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
-
- next: function(element) {
- if (element.nextElementSibling) {
- return element.nextElementSibling;
- }
-
- // IE8 doesn't have nextElementSibling
- var elm = element.nextSibling;
- while (elm != null && elm.nodeType !== 1) {
- elm = elm.nextSibling;
- }
- return elm;
- },
-
- find: function(element, selector) {
- if (element.getElementsByTagName) {
- return element.getElementsByTagName(selector);
- } else {
- return [];
- }
- },
-
- clone: jqLiteClone,
-
- triggerHandler: function(element, event, extraParameters) {
-
- var dummyEvent, eventFnsCopy, handlerArgs;
- var eventName = event.type || event;
- var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];
-
- if (eventFns) {
-
- // Create a dummy event to pass to the handlers
- dummyEvent = {
- preventDefault: function() { this.defaultPrevented = true; },
- isDefaultPrevented: function() { return this.defaultPrevented === true; },
- stopPropagation: noop,
- type: eventName,
- target: element
- };
-
- // If a custom event was provided then extend our dummy event with it
- if (event.type) {
- dummyEvent = extend(dummyEvent, event);
- }
-
- // Copy event handlers in case event handlers array is modified during execution.
- eventFnsCopy = shallowCopy(eventFns);
- handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
-
- forEach(eventFnsCopy, function(fn) {
- fn.apply(element, handlerArgs);
- });
-
- }
- }
-}, function(fn, name){
- /**
- * chaining functions
- */
- JQLite.prototype[name] = function(arg1, arg2, arg3) {
- var value;
- for(var i=0; i < this.length; i++) {
- if (isUndefined(value)) {
- value = fn(this[i], arg1, arg2, arg3);
- if (isDefined(value)) {
- // any function which returns a value needs to be wrapped
- value = jqLite(value);
- }
- } else {
- jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
- }
- }
- return isDefined(value) ? value : this;
- };
-
- // bind legacy bind/unbind to on/off
- JQLite.prototype.bind = JQLite.prototype.on;
- JQLite.prototype.unbind = JQLite.prototype.off;
-});
-
-/**
- * Computes a hash of an 'obj'.
- * Hash of a:
- * string is string
- * number is number as string
- * object is either result of calling $$hashKey function on the object or uniquely generated id,
- * that is also assigned to the $$hashKey property of the object.
- *
- * @param obj
- * @returns {string} hash string such that the same input will have the same hash string.
- * The resulting string key is in 'type:hashKey' format.
- */
-function hashKey(obj, nextUidFn) {
- var objType = typeof obj,
- key;
-
- if (objType == 'function' || (objType == 'object' && obj !== null)) {
- if (typeof (key = obj.$$hashKey) == 'function') {
- // must invoke on object to keep the right this
- key = obj.$$hashKey();
- } else if (key === undefined) {
- key = obj.$$hashKey = (nextUidFn || nextUid)();
- }
- } else {
- key = obj;
- }
-
- return objType + ':' + key;
-}
-
-/**
- * HashMap which can use objects as keys
- */
-function HashMap(array, isolatedUid) {
- if (isolatedUid) {
- var uid = 0;
- this.nextUid = function() {
- return ++uid;
- };
- }
- forEach(array, this.put, this);
-}
-HashMap.prototype = {
- /**
- * Store key value pair
- * @param key key to store can be any type
- * @param value value to store can be any type
- */
- put: function(key, value) {
- this[hashKey(key, this.nextUid)] = value;
- },
-
- /**
- * @param key
- * @returns {Object} the value for the key
- */
- get: function(key) {
- return this[hashKey(key, this.nextUid)];
- },
-
- /**
- * Remove the key/value pair
- * @param key
- */
- remove: function(key) {
- var value = this[key = hashKey(key, this.nextUid)];
- delete this[key];
- return value;
- }
-};
-
-/**
- * @ngdoc function
- * @module ng
- * @name angular.injector
- * @kind function
- *
- * @description
- * Creates an injector function that can be used for retrieving services as well as for
- * dependency injection (see {@link guide/di dependency injection}).
- *
-
- * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
- * {@link angular.module}. The `ng` module must be explicitly added.
- * @returns {function()} Injector function. See {@link auto.$injector $injector}.
- *
- * @example
- * Typical usage
- * ```js
- * // create an injector
- * var $injector = angular.injector(['ng']);
- *
- * // use the injector to kick off your application
- * // use the type inference to auto inject arguments, or use implicit injection
- * $injector.invoke(function($rootScope, $compile, $document){
- * $compile($document)($rootScope);
- * $rootScope.$digest();
- * });
- * ```
- *
- * Sometimes you want to get access to the injector of a currently running Angular app
- * from outside Angular. Perhaps, you want to inject and compile some markup after the
- * application has been bootstrapped. You can do this using the extra `injector()` added
- * to JQuery/jqLite elements. See {@link angular.element}.
- *
- * *This is fairly rare but could be the case if a third party library is injecting the
- * markup.*
- *
- * In the following example a new block of HTML containing a `ng-controller`
- * directive is added to the end of the document body by JQuery. We then compile and link
- * it into the current AngularJS scope.
- *
- * ```js
- * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
- * $(document.body).append($div);
- *
- * angular.element(document).injector().invoke(function($compile) {
- * var scope = angular.element($div).scope();
- * $compile($div)(scope);
- * });
- * ```
- */
-
-
-/**
- * @ngdoc module
- * @name auto
- * @description
- *
- * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
- */
-
-var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
-var FN_ARG_SPLIT = /,/;
-var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
-var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
-var $injectorMinErr = minErr('$injector');
-function annotate(fn) {
- var $inject,
- fnText,
- argDecl,
- last;
-
- if (typeof fn === 'function') {
- if (!($inject = fn.$inject)) {
- $inject = [];
- if (fn.length) {
- fnText = fn.toString().replace(STRIP_COMMENTS, '');
- argDecl = fnText.match(FN_ARGS);
- forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
- arg.replace(FN_ARG, function(all, underscore, name){
- $inject.push(name);
- });
- });
- }
- fn.$inject = $inject;
- }
- } else if (isArray(fn)) {
- last = fn.length - 1;
- assertArgFn(fn[last], 'fn');
- $inject = fn.slice(0, last);
- } else {
- assertArgFn(fn, 'fn', true);
- }
- return $inject;
-}
-
-///////////////////////////////////////
-
-/**
- * @ngdoc service
- * @name $injector
- * @kind function
- *
- * @description
- *
- * `$injector` is used to retrieve object instances as defined by
- * {@link auto.$provide provider}, instantiate types, invoke methods,
- * and load modules.
- *
- * The following always holds true:
- *
- * ```js
- * var $injector = angular.injector();
- * expect($injector.get('$injector')).toBe($injector);
- * expect($injector.invoke(function($injector){
- * return $injector;
- * }).toBe($injector);
- * ```
- *
- * # Injection Function Annotation
- *
- * JavaScript does not have annotations, and annotations are needed for dependency injection. The
- * following are all valid ways of annotating function with injection arguments and are equivalent.
- *
- * ```js
- * // inferred (only works if code not minified/obfuscated)
- * $injector.invoke(function(serviceA){});
- *
- * // annotated
- * function explicit(serviceA) {};
- * explicit.$inject = ['serviceA'];
- * $injector.invoke(explicit);
- *
- * // inline
- * $injector.invoke(['serviceA', function(serviceA){}]);
- * ```
- *
- * ## Inference
- *
- * In JavaScript calling `toString()` on a function returns the function definition. The definition
- * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
- * minification, and obfuscation tools since these tools change the argument names.
- *
- * ## `$inject` Annotation
- * By adding an `$inject` property onto a function the injection parameters can be specified.
- *
- * ## Inline
- * As an array of injection names, where the last item in the array is the function to call.
- */
-
-/**
- * @ngdoc method
- * @name $injector#get
- *
- * @description
- * Return an instance of the service.
- *
- * @param {string} name The name of the instance to retrieve.
- * @return {*} The instance.
- */
-
-/**
- * @ngdoc method
- * @name $injector#invoke
- *
- * @description
- * Invoke the method and supply the method arguments from the `$injector`.
- *
- * @param {!Function} fn The function to invoke. Function parameters are injected according to the
- * {@link guide/di $inject Annotation} rules.
- * @param {Object=} self The `this` for the invoked method.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- * object first, before the `$injector` is consulted.
- * @returns {*} the value returned by the invoked `fn` function.
- */
-
-/**
- * @ngdoc method
- * @name $injector#has
- *
- * @description
- * Allows the user to query if the particular service exists.
- *
- * @param {string} Name of the service to query.
- * @returns {boolean} returns true if injector has given service.
- */
-
-/**
- * @ngdoc method
- * @name $injector#instantiate
- * @description
- * Create a new instance of JS type. The method takes a constructor function, invokes the new
- * operator, and supplies all of the arguments to the constructor function as specified by the
- * constructor annotation.
- *
- * @param {Function} Type Annotated constructor function.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- * object first, before the `$injector` is consulted.
- * @returns {Object} new instance of `Type`.
- */
-
-/**
- * @ngdoc method
- * @name $injector#annotate
- *
- * @description
- * Returns an array of service names which the function is requesting for injection. This API is
- * used by the injector to determine which services need to be injected into the function when the
- * function is invoked. There are three ways in which the function can be annotated with the needed
- * dependencies.
- *
- * # Argument names
- *
- * The simplest form is to extract the dependencies from the arguments of the function. This is done
- * by converting the function into a string using `toString()` method and extracting the argument
- * names.
- * ```js
- * // Given
- * function MyController($scope, $route) {
- * // ...
- * }
- *
- * // Then
- * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
- *
- * This method does not work with code minification / obfuscation. For this reason the following
- * annotation strategies are supported.
- *
- * # The `$inject` property
- *
- * If a function has an `$inject` property and its value is an array of strings, then the strings
- * represent names of services to be injected into the function.
- * ```js
- * // Given
- * var MyController = function(obfuscatedScope, obfuscatedRoute) {
- * // ...
- * }
- * // Define function dependencies
- * MyController['$inject'] = ['$scope', '$route'];
- *
- * // Then
- * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * ```
- *
- * # The array notation
- *
- * It is often desirable to inline Injected functions and that's when setting the `$inject` property
- * is very inconvenient. In these situations using the array notation to specify the dependencies in
- * a way that survives minification is a better choice:
- *
- * ```js
- * // We wish to write this (not minification / obfuscation safe)
- * injector.invoke(function($compile, $rootScope) {
- * // ...
- * });
- *
- * // We are forced to write break inlining
- * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
- * // ...
- * };
- * tmpFn.$inject = ['$compile', '$rootScope'];
- * injector.invoke(tmpFn);
- *
- * // To better support inline function the inline annotation is supported
- * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
- * // ...
- * }]);
- *
- * // Therefore
- * expect(injector.annotate(
- * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
- * ).toEqual(['$compile', '$rootScope']);
- * ```
- *
- * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
- * be retrieved as described above.
- *
- * @returns {Array.<string>} The names of the services which the function requires.
- */
-
-
-
-
-/**
- * @ngdoc service
- * @name $provide
- *
- * @description
- *
- * The {@link auto.$provide $provide} service has a number of methods for registering components
- * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
- * {@link angular.Module}.
- *
- * An Angular **service** is a singleton object created by a **service factory**. These **service
- * factories** are functions which, in turn, are created by a **service provider**.
- * The **service providers** are constructor functions. When instantiated they must contain a
- * property called `$get`, which holds the **service factory** function.
- *
- * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
- * correct **service provider**, instantiating it and then calling its `$get` **service factory**
- * function to get the instance of the **service**.
- *
- * Often services have no configuration options and there is no need to add methods to the service
- * provider. The provider will be no more than a constructor function with a `$get` property. For
- * these cases the {@link auto.$provide $provide} service has additional helper methods to register
- * services without specifying a provider.
- *
- * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
- * {@link auto.$injector $injector}
- * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
- * providers and services.
- * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
- * services, not providers.
- * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
- * that will be wrapped in a **service provider** object, whose `$get` property will contain the
- * given factory function.
- * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
- * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
- * a new object using the given constructor function.
- *
- * See the individual methods for more information and examples.
- */
-
-/**
- * @ngdoc method
- * @name $provide#provider
- * @description
- *
- * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
- * are constructor functions, whose instances are responsible for "providing" a factory for a
- * service.
- *
- * Service provider names start with the name of the service they provide followed by `Provider`.
- * For example, the {@link ng.$log $log} service has a provider called
- * {@link ng.$logProvider $logProvider}.
- *
- * Service provider objects can have additional methods which allow configuration of the provider
- * and its service. Importantly, you can configure what kind of service is created by the `$get`
- * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
- * method {@link ng.$logProvider#debugEnabled debugEnabled}
- * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
- * console or not.
- *
- * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
- 'Provider'` key.
- * @param {(Object|function())} provider If the provider is:
- *
- * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
- * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
- * - `Constructor`: a new instance of the provider will be created using
- * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
- *
- * @returns {Object} registered provider instance
-
- * @example
- *
- * The following example shows how to create a simple event tracking service and register it using
- * {@link auto.$provide#provider $provide.provider()}.
- *
- * ```js
- * // Define the eventTracker provider
- * function EventTrackerProvider() {
- * var trackingUrl = '/track';
- *
- * // A provider method for configuring where the tracked events should been saved
- * this.setTrackingUrl = function(url) {
- * trackingUrl = url;
- * };
- *
- * // The service factory function
- * this.$get = ['$http', function($http) {
- * var trackedEvents = {};
- * return {
- * // Call this to track an event
- * event: function(event) {
- * var count = trackedEvents[event] || 0;
- * count += 1;
- * trackedEvents[event] = count;
- * return count;
- * },
- * // Call this to save the tracked events to the trackingUrl
- * save: function() {
- * $http.post(trackingUrl, trackedEvents);
- * }
- * };
- * }];
- * }
- *
- * describe('eventTracker', function() {
- * var postSpy;
- *
- * beforeEach(module(function($provide) {
- * // Register the eventTracker provider
- * $provide.provider('eventTracker', EventTrackerProvider);
- * }));
- *
- * beforeEach(module(function(eventTrackerProvider) {
- * // Configure eventTracker provider
- * eventTrackerProvider.setTrackingUrl('/custom-track');
- * }));
- *
- * it('tracks events', inject(function(eventTracker) {
- * expect(eventTracker.event('login')).toEqual(1);
- * expect(eventTracker.event('login')).toEqual(2);
- * }));
- *
- * it('saves to the tracking url', inject(function(eventTracker, $http) {
- * postSpy = spyOn($http, 'post');
- * eventTracker.event('login');
- * eventTracker.save();
- * expect(postSpy).toHaveBeenCalled();
- * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
- * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
- * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
- * }));
- * });
- * ```
- */
-
-/**
- * @ngdoc method
- * @name $provide#factory
- * @description
- *
- * Register a **service factory**, which will be called to return the service instance.
- * This is short for registering a service where its provider consists of only a `$get` property,
- * which is the given service factory function.
- * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
- * configure your service in a provider.
- *
- * @param {string} name The name of the instance.
- * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
- * for `$provide.provider(name, {$get: $getFn})`.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service
- * ```js
- * $provide.factory('ping', ['$http', function($http) {
- * return function ping() {
- * return $http.send('/ping');
- * };
- * }]);
- * ```
- * You would then inject and use this service like this:
- * ```js
- * someModule.controller('Ctrl', ['ping', function(ping) {
- * ping();
- * }]);
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#service
- * @description
- *
- * Register a **service constructor**, which will be invoked with `new` to create the service
- * instance.
- * This is short for registering a service where its provider's `$get` property is the service
- * constructor function that will be used to instantiate the service instance.
- *
- * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
- * as a type/class.
- *
- * @param {string} name The name of the instance.
- * @param {Function} constructor A class (constructor function) that will be instantiated.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service using
- * {@link auto.$provide#service $provide.service(class)}.
- * ```js
- * var Ping = function($http) {
- * this.$http = $http;
- * };
- *
- * Ping.$inject = ['$http'];
- *
- * Ping.prototype.send = function() {
- * return this.$http.get('/ping');
- * };
- * $provide.service('ping', Ping);
- * ```
- * You would then inject and use this service like this:
- * ```js
- * someModule.controller('Ctrl', ['ping', function(ping) {
- * ping.send();
- * }]);
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#value
- * @description
- *
- * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
- * number, an array, an object or a function. This is short for registering a service where its
- * provider's `$get` property is a factory function that takes no arguments and returns the **value
- * service**.
- *
- * Value services are similar to constant services, except that they cannot be injected into a
- * module configuration function (see {@link angular.Module#config}) but they can be overridden by
- * an Angular
- * {@link auto.$provide#decorator decorator}.
- *
- * @param {string} name The name of the instance.
- * @param {*} value The value.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here are some examples of creating value services.
- * ```js
- * $provide.value('ADMIN_USER', 'admin');
- *
- * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
- *
- * $provide.value('halfOf', function(value) {
- * return value / 2;
- * });
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#constant
- * @description
- *
- * Register a **constant service**, such as a string, a number, an array, an object or a function,
- * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
- * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
- * be overridden by an Angular {@link auto.$provide#decorator decorator}.
- *
- * @param {string} name The name of the constant.
- * @param {*} value The constant value.
- * @returns {Object} registered instance
- *
- * @example
- * Here a some examples of creating constants:
- * ```js
- * $provide.constant('SHARD_HEIGHT', 306);
- *
- * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
- *
- * $provide.constant('double', function(value) {
- * return value * 2;
- * });
- * ```
- */
-
-
-/**
- * @ngdoc method
- * @name $provide#decorator
- * @description
- *
- * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
- * intercepts the creation of a service, allowing it to override or modify the behaviour of the
- * service. The object returned by the decorator may be the original service, or a new service
- * object which replaces or wraps and delegates to the original service.
- *
- * @param {string} name The name of the service to decorate.
- * @param {function()} decorator This function will be invoked when the service needs to be
- * instantiated and should return the decorated service instance. The function is called using
- * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
- * Local injection arguments:
- *
- * * `$delegate` - The original service instance, which can be monkey patched, configured,
- * decorated or delegated to.
- *
- * @example
- * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
- * calls to {@link ng.$log#error $log.warn()}.
- * ```js
- * $provide.decorator('$log', ['$delegate', function($delegate) {
- * $delegate.warn = $delegate.error;
- * return $delegate;
- * }]);
- * ```
- */
-
-
-function createInjector(modulesToLoad) {
- var INSTANTIATING = {},
- providerSuffix = 'Provider',
- path = [],
- loadedModules = new HashMap([], true),
- providerCache = {
- $provide: {
- provider: supportObject(provider),
- factory: supportObject(factory),
- service: supportObject(service),
- value: supportObject(value),
- constant: supportObject(constant),
- decorator: decorator
- }
- },
- providerInjector = (providerCache.$injector =
- createInternalInjector(providerCache, function() {
- throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
- })),
- instanceCache = {},
- instanceInjector = (instanceCache.$injector =
- createInternalInjector(instanceCache, function(servicename) {
- var provider = providerInjector.get(servicename + providerSuffix);
- return instanceInjector.invoke(provider.$get, provider);
- }));
-
-
- forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
-
- return instanceInjector;
-
- ////////////////////////////////////
- // $provider
- ////////////////////////////////////
-
- function supportObject(delegate) {
- return function(key, value) {
- if (isObject(key)) {
- forEach(key, reverseParams(delegate));
- } else {
- return delegate(key, value);
- }
- };
- }
-
- function provider(name, provider_) {
- assertNotHasOwnProperty(name, 'service');
- if (isFunction(provider_) || isArray(provider_)) {
- provider_ = providerInjector.instantiate(provider_);
- }
- if (!provider_.$get) {
- throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
- }
- return providerCache[name + providerSuffix] = provider_;
- }
-
- function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
-
- function service(name, constructor) {
- return factory(name, ['$injector', function($injector) {
- return $injector.instantiate(constructor);
- }]);
- }
-
- function value(name, val) { return factory(name, valueFn(val)); }
-
- function constant(name, value) {
- assertNotHasOwnProperty(name, 'constant');
- providerCache[name] = value;
- instanceCache[name] = value;
- }
-
- function decorator(serviceName, decorFn) {
- var origProvider = providerInjector.get(serviceName + providerSuffix),
- orig$get = origProvider.$get;
-
- origProvider.$get = function() {
- var origInstance = instanceInjector.invoke(orig$get, origProvider);
- return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
- };
- }
-
- ////////////////////////////////////
- // Module Loading
- ////////////////////////////////////
- function loadModules(modulesToLoad){
- var runBlocks = [], moduleFn, invokeQueue, i, ii;
- forEach(modulesToLoad, function(module) {
- if (loadedModules.get(module)) return;
- loadedModules.put(module, true);
-
- try {
- if (isString(module)) {
- moduleFn = angularModule(module);
- runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
-
- for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
- var invokeArgs = invokeQueue[i],
- provider = providerInjector.get(invokeArgs[0]);
-
- provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
- }
- } else if (isFunction(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else if (isArray(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else {
- assertArgFn(module, 'module');
- }
- } catch (e) {
- if (isArray(module)) {
- module = module[module.length - 1];
- }
- if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
- // Safari & FF's stack traces don't contain error.message content
- // unlike those of Chrome and IE
- // So if stack doesn't contain message, we create a new string that contains both.
- // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
- /* jshint -W022 */
- e = e.message + '\n' + e.stack;
- }
- throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
- module, e.stack || e.message || e);
- }
- });
- return runBlocks;
- }
-
- ////////////////////////////////////
- // internal Injector
- ////////////////////////////////////
-
- function createInternalInjector(cache, factory) {
-
- function getService(serviceName) {
- if (cache.hasOwnProperty(serviceName)) {
- if (cache[serviceName] === INSTANTIATING) {
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
- serviceName + ' <- ' + path.join(' <- '));
- }
- return cache[serviceName];
- } else {
- try {
- path.unshift(serviceName);
- cache[serviceName] = INSTANTIATING;
- return cache[serviceName] = factory(serviceName);
- } catch (err) {
- if (cache[serviceName] === INSTANTIATING) {
- delete cache[serviceName];
- }
- throw err;
- } finally {
- path.shift();
- }
- }
- }
-
- function invoke(fn, self, locals){
- var args = [],
- $inject = annotate(fn),
- length, i,
- key;
-
- for(i = 0, length = $inject.length; i < length; i++) {
- key = $inject[i];
- if (typeof key !== 'string') {
- throw $injectorMinErr('itkn',
- 'Incorrect injection token! Expected service name as string, got {0}', key);
- }
- args.push(
- locals && locals.hasOwnProperty(key)
- ? locals[key]
- : getService(key)
- );
- }
- if (isArray(fn)) {
- fn = fn[length];
- }
-
- // http://jsperf.com/angularjs-invoke-apply-vs-switch
- // #5388
- return fn.apply(self, args);
- }
-
- function instantiate(Type, locals) {
- var Constructor = function() {},
- instance, returnedValue;
-
- // Check if Type is annotated and use just the given function at n-1 as parameter
- // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
- Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
- instance = new Constructor();
- returnedValue = invoke(Type, instance, locals);
-
- return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
- }
-
- return {
- invoke: invoke,
- instantiate: instantiate,
- get: getService,
- annotate: annotate,
- has: function(name) {
- return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
- }
- };
- }
-}
-
-/**
- * @ngdoc service
- * @name $anchorScroll
- * @kind function
- * @requires $window
- * @requires $location
- * @requires $rootScope
- *
- * @description
- * When called, it checks current value of `$location.hash()` and scrolls to the related element,
- * according to rules specified in
- * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
- *
- * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
- * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
- *
- * @example
- <example>
- <file name="index.html">
- <div id="scrollArea" ng-controller="ScrollCtrl">
- <a ng-click="gotoBottom()">Go to bottom</a>
- <a id="bottom"></a> You're at the bottom!
- </div>
- </file>
- <file name="script.js">
- function ScrollCtrl($scope, $location, $anchorScroll) {
- $scope.gotoBottom = function (){
- // set the location.hash to the id of
- // the element you wish to scroll to.
- $location.hash('bottom');
-
- // call $anchorScroll()
- $anchorScroll();
- };
- }
- </file>
- <file name="style.css">
- #scrollArea {
- height: 350px;
- overflow: auto;
- }
-
- #bottom {
- display: block;
- margin-top: 2000px;
- }
- </file>
- </example>
- */
-function $AnchorScrollProvider() {
-
- var autoScrollingEnabled = true;
-
- this.disableAutoScrolling = function() {
- autoScrollingEnabled = false;
- };
-
- this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
- var document = $window.document;
-
- // helper function to get first anchor from a NodeList
- // can't use filter.filter, as it accepts only instances of Array
- // and IE can't convert NodeList to an array using [].slice
- // TODO(vojta): use filter if we change it to accept lists as well
- function getFirstAnchor(list) {
- var result = null;
- forEach(list, function(element) {
- if (!result && lowercase(element.nodeName) === 'a') result = element;
- });
- return result;
- }
-
- function scroll() {
- var hash = $location.hash(), elm;
-
- // empty hash, scroll to the top of the page
- if (!hash) $window.scrollTo(0, 0);
-
- // element with given id
- else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
-
- // first anchor with given name :-D
- else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
-
- // no element and hash == 'top', scroll to the top of the page
- else if (hash === 'top') $window.scrollTo(0, 0);
- }
-
- // does not scroll when user clicks on anchor link that is currently on
- // (no url change, no $location.hash() change), browser native does scroll
- if (autoScrollingEnabled) {
- $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
- function autoScrollWatchAction() {
- $rootScope.$evalAsync(scroll);
- });
- }
-
- return scroll;
- }];
-}
-
-var $animateMinErr = minErr('$animate');
-
-/**
- * @ngdoc provider
- * @name $animateProvider
- *
- * @description
- * Default implementation of $animate that doesn't perform any animations, instead just
- * synchronously performs DOM
- * updates and calls done() callbacks.
- *
- * In order to enable animations the ngAnimate module has to be loaded.
- *
- * To see the functional implementation check out src/ngAnimate/animate.js
- */
-var $AnimateProvider = ['$provide', function($provide) {
-
-
- this.$$selectors = {};
-
-
- /**
- * @ngdoc method
- * @name $animateProvider#register
- *
- * @description
- * Registers a new injectable animation factory function. The factory function produces the
- * animation object which contains callback functions for each event that is expected to be
- * animated.
- *
- * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
- * must be called once the element animation is complete. If a function is returned then the
- * animation service will use this function to cancel the animation whenever a cancel event is
- * triggered.
- *
- *
- * ```js
- * return {
- * eventFn : function(element, done) {
- * //code to run the animation
- * //once complete, then run done()
- * return function cancellationFunction() {
- * //code to cancel the animation
- * }
- * }
- * }
- * ```
- *
- * @param {string} name The name of the animation.
- * @param {Function} factory The factory function that will be executed to return the animation
- * object.
- */
- this.register = function(name, factory) {
- var key = name + '-animation';
- if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
- "Expecting class selector starting with '.' got '{0}'.", name);
- this.$$selectors[name.substr(1)] = key;
- $provide.factory(key, factory);
- };
-
- /**
- * @ngdoc method
- * @name $animateProvider#classNameFilter
- *
- * @description
- * Sets and/or returns the CSS class regular expression that is checked when performing
- * an animation. Upon bootstrap the classNameFilter value is not set at all and will
- * therefore enable $animate to attempt to perform an animation on any element.
- * When setting the classNameFilter value, animations will only be performed on elements
- * that successfully match the filter expression. This in turn can boost performance
- * for low-powered devices as well as applications containing a lot of structural operations.
- * @param {RegExp=} expression The className expression which will be checked against all animations
- * @return {RegExp} The current CSS className expression value. If null then there is no expression value
- */
- this.classNameFilter = function(expression) {
- if(arguments.length === 1) {
- this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
- }
- return this.$$classNameFilter;
- };
-
- this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {
-
- function async(fn) {
- fn && $$asyncCallback(fn);
- }
-
- /**
- *
- * @ngdoc service
- * @name $animate
- * @description The $animate service provides rudimentary DOM manipulation functions to
- * insert, remove and move elements within the DOM, as well as adding and removing classes.
- * This service is the core service used by the ngAnimate $animator service which provides
- * high-level animation hooks for CSS and JavaScript.
- *
- * $animate is available in the AngularJS core, however, the ngAnimate module must be included
- * to enable full out animation support. Otherwise, $animate will only perform simple DOM
- * manipulation operations.
- *
- * To learn more about enabling animation support, click here to visit the {@link ngAnimate
- * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
- * page}.
- */
- return {
-
- /**
- *
- * @ngdoc method
- * @name $animate#enter
- * @kind function
- * @description Inserts the element into the DOM either after the `after` element or within
- * the `parent` element. Once complete, the done() callback will be fired (if provided).
- * @param {DOMElement} element the element which will be inserted into the DOM
- * @param {DOMElement} parent the parent element which will append the element as
- * a child (if the after element is not present)
- * @param {DOMElement} after the sibling element which will append the element
- * after itself
- * @param {Function=} done callback function that will be called after the element has been
- * inserted into the DOM
- */
- enter : function(element, parent, after, done) {
- if (after) {
- after.after(element);
- } else {
- if (!parent || !parent[0]) {
- parent = after.parent();
- }
- parent.append(element);
- }
- async(done);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#leave
- * @kind function
- * @description Removes the element from the DOM. Once complete, the done() callback will be
- * fired (if provided).
- * @param {DOMElement} element the element which will be removed from the DOM
- * @param {Function=} done callback function that will be called after the element has been
- * removed from the DOM
- */
- leave : function(element, done) {
- element.remove();
- async(done);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#move
- * @kind function
- * @description Moves the position of the provided element within the DOM to be placed
- * either after the `after` element or inside of the `parent` element. Once complete, the
- * done() callback will be fired (if provided).
- *
- * @param {DOMElement} element the element which will be moved around within the
- * DOM
- * @param {DOMElement} parent the parent element where the element will be
- * inserted into (if the after element is not present)
- * @param {DOMElement} after the sibling element where the element will be
- * positioned next to
- * @param {Function=} done the callback function (if provided) that will be fired after the
- * element has been moved to its new position
- */
- move : function(element, parent, after, done) {
- // Do not remove element before insert. Removing will cause data associated with the
- // element to be dropped. Insert will implicitly do the remove.
- this.enter(element, parent, after, done);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#addClass
- * @kind function
- * @description Adds the provided className CSS class value to the provided element. Once
- * complete, the done() callback will be fired (if provided).
- * @param {DOMElement} element the element which will have the className value
- * added to it
- * @param {string} className the CSS class which will be added to the element
- * @param {Function=} done the callback function (if provided) that will be fired after the
- * className value has been added to the element
- */
- addClass : function(element, className, done) {
- className = isString(className) ?
- className :
- isArray(className) ? className.join(' ') : '';
- forEach(element, function (element) {
- jqLiteAddClass(element, className);
- });
- async(done);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#removeClass
- * @kind function
- * @description Removes the provided className CSS class value from the provided element.
- * Once complete, the done() callback will be fired (if provided).
- * @param {DOMElement} element the element which will have the className value
- * removed from it
- * @param {string} className the CSS class which will be removed from the element
- * @param {Function=} done the callback function (if provided) that will be fired after the
- * className value has been removed from the element
- */
- removeClass : function(element, className, done) {
- className = isString(className) ?
- className :
- isArray(className) ? className.join(' ') : '';
- forEach(element, function (element) {
- jqLiteRemoveClass(element, className);
- });
- async(done);
- },
-
- /**
- *
- * @ngdoc method
- * @name $animate#setClass
- * @kind function
- * @description Adds and/or removes the given CSS classes to and from the element.
- * Once complete, the done() callback will be fired (if provided).
- * @param {DOMElement} element the element which will have its CSS classes changed
- * removed from it
- * @param {string} add the CSS classes which will be added to the element
- * @param {string} remove the CSS class which will be removed from the element
- * @param {Function=} done the callback function (if provided) that will be fired after the
- * CSS classes have been set on the element
- */
- setClass : function(element, add, remove, done) {
- forEach(element, function (element) {
- jqLiteAddClass(element, add);
- jqLiteRemoveClass(element, remove);
- });
- async(done);
- },
-
- enabled : noop
- };
- }];
-}];
-
-function $$AsyncCallbackProvider(){
- this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
- return $$rAF.supported
- ? function(fn) { return $$rAF(fn); }
- : function(fn) {
- return $timeout(fn, 0, false);
- };
- }];
-}
-
-/**
- * ! This is a private undocumented service !
- *
- * @name $browser
- * @requires $log
- * @description
- * This object has two goals:
- *
- * - hide all the global state in the browser caused by the window object
- * - abstract away all the browser specific features and inconsistencies
- *
- * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
- * service, which can be used for convenient testing of the application without the interaction with
- * the real browser apis.
- */
-/**
- * @param {object} window The global window object.
- * @param {object} document jQuery wrapped document.
- * @param {function()} XHR XMLHttpRequest constructor.
- * @param {object} $log console.log or an object with the same interface.
- * @param {object} $sniffer $sniffer service
- */
-function Browser(window, document, $log, $sniffer) {
- var self = this,
- rawDocument = document[0],
- location = window.location,
- history = window.history,
- setTimeout = window.setTimeout,
- clearTimeout = window.clearTimeout,
- pendingDeferIds = {};
-
- self.isMock = false;
-
- var outstandingRequestCount = 0;
- var outstandingRequestCallbacks = [];
-
- // TODO(vojta): remove this temporary api
- self.$$completeOutstandingRequest = completeOutstandingRequest;
- self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
-
- /**
- * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
- * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
- */
- function completeOutstandingRequest(fn) {
- try {
- fn.apply(null, sliceArgs(arguments, 1));
- } finally {
- outstandingRequestCount--;
- if (outstandingRequestCount === 0) {
- while(outstandingRequestCallbacks.length) {
- try {
- outstandingRequestCallbacks.pop()();
- } catch (e) {
- $log.error(e);
- }
- }
- }
- }
- }
-
- /**
- * @private
- * Note: this method is used only by scenario runner
- * TODO(vojta): prefix this method with $$ ?
- * @param {function()} callback Function that will be called when no outstanding request
- */
- self.notifyWhenNoOutstandingRequests = function(callback) {
- // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
- // at some deterministic time in respect to the test runner's actions. Leaving things up to the
- // regular poller would result in flaky tests.
- forEach(pollFns, function(pollFn){ pollFn(); });
-
- if (outstandingRequestCount === 0) {
- callback();
- } else {
- outstandingRequestCallbacks.push(callback);
- }
- };
-
- //////////////////////////////////////////////////////////////
- // Poll Watcher API
- //////////////////////////////////////////////////////////////
- var pollFns = [],
- pollTimeout;
-
- /**
- * @name $browser#addPollFn
- *
- * @param {function()} fn Poll function to add
- *
- * @description
- * Adds a function to the list of functions that poller periodically executes,
- * and starts polling if not started yet.
- *
- * @returns {function()} the added function
- */
- self.addPollFn = function(fn) {
- if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
- pollFns.push(fn);
- return fn;
- };
-
- /**
- * @param {number} interval How often should browser call poll functions (ms)
- * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
- *
- * @description
- * Configures the poller to run in the specified intervals, using the specified
- * setTimeout fn and kicks it off.
- */
- function startPoller(interval, setTimeout) {
- (function check() {
- forEach(pollFns, function(pollFn){ pollFn(); });
- pollTimeout = setTimeout(check, interval);
- })();
- }
-
- //////////////////////////////////////////////////////////////
- // URL API
- //////////////////////////////////////////////////////////////
-
- var lastBrowserUrl = location.href,
- baseElement = document.find('base'),
- newLocation = null;
-
- /**
- * @name $browser#url
- *
- * @description
- * GETTER:
- * Without any argument, this method just returns current value of location.href.
- *
- * SETTER:
- * With at least one argument, this method sets url to new value.
- * If html5 history api supported, pushState/replaceState is used, otherwise
- * location.href/location.replace is used.
- * Returns its own instance to allow chaining
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link ng.$location $location service} to change url.
- *
- * @param {string} url New url (when used as setter)
- * @param {boolean=} replace Should new url replace current history record ?
- */
- self.url = function(url, replace) {
- // Android Browser BFCache causes location, history reference to become stale.
- if (location !== window.location) location = window.location;
- if (history !== window.history) history = window.history;
-
- // setter
- if (url) {
- if (lastBrowserUrl == url) return;
- lastBrowserUrl = url;
- if ($sniffer.history) {
- if (replace) history.replaceState(null, '', url);
- else {
- history.pushState(null, '', url);
- // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462
- baseElement.attr('href', baseElement.attr('href'));
- }
- } else {
- newLocation = url;
- if (replace) {
- location.replace(url);
- } else {
- location.href = url;
- }
- }
- return self;
- // getter
- } else {
- // - newLocation is a workaround for an IE7-9 issue with location.replace and location.href
- // methods not updating location.href synchronously.
- // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
- return newLocation || location.href.replace(/%27/g,"'");
- }
- };
-
- var urlChangeListeners = [],
- urlChangeInit = false;
-
- function fireUrlChange() {
- newLocation = null;
- if (lastBrowserUrl == self.url()) return;
-
- lastBrowserUrl = self.url();
- forEach(urlChangeListeners, function(listener) {
- listener(self.url());
- });
- }
-
- /**
- * @name $browser#onUrlChange
- *
- * @description
- * Register callback function that will be called, when url changes.
- *
- * It's only called when the url is changed from outside of angular:
- * - user types different url into address bar
- * - user clicks on history (forward/back) button
- * - user clicks on a link
- *
- * It's not called when url is changed by $browser.url() method
- *
- * The listener gets called with new url as parameter.
- *
- * NOTE: this api is intended for use only by the $location service. Please use the
- * {@link ng.$location $location service} to monitor url changes in angular apps.
- *
- * @param {function(string)} listener Listener function to be called when url changes.
- * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
- */
- self.onUrlChange = function(callback) {
- // TODO(vojta): refactor to use node's syntax for events
- if (!urlChangeInit) {
- // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
- // don't fire popstate when user change the address bar and don't fire hashchange when url
- // changed by push/replaceState
-
- // html5 history api - popstate event
- if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
- // hashchange event
- if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
- // polling
- else self.addPollFn(fireUrlChange);
-
- urlChangeInit = true;
- }
-
- urlChangeListeners.push(callback);
- return callback;
- };
-
- /**
- * Checks whether the url has changed outside of Angular.
- * Needs to be exported to be able to check for changes that have been done in sync,
- * as hashchange/popstate events fire in async.
- */
- self.$$checkUrlChange = fireUrlChange;
-
- //////////////////////////////////////////////////////////////
- // Misc API
- //////////////////////////////////////////////////////////////
-
- /**
- * @name $browser#baseHref
- *
- * @description
- * Returns current <base href>
- * (always relative - without domain)
- *
- * @returns {string} The current base href
- */
- self.baseHref = function() {
- var href = baseElement.attr('href');
- return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
- };
-
- //////////////////////////////////////////////////////////////
- // Cookies API
- //////////////////////////////////////////////////////////////
- var lastCookies = {};
- var lastCookieString = '';
- var cookiePath = self.baseHref();
-
- /**
- * @name $browser#cookies
- *
- * @param {string=} name Cookie name
- * @param {string=} value Cookie value
- *
- * @description
- * The cookies method provides a 'private' low level access to browser cookies.
- * It is not meant to be used directly, use the $cookie service instead.
- *
- * The return values vary depending on the arguments that the method was called with as follows:
- *
- * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
- * it
- * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
- * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
- * way)
- *
- * @returns {Object} Hash of all cookies (if called without any parameter)
- */
- self.cookies = function(name, value) {
- /* global escape: false, unescape: false */
- var cookieLength, cookieArray, cookie, i, index;
-
- if (name) {
- if (value === undefined) {
- rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
- ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
- } else {
- if (isString(value)) {
- cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
- ';path=' + cookiePath).length + 1;
-
- // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
- // - 300 cookies
- // - 20 cookies per unique domain
- // - 4096 bytes per cookie
- if (cookieLength > 4096) {
- $log.warn("Cookie '"+ name +
- "' possibly not set or overflowed because it was too large ("+
- cookieLength + " > 4096 bytes)!");
- }
- }
- }
- } else {
- if (rawDocument.cookie !== lastCookieString) {
- lastCookieString = rawDocument.cookie;
- cookieArray = lastCookieString.split("; ");
- lastCookies = {};
-
- for (i = 0; i < cookieArray.length; i++) {
- cookie = cookieArray[i];
- index = cookie.indexOf('=');
- if (index > 0) { //ignore nameless cookies
- name = unescape(cookie.substring(0, index));
- // the first value that is seen for a cookie is the most
- // specific one. values for the same cookie name that
- // follow are for less specific paths.
- if (lastCookies[name] === undefined) {
- lastCookies[name] = unescape(cookie.substring(index + 1));
- }
- }
- }
- }
- return lastCookies;
- }
- };
-
-
- /**
- * @name $browser#defer
- * @param {function()} fn A function, who's execution should be deferred.
- * @param {number=} [delay=0] of milliseconds to defer the function execution.
- * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
- *
- * @description
- * Executes a fn asynchronously via `setTimeout(fn, delay)`.
- *
- * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
- * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
- * via `$browser.defer.flush()`.
- *
- */
- self.defer = function(fn, delay) {
- var timeoutId;
- outstandingRequestCount++;
- timeoutId = setTimeout(function() {
- delete pendingDeferIds[timeoutId];
- completeOutstandingRequest(fn);
- }, delay || 0);
- pendingDeferIds[timeoutId] = true;
- return timeoutId;
- };
-
-
- /**
- * @name $browser#defer.cancel
- *
- * @description
- * Cancels a deferred task identified with `deferId`.
- *
- * @param {*} deferId Token returned by the `$browser.defer` function.
- * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
- * canceled.
- */
- self.defer.cancel = function(deferId) {
- if (pendingDeferIds[deferId]) {
- delete pendingDeferIds[deferId];
- clearTimeout(deferId);
- completeOutstandingRequest(noop);
- return true;
- }
- return false;
- };
-
-}
-
-function $BrowserProvider(){
- this.$get = ['$window', '$log', '$sniffer', '$document',
- function( $window, $log, $sniffer, $document){
- return new Browser($window, $document, $log, $sniffer);
- }];
-}
-
-/**
- * @ngdoc service
- * @name $cacheFactory
- *
- * @description
- * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
- * them.
- *
- * ```js
- *
- * var cache = $cacheFactory('cacheId');
- * expect($cacheFactory.get('cacheId')).toBe(cache);
- * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
- *
- * cache.put("key", "value");
- * cache.put("another key", "another value");
- *
- * // We've specified no options on creation
- * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
- *
- * ```
- *
- *
- * @param {string} cacheId Name or id of the newly created cache.
- * @param {object=} options Options object that specifies the cache behavior. Properties:
- *
- * - `{number=}` `capacity` — turns the cache into LRU cache.
- *
- * @returns {object} Newly created cache object with the following set of methods:
- *
- * - `{object}` `info()` — Returns id, size, and options of cache.
- * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
- * it.
- * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
- * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
- * - `{void}` `removeAll()` — Removes all cached values.
- * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
- *
- * @example
- <example module="cacheExampleApp">
- <file name="index.html">
- <div ng-controller="CacheController">
- <input ng-model="newCacheKey" placeholder="Key">
- <input ng-model="newCacheValue" placeholder="Value">
- <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
-
- <p ng-if="keys.length">Cached Values</p>
- <div ng-repeat="key in keys">
- <span ng-bind="key"></span>
- <span>: </span>
- <b ng-bind="cache.get(key)"></b>
- </div>
-
- <p>Cache Info</p>
- <div ng-repeat="(key, value) in cache.info()">
- <span ng-bind="key"></span>
- <span>: </span>
- <b ng-bind="value"></b>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('cacheExampleApp', []).
- controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
- $scope.keys = [];
- $scope.cache = $cacheFactory('cacheId');
- $scope.put = function(key, value) {
- if ($scope.cache.get(key) === undefined) {
- $scope.keys.push(key);
- }
- $scope.cache.put(key, value === undefined ? null : value);
- };
- }]);
- </file>
- <file name="style.css">
- p {
- margin: 10px 0 3px;
- }
- </file>
- </example>
- */
-function $CacheFactoryProvider() {
-
- this.$get = function() {
- var caches = {};
-
- function cacheFactory(cacheId, options) {
- if (cacheId in caches) {
- throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
- }
-
- var size = 0,
- stats = extend({}, options, {id: cacheId}),
- data = {},
- capacity = (options && options.capacity) || Number.MAX_VALUE,
- lruHash = {},
- freshEnd = null,
- staleEnd = null;
-
- /**
- * @ngdoc type
- * @name $cacheFactory.Cache
- *
- * @description
- * A cache object used to store and retrieve data, primarily used by
- * {@link $http $http} and the {@link ng.directive:script script} directive to cache
- * templates and other data.
- *
- * ```js
- * angular.module('superCache')
- * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
- * return $cacheFactory('super-cache');
- * }]);
- * ```
- *
- * Example test:
- *
- * ```js
- * it('should behave like a cache', inject(function(superCache) {
- * superCache.put('key', 'value');
- * superCache.put('another key', 'another value');
- *
- * expect(superCache.info()).toEqual({
- * id: 'super-cache',
- * size: 2
- * });
- *
- * superCache.remove('another key');
- * expect(superCache.get('another key')).toBeUndefined();
- *
- * superCache.removeAll();
- * expect(superCache.info()).toEqual({
- * id: 'super-cache',
- * size: 0
- * });
- * }));
- * ```
- */
- return caches[cacheId] = {
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#put
- * @kind function
- *
- * @description
- * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
- * retrieved later, and incrementing the size of the cache if the key was not already
- * present in the cache. If behaving like an LRU cache, it will also remove stale
- * entries from the set.
- *
- * It will not insert undefined values into the cache.
- *
- * @param {string} key the key under which the cached data is stored.
- * @param {*} value the value to store alongside the key. If it is undefined, the key
- * will not be stored.
- * @returns {*} the value stored.
- */
- put: function(key, value) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
-
- refresh(lruEntry);
- }
-
- if (isUndefined(value)) return;
- if (!(key in data)) size++;
- data[key] = value;
-
- if (size > capacity) {
- this.remove(staleEnd.key);
- }
-
- return value;
- },
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#get
- * @kind function
- *
- * @description
- * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
- *
- * @param {string} key the key of the data to be retrieved
- * @returns {*} the value stored.
- */
- get: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
-
- if (!lruEntry) return;
-
- refresh(lruEntry);
- }
-
- return data[key];
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#remove
- * @kind function
- *
- * @description
- * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
- *
- * @param {string} key the key of the entry to be removed
- */
- remove: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
-
- if (!lruEntry) return;
-
- if (lruEntry == freshEnd) freshEnd = lruEntry.p;
- if (lruEntry == staleEnd) staleEnd = lruEntry.n;
- link(lruEntry.n,lruEntry.p);
-
- delete lruHash[key];
- }
-
- delete data[key];
- size--;
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#removeAll
- * @kind function
- *
- * @description
- * Clears the cache object of any entries.
- */
- removeAll: function() {
- data = {};
- size = 0;
- lruHash = {};
- freshEnd = staleEnd = null;
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#destroy
- * @kind function
- *
- * @description
- * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
- * removing it from the {@link $cacheFactory $cacheFactory} set.
- */
- destroy: function() {
- data = null;
- stats = null;
- lruHash = null;
- delete caches[cacheId];
- },
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory.Cache#info
- * @kind function
- *
- * @description
- * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
- *
- * @returns {object} an object with the following properties:
- * <ul>
- * <li>**id**: the id of the cache instance</li>
- * <li>**size**: the number of entries kept in the cache instance</li>
- * <li>**...**: any additional properties from the options object when creating the
- * cache.</li>
- * </ul>
- */
- info: function() {
- return extend({}, stats, {size: size});
- }
- };
-
-
- /**
- * makes the `entry` the freshEnd of the LRU linked list
- */
- function refresh(entry) {
- if (entry != freshEnd) {
- if (!staleEnd) {
- staleEnd = entry;
- } else if (staleEnd == entry) {
- staleEnd = entry.n;
- }
-
- link(entry.n, entry.p);
- link(entry, freshEnd);
- freshEnd = entry;
- freshEnd.n = null;
- }
- }
-
-
- /**
- * bidirectionally links two entries of the LRU linked list
- */
- function link(nextEntry, prevEntry) {
- if (nextEntry != prevEntry) {
- if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
- if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
- }
- }
- }
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory#info
- *
- * @description
- * Get information about all the caches that have been created
- *
- * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
- */
- cacheFactory.info = function() {
- var info = {};
- forEach(caches, function(cache, cacheId) {
- info[cacheId] = cache.info();
- });
- return info;
- };
-
-
- /**
- * @ngdoc method
- * @name $cacheFactory#get
- *
- * @description
- * Get access to a cache object by the `cacheId` used when it was created.
- *
- * @param {string} cacheId Name or id of a cache to access.
- * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
- */
- cacheFactory.get = function(cacheId) {
- return caches[cacheId];
- };
-
-
- return cacheFactory;
- };
-}
-
-/**
- * @ngdoc service
- * @name $templateCache
- *
- * @description
- * The first time a template is used, it is loaded in the template cache for quick retrieval. You
- * can load templates directly into the cache in a `script` tag, or by consuming the
- * `$templateCache` service directly.
- *
- * Adding via the `script` tag:
- *
- * ```html
- * <script type="text/ng-template" id="templateId.html">
- * <p>This is the content of the template</p>
- * </script>
- * ```
- *
- * **Note:** the `script` tag containing the template does not need to be included in the `head` of
- * the document, but it must be below the `ng-app` definition.
- *
- * Adding via the $templateCache service:
- *
- * ```js
- * var myApp = angular.module('myApp', []);
- * myApp.run(function($templateCache) {
- * $templateCache.put('templateId.html', 'This is the content of the template');
- * });
- * ```
- *
- * To retrieve the template later, simply use it in your HTML:
- * ```html
- * <div ng-include=" 'templateId.html' "></div>
- * ```
- *
- * or get it via Javascript:
- * ```js
- * $templateCache.get('templateId.html')
- * ```
- *
- * See {@link ng.$cacheFactory $cacheFactory}.
- *
- */
-function $TemplateCacheProvider() {
- this.$get = ['$cacheFactory', function($cacheFactory) {
- return $cacheFactory('templates');
- }];
-}
-
-/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
- *
- * DOM-related variables:
- *
- * - "node" - DOM Node
- * - "element" - DOM Element or Node
- * - "$node" or "$element" - jqLite-wrapped node or element
- *
- *
- * Compiler related stuff:
- *
- * - "linkFn" - linking fn of a single directive
- * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
- * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
- * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
- */
-
-
-/**
- * @ngdoc service
- * @name $compile
- * @kind function
- *
- * @description
- * Compiles an HTML string or DOM into a template and produces a template function, which
- * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
- *
- * The compilation is a process of walking the DOM tree and matching DOM elements to
- * {@link ng.$compileProvider#directive directives}.
- *
- * <div class="alert alert-warning">
- * **Note:** This document is an in-depth reference of all directive options.
- * For a gentle introduction to directives with examples of common use cases,
- * see the {@link guide/directive directive guide}.
- * </div>
- *
- * ## Comprehensive Directive API
- *
- * There are many different options for a directive.
- *
- * The difference resides in the return value of the factory function.
- * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
- * or just the `postLink` function (all other properties will have the default values).
- *
- * <div class="alert alert-success">
- * **Best Practice:** It's recommended to use the "directive definition object" form.
- * </div>
- *
- * Here's an example directive declared with a Directive Definition Object:
- *
- * ```js
- * var myModule = angular.module(...);
- *
- * myModule.directive('directiveName', function factory(injectables) {
- * var directiveDefinitionObject = {
- * priority: 0,
- * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
- * // or
- * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
- * transclude: false,
- * restrict: 'A',
- * scope: false,
- * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
- * controllerAs: 'stringAlias',
- * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
- * compile: function compile(tElement, tAttrs, transclude) {
- * return {
- * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- * post: function postLink(scope, iElement, iAttrs, controller) { ... }
- * }
- * // or
- * // return function postLink( ... ) { ... }
- * },
- * // or
- * // link: {
- * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
- * // }
- * // or
- * // link: function postLink( ... ) { ... }
- * };
- * return directiveDefinitionObject;
- * });
- * ```
- *
- * <div class="alert alert-warning">
- * **Note:** Any unspecified options will use the default value. You can see the default values below.
- * </div>
- *
- * Therefore the above can be simplified as:
- *
- * ```js
- * var myModule = angular.module(...);
- *
- * myModule.directive('directiveName', function factory(injectables) {
- * var directiveDefinitionObject = {
- * link: function postLink(scope, iElement, iAttrs) { ... }
- * };
- * return directiveDefinitionObject;
- * // or
- * // return function postLink(scope, iElement, iAttrs) { ... }
- * });
- * ```
- *
- *
- *
- * ### Directive Definition Object
- *
- * The directive definition object provides instructions to the {@link ng.$compile
- * compiler}. The attributes are:
- *
- * #### `priority`
- * When there are multiple directives defined on a single DOM element, sometimes it
- * is necessary to specify the order in which the directives are applied. The `priority` is used
- * to sort the directives before their `compile` functions get called. Priority is defined as a
- * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
- * are also run in priority order, but post-link functions are run in reverse order. The order
- * of directives with the same priority is undefined. The default priority is `0`.
- *
- * #### `terminal`
- * If set to true then the current `priority` will be the last set of directives
- * which will execute (any directives at the current priority will still execute
- * as the order of execution on same `priority` is undefined).
- *
- * #### `scope`
- * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
- * same element request a new scope, only one new scope is created. The new scope rule does not
- * apply for the root of the template since the root of the template always gets a new scope.
- *
- * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
- * normal scope in that it does not prototypically inherit from the parent scope. This is useful
- * when creating reusable components, which should not accidentally read or modify data in the
- * parent scope.
- *
- * The 'isolate' scope takes an object hash which defines a set of local scope properties
- * derived from the parent scope. These local properties are useful for aliasing values for
- * templates. Locals definition is a hash of local scope property to its source:
- *
- * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
- * always a string since DOM attributes are strings. If no `attr` name is specified then the
- * attribute name is assumed to be the same as the local name.
- * Given `<widget my-attr="hello {{name}}">` and widget definition
- * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
- * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
- * `localName` property on the widget scope. The `name` is read from the parent scope (not
- * component scope).
- *
- * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
- * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
- * name is specified then the attribute name is assumed to be the same as the local name.
- * Given `<widget my-attr="parentModel">` and widget definition of
- * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
- * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
- * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
- * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
- * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
- *
- * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
- * If no `attr` name is specified then the attribute name is assumed to be the same as the
- * local name. Given `<widget my-attr="count = count + value">` and widget definition of
- * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
- * a function wrapper for the `count = count + value` expression. Often it's desirable to
- * pass data from the isolated scope via an expression to the parent scope, this can be
- * done by passing a map of local variable names and values into the expression wrapper fn.
- * For example, if the expression is `increment(amount)` then we can specify the amount value
- * by calling the `localFn` as `localFn({amount: 22})`.
- *
- *
- *
- * #### `controller`
- * Controller constructor function. The controller is instantiated before the
- * pre-linking phase and it is shared with other directives (see
- * `require` attribute). This allows the directives to communicate with each other and augment
- * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
- *
- * * `$scope` - Current scope associated with the element
- * * `$element` - Current element
- * * `$attrs` - Current attributes object for the element
- * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.
- * The scope can be overridden by an optional first argument.
- * `function([scope], cloneLinkingFn)`.
- *
- *
- * #### `require`
- * Require another directive and inject its controller as the fourth argument to the linking function. The
- * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
- * injected argument will be an array in corresponding order. If no such directive can be
- * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:
- *
- * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
- * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
- * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
- * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
- * `null` to the `link` fn if not found.
- *
- *
- * #### `controllerAs`
- * Controller alias at the directive scope. An alias for the controller so it
- * can be referenced at the directive template. The directive needs to define a scope for this
- * configuration to be used. Useful in the case when directive is used as component.
- *
- *
- * #### `restrict`
- * String of subset of `EACM` which restricts the directive to a specific directive
- * declaration style. If omitted, the default (attributes only) is used.
- *
- * * `E` - Element name: `<my-directive></my-directive>`
- * * `A` - Attribute (default): `<div my-directive="exp"></div>`
- * * `C` - Class: `<div class="my-directive: exp;"></div>`
- * * `M` - Comment: `<!-- directive: my-directive exp -->`
- *
- *
- * #### `template`
- * HTML markup that may:
- * * Replace the contents of the directive's element (default).
- * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
- * * Wrap the contents of the directive's element (if `transclude` is true).
- *
- * Value may be:
- *
- * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
- * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
- * function api below) and returns a string value.
- *
- *
- * #### `templateUrl`
- * Same as `template` but the template is loaded from the specified URL. Because
- * the template loading is asynchronous the compilation/linking is suspended until the template
- * is loaded.
- *
- * You can specify `templateUrl` as a string representing the URL or as a function which takes two
- * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
- * a string value representing the url. In either case, the template URL is passed through {@link
- * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
- *
- *
- * #### `replace` ([*DEPRECATED*!], will be removed in next major release)
- * specify what the template should replace. Defaults to `false`.
- *
- * * `true` - the template will replace the directive's element.
- * * `false` - the template will replace the contents of the directive's element.
- *
- * The replacement process migrates all of the attributes / classes from the old element to the new
- * one. See the {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive
- * Directives Guide} for an example.
- *
- * #### `transclude`
- * compile the content of the element and make it available to the directive.
- * Typically used with {@link ng.directive:ngTransclude
- * ngTransclude}. The advantage of transclusion is that the linking function receives a
- * transclusion function which is pre-bound to the correct scope. In a typical setup the widget
- * creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate`
- * scope. This makes it possible for the widget to have private state, and the transclusion to
- * be bound to the parent (pre-`isolate`) scope.
- *
- * * `true` - transclude the content of the directive.
- * * `'element'` - transclude the whole element including any directives defined at lower priority.
- *
- * <div class="alert alert-warning">
- * **Note:** When testing an element transclude directive you must not place the directive at the root of the
- * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
- * Testing Transclusion Directives}.
- * </div>
- *
- * #### `compile`
- *
- * ```js
- * function compile(tElement, tAttrs, transclude) { ... }
- * ```
- *
- * The compile function deals with transforming the template DOM. Since most directives do not do
- * template transformation, it is not used often. The compile function takes the following arguments:
- *
- * * `tElement` - template element - The element where the directive has been declared. It is
- * safe to do template transformation on the element and child elements only.
- *
- * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
- * between all directive compile functions.
- *
- * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
- *
- * <div class="alert alert-warning">
- * **Note:** The template instance and the link instance may be different objects if the template has
- * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
- * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
- * should be done in a linking function rather than in a compile function.
- * </div>
-
- * <div class="alert alert-warning">
- * **Note:** The compile function cannot handle directives that recursively use themselves in their
- * own templates or compile functions. Compiling these directives results in an infinite loop and a
- * stack overflow errors.
- *
- * This can be avoided by manually using $compile in the postLink function to imperatively compile
- * a directive's template instead of relying on automatic template compilation via `template` or
- * `templateUrl` declaration or manual compilation inside the compile function.
- * </div>
- *
- * <div class="alert alert-error">
- * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
- * e.g. does not know about the right outer scope. Please use the transclude function that is passed
- * to the link function instead.
- * </div>
-
- * A compile function can have a return value which can be either a function or an object.
- *
- * * returning a (post-link) function - is equivalent to registering the linking function via the
- * `link` property of the config object when the compile function is empty.
- *
- * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
- * control when a linking function should be called during the linking phase. See info about
- * pre-linking and post-linking functions below.
- *
- *
- * #### `link`
- * This property is used only if the `compile` property is not defined.
- *
- * ```js
- * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
- * ```
- *
- * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
- * executed after the template has been cloned. This is where most of the directive logic will be
- * put.
- *
- * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
- * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
- *
- * * `iElement` - instance element - The element where the directive is to be used. It is safe to
- * manipulate the children of the element only in `postLink` function since the children have
- * already been linked.
- *
- * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
- * between all directive linking functions.
- *
- * * `controller` - a controller instance - A controller instance if at least one directive on the
- * element defines a controller. The controller is shared among all the directives, which allows
- * the directives to use the controllers as a communication channel.
- *
- * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
- * The scope can be overridden by an optional first argument. This is the same as the `$transclude`
- * parameter of directive controllers.
- * `function([scope], cloneLinkingFn)`.
- *
- *
- * #### Pre-linking function
- *
- * Executed before the child elements are linked. Not safe to do DOM transformation since the
- * compiler linking function will fail to locate the correct elements for linking.
- *
- * #### Post-linking function
- *
- * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
- *
- * <a name="Attributes"></a>
- * ### Attributes
- *
- * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
- * `link()` or `compile()` functions. It has a variety of uses.
- *
- * accessing *Normalized attribute names:*
- * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
- * the attributes object allows for normalized access to
- * the attributes.
- *
- * * *Directive inter-communication:* All directives share the same instance of the attributes
- * object which allows the directives to use the attributes object as inter directive
- * communication.
- *
- * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
- * allowing other directives to read the interpolated value.
- *
- * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
- * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
- * the only way to easily get the actual value because during the linking phase the interpolation
- * hasn't been evaluated yet and so the value is at this time set to `undefined`.
- *
- * ```js
- * function linkingFn(scope, elm, attrs, ctrl) {
- * // get the attribute value
- * console.log(attrs.ngModel);
- *
- * // change the attribute
- * attrs.$set('ngModel', 'new value');
- *
- * // observe changes to interpolated attribute
- * attrs.$observe('ngModel', function(value) {
- * console.log('ngModel has changed value to ' + value);
- * });
- * }
- * ```
- *
- * Below is an example using `$compileProvider`.
- *
- * <div class="alert alert-warning">
- * **Note**: Typically directives are registered with `module.directive`. The example below is
- * to illustrate how `$compile` works.
- * </div>
- *
- <example module="compileExample">
- <file name="index.html">
- <script>
- angular.module('compileExample', [], function($compileProvider) {
- // configure new 'compile' directive by passing a directive
- // factory function. The factory function injects the '$compile'
- $compileProvider.directive('compile', function($compile) {
- // directive factory creates a link function
- return function(scope, element, attrs) {
- scope.$watch(
- function(scope) {
- // watch the 'compile' expression for changes
- return scope.$eval(attrs.compile);
- },
- function(value) {
- // when the 'compile' expression changes
- // assign it into the current DOM
- element.html(value);
-
- // compile the new DOM and link it to the current
- // scope.
- // NOTE: we only compile .childNodes so that
- // we don't get into infinite loop compiling ourselves
- $compile(element.contents())(scope);
- }
- );
- };
- });
- })
- .controller('GreeterController', ['$scope', function($scope) {
- $scope.name = 'Angular';
- $scope.html = 'Hello {{name}}';
- }]);
- </script>
- <div ng-controller="GreeterController">
- <input ng-model="name"> <br>
- <textarea ng-model="html"></textarea> <br>
- <div compile="html"></div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should auto compile', function() {
- var textarea = $('textarea');
- var output = $('div[compile]');
- // The initial state reads 'Hello Angular'.
- expect(output.getText()).toBe('Hello Angular');
- textarea.clear();
- textarea.sendKeys('{{name}}!');
- expect(output.getText()).toBe('Angular!');
- });
- </file>
- </example>
-
- *
- *
- * @param {string|DOMElement} element Element or HTML string to compile into a template function.
- * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives.
- * @param {number} maxPriority only apply directives lower than given priority (Only effects the
- * root element(s), not their children)
- * @returns {function(scope, cloneAttachFn=)} a link function which is used to bind template
- * (a DOM element/tree) to a scope. Where:
- *
- * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
- * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
- * `template` and call the `cloneAttachFn` function allowing the caller to attach the
- * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
- * called as: <br> `cloneAttachFn(clonedElement, scope)` where:
- *
- * * `clonedElement` - is a clone of the original `element` passed into the compiler.
- * * `scope` - is the current scope with which the linking function is working with.
- *
- * Calling the linking function returns the element of the template. It is either the original
- * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
- *
- * After linking the view is not updated until after a call to $digest which typically is done by
- * Angular automatically.
- *
- * If you need access to the bound view, there are two ways to do it:
- *
- * - If you are not asking the linking function to clone the template, create the DOM element(s)
- * before you send them to the compiler and keep this reference around.
- * ```js
- * var element = $compile('<p>{{total}}</p>')(scope);
- * ```
- *
- * - if on the other hand, you need the element to be cloned, the view reference from the original
- * example would not point to the clone, but rather to the original template that was cloned. In
- * this case, you can access the clone via the cloneAttachFn:
- * ```js
- * var templateElement = angular.element('<p>{{total}}</p>'),
- * scope = ....;
- *
- * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
- * //attach the clone to DOM document at the right place
- * });
- *
- * //now we have reference to the cloned DOM via `clonedElement`
- * ```
- *
- *
- * For information on how the compiler works, see the
- * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
- */
-
-var $compileMinErr = minErr('$compile');
-
-/**
- * @ngdoc provider
- * @name $compileProvider
- * @kind function
- *
- * @description
- */
-$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
-function $CompileProvider($provide, $$sanitizeUriProvider) {
- var hasDirectives = {},
- Suffix = 'Directive',
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;
-
- // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
- // The assumption is that future DOM event attribute names will begin with
- // 'on' and be composed of only English letters.
- var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
-
- /**
- * @ngdoc method
- * @name $compileProvider#directive
- * @kind function
- *
- * @description
- * Register a new directive with the compiler.
- *
- * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
- * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
- * names and the values are the factories.
- * @param {Function|Array} directiveFactory An injectable directive factory function. See
- * {@link guide/directive} for more info.
- * @returns {ng.$compileProvider} Self for chaining.
- */
- this.directive = function registerDirective(name, directiveFactory) {
- assertNotHasOwnProperty(name, 'directive');
- if (isString(name)) {
- assertArg(directiveFactory, 'directiveFactory');
- if (!hasDirectives.hasOwnProperty(name)) {
- hasDirectives[name] = [];
- $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
- function($injector, $exceptionHandler) {
- var directives = [];
- forEach(hasDirectives[name], function(directiveFactory, index) {
- try {
- var directive = $injector.invoke(directiveFactory);
- if (isFunction(directive)) {
- directive = { compile: valueFn(directive) };
- } else if (!directive.compile && directive.link) {
- directive.compile = valueFn(directive.link);
- }
- directive.priority = directive.priority || 0;
- directive.index = index;
- directive.name = directive.name || name;
- directive.require = directive.require || (directive.controller && directive.name);
- directive.restrict = directive.restrict || 'A';
- directives.push(directive);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- return directives;
- }]);
- }
- hasDirectives[name].push(directiveFactory);
- } else {
- forEach(name, reverseParams(registerDirective));
- }
- return this;
- };
-
-
- /**
- * @ngdoc method
- * @name $compileProvider#aHrefSanitizationWhitelist
- * @kind function
- *
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during a[href] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
- }
- };
-
-
- /**
- * @ngdoc method
- * @name $compileProvider#imgSrcSanitizationWhitelist
- * @kind function
- *
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during img[src] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
- }
- };
-
- this.$get = [
- '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
- function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
-
- var Attributes = function(element, attr) {
- this.$$element = element;
- this.$attr = attr || {};
- };
-
- Attributes.prototype = {
- $normalize: directiveNormalize,
-
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$addClass
- * @kind function
- *
- * @description
- * Adds the CSS class value specified by the classVal parameter to the element. If animations
- * are enabled then an animation will be triggered for the class addition.
- *
- * @param {string} classVal The className value that will be added to the element
- */
- $addClass : function(classVal) {
- if(classVal && classVal.length > 0) {
- $animate.addClass(this.$$element, classVal);
- }
- },
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$removeClass
- * @kind function
- *
- * @description
- * Removes the CSS class value specified by the classVal parameter from the element. If
- * animations are enabled then an animation will be triggered for the class removal.
- *
- * @param {string} classVal The className value that will be removed from the element
- */
- $removeClass : function(classVal) {
- if(classVal && classVal.length > 0) {
- $animate.removeClass(this.$$element, classVal);
- }
- },
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$updateClass
- * @kind function
- *
- * @description
- * Adds and removes the appropriate CSS class values to the element based on the difference
- * between the new and old CSS class values (specified as newClasses and oldClasses).
- *
- * @param {string} newClasses The current CSS className value
- * @param {string} oldClasses The former CSS className value
- */
- $updateClass : function(newClasses, oldClasses) {
- var toAdd = tokenDifference(newClasses, oldClasses);
- var toRemove = tokenDifference(oldClasses, newClasses);
-
- if(toAdd.length === 0) {
- $animate.removeClass(this.$$element, toRemove);
- } else if(toRemove.length === 0) {
- $animate.addClass(this.$$element, toAdd);
- } else {
- $animate.setClass(this.$$element, toAdd, toRemove);
- }
- },
-
- /**
- * Set a normalized attribute on the element in a way such that all directives
- * can share the attribute. This function properly handles boolean attributes.
- * @param {string} key Normalized key. (ie ngAttribute)
- * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
- * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
- * Defaults to true.
- * @param {string=} attrName Optional none normalized name. Defaults to key.
- */
- $set: function(key, value, writeAttr, attrName) {
- // TODO: decide whether or not to throw an error if "class"
- //is set through this function since it may cause $updateClass to
- //become unstable.
-
- var booleanKey = getBooleanAttrName(this.$$element[0], key),
- normalizedVal,
- nodeName;
-
- if (booleanKey) {
- this.$$element.prop(key, value);
- attrName = booleanKey;
- }
-
- this[key] = value;
-
- // translate normalized key to actual key
- if (attrName) {
- this.$attr[key] = attrName;
- } else {
- attrName = this.$attr[key];
- if (!attrName) {
- this.$attr[key] = attrName = snake_case(key, '-');
- }
- }
-
- nodeName = nodeName_(this.$$element);
-
- // sanitize a[href] and img[src] values
- if ((nodeName === 'A' && key === 'href') ||
- (nodeName === 'IMG' && key === 'src')) {
- this[key] = value = $$sanitizeUri(value, key === 'src');
- }
-
- if (writeAttr !== false) {
- if (value === null || value === undefined) {
- this.$$element.removeAttr(attrName);
- } else {
- this.$$element.attr(attrName, value);
- }
- }
-
- // fire observers
- var $$observers = this.$$observers;
- $$observers && forEach($$observers[key], function(fn) {
- try {
- fn(value);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- },
-
-
- /**
- * @ngdoc method
- * @name $compile.directive.Attributes#$observe
- * @kind function
- *
- * @description
- * Observes an interpolated attribute.
- *
- * The observer function will be invoked once during the next `$digest` following
- * compilation. The observer is then invoked whenever the interpolated value
- * changes.
- *
- * @param {string} key Normalized key. (ie ngAttribute) .
- * @param {function(interpolatedValue)} fn Function that will be called whenever
- the interpolated value of the attribute changes.
- * See the {@link guide/directive#Attributes Directives} guide for more info.
- * @returns {function()} the `fn` parameter.
- */
- $observe: function(key, fn) {
- var attrs = this,
- $$observers = (attrs.$$observers || (attrs.$$observers = {})),
- listeners = ($$observers[key] || ($$observers[key] = []));
-
- listeners.push(fn);
- $rootScope.$evalAsync(function() {
- if (!listeners.$$inter) {
- // no one registered attribute interpolation function, so lets call it manually
- fn(attrs[key]);
- }
- });
- return fn;
- }
- };
-
- var startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
- ? identity
- : function denormalizeTemplate(template) {
- return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
- },
- NG_ATTR_BINDING = /^ngAttr[A-Z]/;
-
-
- return compile;
-
- //================================
-
- function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
- previousCompileContext) {
- if (!($compileNodes instanceof jqLite)) {
- // jquery always rewraps, whereas we need to preserve the original selector so that we can
- // modify it.
- $compileNodes = jqLite($compileNodes);
- }
- // We can not compile top level text elements since text nodes can be merged and we will
- // not be able to attach scope data to them, so we will wrap them in <span>
- forEach($compileNodes, function(node, index){
- if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
- $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];
- }
- });
- var compositeLinkFn =
- compileNodes($compileNodes, transcludeFn, $compileNodes,
- maxPriority, ignoreDirective, previousCompileContext);
- safeAddClass($compileNodes, 'ng-scope');
- return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
- assertArg(scope, 'scope');
- // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
- // and sometimes changes the structure of the DOM.
- var $linkNode = cloneConnectFn
- ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
- : $compileNodes;
-
- forEach(transcludeControllers, function(instance, name) {
- $linkNode.data('$' + name + 'Controller', instance);
- });
-
- // Attach scope only to non-text nodes.
- for(var i = 0, ii = $linkNode.length; i<ii; i++) {
- var node = $linkNode[i],
- nodeType = node.nodeType;
- if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
- $linkNode.eq(i).data('$scope', scope);
- }
- }
-
- if (cloneConnectFn) cloneConnectFn($linkNode, scope);
- if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
- return $linkNode;
- };
- }
-
- function safeAddClass($element, className) {
- try {
- $element.addClass(className);
- } catch(e) {
- // ignore, since it means that we are trying to set class on
- // SVG element, where class name is read-only.
- }
- }
-
- /**
- * Compile function matches each node in nodeList against the directives. Once all directives
- * for a particular node are collected their compile functions are executed. The compile
- * functions return values - the linking functions - are combined into a composite linking
- * function, which is the a linking function for the node.
- *
- * @param {NodeList} nodeList an array of nodes or NodeList to compile
- * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
- * scope argument is auto-generated to the new child of the transcluded parent scope.
- * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
- * the rootElement must be set the jqLite collection of the compile root. This is
- * needed so that the jqLite collection items can be replaced with widgets.
- * @param {number=} maxPriority Max directive priority.
- * @returns {Function} A composite linking function of all of the matched directives or null.
- */
- function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
- previousCompileContext) {
- var linkFns = [],
- attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;
-
- for (var i = 0; i < nodeList.length; i++) {
- attrs = new Attributes();
-
- // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
- directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
- ignoreDirective);
-
- nodeLinkFn = (directives.length)
- ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
- null, [], [], previousCompileContext)
- : null;
-
- if (nodeLinkFn && nodeLinkFn.scope) {
- safeAddClass(attrs.$$element, 'ng-scope');
- }
-
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
- !(childNodes = nodeList[i].childNodes) ||
- !childNodes.length)
- ? null
- : compileNodes(childNodes,
- nodeLinkFn ? (
- (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
- && nodeLinkFn.transclude) : transcludeFn);
-
- linkFns.push(nodeLinkFn, childLinkFn);
- linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
- //use the previous context only for the first element in the virtual group
- previousCompileContext = null;
- }
-
- // return a linking function if we have found anything, null otherwise
- return linkFnFound ? compositeLinkFn : null;
-
- function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
- var nodeLinkFn, childLinkFn, node, childScope, i, ii, n, childBoundTranscludeFn;
-
- // copy nodeList so that linking doesn't break due to live list updates.
- var nodeListLength = nodeList.length,
- stableNodeList = new Array(nodeListLength);
- for (i = 0; i < nodeListLength; i++) {
- stableNodeList[i] = nodeList[i];
- }
-
- for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
- node = stableNodeList[n];
- nodeLinkFn = linkFns[i++];
- childLinkFn = linkFns[i++];
-
- if (nodeLinkFn) {
- if (nodeLinkFn.scope) {
- childScope = scope.$new();
- jqLite.data(node, '$scope', childScope);
- } else {
- childScope = scope;
- }
-
- if ( nodeLinkFn.transcludeOnThisElement ) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
-
- } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
- childBoundTranscludeFn = parentBoundTranscludeFn;
-
- } else if (!parentBoundTranscludeFn && transcludeFn) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
-
- } else {
- childBoundTranscludeFn = null;
- }
-
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
-
- } else if (childLinkFn) {
- childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
- }
- }
- }
- }
-
- function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
-
- var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
- var scopeCreated = false;
-
- if (!transcludedScope) {
- transcludedScope = scope.$new();
- transcludedScope.$$transcluded = true;
- scopeCreated = true;
- }
-
- var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
- if (scopeCreated) {
- clone.on('$destroy', function() { transcludedScope.$destroy(); });
- }
- return clone;
- };
-
- return boundTranscludeFn;
- }
-
- /**
- * Looks for directives on the given node and adds them to the directive collection which is
- * sorted.
- *
- * @param node Node to search.
- * @param directives An array to which the directives are added to. This array is sorted before
- * the function returns.
- * @param attrs The shared attrs object which is used to populate the normalized attributes.
- * @param {number=} maxPriority Max directive priority.
- */
- function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
- var nodeType = node.nodeType,
- attrsMap = attrs.$attr,
- match,
- className;
-
- switch(nodeType) {
- case 1: /* Element */
- // use the node name: <directive>
- addDirective(directives,
- directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
-
- // iterate over the attributes
- for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
- j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
- var attrStartName = false;
- var attrEndName = false;
-
- attr = nAttrs[j];
- if (!msie || msie >= 8 || attr.specified) {
- name = attr.name;
- value = trim(attr.value);
-
- // support ngAttr attribute binding
- ngAttrName = directiveNormalize(name);
- if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
- name = snake_case(ngAttrName.substr(6), '-');
- }
-
- var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
- if (ngAttrName === directiveNName + 'Start') {
- attrStartName = name;
- attrEndName = name.substr(0, name.length - 5) + 'end';
- name = name.substr(0, name.length - 6);
- }
-
- nName = directiveNormalize(name.toLowerCase());
- attrsMap[nName] = name;
- if (isNgAttr || !attrs.hasOwnProperty(nName)) {
- attrs[nName] = value;
- if (getBooleanAttrName(node, nName)) {
- attrs[nName] = true; // presence means true
- }
- }
- addAttrInterpolateDirective(node, directives, value, nName);
- addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
- attrEndName);
- }
- }
-
- // use class as directive
- className = node.className;
- if (isString(className) && className !== '') {
- while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
- nName = directiveNormalize(match[2]);
- if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[3]);
- }
- className = className.substr(match.index + match[0].length);
- }
- }
- break;
- case 3: /* Text Node */
- addTextInterpolateDirective(directives, node.nodeValue);
- break;
- case 8: /* Comment */
- try {
- match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
- if (match) {
- nName = directiveNormalize(match[1]);
- if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[2]);
- }
- }
- } catch (e) {
- // turns out that under some circumstances IE9 throws errors when one attempts to read
- // comment's node value.
- // Just ignore it and continue. (Can't seem to reproduce in test case.)
- }
- break;
- }
-
- directives.sort(byPriority);
- return directives;
- }
-
- /**
- * Given a node with an directive-start it collects all of the siblings until it finds
- * directive-end.
- * @param node
- * @param attrStart
- * @param attrEnd
- * @returns {*}
- */
- function groupScan(node, attrStart, attrEnd) {
- var nodes = [];
- var depth = 0;
- if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
- var startNode = node;
- do {
- if (!node) {
- throw $compileMinErr('uterdir',
- "Unterminated attribute, found '{0}' but no matching '{1}' found.",
- attrStart, attrEnd);
- }
- if (node.nodeType == 1 /** Element **/) {
- if (node.hasAttribute(attrStart)) depth++;
- if (node.hasAttribute(attrEnd)) depth--;
- }
- nodes.push(node);
- node = node.nextSibling;
- } while (depth > 0);
- } else {
- nodes.push(node);
- }
-
- return jqLite(nodes);
- }
-
- /**
- * Wrapper for linking function which converts normal linking function into a grouped
- * linking function.
- * @param linkFn
- * @param attrStart
- * @param attrEnd
- * @returns {Function}
- */
- function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
- return function(scope, element, attrs, controllers, transcludeFn) {
- element = groupScan(element[0], attrStart, attrEnd);
- return linkFn(scope, element, attrs, controllers, transcludeFn);
- };
- }
-
- /**
- * Once the directives have been collected, their compile functions are executed. This method
- * is responsible for inlining directive templates as well as terminating the application
- * of the directives if the terminal directive has been reached.
- *
- * @param {Array} directives Array of collected directives to execute their compile function.
- * this needs to be pre-sorted by priority order.
- * @param {Node} compileNode The raw DOM node to apply the compile functions to
- * @param {Object} templateAttrs The shared attribute function
- * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
- * scope argument is auto-generated to the new
- * child of the transcluded parent scope.
- * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
- * argument has the root jqLite array so that we can replace nodes
- * on it.
- * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
- * compiling the transclusion.
- * @param {Array.<Function>} preLinkFns
- * @param {Array.<Function>} postLinkFns
- * @param {Object} previousCompileContext Context used for previous compilation of the current
- * node
- * @returns {Function} linkFn
- */
- function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
- jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
- previousCompileContext) {
- previousCompileContext = previousCompileContext || {};
-
- var terminalPriority = -Number.MAX_VALUE,
- newScopeDirective,
- controllerDirectives = previousCompileContext.controllerDirectives,
- newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
- templateDirective = previousCompileContext.templateDirective,
- nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
- hasTranscludeDirective = false,
- hasTemplate = false,
- hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
- $compileNode = templateAttrs.$$element = jqLite(compileNode),
- directive,
- directiveName,
- $template,
- replaceDirective = originalReplaceDirective,
- childTranscludeFn = transcludeFn,
- linkFn,
- directiveValue;
-
- // executes all directives on the current element
- for(var i = 0, ii = directives.length; i < ii; i++) {
- directive = directives[i];
- var attrStart = directive.$$start;
- var attrEnd = directive.$$end;
-
- // collect multiblock sections
- if (attrStart) {
- $compileNode = groupScan(compileNode, attrStart, attrEnd);
- }
- $template = undefined;
-
- if (terminalPriority > directive.priority) {
- break; // prevent further processing of directives
- }
-
- if (directiveValue = directive.scope) {
- newScopeDirective = newScopeDirective || directive;
-
- // skip the check for directives with async templates, we'll check the derived sync
- // directive when the template arrives
- if (!directive.templateUrl) {
- assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
- $compileNode);
- if (isObject(directiveValue)) {
- newIsolateScopeDirective = directive;
- }
- }
- }
-
- directiveName = directive.name;
-
- if (!directive.templateUrl && directive.controller) {
- directiveValue = directive.controller;
- controllerDirectives = controllerDirectives || {};
- assertNoDuplicate("'" + directiveName + "' controller",
- controllerDirectives[directiveName], directive, $compileNode);
- controllerDirectives[directiveName] = directive;
- }
-
- if (directiveValue = directive.transclude) {
- hasTranscludeDirective = true;
-
- // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
- // This option should only be used by directives that know how to safely handle element transclusion,
- // where the transcluded nodes are added or replaced after linking.
- if (!directive.$$tlb) {
- assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
- nonTlbTranscludeDirective = directive;
- }
-
- if (directiveValue == 'element') {
- hasElementTranscludeDirective = true;
- terminalPriority = directive.priority;
- $template = $compileNode;
- $compileNode = templateAttrs.$$element =
- jqLite(document.createComment(' ' + directiveName + ': ' +
- templateAttrs[directiveName] + ' '));
- compileNode = $compileNode[0];
- replaceWith(jqCollection, sliceArgs($template), compileNode);
-
- childTranscludeFn = compile($template, transcludeFn, terminalPriority,
- replaceDirective && replaceDirective.name, {
- // Don't pass in:
- // - controllerDirectives - otherwise we'll create duplicates controllers
- // - newIsolateScopeDirective or templateDirective - combining templates with
- // element transclusion doesn't make sense.
- //
- // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
- // on the same element more than once.
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- } else {
- $template = jqLite(jqLiteClone(compileNode)).contents();
- $compileNode.empty(); // clear contents
- childTranscludeFn = compile($template, transcludeFn);
- }
- }
-
- if (directive.template) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
-
- directiveValue = (isFunction(directive.template))
- ? directive.template($compileNode, templateAttrs)
- : directive.template;
-
- directiveValue = denormalizeTemplate(directiveValue);
-
- if (directive.replace) {
- replaceDirective = directive;
- if (jqLiteIsTextNode(directiveValue)) {
- $template = [];
- } else {
- $template = jqLite(trim(directiveValue));
- }
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- directiveName, '');
- }
-
- replaceWith(jqCollection, $compileNode, compileNode);
-
- var newTemplateAttrs = {$attr: {}};
-
- // combine directives from the original node and from the template:
- // - take the array of directives for this element
- // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
- // - collect directives from the template and sort them by priority
- // - combine directives as: processed + template + unprocessed
- var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
- var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
-
- if (newIsolateScopeDirective) {
- markDirectivesAsIsolate(templateDirectives);
- }
- directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
- mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
-
- ii = directives.length;
- } else {
- $compileNode.html(directiveValue);
- }
- }
-
- if (directive.templateUrl) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
-
- if (directive.replace) {
- replaceDirective = directive;
- }
-
- nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
- templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
- controllerDirectives: controllerDirectives,
- newIsolateScopeDirective: newIsolateScopeDirective,
- templateDirective: templateDirective,
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- ii = directives.length;
- } else if (directive.compile) {
- try {
- linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
- if (isFunction(linkFn)) {
- addLinkFns(null, linkFn, attrStart, attrEnd);
- } else if (linkFn) {
- addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
- }
- } catch (e) {
- $exceptionHandler(e, startingTag($compileNode));
- }
- }
-
- if (directive.terminal) {
- nodeLinkFn.terminal = true;
- terminalPriority = Math.max(terminalPriority, directive.priority);
- }
-
- }
-
- nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
- nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
- nodeLinkFn.templateOnThisElement = hasTemplate;
- nodeLinkFn.transclude = childTranscludeFn;
-
- previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
-
- // might be normal or delayed nodeLinkFn depending on if templateUrl is present
- return nodeLinkFn;
-
- ////////////////////
-
- function addLinkFns(pre, post, attrStart, attrEnd) {
- if (pre) {
- if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
- pre.require = directive.require;
- pre.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- pre = cloneAndAnnotateFn(pre, {isolateScope: true});
- }
- preLinkFns.push(pre);
- }
- if (post) {
- if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
- post.require = directive.require;
- post.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- post = cloneAndAnnotateFn(post, {isolateScope: true});
- }
- postLinkFns.push(post);
- }
- }
-
-
- function getControllers(directiveName, require, $element, elementControllers) {
- var value, retrievalMethod = 'data', optional = false;
- if (isString(require)) {
- while((value = require.charAt(0)) == '^' || value == '?') {
- require = require.substr(1);
- if (value == '^') {
- retrievalMethod = 'inheritedData';
- }
- optional = optional || value == '?';
- }
- value = null;
-
- if (elementControllers && retrievalMethod === 'data') {
- value = elementControllers[require];
- }
- value = value || $element[retrievalMethod]('$' + require + 'Controller');
-
- if (!value && !optional) {
- throw $compileMinErr('ctreq',
- "Controller '{0}', required by directive '{1}', can't be found!",
- require, directiveName);
- }
- return value;
- } else if (isArray(require)) {
- value = [];
- forEach(require, function(require) {
- value.push(getControllers(directiveName, require, $element, elementControllers));
- });
- }
- return value;
- }
-
-
- function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
- var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
-
- attrs = (compileNode === linkNode)
- ? templateAttrs
- : shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
- $element = attrs.$$element;
-
- if (newIsolateScopeDirective) {
- var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
-
- isolateScope = scope.$new(true);
-
- if (templateDirective && (templateDirective === newIsolateScopeDirective ||
- templateDirective === newIsolateScopeDirective.$$originalDirective)) {
- $element.data('$isolateScope', isolateScope);
- } else {
- $element.data('$isolateScopeNoTemplate', isolateScope);
- }
-
-
-
- safeAddClass($element, 'ng-isolate-scope');
-
- forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
- var match = definition.match(LOCAL_REGEXP) || [],
- attrName = match[3] || scopeName,
- optional = (match[2] == '?'),
- mode = match[1], // @, =, or &
- lastValue,
- parentGet, parentSet, compare;
-
- isolateScope.$$isolateBindings[scopeName] = mode + attrName;
-
- switch (mode) {
-
- case '@':
- attrs.$observe(attrName, function(value) {
- isolateScope[scopeName] = value;
- });
- attrs.$$observers[attrName].$$scope = scope;
- if( attrs[attrName] ) {
- // If the attribute has been provided then we trigger an interpolation to ensure
- // the value is there for use in the link fn
- isolateScope[scopeName] = $interpolate(attrs[attrName])(scope);
- }
- break;
-
- case '=':
- if (optional && !attrs[attrName]) {
- return;
- }
- parentGet = $parse(attrs[attrName]);
- if (parentGet.literal) {
- compare = equals;
- } else {
- compare = function(a,b) { return a === b || (a !== a && b !== b); };
- }
- parentSet = parentGet.assign || function() {
- // reset the change, or we will throw this exception on every $digest
- lastValue = isolateScope[scopeName] = parentGet(scope);
- throw $compileMinErr('nonassign',
- "Expression '{0}' used with directive '{1}' is non-assignable!",
- attrs[attrName], newIsolateScopeDirective.name);
- };
- lastValue = isolateScope[scopeName] = parentGet(scope);
- isolateScope.$watch(function parentValueWatch() {
- var parentValue = parentGet(scope);
- if (!compare(parentValue, isolateScope[scopeName])) {
- // we are out of sync and need to copy
- if (!compare(parentValue, lastValue)) {
- // parent changed and it has precedence
- isolateScope[scopeName] = parentValue;
- } else {
- // if the parent can be assigned then do so
- parentSet(scope, parentValue = isolateScope[scopeName]);
- }
- }
- return lastValue = parentValue;
- }, null, parentGet.literal);
- break;
-
- case '&':
- parentGet = $parse(attrs[attrName]);
- isolateScope[scopeName] = function(locals) {
- return parentGet(scope, locals);
- };
- break;
-
- default:
- throw $compileMinErr('iscp',
- "Invalid isolate scope definition for directive '{0}'." +
- " Definition: {... {1}: '{2}' ...}",
- newIsolateScopeDirective.name, scopeName, definition);
- }
- });
- }
- transcludeFn = boundTranscludeFn && controllersBoundTransclude;
- if (controllerDirectives) {
- forEach(controllerDirectives, function(directive) {
- var locals = {
- $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
- $element: $element,
- $attrs: attrs,
- $transclude: transcludeFn
- }, controllerInstance;
-
- controller = directive.controller;
- if (controller == '@') {
- controller = attrs[directive.name];
- }
-
- controllerInstance = $controller(controller, locals);
- // For directives with element transclusion the element is a comment,
- // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
- // clean up (http://bugs.jquery.com/ticket/8335).
- // Instead, we save the controllers for the element in a local hash and attach to .data
- // later, once we have the actual element.
- elementControllers[directive.name] = controllerInstance;
- if (!hasElementTranscludeDirective) {
- $element.data('$' + directive.name + 'Controller', controllerInstance);
- }
-
- if (directive.controllerAs) {
- locals.$scope[directive.controllerAs] = controllerInstance;
- }
- });
- }
-
- // PRELINKING
- for(i = 0, ii = preLinkFns.length; i < ii; i++) {
- try {
- linkFn = preLinkFns[i];
- linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
- // RECURSION
- // We only pass the isolate scope, if the isolate directive has a template,
- // otherwise the child elements do not belong to the isolate directive.
- var scopeToChild = scope;
- if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
- scopeToChild = isolateScope;
- }
- childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
-
- // POSTLINKING
- for(i = postLinkFns.length - 1; i >= 0; i--) {
- try {
- linkFn = postLinkFns[i];
- linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
- // This is the function that is injected as `$transclude`.
- function controllersBoundTransclude(scope, cloneAttachFn) {
- var transcludeControllers;
-
- // no scope passed
- if (arguments.length < 2) {
- cloneAttachFn = scope;
- scope = undefined;
- }
-
- if (hasElementTranscludeDirective) {
- transcludeControllers = elementControllers;
- }
-
- return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
- }
- }
- }
-
- function markDirectivesAsIsolate(directives) {
- // mark all directives as needing isolate scope.
- for (var j = 0, jj = directives.length; j < jj; j++) {
- directives[j] = inherit(directives[j], {$$isolateScope: true});
- }
- }
-
- /**
- * looks up the directive and decorates it with exception handling and proper parameters. We
- * call this the boundDirective.
- *
- * @param {string} name name of the directive to look up.
- * @param {string} location The directive must be found in specific format.
- * String containing any of theses characters:
- *
- * * `E`: element name
- * * `A': attribute
- * * `C`: class
- * * `M`: comment
- * @returns {boolean} true if directive was added.
- */
- function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
- endAttrName) {
- if (name === ignoreDirective) return null;
- var match = null;
- if (hasDirectives.hasOwnProperty(name)) {
- for(var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i<ii; i++) {
- try {
- directive = directives[i];
- if ( (maxPriority === undefined || maxPriority > directive.priority) &&
- directive.restrict.indexOf(location) != -1) {
- if (startAttrName) {
- directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
- }
- tDirectives.push(directive);
- match = directive;
- }
- } catch(e) { $exceptionHandler(e); }
- }
- }
- return match;
- }
-
-
- /**
- * When the element is replaced with HTML template then the new attributes
- * on the template need to be merged with the existing attributes in the DOM.
- * The desired effect is to have both of the attributes present.
- *
- * @param {object} dst destination attributes (original DOM)
- * @param {object} src source attributes (from the directive template)
- */
- function mergeTemplateAttributes(dst, src) {
- var srcAttr = src.$attr,
- dstAttr = dst.$attr,
- $element = dst.$$element;
-
- // reapply the old attributes to the new element
- forEach(dst, function(value, key) {
- if (key.charAt(0) != '$') {
- if (src[key] && src[key] !== value) {
- value += (key === 'style' ? ';' : ' ') + src[key];
- }
- dst.$set(key, value, true, srcAttr[key]);
- }
- });
-
- // copy the new attributes on the old attrs object
- forEach(src, function(value, key) {
- if (key == 'class') {
- safeAddClass($element, value);
- dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
- } else if (key == 'style') {
- $element.attr('style', $element.attr('style') + ';' + value);
- dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
- // `dst` will never contain hasOwnProperty as DOM parser won't let it.
- // You will get an "InvalidCharacterError: DOM Exception 5" error if you
- // have an attribute like "has-own-property" or "data-has-own-property", etc.
- } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
- dst[key] = value;
- dstAttr[key] = srcAttr[key];
- }
- });
- }
-
-
- function compileTemplateUrl(directives, $compileNode, tAttrs,
- $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
- var linkQueue = [],
- afterTemplateNodeLinkFn,
- afterTemplateChildLinkFn,
- beforeTemplateCompileNode = $compileNode[0],
- origAsyncDirective = directives.shift(),
- // The fact that we have to copy and patch the directive seems wrong!
- derivedSyncDirective = extend({}, origAsyncDirective, {
- templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
- }),
- templateUrl = (isFunction(origAsyncDirective.templateUrl))
- ? origAsyncDirective.templateUrl($compileNode, tAttrs)
- : origAsyncDirective.templateUrl;
-
- $compileNode.empty();
-
- $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
- success(function(content) {
- var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
-
- content = denormalizeTemplate(content);
-
- if (origAsyncDirective.replace) {
- if (jqLiteIsTextNode(content)) {
- $template = [];
- } else {
- $template = jqLite(trim(content));
- }
- compileNode = $template[0];
-
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- origAsyncDirective.name, templateUrl);
- }
-
- tempTemplateAttrs = {$attr: {}};
- replaceWith($rootElement, $compileNode, compileNode);
- var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
-
- if (isObject(origAsyncDirective.scope)) {
- markDirectivesAsIsolate(templateDirectives);
- }
- directives = templateDirectives.concat(directives);
- mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
- } else {
- compileNode = beforeTemplateCompileNode;
- $compileNode.html(content);
- }
-
- directives.unshift(derivedSyncDirective);
-
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
- childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
- previousCompileContext);
- forEach($rootElement, function(node, i) {
- if (node == compileNode) {
- $rootElement[i] = $compileNode[0];
- }
- });
- afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
-
- while(linkQueue.length) {
- var scope = linkQueue.shift(),
- beforeTemplateLinkNode = linkQueue.shift(),
- linkRootElement = linkQueue.shift(),
- boundTranscludeFn = linkQueue.shift(),
- linkNode = $compileNode[0];
-
- if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
- var oldClasses = beforeTemplateLinkNode.className;
-
- if (!(previousCompileContext.hasElementTranscludeDirective &&
- origAsyncDirective.replace)) {
- // it was cloned therefore we have to clone as well.
- linkNode = jqLiteClone(compileNode);
- }
-
- replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
-
- // Copy in CSS classes from original node
- safeAddClass(jqLite(linkNode), oldClasses);
- }
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- } else {
- childBoundTranscludeFn = boundTranscludeFn;
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
- childBoundTranscludeFn);
- }
- linkQueue = null;
- }).
- error(function(response, code, headers, config) {
- throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
- });
-
- return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
- var childBoundTranscludeFn = boundTranscludeFn;
- if (linkQueue) {
- linkQueue.push(scope);
- linkQueue.push(node);
- linkQueue.push(rootElement);
- linkQueue.push(childBoundTranscludeFn);
- } else {
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
- }
- };
- }
-
-
- /**
- * Sorting function for bound directives.
- */
- function byPriority(a, b) {
- var diff = b.priority - a.priority;
- if (diff !== 0) return diff;
- if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
- return a.index - b.index;
- }
-
-
- function assertNoDuplicate(what, previousDirective, directive, element) {
- if (previousDirective) {
- throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
- previousDirective.name, directive.name, what, startingTag(element));
- }
- }
-
-
- function addTextInterpolateDirective(directives, text) {
- var interpolateFn = $interpolate(text, true);
- if (interpolateFn) {
- directives.push({
- priority: 0,
- compile: function textInterpolateCompileFn(templateNode) {
- // when transcluding a template that has bindings in the root
- // then we don't have a parent and should do this in the linkFn
- var parent = templateNode.parent(), hasCompileParent = parent.length;
- if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
-
- return function textInterpolateLinkFn(scope, node) {
- var parent = node.parent(),
- bindings = parent.data('$binding') || [];
- bindings.push(interpolateFn);
- parent.data('$binding', bindings);
- if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
- node[0].nodeValue = value;
- });
- };
- }
- });
- }
- }
-
-
- function getTrustedContext(node, attrNormalizedName) {
- if (attrNormalizedName == "srcdoc") {
- return $sce.HTML;
- }
- var tag = nodeName_(node);
- // maction[xlink:href] can source SVG. It's not limited to <maction>.
- if (attrNormalizedName == "xlinkHref" ||
- (tag == "FORM" && attrNormalizedName == "action") ||
- (tag != "IMG" && (attrNormalizedName == "src" ||
- attrNormalizedName == "ngSrc"))) {
- return $sce.RESOURCE_URL;
- }
- }
-
-
- function addAttrInterpolateDirective(node, directives, value, name) {
- var interpolateFn = $interpolate(value, true);
-
- // no interpolation found -> ignore
- if (!interpolateFn) return;
-
-
- if (name === "multiple" && nodeName_(node) === "SELECT") {
- throw $compileMinErr("selmulti",
- "Binding to the 'multiple' attribute is not supported. Element: {0}",
- startingTag(node));
- }
-
- directives.push({
- priority: 100,
- compile: function() {
- return {
- pre: function attrInterpolatePreLinkFn(scope, element, attr) {
- var $$observers = (attr.$$observers || (attr.$$observers = {}));
-
- if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
- throw $compileMinErr('nodomevents',
- "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
- "ng- versions (such as ng-click instead of onclick) instead.");
- }
-
- // we need to interpolate again, in case the attribute value has been updated
- // (e.g. by another directive's compile function)
- interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));
-
- // if attribute was updated so that there is no interpolation going on we don't want to
- // register any observers
- if (!interpolateFn) return;
-
- // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the
- // actual attr value
- attr[name] = interpolateFn(scope);
- ($$observers[name] || ($$observers[name] = [])).$$inter = true;
- (attr.$$observers && attr.$$observers[name].$$scope || scope).
- $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
- //special case for class attribute addition + removal
- //so that class changes can tap into the animation
- //hooks provided by the $animate service. Be sure to
- //skip animations when the first digest occurs (when
- //both the new and the old values are the same) since
- //the CSS classes are the non-interpolated values
- if(name === 'class' && newValue != oldValue) {
- attr.$updateClass(newValue, oldValue);
- } else {
- attr.$set(name, newValue);
- }
- });
- }
- };
- }
- });
- }
-
-
- /**
- * This is a special jqLite.replaceWith, which can replace items which
- * have no parents, provided that the containing jqLite collection is provided.
- *
- * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
- * in the root of the tree.
- * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
- * the shell, but replace its DOM node reference.
- * @param {Node} newNode The new DOM node.
- */
- function replaceWith($rootElement, elementsToRemove, newNode) {
- var firstElementToRemove = elementsToRemove[0],
- removeCount = elementsToRemove.length,
- parent = firstElementToRemove.parentNode,
- i, ii;
-
- if ($rootElement) {
- for(i = 0, ii = $rootElement.length; i < ii; i++) {
- if ($rootElement[i] == firstElementToRemove) {
- $rootElement[i++] = newNode;
- for (var j = i, j2 = j + removeCount - 1,
- jj = $rootElement.length;
- j < jj; j++, j2++) {
- if (j2 < jj) {
- $rootElement[j] = $rootElement[j2];
- } else {
- delete $rootElement[j];
- }
- }
- $rootElement.length -= removeCount - 1;
- break;
- }
- }
- }
-
- if (parent) {
- parent.replaceChild(newNode, firstElementToRemove);
- }
- var fragment = document.createDocumentFragment();
- fragment.appendChild(firstElementToRemove);
- newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
- for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
- var element = elementsToRemove[k];
- jqLite(element).remove(); // must do this way to clean up expando
- fragment.appendChild(element);
- delete elementsToRemove[k];
- }
-
- elementsToRemove[0] = newNode;
- elementsToRemove.length = 1;
- }
-
-
- function cloneAndAnnotateFn(fn, annotation) {
- return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
- }
- }];
-}
-
-var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
-/**
- * Converts all accepted directives format into proper directive name.
- * All of these will become 'myDirective':
- * my:Directive
- * my-directive
- * x-my-directive
- * data-my:directive
- *
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function directiveNormalize(name) {
- return camelCase(name.replace(PREFIX_REGEXP, ''));
-}
-
-/**
- * @ngdoc type
- * @name $compile.directive.Attributes
- *
- * @description
- * A shared object between directive compile / linking functions which contains normalized DOM
- * element attributes. The values reflect current binding state `{{ }}`. The normalization is
- * needed since all of these are treated as equivalent in Angular:
- *
- * ```
- * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
- * ```
- */
-
-/**
- * @ngdoc property
- * @name $compile.directive.Attributes#$attr
- *
- * @description
- * A map of DOM element attribute names to the normalized name. This is
- * needed to do reverse lookup from normalized name back to actual name.
- */
-
-
-/**
- * @ngdoc method
- * @name $compile.directive.Attributes#$set
- * @kind function
- *
- * @description
- * Set DOM element attribute value.
- *
- *
- * @param {string} name Normalized element attribute name of the property to modify. The name is
- * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
- * property to the original name.
- * @param {string} value Value to set the attribute to. The value can be an interpolated string.
- */
-
-
-
-/**
- * Closure compiler type information
- */
-
-function nodesetLinkingFn(
- /* angular.Scope */ scope,
- /* NodeList */ nodeList,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-){}
-
-function directiveLinkingFn(
- /* nodesetLinkingFn */ nodesetLinkingFn,
- /* angular.Scope */ scope,
- /* Node */ node,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
-){}
-
-function tokenDifference(str1, str2) {
- var values = '',
- tokens1 = str1.split(/\s+/),
- tokens2 = str2.split(/\s+/);
-
- outer:
- for(var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for(var j = 0; j < tokens2.length; j++) {
- if(token == tokens2[j]) continue outer;
- }
- values += (values.length > 0 ? ' ' : '') + token;
- }
- return values;
-}
-
-/**
- * @ngdoc provider
- * @name $controllerProvider
- * @description
- * The {@link ng.$controller $controller service} is used by Angular to create new
- * controllers.
- *
- * This provider allows controller registration via the
- * {@link ng.$controllerProvider#register register} method.
- */
-function $ControllerProvider() {
- var controllers = {},
- CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
-
-
- /**
- * @ngdoc method
- * @name $controllerProvider#register
- * @param {string|Object} name Controller name, or an object map of controllers where the keys are
- * the names and the values are the constructors.
- * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
- * annotations in the array notation).
- */
- this.register = function(name, constructor) {
- assertNotHasOwnProperty(name, 'controller');
- if (isObject(name)) {
- extend(controllers, name);
- } else {
- controllers[name] = constructor;
- }
- };
-
-
- this.$get = ['$injector', '$window', function($injector, $window) {
-
- /**
- * @ngdoc service
- * @name $controller
- * @requires $injector
- *
- * @param {Function|string} constructor If called with a function then it's considered to be the
- * controller constructor function. Otherwise it's considered to be a string which is used
- * to retrieve the controller constructor using the following steps:
- *
- * * check if a controller with given name is registered via `$controllerProvider`
- * * check if evaluating the string on the current scope returns a constructor
- * * check `window[constructor]` on the global `window` object
- *
- * @param {Object} locals Injection locals for Controller.
- * @return {Object} Instance of given controller.
- *
- * @description
- * `$controller` service is responsible for instantiating controllers.
- *
- * It's just a simple call to {@link auto.$injector $injector}, but extracted into
- * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
- */
- return function(expression, locals) {
- var instance, match, constructor, identifier;
-
- if(isString(expression)) {
- match = expression.match(CNTRL_REG),
- constructor = match[1],
- identifier = match[3];
- expression = controllers.hasOwnProperty(constructor)
- ? controllers[constructor]
- : getter(locals.$scope, constructor, true) || getter($window, constructor, true);
-
- assertArgFn(expression, constructor, true);
- }
-
- instance = $injector.instantiate(expression, locals);
-
- if (identifier) {
- if (!(locals && typeof locals.$scope === 'object')) {
- throw minErr('$controller')('noscp',
- "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
- constructor || expression.name, identifier);
- }
-
- locals.$scope[identifier] = instance;
- }
-
- return instance;
- };
- }];
-}
-
-/**
- * @ngdoc service
- * @name $document
- * @requires $window
- *
- * @description
- * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
- *
- * @example
- <example module="documentExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p>$document title: <b ng-bind="title"></b></p>
- <p>window.document title: <b ng-bind="windowTitle"></b></p>
- </div>
- </file>
- <file name="script.js">
- angular.module('documentExample', [])
- .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
- $scope.title = $document[0].title;
- $scope.windowTitle = angular.element(window.document)[0].title;
- }]);
- </file>
- </example>
- */
-function $DocumentProvider(){
- this.$get = ['$window', function(window){
- return jqLite(window.document);
- }];
-}
-
-/**
- * @ngdoc service
- * @name $exceptionHandler
- * @requires ng.$log
- *
- * @description
- * Any uncaught exception in angular expressions is delegated to this service.
- * The default implementation simply delegates to `$log.error` which logs it into
- * the browser console.
- *
- * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
- * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
- *
- * ## Example:
- *
- * ```js
- * angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
- * return function (exception, cause) {
- * exception.message += ' (caused by "' + cause + '")';
- * throw exception;
- * };
- * });
- * ```
- *
- * This example will override the normal action of `$exceptionHandler`, to make angular
- * exceptions fail hard when they happen, instead of just logging to the console.
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- * the error was thrown.
- *
- */
-function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log) {
- return function(exception, cause) {
- $log.error.apply($log, arguments);
- };
- }];
-}
-
-/**
- * Parse headers into key value object
- *
- * @param {string} headers Raw headers as a string
- * @returns {Object} Parsed headers as key value object
- */
-function parseHeaders(headers) {
- var parsed = {}, key, val, i;
-
- if (!headers) return parsed;
-
- forEach(headers.split('\n'), function(line) {
- i = line.indexOf(':');
- key = lowercase(trim(line.substr(0, i)));
- val = trim(line.substr(i + 1));
-
- if (key) {
- parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
- }
- });
-
- return parsed;
-}
-
-
-/**
- * Returns a function that provides access to parsed headers.
- *
- * Headers are lazy parsed when first requested.
- * @see parseHeaders
- *
- * @param {(string|Object)} headers Headers to provide access to.
- * @returns {function(string=)} Returns a getter function which if called with:
- *
- * - if called with single an argument returns a single header value or null
- * - if called with no arguments returns an object containing all headers.
- */
-function headersGetter(headers) {
- var headersObj = isObject(headers) ? headers : undefined;
-
- return function(name) {
- if (!headersObj) headersObj = parseHeaders(headers);
-
- if (name) {
- return headersObj[lowercase(name)] || null;
- }
-
- return headersObj;
- };
-}
-
-
-/**
- * Chain all given functions
- *
- * This function is used for both request and response transforming
- *
- * @param {*} data Data to transform.
- * @param {function(string=)} headers Http headers getter fn.
- * @param {(Function|Array.<Function>)} fns Function or an array of functions.
- * @returns {*} Transformed data.
- */
-function transformData(data, headers, fns) {
- if (isFunction(fns))
- return fns(data, headers);
-
- forEach(fns, function(fn) {
- data = fn(data, headers);
- });
-
- return data;
-}
-
-
-function isSuccess(status) {
- return 200 <= status && status < 300;
-}
-
-
-/**
- * @ngdoc provider
- * @name $httpProvider
- * @description
- * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
- * */
-function $HttpProvider() {
- var JSON_START = /^\s*(\[|\{[^\{])/,
- JSON_END = /[\}\]]\s*$/,
- PROTECTION_PREFIX = /^\)\]\}',?\n/,
- CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
-
- /**
- * @ngdoc property
- * @name $httpProvider#defaults
- * @description
- *
- * Object containing default values for all {@link ng.$http $http} requests.
- *
- * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
- * Defaults value is `'XSRF-TOKEN'`.
- *
- * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
- * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
- *
- * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
- * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
- * setting default headers.
- * - **`defaults.headers.common`**
- * - **`defaults.headers.post`**
- * - **`defaults.headers.put`**
- * - **`defaults.headers.patch`**
- **/
- var defaults = this.defaults = {
- // transform incoming response data
- transformResponse: [function(data) {
- if (isString(data)) {
- // strip json vulnerability protection prefix
- data = data.replace(PROTECTION_PREFIX, '');
- if (JSON_START.test(data) && JSON_END.test(data))
- data = fromJson(data);
- }
- return data;
- }],
-
- // transform outgoing request data
- transformRequest: [function(d) {
- return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
- }],
-
- // default headers
- headers: {
- common: {
- 'Accept': 'application/json, text/plain, */*'
- },
- post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
- },
-
- xsrfCookieName: 'XSRF-TOKEN',
- xsrfHeaderName: 'X-XSRF-TOKEN'
- };
-
- /**
- * Are ordered by request, i.e. they are applied in the same order as the
- * array, on request, but reverse order, on response.
- */
- var interceptorFactories = this.interceptors = [];
-
- /**
- * For historical reasons, response interceptors are ordered by the order in which
- * they are applied to the response. (This is the opposite of interceptorFactories)
- */
- var responseInterceptorFactories = this.responseInterceptors = [];
-
- this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
- function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
-
- var defaultCache = $cacheFactory('$http');
-
- /**
- * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
- * The reversal is needed so that we can build up the interception chain around the
- * server request.
- */
- var reversedInterceptors = [];
-
- forEach(interceptorFactories, function(interceptorFactory) {
- reversedInterceptors.unshift(isString(interceptorFactory)
- ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
- });
-
- forEach(responseInterceptorFactories, function(interceptorFactory, index) {
- var responseFn = isString(interceptorFactory)
- ? $injector.get(interceptorFactory)
- : $injector.invoke(interceptorFactory);
-
- /**
- * Response interceptors go before "around" interceptors (no real reason, just
- * had to pick one.) But they are already reversed, so we can't use unshift, hence
- * the splice.
- */
- reversedInterceptors.splice(index, 0, {
- response: function(response) {
- return responseFn($q.when(response));
- },
- responseError: function(response) {
- return responseFn($q.reject(response));
- }
- });
- });
-
-
- /**
- * @ngdoc service
- * @kind function
- * @name $http
- * @requires ng.$httpBackend
- * @requires $cacheFactory
- * @requires $rootScope
- * @requires $q
- * @requires $injector
- *
- * @description
- * The `$http` service is a core Angular service that facilitates communication with the remote
- * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
- * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
- *
- * For unit testing applications that use `$http` service, see
- * {@link ngMock.$httpBackend $httpBackend mock}.
- *
- * For a higher level of abstraction, please check out the {@link ngResource.$resource
- * $resource} service.
- *
- * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
- * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
- * it is important to familiarize yourself with these APIs and the guarantees they provide.
- *
- *
- * # General usage
- * The `$http` service is a function which takes a single argument — a configuration object —
- * that is used to generate an HTTP request and returns a {@link ng.$q promise}
- * with two $http specific methods: `success` and `error`.
- *
- * ```js
- * $http({method: 'GET', url: '/someUrl'}).
- * success(function(data, status, headers, config) {
- * // this callback will be called asynchronously
- * // when the response is available
- * }).
- * error(function(data, status, headers, config) {
- * // called asynchronously if an error occurs
- * // or server returns response with an error status.
- * });
- * ```
- *
- * Since the returned value of calling the $http function is a `promise`, you can also use
- * the `then` method to register callbacks, and these callbacks will receive a single argument –
- * an object representing the response. See the API signature and type info below for more
- * details.
- *
- * A response status code between 200 and 299 is considered a success status and
- * will result in the success callback being called. Note that if the response is a redirect,
- * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
- * called for such responses.
- *
- * # Writing Unit Tests that use $http
- * When unit testing (using {@link ngMock ngMock}), it is necessary to call
- * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
- * request using trained responses.
- *
- * ```
- * $httpBackend.expectGET(...);
- * $http.get(...);
- * $httpBackend.flush();
- * ```
- *
- * # Shortcut methods
- *
- * Shortcut methods are also available. All shortcut methods require passing in the URL, and
- * request data must be passed in for POST/PUT requests.
- *
- * ```js
- * $http.get('/someUrl').success(successCallback);
- * $http.post('/someUrl', data).success(successCallback);
- * ```
- *
- * Complete list of shortcut methods:
- *
- * - {@link ng.$http#get $http.get}
- * - {@link ng.$http#head $http.head}
- * - {@link ng.$http#post $http.post}
- * - {@link ng.$http#put $http.put}
- * - {@link ng.$http#delete $http.delete}
- * - {@link ng.$http#jsonp $http.jsonp}
- * - {@link ng.$http#patch $http.patch}
- *
- *
- * # Setting HTTP Headers
- *
- * The $http service will automatically add certain HTTP headers to all requests. These defaults
- * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
- * object, which currently contains this default configuration:
- *
- * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
- * - `Accept: application/json, text/plain, * / *`
- * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
- * - `Content-Type: application/json`
- * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
- * - `Content-Type: application/json`
- *
- * To add or overwrite these defaults, simply add or remove a property from these configuration
- * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
- * with the lowercased HTTP method name as the key, e.g.
- * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
- *
- * The defaults can also be set at runtime via the `$http.defaults` object in the same
- * fashion. For example:
- *
- * ```
- * module.run(function($http) {
- * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
- * });
- * ```
- *
- * In addition, you can supply a `headers` property in the config object passed when
- * calling `$http(config)`, which overrides the defaults without changing them globally.
- *
- *
- * # Transforming Requests and Responses
- *
- * Both requests and responses can be transformed using transform functions. By default, Angular
- * applies these transformations:
- *
- * Request transformations:
- *
- * - If the `data` property of the request configuration object contains an object, serialize it
- * into JSON format.
- *
- * Response transformations:
- *
- * - If XSRF prefix is detected, strip it (see Security Considerations section below).
- * - If JSON response is detected, deserialize it using a JSON parser.
- *
- * To globally augment or override the default transforms, modify the
- * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
- * properties. These properties are by default an array of transform functions, which allows you
- * to `push` or `unshift` a new transformation function into the transformation chain. You can
- * also decide to completely override any default transformations by assigning your
- * transformation functions to these properties directly without the array wrapper. These defaults
- * are again available on the $http factory at run-time, which may be useful if you have run-time
- * services you wish to be involved in your transformations.
- *
- * Similarly, to locally override the request/response transforms, augment the
- * `transformRequest` and/or `transformResponse` properties of the configuration object passed
- * into `$http`.
- *
- *
- * # Caching
- *
- * To enable caching, set the request configuration `cache` property to `true` (to use default
- * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
- * When the cache is enabled, `$http` stores the response from the server in the specified
- * cache. The next time the same request is made, the response is served from the cache without
- * sending a request to the server.
- *
- * Note that even if the response is served from cache, delivery of the data is asynchronous in
- * the same way that real requests are.
- *
- * If there are multiple GET requests for the same URL that should be cached using the same
- * cache, but the cache is not populated yet, only one request to the server will be made and
- * the remaining requests will be fulfilled using the response from the first request.
- *
- * You can change the default cache to a new object (built with
- * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
- * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set
- * their `cache` property to `true` will now use this cache object.
- *
- * If you set the default cache to `false` then only requests that specify their own custom
- * cache object will be cached.
- *
- * # Interceptors
- *
- * Before you start creating interceptors, be sure to understand the
- * {@link ng.$q $q and deferred/promise APIs}.
- *
- * For purposes of global error handling, authentication, or any kind of synchronous or
- * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
- * able to intercept requests before they are handed to the server and
- * responses before they are handed over to the application code that
- * initiated these requests. The interceptors leverage the {@link ng.$q
- * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
- *
- * The interceptors are service factories that are registered with the `$httpProvider` by
- * adding them to the `$httpProvider.interceptors` array. The factory is called and
- * injected with dependencies (if specified) and returns the interceptor.
- *
- * There are two kinds of interceptors (and two kinds of rejection interceptors):
- *
- * * `request`: interceptors get called with a http `config` object. The function is free to
- * modify the `config` object or create a new one. The function needs to return the `config`
- * object directly, or a promise containing the `config` or a new `config` object.
- * * `requestError`: interceptor gets called when a previous interceptor threw an error or
- * resolved with a rejection.
- * * `response`: interceptors get called with http `response` object. The function is free to
- * modify the `response` object or create a new one. The function needs to return the `response`
- * object directly, or as a promise containing the `response` or a new `response` object.
- * * `responseError`: interceptor gets called when a previous interceptor threw an error or
- * resolved with a rejection.
- *
- *
- * ```js
- * // register the interceptor as a service
- * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
- * return {
- * // optional method
- * 'request': function(config) {
- * // do something on success
- * return config;
- * },
- *
- * // optional method
- * 'requestError': function(rejection) {
- * // do something on error
- * if (canRecover(rejection)) {
- * return responseOrNewPromise
- * }
- * return $q.reject(rejection);
- * },
- *
- *
- *
- * // optional method
- * 'response': function(response) {
- * // do something on success
- * return response;
- * },
- *
- * // optional method
- * 'responseError': function(rejection) {
- * // do something on error
- * if (canRecover(rejection)) {
- * return responseOrNewPromise
- * }
- * return $q.reject(rejection);
- * }
- * };
- * });
- *
- * $httpProvider.interceptors.push('myHttpInterceptor');
- *
- *
- * // alternatively, register the interceptor via an anonymous factory
- * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
- * return {
- * 'request': function(config) {
- * // same as above
- * },
- *
- * 'response': function(response) {
- * // same as above
- * }
- * };
- * });
- * ```
- *
- * # Response interceptors (DEPRECATED)
- *
- * Before you start creating interceptors, be sure to understand the
- * {@link ng.$q $q and deferred/promise APIs}.
- *
- * For purposes of global error handling, authentication or any kind of synchronous or
- * asynchronous preprocessing of received responses, it is desirable to be able to intercept
- * responses for http requests before they are handed over to the application code that
- * initiated these requests. The response interceptors leverage the {@link ng.$q
- * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
- *
- * The interceptors are service factories that are registered with the $httpProvider by
- * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
- * injected with dependencies (if specified) and returns the interceptor — a function that
- * takes a {@link ng.$q promise} and returns the original or a new promise.
- *
- * ```js
- * // register the interceptor as a service
- * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
- * return function(promise) {
- * return promise.then(function(response) {
- * // do something on success
- * return response;
- * }, function(response) {
- * // do something on error
- * if (canRecover(response)) {
- * return responseOrNewPromise
- * }
- * return $q.reject(response);
- * });
- * }
- * });
- *
- * $httpProvider.responseInterceptors.push('myHttpInterceptor');
- *
- *
- * // register the interceptor via an anonymous factory
- * $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
- * return function(promise) {
- * // same as above
- * }
- * });
- * ```
- *
- *
- * # Security Considerations
- *
- * When designing web applications, consider security threats from:
- *
- * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
- * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
- *
- * Both server and the client must cooperate in order to eliminate these threats. Angular comes
- * pre-configured with strategies that address these issues, but for this to work backend server
- * cooperation is required.
- *
- * ## JSON Vulnerability Protection
- *
- * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
- * allows third party website to turn your JSON resource URL into
- * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
- * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
- * Angular will automatically strip the prefix before processing it as JSON.
- *
- * For example if your server needs to return:
- * ```js
- * ['one','two']
- * ```
- *
- * which is vulnerable to attack, your server can return:
- * ```js
- * )]}',
- * ['one','two']
- * ```
- *
- * Angular will strip the prefix, before processing the JSON.
- *
- *
- * ## Cross Site Request Forgery (XSRF) Protection
- *
- * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
- * an unauthorized site can gain your user's private data. Angular provides a mechanism
- * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
- * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
- * JavaScript that runs on your domain could read the cookie, your server can be assured that
- * the XHR came from JavaScript running on your domain. The header will not be set for
- * cross-domain requests.
- *
- * To take advantage of this, your server needs to set a token in a JavaScript readable session
- * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
- * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
- * that only JavaScript running on your domain could have sent the request. The token must be
- * unique for each user and must be verifiable by the server (to prevent the JavaScript from
- * making up its own tokens). We recommend that the token is a digest of your site's
- * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
- * for added security.
- *
- * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
- * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
- * or the per-request config object.
- *
- *
- * @param {object} config Object describing the request to be made and how it should be
- * processed. The object has following properties:
- *
- * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
- * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
- * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned
- * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
- * JSONified.
- * - **data** – `{string|Object}` – Data to be sent as the request message data.
- * - **headers** – `{Object}` – Map of strings or functions which return strings representing
- * HTTP headers to send to the server. If the return value of a function is null, the
- * header will not be sent.
- * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
- * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
- * - **transformRequest** –
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
- * transform function or an array of such functions. The transform function takes the http
- * request body and headers and returns its transformed (typically serialized) version.
- * - **transformResponse** –
- * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
- * transform function or an array of such functions. The transform function takes the http
- * response body and headers and returns its transformed (typically deserialized) version.
- * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
- * GET request, otherwise if a cache instance built with
- * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
- * caching.
- * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
- * that should abort the request when resolved.
- * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
- * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
- * for more information.
- * - **responseType** - `{string}` - see
- * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
- *
- * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
- * standard `then` method and two http specific methods: `success` and `error`. The `then`
- * method takes two arguments a success and an error callback which will be called with a
- * response object. The `success` and `error` methods take a single argument - a function that
- * will be called when the request succeeds or fails respectively. The arguments passed into
- * these functions are destructured representation of the response object passed into the
- * `then` method. The response object has these properties:
- *
- * - **data** – `{string|Object}` – The response body transformed with the transform
- * functions.
- * - **status** – `{number}` – HTTP status code of the response.
- * - **headers** – `{function([headerName])}` – Header getter function.
- * - **config** – `{Object}` – The configuration object that was used to generate the request.
- * - **statusText** – `{string}` – HTTP status text of the response.
- *
- * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
- * requests. This is primarily meant to be used for debugging purposes.
- *
- *
- * @example
-<example module="httpExample">
-<file name="index.html">
- <div ng-controller="FetchController">
- <select ng-model="method">
- <option>GET</option>
- <option>JSONP</option>
- </select>
- <input type="text" ng-model="url" size="80"/>
- <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
- <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
- <button id="samplejsonpbtn"
- ng-click="updateModel('JSONP',
- 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
- Sample JSONP
- </button>
- <button id="invalidjsonpbtn"
- ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
- Invalid JSONP
- </button>
- <pre>http status code: {{status}}</pre>
- <pre>http response data: {{data}}</pre>
- </div>
-</file>
-<file name="script.js">
- angular.module('httpExample', [])
- .controller('FetchController', ['$scope', '$http', '$templateCache',
- function($scope, $http, $templateCache) {
- $scope.method = 'GET';
- $scope.url = 'http-hello.html';
-
- $scope.fetch = function() {
- $scope.code = null;
- $scope.response = null;
-
- $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
- success(function(data, status) {
- $scope.status = status;
- $scope.data = data;
- }).
- error(function(data, status) {
- $scope.data = data || "Request failed";
- $scope.status = status;
- });
- };
-
- $scope.updateModel = function(method, url) {
- $scope.method = method;
- $scope.url = url;
- };
- }]);
-</file>
-<file name="http-hello.html">
- Hello, $http!
-</file>
-<file name="protractor.js" type="protractor">
- var status = element(by.binding('status'));
- var data = element(by.binding('data'));
- var fetchBtn = element(by.id('fetchbtn'));
- var sampleGetBtn = element(by.id('samplegetbtn'));
- var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
- var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
-
- it('should make an xhr GET request', function() {
- sampleGetBtn.click();
- fetchBtn.click();
- expect(status.getText()).toMatch('200');
- expect(data.getText()).toMatch(/Hello, \$http!/);
- });
-
- it('should make a JSONP request to angularjs.org', function() {
- sampleJsonpBtn.click();
- fetchBtn.click();
- expect(status.getText()).toMatch('200');
- expect(data.getText()).toMatch(/Super Hero!/);
- });
-
- it('should make JSONP request to invalid URL and invoke the error handler',
- function() {
- invalidJsonpBtn.click();
- fetchBtn.click();
- expect(status.getText()).toMatch('0');
- expect(data.getText()).toMatch('Request failed');
- });
-</file>
-</example>
- */
- function $http(requestConfig) {
- var config = {
- method: 'get',
- transformRequest: defaults.transformRequest,
- transformResponse: defaults.transformResponse
- };
- var headers = mergeHeaders(requestConfig);
-
- extend(config, requestConfig);
- config.headers = headers;
- config.method = uppercase(config.method);
-
- var serverRequest = function(config) {
- headers = config.headers;
- var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
-
- // strip content-type if data is undefined
- if (isUndefined(reqData)) {
- forEach(headers, function(value, header) {
- if (lowercase(header) === 'content-type') {
- delete headers[header];
- }
- });
- }
-
- if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
- config.withCredentials = defaults.withCredentials;
- }
-
- // send request
- return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
- };
-
- var chain = [serverRequest, undefined];
- var promise = $q.when(config);
-
- // apply interceptors
- forEach(reversedInterceptors, function(interceptor) {
- if (interceptor.request || interceptor.requestError) {
- chain.unshift(interceptor.request, interceptor.requestError);
- }
- if (interceptor.response || interceptor.responseError) {
- chain.push(interceptor.response, interceptor.responseError);
- }
- });
-
- while(chain.length) {
- var thenFn = chain.shift();
- var rejectFn = chain.shift();
-
- promise = promise.then(thenFn, rejectFn);
- }
-
- promise.success = function(fn) {
- promise.then(function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
-
- promise.error = function(fn) {
- promise.then(null, function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
-
- return promise;
-
- function transformResponse(response) {
- // make a copy since the response must be cacheable
- var resp = extend({}, response, {
- data: transformData(response.data, response.headers, config.transformResponse)
- });
- return (isSuccess(response.status))
- ? resp
- : $q.reject(resp);
- }
-
- function mergeHeaders(config) {
- var defHeaders = defaults.headers,
- reqHeaders = extend({}, config.headers),
- defHeaderName, lowercaseDefHeaderName, reqHeaderName;
-
- defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
-
- // using for-in instead of forEach to avoid unecessary iteration after header has been found
- defaultHeadersIteration:
- for (defHeaderName in defHeaders) {
- lowercaseDefHeaderName = lowercase(defHeaderName);
-
- for (reqHeaderName in reqHeaders) {
- if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
- continue defaultHeadersIteration;
- }
- }
-
- reqHeaders[defHeaderName] = defHeaders[defHeaderName];
- }
-
- // execute if header value is a function for merged headers
- execHeaders(reqHeaders);
- return reqHeaders;
-
- function execHeaders(headers) {
- var headerContent;
-
- forEach(headers, function(headerFn, header) {
- if (isFunction(headerFn)) {
- headerContent = headerFn();
- if (headerContent != null) {
- headers[header] = headerContent;
- } else {
- delete headers[header];
- }
- }
- });
- }
- }
- }
-
- $http.pendingRequests = [];
-
- /**
- * @ngdoc method
- * @name $http#get
- *
- * @description
- * Shortcut method to perform `GET` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#delete
- *
- * @description
- * Shortcut method to perform `DELETE` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#head
- *
- * @description
- * Shortcut method to perform `HEAD` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#jsonp
- *
- * @description
- * Shortcut method to perform `JSONP` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request.
- * The name of the callback should be the string `JSON_CALLBACK`.
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
- createShortMethods('get', 'delete', 'head', 'jsonp');
-
- /**
- * @ngdoc method
- * @name $http#post
- *
- * @description
- * Shortcut method to perform `POST` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {*} data Request content
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
-
- /**
- * @ngdoc method
- * @name $http#put
- *
- * @description
- * Shortcut method to perform `PUT` request.
- *
- * @param {string} url Relative or absolute URL specifying the destination of the request
- * @param {*} data Request content
- * @param {Object=} config Optional configuration object
- * @returns {HttpPromise} Future object
- */
- createShortMethodsWithData('post', 'put');
-
- /**
- * @ngdoc property
- * @name $http#defaults
- *
- * @description
- * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
- * default headers, withCredentials as well as request and response transformations.
- *
- * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
- */
- $http.defaults = defaults;
-
-
- return $http;
-
-
- function createShortMethods(names) {
- forEach(arguments, function(name) {
- $http[name] = function(url, config) {
- return $http(extend(config || {}, {
- method: name,
- url: url
- }));
- };
- });
- }
-
-
- function createShortMethodsWithData(name) {
- forEach(arguments, function(name) {
- $http[name] = function(url, data, config) {
- return $http(extend(config || {}, {
- method: name,
- url: url,
- data: data
- }));
- };
- });
- }
-
-
- /**
- * Makes the request.
- *
- * !!! ACCESSES CLOSURE VARS:
- * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
- */
- function sendReq(config, reqData, reqHeaders) {
- var deferred = $q.defer(),
- promise = deferred.promise,
- cache,
- cachedResp,
- url = buildUrl(config.url, config.params);
-
- $http.pendingRequests.push(config);
- promise.then(removePendingReq, removePendingReq);
-
-
- if ((config.cache || defaults.cache) && config.cache !== false &&
- (config.method === 'GET' || config.method === 'JSONP')) {
- cache = isObject(config.cache) ? config.cache
- : isObject(defaults.cache) ? defaults.cache
- : defaultCache;
- }
-
- if (cache) {
- cachedResp = cache.get(url);
- if (isDefined(cachedResp)) {
- if (isPromiseLike(cachedResp)) {
- // cached request has already been sent, but there is no response yet
- cachedResp.then(removePendingReq, removePendingReq);
- return cachedResp;
- } else {
- // serving from cache
- if (isArray(cachedResp)) {
- resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
- } else {
- resolvePromise(cachedResp, 200, {}, 'OK');
- }
- }
- } else {
- // put the promise for the non-transformed response into cache as a placeholder
- cache.put(url, promise);
- }
- }
-
-
- // if we won't have the response in cache, set the xsrf headers and
- // send the request to the backend
- if (isUndefined(cachedResp)) {
- var xsrfValue = urlIsSameOrigin(config.url)
- ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
- : undefined;
- if (xsrfValue) {
- reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
- }
-
- $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
- config.withCredentials, config.responseType);
- }
-
- return promise;
-
-
- /**
- * Callback registered to $httpBackend():
- * - caches the response if desired
- * - resolves the raw $http promise
- * - calls $apply
- */
- function done(status, response, headersString, statusText) {
- if (cache) {
- if (isSuccess(status)) {
- cache.put(url, [status, response, parseHeaders(headersString), statusText]);
- } else {
- // remove promise from the cache
- cache.remove(url);
- }
- }
-
- resolvePromise(response, status, headersString, statusText);
- if (!$rootScope.$$phase) $rootScope.$apply();
- }
-
-
- /**
- * Resolves the raw $http promise.
- */
- function resolvePromise(response, status, headers, statusText) {
- // normalize internal statuses to 0
- status = Math.max(status, 0);
-
- (isSuccess(status) ? deferred.resolve : deferred.reject)({
- data: response,
- status: status,
- headers: headersGetter(headers),
- config: config,
- statusText : statusText
- });
- }
-
-
- function removePendingReq() {
- var idx = indexOf($http.pendingRequests, config);
- if (idx !== -1) $http.pendingRequests.splice(idx, 1);
- }
- }
-
-
- function buildUrl(url, params) {
- if (!params) return url;
- var parts = [];
- forEachSorted(params, function(value, key) {
- if (value === null || isUndefined(value)) return;
- if (!isArray(value)) value = [value];
-
- forEach(value, function(v) {
- if (isObject(v)) {
- if (isDate(v)){
- v = v.toISOString();
- } else {
- v = toJson(v);
- }
- }
- parts.push(encodeUriQuery(key) + '=' +
- encodeUriQuery(v));
- });
- });
- if(parts.length > 0) {
- url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
- }
- return url;
- }
- }];
-}
-
-function createXhr(method) {
- //if IE and the method is not RFC2616 compliant, or if XMLHttpRequest
- //is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest
- //if it is available
- if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||
- !window.XMLHttpRequest)) {
- return new window.ActiveXObject("Microsoft.XMLHTTP");
- } else if (window.XMLHttpRequest) {
- return new window.XMLHttpRequest();
- }
-
- throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
-}
-
-/**
- * @ngdoc service
- * @name $httpBackend
- * @requires $window
- * @requires $document
- *
- * @description
- * HTTP backend used by the {@link ng.$http service} that delegates to
- * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
- *
- * You should never need to use this service directly, instead use the higher-level abstractions:
- * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
- *
- * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
- * $httpBackend} which can be trained with responses.
- */
-function $HttpBackendProvider() {
- this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
- return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
- }];
-}
-
-function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
- var ABORTED = -1;
-
- // TODO(vojta): fix the signature
- return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
- var status;
- $browser.$$incOutstandingRequestCount();
- url = url || $browser.url();
-
- if (lowercase(method) == 'jsonp') {
- var callbackId = '_' + (callbacks.counter++).toString(36);
- callbacks[callbackId] = function(data) {
- callbacks[callbackId].data = data;
- callbacks[callbackId].called = true;
- };
-
- var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
- callbackId, function(status, text) {
- completeRequest(callback, status, callbacks[callbackId].data, "", text);
- callbacks[callbackId] = noop;
- });
- } else {
-
- var xhr = createXhr(method);
-
- xhr.open(method, url, true);
- forEach(headers, function(value, key) {
- if (isDefined(value)) {
- xhr.setRequestHeader(key, value);
- }
- });
-
- // In IE6 and 7, this might be called synchronously when xhr.send below is called and the
- // response is in the cache. the promise api will ensure that to the app code the api is
- // always async
- xhr.onreadystatechange = function() {
- // onreadystatechange might get called multiple times with readyState === 4 on mobile webkit caused by
- // xhrs that are resolved while the app is in the background (see #5426).
- // since calling completeRequest sets the `xhr` variable to null, we just check if it's not null before
- // continuing
- //
- // we can't set xhr.onreadystatechange to undefined or delete it because that breaks IE8 (method=PATCH) and
- // Safari respectively.
- if (xhr && xhr.readyState == 4) {
- var responseHeaders = null,
- response = null,
- statusText = '';
-
- if(status !== ABORTED) {
- responseHeaders = xhr.getAllResponseHeaders();
-
- // responseText is the old-school way of retrieving response (supported by IE8 & 9)
- // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
- response = ('response' in xhr) ? xhr.response : xhr.responseText;
- }
-
- // Accessing statusText on an aborted xhr object will
- // throw an 'c00c023f error' in IE9 and lower, don't touch it.
- if (!(status === ABORTED && msie < 10)) {
- statusText = xhr.statusText;
- }
-
- completeRequest(callback,
- status || xhr.status,
- response,
- responseHeaders,
- statusText);
- }
- };
-
- if (withCredentials) {
- xhr.withCredentials = true;
- }
-
- if (responseType) {
- try {
- xhr.responseType = responseType;
- } catch (e) {
- // WebKit added support for the json responseType value on 09/03/2013
- // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
- // known to throw when setting the value "json" as the response type. Other older
- // browsers implementing the responseType
- //
- // The json response type can be ignored if not supported, because JSON payloads are
- // parsed on the client-side regardless.
- if (responseType !== 'json') {
- throw e;
- }
- }
- }
-
- xhr.send(post || null);
- }
-
- if (timeout > 0) {
- var timeoutId = $browserDefer(timeoutRequest, timeout);
- } else if (isPromiseLike(timeout)) {
- timeout.then(timeoutRequest);
- }
-
-
- function timeoutRequest() {
- status = ABORTED;
- jsonpDone && jsonpDone();
- xhr && xhr.abort();
- }
-
- function completeRequest(callback, status, response, headersString, statusText) {
- // cancel timeout and subsequent timeout promise resolution
- timeoutId && $browserDefer.cancel(timeoutId);
- jsonpDone = xhr = null;
-
- // fix status code when it is 0 (0 status is undocumented).
- // Occurs when accessing file resources or on Android 4.1 stock browser
- // while retrieving files from application cache.
- if (status === 0) {
- status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
- }
-
- // normalize IE bug (http://bugs.jquery.com/ticket/1450)
- status = status === 1223 ? 204 : status;
- statusText = statusText || '';
-
- callback(status, response, headersString, statusText);
- $browser.$$completeOutstandingRequest(noop);
- }
- };
-
- function jsonpReq(url, callbackId, done) {
- // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
- // - fetches local scripts via XHR and evals them
- // - adds and immediately removes script elements from the document
- var script = rawDocument.createElement('script'), callback = null;
- script.type = "text/javascript";
- script.src = url;
- script.async = true;
-
- callback = function(event) {
- removeEventListenerFn(script, "load", callback);
- removeEventListenerFn(script, "error", callback);
- rawDocument.body.removeChild(script);
- script = null;
- var status = -1;
- var text = "unknown";
-
- if (event) {
- if (event.type === "load" && !callbacks[callbackId].called) {
- event = { type: "error" };
- }
- text = event.type;
- status = event.type === "error" ? 404 : 200;
- }
-
- if (done) {
- done(status, text);
- }
- };
-
- addEventListenerFn(script, "load", callback);
- addEventListenerFn(script, "error", callback);
-
- if (msie <= 8) {
- script.onreadystatechange = function() {
- if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
- script.onreadystatechange = null;
- callback({
- type: 'load'
- });
- }
- };
- }
-
- rawDocument.body.appendChild(script);
- return callback;
- }
-}
-
-var $interpolateMinErr = minErr('$interpolate');
-
-/**
- * @ngdoc provider
- * @name $interpolateProvider
- * @kind function
- *
- * @description
- *
- * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
- *
- * @example
-<example module="customInterpolationApp">
-<file name="index.html">
-<script>
- var customInterpolationApp = angular.module('customInterpolationApp', []);
-
- customInterpolationApp.config(function($interpolateProvider) {
- $interpolateProvider.startSymbol('//');
- $interpolateProvider.endSymbol('//');
- });
-
-
- customInterpolationApp.controller('DemoController', function() {
- this.label = "This binding is brought you by // interpolation symbols.";
- });
-</script>
-<div ng-app="App" ng-controller="DemoController as demo">
- //demo.label//
-</div>
-</file>
-<file name="protractor.js" type="protractor">
- it('should interpolate binding with custom symbols', function() {
- expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
- });
-</file>
-</example>
- */
-function $InterpolateProvider() {
- var startSymbol = '{{';
- var endSymbol = '}}';
-
- /**
- * @ngdoc method
- * @name $interpolateProvider#startSymbol
- * @description
- * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
- *
- * @param {string=} value new value to set the starting symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.startSymbol = function(value){
- if (value) {
- startSymbol = value;
- return this;
- } else {
- return startSymbol;
- }
- };
-
- /**
- * @ngdoc method
- * @name $interpolateProvider#endSymbol
- * @description
- * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
- *
- * @param {string=} value new value to set the ending symbol to.
- * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
- */
- this.endSymbol = function(value){
- if (value) {
- endSymbol = value;
- return this;
- } else {
- return endSymbol;
- }
- };
-
-
- this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
- var startSymbolLength = startSymbol.length,
- endSymbolLength = endSymbol.length;
-
- /**
- * @ngdoc service
- * @name $interpolate
- * @kind function
- *
- * @requires $parse
- * @requires $sce
- *
- * @description
- *
- * Compiles a string with markup into an interpolation function. This service is used by the
- * HTML {@link ng.$compile $compile} service for data binding. See
- * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
- * interpolation markup.
- *
- *
- * ```js
- * var $interpolate = ...; // injected
- * var exp = $interpolate('Hello {{name | uppercase}}!');
- * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
- * ```
- *
- *
- * @param {string} text The text with markup to interpolate.
- * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
- * embedded expression in order to return an interpolation function. Strings with no
- * embedded expression will return null for the interpolation function.
- * @param {string=} trustedContext when provided, the returned function passes the interpolated
- * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
- * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
- * provides Strict Contextual Escaping for details.
- * @returns {function(context)} an interpolation function which is used to compute the
- * interpolated string. The function has these parameters:
- *
- * * `context`: an object against which any expressions embedded in the strings are evaluated
- * against.
- *
- */
- function $interpolate(text, mustHaveExpression, trustedContext) {
- var startIndex,
- endIndex,
- index = 0,
- parts = [],
- length = text.length,
- hasInterpolation = false,
- fn,
- exp,
- concat = [];
-
- while(index < length) {
- if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
- ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
- (index != startIndex) && parts.push(text.substring(index, startIndex));
- parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
- fn.exp = exp;
- index = endIndex + endSymbolLength;
- hasInterpolation = true;
- } else {
- // we did not find anything, so we have to add the remainder to the parts array
- (index != length) && parts.push(text.substring(index));
- index = length;
- }
- }
-
- if (!(length = parts.length)) {
- // we added, nothing, must have been an empty string.
- parts.push('');
- length = 1;
- }
-
- // Concatenating expressions makes it hard to reason about whether some combination of
- // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
- // single expression be used for iframe[src], object[src], etc., we ensure that the value
- // that's used is assigned or constructed by some JS code somewhere that is more testable or
- // make it obvious that you bound the value to some user controlled value. This helps reduce
- // the load when auditing for XSS issues.
- if (trustedContext && parts.length > 1) {
- throw $interpolateMinErr('noconcat',
- "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
- "interpolations that concatenate multiple expressions when a trusted value is " +
- "required. See http://docs.angularjs.org/api/ng.$sce", text);
- }
-
- if (!mustHaveExpression || hasInterpolation) {
- concat.length = length;
- fn = function(context) {
- try {
- for(var i = 0, ii = length, part; i<ii; i++) {
- if (typeof (part = parts[i]) == 'function') {
- part = part(context);
- if (trustedContext) {
- part = $sce.getTrusted(trustedContext, part);
- } else {
- part = $sce.valueOf(part);
- }
- if (part == null) { // null || undefined
- part = '';
- } else {
- switch (typeof part) {
- case 'string':
- {
- break;
- }
- case 'number':
- {
- part = '' + part;
- break;
- }
- default:
- {
- part = toJson(part);
- }
- }
- }
- }
- concat[i] = part;
- }
- return concat.join('');
- }
- catch(err) {
- var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
- err.toString());
- $exceptionHandler(newErr);
- }
- };
- fn.exp = text;
- fn.parts = parts;
- return fn;
- }
- }
-
-
- /**
- * @ngdoc method
- * @name $interpolate#startSymbol
- * @description
- * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
- *
- * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
- * the symbol.
- *
- * @returns {string} start symbol.
- */
- $interpolate.startSymbol = function() {
- return startSymbol;
- };
-
-
- /**
- * @ngdoc method
- * @name $interpolate#endSymbol
- * @description
- * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
- *
- * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
- * the symbol.
- *
- * @returns {string} end symbol.
- */
- $interpolate.endSymbol = function() {
- return endSymbol;
- };
-
- return $interpolate;
- }];
-}
-
-function $IntervalProvider() {
- this.$get = ['$rootScope', '$window', '$q',
- function($rootScope, $window, $q) {
- var intervals = {};
-
-
- /**
- * @ngdoc service
- * @name $interval
- *
- * @description
- * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
- * milliseconds.
- *
- * The return value of registering an interval function is a promise. This promise will be
- * notified upon each tick of the interval, and will be resolved after `count` iterations, or
- * run indefinitely if `count` is not defined. The value of the notification will be the
- * number of iterations that have run.
- * To cancel an interval, call `$interval.cancel(promise)`.
- *
- * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
- * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
- * time.
- *
- * <div class="alert alert-warning">
- * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
- * with them. In particular they are not automatically destroyed when a controller's scope or a
- * directive's element are destroyed.
- * You should take this into consideration and make sure to always cancel the interval at the
- * appropriate moment. See the example below for more details on how and when to do this.
- * </div>
- *
- * @param {function()} fn A function that should be called repeatedly.
- * @param {number} delay Number of milliseconds between each function call.
- * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
- * indefinitely.
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
- * @returns {promise} A promise which will be notified on each iteration.
- *
- * @example
- * <example module="intervalExample">
- * <file name="index.html">
- * <script>
- * angular.module('intervalExample', [])
- * .controller('ExampleController', ['$scope', '$interval',
- * function($scope, $interval) {
- * $scope.format = 'M/d/yy h:mm:ss a';
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
- *
- * var stop;
- * $scope.fight = function() {
- * // Don't start a new fight if we are already fighting
- * if ( angular.isDefined(stop) ) return;
- *
- * stop = $interval(function() {
- * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
- * $scope.blood_1 = $scope.blood_1 - 3;
- * $scope.blood_2 = $scope.blood_2 - 4;
- * } else {
- * $scope.stopFight();
- * }
- * }, 100);
- * };
- *
- * $scope.stopFight = function() {
- * if (angular.isDefined(stop)) {
- * $interval.cancel(stop);
- * stop = undefined;
- * }
- * };
- *
- * $scope.resetFight = function() {
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
- * };
- *
- * $scope.$on('$destroy', function() {
- * // Make sure that the interval is destroyed too
- * $scope.stopFight();
- * });
- * }])
- * // Register the 'myCurrentTime' directive factory method.
- * // We inject $interval and dateFilter service since the factory method is DI.
- * .directive('myCurrentTime', ['$interval', 'dateFilter',
- * function($interval, dateFilter) {
- * // return the directive link function. (compile function not needed)
- * return function(scope, element, attrs) {
- * var format, // date format
- * stopTime; // so that we can cancel the time updates
- *
- * // used to update the UI
- * function updateTime() {
- * element.text(dateFilter(new Date(), format));
- * }
- *
- * // watch the expression, and update the UI on change.
- * scope.$watch(attrs.myCurrentTime, function(value) {
- * format = value;
- * updateTime();
- * });
- *
- * stopTime = $interval(updateTime, 1000);
- *
- * // listen on DOM destroy (removal) event, and cancel the next UI update
- * // to prevent updating time after the DOM element was removed.
- * element.bind('$destroy', function() {
- * $interval.cancel(stopTime);
- * });
- * }
- * }]);
- * </script>
- *
- * <div>
- * <div ng-controller="ExampleController">
- * Date format: <input ng-model="format"> <hr/>
- * Current time is: <span my-current-time="format"></span>
- * <hr/>
- * Blood 1 : <font color='red'>{{blood_1}}</font>
- * Blood 2 : <font color='red'>{{blood_2}}</font>
- * <button type="button" data-ng-click="fight()">Fight</button>
- * <button type="button" data-ng-click="stopFight()">StopFight</button>
- * <button type="button" data-ng-click="resetFight()">resetFight</button>
- * </div>
- * </div>
- *
- * </file>
- * </example>
- */
- function interval(fn, delay, count, invokeApply) {
- var setInterval = $window.setInterval,
- clearInterval = $window.clearInterval,
- deferred = $q.defer(),
- promise = deferred.promise,
- iteration = 0,
- skipApply = (isDefined(invokeApply) && !invokeApply);
-
- count = isDefined(count) ? count : 0;
-
- promise.then(null, null, fn);
-
- promise.$$intervalId = setInterval(function tick() {
- deferred.notify(iteration++);
-
- if (count > 0 && iteration >= count) {
- deferred.resolve(iteration);
- clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- }
-
- if (!skipApply) $rootScope.$apply();
-
- }, delay);
-
- intervals[promise.$$intervalId] = deferred;
-
- return promise;
- }
-
-
- /**
- * @ngdoc method
- * @name $interval#cancel
- *
- * @description
- * Cancels a task associated with the `promise`.
- *
- * @param {promise} promise returned by the `$interval` function.
- * @returns {boolean} Returns `true` if the task was successfully canceled.
- */
- interval.cancel = function(promise) {
- if (promise && promise.$$intervalId in intervals) {
- intervals[promise.$$intervalId].reject('canceled');
- $window.clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- return true;
- }
- return false;
- };
-
- return interval;
- }];
-}
-
-/**
- * @ngdoc service
- * @name $locale
- *
- * @description
- * $locale service provides localization rules for various Angular components. As of right now the
- * only public api is:
- *
- * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
- */
-function $LocaleProvider(){
- this.$get = function() {
- return {
- id: 'en-us',
-
- NUMBER_FORMATS: {
- DECIMAL_SEP: '.',
- GROUP_SEP: ',',
- PATTERNS: [
- { // Decimal Pattern
- minInt: 1,
- minFrac: 0,
- maxFrac: 3,
- posPre: '',
- posSuf: '',
- negPre: '-',
- negSuf: '',
- gSize: 3,
- lgSize: 3
- },{ //Currency Pattern
- minInt: 1,
- minFrac: 2,
- maxFrac: 2,
- posPre: '\u00A4',
- posSuf: '',
- negPre: '(\u00A4',
- negSuf: ')',
- gSize: 3,
- lgSize: 3
- }
- ],
- CURRENCY_SYM: '$'
- },
-
- DATETIME_FORMATS: {
- MONTH:
- 'January,February,March,April,May,June,July,August,September,October,November,December'
- .split(','),
- SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
- DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
- SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
- AMPMS: ['AM','PM'],
- medium: 'MMM d, y h:mm:ss a',
- short: 'M/d/yy h:mm a',
- fullDate: 'EEEE, MMMM d, y',
- longDate: 'MMMM d, y',
- mediumDate: 'MMM d, y',
- shortDate: 'M/d/yy',
- mediumTime: 'h:mm:ss a',
- shortTime: 'h:mm a'
- },
-
- pluralCat: function(num) {
- if (num === 1) {
- return 'one';
- }
- return 'other';
- }
- };
- };
-}
-
-var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
- DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
-var $locationMinErr = minErr('$location');
-
-
-/**
- * Encode path using encodeUriSegment, ignoring forward slashes
- *
- * @param {string} path Path to encode
- * @returns {string}
- */
-function encodePath(path) {
- var segments = path.split('/'),
- i = segments.length;
-
- while (i--) {
- segments[i] = encodeUriSegment(segments[i]);
- }
-
- return segments.join('/');
-}
-
-function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
- var parsedUrl = urlResolve(absoluteUrl, appBase);
-
- locationObj.$$protocol = parsedUrl.protocol;
- locationObj.$$host = parsedUrl.hostname;
- locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
-}
-
-
-function parseAppUrl(relativeUrl, locationObj, appBase) {
- var prefixed = (relativeUrl.charAt(0) !== '/');
- if (prefixed) {
- relativeUrl = '/' + relativeUrl;
- }
- var match = urlResolve(relativeUrl, appBase);
- locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
- match.pathname.substring(1) : match.pathname);
- locationObj.$$search = parseKeyValue(match.search);
- locationObj.$$hash = decodeURIComponent(match.hash);
-
- // make sure path starts with '/';
- if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
- locationObj.$$path = '/' + locationObj.$$path;
- }
-}
-
-
-/**
- *
- * @param {string} begin
- * @param {string} whole
- * @returns {string} returns text from whole after begin or undefined if it does not begin with
- * expected string.
- */
-function beginsWith(begin, whole) {
- if (whole.indexOf(begin) === 0) {
- return whole.substr(begin.length);
- }
-}
-
-
-function stripHash(url) {
- var index = url.indexOf('#');
- return index == -1 ? url : url.substr(0, index);
-}
-
-
-function stripFile(url) {
- return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
-}
-
-/* return the server only (scheme://host:port) */
-function serverBase(url) {
- return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
-}
-
-
-/**
- * LocationHtml5Url represents an url
- * This object is exposed as $location service when HTML5 mode is enabled and supported
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} basePrefix url path prefix
- */
-function LocationHtml5Url(appBase, basePrefix) {
- this.$$html5 = true;
- basePrefix = basePrefix || '';
- var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this, appBase);
-
-
- /**
- * Parse given html5 (regular) url string into properties
- * @param {string} newAbsoluteUrl HTML5 url
- * @private
- */
- this.$$parse = function(url) {
- var pathUrl = beginsWith(appBaseNoFile, url);
- if (!isString(pathUrl)) {
- throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
- appBaseNoFile);
- }
-
- parseAppUrl(pathUrl, this, appBase);
-
- if (!this.$$path) {
- this.$$path = '/';
- }
-
- this.$$compose();
- };
-
- /**
- * Compose url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
- };
-
- this.$$rewrite = function(url) {
- var appUrl, prevAppUrl;
-
- if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
- prevAppUrl = appUrl;
- if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
- return appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
- } else {
- return appBase + prevAppUrl;
- }
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
- return appBaseNoFile + appUrl;
- } else if (appBaseNoFile == url + '/') {
- return appBaseNoFile;
- }
- };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when developer doesn't opt into html5 mode.
- * It also serves as the base class for html5 mode fallback on legacy browsers.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangUrl(appBase, hashPrefix) {
- var appBaseNoFile = stripFile(appBase);
-
- parseAbsoluteUrl(appBase, this, appBase);
-
-
- /**
- * Parse given hashbang url into properties
- * @param {string} url Hashbang url
- * @private
- */
- this.$$parse = function(url) {
- var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
- var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
- ? beginsWith(hashPrefix, withoutBaseUrl)
- : (this.$$html5)
- ? withoutBaseUrl
- : '';
-
- if (!isString(withoutHashUrl)) {
- throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
- hashPrefix);
- }
- parseAppUrl(withoutHashUrl, this, appBase);
-
- this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
-
- this.$$compose();
-
- /*
- * In Windows, on an anchor node on documents loaded from
- * the filesystem, the browser will return a pathname
- * prefixed with the drive name ('/C:/path') when a
- * pathname without a drive is set:
- * * a.setAttribute('href', '/foo')
- * * a.pathname === '/C:/foo' //true
- *
- * Inside of Angular, we're always using pathnames that
- * do not include drive names for routing.
- */
- function removeWindowsDriveName (path, url, base) {
- /*
- Matches paths for file protocol on windows,
- such as /C:/foo/bar, and captures only /foo/bar.
- */
- var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
-
- var firstPathSegmentMatch;
-
- //Get the relative path from the input URL.
- if (url.indexOf(base) === 0) {
- url = url.replace(base, '');
- }
-
- // The input URL intentionally contains a first path segment that ends with a colon.
- if (windowsFilePathExp.exec(url)) {
- return path;
- }
-
- firstPathSegmentMatch = windowsFilePathExp.exec(path);
- return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
- }
- };
-
- /**
- * Compose hashbang url and update `absUrl` property
- * @private
- */
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
- };
-
- this.$$rewrite = function(url) {
- if(stripHash(appBase) == stripHash(url)) {
- return url;
- }
- };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when html5 history api is enabled but the browser
- * does not support it.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangInHtml5Url(appBase, hashPrefix) {
- this.$$html5 = true;
- LocationHashbangUrl.apply(this, arguments);
-
- var appBaseNoFile = stripFile(appBase);
-
- this.$$rewrite = function(url) {
- var appUrl;
-
- if ( appBase == stripHash(url) ) {
- return url;
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
- return appBase + hashPrefix + appUrl;
- } else if ( appBaseNoFile === url + '/') {
- return appBaseNoFile;
- }
- };
-
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
- this.$$absUrl = appBase + hashPrefix + this.$$url;
- };
-
-}
-
-
-LocationHashbangInHtml5Url.prototype =
- LocationHashbangUrl.prototype =
- LocationHtml5Url.prototype = {
-
- /**
- * Are we in html5 mode?
- * @private
- */
- $$html5: false,
-
- /**
- * Has any change been replacing ?
- * @private
- */
- $$replace: false,
-
- /**
- * @ngdoc method
- * @name $location#absUrl
- *
- * @description
- * This method is getter only.
- *
- * Return full url representation with all segments encoded according to rules specified in
- * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
- *
- * @return {string} full url
- */
- absUrl: locationGetter('$$absUrl'),
-
- /**
- * @ngdoc method
- * @name $location#url
- *
- * @description
- * This method is getter / setter.
- *
- * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
- *
- * Change path, search and hash, when called with parameter and return `$location`.
- *
- * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
- * @return {string} url
- */
- url: function(url) {
- if (isUndefined(url))
- return this.$$url;
-
- var match = PATH_MATCH.exec(url);
- if (match[1]) this.path(decodeURIComponent(match[1]));
- if (match[2] || match[1]) this.search(match[3] || '');
- this.hash(match[5] || '');
-
- return this;
- },
-
- /**
- * @ngdoc method
- * @name $location#protocol
- *
- * @description
- * This method is getter only.
- *
- * Return protocol of current url.
- *
- * @return {string} protocol of current url
- */
- protocol: locationGetter('$$protocol'),
-
- /**
- * @ngdoc method
- * @name $location#host
- *
- * @description
- * This method is getter only.
- *
- * Return host of current url.
- *
- * @return {string} host of current url.
- */
- host: locationGetter('$$host'),
-
- /**
- * @ngdoc method
- * @name $location#port
- *
- * @description
- * This method is getter only.
- *
- * Return port of current url.
- *
- * @return {Number} port
- */
- port: locationGetter('$$port'),
-
- /**
- * @ngdoc method
- * @name $location#path
- *
- * @description
- * This method is getter / setter.
- *
- * Return path of current url when called without any parameter.
- *
- * Change path when called with parameter and return `$location`.
- *
- * Note: Path should always begin with forward slash (/), this method will add the forward slash
- * if it is missing.
- *
- * @param {(string|number)=} path New path
- * @return {string} path
- */
- path: locationGetterSetter('$$path', function(path) {
- path = path ? path.toString() : '';
- return path.charAt(0) == '/' ? path : '/' + path;
- }),
-
- /**
- * @ngdoc method
- * @name $location#search
- *
- * @description
- * This method is getter / setter.
- *
- * Return search part (as object) of current url when called without any parameter.
- *
- * Change search part when called with parameter and return `$location`.
- *
- *
- * ```js
- * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
- * var searchObject = $location.search();
- * // => {foo: 'bar', baz: 'xoxo'}
- *
- *
- * // set foo to 'yipee'
- * $location.search('foo', 'yipee');
- * // => $location
- * ```
- *
- * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
- * hash object.
- *
- * When called with a single argument the method acts as a setter, setting the `search` component
- * of `$location` to the specified value.
- *
- * If the argument is a hash object containing an array of values, these values will be encoded
- * as duplicate search parameters in the url.
- *
- * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
- * will override only a single search property.
- *
- * If `paramValue` is an array, it will override the property of the `search` component of
- * `$location` specified via the first argument.
- *
- * If `paramValue` is `null`, the property specified via the first argument will be deleted.
- *
- * If `paramValue` is `true`, the property specified via the first argument will be added with no
- * value nor trailing equal sign.
- *
- * @return {Object} If called with no arguments returns the parsed `search` object. If called with
- * one or more arguments returns `$location` object itself.
- */
- search: function(search, paramValue) {
- switch (arguments.length) {
- case 0:
- return this.$$search;
- case 1:
- if (isString(search) || isNumber(search)) {
- search = search.toString();
- this.$$search = parseKeyValue(search);
- } else if (isObject(search)) {
- // remove object undefined or null properties
- forEach(search, function(value, key) {
- if (value == null) delete search[key];
- });
-
- this.$$search = search;
- } else {
- throw $locationMinErr('isrcharg',
- 'The first argument of the `$location#search()` call must be a string or an object.');
- }
- break;
- default:
- if (isUndefined(paramValue) || paramValue === null) {
- delete this.$$search[search];
- } else {
- this.$$search[search] = paramValue;
- }
- }
-
- this.$$compose();
- return this;
- },
-
- /**
- * @ngdoc method
- * @name $location#hash
- *
- * @description
- * This method is getter / setter.
- *
- * Return hash fragment when called without any parameter.
- *
- * Change hash fragment when called with parameter and return `$location`.
- *
- * @param {(string|number)=} hash New hash fragment
- * @return {string} hash
- */
- hash: locationGetterSetter('$$hash', function(hash) {
- return hash ? hash.toString() : '';
- }),
-
- /**
- * @ngdoc method
- * @name $location#replace
- *
- * @description
- * If called, all changes to $location during current `$digest` will be replacing current history
- * record, instead of adding new one.
- */
- replace: function() {
- this.$$replace = true;
- return this;
- }
-};
-
-function locationGetter(property) {
- return function() {
- return this[property];
- };
-}
-
-
-function locationGetterSetter(property, preprocess) {
- return function(value) {
- if (isUndefined(value))
- return this[property];
-
- this[property] = preprocess(value);
- this.$$compose();
-
- return this;
- };
-}
-
-
-/**
- * @ngdoc service
- * @name $location
- *
- * @requires $rootElement
- *
- * @description
- * The $location service parses the URL in the browser address bar (based on the
- * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
- * available to your application. Changes to the URL in the address bar are reflected into
- * $location service and changes to $location are reflected into the browser address bar.
- *
- * **The $location service:**
- *
- * - Exposes the current URL in the browser address bar, so you can
- * - Watch and observe the URL.
- * - Change the URL.
- * - Synchronizes the URL with the browser when the user
- * - Changes the address bar.
- * - Clicks the back or forward button (or clicks a History link).
- * - Clicks on a link.
- * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
- *
- * For more information see {@link guide/$location Developer Guide: Using $location}
- */
-
-/**
- * @ngdoc provider
- * @name $locationProvider
- * @description
- * Use the `$locationProvider` to configure how the application deep linking paths are stored.
- */
-function $LocationProvider(){
- var hashPrefix = '',
- html5Mode = false;
-
- /**
- * @ngdoc method
- * @name $locationProvider#hashPrefix
- * @description
- * @param {string=} prefix Prefix for hash part (containing path and search)
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.hashPrefix = function(prefix) {
- if (isDefined(prefix)) {
- hashPrefix = prefix;
- return this;
- } else {
- return hashPrefix;
- }
- };
-
- /**
- * @ngdoc method
- * @name $locationProvider#html5Mode
- * @description
- * @param {boolean=} mode Use HTML5 strategy if available.
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.html5Mode = function(mode) {
- if (isDefined(mode)) {
- html5Mode = mode;
- return this;
- } else {
- return html5Mode;
- }
- };
-
- /**
- * @ngdoc event
- * @name $location#$locationChangeStart
- * @eventType broadcast on root scope
- * @description
- * Broadcasted before a URL will change. This change can be prevented by calling
- * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
- * details about event object. Upon successful change
- * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {string} newUrl New URL
- * @param {string=} oldUrl URL that was before it was changed.
- */
-
- /**
- * @ngdoc event
- * @name $location#$locationChangeSuccess
- * @eventType broadcast on root scope
- * @description
- * Broadcasted after a URL was changed.
- *
- * @param {Object} angularEvent Synthetic event object.
- * @param {string} newUrl New URL
- * @param {string=} oldUrl URL that was before it was changed.
- */
-
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
- function( $rootScope, $browser, $sniffer, $rootElement) {
- var $location,
- LocationMode,
- baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
- initialUrl = $browser.url(),
- appBase;
-
- if (html5Mode) {
- appBase = serverBase(initialUrl) + (baseHref || '/');
- LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
- } else {
- appBase = stripHash(initialUrl);
- LocationMode = LocationHashbangUrl;
- }
- $location = new LocationMode(appBase, '#' + hashPrefix);
- $location.$$parse($location.$$rewrite(initialUrl));
-
- var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
-
- $rootElement.on('click', function(event) {
- // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
- // currently we open nice url link and redirect then
-
- if (event.ctrlKey || event.metaKey || event.which == 2) return;
-
- var elm = jqLite(event.target);
-
- // traverse the DOM up to find first A tag
- while (lowercase(elm[0].nodeName) !== 'a') {
- // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
- if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
- }
-
- var absHref = elm.prop('href');
-
- if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
- // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
- // an animation.
- absHref = urlResolve(absHref.animVal).href;
- }
-
- // Ignore when url is started with javascript: or mailto:
- if (IGNORE_URI_REGEXP.test(absHref)) return;
-
- // Make relative links work in HTML5 mode for legacy browsers (or at least IE8 & 9)
- // The href should be a regular url e.g. /link/somewhere or link/somewhere or ../somewhere or
- // somewhere#anchor or http://example.com/somewhere
- if (LocationMode === LocationHashbangInHtml5Url) {
- // get the actual href attribute - see
- // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
- var href = elm.attr('href') || elm.attr('xlink:href');
-
- if (href && href.indexOf('://') < 0) { // Ignore absolute URLs
- var prefix = '#' + hashPrefix;
- if (href[0] == '/') {
- // absolute path - replace old path
- absHref = appBase + prefix + href;
- } else if (href[0] == '#') {
- // local anchor
- absHref = appBase + prefix + ($location.path() || '/') + href;
- } else {
- // relative path - join with current path
- var stack = $location.path().split("/"),
- parts = href.split("/");
- if (stack.length === 2 && !stack[1]) stack.length = 1;
- for (var i=0; i<parts.length; i++) {
- if (parts[i] == ".")
- continue;
- else if (parts[i] == "..")
- stack.pop();
- else if (parts[i].length)
- stack.push(parts[i]);
- }
- absHref = appBase + prefix + stack.join('/');
- }
- }
- }
-
- var rewrittenUrl = $location.$$rewrite(absHref);
-
- if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
- event.preventDefault();
- if (rewrittenUrl != $browser.url()) {
- // update location manually
- $location.$$parse(rewrittenUrl);
- $rootScope.$apply();
- // hack to work around FF6 bug 684208 when scenario runner clicks on links
- window.angular['ff-684208-preventDefault'] = true;
- }
- }
- });
-
-
- // rewrite hashbang url <> html5 url
- if ($location.absUrl() != initialUrl) {
- $browser.url($location.absUrl(), true);
- }
-
- // update $location when $browser url changes
- $browser.onUrlChange(function(newUrl) {
- if ($location.absUrl() != newUrl) {
- $rootScope.$evalAsync(function() {
- var oldUrl = $location.absUrl();
-
- $location.$$parse(newUrl);
- if ($rootScope.$broadcast('$locationChangeStart', newUrl,
- oldUrl).defaultPrevented) {
- $location.$$parse(oldUrl);
- $browser.url(oldUrl);
- } else {
- afterLocationChange(oldUrl);
- }
- });
- if (!$rootScope.$$phase) $rootScope.$digest();
- }
- });
-
- // update browser
- var changeCounter = 0;
- $rootScope.$watch(function $locationWatch() {
- var oldUrl = $browser.url();
- var currentReplace = $location.$$replace;
-
- if (!changeCounter || oldUrl != $location.absUrl()) {
- changeCounter++;
- $rootScope.$evalAsync(function() {
- if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
- defaultPrevented) {
- $location.$$parse(oldUrl);
- } else {
- $browser.url($location.absUrl(), currentReplace);
- afterLocationChange(oldUrl);
- }
- });
- }
- $location.$$replace = false;
-
- return changeCounter;
- });
-
- return $location;
-
- function afterLocationChange(oldUrl) {
- $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
- }
-}];
-}
-
-/**
- * @ngdoc service
- * @name $log
- * @requires $window
- *
- * @description
- * Simple service for logging. Default implementation safely writes the message
- * into the browser's console (if present).
- *
- * The main purpose of this service is to simplify debugging and troubleshooting.
- *
- * The default is to log `debug` messages. You can use
- * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
- *
- * @example
- <example module="logExample">
- <file name="script.js">
- angular.module('logExample', [])
- .controller('LogController', ['$scope', '$log', function($scope, $log) {
- $scope.$log = $log;
- $scope.message = 'Hello World!';
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="LogController">
- <p>Reload this page with open console, enter text and hit the log button...</p>
- Message:
- <input type="text" ng-model="message"/>
- <button ng-click="$log.log(message)">log</button>
- <button ng-click="$log.warn(message)">warn</button>
- <button ng-click="$log.info(message)">info</button>
- <button ng-click="$log.error(message)">error</button>
- </div>
- </file>
- </example>
- */
-
-/**
- * @ngdoc provider
- * @name $logProvider
- * @description
- * Use the `$logProvider` to configure how the application logs messages
- */
-function $LogProvider(){
- var debug = true,
- self = this;
-
- /**
- * @ngdoc method
- * @name $logProvider#debugEnabled
- * @description
- * @param {boolean=} flag enable or disable debug level messages
- * @returns {*} current value if used as getter or itself (chaining) if used as setter
- */
- this.debugEnabled = function(flag) {
- if (isDefined(flag)) {
- debug = flag;
- return this;
- } else {
- return debug;
- }
- };
-
- this.$get = ['$window', function($window){
- return {
- /**
- * @ngdoc method
- * @name $log#log
- *
- * @description
- * Write a log message
- */
- log: consoleLog('log'),
-
- /**
- * @ngdoc method
- * @name $log#info
- *
- * @description
- * Write an information message
- */
- info: consoleLog('info'),
-
- /**
- * @ngdoc method
- * @name $log#warn
- *
- * @description
- * Write a warning message
- */
- warn: consoleLog('warn'),
-
- /**
- * @ngdoc method
- * @name $log#error
- *
- * @description
- * Write an error message
- */
- error: consoleLog('error'),
-
- /**
- * @ngdoc method
- * @name $log#debug
- *
- * @description
- * Write a debug message
- */
- debug: (function () {
- var fn = consoleLog('debug');
-
- return function() {
- if (debug) {
- fn.apply(self, arguments);
- }
- };
- }())
- };
-
- function formatError(arg) {
- if (arg instanceof Error) {
- if (arg.stack) {
- arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
- ? 'Error: ' + arg.message + '\n' + arg.stack
- : arg.stack;
- } else if (arg.sourceURL) {
- arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
- }
- }
- return arg;
- }
-
- function consoleLog(type) {
- var console = $window.console || {},
- logFn = console[type] || console.log || noop,
- hasApply = false;
-
- // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
- // The reason behind this is that console.log has type "object" in IE8...
- try {
- hasApply = !!logFn.apply;
- } catch (e) {}
-
- if (hasApply) {
- return function() {
- var args = [];
- forEach(arguments, function(arg) {
- args.push(formatError(arg));
- });
- return logFn.apply(console, args);
- };
- }
-
- // we are IE which either doesn't have window.console => this is noop and we do nothing,
- // or we are IE where console.log doesn't have apply so we log at least first 2 args
- return function(arg1, arg2) {
- logFn(arg1, arg2 == null ? '' : arg2);
- };
- }
- }];
-}
-
-var $parseMinErr = minErr('$parse');
-var promiseWarningCache = {};
-var promiseWarning;
-
-// Sandboxing Angular Expressions
-// ------------------------------
-// Angular expressions are generally considered safe because these expressions only have direct
-// access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
-// obtaining a reference to native JS functions such as the Function constructor.
-//
-// As an example, consider the following Angular expression:
-//
-// {}.toString.constructor('alert("evil JS code")')
-//
-// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
-// against the expression language, but not to prevent exploits that were enabled by exposing
-// sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
-// practice and therefore we are not even trying to protect against interaction with an object
-// explicitly exposed in this way.
-//
-// In general, it is not possible to access a Window object from an angular expression unless a
-// window or some DOM object that has a reference to window is published onto a Scope.
-// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
-// native objects.
-
-
-function ensureSafeMemberName(name, fullExpression) {
- if (name === "__defineGetter__" || name === "__defineSetter__"
- || name === "__lookupGetter__" || name === "__lookupSetter__"
- || name === "__proto__") {
- throw $parseMinErr('isecfld',
- 'Attempting to access a disallowed field in Angular expressions! '
- +'Expression: {0}', fullExpression);
- }
- return name;
-}
-
-function ensureSafeObject(obj, fullExpression) {
- // nifty check if obj is Function that is fast and works across iframes and other contexts
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// isWindow(obj)
- obj.document && obj.location && obj.alert && obj.setInterval) {
- throw $parseMinErr('isecwindow',
- 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// isElement(obj)
- obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
- throw $parseMinErr('isecdom',
- 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (// block Object so that we can't get hold of dangerous Object.* methods
- obj === Object) {
- throw $parseMinErr('isecobj',
- 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
- return obj;
-}
-
-var CALL = Function.prototype.call;
-var APPLY = Function.prototype.apply;
-var BIND = Function.prototype.bind;
-
-function ensureSafeFunction(obj, fullExpression) {
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
- throw $parseMinErr('isecff',
- 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
-}
-
-var OPERATORS = {
- /* jshint bitwise : false */
- 'null':function(){return null;},
- 'true':function(){return true;},
- 'false':function(){return false;},
- undefined:noop,
- '+':function(self, locals, a,b){
- a=a(self, locals); b=b(self, locals);
- if (isDefined(a)) {
- if (isDefined(b)) {
- return a + b;
- }
- return a;
- }
- return isDefined(b)?b:undefined;},
- '-':function(self, locals, a,b){
- a=a(self, locals); b=b(self, locals);
- return (isDefined(a)?a:0)-(isDefined(b)?b:0);
- },
- '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
- '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
- '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
- '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
- '=':noop,
- '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
- '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
- '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
- '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
- '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
- '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
- '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
- '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
- '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
- '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
- '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
-// '|':function(self, locals, a,b){return a|b;},
- '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
- '!':function(self, locals, a){return !a(self, locals);}
-};
-/* jshint bitwise: true */
-var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
-
-
-/////////////////////////////////////////
-
-
-/**
- * @constructor
- */
-var Lexer = function (options) {
- this.options = options;
-};
-
-Lexer.prototype = {
- constructor: Lexer,
-
- lex: function (text) {
- this.text = text;
-
- this.index = 0;
- this.ch = undefined;
- this.lastCh = ':'; // can start regexp
-
- this.tokens = [];
-
- while (this.index < this.text.length) {
- this.ch = this.text.charAt(this.index);
- if (this.is('"\'')) {
- this.readString(this.ch);
- } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
- this.readNumber();
- } else if (this.isIdent(this.ch)) {
- this.readIdent();
- } else if (this.is('(){}[].,;:?')) {
- this.tokens.push({
- index: this.index,
- text: this.ch
- });
- this.index++;
- } else if (this.isWhitespace(this.ch)) {
- this.index++;
- continue;
- } else {
- var ch2 = this.ch + this.peek();
- var ch3 = ch2 + this.peek(2);
- var fn = OPERATORS[this.ch];
- var fn2 = OPERATORS[ch2];
- var fn3 = OPERATORS[ch3];
- if (fn3) {
- this.tokens.push({index: this.index, text: ch3, fn: fn3});
- this.index += 3;
- } else if (fn2) {
- this.tokens.push({index: this.index, text: ch2, fn: fn2});
- this.index += 2;
- } else if (fn) {
- this.tokens.push({
- index: this.index,
- text: this.ch,
- fn: fn
- });
- this.index += 1;
- } else {
- this.throwError('Unexpected next character ', this.index, this.index + 1);
- }
- }
- this.lastCh = this.ch;
- }
- return this.tokens;
- },
-
- is: function(chars) {
- return chars.indexOf(this.ch) !== -1;
- },
-
- was: function(chars) {
- return chars.indexOf(this.lastCh) !== -1;
- },
-
- peek: function(i) {
- var num = i || 1;
- return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
- },
-
- isNumber: function(ch) {
- return ('0' <= ch && ch <= '9');
- },
-
- isWhitespace: function(ch) {
- // IE treats non-breaking space as \u00A0
- return (ch === ' ' || ch === '\r' || ch === '\t' ||
- ch === '\n' || ch === '\v' || ch === '\u00A0');
- },
-
- isIdent: function(ch) {
- return ('a' <= ch && ch <= 'z' ||
- 'A' <= ch && ch <= 'Z' ||
- '_' === ch || ch === '$');
- },
-
- isExpOperator: function(ch) {
- return (ch === '-' || ch === '+' || this.isNumber(ch));
- },
-
- throwError: function(error, start, end) {
- end = end || this.index;
- var colStr = (isDefined(start)
- ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
- : ' ' + end);
- throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
- error, colStr, this.text);
- },
-
- readNumber: function() {
- var number = '';
- var start = this.index;
- while (this.index < this.text.length) {
- var ch = lowercase(this.text.charAt(this.index));
- if (ch == '.' || this.isNumber(ch)) {
- number += ch;
- } else {
- var peekCh = this.peek();
- if (ch == 'e' && this.isExpOperator(peekCh)) {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- peekCh && this.isNumber(peekCh) &&
- number.charAt(number.length - 1) == 'e') {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- (!peekCh || !this.isNumber(peekCh)) &&
- number.charAt(number.length - 1) == 'e') {
- this.throwError('Invalid exponent');
- } else {
- break;
- }
- }
- this.index++;
- }
- number = 1 * number;
- this.tokens.push({
- index: start,
- text: number,
- literal: true,
- constant: true,
- fn: function() { return number; }
- });
- },
-
- readIdent: function() {
- var parser = this;
-
- var ident = '';
- var start = this.index;
-
- var lastDot, peekIndex, methodName, ch;
-
- while (this.index < this.text.length) {
- ch = this.text.charAt(this.index);
- if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
- if (ch === '.') lastDot = this.index;
- ident += ch;
- } else {
- break;
- }
- this.index++;
- }
-
- //check if this is not a method invocation and if it is back out to last dot
- if (lastDot) {
- peekIndex = this.index;
- while (peekIndex < this.text.length) {
- ch = this.text.charAt(peekIndex);
- if (ch === '(') {
- methodName = ident.substr(lastDot - start + 1);
- ident = ident.substr(0, lastDot - start);
- this.index = peekIndex;
- break;
- }
- if (this.isWhitespace(ch)) {
- peekIndex++;
- } else {
- break;
- }
- }
- }
-
-
- var token = {
- index: start,
- text: ident
- };
-
- // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
- if (OPERATORS.hasOwnProperty(ident)) {
- token.fn = OPERATORS[ident];
- token.literal = true;
- token.constant = true;
- } else {
- var getter = getterFn(ident, this.options, this.text);
- token.fn = extend(function(self, locals) {
- return (getter(self, locals));
- }, {
- assign: function(self, value) {
- return setter(self, ident, value, parser.text, parser.options);
- }
- });
- }
-
- this.tokens.push(token);
-
- if (methodName) {
- this.tokens.push({
- index:lastDot,
- text: '.'
- });
- this.tokens.push({
- index: lastDot + 1,
- text: methodName
- });
- }
- },
-
- readString: function(quote) {
- var start = this.index;
- this.index++;
- var string = '';
- var rawString = quote;
- var escape = false;
- while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- rawString += ch;
- if (escape) {
- if (ch === 'u') {
- var hex = this.text.substring(this.index + 1, this.index + 5);
- if (!hex.match(/[\da-f]{4}/i))
- this.throwError('Invalid unicode escape [\\u' + hex + ']');
- this.index += 4;
- string += String.fromCharCode(parseInt(hex, 16));
- } else {
- var rep = ESCAPE[ch];
- string = string + (rep || ch);
- }
- escape = false;
- } else if (ch === '\\') {
- escape = true;
- } else if (ch === quote) {
- this.index++;
- this.tokens.push({
- index: start,
- text: rawString,
- string: string,
- literal: true,
- constant: true,
- fn: function() { return string; }
- });
- return;
- } else {
- string += ch;
- }
- this.index++;
- }
- this.throwError('Unterminated quote', start);
- }
-};
-
-
-/**
- * @constructor
- */
-var Parser = function (lexer, $filter, options) {
- this.lexer = lexer;
- this.$filter = $filter;
- this.options = options;
-};
-
-Parser.ZERO = extend(function () {
- return 0;
-}, {
- constant: true
-});
-
-Parser.prototype = {
- constructor: Parser,
-
- parse: function (text) {
- this.text = text;
-
- this.tokens = this.lexer.lex(text);
-
- var value = this.statements();
-
- if (this.tokens.length !== 0) {
- this.throwError('is an unexpected token', this.tokens[0]);
- }
-
- value.literal = !!value.literal;
- value.constant = !!value.constant;
-
- return value;
- },
-
- primary: function () {
- var primary;
- if (this.expect('(')) {
- primary = this.filterChain();
- this.consume(')');
- } else if (this.expect('[')) {
- primary = this.arrayDeclaration();
- } else if (this.expect('{')) {
- primary = this.object();
- } else {
- var token = this.expect();
- primary = token.fn;
- if (!primary) {
- this.throwError('not a primary expression', token);
- }
- primary.literal = !!token.literal;
- primary.constant = !!token.constant;
- }
-
- var next, context;
- while ((next = this.expect('(', '[', '.'))) {
- if (next.text === '(') {
- primary = this.functionCall(primary, context);
- context = null;
- } else if (next.text === '[') {
- context = primary;
- primary = this.objectIndex(primary);
- } else if (next.text === '.') {
- context = primary;
- primary = this.fieldAccess(primary);
- } else {
- this.throwError('IMPOSSIBLE');
- }
- }
- return primary;
- },
-
- throwError: function(msg, token) {
- throw $parseMinErr('syntax',
- 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
- token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
- },
-
- peekToken: function() {
- if (this.tokens.length === 0)
- throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
- return this.tokens[0];
- },
-
- peek: function(e1, e2, e3, e4) {
- if (this.tokens.length > 0) {
- var token = this.tokens[0];
- var t = token.text;
- if (t === e1 || t === e2 || t === e3 || t === e4 ||
- (!e1 && !e2 && !e3 && !e4)) {
- return token;
- }
- }
- return false;
- },
-
- expect: function(e1, e2, e3, e4){
- var token = this.peek(e1, e2, e3, e4);
- if (token) {
- this.tokens.shift();
- return token;
- }
- return false;
- },
-
- consume: function(e1){
- if (!this.expect(e1)) {
- this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
- }
- },
-
- unaryFn: function(fn, right) {
- return extend(function(self, locals) {
- return fn(self, locals, right);
- }, {
- constant:right.constant
- });
- },
-
- ternaryFn: function(left, middle, right){
- return extend(function(self, locals){
- return left(self, locals) ? middle(self, locals) : right(self, locals);
- }, {
- constant: left.constant && middle.constant && right.constant
- });
- },
-
- binaryFn: function(left, fn, right) {
- return extend(function(self, locals) {
- return fn(self, locals, left, right);
- }, {
- constant:left.constant && right.constant
- });
- },
-
- statements: function() {
- var statements = [];
- while (true) {
- if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
- statements.push(this.filterChain());
- if (!this.expect(';')) {
- // optimize for the common case where there is only one statement.
- // TODO(size): maybe we should not support multiple statements?
- return (statements.length === 1)
- ? statements[0]
- : function(self, locals) {
- var value;
- for (var i = 0; i < statements.length; i++) {
- var statement = statements[i];
- if (statement) {
- value = statement(self, locals);
- }
- }
- return value;
- };
- }
- }
- },
-
- filterChain: function() {
- var left = this.expression();
- var token;
- while (true) {
- if ((token = this.expect('|'))) {
- left = this.binaryFn(left, token.fn, this.filter());
- } else {
- return left;
- }
- }
- },
-
- filter: function() {
- var token = this.expect();
- var fn = this.$filter(token.text);
- var argsFn = [];
- while (true) {
- if ((token = this.expect(':'))) {
- argsFn.push(this.expression());
- } else {
- var fnInvoke = function(self, locals, input) {
- var args = [input];
- for (var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](self, locals));
- }
- return fn.apply(self, args);
- };
- return function() {
- return fnInvoke;
- };
- }
- }
- },
-
- expression: function() {
- return this.assignment();
- },
-
- assignment: function() {
- var left = this.ternary();
- var right;
- var token;
- if ((token = this.expect('='))) {
- if (!left.assign) {
- this.throwError('implies assignment but [' +
- this.text.substring(0, token.index) + '] can not be assigned to', token);
- }
- right = this.ternary();
- return function(scope, locals) {
- return left.assign(scope, right(scope, locals), locals);
- };
- }
- return left;
- },
-
- ternary: function() {
- var left = this.logicalOR();
- var middle;
- var token;
- if ((token = this.expect('?'))) {
- middle = this.assignment();
- if ((token = this.expect(':'))) {
- return this.ternaryFn(left, middle, this.assignment());
- } else {
- this.throwError('expected :', token);
- }
- } else {
- return left;
- }
- },
-
- logicalOR: function() {
- var left = this.logicalAND();
- var token;
- while (true) {
- if ((token = this.expect('||'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND());
- } else {
- return left;
- }
- }
- },
-
- logicalAND: function() {
- var left = this.equality();
- var token;
- if ((token = this.expect('&&'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND());
- }
- return left;
- },
-
- equality: function() {
- var left = this.relational();
- var token;
- if ((token = this.expect('==','!=','===','!=='))) {
- left = this.binaryFn(left, token.fn, this.equality());
- }
- return left;
- },
-
- relational: function() {
- var left = this.additive();
- var token;
- if ((token = this.expect('<', '>', '<=', '>='))) {
- left = this.binaryFn(left, token.fn, this.relational());
- }
- return left;
- },
-
- additive: function() {
- var left = this.multiplicative();
- var token;
- while ((token = this.expect('+','-'))) {
- left = this.binaryFn(left, token.fn, this.multiplicative());
- }
- return left;
- },
-
- multiplicative: function() {
- var left = this.unary();
- var token;
- while ((token = this.expect('*','/','%'))) {
- left = this.binaryFn(left, token.fn, this.unary());
- }
- return left;
- },
-
- unary: function() {
- var token;
- if (this.expect('+')) {
- return this.primary();
- } else if ((token = this.expect('-'))) {
- return this.binaryFn(Parser.ZERO, token.fn, this.unary());
- } else if ((token = this.expect('!'))) {
- return this.unaryFn(token.fn, this.unary());
- } else {
- return this.primary();
- }
- },
-
- fieldAccess: function(object) {
- var parser = this;
- var field = this.expect().text;
- var getter = getterFn(field, this.options, this.text);
-
- return extend(function(scope, locals, self) {
- return getter(self || object(scope, locals));
- }, {
- assign: function(scope, value, locals) {
- var o = object(scope, locals);
- if (!o) object.assign(scope, o = {});
- return setter(o, field, value, parser.text, parser.options);
- }
- });
- },
-
- objectIndex: function(obj) {
- var parser = this;
-
- var indexFn = this.expression();
- this.consume(']');
-
- return extend(function(self, locals) {
- var o = obj(self, locals),
- i = indexFn(self, locals),
- v, p;
-
- ensureSafeMemberName(i, parser.text);
- if (!o) return undefined;
- v = ensureSafeObject(o[i], parser.text);
- if (v && v.then && parser.options.unwrapPromises) {
- p = v;
- if (!('$$v' in v)) {
- p.$$v = undefined;
- p.then(function(val) { p.$$v = val; });
- }
- v = v.$$v;
- }
- return v;
- }, {
- assign: function(self, value, locals) {
- var key = ensureSafeMemberName(indexFn(self, locals), parser.text);
- // prevent overwriting of Function.constructor which would break ensureSafeObject check
- var o = ensureSafeObject(obj(self, locals), parser.text);
- if (!o) obj.assign(self, o = {});
- return o[key] = value;
- }
- });
- },
-
- functionCall: function(fn, contextGetter) {
- var argsFn = [];
- if (this.peekToken().text !== ')') {
- do {
- argsFn.push(this.expression());
- } while (this.expect(','));
- }
- this.consume(')');
-
- var parser = this;
-
- return function(scope, locals) {
- var args = [];
- var context = contextGetter ? contextGetter(scope, locals) : scope;
-
- for (var i = 0; i < argsFn.length; i++) {
- args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));
- }
- var fnPtr = fn(scope, locals, context) || noop;
-
- ensureSafeObject(context, parser.text);
- ensureSafeFunction(fnPtr, parser.text);
-
- // IE stupidity! (IE doesn't have apply for some native functions)
- var v = fnPtr.apply
- ? fnPtr.apply(context, args)
- : fnPtr(args[0], args[1], args[2], args[3], args[4]);
-
- return ensureSafeObject(v, parser.text);
- };
- },
-
- // This is used with json array declaration
- arrayDeclaration: function () {
- var elementFns = [];
- var allConstant = true;
- if (this.peekToken().text !== ']') {
- do {
- if (this.peek(']')) {
- // Support trailing commas per ES5.1.
- break;
- }
- var elementFn = this.expression();
- elementFns.push(elementFn);
- if (!elementFn.constant) {
- allConstant = false;
- }
- } while (this.expect(','));
- }
- this.consume(']');
-
- return extend(function(self, locals) {
- var array = [];
- for (var i = 0; i < elementFns.length; i++) {
- array.push(elementFns[i](self, locals));
- }
- return array;
- }, {
- literal: true,
- constant: allConstant
- });
- },
-
- object: function () {
- var keyValues = [];
- var allConstant = true;
- if (this.peekToken().text !== '}') {
- do {
- if (this.peek('}')) {
- // Support trailing commas per ES5.1.
- break;
- }
- var token = this.expect(),
- key = token.string || token.text;
- this.consume(':');
- var value = this.expression();
- keyValues.push({key: key, value: value});
- if (!value.constant) {
- allConstant = false;
- }
- } while (this.expect(','));
- }
- this.consume('}');
-
- return extend(function(self, locals) {
- var object = {};
- for (var i = 0; i < keyValues.length; i++) {
- var keyValue = keyValues[i];
- object[keyValue.key] = keyValue.value(self, locals);
- }
- return object;
- }, {
- literal: true,
- constant: allConstant
- });
- }
-};
-
-
-//////////////////////////////////////////////////
-// Parser helper functions
-//////////////////////////////////////////////////
-
-function setter(obj, path, setValue, fullExp, options) {
- ensureSafeObject(obj, fullExp);
-
- //needed?
- options = options || {};
-
- var element = path.split('.'), key;
- for (var i = 0; element.length > 1; i++) {
- key = ensureSafeMemberName(element.shift(), fullExp);
- var propertyObj = ensureSafeObject(obj[key], fullExp);
- if (!propertyObj) {
- propertyObj = {};
- obj[key] = propertyObj;
- }
- obj = propertyObj;
- if (obj.then && options.unwrapPromises) {
- promiseWarning(fullExp);
- if (!("$$v" in obj)) {
- (function(promise) {
- promise.then(function(val) { promise.$$v = val; }); }
- )(obj);
- }
- if (obj.$$v === undefined) {
- obj.$$v = {};
- }
- obj = obj.$$v;
- }
- }
- key = ensureSafeMemberName(element.shift(), fullExp);
- ensureSafeObject(obj[key], fullExp);
- obj[key] = setValue;
- return setValue;
-}
-
-var getterFnCache = {};
-
-/**
- * Implementation of the "Black Hole" variant from:
- * - http://jsperf.com/angularjs-parse-getter/4
- * - http://jsperf.com/path-evaluation-simplified/7
- */
-function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
- ensureSafeMemberName(key0, fullExp);
- ensureSafeMemberName(key1, fullExp);
- ensureSafeMemberName(key2, fullExp);
- ensureSafeMemberName(key3, fullExp);
- ensureSafeMemberName(key4, fullExp);
-
- return !options.unwrapPromises
- ? function cspSafeGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
-
- if (pathVal == null) return pathVal;
- pathVal = pathVal[key0];
-
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
-
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
-
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
-
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
-
- return pathVal;
- }
- : function cspSafePromiseEnabledGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
- promise;
-
- if (pathVal == null) return pathVal;
-
- pathVal = pathVal[key0];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- return pathVal;
- };
-}
-
-function getterFn(path, options, fullExp) {
- // Check whether the cache has this getter already.
- // We can use hasOwnProperty directly on the cache because we ensure,
- // see below, that the cache never stores a path called 'hasOwnProperty'
- if (getterFnCache.hasOwnProperty(path)) {
- return getterFnCache[path];
- }
-
- var pathKeys = path.split('.'),
- pathKeysLength = pathKeys.length,
- fn;
-
- // http://jsperf.com/angularjs-parse-getter/6
- if (options.csp) {
- if (pathKeysLength < 6) {
- fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
- options);
- } else {
- fn = function(scope, locals) {
- var i = 0, val;
- do {
- val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
- pathKeys[i++], fullExp, options)(scope, locals);
-
- locals = undefined; // clear after first iteration
- scope = val;
- } while (i < pathKeysLength);
- return val;
- };
- }
- } else {
- var code = 'var p;\n';
- forEach(pathKeys, function(key, index) {
- ensureSafeMemberName(key, fullExp);
- code += 'if(s == null) return undefined;\n' +
- 's='+ (index
- // we simply dereference 's' on any .dot notation
- ? 's'
- // but if we are first then we check locals first, and if so read it first
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
- (options.unwrapPromises
- ? 'if (s && s.then) {\n' +
- ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
- ' if (!("$$v" in s)) {\n' +
- ' p=s;\n' +
- ' p.$$v = undefined;\n' +
- ' p.then(function(v) {p.$$v=v;});\n' +
- '}\n' +
- ' s=s.$$v\n' +
- '}\n'
- : '');
- });
- code += 'return s;';
-
- /* jshint -W054 */
- var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
- /* jshint +W054 */
- evaledFnGetter.toString = valueFn(code);
- fn = options.unwrapPromises ? function(scope, locals) {
- return evaledFnGetter(scope, locals, promiseWarning);
- } : evaledFnGetter;
- }
-
- // Only cache the value if it's not going to mess up the cache object
- // This is more performant that using Object.prototype.hasOwnProperty.call
- if (path !== 'hasOwnProperty') {
- getterFnCache[path] = fn;
- }
- return fn;
-}
-
-///////////////////////////////////
-
-/**
- * @ngdoc service
- * @name $parse
- * @kind function
- *
- * @description
- *
- * Converts Angular {@link guide/expression expression} into a function.
- *
- * ```js
- * var getter = $parse('user.name');
- * var setter = getter.assign;
- * var context = {user:{name:'angular'}};
- * var locals = {user:{name:'local'}};
- *
- * expect(getter(context)).toEqual('angular');
- * setter(context, 'newValue');
- * expect(context.user.name).toEqual('newValue');
- * expect(getter(context, locals)).toEqual('local');
- * ```
- *
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- *
- * The returned function also has the following properties:
- * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
- * literal.
- * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
- * constant literals.
- * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
- * set to a function to change its value on the given context.
- *
- */
-
-
-/**
- * @ngdoc provider
- * @name $parseProvider
- * @kind function
- *
- * @description
- * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
- * service.
- */
-function $ParseProvider() {
- var cache = {};
-
- var $parseOptions = {
- csp: false,
- unwrapPromises: false,
- logPromiseWarnings: true
- };
-
-
- /**
- * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
- *
- * @ngdoc method
- * @name $parseProvider#unwrapPromises
- * @description
- *
- * **This feature is deprecated, see deprecation notes below for more info**
- *
- * If set to true (default is false), $parse will unwrap promises automatically when a promise is
- * found at any part of the expression. In other words, if set to true, the expression will always
- * result in a non-promise value.
- *
- * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
- * the fulfillment value is used in place of the promise while evaluating the expression.
- *
- * **Deprecation notice**
- *
- * This is a feature that didn't prove to be wildly useful or popular, primarily because of the
- * dichotomy between data access in templates (accessed as raw values) and controller code
- * (accessed as promises).
- *
- * In most code we ended up resolving promises manually in controllers anyway and thus unifying
- * the model access there.
- *
- * Other downsides of automatic promise unwrapping:
- *
- * - when building components it's often desirable to receive the raw promises
- * - adds complexity and slows down expression evaluation
- * - makes expression code pre-generation unattractive due to the amount of code that needs to be
- * generated
- * - makes IDE auto-completion and tool support hard
- *
- * **Warning Logs**
- *
- * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
- * promise (to reduce the noise, each expression is logged only once). To disable this logging use
- * `$parseProvider.logPromiseWarnings(false)` api.
- *
- *
- * @param {boolean=} value New value.
- * @returns {boolean|self} Returns the current setting when used as getter and self if used as
- * setter.
- */
- this.unwrapPromises = function(value) {
- if (isDefined(value)) {
- $parseOptions.unwrapPromises = !!value;
- return this;
- } else {
- return $parseOptions.unwrapPromises;
- }
- };
-
-
- /**
- * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
- *
- * @ngdoc method
- * @name $parseProvider#logPromiseWarnings
- * @description
- *
- * Controls whether Angular should log a warning on any encounter of a promise in an expression.
- *
- * The default is set to `true`.
- *
- * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
- *
- * @param {boolean=} value New value.
- * @returns {boolean|self} Returns the current setting when used as getter and self if used as
- * setter.
- */
- this.logPromiseWarnings = function(value) {
- if (isDefined(value)) {
- $parseOptions.logPromiseWarnings = value;
- return this;
- } else {
- return $parseOptions.logPromiseWarnings;
- }
- };
-
-
- this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
- $parseOptions.csp = $sniffer.csp;
-
- promiseWarning = function promiseWarningFn(fullExp) {
- if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
- promiseWarningCache[fullExp] = true;
- $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
- 'Automatic unwrapping of promises in Angular expressions is deprecated.');
- };
-
- return function(exp) {
- var parsedExpression;
-
- switch (typeof exp) {
- case 'string':
-
- if (cache.hasOwnProperty(exp)) {
- return cache[exp];
- }
-
- var lexer = new Lexer($parseOptions);
- var parser = new Parser(lexer, $filter, $parseOptions);
- parsedExpression = parser.parse(exp);
-
- if (exp !== 'hasOwnProperty') {
- // Only cache the value if it's not going to mess up the cache object
- // This is more performant that using Object.prototype.hasOwnProperty.call
- cache[exp] = parsedExpression;
- }
-
- return parsedExpression;
-
- case 'function':
- return exp;
-
- default:
- return noop;
- }
- };
- }];
-}
-
-/**
- * @ngdoc service
- * @name $q
- * @requires $rootScope
- *
- * @description
- * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
- *
- * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
- * interface for interacting with an object that represents the result of an action that is
- * performed asynchronously, and may or may not be finished at any given point in time.
- *
- * From the perspective of dealing with error handling, deferred and promise APIs are to
- * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
- *
- * ```js
- * // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
- * // are available in the current lexical scope (they could have been injected or passed in).
- *
- * function asyncGreet(name) {
- * var deferred = $q.defer();
- *
- * setTimeout(function() {
- * deferred.notify('About to greet ' + name + '.');
- *
- * if (okToGreet(name)) {
- * deferred.resolve('Hello, ' + name + '!');
- * } else {
- * deferred.reject('Greeting ' + name + ' is not allowed.');
- * }
- * }, 1000);
- *
- * return deferred.promise;
- * }
- *
- * var promise = asyncGreet('Robin Hood');
- * promise.then(function(greeting) {
- * alert('Success: ' + greeting);
- * }, function(reason) {
- * alert('Failed: ' + reason);
- * }, function(update) {
- * alert('Got notification: ' + update);
- * });
- * ```
- *
- * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
- * comes in the way of guarantees that promise and deferred APIs make, see
- * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
- *
- * Additionally the promise api allows for composition that is very hard to do with the
- * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
- * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
- * section on serial or parallel joining of promises.
- *
- *
- * # The Deferred API
- *
- * A new instance of deferred is constructed by calling `$q.defer()`.
- *
- * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
- * that can be used for signaling the successful or unsuccessful completion, as well as the status
- * of the task.
- *
- * **Methods**
- *
- * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
- * constructed via `$q.reject`, the promise will be rejected instead.
- * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
- * resolving it with a rejection constructed via `$q.reject`.
- * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
- * multiple times before the promise is either resolved or rejected.
- *
- * **Properties**
- *
- * - promise – `{Promise}` – promise object associated with this deferred.
- *
- *
- * # The Promise API
- *
- * A new promise instance is created when a deferred instance is created and can be retrieved by
- * calling `deferred.promise`.
- *
- * The purpose of the promise object is to allow for interested parties to get access to the result
- * of the deferred task when it completes.
- *
- * **Methods**
- *
- * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
- * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
- * as soon as the result is available. The callbacks are called with a single argument: the result
- * or rejection reason. Additionally, the notify callback may be called zero or more times to
- * provide a progress indication, before the promise is resolved or rejected.
- *
- * This method *returns a new promise* which is resolved or rejected via the return value of the
- * `successCallback`, `errorCallback`. It also notifies via the return value of the
- * `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback
- * method.
- *
- * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
- *
- * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,
- * but to do so without modifying the final value. This is useful to release resources or do some
- * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
- * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
- * more information.
- *
- * Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
- * property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
- * make your code IE8 and Android 2.x compatible.
- *
- * # Chaining promises
- *
- * Because calling the `then` method of a promise returns a new derived promise, it is easily
- * possible to create a chain of promises:
- *
- * ```js
- * promiseB = promiseA.then(function(result) {
- * return result + 1;
- * });
- *
- * // promiseB will be resolved immediately after promiseA is resolved and its value
- * // will be the result of promiseA incremented by 1
- * ```
- *
- * It is possible to create chains of any length and since a promise can be resolved with another
- * promise (which will defer its resolution further), it is possible to pause/defer resolution of
- * the promises at any point in the chain. This makes it possible to implement powerful APIs like
- * $http's response interceptors.
- *
- *
- * # Differences between Kris Kowal's Q and $q
- *
- * There are two main differences:
- *
- * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
- * mechanism in angular, which means faster propagation of resolution or rejection into your
- * models and avoiding unnecessary browser repaints, which would result in flickering UI.
- * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
- * all the important functionality needed for common async tasks.
- *
- * # Testing
- *
- * ```js
- * it('should simulate promise', inject(function($q, $rootScope) {
- * var deferred = $q.defer();
- * var promise = deferred.promise;
- * var resolvedValue;
- *
- * promise.then(function(value) { resolvedValue = value; });
- * expect(resolvedValue).toBeUndefined();
- *
- * // Simulate resolving of promise
- * deferred.resolve(123);
- * // Note that the 'then' function does not get called synchronously.
- * // This is because we want the promise API to always be async, whether or not
- * // it got called synchronously or asynchronously.
- * expect(resolvedValue).toBeUndefined();
- *
- * // Propagate promise resolution to 'then' functions using $apply().
- * $rootScope.$apply();
- * expect(resolvedValue).toEqual(123);
- * }));
- * ```
- */
-function $QProvider() {
-
- this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
- return qFactory(function(callback) {
- $rootScope.$evalAsync(callback);
- }, $exceptionHandler);
- }];
-}
-
-
-/**
- * Constructs a promise manager.
- *
- * @param {function(Function)} nextTick Function for executing functions in the next turn.
- * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
- * debugging purposes.
- * @returns {object} Promise manager.
- */
-function qFactory(nextTick, exceptionHandler) {
-
- /**
- * @ngdoc method
- * @name $q#defer
- * @kind function
- *
- * @description
- * Creates a `Deferred` object which represents a task which will finish in the future.
- *
- * @returns {Deferred} Returns a new instance of deferred.
- */
- var defer = function() {
- var pending = [],
- value, deferred;
-
- deferred = {
-
- resolve: function(val) {
- if (pending) {
- var callbacks = pending;
- pending = undefined;
- value = ref(val);
-
- if (callbacks.length) {
- nextTick(function() {
- var callback;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- callback = callbacks[i];
- value.then(callback[0], callback[1], callback[2]);
- }
- });
- }
- }
- },
-
-
- reject: function(reason) {
- deferred.resolve(createInternalRejectedPromise(reason));
- },
-
-
- notify: function(progress) {
- if (pending) {
- var callbacks = pending;
-
- if (pending.length) {
- nextTick(function() {
- var callback;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- callback = callbacks[i];
- callback[2](progress);
- }
- });
- }
- }
- },
-
-
- promise: {
- then: function(callback, errback, progressback) {
- var result = defer();
-
- var wrappedCallback = function(value) {
- try {
- result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- };
-
- var wrappedErrback = function(reason) {
- try {
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- };
-
- var wrappedProgressback = function(progress) {
- try {
- result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
- } catch(e) {
- exceptionHandler(e);
- }
- };
-
- if (pending) {
- pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
- } else {
- value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
- }
-
- return result.promise;
- },
-
- "catch": function(callback) {
- return this.then(null, callback);
- },
-
- "finally": function(callback) {
-
- function makePromise(value, resolved) {
- var result = defer();
- if (resolved) {
- result.resolve(value);
- } else {
- result.reject(value);
- }
- return result.promise;
- }
-
- function handleCallback(value, isResolved) {
- var callbackOutput = null;
- try {
- callbackOutput = (callback ||defaultCallback)();
- } catch(e) {
- return makePromise(e, false);
- }
- if (isPromiseLike(callbackOutput)) {
- return callbackOutput.then(function() {
- return makePromise(value, isResolved);
- }, function(error) {
- return makePromise(error, false);
- });
- } else {
- return makePromise(value, isResolved);
- }
- }
-
- return this.then(function(value) {
- return handleCallback(value, true);
- }, function(error) {
- return handleCallback(error, false);
- });
- }
- }
- };
-
- return deferred;
- };
-
-
- var ref = function(value) {
- if (isPromiseLike(value)) return value;
- return {
- then: function(callback) {
- var result = defer();
- nextTick(function() {
- result.resolve(callback(value));
- });
- return result.promise;
- }
- };
- };
-
-
- /**
- * @ngdoc method
- * @name $q#reject
- * @kind function
- *
- * @description
- * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
- * used to forward rejection in a chain of promises. If you are dealing with the last promise in
- * a promise chain, you don't need to worry about it.
- *
- * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
- * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
- * a promise error callback and you want to forward the error to the promise derived from the
- * current promise, you have to "rethrow" the error by returning a rejection constructed via
- * `reject`.
- *
- * ```js
- * promiseB = promiseA.then(function(result) {
- * // success: do something and resolve promiseB
- * // with the old or a new result
- * return result;
- * }, function(reason) {
- * // error: handle the error if possible and
- * // resolve promiseB with newPromiseOrValue,
- * // otherwise forward the rejection to promiseB
- * if (canHandle(reason)) {
- * // handle the error and recover
- * return newPromiseOrValue;
- * }
- * return $q.reject(reason);
- * });
- * ```
- *
- * @param {*} reason Constant, message, exception or an object representing the rejection reason.
- * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
- */
- var reject = function(reason) {
- var result = defer();
- result.reject(reason);
- return result.promise;
- };
-
- var createInternalRejectedPromise = function(reason) {
- return {
- then: function(callback, errback) {
- var result = defer();
- nextTick(function() {
- try {
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- });
- return result.promise;
- }
- };
- };
-
-
- /**
- * @ngdoc method
- * @name $q#when
- * @kind function
- *
- * @description
- * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
- * This is useful when you are dealing with an object that might or might not be a promise, or if
- * the promise comes from a source that can't be trusted.
- *
- * @param {*} value Value or a promise
- * @returns {Promise} Returns a promise of the passed value or promise
- */
- var when = function(value, callback, errback, progressback) {
- var result = defer(),
- done;
-
- var wrappedCallback = function(value) {
- try {
- return (isFunction(callback) ? callback : defaultCallback)(value);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
-
- var wrappedErrback = function(reason) {
- try {
- return (isFunction(errback) ? errback : defaultErrback)(reason);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
-
- var wrappedProgressback = function(progress) {
- try {
- return (isFunction(progressback) ? progressback : defaultCallback)(progress);
- } catch (e) {
- exceptionHandler(e);
- }
- };
-
- nextTick(function() {
- ref(value).then(function(value) {
- if (done) return;
- done = true;
- result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback));
- }, function(reason) {
- if (done) return;
- done = true;
- result.resolve(wrappedErrback(reason));
- }, function(progress) {
- if (done) return;
- result.notify(wrappedProgressback(progress));
- });
- });
-
- return result.promise;
- };
-
-
- function defaultCallback(value) {
- return value;
- }
-
-
- function defaultErrback(reason) {
- return reject(reason);
- }
-
-
- /**
- * @ngdoc method
- * @name $q#all
- * @kind function
- *
- * @description
- * Combines multiple promises into a single promise that is resolved when all of the input
- * promises are resolved.
- *
- * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
- * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
- * each value corresponding to the promise at the same index/key in the `promises` array/hash.
- * If any of the promises is resolved with a rejection, this resulting promise will be rejected
- * with the same rejection value.
- */
- function all(promises) {
- var deferred = defer(),
- counter = 0,
- results = isArray(promises) ? [] : {};
-
- forEach(promises, function(promise, key) {
- counter++;
- ref(promise).then(function(value) {
- if (results.hasOwnProperty(key)) return;
- results[key] = value;
- if (!(--counter)) deferred.resolve(results);
- }, function(reason) {
- if (results.hasOwnProperty(key)) return;
- deferred.reject(reason);
- });
- });
-
- if (counter === 0) {
- deferred.resolve(results);
- }
-
- return deferred.promise;
- }
-
- return {
- defer: defer,
- reject: reject,
- when: when,
- all: all
- };
-}
-
-function $$RAFProvider(){ //rAF
- this.$get = ['$window', '$timeout', function($window, $timeout) {
- var requestAnimationFrame = $window.requestAnimationFrame ||
- $window.webkitRequestAnimationFrame ||
- $window.mozRequestAnimationFrame;
-
- var cancelAnimationFrame = $window.cancelAnimationFrame ||
- $window.webkitCancelAnimationFrame ||
- $window.mozCancelAnimationFrame ||
- $window.webkitCancelRequestAnimationFrame;
-
- var rafSupported = !!requestAnimationFrame;
- var raf = rafSupported
- ? function(fn) {
- var id = requestAnimationFrame(fn);
- return function() {
- cancelAnimationFrame(id);
- };
- }
- : function(fn) {
- var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
- return function() {
- $timeout.cancel(timer);
- };
- };
-
- raf.supported = rafSupported;
-
- return raf;
- }];
-}
-
-/**
- * DESIGN NOTES
- *
- * The design decisions behind the scope are heavily favored for speed and memory consumption.
- *
- * The typical use of scope is to watch the expressions, which most of the time return the same
- * value as last time so we optimize the operation.
- *
- * Closures construction is expensive in terms of speed as well as memory:
- * - No closures, instead use prototypical inheritance for API
- * - Internal state needs to be stored on scope directly, which means that private state is
- * exposed as $$____ properties
- *
- * Loop operations are optimized by using while(count--) { ... }
- * - this means that in order to keep the same order of execution as addition we have to add
- * items to the array at the beginning (unshift) instead of at the end (push)
- *
- * Child scopes are created and removed often
- * - Using an array would be slow since inserts in middle are expensive so we use linked list
- *
- * There are few watches then a lot of observers. This is why you don't want the observer to be
- * implemented in the same way as watch. Watch requires return of initialization function which
- * are expensive to construct.
- */
-
-
-/**
- * @ngdoc provider
- * @name $rootScopeProvider
- * @description
- *
- * Provider for the $rootScope service.
- */
-
-/**
- * @ngdoc method
- * @name $rootScopeProvider#digestTtl
- * @description
- *
- * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
- * assuming that the model is unstable.
- *
- * The current default is 10 iterations.
- *
- * In complex applications it's possible that the dependencies between `$watch`s will result in
- * several digest iterations. However if an application needs more than the default 10 digest
- * iterations for its model to stabilize then you should investigate what is causing the model to
- * continuously change during the digest.
- *
- * Increasing the TTL could have performance implications, so you should not change it without
- * proper justification.
- *
- * @param {number} limit The number of digest iterations.
- */
-
-
-/**
- * @ngdoc service
- * @name $rootScope
- * @description
- *
- * Every application has a single root {@link ng.$rootScope.Scope scope}.
- * All other scopes are descendant scopes of the root scope. Scopes provide separation
- * between the model and the view, via a mechanism for watching the model for changes.
- * They also provide an event emission/broadcast and subscription facility. See the
- * {@link guide/scope developer guide on scopes}.
- */
-function $RootScopeProvider(){
- var TTL = 10;
- var $rootScopeMinErr = minErr('$rootScope');
- var lastDirtyWatch = null;
-
- this.digestTtl = function(value) {
- if (arguments.length) {
- TTL = value;
- }
- return TTL;
- };
-
- this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
- function( $injector, $exceptionHandler, $parse, $browser) {
-
- /**
- * @ngdoc type
- * @name $rootScope.Scope
- *
- * @description
- * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
- * {@link auto.$injector $injector}. Child scopes are created using the
- * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
- * compiled HTML template is executed.)
- *
- * Here is a simple scope snippet to show how you can interact with the scope.
- * ```html
- * <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
- * ```
- *
- * # Inheritance
- * A scope can inherit from a parent scope, as in this example:
- * ```js
- var parent = $rootScope;
- var child = parent.$new();
-
- parent.salutation = "Hello";
- child.name = "World";
- expect(child.salutation).toEqual('Hello');
-
- child.salutation = "Welcome";
- expect(child.salutation).toEqual('Welcome');
- expect(parent.salutation).toEqual('Hello');
- * ```
- *
- *
- * @param {Object.<string, function()>=} providers Map of service factory which need to be
- * provided for the current scope. Defaults to {@link ng}.
- * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
- * append/override services provided by `providers`. This is handy
- * when unit-testing and having the need to override a default
- * service.
- * @returns {Object} Newly created scope.
- *
- */
- function Scope() {
- this.$id = nextUid();
- this.$$phase = this.$parent = this.$$watchers =
- this.$$nextSibling = this.$$prevSibling =
- this.$$childHead = this.$$childTail = null;
- this['this'] = this.$root = this;
- this.$$destroyed = false;
- this.$$asyncQueue = [];
- this.$$postDigestQueue = [];
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$$isolateBindings = {};
- }
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$id
- *
- * @description
- * Unique scope ID (monotonically increasing) useful for debugging.
- */
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$parent
- *
- * @description
- * Reference to the parent scope.
- */
-
- /**
- * @ngdoc property
- * @name $rootScope.Scope#$root
- *
- * @description
- * Reference to the root scope.
- */
-
- Scope.prototype = {
- constructor: Scope,
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$new
- * @kind function
- *
- * @description
- * Creates a new child {@link ng.$rootScope.Scope scope}.
- *
- * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
- * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
- *
- * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
- * desired for the scope and its child scopes to be permanently detached from the parent and
- * thus stop participating in model change detection and listener notification by invoking.
- *
- * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
- * parent scope. The scope is isolated, as it can not see parent scope properties.
- * When creating widgets, it is useful for the widget to not accidentally read parent
- * state.
- *
- * @returns {Object} The newly created child scope.
- *
- */
- $new: function(isolate) {
- var ChildScope,
- child;
-
- if (isolate) {
- child = new Scope();
- child.$root = this.$root;
- // ensure that there is just one async queue per $rootScope and its children
- child.$$asyncQueue = this.$$asyncQueue;
- child.$$postDigestQueue = this.$$postDigestQueue;
- } else {
- // Only create a child scope class if somebody asks for one,
- // but cache it to allow the VM to optimize lookups.
- if (!this.$$childScopeClass) {
- this.$$childScopeClass = function() {
- this.$$watchers = this.$$nextSibling =
- this.$$childHead = this.$$childTail = null;
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$id = nextUid();
- this.$$childScopeClass = null;
- };
- this.$$childScopeClass.prototype = this;
- }
- child = new this.$$childScopeClass();
- }
- child['this'] = child;
- child.$parent = this;
- child.$$prevSibling = this.$$childTail;
- if (this.$$childHead) {
- this.$$childTail.$$nextSibling = child;
- this.$$childTail = child;
- } else {
- this.$$childHead = this.$$childTail = child;
- }
- return child;
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$watch
- * @kind function
- *
- * @description
- * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
- *
- * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
- * $digest()} and should return the value that will be watched. (Since
- * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
- * `watchExpression` can execute multiple times per
- * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
- * - The `listener` is called only when the value from the current `watchExpression` and the
- * previous call to `watchExpression` are not equal (with the exception of the initial run,
- * see below). Inequality is determined according to reference inequality,
- * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
- * via the `!==` Javascript operator, unless `objectEquality == true`
- * (see next point)
- * - When `objectEquality == true`, inequality of the `watchExpression` is determined
- * according to the {@link angular.equals} function. To save the value of the object for
- * later comparison, the {@link angular.copy} function is used. This therefore means that
- * watching complex objects will have adverse memory and performance implications.
- * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
- * This is achieved by rerunning the watchers until no changes are detected. The rerun
- * iteration limit is 10 to prevent an infinite loop deadlock.
- *
- *
- * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
- * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
- * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
- * change is detected, be prepared for multiple calls to your listener.)
- *
- * After a watcher is registered with the scope, the `listener` fn is called asynchronously
- * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
- * watcher. In rare cases, this is undesirable because the listener is called when the result
- * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
- * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
- * listener was called due to initialization.
- *
- * The example below contains an illustration of using a function as your $watch listener
- *
- *
- * # Example
- * ```js
- // let's assume that scope was dependency injected as the $rootScope
- var scope = $rootScope;
- scope.name = 'misko';
- scope.counter = 0;
-
- expect(scope.counter).toEqual(0);
- scope.$watch('name', function(newValue, oldValue) {
- scope.counter = scope.counter + 1;
- });
- expect(scope.counter).toEqual(0);
-
- scope.$digest();
- // the listener is always called during the first $digest loop after it was registered
- expect(scope.counter).toEqual(1);
-
- scope.$digest();
- // but now it will not be called unless the value changes
- expect(scope.counter).toEqual(1);
-
- scope.name = 'adam';
- scope.$digest();
- expect(scope.counter).toEqual(2);
-
-
-
- // Using a listener function
- var food;
- scope.foodCounter = 0;
- expect(scope.foodCounter).toEqual(0);
- scope.$watch(
- // This is the listener function
- function() { return food; },
- // This is the change handler
- function(newValue, oldValue) {
- if ( newValue !== oldValue ) {
- // Only increment the counter if the value changed
- scope.foodCounter = scope.foodCounter + 1;
- }
- }
- );
- // No digest has been run so the counter will be zero
- expect(scope.foodCounter).toEqual(0);
-
- // Run the digest but since food has not changed count will still be zero
- scope.$digest();
- expect(scope.foodCounter).toEqual(0);
-
- // Update food and run digest. Now the counter will increment
- food = 'cheeseburger';
- scope.$digest();
- expect(scope.foodCounter).toEqual(1);
-
- * ```
- *
- *
- *
- * @param {(function()|string)} watchExpression Expression that is evaluated on each
- * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
- * a call to the `listener`.
- *
- * - `string`: Evaluated as {@link guide/expression expression}
- * - `function(scope)`: called with current `scope` as a parameter.
- * @param {(function()|string)=} listener Callback called whenever the return value of
- * the `watchExpression` changes.
- *
- * - `string`: Evaluated as {@link guide/expression expression}
- * - `function(newValue, oldValue, scope)`: called with current and previous values as
- * parameters.
- *
- * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
- * comparing for reference equality.
- * @returns {function()} Returns a deregistration function for this listener.
- */
- $watch: function(watchExp, listener, objectEquality) {
- var scope = this,
- get = compileToFn(watchExp, 'watch'),
- array = scope.$$watchers,
- watcher = {
- fn: listener,
- last: initWatchVal,
- get: get,
- exp: watchExp,
- eq: !!objectEquality
- };
-
- lastDirtyWatch = null;
-
- // in the case user pass string, we need to compile it, do we really need this ?
- if (!isFunction(listener)) {
- var listenFn = compileToFn(listener || noop, 'listener');
- watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
- }
-
- if (typeof watchExp == 'string' && get.constant) {
- var originalFn = watcher.fn;
- watcher.fn = function(newVal, oldVal, scope) {
- originalFn.call(this, newVal, oldVal, scope);
- arrayRemove(array, watcher);
- };
- }
-
- if (!array) {
- array = scope.$$watchers = [];
- }
- // we use unshift since we use a while loop in $digest for speed.
- // the while loop reads in reverse order.
- array.unshift(watcher);
-
- return function deregisterWatch() {
- arrayRemove(array, watcher);
- lastDirtyWatch = null;
- };
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$watchCollection
- * @kind function
- *
- * @description
- * Shallow watches the properties of an object and fires whenever any of the properties change
- * (for arrays, this implies watching the array items; for object maps, this implies watching
- * the properties). If a change is detected, the `listener` callback is fired.
- *
- * - The `obj` collection is observed via standard $watch operation and is examined on every
- * call to $digest() to see if any items have been added, removed, or moved.
- * - The `listener` is called whenever anything within the `obj` has changed. Examples include
- * adding, removing, and moving items belonging to an object or array.
- *
- *
- * # Example
- * ```js
- $scope.names = ['igor', 'matias', 'misko', 'james'];
- $scope.dataCount = 4;
-
- $scope.$watchCollection('names', function(newNames, oldNames) {
- $scope.dataCount = newNames.length;
- });
-
- expect($scope.dataCount).toEqual(4);
- $scope.$digest();
-
- //still at 4 ... no changes
- expect($scope.dataCount).toEqual(4);
-
- $scope.names.pop();
- $scope.$digest();
-
- //now there's been a change
- expect($scope.dataCount).toEqual(3);
- * ```
- *
- *
- * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
- * expression value should evaluate to an object or an array which is observed on each
- * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
- * collection will trigger a call to the `listener`.
- *
- * @param {function(newCollection, oldCollection, scope)} listener a callback function called
- * when a change is detected.
- * - The `newCollection` object is the newly modified data obtained from the `obj` expression
- * - The `oldCollection` object is a copy of the former collection data.
- * Due to performance considerations, the`oldCollection` value is computed only if the
- * `listener` function declares two or more arguments.
- * - The `scope` argument refers to the current scope.
- *
- * @returns {function()} Returns a de-registration function for this listener. When the
- * de-registration function is executed, the internal watch operation is terminated.
- */
- $watchCollection: function(obj, listener) {
- var self = this;
- // the current value, updated on each dirty-check run
- var newValue;
- // a shallow copy of the newValue from the last dirty-check run,
- // updated to match newValue during dirty-check run
- var oldValue;
- // a shallow copy of the newValue from when the last change happened
- var veryOldValue;
- // only track veryOldValue if the listener is asking for it
- var trackVeryOldValue = (listener.length > 1);
- var changeDetected = 0;
- var objGetter = $parse(obj);
- var internalArray = [];
- var internalObject = {};
- var initRun = true;
- var oldLength = 0;
-
- function $watchCollectionWatch() {
- newValue = objGetter(self);
- var newLength, key, bothNaN;
-
- if (!isObject(newValue)) { // if primitive
- if (oldValue !== newValue) {
- oldValue = newValue;
- changeDetected++;
- }
- } else if (isArrayLike(newValue)) {
- if (oldValue !== internalArray) {
- // we are transitioning from something which was not an array into array.
- oldValue = internalArray;
- oldLength = oldValue.length = 0;
- changeDetected++;
- }
-
- newLength = newValue.length;
-
- if (oldLength !== newLength) {
- // if lengths do not match we need to trigger change notification
- changeDetected++;
- oldValue.length = oldLength = newLength;
- }
- // copy the items to oldValue and look for changes.
- for (var i = 0; i < newLength; i++) {
- bothNaN = (oldValue[i] !== oldValue[i]) &&
- (newValue[i] !== newValue[i]);
- if (!bothNaN && (oldValue[i] !== newValue[i])) {
- changeDetected++;
- oldValue[i] = newValue[i];
- }
- }
- } else {
- if (oldValue !== internalObject) {
- // we are transitioning from something which was not an object into object.
- oldValue = internalObject = {};
- oldLength = 0;
- changeDetected++;
- }
- // copy the items to oldValue and look for changes.
- newLength = 0;
- for (key in newValue) {
- if (newValue.hasOwnProperty(key)) {
- newLength++;
- if (oldValue.hasOwnProperty(key)) {
- bothNaN = (oldValue[key] !== oldValue[key]) &&
- (newValue[key] !== newValue[key]);
- if (!bothNaN && (oldValue[key] !== newValue[key])) {
- changeDetected++;
- oldValue[key] = newValue[key];
- }
- } else {
- oldLength++;
- oldValue[key] = newValue[key];
- changeDetected++;
- }
- }
- }
- if (oldLength > newLength) {
- // we used to have more keys, need to find them and destroy them.
- changeDetected++;
- for(key in oldValue) {
- if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {
- oldLength--;
- delete oldValue[key];
- }
- }
- }
- }
- return changeDetected;
- }
-
- function $watchCollectionAction() {
- if (initRun) {
- initRun = false;
- listener(newValue, newValue, self);
- } else {
- listener(newValue, veryOldValue, self);
- }
-
- // make a copy for the next time a collection is changed
- if (trackVeryOldValue) {
- if (!isObject(newValue)) {
- //primitive
- veryOldValue = newValue;
- } else if (isArrayLike(newValue)) {
- veryOldValue = new Array(newValue.length);
- for (var i = 0; i < newValue.length; i++) {
- veryOldValue[i] = newValue[i];
- }
- } else { // if object
- veryOldValue = {};
- for (var key in newValue) {
- if (hasOwnProperty.call(newValue, key)) {
- veryOldValue[key] = newValue[key];
- }
- }
- }
- }
- }
-
- return this.$watch($watchCollectionWatch, $watchCollectionAction);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$digest
- * @kind function
- *
- * @description
- * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
- * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
- * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
- * until no more listeners are firing. This means that it is possible to get into an infinite
- * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
- * iterations exceeds 10.
- *
- * Usually, you don't call `$digest()` directly in
- * {@link ng.directive:ngController controllers} or in
- * {@link ng.$compileProvider#directive directives}.
- * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
- * a {@link ng.$compileProvider#directive directives}), which will force a `$digest()`.
- *
- * If you want to be notified whenever `$digest()` is called,
- * you can register a `watchExpression` function with
- * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
- *
- * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
- *
- * # Example
- * ```js
- var scope = ...;
- scope.name = 'misko';
- scope.counter = 0;
-
- expect(scope.counter).toEqual(0);
- scope.$watch('name', function(newValue, oldValue) {
- scope.counter = scope.counter + 1;
- });
- expect(scope.counter).toEqual(0);
-
- scope.$digest();
- // the listener is always called during the first $digest loop after it was registered
- expect(scope.counter).toEqual(1);
-
- scope.$digest();
- // but now it will not be called unless the value changes
- expect(scope.counter).toEqual(1);
-
- scope.name = 'adam';
- scope.$digest();
- expect(scope.counter).toEqual(2);
- * ```
- *
- */
- $digest: function() {
- var watch, value, last,
- watchers,
- asyncQueue = this.$$asyncQueue,
- postDigestQueue = this.$$postDigestQueue,
- length,
- dirty, ttl = TTL,
- next, current, target = this,
- watchLog = [],
- logIdx, logMsg, asyncTask;
-
- beginPhase('$digest');
- // Check for changes to browser url that happened in sync before the call to $digest
- $browser.$$checkUrlChange();
-
- lastDirtyWatch = null;
-
- do { // "while dirty" loop
- dirty = false;
- current = target;
-
- while(asyncQueue.length) {
- try {
- asyncTask = asyncQueue.shift();
- asyncTask.scope.$eval(asyncTask.expression);
- } catch (e) {
- clearPhase();
- $exceptionHandler(e);
- }
- lastDirtyWatch = null;
- }
-
- traverseScopesLoop:
- do { // "traverse the scopes" loop
- if ((watchers = current.$$watchers)) {
- // process our watches
- length = watchers.length;
- while (length--) {
- try {
- watch = watchers[length];
- // Most common watches are on primitives, in which case we can short
- // circuit it with === operator, only when === fails do we use .equals
- if (watch) {
- if ((value = watch.get(current)) !== (last = watch.last) &&
- !(watch.eq
- ? equals(value, last)
- : (typeof value === 'number' && typeof last === 'number'
- && isNaN(value) && isNaN(last)))) {
- dirty = true;
- lastDirtyWatch = watch;
- watch.last = watch.eq ? copy(value, null) : value;
- watch.fn(value, ((last === initWatchVal) ? value : last), current);
- if (ttl < 5) {
- logIdx = 4 - ttl;
- if (!watchLog[logIdx]) watchLog[logIdx] = [];
- logMsg = (isFunction(watch.exp))
- ? 'fn: ' + (watch.exp.name || watch.exp.toString())
- : watch.exp;
- logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
- watchLog[logIdx].push(logMsg);
- }
- } else if (watch === lastDirtyWatch) {
- // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
- // have already been tested.
- dirty = false;
- break traverseScopesLoop;
- }
- }
- } catch (e) {
- clearPhase();
- $exceptionHandler(e);
- }
- }
- }
-
- // Insanity Warning: scope depth-first traversal
- // yes, this code is a bit crazy, but it works and we have tests to prove it!
- // this piece should be kept in sync with the traversal in $broadcast
- if (!(next = (current.$$childHead ||
- (current !== target && current.$$nextSibling)))) {
- while(current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- } while ((current = next));
-
- // `break traverseScopesLoop;` takes us to here
-
- if((dirty || asyncQueue.length) && !(ttl--)) {
- clearPhase();
- throw $rootScopeMinErr('infdig',
- '{0} $digest() iterations reached. Aborting!\n' +
- 'Watchers fired in the last 5 iterations: {1}',
- TTL, toJson(watchLog));
- }
-
- } while (dirty || asyncQueue.length);
-
- clearPhase();
-
- while(postDigestQueue.length) {
- try {
- postDigestQueue.shift()();
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- },
-
-
- /**
- * @ngdoc event
- * @name $rootScope.Scope#$destroy
- * @eventType broadcast on scope being destroyed
- *
- * @description
- * Broadcasted when a scope and its children are being destroyed.
- *
- * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
- * clean up DOM bindings before an element is removed from the DOM.
- */
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$destroy
- * @kind function
- *
- * @description
- * Removes the current scope (and all of its children) from the parent scope. Removal implies
- * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
- * propagate to the current scope and its children. Removal also implies that the current
- * scope is eligible for garbage collection.
- *
- * The `$destroy()` is usually used by directives such as
- * {@link ng.directive:ngRepeat ngRepeat} for managing the
- * unrolling of the loop.
- *
- * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
- * Application code can register a `$destroy` event handler that will give it a chance to
- * perform any necessary cleanup.
- *
- * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
- * clean up DOM bindings before an element is removed from the DOM.
- */
- $destroy: function() {
- // we can't destroy the root scope or a scope that has been already destroyed
- if (this.$$destroyed) return;
- var parent = this.$parent;
-
- this.$broadcast('$destroy');
- this.$$destroyed = true;
- if (this === $rootScope) return;
-
- forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
-
- // sever all the references to parent scopes (after this cleanup, the current scope should
- // not be retained by any of our references and should be eligible for garbage collection)
- if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
- if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
- if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
- if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
-
-
- // All of the code below is bogus code that works around V8's memory leak via optimized code
- // and inline caches.
- //
- // see:
- // - https://code.google.com/p/v8/issues/detail?id=2073#c26
- // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
- // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
-
- this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
- this.$$childTail = this.$root = null;
-
- // don't reset these to null in case some async task tries to register a listener/watch/task
- this.$$listeners = {};
- this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];
-
- // prevent NPEs since these methods have references to properties we nulled out
- this.$destroy = this.$digest = this.$apply = noop;
- this.$on = this.$watch = function() { return noop; };
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$eval
- * @kind function
- *
- * @description
- * Executes the `expression` on the current scope and returns the result. Any exceptions in
- * the expression are propagated (uncaught). This is useful when evaluating Angular
- * expressions.
- *
- * # Example
- * ```js
- var scope = ng.$rootScope.Scope();
- scope.a = 1;
- scope.b = 2;
-
- expect(scope.$eval('a+b')).toEqual(3);
- expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
- * ```
- *
- * @param {(string|function())=} expression An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with the current `scope` parameter.
- *
- * @param {(object)=} locals Local variables object, useful for overriding values in scope.
- * @returns {*} The result of evaluating the expression.
- */
- $eval: function(expr, locals) {
- return $parse(expr)(this, locals);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$evalAsync
- * @kind function
- *
- * @description
- * Executes the expression on the current scope at a later point in time.
- *
- * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
- * that:
- *
- * - it will execute after the function that scheduled the evaluation (preferably before DOM
- * rendering).
- * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
- * `expression` execution.
- *
- * Any exceptions from the execution of the expression are forwarded to the
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
- * will be scheduled. However, it is encouraged to always call code that changes the model
- * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
- *
- * @param {(string|function())=} expression An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with the current `scope` parameter.
- *
- */
- $evalAsync: function(expr) {
- // if we are outside of an $digest loop and this is the first time we are scheduling async
- // task also schedule async auto-flush
- if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
- $browser.defer(function() {
- if ($rootScope.$$asyncQueue.length) {
- $rootScope.$digest();
- }
- });
- }
-
- this.$$asyncQueue.push({scope: this, expression: expr});
- },
-
- $$postDigest : function(fn) {
- this.$$postDigestQueue.push(fn);
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$apply
- * @kind function
- *
- * @description
- * `$apply()` is used to execute an expression in angular from outside of the angular
- * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
- * Because we are calling into the angular framework we need to perform proper scope life
- * cycle of {@link ng.$exceptionHandler exception handling},
- * {@link ng.$rootScope.Scope#$digest executing watches}.
- *
- * ## Life cycle
- *
- * # Pseudo-Code of `$apply()`
- * ```js
- function $apply(expr) {
- try {
- return $eval(expr);
- } catch (e) {
- $exceptionHandler(e);
- } finally {
- $root.$digest();
- }
- }
- * ```
- *
- *
- * Scope's `$apply()` method transitions through the following stages:
- *
- * 1. The {@link guide/expression expression} is executed using the
- * {@link ng.$rootScope.Scope#$eval $eval()} method.
- * 2. Any exceptions from the execution of the expression are forwarded to the
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
- * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
- *
- *
- * @param {(string|function())=} exp An angular expression to be executed.
- *
- * - `string`: execute using the rules as defined in {@link guide/expression expression}.
- * - `function(scope)`: execute the function with current `scope` parameter.
- *
- * @returns {*} The result of evaluating the expression.
- */
- $apply: function(expr) {
- try {
- beginPhase('$apply');
- return this.$eval(expr);
- } catch (e) {
- $exceptionHandler(e);
- } finally {
- clearPhase();
- try {
- $rootScope.$digest();
- } catch (e) {
- $exceptionHandler(e);
- throw e;
- }
- }
- },
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$on
- * @kind function
- *
- * @description
- * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
- * discussion of event life cycle.
- *
- * The event listener function format is: `function(event, args...)`. The `event` object
- * passed into the listener has the following attributes:
- *
- * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
- * `$broadcast`-ed.
- * - `currentScope` - `{Scope}`: the current scope which is handling the event.
- * - `name` - `{string}`: name of the event.
- * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
- * further event propagation (available only for events that were `$emit`-ed).
- * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
- * to true.
- * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
- *
- * @param {string} name Event name to listen on.
- * @param {function(event, ...args)} listener Function to call when the event is emitted.
- * @returns {function()} Returns a deregistration function for this listener.
- */
- $on: function(name, listener) {
- var namedListeners = this.$$listeners[name];
- if (!namedListeners) {
- this.$$listeners[name] = namedListeners = [];
- }
- namedListeners.push(listener);
-
- var current = this;
- do {
- if (!current.$$listenerCount[name]) {
- current.$$listenerCount[name] = 0;
- }
- current.$$listenerCount[name]++;
- } while ((current = current.$parent));
-
- var self = this;
- return function() {
- namedListeners[indexOf(namedListeners, listener)] = null;
- decrementListenerCount(self, 1, name);
- };
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$emit
- * @kind function
- *
- * @description
- * Dispatches an event `name` upwards through the scope hierarchy notifying the
- * registered {@link ng.$rootScope.Scope#$on} listeners.
- *
- * The event life cycle starts at the scope on which `$emit` was called. All
- * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
- * notified. Afterwards, the event traverses upwards toward the root scope and calls all
- * registered listeners along the way. The event will stop propagating if one of the listeners
- * cancels it.
- *
- * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
- * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * @param {string} name Event name to emit.
- * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
- * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
- */
- $emit: function(name, args) {
- var empty = [],
- namedListeners,
- scope = this,
- stopPropagation = false,
- event = {
- name: name,
- targetScope: scope,
- stopPropagation: function() {stopPropagation = true;},
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- },
- listenerArgs = concat([event], arguments, 1),
- i, length;
-
- do {
- namedListeners = scope.$$listeners[name] || empty;
- event.currentScope = scope;
- for (i=0, length=namedListeners.length; i<length; i++) {
-
- // if listeners were deregistered, defragment the array
- if (!namedListeners[i]) {
- namedListeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
- try {
- //allow all listeners attached to the current scope to run
- namedListeners[i].apply(null, listenerArgs);
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- //if any listener on the current scope stops propagation, prevent bubbling
- if (stopPropagation) return event;
- //traverse upwards
- scope = scope.$parent;
- } while (scope);
-
- return event;
- },
-
-
- /**
- * @ngdoc method
- * @name $rootScope.Scope#$broadcast
- * @kind function
- *
- * @description
- * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
- * registered {@link ng.$rootScope.Scope#$on} listeners.
- *
- * The event life cycle starts at the scope on which `$broadcast` was called. All
- * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
- * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
- * scope and calls all registered listeners along the way. The event cannot be canceled.
- *
- * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
- * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * @param {string} name Event name to broadcast.
- * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
- * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
- */
- $broadcast: function(name, args) {
- var target = this,
- current = target,
- next = target,
- event = {
- name: name,
- targetScope: target,
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- },
- listenerArgs = concat([event], arguments, 1),
- listeners, i, length;
-
- //down while you can, then up and next sibling or up and next sibling until back at root
- while ((current = next)) {
- event.currentScope = current;
- listeners = current.$$listeners[name] || [];
- for (i=0, length = listeners.length; i<length; i++) {
- // if listeners were deregistered, defragment the array
- if (!listeners[i]) {
- listeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
-
- try {
- listeners[i].apply(null, listenerArgs);
- } catch(e) {
- $exceptionHandler(e);
- }
- }
-
- // Insanity Warning: scope depth-first traversal
- // yes, this code is a bit crazy, but it works and we have tests to prove it!
- // this piece should be kept in sync with the traversal in $digest
- // (though it differs due to having the extra check for $$listenerCount)
- if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
- (current !== target && current.$$nextSibling)))) {
- while(current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- }
-
- return event;
- }
- };
-
- var $rootScope = new Scope();
-
- return $rootScope;
-
-
- function beginPhase(phase) {
- if ($rootScope.$$phase) {
- throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
- }
-
- $rootScope.$$phase = phase;
- }
-
- function clearPhase() {
- $rootScope.$$phase = null;
- }
-
- function compileToFn(exp, name) {
- var fn = $parse(exp);
- assertArgFn(fn, name);
- return fn;
- }
-
- function decrementListenerCount(current, count, name) {
- do {
- current.$$listenerCount[name] -= count;
-
- if (current.$$listenerCount[name] === 0) {
- delete current.$$listenerCount[name];
- }
- } while ((current = current.$parent));
- }
-
- /**
- * function used as an initial value for watchers.
- * because it's unique we can easily tell it apart from other values
- */
- function initWatchVal() {}
- }];
-}
-
-/**
- * @description
- * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
- */
-function $$SanitizeUriProvider() {
- var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
- imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file):|data:image\/)/;
-
- /**
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during a[href] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- aHrefSanitizationWhitelist = regexp;
- return this;
- }
- return aHrefSanitizationWhitelist;
- };
-
-
- /**
- * @description
- * Retrieves or overrides the default regular expression that is used for whitelisting of safe
- * urls during img[src] sanitization.
- *
- * The sanitization is a security measure aimed at prevent XSS attacks via html links.
- *
- * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
- * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
- * regular expression. If a match is found, the original url is written into the dom. Otherwise,
- * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
- *
- * @param {RegExp=} regexp New regexp to whitelist urls with.
- * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
- * chaining otherwise.
- */
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- imgSrcSanitizationWhitelist = regexp;
- return this;
- }
- return imgSrcSanitizationWhitelist;
- };
-
- this.$get = function() {
- return function sanitizeUri(uri, isImage) {
- var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
- var normalizedVal;
- // NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.
- if (!msie || msie >= 8 ) {
- normalizedVal = urlResolve(uri).href;
- if (normalizedVal !== '' && !normalizedVal.match(regex)) {
- return 'unsafe:'+normalizedVal;
- }
- }
- return uri;
- };
- };
-}
-
-var $sceMinErr = minErr('$sce');
-
-var SCE_CONTEXTS = {
- HTML: 'html',
- CSS: 'css',
- URL: 'url',
- // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
- // url. (e.g. ng-include, script src, templateUrl)
- RESOURCE_URL: 'resourceUrl',
- JS: 'js'
-};
-
-// Helper functions follow.
-
-// Copied from:
-// http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962
-// Prereq: s is a string.
-function escapeForRegexp(s) {
- return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
- replace(/\x08/g, '\\x08');
-}
-
-
-function adjustMatcher(matcher) {
- if (matcher === 'self') {
- return matcher;
- } else if (isString(matcher)) {
- // Strings match exactly except for 2 wildcards - '*' and '**'.
- // '*' matches any character except those from the set ':/.?&'.
- // '**' matches any character (like .* in a RegExp).
- // More than 2 *'s raises an error as it's ill defined.
- if (matcher.indexOf('***') > -1) {
- throw $sceMinErr('iwcard',
- 'Illegal sequence *** in string matcher. String: {0}', matcher);
- }
- matcher = escapeForRegexp(matcher).
- replace('\\*\\*', '.*').
- replace('\\*', '[^:/.?&;]*');
- return new RegExp('^' + matcher + '$');
- } else if (isRegExp(matcher)) {
- // The only other type of matcher allowed is a Regexp.
- // Match entire URL / disallow partial matches.
- // Flags are reset (i.e. no global, ignoreCase or multiline)
- return new RegExp('^' + matcher.source + '$');
- } else {
- throw $sceMinErr('imatcher',
- 'Matchers may only be "self", string patterns or RegExp objects');
- }
-}
-
-
-function adjustMatchers(matchers) {
- var adjustedMatchers = [];
- if (isDefined(matchers)) {
- forEach(matchers, function(matcher) {
- adjustedMatchers.push(adjustMatcher(matcher));
- });
- }
- return adjustedMatchers;
-}
-
-
-/**
- * @ngdoc service
- * @name $sceDelegate
- * @kind function
- *
- * @description
- *
- * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
- * Contextual Escaping (SCE)} services to AngularJS.
- *
- * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
- * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
- * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
- * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
- * work because `$sce` delegates to `$sceDelegate` for these operations.
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
- *
- * The default instance of `$sceDelegate` should work out of the box with little pain. While you
- * can override it completely to change the behavior of `$sce`, the common case would
- * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
- * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
- * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
- * $sceDelegateProvider.resourceUrlWhitelist} and {@link
- * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- */
-
-/**
- * @ngdoc provider
- * @name $sceDelegateProvider
- * @description
- *
- * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
- * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
- * that the URLs used for sourcing Angular templates are safe. Refer {@link
- * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
- * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- *
- * For the general details about this service in Angular, read the main page for {@link ng.$sce
- * Strict Contextual Escaping (SCE)}.
- *
- * **Example**: Consider the following case. <a name="example"></a>
- *
- * - your app is hosted at url `http://myapp.example.com/`
- * - but some of your templates are hosted on other domains you control such as
- * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
- * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
- *
- * Here is what a secure configuration for this scenario might look like:
- *
- * ```
- * angular.module('myApp', []).config(function($sceDelegateProvider) {
- * $sceDelegateProvider.resourceUrlWhitelist([
- * // Allow same origin resource loads.
- * 'self',
- * // Allow loading from our assets domain. Notice the difference between * and **.
- * 'http://srv*.assets.example.com/**'
- * ]);
- *
- * // The blacklist overrides the whitelist so the open redirect here is blocked.
- * $sceDelegateProvider.resourceUrlBlacklist([
- * 'http://myapp.example.com/clickThru**'
- * ]);
- * });
- * ```
- */
-
-function $SceDelegateProvider() {
- this.SCE_CONTEXTS = SCE_CONTEXTS;
-
- // Resource URLs can also be trusted by policy.
- var resourceUrlWhitelist = ['self'],
- resourceUrlBlacklist = [];
-
- /**
- * @ngdoc method
- * @name $sceDelegateProvider#resourceUrlWhitelist
- * @kind function
- *
- * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
- *
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
- *
- * Note: **an empty whitelist array will block all URLs**!
- *
- * @return {Array} the currently set whitelist array.
- *
- * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
- * same origin resource requests.
- *
- * @description
- * Sets/Gets the whitelist of trusted resource URLs.
- */
- this.resourceUrlWhitelist = function (value) {
- if (arguments.length) {
- resourceUrlWhitelist = adjustMatchers(value);
- }
- return resourceUrlWhitelist;
- };
-
- /**
- * @ngdoc method
- * @name $sceDelegateProvider#resourceUrlBlacklist
- * @kind function
- *
- * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
- * provided. This must be an array or null. A snapshot of this array is used so further
- * changes to the array are ignored.
- *
- * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
- * allowed in this array.
- *
- * The typical usage for the blacklist is to **block
- * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
- * these would otherwise be trusted but actually return content from the redirected domain.
- *
- * Finally, **the blacklist overrides the whitelist** and has the final say.
- *
- * @return {Array} the currently set blacklist array.
- *
- * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
- * is no blacklist.)
- *
- * @description
- * Sets/Gets the blacklist of trusted resource URLs.
- */
-
- this.resourceUrlBlacklist = function (value) {
- if (arguments.length) {
- resourceUrlBlacklist = adjustMatchers(value);
- }
- return resourceUrlBlacklist;
- };
-
- this.$get = ['$injector', function($injector) {
-
- var htmlSanitizer = function htmlSanitizer(html) {
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- };
-
- if ($injector.has('$sanitize')) {
- htmlSanitizer = $injector.get('$sanitize');
- }
-
-
- function matchUrl(matcher, parsedUrl) {
- if (matcher === 'self') {
- return urlIsSameOrigin(parsedUrl);
- } else {
- // definitely a regex. See adjustMatchers()
- return !!matcher.exec(parsedUrl.href);
- }
- }
-
- function isResourceUrlAllowedByPolicy(url) {
- var parsedUrl = urlResolve(url.toString());
- var i, n, allowed = false;
- // Ensure that at least one item from the whitelist allows this url.
- for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
- if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
- allowed = true;
- break;
- }
- }
- if (allowed) {
- // Ensure that no item from the blacklist blocked this url.
- for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
- if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
- allowed = false;
- break;
- }
- }
- }
- return allowed;
- }
-
- function generateHolderType(Base) {
- var holderType = function TrustedValueHolderType(trustedValue) {
- this.$$unwrapTrustedValue = function() {
- return trustedValue;
- };
- };
- if (Base) {
- holderType.prototype = new Base();
- }
- holderType.prototype.valueOf = function sceValueOf() {
- return this.$$unwrapTrustedValue();
- };
- holderType.prototype.toString = function sceToString() {
- return this.$$unwrapTrustedValue().toString();
- };
- return holderType;
- }
-
- var trustedValueHolderBase = generateHolderType(),
- byType = {};
-
- byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
-
- /**
- * @ngdoc method
- * @name $sceDelegate#trustAs
- *
- * @description
- * Returns an object that is trusted by angular for use in specified strict
- * contextual escaping contexts (such as ng-bind-html, ng-include, any src
- * attribute interpolation, any dom event binding attribute interpolation
- * such as for onclick, etc.) that uses the provided value.
- * See {@link ng.$sce $sce} for enabling strict contextual escaping.
- *
- * @param {string} type The kind of context in which this value is safe for use. e.g. url,
- * resourceUrl, html, js and css.
- * @param {*} value The value that that should be considered trusted/safe.
- * @returns {*} A value that can be used to stand in for the provided `value` in places
- * where Angular expects a $sce.trustAs() return value.
- */
- function trustAs(type, trustedValue) {
- var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (!Constructor) {
- throw $sceMinErr('icontext',
- 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
- type, trustedValue);
- }
- if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
- return trustedValue;
- }
- // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
- // mutable objects, we ensure here that the value passed in is actually a string.
- if (typeof trustedValue !== 'string') {
- throw $sceMinErr('itype',
- 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
- type);
- }
- return new Constructor(trustedValue);
- }
-
- /**
- * @ngdoc method
- * @name $sceDelegate#valueOf
- *
- * @description
- * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
- * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
- *
- * If the passed parameter is not a value that had been returned by {@link
- * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
- *
- * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
- * call or anything else.
- * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
- * `value` unchanged.
- */
- function valueOf(maybeTrusted) {
- if (maybeTrusted instanceof trustedValueHolderBase) {
- return maybeTrusted.$$unwrapTrustedValue();
- } else {
- return maybeTrusted;
- }
- }
-
- /**
- * @ngdoc method
- * @name $sceDelegate#getTrusted
- *
- * @description
- * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
- * returns the originally supplied value if the queried context type is a supertype of the
- * created type. If this condition isn't satisfied, throws an exception.
- *
- * @param {string} type The kind of context in which this value is to be used.
- * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} call.
- * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
- * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
- */
- function getTrusted(type, maybeTrusted) {
- if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
- return maybeTrusted;
- }
- var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (constructor && maybeTrusted instanceof constructor) {
- return maybeTrusted.$$unwrapTrustedValue();
- }
- // If we get here, then we may only take one of two actions.
- // 1. sanitize the value for the requested type, or
- // 2. throw an exception.
- if (type === SCE_CONTEXTS.RESOURCE_URL) {
- if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
- return maybeTrusted;
- } else {
- throw $sceMinErr('insecurl',
- 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
- maybeTrusted.toString());
- }
- } else if (type === SCE_CONTEXTS.HTML) {
- return htmlSanitizer(maybeTrusted);
- }
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- }
-
- return { trustAs: trustAs,
- getTrusted: getTrusted,
- valueOf: valueOf };
- }];
-}
-
-
-/**
- * @ngdoc provider
- * @name $sceProvider
- * @description
- *
- * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
- * - enable/disable Strict Contextual Escaping (SCE) in a module
- * - override the default implementation with a custom delegate
- *
- * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
- */
-
-/* jshint maxlen: false*/
-
-/**
- * @ngdoc service
- * @name $sce
- * @kind function
- *
- * @description
- *
- * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
- *
- * # Strict Contextual Escaping
- *
- * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
- * contexts to result in a value that is marked as safe to use for that context. One example of
- * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
- * to these contexts as privileged or SCE contexts.
- *
- * As of version 1.2, Angular ships with SCE enabled by default.
- *
- * Note: When enabled (the default), IE8 in quirks mode is not supported. In this mode, IE8 allows
- * one to execute arbitrary javascript by the use of the expression() syntax. Refer
- * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
- * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
- * to the top of your HTML document.
- *
- * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
- * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
- *
- * Here's an example of a binding in a privileged context:
- *
- * ```
- * <input ng-model="userHtml">
- * <div ng-bind-html="userHtml"></div>
- * ```
- *
- * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
- * disabled, this application allows the user to render arbitrary HTML into the DIV.
- * In a more realistic example, one may be rendering user comments, blog articles, etc. via
- * bindings. (HTML is just one example of a context where rendering user controlled input creates
- * security vulnerabilities.)
- *
- * For the case of HTML, you might use a library, either on the client side, or on the server side,
- * to sanitize unsafe HTML before binding to the value and rendering it in the document.
- *
- * How would you ensure that every place that used these types of bindings was bound to a value that
- * was sanitized by your library (or returned as safe for rendering by your server?) How can you
- * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
- * properties/fields and forgot to update the binding to the sanitized value?
- *
- * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
- * determine that something explicitly says it's safe to use a value for binding in that
- * context. You can then audit your code (a simple grep would do) to ensure that this is only done
- * for those values that you can easily tell are safe - because they were received from your server,
- * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
- * allowing only the files in a specific directory to do this. Ensuring that the internal API
- * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
- *
- * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
- * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
- * obtain values that will be accepted by SCE / privileged contexts.
- *
- *
- * ## How does it work?
- *
- * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
- * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
- * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
- * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
- *
- * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
- * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
- * simplified):
- *
- * ```
- * var ngBindHtmlDirective = ['$sce', function($sce) {
- * return function(scope, element, attr) {
- * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
- * element.html(value || '');
- * });
- * };
- * }];
- * ```
- *
- * ## Impact on loading templates
- *
- * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
- * `templateUrl`'s specified by {@link guide/directive directives}.
- *
- * By default, Angular only loads templates from the same domain and protocol as the application
- * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
- * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
- * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
- *
- * *Please note*:
- * The browser's
- * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
- * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
- * policy apply in addition to this and may further restrict whether the template is successfully
- * loaded. This means that without the right CORS policy, loading templates from a different domain
- * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
- * browsers.
- *
- * ## This feels like too much overhead for the developer?
- *
- * It's important to remember that SCE only applies to interpolation expressions.
- *
- * If your expressions are constant literals, they're automatically trusted and you don't need to
- * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
- * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
- *
- * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
- * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
- *
- * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
- * templates in `ng-include` from your application's domain without having to even know about SCE.
- * It blocks loading templates from other domains or loading templates over http from an https
- * served document. You can change these by setting your own custom {@link
- * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
- * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
- *
- * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
- * application that's secure and can be audited to verify that with much more ease than bolting
- * security onto an application later.
- *
- * <a name="contexts"></a>
- * ## What trusted context types are supported?
- *
- * | Context | Notes |
- * |---------------------|----------------|
- * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
- * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
- * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
- * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
- * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
- *
- * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
- *
- * Each element in these arrays must be one of the following:
- *
- * - **'self'**
- * - The special **string**, `'self'`, can be used to match against all URLs of the **same
- * domain** as the application document using the **same protocol**.
- * - **String** (except the special value `'self'`)
- * - The string is matched against the full *normalized / absolute URL* of the resource
- * being tested (substring matches are not good enough.)
- * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
- * match themselves.
- * - `*`: matches zero or more occurrences of any character other than one of the following 6
- * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
- * in a whitelist.
- * - `**`: matches zero or more occurrences of *any* character. As such, it's not
- * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
- * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
- * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
- * http://foo.example.com/templates/**).
- * - **RegExp** (*see caveat below*)
- * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
- * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
- * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
- * have good test coverage.). For instance, the use of `.` in the regex is correct only in a
- * small number of cases. A `.` character in the regex used when matching the scheme or a
- * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
- * is highly recommended to use the string patterns and only fall back to regular expressions
- * if they as a last resort.
- * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
- * matched against the **entire** *normalized / absolute URL* of the resource being tested
- * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
- * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
- * - If you are generating your JavaScript from some other templating engine (not
- * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
- * remember to escape your regular expression (and be aware that you might need more than
- * one level of escaping depending on your templating engine and the way you interpolated
- * the value.) Do make use of your platform's escaping mechanism as it might be good
- * enough before coding your own. e.g. Ruby has
- * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
- * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
- * Javascript lacks a similar built in function for escaping. Take a look at Google
- * Closure library's [goog.string.regExpEscape(s)](
- * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
- *
- * ## Show me an example using SCE.
- *
- * <example module="mySceApp" deps="angular-sanitize.js">
- * <file name="index.html">
- * <div ng-controller="myAppController as myCtrl">
- * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
- * <b>User comments</b><br>
- * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
- * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
- * exploit.
- * <div class="well">
- * <div ng-repeat="userComment in myCtrl.userComments">
- * <b>{{userComment.name}}</b>:
- * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
- * <br>
- * </div>
- * </div>
- * </div>
- * </file>
- *
- * <file name="script.js">
- * var mySceApp = angular.module('mySceApp', ['ngSanitize']);
- *
- * mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
- * var self = this;
- * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
- * self.userComments = userComments;
- * });
- * self.explicitlyTrustedHtml = $sce.trustAsHtml(
- * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
- * 'sanitization.&quot;">Hover over this text.</span>');
- * });
- * </file>
- *
- * <file name="test_data.json">
- * [
- * { "name": "Alice",
- * "htmlComment":
- * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
- * },
- * { "name": "Bob",
- * "htmlComment": "<i>Yes!</i> Am I the only other one?"
- * }
- * ]
- * </file>
- *
- * <file name="protractor.js" type="protractor">
- * describe('SCE doc demo', function() {
- * it('should sanitize untrusted values', function() {
- * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
- * .toBe('<span>Is <i>anyone</i> reading this?</span>');
- * });
- *
- * it('should NOT sanitize explicitly trusted values', function() {
- * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
- * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
- * 'sanitization.&quot;">Hover over this text.</span>');
- * });
- * });
- * </file>
- * </example>
- *
- *
- *
- * ## Can I disable SCE completely?
- *
- * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
- * for little coding overhead. It will be much harder to take an SCE disabled application and
- * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
- * for cases where you have a lot of existing code that was written before SCE was introduced and
- * you're migrating them a module at a time.
- *
- * That said, here's how you can completely disable SCE:
- *
- * ```
- * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
- * // Completely disable SCE. For demonstration purposes only!
- * // Do not use in new projects.
- * $sceProvider.enabled(false);
- * });
- * ```
- *
- */
-/* jshint maxlen: 100 */
-
-function $SceProvider() {
- var enabled = true;
-
- /**
- * @ngdoc method
- * @name $sceProvider#enabled
- * @kind function
- *
- * @param {boolean=} value If provided, then enables/disables SCE.
- * @return {boolean} true if SCE is enabled, false otherwise.
- *
- * @description
- * Enables/disables SCE and returns the current value.
- */
- this.enabled = function (value) {
- if (arguments.length) {
- enabled = !!value;
- }
- return enabled;
- };
-
-
- /* Design notes on the default implementation for SCE.
- *
- * The API contract for the SCE delegate
- * -------------------------------------
- * The SCE delegate object must provide the following 3 methods:
- *
- * - trustAs(contextEnum, value)
- * This method is used to tell the SCE service that the provided value is OK to use in the
- * contexts specified by contextEnum. It must return an object that will be accepted by
- * getTrusted() for a compatible contextEnum and return this value.
- *
- * - valueOf(value)
- * For values that were not produced by trustAs(), return them as is. For values that were
- * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
- * trustAs is wrapping the given values into some type, this operation unwraps it when given
- * such a value.
- *
- * - getTrusted(contextEnum, value)
- * This function should return the a value that is safe to use in the context specified by
- * contextEnum or throw and exception otherwise.
- *
- * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
- * opaque or wrapped in some holder object. That happens to be an implementation detail. For
- * instance, an implementation could maintain a registry of all trusted objects by context. In
- * such a case, trustAs() would return the same object that was passed in. getTrusted() would
- * return the same object passed in if it was found in the registry under a compatible context or
- * throw an exception otherwise. An implementation might only wrap values some of the time based
- * on some criteria. getTrusted() might return a value and not throw an exception for special
- * constants or objects even if not wrapped. All such implementations fulfill this contract.
- *
- *
- * A note on the inheritance model for SCE contexts
- * ------------------------------------------------
- * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
- * is purely an implementation details.
- *
- * The contract is simply this:
- *
- * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
- * will also succeed.
- *
- * Inheritance happens to capture this in a natural way. In some future, we
- * may not use inheritance anymore. That is OK because no code outside of
- * sce.js and sceSpecs.js would need to be aware of this detail.
- */
-
- this.$get = ['$parse', '$sniffer', '$sceDelegate', function(
- $parse, $sniffer, $sceDelegate) {
- // Prereq: Ensure that we're not running in IE8 quirks mode. In that mode, IE allows
- // the "expression(javascript expression)" syntax which is insecure.
- if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {
- throw $sceMinErr('iequirks',
- 'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
- 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
- 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
- }
-
- var sce = shallowCopy(SCE_CONTEXTS);
-
- /**
- * @ngdoc method
- * @name $sce#isEnabled
- * @kind function
- *
- * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
- * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
- *
- * @description
- * Returns a boolean indicating if SCE is enabled.
- */
- sce.isEnabled = function () {
- return enabled;
- };
- sce.trustAs = $sceDelegate.trustAs;
- sce.getTrusted = $sceDelegate.getTrusted;
- sce.valueOf = $sceDelegate.valueOf;
-
- if (!enabled) {
- sce.trustAs = sce.getTrusted = function(type, value) { return value; };
- sce.valueOf = identity;
- }
-
- /**
- * @ngdoc method
- * @name $sce#parseAs
- *
- * @description
- * Converts Angular {@link guide/expression expression} into a function. This is like {@link
- * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
- * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
- * *result*)}
- *
- * @param {string} type The kind of SCE context in which this result will be used.
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
- sce.parseAs = function sceParseAs(type, expr) {
- var parsed = $parse(expr);
- if (parsed.literal && parsed.constant) {
- return parsed;
- } else {
- return function sceParseAsTrusted(self, locals) {
- return sce.getTrusted(type, parsed(self, locals));
- };
- }
- };
-
- /**
- * @ngdoc method
- * @name $sce#trustAs
- *
- * @description
- * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
- * returns an object that is trusted by angular for use in specified strict contextual
- * escaping contexts (such as ng-bind-html, ng-include, any src attribute
- * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
- * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
- * escaping.
- *
- * @param {string} type The kind of context in which this value is safe for use. e.g. url,
- * resource_url, html, js and css.
- * @param {*} value The value that that should be considered trusted/safe.
- * @returns {*} A value that can be used to stand in for the provided `value` in places
- * where Angular expects a $sce.trustAs() return value.
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsHtml
- *
- * @description
- * Shorthand method. `$sce.trustAsHtml(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
- * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsUrl
- *
- * @description
- * Shorthand method. `$sce.trustAsUrl(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
- * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsResourceUrl
- *
- * @description
- * Shorthand method. `$sce.trustAsResourceUrl(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the return
- * value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#trustAsJs
- *
- * @description
- * Shorthand method. `$sce.trustAsJs(value)` →
- * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
- *
- * @param {*} value The value to trustAs.
- * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
- * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
- * only accept expressions that are either literal constants or are the
- * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrusted
- *
- * @description
- * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
- * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
- * originally supplied value if the queried context type is a supertype of the created type.
- * If this condition isn't satisfied, throws an exception.
- *
- * @param {string} type The kind of context in which this value is to be used.
- * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
- * call.
- * @returns {*} The value the was originally provided to
- * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
- * Otherwise, throws an exception.
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedHtml
- *
- * @description
- * Shorthand method. `$sce.getTrustedHtml(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedCss
- *
- * @description
- * Shorthand method. `$sce.getTrustedCss(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedUrl
- *
- * @description
- * Shorthand method. `$sce.getTrustedUrl(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedResourceUrl
- *
- * @description
- * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
- *
- * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#getTrustedJs
- *
- * @description
- * Shorthand method. `$sce.getTrustedJs(value)` →
- * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
- *
- * @param {*} value The value to pass to `$sce.getTrusted`.
- * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsHtml
- *
- * @description
- * Shorthand method. `$sce.parseAsHtml(expression string)` →
- * {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsCss
- *
- * @description
- * Shorthand method. `$sce.parseAsCss(value)` →
- * {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsUrl
- *
- * @description
- * Shorthand method. `$sce.parseAsUrl(value)` →
- * {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsResourceUrl
- *
- * @description
- * Shorthand method. `$sce.parseAsResourceUrl(value)` →
- * {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- /**
- * @ngdoc method
- * @name $sce#parseAsJs
- *
- * @description
- * Shorthand method. `$sce.parseAsJs(value)` →
- * {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
- * are evaluated against (typically a scope object).
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
- * `context`.
- */
-
- // Shorthand delegations.
- var parse = sce.parseAs,
- getTrusted = sce.getTrusted,
- trustAs = sce.trustAs;
-
- forEach(SCE_CONTEXTS, function (enumValue, name) {
- var lName = lowercase(name);
- sce[camelCase("parse_as_" + lName)] = function (expr) {
- return parse(enumValue, expr);
- };
- sce[camelCase("get_trusted_" + lName)] = function (value) {
- return getTrusted(enumValue, value);
- };
- sce[camelCase("trust_as_" + lName)] = function (value) {
- return trustAs(enumValue, value);
- };
- });
-
- return sce;
- }];
-}
-
-/**
- * !!! This is an undocumented "private" service !!!
- *
- * @name $sniffer
- * @requires $window
- * @requires $document
- *
- * @property {boolean} history Does the browser support html5 history api ?
- * @property {boolean} hashchange Does the browser support hashchange event ?
- * @property {boolean} transitions Does the browser support CSS transition events ?
- * @property {boolean} animations Does the browser support CSS animation events ?
- *
- * @description
- * This is very simple implementation of testing browser's features.
- */
-function $SnifferProvider() {
- this.$get = ['$window', '$document', function($window, $document) {
- var eventSupport = {},
- android =
- int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
- boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
- document = $document[0] || {},
- documentMode = document.documentMode,
- vendorPrefix,
- vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
- bodyStyle = document.body && document.body.style,
- transitions = false,
- animations = false,
- match;
-
- if (bodyStyle) {
- for(var prop in bodyStyle) {
- if(match = vendorRegex.exec(prop)) {
- vendorPrefix = match[0];
- vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
- break;
- }
- }
-
- if(!vendorPrefix) {
- vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
- }
-
- transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
- animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
-
- if (android && (!transitions||!animations)) {
- transitions = isString(document.body.style.webkitTransition);
- animations = isString(document.body.style.webkitAnimation);
- }
- }
-
-
- return {
- // Android has history.pushState, but it does not update location correctly
- // so let's not use the history API at all.
- // http://code.google.com/p/android/issues/detail?id=17471
- // https://github.com/angular/angular.js/issues/904
-
- // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
- // so let's not use the history API also
- // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
- // jshint -W018
- history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
- // jshint +W018
- hashchange: 'onhashchange' in $window &&
- // IE8 compatible mode lies
- (!documentMode || documentMode > 7),
- hasEvent: function(event) {
- // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
- // it. In particular the event is not fired when backspace or delete key are pressed or
- // when cut operation is performed.
- if (event == 'input' && msie == 9) return false;
-
- if (isUndefined(eventSupport[event])) {
- var divElm = document.createElement('div');
- eventSupport[event] = 'on' + event in divElm;
- }
-
- return eventSupport[event];
- },
- csp: csp(),
- vendorPrefix: vendorPrefix,
- transitions : transitions,
- animations : animations,
- android: android,
- msie : msie,
- msieDocumentMode: documentMode
- };
- }];
-}
-
-function $TimeoutProvider() {
- this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
- function($rootScope, $browser, $q, $exceptionHandler) {
- var deferreds = {};
-
-
- /**
- * @ngdoc service
- * @name $timeout
- *
- * @description
- * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
- * block and delegates any exceptions to
- * {@link ng.$exceptionHandler $exceptionHandler} service.
- *
- * The return value of registering a timeout function is a promise, which will be resolved when
- * the timeout is reached and the timeout function is executed.
- *
- * To cancel a timeout request, call `$timeout.cancel(promise)`.
- *
- * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
- * synchronously flush the queue of deferred functions.
- *
- * @param {function()} fn A function, whose execution should be delayed.
- * @param {number=} [delay=0] Delay in milliseconds.
- * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
- * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
- * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
- * promise will be resolved with is the return value of the `fn` function.
- *
- */
- function timeout(fn, delay, invokeApply) {
- var deferred = $q.defer(),
- promise = deferred.promise,
- skipApply = (isDefined(invokeApply) && !invokeApply),
- timeoutId;
-
- timeoutId = $browser.defer(function() {
- try {
- deferred.resolve(fn());
- } catch(e) {
- deferred.reject(e);
- $exceptionHandler(e);
- }
- finally {
- delete deferreds[promise.$$timeoutId];
- }
-
- if (!skipApply) $rootScope.$apply();
- }, delay);
-
- promise.$$timeoutId = timeoutId;
- deferreds[timeoutId] = deferred;
-
- return promise;
- }
-
-
- /**
- * @ngdoc method
- * @name $timeout#cancel
- *
- * @description
- * Cancels a task associated with the `promise`. As a result of this, the promise will be
- * resolved with a rejection.
- *
- * @param {Promise=} promise Promise returned by the `$timeout` function.
- * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
- * canceled.
- */
- timeout.cancel = function(promise) {
- if (promise && promise.$$timeoutId in deferreds) {
- deferreds[promise.$$timeoutId].reject('canceled');
- delete deferreds[promise.$$timeoutId];
- return $browser.defer.cancel(promise.$$timeoutId);
- }
- return false;
- };
-
- return timeout;
- }];
-}
-
-// NOTE: The usage of window and document instead of $window and $document here is
-// deliberate. This service depends on the specific behavior of anchor nodes created by the
-// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
-// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
-// doesn't know about mocked locations and resolves URLs to the real document - which is
-// exactly the behavior needed here. There is little value is mocking these out for this
-// service.
-var urlParsingNode = document.createElement("a");
-var originUrl = urlResolve(window.location.href, true);
-
-
-/**
- *
- * Implementation Notes for non-IE browsers
- * ----------------------------------------
- * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
- * results both in the normalizing and parsing of the URL. Normalizing means that a relative
- * URL will be resolved into an absolute URL in the context of the application document.
- * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
- * properties are all populated to reflect the normalized URL. This approach has wide
- * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
- * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- *
- * Implementation Notes for IE
- * ---------------------------
- * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
- * browsers. However, the parsed components will not be set if the URL assigned did not specify
- * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
- * work around that by performing the parsing in a 2nd step by taking a previously normalized
- * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
- * properties such as protocol, hostname, port, etc.
- *
- * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
- * uses the inner HTML approach to assign the URL as part of an HTML snippet -
- * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.
- * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
- * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
- * method and IE < 8 is unsupported.
- *
- * References:
- * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
- * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- * http://url.spec.whatwg.org/#urlutils
- * https://github.com/angular/angular.js/pull/2902
- * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
- *
- * @kind function
- * @param {string} url The URL to be parsed.
- * @description Normalizes and parses a URL.
- * @returns {object} Returns the normalized URL as a dictionary.
- *
- * | member name | Description |
- * |---------------|----------------|
- * | href | A normalized version of the provided URL if it was not an absolute URL |
- * | protocol | The protocol including the trailing colon |
- * | host | The host and port (if the port is non-default) of the normalizedUrl |
- * | search | The search params, minus the question mark |
- * | hash | The hash string, minus the hash symbol
- * | hostname | The hostname
- * | port | The port, without ":"
- * | pathname | The pathname, beginning with "/"
- *
- */
-function urlResolve(url, base) {
- var href = url;
-
- if (msie) {
- // Normalize before parse. Refer Implementation Notes on why this is
- // done in two steps on IE.
- urlParsingNode.setAttribute("href", href);
- href = urlParsingNode.href;
- }
-
- urlParsingNode.setAttribute('href', href);
-
- // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
- return {
- href: urlParsingNode.href,
- protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
- host: urlParsingNode.host,
- search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
- hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
- hostname: urlParsingNode.hostname,
- port: urlParsingNode.port,
- pathname: (urlParsingNode.pathname.charAt(0) === '/')
- ? urlParsingNode.pathname
- : '/' + urlParsingNode.pathname
- };
-}
-
-/**
- * Parse a request URL and determine whether this is a same-origin request as the application document.
- *
- * @param {string|object} requestUrl The url of the request as a string that will be resolved
- * or a parsed URL object.
- * @returns {boolean} Whether the request is for the same origin as the application document.
- */
-function urlIsSameOrigin(requestUrl) {
- var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
- return (parsed.protocol === originUrl.protocol &&
- parsed.host === originUrl.host);
-}
-
-/**
- * @ngdoc service
- * @name $window
- *
- * @description
- * A reference to the browser's `window` object. While `window`
- * is globally available in JavaScript, it causes testability problems, because
- * it is a global variable. In angular we always refer to it through the
- * `$window` service, so it may be overridden, removed or mocked for testing.
- *
- * Expressions, like the one defined for the `ngClick` directive in the example
- * below, are evaluated with respect to the current scope. Therefore, there is
- * no risk of inadvertently coding in a dependency on a global value in such an
- * expression.
- *
- * @example
- <example module="windowExample">
- <file name="index.html">
- <script>
- angular.module('windowExample', [])
- .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
- $scope.greeting = 'Hello, World!';
- $scope.doGreeting = function(greeting) {
- $window.alert(greeting);
- };
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input type="text" ng-model="greeting" />
- <button ng-click="doGreeting(greeting)">ALERT</button>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should display the greeting in the input box', function() {
- element(by.model('greeting')).sendKeys('Hello, E2E Tests');
- // If we click the button it will block the test runner
- // element(':button').click();
- });
- </file>
- </example>
- */
-function $WindowProvider(){
- this.$get = valueFn(window);
-}
-
-/* global currencyFilter: true,
- dateFilter: true,
- filterFilter: true,
- jsonFilter: true,
- limitToFilter: true,
- lowercaseFilter: true,
- numberFilter: true,
- orderByFilter: true,
- uppercaseFilter: true,
- */
-
-/**
- * @ngdoc provider
- * @name $filterProvider
- * @description
- *
- * Filters are just functions which transform input to an output. However filters need to be
- * Dependency Injected. To achieve this a filter definition consists of a factory function which is
- * annotated with dependencies and is responsible for creating a filter function.
- *
- * ```js
- * // Filter registration
- * function MyModule($provide, $filterProvider) {
- * // create a service to demonstrate injection (not always needed)
- * $provide.value('greet', function(name){
- * return 'Hello ' + name + '!';
- * });
- *
- * // register a filter factory which uses the
- * // greet service to demonstrate DI.
- * $filterProvider.register('greet', function(greet){
- * // return the filter function which uses the greet service
- * // to generate salutation
- * return function(text) {
- * // filters need to be forgiving so check input validity
- * return text && greet(text) || text;
- * };
- * });
- * }
- * ```
- *
- * The filter function is registered with the `$injector` under the filter name suffix with
- * `Filter`.
- *
- * ```js
- * it('should be the same instance', inject(
- * function($filterProvider) {
- * $filterProvider.register('reverse', function(){
- * return ...;
- * });
- * },
- * function($filter, reverseFilter) {
- * expect($filter('reverse')).toBe(reverseFilter);
- * });
- * ```
- *
- *
- * For more information about how angular filters work, and how to create your own filters, see
- * {@link guide/filter Filters} in the Angular Developer Guide.
- */
-
-/**
- * @ngdoc service
- * @name $filter
- * @kind function
- * @description
- * Filters are used for formatting data displayed to the user.
- *
- * The general syntax in templates is as follows:
- *
- * {{ expression [| filter_name[:parameter_value] ... ] }}
- *
- * @param {String} name Name of the filter function to retrieve
- * @return {Function} the filter function
- * @example
- <example name="$filter" module="filterExample">
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <h3>{{ originalText }}</h3>
- <h3>{{ filteredText }}</h3>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('filterExample', [])
- .controller('MainCtrl', function($scope, $filter) {
- $scope.originalText = 'hello';
- $scope.filteredText = $filter('uppercase')($scope.originalText);
- });
- </file>
- </example>
- */
-$FilterProvider.$inject = ['$provide'];
-function $FilterProvider($provide) {
- var suffix = 'Filter';
-
- /**
- * @ngdoc method
- * @name $filterProvider#register
- * @param {string|Object} name Name of the filter function, or an object map of filters where
- * the keys are the filter names and the values are the filter factories.
- * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
- * of the registered filter instances.
- */
- function register(name, factory) {
- if(isObject(name)) {
- var filters = {};
- forEach(name, function(filter, key) {
- filters[key] = register(key, filter);
- });
- return filters;
- } else {
- return $provide.factory(name + suffix, factory);
- }
- }
- this.register = register;
-
- this.$get = ['$injector', function($injector) {
- return function(name) {
- return $injector.get(name + suffix);
- };
- }];
-
- ////////////////////////////////////////
-
- /* global
- currencyFilter: false,
- dateFilter: false,
- filterFilter: false,
- jsonFilter: false,
- limitToFilter: false,
- lowercaseFilter: false,
- numberFilter: false,
- orderByFilter: false,
- uppercaseFilter: false,
- */
-
- register('currency', currencyFilter);
- register('date', dateFilter);
- register('filter', filterFilter);
- register('json', jsonFilter);
- register('limitTo', limitToFilter);
- register('lowercase', lowercaseFilter);
- register('number', numberFilter);
- register('orderBy', orderByFilter);
- register('uppercase', uppercaseFilter);
-}
-
-/**
- * @ngdoc filter
- * @name filter
- * @kind function
- *
- * @description
- * Selects a subset of items from `array` and returns it as a new array.
- *
- * @param {Array} array The source array.
- * @param {string|Object|function()} expression The predicate to be used for selecting items from
- * `array`.
- *
- * Can be one of:
- *
- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
- * will be returned. The predicate can be negated by prefixing the string with `!`.
- *
- * - `Object`: A pattern object can be used to filter specific properties on objects contained
- * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
- * which have property `name` containing "M" and property `phone` containing "1". A special
- * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
- * property of the object. That's equivalent to the simple substring match with a `string`
- * as described above. The predicate can be negated by prefixing the string with `!`.
- * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
- * not containing "M".
- *
- * - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
- * called for each element of `array`. The final result is an array of those elements that
- * the predicate returned true for.
- *
- * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
- * determining if the expected value (from the filter expression) and actual value (from
- * the object in the array) should be considered a match.
- *
- * Can be one of:
- *
- * - `function(actual, expected)`:
- * The function will be given the object value and the predicate value to compare and
- * should return true if the item should be included in filtered result.
- *
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
- * this is essentially strict comparison of expected and actual.
- *
- * - `false|undefined`: A short hand for a function which will look for a substring match in case
- * insensitive way.
- *
- * @example
- <example>
- <file name="index.html">
- <div ng-init="friends = [{name:'John', phone:'555-1276'},
- {name:'Mary', phone:'800-BIG-MARY'},
- {name:'Mike', phone:'555-4321'},
- {name:'Adam', phone:'555-5678'},
- {name:'Julie', phone:'555-8765'},
- {name:'Juliette', phone:'555-5678'}]"></div>
-
- Search: <input ng-model="searchText">
- <table id="searchTextResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friend in friends | filter:searchText">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- </tr>
- </table>
- <hr>
- Any: <input ng-model="search.$"> <br>
- Name only <input ng-model="search.name"><br>
- Phone only <input ng-model="search.phone"><br>
- Equality <input type="checkbox" ng-model="strict"><br>
- <table id="searchObjResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friendObj in friends | filter:search:strict">
- <td>{{friendObj.name}}</td>
- <td>{{friendObj.phone}}</td>
- </tr>
- </table>
- </file>
- <file name="protractor.js" type="protractor">
- var expectFriendNames = function(expectedNames, key) {
- element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
- arr.forEach(function(wd, i) {
- expect(wd.getText()).toMatch(expectedNames[i]);
- });
- });
- };
-
- it('should search across all fields when filtering with a string', function() {
- var searchText = element(by.model('searchText'));
- searchText.clear();
- searchText.sendKeys('m');
- expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
-
- searchText.clear();
- searchText.sendKeys('76');
- expectFriendNames(['John', 'Julie'], 'friend');
- });
-
- it('should search in specific fields when filtering with a predicate object', function() {
- var searchAny = element(by.model('search.$'));
- searchAny.clear();
- searchAny.sendKeys('i');
- expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
- });
- it('should use a equal comparison when comparator is true', function() {
- var searchName = element(by.model('search.name'));
- var strict = element(by.model('strict'));
- searchName.clear();
- searchName.sendKeys('Julie');
- strict.click();
- expectFriendNames(['Julie'], 'friendObj');
- });
- </file>
- </example>
- */
-function filterFilter() {
- return function(array, expression, comparator) {
- if (!isArray(array)) return array;
-
- var comparatorType = typeof(comparator),
- predicates = [];
-
- predicates.check = function(value) {
- for (var j = 0; j < predicates.length; j++) {
- if(!predicates[j](value)) {
- return false;
- }
- }
- return true;
- };
-
- if (comparatorType !== 'function') {
- if (comparatorType === 'boolean' && comparator) {
- comparator = function(obj, text) {
- return angular.equals(obj, text);
- };
- } else {
- comparator = function(obj, text) {
- if (obj && text && typeof obj === 'object' && typeof text === 'object') {
- for (var objKey in obj) {
- if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
- comparator(obj[objKey], text[objKey])) {
- return true;
- }
- }
- return false;
- }
- text = (''+text).toLowerCase();
- return (''+obj).toLowerCase().indexOf(text) > -1;
- };
- }
- }
-
- var search = function(obj, text){
- if (typeof text == 'string' && text.charAt(0) === '!') {
- return !search(obj, text.substr(1));
- }
- switch (typeof obj) {
- case "boolean":
- case "number":
- case "string":
- return comparator(obj, text);
- case "object":
- switch (typeof text) {
- case "object":
- return comparator(obj, text);
- default:
- for ( var objKey in obj) {
- if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
- return true;
- }
- }
- break;
- }
- return false;
- case "array":
- for ( var i = 0; i < obj.length; i++) {
- if (search(obj[i], text)) {
- return true;
- }
- }
- return false;
- default:
- return false;
- }
- };
- switch (typeof expression) {
- case "boolean":
- case "number":
- case "string":
- // Set up expression object and fall through
- expression = {$:expression};
- // jshint -W086
- case "object":
- // jshint +W086
- for (var key in expression) {
- (function(path) {
- if (typeof expression[path] === 'undefined') return;
- predicates.push(function(value) {
- return search(path == '$' ? value : (value && value[path]), expression[path]);
- });
- })(key);
- }
- break;
- case 'function':
- predicates.push(expression);
- break;
- default:
- return array;
- }
- var filtered = [];
- for ( var j = 0; j < array.length; j++) {
- var value = array[j];
- if (predicates.check(value)) {
- filtered.push(value);
- }
- }
- return filtered;
- };
-}
-
-/**
- * @ngdoc filter
- * @name currency
- * @kind function
- *
- * @description
- * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
- * symbol for current locale is used.
- *
- * @param {number} amount Input to filter.
- * @param {string=} symbol Currency symbol or identifier to be displayed.
- * @returns {string} Formatted number.
- *
- *
- * @example
- <example module="currencyExample">
- <file name="index.html">
- <script>
- angular.module('currencyExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.amount = 1234.56;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input type="number" ng-model="amount"> <br>
- default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
- custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should init with 1234.56', function() {
- expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
- expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56');
- });
- it('should update', function() {
- if (browser.params.browser == 'safari') {
- // Safari does not understand the minus key. See
- // https://github.com/angular/protractor/issues/481
- return;
- }
- element(by.model('amount')).clear();
- element(by.model('amount')).sendKeys('-1234');
- expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
- expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)');
- });
- </file>
- </example>
- */
-currencyFilter.$inject = ['$locale'];
-function currencyFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(amount, currencySymbol){
- if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
- return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
- replace(/\u00A4/g, currencySymbol);
- };
-}
-
-/**
- * @ngdoc filter
- * @name number
- * @kind function
- *
- * @description
- * Formats a number as text.
- *
- * If the input is not a number an empty string is returned.
- *
- * @param {number|string} number Number to format.
- * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
- * If this is not provided then the fraction size is computed from the current locale's number
- * formatting pattern. In the case of the default locale, it will be 3.
- * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit.
- *
- * @example
- <example module="numberFilterExample">
- <file name="index.html">
- <script>
- angular.module('numberFilterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.val = 1234.56789;
- }]);
- </script>
- <div ng-controller="ExampleController">
- Enter number: <input ng-model='val'><br>
- Default formatting: <span id='number-default'>{{val | number}}</span><br>
- No fractions: <span>{{val | number:0}}</span><br>
- Negative number: <span>{{-val | number:4}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format numbers', function() {
- expect(element(by.id('number-default')).getText()).toBe('1,234.568');
- expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
- });
-
- it('should update', function() {
- element(by.model('val')).clear();
- element(by.model('val')).sendKeys('3374.333');
- expect(element(by.id('number-default')).getText()).toBe('3,374.333');
- expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
- });
- </file>
- </example>
- */
-
-
-numberFilter.$inject = ['$locale'];
-function numberFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(number, fractionSize) {
- return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
- fractionSize);
- };
-}
-
-var DECIMAL_SEP = '.';
-function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
- if (number == null || !isFinite(number) || isObject(number)) return '';
-
- var isNegative = number < 0;
- number = Math.abs(number);
- var numStr = number + '',
- formatedText = '',
- parts = [];
-
- var hasExponent = false;
- if (numStr.indexOf('e') !== -1) {
- var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
- if (match && match[2] == '-' && match[3] > fractionSize + 1) {
- numStr = '0';
- number = 0;
- } else {
- formatedText = numStr;
- hasExponent = true;
- }
- }
-
- if (!hasExponent) {
- var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
-
- // determine fractionSize if it is not specified
- if (isUndefined(fractionSize)) {
- fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
- }
-
- // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
- // inspired by:
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
- number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
-
- if (number === 0) {
- isNegative = false;
- }
-
- var fraction = ('' + number).split(DECIMAL_SEP);
- var whole = fraction[0];
- fraction = fraction[1] || '';
-
- var i, pos = 0,
- lgroup = pattern.lgSize,
- group = pattern.gSize;
-
- if (whole.length >= (lgroup + group)) {
- pos = whole.length - lgroup;
- for (i = 0; i < pos; i++) {
- if ((pos - i)%group === 0 && i !== 0) {
- formatedText += groupSep;
- }
- formatedText += whole.charAt(i);
- }
- }
-
- for (i = pos; i < whole.length; i++) {
- if ((whole.length - i)%lgroup === 0 && i !== 0) {
- formatedText += groupSep;
- }
- formatedText += whole.charAt(i);
- }
-
- // format fraction part.
- while(fraction.length < fractionSize) {
- fraction += '0';
- }
-
- if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
- } else {
-
- if (fractionSize > 0 && number > -1 && number < 1) {
- formatedText = number.toFixed(fractionSize);
- }
- }
-
- parts.push(isNegative ? pattern.negPre : pattern.posPre);
- parts.push(formatedText);
- parts.push(isNegative ? pattern.negSuf : pattern.posSuf);
- return parts.join('');
-}
-
-function padNumber(num, digits, trim) {
- var neg = '';
- if (num < 0) {
- neg = '-';
- num = -num;
- }
- num = '' + num;
- while(num.length < digits) num = '0' + num;
- if (trim)
- num = num.substr(num.length - digits);
- return neg + num;
-}
-
-
-function dateGetter(name, size, offset, trim) {
- offset = offset || 0;
- return function(date) {
- var value = date['get' + name]();
- if (offset > 0 || value > -offset)
- value += offset;
- if (value === 0 && offset == -12 ) value = 12;
- return padNumber(value, size, trim);
- };
-}
-
-function dateStrGetter(name, shortForm) {
- return function(date, formats) {
- var value = date['get' + name]();
- var get = uppercase(shortForm ? ('SHORT' + name) : name);
-
- return formats[get][value];
- };
-}
-
-function timeZoneGetter(date) {
- var zone = -1 * date.getTimezoneOffset();
- var paddedZone = (zone >= 0) ? "+" : "";
-
- paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
- padNumber(Math.abs(zone % 60), 2);
-
- return paddedZone;
-}
-
-function ampmGetter(date, formats) {
- return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
-}
-
-var DATE_FORMATS = {
- yyyy: dateGetter('FullYear', 4),
- yy: dateGetter('FullYear', 2, 0, true),
- y: dateGetter('FullYear', 1),
- MMMM: dateStrGetter('Month'),
- MMM: dateStrGetter('Month', true),
- MM: dateGetter('Month', 2, 1),
- M: dateGetter('Month', 1, 1),
- dd: dateGetter('Date', 2),
- d: dateGetter('Date', 1),
- HH: dateGetter('Hours', 2),
- H: dateGetter('Hours', 1),
- hh: dateGetter('Hours', 2, -12),
- h: dateGetter('Hours', 1, -12),
- mm: dateGetter('Minutes', 2),
- m: dateGetter('Minutes', 1),
- ss: dateGetter('Seconds', 2),
- s: dateGetter('Seconds', 1),
- // while ISO 8601 requires fractions to be prefixed with `.` or `,`
- // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
- sss: dateGetter('Milliseconds', 3),
- EEEE: dateStrGetter('Day'),
- EEE: dateStrGetter('Day', true),
- a: ampmGetter,
- Z: timeZoneGetter
-};
-
-var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
- NUMBER_STRING = /^\-?\d+$/;
-
-/**
- * @ngdoc filter
- * @name date
- * @kind function
- *
- * @description
- * Formats `date` to a string based on the requested `format`.
- *
- * `format` string can be composed of the following elements:
- *
- * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
- * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
- * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
- * * `'MMMM'`: Month in year (January-December)
- * * `'MMM'`: Month in year (Jan-Dec)
- * * `'MM'`: Month in year, padded (01-12)
- * * `'M'`: Month in year (1-12)
- * * `'dd'`: Day in month, padded (01-31)
- * * `'d'`: Day in month (1-31)
- * * `'EEEE'`: Day in Week,(Sunday-Saturday)
- * * `'EEE'`: Day in Week, (Sun-Sat)
- * * `'HH'`: Hour in day, padded (00-23)
- * * `'H'`: Hour in day (0-23)
- * * `'hh'`: Hour in am/pm, padded (01-12)
- * * `'h'`: Hour in am/pm, (1-12)
- * * `'mm'`: Minute in hour, padded (00-59)
- * * `'m'`: Minute in hour (0-59)
- * * `'ss'`: Second in minute, padded (00-59)
- * * `'s'`: Second in minute (0-59)
- * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
- * * `'a'`: am/pm marker
- * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
- *
- * `format` string can also be one of the following predefined
- * {@link guide/i18n localizable formats}:
- *
- * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
- * (e.g. Sep 3, 2010 12:05:08 pm)
- * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm)
- * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale
- * (e.g. Friday, September 3, 2010)
- * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
- * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
- * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
- * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
- * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
- *
- * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
- * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
- * (e.g. `"h 'o''clock'"`).
- *
- * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
- * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
- * specified in the string input, the time is considered to be in the local timezone.
- * @param {string=} format Formatting rules (see Description). If not specified,
- * `mediumDate` is used.
- * @returns {string} Formatted string or the input if input is not recognized as date/millis.
- *
- * @example
- <example>
- <file name="index.html">
- <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
- <span>{{1288323623006 | date:'medium'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
- <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
- <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
- <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format date', function() {
- expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
- toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
- expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
- expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
- toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
- expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
- toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
- });
- </file>
- </example>
- */
-dateFilter.$inject = ['$locale'];
-function dateFilter($locale) {
-
-
- var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
- // 1 2 3 4 5 6 7 8 9 10 11
- function jsonStringToDate(string) {
- var match;
- if (match = string.match(R_ISO8601_STR)) {
- var date = new Date(0),
- tzHour = 0,
- tzMin = 0,
- dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
- timeSetter = match[8] ? date.setUTCHours : date.setHours;
-
- if (match[9]) {
- tzHour = int(match[9] + match[10]);
- tzMin = int(match[9] + match[11]);
- }
- dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
- var h = int(match[4]||0) - tzHour;
- var m = int(match[5]||0) - tzMin;
- var s = int(match[6]||0);
- var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
- timeSetter.call(date, h, m, s, ms);
- return date;
- }
- return string;
- }
-
-
- return function(date, format) {
- var text = '',
- parts = [],
- fn, match;
-
- format = format || 'mediumDate';
- format = $locale.DATETIME_FORMATS[format] || format;
- if (isString(date)) {
- date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
- }
-
- if (isNumber(date)) {
- date = new Date(date);
- }
-
- if (!isDate(date)) {
- return date;
- }
-
- while(format) {
- match = DATE_FORMATS_SPLIT.exec(format);
- if (match) {
- parts = concat(parts, match, 1);
- format = parts.pop();
- } else {
- parts.push(format);
- format = null;
- }
- }
-
- forEach(parts, function(value){
- fn = DATE_FORMATS[value];
- text += fn ? fn(date, $locale.DATETIME_FORMATS)
- : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
- });
-
- return text;
- };
-}
-
-
-/**
- * @ngdoc filter
- * @name json
- * @kind function
- *
- * @description
- * Allows you to convert a JavaScript object into JSON string.
- *
- * This filter is mostly useful for debugging. When using the double curly {{value}} notation
- * the binding is automatically converted to JSON.
- *
- * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
- * @returns {string} JSON string.
- *
- *
- * @example
- <example>
- <file name="index.html">
- <pre>{{ {'name':'value'} | json }}</pre>
- </file>
- <file name="protractor.js" type="protractor">
- it('should jsonify filtered objects', function() {
- expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/);
- });
- </file>
- </example>
- *
- */
-function jsonFilter() {
- return function(object) {
- return toJson(object, true);
- };
-}
-
-
-/**
- * @ngdoc filter
- * @name lowercase
- * @kind function
- * @description
- * Converts string to lowercase.
- * @see angular.lowercase
- */
-var lowercaseFilter = valueFn(lowercase);
-
-
-/**
- * @ngdoc filter
- * @name uppercase
- * @kind function
- * @description
- * Converts string to uppercase.
- * @see angular.uppercase
- */
-var uppercaseFilter = valueFn(uppercase);
-
-/**
- * @ngdoc filter
- * @name limitTo
- * @kind function
- *
- * @description
- * Creates a new array or string containing only a specified number of elements. The elements
- * are taken from either the beginning or the end of the source array or string, as specified by
- * the value and sign (positive or negative) of `limit`.
- *
- * @param {Array|string} input Source array or string to be limited.
- * @param {string|number} limit The length of the returned array or string. If the `limit` number
- * is positive, `limit` number of items from the beginning of the source array/string are copied.
- * If the number is negative, `limit` number of items from the end of the source array/string
- * are copied. The `limit` will be trimmed if it exceeds `array.length`
- * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
- * had less than `limit` elements.
- *
- * @example
- <example module="limitToExample">
- <file name="index.html">
- <script>
- angular.module('limitToExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.numbers = [1,2,3,4,5,6,7,8,9];
- $scope.letters = "abcdefghi";
- $scope.numLimit = 3;
- $scope.letterLimit = 3;
- }]);
- </script>
- <div ng-controller="ExampleController">
- Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
- <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
- Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
- <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- var numLimitInput = element(by.model('numLimit'));
- var letterLimitInput = element(by.model('letterLimit'));
- var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
- var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
-
- it('should limit the number array to first three items', function() {
- expect(numLimitInput.getAttribute('value')).toBe('3');
- expect(letterLimitInput.getAttribute('value')).toBe('3');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
- expect(limitedLetters.getText()).toEqual('Output letters: abc');
- });
-
- it('should update the output when -3 is entered', function() {
- numLimitInput.clear();
- numLimitInput.sendKeys('-3');
- letterLimitInput.clear();
- letterLimitInput.sendKeys('-3');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
- expect(limitedLetters.getText()).toEqual('Output letters: ghi');
- });
-
- it('should not exceed the maximum size of input array', function() {
- numLimitInput.clear();
- numLimitInput.sendKeys('100');
- letterLimitInput.clear();
- letterLimitInput.sendKeys('100');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
- expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
- });
- </file>
- </example>
- */
-function limitToFilter(){
- return function(input, limit) {
- if (!isArray(input) && !isString(input)) return input;
-
- if (Math.abs(Number(limit)) === Infinity) {
- limit = Number(limit);
- } else {
- limit = int(limit);
- }
-
- if (isString(input)) {
- //NaN check on limit
- if (limit) {
- return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
- } else {
- return "";
- }
- }
-
- var out = [],
- i, n;
-
- // if abs(limit) exceeds maximum length, trim it
- if (limit > input.length)
- limit = input.length;
- else if (limit < -input.length)
- limit = -input.length;
-
- if (limit > 0) {
- i = 0;
- n = limit;
- } else {
- i = input.length + limit;
- n = input.length;
- }
-
- for (; i<n; i++) {
- out.push(input[i]);
- }
-
- return out;
- };
-}
-
-/**
- * @ngdoc filter
- * @name orderBy
- * @kind function
- *
- * @description
- * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
- * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
- * correctly, make sure they are actually being saved as numbers and not strings.
- *
- * @param {Array} array The array to sort.
- * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
- * used by the comparator to determine the order of elements.
- *
- * Can be one of:
- *
- * - `function`: Getter function. The result of this function will be sorted using the
- * `<`, `=`, `>` operator.
- * - `string`: An Angular expression. The result of this expression is used to compare elements
- * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
- * 3 first characters of a property called `name`). The result of a constant expression
- * is interpreted as a property name to be used in comparisons (for example `"special name"`
- * to sort object by the value of their `special name` property). An expression can be
- * optionally prefixed with `+` or `-` to control ascending or descending sort order
- * (for example, `+name` or `-name`).
- * - `Array`: An array of function or string predicates. The first predicate in the array
- * is used for sorting, but when two items are equivalent, the next predicate is used.
- *
- * @param {boolean=} reverse Reverse the order of the array.
- * @returns {Array} Sorted copy of the source array.
- *
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <script>
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- $scope.predicate = '-age';
- }]);
- </script>
- <div ng-controller="ExampleController">
- <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
- <hr/>
- [ <a href="" ng-click="predicate=''">unsorted</a> ]
- <table class="friend">
- <tr>
- <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
- (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
- <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
- <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
- </tr>
- <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
- </example>
- *
- * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
- * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
- * desired parameters.
- *
- * Example:
- *
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <table class="friend">
- <tr>
- <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
- (<a href="" ng-click="order('-name',false)">^</a>)</th>
- <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
- <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
- </tr>
- <tr ng-repeat="friend in friends">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
- var orderBy = $filter('orderBy');
- $scope.friends = [
- { name: 'John', phone: '555-1212', age: 10 },
- { name: 'Mary', phone: '555-9876', age: 19 },
- { name: 'Mike', phone: '555-4321', age: 21 },
- { name: 'Adam', phone: '555-5678', age: 35 },
- { name: 'Julie', phone: '555-8765', age: 29 }
- ];
- $scope.order = function(predicate, reverse) {
- $scope.friends = orderBy($scope.friends, predicate, reverse);
- };
- $scope.order('-age',false);
- }]);
- </file>
-</example>
- */
-orderByFilter.$inject = ['$parse'];
-function orderByFilter($parse){
- return function(array, sortPredicate, reverseOrder) {
- if (!(isArrayLike(array))) return array;
- if (!sortPredicate) return array;
- sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
- sortPredicate = map(sortPredicate, function(predicate){
- var descending = false, get = predicate || identity;
- if (isString(predicate)) {
- if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
- descending = predicate.charAt(0) == '-';
- predicate = predicate.substring(1);
- }
- get = $parse(predicate);
- if (get.constant) {
- var key = get();
- return reverseComparator(function(a,b) {
- return compare(a[key], b[key]);
- }, descending);
- }
- }
- return reverseComparator(function(a,b){
- return compare(get(a),get(b));
- }, descending);
- });
- var arrayCopy = [];
- for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
- return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
-
- function comparator(o1, o2){
- for ( var i = 0; i < sortPredicate.length; i++) {
- var comp = sortPredicate[i](o1, o2);
- if (comp !== 0) return comp;
- }
- return 0;
- }
- function reverseComparator(comp, descending) {
- return toBoolean(descending)
- ? function(a,b){return comp(b,a);}
- : comp;
- }
- function compare(v1, v2){
- var t1 = typeof v1;
- var t2 = typeof v2;
- if (t1 == t2) {
- if (isDate(v1) && isDate(v2)) {
- v1 = v1.valueOf();
- v2 = v2.valueOf();
- }
- if (t1 == "string") {
- v1 = v1.toLowerCase();
- v2 = v2.toLowerCase();
- }
- if (v1 === v2) return 0;
- return v1 < v2 ? -1 : 1;
- } else {
- return t1 < t2 ? -1 : 1;
- }
- }
- };
-}
-
-function ngDirective(directive) {
- if (isFunction(directive)) {
- directive = {
- link: directive
- };
- }
- directive.restrict = directive.restrict || 'AC';
- return valueFn(directive);
-}
-
-/**
- * @ngdoc directive
- * @name a
- * @restrict E
- *
- * @description
- * Modifies the default behavior of the html A tag so that the default action is prevented when
- * the href attribute is empty.
- *
- * This change permits the easy creation of action links with the `ngClick` directive
- * without changing the location or causing page reloads, e.g.:
- * `<a href="" ng-click="list.addItem()">Add Item</a>`
- */
-var htmlAnchorDirective = valueFn({
- restrict: 'E',
- compile: function(element, attr) {
-
- if (msie <= 8) {
-
- // turn <a href ng-click="..">link</a> into a stylable link in IE
- // but only if it doesn't have name attribute, in which case it's an anchor
- if (!attr.href && !attr.name) {
- attr.$set('href', '');
- }
-
- // add a comment node to anchors to workaround IE bug that causes element content to be reset
- // to new attribute content if attribute is updated with value containing @ and element also
- // contains value with @
- // see issue #1949
- element.append(document.createComment('IE fix'));
- }
-
- if (!attr.href && !attr.xlinkHref && !attr.name) {
- return function(scope, element) {
- // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
- var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
- 'xlink:href' : 'href';
- element.on('click', function(event){
- // if we have no href url, then don't navigate anywhere.
- if (!element.attr(href)) {
- event.preventDefault();
- }
- });
- };
- }
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngHref
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in an href attribute will
- * make the link go to the wrong URL if the user clicks it before
- * Angular has a chance to replace the `{{hash}}` markup with its
- * value. Until Angular replaces the markup the link will be broken
- * and will most likely return a 404 error.
- *
- * The `ngHref` directive solves this problem.
- *
- * The wrong way to write it:
- * ```html
- * <a href="http://www.gravatar.com/avatar/{{hash}}"/>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <a ng-href="http://www.gravatar.com/avatar/{{hash}}"/>
- * ```
- *
- * @element A
- * @param {template} ngHref any string which can contain `{{}}` markup.
- *
- * @example
- * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
- * in links and their different behaviors:
- <example>
- <file name="index.html">
- <input ng-model="value" /><br />
- <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
- <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
- <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
- <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
- <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
- <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
- </file>
- <file name="protractor.js" type="protractor">
- it('should execute ng-click but not reload when href without value', function() {
- element(by.id('link-1')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('1');
- expect(element(by.id('link-1')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click but not reload when href empty string', function() {
- element(by.id('link-2')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('2');
- expect(element(by.id('link-2')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click and change url when ng-href specified', function() {
- expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
-
- element(by.id('link-3')).click();
-
- // At this point, we navigate away from an Angular page, so we need
- // to use browser.driver to get the base webdriver.
-
- browser.wait(function() {
- return browser.driver.getCurrentUrl().then(function(url) {
- return url.match(/\/123$/);
- });
- }, 5000, 'page should navigate to /123');
- });
-
- xit('should execute ng-click but not reload when href empty string and name specified', function() {
- element(by.id('link-4')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('4');
- expect(element(by.id('link-4')).getAttribute('href')).toBe('');
- });
-
- it('should execute ng-click but not reload when no href but name specified', function() {
- element(by.id('link-5')).click();
- expect(element(by.model('value')).getAttribute('value')).toEqual('5');
- expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
- });
-
- it('should only change url when only ng-href', function() {
- element(by.model('value')).clear();
- element(by.model('value')).sendKeys('6');
- expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
-
- element(by.id('link-6')).click();
-
- // At this point, we navigate away from an Angular page, so we need
- // to use browser.driver to get the base webdriver.
- browser.wait(function() {
- return browser.driver.getCurrentUrl().then(function(url) {
- return url.match(/\/6$/);
- });
- }, 5000, 'page should navigate to /6');
- });
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngSrc
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrc` directive solves this problem.
- *
- * The buggy way to write it:
- * ```html
- * <img src="http://www.gravatar.com/avatar/{{hash}}"/>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
- * ```
- *
- * @element IMG
- * @param {template} ngSrc any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ngSrcset
- * @restrict A
- * @priority 99
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrcset` directive solves this problem.
- *
- * The buggy way to write it:
- * ```html
- * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
- * ```
- *
- * The correct way to write it:
- * ```html
- * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
- * ```
- *
- * @element IMG
- * @param {template} ngSrcset any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ngDisabled
- * @restrict A
- * @priority 100
- *
- * @description
- *
- * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
- * ```html
- * <div ng-init="scope = { isDisabled: false }">
- * <button disabled="{{scope.isDisabled}}">Disabled</button>
- * </div>
- * ```
- *
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as disabled. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngDisabled` directive solves this problem for the `disabled` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- *
- * @example
- <example>
- <file name="index.html">
- Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
- <button ng-model="button" ng-disabled="checked">Button</button>
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle button', function() {
- expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
- element(by.model('checked')).click();
- expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
- * then special attribute "disabled" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngChecked
- * @restrict A
- * @priority 100
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as checked. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngChecked` directive solves this problem for the `checked` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- * @example
- <example>
- <file name="index.html">
- Check me to check both: <input type="checkbox" ng-model="master"><br/>
- <input id="checkSlave" type="checkbox" ng-checked="master">
- </file>
- <file name="protractor.js" type="protractor">
- it('should check both checkBoxes', function() {
- expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
- element(by.model('master')).click();
- expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
- * then special attribute "checked" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngReadonly
- * @restrict A
- * @priority 100
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as readonly. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngReadonly` directive solves this problem for the `readonly` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- * @example
- <example>
- <file name="index.html">
- Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
- <input type="text" ng-readonly="checked" value="I'm Angular"/>
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle readonly attr', function() {
- expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
- element(by.model('checked')).click();
- expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element INPUT
- * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
- * then special attribute "readonly" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ngSelected
- * @restrict A
- * @priority 100
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as selected. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngSelected` directive solves this problem for the `selected` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- *
- * @example
- <example>
- <file name="index.html">
- Check me to select: <input type="checkbox" ng-model="selected"><br/>
- <select>
- <option>Hello!</option>
- <option id="greet" ng-selected="selected">Greetings!</option>
- </select>
- </file>
- <file name="protractor.js" type="protractor">
- it('should select Greetings!', function() {
- expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
- element(by.model('selected')).click();
- expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element OPTION
- * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
- * then special attribute "selected" will be set on the element
- */
-
-/**
- * @ngdoc directive
- * @name ngOpen
- * @restrict A
- * @priority 100
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as open. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngOpen` directive solves this problem for the `open` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- * @example
- <example>
- <file name="index.html">
- Check me check multiple: <input type="checkbox" ng-model="open"><br/>
- <details id="details" ng-open="open">
- <summary>Show/Hide me</summary>
- </details>
- </file>
- <file name="protractor.js" type="protractor">
- it('should toggle open', function() {
- expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
- element(by.model('open')).click();
- expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
- });
- </file>
- </example>
- *
- * @element DETAILS
- * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
- * then special attribute "open" will be set on the element
- */
-
-var ngAttributeAliasDirectives = {};
-
-
-// boolean attrs are evaluated
-forEach(BOOLEAN_ATTR, function(propName, attrName) {
- // binding to multiple is not supported
- if (propName == "multiple") return;
-
- var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- priority: 100,
- link: function(scope, element, attr) {
- scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
- attr.$set(attrName, !!value);
- });
- }
- };
- };
-});
-
-
-// ng-src, ng-srcset, ng-href are interpolated
-forEach(['src', 'srcset', 'href'], function(attrName) {
- var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- priority: 99, // it needs to run after the attributes are interpolated
- link: function(scope, element, attr) {
- var propName = attrName,
- name = attrName;
-
- if (attrName === 'href' &&
- toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
- name = 'xlinkHref';
- attr.$attr[name] = 'xlink:href';
- propName = null;
- }
-
- attr.$observe(normalized, function(value) {
- if (!value) {
- if (attrName === 'href') {
- attr.$set(name, null);
- }
- return;
- }
-
- attr.$set(name, value);
-
- // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
- // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
- // to set the property as well to achieve the desired effect.
- // we use attr[attrName] value since $set can sanitize the url.
- if (msie && propName) element.prop(propName, attr[name]);
- });
- }
- };
- };
-});
-
-/* global -nullFormCtrl */
-var nullFormCtrl = {
- $addControl: noop,
- $removeControl: noop,
- $setValidity: noop,
- $setDirty: noop,
- $setPristine: noop
-};
-
-/**
- * @ngdoc type
- * @name form.FormController
- *
- * @property {boolean} $pristine True if user has not interacted with the form yet.
- * @property {boolean} $dirty True if user has already interacted with the form.
- * @property {boolean} $valid True if all of the containing forms and controls are valid.
- * @property {boolean} $invalid True if at least one containing control or form is invalid.
- *
- * @property {Object} $error Is an object hash, containing references to all invalid controls or
- * forms, where:
- *
- * - keys are validation tokens (error names),
- * - values are arrays of controls or forms that are invalid for given error name.
- *
- *
- * Built-in validation tokens:
- *
- * - `email`
- * - `max`
- * - `maxlength`
- * - `min`
- * - `minlength`
- * - `number`
- * - `pattern`
- * - `required`
- * - `url`
- *
- * @description
- * `FormController` keeps track of all its controls and nested forms as well as the state of them,
- * such as being valid/invalid or dirty/pristine.
- *
- * Each {@link ng.directive:form form} directive creates an instance
- * of `FormController`.
- *
- */
-//asks for $scope to fool the BC controller module
-FormController.$inject = ['$element', '$attrs', '$scope', '$animate'];
-function FormController(element, attrs, $scope, $animate) {
- var form = this,
- parentForm = element.parent().controller('form') || nullFormCtrl,
- invalidCount = 0, // used to easily determine if we are valid
- errors = form.$error = {},
- controls = [];
-
- // init state
- form.$name = attrs.name || attrs.ngForm;
- form.$dirty = false;
- form.$pristine = true;
- form.$valid = true;
- form.$invalid = false;
-
- parentForm.$addControl(form);
-
- // Setup initial state of the control
- element.addClass(PRISTINE_CLASS);
- toggleValidCss(true);
-
- // convenience method for easy toggling of classes
- function toggleValidCss(isValid, validationErrorKey) {
- validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
- $animate.setClass(element,
- (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,
- (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
- }
-
- /**
- * @ngdoc method
- * @name form.FormController#$addControl
- *
- * @description
- * Register a control with the form.
- *
- * Input elements using ngModelController do this automatically when they are linked.
- */
- form.$addControl = function(control) {
- // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
- // and not added to the scope. Now we throw an error.
- assertNotHasOwnProperty(control.$name, 'input');
- controls.push(control);
-
- if (control.$name) {
- form[control.$name] = control;
- }
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$removeControl
- *
- * @description
- * Deregister a control from the form.
- *
- * Input elements using ngModelController do this automatically when they are destroyed.
- */
- form.$removeControl = function(control) {
- if (control.$name && form[control.$name] === control) {
- delete form[control.$name];
- }
- forEach(errors, function(queue, validationToken) {
- form.$setValidity(validationToken, true, control);
- });
-
- arrayRemove(controls, control);
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setValidity
- *
- * @description
- * Sets the validity of a form control.
- *
- * This method will also propagate to parent forms.
- */
- form.$setValidity = function(validationToken, isValid, control) {
- var queue = errors[validationToken];
-
- if (isValid) {
- if (queue) {
- arrayRemove(queue, control);
- if (!queue.length) {
- invalidCount--;
- if (!invalidCount) {
- toggleValidCss(isValid);
- form.$valid = true;
- form.$invalid = false;
- }
- errors[validationToken] = false;
- toggleValidCss(true, validationToken);
- parentForm.$setValidity(validationToken, true, form);
- }
- }
-
- } else {
- if (!invalidCount) {
- toggleValidCss(isValid);
- }
- if (queue) {
- if (includes(queue, control)) return;
- } else {
- errors[validationToken] = queue = [];
- invalidCount++;
- toggleValidCss(false, validationToken);
- parentForm.$setValidity(validationToken, false, form);
- }
- queue.push(control);
-
- form.$valid = false;
- form.$invalid = true;
- }
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setDirty
- *
- * @description
- * Sets the form to a dirty state.
- *
- * This method can be called to add the 'ng-dirty' class and set the form to a dirty
- * state (ng-dirty class). This method will also propagate to parent forms.
- */
- form.$setDirty = function() {
- $animate.removeClass(element, PRISTINE_CLASS);
- $animate.addClass(element, DIRTY_CLASS);
- form.$dirty = true;
- form.$pristine = false;
- parentForm.$setDirty();
- };
-
- /**
- * @ngdoc method
- * @name form.FormController#$setPristine
- *
- * @description
- * Sets the form to its pristine state.
- *
- * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
- * state (ng-pristine class). This method will also propagate to all the controls contained
- * in this form.
- *
- * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
- * saving or resetting it.
- */
- form.$setPristine = function () {
- $animate.removeClass(element, DIRTY_CLASS);
- $animate.addClass(element, PRISTINE_CLASS);
- form.$dirty = false;
- form.$pristine = true;
- forEach(controls, function(control) {
- control.$setPristine();
- });
- };
-}
-
-
-/**
- * @ngdoc directive
- * @name ngForm
- * @restrict EAC
- *
- * @description
- * Nestable alias of {@link ng.directive:form `form`} directive. HTML
- * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
- * sub-group of controls needs to be determined.
- *
- * Note: the purpose of `ngForm` is to group controls,
- * but not to be a replacement for the `<form>` tag with all of its capabilities
- * (e.g. posting to the server, ...).
- *
- * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
- * related scope, under this name.
- *
- */
-
- /**
- * @ngdoc directive
- * @name form
- * @restrict E
- *
- * @description
- * Directive that instantiates
- * {@link form.FormController FormController}.
- *
- * If the `name` attribute is specified, the form controller is published onto the current scope under
- * this name.
- *
- * # Alias: {@link ng.directive:ngForm `ngForm`}
- *
- * In Angular forms can be nested. This means that the outer form is valid when all of the child
- * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
- * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
- * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
- * using Angular validation directives in forms that are dynamically generated using the
- * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
- * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
- * `ngForm` directive and nest these in an outer `form` element.
- *
- *
- * # CSS classes
- * - `ng-valid` is set if the form is valid.
- * - `ng-invalid` is set if the form is invalid.
- * - `ng-pristine` is set if the form is pristine.
- * - `ng-dirty` is set if the form is dirty.
- *
- * Keep in mind that ngAnimate can detect each of these classes when added and removed.
- *
- *
- * # Submitting a form and preventing the default action
- *
- * Since the role of forms in client-side Angular applications is different than in classical
- * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
- * page reload that sends the data to the server. Instead some javascript logic should be triggered
- * to handle the form submission in an application-specific way.
- *
- * For this reason, Angular prevents the default action (form submission to the server) unless the
- * `<form>` element has an `action` attribute specified.
- *
- * You can use one of the following two ways to specify what javascript method should be called when
- * a form is submitted:
- *
- * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
- * - {@link ng.directive:ngClick ngClick} directive on the first
- * button or input field of type submit (input[type=submit])
- *
- * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
- * or {@link ng.directive:ngClick ngClick} directives.
- * This is because of the following form submission rules in the HTML specification:
- *
- * - If a form has only one input field then hitting enter in this field triggers form submit
- * (`ngSubmit`)
- * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
- * doesn't trigger submit
- * - if a form has one or more input fields and one or more buttons or input[type=submit] then
- * hitting enter in any of the input fields will trigger the click handler on the *first* button or
- * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
- *
- *
- * ## Animation Hooks
- *
- * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
- * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
- * other validations that are performed within the form. Animations in ngForm are similar to how
- * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
- * as JS animations.
- *
- * The following example shows a simple way to utilize CSS transitions to style a form element
- * that has been rendered as invalid after it has been validated:
- *
- * <pre>
- * //be sure to include ngAnimate as a module to hook into more
- * //advanced animations
- * .my-form {
- * transition:0.5s linear all;
- * background: white;
- * }
- * .my-form.ng-invalid {
- * background: red;
- * color:white;
- * }
- * </pre>
- *
- * @example
- <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
- <file name="index.html">
- <script>
- angular.module('formExample', [])
- .controller('FormController', ['$scope', function($scope) {
- $scope.userType = 'guest';
- }]);
- </script>
- <style>
- .my-form {
- -webkit-transition:all linear 0.5s;
- transition:all linear 0.5s;
- background: transparent;
- }
- .my-form.ng-invalid {
- background: red;
- }
- </style>
- <form name="myForm" ng-controller="FormController" class="my-form">
- userType: <input name="input" ng-model="userType" required>
- <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
- <tt>userType = {{userType}}</tt><br>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should initialize to model', function() {
- var userType = element(by.binding('userType'));
- var valid = element(by.binding('myForm.input.$valid'));
-
- expect(userType.getText()).toContain('guest');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- var userType = element(by.binding('userType'));
- var valid = element(by.binding('myForm.input.$valid'));
- var userInput = element(by.model('userType'));
-
- userInput.clear();
- userInput.sendKeys('');
-
- expect(userType.getText()).toEqual('userType =');
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- *
- * @param {string=} name Name of the form. If specified, the form controller will be published into
- * related scope, under this name.
- */
-var formDirectiveFactory = function(isNgForm) {
- return ['$timeout', function($timeout) {
- var formDirective = {
- name: 'form',
- restrict: isNgForm ? 'EAC' : 'E',
- controller: FormController,
- compile: function() {
- return {
- pre: function(scope, formElement, attr, controller) {
- if (!attr.action) {
- // we can't use jq events because if a form is destroyed during submission the default
- // action is not prevented. see #1238
- //
- // IE 9 is not affected because it doesn't fire a submit event and try to do a full
- // page reload if the form was destroyed by submission of the form via a click handler
- // on a button in the form. Looks like an IE9 specific bug.
- var preventDefaultListener = function(event) {
- event.preventDefault
- ? event.preventDefault()
- : event.returnValue = false; // IE
- };
-
- addEventListenerFn(formElement[0], 'submit', preventDefaultListener);
-
- // unregister the preventDefault listener so that we don't not leak memory but in a
- // way that will achieve the prevention of the default action.
- formElement.on('$destroy', function() {
- $timeout(function() {
- removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
- }, 0, false);
- });
- }
-
- var parentFormCtrl = formElement.parent().controller('form'),
- alias = attr.name || attr.ngForm;
-
- if (alias) {
- setter(scope, alias, controller, alias);
- }
- if (parentFormCtrl) {
- formElement.on('$destroy', function() {
- parentFormCtrl.$removeControl(controller);
- if (alias) {
- setter(scope, alias, undefined, alias);
- }
- extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
- });
- }
- }
- };
- }
- };
-
- return formDirective;
- }];
-};
-
-var formDirective = formDirectiveFactory();
-var ngFormDirective = formDirectiveFactory(true);
-
-/* global VALID_CLASS: true,
- INVALID_CLASS: true,
- PRISTINE_CLASS: true,
- DIRTY_CLASS: true
-*/
-
-var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
-var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
-var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
-
-var inputType = {
-
- /**
- * @ngdoc input
- * @name input[text]
- *
- * @description
- * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
- *
- * *NOTE* Not every feature offered is available for all input types.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Adds `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- * This parameter is ignored for input[type=password] controls, which will never trim the
- * input.
- *
- * @example
- <example name="text-input-directive" module="textInputExample">
- <file name="index.html">
- <script>
- angular.module('textInputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.text = 'guest';
- $scope.word = /^\s*\w*\s*$/;
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- Single word: <input type="text" name="input" ng-model="text"
- ng-pattern="word" required ng-trim="false">
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.pattern">
- Single word only!</span>
-
- <tt>text = {{text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('guest');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
-
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if multi word', function() {
- input.clear();
- input.sendKeys('hello world');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'text': textInputType,
-
-
- /**
- * @ngdoc input
- * @name input[number]
- *
- * @description
- * Text input with number validation and transformation. Sets the `number` validation
- * error if not a valid number.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="number-input-directive" module="numberExample">
- <file name="index.html">
- <script>
- angular.module('numberExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.value = 12;
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- Number: <input type="number" name="input" ng-model="value"
- min="0" max="99" required>
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.number">
- Not valid number!</span>
- <tt>value = {{value}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var value = element(by.binding('value'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('value'));
-
- it('should initialize to model', function() {
- expect(value.getText()).toContain('12');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if over max', function() {
- input.clear();
- input.sendKeys('123');
- expect(value.getText()).toEqual('value =');
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'number': numberInputType,
-
-
- /**
- * @ngdoc input
- * @name input[url]
- *
- * @description
- * Text input with URL validation. Sets the `url` validation error key if the content is not a
- * valid URL.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="url-input-directive" module="urlExample">
- <file name="index.html">
- <script>
- angular.module('urlExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.text = 'http://google.com';
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- URL: <input type="url" name="input" ng-model="text" required>
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.url">
- Not valid url!</span>
- <tt>text = {{text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('http://google.com');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
-
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if not url', function() {
- input.clear();
- input.sendKeys('box');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'url': urlInputType,
-
-
- /**
- * @ngdoc input
- * @name input[email]
- *
- * @description
- * Text input with email validation. Sets the `email` validation error key if not a valid email
- * address.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="email-input-directive" module="emailExample">
- <file name="index.html">
- <script>
- angular.module('emailExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.text = 'me@example.com';
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- Email: <input type="email" name="input" ng-model="text" required>
- <span class="error" ng-show="myForm.input.$error.required">
- Required!</span>
- <span class="error" ng-show="myForm.input.$error.email">
- Not valid email!</span>
- <tt>text = {{text}}</tt><br/>
- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var text = element(by.binding('text'));
- var valid = element(by.binding('myForm.input.$valid'));
- var input = element(by.model('text'));
-
- it('should initialize to model', function() {
- expect(text.getText()).toContain('me@example.com');
- expect(valid.getText()).toContain('true');
- });
-
- it('should be invalid if empty', function() {
- input.clear();
- input.sendKeys('');
- expect(text.getText()).toEqual('text =');
- expect(valid.getText()).toContain('false');
- });
-
- it('should be invalid if not email', function() {
- input.clear();
- input.sendKeys('xxx');
-
- expect(valid.getText()).toContain('false');
- });
- </file>
- </example>
- */
- 'email': emailInputType,
-
-
- /**
- * @ngdoc input
- * @name input[radio]
- *
- * @description
- * HTML radio button.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string} value The value to which the expression should be set when selected.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {string} ngValue Angular expression which sets the value to which the expression should
- * be set when selected.
- *
- * @example
- <example name="radio-input-directive" module="radioExample">
- <file name="index.html">
- <script>
- angular.module('radioExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.color = 'blue';
- $scope.specialValue = {
- "id": "12345",
- "value": "green"
- };
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- <input type="radio" ng-model="color" value="red"> Red <br/>
- <input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
- <input type="radio" ng-model="color" value="blue"> Blue <br/>
- <tt>color = {{color | json}}</tt><br/>
- </form>
- Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
- </file>
- <file name="protractor.js" type="protractor">
- it('should change state', function() {
- var color = element(by.binding('color'));
-
- expect(color.getText()).toContain('blue');
-
- element.all(by.model('color')).get(0).click();
-
- expect(color.getText()).toContain('red');
- });
- </file>
- </example>
- */
- 'radio': radioInputType,
-
-
- /**
- * @ngdoc input
- * @name input[checkbox]
- *
- * @description
- * HTML checkbox.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} ngTrueValue The value to which the expression should be set when selected.
- * @param {string=} ngFalseValue The value to which the expression should be set when not selected.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <example name="checkbox-input-directive" module="checkboxExample">
- <file name="index.html">
- <script>
- angular.module('checkboxExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.value1 = true;
- $scope.value2 = 'YES'
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- Value1: <input type="checkbox" ng-model="value1"> <br/>
- Value2: <input type="checkbox" ng-model="value2"
- ng-true-value="YES" ng-false-value="NO"> <br/>
- <tt>value1 = {{value1}}</tt><br/>
- <tt>value2 = {{value2}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should change state', function() {
- var value1 = element(by.binding('value1'));
- var value2 = element(by.binding('value2'));
-
- expect(value1.getText()).toContain('true');
- expect(value2.getText()).toContain('YES');
-
- element(by.model('value1')).click();
- element(by.model('value2')).click();
-
- expect(value1.getText()).toContain('false');
- expect(value2.getText()).toContain('NO');
- });
- </file>
- </example>
- */
- 'checkbox': checkboxInputType,
-
- 'hidden': noop,
- 'button': noop,
- 'submit': noop,
- 'reset': noop,
- 'file': noop
-};
-
-// A helper function to call $setValidity and return the value / undefined,
-// a pattern that is repeated a lot in the input validation logic.
-function validate(ctrl, validatorName, validity, value){
- ctrl.$setValidity(validatorName, validity);
- return validity ? value : undefined;
-}
-
-function testFlags(validity, flags) {
- var i, flag;
- if (flags) {
- for (i=0; i<flags.length; ++i) {
- flag = flags[i];
- if (validity[flag]) {
- return true;
- }
- }
- }
- return false;
-}
-
-// Pass validity so that behaviour can be mocked easier.
-function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
- if (isObject(validity)) {
- ctrl.$$hasNativeValidators = true;
- var validator = function(value) {
- // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can
- // perform the required validation)
- if (!ctrl.$error[validatorName] &&
- !testFlags(validity, ignoreFlags) &&
- testFlags(validity, badFlags)) {
- ctrl.$setValidity(validatorName, false);
- return;
- }
- return value;
- };
- ctrl.$parsers.push(validator);
- }
-}
-
-function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- var validity = element.prop(VALIDITY_STATE_PROPERTY);
- var placeholder = element[0].placeholder, noevent = {};
- var type = lowercase(element[0].type);
- ctrl.$$validityState = validity;
-
- // In composition mode, users are still inputing intermediate text buffer,
- // hold the listener until composition is done.
- // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
- if (!$sniffer.android) {
- var composing = false;
-
- element.on('compositionstart', function(data) {
- composing = true;
- });
-
- element.on('compositionend', function() {
- composing = false;
- listener();
- });
- }
-
- var listener = function(ev) {
- if (composing) return;
- var value = element.val();
-
- // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
- // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
- // IE also sends input events for other non-input-related things, (such as focusing on a
- // form control), so this change is not entirely enough to solve this.
- if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
- placeholder = element[0].placeholder;
- return;
- }
-
- // By default we will trim the value
- // If the attribute ng-trim exists we will avoid trimming
- // If input type is 'password', the value is never trimmed
- if (type !== 'password' && (toBoolean(attr.ngTrim || 'T'))) {
- value = trim(value);
- }
-
- // If a control is suffering from bad input, browsers discard its value, so it may be
- // necessary to revalidate even if the control's value is the same empty value twice in
- // a row.
- var revalidate = validity && ctrl.$$hasNativeValidators;
- if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
- if (scope.$root.$$phase) {
- ctrl.$setViewValue(value);
- } else {
- scope.$apply(function() {
- ctrl.$setViewValue(value);
- });
- }
- }
- };
-
- // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
- // input event on backspace, delete or cut
- if ($sniffer.hasEvent('input')) {
- element.on('input', listener);
- } else {
- var timeout;
-
- var deferListener = function() {
- if (!timeout) {
- timeout = $browser.defer(function() {
- listener();
- timeout = null;
- });
- }
- };
-
- element.on('keydown', function(event) {
- var key = event.keyCode;
-
- // ignore
- // command modifiers arrows
- if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
-
- deferListener();
- });
-
- // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
- if ($sniffer.hasEvent('paste')) {
- element.on('paste cut', deferListener);
- }
- }
-
- // if user paste into input using mouse on older browser
- // or form autocomplete on newer browser, we need "change" event to catch it
- element.on('change', listener);
-
- ctrl.$render = function() {
- element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
- };
-
- // pattern validator
- var pattern = attr.ngPattern,
- patternValidator,
- match;
-
- if (pattern) {
- var validateRegex = function(regexp, value) {
- return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value);
- };
- match = pattern.match(/^\/(.*)\/([gim]*)$/);
- if (match) {
- pattern = new RegExp(match[1], match[2]);
- patternValidator = function(value) {
- return validateRegex(pattern, value);
- };
- } else {
- patternValidator = function(value) {
- var patternObj = scope.$eval(pattern);
-
- if (!patternObj || !patternObj.test) {
- throw minErr('ngPattern')('noregexp',
- 'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,
- patternObj, startingTag(element));
- }
- return validateRegex(patternObj, value);
- };
- }
-
- ctrl.$formatters.push(patternValidator);
- ctrl.$parsers.push(patternValidator);
- }
-
- // min length validator
- if (attr.ngMinlength) {
- var minlength = int(attr.ngMinlength);
- var minLengthValidator = function(value) {
- return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value);
- };
-
- ctrl.$parsers.push(minLengthValidator);
- ctrl.$formatters.push(minLengthValidator);
- }
-
- // max length validator
- if (attr.ngMaxlength) {
- var maxlength = int(attr.ngMaxlength);
- var maxLengthValidator = function(value) {
- return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value);
- };
-
- ctrl.$parsers.push(maxLengthValidator);
- ctrl.$formatters.push(maxLengthValidator);
- }
-}
-
-var numberBadFlags = ['badInput'];
-
-function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
- ctrl.$parsers.push(function(value) {
- var empty = ctrl.$isEmpty(value);
- if (empty || NUMBER_REGEXP.test(value)) {
- ctrl.$setValidity('number', true);
- return value === '' ? null : (empty ? value : parseFloat(value));
- } else {
- ctrl.$setValidity('number', false);
- return undefined;
- }
- });
-
- addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
-
- ctrl.$formatters.push(function(value) {
- return ctrl.$isEmpty(value) ? '' : '' + value;
- });
-
- if (attr.min) {
- var minValidator = function(value) {
- var min = parseFloat(attr.min);
- return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);
- };
-
- ctrl.$parsers.push(minValidator);
- ctrl.$formatters.push(minValidator);
- }
-
- if (attr.max) {
- var maxValidator = function(value) {
- var max = parseFloat(attr.max);
- return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value);
- };
-
- ctrl.$parsers.push(maxValidator);
- ctrl.$formatters.push(maxValidator);
- }
-
- ctrl.$formatters.push(function(value) {
- return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value);
- });
-}
-
-function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
- var urlValidator = function(value) {
- return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
- };
-
- ctrl.$formatters.push(urlValidator);
- ctrl.$parsers.push(urlValidator);
-}
-
-function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
- var emailValidator = function(value) {
- return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
- };
-
- ctrl.$formatters.push(emailValidator);
- ctrl.$parsers.push(emailValidator);
-}
-
-function radioInputType(scope, element, attr, ctrl) {
- // make the name unique, if not defined
- if (isUndefined(attr.name)) {
- element.attr('name', nextUid());
- }
-
- element.on('click', function() {
- if (element[0].checked) {
- scope.$apply(function() {
- ctrl.$setViewValue(attr.value);
- });
- }
- });
-
- ctrl.$render = function() {
- var value = attr.value;
- element[0].checked = (value == ctrl.$viewValue);
- };
-
- attr.$observe('value', ctrl.$render);
-}
-
-function checkboxInputType(scope, element, attr, ctrl) {
- var trueValue = attr.ngTrueValue,
- falseValue = attr.ngFalseValue;
-
- if (!isString(trueValue)) trueValue = true;
- if (!isString(falseValue)) falseValue = false;
-
- element.on('click', function() {
- scope.$apply(function() {
- ctrl.$setViewValue(element[0].checked);
- });
- });
-
- ctrl.$render = function() {
- element[0].checked = ctrl.$viewValue;
- };
-
- // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox.
- ctrl.$isEmpty = function(value) {
- return value !== trueValue;
- };
-
- ctrl.$formatters.push(function(value) {
- return value === trueValue;
- });
-
- ctrl.$parsers.push(function(value) {
- return value ? trueValue : falseValue;
- });
-}
-
-
-/**
- * @ngdoc directive
- * @name textarea
- * @restrict E
- *
- * @description
- * HTML textarea element control with angular data-binding. The data-binding and validation
- * properties of this element are exactly the same as those of the
- * {@link ng.directive:input input element}.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- */
-
-
-/**
- * @ngdoc directive
- * @name input
- * @restrict E
- *
- * @description
- * HTML input element control with angular data-binding. Input control follows HTML5 input types
- * and polyfills the HTML5 validation behavior for older browsers.
- *
- * *NOTE* Not every feature offered is available for all input types.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {boolean=} ngRequired Sets `required` attribute if set to true
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- * interaction with the input element.
- * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
- * This parameter is ignored for input[type=password] controls, which will never trim the
- * input.
- *
- * @example
- <example name="input-directive" module="inputExample">
- <file name="index.html">
- <script>
- angular.module('inputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = {name: 'guest', last: 'visitor'};
- }]);
- </script>
- <div ng-controller="ExampleController">
- <form name="myForm">
- User name: <input type="text" name="userName" ng-model="user.name" required>
- <span class="error" ng-show="myForm.userName.$error.required">
- Required!</span><br>
- Last name: <input type="text" name="lastName" ng-model="user.last"
- ng-minlength="3" ng-maxlength="10">
- <span class="error" ng-show="myForm.lastName.$error.minlength">
- Too short!</span>
- <span class="error" ng-show="myForm.lastName.$error.maxlength">
- Too long!</span><br>
- </form>
- <hr>
- <tt>user = {{user}}</tt><br/>
- <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
- <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
- <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
- <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
- <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
- <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- var user = element(by.binding('{{user}}'));
- var userNameValid = element(by.binding('myForm.userName.$valid'));
- var lastNameValid = element(by.binding('myForm.lastName.$valid'));
- var lastNameError = element(by.binding('myForm.lastName.$error'));
- var formValid = element(by.binding('myForm.$valid'));
- var userNameInput = element(by.model('user.name'));
- var userLastInput = element(by.model('user.last'));
-
- it('should initialize to model', function() {
- expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
- expect(userNameValid.getText()).toContain('true');
- expect(formValid.getText()).toContain('true');
- });
-
- it('should be invalid if empty when required', function() {
- userNameInput.clear();
- userNameInput.sendKeys('');
-
- expect(user.getText()).toContain('{"last":"visitor"}');
- expect(userNameValid.getText()).toContain('false');
- expect(formValid.getText()).toContain('false');
- });
-
- it('should be valid if empty when min length is set', function() {
- userLastInput.clear();
- userLastInput.sendKeys('');
-
- expect(user.getText()).toContain('{"name":"guest","last":""}');
- expect(lastNameValid.getText()).toContain('true');
- expect(formValid.getText()).toContain('true');
- });
-
- it('should be invalid if less than required min length', function() {
- userLastInput.clear();
- userLastInput.sendKeys('xx');
-
- expect(user.getText()).toContain('{"name":"guest"}');
- expect(lastNameValid.getText()).toContain('false');
- expect(lastNameError.getText()).toContain('minlength');
- expect(formValid.getText()).toContain('false');
- });
-
- it('should be invalid if longer than max length', function() {
- userLastInput.clear();
- userLastInput.sendKeys('some ridiculously long name');
-
- expect(user.getText()).toContain('{"name":"guest"}');
- expect(lastNameValid.getText()).toContain('false');
- expect(lastNameError.getText()).toContain('maxlength');
- expect(formValid.getText()).toContain('false');
- });
- </file>
- </example>
- */
-var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
- return {
- restrict: 'E',
- require: '?ngModel',
- link: function(scope, element, attr, ctrl) {
- if (ctrl) {
- (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,
- $browser);
- }
- }
- };
-}];
-
-var VALID_CLASS = 'ng-valid',
- INVALID_CLASS = 'ng-invalid',
- PRISTINE_CLASS = 'ng-pristine',
- DIRTY_CLASS = 'ng-dirty';
-
-/**
- * @ngdoc type
- * @name ngModel.NgModelController
- *
- * @property {string} $viewValue Actual string value in the view.
- * @property {*} $modelValue The value in the model, that the control is bound to.
- * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
- the control reads value from the DOM. Each function is called, in turn, passing the value
- through to the next. The last return value is used to populate the model.
- Used to sanitize / convert the value as well as validation. For validation,
- the parsers should update the validity state using
- {@link ngModel.NgModelController#$setValidity $setValidity()},
- and return `undefined` for invalid values.
-
- *
- * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
- the model value changes. Each function is called, in turn, passing the value through to the
- next. Used to format / convert values for display in the control and validation.
- * ```js
- * function formatter(value) {
- * if (value) {
- * return value.toUpperCase();
- * }
- * }
- * ngModel.$formatters.push(formatter);
- * ```
- *
- * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
- * view value has changed. It is called with no arguments, and its return value is ignored.
- * This can be used in place of additional $watches against the model value.
- *
- * @property {Object} $error An object hash with all errors as keys.
- *
- * @property {boolean} $pristine True if user has not interacted with the control yet.
- * @property {boolean} $dirty True if user has already interacted with the control.
- * @property {boolean} $valid True if there is no error.
- * @property {boolean} $invalid True if at least one error on the control.
- *
- * @description
- *
- * `NgModelController` provides API for the `ng-model` directive. The controller contains
- * services for data-binding, validation, CSS updates, and value formatting and parsing. It
- * purposefully does not contain any logic which deals with DOM rendering or listening to
- * DOM events. Such DOM related logic should be provided by other directives which make use of
- * `NgModelController` for data-binding.
- *
- * ## Custom Control Example
- * This example shows how to use `NgModelController` with a custom control to achieve
- * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
- * collaborate together to achieve the desired result.
- *
- * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
- * contents be edited in place by the user. This will not work on older browsers.
- *
- * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
- * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
- * However, as we are using `$sce` the model can still decide to to provide unsafe content if it marks
- * that content using the `$sce` service.
- *
- * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
- <file name="style.css">
- [contenteditable] {
- border: 1px solid black;
- background-color: white;
- min-height: 20px;
- }
-
- .ng-invalid {
- border: 1px solid red;
- }
-
- </file>
- <file name="script.js">
- angular.module('customControl', ['ngSanitize']).
- directive('contenteditable', ['$sce', function($sce) {
- return {
- restrict: 'A', // only activate on element attribute
- require: '?ngModel', // get a hold of NgModelController
- link: function(scope, element, attrs, ngModel) {
- if(!ngModel) return; // do nothing if no ng-model
-
- // Specify how UI should be updated
- ngModel.$render = function() {
- element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
- };
-
- // Listen for change events to enable binding
- element.on('blur keyup change', function() {
- scope.$apply(read);
- });
- read(); // initialize
-
- // Write data to the model
- function read() {
- var html = element.html();
- // When we clear the content editable the browser leaves a <br> behind
- // If strip-br attribute is provided then we strip this out
- if( attrs.stripBr && html == '<br>' ) {
- html = '';
- }
- ngModel.$setViewValue(html);
- }
- }
- };
- }]);
- </file>
- <file name="index.html">
- <form name="myForm">
- <div contenteditable
- name="myWidget" ng-model="userContent"
- strip-br="true"
- required>Change me!</div>
- <span ng-show="myForm.myWidget.$error.required">Required!</span>
- <hr>
- <textarea ng-model="userContent"></textarea>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should data-bind and become invalid', function() {
- if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
- // SafariDriver can't handle contenteditable
- // and Firefox driver can't clear contenteditables very well
- return;
- }
- var contentEditable = element(by.css('[contenteditable]'));
- var content = 'Change me!';
-
- expect(contentEditable.getText()).toEqual(content);
-
- contentEditable.clear();
- contentEditable.sendKeys(protractor.Key.BACK_SPACE);
- expect(contentEditable.getText()).toEqual('');
- expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
- });
- </file>
- * </example>
- *
- *
- */
-var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate',
- function($scope, $exceptionHandler, $attr, $element, $parse, $animate) {
- this.$viewValue = Number.NaN;
- this.$modelValue = Number.NaN;
- this.$parsers = [];
- this.$formatters = [];
- this.$viewChangeListeners = [];
- this.$pristine = true;
- this.$dirty = false;
- this.$valid = true;
- this.$invalid = false;
- this.$name = $attr.name;
-
- var ngModelGet = $parse($attr.ngModel),
- ngModelSet = ngModelGet.assign;
-
- if (!ngModelSet) {
- throw minErr('ngModel')('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
- $attr.ngModel, startingTag($element));
- }
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$render
- *
- * @description
- * Called when the view needs to be updated. It is expected that the user of the ng-model
- * directive will implement this method.
- */
- this.$render = noop;
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$isEmpty
- *
- * @description
- * This is called when we need to determine if the value of the input is empty.
- *
- * For instance, the required directive does this to work out if the input has data or not.
- * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
- *
- * You can override this for input directives whose concept of being empty is different to the
- * default. The `checkboxInputType` directive does this because in its case a value of `false`
- * implies empty.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is empty.
- */
- this.$isEmpty = function(value) {
- return isUndefined(value) || value === '' || value === null || value !== value;
- };
-
- var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
- invalidCount = 0, // used to easily determine if we are valid
- $error = this.$error = {}; // keep invalid keys here
-
-
- // Setup initial state of the control
- $element.addClass(PRISTINE_CLASS);
- toggleValidCss(true);
-
- // convenience method for easy toggling of classes
- function toggleValidCss(isValid, validationErrorKey) {
- validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
- $animate.removeClass($element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
- $animate.addClass($element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
- }
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setValidity
- *
- * @description
- * Change the validity state, and notifies the form when the control changes validity. (i.e. it
- * does not notify form if given validator is already marked as invalid).
- *
- * This method should be called by validators - i.e. the parser or formatter functions.
- *
- * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
- * to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.
- * The `validationErrorKey` should be in camelCase and will get converted into dash-case
- * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
- * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
- * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).
- */
- this.$setValidity = function(validationErrorKey, isValid) {
- // Purposeful use of ! here to cast isValid to boolean in case it is undefined
- // jshint -W018
- if ($error[validationErrorKey] === !isValid) return;
- // jshint +W018
-
- if (isValid) {
- if ($error[validationErrorKey]) invalidCount--;
- if (!invalidCount) {
- toggleValidCss(true);
- this.$valid = true;
- this.$invalid = false;
- }
- } else {
- toggleValidCss(false);
- this.$invalid = true;
- this.$valid = false;
- invalidCount++;
- }
-
- $error[validationErrorKey] = !isValid;
- toggleValidCss(isValid, validationErrorKey);
-
- parentForm.$setValidity(validationErrorKey, isValid, this);
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setPristine
- *
- * @description
- * Sets the control to its pristine state.
- *
- * This method can be called to remove the 'ng-dirty' class and set the control to its pristine
- * state (ng-pristine class).
- */
- this.$setPristine = function () {
- this.$dirty = false;
- this.$pristine = true;
- $animate.removeClass($element, DIRTY_CLASS);
- $animate.addClass($element, PRISTINE_CLASS);
- };
-
- /**
- * @ngdoc method
- * @name ngModel.NgModelController#$setViewValue
- *
- * @description
- * Update the view value.
- *
- * This method should be called when the view value changes, typically from within a DOM event handler.
- * For example {@link ng.directive:input input} and
- * {@link ng.directive:select select} directives call it.
- *
- * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
- * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
- * `$modelValue` and the **expression** specified in the `ng-model` attribute.
- *
- * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
- *
- * Note that calling this function does not trigger a `$digest`.
- *
- * @param {string} value Value from the view.
- */
- this.$setViewValue = function(value) {
- this.$viewValue = value;
-
- // change to dirty
- if (this.$pristine) {
- this.$dirty = true;
- this.$pristine = false;
- $animate.removeClass($element, PRISTINE_CLASS);
- $animate.addClass($element, DIRTY_CLASS);
- parentForm.$setDirty();
- }
-
- forEach(this.$parsers, function(fn) {
- value = fn(value);
- });
-
- if (this.$modelValue !== value) {
- this.$modelValue = value;
- ngModelSet($scope, value);
- forEach(this.$viewChangeListeners, function(listener) {
- try {
- listener();
- } catch(e) {
- $exceptionHandler(e);
- }
- });
- }
- };
-
- // model -> value
- var ctrl = this;
-
- $scope.$watch(function ngModelWatch() {
- var value = ngModelGet($scope);
-
- // if scope model value and ngModel value are out of sync
- if (ctrl.$modelValue !== value) {
-
- var formatters = ctrl.$formatters,
- idx = formatters.length;
-
- ctrl.$modelValue = value;
- while(idx--) {
- value = formatters[idx](value);
- }
-
- if (ctrl.$viewValue !== value) {
- ctrl.$viewValue = value;
- ctrl.$render();
- }
- }
-
- return value;
- });
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngModel
- *
- * @element input
- *
- * @description
- * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
- * property on the scope using {@link ngModel.NgModelController NgModelController},
- * which is created and exposed by this directive.
- *
- * `ngModel` is responsible for:
- *
- * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
- * require.
- * - Providing validation behavior (i.e. required, number, email, url).
- * - Keeping the state of the control (valid/invalid, dirty/pristine, validation errors).
- * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`) including animations.
- * - Registering the control with its parent {@link ng.directive:form form}.
- *
- * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
- * current scope. If the property doesn't already exist on this scope, it will be created
- * implicitly and added to the scope.
- *
- * For best practices on using `ngModel`, see:
- *
- * - [https://github.com/angular/angular.js/wiki/Understanding-Scopes]
- *
- * For basic examples, how to use `ngModel`, see:
- *
- * - {@link ng.directive:input input}
- * - {@link input[text] text}
- * - {@link input[checkbox] checkbox}
- * - {@link input[radio] radio}
- * - {@link input[number] number}
- * - {@link input[email] email}
- * - {@link input[url] url}
- * - {@link ng.directive:select select}
- * - {@link ng.directive:textarea textarea}
- *
- * # CSS classes
- * The following CSS classes are added and removed on the associated input/select/textarea element
- * depending on the validity of the model.
- *
- * - `ng-valid` is set if the model is valid.
- * - `ng-invalid` is set if the model is invalid.
- * - `ng-pristine` is set if the model is pristine.
- * - `ng-dirty` is set if the model is dirty.
- *
- * Keep in mind that ngAnimate can detect each of these classes when added and removed.
- *
- * ## Animation Hooks
- *
- * Animations within models are triggered when any of the associated CSS classes are added and removed
- * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
- * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
- * The animations that are triggered within ngModel are similar to how they work in ngClass and
- * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
- *
- * The following example shows a simple way to utilize CSS transitions to style an input element
- * that has been rendered as invalid after it has been validated:
- *
- * <pre>
- * //be sure to include ngAnimate as a module to hook into more
- * //advanced animations
- * .my-input {
- * transition:0.5s linear all;
- * background: white;
- * }
- * .my-input.ng-invalid {
- * background: red;
- * color:white;
- * }
- * </pre>
- *
- * @example
- * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
- <file name="index.html">
- <script>
- angular.module('inputExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.val = '1';
- }]);
- </script>
- <style>
- .my-input {
- -webkit-transition:all linear 0.5s;
- transition:all linear 0.5s;
- background: transparent;
- }
- .my-input.ng-invalid {
- color:white;
- background: red;
- }
- </style>
- Update input to see transitions when valid/invalid.
- Integer is a valid value.
- <form name="testForm" ng-controller="ExampleController">
- <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
- </form>
- </file>
- * </example>
- */
-var ngModelDirective = function() {
- return {
- require: ['ngModel', '^?form'],
- controller: NgModelController,
- link: function(scope, element, attr, ctrls) {
- // notify others, especially parent forms
-
- var modelCtrl = ctrls[0],
- formCtrl = ctrls[1] || nullFormCtrl;
-
- formCtrl.$addControl(modelCtrl);
-
- scope.$on('$destroy', function() {
- formCtrl.$removeControl(modelCtrl);
- });
- }
- };
-};
-
-
-/**
- * @ngdoc directive
- * @name ngChange
- *
- * @description
- * Evaluate the given expression when the user changes the input.
- * The expression is evaluated immediately, unlike the JavaScript onchange event
- * which only triggers at the end of a change (usually, when the user leaves the
- * form element or presses the return key).
- * The expression is not evaluated when the value change is coming from the model.
- *
- * Note, this directive requires `ngModel` to be present.
- *
- * @element input
- * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
- * in input value.
- *
- * @example
- * <example name="ngChange-directive" module="changeExample">
- * <file name="index.html">
- * <script>
- * angular.module('changeExample', [])
- * .controller('ExampleController', ['$scope', function($scope) {
- * $scope.counter = 0;
- * $scope.change = function() {
- * $scope.counter++;
- * };
- * }]);
- * </script>
- * <div ng-controller="ExampleController">
- * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
- * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
- * <label for="ng-change-example2">Confirmed</label><br />
- * <tt>debug = {{confirmed}}</tt><br/>
- * <tt>counter = {{counter}}</tt><br/>
- * </div>
- * </file>
- * <file name="protractor.js" type="protractor">
- * var counter = element(by.binding('counter'));
- * var debug = element(by.binding('confirmed'));
- *
- * it('should evaluate the expression if changing from view', function() {
- * expect(counter.getText()).toContain('0');
- *
- * element(by.id('ng-change-example1')).click();
- *
- * expect(counter.getText()).toContain('1');
- * expect(debug.getText()).toContain('true');
- * });
- *
- * it('should not evaluate the expression if changing from model', function() {
- * element(by.id('ng-change-example2')).click();
-
- * expect(counter.getText()).toContain('0');
- * expect(debug.getText()).toContain('true');
- * });
- * </file>
- * </example>
- */
-var ngChangeDirective = valueFn({
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- ctrl.$viewChangeListeners.push(function() {
- scope.$eval(attr.ngChange);
- });
- }
-});
-
-
-var requiredDirective = function() {
- return {
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
- attr.required = true; // force truthy in case we are on non input element
-
- var validator = function(value) {
- if (attr.required && ctrl.$isEmpty(value)) {
- ctrl.$setValidity('required', false);
- return;
- } else {
- ctrl.$setValidity('required', true);
- return value;
- }
- };
-
- ctrl.$formatters.push(validator);
- ctrl.$parsers.unshift(validator);
-
- attr.$observe('required', function() {
- validator(ctrl.$viewValue);
- });
- }
- };
-};
-
-
-/**
- * @ngdoc directive
- * @name ngList
- *
- * @description
- * Text input that converts between a delimited string and an array of strings. The delimiter
- * can be a fixed string (by default a comma) or a regular expression.
- *
- * @element input
- * @param {string=} ngList optional delimiter that should be used to split the value. If
- * specified in form `/something/` then the value will be converted into a regular expression.
- *
- * @example
- <example name="ngList-directive" module="listExample">
- <file name="index.html">
- <script>
- angular.module('listExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.names = ['igor', 'misko', 'vojta'];
- }]);
- </script>
- <form name="myForm" ng-controller="ExampleController">
- List: <input name="namesInput" ng-model="names" ng-list required>
- <span class="error" ng-show="myForm.namesInput.$error.required">
- Required!</span>
- <br>
- <tt>names = {{names}}</tt><br/>
- <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
- <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
- <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var listInput = element(by.model('names'));
- var names = element(by.binding('{{names}}'));
- var valid = element(by.binding('myForm.namesInput.$valid'));
- var error = element(by.css('span.error'));
-
- it('should initialize to model', function() {
- expect(names.getText()).toContain('["igor","misko","vojta"]');
- expect(valid.getText()).toContain('true');
- expect(error.getCssValue('display')).toBe('none');
- });
-
- it('should be invalid if empty', function() {
- listInput.clear();
- listInput.sendKeys('');
-
- expect(names.getText()).toContain('');
- expect(valid.getText()).toContain('false');
- expect(error.getCssValue('display')).not.toBe('none'); });
- </file>
- </example>
- */
-var ngListDirective = function() {
- return {
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- var match = /\/(.*)\//.exec(attr.ngList),
- separator = match && new RegExp(match[1]) || attr.ngList || ',';
-
- var parse = function(viewValue) {
- // If the viewValue is invalid (say required but empty) it will be `undefined`
- if (isUndefined(viewValue)) return;
-
- var list = [];
-
- if (viewValue) {
- forEach(viewValue.split(separator), function(value) {
- if (value) list.push(trim(value));
- });
- }
-
- return list;
- };
-
- ctrl.$parsers.push(parse);
- ctrl.$formatters.push(function(value) {
- if (isArray(value)) {
- return value.join(', ');
- }
-
- return undefined;
- });
-
- // Override the standard $isEmpty because an empty array means the input is empty.
- ctrl.$isEmpty = function(value) {
- return !value || !value.length;
- };
- }
- };
-};
-
-
-var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
-/**
- * @ngdoc directive
- * @name ngValue
- *
- * @description
- * Binds the given expression to the value of `input[select]` or `input[radio]`, so
- * that when the element is selected, the `ngModel` of that element is set to the
- * bound value.
- *
- * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as
- * shown below.
- *
- * @element input
- * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
- * of the `input` element
- *
- * @example
- <example name="ngValue-directive" module="valueExample">
- <file name="index.html">
- <script>
- angular.module('valueExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.names = ['pizza', 'unicorns', 'robots'];
- $scope.my = { favorite: 'unicorns' };
- }]);
- </script>
- <form ng-controller="ExampleController">
- <h2>Which is your favorite?</h2>
- <label ng-repeat="name in names" for="{{name}}">
- {{name}}
- <input type="radio"
- ng-model="my.favorite"
- ng-value="name"
- id="{{name}}"
- name="favorite">
- </label>
- <div>You chose {{my.favorite}}</div>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- var favorite = element(by.binding('my.favorite'));
-
- it('should initialize to model', function() {
- expect(favorite.getText()).toContain('unicorns');
- });
- it('should bind the values to the inputs', function() {
- element.all(by.model('my.favorite')).get(0).click();
- expect(favorite.getText()).toContain('pizza');
- });
- </file>
- </example>
- */
-var ngValueDirective = function() {
- return {
- priority: 100,
- compile: function(tpl, tplAttr) {
- if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
- return function ngValueConstantLink(scope, elm, attr) {
- attr.$set('value', scope.$eval(attr.ngValue));
- };
- } else {
- return function ngValueLink(scope, elm, attr) {
- scope.$watch(attr.ngValue, function valueWatchAction(value) {
- attr.$set('value', value);
- });
- };
- }
- }
- };
-};
-
-/**
- * @ngdoc directive
- * @name ngBind
- * @restrict AC
- *
- * @description
- * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
- * with the value of a given expression, and to update the text content when the value of that
- * expression changes.
- *
- * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
- * `{{ expression }}` which is similar but less verbose.
- *
- * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
- * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
- * element attribute, it makes the bindings invisible to the user while the page is loading.
- *
- * An alternative solution to this problem would be using the
- * {@link ng.directive:ngCloak ngCloak} directive.
- *
- *
- * @element ANY
- * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
- *
- * @example
- * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.name = 'Whirled';
- }]);
- </script>
- <div ng-controller="ExampleController">
- Enter name: <input type="text" ng-model="name"><br>
- Hello <span ng-bind="name"></span>!
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var nameInput = element(by.model('name'));
-
- expect(element(by.binding('name')).getText()).toBe('Whirled');
- nameInput.clear();
- nameInput.sendKeys('world');
- expect(element(by.binding('name')).getText()).toBe('world');
- });
- </file>
- </example>
- */
-var ngBindDirective = ngDirective({
- compile: function(templateElement) {
- templateElement.addClass('ng-binding');
- return function (scope, element, attr) {
- element.data('$binding', attr.ngBind);
- scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
- // We are purposefully using == here rather than === because we want to
- // catch when value is "null or undefined"
- // jshint -W041
- element.text(value == undefined ? '' : value);
- });
- };
- }
-});
-
-
-/**
- * @ngdoc directive
- * @name ngBindTemplate
- *
- * @description
- * The `ngBindTemplate` directive specifies that the element
- * text content should be replaced with the interpolation of the template
- * in the `ngBindTemplate` attribute.
- * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
- * expressions. This directive is needed since some HTML elements
- * (such as TITLE and OPTION) cannot contain SPAN elements.
- *
- * @element ANY
- * @param {string} ngBindTemplate template of form
- * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
- *
- * @example
- * Try it here: enter text in text box and watch the greeting change.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function ($scope) {
- $scope.salutation = 'Hello';
- $scope.name = 'World';
- }]);
- </script>
- <div ng-controller="ExampleController">
- Salutation: <input type="text" ng-model="salutation"><br>
- Name: <input type="text" ng-model="name"><br>
- <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var salutationElem = element(by.binding('salutation'));
- var salutationInput = element(by.model('salutation'));
- var nameInput = element(by.model('name'));
-
- expect(salutationElem.getText()).toBe('Hello World!');
-
- salutationInput.clear();
- salutationInput.sendKeys('Greetings');
- nameInput.clear();
- nameInput.sendKeys('user');
-
- expect(salutationElem.getText()).toBe('Greetings user!');
- });
- </file>
- </example>
- */
-var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
- return function(scope, element, attr) {
- // TODO: move this to scenario runner
- var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
- element.addClass('ng-binding').data('$binding', interpolateFn);
- attr.$observe('ngBindTemplate', function(value) {
- element.text(value);
- });
- };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngBindHtml
- *
- * @description
- * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
- * element in a secure way. By default, the innerHTML-ed content will be sanitized using the {@link
- * ngSanitize.$sanitize $sanitize} service. To utilize this functionality, ensure that `$sanitize`
- * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in
- * core Angular.) You may also bypass sanitization for values you know are safe. To do so, bind to
- * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
- * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.
- *
- * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
- * will have an exception (instead of an exploit.)
- *
- * @element ANY
- * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
- *
- * @example
-
- <example module="bindHtmlExample" deps="angular-sanitize.js">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p ng-bind-html="myHTML"></p>
- </div>
- </file>
-
- <file name="script.js">
- angular.module('bindHtmlExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.myHTML =
- 'I am an <code>HTML</code>string with ' +
- '<a href="#">links!</a> and other <em>stuff</em>';
- }]);
- </file>
-
- <file name="protractor.js" type="protractor">
- it('should check ng-bind-html', function() {
- expect(element(by.binding('myHTML')).getText()).toBe(
- 'I am an HTMLstring with links! and other stuff');
- });
- </file>
- </example>
- */
-var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
- return {
- compile: function (tElement) {
- tElement.addClass('ng-binding');
-
- return function (scope, element, attr) {
- element.data('$binding', attr.ngBindHtml);
-
- var parsed = $parse(attr.ngBindHtml);
-
- function getStringValue() {
- return (parsed(scope) || '').toString();
- }
-
- scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
- element.html($sce.getTrustedHtml(parsed(scope)) || '');
- });
- };
- }
- };
-}];
-
-function classDirective(name, selector) {
- name = 'ngClass' + name;
- return ['$animate', function($animate) {
- return {
- restrict: 'AC',
- link: function(scope, element, attr) {
- var oldVal;
-
- scope.$watch(attr[name], ngClassWatchAction, true);
-
- attr.$observe('class', function(value) {
- ngClassWatchAction(scope.$eval(attr[name]));
- });
-
-
- if (name !== 'ngClass') {
- scope.$watch('$index', function($index, old$index) {
- // jshint bitwise: false
- var mod = $index & 1;
- if (mod !== (old$index & 1)) {
- var classes = arrayClasses(scope.$eval(attr[name]));
- mod === selector ?
- addClasses(classes) :
- removeClasses(classes);
- }
- });
- }
-
- function addClasses(classes) {
- var newClasses = digestClassCounts(classes, 1);
- attr.$addClass(newClasses);
- }
-
- function removeClasses(classes) {
- var newClasses = digestClassCounts(classes, -1);
- attr.$removeClass(newClasses);
- }
-
- function digestClassCounts (classes, count) {
- var classCounts = element.data('$classCounts') || {};
- var classesToUpdate = [];
- forEach(classes, function (className) {
- if (count > 0 || classCounts[className]) {
- classCounts[className] = (classCounts[className] || 0) + count;
- if (classCounts[className] === +(count > 0)) {
- classesToUpdate.push(className);
- }
- }
- });
- element.data('$classCounts', classCounts);
- return classesToUpdate.join(' ');
- }
-
- function updateClasses (oldClasses, newClasses) {
- var toAdd = arrayDifference(newClasses, oldClasses);
- var toRemove = arrayDifference(oldClasses, newClasses);
- toRemove = digestClassCounts(toRemove, -1);
- toAdd = digestClassCounts(toAdd, 1);
-
- if (toAdd.length === 0) {
- $animate.removeClass(element, toRemove);
- } else if (toRemove.length === 0) {
- $animate.addClass(element, toAdd);
- } else {
- $animate.setClass(element, toAdd, toRemove);
- }
- }
-
- function ngClassWatchAction(newVal) {
- if (selector === true || scope.$index % 2 === selector) {
- var newClasses = arrayClasses(newVal || []);
- if (!oldVal) {
- addClasses(newClasses);
- } else if (!equals(newVal,oldVal)) {
- var oldClasses = arrayClasses(oldVal);
- updateClasses(oldClasses, newClasses);
- }
- }
- oldVal = shallowCopy(newVal);
- }
- }
- };
-
- function arrayDifference(tokens1, tokens2) {
- var values = [];
-
- outer:
- for(var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for(var j = 0; j < tokens2.length; j++) {
- if(token == tokens2[j]) continue outer;
- }
- values.push(token);
- }
- return values;
- }
-
- function arrayClasses (classVal) {
- if (isArray(classVal)) {
- return classVal;
- } else if (isString(classVal)) {
- return classVal.split(' ');
- } else if (isObject(classVal)) {
- var classes = [], i = 0;
- forEach(classVal, function(v, k) {
- if (v) {
- classes = classes.concat(k.split(' '));
- }
- });
- return classes;
- }
- return classVal;
- }
- }];
-}
-
-/**
- * @ngdoc directive
- * @name ngClass
- * @restrict AC
- *
- * @description
- * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
- * an expression that represents all classes to be added.
- *
- * The directive operates in three different ways, depending on which of three types the expression
- * evaluates to:
- *
- * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
- * names.
- *
- * 2. If the expression evaluates to an array, each element of the array should be a string that is
- * one or more space-delimited class names.
- *
- * 3. If the expression evaluates to an object, then for each key-value pair of the
- * object with a truthy value the corresponding key is used as a class name.
- *
- * The directive won't add duplicate classes if a particular class was already set.
- *
- * When the expression changes, the previously added classes are removed and only then the
- * new classes are added.
- *
- * @animations
- * add - happens just before the class is applied to the element
- * remove - happens just before the class is removed from the element
- *
- * @element ANY
- * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class
- * names, an array, or a map of class names to boolean values. In the case of a map, the
- * names of the properties whose values are truthy will be added as css classes to the
- * element.
- *
- * @example Example that demonstrates basic bindings via ngClass directive.
- <example>
- <file name="index.html">
- <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
- <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
- <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
- <input type="checkbox" ng-model="error"> error (apply "red" class)
- <hr>
- <p ng-class="style">Using String Syntax</p>
- <input type="text" ng-model="style" placeholder="Type: bold strike red">
- <hr>
- <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
- <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
- <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
- <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
- </file>
- <file name="style.css">
- .strike {
- text-decoration: line-through;
- }
- .bold {
- font-weight: bold;
- }
- .red {
- color: red;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var ps = element.all(by.css('p'));
-
- it('should let you toggle the class', function() {
-
- expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
- expect(ps.first().getAttribute('class')).not.toMatch(/red/);
-
- element(by.model('important')).click();
- expect(ps.first().getAttribute('class')).toMatch(/bold/);
-
- element(by.model('error')).click();
- expect(ps.first().getAttribute('class')).toMatch(/red/);
- });
-
- it('should let you toggle string example', function() {
- expect(ps.get(1).getAttribute('class')).toBe('');
- element(by.model('style')).clear();
- element(by.model('style')).sendKeys('red');
- expect(ps.get(1).getAttribute('class')).toBe('red');
- });
-
- it('array example should have 3 classes', function() {
- expect(ps.last().getAttribute('class')).toBe('');
- element(by.model('style1')).sendKeys('bold');
- element(by.model('style2')).sendKeys('strike');
- element(by.model('style3')).sendKeys('red');
- expect(ps.last().getAttribute('class')).toBe('bold strike red');
- });
- </file>
- </example>
-
- ## Animations
-
- The example below demonstrates how to perform animations using ngClass.
-
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
- <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
- <br>
- <span class="base-class" ng-class="myVar">Sample Text</span>
- </file>
- <file name="style.css">
- .base-class {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- }
-
- .base-class.my-class {
- color: red;
- font-size:3em;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class', function() {
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
-
- element(by.id('setbtn')).click();
-
- expect(element(by.css('.base-class')).getAttribute('class')).
- toMatch(/my-class/);
-
- element(by.id('clearbtn')).click();
-
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
- });
- </file>
- </example>
-
-
- ## ngClass and pre-existing CSS3 Transitions/Animations
- The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
- Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
- any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
- to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and
- {@link ngAnimate.$animate#removeclass $animate.removeClass}.
- */
-var ngClassDirective = classDirective('', true);
-
-/**
- * @ngdoc directive
- * @name ngClassOdd
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}}
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
-var ngClassOddDirective = classDirective('Odd', 0);
-
-/**
- * @ngdoc directive
- * @name ngClassEven
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
- * result of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}} &nbsp; &nbsp; &nbsp;
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
-var ngClassEvenDirective = classDirective('Even', 1);
-
-/**
- * @ngdoc directive
- * @name ngCloak
- * @restrict AC
- *
- * @description
- * The `ngCloak` directive is used to prevent the Angular html template from being briefly
- * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
- * directive to avoid the undesirable flicker effect caused by the html template display.
- *
- * The directive can be applied to the `<body>` element, but the preferred usage is to apply
- * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
- * of the browser view.
- *
- * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
- * `angular.min.js`.
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```css
- * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- * display: none !important;
- * }
- * ```
- *
- * When this css rule is loaded by the browser, all html elements (including their children) that
- * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
- * during the compilation of the template it deletes the `ngCloak` element attribute, making
- * the compiled element visible.
- *
- * For the best result, the `angular.js` script must be loaded in the head section of the html
- * document; alternatively, the css rule above must be included in the external stylesheet of the
- * application.
- *
- * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
- * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
- * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
- *
- * @element ANY
- *
- * @example
- <example>
- <file name="index.html">
- <div id="template1" ng-cloak>{{ 'hello' }}</div>
- <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should remove the template directive and css class', function() {
- expect($('#template1').getAttribute('ng-cloak')).
- toBeNull();
- expect($('#template2').getAttribute('ng-cloak')).
- toBeNull();
- });
- </file>
- </example>
- *
- */
-var ngCloakDirective = ngDirective({
- compile: function(element, attr) {
- attr.$set('ngCloak', undefined);
- element.removeClass('ng-cloak');
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngController
- *
- * @description
- * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
- * supports the principles behind the Model-View-Controller design pattern.
- *
- * MVC components in angular:
- *
- * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
- * are accessed through bindings.
- * * View — The template (HTML with data bindings) that is rendered into the View.
- * * Controller — The `ngController` directive specifies a Controller class; the class contains business
- * logic behind the application to decorate the scope with functions and values
- *
- * Note that you can also attach controllers to the DOM by declaring it in a route definition
- * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
- * again using `ng-controller` in the template itself. This will cause the controller to be attached
- * and executed twice.
- *
- * @element ANY
- * @scope
- * @param {expression} ngController Name of a globally accessible constructor function or an
- * {@link guide/expression expression} that on the current scope evaluates to a
- * constructor function. The controller instance can be published into a scope property
- * by specifying `as propertyName`.
- *
- * @example
- * Here is a simple form for editing user contact information. Adding, removing, clearing, and
- * greeting are methods declared on the controller (see source tab). These methods can
- * easily be called from the angular markup. Any changes to the data are automatically reflected
- * in the View without the need for a manual update.
- *
- * Two different declaration styles are included below:
- *
- * * one binds methods and properties directly onto the controller using `this`:
- * `ng-controller="SettingsController1 as settings"`
- * * one injects `$scope` into the controller:
- * `ng-controller="SettingsController2"`
- *
- * The second option is more common in the Angular community, and is generally used in boilerplates
- * and in this guide. However, there are advantages to binding properties directly to the controller
- * and avoiding scope.
- *
- * * Using `controller as` makes it obvious which controller you are accessing in the template when
- * multiple controllers apply to an element.
- * * If you are writing your controllers as classes you have easier access to the properties and
- * methods, which will appear on the scope, from inside the controller code.
- * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
- * inheritance masking primitives.
- *
- * This example demonstrates the `controller as` syntax.
- *
- * <example name="ngControllerAs" module="controllerAsExample">
- * <file name="index.html">
- * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
- * Name: <input type="text" ng-model="settings.name"/>
- * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in settings.contacts">
- * <select ng-model="contact.type">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value"/>
- * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
- * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
- * </li>
- * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerAsExample', [])
- * .controller('SettingsController1', SettingsController1);
- *
- * function SettingsController1() {
- * this.name = "John Smith";
- * this.contacts = [
- * {type: 'phone', value: '408 555 1212'},
- * {type: 'email', value: 'john.smith@example.org'} ];
- * }
- *
- * SettingsController1.prototype.greet = function() {
- * alert(this.name);
- * };
- *
- * SettingsController1.prototype.addContact = function() {
- * this.contacts.push({type: 'email', value: 'yourname@example.org'});
- * };
- *
- * SettingsController1.prototype.removeContact = function(contactToRemove) {
- * var index = this.contacts.indexOf(contactToRemove);
- * this.contacts.splice(index, 1);
- * };
- *
- * SettingsController1.prototype.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller as', function() {
- * var container = element(by.id('ctrl-as-exmpl'));
- * expect(container.element(by.model('settings.name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- *
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.linkText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.linkText('add')).click();
- *
- * expect(container.element(by.repeater('contact in settings.contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- * </example>
- *
- * This example demonstrates the "attach to `$scope`" style of controller.
- *
- * <example name="ngController" module="controllerExample">
- * <file name="index.html">
- * <div id="ctrl-exmpl" ng-controller="SettingsController2">
- * Name: <input type="text" ng-model="name"/>
- * [ <a href="" ng-click="greet()">greet</a> ]<br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in contacts">
- * <select ng-model="contact.type">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value"/>
- * [ <a href="" ng-click="clearContact(contact)">clear</a>
- * | <a href="" ng-click="removeContact(contact)">X</a> ]
- * </li>
- * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerExample', [])
- * .controller('SettingsController2', ['$scope', SettingsController2]);
- *
- * function SettingsController2($scope) {
- * $scope.name = "John Smith";
- * $scope.contacts = [
- * {type:'phone', value:'408 555 1212'},
- * {type:'email', value:'john.smith@example.org'} ];
- *
- * $scope.greet = function() {
- * alert($scope.name);
- * };
- *
- * $scope.addContact = function() {
- * $scope.contacts.push({type:'email', value:'yourname@example.org'});
- * };
- *
- * $scope.removeContact = function(contactToRemove) {
- * var index = $scope.contacts.indexOf(contactToRemove);
- * $scope.contacts.splice(index, 1);
- * };
- *
- * $scope.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * }
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller', function() {
- * var container = element(by.id('ctrl-exmpl'));
- *
- * expect(container.element(by.model('name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.linkText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.linkText('add')).click();
- *
- * expect(container.element(by.repeater('contact in contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- *</example>
-
- */
-var ngControllerDirective = [function() {
- return {
- scope: true,
- controller: '@',
- priority: 500
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngCsp
- *
- * @element html
- * @description
- * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
- *
- * This is necessary when developing things like Google Chrome Extensions.
- *
- * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
- * For Angular to be CSP compatible there are only two things that we need to do differently:
- *
- * - don't use `Function` constructor to generate optimized value getters
- * - don't inject custom stylesheet into the document
- *
- * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
- * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
- * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
- * be raised.
- *
- * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
- * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
- * To make those directives work in CSP mode, include the `angular-csp.css` manually.
- *
- * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
- * autodetection however triggers a CSP error to be logged in the console:
- *
- * ```
- * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
- * script in the following Content Security Policy directive: "default-src 'self'". Note that
- * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
- * ```
- *
- * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
- * directive on the root element of the application or on the `angular.js` script tag, whichever
- * appears first in the html document.
- *
- * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
- *
- * @example
- * This example shows how to apply the `ngCsp` directive to the `html` tag.
- ```html
- <!doctype html>
- <html ng-app ng-csp>
- ...
- ...
- </html>
- ```
- */
-
-// ngCsp is not implemented as a proper directive any more, because we need it be processed while we
-// bootstrap the system (before $parse is instantiated), for this reason we just have
-// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
-
-/**
- * @ngdoc directive
- * @name ngClick
- *
- * @description
- * The ngClick directive allows you to specify custom behavior when
- * an element is clicked.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
- * click. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-click="count = count + 1" ng-init="count=0">
- Increment
- </button>
- <span>
- count: {{count}}
- <span>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-click', function() {
- expect(element(by.binding('count')).getText()).toMatch('0');
- element(by.css('button')).click();
- expect(element(by.binding('count')).getText()).toMatch('1');
- });
- </file>
- </example>
- */
-/*
- * A directive that allows creation of custom onclick handlers that are defined as angular
- * expressions and are compiled and executed within the current scope.
- *
- * Events that are handled via these handler are always configured not to propagate further.
- */
-var ngEventDirectives = {};
-
-// For events that might fire synchronously during DOM manipulation
-// we need to execute their event handlers asynchronously using $evalAsync,
-// so that they are not executed in an inconsistent state.
-var forceAsyncEvents = {
- 'blur': true,
- 'focus': true
-};
-forEach(
- 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
- function(eventName) {
- var directiveName = directiveNormalize('ng-' + eventName);
- ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
- return {
- compile: function($element, attr) {
- var fn = $parse(attr[directiveName]);
- return function ngEventHandler(scope, element) {
- element.on(eventName, function(event) {
- var callback = function() {
- fn(scope, {$event:event});
- };
- if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
- scope.$evalAsync(callback);
- } else {
- scope.$apply(callback);
- }
- });
- };
- }
- };
- }];
- }
-);
-
-/**
- * @ngdoc directive
- * @name ngDblclick
- *
- * @description
- * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
- * a dblclick. (The Event object is available as `$event`)
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-dblclick="count = count + 1" ng-init="count=0">
- Increment (on double click)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMousedown
- *
- * @description
- * The ngMousedown directive allows you to specify custom behavior on mousedown event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
- * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mousedown="count = count + 1" ng-init="count=0">
- Increment (on mouse down)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseup
- *
- * @description
- * Specify custom behavior on mouseup event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
- * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseup="count = count + 1" ng-init="count=0">
- Increment (on mouse up)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngMouseover
- *
- * @description
- * Specify custom behavior on mouseover event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
- * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseover="count = count + 1" ng-init="count=0">
- Increment (when mouse is over)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseenter
- *
- * @description
- * Specify custom behavior on mouseenter event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
- * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseenter="count = count + 1" ng-init="count=0">
- Increment (when mouse enters)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMouseleave
- *
- * @description
- * Specify custom behavior on mouseleave event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
- * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mouseleave="count = count + 1" ng-init="count=0">
- Increment (when mouse leaves)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngMousemove
- *
- * @description
- * Specify custom behavior on mousemove event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
- * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-mousemove="count = count + 1" ng-init="count=0">
- Increment (when mouse moves)
- </button>
- count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeydown
- *
- * @description
- * Specify custom behavior on keydown event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
- * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-keydown="count = count + 1" ng-init="count=0">
- key down count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeyup
- *
- * @description
- * Specify custom behavior on keyup event.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
- * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <p>Typing in the input box below updates the key count</p>
- <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
-
- <p>Typing in the input box below updates the keycode</p>
- <input ng-keyup="event=$event">
- <p>event keyCode: {{ event.keyCode }}</p>
- <p>event altKey: {{ event.altKey }}</p>
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngKeypress
- *
- * @description
- * Specify custom behavior on keypress event.
- *
- * @element ANY
- * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
- * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
- * and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-keypress="count = count + 1" ng-init="count=0">
- key press count: {{count}}
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc directive
- * @name ngSubmit
- *
- * @description
- * Enables binding angular expressions to onsubmit events.
- *
- * Additionally it prevents the default action (which for form means sending the request to the
- * server and reloading the current page), but only if the form does not contain `action`,
- * `data-action`, or `x-action` attributes.
- *
- * <div class="alert alert-warning">
- * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
- * `ngSubmit` handlers together. See the
- * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
- * for a detailed discussion of when `ngSubmit` may be triggered.
- * </div>
- *
- * @element form
- * @priority 0
- * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
- * ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example module="submitExample">
- <file name="index.html">
- <script>
- angular.module('submitExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.list = [];
- $scope.text = 'hello';
- $scope.submit = function() {
- if ($scope.text) {
- $scope.list.push(this.text);
- $scope.text = '';
- }
- };
- }]);
- </script>
- <form ng-submit="submit()" ng-controller="ExampleController">
- Enter text and hit enter:
- <input type="text" ng-model="text" name="text" />
- <input type="submit" id="submit" value="Submit" />
- <pre>list={{list}}</pre>
- </form>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-submit', function() {
- expect(element(by.binding('list')).getText()).toBe('list=[]');
- element(by.css('#submit')).click();
- expect(element(by.binding('list')).getText()).toContain('hello');
- expect(element(by.model('text')).getAttribute('value')).toBe('');
- });
- it('should ignore empty strings', function() {
- expect(element(by.binding('list')).getText()).toBe('list=[]');
- element(by.css('#submit')).click();
- element(by.css('#submit')).click();
- expect(element(by.binding('list')).getText()).toContain('hello');
- });
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngFocus
- *
- * @description
- * Specify custom behavior on focus event.
- *
- * Note: As the `focus` event is executed synchronously when calling `input.focus()`
- * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
- * during an `$apply` to ensure a consistent state.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
- * focus. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ngBlur
- *
- * @description
- * Specify custom behavior on blur event.
- *
- * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
- * an element has lost focus.
- *
- * Note: As the `blur` event is executed synchronously also during DOM manipulations
- * (e.g. removing a focussed input),
- * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
- * during an `$apply` to ensure a consistent state.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
- * blur. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ngCopy
- *
- * @description
- * Specify custom behavior on copy event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
- * copy. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
- copied: {{copied}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngCut
- *
- * @description
- * Specify custom behavior on cut event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
- * cut. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
- cut: {{cut}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngPaste
- *
- * @description
- * Specify custom behavior on paste event.
- *
- * @element window, input, select, textarea, a
- * @priority 0
- * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
- * paste. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
- pasted: {{paste}}
- </file>
- </example>
- */
-
-/**
- * @ngdoc directive
- * @name ngIf
- * @restrict A
- *
- * @description
- * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
- * {expression}. If the expression assigned to `ngIf` evaluates to a false
- * value then the element is removed from the DOM, otherwise a clone of the
- * element is reinserted into the DOM.
- *
- * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
- * element in the DOM rather than changing its visibility via the `display` css property. A common
- * case when this difference is significant is when using css selectors that rely on an element's
- * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
- *
- * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
- * is created when the element is restored. The scope created within `ngIf` inherits from
- * its parent scope using
- * [prototypal inheritance](https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance).
- * An important implication of this is if `ngModel` is used within `ngIf` to bind to
- * a javascript primitive defined in the parent scope. In this case any modifications made to the
- * variable within the child scope will override (hide) the value in the parent scope.
- *
- * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
- * is if an element's class attribute is directly modified after it's compiled, using something like
- * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
- * the added class will be lost because the original compiled state is used to regenerate the element.
- *
- * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
- * and `leave` effects.
- *
- * @animations
- * enter - happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container
- * leave - happens just before the ngIf contents are removed from the DOM
- *
- * @element ANY
- * @scope
- * @priority 600
- * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
- * the element is removed from the DOM tree. If it is truthy a copy of the compiled
- * element is added to the DOM tree.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
- Show when checked:
- <span ng-if="checked" class="animate-if">
- I'm removed when the checkbox is unchecked.
- </span>
- </file>
- <file name="animations.css">
- .animate-if {
- background:white;
- border:1px solid black;
- padding:10px;
- }
-
- .animate-if.ng-enter, .animate-if.ng-leave {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- }
-
- .animate-if.ng-enter,
- .animate-if.ng-leave.ng-leave-active {
- opacity:0;
- }
-
- .animate-if.ng-leave,
- .animate-if.ng-enter.ng-enter-active {
- opacity:1;
- }
- </file>
- </example>
- */
-var ngIfDirective = ['$animate', function($animate) {
- return {
- transclude: 'element',
- priority: 600,
- terminal: true,
- restrict: 'A',
- $$tlb: true,
- link: function ($scope, $element, $attr, ctrl, $transclude) {
- var block, childScope, previousElements;
- $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
-
- if (toBoolean(value)) {
- if (!childScope) {
- childScope = $scope.$new();
- $transclude(childScope, function (clone) {
- clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
- // Note: We only need the first/last node of the cloned nodes.
- // However, we need to keep the reference to the jqlite wrapper as it might be changed later
- // by a directive with templateUrl when its template arrives.
- block = {
- clone: clone
- };
- $animate.enter(clone, $element.parent(), $element);
- });
- }
- } else {
- if(previousElements) {
- previousElements.remove();
- previousElements = null;
- }
- if(childScope) {
- childScope.$destroy();
- childScope = null;
- }
- if(block) {
- previousElements = getBlockElements(block.clone);
- $animate.leave(previousElements, function() {
- previousElements = null;
- });
- block = null;
- }
- }
- });
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngInclude
- * @restrict ECA
- *
- * @description
- * Fetches, compiles and includes an external HTML fragment.
- *
- * By default, the template URL is restricted to the same domain and protocol as the
- * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
- * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
- * [wrap them](ng.$sce#trustAsResourceUrl) as trusted values. Refer to Angular's {@link
- * ng.$sce Strict Contextual Escaping}.
- *
- * In addition, the browser's
- * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
- * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
- * policy may further restrict whether the template is successfully loaded.
- * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
- * access on some browsers.
- *
- * @animations
- * enter - animation is used to bring new content into the browser.
- * leave - animation is used to animate existing content away.
- *
- * The enter and leave animation occur concurrently.
- *
- * @scope
- * @priority 400
- *
- * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
- * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
- * @param {string=} onload Expression to evaluate when a new partial is loaded.
- *
- * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
- * $anchorScroll} to scroll the viewport after the content is loaded.
- *
- * - If the attribute is not set, disable scrolling.
- * - If the attribute is set without value, enable scrolling.
- * - Otherwise enable scrolling only if the expression evaluates to truthy value.
- *
- * @example
- <example module="includeExample" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <select ng-model="template" ng-options="t.name for t in templates">
- <option value="">(blank)</option>
- </select>
- url of the template: <tt>{{template.url}}</tt>
- <hr/>
- <div class="slide-animate-container">
- <div class="slide-animate" ng-include="template.url"></div>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('includeExample', ['ngAnimate'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.templates =
- [ { name: 'template1.html', url: 'template1.html'},
- { name: 'template2.html', url: 'template2.html'} ];
- $scope.template = $scope.templates[0];
- }]);
- </file>
- <file name="template1.html">
- Content of template1.html
- </file>
- <file name="template2.html">
- Content of template2.html
- </file>
- <file name="animations.css">
- .slide-animate-container {
- position:relative;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .slide-animate {
- padding:10px;
- }
-
- .slide-animate.ng-enter, .slide-animate.ng-leave {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- display:block;
- padding:10px;
- }
-
- .slide-animate.ng-enter {
- top:-50px;
- }
- .slide-animate.ng-enter.ng-enter-active {
- top:0;
- }
-
- .slide-animate.ng-leave {
- top:0;
- }
- .slide-animate.ng-leave.ng-leave-active {
- top:50px;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var templateSelect = element(by.model('template'));
- var includeElem = element(by.css('[ng-include]'));
-
- it('should load template1.html', function() {
- expect(includeElem.getText()).toMatch(/Content of template1.html/);
- });
-
- it('should load template2.html', function() {
- if (browser.params.browser == 'firefox') {
- // Firefox can't handle using selects
- // See https://github.com/angular/protractor/issues/480
- return;
- }
- templateSelect.click();
- templateSelect.all(by.css('option')).get(2).click();
- expect(includeElem.getText()).toMatch(/Content of template2.html/);
- });
-
- it('should change to blank', function() {
- if (browser.params.browser == 'firefox') {
- // Firefox can't handle using selects
- return;
- }
- templateSelect.click();
- templateSelect.all(by.css('option')).get(0).click();
- expect(includeElem.isPresent()).toBe(false);
- });
- </file>
- </example>
- */
-
-
-/**
- * @ngdoc event
- * @name ngInclude#$includeContentRequested
- * @eventType emit on the scope ngInclude was declared in
- * @description
- * Emitted every time the ngInclude content is requested.
- */
-
-
-/**
- * @ngdoc event
- * @name ngInclude#$includeContentLoaded
- * @eventType emit on the current ngInclude scope
- * @description
- * Emitted every time the ngInclude content is reloaded.
- */
-var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
- function($http, $templateCache, $anchorScroll, $animate, $sce) {
- return {
- restrict: 'ECA',
- priority: 400,
- terminal: true,
- transclude: 'element',
- controller: angular.noop,
- compile: function(element, attr) {
- var srcExp = attr.ngInclude || attr.src,
- onloadExp = attr.onload || '',
- autoScrollExp = attr.autoscroll;
-
- return function(scope, $element, $attr, ctrl, $transclude) {
- var changeCounter = 0,
- currentScope,
- previousElement,
- currentElement;
-
- var cleanupLastIncludeContent = function() {
- if(previousElement) {
- previousElement.remove();
- previousElement = null;
- }
- if(currentScope) {
- currentScope.$destroy();
- currentScope = null;
- }
- if(currentElement) {
- $animate.leave(currentElement, function() {
- previousElement = null;
- });
- previousElement = currentElement;
- currentElement = null;
- }
- };
-
- scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
- var afterAnimation = function() {
- if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
- $anchorScroll();
- }
- };
- var thisChangeId = ++changeCounter;
-
- if (src) {
- $http.get(src, {cache: $templateCache}).success(function(response) {
- if (thisChangeId !== changeCounter) return;
- var newScope = scope.$new();
- ctrl.template = response;
-
- // Note: This will also link all children of ng-include that were contained in the original
- // html. If that content contains controllers, ... they could pollute/change the scope.
- // However, using ng-include on an element with additional content does not make sense...
- // Note: We can't remove them in the cloneAttchFn of $transclude as that
- // function is called before linking the content, which would apply child
- // directives to non existing elements.
- var clone = $transclude(newScope, function(clone) {
- cleanupLastIncludeContent();
- $animate.enter(clone, null, $element, afterAnimation);
- });
-
- currentScope = newScope;
- currentElement = clone;
-
- currentScope.$emit('$includeContentLoaded');
- scope.$eval(onloadExp);
- }).error(function() {
- if (thisChangeId === changeCounter) cleanupLastIncludeContent();
- });
- scope.$emit('$includeContentRequested');
- } else {
- cleanupLastIncludeContent();
- ctrl.template = null;
- }
- });
- };
- }
- };
-}];
-
-// This directive is called during the $transclude call of the first `ngInclude` directive.
-// It will replace and compile the content of the element with the loaded template.
-// We need this directive so that the element content is already filled when
-// the link function of another directive on the same element as ngInclude
-// is called.
-var ngIncludeFillContentDirective = ['$compile',
- function($compile) {
- return {
- restrict: 'ECA',
- priority: -400,
- require: 'ngInclude',
- link: function(scope, $element, $attr, ctrl) {
- $element.html(ctrl.template);
- $compile($element.contents())(scope);
- }
- };
- }];
-
-/**
- * @ngdoc directive
- * @name ngInit
- * @restrict AC
- *
- * @description
- * The `ngInit` directive allows you to evaluate an expression in the
- * current scope.
- *
- * <div class="alert alert-error">
- * The only appropriate use of `ngInit` is for aliasing special properties of
- * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
- * should use {@link guide/controller controllers} rather than `ngInit`
- * to initialize values on a scope.
- * </div>
- * <div class="alert alert-warning">
- * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
- * sure you have parenthesis for correct precedence:
- * <pre class="prettyprint">
- * <div ng-init="test1 = (data | orderBy:'name')"></div>
- * </pre>
- * </div>
- *
- * @priority 450
- *
- * @element ANY
- * @param {expression} ngInit {@link guide/expression Expression} to eval.
- *
- * @example
- <example module="initExample">
- <file name="index.html">
- <script>
- angular.module('initExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.list = [['a', 'b'], ['c', 'd']];
- }]);
- </script>
- <div ng-controller="ExampleController">
- <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
- <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
- <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
- </div>
- </div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should alias index positions', function() {
- var elements = element.all(by.css('.example-init'));
- expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
- expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
- expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
- expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
- });
- </file>
- </example>
- */
-var ngInitDirective = ngDirective({
- priority: 450,
- compile: function() {
- return {
- pre: function(scope, element, attrs) {
- scope.$eval(attrs.ngInit);
- }
- };
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngNonBindable
- * @restrict AC
- * @priority 1000
- *
- * @description
- * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
- * DOM element. This is useful if the element contains what appears to be Angular directives and
- * bindings but which should be ignored by Angular. This could be the case if you have a site that
- * displays snippets of code, for instance.
- *
- * @element ANY
- *
- * @example
- * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
- * but the one wrapped in `ngNonBindable` is left alone.
- *
- * @example
- <example>
- <file name="index.html">
- <div>Normal: {{1 + 2}}</div>
- <div ng-non-bindable>Ignored: {{1 + 2}}</div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-non-bindable', function() {
- expect(element(by.binding('1 + 2')).getText()).toContain('3');
- expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
- });
- </file>
- </example>
- */
-var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
-
-/**
- * @ngdoc directive
- * @name ngPluralize
- * @restrict EA
- *
- * @description
- * `ngPluralize` is a directive that displays messages according to en-US localization rules.
- * These rules are bundled with angular.js, but can be overridden
- * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
- * by specifying the mappings between
- * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
- * and the strings to be displayed.
- *
- * # Plural categories and explicit number rules
- * There are two
- * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
- * in Angular's default en-US locale: "one" and "other".
- *
- * While a plural category may match many numbers (for example, in en-US locale, "other" can match
- * any number that is not 1), an explicit number rule can only match one number. For example, the
- * explicit number rule for "3" matches the number 3. There are examples of plural categories
- * and explicit number rules throughout the rest of this documentation.
- *
- * # Configuring ngPluralize
- * You configure ngPluralize by providing 2 attributes: `count` and `when`.
- * You can also provide an optional attribute, `offset`.
- *
- * The value of the `count` attribute can be either a string or an {@link guide/expression
- * Angular expression}; these are evaluated on the current scope for its bound value.
- *
- * The `when` attribute specifies the mappings between plural categories and the actual
- * string to be displayed. The value of the attribute should be a JSON object.
- *
- * The following example shows how to configure ngPluralize:
- *
- * ```html
- * <ng-pluralize count="personCount"
- when="{'0': 'Nobody is viewing.',
- * 'one': '1 person is viewing.',
- * 'other': '{} people are viewing.'}">
- * </ng-pluralize>
- *```
- *
- * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
- * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
- * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
- * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
- * show "a dozen people are viewing".
- *
- * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
- * into pluralized strings. In the previous example, Angular will replace `{}` with
- * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
- * for <span ng-non-bindable>{{numberExpression}}</span>.
- *
- * # Configuring ngPluralize with offset
- * The `offset` attribute allows further customization of pluralized text, which can result in
- * a better user experience. For example, instead of the message "4 people are viewing this document",
- * you might display "John, Kate and 2 others are viewing this document".
- * The offset attribute allows you to offset a number by any desired value.
- * Let's take a look at an example:
- *
- * ```html
- * <ng-pluralize count="personCount" offset=2
- * when="{'0': 'Nobody is viewing.',
- * '1': '{{person1}} is viewing.',
- * '2': '{{person1}} and {{person2}} are viewing.',
- * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
- * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
- * </ng-pluralize>
- * ```
- *
- * Notice that we are still using two plural categories(one, other), but we added
- * three explicit number rules 0, 1 and 2.
- * When one person, perhaps John, views the document, "John is viewing" will be shown.
- * When three people view the document, no explicit number rule is found, so
- * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
- * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
- * is shown.
- *
- * Note that when you specify offsets, you must provide explicit number rules for
- * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
- * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
- * plural categories "one" and "other".
- *
- * @param {string|expression} count The variable to be bound to.
- * @param {string} when The mapping between plural category to its corresponding strings.
- * @param {number=} offset Offset to deduct from the total number.
- *
- * @example
- <example module="pluralizeExample">
- <file name="index.html">
- <script>
- angular.module('pluralizeExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.person1 = 'Igor';
- $scope.person2 = 'Misko';
- $scope.personCount = 1;
- }]);
- </script>
- <div ng-controller="ExampleController">
- Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
- Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
- Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
-
- <!--- Example with simple pluralization rules for en locale --->
- Without Offset:
- <ng-pluralize count="personCount"
- when="{'0': 'Nobody is viewing.',
- 'one': '1 person is viewing.',
- 'other': '{} people are viewing.'}">
- </ng-pluralize><br>
-
- <!--- Example with offset --->
- With Offset(2):
- <ng-pluralize count="personCount" offset=2
- when="{'0': 'Nobody is viewing.',
- '1': '{{person1}} is viewing.',
- '2': '{{person1}} and {{person2}} are viewing.',
- 'one': '{{person1}}, {{person2}} and one other person are viewing.',
- 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
- </ng-pluralize>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should show correct pluralized string', function() {
- var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
- var withOffset = element.all(by.css('ng-pluralize')).get(1);
- var countInput = element(by.model('personCount'));
-
- expect(withoutOffset.getText()).toEqual('1 person is viewing.');
- expect(withOffset.getText()).toEqual('Igor is viewing.');
-
- countInput.clear();
- countInput.sendKeys('0');
-
- expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
- expect(withOffset.getText()).toEqual('Nobody is viewing.');
-
- countInput.clear();
- countInput.sendKeys('2');
-
- expect(withoutOffset.getText()).toEqual('2 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
-
- countInput.clear();
- countInput.sendKeys('3');
-
- expect(withoutOffset.getText()).toEqual('3 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
-
- countInput.clear();
- countInput.sendKeys('4');
-
- expect(withoutOffset.getText()).toEqual('4 people are viewing.');
- expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
- });
- it('should show data-bound names', function() {
- var withOffset = element.all(by.css('ng-pluralize')).get(1);
- var personCount = element(by.model('personCount'));
- var person1 = element(by.model('person1'));
- var person2 = element(by.model('person2'));
- personCount.clear();
- personCount.sendKeys('4');
- person1.clear();
- person1.sendKeys('Di');
- person2.clear();
- person2.sendKeys('Vojta');
- expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
- });
- </file>
- </example>
- */
-var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
- var BRACE = /{}/g;
- return {
- restrict: 'EA',
- link: function(scope, element, attr) {
- var numberExp = attr.count,
- whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
- offset = attr.offset || 0,
- whens = scope.$eval(whenExp) || {},
- whensExpFns = {},
- startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- isWhen = /^when(Minus)?(.+)$/;
-
- forEach(attr, function(expression, attributeName) {
- if (isWhen.test(attributeName)) {
- whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
- element.attr(attr.$attr[attributeName]);
- }
- });
- forEach(whens, function(expression, key) {
- whensExpFns[key] =
- $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
- offset + endSymbol));
- });
-
- scope.$watch(function ngPluralizeWatch() {
- var value = parseFloat(scope.$eval(numberExp));
-
- if (!isNaN(value)) {
- //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
- //check it against pluralization rules in $locale service
- if (!(value in whens)) value = $locale.pluralCat(value - offset);
- return whensExpFns[value](scope, element, true);
- } else {
- return '';
- }
- }, function ngPluralizeWatchAction(newVal) {
- element.text(newVal);
- });
- }
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngRepeat
- *
- * @description
- * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
- * instance gets its own scope, where the given loop variable is set to the current collection item,
- * and `$index` is set to the item index or key.
- *
- * Special properties are exposed on the local scope of each template instance, including:
- *
- * | Variable | Type | Details |
- * |-----------|-----------------|-----------------------------------------------------------------------------|
- * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
- * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
- * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
- * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
- * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
- * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
- *
- * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
- * This may be useful when, for instance, nesting ngRepeats.
- *
- * # Special repeat start and end points
- * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
- * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
- * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
- * up to and including the ending HTML tag where **ng-repeat-end** is placed.
- *
- * The example below makes use of this feature:
- * ```html
- * <header ng-repeat-start="item in items">
- * Header {{ item }}
- * </header>
- * <div class="body">
- * Body {{ item }}
- * </div>
- * <footer ng-repeat-end>
- * Footer {{ item }}
- * </footer>
- * ```
- *
- * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
- * ```html
- * <header>
- * Header A
- * </header>
- * <div class="body">
- * Body A
- * </div>
- * <footer>
- * Footer A
- * </footer>
- * <header>
- * Header B
- * </header>
- * <div class="body">
- * Body B
- * </div>
- * <footer>
- * Footer B
- * </footer>
- * ```
- *
- * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
- * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
- *
- * @animations
- * **.enter** - when a new item is added to the list or when an item is revealed after a filter
- *
- * **.leave** - when an item is removed from the list or when an item is filtered out
- *
- * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
- *
- * @element ANY
- * @scope
- * @priority 1000
- * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
- * formats are currently supported:
- *
- * * `variable in expression` – where variable is the user defined loop variable and `expression`
- * is a scope expression giving the collection to enumerate.
- *
- * For example: `album in artist.albums`.
- *
- * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
- * and `expression` is the scope expression giving the collection to enumerate.
- *
- * For example: `(name, age) in {'adam':10, 'amalie':12}`.
- *
- * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function
- * which can be used to associate the objects in the collection with the DOM elements. If no tracking function
- * is specified the ng-repeat associates elements by identity in the collection. It is an error to have
- * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
- * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression,
- * before specifying a tracking expression.
- *
- * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
- * will be associated by item identity in the array.
- *
- * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
- * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
- * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
- * element in the same way in the DOM.
- *
- * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
- * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
- * property is same.
- *
- * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
- * to items in conjunction with a tracking expression.
- *
- * @example
- * This example initializes the scope to a list of names and
- * then uses `ngRepeat` to display every person:
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-init="friends = [
- {name:'John', age:25, gender:'boy'},
- {name:'Jessie', age:30, gender:'girl'},
- {name:'Johanna', age:28, gender:'girl'},
- {name:'Joy', age:15, gender:'girl'},
- {name:'Mary', age:28, gender:'girl'},
- {name:'Peter', age:95, gender:'boy'},
- {name:'Sebastian', age:50, gender:'boy'},
- {name:'Erika', age:27, gender:'girl'},
- {name:'Patrick', age:40, gender:'boy'},
- {name:'Samantha', age:60, gender:'girl'}
- ]">
- I have {{friends.length}} friends. They are:
- <input type="search" ng-model="q" placeholder="filter friends..." />
- <ul class="example-animate-container">
- <li class="animate-repeat" ng-repeat="friend in friends | filter:q">
- [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
- </li>
- </ul>
- </div>
- </file>
- <file name="animations.css">
- .example-animate-container {
- background:white;
- border:1px solid black;
- list-style:none;
- margin:0;
- padding:0 10px;
- }
-
- .animate-repeat {
- line-height:40px;
- list-style:none;
- box-sizing:border-box;
- }
-
- .animate-repeat.ng-move,
- .animate-repeat.ng-enter,
- .animate-repeat.ng-leave {
- -webkit-transition:all linear 0.5s;
- transition:all linear 0.5s;
- }
-
- .animate-repeat.ng-leave.ng-leave-active,
- .animate-repeat.ng-move,
- .animate-repeat.ng-enter {
- opacity:0;
- max-height:0;
- }
-
- .animate-repeat.ng-leave,
- .animate-repeat.ng-move.ng-move-active,
- .animate-repeat.ng-enter.ng-enter-active {
- opacity:1;
- max-height:40px;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var friends = element.all(by.repeater('friend in friends'));
-
- it('should render initial data set', function() {
- expect(friends.count()).toBe(10);
- expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
- expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
- expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
- expect(element(by.binding('friends.length')).getText())
- .toMatch("I have 10 friends. They are:");
- });
-
- it('should update repeater when filter predicate changes', function() {
- expect(friends.count()).toBe(10);
-
- element(by.model('q')).sendKeys('ma');
-
- expect(friends.count()).toBe(2);
- expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
- expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
- });
- </file>
- </example>
- */
-var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
- var NG_REMOVED = '$$NG_REMOVED';
- var ngRepeatMinErr = minErr('ngRepeat');
- return {
- transclude: 'element',
- priority: 1000,
- terminal: true,
- $$tlb: true,
- link: function($scope, $element, $attr, ctrl, $transclude){
- var expression = $attr.ngRepeat;
- var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
- trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
- lhs, rhs, valueIdentifier, keyIdentifier,
- hashFnLocals = {$id: hashKey};
-
- if (!match) {
- throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
- expression);
- }
-
- lhs = match[1];
- rhs = match[2];
- trackByExp = match[3];
-
- if (trackByExp) {
- trackByExpGetter = $parse(trackByExp);
- trackByIdExpFn = function(key, value, index) {
- // assign key, value, and $index to the locals so that they can be used in hash functions
- if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
- hashFnLocals[valueIdentifier] = value;
- hashFnLocals.$index = index;
- return trackByExpGetter($scope, hashFnLocals);
- };
- } else {
- trackByIdArrayFn = function(key, value) {
- return hashKey(value);
- };
- trackByIdObjFn = function(key) {
- return key;
- };
- }
-
- match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
- if (!match) {
- throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
- lhs);
- }
- valueIdentifier = match[3] || match[1];
- keyIdentifier = match[2];
-
- // Store a list of elements from previous run. This is a hash where key is the item from the
- // iterator, and the value is objects with following properties.
- // - scope: bound scope
- // - element: previous element.
- // - index: position
- var lastBlockMap = {};
-
- //watch props
- $scope.$watchCollection(rhs, function ngRepeatAction(collection){
- var index, length,
- previousNode = $element[0], // current position of the node
- nextNode,
- // Same as lastBlockMap but it has the current state. It will become the
- // lastBlockMap on the next iteration.
- nextBlockMap = {},
- arrayLength,
- childScope,
- key, value, // key/value of iteration
- trackById,
- trackByIdFn,
- collectionKeys,
- block, // last object information {scope, element, id}
- nextBlockOrder = [],
- elementsToRemove;
-
-
- if (isArrayLike(collection)) {
- collectionKeys = collection;
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
- } else {
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
- // if object, extract keys, sort them and use to determine order of iteration over obj props
- collectionKeys = [];
- for (key in collection) {
- if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {
- collectionKeys.push(key);
- }
- }
- collectionKeys.sort();
- }
-
- arrayLength = collectionKeys.length;
-
- // locate existing items
- length = nextBlockOrder.length = collectionKeys.length;
- for(index = 0; index < length; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- trackById = trackByIdFn(key, value, index);
- assertNotHasOwnProperty(trackById, '`track by` id');
- if(lastBlockMap.hasOwnProperty(trackById)) {
- block = lastBlockMap[trackById];
- delete lastBlockMap[trackById];
- nextBlockMap[trackById] = block;
- nextBlockOrder[index] = block;
- } else if (nextBlockMap.hasOwnProperty(trackById)) {
- // restore lastBlockMap
- forEach(nextBlockOrder, function(block) {
- if (block && block.scope) lastBlockMap[block.id] = block;
- });
- // This is a duplicate and we need to throw an error
- throw ngRepeatMinErr('dupes',
- "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
- expression, trackById, toJson(value));
- } else {
- // new never before seen block
- nextBlockOrder[index] = { id: trackById };
- nextBlockMap[trackById] = false;
- }
- }
-
- // remove existing items
- for (key in lastBlockMap) {
- // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
- if (lastBlockMap.hasOwnProperty(key)) {
- block = lastBlockMap[key];
- elementsToRemove = getBlockElements(block.clone);
- $animate.leave(elementsToRemove);
- forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
- block.scope.$destroy();
- }
- }
-
- // we are not using forEach for perf reasons (trying to avoid #call)
- for (index = 0, length = collectionKeys.length; index < length; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- block = nextBlockOrder[index];
- if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
-
- if (block.scope) {
- // if we have already seen this object, then we need to reuse the
- // associated scope/element
- childScope = block.scope;
-
- nextNode = previousNode;
- do {
- nextNode = nextNode.nextSibling;
- } while(nextNode && nextNode[NG_REMOVED]);
-
- if (getBlockStart(block) != nextNode) {
- // existing item which got moved
- $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
- }
- previousNode = getBlockEnd(block);
- } else {
- // new item which we don't know about
- childScope = $scope.$new();
- }
-
- childScope[valueIdentifier] = value;
- if (keyIdentifier) childScope[keyIdentifier] = key;
- childScope.$index = index;
- childScope.$first = (index === 0);
- childScope.$last = (index === (arrayLength - 1));
- childScope.$middle = !(childScope.$first || childScope.$last);
- // jshint bitwise: false
- childScope.$odd = !(childScope.$even = (index&1) === 0);
- // jshint bitwise: true
-
- if (!block.scope) {
- $transclude(childScope, function(clone) {
- clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
- $animate.enter(clone, null, jqLite(previousNode));
- previousNode = clone;
- block.scope = childScope;
- // Note: We only need the first/last node of the cloned nodes.
- // However, we need to keep the reference to the jqlite wrapper as it might be changed later
- // by a directive with templateUrl when its template arrives.
- block.clone = clone;
- nextBlockMap[block.id] = block;
- });
- }
- }
- lastBlockMap = nextBlockMap;
- });
- }
- };
-
- function getBlockStart(block) {
- return block.clone[0];
- }
-
- function getBlockEnd(block) {
- return block.clone[block.clone.length - 1];
- }
-}];
-
-/**
- * @ngdoc directive
- * @name ngShow
- *
- * @description
- * The `ngShow` directive shows or hides the given HTML element based on the expression
- * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
- * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```html
- * <!-- when $scope.myValue is truthy (element is visible) -->
- * <div ng-show="myValue"></div>
- *
- * <!-- when $scope.myValue is falsy (element is hidden) -->
- * <div ng-show="myValue" class="ng-hide"></div>
- * ```
- *
- * When the `ngShow` expression evaluates to false then the `.ng-hide` CSS class is added to the class attribute
- * on the element causing it to become hidden. When true, the `.ng-hide` CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * <div class="alert alert-warning">
- * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
- * "f" / "0" / "false" / "no" / "n" / "[]"
- * </div>
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding `.ng-hide`
- *
- * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
- * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
- * class in CSS:
- *
- * ```css
- * .ng-hide {
- * //this is just another form of hiding an element
- * display:block!important;
- * position:absolute;
- * top:-9999px;
- * left:-9999px;
- * }
- * ```
- *
- * By default you don't need to override in CSS anything and the animations will work around the display style.
- *
- * ## A note about animations with `ngShow`
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass except that
- * you must also include the !important flag to override the display property
- * so that you can perform an animation when the element is hidden during the time of the animation.
- *
- * ```css
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- * transition:0.5s linear all;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * ```
- *
- * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
- * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
- *
- * @animations
- * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
- * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
- *
- * @element ANY
- * @param {expression} ngShow If the {@link guide/expression expression} is truthy
- * then the element is shown or hidden respectively.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- Click me: <input type="checkbox" ng-model="checked"><br/>
- <div>
- Show:
- <div class="check-element animate-show" ng-show="checked">
- <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
- </div>
- </div>
- <div>
- Hide:
- <div class="check-element animate-show" ng-hide="checked">
- <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
- </div>
- </div>
- </file>
- <file name="glyphicons.css">
- @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
- </file>
- <file name="animations.css">
- .animate-show {
- -webkit-transition:all linear 0.5s;
- transition:all linear 0.5s;
- line-height:20px;
- opacity:1;
- padding:10px;
- border:1px solid black;
- background:white;
- }
-
- .animate-show.ng-hide {
- line-height:0;
- opacity:0;
- padding:0 10px;
- }
-
- .check-element {
- padding:10px;
- border:1px solid black;
- background:white;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
- var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
-
- it('should check ng-show / ng-hide', function() {
- expect(thumbsUp.isDisplayed()).toBeFalsy();
- expect(thumbsDown.isDisplayed()).toBeTruthy();
-
- element(by.model('checked')).click();
-
- expect(thumbsUp.isDisplayed()).toBeTruthy();
- expect(thumbsDown.isDisplayed()).toBeFalsy();
- });
- </file>
- </example>
- */
-var ngShowDirective = ['$animate', function($animate) {
- return function(scope, element, attr) {
- scope.$watch(attr.ngShow, function ngShowWatchAction(value){
- $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
- });
- };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ngHide
- *
- * @description
- * The `ngHide` directive shows or hides the given HTML element based on the expression
- * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
- * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```html
- * <!-- when $scope.myValue is truthy (element is hidden) -->
- * <div ng-hide="myValue" class="ng-hide"></div>
- *
- * <!-- when $scope.myValue is falsy (element is visible) -->
- * <div ng-hide="myValue"></div>
- * ```
- *
- * When the `.ngHide` expression evaluates to true then the `.ng-hide` CSS class is added to the class attribute
- * on the element causing it to become hidden. When false, the `.ng-hide` CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * <div class="alert alert-warning">
- * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
- * "f" / "0" / "false" / "no" / "n" / "[]"
- * </div>
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding `.ng-hide`
- *
- * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
- * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
- * class in CSS:
- *
- * ```css
- * .ng-hide {
- * //this is just another form of hiding an element
- * display:block!important;
- * position:absolute;
- * top:-9999px;
- * left:-9999px;
- * }
- * ```
- *
- * By default you don't need to override in CSS anything and the animations will work around the display style.
- *
- * ## A note about animations with `ngHide`
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
- * CSS class is added and removed for you instead of your own CSS class.
- *
- * ```css
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- * transition:0.5s linear all;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * ```
- *
- * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
- * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
- *
- * @animations
- * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
- * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
- *
- * @element ANY
- * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
- * the element is shown or hidden respectively.
- *
- * @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- Click me: <input type="checkbox" ng-model="checked"><br/>
- <div>
- Show:
- <div class="check-element animate-hide" ng-show="checked">
- <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
- </div>
- </div>
- <div>
- Hide:
- <div class="check-element animate-hide" ng-hide="checked">
- <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
- </div>
- </div>
- </file>
- <file name="glyphicons.css">
- @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
- </file>
- <file name="animations.css">
- .animate-hide {
- -webkit-transition:all linear 0.5s;
- transition:all linear 0.5s;
- line-height:20px;
- opacity:1;
- padding:10px;
- border:1px solid black;
- background:white;
- }
-
- .animate-hide.ng-hide {
- line-height:0;
- opacity:0;
- padding:0 10px;
- }
-
- .check-element {
- padding:10px;
- border:1px solid black;
- background:white;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
- var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
-
- it('should check ng-show / ng-hide', function() {
- expect(thumbsUp.isDisplayed()).toBeFalsy();
- expect(thumbsDown.isDisplayed()).toBeTruthy();
-
- element(by.model('checked')).click();
-
- expect(thumbsUp.isDisplayed()).toBeTruthy();
- expect(thumbsDown.isDisplayed()).toBeFalsy();
- });
- </file>
- </example>
- */
-var ngHideDirective = ['$animate', function($animate) {
- return function(scope, element, attr) {
- scope.$watch(attr.ngHide, function ngHideWatchAction(value){
- $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
- });
- };
-}];
-
-/**
- * @ngdoc directive
- * @name ngStyle
- * @restrict AC
- *
- * @description
- * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
- *
- * @element ANY
- * @param {expression} ngStyle
- *
- * {@link guide/expression Expression} which evals to an
- * object whose keys are CSS style names and values are corresponding values for those CSS
- * keys.
- *
- * Since some CSS style names are not valid keys for an object, they must be quoted.
- * See the 'background-color' style in the example below.
- *
- * @example
- <example>
- <file name="index.html">
- <input type="button" value="set color" ng-click="myStyle={color:'red'}">
- <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
- <input type="button" value="clear" ng-click="myStyle={}">
- <br/>
- <span ng-style="myStyle">Sample Text</span>
- <pre>myStyle={{myStyle}}</pre>
- </file>
- <file name="style.css">
- span {
- color: black;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var colorSpan = element(by.css('span'));
-
- it('should check ng-style', function() {
- expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
- element(by.css('input[value=\'set color\']')).click();
- expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
- element(by.css('input[value=clear]')).click();
- expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
- });
- </file>
- </example>
- */
-var ngStyleDirective = ngDirective(function(scope, element, attr) {
- scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
- if (oldStyles && (newStyles !== oldStyles)) {
- forEach(oldStyles, function(val, style) { element.css(style, '');});
- }
- if (newStyles) element.css(newStyles);
- }, true);
-});
-
-/**
- * @ngdoc directive
- * @name ngSwitch
- * @restrict EA
- *
- * @description
- * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
- * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
- * as specified in the template.
- *
- * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
- * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
- * matches the value obtained from the evaluated expression. In other words, you define a container element
- * (where you place the directive), place an expression on the **`on="..."` attribute**
- * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
- * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
- * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
- * attribute is displayed.
- *
- * <div class="alert alert-info">
- * Be aware that the attribute values to match against cannot be expressions. They are interpreted
- * as literal string values to match against.
- * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
- * value of the expression `$scope.someVal`.
- * </div>
-
- * @animations
- * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
- * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
- *
- * @usage
- *
- * ```
- * <ANY ng-switch="expression">
- * <ANY ng-switch-when="matchValue1">...</ANY>
- * <ANY ng-switch-when="matchValue2">...</ANY>
- * <ANY ng-switch-default>...</ANY>
- * </ANY>
- * ```
- *
- *
- * @scope
- * @priority 800
- * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
- * On child elements add:
- *
- * * `ngSwitchWhen`: the case statement to match against. If match then this
- * case will be displayed. If the same match appears multiple times, all the
- * elements will be displayed.
- * * `ngSwitchDefault`: the default case when no other case match. If there
- * are multiple default cases, all of them will be displayed when no other
- * case match.
- *
- *
- * @example
- <example module="switchExample" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <select ng-model="selection" ng-options="item for item in items">
- </select>
- <tt>selection={{selection}}</tt>
- <hr/>
- <div class="animate-switch-container"
- ng-switch on="selection">
- <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
- <div class="animate-switch" ng-switch-when="home">Home Span</div>
- <div class="animate-switch" ng-switch-default>default</div>
- </div>
- </div>
- </file>
- <file name="script.js">
- angular.module('switchExample', ['ngAnimate'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.items = ['settings', 'home', 'other'];
- $scope.selection = $scope.items[0];
- }]);
- </file>
- <file name="animations.css">
- .animate-switch-container {
- position:relative;
- background:white;
- border:1px solid black;
- height:40px;
- overflow:hidden;
- }
-
- .animate-switch {
- padding:10px;
- }
-
- .animate-switch.ng-animate {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
- position:absolute;
- top:0;
- left:0;
- right:0;
- bottom:0;
- }
-
- .animate-switch.ng-leave.ng-leave-active,
- .animate-switch.ng-enter {
- top:-50px;
- }
- .animate-switch.ng-leave,
- .animate-switch.ng-enter.ng-enter-active {
- top:0;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var switchElem = element(by.css('[ng-switch]'));
- var select = element(by.model('selection'));
-
- it('should start in settings', function() {
- expect(switchElem.getText()).toMatch(/Settings Div/);
- });
- it('should change to home', function() {
- select.all(by.css('option')).get(1).click();
- expect(switchElem.getText()).toMatch(/Home Span/);
- });
- it('should select default', function() {
- select.all(by.css('option')).get(2).click();
- expect(switchElem.getText()).toMatch(/default/);
- });
- </file>
- </example>
- */
-var ngSwitchDirective = ['$animate', function($animate) {
- return {
- restrict: 'EA',
- require: 'ngSwitch',
-
- // asks for $scope to fool the BC controller module
- controller: ['$scope', function ngSwitchController() {
- this.cases = {};
- }],
- link: function(scope, element, attr, ngSwitchController) {
- var watchExpr = attr.ngSwitch || attr.on,
- selectedTranscludes = [],
- selectedElements = [],
- previousElements = [],
- selectedScopes = [];
-
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
- var i, ii;
- for (i = 0, ii = previousElements.length; i < ii; ++i) {
- previousElements[i].remove();
- }
- previousElements.length = 0;
-
- for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
- var selected = selectedElements[i];
- selectedScopes[i].$destroy();
- previousElements[i] = selected;
- $animate.leave(selected, function() {
- previousElements.splice(i, 1);
- });
- }
-
- selectedElements.length = 0;
- selectedScopes.length = 0;
-
- if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
- scope.$eval(attr.change);
- forEach(selectedTranscludes, function(selectedTransclude) {
- var selectedScope = scope.$new();
- selectedScopes.push(selectedScope);
- selectedTransclude.transclude(selectedScope, function(caseElement) {
- var anchor = selectedTransclude.element;
-
- selectedElements.push(caseElement);
- $animate.enter(caseElement, anchor.parent(), anchor);
- });
- });
- }
- });
- }
- };
-}];
-
-var ngSwitchWhenDirective = ngDirective({
- transclude: 'element',
- priority: 800,
- require: '^ngSwitch',
- link: function(scope, element, attrs, ctrl, $transclude) {
- ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
- ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
- }
-});
-
-var ngSwitchDefaultDirective = ngDirective({
- transclude: 'element',
- priority: 800,
- require: '^ngSwitch',
- link: function(scope, element, attr, ctrl, $transclude) {
- ctrl.cases['?'] = (ctrl.cases['?'] || []);
- ctrl.cases['?'].push({ transclude: $transclude, element: element });
- }
-});
-
-/**
- * @ngdoc directive
- * @name ngTransclude
- * @restrict AC
- *
- * @description
- * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
- *
- * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
- *
- * @element ANY
- *
- * @example
- <example module="transcludeExample">
- <file name="index.html">
- <script>
- angular.module('transcludeExample', [])
- .directive('pane', function(){
- return {
- restrict: 'E',
- transclude: true,
- scope: { title:'@' },
- template: '<div style="border: 1px solid black;">' +
- '<div style="background-color: gray">{{title}}</div>' +
- '<div ng-transclude></div>' +
- '</div>'
- };
- })
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.title = 'Lorem Ipsum';
- $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input ng-model="title"><br>
- <textarea ng-model="text"></textarea> <br/>
- <pane title="{{title}}">{{text}}</pane>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should have transcluded', function() {
- var titleElement = element(by.model('title'));
- titleElement.clear();
- titleElement.sendKeys('TITLE');
- var textElement = element(by.model('text'));
- textElement.clear();
- textElement.sendKeys('TEXT');
- expect(element(by.binding('title')).getText()).toEqual('TITLE');
- expect(element(by.binding('text')).getText()).toEqual('TEXT');
- });
- </file>
- </example>
- *
- */
-var ngTranscludeDirective = ngDirective({
- link: function($scope, $element, $attrs, controller, $transclude) {
- if (!$transclude) {
- throw minErr('ngTransclude')('orphan',
- 'Illegal use of ngTransclude directive in the template! ' +
- 'No parent directive that requires a transclusion found. ' +
- 'Element: {0}',
- startingTag($element));
- }
-
- $transclude(function(clone) {
- $element.empty();
- $element.append(clone);
- });
- }
-});
-
-/**
- * @ngdoc directive
- * @name script
- * @restrict E
- *
- * @description
- * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
- * template can be used by {@link ng.directive:ngInclude `ngInclude`},
- * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
- * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
- * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
- *
- * @param {string} type Must be set to `'text/ng-template'`.
- * @param {string} id Cache name of the template.
- *
- * @example
- <example>
- <file name="index.html">
- <script type="text/ng-template" id="/tpl.html">
- Content of the template.
- </script>
-
- <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
- <div id="tpl-content" ng-include src="currentTpl"></div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should load template defined inside script tag', function() {
- element(by.css('#tpl-link')).click();
- expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
- });
- </file>
- </example>
- */
-var scriptDirective = ['$templateCache', function($templateCache) {
- return {
- restrict: 'E',
- terminal: true,
- compile: function(element, attr) {
- if (attr.type == 'text/ng-template') {
- var templateUrl = attr.id,
- // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent
- text = element[0].text;
-
- $templateCache.put(templateUrl, text);
- }
- }
- };
-}];
-
-var ngOptionsMinErr = minErr('ngOptions');
-/**
- * @ngdoc directive
- * @name select
- * @restrict E
- *
- * @description
- * HTML `SELECT` element with angular data-binding.
- *
- * # `ngOptions`
- *
- * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
- * elements for the `<select>` element using the array or object obtained by evaluating the
- * `ngOptions` comprehension_expression.
- *
- * When an item in the `<select>` menu is selected, the array element or object property
- * represented by the selected option will be bound to the model identified by the `ngModel`
- * directive.
- *
- * <div class="alert alert-warning">
- * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
- * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
- * </div>
- *
- * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
- * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
- * option. See example below for demonstration.
- *
- * <div class="alert alert-warning">
- * **Note:** `ngOptions` provides an iterator facility for the `<option>` element which should be used instead
- * of {@link ng.directive:ngRepeat ngRepeat} when you want the
- * `select` model to be bound to a non-string value. This is because an option element can only
- * be bound to string values at present.
- * </div>
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required The control is considered valid only if value is entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- * `required` when you want to data-bind to the `required` attribute.
- * @param {comprehension_expression=} ngOptions in one of the following forms:
- *
- * * for array data sources:
- * * `label` **`for`** `value` **`in`** `array`
- * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
- * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
- * * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
- * * for object data sources:
- * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
- * * `select` **`as`** `label` **`group by`** `group`
- * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
- *
- * Where:
- *
- * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
- * * `value`: local variable which will refer to each item in the `array` or each property value
- * of `object` during iteration.
- * * `key`: local variable which will refer to a property name in `object` during iteration.
- * * `label`: The result of this expression will be the label for `<option>` element. The
- * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
- * * `select`: The result of this expression will be bound to the model of the parent `<select>`
- * element. If not specified, `select` expression will default to `value`.
- * * `group`: The result of this expression will be used to group options using the `<optgroup>`
- * DOM element.
- * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
- * used to identify the objects in the array. The `trackexpr` will most likely refer to the
- * `value` variable (e.g. `value.propertyName`).
- *
- * @example
- <example module="selectExample">
- <file name="index.html">
- <script>
- angular.module('selectExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.colors = [
- {name:'black', shade:'dark'},
- {name:'white', shade:'light'},
- {name:'red', shade:'dark'},
- {name:'blue', shade:'dark'},
- {name:'yellow', shade:'light'}
- ];
- $scope.myColor = $scope.colors[2]; // red
- }]);
- </script>
- <div ng-controller="ExampleController">
- <ul>
- <li ng-repeat="color in colors">
- Name: <input ng-model="color.name">
- [<a href ng-click="colors.splice($index, 1)">X</a>]
- </li>
- <li>
- [<a href ng-click="colors.push({})">add</a>]
- </li>
- </ul>
- <hr/>
- Color (null not allowed):
- <select ng-model="myColor" ng-options="color.name for color in colors"></select><br>
-
- Color (null allowed):
- <span class="nullable">
- <select ng-model="myColor" ng-options="color.name for color in colors">
- <option value="">-- choose color --</option>
- </select>
- </span><br/>
-
- Color grouped by shade:
- <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
- </select><br/>
-
-
- Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
- <hr/>
- Currently selected: {{ {selected_color:myColor} }}
- <div style="border:solid 1px black; height:20px"
- ng-style="{'background-color':myColor.name}">
- </div>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-options', function() {
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
- element.all(by.model('myColor')).first().click();
- element.all(by.css('select[ng-model="myColor"] option')).first().click();
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
- element(by.css('.nullable select[ng-model="myColor"]')).click();
- element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
- expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
- });
- </file>
- </example>
- */
-
-var ngOptionsDirective = valueFn({ terminal: true });
-// jshint maxlen: false
-var selectDirective = ['$compile', '$parse', function($compile, $parse) {
- //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
- var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
- nullModelCtrl = {$setViewValue: noop};
-// jshint maxlen: 100
-
- return {
- restrict: 'E',
- require: ['select', '?ngModel'],
- controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
- var self = this,
- optionsMap = {},
- ngModelCtrl = nullModelCtrl,
- nullOption,
- unknownOption;
-
-
- self.databound = $attrs.ngModel;
-
-
- self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
- ngModelCtrl = ngModelCtrl_;
- nullOption = nullOption_;
- unknownOption = unknownOption_;
- };
-
-
- self.addOption = function(value) {
- assertNotHasOwnProperty(value, '"option value"');
- optionsMap[value] = true;
-
- if (ngModelCtrl.$viewValue == value) {
- $element.val(value);
- if (unknownOption.parent()) unknownOption.remove();
- }
- };
-
-
- self.removeOption = function(value) {
- if (this.hasOption(value)) {
- delete optionsMap[value];
- if (ngModelCtrl.$viewValue == value) {
- this.renderUnknownOption(value);
- }
- }
- };
-
-
- self.renderUnknownOption = function(val) {
- var unknownVal = '? ' + hashKey(val) + ' ?';
- unknownOption.val(unknownVal);
- $element.prepend(unknownOption);
- $element.val(unknownVal);
- unknownOption.prop('selected', true); // needed for IE
- };
-
-
- self.hasOption = function(value) {
- return optionsMap.hasOwnProperty(value);
- };
-
- $scope.$on('$destroy', function() {
- // disable unknown option so that we don't do work when the whole select is being destroyed
- self.renderUnknownOption = noop;
- });
- }],
-
- link: function(scope, element, attr, ctrls) {
- // if ngModel is not defined, we don't need to do anything
- if (!ctrls[1]) return;
-
- var selectCtrl = ctrls[0],
- ngModelCtrl = ctrls[1],
- multiple = attr.multiple,
- optionsExp = attr.ngOptions,
- nullOption = false, // if false, user will not be able to select it (used by ngOptions)
- emptyOption,
- // we can't just jqLite('<option>') since jqLite is not smart enough
- // to create it in <select> and IE barfs otherwise.
- optionTemplate = jqLite(document.createElement('option')),
- optGroupTemplate =jqLite(document.createElement('optgroup')),
- unknownOption = optionTemplate.clone();
-
- // find "null" option
- for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
- if (children[i].value === '') {
- emptyOption = nullOption = children.eq(i);
- break;
- }
- }
-
- selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
-
- // required validator
- if (multiple) {
- ngModelCtrl.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
- }
-
- if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
- else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
- else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
-
-
- ////////////////////////////
-
-
-
- function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
- ngModelCtrl.$render = function() {
- var viewValue = ngModelCtrl.$viewValue;
-
- if (selectCtrl.hasOption(viewValue)) {
- if (unknownOption.parent()) unknownOption.remove();
- selectElement.val(viewValue);
- if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
- } else {
- if (isUndefined(viewValue) && emptyOption) {
- selectElement.val('');
- } else {
- selectCtrl.renderUnknownOption(viewValue);
- }
- }
- };
-
- selectElement.on('change', function() {
- scope.$apply(function() {
- if (unknownOption.parent()) unknownOption.remove();
- ngModelCtrl.$setViewValue(selectElement.val());
- });
- });
- }
-
- function setupAsMultiple(scope, selectElement, ctrl) {
- var lastView;
- ctrl.$render = function() {
- var items = new HashMap(ctrl.$viewValue);
- forEach(selectElement.find('option'), function(option) {
- option.selected = isDefined(items.get(option.value));
- });
- };
-
- // we have to do it on each watch since ngModel watches reference, but
- // we need to work of an array, so we need to see if anything was inserted/removed
- scope.$watch(function selectMultipleWatch() {
- if (!equals(lastView, ctrl.$viewValue)) {
- lastView = shallowCopy(ctrl.$viewValue);
- ctrl.$render();
- }
- });
-
- selectElement.on('change', function() {
- scope.$apply(function() {
- var array = [];
- forEach(selectElement.find('option'), function(option) {
- if (option.selected) {
- array.push(option.value);
- }
- });
- ctrl.$setViewValue(array);
- });
- });
- }
-
- function setupAsOptions(scope, selectElement, ctrl) {
- var match;
-
- if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {
- throw ngOptionsMinErr('iexp',
- "Expected expression in form of " +
- "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
- " but got '{0}'. Element: {1}",
- optionsExp, startingTag(selectElement));
- }
-
- var displayFn = $parse(match[2] || match[1]),
- valueName = match[4] || match[6],
- keyName = match[5],
- groupByFn = $parse(match[3] || ''),
- valueFn = $parse(match[2] ? match[1] : valueName),
- valuesFn = $parse(match[7]),
- track = match[8],
- trackFn = track ? $parse(match[8]) : null,
- // This is an array of array of existing option groups in DOM.
- // We try to reuse these if possible
- // - optionGroupsCache[0] is the options with no option group
- // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
- optionGroupsCache = [[{element: selectElement, label:''}]];
-
- if (nullOption) {
- // compile the element since there might be bindings in it
- $compile(nullOption)(scope);
-
- // remove the class, which is added automatically because we recompile the element and it
- // becomes the compilation root
- nullOption.removeClass('ng-scope');
-
- // we need to remove it before calling selectElement.empty() because otherwise IE will
- // remove the label from the element. wtf?
- nullOption.remove();
- }
-
- // clear contents, we'll add what's needed based on the model
- selectElement.empty();
-
- selectElement.on('change', function() {
- scope.$apply(function() {
- var optionGroup,
- collection = valuesFn(scope) || [],
- locals = {},
- key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;
-
- if (multiple) {
- value = [];
- for (groupIndex = 0, groupLength = optionGroupsCache.length;
- groupIndex < groupLength;
- groupIndex++) {
- // list of options for that group. (first item has the parent)
- optionGroup = optionGroupsCache[groupIndex];
-
- for(index = 1, length = optionGroup.length; index < length; index++) {
- if ((optionElement = optionGroup[index].element)[0].selected) {
- key = optionElement.val();
- if (keyName) locals[keyName] = key;
- if (trackFn) {
- for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
- locals[valueName] = collection[trackIndex];
- if (trackFn(scope, locals) == key) break;
- }
- } else {
- locals[valueName] = collection[key];
- }
- value.push(valueFn(scope, locals));
- }
- }
- }
- } else {
- key = selectElement.val();
- if (key == '?') {
- value = undefined;
- } else if (key === ''){
- value = null;
- } else {
- if (trackFn) {
- for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
- locals[valueName] = collection[trackIndex];
- if (trackFn(scope, locals) == key) {
- value = valueFn(scope, locals);
- break;
- }
- }
- } else {
- locals[valueName] = collection[key];
- if (keyName) locals[keyName] = key;
- value = valueFn(scope, locals);
- }
- }
- }
- ctrl.$setViewValue(value);
- render();
- });
- });
-
- ctrl.$render = render;
-
- scope.$watchCollection(valuesFn, render);
- scope.$watchCollection(function () {
- var locals = {},
- values = valuesFn(scope);
- if (values) {
- var toDisplay = new Array(values.length);
- for (var i = 0, ii = values.length; i < ii; i++) {
- locals[valueName] = values[i];
- toDisplay[i] = displayFn(scope, locals);
- }
- return toDisplay;
- }
- }, render);
-
- if ( multiple ) {
- scope.$watchCollection(function() { return ctrl.$modelValue; }, render);
- }
-
- function getSelectedSet() {
- var selectedSet = false;
- if (multiple) {
- var modelValue = ctrl.$modelValue;
- if (trackFn && isArray(modelValue)) {
- selectedSet = new HashMap([]);
- var locals = {};
- for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
- locals[valueName] = modelValue[trackIndex];
- selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
- }
- } else {
- selectedSet = new HashMap(modelValue);
- }
- }
- return selectedSet;
- }
-
-
- function render() {
- // Temporary location for the option groups before we render them
- var optionGroups = {'':[]},
- optionGroupNames = [''],
- optionGroupName,
- optionGroup,
- option,
- existingParent, existingOptions, existingOption,
- modelValue = ctrl.$modelValue,
- values = valuesFn(scope) || [],
- keys = keyName ? sortedKeys(values) : values,
- key,
- groupLength, length,
- groupIndex, index,
- locals = {},
- selected,
- selectedSet = getSelectedSet(),
- lastElement,
- element,
- label;
-
-
- // We now build up the list of options we need (we merge later)
- for (index = 0; length = keys.length, index < length; index++) {
-
- key = index;
- if (keyName) {
- key = keys[index];
- if ( key.charAt(0) === '$' ) continue;
- locals[keyName] = key;
- }
-
- locals[valueName] = values[key];
-
- optionGroupName = groupByFn(scope, locals) || '';
- if (!(optionGroup = optionGroups[optionGroupName])) {
- optionGroup = optionGroups[optionGroupName] = [];
- optionGroupNames.push(optionGroupName);
- }
- if (multiple) {
- selected = isDefined(
- selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))
- );
- } else {
- if (trackFn) {
- var modelCast = {};
- modelCast[valueName] = modelValue;
- selected = trackFn(scope, modelCast) === trackFn(scope, locals);
- } else {
- selected = modelValue === valueFn(scope, locals);
- }
- selectedSet = selectedSet || selected; // see if at least one item is selected
- }
- label = displayFn(scope, locals); // what will be seen by the user
-
- // doing displayFn(scope, locals) || '' overwrites zero values
- label = isDefined(label) ? label : '';
- optionGroup.push({
- // either the index into array or key from object
- id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),
- label: label,
- selected: selected // determine if we should be selected
- });
- }
- if (!multiple) {
- if (nullOption || modelValue === null) {
- // insert null option if we have a placeholder, or the model is null
- optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
- } else if (!selectedSet) {
- // option could not be found, we have to insert the undefined item
- optionGroups[''].unshift({id:'?', label:'', selected:true});
- }
- }
-
- // Now we need to update the list of DOM nodes to match the optionGroups we computed above
- for (groupIndex = 0, groupLength = optionGroupNames.length;
- groupIndex < groupLength;
- groupIndex++) {
- // current option group name or '' if no group
- optionGroupName = optionGroupNames[groupIndex];
-
- // list of options for that group. (first item has the parent)
- optionGroup = optionGroups[optionGroupName];
-
- if (optionGroupsCache.length <= groupIndex) {
- // we need to grow the optionGroups
- existingParent = {
- element: optGroupTemplate.clone().attr('label', optionGroupName),
- label: optionGroup.label
- };
- existingOptions = [existingParent];
- optionGroupsCache.push(existingOptions);
- selectElement.append(existingParent.element);
- } else {
- existingOptions = optionGroupsCache[groupIndex];
- existingParent = existingOptions[0]; // either SELECT (no group) or OPTGROUP element
-
- // update the OPTGROUP label if not the same.
- if (existingParent.label != optionGroupName) {
- existingParent.element.attr('label', existingParent.label = optionGroupName);
- }
- }
-
- lastElement = null; // start at the beginning
- for(index = 0, length = optionGroup.length; index < length; index++) {
- option = optionGroup[index];
- if ((existingOption = existingOptions[index+1])) {
- // reuse elements
- lastElement = existingOption.element;
- if (existingOption.label !== option.label) {
- lastElement.text(existingOption.label = option.label);
- }
- if (existingOption.id !== option.id) {
- lastElement.val(existingOption.id = option.id);
- }
- // lastElement.prop('selected') provided by jQuery has side-effects
- if (lastElement[0].selected !== option.selected) {
- lastElement.prop('selected', (existingOption.selected = option.selected));
- if (msie) {
- // See #7692
- // The selected item wouldn't visually update on IE without this.
- // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well
- lastElement.prop('selected', existingOption.selected);
- }
- }
- } else {
- // grow elements
-
- // if it's a null option
- if (option.id === '' && nullOption) {
- // put back the pre-compiled element
- element = nullOption;
- } else {
- // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but
- // in this version of jQuery on some browser the .text() returns a string
- // rather then the element.
- (element = optionTemplate.clone())
- .val(option.id)
- .prop('selected', option.selected)
- .attr('selected', option.selected)
- .text(option.label);
- }
-
- existingOptions.push(existingOption = {
- element: element,
- label: option.label,
- id: option.id,
- selected: option.selected
- });
- if (lastElement) {
- lastElement.after(element);
- } else {
- existingParent.element.append(element);
- }
- lastElement = element;
- }
- }
- // remove any excessive OPTIONs in a group
- index++; // increment since the existingOptions[0] is parent element not OPTION
- while(existingOptions.length > index) {
- existingOptions.pop().element.remove();
- }
- }
- // remove any excessive OPTGROUPs from select
- while(optionGroupsCache.length > groupIndex) {
- optionGroupsCache.pop()[0].element.remove();
- }
- }
- }
- }
- };
-}];
-
-var optionDirective = ['$interpolate', function($interpolate) {
- var nullSelectCtrl = {
- addOption: noop,
- removeOption: noop
- };
-
- return {
- restrict: 'E',
- priority: 100,
- compile: function(element, attr) {
- if (isUndefined(attr.value)) {
- var interpolateFn = $interpolate(element.text(), true);
- if (!interpolateFn) {
- attr.$set('value', element.text());
- }
- }
-
- return function (scope, element, attr) {
- var selectCtrlName = '$selectController',
- parent = element.parent(),
- selectCtrl = parent.data(selectCtrlName) ||
- parent.parent().data(selectCtrlName); // in case we are in optgroup
-
- if (selectCtrl && selectCtrl.databound) {
- // For some reason Opera defaults to true and if not overridden this messes up the repeater.
- // We don't want the view to drive the initialization of the model anyway.
- element.prop('selected', false);
- } else {
- selectCtrl = nullSelectCtrl;
- }
-
- if (interpolateFn) {
- scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
- attr.$set('value', newVal);
- if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
- selectCtrl.addOption(newVal);
- });
- } else {
- selectCtrl.addOption(attr.value);
- }
-
- element.on('$destroy', function() {
- selectCtrl.removeOption(attr.value);
- });
- };
- }
- };
-}];
-
-var styleDirective = valueFn({
- restrict: 'E',
- terminal: true
-});
-
- if (window.angular.bootstrap) {
- //AngularJS is already loaded, so we can return here...
- console.log('WARNING: Tried to load angular more than once.');
- return;
- }
-
- //try to bind to jquery now so that one can write angular.element().read()
- //but we will rebind on bootstrap again.
- bindJQuery();
-
- publishExternalAPI(angular);
-
- jqLite(document).ready(function() {
- angularInit(document, bootstrap);
- });
-
-})(window, document);
-
-!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>'); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/app.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/app.js
deleted file mode 100644
index a403b5b5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/app.js
+++ /dev/null
@@ -1,6 +0,0 @@
-angular.module('att.abs.helper', []);
-angular.module('quantum', []);
-angular.module('ui.bootstrap', []);
-var app=angular.module("abs", ["att.abs", "att.abs.helper","modalServices",
- "att.gridster","checklist-model","ngRoute", "ui.bootstrap","ngCookies"]);
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.js
deleted file mode 100644
index 09d8cefb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Checklist-model
- * AngularJS directive for list of checkboxes
- */
-
-angular.module('checklist-model', [])
-.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
- // contains
- function contains(arr, item) {
- if (angular.isArray(arr)) {
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- return true;
- }
- }
- }
- return false;
- }
-
- // add
- function add(arr, item) {
- arr = angular.isArray(arr) ? arr : [];
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- return arr;
- }
- }
- arr.push(item);
- return arr;
- }
-
- // remove
- function remove(arr, item) {
- if (angular.isArray(arr)) {
- for (var i = 0; i < arr.length; i++) {
- if (angular.equals(arr[i], item)) {
- arr.splice(i, 1);
- break;
- }
- }
- }
- return arr;
- }
-
- // http://stackoverflow.com/a/19228302/1458162
- function postLinkFn(scope, elem, attrs) {
- // compile with `ng-model` pointing to `checked`
- $compile(elem)(scope);
-
- // getter / setter for original model
- var getter = $parse(attrs.checklistModel);
- var setter = getter.assign;
-
- // value added to list
- var value = $parse(attrs.checklistValue)(scope.$parent);
-
- // watch UI checked change
- scope.$watch('checked', function(newValue, oldValue) {
- if (newValue === oldValue) {
- return;
- }
- var current = getter(scope.$parent);
- if (newValue === true) {
- setter(scope.$parent, add(current, value));
- } else {
- setter(scope.$parent, remove(current, value));
- }
- });
-
- // watch original model change
- scope.$parent.$watch(attrs.checklistModel, function(newArr, oldArr) {
- scope.checked = contains(newArr, value);
- }, true);
- }
-
- return {
- restrict: 'A',
- priority: 1000,
- terminal: true,
- scope: true,
- compile: function(tElement, tAttrs) {
- if (tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') {
- throw 'checklist-model should be applied to `input[type="checkbox"]`.';
- }
-
- if (!tAttrs.checklistValue) {
- throw 'You should provide `checklist-value`.';
- }
-
- // exclude recursion
- tElement.removeAttr('checklist-model');
-
- // local scope var storing individual checkbox model
- tElement.attr('ng-model', 'checked');
-
- return postLinkFn;
- }
- };
-}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.min.js
deleted file mode 100644
index 61be598e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/checklist-model.min.js
+++ /dev/null
@@ -1 +0,0 @@
-angular.module("checklist-model",[]).directive("checklistModel",["$parse","$compile",function(e,c){function b(g,j){if(angular.isArray(g)){for(var h=0;h<g.length;h++){if(angular.equals(g[h],j)){return true}}}return false}function f(g,j){g=angular.isArray(g)?g:[];for(var h=0;h<g.length;h++){if(angular.equals(g[h],j)){return g}}g.push(j);return g}function a(g,j){if(angular.isArray(g)){for(var h=0;h<g.length;h++){if(angular.equals(g[h],j)){g.splice(h,1);break}}}return g}function d(i,j,h){c(j)(i);var g=e(h.checklistModel);var l=g.assign;var k=e(h.checklistValue)(i.$parent);i.$watch("checked",function(o,m){if(o===m){return}var n=g(i.$parent);if(o===true){l(i.$parent,f(n,k))}else{l(i.$parent,a(n,k))}});i.$parent.$watch(h.checklistModel,function(n,m){i.checked=b(n,k)},true)}return{restrict:"A",priority:1000,terminal:true,scope:true,compile:function(g,h){if(g[0].tagName!=="INPUT"||!g.attr("type","checkbox")){throw'checklist-model should be applied to `input[type="checkbox"]`.'}if(!h.checklistValue){throw"You should provide `checklist-value`."}g.removeAttr("checklist-model");g.attr("ng-model","checked");return d}}}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/gestures.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/gestures.js
deleted file mode 100644
index 8c515d8a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/gestures.js
+++ /dev/null
@@ -1,1495 +0,0 @@
-/*! Hammer.JS - v1.0.5 - 2013-04-07
- * http://eightmedia.github.com/hammer.js
- *
- * Copyright (c) 2013 Jorik Tangelder <j.tangelder@gmail.com>;
- * Licensed under the MIT license */
-
-(function(window, undefined) {
- 'use strict';
-
-/**
- * Hammer
- * use this to create instances
- * @param {HTMLElement} element
- * @param {Object} options
- * @returns {Hammer.Instance}
- * @constructor
- */
-var Hammer = function(element, options) {
- return new Hammer.Instance(element, options || {});
-};
-
-// default settings
-Hammer.defaults = {
- // add styles and attributes to the element to prevent the browser from doing
- // its native behavior. this doesnt prevent the scrolling, but cancels
- // the contextmenu, tap highlighting etc
- // set to false to disable this
- stop_browser_behavior: {
- // this also triggers onselectstart=false for IE
- userSelect: 'none',
- // this makes the element blocking in IE10 >, you could experiment with the value
- // see for more options this issue; https://github.com/EightMedia/hammer.js/issues/241
- touchAction: 'none',
- touchCallout: 'none',
- contentZooming: 'none',
- userDrag: 'none',
- tapHighlightColor: 'rgba(0,0,0,0)'
- }
-
- // more settings are defined per gesture at gestures.js
-};
-
-// detect touchevents
-Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;
-Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);
-
-// dont use mouseevents on mobile devices
-Hammer.MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
-Hammer.NO_MOUSEEVENTS = Hammer.HAS_TOUCHEVENTS && navigator.userAgent.match(Hammer.MOBILE_REGEX);
-
-// eventtypes per touchevent (start, move, end)
-// are filled by Hammer.event.determineEventTypes on setup
-Hammer.EVENT_TYPES = {};
-
-// direction defines
-Hammer.DIRECTION_DOWN = 'down';
-Hammer.DIRECTION_LEFT = 'left';
-Hammer.DIRECTION_UP = 'up';
-Hammer.DIRECTION_RIGHT = 'right';
-
-// pointer type
-Hammer.POINTER_MOUSE = 'mouse';
-Hammer.POINTER_TOUCH = 'touch';
-Hammer.POINTER_PEN = 'pen';
-
-// touch event defines
-Hammer.EVENT_START = 'start';
-Hammer.EVENT_MOVE = 'move';
-Hammer.EVENT_END = 'end';
-
-// hammer document where the base events are added at
-Hammer.DOCUMENT = document;
-
-// plugins namespace
-Hammer.plugins = {};
-
-// if the window events are set...
-Hammer.READY = false;
-
-/**
- * setup events to detect gestures on the document
- */
-function setup() {
- if(Hammer.READY) {
- return;
- }
-
- // find what eventtypes we add listeners to
- Hammer.event.determineEventTypes();
-
- // Register all gestures inside Hammer.gestures
- for(var name in Hammer.gestures) {
- if(Hammer.gestures.hasOwnProperty(name)) {
- Hammer.detection.register(Hammer.gestures[name]);
- }
- }
-
- // Add touch events on the document
- Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_MOVE, Hammer.detection.detect);
- Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_END, Hammer.detection.detect);
-
- // Hammer is ready...!
- Hammer.READY = true;
-}
-
-/**
- * create new hammer instance
- * all methods should return the instance itself, so it is chainable.
- * @param {HTMLElement} element
- * @param {Object} [options={}]
- * @returns {Hammer.Instance}
- * @constructor
- */
-Hammer.Instance = function(element, options) {
- var self = this;
-
- // setup HammerJS window events and register all gestures
- // this also sets up the default options
- setup();
-
- this.element = element;
-
- // start/stop detection option
- this.enabled = true;
-
- // merge options
- this.options = Hammer.utils.extend(
- Hammer.utils.extend({}, Hammer.defaults),
- options || {});
-
- // add some css to the element to prevent the browser from doing its native behavoir
- if(this.options.stop_browser_behavior) {
- Hammer.utils.stopDefaultBrowserBehavior(this.element, this.options.stop_browser_behavior);
- }
-
- // start detection on touchstart
- Hammer.event.onTouch(element, Hammer.EVENT_START, function(ev) {
- if(self.enabled) {
- Hammer.detection.startDetect(self, ev);
- }
- });
-
- // return instance
- return this;
-};
-
-
-Hammer.Instance.prototype = {
- /**
- * bind events to the instance
- * @param {String} gesture
- * @param {Function} handler
- * @returns {Hammer.Instance}
- */
- on: function onEvent(gesture, handler){
- var gestures = gesture.split(' ');
- for(var t=0; t<gestures.length; t++) {
- this.element.addEventListener(gestures[t], handler, false);
- }
- return this;
- },
-
-
- /**
- * unbind events to the instance
- * @param {String} gesture
- * @param {Function} handler
- * @returns {Hammer.Instance}
- */
- off: function offEvent(gesture, handler){
- var gestures = gesture.split(' ');
- for(var t=0; t<gestures.length; t++) {
- this.element.removeEventListener(gestures[t], handler, false);
- }
- return this;
- },
-
-
- /**
- * trigger gesture event
- * @param {String} gesture
- * @param {Object} eventData
- * @returns {Hammer.Instance}
- */
- trigger: function triggerEvent(gesture, eventData){
- // create DOM event
- var event = Hammer.DOCUMENT.createEvent('Event');
- event.initEvent(gesture, true, true);
- event.gesture = eventData;
-
- // trigger on the target if it is in the instance element,
- // this is for event delegation tricks
- var element = this.element;
- if(Hammer.utils.hasParent(eventData.target, element)) {
- element = eventData.target;
- }
-
- element.dispatchEvent(event);
- return this;
- },
-
-
- /**
- * enable of disable hammer.js detection
- * @param {Boolean} state
- * @returns {Hammer.Instance}
- */
- enable: function enable(state) {
- this.enabled = state;
- return this;
- }
-};
-
-/**
- * this holds the last move event,
- * used to fix empty touchend issue
- * see the onTouch event for an explanation
- * @type {Object}
- */
-var last_move_event = null;
-
-
-/**
- * when the mouse is hold down, this is true
- * @type {Boolean}
- */
-var enable_detect = false;
-
-
-/**
- * when touch events have been fired, this is true
- * @type {Boolean}
- */
-var touch_triggered = false;
-
-
-Hammer.event = {
- /**
- * simple addEventListener
- * @param {HTMLElement} element
- * @param {String} type
- * @param {Function} handler
- */
- bindDom: function(element, type, handler) {
- var types = type.split(' ');
- for(var t=0; t<types.length; t++) {
- element.addEventListener(types[t], handler, false);
- }
- },
-
-
- /**
- * touch events with mouse fallback
- * @param {HTMLElement} element
- * @param {String} eventType like Hammer.EVENT_MOVE
- * @param {Function} handler
- */
- onTouch: function onTouch(element, eventType, handler) {
- var self = this;
-
- this.bindDom(element, Hammer.EVENT_TYPES[eventType], function bindDomOnTouch(ev) {
- var sourceEventType = ev.type.toLowerCase();
-
- // onmouseup, but when touchend has been fired we do nothing.
- // this is for touchdevices which also fire a mouseup on touchend
- if(sourceEventType.match(/mouse/) && touch_triggered) {
- return;
- }
-
- // mousebutton must be down or a touch event
- else if( sourceEventType.match(/touch/) || // touch events are always on screen
- sourceEventType.match(/pointerdown/) || // pointerevents touch
- (sourceEventType.match(/mouse/) && ev.which === 1) // mouse is pressed
- ){
- enable_detect = true;
- }
-
- // we are in a touch event, set the touch triggered bool to true,
- // this for the conflicts that may occur on ios and android
- if(sourceEventType.match(/touch|pointer/)) {
- touch_triggered = true;
- }
-
- // count the total touches on the screen
- var count_touches = 0;
-
- // when touch has been triggered in this detection session
- // and we are now handling a mouse event, we stop that to prevent conflicts
- if(enable_detect) {
- // update pointerevent
- if(Hammer.HAS_POINTEREVENTS && eventType != Hammer.EVENT_END) {
- count_touches = Hammer.PointerEvent.updatePointer(eventType, ev);
- }
- // touch
- else if(sourceEventType.match(/touch/)) {
- count_touches = ev.touches.length;
- }
- // mouse
- else if(!touch_triggered) {
- count_touches = sourceEventType.match(/up/) ? 0 : 1;
- }
-
- // if we are in a end event, but when we remove one touch and
- // we still have enough, set eventType to move
- if(count_touches > 0 && eventType == Hammer.EVENT_END) {
- eventType = Hammer.EVENT_MOVE;
- }
- // no touches, force the end event
- else if(!count_touches) {
- eventType = Hammer.EVENT_END;
- }
-
- // because touchend has no touches, and we often want to use these in our gestures,
- // we send the last move event as our eventData in touchend
- if(!count_touches && last_move_event !== null) {
- ev = last_move_event;
- }
- // store the last move event
- else {
- last_move_event = ev;
- }
-
- // trigger the handler
- handler.call(Hammer.detection, self.collectEventData(element, eventType, ev));
-
- // remove pointerevent from list
- if(Hammer.HAS_POINTEREVENTS && eventType == Hammer.EVENT_END) {
- count_touches = Hammer.PointerEvent.updatePointer(eventType, ev);
- }
- }
-
- //debug(sourceEventType +" "+ eventType);
-
- // on the end we reset everything
- if(!count_touches) {
- last_move_event = null;
- enable_detect = false;
- touch_triggered = false;
- Hammer.PointerEvent.reset();
- }
- });
- },
-
-
- /**
- * we have different events for each device/browser
- * determine what we need and set them in the Hammer.EVENT_TYPES constant
- */
- determineEventTypes: function determineEventTypes() {
- // determine the eventtype we want to set
- var types;
-
- // pointerEvents magic
- if(Hammer.HAS_POINTEREVENTS) {
- types = Hammer.PointerEvent.getEvents();
- }
- // on Android, iOS, blackberry, windows mobile we dont want any mouseevents
- else if(Hammer.NO_MOUSEEVENTS) {
- types = [
- 'touchstart',
- 'touchmove',
- 'touchend touchcancel'];
- }
- // for non pointer events browsers and mixed browsers,
- // like chrome on windows8 touch laptop
- else {
- types = [
- 'touchstart mousedown',
- 'touchmove mousemove',
- 'touchend touchcancel mouseup'];
- }
-
- Hammer.EVENT_TYPES[Hammer.EVENT_START] = types[0];
- Hammer.EVENT_TYPES[Hammer.EVENT_MOVE] = types[1];
- Hammer.EVENT_TYPES[Hammer.EVENT_END] = types[2];
- },
-
-
- /**
- * create touchlist depending on the event
- * @param {Object} ev
- * @param {String} eventType used by the fakemultitouch plugin
- */
- getTouchList: function getTouchList(ev/*, eventType*/) {
- // get the fake pointerEvent touchlist
- if(Hammer.HAS_POINTEREVENTS) {
- return Hammer.PointerEvent.getTouchList();
- }
- // get the touchlist
- else if(ev.touches) {
- return ev.touches;
- }
- // make fake touchlist from mouse position
- else {
- return [{
- identifier: 1,
- pageX: ev.pageX,
- pageY: ev.pageY,
- target: ev.target
- }];
- }
- },
-
-
- /**
- * collect event data for Hammer js
- * @param {HTMLElement} element
- * @param {String} eventType like Hammer.EVENT_MOVE
- * @param {Object} eventData
- */
- collectEventData: function collectEventData(element, eventType, ev) {
- var touches = this.getTouchList(ev, eventType);
-
- // find out pointerType
- var pointerType = Hammer.POINTER_TOUCH;
- if(ev.type.match(/mouse/) || Hammer.PointerEvent.matchType(Hammer.POINTER_MOUSE, ev)) {
- pointerType = Hammer.POINTER_MOUSE;
- }
-
- return {
- center : Hammer.utils.getCenter(touches),
- timeStamp : new Date().getTime(),
- target : ev.target,
- touches : touches,
- eventType : eventType,
- pointerType : pointerType,
- srcEvent : ev,
-
- /**
- * prevent the browser default actions
- * mostly used to disable scrolling of the browser
- */
- preventDefault: function() {
- if(this.srcEvent.preventManipulation) {
- this.srcEvent.preventManipulation();
- }
-
- if(this.srcEvent.preventDefault) {
- this.srcEvent.preventDefault();
- }
- },
-
- /**
- * stop bubbling the event up to its parents
- */
- stopPropagation: function() {
- this.srcEvent.stopPropagation();
- },
-
- /**
- * immediately stop gesture detection
- * might be useful after a swipe was detected
- * @return {*}
- */
- stopDetect: function() {
- return Hammer.detection.stopDetect();
- }
- };
- }
-};
-
-Hammer.PointerEvent = {
- /**
- * holds all pointers
- * @type {Object}
- */
- pointers: {},
-
- /**
- * get a list of pointers
- * @returns {Array} touchlist
- */
- getTouchList: function() {
- var self = this;
- var touchlist = [];
-
- // we can use forEach since pointerEvents only is in IE10
- Object.keys(self.pointers).sort().forEach(function(id) {
- touchlist.push(self.pointers[id]);
- });
- return touchlist;
- },
-
- /**
- * update the position of a pointer
- * @param {String} type Hammer.EVENT_END
- * @param {Object} pointerEvent
- */
- updatePointer: function(type, pointerEvent) {
- if(type == Hammer.EVENT_END) {
- this.pointers = {};
- }
- else {
- pointerEvent.identifier = pointerEvent.pointerId;
- this.pointers[pointerEvent.pointerId] = pointerEvent;
- }
-
- return Object.keys(this.pointers).length;
- },
-
- /**
- * check if ev matches pointertype
- * @param {String} pointerType Hammer.POINTER_MOUSE
- * @param {PointerEvent} ev
- */
- matchType: function(pointerType, ev) {
- if(!ev.pointerType) {
- return false;
- }
-
- var types = {};
- types[Hammer.POINTER_MOUSE] = (ev.pointerType == ev.MSPOINTER_TYPE_MOUSE || ev.pointerType == Hammer.POINTER_MOUSE);
- types[Hammer.POINTER_TOUCH] = (ev.pointerType == ev.MSPOINTER_TYPE_TOUCH || ev.pointerType == Hammer.POINTER_TOUCH);
- types[Hammer.POINTER_PEN] = (ev.pointerType == ev.MSPOINTER_TYPE_PEN || ev.pointerType == Hammer.POINTER_PEN);
- return types[pointerType];
- },
-
-
- /**
- * get events
- */
- getEvents: function() {
- return [
- 'pointerdown MSPointerDown',
- 'pointermove MSPointerMove',
- 'pointerup pointercancel MSPointerUp MSPointerCancel'
- ];
- },
-
- /**
- * reset the list
- */
- reset: function() {
- this.pointers = {};
- }
-};
-
-
-Hammer.utils = {
- /**
- * extend method,
- * also used for cloning when dest is an empty object
- * @param {Object} dest
- * @param {Object} src
- * @parm {Boolean} merge do a merge
- * @returns {Object} dest
- */
- extend: function extend(dest, src, merge) {
- for (var key in src) {
- if(dest[key] !== undefined && merge) {
- continue;
- }
- dest[key] = src[key];
- }
- return dest;
- },
-
-
- /**
- * find if a node is in the given parent
- * used for event delegation tricks
- * @param {HTMLElement} node
- * @param {HTMLElement} parent
- * @returns {boolean} has_parent
- */
- hasParent: function(node, parent) {
- while(node){
- if(node == parent) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
- },
-
-
- /**
- * get the center of all the touches
- * @param {Array} touches
- * @returns {Object} center
- */
- getCenter: function getCenter(touches) {
- var valuesX = [], valuesY = [];
-
- for(var t= 0,len=touches.length; t<len; t++) {
- valuesX.push(touches[t].pageX);
- valuesY.push(touches[t].pageY);
- }
-
- return {
- pageX: ((Math.min.apply(Math, valuesX) + Math.max.apply(Math, valuesX)) / 2),
- pageY: ((Math.min.apply(Math, valuesY) + Math.max.apply(Math, valuesY)) / 2)
- };
- },
-
-
- /**
- * calculate the velocity between two points
- * @param {Number} delta_time
- * @param {Number} delta_x
- * @param {Number} delta_y
- * @returns {Object} velocity
- */
- getVelocity: function getVelocity(delta_time, delta_x, delta_y) {
- return {
- x: Math.abs(delta_x / delta_time) || 0,
- y: Math.abs(delta_y / delta_time) || 0
- };
- },
-
-
- /**
- * calculate the angle between two coordinates
- * @param {Touch} touch1
- * @param {Touch} touch2
- * @returns {Number} angle
- */
- getAngle: function getAngle(touch1, touch2) {
- var y = touch2.pageY - touch1.pageY,
- x = touch2.pageX - touch1.pageX;
- return Math.atan2(y, x) * 180 / Math.PI;
- },
-
-
- /**
- * angle to direction define
- * @param {Touch} touch1
- * @param {Touch} touch2
- * @returns {String} direction constant, like Hammer.DIRECTION_LEFT
- */
- getDirection: function getDirection(touch1, touch2) {
- var x = Math.abs(touch1.pageX - touch2.pageX),
- y = Math.abs(touch1.pageY - touch2.pageY);
-
- if(x >= y) {
- return touch1.pageX - touch2.pageX > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
- }
- else {
- return touch1.pageY - touch2.pageY > 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
- }
- },
-
-
- /**
- * calculate the distance between two touches
- * @param {Touch} touch1
- * @param {Touch} touch2
- * @returns {Number} distance
- */
- getDistance: function getDistance(touch1, touch2) {
- var x = touch2.pageX - touch1.pageX,
- y = touch2.pageY - touch1.pageY;
- return Math.sqrt((x*x) + (y*y));
- },
-
-
- /**
- * calculate the scale factor between two touchLists (fingers)
- * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
- * @param {Array} start
- * @param {Array} end
- * @returns {Number} scale
- */
- getScale: function getScale(start, end) {
- // need two fingers...
- if(start.length >= 2 && end.length >= 2) {
- return this.getDistance(end[0], end[1]) /
- this.getDistance(start[0], start[1]);
- }
- return 1;
- },
-
-
- /**
- * calculate the rotation degrees between two touchLists (fingers)
- * @param {Array} start
- * @param {Array} end
- * @returns {Number} rotation
- */
- getRotation: function getRotation(start, end) {
- // need two fingers
- if(start.length >= 2 && end.length >= 2) {
- return this.getAngle(end[1], end[0]) -
- this.getAngle(start[1], start[0]);
- }
- return 0;
- },
-
-
- /**
- * boolean if the direction is vertical
- * @param {String} direction
- * @returns {Boolean} is_vertical
- */
- isVertical: function isVertical(direction) {
- return (direction == Hammer.DIRECTION_UP || direction == Hammer.DIRECTION_DOWN);
- },
-
-
- /**
- * stop browser default behavior with css props
- * @param {HtmlElement} element
- * @param {Object} css_props
- */
- stopDefaultBrowserBehavior: function stopDefaultBrowserBehavior(element, css_props) {
- var prop,
- vendors = ['webkit','khtml','moz','ms','o',''];
-
- if(!css_props || !element.style) {
- return;
- }
-
- // with css properties for modern browsers
- for(var i = 0; i < vendors.length; i++) {
- for(var p in css_props) {
- if(css_props.hasOwnProperty(p)) {
- prop = p;
-
- // vender prefix at the property
- if(vendors[i]) {
- prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1);
- }
-
- // set the style
- element.style[prop] = css_props[p];
- }
- }
- }
-
- // also the disable onselectstart
- if(css_props.userSelect == 'none') {
- element.onselectstart = function() {
- return false;
- };
- }
- }
-};
-
-Hammer.detection = {
- // contains all registred Hammer.gestures in the correct order
- gestures: [],
-
- // data of the current Hammer.gesture detection session
- current: null,
-
- // the previous Hammer.gesture session data
- // is a full clone of the previous gesture.current object
- previous: null,
-
- // when this becomes true, no gestures are fired
- stopped: false,
-
-
- /**
- * start Hammer.gesture detection
- * @param {Hammer.Instance} inst
- * @param {Object} eventData
- */
- startDetect: function startDetect(inst, eventData) {
- // already busy with a Hammer.gesture detection on an element
- if(this.current) {
- return;
- }
-
- this.stopped = false;
-
- this.current = {
- inst : inst, // reference to HammerInstance we're working for
- startEvent : Hammer.utils.extend({}, eventData), // start eventData for distances, timing etc
- lastEvent : false, // last eventData
- name : '' // current gesture we're in/detected, can be 'tap', 'hold' etc
- };
-
- this.detect(eventData);
- },
-
-
- /**
- * Hammer.gesture detection
- * @param {Object} eventData
- * @param {Object} eventData
- */
- detect: function detect(eventData) {
- if(!this.current || this.stopped) {
- return;
- }
-
- // extend event data with calculations about scale, distance etc
- eventData = this.extendEventData(eventData);
-
- // instance options
- var inst_options = this.current.inst.options;
-
- // call Hammer.gesture handlers
- for(var g=0,len=this.gestures.length; g<len; g++) {
- var gesture = this.gestures[g];
-
- // only when the instance options have enabled this gesture
- if(!this.stopped && inst_options[gesture.name] !== false) {
- // if a handler returns false, we stop with the detection
- if(gesture.handler.call(gesture, eventData, this.current.inst) === false) {
- this.stopDetect();
- break;
- }
- }
- }
-
- // store as previous event event
- if(this.current) {
- this.current.lastEvent = eventData;
- }
-
- // endevent, but not the last touch, so dont stop
- if(eventData.eventType == Hammer.EVENT_END && !eventData.touches.length-1) {
- this.stopDetect();
- }
-
- return eventData;
- },
-
-
- /**
- * clear the Hammer.gesture vars
- * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected
- * to stop other Hammer.gestures from being fired
- */
- stopDetect: function stopDetect() {
- // clone current data to the store as the previous gesture
- // used for the double tap gesture, since this is an other gesture detect session
- this.previous = Hammer.utils.extend({}, this.current);
-
- // reset the current
- this.current = null;
-
- // stopped!
- this.stopped = true;
- },
-
-
- /**
- * extend eventData for Hammer.gestures
- * @param {Object} ev
- * @returns {Object} ev
- */
- extendEventData: function extendEventData(ev) {
- var startEv = this.current.startEvent;
-
- // if the touches change, set the new touches over the startEvent touches
- // this because touchevents don't have all the touches on touchstart, or the
- // user must place his fingers at the EXACT same time on the screen, which is not realistic
- // but, sometimes it happens that both fingers are touching at the EXACT same time
- if(startEv && (ev.touches.length != startEv.touches.length || ev.touches === startEv.touches)) {
- // extend 1 level deep to get the touchlist with the touch objects
- startEv.touches = [];
- for(var i=0,len=ev.touches.length; i<len; i++) {
- startEv.touches.push(Hammer.utils.extend({}, ev.touches[i]));
- }
- }
-
- var delta_time = ev.timeStamp - startEv.timeStamp,
- delta_x = ev.center.pageX - startEv.center.pageX,
- delta_y = ev.center.pageY - startEv.center.pageY,
- velocity = Hammer.utils.getVelocity(delta_time, delta_x, delta_y);
-
- Hammer.utils.extend(ev, {
- deltaTime : delta_time,
-
- deltaX : delta_x,
- deltaY : delta_y,
-
- velocityX : velocity.x,
- velocityY : velocity.y,
-
- distance : Hammer.utils.getDistance(startEv.center, ev.center),
- angle : Hammer.utils.getAngle(startEv.center, ev.center),
- direction : Hammer.utils.getDirection(startEv.center, ev.center),
-
- scale : Hammer.utils.getScale(startEv.touches, ev.touches),
- rotation : Hammer.utils.getRotation(startEv.touches, ev.touches),
-
- startEvent : startEv
- });
-
- return ev;
- },
-
-
- /**
- * register new gesture
- * @param {Object} gesture object, see gestures.js for documentation
- * @returns {Array} gestures
- */
- register: function register(gesture) {
- // add an enable gesture options if there is no given
- var options = gesture.defaults || {};
- if(options[gesture.name] === undefined) {
- options[gesture.name] = true;
- }
-
- // extend Hammer default options with the Hammer.gesture options
- Hammer.utils.extend(Hammer.defaults, options, true);
-
- // set its index
- gesture.index = gesture.index || 1000;
-
- // add Hammer.gesture to the list
- this.gestures.push(gesture);
-
- // sort the list by index
- this.gestures.sort(function(a, b) {
- if (a.index < b.index) {
- return -1;
- }
- if (a.index > b.index) {
- return 1;
- }
- return 0;
- });
-
- return this.gestures;
- }
-};
-
-
-Hammer.gestures = Hammer.gestures || {};
-
-/**
- * Custom gestures
- * ==============================
- *
- * Gesture object
- * --------------------
- * The object structure of a gesture:
- *
- * { name: 'mygesture',
- * index: 1337,
- * defaults: {
- * mygesture_option: true
- * }
- * handler: function(type, ev, inst) {
- * // trigger gesture event
- * inst.trigger(this.name, ev);
- * }
- * }
-
- * @param {String} name
- * this should be the name of the gesture, lowercase
- * it is also being used to disable/enable the gesture per instance config.
- *
- * @param {Number} [index=1000]
- * the index of the gesture, where it is going to be in the stack of gestures detection
- * like when you build an gesture that depends on the drag gesture, it is a good
- * idea to place it after the index of the drag gesture.
- *
- * @param {Object} [defaults={}]
- * the default settings of the gesture. these are added to the instance settings,
- * and can be overruled per instance. you can also add the name of the gesture,
- * but this is also added by default (and set to true).
- *
- * @param {Function} handler
- * this handles the gesture detection of your custom gesture and receives the
- * following arguments:
- *
- * @param {Object} eventData
- * event data containing the following properties:
- * timeStamp {Number} time the event occurred
- * target {HTMLElement} target element
- * touches {Array} touches (fingers, pointers, mouse) on the screen
- * pointerType {String} kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH
- * center {Object} center position of the touches. contains pageX and pageY
- * deltaTime {Number} the total time of the touches in the screen
- * deltaX {Number} the delta on x axis we haved moved
- * deltaY {Number} the delta on y axis we haved moved
- * velocityX {Number} the velocity on the x
- * velocityY {Number} the velocity on y
- * angle {Number} the angle we are moving
- * direction {String} the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT
- * distance {Number} the distance we haved moved
- * scale {Number} scaling of the touches, needs 2 touches
- * rotation {Number} rotation of the touches, needs 2 touches *
- * eventType {String} matches Hammer.EVENT_START|MOVE|END
- * srcEvent {Object} the source event, like TouchStart or MouseDown *
- * startEvent {Object} contains the same properties as above,
- * but from the first touch. this is used to calculate
- * distances, deltaTime, scaling etc
- *
- * @param {Hammer.Instance} inst
- * the instance we are doing the detection for. you can get the options from
- * the inst.options object and trigger the gesture event by calling inst.trigger
- *
- *
- * Handle gestures
- * --------------------
- * inside the handler you can get/set Hammer.detection.current. This is the current
- * detection session. It has the following properties
- * @param {String} name
- * contains the name of the gesture we have detected. it has not a real function,
- * only to check in other gestures if something is detected.
- * like in the drag gesture we set it to 'drag' and in the swipe gesture we can
- * check if the current gesture is 'drag' by accessing Hammer.detection.current.name
- *
- * @readonly
- * @param {Hammer.Instance} inst
- * the instance we do the detection for
- *
- * @readonly
- * @param {Object} startEvent
- * contains the properties of the first gesture detection in this session.
- * Used for calculations about timing, distance, etc.
- *
- * @readonly
- * @param {Object} lastEvent
- * contains all the properties of the last gesture detect in this session.
- *
- * after the gesture detection session has been completed (user has released the screen)
- * the Hammer.detection.current object is copied into Hammer.detection.previous,
- * this is usefull for gestures like doubletap, where you need to know if the
- * previous gesture was a tap
- *
- * options that have been set by the instance can be received by calling inst.options
- *
- * You can trigger a gesture event by calling inst.trigger("mygesture", event).
- * The first param is the name of your gesture, the second the event argument
- *
- *
- * Register gestures
- * --------------------
- * When an gesture is added to the Hammer.gestures object, it is auto registered
- * at the setup of the first Hammer instance. You can also call Hammer.detection.register
- * manually and pass your gesture object as a param
- *
- */
-
-/**
- * Hold
- * Touch stays at the same place for x time
- * @events hold
- */
-Hammer.gestures.Hold = {
- name: 'hold',
- index: 10,
- defaults: {
- hold_timeout : 500,
- hold_threshold : 1
- },
- timer: null,
- handler: function holdGesture(ev, inst) {
- switch(ev.eventType) {
- case Hammer.EVENT_START:
- // clear any running timers
- clearTimeout(this.timer);
-
- // set the gesture so we can check in the timeout if it still is
- Hammer.detection.current.name = this.name;
-
- // set timer and if after the timeout it still is hold,
- // we trigger the hold event
- this.timer = setTimeout(function() {
- if(Hammer.detection.current.name == 'hold') {
- inst.trigger('hold', ev);
- }
- }, inst.options.hold_timeout);
- break;
-
- // when you move or end we clear the timer
- case Hammer.EVENT_MOVE:
- if(ev.distance > inst.options.hold_threshold) {
- clearTimeout(this.timer);
- }
- break;
-
- case Hammer.EVENT_END:
- clearTimeout(this.timer);
- break;
- }
- }
-};
-
-
-/**
- * Tap/DoubleTap
- * Quick touch at a place or double at the same place
- * @events tap, doubletap
- */
-Hammer.gestures.Tap = {
- name: 'tap',
- index: 100,
- defaults: {
- tap_max_touchtime : 250,
- tap_max_distance : 10,
- tap_always : true,
- doubletap_distance : 20,
- doubletap_interval : 300
- },
- handler: function tapGesture(ev, inst) {
- if(ev.eventType == Hammer.EVENT_END) {
- // previous gesture, for the double tap since these are two different gesture detections
- var prev = Hammer.detection.previous,
- did_doubletap = false;
-
- // when the touchtime is higher then the max touch time
- // or when the moving distance is too much
- if(ev.deltaTime > inst.options.tap_max_touchtime ||
- ev.distance > inst.options.tap_max_distance) {
- return;
- }
-
- // check if double tap
- if(prev && prev.name == 'tap' &&
- (ev.timeStamp - prev.lastEvent.timeStamp) < inst.options.doubletap_interval &&
- ev.distance < inst.options.doubletap_distance) {
- inst.trigger('doubletap', ev);
- did_doubletap = true;
- }
-
- // do a single tap
- if(!did_doubletap || inst.options.tap_always) {
- Hammer.detection.current.name = 'tap';
- inst.trigger(Hammer.detection.current.name, ev);
- }
- }
- }
-};
-
-
-/**
- * Swipe
- * triggers swipe events when the end velocity is above the threshold
- * @events swipe, swipeleft, swiperight, swipeup, swipedown
- */
-Hammer.gestures.Swipe = {
- name: 'swipe',
- index: 40,
- defaults: {
- // set 0 for unlimited, but this can conflict with transform
- swipe_max_touches : 1,
- swipe_velocity : 0.7
- },
- handler: function swipeGesture(ev, inst) {
- if(ev.eventType == Hammer.EVENT_END) {
- // max touches
- if(inst.options.swipe_max_touches > 0 &&
- ev.touches.length > inst.options.swipe_max_touches) {
- return;
- }
-
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if(ev.velocityX > inst.options.swipe_velocity ||
- ev.velocityY > inst.options.swipe_velocity) {
- // trigger swipe events
- inst.trigger(this.name, ev);
- inst.trigger(this.name + ev.direction, ev);
- }
- }
- }
-};
-
-
-/**
- * Drag
- * Move with x fingers (default 1) around on the page. Blocking the scrolling when
- * moving left and right is a good practice. When all the drag events are blocking
- * you disable scrolling on that area.
- * @events drag, drapleft, dragright, dragup, dragdown
- */
-Hammer.gestures.Drag = {
- name: 'drag',
- index: 50,
- defaults: {
- drag_min_distance : 10,
- // set 0 for unlimited, but this can conflict with transform
- drag_max_touches : 1,
- // prevent default browser behavior when dragging occurs
- // be careful with it, it makes the element a blocking element
- // when you are using the drag gesture, it is a good practice to set this true
- drag_block_horizontal : false,
- drag_block_vertical : false,
- // drag_lock_to_axis keeps the drag gesture on the axis that it started on,
- // It disallows vertical directions if the initial direction was horizontal, and vice versa.
- drag_lock_to_axis : false,
- // drag lock only kicks in when distance > drag_lock_min_distance
- // This way, locking occurs only when the distance has become large enough to reliably determine the direction
- drag_lock_min_distance : 25
- },
- triggered: false,
- handler: function dragGesture(ev, inst) {
- // current gesture isnt drag, but dragged is true
- // this means an other gesture is busy. now call dragend
- if(Hammer.detection.current.name != this.name && this.triggered) {
- inst.trigger(this.name +'end', ev);
- this.triggered = false;
- return;
- }
-
- // max touches
- if(inst.options.drag_max_touches > 0 &&
- ev.touches.length > inst.options.drag_max_touches) {
- return;
- }
-
- switch(ev.eventType) {
- case Hammer.EVENT_START:
- this.triggered = false;
- break;
-
- case Hammer.EVENT_MOVE:
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if(ev.distance < inst.options.drag_min_distance &&
- Hammer.detection.current.name != this.name) {
- return;
- }
-
- // we are dragging!
- Hammer.detection.current.name = this.name;
-
- // lock drag to axis?
- if(Hammer.detection.current.lastEvent.drag_locked_to_axis || (inst.options.drag_lock_to_axis && inst.options.drag_lock_min_distance<=ev.distance)) {
- ev.drag_locked_to_axis = true;
- }
- var last_direction = Hammer.detection.current.lastEvent.direction;
- if(ev.drag_locked_to_axis && last_direction !== ev.direction) {
- // keep direction on the axis that the drag gesture started on
- if(Hammer.utils.isVertical(last_direction)) {
- ev.direction = (ev.deltaY < 0) ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
- }
- else {
- ev.direction = (ev.deltaX < 0) ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
- }
- }
-
- // first time, trigger dragstart event
- if(!this.triggered) {
- inst.trigger(this.name +'start', ev);
- this.triggered = true;
- }
-
- // trigger normal event
- inst.trigger(this.name, ev);
-
- // direction event, like dragdown
- inst.trigger(this.name + ev.direction, ev);
-
- // block the browser events
- if( (inst.options.drag_block_vertical && Hammer.utils.isVertical(ev.direction)) ||
- (inst.options.drag_block_horizontal && !Hammer.utils.isVertical(ev.direction))) {
- ev.preventDefault();
- }
- break;
-
- case Hammer.EVENT_END:
- // trigger dragend
- if(this.triggered) {
- inst.trigger(this.name +'end', ev);
- }
-
- this.triggered = false;
- break;
- }
- }
-};
-
-
-/**
- * Transform
- * User want to scale or rotate with 2 fingers
- * @events transform, pinch, pinchin, pinchout, rotate
- */
-Hammer.gestures.Transform = {
- name: 'transform',
- index: 45,
- defaults: {
- // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
- transform_min_scale : 0.01,
- // rotation in degrees
- transform_min_rotation : 1,
- // prevent default browser behavior when two touches are on the screen
- // but it makes the element a blocking element
- // when you are using the transform gesture, it is a good practice to set this true
- transform_always_block : false
- },
- triggered: false,
- handler: function transformGesture(ev, inst) {
- // current gesture isnt drag, but dragged is true
- // this means an other gesture is busy. now call dragend
- if(Hammer.detection.current.name != this.name && this.triggered) {
- inst.trigger(this.name +'end', ev);
- this.triggered = false;
- return;
- }
-
- // atleast multitouch
- if(ev.touches.length < 2) {
- return;
- }
-
- // prevent default when two fingers are on the screen
- if(inst.options.transform_always_block) {
- ev.preventDefault();
- }
-
- switch(ev.eventType) {
- case Hammer.EVENT_START:
- this.triggered = false;
- break;
-
- case Hammer.EVENT_MOVE:
- var scale_threshold = Math.abs(1-ev.scale);
- var rotation_threshold = Math.abs(ev.rotation);
-
- // when the distance we moved is too small we skip this gesture
- // or we can be already in dragging
- if(scale_threshold < inst.options.transform_min_scale &&
- rotation_threshold < inst.options.transform_min_rotation) {
- return;
- }
-
- // we are transforming!
- Hammer.detection.current.name = this.name;
-
- // first time, trigger dragstart event
- if(!this.triggered) {
- inst.trigger(this.name +'start', ev);
- this.triggered = true;
- }
-
- inst.trigger(this.name, ev); // basic transform event
-
- // trigger rotate event
- if(rotation_threshold > inst.options.transform_min_rotation) {
- inst.trigger('rotate', ev);
- }
-
- // trigger pinch event
- if(scale_threshold > inst.options.transform_min_scale) {
- inst.trigger('pinch', ev);
- inst.trigger('pinch'+ ((ev.scale < 1) ? 'in' : 'out'), ev);
- }
- break;
-
- case Hammer.EVENT_END:
- // trigger dragend
- if(this.triggered) {
- inst.trigger(this.name +'end', ev);
- }
-
- this.triggered = false;
- break;
- }
- }
-};
-
-
-/**
- * Touch
- * Called as first, tells the user has touched the screen
- * @events touch
- */
-Hammer.gestures.Touch = {
- name: 'touch',
- index: -Infinity,
- defaults: {
- // call preventDefault at touchstart, and makes the element blocking by
- // disabling the scrolling of the page, but it improves gestures like
- // transforming and dragging.
- // be careful with using this, it can be very annoying for users to be stuck
- // on the page
- prevent_default: false,
-
- // disable mouse events, so only touch (or pen!) input triggers events
- prevent_mouseevents: false
- },
- handler: function touchGesture(ev, inst) {
- if(inst.options.prevent_mouseevents && ev.pointerType == Hammer.POINTER_MOUSE) {
- ev.stopDetect();
- return;
- }
-
- if(inst.options.prevent_default) {
- ev.preventDefault();
- }
-
- if(ev.eventType == Hammer.EVENT_START) {
- inst.trigger(this.name, ev);
- }
- }
-};
-
-
-/**
- * Release
- * Called as last, tells the user has released the screen
- * @events release
- */
-Hammer.gestures.Release = {
- name: 'release',
- index: Infinity,
- handler: function releaseGesture(ev, inst) {
- if(ev.eventType == Hammer.EVENT_END) {
- inst.trigger(this.name, ev);
- }
- }
-};
-
-// node export
-if(typeof module === 'object' && typeof module.exports === 'object'){
- module.exports = Hammer;
-}
-// just window export
-else {
- window.Hammer = Hammer;
-
- // requireJS module definition
- if(typeof window.define === 'function' && window.define.amd) {
- window.define('hammer', [], function() {
- return Hammer;
- });
- }
-}
-})(this);
-'use strict';
-
-angular.module('angular-gestures', []);
-
-/**
- * Inspired by AngularJS' implementation of "click dblclick mousedown..."
- *
- * This ties in the Hammer 1.0.0 events to attributes like:
- *
- * hm-tap="add_something()" hm-swipe="remove_something()"
- *
- * and also has support for Hammer options with:
- *
- * hm-tap-opts="{hold: false}"
- *
- * or any other of the "hm-event" listed underneath.
- */
-var HGESTURES = {
- hmDoubleTap : 'doubletap',
- hmDragstart : 'dragstart',
- hmDrag : 'drag',
- hmDragUp : 'dragup',
- hmDragDown : 'dragdown',
- hmDragLeft : 'dragleft',
- hmDragRight : 'dragright',
- hmDragend : 'dragend',
- hmHold : 'hold',
- hmPinch : 'pinch',
- hmPinchIn : 'pinchin',
- hmPinchOut : 'pinchout',
- hmRelease : 'release',
- hmRotate : 'rotate',
- hmSwipe : 'swipe',
- hmSwipeUp : 'swipeup',
- hmSwipeDown : 'swipedown',
- hmSwipeLeft : 'swipeleft',
- hmSwipeRight : 'swiperight',
- hmTap : 'tap',
- hmTouch : 'touch',
- hmTransformstart : 'transformstart',
- hmTransform : 'transform',
- hmTransformend : 'transformend'
-};
-
-var VERBOSE = false;
-
-angular.forEach(HGESTURES, function(eventName, directiveName) {
- angular.module('angular-gestures').directive(
- directiveName,
- ['$parse', '$log', '$timeout', function($parse, $log, $timeout) {
- return function(scope, element, attr) {
- var hammertime, handler;
- attr.$observe(directiveName, function(value) {
- var fn = $parse(value);
- var opts = $parse(attr[directiveName + 'Opts'])
- (scope, {});
- hammertime = new Hammer(element[0], opts);
- handler = function(event) {
- if (VERBOSE) {
- $log.debug('angular-gestures: %s',
- eventName);
- }
- $timeout(function() {
- fn(scope, { $event : event });
- }, 0);
- };
- hammertime.on(eventName, handler);
- });
- scope.$on('$destroy', function() {
- hammertime.off(eventName, handler);
- });
- };
- }]);
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ng_base.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ng_base.js
deleted file mode 100644
index f864525c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ng_base.js
+++ /dev/null
@@ -1,4 +0,0 @@
-!function(a,b){function c(a){var b=a.length,c=kb.type(a);return kb.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||"function"!==c&&(0===b||"number"==typeof b&&b>0&&b-1 in a)}function d(a){var b=zb[a]={};return kb.each(a.match(mb)||[],function(a,c){b[c]=!0}),b}function e(a,c,d,e){if(kb.acceptData(a)){var f,g,h=kb.expando,i=a.nodeType,j=i?kb.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||d!==b||"string"!=typeof c)return k||(k=i?a[h]=bb.pop()||kb.guid++:h),j[k]||(j[k]=i?{}:{toJSON:kb.noop}),("object"==typeof c||"function"==typeof c)&&(e?j[k]=kb.extend(j[k],c):j[k].data=kb.extend(j[k].data,c)),g=j[k],e||(g.data||(g.data={}),g=g.data),d!==b&&(g[kb.camelCase(c)]=d),"string"==typeof c?(f=g[c],null==f&&(f=g[kb.camelCase(c)])):f=g,f}}function f(a,b,c){if(kb.acceptData(a)){var d,e,f=a.nodeType,g=f?kb.cache:a,i=f?a[kb.expando]:kb.expando;if(g[i]){if(b&&(d=c?g[i]:g[i].data)){kb.isArray(b)?b=b.concat(kb.map(b,kb.camelCase)):b in d?b=[b]:(b=kb.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;for(;e--;)delete d[b[e]];if(c?!h(d):!kb.isEmptyObject(d))return}(c||(delete g[i].data,h(g[i])))&&(f?kb.cleanData([a],!0):kb.support.deleteExpando||g!=g.window?delete g[i]:g[i]=null)}}}function g(a,c,d){if(d===b&&1===a.nodeType){var e="data-"+c.replace(Bb,"-$1").toLowerCase();if(d=a.getAttribute(e),"string"==typeof d){try{d="true"===d?!0:"false"===d?!1:"null"===d?null:+d+""===d?+d:Ab.test(d)?kb.parseJSON(d):d}catch(f){}kb.data(a,c,d)}else d=b}return d}function h(a){var b;for(b in a)if(("data"!==b||!kb.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function i(){return!0}function j(){return!1}function k(){try{return Y.activeElement}catch(a){}}function l(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}function m(a,b,c){if(kb.isFunction(b))return kb.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return kb.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(Qb.test(b))return kb.filter(b,a,c);b=kb.filter(b,a)}return kb.grep(a,function(a){return kb.inArray(a,b)>=0!==c})}function n(a){var b=Ub.split("|"),c=a.createDocumentFragment();if(c.createElement)for(;b.length;)c.createElement(b.pop());return c}function o(a,b){return kb.nodeName(a,"table")&&kb.nodeName(1===b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function p(a){return a.type=(null!==kb.find.attr(a,"type"))+"/"+a.type,a}function q(a){var b=ec.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function r(a,b){for(var c,d=0;null!=(c=a[d]);d++)kb._data(c,"globalEval",!b||kb._data(b[d],"globalEval"))}function s(a,b){if(1===b.nodeType&&kb.hasData(a)){var c,d,e,f=kb._data(a),g=kb._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)kb.event.add(b,c,h[c][d])}g.data&&(g.data=kb.extend({},g.data))}}function t(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!kb.support.noCloneEvent&&b[kb.expando]){e=kb._data(b);for(d in e.events)kb.removeEvent(b,d,e.handle);b.removeAttribute(kb.expando)}"script"===c&&b.text!==a.text?(p(b).text=a.text,q(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),kb.support.html5Clone&&a.innerHTML&&!kb.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&bc.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}function u(a,c){var d,e,f=0,g=typeof a.getElementsByTagName!==W?a.getElementsByTagName(c||"*"):typeof a.querySelectorAll!==W?a.querySelectorAll(c||"*"):b;if(!g)for(g=[],d=a.childNodes||a;null!=(e=d[f]);f++)!c||kb.nodeName(e,c)?g.push(e):kb.merge(g,u(e,c));return c===b||c&&kb.nodeName(a,c)?kb.merge([a],g):g}function v(a){bc.test(a.type)&&(a.defaultChecked=a.checked)}function w(a,b){if(b in a)return b;for(var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=yc.length;e--;)if(b=yc[e]+c,b in a)return b;return d}function x(a,b){return a=b||a,"none"===kb.css(a,"display")||!kb.contains(a.ownerDocument,a)}function y(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=kb._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&x(d)&&(f[g]=kb._data(d,"olddisplay",C(d.nodeName)))):f[g]||(e=x(d),(c&&"none"!==c||!e)&&kb._data(d,"olddisplay",e?c:kb.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function z(a,b,c){var d=rc.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function A(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=kb.css(a,c+xc[f],!0,e)),d?("content"===c&&(g-=kb.css(a,"padding"+xc[f],!0,e)),"margin"!==c&&(g-=kb.css(a,"border"+xc[f]+"Width",!0,e))):(g+=kb.css(a,"padding"+xc[f],!0,e),"padding"!==c&&(g+=kb.css(a,"border"+xc[f]+"Width",!0,e)));return g}function B(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=kc(a),g=kb.support.boxSizing&&"border-box"===kb.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=lc(a,b,f),(0>e||null==e)&&(e=a.style[b]),sc.test(e))return e;d=g&&(kb.support.boxSizingReliable||e===a.style[b]),e=parseFloat(e)||0}return e+A(a,b,c||(g?"border":"content"),d,f)+"px"}function C(a){var b=Y,c=uc[a];return c||(c=D(a,b),"none"!==c&&c||(jc=(jc||kb("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(b.documentElement),b=(jc[0].contentWindow||jc[0].contentDocument).document,b.write("<!doctype html><html><body>"),b.close(),c=D(a,b),jc.detach()),uc[a]=c),c}function D(a,b){var c=kb(b.createElement(a)).appendTo(b.body),d=kb.css(c[0],"display");return c.remove(),d}function E(a,b,c,d){var e;if(kb.isArray(b))kb.each(b,function(b,e){c||Ac.test(a)?d(a,e):E(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==kb.type(b))d(a,b);else for(e in b)E(a+"["+e+"]",b[e],c,d)}function F(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(mb)||[];if(kb.isFunction(c))for(;d=f[e++];)"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function G(a,b,c,d){function e(h){var i;return f[h]=!0,kb.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||g||f[j]?g?!(i=j):void 0:(b.dataTypes.unshift(j),e(j),!1)}),i}var f={},g=a===Rc;return e(b.dataTypes[0])||!f["*"]&&e("*")}function H(a,c){var d,e,f=kb.ajaxSettings.flatOptions||{};for(e in c)c[e]!==b&&((f[e]?a:d||(d={}))[e]=c[e]);return d&&kb.extend(!0,a,d),a}function I(a,c,d){for(var e,f,g,h,i=a.contents,j=a.dataTypes;"*"===j[0];)j.shift(),f===b&&(f=a.mimeType||c.getResponseHeader("Content-Type"));if(f)for(h in i)if(i[h]&&i[h].test(f)){j.unshift(h);break}if(j[0]in d)g=j[0];else{for(h in d){if(!j[0]||a.converters[h+" "+j[0]]){g=h;break}e||(e=h)}g=g||e}return g?(g!==j[0]&&j.unshift(g),d[g]):void 0}function J(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];for(f=k.shift();f;)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}function K(){try{return new a.XMLHttpRequest}catch(b){}}function L(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function M(){return setTimeout(function(){$c=b}),$c=kb.now()}function N(a,b,c){for(var d,e=(ed[b]||[]).concat(ed["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function O(a,b,c){var d,e,f=0,g=dd.length,h=kb.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$c||M(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:kb.extend({},b),opts:kb.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$c||M(),duration:c.duration,tweens:[],createTween:function(b,c){var d=kb.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(P(k,j.opts.specialEasing);g>f;f++)if(d=dd[f].call(j,a,k,j.opts))return d;return kb.map(k,N,j),kb.isFunction(j.opts.start)&&j.opts.start.call(a,j),kb.fx.timer(kb.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function P(a,b){var c,d,e,f,g;for(c in a)if(d=kb.camelCase(c),e=b[d],f=a[c],kb.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=kb.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Q(a,b,c){var d,e,f,g,h,i,j=this,k={},l=a.style,m=a.nodeType&&x(a),n=kb._data(a,"fxshow");c.queue||(h=kb._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,j.always(function(){j.always(function(){h.unqueued--,kb.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[l.overflow,l.overflowX,l.overflowY],"inline"===kb.css(a,"display")&&"none"===kb.css(a,"float")&&(kb.support.inlineBlockNeedsLayout&&"inline"!==C(a.nodeName)?l.zoom=1:l.display="inline-block")),c.overflow&&(l.overflow="hidden",kb.support.shrinkWrapBlocks||j.always(function(){l.overflow=c.overflow[0],l.overflowX=c.overflow[1],l.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ad.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(m?"hide":"show"))continue;k[d]=n&&n[d]||kb.style(a,d)}if(!kb.isEmptyObject(k)){n?"hidden"in n&&(m=n.hidden):n=kb._data(a,"fxshow",{}),f&&(n.hidden=!m),m?kb(a).show():j.done(function(){kb(a).hide()}),j.done(function(){var b;kb._removeData(a,"fxshow");for(b in k)kb.style(a,b,k[b])});for(d in k)g=N(m?n[d]:0,d,j),d in n||(n[d]=g.start,m&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function R(a,b,c,d,e){return new R.prototype.init(a,b,c,d,e)}function S(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=xc[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function T(a){return kb.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}var U,V,W=typeof b,X=a.location,Y=a.document,Z=Y.documentElement,$=a.jQuery,_=a.$,ab={},bb=[],cb="1.10.2",db=bb.concat,eb=bb.push,fb=bb.slice,gb=bb.indexOf,hb=ab.toString,ib=ab.hasOwnProperty,jb=cb.trim,kb=function(a,b){return new kb.fn.init(a,b,V)},lb=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,mb=/\S+/g,nb=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,ob=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,pb=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,qb=/^[\],:{}\s]*$/,rb=/(?:^|:|,)(?:\s*\[)+/g,sb=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,tb=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,ub=/^-ms-/,vb=/-([\da-z])/gi,wb=function(a,b){return b.toUpperCase()},xb=function(a){(Y.addEventListener||"load"===a.type||"complete"===Y.readyState)&&(yb(),kb.ready())},yb=function(){Y.addEventListener?(Y.removeEventListener("DOMContentLoaded",xb,!1),a.removeEventListener("load",xb,!1)):(Y.detachEvent("onreadystatechange",xb),a.detachEvent("onload",xb))};kb.fn=kb.prototype={jquery:cb,constructor:kb,init:function(a,c,d){var e,f;if(!a)return this;if("string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:ob.exec(a),!e||!e[1]&&c)return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a);if(e[1]){if(c=c instanceof kb?c[0]:c,kb.merge(this,kb.parseHTML(e[1],c&&c.nodeType?c.ownerDocument||c:Y,!0)),pb.test(e[1])&&kb.isPlainObject(c))for(e in c)kb.isFunction(this[e])?this[e](c[e]):this.attr(e,c[e]);return this}if(f=Y.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return d.find(a);this.length=1,this[0]=f}return this.context=Y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):kb.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),kb.makeArray(a,this))},selector:"",length:0,toArray:function(){return fb.call(this)},get:function(a){return null==a?this.toArray():0>a?this[this.length+a]:this[a]},pushStack:function(a){var b=kb.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return kb.each(this,a,b)},ready:function(a){return kb.ready.promise().done(a),this},slice:function(){return this.pushStack(fb.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},map:function(a){return this.pushStack(kb.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:eb,sort:[].sort,splice:[].splice},kb.fn.init.prototype=kb.fn,kb.extend=kb.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;for("boolean"==typeof h&&(k=h,h=arguments[1]||{},i=2),"object"==typeof h||kb.isFunction(h)||(h={}),j===i&&(h=this,--i);j>i;i++)if(null!=(f=arguments[i]))for(e in f)a=h[e],d=f[e],h!==d&&(k&&d&&(kb.isPlainObject(d)||(c=kb.isArray(d)))?(c?(c=!1,g=a&&kb.isArray(a)?a:[]):g=a&&kb.isPlainObject(a)?a:{},h[e]=kb.extend(k,g,d)):d!==b&&(h[e]=d));return h},kb.extend({expando:"jQuery"+(cb+Math.random()).replace(/\D/g,""),noConflict:function(b){return a.$===kb&&(a.$=_),b&&a.jQuery===kb&&(a.jQuery=$),kb},isReady:!1,readyWait:1,holdReady:function(a){a?kb.readyWait++:kb.ready(!0)},ready:function(a){if(a===!0?!--kb.readyWait:!kb.isReady){if(!Y.body)return setTimeout(kb.ready);kb.isReady=!0,a!==!0&&--kb.readyWait>0||(U.resolveWith(Y,[kb]),kb.fn.trigger&&kb(Y).trigger("ready").off("ready"))}},isFunction:function(a){return"function"===kb.type(a)},isArray:Array.isArray||function(a){return"array"===kb.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return null==a?String(a):"object"==typeof a||"function"==typeof a?ab[hb.call(a)]||"object":typeof a},isPlainObject:function(a){var c;if(!a||"object"!==kb.type(a)||a.nodeType||kb.isWindow(a))return!1;try{if(a.constructor&&!ib.call(a,"constructor")&&!ib.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(d){return!1}if(kb.support.ownLast)for(c in a)return ib.call(a,c);for(c in a);return c===b||ib.call(a,c)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||Y;var d=pb.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=kb.buildFragment([a],b,e),e&&kb(e).remove(),kb.merge([],d.childNodes))},parseJSON:function(b){return a.JSON&&a.JSON.parse?a.JSON.parse(b):null===b?b:"string"==typeof b&&(b=kb.trim(b),b&&qb.test(b.replace(sb,"@").replace(tb,"]").replace(rb,"")))?new Function("return "+b)():void kb.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||"string"!=typeof c)return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return d&&d.documentElement&&!d.getElementsByTagName("parsererror").length||kb.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&kb.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(ub,"ms-").replace(vb,wb)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,d){var e,f=0,g=a.length,h=c(a);if(d){if(h)for(;g>f&&(e=b.apply(a[f],d),e!==!1);f++);else for(f in a)if(e=b.apply(a[f],d),e===!1)break}else if(h)for(;g>f&&(e=b.call(a[f],f,a[f]),e!==!1);f++);else for(f in a)if(e=b.call(a[f],f,a[f]),e===!1)break;return a},trim:jb&&!jb.call(" ")?function(a){return null==a?"":jb.call(a)}:function(a){return null==a?"":(a+"").replace(nb,"")},makeArray:function(a,b){var d=b||[];return null!=a&&(c(Object(a))?kb.merge(d,"string"==typeof a?[a]:a):eb.call(d,a)),d},inArray:function(a,b,c){var d;if(b){if(gb)return gb.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if("number"==typeof d)for(;d>f;f++)a[e++]=c[f];else for(;c[f]!==b;)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;for(c=!!c;g>f;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,b,d){var e,f=0,g=a.length,h=c(a),i=[];if(h)for(;g>f;f++)e=b(a[f],f,d),null!=e&&(i[i.length]=e);else for(f in a)e=b(a[f],f,d),null!=e&&(i[i.length]=e);return db.apply([],i)},guid:1,proxy:function(a,c){var d,e,f;return"string"==typeof c&&(f=a[c],c=a,a=f),kb.isFunction(a)?(d=fb.call(arguments,2),e=function(){return a.apply(c||this,d.concat(fb.call(arguments)))},e.guid=a.guid=a.guid||kb.guid++,e):b},access:function(a,c,d,e,f,g,h){var i=0,j=a.length,k=null==d;if("object"===kb.type(d)){f=!0;for(i in d)kb.access(a,c,i,d[i],!0,g,h)}else if(e!==b&&(f=!0,kb.isFunction(e)||(h=!0),k&&(h?(c.call(a,e),c=null):(k=c,c=function(a,b,c){return k.call(kb(a),c)})),c))for(;j>i;i++)c(a[i],d,h?e:e.call(a[i],i,c(a[i],d)));return f?a:k?c.call(a):j?c(a[0],d):g},now:function(){return(new Date).getTime()},swap:function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e}}),kb.ready.promise=function(b){if(!U)if(U=kb.Deferred(),"complete"===Y.readyState)setTimeout(kb.ready);else if(Y.addEventListener)Y.addEventListener("DOMContentLoaded",xb,!1),a.addEventListener("load",xb,!1);else{Y.attachEvent("onreadystatechange",xb),a.attachEvent("onload",xb);var c=!1;try{c=null==a.frameElement&&Y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!kb.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}yb(),kb.ready()}}()}return U.promise(b)},kb.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){ab["[object "+b+"]"]=b.toLowerCase()}),V=kb(Y),function(a,b){function c(a,b,c,d){var e,f,g,h,i,j,k,l,o,p;if((b?b.ownerDocument||b:O)!==G&&F(b),b=b||G,c=c||[],!a||"string"!=typeof a)return c;if(1!==(h=b.nodeType)&&9!==h)return[];if(I&&!d){if(e=tb.exec(a))if(g=e[1]){if(9===h){if(f=b.getElementById(g),!f||!f.parentNode)return c;if(f.id===g)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(g))&&M(b,f)&&f.id===g)return c.push(f),c}else{if(e[2])return ab.apply(c,b.getElementsByTagName(a)),c;if((g=e[3])&&x.getElementsByClassName&&b.getElementsByClassName)return ab.apply(c,b.getElementsByClassName(g)),c}if(x.qsa&&(!J||!J.test(a))){if(l=k=N,o=b,p=9===h&&a,1===h&&"object"!==b.nodeName.toLowerCase()){for(j=m(a),(k=b.getAttribute("id"))?l=k.replace(wb,"\\$&"):b.setAttribute("id",l),l="[id='"+l+"'] ",i=j.length;i--;)j[i]=l+n(j[i]);o=nb.test(a)&&b.parentNode||b,p=j.join(",")}if(p)try{return ab.apply(c,o.querySelectorAll(p)),c}catch(q){}finally{k||b.removeAttribute("id")}}}return v(a.replace(jb,"$1"),b,c,d)}function d(){function a(c,d){return b.push(c+=" ")>z.cacheLength&&delete a[b.shift()],a[c]=d}var b=[];return a}function e(a){return a[N]=!0,a}function f(a){var b=G.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function g(a,b){for(var c=a.split("|"),d=a.length;d--;)z.attrHandle[c[d]]=b}function h(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||X)-(~a.sourceIndex||X);if(d)return d;if(c)for(;c=c.nextSibling;)if(c===b)return-1;return a?1:-1}function i(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function j(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function k(a){return e(function(b){return b=+b,e(function(c,d){for(var e,f=a([],c.length,b),g=f.length;g--;)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function l(){}function m(a,b){var d,e,f,g,h,i,j,k=S[a+" "];if(k)return b?0:k.slice(0);for(h=a,i=[],j=z.preFilter;h;){(!d||(e=lb.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),d=!1,(e=mb.exec(h))&&(d=e.shift(),f.push({value:d,type:e[0].replace(jb," ")}),h=h.slice(d.length));for(g in z.filter)!(e=rb[g].exec(h))||j[g]&&!(e=j[g](e))||(d=e.shift(),f.push({value:d,type:g,matches:e}),h=h.slice(d.length));if(!d)break}return b?h.length:h?c.error(a):S(a,i).slice(0)}function n(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function o(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=Q++;return b.first?function(b,c,f){for(;b=b[d];)if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=P+" "+f;if(g){for(;b=b[d];)if((1===b.nodeType||e)&&a(b,c,g))return!0}else for(;b=b[d];)if(1===b.nodeType||e)if(j=b[N]||(b[N]={}),(i=j[d])&&i[0]===k){if((h=i[1])===!0||h===y)return h===!0}else if(i=j[d]=[k],i[1]=a(b,c,g)||y,i[1]===!0)return!0}}function p(a){return a.length>1?function(b,c,d){for(var e=a.length;e--;)if(!a[e](b,c,d))return!1;return!0}:a[0]}function q(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function r(a,b,c,d,f,g){return d&&!d[N]&&(d=r(d)),f&&!f[N]&&(f=r(f,g)),e(function(e,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=e||u(b||"*",h.nodeType?[h]:h,[]),r=!a||!e&&b?p:q(p,m,a,h,i),s=c?f||(e?a:o||d)?[]:g:r;if(c&&c(r,s,h,i),d)for(j=q(s,n),d(j,[],h,i),k=j.length;k--;)(l=j[k])&&(s[n[k]]=!(r[n[k]]=l));if(e){if(f||a){if(f){for(j=[],k=s.length;k--;)(l=s[k])&&j.push(r[k]=l);f(null,s=[],j,i)}for(k=s.length;k--;)(l=s[k])&&(j=f?cb.call(e,l):m[k])>-1&&(e[j]=!(g[j]=l))}}else s=q(s===g?s.splice(o,s.length):s),f?f(null,g,s,i):ab.apply(g,s)})}function s(a){for(var b,c,d,e=a.length,f=z.relative[a[0].type],g=f||z.relative[" "],h=f?1:0,i=o(function(a){return a===b},g,!0),j=o(function(a){return cb.call(b,a)>-1},g,!0),k=[function(a,c,d){return!f&&(d||c!==D)||((b=c).nodeType?i(a,c,d):j(a,c,d))}];e>h;h++)if(c=z.relative[a[h].type])k=[o(p(k),c)];else{if(c=z.filter[a[h].type].apply(null,a[h].matches),c[N]){for(d=++h;e>d&&!z.relative[a[d].type];d++);return r(h>1&&p(k),h>1&&n(a.slice(0,h-1).concat({value:" "===a[h-2].type?"*":""})).replace(jb,"$1"),c,d>h&&s(a.slice(h,d)),e>d&&s(a=a.slice(d)),e>d&&n(a))}k.push(c)}return p(k)}function t(a,b){var d=0,f=b.length>0,g=a.length>0,h=function(e,h,i,j,k){var l,m,n,o=[],p=0,r="0",s=e&&[],t=null!=k,u=D,v=e||g&&z.find.TAG("*",k&&h.parentNode||h),w=P+=null==u?1:Math.random()||.1;for(t&&(D=h!==G&&h,y=d);null!=(l=v[r]);r++){if(g&&l){for(m=0;n=a[m++];)if(n(l,h,i)){j.push(l);break}t&&(P=w,y=++d)}f&&((l=!n&&l)&&p--,e&&s.push(l))}if(p+=r,f&&r!==p){for(m=0;n=b[m++];)n(s,o,h,i);if(e){if(p>0)for(;r--;)s[r]||o[r]||(o[r]=$.call(j));o=q(o)}ab.apply(j,o),t&&!e&&o.length>0&&p+b.length>1&&c.uniqueSort(j)}return t&&(P=w,D=u),s};return f?e(h):h}function u(a,b,d){for(var e=0,f=b.length;f>e;e++)c(a,b[e],d);return d}function v(a,b,c,d){var e,f,g,h,i,j=m(a);if(!d&&1===j.length){if(f=j[0]=j[0].slice(0),f.length>2&&"ID"===(g=f[0]).type&&x.getById&&9===b.nodeType&&I&&z.relative[f[1].type]){if(b=(z.find.ID(g.matches[0].replace(xb,yb),b)||[])[0],!b)return c;a=a.slice(f.shift().value.length)}for(e=rb.needsContext.test(a)?0:f.length;e--&&(g=f[e],!z.relative[h=g.type]);)if((i=z.find[h])&&(d=i(g.matches[0].replace(xb,yb),nb.test(f[0].type)&&b.parentNode||b))){if(f.splice(e,1),a=d.length&&n(f),!a)return ab.apply(c,d),c;break}}return C(a,j)(d,b,!I,c,nb.test(a)),c}var w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N="sizzle"+-new Date,O=a.document,P=0,Q=0,R=d(),S=d(),T=d(),U=!1,V=function(a,b){return a===b?(U=!0,0):0},W=typeof b,X=1<<31,Y={}.hasOwnProperty,Z=[],$=Z.pop,_=Z.push,ab=Z.push,bb=Z.slice,cb=Z.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},db="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",eb="[\\x20\\t\\r\\n\\f]",fb="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",gb=fb.replace("w","w#"),hb="\\["+eb+"*("+fb+")"+eb+"*(?:([*^$|!~]?=)"+eb+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+gb+")|)|)"+eb+"*\\]",ib=":("+fb+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+hb.replace(3,8)+")*)|.*)\\)|)",jb=new RegExp("^"+eb+"+|((?:^|[^\\\\])(?:\\\\.)*)"+eb+"+$","g"),lb=new RegExp("^"+eb+"*,"+eb+"*"),mb=new RegExp("^"+eb+"*([>+~]|"+eb+")"+eb+"*"),nb=new RegExp(eb+"*[+~]"),ob=new RegExp("="+eb+"*([^\\]'\"]*)"+eb+"*\\]","g"),pb=new RegExp(ib),qb=new RegExp("^"+gb+"$"),rb={ID:new RegExp("^#("+fb+")"),CLASS:new RegExp("^\\.("+fb+")"),TAG:new RegExp("^("+fb.replace("w","w*")+")"),ATTR:new RegExp("^"+hb),PSEUDO:new RegExp("^"+ib),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+eb+"*(even|odd|(([+-]|)(\\d*)n|)"+eb+"*(?:([+-]|)"+eb+"*(\\d+)|))"+eb+"*\\)|)","i"),bool:new RegExp("^(?:"+db+")$","i"),needsContext:new RegExp("^"+eb+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+eb+"*((?:-\\d)?\\d*)"+eb+"*\\)|)(?=[^-]|$)","i")},sb=/^[^{]+\{\s*\[native \w/,tb=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ub=/^(?:input|select|textarea|button)$/i,vb=/^h\d$/i,wb=/'|\\/g,xb=new RegExp("\\\\([\\da-f]{1,6}"+eb+"?|("+eb+")|.)","ig"),yb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{ab.apply(Z=bb.call(O.childNodes),O.childNodes),Z[O.childNodes.length].nodeType}catch(zb){ab={apply:Z.length?function(a,b){_.apply(a,bb.call(b))}:function(a,b){for(var c=a.length,d=0;a[c++]=b[d++];);a.length=c-1}}}B=c.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},x=c.support={},F=c.setDocument=function(a){var b=a?a.ownerDocument||a:O,c=b.defaultView;return b!==G&&9===b.nodeType&&b.documentElement?(G=b,H=b.documentElement,I=!B(b),c&&c.attachEvent&&c!==c.top&&c.attachEvent("onbeforeunload",function(){F()}),x.attributes=f(function(a){return a.className="i",!a.getAttribute("className")}),x.getElementsByTagName=f(function(a){return a.appendChild(b.createComment("")),!a.getElementsByTagName("*").length}),x.getElementsByClassName=f(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),x.getById=f(function(a){return H.appendChild(a).id=N,!b.getElementsByName||!b.getElementsByName(N).length}),x.getById?(z.find.ID=function(a,b){if(typeof b.getElementById!==W&&I){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},z.filter.ID=function(a){var b=a.replace(xb,yb);return function(a){return a.getAttribute("id")===b}}):(delete z.find.ID,z.filter.ID=function(a){var b=a.replace(xb,yb);return function(a){var c=typeof a.getAttributeNode!==W&&a.getAttributeNode("id");return c&&c.value===b}}),z.find.TAG=x.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==W?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){for(;c=f[e++];)1===c.nodeType&&d.push(c);return d}return f},z.find.CLASS=x.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==W&&I?b.getElementsByClassName(a):void 0},K=[],J=[],(x.qsa=sb.test(b.querySelectorAll))&&(f(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||J.push("\\["+eb+"*(?:value|"+db+")"),a.querySelectorAll(":checked").length||J.push(":checked")}),f(function(a){var c=b.createElement("input");c.setAttribute("type","hidden"),a.appendChild(c).setAttribute("t",""),a.querySelectorAll("[t^='']").length&&J.push("[*^$]="+eb+"*(?:''|\"\")"),a.querySelectorAll(":enabled").length||J.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),J.push(",.*:")})),(x.matchesSelector=sb.test(L=H.webkitMatchesSelector||H.mozMatchesSelector||H.oMatchesSelector||H.msMatchesSelector))&&f(function(a){x.disconnectedMatch=L.call(a,"div"),L.call(a,"[s!='']:x"),K.push("!=",ib)}),J=J.length&&new RegExp(J.join("|")),K=K.length&&new RegExp(K.join("|")),M=sb.test(H.contains)||H.compareDocumentPosition?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)for(;b=b.parentNode;)if(b===a)return!0;return!1},V=H.compareDocumentPosition?function(a,c){if(a===c)return U=!0,0;var d=c.compareDocumentPosition&&a.compareDocumentPosition&&a.compareDocumentPosition(c);return d?1&d||!x.sortDetached&&c.compareDocumentPosition(a)===d?a===b||M(O,a)?-1:c===b||M(O,c)?1:E?cb.call(E,a)-cb.call(E,c):0:4&d?-1:1:a.compareDocumentPosition?-1:1}:function(a,c){var d,e=0,f=a.parentNode,g=c.parentNode,i=[a],j=[c];if(a===c)return U=!0,0;if(!f||!g)return a===b?-1:c===b?1:f?-1:g?1:E?cb.call(E,a)-cb.call(E,c):0;if(f===g)return h(a,c);for(d=a;d=d.parentNode;)i.unshift(d);for(d=c;d=d.parentNode;)j.unshift(d);for(;i[e]===j[e];)e++;return e?h(i[e],j[e]):i[e]===O?-1:j[e]===O?1:0},b):G},c.matches=function(a,b){return c(a,null,null,b)},c.matchesSelector=function(a,b){if((a.ownerDocument||a)!==G&&F(a),b=b.replace(ob,"='$1']"),!(!x.matchesSelector||!I||K&&K.test(b)||J&&J.test(b)))try{var d=L.call(a,b);if(d||x.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return c(b,G,null,[a]).length>0},c.contains=function(a,b){return(a.ownerDocument||a)!==G&&F(a),M(a,b)},c.attr=function(a,c){(a.ownerDocument||a)!==G&&F(a);var d=z.attrHandle[c.toLowerCase()],e=d&&Y.call(z.attrHandle,c.toLowerCase())?d(a,c,!I):b;return e===b?x.attributes||!I?a.getAttribute(c):(e=a.getAttributeNode(c))&&e.specified?e.value:null:e},c.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},c.uniqueSort=function(a){var b,c=[],d=0,e=0;if(U=!x.detectDuplicates,E=!x.sortStable&&a.slice(0),a.sort(V),U){for(;b=a[e++];)b===a[e]&&(d=c.push(e));for(;d--;)a.splice(c[d],1)}return a},A=c.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(1===e||9===e||11===e){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=A(a)}else if(3===e||4===e)return a.nodeValue}else for(;b=a[d];d++)c+=A(b);return c},z=c.selectors={cacheLength:50,createPseudo:e,match:rb,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(xb,yb),a[3]=(a[4]||a[5]||"").replace(xb,yb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||c.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&c.error(a[0]),a},PSEUDO:function(a){var c,d=!a[5]&&a[2];return rb.CHILD.test(a[0])?null:(a[3]&&a[4]!==b?a[2]=a[4]:d&&pb.test(d)&&(c=m(d,!0))&&(c=d.indexOf(")",d.length-c)-d.length)&&(a[0]=a[0].slice(0,c),a[2]=d.slice(0,c)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(xb,yb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=R[a+" "];return b||(b=new RegExp("(^|"+eb+")"+a+"("+eb+"|$)"))&&R(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==W&&a.getAttribute("class")||"")})},ATTR:function(a,b,d){return function(e){var f=c.attr(e,a);return null==f?"!="===b:b?(f+="","="===b?f===d:"!="===b?f!==d:"^="===b?d&&0===f.indexOf(d):"*="===b?d&&f.indexOf(d)>-1:"$="===b?d&&f.slice(-d.length)===d:"~="===b?(" "+f+" ").indexOf(d)>-1:"|="===b?f===d||f.slice(0,d.length+1)===d+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;
-return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){for(;p;){for(l=b;l=l[p];)if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){for(k=q[N]||(q[N]={}),j=k[a]||[],n=j[0]===P&&j[1],m=j[0]===P&&j[2],l=n&&q.childNodes[n];l=++n&&l&&l[p]||(m=n=0)||o.pop();)if(1===l.nodeType&&++m&&l===b){k[a]=[P,n,m];break}}else if(s&&(j=(b[N]||(b[N]={}))[a])&&j[0]===P)m=j[1];else for(;(l=++n&&l&&l[p]||(m=n=0)||o.pop())&&((h?l.nodeName.toLowerCase()!==r:1!==l.nodeType)||!++m||(s&&((l[N]||(l[N]={}))[a]=[P,m]),l!==b)););return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var d,f=z.pseudos[a]||z.setFilters[a.toLowerCase()]||c.error("unsupported pseudo: "+a);return f[N]?f(b):f.length>1?(d=[a,a,"",b],z.setFilters.hasOwnProperty(a.toLowerCase())?e(function(a,c){for(var d,e=f(a,b),g=e.length;g--;)d=cb.call(a,e[g]),a[d]=!(c[d]=e[g])}):function(a){return f(a,0,d)}):f}},pseudos:{not:e(function(a){var b=[],c=[],d=C(a.replace(jb,"$1"));return d[N]?e(function(a,b,c,e){for(var f,g=d(a,null,e,[]),h=a.length;h--;)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:e(function(a){return function(b){return c(a,b).length>0}}),contains:e(function(a){return function(b){return(b.textContent||b.innerText||A(b)).indexOf(a)>-1}}),lang:e(function(a){return qb.test(a||"")||c.error("unsupported lang: "+a),a=a.replace(xb,yb).toLowerCase(),function(b){var c;do if(c=I?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===H},focus:function(a){return a===G.activeElement&&(!G.hasFocus||G.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeName>"@"||3===a.nodeType||4===a.nodeType)return!1;return!0},parent:function(a){return!z.pseudos.empty(a)},header:function(a){return vb.test(a.nodeName)},input:function(a){return ub.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||b.toLowerCase()===a.type)},first:k(function(){return[0]}),last:k(function(a,b){return[b-1]}),eq:k(function(a,b,c){return[0>c?c+b:c]}),even:k(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:k(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:k(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:k(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},z.pseudos.nth=z.pseudos.eq;for(w in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})z.pseudos[w]=i(w);for(w in{submit:!0,reset:!0})z.pseudos[w]=j(w);l.prototype=z.filters=z.pseudos,z.setFilters=new l,C=c.compile=function(a,b){var c,d=[],e=[],f=T[a+" "];if(!f){for(b||(b=m(a)),c=b.length;c--;)f=s(b[c]),f[N]?d.push(f):e.push(f);f=T(a,t(e,d))}return f},x.sortStable=N.split("").sort(V).join("")===N,x.detectDuplicates=U,F(),x.sortDetached=f(function(a){return 1&a.compareDocumentPosition(G.createElement("div"))}),f(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||g("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),x.attributes&&f(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||g("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),f(function(a){return null==a.getAttribute("disabled")})||g(db,function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&d.specified?d.value:a[b]===!0?b.toLowerCase():null}),kb.find=c,kb.expr=c.selectors,kb.expr[":"]=kb.expr.pseudos,kb.unique=c.uniqueSort,kb.text=c.getText,kb.isXMLDoc=c.isXML,kb.contains=c.contains}(a);var zb={};kb.Callbacks=function(a){a="string"==typeof a?zb[a]||d(a):kb.extend({},a);var c,e,f,g,h,i,j=[],k=!a.once&&[],l=function(b){for(e=a.memory&&b,f=!0,h=i||0,i=0,g=j.length,c=!0;j&&g>h;h++)if(j[h].apply(b[0],b[1])===!1&&a.stopOnFalse){e=!1;break}c=!1,j&&(k?k.length&&l(k.shift()):e?j=[]:m.disable())},m={add:function(){if(j){var b=j.length;!function d(b){kb.each(b,function(b,c){var e=kb.type(c);"function"===e?a.unique&&m.has(c)||j.push(c):c&&c.length&&"string"!==e&&d(c)})}(arguments),c?g=j.length:e&&(i=b,l(e))}return this},remove:function(){return j&&kb.each(arguments,function(a,b){for(var d;(d=kb.inArray(b,j,d))>-1;)j.splice(d,1),c&&(g>=d&&g--,h>=d&&h--)}),this},has:function(a){return a?kb.inArray(a,j)>-1:!(!j||!j.length)},empty:function(){return j=[],g=0,this},disable:function(){return j=k=e=b,this},disabled:function(){return!j},lock:function(){return k=b,e||m.disable(),this},locked:function(){return!k},fireWith:function(a,b){return!j||f&&!k||(b=b||[],b=[a,b.slice?b.slice():b],c?k.push(b):l(b)),this},fire:function(){return m.fireWith(this,arguments),this},fired:function(){return!!f}};return m},kb.extend({Deferred:function(a){var b=[["resolve","done",kb.Callbacks("once memory"),"resolved"],["reject","fail",kb.Callbacks("once memory"),"rejected"],["notify","progress",kb.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return kb.Deferred(function(c){kb.each(b,function(b,f){var g=f[0],h=kb.isFunction(a[b])&&a[b];e[f[1]](function(){var a=h&&h.apply(this,arguments);a&&kb.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[g+"With"](this===d?c.promise():this,h?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?kb.extend(a,d):d}},e={};return d.pipe=d.then,kb.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b,c,d,e=0,f=fb.call(arguments),g=f.length,h=1!==g||a&&kb.isFunction(a.promise)?g:0,i=1===h?a:kb.Deferred(),j=function(a,c,d){return function(e){c[a]=this,d[a]=arguments.length>1?fb.call(arguments):e,d===b?i.notifyWith(c,d):--h||i.resolveWith(c,d)}};if(g>1)for(b=new Array(g),c=new Array(g),d=new Array(g);g>e;e++)f[e]&&kb.isFunction(f[e].promise)?f[e].promise().done(j(e,d,f)).fail(i.reject).progress(j(e,c,b)):--h;return h||i.resolveWith(d,f),i.promise()}}),kb.support=function(b){var c,d,e,f,g,h,i,j,k,l=Y.createElement("div");if(l.setAttribute("className","t"),l.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=l.getElementsByTagName("*")||[],d=l.getElementsByTagName("a")[0],!d||!d.style||!c.length)return b;f=Y.createElement("select"),h=f.appendChild(Y.createElement("option")),e=l.getElementsByTagName("input")[0],d.style.cssText="top:1px;float:left;opacity:.5",b.getSetAttribute="t"!==l.className,b.leadingWhitespace=3===l.firstChild.nodeType,b.tbody=!l.getElementsByTagName("tbody").length,b.htmlSerialize=!!l.getElementsByTagName("link").length,b.style=/top/.test(d.getAttribute("style")),b.hrefNormalized="/a"===d.getAttribute("href"),b.opacity=/^0.5/.test(d.style.opacity),b.cssFloat=!!d.style.cssFloat,b.checkOn=!!e.value,b.optSelected=h.selected,b.enctype=!!Y.createElement("form").enctype,b.html5Clone="<:nav></:nav>"!==Y.createElement("nav").cloneNode(!0).outerHTML,b.inlineBlockNeedsLayout=!1,b.shrinkWrapBlocks=!1,b.pixelPosition=!1,b.deleteExpando=!0,b.noCloneEvent=!0,b.reliableMarginRight=!0,b.boxSizingReliable=!0,e.checked=!0,b.noCloneChecked=e.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!h.disabled;try{delete l.test}catch(m){b.deleteExpando=!1}e=Y.createElement("input"),e.setAttribute("value",""),b.input=""===e.getAttribute("value"),e.value="t",e.setAttribute("type","radio"),b.radioValue="t"===e.value,e.setAttribute("checked","t"),e.setAttribute("name","t"),g=Y.createDocumentFragment(),g.appendChild(e),b.appendChecked=e.checked,b.checkClone=g.cloneNode(!0).cloneNode(!0).lastChild.checked,l.attachEvent&&(l.attachEvent("onclick",function(){b.noCloneEvent=!1}),l.cloneNode(!0).click());for(k in{submit:!0,change:!0,focusin:!0})l.setAttribute(i="on"+k,"t"),b[k+"Bubbles"]=i in a||l.attributes[i].expando===!1;l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",b.clearCloneStyle="content-box"===l.style.backgroundClip;for(k in kb(b))break;return b.ownLast="0"!==k,kb(function(){var c,d,e,f="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",g=Y.getElementsByTagName("body")[0];g&&(c=Y.createElement("div"),c.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",g.appendChild(c).appendChild(l),l.innerHTML="<table><tr><td></td><td>t</td></tr></table>",e=l.getElementsByTagName("td"),e[0].style.cssText="padding:0;margin:0;border:0;display:none",j=0===e[0].offsetHeight,e[0].style.display="",e[1].style.display="none",b.reliableHiddenOffsets=j&&0===e[0].offsetHeight,l.innerHTML="",l.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",kb.swap(g,null!=g.style.zoom?{zoom:1}:{},function(){b.boxSizing=4===l.offsetWidth}),a.getComputedStyle&&(b.pixelPosition="1%"!==(a.getComputedStyle(l,null)||{}).top,b.boxSizingReliable="4px"===(a.getComputedStyle(l,null)||{width:"4px"}).width,d=l.appendChild(Y.createElement("div")),d.style.cssText=l.style.cssText=f,d.style.marginRight=d.style.width="0",l.style.width="1px",b.reliableMarginRight=!parseFloat((a.getComputedStyle(d,null)||{}).marginRight)),typeof l.style.zoom!==W&&(l.innerHTML="",l.style.cssText=f+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=3===l.offsetWidth,l.style.display="block",l.innerHTML="<div></div>",l.firstChild.style.width="5px",b.shrinkWrapBlocks=3!==l.offsetWidth,b.inlineBlockNeedsLayout&&(g.style.zoom=1)),g.removeChild(c),c=l=e=d=null)}),c=f=g=h=d=e=null,b}({});var Ab=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,Bb=/([A-Z])/g;kb.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?kb.cache[a[kb.expando]]:a[kb.expando],!!a&&!h(a)},data:function(a,b,c){return e(a,b,c)},removeData:function(a,b){return f(a,b)},_data:function(a,b,c){return e(a,b,c,!0)},_removeData:function(a,b){return f(a,b,!0)},acceptData:function(a){if(a.nodeType&&1!==a.nodeType&&9!==a.nodeType)return!1;var b=a.nodeName&&kb.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),kb.fn.extend({data:function(a,c){var d,e,f=null,h=0,i=this[0];if(a===b){if(this.length&&(f=kb.data(i),1===i.nodeType&&!kb._data(i,"parsedAttrs"))){for(d=i.attributes;h<d.length;h++)e=d[h].name,0===e.indexOf("data-")&&(e=kb.camelCase(e.slice(5)),g(i,e,f[e]));kb._data(i,"parsedAttrs",!0)}return f}return"object"==typeof a?this.each(function(){kb.data(this,a)}):arguments.length>1?this.each(function(){kb.data(this,a,c)}):i?g(i,a,kb.data(i,a)):null},removeData:function(a){return this.each(function(){kb.removeData(this,a)})}}),kb.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=kb._data(a,b),c&&(!d||kb.isArray(c)?d=kb._data(a,b,kb.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=kb.queue(a,b),d=c.length,e=c.shift(),f=kb._queueHooks(a,b),g=function(){kb.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return kb._data(a,c)||kb._data(a,c,{empty:kb.Callbacks("once memory").add(function(){kb._removeData(a,b+"queue"),kb._removeData(a,c)})})}}),kb.fn.extend({queue:function(a,c){var d=2;return"string"!=typeof a&&(c=a,a="fx",d--),arguments.length<d?kb.queue(this[0],a):c===b?this:this.each(function(){var b=kb.queue(this,a,c);kb._queueHooks(this,a),"fx"===a&&"inprogress"!==b[0]&&kb.dequeue(this,a)})},dequeue:function(a){return this.each(function(){kb.dequeue(this,a)})},delay:function(a,b){return a=kb.fx?kb.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=kb.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};for("string"!=typeof a&&(c=a,a=b),a=a||"fx";h--;)d=kb._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var Cb,Db,Eb=/[\t\r\n\f]/g,Fb=/\r/g,Gb=/^(?:input|select|textarea|button|object)$/i,Hb=/^(?:a|area)$/i,Ib=/^(?:checked|selected)$/i,Jb=kb.support.getSetAttribute,Kb=kb.support.input;kb.fn.extend({attr:function(a,b){return kb.access(this,kb.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){kb.removeAttr(this,a)})},prop:function(a,b){return kb.access(this,kb.prop,a,b,arguments.length>1)},removeProp:function(a){return a=kb.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g=0,h=this.length,i="string"==typeof a&&a;if(kb.isFunction(a))return this.each(function(b){kb(this).addClass(a.call(this,b,this.className))});if(i)for(b=(a||"").match(mb)||[];h>g;g++)if(c=this[g],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(Eb," "):" ")){for(f=0;e=b[f++];)d.indexOf(" "+e+" ")<0&&(d+=e+" ");c.className=kb.trim(d)}return this},removeClass:function(a){var b,c,d,e,f,g=0,h=this.length,i=0===arguments.length||"string"==typeof a&&a;if(kb.isFunction(a))return this.each(function(b){kb(this).removeClass(a.call(this,b,this.className))});if(i)for(b=(a||"").match(mb)||[];h>g;g++)if(c=this[g],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(Eb," "):"")){for(f=0;e=b[f++];)for(;d.indexOf(" "+e+" ")>=0;)d=d.replace(" "+e+" "," ");c.className=a?kb.trim(d):""}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(kb.isFunction(a)?function(c){kb(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c)for(var b,d=0,e=kb(this),f=a.match(mb)||[];b=f[d++];)e.hasClass(b)?e.removeClass(b):e.addClass(b);else(c===W||"boolean"===c)&&(this.className&&kb._data(this,"__className__",this.className),this.className=this.className||a===!1?"":kb._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(Eb," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];{if(arguments.length)return e=kb.isFunction(a),this.each(function(c){var f;1===this.nodeType&&(f=e?a.call(this,c,kb(this).val()):a,null==f?f="":"number"==typeof f?f+="":kb.isArray(f)&&(f=kb.map(f,function(a){return null==a?"":a+""})),d=kb.valHooks[this.type]||kb.valHooks[this.nodeName.toLowerCase()],d&&"set"in d&&d.set(this,f,"value")!==b||(this.value=f))});if(f)return d=kb.valHooks[f.type]||kb.valHooks[f.nodeName.toLowerCase()],d&&"get"in d&&(c=d.get(f,"value"))!==b?c:(c=f.value,"string"==typeof c?c.replace(Fb,""):null==c?"":c)}}}),kb.extend({valHooks:{option:{get:function(a){var b=kb.find.attr(a,"value");return null!=b?b:a.text}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(kb.support.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&kb.nodeName(c.parentNode,"optgroup"))){if(b=kb(c).val(),f)return b;g.push(b)}return g},set:function(a,b){for(var c,d,e=a.options,f=kb.makeArray(b),g=e.length;g--;)d=e[g],(d.selected=kb.inArray(kb(d).val(),f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}},attr:function(a,c,d){var e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return typeof a.getAttribute===W?kb.prop(a,c,d):(1===g&&kb.isXMLDoc(a)||(c=c.toLowerCase(),e=kb.attrHooks[c]||(kb.expr.match.bool.test(c)?Db:Cb)),d===b?e&&"get"in e&&null!==(f=e.get(a,c))?f:(f=kb.find.attr(a,c),null==f?b:f):null!==d?e&&"set"in e&&(f=e.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d):void kb.removeAttr(a,c))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(mb);if(f&&1===a.nodeType)for(;c=f[e++];)d=kb.propFix[c]||c,kb.expr.match.bool.test(c)?Kb&&Jb||!Ib.test(c)?a[d]=!1:a[kb.camelCase("default-"+c)]=a[d]=!1:kb.attr(a,c,""),a.removeAttribute(Jb?c:d)},attrHooks:{type:{set:function(a,b){if(!kb.support.radioValue&&"radio"===b&&kb.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(a&&3!==h&&8!==h&&2!==h)return g=1!==h||!kb.isXMLDoc(a),g&&(c=kb.propFix[c]||c,f=kb.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&null!==(e=f.get(a,c))?e:a[c]},propHooks:{tabIndex:{get:function(a){var b=kb.find.attr(a,"tabindex");return b?parseInt(b,10):Gb.test(a.nodeName)||Hb.test(a.nodeName)&&a.href?0:-1}}}}),Db={set:function(a,b,c){return b===!1?kb.removeAttr(a,c):Kb&&Jb||!Ib.test(c)?a.setAttribute(!Jb&&kb.propFix[c]||c,c):a[kb.camelCase("default-"+c)]=a[c]=!0,c}},kb.each(kb.expr.match.bool.source.match(/\w+/g),function(a,c){var d=kb.expr.attrHandle[c]||kb.find.attr;kb.expr.attrHandle[c]=Kb&&Jb||!Ib.test(c)?function(a,c,e){var f=kb.expr.attrHandle[c],g=e?b:(kb.expr.attrHandle[c]=b)!=d(a,c,e)?c.toLowerCase():null;return kb.expr.attrHandle[c]=f,g}:function(a,c,d){return d?b:a[kb.camelCase("default-"+c)]?c.toLowerCase():null}}),Kb&&Jb||(kb.attrHooks.value={set:function(a,b,c){return kb.nodeName(a,"input")?void(a.defaultValue=b):Cb&&Cb.set(a,b,c)}}),Jb||(Cb={set:function(a,c,d){var e=a.getAttributeNode(d);return e||a.setAttributeNode(e=a.ownerDocument.createAttribute(d)),e.value=c+="","value"===d||c===a.getAttribute(d)?c:b}},kb.expr.attrHandle.id=kb.expr.attrHandle.name=kb.expr.attrHandle.coords=function(a,c,d){var e;return d?b:(e=a.getAttributeNode(c))&&""!==e.value?e.value:null},kb.valHooks.button={get:function(a,c){var d=a.getAttributeNode(c);return d&&d.specified?d.value:b},set:Cb.set},kb.attrHooks.contenteditable={set:function(a,b,c){Cb.set(a,""===b?!1:b,c)}},kb.each(["width","height"],function(a,b){kb.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),kb.support.hrefNormalized||kb.each(["href","src"],function(a,b){kb.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),kb.support.style||(kb.attrHooks.style={get:function(a){return a.style.cssText||b},set:function(a,b){return a.style.cssText=b+""}}),kb.support.optSelected||(kb.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),kb.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){kb.propFix[this.toLowerCase()]=this}),kb.support.enctype||(kb.propFix.enctype="encoding"),kb.each(["radio","checkbox"],function(){kb.valHooks[this]={set:function(a,b){return kb.isArray(b)?a.checked=kb.inArray(kb(a).val(),b)>=0:void 0}},kb.support.checkOn||(kb.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var Lb=/^(?:input|select|textarea)$/i,Mb=/^key/,Nb=/^(?:mouse|contextmenu)|click/,Ob=/^(?:focusinfocus|focusoutblur)$/,Pb=/^([^.]*)(?:\.(.+)|)$/;kb.event={global:{},add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,p,q,r=kb._data(a);if(r){for(d.handler&&(j=d,d=j.handler,f=j.selector),d.guid||(d.guid=kb.guid++),(h=r.events)||(h=r.events={}),(l=r.handle)||(l=r.handle=function(a){return typeof kb===W||a&&kb.event.triggered===a.type?b:kb.event.dispatch.apply(l.elem,arguments)},l.elem=a),c=(c||"").match(mb)||[""],i=c.length;i--;)g=Pb.exec(c[i])||[],o=q=g[1],p=(g[2]||"").split(".").sort(),o&&(k=kb.event.special[o]||{},o=(f?k.delegateType:k.bindType)||o,k=kb.event.special[o]||{},m=kb.extend({type:o,origType:q,data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&kb.expr.match.needsContext.test(f),namespace:p.join(".")},j),(n=h[o])||(n=h[o]=[],n.delegateCount=0,k.setup&&k.setup.call(a,e,p,l)!==!1||(a.addEventListener?a.addEventListener(o,l,!1):a.attachEvent&&a.attachEvent("on"+o,l))),k.add&&(k.add.call(a,m),m.handler.guid||(m.handler.guid=d.guid)),f?n.splice(n.delegateCount++,0,m):n.push(m),kb.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=kb.hasData(a)&&kb._data(a);if(q&&(k=q.events)){for(b=(b||"").match(mb)||[""],j=b.length;j--;)if(h=Pb.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){for(l=kb.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=k[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;f--;)g=m[f],!e&&p!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||kb.removeEvent(a,n,q.handle),delete k[n])}else for(n in k)kb.event.remove(a,n+b[j],c,d,!0);kb.isEmptyObject(k)&&(delete q.handle,kb._removeData(a,"events"))}},trigger:function(c,d,e,f){var g,h,i,j,k,l,m,n=[e||Y],o=ib.call(c,"type")?c.type:c,p=ib.call(c,"namespace")?c.namespace.split("."):[];if(i=l=e=e||Y,3!==e.nodeType&&8!==e.nodeType&&!Ob.test(o+kb.event.triggered)&&(o.indexOf(".")>=0&&(p=o.split("."),o=p.shift(),p.sort()),h=o.indexOf(":")<0&&"on"+o,c=c[kb.expando]?c:new kb.Event(o,"object"==typeof c&&c),c.isTrigger=f?2:3,c.namespace=p.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,c.result=b,c.target||(c.target=e),d=null==d?[c]:kb.makeArray(d,[c]),k=kb.event.special[o]||{},f||!k.trigger||k.trigger.apply(e,d)!==!1)){if(!f&&!k.noBubble&&!kb.isWindow(e)){for(j=k.delegateType||o,Ob.test(j+o)||(i=i.parentNode);i;i=i.parentNode)n.push(i),l=i;l===(e.ownerDocument||Y)&&n.push(l.defaultView||l.parentWindow||a)}for(m=0;(i=n[m++])&&!c.isPropagationStopped();)c.type=m>1?j:k.bindType||o,g=(kb._data(i,"events")||{})[c.type]&&kb._data(i,"handle"),g&&g.apply(i,d),g=h&&i[h],g&&kb.acceptData(i)&&g.apply&&g.apply(i,d)===!1&&c.preventDefault();if(c.type=o,!f&&!c.isDefaultPrevented()&&(!k._default||k._default.apply(n.pop(),d)===!1)&&kb.acceptData(e)&&h&&e[o]&&!kb.isWindow(e)){l=e[h],l&&(e[h]=null),kb.event.triggered=o;try{e[o]()}catch(q){}kb.event.triggered=b,l&&(e[h]=l)}return c.result}},dispatch:function(a){a=kb.event.fix(a);var c,d,e,f,g,h=[],i=fb.call(arguments),j=(kb._data(this,"events")||{})[a.type]||[],k=kb.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){for(h=kb.event.handlers.call(this,a,j),c=0;(f=h[c++])&&!a.isPropagationStopped();)for(a.currentTarget=f.elem,g=0;(e=f.handlers[g++])&&!a.isImmediatePropagationStopped();)(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,d=((kb.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),d!==b&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()));return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,c){var d,e,f,g,h=[],i=c.delegateCount,j=a.target;if(i&&j.nodeType&&(!a.button||"click"!==a.type))for(;j!=this;j=j.parentNode||this)if(1===j.nodeType&&(j.disabled!==!0||"click"!==a.type)){for(f=[],g=0;i>g;g++)e=c[g],d=e.selector+" ",f[d]===b&&(f[d]=e.needsContext?kb(d,this).index(j)>=0:kb.find(d,this,null,[j]).length),f[d]&&f.push(e);f.length&&h.push({elem:j,handlers:f})}return i<c.length&&h.push({elem:this,handlers:c.slice(i)}),h},fix:function(a){if(a[kb.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];for(g||(this.fixHooks[e]=g=Nb.test(e)?this.mouseHooks:Mb.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new kb.Event(f),b=d.length;b--;)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||Y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,e,f,g=c.button,h=c.fromElement;return null==a.pageX&&null!=c.clientX&&(e=a.target.ownerDocument||Y,f=e.documentElement,d=e.body,a.pageX=c.clientX+(f&&f.scrollLeft||d&&d.scrollLeft||0)-(f&&f.clientLeft||d&&d.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||d&&d.scrollTop||0)-(f&&f.clientTop||d&&d.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?c.toElement:h),a.which||g===b||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==k()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===k()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return kb.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return kb.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){a.result!==b&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=kb.extend(new kb.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?kb.event.trigger(e,null,b):kb.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},kb.removeEvent=Y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===W&&(a[d]=null),a.detachEvent(d,c))},kb.Event=function(a,b){return this instanceof kb.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?i:j):this.type=a,b&&kb.extend(this,b),this.timeStamp=a&&a.timeStamp||kb.now(),void(this[kb.expando]=!0)):new kb.Event(a,b)},kb.Event.prototype={isDefaultPrevented:j,isPropagationStopped:j,isImmediatePropagationStopped:j,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=i,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=i,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=i,this.stopPropagation()}},kb.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){kb.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!kb.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),kb.support.submitBubbles||(kb.event.special.submit={setup:function(){return kb.nodeName(this,"form")?!1:void kb.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=kb.nodeName(c,"input")||kb.nodeName(c,"button")?c.form:b;d&&!kb._data(d,"submitBubbles")&&(kb.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),kb._data(d,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&kb.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return kb.nodeName(this,"form")?!1:void kb.event.remove(this,"._submit")}}),kb.support.changeBubbles||(kb.event.special.change={setup:function(){return Lb.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(kb.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),kb.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),kb.event.simulate("change",this,a,!0)})),!1):void kb.event.add(this,"beforeactivate._change",function(a){var b=a.target;Lb.test(b.nodeName)&&!kb._data(b,"changeBubbles")&&(kb.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||kb.event.simulate("change",this.parentNode,a,!0)}),kb._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return kb.event.remove(this,"._change"),!Lb.test(this.nodeName)}}),kb.support.focusinBubbles||kb.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){kb.event.simulate(b,a.target,kb.event.fix(a),!0)};kb.event.special[b]={setup:function(){0===c++&&Y.addEventListener(a,d,!0)},teardown:function(){0===--c&&Y.removeEventListener(a,d,!0)}}}),kb.fn.extend({on:function(a,c,d,e,f){var g,h;if("object"==typeof a){"string"!=typeof c&&(d=d||c,c=b);for(g in a)this.on(g,c,d,a[g],f);return this}if(null==d&&null==e?(e=c,d=c=b):null==e&&("string"==typeof c?(e=d,d=b):(e=d,d=c,c=b)),e===!1)e=j;else if(!e)return this;return 1===f&&(h=e,e=function(a){return kb().off(a),h.apply(this,arguments)},e.guid=h.guid||(h.guid=kb.guid++)),this.each(function(){kb.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,kb(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if("object"==typeof a){for(f in a)this.off(f,c,a[f]);return this}return(c===!1||"function"==typeof c)&&(d=c,c=b),d===!1&&(d=j),this.each(function(){kb.event.remove(this,a,d,c)})},trigger:function(a,b){return this.each(function(){kb.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?kb.event.trigger(a,b,c,!0):void 0}});var Qb=/^.[^:#\[\.,]*$/,Rb=/^(?:parents|prev(?:Until|All))/,Sb=kb.expr.match.needsContext,Tb={children:!0,contents:!0,next:!0,prev:!0};kb.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(kb(a).filter(function(){for(b=0;e>b;b++)if(kb.contains(d[b],this))return!0}));for(b=0;e>b;b++)kb.find(a,d[b],c);return c=this.pushStack(e>1?kb.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},has:function(a){var b,c=kb(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(kb.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(m(this,a||[],!0))},filter:function(a){return this.pushStack(m(this,a||[],!1))},is:function(a){return!!m(this,"string"==typeof a&&Sb.test(a)?kb(a):a||[],!1).length},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=Sb.test(a)||"string"!=typeof a?kb(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&kb.find.matchesSelector(c,a))){c=f.push(c);break}return this.pushStack(f.length>1?kb.unique(f):f)},index:function(a){return a?"string"==typeof a?kb.inArray(this[0],kb(a)):kb.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){var c="string"==typeof a?kb(a,b):kb.makeArray(a&&a.nodeType?[a]:a),d=kb.merge(this.get(),c);return this.pushStack(kb.unique(d))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}}),kb.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null
-},parents:function(a){return kb.dir(a,"parentNode")},parentsUntil:function(a,b,c){return kb.dir(a,"parentNode",c)},next:function(a){return l(a,"nextSibling")},prev:function(a){return l(a,"previousSibling")},nextAll:function(a){return kb.dir(a,"nextSibling")},prevAll:function(a){return kb.dir(a,"previousSibling")},nextUntil:function(a,b,c){return kb.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return kb.dir(a,"previousSibling",c)},siblings:function(a){return kb.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return kb.sibling(a.firstChild)},contents:function(a){return kb.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:kb.merge([],a.childNodes)}},function(a,b){kb.fn[a]=function(c,d){var e=kb.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=kb.filter(d,e)),this.length>1&&(Tb[a]||(e=kb.unique(e)),Rb.test(a)&&(e=e.reverse())),this.pushStack(e)}}),kb.extend({filter:function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?kb.find.matchesSelector(d,a)?[d]:[]:kb.find.matches(a,kb.grep(b,function(a){return 1===a.nodeType}))},dir:function(a,c,d){for(var e=[],f=a[c];f&&9!==f.nodeType&&(d===b||1!==f.nodeType||!kb(f).is(d));)1===f.nodeType&&e.push(f),f=f[c];return e},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}});var Ub="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Vb=/ jQuery\d+="(?:null|\d+)"/g,Wb=new RegExp("<(?:"+Ub+")[\\s/>]","i"),Xb=/^\s+/,Yb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Zb=/<([\w:]+)/,$b=/<tbody/i,_b=/<|&#?\w+;/,ac=/<(?:script|style|link)/i,bc=/^(?:checkbox|radio)$/i,cc=/checked\s*(?:[^=]|=\s*.checked.)/i,dc=/^$|\/(?:java|ecma)script/i,ec=/^true\/(.*)/,fc=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,gc={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:kb.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},hc=n(Y),ic=hc.appendChild(Y.createElement("div"));gc.optgroup=gc.option,gc.tbody=gc.tfoot=gc.colgroup=gc.caption=gc.thead,gc.th=gc.td,kb.fn.extend({text:function(a){return kb.access(this,function(a){return a===b?kb.text(this):this.empty().append((this[0]&&this[0].ownerDocument||Y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=o(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=o(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?kb.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||kb.cleanData(u(c)),c.parentNode&&(b&&kb.contains(c.ownerDocument,c)&&r(u(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){for(1===a.nodeType&&kb.cleanData(u(a,!1));a.firstChild;)a.removeChild(a.firstChild);a.options&&kb.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return kb.clone(this,a,b)})},html:function(a){return kb.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return 1===c.nodeType?c.innerHTML.replace(Vb,""):b;if(!("string"!=typeof a||ac.test(a)||!kb.support.htmlSerialize&&Wb.test(a)||!kb.support.leadingWhitespace&&Xb.test(a)||gc[(Zb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(Yb,"<$1></$2>");try{for(;e>d;d++)c=this[d]||{},1===c.nodeType&&(kb.cleanData(u(c,!1)),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=kb.map(this,function(a){return[a.nextSibling,a.parentNode]}),b=0;return this.domManip(arguments,function(c){var d=a[b++],e=a[b++];e&&(d&&d.parentNode!==e&&(d=this.nextSibling),kb(this).remove(),e.insertBefore(c,d))},!0),b?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b,c){a=db.apply([],a);var d,e,f,g,h,i,j=0,k=this.length,l=this,m=k-1,n=a[0],o=kb.isFunction(n);if(o||!(1>=k||"string"!=typeof n||kb.support.checkClone)&&cc.test(n))return this.each(function(d){var e=l.eq(d);o&&(a[0]=n.call(this,d,e.html())),e.domManip(a,b,c)});if(k&&(i=kb.buildFragment(a,this[0].ownerDocument,!1,!c&&this),d=i.firstChild,1===i.childNodes.length&&(i=d),d)){for(g=kb.map(u(i,"script"),p),f=g.length;k>j;j++)e=i,j!==m&&(e=kb.clone(e,!0,!0),f&&kb.merge(g,u(e,"script"))),b.call(this[j],e,j);if(f)for(h=g[g.length-1].ownerDocument,kb.map(g,q),j=0;f>j;j++)e=g[j],dc.test(e.type||"")&&!kb._data(e,"globalEval")&&kb.contains(h,e)&&(e.src?kb._evalUrl(e.src):kb.globalEval((e.text||e.textContent||e.innerHTML||"").replace(fc,"")));i=d=null}return this}}),kb.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){kb.fn[a]=function(a){for(var c,d=0,e=[],f=kb(a),g=f.length-1;g>=d;d++)c=d===g?this:this.clone(!0),kb(f[d])[b](c),eb.apply(e,c.get());return this.pushStack(e)}}),kb.extend({clone:function(a,b,c){var d,e,f,g,h,i=kb.contains(a.ownerDocument,a);if(kb.support.html5Clone||kb.isXMLDoc(a)||!Wb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ic.innerHTML=a.outerHTML,ic.removeChild(f=ic.firstChild)),!(kb.support.noCloneEvent&&kb.support.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||kb.isXMLDoc(a)))for(d=u(f),h=u(a),g=0;null!=(e=h[g]);++g)d[g]&&t(e,d[g]);if(b)if(c)for(h=h||u(a),d=d||u(f),g=0;null!=(e=h[g]);g++)s(e,d[g]);else s(a,f);return d=u(f,"script"),d.length>0&&r(d,!i&&u(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,l=a.length,m=n(b),o=[],p=0;l>p;p++)if(f=a[p],f||0===f)if("object"===kb.type(f))kb.merge(o,f.nodeType?[f]:f);else if(_b.test(f)){for(h=h||m.appendChild(b.createElement("div")),i=(Zb.exec(f)||["",""])[1].toLowerCase(),k=gc[i]||gc._default,h.innerHTML=k[1]+f.replace(Yb,"<$1></$2>")+k[2],e=k[0];e--;)h=h.lastChild;if(!kb.support.leadingWhitespace&&Xb.test(f)&&o.push(b.createTextNode(Xb.exec(f)[0])),!kb.support.tbody)for(f="table"!==i||$b.test(f)?"<table>"!==k[1]||$b.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;e--;)kb.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j);for(kb.merge(o,h.childNodes),h.textContent="";h.firstChild;)h.removeChild(h.firstChild);h=m.lastChild}else o.push(b.createTextNode(f));for(h&&m.removeChild(h),kb.support.appendChecked||kb.grep(u(o,"input"),v),p=0;f=o[p++];)if((!d||-1===kb.inArray(f,d))&&(g=kb.contains(f.ownerDocument,f),h=u(m.appendChild(f),"script"),g&&r(h),c))for(e=0;f=h[e++];)dc.test(f.type||"")&&c.push(f);return h=null,m},cleanData:function(a,b){for(var c,d,e,f,g=0,h=kb.expando,i=kb.cache,j=kb.support.deleteExpando,k=kb.event.special;null!=(c=a[g]);g++)if((b||kb.acceptData(c))&&(e=c[h],f=e&&i[e])){if(f.events)for(d in f.events)k[d]?kb.event.remove(c,d):kb.removeEvent(c,d,f.handle);i[e]&&(delete i[e],j?delete c[h]:typeof c.removeAttribute!==W?c.removeAttribute(h):c[h]=null,bb.push(e))}},_evalUrl:function(a){return kb.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),kb.fn.extend({wrapAll:function(a){if(kb.isFunction(a))return this.each(function(b){kb(this).wrapAll(a.call(this,b))});if(this[0]){var b=kb(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){for(var a=this;a.firstChild&&1===a.firstChild.nodeType;)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(kb.isFunction(a)?function(b){kb(this).wrapInner(a.call(this,b))}:function(){var b=kb(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=kb.isFunction(a);return this.each(function(c){kb(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){kb.nodeName(this,"body")||kb(this).replaceWith(this.childNodes)}).end()}});var jc,kc,lc,mc=/alpha\([^)]*\)/i,nc=/opacity\s*=\s*([^)]*)/,oc=/^(top|right|bottom|left)$/,pc=/^(none|table(?!-c[ea]).+)/,qc=/^margin/,rc=new RegExp("^("+lb+")(.*)$","i"),sc=new RegExp("^("+lb+")(?!px)[a-z%]+$","i"),tc=new RegExp("^([+-])=("+lb+")","i"),uc={BODY:"block"},vc={position:"absolute",visibility:"hidden",display:"block"},wc={letterSpacing:0,fontWeight:400},xc=["Top","Right","Bottom","Left"],yc=["Webkit","O","Moz","ms"];kb.fn.extend({css:function(a,c){return kb.access(this,function(a,c,d){var e,f,g={},h=0;if(kb.isArray(c)){for(f=kc(a),e=c.length;e>h;h++)g[c[h]]=kb.css(a,c[h],!1,f);return g}return d!==b?kb.style(a,c,d):kb.css(a,c)},a,c,arguments.length>1)},show:function(){return y(this,!0)},hide:function(){return y(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){x(this)?kb(this).show():kb(this).hide()})}}),kb.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=lc(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":kb.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var f,g,h,i=kb.camelCase(c),j=a.style;if(c=kb.cssProps[i]||(kb.cssProps[i]=w(j,i)),h=kb.cssHooks[c]||kb.cssHooks[i],d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];if(g=typeof d,"string"===g&&(f=tc.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(kb.css(a,c)),g="number"),!(null==d||"number"===g&&isNaN(d)||("number"!==g||kb.cssNumber[i]||(d+="px"),kb.support.clearCloneStyle||""!==d||0!==c.indexOf("background")||(j[c]="inherit"),h&&"set"in h&&(d=h.set(a,d,e))===b)))try{j[c]=d}catch(k){}}},css:function(a,c,d,e){var f,g,h,i=kb.camelCase(c);return c=kb.cssProps[i]||(kb.cssProps[i]=w(a.style,i)),h=kb.cssHooks[c]||kb.cssHooks[i],h&&"get"in h&&(g=h.get(a,!0,d)),g===b&&(g=lc(a,c,e)),"normal"===g&&c in wc&&(g=wc[c]),""===d||d?(f=parseFloat(g),d===!0||kb.isNumeric(f)?f||0:g):g}}),a.getComputedStyle?(kc=function(b){return a.getComputedStyle(b,null)},lc=function(a,c,d){var e,f,g,h=d||kc(a),i=h?h.getPropertyValue(c)||h[c]:b,j=a.style;return h&&(""!==i||kb.contains(a.ownerDocument,a)||(i=kb.style(a,c)),sc.test(i)&&qc.test(c)&&(e=j.width,f=j.minWidth,g=j.maxWidth,j.minWidth=j.maxWidth=j.width=i,i=h.width,j.width=e,j.minWidth=f,j.maxWidth=g)),i}):Y.documentElement.currentStyle&&(kc=function(a){return a.currentStyle},lc=function(a,c,d){var e,f,g,h=d||kc(a),i=h?h[c]:b,j=a.style;return null==i&&j&&j[c]&&(i=j[c]),sc.test(i)&&!oc.test(c)&&(e=j.left,f=a.runtimeStyle,g=f&&f.left,g&&(f.left=a.currentStyle.left),j.left="fontSize"===c?"1em":i,i=j.pixelLeft+"px",j.left=e,g&&(f.left=g)),""===i?"auto":i}),kb.each(["height","width"],function(a,b){kb.cssHooks[b]={get:function(a,c,d){return c?0===a.offsetWidth&&pc.test(kb.css(a,"display"))?kb.swap(a,vc,function(){return B(a,b,d)}):B(a,b,d):void 0},set:function(a,c,d){var e=d&&kc(a);return z(a,c,d?A(a,b,d,kb.support.boxSizing&&"border-box"===kb.css(a,"boxSizing",!1,e),e):0)}}}),kb.support.opacity||(kb.cssHooks.opacity={get:function(a,b){return nc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=kb.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===kb.trim(f.replace(mc,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=mc.test(f)?f.replace(mc,e):f+" "+e)}}),kb(function(){kb.support.reliableMarginRight||(kb.cssHooks.marginRight={get:function(a,b){return b?kb.swap(a,{display:"inline-block"},lc,[a,"marginRight"]):void 0}}),!kb.support.pixelPosition&&kb.fn.position&&kb.each(["top","left"],function(a,b){kb.cssHooks[b]={get:function(a,c){return c?(c=lc(a,b),sc.test(c)?kb(a).position()[b]+"px":c):void 0}}})}),kb.expr&&kb.expr.filters&&(kb.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!kb.support.reliableHiddenOffsets&&"none"===(a.style&&a.style.display||kb.css(a,"display"))},kb.expr.filters.visible=function(a){return!kb.expr.filters.hidden(a)}),kb.each({margin:"",padding:"",border:"Width"},function(a,b){kb.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+xc[d]+b]=f[d]||f[d-2]||f[0];return e}},qc.test(a)||(kb.cssHooks[a+b].set=z)});var zc=/%20/g,Ac=/\[\]$/,Bc=/\r?\n/g,Cc=/^(?:submit|button|image|reset|file)$/i,Dc=/^(?:input|select|textarea|keygen)/i;kb.fn.extend({serialize:function(){return kb.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=kb.prop(this,"elements");return a?kb.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!kb(this).is(":disabled")&&Dc.test(this.nodeName)&&!Cc.test(a)&&(this.checked||!bc.test(a))}).map(function(a,b){var c=kb(this).val();return null==c?null:kb.isArray(c)?kb.map(c,function(a){return{name:b.name,value:a.replace(Bc,"\r\n")}}):{name:b.name,value:c.replace(Bc,"\r\n")}}).get()}}),kb.param=function(a,c){var d,e=[],f=function(a,b){b=kb.isFunction(b)?b():null==b?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(c===b&&(c=kb.ajaxSettings&&kb.ajaxSettings.traditional),kb.isArray(a)||a.jquery&&!kb.isPlainObject(a))kb.each(a,function(){f(this.name,this.value)});else for(d in a)E(d,a[d],c,f);return e.join("&").replace(zc,"+")},kb.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){kb.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),kb.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var Ec,Fc,Gc=kb.now(),Hc=/\?/,Ic=/#.*$/,Jc=/([?&])_=[^&]*/,Kc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Lc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mc=/^(?:GET|HEAD)$/,Nc=/^\/\//,Oc=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Pc=kb.fn.load,Qc={},Rc={},Sc="*/".concat("*");try{Fc=X.href}catch(Tc){Fc=Y.createElement("a"),Fc.href="",Fc=Fc.href}Ec=Oc.exec(Fc.toLowerCase())||[],kb.fn.load=function(a,c,d){if("string"!=typeof a&&Pc)return Pc.apply(this,arguments);var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),kb.isFunction(c)?(d=c,c=b):c&&"object"==typeof c&&(g="POST"),h.length>0&&kb.ajax({url:a,type:g,dataType:"html",data:c}).done(function(a){f=arguments,h.html(e?kb("<div>").append(kb.parseHTML(a)).find(e):a)}).complete(d&&function(a,b){h.each(d,f||[a.responseText,b,a])}),this},kb.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){kb.fn[b]=function(a){return this.on(b,a)}}),kb.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Fc,type:"GET",isLocal:Lc.test(Ec[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Sc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":kb.parseJSON,"text xml":kb.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?H(H(a,kb.ajaxSettings),b):H(kb.ajaxSettings,a)},ajaxPrefilter:F(Qc),ajaxTransport:F(Rc),ajax:function(a,c){function d(a,c,d,e){var f,l,s,t,v,x=c;2!==u&&(u=2,i&&clearTimeout(i),k=b,h=e||"",w.readyState=a>0?4:0,f=a>=200&&300>a||304===a,d&&(t=I(m,w,d)),t=J(m,t,w,f),f?(m.ifModified&&(v=w.getResponseHeader("Last-Modified"),v&&(kb.lastModified[g]=v),v=w.getResponseHeader("etag"),v&&(kb.etag[g]=v)),204===a||"HEAD"===m.type?x="nocontent":304===a?x="notmodified":(x=t.state,l=t.data,s=t.error,f=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),w.status=a,w.statusText=(c||x)+"",f?p.resolveWith(n,[l,x,w]):p.rejectWith(n,[w,x,s]),w.statusCode(r),r=b,j&&o.trigger(f?"ajaxSuccess":"ajaxError",[w,m,f?l:s]),q.fireWith(n,[w,x]),j&&(o.trigger("ajaxComplete",[w,m]),--kb.active||kb.event.trigger("ajaxStop")))}"object"==typeof a&&(c=a,a=b),c=c||{};var e,f,g,h,i,j,k,l,m=kb.ajaxSetup({},c),n=m.context||m,o=m.context&&(n.nodeType||n.jquery)?kb(n):kb.event,p=kb.Deferred(),q=kb.Callbacks("once memory"),r=m.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!l)for(l={};b=Kc.exec(h);)l[b[1].toLowerCase()]=b[2];b=l[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?h:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return k&&k.abort(b),d(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,m.url=((a||m.url||Fc)+"").replace(Ic,"").replace(Nc,Ec[1]+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=kb.trim(m.dataType||"*").toLowerCase().match(mb)||[""],null==m.crossDomain&&(e=Oc.exec(m.url.toLowerCase()),m.crossDomain=!(!e||e[1]===Ec[1]&&e[2]===Ec[2]&&(e[3]||("http:"===e[1]?"80":"443"))===(Ec[3]||("http:"===Ec[1]?"80":"443")))),m.data&&m.processData&&"string"!=typeof m.data&&(m.data=kb.param(m.data,m.traditional)),G(Qc,m,c,w),2===u)return w;j=m.global,j&&0===kb.active++&&kb.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!Mc.test(m.type),g=m.url,m.hasContent||(m.data&&(g=m.url+=(Hc.test(g)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=Jc.test(g)?g.replace(Jc,"$1_="+Gc++):g+(Hc.test(g)?"&":"?")+"_="+Gc++)),m.ifModified&&(kb.lastModified[g]&&w.setRequestHeader("If-Modified-Since",kb.lastModified[g]),kb.etag[g]&&w.setRequestHeader("If-None-Match",kb.etag[g])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",m.contentType),w.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+Sc+"; q=0.01":""):m.accepts["*"]);for(f in m.headers)w.setRequestHeader(f,m.headers[f]);if(m.beforeSend&&(m.beforeSend.call(n,w,m)===!1||2===u))return w.abort();v="abort";for(f in{success:1,error:1,complete:1})w[f](m[f]);if(k=G(Rc,m,c,w)){w.readyState=1,j&&o.trigger("ajaxSend",[w,m]),m.async&&m.timeout>0&&(i=setTimeout(function(){w.abort("timeout")},m.timeout));try{u=1,k.send(s,d)}catch(x){if(!(2>u))throw x;d(-1,x)}}else d(-1,"No Transport");return w},getJSON:function(a,b,c){return kb.get(a,b,c,"json")},getScript:function(a,c){return kb.get(a,b,c,"script")}}),kb.each(["get","post"],function(a,c){kb[c]=function(a,d,e,f){return kb.isFunction(d)&&(f=f||e,e=d,d=b),kb.ajax({url:a,type:c,dataType:f,data:d,success:e})}}),kb.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return kb.globalEval(a),a}}}),kb.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),kb.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=Y.head||kb("head")[0]||Y.documentElement;return{send:function(b,e){c=Y.createElement("script"),c.async=!0,a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,b){(b||!c.readyState||/loaded|complete/.test(c.readyState))&&(c.onload=c.onreadystatechange=null,c.parentNode&&c.parentNode.removeChild(c),c=null,b||e(200,"success"))},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(b,!0)}}}});var Uc=[],Vc=/(=)\?(?=&|$)|\?\?/;kb.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Uc.pop()||kb.expando+"_"+Gc++;return this[a]=!0,a}}),kb.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.jsonp!==!1&&(Vc.test(c.url)?"url":"string"==typeof c.data&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vc.test(c.data)&&"data");return i||"jsonp"===c.dataTypes[0]?(f=c.jsonpCallback=kb.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,i?c[i]=c[i].replace(Vc,"$1"+f):c.jsonp!==!1&&(c.url+=(Hc.test(c.url)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||kb.error(f+" was not called"),h[0]},c.dataTypes[0]="json",g=a[f],a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,Uc.push(f)),h&&kb.isFunction(g)&&g(h[0]),h=g=b}),"script"):void 0});var Wc,Xc,Yc=0,Zc=a.ActiveXObject&&function(){var a;for(a in Wc)Wc[a](b,!0)};kb.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&K()||L()}:K,Xc=kb.ajaxSettings.xhr(),kb.support.cors=!!Xc&&"withCredentials"in Xc,Xc=kb.support.ajax=!!Xc,Xc&&kb.ajaxTransport(function(c){if(!c.crossDomain||kb.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();if(c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async),c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),c.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l;try{if(d&&(e||4===i.readyState))if(d=b,g&&(i.onreadystatechange=kb.noop,Zc&&delete Wc[g]),e)4!==i.readyState&&i.abort();else{l={},h=i.status,j=i.getAllResponseHeaders(),"string"==typeof i.responseText&&(l.text=i.responseText);try{k=i.statusText}catch(m){k=""}h||!c.isLocal||c.crossDomain?1223===h&&(h=204):h=l.text?200:404}}catch(n){e||f(-1,n)}l&&f(h,k,l,j)},c.async?4===i.readyState?setTimeout(d):(g=++Yc,Zc&&(Wc||(Wc={},kb(a).unload(Zc)),Wc[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(b,!0)}}}});var $c,_c,ad=/^(?:toggle|show|hide)$/,bd=new RegExp("^(?:([+-])=|)("+lb+")([a-z%]*)$","i"),cd=/queueHooks$/,dd=[Q],ed={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bd.exec(b),f=e&&e[3]||(kb.cssNumber[a]?"":"px"),g=(kb.cssNumber[a]||"px"!==f&&+d)&&bd.exec(kb.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,kb.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};kb.Animation=kb.extend(O,{tweener:function(a,b){kb.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ed[c]=ed[c]||[],ed[c].unshift(b)},prefilter:function(a,b){b?dd.unshift(a):dd.push(a)}}),kb.Tween=R,R.prototype={constructor:R,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(kb.cssNumber[c]?"":"px")},cur:function(){var a=R.propHooks[this.prop];return a&&a.get?a.get(this):R.propHooks._default.get(this)},run:function(a){var b,c=R.propHooks[this.prop];return this.pos=b=this.options.duration?kb.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):R.propHooks._default.set(this),this}},R.prototype.init.prototype=R.prototype,R.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=kb.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){kb.fx.step[a.prop]?kb.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[kb.cssProps[a.prop]]||kb.cssHooks[a.prop])?kb.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},R.propHooks.scrollTop=R.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},kb.each(["toggle","show","hide"],function(a,b){var c=kb.fn[b];kb.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(S(b,!0),a,d,e)}}),kb.fn.extend({fadeTo:function(a,b,c,d){return this.filter(x).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=kb.isEmptyObject(a),f=kb.speed(b,c,d),g=function(){var b=O(this,kb.extend({},a),f);(e||kb._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return"string"!=typeof a&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=null!=a&&a+"queueHooks",f=kb.timers,g=kb._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cd.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem!==this||null!=a&&f[c].queue!==a||(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&kb.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=kb._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=kb.timers,g=d?d.length:0;for(c.finish=!0,kb.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),kb.each({slideDown:S("show"),slideUp:S("hide"),slideToggle:S("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){kb.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),kb.speed=function(a,b,c){var d=a&&"object"==typeof a?kb.extend({},a):{complete:c||!c&&b||kb.isFunction(a)&&a,duration:a,easing:c&&b||b&&!kb.isFunction(b)&&b};return d.duration=kb.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in kb.fx.speeds?kb.fx.speeds[d.duration]:kb.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){kb.isFunction(d.old)&&d.old.call(this),d.queue&&kb.dequeue(this,d.queue)},d},kb.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},kb.timers=[],kb.fx=R.prototype.init,kb.fx.tick=function(){var a,c=kb.timers,d=0;for($c=kb.now();d<c.length;d++)a=c[d],a()||c[d]!==a||c.splice(d--,1);c.length||kb.fx.stop(),$c=b},kb.fx.timer=function(a){a()&&kb.timers.push(a)&&kb.fx.start()},kb.fx.interval=13,kb.fx.start=function(){_c||(_c=setInterval(kb.fx.tick,kb.fx.interval))},kb.fx.stop=function(){clearInterval(_c),_c=null},kb.fx.speeds={slow:600,fast:200,_default:400},kb.fx.step={},kb.expr&&kb.expr.filters&&(kb.expr.filters.animated=function(a){return kb.grep(kb.timers,function(b){return a===b.elem}).length}),kb.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){kb.offset.setOffset(this,a,b)});var c,d,e={top:0,left:0},f=this[0],g=f&&f.ownerDocument;if(g)return c=g.documentElement,kb.contains(c,f)?(typeof f.getBoundingClientRect!==W&&(e=f.getBoundingClientRect()),d=T(g),{top:e.top+(d.pageYOffset||c.scrollTop)-(c.clientTop||0),left:e.left+(d.pageXOffset||c.scrollLeft)-(c.clientLeft||0)}):e},kb.offset={setOffset:function(a,b,c){var d=kb.css(a,"position");"static"===d&&(a.style.position="relative");var e,f,g=kb(a),h=g.offset(),i=kb.css(a,"top"),j=kb.css(a,"left"),k=("absolute"===d||"fixed"===d)&&kb.inArray("auto",[i,j])>-1,l={},m={};k?(m=g.position(),e=m.top,f=m.left):(e=parseFloat(i)||0,f=parseFloat(j)||0),kb.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(l.top=b.top-h.top+e),null!=b.left&&(l.left=b.left-h.left+f),"using"in b?b.using.call(a,l):g.css(l)}},kb.fn.extend({position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===kb.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),kb.nodeName(a[0],"html")||(c=a.offset()),c.top+=kb.css(a[0],"borderTopWidth",!0),c.left+=kb.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-kb.css(d,"marginTop",!0),left:b.left-c.left-kb.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||Z;a&&!kb.nodeName(a,"html")&&"static"===kb.css(a,"position");)a=a.offsetParent;return a||Z})}}),kb.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);kb.fn[a]=function(e){return kb.access(this,function(a,e,f){var g=T(a);return f===b?g?c in g?g[c]:g.document.documentElement[e]:a[e]:void(g?g.scrollTo(d?kb(g).scrollLeft():f,d?f:kb(g).scrollTop()):a[e]=f)},a,e,arguments.length,null)}}),kb.each({Height:"height",Width:"width"},function(a,c){kb.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){kb.fn[e]=function(e,f){var g=arguments.length&&(d||"boolean"!=typeof e),h=d||(e===!0||f===!0?"margin":"border");return kb.access(this,function(c,d,e){var f;return kb.isWindow(c)?c.document.documentElement["client"+a]:9===c.nodeType?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?kb.css(c,d,h):kb.style(c,d,e,h)},c,g?e:b,g,null)}})}),kb.fn.size=function(){return this.length},kb.fn.andSelf=kb.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=kb:(a.jQuery=a.$=kb,"function"==typeof define&&define.amd&&define("jquery",[],function(){return kb}))}(window),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";
-this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),function(a){function b(a){return"object"==typeof a?a:{top:a,left:a}}var c=a.scrollTo=function(b,c,d){a(window).scrollTo(b,c,d)};c.defaults={axis:"xy",duration:parseFloat(a.fn.jquery)>=1.3?0:1,limit:!0},c.window=function(){return a(window)._scrollable()},a.fn._scrollable=function(){return this.map(function(){var b=this,c=!b.nodeName||-1!=a.inArray(b.nodeName.toLowerCase(),["iframe","#document","html","body"]);if(!c)return b;var d=(b.contentWindow||b).document||b.ownerDocument||b;return/webkit/i.test(navigator.userAgent)||"BackCompat"==d.compatMode?d.body:d.documentElement})},a.fn.scrollTo=function(d,e,f){return"object"==typeof e&&(f=e,e=0),"function"==typeof f&&(f={onAfter:f}),"max"==d&&(d=9e9),f=a.extend({},c.defaults,f),e=e||f.duration,f.queue=f.queue&&f.axis.length>1,f.queue&&(e/=2),f.offset=b(f.offset),f.over=b(f.over),this._scrollable().each(function(){function g(a){j.animate(l,e,f.easing,a&&function(){a.call(this,k,f)})}if(null!=d){var h,i=this,j=a(i),k=d,l={},m=j.is("html,body");switch(typeof k){case"number":case"string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(k)){k=b(k);break}if(k=a(k,this),!k.length)return;case"object":(k.is||k.style)&&(h=(k=a(k)).offset())}a.each(f.axis.split(""),function(a,b){var d="x"==b?"Left":"Top",e=d.toLowerCase(),n="scroll"+d,o=i[n],p=c.max(i,b);if(h)l[n]=h[e]+(m?0:o-j.offset()[e]),f.margin&&(l[n]-=parseInt(k.css("margin"+d))||0,l[n]-=parseInt(k.css("border"+d+"Width"))||0),l[n]+=f.offset[e]||0,f.over[e]&&(l[n]+=k["x"==b?"width":"height"]()*f.over[e]);else{var q=k[e];l[n]=q.slice&&"%"==q.slice(-1)?parseFloat(q)/100*p:q}f.limit&&/^\d+$/.test(l[n])&&(l[n]=l[n]<=0?0:Math.min(l[n],p)),!a&&f.queue&&(o!=l[n]&&g(f.onAfterFirst),delete l[n])}),g(f.onAfter)}}).end()},c.max=function(b,c){var d="x"==c?"Width":"Height",e="scroll"+d;if(!a(b).is("html,body"))return b[e]-a(b)[d.toLowerCase()]();var f="client"+d,g=b.ownerDocument.documentElement,h=b.ownerDocument.body;return Math.max(g[e],h[e])-Math.min(g[f],h[f])}}(jQuery),function(a){function b(b,c,d){var e=c.hash.slice(1),f=document.getElementById(e)||document.getElementsByName(e)[0];if(f){b&&b.preventDefault();var g=a(d.target);if(!(d.lock&&g.is(":animated")||d.onBefore&&d.onBefore(b,f,g)===!1)){if(d.stop&&g._scrollable().stop(!0),d.hash){var h=d.offset;h=h&&h.top||h||0;var i=f.id==e?"id":"name",j=a("<a> </a>").attr(i,e).css({position:"absolute",top:a(window).scrollTop()+h,left:a(window).scrollLeft()});f[i]="",a("body").prepend(j),location=c.hash,j.remove(),f[i]=e}g.scrollTo(f,d).trigger("notify.serialScroll",[f])}}}var c=location.href.replace(/#.*/,""),d=a.localScroll=function(b){a("body").localScroll(b)};d.defaults={duration:1e3,axis:"y",event:"click",stop:!0,target:window,reset:!0},d.hash=function(c){if(location.hash){if(c=a.extend({},d.defaults,c),c.hash=!1,c.reset){var e=c.duration;delete c.duration,a(c.target).scrollTo(0,c),c.duration=e}b(0,location,c)}},a.fn.localScroll=function(e){function f(){return!(!this.href||!this.hash||this.href.replace(this.hash,"")!=c||e.filter&&!a(this).is(e.filter))}return e=a.extend({},d.defaults,e),e.lazy?this.bind(e.event,function(c){var d=a([c.target,c.target.parentNode]).filter(f)[0];d&&b(c,d,e)}):this.find("a,area").filter(f).bind(e.event,function(a){b(a,this,e)}).end().end()}}(jQuery),function(){if(navigator.appVersion.indexOf("MSIE 8")>0){var a=Array.prototype.slice;Array.prototype.slice=function(){if(this instanceof Array)return a.apply(this,arguments);for(var b=[],c=arguments.length>=1?arguments[0]:0,d=arguments.length>=2?arguments[1]:this.length,e=c;d>e;e++)b.push(this[e]);return b},"function"!=typeof Array.prototype.forEach&&(Array.prototype.forEach=function(a){for(var b=0;b<this.length;b++)a.apply(this,[this[b],b,this])})}}();var self="undefined"!=typeof window?window:{},Prism=function(){var a=/\blang(?:uage)?-(?!\*)(\w+)\b/i,b=self.Prism={util:{type:function(a){return Object.prototype.toString.call(a).match(/\[object (\w+)\]/)[1]},clone:function(a){var c=b.util.type(a);switch(c){case"Object":var d={};for(var e in a)a.hasOwnProperty(e)&&(d[e]=b.util.clone(a[e]));return d;case"Array":return a.slice()}return a}},languages:{extend:function(a,c){var d=b.util.clone(b.languages[a]);for(var e in c)d[e]=c[e];return d},insertBefore:function(a,c,d,e){e=e||b.languages;var f=e[a],g={};for(var h in f)if(f.hasOwnProperty(h)){if(h==c)for(var i in d)d.hasOwnProperty(i)&&(g[i]=d[i]);g[h]=f[h]}return e[a]=g},DFS:function(a,c){for(var d in a)c.call(a,d,a[d]),"Object"===b.util.type(a)&&b.languages.DFS(a[d],c)}},highlightAll:function(a,c){for(var d,e=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),f=0;d=e[f++];)b.highlightElement(d,a===!0,c)},highlightElement:function(d,e,f){for(var g,h,i=d;i&&!a.test(i.className);)i=i.parentNode;if(i&&(g=(i.className.match(a)||[,""])[1],h=b.languages[g]),h){d.className=d.className.replace(a,"").replace(/\s+/g," ")+" language-"+g,i=d.parentNode,/pre/i.test(i.nodeName)&&(i.className=i.className.replace(a,"").replace(/\s+/g," ")+" language-"+g);var j=d.textContent;if(j){j=j.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ");var k={element:d,language:g,grammar:h,code:j};if(b.hooks.run("before-highlight",k),e&&self.Worker){var l=new Worker(b.filename);l.onmessage=function(a){k.highlightedCode=c.stringify(JSON.parse(a.data),g),b.hooks.run("before-insert",k),k.element.innerHTML=k.highlightedCode,f&&f.call(k.element),b.hooks.run("after-highlight",k)},l.postMessage(JSON.stringify({language:k.language,code:k.code}))}else k.highlightedCode=b.highlight(k.code,k.grammar,k.language),b.hooks.run("before-insert",k),k.element.innerHTML=k.highlightedCode,f&&f.call(d),b.hooks.run("after-highlight",k)}}},highlight:function(a,d,e){return c.stringify(b.tokenize(a,d),e)},tokenize:function(a,c){var d=b.Token,e=[a],f=c.rest;if(f){for(var g in f)c[g]=f[g];delete c.rest}a:for(var g in c)if(c.hasOwnProperty(g)&&c[g]){var h=c[g],i=h.inside,j=!!h.lookbehind,k=0;h=h.pattern||h;for(var l=0;l<e.length;l++){var m=e[l];if(e.length>a.length)break a;if(!(m instanceof d)){h.lastIndex=0;var n=h.exec(m);if(n){j&&(k=n[1].length);var o=n.index-1+k,n=n[0].slice(k),p=n.length,q=o+p,r=m.slice(0,o+1),s=m.slice(q+1),t=[l,1];r&&t.push(r);var u=new d(g,i?b.tokenize(n,i):n);t.push(u),s&&t.push(s),Array.prototype.splice.apply(e,t)}}}}return e},hooks:{all:{},add:function(a,c){var d=b.hooks.all;d[a]=d[a]||[],d[a].push(c)},run:function(a,c){var d=b.hooks.all[a];if(d&&d.length)for(var e,f=0;e=d[f++];)e(c)}}},c=b.Token=function(a,b){this.type=a,this.content=b};if(c.stringify=function(a,d,e){if("string"==typeof a)return a;if("[object Array]"==Object.prototype.toString.call(a))return a.map(function(b){return c.stringify(b,d,a)}).join("");var f={type:a.type,content:c.stringify(a.content,d,e),tag:"span",classes:["token",a.type],attributes:{},language:d,parent:e};"comment"==f.type&&(f.attributes.spellcheck="true"),b.hooks.run("wrap",f);var g="";for(var h in f.attributes)g+=h+'="'+(f.attributes[h]||"")+'"';return"<"+f.tag+' class="'+f.classes.join(" ")+'" '+g+">"+f.content+"</"+f.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(a){var c=JSON.parse(a.data),d=c.language,e=c.code;self.postMessage(JSON.stringify(b.tokenize(e,b.languages[d]))),self.close()},!1),self.Prism):self.Prism;var d=document.getElementsByTagName("script");return d=d[d.length-1],d&&(b.filename=d.src,document.addEventListener&&!d.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",b.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),Prism.languages.markup={comment:/&lt;!--[\w\W]*?-->/g,prolog:/&lt;\?.+?\?>/,doctype:/&lt;!DOCTYPE.+?>/,cdata:/&lt;!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^&lt;\/?[\w:-]+/i,inside:{punctuation:/^&lt;\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi},Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&amp;/,"&"))}),Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/gi,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g},Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/gi,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}}),Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g},Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/gi,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}}),function(){if(self.Prism&&self.document&&document.querySelector){var a={js:"javascript",html:"markup",svg:"markup"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(b){var c=b.getAttribute("data-src"),d=(c.match(/\.(\w+)$/)||[,""])[1],e=a[d]||d,f=document.createElement("code");f.className="language-"+e,b.textContent="",f.textContent="Loading…",b.appendChild(f);var g=new XMLHttpRequest;g.open("GET",c,!0),g.onreadystatechange=function(){4==g.readyState&&(g.status<400&&g.responseText?(f.textContent=g.responseText,Prism.highlightElement(f)):f.textContent=g.status>=400?"✖ Error "+g.status+" while fetching file: "+g.statusText:"✖ Error: File does not exist or is empty")},g.send(null)})}}(),Prism.hooks.add("after-highlight",function(a){var b=a.element.parentNode;if(b&&/pre/i.test(b.nodeName)&&-1!==b.className.indexOf("line-numbers")){var c,d=1+a.code.split("\n").length;lines=new Array(d),lines=lines.join("<span></span>"),c=document.createElement("span"),c.className="line-numbers-rows",c.innerHTML=lines,b.hasAttribute("data-start")&&(b.style.counterReset="linenumber "+(parseInt(b.getAttribute("data-start"),10)-1)),a.element.appendChild(c)}}),function(a){function b(){function b(c,d,e){var f,g=a("<li>"),h=a("<a>");if(h.attr({href:"#"+c}),h.text(d.attr("title")?d.attr("title"):d.text()),e&&e.length){f=a("<ul>",{"class":"nav"});for(var i=0;i<e.length;i++){var j=a(e[i]);f.append(b(j.attr("id"),j))}}return g.append(h),h.after(f),f&&f.find("ul").each(function(){a(this).height(a(this).outerHeight()).hide()}),g}var c=a("#sidebar-nav");a("section").each(function(){var d=a(this);c.append(b(d.attr("id"),d.find("h2:first"),d.find(".section-row h3[id], .section-row h4[id]")))}),a("#sidebar-nav > li").on("activate",function(){a(this).find(".nav").show()}).on("deactivate",function(){a(this).find(".nav").hide()})}function c(){a.localScroll({offset:-110,duration:200,filter:":not([data-tabs] a)"})}a(function(){b(),c(),a("body").scrollspy({target:".sidebar",offset:100}).css("opacity",1)})}(jQuery,window,document,void 0); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ui-charts-tpls.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ui-charts-tpls.js
deleted file mode 100644
index 41d1bf6c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/angular_js/ui-charts-tpls.js
+++ /dev/null
@@ -1,3909 +0,0 @@
-/*Sandbox version 0.0.41a*/
-angular.module("att.charts", ["att.charts.tpls", "att.charts.utilities","att.charts.areachartD3","att.charts.barchartD3","att.charts.coschartD3","att.charts.coschartwithbarD3","att.charts.cosdeletionD3","att.charts.cosmultichartD3","att.charts.donutD3","att.charts.donutFusion","att.charts.horseshoeD3","att.charts.radialguageD3","att.charts.stackedBarchart","att.charts.stackedareachart"]);
-angular.module("att.charts.tpls", ["template/areachartD3/attAreaChartD3.html","template/barchartD3/attBarChartD3.html","template/coschartD3/attCosd3Chart.html","template/coschartwithbarD3/attCosBarD3Chart.html","template/cosmultichartD3/attCosmultid3Chart.html","template/donutD3/attDonutd3Chart.html","template/donutFusion/attDonutfusionChart.html","template/horseshoeD3/attHorseshoeD3Chart.html","template/stackedBarchart/stackedBarchart.html","template/stackedareachart/stackedAreaChart.html"]);
-angular.module('att.charts.utilities', [])
- .factory('$extendObj', [function () {
- var _extendDeep = function (dst) {
- angular.forEach(arguments, function (obj) {
- if (obj !== dst) {
- angular.forEach(obj, function (value, key) {
- if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
- _extendDeep(dst[key], value);
- } else {
- dst[key] = value;
- }
- });
- }
- });
- return dst;
- };
- return {
- extendDeep: _extendDeep
-
- };
- }]);
-
-angular.module('att.charts.areachartD3', ['att.charts.utilities'])
- .constant("areaChartConfig",
- {
- "chartcolor": {
- "areaChartColor": ["#bff1ec", "#bbf0eb", "#00c7b2"],
- "lineChartColor": ["#444444", "#444444"],
- "overageColor": ["#b8509e"]
- },
- "gridLineColor": "#808080",
- "lineCurveType": 'cardinal',
- "yAxisMaxTicks": 4,
- "chartHeight": "200",
- "dataType": "GB",
- "lineStroke": 3,
- "opacityOnHover": "0.5",
- "circleRadius": 3.5,
- "yearLabelPos": [5, -5],
- "tooltipTopMargin": 105,
- "tooltipLeftMargin": 28,
- "amountKDivision": 1000,
- "amountKText": "K",
- "amountMDivision": 1000000,
- "amountMText": "M"
- })
- .directive('attAreaChart', ['areaChartConfig', '$extendObj', '$timeout', function (areaChartConfig, $extendObj, $timeout) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- chartColor: "=",
- legendLabel: "=",
- refreshChart: "=",
- chartConfig: "="
- },
- templateUrl: "template/areachartD3/attAreaChartD3.html",
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- areaChartConfig = $extendObj.extendDeep(areaChartConfig, $scope.chartConfig);
- }
- $scope.dataType = areaChartConfig.dataType;
- $scope.chartID = $attrs.id;
- }],
- link: function (scope, element, attrs, ctrl) {
- scope.tooltipFlag = false;
- scope.overageFlag = false;
- scope.underageFlag = false;
- var startColor, stopColor, lineColor, xAxisticks, dataObj, margin = {top: 30, right: 15, bottom: 30, left: 40},
- width = parseInt(attrs.chartWidth, 10),
- height = areaChartConfig.chartHeight,
- parseDate = d3.time.format("%d-%b-%Y").parse,
- tooltipFormat = d3.time.format("%B-%Y"),
- labelFormat = d3.time.format("%Y");
- var legendColors = [];
- legendColors = (scope.chartColor) ? scope.chartColor : areaChartConfig.chartcolor;
- startColor = legendColors.areaChartColor[0];
- stopColor = legendColors.areaChartColor[1];
- lineColor = legendColors.lineChartColor[0];
- scope.areaLegendColor = legendColors.areaChartColor[2];
- scope.lineLegendColor = legendColors.lineChartColor[1];
- scope.overageLegend = legendColors.overageColor[0];
- var oldIE = navigator.userAgent.toLowerCase().indexOf('msie 8.0') !== -1;
- scope.addLegendColor = function (id) {
- var bgColor = null;
- switch (id) {
- case 0:
- bgColor = {"background-color": scope.areaLegendColor, "border-radius": "100%"};
- break;
- case 1:
- bgColor = {"background-color": scope.lineLegendColor};
- break;
- case 2:
- bgColor = {"background-color": scope.overageLegend, "border-radius": "100%"};
- break;
- }
- return bgColor;
- };
-
- attrs.$observe('legendRequired', function (val) {
- if (val === 'true') {
- scope.showLegend = true;
- }
- else {
- scope.showLegend = false;
- }
- });
-
- scope.$watch('refreshChart', function (value) {
- if (value === false) {
- return;
- }
- if (angular.isDefined(scope.chartConfig)) {
- areaChartConfig = $extendObj.extendDeep(areaChartConfig, scope.chartConfig);
- }
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- d3.selectAll("div#areaChartContainer" + " > div").remove();
- xAxisticks = scope.chartData.length;
- dataObj = scope.chartData;
- var yearLabel = '', monthArr = {}, isSingleMonth, singleMonthName;
-
- // On selecting same month in From and To dropdowns, User should be getting graph
- if (dataObj.length === 1) {
- isSingleMonth = true;
- var tmp1 = "01-" + dataObj[0].month;
- var tmp = parseDate(tmp1);
- singleMonthName = tmp.toString().split(" ")[1];
- tmp.setMonth(tmp.getMonth() + 1);
- var nextMonth = tmp.toString().split(" ")[1] + "-" + tmp.getFullYear();
- dataObj.push({month: nextMonth, usage: dataObj[0].usage, available: dataObj[0].available, usageDataType: dataObj[0].usageDataType, availableDataType: dataObj[0].availableDataType});
- }
-
- dataObj.forEach(function (d) {
- var tmp = "01-" + d.month;
- d.numericMonth = parseDate(tmp);
- d.usage = +d.usage;
- d.available = +d.available;
- monthArr[labelFormat(d.numericMonth)] = labelFormat(d.numericMonth);
- });
-
- for (var key in monthArr) {
- var label = monthArr[key];
- if (!yearLabel) {
- yearLabel = label;
- }
- else {
- if (!isSingleMonth) {
- yearLabel = yearLabel + "-" + label;
- }
- }
- }
-
- //X-Axis Range
- var xRange = d3.time.scale()
- .range([0, width]);
-
- //Y-Axis Range
- var yRange = d3.scale.linear()
- .range([height, 0]);
-
- //X-Axis Domain
- xRange.domain(d3.extent(dataObj, function (d) {
- return d.numericMonth;
- }));
-
- //Y-Axis Domain
- var yDomainData = [], yAxisData = [];
- for (var b = 0; b < dataObj.length; b++) {
- var usageVal = Math.round(parseInt(dataObj[b].usage, 10) / areaChartConfig.yAxisMaxTicks);
- var availableVal = Math.round(parseInt(dataObj[b].available, 10) / areaChartConfig.yAxisMaxTicks);
- var val;
- if (usageVal > availableVal) {
- val = usageVal;
- }
- else {
- val = availableVal;
- }
- var Calc = Math.ceil((val / Math.pow(10, ("" + val).length - 1))) * (areaChartConfig.yAxisMaxTicks) * Math.pow(10, ("" + val).length - 1);
- yDomainData.push({'yAxisVal': Calc});
- }
-
- //Y-Axis Domain
- yRange.domain([0, d3.max(yDomainData, function (d) {
- return (d.yAxisVal);
- })]);
-
- var yTick = d3.max(yDomainData, function (d) {
- return d.yAxisVal;
- });
-
- yTick = yTick / areaChartConfig.yAxisMaxTicks;
- for (var x = 0; x <= areaChartConfig.yAxisMaxTicks; x++) {
- yAxisData.push(yTick * x);
- }
- var formatData = function (d) {
- if (d >= areaChartConfig.amountMDivision) {
- return d / areaChartConfig.amountMDivision + areaChartConfig.amountMText;
- } else if (d >= areaChartConfig.amountKDivision) {
- return d / areaChartConfig.amountKDivision + areaChartConfig.amountKText;
- } else {
- return d;
- }
- };
- var xAxis = d3.svg.axis().scale(xRange).orient("bottom").tickFormat(d3.time.format('%b')).ticks(d3.time.months);
- var yAxis = d3.svg.axis().scale(yRange).orient("left").tickValues(yAxisData).ticks(areaChartConfig.yAxisMaxTicks).tickFormat(formatData);
-
- //Draw Line
- var line = d3.svg.line()
- .x(function (d) {
- return xRange(d.numericMonth);
- })
- .y(function (d) {
- return yRange(d.available);
- }).interpolate(areaChartConfig.lineCurveType);
-
- //Draw Area
- var area = d3.svg.area()
- .x(function (d) {
- return xRange(d.numericMonth);
- })
- .y0(height)
- .y1(function (d) {
- return yRange(d.usage);
- }).interpolate(areaChartConfig.lineCurveType);
-
- //Plot Chart
- var drawChart = d3.select("#areaChartContainer")
- .append("svg")
- .attr("id", attrs.id)
- .data(dataObj)
- .attr("width", width + margin.left + margin.right)
- .attr("height", parseInt(height, 10) + parseInt(margin.top, 10) + parseInt(margin.bottom, 10))
- .append("g")
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- //Apply gradients
- if (!oldIE) {
- var svgDefs = drawChart.append("defs")
- .append("linearGradient")
- .attr("id", "areaGradient")
- .attr('x1', '0%').attr('y1', '0%')
- .attr('x2', '0%').attr('y2', '100%');
-
- //Fill gradient
- svgDefs.append('stop')
- .attr('stop-color', startColor)
- .attr("offset", "0%")
- .attr("stop-opacity", "1");
- svgDefs.append('stop')
- .attr('stop-color', stopColor)
- .attr("offset", "100%")
- .attr("stop-opacity", "1");
- }
-
- //Draw X Axis
- drawChart.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + height + ")")
- .call(xAxis).selectAll("text")
- .attr("dy", "1.2em");
-
-
- if (isSingleMonth) {
- drawChart.selectAll('.x.axis').selectAll('.tick').selectAll('text')[1][0].textContent = singleMonthName;
- }
-
- //Plot Area
- var areaPath = drawChart.append("path")
- .datum(dataObj)
- .attr("class", "area")
- .attr("d", area).style("fill", "url(#areaGradient)").append("title").text(function () {
- return scope.legendLabel[0].series;
- });
-
- var newDataObj = dataObj;
- if (isSingleMonth) {
- newDataObj = dataObj.slice(0, 1);
- }
-
- //Draw Data Points for Area Chart
- var circle = drawChart.selectAll(".dot")
- .data(newDataObj)
- .enter().append("circle")
- .attr("class", "dot")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .style("fill", function (d) {
- if (d.usage > d.available) {
- return scope.overageLegend;
- }
- else {
- return scope.areaLegendColor;
- }
- })
- .attr("r", areaChartConfig.circleRadius)
- .attr("cx", function (d) {
- return xRange(d.numericMonth);
- })
- .attr("cy", function (d) {
- return yRange(d.usage);
- }).on("mouseover", function (d) {
- var offsetX = Math.ceil(d3.select(this).attr("cx"));
- show_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- var offsetY = Math.round(d3.select(this).attr("cy"));
- d3.select('svg#' + attrs.id).style("fill-opacity", areaChartConfig.opacityOnHover);
- mouseOver(d, offsetX - 3, offsetY - 3);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- d3.select('svg#' + attrs.id).style("fill-opacity", "1");
- scope.tooltipFlag = false;
- scope.$apply();
- });
- circle.append('desc').append('title').text(function (d) {
- return(addTitle(d));
- });
-
- //Draw Line Chart
- drawChart.append("path")
- .attr("class", "line")
- .style("stroke", lineColor)
- //.style("stroke-dasharray", (areaChartConfig.lineStroke, areaChartConfig.lineStroke))
- .attr("d", line(dataObj)).append("title").text(function () {
- return scope.legendLabel[1].series;
- });
-
- //Draw data points for Line Chart
- if (!oldIE) {
- var squaredot = drawChart.selectAll(".square-dot")
- .data(newDataObj).enter().append("rect")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .style("fill", scope.lineLegendColor)
- .attr("class", "square-dot")
- .attr("x", function (d) {
- var tmp = xRange(d.numericMonth);
- tmp = tmp - 2.5;
- return tmp;
- })
- .attr("y", function (d) {
- var tmp = yRange(d.available);
- tmp = tmp - 2.5;
- return tmp;
- })
- .attr("width", "5px")
- .attr("height", "5px")
- .on("mouseover", function (d) {
- var offsetX = Math.ceil(d3.select(this).attr("x"));
- show_tooltip_grid_line(d3.select(this).attr("x"), "rect", "x");
- var offsetY = Math.round(d3.select(this).attr("y"));
- d3.select('svg#' + attrs.id).style("fill-opacity", areaChartConfig.opacityOnHover);
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("x"), "rect", "x");
- d3.select('svg#' + attrs.id).style("fill-opacity", "1");
- scope.tooltipFlag = false;
- scope.$apply();
- });
- squaredot.append('desc').append('title').text(function (d) {
- return(addTitle(d));
- });
- }
- else {
- areaPath.style("fill", startColor);
- var squareDot = drawChart.selectAll(".square-dot")
- .data(newDataObj).enter().append("circle")
- .attr("class", "square-dot")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .style("fill", scope.areaLegendColor)
- .attr("r", areaChartConfig.circleRadius)
- .attr("cx", function (d) {
- return xRange(d.numericMonth);
- })
- .attr("cy", function (d) {
- return yRange(d.available);
- }).on("mouseover", function (d) {
- var offsetX = Math.ceil(d3.select(this).attr("cx"));
- var offsetY = Math.round(d3.select(this).attr("cy"));
- show_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- d3.select('svg#' + attrs.id).style("fill-opacity", areaChartConfig.opacityOnHover);
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- d3.select('svg#' + attrs.id).style("fill-opacity", "1");
- scope.tooltipFlag = false;
- scope.$apply();
- });
- squareDot.append('desc').append('title').text(function (d) {
- return(addTitle(d));
- });
- }
-
- //Draw Y Axis
- var yAxisNodes = drawChart.append("g")
- .attr("class", "y axis").attr("id", "yAxisId")
- .call(yAxis);
-
- yAxisNodes.selectAll("text")
- .attr("id", function (d, i) {
- return ("yAxisText" + i);
- });
-
- //Append Year Label
- yAxisNodes.append("text")
- .attr("transform", "rotate(0)")
- .attr("y", areaChartConfig.yearLabelPos[1])
- .attr("x", areaChartConfig.yearLabelPos[0]).attr("class", "yearLabel")
- .text(yearLabel);
- //Remove minimum value label form Y Axis
- drawChart.select("#yAxisText0").remove();
-
- // Draw the x Grid lines
- drawChart.append("g")
- .attr("class", "grid")
- .attr("id", "xGrid")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .call(make_x_axis()
- .tickSize(-height, 0)
- .tickFormat(""));
-
- // function for the x grid lines
- function make_x_axis() {
- return d3.svg.axis()
- .scale(xRange)
- .orient("top")
- .tickFormat(d3.time.format('%b')).ticks(d3.time.months);
- }
-
- //drawChart.select("#xGrid").selectAll("line").style("stroke", areaChartConfig.gridLineColor);
- drawChart.select("#xGrid").selectAll("line").style("stroke", "none");
- drawChart.select("#xGrid").selectAll("line")
- .attr("id", function (d, i) {
- return ("xAxisLine" + i);
- });
-
- //Add title for NVDA screen reader
- function addTitle(d) {
- return (tooltipFormat(d.numericMonth) + "Used" + d.usage + d.usageDataType + "Available" + d.available + d.availableDataType);
- }
-
- //Show Gridline on Mouse Hover
- function show_tooltip_grid_line(offsetX, shape, attr) {
- try {
- for (var i = 0; i < xAxisticks; i++) {
- var circle = drawChart.selectAll(shape);
- if (circle[0][i].getAttribute(attr) === offsetX) {
- drawChart.select("#xAxisLine" + i).style("stroke", areaChartConfig.gridLineColor);
- }
- }
- } catch (e) {
- }
- }
-
- //Hide Gridline on Mouse Hover
- function hide_tooltip_grid_line(offsetX, shape, attr) {
- try {
- for (var i = 0; i < xAxisticks; i++) {
- var circle = drawChart.selectAll(shape);
- if (circle[0][i].getAttribute(attr) === offsetX) {
- drawChart.select("#xAxisLine" + i).style("stroke", "transparent");
- }
- }
- } catch (e) {
- }
- }
-
- //Mouse Hover
- function mouseOver(d, offsetX, offsetY) {
- scope.underageFlag = false;
- scope.overageFlag = false;
- if (d.usage > d.available) {
- scope.overageFlag = true;
- }
- if (d.usage < d.available) {
- scope.underageFlag = true;
- }
- scope.dataPoint = {"xData": tooltipFormat(d.numericMonth).replace('-', ' '), "dataUsed": d.usage, "dataAvailable": d.available, "overage": d.overage, "usageDataType": d.usageDataType, "availableDataType": d.availableDataType, "underage": d.underage};
- scope.$apply();
- $timeout(function () {
- offsetY = offsetY - areaChartConfig.tooltipTopMargin;
- var tooltipEl = element.children().eq(2);
- var tooltipWidth = tooltipEl[0].offsetWidth;
- if (isSingleMonth) {
- offsetX = offsetX - (tooltipWidth / 2) + areaChartConfig.tooltipLeftMargin + (width / 2);
- } else {
- offsetX = offsetX - (tooltipWidth / 2) + areaChartConfig.tooltipLeftMargin;
- }
- scope.tooltipStyle = {"left": offsetX + "px", "top": offsetY + "px"};
- scope.tooltipFlag = true;
- },0);
- }
- scope.refreshChart = false;
- });
- }
- };
- }])
- .filter('filterInput', function () {
- return function (input) {
- return input.replace(/ +/g, "").toLowerCase();
- };
- });
-angular.module('att.charts.barchartD3', ['att.charts.utilities'])
-
- .constant("BarChartD3Config",
- {
- "barChartColor": "#0081C2",
- "gridLineColor": "#808080",
- "yaxisGridLineColor": "#000000",
- "margin": {
- top : 40,
- right: 20,
- bottom: 30,
- left: 40
- },
- "attributes": {
- "userName": "name",
- "phoneNumber": "phoneNumber",
- "charges": "charges"
- },
- "yAxisMaxTicks": 4,
- "chartHeight": 160,
- "amountFormat" : "$0,000",
- "amountKDivision" : 1000,
- "amountKText" : "K",
- "amountMDivision" : 1000000,
- "amountMText" : "M",
- "xAxistickSize":0,
- "tooltipTopMargin":69,
- "tooltipLeftMargin":59,
- "xAxisTextTopMargin":15,
- "xAxisTextLeftMargin":7,
- "barChartSize":25,
- "barHoverOpacity":0.2
- })
-
- .directive('attBarChart', ['BarChartD3Config','$extendObj', function(BarChartD3Config,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- chartConfig: '=',
- refreshChart: "="
- },
- templateUrl: "template/barchartD3/attBarChartD3.html",
- replace: true,
- link: function(scope, element, attrs, ctrl) {
-
- scope.$watch('refreshChart', function() {
- if (angular.isDefined(scope.chartConfig)) {
- BarChartD3Config = $extendObj.extendDeep(BarChartD3Config, scope.chartConfig);
- }
-
- var width = parseInt(attrs.chartWidth, 10),
- chartColor = BarChartD3Config.barChartColor,
- height = BarChartD3Config.chartHeight,
- userName = BarChartD3Config.attributes.userName,
- charges = BarChartD3Config.attributes.charges,
- phoneNumber = BarChartD3Config.attributes.phoneNumber,
- formatCharges = d3.format(BarChartD3Config.amountFormat),
- isSingleDataObj = false, padding = 20;
- var barChartData, yDomainData = [],yAxisData = [];
- scope.tooltipFlag = false;
- var compare = function compare(a, b) {
- if (parseInt(a[charges], 10) > parseInt(b[charges], 10)) {
- return -1;
- }
- if (parseInt(a[charges], 10) < parseInt(b[charges], 10)) {
- return 1;
- }
- return 0;
- };
-
-
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- d3.selectAll("div#barChartContainer" + " > div").remove();
-
- barChartData = scope.chartData.sort(compare);
- barChartData = barChartData.slice(0,BarChartD3Config.barChartSize);
- if (barChartData.length === 1) {
- isSingleDataObj = true;
- }
- var x = d3.scale.ordinal().rangeBands([0, width]);
-
- var y = d3.scale.linear()
- .range([height, 0]);
-
- x.domain(barChartData.map(function(d, i) {
- return i + 1;
- }));
-
- for(var b=0; b < barChartData.length; b++){
- var val = Math.round(parseInt(barChartData[b].charges, 10)/BarChartD3Config.yAxisMaxTicks);
- var Calc = Math.ceil((val / Math.pow(10, ("" + val).length - 1))) * (BarChartD3Config.yAxisMaxTicks) * Math.pow(10, ("" + val).length - 1);
- yDomainData.push({'yAxisVal':Calc});
- }
-
- //Y-Axis Domain
- y.domain([0, d3.max(yDomainData, function(d) {
- return (d.yAxisVal);
- })]);
-
- var yTick = d3.max(yDomainData, function(d) {return d.yAxisVal;});
-
- yTick = yTick/BarChartD3Config.yAxisMaxTicks;
- for(var z = 0; z <= BarChartD3Config.yAxisMaxTicks; z++){
- yAxisData.push(yTick * z);
- }
- var formatMoney = function(d) {
- if (d >= BarChartD3Config.amountMDivision) {
- return "$" + d / BarChartD3Config.amountMDivision + BarChartD3Config.amountMText;
- } else if (d >= BarChartD3Config.amountKDivision) {
- return "$" + d / BarChartD3Config.amountKDivision + BarChartD3Config.amountKText;
- } else {
- return "$" + d;
- }
- };
-
- var xAxis = d3.svg.axis()
- .scale(x)
- .orient("bottom")
- .tickSize(BarChartD3Config.xAxistickSize);
-
- var yAxis = d3.svg.axis().scale(y).orient("left").tickValues(yAxisData).ticks(BarChartD3Config.yAxisMaxTicks).tickFormat(formatMoney);
-
- var svg = d3.select("#barChartContainer")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", width + BarChartD3Config.margin.left + BarChartD3Config.margin.right)
- .attr("height", height + BarChartD3Config.margin.top + BarChartD3Config.margin.bottom)
- .append("g")
- .attr("transform", "translate(" + BarChartD3Config.margin.left + "," + BarChartD3Config.margin.top + ")");
-
- svg.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(" + -Math.ceil((x(2) - x(1)) / 2 - BarChartD3Config.xAxisTextTopMargin) + "," + (height + BarChartD3Config.xAxisTextLeftMargin) + ")")
- .call(xAxis);
-
- var formatPhNumber = function(phoneNum) {
- if (phoneNum.indexOf("-") === -1) {
- return phoneNum.substr(0, 3) + '-' + phoneNum.substr(3, 3) + '-' + phoneNum.substr(6);
- } else {
- return phoneNum;
- }
- };
-
- var rectBarGroup = svg.append("g")
- .attr("class", "group").attr("id", function (d, i) {
- return ("barGroup" + i);
- }).attr("transform", "translate(" + (isSingleDataObj === true? ((width / 2) + 11):10) + ",0)");
-
- var rectBars = rectBarGroup.selectAll(".bar")
- .data(barChartData)
- .enter().append("rect")
- .attr("style", "fill:" + chartColor)
- .attr("class", "bar")
- .attr("x", function(d, i) {
- return Math.round(x(i + 1));
- })
- .attr("width", 10)
- .attr("y", function(d) {
- return y(d[charges]);
- })
- .attr("height", function(d) {
- return (height - y(d[charges]));
- })
- .on("mouseover", function(d) {
- var offsetX = Math.round(d3.select(this).attr("x"));
- show_tooltip_grid_line(offsetX);
- var offsetY = Math.round(d3.select(this).attr("y"));
- svg.select(".grid").selectAll("line").style("stroke", "transparent");
- svg.selectAll(".bar").style("fill-opacity",BarChartD3Config.barHoverOpacity);
- d3.select(this).style("fill-opacity","1");
- mouseOver(d, offsetX, offsetY);
- })
- .on("mouseout", function() {
- var offsetX = Math.round(d3.select(this).attr("x"));
- hide_tooltip_grid_line(offsetX);
- scope.tooltipFlag = false;
- svg.select(".grid").selectAll("line").style("stroke", BarChartD3Config.gridLineColor);
- svg.selectAll(".bar").style("fill-opacity","1");
- scope.$apply();
- });
- rectBars.append('desc').append('title').text(function(d){ return (d[userName] + "-- Wireless Number" + formatPhNumber(d[phoneNumber]) + "Charges-" + d[charges]);});
-
- var yAxisNodes = svg.append("g")
- .attr("class", "y axis")
- .call(yAxis);
-
- yAxisNodes.selectAll("text")
- .attr("id", function(d, i) {
- return ("yAxisText" + i);
- });
-
- yAxisNodes.selectAll("line")
- .attr("id", function(d, i) {
- return ("yAxisLine" + i);
- });
-
- //Remove minimum value label form Y Axis
- d3.select("#yAxisText0").remove();
- d3.select("#yAxisLine0").remove();
- yAxisNodes.select("path").remove();
-
- // Draw the y Grid lines
- svg.append("g")
- .attr("class", "grid")
- .attr("transform", "translate(0,0)")
- .call(make_y_axis()
- .tickSize(-width + x(2) - x(1), 0, 0)
- .tickFormat(""));
- svg.select(".grid").selectAll("line").style("stroke", BarChartD3Config.gridLineColor);
- // function for the y grid lines
- function make_y_axis() {
- return d3.svg.axis()
- .scale(y)
- .orient("left")
- .ticks(BarChartD3Config.yAxisMaxTicks).tickValues(yAxisData);
- }
- // Draw the x Grid lines
- svg.append("g")
- .attr("class", "grid").attr("id", "xGrid")
- .call(make_x_axis()
- .tickSize(-height , 0)
- .tickFormat("")).selectAll("line").attr("transform", "translate(" + -Math.ceil((x(2) - x(1)) / 2 - BarChartD3Config.xAxisTextTopMargin) + ",0)")
- .attr("id", function (d, i) {
- return ("xAxisLine" + i);
- });
-
-
- // function for the x grid lines
- function make_x_axis() {
- return d3.svg.axis()
- .scale(x)
- .orient("top")
- .ticks(BarChartD3Config.yAxisMaxTicks)
- ;
- }
- svg.select("#xGrid").selectAll("line")
- .attr("id", function(d, i) {
- return ("xAxisLine" + i);
- });
-
- function show_tooltip_grid_line(offsetX){
- for (var i = 0; i < barChartData.length; i++) {
- if(Math.round(x(i+1))===offsetX){
- svg.select("#xAxisLine"+i).style("stroke", BarChartD3Config.yaxisGridLineColor);
- }
- }
- }
-
- function hide_tooltip_grid_line(offsetX){
- for (var i = 0; i < barChartData.length; i++) {
- if(Math.round(x(i+1))===offsetX){
- svg.select("#xAxisLine"+i).style("stroke", "transparent");
- }
- }
- }
- function mouseOver(d, offsetX, offsetY) {
- offsetY = offsetY - BarChartD3Config.tooltipTopMargin;
- if (isSingleDataObj) {
- offsetX = offsetX - BarChartD3Config.tooltipLeftMargin + (width / 2);
- } else {
- offsetX = offsetX - BarChartD3Config.tooltipLeftMargin;
- }
- scope.tooltipFlag = true;
- scope.tooltipStyle = {"left": offsetX + "px", "top": offsetY + "px"};
- scope.dataPoint = {"name": d[userName], "phoneNumber": formatPhNumber(d[phoneNumber]), "charges": formatCharges(d[charges])};
- scope.$apply();
- }
- scope.refreshChart = false;
- });
- }
- };
- }]);
-angular.module('att.charts.coschartD3', ['att.charts.utilities'])
- .constant("CosChartD3Config",
- {
- "chartcolor": {
- "paletteColors": ["#097cb5", "#FEFFF7"] //default color options for rendering chart baseColor and NeedleColor,
-
- },
- "defaultcenterlabel": "COS 1",
- "defaultcentercategory": "Real Time",
- "zoomLevel": "25",
- "doughnutratio": 20,
- "legendreqd": "false",
- "animduration": "300",
- "legendposition": "top",
- "centerTextValueDy": "0",
- "centerTextValueDx": "0",
- "centerTextPercentDx": "20",
- "centerTextPercentDy": "-10",
- "centerTextLabelDy": "20",
- "centerTextLabelDx": "0",
- "arcOverMargin": 5
- })
- .directive('attCosd3Chart', ['CosChartD3Config', '$timeout','$extendObj', function (CosChartD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- chartConfig: '=',
- initVal: '='
- },
- templateUrl: 'template/coschartD3/attCosd3Chart.html',
- transclude: true,
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- CosChartD3Config = $extendObj.extendDeep(CosChartD3Config, $scope.chartConfig);
- }
- var legendColor = [];
- legendColor = CosChartD3Config.chartcolor.paletteColors;
- $scope.addLegendColor = function () {
- return {"color": legendColor[0]};
- };
- $scope.chartID = $attrs.id;
- if (!angular.isDefined($attrs.legendRequired)) {
- $scope.legendRequired = CosChartD3Config.legendreqd;
- } else {
- $scope.legendRequired = $attrs.legendRequired;
- }
- if (!angular.isDefined($attrs.legendPosition)) {
- $scope.legendPosition = CosChartD3Config.legendposition;
- } else {
- $scope.legendPosition = $attrs.legendPosition;
- }
- }],
- link: function (scope, element, attrs) {
- // var radius = Math.min(attrs.chartWidth, attrs.chartHeight) / 2,
- var color = d3.scale.ordinal().range(CosChartD3Config.chartcolor.paletteColors),
- zoom = parseInt(CosChartD3Config.zoomLevel, 0),data,
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2;
- scope.LegendLabel = CosChartD3Config.defaultcenterlabel;
- scope.LegendCategory = CosChartD3Config.defaultcentercategory;
- scope.$watch('initVal', function (value) {
- if(!angular.isDefined(scope.initVal)){
- return;
- }
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- var cosval = parseInt(scope.initVal.value, 10);
- scope.cosval = cosval + "%";
- if(cosval>100){
- data = [
- {"name": "cos1", "value": 100},
- {"name": "rest", "value": 0}
- ];
- }else{
- data = [
- {"name": "cos1", "value": cosval},
- {"name": "rest", "value": 100 - (parseInt(cosval, 10))}
- ];
- }
- var sliderpercent = parseInt(cosval, 10);
- if (angular.isDefined(sliderpercent)) {
- sliderpercent = 0;
- }
- element[0].querySelector('.cosd3Container').setAttribute('id', attrs.id);
- // build chart
- var svg = d3.select(".cosd3Container#" + attrs.id)
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", "100%")
- .attr("height", "100%")
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius - CosChartD3Config.doughnutratio)
- .outerRadius(radius);
- // set hovered radius
- var arcOver = d3.svg.arc()
- .innerRadius(radius - CosChartD3Config.doughnutratio)
- .outerRadius(radius + CosChartD3Config.arcOverMargin);
-
- // add center text element
- var centerTextValue = svg.append("text")
- .attr("y", CosChartD3Config.centerTextValueDy)
- .attr("x", CosChartD3Config.centerTextValueDx)
- .attr("class", "coschartcenterValue");
- var centerTextPercent = svg.append("text")
- .attr("x", CosChartD3Config.centerTextPercentDx)
- .attr("y", CosChartD3Config.centerTextPercentDy)
- .attr("class", "coschartcenterPercent");
- var centerTextLabel = svg.append("text")
- .attr("y", CosChartD3Config.centerTextLabelDy)
- .attr("x", CosChartD3Config.centerTextLabelDx)
- .attr("class", "coschartcenterLabel");
- centerTextValue.text(cosval);
- centerTextPercent.text("%");
- centerTextLabel.text(CosChartD3Config.defaultcenterlabel + "(" + CosChartD3Config.defaultcentercategory + ")");
-
- var pie = d3.layout.pie()
- .sort(null)
- .startAngle(3.2 * Math.PI)
- .endAngle(5.2 * Math.PI)
- .value(function (d) {
- return d.value;
- });
-
- // set chart attributes and bind hover events
- var g = svg.selectAll(".arc")
- .data(pie(data))
- .enter()
- .append("g")
- .attr("class", "arc")
- .attr("id", function (d, i) {
- return "cosarc-" + i;
- })
- .style("cursor", "pointer");
-
- g.append("path")
- .style("fill", function (d) {
- return color(d.data.name);
- })
- .attr("id", function (d, i) {
- return "cospath-" + i;
- })
- .on("mouseover", function (d) {
- d3.select(this).transition()
- .duration(CosChartD3Config.animduration)
- .attr("d", arcOver);
- })
- .on("mouseout", function (d) {
- d3.select(this).transition()
- .duration(CosChartD3Config.animduration)
- .attr("d", arc);
- })
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
-
- // animate function
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 2.1 * Math.PI,
- endAngle: 2.1 * Math.PI
- }, b);
- return function (t) {
- return arc(i(t));
- };
- }
- if(cosval>0 && cosval<100){
- d3.select(".cosd3Container path#cospath-1").style('stroke', 'black');
- }
-
-
-
- });
- }
- };
- }]);
-angular.module('att.charts.coschartwithbarD3', ['att.charts.utilities'])
-.constant("CosChartWithBarD3Config",
- {
- "chartcolor": {
- "paletteColors": ["#0574ac", "#44c8f5", "#4ca90c", "#da0081", "#ff9900", "#81017e"], //["#097cb5", "#FEFFF7"], //default color options for rendering chart baseColor and NeedleColor,
- "zeroColor": "#ffffff",
- "borderColor": "#666666"
- },
- "zoomLevel": "25",
- "doughnutratio": 20,
- "barreqd": "true",
- "barHeight": 50,
- "barWidth": 150,
- "barCornerRadius": 9,
- //"barTextValueDy": "250",
- //"barTextValueDx": "0",
- //"barTextPercentDx": "20",
- //"barTextPercentDy": "-250",
- //"barTextLabelDy": "60",
- //"barTextLabelDx": "-80",
- //"defaultbarlabel": "CoS 2V/CoS 2/CoS 3/CoS 4/CoS 5",
- "animduration": "300",
- "centerText": {
- 'defaultCenterLabel': 'COS 1',
- 'defaultCenterCategory': 'Real Time',
- 'textValueDy': '0',
- 'textValueDx': '0',
- 'textPercentDx': '20',
- 'textPercentDy': '-10',
- 'textLabelDx': '0',
- 'textLabelDy': '20',
- 'color': '#666666',
- 'size': '36px',
- 'font': 'omnes_att_light'
- },
- "centerTextValueDy": "0",
- "centerTextValueDx": "0",
- "centerTextPercentDx": "20",
- "centerTextPercentDy": "-10",
- "centerTextLabelDy": "20",
- "centerTextLabelDx": "0",
- "arcOverMargin": 5
- })
-.directive('attCosBarD3Chart', ['CosChartWithBarD3Config', '$timeout','$extendObj', function (CosChartWithBarD3Config, $timeout,$extendObj) {return {
- restrict: 'A',
- scope: {
- chartConfig: '=',
- chartData: '=',
- totalCos: '=',
- remainingCos: '=',
- mouseOver: '=?'
- },
- templateUrl: 'template/coschartwithbarD3/attCosBarD3Chart.html',
- transclude: true,
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- CosChartWithBarD3Config = $extendObj.extendDeep(CosChartWithBarD3Config, $scope.chartConfig);
- }
-
- $scope.chartID = $attrs.id;
- if (!angular.isDefined($attrs.barRequired)) {
- $scope.barRequired = CosChartWithBarD3Config.barreqd;
- } else {
- $scope.barRequired = $attrs.barRequired;
- }
-
- }],
- link: function (scope, element, attrs) {
- /*
- x: x-coordinate
- y: y-coordinate
- w: width
- h: height
- r: corner radius
- tl: top_left rounded?
- tr: top_right rounded?
- bl: bottom_left rounded?
- br: bottom_right rounded?
- */
- function rounded_rect(x, y, w, h, r, tl, tr, bl, br) {
- var retval;
- retval = "M" + (x + r) + "," + y;
- retval += "h" + (w - 2*r);
- if (tr) { retval += "a" + r + "," + r + " 0 0 1 " + r + "," + r; }
- else { retval += "h" + r; retval += "v" + r; }
- retval += "v" + (h - 2*r);
- if (br) { retval += "a" + r + "," + r + " 0 0 1 " + -r + "," + r; }
- else { retval += "v" + r; retval += "h" + -r; }
- retval += "h" + (2*r - w);
- if (bl) { retval += "a" + r + "," + r + " 0 0 1 " + -r + "," + -r; }
- else { retval += "h" + -r; retval += "v" + -r; }
- retval += "v" + (2*r - h);
- if (tl) { retval += "a" + r + "," + r + " 0 0 1 " + r + "," + -r; }
- else { retval += "v" + -r; retval += "h" + r; }
- retval += "z";
- return retval;
- }
-
- var radScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
-
-
- var zoom = parseInt(CosChartWithBarD3Config.zoomLevel, 0),data,
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2;
-
-
- scope.$watchCollection('chartData', function (value) {
- var j = 0; // index for for-loops
-
- if(!angular.isDefined(scope.chartData) || scope.chartData.length < 1){
- return;
- }
-
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
-
- // SnickrBar
- d3.select("svg#" + scope.snickrbarId).remove();
- d3.selectAll("svg#" + scope.snickrbarId + " > *").remove();
-
- var cosval = scope.chartData[0];
- var remainingCosVal = 0, restCosVal = 0;
-
- for(j = 1; j < scope.chartData.length; j++)
- {
- remainingCosVal += parseInt(scope.chartData[j], 10); //parseInt allows strings to be passed in
- }
- restCosVal = 100 - cosval - remainingCosVal;
- scope.totalCos = cosval + remainingCosVal;
- scope.remainingCos = remainingCosVal;
-
- var data = angular.copy(scope.chartData);
- if (angular.isDefined(restCosVal)) {
- data.push(restCosVal);
- }
-
- element[0].querySelector('.cosd3Container').setAttribute('id', attrs.id);
- // build chart
- var svg = d3.select(".cosd3Container#" + attrs.id)
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", "100%")
- .attr("height", "100%")
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
-
- scope.snickrbarId = attrs.id + 'snickrbar';
- var snickrbar = d3.select(".snickrBar")
- .attr('style', 'margin-left:' + Math.floor(CosChartWithBarD3Config.barWidth/3) + ';')
- .style({'background-color': CosChartWithBarD3Config.chartcolor.zeroColor, 'width': CosChartWithBarD3Config.barWidth + 'px', 'border': '1px solid #777', 'border-radius': '10px'})
- .append("svg")
- .attr("id", scope.snickrbarId)
- .attr("width", CosChartWithBarD3Config.barWidth + "px")
- .attr("height", CosChartWithBarD3Config.barHeight + "px")
- .append("g");
-
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius - CosChartWithBarD3Config.doughnutratio)
- .outerRadius(radius);
-
- // set hovered radius
- var arcOver = d3.svg.arc()
- .innerRadius(radius - CosChartWithBarD3Config.doughnutratio)
- .outerRadius(radius + CosChartWithBarD3Config.arcOverMargin);
-
- // add center text element
- var centerTextValue = svg.append("text")
- .attr("y", CosChartWithBarD3Config.centerText.textValueDy)
- .attr("x", CosChartWithBarD3Config.centerText.textValueDx)
- .attr("class", "coschartcenterValue");
- var centerTextPercent = svg.append("text")
- .attr("x", CosChartWithBarD3Config.centerText.textPercentDx)
- .attr("y", CosChartWithBarD3Config.centerText.textPercentDy)
- .attr("class", "coschartcenterPercent");
- var centerTextLabel = svg.append("text")
- .attr("y", CosChartWithBarD3Config.centerText.textLabelDy)
- .attr("x", CosChartWithBarD3Config.centerText.textLabelDx)
- .attr("class", "coschartcenterLabel");
- centerTextValue.text(cosval);
- centerTextPercent.text("%");
- centerTextLabel.text(CosChartWithBarD3Config.centerText.defaultCenterLabel + "(" + CosChartWithBarD3Config.centerText.defaultCenterCategory + ")");
-
- var scale = function(d) {
- if (d <= 0) {
- return 0;
- } else {
- var r = (d * CosChartWithBarD3Config.barWidth) / 100;
- if (isNaN(r)) { r = 0; }
- else if (!isFinite(r)) { r = CosChartWithBarD3Config.barWidth; }
-
- return r;
- }
- };
-
- // Only executed when totalCos is 0
- if (cosval <= 0) {
- arc.startAngle(0).endAngle(2 * Math.PI); //just radians
- svg.append("path")
- .attr("d", arc)
- .attr("fill", CosChartWithBarD3Config.chartcolor.zeroColor)
- .style("stroke", CosChartWithBarD3Config.chartcolor.borderColor)
- .style("stroke-width", 1);
- } else {
-
- // JVM: This code is temp for just snicker's bar release
- var temp = 100-data[0];
- var newData = [];
- newData.push({'value':data[0]});
- newData.push({'value':temp});
-
- /*for(j = 0; j < data.length; j++) {
- var obj = angular.extend({}, data[j]);
- obj.value = data[j];
- newData.push(obj);
- }*/
-
-
- //======================================================
-
-
- var pie = d3.layout.pie()
- .sort(null)
- .value(function (d,index) {
- var r = d.value;
- if (d.value <= 0) { r = 0; }
- return r;
- });
-
- // set chart attributes and bind hover events
- var g = svg.selectAll(".arc")
- .data(pie(newData))
- .enter()
- .append("g")
- .attr("class", "arc")
- .attr("id", function (d, i) {
- return "cosarc-" + i;
- })
- .style("cursor", "pointer");
-
- g.append("path")
- .style("fill", function (d, i) {
- if (i === CosChartWithBarD3Config.chartcolor.paletteColors.length || i === newData.length-1 || d.data.value === 0) {
- return CosChartWithBarD3Config.chartcolor.zeroColor;
- }
-
- return CosChartWithBarD3Config.chartcolor.paletteColors[i];
- })
- .style("stroke", "white")
- .style("stroke-width", function(d,index) { if (cosval >= 100) { return 0; } else { return 1; } })
- .attr("id", function (d, i) {
- return "cospath-" + i;
- })
- .on("mouseover", function (d, index) {
- if (index < newData.length-1) {
- d3.select(this).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arcOver);
- }
- })
- .on("mouseout", function (d, index) {
- if (index < newData.length-1) {
- d3.select(this).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arc);
- }
- })
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
- } // end of else
-
- if (!CosChartWithBarD3Config.barreqd) { return; }
- var snickrData = [];
- var d = scope.chartData.slice(1, scope.chartData.length);
- for (j = 0; j < d.length; j++) {
- if (d[j] !== 0) {
- var obj = {};
- obj.data = d[j];
- obj.color = CosChartWithBarD3Config.chartcolor.paletteColors[j+1];
- snickrData.push(obj);
- }
- }
-
- var prevWidth = 0;
- var nextX = function(d, i) {
- if (i === 0) {
- prevWidth = scale(d);
- return 0;
- } else {
- var p = prevWidth;
- prevWidth += scale(d);
- return p;
- }
- };
-
- var rect = snickrbar.selectAll("path")
- .data(snickrData)
- .enter()
- .append("path")
- .style("fill", function(d, i) {
- if (i >= CosChartWithBarD3Config.chartcolor.paletteColors.length || d.data === 0) {
- return CosChartWithBarD3Config.chartcolor.zeroColor;
- }
-
- return d.color;
- })
- .attr("d", function(d, index) {
- if (index === 0) {
- // Left rounded rectangle
- return rounded_rect(nextX(d.data, index), 0, scale(d.data), CosChartWithBarD3Config.barHeight, CosChartWithBarD3Config.barCornerRadius, true, false, true, false);
- } else if (index === snickrData.length-1 && remainingCosVal >= 100) {
- // Right rounded rectangle
- return rounded_rect(nextX(d.data, index), 0, scale(d.data), CosChartWithBarD3Config.barHeight, CosChartWithBarD3Config.barCornerRadius, false, true, false, true);
- } else {
- console.log('normal rect at ' + index);
- return rounded_rect(nextX(d.data, index), 0, scale(d.data), CosChartWithBarD3Config.barHeight, 0, false, false, false, false);
- }
- });
-
- if (remainingCosVal === 0) {
- snickrbar.attr("fill", CosChartWithBarD3Config.chartcolor.zeroColor);
- }
-
- // add bar text element
- /*var snickerText = d3.select('.snickrBar svg')
- .append("g")
- .style("fill", "black");
-
- var barTextValue = snickerText.append("text")
- .attr("y", CosChartWithBarD3Config.barTextValueDy)
- .attr("x", CosChartWithBarD3Config.barTextValueDx)
- .attr("class", "coschartbarcenterValue");
- var barTextPercent = snickerText.append("text")
- .attr("x", CosChartWithBarD3Config.barTextPercentDx)
- .attr("y", CosChartWithBarD3Config.centerTextPercentDy)
- .attr("class", "coschartbarcenterPercent");
- var barTextLabel = snickerText.append("text")
- .attr("y", CosChartWithBarD3Config.barTextLabelDy)
- .attr("x", CosChartWithBarD3Config.barTextLabelDx)
- .attr("class", "coschartbarcenterLabel");
- barTextValue.text(cosval);
- barTextPercent.text("%");
- barTextLabel.text(CosChartWithBarD3Config.defaultbarlabel);*/
-
-
-
- // animate function
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 2.1 * Math.PI,
- endAngle: 2.1 * Math.PI
- }, b);
- return function (t) {
- return arc(i(t));
- };
- }
-
- scope.$watch('mouseOver', function(val) {
- if (!angular.isDefined(scope.mouseOver)) { return; }
- var id = scope.mouseOver.split('-')[1];
- if (scope.mouseOver.split('-')[0] === 'true') {
- if (id === '0') {
- d3.select("#cospath-" + id).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arcOver);
- } else {
- for (var i = 0; i < newData.length-1; i++) {
- d3.select("#cospath-" + (i+1)).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arcOver);
- }
- }
- } else {
- if (id === '0') {
- d3.select("#cospath-" + id).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arc);
- } else {
- for (j = 0; j < newData.length-1; j++) {
- d3.select("#cospath-" + (j+1)).transition()
- .duration(CosChartWithBarD3Config.animduration)
- .attr("d", arc);
- }
- }
- }
- });
-
- });
-
- }
- };
- }]);
-angular.module('att.charts.cosdeletionD3', ['att.charts.utilities'])
- .constant("CosdeletionD3Config",
- {
- "chartcolor": {
- "MaxBandwidthReached": "#d3d3d3",
- "ZeroBandwidthSelected": "#FEFFF7",
- "RemainingBandwidthColor": "#ffffff",
- "RemainingBandwidthStrokeColor": "#d3d3d3",
- "RemainingBandwidthStrokeWidth": 1.5,
- "UsedBandwidthColor": "#0574AC",
- "UsedBandwidthStrokeColor":"#efefef", //white
- "UsedBandwidthStrokeWidth":"1"
- },
- "defaultcenterlabel": "Kbps",
- "zoomLevel": "10",
- "doughnutratio": 21,
- "animduration": "300",
- "guageStartAngle":4,
- "guageEndAngle":8.56,
- "legendreqd": "false",
- "initduration": "1000",
- "legendposition": "top",
- "centerTextLabelDy": "20",
- "centerTextValueDy": "0",
- "centerTextValueDx": "-30",
- "centerTextLabelDx": "-10",
- "maxbandwidthTextDx": "25",
- "maxbandwidthTextDy": "70",
- "arcOverMargin": 5
- })
- .directive('attCosdeletiond3Chart', ['CosdeletionD3Config', '$timeout','$extendObj', function(CosdeletionD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- maxValue: '=',
- chartData: '=',
- chartConfig: '=',
- resetChart: '=',
- removeArcs: '='
- },
- controller: ['$scope', '$attrs', function($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- CosdeletionD3Config = $extendObj.extendDeep(CosdeletionD3Config, $scope.chartConfig);
- }
-
- }],
- link: function(scope, element, attrs) {
- var zoom = parseInt(CosdeletionD3Config.zoomLevel, 0),
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2,arcPath;
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius - CosdeletionD3Config.doughnutratio)
- .outerRadius(radius);
- var arcOver = d3.svg.arc()
- .innerRadius(radius - CosdeletionD3Config.doughnutratio)
- .outerRadius(radius + CosdeletionD3Config.arcOverMargin);
-
- // Browser onresize event
- window.onresize = function() {
- scope.$apply();
- };
- scope.$watch('resetChart', function(newValue, oldValue) {
- if(scope.resetChart === true){
- scope.resetChart = false;
- return;
- }
- return scope.render(newValue, oldValue);
- });
- scope.render = function(newValue, oldValue) {
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- if (!scope.chartData)
- {
- return;
- }
- var data=angular.copy(scope.chartData);
- data=data.reverse();
- var totalBandwidth=0,totalUsed=0,remainingBandwidth=0,dynamicColorRange=[],noCheckBoxSelected=true,selectedBandwidth=0,selectedElem=[];
- if (angular.isDefined(scope.maxValue)) {
- totalBandwidth = parseInt(scope.maxValue, 0);
- }
- for (var j = 0; j < data.length; j++) {
- totalUsed = (totalUsed + parseInt(data[j].value, 0));
- if(angular.equals(data[j].status, true)){
- noCheckBoxSelected=false;
- selectedBandwidth=selectedBandwidth+data[j].value;
-
- data[j].value=0;
- dynamicColorRange.push(CosdeletionD3Config.chartcolor.MaxBandwidthReached);
-
- }else{
- selectedElem.push({index: data[j].id, value: data[j].value});
- dynamicColorRange.push(CosdeletionD3Config.chartcolor.UsedBandwidthColor);
- }
- }
- if(scope.removeArcs){
- while(data.length > 0) {
- data.pop();
- }
- dynamicColorRange=[];
- data.push({name: "totalUsed", value: totalUsed-selectedBandwidth,id:"totalUsed"});
- dynamicColorRange.push(CosdeletionD3Config.chartcolor.UsedBandwidthColor);
- scope.removeArcs=false;
- }
- if(totalUsed>0 && totalUsed<totalBandwidth){
- remainingBandwidth=totalBandwidth-totalUsed;
- if(!noCheckBoxSelected){
- data.push({name: "selectedBandwidth", value: selectedBandwidth,id:"selectedBandwidth"});
- dynamicColorRange.push(CosdeletionD3Config.chartcolor.MaxBandwidthReached);
- }
- data.push({name: "remaining", value: remainingBandwidth,id:"remaining"});
- dynamicColorRange.push(CosdeletionD3Config.chartcolor.RemainingBandwidthColor);
- }
- element[0].setAttribute('id', attrs.id);
- var svg = d3.select(element[0])
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("radius", radius)
- .attr("width", attrs.chartWidth)
- .attr("height", attrs.chartHeight)
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
-
- var centerTextValue = svg.append("text")
- .attr("y", CosdeletionD3Config.centerTextValueDy)
- .attr("x", CosdeletionD3Config.centerTextValueDx)
- .attr("class", "cosdeletioncenterValue");
- var centerTextLabel = svg.append("text")
- .attr("y", CosdeletionD3Config.centerTextLabelDy)
- .attr("x", CosdeletionD3Config.centerTextLabelDx)
- .attr("class", "cosdeletioncenterLabel");
- var maxbandwidthText = svg.append("text")
- .attr("y", CosdeletionD3Config.maxbandwidthTextDy)
- .attr("x", CosdeletionD3Config.maxbandwidthTextDx)
- .attr("class", "cosdeletionmaxbandwidthText");
-
- var color = d3.scale.ordinal().range(dynamicColorRange);
- centerTextValue.text(totalUsed-selectedBandwidth);
- centerTextLabel.text(CosdeletionD3Config.defaultcenterlabel);
- maxbandwidthText.text(totalBandwidth + " " + CosdeletionD3Config.defaultcenterlabel);
-
- var pie = d3.layout.pie()
- .sort(null)
- .startAngle(CosdeletionD3Config.guageStartAngle)
- .endAngle(CosdeletionD3Config.guageEndAngle)
- .value(function(d) {
- return d.value;
- });
-
- var g = svg.selectAll(".arc")
- .data(pie(data))
- .enter()
- .append("g")
- .attr("class", "arc")
- .attr("id", function(d, i) {
- return "cosdeletionarc-" + d.data.id;
- })
- .style("cursor", "pointer");
-
- arcPath = g.append("path")
- .style("fill", function(d) {
- return color(d.data.name);
- }).attr("id", function(d, i) {
- return "cosdeletionpath-" + d.data.id;
- })
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
-
- arcPath = arcPath[0];
- for (var i = 0; i < arcPath.length; i++) {
- var id = arcPath[i].id;
- if (id !== 'cosdeletionpath-remaining' && id !== 'cosdeletionpath-selectedBandwidth') {
- d3.select("path#" + id).transition().attr("d", arcOver);
- }
- }
-
- if (remainingBandwidth > 0) {
- if(angular.isDefined(newValue) && angular.isDefined(oldValue)){
- for (var k = 0; k < selectedElem.length; k++) {
- var index =selectedElem[k].index;
- d3.select("path#cosdeletionpath-" + index).style('stroke', CosdeletionD3Config.chartcolor.UsedBandwidthStrokeColor).style("stroke-width", CosdeletionD3Config.chartcolor.UsedBandwidthStrokeWidth);
- }
- }
- d3.select("#" + attrs.id + " path#cosdeletionpath-remaining").style('stroke', CosdeletionD3Config.chartcolor.RemainingBandwidthStrokeColor).style("stroke-width", CosdeletionD3Config.chartcolor.RemainingBandwidthStrokeWidth);
- }
- };
-
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 2.1 * Math.PI,
- endAngle: 2.1 * Math.PI
- }, b);
- return function(t) {
- return arc(i(t));
- };
- }
- }
- };
- }]);
-angular.module('att.charts.cosmultichartD3', ['att.charts.utilities'])
- .constant("CosMultiChartD3Config",
- {
- "chartcolor": {
- "paletteColors": ["#44c6f7", "#4ba90b", "#d70e80", "#ff9900", "#81017e", "#cccccc"], //default color options for rendering chart baseColor and NeedleColor,
- "zeroTicketColor": ["#d3d3d3"]
- },
- "defaultcenterlabel": "CoS",
- "defaultcentercategory": "2V/2/3/4/5",
- "zoomLevel": "25",
- "doughnutratio": 20,
- "animduration": "300",
- "legendreqd": "false",
- "initduration": "1000",
- "legendposition": "top",
- "centerTextValueDy": "0",
- "centerTextValueDx": "0",
- "centerTextPercentDx": "22",
- "centerTextPercentDy": "-8",
- "centerTextLabelDy": "20",
- "centerTextLabelDx": "0",
- "arcOverMargin": 5
- })
- .directive('attCosmultid3Chart', ['CosMultiChartD3Config', '$timeout','$extendObj', function (CosMultiChartD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- chartConfig: '='
- },
- templateUrl: 'template/cosmultichartD3/attCosmultid3Chart.html',
- transclude: true,
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
-
- if (angular.isDefined($scope.chartConfig)) {
- CosMultiChartD3Config = $extendObj.extendDeep(CosMultiChartD3Config, $scope.chartConfig);
- }
-
- $scope.addLegendColor = function (id, item) {
- return {"color": CosMultiChartD3Config.chartcolor.paletteColors[id]};
- };
-
- $scope.chartID = $attrs.id;
- if (!angular.isDefined($attrs.legendRequired)) {
- $scope.legendRequired = CosMultiChartD3Config.legendreqd;
- } else {
- $scope.legendRequired = $attrs.legendRequired;
- }
- if (!angular.isDefined($attrs.legendPosition)) {
- $scope.legendPosition = CosMultiChartD3Config.legendposition;
- } else {
- $scope.legendPosition = $attrs.legendPosition;
- }
- }],
- link: function (scope, element, attrs) {
- var zoom = parseInt(CosMultiChartD3Config.zoomLevel, 0),
- pi = Math.PI,
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2;
-
- function renderChart() {
- var color = d3.scale.ordinal().range(CosMultiChartD3Config.chartcolor.paletteColors);
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- var totalCosVal = 0, remainingCosVal;
- for (var j = 0; j < scope.chartData.length; j++) {
- var chartObj = scope.chartData[j];
- totalCosVal = (totalCosVal + parseInt(chartObj.value, 10));
- }
- remainingCosVal = 100 - parseInt(totalCosVal, 10);
- var data = angular.copy(scope.chartData);
- if (angular.isDefined(remainingCosVal)) {
- data.push({name: "rest", value: remainingCosVal});
- }
- element[0].querySelector('.cosmultid3Container').setAttribute('id', attrs.id);
- // build chart
- var svg = d3.select(".cosmultid3Container#" + attrs.id)
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", "100%")
- .attr("height", "100%")
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius - CosMultiChartD3Config.doughnutratio)
- .outerRadius(radius);
- // set hovered radius
- var arcOver = d3.svg.arc()
- .innerRadius(radius - CosMultiChartD3Config.doughnutratio)
- .outerRadius(radius + CosMultiChartD3Config.arcOverMargin);
- // add center text element
- var centerTextValue = svg.append("text")
- .attr("y", CosMultiChartD3Config.centerTextValueDy)
- .attr("x", CosMultiChartD3Config.centerTextValueDx)
- .attr("class", "cosmultichartcenterValue");
- var centerTextPercent = svg.append("text")
- .attr("x", CosMultiChartD3Config.centerTextPercentDx)
- .attr("y", CosMultiChartD3Config.centerTextPercentDy)
- .attr("class", "cosmultichartcenterPercent");
- var centerTextLabel = svg.append("text")
- .attr("y", CosMultiChartD3Config.centerTextLabelDy)
- .attr("x", CosMultiChartD3Config.centerTextLabelDx)
- .attr("class", "cosmultichartcenterLabel");
- centerTextValue.text(totalCosVal);
- centerTextPercent.text("%");
- centerTextLabel.text(CosMultiChartD3Config.defaultcenterlabel +" " + CosMultiChartD3Config.defaultcentercategory);
-
- if (totalCosVal <= 0) {
- arc.startAngle(0).endAngle(2 * pi); //just radians
- svg.append("path")
- .attr("d", arc)
- .attr("fill", CosMultiChartD3Config.chartcolor.zeroTicketColor);
- } else {
- var pie = d3.layout.pie()
- .sort(null)
- .startAngle(3.2 * Math.PI)
- .endAngle(5.2 * Math.PI)
- .value(function (d) {
- return d.value;
- });
-
- var g = svg.selectAll(".arc")
- .data(pie(data))
- .enter()
- .append("g")
- .attr("class", "arc")
- .attr("id", function (d, i) {
- return "cosmultiarc-" + i;
- })
- .style("cursor", "pointer");
-
- g.append("path")
- .style("fill", function (d) {
- return color(d.data.name);
- })
- .attr("id", function (d, i) {
- return "cosmultipath-" + i;
- })
- .style("stroke", "white")
- .style("stroke-width", 1)
- .on("mouseover", function (d) {
- d3.select(this).transition()
- .duration(CosMultiChartD3Config.animduration)
- .attr("d", arcOver);
- })
- .on("mouseout", function (d) {
- d3.select(this).transition()
- .duration(CosMultiChartD3Config.animduration)
- .attr("d", arc);
- })
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
-
-
- }
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 2.1 * Math.PI,
- endAngle: 2.1 * Math.PI
- }, b);
- return function (t) {
- return arc(i(t));
- };
- }
- }
-
- scope.$watch('chartConfig', function(value) {
- if (angular.isDefined(scope.chartConfig)) {
- CosMultiChartD3Config = $extendObj.extendDeep(CosMultiChartD3Config, scope.chartConfig);
- }
-
- renderChart();
- }, true);
-
- scope.$watch('chartData', function (value) {
- renderChart();
- });
- }
- };
- }]);
-angular.module('att.charts.donutD3', ['att.charts.utilities'])
- .constant("DonutChartD3Config",
- {
- "chartcolor": {
- "paletteColors": ["#676767", "#96B1D0", "#0B2477", "#FF9900", "#81017D", "#B6BF00", "#DA0081", "#00C7B2"], //default color options for rendering chart
- "zeroTicketColor": ["#d3d3d3"],
- "centerTicketCountHoverColor":["#0574AC"]
- },
- "zoomlevel": "25",
- "defaultcenterlabel": "Total",
- "donutratio": "1.5",
- "initduration": "1000",
- "animduration": "300",
- "legendreqd": "false",
- "legendposition": "right",
- "centerTextLabelDy": "20",
- "clipMargin": "400",
- "arcOverMargin":10
- })
- .directive('attDonutd3Chart', ['DonutChartD3Config', '$timeout','$extendObj', function (DonutChartD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- chartColor: '=',
- chartConfig: '=',
- refreshChart: '=',
- onclickcallback: '&',
- legendclickcallback: '&',
- centerclickcallback: '&'
- },
- templateUrl: 'template/donutD3/attDonutd3Chart.html',
- transclude: true,
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- DonutChartD3Config = $extendObj.extendDeep(DonutChartD3Config,$scope.chartConfig);
- }
- var legendColors = [];
- legendColors = ($scope.chartColor) ? $scope.chartColor : DonutChartD3Config.chartcolor.paletteColors;
- $scope.addLegendColor = function (id, item) {
- if (item.value > 0) {
- return {"color": legendColors[id]};
- } else {
- return {"color": DonutChartD3Config.chartcolor.zeroTicketColor};
- }
- };
- $scope.chartID = $attrs.id;
- if (!angular.isDefined($attrs.legendRequired)) {
- $scope.legendRequired = DonutChartD3Config.legendreqd;
- } else {
- $scope.legendRequired = $attrs.legendRequired;
- }
- if (!angular.isDefined($attrs.legendPosition)) {
- $scope.legendPosition = DonutChartD3Config.legendposition;
- } else {
- $scope.legendPosition = $attrs.legendPosition;
- }
- $scope.addStyle = function (elem) {
- if ($scope.legendRequired && angular.isDefined($scope.legendPosition)) {
- if ($attrs.legendPosition === "right") {
- return "floatLeft";
- } else {
- if (elem === 'chartLegend')
- {
- return "floatLeft";
- }
- else
- {
- return "floatRight";
- }
- }
- } else {
- return "floatLeft";
- }
- };
- }],
- link: function (scope, element, attrs) {
- scope.$watch('refreshChart', function () {
- if (angular.isDefined(scope.refreshChart)) {
- if (scope.refreshChart !== true)
- {
- return;
- } else {
- for (var j = 0; j < scope.chartData.length; j++) {
- var chartObj =scope.chartData[j];
- var className = (chartObj.name).replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + className + "]")).removeClass("active");
- }
-
- }
-
- }
-
- if (angular.isDefined(scope.chartConfig)) {
- DonutChartD3Config = $extendObj.extendDeep(DonutChartD3Config, scope.chartConfig);
- }
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- var selectedPath = "",
- lastSelected,
- pi = Math.PI;
- var zoom = parseInt(DonutChartD3Config.zoomlevel, 0),
- coloroptions = (scope.chartColor) ? scope.chartColor : DonutChartD3Config.chartcolor.paletteColors,
- defaultcenterlabel = DonutChartD3Config.defaultcenterlabel,
- totalcount = 0,
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- // set height and width plus margin so zoomed area is not clipped
- /* width = parseInt(attrs.chartWidth, 0) - (margin.left + margin.right),
- height = parseInt(attrs.chartHeight, 0) - (margin.top + margin.bottom),
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2,*/
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2,
- color = d3.scale.ordinal().range(coloroptions);
- if (angular.isDefined(scope.chartData)) {
- for (var i in scope.chartData) {
- if (angular.isDefined(scope.chartData[i].value)) {
- totalcount = (totalcount + parseInt(scope.chartData[i].value, 10));
- }
- }
- }
-
- var data=[];
- for (var z = 0; z < scope.chartData.length; z++) {
- var chartElem =scope.chartData[z];
- if(chartElem.value <= 0){
- data.push({index: z, value: chartElem.value});
- }
- }
- var chartStyle = d3.select(".chartContainer#" + attrs.id)
- .attr("style");
- var chart = d3.select(".chartContainer#" + attrs.id)
- .attr("style", "height: " + attrs.chartHeight + "px;width:" + attrs.chartWidth + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", '100%')
- .attr("height", '100%')
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius / DonutChartD3Config.donutratio)
- .outerRadius(radius);
- // add center text element
- var centerTextValue = chart.append("text")
- .attr("class", "donutcenterValue")
- .attr("id", attrs.id + "count")
- .on("click", function (d) {
- var value = d3.select("g > text#" + attrs.id + "count").text();
- var label = d3.select("g > text#" + attrs.id + "category").text();
- if (angular.isDefined(scope.onclickcallback)) {
- scope.centerclickcallback({count: value, category: label});
- }
- });
- var centerTextLabel = chart.append("text")
- .attr("y", DonutChartD3Config.centerTextLabelDy)
- .attr("class", "donutcenterLabel")
- .attr("id", attrs.id + "category");
-
- centerTextValue.text(totalcount);
- centerTextLabel.text(defaultcenterlabel);
- if (totalcount <= 0) {
- arc.startAngle(0).endAngle(2 * pi); //just radians
- chart.append("path")
- .attr("d", arc)
- .attr("fill", DonutChartD3Config.chartcolor.zeroTicketColor);
- } else {
- // set hovered radius
- var arcOver = d3.svg.arc()
- .innerRadius(radius / DonutChartD3Config.donutratio)
- .outerRadius(radius + DonutChartD3Config.arcOverMargin);
- var pie = d3.layout.pie()
- .sort(null)
- .startAngle(1.1 * Math.PI)
- .endAngle(3.1 * Math.PI)
- .value(function (d) {
- return d.value;
- });
- var g = chart.selectAll(".arc")
- .data(pie(scope.chartData))
- .enter()
- .append("g")
- .attr("class", "arc")
- .style("cursor", "pointer");
- // set fill color and animate tween
- g.append("path")
- .style("fill", function (d) {
- return color(d.data.name);
- })
- .attr("path-id",function (d, i) {
- return "b-" + i;
- })
- .style("stroke", "white")
- .style("stroke-width", 1)
- .on("mouseover", function (d) {
- d3.select(this).transition()
- .duration(DonutChartD3Config.animduration)
- .attr("d", arcOver);
-
- centerTextValue.text(d3.select(this).datum().data.value);
- centerTextLabel.text(d3.select(this).datum().data.name);
- var className = d3.select(this).datum().data.name.replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + className + "]")).addClass("active");
- })
- .on("mouseout", function (d) {
- if (!this.getAttribute("clicked")) {
- d3.select(this).transition()
- .duration(DonutChartD3Config.animduration)
- .attr("d", arc);
- if (selectedPath.length === 0) {
- centerTextValue.text(totalcount);
- centerTextLabel.text(defaultcenterlabel);
- } else {
- centerTextValue.text(selectedPath.datum().data.value);
- centerTextLabel.text(selectedPath.datum().data.name);
- }
- var className = d3.select(this).datum().data.name.replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + className + "]")).removeClass("active");
- } else if (angular.isDefined(lastSelected) && lastSelected!=="") {
- lastSelected.transition()
- .duration(DonutChartD3Config.animduration)
- .attr("d", arc);
- if (angular.isDefined(lastSelected)) {
- var prevclassName = lastSelected.datum().data.name.replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + prevclassName + "]")).removeClass("active");
- }
- }
- })
- .on("click", function (d, i) {
- if (angular.isDefined(scope.onclickcallback)) {
- scope.onclickcallback({name: d3.select(this).datum().data.name, value: d3.select(this).datum().data.value});
- }
- if (!this.getAttribute("clicked")) {
- this.setAttribute("clicked", "clicked");
- if (selectedPath !== "") {
- lastSelected = selectedPath;
- selectedPath[0][0].removeAttribute("clicked");
- }
- selectedPath = d3.select(this);
- } else {
- if (this.getAttribute("path-id") === selectedPath.attr("path-id")) {
- selectedPath[0][0].removeAttribute("clicked");
- selectedPath = "";
- }
- }
-
- })
- .transition()
- .ease("exp")
- .duration(DonutChartD3Config.initduration)
- .attrTween("d", tweenPie);
- // animate function
- scope.legendMouseOver = function (item, id, e) {
- selectedId="b-"+id;
- if (item.value > 0) {
- scope.LegendClass = "";
- this.LegendClass = "active";
- centerTextValue.text(item.value);
- centerTextLabel.text(item.name);
- d3.selectAll(".chartContainer#"+attrs.id+" "+"path").each(function(d, i) {
- if(this.getAttribute("path-id")==selectedId){
- d3.select(this).transition()
- .duration(DonutChartD3Config.animduration)
- .attr("d", arcOver);
- }
- });
-
- d3.select("#TicketGraphcount").style('fill',DonutChartD3Config.chartcolor.centerTicketCountHoverColor);
- }
- };
- scope.legendMouseLeave = function (item, id, e) {
- selectedId="b-"+id;
- hoveredLegendItem=this;
- if (item.value > 0) {
- if (selectedPath.length === 0) {
- centerTextValue.text(totalcount);
- centerTextLabel.text(defaultcenterlabel);
- } else {
- centerTextValue.text(selectedPath.datum().data.value);
- centerTextLabel.text(selectedPath.datum().data.name);
- }
- d3.selectAll(".chartContainer#"+attrs.id+" "+"path").each(function(d, i) {
- if(this.getAttribute("path-id")==selectedId){
- if(this.getAttribute("clicked")===null){
- hoveredLegendItem.LegendClass = "";
- d3.select(this).transition().duration(DonutChartD3Config.animduration).attr("d", arc);
- }
- }
- });
- d3.select("#TicketGraphcount").style('fill', "#000");
-
- }
- };
- }
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 1.1 * Math.PI,
- endAngle: 1.1 * Math.PI
- }, b);
- return function (t) {
- return arc(i(t));
- };
- }
- $timeout(function () {
- var h = element.find("ul")[0].clientHeight,
- fHeight = (parseInt(height, 10) - h),
- className = scope.addStyle('chartContainer');
- fHeight = (fHeight < 0) ? 0 : fHeight;
- angular.element(element[0].querySelector('.chartContainer')).addClass(className);
- angular.element(element[0].querySelector(".chartLegend")).css({
- "margin-top": (fHeight / 2) + "px"
- });
- }, 200);
- for (var k = 0; k < data.length; k++) {
- var index =data[k].index;
- var zeroValIndex="b-"+index;
- if(data[k].value <= 0){
- removeStrokelines(zeroValIndex);
- }
-
- }
-
- function removeStrokelines(zeroValIndex){
- d3.selectAll(".chartContainer#"+attrs.id+" "+"path").each(function(d, i) {
- if(this.getAttribute("path-id")==zeroValIndex){
- d3.select(this).style('stroke', "").style("stroke-width", "");
- }
- });
- }
- scope.refreshChart = false;
- });
-
- }
- };
- }])
- .filter('filterData', function () {
- return function (input) {
- return input.replace(/ /g, "").toUpperCase();
- };
- });
-angular.module('att.charts.donutFusion', [])
- .constant("DonutChartFusionConfig",
- {
- "chart": {
- "caption": "Tickets",
- "startingAngle": 0,
- "theme": "fist",
- "captionPadding": "0",
- "paletteColors": "#FF0066,#00CCFF,#00CC66,#6699FF,#000099,#660066,#FF6600,#4D4D4D", //default color options for rendering chart
- "enableSmartLabels": "0",
- "enableMultiSlicing": "1",
- "donutRadius": "65",
- "pieRadius": "110",
- "showLabels": "0",
- "showValues": "0",
- "showBorder": "0",
- "showpercentintooltip": "0",
- "bgcolor": "#FFFFFF",
- "defaultCenterLabel": "Total",
- "showshadow": 0,
- "centerLabel": "$value $label",
- "plotHoverEffect": 1,
- "plotBorderHoverDashGap": "50",
- "enableRotation": "0",
- "baseFont": "Arial",
- "baseFontColor": "#666666",
- "use3DLighting": "0",
- "numbersuffix": "",
- "defaultAnimation": "0",
- "showValuesOnHover": 0
- }
- })
- .directive('attDonutfusionChart', ['DonutChartFusionConfig', '$timeout', function (DonutChartFusionConfig, $timeout) {
- 'use strict';
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- onclickcallback: '&'
- },
- templateUrl: 'template/donutFusion/attDonutfusionChart.html',
- transclude: true,
- replace: true,
- link: function (scope, element, attrs, controller, transclude) {
- var totalItems = 0;
- if (angular.isDefined(scope.chartData)) {
- for (var i in scope.chartData) {
- if(angular.isDefined(scope.chartData[i].value)){
- totalItems = (totalItems + parseInt(scope.chartData[i].value, 10));
- }
- }
- }
- DonutChartFusionConfig.data = scope.chartData;
- var donutChartDataSource = DonutChartFusionConfig;
- var defaultCenterLabelText;
- defaultCenterLabelText = totalItems + ' ' + DonutChartFusionConfig.chart.defaultCenterLabel;
- donutChartDataSource.chart.defaultCenterLabel = defaultCenterLabelText;
-
- var initChart = function () {
- FusionCharts.ready(function () {
- var donutChart = new FusionCharts({
- type: 'doughnut2d',
- renderAt: "donutFusionChart",
- //width: '100%',
- width: attrs.chartWidth,
- height: attrs.chartHeight,
- dataFormat: 'json',
- dataSource: donutChartDataSource,
- events: {
- //dataPlotRollOver event is raised whenever you hover over a data plot (column, anchor of line or area, pie etc.)
- "dataPlotRollOver": function (evtObj, argumentsObject) {
- var selectedLabelArr = argumentsObject.toolText.split(",");
- var className = selectedLabelArr[0].replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + className + "_fusion" + "]")).addClass("active");
- },
- "dataPlotRollOut": function (evtObj, argObj) {
- var selectedLabelArr = argObj.toolText.split(",");
- var className = selectedLabelArr[0].replace(/ /g, "").toUpperCase();
- angular.element(document.querySelector("[chart-legend-id=" + className + "_fusion" + "]")).removeClass("active");
- },
- "dataPlotClick": function (evtObj, argObj) {
- if(angular.isDefined(scope.onclickcallback)){
- scope.onclickcallback({evtObj:evtObj, argObj:argObj});
- }
- }
- }
- });
- donutChart.render();
- DonutChartFusionConfig.chart.defaultCenterLabel = DonutChartFusionConfig.chart.defaultCenterLabel;
- });
- };
- initChart();
- $timeout(function () {
- var w = element.find("ul")[0].clientHeight,
- fWidth = (parseInt(attrs.chartHeight, 10) - w);
- element.find("ul").css("margin-top", (fWidth / 2) + "px");
-
- }, 200);
- },
- controller: function ($scope, $element, $attrs) {
- var legendColors = [];
- legendColors = DonutChartFusionConfig.chart.paletteColors.split(",");
- $scope.addLegendColor = function (id) {
- return {"color": legendColors[id]};
- };
- $scope.legendRequired = $attrs.legendRequired;
-
- $scope.addStyle = function (elem) {
- if ($scope.legendRequired && angular.isDefined($attrs.legendPosition)) {
- if ($attrs.legendPosition === "right") {
- if (elem === 'chartLegend')
- {
- return {"float": "left"};
- }
- else
- {
- return {"float": "left"};
- }
- } else {
- if (elem === 'chartLegend')
- {
- return {"float": "left"};
- }
- else
- {
- return {"float": "right"};
- }
- }
- } else {
- return {"float": "left"};
- }
- };
- }
- };
- }])
- .filter('filterData', function () {
- return function (input) {
- return input.replace(/ /g, "").toUpperCase();
- };
- });
-angular.module('att.charts.horseshoeD3', ['att.charts.utilities'])
- .constant("HorseShoeChartD3Config",
- {
- "chartcolor": {
- "paletteColors": ["#1072b8", "#FEFFF7"], //default color options for rendering chart baseColor and NeedleColor,
- "paletteBorderColors": ["#1072b8", "#000"]
- },
- "defaultcenterlabel": "COS 1",
- "defaultcentercategory": "Real Time",
- "animduration": 500,
- "legendreqd": "false",
- "legendposition": "top",
- "centerTextLabelDy": "20"
- })
- .directive('attHorseshoed3Chart', ['HorseShoeChartD3Config', '$timeout','$extendObj', function (HorseShoeChartD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- chartConfig: '=',
- initVal: '=',
- horseShoeId: '@'
- },
- templateUrl: 'template/horseshoeD3/attHorseshoeD3Chart.html',
- transclude: true,
- replace: true,
- controller: ['$scope', '$attrs',function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- HorseShoeChartD3Config = $extendObj.extendDeep(HorseShoeChartD3Config, $scope.chartConfig);
- }
- var legendColor = [];
- legendColor = HorseShoeChartD3Config.chartcolor.paletteColors;
- $scope.addLegendColor = function () {
- return {"color": legendColor[0]};
- };
- if (!angular.isDefined($attrs.legendRequired)) {
- $scope.legendRequired = HorseShoeChartD3Config.legendreqd;
- } else {
- $scope.legendRequired = $attrs.legendRequired;
- }
- if (!angular.isDefined($attrs.legendPosition)) {
- $scope.legendPosition = HorseShoeChartD3Config.legendposition;
- } else {
- $scope.legendPosition = $attrs.legendPosition;
- }
- }],
- link: function (scope, element, attrs) {
- var radius = Math.min(attrs.chartWidth, attrs.chartHeight) / 2;
- scope.LegendLabel = HorseShoeChartD3Config.defaultcenterlabel;
- scope.LegendCategory = HorseShoeChartD3Config.defaultcentercategory;
- var duration = HorseShoeChartD3Config.animduration,
- guageVal = parseInt(scope.initVal.value, 10);
- scope.guageVal = guageVal + "%";
- var dataset = {
- lower: calcPercent(0),
- upper: calcPercent(guageVal)
- },
- pie = d3.layout.pie().sort(null),
- format = d3.format(".0%");
- var arc = d3.svg.arc()
- .innerRadius(radius - 20)
- .outerRadius(radius)
- .startAngle(function (d) {
- return d.startAngle + 2.6 * Math.PI / 2;
- })
- .endAngle(function (d) {
- return d.endAngle + 2.6 * Math.PI / 2;
- });
-
- element[0].querySelector('.horseshoed3Container').setAttribute('id', scope.horseShoeId);
-
- var svg = d3.select(".horseshoed3Container#" + scope.horseShoeId)
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", scope.horseShoeId)
- .attr("width", "100%")
- .attr("height", "100%")
- .attr('viewBox', '0 0 ' + Math.min(attrs.chartWidth, attrs.chartHeight) + ' ' + Math.min(attrs.chartWidth, attrs.chartHeight))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(attrs.chartWidth, attrs.chartHeight) / 2 + "," + Math.min(attrs.chartWidth, attrs.chartHeight) / 2 + ")");
- var path = svg.selectAll("path")
- .data(pie(dataset.lower))
- .enter().append("path")
- .attr("class", function (d, i) {
- return "color" + i;
- })
- .attr("fill", HorseShoeChartD3Config.chartcolor.paletteColors[1])
- .attr("stroke", HorseShoeChartD3Config.chartcolor.paletteBorderColors[1])
- .attr("d", arc)
- .each(function (d) {
- this._current = d;
- }); // store the initial values
- // add center text element
- var centerTextValue = svg.append("text")
- .attr("class", "horseshoecenterValue");
- var centerTextLabel = svg.append("text")
- .attr("y", HorseShoeChartD3Config.centerTextLabelDy)
- .attr("class", "horseshoecenterLabel");
- if (typeof (guageVal) === "string") {
- centerTextValue.text(guageVal);
- centerTextLabel.text(HorseShoeChartD3Config.defaultcenterlabel + "(" + HorseShoeChartD3Config.defaultcentercategory + ")");
- }
- else {
- var progress = 0;
- var timeout = setTimeout(function () {
- clearTimeout(timeout);
- path = path.data(pie(dataset.upper)); // update the data
- path.transition().duration(duration).attrTween("d", function (a, index) {
- angular.element(this)
- .attr("fill", HorseShoeChartD3Config.chartcolor.paletteColors[index])
- .attr("stroke", HorseShoeChartD3Config.chartcolor.paletteBorderColors[index]);
-
- var i = d3.interpolate(this._current, a);
- var i2 = d3.interpolate(progress, guageVal);
- this._current = i(0);
- return function (t) {
- centerTextValue.text(format(i2(t) / 100));
- centerTextLabel.text(HorseShoeChartD3Config.defaultcenterlabel + "(" + HorseShoeChartD3Config.defaultcentercategory + ")");
- return arc(i(t));
- };
- }); // redraw the arcs
-
- }, 200);
- }
- scope.$watch('initVal', function (value) {
- scope.guageVal = value.value + "%";
- path.data(pie(calcPercent(value.value)));
- path.transition().duration(duration).attrTween("d", function (a, index) {
- angular.element(this)
- .attr("fill", HorseShoeChartD3Config.chartcolor.paletteColors[index])
- .attr("stroke", HorseShoeChartD3Config.chartcolor.paletteBorderColors[index]);
-
- var i = d3.interpolate(this._current, a);
- var i2 = d3.interpolate(progress, value.value);
- this._current = i(0);
- return function (t) {
- centerTextValue.text(format(i2(t) / 100));
- centerTextLabel.text(HorseShoeChartD3Config.defaultcenterlabel + "(" + HorseShoeChartD3Config.defaultcentercategory + ")");
- return arc(i(t));
- };
- }); // redraw the arcs
-
- });
- function calcPercent(guageVal) {
- return [guageVal, 100 - guageVal];
- }
-
- }
- };
- }]);
-angular.module('att.charts.radialguageD3', ['att.charts.utilities'])
- .constant("RadialGuageChartD3Config",
- {
- "chartcolor": {
- "MaxBandwidthReached": ["#efefef"],
- "ZeroBandwidthSelected": ["#FEFFF7"],
- "RemainingBandwidthColor": ["#FEFFF7"],
- "RemainingBandwidthStrokeColor": ["#000000"],
- "UsedBandwidthColor": ["#1072b8"],
- "MouseOverArcFillColor": ["#0091d9"],
- "RemainingBandwidthStrokeWidth":1,
- "UsedBandwidthStrokeWidth":1,
- "UsedBandwidthStrokeColor":["#efefef"]
- },
- "defaultcenterlabel": "Kbps",
- "maxAllowedUnitsLabel": "Kbps",
- "zoomLevel": "25",
- "doughnutratio": 20,
- "animduration": "300",
- "guageStartAngle":4,
- "guageEndAngle":8.56,
- "legendreqd": "false",
- "legendposition": "top",
- "centerTextLabelDy": "20",
- "centerTextValueDy": "0",
- "centerTextValueDx": "0",
- "centerTextLabelDx": "0",
- "maxbandwidthTextDx": "65",
- "maxbandwidthTextDy": "100",
- "arcOverMargin": 5
- })
- .directive('attRadialguaged3Chart', ['RadialGuageChartD3Config', '$timeout','$extendObj', function(RadialGuageChartD3Config, $timeout,$extendObj) {
- return {
- restrict: 'A',
- scope: {
- maxValue: '=',
- chartData: '=',
- chartConfig: '=',
- resetChart: '=',
- mouseOver: '=?'
- },
- controller: ['$scope', '$attrs', function($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- RadialGuageChartD3Config = $extendObj.extendDeep(RadialGuageChartD3Config, $scope.chartConfig);
- }
-
- }],
- link: function(scope, element, attrs) {
- var zoom = parseInt(RadialGuageChartD3Config.zoomLevel, 0),
- margin = {// optionally set margins
- top: zoom,
- right: zoom,
- bottom: zoom,
- left: zoom
- },
- width = attrs.chartWidth,
- height = attrs.chartHeight,
- radius = Math.min(
- width - (margin.left + margin.right),
- height - (margin.top + margin.bottom)) / 2;
- // set radius
- var arc = d3.svg.arc()
- .innerRadius(radius - RadialGuageChartD3Config.doughnutratio)
- .outerRadius(radius);
- // set hovered radius
- var arcOver = d3.svg.arc()
- .innerRadius(radius - RadialGuageChartD3Config.doughnutratio)
- .outerRadius(radius + RadialGuageChartD3Config.arcOverMargin);
- // Browser onresize event
- window.onresize = function() {
- scope.$apply();
- };
-
- scope.$watch('mouseOver', function(val) {
- if (!angular.isDefined(scope.mouseOver)) { return; }
- var id = parseInt(scope.mouseOver.split('-')[1], 10);
- if (scope.mouseOver.split('-')[0] === 'true') {
- d3.select('path#radialguagepath-' + (id)).transition()
- .duration(parseInt(RadialGuageChartD3Config.animduration,10))
- .attr('d', arcOver);
-
- } else {
- d3.select('path#radialguagepath-' + (id)).transition()
- .duration(parseInt(RadialGuageChartD3Config.animduration,10))
- .attr('d', arc);
- }
- });
-
- scope.$watch('resetChart', function() {
- if (angular.isDefined(scope.resetChart)) {
- if (angular.isDefined(scope.chartData)) {
- scope.render(scope.chartData, scope.chartData);
- }
- scope.resetChart = false;
- }
- });
- scope.$watch('chartData', function(newValue, oldValue) {
- return scope.render(newValue, oldValue);
- }, true);
- scope.render = function(newValue, oldValue) {
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- if (!scope.chartData)
- {
- return;
- }
- var color, selectedSlider, totalBandwidth = 0, totalUsed = 0, remainingBandwidth = 0;
- if (angular.isDefined(scope.maxValue)) {
- totalBandwidth = parseInt(scope.maxValue, 0);
- }
- angular.forEach(newValue, function(val, key) {
- totalUsed = (totalUsed + parseInt(val.value, 10));
- if (newValue[key].value !== oldValue[key].value) {
- selectedSlider = key;
- }
- });
- var data = angular.copy(scope.chartData);
- if (totalUsed < totalBandwidth) {
- remainingBandwidth = totalBandwidth - parseInt(totalUsed, 0);
- data.push({name: "remaining", value: remainingBandwidth});
- }
- element[0].setAttribute('id', attrs.id);
- var svg = d3.select(element[0])
- .attr("style", "height: " + attrs.chartHeight + "px;")
- .append("svg")
- .attr("id", attrs.id)
- .attr("width", "100%")
- .attr("height", "100%")
- .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
- .attr('preserveAspectRatio', 'xMinYMin')
- .append("g")
- .attr("transform", "translate(" + Math.min(width, height) / 2 + "," + Math.min(width, height) / 2 + ")");
-
- var centerTextValue = svg.append("text")
- .attr("y", RadialGuageChartD3Config.centerTextValueDy)
- .attr("x", RadialGuageChartD3Config.centerTextValueDx)
- .attr("class", "radialguagecenterValue");
- var centerTextLabel = svg.append("text")
- .attr("y", RadialGuageChartD3Config.centerTextLabelDy)
- .attr("x", RadialGuageChartD3Config.centerTextLabelDx)
- .attr("class", "radialguagecenterLabel");
- var maxbandwidthText = svg.append("text")
- .attr("y", RadialGuageChartD3Config.maxbandwidthTextDy)
- .attr("x", RadialGuageChartD3Config.maxbandwidthTextDx)
- .attr("class", "radialmaxbandwidthText");
- if (totalUsed > totalBandwidth) {
- totalUsed = totalBandwidth;
- data = [
- {
- name: "totalUsed",
- value: "100"
- }
- ];
- color = d3.scale.ordinal().range(RadialGuageChartD3Config.chartcolor.MaxBandwidthReached);
- } else if (totalUsed <= 0) {
- data = [
- {
- name: "totalUnUsed",
- value: "100"
- }
- ];
- color = d3.scale.ordinal().range(RadialGuageChartD3Config.chartcolor.ZeroBandwidthSelected);
-
- } else {
- var Colorpalette = [];
- if (newValue === oldValue) {
- data = [
- {
- name: "totalUsed",
- value: totalUsed
- }
- ];
- if (remainingBandwidth > 0) {
- data.push({name: "remaining", value: remainingBandwidth});
- }
- }
- for (var j = 0; j < data.length - 1; j++) {
- Colorpalette[j] = RadialGuageChartD3Config.chartcolor.UsedBandwidthColor;
- }
- if (remainingBandwidth > 0) {
- Colorpalette.push(RadialGuageChartD3Config.chartcolor.RemainingBandwidthColor);
- }
- color = d3.scale.ordinal().range(Colorpalette);
- }
-
- centerTextValue.text(totalUsed);
- centerTextLabel.text(RadialGuageChartD3Config.defaultcenterlabel);
- maxbandwidthText.text(totalBandwidth + " " + RadialGuageChartD3Config.maxAllowedUnitsLabel);
- var pie = d3.layout.pie()
- .sort(null)
- .startAngle(RadialGuageChartD3Config.guageStartAngle)
- .endAngle(RadialGuageChartD3Config.guageEndAngle)
- .value(function(d) {
- return d.value;
- });
-
- var g = svg.selectAll(".arc")
- .data(pie(data))
- .enter()
- .append("g")
- .attr("class", "arc")
- .attr("id", function(d, i) {
- return "radialguagearc-" + i;
- })
- .style("cursor", "pointer");
-
- if (newValue === oldValue) {
- g.append("path")
- .style("fill", function(d) {
- return color(d.data.name);
- })
- .attr("id", function(d, i) {
- return "radialguagepath-" + i;
- })
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
- } else {
- g.append("path")
- .style("fill", function(d) {
- return color(d.data.name);
- })
- .attr("id", function(d, i) {
- return "radialguagepath-" + i;
- })
- .style("stroke", RadialGuageChartD3Config.chartcolor.RemainingBandwidthColor)
- .style("stroke-width", RadialGuageChartD3Config.chartcolor.UsedBandwidthStrokeWidth)
- .transition()
- .ease("exp")
- .duration(0)
- .attrTween("d", tweenPie);
- }
- if (totalUsed === totalBandwidth || remainingBandwidth > 0) {
- var count = data.length - 1;
- d3.select("#" + attrs.id + " path#radialguagepath-" + count).style('stroke', RadialGuageChartD3Config.chartcolor.RemainingBandwidthStrokeColor).style("stroke-width", RadialGuageChartD3Config.chartcolor.RemainingBandwidthStrokeWidth);
- }
- if (angular.isDefined(selectedSlider) && remainingBandwidth > 0) {
-
- d3.select("#" + attrs.id + " path#radialguagepath-" + selectedSlider).transition()
- .duration(RadialGuageChartD3Config.animduration)
- .attr("d", arcOver);
- d3.select("#" + attrs.id + " path#radialguagepath-" + selectedSlider).style('fill', RadialGuageChartD3Config.chartcolor.MouseOverArcFillColor);
- }
- function tweenPie(b) {
- var i = d3.interpolate({
- startAngle: 2.1 * Math.PI,
- endAngle: 2.1 * Math.PI
- }, b);
- return function(t) {
- return arc(i(t));
- };
- }
-
- };
-
-
- }
- };
- }]);
-angular.module('att.charts.stackedBarchart', ['att.charts.utilities'])
- .constant("stackBarChartConfig",
- {
- "chartcolor": ["#B2B2B2", "#00CC00"],
- "gridLineColor": "#CCCCCC",
- "yAxisMaxTicks": 4,
- "chartHeight": "200",
- "chartOpacity": 0.3,
- "amountKDivision": 1000,
- "amountKText": "K",
- "amountMDivision": 1000000,
- "amountMText": "M",
- "yearLabelPos": {"x": 10, "y": 15},
- "tooltipTopMargin": 110,
- "tooltipLeftMargin": 54,
- "margin": {
- top: 20,
- right: 80,
- bottom: 30,
- left: 52
- }
- })
- .directive('stackedBarChart', ['stackBarChartConfig', '$extendObj', '$timeout', function (stackBarChartConfig, $extendObj, $timeout) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- legendRequired: "=",
- refreshChart: "=",
- chartConfig: "="
- },
- templateUrl: "template/stackedBarchart/stackedBarchart.html",
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- if (angular.isDefined($scope.chartConfig)) {
- stackBarChartConfig = $extendObj.extendDeep(stackBarChartConfig, $scope.chartConfig);
- }
- $scope.chartID = $attrs.id;
- $scope.legendColors = stackBarChartConfig.chartcolor;
- $scope.addLegendColor = function (id) {
- var bgColor = null;
- bgColor = {"background-color": $scope.legendColors[id]};
- return bgColor;
- };
- }],
- link: function (scope, element, attrs, ctrl) {
- scope.tooltipFlag = false;
- var dataObj, idx = 0, xAxisTicks, margin = stackBarChartConfig.margin,
- width = parseInt(attrs.chartWidth, 10),
- height = parseInt(stackBarChartConfig.chartHeight, 10),
- padding = 20,
- parseDate = d3.time.format("%d-%b-%Y").parse,
- tooltipFormat = d3.time.format("%B-%Y"),
- labelFormat = d3.time.format("%Y");
- attrs.$observe('legendRequired', function (val) {
- if (val === 'true') {
- scope.showLegend = true;
- }
- else {
- scope.showLegend = false;
- }
- });
- scope.$watch('refreshChart', function (value) {
- if (value === false) {
- return;
- }
-
- if (angular.isDefined(scope.chartConfig)) {
- stackBarChartConfig = $extendObj.extendDeep(stackBarChartConfig, scope.chartConfig);
- }
-
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- d3.selectAll("div#stackBarChartContainer" + " > div").remove();
- if (scope.chartData[0].values.length === 0) {
- scope.refreshChart = false;
- return;
- }
-
- var xMonth = [], yDomainData = [], yAxisData = [], yValue = [], tempData = [], tooltipData = {}, yearArr = {}, isSingleMonth = false;
-
- //X-Axis Range
- var xRange = d3.time.scale().range([padding, width - padding * 2]);
-
- //Y-Axis Range
- var yRange = d3.scale.linear().range([height - padding, padding]);
-
- dataObj = scope.chartData;
-
- dataObj.forEach(function (data) {
- var obj = data.values;
- xAxisTicks = obj.length;
- if (obj.length == 1) {
- isSingleMonth = true;
- }
- obj.forEach(function (d) {
- var tmp = "01-" + d.month;
- d.numericMonth = parseDate(tmp);
- yValue.push({'value': +d.value});
- d.value = +d.value;
- xMonth.push({'numericMonth': d.numericMonth});
- });
- });
-
- //ToolTip Data
- for (var z = 0; z < dataObj.length; z++) {
- var tempSeries = dataObj[z].series;
- for (var j = 0; j < dataObj[z].values.length; j++) {
- var months = dataObj[z].values[j].month;
- var tempVal = dataObj[z].values[j].value;
- var percent = dataObj[z].values[j].percent;
- tempData.push({"month": months, "series": tempSeries, "value": tempVal, "percent": percent});
- }
- }
-
- for (var k = 0; k < tempData.length; k++) {
- var seriesName = tempData[k].series;
- var seriesVal = tempData[k].value;
- var seriesPer = tempData[k].percent;
- var tempObj = tooltipData[tempData[k].month];
- if (!(tempObj)) {
- tempObj = [];
- tooltipData[tempData[k].month] = tempObj;
- tooltipData[tempData[k].month]['seriesPer'] = seriesPer;
- }
- tempObj.push({seriesName: seriesName, seriesVal: seriesVal});
- }
-
- //X-Axis Domain
- xRange.domain(d3.extent(xMonth, function (d) {
- return d.numericMonth;
- }));
-
- for (var b = 0; b < tempData.length; b++) {
- var val = Math.round(parseInt(tempData[b].value, 10) / stackBarChartConfig.yAxisMaxTicks);
- var Calc = Math.ceil((val / Math.pow(10, ("" + val).length - 1))) * (stackBarChartConfig.yAxisMaxTicks) * Math.pow(10, ("" + val).length - 1);
- yDomainData.push({'yAxisVal': Calc});
- }
-
- //Y-Axis Domain
- yRange.domain([0, d3.max(yDomainData, function (d) {
- return (d.yAxisVal);
- })]);
-
- var yTick = d3.max(yDomainData, function (d) {
- return d.yAxisVal;
- });
-
- yTick = yTick / stackBarChartConfig.yAxisMaxTicks;
- for (var x = 0; x <= stackBarChartConfig.yAxisMaxTicks; x++) {
- yAxisData.push(yTick * x);
- }
-
- var formatMoney = function (d) {
- if (d >= stackBarChartConfig.amountMDivision) {
- return d / stackBarChartConfig.amountMDivision + stackBarChartConfig.amountMText;
- } else if (d >= stackBarChartConfig.amountKDivision) {
- return d / stackBarChartConfig.amountKDivision + stackBarChartConfig.amountKText;
- } else {
- return d;
- }
- };
- var xAxis = d3.svg.axis().scale(xRange).orient("bottom").tickFormat(d3.time.format('%b')).ticks(d3.time.months);
- var xAxisGrid = d3.svg.axis().scale(xRange).orient("top").ticks(d3.time.months).tickFormat('').tickSize(-height + 2 * padding, 0);
-
- var yAxis = d3.svg.axis().scale(yRange).orient("left").tickValues(yAxisData).ticks(stackBarChartConfig.yAxisMaxTicks).tickFormat(formatMoney);
- var yAxisGrid = d3.svg.axis().scale(yRange).orient("left").tickValues(yAxisData).ticks(stackBarChartConfig.yAxisMaxTicks).tickSize(-width, 0, 0);
-
-
- //Calculate values for Stack
- var stack = d3.layout.stack()
- .values(function (d) {
- return d.values;
- })
- .x(function (d) {
- return d.numericMonth;
- })
- .y(function (d) {
- return d.value;
- });
-
- //Plot Chart
- var drawBarChart = d3.select("#stackBarChartContainer")
- .append("svg")
- .attr("id", attrs.id)
- .data(dataObj)
- .attr("width", width + margin.left + margin.right)
- .attr("height", parseInt(height, 10) + parseInt(margin.top, 10) + parseInt(margin.bottom, 10))
- .append("g")
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- //Draw X Axis
- drawBarChart.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + (height - padding) + ")")
- .call(xAxis);
-
- if (isSingleMonth) {
- drawBarChart.select(".x").select(".tick").attr("transform", "translate(" + (isSingleMonth === true) * (width / 2 + 20) + ",0)");
- }
-
- //Draw Y Grid Lines
- var yGrid = drawBarChart.append("g")
- .attr("class", "grid").attr("id", "stackBarYGrid")
- .attr("transform", "translate(0,0)")
- .call(yAxisGrid);
- yGrid.selectAll("line").style("stroke", stackBarChartConfig.gridLineColor);
- yGrid.selectAll("text").remove();
-
- //Plot Bars for multiple Stacks
- var barGroup = drawBarChart.selectAll(".group")
- .data(stack(dataObj))
- .enter().append("g")
- .attr("class", "group").attr("id", function (d, i) {
- return ("stackBar" + i);
- })
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)");
-
- barGroup.append("title").text(function (d) {
- return d.series;
- });
-
- var bars = barGroup.selectAll("rect")
- .data(function (d) {
- return d.values;
- })
- .enter().append("rect")
- .attr("class", "bar")
- .attr("x", function (d) {
- return (xRange(d.numericMonth) - 10);
- })
- .attr("y", function (d) {
- return yRange(d.value);
- })
- .attr("width", "20")
- .attr("height", function (d) {
- return ((height - yRange(d.value)) - padding);
- }).on("mouseover", function (d) {
- var offsetX = d3.select(this).attr("x");
- var offsetY = d3.select(this).attr("y");
- show_tooltip_grid_line(offsetX, "x");
- drawBarChart.selectAll(".bar").style("fill-opacity", stackBarChartConfig.chartOpacity);
- d3.select(this).style("fill-opacity", "1");
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("x"), "x");
- scope.tooltipFlag = false;
- drawBarChart.selectAll(".bar").style("fill-opacity", "1");
- scope.$apply();
- });
-
- bars.append('desc').append('title').text(function (d) {
- var nvdaObj = tooltipData[d.month];
- return (addTitle(nvdaObj, d));
- });
-
- //Fill color in Bars
- for (var a = 0; a < dataObj.length; a++) {
- var rectBars = drawBarChart.select('#stackBar' + a).selectAll('rect');
- rectBars.attr('fill', scope.legendColors[a]).attr("fill-opacity", "1");
- }
-
- // Draw the x Grid lines
- var xGrid = drawBarChart.append("g")
- .attr("class", "grid").attr("id", "stackBarXGrid")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .call(xAxisGrid);
-
- xGrid.selectAll("line").attr("transform", "translate(" + -Math.ceil((xRange(2) - xRange(1)) / 2) + "," + padding + ")")
- .attr("id", function (d, i) {
- return ("xGridLine" + i);
- });
-
- //Draw dual Y axis on change of Year
- var yAxisObj = dataObj[0].values, yAxisIdx = 0;
- for (var i = 0; i < yAxisObj.length; i++) {
- var tmpObj = [];
-
- tmpObj.push({"year": labelFormat(yAxisObj[i].numericMonth), "transform": xRange(yAxisObj[i].numericMonth)});
- if (!yearArr[labelFormat(yAxisObj[i].numericMonth)]) {
- yearArr[labelFormat(yAxisObj[i].numericMonth)] = tmpObj;
- }
- }
- for (var key in yearArr) {
- var obj = yearArr[key];
- var yAxisNodes = drawBarChart.append("g")
- .attr("class", "y axis").attr("id", yAxisId(yAxisIdx))
- .attr("transform", "translate(" + (obj[0].transform - padding) + ",0)")
- .call(yAxis);
-
- yAxisNodes.selectAll("text").attr('class', 'ticktext');
-
- //Append Year Label
- yAxisNodes.append("text")
- .attr("transform", "rotate(0)")
- .attr("y", stackBarChartConfig.yearLabelPos.y)
- .attr("x", stackBarChartConfig.yearLabelPos.x)
- .text(obj[0].year).attr("class", "yearLabel");
- yAxisIdx++;
- }
-
- function yAxisId(yAxisIdx) {
- return ("yAxis" + yAxisIdx);
- }
-
- //function to select first element
- d3.selection.prototype.first = function () {
- return d3.select(this[0][0]);
- };
-
- //Remove minimum value label form Y Axis
- var tickLabels = d3.select("#yAxis0").selectAll('.ticktext');
- //tickLabels.first().remove();
- d3.select("#yAxis1").selectAll('.ticktext').remove();
-
- //Add title for NVDA screen reader
- function addTitle(nvdaObj, d) {
- var temp = "";
- for (var y = 0; y < nvdaObj.length; y++) {
- temp = temp + nvdaObj[y].seriesName + nvdaObj[y].seriesVal;
- }
- return (tooltipFormat(d.numericMonth) + "--" + temp + "Retainibility Percentage" + nvdaObj.seriesPer);
- }
-
- //MouseOver Event
- function mouseOver(d, offsetX, offsetY) {
- for (var key in tooltipData) {
- if (key == d.month) {
- scope.stackDataPoint = tooltipData[key];
- break;
- }
- }
- scope.monthPoint = {"xData": tooltipFormat(d.numericMonth).replace('-', ' ')};
- scope.$apply();
- $timeout(function () {
- offsetY = offsetY - stackBarChartConfig.tooltipTopMargin;
- var tooltipEl = element.children().eq(2);
- var tooltipWidth = tooltipEl[0].offsetWidth;
- if (isSingleMonth) {
- offsetX = offsetX - (tooltipWidth / 2) + stackBarChartConfig.tooltipLeftMargin + (width / 2);
- } else {
- offsetX = offsetX - (tooltipWidth / 2) + stackBarChartConfig.tooltipLeftMargin;
- }
- scope.tooltipStyle = {"left": offsetX + "px", "top": offsetY + "px"};
- scope.tooltipFlag = true;
- }, 0);
- }
-
- //Show Grid Line on Over
- function show_tooltip_grid_line(offsetX, attr) {
- var dataLength;
- dataLength = scope.chartData[0].values.length;
- for (var i = 0; i < dataLength; i++) {
- var bar = drawBarChart.selectAll(".bar");
- if (bar[0][i].getAttribute(attr) === offsetX) {
- drawBarChart.select("#xGridLine" + i).style("stroke", stackBarChartConfig.gridLineColor);
- }
- }
- }
-
- //Hide Grid Line
- function hide_tooltip_grid_line(offsetX, attr) {
- var dataLength;
- dataLength = scope.chartData[0].values.length;
- for (var i = 0; i < dataLength; i++) {
- var bar = drawBarChart.selectAll(".bar");
- if (bar[0][i].getAttribute(attr) === offsetX) {
- drawBarChart.select("#xGridLine" + i).style("stroke", "transparent");
- }
- }
- }
- scope.refreshChart = false;
- });
- }
- };
- }])
- .filter('filterInput', function () {
- return function (input) {
- return input.replace(/ +/g, "").toLowerCase();
- };
- });
-angular.module('att.charts.stackedareachart', ['att.charts.utilities'])
- .constant("stackChartConfig",
- {
- "chartcolor": ["#9966FF", "#E68A2E", "#4DDB4D"],
- "gridLineColor": "#808080",
- "lineCurveType": 'linear',
- "yAxisMaxTicks": 4,
- "chartHeight": "200",
- "shapes": ['circle', 'rect', 'triangle'],
- "shapeSize": [3, 5, 6],
- "chartOpacity": 0.6,
- "yearLabelPos": {"x": 8, "y": -5},
- "tooltipTopMargin": 100,
- "tooltipLeftMargin": 42,
- "yAxisUnitRange": 500000,
- "margin": {
- top: 30,
- right: 80,
- bottom: 30,
- left: 52
- }
- })
- .directive('stackedAreaChart', ['stackChartConfig','$extendObj','$timeout', function (stackChartConfig,$extendObj,$timeout) {
- return {
- restrict: 'A',
- scope: {
- chartData: '=',
- legendRequired: "=",
- refreshChart: "=",
- chartConfig: "="
- },
- templateUrl: "template/stackedareachart/stackedAreaChart.html",
- replace: true,
- controller: ['$scope', '$attrs', function ($scope, $attrs) {
- var extendDeep = function extendDeep(dst) {
- angular.forEach(arguments, function(obj) {
- if (obj !== dst) {
- angular.forEach(obj, function(value, key) {
- if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
- extendDeep(dst[key], value);
- } else {
- dst[key] = value;
- }
- });
- }
- });
- return dst;
- };
- if (angular.isDefined($scope.chartConfig)) {
- stackChartConfig = $extendObj.extendDeep(stackChartConfig, $scope.chartConfig);
- }
- $scope.chartID = $attrs.id;
- $scope.legendColors = stackChartConfig.chartcolor;
- $scope.legendTooltipColors = angular.copy(stackChartConfig.chartcolor).reverse();
- $scope.addLegendColor = function (id) {
- var bgColor = null;
- switch (id) {
- case 0:
- bgColor = {"background-color": $scope.legendColors[id], "border-radius": "100%"};
- break;
- case 1:
- bgColor = {"background-color": $scope.legendColors[id]};
- break;
- case 2:
- bgColor = {"width": "0", "height": "0", "border-left": "8px solid transparent", "border-right": "8px solid transparent", "border-bottom-style": "solid", "border-bottom-width": "8px", "border-bottom-color": $scope.legendColors[id]};
- break;
- }
- return bgColor;
- };
- $scope.addToolTipLegendColor = function (id) {
- var bgColor = null;
- switch (id) {
- case 2:
- bgColor = {"background-color": $scope.legendTooltipColors[id], "border-radius": "100%"};
- break;
- case 1:
- bgColor = {"background-color": $scope.legendTooltipColors[id]};
- break;
- case 0:
- bgColor = {"width": "0", "height": "0", "border-left": "6px solid transparent", "border-right": "6px solid transparent", "border-bottom-style": "solid", "border-bottom-width": "12px", "border-bottom-color": $scope.legendTooltipColors[id]};
- break;
- }
- return bgColor;
- };
- }],
- link: function (scope, element, attrs, ctrl) {
- scope.tooltipFlag = false;
- var dataObj, idx = 0, xAxisTicks, margin = stackChartConfig.margin,
- width = parseInt(attrs.chartWidth, 10),
- height = stackChartConfig.chartHeight,
- parseDate = d3.time.format("%d-%b-%Y").parse,
- tooltipFormat = d3.time.format("%B-%Y"),
- labelFormat = d3.time.format("%Y");
- attrs.$observe('legendRequired', function (val) {
- if (val === 'true') {
- scope.showLegend = true;
- }
- else {
- scope.showLegend = false;
- }
- });
- scope.$watch('refreshChart', function (value) {
- if (value === false) {
- return;
- }
- if (angular.isDefined(scope.chartConfig)) {
- stackChartConfig = $extendObj.extendDeep(stackChartConfig, scope.chartConfig);
- }
- d3.select("svg#" + attrs.id).remove();
- d3.selectAll("svg#" + attrs.id + " > *").remove();
- d3.selectAll("div#stackChartContainer" + " > div").remove();
- if (scope.chartData[0].values.length === 0) {
- scope.refreshChart = false;
- return;
- }
-
- var xMonth = [], yValue = [], tempData = [], tooltipData = {}, yearArr = {}, yearLabel = '', isSingleMonth = false, singleMonthName, currencyFormat = 'K';
-
- //X-Axis Range
- var xRange = d3.time.scale()
- .range([0, width]);
-
- //Y-Axis Range
- var yRange = d3.scale.linear()
- .range([height, 0]);
-
- dataObj = scope.chartData;
-
- // On selecting same month in From and To dropdowns, User should be getting graph
- if (dataObj[0].values.length === 1) {
- isSingleMonth = true;
- dataObj.forEach(function (data) {
- var tmp1 = "01-" + data.values[0].month;
- var tmp = parseDate(tmp1);
- singleMonthName = tmp.toString().split(" ")[1];
- tmp.setMonth(tmp.getMonth() + 1);
- var nextMonth = tmp.toString().split(" ")[1] + "-" + tmp.getFullYear();
- data.values.push({month: nextMonth, value: data.values[0].value});
- });
- }
-
- dataObj.forEach(function (data) {
- var obj = data.values;
- xAxisTicks = obj.length;
- obj.forEach(function (d) {
- var tmp = "01-" + d.month;
- d.numericMonth = parseDate(tmp);
- yValue.push({'value': +d.value});
- d.value = +d.value;
- xMonth.push({'numericMonth': d.numericMonth});
- if (d.value > stackChartConfig.yAxisUnitRange) {
- currencyFormat = 'M';
- }
- });
- });
-
- //ToolTip Data
- for (var z = 0; z < dataObj.length; z++) {
- var tempSeries = dataObj[z].series;
- for (var j = 0; j < dataObj[z].values.length; j++) {
- var months = dataObj[z].values[j].month;
- var tempVal = dataObj[z].values[j].value;
- tempData.push({"month": months, "series": tempSeries, "value": tempVal});
- }
- }
- for (var k = 0; k < tempData.length; k++) {
- var seriesName = tempData[k].series;
- var seriesVal = tempData[k].value;
- var tempObj = tooltipData[tempData[k].month];
- if (!(tempObj)) {
- tempObj = [];
- tooltipData[tempData[k].month] = tempObj;
- }
- tempObj.push({seriesName: seriesName, seriesVal: seriesVal});
- }
- for (var d in tooltipData) {
- var tooltipObj = tooltipData[d];
- var temp = 0, monthTotalVal = 0;
- for (var y = 0; y < tooltipObj.length; y++) {
- temp = parseFloat(tooltipObj[y].seriesVal);
- monthTotalVal = monthTotalVal + temp;
- tooltipObj['total'] = monthTotalVal;
- }
- }
- var yDomainData = [],yAxisData = [],yTicksData = [];
- for (var month in tooltipData) {
- yDomainData.push({"total": tooltipData[month].total});
- }
-
- //Format yAxis Labels
- var formatCurrency = function (d) {
- if (currencyFormat === 'M') {
- return "$" + d / 1000000 + "M";
- } else {
- return "$" + d / 1000 + "K";
- }
- };
-
- //X-Axis Domain
- xRange.domain(d3.extent(xMonth, function (d) {
- return d.numericMonth;
- }));
-
- for (var b = 0; b < yDomainData.length; b++) {
- var val = Math.round(parseInt(yDomainData[b].total, 10) / stackChartConfig.yAxisMaxTicks);
- var Calc = Math.ceil((val / Math.pow(10, ("" + val).length - 1))) * (stackChartConfig.yAxisMaxTicks) * Math.pow(10, ("" + val).length - 1);
- yAxisData.push({'yAxisVal': Calc});
- }
-
- //Y-Axis Domain
- yRange.domain([0, d3.max(yAxisData, function (d) {
- return (d.yAxisVal);
- })]);
-
- var yTick = d3.max(yAxisData, function (d) {
- return d.yAxisVal;
- });
-
- yTick = yTick / stackChartConfig.yAxisMaxTicks;
- for (var c = 0; c <= stackChartConfig.yAxisMaxTicks; c++) {
- yTicksData.push(yTick * c);
- }
-
- var xAxis = d3.svg.axis().scale(xRange).orient("bottom").tickFormat(d3.time.format('%b')).ticks(d3.time.months);
- var yAxis = d3.svg.axis().scale(yRange).orient("left").tickValues(yTicksData).ticks(stackChartConfig.yAxisMaxTicks).tickFormat(formatCurrency);
- var yAxisGrid = d3.svg.axis().scale(yRange).orient("left").tickValues(yTicksData).ticks(stackChartConfig.yAxisMaxTicks).tickSize(-width, 0, 0);
-
- //Calculate values for Stack
- var stack = d3.layout.stack()
- .values(function (d) {
- return d.values;
- })
- .x(function (d) {
- return d.numericMonth;
- })
- .y(function (d) {
- return d.value;
- });
-
- //Draw Area
- var area = d3.svg.area()
- .x(function (d) {
- return xRange(d.numericMonth);
- })
- .y0(function (d) {
- return yRange(d.y0);
- })
- .y1(function (d) {
- return yRange(d.y0 + d.y);
- }).interpolate(stackChartConfig.lineCurveType);
-
- //Plot Chart
- var drawChart = d3.select("#stackChartContainer")
- .append("svg")
- .attr("id", attrs.id)
- .data(dataObj)
- .attr("width", width + margin.left + margin.right)
- .attr("height", parseInt(height, 10) + parseInt(margin.top, 10) + parseInt(margin.bottom, 10))
- .append("g")
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- //Draw X Axis
- drawChart.append("g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + height + ")")
- .call(xAxis);
-
- //Plot Area for multiple Stacks
- drawChart.selectAll(".layer")
- .data(stack(dataObj))
- .enter().append("path")
- .attr("class", "layer")
- .attr("d", function (d) {
- return area(d.values);
- }).style("fill", function (d, i) {
- return scope.legendColors[i];
- }).style("opacity", stackChartConfig.chartOpacity).style("stroke", "#ddd").append("title")
- .text(function (d) {
- return d.series;
- });
-
- //Draw dual Y axis on change of Year
- var yAxisObj = dataObj[0].values, yAxisIdx = 0;
- for (var i = 0; i < yAxisObj.length; i++) {
- var tmpObj = [];
- tmpObj.push({"year": labelFormat(yAxisObj[i].numericMonth), "transform": xRange(yAxisObj[i].numericMonth)});
- if (!yearArr[labelFormat(yAxisObj[i].numericMonth)]) {
- yearArr[labelFormat(yAxisObj[i].numericMonth)] = tmpObj;
- }
- }
- for (var key in yearArr) {
- var obj = yearArr[key];
- var yAxisNodes = drawChart.append("g")
- .attr("class", "y axis").attr("id", yAxisId(yAxisIdx))
- .attr("transform", "translate(" + obj[0].transform + ",0)")
- .call(yAxis);
-
- yAxisNodes.selectAll("text").attr('class', 'ticktext');
- //Append Year Label
- yAxisNodes.append("text")
- .attr("transform", "rotate(0)")
- .attr("y", stackChartConfig.yearLabelPos.y)
- .attr("x", stackChartConfig.yearLabelPos.x)
- .text(obj[0].year).attr("class", "yearLabel");
- yAxisIdx++;
- }
-
- //Remove next year Y axis in case of single Month selection
- if (isSingleMonth) {
- d3.select("#yAxisId1").remove();
- }
-
- function yAxisId(yAxisIdx) {
- return ("yAxisId" + yAxisIdx);
- }
-
- //function to select first element
- d3.selection.prototype.first = function () {
- return d3.select(this[0][0]);
- };
-
- //Remove minimum value label form Y Axis
- var tickLabels = d3.select("#yAxisId0").selectAll('.ticktext');
- tickLabels.first().remove();
- d3.select("#yAxisId1").selectAll('.ticktext').remove();
-
- if (isSingleMonth) {
- drawChart.selectAll('.x.axis').selectAll('.tick').selectAll('text')[1][0].textContent = singleMonthName;
- }
-
- //Append Data Points
- for (var x = 0; x < dataObj.length; x++) {
- drawChart.append('g').attr('id', "pathId" + x).attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)");
- if (idx >= stackChartConfig.shapes.length) {
- idx = 0;
- }
- var shape = stackChartConfig.shapes[idx], shapeToAppend;
- if (shape == 'rect' || shape == 'triangle') {
- shapeToAppend = 'polygon';
- }
- else {
- shapeToAppend = 'circle';
- }
-
- var newDataObj;
- if (isSingleMonth) {
- newDataObj = dataObj[x].values.slice(0, 1);
- } else {
- newDataObj = dataObj[x].values;
- }
-
- var dataPoints = drawChart.select('#pathId' + x).selectAll(shapeToAppend)
- .data(newDataObj)
- .enter()
- .append(shapeToAppend)
- .attr('class', shape);
- drawShapes(shape, dataPoints);
- idx++;
- }
-
- //Fill color in dataPoints
- for (var a = 0; a <= dataObj.length; a++) {
- var Dots = drawChart.selectAll('.' + stackChartConfig.shapes[a]);
- Dots.attr('fill', scope.legendColors[a]);
- }
-
- //function to draw multiple shapes for Data Points
- function drawShapes(shape, dataPoints) {
- switch (shape) {
- case 'circle':
- var circle = dataPoints.attr("cx", function (d) {
- return xRange(d.numericMonth);
- }).attr("cy", function (d) {
- return yRange(d.y + d.y0);
- }).attr("r", stackChartConfig.shapeSize[0]).on("mouseover", function (d) {
- show_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- var offsetX = Math.ceil(d3.select(this).attr("cx"));
- var offsetY = Math.round(d3.select(this).attr("cy"));
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", stackChartConfig.chartOpacity);
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("cx"), "circle", "cx");
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", 1);
- scope.tooltipFlag = false;
- scope.$apply();
- });
- circle.append('desc').append('title').text(function (d) {
- var nvdaObj = tooltipData[d.month];
- return (addTitle(nvdaObj, d));
- });
- break;
- case 'rect':
- var rect = dataPoints.attr("points", function (d) {
- var x = parseInt(xRange(d.numericMonth), 10);
- x = x + (stackChartConfig.shapeSize[1] / 2);
- var y = parseInt(yRange(d.y + d.y0), 10);
- y = y - (stackChartConfig.shapeSize[1] / 2);
- var x1 = parseInt((x - stackChartConfig.shapeSize[1]), 10);
- var y1 = y;
- var x2 = x1;
- var y2 = parseInt((y1 + stackChartConfig.shapeSize[1]), 10);
- var x3 = x;
- var y3 = y2;
- var tmp = x2 + "," + y2 + " " + x3 + "," + y3 + " " + x + "," + y + " " + x1 + "," + y1;
- return tmp;
- }).attr('x', function (d) {
- return xRange(d.numericMonth);
- }).attr('y', function (d) {
- return yRange(d.y + d.y0);
- }).on("mouseover", function (d) {
- show_tooltip_grid_line(d3.select(this).attr("x"), "rect", "x");
- var offsetX = Math.ceil(d3.select(this).attr("x"));
- var offsetY = Math.round(d3.select(this).attr("y"));
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", stackChartConfig.chartOpacity);
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("x"), "rect", "x");
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", 1);
- scope.tooltipFlag = false;
- scope.$apply();
- });
- rect.append('desc').append('title').text(function (d) {
- var nvdaObj = tooltipData[d.month];
- return (addTitle(nvdaObj, d));
- });
- break;
- case 'triangle':
- var triangle = dataPoints.attr("points", function (d) {
- var x = parseInt(xRange(d.numericMonth), 10);
- var y = parseInt(yRange(d.y + d.y0), 10);
- var x1 = parseInt((x - stackChartConfig.shapeSize[2]), 10);
- var y1 = parseInt((y - stackChartConfig.shapeSize[2]), 10);
- var x2 = parseInt((x + stackChartConfig.shapeSize[2]), 10);
- var y2 = y1;
- var tmp = x1 + "," + y1 + " " + x + "," + y + " " + x2 + "," + y2;
- return tmp;
- }).attr("transform", function (d) {
- var x = parseInt(xRange(d.numericMonth), 10);
- var y = parseInt(yRange(d.y + d.y0), 10);
- y = y - 2;
- var tmp = "rotate(180," + x + "," + y + ")";
- return tmp;
- }).attr('x', function (d) {
- return xRange(d.numericMonth);
- }).attr('y', function (d) {
- return yRange(d.y + d.y0);
- }).on("mouseover", function (d) {
- show_tooltip_grid_line(d3.select(this).attr("x"), "triangle", "x");
- var offsetX = Math.ceil(d3.select(this).attr("x"));
- var offsetY = Math.round(d3.select(this).attr("y"));
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", stackChartConfig.chartOpacity);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", stackChartConfig.chartOpacity);
- mouseOver(d, offsetX, offsetY);
- }).on("mouseout", function () {
- hide_tooltip_grid_line(d3.select(this).attr("x"), "triangle", "x");
- d3.selectAll('svg#' + attrs.id + " " + "path").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "polygon").style("fill-opacity", 1);
- d3.selectAll('svg#' + attrs.id + " " + "circle").style("fill-opacity", 1);
- scope.tooltipFlag = false;
- scope.$apply();
- });
- triangle.append('desc').append('title').text(function (d) {
- var nvdaObj = tooltipData[d.month];
- return (addTitle(nvdaObj, d));
- });
- break;
- }
- }
-
- //Draw Grid Lines
- drawChart.append("g")
- .attr("class", "grid")
- .attr("id", "yStackGrid")
- .attr("transform", "translate(0,0)")
- .call(yAxisGrid)
- .selectAll("text").remove();
-
- // Draw the x Grid lines
- drawChart.append("g")
- .attr("class", "grid")
- .attr("id", "xGrid")
- .attr("transform", "translate(" + (isSingleMonth === true) * width / 2 + ",0)")
- .call(make_x_axis()
- .tickSize(-height, 0)
- .tickFormat(""));
-
- // function for the x grid lines
- function make_x_axis() {
- return d3.svg.axis()
- .scale(xRange)
- .orient("top")
- .tickFormat(d3.time.format('%b')).ticks(d3.time.months);
- }
-
- drawChart.select("#xGrid").selectAll("line").style("stroke", "none");
- drawChart.select("#xGrid").selectAll("line")
- .attr("id", function (d, i) {
- return ("xAxisLine" + i);
- });
- //Add title for NVDA screen reader
- function addTitle(nvdaObj, d) {
- var temp = "";
- for (var y = 0; y < nvdaObj.length; y++) {
- temp = temp + nvdaObj[y].seriesName + nvdaObj[y].seriesVal;
- }
- return (tooltipFormat(d.numericMonth) + "--" + temp + "Total Charges" + nvdaObj.total);
- }
-
- //Show Grid Lines on Mouse Hover
- function show_tooltip_grid_line(offsetX, shape, attr) {
- try {
- var dataLength;
- if (isSingleMonth) {
- dataLength = 1;
- } else {
- dataLength = scope.chartData[0].values.length;
- }
-
- for (var i = 0; i < dataLength; i++) {
- var circle = drawChart.selectAll("." + shape);
- if (circle[0][i].getAttribute(attr) === offsetX) {
- drawChart.select("#xAxisLine" + i).style("stroke", stackChartConfig.gridLineColor);
- }
- }
- } catch (e) {
- }
- }
-
- //Hide grid Lines
- function hide_tooltip_grid_line(offsetX, shape, attr) {
- try {
- var dataLength;
- if (isSingleMonth) {
- dataLength = 1;
- } else {
- dataLength = scope.chartData[0].values.length;
- }
-
- for (var i = 0; i < dataLength; i++) {
- var circle = drawChart.selectAll("." + shape);
- if (circle[0][i].getAttribute(attr) === offsetX) {
- drawChart.select("#xAxisLine" + i).style("stroke", "transparent");
- }
- }
- } catch (e) {
- }
- }
-
- //MouseOver Event
- function mouseOver(d, offsetX, offsetY) {
- for (var key in tooltipData) {
- if (key == d.month) {
- var data = angular.copy(tooltipData);
- scope.stackDataPoint = data[key].reverse();
- break;
- }
- }
- var tmp = 0, monthTotalVal = 0;
- for (var b = 0; b < scope.stackDataPoint.length; b++) {
- tmp = parseFloat(scope.stackDataPoint[b].seriesVal);
- monthTotalVal = monthTotalVal + tmp;
- }
- scope.total = monthTotalVal;
- scope.stackDataPoint.total = monthTotalVal;
-
- scope.monthPoint = {"xData": tooltipFormat(d.numericMonth).replace('-', ' ')};
- scope.$apply();
- $timeout(function(){
- offsetY = offsetY - stackChartConfig.tooltipTopMargin;
- var tooltipEl = element.children().eq(2);
- var tooltipWidth = tooltipEl[0].offsetWidth;
- if (isSingleMonth) {
- offsetX = offsetX - (tooltipWidth/2) + stackChartConfig.tooltipLeftMargin + (width / 2);
- } else {
- offsetX = offsetX - (tooltipWidth/2) + stackChartConfig.tooltipLeftMargin;
- }
- scope.tooltipStyle = {"left": offsetX + "px", "top": offsetY + "px"};
- scope.tooltipFlag = true;
- },0);
-
-
-
-
- }
- //fix for removing upper text if it is below to year label
-// try {
-// var lastTickPostion = drawChart.selectAll('#yAxisId0').selectAll('.tick')[0].length - 1;
-// var lastGridPos = drawChart.select("#yStackGrid").selectAll('.tick')[0].length - 1;
-// var val = drawChart.selectAll('#yAxisId0').selectAll('.tick')[0][lastTickPostion].attributes.transform.value.split(',')[1].split(')')[0];
-// if (val < 20) {
-// drawChart.selectAll('#yAxisId0').selectAll('text')[0][lastTickPostion - 1].remove();
-// drawChart.select("#yStackGrid").selectAll('.tick')[0][lastGridPos].remove();
-// }
-// } catch (e) {
-// }
- scope.refreshChart = false;
- });
- }
- };
- }])
- .filter('filterInput', function () {
- return function (input) {
- return input.replace(/ +/g, "").toLowerCase();
- };
- });
-angular.module("template/areachartD3/attAreaChartD3.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/areachartD3/attAreaChartD3.html",
- "<div class=\"areaChartD3\">\n" +
- " <ul class=\"legendsList\" ng-show=\"showLegend\">\n" +
- " <li ng-repeat=\"label in legendLabel\" id=\"{{label.series|filterInput}}\">\n" +
- " <i class=\"legend-icon\" ng-style=\"addLegendColor($index)\"></i>{{label.series}}\n" +
- " </li>\n" +
- " </ul>\n" +
- " <div id=\"areaChartContainer\">\n" +
- " </div>\n" +
- " <div ng-class=\"{'tooltip--on': tooltipFlag,'tooltip': !tooltipFlag}\" ng-style=\"tooltipStyle\">\n" +
- " <span class=\"title\">{{dataPoint.xData}}</span>\n" +
- " <p>\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon\" ng-style=\"addLegendColor(1)\"></i>Available</span>\n" +
- " <span class=\"alignRight\">{{dataPoint.dataAvailable}} <span>{{dataPoint.usageDataType}}</span></span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div> \n" +
- " <p>\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon\" ng-style=\"addLegendColor(0)\"></i>Used</span>\n" +
- " <span class=\"alignRight\">{{dataPoint.dataUsed}} <span>{{dataPoint.availableDataType}}</span></span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div>\n" +
- " <p ng-show=\"overageFlag\">\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon\" ng-style=\"addLegendColor(2)\"></i>Overage</span> \n" +
- " <span class=\"alignRight\">{{dataPoint.overage}}</span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div>\n" +
- " <p ng-show=\"underageFlag\">\n" +
- " <span class=\"alignLeft\">Buffer</span> \n" +
- " <span class=\"alignRight\">{{dataPoint.underage}}</span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div>\n" +
- " <span class=\"tooltipArrow\"></span>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/barchartD3/attBarChartD3.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/barchartD3/attBarChartD3.html",
- "<div class=\"barChartD3\">\n" +
- " <div id=\"barChartContainer\">\n" +
- " <span class=\"tooltip\" ng-class=\"{'tooltip--on': tooltipFlag}\" ng-show=\"tooltipFlag\" ng-style=\"tooltipStyle\">\n" +
- " <span class=\"title\">{{dataPoint.name}}</span>\n" +
- " <span><span class=\"alignText\">Wireless number</span><span style=\"float:right\">{{dataPoint.phoneNumber}}</span></span>\n" +
- " <span><span class=\"alignText\">Charges</span><span style=\"float:right\">{{dataPoint.charges}}</span></span>\n" +
- " <span class=\"tooltipArrow\"></span>\n" +
- " </span>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/coschartD3/attCosd3Chart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/coschartD3/attCosd3Chart.html",
- "<div class=\"attCosd3Chart\">\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'top' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-style=\"addLegendColor()\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{LegendLabel}}</span> <span class=\"LegendCategory\">{{LegendCategory}}</span> <span class=\"legendItemValue\">({{cosval}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div id={{chartID}} class=\"cosd3Container\"></div>\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'bottom' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-style=\"addLegendColor()\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{LegendLabel}}</span> <span class=\"LegendCategory\">{{LegendCategory}}</span> <span class=\"legendItemValue\">({{cosval}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/coschartwithbarD3/attCosBarD3Chart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/coschartwithbarD3/attCosBarD3Chart.html",
- "<div class=\"attCosWithBard3Chart\">\n" +
- " <div id={{chartID}} class=\"cosd3Container\"></div>\n" +
- " <div id={{snickrbarId}} class=\"snickrBar\" ng-if=\"barRequired\"></div>\n" +
- "</div>");
-}]);
-
-angular.module("template/cosmultichartD3/attCosmultid3Chart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/cosmultichartD3/attCosmultid3Chart.html",
- "<div class=\"attCosmultid3Chart\">\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'top' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-repeat=\"item in chartData\" ng-style=\"addLegendColor($index,item)\" chart-legend-id=\"{{item.name}}\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{item.name}}</span> <span class=\"LegendCategory\">{{item.category}}</span> <span class=\"legendItemValue\">({{item.value}}%)</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div id={{chartID}} class=\"cosmultid3Container\"></div>\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'bottom' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-repeat=\"item in chartData\" ng-style=\"addLegendColor($index,item)\" chart-legend-id=\"{{item.name}}\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{item.name}}</span> <span class=\"LegendCategory\">{{item.category}}</span> <span class=\"legendItemValue\">({{item.value}}%)</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/donutD3/attDonutd3Chart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/donutD3/attDonutd3Chart.html",
- "<div class=\"attDonutd3Chart\">\n" +
- " <div id={{chartID}} class=\"chartContainer\" ng-class=\"addStyle('chartContainer')\"></div>\n" +
- " <div ng-show=\"legendRequired\" chartLegend class=\"chartLegend\" ng-class=\"addStyle('chartLegend')\">\n" +
- " <ul>\n" +
- " <li ng-repeat=\"item in chartData\" ng-style=\"addLegendColor($index,item)\" chart-legend-id=\"{{item.name|filterData}}\" ng-mouseover=\"legendMouseOver(item,$index,$event)\" ng-mouseleave=\"legendMouseLeave(item,$index,$event)\" ng-class=\"LegendClass\" ng-click=\"legendclickcallback({name:item.name , value:item.value})\">\n" +
- " <div ng-class=\"{'emptyticket-category': item.value ===0}\" >\n" +
- " <span class=\"legendItemName\">{{item.name}}</span> <span class=\"legendItemValue\">({{item.value}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div style=\"clear: both;\"></div>\n" +
- "</div>");
-}]);
-
-angular.module("template/donutFusion/attDonutfusionChart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/donutFusion/attDonutfusionChart.html",
- "<div class=\"attDonutfusionChart\">\n" +
- " <div id=\"donutFusionChart\" chartContainer class=\"chartContainer\" ng-style=\"addStyle('chartContainer')\"></div>\n" +
- " <div ng-show=\"legendRequired\" chartLegend class=\"chartLegend\" ng-style=\"addStyle('chartLegend')\">\n" +
- " <ul>\n" +
- " <li ng-repeat=\"item in chartData\" ng-show=\"item.value > 0\" ng-style=\"addLegendColor($index)\">\n" +
- " <div chart-legend-id=\"{{item.name|filterData}}_fusion\">\n" +
- " <span class=\"legendItemName\">{{item.name}}</span> <span class=\"legendItemValue\">({{item.value}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div style=\"clear: both;\">\n" +
- " </div>\n" +
- "</div> ");
-}]);
-
-angular.module("template/horseshoeD3/attHorseshoeD3Chart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/horseshoeD3/attHorseshoeD3Chart.html",
- "<div class=\"attHorseshoed3Chart\">\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'top' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-style=\"addLegendColor()\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{LegendLabel}}</span> <span class=\"LegendCategory\">{{LegendCategory}}</span> <span class=\"legendItemValue\">({{guageVal}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div class=\"horseshoed3Container\"></div>\n" +
- " <div class=\"chartLegend\" ng-if=\"legendPosition == 'bottom' && legendRequired\">\n" +
- " <ul>\n" +
- " <li ng-style=\"addLegendColor()\">\n" +
- " <div>\n" +
- " <span class=\"LegendLabel\">{{LegendLabel}}</span> <span class=\"LegendCategory\">{{LegendCategory}}</span> <span class=\"legendItemValue\">({{guageVal}})</span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/stackedBarchart/stackedBarchart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/stackedBarchart/stackedBarchart.html",
- "<div class=\"stackedBarChart\">\n" +
- " <ul class=\"legendsList\" ng-show=\"showLegend\">\n" +
- " <li ng-repeat=\"label in chartData\" id=\"{{label.series|filterInput}}\">\n" +
- " <i class=\"legend-icon\" ng-style=\"addLegendColor($index)\"></i>{{label.series}}\n" +
- " </li>\n" +
- " </ul>\n" +
- " <div id=\"stackBarChartContainer\"></div>\n" +
- " <div ng-class=\"{'tooltip--on': tooltipFlag,'tooltip': !tooltipFlag}\" ng-style=\"tooltipStyle\">\n" +
- " <span class=\"title\">{{monthPoint.xData}}</span>\n" +
- " <div ng-repeat=\"label in stackDataPoint\">\n" +
- " <p>\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon-stackedchart\" ng-style=\"addLegendColor($index)\"></i>{{label.seriesName}}</span>\n" +
- " <span class=\"alignRight\">{{label.seriesVal| number:0}}</span>\n" +
- " </p> \n" +
- "\n" +
- " <div style=\"clear:both\"></div>\n" +
- " </div>\n" +
- " <p>\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon-stackedchart\"></i>Retainability percentage</span>\n" +
- " <span class=\"alignRight\">{{stackDataPoint.seriesPer}}</span>\n" +
- "\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div>\n" +
- " <span class=\"tooltipArrow\"></span>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("template/stackedareachart/stackedAreaChart.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("template/stackedareachart/stackedAreaChart.html",
- "<div class=\"stackedAreaChart\">\n" +
- " <ul class=\"legendsList\" ng-show=\"showLegend\">\n" +
- " <li ng-repeat=\"label in chartData\" id=\"{{label.series|filterInput}}\">\n" +
- " <i class=\"legend-icon\" ng-style=\"addLegendColor($index)\"></i>{{label.series}}\n" +
- " </li>\n" +
- " </ul>\n" +
- " <div id=\"stackChartContainer\"></div>\n" +
- " <div ng-class=\"{'tooltip--on': tooltipFlag,'tooltip': !tooltipFlag}\" ng-style=\"tooltipStyle\">\n" +
- " <span class=\"title\">{{monthPoint.xData}}</span>\n" +
- " <div ng-repeat=\"label in stackDataPoint\">\n" +
- " <p>\n" +
- " <span class=\"alignLeft\"><i class=\"legend-icon-stackedchart\" ng-style=\"addToolTipLegendColor($index)\"></i>{{label.seriesName}}</span>\n" +
- " <span class=\"alignRight\">{{label.seriesVal| currency}}</span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div> \n" +
- " </div>\n" +
- " <p>\n" +
- " <span class=\"alignLeft\">Total charges</span>\n" +
- " <span class=\"alignRight\">{{stackDataPoint.total| currency}}</span>\n" +
- " </p>\n" +
- " <div style=\"clear:both\"></div>\n" +
- " <span class=\"tooltipArrow\"></span>\n" +
- " </div>\n" +
- "</div>");
-}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/footer.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/footer.css
deleted file mode 100644
index fcb94c79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/footer.css
+++ /dev/null
@@ -1,311 +0,0 @@
-/* Please include base.less file to make this footer work*/
-/*font family*/
-.footerContainer {
- background: none repeat scroll 0 0 #067AB4;
- width: 100%;
- margin: 0 auto;
- background-color: #067AB4;
- position: relative;
- z-index: 2;
-}
-.footerContainer.stickyFooter {
- position: absolute;
- left: 0;
- right: 0;
-}
-.footerContainer .footerWrapper {
- width: 980px;
- padding-bottom: 25px;
- margin: 0 auto;
- background-color: #067AB4;
-}
-.footerContainer .footerWrapper .footerItem {
- width: 980px;
- height: 60px;
- line-height: 1;
- margin: auto;
- overflow: hidden;
- font-family: clearviewatt;
- font-size: 12px;
- color: #ffffff;
-}
-.footerContainer .footerWrapper .footerItem .divider {
- border-bottom: 1px solid #ffffff;
- margin-top: 10px;
- margin-bottom: 10px;
- width: 100px;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport {
- float: left;
- width: 160px;
- margin-left: 30px;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport .customerHelp {
- font-size: 14px;
- margin-bottom: 20px;
- margin-top: 45px;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport a {
- color: #ffffff !important;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo {
- float: left;
- width: 160px;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo .legal {
- font-size: 14px;
- margin-bottom: 20px;
- margin-top: 45px;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo a {
- color: #ffffff !important;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection {
- float: left;
- width: 295px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeSave {
- font-size: 14px;
- margin-bottom: 20px;
- margin-top: 45px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection {
- margin-top: 15px;
- overflow: hidden;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .emailAddress {
- float: left;
- width: 170px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .emailAddress input {
- background-color: #067AB4;
- color: #FFFFFF !important;
- width: 152px;
- padding: 5px 10px 5px 5px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .subscribeBtn {
- background-color: #FFFFFF;
- border-radius: 1px 5px 5px 1px;
- color: #067AB4;
- cursor: pointer;
- float: left;
- font-size: 14px;
- height: 30px;
- position: relative;
- right: 7px;
- text-align: center;
- top: 1px;
- vertical-align: middle;
- width: 95px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia {
- float: left;
- margin-left: 0px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .followAtt {
- font-size: 14px;
- margin-bottom: 20px;
- margin-top: 45px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds {
- margin-left: -8px;
- margin-top: 20px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span {
- font-size: 30px;
- margin: 0;
- padding: 5px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span a {
- color: #ffffff;
- margin: 0;
- padding: 0;
- /*width: 30px;*/
-
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .dividerBottom {
- border-bottom: 1px solid #ffffff;
- margin: auto;
- width: 920px;
-}
-.footerContainer .footerWrapper .feedbackSection {
- margin: auto;
- width: 920px;
- display: none;
-}
-.footerContainer .footerWrapper .feedbackSection .dividerTop {
- border-bottom: 1px solid #ffffff;
- margin: auto;
- width: 920px;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent {
- margin: 30px auto;
- height: 240px;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent #feedbackForm {
- height: 120px;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackInfo {
- margin-right: 30px;
- width: 270px;
- font-family: clearviewatt;
- font-size: 12px;
- color: #FFFFFF;
- float: left;
- margin-top: -5px;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackTextSection .feedbackText {
- width: 620px;
- height: 170px;
- border: 1px solid #FFFFFF;
- background-color: #067AB4;
- border-radius: 5px;
- font-family: clearviewatt;
- font-size: 14px;
- cursor: text;
- color: #FFFFFF;
- float: left;
- padding: 10px;
- resize: none;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackTextSection .feedbackSubmitButton {
- width: 82px;
- background-color: #FFFFFF;
- margin-left: 16px;
- padding: 5px;
- border-radius: 5px;
- color: #067AB4;
- cursor: pointer;
- font-family: clearviewatt;
- font-size: 14px;
- border: none;
- margin-top: 10px;
- margin-right: 0px;
- float: right;
-}
-.footerContainer .footerWrapper .feedbackResultMsg {
- font-family: clearviewatt;
- font-size: 18px;
- color: #FFFFFF;
- line-height: 70px;
- width: 980px;
- text-align: center;
- margin: 0 auto;
- display: none;
-}
-.footerContainer .footerWrapper .feedbackResultMsg #feedbackMsgCheck {
- margin-right: 20px;
- font-size: 20px;
-}
-.footerContainer .footerWrapper .feedbackResultMsg .feedbackMsgOKButton {
- width: 82px;
- height: 30px;
- line-height: 0px;
- background-color: #FFFFFF;
- margin-left: 16px;
- padding: 5px;
- border-radius: 5px;
- color: #067AB4;
- cursor: pointer;
- font-family: clearviewatt;
- font-size: 14px;
- border: none;
- margin-top: 20px;
- margin-right: 30px;
- float: right;
-}
-.footerContainer .footerWrapper #feedbackResultDivider {
- display: none;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv {
- margin: auto;
- max-width: 110px;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .feedbackButton,
-.footerContainer .footerWrapper .feedbackButtonDiv .closeFeedbackButton {
- background-color: #FFFFFF;
- background: #FFFFFF;
- margin: -1px auto auto;
- padding: 5px 10px;
- border-radius: 0 0 5px 5px;
- color: #067AB4;
- cursor: pointer;
- border: none;
- font-family: clearviewatt;
- font-size: 14px;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .feedbackButton span,
-.footerContainer .footerWrapper .feedbackButtonDiv .closeFeedbackButton span {
- padding-left: 10px;
- background-image: none;
-}
-.footerContainer .footerWrapper .attFooterInfo {
- margin: auto;
- width: 980px;
- overflow: hidden;
- font-family: clearviewatt;
- font-size: 12px;
- color: #ffffff;
-}
-.footerContainer .footerWrapper .attFooterInfo a {
- color: #ffffff;
- margin: 0;
- padding: 0;
- text-decoration: underline;
-}
-.footerContainer .footerWrapper .attFooterInfo .footerLastSection {
- margin-top: 40px;
- width: 980px;
- overflow: hidden;
-}
-.footerContainer .footerWrapper .attFooterInfo span {
- border-right: 1px solid #ffffff;
- padding-left: 3px;
- padding-right: 5px;
-}
-.footerContainer .footerWrapper .attFooterInfo span:last-child {
- border: none;
-}
-.footerContainer .footerWrapper .attFooterInfo .attLogo {
-
- width: 150px;
- height: 77px;
- margin-left: 17px;
- margin-right: 0;
- float: left;
-}
-.footerContainer .footerWrapper .attFooterInfo .attQuality {
- background: url("../images/common/footer/footer-consumerinfo.png") repeat-x scroll 0 0 transparent;
- margin-right: 103px;
- float: left;
- width: 79px;
- height: 82px;
- position: relative;
- top: -5px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise {
- float: right;
- width: 68%;
- margin-right: 30px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy {
- margin-top: 17px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a {
- text-decoration: underline;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a span {
- padding: 0px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a:hover {
- text-decoration: underline;
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/header.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/header.css
deleted file mode 100644
index 6e387806..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/header.css
+++ /dev/null
@@ -1,1866 +0,0 @@
-/* Generated by F12 developer tools. This might not be an accurate representation of the original source file */
-
-.bui-global-btn {
- padding: 8px 20px; border-radius: 6px; border: 0px currentColor; transition:background-color 0.3s ease-out; height: auto; text-align: center; color: rgb(255, 255, 255) !important; line-height: 1; font-size: 14px; text-decoration: none !important; vertical-align: middle; display: inline-block; position: relative; cursor: pointer; box-sizing: border-box; background-color:;
-}
-.bui-global-btn-small {
- height: 30px !important; min-width: 60px;
-}
-.bui-global-btn-primary {
- border-color: rgb(53, 128, 189); color: rgb(255, 255, 255) !important; background-color: rgb(6, 122, 180);
-}
-.bui-global-btn-primary:hover {
- background-color: rgb(25, 157, 223);
-}
-.bui-global-btn-primary:active {
- border-color: rgb(40, 97, 141); background-color: rgb(50, 120, 177);
-}
-.bui-global-btn-hero {
- color: rgb(255, 255, 255); background-color: rgb(239, 111, 0);
-}
-.bui-global-btn-hero:hover {
- background-color: rgb(252, 179, 20);
-}
-.bui-global-btn-hero:active {
- background-color: rgb(255, 114, 0);
-}
-.bui-global-btn-secondary {
- color: rgb(255, 255, 255); background-color: rgb(102, 102, 102);
-}
-.bui-global-btn-secondary:hover {
- background-color: rgb(187, 187, 187);
-}
-.bui-global-btn-secondary:active {
- background-color: rgb(102, 102, 102);
-}
-.bui-global-btn-disabled {
- color: rgb(153, 153, 153) !important; cursor: pointer; background-color: rgb(221, 221, 221);
-}
-.bui-global-btn-disabled:hover {
- background-color: rgb(221, 221, 221);
-}
-.bui-global-btn-disabled:active {
- background-color: rgb(221, 221, 221);
-}
-.bui-global-links {
- transition:0.3s ease-in-out; color: rgb(6, 122, 180); text-decoration: none;
-}
-.bui-global-links:hover {
- color: rgb(25, 157, 223); text-decoration: underline;
-}
-.bui-global-links:active {
- text-decoration: none; coloe: #199ddf;
-}
-.att-global-fonts-common {
- margin: 0px; text-transform: none;
-}
-.att-global-fonts-popup-header {
- margin: 0px; text-transform: none; line-height: 10px; font-family: clearviewatt_ltbold; font-size: 11px; font-weight: 100;
-}
-.att-global-fonts-popup-content {
- margin: 0px; text-transform: none; line-height: 15px; font-family: clearviewattregular; font-size: 14px;
-}
-a.reg-logout-btn {
- padding: 8px 20px; border-radius: 6px; border: currentColor !important; transition:background-color 0.3s ease-out; width: 94px !important; height: auto; text-align: center; color: rgb(255, 255, 255) !important; line-height: 1; font-family: clearviewattregular; font-size: 14px; text-decoration: none !important; vertical-align: middle; display: inline-block; position: relative; cursor: pointer; box-sizing: border-box; background-color: rgb(102, 102, 102); -moz-box-sizing: border-box; valign: middle;
-}
-a.reg-logout-btn:hover {
- background-color: rgb(187, 187, 187);
-}
-a.reg-logout-btn:active {
- background-color: rgb(102, 102, 102);
-}
-ul.reg-Details-table > li {
- line-height: 0px !important;
-}
-ul.reg-Details-table {
- margin: 0px; padding: 0px;
-}
-#reg-header-snippet {
- width: inherit; height: auto; overflow: hidden; clear: both; background-color: rgb(250, 250, 250);
-}
-#reg-header-snippet .reg-profilePicture {
- padding: 20px 20px 17px; width: 109px; margin-bottom: 0px; border-right-color: rgb(211, 211, 211); border-right-width: 1px; border-right-style: solid; float: left; background-color: rgb(250, 250, 250);
-}
-#reg-header-snippet .reg-profilePicture #reg-profileImage {
- width: 100%; clear: both; margin-left: 15px;
-}
-#reg-header-snippet .reg-profilePicture #reg-myprofile-link {
- text-align: left; margin-top: 18px;
-}
-#reg-header-snippet .reg-profilePicture #reg-myprofile-link a {
- transition:0.3s ease-in-out; color: rgb(6, 122, 180); line-height: 15px; padding-left: 21px; font-size: 14px; text-decoration: none;
-}
-#reg-header-snippet .reg-profilePicture #reg-myprofile-link a:hover {
- color: rgb(25, 157, 223); text-decoration: underline;
-}
-#reg-header-snippet .reg-profilePicture #reg-myprofile-link a:active {
- text-decoration: none; coloe: #199ddf;
-}
-#reg-header-snippet .reg-profilePicture #reg-companyProfile-link {
- margin-top: 14px;
-}
-#reg-header-snippet .reg-profilePicture #reg-companyProfile-link a {
- transition:0.3s ease-in-out; color: rgb(6, 122, 180); line-height: 15px; font-size: 14px; text-decoration: none;
-}
-#reg-header-snippet .reg-profilePicture #reg-companyProfile-link a:hover {
- color: rgb(25, 157, 223); text-decoration: underline;
-}
-#reg-header-snippet .reg-profilePicture #reg-companyProfile-link a:active {
- text-decoration: none; coloe: #199ddf;
-}
-#reg-header-snippet .reg-profilePicture #reg-logout-div {
- margin-top: 38px;
-}
-#reg-header-snippet .reg-profilePicture #reg-logout-div form.reg-logoutForm {
- margin: 0px;
-}
-#reg-header-snippet .reg-profileDetails {
- padding: 11px 20px 20px; width: 199px; margin-bottom: 0px; border-bottom-width: 0px; float: left; min-height: 220px; background-color: rgb(255, 255, 255);
-}
-#reg-header-snippet .reg-profileDetails .reg-userName-table {
- height: 70px; display: table; min-height: 70px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userName-table #reg-userName-table-row {
- text-align: left; clear: both; display: table-row; min-height: inherit;
-}
-#reg-header-snippet .reg-profileDetails .reg-userName-table #reg-userName-table-row #reg-userName-table-cell {
- height: inherit; vertical-align: middle; display: table-cell; -ms-word-wrap: break-word; min-height: inherit;
-}
-#reg-header-snippet .reg-profileDetails .reg-userName-table #reg-userName-table-row #reg-userName-table-cell #reg-userName {
- width: 8em; color: rgb(68, 68, 68); overflow: hidden; font-weight: normal; float: left; white-space: normal;
-}
-#reg-header-snippet .reg-profileDetails .reg-userEmail-label {
- text-align: left; clear: both; margin-top: 21px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userEmail-label .reg-userEmail-label-spn {
- margin: 0px; color: rgb(68, 68, 68); text-transform: none; line-height: 10px; font-family: clearviewatt_ltbold; font-size: 11px; font-weight: 100;
-}
-#reg-header-snippet .reg-profileDetails .reg-userEmail-value {
- text-align: left; clear: both; margin-top: 5px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userEmail-value .reg-userEmail-value-spn {
- margin: 0px; color: rgb(102, 102, 102); text-transform: none; line-height: 15px; font-family: clearviewattregular; font-size: 14px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userRole-label {
- text-align: left; clear: both; margin-top: 20px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userRole-label .reg-userRole-label-spn {
- margin: 0px; color: rgb(68, 68, 68); text-transform: none; line-height: 10px; font-family: clearviewatt_ltbold; font-size: 11px; font-weight: 100;
-}
-#reg-header-snippet .reg-profileDetails .reg-userRole-value {
- text-align: left; clear: both; margin-top: 6px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userRole-value .reg-userRole-value-spn {
- margin: 0px; color: rgb(102, 102, 102); text-transform: none; line-height: 15px; font-family: clearviewattregular; font-size: 14px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userCompany-label {
- text-align: left; clear: both; margin-top: 19px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userCompany-label .reg-userCompany-spn {
- margin: 0px; color: rgb(68, 68, 68); text-transform: none; line-height: 10px; font-family: clearviewatt_ltbold; font-size: 11px; font-weight: 100;
-}
-#reg-header-snippet .reg-profileDetails .reg-userCompany-value {
- text-align: left; clear: both; margin-top: 5px;
-}
-#reg-header-snippet .reg-profileDetails .reg-userCompany-value .reg-userCompany-spn {
- margin: 0px; color: rgb(102, 102, 102); text-transform: none; line-height: 15px; font-family: clearviewattregular; font-size: 14px; -ms-word-wrap: break-word;
-}
-.bui-global-transitions-hover {
- border: 1px solid rgb(187, 187, 187); z-index: 90;
-}
-.bui-global-transitions-focus {
- outline: 0px; border: 1px solid rgb(25, 157, 223) !important; z-index: 100; box-shadow: none; -webkit-box-shadow: none;
-}
-.bui-global-transitions-login-page {
- background: 0px 0px rgb(250, 250, 250); border-radius: 3px; border: 1px solid rgb(211, 211, 211); transition:border 0.3s ease-in-out; color: rgb(68, 68, 68); font-family: clearviewattregular; box-shadow: none !important;
-}
-.bui-global-transitions-login-page:hover {
- border: 1px solid rgb(187, 187, 187); z-index: 90;
-}
-.bui-global-transitions-login-page:focus {
- outline: 0px; border: 1px solid rgb(25, 157, 223) !important; z-index: 100; box-shadow: none; -webkit-box-shadow: none;
-}
-li#anchor ul.column {
- display: none;
-}
-li#anchor:hover ul.column {
- display: block;
-}
-.login-icon {
- width: 27px; height: 27px; vertical-align: middle; display: inline-block; background-image: url("../images/common/header/login-icon.png"); background-repeat: no-repeat;
-}
-.bui-reg-one-line-layout * {
- display: inline-block;
-}
-.popbox {
- margin: 0px auto; text-align: center; position: relative;
-}
-.collapse {
- position: relative;
-}
-.box {
- background: rgb(255, 255, 255); border: 1px solid rgb(187, 187, 187); width: auto; height: auto; display: none; position: relative; z-index: 0; min-width: 260px;
-}
-.box * {
- box-sizing: content-box; -webkit-box-sizing: content-box; -moz-box-sizing: content-box;
-}
-.box ::after {
- box-sizing: content-box; -webkit-box-sizing: content-box; -moz-box-sizing: content-box;
-}
-.box ::before {
- box-sizing: content-box; -webkit-box-sizing: content-box; -moz-box-sizing: content-box;
-}
-.box a.close {
- color: red; font-family: arial; font-size: 12px; text-decoration: underline;
-}
-.box .arrow {
- left: 1px; top: -8px; width: 0px; height: 0px; border-right-color: transparent; border-bottom-color: rgb(255, 255, 255); border-left-color: transparent; border-right-width: 8px; border-bottom-width: 8px; border-left-width: 8px; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; position: absolute; z-index: 1001;
-}
-.standard-input-error-msg-class {
- background: url("../images/common/header/exclamation-error.png") no-repeat 337px rgb(231, 229, 230) !important;
-}
-.box-form {
- padding-top: 10px; padding-bottom: 0px; padding-left: 16px;
-}
-.control-text-popup {
- border-radius: 3px 3px 0px 0px !important; width: 200px !important;
-}
-.control-label-password {
- line-height: 10px !important; padding-top: 3px !important;
-}
-.control-label-checkbox {
- line-height: 15px; padding-top: 5px;
-}
-.placeholder-class {
- color: rgb(139, 139, 139) !important;
-}
-.forgot-userid-password {
- font-size: 10px !important; font-weight: normal !important;
-}
-.header-login-label {
- color: rgb(255, 255, 255); font-size: 13px; maxlength: 10;
-}
-.ellipsis-header-name {
- overflow: hidden; padding-top: 0px; margin-top: 0px; white-space: nowrap; -ms-text-overflow: ellipsis; max-width: 100px; ms-text-overflow: ellipsis;
-}
-#generic-image {
- padding: 100px; background-image: url("../images/common/header/placerimage.jpg"); background-repeat: no-repeat;
-}
-.bui-reg-horizontal-rule {
- width: 100%; height: 1.25px; clear: both; background-color: rgb(231, 230, 230);
-}
-.bui-reg-horizontal-rule-margin {
- margin-top: 20px; margin-bottom: 20px;
-}
-.password-horizontal-rule-margin {
- margin-top: 5px; margin-bottom: 5px;
-}
-.requiredInformation {
- font-size: 11px;
-}
-.header-login-window {
- height: 100px;
-}
-.header-login-window-image {
- padding: 18px;
-}
-.header-login-window-name {
- line-height: 1.5em; overflow: hidden; padding-top: 18px; padding-right: 18px; font-family: clearviewatt_ltbold; font-size: 16px;
-}
-.header-login-window-role {
- font-family: clearviewattregular; font-size: 12px;
-}
-.header-login-window-logout {
- background: rgb(231, 229, 230); height: 27px; line-height: 27px; font-family: clearviewatt_ltbold; font-size: 11px; z-index: 10001;
-}
-.header-login-window-logout a {
- color: rgb(103, 103, 103);
-}
-.header-login-name {
- width: auto; line-height: 50px; padding-right: 23px; padding-left: 3px; float: left; cursor: pointer;
-}
-.error-msg-box {
- border-radius: 3px; width: 200px; height: 35px; color: rgb(255, 255, 255); line-height: 35px; font-size: 12px; margin-top: 15px; margin-left: 30px; background-color: rgb(255, 69, 57);
-}
-.header_login_field_border_error {
- background: url("../images/common/header/icon-error.png") no-repeat 118px rgb(255, 255, 255) !important; border: 1px solid rgb(255, 69, 57) !important; z-index: 100;
-}
-.header_login_field_border_error:hover {
- border: 1px solid rgb(255, 69, 57) !important;
-}
-.header_login_field_3sides_error {
- background: url("../images/common/header/icon-error.png") no-repeat 118px rgb(255, 255, 255) !important; border-right-color: rgb(255, 69, 57) !important; border-bottom-color: rgb(255, 69, 57) !important; border-left-color: rgb(255, 69, 57) !important; border-right-width: 1px !important; border-bottom-width: 1px !important; border-left-width: 1px !important; border-right-style: solid !important; border-bottom-style: solid !important; border-left-style: solid !important;
-}
-.header_login_field_3sides_error:hover {
- border: 1px solid rgb(255, 69, 57) !important;
-}
-.header_login_field_wrapper_border_error {
- background: url("../images/common/header/icon-error.png") no-repeat 118px rgb(255, 255, 255) !important;
-}
-.error-msg-class {
- background: url("../images/common/header/exclamation-error.png") no-repeat 178px rgb(255, 255, 255) !important; border-color: rgb(177, 11, 59) !important; color: rgb(179, 10, 60) !important; font-size: 10px; box-shadow: inset 0px 0px 3px #b10b3b, 0px 0px 3px #b10b3b !important;
-}
-.regFormInputLoginText {
- background: no-repeat 100% -22px rgb(250, 250, 250); padding: 10px; width: 200px; height: 20px; color: rgb(68, 68, 68); font-size: 12px; display: block;
-}
-.regFormInputLoginPassword {
- background: no-repeat 100% -22px rgb(250, 250, 250); padding: 10px; width: 200px; height: 20px; color: rgb(68, 68, 68); font-size: 12px; display: block;
-}
-.header-login-button {
- height: 20px; min-width: 10px !important; box-shadow: none;
-}
-#headerLoginFormID #header_login_title {
- color: rgb(68, 68, 68); font-family: clearviewattregular; font-size: 14px; margin-top: 25px;
-}
-#headerLoginFormID #header_login_id {
- background: url("../images/common/header/icon-username.png") no-repeat 10px rgb(250, 250, 250) !important; padding: 10px 10px 10px 36px; border-radius: 3px 3px 0px 0px !important; border: 1px solid rgb(211, 211, 211); transition:border 0.3s ease-in-out; width: 200px; height: 32px; color: rgb(68, 68, 68); font-family: clearviewattregular; font-size: 12px; margin-top: 15px; margin-bottom: 10px !important; margin-left: 30px; display: block; box-shadow: none !important;
-}
-#headerLoginFormID #header_login_id:hover {
- border: 1px solid rgb(187, 187, 187); z-index: 90;
-}
-#headerLoginFormID #header_login_id:focus {
- outline: 0px; border: 1px solid rgb(25, 157, 223) !important; z-index: 100; box-shadow: none; -webkit-box-shadow: none;
-}
-#headerLoginFormID #header_password {
- background: url("../images/common/header/icon-password.png") no-repeat 10px rgb(250, 250, 250) !important; padding: 10px 10px 10px 36px; border-radius: 0px 0px 3px 3px !important; border: 1px solid rgb(211, 211, 211); transition:border 0.3s ease-in-out; width: 200px; height: 32px; color: rgb(68, 68, 68); font-family: clearviewattregular; font-size: 12px; margin-top: -11px; margin-bottom: 0px; margin-left: 30px; display: block; box-shadow: none !important;
-}
-#headerLoginFormID #header_password:hover {
- border: 1px solid rgb(187, 187, 187); z-index: 90;
-}
-#headerLoginFormID #header_password:focus {
- outline: 0px; border: 1px solid rgb(25, 157, 223) !important; z-index: 100; box-shadow: none; -webkit-box-shadow: none;
-}
-#headerLoginFormID #header_login_block {
- height: 30px; margin-top: 15px;
-}
-#headerLoginFormID #header_login_block #header_login_button {
- padding: 8px 20px; border-radius: 6px; border: 0px rgb(53, 128, 189); transition:background-color 0.3s ease-out; width: 80px; height: 30px !important; text-align: center; color: rgb(255, 255, 255) !important; line-height: 1; font-size: 14px; text-decoration: none !important; margin-left: 25px; vertical-align: middle; float: left; display: inline-block; position: relative; cursor: pointer; min-width: 60px; box-sizing: border-box; background-color: rgb(6, 122, 180); -moz-box-sizing: border-box; valign: middle;
-}
-#headerLoginFormID #header_login_block #header_login_button:hover {
- background-color: rgb(25, 157, 223);
-}
-#headerLoginFormID #header_login_block #header_login_button:active {
- border-color: rgb(40, 97, 141); background-color: rgb(50, 120, 177);
-}
-#headerLoginFormID #remember_me_component {
- padding-left: 30px; margin-top: 11px;
-}
-#headerLoginFormID #remember_me_component #rememberme_header_label {
- margin-top: 4px;
-}
-#headerLoginFormID #remember_me_component #remember-me {
- color: rgb(102, 102, 102); font-family: clearviewattregular; font-size: 12px; font-weight: normal;
-}
-#headerLoginFormID #forgot_username_component {
- text-align: left; padding-top: 30px; padding-bottom: 30px; padding-left: 30px; clear: both;
-}
-#headerLoginFormID #forgot_username_component .regular {
- color: rgb(68, 68, 68); font-family: clearviewattregular; font-size: 12px;
-}
-#headerLoginFormID #forgot_username_component .link {
- color: rgb(6, 122, 180); font-family: clearviewattregular; font-size: 12px;
-}
-.footerContainer {
- background: 0px 0px rgb(6, 122, 180); margin: 0px auto; width: 100%;
-}
-.footerContainer .footerWrapper {
- margin: 0px auto; width: 100%; padding-bottom: 25px; background-color: rgb(6, 122, 180);
-}
-.footerContainer .footerWrapper .footerItem {
- margin: auto; width: 100%; height: 60px; color: rgb(255, 255, 255); line-height: 1; overflow: hidden; font-family: clearview_att_regular; font-size: 12px;
-}
-.footerContainer .footerWrapper .footerItem .divider {
- width: 100px; margin-top: 10px; margin-bottom: 10px; border-bottom-color: rgb(255, 255, 255); border-bottom-width: 1px; border-bottom-style: solid;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport {
- width: 160px; margin-left: 30px; float: left;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport .customerHelp {
- font-size: 14px; margin-top: 45px; margin-bottom: 20px;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport a {
- color: rgb(255, 255, 255) !important;
-}
-.footerContainer .footerWrapper .footerItem .customerSupport a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo {
- width: 160px; float: left;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo .legal {
- font-size: 14px; margin-top: 45px; margin-bottom: 20px;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo a {
- color: rgb(255, 255, 255) !important;
-}
-.footerContainer .footerWrapper .footerItem .legalInfo a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection {
- width: 295px; float: left;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeSave {
- font-size: 14px; margin-top: 45px; margin-bottom: 20px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection {
- overflow: hidden; margin-top: 15px;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .emailAddress {
- width: 170px; float: left;
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .emailAddress input {
- padding: 5px 10px 5px 5px; width: 152px; color: rgb(255, 255, 255) !important; background-color: rgb(6, 122, 180);
-}
-.footerContainer .footerWrapper .footerItem .subscribeSection .subscribeToSection .subscribeBtn {
- border-radius: 1px 5px 5px 1px; top: 1px; width: 95px; height: 30px; text-align: center; right: 7px; color: rgb(6, 122, 180); font-size: 14px; vertical-align: middle; float: left; position: relative; cursor: pointer; background-color: rgb(255, 255, 255);
-}
-.footerContainer .footerWrapper .footerItem .socialMedia {
- margin-left: 0px; float: left;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .followAtt {
- font-size: 14px; margin-top: 45px; margin-bottom: 20px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds {
- margin-top: 20px; margin-left: -8px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span {
- margin: 0px; padding: 5px; font-size: 30px;
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span a {
- margin: 0px; padding: 0px; color: rgb(255, 255, 255);
-}
-.footerContainer .footerWrapper .footerItem .socialMedia .socialFeeds span a:hover {
- text-decoration: none;
-}
-.footerContainer .footerWrapper .dividerBottom {
- margin: auto; width: 920px; border-bottom-color: rgb(255, 255, 255); border-bottom-width: 1px; border-bottom-style: solid;
-}
-.footerContainer .footerWrapper .feedbackSection {
- margin: auto; width: 920px; display: none;
-}
-.footerContainer .footerWrapper .feedbackSection .dividerTop {
- margin: auto; width: 920px; border-bottom-color: rgb(255, 255, 255); border-bottom-width: 1px; border-bottom-style: solid;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent {
- margin: 30px auto;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent #feedbackForm {
- height: 120px;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackInfo {
- width: 270px; color: rgb(255, 255, 255); font-family: clearview_att_regular; font-size: 12px; margin-top: -5px; margin-right: 30px; float: left;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackTextSection .feedbackText {
- padding: 10px; border-radius: 5px; border: 1px solid rgb(255, 255, 255); width: 500px; height: 100px; color: rgb(255, 255, 255); font-family: clearview_att_regular; font-size: 14px; float: left; cursor: text; background-color: rgb(6, 122, 180); resize: none;
-}
-.footerContainer .footerWrapper .feedbackSection .feedbackContent .feedbackTextSection .feedbackSubmitButton {
- padding: 5px; border-radius: 5px; border: currentColor; width: 82px; color: rgb(6, 122, 180); font-family: clearview_att_regular; font-size: 14px; margin-top: 92px; margin-left: 16px; cursor: pointer; background-color: rgb(255, 255, 255);
-}
-.footerContainer .footerWrapper .feedbackResultMsg {
- margin: 0px auto; width: 100%; text-align: center; color: rgb(255, 255, 255); line-height: 70px; font-family: clearview_att_regular; font-size: 18px; display: none;
-}
-.footerContainer .footerWrapper .feedbackResultMsg #feedbackMsgCheck {
- font-size: 20px; margin-right: 20px;
-}
-.footerContainer .footerWrapper #feedbackResultDivider {
- display: none;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv {
- margin: auto; max-width: 110px;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .feedbackButton {
- background: rgb(255, 255, 255); margin: -1px auto auto; padding: 5px 10px; border-radius: 0px 0px 5px 5px; border: currentColor; color: rgb(6, 122, 180); font-family: clearview_att_regular; font-size: 14px; cursor: pointer;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .closeFeedbackButton {
- background: rgb(255, 255, 255); margin: -1px auto auto; padding: 5px 10px; border-radius: 0px 0px 5px 5px; border: currentColor; color: rgb(6, 122, 180); font-family: clearview_att_regular; font-size: 14px; cursor: pointer;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .feedbackButton span {
- padding-left: 10px; background-image: none;
-}
-.footerContainer .footerWrapper .feedbackButtonDiv .closeFeedbackButton span {
- padding-left: 10px; background-image: none;
-}
-.footerContainer .footerWrapper .attFooterInfo {
- margin: auto; width: 100%; color: rgb(255, 255, 255); overflow: hidden; font-family: clearview_att_regular; font-size: 12px;
-}
-.footerContainer .footerWrapper .attFooterInfo a {
- margin: 0px; padding: 0px; color: rgb(255, 255, 255); text-decoration: underline;
-}
-.footerContainer .footerWrapper .attFooterInfo .footerLastSection {
- overflow: hidden; margin-top: 40px;
-}
-.footerContainer .footerWrapper .attFooterInfo span {
- padding-right: 5px; padding-left: 3px; border-right-color: rgb(255, 255, 255); border-right-width: 1px; border-right-style: solid;
-}
-.footerContainer .footerWrapper .attFooterInfo span:last-child {
- border: currentColor;
-}
-.footerContainer .footerWrapper .attFooterInfo .attLogo {
- width: 150px; height: 77px; margin-right: 0px; margin-left: 17px; float: left;
-}
-.footerContainer .footerWrapper .attFooterInfo .attQuality {
- background: url("../images/common/footer/footer-consumerinfo.png") repeat-x 0px 0px; top: -5px; width: 79px; height: 82px; margin-right: 103px; float: left; position: relative;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise {
- width: 64%; float: right;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy {
- margin-top: 17px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a {
- text-decoration: underline;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a span {
- padding: 0px;
-}
-.footerContainer .footerWrapper .attFooterInfo .attAdvertise .privacyPolicy a:hover {
- text-decoration: underline;
-}
-[data-icon]::before {
- text-transform: none; line-height: 1; font-family: "atticons"; font-variant: normal; font-weight: normal; content: attr(data-icon); speak: none; -webkit-font-smoothing: antialiased;
-}
-[class^='icon-'] {
- text-transform: none; line-height: 1; font-family: "atticons"; font-style: normal; font-variant: normal; font-weight: normal; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
-}
-[class*=' icon-'] {
- text-transform: none; line-height: 1; font-family: "atticons"; font-style: normal; font-variant: normal; font-weight: normal; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
-}
-.icon-wireless-outline::before {
- content: "\e600";
-}
-.icon-wireless-dashboard::before {
- content: "\e601";
-}
-.icon-website-hosting-outline::before {
- content: "\e602";
-}
-.icon-volume-up::before {
- content: "\e603";
-}
-.icon-volume-mute::before {
- content: "\e604";
-}
-.icon-volume-down::before {
- content: "\e605";
-}
-.icon-video::before {
- content: "\e606";
-}
-.icon-video-tutorials::before {
- content: "\e607";
-}
-.icon-video-tutorials-outline::before {
- content: "\e608";
-}
-.icon-video-outline::before {
- content: "\e609";
-}
-.icon-user::before {
- content: "\e60a";
-}
-.icon-user-small::before {
- content: "\e60b";
-}
-.icon-user-outline::before {
- content: "\e60c";
-}
-.icon-user-large-outline::before {
- content: "\e60d";
-}
-.icon-upgrades::before {
- content: "\e60e";
-}
-.icon-upgrades-outline::before {
- content: "\e60f";
-}
-.icon-unlimited-nights-weekends-outline::before {
- content: "\e610";
-}
-.icon-unlimited-minutes-outline::before {
- content: "\e611";
-}
-.icon-unlimited-messaging-outline::before {
- content: "\e612";
-}
-.icon-unlimited-m2m-outline::before {
- content: "\e613";
-}
-.icon-unlimited-calling::before {
- content: "\e614";
-}
-.icon-tv-packages-outline::before {
- content: "\e615";
-}
-.icon-travel-minutes-outline::before {
- content: "\e616";
-}
-.icon-trash::before {
- content: "\e617";
-}
-.icon-tollfree-outline::before {
- content: "\e618";
-}
-.icon-tiles::before {
- content: "\e619";
-}
-.icon-tiles-small::before {
- content: "\e61a";
-}
-.icon-tickets::before {
- content: "\e61b";
-}
-.icon-tickets-returned::before {
- content: "\e61c";
-}
-.icon-tickets-referred::before {
- content: "\e61d";
-}
-.icon-tickets-outline::before {
- content: "\e61e";
-}
-.icon-tickets-open::before {
- content: "\e61f";
-}
-.icon-tickets-escalate::before {
- content: "\e620";
-}
-.icon-tickets-contested::before {
- content: "\e621";
-}
-.icon-tickets-closed::before {
- content: "\e622";
-}
-.icon-tickets-cleared::before {
- content: "\e623";
-}
-.icon-tickets-arquived::before {
- content: "\e624";
-}
-.icon-tickets-active::before {
- content: "\e625";
-}
-.icon-technical-specifications::before {
- content: "\e626";
-}
-.icon-tech-support::before {
- content: "\e627";
-}
-.icon-tech-support-outline::before {
- content: "\e628";
-}
-.icon-tablet::before {
- content: "\e629";
-}
-.icon-tablet-outline::before {
- content: "\e62a";
-}
-.icon-support::before {
- content: "\e62b";
-}
-.icon-support-outline::before {
- content: "\e62c";
-}
-.icon-star::before {
- content: "\e62d";
-}
-.icon-sort::before {
- content: "\e62e";
-}
-.icon-social-outline::before {
- content: "\e62f";
-}
-.icon-smartphone::before {
- content: "\e630";
-}
-.icon-smartphone-outline::before {
- content: "\e631";
-}
-.icon-signout-outline::before {
- content: "\e632";
-}
-.icon-sign-out::before {
- content: "\e633";
-}
-.icon-shop::before {
- content: "\e634";
-}
-.icon-shop-outline::before {
- content: "\e635";
-}
-.icon-shared-outline::before {
- content: "\e636";
-}
-.icon-shared-minutes-outline::before {
- content: "\e637";
-}
-.icon-share::before {
- content: "\e638";
-}
-.icon-settings::before {
- content: "\e639";
-}
-.icon-send-invoice-outline::before {
- content: "\e63a";
-}
-.icon-see-more::before {
- content: "\e63b";
-}
-.icon-see-less::before {
- content: "\e63c";
-}
-.icon-search::before {
- content: "\e63d";
-}
-.icon-search-small::before {
- content: "\e63e";
-}
-.icon-screen-calls-outline::before {
- content: "\e63f";
-}
-.icon-save-time-outline::before {
- content: "\e640";
-}
-.icon-saas-enablement-outline::before {
- content: "\e641";
-}
-.icon-s-beam::before {
- content: "\e642";
-}
-.icon-s-beam-outline::before {
- content: "\e643";
-}
-.icon-rollover-outline::before {
- content: "\e644";
-}
-.icon-rollover-minutes::before {
- content: "\e645";
-}
-.icon-reviews-outline::before {
- content: "\e646";
-}
-.icon-reports::before {
- content: "\e647";
-}
-.icon-reports-outline::before {
- content: "\e648";
-}
-.icon-recommendation-tool::before {
- content: "\e649";
-}
-.icon-receivers-outline::before {
- content: "\e64a";
-}
-.icon-productivity-outline::before {
- content: "\e64b";
-}
-.icon-print::before {
- content: "\e64c";
-}
-.icon-plus::before {
- content: "\e64d";
-}
-.icon-plus-outline::before {
- content: "\e64e";
-}
-.icon-play::before {
- content: "\e64f";
-}
-.icon-platform-as-service-outline::before {
- content: "\e650";
-}
-.icon-plans::before {
- content: "\e651";
-}
-.icon-plans-outline::before {
- content: "\e652";
-}
-.icon-pie-chart::before {
- content: "\e653";
-}
-.icon-photos::before {
- content: "\e654";
-}
-.icon-photos-outline::before {
- content: "\e655";
-}
-.icon-phone-data-outline::before {
- content: "\e656";
-}
-.icon-payments::before {
- content: "\e657";
-}
-.icon-payments-outline::before {
- content: "\e658";
-}
-.icon-pause::before {
- content: "\e659";
-}
-.icon-password::before {
- content: "\e65a";
-}
-.icon-password-outline::before {
- content: "\e65b";
-}
-.icon-overview::before {
- content: "\e65c";
-}
-.icon-overview-small::before {
- content: "\e65d";
-}
-.icon-overages::before {
- content: "\e65e";
-}
-.icon-overages-outline::before {
- content: "\e65f";
-}
-.icon-outage-outline::before {
- content: "\e660";
-}
-.icon-orders::before {
- content: "\e661";
-}
-.icon-orders-outline::before {
- content: "\e662";
-}
-.icon-optional-applications-outline::before {
- content: "\e663";
-}
-.icon-office-at-hand-outline::before {
- content: "\e664";
-}
-.icon-offers::before {
- content: "\e665";
-}
-.icon-offers-outline::before {
- content: "\e666";
-}
-.icon-notifications::before {
- content: "\e667";
-}
-.icon-notifications-outline::before {
- content: "\e668";
-}
-.icon-normal-screen::before {
- content: "\e669";
-}
-.icon-nights-weekends-outline::before {
- content: "\e66a";
-}
-.icon-new-requests-outline::before {
- content: "\e66b";
-}
-.icon-network::before {
- content: "\e66c";
-}
-.icon-network-dashboard::before {
- content: "\e66d";
-}
-.icon-netbook::before {
- content: "\e66e";
-}
-.icon-netbook-outline::before {
- content: "\e66f";
-}
-.icon-music::before {
- content: "\e670";
-}
-.icon-music-video::before {
- content: "\e671";
-}
-.icon-music-video-outline::before {
- content: "\e672";
-}
-.icon-music-outline::before {
- content: "\e673";
-}
-.icon-modem::before {
- content: "\e674";
-}
-.icon-modem-outline::before {
- content: "\e675";
-}
-.icon-mobile-insurance::before {
- content: "\e676";
-}
-.icon-mobile-insurance-outline::before {
- content: "\e677";
-}
-.icon-mobile-2-mobile-outline::before {
- content: "\e678";
-}
-.icon-missed-calls-outline::before {
- content: "\e679";
-}
-.icon-minutes::before {
- content: "\e67a";
-}
-.icon-minutes-outline::before {
- content: "\e67b";
-}
-.icon-messaging::before {
- content: "\e67c";
-}
-.icon-messaging-toolkit-outline::before {
- content: "\e67d";
-}
-.icon-messaging-outline::before {
- content: "\e67e";
-}
-.icon-messaging-email::before {
- content: "\e67f";
-}
-.icon-messaging-email-outline::before {
- content: "\e680";
-}
-.icon-message-small::before {
- content: "\e681";
-}
-.icon-maintenance::before {
- content: "\e682";
-}
-.icon-location-pin::before {
- content: "\e683";
-}
-.icon-location-pin-small::before {
- content: "\e684";
-}
-.icon-local-search::before {
- content: "\e685";
-}
-.icon-local-long-distance-outline::before {
- content: "\e686";
-}
-.icon-list::before {
- content: "\e687";
-}
-.icon-learn::before {
- content: "\e688";
-}
-.icon-learn-outline::before {
- content: "\e689";
-}
-.icon-laptop::before {
- content: "\e68a";
-}
-.icon-landline::before {
- content: "\e68b";
-}
-.icon-landline-outline::before {
- content: "\e68c";
-}
-.icon-invoices::before {
- content: "\e68d";
-}
-.icon-invoices-outline::before {
- content: "\e68e";
-}
-.icon-inventory::before {
- content: "\e68f";
-}
-.icon-intranet-outline::before {
- content: "\e690";
-}
-.icon-interpreter::before {
- content: "\e691";
-}
-.icon-interpreter-outline::before {
- content: "\e692";
-}
-.icon-internet::before {
- content: "\e693";
-}
-.icon-internet-outline::before {
- content: "\e694";
-}
-.icon-internet-24-outline::before {
- content: "\e695";
-}
-.icon-internet-18-outline::before {
- content: "\e696";
-}
-.icon-international-outline::before {
- content: "\e697";
-}
-.icon-international-long-distance-outline::before {
- content: "\e698";
-}
-.icon-international-data-outline::before {
- content: "\e699";
-}
-.icon-installation-outline::before {
- content: "\e69a";
-}
-.icon-information::before {
- content: "\e69b";
-}
-.icon-info-success::before {
- content: "\e69c";
-}
-.icon-info-alert::before {
- content: "\e69d";
-}
-.icon-info-alert-outline::before {
- content: "\e69e";
-}
-.icon-included-checkmark::before {
- content: "\e69f";
-}
-.icon-included-checkmark-outline::before {
- content: "\e6a0";
-}
-.icon-hotspot::before {
- content: "\e6a1";
-}
-.icon-hotspot-outline::before {
- content: "\e6a2";
-}
-.icon-hotspot-access-outline::before {
- content: "\e6a3";
-}
-.icon-home::before {
- content: "\e6a4";
-}
-.icon-help::before {
- content: "\e6a5";
-}
-.icon-help-outline::before {
- content: "\e6a6";
-}
-.icon-hd::before {
- content: "\e6a7";
-}
-.icon-hd-outline::before {
- content: "\e6a8";
-}
-.icon-hamburger::before {
- content: "\e6a9";
-}
-.icon-group-outline::before {
- content: "\e6aa";
-}
-.icon-gps::before {
- content: "\e6ab";
-}
-.icon-gps-outline::before {
- content: "\e6ac";
-}
-.icon-go-paperless-email-outline::before {
- content: "\e6ad";
-}
-.icon-global-messaging-outline::before {
- content: "\e6ae";
-}
-.icon-gamepad-outline::before {
- content: "\e6af";
-}
-.icon-game-devices::before {
- content: "\e6b0";
-}
-.icon-full-screen::before {
- content: "\e6b1";
-}
-.icon-forward-calls-outline::before {
- content: "\e6b2";
-}
-.icon-forum::before {
- content: "\e6b3";
-}
-.icon-forum-outline::before {
- content: "\e6b4";
-}
-.icon-filter::before {
- content: "\e6b5";
-}
-.icon-extras::before {
- content: "\e6b6";
-}
-.icon-extras-outline::before {
- content: "\e6b7";
-}
-.icon-erase::before {
- content: "\e6b8";
-}
-.icon-envelope::before {
- content: "\e6b9";
-}
-.icon-envelope-outline::before {
- content: "\e6ba";
-}
-.icon-enterprise-messaging-outline::before {
- content: "\e6bb";
-}
-.icon-edit::before {
- content: "\e6bc";
-}
-.icon-duplicate::before {
- content: "\e6bd";
-}
-.icon-dropdown-up::before {
- content: "\e6be";
-}
-.icon-dropdown-down::before {
- content: "\e6bf";
-}
-.icon-download::before {
- content: "\e6c0";
-}
-.icon-download-outline::before {
- content: "\e6c1";
-}
-.icon-disputes::before {
- content: "\e6c2";
-}
-.icon-detailed-billing::before {
- content: "\e6c3";
-}
-.icon-detailed-billing-outline::before {
- content: "\e6c4";
-}
-.icon-desktop-outline::before {
- content: "\e6c5";
-}
-.icon-data::before {
- content: "\e6c6";
-}
-.icon-data-outline::before {
- content: "\e6c7";
-}
-.icon-data-additional-outline::before {
- content: "\e6c8";
-}
-.icon-compare::before {
- content: "\e6c9";
-}
-.icon-cloud-storage-outline::before {
- content: "\e6ca";
-}
-.icon-cloud-outline::before {
- content: "\e6cb";
-}
-.icon-cloud-computing-outline::before {
- content: "\e6cc";
-}
-.icon-cloud-backup::before {
- content: "\e6cd";
-}
-.icon-cloud-backup-outline::before {
- content: "\e6ce";
-}
-.icon-circle-information-outline::before {
- content: "\e6cf";
-}
-.icon-circle-action-plus-outline::before {
- content: "\e6d0";
-}
-.icon-circle-action-minus-outline::before {
- content: "\e6d1";
-}
-.icon-circle-action-empty::before {
- content: "\e6d2";
-}
-.icon-circle-action-delete-outline::before {
- content: "\e6d3";
-}
-.icon-circle-action-close::before {
- content: "\e6d4";
-}
-.icon-circle-action-check-outline::before {
- content: "\e6d5";
-}
-.icon-circle-action-remove::before {
- content: "\e6d6";
-}
-.icon-circle-action-add::before {
- content: "\e6d7";
-}
-.icon-chip-outline::before {
- content: "\e6d8";
-}
-.icon-chevron-up::before {
- content: "\e6d9";
-}
-.icon-chevron-right::before {
- content: "\e6da";
-}
-.icon-chevron-left::before {
- content: "\e6db";
-}
-.icon-chevron-down::before {
- content: "\e6dc";
-}
-.icon-checkbox-checkmark::before {
- content: "\e6dd";
-}
-.icon-chat::before {
- content: "\e6de";
-}
-.icon-chat-small::before {
- content: "\e6df";
-}
-.icon-case-studies::before {
- content: "\e6e0";
-}
-.icon-cart::before {
- content: "\e6e1";
-}
-.icon-cart-small::before {
- content: "\e6e2";
-}
-.icon-camera::before {
- content: "\e6e3";
-}
-.icon-camera-outline::before {
- content: "\e6e4";
-}
-.icon-calendar-outline::before {
- content: "\e6e5";
-}
-.icon-business::before {
- content: "\e6e6";
-}
-.icon-business-tv::before {
- content: "\e6e7";
-}
-.icon-business-tv-outline::before {
- content: "\e6e8";
-}
-.icon-business-tv-additional-packs-outline::before {
- content: "\e6e9";
-}
-.icon-business-outline::before {
- content: "\e6ea";
-}
-.icon-business-center::before {
- content: "\e6eb";
-}
-.icon-business-center-outline::before {
- content: "\e6ec";
-}
-.icon-bundles::before {
- content: "\e6ed";
-}
-.icon-bundles-outline::before {
- content: "\e6ee";
-}
-.icon-billing::before {
- content: "\e6ef";
-}
-.icon-billing-history-outline::before {
- content: "\e6f0";
-}
-.icon-billing-dashboard::before {
- content: "\e6f1";
-}
-.icon-bd-maps::before {
- content: "\e6f2";
-}
-.icon-basicphone::before {
- content: "\e6f3";
-}
-.icon-basicphone-outline::before {
- content: "\e6f4";
-}
-.icon-barcode-outline::before {
- content: "\e6f5";
-}
-.icon-bar-chart-vertical::before {
- content: "\e6f6";
-}
-.icon-bar-chart-horizontal::before {
- content: "\e6f7";
-}
-.icon-arrow-up::before {
- content: "\e6f8";
-}
-.icon-arrow-up-right::before {
- content: "\e6f9";
-}
-.icon-arrow-up-left::before {
- content: "\e6fa";
-}
-.icon-arrow-up-circle::before {
- content: "\e6fb";
-}
-.icon-arrow-right::before {
- content: "\e6fc";
-}
-.icon-arrow-right-circle::before {
- content: "\e6fd";
-}
-.icon-arrow-left::before {
- content: "\e6fe";
-}
-.icon-arrow-left-circle::before {
- content: "\e6ff";
-}
-.icon-arrow-down::before {
- content: "\e700";
-}
-.icon-arrow-down-right::before {
- content: "\e701";
-}
-.icon-arrow-down-left::before {
- content: "\e702";
-}
-.icon-arrow-down-circle::before {
- content: "\e703";
-}
-.icon-arrow-double-right::before {
- content: "\e704";
-}
-.icon-arrow-double-left::before {
- content: "\e705";
-}
-.icon-apps-media::before {
- content: "\e706";
-}
-.icon-apps-media-outline::before {
- content: "\e707";
-}
-.icon-apps-marketplace::before {
- content: "\e708";
-}
-.icon-apps-marketplace-outline::before {
- content: "\e709";
-}
-.icon-analytics::before {
- content: "\e70a";
-}
-.icon-alt-media-subscription-outline::before {
- content: "\e70b";
-}
-.icon-all-locations::before {
- content: "\e70c";
-}
-.icon-all-devices::before {
- content: "\e70d";
-}
-.icon-all-devices-outline::before {
- content: "\e70e";
-}
-.icon-alarms::before {
- content: "\e70f";
-}
-.icon-alarms-outline::before {
- content: "\e710";
-}
-.icon-address-ip-outline::before {
- content: "\e711";
-}
-.icon-addons::before {
- content: "\e712";
-}
-.icon-addons-outline::before {
- content: "\e713";
-}
-.icon-additional-services::before {
- content: "\e714";
-}
-.icon-additional-minutes-outline::before {
- content: "\e715";
-}
-.icon-add-widget::before {
- content: "\e716";
-}
-.icon-activity-feed::before {
- content: "\e717";
-}
-.icon-accessories::before {
- content: "\e718";
-}
-.icon-accessories-outline::before {
- content: "\e719";
-}
-.icon-foundation-account::before {
- content: "\e71a";
-}
-.icon-billing-account::before {
- content: "\e71b";
-}
-.headerContainer {
- left: 0px; top: 0px; width: 100%; color: rgb(255, 255, 255); line-height: 50px; position: fixed; z-index: 999; background-color: rgb(6, 122, 180); height: 55px;
-}
-.icon-infinite::before {
- content: "\e71c";
-}
-.headerContentContainer .primaryMenuContainer {
- font-family: clearview_att_regular; font-size: 18px;
-}
-.icon-social-business-community::before {
- content: "\e71d";
-}
-.icon-social-facebook::before {
- content: "\e71e";
-}
-.icon-social-feed::before {
- content: "\e71f";
-}
-.icon-social-google-plus::before {
- content: "\e720";
-}
-.icon-social-linkedin::before {
- content: "\e721";
-}
-.icon-social-network-exchange::before {
- content: "\e722";
-}
-.icon-social-twitter-bird::before {
- content: "\e723";
-}
-.icon-social-twitter::before {
- content: "\e724";
-}
-.icon-social-youtube::before {
- content: "\e725";
-}
-.icon-blocked::before {
- content: "\e726";
-}
-.icon-talk-text::before {
- content: "\e727";
-}
-.icon-blocked::before {
- content: "\e726";
-}
-.icon-group::before {
- content: "\e72c";
-}
-.icon-group-create::before {
- content: "\e72b";
-}
-.headerContentContainer {
- margin: auto; width: 100%; height: 50px; margin-top:5px;
-}
-.headerContentContainer .primaryMenuContainer .linkToRegistration {
- color: rgb(255, 255, 255); float: right;
-}
-.headerContentContainer .primaryMenuContainer .ATTLogo {
- background: url("../images/common/header/attLogo.png") no-repeat -10px -10px; width: 36px; height: 36px; margin-top: 7px; margin-right: 35px; margin-left: 10px; float: left;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer {
- float: left; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR {
- font-family: clearviewatt_ltbold; margin-right: 4px; margin-left: 2px; float: left;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR a {
- color: rgb(255, 255, 255); font-family: clearviewatt_ltbold; font-size: 18px; text-decoration: none;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR a:hover {
- color: rgb(191, 231, 251); text-decoration: none;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR a:active {
- color: rgb(191, 231, 251); text-decoration: none;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR:hover {
- margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .attHomeContainer .businessCenterR:active {
- margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .primaryMenuOptionsContainer .primaryMenuOptionLink {
- color: rgb(255, 255, 255); font-family: clearviewatt; font-size: 18px; text-decoration: none; margin-left: 20px; float: left; cursor: pointer;
-}
-/* .primaryMenuOptionLink { */
-/* width: 8em; text-overflow: clip; text-overflow: ellipsis; text-overflow: "…"; white-space: nowrap; */
-/* } */
-.headerContentContainer .primaryMenuContainer .primaryMenuOptionsContainer .primaryMenuOptionLink:hover {
- color: rgb(191, 231, 251); text-decoration: none; margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .primaryMenuOptionsContainer .primaryMenuOptionLink:focus {
- color: rgb(191, 231, 251); text-decoration: none; margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .primaryMenuOptionsContainer .primaryMenuOptionLink:active {
- color: rgb(191, 231, 251); text-decoration: none; margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .pageNameContainer .pageName {
- color: rgb(255, 255, 255); font-family: clearviewatt_ltbold; font-size: 18px; text-decoration: none; margin-left: 30px; float: left; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .pageNameContainer .pageName:hover {
- color: rgb(191, 231, 251); text-decoration: none; margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .pageNameContainer .pageName:active {
- color: rgb(191, 231, 251); text-decoration: none; margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .selectedOptionIndicator {
- border-width: 0px 8px 8px; border-style: solid; border-color: transparent transparent rgb(255, 255, 255); width: 0px; height: 0px; margin-top: 43px; position: absolute;
-}
-.headerContentContainer .primaryMenuContainer .loginIcon {
- background: url("") no-repeat -10px -41px; width: 16px; height: 21px; color: rgb(255, 255, 255); line-height: 50px; font-size: 18px; margin-top: 14px; margin-right: 10px; float: left; position: relative; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .loginIcon:hover {
- background-position: -10px -10px; margin-top: 12px;
-}
-.headerContentContainer .primaryMenuContainer .loginIcon:focus {
- background-position: -10px -10px; margin-top: 12px;
-}
-.headerContentContainer .primaryMenuContainer .icon-cart {
- background-position: -1000px; color: rgb(255, 255, 255); line-height: 50px; font-size: 18px; margin-right: 34px; float: left; position: relative; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .icon-cart:hover {
- color: rgb(191, 231, 251); margin-top: -2px;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer {
- height: 50px; float: right; position: relative;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .loginName {
- line-height: 50px; font-family: clearviewatt; font-size: 12px; margin-right: 31px; float: left; position: relative;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .chatIcon {
- background: url("../images/headerChatIcon.png") no-repeat -3px -3px; width: 18px; height: 19px; color: rgb(255, 255, 255); line-height: 50px; margin-top: 16px; margin-right: 32px; float: left; position: relative; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .chatIcon:hover {
- background-position: -3px -4px; margin-top: 14px;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .chatIcon:focus {
- background-position: -3px -4px; margin-top: 14px;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .searchIcon {
- background-position: -1000px; color: rgb(255, 255, 255); line-height: 50px; margin-right: 31px; float: left; position: relative; cursor: pointer;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .searchIcon:hover {
- color: rgb(191, 231, 251); margin-top: -2px;
-}
-.selectedPrimaryMenuOption {
- color: rgb(255, 255, 255); font-family: clearviewatt_ltbold !important;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .thirdMenuContainer .thirdFourthMenuContainer {
-
-}
-.secondaryTopMenuContainer {
- color: rgb(102, 102, 102); line-height: 50px; font-family: clearviewatt;
- font-size: 16px; float: left; background-color: rgb(255, 255, 255); z-index: 1000;
- top: 57px; margin: 0 auto 10; height: auto; margin-left: 201px; padding-right: 10px;
- /* width: 100%; margin-top: 50px; margin-bottom: 50px; */
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption {
- overflow: hidden; float: left; cursor: pointer;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption .selectionDiv {
- top: -4px; height: 4px; position: relative; background-color: rgb(6, 122, 180);
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption .secondaryMenuOptionLink {
- outline: 0px; color: rgb(102, 102, 102); text-decoration: none;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption .secondaryMenuOptionLink:hover {
- font-weight: bold; font-size: 16px; text-decoration: none;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption .secondaryMenuOptionLink:focus {
- font-weight: bold; font-size: 16px; text-decoration: none;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption {
- outline: 0px; color: rgb(102, 102, 102); text-decoration: none;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption {
- font-family: clearviewatt_ltbold; font-size: 16px; text-decoration: none;
-}
-.secondaryTopMenuContainer .secondaryMenuContentContainer .secondaryMenuOption {
- font-family: clearviewatt_ltbold; font-size: 16px; text-decoration: none;
-}
-.selectedSecondaryMenuOption {
- font-family: clearviewatt_ltbold; font-size: 16px;
-}
-
-.secondThirdFourthContainer {
- display: block;
-}
-
-.thirdSubmenuOptionLink a:hover:after, .headerMenus selected {
- outline: 0;
- font-weight: bold;
- !important;
-}
-
-.thirdSubmenuContainer {
- font-family: clearviewatt;
- font-size: 14px;
- float: left;
- background-color: rgb(255, 255, 255);
- left: 0;
-/* top: 90px; */
-/* margin-left: 201px; */
- padding-right: 10px;
- display: inline-flex;
- width: auto;
- position: relative;
-}
-.fourthMenuContainer {
- font-family: clearviewatt;
- font-size: 14px;
- float: left;
- background-color: rgb(255, 255, 255);
- width: auto;
- margin-top: -20px;
- margin-bottom: 30px;
- position: relative;
-}
-.thirdMenuContainer .thirdMenuContentContainer .thirdSubmenuOption {
- cursor: pointer;
-}
-.thirdMenuContainer .thirdMenuContentContainer .thirdSubmenuOption .selectionThirdDiv {
- !important; top: -4px; height: 4px; position: relative; background-color: rgb(6, 122, 180);
-}
-.thirdMenuContainer .thirdMenuContentContainer .thirdSubmenuOption {
- !important; outline: 0px; color: rgb(102, 102, 102); text-decoration: none; !important;
-}
-.thirdMenuContainer .thirdMenuContentContainer .thirdSubmenuOption {
- !important; font-family: clearviewatt_ltbold; font-size: 14px; text-decoration: none; font-weight: bold; !important;
-}
-.thirdMenuContainer .thirdMenuContentContainer .thirdSubmenuOption {
- !important; font-family: clearviewatt_ltbold; font-size: 14px; text-decoration: none; !important;
-}
-.selectedThirdMenuOption {
-/* font-family: clearviewatt_ltbold; font-size: 14px; */
-}
-
-.fourthMenuContainer .fourthMenuContentContainer {
- margin: auto; width: 100%;
-}
-.fourthMenuContainer .fourthMenuContentContainer .fourthSubmenuOption {
- overflow: hidden; float: left; cursor: pointer;
-}
-.fourthMenuContainer .fourthMenuContentContainer .fourthSubmenuOption .selectionFourthDiv {
- top: -4px; height: 4px; position: relative; background-color: rgb(6, 122, 180);
-}
-.fourthMenuContainer .fourthMenuContentContainer .fourthSubmenuOption .fourthSubmenuOptionLink {
- outline: 0px; color: rgb(102, 102, 102); text-decoration: none;
-}
-.fourthMenuContainer .fourthMenuContentContainer .fourthSubmenuOption .fourthSubmenuOptionLink:hover {
- font-family: clearviewatt_ltbold; font-size: 14px; text-decoration: none;
-}
-.fourthMenuContainer .fourthMenuContentContainer .fourthSubmenuOption .fourthSubmenuOptionLink:focus {
- font-family: clearviewatt_ltbold; font-size: 14px; text-decoration: none;
-}
-.selectedfourthMenuOption {
-/* font-family: clearviewatt_ltbold; font-size: 14px; */
-}
-
-.homePageNameHighlight {
- font-family: clearviewatt_ltbold; font-size: 16px;
-}
-.megaMenuContainer {
- width: 100%; overflow: auto; margin-top: 101px; position: fixed; z-index: 3000; height: 55px; max-height: 500px; opacity: 1; background-color: rgb(255, 255, 255);
-}
-.megaMenuContentContainer {
- margin: auto; width: 100%;
-}
-.megaMenuContentContainer .megaMenuTable {
- width: 100%;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn {
- vertical-align: top;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer {
- margin-bottom: 32px; float: left;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer .categoryTitle {
- color: rgb(68, 68, 68); font-family: clearviewatt_ltbold; font-size: 14px; margin-top: 36px; margin-bottom: 22px;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer .categoryOptionLink {
- outline: 0px; color: rgb(68, 68, 68); font-family: clearviewatt; font-size: 12px; text-decoration: none; margin-bottom: 13px;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer .categoryOptionLink:hover {
- color: rgb(25, 157, 223); text-decoration: none;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer .categoryOptionLink:focus {
- color: rgb(25, 157, 223); text-decoration: none;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuRow .categoryContainerColumn .categoryContainer .categoryOptionLink:active {
- color: rgb(25, 157, 223); text-decoration: none;
-}
-.megaMenuContentContainer .megaMenuTable .megaMenuSecondRow .categoryTitle {
- margin-top: 4px !important;
-}
-.addMargin {
- margin-top: 50px;
-}
-.contents {
- padding-top: 100px;
-}
-.megaMenuContentContainer .megaMenuTable li {
- float: left;
-}
-.megaMenuContentContainer ul {
- margin: 0px;
-}
-.unselectable {
- -ms-user-select: none; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none; -khtml-user-select: none;
-}
-.chatBox {
- background: rgb(242, 242, 242); border: 1px solid rgb(187, 187, 187); top: 50px; width: 250px; right: 30px; display: none; position: absolute; z-index: 1000; min-height: 145px; box-sizing: border-box; box-shadow: 0px 4px 4px rgba(0,0,0,0.25); -webkit-box-sizing: border-box; -moz-box-sizing: border-box;
-}
-.chatBox .arrow {
- left: 233px; top: -8px; width: 0px; height: 0px; border-right-color: transparent; border-bottom-color: rgb(255, 255, 255); border-left-color: transparent; border-right-width: 8px; border-bottom-width: 8px; border-left-width: 8px; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; position: absolute; z-index: 1001;
-}
-.chatBox-header {
- padding: 0px 25px; width: 250px; height: 85px; position: relative; box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box;
-}
-.chatBox-heading {
- left: 25px; top: 18px; color: rgb(68, 68, 68); line-height: 28px; font-family: omnes_attlight; font-size: 24px; position: absolute;
-}
-.chatBox-question {
- left: 25px; top: 53px; color: rgb(68, 68, 68); line-height: 16.8px; font-family: clearviewatt; font-size: 13px; position: absolute;
-}
-.circle_close_chat {
- top: 22px; right: 20px; color: rgb(68, 68, 68); font-size: 14px; position: absolute; cursor: pointer;
-}
-.chatBox-body {
- padding: 0px 15px; width: 250px; color: rgb(68, 68, 68); font-size: 12px; position: relative; box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box;
-}
-.chat-option {
- height: 35px; line-height: 45px; margin-bottom: 10px; position: relative;
-}
-.chat-option .hr-chatbox {
- margin: 10px 0px; padding: 0px; border: 0px currentColor !important; width: inherit; height: 1px; display: block;
-}
-.chat-icon-info {
- top: 15px; right: 6px; font-size: 16px; position: absolute;
-}
-.chat-option > span {
- left: 10px; top: 0px; position: absolute; cursor: pointer;
-}
-.chat-option > span {
- left: 10px; top: 0px; position: absolute;
-}
-.chat-option > span:hover {
- color: rgb(6, 122, 180);
-}
-
-.box1 {
- min-width: 260px;
- /* min-height:165px; */
-
- height: auto;
- width: auto;
- z-index: 1000;
- display: none;
- background: #FFF;
- border: solid 1px #BBBBBB;
- /* border-radius:5px; */
-
- box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
- position: relative;
-}
-.box1 *,
-.box1 :after,
-.box1 :before {
- -webkit-box-sizing: content-box;
- -moz-box-sizing: content-box;
- box-sizing: content-box;
-}
-.box1 a.close {
- color: red;
- font-size: 12px;
- font-family: arial;
- text-decoration: underline;
-}
-.box1 .arrow {
- width: 0;
- height: 0;
- border-left: 8px solid transparent;
- border-right: 8px solid transparent;
- border-bottom: 8px solid #FFF;
- position: absolute;
- left: 1px;
- top: -8px;
- z-index: 1001;
-}
-.headerContentContainer .primaryMenuContainer .headerIconContainer .popbox .box1 ul {
- margin-left: 0px;
-}
-
-.logo-image {
- .att-logo;
- display: inline-block;
- vertical-align: middle;
- margin-top: -3px;
- }
-
-.megamenu-tabs .megamenu__item {
- padding: 0 0;
-}
-.megamenu-tabs .megamenu__item span {
- font-size: 18px;
-}
-
-.submenu-tabs {
- line-height:50px;
-
-}
-.submenu-tabs .sub__menu{
- top:54px;
-}
-
-.top-megamenu .megamenu-tabs ul{
- width:98%;
- list-style: none;
-}
-.top-megamenu .megamenu-tabs ul li {
- display: inline-block;
- text-align: left;
-
-}
-
-.favorites-icon-active {
- color: #fbb313;
-}
-
-.favorites-icon-inactive {
- color: #666666;
-}
-.favorites-window {
- width: 100%;
- height: auto;
- //margin: auto;
- font-size: 14px !important;
- display: flex;
- font-family: clearview_att_regular;
- margin-top: 25px;
- margin-left: 25px;
- z-index: 1000;
-
- a:link, a:active, a:hover {
- margin-left: 3px;
- margin-right: 20px;
- text-decoration: none;
- }
-}
-
- .favoritesLargeText {
- font-weight: 400;
- font-family: Arial !important;
- font-size: 18px;
- text-align: center;
- }
-
-
-.favorites-window-empty {
- width: 100%;
- height: auto;
- display:flex;
- justify-content:center;
- align-items:center;
- margin: auto;
- text-align: center;
-
-}
-
-.favoritesNormalText {
- font-size: 14px;
- text-align: center;
- color: #666666
-}
-
-.columns{
- column-count: 5;
- line-height: 15px;
- column-gap: 40px;
- column-rule: 2px outset #666666;
-
-}
-
-.columns-div {
- min-width: 90%;
- margin-top: -5px;
-
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/portal_ebz_header.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/portal_ebz_header.css
deleted file mode 100644
index 639b5e75..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/ebz_header/portal_ebz_header.css
+++ /dev/null
@@ -1,63 +0,0 @@
-li {
- list-style: none;
-}
-
-#userIcon:hover {
- color: rgb(191, 231, 239);
-}
-
- .body-content-jsp {
- margin-top: 50px;
- min-height:500px;
- margin-left:210px;
- margin-right:50px;
-}
-
-.headerContentContainer .primaryMenuContainer .headerIconContainer .popbox .openpopbox:hover
- {
- color: #bfe7fb;
- margin-top: -2px;
- text-decoration: none;
- outline: none
-}
-
-.headerContentContainer .primaryMenuContainer .headerIconContainer .popbox .openpopbox
- {
- color: #fff;
- display: block;
- min-width: 70px;
- max-width: 115px;
- text-decoration: none
-}
-
-a {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-
-/* a:active,a:hover {
- outline: 0;
- font-weight: bold;
-} */
-b,strong {
- font-weight: 700
-}
-
-/* .thirdMenuContainer { */
-/* width: 100%; */
-/* overflow: auto; */
-/* margin-top: 101px; */
-/* position: fixed; */
-/* z-index: 3000; */
-/* min-height: 140px; */
-/* max-height: 500px; */
-/* opacity: 1; */
-/* background-color: rgb(255, 255, 255); */
-
-/* } */
-
-.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden .focusable:active,.visuallyhidden .focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/fn-ebz.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/fn-ebz.css
deleted file mode 100644
index f81cc2a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/fn-ebz.css
+++ /dev/null
@@ -1,1614 +0,0 @@
-@CHARSET "ISO-8859-1";
-
-* {
- font-family: Arial;
-}
-
-/* html, body {
- overflow:auto
-} */
-div.fn-ebz-container {
- position: relative;
- display: inline-block;
- margin-top: 4px;
- padding-bottom: 16px;
-}
-
-div.fn-ebz-small-container {
- position: relative;
- display: inline-block;
- margin-top: 4px;
- padding-bottom: 16px;
- height: 30px;
-}
-
-.myDivBackground div {
- font-family: clearviewatt;
- font-size: 11px;
- font-weight: normal;
- background: rgb(242, 242, 242);
-}
-
-.myGrid tr.z-row td.z-row-inner {
- border: 0px rgb(242, 242, 242);
- border-right: 0px solid transparent;
- padding: 0px;
-}
-
-.myGrid tr.z-row-over>td.z-row-inner>.z-row-cnt {
- color: #00547A;
-}
-
-.ebz-radioDiv {
- border: 1px solid #8FB9D0;
- padding: 10px;
- "
-}
-/**************************************************************************************/
-/**************************** following is for button**********************************/
-/**************************************************************************************/
-.fn-ebz-btn,.fn-ebz-btn.std {
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- height: 40px;
- padding-left: 30px;
- padding-right: 30px;
- font-size: 18px;
- text-align: center;
- border: 0px;
- cursor: pointer;
- color: rgba(255, 255, 255, 1);
- margin-top: 5px;
- margin-bottom: 5px;
-}
-
-.fn-ebz-btn.sm {
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- height: 30px;
- padding-left: 20px;
- padding-right: 20px;
- font-size: 12px;
- text-align: center;
- border: 0px;
- cursor: pointer;
- color: rgba(255, 255, 255, 1);
-}
-
-.fn-ebz-btn.primary {
- background-color: #067AB4;
-}
-
-.fn-ebz-btn.footer {
- color: #067AB4;
-}
-
-.fn-ebz-btn:hover {
- background-color: rgba(0, 145, 217, 1) !important;
-}
-
-.fn-ebz-btn:active {
- background-color: rgba(57, 176, 236, 1) !important;
-}
-
-.fn-ebz-btn:disabled {
- background-color: rgba(211, 211, 211, 1) !important;
- color: rgba(170, 170, 170, 1);
- cursor: initial;
-}
-
-.fn-ebz-btn:focus {
- outline-offset: 2px; /* not supported in IE */
- outline: rgba(57, 176, 236, 1) solid 1px;
-}
-
-.fn-ebz-btn.loading {
- color: transparent !important;
- background: url("../images/fn-ebz-css/processing.gif") no-repeat;
- background-position: center;
- background-color: rgba(211, 211, 211, 1) !important;
-}
-
-.fn-ebz-btn.directional::after {
- content: " \2192";
- vertical-align: middle;
-}
-
-/*************************************************************************************/
-/**************************** following is for label**********************************/
-/*************************************************************************************/
-/*-----------------------------------------------------------------------------------*/
-/*---- font-size rules for label, specify top attr when change font size of label ---*/
-/*------------------------------ top: -(font-size)px --------------------------------*/
-/*-----------------------------------------------------------------------------------*/
-label.fn-ebz-text-label,label.fn-ebz-select-label {
- position: absolute;
- color: #444444;
- left: 0px;
- top: -5px;
- white-space: nowrap;
- font-family: Arial;
- /*font-size: 12px;*/
- font-size: .75rem;
-}
-
-label.fn-ebz-radiobtn-label {
- background-image: url(../images/fn-ebz-css/radio_btn.png);
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-/*************************************************************************************/
-/**************************** following is for text field ****************************/
-/*************************************************************************************/
-input[type="password"].fn-ebz-text {
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- margin-top: 8px;
- height: 30px;
- width: 250px;
- border: 1px solid gray;
- font-size: .875rem;
- /*font-size: 11px;*/
- /*font-weight: bold;*/
- padding-left: 10px;
-}
-
-input[type="text"].fn-ebz-text {
- width: 210px;
- margin-right: 20px;
-}
-
-input[type="text"].fn-ebz-text:hover {
- border: 1px solid black;
-}
-
-input[type="text"].fn-ebz-text:hover+label.fn-ebz-text-label {
- color: black;
-}
-
-input[type="text"].fn-ebz-text:focus {
- outline: 0;
- border: 1px solid rgba(57, 176, 236, 1);
-}
-
-input[type="text"].fn-ebz-text:focus+label.fn-ebz-text-label {
- color: rgba(57, 176, 236, 1);
-}
-
-input[type="text"].fn-ebz-text:disabled {
- background-color: LightGray;
-}
-
-input[type="text"].fn-ebz-text:disabled+label.fn-ebz-text-label {
- color: LightGray;
-}
-
-input[type="text"].fn-ebz-text:hover:disabled {
- border: 1px solid gray;
-}
-
-input[type="text"].fn-ebz-text:hover:disabled+label.fn-ebz-text-label {
- color: LightGray;
-}
-
-input[type="text"].fn-ebz-text.small {
- width: 30px;
- height: 20px;
-}
-
-input[type="text"].fn-ebz-text.medium-width {
- width: 60px;
-}
-
-input[type="text"].fn-ebz-text.large {
- width: 350px;
-}
-
-input[type="text"].fn-ebz-text.extra-large {
- width: 520px;
-}
-
-input[type="text"].fn-ebz-text.medium {
- width: 200px;
- height: 29px;
- margin-top: 0;
- padding-top: 10px;
- padding-right: 10px;
- padding-bottom: 10px;
- padding-left: 10px;
-}
-
-input[type="text"].fn-ebz-text.search {
- width: 200px;
- height: 30px;
- padding-top: 10px;
- padding-right: 10px;
- padding-bottom: 10px;
- padding-left: 10px;
-}
-
-input[type="text"].fn-ebz-text.normal {
- width: 250px;
- height: 30px;
- padding-top: 10px;
- padding-right: 10px;
- padding-bottom: 10px;
- padding-left: 10px;
-}
-/********************************************************************************/
-/************************ following is for errors and valid *********************/
-/********************************************************************************/
-.fn-ebz-error {
- border: 1px solid red !important;
-}
-
-.fn-ebz-errorGeneric {
- border: 1px solid red !important;
-}
-
-.fn-ebz-errorGeneric+label.fn-ebz-text-label::after,.fn-ebz-errorGeneric+label.fn-ebz-select-label::after
- {
- content: url("../images/fn-ebz-css/error_sign_generic.png");
- baseline-shift: -2px;
- margin-left: 10px;
-}
-
-.fn-ebz-validInput {
- border: 1px solid green !important;
-}
-
-.fn-ebz-validInput+label.fn-ebz-text-label::after {
- content: url("../images/fn-ebz-css/warning_sign.png")
- url("../images/fn-ebz-css/10px_space.png")
- url("../images/fn-ebz-css/valid_check.png");
- baseline-shift: -2px;
- margin-left: 5px;
- margin-right: 5px;
-}
-
-.fn-ebz-validInput+label.fn-ebz-select-label {
- color: green;
-}
-
-.fn-ebz-validInput+label.fn-ebz-select-label::after {
- content: url("../images/fn-ebz-css/valid_check.png");
- baseline-shift: -2px;
- margin-left: 10px;
-}
-
-/*************************************************************************************************/
-/************************************* Following is for tooltips *********************************/
-/*************************************************************************************************/
-span.fn-ebz-tooltip,span.fn-ebz-tooltip.south {
- position: absolute;
- height: 30px;
- top: 90%;
- left: 0%;
- line-height: 30px;
- text-align: center;
- visibility: hidden;
- border-radius: 6px;
- padding-left: 10px;
- padding-right: 10px;
- opacity: 0.7;
- z-index: 999;
- font-weight: bold;
- font-size: 14px;
- color: #000000;
- background: #FFFFFF;
- box-shadow: 0px 6px 6px gray;
- border: 2px solid #EEEEEE;
- text-align: center;
- white-space: nowrap;
-}
-
-span.fn-ebz-tooltip::before,span.fn-ebz-tooltip.south::before {
- content: '';
- position: absolute;
- bottom: 100%;
- left: 14px;
- margin-left: -12px;
- width: 0;
- height: 0;
- border-bottom: 12px solid #EEEEEE;
- border-right: 12px solid transparent;
- border-left: 12px solid transparent;
-}
-
-span.fn-ebz-tooltip::after,span.fn-ebz-tooltip.south::after {
- content: '';
- position: absolute;
- bottom: 99%;
- left: 14px;
- margin-left: -8px;
- width: 0;
- height: 0;
- border-bottom: 8px solid #FFFFFF;
- border-right: 8px solid transparent;
- border-left: 8px solid transparent;
-}
-
-span.fn-ebz-tooltip:hover {
- border: 2px solid Darkgray;
-}
-
-span.fn-ebz-tooltip:hover.south::before {
- border-bottom: 12px solid Darkgray;
-}
-
-span.fn-ebz-tooltip:hover.south::after {
- border-bottom: 8px solid white;
-}
-
-span.fn-ebz-tooltip:hover.north::before {
- border-top: 12px solid Darkgray;
-}
-
-span.fn-ebz-tooltip:hover.north::after {
- border-top: 8px solid white;
-}
-
-span.fn-ebz-tooltip.north {
- top: -70%;
-}
-
-span.fn-ebz-tooltip.north::before {
- top: 100%;
- border-top: 12px solid #EEEEEE;
- border-bottom: 0;
-}
-
-span.fn-ebz-tooltip.north::after {
- top: 100%;
- border-top: 8px solid #FFFFFF;
- border-bottom: 0;
-}
-
-span.fn-ebz-tooltip.error {
- color: #FFFFFF;
- padding-left: 30px;
- background: url("../images/fn-ebz-css/error_sign_spec.png") no-repeat;
- background-position: 10px 7px;
- background-color: #FF0000;
- border: 0;
-}
-
-span.fn-ebz-tooltip.error::before,span.fn-ebz-tooltip.warning:before {
- border: 0;
-}
-
-span.fn-ebz-tooltip.error.south::after {
- border-bottom: 8px solid #FF0000 !important;
-}
-
-span.fn-ebz-tooltip.error.north::after {
- border-top: 8px solid #FF0000 !important;
-}
-
-span.fn-ebz-tooltip.warning {
- color: black;
- padding-left: 30px;
- background: url("../images/fn-ebz-css/warning_sign.png") no-repeat;
- background-position: 10px 7px;
- background-color: orange;
- border: 0;
-}
-
-span.fn-ebz-tooltip.warning.south::after {
- border-bottom: 8px solid orange !important;
-}
-
-span.fn-ebz-tooltip.warning.north::after {
- border-bottom: 8px solid orange !important;
-}
-
-/*************************************************************************************************/
-/************************************* Following is for Dropdown *********************************/
-/*************************************************************************************************/
-select.fn-ebz-dropdown::-ms-expand {
- display: none;
-}
-
-select.fn-ebz-dropdown {
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- -webkit-appearance: none; /* not supported in IE */
- -moz-appearance: none; /* not supported in IE */
- appearance: none; /* not supported in IE */
- height: 30px;
- width: 200px;
- padding-left: 10px;
- padding-right: 30px;
- background: url(../images/fn-ebz-css/down_arrow.png) no-repeat right;
- background-color: white;
- color: gray;
- margin-top: 8px;
- font-size: 12px;
-}
-
-select.fn-ebz-dropdown:hover {
- border: 1px solid black;
- color: black;
-}
-
-select.fn-ebz-dropdown:hover+label.fn-ebz-select-label {
- color: black;
-}
-
-select.fn-ebz-dropdown:focus {
- outline: 0;
- color: black;
- border: 1px solid rgba(0, 145, 217, 1);
- background: url(../images/fn-ebz-css/up_arrow.png) no-repeat right;
-}
-
-select.fn-ebz-dropdown:focus+label.fn-ebz-select-label {
- color: rgba(0, 145, 217, 1);
-}
-
-select.fn-ebz-dropdown.medium {
- width: 150px;
- height: 29px;
- margin: auto;
- padding-right: 10px;
- padding-left: 10px;
-}
-
-select.fn-ebz-dropdown.large {
- height: 36px;
- font-size: 14px;
-}
-
-.mydropdown {
- color: gray;
- /*font-size:11px;*/
- font-size: .875rem;
-}
-
-select.fn-ebz-dropdown.search {
- width: 200px;
- height: 30px;
- margin: auto;
- padding: 0px;
-}
-/*************************************************************************************************/
-/********************************* following is for radio button *********************************/
-/*************************************************************************************************/
-div.fn-ebz-container>input[type=radio],input[type=radio].fn-ebz-radiobtn
- {
- display: none;
-}
-
-div.fn-ebz-container>input[type=radio]+label.fn-ebz-radiobtn-label,input[type=radio].fn-ebz-radiobtn+label.fn-ebz-radiobtn-label
- {
- background-image: url(../images/fn-ebz-css/radio_btn.png);
- padding-left: 32px;
- height: 30px;
- display: block;
- line-height: 30px;
- background-repeat: no-repeat;
- background-position: 0 0px;
- font-size: 16px;
- vertical-align: middle;
- cursor: pointer;
- opacity: 0.8;
-}
-
-div.fn-ebz-container>input[type=radio]+label.fn-ebz-radiobtn-label:hover,input[type=radio].fn-ebz-radiobtn+label.fn-ebz-radiobtn-label:hover
- {
- opacity: 1;
-}
-
-div.fn-ebz-container>input[type=radio]:checked+label.fn-ebz-radiobtn-label,input[type=radio].fn-ebz-radiobtn:checked+label.fn-ebz-radiobtn-label
- {
- background-image: url(../images/fn-ebz-css/radio_btn.png);
- background-position: 0 -30px;
-}
-
-div.fn-ebz-container>input[type=radio]:disabled+label.fn-ebz-radiobtn-label,input[type=radio].fn-ebz-radiobtn:disabled+label.fn-ebz-radiobtn-label
- {
- -webkit-filter: grayscale(100%);
- opacity: 0.5;
- cursor: default;
-}
-
-label.fn-ebz-radiobtn-label:active {
- background-position: 0 -60px !important;
- color: rgba(0, 145, 217, 1);
-}
-
-div.fn-ebz-container>input[type=radio].fn-ebz-error+label.fn-ebz-radiobtn-label,input[type=radio].fn-ebz-radiobtn.fn-ebz-error+label.fn-ebz-radiobtn-label
- {
- background-position: 0 -90px;
-}
-
-div.fn-ebz-container>input[type=radio].fn-ebz-errorGeneric+label.fn-ebz-radiobtn-label,input[type=radio].fn-ebz-radiobtn.fn-ebz-errorGeneric+label.fn-ebz-radiobtn-label
- {
- background-position: 0 -90px;
-}
-
-/*************************************************************************************************/
-/********************************* following is header and footer *********************************/
-/*************************************************************************************************/
-.ebz_footer {
- /*clear: both;*/
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- font-family: inherit;
- font-size: 12px;
- padding: 10px 10px 30px 10px;
- /* background: rgba(6, 124, 180, 0.82) !important; */
- background: #067AB4;
- color: white;
-}
-
-.ebz_header {
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- font-size: 12px;
- font-family: inherit;
-}
-
-.ebz_header.level1 {
- background: #226485;
- color: white;
-}
-
-.ebz_header.level2 {
- background: #067AB4;
- padding: 10px 10px 15px 10px;
- color: white;
- font-size: 20px;
-}
-
-.ebz_header.level3 {
- background: white;
- padding: 10px 10px 10px 10px;
- color: black;
-}
-
-/*************************************************************************************************/
-/********************************* following is for grid in user page ****************************/
-/*************************************************************************************************/
-.heading1 {
- font-family: omnes_att_light;
- font-size: 36px;
- color: #444444;
- margin: 0;
- padding: 0;
- font-weight: normal;
-}
-
-.heading2 {
- font-family: omnes_att_light;
- font-size: 24px;
- color: #444444;
- margin: 0;
- padding: 0;
- font-weight: normal;
-}
-
-.heading3 {
- font-family: omnes_att_light;
- font-size: 16px;
- color: #444444;
- margin: 0;
- padding: 0;
- font-weight: bold;
-}
-
-.fn-ebz-grid.limited-size {
- padding: 0;
- margin: 0;
- min-height: 40px;
- max-width: 940px;
- max-height: 900px;
-}
-
-.fn-ebz-grid tr.z-row td.z-row-inner,tr.z-row .z-cell {
- border: 0 white;
- background: rgb(242, 242, 242);
-}
-
-.fn-ebz-grid tr.z-grid-odd td.z-row-inner,tr.z-grid-odd .z-cell,tr.z-grid-odd
- {
- background: rgb(255, 255, 255);
-}
-
-.fn-ebz-grid .z-grid-header-bg {
- background-image: none;
-}
-
-/* .fn-ebz-grid tr.z-grid-odd .z-row-over{
- background: rgb(107,166,191);
- } */
-.fn-ebz-grid .z-column-cnt,.z-row-cnt {
- font-size: 13px;
- font-weight: normal;
- color: black;
-}
-
-.fn-ebz-grid .z-column-cnt {
- text-align: left;
-}
-
-.fn-ebz-grid .z-label {
- font-size: 12px;
- font-weight: normal;
- word-wrap: break-word;
- white-space: pre-wrap;
-}
-
-.fn-ebz-grid .z-grid-header th.z-column div.z-column-cnt {
- white-space: pre-wrap;
- color: white;
- backgroud: grey;
-}
-
-.fn-ebz-grid div.z-grid-header th.z-column,div.z-grid-header th.z-auxheader
- {
- background: rgb(102, 102, 102) repeat-x 0 0 !important;
- background-image: none !important;
- background-color: grey;
- border-color: grey;
- height: 40px;
-}
-
-.fn-ebz-grid tr.z-row-over>td.z-row-inner {
- border-color: lightgrey;
-}
-
-.fn-ebz-grid tr.z-row-over>td.z-row-inner,tr.z-row-over>.z-cell {
- background-color: lightgrey;
-}
-
-.fn-ebz-grid .z-row-cnt {
- color: black;
-}
-
-.fn-ebz-grid tr.z-row-over>td.z-row-inner>.z-row-cnt {
- color: black;
-}
-
-.fn-ebz-btn.grid-btn {
- margin: auto;
-}
-
-.fn-ebz-grid .z-toolbarbutton-cnt {
- padding: 8px 2px;
- margin: auto;
-}
-
-.z-button-os,.z-label,.z-button,.z-radio-cnt,.z-checkbox-cnt,.z-loading,.z-toolbarbutton-cnt,.z-button tr td
- {
- font-family: Arial;
-}
-
-.fn-ebz-btn.z-button tr td {
- color: rgba(255, 255, 255, 1);
-}
-
-.fn-ebz-btn.grid-btn.z-toolbarbutton-over .z-toolbarbutton-cnt,.fn-ebz-btn.z-button .z-button-tm,.z-button .z-button-bm,.fn-ebz-btn.z-button .z-button-cm,.z-button .z-button-tl,.fn-ebz-btn.z-button .z-button-tr,.fn-ebz-btn.z-button .z-button-bl,.z-button .z-button-br,.fn-ebz-btn.z-button .z-button-cl,.fn-ebz-btn.z-button .z-button-cr
- {
- background-image: none;
-}
-
-.fn-ebz-btn.z-button .z-button-cm {
- padding: 0;
-}
-
-.fn-ebz-btn.grid-btn.z-toolbarbutton-over .z-toolbarbutton-body {
- border: 0px;
-}
-
-.fn-ebz-pop-up {
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- border-style: solid;
- border-width: 1px;
- max-width: 360px;
-}
-
-.fn-ebz-pop-up .z-label {
- margin: 0;
- padding: 0;
- white-space: pre-wrap;
-}
-
-.fn-ebz-pop-up.success {
- border-color: #4CA90C;
-}
-
-.fn-ebz-pop-up.warning-unsuccess {
- border-color: #FF9900;
-}
-
-.fn-ebz-pop-up .heading,.fn-ebz-pop-up .heading .z-label {
- font-family: Calibri;
- font-size: 16px;
- font-weight: bold;
- white-space: pre-wrap;
-}
-
-.fn-ebz-pop-up.success .heading,.fn-ebz-pop-up.success .heading .z-label
- {
- color: #4CA90C
-}
-
-.fn-ebz-pop-up.warning-unsuccess .heading,.fn-ebz-pop-up.warning-unsuccess .heading .z-label
- {
- color: #FF9900;
-}
-
-.fn-ebz-pop-up.success .text-content {
- background-image: url('../images/vsp_check_sign.jpg');
-}
-
-.fn-ebz-pop-up.warning-unsuccess .text-content {
- background-image: url('../images/vsp_warning_sign.jpg');
-}
-
-.fn-ebz-pop-up .text-content {
- background-repeat: no-repeat;
- background-position: 15px center;
- background-size: 30px 30px;
- margin: 0;
- padding: 10px 20px 16px 60px;
-}
-
-.fn-ebz-pop-up {
- background-color: #FFF;
- opacity: 0.95;
-}
-
-a.fn-ebz-link {
- font-family: Calibri;
- text-decoration: none;
- color: grey;
- font-size: 18px;
-}
-
-a.fn-ebz-link:hover {
- color: rgb(6, 122, 180);
- cursor: pointer;
-}
-
-.hide,.show {
- width: 100%;
- height: 100%;
-}
-
-a.collapsibleArrow {
- width: 30px;
- height: 30px;
- margin-left: 10px;
-}
-
-.fn-ebz-grid .z-column-unassigned-Image {
- width: 7px;
- height: 7px;
-}
-
-/*************************************************************************************************/
-/********************************* following is for info label ***********************************/
-/*************************************************************************************************/
-.fn-ebz-info-label {
- display: inline-block;
- width: 300px;
- color: black;
- padding-left: 30px;
- background: url("../images/info_blue.jpg") no-repeat;
- background-position: top left;
-}
-
-/*************************************************************************************************/
-/********************************* following is for ListBox ****************************/
-/*************************************************************************************************/
-
-/*To change the header color to gray*/
-.mylistbox .z-listbox-header tr.z-listhead,.mylistheader .z-listbox-header tr.z-auxhead
- {
- background: rgb(102, 102, 102) repeat-x 0 0 !important;
- background-image: none !important;
-}
-
-.mylistbox .z-listheader-sort-asc .z-listheader-sort-img,.z-listheader-sort-dsc .z-listheader-sort-img
- {
- background-position: 0 0;
- background-repeat: no-repeat;
- background-image: none;
-}
-
-.mylistbox tr.z-listbox-odd {
- background: rgb(255, 255, 255);
-}
-
-.mylistbox .z-listitem {
- background: rgb(242, 242, 242);
-}
-
-.mylistbox .z-listitem-over {
- background-color: rgb(107, 166, 191) !important;
- border: none;
- cursor: pointer;
- text-shadow: 1px 1px 1px #59ACC1;
-}
-
-.mylistbox .z-listbox-header-bg {
- background-image: none;
-}
-
-.mylistbox div.z-listheader-cnt {
- color: white;
-}
-
-div.z-listbox {
- overflow: hidden;
- zoom: 1;
- background: #FFF;
- border: none;
- background-image: none;
-}
-
-.mylistbox .z-listcell-cnt {
- font-size: 13px;
- font-family: Arial;
-}
-
-div.ebz-listbox {
- height: 350px;
- border: 1px solid black;
- overflow: auto;
- border-radius: 6px;
- border-color: rgb(105, 138, 154);
- background-color: rgb(255, 255, 255);
- padding: 10px;
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
-}
-
-/*************************************************************************************************/
-/********************************* following is for butto on LocationPhoneNosList ****************************/
-/*************************************************************************************************/
-.myComboboxTextbox .z-combobox .z-combobox-inp {
- border: 1px solid #E6E6E6;
- border-top-color: #B2B2B2;
- border-right: 0;
- padding: 2px;
- border-radius: 6px 0 0 2px;
- -moz-border-radius: 2px 0 0 2px;
- -webkit-border-radius: 6px 0 0 2px;
- height: 25px;
-}
-
-.myzkBtn {
- color: gray;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- height: 32px;
- width: 32px;
- background: white;
- margin-top: 8px;
-}
-
-.myTextbox {
- padding-left: 8px;
- border-radius: 6px;
- height: 30px;
- width: 150px;
-}
-/*************************************************************************************************/
-/********************************* following is for Dashboard ****************************/
-/*************************************************************************************************/
-.ebz_dashboard .z-panel-br,.ebz_dashboard .z-panel-cr,.ebz_dashboard .z-panel-cl,.ebz_dashboard .z-panel-hr,.ebz_dashboard .z-panel-tr,.ebz_dashboard .z-panel-hl
- {
- background-image: none;
- background-color: white;
- color: white;
-}
-
-.ebz_dashboard .z-panel-hm .z-panel-header,.ebz_dashboard .z-panel-header
- {
- background-image: none;
- background-color: white;
- font-size: 15px;
- font-weight: bold;
- color: grey;
- font-family: Arial;
-}
-
-.ebz_dashboard .z-panel-hl {
- border-bottom: 0px;
-}
-
-.ebz_dashboard .z-panelchildren {
- border: 0px;
-}
-
-.ebz_dashboard .z-panel-shadow {
- box-shadow: 0 2px 5px 0 #bebebe;
- border: 3px solid rgb(242, 242, 242);
-}
-
-.ebz_dashboard .search_panel_span {
- font-size: 12px;
-}
-
-.mypanel .z-panel-br,.mypanel .z-panel-cr,.mypanel .z-panel-cl,.mypanel .z-panel-hr,.mypanel .z-panel-tr,.mypanel .z-panel-hl
- {
- background-image: none;
- background-color: grey;
- color: white;
-}
-
-.mypanel .z-panel-hm .z-panel-header,.mypanel .z-panel-header {
- background-image: none;
- background-color: grey;
- font-size: 15px;
- font-weight: bold;
- color: white;
-}
-
-.adashboard {
- color: grey;
- text-decoration: none;
- font-size: 14px;
- font-family: Arial;
-}
-
-.adashboard:hover {
- color: rgb(6, 122, 180);
-}
-
-.horizontal-label {
- font-size: 12px;
-}
-
-.myDashboard iframe {
- position: relative;
- height: 100%;
- width: 100%;
- background: rgb(242, 242, 242);
- border: none;
-}
-
-.myDashboard .a {
- color: grey !important;
- font-family: Calibri;
- text-decoration: none;
- font-size: 18px;
-}
-
-.myDashboard .a:hover {
- color: rgb(6, 122, 180);
-}
-
-.fn-ebz-info {
- width: 500px
-}
-
-.myDashboard .z-panel-hm .z-panel-header,.myDashboard .z-panel-header {
- background-image: none;
- background-color: grey;
- font-size: 15px;
- font-weight: bold;
-}
-
-.myDashboard .z-window-overlapped-cnt-noborder {
- padding: 0px;
-}
-
-.fn_ebz_dashboard_search_dd .select2-container .select2-choice {
- height: 30px;
- border-top-right-radius: 0px;
- border-bottom-right-radius: 0px;
- border: 1px solid #D3D3D3;
- z-index: 0;
-}
-
-.fn_ebz_dashboard_search_dd .select2-container .select2-chosen {
- line-height: 30px;
-}
-
-.fn_ebz_dashboard_search_dd .select2-container .select2-choice .select2-arrow b:after,.select2-container.select2-container-disabled .select2-choice .select2-arrow b:after
- {
- height: 30px;
- line-height: 30px;
-}
-
-.fn_ebz_dashboard_search_dd .select2-results {
- margin: -4px 0 0;
-}
-
-.fn_ebz_dashboard_search_dd .select2-dropdown-open .select2-choice {
- border-top-right-radius: 0 !important;
-}
-
-.fn_ebz_dashboard_search_dd .select2-container .select2-choice .select2-arrow
- {
- border-top-right-radius: 0 !important;
-}
-
-.fn_ebz_dashboard_search_button .button {
- padding: 6px;
- border-bottom-left-radius: 0px;
- border-top-left-radius: 0px;
-}
-
-.fn_ebz_dashboard_input {
- background: white !important;
- border-radius: 0 0 0 0 !important;
- font-family: Arial !important;
- height: 30px !important;
- border-left-width: 0px !important;
- padding-bottom: 9px !important;
-}
-/*************************************************************************************************/
-/********************************* following is for location Manage ****************************/
-/*************************************************************************************************/
-.ebz_location_manage tr.z-listitem-seld .z-listcell-cnt,.ebz_location_manage tr.z-listitem-over-seld .z-listcell-cnt,.ebz_location_manage tr.z-listitem-over .z-listcell-cnt
- {
- color: black;
-}
-
-.ebz_location_manage div.z-listbox-header th.z-auxheader {
- border: none;
-}
-
-.ebz_location_manage div.z-listbox-header div.z-auxheader-cnt {
- padding-bottom: 0;
-}
-
-.ebz_location_manage div.z-listbox-footer .z-listfooter,.ebz_location_manage div.z-listbox-footer
- {
- background: none;
- border: none;
-}
-
-.ebz_location_manage div.z-listbox-footer table {
- margin: 0;
-}
-
-/*************************************************************************************************/
-/********************************* following is for CallFowardAdd ****************************/
-/*************************************************************************************************/
-.myhlayout .z-hlayout-inner {
- vertical-align: middle;
-}
-
-.myhlayout {
- position: relative;
- left: 55px;
-}
-
-/* div.tile{
- display: table-cell;
- position: relative;
- height:50%;
- border: 1px solid grey;
- border-radius: 15px;
-}
-div.tile-content{
- margin: 0;
- padding: 20px 20px 100px 20px;
- height:100%;
-}
-div.tile.without_save_btn .tile-content{
- padding-bottom: 20px;
-}
-div.detail{
- padding-left:5%;
- width: 100%;
- height:100%;
- display: table;
- table-layout: fixed;
- border-spacing: 5px;
-}
-div.detail-row{
- display:table-row;
- width:100%;
- height:100%;
-} */
-.right-bottom {
- position: absolute;
- right: 20px;
- top: 40px;
-}
-
-.lred .tags__item--color.tags__item .tags__item--color-icon {
- background: red;
- border-color: red;
- z-index: 0;
-}
-
-.lred .tags__item.tags__item--color {
- border: none;
-}
-
-.lred .tags__item.tags__item--color:active {
- background: none;
-}
-
-.lgreen .tags__item--color.tags__item .tags__item--color-icon {
- background: #118817;
- border-color: #118817;
- z-index: 0;
-}
-
-.lgreen .tags__item.tags__item--color {
- border: none;
-}
-
-.lgreen .tags__item.tags__item--color:active {
- background: none;
-}
-
-ul.tab {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-ul.tab li {
- float: left;
- border: 1px solid #000;
- border-bottom-width: 0;
- margin: 3px 3px 0px 3px;
- padding: 5px 5px 0px 5px;
- background-color: #CCC;
- color: #696969;
- cursor: pointer;
-}
-
-ul.tab li.active {
- background-color: #FFF;
- color: #000;
-}
-
-a.info-link:before {
- content: url(../images/info_blue.jpg);
- margin: 0;
-}
-
-table.tableSection {
- display: table;
- width: 100%;
-}
-
-table.tableSection thead,table.tableSection tbody {
- float: left;
- width: 100%;
-}
-
-table.tableSection tbody {
- overflow: auto;
- overflow-x: hidden;
-}
-
-table.tableSection tr {
- width: 100%;
- display: table;
- text-align: left;
-}
-
-.custom-file-input::-webkit-file-upload-button {
- visibility: hidden;
-}
-
-.custom-file-input::before {
- content: 'Browse';
- background-color: #067AB4;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- display: inline-block;
- height: 30px;
- padding-left: 10px;
- padding-right: 10px;
- padding-top: 5px;
- font-size: 14px;
- text-align: center;
- border: 0px;
- cursor: pointer;
- color: rgba(255, 255, 255, 1);
- margin-top: 5px;
- margin-bottom: 5px;
- margin_right: 5px
-}
-
-.custom-file-input:hover::before {
- border-color: black;
-}
-
-.custom-file-input:active::before {
- background: -webkit-linear-gradient(top, #e3e3e3, #f9f9f9);
-}
-
-.ebz_menu_anchorMenuDiv {
- position: absolute;
- display: none;
- margin-top: 0px;
- background-color: white;
- width: 955px;
- border: 1px solid;
- border-right: 0px;
- color: rgb(211, 211, 211);
-}
-
-.ebz_menu_anchorMenuDiv2 {
- background-color: white;
- width: 130px;
- display: true;
- border: 1px solid;
- color: rgb(211, 211, 211);
- float: right;
- margin-top: -29px;
- box-shadow: 10px 10px 5px #888888;
- height: 94vh;
- position: relative;
- z-index: 1;
- border-radius: 8px;
-}
-
-.ebz_menu_anchorHead2 {
- font-size: 18px;
-}
-
-.ebz_menu_meunIcon_div {
- width: 1029px;
- position: relative;
- z-index: 2;
-}
-
-.ebz_menu_anchorMenu_div {
- width: 1230px;
-}
-
-.ebz_menu_anchorIcon {
- margin-top: 10px;
- font-size: 35px;
-}
-
-.ebz_menu_anchorIcon2 {
- font-size: 35px;
-}
-
-.ebz_menu_anchorIconAndHead {
- float: left;
- margin-left: 40px;
- width: 125px;
- height: 95px;
-}
-
-.ebz_menu_anchorIconAndHead2 {
- margin-top: 20px;
- margin-bottom: 20px;
-}
-
-.ebz_menu_userItems {
- text-transform: none;
- line-height: 10px;
- font-weight: 100;
- color: black;
-}
-
-.ebz_menu_userItemsValue {
- color: #666666;
-}
-
-.ebz_menu_secondLevelOption {
- font-size: 18px;
- color: #666666;
- margin-left: auto;
- margin-right: auto;
- float: left;
-}
-
-.ebz_menu_thirdLevelOptionHeader a {
- color: black;
- font-weight: bold;
- font-size: 12px;
-}
-
-.ebz_menu_thirdLevelOptionHeader {
- margin-top: 25px;
- float: left;
- width: 180px;
-}
-
-.ebz_menu_userMenuInfoDiv {
- margin-top: -252px;
- background-color: white;
- margin-left: auto;
- height: 252px;
- width: 207px;
- display: block;
- border: 1px solid;
- color: rgb(211, 211, 211);
-}
-
-.ebz_menu_userMenuLogoutDiv {
- margin-top: 0px;
- margin-left: 441px;
- background-color: rgb(250, 250, 250);
- height: 252px;
- width: 125px;
- display: true;
- border: 1px solid;
- border-right: 0px;
- color: rgb(211, 211, 211);
-}
-
-.ebz_menu_navBtn a {
- position: relative;
- font-size: 18px;
- color: white;
- font-size: 18px;
- -webkit-transition-property: position, color; /* Safari */
- -webkit-transition-duration: 5s; /* Safari */
- transition-property: position, color;
- transition-duration: 5s;
-}
-
-.ebz_menu_navBtn a:hover {
- position: relative;
- bottom: 2px;
- color: rgb(191, 213, 224);
-}
-
-.ebz_search_directory_phone_detail .phoneDetail {
- display: inline-block;
- margin-left: 20px;
- margin-bottom: 20px;
-}
-
-.ebz_search_directory_phone_detail .phoneDetailInside .colsize {
- width: 180px;
- height: 45px;
- padding: 0px;
-}
-
-.ebz_search_directory_phone_detail .phoneDetailInside {
- border: 1px solid;
- width: 400px;
- height: 250px;
- background: white;
-}
-
-.ebz_search_button {
- color: gray;
- -webkit-border-radius: 6px;
- -moz-border-radius: 6px;
- border-radius: 6px;
- height: 32px;
- width: 32px;
- background: white;
- background-repeat: no-repeat;
- background-position: center;
- margin-top: 0px;
-}
-
-.ebz_helpfulInfo {
- border-style: solid;
- border-width: 1px;
- margin-bottom: 50px;
-}
-
-.ebz_helpfulInfo .helpfulInfoContent {
- margin-left: 10px;
- margin-top: 10px;
-}
-
-.ebz_helpfulInfo .helpfulInfoTable {
- width: 340px;
- margin-left: 10px;
- display: inline-flex;
-}
-
-.ebz_helpfulInfo .helpfulInfoTableHeight {
- height: 250px;;
-}
-
-.ebz_bulk_edit {
- margin-top: 20px;
-}
-
-.ebz_bulk_edit .content {
- margin-top: 20px;
-}
-
-.form-field,.form-field-input-container {
- width: 210px !important;
- margin-right: 20px;
-}
-
-.form-field__square .select2-container .select2-choice,.form-field__square select,.form-field__square
- {
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- border-radius: 0;
-}
-
-.form-field__square.left_round_border .select2-container .select2-choice,.form-field__square.left_round_border select,.form-field__square.left_round_border div,.form-field__glued.form-field__square.left_round_border input[type="text"]
- {
- -webkit-border-radius: 5px 0px 0px 5px;
- -moz-border-radius: 5px 0px 0px 5px;
- border-radius: 5px 0px 0px 5px;
-}
-
-.form-field__square.right_round_border .select2-container .select2-choice,.form-field__square.right_round_border select,.form-field__square.right_round_border div,.form-field__glued.form-field__square.right_round_border input[type="text"]
- {
- -webkit-border-radius: 0px 5px 5px 0px;
- -moz-border-radius: 0px 5px 5px 0px;
- border-radius: 0px 5px 5px 0px;
-}
-
-.form-field__glued.form-field__square {
- margin-right: -5px;
-}
-
-.form-field__glued.form-field__square {
- vertical-align: top;
-}
-
-.form-field__glued.form-field__square input[type=text],.form-field__glued.form-field__square select
- {
- margin-top: 0;
-}
-
-div.hide-password-placeholder>div.form-field>label.form-field__label.form-field__label--show,div.hide-password-placeholder>div.form-field>label.form-field__label.form-field__label--hide
- {
- visibility: hidden;
-}
-
-.col-md-18.content div.fn-ebz-container {
- margin-top: 14px;
-}
-
-.col-md-18.content div.fixed-in-row {
- position: fixed;
- top: 115px;
- z-index: 95;
- width: 725px;
-}
-
-.col-md-18.content div.fixed-in-row {
- text-align: right;
-}
-
-.col-md-18.content .size-onefourth,.form-field__glued.size-onefourth {
- width: 25%;
-}
-
-.voiceAndCalllog {
- display: none;
- position: relative;
- margin-left: 5px;
-}
-
-.loadingId {
- position: fixed;
- top: 50%;
- right: 50%;
- z-index: 101;
-}
-
-#messagingDashboard .widgetBody {
- border: 1px solid #d3d3d3;
- overflow: hidden
-}
-
-#messagingDashboard .widgetHeader {
- height: 50px !important;
- border: 1px solid #d3d3d3;
- border-bottom: 0;
- background-color: #e5e5e5;
- padding-right: 20px;
- width: 100%;
- white-space: nowrap;
- text-overflow: ellipsis;
- z-index: 1;
- -webkit-border-radius: 2px 2px 0 0;
- -moz-border-radius: 2px 2px 0 0;
- -ms-border-radius: 2px 2px 0 0;
- -o-border-radius: 2px 2px 0 0;
- border-radius: 2px 2px 0 0;
- behavior: url(/ebiz/dashboard/web/common/css/pie/PIE.htc );
- position: relative
-}
-
-#messagingDashboard .widgetHeader .widgetHeaderContent {
- line-height: 44px;
- font-family: clearviewatt;
- font-size: 18px;
- color: #444
-}
-
-#messagingDashboard .widgetHeader .widgetSubHeaderContent {
- position: absolute;
- top: 29.5px;
- left: 18px;
- font-family: clearviewatt;
- font-size: 12px;
- color: #444
-}
-
-#messagingDashboard input[type="text"].fn-ebz-text {
- width: 150px;
- margin-top: 0;
-}
-
-#messagingDashboard div.without_save_btn {
- display: table-cell;
-}
-
-#messagingDashboard .content-summary {
- margin-top: 20px;
- margin-right: 50px;
-}
-
-.appBody {
- background-color: rgb(242, 242, 242)
-}
-
-.att-drawer {
- z-index: 997 !important;
-}
-
-.secondaryMenuContainer {
- z-index: 1000;
-}
-
-.appContent {
- margin-left: 50px;
-
- display: inline-block;
- float: left;
-}
-
-.appLeftMenu{
- display: inline-block;
- float: left;
- width:200px;
- height:1px;
-
-}
-
-.appLeftMenu .appLeftMenuDiv{
- position: relative;
- color: black;
- top: 70px;
-}
-
-.appLeftMenu .appLeftMenuAccordDiv{
- margin-left:10px;
- margin-right:10px;
-
- }
-.appFooter{
- display: inline-block;
- width:100%
-}
-.drawer-backdrop{
- position:relative !important;
-}
-
-.license-notification{
- position:fixed;
- top:60px;
- right:20px;
- z-index: 999;
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/images/no_favorites_star.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/images/no_favorites_star.png
deleted file mode 100644
index 4db05403..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/images/no_favorites_star.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/attHeaderSnippet.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/attHeaderSnippet.js
deleted file mode 100644
index 2c0dfc37..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/attHeaderSnippet.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Popup Box function */
-(function(){
-
- $.fn.popbox = function(options){
- settings = $.extend({
- selector : this.selector,
- open : '.openpopbox',
- box : '.box1',
- arrow : '.arrow',
- arrow_border : '.arrow-border',
- close : '.close'
- }, options);
-
- var methods = {
- open: function(event){
- event.preventDefault();
- var pop = $(this);
- var box = $(this).parent().find(settings['box']);
- box.find(settings['arrow']).css({'left': box.width()/2 - 10 + 46});
- box.find(settings['arrow_border']).css({'left': box.width()/2 - 10 - 63});
- if(box.css('display') == 'block'){
- /* methods.close();
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- if($(window).scrollTop() > 20){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };*/
- $('.box1').fadeIn('slow');
- } else {
- $('.chatBox').fadeOut('fast');
- $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- if(box.attr('target') == 'auth'){
- box.find(settings['arrow']).css({'left': box.width()/2 + 36});
- box.css({'display': 'block', 'top': 0, 'left': ((pop.parent().parent().width()/2) -box.width()/2 ) - 90});
- }
- else{
- box.find(settings['arrow']).css({'left': box.width()/2 - 42});
- box.css({'display': 'block', 'top': 0, 'left': ((pop.parent().parent().width()/2) -box.width()/2-15 )});
- box.find("#header_login_id").focus();
- box.find('#header_password').val('');
- }
- }
- },
-
- close: function(){
- $(settings['box']).fadeOut("fast");
- }
- };
-
- $(document).bind('keyup', function(event){
- if(event.keyCode == 27){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- if($(window).scrollTop() > 20){
- // setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };
- methods.close();
- }
- });
- // Close chat-box and popup on clicking out of chat-box
- $(document).bind('click', function(event){
- if(!($(event.target).closest('.chatBox').length || $(event.target).hasClass('chatIcon') || $(event.target).closest(settings['selector']).length)){
- methods.close();
- if ($("#actionsDropDown").css('z-index')=='-999'){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- }
- if($(window).scrollTop() > 20){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };
-
- $('.chatBox').fadeOut('fast');
-
- }
- });
-
- return this.each(function(){
-
- $(this).css({'width': $(settings['box']).width()}); // Width needs to be set otherwise popbox will not move when window resized.
- $(settings['open'], this).bind('click', methods.open);
- $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- $(settings['open'], this).parent().find(settings['close']).bind('click', function(event){
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- methods.close();
- });
- });
- }
-
-}).call(this);
-
-
-$('.popbox').popbox();
-
-$(function(){
- var displayName = "";
- if($("#reg-fn-ln-id").length > 0){
- var fnln = $("#reg-fn-ln-id").val().length;
- if(fnln > 0){
- var fnVar = $("#reg-fname-id").val();
- var lnVar = $("#reg-lname-id").val();
- var numChars = 13;
- var nameLen = fnVar.length + lnVar.length + 1; // 1 for space between the first name and the last name
- if(fnVar != " " && lnVar != " "){
- if(nameLen <= numChars){
- displayName = fnVar+" "+lnVar;
- }else if(nameLen <= (numChars * 2)){
- displayName = fnVar+"<br/>"+lnVar;
- }else
- {
- if(fnVar.length < numChars && lnVar.length > numChars){ //Smaller first name and longer last name
- displayName = fnVar+"<br/>"+lnVar.substring(0,numChars-1)+"...";
- }
-
- if(fnVar.length >= numChars ){ //Longer first name
- // 2 = 1 for elipses, 1 for space between the first name and last name
- longLName = numChars - ((fnVar.substring(numChars,fnVar.length)).length + 2);
- displayName = fnVar.substring(0,numChars)+"<br/>"+fnVar.substring(numChars,fnVar.length)+" "+lnVar.substring(0,longLName)+"...";
- }
- }
- }
- else{
- displayName = fnVar+" "+lnVar;
- }
- }
-
- $("#reg-userName").html(displayName);
- }
-});
-
-/* ClickToChat ANONYMOUS FUNCTION DEFINITION *
- * =============================================== *
- * On clicking the chat icon displays the chat box */
-(function(){
-
- var chatbox = $('.chatBox');
-
- // var actionsDropDown = $('#actionsDropDown');
- var methods = {
- open: function(){chatbox.css('display','block');},
- close: function(){chatbox.fadeOut('fast');}
- };
- $('.chatIcon').click(function(){
- if (chatbox.css('display') == 'block'){
- methods.close();
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- if($(window).scrollTop() > 20){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };
- } else {
- $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- methods.open();
- $(settings['box']).fadeOut("fast");
- }
- });
-
- // Close chat-box on clicking cross icon
- $('.circle_close_chat').click(function(){
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- methods.close();
- if($(window).scrollTop() > 20){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };
- });
-
- // Close chat-box on Escape key press
- $(document).bind('keyup', function(event){
- if(event.keyCode == 27){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','999'); },200);
- methods.close();
- if($(window).scrollTop() > 20){
- setTimeout(function(){ $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999'); },200);
- //$(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- };
- }
- });
-
- // Close chat-box on clicking out of chat-box
- // $(document).bind('click', function(event){
-
- // console.log(event.target,"2");
- // if(!($(event.target).closest('.chatBox').length || $(event.target).hasClass('chatIcon'))) {
- // event.preventDefault();
- // // console.log($(event.target).closest(settings['selector']).length);
- // console.log($(event.target).closest('. ').length);
- // console.log($(event.target).hasClass('chatIcon'));
-
-
- // // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- // methods.close();
- // if ($("#actionsDropDown").css('z-index')=='-999') {
- // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- // };
- // // if (flag!="clicked") {
- // // if ($('.box').css('display') == 'block' || $('.chatBox').css('display') == 'block' ){
- // // $(".btn-panel-vertical,#actionsDropDown").css('z-index','-999');
- // // } else {
- // // $(".btn-panel-vertical,#actionsDropDown").css('z-index','999');
- // // }
- // // }
- // }
- // });
-
-})(); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/footer.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/footer.js
deleted file mode 100644
index 4cc2d2a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/js/footer.js
+++ /dev/null
@@ -1,110 +0,0 @@
-var feedbackText, pageAddress;
-(function ( $ ) {
- $(document).on('click', '.feedbackButtonDiv', function (e) {
- $(".feedbackSection").slideToggle(600, function(){
- if($(".feedbackButton").hasClass("closeFeedbackButton")) {
- $(".footerContainer .feedbackButton").html("Feedback<span class='icon-chevron-down'></span>");
- $(".footerContainer .feedbackButton").removeClass("closeFeedbackButton");
- } else {
- $(".footerContainer .feedbackButton").html("Close<span class='icon-chevron-up'></span>");
- $(".footerContainer .feedbackButton").addClass("closeFeedbackButton");
- $(".footerContainer .feedbackText").focus();
- }
-
- });
- });
-
- $(document).on('click', '.closeFeedback', function (e) {
- $(".feedbackSection").slideUp(600, function(){
-
- });
- });
-
- $(document).on('click keypress keyup blur paste','textarea[maxlength]', function(e) {
- var maxlength = $(this).attr('maxlength');
- var val = $(this).val();
-
- if (val.length > maxlength) {
- $(this).val(val.slice(0, maxlength));
- }
- });
-
- $(document).on('click', '.feedbackSubmitButton', function (e) {
- var feedbackTextTemp = $(".feedbackText").val();
- feedbackText = $.trim(feedbackTextTemp);
- var feedbackData = feedbackText;
- if (feedbackText != null && feedbackText != '') {
- $.ajax({
- type: "post",
- contentType :'application/json',
- dataType: 'json',
- data: feedbackData,
- url: "/ebiz/dashboard/feedback/createfeedback",
- success: function (data) {
- if (data.success) {
- $(".feedbackSection").slideUp(600, function() {
- $(".feedbackText").val("");
- $(".footerContainer .feedbackButton").html("Feedback<span class='icon-chevron-down'></span>");
- $(".footerContainer .feedbackButton").removeClass("closeFeedbackButton");
- $(".feedbackButtonDiv").slideUp(600);
- $(".readFeedBackMessage").text(data.feedBackMessage);
- $(".feedbackResultMsg, #feedbackResultDivider").slideDown(600);
- $(".readFeedBackMessage").focus();
- });
- } else if (typeof console == "object") {
-
- }
- },
- error: function () {
-
- }
- });
- } else {
- e.preventDefault();
- if (typeof console == 'object') {
- console.log("Invalid Input String");
- }
- }
-
- });
-
- // Click function definition for OK button in feedback success message
- $(document).on('click', '.feedbackMsgOKButton', function(e) {
- $(".feedbackResultMsg, #feedbackResultDivider").slideUp(600, function(){
- $(".readFeedBackMessage").text("");
- });
- $(".feedbackButtonDiv").slideDown(600, function() {
- $('.feedbackButton').focus();
- });
- });
-
-}( jQuery ));
-
-$(function() {
- var footerHeight = 0,
- footerTop = 0,
- $footer = $("#footer");
-
- positionFooter();
-
-
- function positionFooter() {
-
- footerHeight = $footer.height();
- footerTop = ($(window).scrollTop() + $(window).height() - footerHeight) + "px";
-
- if (($(document.body).height() + footerHeight) < $(window).height()) {
- $footer.addClass('stickyFooter')
- .animate({
- top: footerTop
- }, -1)
- } else {
- $footer.removeClass('stickyFooter');
- }
-
- }
-
- $(window)
- .scroll(positionFooter)
- .resize(positionFooter)
-}); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.js
deleted file mode 100644
index 95964973..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.js
+++ /dev/null
@@ -1,20451 +0,0 @@
-/**
-* FileName att-style-guide
-* Version 2.17.0
-* Build number 5c64ecd381d5984c483cdfaa078a1890
-* Date 11/23/2015
-*/
-
-(function(angular, window){
-angular.module("att.abs", ["att.abs.tpls", "att.abs.utilities","att.abs.position","att.abs.transition","att.abs.accordion","att.abs.alert","att.abs.boardStrip","att.abs.breadCrumbs","att.abs.buttons","att.abs.checkbox","att.abs.colorselector","att.abs.datepicker","att.abs.devNotes","att.abs.dividerLines","att.abs.dragdrop","att.abs.drawer","att.abs.message","att.abs.formField","att.abs.hourpicker","att.abs.iconButtons","att.abs.links","att.abs.loading","att.abs.modal","att.abs.pagination","att.abs.paneSelector","att.abs.tooltip","att.abs.popOvers","att.abs.profileCard","att.abs.progressBars","att.abs.radio","att.abs.scrollbar","att.abs.search","att.abs.select","att.abs.slider","att.abs.splitButtonDropdown","att.abs.splitIconButton","att.abs.stepSlider","att.abs.steptracker","att.abs.table","att.abs.tableMessages","att.abs.tabs","att.abs.tagBadges","att.abs.textOverflow","att.abs.toggle","att.abs.treeview","att.abs.typeAhead","att.abs.verticalSteptracker","att.abs.videoControls"]);
-angular.module("att.abs.tpls", ["app/scripts/ng_js_att_tpls/accordion/accordion.html","app/scripts/ng_js_att_tpls/accordion/accordion_alt.html","app/scripts/ng_js_att_tpls/accordion/attAccord.html","app/scripts/ng_js_att_tpls/accordion/attAccordBody.html","app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html","app/scripts/ng_js_att_tpls/alert/alert.html","app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html","app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html","app/scripts/ng_js_att_tpls/colorselector/colorselector.html","app/scripts/ng_js_att_tpls/datepicker/dateFilter.html","app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html","app/scripts/ng_js_att_tpls/datepicker/datepicker.html","app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html","app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html","app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html","app/scripts/ng_js_att_tpls/formField/creditCardImage.html","app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html","app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html","app/scripts/ng_js_att_tpls/links/readMore.html","app/scripts/ng_js_att_tpls/loading/loading.html","app/scripts/ng_js_att_tpls/modal/backdrop.html","app/scripts/ng_js_att_tpls/modal/tabbedItem.html","app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html","app/scripts/ng_js_att_tpls/modal/window.html","app/scripts/ng_js_att_tpls/pagination/pagination.html","app/scripts/ng_js_att_tpls/paneSelector/innerPane.html","app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html","app/scripts/ng_js_att_tpls/paneSelector/sidePane.html","app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html","app/scripts/ng_js_att_tpls/popOvers/popOvers.html","app/scripts/ng_js_att_tpls/profileCard/addUser.html","app/scripts/ng_js_att_tpls/profileCard/profileCard.html","app/scripts/ng_js_att_tpls/progressBars/progressBars.html","app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html","app/scripts/ng_js_att_tpls/search/search.html","app/scripts/ng_js_att_tpls/select/select.html","app/scripts/ng_js_att_tpls/select/textDropdown.html","app/scripts/ng_js_att_tpls/slider/maxContent.html","app/scripts/ng_js_att_tpls/slider/minContent.html","app/scripts/ng_js_att_tpls/slider/slider.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html","app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html","app/scripts/ng_js_att_tpls/steptracker/step-tracker.html","app/scripts/ng_js_att_tpls/steptracker/step.html","app/scripts/ng_js_att_tpls/steptracker/timeline.html","app/scripts/ng_js_att_tpls/steptracker/timelineBar.html","app/scripts/ng_js_att_tpls/steptracker/timelineDot.html","app/scripts/ng_js_att_tpls/table/attTable.html","app/scripts/ng_js_att_tpls/table/attTableBody.html","app/scripts/ng_js_att_tpls/table/attTableHeader.html","app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html","app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html","app/scripts/ng_js_att_tpls/tabs/floatingTabs.html","app/scripts/ng_js_att_tpls/tabs/genericTabs.html","app/scripts/ng_js_att_tpls/tabs/menuTab.html","app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html","app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html","app/scripts/ng_js_att_tpls/tabs/submenuTab.html","app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html","app/scripts/ng_js_att_tpls/toggle/demoToggle.html","app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html","app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html","app/scripts/ng_js_att_tpls/videoControls/photoControls.html","app/scripts/ng_js_att_tpls/videoControls/videoControls.html"]);
-angular.module('att.abs.utilities', [])
-
-.filter('unsafe',[ '$sce', function ($sce) {
- return function(val){
- return $sce.trustAsHtml(val);
- };
-}])
-
-.filter('highlight', function () {
- function escapeRegexp(queryToEscape) {
- return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
- }
- return function (matchItem, query, className) {
- return query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<span class=\"' + className + '\">$&</span>') : matchItem;
- };
-})
-
-.filter('attLimitTo', function() {
- return function(actualArray, _limit, _begin) {
- var finalArray = [];
- var limit = _limit;
- var begin = _begin;
- if(isNaN(begin)) {
- begin = 0;
- }
- if(actualArray && !isNaN(limit)) {
- finalArray = actualArray.slice(begin, begin+limit);
- } else {
- finalArray = actualArray;
- }
- return finalArray;
- };
-})
-
-.filter('startsWith', function() {
- if (typeof String.prototype.startsWith !== 'function') {
- // see below for better implementation!
- String.prototype.startsWith = function (str){
- return this.indexOf(str) === 0;
- };
- }
-
- return function(items, searchString) {
- if (searchString === undefined || searchString === "") {
- return items;
- }
-
- var filtered = [];
- angular.forEach(items, function(item) {
- if (item.title.toLowerCase().startsWith(searchString.toLowerCase())) {
- filtered.push(item);
- }
- });
- return filtered;
- };
-})
-
-.directive('attInputDeny', [function() {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function (scope, elem, attr, ctrl) {
- var regexExpression = null;
- attr.$observe('attInputDeny', function (value) {
- if (value) {
- regexExpression = new RegExp(value, 'g');
- }
- });
- elem.bind('input', function () {
- var inputString = ctrl.$viewValue && ctrl.$viewValue.replace(regexExpression, '');
- if (inputString !== ctrl.$viewValue) {
- ctrl.$setViewValue(inputString);
- ctrl.$render();
- scope.$apply();
- }
- });
- }
- };
-}])
-
-.directive('attAccessibilityClick', [function() {
- return {
- restrict: 'A',
- link: function (scope, elem, attr) {
- var keyCode = [];
- attr.$observe('attAccessibilityClick', function (value) {
- if (value) {
- keyCode = value.split(',');
- }
- });
- elem.bind('keydown', function (ev) {
- var keyCodeCondition = function(){
- var flag = false;
- if(!(ev.keyCode)){
- if(ev.which){
- ev.keyCode = ev.which;
- }
- else if(ev.charCode){
- ev.keyCode = ev.charCode;
- }
- }
- if((ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1)){
- flag = true;
- }
- return flag;
- };
- if(keyCode.length > 0 && keyCodeCondition()) {
- elem[0].click();
- ev.preventDefault();
- }
- });
- }
- };
-}])
-
-.directive('attElementFocus', [function() {
- return {
- restrict: 'A',
- link: function(scope, elem, attr) {
- scope.$watch(attr.attElementFocus, function (value) {
- if (value) {
- elem[0].focus();
- }
- });
- }
- };
-}])
-
-.directive('focusOn', ['$timeout',
- function ($timeout) {
- var checkDirectivePrerequisites = function (attrs) {
- if (!attrs.focusOn && attrs.focusOn !== '') {
- throw 'FocusOnCondition missing attribute to evaluate';
- }
- };
- return {
- restrict: 'A',
- link: function (scope, element, attrs) {
- checkDirectivePrerequisites(attrs);
-
- scope.$watch(attrs.focusOn, function (currentValue) {
- if(currentValue) {
- $timeout(function () {
- element[0].focus();
- });
- }
- });
- }
- };
- }
-])
-.constant('whenScrollEndsConstants', {
- 'threshold': 100,
- 'width': 0,
- 'height': 0
-})
-.directive('whenScrollEnds', function(whenScrollEndsConstants, $log) {
- return {
- restrict: 'A',
- link: function (scope, element, attrs) {
- /**
- * Exposed Attributes:
- * threshold - integer - number of pixels before scrollbar hits end that callback is called
- * width - integer - override for element's width (px)
- * height - integer - override for element's height (px)
- * axis - string - x/y for scroll bar axis
- */
- var threshold = parseInt(attrs.threshold, 10) || whenScrollEndsConstants.threshold;
-
- if (!attrs.axis || attrs.axis === '') {
- $log.warn('axis attribute must be defined for whenScrollEnds.');
- return;
- }
-
- if (attrs.axis === 'x') {
- visibleWidth = parseInt(attrs.width, 10) || whenScrollEndsConstants.width;
- if (element.css('width')) {
- visibleWidth = element.css('width').split('px')[0];
- }
-
- element[0].addEventListener('scroll', function() {
- var scrollableWidth = element.prop('scrollWidth');
- if (scrollableWidth === undefined) {
- scrollableWidth = 1;
- }
- var hiddenContentWidth = scrollableWidth - visibleWidth;
-
- if (hiddenContentWidth - element[0].scrollLeft <= threshold) {
- /* Scroll almost at bottom, load more rows */
- scope.$apply(attrs.whenScrollEnds);
- }
- });
- } else if (attrs.axis === 'y') {
- visibleHeight = parseInt(attrs.height, 10) || whenScrollEndsConstants.height;
- if (element.css('width')) {
- visibleHeight = element.css('height').split('px')[0];
- }
-
- element[0].addEventListener('scroll', function() {
- var scrollableHeight = element.prop('scrollHeight');
- if (scrollableHeight === undefined) {
- scrollableHeight = 1;
- }
- var hiddenContentHeight = scrollableHeight - visibleHeight;
-
- if (hiddenContentHeight - element[0].scrollTop <= threshold) {
- /* Scroll almost at bottom, load more rows */
- scope.$apply(attrs.whenScrollEnds);
- }
- });
- }
- }
- };
-})
-
-.directive("validImei", function(){
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function(scope, ele, attrs, ctrl)
- {
- ctrl.$parsers.unshift(function(value)
- {
- if(value){
- scope.valid = false;
- if (!isNaN(value) && value.length === 15)
- {
- var sumImeiVal = 0;
- var posIMEI = [];
- for (var imeiIndex=0; imeiIndex<15; imeiIndex++)
- {
- posIMEI[imeiIndex] = parseInt(value.substring(imeiIndex,imeiIndex + 1),10);
- if (imeiIndex % 2 !== 0)
- {
- posIMEI[imeiIndex] = parseInt((posIMEI[imeiIndex] * 2),10);
- }
- if (posIMEI[imeiIndex] > 9)
- {
- posIMEI[imeiIndex] = parseInt((posIMEI[imeiIndex] % 10),10) + parseInt((posIMEI[imeiIndex] / 10),10);
- }
- sumImeiVal=sumImeiVal+parseInt((posIMEI[imeiIndex]),10);
- }
-
- if((sumImeiVal % 10) === 0)
- {
- scope.valid = true;
- }
- else
- {
- scope.valid = false;
- }
- }
- else
- {
- scope.valid = false;
- }
- ctrl.$setValidity('invalidImei', scope.valid);
- }
- return scope.valid ? value : undefined;
- });
- }
- };
-})
-
-.directive("togglePassword", function(){
- return{
- restrict:'A',
- transclude:false,
- link: function(scope, element, attr, ctrl)
- {
- element.bind("click", function()
- {
- var ipwd = attr.togglePassword;
- element[0].innerHTML = element[0].innerHTML === "Show" ? "Hide" : "Show";
- var e = angular.element(document.querySelector('#' + ipwd))[0].type;
- angular.element(document.querySelector('#' + ipwd))[0].type = e === "password"? "text" : "password";
-
- });
-
- }
- };
-})
-
-.factory('events', function(){
- var _stopPropagation = function(evt){
- if(evt.stopPropagation) {
- evt.stopPropagation();
- } else {
- evt.returnValue = false;
- }
- };
- var _preventDefault = function(evt) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- return {
- stopPropagation: _stopPropagation,
- preventDefault: _preventDefault
- };
-})
-
-.factory('$documentBind', ['$document', '$timeout', function ($document, $timeout) {
- var _click = function (flag, callbackFunc, scope) {
- scope.$watch(flag, function (val) {
- $timeout(function () {
- if (val) {
- $document.bind('click', callbackFunc);
- } else {
- $document.unbind('click', callbackFunc);
- }
- });
- });
- };
-
- var _event = function (event, flag, callbackFunc, scope, timeoutFlag, timeoutValue) {
- if (timeoutFlag) {
- if (!(timeoutValue)) {
- timeoutValue = 0;
- }
- scope.$watch(flag, function (newVal, oldVal) {
- if (newVal !== oldVal) {
- $timeout(function () {
- if (newVal) {
- $document.bind(event, callbackFunc);
- } else {
- $document.unbind(event, callbackFunc);
- }
- }, timeoutValue);
- }
- });
- } else {
- scope.$watch(flag, function (newVal, oldVal) {
- if (newVal !== oldVal) {
- if (newVal) {
- $document.bind(event, callbackFunc);
- } else {
- $document.unbind(event, callbackFunc);
- }
- }
- });
- }
- };
-
- return {
- click: _click,
- event: _event
- };
-}])
-
-.factory('DOMHelper', function() {
-
- function isTabable(node) {
- var element = angular.element(node);
- var hasTabindex = (parseInt(element.attr('tabindex'), 10) >= 0) ? true : false;
- var tagName = element[0].tagName.toUpperCase();
-
- if (hasTabindex || tagName === 'A' || tagName === 'INPUT' || tagName === 'TEXTAREA') {
- return !(element[0].disabled || element[0].readOnly);
- }
- return false;
- }
-
- function isValidChild(child) {
- return child.nodeType == 1 && child.nodeName != 'SCRIPT' && child.nodeName != 'STYLE';
- }
-
- function traverse(obj) {
- var obj = obj || document.getElementsByTagName('body')[0];
- if (isValidChild(obj) && isTabable(obj)) {
- return obj;
- }
- if (obj.hasChildNodes()) {
- var child = obj.firstChild;
- while(child) {
- var res = traverse(child);
- if(res){
- return res;
- }
- else{
- child = child.nextSibling;
- }
- }
- }
- else{
- return undefined;
- }
- }
-
- var _firstTabableElement = function(el) {
- /* This will return the first tabable element from the parent el */
- var elem = el;
- if (el.hasOwnProperty('length')) {
- elem = el[0];
- }
-
- return traverse(elem);
- };
-
- return {
- firstTabableElement: _firstTabableElement
- };
-})
-
-.factory('keymap', function(){
- return {
- KEY:{
- TAB: 9,
- ENTER: 13,
- ESC: 27,
- SPACE: 32,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- SHIFT: 16,
- CTRL: 17,
- ALT: 18,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- HOME: 36,
- END: 35,
- BACKSPACE: 8,
- DELETE: 46,
- COMMAND: 91
- },
- MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'"
- },
- isControl: function (e) {
- var k = e.keyCode;
- switch (k) {
- case this.KEY.COMMAND:
- case this.KEY.SHIFT:
- case this.KEY.CTRL:
- case this.KEY.ALT:
- return true;
- default:;
- }
-
- if (e.metaKey) {
- return true;
- }
-
- return false;
- },
- isFunctionKey: function (k) {
- k = k.keyCode ? k.keyCode : k;
- return k >= 112 && k <= 123;
- },
- isVerticalMovement: function (k){
- return ~[this.KEY.UP, this.KEY.DOWN].indexOf(k);
- },
- isHorizontalMovement: function (k){
- return ~[this.KEY.LEFT, this.KEY.RIGHT, this.KEY.BACKSPACE, this.KEY.DELETE].indexOf(k);
- },
- isAllowedKey: function (k){
- return (~[this.KEY.SPACE, this.KEY.ESC, this.KEY.ENTER].indexOf(k)) || this.isHorizontalMovement(k) || this.isVerticalMovement(k);
- }
- };
-})
-
-.factory('keyMapAc', function(){
- return {
- keys:{ "32":" ", "33":"!", "34":"\"", "35":"#", "36":"$", "37":"%", "38":"&", "39":"'"
- , "40":"(", "41":")", "42":"*", "43":"+", "44":",", "45":"-", "46":".", "47":"\/", "58":":"
- , "59":";", "60":"<", "61":"=", "62":">", "63":"?", "64":"@", "91":"[", "92":"\\", "93":"]"
- , "94":"^", "95":"_", "96":"`", "123":"{", "124":"|", "125":"}", "126":"~"
- },
- keyRange:{"startNum":"48","endNum":"57","startSmallLetters":"97","endSmallLetters":"122"
- ,"startCapitalLetters":"65","endCapitalLetters":"90"},
- allowedKeys:{TAB:8, BACKSPACE:9, DELETE:16}
- };
-})
-
-.factory('$attElementDetach', function () {
- var _detach = function (element) {
- if (element && element.parentNode) {
- element.parentNode.removeChild(element);
- }
- };
- return _detach;
-})
-
-.factory('$ieVersion', function () {
- var ie = null;
-
- var loadIEVersion = function () {
- var isIE10 = (eval("/*@cc_on!@*/false") && document.documentMode === 10);
- if (isIE10) {
- return 10;
- }
- var v = 3,
- div = document.createElement('div'),
- all = div.getElementsByTagName('i');
- do {
- div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
- } while (all[0]);
- return v > 4 ? v : undefined;
- };
-
- return function () {
- if (ie===null) {
- ie = loadIEVersion();
- }
- return ie;
- };
-});
-(function () {
- String.prototype.toSnakeCase = function () {
- return this.replace(/([A-Z])/g, function ($1) {
- return "-" + $1.toLowerCase();
- });
- };
- var concat = function (character, times) {
- character = character || '';
- times = (!isNaN(times) && times) || 0;
- var finalChar = '';
- for (var i = 0; i < times; i++) {
- finalChar += character;
- }
- return finalChar;
- };
-
- // direction: true for left and false for right
- var pad = function (actualString, width, character, direction) {
- actualString = actualString || '';
- width = (!isNaN(width) && width) || 0;
- character = character || '';
- if (width > actualString.length) {
- if (direction) {
- return concat(character, (width - actualString.length)) + actualString;
- } else {
- return actualString + concat(character, (width - actualString.length));
- }
- }
- return actualString;
- };
-
- String.prototype.lPad = function (width, character) {
- return pad(this, width, character, true);
- };
-
- String.prototype.rPad = function (width, character) {
- return pad(this, width, character, false);
- };
-
- if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (val) {
- for (var index = 0; index < this.length; index++) {
- if (this[index] === val) {
- return index;
- }
- }
- return -1;
- };
- }
-})();
-
-angular.module('att.abs.position', [])
-
-.factory('$position', ['$document', '$window', function ($document, $window) {
- function getStyle(el, cssprop) {
- if (el.currentStyle) { //IE
- return el.currentStyle[cssprop];
- } else if ($window.getComputedStyle) {
- return $window.getComputedStyle(el)[cssprop];
- }
- // finally try and get inline style
- return el.style[cssprop];
- }
-
- /**
- * Checks if a given element is statically positioned
- * @param element - raw DOM element
- */
- function isStaticPositioned(element) {
- return (getStyle(element, "position") || 'static') === 'static';
- }
-
- /**
- * returns the closest, non-statically positioned parentOffset of a given element
- * @param element
- */
- var parentOffsetEl = function (element) {
- var docDomEl = $document[0];
- var offsetParent = element.offsetParent || docDomEl;
- while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
- offsetParent = offsetParent.offsetParent;
- }
- return offsetParent || docDomEl;
- };
-
- return {
- /**
- * Provides read-only equivalent of jQuery's position function:
- * http://api.jquery.com/position/
- */
- position: function (element) {
- var elBCR = this.offset(element);
- var offsetParentBCR = {
- top: 0,
- left: 0
- };
- var offsetParentEl = parentOffsetEl(element[0]);
- if (offsetParentEl !== $document[0]) {
- offsetParentBCR = this.offset(angular.element(offsetParentEl));
- offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
- offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
- }
-
- return {
- width: element.prop('offsetWidth'),
- height: element.prop('offsetHeight'),
- top: elBCR.top - offsetParentBCR.top,
- left: elBCR.left - offsetParentBCR.left
- };
- },
-
- /**
- * Provides read-only equivalent of jQuery's offset function:
- * http://api.jquery.com/offset/
- */
- offset: function (element) {
- var boundingClientRect = element[0].getBoundingClientRect();
- return {
- width: element.prop('offsetWidth'),
- height: element.prop('offsetHeight'),
- top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
- left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
- };
- }
- };
-}])
-
-.factory('$isElement', [function () {
- var isElement = function (currentElem, targetElem, alternateElem) {
- if (currentElem[0] === targetElem[0]) {
- return true;
- } else if (currentElem[0] === alternateElem[0]) {
- return false;
- } else {
- return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
- }
- };
-
- return isElement;
-}])
-
-.directive('attPosition', ['$position', function ($position) {
- return {
- restrict: 'A',
- link: function (scope, elem, attr) {
- scope.$watchCollection(function () {
- return $position.position(elem);
- }, function (value) {
- scope[attr.attPosition] = value;
- });
- }
- };
-}]);
-
-/*!
- * VERSION: 1.7.3
- * DATE: 2014-01-14
- * UPDATES AND DOCS AT: http://www.greensock.com
- *
- * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
- * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
- * Club GreenSock members, the software agreement that was issued with your membership.
- *
- * @author: Jack Doyle, jack@greensock.com
- **/
-(window._gsQueue || (window._gsQueue = [])).push( function() {
-
- "use strict";
-
- var _doc = document.documentElement,
- _window = window,
- _max = function(element, axis) {
- var dim = (axis === "x") ? "Width" : "Height",
- scroll = "scroll" + dim,
- client = "client" + dim,
- body = document.body;
- return (element === _window || element === _doc || element === body) ? Math.max(_doc[scroll], body[scroll]) - (_window["inner" + dim] || Math.max(_doc[client], body[client])) : element[scroll] - element["offset" + dim];
- },
-
- ScrollToPlugin = window._gsDefine.plugin({
- propName: "scrollTo",
- API: 2,
- version:"1.7.3",
-
- //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
- init: function(target, value, tween) {
- this._wdw = (target === _window);
- this._target = target;
- this._tween = tween;
- if (typeof(value) !== "object") {
- value = {y:value}; //if we don't receive an object as the parameter, assume the user intends "y".
- }
- this._autoKill = (value.autoKill !== false);
- this.x = this.xPrev = this.getX();
- this.y = this.yPrev = this.getY();
- if (value.x != null) {
- this._addTween(this, "x", this.x, (value.x === "max") ? _max(target, "x") : value.x, "scrollTo_x", true);
- this._overwriteProps.push("scrollTo_x");
- } else {
- this.skipX = true;
- }
- if (value.y != null) {
- this._addTween(this, "y", this.y, (value.y === "max") ? _max(target, "y") : value.y, "scrollTo_y", true);
- this._overwriteProps.push("scrollTo_y");
- } else {
- this.skipY = true;
- }
- return true;
- },
-
- //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
- set: function(v) {
- this._super.setRatio.call(this, v);
-
- var x = (this._wdw || !this.skipX) ? this.getX() : this.xPrev,
- y = (this._wdw || !this.skipY) ? this.getY() : this.yPrev,
- yDif = y - this.yPrev,
- xDif = x - this.xPrev;
-
- if (this._autoKill) {
- //note: iOS has a bug that throws off the scroll by several pixels, so we need to check if it's within 7 pixels of the previous one that we set instead of just looking for an exact match.
- if (!this.skipX && (xDif > 7 || xDif < -7) && x < _max(this._target, "x")) {
- this.skipX = true; //if the user scrolls separately, we should stop tweening!
- }
- if (!this.skipY && (yDif > 7 || yDif < -7) && y < _max(this._target, "y")) {
- this.skipY = true; //if the user scrolls separately, we should stop tweening!
- }
- if (this.skipX && this.skipY) {
- this._tween.kill();
- }
- }
- if (this._wdw) {
- _window.scrollTo((!this.skipX) ? this.x : x, (!this.skipY) ? this.y : y);
- } else {
- if (!this.skipY) {
- this._target.scrollTop = this.y;
- }
- if (!this.skipX) {
- this._target.scrollLeft = this.x;
- }
- }
- this.xPrev = this.x;
- this.yPrev = this.y;
- }
-
- }),
- p = ScrollToPlugin.prototype;
-
- ScrollToPlugin.max = _max;
-
- p.getX = function() {
- return (!this._wdw) ? this._target.scrollLeft : (_window.pageXOffset != null) ? _window.pageXOffset : (_doc.scrollLeft != null) ? _doc.scrollLeft : document.body.scrollLeft;
- };
-
- p.getY = function() {
- return (!this._wdw) ? this._target.scrollTop : (_window.pageYOffset != null) ? _window.pageYOffset : (_doc.scrollTop != null) ? _doc.scrollTop : document.body.scrollTop;
- };
-
- p._kill = function(lookup) {
- if (lookup.scrollTo_x) {
- this.skipX = true;
- }
- if (lookup.scrollTo_y) {
- this.skipY = true;
- }
- return this._super._kill.call(this, lookup);
- };
-
-}); if (window._gsDefine) { window._gsQueue.pop()(); }
-/*!
- * VERSION: 1.12.1
- * DATE: 2014-06-26
- * UPDATES AND DOCS AT: http://www.greensock.com
- *
- * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
- *
- * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
- * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
- * Club GreenSock members, the software agreement that was issued with your membership.
- *
- * @author: Jack Doyle, jack@greensock.com
- **/
-
-(window._gsQueue || (window._gsQueue = [])).push( function() {
-
- "use strict";
-
- window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
-
- var _slice = [].slice,
- TweenMax = function(target, duration, vars) {
- TweenLite.call(this, target, duration, vars);
- this._cycle = 0;
- this._yoyo = (this.vars.yoyo === true);
- this._repeat = this.vars.repeat || 0;
- this._repeatDelay = this.vars.repeatDelay || 0;
- this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
- this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
- },
- _tinyNum = 0.0000000001,
- TweenLiteInternals = TweenLite._internals,
- _isSelector = TweenLiteInternals.isSelector,
- _isArray = TweenLiteInternals.isArray,
- p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
- _blankArray = [];
-
- TweenMax.version = "1.12.1";
- p.constructor = TweenMax;
- p.kill()._gc = false;
- TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
- TweenMax.getTweensOf = TweenLite.getTweensOf;
- TweenMax.lagSmoothing = TweenLite.lagSmoothing;
- TweenMax.ticker = TweenLite.ticker;
- TweenMax.render = TweenLite.render;
-
- p.invalidate = function() {
- this._yoyo = (this.vars.yoyo === true);
- this._repeat = this.vars.repeat || 0;
- this._repeatDelay = this.vars.repeatDelay || 0;
- this._uncache(true);
- return TweenLite.prototype.invalidate.call(this);
- };
-
- p.updateTo = function(vars, resetDuration) {
- var curRatio = this.ratio, p;
- if (resetDuration && this._startTime < this._timeline._time) {
- this._startTime = this._timeline._time;
- this._uncache(false);
- if (this._gc) {
- this._enabled(true, false);
- } else {
- this._timeline.insert(this, this._startTime - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
- }
- }
- for (p in vars) {
- this.vars[p] = vars[p];
- }
- if (this._initted) {
- if (resetDuration) {
- this._initted = false;
- } else {
- if (this._gc) {
- this._enabled(true, false);
- }
- if (this._notifyPluginsOfEnabled && this._firstPT) {
- TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks
- }
- if (this._time / this._duration > 0.998) { //if the tween has finished (or come extremely close to finishing), we just need to rewind it to 0 and then render it again at the end which forces it to re-initialize (parsing the new vars). We allow tweens that are close to finishing (but haven't quite finished) to work this way too because otherwise, the values are so small when determining where to project the starting values that binary math issues creep in and can make the tween appear to render incorrectly when run backwards.
- var prevTime = this._time;
- this.render(0, true, false);
- this._initted = false;
- this.render(prevTime, true, false);
- } else if (this._time > 0) {
- this._initted = false;
- this._init();
- var inv = 1 / (1 - curRatio),
- pt = this._firstPT, endValue;
- while (pt) {
- endValue = pt.s + pt.c;
- pt.c *= inv;
- pt.s = endValue - pt.c;
- pt = pt._next;
- }
- }
- }
- }
- return this;
- };
-
- p.render = function(time, suppressEvents, force) {
- if (!this._initted) if (this._duration === 0 && this.vars.repeat) { //zero duration tweens that render immediately have render() called from TweenLite's constructor, before TweenMax's constructor has finished setting _repeat, _repeatDelay, and _yoyo which are critical in determining totalDuration() so we need to call invalidate() which is a low-kb way to get those set properly.
- this.invalidate();
- }
- var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
- prevTime = this._time,
- prevTotalTime = this._totalTime,
- prevCycle = this._cycle,
- duration = this._duration,
- prevRawPrevTime = this._rawPrevTime,
- isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
- if (time >= totalDur) {
- this._totalTime = totalDur;
- this._cycle = this._repeat;
- if (this._yoyo && (this._cycle & 1) !== 0) {
- this._time = 0;
- this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
- } else {
- this._time = duration;
- this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
- }
- if (!this._reversed) {
- isComplete = true;
- callback = "onComplete";
- }
- if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
- time = 0;
- }
- if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
- force = true;
- if (prevRawPrevTime > _tinyNum) {
- callback = "onReverseComplete";
- }
- }
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- }
-
- } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
- this._totalTime = this._time = this._cycle = 0;
- this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
- if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
- callback = "onReverseComplete";
- isComplete = this._reversed;
- }
- if (time < 0) {
- this._active = false;
- if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- if (prevRawPrevTime >= 0) {
- force = true;
- }
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- }
- } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
- force = true;
- }
- } else {
- this._totalTime = this._time = time;
-
- if (this._repeat !== 0) {
- cycleDuration = duration + this._repeatDelay;
- this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but Flash reports it as 0.79999999!)
- if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
- this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
- }
- this._time = this._totalTime - (this._cycle * cycleDuration);
- if (this._yoyo) if ((this._cycle & 1) !== 0) {
- this._time = duration - this._time;
- }
- if (this._time > duration) {
- this._time = duration;
- } else if (this._time < 0) {
- this._time = 0;
- }
- }
-
- if (this._easeType) {
- r = this._time / duration;
- type = this._easeType;
- pow = this._easePower;
- if (type === 1 || (type === 3 && r >= 0.5)) {
- r = 1 - r;
- }
- if (type === 3) {
- r *= 2;
- }
- if (pow === 1) {
- r *= r;
- } else if (pow === 2) {
- r *= r * r;
- } else if (pow === 3) {
- r *= r * r * r;
- } else if (pow === 4) {
- r *= r * r * r * r;
- }
-
- if (type === 1) {
- this.ratio = 1 - r;
- } else if (type === 2) {
- this.ratio = r;
- } else if (this._time / duration < 0.5) {
- this.ratio = r / 2;
- } else {
- this.ratio = 1 - (r / 2);
- }
-
- } else {
- this.ratio = this._ease.getRatio(this._time / duration);
- }
-
- }
-
- if (prevTime === this._time && !force && prevCycle === this._cycle) {
- if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
- return;
- } else if (!this._initted) {
- this._init();
- if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
- return;
- } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) { //we stick it in the queue for rendering at the very end of the tick - this is a performance optimization because browsers invalidate styles and force a recalculation if you read, write, and then read style data (so it's better to read/read/read/write/write/write than read/write/read/write/read/write). The down side, of course, is that usually you WANT things to render immediately because you may have code running right after that which depends on the change. Like imagine running TweenLite.set(...) and then immediately after that, creating a nother tween that animates the same property to another value; the starting values of that 2nd tween wouldn't be accurate if lazy is true.
- this._time = prevTime;
- this._totalTime = prevTotalTime;
- this._rawPrevTime = prevRawPrevTime;
- this._cycle = prevCycle;
- TweenLiteInternals.lazyTweens.push(this);
- this._lazy = time;
- return;
- }
- //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
- if (this._time && !isComplete) {
- this.ratio = this._ease.getRatio(this._time / duration);
- } else if (isComplete && this._ease._calcEnd) {
- this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
- }
- }
- if (this._lazy !== false) {
- this._lazy = false;
- }
-
- if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
- this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
- }
- if (prevTotalTime === 0) {
- if (this._initted === 2 && time > 0) {
- //this.invalidate();
- this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
- }
- if (this._startAt) {
- if (time >= 0) {
- this._startAt.render(time, suppressEvents, force);
- } else if (!callback) {
- callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
- }
- }
- if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
- this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
- }
- }
-
- pt = this._firstPT;
- while (pt) {
- if (pt.f) {
- pt.t[pt.p](pt.c * this.ratio + pt.s);
- } else {
- pt.t[pt.p] = pt.c * this.ratio + pt.s;
- }
- pt = pt._next;
- }
-
- if (this._onUpdate) {
- if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
- }
- if (!suppressEvents) if (this._totalTime !== prevTotalTime || isComplete) {
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
- }
- if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
- this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
- }
- if (callback) if (!this._gc) { //check gc because there's a chance that kill() could be called in an onUpdate
- if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force);
- }
- if (isComplete) {
- if (this._timeline.autoRemoveChildren) {
- this._enabled(false, false);
- }
- this._active = false;
- }
- if (!suppressEvents && this.vars[callback]) {
- this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
- }
- if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
- this._rawPrevTime = 0;
- }
- }
- };
-
-//---- STATIC FUNCTIONS -----------------------------------------------------------------------------------------------------------
-
- TweenMax.to = function(target, duration, vars) {
- return new TweenMax(target, duration, vars);
- };
-
- TweenMax.from = function(target, duration, vars) {
- vars.runBackwards = true;
- vars.immediateRender = (vars.immediateRender != false);
- return new TweenMax(target, duration, vars);
- };
-
- TweenMax.fromTo = function(target, duration, fromVars, toVars) {
- toVars.startAt = fromVars;
- toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
- return new TweenMax(target, duration, toVars);
- };
-
- TweenMax.staggerTo = TweenMax.allTo = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- stagger = stagger || 0;
- var delay = vars.delay || 0,
- a = [],
- finalComplete = function() {
- if (vars.onComplete) {
- vars.onComplete.apply(vars.onCompleteScope || this, arguments);
- }
- onCompleteAll.apply(onCompleteAllScope || this, onCompleteAllParams || _blankArray);
- },
- l, copy, i, p;
- if (!_isArray(targets)) {
- if (typeof(targets) === "string") {
- targets = TweenLite.selector(targets) || targets;
- }
- if (_isSelector(targets)) {
- targets = _slice.call(targets, 0);
- }
- }
- l = targets.length;
- for (i = 0; i < l; i++) {
- copy = {};
- for (p in vars) {
- copy[p] = vars[p];
- }
- copy.delay = delay;
- if (i === l - 1 && onCompleteAll) {
- copy.onComplete = finalComplete;
- }
- a[i] = new TweenMax(targets[i], duration, copy);
- delay += stagger;
- }
- return a;
- };
-
- TweenMax.staggerFrom = TweenMax.allFrom = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- vars.runBackwards = true;
- vars.immediateRender = (vars.immediateRender != false);
- return TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
- };
-
- TweenMax.staggerFromTo = TweenMax.allFromTo = function(targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- toVars.startAt = fromVars;
- toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
- return TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
- };
-
- TweenMax.delayedCall = function(delay, callback, params, scope, useFrames) {
- return new TweenMax(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
- };
-
- TweenMax.set = function(target, vars) {
- return new TweenMax(target, 0, vars);
- };
-
- TweenMax.isTweening = function(target) {
- return (TweenLite.getTweensOf(target, true).length > 0);
- };
-
- var _getChildrenOf = function(timeline, includeTimelines) {
- var a = [],
- cnt = 0,
- tween = timeline._first;
- while (tween) {
- if (tween instanceof TweenLite) {
- a[cnt++] = tween;
- } else {
- if (includeTimelines) {
- a[cnt++] = tween;
- }
- a = a.concat(_getChildrenOf(tween, includeTimelines));
- cnt = a.length;
- }
- tween = tween._next;
- }
- return a;
- },
- getAllTweens = TweenMax.getAllTweens = function(includeTimelines) {
- return _getChildrenOf(Animation._rootTimeline, includeTimelines).concat( _getChildrenOf(Animation._rootFramesTimeline, includeTimelines) );
- };
-
- TweenMax.killAll = function(complete, tweens, delayedCalls, timelines) {
- if (tweens == null) {
- tweens = true;
- }
- if (delayedCalls == null) {
- delayedCalls = true;
- }
- var a = getAllTweens((timelines != false)),
- l = a.length,
- allTrue = (tweens && delayedCalls && timelines),
- isDC, tween, i;
- for (i = 0; i < l; i++) {
- tween = a[i];
- if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
- if (complete) {
- tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
- } else {
- tween._enabled(false, false);
- }
- }
- }
- };
-
- TweenMax.killChildTweensOf = function(parent, complete) {
- if (parent == null) {
- return;
- }
- var tl = TweenLiteInternals.tweenLookup,
- a, curParent, p, i, l;
- if (typeof(parent) === "string") {
- parent = TweenLite.selector(parent) || parent;
- }
- if (_isSelector(parent)) {
- parent = _slice.call(parent, 0);
- }
- if (_isArray(parent)) {
- i = parent.length;
- while (--i > -1) {
- TweenMax.killChildTweensOf(parent[i], complete);
- }
- return;
- }
- a = [];
- for (p in tl) {
- curParent = tl[p].target.parentNode;
- while (curParent) {
- if (curParent === parent) {
- a = a.concat(tl[p].tweens);
- }
- curParent = curParent.parentNode;
- }
- }
- l = a.length;
- for (i = 0; i < l; i++) {
- if (complete) {
- a[i].totalTime(a[i].totalDuration());
- }
- a[i]._enabled(false, false);
- }
- };
-
- var _changePause = function(pause, tweens, delayedCalls, timelines) {
- tweens = (tweens !== false);
- delayedCalls = (delayedCalls !== false);
- timelines = (timelines !== false);
- var a = getAllTweens(timelines),
- allTrue = (tweens && delayedCalls && timelines),
- i = a.length,
- isDC, tween;
- while (--i > -1) {
- tween = a[i];
- if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
- tween.paused(pause);
- }
- }
- };
-
- TweenMax.pauseAll = function(tweens, delayedCalls, timelines) {
- _changePause(true, tweens, delayedCalls, timelines);
- };
-
- TweenMax.resumeAll = function(tweens, delayedCalls, timelines) {
- _changePause(false, tweens, delayedCalls, timelines);
- };
-
- TweenMax.globalTimeScale = function(value) {
- var tl = Animation._rootTimeline,
- t = TweenLite.ticker.time;
- if (!arguments.length) {
- return tl._timeScale;
- }
- value = value || _tinyNum; //can't allow zero because it'll throw the math off
- tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
- tl = Animation._rootFramesTimeline;
- t = TweenLite.ticker.frame;
- tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
- tl._timeScale = Animation._rootTimeline._timeScale = value;
- return value;
- };
-
-
-//---- GETTERS / SETTERS ----------------------------------------------------------------------------------------------------------
-
- p.progress = function(value) {
- return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
- };
-
- p.totalProgress = function(value) {
- return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
- };
-
- p.time = function(value, suppressEvents) {
- if (!arguments.length) {
- return this._time;
- }
- if (this._dirty) {
- this.totalDuration();
- }
- if (value > this._duration) {
- value = this._duration;
- }
- if (this._yoyo && (this._cycle & 1) !== 0) {
- value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
- } else if (this._repeat !== 0) {
- value += this._cycle * (this._duration + this._repeatDelay);
- }
- return this.totalTime(value, suppressEvents);
- };
-
- p.duration = function(value) {
- if (!arguments.length) {
- return this._duration; //don't set _dirty = false because there could be repeats that haven't been factored into the _totalDuration yet. Otherwise, if you create a repeated TweenMax and then immediately check its duration(), it would cache the value and the totalDuration would not be correct, thus repeats wouldn't take effect.
- }
- return Animation.prototype.duration.call(this, value);
- };
-
- p.totalDuration = function(value) {
- if (!arguments.length) {
- if (this._dirty) {
- //instead of Infinity, we use 999999999999 so that we can accommodate reverses
- this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
- this._dirty = false;
- }
- return this._totalDuration;
- }
- return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
- };
-
- p.repeat = function(value) {
- if (!arguments.length) {
- return this._repeat;
- }
- this._repeat = value;
- return this._uncache(true);
- };
-
- p.repeatDelay = function(value) {
- if (!arguments.length) {
- return this._repeatDelay;
- }
- this._repeatDelay = value;
- return this._uncache(true);
- };
-
- p.yoyo = function(value) {
- if (!arguments.length) {
- return this._yoyo;
- }
- this._yoyo = value;
- return this;
- };
-
-
- return TweenMax;
-
- }, true);
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * TimelineLite
- * ----------------------------------------------------------------
- */
- window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
-
- var TimelineLite = function(vars) {
- SimpleTimeline.call(this, vars);
- this._labels = {};
- this.autoRemoveChildren = (this.vars.autoRemoveChildren === true);
- this.smoothChildTiming = (this.vars.smoothChildTiming === true);
- this._sortChildren = true;
- this._onUpdate = this.vars.onUpdate;
- var v = this.vars,
- val, p;
- for (p in v) {
- val = v[p];
- if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) {
- v[p] = this._swapSelfInParams(val);
- }
- }
- if (_isArray(v.tweens)) {
- this.add(v.tweens, 0, v.align, v.stagger);
- }
- },
- _tinyNum = 0.0000000001,
- _isSelector = TweenLite._internals.isSelector,
- _isArray = TweenLite._internals.isArray,
- _blankArray = [],
- _globals = window._gsDefine.globals,
- _copy = function(vars) {
- var copy = {}, p;
- for (p in vars) {
- copy[p] = vars[p];
- }
- return copy;
- },
- _pauseCallback = function(tween, callback, params, scope) {
- tween._timeline.pause(tween._startTime);
- if (callback) {
- callback.apply(scope || tween._timeline, params || _blankArray);
- }
- },
- _slice = _blankArray.slice,
- p = TimelineLite.prototype = new SimpleTimeline();
-
- TimelineLite.version = "1.12.1";
- p.constructor = TimelineLite;
- p.kill()._gc = false;
-
- p.to = function(target, duration, vars, position) {
- var Engine = (vars.repeat && _globals.TweenMax) || TweenLite;
- return duration ? this.add( new Engine(target, duration, vars), position) : this.set(target, vars, position);
- };
-
- p.from = function(target, duration, vars, position) {
- return this.add( ((vars.repeat && _globals.TweenMax) || TweenLite).from(target, duration, vars), position);
- };
-
- p.fromTo = function(target, duration, fromVars, toVars, position) {
- var Engine = (toVars.repeat && _globals.TweenMax) || TweenLite;
- return duration ? this.add( Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position);
- };
-
- p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope, smoothChildTiming:this.smoothChildTiming}),
- i;
- if (typeof(targets) === "string") {
- targets = TweenLite.selector(targets) || targets;
- }
- if (_isSelector(targets)) { //senses if the targets object is a selector. If it is, we should translate it into an array.
- targets = _slice.call(targets, 0);
- }
- stagger = stagger || 0;
- for (i = 0; i < targets.length; i++) {
- if (vars.startAt) {
- vars.startAt = _copy(vars.startAt);
- }
- tl.to(targets[i], duration, _copy(vars), i * stagger);
- }
- return this.add(tl, position);
- };
-
- p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- vars.immediateRender = (vars.immediateRender != false);
- vars.runBackwards = true;
- return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
- };
-
- p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
- toVars.startAt = fromVars;
- toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
- return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
- };
-
- p.call = function(callback, params, scope, position) {
- return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
- };
-
- p.set = function(target, vars, position) {
- position = this._parseTimeOrLabel(position, 0, true);
- if (vars.immediateRender == null) {
- vars.immediateRender = (position === this._time && !this._paused);
- }
- return this.add( new TweenLite(target, 0, vars), position);
- };
-
- TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) {
- vars = vars || {};
- if (vars.smoothChildTiming == null) {
- vars.smoothChildTiming = true;
- }
- var tl = new TimelineLite(vars),
- root = tl._timeline,
- tween, next;
- if (ignoreDelayedCalls == null) {
- ignoreDelayedCalls = true;
- }
- root._remove(tl, true);
- tl._startTime = 0;
- tl._rawPrevTime = tl._time = tl._totalTime = root._time;
- tween = root._first;
- while (tween) {
- next = tween._next;
- if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
- tl.add(tween, tween._startTime - tween._delay);
- }
- tween = next;
- }
- root.add(tl, 0);
- return tl;
- };
-
- p.add = function(value, position, align, stagger) {
- var curTime, l, i, child, tl, beforeRawTime;
- if (typeof(position) !== "number") {
- position = this._parseTimeOrLabel(position, 0, true, value);
- }
- if (!(value instanceof Animation)) {
- if ((value instanceof Array) || (value && value.push && _isArray(value))) {
- align = align || "normal";
- stagger = stagger || 0;
- curTime = position;
- l = value.length;
- for (i = 0; i < l; i++) {
- if (_isArray(child = value[i])) {
- child = new TimelineLite({tweens:child});
- }
- this.add(child, curTime);
- if (typeof(child) !== "string" && typeof(child) !== "function") {
- if (align === "sequence") {
- curTime = child._startTime + (child.totalDuration() / child._timeScale);
- } else if (align === "start") {
- child._startTime -= child.delay();
- }
- }
- curTime += stagger;
- }
- return this._uncache(true);
- } else if (typeof(value) === "string") {
- return this.addLabel(value, position);
- } else if (typeof(value) === "function") {
- value = TweenLite.delayedCall(0, value);
- } else {
- throw("Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string.");
- }
- }
-
- SimpleTimeline.prototype.add.call(this, value, position);
-
- //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. We should also align the playhead with the parent timeline's when appropriate.
- if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) {
- //in case any of the ancestors had completed but should now be enabled...
- tl = this;
- beforeRawTime = (tl.rawTime() > value._startTime); //if the tween is placed on the timeline so that it starts BEFORE the current rawTime, we should align the playhead (move the timeline). This is because sometimes users will create a timeline, let it finish, and much later append a tween and expect it to run instead of jumping to its end state. While technically one could argue that it should jump to its end state, that's not what users intuitively expect.
- while (tl._timeline) {
- if (beforeRawTime && tl._timeline.smoothChildTiming) {
- tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it.
- } else if (tl._gc) {
- tl._enabled(true, false);
- }
- tl = tl._timeline;
- }
- }
-
- return this;
- };
-
- p.remove = function(value) {
- if (value instanceof Animation) {
- return this._remove(value, false);
- } else if (value instanceof Array || (value && value.push && _isArray(value))) {
- var i = value.length;
- while (--i > -1) {
- this.remove(value[i]);
- }
- return this;
- } else if (typeof(value) === "string") {
- return this.removeLabel(value);
- }
- return this.kill(null, value);
- };
-
- p._remove = function(tween, skipDisable) {
- SimpleTimeline.prototype._remove.call(this, tween, skipDisable);
- var last = this._last;
- if (!last) {
- this._time = this._totalTime = this._duration = this._totalDuration = 0;
- } else if (this._time > last._startTime + last._totalDuration / last._timeScale) {
- this._time = this.duration();
- this._totalTime = this._totalDuration;
- }
- return this;
- };
-
- p.append = function(value, offsetOrLabel) {
- return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value));
- };
-
- p.insert = p.insertMultiple = function(value, position, align, stagger) {
- return this.add(value, position || 0, align, stagger);
- };
-
- p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) {
- return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger);
- };
-
- p.addLabel = function(label, position) {
- this._labels[label] = this._parseTimeOrLabel(position);
- return this;
- };
-
- p.addPause = function(position, callback, params, scope) {
- return this.call(_pauseCallback, ["{self}", callback, params, scope], this, position);
- };
-
- p.removeLabel = function(label) {
- delete this._labels[label];
- return this;
- };
-
- p.getLabelTime = function(label) {
- return (this._labels[label] != null) ? this._labels[label] : -1;
- };
-
- p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) {
- var i;
- //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration().
- if (ignore instanceof Animation && ignore.timeline === this) {
- this.remove(ignore);
- } else if (ignore && ((ignore instanceof Array) || (ignore.push && _isArray(ignore)))) {
- i = ignore.length;
- while (--i > -1) {
- if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
- this.remove(ignore[i]);
- }
- }
- }
- if (typeof(offsetOrLabel) === "string") {
- return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent);
- }
- offsetOrLabel = offsetOrLabel || 0;
- if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value).
- i = timeOrLabel.indexOf("=");
- if (i === -1) {
- if (this._labels[timeOrLabel] == null) {
- return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel;
- }
- return this._labels[timeOrLabel] + offsetOrLabel;
- }
- offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1));
- timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration();
- } else if (timeOrLabel == null) {
- timeOrLabel = this.duration();
- }
- return Number(timeOrLabel) + offsetOrLabel;
- };
-
- p.seek = function(position, suppressEvents) {
- return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false));
- };
-
- p.stop = function() {
- return this.paused(true);
- };
-
- p.gotoAndPlay = function(position, suppressEvents) {
- return this.play(position, suppressEvents);
- };
-
- p.gotoAndStop = function(position, suppressEvents) {
- return this.pause(position, suppressEvents);
- };
-
- p.render = function(time, suppressEvents, force) {
- if (this._gc) {
- this._enabled(true, false);
- }
- var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
- prevTime = this._time,
- prevStart = this._startTime,
- prevTimeScale = this._timeScale,
- prevPaused = this._paused,
- tween, isComplete, next, callback, internalForce;
- if (time >= totalDur) {
- this._totalTime = this._time = totalDur;
- if (!this._reversed) if (!this._hasPausedChild()) {
- isComplete = true;
- callback = "onComplete";
- if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) {
- internalForce = true;
- if (this._rawPrevTime > _tinyNum) {
- callback = "onReverseComplete";
- }
- }
- }
- this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- time = totalDur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7.
-
- } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
- this._totalTime = this._time = 0;
- if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || (time < 0 && this._rawPrevTime >= 0)))) {
- callback = "onReverseComplete";
- isComplete = this._reversed;
- }
- if (time < 0) {
- this._active = false;
- if (this._duration === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- internalForce = true;
- }
- this._rawPrevTime = time;
- } else {
- this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
-
- time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
- if (!this._initted) {
- internalForce = true;
- }
- }
-
- } else {
- this._totalTime = this._time = this._rawPrevTime = time;
- }
- if ((this._time === prevTime || !this._first) && !force && !internalForce) {
- return;
- } else if (!this._initted) {
- this._initted = true;
- }
-
- if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) {
- this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
- }
-
- if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) {
- this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
- }
-
- if (this._time >= prevTime) {
- tween = this._first;
- while (tween) {
- next = tween._next; //record it here because the value could change after rendering...
- if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
- break;
- } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
- if (!tween._reversed) {
- tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
- } else {
- tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
- }
- }
- tween = next;
- }
- } else {
- tween = this._last;
- while (tween) {
- next = tween._prev; //record it here because the value could change after rendering...
- if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
- break;
- } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
- if (!tween._reversed) {
- tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
- } else {
- tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
- }
- }
- tween = next;
- }
- }
-
- if (this._onUpdate) if (!suppressEvents) {
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
-
- if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
- if (isComplete) {
- if (this._timeline.autoRemoveChildren) {
- this._enabled(false, false);
- }
- this._active = false;
- }
- if (!suppressEvents && this.vars[callback]) {
- this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
- }
- }
- };
-
- p._hasPausedChild = function() {
- var tween = this._first;
- while (tween) {
- if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) {
- return true;
- }
- tween = tween._next;
- }
- return false;
- };
-
- p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) {
- ignoreBeforeTime = ignoreBeforeTime || -9999999999;
- var a = [],
- tween = this._first,
- cnt = 0;
- while (tween) {
- if (tween._startTime < ignoreBeforeTime) {
- //do nothing
- } else if (tween instanceof TweenLite) {
- if (tweens !== false) {
- a[cnt++] = tween;
- }
- } else {
- if (timelines !== false) {
- a[cnt++] = tween;
- }
- if (nested !== false) {
- a = a.concat(tween.getChildren(true, tweens, timelines));
- cnt = a.length;
- }
- }
- tween = tween._next;
- }
- return a;
- };
-
- p.getTweensOf = function(target, nested) {
- var disabled = this._gc,
- a = [],
- cnt = 0,
- tweens, i;
- if (disabled) {
- this._enabled(true, true); //getTweensOf() filters out disabled tweens, and we have to mark them as _gc = true when the timeline completes in order to allow clean garbage collection, so temporarily re-enable the timeline here.
- }
- tweens = TweenLite.getTweensOf(target);
- i = tweens.length;
- while (--i > -1) {
- if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
- a[cnt++] = tweens[i];
- }
- }
- if (disabled) {
- this._enabled(false, true);
- }
- return a;
- };
-
- p._contains = function(tween) {
- var tl = tween.timeline;
- while (tl) {
- if (tl === this) {
- return true;
- }
- tl = tl.timeline;
- }
- return false;
- };
-
- p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) {
- ignoreBeforeTime = ignoreBeforeTime || 0;
- var tween = this._first,
- labels = this._labels,
- p;
- while (tween) {
- if (tween._startTime >= ignoreBeforeTime) {
- tween._startTime += amount;
- }
- tween = tween._next;
- }
- if (adjustLabels) {
- for (p in labels) {
- if (labels[p] >= ignoreBeforeTime) {
- labels[p] += amount;
- }
- }
- }
- return this._uncache(true);
- };
-
- p._kill = function(vars, target) {
- if (!vars && !target) {
- return this._enabled(false, false);
- }
- var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target),
- i = tweens.length,
- changed = false;
- while (--i > -1) {
- if (tweens[i]._kill(vars, target)) {
- changed = true;
- }
- }
- return changed;
- };
-
- p.clear = function(labels) {
- var tweens = this.getChildren(false, true, true),
- i = tweens.length;
- this._time = this._totalTime = 0;
- while (--i > -1) {
- tweens[i]._enabled(false, false);
- }
- if (labels !== false) {
- this._labels = {};
- }
- return this._uncache(true);
- };
-
- p.invalidate = function() {
- var tween = this._first;
- while (tween) {
- tween.invalidate();
- tween = tween._next;
- }
- return this;
- };
-
- p._enabled = function(enabled, ignoreTimeline) {
- if (enabled === this._gc) {
- var tween = this._first;
- while (tween) {
- tween._enabled(enabled, true);
- tween = tween._next;
- }
- }
- return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline);
- };
-
- p.duration = function(value) {
- if (!arguments.length) {
- if (this._dirty) {
- this.totalDuration(); //just triggers recalculation
- }
- return this._duration;
- }
- if (this.duration() !== 0 && value !== 0) {
- this.timeScale(this._duration / value);
- }
- return this;
- };
-
- p.totalDuration = function(value) {
- if (!arguments.length) {
- if (this._dirty) {
- var max = 0,
- tween = this._last,
- prevStart = 999999999999,
- prev, end;
- while (tween) {
- prev = tween._prev; //record it here in case the tween changes position in the sequence...
- if (tween._dirty) {
- tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
- }
- if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence
- this.add(tween, tween._startTime - tween._delay);
- } else {
- prevStart = tween._startTime;
- }
- if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found.
- max -= tween._startTime;
- if (this._timeline.smoothChildTiming) {
- this._startTime += tween._startTime / this._timeScale;
- }
- this.shiftChildren(-tween._startTime, false, -9999999999);
- prevStart = 0;
- }
- end = tween._startTime + (tween._totalDuration / tween._timeScale);
- if (end > max) {
- max = end;
- }
- tween = prev;
- }
- this._duration = this._totalDuration = max;
- this._dirty = false;
- }
- return this._totalDuration;
- }
- if (this.totalDuration() !== 0) if (value !== 0) {
- this.timeScale(this._totalDuration / value);
- }
- return this;
- };
-
- p.usesFrames = function() {
- var tl = this._timeline;
- while (tl._timeline) {
- tl = tl._timeline;
- }
- return (tl === Animation._rootFramesTimeline);
- };
-
- p.rawTime = function() {
- return this._paused ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale;
- };
-
- return TimelineLite;
-
- }, true);
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * TimelineMax
- * ----------------------------------------------------------------
- */
- window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) {
-
- var TimelineMax = function(vars) {
- TimelineLite.call(this, vars);
- this._repeat = this.vars.repeat || 0;
- this._repeatDelay = this.vars.repeatDelay || 0;
- this._cycle = 0;
- this._yoyo = (this.vars.yoyo === true);
- this._dirty = true;
- },
- _tinyNum = 0.0000000001,
- _blankArray = [],
- _easeNone = new Ease(null, null, 1, 0),
- p = TimelineMax.prototype = new TimelineLite();
-
- p.constructor = TimelineMax;
- p.kill()._gc = false;
- TimelineMax.version = "1.12.1";
-
- p.invalidate = function() {
- this._yoyo = (this.vars.yoyo === true);
- this._repeat = this.vars.repeat || 0;
- this._repeatDelay = this.vars.repeatDelay || 0;
- this._uncache(true);
- return TimelineLite.prototype.invalidate.call(this);
- };
-
- p.addCallback = function(callback, position, params, scope) {
- return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
- };
-
- p.removeCallback = function(callback, position) {
- if (callback) {
- if (position == null) {
- this._kill(null, callback);
- } else {
- var a = this.getTweensOf(callback, false),
- i = a.length,
- time = this._parseTimeOrLabel(position);
- while (--i > -1) {
- if (a[i]._startTime === time) {
- a[i]._enabled(false, false);
- }
- }
- }
- }
- return this;
- };
-
- p.tweenTo = function(position, vars) {
- vars = vars || {};
- var copy = {ease:_easeNone, overwrite:(vars.delay ? 2 : 1), useFrames:this.usesFrames(), immediateRender:false},//note: set overwrite to 1 (true/all) by default unless there's a delay so that we avoid a racing situation that could happen if, for example, an onmousemove creates the same tweenTo() over and over again.
- duration, p, t;
- for (p in vars) {
- copy[p] = vars[p];
- }
- copy.time = this._parseTimeOrLabel(position);
- duration = (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001;
- t = new TweenLite(this, duration, copy);
- copy.onStart = function() {
- t.target.paused(true);
- if (t.vars.time !== t.target.time() && duration === t.duration()) { //don't make the duration zero - if it's supposed to be zero, don't worry because it's already initting the tween and will complete immediately, effectively making the duration zero anyway. If we make duration zero, the tween won't run at all.
- t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale );
- }
- if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it.
- vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray);
- }
- };
- return t;
- };
-
- p.tweenFromTo = function(fromPosition, toPosition, vars) {
- vars = vars || {};
- fromPosition = this._parseTimeOrLabel(fromPosition);
- vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this};
- vars.immediateRender = (vars.immediateRender !== false);
- var t = this.tweenTo(toPosition, vars);
- return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001);
- };
-
- p.render = function(time, suppressEvents, force) {
- if (this._gc) {
- this._enabled(true, false);
- }
- var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
- dur = this._duration,
- prevTime = this._time,
- prevTotalTime = this._totalTime,
- prevStart = this._startTime,
- prevTimeScale = this._timeScale,
- prevRawPrevTime = this._rawPrevTime,
- prevPaused = this._paused,
- prevCycle = this._cycle,
- tween, isComplete, next, callback, internalForce, cycleDuration;
- if (time >= totalDur) {
- if (!this._locked) {
- this._totalTime = totalDur;
- this._cycle = this._repeat;
- }
- if (!this._reversed) if (!this._hasPausedChild()) {
- isComplete = true;
- callback = "onComplete";
- if (this._duration === 0) if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) {
- internalForce = true;
- if (prevRawPrevTime > _tinyNum) {
- callback = "onReverseComplete";
- }
- }
- }
- this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- if (this._yoyo && (this._cycle & 1) !== 0) {
- this._time = time = 0;
- } else {
- this._time = dur;
- time = dur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7. We cannot do less then 0.0001 because the same issue can occur when the duration is extremely large like 999999999999 in which case adding 0.00000001, for example, causes it to act like nothing was added.
- }
-
- } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
- if (!this._locked) {
- this._totalTime = this._cycle = 0;
- }
- this._time = 0;
- if (prevTime !== 0 || (dur === 0 && prevRawPrevTime !== _tinyNum && (prevRawPrevTime > 0 || (time < 0 && prevRawPrevTime >= 0)) && !this._locked)) { //edge case for checking time < 0 && prevRawPrevTime >= 0: a zero-duration fromTo() tween inside a zero-duration timeline (yeah, very rare)
- callback = "onReverseComplete";
- isComplete = this._reversed;
- }
- if (time < 0) {
- this._active = false;
- if (dur === 0) if (prevRawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- internalForce = true;
- }
- this._rawPrevTime = time;
- } else {
- this._rawPrevTime = (dur || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
- if (!this._initted) {
- internalForce = true;
- }
- }
-
- } else {
- if (dur === 0 && prevRawPrevTime < 0) { //without this, zero-duration repeating timelines (like with a simple callback nested at the very beginning and a repeatDelay) wouldn't render the first time through.
- internalForce = true;
- }
- this._time = this._rawPrevTime = time;
- if (!this._locked) {
- this._totalTime = time;
- if (this._repeat !== 0) {
- cycleDuration = dur + this._repeatDelay;
- this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but it gets reported as 0.79999999!)
- if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
- this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
- }
- this._time = this._totalTime - (this._cycle * cycleDuration);
- if (this._yoyo) if ((this._cycle & 1) !== 0) {
- this._time = dur - this._time;
- }
- if (this._time > dur) {
- this._time = dur;
- time = dur + 0.0001; //to avoid occasional floating point rounding error
- } else if (this._time < 0) {
- this._time = time = 0;
- } else {
- time = this._time;
- }
- }
- }
- }
-
- if (this._cycle !== prevCycle) if (!this._locked) {
- /*
- make sure children at the end/beginning of the timeline are rendered properly. If, for example,
- a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
- would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there
- could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So
- we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must
- ensure that zero-duration tweens at the very beginning or end of the TimelineMax work.
- */
- var backwards = (this._yoyo && (prevCycle & 1) !== 0),
- wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)),
- recTotalTime = this._totalTime,
- recCycle = this._cycle,
- recRawPrevTime = this._rawPrevTime,
- recTime = this._time;
-
- this._totalTime = prevCycle * dur;
- if (this._cycle < prevCycle) {
- backwards = !backwards;
- } else {
- this._totalTime += dur;
- }
- this._time = prevTime; //temporarily revert _time so that render() renders the children in the correct order. Without this, tweens won't rewind correctly. We could arhictect things in a "cleaner" way by splitting out the rendering queue into a separate method but for performance reasons, we kept it all inside this method.
-
- this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.0001 : prevRawPrevTime;
- this._cycle = prevCycle;
- this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render()
- prevTime = (backwards) ? 0 : dur;
- this.render(prevTime, suppressEvents, (dur === 0));
- if (!suppressEvents) if (!this._gc) {
- if (this.vars.onRepeat) {
- this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
- }
- }
- if (wrap) {
- prevTime = (backwards) ? dur + 0.0001 : -0.0001;
- this.render(prevTime, true, false);
- }
- this._locked = false;
- if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible)
- return;
- }
- this._time = recTime;
- this._totalTime = recTotalTime;
- this._cycle = recCycle;
- this._rawPrevTime = recRawPrevTime;
- }
-
- if ((this._time === prevTime || !this._first) && !force && !internalForce) {
- if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
- return;
- } else if (!this._initted) {
- this._initted = true;
- }
-
- if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) {
- this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
- }
-
- if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) {
- this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
- }
-
- if (this._time >= prevTime) {
- tween = this._first;
- while (tween) {
- next = tween._next; //record it here because the value could change after rendering...
- if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
- break;
- } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
- if (!tween._reversed) {
- tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
- } else {
- tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
- }
-
- }
- tween = next;
- }
- } else {
- tween = this._last;
- while (tween) {
- next = tween._prev; //record it here because the value could change after rendering...
- if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
- break;
- } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
- if (!tween._reversed) {
- tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
- } else {
- tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
- }
- }
- tween = next;
- }
- }
-
- if (this._onUpdate) if (!suppressEvents) {
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
- if (callback) if (!this._locked) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
- if (isComplete) {
- if (this._timeline.autoRemoveChildren) {
- this._enabled(false, false);
- }
- this._active = false;
- }
- if (!suppressEvents && this.vars[callback]) {
- this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
- }
- }
- };
-
- p.getActive = function(nested, tweens, timelines) {
- if (nested == null) {
- nested = true;
- }
- if (tweens == null) {
- tweens = true;
- }
- if (timelines == null) {
- timelines = false;
- }
- var a = [],
- all = this.getChildren(nested, tweens, timelines),
- cnt = 0,
- l = all.length,
- i, tween;
- for (i = 0; i < l; i++) {
- tween = all[i];
- if (tween.isActive()) {
- a[cnt++] = tween;
- }
- }
- return a;
- };
-
-
- p.getLabelAfter = function(time) {
- if (!time) if (time !== 0) { //faster than isNan()
- time = this._time;
- }
- var labels = this.getLabelsArray(),
- l = labels.length,
- i;
- for (i = 0; i < l; i++) {
- if (labels[i].time > time) {
- return labels[i].name;
- }
- }
- return null;
- };
-
- p.getLabelBefore = function(time) {
- if (time == null) {
- time = this._time;
- }
- var labels = this.getLabelsArray(),
- i = labels.length;
- while (--i > -1) {
- if (labels[i].time < time) {
- return labels[i].name;
- }
- }
- return null;
- };
-
- p.getLabelsArray = function() {
- var a = [],
- cnt = 0,
- p;
- for (p in this._labels) {
- a[cnt++] = {time:this._labels[p], name:p};
- }
- a.sort(function(a,b) {
- return a.time - b.time;
- });
- return a;
- };
-
-
-//---- GETTERS / SETTERS -------------------------------------------------------------------------------------------------------
-
- p.progress = function(value) {
- return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
- };
-
- p.totalProgress = function(value) {
- return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
- };
-
- p.totalDuration = function(value) {
- if (!arguments.length) {
- if (this._dirty) {
- TimelineLite.prototype.totalDuration.call(this); //just forces refresh
- //Instead of Infinity, we use 999999999999 so that we can accommodate reverses.
- this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
- }
- return this._totalDuration;
- }
- return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
- };
-
- p.time = function(value, suppressEvents) {
- if (!arguments.length) {
- return this._time;
- }
- if (this._dirty) {
- this.totalDuration();
- }
- if (value > this._duration) {
- value = this._duration;
- }
- if (this._yoyo && (this._cycle & 1) !== 0) {
- value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
- } else if (this._repeat !== 0) {
- value += this._cycle * (this._duration + this._repeatDelay);
- }
- return this.totalTime(value, suppressEvents);
- };
-
- p.repeat = function(value) {
- if (!arguments.length) {
- return this._repeat;
- }
- this._repeat = value;
- return this._uncache(true);
- };
-
- p.repeatDelay = function(value) {
- if (!arguments.length) {
- return this._repeatDelay;
- }
- this._repeatDelay = value;
- return this._uncache(true);
- };
-
- p.yoyo = function(value) {
- if (!arguments.length) {
- return this._yoyo;
- }
- this._yoyo = value;
- return this;
- };
-
- p.currentLabel = function(value) {
- if (!arguments.length) {
- return this.getLabelBefore(this._time + 0.00000001);
- }
- return this.seek(value, true);
- };
-
- return TimelineMax;
-
- }, true);
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * BezierPlugin
- * ----------------------------------------------------------------
- */
- (function() {
-
- var _RAD2DEG = 180 / Math.PI,
- _r1 = [],
- _r2 = [],
- _r3 = [],
- _corProps = {},
- Segment = function(a, b, c, d) {
- this.a = a;
- this.b = b;
- this.c = c;
- this.d = d;
- this.da = d - a;
- this.ca = c - a;
- this.ba = b - a;
- },
- _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",
- cubicToQuadratic = function(a, b, c, d) {
- var q1 = {a:a},
- q2 = {},
- q3 = {},
- q4 = {c:d},
- mab = (a + b) / 2,
- mbc = (b + c) / 2,
- mcd = (c + d) / 2,
- mabc = (mab + mbc) / 2,
- mbcd = (mbc + mcd) / 2,
- m8 = (mbcd - mabc) / 8;
- q1.b = mab + (a - mab) / 4;
- q2.b = mabc + m8;
- q1.c = q2.a = (q1.b + q2.b) / 2;
- q2.c = q3.a = (mabc + mbcd) / 2;
- q3.b = mbcd - m8;
- q4.b = mcd + (d - mcd) / 4;
- q3.c = q4.a = (q3.b + q4.b) / 2;
- return [q1, q2, q3, q4];
- },
- _calculateControlPoints = function(a, curviness, quad, basic, correlate) {
- var l = a.length - 1,
- ii = 0,
- cp1 = a[0].a,
- i, p1, p2, p3, seg, m1, m2, mm, cp2, qb, r1, r2, tl;
- for (i = 0; i < l; i++) {
- seg = a[ii];
- p1 = seg.a;
- p2 = seg.d;
- p3 = a[ii+1].d;
-
- if (correlate) {
- r1 = _r1[i];
- r2 = _r2[i];
- tl = ((r2 + r1) * curviness * 0.25) / (basic ? 0.5 : _r3[i] || 0.5);
- m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : (r1 !== 0 ? tl / r1 : 0));
- m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : (r2 !== 0 ? tl / r2 : 0));
- mm = p2 - (m1 + (((m2 - m1) * ((r1 * 3 / (r1 + r2)) + 0.5) / 4) || 0));
- } else {
- m1 = p2 - (p2 - p1) * curviness * 0.5;
- m2 = p2 + (p3 - p2) * curviness * 0.5;
- mm = p2 - (m1 + m2) / 2;
- }
- m1 += mm;
- m2 += mm;
-
- seg.c = cp2 = m1;
- if (i !== 0) {
- seg.b = cp1;
- } else {
- seg.b = cp1 = seg.a + (seg.c - seg.a) * 0.6; //instead of placing b on a exactly, we move it inline with c so that if the user specifies an ease like Back.easeIn or Elastic.easeIn which goes BEYOND the beginning, it will do so smoothly.
- }
-
- seg.da = p2 - p1;
- seg.ca = cp2 - p1;
- seg.ba = cp1 - p1;
-
- if (quad) {
- qb = cubicToQuadratic(p1, cp1, cp2, p2);
- a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
- ii += 4;
- } else {
- ii++;
- }
-
- cp1 = m2;
- }
- seg = a[ii];
- seg.b = cp1;
- seg.c = cp1 + (seg.d - cp1) * 0.4; //instead of placing c on d exactly, we move it inline with b so that if the user specifies an ease like Back.easeOut or Elastic.easeOut which goes BEYOND the end, it will do so smoothly.
- seg.da = seg.d - seg.a;
- seg.ca = seg.c - seg.a;
- seg.ba = cp1 - seg.a;
- if (quad) {
- qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
- a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
- }
- },
- _parseAnchors = function(values, p, correlate, prepend) {
- var a = [],
- l, i, p1, p2, p3, tmp;
- if (prepend) {
- values = [prepend].concat(values);
- i = values.length;
- while (--i > -1) {
- if (typeof( (tmp = values[i][p]) ) === "string") if (tmp.charAt(1) === "=") {
- values[i][p] = prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)); //accommodate relative values. Do it inline instead of breaking it out into a function for speed reasons
- }
- }
- }
- l = values.length - 2;
- if (l < 0) {
- a[0] = new Segment(values[0][p], 0, 0, values[(l < -1) ? 0 : 1][p]);
- return a;
- }
- for (i = 0; i < l; i++) {
- p1 = values[i][p];
- p2 = values[i+1][p];
- a[i] = new Segment(p1, 0, 0, p2);
- if (correlate) {
- p3 = values[i+2][p];
- _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
- _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
- }
- }
- a[i] = new Segment(values[i][p], 0, 0, values[i+1][p]);
- return a;
- },
- bezierThrough = function(values, curviness, quadratic, basic, correlate, prepend) {
- var obj = {},
- props = [],
- first = prepend || values[0],
- i, p, a, j, r, l, seamless, last;
- correlate = (typeof(correlate) === "string") ? ","+correlate+"," : _correlate;
- if (curviness == null) {
- curviness = 1;
- }
- for (p in values[0]) {
- props.push(p);
- }
- //check to see if the last and first values are identical (well, within 0.05). If so, make seamless by appending the second element to the very end of the values array and the 2nd-to-last element to the very beginning (we'll remove those segments later)
- if (values.length > 1) {
- last = values[values.length - 1];
- seamless = true;
- i = props.length;
- while (--i > -1) {
- p = props[i];
- if (Math.abs(first[p] - last[p]) > 0.05) { //build in a tolerance of +/-0.05 to accommodate rounding errors. For example, if you set an object's position to 4.945, Flash will make it 4.9
- seamless = false;
- break;
- }
- }
- if (seamless) {
- values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens
- if (prepend) {
- values.unshift(prepend);
- }
- values.push(values[1]);
- prepend = values[values.length - 3];
- }
- }
- _r1.length = _r2.length = _r3.length = 0;
- i = props.length;
- while (--i > -1) {
- p = props[i];
- _corProps[p] = (correlate.indexOf(","+p+",") !== -1);
- obj[p] = _parseAnchors(values, p, _corProps[p], prepend);
- }
- i = _r1.length;
- while (--i > -1) {
- _r1[i] = Math.sqrt(_r1[i]);
- _r2[i] = Math.sqrt(_r2[i]);
- }
- if (!basic) {
- i = props.length;
- while (--i > -1) {
- if (_corProps[p]) {
- a = obj[props[i]];
- l = a.length - 1;
- for (j = 0; j < l; j++) {
- r = a[j+1].da / _r2[j] + a[j].da / _r1[j];
- _r3[j] = (_r3[j] || 0) + r * r;
- }
- }
- }
- i = _r3.length;
- while (--i > -1) {
- _r3[i] = Math.sqrt(_r3[i]);
- }
- }
- i = props.length;
- j = quadratic ? 4 : 1;
- while (--i > -1) {
- p = props[i];
- a = obj[p];
- _calculateControlPoints(a, curviness, quadratic, basic, _corProps[p]); //this method requires that _parseAnchors() and _setSegmentRatios() ran first so that _r1, _r2, and _r3 values are populated for all properties
- if (seamless) {
- a.splice(0, j);
- a.splice(a.length - j, j);
- }
- }
- return obj;
- },
- _parseBezierData = function(values, type, prepend) {
- type = type || "soft";
- var obj = {},
- inc = (type === "cubic") ? 3 : 2,
- soft = (type === "soft"),
- props = [],
- a, b, c, d, cur, i, j, l, p, cnt, tmp;
- if (soft && prepend) {
- values = [prepend].concat(values);
- }
- if (values == null || values.length < inc + 1) { throw "invalid Bezier data"; }
- for (p in values[0]) {
- props.push(p);
- }
- i = props.length;
- while (--i > -1) {
- p = props[i];
- obj[p] = cur = [];
- cnt = 0;
- l = values.length;
- for (j = 0; j < l; j++) {
- a = (prepend == null) ? values[j][p] : (typeof( (tmp = values[j][p]) ) === "string" && tmp.charAt(1) === "=") ? prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)) : Number(tmp);
- if (soft) if (j > 1) if (j < l - 1) {
- cur[cnt++] = (a + cur[cnt-2]) / 2;
- }
- cur[cnt++] = a;
- }
- l = cnt - inc + 1;
- cnt = 0;
- for (j = 0; j < l; j += inc) {
- a = cur[j];
- b = cur[j+1];
- c = cur[j+2];
- d = (inc === 2) ? 0 : cur[j+3];
- cur[cnt++] = tmp = (inc === 3) ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
- }
- cur.length = cnt;
- }
- return obj;
- },
- _addCubicLengths = function(a, steps, resolution) {
- var inc = 1 / resolution,
- j = a.length,
- d, d1, s, da, ca, ba, p, i, inv, bez, index;
- while (--j > -1) {
- bez = a[j];
- s = bez.a;
- da = bez.d - s;
- ca = bez.c - s;
- ba = bez.b - s;
- d = d1 = 0;
- for (i = 1; i <= resolution; i++) {
- p = inc * i;
- inv = 1 - p;
- d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
- index = j * resolution + i - 1;
- steps[index] = (steps[index] || 0) + d * d;
- }
- }
- },
- _parseLengthData = function(obj, resolution) {
- resolution = resolution >> 0 || 6;
- var a = [],
- lengths = [],
- d = 0,
- total = 0,
- threshold = resolution - 1,
- segments = [],
- curLS = [], //current length segments array
- p, i, l, index;
- for (p in obj) {
- _addCubicLengths(obj[p], a, resolution);
- }
- l = a.length;
- for (i = 0; i < l; i++) {
- d += Math.sqrt(a[i]);
- index = i % resolution;
- curLS[index] = d;
- if (index === threshold) {
- total += d;
- index = (i / resolution) >> 0;
- segments[index] = curLS;
- lengths[index] = total;
- d = 0;
- curLS = [];
- }
- }
- return {length:total, lengths:lengths, segments:segments};
- },
-
-
-
- BezierPlugin = window._gsDefine.plugin({
- propName: "bezier",
- priority: -1,
- version: "1.3.2",
- API: 2,
- global:true,
-
- //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
- init: function(target, vars, tween) {
- this._target = target;
- if (vars instanceof Array) {
- vars = {values:vars};
- }
- this._func = {};
- this._round = {};
- this._props = [];
- this._timeRes = (vars.timeResolution == null) ? 6 : parseInt(vars.timeResolution, 10);
- var values = vars.values || [],
- first = {},
- second = values[0],
- autoRotate = vars.autoRotate || tween.vars.orientToBezier,
- p, isFunc, i, j, prepend;
-
- this._autoRotate = autoRotate ? (autoRotate instanceof Array) ? autoRotate : [["x","y","rotation",((autoRotate === true) ? 0 : Number(autoRotate) || 0)]] : null;
- for (p in second) {
- this._props.push(p);
- }
-
- i = this._props.length;
- while (--i > -1) {
- p = this._props[i];
-
- this._overwriteProps.push(p);
- isFunc = this._func[p] = (typeof(target[p]) === "function");
- first[p] = (!isFunc) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
- if (!prepend) if (first[p] !== values[0][p]) {
- prepend = first;
- }
- }
- this._beziers = (vars.type !== "cubic" && vars.type !== "quadratic" && vars.type !== "soft") ? bezierThrough(values, isNaN(vars.curviness) ? 1 : vars.curviness, false, (vars.type === "thruBasic"), vars.correlate, prepend) : _parseBezierData(values, vars.type, first);
- this._segCount = this._beziers[p].length;
-
- if (this._timeRes) {
- var ld = _parseLengthData(this._beziers, this._timeRes);
- this._length = ld.length;
- this._lengths = ld.lengths;
- this._segments = ld.segments;
- this._l1 = this._li = this._s1 = this._si = 0;
- this._l2 = this._lengths[0];
- this._curSeg = this._segments[0];
- this._s2 = this._curSeg[0];
- this._prec = 1 / this._curSeg.length;
- }
-
- if ((autoRotate = this._autoRotate)) {
- this._initialRotations = [];
- if (!(autoRotate[0] instanceof Array)) {
- this._autoRotate = autoRotate = [autoRotate];
- }
- i = autoRotate.length;
- while (--i > -1) {
- for (j = 0; j < 3; j++) {
- p = autoRotate[i][j];
- this._func[p] = (typeof(target[p]) === "function") ? target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ] : false;
- }
- p = autoRotate[i][2];
- this._initialRotations[i] = this._func[p] ? this._func[p].call(this._target) : this._target[p];
- }
- }
- this._startRatio = tween.vars.runBackwards ? 1 : 0; //we determine the starting ratio when the tween inits which is always 0 unless the tween has runBackwards:true (indicating it's a from() tween) in which case it's 1.
- return true;
- },
-
- //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
- set: function(v) {
- var segments = this._segCount,
- func = this._func,
- target = this._target,
- notStart = (v !== this._startRatio),
- curIndex, inv, i, p, b, t, val, l, lengths, curSeg;
- if (!this._timeRes) {
- curIndex = (v < 0) ? 0 : (v >= 1) ? segments - 1 : (segments * v) >> 0;
- t = (v - (curIndex * (1 / segments))) * segments;
- } else {
- lengths = this._lengths;
- curSeg = this._curSeg;
- v *= this._length;
- i = this._li;
- //find the appropriate segment (if the currently cached one isn't correct)
- if (v > this._l2 && i < segments - 1) {
- l = segments - 1;
- while (i < l && (this._l2 = lengths[++i]) <= v) { }
- this._l1 = lengths[i-1];
- this._li = i;
- this._curSeg = curSeg = this._segments[i];
- this._s2 = curSeg[(this._s1 = this._si = 0)];
- } else if (v < this._l1 && i > 0) {
- while (i > 0 && (this._l1 = lengths[--i]) >= v) { }
- if (i === 0 && v < this._l1) {
- this._l1 = 0;
- } else {
- i++;
- }
- this._l2 = lengths[i];
- this._li = i;
- this._curSeg = curSeg = this._segments[i];
- this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
- this._s2 = curSeg[this._si];
- }
- curIndex = i;
- //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one)
- v -= this._l1;
- i = this._si;
- if (v > this._s2 && i < curSeg.length - 1) {
- l = curSeg.length - 1;
- while (i < l && (this._s2 = curSeg[++i]) <= v) { }
- this._s1 = curSeg[i-1];
- this._si = i;
- } else if (v < this._s1 && i > 0) {
- while (i > 0 && (this._s1 = curSeg[--i]) >= v) { }
- if (i === 0 && v < this._s1) {
- this._s1 = 0;
- } else {
- i++;
- }
- this._s2 = curSeg[i];
- this._si = i;
- }
- t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec;
- }
- inv = 1 - t;
-
- i = this._props.length;
- while (--i > -1) {
- p = this._props[i];
- b = this._beziers[p][curIndex];
- val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
- if (this._round[p]) {
- val = Math.round(val);
- }
- if (func[p]) {
- target[p](val);
- } else {
- target[p] = val;
- }
- }
-
- if (this._autoRotate) {
- var ar = this._autoRotate,
- b2, x1, y1, x2, y2, add, conv;
- i = ar.length;
- while (--i > -1) {
- p = ar[i][2];
- add = ar[i][3] || 0;
- conv = (ar[i][4] === true) ? 1 : _RAD2DEG;
- b = this._beziers[ar[i][0]];
- b2 = this._beziers[ar[i][1]];
-
- if (b && b2) { //in case one of the properties got overwritten.
- b = b[curIndex];
- b2 = b2[curIndex];
-
- x1 = b.a + (b.b - b.a) * t;
- x2 = b.b + (b.c - b.b) * t;
- x1 += (x2 - x1) * t;
- x2 += ((b.c + (b.d - b.c) * t) - x2) * t;
-
- y1 = b2.a + (b2.b - b2.a) * t;
- y2 = b2.b + (b2.c - b2.b) * t;
- y1 += (y2 - y1) * t;
- y2 += ((b2.c + (b2.d - b2.c) * t) - y2) * t;
-
- val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i];
-
- if (func[p]) {
- target[p](val);
- } else {
- target[p] = val;
- }
- }
- }
- }
- }
- }),
- p = BezierPlugin.prototype;
-
-
- BezierPlugin.bezierThrough = bezierThrough;
- BezierPlugin.cubicToQuadratic = cubicToQuadratic;
- BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite
- BezierPlugin.quadraticToCubic = function(a, b, c) {
- return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
- };
-
- BezierPlugin._cssRegister = function() {
- var CSSPlugin = window._gsDefine.globals.CSSPlugin;
- if (!CSSPlugin) {
- return;
- }
- var _internals = CSSPlugin._internals,
- _parseToProxy = _internals._parseToProxy,
- _setPluginRatio = _internals._setPluginRatio,
- CSSPropTween = _internals.CSSPropTween;
- _internals._registerComplexSpecialProp("bezier", {parser:function(t, e, prop, cssp, pt, plugin) {
- if (e instanceof Array) {
- e = {values:e};
- }
- plugin = new BezierPlugin();
- var values = e.values,
- l = values.length - 1,
- pluginValues = [],
- v = {},
- i, p, data;
- if (l < 0) {
- return pt;
- }
- for (i = 0; i <= l; i++) {
- data = _parseToProxy(t, values[i], cssp, pt, plugin, (l !== i));
- pluginValues[i] = data.end;
- }
- for (p in e) {
- v[p] = e[p]; //duplicate the vars object because we need to alter some things which would cause problems if the user plans to reuse the same vars object for another tween.
- }
- v.values = pluginValues;
- pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2);
- pt.data = data;
- pt.plugin = plugin;
- pt.setRatio = _setPluginRatio;
- if (v.autoRotate === 0) {
- v.autoRotate = true;
- }
- if (v.autoRotate && !(v.autoRotate instanceof Array)) {
- i = (v.autoRotate === true) ? 0 : Number(v.autoRotate);
- v.autoRotate = (data.end.left != null) ? [["left","top","rotation",i,false]] : (data.end.x != null) ? [["x","y","rotation",i,false]] : false;
- }
- if (v.autoRotate) {
- if (!cssp._transform) {
- cssp._enableTransforms(false);
- }
- data.autoRotate = cssp._target._gsTransform;
- }
- plugin._onInitTween(data.proxy, v, cssp._tween);
- return pt;
- }});
- };
-
- p._roundProps = function(lookup, value) {
- var op = this._overwriteProps,
- i = op.length;
- while (--i > -1) {
- if (lookup[op[i]] || lookup.bezier || lookup.bezierThrough) {
- this._round[op[i]] = value;
- }
- }
- };
-
- p._kill = function(lookup) {
- var a = this._props,
- p, i;
- for (p in this._beziers) {
- if (p in lookup) {
- delete this._beziers[p];
- delete this._func[p];
- i = a.length;
- while (--i > -1) {
- if (a[i] === p) {
- a.splice(i, 1);
- }
- }
- }
- }
- return this._super._kill.call(this, lookup);
- };
-
- }());
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * CSSPlugin
- * ----------------------------------------------------------------
- */
- window._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin","TweenLite"], function(TweenPlugin, TweenLite) {
-
- /** @constructor **/
- var CSSPlugin = function() {
- TweenPlugin.call(this, "css");
- this._overwriteProps.length = 0;
- this.setRatio = CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method)
- },
- _hasPriority, //turns true whenever a CSSPropTween instance is created that has a priority other than 0. This helps us discern whether or not we should spend the time organizing the linked list or not after a CSSPlugin's _onInitTween() method is called.
- _suffixMap, //we set this in _onInitTween() each time as a way to have a persistent variable we can use in other methods like _parse() without having to pass it around as a parameter and we keep _parse() decoupled from a particular CSSPlugin instance
- _cs, //computed style (we store this in a shared variable to conserve memory and make minification tighter
- _overwriteProps, //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification.
- _specialProps = {},
- p = CSSPlugin.prototype = new TweenPlugin("css");
-
- p.constructor = CSSPlugin;
- CSSPlugin.version = "1.12.1";
- CSSPlugin.API = 2;
- CSSPlugin.defaultTransformPerspective = 0;
- CSSPlugin.defaultSkewType = "compensated";
- p = "px"; //we'll reuse the "p" variable to keep file size down
- CSSPlugin.suffixMap = {top:p, right:p, bottom:p, left:p, width:p, height:p, fontSize:p, padding:p, margin:p, perspective:p, lineHeight:""};
-
-
- var _numExp = /(?:\d|\-\d|\.\d|\-\.\d)+/g,
- _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
- _valuesExp = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, //finds all the values that begin with numbers or += or -= and then a number. Includes suffixes. We use this to split complex values apart like "1px 5px 20px rgb(255,102,51)"
- _NaNExp = /[^\d\-\.]/g,
- _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
- _opacityExp = /opacity *= *([^)]*)/i,
- _opacityValExp = /opacity:([^;]*)/i,
- _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
- _rgbhslExp = /^(rgb|hsl)/,
- _capsExp = /([A-Z])/g,
- _camelExp = /-([a-z])/gi,
- _urlExp = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, //for pulling out urls from url(...) or url("...") strings (some browsers wrap urls in quotes, some don't when reporting things like backgroundImage)
- _camelFunc = function(s, g) { return g.toUpperCase(); },
- _horizExp = /(?:Left|Right|Width)/i,
- _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi,
- _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,
- _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, //finds any commas that are not within parenthesis
- _DEG2RAD = Math.PI / 180,
- _RAD2DEG = 180 / Math.PI,
- _forcePT = {},
- _doc = document,
- _tempDiv = _doc.createElement("div"),
- _tempImg = _doc.createElement("img"),
- _internals = CSSPlugin._internals = {_specialProps:_specialProps}, //provides a hook to a few internal methods that we need to access from inside other plugins
- _agent = navigator.userAgent,
- _autoRound,
- _reqSafariFix, //we won't apply the Safari transform fix until we actually come across a tween that affects a transform property (to maintain best performance).
-
- _isSafari,
- _isFirefox, //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element.
- _isSafariLT6, //Safari (and Android 4 which uses a flavor of Safari) has a bug that prevents changes to "top" and "left" properties from rendering properly if changed on the same frame as a transform UNLESS we set the element's WebkitBackfaceVisibility to hidden (weird, I know). Doing this for Android 3 and earlier seems to actually cause other problems, though (fun!)
- _ieVers,
- _supportsOpacity = (function() { //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version.
- var i = _agent.indexOf("Android"),
- d = _doc.createElement("div"), a;
-
- _isSafari = (_agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || Number(_agent.substr(i+8, 1)) > 3));
- _isSafariLT6 = (_isSafari && (Number(_agent.substr(_agent.indexOf("Version/")+8, 1)) < 6));
- _isFirefox = (_agent.indexOf("Firefox") !== -1);
-
- if ((/MSIE ([0-9]{1,}[\.0-9]{0,})/).exec(_agent)) {
- _ieVers = parseFloat( RegExp.$1 );
- }
-
- d.innerHTML = "<a style='top:1px;opacity:.55;'>a</a>";
- a = d.getElementsByTagName("a")[0];
- return a ? /^0.55/.test(a.style.opacity) : false;
- }()),
- _getIEOpacity = function(v) {
- return (_opacityExp.test( ((typeof(v) === "string") ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ) ? ( parseFloat( RegExp.$1 ) / 100 ) : 1);
- },
- _log = function(s) {//for logging messages, but in a way that won't throw errors in old versions of IE.
- if (window.console) {
- //console.log(s);
- }
- },
- _prefixCSS = "", //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-"
- _prefix = "", //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz".
-
- // @private feed in a camelCase property name like "transform" and it will check to see if it is valid as-is or if it needs a vendor prefix. It returns the corrected camelCase property name (i.e. "WebkitTransform" or "MozTransform" or "transform" or null if no such property is found, like if the browser is IE8 or before, "transform" won't be found at all)
- _checkPropPrefix = function(p, e) {
- e = e || _tempDiv;
- var s = e.style,
- a, i;
- if (s[p] !== undefined) {
- return p;
- }
- p = p.charAt(0).toUpperCase() + p.substr(1);
- a = ["O","Moz","ms","Ms","Webkit"];
- i = 5;
- while (--i > -1 && s[a[i]+p] === undefined) { }
- if (i >= 0) {
- _prefix = (i === 3) ? "ms" : a[i];
- _prefixCSS = "-" + _prefix.toLowerCase() + "-";
- return _prefix + p;
- }
- return null;
- },
-
- _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function() {},
-
- /**
- * @private Returns the css style for a particular property of an element. For example, to get whatever the current "left" css value for an element with an ID of "myElement", you could do:
- * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left");
- *
- * @param {!Object} t Target element whose style property you want to query
- * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.)
- * @param {Object=} cs Computed style object. This just provides a way to speed processing if you're going to get several properties on the same element in quick succession - you can reuse the result of the getComputedStyle() call.
- * @param {boolean=} calc If true, the value will not be read directly from the element's "style" property (if it exists there), but instead the getComputedStyle() result will be used. This can be useful when you want to ensure that the browser itself is interpreting the value.
- * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto".
- * @return {?string} The current property value
- */
- _getStyle = CSSPlugin.getStyle = function(t, p, cs, calc, dflt) {
- var rv;
- if (!_supportsOpacity) if (p === "opacity") { //several versions of IE don't use the standard "opacity" property - they use things like filter:alpha(opacity=50), so we parse that here.
- return _getIEOpacity(t);
- }
- if (!calc && t.style[p]) {
- rv = t.style[p];
- } else if ((cs = cs || _getComputedStyle(t))) {
- rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
- } else if (t.currentStyle) {
- rv = t.currentStyle[p];
- }
- return (dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto")) ? dflt : rv;
- },
-
- /**
- * @private Pass the target element, the property name, the numeric value, and the suffix (like "%", "em", "px", etc.) and it will spit back the equivalent pixel number.
- * @param {!Object} t Target element
- * @param {!string} p Property name (like "left", "top", "marginLeft", etc.)
- * @param {!number} v Value
- * @param {string=} sfx Suffix (like "px" or "%" or "em")
- * @param {boolean=} recurse If true, the call is a recursive one. In some browsers (like IE7/8), occasionally the value isn't accurately reported initially, but if we run the function again it will take effect.
- * @return {number} value in pixels
- */
- _convertToPixels = _internals.convertToPixels = function(t, p, v, sfx, recurse) {
- if (sfx === "px" || !sfx) { return v; }
- if (sfx === "auto" || !v) { return 0; }
- var horiz = _horizExp.test(p),
- node = t,
- style = _tempDiv.style,
- neg = (v < 0),
- pix, cache, time;
- if (neg) {
- v = -v;
- }
- if (sfx === "%" && p.indexOf("border") !== -1) {
- pix = (v / 100) * (horiz ? t.clientWidth : t.clientHeight);
- } else {
- style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;";
- if (sfx === "%" || !node.appendChild) {
- node = t.parentNode || _doc.body;
- cache = node._gsCache;
- time = TweenLite.ticker.frame;
- if (cache && horiz && cache.time === time) { //performance optimization: we record the width of elements along with the ticker frame so that we can quickly get it again on the same tick (seems relatively safe to assume it wouldn't change on the same tick)
- return cache.width * v / 100;
- }
- style[(horiz ? "width" : "height")] = v + sfx;
- } else {
- style[(horiz ? "borderLeftWidth" : "borderTopWidth")] = v + sfx;
- }
- node.appendChild(_tempDiv);
- pix = parseFloat(_tempDiv[(horiz ? "offsetWidth" : "offsetHeight")]);
- node.removeChild(_tempDiv);
- if (horiz && sfx === "%" && CSSPlugin.cacheWidths !== false) {
- cache = node._gsCache = node._gsCache || {};
- cache.time = time;
- cache.width = pix / v * 100;
- }
- if (pix === 0 && !recurse) {
- pix = _convertToPixels(t, p, v, sfx, true);
- }
- }
- return neg ? -pix : pix;
- },
- _calculateOffset = _internals.calculateOffset = function(t, p, cs) { //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop
- if (_getStyle(t, "position", cs) !== "absolute") { return 0; }
- var dim = ((p === "left") ? "Left" : "Top"),
- v = _getStyle(t, "margin" + dim, cs);
- return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0);
- },
-
- // @private returns at object containing ALL of the style properties in camelCase and their associated values.
- _getAllStyles = function(t, cs) {
- var s = {},
- i, tr;
- if ((cs = cs || _getComputedStyle(t, null))) {
- if ((i = cs.length)) {
- while (--i > -1) {
- s[cs[i].replace(_camelExp, _camelFunc)] = cs.getPropertyValue(cs[i]);
- }
- } else { //Opera behaves differently - cs.length is always 0, so we must do a for...in loop.
- for (i in cs) {
- s[i] = cs[i];
- }
- }
- } else if ((cs = t.currentStyle || t.style)) {
- for (i in cs) {
- if (typeof(i) === "string" && s[i] === undefined) {
- s[i.replace(_camelExp, _camelFunc)] = cs[i];
- }
- }
- }
- if (!_supportsOpacity) {
- s.opacity = _getIEOpacity(t);
- }
- tr = _getTransform(t, cs, false);
- s.rotation = tr.rotation;
- s.skewX = tr.skewX;
- s.scaleX = tr.scaleX;
- s.scaleY = tr.scaleY;
- s.x = tr.x;
- s.y = tr.y;
- if (_supports3D) {
- s.z = tr.z;
- s.rotationX = tr.rotationX;
- s.rotationY = tr.rotationY;
- s.scaleZ = tr.scaleZ;
- }
- if (s.filters) {
- delete s.filters;
- }
- return s;
- },
-
- // @private analyzes two style objects (as returned by _getAllStyles()) and only looks for differences between them that contain tweenable values (like a number or color). It returns an object with a "difs" property which refers to an object containing only those isolated properties and values for tweening, and a "firstMPT" property which refers to the first MiniPropTween instance in a linked list that recorded all the starting values of the different properties so that we can revert to them at the end or beginning of the tween - we don't want the cascading to get messed up. The forceLookup parameter is an optional generic object with properties that should be forced into the results - this is necessary for className tweens that are overwriting others because imagine a scenario where a rollover/rollout adds/removes a class and the user swipes the mouse over the target SUPER fast, thus nothing actually changed yet and the subsequent comparison of the properties would indicate they match (especially when px rounding is taken into consideration), thus no tweening is necessary even though it SHOULD tween and remove those properties after the tween (otherwise the inline styles will contaminate things). See the className SpecialProp code for details.
- _cssDif = function(t, s1, s2, vars, forceLookup) {
- var difs = {},
- style = t.style,
- val, p, mpt;
- for (p in s2) {
- if (p !== "cssText") if (p !== "length") if (isNaN(p)) if (s1[p] !== (val = s2[p]) || (forceLookup && forceLookup[p])) if (p.indexOf("Origin") === -1) if (typeof(val) === "number" || typeof(val) === "string") {
- difs[p] = (val === "auto" && (p === "left" || p === "top")) ? _calculateOffset(t, p) : ((val === "" || val === "auto" || val === "none") && typeof(s1[p]) === "string" && s1[p].replace(_NaNExp, "") !== "") ? 0 : val; //if the ending value is defaulting ("" or "auto"), we check the starting value and if it can be parsed into a number (a string which could have a suffix too, like 700px), then we swap in 0 for "" or "auto" so that things actually tween.
- if (style[p] !== undefined) { //for className tweens, we must remember which properties already existed inline - the ones that didn't should be removed when the tween isn't in progress because they were only introduced to facilitate the transition between classes.
- mpt = new MiniPropTween(style, p, style[p], mpt);
- }
- }
- }
- if (vars) {
- for (p in vars) { //copy properties (except className)
- if (p !== "className") {
- difs[p] = vars[p];
- }
- }
- }
- return {difs:difs, firstMPT:mpt};
- },
- _dimensions = {width:["Left","Right"], height:["Top","Bottom"]},
- _margins = ["marginLeft","marginRight","marginTop","marginBottom"],
-
- /**
- * @private Gets the width or height of an element
- * @param {!Object} t Target element
- * @param {!string} p Property name ("width" or "height")
- * @param {Object=} cs Computed style object (if one exists). Just a speed optimization.
- * @return {number} Dimension (in pixels)
- */
- _getDimension = function(t, p, cs) {
- var v = parseFloat((p === "width") ? t.offsetWidth : t.offsetHeight),
- a = _dimensions[p],
- i = a.length;
- cs = cs || _getComputedStyle(t, null);
- while (--i > -1) {
- v -= parseFloat( _getStyle(t, "padding" + a[i], cs, true) ) || 0;
- v -= parseFloat( _getStyle(t, "border" + a[i] + "Width", cs, true) ) || 0;
- }
- return v;
- },
-
- // @private Parses position-related complex strings like "top left" or "50px 10px" or "70% 20%", etc. which are used for things like transformOrigin or backgroundPosition. Optionally decorates a supplied object (recObj) with the following properties: "ox" (offsetX), "oy" (offsetY), "oxp" (if true, "ox" is a percentage not a pixel value), and "oxy" (if true, "oy" is a percentage not a pixel value)
- _parsePosition = function(v, recObj) {
- if (v == null || v === "" || v === "auto" || v === "auto auto") { //note: Firefox uses "auto auto" as default whereas Chrome uses "auto".
- v = "0 0";
- }
- var a = v.split(" "),
- x = (v.indexOf("left") !== -1) ? "0%" : (v.indexOf("right") !== -1) ? "100%" : a[0],
- y = (v.indexOf("top") !== -1) ? "0%" : (v.indexOf("bottom") !== -1) ? "100%" : a[1];
- if (y == null) {
- y = "0";
- } else if (y === "center") {
- y = "50%";
- }
- if (x === "center" || (isNaN(parseFloat(x)) && (x + "").indexOf("=") === -1)) { //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it could be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative.
- x = "50%";
- }
- if (recObj) {
- recObj.oxp = (x.indexOf("%") !== -1);
- recObj.oyp = (y.indexOf("%") !== -1);
- recObj.oxr = (x.charAt(1) === "=");
- recObj.oyr = (y.charAt(1) === "=");
- recObj.ox = parseFloat(x.replace(_NaNExp, ""));
- recObj.oy = parseFloat(y.replace(_NaNExp, ""));
- }
- return x + " " + y + ((a.length > 2) ? " " + a[2] : "");
- },
-
- /**
- * @private Takes an ending value (typically a string, but can be a number) and a starting value and returns the change between the two, looking for relative value indicators like += and -= and it also ignores suffixes (but make sure the ending value starts with a number or +=/-= and that the starting value is a NUMBER!)
- * @param {(number|string)} e End value which is typically a string, but could be a number
- * @param {(number|string)} b Beginning value which is typically a string but could be a number
- * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized)
- */
- _parseChange = function(e, b) {
- return (typeof(e) === "string" && e.charAt(1) === "=") ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b);
- },
-
- /**
- * @private Takes a value and a default number, checks if the value is relative, null, or numeric and spits back a normalized number accordingly. Primarily used in the _parseTransform() function.
- * @param {Object} v Value to be parsed
- * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
- * @return {number} Parsed value
- */
- _parseVal = function(v, d) {
- return (v == null) ? d : (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) + d : parseFloat(v);
- },
-
- /**
- * @private Translates strings like "40deg" or "40" or 40rad" or "+=40deg" or "270_short" or "-90_cw" or "+=45_ccw" to a numeric radian angle. Of course a starting/default value must be fed in too so that relative values can be calculated properly.
- * @param {Object} v Value to be parsed
- * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
- * @param {string=} p property name for directionalEnd (optional - only used when the parsed value is directional ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation). Property name would be "rotation", "rotationX", or "rotationY"
- * @param {Object=} directionalEnd An object that will store the raw end values for directional angles ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation.
- * @return {number} parsed angle in radians
- */
- _parseAngle = function(v, d, p, directionalEnd) {
- var min = 0.000001,
- cap, split, dif, result;
- if (v == null) {
- result = d;
- } else if (typeof(v) === "number") {
- result = v;
- } else {
- cap = 360;
- split = v.split("_");
- dif = Number(split[0].replace(_NaNExp, "")) * ((v.indexOf("rad") === -1) ? 1 : _RAD2DEG) - ((v.charAt(1) === "=") ? 0 : d);
- if (split.length) {
- if (directionalEnd) {
- directionalEnd[p] = d + dif;
- }
- if (v.indexOf("short") !== -1) {
- dif = dif % cap;
- if (dif !== dif % (cap / 2)) {
- dif = (dif < 0) ? dif + cap : dif - cap;
- }
- }
- if (v.indexOf("_cw") !== -1 && dif < 0) {
- dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
- } else if (v.indexOf("ccw") !== -1 && dif > 0) {
- dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
- }
- }
- result = d + dif;
- }
- if (result < min && result > -min) {
- result = 0;
- }
- return result;
- },
-
- _colorLookup = {aqua:[0,255,255],
- lime:[0,255,0],
- silver:[192,192,192],
- black:[0,0,0],
- maroon:[128,0,0],
- teal:[0,128,128],
- blue:[0,0,255],
- navy:[0,0,128],
- white:[255,255,255],
- fuchsia:[255,0,255],
- olive:[128,128,0],
- yellow:[255,255,0],
- orange:[255,165,0],
- gray:[128,128,128],
- purple:[128,0,128],
- green:[0,128,0],
- red:[255,0,0],
- pink:[255,192,203],
- cyan:[0,255,255],
- transparent:[255,255,255,0]},
-
- _hue = function(h, m1, m2) {
- h = (h < 0) ? h + 1 : (h > 1) ? h - 1 : h;
- return ((((h * 6 < 1) ? m1 + (m2 - m1) * h * 6 : (h < 0.5) ? m2 : (h * 3 < 2) ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * 255) + 0.5) | 0;
- },
-
- /**
- * @private Parses a color (like #9F0, #FF9900, or rgb(255,51,153)) into an array with 3 elements for red, green, and blue. Also handles rgba() values (splits into array of 4 elements of course)
- * @param {(string|number)} v The value the should be parsed which could be a string like #9F0 or rgb(255,102,51) or rgba(255,0,0,0.5) or it could be a number like 0xFF00CC or even a named color like red, blue, purple, etc.
- * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order.
- */
- _parseColor = function(v) {
- var c1, c2, c3, h, s, l;
- if (!v || v === "") {
- return _colorLookup.black;
- }
- if (typeof(v) === "number") {
- return [v >> 16, (v >> 8) & 255, v & 255];
- }
- if (v.charAt(v.length - 1) === ",") { //sometimes a trailing commma is included and we should chop it off (typically from a comma-delimited list of values like a textShadow:"2px 2px 2px blue, 5px 5px 5px rgb(255,0,0)" - in this example "blue," has a trailing comma. We could strip it out inside parseComplex() but we'd need to do it to the beginning and ending values plus it wouldn't provide protection from other potential scenarios like if the user passes in a similar value.
- v = v.substr(0, v.length - 1);
- }
- if (_colorLookup[v]) {
- return _colorLookup[v];
- }
- if (v.charAt(0) === "#") {
- if (v.length === 4) { //for shorthand like #9F0
- c1 = v.charAt(1),
- c2 = v.charAt(2),
- c3 = v.charAt(3);
- v = "#" + c1 + c1 + c2 + c2 + c3 + c3;
- }
- v = parseInt(v.substr(1), 16);
- return [v >> 16, (v >> 8) & 255, v & 255];
- }
- if (v.substr(0, 3) === "hsl") {
- v = v.match(_numExp);
- h = (Number(v[0]) % 360) / 360;
- s = Number(v[1]) / 100;
- l = Number(v[2]) / 100;
- c2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
- c1 = l * 2 - c2;
- if (v.length > 3) {
- v[3] = Number(v[3]);
- }
- v[0] = _hue(h + 1 / 3, c1, c2);
- v[1] = _hue(h, c1, c2);
- v[2] = _hue(h - 1 / 3, c1, c2);
- return v;
- }
- v = v.match(_numExp) || _colorLookup.transparent;
- v[0] = Number(v[0]);
- v[1] = Number(v[1]);
- v[2] = Number(v[2]);
- if (v.length > 3) {
- v[3] = Number(v[3]);
- }
- return v;
- },
- _colorExp = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#.+?\\b"; //we'll dynamically build this Regular Expression to conserve file size. After building it, it will be able to find rgb(), rgba(), # (hexadecimal), and named color values like red, blue, purple, etc.
-
- for (p in _colorLookup) {
- _colorExp += "|" + p + "\\b";
- }
- _colorExp = new RegExp(_colorExp+")", "gi");
-
- /**
- * @private Returns a formatter function that handles taking a string (or number in some cases) and returning a consistently formatted one in terms of delimiters, quantity of values, etc. For example, we may get boxShadow values defined as "0px red" or "0px 0px 10px rgb(255,0,0)" or "0px 0px 20px 20px #F00" and we need to ensure that what we get back is described with 4 numbers and a color. This allows us to feed it into the _parseComplex() method and split the values up appropriately. The neat thing about this _getFormatter() function is that the dflt defines a pattern as well as a default, so for example, _getFormatter("0px 0px 0px 0px #777", true) not only sets the default as 0px for all distances and #777 for the color, but also sets the pattern such that 4 numbers and a color will always get returned.
- * @param {!string} dflt The default value and pattern to follow. So "0px 0px 0px 0px #777" will ensure that 4 numbers and a color will always get returned.
- * @param {boolean=} clr If true, the values should be searched for color-related data. For example, boxShadow values typically contain a color whereas borderRadius don't.
- * @param {boolean=} collapsible If true, the value is a top/left/right/bottom style one that acts like margin or padding, where if only one value is received, it's used for all 4; if 2 are received, the first is duplicated for 3rd (bottom) and the 2nd is duplicated for the 4th spot (left), etc.
- * @return {Function} formatter function
- */
- var _getFormatter = function(dflt, clr, collapsible, multi) {
- if (dflt == null) {
- return function(v) {return v;};
- }
- var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "",
- dVals = dflt.split(dColor).join("").match(_valuesExp) || [],
- pfx = dflt.substr(0, dflt.indexOf(dVals[0])),
- sfx = (dflt.charAt(dflt.length - 1) === ")") ? ")" : "",
- delim = (dflt.indexOf(" ") !== -1) ? " " : ",",
- numVals = dVals.length,
- dSfx = (numVals > 0) ? dVals[0].replace(_numExp, "") : "",
- formatter;
- if (!numVals) {
- return function(v) {return v;};
- }
- if (clr) {
- formatter = function(v) {
- var color, vals, i, a;
- if (typeof(v) === "number") {
- v += dSfx;
- } else if (multi && _commasOutsideParenExp.test(v)) {
- a = v.replace(_commasOutsideParenExp, "|").split("|");
- for (i = 0; i < a.length; i++) {
- a[i] = formatter(a[i]);
- }
- return a.join(",");
- }
- color = (v.match(_colorExp) || [dColor])[0];
- vals = v.split(color).join("").match(_valuesExp) || [];
- i = vals.length;
- if (numVals > i--) {
- while (++i < numVals) {
- vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
- }
- }
- return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : "");
- };
- return formatter;
-
- }
- formatter = function(v) {
- var vals, a, i;
- if (typeof(v) === "number") {
- v += dSfx;
- } else if (multi && _commasOutsideParenExp.test(v)) {
- a = v.replace(_commasOutsideParenExp, "|").split("|");
- for (i = 0; i < a.length; i++) {
- a[i] = formatter(a[i]);
- }
- return a.join(",");
- }
- vals = v.match(_valuesExp) || [];
- i = vals.length;
- if (numVals > i--) {
- while (++i < numVals) {
- vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
- }
- }
- return pfx + vals.join(delim) + sfx;
- };
- return formatter;
- },
-
- /**
- * @private returns a formatter function that's used for edge-related values like marginTop, marginLeft, paddingBottom, paddingRight, etc. Just pass a comma-delimited list of property names related to the edges.
- * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft"
- * @return {Function} a formatter function
- */
- _getEdgeParser = function(props) {
- props = props.split(",");
- return function(t, e, p, cssp, pt, plugin, vars) {
- var a = (e + "").split(" "),
- i;
- vars = {};
- for (i = 0; i < 4; i++) {
- vars[props[i]] = a[i] = a[i] || a[(((i - 1) / 2) >> 0)];
- }
- return cssp.parse(t, vars, pt, plugin);
- };
- },
-
- // @private used when other plugins must tween values first, like BezierPlugin or ThrowPropsPlugin, etc. That plugin's setRatio() gets called first so that the values are updated, and then we loop through the MiniPropTweens which handle copying the values into their appropriate slots so that they can then be applied correctly in the main CSSPlugin setRatio() method. Remember, we typically create a proxy object that has a bunch of uniquely-named properties that we feed to the sub-plugin and it does its magic normally, and then we must interpret those values and apply them to the css because often numbers must get combined/concatenated, suffixes added, etc. to work with css, like boxShadow could have 4 values plus a color.
- _setPluginRatio = _internals._setPluginRatio = function(v) {
- this.plugin.setRatio(v);
- var d = this.data,
- proxy = d.proxy,
- mpt = d.firstMPT,
- min = 0.000001,
- val, pt, i, str;
- while (mpt) {
- val = proxy[mpt.v];
- if (mpt.r) {
- val = Math.round(val);
- } else if (val < min && val > -min) {
- val = 0;
- }
- mpt.t[mpt.p] = val;
- mpt = mpt._next;
- }
- if (d.autoRotate) {
- d.autoRotate.rotation = proxy.rotation;
- }
- //at the end, we must set the CSSPropTween's "e" (end) value dynamically here because that's what is used in the final setRatio() method.
- if (v === 1) {
- mpt = d.firstMPT;
- while (mpt) {
- pt = mpt.t;
- if (!pt.type) {
- pt.e = pt.s + pt.xs0;
- } else if (pt.type === 1) {
- str = pt.xs0 + pt.s + pt.xs1;
- for (i = 1; i < pt.l; i++) {
- str += pt["xn"+i] + pt["xs"+(i+1)];
- }
- pt.e = str;
- }
- mpt = mpt._next;
- }
- }
- },
-
- /**
- * @private @constructor Used by a few SpecialProps to hold important values for proxies. For example, _parseToProxy() creates a MiniPropTween instance for each property that must get tweened on the proxy, and we record the original property name as well as the unique one we create for the proxy, plus whether or not the value needs to be rounded plus the original value.
- * @param {!Object} t target object whose property we're tweening (often a CSSPropTween)
- * @param {!string} p property name
- * @param {(number|string|object)} v value
- * @param {MiniPropTween=} next next MiniPropTween in the linked list
- * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer
- */
- MiniPropTween = function(t, p, v, next, r) {
- this.t = t;
- this.p = p;
- this.v = v;
- this.r = r;
- if (next) {
- next._prev = this;
- this._next = next;
- }
- },
-
- /**
- * @private Most other plugins (like BezierPlugin and ThrowPropsPlugin and others) can only tween numeric values, but CSSPlugin must accommodate special values that have a bunch of extra data (like a suffix or strings between numeric values, etc.). For example, boxShadow has values like "10px 10px 20px 30px rgb(255,0,0)" which would utterly confuse other plugins. This method allows us to split that data apart and grab only the numeric data and attach it to uniquely-named properties of a generic proxy object ({}) so that we can feed that to virtually any plugin to have the numbers tweened. However, we must also keep track of which properties from the proxy go with which CSSPropTween values and instances. So we create a linked list of MiniPropTweens. Each one records a target (the original CSSPropTween), property (like "s" or "xn1" or "xn2") that we're tweening and the unique property name that was used for the proxy (like "boxShadow_xn1" and "boxShadow_xn2") and whether or not they need to be rounded. That way, in the _setPluginRatio() method we can simply copy the values over from the proxy to the CSSPropTween instance(s). Then, when the main CSSPlugin setRatio() method runs and applies the CSSPropTween values accordingly, they're updated nicely. So the external plugin tweens the numbers, _setPluginRatio() copies them over, and setRatio() acts normally, applying css-specific values to the element.
- * This method returns an object that has the following properties:
- * - proxy: a generic object containing the starting values for all the properties that will be tweened by the external plugin. This is what we feed to the external _onInitTween() as the target
- * - end: a generic object containing the ending values for all the properties that will be tweened by the external plugin. This is what we feed to the external plugin's _onInitTween() as the destination values
- * - firstMPT: the first MiniPropTween in the linked list
- * - pt: the first CSSPropTween in the linked list that was created when parsing. If shallow is true, this linked list will NOT attach to the one passed into the _parseToProxy() as the "pt" (4th) parameter.
- * @param {!Object} t target object to be tweened
- * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed
- * @param {!CSSPlugin} cssp The CSSPlugin instance
- * @param {CSSPropTween=} pt the next CSSPropTween in the linked list
- * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values
- * @param {boolean=} shallow if true, the resulting linked list from the parse will NOT be attached to the CSSPropTween that was passed in as the "pt" (4th) parameter.
- * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions)
- */
- _parseToProxy = _internals._parseToProxy = function(t, vars, cssp, pt, plugin, shallow) {
- var bpt = pt,
- start = {},
- end = {},
- transform = cssp._transform,
- oldForce = _forcePT,
- i, p, xp, mpt, firstPT;
- cssp._transform = null;
- _forcePT = vars;
- pt = firstPT = cssp.parse(t, vars, pt, plugin);
- _forcePT = oldForce;
- //break off from the linked list so the new ones are isolated.
- if (shallow) {
- cssp._transform = transform;
- if (bpt) {
- bpt._prev = null;
- if (bpt._prev) {
- bpt._prev._next = null;
- }
- }
- }
- while (pt && pt !== bpt) {
- if (pt.type <= 1) {
- p = pt.p;
- end[p] = pt.s + pt.c;
- start[p] = pt.s;
- if (!shallow) {
- mpt = new MiniPropTween(pt, "s", p, mpt, pt.r);
- pt.c = 0;
- }
- if (pt.type === 1) {
- i = pt.l;
- while (--i > 0) {
- xp = "xn" + i;
- p = pt.p + "_" + xp;
- end[p] = pt.data[xp];
- start[p] = pt[xp];
- if (!shallow) {
- mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]);
- }
- }
- }
- }
- pt = pt._next;
- }
- return {proxy:start, end:end, firstMPT:mpt, pt:firstPT};
- },
-
-
-
- /**
- * @constructor Each property that is tweened has at least one CSSPropTween associated with it. These instances store important information like the target, property, starting value, amount of change, etc. They can also optionally have a number of "extra" strings and numeric values named xs1, xn1, xs2, xn2, xs3, xn3, etc. where "s" indicates string and "n" indicates number. These can be pieced together in a complex-value tween (type:1) that has alternating types of data like a string, number, string, number, etc. For example, boxShadow could be "5px 5px 8px rgb(102, 102, 51)". In that value, there are 6 numbers that may need to tween and then pieced back together into a string again with spaces, suffixes, etc. xs0 is special in that it stores the suffix for standard (type:0) tweens, -OR- the first string (prefix) in a complex-value (type:1) CSSPropTween -OR- it can be the non-tweening value in a type:-1 CSSPropTween. We do this to conserve memory.
- * CSSPropTweens have the following optional properties as well (not defined through the constructor):
- * - l: Length in terms of the number of extra properties that the CSSPropTween has (default: 0). For example, for a boxShadow we may need to tween 5 numbers in which case l would be 5; Keep in mind that the start/end values for the first number that's tweened are always stored in the s and c properties to conserve memory. All additional values thereafter are stored in xn1, xn2, etc.
- * - xfirst: The first instance of any sub-CSSPropTweens that are tweening properties of this instance. For example, we may split up a boxShadow tween so that there's a main CSSPropTween of type:1 that has various xs* and xn* values associated with the h-shadow, v-shadow, blur, color, etc. Then we spawn a CSSPropTween for each of those that has a higher priority and runs BEFORE the main CSSPropTween so that the values are all set by the time it needs to re-assemble them. The xfirst gives us an easy way to identify the first one in that chain which typically ends at the main one (because they're all prepende to the linked list)
- * - plugin: The TweenPlugin instance that will handle the tweening of any complex values. For example, sometimes we don't want to use normal subtweens (like xfirst refers to) to tween the values - we might want ThrowPropsPlugin or BezierPlugin some other plugin to do the actual tweening, so we create a plugin instance and store a reference here. We need this reference so that if we get a request to round values or disable a tween, we can pass along that request.
- * - data: Arbitrary data that needs to be stored with the CSSPropTween. Typically if we're going to have a plugin handle the tweening of a complex-value tween, we create a generic object that stores the END values that we're tweening to and the CSSPropTween's xs1, xs2, etc. have the starting values. We store that object as data. That way, we can simply pass that object to the plugin and use the CSSPropTween as the target.
- * - setRatio: Only used for type:2 tweens that require custom functionality. In this case, we call the CSSPropTween's setRatio() method and pass the ratio each time the tween updates. This isn't quite as efficient as doing things directly in the CSSPlugin's setRatio() method, but it's very convenient and flexible.
- * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything.
- * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width".
- * @param {number} s Starting numeric value
- * @param {number} c Change in numeric value over the course of the entire tween. For example, if element.width starts at 5 and should end at 100, c would be 95.
- * @param {CSSPropTween=} next The next CSSPropTween in the linked list. If one is defined, we will define its _prev as the new instance, and the new instance's _next will be pointed at it.
- * @param {number=} type The type of CSSPropTween where -1 = a non-tweening value, 0 = a standard simple tween, 1 = a complex value (like one that has multiple numbers in a comma- or space-delimited string like border:"1px solid red"), and 2 = one that uses a custom setRatio function that does all of the work of applying the values on each update.
- * @param {string=} n Name of the property that should be used for overwriting purposes which is typically the same as p but not always. For example, we may need to create a subtween for the 2nd part of a "clip:rect(...)" tween in which case "p" might be xs1 but "n" is still "clip"
- * @param {boolean=} r If true, the value(s) should be rounded
- * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0.
- * @param {string=} b Beginning value. We store this to ensure that it is EXACTLY what it was when the tween began without any risk of interpretation issues.
- * @param {string=} e Ending value. We store this to ensure that it is EXACTLY what the user defined at the end of the tween without any risk of interpretation issues.
- */
- CSSPropTween = _internals.CSSPropTween = function(t, p, s, c, next, type, n, r, pr, b, e) {
- this.t = t; //target
- this.p = p; //property
- this.s = s; //starting value
- this.c = c; //change value
- this.n = n || p; //name that this CSSPropTween should be associated to (usually the same as p, but not always - n is what overwriting looks at)
- if (!(t instanceof CSSPropTween)) {
- _overwriteProps.push(this.n);
- }
- this.r = r; //round (boolean)
- this.type = type || 0; //0 = normal tween, -1 = non-tweening (in which case xs0 will be applied to the target's property, like tp.t[tp.p] = tp.xs0), 1 = complex-value SpecialProp, 2 = custom setRatio() that does all the work
- if (pr) {
- this.pr = pr;
- _hasPriority = true;
- }
- this.b = (b === undefined) ? s : b;
- this.e = (e === undefined) ? s + c : e;
- if (next) {
- this._next = next;
- next._prev = this;
- }
- },
-
- /**
- * Takes a target, the beginning value and ending value (as strings) and parses them into a CSSPropTween (possibly with child CSSPropTweens) that accommodates multiple numbers, colors, comma-delimited values, etc. For example:
- * sp.parseComplex(element, "boxShadow", "5px 10px 20px rgb(255,102,51)", "0px 0px 0px red", true, "0px 0px 0px rgb(0,0,0,0)", pt);
- * It will walk through the beginning and ending values (which should be in the same format with the same number and type of values) and figure out which parts are numbers, what strings separate the numeric/tweenable values, and then create the CSSPropTweens accordingly. If a plugin is defined, no child CSSPropTweens will be created. Instead, the ending values will be stored in the "data" property of the returned CSSPropTween like: {s:-5, xn1:-10, xn2:-20, xn3:255, xn4:0, xn5:0} so that it can be fed to any other plugin and it'll be plain numeric tweens but the recomposition of the complex value will be handled inside CSSPlugin's setRatio().
- * If a setRatio is defined, the type of the CSSPropTween will be set to 2 and recomposition of the values will be the responsibility of that method.
- *
- * @param {!Object} t Target whose property will be tweened
- * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow")
- * @param {string} b Beginning value
- * @param {string} e Ending value
- * @param {boolean} clrs If true, the value could contain a color value like "rgb(255,0,0)" or "#F00" or "red". The default is false, so no colors will be recognized (a performance optimization)
- * @param {(string|number|Object)} dflt The default beginning value that should be used if no valid beginning value is defined or if the number of values inside the complex beginning and ending values don't match
- * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this).
- * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0.
- * @param {TweenPlugin=} plugin If a plugin should handle the tweening of extra properties, pass the plugin instance here. If one is defined, then NO subtweens will be created for any extra properties (the properties will be created - just not additional CSSPropTween instances to tween them) because the plugin is expected to do so. However, the end values WILL be populated in the "data" property, like {s:100, xn1:50, xn2:300}
- * @param {function(number)=} setRatio If values should be set in a custom function instead of being pieced together in a type:1 (complex-value) CSSPropTween, define that custom function here.
- * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call.
- */
- _parseComplex = CSSPlugin.parseComplex = function(t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) {
- //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e);
- b = b || dflt || "";
- pt = new CSSPropTween(t, p, 0, 0, pt, (setRatio ? 2 : 1), null, false, pr, b, e);
- e += ""; //ensures it's a string
- var ba = b.split(", ").join(",").split(" "), //beginning array
- ea = e.split(", ").join(",").split(" "), //ending array
- l = ba.length,
- autoRound = (_autoRound !== false),
- i, xi, ni, bv, ev, bnums, enums, bn, rgba, temp, cv, str;
- if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
- ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
- ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
- l = ba.length;
- }
- if (l !== ea.length) {
- //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
- ba = (dflt || "").split(" ");
- l = ba.length;
- }
- pt.plugin = plugin;
- pt.setRatio = setRatio;
- for (i = 0; i < l; i++) {
- bv = ba[i];
- ev = ea[i];
- bn = parseFloat(bv);
-
- //if the value begins with a number (most common). It's fine if it has a suffix like px
- if (bn || bn === 0) {
- pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), (autoRound && ev.indexOf("px") !== -1), true);
-
- //if the value is a color
- } else if (clrs && (bv.charAt(0) === "#" || _colorLookup[bv] || _rgbhslExp.test(bv))) {
- str = ev.charAt(ev.length - 1) === "," ? ")," : ")"; //if there's a comma at the end, retain it.
- bv = _parseColor(bv);
- ev = _parseColor(ev);
- rgba = (bv.length + ev.length > 6);
- if (rgba && !_supportsOpacity && ev[3] === 0) { //older versions of IE don't support rgba(), so if the destination alpha is 0, just use "transparent" for the end color
- pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
- pt.e = pt.e.split(ea[i]).join("transparent");
- } else {
- if (!_supportsOpacity) { //old versions of IE don't support rgba().
- rgba = false;
- }
- pt.appendXtra((rgba ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true)
- .appendXtra("", bv[1], ev[1] - bv[1], ",", true)
- .appendXtra("", bv[2], ev[2] - bv[2], (rgba ? "," : str), true);
- if (rgba) {
- bv = (bv.length < 4) ? 1 : bv[3];
- pt.appendXtra("", bv, ((ev.length < 4) ? 1 : ev[3]) - bv, str, false);
- }
- }
-
- } else {
- bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array
-
- //if no number is found, treat it as a non-tweening value and just append the string to the current xs.
- if (!bnums) {
- pt["xs" + pt.l] += pt.l ? " " + bv : bv;
-
- //loop through all the numbers that are found and construct the extra values on the pt.
- } else {
- enums = ev.match(_relNumExp); //get each group of numbers in the end value string and drop them into an array. We allow relative values too, like +=50 or -=.5
- if (!enums || enums.length !== bnums.length) {
- //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
- return pt;
- }
- ni = 0;
- for (xi = 0; xi < bnums.length; xi++) {
- cv = bnums[xi];
- temp = bv.indexOf(cv, ni);
- pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", (autoRound && bv.substr(temp + cv.length, 2) === "px"), (xi === 0));
- ni = temp + cv.length;
- }
- pt["xs" + pt.l] += bv.substr(ni);
- }
- }
- }
- //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly.
- if (e.indexOf("=") !== -1) if (pt.data) {
- str = pt.xs0 + pt.data.s;
- for (i = 1; i < pt.l; i++) {
- str += pt["xs" + i] + pt.data["xn" + i];
- }
- pt.e = str + pt["xs" + i];
- }
- if (!pt.l) {
- pt.type = -1;
- pt.xs0 = pt.e;
- }
- return pt.xfirst || pt;
- },
- i = 9;
-
-
- p = CSSPropTween.prototype;
- p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc.
- while (--i > 0) {
- p["xn" + i] = 0;
- p["xs" + i] = "";
- }
- p.xs0 = "";
- p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null;
-
-
- /**
- * Appends and extra tweening value to a CSSPropTween and automatically manages any prefix and suffix strings. The first extra value is stored in the s and c of the main CSSPropTween instance, but thereafter any extras are stored in the xn1, xn2, xn3, etc. The prefixes and suffixes are stored in the xs0, xs1, xs2, etc. properties. For example, if I walk through a clip value like "rect(10px, 5px, 0px, 20px)", the values would be stored like this:
- * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)"
- * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method).
- * @param {string=} pfx Prefix (if any)
- * @param {!number} s Starting value
- * @param {!number} c Change in numeric value over the course of the entire tween. For example, if the start is 5 and the end is 100, the change would be 95.
- * @param {string=} sfx Suffix (if any)
- * @param {boolean=} r Round (if true).
- * @param {boolean=} pad If true, this extra value should be separated by the previous one by a space. If there is no previous extra and pad is true, it will automatically drop the space.
- * @return {CSSPropTween} returns itself so that multiple methods can be chained together.
- */
- p.appendXtra = function(pfx, s, c, sfx, r, pad) {
- var pt = this,
- l = pt.l;
- pt["xs" + l] += (pad && l) ? " " + pfx : pfx || "";
- if (!c) if (l !== 0 && !pt.plugin) { //typically we'll combine non-changing values right into the xs to optimize performance, but we don't combine them when there's a plugin that will be tweening the values because it may depend on the values being split apart, like for a bezier, if a value doesn't change between the first and second iteration but then it does on the 3rd, we'll run into trouble because there's no xn slot for that value!
- pt["xs" + l] += s + (sfx || "");
- return pt;
- }
- pt.l++;
- pt.type = pt.setRatio ? 2 : 1;
- pt["xs" + pt.l] = sfx || "";
- if (l > 0) {
- pt.data["xn" + l] = s + c;
- pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method)
- pt["xn" + l] = s;
- if (!pt.plugin) {
- pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr);
- pt.xfirst.xs0 = 0; //just to ensure that the property stays numeric which helps modern browsers speed up processing. Remember, in the setRatio() method, we do pt.t[pt.p] = val + pt.xs0 so if pt.xs0 is "" (the default), it'll cast the end value as a string. When a property is a number sometimes and a string sometimes, it prevents the compiler from locking in the data type, slowing things down slightly.
- }
- return pt;
- }
- pt.data = {s:s + c};
- pt.rxp = {};
- pt.s = s;
- pt.c = c;
- pt.r = r;
- return pt;
- };
-
- /**
- * @constructor A SpecialProp is basically a css property that needs to be treated in a non-standard way, like if it may contain a complex value like boxShadow:"5px 10px 15px rgb(255, 102, 51)" or if it is associated with another plugin like ThrowPropsPlugin or BezierPlugin. Every SpecialProp is associated with a particular property name like "boxShadow" or "throwProps" or "bezier" and it will intercept those values in the vars object that's passed to the CSSPlugin and handle them accordingly.
- * @param {!string} p Property name (like "boxShadow" or "throwProps")
- * @param {Object=} options An object containing any of the following configuration options:
- * - defaultValue: the default value
- * - parser: A function that should be called when the associated property name is found in the vars. This function should return a CSSPropTween instance and it should ensure that it is properly inserted into the linked list. It will receive 4 paramters: 1) The target, 2) The value defined in the vars, 3) The CSSPlugin instance (whose _firstPT should be used for the linked list), and 4) A computed style object if one was calculated (this is a speed optimization that allows retrieval of starting values quicker)
- * - formatter: a function that formats any value received for this special property (for example, boxShadow could take "5px 5px red" and format it to "5px 5px 0px 0px red" so that both the beginning and ending values have a common order and quantity of values.)
- * - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O)
- * - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc.
- * - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0.
- * - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out.
- * - collapsible: if true, the formatter should treat the value like it's a top/right/bottom/left value that could be collapsed, like "5px" would apply to all, "5px, 10px" would use 5px for top/bottom and 10px for right/left, etc.
- * - keyword: a special keyword that can [optionally] be found inside the value (like "inset" for boxShadow). This allows us to validate beginning/ending values to make sure they match (if the keyword is found in one, it'll be added to the other for consistency by default).
- */
- var SpecialProp = function(p, options) {
- options = options || {};
- this.p = options.prefix ? _checkPropPrefix(p) || p : p;
- _specialProps[p] = _specialProps[this.p] = this;
- this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi);
- if (options.parser) {
- this.parse = options.parser;
- }
- this.clrs = options.color;
- this.multi = options.multi;
- this.keyword = options.keyword;
- this.dflt = options.defaultValue;
- this.pr = options.priority || 0;
- },
-
- //shortcut for creating a new SpecialProp that can accept multiple properties as a comma-delimited list (helps minification). dflt can be an array for multiple values (we don't do a comma-delimited list because the default value may contain commas, like rect(0px,0px,0px,0px)). We attach this method to the SpecialProp class/object instead of using a private _createSpecialProp() method so that we can tap into it externally if necessary, like from another plugin.
- _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function(p, options, defaults) {
- if (typeof(options) !== "object") {
- options = {parser:defaults}; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin
- }
- var a = p.split(","),
- d = options.defaultValue,
- i, temp;
- defaults = defaults || [d];
- for (i = 0; i < a.length; i++) {
- options.prefix = (i === 0 && options.prefix);
- options.defaultValue = defaults[i] || d;
- temp = new SpecialProp(a[i], options);
- }
- },
-
- //creates a placeholder special prop for a plugin so that the property gets caught the first time a tween of it is attempted, and at that time it makes the plugin register itself, thus taking over for all future tweens of that property. This allows us to not mandate that things load in a particular order and it also allows us to log() an error that informs the user when they attempt to tween an external plugin-related property without loading its .js file.
- _registerPluginProp = function(p) {
- if (!_specialProps[p]) {
- var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin";
- _registerComplexSpecialProp(p, {parser:function(t, e, p, cssp, pt, plugin, vars) {
- var pluginClass = (window.GreenSockGlobals || window).com.greensock.plugins[pluginName];
- if (!pluginClass) {
- _log("Error: " + pluginName + " js file not loaded.");
- return pt;
- }
- pluginClass._cssRegister();
- return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars);
- }});
- }
- };
-
-
- p = SpecialProp.prototype;
-
- /**
- * Alias for _parseComplex() that automatically plugs in certain values for this SpecialProp, like its property name, whether or not colors should be sensed, the default value, and priority. It also looks for any keyword that the SpecialProp defines (like "inset" for boxShadow) and ensures that the beginning and ending values have the same number of values for SpecialProps where multi is true (like boxShadow and textShadow can have a comma-delimited list)
- * @param {!Object} t target element
- * @param {(string|number|object)} b beginning value
- * @param {(string|number|object)} e ending (destination) value
- * @param {CSSPropTween=} pt next CSSPropTween in the linked list
- * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here.
- * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here.
- * @return {CSSPropTween=} First CSSPropTween in the linked list
- */
- p.parseComplex = function(t, b, e, pt, plugin, setRatio) {
- var kwd = this.keyword,
- i, ba, ea, l, bi, ei;
- //if this SpecialProp's value can contain a comma-delimited list of values (like boxShadow or textShadow), we must parse them in a special way, and look for a keyword (like "inset" for boxShadow) and ensure that the beginning and ending BOTH have it if the end defines it as such. We also must ensure that there are an equal number of values specified (we can't tween 1 boxShadow to 3 for example)
- if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) {
- ba = b.replace(_commasOutsideParenExp, "|").split("|");
- ea = e.replace(_commasOutsideParenExp, "|").split("|");
- } else if (kwd) {
- ba = [b];
- ea = [e];
- }
- if (ea) {
- l = (ea.length > ba.length) ? ea.length : ba.length;
- for (i = 0; i < l; i++) {
- b = ba[i] = ba[i] || this.dflt;
- e = ea[i] = ea[i] || this.dflt;
- if (kwd) {
- bi = b.indexOf(kwd);
- ei = e.indexOf(kwd);
- if (bi !== ei) {
- e = (ei === -1) ? ea : ba;
- e[i] += " " + kwd;
- }
- }
- }
- b = ba.join(", ");
- e = ea.join(", ");
- }
- return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio);
- };
-
- /**
- * Accepts a target and end value and spits back a CSSPropTween that has been inserted into the CSSPlugin's linked list and conforms with all the conventions we use internally, like type:-1, 0, 1, or 2, setting up any extra property tweens, priority, etc. For example, if we have a boxShadow SpecialProp and call:
- * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this);
- * It should figure out the starting value of the element's boxShadow, compare it to the provided end value and create all the necessary CSSPropTweens of the appropriate types to tween the boxShadow. The CSSPropTween that gets spit back should already be inserted into the linked list (the 4th parameter is the current head, so prepend to that).
- * @param {!Object} t Target object whose property is being tweened
- * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object).
- * @param {!string} p Property name
- * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween.
- * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it)
- * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance.
- * @param {Object=} vars Original vars object that contains the data for parsing.
- * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call.
- */
- p.parse = function(t, e, p, cssp, pt, plugin, vars) {
- return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin);
- };
-
- /**
- * Registers a special property that should be intercepted from any "css" objects defined in tweens. This allows you to handle them however you want without CSSPlugin doing it for you. The 2nd parameter should be a function that accepts 3 parameters:
- * 1) Target object whose property should be tweened (typically a DOM element)
- * 2) The end/destination value (could be a string, number, object, or whatever you want)
- * 3) The tween instance (you probably don't need to worry about this, but it can be useful for looking up information like the duration)
- *
- * Then, your function should return a function which will be called each time the tween gets rendered, passing a numeric "ratio" parameter to your function that indicates the change factor (usually between 0 and 1). For example:
- *
- * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) {
- * var start = target.style.width;
- * return function(ratio) {
- * target.style.width = (start + value * ratio) + "px";
- * console.log("set width to " + target.style.width);
- * }
- * }, 0);
- *
- * Then, when I do this tween, it will trigger my special property:
- *
- * TweenLite.to(element, 1, {css:{myCustomProp:100}});
- *
- * In the example, of course, we're just changing the width, but you can do anything you want.
- *
- * @param {!string} name Property name (or comma-delimited list of property names) that should be intercepted and handled by your function. For example, if I define "myCustomProp", then it would handle that portion of the following tween: TweenLite.to(element, 1, {css:{myCustomProp:100}})
- * @param {!function(Object, Object, Object, string):function(number)} onInitTween The function that will be called when a tween of this special property is performed. The function will receive 4 parameters: 1) Target object that should be tweened, 2) Value that was passed to the tween, 3) The tween instance itself (rarely used), and 4) The property name that's being tweened. Your function should return a function that should be called on every update of the tween. That function will receive a single parameter that is a "change factor" value (typically between 0 and 1) indicating the amount of change as a ratio. You can use this to determine how to set the values appropriately in your function.
- * @param {number=} priority Priority that helps the engine determine the order in which to set the properties (default: 0). Higher priority properties will be updated before lower priority ones.
- */
- CSSPlugin.registerSpecialProp = function(name, onInitTween, priority) {
- _registerComplexSpecialProp(name, {parser:function(t, e, p, cssp, pt, plugin, vars) {
- var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority);
- rv.plugin = plugin;
- rv.setRatio = onInitTween(t, e, cssp._tween, p);
- return rv;
- }, priority:priority});
- };
-
-
-
-
-
-
-
-
- //transform-related methods and properties
- var _transformProps = ("scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective").split(","),
- _transformProp = _checkPropPrefix("transform"), //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform.
- _transformPropCSS = _prefixCSS + "transform",
- _transformOriginProp = _checkPropPrefix("transformOrigin"),
- _supports3D = (_checkPropPrefix("perspective") !== null),
- Transform = _internals.Transform = function() {
- this.skewY = 0;
- },
-
- /**
- * Parses the transform values for an element, returning an object with x, y, z, scaleX, scaleY, scaleZ, rotation, rotationX, rotationY, skewX, and skewY properties. Note: by default (for performance reasons), all skewing is combined into skewX and rotation but skewY still has a place in the transform object so that we can record how much of the skew is attributed to skewX vs skewY. Remember, a skewY of 10 looks the same as a rotation of 10 and skewX of -10.
- * @param {!Object} t target element
- * @param {Object=} cs computed style object (optional)
- * @param {boolean=} rec if true, the transform values will be recorded to the target element's _gsTransform object, like target._gsTransform = {x:0, y:0, z:0, scaleX:1...}
- * @param {boolean=} parse if true, we'll ignore any _gsTransform values that already exist on the element, and force a reparsing of the css (calculated style)
- * @return {object} object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...}
- */
- _getTransform = _internals.getTransform = function(t, cs, rec, parse) {
- if (t._gsTransform && rec && !parse) {
- return t._gsTransform; //if the element already has a _gsTransform, use that. Note: some browsers don't accurately return the calculated style for the transform (particularly for SVG), so it's almost always safest to just use the values we've already applied rather than re-parsing things.
- }
- var tm = rec ? t._gsTransform || new Transform() : new Transform(),
- invX = (tm.scaleX < 0), //in order to interpret things properly, we need to know if the user applied a negative scaleX previously so that we can adjust the rotation and skewX accordingly. Otherwise, if we always interpret a flipped matrix as affecting scaleY and the user only wants to tween the scaleX on multiple sequential tweens, it would keep the negative scaleY without that being the user's intent.
- min = 0.00002,
- rnd = 100000,
- minAngle = 179.99,
- minPI = minAngle * _DEG2RAD,
- zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin || 0 : 0,
- s, m, i, n, dec, scaleX, scaleY, rotation, skewX, difX, difY, difR, difS;
- if (_transformProp) {
- s = _getStyle(t, _transformPropCSS, cs, true);
- } else if (t.currentStyle) {
- //for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix.
- s = t.currentStyle.filter.match(_ieGetMatrixExp);
- s = (s && s.length === 4) ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), (tm.x || 0), (tm.y || 0)].join(",") : "";
- }
- //split the matrix values out into an array (m for matrix)
- m = (s || "").match(/(?:\-|\b)[\d\-\.e]+\b/gi) || [];
- i = m.length;
- while (--i > -1) {
- n = Number(m[i]);
- m[i] = (dec = n - (n |= 0)) ? ((dec * rnd + (dec < 0 ? -0.5 : 0.5)) | 0) / rnd + n : n; //convert strings to Numbers and round to 5 decimal places to avoid issues with tiny numbers. Roughly 20x faster than Number.toFixed(). We also must make sure to round before dividing so that values like 0.9999999999 become 1 to avoid glitches in browser rendering and interpretation of flipped/rotated 3D matrices. And don't just multiply the number by rnd, floor it, and then divide by rnd because the bitwise operations max out at a 32-bit signed integer, thus it could get clipped at a relatively low value (like 22,000.00000 for example).
- }
- if (m.length === 16) {
-
- //we'll only look at these position-related 6 variables first because if x/y/z all match, it's relatively safe to assume we don't need to re-parse everything which risks losing important rotational information (like rotationX:180 plus rotationY:180 would look the same as rotation:180 - there's no way to know for sure which direction was taken based solely on the matrix3d() values)
- var a13 = m[8], a23 = m[9], a33 = m[10],
- a14 = m[12], a24 = m[13], a34 = m[14];
-
- //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari
- if (tm.zOrigin) {
- a34 = -tm.zOrigin;
- a14 = a13*a34-m[12];
- a24 = a23*a34-m[13];
- a34 = a33*a34+tm.zOrigin-m[14];
- }
-
- //only parse from the matrix if we MUST because not only is it usually unnecessary due to the fact that we store the values in the _gsTransform object, but also because it's impossible to accurately interpret rotationX, rotationY, rotationZ, scaleX, and scaleY if all are applied, so it's much better to rely on what we store. However, we must parse the first time that an object is tweened. We also assume that if the position has changed, the user must have done some styling changes outside of CSSPlugin, thus we force a parse in that scenario.
- if (!rec || parse || tm.rotationX == null) {
- var a11 = m[0], a21 = m[1], a31 = m[2], a41 = m[3],
- a12 = m[4], a22 = m[5], a32 = m[6], a42 = m[7],
- a43 = m[11],
- angle = Math.atan2(a32, a33),
- xFlip = (angle < -minPI || angle > minPI),
- t1, t2, t3, cos, sin, yFlip, zFlip;
- tm.rotationX = angle * _RAD2DEG;
- //rotationX
- if (angle) {
- cos = Math.cos(-angle);
- sin = Math.sin(-angle);
- t1 = a12*cos+a13*sin;
- t2 = a22*cos+a23*sin;
- t3 = a32*cos+a33*sin;
- a13 = a12*-sin+a13*cos;
- a23 = a22*-sin+a23*cos;
- a33 = a32*-sin+a33*cos;
- a43 = a42*-sin+a43*cos;
- a12 = t1;
- a22 = t2;
- a32 = t3;
- }
- //rotationY
- angle = Math.atan2(a13, a11);
- tm.rotationY = angle * _RAD2DEG;
- if (angle) {
- yFlip = (angle < -minPI || angle > minPI);
- cos = Math.cos(-angle);
- sin = Math.sin(-angle);
- t1 = a11*cos-a13*sin;
- t2 = a21*cos-a23*sin;
- t3 = a31*cos-a33*sin;
- a23 = a21*sin+a23*cos;
- a33 = a31*sin+a33*cos;
- a43 = a41*sin+a43*cos;
- a11 = t1;
- a21 = t2;
- a31 = t3;
- }
- //rotationZ
- angle = Math.atan2(a21, a22);
- tm.rotation = angle * _RAD2DEG;
- if (angle) {
- zFlip = (angle < -minPI || angle > minPI);
- cos = Math.cos(-angle);
- sin = Math.sin(-angle);
- a11 = a11*cos+a12*sin;
- t2 = a21*cos+a22*sin;
- a22 = a21*-sin+a22*cos;
- a32 = a31*-sin+a32*cos;
- a21 = t2;
- }
-
- if (zFlip && xFlip) {
- tm.rotation = tm.rotationX = 0;
- } else if (zFlip && yFlip) {
- tm.rotation = tm.rotationY = 0;
- } else if (yFlip && xFlip) {
- tm.rotationY = tm.rotationX = 0;
- }
-
- tm.scaleX = ((Math.sqrt(a11 * a11 + a21 * a21) * rnd + 0.5) | 0) / rnd;
- tm.scaleY = ((Math.sqrt(a22 * a22 + a23 * a23) * rnd + 0.5) | 0) / rnd;
- tm.scaleZ = ((Math.sqrt(a32 * a32 + a33 * a33) * rnd + 0.5) | 0) / rnd;
- tm.skewX = 0;
- tm.perspective = a43 ? 1 / ((a43 < 0) ? -a43 : a43) : 0;
- tm.x = a14;
- tm.y = a24;
- tm.z = a34;
- }
-
- } else if ((!_supports3D || parse || !m.length || tm.x !== m[4] || tm.y !== m[5] || (!tm.rotationX && !tm.rotationY)) && !(tm.x !== undefined && _getStyle(t, "display", cs) === "none")) { //sometimes a 6-element matrix is returned even when we performed 3D transforms, like if rotationX and rotationY are 180. In cases like this, we still need to honor the 3D transforms. If we just rely on the 2D info, it could affect how the data is interpreted, like scaleY might get set to -1 or rotation could get offset by 180 degrees. For example, do a TweenLite.to(element, 1, {css:{rotationX:180, rotationY:180}}) and then later, TweenLite.to(element, 1, {css:{rotationX:0}}) and without this conditional logic in place, it'd jump to a state of being unrotated when the 2nd tween starts. Then again, we need to honor the fact that the user COULD alter the transforms outside of CSSPlugin, like by manually applying new css, so we try to sense that by looking at x and y because if those changed, we know the changes were made outside CSSPlugin and we force a reinterpretation of the matrix values. Also, in Webkit browsers, if the element's "display" is "none", its calculated style value will always return empty, so if we've already recorded the values in the _gsTransform object, we'll just rely on those.
- var k = (m.length >= 6),
- a = k ? m[0] : 1,
- b = m[1] || 0,
- c = m[2] || 0,
- d = k ? m[3] : 1;
- tm.x = m[4] || 0;
- tm.y = m[5] || 0;
- scaleX = Math.sqrt(a * a + b * b);
- scaleY = Math.sqrt(d * d + c * c);
- rotation = (a || b) ? Math.atan2(b, a) * _RAD2DEG : tm.rotation || 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist).
- skewX = (c || d) ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0;
- difX = scaleX - Math.abs(tm.scaleX || 0);
- difY = scaleY - Math.abs(tm.scaleY || 0);
- if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
- if (invX) {
- scaleX *= -1;
- skewX += (rotation <= 0) ? 180 : -180;
- rotation += (rotation <= 0) ? 180 : -180;
- } else {
- scaleY *= -1;
- skewX += (skewX <= 0) ? 180 : -180;
- }
- }
- difR = (rotation - tm.rotation) % 180; //note: matching ranges would be very small (+/-0.0001) or very close to 180.
- difS = (skewX - tm.skewX) % 180;
- //if there's already a recorded _gsTransform in place for the target, we should leave those values in place unless we know things changed for sure (beyond a super small amount). This gets around ambiguous interpretations, like if scaleX and scaleY are both -1, the matrix would be the same as if the rotation was 180 with normal scaleX/scaleY. If the user tweened to particular values, those must be prioritized to ensure animation is consistent.
- if (tm.skewX === undefined || difX > min || difX < -min || difY > min || difY < -min || (difR > -minAngle && difR < minAngle && (difR * rnd) | 0 !== 0) || (difS > -minAngle && difS < minAngle && (difS * rnd) | 0 !== 0)) {
- tm.scaleX = scaleX;
- tm.scaleY = scaleY;
- tm.rotation = rotation;
- tm.skewX = skewX;
- }
- if (_supports3D) {
- tm.rotationX = tm.rotationY = tm.z = 0;
- tm.perspective = parseFloat(CSSPlugin.defaultTransformPerspective) || 0;
- tm.scaleZ = 1;
- }
- }
- tm.zOrigin = zOrigin;
-
- //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 0 in these cases. The conditional logic here is faster than calling Math.abs(). Also, browsers tend to render a SLIGHTLY rotated object in a fuzzy way, so we need to snap to exactly 0 when appropriate.
- for (i in tm) {
- if (tm[i] < min) if (tm[i] > -min) {
- tm[i] = 0;
- }
- }
- //DEBUG: _log("parsed rotation: "+(tm.rotationX)+", "+(tm.rotationY)+", "+(tm.rotation)+", scale: "+tm.scaleX+", "+tm.scaleY+", "+tm.scaleZ+", position: "+tm.x+", "+tm.y+", "+tm.z+", perspective: "+tm.perspective);
- if (rec) {
- t._gsTransform = tm; //record to the object's _gsTransform which we use so that tweens can control individual properties independently (we need all the properties to accurately recompose the matrix in the setRatio() method)
- }
- return tm;
- },
-
- //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms)
- _setIETransformRatio = function(v) {
- var t = this.data, //refers to the element's _gsTransform object
- ang = -t.rotation * _DEG2RAD,
- skew = ang + t.skewX * _DEG2RAD,
- rnd = 100000,
- a = ((Math.cos(ang) * t.scaleX * rnd) | 0) / rnd,
- b = ((Math.sin(ang) * t.scaleX * rnd) | 0) / rnd,
- c = ((Math.sin(skew) * -t.scaleY * rnd) | 0) / rnd,
- d = ((Math.cos(skew) * t.scaleY * rnd) | 0) / rnd,
- style = this.t.style,
- cs = this.t.currentStyle,
- filters, val;
- if (!cs) {
- return;
- }
- val = b; //just for swapping the variables an inverting them (reused "val" to avoid creating another variable in memory). IE's filter matrix uses a non-standard matrix configuration (angle goes the opposite way, and b and c are reversed and inverted)
- b = -c;
- c = -val;
- filters = cs.filter;
- style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight
- var w = this.t.offsetWidth,
- h = this.t.offsetHeight,
- clip = (cs.position !== "absolute"),
- m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d,
- ox = t.x,
- oy = t.y,
- dx, dy;
-
- //if transformOrigin is being used, adjust the offset x and y
- if (t.ox != null) {
- dx = ((t.oxp) ? w * t.ox * 0.01 : t.ox) - w / 2;
- dy = ((t.oyp) ? h * t.oy * 0.01 : t.oy) - h / 2;
- ox += dx - (dx * a + dy * b);
- oy += dy - (dx * c + dy * d);
- }
-
- if (!clip) {
- m += ", sizingMethod='auto expand')";
- } else {
- dx = (w / 2);
- dy = (h / 2);
- //translate to ensure that transformations occur around the correct origin (default is center).
- m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")";
- }
- if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
- style.filter = filters.replace(_ieSetMatrixExp, m);
- } else {
- style.filter = m + " " + filters; //we must always put the transform/matrix FIRST (before alpha(opacity=xx)) to avoid an IE bug that slices part of the object when rotation is applied with alpha.
- }
-
- //at the end or beginning of the tween, if the matrix is normal (1, 0, 0, 1) and opacity is 100 (or doesn't exist), remove the filter to improve browser performance.
- if (v === 0 || v === 1) if (a === 1) if (b === 0) if (c === 0) if (d === 1) if (!clip || m.indexOf("Dx=0, Dy=0") !== -1) if (!_opacityExp.test(filters) || parseFloat(RegExp.$1) === 100) if (filters.indexOf("gradient(" && filters.indexOf("Alpha")) === -1) {
- style.removeAttribute("filter");
- }
-
- //we must set the margins AFTER applying the filter in order to avoid some bugs in IE8 that could (in rare scenarios) cause them to be ignored intermittently (vibration).
- if (!clip) {
- var mult = (_ieVers < 8) ? 1 : -1, //in Internet Explorer 7 and before, the box model is broken, causing the browser to treat the width/height of the actual rotated filtered image as the width/height of the box itself, but Microsoft corrected that in IE8. We must use a negative offset in IE8 on the right/bottom
- marg, prop, dif;
- dx = t.ieOffsetX || 0;
- dy = t.ieOffsetY || 0;
- t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox);
- t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy);
- for (i = 0; i < 4; i++) {
- prop = _margins[i];
- marg = cs[prop];
- //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes)
- val = (marg.indexOf("px") !== -1) ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0;
- if (val !== t[prop]) {
- dif = (i < 2) ? -t.ieOffsetX : -t.ieOffsetY; //if another tween is controlling a margin, we cannot only apply the difference in the ieOffsets, so we essentially zero-out the dx and dy here in that case. We record the margin(s) later so that we can keep comparing them, making this code very flexible.
- } else {
- dif = (i < 2) ? dx - t.ieOffsetX : dy - t.ieOffsetY;
- }
- style[prop] = (t[prop] = Math.round( val - dif * ((i === 0 || i === 2) ? 1 : mult) )) + "px";
- }
- }
- },
-
- _set3DTransformRatio = _internals.set3DTransformRatio = function(v) {
- var t = this.data, //refers to the element's _gsTransform object
- style = this.t.style,
- angle = t.rotation * _DEG2RAD,
- sx = t.scaleX,
- sy = t.scaleY,
- sz = t.scaleZ,
- perspective = t.perspective,
- a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
- zOrigin, rnd, cos, sin, t1, t2, t3, t4;
- if (v === 1 || v === 0) if (t.force3D === "auto") if (!t.rotationY && !t.rotationX && sz === 1 && !perspective && !t.z) { //on the final render (which could be 0 for a from tween), if there are no 3D aspects, render in 2D to free up memory and improve performance especially on mobile devices
- _set2DTransformRatio.call(this, v);
- return;
- }
- if (_isFirefox) {
- var n = 0.0001;
- if (sx < n && sx > -n) { //Firefox has a bug (at least in v25) that causes it to render the transparent part of 32-bit PNG images as black when displayed inside an iframe and the 3D scale is very small and doesn't change sufficiently enough between renders (like if you use a Power4.easeInOut to scale from 0 to 1 where the beginning values only change a tiny amount to begin the tween before accelerating). In this case, we force the scale to be 0.00002 instead which is visually the same but works around the Firefox issue.
- sx = sz = 0.00002;
- }
- if (sy < n && sy > -n) {
- sy = sz = 0.00002;
- }
- if (perspective && !t.z && !t.rotationX && !t.rotationY) { //Firefox has a bug that causes elements to have an odd super-thin, broken/dotted black border on elements that have a perspective set but aren't utilizing 3D space (no rotationX, rotationY, or z).
- perspective = 0;
- }
- }
- if (angle || t.skewX) {
- cos = Math.cos(angle);
- sin = Math.sin(angle);
- a11 = cos;
- a21 = sin;
- if (t.skewX) {
- angle -= t.skewX * _DEG2RAD;
- cos = Math.cos(angle);
- sin = Math.sin(angle);
- if (t.skewType === "simple") { //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does
- t1 = Math.tan(t.skewX * _DEG2RAD);
- t1 = Math.sqrt(1 + t1 * t1);
- cos *= t1;
- sin *= t1;
- }
- }
- a12 = -sin;
- a22 = cos;
-
- } else if (!t.rotationY && !t.rotationX && sz === 1 && !perspective) { //if we're only translating and/or 2D scaling, this is faster...
- style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");
- return;
- } else {
- a11 = a22 = 1;
- a12 = a21 = 0;
- }
- a33 = 1;
- a13 = a14 = a23 = a24 = a31 = a32 = a34 = a41 = a42 = 0;
- a43 = (perspective) ? -1 / perspective : 0;
- zOrigin = t.zOrigin;
- rnd = 100000;
- angle = t.rotationY * _DEG2RAD;
- if (angle) {
- cos = Math.cos(angle);
- sin = Math.sin(angle);
- a31 = a33*-sin;
- a41 = a43*-sin;
- a13 = a11*sin;
- a23 = a21*sin;
- a33 *= cos;
- a43 *= cos;
- a11 *= cos;
- a21 *= cos;
- }
- angle = t.rotationX * _DEG2RAD;
- if (angle) {
- cos = Math.cos(angle);
- sin = Math.sin(angle);
- t1 = a12*cos+a13*sin;
- t2 = a22*cos+a23*sin;
- t3 = a32*cos+a33*sin;
- t4 = a42*cos+a43*sin;
- a13 = a12*-sin+a13*cos;
- a23 = a22*-sin+a23*cos;
- a33 = a32*-sin+a33*cos;
- a43 = a42*-sin+a43*cos;
- a12 = t1;
- a22 = t2;
- a32 = t3;
- a42 = t4;
- }
- if (sz !== 1) {
- a13*=sz;
- a23*=sz;
- a33*=sz;
- a43*=sz;
- }
- if (sy !== 1) {
- a12*=sy;
- a22*=sy;
- a32*=sy;
- a42*=sy;
- }
- if (sx !== 1) {
- a11*=sx;
- a21*=sx;
- a31*=sx;
- a41*=sx;
- }
- if (zOrigin) {
- a34 -= zOrigin;
- a14 = a13*a34;
- a24 = a23*a34;
- a34 = a33*a34+zOrigin;
- }
- //we round the x, y, and z slightly differently to allow even larger values.
- a14 = (t1 = (a14 += t.x) - (a14 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a14 : a14;
- a24 = (t1 = (a24 += t.y) - (a24 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a24 : a24;
- a34 = (t1 = (a34 += t.z) - (a34 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a34 : a34;
- style[_transformProp] = "matrix3d(" + [ (((a11 * rnd) | 0) / rnd), (((a21 * rnd) | 0) / rnd), (((a31 * rnd) | 0) / rnd), (((a41 * rnd) | 0) / rnd), (((a12 * rnd) | 0) / rnd), (((a22 * rnd) | 0) / rnd), (((a32 * rnd) | 0) / rnd), (((a42 * rnd) | 0) / rnd), (((a13 * rnd) | 0) / rnd), (((a23 * rnd) | 0) / rnd), (((a33 * rnd) | 0) / rnd), (((a43 * rnd) | 0) / rnd), a14, a24, a34, (perspective ? (1 + (-a34 / perspective)) : 1) ].join(",") + ")";
- },
-
- _set2DTransformRatio = _internals.set2DTransformRatio = function(v) {
- var t = this.data, //refers to the element's _gsTransform object
- targ = this.t,
- style = targ.style,
- ang, skew, rnd, sx, sy;
- if (t.rotationX || t.rotationY || t.z || t.force3D === true || (t.force3D === "auto" && v !== 1 && v !== 0)) { //if a 3D tween begins while a 2D one is running, we need to kick the rendering over to the 3D method. For example, imagine a yoyo-ing, infinitely repeating scale tween running, and then the object gets rotated in 3D space with a different tween.
- this.setRatio = _set3DTransformRatio;
- _set3DTransformRatio.call(this, v);
- return;
- }
- if (!t.rotation && !t.skewX) {
- style[_transformProp] = "matrix(" + t.scaleX + ",0,0," + t.scaleY + "," + t.x + "," + t.y + ")";
- } else {
- ang = t.rotation * _DEG2RAD;
- skew = ang - t.skewX * _DEG2RAD;
- rnd = 100000;
- sx = t.scaleX * rnd;
- sy = t.scaleY * rnd;
- //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 5 decimal places.
- style[_transformProp] = "matrix(" + (((Math.cos(ang) * sx) | 0) / rnd) + "," + (((Math.sin(ang) * sx) | 0) / rnd) + "," + (((Math.sin(skew) * -sy) | 0) / rnd) + "," + (((Math.cos(skew) * sy) | 0) / rnd) + "," + t.x + "," + t.y + ")";
- }
- };
-
- _registerComplexSpecialProp("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType", {parser:function(t, e, p, cssp, pt, plugin, vars) {
- if (cssp._transform) { return pt; } //only need to parse the transform once, and only if the browser supports it.
- var m1 = cssp._transform = _getTransform(t, _cs, true, vars.parseTransform),
- style = t.style,
- min = 0.000001,
- i = _transformProps.length,
- v = vars,
- endRotations = {},
- m2, skewY, copy, orig, has3D, hasChange, dr;
- if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
- copy = _tempDiv.style; //don't use the original target because it might be SVG in which case some browsers don't report computed style correctly.
- copy[_transformProp] = v.transform;
- copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
- copy.position = "absolute";
- _doc.body.appendChild(_tempDiv);
- m2 = _getTransform(_tempDiv, null, false);
- _doc.body.removeChild(_tempDiv);
- } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
- m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
- scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
- scaleZ:_parseVal(v.scaleZ, m1.scaleZ),
- x:_parseVal(v.x, m1.x),
- y:_parseVal(v.y, m1.y),
- z:_parseVal(v.z, m1.z),
- perspective:_parseVal(v.transformPerspective, m1.perspective)};
- dr = v.directionalRotation;
- if (dr != null) {
- if (typeof(dr) === "object") {
- for (copy in dr) {
- v[copy] = dr[copy];
- }
- } else {
- v.rotation = dr;
- }
- }
- m2.rotation = _parseAngle(("rotation" in v) ? v.rotation : ("shortRotation" in v) ? v.shortRotation + "_short" : ("rotationZ" in v) ? v.rotationZ : m1.rotation, m1.rotation, "rotation", endRotations);
- if (_supports3D) {
- m2.rotationX = _parseAngle(("rotationX" in v) ? v.rotationX : ("shortRotationX" in v) ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations);
- m2.rotationY = _parseAngle(("rotationY" in v) ? v.rotationY : ("shortRotationY" in v) ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations);
- }
- m2.skewX = (v.skewX == null) ? m1.skewX : _parseAngle(v.skewX, m1.skewX);
-
- //note: for performance reasons, we combine all skewing into the skewX and rotation values, ignoring skewY but we must still record it so that we can discern how much of the overall skew is attributed to skewX vs. skewY. Otherwise, if the skewY would always act relative (tween skewY to 10deg, for example, multiple times and if we always combine things into skewX, we can't remember that skewY was 10 from last time). Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of -10 degrees.
- m2.skewY = (v.skewY == null) ? m1.skewY : _parseAngle(v.skewY, m1.skewY);
- if ((skewY = m2.skewY - m1.skewY)) {
- m2.skewX += skewY;
- m2.rotation += skewY;
- }
- }
-
- if (_supports3D && v.force3D != null) {
- m1.force3D = v.force3D;
- hasChange = true;
- }
-
- m1.skewType = v.skewType || m1.skewType || CSSPlugin.defaultSkewType;
-
- has3D = (m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective);
- if (!has3D && v.scale != null) {
- m2.scaleZ = 1; //no need to tween scaleZ.
- }
-
- while (--i > -1) {
- p = _transformProps[i];
- orig = m2[p] - m1[p];
- if (orig > min || orig < -min || _forcePT[p] != null) {
- hasChange = true;
- pt = new CSSPropTween(m1, p, m1[p], orig, pt);
- if (p in endRotations) {
- pt.e = endRotations[p]; //directional rotations typically have compensated values during the tween, but we need to make sure they end at exactly what the user requested
- }
- pt.xs0 = 0; //ensures the value stays numeric in setRatio()
- pt.plugin = plugin;
- cssp._overwriteProps.push(pt.n);
- }
- }
-
- orig = v.transformOrigin;
- if (orig || (_supports3D && has3D && m1.zOrigin)) { //if anything 3D is happening and there's a transformOrigin with a z component that's non-zero, we must ensure that the transformOrigin's z-component is set to 0 so that we can manually do those calculations to get around Safari bugs. Even if the user didn't specifically define a "transformOrigin" in this particular tween (maybe they did it via css directly).
- if (_transformProp) {
- hasChange = true;
- p = _transformOriginProp;
- orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors
- pt = new CSSPropTween(style, p, 0, 0, pt, -1, "transformOrigin");
- pt.b = style[p];
- pt.plugin = plugin;
- if (_supports3D) {
- copy = m1.zOrigin;
- orig = orig.split(" ");
- m1.zOrigin = ((orig.length > 2 && !(copy !== 0 && orig[2] === "0px")) ? parseFloat(orig[2]) : copy) || 0; //Safari doesn't handle the z part of transformOrigin correctly, so we'll manually handle it in the _set3DTransformRatio() method.
- pt.xs0 = pt.e = orig[0] + " " + (orig[1] || "50%") + " 0px"; //we must define a z value of 0px specifically otherwise iOS 5 Safari will stick with the old one (if one was defined)!
- pt = new CSSPropTween(m1, "zOrigin", 0, 0, pt, -1, pt.n); //we must create a CSSPropTween for the _gsTransform.zOrigin so that it gets reset properly at the beginning if the tween runs backward (as opposed to just setting m1.zOrigin here)
- pt.b = copy;
- pt.xs0 = pt.e = m1.zOrigin;
- } else {
- pt.xs0 = pt.e = orig;
- }
-
- //for older versions of IE (6-8), we need to manually calculate things inside the setRatio() function. We record origin x and y (ox and oy) and whether or not the values are percentages (oxp and oyp).
- } else {
- _parsePosition(orig + "", m1);
- }
- }
-
- if (hasChange) {
- cssp._transformType = (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms();
- }
- return pt;
- }, prefix:true});
-
- _registerComplexSpecialProp("boxShadow", {defaultValue:"0px 0px 0px 0px #999", prefix:true, color:true, multi:true, keyword:"inset"});
-
- _registerComplexSpecialProp("borderRadius", {defaultValue:"0px", parser:function(t, e, p, cssp, pt, plugin) {
- e = this.format(e);
- var props = ["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],
- style = t.style,
- ea1, i, es2, bs2, bs, es, bn, en, w, h, esfx, bsfx, rel, hn, vn, em;
- w = parseFloat(t.offsetWidth);
- h = parseFloat(t.offsetHeight);
- ea1 = e.split(" ");
- for (i = 0; i < props.length; i++) { //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis!
- if (this.p.indexOf("border")) { //older browsers used a prefix
- props[i] = _checkPropPrefix(props[i]);
- }
- bs = bs2 = _getStyle(t, props[i], _cs, false, "0px");
- if (bs.indexOf(" ") !== -1) {
- bs2 = bs.split(" ");
- bs = bs2[0];
- bs2 = bs2[1];
- }
- es = es2 = ea1[i];
- bn = parseFloat(bs);
- bsfx = bs.substr((bn + "").length);
- rel = (es.charAt(1) === "=");
- if (rel) {
- en = parseInt(es.charAt(0)+"1", 10);
- es = es.substr(2);
- en *= parseFloat(es);
- esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || "";
- } else {
- en = parseFloat(es);
- esfx = es.substr((en + "").length);
- }
- if (esfx === "") {
- esfx = _suffixMap[p] || bsfx;
- }
- if (esfx !== bsfx) {
- hn = _convertToPixels(t, "borderLeft", bn, bsfx); //horizontal number (we use a bogus "borderLeft" property just because the _convertToPixels() method searches for the keywords "Left", "Right", "Top", and "Bottom" to determine of it's a horizontal or vertical property, and we need "border" in the name so that it knows it should measure relative to the element itself, not its parent.
- vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number
- if (esfx === "%") {
- bs = (hn / w * 100) + "%";
- bs2 = (vn / h * 100) + "%";
- } else if (esfx === "em") {
- em = _convertToPixels(t, "borderLeft", 1, "em");
- bs = (hn / em) + "em";
- bs2 = (vn / em) + "em";
- } else {
- bs = hn + "px";
- bs2 = vn + "px";
- }
- if (rel) {
- es = (parseFloat(bs) + en) + esfx;
- es2 = (parseFloat(bs2) + en) + esfx;
- }
- }
- pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt);
- }
- return pt;
- }, prefix:true, formatter:_getFormatter("0px 0px 0px 0px", false, true)});
- _registerComplexSpecialProp("backgroundPosition", {defaultValue:"0 0", parser:function(t, e, p, cssp, pt, plugin) {
- var bp = "background-position",
- cs = (_cs || _getComputedStyle(t, null)),
- bs = this.format( ((cs) ? _ieVers ? cs.getPropertyValue(bp + "-x") + " " + cs.getPropertyValue(bp + "-y") : cs.getPropertyValue(bp) : t.currentStyle.backgroundPositionX + " " + t.currentStyle.backgroundPositionY) || "0 0"), //Internet Explorer doesn't report background-position correctly - we must query background-position-x and background-position-y and combine them (even in IE10). Before IE9, we must do the same with the currentStyle object and use camelCase
- es = this.format(e),
- ba, ea, i, pct, overlap, src;
- if ((bs.indexOf("%") !== -1) !== (es.indexOf("%") !== -1)) {
- src = _getStyle(t, "backgroundImage").replace(_urlExp, "");
- if (src && src !== "none") {
- ba = bs.split(" ");
- ea = es.split(" ");
- _tempImg.setAttribute("src", src); //set the temp <img>'s src to the background-image so that we can measure its width/height
- i = 2;
- while (--i > -1) {
- bs = ba[i];
- pct = (bs.indexOf("%") !== -1);
- if (pct !== (ea[i].indexOf("%") !== -1)) {
- overlap = (i === 0) ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height;
- ba[i] = pct ? (parseFloat(bs) / 100 * overlap) + "px" : (parseFloat(bs) / overlap * 100) + "%";
- }
- }
- bs = ba.join(" ");
- }
- }
- return this.parseComplex(t.style, bs, es, pt, plugin);
- }, formatter:_parsePosition});
- _registerComplexSpecialProp("backgroundSize", {defaultValue:"0 0", formatter:_parsePosition});
- _registerComplexSpecialProp("perspective", {defaultValue:"0px", prefix:true});
- _registerComplexSpecialProp("perspectiveOrigin", {defaultValue:"50% 50%", prefix:true});
- _registerComplexSpecialProp("transformStyle", {prefix:true});
- _registerComplexSpecialProp("backfaceVisibility", {prefix:true});
- _registerComplexSpecialProp("userSelect", {prefix:true});
- _registerComplexSpecialProp("margin", {parser:_getEdgeParser("marginTop,marginRight,marginBottom,marginLeft")});
- _registerComplexSpecialProp("padding", {parser:_getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft")});
- _registerComplexSpecialProp("clip", {defaultValue:"rect(0px,0px,0px,0px)", parser:function(t, e, p, cssp, pt, plugin){
- var b, cs, delim;
- if (_ieVers < 9) { //IE8 and earlier don't report a "clip" value in the currentStyle - instead, the values are split apart into clipTop, clipRight, clipBottom, and clipLeft. Also, in IE7 and earlier, the values inside rect() are space-delimited, not comma-delimited.
- cs = t.currentStyle;
- delim = _ieVers < 8 ? " " : ",";
- b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")";
- e = this.format(e).split(",").join(delim);
- } else {
- b = this.format(_getStyle(t, this.p, _cs, false, this.dflt));
- e = this.format(e);
- }
- return this.parseComplex(t.style, b, e, pt, plugin);
- }});
- _registerComplexSpecialProp("textShadow", {defaultValue:"0px 0px 0px #999", color:true, multi:true});
- _registerComplexSpecialProp("autoRound,strictUnits", {parser:function(t, e, p, cssp, pt) {return pt;}}); //just so that we can ignore these properties (not tween them)
- _registerComplexSpecialProp("border", {defaultValue:"0px solid #000", parser:function(t, e, p, cssp, pt, plugin) {
- return this.parseComplex(t.style, this.format(_getStyle(t, "borderTopWidth", _cs, false, "0px") + " " + _getStyle(t, "borderTopStyle", _cs, false, "solid") + " " + _getStyle(t, "borderTopColor", _cs, false, "#000")), this.format(e), pt, plugin);
- }, color:true, formatter:function(v) {
- var a = v.split(" ");
- return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0];
- }});
- _registerComplexSpecialProp("borderWidth", {parser:_getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}); //Firefox doesn't pick up on borderWidth set in style sheets (only inline).
- _registerComplexSpecialProp("float,cssFloat,styleFloat", {parser:function(t, e, p, cssp, pt, plugin) {
- var s = t.style,
- prop = ("cssFloat" in s) ? "cssFloat" : "styleFloat";
- return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e);
- }});
-
- //opacity-related
- var _setIEOpacityRatio = function(v) {
- var t = this.t, //refers to the element's style property
- filters = t.filter || _getStyle(this.data, "filter"),
- val = (this.s + this.c * v) | 0,
- skip;
- if (val === 100) { //for older versions of IE that need to use a filter to apply opacity, we should remove the filter if opacity hits 1 in order to improve performance, but make sure there isn't a transform (matrix) or gradient in the filters.
- if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) {
- t.removeAttribute("filter");
- skip = (!_getStyle(this.data, "filter")); //if a class is applied that has an alpha filter, it will take effect (we don't want that), so re-apply our alpha filter in that case. We must first remove it and then check.
- } else {
- t.filter = filters.replace(_alphaFilterExp, "");
- skip = true;
- }
- }
- if (!skip) {
- if (this.xn1) {
- t.filter = filters = filters || ("alpha(opacity=" + val + ")"); //works around bug in IE7/8 that prevents changes to "visibility" from being applied properly if the filter is changed to a different alpha on the same frame.
- }
- if (filters.indexOf("pacity") === -1) { //only used if browser doesn't support the standard opacity style property (IE 7 and 8). We omit the "O" to avoid case-sensitivity issues
- if (val !== 0 || !this.xn1) { //bugs in IE7/8 won't render the filter properly if opacity is ADDED on the same frame/render as "visibility" changes (this.xn1 is 1 if this tween is an "autoAlpha" tween)
- t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
- }
- } else {
- t.filter = filters.replace(_opacityExp, "opacity=" + val);
- }
- }
- };
- _registerComplexSpecialProp("opacity,alpha,autoAlpha", {defaultValue:"1", parser:function(t, e, p, cssp, pt, plugin) {
- var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")),
- style = t.style,
- isAutoAlpha = (p === "autoAlpha");
- if (typeof(e) === "string" && e.charAt(1) === "=") {
- e = ((e.charAt(0) === "-") ? -1 : 1) * parseFloat(e.substr(2)) + b;
- }
- if (isAutoAlpha && b === 1 && _getStyle(t, "visibility", _cs) === "hidden" && e !== 0) { //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience)
- b = 0;
- }
- if (_supportsOpacity) {
- pt = new CSSPropTween(style, "opacity", b, e - b, pt);
- } else {
- pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt);
- pt.xn1 = isAutoAlpha ? 1 : 0; //we need to record whether or not this is an autoAlpha so that in the setRatio(), we know to duplicate the setting of the alpha in order to work around a bug in IE7 and IE8 that prevents changes to "visibility" from taking effect if the filter is changed to a different alpha(opacity) at the same time. Setting it to the SAME value first, then the new value works around the IE7/8 bug.
- style.zoom = 1; //helps correct an IE issue.
- pt.type = 2;
- pt.b = "alpha(opacity=" + pt.s + ")";
- pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")";
- pt.data = t;
- pt.plugin = plugin;
- pt.setRatio = _setIEOpacityRatio;
- }
- if (isAutoAlpha) { //we have to create the "visibility" PropTween after the opacity one in the linked list so that they run in the order that works properly in IE8 and earlier
- pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, ((b !== 0) ? "inherit" : "hidden"), ((e === 0) ? "hidden" : "inherit"));
- pt.xs0 = "inherit";
- cssp._overwriteProps.push(pt.n);
- cssp._overwriteProps.push(p);
- }
- return pt;
- }});
-
-
- var _removeProp = function(s, p) {
- if (p) {
- if (s.removeProperty) {
- if (p.substr(0,2) === "ms") { //Microsoft browsers don't conform to the standard of capping the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example)
- p = "M" + p.substr(1);
- }
- s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
- } else { //note: old versions of IE use "removeAttribute()" instead of "removeProperty()"
- s.removeAttribute(p);
- }
- }
- },
- _setClassNameRatio = function(v) {
- this.t._gsClassPT = this;
- if (v === 1 || v === 0) {
- this.t.setAttribute("class", (v === 0) ? this.b : this.e);
- var mpt = this.data, //first MiniPropTween
- s = this.t.style;
- while (mpt) {
- if (!mpt.v) {
- _removeProp(s, mpt.p);
- } else {
- s[mpt.p] = mpt.v;
- }
- mpt = mpt._next;
- }
- if (v === 1 && this.t._gsClassPT === this) {
- this.t._gsClassPT = null;
- }
- } else if (this.t.getAttribute("class") !== this.e) {
- this.t.setAttribute("class", this.e);
- }
- };
- _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
- var b = t.getAttribute("class") || "", //don't use t.className because it doesn't work consistently on SVG elements; getAttribute("class") and setAttribute("class", value") is more reliable.
- cssText = t.style.cssText,
- difData, bs, cnpt, cnptLookup, mpt;
- pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
- pt.setRatio = _setClassNameRatio;
- pt.pr = -11;
- _hasPriority = true;
- pt.b = b;
- bs = _getAllStyles(t, _cs);
- //if there's a className tween already operating on the target, force it to its end so that the necessary inline styles are removed and the class name is applied before we determine the end state (we don't want inline styles interfering that were there just for class-specific values)
- cnpt = t._gsClassPT;
- if (cnpt) {
- cnptLookup = {};
- mpt = cnpt.data; //first MiniPropTween which stores the inline styles - we need to force these so that the inline styles don't contaminate things. Otherwise, there's a small chance that a tween could start and the inline values match the destination values and they never get cleaned.
- while (mpt) {
- cnptLookup[mpt.p] = 1;
- mpt = mpt._next;
- }
- cnpt.setRatio(1);
- }
- t._gsClassPT = pt;
- pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
- if (cssp._tween._duration) { //if it's a zero-duration tween, there's no need to tween anything or parse the data. In fact, if we switch classes temporarily (which we must do for proper parsing) and the class has a transition applied, it could cause a quick flash to the end state and back again initially in some browsers.
- t.setAttribute("class", pt.e);
- difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
- t.setAttribute("class", b);
- pt.data = difData.firstMPT;
- t.style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity).
- pt = pt.xfirst = cssp.parse(t, difData.difs, pt, plugin); //we record the CSSPropTween as the xfirst so that we can handle overwriting propertly (if "className" gets overwritten, we must kill all the properties associated with the className part of the tween, so we can loop through from xfirst to the pt itself)
- }
- return pt;
- }});
-
-
- var _setClearPropsRatio = function(v) {
- if (v === 1 || v === 0) if (this.data._totalTime === this.data._totalDuration && this.data.data !== "isFromStart") { //this.data refers to the tween. Only clear at the END of the tween (remember, from() tweens make the ratio go from 1 to 0, so we can't just check that and if the tween is the zero-duration one that's created internally to render the starting values in a from() tween, ignore that because otherwise, for example, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in).
- var s = this.t.style,
- transformParse = _specialProps.transform.parse,
- a, p, i, clearTransform;
- if (this.e === "all") {
- s.cssText = "";
- clearTransform = true;
- } else {
- a = this.e.split(",");
- i = a.length;
- while (--i > -1) {
- p = a[i];
- if (_specialProps[p]) {
- if (_specialProps[p].parse === transformParse) {
- clearTransform = true;
- } else {
- p = (p === "transformOrigin") ? _transformOriginProp : _specialProps[p].p; //ensures that special properties use the proper browser-specific property name, like "scaleX" might be "-webkit-transform" or "boxShadow" might be "-moz-box-shadow"
- }
- }
- _removeProp(s, p);
- }
- }
- if (clearTransform) {
- _removeProp(s, _transformProp);
- if (this.t._gsTransform) {
- delete this.t._gsTransform;
- }
- }
-
- }
- };
- _registerComplexSpecialProp("clearProps", {parser:function(t, e, p, cssp, pt) {
- pt = new CSSPropTween(t, p, 0, 0, pt, 2);
- pt.setRatio = _setClearPropsRatio;
- pt.e = e;
- pt.pr = -10;
- pt.data = cssp._tween;
- _hasPriority = true;
- return pt;
- }});
-
- p = "bezier,throwProps,physicsProps,physics2D".split(",");
- i = p.length;
- while (i--) {
- _registerPluginProp(p[i]);
- }
-
-
-
-
-
-
-
-
- p = CSSPlugin.prototype;
- p._firstPT = null;
-
- //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc.
- p._onInitTween = function(target, vars, tween) {
- if (!target.nodeType) { //css is only for dom elements
- return false;
- }
- this._target = target;
- this._tween = tween;
- this._vars = vars;
- _autoRound = vars.autoRound;
- _hasPriority = false;
- _suffixMap = vars.suffixMap || CSSPlugin.suffixMap;
- _cs = _getComputedStyle(target, "");
- _overwriteProps = this._overwriteProps;
- var style = target.style,
- v, pt, pt2, first, last, next, zIndex, tpt, threeD;
- if (_reqSafariFix) if (style.zIndex === "") {
- v = _getStyle(target, "zIndex", _cs);
- if (v === "auto" || v === "") {
- //corrects a bug in [non-Android] Safari that prevents it from repainting elements in their new positions if they don't have a zIndex set. We also can't just apply this inside _parseTransform() because anything that's moved in any way (like using "left" or "top" instead of transforms like "x" and "y") can be affected, so it is best to ensure that anything that's tweening has a z-index. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. Plus zIndex is less memory-intensive.
- this._addLazySet(style, "zIndex", 0);
- }
- }
-
- if (typeof(vars) === "string") {
- first = style.cssText;
- v = _getAllStyles(target, _cs);
- style.cssText = first + ";" + vars;
- v = _cssDif(target, v, _getAllStyles(target)).difs;
- if (!_supportsOpacity && _opacityValExp.test(vars)) {
- v.opacity = parseFloat( RegExp.$1 );
- }
- vars = v;
- style.cssText = first;
- }
- this._firstPT = pt = this.parse(target, vars, null);
-
- if (this._transformType) {
- threeD = (this._transformType === 3);
- if (!_transformProp) {
- style.zoom = 1; //helps correct an IE issue.
- } else if (_isSafari) {
- _reqSafariFix = true;
- //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random).
- if (style.zIndex === "") {
- zIndex = _getStyle(target, "zIndex", _cs);
- if (zIndex === "auto" || zIndex === "") {
- this._addLazySet(style, "zIndex", 0);
- }
- }
- //Setting WebkitBackfaceVisibility corrects 3 bugs:
- // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update.
- // 2) iOS Safari sometimes neglects to repaint elements in their new positions. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly.
- // 3) Safari sometimes displayed odd artifacts when tweening the transform (or WebkitTransform) property, like ghosts of the edges of the element remained. Definitely a browser bug.
- //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
- if (_isSafariLT6) {
- this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
- }
- }
- pt2 = pt;
- while (pt2 && pt2._next) {
- pt2 = pt2._next;
- }
- tpt = new CSSPropTween(target, "transform", 0, 0, null, 2);
- this._linkCSSP(tpt, null, pt2);
- tpt.setRatio = (threeD && _supports3D) ? _set3DTransformRatio : _transformProp ? _set2DTransformRatio : _setIETransformRatio;
- tpt.data = this._transform || _getTransform(target, _cs, true);
- _overwriteProps.pop(); //we don't want to force the overwrite of all "transform" tweens of the target - we only care about individual transform properties like scaleX, rotation, etc. The CSSPropTween constructor automatically adds the property to _overwriteProps which is why we need to pop() here.
- }
-
- if (_hasPriority) {
- //reorders the linked list in order of pr (priority)
- while (pt) {
- next = pt._next;
- pt2 = first;
- while (pt2 && pt2.pr > pt.pr) {
- pt2 = pt2._next;
- }
- if ((pt._prev = pt2 ? pt2._prev : last)) {
- pt._prev._next = pt;
- } else {
- first = pt;
- }
- if ((pt._next = pt2)) {
- pt2._prev = pt;
- } else {
- last = pt;
- }
- pt = next;
- }
- this._firstPT = first;
- }
- return true;
- };
-
-
- p.parse = function(target, vars, pt, plugin) {
- var style = target.style,
- p, sp, bn, en, bs, es, bsfx, esfx, isStr, rel;
- for (p in vars) {
- es = vars[p]; //ending value string
- sp = _specialProps[p]; //SpecialProp lookup.
- if (sp) {
- pt = sp.parse(target, es, p, this, pt, plugin, vars);
-
- } else {
- bs = _getStyle(target, p, _cs) + "";
- isStr = (typeof(es) === "string");
- if (p === "color" || p === "fill" || p === "stroke" || p.indexOf("Color") !== -1 || (isStr && _rgbhslExp.test(es))) { //Opera uses background: to define color sometimes in addition to backgroundColor:
- if (!isStr) {
- es = _parseColor(es);
- es = ((es.length > 3) ? "rgba(" : "rgb(") + es.join(",") + ")";
- }
- pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin);
-
- } else if (isStr && (es.indexOf(" ") !== -1 || es.indexOf(",") !== -1)) {
- pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin);
-
- } else {
- bn = parseFloat(bs);
- bsfx = (bn || bn === 0) ? bs.substr((bn + "").length) : ""; //remember, bs could be non-numeric like "normal" for fontWeight, so we should default to a blank suffix in that case.
-
- if (bs === "" || bs === "auto") {
- if (p === "width" || p === "height") {
- bn = _getDimension(target, p, _cs);
- bsfx = "px";
- } else if (p === "left" || p === "top") {
- bn = _calculateOffset(target, p, _cs);
- bsfx = "px";
- } else {
- bn = (p !== "opacity") ? 0 : 1;
- bsfx = "";
- }
- }
-
- rel = (isStr && es.charAt(1) === "=");
- if (rel) {
- en = parseInt(es.charAt(0) + "1", 10);
- es = es.substr(2);
- en *= parseFloat(es);
- esfx = es.replace(_suffixExp, "");
- } else {
- en = parseFloat(es);
- esfx = isStr ? es.substr((en + "").length) || "" : "";
- }
-
- if (esfx === "") {
- esfx = (p in _suffixMap) ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix.
- }
-
- es = (en || en === 0) ? (rel ? en + bn : en) + esfx : vars[p]; //ensures that any += or -= prefixes are taken care of. Record the end value before normalizing the suffix because we always want to end the tween on exactly what they intended even if it doesn't match the beginning value's suffix.
-
- //if the beginning/ending suffixes don't match, normalize them...
- if (bsfx !== esfx) if (esfx !== "") if (en || en === 0) if (bn) { //note: if the beginning value (bn) is 0, we don't need to convert units!
- bn = _convertToPixels(target, p, bn, bsfx);
- if (esfx === "%") {
- bn /= _convertToPixels(target, p, 100, "%") / 100;
- if (vars.strictUnits !== true) { //some browsers report only "px" values instead of allowing "%" with getComputedStyle(), so we assume that if we're tweening to a %, we should start there too unless strictUnits:true is defined. This approach is particularly useful for responsive designs that use from() tweens.
- bs = bn + "%";
- }
-
- } else if (esfx === "em") {
- bn /= _convertToPixels(target, p, 1, "em");
-
- //otherwise convert to pixels.
- } else if (esfx !== "px") {
- en = _convertToPixels(target, p, en, esfx);
- esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too.
- }
- if (rel) if (en || en === 0) {
- es = (en + bn) + esfx; //the changes we made affect relative calculations, so adjust the end value here.
- }
- }
-
- if (rel) {
- en += bn;
- }
-
- if ((bn || bn === 0) && (en || en === 0)) { //faster than isNaN(). Also, previously we required en !== bn but that doesn't really gain much performance and it prevents _parseToProxy() from working properly if beginning and ending values match but need to get tweened by an external plugin anyway. For example, a bezier tween where the target starts at left:0 and has these points: [{left:50},{left:0}] wouldn't work properly because when parsing the last point, it'd match the first (current) one and a non-tweening CSSPropTween would be recorded when we actually need a normal tween (type:0) so that things get updated during the tween properly.
- pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, (_autoRound !== false && (esfx === "px" || p === "zIndex")), 0, bs, es);
- pt.xs0 = esfx;
- //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0);
- } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) {
- _log("invalid " + p + " tween value: " + vars[p]);
- } else {
- pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es);
- pt.xs0 = (es === "none" && (p === "display" || p.indexOf("Style") !== -1)) ? bs : es; //intermediate value should typically be set immediately (end value) except for "display" or things like borderTopStyle, borderBottomStyle, etc. which should use the beginning value during the tween.
- //DEBUG: _log("non-tweening value "+p+": "+pt.xs0);
- }
- }
- }
- if (plugin) if (pt && !pt.plugin) {
- pt.plugin = plugin;
- }
- }
- return pt;
- };
-
-
- //gets called every time the tween updates, passing the new ratio (typically a value between 0 and 1, but not always (for example, if an Elastic.easeOut is used, the value can jump above 1 mid-tween). It will always start and 0 and end at 1.
- p.setRatio = function(v) {
- var pt = this._firstPT,
- min = 0.000001,
- val, str, i;
-
- //at the end of the tween, we set the values to exactly what we received in order to make sure non-tweening values (like "position" or "float" or whatever) are set and so that if the beginning/ending suffixes (units) didn't match and we normalized to px, the value that the user passed in is used here. We check to see if the tween is at its beginning in case it's a from() tween in which case the ratio will actually go from 1 to 0 over the course of the tween (backwards).
- if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) {
- while (pt) {
- if (pt.type !== 2) {
- pt.t[pt.p] = pt.e;
- } else {
- pt.setRatio(v);
- }
- pt = pt._next;
- }
-
- } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) {
- while (pt) {
- val = pt.c * v + pt.s;
- if (pt.r) {
- val = Math.round(val);
- } else if (val < min) if (val > -min) {
- val = 0;
- }
- if (!pt.type) {
- pt.t[pt.p] = val + pt.xs0;
- } else if (pt.type === 1) { //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)"
- i = pt.l;
- if (i === 2) {
- pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2;
- } else if (i === 3) {
- pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3;
- } else if (i === 4) {
- pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4;
- } else if (i === 5) {
- pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4 + pt.xn4 + pt.xs5;
- } else {
- str = pt.xs0 + val + pt.xs1;
- for (i = 1; i < pt.l; i++) {
- str += pt["xn"+i] + pt["xs"+(i+1)];
- }
- pt.t[pt.p] = str;
- }
-
- } else if (pt.type === -1) { //non-tweening value
- pt.t[pt.p] = pt.xs0;
-
- } else if (pt.setRatio) { //custom setRatio() for things like SpecialProps, external plugins, etc.
- pt.setRatio(v);
- }
- pt = pt._next;
- }
-
- //if the tween is reversed all the way back to the beginning, we need to restore the original values which may have different units (like % instead of px or em or whatever).
- } else {
- while (pt) {
- if (pt.type !== 2) {
- pt.t[pt.p] = pt.b;
- } else {
- pt.setRatio(v);
- }
- pt = pt._next;
- }
- }
- };
-
- /**
- * @private
- * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called.
- * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked
- * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call
- * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin
- * doesn't have any transform-related properties of its own. You can call this method as many times as you
- * want and it won't create duplicate CSSPropTweens.
- *
- * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster)
- */
- p._enableTransforms = function(threeD) {
- this._transformType = (threeD || this._transformType === 3) ? 3 : 2;
- this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
- };
-
- var lazySet = function(v) {
- this.t[this.p] = this.e;
- this.data._linkCSSP(this, this._next, null, true); //we purposefully keep this._next even though it'd make sense to null it, but this is a performance optimization, as this happens during the while (pt) {} loop in setRatio() at the bottom of which it sets pt = pt._next, so if we null it, the linked list will be broken in that loop.
- };
- /** @private Gives us a way to set a value on the first render (and only the first render). **/
- p._addLazySet = function(t, p, v) {
- var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
- pt.e = v;
- pt.setRatio = lazySet;
- pt.data = this;
- };
-
- /** @private **/
- p._linkCSSP = function(pt, next, prev, remove) {
- if (pt) {
- if (next) {
- next._prev = pt;
- }
- if (pt._next) {
- pt._next._prev = pt._prev;
- }
- if (pt._prev) {
- pt._prev._next = pt._next;
- } else if (this._firstPT === pt) {
- this._firstPT = pt._next;
- remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed)
- }
- if (prev) {
- prev._next = pt;
- } else if (!remove && this._firstPT === null) {
- this._firstPT = pt;
- }
- pt._next = next;
- pt._prev = prev;
- }
- return pt;
- };
-
- //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property.
- p._kill = function(lookup) {
- var copy = lookup,
- pt, p, xfirst;
- if (lookup.autoAlpha || lookup.alpha) {
- copy = {};
- for (p in lookup) { //copy the lookup so that we're not changing the original which may be passed elsewhere.
- copy[p] = lookup[p];
- }
- copy.opacity = 1;
- if (copy.autoAlpha) {
- copy.visibility = 1;
- }
- }
- if (lookup.className && (pt = this._classNamePT)) { //for className tweens, we need to kill any associated CSSPropTweens too; a linked list starts at the className's "xfirst".
- xfirst = pt.xfirst;
- if (xfirst && xfirst._prev) {
- this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev
- } else if (xfirst === this._firstPT) {
- this._firstPT = pt._next;
- }
- if (pt._next) {
- this._linkCSSP(pt._next, pt._next._next, xfirst._prev);
- }
- this._classNamePT = null;
- }
- return TweenPlugin.prototype._kill.call(this, copy);
- };
-
-
-
- //used by cascadeTo() for gathering all the style properties of each child element into an array for comparison.
- var _getChildStyles = function(e, props, targets) {
- var children, i, child, type;
- if (e.slice) {
- i = e.length;
- while (--i > -1) {
- _getChildStyles(e[i], props, targets);
- }
- return;
- }
- children = e.childNodes;
- i = children.length;
- while (--i > -1) {
- child = children[i];
- type = child.type;
- if (child.style) {
- props.push(_getAllStyles(child));
- if (targets) {
- targets.push(child);
- }
- }
- if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) {
- _getChildStyles(child, props, targets);
- }
- }
- };
-
- /**
- * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite
- * and then compares the style properties of all the target's child elements at the tween's start and end, and
- * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting
- * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is
- * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens
- * is because it creates entirely new tweens that may have completely different targets than the original tween,
- * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API
- * and it would create other problems. For example:
- * - If I create a tween of elementA, that tween instance may suddenly change its target to include 50 other elements (unintuitive if I specifically defined the target I wanted)
- * - We can't just create new independent tweens because otherwise, what happens if the original/parent tween is reversed or pause or dropped into a TimelineLite for tight control? You'd expect that tween's behavior to affect all the others.
- * - Analyzing every style property of every child before and after the tween is an expensive operation when there are many children, so this behavior shouldn't be imposed on all className tweens by default, especially since it's probably rare that this extra functionality is needed.
- *
- * @param {Object} target object to be tweened
- * @param {number} Duration in seconds (or frames for frames-based tweens)
- * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone}
- * @return {Array} An array of TweenLite instances
- */
- CSSPlugin.cascadeTo = function(target, duration, vars) {
- var tween = TweenLite.to(target, duration, vars),
- results = [tween],
- b = [],
- e = [],
- targets = [],
- _reservedProps = TweenLite._internals.reservedProps,
- i, difs, p;
- target = tween._targets || tween.target;
- _getChildStyles(target, b, targets);
- tween.render(duration, true);
- _getChildStyles(target, e);
- tween.render(0, true);
- tween._enabled(true);
- i = targets.length;
- while (--i > -1) {
- difs = _cssDif(targets[i], b[i], e[i]);
- if (difs.firstMPT) {
- difs = difs.difs;
- for (p in vars) {
- if (_reservedProps[p]) {
- difs[p] = vars[p];
- }
- }
- results.push( TweenLite.to(targets[i], duration, difs) );
- }
- }
- return results;
- };
-
- TweenPlugin.activate([CSSPlugin]);
- return CSSPlugin;
-
- }, true);
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * RoundPropsPlugin
- * ----------------------------------------------------------------
- */
- (function() {
-
- var RoundPropsPlugin = window._gsDefine.plugin({
- propName: "roundProps",
- priority: -1,
- API: 2,
-
- //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
- init: function(target, value, tween) {
- this._tween = tween;
- return true;
- }
-
- }),
- p = RoundPropsPlugin.prototype;
-
- p._onInitAllProps = function() {
- var tween = this._tween,
- rp = (tween.vars.roundProps instanceof Array) ? tween.vars.roundProps : tween.vars.roundProps.split(","),
- i = rp.length,
- lookup = {},
- rpt = tween._propLookup.roundProps,
- prop, pt, next;
- while (--i > -1) {
- lookup[rp[i]] = 1;
- }
- i = rp.length;
- while (--i > -1) {
- prop = rp[i];
- pt = tween._firstPT;
- while (pt) {
- next = pt._next; //record here, because it may get removed
- if (pt.pg) {
- pt.t._roundProps(lookup, true);
- } else if (pt.n === prop) {
- this._add(pt.t, prop, pt.s, pt.c);
- //remove from linked list
- if (next) {
- next._prev = pt._prev;
- }
- if (pt._prev) {
- pt._prev._next = next;
- } else if (tween._firstPT === pt) {
- tween._firstPT = next;
- }
- pt._next = pt._prev = null;
- tween._propLookup[prop] = rpt;
- }
- pt = next;
- }
- }
- return false;
- };
-
- p._add = function(target, p, s, c) {
- this._addTween(target, p, s, s + c, p, true);
- this._overwriteProps.push(p);
- };
-
- }());
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * AttrPlugin
- * ----------------------------------------------------------------
- */
- window._gsDefine.plugin({
- propName: "attr",
- API: 2,
- version: "0.3.2",
-
- //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
- init: function(target, value, tween) {
- var p, start, end;
- if (typeof(target.setAttribute) !== "function") {
- return false;
- }
- this._target = target;
- this._proxy = {};
- this._start = {}; // we record start and end values exactly as they are in case they're strings (not numbers) - we need to be able to revert to them cleanly.
- this._end = {};
- for (p in value) {
- this._start[p] = this._proxy[p] = start = target.getAttribute(p);
- end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
- this._end[p] = end ? end.s + end.c : value[p];
- this._overwriteProps.push(p);
- }
- return true;
- },
-
- //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
- set: function(ratio) {
- this._super.setRatio.call(this, ratio);
- var props = this._overwriteProps,
- i = props.length,
- lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
- p;
- while (--i > -1) {
- p = props[i];
- this._target.setAttribute(p, lookup[p] + "");
- }
- }
-
- });
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * DirectionalRotationPlugin
- * ----------------------------------------------------------------
- */
- window._gsDefine.plugin({
- propName: "directionalRotation",
- API: 2,
- version: "0.2.0",
-
- //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
- init: function(target, value, tween) {
- if (typeof(value) !== "object") {
- value = {rotation:value};
- }
- this.finals = {};
- var cap = (value.useRadians === true) ? Math.PI * 2 : 360,
- min = 0.000001,
- p, v, start, end, dif, split;
- for (p in value) {
- if (p !== "useRadians") {
- split = (value[p] + "").split("_");
- v = split[0];
- start = parseFloat( (typeof(target[p]) !== "function") ? target[p] : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]() );
- end = this.finals[p] = (typeof(v) === "string" && v.charAt(1) === "=") ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0;
- dif = end - start;
- if (split.length) {
- v = split.join("_");
- if (v.indexOf("short") !== -1) {
- dif = dif % cap;
- if (dif !== dif % (cap / 2)) {
- dif = (dif < 0) ? dif + cap : dif - cap;
- }
- }
- if (v.indexOf("_cw") !== -1 && dif < 0) {
- dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
- } else if (v.indexOf("ccw") !== -1 && dif > 0) {
- dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
- }
- }
- if (dif > min || dif < -min) {
- this._addTween(target, p, start, start + dif, p);
- this._overwriteProps.push(p);
- }
- }
- }
- return true;
- },
-
- //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
- set: function(ratio) {
- var pt;
- if (ratio !== 1) {
- this._super.setRatio.call(this, ratio);
- } else {
- pt = this._firstPT;
- while (pt) {
- if (pt.f) {
- pt.t[pt.p](this.finals[pt.p]);
- } else {
- pt.t[pt.p] = this.finals[pt.p];
- }
- pt = pt._next;
- }
- }
- }
-
- })._autoCSS = true;
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * EasePack
- * ----------------------------------------------------------------
- */
- window._gsDefine("easing.Back", ["easing.Ease"], function(Ease) {
-
- var w = (window.GreenSockGlobals || window),
- gs = w.com.greensock,
- _2PI = Math.PI * 2,
- _HALF_PI = Math.PI / 2,
- _class = gs._class,
- _create = function(n, f) {
- var C = _class("easing." + n, function(){}, true),
- p = C.prototype = new Ease();
- p.constructor = C;
- p.getRatio = f;
- return C;
- },
- _easeReg = Ease.register || function(){}, //put an empty function in place just as a safety measure in case someone loads an OLD version of TweenLite.js where Ease.register doesn't exist.
- _wrap = function(name, EaseOut, EaseIn, EaseInOut, aliases) {
- var C = _class("easing."+name, {
- easeOut:new EaseOut(),
- easeIn:new EaseIn(),
- easeInOut:new EaseInOut()
- }, true);
- _easeReg(C, name);
- return C;
- },
- EasePoint = function(time, value, next) {
- this.t = time;
- this.v = value;
- if (next) {
- this.next = next;
- next.prev = this;
- this.c = next.v - value;
- this.gap = next.t - time;
- }
- },
-
- //Back
- _createBack = function(n, f) {
- var C = _class("easing." + n, function(overshoot) {
- this._p1 = (overshoot || overshoot === 0) ? overshoot : 1.70158;
- this._p2 = this._p1 * 1.525;
- }, true),
- p = C.prototype = new Ease();
- p.constructor = C;
- p.getRatio = f;
- p.config = function(overshoot) {
- return new C(overshoot);
- };
- return C;
- },
-
- Back = _wrap("Back",
- _createBack("BackOut", function(p) {
- return ((p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1);
- }),
- _createBack("BackIn", function(p) {
- return p * p * ((this._p1 + 1) * p - this._p1);
- }),
- _createBack("BackInOut", function(p) {
- return ((p *= 2) < 1) ? 0.5 * p * p * ((this._p2 + 1) * p - this._p2) : 0.5 * ((p -= 2) * p * ((this._p2 + 1) * p + this._p2) + 2);
- })
- ),
-
-
- //SlowMo
- SlowMo = _class("easing.SlowMo", function(linearRatio, power, yoyoMode) {
- power = (power || power === 0) ? power : 0.7;
- if (linearRatio == null) {
- linearRatio = 0.7;
- } else if (linearRatio > 1) {
- linearRatio = 1;
- }
- this._p = (linearRatio !== 1) ? power : 0;
- this._p1 = (1 - linearRatio) / 2;
- this._p2 = linearRatio;
- this._p3 = this._p1 + this._p2;
- this._calcEnd = (yoyoMode === true);
- }, true),
- p = SlowMo.prototype = new Ease(),
- SteppedEase, RoughEase, _createElastic;
-
- p.constructor = SlowMo;
- p.getRatio = function(p) {
- var r = p + (0.5 - p) * this._p;
- if (p < this._p1) {
- return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
- } else if (p > this._p3) {
- return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
- }
- return this._calcEnd ? 1 : r;
- };
- SlowMo.ease = new SlowMo(0.7, 0.7);
-
- p.config = SlowMo.config = function(linearRatio, power, yoyoMode) {
- return new SlowMo(linearRatio, power, yoyoMode);
- };
-
-
- //SteppedEase
- SteppedEase = _class("easing.SteppedEase", function(steps) {
- steps = steps || 1;
- this._p1 = 1 / steps;
- this._p2 = steps + 1;
- }, true);
- p = SteppedEase.prototype = new Ease();
- p.constructor = SteppedEase;
- p.getRatio = function(p) {
- if (p < 0) {
- p = 0;
- } else if (p >= 1) {
- p = 0.999999999;
- }
- return ((this._p2 * p) >> 0) * this._p1;
- };
- p.config = SteppedEase.config = function(steps) {
- return new SteppedEase(steps);
- };
-
-
- //RoughEase
- RoughEase = _class("easing.RoughEase", function(vars) {
- vars = vars || {};
- var taper = vars.taper || "none",
- a = [],
- cnt = 0,
- points = (vars.points || 20) | 0,
- i = points,
- randomize = (vars.randomize !== false),
- clamp = (vars.clamp === true),
- template = (vars.template instanceof Ease) ? vars.template : null,
- strength = (typeof(vars.strength) === "number") ? vars.strength * 0.4 : 0.4,
- x, y, bump, invX, obj, pnt;
- while (--i > -1) {
- x = randomize ? Math.random() : (1 / points) * i;
- y = template ? template.getRatio(x) : x;
- if (taper === "none") {
- bump = strength;
- } else if (taper === "out") {
- invX = 1 - x;
- bump = invX * invX * strength;
- } else if (taper === "in") {
- bump = x * x * strength;
- } else if (x < 0.5) { //"both" (start)
- invX = x * 2;
- bump = invX * invX * 0.5 * strength;
- } else { //"both" (end)
- invX = (1 - x) * 2;
- bump = invX * invX * 0.5 * strength;
- }
- if (randomize) {
- y += (Math.random() * bump) - (bump * 0.5);
- } else if (i % 2) {
- y += bump * 0.5;
- } else {
- y -= bump * 0.5;
- }
- if (clamp) {
- if (y > 1) {
- y = 1;
- } else if (y < 0) {
- y = 0;
- }
- }
- a[cnt++] = {x:x, y:y};
- }
- a.sort(function(a, b) {
- return a.x - b.x;
- });
-
- pnt = new EasePoint(1, 1, null);
- i = points;
- while (--i > -1) {
- obj = a[i];
- pnt = new EasePoint(obj.x, obj.y, pnt);
- }
-
- this._prev = new EasePoint(0, 0, (pnt.t !== 0) ? pnt : pnt.next);
- }, true);
- p = RoughEase.prototype = new Ease();
- p.constructor = RoughEase;
- p.getRatio = function(p) {
- var pnt = this._prev;
- if (p > pnt.t) {
- while (pnt.next && p >= pnt.t) {
- pnt = pnt.next;
- }
- pnt = pnt.prev;
- } else {
- while (pnt.prev && p <= pnt.t) {
- pnt = pnt.prev;
- }
- }
- this._prev = pnt;
- return (pnt.v + ((p - pnt.t) / pnt.gap) * pnt.c);
- };
- p.config = function(vars) {
- return new RoughEase(vars);
- };
- RoughEase.ease = new RoughEase();
-
-
- //Bounce
- _wrap("Bounce",
- _create("BounceOut", function(p) {
- if (p < 1 / 2.75) {
- return 7.5625 * p * p;
- } else if (p < 2 / 2.75) {
- return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
- } else if (p < 2.5 / 2.75) {
- return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
- }
- return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
- }),
- _create("BounceIn", function(p) {
- if ((p = 1 - p) < 1 / 2.75) {
- return 1 - (7.5625 * p * p);
- } else if (p < 2 / 2.75) {
- return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);
- } else if (p < 2.5 / 2.75) {
- return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);
- }
- return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);
- }),
- _create("BounceInOut", function(p) {
- var invert = (p < 0.5);
- if (invert) {
- p = 1 - (p * 2);
- } else {
- p = (p * 2) - 1;
- }
- if (p < 1 / 2.75) {
- p = 7.5625 * p * p;
- } else if (p < 2 / 2.75) {
- p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
- } else if (p < 2.5 / 2.75) {
- p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
- } else {
- p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
- }
- return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5;
- })
- );
-
-
- //CIRC
- _wrap("Circ",
- _create("CircOut", function(p) {
- return Math.sqrt(1 - (p = p - 1) * p);
- }),
- _create("CircIn", function(p) {
- return -(Math.sqrt(1 - (p * p)) - 1);
- }),
- _create("CircInOut", function(p) {
- return ((p*=2) < 1) ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1);
- })
- );
-
-
- //Elastic
- _createElastic = function(n, f, def) {
- var C = _class("easing." + n, function(amplitude, period) {
- this._p1 = amplitude || 1;
- this._p2 = period || def;
- this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0);
- }, true),
- p = C.prototype = new Ease();
- p.constructor = C;
- p.getRatio = f;
- p.config = function(amplitude, period) {
- return new C(amplitude, period);
- };
- return C;
- };
- _wrap("Elastic",
- _createElastic("ElasticOut", function(p) {
- return this._p1 * Math.pow(2, -10 * p) * Math.sin( (p - this._p3) * _2PI / this._p2 ) + 1;
- }, 0.3),
- _createElastic("ElasticIn", function(p) {
- return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ));
- }, 0.3),
- _createElastic("ElasticInOut", function(p) {
- return ((p *= 2) < 1) ? -0.5 * (this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2)) : this._p1 * Math.pow(2, -10 *(p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ) *0.5 + 1;
- }, 0.45)
- );
-
-
- //Expo
- _wrap("Expo",
- _create("ExpoOut", function(p) {
- return 1 - Math.pow(2, -10 * p);
- }),
- _create("ExpoIn", function(p) {
- return Math.pow(2, 10 * (p - 1)) - 0.001;
- }),
- _create("ExpoInOut", function(p) {
- return ((p *= 2) < 1) ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
- })
- );
-
-
- //Sine
- _wrap("Sine",
- _create("SineOut", function(p) {
- return Math.sin(p * _HALF_PI);
- }),
- _create("SineIn", function(p) {
- return -Math.cos(p * _HALF_PI) + 1;
- }),
- _create("SineInOut", function(p) {
- return -0.5 * (Math.cos(Math.PI * p) - 1);
- })
- );
-
- _class("easing.EaseLookup", {
- find:function(s) {
- return Ease.map[s];
- }
- }, true);
-
- //register the non-standard eases
- _easeReg(w.SlowMo, "SlowMo", "ease,");
- _easeReg(RoughEase, "RoughEase", "ease,");
- _easeReg(SteppedEase, "SteppedEase", "ease,");
-
- return Back;
-
- }, true);
-
-
-});
-
-
-
-
-
-
-
-
-
-
-
-/*
- * ----------------------------------------------------------------
- * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc.
- * ----------------------------------------------------------------
- */
-(function(window) {
-
- "use strict";
- var _globals = window.GreenSockGlobals || window;
- if (_globals.TweenLite) {
- return; //in case the core set of classes is already loaded, don't instantiate twice.
- }
- var _namespace = function(ns) {
- var a = ns.split("."),
- p = _globals, i;
- for (i = 0; i < a.length; i++) {
- p[a[i]] = p = p[a[i]] || {};
- }
- return p;
- },
- gs = _namespace("com.greensock"),
- _tinyNum = 0.0000000001,
- _slice = [].slice,
- _emptyFunc = function() {},
- _isArray = (function() { //works around issues in iframe environments where the Array global isn't shared, thus if the object originates in a different window/iframe, "(obj instanceof Array)" will evaluate false. We added some speed optimizations to avoid Object.prototype.toString.call() unless it's absolutely necessary because it's VERY slow (like 20x slower)
- var toString = Object.prototype.toString,
- array = toString.call([]);
- return function(obj) {
- return obj != null && (obj instanceof Array || (typeof(obj) === "object" && !!obj.push && toString.call(obj) === array));
- };
- }()),
- a, i, p, _ticker, _tickerActive,
- _defLookup = {},
-
- /**
- * @constructor
- * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition.
- * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is
- * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin
- * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally.
- *
- * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found,
- * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere,
- * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so
- * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything
- * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock
- * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could
- * sandbox the banner one like:
- *
- * <script>
- * var gs = window.GreenSockGlobals = {}; //the newer version we're about to load could now be referenced in a "gs" object, like gs.TweenLite.to(...). Use whatever alias you want as long as it's unique, "gs" or "banner" or whatever.
- * </script>
- * <script src="js/greensock/v1.7/TweenMax.js"></script>
- * <script>
- * window.GreenSockGlobals = null; //reset it back to null so that the next load of TweenMax affects the window and we can reference things directly like TweenLite.to(...)
- * </script>
- * <script src="js/greensock/v1.6/TweenMax.js"></script>
- * <script>
- * gs.TweenLite.to(...); //would use v1.7
- * TweenLite.to(...); //would use v1.6
- * </script>
- *
- * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back".
- * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"]
- * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition.
- * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object)
- */
- Definition = function(ns, dependencies, func, global) {
- this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses
- _defLookup[ns] = this;
- this.gsClass = null;
- this.func = func;
- var _classes = [];
- this.check = function(init) {
- var i = dependencies.length,
- missing = i,
- cur, a, n, cl;
- while (--i > -1) {
- if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) {
- _classes[i] = cur.gsClass;
- missing--;
- } else if (init) {
- cur.sc.push(this);
- }
- }
- if (missing === 0 && func) {
- a = ("com.greensock." + ns).split(".");
- n = a.pop();
- cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes);
-
- //exports to multiple environments
- if (global) {
- _globals[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.)
- if (typeof(define) === "function" && define.amd){ //AMD
- define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; });
- } else if (typeof(module) !== "undefined" && module.exports){ //node
- module.exports = cl;
- }
- }
- for (i = 0; i < this.sc.length; i++) {
- this.sc[i].check();
- }
- }
- };
- this.check(true);
- },
-
- //used to create Definition instances (which basically registers a class that has dependencies).
- _gsDefine = window._gsDefine = function(ns, dependencies, func, global) {
- return new Definition(ns, dependencies, func, global);
- },
-
- //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class).
- _class = gs._class = function(ns, func, global) {
- func = func || function() {};
- _gsDefine(ns, [], function(){ return func; }, global);
- return func;
- };
-
- _gsDefine.globals = _globals;
-
-
-
-/*
- * ----------------------------------------------------------------
- * Ease
- * ----------------------------------------------------------------
- */
- var _baseParams = [0, 0, 1, 1],
- _blankArray = [],
- Ease = _class("easing.Ease", function(func, extraParams, type, power) {
- this._func = func;
- this._type = type || 0;
- this._power = power || 0;
- this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams;
- }, true),
- _easeMap = Ease.map = {},
- _easeReg = Ease.register = function(ease, names, types, create) {
- var na = names.split(","),
- i = na.length,
- ta = (types || "easeIn,easeOut,easeInOut").split(","),
- e, name, j, type;
- while (--i > -1) {
- name = na[i];
- e = create ? _class("easing."+name, null, true) : gs.easing[name] || {};
- j = ta.length;
- while (--j > -1) {
- type = ta[j];
- _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease();
- }
- }
- };
-
- p = Ease.prototype;
- p._calcEnd = false;
- p.getRatio = function(p) {
- if (this._func) {
- this._params[0] = p;
- return this._func.apply(null, this._params);
- }
- var t = this._type,
- pw = this._power,
- r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2;
- if (pw === 1) {
- r *= r;
- } else if (pw === 2) {
- r *= r * r;
- } else if (pw === 3) {
- r *= r * r * r;
- } else if (pw === 4) {
- r *= r * r * r * r;
- }
- return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2);
- };
-
- //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut)
- a = ["Linear","Quad","Cubic","Quart","Quint,Strong"];
- i = a.length;
- while (--i > -1) {
- p = a[i]+",Power"+i;
- _easeReg(new Ease(null,null,1,i), p, "easeOut", true);
- _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : ""));
- _easeReg(new Ease(null,null,3,i), p, "easeInOut");
- }
- _easeMap.linear = gs.easing.Linear.easeIn;
- _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks
-
-
-/*
- * ----------------------------------------------------------------
- * EventDispatcher
- * ----------------------------------------------------------------
- */
- var EventDispatcher = _class("events.EventDispatcher", function(target) {
- this._listeners = {};
- this._eventTarget = target || this;
- });
- p = EventDispatcher.prototype;
-
- p.addEventListener = function(type, callback, scope, useParam, priority) {
- priority = priority || 0;
- var list = this._listeners[type],
- index = 0,
- listener, i;
- if (list == null) {
- this._listeners[type] = list = [];
- }
- i = list.length;
- while (--i > -1) {
- listener = list[i];
- if (listener.c === callback && listener.s === scope) {
- list.splice(i, 1);
- } else if (index === 0 && listener.pr < priority) {
- index = i + 1;
- }
- }
- list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority});
- if (this === _ticker && !_tickerActive) {
- _ticker.wake();
- }
- };
-
- p.removeEventListener = function(type, callback) {
- var list = this._listeners[type], i;
- if (list) {
- i = list.length;
- while (--i > -1) {
- if (list[i].c === callback) {
- list.splice(i, 1);
- return;
- }
- }
- }
- };
-
- p.dispatchEvent = function(type) {
- var list = this._listeners[type],
- i, t, listener;
- if (list) {
- i = list.length;
- t = this._eventTarget;
- while (--i > -1) {
- listener = list[i];
- if (listener.up) {
- listener.c.call(listener.s || t, {type:type, target:t});
- } else {
- listener.c.call(listener.s || t);
- }
- }
- }
- };
-
-
-/*
- * ----------------------------------------------------------------
- * Ticker
- * ----------------------------------------------------------------
- */
- var _reqAnimFrame = window.requestAnimationFrame,
- _cancelAnimFrame = window.cancelAnimationFrame,
- _getTime = Date.now || function() {return new Date().getTime();},
- _lastUpdate = _getTime();
-
- //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill.
- a = ["ms","moz","webkit","o"];
- i = a.length;
- while (--i > -1 && !_reqAnimFrame) {
- _reqAnimFrame = window[a[i] + "RequestAnimationFrame"];
- _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"];
- }
-
- _class("Ticker", function(fps, useRAF) {
- var _self = this,
- _startTime = _getTime(),
- _useRAF = (useRAF !== false && _reqAnimFrame),
- _lagThreshold = 500,
- _adjustedLag = 33,
- _fps, _req, _id, _gap, _nextTime,
- _tick = function(manual) {
- var elapsed = _getTime() - _lastUpdate,
- overlap, dispatch;
- if (elapsed > _lagThreshold) {
- _startTime += elapsed - _adjustedLag;
- }
- _lastUpdate += elapsed;
- _self.time = (_lastUpdate - _startTime) / 1000;
- overlap = _self.time - _nextTime;
- if (!_fps || overlap > 0 || manual === true) {
- _self.frame++;
- _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
- dispatch = true;
- }
- if (manual !== true) { //make sure the request is made before we dispatch the "tick" event so that timing is maintained. Otherwise, if processing the "tick" requires a bunch of time (like 15ms) and we're using a setTimeout() that's based on 16.7ms, it'd technically take 31.7ms between frames otherwise.
- _id = _req(_tick);
- }
- if (dispatch) {
- _self.dispatchEvent("tick");
- }
- };
-
- EventDispatcher.call(_self);
- _self.time = _self.frame = 0;
- _self.tick = function() {
- _tick(true);
- };
-
- _self.lagSmoothing = function(threshold, adjustedLag) {
- _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
- _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
- };
-
- _self.sleep = function() {
- if (_id == null) {
- return;
- }
- if (!_useRAF || !_cancelAnimFrame) {
- clearTimeout(_id);
- } else {
- _cancelAnimFrame(_id);
- }
- _req = _emptyFunc;
- _id = null;
- if (_self === _ticker) {
- _tickerActive = false;
- }
- };
-
- _self.wake = function() {
- if (_id !== null) {
- _self.sleep();
- } else if (_self.frame > 10) { //don't trigger lagSmoothing if we're just waking up, and make sure that at least 10 frames have elapsed because of the iOS bug that we work around below with the 1.5-second setTimout().
- _lastUpdate = _getTime() - _lagThreshold + 5;
- }
- _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
- if (_self === _ticker) {
- _tickerActive = true;
- }
- _tick(2);
- };
-
- _self.fps = function(value) {
- if (!arguments.length) {
- return _fps;
- }
- _fps = value;
- _gap = 1 / (_fps || 60);
- _nextTime = this.time + _gap;
- _self.wake();
- };
-
- _self.useRAF = function(value) {
- if (!arguments.length) {
- return _useRAF;
- }
- _self.sleep();
- _useRAF = value;
- _self.fps(_fps);
- };
- _self.fps(fps);
-
- //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition.
- setTimeout(function() {
- if (_useRAF && (!_id || _self.frame < 5)) {
- _self.useRAF(false);
- }
- }, 1500);
- });
-
- p = gs.Ticker.prototype = new gs.events.EventDispatcher();
- p.constructor = gs.Ticker;
-
-
-/*
- * ----------------------------------------------------------------
- * Animation
- * ----------------------------------------------------------------
- */
- var Animation = _class("core.Animation", function(duration, vars) {
- this.vars = vars = vars || {};
- this._duration = this._totalDuration = duration || 0;
- this._delay = Number(vars.delay) || 0;
- this._timeScale = 1;
- this._active = (vars.immediateRender === true);
- this.data = vars.data;
- this._reversed = (vars.reversed === true);
-
- if (!_rootTimeline) {
- return;
- }
- if (!_tickerActive) { //some browsers (like iOS 6 Safari) shut down JavaScript execution when the tab is disabled and they [occasionally] neglect to start up requestAnimationFrame again when returning - this code ensures that the engine starts up again properly.
- _ticker.wake();
- }
-
- var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline;
- tl.add(this, tl._time);
-
- if (this.vars.paused) {
- this.paused(true);
- }
- });
-
- _ticker = Animation.ticker = new gs.Ticker();
- p = Animation.prototype;
- p._dirty = p._gc = p._initted = p._paused = false;
- p._totalTime = p._time = 0;
- p._rawPrevTime = -1;
- p._next = p._last = p._onUpdate = p._timeline = p.timeline = null;
- p._paused = false;
-
-
- //some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker.
- var _checkTimeout = function() {
- if (_tickerActive && _getTime() - _lastUpdate > 2000) {
- _ticker.wake();
- }
- setTimeout(_checkTimeout, 2000);
- };
- _checkTimeout();
-
-
- p.play = function(from, suppressEvents) {
- if (from != null) {
- this.seek(from, suppressEvents);
- }
- return this.reversed(false).paused(false);
- };
-
- p.pause = function(atTime, suppressEvents) {
- if (atTime != null) {
- this.seek(atTime, suppressEvents);
- }
- return this.paused(true);
- };
-
- p.resume = function(from, suppressEvents) {
- if (from != null) {
- this.seek(from, suppressEvents);
- }
- return this.paused(false);
- };
-
- p.seek = function(time, suppressEvents) {
- return this.totalTime(Number(time), suppressEvents !== false);
- };
-
- p.restart = function(includeDelay, suppressEvents) {
- return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true);
- };
-
- p.reverse = function(from, suppressEvents) {
- if (from != null) {
- this.seek((from || this.totalDuration()), suppressEvents);
- }
- return this.reversed(true).paused(false);
- };
-
- p.render = function(time, suppressEvents, force) {
- //stub - we override this method in subclasses.
- };
-
- p.invalidate = function() {
- return this;
- };
-
- p.isActive = function() {
- var tl = this._timeline, //the 2 root timelines won't have a _timeline; they're always active.
- startTime = this._startTime,
- rawTime;
- return (!tl || (!this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime()) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale));
- };
-
- p._enabled = function (enabled, ignoreTimeline) {
- if (!_tickerActive) {
- _ticker.wake();
- }
- this._gc = !enabled;
- this._active = this.isActive();
- if (ignoreTimeline !== true) {
- if (enabled && !this.timeline) {
- this._timeline.add(this, this._startTime - this._delay);
- } else if (!enabled && this.timeline) {
- this._timeline._remove(this, true);
- }
- }
- return false;
- };
-
-
- p._kill = function(vars, target) {
- return this._enabled(false, false);
- };
-
- p.kill = function(vars, target) {
- this._kill(vars, target);
- return this;
- };
-
- p._uncache = function(includeSelf) {
- var tween = includeSelf ? this : this.timeline;
- while (tween) {
- tween._dirty = true;
- tween = tween.timeline;
- }
- return this;
- };
-
- p._swapSelfInParams = function(params) {
- var i = params.length,
- copy = params.concat();
- while (--i > -1) {
- if (params[i] === "{self}") {
- copy[i] = this;
- }
- }
- return copy;
- };
-
-//----Animation getters/setters --------------------------------------------------------
-
- p.eventCallback = function(type, callback, params, scope) {
- if ((type || "").substr(0,2) === "on") {
- var v = this.vars;
- if (arguments.length === 1) {
- return v[type];
- }
- if (callback == null) {
- delete v[type];
- } else {
- v[type] = callback;
- v[type + "Params"] = (_isArray(params) && params.join("").indexOf("{self}") !== -1) ? this._swapSelfInParams(params) : params;
- v[type + "Scope"] = scope;
- }
- if (type === "onUpdate") {
- this._onUpdate = callback;
- }
- }
- return this;
- };
-
- p.delay = function(value) {
- if (!arguments.length) {
- return this._delay;
- }
- if (this._timeline.smoothChildTiming) {
- this.startTime( this._startTime + value - this._delay );
- }
- this._delay = value;
- return this;
- };
-
- p.duration = function(value) {
- if (!arguments.length) {
- this._dirty = false;
- return this._duration;
- }
- this._duration = this._totalDuration = value;
- this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration.
- if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) {
- this.totalTime(this._totalTime * (value / this._duration), true);
- }
- return this;
- };
-
- p.totalDuration = function(value) {
- this._dirty = false;
- return (!arguments.length) ? this._totalDuration : this.duration(value);
- };
-
- p.time = function(value, suppressEvents) {
- if (!arguments.length) {
- return this._time;
- }
- if (this._dirty) {
- this.totalDuration();
- }
- return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents);
- };
-
- p.totalTime = function(time, suppressEvents, uncapped) {
- if (!_tickerActive) {
- _ticker.wake();
- }
- if (!arguments.length) {
- return this._totalTime;
- }
- if (this._timeline) {
- if (time < 0 && !uncapped) {
- time += this.totalDuration();
- }
- if (this._timeline.smoothChildTiming) {
- if (this._dirty) {
- this.totalDuration();
- }
- var totalDuration = this._totalDuration,
- tl = this._timeline;
- if (time > totalDuration && !uncapped) {
- time = totalDuration;
- }
- this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale);
- if (!tl._dirty) { //for performance improvement. If the parent's cache is already dirty, it already took care of marking the ancestors as dirty too, so skip the function call here.
- this._uncache(false);
- }
- //in case any of the ancestor timelines had completed but should now be enabled, we should reset their totalTime() which will also ensure that they're lined up properly and enabled. Skip for animations that are on the root (wasteful). Example: a TimelineLite.exportRoot() is performed when there's a paused tween on the root, the export will not complete until that tween is unpaused, but imagine a child gets restarted later, after all [unpaused] tweens have completed. The startTime of that child would get pushed out, but one of the ancestors may have completed.
- if (tl._timeline) {
- while (tl._timeline) {
- if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) {
- tl.totalTime(tl._totalTime, true);
- }
- tl = tl._timeline;
- }
- }
- }
- if (this._gc) {
- this._enabled(true, false);
- }
- if (this._totalTime !== time || this._duration === 0) {
- this.render(time, suppressEvents, false);
- if (_lazyTweens.length) { //in case rendering caused any tweens to lazy-init, we should render them because typically when someone calls seek() or time() or progress(), they expect an immediate render.
- _lazyRender();
- }
- }
- }
- return this;
- };
-
- p.progress = p.totalProgress = function(value, suppressEvents) {
- return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, suppressEvents);
- };
-
- p.startTime = function(value) {
- if (!arguments.length) {
- return this._startTime;
- }
- if (value !== this._startTime) {
- this._startTime = value;
- if (this.timeline) if (this.timeline._sortChildren) {
- this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
- }
- }
- return this;
- };
-
- p.timeScale = function(value) {
- if (!arguments.length) {
- return this._timeScale;
- }
- value = value || _tinyNum; //can't allow zero because it'll throw the math off
- if (this._timeline && this._timeline.smoothChildTiming) {
- var pauseTime = this._pauseTime,
- t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
- this._startTime = t - ((t - this._startTime) * this._timeScale / value);
- }
- this._timeScale = value;
- return this._uncache(false);
- };
-
- p.reversed = function(value) {
- if (!arguments.length) {
- return this._reversed;
- }
- if (value != this._reversed) {
- this._reversed = value;
- this.totalTime(((this._timeline && !this._timeline.smoothChildTiming) ? this.totalDuration() - this._totalTime : this._totalTime), true);
- }
- return this;
- };
-
- p.paused = function(value) {
- if (!arguments.length) {
- return this._paused;
- }
- if (value != this._paused) if (this._timeline) {
- if (!_tickerActive && !value) {
- _ticker.wake();
- }
- var tl = this._timeline,
- raw = tl.rawTime(),
- elapsed = raw - this._pauseTime;
- if (!value && tl.smoothChildTiming) {
- this._startTime += elapsed;
- this._uncache(false);
- }
- this._pauseTime = value ? raw : null;
- this._paused = value;
- this._active = this.isActive();
- if (!value && elapsed !== 0 && this._initted && this.duration()) {
- this.render((tl.smoothChildTiming ? this._totalTime : (raw - this._startTime) / this._timeScale), true, true); //in case the target's properties changed via some other tween or manual update by the user, we should force a render.
- }
- }
- if (this._gc && !value) {
- this._enabled(true, false);
- }
- return this;
- };
-
-
-/*
- * ----------------------------------------------------------------
- * SimpleTimeline
- * ----------------------------------------------------------------
- */
- var SimpleTimeline = _class("core.SimpleTimeline", function(vars) {
- Animation.call(this, 0, vars);
- this.autoRemoveChildren = this.smoothChildTiming = true;
- });
-
- p = SimpleTimeline.prototype = new Animation();
- p.constructor = SimpleTimeline;
- p.kill()._gc = false;
- p._first = p._last = null;
- p._sortChildren = false;
-
- p.add = p.insert = function(child, position, align, stagger) {
- var prevTween, st;
- child._startTime = Number(position || 0) + child._delay;
- if (child._paused) if (this !== child._timeline) { //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order).
- child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale);
- }
- if (child.timeline) {
- child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one.
- }
- child.timeline = child._timeline = this;
- if (child._gc) {
- child._enabled(true, true);
- }
- prevTween = this._last;
- if (this._sortChildren) {
- st = child._startTime;
- while (prevTween && prevTween._startTime > st) {
- prevTween = prevTween._prev;
- }
- }
- if (prevTween) {
- child._next = prevTween._next;
- prevTween._next = child;
- } else {
- child._next = this._first;
- this._first = child;
- }
- if (child._next) {
- child._next._prev = child;
- } else {
- this._last = child;
- }
- child._prev = prevTween;
- if (this._timeline) {
- this._uncache(true);
- }
- return this;
- };
-
- p._remove = function(tween, skipDisable) {
- if (tween.timeline === this) {
- if (!skipDisable) {
- tween._enabled(false, true);
- }
- tween.timeline = null;
-
- if (tween._prev) {
- tween._prev._next = tween._next;
- } else if (this._first === tween) {
- this._first = tween._next;
- }
- if (tween._next) {
- tween._next._prev = tween._prev;
- } else if (this._last === tween) {
- this._last = tween._prev;
- }
-
- if (this._timeline) {
- this._uncache(true);
- }
- }
- return this;
- };
-
- p.render = function(time, suppressEvents, force) {
- var tween = this._first,
- next;
- this._totalTime = this._time = this._rawPrevTime = time;
- while (tween) {
- next = tween._next; //record it here because the value could change after rendering...
- if (tween._active || (time >= tween._startTime && !tween._paused)) {
- if (!tween._reversed) {
- tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
- } else {
- tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
- }
- }
- tween = next;
- }
- };
-
- p.rawTime = function() {
- if (!_tickerActive) {
- _ticker.wake();
- }
- return this._totalTime;
- };
-
-/*
- * ----------------------------------------------------------------
- * TweenLite
- * ----------------------------------------------------------------
- */
- var TweenLite = _class("TweenLite", function(target, duration, vars) {
- Animation.call(this, duration, vars);
- this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
-
- if (target == null) {
- throw "Cannot tween a null target.";
- }
-
- this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
-
- var isSelector = (target.jquery || (target.length && target !== window && target[0] && (target[0] === window || (target[0].nodeType && target[0].style && !target.nodeType)))),
- overwrite = this.vars.overwrite,
- i, targ, targets;
-
- this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite];
-
- if ((isSelector || target instanceof Array || (target.push && _isArray(target))) && typeof(target[0]) !== "number") {
- this._targets = targets = _slice.call(target, 0);
- this._propLookup = [];
- this._siblings = [];
- for (i = 0; i < targets.length; i++) {
- targ = targets[i];
- if (!targ) {
- targets.splice(i--, 1);
- continue;
- } else if (typeof(targ) === "string") {
- targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings
- if (typeof(targ) === "string") {
- targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case)
- }
- continue;
- } else if (targ.length && targ !== window && targ[0] && (targ[0] === window || (targ[0].nodeType && targ[0].style && !targ.nodeType))) { //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that <select> elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself.
- targets.splice(i--, 1);
- this._targets = targets = targets.concat(_slice.call(targ, 0));
- continue;
- }
- this._siblings[i] = _register(targ, this, false);
- if (overwrite === 1) if (this._siblings[i].length > 1) {
- _applyOverwrite(targ, this, null, 1, this._siblings[i]);
- }
- }
-
- } else {
- this._propLookup = {};
- this._siblings = _register(target, this, false);
- if (overwrite === 1) if (this._siblings.length > 1) {
- _applyOverwrite(target, this, null, 1, this._siblings);
- }
- }
- if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
- this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render)
- this.render(-this._delay);
- }
- }, true),
- _isSelector = function(v) {
- return (v.length && v !== window && v[0] && (v[0] === window || (v[0].nodeType && v[0].style && !v.nodeType))); //we cannot check "nodeType" if the target is window from within an iframe, otherwise it will trigger a security error in some browsers like Firefox.
- },
- _autoCSS = function(vars, target) {
- var css = {},
- p;
- for (p in vars) {
- if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || (_plugins[p] && _plugins[p]._autoCSS))) { //note: <img> elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties.
- css[p] = vars[p];
- delete vars[p];
- }
- }
- vars.css = css;
- };
-
- p = TweenLite.prototype = new Animation();
- p.constructor = TweenLite;
- p.kill()._gc = false;
-
-//----TweenLite defaults, overwrite management, and root updates ----------------------------------------------------
-
- p.ratio = 0;
- p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
- p._notifyPluginsOfEnabled = p._lazy = false;
-
- TweenLite.version = "1.12.1";
- TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
- TweenLite.defaultOverwrite = "auto";
- TweenLite.ticker = _ticker;
- TweenLite.autoSleep = true;
- TweenLite.lagSmoothing = function(threshold, adjustedLag) {
- _ticker.lagSmoothing(threshold, adjustedLag);
- };
- TweenLite.selector = window.$ || window.jQuery || function(e) { if (window.$) { TweenLite.selector = window.$; return window.$(e); } return window.document ? window.document.getElementById((e.charAt(0) === "#") ? e.substr(1) : e) : e; };
-
- var _lazyTweens = [],
- _lazyLookup = {},
- _internals = TweenLite._internals = {isArray:_isArray, isSelector:_isSelector, lazyTweens:_lazyTweens}, //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object.
- _plugins = TweenLite._plugins = {},
- _tweenLookup = _internals.tweenLookup = {},
- _tweenLookupNum = 0,
- _reservedProps = _internals.reservedProps = {ease:1, delay:1, overwrite:1, onComplete:1, onCompleteParams:1, onCompleteScope:1, useFrames:1, runBackwards:1, startAt:1, onUpdate:1, onUpdateParams:1, onUpdateScope:1, onStart:1, onStartParams:1, onStartScope:1, onReverseComplete:1, onReverseCompleteParams:1, onReverseCompleteScope:1, onRepeat:1, onRepeatParams:1, onRepeatScope:1, easeParams:1, yoyo:1, immediateRender:1, repeat:1, repeatDelay:1, data:1, paused:1, reversed:1, autoCSS:1, lazy:1},
- _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
- _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
- _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
- _lazyRender = function() {
- var i = _lazyTweens.length;
- _lazyLookup = {};
- while (--i > -1) {
- a = _lazyTweens[i];
- if (a && a._lazy !== false) {
- a.render(a._lazy, false, true);
- a._lazy = false;
- }
- }
- _lazyTweens.length = 0;
- };
-
- _rootTimeline._startTime = _ticker.time;
- _rootFramesTimeline._startTime = _ticker.frame;
- _rootTimeline._active = _rootFramesTimeline._active = true;
- setTimeout(_lazyRender, 1); //on some mobile devices, there isn't a "tick" before code runs which means any lazy renders wouldn't run before the next official "tick".
-
- Animation._updateRoot = TweenLite.render = function() {
- var i, a, p;
- if (_lazyTweens.length) { //if code is run outside of the requestAnimationFrame loop, there may be tweens queued AFTER the engine refreshed, so we need to ensure any pending renders occur before we refresh again.
- _lazyRender();
- }
- _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
- _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
- if (_lazyTweens.length) {
- _lazyRender();
- }
- if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
- for (p in _tweenLookup) {
- a = _tweenLookup[p].tweens;
- i = a.length;
- while (--i > -1) {
- if (a[i]._gc) {
- a.splice(i, 1);
- }
- }
- if (a.length === 0) {
- delete _tweenLookup[p];
- }
- }
- //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly
- p = _rootTimeline._first;
- if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) {
- while (p && p._paused) {
- p = p._next;
- }
- if (!p) {
- _ticker.sleep();
- }
- }
- }
- };
-
- _ticker.addEventListener("tick", Animation._updateRoot);
-
- var _register = function(target, tween, scrub) {
- var id = target._gsTweenID, a, i;
- if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) {
- _tweenLookup[id] = {target:target, tweens:[]};
- }
- if (tween) {
- a = _tweenLookup[id].tweens;
- a[(i = a.length)] = tween;
- if (scrub) {
- while (--i > -1) {
- if (a[i] === tween) {
- a.splice(i, 1);
- }
- }
- }
- }
- return _tweenLookup[id].tweens;
- },
-
- _applyOverwrite = function(target, tween, props, mode, siblings) {
- var i, changed, curTween, l;
- if (mode === 1 || mode >= 4) {
- l = siblings.length;
- for (i = 0; i < l; i++) {
- if ((curTween = siblings[i]) !== tween) {
- if (!curTween._gc) if (curTween._enabled(false, false)) {
- changed = true;
- }
- } else if (mode === 5) {
- break;
- }
- }
- return changed;
- }
- //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example)
- var startTime = tween._startTime + _tinyNum,
- overlaps = [],
- oCount = 0,
- zeroDur = (tween._duration === 0),
- globalStart;
- i = siblings.length;
- while (--i > -1) {
- if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) {
- //ignore
- } else if (curTween._timeline !== tween._timeline) {
- globalStart = globalStart || _checkOverlap(tween, 0, zeroDur);
- if (_checkOverlap(curTween, globalStart, zeroDur) === 0) {
- overlaps[oCount++] = curTween;
- }
- } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) {
- overlaps[oCount++] = curTween;
- }
- }
-
- i = oCount;
- while (--i > -1) {
- curTween = overlaps[i];
- if (mode === 2) if (curTween._kill(props, target)) {
- changed = true;
- }
- if (mode !== 2 || (!curTween._firstPT && curTween._initted)) {
- if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween.
- changed = true;
- }
- }
- }
- return changed;
- },
-
- _checkOverlap = function(tween, reference, zeroDur) {
- var tl = tween._timeline,
- ts = tl._timeScale,
- t = tween._startTime;
- while (tl._timeline) {
- t += tl._startTime;
- ts *= tl._timeScale;
- if (tl._paused) {
- return -100;
- }
- tl = tl._timeline;
- }
- t /= ts;
- return (t > reference) ? t - reference : ((zeroDur && t === reference) || (!tween._initted && t - reference < 2 * _tinyNum)) ? _tinyNum : ((t += tween.totalDuration() / tween._timeScale / ts) > reference + _tinyNum) ? 0 : t - reference - _tinyNum;
- };
-
-
-//---- TweenLite instance methods -----------------------------------------------------------------------------
-
- p._init = function() {
- var v = this.vars,
- op = this._overwrittenProps,
- dur = this._duration,
- immediate = !!v.immediateRender,
- ease = v.ease,
- i, initPlugins, pt, p, startVars;
- if (v.startAt) {
- if (this._startAt) {
- this._startAt.render(-1, true); //if we've run a startAt previously (when the tween instantiated), we should revert it so that the values re-instantiate correctly particularly for relative tweens. Without this, a TweenLite.fromTo(obj, 1, {x:"+=100"}, {x:"-=100"}), for example, would actually jump to +=200 because the startAt would run twice, doubling the relative change.
- this._startAt.kill();
- }
- startVars = {};
- for (p in v.startAt) { //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from);
- startVars[p] = v.startAt[p];
- }
- startVars.overwrite = false;
- startVars.immediateRender = true;
- startVars.lazy = (immediate && v.lazy !== false);
- startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
- this._startAt = TweenLite.to(this.target, 0, startVars);
- if (immediate) {
- if (this._time > 0) {
- this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()).
- } else if (dur !== 0) {
- return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting.
- }
- }
- } else if (v.runBackwards && dur !== 0) {
- //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards)
- if (this._startAt) {
- this._startAt.render(-1, true);
- this._startAt.kill();
- this._startAt = null;
- } else {
- pt = {};
- for (p in v) { //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through.
- if (!_reservedProps[p] || p === "autoCSS") {
- pt[p] = v[p];
- }
- }
- pt.overwrite = 0;
- pt.data = "isFromStart"; //we tag the tween with as "isFromStart" so that if [inside a plugin] we need to only do something at the very END of a tween, we have a way of identifying this tween as merely the one that's setting the beginning values for a "from()" tween. For example, clearProps in CSSPlugin should only get applied at the very END of a tween and without this tag, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in.
- pt.lazy = (immediate && v.lazy !== false);
- pt.immediateRender = immediate; //zero-duration tweens render immediately by default, but if we're not specifically instructed to render this tween immediately, we should skip this and merely _init() to record the starting values (rendering them immediately would push them to completion which is wasteful in that case - we'd have to render(-1) immediately after)
- this._startAt = TweenLite.to(this.target, 0, pt);
- if (!immediate) {
- this._startAt._init(); //ensures that the initial values are recorded
- this._startAt._enabled(false); //no need to have the tween render on the next cycle. Disable it because we'll always manually control the renders of the _startAt tween.
- } else if (this._time === 0) {
- return;
- }
- }
- }
- if (!ease) {
- this._ease = TweenLite.defaultEase;
- } else if (ease instanceof Ease) {
- this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease;
- } else {
- this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase;
- }
- this._easeType = this._ease._type;
- this._easePower = this._ease._power;
- this._firstPT = null;
-
- if (this._targets) {
- i = this._targets.length;
- while (--i > -1) {
- if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) {
- initPlugins = true;
- }
- }
- } else {
- initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op);
- }
-
- if (initPlugins) {
- TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite
- }
- if (op) if (!this._firstPT) if (typeof(this.target) !== "function") { //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live.
- this._enabled(false, false);
- }
- if (v.runBackwards) {
- pt = this._firstPT;
- while (pt) {
- pt.s += pt.c;
- pt.c = -pt.c;
- pt = pt._next;
- }
- }
- this._onUpdate = v.onUpdate;
- this._initted = true;
- };
-
- p._initProps = function(target, propLookup, siblings, overwrittenProps) {
- var p, i, initPlugins, plugin, pt, v;
- if (target == null) {
- return false;
- }
-
- if (_lazyLookup[target._gsTweenID]) {
- _lazyRender(); //if other tweens of the same target have recently initted but haven't rendered yet, we've got to force the render so that the starting values are correct (imagine populating a timeline with a bunch of sequential tweens and then jumping to the end)
- }
-
- if (!this.vars.css) if (target.style) if (target !== window && target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity). Note: we cannot check "nodeType" on the window inside an iframe.
- _autoCSS(this.vars, target);
- }
- for (p in this.vars) {
- v = this.vars[p];
- if (_reservedProps[p]) {
- if (v) if ((v instanceof Array) || (v.push && _isArray(v))) if (v.join("").indexOf("{self}") !== -1) {
- this.vars[p] = v = this._swapSelfInParams(v, this);
- }
-
- } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) {
-
- //t - target [object]
- //p - property [string]
- //s - start [number]
- //c - change [number]
- //f - isFunction [boolean]
- //n - name [string]
- //pg - isPlugin [boolean]
- //pr - priority [number]
- this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority};
- i = plugin._overwriteProps.length;
- while (--i > -1) {
- propLookup[plugin._overwriteProps[i]] = this._firstPT;
- }
- if (plugin._priority || plugin._onInitAllProps) {
- initPlugins = true;
- }
- if (plugin._onDisable || plugin._onEnable) {
- this._notifyPluginsOfEnabled = true;
- }
-
- } else {
- this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0};
- pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
- pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0;
- }
- if (pt) if (pt._next) {
- pt._next._prev = pt;
- }
- }
-
- if (overwrittenProps) if (this._kill(overwrittenProps, target)) { //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first)
- return this._initProps(target, propLookup, siblings, overwrittenProps);
- }
- if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) {
- this._kill(propLookup, target);
- return this._initProps(target, propLookup, siblings, overwrittenProps);
- }
- if (this._firstPT) if ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration)) { //zero duration tweens don't lazy render by default; everything else does.
- _lazyLookup[target._gsTweenID] = true;
- }
- return initPlugins;
- };
-
- p.render = function(time, suppressEvents, force) {
- var prevTime = this._time,
- duration = this._duration,
- prevRawPrevTime = this._rawPrevTime,
- isComplete, callback, pt, rawPrevTime;
- if (time >= duration) {
- this._totalTime = this._time = duration;
- this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
- if (!this._reversed ) {
- isComplete = true;
- callback = "onComplete";
- }
- if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
- time = 0;
- }
- if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
- force = true;
- if (prevRawPrevTime > _tinyNum) {
- callback = "onReverseComplete";
- }
- }
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- }
-
- } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
- this._totalTime = this._time = 0;
- this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
- if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
- callback = "onReverseComplete";
- isComplete = this._reversed;
- }
- if (time < 0) {
- this._active = false;
- if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
- if (prevRawPrevTime >= 0) {
- force = true;
- }
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
- }
- } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
- force = true;
- }
- } else {
- this._totalTime = this._time = time;
-
- if (this._easeType) {
- var r = time / duration, type = this._easeType, pow = this._easePower;
- if (type === 1 || (type === 3 && r >= 0.5)) {
- r = 1 - r;
- }
- if (type === 3) {
- r *= 2;
- }
- if (pow === 1) {
- r *= r;
- } else if (pow === 2) {
- r *= r * r;
- } else if (pow === 3) {
- r *= r * r * r;
- } else if (pow === 4) {
- r *= r * r * r * r;
- }
-
- if (type === 1) {
- this.ratio = 1 - r;
- } else if (type === 2) {
- this.ratio = r;
- } else if (time / duration < 0.5) {
- this.ratio = r / 2;
- } else {
- this.ratio = 1 - (r / 2);
- }
-
- } else {
- this.ratio = this._ease.getRatio(time / duration);
- }
- }
-
- if (this._time === prevTime && !force) {
- return;
- } else if (!this._initted) {
- this._init();
- if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
- return;
- } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
- this._time = this._totalTime = prevTime;
- this._rawPrevTime = prevRawPrevTime;
- _lazyTweens.push(this);
- this._lazy = time;
- return;
- }
- //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
- if (this._time && !isComplete) {
- this.ratio = this._ease.getRatio(this._time / duration);
- } else if (isComplete && this._ease._calcEnd) {
- this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
- }
- }
- if (this._lazy !== false) { //in case a lazy render is pending, we should flush it because the new render is occuring now (imagine a lazy tween instantiating and then immediately the user calls tween.seek(tween.duration()), skipping to the end - the end render would be forced, and then if we didn't flush the lazy render, it'd fire AFTER the seek(), rendering it at the wrong time.
- this._lazy = false;
- }
- if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
- this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
- }
- if (prevTime === 0) {
- if (this._startAt) {
- if (time >= 0) {
- this._startAt.render(time, suppressEvents, force);
- } else if (!callback) {
- callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
- }
- }
- if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
- this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
- }
- }
-
- pt = this._firstPT;
- while (pt) {
- if (pt.f) {
- pt.t[pt.p](pt.c * this.ratio + pt.s);
- } else {
- pt.t[pt.p] = pt.c * this.ratio + pt.s;
- }
- pt = pt._next;
- }
-
- if (this._onUpdate) {
- if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
- }
- if (!suppressEvents) if (this._time !== prevTime || isComplete) {
- this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
- }
- }
-
- if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate
- if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force);
- }
- if (isComplete) {
- if (this._timeline.autoRemoveChildren) {
- this._enabled(false, false);
- }
- this._active = false;
- }
- if (!suppressEvents && this.vars[callback]) {
- this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
- }
- if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
- this._rawPrevTime = 0;
- }
- }
-
- };
-
- p._kill = function(vars, target) {
- if (vars === "all") {
- vars = null;
- }
- if (vars == null) if (target == null || target === this.target) {
- this._lazy = false;
- return this._enabled(false, false);
- }
- target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
- var i, overwrittenProps, p, pt, propLookup, changed, killProps, record;
- if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
- i = target.length;
- while (--i > -1) {
- if (this._kill(vars, target[i])) {
- changed = true;
- }
- }
- } else {
- if (this._targets) {
- i = this._targets.length;
- while (--i > -1) {
- if (target === this._targets[i]) {
- propLookup = this._propLookup[i] || {};
- this._overwrittenProps = this._overwrittenProps || [];
- overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all";
- break;
- }
- }
- } else if (target !== this.target) {
- return false;
- } else {
- propLookup = this._propLookup;
- overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all";
- }
-
- if (propLookup) {
- killProps = vars || propLookup;
- record = (vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (typeof(vars) !== "object" || !vars._tempKill)); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin)
- for (p in killProps) {
- if ((pt = propLookup[p])) {
- if (pt.pg && pt.t._kill(killProps)) {
- changed = true; //some plugins need to be notified so they can perform cleanup tasks first
- }
- if (!pt.pg || pt.t._overwriteProps.length === 0) {
- if (pt._prev) {
- pt._prev._next = pt._next;
- } else if (pt === this._firstPT) {
- this._firstPT = pt._next;
- }
- if (pt._next) {
- pt._next._prev = pt._prev;
- }
- pt._next = pt._prev = null;
- }
- delete propLookup[p];
- }
- if (record) {
- overwrittenProps[p] = 1;
- }
- }
- if (!this._firstPT && this._initted) { //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening.
- this._enabled(false, false);
- }
- }
- }
- return changed;
- };
-
- p.invalidate = function() {
- if (this._notifyPluginsOfEnabled) {
- TweenLite._onPluginEvent("_onDisable", this);
- }
- this._firstPT = null;
- this._overwrittenProps = null;
- this._onUpdate = null;
- this._startAt = null;
- this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
- this._propLookup = (this._targets) ? {} : [];
- return this;
- };
-
- p._enabled = function(enabled, ignoreTimeline) {
- if (!_tickerActive) {
- _ticker.wake();
- }
- if (enabled && this._gc) {
- var targets = this._targets,
- i;
- if (targets) {
- i = targets.length;
- while (--i > -1) {
- this._siblings[i] = _register(targets[i], this, true);
- }
- } else {
- this._siblings = _register(this.target, this, true);
- }
- }
- Animation.prototype._enabled.call(this, enabled, ignoreTimeline);
- if (this._notifyPluginsOfEnabled) if (this._firstPT) {
- return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this);
- }
- return false;
- };
-
-
-//----TweenLite static methods -----------------------------------------------------
-
- TweenLite.to = function(target, duration, vars) {
- return new TweenLite(target, duration, vars);
- };
-
- TweenLite.from = function(target, duration, vars) {
- vars.runBackwards = true;
- vars.immediateRender = (vars.immediateRender != false);
- return new TweenLite(target, duration, vars);
- };
-
- TweenLite.fromTo = function(target, duration, fromVars, toVars) {
- toVars.startAt = fromVars;
- toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
- return new TweenLite(target, duration, toVars);
- };
-
- TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) {
- return new TweenLite(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
- };
-
- TweenLite.set = function(target, vars) {
- return new TweenLite(target, 0, vars);
- };
-
- TweenLite.getTweensOf = function(target, onlyActive) {
- if (target == null) { return []; }
- target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
- var i, a, j, t;
- if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
- i = target.length;
- a = [];
- while (--i > -1) {
- a = a.concat(TweenLite.getTweensOf(target[i], onlyActive));
- }
- i = a.length;
- //now get rid of any duplicates (tweens of arrays of objects could cause duplicates)
- while (--i > -1) {
- t = a[i];
- j = i;
- while (--j > -1) {
- if (t === a[j]) {
- a.splice(i, 1);
- }
- }
- }
- } else {
- a = _register(target).concat();
- i = a.length;
- while (--i > -1) {
- if (a[i]._gc || (onlyActive && !a[i].isActive())) {
- a.splice(i, 1);
- }
- }
- }
- return a;
- };
-
- TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, onlyActive, vars) {
- if (typeof(onlyActive) === "object") {
- vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted)
- onlyActive = false;
- }
- var a = TweenLite.getTweensOf(target, onlyActive),
- i = a.length;
- while (--i > -1) {
- a[i]._kill(vars, target);
- }
- };
-
-
-
-/*
- * ----------------------------------------------------------------
- * TweenPlugin (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another <script> call before loading plugins which is easy to forget)
- * ----------------------------------------------------------------
- */
- var TweenPlugin = _class("plugins.TweenPlugin", function(props, priority) {
- this._overwriteProps = (props || "").split(",");
- this._propName = this._overwriteProps[0];
- this._priority = priority || 0;
- this._super = TweenPlugin.prototype;
- }, true);
-
- p = TweenPlugin.prototype;
- TweenPlugin.version = "1.10.1";
- TweenPlugin.API = 2;
- p._firstPT = null;
-
- p._addTween = function(target, prop, start, end, overwriteProp, round) {
- var c, pt;
- if (end != null && (c = (typeof(end) === "number" || end.charAt(1) !== "=") ? Number(end) - start : parseInt(end.charAt(0) + "1", 10) * Number(end.substr(2)))) {
- this._firstPT = pt = {_next:this._firstPT, t:target, p:prop, s:start, c:c, f:(typeof(target[prop]) === "function"), n:overwriteProp || prop, r:round};
- if (pt._next) {
- pt._next._prev = pt;
- }
- return pt;
- }
- };
-
- p.setRatio = function(v) {
- var pt = this._firstPT,
- min = 0.000001,
- val;
- while (pt) {
- val = pt.c * v + pt.s;
- if (pt.r) {
- val = Math.round(val);
- } else if (val < min) if (val > -min) { //prevents issues with converting very small numbers to strings in the browser
- val = 0;
- }
- if (pt.f) {
- pt.t[pt.p](val);
- } else {
- pt.t[pt.p] = val;
- }
- pt = pt._next;
- }
- };
-
- p._kill = function(lookup) {
- var a = this._overwriteProps,
- pt = this._firstPT,
- i;
- if (lookup[this._propName] != null) {
- this._overwriteProps = [];
- } else {
- i = a.length;
- while (--i > -1) {
- if (lookup[a[i]] != null) {
- a.splice(i, 1);
- }
- }
- }
- while (pt) {
- if (lookup[pt.n] != null) {
- if (pt._next) {
- pt._next._prev = pt._prev;
- }
- if (pt._prev) {
- pt._prev._next = pt._next;
- pt._prev = null;
- } else if (this._firstPT === pt) {
- this._firstPT = pt._next;
- }
- }
- pt = pt._next;
- }
- return false;
- };
-
- p._roundProps = function(lookup, value) {
- var pt = this._firstPT;
- while (pt) {
- if (lookup[this._propName] || (pt.n != null && lookup[ pt.n.split(this._propName + "_").join("") ])) { //some properties that are very plugin-specific add a prefix named after the _propName plus an underscore, so we need to ignore that extra stuff here.
- pt.r = value;
- }
- pt = pt._next;
- }
- };
-
- TweenLite._onPluginEvent = function(type, tween) {
- var pt = tween._firstPT,
- changed, pt2, first, last, next;
- if (type === "_onInitAllProps") {
- //sorts the PropTween linked list in order of priority because some plugins need to render earlier/later than others, like MotionBlurPlugin applies its effects after all x/y/alpha tweens have rendered on each frame.
- while (pt) {
- next = pt._next;
- pt2 = first;
- while (pt2 && pt2.pr > pt.pr) {
- pt2 = pt2._next;
- }
- if ((pt._prev = pt2 ? pt2._prev : last)) {
- pt._prev._next = pt;
- } else {
- first = pt;
- }
- if ((pt._next = pt2)) {
- pt2._prev = pt;
- } else {
- last = pt;
- }
- pt = next;
- }
- pt = tween._firstPT = first;
- }
- while (pt) {
- if (pt.pg) if (typeof(pt.t[type]) === "function") if (pt.t[type]()) {
- changed = true;
- }
- pt = pt._next;
- }
- return changed;
- };
-
- TweenPlugin.activate = function(plugins) {
- var i = plugins.length;
- while (--i > -1) {
- if (plugins[i].API === TweenPlugin.API) {
- _plugins[(new plugins[i]())._propName] = plugins[i];
- }
- }
- return true;
- };
-
- //provides a more concise way to define plugins that have no dependencies besides TweenPlugin and TweenLite, wrapping common boilerplate stuff into one function (added in 1.9.0). You don't NEED to use this to define a plugin - the old way still works and can be useful in certain (rare) situations.
- _gsDefine.plugin = function(config) {
- if (!config || !config.propName || !config.init || !config.API) { throw "illegal plugin definition."; }
- var propName = config.propName,
- priority = config.priority || 0,
- overwriteProps = config.overwriteProps,
- map = {init:"_onInitTween", set:"setRatio", kill:"_kill", round:"_roundProps", initAll:"_onInitAllProps"},
- Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin",
- function() {
- TweenPlugin.call(this, propName, priority);
- this._overwriteProps = overwriteProps || [];
- }, (config.global === true)),
- p = Plugin.prototype = new TweenPlugin(propName),
- prop;
- p.constructor = Plugin;
- Plugin.API = config.API;
- for (prop in map) {
- if (typeof(config[prop]) === "function") {
- p[map[prop]] = config[prop];
- }
- }
- Plugin.version = config.version;
- TweenPlugin.activate([Plugin]);
- return Plugin;
- };
-
-
- //now run through all the dependencies discovered and if any are missing, log that to the console as a warning. This is why it's best to have TweenLite load last - it can check all the dependencies for you.
- a = window._gsQueue;
- if (a) {
- for (i = 0; i < a.length; i++) {
- a[i]();
- }
- for (p in _defLookup) {
- if (!_defLookup[p].func) {
- //window.console.log("GSAP encountered missing dependency: com.greensock." + p);
- }
- }
- }
-
- _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated
-
-})(window);
-
-angular.module('att.abs.transition', [])
-
-.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
-
- var $transition = function(element, trigger, options) {
- options = options || {};
- var deferred = $q.defer();
- var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
-
- var transitionEndHandler = function() {
- $rootScope.$apply(function() {
- element.unbind(endEventName, transitionEndHandler);
- deferred.resolve(element);
- });
- };
-
- if (endEventName) {
- element.bind(endEventName, transitionEndHandler);
- }
-
- // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
- $timeout(function() {
- if ( angular.isString(trigger) ) {
- element.addClass(trigger);
- } else if ( angular.isFunction(trigger) ) {
- trigger(element);
- } else if ( angular.isObject(trigger) ) {
- element.css(trigger);
- }
- //If browser does not support transitions, instantly resolve
- if ( !endEventName ) {
- deferred.resolve(element);
- }
- }, 100);
-
- // Add our custom cancel function to the promise that is returned
- // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
- // i.e. it will therefore never raise a transitionEnd event for that transition
- deferred.promise.cancel = function() {
- if ( endEventName ) {
- element.unbind(endEventName, transitionEndHandler);
- }
- deferred.reject('Transition cancelled');
- };
-
- return deferred.promise;
- };
-
- // Work out the name of the transitionEnd event
- var transElement = document.createElement('trans');
- var transitionEndEventNames = {
- 'WebkitTransition': 'webkitTransitionEnd',
- 'MozTransition': 'transitionend',
- 'OTransition': 'oTransitionEnd',
- 'transition': 'transitionend'
- };
- var animationEndEventNames = {
- 'WebkitTransition': 'webkitAnimationEnd',
- 'MozTransition': 'animationend',
- 'OTransition': 'oAnimationEnd',
- 'transition': 'animationend'
- };
- function findEndEventName(endEventNames) {
- for (var name in endEventNames){
- if (transElement.style[name] !== undefined) {
- return endEventNames[name];
- }
- }
- }
- $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
- $transition.animationEndEventName = findEndEventName(animationEndEventNames);
- return $transition;
-}])
-
-.factory('$scrollTo', ['$window', function($window) {
- var $scrollTo = function(offsetLeft, offsetTop, duration) {
- TweenMax.to($window, duration || 1, {scrollTo: {y: offsetTop, x: offsetLeft}, ease: Power4.easeOut});
- };
- return $scrollTo;
-}])
-.factory('animation', function(){
- return TweenMax;
-})
-.factory('$progressBar', function(){
-
- //Provides a function to pass in code for closure purposes
- var loadingAnimationCreator = function(onUpdateCallback){
-
- //Use closure to setup some resuable code
- var loadingAnimation = function(callback, duration){
- TweenMax.to({}, duration, {
- onUpdateParams: ["{self}"],
- onUpdate: onUpdateCallback,
- onComplete: callback
- });
- };
- //Returns a function that takes a callback function and a duration for the animation
- return (function(){
- return loadingAnimation;
- })();
- };
-
- return loadingAnimationCreator;
-})
-.factory('$height', function(){
- var heightAnimation = function(element,duration,height,alpha){
- TweenMax.to(element,
- duration,
- {height:height, autoAlpha:alpha},
- 0);
- };
- return heightAnimation;
-});
-angular.module('att.abs.accordion', ['att.abs.utilities', 'att.abs.position', 'att.abs.transition'])
-.constant('accordionConfig', {
- closeOthers: false
-}).controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', '$log',
-function ($scope, $attrs, accordionConfig, $log) {
-// This array keeps track of the accordion groups
-this.groups = [];
-this.index = -1;
-// Keep reference to user's scope to properly assign `is-open`
-this.scope = $scope;
-$scope.forceExpand = false;
-// Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
-this.closeOthers = function (openGroup) {
- var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
- if (closeOthers && !$scope.forceExpand) {
- angular.forEach(this.groups, function (group) {
- if (group !== openGroup) {
- group.isOpen = false;
- }
- });
- }
- if (this.groups.indexOf(openGroup) === (this.groups.length - 1) && $scope.forceExpand) {
- $scope.forceExpand = false;
- }
-};
-this.expandAll = function () {
- $scope.forceExpand = true;
- angular.forEach(this.groups, function (group) {
- group.isOpen = true;
- });
-};
-this.collapseAll = function () {
- angular.forEach(this.groups, function (group) {
- group.isOpen = false;
- });
-};
-/**function focus @param focusGroup */
-this.focus = function (focusGroup) {
- var self = this;
- angular.forEach(this.groups, function (group, index) {
- if (group !== focusGroup) {
- group.focused = false;
- } else {
- self.index = index;
- group.focused = true;
- }
- });
-};
-/** @param blurGroup*/
-this.blur = function (blurGroup) {
- blurGroup.focused = false;
- this.index = -1;
- $log.log("accordion.blur()", blurGroup);
-};
-/** @param group - the group in current focus @param down - cycling down */
-this.cycle = function (group, down, noRecycle) {
- if (!down) {
- if (this.index <= 0 && !noRecycle) {
- this.index = this.groups.length - 1;
- } else {
- this.index--;
- }
- } else {
- if (this.index === (this.groups.length - 1))
- {
- if (noRecycle) {
- this.index = 0;
- group.focused = false;
- $scope.$apply();
- return;
- }
- else
- {
- this.index = 0;
- }
- } else {
- this.index++;
- }
- }
-
- group.focused = false;
- this.groups[this.index].setFocus = true;
- this.groups[this.index].focused = true;
- $scope.$apply();
-};
-// This is called from the accordion-group directive to add itself to the accordion
-this.addGroup = function (groupScope) {
- var that = this;
- groupScope.index = this.groups.length;
- groupScope.focused = false;
- this.groups.push(groupScope);
-
- if(this.groups.length > 0){
- this.index = 0;
- }
-
- groupScope.$on('$destroy', function () {
- that.removeGroup(groupScope);
- });
-};
-// This is called from the accordion-group directive when to remove itself
-this.removeGroup = function (group) {
- var index = this.groups.indexOf(group);
- if (index !== -1) {
- this.groups.splice(this.groups.indexOf(group), 1);
- }
-};
-}])
-//The accordion directive simply sets up the directive controller and adds an accordion CSS class to itself element.
-.directive('accordion', function () {
- return {
- restrict: 'EA',
- controller: 'AccordionController',
- transclude: true,
- replace: false,
- scope: {
- cClass: '@css',
- expandAll: "=?",
- collapseAll: "=?"
- },
- template: '<div class="{{cClass}}" ng-transclude></div>',
- link: function (scope, elem, attribute, ctrl) {
- scope.$watch("expandAll", function (value) {
- if (value) {
- ctrl.expandAll();
- scope.expandAll = false;
- }
- });
- scope.$watch("collapseAll", function (value) {
- if (value) {
- ctrl.collapseAll();
- scope.collapseAll = false;
- }
- });
- }
- };
-})
-//The accordion-group directive indicates a block of html that will expand and collapse in an accordion
-.directive('accordionGroup', [ function () {
- return {
- // We need this directive to be inside an accordion
- require: ['^accordion', 'accordionGroup'],
- restrict: 'EA',
- // It transcludes the contents of the directive into the template
- transclude: true,
- // The element containing the directive will be replaced with the template
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/accordion/accordion.html',
- scope: {
- // Create an isolated scope and interpolate the heading attribute onto this scope
- heading: '@',
- isOpen: '=?'
- },
- controller: ['$scope', function ($scope)
- {
- $scope.showicon = true;
- this.setHeading = function (element)
- {
- this.heading = element;
- $scope.showicon = false;
- };
- this.isIsOpen = function ()
- {
- return $scope.isOpen;
- };
- }],
- link: function (scope, element, attrs, ctrl) {
- var accordionCtrl = ctrl[0];
- var accordionGroupCtrl = ctrl[1];
- var keys = {tab: 9, enter: 13, esc: 27, space: 32, pageup: 33, pagedown: 34, end: 35, home: 36, left: 37, up: 38, right: 39, down: 40};
- //not a fix
- var tab = element.children().eq(0);
- var parentHyperLink=attrs.parentLink;
- scope.setFocus = false;
- scope.childLength = attrs.childLength;
- scope.headingIconClass = attrs.imageSource;
-
- var handleKeydown = function (ev) {
- var boolFlag = true;
- switch (ev.keyCode)
- {
- case keys.enter:
- ev.preventDefault();
- scope.toggle();
- scope.$apply();
- break;
- case keys.up:
- case keys.left:
- ev.preventDefault();
- accordionCtrl.cycle(scope, false);
- break;
- case keys.down:
- case keys.right:
- ev.preventDefault();
- accordionCtrl.cycle(scope, true);
- break;
- default:
- boolFlag = false;
- break;
- }
- ev.stopPropagation();
- return boolFlag;
- };
-
- if (angular.isUndefined(scope.isOpen)) {
- scope.isOpen = false;
- }
-
- tab.bind("keydown", handleKeydown);
-
- accordionCtrl.addGroup(scope);
-
- if (scope.index === 0) {
- scope.focused = true;
- }
-
- accordionGroupCtrl.toggle = scope.toggle = function () {
- /* if the menu item has children, toggle/expand child menu of this item */
- if (scope.childLength>0) {
- scope.isOpen = !scope.isOpen;
- accordionCtrl.focus(scope);
- return scope.isOpen;
- }
- /* if the menu item does not have children, redirect to parent action URL*/
- else {
- window.location.href = parentHyperLink;
- }
-
- };
-
- scope.$watch('isOpen', function (value) {
- if (value) {
- accordionCtrl.closeOthers(scope);
- }
- });
-
- scope.$watch("focused", function (value) {
- if (!!value) {
- tab.attr("tabindex", "0");
- if(scope.setFocus){
- tab[0].focus();
- }
- }
- else{
- scope.setFocus = false;
- tab.attr("tabindex", "-1");
- }
- });
- }
- };
- }])
-//Use accordion-heading below an accordion-group to provide a heading containing HTML
-//<accordion-group>
-//<accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
-//</accordion-group>
-.directive('accordionToggle', function () {
- return{
- restrict: 'EA',
- require: '^accordionGroup',
- scope: {
- expandIcon: '@',
- collapseIcon: '@'
- },
- link: function (scope, element, attr, accordionCtrl)
- {
- var setIcon = function (isOpen) {
- if (scope.expandIcon && scope.collapseIcon)
- {
- if (isOpen) {
- element.removeClass(scope.expandIcon);
- element.addClass(scope.collapseIcon);
- }
- else {
- element.removeClass(scope.collapseIcon);
- element.addClass(scope.expandIcon);
- }
- }
- };
- element.bind('click', function ()
- {
- accordionCtrl.toggle();
- scope.$apply();
- });
- scope.$watch(function () {
- return accordionCtrl.isIsOpen();
- }, function (value) {
- setIcon(value);
- });
- }
- };
-}).directive('accordionHeading', function () {
-return {
-restrict: 'EA',
-transclude: true,
-template: '',
-require: '^accordionGroup',
-compile: function (element, attr, transclude) {
- var link = function (scope, element, attr, accordionGroupCtrl) {
- // Pass the heading to the accordion-group controller
- // so that it can be transcluded into the right place in the template
- // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
- transclude(scope, function (clone) {
- element.append(clone);
- accordionGroupCtrl.setHeading(element);
- });
- };
- return link;
-}
-};
-})
-// Use in the accordion-group template to indicate where you want the heading to be transcluded
-// You must provide the property on the accordion-group controller that will hold the transcluded element
- .directive('accordionTransclude', function () {
- return {
- require: '^accordionGroup',
- link: function (scope, element, attr, controller) {
- scope.$watch(function () {
- return controller[attr.accordionTransclude];
- }, function (heading) {
- if (heading) {
- element.find("span").eq(0).prepend(heading);
- }
- });
- }
- };
- })
- .directive('attGoTop', ['$scrollTo', function ($scrollTo) {
- return {
- restrict: 'A',
- transclude: false,
- link: function (scope, elem, attrs)
- {
- elem.bind('click', function ()
- {
- $scrollTo(0, attrs["attGoTop"]);
- });
- }
- };
- }])
- .directive('attGoTo', ['$anchorScroll', '$location', function ($anchorScroll, $location) {
- return {
- restrict: 'A',
- transclude: false,
- link: function (scope, elem, attrs)
- {
- elem.bind('click', function ()
- {
- var newHash = attrs["attGoTo"];
- if ($location.hash() !== newHash)
- {
- $location.hash(attrs["attGoTo"]);
- }
- else
- {
- $anchorScroll();
- }
- });
- }
- };
- }])
- .directive('freeStanding', function () {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- scope: true,
- template: "<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n" +
- "<div class='section-toggle'>\n" +
- "<button class='section-toggle__button' ng-click='fsToggle()'>\n" +
- " {{btnText}}<i style='font-size:0.875rem' ng-class='{\"ion-ios-arrow-up\": showAccordion,\"ion-ios-arrow-down\": !showAccordion, }'></i> \n" +
- "</button>\n" +
- "</div></div>",
- compile: function (element, attr, transclude)
- {
- var link = function (scope, elem, attrs) {
- scope.content = "";
- transclude(scope, function (clone)
- {
- elem.find("span").append(clone);
- });
- scope.showAccordion = false;
- scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
- scope.fsToggle = function ()
- {
- scope.showAccordion = !scope.showAccordion;
- scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
- };
- };
- return link;
- }
- };
- }).directive('expanders', function () {
- return{
- restrict: 'EA',
- replace: true,
- transclude: true,
- template: "<div ng-transclude></div>",
- controller: ['$scope', function ($scope){
- var bodyScope = null;
- this.setScope = function (scope) {
- bodyScope = scope;
- };
- this.toggle = function () {
- $scope.isOpen = bodyScope.isOpen = !bodyScope.isOpen;
- return bodyScope.isOpen;
- };
- }],
- link: function (scope)
- {
- scope.isOpen = false;
- }
- };
-}).directive('expanderHeading', function () {
- return{
- require: "^expanders",
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: true,
- template: "<div style='padding:10px !important' ng-transclude></div>"
- };
-}).directive('expanderBody', function () {
- return{
- restrict: 'EA',
- require: "^expanders",
- replace: true,
- transclude: true,
- scope: {},
- template: "<div collapse='!isOpen'><div ng-transclude></div></div>",
- link: function (scope, elem, attr, myCtrl) {
- scope.isOpen = false;
- myCtrl.setScope(scope);
- }
- };
-}).directive('expanderToggle', function () {
- return{
- restrict: 'EA',
- require: "^expanders",
- scope: {
- expandIcon: '@',
- collapseIcon: '@'
- },
- link: function (scope, element, attr, myCtrl)
- {
- var isOpen = false;
- var setIcon = function () {
- if (scope.expandIcon && scope.collapseIcon)
- {
- if (isOpen) {
- element.removeClass(scope.expandIcon);
- element.addClass(scope.collapseIcon);
- }
- else {
- element.removeClass(scope.collapseIcon);
- element.addClass(scope.expandIcon);
- }
- }
- };
- element.bind("keydown", function (e) {
- if (e.keyCode === 13)
- {
- scope.toggleit();
- }
- });
- element.bind('click', function ()
- {
- scope.toggleit();
- });
- scope.toggleit = function ()
- {
- isOpen = myCtrl.toggle();
- setIcon();
- scope.$apply();
- };
- setIcon();
- }
- };
-}).directive('collapse', ['$transition', function ($transition) {
- // CSS transitions don't work with height: auto, so we have to manually change the height to a
- // specific value and then once the animation completes, we can reset the height to auto.
- // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
- // "collapse") then you trigger a change to height 0 in between.
- // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
- var props = {
- open: {
- marginTop: null,
- marginBottom: null,
- paddingTop: null,
- paddingBottom: null,
- display: 'block'
- },
- closed: {
- marginTop: 0,
- marginBottom: 0,
- paddingTop: 0,
- paddingBottom: 0,
- display: 'none'
- }
- };
- var fixUpHeight = function (scope, element, height) {
- // We remove the collapse CSS class to prevent a transition when we change to height: auto
- element.removeClass('collapse');
- element.css({height: height});
- //adjusting for any margin or padding
- if (height === 0) {
- element.css(props.closed);
- } else {
- element.css(props.open);
- }
- // It appears that reading offsetWidth makes the browser realise that we have changed the
- // height already :-/
- element.addClass('collapse');
- };
- return {
- link: function (scope, element, attrs) {
- var isCollapsed;
- var initialAnimSkip = true;
- scope.$watch(function () {
- return element[0].scrollHeight;
- }, function () {
- //The listener is called when scrollHeight changes
- //It actually does on 2 scenarios:
- // 1. Parent is set to display none
- // 2. angular bindings inside are resolved
- //When we have a change of scrollHeight we are setting again the correct height if the group is opened
- if (element[0].scrollHeight !== 0 && !isCollapsed) {
- if (initialAnimSkip) {
- fixUpHeight(scope, element, element[0].scrollHeight + 'px');
- } else {
- fixUpHeight(scope, element, 'auto');
- }
- }
- });
- var currentTransition;
- var doTransition = function (change) {
- if (currentTransition) {
- currentTransition.cancel();
- }
- currentTransition = $transition(element, change);
- currentTransition.then(
- function () {
- currentTransition = undefined;
- },
- function () {
- currentTransition = undefined;
- }
- );
- return currentTransition;
- };
- var expand = function () {
- scope.postTransition = true;
- if (initialAnimSkip) {
- initialAnimSkip = false;
- if (!isCollapsed) {
- fixUpHeight(scope, element, 'auto');
- }
- } else {
- doTransition(angular.extend({height: element[0].scrollHeight + 'px'}, props.open))
- .then(function () {
- // This check ensures that we don't accidentally update the height if the user has closed
- // the group while the animation was still running
- if (!isCollapsed)
- {
- fixUpHeight(scope, element, 'auto');
- }
- });
- }
- isCollapsed = false;
- };
- var collapse = function () {
- isCollapsed = true;
- if (initialAnimSkip) {
- initialAnimSkip = false;
- fixUpHeight(scope, element, 0);
- } else {
- fixUpHeight(scope, element, element[0].scrollHeight + 'px');
- doTransition(angular.extend({height: 0}, props.closed)).then(function () {
- scope.postTransition = false;
- });
- }
- };
- scope.$watch(attrs.collapse, function (value) {
- if (value) {
- collapse();
- } else {
- expand();
- }
- });
- }
- };
- }])
- .directive('attAccord', function () {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- scope: {},
- controller: 'AttAccordCtrl',
- templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html'
- };
- })
- .controller('AttAccordCtrl', [function () {
- this.type = 'attAccord';
- this.headerCtrl;
- this.bodyCtrl;
- var isOpen = true;
- this.toggleBody = function () {
- if (isOpen) {
- this.expandBody();
- }
- else {
- this.collapseBody();
- }
- isOpen = !isOpen;
- };
- this.expandBody = function () {
- this.bodyCtrl.expand();
- };
- this.collapseBody = function () {
- this.bodyCtrl.collapse();
- };
- }])
- .controller('AttAccordHeaderCtrl', [function () {
- this.type = 'header';
- }])
- .directive('attAccordHeader', ['keymap', 'events', function (keymap, events) {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- require: ['^attAccord', 'attAccordHeader'],
- controller: 'AttAccordHeaderCtrl',
- templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
- link: function (scope, element, attr, ctrls) {
- var attAccordCtrl = ctrls[0];
- var attAccordHeaderCtrl = ctrls[1];
- attAccordCtrl.headerCtrl = attAccordHeaderCtrl;
- var tab = element.children().eq(0);
-
- scope.clickFunc = function () {
- attAccordCtrl.toggleBody();
- };
-
- var handleKeydown = function (ev) {
- var boolFlag = true;
- switch (ev.keyCode)
- {
- case keymap.KEY.ENTER:
- ev.preventDefault();
- scope.clickFunc();
- scope.$apply();
- break;
- default:
- boolFlag = false;
- break;
- }
- ev.stopPropagation();
- return boolFlag;
- };
-
- if (angular.isUndefined(scope.isOpen)) {
- scope.isOpen = false;
- }
-
- tab.bind("keydown", handleKeydown);
- }
- };
- }])
- .controller('AttAccordBodyCtrl', ['$scope', function ($scope) {
- this.type = 'body';
- this.expand = function () {
- $scope.expand();
- };
- this.collapse = function () {
- $scope.collapse();
- };
- }])
- .directive('attAccordBody', ['$timeout', '$height', function ($timeout, $height) {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- require: ['^attAccord', 'attAccordBody'],
- controller: 'AttAccordBodyCtrl',
- templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordBody.html',
- link: function (scope, element, attr, ctrls) {
- var attAccordCtrl = ctrls[0];
- var attAccordBodyCtrl = ctrls[1];
- attAccordCtrl.bodyCtrl = attAccordBodyCtrl;
- var originalHeight;
- $timeout(function () {
- originalHeight = element[0].offsetHeight;
- $height(element, 0, 0, 0);
- });
- scope.expand = function () {
- $height(element, 0.05, originalHeight, 1);
- };
- scope.collapse = function () {
- $height(element, 0.25, 0, 0);
- };
- }
- };
- }]);
-angular.module('att.abs.alert', [])
-.directive('attAlert', [function()
-{
- return {
- restrict:'EA',
- replace : true,
- transclude : true,
- scope: {
- alertType : "@type",
- showTop : "@topPos",
- showAlert : "="
- },
- templateUrl : 'app/scripts/ng_js_att_tpls/alert/alert.html',
- link: function(scope)
- {
- if(scope.showTop === 'true'){
- scope.cssStyle = {'top':'50px'};
- }
- else{
- scope.cssStyle = {'top':'0px'};
- }
- scope.close = function(){
- scope.showAlert = false;
- };
- }
- };
-}]);
-
-angular.module('att.abs.boardStrip', ['att.abs.utilities'])
-.constant('BoardStripConfig', {
- 'maxVisibleBoards': 4,
- 'boardsToScroll': 1,
- /* These parameters are non-configurable and remain unaltered, until there is a change in corresponding SCSS */
- 'boardLength': 140,
- 'boardMargin': 15
-})
-.directive('attBoard', [function() {
- return {
- restrict: 'AE',
- replace: true,
- transclude: true,
- require: '^attBoardStrip',
- scope : {
- boardIndex : '=',
- boardLabel : '='
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoard.html',
- link: function(scope, element, attrs, ctrls) {
-
- var parentCtrl = ctrls;
-
- scope.getCurrentIndex = function() {
- return parentCtrl.getCurrentIndex();
- };
- scope.selectBoard = function(boardIndex) {
- if (!isNaN(boardIndex)) {
- parentCtrl.setCurrentIndex(boardIndex);
- }
- };
- scope.isInView = function(boardIndex) {
- return parentCtrl.isInView(boardIndex);
- };
- }
- };
-}])
-.directive('attBoardStrip', ['BoardStripConfig', '$timeout', '$ieVersion', function(BoardStripConfig, $timeout, $ieVersion) {
- return {
- restrict: 'AE',
- replace: true,
- transclude: true,
- scope: {
- currentIndex: '=selectedIndex',
- boardsMasterArray : '=',
- onAddBoard : '&?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html',
- controller: function($scope) {
- if(!angular.isDefined($scope.boardsMasterArray)){
- $scope.boardsMasterArray = [];
- }
-
- this.rectifyMaxVisibleBoards = function() {
- if (this.maxVisibleIndex >= $scope.boardsMasterArray.length) {
- this.maxVisibleIndex = $scope.boardsMasterArray.length - 1;
- }
-
- if (this.maxVisibleIndex < 0) {
- this.maxVisibleIndex = 0;
- }
- };
-
- this.resetBoardStrip = function(){
- $scope.currentIndex = 0;
-
- this.maxVisibleIndex = BoardStripConfig.maxVisibleBoards-1;
- this.minVisibleIndex = 0;
-
- this.rectifyMaxVisibleBoards();
- };
-
-
- if ($scope.currentIndex > 0) {
- var index = $scope.currentIndex;
- this.resetBoardStrip();
- if (index > $scope.boardsMasterArray.length) {
- $scope.currentIndex = $scope.boardsMasterArray.length-1;
- } else {
- $scope.currentIndex = index;
- }
- } else {
- this.resetBoardStrip();
- }
-
-
- this.getCurrentIndex = function() {
- return $scope.currentIndex;
- };
- this.setCurrentIndex = function(indx) {
- $scope.currentIndex = indx;
- };
-
- this.isInView = function(index) {
- return (index <= this.maxVisibleIndex && index >= this.minVisibleIndex);
- };
-
- this.getBoardsMasterArrayLength = function() {
- return $scope.boardsMasterArray.length;
- };
- },
- link: function(scope, element, attrs, ctrl) {
- var ieVersion = $ieVersion();
-
- var oldTimeout;
- var animationTimeout = 1000;
-
- if(ieVersion && ieVersion < 10) {
- animationTimeout = 0;
- }
-
- var getBoardViewportWidth = function (numberOfVisibleBoards) {
- return numberOfVisibleBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
- };
- if(element[0].querySelector(".board-viewport")) {
- angular.element(element[0].querySelector(".board-viewport")).css({"width": getBoardViewportWidth(BoardStripConfig.maxVisibleBoards) + "px"});
- }
-
- var getBoardstripContainerWidth = function (totalNumberOfBoards) {
- return totalNumberOfBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
- };
- if(element[0].querySelector(".boardstrip-container")) {
- angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
- angular.element(element[0].querySelector(".boardstrip-container")).css({"left": "0px"});
- }
-
- var calculateAndGetBoardstripContainerAdjustment = function () {
-
- var calculatedAdjustmentValue;
-
- if(ctrl.getBoardsMasterArrayLength() <= BoardStripConfig.maxVisibleBoards) {
- calculatedAdjustmentValue = 0;
- }
- else{
- calculatedAdjustmentValue = (ctrl.minVisibleIndex * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin))* -1;
- }
-
- return calculatedAdjustmentValue;
- };
-
- var updateBoardsTabIndex = function(boardArray, minViewIndex, maxViewIndex) {
- for (var i = 0; i < boardArray.length; i++) {
- angular.element(boardArray[i]).attr('tabindex', '-1');
- }
- for (var i = minViewIndex; i <= maxViewIndex; i++) {
- angular.element(boardArray[i]).attr('tabindex', '0');
- }
- };
-
- scope.$watchCollection('boardsMasterArray', function(newVal, oldVal){
- if(newVal !== oldVal){
- /* When a board is removed */
- if(newVal.length < oldVal.length){
- ctrl.resetBoardStrip();
- $timeout(function(){
-
- var currentBoardArray = element[0].querySelectorAll('[att-board]');
- if(currentBoardArray.length !== 0) {
-
- var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
- var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
- if(oldContainerAdjustment !== containerAdjustment+'px') {
- angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
-
- $timeout.cancel(oldTimeout);
- oldTimeout = $timeout(function(){
- currentBoardArray[0].focus();
- }, animationTimeout);
- }
- else{
- currentBoardArray[0].focus();
- }
- }
- else{
- element[0].querySelector('div.boardstrip-item--add').focus();
- }
-
- angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
- });
- }
- /* When a board is added */
- else {
- ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength()-1;
- ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
-
- ctrl.setCurrentIndex(ctrl.maxVisibleIndex);
-
- $timeout(function(){
- angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
-
- var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
- var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
- var currentBoardArray = element[0].querySelectorAll('[att-board]');
- if(oldContainerAdjustment !== containerAdjustment+'px') {
- angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
-
- $timeout.cancel(oldTimeout);
- oldTimeout = $timeout(function(){
- currentBoardArray[currentBoardArray.length-1].focus();
- }, animationTimeout);
- }
- else{
- currentBoardArray[currentBoardArray.length-1].focus();
- }
- /* Update tabindecies to ensure keyboard navigation behaves correctly */
- updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
- });
- }
- }
- });
-
- scope.nextBoard = function() {
- ctrl.maxVisibleIndex += BoardStripConfig.boardsToScroll;
- ctrl.rectifyMaxVisibleBoards();
- ctrl.minVisibleIndex = ctrl.maxVisibleIndex - (BoardStripConfig.maxVisibleBoards-1);
-
- $timeout.cancel(oldTimeout);
- angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
-
- $timeout(function(){
- var currentBoardArray = element[0].querySelectorAll('[att-board]');
-
- /* Remove tabindex from non-visible boards */
- updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
-
- if (!(scope.isNextBoard())) {
- try {
- currentBoardArray[currentBoardArray.length-1].focus();
- } catch(e) {}
- }
- }, animationTimeout);
- };
- scope.prevBoard = function() {
-
- ctrl.minVisibleIndex -= BoardStripConfig.boardsToScroll;
- if (ctrl.minVisibleIndex < 0) {
- ctrl.minVisibleIndex = 0;
- }
-
- ctrl.maxVisibleIndex = ctrl.minVisibleIndex + BoardStripConfig.maxVisibleBoards-1;
- ctrl.rectifyMaxVisibleBoards();
-
- $timeout.cancel(oldTimeout);
- angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
-
- $timeout(function(){
- var currentBoardArray = element[0].querySelectorAll('[att-board]');
-
- /* Remove tabindex from non-visible boards */
- updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
-
- if (ctrl.minVisibleIndex === 0) {
- try {
- element[0].querySelector('div.boardstrip-item--add').focus();
- } catch (e) {} /* IE8 may throw exception */
- }
- });
- };
-
- scope.isPrevBoard = function() {
- return (ctrl.minVisibleIndex > 0);
- };
- scope.isNextBoard = function() {
- return (ctrl.getBoardsMasterArrayLength()-1 > ctrl.maxVisibleIndex);
- };
- }
- };
-}])
-.directive('attAddBoard', ['BoardStripConfig', '$parse', '$timeout', function(BoardStripConfig, $parse, $timeout) {
- return {
- restrict: 'AE',
- replace: true,
- require: '^attBoardStrip',
- scope : {
- onAddBoard : '&?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html',
- link: function(scope, element, attrs, ctrls) {
- var parentCtrl = ctrls;
- scope.addBoard = function() {
- if (attrs['onAddBoard'] ) {
- scope.onAddBoard = $parse(scope.onAddBoard);
- scope.onAddBoard();
- }
- };
- }
- };
-}])
-.directive('attBoardNavigation', ['keymap', 'events', function(keymap, events) {
- return {
- restrict: 'AE',
- link: function(scope, elem) {
-
- var prevElem = keymap.KEY.LEFT;
- var nextElem = keymap.KEY.RIGHT;
-
- elem.bind('keydown', function (ev) {
-
- if (!(ev.keyCode)) {
- ev.keyCode = ev.which;
- }
-
- switch (ev.keyCode) {
- case nextElem:
- events.preventDefault(ev);
- events.stopPropagation(ev);
-
- if (elem[0].nextElementSibling && parseInt(angular.element(elem[0].nextElementSibling).attr('tabindex')) >= 0) {
- angular.element(elem[0])[0].nextElementSibling.focus();
- } else {
- /* IE8 fix */
- var el = angular.element(elem[0])[0];
- do {
- if (el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
-
- if (el.tagName && el.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
- el.focus();
- }
- }
-
- break;
- case prevElem:
- events.preventDefault(ev);
- events.stopPropagation(ev);
-
- if (elem[0].previousElementSibling && parseInt(angular.element(elem[0].previousElementSibling).attr('tabindex')) >= 0) {
- angular.element(elem[0])[0].previousElementSibling.focus();
- } else {
- /* IE8 fix */
- var el1 = angular.element(elem[0])[0];
- do {
- if (el1.previousSibling){
- el1 = el1.previousSibling;
- }
- else{
- break;
- }
- } while (el1 && el1.tagName !== 'LI');
-
- if (el1.tagName && el1.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
- el1.focus();
- }
- }
- break;
- default:
- break;
- }
- });
- }
- };
-}]);
-
-angular.module('att.abs.breadCrumbs', [])
- .constant("classConstant",{
- "defaultClass" : "breadcrumbs__link",
- "activeClass": "breadcrumbs__link--active"
- })
- .directive('attCrumb', ['classConstant', function(classConstant) {
- return {
- restrict: 'A',
- link: function(scope, elem, attr) {
- elem.addClass(classConstant.defaultClass);
- if(attr.attCrumb === 'active'){
- elem.addClass(classConstant.activeClass);
- }
- if(!elem.hasClass('last')){
- elem.after('<i class="breadcrumbs__item"></i>');
- }
- }
- };
- }
-]);
-angular.module('att.abs.buttons', ['att.abs.position', 'att.abs.utilities'])
- .constant('btnConfig', {
- btnClass: 'button',
- btnPrimaryClass: 'button--primary',
- btnSecondaryClass: 'button--secondary',
- btnDisabledClass: 'button--inactive',
- btnSmallClass: 'button--small'
- })
- .directive('attButton', ['btnConfig', function (btnConfig) {
- return {
- restrict: 'A',
- link: function (scope, element, attrs) {
- element.addClass(btnConfig.btnClass);
- if (attrs.size === 'small') {
- element.addClass(btnConfig.btnSmallClass);
- }
- attrs.$observe('btnType', function (value) {
- if (value === 'primary') {
- element.addClass(btnConfig.btnPrimaryClass);
- element.removeClass(btnConfig.btnSecondaryClass);
- element.removeClass(btnConfig.btnDisabledClass);
- element.removeAttr('disabled');
- } else if (value === 'secondary') {
- element.addClass(btnConfig.btnSecondaryClass);
- element.removeClass(btnConfig.btnPrimaryClass);
- element.removeClass(btnConfig.btnDisabledClass);
- element.removeAttr('disabled');
- } else if (value === 'disabled') {
- element.addClass(btnConfig.btnDisabledClass);
- element.removeClass(btnConfig.btnPrimaryClass);
- element.removeClass(btnConfig.btnSecondaryClass);
- element.attr('disabled', 'disabled');
- }
- });
- }
- };
- }])
- .directive('attButtonLoader', [function () {
- return {
- restrict: 'A',
- replace: false,
- scope: {
- size: '@'
- },
- template: '<div ng-class="{\'button--loading\': size === \'large\',\'button--loading__small\': size === \'small\'}"><i></i><i class="second__loader"></i><i></i></div>',
- link: function (scope, element) {
- element.addClass('button button--inactive');
- }
- };
- }])
- .directive('attButtonHero', [function () {
- return {
- restrict: 'A',
- replace: false,
- transclude: true,
- scope: {
- icon: '@'
- },
- template: '<div class="button--hero__inner"><span ng-transclude></span> <i ng-class="{\'icon-arrow-right\': icon === \'arrow-right\',\'icon-cart\': icon === \'cart\'}"></i></div>',
- link: function (scope, element) {
- element.addClass('button button--hero');
- element.attr("tabindex", "0");
- }
- };
- }])
- .directive('attBtnDropdown', ['$document', '$timeout', '$isElement', '$documentBind', 'keymap', 'events', function ($document, $timeout, $isElement, $documentBind, keymap, events) {
- return {
- restrict: 'EA',
- scope: {
- type: "@dropdowntype"
- },
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html',
- link: function (scope, element) {
- scope.isOpen = false;
- var currentIndex = -1;
- // Capture all the li elements after compilation
- var list = [], button = undefined;
- $timeout(function() {
- list = element.find('li');
- button = element.find('button')[0];
- }, 10);
- var toggle = scope.toggle = function (show) {
- if (angular.isUndefined(show) || show === '') {
- scope.isOpen = !scope.isOpen;
- }
- else {
- scope.isOpen = show;
- }
- };
- var selectNext = function() {
- if (currentIndex+1 < list.length) {
- currentIndex++;
- list[currentIndex].focus();
- }
- };
- var selectPrev = function() {
- if (currentIndex-1 >= 0) {
- currentIndex--;
- list[currentIndex].focus();
- }
- };
- element.bind("keydown", function($event) {
- var keyCode = $event.keyCode;
- if (keymap.isAllowedKey(keyCode) || keymap.isControl($event) || keymap.isFunctionKey($event)) {
- switch (keyCode) {
- case keymap.KEY.ENTER:
- if (currentIndex > 0) {
- button.focus();
- scope.$apply();
- }
- break;
- case keymap.KEY.ESC:
- toggle(false);
- currentIndex = -1;
- button.focus();
- scope.$apply();
- break;
- case keymap.KEY.DOWN:
- selectNext();
- scope.$apply();
- events.preventDefault($event);
- events.stopPropagation($event);
- break;
- case keymap.KEY.UP:
- selectPrev();
- scope.$apply();
- events.preventDefault($event);
- events.stopPropagation($event);
- break;
- default:
- break;
- }
- } else if (keyCode === keymap.KEY.TAB) {
- toggle(false);
- currentIndex = -1;
- scope.$apply();
- }
- });
- var outsideClick = function (e) {
- var isElement = $isElement(angular.element(e.target), element, $document);
- if (!isElement) {
- toggle(false);
- currentIndex = -1;
- for (var i = 0; i < list.length; i++) {
- angular.element(list[i]).removeClass('selected');
- }
- button.focus();
- scope.$apply();
- }
- };
- $documentBind.click('isOpen', outsideClick, scope);
- }
- };
- }]);
-angular.module('att.abs.checkbox', [])
-.constant("attCheckboxConfig", {
- activeClass : "att-checkbox--on",
- disabledClass : "att-checkbox--disabled"
-})
-.directive('checkboxLimit', function () {
-return {
- scope: {
- checkboxLimit:'=',
- selectLimit:'@?',
- maxSelected:'&?'
- },
- restrict: 'A',
- require:'checkboxLimit',
- controller: ['$scope',function($scope)
- {
- $scope.limit=true;
- this.getMaxLimits=function(){
- return $scope.limit;
- };
- this.setMaxLimits=function(value){
- $scope.limit=value;
- };
- this.maxCheckboxSelected=function(){
- $scope.maxSelected();
- };
- }],
- link: function (scope, element, attribute, ctrl) {
- scope.$watch('checkboxLimit', function()
- {
- var countTrue = 0;
- for (var keys in scope.checkboxLimit) {
- if (scope.checkboxLimit.hasOwnProperty(keys) && scope.checkboxLimit[keys]) {
- countTrue = countTrue + 1;
- }
- };
- if(countTrue>=parseInt(scope.selectLimit)){
- ctrl.setMaxLimits(false);
- }
- else{
- ctrl.setMaxLimits(true);
- }
- }, true);
- }
-};
-})
-.directive('attCheckbox', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
- return {
- scope: {},
- restrict: 'A',
- require: ['ngModel','^?checkboxLimit'],
- link: function (scope, element, attribute, ctrl) {
- var ngCtrl = ctrl[0];
- var checkboxLimitCtrl = ctrl[1];
- var parentDiv = $compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" aria-label="Checkbox" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope);
- element.css({display:'none'});
- element.wrap(parentDiv);
- element.parent().append('<div class="att-checkbox__indicator"></div>');
- element.parent().attr("title", attribute.title);
- element.parent().attr("aria-label", attribute.title);
- element.parent().attr("id", attribute.id);
- element.removeAttr("id");
- //element.removeAttr("title");
- //model -> UI
- ngCtrl.$render = function () {
- var selected = ngCtrl.$modelValue ? true : false;
- element.parent().toggleClass(attCheckboxConfig.activeClass, selected);
- element.parent().attr("aria-checked", selected);
- };
-
- //ui->model
- scope.updateModel = function (evt) {
- if (!scope.disabled) {
- ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? false : true);
- if(checkboxLimitCtrl && !(checkboxLimitCtrl.getMaxLimits())){
- if(!ngCtrl.$modelValue){
- ngCtrl.$render();
- }
- else{
- checkboxLimitCtrl.maxCheckboxSelected();
- ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? true : false);
- }
- }
- else{
- ngCtrl.$render();
- }
- }
- evt.preventDefault();
- };
-
- attribute.$observe('disabled', function(val) {
- scope.disabled = (val || val === "disabled" || val === "true");
- element.parent().toggleClass(attCheckboxConfig.disabledClass, scope.disabled);
- element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
- });
- }
- };
-}])
-.directive('checkboxGroup', ['$compile',function($compile) {
- return {
- scope:{
- checkboxGroup: "=",
- checkboxGroupValue: "=?"
- },
- restrict: 'A',
- link: function(scope, element, attribute){
- scope.checkboxState = 'none';
- if (scope.checkboxGroupValue === undefined) {
- scope.checkboxGroupValue = "indeterminate";
- }
- element.css({display:'none'});
- element.wrap($compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope));
- element.parent().append('<div class="att-checkbox__indicator"></div>');
- element.parent().attr("title", attribute.title);
- element.parent().attr("aria-label", attribute.title);
- scope.$watch('checkboxState', function(val) {
- if (val === 'all') {
- element.parent().addClass('att-checkbox--on');
- element.parent().removeClass('att-checkbox--indeterminate');
- element.parent().attr("aria-checked", true);
- }
- else if (val === 'none') {
- element.parent().removeClass('att-checkbox--on');
- element.parent().removeClass('att-checkbox--indeterminate');
- element.parent().attr("aria-checked", false);
- }
- else if (val === 'indeterminate') {
- element.parent().removeClass('att-checkbox--on');
- element.parent().addClass('att-checkbox--indeterminate');
- element.parent().attr("aria-checked", true);
- }
- });
- scope.updateModel = function(evt){
- if (element.parent().hasClass('att-checkbox--on')) {
- element.parent().removeClass('att-checkbox--on');
- for (var keys in scope.checkboxGroup) {
- if (scope.checkboxGroup.hasOwnProperty(keys)) {
- scope.checkboxGroup[keys] = false;
- }
- };
- }
- else {
- element.parent().addClass('att-checkbox--on');
- for (var key in scope.checkboxGroup) {
- if (scope.checkboxGroup.hasOwnProperty(key)) {
- scope.checkboxGroup[key] = true;
- }
- };
- }
- evt.preventDefault();
- };
- scope.$watch('checkboxGroupValue', function (value) {
- if (value===false) {
- element.parent().removeClass('att-checkbox--on');
- for (var keys in scope.checkboxGroup) {
- if (scope.checkboxGroup.hasOwnProperty(keys)) {
- scope.checkboxGroup[keys] = false;
- }
- };
- }
- else if (value === true){
- element.parent().addClass('att-checkbox--on');
- for (var key in scope.checkboxGroup) {
- if (scope.checkboxGroup.hasOwnProperty(key)) {
- scope.checkboxGroup[key] = true;
- }
- };
- }
- });
- scope.$watch('checkboxGroup', function(){
- var countTrue = 0;
- var countFalse = 0;
- var count = 0;
- for (var keys in scope.checkboxGroup) {
- if (scope.checkboxGroup.hasOwnProperty(keys)) {
- count = count + 1;
- if (scope.checkboxGroup[keys]) {
- countTrue = countTrue + 1;
- }
- else if (!scope.checkboxGroup[keys]) {
- countFalse = countFalse + 1;
- }
- }
- };
- if (count === countTrue) {
- scope.checkboxState = "all";
- scope.checkboxGroupValue=true;
- }
- else if (count === countFalse) {
- scope.checkboxState = "none";
- scope.checkboxGroupValue=false;
- }
- else {
- scope.checkboxState = "indeterminate";
- scope.checkboxGroupValue="indeterminate";
- }
- }, true);
- }
- };
-}]);
-
-angular.module('att.abs.colorselector', [])
- .directive('colorSelectorWrapper', [function() {
- return {
- scope: {
- selected: '=',
- iconColor: '@'
-
- },
- restrict: 'AE',
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/colorselector/colorselector.html',
- link: function(scope) {
- scope.applycolor = {'background-color': scope.iconColor};
- scope.selectedcolor = function(iconColor) {
- scope.selected = iconColor;
- };
- }
- };
- }])
- .directive('colorSelector', ['$compile', function($compile) {
- return{
- restrict: 'A',
- scope: {
- colorSelector: '@',
- ngModel: '='
- },
- link: function(scope, element, attr) {
- element.removeAttr('color-selector');
- var colorTitle = attr.title;
- var wrapcont = angular.element('<color-selector-wrapper selected="ngModel" title="' + colorTitle + '" icon-color="{{colorSelector}}">' + element.prop('outerHTML') + '</color-selector-wrapper>');
- var newWrapcont = $compile(wrapcont)(scope);
- element.replaceWith(newWrapcont);
- }
- };
- }]);
-angular.module('att.abs.datepicker', ['att.abs.position', 'att.abs.utilities'])
-
-.constant('datepickerConfig', {
- dateFormat: 'MM/dd/yyyy',
- dayFormat: 'd',
- monthFormat: 'MMMM',
- yearFormat: 'yyyy',
- dayHeaderFormat: 'EEEE',
- dayTitleFormat: 'MMMM yyyy',
- disableWeekend: false,
- disableSunday: false,
- startingDay: 0,
- minDate: null,
- maxDate: null,
- mode: 0,
- dateFilter: {
- defaultText: 'Select from list'
- },
- datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'mode'],
- datepickerWatchAttributes: ['min', 'max']
-})
-
-.factory('datepickerService', ['datepickerConfig', 'dateFilter', function (datepickerConfig, dateFilter) {
- var setAttributes = function (attr, elem) {
- if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
- var attributes = datepickerConfig.datepickerEvalAttributes.concat(datepickerConfig.datepickerWatchAttributes);
- for (var key in attr) {
- var val = attr[key];
- if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
- elem.attr(key.toSnakeCase(), key);
- }
- }
- }
- };
-
- var bindScope = function (attr, scope) {
- if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
- var evalFunction = function (key, val) {
- scope[key] = scope.$parent.$eval(val);
- };
-
- var watchFunction = function (key, val) {
- scope.$parent.$watch(val, function (value) {
- scope[key] = value;
- });
- scope.$watch(key, function (value) {
- scope.$parent[val] = value;
- });
- };
-
- var evalAttributes = datepickerConfig.datepickerEvalAttributes;
- var watchAttributes = datepickerConfig.datepickerWatchAttributes;
- for (var key in attr) {
- var val = attr[key];
- if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
- evalFunction(key, val);
- } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
- watchFunction(key, val);
- }
- }
- }
- };
-
- var validateDateString = function (dateString, dateFormat) {
- if (dateString && dateFormat) {
- var delimiter;
- if (dateFormat.indexOf('/') !== -1) {
- delimiter = '/';
- } else if (dateFormat.indexOf('-') !== -1) {
- delimiter = '-';
- } else if (dateFormat.indexOf('.') !== -1) {
- delimiter = '.';
- }
-
- var dateStringArray = dateString.split(delimiter);
- var dateFormatArray = dateFormat.split(delimiter);
- if (dateStringArray.length !== dateFormatArray.length) {
- return false;
- }
-
- for (var i = 0; i < dateStringArray.length; i++) {
- dateStringArray[i] = dateStringArray[i].lPad(dateFormatArray[i].length, '0');
- }
- var intermediateDateString = dateStringArray.join(delimiter);
-
- var actualDateString = dateFilter(new Date(intermediateDateString), dateFormat);
- return intermediateDateString === actualDateString;
- }
- };
-
- return {
- setAttributes: setAttributes,
- bindScope: bindScope,
- validateDateString: validateDateString
- };
-}])
-
-.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
- var format = {
- date: getValue($attrs.dateFormat, dtConfig.dateFormat),
- day: getValue($attrs.dayFormat, dtConfig.dayFormat),
- month: getValue($attrs.monthFormat, dtConfig.monthFormat),
- year: getValue($attrs.yearFormat, dtConfig.yearFormat),
- dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
- dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
- disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
- disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday)
- },
- startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
- $scope.mode = getValue($attrs.mode, dtConfig.mode);
-
- $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
- $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
-
- function getValue(value, defaultValue) {
- return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
- }
-
- function getDaysInMonth(year, month) {
- return new Date(year, month, 0).getDate();
- }
-
- function getDates(startDate, n) {
- var dates = [];
- var current = startDate, i = 0;
- while (i < n) {
- dates[i++] = new Date(current);
- current.setDate(current.getDate() + 1);
- }
- return dates;
- }
-
- var compare = this.compare = function(date1, date2) {
- return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
- };
-
- function isSelected(dt) {
- if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
- return true;
- }
- return false;
- }
-
- function isFromDate(dt) {
- if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
- return true;
- }
- return false;
- }
-
- function isToDate(dt) {
- if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
- return true;
- }
- return false;
- }
-
- function isDateRange(dt) {
- if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
- return true;
- }
- return false;
- }
-
- function isWeekend(date) {
- if (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday") {
- return true;
- }
- return false;
- }
-
- function isToday(date) {
- if (compare(date, $scope.resetTime(new Date())) === 0) {
- return true;
- }
- return false;
- }
- function isFocused(date) {
- if (date && angular.isDate($scope.focusedDate) && compare(date, $scope.focusedDate) === 0) {
- return true;
- }
- return false;
- }
-
- var isDisabled = this.isDisabled = function(date) {
- if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
- return true;
- }
- if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
- return true;
- }
- return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0));
- };
-
-
- function isMinDateAvailable(startDate, endDate) {
- return ($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime());
- }
-
- function isMaxDateAvailable(startDate, endDate) {
- return ($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime());
- }
-
- function getLabel(label) {
- if (label)
- {
- var labelObj = {
- pre: label.substr(0, 3),
- post: label
- };
- return labelObj;
- }
- return;
- }
- function makeDate(dateobj) {
- return {date: dateobj.date, label: dateFilter(dateobj.date, dateobj.formatDay), header: dateFilter(dateobj.date, dateobj.formatHeader), focused: !!dateobj.isFocused, selected: !!dateobj.isSelected, from: !!dateobj.isFromDate, to: !!dateobj.isToDate, dateRange: !!dateobj.isDateRange, oldMonth: !!dateobj.oldMonth, nextMonth: !!dateobj.newMonth, disabled: !!dateobj.isDisabled, today: !!dateobj.isToday, weekend: !!dateobj.isWeakend};
- }
-
- this.modes = [
- {
- name: 'day',
- getVisibleDates: function(date, calendar) {
- var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1), lastDayOfMonth = new Date(year, month+1, 0);
- var difference = startingDay - firstDayOfMonth.getDay(),
- numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
- firstDate = new Date(firstDayOfMonth), numDates = 0;
-
- if (numDisplayedFromPreviousMonth > 0) {
- firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
- numDates += numDisplayedFromPreviousMonth; // Previous
- }
- numDates += getDaysInMonth(year, month + 1); // Current
- numDates += (7 - numDates % 7) % 7; // Next
-
- var days = getDates(firstDate, numDates), labels = [];
- for (var i = 0; i < numDates; i++) {
- var dt = new Date(days[i]);
- days[i] = makeDate({date:dt,
- formatDay:format.day,
- formatHeader:format.dayHeader,
- isFocused:isFocused(dt),
- isSelected:isSelected(dt),
- isFromDate:isFromDate(dt),
- isToDate:isToDate(dt),
- isDateRange:isDateRange(dt),
- oldMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() < new Date(year, month, 1, 0, 0, 0).getTime()),
- newMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() > new Date(year, month, 1, 0, 0, 0).getTime()),
- isDisabled:isDisabled(dt),
- isToday:isToday(dt),
- isWeakend:isWeekend(dt)});
- }
- for (var j = 0; j < 7; j++) {
- labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
- }
- if (calendar === 'top') {
- $scope.disablePrevTop = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
- $scope.disableNextTop = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
- } else if (calendar === 'bottom') {
- $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
- $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
- } else {
- $scope.disablePrevTop = $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
- $scope.disableNextTop = $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
- }
- $scope.disablePrev = $scope.disablePrevTop || $scope.disablePrevBottom;
- $scope.disableNext = $scope.disableNextTop || $scope.disableNextBottom;
- return {objects: days, title: dateFilter(date, format.dayTitle), labels: labels};
- },
- split: 7,
- step: {months: 1}
- },
- {
- name: 'month',
- getVisibleDates: function(date) {
- var months = [], labels = [], year = date.getFullYear();
- for (var i = 0; i < 12; i++) {
- var dt = new Date(year,i,1);
- months[i] = makeDate({date:dt,
- formatDay:format.month,
- formatHeader:format.month,
- isFocused:isFocused(dt),
- isSelected:isSelected(dt),
- isFromDate:isFromDate(dt),
- isToDate:isToDate(dt),
- isDateRange:isDateRange(dt),
- oldMonth:false,
- newMonth:false,
- isDisabled:isDisabled(dt),
- isToday:isToday(dt),
- isWeakend:false});
- }
- return {objects: months, title: dateFilter(date, format.year), labels: labels};
- },
- split:3,
- step: {years: 1}
- }
- ];
-
-}])
-
-.directive('datepicker', ['$timeout', function ($timeout) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepicker.html',
- scope: {
- currentDate: "=?current",
- fromDate: "=?from"
- },
- require: 'datepicker',
- controller: 'DatepickerController',
- link: function(scope, element, attrs, ctrl) {
- var datepickerCtrl = ctrl;
- var selected, calendarSelected = false;
- scope.focusedDate;
-
- scope.resetTime = function(date) {
- var dt;
- if (!isNaN(new Date(date))) {
- dt = new Date(date);
- if(scope.mode === 1){
- dt = new Date(dt.getFullYear(), dt.getMonth());
- }else{
- dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
- }
- } else {
- return null;
- }
- return dt;
- };
-
- if (attrs.min) {
- scope.$parent.$watch(attrs.min, function(value) {
- scope.minDate = value ? scope.resetTime(value) : null;
- refill();
- });
- }
- if (attrs.max) {
- scope.$parent.$watch(attrs.max, function(value) {
- scope.maxDate = value ? scope.resetTime(value) : null;
- refill();
- });
- }
-
- // Split array into smaller arrays
- function split(arr, size) {
- var arrays = [];
- while (arr.length > 0) {
- arrays.push(arr.splice(0, size));
- }
- return arrays;
- }
- var moveMonth = function(selectedDate, direction) {
- var step = datepickerCtrl.modes[scope.mode].step;
- selectedDate.setDate(1);
- selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
- selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
-
- return selectedDate;
- };
-
- function refill(date) {
- if (angular.isDate(date) && !isNaN(date)) {
- selected = new Date(date);
- } else {
- if (!selected) {
- selected = new Date();
- }
- }
-
- if (selected) {
- var selectedCalendar;
- if(scope.mode === 1){
- selected = new Date();
- selectedCalendar = moveMonth(angular.copy(selected), -1);
- } else {
- selectedCalendar = angular.copy(selected);
- }
-
- var currentMode = datepickerCtrl.modes[scope.mode];
- var currentData = currentMode.getVisibleDates(selectedCalendar, 'top');
- scope.currentRows = split(currentData.objects, currentMode.split);
- scope.currentTitle = currentData.title;
- scope.labels = currentData.labels || [];
-
- var nextData = currentMode.getVisibleDates(moveMonth(angular.copy(selectedCalendar), 1), 'bottom');
- scope.nextRows = split(nextData.objects, currentMode.split);
- scope.nextTitle = nextData.title;
- }
- }
-
- var selectCurrentDate = function(date) {
- var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
- scope.currentDate = dt;
- };
-
- var selectFromDate = function(date) {
- var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
- scope.fromDate = dt;
- };
-
- scope.select = function(date) {
- calendarSelected = true;
- if(attrs.from) {
- if(!(angular.isDate(scope.fromDate) && angular.isDate(scope.currentDate))) {
- if(angular.isDate(scope.fromDate)) {
- selectCurrentDate(date);
- } else if(!angular.isDate(scope.fromDate)) {
- selectFromDate(date);
- }
- }
- } else {
- selectCurrentDate(date);
- }
- scope.focusedDate = date;
- };
-
- var swapDate = function(fromDate, currentDate) {
- selectFromDate(currentDate);
- $timeout(function () {
- calendarSelected = true;
- scope.focusedDate = currentDate;
- selectCurrentDate(fromDate);
- });
- };
-
- scope.move = function(direction) {
- selected = moveMonth(angular.copy(selected), direction);
- refill();
- };
-
- scope.$watch('currentDate', function (value) {
- if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
- scope.currentDate = null;
- return;
- }
-
- if (attrs.from && !isNaN(value) && !isNaN(scope.fromDate) && datepickerCtrl.compare(value, scope.fromDate) < 0) {
- swapDate(scope.fromDate, value);
- return;
- }
-
- if (calendarSelected) {
- refill();
- calendarSelected = false;
- } else {
- if (angular.isDefined(value) && value !== null) {
- refill(value);
- } else {
- refill();
- }
- }
- scope.focusedDate = undefined;
- });
-
- scope.$watch('fromDate', function (value) {
- if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
- scope.fromDate = null;
- return;
- }
- if (attrs.from) {
- if (!isNaN(scope.currentDate) && !isNaN(value) && datepickerCtrl.compare(scope.currentDate, value) < 0) {
- swapDate(value, scope.currentDate);
- return;
- }
- if (calendarSelected) {
- refill();
- calendarSelected = false;
- } else {
- if (angular.isDefined(value) && value !== null) {
- refill(value);
- } else {
- refill();
- }
- }
- }
- scope.focusedDate = undefined;
- });
- }
- };
-}])
-.directive('datepickerPopup', ['$document', 'datepickerService', '$isElement', '$documentBind', function($document, datepickerService, $isElement, $documentBind) {
- var link = function (scope, elem, attr) {
- datepickerService.bindScope(attr, scope);
-
- scope.isOpen = false;
-
- var toggle = scope.toggle = function (show) {
- if(show === true || show === false) {
- scope.isOpen = show;
- } else {
- scope.isOpen = !scope.isOpen;
- }
- };
-
- scope.$watch('current', function () {
- toggle(false);
- });
-
- var outsideClick = function (e) {
- var isElement = $isElement(angular.element(e.target), elem, $document);
- if(!isElement) {
- toggle(false);
- scope.$apply();
- }
- };
-
- $documentBind.click('isOpen', outsideClick, scope);
- };
-
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html',
- scope: {
- current: "=current"
- },
- compile: function (elem, attr) {
- var wrapperElement = elem.find('span').eq(1);
- wrapperElement.attr('current', 'current');
- datepickerService.setAttributes(attr, wrapperElement);
-
- return link;
- }
- };
-}])
-
-.directive('attDatepicker', ['$log', function($log) {
- return {
- restrict: 'A',
- require: 'ngModel',
- scope: {},
- controller: ['$scope', '$element', '$attrs', '$compile', 'datepickerConfig', 'datepickerService', function($scope, $element, $attrs, $compile, datepickerConfig, datepickerService) {
- var dateFormatString = angular.isDefined($attrs.dateFormat) ? $scope.$parent.$eval($attrs.dateFormat) : datepickerConfig.dateFormat;
- var selectedDateMessage = '<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \'' + dateFormatString + '\'}}</div>';
-
- $element.removeAttr('att-datepicker');
- $element.removeAttr('ng-model');
- $element.attr('ng-model', '$parent.current');
- $element.attr('aria-describedby', 'datepicker');
- $element.attr('format-date', dateFormatString);
- $element.attr('att-input-deny', '[^0-9\/-]');
- $element.attr('maxlength', 10);
- $element.attr('readonly', 'readonly'); //Trinity for CATO
- var wrapperElement = angular.element('<div></div>');
- wrapperElement.attr('datepicker-popup', '');
- wrapperElement.attr('current', 'current');
-
- datepickerService.setAttributes($attrs, wrapperElement);
- datepickerService.bindScope($attrs, $scope);
-
- wrapperElement.html('');
- wrapperElement.append($element.prop('outerHTML'));
- if (navigator.userAgent.match(/MSIE 8/) === null) {
- wrapperElement.append(selectedDateMessage);
- }
- var elm = wrapperElement.prop('outerHTML');
- elm = $compile(elm)($scope);
- $element.replaceWith(elm);
- }],
- link: function(scope, elem, attr, ctrl) {
- if (!ctrl) {
- // do nothing if no ng-model
- $log.error("ng-model is required.");
- return;
- }
-
- scope.$watch('current', function(value) {
- ctrl.$setViewValue(value);
- });
- ctrl.$render = function() {
- scope.current = ctrl.$viewValue;
- };
- }
- };
-}])
-
-.directive('formatDate', ['dateFilter', 'datepickerService', function(dateFilter, datepickerService) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function(scope, elem, attr, ctrl) {
- var formatDate = "";
- attr.$observe('formatDate', function (value) {
- formatDate = value;
- });
- var dateToString = function(value) {
- if (value) {
- ctrl.$setValidity('invalidDate', true);
- return dateFilter(value, formatDate);
- } else {
- ctrl.$setValidity('invalidDate', false);
- return elem.val();
- }
- };
- var stringToDate = function(value) {
- if(datepickerService.validateDateString(value, formatDate)) {
- ctrl.$setValidity('invalidDate', true);
- return new Date(value);
- } else {
- ctrl.$setValidity('invalidDate', false);
- return null;
- }
- };
- ctrl.$formatters.unshift(dateToString);
- ctrl.$parsers.unshift(stringToDate);
- }
- };
-}])
-
-.directive('attDateFilter', ['$document', 'dateFilter', 'datepickerConfig', 'datepickerService', '$isElement', '$documentBind', function($document, dateFilter, datepickerConfig, datepickerService, $isElement, $documentBind) {
-
- var link = function (scope, elem, attr, ctrl) {
- datepickerService.bindScope(attr, scope);
-
- scope.selectedOption = datepickerConfig.dateFilter.defaultText;
- scope.showDropdownList = false;
- scope.showCalendar = false;
- scope.applyButtonType = "disabled";
-
- scope.currentSelection = "";
- var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : datepickerConfig.dateFormat;
- var inputChange = false;
-
- var setDropdownText = function(value) {
- if(inputChange) {
- return;
- }
-
- var fromDateText = dateFormatString.toUpperCase();
- var currentDateText = dateFormatString.toUpperCase();
-
- if(!isNaN(new Date(scope.fromDate))) {
- fromDateText = dateFilter(scope.fromDate, dateFormatString);
- }
- if(!isNaN(new Date(scope.currentDate))) {
- currentDateText = dateFilter(scope.currentDate, dateFormatString);
- }
-
- if(value === 'Custom Single Date') {
- ctrl.$setValidity('invalidDate', true);
- scope.maxLength = 10;
- scope.selectedOption = currentDateText;
- } else if(value === 'Custom Range') {
- ctrl.$setValidity('invalidDate', true);
- ctrl.$setValidity('invalidDateRange', true);
- scope.maxLength = 21;
- scope.selectedOption = fromDateText + '-' + currentDateText;
- }
- };
-
- var clear = scope.clear = function(partial) {
- scope.fromDate = undefined;
- scope.currentDate = undefined;
- scope.applyButtonType = "disabled";
- if(!partial) {
- ctrl.$setValidity('invalidDate', true);
- ctrl.$setValidity('invalidDateRange', true);
- setDropdownText(scope.currentSelection);
- }
- };
-
- var showCalendar = function() {
- scope.showCalendar = true;
- };
-
- var hideCalendar = function() {
- scope.showCalendar = false;
- if(scope.currentSelection !== 'Custom Single Date' && scope.currentSelection !== 'Custom Range') {
- clear(true);
- }
- };
-
- var showDropdown = scope.showDropdown = function (show) {
- if(show === true || show === false) {
- scope.showDropdownList = show;
- } else {
- scope.showDropdownList = !scope.showDropdownList;
- }
-
- if (!scope.showDropdownList) {
- scope.focusInputButton = true;
- hideCalendar();
- } else {
- if (scope.currentSelection === 'Custom Single Date' || scope.currentSelection === 'Custom Range') {
- showCalendar();
- }
- }
- };
-
- scope.resetTime = function(date) {
- var dt;
- if (!isNaN(new Date(date))) {
- dt = new Date(date);
- } else {
- return null;
- }
- return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
- };
-
- scope.getDropdownText = function () {
- inputChange = true;
- var dropdownText = scope.selectedOption;
-
- if (scope.currentSelection === 'Custom Single Date') {
- if (!isNaN(new Date(dropdownText)) && datepickerService.validateDateString(dropdownText, dateFormatString)) {
- ctrl.$setValidity('invalidDate', true);
- scope.fromDate = undefined;
- scope.currentDate = new Date(dropdownText);
- } else {
- ctrl.$setValidity('invalidDate', false);
- clear(true);
- }
- } else if (scope.currentSelection === 'Custom Range') {
- if (dropdownText.indexOf('-') !== -1 && (dropdownText.split('-').length === 2 || dropdownText.split('-').length === 6)) {
- ctrl.$setValidity('invalidDateRange', true);
- var resultDropdownText = dropdownText.split('-');
- if (resultDropdownText.length === 2) {
- resultDropdownText[0] = resultDropdownText[0].trim();
- resultDropdownText[1] = resultDropdownText[1].trim();
- } else if (resultDropdownText.length === 6) {
- var firstDateString = resultDropdownText[0].trim() + '-' + resultDropdownText[1].trim() + '-' + resultDropdownText[2].trim();
- var secondDateString = resultDropdownText[3].trim() + '-' + resultDropdownText[4].trim() + '-' + resultDropdownText[5].trim();
- resultDropdownText[0] = firstDateString;
- resultDropdownText[1] = secondDateString;
- }
-
- if (!isNaN(new Date(resultDropdownText[0])) && !isNaN(new Date(resultDropdownText[1])) && datepickerService.validateDateString(resultDropdownText[0], dateFormatString) && datepickerService.validateDateString(resultDropdownText[1], dateFormatString)) {
- ctrl.$setValidity('invalidDate', true);
- var fromDate = new Date(resultDropdownText[0]);
- var currentDate = new Date(resultDropdownText[1]);
- if(fromDate.getTime() < currentDate.getTime()) {
- ctrl.$setValidity('invalidDateRange', true);
- scope.fromDate = fromDate;
- scope.currentDate = currentDate;
- } else {
- ctrl.$setValidity('invalidDateRange', false);
- clear(true);
- }
- } else {
- ctrl.$setValidity('invalidDate', false);
- clear(true);
- }
- } else {
- ctrl.$setValidity('invalidDateRange', false);
- clear(true);
- }
- }
- };
-
- scope.untrackInputChange = function() {
- inputChange = false;
- };
-
- scope.selectAdvancedOption = function (value, notClearFlag) {
- scope.currentSelection = value;
- if(!notClearFlag){
- clear();
- showCalendar();
- }
- scope.$watch('currentDate', function(val) {
- if(!isNaN(new Date(val))) {
- scope.applyButtonType = "primary";
- setDropdownText(value);
- if (!inputChange) {
- scope.focusApplyButton = true;
- }
- }
- });
- scope.$watch('fromDate', function(val) {
- if(!isNaN(new Date(val))) {
- setDropdownText(value);
- }
- });
- if (value === 'Custom Single Date') {
- scope.focusSingleDateCalendar = true;
- } else if (value === 'Custom Range') {
- scope.focusRangeCalendar = true;
- }
- };
-
- scope.resetFocus = function () {
- scope.focusSingleDateCalendar = false;
- scope.focusRangeCalendar = false;
- scope.focusApplyButton = false;
- };
-
- scope.apply = function() {
- scope.dateRange.selection = scope.selectedOption;
- if(!isNaN(new Date(scope.fromDate))) {
- scope.from = scope.fromDate;
- scope.dateRange.from = scope.fromDate;
- } else {
- scope.from = undefined;
- scope.dateRange.from = undefined;
- }
- if(!isNaN(new Date(scope.currentDate))) {
- scope.current = scope.currentDate;
- scope.dateRange.current = scope.currentDate;
- } else {
- scope.current = undefined;
- scope.dateRange.current = undefined;
- }
-
- showDropdown();
- };
-
- scope.$watchCollection(function() {
- return scope.dateRange;
- }, function(value) {
- if(ctrl) {
- var finalDateRange = angular.copy(value);
- ctrl.$setViewValue(finalDateRange);
- }
- });
-
- ctrl.$render = function () {
- if (ctrl.$viewValue) {
- var inputRange = ctrl.$viewValue;
- scope.selectedOption = inputRange.selection;
- scope.fromDate = inputRange.from;
- scope.currentDate = inputRange.current;
- if (scope.fromDate !== undefined && scope.currentDate !== undefined) {
- scope.selectAdvancedOption('Custom Range', true);
- scope.dateRange.from = scope.fromDate;
- scope.dateRange.current = scope.currentDate;
- } else if (scope.currentDate !== undefined) {
- scope.selectAdvancedOption('Custom Single Date', true);
- scope.dateRange.from = undefined;
- scope.dateRange.current = scope.currentDate;
- }
- }
- };
-
- scope.cancel = function() {
- scope.currentSelection = "";
- scope.selectedOption = datepickerConfig.dateFilter.defaultText;
- showDropdown();
- };
-
- var outsideClick = function (e) {
- var isElement = $isElement(angular.element(e.target), elem, $document);
- if(!isElement) {
- scope.cancel();
- scope.$apply();
- }
- };
- $documentBind.click('showDropdownList', outsideClick, scope);
- };
-
- return {
- restrict: 'EA',
- scope: {
- from: '=?from',
- current: "=?current"
- },
- replace: true,
- require: '?ngModel',
- transclude:true,
- templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/dateFilter.html',
- controller:['$scope', '$element', '$attrs',function($scope){
- $scope.dateRange = {
- selection: undefined,
- from: undefined,
- current: undefined
- };
- this.selectOption = function (fromDate,toDate,caption) {
- $scope.selectedOption = caption;
- $scope.currentSelection =caption;
- $scope.dateRange.selection = caption;
- $scope.dateRange.current = $scope.resetTime(toDate);
- $scope.dateRange.from = $scope.resetTime(fromDate);
- $scope.showDropdown();
- };
- $scope.checkCurrentSelection=this.checkCurrentSelection = function(value) {
- if(value === $scope.currentSelection) {
- return true;
- }
- return false;
- };
- }],
- compile: function(elem, attr) {
- var singleDateCalendar = elem.find('span').eq(4);
- var rangeCalendar = elem.find('span').eq(5);
- rangeCalendar.attr('from', 'fromDate');
- singleDateCalendar.attr('current', 'currentDate');
- rangeCalendar.attr('current', 'currentDate');
- datepickerService.setAttributes(attr, singleDateCalendar);
- datepickerService.setAttributes(attr, rangeCalendar);
-
- return link;
- }
- };
-}])
-.directive('attDateFilterList',function(){
- return{
- restrict:'EA',
- scope:{
- fromDate:'=fromDate',
- toDate:'=toDate',
- caption:'=caption',
- disabled:'=disabled'
- },
- require:'^attDateFilter',
- transclude:true,
- replace:true,
- templateUrl:'app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html',
- link:function(scope,elem,attr,ctrl){
- scope.selectOption=function(fromDate,toDate,caption){
- ctrl.selectOption(fromDate,toDate,caption);
- };
- scope.checkCurrentSelection=ctrl.checkCurrentSelection;
- }
- };
-});
-angular.module('att.abs.devNotes', [])
-
- .directive('attDevNotes', function() {
- return {
- restrict: 'EA',
- transclude: true,
- scope: {},
- controller: function($scope){
- var panes = $scope.panes = [];
- $scope.select = function(pane)
- {
- angular.forEach(panes, function(pane)
- {
- pane.selected = false;
- });
- pane.selected = true;
- };
- this.addPane = function(pane) {
- if (panes.length === 0) {
- $scope.select(pane);
- }
- panes.push(pane);
- };
- },
- template:'<div>'+
- '<ul class="tabs">' +
- '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
- '<a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a>' +
- '</li>' +
- '</ul>' +
- '<div ng-transclude></div>'+
- '</div>',
- replace: true
- };
- })
-
- .directive('pane', function() {
- return {
- require: '^attDevNotes',
- restrict: 'EA',
- transclude: true,
- scope: {
- title: '@'
- },
- link: function(scope, element, attrs, tabsCtrl) {
- tabsCtrl.addPane(scope);
- },
- template:
- '<div class="tab-pane" ng-class="{active: selected}">' +
- '<pre ng-class="{\'language-markup\':title==\'HTML\',\'language-javascript\':title==\'JavaScript\',\'language-json\':title==\'JSON\'}" class=" line-numbers">' +
- '<code ng-transclude></code>' +
- '</pre>' +
- '</div>',
- replace: true
- };
- });
-
-angular.module('att.abs.dividerLines', [])
- .directive('attDividerLines', [function()
- {
- return {
- scope: {
- attDividerLines: '@'
- },
- restrict: 'A',
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html',
- link: function(scope, element, attribute)
- {
- scope.lightContainer = attribute.attDividerLines;
- }
- };
- }]);
-
-angular.module('att.abs.dragdrop', [])
- .directive('attFileDrop', ['$parse', function($parse) {
- return {
- restrict: 'A',
- scope: {
- fileModel : '=',
- onDrop : '&',
- attFileDrop : '&'
- },
- controller: ['$scope', '$attrs', function($scope, $attrs){
- if($attrs.attFileDrop!==""){
- $scope.onDrop=$scope.attFileDrop;
- }
- this.onDrop = $scope.onDrop;
- }],
- link: function(scope, element) {
- element.addClass('dragdrop');
- element.bind(
- 'dragover',
- function(e) {
- if(e.originalEvent){
- e.dataTransfer = e.originalEvent.dataTransfer;
- }
- e.dataTransfer.dropEffect = 'move';
- // allows us to drop
- if (e.preventDefault) {
- e.preventDefault();
- }
- element.addClass('dragdrop-over');
- return false;
- }
- );
- element.bind(
- 'dragenter',
- function(e) {
- // allows us to drop
- if (e.preventDefault) {
- e.preventDefault();
- }
- element.addClass('dragdrop-over');
- return false;
- }
- );
- element.bind(
- 'dragleave',
- function() {
- element.removeClass('dragdrop-over');
- return false;
- }
- );
- element.bind(
- 'drop',
- function(e) {
- // Stops some browsers from redirecting.
- if(e.preventDefault) {
- e.preventDefault();
- }
- if (e.stopPropagation) {
- e.stopPropagation();
- }
- if(e.originalEvent){
- e.dataTransfer = e.originalEvent.dataTransfer;
- }
- element.removeClass('dragdrop-over');
- if(e.dataTransfer.files && e.dataTransfer.files.length > 0){
- scope.fileModel = e.dataTransfer.files[0];
- scope.$apply();
- if(typeof scope.onDrop === "function"){
- scope.onDrop = $parse(scope.onDrop);
- scope.onDrop();
- }
- }
- return false;
- }
- );
- }
- };
- }])
- .directive('attFileLink', [ function() {
- return {
- restrict: 'EA',
- require: '^?attFileDrop',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html',
- scope: {
- fileModel : '=?',
- onFileSelect : '&',
- attFileLink : '&'
- },
- controller: ['$scope', '$parse', function($scope, $parse){
- this.setFileModel= function(fileModel){
- if($scope.takeFileModelFromParent){
- $scope.$parent.fileModel = fileModel;
- $scope.$parent.$apply();
- }
- else{
- $scope.fileModel = fileModel;
- $scope.$apply();
- }
- };
- this.callbackFunction= function(){
- if(typeof $scope.onFileSelect === "function"){
- $scope.onFileSelect = $parse($scope.onFileSelect);
- $scope.onFileSelect();
- }
- };
-
- }],
- link: function(scope, element, attr, attFileDropCtrl) {
- scope.takeFileModelFromParent = false;
- if(!(attr.fileModel) && attFileDropCtrl){
- scope.takeFileModelFromParent = true;
- }
- if(attr.attFileLink!==""){
- scope.onFileSelect=scope.attFileLink;
- }
- else if(!(attr.onFileSelect) && attFileDropCtrl){
- scope.onFileSelect = attFileDropCtrl.onDrop;
- }
- }
- };
- }])
- .directive('attFileChange', ['$log','$rootScope',function($log,$rootScope) {
- return {
- restrict: 'A',
- require: '^attFileLink',
- link: function(scope, element, attr, attFileLinkCtrl) {
- element.bind('change',changeFileModel);
- function changeFileModel(e) {
- if (e.target.files && e.target.files.length > 0) {
- attFileLinkCtrl.setFileModel(e.target.files[0]);
- attFileLinkCtrl.callbackFunction();
- }
- else {
- var strFileName = e.target.value;
- try {
- var objFSO = new ActiveXObject("Scripting.FileSystemObject");
- attFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
- attFileLinkCtrl.callbackFunction();
- }
- catch (e) {
- var errMsg = "Error: Please follow the guidelines of Drag and Drop component on Sandbox demo page.";
- $log.error(errMsg);
- $rootScope.$broadcast('att-file-link-failure', errMsg);
- }
- }
- }
- }
- };
- }]);
-angular.module("att.abs.drawer", ['att.abs.utilities'])
-.directive('attDrawer', ['$document', '$timeout', 'DOMHelper', function ($document, $timeout, DOMHelper) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: {
- drawerOpen: "=?",
- drawerAutoClose: "&?"
- },
- template: '<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',
- link: function ($scope, element, attrs) {
- var param = {};
- // First Element in Drawer component
- var firstElement = undefined;
- // Element drawer is toggled from
- var drawerLaunchingElement = undefined;
- // Override default parameters
- param.side = attrs.drawerSlide || 'top';
- param.speed = attrs.drawerSpeed || '0.25';
- param.size = attrs.drawerSize || '300px';
- param.zindex = attrs.drawerZindex || 1000;
- param.className = attrs.drawerClass || 'att-drawer';
- var slider = element.eq(0).children()[0];
- var content = angular.element(slider).children()[0];
- slider.className = param.className;
- /* Style setup */
- slider.style.transitionDuration = param.speed + 's';
- slider.style.webkitTransitionDuration = param.speed + 's';
- slider.style.zIndex = param.zindex;
- slider.style.position = 'fixed';
- slider.style.width = 0;
- slider.style.height = 0;
- slider.style.transitionProperty = 'width, height';
- if(param.side==='right'){
- slider.style.height = attrs.drawerCustomHeight || '100%';
- slider.style.top = attrs.drawerCustomTop || '0px';
- slider.style.bottom = attrs.drawerCustomBottom || '0px';
- slider.style.right = attrs.drawerCustomRight || '0px';
- }else if(param.side==='left'){ /*Added this part for ECOM*/
- slider.style.height = attrs.drawerCustomHeight || '100%';
- slider.style.top = attrs.drawerCustomTop || '0px';
- slider.style.bottom = attrs.drawerCustomBottom || '0px';
- slider.style.left = attrs.drawerCustomRight || '0px';
- }
- else if(param.side==='top' || param.side==='bottom'){
- slider.style.width = attrs.drawerCustomWidth || '100%';
- slider.style.left = attrs.drawerCustomLeft || '0px';
- slider.style.top = attrs.drawerCustomTop || '0px';
- slider.style.right = attrs.drawerCustomRight || '0px';
- }
- $timeout(function() {
- firstElement = DOMHelper.firstTabableElement(element[0]);
- }, 10, false);
- /* Closed */
- function drawerClose(slider, param) {
- if (slider && slider.style.width !== 0 && slider.style.height !== 0){
- content.style.display = 'none';
- if(param.side==='right' || param.side==='left'){
- slider.style.width = '0px';
- }
- else if(param.side==='top' || param.side==='bottom'){
- slider.style.height = '0px';
- }
- }
- $scope.drawerOpen = false;
- // Shift focus
- if (angular.isDefined(drawerLaunchingElement) && drawerLaunchingElement != null) {
- drawerLaunchingElement.focus();
- }
- }
- /* Open */
- function drawerOpen(slider, param) {
- // Before opening drawer, find the focused element
- drawerLaunchingElement = document.activeElement;
- if (slider.style.width !== 0 && slider.style.height !== 0){
- if(param.side==='right' || param.side==='left'){
- slider.style.width = param.size;
- }
- else if(param.side==='top' || param.side==='bottom'){
- slider.style.height = param.size;
- }
- $timeout(function() {
- content.style.display = 'block';
- // Shift focus
- if (angular.isDefined(firstElement) && firstElement != null) {
- firstElement.focus();
- }
- },(param.speed * 1000));
- }
- }
- function isFunction(functionToCheck) {
- var getType = {};
- return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
- }
- /*
- * Watchers
- * */
- if(attrs.drawerSize) {
- $scope.$watch(function() {
- return attrs.drawerSize;
- }, function(newVal) {
- param.size = newVal;
- if($scope.drawerOpen) {
- drawerOpen(slider,param);
- }
- });
- }
- $scope.$watch("drawerOpen", function (value){
- if (!!value) {
- // Open
- drawerOpen(slider,param);
- } else {
- // Close
- drawerClose(slider,param);
- }
- });
- // close panel on location change
- if($scope.drawerAutoClose()) {
- $scope.$on("$locationChangeStart", function(){
- drawerClose(slider, param);
- if(isFunction($scope.drawerAutoClose())) {
- $scope.drawerAutoClose();
- }
- });
- $scope.$on("$stateChangeStart", function(){
- drawerClose(slider, param);
- if(isFunction($scope.drawerAutoClose)) {
- $scope.drawerAutoClose();
- }
- });
- }
- }
- };
- }
-]);
-angular.module('att.abs.message', [])
-
-.directive('attMessages', [function() {
- return {
- restrict: 'EA',
- scope: {
- messageType: '=?'
- },
- controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
- $scope.messageScope = [];
- this.registerScope = function(messageScope) {
- $scope.messageScope.push(messageScope);
- };
- $scope.$parent.$watchCollection($attrs['for'], function(errors) {
- for (var key in errors) {
- if (errors[key]) {
- $scope.error = key;
- break;
- } else {
- $scope.error = null;
- }
- }
- for (var i = 0; i < $scope.messageScope.length; i++) {
- if($scope.messageScope[i].when === $scope.error) {
- $scope.messageScope[i].show();
- $scope.setMessageType($scope.messageScope[i].type);
- } else {
- $scope.messageScope[i].hide();
- }
- }
- if($scope.error === null) {
- $scope.setMessageType(null);
- }
- });
- $scope.setMessageType = this.setMessageType = function(messageType) {
- if($attrs.messageType) {
- $scope.messageType = messageType;
- }
- };
- }]
- };
-}])
-
-.directive('attMessage', [function() {
- return {
- restrict: 'EA',
- scope: {},
- require: '^attMessages',
- link: function(scope, elem, attr, ctrl) {
- ctrl.registerScope(scope);
- elem.attr('role', 'alert'); //Trinity CATO
- scope.when = attr.when || attr.attMessage;
- scope.type = attr.type;
- scope.show = function() {
- elem.css({display: 'block'});
- };
- scope.hide = function() {
- elem.css({display: 'none'});
- };
- scope.hide();
- }
- };
-}]);
-
-angular.module('att.abs.formField', ['att.abs.message', 'att.abs.utilities'])
-.directive('attFormField', [function() {
- return {
- priority: 101,
- restrict: 'A',
- controller:function() {
- },
- link: function(scope, elem, attr) {
- elem.wrap('<div class="form-field"></div>');
- elem.parent().append('<label class="form-field__label">' + attr.placeholder || attr.attFormField + '</label>');
- elem.wrap('<div class="form-field-input-container"></div>');
-
- elem.bind('keyup', function() {
- if (this.value !== '') {
- elem.parent().parent().find('label').addClass('form-field__label--show').removeClass('form-field__label--hide');
- } else {
- elem.parent().parent().find('label').addClass('form-field__label--hide').removeClass('form-field__label--show');
- }
- });
-
- elem.bind('blur', function() {
- if (this.value === '') {
- elem.parent().parent().find('label').removeClass('form-field__label--hide');
- }
- });
- }
- };
-}])
-.directive('attFormFieldValidation', ['$compile', '$log', function($compile, $log) {
- return {
- priority: 102,
- scope: {},
- restrict: 'A',
- require: ['?ngModel', '?attFormField'],
- link: function(scope, elem, attr, ctrl) {
- var ngCtrl = ctrl[0];
- var attFormFieldCtrl = ctrl[1];
- scope.valid = "";
- if (!ngCtrl) {
- $log.error("att-form-field-validation :: ng-model directive is required.");
- return;
- }
- if (!attFormFieldCtrl) {
- $log.error("att-form-field-validation :: att-form-field directive is required.");
- return;
- }
-
- elem.parent().append($compile(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(scope));
- elem.parent().append($compile(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(scope));
-
- scope.$watch('valid', function(value) {
- if (value) {
- elem.parent().parent().addClass('success');
- } else if (value === false) {
- elem.parent().parent().addClass('error');
- } else {
- elem.parent().parent().removeClass('success').removeClass('error');
- }
- });
-
- elem.bind('keyup', function() {
- if (ngCtrl.$valid) {
- scope.valid = true;
- } else if (ngCtrl.$invalid) {
- scope.valid = false;
- } else {
- scope.valid = "";
- }
- scope.$apply();
- });
- }
- };
-}])
-.directive('attFormFieldValidationAlert', ['$timeout', function($timeout) {
- return {
- scope: {
- messageType: '=?'
- },
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html',
- link: function(scope, elem, attr, ctrl) {
- scope.showLabel = false;
- scope.hideLabel = false;
- scope.errorMessage = false;
- scope.warningMessage = false;
- var checkMessageType = function() {
- var messageType = scope.messageType;
- if (messageType === 'error') {
- scope.errorMessage = true;
- scope.warningMessage = false;
- } else if (messageType === 'warning') {
- scope.errorMessage = false;
- scope.warningMessage = true;
- } else {
- scope.errorMessage = false;
- scope.warningMessage = false;
- }
- };
- var oldIE = navigator.userAgent.toLowerCase().indexOf('msie 8.0') !== -1;
- elem.find('label').text(elem.find('input').attr('placeholder'));
- elem.find('input').bind('keyup', function() {
- if (this.value !== '') {
- scope.showLabel = true;
- scope.hideLabel = false;
- if (oldIE) {
- elem.find('label').css({top: '-20px'});
- }
- } else {
- scope.showLabel = false;
- scope.hideLabel = true;
- if (oldIE) {
- elem.find('label').css({top: '0px'});
- }
- }
- checkMessageType();
- scope.$apply();
- });
-
- elem.find('input').bind('blur', function() {
- if (this.value === '') {
- scope.showLabel = false;
- scope.hideLabel = false;
- }
- scope.$apply();
- });
- $timeout(function() {
- checkMessageType();
- }, 100);
- }
- };
-}])
-.constant("CoreFormsUiConfig", {
- phoneMask: '(___) ___-____'
- })
-.directive('attPhoneMask', ['$parse', 'CoreFormsUiConfig', function($parse, CoreFormsUiConfig) {
- return {
- require: 'ngModel',
- scope: {
- ngModel: '='
- },
- link: function(scope, iElement, iAttrs, ctrl) {
- var B = navigator.userAgent.toLowerCase(), C = B.indexOf("android") > -1,
- oldIE = B.indexOf('msie 8.0') !== -1;;
- var A = '';
- var validPhoneNumber = false;
- if (C) {
- A = "__________";
- }
- else {
- A = CoreFormsUiConfig.phoneMask;
- }
- iElement.attr("maxlength", A.length);
- var checkValidity = function(unmaskedValue) {
- var valid = false;
- if (unmaskedValue){
- valid = (unmaskedValue.length === 10);}
- ctrl.$setValidity('invalidPhoneNumber', validPhoneNumber);
- ctrl.$setValidity('mask', valid);
- return valid;
- };
-
- var handleKeyup = function() {
- var E,D = ctrl.$modelValue;
- if (!D.length) {
- return;
- }
- var L, K, G, J, I;
- J = [];
- G = A.split("");
- I = G.length;
- L = D.substring(0, A.length);
- K = D.replace(/[^0-9]/g, "").split("");
- for (E = 0; E < I; E++) {
- J.push(G[E] === "_" ? K.shift() : G[E]);
- if (K.length === 0) {
- break;
- }
- }
- D = J.join("");
- if (D === '('){
- D = '';}
- ctrl.$setViewValue(D);
- ctrl.$render();
- return D;
- };
-
-
- // since we are only allowing 0-9, why even let the keypress go forward?
- // also added in delete... in case they want to delete :)
- var handlePress = function(e) {
- if (e.which) {
- if ((e.which < 48 || e.which > 57) && (e.which < 96 || e.which > 105)) {
- if (e.which !== 8 && e.which !== 9 && e.which !== 46 && e.which !== 13 && e.which !== 37 && e.which !== 39 &&
- // Allow: Ctrl+V/v
- (e.ctrlKey !== true && (e.which !== '118' || e.which !== '86'))&&
- // Allow: Ctrl+C/c
- (e.ctrlKey !== true && (e.which !== '99' || e.which !== '67'))&&
- // Allow: Ctrl+X/x
- (e.ctrlKey !== true && (e.which !== '120' || e.which !== '88')))
- {
- e.preventDefault ? e.preventDefault() : e.returnValue = false;
- iElement.attr("aria-label","Only numbers are allowed");
- validPhoneNumber = false;
- }}
- else{
- iElement.removeAttr("aria-label");
- validPhoneNumber = true;
- }
- }
- scope.$apply();
- };
- // i moved this out because i thought i might need focus as well..
- // to handle setting the model as the view changes
- var parser = function(fromViewValue) {
- var letters = /^[A-Za-z]+$/;
- var numbers = /^[0-9]+$/;
- if(fromViewValue.match(letters))
- {validPhoneNumber = false;}
- if(fromViewValue.match(numbers))
- {validPhoneNumber = true;}
- var clean = "";
- if (fromViewValue && fromViewValue.length > 0) {
- clean = fromViewValue.replace(/[^0-9]/g, '');
- }
- checkValidity(clean);
- return clean;
- };
-
- //to handle reading the model and formatting it
- var formatter = function(fromModelView) {
- var input = '';
- checkValidity(fromModelView);
- if (fromModelView){
- input = handleKeyup();}
- return input;
- };
- ctrl.$parsers.push(parser);
- ctrl.$formatters.push(formatter);
- iElement.bind('keyup', handleKeyup);
- iElement.bind('keydown', handlePress);
- iElement.bind('input', function(e){
- handleKeyup(e);
- handlePress(e);
- });
- }
- };
-}])
-.constant('validationTypeInt', {
- validationNum: {'number':'1','text':'2','email':'3'}
- })
-.directive('attFormFieldPrv', [ 'keyMapAc', 'validationTypeInt', function( keyMapAc, validationTypeInt ) {
- return {
- priority: 101,
- restrict: 'AE',
- controller:['$scope', function($scope) {
- this.showHideErrorMessage = function ( booleanValue ){
- if( $scope.$$prevSibling != null && angular.isDefined( $scope.$$prevSibling )
- && angular.isDefined( $scope.$$prevSibling.hideErrorMsg ) ){
- $scope.$$prevSibling.hideErrorMsg = booleanValue;
- $scope.$apply();
- }
- };
- this.findAllowedCharactor = function( keyCode ){
- var keyMapSc = keyMapAc.keys;
- if( angular.isDefined( $scope.allowedSpecialCharacters )
- && angular.isDefined( $scope.allowedSpecialCharacters.length )
- && $scope.allowedSpecialCharacters.length > 0 ){
- var allowedCharList = $scope.allowedSpecialCharacters;
- var charFound = false;
- for( var i=0 ; i < allowedCharList.length ; i++){
- if( allowedCharList[i] === keyMapSc[keyCode] ){
- charFound = true;
- break;
- }
- }
- return charFound;
- }else{
- return false;
- }
- };
- this.validateText = function( validationType, allowedChars, validationInput, outputSpecialChars ){
- if( angular.isDefined( allowedChars ) && allowedChars.length === 0 ){
- var expAlphanumeric = /^[a-zA-Z0-9]*$/i;
- return expAlphanumeric.test( validationInput );
- }else{
- var expAlphanumericSpecialChar = '^[a-zA-Z0-9' + outputSpecialChars + ']*$';
- var regularExp = new RegExp( expAlphanumericSpecialChar, 'i' );
- return regularExp.test( validationInput );
- }
- };
- this.validateNumber = function( validationType, allowedChars, validationInput, outputSpecialChars ){
- if( angular.isDefined( allowedChars ) && allowedChars.length === 0 ){
- var expNumber = /^[0-9\.]+$/;
- return expNumber.test( validationInput );
- }else{
- var expNumberSpecial = '^[0-9\.' + outputSpecialChars + ']*$';
- var regularExp = new RegExp( expNumberSpecial, 'i' );
- return regularExp.test( validationInput );
- }
- };
- this.validateEmail = function( validationType, allowedChars, validationInput, outputSpecialChars ){
- if( angular.isDefined( allowedChars ) && allowedChars.length === 0 ){
- var expEmail = /(([a-zA-Z0-9\-?\.?]+)@(([a-zA-Z0-9\-_]+\.)+)([a-z]{2,3}))+$/;
- return expEmail.test( validationInput );
- }else{
- var expEmailSpecial = '(([a-z' + outputSpecialChars + 'A-Z0-9\-?\.?]+)@(([a-z'
- + outputSpecialChars + 'A-Z0-9\-_]+\.)+)([' + outputSpecialChars + 'a-z]{2,3}))+$';
- var regularExp = new RegExp( expEmailSpecial, 'i' );
- return regularExp.test( validationInput );
- }
- };
- this.validateInput = function( validationType, allowedChars, validationInput ){
- var outputSpecialChars = '';
- var result = false;
- if( angular.isDefined( allowedChars ) && angular.isDefined( allowedChars.length )
- && allowedChars.length > 0 ){
- for( var i = 0; i < allowedChars.length; i++){
- outputSpecialChars += '\\'+allowedChars[i];
- }
- }
- switch ( validationTypeInt.validationNum[ validationType ] ) {
- case validationTypeInt.validationNum["text"]:
- result = this.validateText( validationType, allowedChars, validationInput, outputSpecialChars );
- break;
- case validationTypeInt.validationNum["number"]:
- result = this.validateNumber( validationType, allowedChars, validationInput, outputSpecialChars );
- break;
- case validationTypeInt.validationNum["email"]:
- result = this.validateEmail( validationType, allowedChars, validationInput, outputSpecialChars );
- break;
- default:
- break;
- }
- return result;
- };
- }],
- link: function(scope, elem, attr ) {
- elem.parent().prepend('<label class="form-field__label">' + attr.placeholder + '</label>');
- elem.wrap('<div class="form-field-input-container"></div>');
- elem.parent().parent().find('label').addClass('form-field__label--show');
- }
- };
-}])
-.directive('attFormFieldValidationPrv', [ 'keyMapAc','validationTypeInt' , function( keyMapAc, validationTypeInt ) {
- return {
- priority: 202,
- scope: {
- validationType: '=',
- allowedChars: '='
- },
- restrict: 'A',
- require: ['?ngModel', '^attFormFieldPrv'],
- link: function(scope, elem, attr, ctrl) {
- var attFormFieldCtrl = ctrl[1];
- elem.bind('keyup', function() {
- /* email validation has tobe done on keyup */
- if( attFormFieldCtrl.validateInput( scope.validationType, scope.allowedChars, elem[0].value ) ){
- attFormFieldCtrl.showHideErrorMessage(false);
- }
- else{
- attFormFieldCtrl.showHideErrorMessage(true);
- }
- });
- var keyMapSc = keyMapAc.keyRange;
- var allowedKeys = keyMapAc.allowedKeys;
- var validateTextCode = function( charFound,event ){
- var resultOne = (event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] );
- var resultTwo = (event.which < keyMapSc['startCapitalLetters'] || event.which > keyMapSc['endCapitalLetters'] );
- var resultThree = (event.which < keyMapSc['startSmallLetters'] || event.which > keyMapSc['endSmallLetters'] );
- var result = ( resultOne && resultTwo && resultThree );
- return ( result && ( !charFound ) );
- };
- var validateNumberCode = function( charFound,event ){
- return ( ( event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] ) && ( !charFound ) );
- };
- var validateEmailCode = function( charFound,event ){
- var condOne = String.fromCharCode( event.which ) !== '-' && String.fromCharCode( event.which ) !== '_';
- var condTwo = String.fromCharCode( event.which ) !== '@' && String.fromCharCode( event.which ) !== '.';
- var ifAllowedChars = condOne && condTwo;
- var ifCharRange = validateTextCode( charFound,event );
- return ( ( !charFound ) && ifAllowedChars && ifCharRange );
- };
- var validateSwitch = function( validationTypeSwitch, charFound, event ){
- switch ( validationTypeSwitch ) {
- case validationTypeInt.validationNum["text"]:
- /* 97-122 65-90 48-57 if keyCode is outside range of alphanumeric chars and not found in list then prevent */
- if( validateTextCode( charFound, event ) ){
- return true;
- }
- break;
- case validationTypeInt.validationNum["number"]:
- /* if key code is outside number range and notfound then prevent */
- if( validateNumberCode( charFound, event ) ){
- return true;
- }
- break;
- case validationTypeInt.validationNum["email"]:
- /* if keyCode is outside charactor/number range and not _-@. then prevent */
- if( validateEmailCode( charFound, event ) ){
- return true;
- }
- break;
- default:
- break;
- }
- return false;
- };
- /* key stroke prevention has to be happen on numeric and alphanumeric fields */
- elem.bind('keypress', function( event ){
- if(!(event.which)){
- if(event.keyCode){
- event.which = event.keyCode;
- }
- else if(event.charCode){
- event.which = event.charCode;
- }
- }
- var charFound = attFormFieldCtrl.findAllowedCharactor( event.which );
- var insideCondOne = ( angular.isDefined( scope.validationType ) && scope.validationType !== '');
- var insideCondTwo = ( event.which !== allowedKeys['TAB']
- && event.which !== allowedKeys['BACKSPACE'] && event.which!== allowedKeys['DELETE'] );
- var goInside = insideCondOne && insideCondTwo;
- if( goInside && validateSwitch( validationTypeInt.validationNum[ scope.validationType ], charFound, event ) ){
- event.preventDefault();
- }
- });
- }
- };
-}])
-.directive('attFormFieldValidationAlertPrv', [ function() {
- return {
- restrict: 'A',
- scope : { errorMessage : '=' },
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html',
- link: function( scope ) {
- scope.errorMessage = scope.errorMessage;
- if( angular.isDefined( scope.$parent.hideErrorMsg ) ){
- scope.hideErrorMsg = scope.$parent.hideErrorMsg;
- }
- else{
- scope.hideErrorMsg = true;
- }
- }
- };
-}])
-//Credit card validation directives starts here
-.factory('Cards', [function() {
- var defaultFormat = /(\d{1,4})/g;
- var defaultInputFormat = /(?:^|\s)(\d{4})$/;
- var cards = [
- {
- type: 'discover',
- pattern: /^(6011|65|64[4-9]|622)/,
- format: defaultFormat,
- inputFormat: defaultInputFormat,
- length: [16],
- cvcLength: [3],
- cvcSecurityImg: 'visaI',
- zipLength: [5],
- luhn: true
- },
- {
- type: 'mc',
- pattern: /^5[1-5]/,
- format: defaultFormat,
- inputFormat: defaultInputFormat,
- length: [16],
- cvcLength: [3],
- cvcSecurityImg: 'visaI',
- zipLength: [5],
- luhn: true
- },
- {
- type: 'amex',
- pattern: /^3[47]/,
- format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
- inputFormat: /^(\d{4}|\d{4}\s\d{6})$/,
- length: [15],
- cvcLength: [4],
- cvcSecurityImg: 'amexI',
- zipLength: [5],
- luhn: true
- },
- {
- type: 'visa',
- pattern: /^4/,
- format: defaultFormat,
- inputFormat: defaultInputFormat,
- length: [16],
- cvcLength: [3],
- cvcSecurityImg: 'visaI',
- zipLength: [5],
- luhn: true
- }
- ];
-
- var _fromNumber = function(num) {
- var card, i, len;
-
- num = (num + '').replace(/\D/g, '');
-
- for (i = 0, len = cards.length; i < len; i++) {
-
- card = cards[i];
-
- if (card.pattern.test(num)) {
- return card;
- }
-
- }
- };
-
- var _fromType = function(type) {
- var card, i, len;
-
- for (i = 0, len = cards.length; i < len; i++) {
-
- card = cards[i];
-
- if (card.type === type) {
- return card;
- }
-
- }
- };
-
- return {
- fromNumber: function(val) {
- return _fromNumber(val);
- },
- fromType: function(val) {
- return _fromType(val);
- },
- defaultFormat: function() {
- return defaultFormat;
- },
- defaultInputFormat: function() {
- return defaultInputFormat;
- }
- };
-
- }])
-.factory('_Validate', ['Cards', '$parse', function(Cards, $parse) {
- var __indexOf = [].indexOf || function(item)
- {
- for (var i = 0, l = this.length; i < l; i++)
- {
- if (i in this && this[i] === item)
- {
- return i;
- }
- }
- return -1;
- };
-
- var _luhnCheck = function(num) {
- var digit, digits, odd, sum, i, len;
-
- odd = true;
- sum = 0;
- digits = (num + '').split('').reverse();
-
- for (i = 0, len = digits.length; i < len; i++) {
-
- digit = digits[i];
- digit = parseInt(digit, 10);
-
- if ((odd = !odd)) {
- digit *= 2;
- }
-
- if (digit > 9) {
- digit -= 9;
- }
-
- sum += digit;
-
- }
-
- return sum % 10 === 0;
- };
-
- var _validators = {};
-
- _validators['cvc'] = function(cvc, ctrl, scope, attr) {
- var ref, ref1;
-
- // valid if empty - let ng-required handle empty
- if ((angular.isUndefined(cvc)) || (cvc === null) || (cvc.length === 0))
- {
- return true;
- }
-
- if (!/^\d+$/.test(cvc)) {
- return false;
- }
-
- var type;
- if (attr.paymentsTypeModel) {
- var typeModel = $parse(attr.paymentsTypeModel);
- type = typeModel(scope);
- }
-
- if (type)
- {
- ref1 = Cards.fromType(type);
- return (ref = cvc.length, __indexOf.call((ref1 !== null) ? ref1.cvcLength : void 0, ref)) >= 0;
- }
- else
- {
- return cvc.length >= 3 && cvc.length <= 4;
- }
- };
- _validators['zip'] = function(zip, ctrl, scope, attr) {
- var ref, ref1;
-
- // valid if empty - let ng-required handle empty
- if ((angular.isUndefined(zip)) || (zip === null) || (zip.length === 0))
- {
- return true;
- }
-
- if (!/^\d+$/.test(zip)) {
- return false;
- }
-
- var type;
- if (attr.paymentsTypeModel) {
- var typeModel = $parse(attr.paymentsTypeModel);
- type = typeModel(scope);
- }
- if (type)
- {
- ref1 = Cards.fromType(type);
- return (ref = zip.length, __indexOf.call(ref1 !== null ? ref1.zipLength : void 0, ref)) >= 0;
- }
- else
- {
- return zip.length < 6;
- }
- };
- _validators['card'] = function(num, ctrl, scope, attr) {
- var card, ref, typeModel;
-
- if (attr.paymentsTypeModel) {
- typeModel = $parse(attr.paymentsTypeModel);
- }
-
- var clearCard = function() {
- if (typeModel) {
- typeModel.assign(scope, null);
- }
- ctrl.$card = null;
- };
-
- // valid if empty - let ng-required handle empty
- if ((angular.isUndefined(num)) || (num === null) || (num.length === 0)) {
- clearCard();
- return true;
- }
-
- num = (num + '').replace(/\s+|-/g, '');
-
- if (!/^\d+$/.test(num)) {
- clearCard();
- return false;
- }
-
- card = Cards.fromNumber(num);
- if (!card) {
- clearCard();
- return false;
- }
- ctrl.$card = angular.copy(card);
-
- if (typeModel) {
- typeModel.assign(scope, card.type);
- }
-
- ret = (ref = num.length, __indexOf.call(card.length, ref) >= 0) && (card.luhn === false || _luhnCheck(num));
- return ret;
- };
- return function(type, val, ctrl, scope, attr) {
- if (!_validators[type]) {
-
- types = Object.keys(_validators);
-
- errstr = 'Unknown type for validation: "' + type + '". ';
- errstr += 'Should be one of: "' + types.join('", "') + '"';
-
- throw errstr;
- }
- return _validators[type](val, ctrl, scope, attr);
- };
- }])
-.factory('_ValidateWatch', ['_Validate', function(_Validate) {
-
- var _validatorWatches = {};
-
- _validatorWatches['cvc'] = function(type, ctrl, scope, attr) {
- if (attr.paymentsTypeModel) {
- scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
- if (newVal !== oldVal) {
- var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
- ctrl.$setValidity(type, valid);
- }
- });
- }
- };
- _validatorWatches['zip'] = function(type, ctrl, scope, attr) {
- if (attr.paymentsTypeModel) {
- scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
- if (newVal !== oldVal) {
- var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
- ctrl.$setValidity(type, valid);
- }
- });
- }
- };
- return function(type, ctrl, scope, attr) {
- if (_validatorWatches[type]) {
- return _validatorWatches[type](type, ctrl, scope, attr);
- }
- };
- }])
-.directive('validateCard', ['$window', '_Validate', '_ValidateWatch', function($window, _Validate, _ValidateWatch) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function(scope, elem, attr, ctrl) {
-
- var type = attr.validateCard;
- _ValidateWatch(type, ctrl, scope, attr);
- var validateFn = function(val) {
- var valid = _Validate(type, val, ctrl, scope, attr);
- ctrl.$setValidity(type, valid);
- if (type === 'card')
- {
- if (ctrl.$card === null)
- {
- if ((val == null) || (val === "") || (val === ''))
- {
- scope.invalidCardError = '';
- scope.invalidCard = "";
- }
- else if (val.length >= 1)
- {
- scope.invalidCardError = 'error';
- scope.invalidCard = "The number entered is not a recognized credit card number.";
- }
- }
- else
- {
- if (!valid)
- {
- if (ctrl.$card.length.indexOf(val.length) >= 0)
- {
- scope.invalidCardError = 'error';
- scope.invalidCard = "The number entered is not a recognized credit card number.";
- }
- else
- {
- scope.invalidCardError = '';
- scope.invalidCard = "";
- }
- }
- else
- {
- scope.invalidCardError = '';
- scope.invalidCard = "";
- }
- }
- elem.bind("blur", function()
- {
- if ((!valid) || (ctrl.$card === null))
- {
- scope.invalidCardError = 'error';
- scope.invalidCard = "The number entered is not a recognized credit card number.";
- }
- else
- {
- scope.invalidCardError = '';
- scope.invalidCard = "";
- }
- });
- }
- return valid ? val : undefined;
- };
- ctrl.$formatters.push(validateFn);
- ctrl.$parsers.push(validateFn);
- }
- };
- }])
-.directive('creditCardImage', function() {
- return{
- templateUrl: 'app/scripts/ng_js_att_tpls/formField/creditCardImage.html',
- replace: false,
- transclude: false,
- link: function(scope, element, attr)
- {
- scope.$watch(attr.creditCardImage, function(newVal, oldVal)
- {
- if (newVal !== oldVal)
- {
- scope.cvc = '';
- if (!angular.isUndefined(newVal) && newVal !== null)
- {
- scope.newValCCI = 'show-' + newVal;
- }
- if (newVal === null)
- {
- scope.newValCCI = '';
- }
- }
- });
- }
- };
-})
-.directive('securityCodeImage', ['$document', function($document) {
- return{
- templateUrl: 'app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html',
- replace: false,
- transclude: false,
- link: function(scope, element, attr)
- {
- scope.$watch(attr.securityCodeImage, function(newVal, oldVal)
- {
- if (newVal !== oldVal)
- {
- if (!angular.isUndefined(newVal) && newVal !== null)
- {
- if (newVal === 'amexI')
- {
- scope.newValI = 'ccv2-security-amex';
- scope.newValIAlt = "The 4 digit CVC security code is on the front of the card.";
- scope.cvcPlaceholder = "4 digits";
- scope.cvcMaxlength = 4;
- }
- else if (newVal === 'visaI')
- {
- scope.newValI = 'ccv2-security';
- scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
- scope.cvcPlaceholder = "3 digits";
- scope.cvcMaxlength = 3;
- }
- }
- if (newVal === null)
- {
- scope.newValI = 'ccv2-security';
- scope.cvcPlaceholder = "3 digits";
- scope.cvcMaxlength = 3;
- scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
- }
-
- }
- });
- element.bind("click", function(ev) {
- ev.preventDefault();
- if (element.find("button").hasClass("active")) {
- element.find("button").removeClass("active");
- }
- else {
- element.find("button").addClass("active");
- }
- });
-
- var window = angular.element($document);
- window.bind("click", function(ev) {
- var targetClassname = ev.target.className;
- if ((targetClassname !== "btn btn-alt btn-tooltip active")) {
- if (element.find("button").hasClass("active")) {
- element.find("button").removeClass("active");
- }
- }
-
- });
- }
- };
- }]);
-
-angular.module('att.abs.hourpicker', ['att.abs.utilities'])
- .constant('hourpickerConfig', {
- days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
- customOption: 'Custom'
- })
-
-.controller('hourPickerController', ['$scope', function ($scope) {
-
- $scope.options = [];
- this.setOptions = function (value, fromtime, totime, preselect, uncheckedFromTime, uncheckedToTime) {
- $scope.options.push(value);
-
- if (preselect !== undefined) {
- $scope.preselect = preselect;
- }
-
- var daycount;
-
- if (fromtime !== undefined) {
- $scope.fromtime = fromtime;
- for (daycount in $scope.days) {
- if ($scope.days.hasOwnProperty(daycount)) {
- $scope.FrtimeList[$scope.days[daycount]] = {};
- if (uncheckedFromTime !== undefined) {
- $scope.FrtimeList[$scope.days[daycount]].value = uncheckedFromTime;
- $scope.selectedFromOption[$scope.days[daycount]] = uncheckedFromTime;
- } else {
- $scope.FrtimeList[$scope.days[daycount]].value = fromtime[0].value;
- $scope.selectedFromOption[$scope.days[daycount]] = fromtime[0].value;
- }
- }
- }
- }
- if (totime !== undefined) {
- $scope.totime = totime;
- for (daycount in $scope.days) {
- if ($scope.days.hasOwnProperty(daycount)) {
- $scope.TotimeList[$scope.days[daycount]] = {};
- if (uncheckedToTime !== undefined) {
- $scope.TotimeList[$scope.days[daycount]].value = uncheckedToTime;
- $scope.selectedToOption[$scope.days[daycount]] = uncheckedToTime;
- } else {
- $scope.TotimeList[$scope.days[daycount]].value = totime[0].value;
- $scope.selectedToOption[$scope.days[daycount]] = totime[0].value;
- }
- $scope.showToTimeErrorDay[$scope.days[daycount]] = false;
- }
- }
- }
-
- if (uncheckedFromTime !== undefined) {
- $scope.uncheckedFromTime = uncheckedFromTime;
- }
- if (uncheckedToTime !== undefined) {
- $scope.uncheckedToTime = uncheckedToTime;
- }
- };
-
- this.getSelectedOption = function () {
- return $scope.selectedOption;
- };
-
- this.setToTimeErrorDay = function (day, flag) {
- $scope.showToTimeErrorDay[day] = flag;
- };
-}])
-
-.directive('attHourpickerOption', [function () {
- return {
- restrict: 'EA',
- require: '^attHourpicker',
- scope: {
- option: "=option",
- fromtime: "=fromtime",
- totime: "=totime",
- preselect: "=preselect",
- uncheckedFromTime: "=",
- uncheckedToTime: "="
- },
- link: function (scope, element, attr, ctrl) {
- ctrl.setOptions(scope.option,
- scope.fromtime,
- scope.totime,
- scope.preselect,
- scope.uncheckedFromTime,
- scope.uncheckedToTime);
- }
- };
-}])
-
-.directive('attHourpicker', ["hourpickerConfig", "$document", "$log", "$documentBind", "$timeout", function (hourpickerConfig, $document, $log, $documentBind, $timeout) {
- return {
- require: 'ngModel',
- restrict: 'EA',
- controller: 'hourPickerController',
- transclude: true,
- scope: {
- model: "=ngModel",
- resetFlag: "=?"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html',
- link: function (scope, element, attr, ctrl) {
- var flag = false;
- scope.isFromDropDownOpen = false;
- scope.isToDropDownOpen = false;
- var dropDownOpenValue = "";
- var custTime = {};
- scope.days = hourpickerConfig.days;
- scope.daysList = {};
- scope.FrtimeList = {};
- scope.FrtimeListDay = {};
- scope.TotimeListDay = {};
- scope.selectedFromOption = {};
- scope.selectedToOption = {};
- scope.TotimeList = {};
- scope.selectedIndex = 0;
- scope.selectedOption = "Select from list";
- scope.customTime = [];
-
- scope.resetFlag = false;
- scope.showToTimeErrorDay = {};
- scope.validatedCustomPreselect = [];
-
- scope.$watch('resetFlag', function (newVal, oldVal) {
- if (newVal !== oldVal) {
- if (newVal && scope.selectedOption === hourpickerConfig.customOption) {
- //disable and reset all days checkbox
- for (day in scope.daysList) {
- if (scope.daysList.hasOwnProperty(day)) {
- scope.daysList[day] = false;
- scope.addSelectedValue(day);
- }
- }
- scope.preselectUpdateFxn(scope.preselect);
- }
- scope.resetFlag = false;
- }
- });
-
- scope.$watch('selCategory', function (value) {
- if (value) {
- ctrl.$setViewValue(value);
- }
- }, true);
-
- scope.updateData = function (value) {
- if (value.constructor === Array) {
- scope.showDaysSelector = true;
- scope.selectedOption = hourpickerConfig.customOption;
- for (var arry in value) {
- if (value.hasOwnProperty(arry)) {
- var day = value[arry].day;
-
- if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
- scope.daysList[day] = true;
- } else {
- scope.daysList[day] = false;
- }
-
- for (var fromcount in scope.fromtime) {
- if (scope.fromtime[fromcount].value === value[arry].FromTime && !scope.uncheckedFromTime) {
- scope.FrtimeList[day].value = scope.fromtime[fromcount].value;
- scope.selectedFromOption[day] = scope.FrtimeList[day].value;
- }
- }
- for (var tocount in scope.totime) {
- if (scope.totime[tocount].value === value[arry].ToTime && !scope.uncheckedToTime) {
- scope.TotimeList[day].value = scope.totime[tocount].value;
- scope.selectedToOption[day] = scope.TotimeList[day].value;
- }
- }
-
- scope.addSelectedValue(day, value[arry].FromTime, value[arry].ToTime);
-
- //for IE8 Fix
- if (parseInt(arry) + 1 === value.length) {
- break;
- }
- }
- }
- } else {
- scope.selectOption(value.day);
- }
- };
-
- scope.$watch('preselect', function (value) {
- scope.preselectUpdateFxn(value);
- });
-
- scope.preselectUpdateFxn = function (value) {
- if (value !== undefined) {
- if (scope.options) {
- value = scope.validatePreselectData(value);
- }
- if (value === "") {
- return;
- }
- scope.updateData(value);
- }
- };
-
- scope.validatePreselectData = function (value) {
- if (value.constructor === Array) {
- for (var arry in value) {
- if (value.hasOwnProperty(arry)) {
- var day = value[arry].day;
- var isDayFound = false;
- var isFrmFound = false;
- var isToFound = false;
- for (var daycount in scope.days) {
- if (scope.days[daycount] === day) {
- isDayFound = true;
- break;
- }
- }
- if (!isDayFound) {
- value.splice(arry, 1);
- continue;
- }
- for (var fromcount in scope.fromtime) {
- if (scope.fromtime[fromcount].value === value[arry].FromTime) {
- isFrmFound = true;
- break;
- }
- }
- if (!isFrmFound) {
- value[arry].FromTime = scope.fromtime[0].value;
- }
- for (var tocount in scope.totime) {
- if (scope.totime[tocount].value === value[arry].ToTime) {
- isToFound = true;
- break;
- }
- }
- if (!isToFound) {
- value[arry].ToTime = scope.totime[0].value;
- }
-
- if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
- value[arry].preEnabled = true;
- } else {
- value[arry].preEnabled = false;
- }
-
- scope.validatedCustomPreselect[day] = {};
- scope.validatedCustomPreselect[day].FromTime = value[arry].FromTime;
- scope.validatedCustomPreselect[day].ToTime = value[arry].ToTime;
-
- //for IE8 Fix
- if (parseInt(arry) + 1 === value.length) {
- break;
- }
- }
- }
- } else {
- var isOptionFound = false;
- for (var optcount in scope.options) {
- if (scope.options[optcount] === value.day) {
- isOptionFound = true;
- break;
- }
- }
- if (!isOptionFound) {
- value = "";
- }
- }
- return value;
- };
-
- scope.selectPrevNextValue = function ($event, arrayValues, currValue) {
-
- var value;
- var index = 0;
- if ($event.keyCode === 38) {
- value = -1;
- } else if ($event.keyCode === 40) {
- value = 1;
- } else {
- return currValue;
- }
-
- if (arrayValues.indexOf(currValue) !== -1) {
- index = arrayValues.indexOf(currValue) + value;
- } else {
- for (var count in arrayValues) {
- if (arrayValues[count].value === currValue) {
- index = parseInt(count) + value;
- break;
- }
- }
- }
-
- if (index === arrayValues.length) {
- index = index - 1;
- } else if (index === -1) {
- index = index + 1;
- }
-
- $event.preventDefault();
- if (arrayValues[index].value) {
- return arrayValues[index].value;
- } else {
- return arrayValues[index];
- }
- };
-
- scope.showDropdown = function () {
- scope.showlist = !scope.showlist;
- flag = !flag;
- };
-
- scope.showfromDayDropdown = function (value) {
- //close dropdown if any other From drop down is opened
- for (count in scope.FrtimeListDay) {
- if (count !== value && scope.FrtimeListDay[count]) {
- scope.FrtimeListDay[count] = false;
- }
- }
- for (count in scope.TotimeListDay) {
- if (scope.TotimeListDay[count]) {
- scope.TotimeListDay[count] = false;
- }
- }
- scope.FrtimeListDay[value] = !scope.FrtimeListDay[value];
- flag = !flag;
- scope.showlist = false;
-
- //save model value so we can close current dropdown on click of other part of the document
- if (scope.FrtimeListDay[value]) {
- scope.isFromDropDownOpen = true;
- dropDownOpenValue = value;
- } else {
- scope.isFromDropDownOpen = false;
- }
-
- $timeout(function () {
- if (scope.FrtimeListDay[value]) {
- var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
- var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
- var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
- angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
- }
- });
- };
-
- scope.showtoDayDropdown = function (value) {
- //close dropdown if any other To drop down is opened
- for (count in scope.TotimeListDay) {
- if (count !== value && scope.TotimeListDay[count]) {
- scope.TotimeListDay[count] = false;
- }
- }
- for (count in scope.FrtimeListDay) {
- if (scope.FrtimeListDay[count]) {
- scope.FrtimeListDay[count] = false;
- }
- }
- scope.TotimeListDay[value] = !scope.TotimeListDay[value];
- flag = !flag;
- scope.showlist = false;
-
- //save model value so we can close current dropdown on click of other part of the document
- if (scope.TotimeListDay[value]) {
- scope.isToDropDownOpen = true;
- dropDownOpenValue = value;
-
- } else {
- scope.isToDropDownOpen = false;
- }
-
- $timeout(function () {
- if (scope.TotimeListDay[value]) {
- var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
- var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
- var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
- angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
- }
- });
- };
-
- scope.selectFromDayOption = function (day, value) {
- scope.selectedFromOption[day] = value;
- scope.FrtimeList[day].value = value;
- scope.FrtimeListDay[day] = false;
- scope.isFromDropDownOpen = false;
- };
-
- scope.selectToDayOption = function (day, value) {
- scope.selectedToOption[day] = value;
- scope.TotimeList[day].value = value;
- scope.TotimeListDay[day] = false;
- scope.isToDropDownOpen = false;
- };
-
- scope.addSelectedValue = function (value, fromtime, totime) {
- var count, len;
- if (scope.daysList[value] !== undefined && !scope.daysList[value]) {
- for (count = 0, len = scope.customTime.length; count < len; count++) {
- if (scope.customTime[count].day === value) {
- if (scope.uncheckedFromTime) {
- scope.selectedFromOption[scope.customTime[count].day] = scope.uncheckedFromTime;
- } else {
- scope.selectedFromOption[scope.customTime[count].day] = scope.FrtimeList[scope.customTime[count].day].value;
- }
-
- if (scope.uncheckedToTime) {
- scope.selectedToOption[scope.customTime[count].day] = scope.uncheckedToTime;
- } else {
- scope.selectedToOption[scope.customTime[count].day] = scope.TotimeList[scope.customTime[count].day].value;
- }
-
- scope.customTime.splice(count, 1);
- break;
- }
- }
- } else {
- if (scope.selectedFromOption[value] === scope.uncheckedFromTime) {
-
- if (angular.isDefined(scope.validatedCustomPreselect[value])) {
- scope.selectedFromOption[value] = scope.validatedCustomPreselect[value].FromTime;
- fromtime = scope.validatedCustomPreselect[value].FromTime;
- scope.FrtimeList[value].value = scope.validatedCustomPreselect[value].FromTime;
- } else {
- scope.selectedFromOption[value] = scope.fromtime[0].value;
- fromtime = scope.fromtime[0].value;
- scope.FrtimeList[value].value = scope.fromtime[0].value;
- }
-
- }
-
- if (scope.selectedToOption[value] === scope.uncheckedToTime) {
-
- if (angular.isDefined(scope.validatedCustomPreselect[value])) {
- scope.selectedToOption[value] = scope.validatedCustomPreselect[value].ToTime;
- totime = scope.validatedCustomPreselect[value].ToTime;
- scope.TotimeList[value].value = scope.validatedCustomPreselect[value].ToTime;
- } else {
- scope.selectedToOption[value] = scope.totime[0].value;
- totime = scope.totime[0].value;
- scope.TotimeList[value].value = scope.totime[0].value;
- }
- }
-
- custTime["day"] = value;
- custTime["FromTime"] = scope.FrtimeList[value].value;
- custTime["ToTime"] = scope.TotimeList[value].value;
-
- for (count = 0, len = scope.customTime.length; count < len; count++) {
- if (scope.customTime[count].day === value) {
- scope.customTime[count].FromTime = custTime["FromTime"];
- scope.customTime[count].ToTime = custTime["ToTime"];
- break;
- }
- }
- if (count === len) {
- var x = angular.copy(custTime);
- scope.customTime.push(x);
- }
- }
- scope.selCategory = scope.customTime;
- };
-
-
- var outsideClick = function () {
- if (scope.showlist) {
- scope.$apply(function () {
- scope.showlist = false;
- });
- }
- };
-
- $documentBind.click('showlist', outsideClick, scope);
-
- var outsideClickFromDropdown = function () {
- scope.$apply(function () {
- if (scope.isFromDropDownOpen) {
- scope.FrtimeListDay[dropDownOpenValue] = false;
- scope.isFromDropDownOpen = false;
- }
- });
- };
-
- $documentBind.click('isFromDropDownOpen', outsideClickFromDropdown, scope);
-
- var outsideClickToDropdown = function () {
- scope.$apply(function () {
- if (scope.isToDropDownOpen) {
- scope.TotimeListDay[dropDownOpenValue] = false;
- scope.isToDropDownOpen = false;
- }
- });
- };
-
- $documentBind.click('isToDropDownOpen', outsideClickToDropdown, scope);
-
- scope.selectOption = function (sItem) {
-
- if (sItem === hourpickerConfig.customOption) {
- scope.showDaysSelector = true;
- scope.selCategory = scope.customTime;
- } else {
- scope.showDaysSelector = false;
- var fromTime = /[0-9]\s?am/i.exec(sItem);
- var toTime = /[0-9]\s?pm/i.exec(sItem);
- scope.selCategory = {
- day: sItem,
- FromTime: fromTime === null ? 'NA' : fromTime[0],
- ToTime: toTime === null ? 'NA' : toTime[0]
- };
- }
-
- scope.showlist = false;
- flag = false;
- scope.selectedOption = sItem;
- };
- }
- };
-}])
-
-.directive('attHourpickerValidator', ['hourpickerConfig', function (hourpickerConfig) {
- return {
- restrict: 'A',
- require: ['attHourpicker', 'ngModel'],
- link: function (scope, element, attr, ctrl) {
-
- var attHourpickerCtrl = ctrl[0];
- var ngModelCtrl = ctrl[1];
-
- //required format [h:MM tt] like '1:10 PM'
- var convertTimeStrngToMilitaryFormat = function (time) {
- var hours = Number(time.match(/^(\d+)/)[1]);
- var minutes = Number(time.match(/:(\d+)/)[1]);
- var AMPM = (time.match(/\s(.*)$/)[1]).toUpperCase();
- if (AMPM === 'PM' && hours < 12) {
- hours = hours + 12;
- }
- if (AMPM === 'AM' && hours === 12) {
- hours = hours - 12;
- }
- var sHours = hours.toString();
- var sMinutes = minutes.toString();
- if (hours < 10) {
- sHours = '0' + sHours;
- }
- if (minutes < 10) {
- sMinutes = '0' + sMinutes;
- }
- return parseInt(sHours + sMinutes, 10);
- };
-
- var compareTimeStrings = function (fromTimeString, toTimeString) {
- var fromMilitaryTime = convertTimeStrngToMilitaryFormat(fromTimeString);
- var toMilitaryTime = convertTimeStrngToMilitaryFormat(toTimeString);
- return (toMilitaryTime - fromMilitaryTime);
- };
-
- var validateCustomData = function (finalDataModal) {
-
- if (attHourpickerCtrl.getSelectedOption() === hourpickerConfig.customOption) {
-
- var errorDaysCount = 0;
-
- for (var item in finalDataModal) {
- if (finalDataModal.hasOwnProperty(item)) {
- if (compareTimeStrings(finalDataModal[item].FromTime, finalDataModal[item].ToTime) <= 0) {
- attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, true);
- errorDaysCount++;
- } else {
- attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, false);
- }
- }
- }
-
- if (errorDaysCount > 0) {
- //validation error
- ngModelCtrl.$setValidity('validationStatus', false);
- return [];
- } else {
- //validation successful
- ngModelCtrl.$setValidity('validationStatus', true);
- return finalDataModal;
- }
- } else {
- //default case no validation
- ngModelCtrl.$setValidity('validationStatus', true);
- return finalDataModal;
- }
-
- };
-
- ngModelCtrl.$parsers.unshift(validateCustomData);
- }
- };
-}]);
-angular.module('att.abs.iconButtons', [])
- .constant('buttonConfig', {
- activeClass: 'active--button',
- toggleEvent: 'click'
- })
- .directive('attIconBtnRadio', ['buttonConfig', function(buttonConfig) {
- var activeClass = buttonConfig.activeClass || 'active--button';
- var toggleEvent = buttonConfig.toggleEvent || 'click';
- return {
- require: 'ngModel',
- link: function(scope, element, attrs, ngModelCtrl) {
- element.attr("tabindex","0");
- element.append("<span class='hidden-spoken'>"+attrs.attIconBtnRadio+"</span>");
- //model -> UI
- ngModelCtrl.$render = function() {
- element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio));
- };
- //ui->model
- element.parent().bind(toggleEvent, function() {
- if (!element.parent().hasClass(activeClass)) {
- scope.$apply(function() {
- ngModelCtrl.$setViewValue(attrs.attIconBtnRadio);
- ngModelCtrl.$render();
- });
- }
- });
- }
- };
- }])
- .directive('attIconBtnCheckbox', ['buttonConfig', function(buttonConfig) {
- var activeClass = buttonConfig.activeClass || 'active--button';
- var toggleEvent = buttonConfig.toggleEvent || 'click';
- return {
- require: 'ngModel',
- link: function(scope, element, attrs, ngModelCtrl) {
- element.attr("tabindex","0");
- element.append("<span class='hidden-spoken'>"+attrs.attIconBtnCheckbox+"</span>");
- function getTrueValue() {
- var trueValue = scope.$eval(attrs.btnCheckboxTrue);
- return angular.isDefined(trueValue) ? trueValue : true;
- }
- function getFalseValue() {
- var falseValue = scope.$eval(attrs.btnCheckboxFalse);
- return angular.isDefined(falseValue) ? falseValue : false;
- }
- //model -> UI
- ngModelCtrl.$render = function() {
- element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
- };
- //ui->model
- element.parent().bind(toggleEvent, function() {
- scope.$apply(function() {
- ngModelCtrl.$setViewValue(element.parent().hasClass(activeClass) ? getFalseValue() : getTrueValue());
- ngModelCtrl.$render();
- });
- });
- }
- };
- }]);
-
-angular.module('att.abs.links', ['ngSanitize'])
- .directive('attLink', [function() {
- return {
- restrict: 'A',
- link: function(scope, elem) {
- elem.addClass('link');
- if(!(elem.attr('href'))){
- elem.attr("tabindex", "0");
- }
- }
- };
- }])
- .directive('attLinkVisited', [function() {
- return {
- restrict: 'A',
- link: function(scope, elem) {
- elem.addClass('link--visited');
- if(!(elem.attr('href'))){
- elem.attr("tabindex", "0");
- }
- }
- };
- }])
- .directive('attReadmore', ['$timeout',function($timeout) {
- return {
- restrict: 'A',
- scope: {
- lines:"@noOfLines",
- textModel: "=",
- //attribute to use readmore inside accordion
- isOpen: "="
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/links/readMore.html',
- link: function(scope, elem) {
- var height = 1;
- scope.$watch('textModel', function(val){
- if(!val){
- scope.textToDisplay = '';
- scope.readMoreLink = false;
- scope.readLessLink = false;
- scope.readFlag = false;
- }
- else{
- if (typeof String.prototype.trim !== 'function') {
- String.prototype.trim = function() {
- return this.replace(/^\s+|\s+$/g, '');
- };
- }
- scope.textToDisplay = val.trim();
- scope.readFlag = true;
- $timeout(function() {
- var readElem = elem[0].children[0].children[0];
- if(height===1){
- if(window.getComputedStyle){
- height = parseInt(scope.lines) * parseFloat(window.getComputedStyle(readElem,null).getPropertyValue("height"));
- }
- else {
- height = parseInt(scope.lines) * parseFloat(readElem.currentStyle.height);
- }
- scope.elemHeight = height;
- scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
- }
- });
- scope.readMoreLink = true;
- scope.readLessLink = false;
- }
- });
- // Code to use readmore inside accordion
- var parentElem = elem.parent();
- if (parentElem.hasClass('att-accordion__body')) {
- scope.$watch('isOpen', function(val) {
- if (!val) {
- scope.readMoreLink = true;
- scope.readLessLink = false;
- scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
- scope.readFlag = true;
- }
- });
- }
- scope.readMore = function() {
- scope.readMoreLink = false;
- scope.readLessLink = true;
- scope.readLinkStyle = {'height': 'auto'};
- scope.readFlag = false;
- var moreLink = angular.element(elem).children().eq(1).find('a')[0];
- $timeout(function()
- {
- moreLink.focus();
- });
- };
- scope.readLess = function() {
- scope.readMoreLink = true;
- scope.readLessLink = false;
- scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
- scope.readFlag = true;
- var readLessLink = angular.element(elem).children().eq(0).find('a')[0];
- $timeout(function()
- {
- readLessLink.focus();
- });
- };
- }
- };
- }])
- .directive('attLinksList', [function() {
- return {
- restrict: 'A',
- controller: function() {
- },
- link: function(scope, elem) {
- elem.addClass('links-list');
- }
- };
- }])
- .directive('attLinksListItem', [function() {
- return {
- restrict: 'A',
- require: '^attLinksList',
- link: function(scope, elem) {
- elem.addClass('links-list__item');
- if(!(elem.attr('href'))){
- elem.attr("tabindex", "0");
- }
- }
- };
- }]);
-angular.module('att.abs.loading', [])
- .directive('attLoading', ['$window',function($window) {
- return {
- restrict: 'A',
- replace: true,
- scope: {
- icon: '@attLoading',
- progressStatus: '=?',
- colorClass: '=?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/loading/loading.html',
- link: function(scope, element) {
- var progressvalue = scope.progressStatus;
- scope.progressStatus = Math.min(100, Math.max(0, progressvalue));
- if($window.navigator.userAgent.indexOf("MSIE 8.")!==-1){
- var shiftX = 0, shiftY = scope.progressStatus * 36;
- element.css({
- 'background-position-x' : shiftX,
- 'background-position-y' : -shiftY
- });
- }
- }
- };
- }]);
-angular.module('att.abs.modal', ['att.abs.utilities'])
-/**
- * A helper, internal data structure that acts as a map but also allows getting / removing
- * elements in the LIFO order
- */
- .factory('$$stackedMap', function () {
- return {
- createNew: function () {
- var stack = [];
-
- return {
- add: function (key, value) {
- stack.push({
- key: key,
- value: value
- });
- },
- get: function (key) {
- for (var i = 0; i < stack.length; i++) {
- if (key === stack[i].key) {
- return stack[i];
- }
- }
- },
- keys: function() {
- var keys = [];
- for (var i = 0; i < stack.length; i++) {
- keys.push(stack[i].key);
- }
- return keys;
- },
- top: function () {
- return stack[stack.length - 1];
- },
- remove: function (key) {
- var idx = -1;
- for (var i = 0; i < stack.length; i++) {
- if (key === stack[i].key) {
- idx = i;
- break;
- }
- }
- return stack.splice(idx, 1)[0];
- },
- removeTop: function () {
- return stack.splice(stack.length - 1, 1)[0];
- },
- length: function () {
- return stack.length;
- }
- };
- }
- };
- })
-
-/**
- * A helper directive for the $modal service. It creates a backdrop element.
- */
- .directive('modalBackdrop', ['$timeout', function ($timeout) {
- return {
- restrict: 'EA',
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/modal/backdrop.html',
- link: function (scope) {
- scope.animate = false;
- //trigger CSS transitions
- $timeout(function () {
- scope.animate = true;
- });
- }
- };
- }])
-
- .directive('modalWindow', ['$modalStack','$timeout','$document', function ($modalStack,$timeout,$document) {
- return {
- restrict: 'EA',
- scope: {
- index: '@',
- modalTitle: '@?'
- },
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/modal/window.html',
- link: function (scope, element, attrs) {
- scope.windowClass = attrs.windowClass || '';
- if (attrs['modalTitle'] && attrs['modalTitle']!=="") {
- element[0].setAttribute('aria-label', attrs['modalTitle']);
- element[0].removeAttribute('modal-title');
- }
- $timeout(function () {
- // trigger CSS transitions
- scope.focusModalFlag = true;
- scope.animate = true;
- });
- $document.on('focus keydown', function(e){
- if (e.which ===9) {
- String.prototype.contains = function(it) {
- return this.indexOf(it) !== -1;
- };
- if (element[0] !== e.target && !element[0].contains( e.target )) {
- element[0].focus();
- }
- }
- });
- scope.close = function (evt) {
- var modal = $modalStack.getTop();
- if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
- // Check if preventDefault exists due to lack of support for IE8
- if (evt.preventDefault) {
- evt.preventDefault();
- evt.stopPropagation();
- } else {
- evt.returnValue = false;
- }
- $modalStack.dismiss(modal.key, 'backdrop click');
- }
- };
- }
- };
- }])
-
- .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', 'events', 'keymap',
- function ($document, $compile, $rootScope, $$stackedMap, events, keymap) {
- var OPENED_MODAL_CLASS = 'modal-open';
- var backdropjqLiteEl, backdropDomEl;
- var backdropScope = $rootScope.$new(true);
- var openedWindows = $$stackedMap.createNew();
- var $modalStack = {};
- var modalLaunchingElement = undefined;
- function backdropIndex() {
- var topBackdropIndex = -1;
- var opened = openedWindows.keys();
- for (var i = 0; i < opened.length; i++) {
- if (openedWindows.get(opened[i]).value.backdrop) {
- topBackdropIndex = i;
- }
- }
- return topBackdropIndex;
- }
-
- $rootScope.$watch(backdropIndex, function(newBackdropIndex){
- backdropScope.index = newBackdropIndex;
- });
-
- function removeModalWindow(modalInstance) {
-
- var body = $document.find('body').eq(0);
- var html = $document.find('html').eq(0);
- var modalWindow = openedWindows.get(modalInstance).value;
- //clean up the stack
- openedWindows.remove(modalInstance);
- ////remove window DOM element
- modalWindow.modalDomEl.remove();
- body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
- html.css({overflow: 'scroll'});
-
- //remove backdrop if no longer needed
- if (backdropDomEl && backdropIndex() == -1) {
- backdropDomEl.remove();
- backdropDomEl = undefined;
- }
- //destroy scope
- modalWindow.modalScope.$destroy();
-
- // Shift focus
- if (angular.isDefined(modalLaunchingElement) && modalLaunchingElement != null) {
- modalLaunchingElement.focus();
- }
- }
- $document.bind('keydown', function (evt) {
- var modal;
- if (evt.which === 27) {
- modal = openedWindows.top();
- if (modal && modal.value.keyboard) {
- $rootScope.$apply(function () {
- $modalStack.dismiss(modal.key);
- });
- }
- } else if (evt.keyCode === keymap.KEY.BACKSPACE) {
- var doPrevent = false;
- var d = evt.srcElement || evt.target;
- var type;
- if (d.type === undefined) {
- doPrevent = true;
- } else if (d.tagName.toUpperCase() === 'INPUT' &&
- ( (type = d.type.toUpperCase()) === 'TEXT' ||
- type === 'PASSWORD' ||
- type === 'FILE' ||
- type === 'SEARCH' ||
- type === 'EMAIL' ||
- type === 'NUMBER' ||
- type === 'DATE' ||
- type === 'TEL' ||
- type === 'URL' ||
- type === 'TIME')
- || d.tagName.toUpperCase() === 'TEXTAREA') {
- doPrevent = d.readOnly || d.disabled;
- } else {
- doPrevent = true;
- }
- if (doPrevent) {
- events.preventDefault(evt);
- }
- }
- });
-
- $modalStack.open = function (modalInstance, modal) {
- openedWindows.add(modalInstance, {
- deferred: modal.deferred,
- modalScope: modal.scope,
- backdrop: modal.backdrop,
- keyboard: modal.keyboard
- });
-
- //Before opening modal, find the focused element
- modalLaunchingElement = document.activeElement;
-
- var body = $document.find('body').eq(0);
- var html = $document.find('html').eq(0);
-
- if (backdropIndex() >= 0 && !backdropDomEl) {
- backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
- backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
- body.append(backdropDomEl);
- }
- var angularDomEl = angular.element('<div modal-window></div>');
- angularDomEl.attr('window-class', modal.windowClass);
- angularDomEl.attr('index', openedWindows.length() - 1);
- angularDomEl.attr('modal-title', modal.modalTitle);
- angularDomEl.html(modal.content);
-
- var modalDomEl = $compile(angularDomEl)(modal.scope);
- openedWindows.top().value.modalDomEl = modalDomEl;
- body.append(modalDomEl);
- body.addClass(OPENED_MODAL_CLASS);
- html.css({overflow: 'hidden'});
- };
-
- $modalStack.close = function (modalInstance, result) {
- var modal = openedWindows.get(modalInstance);
- if (modal) {
- modal.value.deferred.resolve(result);
- removeModalWindow(modalInstance);
- }
- };
-
- $modalStack.dismiss = function (modalInstance, reason) {
- var modalWindow = openedWindows.get(modalInstance).value;
- if (modalWindow) {
- modalWindow.deferred.reject(reason);
- removeModalWindow(modalInstance);
- }
- };
-
- $modalStack.getTop = function () {
- return openedWindows.top();
- };
-
- return $modalStack;
- }])
-
- .provider('$modal', function () {
-
- var $modalProvider = {
- options: {
- //can be also false or 'static'
- backdrop: true,
- keyboard: true
- },
- $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
- function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
- var $modal = {};
- function getTemplatePromise(options) {
- return options.template ? $q.when(options.template) :
- $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
- return result.data;
- });
- }
-
- function getResolvePromises(resolves) {
- var promisesArr = [];
- angular.forEach(resolves, function (value) {
- if (angular.isFunction(value) || angular.isArray(value)) {
- promisesArr.push($q.when($injector.invoke(value)));
- }
- });
- return promisesArr;
- }
- $modal.open = function (modalOptions) {
- var modalResultDeferred = $q.defer();
- var modalOpenedDeferred = $q.defer();
-
- //prepare an instance of a modal to be injected into controllers and returned to a caller
- var modalInstance = {
- result: modalResultDeferred.promise,
- opened: modalOpenedDeferred.promise,
- close: function (result) {
- $modalStack.close(modalInstance, result);
- },
- dismiss: function (reason) {
- $modalStack.dismiss(modalInstance, reason);
- }
- };
- //merge and clean up options
- modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
- modalOptions.resolve = modalOptions.resolve || {};
-
- //verify options
- if (!modalOptions.template && !modalOptions.templateUrl) {
- throw new Error('One of template or templateUrl options is required.');
- }
-
- var templateAndResolvePromise =
- $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
- templateAndResolvePromise.then(function(tplAndVars) {
- var modalScope = (modalOptions.scope || $rootScope).$new();
- modalScope.$close = modalInstance.close;
- modalScope.$dismiss = modalInstance.dismiss;
-
- var ctrlInstance, ctrlLocals = {};
- var resolveIter = 1;
-
- //controllers
- if (modalOptions.controller) {
- ctrlLocals.$scope = modalScope;
- ctrlLocals.$modalInstance = modalInstance;
- angular.forEach(modalOptions.resolve, function (value, key) {
- ctrlLocals[key] = tplAndVars[resolveIter++];
- });
-
- ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
- }
-
- $modalStack.open(modalInstance, {
- scope: modalScope,
- deferred: modalResultDeferred,
- content: tplAndVars[0],
- backdrop: modalOptions.backdrop,
- keyboard: modalOptions.keyboard,
- windowClass: modalOptions.windowClass,
- modalTitle: modalOptions.modalTitle
- });
-
- }, function(reason) {
- modalResultDeferred.reject(reason);
- });
-
- templateAndResolvePromise.then(function () {
- modalOpenedDeferred.resolve(true);
- }, function () {
- modalOpenedDeferred.reject(false);
- });
-
- return modalInstance;
- };
-
- return $modal;
- }]
- };
-
- return $modalProvider;
- })
-
-.directive("simpleModal", ["$modal", function($modal) {
- return {
- restrict: 'EA',
- scope: {
- simpleModal: '@',
- backdrop:'@',
- keyboard:'@',
- modalOk:'&',
- modalCancel:'&',
- windowClass:'@',
- controller:'@',
- modalTitle: '@?'
- },
- link: function(scope, elm) {
- elm.bind('click', function(ev) {
- ev.preventDefault();
- if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
- scope.simpleModal = elm.attr("href");
- }
-
- scope.backdrop === "false" ? scope.backdropclick = 'static' : scope.backdropclick = true;
- scope.keyboard === "false" ? scope.keyboardev = false : scope.keyboardev = true;
-
- $modal.open({
- templateUrl: scope.simpleModal,
- backdrop:scope.backdropclick,
- keyboard:scope.keyboardev,
- windowClass:scope.windowClass,
- controller: scope.controller,
- modalTitle: scope.modalTitle
- }).result.then(scope.modalOk, scope.modalCancel);
- });
- }
- };
- }])
-
-.directive('tabbedItem', ['$modal', '$log',function ($modal, $log){
- return {
- restrict: 'AE',
- replace: true,
- scope: {
- items: "=items",
- controller: "@",
- templateId:"@",
- modalTitle: '@?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedItem.html',
- controller: ['$scope', '$rootScope', '$attrs', function ($scope) {
- $scope.clickTab = function (index) {
- for (var i = 0; i < $scope.items.length; i++) {
- if (i === index) {
- $scope.items[i].isTabOpen = true;
- $scope.items[i].showData = true;
- }
- else {
- $scope.items[i].isTabOpen = false;
- $scope.items[i].showData = false;
- }
- }
- var modalInstance = $modal.open({
- templateUrl: $scope.templateId,
- controller: $scope.controller,
- windowClass: 'tabbedOverlay_modal',
- modalTitle: $scope.modalTitle,
- resolve: {
- items: function () {
- return $scope.items;
- }
- }
- });
- modalInstance.result.then(function (selectedItem) {
- $scope.selected = selectedItem;
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
- };
- $scope.isActiveTab = function (index) {
- return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
- };
- }]
- };
-}])
-
-.directive('tabbedOverlay', [function () {
- return {
- restrict: 'AE',
- replace: true,
- scope: {
- items: "="
- },
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html',
- controller: ['$scope', function ($scope) {
- $scope.clickTab = function (index) {
- for (var i = 0; i < $scope.items.length; i++) {
- if (i === index) {
- $scope.items[i].isTabOpen = true;
- $scope.items[i].showData = true;
- }
- else {
- $scope.items[i].isTabOpen = false;
- $scope.items[i].showData = false;
- }
- }
- };
- $scope.isActiveTab = function (index) {
- return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
- };
- }]
- };
-}]);
-angular.module('att.abs.pagination', ['att.abs.utilities'])
-.directive('attPagination', [ function() {
- return {
- restrict: 'EA',
- scope: {
- totalPages: '=',
- currentPage: '=',
- showInput: '=',
- clickHandler: '=?'
- },
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/pagination/pagination.html',
- link: function(scope) {
- scope.focusedPage;
- scope.$watch('totalPages', function(value) {
- if(angular.isDefined(value) && value !== null){
- scope.pages = [];
- if (value < 1) {
- scope.totalPages = 1;
- return;
- }
- if (value <= 7) {
- for (var i = 1; i <= value; i++) {
- scope.pages.push(i);
- }
- } else if (value > 7) {
- var midVal = Math.ceil(value / 2);
- scope.pages = [midVal - 1, midVal, midVal + 1];
- }
- currentPageChanged(1);
- }
- });
- scope.$watch('currentPage', function(value) {
- currentPageChanged(value);
- });
- var callbackHandler = function(num) {
- if (angular.isFunction(scope.clickHandler)){
- scope.clickHandler(num);
- }
- };
- function currentPageChanged(value) {
- if (angular.isDefined(value) && value !== null) {
- if (!value || value < 1) {
- value = 1;
- }
- if (value > scope.totalPages) {
- value = scope.totalPages;
- }
- if(scope.currentPage !== value) {
- scope.currentPage = value;
- callbackHandler(scope.currentPage);
- }
- if (scope.totalPages > 7) {
- if (value < scope.pages[0] && value > 3) {
- scope.pages = [value, value + 1, value + 2];
- } else if (value > scope.pages[2] && value < scope.totalPages - 2) {
- scope.pages = [value - 2, value - 1, value];
- } else if (value <= 3) {
- scope.pages = [1, 2, 3];
- } else if (value >= scope.totalPages - 2) {
- scope.pages = [scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
- }
- }
- }
- }
- scope.next = function(event) {
- event.preventDefault();
- if (scope.currentPage < scope.totalPages) {
- scope.currentPage += 1;
- callbackHandler(scope.currentPage);
- }
- };
- scope.prev = function(event) {
- event.preventDefault();
- if (scope.currentPage > 1) {
- scope.currentPage -= 1;
- callbackHandler(scope.currentPage);
- }
- };
- scope.selectPage = function(value, event) {
- event.preventDefault();
- scope.currentPage = value;
- scope.focusedPage = value;
- callbackHandler(scope.currentPage);
- };
- scope.checkSelectedPage = function(value) {
- if(scope.currentPage === value) {
- return true;
- }
- return false;
- };
- scope.isFocused = function(page) {
- return scope.focusedPage === page;
- };
- }
- };
-}]);
-
-angular.module('att.abs.paneSelector',['att.abs.utilities'])
-.constant('paneGroupConstants',{
- SIDE_WIDTH_DEFAULT: '33%',
- INNER_PANE_DEFAULT: '67%',
- SIDE_PANE_ID: 'sidePane',
- NO_DRILL_DOWN: 'none'
-})
-.factory('animation', function(){
- return TweenLite;
-}).directive('attPaneAccessibility',['keymap','$window',function(keymap,$window) {
- return{
- restrict: 'A',
- require: ['^?sidePane','^?innerPane'],
- link: function (scope, elem,attr,ctrl) {
- var sidepaneCtrl = ctrl[0],innerPaneCtrl = ctrl[1],ieFlag=false;
- scope.ie = (function () {
- var undef,v = 3,div = document.createElement('div'),
- all = div.getElementsByTagName('i');
- while (
- div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i>< ![endif]-->',
- all[0]
- );
- return v > 4 ? v : undef;
- }());
- if(scope.ie === 8){
- ieFlag = true;
- }
- else{
- ieFlag = false;
- }
- elem.bind('keydown',function(ev){
- if (keymap.isAllowedKey(ev.keyCode) || keymap.isControl(ev) || keymap.isFunctionKey(ev)) {
- ev.preventDefault();
- ev.stopPropagation();
- var el;
- switch (ev.keyCode) {
- case keymap.KEY.DOWN:
- el = angular.element(elem[0])[0];
- if(el && el.nextElementSibling){
- el.nextElementSibling.focus();
- }
- /*IE8 fix*/
- if(ieFlag){
- do {
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'DIV');
- el.focus();
- }
- break;
- case keymap.KEY.UP:
- el = angular.element(elem[0])[0];
- if(el && el.previousElementSibling){
- el.previousElementSibling.focus();
- }
- /*IE8 fix*/
- if(ieFlag){
- do {
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'DIV');
- el.focus();
- }
- break;
- case keymap.KEY.RIGHT:
- if(angular.isDefined(sidepaneCtrl)){
- el = sidepaneCtrl.getElement()[0];
- }
- if(angular.isDefined(innerPaneCtrl)){
- el = innerPaneCtrl.getElement()[0];
- }
- do {
- if (el && el.nextElementSibling){
- el = el.nextElementSibling;
- }
- else{
- break;
- }
- }while(window.getComputedStyle(el, null).getPropertyValue("display") === 'none');
- /*IE8 fix*/
- if(ieFlag){
- do {
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- }while ((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');
- }
- if (el){
- el.querySelector("[att-pane-accessibility]").focus();
- }
- break;
- case keymap.KEY.LEFT:
- if(angular.isDefined(sidepaneCtrl)){
- el = sidepaneCtrl.getElement()[0];
- }
- if(angular.isDefined(innerPaneCtrl)){
- el = innerPaneCtrl.getElement()[0];
- }
- do {
- if (el && el.previousElementSibling){
- el = el.previousElementSibling;
- }
- else{
- break;
- }
- }while (window.getComputedStyle(el, null).getPropertyValue("display") == 'none');
-
- /*IE8 fix*/
- if(ieFlag){
- do {
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- }while((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');
- }
- if (el){
- el.querySelector("[att-pane-accessibility]").focus();
- }
- break;
- default:
- break;
- }
- }
- });
- }
- };
-}])
-.directive('sideRow', [function(){
- return {
- restrict: 'A',
- replace:true,
- require: ['^sidePane','^paneGroup'],
- link: function(scope,element,attr,ctrls){
- var sidePaneCtrl = ctrls[0];
- var paneGroupCtrl = ctrls[1];
- if(scope.$first){
- /*
- Reset the sidePaneId array if a new
- set of ngRepeat data appeared
- */
- sidePaneCtrl.sidePaneIds = [];
- }
- var paneId =attr['paneId'];
- var drillDownTo = attr['drillDownTo'];
- sidePaneCtrl.sidePaneRows.push({'paneId':paneId, 'drillDownTo':drillDownTo});
- element.on('click', function(){
- sidePaneCtrl.currentSelectedRowPaneId = paneId;
- paneGroupCtrl.slideOutPane(paneId,true);
- });
- }
- };
-}])
-.controller('SidePaneCtrl',['$scope', '$element','animation', 'paneGroupConstants',
- function($scope,$element,animation, paneGroupConstants){
- this.getElement = function(){
- return $element;
- };
- this.sidePaneTracker = {};
- this.currentWidth = paneGroupConstants.SIDE_WIDTH_DEFAULT;
- this.paneId = paneGroupConstants.SIDE_PANE_ID;
- this.currentSelectedRowPaneId;
- this.drillDownToMapper = {};
- this.sidePaneRows = [];
- this.init = function(){
- var sidePaneRows = this.sidePaneRows;
- if(sidePaneRows){
- for(var index in sidePaneRows){
- if (sidePaneRows.hasOwnProperty(index)) {
- var paneId = sidePaneRows[index].paneId;
- var drillDownTo = sidePaneRows[index].drillDownTo;
- this.drillDownToMapper[paneId] = drillDownTo;
- if(index == 0){
- this.currentSelectedRowPaneId = paneId;
- this.sidePaneTracker[paneId] = [];
- }
- }
- }
- }
- };
- this.getSidePanesList = function(){
- return this.sidePaneTracker[this.currentSelectedRowPaneId];
- };
- this.addToSidePanesList = function(newPaneId){
- if(this.sidePaneTracker[this.currentSelectedRowPaneId] === undefined){
- this.sidePaneTracker[this.currentSelectedRowPaneId] = [];
- }
- else if(newPaneId){
- this.sidePaneTracker[this.currentSelectedRowPaneId].push(newPaneId);
- }
- };
- this.setWidth = function(val){
- if(val){
- this.currentWidth = val;
- }
- animation.set($element,{width:this.currentWidth});
- };
- this.resizeWidth = function(val){
- if(val){
- this.currentWidth = val;
- }
- animation.to($element,.5,{width:val});
- };
-
-}])
-.directive('sidePane', ['paneGroupConstants', function(paneGroupConstants){
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/sidePane.html',
- require: ['^paneGroup', 'sidePane'],
- controller: 'SidePaneCtrl',
- scope:{},
- link: function(scope,element,attr, ctrls){
- var paneGroupCtrl = ctrls[0];
- var sidePaneCtrl = ctrls[1];
- paneGroupCtrl.addPaneCtrl(paneGroupConstants.SIDE_PANE_ID, sidePaneCtrl);
- }
- };
-}])
-.directive('drillDownRow', ['$parse', 'paneGroupConstants',function($parse,paneGroupConstants){
- return {
- restrict: 'A',
- replace:true,
- require: ['^innerPane','^paneGroup'],
- link: function(scope,element,attr,ctrls){
- var innerPaneCtrl = ctrls[0];
- var paneGroupCtrl = ctrls[1];
- element.on('click', function(){
- var drillDownTo = innerPaneCtrl.drillDownTo;
- if(innerPaneCtrl.drillDownTo !== paneGroupConstants.NO_DRILL_DOWN){
- paneGroupCtrl.slideOutPane(drillDownTo);
- }
- element[0].focus();
- });
- }
- };
-}])
-.controller('InnerPaneCtrl', ['$scope', '$element','animation', 'paneGroupConstants',
- function($scope,$element,animation,paneGroupConstants){
- this.getElement = function(){
- return $element;
- };
- this.paneId = $scope.paneId;
- this.drillDownTo;
- this.currentWidth = paneGroupConstants.INNER_PANE_DEFAULT;
- this.setWidth = function(val){
- if(val){
- this.currentWidth = val;
- }
- animation.set($element,{width:this.currentWidth});
- };
- this.resizeWidth = function(val,callback){
- animation.to($element,.25,{width:val,onComplete: callback});
- };
- this.displayNone = function(){
- animation.set($element, {display:'none'});
- };
- this.displayBlock = function(){
- animation.set($element,{display:'block'});
- if(this){
- this.hideRightBorder();
- }
- };
- this.floatLeft = function(){
- animation.set($element,{float:'left'});
- };
- this.hideLeftBorder = function(){
- animation.set($element, {borderLeftWidth: '0px'});
- };
- this.showLeftBorder = function(){
- animation.set($element,{borderLeftWidth: '1px'});
- };
- this.hideRightBorder = function(){
- animation.set($element,{borderRightWidth: '0px'});
- };
- this.showRightBorder = function(){
- animation.set($element, {borderRightWidth: '1px'});
- };
- this.slideFromRight = function(){
- animation.set($element, {float:'right'});
- animation.set($element, {width: this.currentWidth});
- };
- this.startOpen = function(){
- return $scope.startOpen;
- };
-}])
-.directive('innerPane', function(){
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/innerPane.html',
- require: ['^paneGroup', 'innerPane'],
- controller: 'InnerPaneCtrl',
- scope:{
- paneId:'@'
- },
- link: function(scope,element,attr,ctrls){
- if(attr.startOpen === ""){
- scope.startOpen = true;
- }
- var paneGroupCtrl = ctrls[0];
- var innerPaneCtrl = ctrls[1];
- paneGroupCtrl.addPaneCtrl(scope.paneId,innerPaneCtrl);
- }
- };
-})
-.controller('PaneGroupCtrl', ['$scope', '$element', 'paneGroupConstants',function($scope,$element,paneGroupConstants){
- this.panes = {};
- this.accountLevelPaneModel = [];
- this.title = $scope.title;
- this.init = function(){
- var sidePane = this.panes[paneGroupConstants.SIDE_PANE_ID];
- if(sidePane){
- sidePane.init();
-
- //Show the other panes that may be set to startOpen
- //numOpen starts at 1 because of the side pane
- var numOpen = 1;
- var key;
- for(key in this.panes){
- if(this.panes[key].startOpen && this.panes[key].startOpen()){
- numOpen++;
- }
- }
- var width;
- if(numOpen >= 3){
- width = ((100/numOpen)) + '%';
- }
- if(this.panes[sidePane.currentSelectedRowPaneId])
- {
- if(width){
- sidePane.setWidth(width);
- this.panes[sidePane.currentSelectedRowPaneId].setWidth(width);
- }
- else{
- sidePane.setWidth();
- this.panes[sidePane.currentSelectedRowPaneId].setWidth();
- }
- this.panes[sidePane.currentSelectedRowPaneId].displayBlock();
- for(key in this.panes){
- if(key !== paneGroupConstants.SIDE_PANE_ID && key !== sidePane.currentSelectedRowPaneId){
- this.panes[key].displayNone();
- }
- this.panes[key].drillDownTo = sidePane.drillDownToMapper[key];
- }
- }
- openOtherPanesOnStart(sidePane, this.panes);
- }
-
- function openOtherPanesOnStart(sidePane, panes){
- //Build an array of the panes that need to be out
- var otherPanesStartOpened = [];
- var index;
- for(index in sidePane.sidePaneRows){
- if (sidePane.sidePaneRows.hasOwnProperty(index)) {
- var pane = sidePane.sidePaneRows[index];
-
- //Skip the first pane row since we handled it in the begining
- if(index > 0 && panes[pane.paneId].startOpen && panes[pane.paneId].startOpen()){
- otherPanesStartOpened.push(pane);
- //Remember the panes that are opened for the first pane row Index
- sidePane.addToSidePanesList(pane.paneId);
- }
- }
- }
-
- if(width){
- for(index in otherPanesStartOpened){
- if (otherPanesStartOpened.hasOwnProperty(index)) {
- var paneId = otherPanesStartOpened[index].paneId;
- var paneCtrl = panes[paneId];
- if(paneCtrl && paneCtrl.setWidth && paneCtrl.displayBlock){
- paneCtrl.setWidth(width);
- paneCtrl.displayBlock();
- }
- }
- }
- }
-
- }
- };
-
- /*
- Resets all the panels to their original positions at the end of a sidebar click
- By setting the sideBar to its default width
- Setting all panes to float left and displaynone
- Setting the pane that was clicked to default width and slide right
- */
-
- this.resetPanes = function(){
- for(var key in this.panes){
- if(this.panes.hasOwnProperty(key)){
- var pane = this.panes[key];
- if(pane && (pane.paneId !== paneGroupConstants.SIDE_PANE_ID)){
- pane.floatLeft();
- pane.displayNone();
- }
- }
- }
-
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
- }
- };
-
- this.addPaneCtrl = function(paneId,paneCtrl){
- this.panes[paneId] = paneCtrl;
- };
-
- this._slideOutPane = function(paneId,isFromSidePane){
- this.resetPanes();
- //Check current side pane stack to see how many panes are already open for that side pane choice
- //then add the new pane that needs to be there
- var panesList;
- if(isFromSidePane){
-
- //Check if the side pane id has already been clicked
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- panesList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
- }
- if(!panesList){
- if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
- this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId = paneId;
- this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList();
-
- this.panes[paneId].slideFromRight();
- this.panes[paneId].displayBlock();
-
- this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
- }
- }
- else if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID]){
- //Restore the panes based on the panelist
- if(panesList.length === 0 && this.panes[paneId]){
- //Only one pane is out
- this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
- this.panes[paneId].displayBlock();
- this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
- }
- else{
- //Multiple panes out
- var numPanes = panesList.length + 2;
- var width = ((100/numPanes)) + '%';
- this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
-
- //Set the sidePanes pane
- //set the panes children list
- if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
- this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
- this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(width);
- }
- for(var i in panesList){
- if(this.panes[panesList[i]]){
- this.panes[panesList[i]].displayBlock();
- this.panes[panesList[i]].setWidth(width);
- }
- }
- }
- }
- }
- else{
-
- //Have to check the paneId that was given and where it is drilling down to
- var isPaneInStack = false;
- var stackPaneList;
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- stackPaneList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
- }
- for(var j in stackPaneList){
- if(stackPaneList.hasOwnProperty(j)){
- var pId = stackPaneList[j];
- if(pId === paneId){
- isPaneInStack = true;
- break;
- }
- }
- }
- if(!isPaneInStack && this.panes[paneGroupConstants.SIDE_PANE_ID]){
- this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList(paneId);
- }
- var sidePanesListLength;
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- sidePanesListLength = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList().length;
- }
- var numberPanes = sidePanesListLength + 2;
- var widthToSet = ((100/numberPanes)) + '%';
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(widthToSet);
- }
- var slideInPaneId;
-
- if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
- slideInPaneId = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList()[sidePanesListLength - 1];
- }
-
- var that = this;
-
- if(that.panes[paneGroupConstants.SIDE_PANE_ID]){
- panesList = that.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
- }
-
- for(var p in panesList){
- if(panesList.hasOwnProperty(p)){
- var paneListPaneId = panesList[p];
- var pane = this.panes[paneListPaneId];
- if(paneListPaneId !== slideInPaneId && pane){
- pane.setWidth(widthToSet);
- pane.displayBlock();
- pane.floatLeft();
- }
- }
- }
-
- if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
- this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
- this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder();
-
- this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(widthToSet,function(){
-
- if(that.panes[slideInPaneId] && that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
- that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder();
- that.panes[slideInPaneId].setWidth(widthToSet);
- that.panes[slideInPaneId].slideFromRight();
- that.panes[slideInPaneId].displayBlock();
- that.panes[slideInPaneId].floatLeft();
- }
-
- });
- }
- }
- };
-
- this.slideOutPane = function(paneId,isFromSidePane){
- this._slideOutPane(paneId,isFromSidePane);
- };
-}])
-.directive('paneGroup', ['$timeout',function($timeout){
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html',
- scope:{
- },
- controller: 'PaneGroupCtrl',
- link: function(scope,element,attr,ctrl){
- $timeout(initialize,100);
- function initialize(){
- ctrl.init();
- }
- }
- };
-}]);
-angular.module('att.abs.tooltip', ['att.abs.position', 'att.abs.utilities', 'ngSanitize'])
- // The default options tooltip and popover.
- .constant('tooltipDefaultOptions', {
- placement: 'above',
- animation: false,
- popupDelay: 0,
- stylett: 'dark',
- appendToBody: true
- })
-
- /**
- * The $tooltip service creates tooltip- and popover-like directives as well as
- * houses global options for them.
- */
- .provider('$tooltip', ['tooltipDefaultOptions', function(tooltipDefaultOptions) {
-
- // Default hide triggers for each show trigger
- var triggerMap = {
- 'mouseenter': 'mouseleave',
- 'click': 'click',
- 'focus': 'blur',
- 'mouseover':'mouseout'
- };
-
- // The options specified to the provider globally.
- var globalOptions = {};
-
- this.options = function(value) {
- angular.extend(globalOptions, value);
- };
-
- /**
- * This allows you to extend the set of trigger mappings available. E.g.:
- *
- * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
- */
- this.setTriggers = function(triggers) {
- angular.extend(triggerMap, triggers);
- };
-
- /**
- * This is a helper function for translating camel-case to snake-case.
- */
- function snakeCase(name) {
- var regexp = /[A-Z]/g;
- var separator = '-';
- return name.replace(regexp, function(letter, pos) {
- return (pos ? separator : '') + letter.toLowerCase();
- });
- }
-
- /**
- * Returns the actual instance of the $tooltip service.
- */
- this.$get = ['$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', '$attElementDetach', function($window, $compile, $timeout, $parse, $document, $position, $interpolate, $attElementDetach) {
- return function (type, prefix, defaultTriggerShow) {
- var options = angular.extend({}, tooltipDefaultOptions, globalOptions);
- /**
- * Returns an object of show and hide triggers.
- *
- * If a trigger is supplied,
- * it is used to show the tooltip; otherwise, it will use the `trigger`
- * option passed to the `$tooltipProvider.options` method; else it will
- * default to the trigger supplied to this directive factory.
- *
- * The hide trigger is based on the show trigger. If the `trigger` option
- * was passed to the `$tooltipProvider.options` method, it will use the
- * mapped trigger from `triggerMap` or the passed trigger if the map is
- * undefined; otherwise, it uses the `triggerMap` value of the show
- * trigger; else it will just use the show trigger.
- */
- function getTriggers(trigger) {
- var show = trigger || options.trigger || defaultTriggerShow;
- var hide = triggerMap[show] || show;
- return {
- show: show,
- hide: hide
- };
- }
-
- var directiveName = snakeCase(type);
-
- var startSym = $interpolate.startSymbol();
- var endSym = $interpolate.endSymbol();
-
- return {
- restrict: 'EA',
- scope: true,
- link: function (scope, element, attrs) {
- /* Allows a developer to force element to be non-tabable */
- if (!element.attr('tabindex')) {
- element.attr('tabindex', '0');
- }
-
- var isElementHovered = false;
- element.bind('mouseenter', function(){
- isElementHovered = true;
- element.removeAttr('title');
- });
- element.bind('mouseleave', function(){
- isElementHovered = false;
- // setTooltipAriaLabel();
- });
-
- /* We store our attributes on our scope so any user of $tooltip service can access attributes */
- scope.parentAttrs = attrs;
- var template =
- '<div ' + directiveName + '-popup ' +
- 'title="' + startSym + 'tt_title' + endSym + '" ' +
- 'content="' + startSym + 'tt_content' + endSym + '" ' +
- 'placement="' + startSym + 'tt_placement' + endSym + '" ' +
- 'animation="tt_animation()" ' +
- 'is-open="tt_isOpen" ' +
- 'stylett="' + startSym + 'tt_style' + endSym + '" ' +
- '>' +
- '</div>';
-
- var tooltip = $compile(template)(scope);
- var transitionTimeout;
- var popupTimeout;
- var $body;
- var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
- var triggers = getTriggers(undefined);
- var hasRegisteredTriggers = false;
- var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
- var tooltipOffset = 0;
- var tooltipAriaLabelDefined = false;
-
- // By default, the tooltip is not open.
- // add ability to start tooltip opened
- scope.tt_isOpen = false;
-
- //Adding a scope watch, to remove the created popup from DOM, incase it is updated outside the provider code.
- scope.$watch('tt_isOpen', function(newVal, oldVal){
- if(newVal !== oldVal && !newVal){
- $attElementDetach(tooltip[0]);
- }
- });
-
- function toggleTooltipBind() {
- if (!scope.tt_isOpen) {
- showTooltipBind();
- } else {
- hideTooltipBind();
- }
- }
-
- // Show the tooltip with delay if specified, otherwise show it immediately
- function showTooltipBind() {
- if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
- return;
- }
- if (scope.tt_popupDelay) {
- popupTimeout = $timeout(show, scope.tt_popupDelay);
- } else {
- scope.$apply(show);
- }
- }
-
- function hideTooltipBind() {
- scope.$apply(function() {
- hide();
- });
- }
-
- // Show the tooltip popup element.
- function show() {
- var position,
- ttWidth,
- ttHeight,
- ttPosition;
-
- // Don't show empty tooltips.
- if (!scope.tt_content) {
- return;
- }
-
- // If there is a pending remove transition, we must cancel it, lest the
- // tooltip be mysteriously removed.
- if (transitionTimeout) {
- $timeout.cancel(transitionTimeout);
- }
-
- // Set the initial positioning.
- tooltip.css({top: 0, left: 0, display: 'block', 'z-index': 9999});
-
- // Now we add it to the DOM because need some info about it. But it's not
- // visible yet anyway.
- if (appendToBody) {
- $body = $body || $document.find('body');
- $body.append(tooltip);
- } else {
- element.after(tooltip);
- }
-
- // Get the position of the directive element.
- position = appendToBody ? $position.offset(element) : $position.position(element);
-
- // Get the height and width of the tooltip so we can center it.
- ttWidth = tooltip.prop('offsetWidth');
- ttHeight = tooltip.prop('offsetHeight');
-
- // Calculate the tooltip's top and left coordinates to center it with
- // this directive.
- var ttArrowOffset = 10;
- switch (scope.tt_placement) {
- case 'right':
- if(appendToBody){
- ttPosition = {
- top: position.top + position.height / 2 - ttHeight / 2,
- left: (position.left + position.width) + tooltipOffset
- };
- }else{
- ttPosition = {
- top: position.top + position.height / 2 - ttHeight / 2,
- left: (position.left + position.width + ttArrowOffset) + tooltipOffset
- };
- }
- break;
- case 'below':
- if(appendToBody){
- ttPosition = {
- top: (position.top + position.height) + tooltipOffset,
- left: position.left + position.width / 2 - ttWidth / 2
- };
- }else{
- ttPosition = {
- top: (position.top + position.height + ttArrowOffset) + tooltipOffset,
- left: position.left + position.width / 2 - ttWidth / 2
- };
- }
- break;
- case 'left':
- if(appendToBody){
- ttPosition = {
- top: position.top + position.height / 2 - ttHeight / 2,
- left: (position.left - ttWidth) - tooltipOffset
- };
- }else{
- ttPosition = {
- top: position.top + position.height / 2 - ttHeight / 2,
- left: (position.left - ttWidth - ttArrowOffset) - tooltipOffset
- };
- }
- break;
- default:
- if(appendToBody){
- ttPosition = {
- top: (position.top - ttHeight) - tooltipOffset,
- left: position.left + position.width / 2 - ttWidth / 2
- };
- }else{
- ttPosition = {
- top: (position.top - ttHeight - ttArrowOffset) - tooltipOffset,
- left: position.left + position.width / 2 - ttWidth / 2
- };
- }
- break;
- }
-
- ttPosition.top += 'px';
- ttPosition.left += 'px';
-
- // Now set the calculated positioning.
- tooltip.css(ttPosition);
-
- // And show the tooltip.
- scope.tt_isOpen = true;
- }
-
- // Hide the tooltip popup element.
- function hide() {
- // First things first: we don't show it anymore.
- scope.tt_isOpen = false;
-
- //if tooltip is going to be shown after delay, we must cancel this
- $timeout.cancel(popupTimeout);
-
- // And now we remove it from the DOM. However, if we have animation, we
- // need to wait for it to expire beforehand.
- // This is a placeholder for a port of the transitions library.
- if (angular.isDefined(scope.tt_animation) && scope.tt_animation()) {
- transitionTimeout = $timeout(function() {
- $attElementDetach(tooltip[0]);
- }, 500);
- } else {
- $attElementDetach(tooltip[0]);
- }
- }
-
- function setTooltipAriaLabel() {
- element.removeAttr('title');
- if(!isElementHovered){
- if (tooltipAriaLabelDefined) {
- element.attr('title', scope.tooltipAriaLabel);
- } else {
- element.attr('title', scope.tt_content);
- }
- }
- }
-
- /**
- * Observe the relevant attributes.
- */
- attrs.$observe(type, function(val) {
- if (val) {
- scope.tt_content = val;
- // setTooltipAriaLabel();
- } else {
- if (scope.tt_isOpen) {
- hide();
- }
- }
- });
-
- attrs.$observe(prefix + 'Title', function(val) {
- scope.tt_title = val;
- });
-
- attrs.$observe(prefix + 'Placement', function(val) {
- scope.tt_placement = angular.isDefined(val) ? val : options.placement;
- });
-
- attrs.$observe(prefix + 'Style', function(val) {
- scope.tt_style = angular.isDefined(val) ? val : options.stylett;
- });
-
- attrs.$observe(prefix + 'Animation', function(val) {
- scope.tt_animation = angular.isDefined(val) ? $parse(val) : function() {
- return options.animation;
- };
- });
-
- attrs.$observe(prefix + 'PopupDelay', function(val) {
- var delay = parseInt(val, 10);
- scope.tt_popupDelay = !isNaN(delay) ? delay : options.popupDelay;
- });
-
- attrs.$observe(prefix + 'Trigger', function(val) {
-
- if (hasRegisteredTriggers) {
- element.unbind(triggers.show, showTooltipBind);
- element.unbind(triggers.hide, hideTooltipBind);
- }
-
- triggers = getTriggers(val);
-
- /* This fixes issue in which a click on input field with trigger as focus
- causes focus to fire following click thus making tooltip flash. */
- if (triggers.show === 'focus') {
- element.bind('focus', showTooltipBind);
- element.bind('blur', hideTooltipBind);
- element.bind('click', function(e) {
- e.stopPropagation();
- });
- } else if (triggers.show === triggers.hide) {
- element.bind(triggers.show, toggleTooltipBind);
- } else {
- element.bind(triggers.show, showTooltipBind);
- element.bind(triggers.hide, hideTooltipBind);
- }
-
- hasRegisteredTriggers = true;
- });
-
- attrs.$observe(prefix + 'AppendToBody', function (val) {
- appendToBody = angular.isDefined(val) ? $parse(val)(scope) : appendToBody;
- });
-
- attrs.$observe(prefix + 'Offset', function (val) {
- tooltipOffset = angular.isDefined(val) ? parseInt(val, 10) : 0;
- });
-
- attrs.$observe(prefix + 'AriaLabel', function (val) {
- if (angular.isDefined(val)) {
- scope.tooltipAriaLabel = val;
- tooltipAriaLabelDefined = true;
- } else {
- tooltipAriaLabelDefined = false;
- }
- setTooltipAriaLabel();
- });
-
- // if a tooltip is attached to <body> we need to remove it on
- // location change as its parent scope will probably not be destroyed
- // by the change.
- if (appendToBody) {
- scope.$on('$locationChangeSuccess', function() {
- if (scope.tt_isOpen) {
- hide();
- }
- });
- }
-
- // Make sure tooltip is destroyed and removed.
- scope.$on('$destroy', function() {
- if (scope.tt_isOpen) {
- hide();
- } else {
- tooltip.remove();
- }
- });
- }
- };
- };
- }];
- }])
-
- .directive('tooltipPopup', ['$document', '$documentBind', function($document, $documentBind) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
- templateUrl: 'app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html',
- link: function(scope, elem) {
- scope.$watch("isOpen", function() {
- scope.isOpen;
- });
- elem.bind('click', function (e) {
- e.stopPropagation();
- });
- var outsideClick = function() {
- scope.$apply(function() {
- scope.isOpen = false;
- });
- };
-
- $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
- }
- };
- }])
-
- .directive('tooltip', ['$tooltip', function($tooltip) {
- return $tooltip('tooltip', 'tooltip', 'mouseenter');
- }])
-
- .directive('tooltipCondition', [ '$timeout',function($timeout) {
- return {
- restrict: 'EA',
- replace: true,
- scope:{
- tooltipCondition:"@?"
- },
- template:'<p><span tooltip=\"{{tooltipCondition}}\" ng-if=\"showpop\">{{tooltipCondition}}</span><span id=\"innerElement\" ng-hide=\"showpop\">{{tooltipCondition}}</span></p>',
- link: function(scope, elem, attr){
- scope.showpop=false;
- if(attr.height==='true'){
- $timeout(function () {
- var maxHeight=(elem[0].offsetHeight);
- var elemHeight=elem.children(0)[0].offsetHeight;
- if(elemHeight > maxHeight){
- scope.showpop=true;
- }
- });
- }
- else if(scope.tooltipCondition.length>=25){
- scope.showpop=true;
- }
- }
- };
- }]);
-angular.module('att.abs.popOvers', ['att.abs.tooltip', 'att.abs.utilities', 'ngSanitize'])
- .directive('popover', ['$tooltip', function($tooltip) {
- return $tooltip('popover', 'popover', 'click');
- }])
- .directive('popoverPopup', ['$document', '$documentBind', '$timeout', 'events', 'DOMHelper', function($document, $documentBind, $timeout, events, DOMHelper) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/popOvers/popOvers.html',
- scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
- link: function(scope, elem, attr, ctrl) {
-
- scope.closeable = false;
- try {
- scope.closeable = scope.$parent.parentAttrs['closeable'] === '' ? true : false;
- } catch (e) {}
-
- /* Before opening modal, find the focused element */
- var launchingElement = undefined,
- firstTabableElement = undefined;
-
- var outsideClick = function(evt) {
- scope.$apply(function() {
- scope.isOpen = false;
- });
- };
- var escKeydown = function(evt) {
- if (evt.which === 27 || evt.keyCode === 27) {
- console.log('ESC was pressed!');
- scope.$apply(function() {
- scope.isOpen = false;
- });
- }
- };
-
- $timeout(function() {
- firstTabableElement = DOMHelper.firstTabableElement(elem);
- }, 10, false);
-
- scope.$watch('isOpen', function(value) {
- if (scope.isOpen) {
- launchingElement = document.activeElement;
- /* Focus on first tabbable element */
- if (angular.isDefined(firstTabableElement)) {
- try {
- firstTabableElement.focus();
- } catch(e) {}
- }
- } else {
- if (angular.isDefined(launchingElement)) {
- try {
- launchingElement.focus();
- } catch (e) {} /* IE8 will throw exception */
- }
- }
- });
-
- scope.$watch("stylett", function(value) {
- scope.popOverStyle = value;
- });
-
- scope.$watch("placement", function(value) {
- scope.popOverPlacement = value;
- });
-
- scope.closeMe = function(){
- scope.isOpen = false;
- };
-
- elem.bind('click', function (e) {
- events.stopPropagation(e);
- });
-
- $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
- $documentBind.event('keydown', 'isOpen', escKeydown, scope, true, 10);
- }
- };
- }]);
-
-angular.module('att.abs.profileCard', [])
- .constant('profileStatus',{
- status:{
- ACTIVE:{status:"Active",color:"green"},
- DEACTIVATED:{status:"Deactivated",color:"red"},
- LOCKED:{status:"Locked",color:"red"},
- IDLE:{status:"Idle",color:"yellow"},
- PENDING:{status:"Pending",color:"blue"}
- },
- role:"COMPANY ADMINISTRATOR"
- })
- .directive('profileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
- return {
- restrict: 'EA',
- replace:'true',
- templateUrl:function(element, attrs){
- if(!attrs.addUser){
- return 'app/scripts/ng_js_att_tpls/profileCard/profileCard.html';
- }
- else{
- return 'app/scripts/ng_js_att_tpls/profileCard/addUser.html';
- }
- },
- scope:{
- profile:'='
- },
- link: function(scope, elem, attr){
- scope.image=true;
- function isImage(src) {
- var deferred = $q.defer();
- var image = new Image();
- image.onerror = function() {
- deferred.reject(false);
- };
- image.onload = function() {
- deferred.resolve(true);
- };
- if(src!==undefined && src.length>0 ){
- image.src = src;
- }else{
- deferred.reject(false);
- }
- return deferred.promise;
- }
- if(!attr.addUser){
- scope.image=false;
- isImage(scope.profile.img).then(function(img) {
- scope.image=img;
- });
- var splitName=(scope.profile.name).split(' ');
- scope.initials='';
- for(var i=0;i<splitName.length;i++){
- scope.initials += splitName[i][0];
- }
- if(scope.profile.role.toUpperCase()===profileStatus.role){
- scope.badge=true;
- }
- var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
- if(profileState) {
- scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
- scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
- if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
- scope.profile.lastLogin=scope.profile.state;
- }
- }
- var today=new Date().getTime();
- var lastlogin=new Date(scope.profile.lastLogin).getTime();
- var diff=(today-lastlogin)/(1000*60*60*24);
- if(diff<=1){
- scope.profile.lastLogin="Today";
- }
- else if(diff<=2){
- scope.profile.lastLogin="Yesterday";
- }
- }
- }
- };
- }]);
-angular.module('att.abs.progressBars', [])
-
-.directive('attProgressBar', [function(){
- return {
- restrict: 'A',
- replace: true,
- templateUrl : 'app/scripts/ng_js_att_tpls/progressBars/progressBars.html'
- };
-}]);
-angular.module('att.abs.radio', [])
- .constant('attRadioConfig', {
- activeClass : "att-radio--on",
- disabledClass : "att-radio--disabled"
- })
-.directive('attRadio', ['$compile','attRadioConfig', function ($compile, attRadioConfig) {
- return {
- scope: {},
- restrict: 'A',
- require: 'ngModel',
- link: function (scope, element, attr, ctrl) {
- var ngCtrl = ctrl;
- scope.radioVal='';
- var parentDiv = angular.element('<div att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>');
- element.attr("value",attr.attRadio);
- element.removeAttr("att-radio");
- element.removeAttr("title");
- element.attr("ng-model","radioVal");
- parentDiv.append(element.prop('outerHTML'));
- parentDiv.append('<div class="att-radio__indicator"></div>');
- parentDiv.attr("title", attr.title);
-
- var elm = parentDiv.prop('outerHTML');
- elm = $compile(elm)(scope);
- element = element.replaceWith(elm);
- var radioElm = elm.find("input");
-
- radioElm.on('focus', function() {
- elm.css("outline","2px solid #5E9ED6");
- // elm.css("outline","-mos-focus-ring-color auto 5px");
- elm.css("outline","-webkit-focus-ring-color auto 5px");
-
- });
- radioElm.on('blur', function() {
- elm.css("outline","none");
- });
-
- ngCtrl.$render = function () {
- scope.radioVal = ngCtrl.$modelValue;
- var selected = angular.equals(ngCtrl.$modelValue, attr.attRadio);
- elm.toggleClass(attRadioConfig.activeClass, selected);
- };
-
- scope.updateModel = function () {
- radioElm[0].focus();
- var isActive = elm.hasClass(attRadioConfig.activeClass);
-
- if (!isActive && !scope.disabled) {
- ngCtrl.$setViewValue(isActive ? null : attr.attRadio);
- ngCtrl.$render();
- }
- };
-
- attr.$observe('disabled', function (val) {
- scope.disabled = (val || val === "disabled" || val === "true");
- if (scope.disabled){
- elm.addClass(attRadioConfig.disabledClass);
- elm.attr("tabindex", "-1");
- }else {
- elm.removeClass(attRadioConfig.disabledClass);
- elm.attr("tabindex", "0");
- }
- });
- }
- };
-}]);
-angular.module('att.abs.scrollbar', ['att.abs.position'])
-
-.constant('attScrollbarConstant', {
- defaults: {
- // Vertical or horizontal scrollbar? ( x || y ).
- axis: 'y',
- // Whether navigation pane is required of not.
- navigation: false,
- // Enable or disable the mousewheel.
- wheel: true,
- // How many pixels must the mouswheel scroll at a time.
- wheelSpeed: 40,
- // Lock default scrolling window when there is no more content.
- wheelLock: true,
- //// Enable invert style scrolling
- scrollInvert: false,
- // Set the size of the scrollbar to auto or a fixed number.
- trackSize: false,
- // Set the size of the thumb to auto or a fixed number.
- thumbSize: false,
- // Set to false to hide the scrollbar if not being used
- alwaysVisible: true
- }
-})
-
-.directive('attScrollbar', ['$window', '$timeout', '$parse', '$animate', 'attScrollbarConstant', '$position', function ($window, $timeout, $parse, $animate, attScrollbarConstant, $position) {
- return {
- restrict: 'A',
- scope: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html',
- controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
- var defaults = {
- axis: $attrs.attScrollbar || attScrollbarConstant.defaults.axis,
- navigation: $attrs.navigation || attScrollbarConstant.defaults.navigation,
- wheel: attScrollbarConstant.defaults.wheel,
- wheelSpeed: attScrollbarConstant.defaults.wheelSpeed,
- wheelLock: attScrollbarConstant.defaults.wheelLock,
- scrollInvert: attScrollbarConstant.defaults.scrollInvert,
- trackSize: attScrollbarConstant.defaults.trackSize,
- thumbSize: attScrollbarConstant.defaults.thumbSize,
- alwaysVisible: attScrollbarConstant.defaults.alwaysVisible
- };
- var options = $attrs.scrollbar;
- if (options) {
- options = $parse(options)($scope);
- } else {
- options = {};
- }
- this.options = angular.extend({}, defaults, options);
- this._defaults = defaults;
-
- var self = this,
- $body = angular.element(document.querySelectorAll('body')[0]),
- $document = angular.element(document),
- $viewport = angular.element($element[0].querySelectorAll('.scroll-viewport')[0]),
- $overview = angular.element($element[0].querySelectorAll('.scroll-overview')[0]),
- $scrollbar = angular.element($element[0].querySelectorAll('.scroll-bar')[0]),
- $thumb = angular.element($element[0].querySelectorAll('.scroll-thumb')[0]),
- mousePosition = 0,
- isHorizontal = this.options.axis === 'x',
- hasTouchEvents = false,
- // Modern browsers support "wheel"
- wheelEvent = ("onwheel" in document ? "wheel" :
- // Webkit and IE support at least "mousewheel"
- document.onmousewheel !== undefined ? "mousewheel" :
- // let's assume that remaining browsers are older Firefox
- "DOMMouseScroll"),
- sizeLabel = isHorizontal ? 'width' : 'height',
- sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase(),
- posiLabel = isHorizontal ? 'left' : 'top',
- // moveEvent = document.createEvent('HTMLEvents'),
- restoreVisibilityAfterWheel,
- thumbscrolltouch = false,
- documnetscrolltouch = false;
- if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
- hasTouchEvents = true;
- }
-
- //moveEvent.initEvent('move', true, true);
- this.contentPosition = 0;
- this.viewportSize = 0;
- this.contentSize = 0;
- this.contentRatio = 0;
- this.trackSize = 0;
- this.trackRatio = 0;
- this.thumbSize = 0;
- this.thumbPosition = 0;
-
- this.initialize = function () {
- if (!this.options.alwaysVisible) {
- $scrollbar.css('opacity', 0);
- }
- self.update();
- setEvents();
- return self;
- };
-
- this.setSizeData = function () {
- this.viewportSize = $viewport.prop('offset' + sizeLabelCap) || 1;
- this.contentSize = $overview.prop('scroll' + sizeLabelCap) || 1;
- this.contentRatio = this.viewportSize / this.contentSize;
- this.trackSize = this.options.trackSize || this.viewportSize;
- this.thumbSize = Math.min(this.trackSize, Math.max(0, (this.options.thumbSize || (this.trackSize * this.contentRatio))));
- this.trackRatio = this.options.thumbSize ? (this.contentSize - this.viewportSize) / (this.trackSize - this.thumbSize) : (this.contentSize / this.trackSize);
- };
-
- this.update = function (scrollTo) {
- self.setSizeData();
- mousePosition = $scrollbar.prop('offsetTop');
-
- $scrollbar.toggleClass('disable', this.contentRatio >= 1 || isNaN(this.contentRatio));
-
- if (!this.options.alwaysVisible && this.contentRatio < 1 && this.viewportSize > 0) {
- //flash the scrollbar when update happens
- $animate.addClass($scrollbar, 'visible').then(function () {
- $animate.removeClass($scrollbar, 'visible');
- $scope.$digest();
- });
- }
-
- if (scrollTo !== null) {
- if (scrollTo === 'bottom') {
- this.contentPosition = this.contentSize - this.viewportSize;
- } else {
- this.contentPosition = parseInt(scrollTo, 10) || 0;
- }
- }
-
- ensureContentPosition();
- $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
- $scrollbar.css(sizeLabel, self.trackSize + 'px');
- $thumb.css(sizeLabel, self.thumbSize + 'px');
- $overview.css(posiLabel, -self.contentPosition + 'px');
-
- return this;
- };
-
- fireEvent = function (obj, evt) {
- var fireOnThis = obj;
- var evtObj;
- if (document.createEvent) {
- // alert("FF");
- evtObj = document.createEvent('HTMLEvents');
- evtObj.initEvent(evt, true, false);
- fireOnThis.dispatchEvent(evtObj);
- } else if (document.createEventObject) {
- // alert("IE8");
- evtObj = document.createEventObject();
- fireOnThis.fireEvent('on' + evt, evtObj);
- }
- };
-
- function ensureContentPosition() {
- // if scrollbar is on, ensure the bottom of the content does not go above the bottom of the viewport
- if (self.contentRatio <= 1 && self.contentPosition > self.contentSize - self.viewportSize) {
- self.contentPosition = self.contentSize - self.viewportSize;
- }
- // if scrollbar is off, ensure the top of the content does not go below the top of the viewport
- else if (self.contentRatio > 1 && self.contentPosition > 0) {
- self.contentPosition = 0;
- }
-
- if (self.contentPosition <= 0) {
- $scope.prevAvailable = false;
- } else {
- $scope.prevAvailable = true;
- }
-
- if (self.contentPosition >= (self.contentSize - self.viewportSize)) {
- $scope.nextAvailable = false;
- } else {
- $scope.nextAvailable = true;
- }
- }
-
- function setEvents() {
- if (hasTouchEvents) {
- $viewport.on('touchstart', touchstart);
- $thumb.on('touchstart', touchstart);
- } else {
- $thumb.on('mousedown', start);
- $scrollbar.on('mousedown', drag);
- }
-
- angular.element($window).on('resize', resize);
-
- if (self.options.wheel) {
- $element.on(wheelEvent, wheel);
- }
- }
-
- function resize() {
- self.update();
- }
-
- function touchstart(event) {
- if (1 === event.touches.length) {
- event.stopPropagation();
- start(event.touches[0]);
- }
- }
-
- function start(event) {
- $body.addClass('scroll-no-select');
- $element.addClass('scroll-no-select');
-
- if (!self.options.alwaysVisible) {
- $scrollbar.addClass('visible');
- }
- mousePosition = isHorizontal ? event.clientX : event.clientY;
- self.thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
-
- if (hasTouchEvents) {
- documnetscrolltouch = false;
- thumbscrolltouch = false;
- $viewport.on('touchmove', touchdrag);
- $viewport.on('touchend', end);
- $thumb.on('touchmove', touchdragthumb);
- $thumb.on('touchend', end);
- } else {
- $document.on('mousemove', drag);
- $document.on('mouseup', end);
- $thumb.on('mouseup', end);
- }
- }
-
- function wheel(event) {
- if (self.contentRatio >= 1) {
- return;
- }
-
- if (!self.options.alwaysVisible) {
- //cancel removing visibility if wheel event is triggered before the timeout
- if (restoreVisibilityAfterWheel) {
- $timeout.cancel(restoreVisibilityAfterWheel);
- }
- $scrollbar.addClass('visible');
-
- restoreVisibilityAfterWheel = $timeout(function () {
- $scrollbar.removeClass('visible');
- }, 100);
- }
-
- var evntObj = (event && event.originalEvent) || event || $window.event,
- deltaDir = self.options.axis.toUpperCase(),
- delta = {
- X: evntObj.deltaX || 0,
- Y: evntObj.deltaY || 0
- },
- wheelSpeed = evntObj.deltaMode === 0 ? self.options.wheelSpeed : 1;
-
- if (self.options.scrollInvert) {
- wheelSpeed *= -1;
- }
-
- if (wheelEvent === 'mousewheel') {
- delta.Y = -1 * evntObj.wheelDelta / 40;
- if (evntObj.wheelDeltaX) {
- delta.X = -1 * evntObj.wheelDeltaX / 40;
- }
- }
- delta.X *= -1 / wheelSpeed;
- delta.Y *= -1 / wheelSpeed;
-
- var wheelSpeedDelta = delta[deltaDir];
-
- self.contentPosition -= wheelSpeedDelta * self.options.wheelSpeed;
- self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
-
- fireEvent($element[0], 'move');
-
- ensureContentPosition();
- $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
- $overview.css(posiLabel, -self.contentPosition + 'px');
-
- if (self.options.wheelLock || (self.contentPosition !== (self.contentSize - self.viewportSize) && self.contentPosition !== 0)) {
- evntObj.preventDefault();
- }
-
- $scope.$apply();
- }
-
- function touchdrag(event) {
- event.preventDefault();
- documnetscrolltouch = true;
- drag(event.touches[0]);
- }
-
- function touchdragthumb(event) {
- event.preventDefault();
- thumbscrolltouch = true;
- drag(event.touches[0]);
- }
-
- function drag(event) {
- if (self.contentRatio >= 1) {
- return;
- }
-
- var mousePositionNew = isHorizontal ? event.clientX : event.clientY,
- thumbPositionDelta = mousePositionNew - mousePosition;
-
- if ((self.options.scrollInvert && !hasTouchEvents) ||
- (hasTouchEvents && !self.options.scrollInvert)) {
- thumbPositionDelta = mousePosition - mousePositionNew;
- }
- if (documnetscrolltouch && hasTouchEvents) {
- thumbPositionDelta = mousePosition - mousePositionNew;
- }
- if (thumbscrolltouch && hasTouchEvents) {
- thumbPositionDelta = mousePositionNew - mousePosition;
- }
- var thumbPositionNew = Math.min((self.trackSize - self.thumbSize), Math.max(0, self.thumbPosition + thumbPositionDelta));
- self.contentPosition = thumbPositionNew * self.trackRatio;
-
- fireEvent($element[0], 'move');
-
- ensureContentPosition();
- $thumb.css(posiLabel, thumbPositionNew + 'px');
- $overview.css(posiLabel, -self.contentPosition + 'px');
-
- $scope.$apply();
- }
-
- $scope.customScroll = function (direction) {
- if (self.contentRatio >= 1) {
- return;
- }
-
- var customScrollDelta;
- var viewportDimension = $position.position($viewport);
-
- if (isHorizontal) {
- customScrollDelta = viewportDimension.width;
- } else {
- customScrollDelta = viewportDimension.height;
- }
-
- if (direction) {
- self.contentPosition += customScrollDelta;
- } else {
- self.contentPosition -= customScrollDelta;
- }
- self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
-
- fireEvent($element[0], 'move');
-
- ensureContentPosition();
- $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
- $overview.css(posiLabel, -self.contentPosition + 'px');
- };
-
- function end() {
- $body.removeClass('scroll-no-select');
- $element.removeClass('scroll-no-select');
- if (!self.options.alwaysVisible) {
- $scrollbar.removeClass('visible');
- }
- $document.off('mousemove', drag);
- $document.off('mouseup', end);
- $thumb.off('mouseup', end);
- $document.off('touchmove', touchdrag);
- $document.off('ontouchend', end);
- $thumb.off('touchmove', touchdragthumb);
- $thumb.off('touchend', end);
- }
-
- this.cleanup = function () {
- $viewport.off('touchstart', touchstart);
- $thumb.off('mousedown', start);
- $scrollbar.off('mousedown', drag);
- $thumb.off('touchmove', touchdragthumb);
- $thumb.off('touchend', end);
- angular.element($window).off('resize', resize);
- $element.off(wheelEvent, wheel);
- //ensure scrollbar isn't activated
- self.options.alwaysVisible = true;
- end();
- };
- }],
- link: function (scope, iElement, iAttrs, controller) {
- scope.navigation = controller.options.navigation;
- scope.viewportHeight = iAttrs.viewportHeight;
- scope.viewportWidth = iAttrs.viewportWidth;
- scope.scrollbarAxis = controller.options.axis;
- if (scope.scrollbarAxis === 'x') {
- iElement.addClass('horizontal');
- } else if (scope.scrollbarAxis === 'y') {
- iElement.addClass('vertical');
- }
-
- var position = iElement.css('position');
- if (position !== 'relative' && position !== 'absolute') {
- iElement.css('position', 'relative');
- }
-
- scope.$watch(function () {
- $timeout(refreshScrollbar, 100, false);
- });
-
- var refreshScrollbar = function () {
- var $overview = angular.element(iElement[0].querySelectorAll('.scroll-overview')[0]);
- var newValue = $overview.prop('scrollHeight');
- var oldValue = scope.oldValue;
- if (newValue !== oldValue) {
- scope.oldValue = newValue;
- controller.update();
- }
- };
-
- controller.initialize();
- iElement.on('$destroy', function () {
- controller.cleanup();
- });
- }
- };
-}]);
-
-angular.module('att.abs.search', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
-.directive('attSearch', ['$document', '$filter', '$isElement', '$documentBind', '$timeout', '$log', 'keymap', function($document, $filter, $isElement, $documentBind, $timeout, $log, keymap){
- return{
- restrict: 'A',
- scope:{cName: '=attSearch'},
- transclude: false,
- replace: false,
- require:'ngModel',
- templateUrl: 'app/scripts/ng_js_att_tpls/search/search.html',
- link: function(scope, element, attr, ctrl) {
- scope.selectedIndex = -1;
- scope.selectedOption = attr.placeholder;
- scope.isDisabled = false;
- scope.className = "select2-match";
- scope.showSearch = false;
- scope.showlist = false;
-
- // This is used to jump to elements in list
- var search = '';
- // This is used to ensure searches only persist so many ms.
- var prevSearchDate = new Date();
- // This is used to shift focus back after closing dropdown
- var dropdownElement = undefined;
- // Used to ensure focus on dropdown elements
- var list = [];
- $timeout(function() {
- list = element.find('li');
- }, 10);
-
- $log.warn('attSearch is deprecated, please use attSelect instead. This component will be removed by version 2.7.')
- //scope.noFilter = true;
- if (attr.noFilter || attr.noFilter === 'true') {
- scope.noFilter = true;
- } else {
- scope.noFilter = false;
- }
- if (attr.placeholderAsOption === 'false') {
- //scope.selectMsg = '';
- scope.selectedOption = attr.placeholder;
- } else {
- scope.selectMsg = attr.placeholder;
- }
- if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
- scope.startsWithFilter = true;
- }
- if (attr.showInputFilter === 'true') {
- scope.showSearch = false;
- $log.warn('showInputFilter functionality has been removed from the library.');
- // This is deprecated
- }
- if (attr.disabled) {
- scope.isDisabled = true;
- }
- dropdownElement = angular.element(element).children().eq(0).find('a')[0];
- var prevIndex = 0;
- var selectOptionFromSearch = function() {
- if (!scope.noFilter) {
- return;
- }
-
- // Find next element that matches search criteria.
- // If no element is found, loop to beginning and search.
- var criteria = search;
- var i = 0;
- for (i = prevIndex; i < scope.cName.length; i++) {
- // Need to ensure we keep searching until all startsWith have passed before looping
- if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
- scope.selectOption(scope.cName[i], i, scope.showlist);
- prevIndex = i;
- search = '';
- break;
- }
- }
- if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
- prevIndex = 0;
- }
- };
- scope.showDropdown = function() {
- if (!(attr.disabled)) {
- scope.showlist = !scope.showlist;
- scope.setSelectTop();
- }
- };
- element.bind('keydown', function(e) {
- if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
- e.preventDefault();
- e.stopPropagation();
-
- switch (e.keyCode) {
- case keymap.KEY.DOWN:
- scope.selectNext();
- break;
- case keymap.KEY.UP:
- scope.selectPrev();
- search = '';
- break;
- case keymap.KEY.ENTER:
- scope.selectCurrent();
- search = '';
- break;
- case keymap.KEY.BACKSPACE:
- scope.title = '';
- search = '';
- scope.$apply();
- break;
- case keymap.KEY.SPACE:
- if (!scope.noFilter) {
- scope.title += ' ';
- }
- scope.$apply();
- break;
- case keymap.KEY.ESC:
- if (scope.title === '' || scope.title === undefined) {
- scope.showlist = false;
- dropdownElement.focus();
- scope.$apply();
- } else {
- scope.title = '';
- scope.$apply();
- }
- if (scope.noFilter) {
- search = '';
- dropdownElement.focus();
- scope.showlist = false;
- }
- break;
- default:
- break;
- }
- } else {
- if (e.keyCode !== 9)
- {
- if (!scope.noFilter) {
- scope.showlist = true;
- scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
- } else {
- var date = new Date();
- var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
- prevSearchDate = date;
- if (delta > 100) {
- search = '';
- }
- search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
- if (search.length > 2) {
- search = search.substring(0, 2);
- }
- selectOptionFromSearch();
- }
- scope.$apply();
- } else if (e.keyCode === 9) {
- scope.showlist = false;
- scope.title = '';
- scope.$apply();
- }
- }
- });
- scope.selectOption = function(sTitle, sIndex, keepOpen) {
- if (sIndex === -1 || sIndex === '-1') {
- scope.selCategory = '';
- scope.selectedIndex = -1;
- ctrl.$setViewValue('');
- if(attr.placeholderAsOption !== 'false')
- {
- scope.selectedOption = scope.selectMsg;
- }
- } else {
- scope.selCategory = scope.cName[sIndex];
- scope.selectedIndex = sIndex;
- ctrl.$setViewValue(scope.selCategory);
- scope.selectedOption = scope.selCategory.title;
- if (angular.isDefined(list[sIndex])) {
- list[sIndex].focus();
- }
- }
- scope.title = '';
- if (!keepOpen) {
- scope.showlist = false;
- dropdownElement.focus();
- }
- scope.$apply();
- };
- scope.selectCurrent = function() {
- if (scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
- scope.$apply();
- } else {
- scope.showlist = true;
- scope.setSelectTop();
- scope.$apply();
- }
- };
- scope.hoverIn = function(cItem) {
- scope.selectedIndex = cItem;
- scope.focusme();
- };
- scope.setSelectTop = function() {
- $timeout(function() {
- if (scope.showlist && !scope.noFilter)
- {
- var containerUL = angular.element(element)[0].querySelector(".select2-results");
- if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
- {
- var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
- }
- angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
- }
- });
- };
- scope.setCurrentTop = function() {
- $timeout(function() {
- if (scope.showlist) {
- var containerUL = angular.element(element)[0].querySelector(".select2-results");
- if(angular.element(containerUL.querySelector('.hovstyle'))[0])
- {
- var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
- }
- if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
- angular.element(containerUL)[0].scrollTop -= 30;
- } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
- angular.element(containerUL)[0].scrollTop += 30;
- }
-
- }
- });
- };
- scope.selectNext = function() {
- if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
- scope.selectedIndex += 1;
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
- }
- scope.focusme();
- scope.$apply();
- }
- scope.setCurrentTop();
- };
- scope.selectPrev = function() {
- if ((scope.selectedIndex - 1) >= 0) {
- scope.selectedIndex -= 1;
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
- }
- scope.focusme();
- scope.$apply();
- } else if (scope.selectedIndex - 1 < 0) {
- // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
- if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
- scope.selectedIndex = -1;
- } else {
- scope.selectedIndex = 0;
- }
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
- }
- scope.focusme();
- scope.$apply();
- }
- scope.setCurrentTop();
- };
- scope.updateSelection = function(sItem) {
- scope.selectedOption = sItem.title;
- scope.title = "";
- };
- scope.focusme = function() {
- $timeout(function() {
- var list = angular.element(element).find('ul').find('li');
- var index = scope.selectedIndex + 2;
- if (scope.noFilter) {
- index = scope.selectedIndex;
- }
- if (angular.isDefined(list[index])) {
- list[index].focus();
- }
- });
- };
- scope.$watch('selCategory', function(value) {
- if (value) {
- scope.updateSelection(value);
- };
- });
- ctrl.$viewChangeListeners.push(function() {
- scope.$eval(attr.ngChange);
- });
- ctrl.$render = function() {
- scope.selCategory = ctrl.$viewValue;
- };
- var outsideClick = function(e) {
- var isElement = $isElement(angular.element(e.target), element, $document);
- if (!isElement) {
- scope.showlist = false;
- dropdownElement.focus();
- scope.$apply();
- }
- };
- $documentBind.click('showlist', outsideClick, scope);
- }
- };
-}]);
-angular.module('att.abs.select', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
-.directive('attSelect', ["$document", "$filter", "$isElement", '$documentBind', '$timeout', 'keymap', '$log', function($document, $filter, $isElement, $documentBind, $timeout, keymap, $log) {
- return {
- restrict: 'A',
- scope: {
- cName: '=attSelect'
- },
- transclude: false,
- replace: false,
- require: 'ngModel',
- templateUrl: 'app/scripts/ng_js_att_tpls/select/select.html',
- link: function(scope, element, attr, ctrl) {
- scope.selectedIndex = -1;
- scope.selectedOption = attr.placeholder;
- scope.isDisabled = false;
- scope.className = "select2-match";
- scope.showSearch = false;
- scope.showlist = false;
- scope.titleName = attr.titlename;
- scope.$watch('ngModel', function() {
- // console.log('sv:', ctrl.$modelValue);
- });
-
- // This is used to jump to elements in list
- var search = '';
- // This is used to ensure searches only persist so many ms.
- var prevSearchDate = new Date();
- // This is used to shift focus back after closing dropdown
- var dropdownElement = undefined;
- // Used to ensure focus on dropdown elements
- var list = [];
- $timeout(function() {
- list = element.find('li');
- }, 10);
- //scope.noFilter = true;
- if (attr.noFilter || attr.noFilter === 'true') {
- scope.noFilter = true;
- } else {
- scope.noFilter = false;
- }
- if (attr.placeholderAsOption === 'false') {
- scope.selectedOption = attr.placeholder;
- } else {
- scope.selectMsg = attr.placeholder;
- }
- if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
- scope.startsWithFilter = true;
- }
- if (attr.showInputFilter === 'true') {
- scope.showSearch = false;
- /* This is deprecated */
- $log.warn('showInputFilter functionality has been removed from the library.');
- }
- if (attr.disabled) {
- scope.isDisabled = true;
- }
- var getFilterType = function() {
- if (scope.startsWithFilter) {
- return 'startsWith';
- } else {
- return 'filter';
- }
- };
- dropdownElement = angular.element(element).children().eq(0).find('span')[0];
- var prevIndex = 0;
- var selectOptionFromSearch = function() {
- if (!scope.noFilter) {
- return;
- }
-
- // Find next element that matches search criteria.
- // If no element is found, loop to beginning and search.
- var criteria = search;
- var i = 0;
- for (i = prevIndex; i < scope.cName.length; i++) {
- // Need to ensure we keep searching until all startsWith have passed before looping
- if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
- scope.selectOption(scope.cName[i], i, scope.showlist);
- prevIndex = i;
- search = '';
- break;
- }
- }
- if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
- prevIndex = 0;
- }
- };
- scope.showDropdown = function() {
- if (!(attr.disabled)) {
- scope.showlist = !scope.showlist;
- scope.setSelectTop();
- /* Ensure selected element is focused upon opening dropdown */
- scope.focusme();
- }
- };
- element.bind('keydown', function(e) {
- if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
- e.preventDefault();
- e.stopPropagation();
-
- switch (e.keyCode) {
- case keymap.KEY.DOWN:
- scope.selectNext();
- break;
- case keymap.KEY.UP:
- scope.selectPrev();
- search = '';
- break;
- case keymap.KEY.ENTER:
- scope.selectCurrent();
- search = '';
- break;
- case keymap.KEY.BACKSPACE:
- scope.title = '';
- search = '';
- scope.$apply();
- break;
- case keymap.KEY.SPACE:
- if (!scope.noFilter) {
- scope.title += ' ';
- }
- scope.$apply();
- break;
- case keymap.KEY.ESC:
- if (scope.title === '' || scope.title === undefined) {
- scope.showlist = false;
- dropdownElement.focus();
- scope.$apply();
- } else {
- scope.title = '';
- scope.$apply();
- }
- if (scope.noFilter) {
- search = '';
- dropdownElement.focus();
- scope.showlist = false;
- }
- break;
- default:
- break;
- }
- } else {
- if (e.keyCode !== keymap.KEY.TAB)
- {
- if (!scope.noFilter) {
- scope.showlist = true;
- scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
-
- /* Perform index correction */
- if (scope.title != '') {
- var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
-
- for (var i = 0; i < filteredArray.length; i++) {
- for (var j = 0; j < scope.cName.length; j++) {
- if (!angular.isDefined(scope.cName[scope.selectedIndex])) {
- break;
- }
- if (filteredArray[i]['title'] === scope.cName[scope.selectedIndex]['title']) {
- scope.selectedIndex = i;
- scope.focusme();
- break;
- }
- }
- }
- }
- } else {
- var date = new Date();
- var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
- prevSearchDate = date;
- if (delta > 100) {
- search = '';
- }
- search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
- if (search.length > 2) {
- search = search.substring(0, 2);
- }
- selectOptionFromSearch();
- }
- scope.$apply();
- } else if (e.keyCode === keymap.KEY.TAB) {
- scope.showlist = false;
- scope.title = '';
- scope.$apply();
- }
- }
- });
- scope.selectOption = function(sTitle, sIndex, keepOpen) {
-
- if (sIndex === -1 || sIndex === '-1') {
- scope.selCategory = '';
- scope.selectedIndex = -1;
- ctrl.$setViewValue('');
- if(attr.placeholderAsOption !== 'false')
- {
- scope.selectedOption = scope.selectMsg;
- }
- }
- else {
- /* Apply filter here to remap the selected index and shift focus*/
- if (scope.title != '') {
- var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
-
- if (angular.isDefined(filteredArray) && angular.isDefined(filteredArray[sIndex]))
- {
- for (var i = 0; i < scope.cName.length; i++) {
- if (filteredArray[sIndex]['title'] === scope.cName[i]['title']) {
- sIndex = i;
- break;
- }
- }
- }
- }
- scope.selCategory = scope.cName[sIndex];
- scope.selectedIndex = sIndex;
- ctrl.$setViewValue(scope.selCategory);
- scope.selectedOption = scope.selCategory.title;
- ctrl.$render();
-
- $timeout(function(){
- if (angular.isDefined(list[sIndex])) {
- try{
- list[index].focus();
- } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */
- }
- });
- }
- scope.title = '';
- if (!keepOpen) {
- scope.showlist = false;
- dropdownElement.focus();
- }
- };
- scope.selectCurrent = function() {
- if (scope.showlist) {
- scope.selectOption(scope.selectMsg,scope.selectedIndex,false);
- } else {
- scope.showlist = true;
- scope.setSelectTop();
- }
- scope.$apply();
- };
- scope.hoverIn = function(cItem) {
- scope.selectedIndex = cItem;
- scope.focusme();
- };
- scope.setSelectTop = function() {
- $timeout(function() {
- if (scope.showlist && !scope.noFilter)
- {
- var containerUL = angular.element(element)[0].querySelector(".select2-results");
- if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
- {
- var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
- }
- angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
- }
- });
- };
- scope.setCurrentTop = function() {
- $timeout(function() {
- if (scope.showlist) {
- var containerUL = angular.element(element)[0].querySelector(".select2-results");
- if(angular.element(containerUL.querySelector('.hovstyle'))[0])
- {
- var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
- }
- if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
- angular.element(containerUL)[0].scrollTop -= 30;
- } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
- angular.element(containerUL)[0].scrollTop += 30;
- }
-
- }
- });
- };
- scope.selectNext = function() {
- var length = scope.cName.length;
-
- if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
- scope.selectedIndex += 1;
- var nextDisabled = scope.cName[scope.selectedIndex].disabled;
- if (nextDisabled) {
- scope.selectedIndex += 1;
- }
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
- }
- scope.focusme();
- scope.$apply();
- }
- scope.setCurrentTop();
- };
- scope.selectPrev = function() {
- if ((scope.selectedIndex - 1) >= 0) {
- scope.selectedIndex -= 1;
- var prevDisabled = scope.cName[scope.selectedIndex].disabled;
- if (prevDisabled) {
- scope.selectedIndex -= 1;
- }
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
- }
- scope.focusme();
- scope.$apply();
- } else if (scope.selectedIndex - 1 < 0) {
- // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
- if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
- if(attr.placeholder === undefined ){
- scope.selectedIndex = 0;
- }
- else{
- scope.selectedIndex = -1;
- }
- } else {
- scope.selectedIndex = 0;
- }
- if (!scope.showlist) {
- scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
- }
- scope.focusme();
- scope.$apply();
- }
- scope.setCurrentTop();
- };
- scope.updateSelection = function(sItem) {
- scope.selectedOption = sItem.title;
- scope.title = '';
-
- if (sItem.index < 0) {
- scope.selectOption(scope.selectMsg, sItem.index, scope.showlist);
- }
- };
- scope.focusme = function() {
- $timeout(function() {
- var list = angular.element(element).find('ul').find('li');
- var index = scope.selectedIndex + 2;
- if (scope.noFilter) {
- index = scope.selectedIndex;
- }
- if (angular.isDefined(list[index])) {
- try {
- list[index].focus();
- } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */
- }
- });
- };
- scope.$watch('selCategory', function(value) {
- if (value) {
- scope.updateSelection(value);
- };
- });
- ctrl.$viewChangeListeners.push(function() {
- scope.$eval(attr.ngChange);
- });
- ctrl.$render = function() {
- scope.selCategory = ctrl.$viewValue;
- };
- var outsideClick = function(e) {
- var isElement = $isElement(angular.element(e.target), element, $document);
- if (!isElement) {
- scope.showlist = false;
- dropdownElement.focus();
- scope.$apply();
- }
- };
- $documentBind.click('showlist', outsideClick, scope);
- }
- };
-}])
-.directive('textDropdown', ['$document', '$isElement', '$documentBind', "keymap", function($document, $isElement, $documentBind, keymap) {
- return {
- restrict: 'EA',
- replace: true,
- scope: {
- actions: '=actions',
- defaultAction: '=defaultAction',
- onActionClicked: '=?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/select/textDropdown.html',
- link: function(scope, element, attr) {
- scope.selectedIndex = 0;
- scope.selectedOption = attr.placeholder;
- scope.isDisabled = false;
- scope.isActionsShown = false;
- var dropdownElement = undefined;
- if (attr.disabled) {
- scope.isDisabled = true;
- }
-
- dropdownElement = element.find('div')[0];
-
- // Set default Action
- if (!angular.isDefined(scope.defaultAction)) {
- scope.currentAction = scope.actions[0];
- scope.selectedIndex = 0;
- } else if (angular.isDefined(scope.defaultAction) || scope.defaultAction !== '') {
- for (var act in scope.actions) {
- if (scope.actions[act] === scope.defaultAction) {
- scope.currentAction = scope.actions[act];
- scope.selectedIndex = scope.actions.indexOf(act);
- scope.isActionsShown = false;
- break;
- }
- }
- } else {
- scope.currentAction = scope.actions[0];
- }
- scope.toggle = function() {
- scope.isActionsShown = !scope.isActionsShown;
- };
- scope.chooseAction = function($event, action, $index) {
- if ($event != null) {
- scope.currentAction = action;
- scope.selectedIndex = $index;
- } else {
- scope.currentAction = scope.actions[scope.selectedIndex];
- }
- if (angular.isFunction(scope.onActionClicked)) {
- scope.onActionClicked(scope.currentAction);
- }
- scope.toggle();
- };
- scope.isCurrentAction = function(action) {
- return (action === scope.currentAction);
- };
- element.bind("keydown", function(e) {
- if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
- e.preventDefault();
- e.stopPropagation();
- switch (e.keyCode) {
- case keymap.KEY.DOWN:
- scope.selectNext();
- break;
- case keymap.KEY.UP:
- scope.selectPrev();
- break;
- case keymap.KEY.ENTER:
- scope.selectCurrent();
- break;
- case keymap.KEY.ESC:
- scope.isActionsShown = false;
- dropdownElement.focus();
- scope.$apply();
- break;
- default:
- break;
- }
- scope.$apply();
- return;
- } else if (e.keyCode === keymap.KEY.TAB) {
- scope.isActionsShown = false;
- scope.$apply();
- }
- });
- scope.selectCurrent = function() {
- if (scope.selectedIndex < 0) {
- scope.selectedIndex = 0;
- }
- if (!scope.isActionsShown) {
- scope.toggle();
- } else {
- scope.chooseAction(null, scope.currentAction);
- }
- };
- scope.selectNext = function() {
- if (scope.isActionsShown) {
- if ((scope.selectedIndex + 1) < scope.actions.length) {
- scope.selectedIndex += 1;
- } else {
- scope.selectedIndex = (scope.actions.length - 1);
- }
- scope.$apply();
- }
- };
- scope.selectPrev = function() {
- if (scope.isActionsShown) {
- if ((scope.selectedIndex - 1) >= 0) {
- scope.selectedIndex -= 1;
- } else if (scope.selectedIndex - 1 < 0) {
- scope.selectedIndex = 0;
- }
- scope.$apply();
- }
- };
- scope.hoverIn = function(cItem) {
- scope.selectedIndex = cItem;
- };
- //end cato
- var outsideClick = function(e) {
- var isElement = $isElement(angular.element(e.target), element, $document);
- if (!isElement) {
- scope.toggle();
- scope.$apply();
- }
- };
- $documentBind.click('isActionsShown', outsideClick, scope);
- }
- };
-}]);
-angular.module('att.abs.slider', ['att.abs.position'])
- .constant('sliderDefaultOptions', {
- width: 300,
- step: 1,
- precision: 0,
- disabledWidth: 116
- })
- .directive('attSlider', ['sliderDefaultOptions','$position','$document', function(sliderDefaultOptions,$position,$document)
- {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: {
- floor: "=",
- ceiling: "=",
- step: "@",
- precision: "@",
- width: "@",
- textDisplay: "=",
- value: "=",
- ngModelSingle: '=?',
- ngModelLow: '=?',
- ngModelHigh: '=?',
- ngModelDisabled: '=?'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/slider/slider.html',
- link: function(scope, elem, attr)
- {
- var minOffset, maxOffset, newOffset, newOffset1, newOffset2, offsetRange, valueRange, start_x = 0, disabledRange, disabled, evFlag = false, minValue, maxValue, range, refLow, refHigh, maxPtr, minPtr, singlePtr, getHandles;
- scope.minPtrOffset = 0;
- scope.maxPtrOffset = 0;
- var disableWidth = sliderDefaultOptions.disabledWidth;
- //Get handles
- var obj = elem.children();
- disabledRange = obj[0].children;
- disabledRange = angular.element(disabledRange[0]);
- getHandles = obj[1].children;
- singlePtr = angular.element(getHandles[0]);
- minPtr = angular.element(getHandles[1]);
- maxPtr = angular.element(getHandles[2]);
- disabled = ((attr.ngModelSingle == null) && (attr.ngModelLow == null) && (attr.ngModelHigh == null)) && (attr.ngModelDisabled != null);
- range = (attr.ngModelSingle == null) && ((attr.ngModelLow != null) && (attr.ngModelHigh != null));
- refLow = 'ngModelLow';
- refHigh = 'ngModelHigh';
- if (!range) {
- minPtr.remove();
- maxPtr.remove();
- }
- else {
- singlePtr.remove();
- }
- if (!disabled) {
- disabledRange.remove();
- }
- else {
- scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
- scope.handleStyle = {left: disableWidth + 'px'};
- }
- minValue = parseFloat(scope.floor);
- maxValue = parseFloat(scope.ceiling);
- valueRange = maxValue - minValue;
- minOffset = 0;
- if (attr.width !== undefined) {
- maxOffset = attr.width;
- }
- else {
- if (elem[0].clientWidth !== 0) {
- maxOffset = elem[0].clientWidth;
- }
- else {
- maxOffset = sliderDefaultOptions.width;
- }
- }
- offsetRange = maxOffset - minOffset;
- //Key Down Event
- scope.keyDown = function(ev){
- if(ev.keyCode === 39){
- var elemLeft = $position.position(elem).left;
- if (newOffset){
- if(scope.ref === "ngModelLow"){
- newOffset1 = sliderDefaultOptions.step + newOffset1;
- newOffset = newOffset1;
- }
- else if(scope.ref === "ngModelHigh"){
- newOffset2 = sliderDefaultOptions.step + newOffset2;
- newOffset = newOffset2;
- }
- else{newOffset = sliderDefaultOptions.step + newOffset;}
- }
- else {
- if(range &&scope.ref === "ngModelLow"){
- return;
- }
- else {
- newOffset = sliderDefaultOptions.step + elemLeft;
- newOffset1 = newOffset2 = newOffset;
- }
- }
- }
- else if(ev.keyCode === 37){
- var ptrLeft = $position.position(singlePtr).left;
- if(newOffset){
- if (!(newOffset<=0)){
- if(scope.ref === "ngModelLow"){
- newOffset1 = newOffset1 - sliderDefaultOptions.step;
- newOffset = newOffset1;
- }
- else if(scope.ref === "ngModelHigh"){
- newOffset2 = newOffset2 - sliderDefaultOptions.step;
- newOffset = newOffset2;
- }
- else {
- newOffset = newOffset - sliderDefaultOptions.step;
- newOffset1 = newOffset2 = newOffset;
- }
- }
- }
- else {
- newOffset = ptrLeft - sliderDefaultOptions.step;
- }
- }
- if(newOffset>=0){
- scope.ptrOffset(newOffset);
- }
- };
- //Mouse Down Event
- scope.mouseDown = function(e, ref) {
- scope.ref = ref;
- evFlag = true;
- if (!range){
- if (newOffset)
- {
- start_x = e.clientX - newOffset;
- }
- else {
- start_x = e.clientX;
- }
- } else {
- if (scope.ref === refLow) {
- start_x = e.clientX - scope.minPtrOffset;
- }
- else {
- start_x = e.clientX - scope.maxPtrOffset;
- }
- }
- if (disabled) {
- scope.ref= 'ngModelDisabled';
- scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
- }
- };
- // Mouse Move Event
- scope.moveElem = function(ev) {
- if (evFlag) {
- var eventX;
- eventX = ev.clientX;
- newOffset = eventX - start_x;
- scope.ptrOffset(newOffset);
- }
- };
- scope.focus=function(ev,ref){
- console.log(ref);
- scope.ref=ref;
- }
- // Mouse Up Event
- scope.mouseUp = function(ev) {
- evFlag = false;
- minPtr.removeClass('dragging');
- maxPtr.removeClass('dragging');
- singlePtr.removeClass('dragging');
- $document.off('mousemove');
- };
- // key Up Event
- scope.keyUp = function(ev) {
- evFlag = false;
- minPtr.removeClass('dragging');
- maxPtr.removeClass('dragging');
- singlePtr.removeClass('dragging');
- $document.off('mousemove');
- };
- //Function to calculate the current PositionValue
- scope.calStep = function(value, precision, step, floor) {
- var decimals, remainder, roundedValue, steppedValue;
- if (floor === null) {
- floor = 0;
- }
- if (step === null) {
- step = 1 / Math.pow(10, precision);
- }
- remainder = (value - floor) % step;
- steppedValue = remainder > (step / 2) ? value + step - remainder : value - remainder;
- decimals = Math.pow(10, precision);
- roundedValue = steppedValue * decimals / decimals;
- return roundedValue.toFixed(precision);
- };
- //Function to calculate Offset Percent
- scope.percentOffset = function(offset) {
- return ((offset - minOffset) / offsetRange) * 100;
- };
- //Function to calculate Offset position
- scope.ptrOffset = function(newOffset){
- var newPercent, newValue;
- newOffset = Math.max(Math.min(newOffset, maxOffset), minOffset);
- newPercent = scope.percentOffset(newOffset);
- newValue = minValue + (valueRange * newPercent / 100.0);
- if (range) {
- var rangeSliderWidth;
- if (scope.ref === refLow) {
- scope.minHandleStyle = {left: newOffset + "px"};
- scope.minNewVal = newValue;
- scope.minPtrOffset = newOffset;
- minPtr.addClass('dragging');
- if (newValue > scope.maxNewVal) {
- scope.ref = refHigh;
- maxPtr[0].focus();
- scope.maxNewVal = newValue;
- scope.maxPtrOffset = newOffset;
- maxPtr.addClass('dragging');
- minPtr.removeClass('dragging');
- scope.maxHandleStyle = {left: newOffset + "px"};
- }
- }
- else {
- scope.maxHandleStyle = {left: newOffset + "px"};
- scope.maxNewVal = newValue;
- scope.maxPtrOffset = newOffset;
- maxPtr.addClass('dragging');
- if (newValue < scope.minNewVal) {
- scope.ref = refLow;
- minPtr[0].focus();
- scope.minVal = newValue;
- scope.minPtrOffset = newOffset;
- minPtr.addClass('dragging');
- maxPtr.removeClass('dragging');
- scope.minHandleStyle = {left: newOffset + "px"};
- }
- }
- rangeSliderWidth = parseInt(scope.maxPtrOffset) - parseInt(scope.minPtrOffset);
- scope.rangeStyle = {width: rangeSliderWidth + "px", left: scope.minPtrOffset + "px"};
- }
- else {
- if (disabled && newOffset > disableWidth) {
- scope.rangeStyle = {width: newOffset + "px", zIndex: 0};
- }
- else {
- singlePtr.addClass('dragging');
- scope.rangeStyle = {width: newOffset + "px"};
- }
- scope.handleStyle = {left: newOffset + "px"};
- }
- if ((scope.precision === undefined) || (scope.step === undefined)) {
- scope.precision = sliderDefaultOptions.precision;
- scope.step = sliderDefaultOptions.step;
- }
- newValue = scope.calStep(newValue, parseInt(scope.precision), parseFloat(scope.step), parseFloat(scope.floor));
- scope[scope.ref] = newValue;
- };
- }
- };
- }
- ]).directive('attSliderMin',[function()
- {
- return{
- require: '^attSlider',
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/slider/minContent.html'
- };
- }
- ]).directive('attSliderMax',[function()
- {
- return{
- require: '^attSlider',
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/slider/maxContent.html'
- };
- }
- ]);
-angular.module('att.abs.splitButtonDropdown', ['att.abs.utilities','att.abs.position'])
- .directive('attButtonDropdown', ['$document', '$parse', '$documentBind', '$timeout','$isElement', function ($document, $parse, $documentBind, $timeout,$isElement) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html',
- scope: {
- btnText: "@",
- btnType: "@",
- btnLink: "@",
- btnClick: "&",
- toggleTitle:"@",
- },
- controller: ['$scope', '$element', function ($scope, $element) {
-
- this.cSelected = 0;
- this.closeAndFocusDropdown = function () {
- if ($scope.isDropDownOpen) {
- $scope.$apply(function () {
- $scope.isDropDownOpen = false;
- angular.element($element[0].querySelector('a.dropdown-toggle'))[0].focus();
- });
- }
- };
-
- this.focusNext = function () {
- this.cSelected = this.cSelected + 1 >= this.childScopes.length ?($scope.cycleSelection === true ? 0 : this.childScopes.length-1): this.cSelected +1;
- this.childScopes[this.cSelected].sFlag = true;
- this.resetFlag(this.cSelected);
- };
-
- this.focusPrev = function () {
- this.cSelected = this.cSelected -1 < 0 ? ($scope.cycleSelection === true ? this.childScopes.length-1 : 0) : this.cSelected - 1 ;
- this.childScopes[this.cSelected].sFlag = true;
- this.resetFlag(this.cSelected);
- };
-
- this.childScopes = [];
- this.registerScope = function(childScope)
- {
- this.childScopes.push(childScope);
- };
-
- this.resetFlag = function(index){
- for(var i=0; i < this.childScopes.length; i++)
- {
- if(i !== index)
- {
- this.childScopes[i].sFlag = false;
- }
- }
- };
-
- }],
- link: function (scope, element, attr) {
- scope.isSmall = attr.small === "" ? true : false;
- scope.multiselect = attr.multiselect === ""? true : false;
- scope.cycleSelection = attr.cycleSelection === "" ? true : false;
- scope.isDropDownOpen = false;
- scope.isActionDropdown = false;
-
- if (!(scope.btnText)) {
- scope.isActionDropdown = true;
- }
-
- scope.clickFxn = function () {
- if (typeof scope.btnClick === "function" && !scope.btnLink) {
- scope.btnClick = $parse(scope.btnClick);
- scope.btnClick();
- }
- if(scope.multiselect === true)
- {
- scope.isDropDownOpen = false;
- }
- };
-
- scope.toggleDropdown = function () {
- if (!(scope.btnType === 'disabled')) {
- scope.isDropDownOpen = !scope.isDropDownOpen;
- if (scope.isDropDownOpen) {
- $timeout(function () {
- angular.element(element[0].querySelector('li'))[0].focus();
- });
- }
- }
- };
-
- scope.btnTypeSelector = function (directiveValue, attrValue) {
- if (directiveValue !== "") {
- scope.btnTypeFinal = directiveValue;
- } else {
- scope.btnTypeFinal = attrValue;
- }
- };
-
- var outsideClick = function(e) {
- var isElement = $isElement(angular.element(e.target), element.find('ul').eq(0), $document);
- if (!isElement) {
- scope.isDropDownOpen = false;
- scope.$apply();
- }
- };
-
- $documentBind.click('isDropDownOpen', outsideClick, scope);
-
- attr.$observe('btnType', function (val) {
- scope.btnType = val;
- });
- attr.$observe('attButtonDropdown', function (val) {
- attr.attButtonDropdown = val;
- scope.btnTypeSelector(attr.attButtonDropdown, scope.btnType);
- });
- }
- };
-
- }])
-
-.directive('attButtonDropdownItem', ['$location','keymap', function ($location,keymap) {
- return {
- restrict: 'EA',
- require: ['^attButtonDropdown','?ngModel'],
- replace: true,
- transclude: true,
- templateUrl:'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html', scope: {
- itemLink: "@"
- },
- link: function (scope, element, attr, ctrl) {
- var rootLink = angular.element(element[0].querySelector('a'));
- scope.sFlag = false;
- ctrl[0].registerScope(scope);
- var clickOnLink = function () {
- if (scope.itemLinkFinal) {
- $location.url(scope.itemLinkFinal);
- }
- };
-
- if(ctrl[1]){
- scope.isSelected = ctrl[1].$viewValue;
- }else{
- scope.isSelected = false;
- }
-
- element.bind('keydown', function(e) {
- if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
- e.preventDefault();
- e.stopPropagation();
- switch (e.keyCode) {
- case keymap.KEY.DOWN:
- ctrl[0].focusNext();
- break;
- case keymap.KEY.UP:
- ctrl[0].focusPrev();
- break;
- case keymap.KEY.ENTER:
- scope.selectItem();
- break;
- case keymap.KEY.ESC:
- ctrl[0].closeAndFocusDropdown();
- break;
- default:
- break;
- }
-
- }
- scope.$apply();
- });
-
- scope.selectItem = function()
- {
- if(ctrl[1]){
- scope.$evalAsync(function(){ctrl[1].$setViewValue(!ctrl[1].$viewValue)});
- }
- };
-
- }
- };
- }]);
-
-angular.module('att.abs.splitIconButton', ['att.abs.utilities'])
-.constant('iconStateConstants', {
- MIDDLE: 'middle',
- LEFT: 'left',
- RIGHT: 'right',
- NEXT_TO_DROPDOWN:'next-to-dropdown',
- LEFT_NEXT_TO_DROPDOWN:'left-next-to-dropdown',
- DIR_TYPE: {
- LEFT: 'left',
- RIGHT: 'right',
- BUTTON: 'button'
- },
- SPLIT_ICON_BTN_EVENT_EMITTER_KEY: 'splitIconButtonTap'
-})
-.directive('expandableLine', [function(){
- return {
- restrict: 'EA',
- replace: true,
- priority: 300,
- require: ['^attSplitIconButton', 'expandableLine'],
- controller: ['$scope', function($scope){
- $scope.isActive = false;
- this.setActiveState = function(isActive){
- $scope.isActive = isActive;
- };
- this.isActive = $scope.isActive;
- this.dirType = $scope.dirType;
- }],
- template: '<div ng-class="{\'expand-line-container\': !isActive, \'expand-line-container-active\': isActive}"> <div ng-class="{\'hovered-line\':isActive, \'vertical-line\':!isActive}"> </div></div>',
- scope:{
- dirType: '@'
- },
- link: function(scope,element,attr,ctrls) {
- var attSplitIconButtonCtrl = ctrls[0];
- var expandableLineCtrl = ctrls[1];
- attSplitIconButtonCtrl.addSubCtrl(expandableLineCtrl);
- }
- };
-}])
-.controller('AttSplitIconCtrl', ['$scope', function($scope){
- this.setType = function(type){
- $scope.type = type;
- };
- this.isDropdown = function(isDropdown){
- $scope.isDropdown = isDropdown;
- };
- this.dropDownClicked = function(){
- if($scope.dropDownClicked) {
- $scope.dropDownClicked();
- }
- };
- this.dirType = $scope.dirType;
-}])
-.directive('attSplitIcon', ['$document', '$timeout','iconStateConstants','$documentBind','events', 'keymap',
- function($document,$timeout,iconStateConstants,$documentBind, events, keymap){
- return {
- restrict: 'EA',
- replace: true,
- priority: 200,
- transclude: true,
- require: ['^attSplitIconButton','attSplitIcon'],
- templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html',
- scope:{
- icon: '@',
- iconTitle: '@title',
- hoverWatch: '=',
- dropDownWatch: '=',
- dirType: '@'
- },
- controller:'AttSplitIconCtrl',
- link: function(scope,element,attr,ctrls){
- var attSplitIconButtonCtrl = ctrls[0];
- var attSplitIconCtrl = ctrls[1];
- attSplitIconButtonCtrl.addSubCtrl(attSplitIconCtrl);
- scope.iconStateConstants = iconStateConstants;
- var currentIndex = 0;
- var isMyElement = false;
- var listElements;
- scope.isDropdown = false;
- scope.isDropdownOpen = false;
- var outsideClick = function(e) {
- if(scope.isDropdown){
- if (isMyElement) {
- isMyElement = false;
- scope.toggleDropdown();
- } else{
- scope.toggleDropdown(false);
- }
- scope.$apply();
- }
- };
- if(attr.dropDownId && attr.dropDownId !== ''){
- scope.dropDownId = attr.dropDownId;
- scope.isDropdown = true;
- }
- scope.$on(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, function(evnt, data){
- if(typeof data === 'boolean' && data) {
- scope.dropDownClicked();
- /*
- Check if the dropdown is open and if we are selecting one
- of the items, so that when pressing enter it will trigger it.
- */
- if(scope.isDropDownOpen) {
- listElements[currentIndex].eq(0).find('a')[0].click();
- }
- } else {
- var e = data;
- //Only trigger the keyboard event if the icon button is a dropdown type
- if(scope.isDropdown) {
- triggerKeyboardEvents(e);
- }
- }
- function triggerKeyboardEvents(e) {
- switch(e.which) {
- case (keymap.KEY.TAB):
- scope.toggleDropdown(false);
- scope.$digest();
- break;
- case (keymap.KEY.ESC):
- outsideClick();
- break;
- case (keymap.KEY.ENTER):
- if (scope.isDropDownOpen) {
- listElementsInit();
- }
- break;
- case (keymap.KEY.UP):
- e.preventDefault();
- events.stopPropagation(e);
- if(scope.isDropDownOpen) {
- scope.previousItemInDropdown();
- }
- break;
- case (keymap.KEY.DOWN):
- e.preventDefault();
- events.stopPropagation(e);
- //Dropdown is open and the user taps down again
- if(scope.isDropDownOpen) {
- //Now we need to go through the rows in the dropdown
- scope.nextItemInDropdown();
- } else {
- isMyElement = true;
- outsideClick();
- listElementsInit();
- }
- break;
- default:
- break;
- }
- }
- function listElementsInit() {
- if(listElements === undefined) {
- listElements = [];
- var liTemps = element.find('li');
- for(var i = 0; i < liTemps.length; i++) {
- listElements.push(liTemps.eq(i));
- }
- listElements[currentIndex].children().eq(0).addClass('selected-item');
- }
- }
- });
- scope.nextItemInDropdown = function(){
- if(listElements && currentIndex < listElements.length - 1){
- currentIndex++;
- listElements[currentIndex - 1].children().eq(0).removeClass('selected-item');
- listElements[currentIndex].children().eq(0).addClass('selected-item');
- }
- };
- scope.previousItemInDropdown = function(){
- if(currentIndex > 0) {
- currentIndex--;
- listElements[currentIndex].children().eq(0).addClass('selected-item');
-
- if(currentIndex + 1 < listElements.length)
- listElements[currentIndex + 1].children().eq(0).removeClass('selected-item');
- }
- };
- scope.$watch('isIconHovered', function(val) {
- scope.hoverWatch = val;
- });
- scope.$watch('type', function(val) {
- function toggleValues(isMiddle,isNextToDropDown,isRight,isLeft,isLeftNextDropdown){
- scope['isMiddle'] = isMiddle;
- scope['isNextToDropDown'] = isNextToDropDown;
- scope['isRight'] = isRight;
- scope['isLeft'] = isLeft;
- scope['isLeftNextDropdown'] = isLeftNextDropdown;
- };
- switch(val) {
- case (scope.iconStateConstants.MIDDLE):
- toggleValues(true,false,false,true,false);
- break;
- case (scope.iconStateConstants.LEFT):
- toggleValues(false,false,false,true,false);
- break;
- case (scope.iconStateConstants.RIGHT):
- toggleValues(false,false,true,false,false);
- break;
- case (scope.iconStateConstants.NEXT_TO_DROPDOWN):
- toggleValues(false,true,true,true,false);
- break;
- case (scope.iconStateConstants.LEFT_NEXT_TO_DROPDOWN):
- toggleValues(false,false,false,true,true);
- break;
- default:
- break;
- }
- });
- scope.dropDownClicked = function() {
- isMyElement = true;
- };
- scope.toggleDropdown = function(val) {
- if(val !== undefined) {
- scope.isDropDownOpen = val;
- } else {
- scope.isDropDownOpen = !scope.isDropDownOpen;
- }
- scope.dropDownWatch = scope.isDropDownOpen;
- };
- $documentBind.click('isDropdown', outsideClick, scope);
- }
- };
-}])
-.controller('AttSplitIconButtonCtrl',['$scope', 'iconStateConstants',function($scope,iconStateConstants){
- this.subCtrls = [];
- $scope.isLeftLineShown=true;
- $scope.isRightLineShown=true;
- $scope.childrenScopes = [];
- var that = this;
-
- function getDirIndex(dirType) {
- var index = -1;
- for(var c in that.subCtrls) {
- var ctrl = that.subCtrls[c];
- if(ctrl.dirType === dirType) {
- index = c;
- break;
- }
- }
- return index;
- }
- this.addSubCtrl = function(sub) {
- this.subCtrls.push(sub);
- };
- this.isLeftLineShown = function(isShown) {
- if(isShown === undefined) {
- return $scope.isLeftLineShown;
- } else {
- $scope.isLeftLineShown = isShown;
- }
- };
- this.isRightLineShown = function(isShown) {
- if(isShown === undefined) {
- return $scope.isRightLineShown;
- } else {
- $scope.isRightLineShown = isShown;
- }
- };
- this.setLeftLineHover = function(isHovered) {
- var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
-
- if($scope.isLeftLineShown && this.subCtrls[leftLineIndex] && this.subCtrls[leftLineIndex].setActiveState) {
- this.subCtrls[leftLineIndex].setActiveState(isHovered);
- }
- };
- this.setRightLineHover = function(isHovered) {
- var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
- if($scope.isRightLineShown && this.subCtrls[rightLineIndex] && this.subCtrls[rightLineIndex].setActiveState){
- this.subCtrls[rightLineIndex].setActiveState(isHovered);
- }
- };
- this.toggleLines = function(isHovered, buttonGroupCtrl, buttonCtrl, isDropDownOpen) {
- var subIconButtons = buttonGroupCtrl.subIconButtons;
- var subIconButtonsLength = subIconButtons.length;
- var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
- var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
- function noVerticalLineToggle() {
- for(var i =0; i < subIconButtonsLength; i++) {
- if(subIconButtons[i] === buttonCtrl) {
- if(i + 1 <= subIconButtonsLength - 1 && subIconButtons[i+1].isLeftLineShown()
- && subIconButtons[i+1].subCtrls[leftLineIndex]
- && subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState) {
- subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState(isHovered);
- }
- if(i - 1 >= 0 && subIconButtons[i-1].isRightLineShown()
- && subIconButtons[i-1].subCtrls[rightLineIndex]
- && subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState) {
- subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState(isHovered);
- }
- break;
- }
- }
- }
- if(isDropDownOpen) {
- /*
- If the button is next to the dropdown button then just keep the
- buttons left line or its left neighbors right line toggled on
- If the button is the dropdown button don't do anything
- else do things normally witht the button
- */
- /*if(subIconButtons[subIconButtonsLength-1] === buttonCtrl) {
-
- }
- else */
- if(subIconButtons[subIconButtonsLength-2]==buttonCtrl) {
- if(subIconButtons[subIconButtonsLength-2].isLeftLineShown()) {
- subIconButtons[subIconButtonsLength-2].subCtrls[leftLineIndex].setActiveState(isHovered);
- } else if(subIconButtonsLength - 3 >= 0) {
- if(subIconButtons[subIconButtonsLength-3].isRightLineShown()) {
- subIconButtons[subIconButtonsLength-3].subCtrls[rightLineIndex].setActiveState(isHovered);
- }
- }
- } else {
- noVerticalLineToggle();
-
- if($scope.isLeftLineShown) {
- this.subCtrls[leftLineIndex].setActiveState(isHovered);
- }
- if($scope.isRightLineShown) {
- this.subCtrls[rightLineIndex].setActiveState(isHovered);
- }
- }
- } else { // End of if(isDropDownOpen)
- //Handle Special cases where they aren't showing any vertical lines
- //and the dropdown isn't down
- if(!$scope.isLeftLineShown && !$scope.isRightLineShown) {
- noVerticalLineToggle();
- }
- if($scope.isLeftLineShown && this.subCtrls[leftLineIndex].setActiveState) {
- this.subCtrls[leftLineIndex].setActiveState(isHovered);
- }
- if($scope.isRightLineShown && this.subCtrls[rightLineIndex].setActiveState){
- this.subCtrls[rightLineIndex].setActiveState(isHovered);
- }
- }
- };
- this.setButtonType = function(type){
- var buttonIndex = getDirIndex(iconStateConstants.DIR_TYPE.BUTTON);
- if(this.subCtrls[buttonIndex] && this.subCtrls[buttonIndex].setType) {
- this.subCtrls[buttonIndex].setType(type);
- }
- };
-}])
-.directive('attSplitIconButton', ['$document', 'iconStateConstants', 'keymap',
- function($document, iconStateConstants, keymap){
- return {
- restrict: 'EA',
- replace: true,
- priority: 100,
- transclude: true,
- require: ['^attSplitIconButtonGroup', 'attSplitIconButton'],
- controller: 'AttSplitIconButtonCtrl',
- templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html',
- scope:{
- icon: '@',
- title: '@',
- dropDownId: '@'
- },
- link: function(scope,element,attr,ctrls) {
- if(!scope.title) {
- scope.title = scope.icon;
- }
- var attSplitButtonGroupCtrl = ctrls[0];
- var attSplitIconButtonCtrl = ctrls[1];
- attSplitButtonGroupCtrl.addIconButton(attSplitIconButtonCtrl);
- element.bind('keydown', function(e){
- //Check if the key is the up or down key
- if(e.which === keymap.KEY.ESC ||
- e.which === keymap.KEY.DOWN ||
- e.which === keymap.KEY.ENTER ||
- e.which === keymap.KEY.UP ||
- e.which === keymap.KEY.TAB ) {
- scope.clickHandler();
- scope.$broadcast(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, e);
- }
- });
- scope.dropDownWatch = false;
- scope.iconStateConstants = iconStateConstants;
- scope.clickHandler = function() {
- attSplitButtonGroupCtrl.hideLeftLineRightButton(attSplitIconButtonCtrl);
- };
- scope.$watch('isHovered', function(val){
- if(val) {
- attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
- } else{
- attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
- }
- });
- scope.$watch('dropDownWatch', function(val) {
- attSplitButtonGroupCtrl.isDropDownOpen = val;
- attSplitButtonGroupCtrl.toggleDropdownState(val);
- });
- }
- }
-}])
-.controller('AttSplitIconButtonGroupCtrl', ['$scope','iconStateConstants',function($scope,iconStateConstants){
- this.subIconButtons = [];
- this.addIconButton = function(iconButton){
- this.subIconButtons.push(iconButton);
- };
- this.isDropDownOpen = false;
- this.hideLeftLineRightButton = function(btn){
- var numButtons = this.subIconButtons.length;
- var buttonLeftOfRightMost = this.subIconButtons[numButtons - 2];
- var rightMostButton = this.subIconButtons[numButtons -1];
-
- if (btn != buttonLeftOfRightMost && btn != rightMostButton ){
- rightMostButton.setLeftLineHover(false);
- }
- };
- this.toggleDropdownState = function(isDropDownOpen){
- var numButtons = this.subIconButtons.length;
- if(numButtons > 2) {
- if(isDropDownOpen) {
- if(this.subIconButtons[numButtons - 2].isRightLineShown()) {
- this.subIconButtons[numButtons - 2].setRightLineHover(true);
- } else {
- this.subIconButtons[numButtons - 1].setLeftLineHover(true);
- }
- this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.NEXT_TO_DROPDOWN);
- } else {
- this.subIconButtons[numButtons - 1].setLeftLineHover(false);
- this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.MIDDLE);
- }
- } else {
- if(isDropDownOpen) {
- this.subIconButtons[0].setRightLineHover(true);
- this.subIconButtons[0].setButtonType(iconStateConstants.LEFT_NEXT_TO_DROPDOWN);
- } else {
- this.subIconButtons[0].setButtonType(iconStateConstants.LEFT);
- }
- }
- };
-}])
-.directive('attSplitIconButtonGroup', ['$document', '$timeout', 'iconStateConstants' ,function($document,$timeout,iconStateConstants){
- return {
- restrict: 'EA',
- replace: true,
- priority: 50,
- transclude: true,
- require: 'attSplitIconButtonGroup',
- controller: 'AttSplitIconButtonGroupCtrl',
- templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html',
- scope:{},
- link: function(scope,element,attr,ctrls){
- $timeout(initialize,100);
- function initialize(){
- var subIconButtonCtrls = ctrls.subIconButtons;
- var leftMostButtonIndex = 0;
- var rightMostButtonIndex =subIconButtonCtrls.length-1;
- //left most button config
- subIconButtonCtrls[leftMostButtonIndex].setButtonType(iconStateConstants.LEFT);
- subIconButtonCtrls[leftMostButtonIndex].isLeftLineShown(false);
- subIconButtonCtrls[leftMostButtonIndex].isRightLineShown(true);
- //right most button config
- subIconButtonCtrls[rightMostButtonIndex].setButtonType(iconStateConstants.RIGHT);
- subIconButtonCtrls[rightMostButtonIndex].isRightLineShown(false);
- subIconButtonCtrls[rightMostButtonIndex].isLeftLineShown(false);
- //middle buttons config
- if(rightMostButtonIndex >= 2) {
- var index = 1;
- while(index < rightMostButtonIndex) {
- subIconButtonCtrls[index].setButtonType(iconStateConstants.MIDDLE);
- subIconButtonCtrls[index].isRightLineShown(false);
- subIconButtonCtrls[index].isLeftLineShown(false);
- index++;
- }
- var skipIndex = 2;
- while(skipIndex <= rightMostButtonIndex){
- if(skipIndex == rightMostButtonIndex) {
- subIconButtonCtrls[skipIndex].isLeftLineShown(true);
- } else {
- subIconButtonCtrls[skipIndex].isRightLineShown(true);
- subIconButtonCtrls[skipIndex].isLeftLineShown(true);
- }
- skipIndex = skipIndex + 2;
- }
- }
- //reposition the dropdown
- var ulElem = element.find('ul');
- if(ulElem.length > 0) {
- var numButtons = rightMostButtonIndex+1;
- if(numButtons > 2) {
- var offset = (numButtons)*34-70+(numButtons/1.5) + 0.5;
- var offSetStr = offset+'px';
- angular.element(ulElem).css('left',offSetStr);
- angular.element(ulElem).css('border-top-left-radius','0px');
- } else {
- angular.element(ulElem).css('left','0px');
- }
- }
- }
- }
- }
-}]);
-
-angular.module('att.abs.stepSlider', ['att.abs.position'])
- .constant('sliderConstants', {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- SLIDER: {
- settings: {
- from: 1,
- to: 40,
- step: 1,
- smooth: true,
- limits: true,
- value: "3",
- dimension: "",
- vertical: false
- },
- className: "jslider",
- selector: ".jslider-"
- },
- EVENTS: {
- },
- COLORS: {
- GREEN: 'green',
- BLUE_HIGHLIGHT: 'blue',
- MAGENTA: 'magenta',
- GOLD: 'gold',
- PURPLE: 'purple',
- DARK_BLUE: 'dark-blue',
- REGULAR: 'regular',
- WHITE: 'white'
- }
- })
- .factory('utils', function () {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- return {
- offset: function (elm) {
- var rawDom = elm[0];
- var _x = 0;
- var _y = 0;
- var body = document.documentElement || document.body;
- var scrollX = window.pageXOffset || body.scrollLeft;
- var scrollY = window.pageYOffset || body.scrollTop;
- _x = rawDom.getBoundingClientRect().left + scrollX;
- _y = rawDom.getBoundingClientRect().top + scrollY;
- return {left: _x, top: _y};
- },
- roundUpToScale: function (mousePrc, scale, cutOffWidth, cutOffIndex) {
- var lowerVal;
- var higherVal;
- var newMousePrc;
- var middle;
-
- for (var index = 1; index < scale.length; index++) {
- lowerVal = scale[index - 1];
- higherVal = scale[index];
- middle = ((higherVal - lowerVal) * .5) + lowerVal;
- /*
- Handles a situation where the user clicks close to the start point of
- the slider but the pointer doesn't move
- */
- if ((lowerVal === 0 && mousePrc <= middle) || checkEquality(lowerVal, mousePrc)) {
- newMousePrc = lowerVal;
- break;
- }
- else if (lowerVal < mousePrc && (mousePrc < higherVal ||
- checkEquality(mousePrc, higherVal)))
- {
- newMousePrc = higherVal;
- break;
- }
- }
- //Check if the newMousePrc is <= the cuttOffPoint
- if (cutOffWidth && newMousePrc < cutOffWidth) {
- return scale[cutOffIndex];
- }
- else {
- return newMousePrc;
- }
- /*
- Checks to see if 2 points are so close that they are
- basically equal.
- */
- function checkEquality(point1, point2) {
- var precision = 0.1;
- if (Math.abs(point2 - point1) <= precision) {
- return true;
- }
- return false;
- }
- },
- valueForDifferentScale: function (from, to, prc, prcToValueMapper) {
- var decimalPrc = prc / 100;
- if (decimalPrc === 0) {
- return from;
- }
- return prcToValueMapper[prc];
- },
- /* converts the default value Kbps to Mbps or Gbps */
- convertToMbpsGbps: function (unitValue, unitLabel, configDecimalPlaces) {
- var defaultDecimalPlaces = 3; /* this is the default decimal places as per business requirements */
- if (configDecimalPlaces) {
- defaultDecimalPlaces = configDecimalPlaces;
- }
-
- if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Kbps')) {
- unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
- unitLabel = 'Mbps';
- } else if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Mbps')){
- unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
- unitLabel = 'Mbps';
- } else if (unitValue <= 1024 && angular.equals(unitLabel, 'Mbps')) {
- unitLabel = 'Kbps';
- } else {
- unitLabel = 'Kbps';
- }
-
- if (unitValue >= 1000000 && angular.equals(unitLabel, 'Kbps')) {
- unitValue = truncator((unitValue/1000000), defaultDecimalPlaces);
- unitLabel = 'Gbps';
- }
- return {
- unitValue: unitValue,
- unitLabel: unitLabel
- };
-
- function truncator(numToTruncate, intDecimalPlaces) {
- var cnvrtdNum = Math.pow(10, intDecimalPlaces);
- return ~~(numToTruncate * cnvrtdNum)/cnvrtdNum;
- }
- },
- getConversionFactorValue: function (value, conversion, firstDimension) {
- /*
- Loop through the conversion array and keep checking the
- startVal
- */
- if (value <= conversion[0].startVal) {
- return{
- scaledVal: value,
- scaledDimension: firstDimension
- };
- }
- var endIndex = 0;
- for (var index in conversion) {
- var c = conversion[index];
- if (value > c.startVal) {
- endIndex = index;
- }
- }
- var scaleFactor = conversion[endIndex].scaleFactor;
- var scaledVal = value / scaleFactor;
- var scaledDimension = conversion[endIndex].dimension;
- return {
- scaledVal: scaledVal,
- scaledDimension: scaledDimension
- };
- }
- };
- })
- .factory('sliderDraggable', ['utils', function (utils) {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- function Draggable() {
- this._init.apply(this, arguments);
- }
- Draggable.prototype.oninit = function () {
- };
- Draggable.prototype.events = function () {
- };
- Draggable.prototype.onmousedown = function () {
- this.ptr.css({position: "absolute"});
- };
- Draggable.prototype.onmousemove = function (evt, x, y) {
- this.ptr.css({left: x, top: y});
- };
- Draggable.prototype.onmouseup = function () {
- };
- Draggable.prototype.isDefault = {
- drag: false,
- clicked: false,
- toclick: true,
- mouseup: false
- };
- Draggable.prototype._init = function () {
- if (arguments.length > 0) {
- this.ptr = arguments[0];
- this.parent = arguments[2];
- if (!this.ptr) {
- return;
- }
- this.is = {};
- angular.extend(this.is, this.isDefault);
- var offset = utils.offset(this.ptr);
- this.d = {
- left: offset.left,
- top: offset.top,
- width: this.ptr[0].clientWidth,
- height: this.ptr[0].clientHeight
- };
- this.oninit.apply(this, arguments);
- this._events();
- }
- };
- Draggable.prototype._getPageCoords = function (event) {
- var value = {};
- if (event.targetTouches && event.targetTouches[0]) {
- value = {x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY};
- } else {
- value = {x: event.pageX, y: event.pageY};
- }
- return value;
- };
- Draggable.prototype._bindEvent = function (ptr, eventType, handler) {
- if (this.supportTouches_) {
- ptr[0].attachEvent(this.events_[ eventType ], handler);
- }
- else {
- if (ptr.bind) {
- ptr.bind(this.events_[ eventType ], handler);
- }
- }
- };
- Draggable.prototype._events = function () {
- var self = this;
- this.supportTouches_ = 'ontouchend' in document;
- this.events_ = {
- "click": this.supportTouches_ ? "touchstart" : "click",
- "down": this.supportTouches_ ? "touchstart" : "mousedown",
- "move": this.supportTouches_ ? "touchmove" : "mousemove",
- "up": this.supportTouches_ ? "touchend" : "mouseup",
- "mousedown": this.supportTouches_ ? "mousedown" : "mousedown"
- };
- var documentElt = angular.element(window.document);
- this._bindEvent(documentElt, "move", function (event) {
- if (self.is.drag) {
- event.stopPropagation();
- event.preventDefault();
- if (!self.parent.disabled) {
- self._mousemove(event);
- }
- }
- });
- this._bindEvent(documentElt, "down", function (event) {
- if (self.is.drag) {
- event.stopPropagation();
- event.preventDefault();
- }
- });
- this._bindEvent(documentElt, "up", function (event) {
- self._mouseup(event);
- });
- this._bindEvent(this.ptr, "down", function (event) {
- self._mousedown(event);
- return false;
- });
- this._bindEvent(this.ptr, "up", function (event) {
- self._mouseup(event);
- });
- this.events();
- };
- Draggable.prototype._mousedown = function (evt) {
- this.is.drag = true;
- this.is.clicked = false;
- this.is.mouseup = false;
- var coords = this._getPageCoords(evt);
- this.cx = coords.x - this.ptr[0].offsetLeft;
- this.cy = coords.y - this.ptr[0].offsetTop;
- angular.extend(this.d, {
- left: this.ptr[0].offsetLeft,
- top: this.ptr[0].offsetTop,
- width: this.ptr[0].clientWidth,
- height: this.ptr[0].clientHeight
- });
- if (this.outer && this.outer.get(0)) {
- this.outer.css({height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden"});
- }
- this.onmousedown(evt);
- };
- Draggable.prototype._mousemove = function (evt) {
- if (this.uid === 0) {
- return;
- }
- this.is.toclick = false;
- var coords = this._getPageCoords(evt);
- this.onmousemove(evt, coords.x - this.cx, coords.y - this.cy);
- };
- Draggable.prototype._mouseup = function (evt) {
- if (this.is.drag) {
- this.is.drag = false;
- if (this.outer && this.outer.get(0)) {
- if ($.browser.mozilla) {
- this.outer.css({overflow: "hidden"});
- } else {
- this.outer.css({overflow: "visible"});
- }
- if ($.browser.msie && $.browser.version === '6.0') {
- this.outer.css({height: "100%"});
- } else {
- this.outer.css({height: "auto"});
- }
- }
- this.onmouseup(evt);
- }
- };
- return Draggable;
- }])
- .factory('sliderPointer', ['sliderDraggable', 'utils', function (Draggable, utils) {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- function SliderPointer() {
- Draggable.apply(this, arguments);
- }
- SliderPointer.prototype = new Draggable();
- SliderPointer.prototype.oninit = function (ptr, id, _constructor) {
- this.uid = id;
- this.parent = _constructor;
- this.value = {};
- this.settings = angular.copy(_constructor.settings);
- };
- SliderPointer.prototype.onmousedown = function (evt) {
- var off = utils.offset(this.parent.domNode);
- var offset = {
- left: off.left,
- top: off.top,
- width: this.parent.domNode[0].clientWidth,
- height: this.parent.domNode[0].clientHeight
- };
- this._parent = {
- offset: offset,
- width: offset.width,
- height: offset.height
- };
- this.ptr.addClass("jslider-pointer-hover");
- this.setIndexOver();
- };
- SliderPointer.prototype.onmousemove = function (evt, x, y) {
- var coords = this._getPageCoords(evt);
- //val is the percent where the slider pointer is located
- var val = this.calc(coords.x);
- if (!this.parent.settings.smooth) {
- val = utils.roundUpToScale(val,
- this.parent.settings.scale,
- this.parent.settings.cutOffWidth,
- this.parent.settings.cutOffIndex);
- }
- var cutOffWidth = this.parent.settings.cutOffWidth;
- if (cutOffWidth && val < cutOffWidth) {
- val = cutOffWidth;
- }
- this._set(val);
- };
- SliderPointer.prototype.onmouseup = function (evt) {
- if (this.settings.callback && angular.isFunction(this.settings.callback)) {
- var val = this.parent.getValue();
- this.settings.callback.call(this.parent, val);
- }
- this.ptr.removeClass("jslider-pointer-hover");
- };
- SliderPointer.prototype.setIndexOver = function () {
- this.parent.setPointersIndex(1);
- this.index(2);
- };
- SliderPointer.prototype.index = function (i) {
- };
- SliderPointer.prototype.limits = function (x) {
- return this.parent.limits(x, this);
- };
- SliderPointer.prototype.calc = function (coords) {
- var diff = coords - this._parent.offset.left;
- var val = this.limits((diff * 100) / this._parent.width);
- return val;
- };
- SliderPointer.prototype.set = function (value, opt_origin) {
- this.value.origin = this.parent.round(value);
- this._set(this.parent.valueToPrc(value, this), opt_origin);
- };
- SliderPointer.prototype._set = function (prc, opt_origin) {
- if (!opt_origin) {
- this.value.origin = this.parent.prcToValue(prc);
- }
- this.value.prc = prc;
- //Sets the location of the SliderPointer
- this.ptr.css({left: prc + '%'});
- this.parent.redraw(this);
- };
- return SliderPointer;
- }])
- .factory('slider', ['sliderPointer', 'sliderConstants', 'utils', function (SliderPointer, sliderConstants, utils) {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- var cutOffDom;
- function Slider() {
- return this.init.apply(this, arguments);
- }
- function changeCutOffWidth(width) {
- cutOffDom.css('width', width);
- }
- ;
- Slider.prototype.changeCutOffWidth = changeCutOffWidth;
- Slider.prototype.init = function (inputNode, templateNode, settings) {
- this.settings = sliderConstants.SLIDER.settings;
- angular.extend(this.settings, angular.copy(settings));
- this.inputNode = inputNode;
- this.inputNode.addClass("ng-hide");
- this.settings.interval = this.settings.to - this.settings.from;
- if (this.settings.calculate && $.isFunction(this.settings.calculate)) {
- this.nice = this.settings.calculate;
- }
- if (this.settings.onstatechange && $.isFunction(this.settings.onstatechange)) {
- this.onstatechange = this.settings.onstatechange;
- }
- this.is = {init: false};
- this.o = {};
- this.create(templateNode);
- };
- Slider.prototype.create = function (templateNode) {
- var $this = this;
- this.domNode = templateNode;
- var off = utils.offset(this.domNode);
- var offset = {
- left: off.left,
- top: off.top,
- width: this.domNode[0].clientWidth,
- height: this.domNode[0].clientHeight
- };
- this.sizes = {domWidth: this.domNode[0].clientWidth, domOffset: offset};
- angular.extend(this.o, {
- pointers: {},
- labels: {
- 0: {
- o: angular.element(this.domNode.find('div')[5])
- },
- 1: {
- o: angular.element(this.domNode.find('div')[6])
- }
- },
- limits: {
- 0: angular.element(this.domNode.find('div')[3]),
- 1: angular.element(this.domNode.find('div')[5])
- }
- });
- angular.extend(this.o.labels[0], {
- value: this.o.labels[0].o.find("span")
- });
- angular.extend(this.o.labels[1], {
- value: this.o.labels[1].o.find("span")
- });
- if (!$this.settings.value.split(";")[1]) {
- this.settings.single = true;
- }
- var domNodeDivs = this.domNode.find('div');
- cutOffDom = angular.element(domNodeDivs[8]);
- if (cutOffDom && cutOffDom.css) {
- cutOffDom.css('width', '0%');
- }
- var pointers = [angular.element(domNodeDivs[1]), angular.element(domNodeDivs[2])];
- angular.forEach(pointers, function (pointer, key) {
- $this.settings = angular.copy($this.settings);
- var value = $this.settings.value.split(';')[key];
- if (value) {
- $this.o.pointers[key] = new SliderPointer(pointer, key, $this);
- var prev = $this.settings.value.split(';')[key - 1];
- if (prev && parseInt(value, 10) < parseInt(prev, 10)) {
- value = prev;
- }
- var value1 = value < $this.settings.from ? $this.settings.from : value;
- value1 = value > $this.settings.to ? $this.settings.to : value;
- $this.o.pointers[key].set(value1, true);
- if (key === 0) {
- $this.domNode.bind('mousedown', $this.clickHandler.apply($this));
- }
- }
- });
- this.o.value = angular.element(this.domNode.find("i")[2]);
- this.is.init = true;
- angular.forEach(this.o.pointers, function (pointer) {
- $this.redraw(pointer);
- });
- };
- Slider.prototype.clickHandler = function () {
- var self = this;
- return function (evt) {
- if (self.disabled) {
- return;
- }
- var className = evt.target.className;
- var targetIdx = 0;
- if (className.indexOf('jslider-pointer-to') > 0) {
- targetIdx = 1;
- }
- var _off = utils.offset(self.domNode);
- var offset = {
- left: _off.left,
- top: _off.top,
- width: self.domNode[0].clientWidth,
- height: self.domNode[0].clientHeight
- };
- targetIdx = 1;
- var targetPtr = self.o.pointers[targetIdx];
- targetPtr._parent = {offset: offset, width: offset.width, height: offset.height};
- targetPtr._mousemove(evt);
- targetPtr.onmouseup();
- return false;
- };
- };
- Slider.prototype.disable = function (bool) {
- this.disabled = bool;
- };
- Slider.prototype.nice = function (value) {
- return value;
- };
- Slider.prototype.onstatechange = function () {
- };
- Slider.prototype.limits = function (x, pointer) {
- if (!this.settings.smooth) {
- var step = this.settings.step * 100 / (this.settings.interval);
- x = Math.round(x / step) * step;
- }
- var another = this.o.pointers[1 - pointer.uid];
- if (another && pointer.uid && x < another.value.prc) {
- x = another.value.prc;
- }
- if (another && !pointer.uid && x > another.value.prc) {
- x = another.value.prc;
- }
- if (x < 0) {
- x = 0;
- }
- if (x > 100) {
- x = 100;
- }
- var val = Math.round(x * 10) / 10;
- return val;
- };
- Slider.prototype.setPointersIndex = function (i) {
- angular.forEach(this.getPointers(), function (pointer, i) {
- pointer.index(i);
- });
- };
- Slider.prototype.getPointers = function () {
- return this.o.pointers;
- };
- Slider.prototype.onresize = function () {
- var self = this;
- this.sizes = {
- domWidth: this.domNode[0].clientWidth,
- domHeight: this.domNode[0].clientHeight,
- domOffset: {
- left: this.domNode[0].offsetLeft,
- top: this.domNode[0].offsetTop,
- width: this.domNode[0].clientWidth,
- height: this.domNode[0].clientHeight
- }
- };
- angular.forEach(this.o.pointers, function (ptr, key) {
- self.redraw(ptr);
- });
- };
- Slider.prototype.update = function () {
- this.onresize();
- this.drawScale();
- };
- Slider.prototype.drawScale = function () {
- };
- Slider.prototype.redraw = function (pointer) {
- if (!this.settings.smooth) {
- var newMousePrc = utils.roundUpToScale(pointer.value.prc,
- this.settings.scale,
- this.settings.cutOffWidth,
- this.settings.cutOffIndex);
- pointer.value.origin = newMousePrc;
- pointer.value.prc = newMousePrc;
- }
-
- if (!this.is.init) {
- return false;
- }
- this.setValue();
- var width = this.o.pointers[1].value.prc;
- var newPos = {left: '0%', width: width + '%'};
- this.o.value.css(newPos);
- var htmlValue = this.nice(pointer.value.origin);
- var scaledDimension = this.settings.firstDimension;
- if (this.settings.stepWithDifferentScale && !this.settings.smooth) {
- htmlValue = utils.valueForDifferentScale(this.settings.from,
- this.settings.to, htmlValue, this.settings.prcToValueMapper);
- }
- //This is the base value before the conversion
- if (this.settings.realtimeCallback && angular.isFunction(this.settings.realtimeCallback)
- && this.settings.cutOffVal !== undefined && pointer.uid === 1) {
- this.settings.realtimeCallback(htmlValue);
- }
- //Need to change this to the correct value for the scale
- if (this.settings.conversion) {
- var conversionObj = utils.getConversionFactorValue(parseInt(htmlValue),
- this.settings.conversion,
- this.settings.firstDimension);
- htmlValue = conversionObj.scaledVal;
- scaledDimension = conversionObj.scaledDimension;
- }
-
- htmlValue = parseFloat(htmlValue);
- var tooltipLabel = utils.convertToMbpsGbps(htmlValue, scaledDimension, this.settings.decimalPlaces);
-
- this.o.labels[pointer.uid].value.html(tooltipLabel.unitValue + ' ' + tooltipLabel.unitLabel);
- //Top tooltip label
- this.redrawLabels(pointer);
- };
- Slider.prototype.redrawLabels = function (pointer) {
- function setPosition(label, sizes, prc) {
- sizes.margin = -sizes.label / 2;
- var domSize = self.sizes.domWidth;
- var label_left = sizes.border + sizes.margin;
- if (label_left < 0) {
- sizes.margin -= label_left;
- }
- if (sizes.border + sizes.label / 2 > domSize) {
- sizes.margin = 0;
- sizes.right = true;
- } else
- sizes.right = false;
- //Adjust the tooltip location
- sizes.margin = -((label.o[0].clientWidth / 2) - label.o[0].clientWidth / 20);
- label.o.css({left: prc + "%", marginLeft: sizes.margin, right: "auto"});
- if (sizes.right)
- label.o.css({left: "auto", right: 0});
- return sizes;
- }
- var self = this;
- var label = this.o.labels[pointer.uid];
- var prc = pointer.value.prc;
- var sizes = {
- label: label.o[0].offsetWidth,
- right: false,
- border: (prc * domSize) / 100
- };
- var another_label = null;
- var another = null;
- if (!this.settings.single) {
- another = this.o.pointers[1 - pointer.uid];
- another_label = this.o.labels[another.uid];
- switch (pointer.uid) {
- case 0:
- if (sizes.border + sizes.label / 2 > another_label.o[0].offsetLeft - this.sizes.domOffset.left) {
- another_label.o.css({visibility: "hidden"});
- another_label.value.html(this.nice(another.value.origin));
- label.o.css({visibility: "hidden"});
- prc = (another.value.prc - prc) / 2 + prc;
- if (another.value.prc !== pointer.value.prc) {
- label.value.html(this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin));
- sizes.label = label.o[0].clientWidth;
- sizes.border = (prc * domSize) / 100;
- }
- } else {
- another_label.o.css({visibility: "visible"});
- }
- break;
- case 1:
- if (sizes.border - sizes.label / 2 < another_label.o[0].offsetLeft - this.sizes.domOffset.left + another_label.o[0].clientWidth) {
- another_label.o.css({visibility: "hidden"});
- another_label.value.html(this.nice(another.value.origin));
- label.o.css({visibility: "visible"});
- prc = (prc - another.value.prc) / 2 + another.value.prc;
- if (another.value.prc !== pointer.value.prc) {
- label.value.html(this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin));
- sizes.label = label.o[0].clientWidth;
- sizes.border = (prc * domSize) / 100;
- }
- } else {
- another_label.o.css({visibility: "visible"});
- }
- break;
- }
- }
- sizes = setPosition(label, sizes, prc);
- var domSize = self.sizes.domWidth;
- //This is the 0th pointer
- if (another_label) {
- sizes = {
- label: another_label.o[0].clientWidth,
- right: false,
- border: (another.value.prc * this.sizes.domWidth) / 100
- };
- sizes = setPosition(another_label, sizes, another.value.prc);
- }
- };
- Slider.prototype.redrawLimits = function () {
- if (this.settings.limits) {
- var limits = [true, true];
- for (var key in this.o.pointers) {
- if (!this.settings.single || key === 0) {
- var pointer = this.o.pointers[key];
- var label = this.o.labels[pointer.uid];
- var label_left = label.o[0].offsetLeft - this.sizes.domOffset.left;
- var limit = this.o.limits[0];
- if (label_left < limit[0].clientWidth)
- limits[0] = false;
- limit = this.o.limits[1];
- if (label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth)
- limits[1] = false;
- }
- }
- for (var i = 0; i < limits.length; i++) {
- if (limits[i]){
- angular.element(this.o.limits[i]).addClass("animate-show");}
- else{
- angular.element(this.o.limits[i]).addClass("animate-hidde");}
- }
- }
- };
- Slider.prototype.setValue = function () {
- var value = this.getValue();
- this.inputNode.attr("value", value);
- this.onstatechange.call(this, value, this.inputNode);
- };
- Slider.prototype.getValue = function () {
- if (!this.is.init){
- return false;}
- var $this = this;
- var value = "";
- angular.forEach(this.o.pointers, function (pointer, key) {
- if (pointer.value.prc !== undefined && !isNaN(pointer.value.prc)) {
- var pointerPrc = pointer.value.prc;
- var myValue = $this.prcToValue(pointerPrc);
- if (!$this.settings.smooth) {
- var myValue = utils.valueForDifferentScale($this.settings.from,
- $this.settings.to,
- pointerPrc,
- $this.settings.prcToValueMapper);
- }
- value += (key > 0 ? ";" : "") + myValue;
- }
- });
- return value;
- };
- Slider.prototype.getPrcValue = function () {
- if (!this.is.init)
- return false;
- var value = "";
- $.each(this.o.pointers, function (i) {
- if (this.value.prc !== undefined && !isNaN(this.value.prc))
- value += (i > 0 ? ";" : "") + this.value.prc;
- });
- return value;
- };
- Slider.prototype.prcToValue = function (prc) {
- var value;
- if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
- var h = this.settings.heterogeneity;
- var _start = 0;
- var _from = this.settings.from;
- for (var i = 0; i <= h.length; i++) {
- var v;
- if (h[i]){
- v = h[i].split("/");}
- else{
- v = [100, this.settings.to];}
- if (prc >= _start && prc <= v[0]) {
- value = _from + ((prc - _start) * (v[1] - _from)) / (v[0] - _start);
- }
- _start = v[0];
- _from = v[1];
- }
- }
- else {
- value = this.settings.from + (prc * this.settings.interval) / 100;
- }
- var roundedValue = this.round(value);
- return roundedValue;
- };
- Slider.prototype.valueToPrc = function (value, pointer) {
- var prc;
- if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
- var h = this.settings.heterogeneity;
- var _start = 0;
- var _from = this.settings.from;
- for (var i = 0; i <= h.length; i++) {
- var v;
- if (h[i])
- v = h[i].split("/");
- else
- v = [100, this.settings.to];
- if (value >= _from && value <= v[1]) {
- prc = pointer.limits(_start + (value - _from) * (v[0] - _start) / (v[1] - _from));
- }
- _start = v[0];
- _from = v[1];
- }
- } else {
- prc = pointer.limits((value - this.settings.from) * 100 / this.settings.interval);
- }
- return prc;
- };
- Slider.prototype.round = function (value) {
- value = Math.round(value / this.settings.step) * this.settings.step;
- if (this.settings.round){
- value = Math.round(value * Math.pow(10, this.settings.round)) / Math.pow(10, this.settings.round);}
- else{
- value = Math.round(value);}
- return value;
- };
- return Slider;
- }])
- .directive('attStepSlider', [
- '$compile', '$templateCache', '$timeout', '$window', 'slider', 'sliderConstants', 'utils',
- function (compile, templateCache, timeout, win, Slider, sliderConstants, utils) {
- /*
- The MIT License (MIT)
- Copyright (c) 2013 Julien Valéry
- */
- var templateUrl = 'app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html';
- return {
- restrict: 'AE',
- require: '?ngModel',
- scope: {
- options: '=',
- cutOff: '='
- },
- priority: 1,
- templateUrl: templateUrl,
- link: function (scope, element, attrs, ngModel) {
- if (!ngModel)
- return;
- scope.mainSliderClass = 'step-slider';
- element.after(compile(templateCache.get(templateUrl))(scope, function (clonedElement, scope) {
- scope.tmplElt = clonedElement;
- }));
- ngModel.$render = function () {
- if (ngModel.$viewValue.split && ngModel.$viewValue.split(";").length === 1) {
- ngModel.$viewValue = '0;' + ngModel.$viewValue;
- } else if (typeof (ngModel.$viewValue) === 'number') {
- ngModel.$viewValue = '0;' + ngModel.$viewValue;
- }
- if (!ngModel.$viewValue && ngModel.$viewValue !== 0) {
- return;
- }
- if (typeof (ngModel.$viewValue) === 'number') {
- ngModel.$viewValue = '' + ngModel.$viewValue;
- }
- if (scope.slider) {
- var firstPointer = '0';
- scope.slider.getPointers()[0].set(firstPointer, true);
- if (ngModel.$viewValue.split(";")[1]) {
- var value = ngModel.$viewValue.split(";")[1];
- if (value.length >= 4) {
- value = value.substring(0, 2);
- }
- if (!scope.options.realtime)
- scope.options.callback(parseFloat(ngModel.$viewValue.split(";")[1]));
- scope.slider.getPointers()[1].set(ngModel.$viewValue.split(";")[1], true);
- }
- }
- };
- var init = function () {
- scope.from = '' + scope.options.from;
- scope.to = '' + scope.options.to;
- if (scope.options.calculate && typeof scope.options.calculate === 'function') {
- scope.from = scope.options.calculate(scope.from);
- scope.to = scope.options.calculate(scope.to);
- }
- scope.showDividers = scope.options.showDividers;
- scope.COLORS = sliderConstants.COLORS;
- scope.sliderColor = scope.options.sliderColor;
- if (!scope.sliderColor)
- scope.sliderColor = sliderConstants.COLORS.REGULAR;
- var scaleArray = scope.options.scale;
- /* Make a copy of the scaleArray before converting it to percentage for the bars */
- var nonPercentScaleArray = [];
- /* Define variable for displaying lower range values */
- var scaledUpValueArray=[];
- /* Create Mapper for the percentage to value */
- var prcToValueMapper = {};
- for (var i in scaleArray) {
- var s = scaleArray[i];
- nonPercentScaleArray.push(s);
- }
- function addScaleArrayStartAndEnd() {
- if (scaleArray[0] !== 0) {
- scaleArray.splice(0, 0, 0);
- }
- if (scaleArray[scaleArray.length - 1] !== 100) {
- scaleArray.splice(scaleArray.length, 0, 100);
- }
- }
- function convertScaleArrayToPercentage() {
- if (scaleArray[scaleArray.length - 1] !== scope.options.to) {
- scaleArray.splice(scaleArray.length, 0, scope.options.to);
- }
-
- if(scope.options.displayScaledvalues){
- for(var i in scaleArray){
- scaledUpValueArray.push(Math.log2(scaleArray[i]));
- }
- var maxScaledUpValue=scaledUpValueArray[scaledUpValueArray.length-1];
- }
-
- for (var i in scaleArray) {
- var prcValue;
- var fromValueCheck = (scaleArray[i] / scope.options.from);
- var toValueCheck = (scaleArray[i] / scope.options.to);
-
- if (scope.options.displayScaledvalues){
- prcValue = (scaledUpValueArray[i] /maxScaledUpValue)*100;
- } else {
- prcValue = ((scaleArray[i] - scope.options.from) / (scope.options.to - scope.options.from)) * 100;
- }
-
- var realValue = scaleArray[i];
-
- if (toValueCheck === 1) {
- prcValue = 100;
- }
- else if (fromValueCheck === 1) {
- prcValue = 0;
- }
- scaleArray[i] = prcValue;
- prcToValueMapper['' + prcValue] = realValue;
- }
- }
- if ((scope.options.from !== 0 || scope.options.to !== 100)
- && scope.options.smooth) {
- /*
- scale array is in real values.
- */
- addScaleArrayStartAndEnd();
- scope.options.stepWithDifferentScale = true;
- }
- else if ((scope.options.from !== 0 || scope.options.to !== 100)
- && !scope.options.smooth) {
- /*
- Case for different from and to values other than 0 and 100
- so we have to do some different calculations
- */
- scope.options.stepWithDifferentScale = true;
- convertScaleArrayToPercentage();
- addScaleArrayStartAndEnd();
- }
- else {
- /*
- This is the normal case where the from and to values are 0 and
- 100 respectively.
- */
- //Check that the scale starts at 0 and 100
- convertScaleArrayToPercentage();
- addScaleArrayStartAndEnd();
- }
- var decimalPlaces = 0;
- if (scope.options.decimalPlaces) {
- decimalPlaces = scope.options.decimalPlaces;
- }
- //Modify the endDimension based on whether converison was passed in
- //Also change the toStr value to scale to the last factor
- scope.endDimension = scope.options.dimension;
- if (scope.options.conversion) {
- //Get the dimension of the last conversion
- var lastIndex = scope.options.conversion.length - 1;
- var lastDimension = scope.options.conversion[lastIndex].dimension;
- var lastScaleFactor = scope.options.conversion[lastIndex].scaleFactor;
- scope.endDimension = ' ' + lastDimension;
-
- var toVal = (scope.to / lastScaleFactor).toFixed(decimalPlaces);
- scope.toStr = toVal;
- } else {
- scope.toStr = scope.options.to;
- }
-
- var tooltipLabel = utils.convertToMbpsGbps(scope.toStr, scope.endDimension, scope.options.decimalPlaces);
- scope.toStr = tooltipLabel.unitValue;
- scope.endDimension = ' ' + tooltipLabel.unitLabel;
-
- var OPTIONS = {
- from: scope.options.from,
- to: scope.options.to,
- step: scope.options.step,
- smooth: scope.options.smooth,
- limits: true,
- stepWithDifferentScale: scope.options.stepWithDifferentScale,
- round: scope.options.round || false,
- value: ngModel.$viewValue,
- scale: scope.options.scale,
- nonPercentScaleArray: nonPercentScaleArray,
- prcToValueMapper: prcToValueMapper,
- firstDimension: scope.options.dimension,
- decimalPlaces: decimalPlaces,
- conversion: scope.options.conversion,
- realtimeCallback: scope.options.callback
- };
- if (angular.isFunction(scope.options.realtime)) {
- OPTIONS.realtimeCallback = function (value) {
- ngModel.$setViewValue(value);
- scope.options.callback(value);
- };
- }
- else {
- OPTIONS.callback = forceApply;
- }
- OPTIONS.calculate = scope.options.calculate || undefined;
- OPTIONS.onstatechange = scope.options.onstatechange || undefined;
- timeout(function () {
- var scaleDiv = scope.tmplElt.find('div')[7];
- if (!OPTIONS.conversion) {
- scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-left', '10px');
- scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-right', '15px');
- }
- scope.slider = angular.element.slider(element, scope.tmplElt, OPTIONS);
- angular.element(scaleDiv).html(scope.generateScale());
- scope.drawScale(scaleDiv);
- initListener();
- scope.$watch('options.disable', function (val) {
- if (scope.slider) {
- scope.tmplElt.toggleClass('disabled', val);
- scope.slider.disable(val);
- }
- });
- scope.$watch('cutOff', function (cutOffVal) {
- if (cutOffVal && cutOffVal > 0) {
- var cutOffPrc = (cutOffVal - scope.slider.settings.from) / (scope.slider.settings.to -
- scope.slider.settings.from);
- cutOffPrc = cutOffPrc * 100;
- scope.isCutOffSlider = true;
- scope.slider.settings.cutOffWidth = cutOffPrc;
- //cutOffVal is the actual value of the cutoff point
- scope.cutOffVal = cutOffVal;
- if (scope.options.conversion) {
- var convertedVal = utils.getConversionFactorValue(cutOffVal, scope.options.conversion, scope.options.dimension);
- convertedVal.scaledVal = parseFloat(convertedVal.scaledVal).toFixed(scope.options.decimalPlaces);
- scope.cutOffVal = convertedVal.scaledVal + ' ' + convertedVal.scaledDimension;
- }
- scope.slider.settings.cutOffVal = cutOffVal;
- //Calculate the cutOff percentage
- scope.slider.changeCutOffWidth(cutOffPrc + '%');
- var scale = scope.slider.settings.nonPercentScaleArray;
- //Calculate where the cutOff point in relation to the scale array
- for (var i in scale) {
- if (i >= 1) {
- var lowerVal = scale[i - 1];
- var higherVal = scale[i];
- if (cutOffVal > lowerVal && cutOffVal <= higherVal) {
- scope.slider.settings.cutOffIndex = i;
- }
- }
- }
- } else {
- scope.slider.settings.cutOffVal = 0;
- }
- });
- });
- };
- function initListener() {
- angular.element(win).bind('resize', function (event) {
- scope.slider.onresize();
- });
- }
- scope.generateScale = function () {
- if (scope.options.scale && scope.options.scale.length > 0) {
- var str = "";
- var s = scope.options.scale;
- var position = 'left';
- for (var i = 0; i < s.length; i++) {
- if (i !== 0 && i !== s.length - 1) {
- var scaledPosition = ((s[i] - scope.from) / (scope.to - scope.from)) * 100;
- if (scope.options.stepWithDifferentScale && !scope.options.smooth) {
- scaledPosition = s[i];
- }
- str += '<span style="' + position + ': ' + scaledPosition + '%"></span>';
- }
- }
- return str;
- } else
- return "";
- return "";
- };
- scope.drawScale = function (scaleDiv) {
- angular.forEach(angular.element(scaleDiv).find('ins'), function (scaleLabel, key) {
- scaleLabel.style.marginLeft = -scaleLabel.clientWidth / 2;
- });
- };
- var forceApply = function (value) {
- var val = value.split(";")[1];
- scope.$apply(function () {
- ngModel.$setViewValue(parseInt(val));
- });
- if (scope.options.callback) {
- scope.options.callback(parseInt(val));
- }
- };
- scope.$watch('options', function (value) {
- init();
- });
- angular.element.slider = function (inputElement, element, settings) {
- if (!element.data('jslider'))
- element.data('jslider', new Slider(inputElement, element, settings));
- var sliderObj = element.data('jslider');
- return sliderObj;
- };
- }
- };
- }]);
-angular.module('att.abs.steptracker', ['att.abs.transition'])
- .directive('steptracker', ['$timeout', function ($timeout) {
- return {
- // This allows dev's clickHandler to cancel an operation
- priority: 100,
- scope: {
- sdata: "=sdata",
- cstep: "=currentStep",
- clickHandler: '=?',
- disableClick: '=?'
- },
- restrict: 'EA',
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/step-tracker.html',
- link: function (scope, elem) {
- if (scope.disableClick === undefined) {
- scope.disableClick = false;
- }
- $timeout(function () {
- if (scope.cstep < 1) {
- scope.cstep = 1;
- }
- else if (scope.cstep > scope.sdata.length) {
- scope.cstep = scope.sdata.length;
- }
- var divs = elem.find('div');
- var slidertracks = [];
- for (var i in divs) {
- if (divs.eq(i)[0]) {
- var el = divs.eq(i)[0].className;
- if (el.indexOf('track ng-scope') > -1) {
- slidertracks.push(divs.eq(i));
- }
- }
- }
- var currentPage,totalPage,currentTrack = updateCurrentTrack(scope.cstep);
- function updateCurrentTrack(step) {
- // Always return the step-1 because array starts at 0
- return angular.element(slidertracks[step - 1]);
- }
- function updateTrackWidth() {
- if (scope.cstep > 0 && scope.cstep <= scope.sdata.length - 1 && currentPage > 0) {
- var newWidth = ((currentPage / totalPage) * 100) + "%";
- currentTrack = updateCurrentTrack(scope.cstep);
- currentTrack.css('width', newWidth);
- }
- }
- function updatePages() {
- if (scope.cstep <= scope.sdata.length) {
- currentPage = scope.sdata[scope.cstep - 1]['currentPage'];
- totalPage = scope.sdata[scope.cstep - 1]['totalPages'];
- }
- }
- // dynamically add width for steps, depending on the number of steps.
- scope.set_width = function (indexval) {
- var setwidth = (100 / (scope.sdata.length - 1)) + "%";
- // skip last element and add width for all other element
- if ((scope.sdata.length - 1) > indexval) {
- return {'width': setwidth};
- }
- };
- scope.$watch('sdata', function () {
- updatePages();
- var prevStep = scope.cstep;
- // Before anything, ensure currentPage is never below 1
- if (currentPage < 1) {
- currentPage = 1;
- if (scope.cstep !== 1) {
- // Decrease step, current track width is 0%, new step width updates
- scope.cstep--;
- updatePages();
- }
- }
- // Move to next step, reset currentPage, totalPage, and ensure previous steps are completed
- if (currentPage > totalPage) {
- if (scope.cstep > scope.sdata.length - 1) {
- scope.cstep++;
- return;
- } else {
- currentPage = totalPage;
- updateTrackWidth();
- scope.cstep++;
- updatePages();
- updateTrackWidth();
- }
- }
- if (currentPage < 1 && prevStep === scope.cstep) {
- currentPage = 1;
- if (scope.cstep > 1) {
- scope.cstep--;
- scope.sdata[scope.cstep - 1]['currentPage'] = scope.sdata[scope.cstep - 1]['totalPages'];
- scope.sdata[scope.cstep]['currentPage'] = 1;
- }
- }
- updateTrackWidth();
- }, true);
- //add the active class for current step
- scope.activestep = function (index) {
- return (index === scope.cstep - 1);
- };
- //add the done class for finished step
- scope.donesteps = function (index) {
- return (index < scope.cstep - 1);
- };
- //add the last class for final step
- scope.laststep = function (index) {
- return (index === scope.sdata.length - 1);
- };
- scope.isIncomplete = function (index) {
- if (index === scope.cstep - 1) {
- return false;
- }
- if (index >= 0 && index < scope.sdata.length - 1) {
- var step = scope.sdata[index];
- return (step['currentPage'] <= step['totalPages']);
- }
- };
- //click event
- scope.stepclick = function ($event, steps) {
- // If we are decreasing steps, reset all currentPage counts to 1
- if (steps < scope.cstep) {
- for (var i = scope.cstep - 1; i > steps; i--) {
- scope.sdata[i]['currentPage'] = 1;
- }
- scope.sdata[steps]['currentPage']--;
- }
- if (angular.isFunction(scope.clickHandler)) {
- scope.clickHandler($event, steps);
- }
- scope.cstep = steps + 1;
- // In the case we decremented previously from this step, we need to reset currentpage to default
- if (scope.cstep <= scope.sdata.length && scope.sdata[scope.cstep]['currentPage'] < 1) {
- scope.sdata[scope.cstep]['currentPage'] = 1;
- }
- updatePages();
- updateTrackWidth();
- };
- }, 100);
- }
- };
- }
- ])
- .constant('timelineConstants', {
- STEP_TYPE: {
- ALERT: 'alert',
- COMPLETED: 'completed',
- CANCELLED: 'cancelled'
- }
- })
- .controller('AttTimelineCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
- var timelineBarCtrls = [];
- var timelineDotCtrls = [];
- this.numSteps = 0;
- this.isAlternate = function () {
- return $scope.alternate;
- };
- this.addTimelineBarCtrls = function (t) {
- timelineBarCtrls.push(t);
- };
- this.addTimelineDotCtrls = function (b) {
- timelineDotCtrls.push(b);
- };
- $timeout(init, 200);
- function init() {
- function compare(a, b) {
- if (a.order < b.order) {
- return -1;
- }
- if (a.order > b.order) {
- return 1;
- }
- return 0;
- }
- timelineDotCtrls.sort(compare);
- timelineBarCtrls.sort(compare);
- if ($scope.$parent.animate) {
- animateSequence();
- }
- $scope.$watch('trigger', function (val) {
- if (val) {
- $scope.resetTimeline();
- } else {
- $scope.$parent.animate = false;
- }
- });
- }
- function animateSequence() {
- var dotsDuration = .25;
- var timelineBarProgressDuration = .25;
- if (typeof $scope.barAnimateDuration === 'number') {
- timelineBarProgressDuration = $scope.barAnimateDuration;
- }
- var start = createAnimation(0, timelineBarProgressDuration);
- function setToInactiveStates() {
- for (var i in timelineDotCtrls) {
- var dotCtrl = timelineDotCtrls[i];
- if (i % 2 === 0) {
- dotCtrl.unhoveredStateForBelow(.25);
- } else {
- dotCtrl.unhoveredStateForAbove(.25);
- }
- if (dotCtrl.isStop()) {
- break;
- }
- }
- }
- function createAnimation(i, duration) {
- if (i === 0) {
- return function () {
- if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
- timelineBarCtrls[i].isCancelled(true);
- }
- timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
- };
- } else if (i === timelineBarCtrls.length - 1) {
- return function () {
- //Removes the bolded text from the start
- if (timelineDotCtrls[0].isCurrentStep()) {
- timelineDotCtrls[0].isCurrentStep(false);
- }
- if (timelineDotCtrls[i].isStop()) {
- timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
- timelineDotCtrls[i].isCurrentStep(true);
- } else {
- timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
- timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
- }
- timelineDotCtrls[i].expandedAnimate(dotsDuration);
- $timeout(function () {
- setToInactiveStates();
- }, 500);
- };
- }
- //End Dot
- else if (i === timelineBarCtrls.length) {
- return function () {
- //Removes the bolded text from the start
- if (timelineDotCtrls[0].isCurrentStep()) {
- timelineDotCtrls[0].isCurrentStep(false);
- }
- timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
- timelineDotCtrls[i].expandedAnimate(dotsDuration);
- timelineDotCtrls[i].isCurrentStep(true);
- $timeout(function () {
- setToInactiveStates();
- }, 500);
- };
- }
- else {
- return function () {
- //Removes the bolded text from the start
- if (timelineDotCtrls[0].isCurrentStep()) {
- timelineDotCtrls[0].isCurrentStep(false);
- }
- if (timelineDotCtrls[i].isStop()) {
- timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
- timelineDotCtrls[i].expandedAnimate(dotsDuration);
- timelineDotCtrls[i].isCurrentStep(true);
- $timeout(function () {
- setToInactiveStates();
- }, 500);
- } else {
- if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
- timelineBarCtrls[i].isCancelled(true);
- }
- timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
- timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
- timelineDotCtrls[i].expandedAnimate(dotsDuration);
- }
- };
- }
- }
- start();
- }
- }])
- .directive('attTimeline', ['$timeout', '$compile', function ($timeout, $compile) {
- return {
- restrict: 'EA',
- replace: true,
- scope: {
- steps: '=',
- trigger: '=',
- alternate: '=',
- barAnimateDuration: '='
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timeline.html',
- controller: 'AttTimelineCtrl',
- link: function (scope, element, attrs, ctrl) {
- var init = function () {
- var steps = scope.steps;
- var middleSteps = [];
- for (var i = 1; i < steps.length; i++) {
- var aStep = steps[i];
- middleSteps.push(aStep);
- }
- scope.middleSteps = middleSteps;
- //Used in calculating the width of the loading bars
- ctrl.numSteps = steps.length - 1;
- };
- init();
- //Recompile in case of scope changes
- scope.resetTimeline = function () {
- scope.animate = true;
- $compile(element)(scope);
- };
- }
- };
- }])
- .controller('TimelineBarCtrl', ['$scope', function ($scope) {
- this.type = 'timelinebar';
- this.order = parseInt($scope.order);
- this.animate = function (callback, duration) {
- $scope.loadingAnimation(callback, duration);
- };
- this.isCancelled = function (isCancelled) {
- $scope.isCancelled = isCancelled;
- };
- }])
- .directive('timelineBar', ['animation', '$progressBar', function (animation, $progressBar) {
- return {
- restrict: 'EA',
- replace: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineBar.html',
- scope: {
- order: '@'
- },
- require: ['^attTimeline', 'timelineBar'],
- controller: 'TimelineBarCtrl',
- link: function (scope, element, attrs, ctrls) {
- var attTimelineCtrl = ctrls[0];
- var timelineBarCtrl = ctrls[1];
- attTimelineCtrl.addTimelineBarCtrls(timelineBarCtrl);
- scope.isCompleted = true;
- var widthPerc = (100 / attTimelineCtrl.numSteps) - 3;
- element.css('width', widthPerc + '%');
- var elem = element.find('div').eq(0);
- animation.set(elem, {opacity: 0.0});
- var updateCallback = function (selfElement) {
- animation.set(elem, {opacity: 1.0});
- animation.set(elem, {
- scaleX: selfElement.progress(),
- transformOrigin: "left"
- });
- };
- scope.loadingAnimation = $progressBar(updateCallback);
- }
- };
- }])
- .controller('TimelineDotCtrl', ['$scope', '$timeout', 'timelineConstants', function ($scope, $timeout, timelineConstants) {
- this.type = 'dot';
- this.order = parseInt($scope.order);
- var self = this;
- $timeout(function () {
- if (self.order !== 0) {
- if (self.order % 2 !== 0) {
- $scope.initializeAboveForAnimation();
- }
- else {
- $scope.initializeBelowForAnimation();
- }
- }
- });
- this.expandedAnimate = function (duration) {
- $scope.setColor();
- $scope.expandedAnimate(duration);
- if (self.order !== 0 && !$scope.isStepsLessThanFive()) {
- if (self.order % 2 !== 0) {
- $scope.expandContentForAbove(duration);
- } else {
- $scope.expandContentForBelow(duration);
- }
- }
- };
- this.unhoveredStateForAbove = function (duration) {
- $scope.unhoveredStateForAbove(duration);
- };
- this.unhoveredStateForBelow = function (duration) {
- $scope.unhoveredStateForBelow(duration);
- };
- this.shrinkAnimate = function (duration) {
- $scope.shrinkAnimate(duration);
- };
- this.setExpanded = function () {
- $scope.setSize(3);
- };
- this.isStop = function () {
- return $scope.isStop;
- };
- this.isCancelled = function () {
- return ($scope.type === timelineConstants.STEP_TYPE.CANCELLED);
- };
- this.isAlert = function () {
- return ($scope.type === timelineConstants.STEP_TYPE.ALERT);
- };
- //Sets the bolded text
- this.isCurrentStep = function (isCurrentStep) {
- if (isCurrentStep !== undefined) {
- $scope.isCurrentStep = isCurrentStep;
- }
- return $scope.isCurrentStep;
- };
- }])
- .directive('timelineDot', ['animation', 'timelineConstants',
- function (animation, timelineConstants) {
- return {
- restrict: 'EA',
- replace: true,
- scope: {
- order: '@',
- title: '@',
- description: '@',
- by: '@',
- date: '@',
- type: '@'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineDot.html',
- require: ['^attTimeline', 'timelineDot'],
- controller: 'TimelineDotCtrl',
- link: function (scope, element, attrs, ctrls) {
- var attTimelineCtrl = ctrls[0];
- var timelineDotCtrl = ctrls[1];
- attTimelineCtrl.addTimelineDotCtrls(timelineDotCtrl);
- scope.numSteps = attTimelineCtrl.numSteps + 1;
- scope.isCurrentStep = false;
- scope.isCompleted = false;
- scope.isStop = false;
- if (scope.type === timelineConstants.STEP_TYPE.ALERT || scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
- scope.isStop = true;
- }
- scope.isInactive = true;
- var divs = element.find('div');
- var biggerCircleElem = divs.eq(0);
- var expandableCircleElem = divs.eq(2);
- var infoboxElem = divs.eq(3);
- var titleElem = divs.eq(5);
- var contentElem = divs.eq(6);
- var dateElem = divs.eq(9);
- function isEmptyStep() {
- if (!scope.description && !scope.by && !scope.date) {
- return true;
- }
- return false;
- }
- scope.isStepsLessThanFive = function () {
- if (scope.numSteps < 5) {
- return true;
- }
- return false;
- };
- scope.titleMouseover = function (num) {
- if (!scope.isStepsLessThanFive() && !isEmptyStep()) {
- if (num === 1 && scope.order % 2 === 0) {
- scope.expandContentForBelow(.25);
- }
- if (num === 2 && scope.order % 2 !== 0) {
- scope.expandContentForAbove(.25);
- }
- }
- };
- scope.titleMouseleave = function () {
- if (scope.order % 2 === 0) {
- scope.unhoveredStateForBelow(.25);
- }
- else {
- scope.unhoveredStateForAbove(.25);
- }
- };
- scope.initializeAboveForAnimation = function () {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.set(contentElem, {opacity: 0});
- animation.set(dateElem, {opacity: 0});
- if (!isEmptyStep()) {
- var yOffset = contentElem[0].offsetHeight + dateElem[0].offsetHeight;
- animation.set(titleElem, {'top': yOffset});
- }
- }
- };
- scope.expandContentForAbove = function (duration) {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.to(titleElem, duration, {'top': 0});
- animation.to(contentElem, duration, {opacity: 1});
- animation.to(dateElem, duration, {opacity: 1});
- }
- };
- scope.unhoveredStateForAbove = function (duration) {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.set(contentElem, {opacity: 0});
- animation.set(dateElem, {opacity: 1});
- var yOffset = contentElem[0].offsetHeight;
- animation.to(titleElem, duration, {'top': yOffset});
- }
- };
- scope.initializeBelowForAnimation = function () {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.set(contentElem, {height: '0%', opacity: 0, top: '-20px'});
- animation.set(dateElem, {opacity: 0});
- }
- };
- scope.expandContentForBelow = function (duration) {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.set(dateElem, {opacity: 1});
- animation.to(contentElem, duration, {height: 'auto', opacity: 1, top: '0px'});
- }
- };
- scope.unhoveredStateForBelow = function (duration) {
- if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
- animation.to(contentElem, duration, {height: '0%', opacity: 0, top: '-20px', position: 'relative'});
- animation.set(dateElem, {opacity: 1});
- }
- };
- /*Default Initializaztion*/
- //If the info box is above and the description and date and by are empty then we have do reset its position
- if (isEmptyStep() && (scope.order % 2 !== 0 && attTimelineCtrl.isAlternate())) {
- infoboxElem.css('top', '-47px');
- }
- //Check if the order is odd and set the appropiate above or below and other effects
- if (scope.order % 2 === 0 || !attTimelineCtrl.isAlternate()) {
- scope.isBelowInfoBoxShown = true;
- }
- else {
- scope.isBelowInfoBoxShown = false;
- }
- //modify some css for steps less than 5 and not alternating
- if (scope.isStepsLessThanFive() && !attTimelineCtrl.isAlternate()) {
- animation.set(dateElem, {marginTop: 10});
- }
- //For IE 8 fix
- animation.set(biggerCircleElem, {opacity: '.5'});
- //shrink the expandableCircle to we can expand it later
- animation.set(expandableCircleElem, {opacity: '0.0'});
- animation.set(expandableCircleElem, {scale: .10});
- if (scope.order === 0) {
- animation.set(expandableCircleElem, {opacity: '1.0'});
- animation.set(expandableCircleElem, {scale: 1});
- animation.set(biggerCircleElem, {scale: 3});
- scope.isCurrentStep = true;
- scope.isInactive = false;
- scope.isCompleted = true;
- }
- scope.setColor = function () {
- scope.isInactive = false;
- if (scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
- scope.isCancelled = true;
- }
- else if (scope.type === timelineConstants.STEP_TYPE.ALERT) {
- scope.isAlert = true;
- }
- else {
- scope.isCompleted = true;
- }
- if (!scope.$phase) {
- scope.$apply();
- }
- };
- scope.setSize = function (size) {
- animation.set(biggerCircle, {scale: size});
- };
- scope.setExpandedCircle = function () {
- animation.set(expandableCircleElem, {opacity: '1.0'});
- animation.set(expandableCircleElem, {scale: 1});
- };
- scope.expandedAnimate = function (duration) {
- animation.to(biggerCircleElem, duration, {scale: 3});
- animation.set(expandableCircleElem, {opacity: '1.0'});
- animation.to(expandableCircleElem, duration, {scale: 1});
- };
- scope.shrinkAnimate = function (duration) {
- animation.to(biggerCircleElem, duration, {scale: 1});
- };
- }
- };
- }]);
-angular.module('att.abs.table', ['att.abs.utilities'])
-.constant('tableConfig', {
- //true for descending & false for ascending
- defaultSortPattern: false,
- highlightSearchStringClass: 'tablesorter-search-highlight'
-})
-
-.directive('attTable', ['$filter', function($filter) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: {
- tableData: "=",
- viewPerPage: "=",
- currentPage: "=",
- totalPage: "=",
- searchCategory: "=",
- searchString: "="
- },
- require: 'attTable',
- templateUrl: 'app/scripts/ng_js_att_tpls/table/attTable.html',
- controller: ['$scope', function($scope) {
- this.headers = [];
- this.currentSortIndex = null;
- this.setIndex = function(headerScope) {
- this.headers.push(headerScope);
- };
- this.getIndex = function(headerName) {
- for (var i = 0; i < this.headers.length; i++) {
- if (this.headers[i].headerName === headerName) {
- return this.headers[i].index;
- }
- }
- return null;
- };
- this.sortData = function(columnIndex, reverse) {
- $scope.$parent.columnIndex = columnIndex;
- $scope.$parent.reverse = reverse;
- this.currentSortIndex = columnIndex;
- $scope.currentPage = 1;
- this.resetSortPattern();
- };
- this.getSearchString = function() {
- return $scope.searchString;
- };
- this.resetSortPattern = function() {
- for(var i = 0; i < this.headers.length; i++) {
- var currentScope = this.headers[i];
- if(currentScope.index !== this.currentSortIndex) {
- currentScope.resetSortPattern();
- }
- }
- };
- }],
- link: function(scope, elem, attr, ctrl) {
- scope.searchCriteria = {};
- scope.$watchCollection('tableData', function(value) {
- if(value && !isNaN(value.length)) {
- scope.totalRows = value.length;
- }
- });
- scope.$watch('currentPage', function(val) {
- scope.$parent.currentPage = val;
- });
- scope.$watch('viewPerPage', function(val) {
- scope.$parent.viewPerPage = val;
- });
- scope.$watch(function() {
- return scope.totalRows / scope.viewPerPage;
- }, function(value) {
- if(!isNaN(value)) {
- scope.totalPage = Math.ceil(value);
- scope.currentPage = 1;
- }
- });
- var searchValCheck = function(val){
- if(angular.isDefined(val) && val !== null && val !== ""){
- return true;
- }
- };
- var setSearchCriteria = function(v1,v2){
- if(searchValCheck(v1) && searchValCheck(v2)){
- var index = ctrl.getIndex(v2);
- scope.searchCriteria = {};
- if (index !== null) {
- scope.searchCriteria[index] = v1;
- }
- }else if(searchValCheck(v1) && (!angular.isDefined(v2) || v2 === null || v2 === "")){
- scope.searchCriteria = {
- $: v1
- };
- }else {
- scope.searchCriteria = {};
- }
- };
- scope.$watch('searchCategory', function(newVal,oldVal) {
- if(newVal !== oldVal){
- setSearchCriteria(scope.searchString,newVal);
- }
- });
- scope.$watch('searchString', function (newVal,oldVal) {
- if(newVal !== oldVal){
- setSearchCriteria(newVal,scope.searchCategory);
- }
- });
- scope.$watchCollection('searchCriteria', function(val) {
- scope.$parent.searchCriteria = val;
- scope.totalRows = scope.tableData && ($filter('filter')(scope.tableData, val, false)).length || 0;
- scope.currentPage = 1;
- });
- }
- };
-}])
-
-.directive('attTableRow', [function() {
- return {
- restrict: 'EA',
- compile: function (elem, attr) {
- if (attr.type === 'header') {
- elem.find('tr').eq(0).addClass('tablesorter-headerRow');
- } else if (attr.type === 'body') {
- var html = elem.children();
- if(attr.rowRepeat){
- if (attr.trackBy) {
- html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by " + attr.trackBy));
- } else {
- html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by $index"));
- }
- }
- html.attr('ng-class', "{'alt-row': $even,'normal-row': $odd}");
- elem.append(html);
- }
- }
- };
-}])
-
-.directive('attTableHeader', ['tableConfig', function(tableConfig) {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- scope: {
- sortable: '@',
- defaultSort: '@',
- index: '@key'
- },
- require: '^attTable',
- templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableHeader.html',
- link: function(scope, elem, attr, ctrl) {
- var reverse = tableConfig.defaultSortPattern;
- scope.headerName = elem.text();
- scope.sortPattern = null;
- ctrl.setIndex(scope);
-
- scope.$watch(function() {
- return elem.text();
- }, function(value) {
- scope.headerName = value;
- });
- scope.sort = function(sortType) {
- if(typeof sortType === 'boolean') {
- reverse = sortType;
- }
- ctrl.sortData(scope.index, reverse);
- scope.sortPattern = reverse ? 'descending' : 'ascending';
- reverse = !reverse;
- };
- scope.$watch(function() {
- return ctrl.currentSortIndex;
- }, function(value) {
- if (value !== scope.index) {
- scope.sortPattern = null;
- }
- });
-
- if (scope.sortable === undefined || scope.sortable === 'true' || scope.sortable === true) {
- scope.sortable = 'true';
- } else if (scope.sortable === false || scope.sortable === 'false') {
- scope.sortable = 'false';
- }
-
- if(scope.sortable !== 'false') {
- if(scope.defaultSort === 'A' || scope.defaultSort === 'a') {
- scope.sort(false);
- } else if(scope.defaultSort === 'D' || scope.defaultSort === 'd') {
- scope.sort(true);
- }
- }
- scope.resetSortPattern = function() {
- reverse = tableConfig.defaultSortPattern;
- };
- }
- };
-}])
-
-.directive('attTableBody', ['$filter', '$timeout', 'tableConfig', function($filter, $timeout, tableConfig) {
- return {
- restrict: 'EA',
- require: '^attTable',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableBody.html',
- link: function (scope, elem, attr, ctrl) {
- var highlightSearchStringClass = tableConfig.highlightSearchStringClass;
- var searchString = "";
- var wrapElement = function (elem) {
- var text = elem.text();
- elem.html($filter('highlight')(text, searchString, highlightSearchStringClass));
- };
- var traverse = function (elem) {
- var innerHtml = elem.children();
- if (innerHtml.length > 0) {
- for (var i = 0; i < innerHtml.length; i++) {
- traverse(innerHtml.eq(i));
- }
- } else {
- wrapElement(elem);
- return;
- }
- };
- var clearWrap = function (elem) {
- var elems = elem.find('*');
- for (var i = 0; i < elems.length; i++) {
- if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
- var text = elems.eq(i).text();
- elems.eq(i).replaceWith(text);
- }
- }
- };
- $timeout(function () {
- var actualHtml = elem.children();
- scope.$watch(function () {
- return ctrl.getSearchString();
- }, function (val) {
- searchString = val;
- clearWrap(elem);
- if (actualHtml.length > 0) {
- traverse(elem);
- } else {
- wrapElement(elem);
- }
- });
- }, 50);
- }
- };
-}]);
-
-angular.module('att.abs.tableMessages', ['att.abs.utilities'])
- .constant('messageConstants', {
- TABLE_MESSAGE_TYPES: {
- noMatching: 1,
- errorLoading: 2,
- magnifySearch: 3,
- isLoading: 4},
- USER_MESSAGE_TYPES: {
- success: 1,
- error: 0
- }
- })
- .directive('attTableMessage', ['messageConstants', function(messageConstants) {
- return {
- restrict: 'AE',
- replace: true,
- transclude: true,
- scope: {
- msgType: '=',
- onRefreshClick: '&'
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html',
- link: function(scope) {
- scope.messageConstants = messageConstants;
- scope.refreshAction = function(evt) {
- scope.onRefreshClick(evt);
- };
- }
- };
- }]).directive('attUserMessage', ['messageConstants', '$timeout', 'DOMHelper', function(messageConstants, $timeout, DOMHelper) {
- return {
- restrict: 'AE',
- replace: true,
- transclude: true,
- scope: {
- thetitle: '=',
- type: '=',
- message: '=',
- trigger: '='
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html',
- link: function(scope, element) {
- var prevActiveElement = undefined;
- var firstElement = undefined;
- scope.messageConstants = messageConstants;
-
- $timeout(function() {
- firstElement = DOMHelper.firstTabableElement(element[0]);
- }, 10);
-
-
- scope.$watch('trigger', function() {
- if (scope.trigger) {
- prevActiveElement = document.activeElement;
- if (angular.isDefined(firstElement)) {
- firstElement.focus();
- }
- } else {
- if (angular.isDefined(prevActiveElement)) {
- prevActiveElement.focus();
- }
- }
- })
-
-
- }
- };
- }]);
-angular.module('att.abs.tabs', ['att.abs.utilities'])
- .directive('attTabs', function () {
- return{
- restrict: 'EA',
- transclude: false,
- replace: true,
- scope: {
- tabs: "=title"
- },
- controller: ['$scope', function ($scope) {
- this.getData = function () {
- return $scope.tabs;
- };
- this.onClickTab = function (tab) {
- $scope.currentTab = tab.url;
- return $scope.currentTab;
- };
- this.isActiveTab = function (tab) {
- return (tab === $scope.currentTab);
- };
- }],
- link: function (scope) {
- for (var i = 0; i < scope.tabs.length; i++) {
- if ((scope.tabs[i].selected) && (scope.tabs[i].url)) {
- scope.currentTab = scope.tabs[i].url;
- }
- }
- }
- };
- })
- .directive('floatingTabs', function () {
- return {
- require: '^attTabs',
- restrict: 'EA',
- transclude: false,
- replace: true,
- scope: {
- size: "@"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/tabs/floatingTabs.html',
- link: function (scope, elem, attr, attTabsCtrl) {
- scope.tabs = attTabsCtrl.getData();
- scope.onClickTab = attTabsCtrl.onClickTab;
- scope.isActiveTab = attTabsCtrl.isActiveTab;
- }
- };
- })
- .directive('simplifiedTabs', function () {
- return {
- require: '^attTabs',
- restrict: 'EA',
- transclude: false,
- replace: true,
- scope: {
- ctab: "=ngModel"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html',
- link: function (scope, elem, attr, attTabsCtrl) {
- scope.tabs = attTabsCtrl.getData();
- scope.clickTab = function (tab) {
- scope.ctab = tab.id;
- return scope.ctab;
- };
- scope.isActive = function (tab) {
- return (tab === scope.ctab);
- };
- }
- };
- })
- .directive('genericTabs', function () {
- return {
- require: '^attTabs',
- restrict: 'EA',
- transclude: false,
- replace: true,
- scope: {
- ctab: "=ngModel"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/tabs/genericTabs.html',
- link: function (scope, elem, attr, attTabsCtrl) {
- scope.tabs = attTabsCtrl.getData();
- scope.clickTab = function (tab) {
- scope.ctab = tab.id;
- return scope.ctab;
- };
- scope.isActive = function (tab) {
- return (tab === scope.ctab);
- };
- }
- };
- })
- .directive('skipNavigation', function(){
- return{
- link: function(scope,elem,attr){
- elem.bind('click', function(){
- var skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
- (angular.element(skiptoBody)).attr('tabindex',-1);
- skiptoBody.focus();
- });
-
- }
- }
- })
- .directive('parentTab', [function () {
- return {
- restrict: 'EA',
- scope: {
- menuItems: '=',
- activeSubMenu: '=',
- activeMenu: '='
- },
- controller: ['$scope', function ($scope) {
- $scope.megaMenu = $scope.menuItems;
- $scope.megaMenuTab;
- $scope.megaMenuHoverTab;
- this.setMenu = function () {
- $scope.menuItems = $scope.megaMenu;
- $scope.activeSubMenu.scroll=false;
- for (var i = 0; i < $scope.menuItems.length; i++) {
- if ($scope.menuItems[i].active) {
- $scope.activeMenu = $scope.menuItems[i];
- }
- }
- this.setSubMenuStatus(false);
- $scope.$apply();
- };
- this.setActiveMenu = function () {
- if (!($scope.megaMenuTab === undefined || $scope.megaMenuTab === null)) {
- $scope.menuItems = [$scope.megaMenuTab];
- $scope.megaMenuTab.scroll = true;
- $scope.activeMenu = {};
- $scope.activeSubMenu = $scope.megaMenuTab;
- this.setSubMenuStatus(true);
- }
- else{
- for(var i=0; i<$scope.menuItems.length; i++){
- ($scope.menuItems[i].active = false);
- if($scope.menuItems[i].subItems)
- for(var j=0; j<$scope.menuItems[i].subItems.length; j++){
- $scope.menuItems[i].subItems[j].active = false;
- };
- };
- $scope.menuItems=$scope.megaMenu;
- }
- $scope.$apply();
- };
- var checkSubMenuStatus = false;
- this.setSubMenuStatus = function (value) {
- checkSubMenuStatus = value;
- };
- this.getSubMenuStatus = function () {
- return checkSubMenuStatus;
- };
- this.setActiveMenuTab = function (tab) {
- $scope.megaMenuTab = tab;
- };
- this.setActiveMenuHoverTab = function (tab) {
- $scope.megaMenuHoverTab = tab;
- };
- this.setActiveSubMenuTab = function () {
- $scope.megaMenuTab = $scope.megaMenuHoverTab;
- };
- this.resetMenuTab = function () {
- $scope.megaMenuTab = undefined;
- };
- this.clearSubMenu = function () {
- /* Clears Sub-tems when focus shifts from Sub-menu to Mega menu*/
- $scope.$evalAsync(function(){
- $scope.megaMenuTab = undefined;
- $scope.megaMenuHoverTab = undefined;
- })
- };
- }]
- };
- }])
- .directive('parentmenuTabs', [function () {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- scope: {
- megaMenu: '@',
- menuItems: '='
- },
- controller: ['$scope', function ($scope) {
- this.getMenu = function () {
- return $scope.menuItems;
- };
- this.setMenu = function (menuItem) {
- $scope.menuItems = menuItem;
- };
- }],
- templateUrl: 'app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html'
- };
- }])
-
- .directive('menuTabs', ["$window", "$document",'events','keymap', function (win, $document, events, keymap) {
- return {
- restrict: 'EA',
- transclude: true,
- replace: true,
- require: ['^?parentTab', '^?parentmenuTabs'],
- scope: {
- activeMenu: "=",
- menuItem: "=",
- subMenu: "@",
- subItemActive: "@",
- tabName: "=?",
- tabUrl: "=?"
- },
- templateUrl: function (element, attrs) {
- if (attrs.megaMenu) {
- return 'app/scripts/ng_js_att_tpls/tabs/menuTab.html';
- }
- else {
- return 'app/scripts/ng_js_att_tpls/tabs/submenuTab.html';
- }
- },
- link: function (scope, elem, attr, ctrl) {
- var parentCtrl = ctrl[0];
- var parentmenuCtrl = ctrl[1];
- scope.clickInactive = true;
- scope.showHoverChild = function (e) {
- scope.clickInactive = false;
- scope.hoverChild = ctrl[0].getSubMenuStatus();
- if (e.type === "mouseover" && ctrl[0].getSubMenuStatus())
- {
- //scope.showChildren(e);
- }
-
- };
- scope.showChildren = function (e) {
- scope.parentMenuItems = parentmenuCtrl.getMenu();
- for (var i = 0; i < scope.parentMenuItems.length; i++) {
- scope.parentMenuItems[i].active = false;
- if (scope.parentMenuItems[i].subItems) {
- for (var j = 0; j < scope.parentMenuItems[i].subItems.length; j++) {
- scope.parentMenuItems[i].subItems[j].active = false;
- }
- }
- scope.clickInactive = true;
- }
- scope.menuItem.active = true;
- scope.activeMenu = scope.menuItem;
- e.stopPropagation();
- };
- scope.$watch("subItemActive", function (value) {
- if (value === "true" && scope.subMenu === 'true') {
- parentCtrl.setActiveMenuHoverTab(scope.menuItem);
- }
- });
- scope.showMenuClick = function (e) {
- parentCtrl.setActiveMenuTab(scope.menuItem);
- e.stopPropagation();
- };
- scope.showSubMenuClick = function (e) {
- parentCtrl.setActiveSubMenuTab();
- e.stopPropagation();
- };
- scope.resetMenu = function (e) {
- parentCtrl.resetMenuTab();
- e.stopPropagation();
- };
- function debounce(method, delay) {
- clearTimeout(method._tId);
- method._tId = setTimeout(function () {
- parentCtrl.setMenu();
- }, delay);
- }
- function debounce1(method, delay) {
- clearTimeout(method._tId);
- method._tId = setTimeout(function () {
- parentCtrl.setActiveMenu();
- }, delay);
- }
- $document.bind('scroll', function () {
- /* if (win.pageYOffset === 0) {
- debounce(parentCtrl.setMenu, 100);
- }
- else if (win.pageYOffset > 1 && win.pageYOffset < 1500) {
- debounce1(parentCtrl.setActiveMenu, 100);
- }*/
- });
- elem.bind('keydown', function(evt){
- if (!(evt.keyCode)){
- evt.keyCode = evt.which;
- }
- if(evt.keyCode !== keymap.KEY.TAB){
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
-
- switch (evt.keyCode) {
- case keymap.KEY.ESC:
- var skiptoBody;
- if (!(elem.attr('mega-menu'))) {
- if (elem.attr("sub-menu") === "true") {
- /* condition true when user navigates through Sub-menu*/
-
- skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
- (angular.element(skiptoBody)).attr('tabindex',-1);
- skiptoBody.focus();
- }
- else if (elem.attr("sub-menu") === undefined) {
- skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
- (angular.element(skiptoBody)).attr('tabindex',-1);
- skiptoBody.focus();
- }
- }
- else
- {
- if (elem.attr("menu-item") === "item") {
- /* Works when user on Mega menu*/
-
- skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
- (angular.element(skiptoBody)).attr('tabindex',-1);
- skiptoBody.focus();
- }
- }
- break;
- case keymap.KEY.RIGHT:
- if (!(elem.attr('mega-menu'))) {
- var el = angular.element(elem)[0];
- if (elem.attr("sub-menu") === "true") {
- /* condition true when user navigates through Sub-menu*/
- if(el.nextElementSibling === null){ break;}
- if(el.nextElementSibling){
- el.nextElementSibling.querySelector("a").focus();
- }
- else{
- do{
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if (el.querySelector("a") == null){}
- else{
- el.querySelector("a").focus();}
- }
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
- }
- else if (elem.attr("sub-menu") === undefined) {
- if(el.nextElementSibling === null) break;
- if(el.nextElementSibling){
- el.nextElementSibling.querySelector("a").focus();
- }
- else{
- do{
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if (el.querySelector("a") == null){}
- else{
- el.querySelector("a").focus();}
- }
-
- }
- }
- }
- else
- {
- if (elem.attr("menu-item") === "item") {
- /* When user navigates through on Mega menu*/
-
- var el = angular.element(elem)[0];
-
- if(el.nextElementSibling){
- if(el.nextElementSibling.querySelector("span") == null){
- }
- else {
- el.nextElementSibling.querySelector("span").focus();
- }
- }
- else{
- do{
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if(el.querySelector("span") === null){}
- else {
- el.querySelector("span").focus();
- }
- }
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
- }
- }
- break;
- case keymap.KEY.DOWN:
-
-
- if (elem.attr('mega-menu')) {
- /* When user navigates from top menu to Sub-menu*/
- angular.element(elem)[0].querySelectorAll(".megamenu__items")[0].querySelector("a").focus();
- }
- else if(elem.attr("sub-menu") === undefined) {
- /*When user navigates within Sub Items*/
- var el = document.activeElement;
- if(el.nextElementSibling === null) break;
- if(el.nextElementSibling) {
- el.nextElementSibling.focus();
- }else{
- do {
- if (el && el.nextSibling){
- el = el.nextSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'A');
- if(el.attributes !== null){
- el.focus();
- }
- events.stopPropagation(evt);
- }
-
- }
- else if (elem.attr("sub-menu")=== "true" ) {
- /* condition true when user navigates from sub menu to Sub Item*/
- var childItems = angular.element(elem)[0].querySelector("span").querySelector('a');
- if(childItems === null) break;
- childItems.focus();
- }
- break;
-
- case keymap.KEY.LEFT:
-
- if (!(elem.attr('mega-menu'))) {
- var el = angular.element(elem)[0];
- if (elem.attr("sub-menu") === "true") {
- /* condition true when user navigates through Sub-menu*/
- if(el.previousElementSibling === null) break;
- if(el.previousElementSibling){
- el.previousElementSibling.querySelector("a").focus();
- }
- else{
- do{
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if (el.querySelector("a") == null){}
- else{
- el.querySelector("a").focus();}
- }
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
-
- /*el.previousElementSibling.querySelector("span").focus();
- events.stopPropagation(evt);
- break;*/
- }
- else if (elem.attr("sub-menu") === undefined) {
- if(el.previousElementSibling === null) break;
- if(el.previousElementSibling){
- el.previousElementSibling.querySelector("a").focus();
- }
- else{
- do{
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if (el.querySelector("a") == null){}
- else{
- el.querySelector("a").focus();}
- }
- }
- }
- }
- else
- {
- if (elem.attr("menu-item") === "item") {
- /* Works when user on Mega menu*/
-
- var el = angular.element(elem)[0];
- if(el.previousElementSibling){
-
- if(el.previousElementSibling.querySelector("span") === null){
- }
- else {
- el.previousElementSibling.querySelector("span").focus();
- }
-
- }
- else{
- do{
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'LI');
- if(el){
- if (el.querySelector("span") === null) {
- }
- else {
- el.querySelector("span").focus();
- }
- }
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
- }
- }
- break;
- case keymap.KEY.UP:
-
- if (elem.attr("sub-menu") === "true") {
- var el = document.activeElement;
- var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("span");
- parent_menu.focus();
- parentCtrl.clearSubMenu();
- scope.menuItem.active = false;
- break;
- }
- else if(elem.attr("sub-menu") === undefined) {
- /* condition true when user navigates within Sub Items*/
- var el = document.activeElement;
- var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("a");
- if(document.activeElement === angular.element(el).parent().parent()[0].querySelectorAll('a')[0]){
- parent_menu.focus();
- break;
- };
-
- if(el.previousElementSibling) {
- var prev_a = el.previousElementSibling;
- (el.previousElementSibling != null)? el.previousElementSibling.focus(): parent_menu.focus();
- }else{
- do{
- if (el && el.previousSibling){
- el = el.previousSibling;
- }
- else{
- break;
- }
- } while (el && el.tagName !== 'A');
- if(el && (el.nodeType !== 3)){
- el.focus();
- }
- events.preventDefault(evt);
- events.stopPropagation(evt);
- }
-
- break;
- }
- default:
- break;
- }
- });
- }
- };
- }]);
-
-angular.module('att.abs.tagBadges', [])
- .directive('tagBadges', ['$parse', '$timeout', function($parse, $timeout) {
- return {
- restrict: 'EA',
- replace: false,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html',
- scope: {
- styleType: "@",
- onClose: "&"
- },
- link: function(scope, elem, attr) {
- scope.isSmall = false;
- scope.isIcon = false;
- scope.isColor = false;
- scope.display = true;
- scope.isClosable = false;
- scope.isHighlight = false;
- scope.customColor = false;
-
- if (attr.small === "") {
- scope.isSmall = true;
- }
- if (scope.styleType === "icon") {
- scope.isIcon = true;
- }
- else if (scope.styleType === "color") {
- scope.isColor = true;
- if(attr.color !== undefined && attr.color !== "") {
- scope.customColor = true;
- attr.$observe("color", function(val) {
- scope.border_type_borderColor = val;
- scope.background_type_backgroundColor = val;
- scope.background_type_borderColor = val;
- });
- }
- }
- scope.activeHighlight = function(state){
- if(scope.customColor){
- if(state){
- scope.isHighlight = true;
- }
- else{
- scope.isHighlight = false;
- }
- }
- };
- if (attr.closable === "") {
- scope.isClosable = true;
- scope.closeMe = function() {
- scope.display = false;
- $timeout(function(){
- elem.attr("tabindex", "0");
- elem[0].focus();
- elem.bind('blur', function(){
- elem.remove();
- });
- });
- if(attr['onClose']){
- scope.onClose = $parse(scope.onClose);
- scope.onClose();
- }
- };
- }
- }
- };
- }]);
-angular.module('att.abs.textOverflow', [])
- .constant('textDefaultOptions', {
- width: '50%'
- })
-.directive('attTextOverflow', ['textDefaultOptions','$compile',function(textDefaultOptions,$compile)
-{
- return {
- restrict: 'A',
- link: function(scope, elem, attrs)
- {
- var tooltipText = elem.text();
- elem.addClass('text-ellipsis');
- attrs.$observe('attTextOverflow', function(val){
- if(val){
- elem.css({"width":val});
- }
- else{
- elem.css({"width":textDefaultOptions.width});
- }
- });
- if(!(elem.attr('tooltip'))){
- elem.attr("tooltip", tooltipText);
- elem.attr("tooltip-placement", 'above');
- var newElem = angular.element(elem);
- $compile(newElem)(scope);
- }
- }
- };
-}]);
-
-angular.module('att.abs.toggle', ['angular-gestures', 'att.abs.position'])
- .directive('attToggleTemplate', ['$compile', '$log', '$position', function ($compile, $log, $position)
- {
- return{
- restrict: 'A',
- require: 'ngModel',
- transclude: true,
- scope: {
- modelVal: "=ngModel"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/toggle/demoToggle.html',
- link: function (scope, element, attr) {
- scope.initialDragPosition = 0;
- var dragStatus = 0;
- var switchMovementPath = ($position.offset(element.children().eq(1).children().eq(0)).width - 1);
- var updateModelVal = function () {
- if (scope.attrValue === attr.ngTrueValue || scope.attrValue)
- {
- scope.modelVal = false;
- }
- else
- {
- scope.modelVal = true;
- }
- };
- scope.updateModel = function (env) {
- {
- if (dragStatus !== 1) {
- updateModelVal();
- dragStatus = 0;
- }
- }
- env.preventDefault();
- };
- scope.drag = function (e) {
- dragStatus = 1;
- if (e.type === 'dragstart') {
- scope.initialDragPosition = $position.position(element.children().eq(1)).left;
- element.children().eq(1).addClass('dragging');
- } else if (e.type === 'drag') {
- var left = Math.min(0, Math.max(scope.initialDragPosition + e.gesture.deltaX, -switchMovementPath));
- element.children().eq(1).css({
- left: left + 'px'
- });
- } else if (e.type === 'dragend') {
- var isOn = $position.position(element.children().eq(1)).left > (switchMovementPath * -1) / 2;
- element.children().eq(1).removeClass('dragging');
- TweenMax.to(element.children().eq(1), .1, {left: isOn ? 0 : (switchMovementPath * -1), ease: Power4.easeOut,
- onComplete: function () {
- element.children().eq(1).css({left: ''});
- }});
- if (isOn || (!isOn && e.gesture.direction === "left")) {
- updateModelVal();
- }
- dragStatus = 0;
- }
-
- return false;
- };
-
- scope.directiveValue = attr.attToggleTemplate;
- scope.on = attr.trueValue;
- scope.off = attr.falseValue;
- var switchMovementPathPixels = ((switchMovementPath) * -1) + 'px';
- scope.$watch('modelVal', function (newVal) {
- scope.attrValue = newVal;
- if (newVal === attr.ngTrueValue || newVal) {
- element.children().eq(1).css({
- left: '0px'
- });
- element.addClass('att-checkbox--on');
- var elem = element.find('div').find('div').eq(1);
- elem.attr("aria-checked", true);
- dragStatus = 0;
- } else {
- element.children().eq(1).css({
- left: switchMovementPathPixels
- });
- element.removeClass('att-checkbox--on');
- var elem = element.find('div').find('div').eq(1);
- elem.attr("aria-checked", false);
- dragStatus = 0;
- }
- element.children().eq(1).css({
- left: ''
- });
- });
- }
- };
- }
- ])
-
- .directive('attToggleMain', ['$compile', function ($compile)
- {
- return{
- restrict: 'A',
- require: 'ngModel',
- transclude: true,
- replace: true,
- scope: {
- modelValue: "=ngModel",
- trueValue: "=ngTrueValue",
- falseValue: "=ngFalseValue"
- },
- link: function (scope, element, attr) {
- var html = "";
- var attrVal = "";
- element.removeAttr('att-toggle-main');
- scope.on = attr.ngTrueValue;
- scope.off = attr.ngFalseValue;
- scope.largeValue = attr.attToggleMain;
- if (angular.isDefined(attr.ngTrueValue)) {
- html += ' true-value="{{on}}" false-value="{{off}}"';
- }
- if (scope.largeValue !== undefined)
- {
- attrVal += ' ="{{largeValue}}"';
- }
-
- element.css({display: 'none'});
- var elm = angular.element('<div class="att-switch att-switch-alt" ng-class="{\'large\' : largeValue == \'large\'}" ng-model="modelValue"' + html + ' att-toggle-template' + attrVal + '>' + element.prop('outerHTML') + '</div>');
- elm = $compile(elm)(scope);
- element.replaceWith(elm);
- }
- };
- }]);
-angular.module('att.abs.treeview', [])
- .directive('treeView', function() {
- return{
- restrict: 'A',
- link: function(scope, elem) {
- var el = elem.children('ul li');
- var list = TweenMax.from(el, .2, {display: 'none', paused: true, reversed: true});
- elem.attr("tabindex","0");
- function toggleBranch() {
- if (list.reversed())
- {
- list.play();
- } else
- {
- list.reverse();
- }
- };
- function toggleTree(e) {
- e.stopPropagation();
- if (angular.element(e.target).attr("tree-view") !== undefined)
- {
- if (elem.hasClass('minus'))
- {
- elem.removeClass('minus');
- }
- else
- {
- elem.addClass('minus');
- }
- toggleBranch();
- }
- }
- elem.on('click', function(e) {
- toggleTree(e);
- });
- elem.on('keypress', function (e) {
- var activeCode = e.keyCode ? e.keyCode : e.charCode;
- var keyCode = [13,32];
- if (keyCode.length > 0 && ((activeCode && keyCode.indexOf(activeCode) > -1))) {
- toggleTree(e);
- e.preventDefault();
- }
- });
- }
- };
- });
-
-angular.module('att.abs.typeAhead', ['att.abs.tagBadges'])
-
- .directive('focusMe',['$timeout', '$parse', function($timeout, $parse) {
- return {
- link: function(scope, element, attrs) {
- var model = $parse(attrs.focusMe);
- scope.$watch(model, function(value) {
- if (value) {
- $timeout(function() {
- element[0].focus();
- scope.inputActive=true;
- });
- }
- });
- element.bind('blur', function() {
- model.assign(scope, false);
- scope.inputActive=false;
- scope.$digest();
- });
- }
- };
- }])
-
- .directive('typeAhead', ['$timeout','$log', function($timeout,$log) {
- return {
- restrict: 'EA',
- templateUrl: 'app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html',
- replace: true,
- scope: {
- items: '=',
- title: '@?',
- titleName: '@',
- subtitle: '@',
- model: '=',
- emailIdList:'=',
- emailMessage:'='
- },
- link: function(scope, elem) {
- if(!angular.isDefined(scope.titleName) && angular.isDefined(scope.title)){
- $timeout(function(){
- scope.titleName = scope.title;
- $log.warn("title attribute is deprecated and title-name attribute is used instead as it is conflicting with html title attribute");
- });
- }
- scope.lineItems = [];
- scope.filteredListLength = -1;
- scope.filteredList = [];
- scope.setFocus = function() {
- scope.clickFocus = true;
- };
- scope.setFocus();
- scope.handleSelection = function(selectedItem,emailItem) {
- scope.lineItems.push(selectedItem);
- scope.emailIdList.push(emailItem);
- scope.model = "";
- scope.current = 0;
- scope.selected = true;
- scope.clickFocus = true;
- };
- scope.theMethodToBeCalled = function(index) {
- var tempArr = scope.lineItems.slice();
- scope.emailIdList.splice(index, 1);
- tempArr.splice(index, 1);
- $timeout(function() {
- scope.lineItems = [];
- scope.$apply();
- scope.lineItems = scope.lineItems.concat(tempArr);
- });
- };
-
- scope.current = 0;
- scope.selected = true;
-
- scope.isCurrent = function(index, itemName,itemEmail,dropdownLength) {
- if (scope.current === index) {
- scope.itemName = itemName;
- scope.itemEmail = itemEmail;
- }
- scope.dropdownLength=dropdownLength;
- return scope.current === index;
- };
-
- scope.setCurrent = function(index) {
- scope.current = index;
- };
-
- scope.selectionIndex = function(evt) {
- if (evt.keyCode === 38 && scope.current > 0) {
- evt.preventDefault();
- scope.current = scope.current - 1;
- scope.isCurrent(scope.current);
- } else if (evt.keyCode === 9) {
- scope.selected = true;
- } else if (evt.keyCode === 13 && scope.dropdownLength!==scope.items.length) {
- scope.handleSelection(scope.itemName,scope.itemEmail);
- } else if ((evt.keyCode === 8 && scope.model.length === 0) || evt.keyCode === 46) {
- scope.theMethodToBeCalled(scope.lineItems.length - 1);
- } else if (evt.keyCode === 40 && scope.current < scope.dropdownLength-1) {
- evt.preventDefault();
- scope.current = scope.current + 1;
- scope.isCurrent(scope.current);
- }
- elem[0].querySelector('.list-scrollable').scrollTop = (scope.current - 1) * 35;
- };
- }
- };
- }]);
-angular.module('att.abs.verticalSteptracker', ['ngSanitize'])
- .directive('verticalSteptracker', [ function(){
- return {
- restrict: 'EA',
- transclude: true,
- replace: false,
- scope: {},
- template: '<div class="vertical-nav"><ul ng-transclude arial-label="step list" role="presentation" class="tickets-list-height"></ul></div>',
- link: function () {}
- };
- }])
- .directive('verticalSteptrackerStep',[ function(){
- return {
- restrict: 'EA',
- transclude: true,
- replace: false,
- scope: {
- type: "=type",
- id: "=id"
- },
- templateUrl: 'app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html',
- link: function(){}
- };
- }])
- .directive('attAbsLink',[ function(){
- return{
- restrict: 'EA',
- transclude: true,
- replace: false,
- template: '<span ng-transclude class="view-log"></span>'
- };
- }]);
-angular.module('att.abs.videoControls', [])
- .config(['$compileProvider' , function ($compileProvider) {
- $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
- }])
- .directive('videoControls', [function() {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/videoControls.html'
- };
- }])
- .directive('photoControls', [function() {
- return {
- restrict: 'EA',
- replace: true,
- transclude: true,
- templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/photoControls.html',
- scope: {
- prevLink: "@",
- nextLink: "@"
- },
- link: function(scope, elem, attr) {
- if(!attr['prevLink']){
- scope.prevLink = 'javascript:void(0)';
- }
- if(!attr['nextLink']){
- scope.nextLink = 'javascript:void(0)';
- }
- scope.links = {
- prevLink : scope.prevLink,
- nextLink : scope.nextLink
- };
- }
- };
- }]);
-angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",
- "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
- " <a ng-show=\"showicon\" \n" +
- " class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\" \n" +
- " aria-selected=\"{{focused}}\" \n" +
- " aria-controls=\"panel{{index}}\" \n" +
- " aria-expanded=\"{{isOpen}}\" \n" +
- " ng-class=\"{focus: focused, selected: focused}\" \n" +
- " role=\"tab\" \n" +
- " ng-click=\"toggle()\" \n" +
- " accordion-transclude=\"heading\" \n" +
- " style=\"cursor:pointer; text-decoration:none\">\n" +
- " <span href=\"#\"><i class={{headingIconClass}}></i>&nbsp;&nbsp;{{heading}}</span>\n" +
- " <i i ng-show = 'childLength > 0' ng-class=\"{'ion-ios-arrow-down':!isOpen,'ion-ios-arrow-up':isOpen }\" class=\"pull-right\"></i>\n" +
- " </a>\n" +
- " <div ng-show=\"!showicon\" \n" +
- " ng-class=\"{focus: focused, selected: focused}\" \n" +
- " style=\"text-decoration:none\" \n" +
- " accordion-transclude=\"heading\" \n" +
- " role=\"tab\" \n" +
- " aria-expanded=\"{{isOpen}}\"\n" +
- " aria-selected=\"{{focused}}\" \n" +
- " aria-controls=\"panel{{index}}\" \n" +
- " class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\">\n" +
- " <span>{{heading}}</span>\n" +
- " </div> \n" +
- " <div aria-label=\"{{heading}}\" \n" +
- " aria-hidden=\"{{!isOpen}}\" \n" +
- " role=\"tabpanel\" \n" +
- " collapse=\"!isOpen\" \n" +
- " class=\"att-accordion__body\" \n" +
- " id=\"panel{{index}}\" \n" +
- " ng-transclude>\n" +
- " </div>\n" +
- " <div class=\"att-accordion__bottom--border\"></div> \n" +
- "</div> ");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",
- "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
- " <a class=\"toggle-header att-accordion__heading att-accordion__toggle\" \n" +
- " aria-selected=\"{{focused}}\" \n" +
- " aria-controls=\"panel{{index}}\" \n" +
- " ng-class=\"{focus: focused, selected: focused}\" \n" +
- " aria-expanded=\"{{isOpen}}\" \n" +
- " role=\"tab\" \n" +
- " ng-click=\"toggle()\" \n" +
- " accordion-transclude=\"heading\"> \n" +
- " </a>\n" +
- " <span>{{heading}}</span>\n" +
- " <div aria-label=\"{{heading}}\" \n" +
- " aria-hidden=\"{{!isOpen}}\" \n" +
- " role=\"tabpanel\" \n" +
- " collapse=\"!isOpen\" \n" +
- " class=\"att-accordion__body\" \n" +
- " id=\"panel{{index}}\" \n" +
- " ng-transclude>\n" +
- " </div>\n" +
- "</div> ");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html",
- "<div ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",
- "<div ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",
- "<div ng-click=\"clickFunc()\">\n" +
- " <div ng-transclude>\n" +
- " <i class=\"ion-ios-arrow-down\"></i>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/alert/alert.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/alert/alert.html",
- "<div class=\"alert\" ng-class=\"{'alert-success': alertType === 'success', 'alert-warning': alertType === 'warning', 'alert-error': alertType === 'error', 'alert-info': alertType === 'info', 'alert-inplace': showTop !== 'true'}\" ng-show=\"showAlert\" ng-style=\"cssStyle\">\n" +
- " <div class=\"container\">\n" +
- " <a href=\"javascript:void(0)\" alt=\"close\" class=\"close-role\" ng-click=\"close()\" tabindex=\"0\" att-accessibility-click=\"32,13\">Dismiss <i class=\"icon-circle-action-close\"></i></a>\n" +
- " <span ng-transclude> </span>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",
- "<div tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"addBoard()\" aria-label=\"Add Board\" class=\"boardstrip-item--add\">\n" +
- " <i aria-hidden=\"true\" class=\"icon-add centered\"></i>\n" +
- " <br/>\n" +
- " <div class=\"centered\">Add board</div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",
- "<li att-board-navigation tabindex=\"0\" aria-label=\"{{boardLabel}}\" att-accessibility-click=\"13,32\" ng-click=\"selectBoard(boardIndex)\" class=\"board-item\" ng-class=\"{'selected': getCurrentIndex()===boardIndex}\">\n" +
- " <div ng-transclude></div>\n" +
- " <div class=\"board-caret\" ng-if=\"getCurrentIndex()===boardIndex\">\n" +
- " <div class=\"board-caret-indicator\"></div>\n" +
- " <div class=\"board-caret-arrow-up\"></div>\n" +
- " </div>\n" +
- "</li>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",
- "<div class=\"att-boardstrip\">\n" +
- " <div class=\"boardstrip-reel\">\n" +
- " <div class=\"prev-items\" ng-if=\"isPrevBoard()\">\n" +
- " <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Left\" att-accessibility-click=\"13,32\" ng-click=\"prevBoard()\" class=\"arrow icon-arrow-left-circle\"></i>\n" +
- " </div>\n" +
- " <div att-add-board on-add-board=\"onAddBoard()\"></div>\n" +
- " <div class=\"board-viewport\"><ul role=\"presentation\" class=\"boardstrip-container\" ng-transclude></ul></div>\n" +
- " <div class=\"next-items\" ng-if=\"isNextBoard()\">\n" +
- " <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Right\" att-accessibility-click=\"13,32\" ng-click=\"nextBoard()\" class=\"arrow icon-arrow-right-circle\"></i>\n" +
- " </div>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",
- "<div class=\"att-btn-dropdown\">\n" +
- " <div class=\"buttons-dropdown--small btn-group\" ng-class=\"{'open': isOpen}\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\">\n" +
- " \n" +
- " <button role=\"menu\" class=\"button button--secondary button--small buttons-dropdown__drop dropdown-toggle\" ng-if=\"type==='dots'\" alt=\"Click for Options\" >\n" +
- " \n" +
- " <div class=\"circle\"></div>\n" +
- " <div class=\"circle\"></div>\n" +
- " <div class=\"circle\"></div>\n" +
- " </button>\n" +
- " <button role=\"menu\" class=\"button button--secondary button--small buttons-dropdown__drop dropdown-toggle ng-isolate-scope actions-title\" ng-if=\"type === 'actions'\" alt=\"Actions dropdown Buttons\">Actions</button>\n" +
- " \n" +
- "\n" +
- " <ul ng-class=\"{'dropdown-menu dots-dropdwn': type==='dots', 'dropdown-menu actions-dropdwn': type === 'actions'}\" ng-transclude></ul>\n" +
- " </div>\n" +
- " \n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",
- "<div class=\"att-radio att-color-selector__item\" \n" +
- " ng-class=\"{'att-radio--on': (iconColor === selected)}\">\n" +
- " <div class=\"att-radio__indicator\" tabindex=\"0\" att-accessibility-click=\"32,13\" ng-click=\"selectedcolor(iconColor)\" \n" +
- " ng-style=\"applycolor\" ng-transclude></div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",
- "<div class=\"calendar\" ng-class=\"{'monthpicker':mode === 1}\">\n" +
- " <div class=\"select2-container\" ng-class=\"{'select2-container-active select2-dropdown-open': showDropdownList}\" style=\"width: 100%; z-index:0\">\n" +
- " <a tabindex=\"0\" id=\"select2-choice\" class=\"select2-choice\" href=\"javascript:void(0)\" att-element-focus=\"focusInputButton\" ng-show=\"!showCalendar\" att-accessibility-click=\"13,32\" ng-click=\"showDropdown()\" ng-blur=\"focusInputButton=false\">\n" +
- " <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
- " <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" aria-labelledby=\"select2-choice\" ng-change=\"getDropdownText()\" />\n" +
- " <abbr class=\"select2-search-choice-close\"></abbr>\n" +
- " <span ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\"><b></b></span>\n" +
- " </a>\n" +
- " <a id=\"select2-chosen\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"showCalendar\">\n" +
- " <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
- " <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" aria-labelledby=\"select2-chosen\" ng-change=\"getDropdownText()\" />\n" +
- " <abbr class=\"select2-search-choice-close\"></abbr>\n" +
- " <span tabindex=\"0\" ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\" att-accessibility-click=\"13,32\" ng-click=\"showDropdown()\"><b></b></span>\n" +
- " </a>\n" +
- " </div>\n" +
- " <div class=\"select2-drop select2-drop-active select2-display-none\" ng-style=\"{display: (showDropdownList && 'block') || 'none', 'border-radius': showCalendar && '0 0 0 6px'}\" style=\"width: 100%\">\n" +
- " <div id=\"dateFilterList\" att-scrollbar ><ul class=\"select2-results options\" ng-transclude></ul></div>\n" +
- " <ul class=\"select2-results sttings\" style=\"margin-top:0px\">\n" +
- " <li tabindex=\"0\" class=\"select2-result select2-highlighted greyBorder\" ng-class=\"{'select2-result-current': checkCurrentSelection('Custom Single Date')}\" att-accessibility-click=\"13,32\" ng-click=\"selectAdvancedOption('Custom Single Date')\">\n" +
- " <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Single Date...</div>\n" +
- " <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom single month...</div>\n" +
- " </li>\n" +
- " <li tabindex=\"0\" class=\"select2-result select2-highlighted\" ng-class=\"{'select2-result-current': checkCurrentSelection('Custom Range')}\" att-accessibility-click=\"13,32\" ng-click=\"selectAdvancedOption('Custom Range')\">\n" +
- " <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Range...</div>\n" +
- " <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom month range...</div>\n" +
- " </li>\n" +
- " <li class=\"select2-result select2-highlighted btnContainer\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
- " <button tabindex=\"0\" ng-blur=\"resetFocus($event)\" att-element-focus=\"focusApplyButton\" att-button=\"\" btn-type=\"{{applyButtonType}}\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"apply()\">Apply</button>\n" +
- " <button tabindex=\"0\" att-button=\"\" btn-type=\"secondary\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"cancel()\">Cancel</button>\n" +
- " <div>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" ng-if=\"mode !== 1\" style=\"text-decoration:underline;\" att-accessibility-click=\"13,32\" ng-click=\"clear()\">Clear Dates</a>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" ng-if=\"mode === 1\" style=\"text-decoration:underline;\" att-accessibility-click=\"13,32\" ng-click=\"clear()\">Clear Months</a>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- " </div>\n" +
- " <div class=\"datepicker-wrapper show-right\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
- " <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusSingleDateCalendar\" ng-show=\"checkCurrentSelection('Custom Single Date')\"></span>\n" +
- " <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusRangeCalendar\" ng-show=\"checkCurrentSelection('Custom Range')\"></span>\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",
- "<li ng-click=\"!disabled && selectOption(fromDate,toDate,caption)\" att-accessibility-click=\"13,32\" ng-class=\"{'select2-result-current': checkCurrentSelection(caption)}\" class=\"select2-result select2-highlighted ng-scope\" tabindex=\"{{!disabled?'0':'-1'}}\">\n" +
- " <div class=\"select2-result-label\" ng-class=\"{'disabled':disabled}\" ng-transclude></div>\n" +
- "</li>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",
- "<div id=\"datepicker\" class=\"datepicker\" ng-class=\"{'monthpicker': mode === 1}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\" aria-labelledby=\"datepicker\">\n" +
- " <div class=\"datepicker-days\" style=\"display: block;\">\n" +
- " <table class=\"table-condensed\">\n" +
- " <thead>\n" +
- " <tr>\n" +
- " <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch\" colspan=\"{{(mode !== 1) && (currentRows[0].length - 2) || (currentRows[0].length)}}\" style=\"text-align:left\">{{currentTitle}}</th>\n" +
- " <th ng-if=\"mode !== 1\" id=\"prev\" aria-hidden=\"{{!disablePrev && 'false'|| 'true'}}\" tabindex=\"{{!disablePrev && '0'|| '-1'}}\" att-accessibility-click=\"13,32\" ng-click=\"!disablePrev && move(-1)\">\n" +
- " <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-left-circle\" ng-class=\"{'disabled': disablePrev}\" alt=\"Left Arrow\"></i>\n" +
- " </div><span class=\"hidden-spoken\">Previous Month</span>\n" +
- " </th>\n" +
- " <th ng-if=\"mode !== 1\" id=\"next\" aria-hidden=\"{{!disableNext && 'false'|| 'true'}}\" tabindex=\"{{!disableNext && '0'|| '-1'}}\" att-accessibility-click=\"13,32\" ng-click=\"!disableNext && move(1)\">\n" +
- " <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-right-circle\" ng-class=\"{'disabled': disableNext}\" alt=\"Right Arrow\"></i>\n" +
- " </div><span class=\"hidden-spoken\">Next Month</span>\n" +
- " </th>\n" +
- " </tr>\n" +
- " <tr ng-if=\"labels.length > 0\">\n" +
- " <th tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"><span>{{label.pre}}</span></th>\n" +
- " </tr>\n" +
- " </thead>\n" +
- " <tbody>\n" +
- " <tr>\n" +
- " <td id=\"datepickerBody\" att-scrollbar colspan=\"{{currentRows[0].length}}\" style=\"padding: 0px;\" headers=\"\">\n" +
- " <table ng-class=\"{'table-condensed': mode === 0, 'monthtable-condensed': mode === 1}\" style=\"padding: 0px;\">\n" +
- " <thead class=\"hidden-spoken\">\n" +
- " <tr ng-show=\"labels.length > 0\">\n" +
- " <th id=\"{{label.post}}\" tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"></th>\n" +
- " </tr>\n" +
- " </thead>\n" +
- " <tbody>\n" +
- " <tr ng-repeat=\"row in currentRows\">\n" +
- " <td headers=\"{{(mode === 0) && dt.header || 'month'}}\" att-element-focus=\"dt.focused\" aria-hidden=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && 'false') || 'true'}}\" tabindex=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && '0') || '-1'}}\" ng-repeat=\"dt in row\" class=\"days\" ng-class=\"{'active': dt.selected || dt.from || dt.to, 'from': dt.from, 'to': dt.to, 'range': dt.dateRange, 'prev-month ': dt.oldMonth, 'next-month': dt.nextMonth, 'disabled': dt.disabled, 'today': dt.today, 'weekend': dt.weekend}\" ng-click=\"!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)\" att-accessibility-click=\"13,32\" aria-label=\"{{dt.date | date : 'EEEE, MMMM d'}}\"><span class=\"day\">{{dt.label}}</span></td>\n" +
- " </tr>\n" +
- " <tr ng-if=\"mode === 1\" class=\"divider\"><td colspan=\"{{nextRows[0].length}}\"><hr></td></tr>\n" +
- " <tr>\n" +
- " <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch internal\" colspan=\"{{nextRows[0].length}}\" style=\"text-align:left\">{{nextTitle}}</th>\n" +
- " </tr>\n" +
- " <tr ng-repeat=\"row in nextRows\">\n" +
- " <td headers=\"{{(mode === 0) && dt.header || 'month'}}\" att-element-focus=\"dt.focused\" aria-hidden=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && 'false') || 'true'}}\" tabindex=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && '0') || '-1'}}\" ng-repeat=\"dt in row\" class=\"days\" ng-class=\"{'active': dt.selected || dt.from || dt.to, 'from': dt.from, 'to': dt.to, 'range': dt.dateRange, 'prev-month ': dt.oldMonth, 'next-month': dt.nextMonth, 'disabled': dt.disabled, 'today': dt.today, 'weekend': dt.weekend}\" ng-click=\"!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)\" att-accessibility-click=\"13,32\" aria-label=\"{{dt.date | date : 'EEEE, MMMM d'}}\"><span class=\"day\">{{dt.label}}</span></td>\n" +
- " </tr>\n" +
- " </tbody>\n" +
- " </table>\n" +
- " </td>\n" +
- " </tr>\n" +
- " </tbody>\n" +
- " </table>\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",
- "<div class=\"calendar\">\n" +
- " <div class=\"box\" ng-class=\"{'active': isOpen}\">\n" +
- " <span ng-transclude></span>\n" +
- " <i class=\"calendar-icon\" tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\" alt=\"Calendar Icon\"></i>\n" +
- " </div>\n" +
- " <div class=\"datepicker-wrapper datepicker-wrapper-display-none\" ng-style=\"{display: (isOpen && 'block') || 'none'}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
- " <span datepicker></span>\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",
- "<div class=\"divider-container\" ng-class=\"{'divider-container-light': lightContainer}\">\n" +
- " <hr ng-class=\"{'divider-light': lightContainer}\">\n" +
- "</div>\n" +
- "\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",
- "<label class=\"fileContainer\"><span ng-transclude></span><input type=\"file\" att-file-change></label>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",
- "<div class=\"form-field\" ng-class=\"{'error': errorMessage, 'warning': warningMessage}\">\n" +
- " <label class=\"form-field__label\" ng-class=\"{'form-field__label--show': showLabel, 'form-field__label--hide': hideLabel}\"></label>\n" +
- " <div class=\"form-field-input-container\" ng-transclude></div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",
- "<div class=\"form-field\" ng-class=\"{'error':hideErrorMsg}\">\n" +
- " <div class=\"form-field-input-container\" ng-transclude></div>\n" +
- " <div class=\"form-field__message error\" type=\"error\" ng-show=\"hideErrorMsg\" >\n" +
- " <i class=\"icon-info-alert\"></i>{{errorMessage}}\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/formField/creditCardImage.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/formField/creditCardImage.html",
- "<span class=\"css-sprite pull-right\">\n" +
- "<span class=\"hidden-spoken\">We accept</span>\n" +
- "<ul class=\"{{newValCCI}}\">\n" +
- " <li class=\"css-sprite-mc\"><span class=\"hidden-spoken\">MasterCard</span></li>\n" +
- " <li class=\"css-sprite-visa\"><span class=\"hidden-spoken\">Visa</span></li>\n" +
- " <li class=\"css-sprite-amex\"><span class=\"hidden-spoken\">American Express</span></li>\n" +
- " <li class=\"css-sprite-discover\"><span class=\"hidden-spoken\">Discover</span></li> \n" +
- "</ul>\n" +
- "</span>\n" +
- "<label for=\"ccForm.card\" class=\"pull-left\">Card number</label>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",
- "<div>\n" +
- "<button type=\"button\" class=\"btn btn-alt btn-tooltip\" style=\"padding-top:16px\" title=\"Help\"><i class=\"hidden-spoken\">Help</i></button>\n" +
- "<div class=\"helpertext\" role=\"tooltip\">\n" +
- "<div class=\"popover-title\"></div>\n" +
- "<div class=\"popover-content\">\n" +
- " <p class=\"text-legal cvc-cc\">\n" +
- " <img ng-src=\"images/{{newValI}}.png\" alt=\"{{newValIAlt}}\">\n" +
- " </p>\n" +
- "</div>\n" +
- "</div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",
- "<div class=\"hourpicker\">\n" +
- " <div class=\"dropdown-width\">\n" +
- " <div ng-model=\"showlist\" class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" >\n" +
- " <a class=\"select2-choice\" href=\"javascript:void(0)\" id=\"customSelect\" ng-keydown=\"selectOption(selectPrevNextValue($event,options,selectedOption))\" att-accessibility-click=\"13\" ng-click=\"showDropdown()\">\n" +
- " <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
- " <span class=\"select2-arrow\"><b></b></span>\n" +
- " </a>\n" +
- " </div> \n" +
- " <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth\" ng-show=\"showlist\"> \n" +
- " <ul class=\"select2-results resultTopMargin\" > \n" +
- " <li ng-model=\"ListType\" ng-repeat=\"option in options\" att-accessibility-click=\"13\" ng-click=\"selectOption(option,$index)\" class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\"><span >{{option}}</span></div></li> \n" +
- " </ul>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div ng-show=\"showDaysSelector\" class=\"customdays-width\">\n" +
- " <div att-divider-lines class=\"divider-margin-f\"></div> \n" +
- " <div class=\"col-md-3 fromto-margin\">\n" +
- " <div>From</div> <br>\n" +
- " <div>To</div>\n" +
- " </div>\n" +
- " <div ng-repeat=\"day in days\">\n" +
- " <div class=\"col-md-3 col-md-days\">\n" +
- " <div class=\"col-md-1 daysselect-margin\">\n" +
- " <input type=\"checkbox\" ng-model=\"daysList[day]\" title=\"Day selection {{$index}}\" att-checkbox ng-change=\"addSelectedValue(day)\"> \n" +
- " </div>\n" +
- " <span>{{day}}</span><br>\n" +
- " \n" +
- " <div class=\"dropDownMarginBottom\">\n" +
- " <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': FrtimeListDay[day]}\" >\n" +
- " <a class=\"select2-choice selectDropDown\" href=\"javascript:void(0)\" tabindex=\"{{daysList[day] ? '0' : '-1'}}\" att-accessibility-click=\"13\" ng-click=\"daysList[day] && showfromDayDropdown(day)\" ng-class=\"{'select2-chosen-disabled':!daysList[day]}\" ng-keydown=\"daysList[day] && selectFromDayOption(day , selectPrevNextValue($event,fromtime,selectedFromOption[day]));daysList[day] && addSelectedValue(day);\">\n" +
- " <span class=\"select2-chosen dropDownMarginRight\" >{{selectedFromOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"FrtimeListDay[day] ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"></i></span>\n" +
- " </a>\n" +
- " </div> \n" +
- " \n" +
- " <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown\" ng-show=\"FrtimeListDay[day]\"> \n" +
- " <ul class=\"select2-results resultTopMargin\" > \n" +
- " <li ng-click=\"selectFromDayOption(day,time.value);addSelectedValue(day);\" ng-repeat=\"time in fromtime\" class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\" ng-class=\"{'selectedItemInDropDown': (time.value==selectedFromOption[day])}\"><span >{{time.value}}</span></div></li> \n" +
- " </ul>\n" +
- " </div>\n" +
- " </div>\n" +
- " \n" +
- " <div class=\"dropDownMarginBottom\">\n" +
- " <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': TotimeListDay[day]}\" >\n" +
- " <a class=\"select2-choice selectDropDown\" href=\"javascript:void(0)\" tabindex=\"{{daysList[day] ? '0' : '-1'}}\" att-accessibility-click=\"13\" ng-click=\"daysList[day] && showtoDayDropdown(day)\" ng-class=\"{'select2-chosen-disabled':!daysList[day], 'selectDropDown-error':daysList[day] && showToTimeErrorDay[day]}\" ng-keydown=\"daysList[day] && selectToDayOption(day , selectPrevNextValue($event,totime,selectedToOption[day]));daysList[day] && addSelectedValue(day);\">\n" +
- " <span class=\"select2-chosen dropDownMarginRight\">{{selectedToOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"TotimeListDay[day] ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\" ></i></span>\n" +
- " </a>\n" +
- " </div>\n" +
- " \n" +
- " <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown\" ng-show=\"TotimeListDay[day]\"> \n" +
- " <ul class=\"select2-results resultTopMargin\" > \n" +
- " <li ng-click=\"selectToDayOption(day,time.value);addSelectedValue(day);\" ng-repeat=\"time in totime\" class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\" ng-class=\"{'selectedItemInDropDown': (time.value==selectedToOption[day])}\"><span >{{time.value}}</span></div></li> \n" +
- " </ul>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div> \n" +
- " </div> \n" +
- " <div att-divider-lines class=\"divider-margin-s\"></div>\n" +
- " </div>\n" +
- " <div ng-transclude></div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/links/readMore.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/links/readMore.html",
- "<div>\n" +
- " <div ng-bind-html=\"textToDisplay\" ng-class=\"{'att--readMore': readFlag, 'att--readLess': !readFlag}\" ng-style=\"readLinkStyle\"></div>\n" +
- " <span class=\"att--readmore__link\" ng-show=\"readMoreLink\">… <a href=\"javascript:void(0);\" ng-click=\"readMore()\" att-accessbility-click=\"32,13\">Read More</a>\n" +
- " </span>\n" +
- "</div>\n" +
- "<span class=\"att--readless__link\" ng-show=\"readLessLink\">\n" +
- " <a href=\"javascript:void(0);\" ng-click=\"readLess()\" att-accessbility-click=\"32,13\">Read Less</a>\n" +
- "</span>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/loading/loading.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/loading/loading.html",
- "<div data-progress=\"{{progressStatus}}\" class=\"{{colorClass}}\" ng-class=\"{'att-loading-count':icon == 'count','loading--small':icon == 'small','loading': icon != 'count'}\" alt=\"Loading\">\n" +
- " <div class=\"att-loading-circle\" ng-if=\"icon == 'count'\">\n" +
- " <div class=\"att-loading-circle__mask att-loading-circle__full\">\n" +
- " <div class=\"att-loading-circle__fill\"></div>\n" +
- " </div>\n" +
- " <div class=\"att-loading-circle__mask att-loading-circle__half\">\n" +
- " <div class=\"att-loading-circle__fill\"></div>\n" +
- " <div class=\"att-loading-circle__fill att-loading-circle__fix\"></div>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div ng-class=\"{'att-loading-inset':icon == 'count','loading__inside':icon != 'count'}\"><div class=\"att-loading-inset__percentage\" ng-if=\"icon == 'count'\" alt=\"Loading with Count\"></div></div>\n" +
- "</div>\n" +
- "\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",
- "<div class=\"overlayed\" ng-class=\"{show: animate}\" \n" +
- " ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\"> \n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/modal/tabbedItem.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedItem.html",
- "<div>\n" +
- " <ul class=\"tabs_overlay\">\n" +
- " <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
- " <i class=\"{{item.iconClass}}\"></i>\n" +
- " {{item.title}} ({{item.number}})\n" +
- " <a class=\"viewLink\" att-link>Show</a>\n" +
- " </li>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",
- "<div>\n" +
- " <ul class=\"tabs_overlay\">\n" +
- " <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
- " <i class=\"{{item.iconClass}}\"></i>\n" +
- " {{item.title}} ({{item.number}})\n" +
- " <a class=\"viewLink\" att-link>Show</a>\n" +
- " </li>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/modal/window.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/modal/window.html",
- "<div tabindex=\"-1\" role=\"dialog\" att-element-focus=\"focusModalFlag\" class=\"modals {{ windowClass }}\" ng-class=\"{show: animate}\" \n" +
- " ng-style=\"{'z-index': 2010 + index*10}\" ng-click=\"close($event)\" ng-transclude> \n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",
- "<div class=\"pager\">\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item--prev\" att-accessibility-click=\"13,32\" ng-click=\"prev($event)\" ng-if=\"currentPage > 1\"><i class=\"icon-arrow-left\"></i> Previous</a>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" ng-if=\"totalPages > 7 && currentPage > 3\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(1, $event)\">1</a>\n" +
- " <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage > 3\">...</span>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" att-element-focus=\"isFocused(page)\" ng-repeat=\"page in pages\" ng-class=\"{'pager__item--active': checkSelectedPage(page)}\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(page, $event)\">{{page}}</a>\n" +
- " <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2 && showInput !== true\">...</span>\n" +
- " <span ng-show=\"totalPages > 7 && showInput === true\"><input class=\"pager__item--input\" type=\"text\" placeholder=\"...\" maxlength=\"2\" ng-model=\"currentPage\" aria-label=\"Current page count\"/></span>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(totalPages, $event)\">{{totalPages}}</a>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item--next\" att-accessibility-click=\"13,32\" ng-click=\"next($event)\" ng-if=\"currentPage < totalPages\">Next <i class=\"icon-arrow-right\"></i></a>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",
- "<div class='inner-pane' ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",
- "<div class='pane-group' ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",
- "<div class='side-pane' ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",
- "<div class=\"att-tooltip \" \n" +
- " ng-class=\"{ 'att-tooltip--on': isOpen, \n" +
- " 'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n" +
- " 'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n" +
- " 'att-tooltip--left':placement=='left', \n" +
- " 'att-tooltip--above':placement=='above', \n" +
- " 'att-tooltip--right':placement=='right', \n" +
- " 'att-tooltip--below':placement=='below'}\" \n" +
- " ng-bind-html=\"content | unsafe\" ></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/popOvers/popOvers.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/popOvers/popOvers.html",
- "<div class=\"att-popover popover-demo\" ng-style=\"{backgroundColor:popOverStyle}\"\n" +
- " ng-class=\"{'att-tooltip--dark':popOverStyle==='grey',\n" +
- " 'att-pop-over--left':popOverPlacement==='left', \n" +
- " 'att-pop-over--above':popOverPlacement==='above', \n" +
- " 'att-pop-over--right':popOverPlacement==='right'}\" \n" +
- " style='position: absolute; max-width: 490px;'>\n" +
- " <div class=\"pop-over-caret\"\n" +
- " ng-class=\"{'pop-over-caret-border--left':popOverPlacement==='left', \n" +
- " 'pop-over-caret-border--above':popOverPlacement==='above', \n" +
- " 'pop-over-caret-border--right':popOverPlacement==='right', \n" +
- " 'pop-over-caret-border--below':popOverPlacement==='below'}\">\n" +
- " </div>\n" +
- " <div class=\"pop-over-caret\" ng-style=\"popOverPlacement=='below' && {borderBottom:'6px solid ' +popOverStyle}||popOverPlacement=='left' && {borderLeft:'6px solid ' +popOverStyle}||popOverPlacement=='right' && {borderRight:'6px solid ' +popOverStyle}||popOverPlacement=='above' && {borderTop:'6px solid ' +popOverStyle}\"\n" +
- " ng-class=\"{'pop-over-caret--left':popOverPlacement==='left', \n" +
- " 'pop-over-caret--above':popOverPlacement==='above', \n" +
- " 'pop-over-caret--right':popOverPlacement==='right', \n" +
- " 'pop-over-caret--below':popOverPlacement==='below'}\"></div>\n" +
- " \n" +
- " <div class=\"att-popover-content\">\n" +
- " <a ng-if=\"closeable\" href=\"javascript:void(0)\" class=\"icon-close att-popover__close\" ng-click=\"closeMe();$event.preventDefault()\"></a>\n" +
- " <div class=\"popover-packages__container\" ng-include=\"content\"></div>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",
- "<div class=\"col-md-9 profile-card add-user\">\n" +
- " <div class=\"atcenter\">\n" +
- " <div><i class=\"icon-add\"></i></div>\n" +
- " <span>add User</span>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",
- "<div class=\"col-md-9 profile-card\">\n" +
- " <div class=\"top-block\">\n" +
- " <div class=\"profile-image\">\n" +
- " <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\" alt=\"{{profile.name}}\">\n" +
- " <span ng-hide=\"image\" class=\"default-img\">{{initials}}</span>\n" +
- " <p class=\"name\" tooltip-condition=\"{{profile.name}}\" height=\"true\"></p>\n" +
- " <p class=\"status\">\n" +
- " <span class=\"status-icon\" ng-class=\"{'icon-green':colorIcon==='green','icon-red':colorIcon==='red','icon-blue':colorIcon==='blue','icon-yellow':colorIcon==='yellow'}\"> \n" +
- " </span>\n" +
- " <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
- " </p>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div class=\"bottom-block\">\n" +
- " <div class=\"profile-details\">\n" +
- " <label>Username</label>\n" +
- " <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.userName}}\">{{profile.userName}}</p>\n" +
- " <label>Email</label>\n" +
- " <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.email}}\">{{profile.email}}</p>\n" +
- " <label>Role</label>\n" +
- " <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.role}}\">{{profile.role}}</p>\n" +
- " <label>Last Login</label>\n" +
- " <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.lastLogin}}\">{{profile.lastLogin}}</p>\n" +
- " </div>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",
- "<div class=\"att-progress\">\n" +
- " <div class=\"att-progress-value\">&nbsp;</div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",
- "<div class=\"scroll-bar\" style=\"position: absolute\">\n" +
- " <div class=\"scroll-thumb\" style=\"position: absolute; overflow: hidden\"></div>\n" +
- "</div>\n" +
- "<div class=\"prev icons-list\" data-size=\"medium\" ng-show=\"navigation && prevAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
- " <a href=\"javascript:void(0);\" ng-click=\"customScroll(false)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
- " <i ng-class=\"{'ion-ios-arrow-up': (scrollbarAxis === 'y'), 'icon-chevron-left': (scrollbarAxis === 'x')}\"></i>\n" +
- " </a>\n" +
- "</div>\n" +
- "<div class=\"scroll-viewport\" ng-style=\"{height: (scrollbarAxis === 'x' && position.height + 'px') || viewportHeight, width: viewportWidth}\" style=\"position: relative; overflow: hidden\">\n" +
- " <div class=\"scroll-overview\" style=\"position: absolute; display: table; width: 100%\" att-position=\"position\" ng-transclude></div>\n" +
- "</div>\n" +
- "<div class='next icons-list' data-size=\"medium\" ng-show=\"navigation && nextAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
- " <a href=\"javascript:void(0);\" ng-click=\"customScroll(true)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
- " <i ng-class=\"{'ion-ios-arrow-down': (scrollbarAxis === 'y'), 'icon-chevron-right': (scrollbarAxis === 'x')}\"></i>\n" +
- " </a>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/search/search.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/search/search.html",
- "<div class=\"select2-container show-search\" ng-class=\"{'select2-dropdown-open': (showlist && !isDisabled),'select2-container-disabled':isDisabled, 'select2-container-active': isact}\" ng-init=\"isact=false;\" style=\"width: 100%;\">\n" +
- " <a href=\"javascript:void(0)\" class=\"select2-choice needsclick\" tabindex=\"0\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" role=\"combobox\" aria-expanded=\"{{showlist}}\" aria-owns=\"inList\" aria-label=\"{{selectedOption}} selected\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
- " <span class=\"select2-chosen needsclick\" aria-hidden = \"true\">{{selectedOption}}</span>\n" +
- " <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
- " <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
- " <b role=\"presentation\" class=\"needsclick\"></b>\n" +
- " </span>\n" +
- " </a> \n" +
- " <input class=\"select2-focusser select2-offscreen\" \n" +
- " tabindex=\"-1\" \n" +
- " type=\"text\" \n" +
- " aria-hidden=\"true\" \n" +
- " title=\"hidden\" \n" +
- " aria-haspopup=\"true\" \n" +
- " role=\"button\"> \n" +
- "</div>\n" +
- "\n" +
- "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled)}\" style=\"width:100%;z-index: 10\">\n" +
- " <div class=\"select2-search\">\n" +
- " <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
- " <input ng-if=\"!noFilter\" ng-model=\"title\" aria-label=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
- " </div>\n" +
- " <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
- " <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
- " <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\" ng-click=\"selectOption(selectMsg, '-1')\" ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\" ng-mouseover=\"hoverIn(-1)\" aria-label=\"{{selectMsg}}\" tabindex=\"-1\">\n" +
- " <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- "\n" +
- " <li role=\"menuitem\" ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" aria-label=\"{{item.title}}\" tabindex=\"-1\">\n" +
- " <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- "\n" +
- " <li role=\"menuitem\" ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" aria-label=\"{{item.title}}\" tabindex=\"-1\">\n" +
- " <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/select/select.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/select/select.html",
- "<div class=\"select2-container show-search\" ng-class=\"{'select2-dropdown-open': (showlist && !isDisabled),'select2-container-disabled': isDisabled, 'select2-container-active': isact}\" ng-init=\"isact=false;\">\n" +
- " <span class=\"select2-choice needsclick\" tabindex=\"{{isDisabled ? -1 : 0}}\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" role=\"combobox\" aria-expanded=\"{{showlist}}\" aria-owns=\"inList\" aria-label=\"{{titleName}} dropdown {{selectedOption}} selected\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
- " <span class=\"select2-chosen needsclick\" aria-hidden=\"true\" ng-bind-html=\"selectedOption | unsafe\">{{selectedOption}}</span>\n" +
- " <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
- " <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
- " <b role=\"presentation\" class=\"needsclick\"></b>\n" +
- " </span>\n" +
- " </span> \n" +
- " <input class=\"select2-focusser select2-offscreen\" \n" +
- " tabindex=\"-1\" \n" +
- " type=\"text\" \n" +
- " aria-hidden=\"true\" \n" +
- " title=\"hidden\" \n" +
- " aria-haspopup=\"true\" \n" +
- " role=\"button\"> \n" +
- "</div>\n" +
- "\n" +
- "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled)}\" style=\"width:100%;z-index: 10\">\n" +
- " <div class=\"select2-search\">\n" +
- " <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
- " <input ng-if=\"!noFilter\" ng-model=\"title\" aria-label=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
- " </div>\n" +
- " <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
- " <li ng-if=\"!noFilter\" ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
- " <li ng-if=\"!noFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\" ng-click=\"selectOption(selectMsg, '-1')\" ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\" ng-mouseover=\"hoverIn(-1)\" aria-label=\"{{selectMsg}}\" tabindex=\"-1\">\n" +
- " <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- "\n" +
- " <li role=\"menuitem\" ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" tabindex=\"-1\">\n" +
- " <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- "\n" +
- " <li role=\"menuitem\" ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" tabindex=\"-1\">\n" +
- " <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
- " <span class=\"select2-match\"></span>\n" +
- " </div>\n" +
- " </li>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",
- "<div tabindex=\"0\" class=\"text-dropdown\">\n" +
- " <div class=\"dropdown\" ng-class=\"{'not-visible': isActionsShown}\" ng-click=\"toggle()\">\n" +
- " <span class=\"action--selected\" ng-bind=\"currentAction\"></span>\n" +
- " <i ng-class=\"isActionsShown ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"></i>\n" +
- " </div>\n" +
- " <ul ng-class=\"isActionsShown ? 'actionsOpened' : 'actionsClosed'\" ng-show=\"isActionsShown\">\n" +
- " <li ng-class=\"{'highlight': selectedIndex==$index}\" ng-repeat=\"action in actions track by $index\" ng-click=\"chooseAction($event, action, $index)\" ng-mouseover=\"hoverIn($index)\">{{action}}<i ng-class=\"{'icon-included-checkmark': isCurrentAction(action)}\" att-accessibility-click=\"13,32\"></i></li>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",
- "<div class=\"att-slider__label att-slider__label--max att-slider__label--below\" ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/slider/minContent.html",
- "<div class=\"att-slider__label att-slider__label--min att-slider__label--below\" ng-transclude></div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/slider/slider.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/slider/slider.html",
- "<div class=\"att-slider\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\">\n" +
- " <div class=\"att-slider__track\">\n" +
- " <div class=\"att-slider__range att-slider__range--disabled\" ng-style=\"disabledStyle\"></div>\n" +
- " <div class=\"att-slider__range\" ng-style=\"rangeStyle\"></div>\n" +
- " </div>\n" +
- " <div class=\"att-slider__handles-container\">\n" +
- " <div role=\"menuitem\" aria-label=\"{{ngModelSingle}}\" class=\"att-slider__handle\" ng-style=\"handleStyle\" ng-mousedown=\"mouseDown($event,'ngModelSingle')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keydown=\"keyDown($event,'ngModelSingle')\"></div>\n" +
- " <div role=\"menuitem\" aria-label=\"Minimum Value- {{ngModelLow}}\" class=\"att-slider__handle\" ng-style=\"minHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelLow')\" ng-focus=\"focus($event,'ngModelLow')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keyup=\"keyUp($event,'ngModelLow')\" ng-keydown=\"keyDown($event,'ngModelLow')\"></div>\n" +
- " <div role=\"menuitem\" aria-label=\"Maximum Value- {{ngModelHigh}}\" class=\"att-slider__handle\" ng-style=\"maxHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelHigh')\" ng-focus=\"focus($event,'ngModelHigh')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keyup=\"keyUp($event,'ngModelHigh')\" ng-keydown=\"keyDown($event,'ngModelHigh')\"></div>\n" +
- " </div>\n" +
- " <div ng-transclude></div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",
- "<div class=\" btn-group\" \n" +
- " ng-class=\"{'buttons-dropdown--large':!isSmall, \n" +
- " 'buttons-dropdown--small':isSmall, \n" +
- " 'action-dropdown':(isActionDropdown), \n" +
- " 'open':isDropDownOpen}\">\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"button btn buttons-dropdown__split\" \n" +
- " ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
- " 'button--secondary':btnType=='secondary', \n" +
- " 'button--disabled':btnType=='disabled', \n" +
- " 'button--small':isSmall}\" \n" +
- " ng-if=\"!isActionDropdown\"\n" +
- " ng-click=\"btnType==='disabled'?undefined:clickFxn()\" att-accessibility-click=\"13,32\">{{btnText}}</a>\n" +
- " <a tabindex=\"0\" href=\"javascript:void(0)\" role=\"button\" aria-label=\"Toggle Dropdown\" aria-haspopup=\"true\" class=\"button buttons-dropdown__drop dropdown-toggle\" \n" +
- " ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
- " 'button--secondary':btnType=='secondary', \n" +
- " 'button--disabled':btnType=='disabled', \n" +
- " 'button--small':isSmall}\" ng-click=\"toggleDropdown()\" att-accessibility-click=\"13,32\">{{toggleTitle}} </a>\n" +
- " <ul class=\"dropdown-menu\" ng-class=\"{'align-right':multiselect ===true}\" aria-expanded=\"{{isDropDownOpen}}\" ng-click=\"hideDropdown()\" role=\"menu\" ng-transclude></ul>\n" +
- "</div> ");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",
- "<li role=\"menuitem\" att-element-focus=\"sFlag\" tabindex=\"0\" ng-transclude></li>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",
- "<div class='split-icon-button-container'>\n" +
- "\n" +
- " <div class='split-icon-button' ng-class=\"{'icon-with-chevron': isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown, 'split-icon-button-middle':isMiddle, 'split-icon-button-right':isRight, 'split-icon-button-left':isLeft, 'split-icon-button-left-dropdown': isLeftNextDropdown ,'split-icon-button-next-dropdown': isNextToDropDown,'split-icon-button-dropdown': isDropDownOpen,'split-icon-button-hover':isIconHovered || isDropDownOpen}\" ng-mouseover='isIconHovered = true;' ng-mouseleave='isIconHovered = false;' tabindex=\"-1\" att-accessibility-click=\"13,32\" ng-click='dropDownClicked();'>\n" +
- " <a class='{{icon}}' title='{{iconTitle}}' tabindex=\"0\"></a>\n" +
- " <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n" +
- " ng-class=\"isDropDownOpen ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"> </i>\n" +
- " </div> \n" +
- "\n" +
- " <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n" +
- " isDropDownOpen' ng-click='toggleDropdown(false)' role=\"presentation\" ng-transclude>\n" +
- " </ul>\n" +
- "\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",
- "<div>\n" +
- " <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n" +
- " <div ng-click='clickHandler()' att-split-icon icon='{{icon}}' title='{{title}}' dir-type='{{iconStateConstants.DIR_TYPE.BUTTON}}' hover-watch='isHovered' drop-down-watch='dropDownWatch' drop-down-id='{{dropDownId}}'>\n" +
- " <div ng-transclude>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",
- "<div ng-transclude>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",
- "<span ng-class=\"mainSliderClass\">\n" +
- " <table>\n" +
- " <tr>\n" +
- " <td>\n" +
- " <div class=\"jslider-bg\">\n" +
- " <i class=\"l\"></i>\n" +
- " <i class=\"r\"></i>\n" +
- " <i class=\"v\" ng-class=\"{'step-slider-green':sliderColor == COLORS.GREEN, 'step-slider-blue': sliderColor == COLORS.BLUE_HIGHLIGHT, 'step-slider-magenta': sliderColor == COLORS.MAGENTA, 'step-slider-gold': sliderColor == COLORS.GOLD, 'step-slider-purple': sliderColor == COLORS.PURPLE, 'step-slider-dark-blue': sliderColor == COLORS.DARK_BLUE, 'step-slider-regular': sliderColor == COLORS.REGULAR, 'step-slider-white': sliderColor == COLORS.WHITE, 'cutoff-slider': isCutOffSlider}\"></i>\n" +
- " </div>\n" +
- " <div class=\"jslider-pointer\" id=\"left-pointer\"></div>\n" +
- " <div class=\"jslider-pointer jslider-pointer-to\" ng-class=\"{'step-slider-green':sliderColor == COLORS.GREEN, 'step-slider-blue': sliderColor == COLORS.BLUE_HIGHLIGHT, 'step-slider-magenta': sliderColor == COLORS.MAGENTA, 'step-slider-gold': sliderColor == COLORS.GOLD, 'step-slider-purple': sliderColor == COLORS.PURPLE, 'step-slider-dark-blue': sliderColor == COLORS.DARK_BLUE, 'step-slider-regular': sliderColor == COLORS.REGULAR, 'step-slider-white':sliderColor == COLORS.WHITE ,'cutoff-slider': isCutOffSlider}\"></div>\n" +
- " <div class=\"jslider-label\"><span ng-bind=\"from\"></span><span ng-bind=\"options.dimension\"></span></div>\n" +
- " <div class=\"jslider-label jslider-label-to\"><span ng-bind=\"toStr\"></span><span ng-bind=\"endDimension\"></span></div>\n" +
- " <div class=\"jslider-value\" id=\"jslider-value-left\"><span></span>{{options.dimension}}</div>\n" +
- " <div class=\"jslider-value jslider-value-to\"><span></span>{{toolTipDimension}}</div>\n" +
- " <div class=\"jslider-scale\" ng-class=\"{'show-dividers': showDividers, 'cutoff-slider-dividers':isCutOffSlider}\">\n" +
- " </div>\n" +
- " <div class=\"jslider-cutoff\">\n" +
- " <div class=\"jslider-label jslider-label-cutoff\">\n" +
- " <span ng-bind=\"cutOffVal\"></span>\n" +
- " </div>\n" +
- " </div>\n" +
- " </td>\n" +
- " </tr>\n" +
- " </table>\n" +
- "</span>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",
- "<div class=\"steptracker1\">\n" +
- " <div class=\"steptracker-bg\">\n" +
- " <div tabindex=\"0\" ng-click=\"stepclick($event, $index);\" att-accessibility-click=\"13,23\" class=\"steptracker-track size-onethird\" ng-repeat=\"step in sdata\"\n" +
- " ng-style=\"set_width($index)\"\n" +
- " ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index), 'incomplete': isIncomplete($index), 'disabled': disableClick}\">\n" +
- " <div class=\"circle\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
- " <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
- " </div>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step.html",
- "<div class=\"steptracker1\">\n" +
- " <div class=\"steptracker-bg\">\n" +
- " <div class=\"steptracker-track size-onethird\" \n" +
- " ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index)}\">\n" +
- " <div class=\"circle\" tabindex=\"0\" \n" +
- " ng-click=\"stepclick($event, $index);\" \n" +
- " att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
- " <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
- " </div>\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html",
- "<div class='att-timeline'>\n" +
- " <div timeline-dot order='0' title='{{steps[0].title}}' description='{{steps[0].description}}' by='{{steps[0].by}}' date='{{steps[0].date}}' type='{{steps[0].type}}'></div>\n" +
- "\n" +
- " <div ng-repeat=\"m in middleSteps track by $index\">\n" +
- " <div timeline-bar order='{{$index}}'></div>\n" +
- " <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n" +
- " </div>\n" +
- " </div>\n" +
- "\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",
- "<div class='timeline-bar'>\n" +
- " <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
- " </div>\n" +
- " <hr></hr>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",
- "<div class='timeline-dot'>\n" +
- "\n" +
- " <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
- " </div>\n" +
- "\n" +
- " <div class='inactive-circle'>\n" +
- " </div>\n" +
- "\n" +
- " <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
- " </div>\n" +
- "\n" +
- " <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\" tabindex=\"0\">\n" +
- " \n" +
- " <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n" +
- " </div>\n" +
- "\n" +
- " <div class='info-container' ng-init='isContentShown=false'>\n" +
- " <div ng-class=\"{'current-step-title':isCurrentStep, 'title':!isCurrentStep,'completed-color-text':isCompleted,'cancelled-color-text':isCancelled,'alert-color-text':isAlert, 'inactive-color-text':isInactive}\" ng-mouseover='titleMouseover(1)' ng-mouseleave='titleMouseleave()' ng-bind='title' ></div>\n" +
- " <div class='content'>\n" +
- " <div class='description' ng-bind='description'></div>\n" +
- " <div class='submitter' ng-bind='by'></div>\n" +
- " </div>\n" +
- " <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave()' ng-bind='date'></div>\n" +
- " </div>\n" +
- "\n" +
- " <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n" +
- " </div>\n" +
- " </div>\n" +
- "\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/table/attTable.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/table/attTable.html",
- "<table class=\"tablesorter tablesorter-default\" ng-transclude></table>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableBody.html",
- "<td ng-transclude></td>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html",
- "<th role=\"columnheader\" scope=\"col\" aria-live=\"polite\" aria-sort=\"{{sortPattern !== 'null' && '' || sortPattern}}\" aria-label=\"{{headerName}} {{sortable !== 'false' && ': activate to sort' || ' '}} {{sortPattern !== 'null' && '' || sortPattern}}\" tabindex=\"{{sortable !== 'false' && '0' || '-1'}}\" class=\"tablesorter-header\" ng-class=\"{'tablesorter-headerAsc': sortPattern === 'ascending', 'tablesorter-headerDesc': sortPattern === 'descending', 'tablesort-sortable': sortable !== 'false', 'sorter-false': sortable === 'false'}\" att-accessibility-click=\"13,32\" ng-click=\"(sortable !== 'false') && sort();\"><div class=\"tablesorter-header-inner\" ng-transclude></div></th>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",
- "<div class=\"att-table-message\">\n" +
- " <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching\">\n" +
- " <div class=\"img-magnify-glass\"></div> \n" +
- " <div>\n" +
- " <div ng-transclude></div>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading\">\n" +
- " <div class=\"img-oops-exclamation\" tabindex=\"0\" aria-label=\"Oops! The information could not load at this time. Please click link to refresh the page.\"></div> \n" +
- " <div>Oops!</div>\n" +
- " <div>The information could not load at this time.</div>\n" +
- " <div>Please <a href=\"javascript:void(0)\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch\">\n" +
- " <div class=\"img-magnify-glass\"></div>\n" +
- " <div>\n" +
- " <p class=\"title\" tabindex=\"0\">Please input values to <br/> begin your search.</p>\n" +
- " </div>\n" +
- " </div>\n" +
- " <div class=\"message loading-message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading\">\n" +
- " <div class=\"img-loading-dots\"></div>\n" +
- " <div ng-transclude></div>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",
- "<div class=\"att-user-message\">\n" +
- " <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? 'message-wrapper-error' : 'hidden'\">\n" +
- " <div class=\"message-icon-error\"> <i class=\"icon-info-alert\"></i> </div>\n" +
- "\n" +
- " <div class=\"message-body-wrapper\">\n" +
- " <div class=\"message-title-error\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span> </div>\n" +
- " <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
- " <div class=\"message-bottom\">\n" +
- " <div ng-transclude></div>\n" +
- " </div>\n" +
- " </div>\n" +
- "\n" +
- " </div>\n" +
- " <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? 'message-wrapper-success' : 'hidden'\">\n" +
- " <div class=\"message-icon-success\"> <i class=\"icon-included-checkmark\"></i></div>\n" +
- "\n" +
- " <div class=\"message-body-wrapper\">\n" +
- " <div class=\"message-title-success\" ng-if=\"thetitle && thetitle.length > 0\" >\n" +
- " <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span>\n" +
- " </div>\n" +
- " <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
- " <div class=\"message-bottom\">\n" +
- " <div ng-transclude></div>\n" +
- " </div>\n" +
- " </div>\n" +
- "\n" +
- " </div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",
- "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
- " <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActiveTab(tab.url), 'tabsbid__item': !isActiveTab(tab.url)}\" ng-click=\"onClickTab(tab)\">\n" +
- " <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
- " </li>\n" +
- "</ul>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",
- "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
- " <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActive(tab.id), 'tabsbid__item': !isActive(tab.id),'tabs__item--active': isActive(tab.id)}\" ng-click=\"clickTab(tab)\">\n" +
- " <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
- " </li>\n" +
- "</ul>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",
- "<li class=\"megamenu__item\" ng-mouseover=\"showHoverChild($event)\" ng-class=\"{'tabs__item--active': menuItem.active==true && !hoverChild==true}\">\n" +
- " <span role=\"menuitem\" att-accessibility-click=\"13,32\" tabindex=\"0\" ng-click=\"showChildren($event);!clickInactive||resetMenu($event)\">{{tabName}}</span>\n" +
- " <div ng-transclude></div>\n" +
- "</li>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",
- "<div ng-class=\"{'megamenu-tabs': megaMenu,'submenu-tabs': !megaMenu}\">\n" +
- " <ul class=\"megamenu__items\" role=\"presentation\" ng-transclude>\n" +
- " </ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",
- "<div class=\"simplified-tabs\">\n" +
- "<ul class=\"simplified-tabs__items\" role=\"tablist\">\n" +
- " <li ng-repeat=\"tab in tabs\" role=\"tab\" class=\"simplified-tabs__item\" ng-class=\"{'tabs__item--active': isActive(tab.id)}\" ng-click=\"clickTab(tab)\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</li>\n" +
- " <li class=\"tabs__pointer\"></li>\n" +
- "</ul>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",
- "<li class=\"tabsbid__item megamenu__item\" ng-class=\"{'subMenuHover': menuItem.active==true}\">\n" +
- "<a ng-href=\"{{tabUrl}}\" role=\"menuitem\" ng-if=\"subMenu === true\" ng-mouseover=\"!subMenu || showChildren($event)\" ng-focus=\"!subMenu ||showChildren($event)\" tabindex=\"{{subMenu=='true'?0:-1}}\" ng-click=\"!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)\" att-accessibility-click=\"13,32\">{{tabName}}</a>\n" +
- "<a ng-href=\"{{tabUrl}}\" role=\"menuitem\" ng-if=\"!menuItem.leafNode && subMenu !== true\" ng-mouseover=\"!subMenu || showChildren($event)\" ng-focus=\"!subMenu ||showChildren($event)\" tabindex=\"{{subMenu=='true'?0:-1}}\" ng-click=\"!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)\" att-accessibility-click=\"13,32\">{{tabName}}</a>\n" +
- "<span ng-transclude></span>\n" +
- "</li>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",
- "<div class=\"tags__item\" \n" +
- " ng-class=\"{'tags__item--small':isSmall, \n" +
- " 'tags__item--color':isColor, \n" +
- " 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n" +
- " ng-if=\"display\" \n" +
- " ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n" +
- " ng-mousedown=\"activeHighlight(true)\" role=\"presentation\" ng-mouseup=\"activeHighlight(false)\">\n" +
- " <i class=\"icon-filter tags__item--icon\" ng-if=\"isIcon\">&nbsp;</i>\n" +
- " <i class=\"tags__item--color-icon\" ng-if=\"isColor\" ng-style=\"{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}\"></i>\n" +
- " <span class=\"tags__item--title\" role=\"presentation\" tabindex=0 ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\" ng-transclude></span>\n" +
- " <a href=\"javascript:void(0)\" title=\"Dismiss Link\" class=\"tags__item--action\" ng-click=\"closeMe();$event.preventDefault()\" ng-if=\"isClosable\"\n" +
- " ng-style=\"{color: (isHighlight && '#444') || '#888' , borderLeft: (isHighlight && '1px solid #444')|| '1px solid #888' }\">\n" +
- " <i class=\"icon-erase\">&nbsp;</i>\n" +
- " </a>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",
- "<span ng-transclude></span>\n" +
- "<div class=\"att-switch-content\" hm-drag = \"drag($event)\" att-accessibility-click=\"13,32\" ng-click=\"updateModel($event)\" hm-dragstart=\"alert('hello')\" hm-dragend=\"drag($event)\" ng-class=\"{'large' : directiveValue == 'large'}\" style=\"-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\">\n" +
- " <div class=\"att-switch-onText\" ng-style=\"\" ng-class=\"{'icon-included-checkmark ico' : on === undefined,'large' : directiveValue == 'large'}\">{{on}}<span class=\"hidden-spoken\">{{directiveValue}} when checked.</span></div>\n" +
- " <div class=\"att-switch-thumb\" tabindex=\"0\" title=\"Toggle switch\" role=\"checkbox\" ng-class=\"{'large' : directiveValue == 'large'}\"></div>\n" +
- " <div class=\"att-switch-offText\" ng-class=\"{'icon-erase ico' : on === undefined,'large' : directiveValue == 'large'}\">{{off}}<span class=\"hidden-spoken\">{{directiveValue}} when unchecked.</span></div>\n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",
- "<div class=\"typeahead mainContainerOuter\">\n" +
- " <span class=\"message\">To</span>\n" +
- " <div class='maincontainer' ng-click=\"setFocus()\" ng-focus=\"inputActive=true\" ng-class =\"{'typeahed_active':inputActive || (lineItems.length && inputActive)}\">\n" +
- " <span tag-badges closable ng-repeat =\"lineItem in lineItems track by $index\" on-close=\"theMethodToBeCalled($index)\" >{{lineItem}}</span>\n" +
- " <input type=\"text\" focus-me=\"clickFocus\" ng-focus=\"inputActive=true\" ng-model=\"model\" ng-keydown=\"selected = false; selectionIndex($event)\"/><br/> \n" +
- " </div>\n" +
- " <div ng-hide=\"!model.length || selected\">\n" +
- " <div class=\"filtercontainer list-scrollable\" ng-show=\"( items | filter:model).length\">\n" +
- " <div class=\"item\" ng-repeat=\"item in items| filter:model track by $index\" ng-click=\"handleSelection(item[titleName],item[subtitle])\" att-accessibility-click=\"13,32\" ng-class=\"{active:isCurrent($index,item[titleName],item[subtitle],( items | filter:model).length)}\"ng-mouseenter=\"setCurrent($index)\">\n" +
- " <span class=\"title\" >{{item[titleName]}}</span>\n" +
- " <span class=\"subtitle\">{{item[subtitle]}}</span>\n" +
- " </div> \n" +
- " </div>\n" +
- " </div>\n" +
- " \n" +
- " <div class=\"textAreaEmailContentDiv\">\n" +
- " <span class=\"message\">Message</span>\n" +
- " <textarea rows=\"4\" cols=\"50\" role=\"textarea\" class=\"textAreaEmailContent\" ng-model=\"emailMessage\">To send \n" +
- " a text, picture, or video message1 to a wireless device from your email:my message.</textarea>\n" +
- " \n" +
- " </div>\n" +
- " \n" +
- "</div>\n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",
- "<li>\n" +
- " <i ng-class=\"{'icon-tickets-active' : type == 'actual' && id =='Active','icon-tickets-referred' : type == 'actual' && id =='Requested Closed','icon-ticket-regular' : type == 'progress' && id =='In Progress','icon-tickets-contested' : type == 'actual' && id =='Contested','icon-tickets-returned' : type == 'actual' && id =='Deferred','icon-tickets-closed' : type == 'actual' && id =='Ready to Close','icon-tickets-cleared' : type == 'actual' && id =='Cleared'}\"></i>\n" +
- " <span ng-transclude></span>\n" +
- "</li>\n" +
- " \n" +
- "");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",
- "<div>\n" +
- " <a title=\"{{links.prevLink}}\" aria-label=\"Previous Link\" ng-href=\"{{links.prevLink}}\"><i alt=\"previous\" class=\"icon-arrow-left\">&nbsp;</i></a>\n" +
- " <span ng-transclude></span>\n" +
- " <a title=\"{{links.nextLink}}\" aria-label=\"Next Link\" ng-href=\"{{links.nextLink}}\"><i alt=\"next\" class=\"icon-arrow-right\">&nbsp;</i></a>\n" +
- "</div>");
-}]);
-
-angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html", []).run(["$templateCache", function($templateCache) {
- $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",
- "<div class=\"video-player\">\n" +
- " <div class=\"video-player__control video-player__play-button\">\n" +
- " <a class=\"video-player__button gigant-play\" data-toggle-buttons=\"icon-play, icon-pause\" data-target=\"i\"><i class=\"icon-play\" alt=\"Play/Pause Button\"></i></a>\n" +
- " </div>\n" +
- " <div class=\"video-player__control video-player__track\">\n" +
- "\n" +
- " <div class=\"video-player__track--inner\">\n" +
- " <div class=\"video-player__track--loaded\" style=\"width: 75%\"></div>\n" +
- " <div class=\"video-player__track--played\" style=\"width: 40%\">\n" +
- " <div class=\"att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip\" ng-transclude></div>\n" +
- " <div class=\"video-player__track-handle\"></div>\n" +
- " </div>\n" +
- " </div>\n" +
- " </div>\n" +
- " <a class=\"video-player__time\" ng-transclude></a>\n" +
- " <div class=\"video-player__control video-player__volume_icon\">\n" +
- " <a class=\"video-player__button\" data-toggle-buttons=\"icon-volume-mute, icon-volume-up\" data-target=\"i\"><i class=\"icon-volume-up\" alt=\"Volume Button\"></i></a>\n" +
- " </div>\n" +
- " <ul class=\"video-player__control video-player__volume\">\n" +
- " <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
- " <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
- " <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
- " <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
- " <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
- " </ul>\n" +
- " <div class=\"video-player__control video-player__toggle-fullscreen-button\">\n" +
- " <a class=\"video-player__button\" data-toggle-buttons=\"icon-full-screen, icon-normal-screen\" data-target=\"i\"><i class=\"icon-full-screen\" alt=\"Full Screen Button\">&nbsp;</i></a>\n" +
- " </div>\n" +
- "</div>");
-}]);
-
-return {}
-})(angular, window); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.min.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.min.js
deleted file mode 100644
index 31c5ec3b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/att-abs-tpls.min.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
-* FileName att-style-guide
-* Version 2.17.0
-* Build number 5c64ecd381d5984c483cdfaa078a1890
-* Date 11/23/2015
-*/
-
-(function(angular, window){
-angular.module("att.abs",["att.abs.tpls","att.abs.utilities","att.abs.position","att.abs.transition","att.abs.accordion","att.abs.alert","att.abs.boardStrip","att.abs.breadCrumbs","att.abs.buttons","att.abs.checkbox","att.abs.colorselector","att.abs.datepicker","att.abs.devNotes","att.abs.dividerLines","att.abs.dragdrop","att.abs.drawer","att.abs.message","att.abs.formField","att.abs.hourpicker","att.abs.iconButtons","att.abs.links","att.abs.loading","att.abs.modal","att.abs.pagination","att.abs.paneSelector","att.abs.tooltip","att.abs.popOvers","att.abs.profileCard","att.abs.progressBars","att.abs.radio","att.abs.scrollbar","att.abs.search","att.abs.select","att.abs.slider","att.abs.splitButtonDropdown","att.abs.splitIconButton","att.abs.stepSlider","att.abs.steptracker","att.abs.table","att.abs.tableMessages","att.abs.tabs","att.abs.tagBadges","att.abs.textOverflow","att.abs.toggle","att.abs.treeview","att.abs.typeAhead","att.abs.verticalSteptracker","att.abs.videoControls"]),angular.module("att.abs.tpls",["app/scripts/ng_js_att_tpls/accordion/accordion.html","app/scripts/ng_js_att_tpls/accordion/accordion_alt.html","app/scripts/ng_js_att_tpls/accordion/attAccord.html","app/scripts/ng_js_att_tpls/accordion/attAccordBody.html","app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html","app/scripts/ng_js_att_tpls/alert/alert.html","app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html","app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html","app/scripts/ng_js_att_tpls/colorselector/colorselector.html","app/scripts/ng_js_att_tpls/datepicker/dateFilter.html","app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html","app/scripts/ng_js_att_tpls/datepicker/datepicker.html","app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html","app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html","app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html","app/scripts/ng_js_att_tpls/formField/creditCardImage.html","app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html","app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html","app/scripts/ng_js_att_tpls/links/readMore.html","app/scripts/ng_js_att_tpls/loading/loading.html","app/scripts/ng_js_att_tpls/modal/backdrop.html","app/scripts/ng_js_att_tpls/modal/tabbedItem.html","app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html","app/scripts/ng_js_att_tpls/modal/window.html","app/scripts/ng_js_att_tpls/pagination/pagination.html","app/scripts/ng_js_att_tpls/paneSelector/innerPane.html","app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html","app/scripts/ng_js_att_tpls/paneSelector/sidePane.html","app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html","app/scripts/ng_js_att_tpls/popOvers/popOvers.html","app/scripts/ng_js_att_tpls/profileCard/addUser.html","app/scripts/ng_js_att_tpls/profileCard/profileCard.html","app/scripts/ng_js_att_tpls/progressBars/progressBars.html","app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html","app/scripts/ng_js_att_tpls/search/search.html","app/scripts/ng_js_att_tpls/select/select.html","app/scripts/ng_js_att_tpls/select/textDropdown.html","app/scripts/ng_js_att_tpls/slider/maxContent.html","app/scripts/ng_js_att_tpls/slider/minContent.html","app/scripts/ng_js_att_tpls/slider/slider.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html","app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html","app/scripts/ng_js_att_tpls/steptracker/step-tracker.html","app/scripts/ng_js_att_tpls/steptracker/step.html","app/scripts/ng_js_att_tpls/steptracker/timeline.html","app/scripts/ng_js_att_tpls/steptracker/timelineBar.html","app/scripts/ng_js_att_tpls/steptracker/timelineDot.html","app/scripts/ng_js_att_tpls/table/attTable.html","app/scripts/ng_js_att_tpls/table/attTableBody.html","app/scripts/ng_js_att_tpls/table/attTableHeader.html","app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html","app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html","app/scripts/ng_js_att_tpls/tabs/floatingTabs.html","app/scripts/ng_js_att_tpls/tabs/genericTabs.html","app/scripts/ng_js_att_tpls/tabs/menuTab.html","app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html","app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html","app/scripts/ng_js_att_tpls/tabs/submenuTab.html","app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html","app/scripts/ng_js_att_tpls/toggle/demoToggle.html","app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html","app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html","app/scripts/ng_js_att_tpls/videoControls/photoControls.html","app/scripts/ng_js_att_tpls/videoControls/videoControls.html"]),angular.module("att.abs.utilities",[]).filter("unsafe",["$sce",function(a){return function(b){return a.trustAsHtml(b)}}]).filter("highlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c,d){return c&&b?b.replace(new RegExp(a(c),"gi"),'<span class="'+d+'">$&</span>'):b}}).filter("attLimitTo",function(){return function(a,b,c){var d=[],e=b,f=c;return isNaN(f)&&(f=0),d=a&&!isNaN(e)?a.slice(f,f+e):a}}).filter("startsWith",function(){return"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(a){return 0===this.indexOf(a)}),function(a,b){if(void 0===b||""===b)return a;var c=[];return angular.forEach(a,function(a){a.title.toLowerCase().startsWith(b.toLowerCase())&&c.push(a)}),c}}).directive("attInputDeny",[function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){var e=null;c.$observe("attInputDeny",function(a){a&&(e=new RegExp(a,"g"))}),b.bind("input",function(){var b=d.$viewValue&&d.$viewValue.replace(e,"");b!==d.$viewValue&&(d.$setViewValue(b),d.$render(),a.$apply())})}}}]).directive("attAccessibilityClick",[function(){return{restrict:"A",link:function(a,b,c){var d=[];c.$observe("attAccessibilityClick",function(a){a&&(d=a.split(","))}),b.bind("keydown",function(a){var c=function(){var b=!1;return a.keyCode||(a.which?a.keyCode=a.which:a.charCode&&(a.keyCode=a.charCode)),a.keyCode&&d.indexOf(a.keyCode.toString())>-1&&(b=!0),b};d.length>0&&c()&&(b[0].click(),a.preventDefault())})}}}]).directive("attElementFocus",[function(){return{restrict:"A",link:function(a,b,c){a.$watch(c.attElementFocus,function(a){a&&b[0].focus()})}}}]).directive("focusOn",["$timeout",function(a){var b=function(a){if(!a.focusOn&&""!==a.focusOn)throw"FocusOnCondition missing attribute to evaluate"};return{restrict:"A",link:function(c,d,e){b(e),c.$watch(e.focusOn,function(b){b&&a(function(){d[0].focus()})})}}}]).constant("whenScrollEndsConstants",{threshold:100,width:0,height:0}).directive("whenScrollEnds",function(a,b){return{restrict:"A",link:function(c,d,e){var f=parseInt(e.threshold,10)||a.threshold;return e.axis&&""!==e.axis?void("x"===e.axis?(visibleWidth=parseInt(e.width,10)||a.width,d.css("width")&&(visibleWidth=d.css("width").split("px")[0]),d[0].addEventListener("scroll",function(){var a=d.prop("scrollWidth");void 0===a&&(a=1);var b=a-visibleWidth;b-d[0].scrollLeft<=f&&c.$apply(e.whenScrollEnds)})):"y"===e.axis&&(visibleHeight=parseInt(e.height,10)||a.height,d.css("width")&&(visibleHeight=d.css("height").split("px")[0]),d[0].addEventListener("scroll",function(){var a=d.prop("scrollHeight");void 0===a&&(a=1);var b=a-visibleHeight;b-d[0].scrollTop<=f&&c.$apply(e.whenScrollEnds)}))):void b.warn("axis attribute must be defined for whenScrollEnds.")}}}).directive("validImei",function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){d.$parsers.unshift(function(b){if(b){if(a.valid=!1,isNaN(b)||15!==b.length)a.valid=!1;else{for(var c=0,e=[],f=0;15>f;f++)e[f]=parseInt(b.substring(f,f+1),10),f%2!==0&&(e[f]=parseInt(2*e[f],10)),e[f]>9&&(e[f]=parseInt(e[f]%10,10)+parseInt(e[f]/10,10)),c+=parseInt(e[f],10);c%10===0?a.valid=!0:a.valid=!1}d.$setValidity("invalidImei",a.valid)}return a.valid?b:void 0})}}}).directive("togglePassword",function(){return{restrict:"A",transclude:!1,link:function(a,b,c,d){b.bind("click",function(){var a=c.togglePassword;b[0].innerHTML="Show"===b[0].innerHTML?"Hide":"Show";var d=angular.element(document.querySelector("#"+a))[0].type;angular.element(document.querySelector("#"+a))[0].type="password"===d?"text":"password"})}}}).factory("events",function(){var a=function(a){a.stopPropagation?a.stopPropagation():a.returnValue=!1},b=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};return{stopPropagation:a,preventDefault:b}}).factory("$documentBind",["$document","$timeout",function(a,b){var c=function(c,d,e){e.$watch(c,function(c){b(function(){c?a.bind("click",d):a.unbind("click",d)})})},d=function(c,d,e,f,g,h){g?(h||(h=0),f.$watch(d,function(d,f){d!==f&&b(function(){d?a.bind(c,e):a.unbind(c,e)},h)})):f.$watch(d,function(b,d){b!==d&&(b?a.bind(c,e):a.unbind(c,e))})};return{click:c,event:d}}]).factory("DOMHelper",function(){function a(a){var b=angular.element(a),c=parseInt(b.attr("tabindex"),10)>=0?!0:!1,d=b[0].tagName.toUpperCase();return c||"A"===d||"INPUT"===d||"TEXTAREA"===d?!(b[0].disabled||b[0].readOnly):!1}function b(a){return 1==a.nodeType&&"SCRIPT"!=a.nodeName&&"STYLE"!=a.nodeName}function c(d){var d=d||document.getElementsByTagName("body")[0];if(b(d)&&a(d))return d;if(!d.hasChildNodes())return void 0;for(var e=d.firstChild;e;){var f=c(e);if(f)return f;e=e.nextSibling}}var d=function(a){var b=a;return a.hasOwnProperty("length")&&(b=a[0]),c(b)};return{firstTabableElement:d}}).factory("keymap",function(){return{KEY:{TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,COMMAND:91},MAP:{91:"COMMAND",8:"BACKSPACE",9:"TAB",13:"ENTER",16:"SHIFT",17:"CTRL",18:"ALT",19:"PAUSEBREAK",20:"CAPSLOCK",27:"ESC",32:"SPACE",33:"PAGE_UP",34:"PAGE_DOWN",35:"END",36:"HOME",37:"LEFT",38:"UP",39:"RIGHT",40:"DOWN",43:"+",44:"PRINTSCREEN",45:"INSERT",46:"DELETE",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NUMLOCK",145:"SCROLLLOCK",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},isControl:function(a){var b=a.keyCode;switch(b){case this.KEY.COMMAND:case this.KEY.SHIFT:case this.KEY.CTRL:case this.KEY.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.keyCode?a.keyCode:a,a>=112&&123>=a},isVerticalMovement:function(a){return~[this.KEY.UP,this.KEY.DOWN].indexOf(a)},isHorizontalMovement:function(a){return~[this.KEY.LEFT,this.KEY.RIGHT,this.KEY.BACKSPACE,this.KEY.DELETE].indexOf(a)},isAllowedKey:function(a){return~[this.KEY.SPACE,this.KEY.ESC,this.KEY.ENTER].indexOf(a)||this.isHorizontalMovement(a)||this.isVerticalMovement(a)}}}).factory("keyMapAc",function(){return{keys:{32:" ",33:"!",34:'"',35:"#",36:"$",37:"%",38:"&",39:"'",40:"(",41:")",42:"*",43:"+",44:",",45:"-",46:".",47:"/",58:":",59:";",60:"<",61:"=",62:">",63:"?",64:"@",91:"[",92:"\\",93:"]",94:"^",95:"_",96:"`",123:"{",124:"|",125:"}",126:"~"},keyRange:{startNum:"48",endNum:"57",startSmallLetters:"97",endSmallLetters:"122",startCapitalLetters:"65",endCapitalLetters:"90"},allowedKeys:{TAB:8,BACKSPACE:9,DELETE:16}}}).factory("$attElementDetach",function(){var a=function(a){a&&a.parentNode&&a.parentNode.removeChild(a)};return a}).factory("$ieVersion",function(){var ie=null,loadIEVersion=function(){var isIE10=eval("/*@cc_on!@*/false")&&10===document.documentMode;if(isIE10)return 10;var v=3,div=document.createElement("div"),all=div.getElementsByTagName("i");do div.innerHTML="<!--[if gt IE "+ ++v+"]><i></i><![endif]-->";while(all[0]);return v>4?v:void 0};return function(){return null===ie&&(ie=loadIEVersion()),ie}}),function(){String.prototype.toSnakeCase=function(){return this.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})};var a=function(a,b){a=a||"",b=!isNaN(b)&&b||0;for(var c="",d=0;b>d;d++)c+=a;return c},b=function(b,c,d,e){return b=b||"",c=!isNaN(c)&&c||0,d=d||"",c>b.length?e?a(d,c-b.length)+b:b+a(d,c-b.length):b};String.prototype.lPad=function(a,c){return b(this,a,c,!0)},String.prototype.rPad=function(a,c){return b(this,a,c,!1)},Array.prototype.indexOf||(Array.prototype.indexOf=function(a){for(var b=0;b<this.length;b++)if(this[b]===a)return b;return-1})}(),angular.module("att.abs.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);return f!==a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft),{width:b.prop("offsetWidth"),height:b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:c.prop("offsetWidth"),height:c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].body.scrollTop||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].body.scrollLeft||a[0].documentElement.scrollLeft)}}}}]).factory("$isElement",[function(){var a=function(b,c,d){return b[0]===c[0]?!0:b[0]===d[0]?!1:a(b.parent()[0]&&b.parent()||c,c,d)};return a}]).directive("attPosition",["$position",function(a){return{restrict:"A",link:function(b,c,d){b.$watchCollection(function(){return a.position(c)},function(a){b[d.attPosition]=a})}}}]),(window._gsQueue||(window._gsQueue=[])).push(function(){"use strict";var a=document.documentElement,b=window,c=function(c,d){var e="x"===d?"Width":"Height",f="scroll"+e,g="client"+e,h=document.body;return c===b||c===a||c===h?Math.max(a[f],h[f])-(b["inner"+e]||Math.max(a[g],h[g])):c[f]-c["offset"+e]},d=window._gsDefine.plugin({propName:"scrollTo",API:2,version:"1.7.3",init:function(a,d,e){return this._wdw=a===b,this._target=a,this._tween=e,"object"!=typeof d&&(d={y:d}),this._autoKill=d.autoKill!==!1,this.x=this.xPrev=this.getX(),this.y=this.yPrev=this.getY(),null!=d.x?(this._addTween(this,"x",this.x,"max"===d.x?c(a,"x"):d.x,"scrollTo_x",!0),this._overwriteProps.push("scrollTo_x")):this.skipX=!0,null!=d.y?(this._addTween(this,"y",this.y,"max"===d.y?c(a,"y"):d.y,"scrollTo_y",!0),this._overwriteProps.push("scrollTo_y")):this.skipY=!0,!0},set:function(a){this._super.setRatio.call(this,a);var d=this._wdw||!this.skipX?this.getX():this.xPrev,e=this._wdw||!this.skipY?this.getY():this.yPrev,f=e-this.yPrev,g=d-this.xPrev;this._autoKill&&(!this.skipX&&(g>7||-7>g)&&d<c(this._target,"x")&&(this.skipX=!0),!this.skipY&&(f>7||-7>f)&&e<c(this._target,"y")&&(this.skipY=!0),this.skipX&&this.skipY&&this._tween.kill()),this._wdw?b.scrollTo(this.skipX?d:this.x,this.skipY?e:this.y):(this.skipY||(this._target.scrollTop=this.y),this.skipX||(this._target.scrollLeft=this.x)),this.xPrev=this.x,this.yPrev=this.y}}),e=d.prototype;d.max=c,e.getX=function(){return this._wdw?null!=b.pageXOffset?b.pageXOffset:null!=a.scrollLeft?a.scrollLeft:document.body.scrollLeft:this._target.scrollLeft},e.getY=function(){return this._wdw?null!=b.pageYOffset?b.pageYOffset:null!=a.scrollTop?a.scrollTop:document.body.scrollTop:this._target.scrollTop},e._kill=function(a){return a.scrollTo_x&&(this.skipX=!0),a.scrollTo_y&&(this.skipY=!0),this._super._kill.call(this,a)}}),window._gsDefine&&window._gsQueue.pop()(),(window._gsQueue||(window._gsQueue=[])).push(function(){"use strict";window._gsDefine("TweenMax",["core.Animation","core.SimpleTimeline","TweenLite"],function(a,b,c){var d=[].slice,e=function(a,b,d){c.call(this,a,b,d),this._cycle=0,this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._dirty=!0,this.render=e.prototype.render},f=1e-10,g=c._internals,h=g.isSelector,i=g.isArray,j=e.prototype=c.to({},.1,{}),k=[];e.version="1.12.1",j.constructor=e,j.kill()._gc=!1,e.killTweensOf=e.killDelayedCallsTo=c.killTweensOf,e.getTweensOf=c.getTweensOf,e.lagSmoothing=c.lagSmoothing,e.ticker=c.ticker,e.render=c.render,j.invalidate=function(){return this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._uncache(!0),c.prototype.invalidate.call(this)},j.updateTo=function(a,b){var d,e=this.ratio;b&&this._startTime<this._timeline._time&&(this._startTime=this._timeline._time,this._uncache(!1),this._gc?this._enabled(!0,!1):this._timeline.insert(this,this._startTime-this._delay));for(d in a)this.vars[d]=a[d];if(this._initted)if(b)this._initted=!1;else if(this._gc&&this._enabled(!0,!1),this._notifyPluginsOfEnabled&&this._firstPT&&c._onPluginEvent("_onDisable",this),this._time/this._duration>.998){var f=this._time;this.render(0,!0,!1),this._initted=!1,this.render(f,!0,!1)}else if(this._time>0){this._initted=!1,this._init();for(var g,h=1/(1-e),i=this._firstPT;i;)g=i.s+i.c,i.c*=h,i.s=g-i.c,i=i._next}return this},j.render=function(a,b,c){this._initted||0===this._duration&&this.vars.repeat&&this.invalidate();var d,e,h,i,j,l,m,n,o=this._dirty?this.totalDuration():this._totalDuration,p=this._time,q=this._totalTime,r=this._cycle,s=this._duration,t=this._rawPrevTime;if(a>=o?(this._totalTime=o,this._cycle=this._repeat,this._yoyo&&0!==(1&this._cycle)?(this._time=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0):(this._time=s,this.ratio=this._ease._calcEnd?this._ease.getRatio(1):1),this._reversed||(d=!0,e="onComplete"),0===s&&(this._initted||!this.vars.lazy||c)&&(this._startTime===this._timeline._duration&&(a=0),(0===a||0>t||t===f)&&t!==a&&(c=!0,t>f&&(e="onReverseComplete")),this._rawPrevTime=n=!b||a||t===a?a:f)):1e-7>a?(this._totalTime=this._time=this._cycle=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0,(0!==q||0===s&&t>0&&t!==f)&&(e="onReverseComplete",d=this._reversed),0>a?(this._active=!1,0===s&&(this._initted||!this.vars.lazy||c)&&(t>=0&&(c=!0),this._rawPrevTime=n=!b||a||t===a?a:f)):this._initted||(c=!0)):(this._totalTime=this._time=a,0!==this._repeat&&(i=s+this._repeatDelay,this._cycle=this._totalTime/i>>0,0!==this._cycle&&this._cycle===this._totalTime/i&&this._cycle--,this._time=this._totalTime-this._cycle*i,this._yoyo&&0!==(1&this._cycle)&&(this._time=s-this._time),this._time>s?this._time=s:this._time<0&&(this._time=0)),this._easeType?(j=this._time/s,l=this._easeType,m=this._easePower,(1===l||3===l&&j>=.5)&&(j=1-j),3===l&&(j*=2),1===m?j*=j:2===m?j*=j*j:3===m?j*=j*j*j:4===m&&(j*=j*j*j*j),1===l?this.ratio=1-j:2===l?this.ratio=j:this._time/s<.5?this.ratio=j/2:this.ratio=1-j/2):this.ratio=this._ease.getRatio(this._time/s)),p===this._time&&!c&&r===this._cycle)return void(q!==this._totalTime&&this._onUpdate&&(b||this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||k)));if(!this._initted){if(this._init(),!this._initted||this._gc)return;if(!c&&this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration))return this._time=p,this._totalTime=q,this._rawPrevTime=t,this._cycle=r,g.lazyTweens.push(this),void(this._lazy=a);this._time&&!d?this.ratio=this._ease.getRatio(this._time/s):d&&this._ease._calcEnd&&(this.ratio=this._ease.getRatio(0===this._time?0:1))}for(this._lazy!==!1&&(this._lazy=!1),this._active||!this._paused&&this._time!==p&&a>=0&&(this._active=!0),0===q&&(2===this._initted&&a>0&&this._init(),this._startAt&&(a>=0?this._startAt.render(a,b,c):e||(e="_dummyGS")),this.vars.onStart&&(0!==this._totalTime||0===s)&&(b||this.vars.onStart.apply(this.vars.onStartScope||this,this.vars.onStartParams||k))),h=this._firstPT;h;)h.f?h.t[h.p](h.c*this.ratio+h.s):h.t[h.p]=h.c*this.ratio+h.s,h=h._next;this._onUpdate&&(0>a&&this._startAt&&this._startTime&&this._startAt.render(a,b,c),b||(this._totalTime!==q||d)&&this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||k)),this._cycle!==r&&(b||this._gc||this.vars.onRepeat&&this.vars.onRepeat.apply(this.vars.onRepeatScope||this,this.vars.onRepeatParams||k)),e&&(this._gc||(0>a&&this._startAt&&!this._onUpdate&&this._startTime&&this._startAt.render(a,b,c),d&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!b&&this.vars[e]&&this.vars[e].apply(this.vars[e+"Scope"]||this,this.vars[e+"Params"]||k),0===s&&this._rawPrevTime===f&&n!==f&&(this._rawPrevTime=0)))},e.to=function(a,b,c){return new e(a,b,c)},e.from=function(a,b,c){return c.runBackwards=!0,c.immediateRender=0!=c.immediateRender,new e(a,b,c)},e.fromTo=function(a,b,c,d){return d.startAt=c,d.immediateRender=0!=d.immediateRender&&0!=c.immediateRender,new e(a,b,d)},e.staggerTo=e.allTo=function(a,b,f,g,j,l,m){g=g||0;var n,o,p,q,r=f.delay||0,s=[],t=function(){f.onComplete&&f.onComplete.apply(f.onCompleteScope||this,arguments),j.apply(m||this,l||k)};for(i(a)||("string"==typeof a&&(a=c.selector(a)||a),h(a)&&(a=d.call(a,0))),n=a.length,p=0;n>p;p++){o={};for(q in f)o[q]=f[q];o.delay=r,p===n-1&&j&&(o.onComplete=t),s[p]=new e(a[p],b,o),r+=g}return s},e.staggerFrom=e.allFrom=function(a,b,c,d,f,g,h){return c.runBackwards=!0,c.immediateRender=0!=c.immediateRender,e.staggerTo(a,b,c,d,f,g,h)},e.staggerFromTo=e.allFromTo=function(a,b,c,d,f,g,h,i){return d.startAt=c,d.immediateRender=0!=d.immediateRender&&0!=c.immediateRender,e.staggerTo(a,b,d,f,g,h,i)},e.delayedCall=function(a,b,c,d,f){return new e(b,0,{delay:a,onComplete:b,onCompleteParams:c,onCompleteScope:d,onReverseComplete:b,onReverseCompleteParams:c,onReverseCompleteScope:d,immediateRender:!1,useFrames:f,overwrite:0})},e.set=function(a,b){return new e(a,0,b)},e.isTweening=function(a){return c.getTweensOf(a,!0).length>0};var l=function(a,b){for(var d=[],e=0,f=a._first;f;)f instanceof c?d[e++]=f:(b&&(d[e++]=f),d=d.concat(l(f,b)),e=d.length),f=f._next;return d},m=e.getAllTweens=function(b){return l(a._rootTimeline,b).concat(l(a._rootFramesTimeline,b))};e.killAll=function(a,c,d,e){null==c&&(c=!0),null==d&&(d=!0);var f,g,h,i=m(0!=e),j=i.length,k=c&&d&&e;for(h=0;j>h;h++)g=i[h],(k||g instanceof b||(f=g.target===g.vars.onComplete)&&d||c&&!f)&&(a?g.totalTime(g._reversed?0:g.totalDuration()):g._enabled(!1,!1))},e.killChildTweensOf=function(a,b){if(null!=a){var f,j,k,l,m,n=g.tweenLookup;if("string"==typeof a&&(a=c.selector(a)||a),h(a)&&(a=d.call(a,0)),i(a))for(l=a.length;--l>-1;)e.killChildTweensOf(a[l],b);else{f=[];for(k in n)for(j=n[k].target.parentNode;j;)j===a&&(f=f.concat(n[k].tweens)),j=j.parentNode;for(m=f.length,l=0;m>l;l++)b&&f[l].totalTime(f[l].totalDuration()),f[l]._enabled(!1,!1)}}};var n=function(a,c,d,e){c=c!==!1,d=d!==!1,e=e!==!1;for(var f,g,h=m(e),i=c&&d&&e,j=h.length;--j>-1;)g=h[j],(i||g instanceof b||(f=g.target===g.vars.onComplete)&&d||c&&!f)&&g.paused(a)};return e.pauseAll=function(a,b,c){n(!0,a,b,c)},e.resumeAll=function(a,b,c){n(!1,a,b,c)},e.globalTimeScale=function(b){var d=a._rootTimeline,e=c.ticker.time;return arguments.length?(b=b||f,d._startTime=e-(e-d._startTime)*d._timeScale/b,d=a._rootFramesTimeline,e=c.ticker.frame,d._startTime=e-(e-d._startTime)*d._timeScale/b,d._timeScale=a._rootTimeline._timeScale=b,b):d._timeScale},j.progress=function(a){return arguments.length?this.totalTime(this.duration()*(this._yoyo&&0!==(1&this._cycle)?1-a:a)+this._cycle*(this._duration+this._repeatDelay),!1):this._time/this.duration()},j.totalProgress=function(a){return arguments.length?this.totalTime(this.totalDuration()*a,!1):this._totalTime/this.totalDuration()},j.time=function(a,b){return arguments.length?(this._dirty&&this.totalDuration(),a>this._duration&&(a=this._duration),this._yoyo&&0!==(1&this._cycle)?a=this._duration-a+this._cycle*(this._duration+this._repeatDelay):0!==this._repeat&&(a+=this._cycle*(this._duration+this._repeatDelay)),this.totalTime(a,b)):this._time},j.duration=function(b){return arguments.length?a.prototype.duration.call(this,b):this._duration},j.totalDuration=function(a){return arguments.length?-1===this._repeat?this:this.duration((a-this._repeat*this._repeatDelay)/(this._repeat+1)):(this._dirty&&(this._totalDuration=-1===this._repeat?999999999999:this._duration*(this._repeat+1)+this._repeatDelay*this._repeat,this._dirty=!1),this._totalDuration)},j.repeat=function(a){return arguments.length?(this._repeat=a,this._uncache(!0)):this._repeat},j.repeatDelay=function(a){return arguments.length?(this._repeatDelay=a,this._uncache(!0)):this._repeatDelay},j.yoyo=function(a){return arguments.length?(this._yoyo=a,this):this._yoyo},e},!0),window._gsDefine("TimelineLite",["core.Animation","core.SimpleTimeline","TweenLite"],function(a,b,c){var d=function(a){b.call(this,a),this._labels={},this.autoRemoveChildren=this.vars.autoRemoveChildren===!0,this.smoothChildTiming=this.vars.smoothChildTiming===!0,this._sortChildren=!0,this._onUpdate=this.vars.onUpdate;var c,d,e=this.vars;for(d in e)c=e[d],g(c)&&-1!==c.join("").indexOf("{self}")&&(e[d]=this._swapSelfInParams(c));g(e.tweens)&&this.add(e.tweens,0,e.align,e.stagger)},e=1e-10,f=c._internals.isSelector,g=c._internals.isArray,h=[],i=window._gsDefine.globals,j=function(a){var b,c={};for(b in a)c[b]=a[b];return c},k=function(a,b,c,d){a._timeline.pause(a._startTime),b&&b.apply(d||a._timeline,c||h)},l=h.slice,m=d.prototype=new b;return d.version="1.12.1",m.constructor=d,m.kill()._gc=!1,m.to=function(a,b,d,e){var f=d.repeat&&i.TweenMax||c;return b?this.add(new f(a,b,d),e):this.set(a,d,e)},m.from=function(a,b,d,e){return this.add((d.repeat&&i.TweenMax||c).from(a,b,d),e)},m.fromTo=function(a,b,d,e,f){var g=e.repeat&&i.TweenMax||c;return b?this.add(g.fromTo(a,b,d,e),f):this.set(a,e,f)},m.staggerTo=function(a,b,e,g,h,i,k,m){var n,o=new d({onComplete:i,onCompleteParams:k,onCompleteScope:m,smoothChildTiming:this.smoothChildTiming});for("string"==typeof a&&(a=c.selector(a)||a),f(a)&&(a=l.call(a,0)),g=g||0,n=0;n<a.length;n++)e.startAt&&(e.startAt=j(e.startAt)),o.to(a[n],b,j(e),n*g);return this.add(o,h)},m.staggerFrom=function(a,b,c,d,e,f,g,h){return c.immediateRender=0!=c.immediateRender,c.runBackwards=!0,this.staggerTo(a,b,c,d,e,f,g,h)},m.staggerFromTo=function(a,b,c,d,e,f,g,h,i){return d.startAt=c,d.immediateRender=0!=d.immediateRender&&0!=c.immediateRender,this.staggerTo(a,b,d,e,f,g,h,i)},m.call=function(a,b,d,e){return this.add(c.delayedCall(0,a,b,d),e)},m.set=function(a,b,d){return d=this._parseTimeOrLabel(d,0,!0),null==b.immediateRender&&(b.immediateRender=d===this._time&&!this._paused),this.add(new c(a,0,b),d)},d.exportRoot=function(a,b){a=a||{},null==a.smoothChildTiming&&(a.smoothChildTiming=!0);var e,f,g=new d(a),h=g._timeline;for(null==b&&(b=!0),h._remove(g,!0),g._startTime=0,g._rawPrevTime=g._time=g._totalTime=h._time,e=h._first;e;)f=e._next,b&&e instanceof c&&e.target===e.vars.onComplete||g.add(e,e._startTime-e._delay),e=f;return h.add(g,0),g},m.add=function(e,f,h,i){var j,k,l,m,n,o;if("number"!=typeof f&&(f=this._parseTimeOrLabel(f,0,!0,e)),!(e instanceof a)){if(e instanceof Array||e&&e.push&&g(e)){for(h=h||"normal",i=i||0,j=f,k=e.length,l=0;k>l;l++)g(m=e[l])&&(m=new d({tweens:m})),this.add(m,j),"string"!=typeof m&&"function"!=typeof m&&("sequence"===h?j=m._startTime+m.totalDuration()/m._timeScale:"start"===h&&(m._startTime-=m.delay())),j+=i;return this._uncache(!0)}if("string"==typeof e)return this.addLabel(e,f);if("function"!=typeof e)throw"Cannot add "+e+" into the timeline; it is not a tween, timeline, function, or string.";e=c.delayedCall(0,e)}if(b.prototype.add.call(this,e,f),(this._gc||this._time===this._duration)&&!this._paused&&this._duration<this.duration())for(n=this,o=n.rawTime()>e._startTime;n._timeline;)o&&n._timeline.smoothChildTiming?n.totalTime(n._totalTime,!0):n._gc&&n._enabled(!0,!1),n=n._timeline;return this},m.remove=function(b){if(b instanceof a)return this._remove(b,!1);if(b instanceof Array||b&&b.push&&g(b)){for(var c=b.length;--c>-1;)this.remove(b[c]);return this}return"string"==typeof b?this.removeLabel(b):this.kill(null,b)},m._remove=function(a,c){b.prototype._remove.call(this,a,c);var d=this._last;return d?this._time>d._startTime+d._totalDuration/d._timeScale&&(this._time=this.duration(),this._totalTime=this._totalDuration):this._time=this._totalTime=this._duration=this._totalDuration=0,this},m.append=function(a,b){return this.add(a,this._parseTimeOrLabel(null,b,!0,a))},m.insert=m.insertMultiple=function(a,b,c,d){return this.add(a,b||0,c,d)},m.appendMultiple=function(a,b,c,d){return this.add(a,this._parseTimeOrLabel(null,b,!0,a),c,d)},m.addLabel=function(a,b){return this._labels[a]=this._parseTimeOrLabel(b),this},m.addPause=function(a,b,c,d){return this.call(k,["{self}",b,c,d],this,a)},m.removeLabel=function(a){return delete this._labels[a],this},m.getLabelTime=function(a){return null!=this._labels[a]?this._labels[a]:-1},m._parseTimeOrLabel=function(b,c,d,e){var f;if(e instanceof a&&e.timeline===this)this.remove(e);else if(e&&(e instanceof Array||e.push&&g(e)))for(f=e.length;--f>-1;)e[f]instanceof a&&e[f].timeline===this&&this.remove(e[f]);if("string"==typeof c)return this._parseTimeOrLabel(c,d&&"number"==typeof b&&null==this._labels[c]?b-this.duration():0,d);if(c=c||0,"string"!=typeof b||!isNaN(b)&&null==this._labels[b])null==b&&(b=this.duration());else{if(f=b.indexOf("="),-1===f)return null==this._labels[b]?d?this._labels[b]=this.duration()+c:c:this._labels[b]+c;c=parseInt(b.charAt(f-1)+"1",10)*Number(b.substr(f+1)),b=f>1?this._parseTimeOrLabel(b.substr(0,f-1),0,d):this.duration()}return Number(b)+c},m.seek=function(a,b){return this.totalTime("number"==typeof a?a:this._parseTimeOrLabel(a),b!==!1)},m.stop=function(){return this.paused(!0)},m.gotoAndPlay=function(a,b){return this.play(a,b)},m.gotoAndStop=function(a,b){return this.pause(a,b)},m.render=function(a,b,c){this._gc&&this._enabled(!0,!1);var d,f,g,i,j,k=this._dirty?this.totalDuration():this._totalDuration,l=this._time,m=this._startTime,n=this._timeScale,o=this._paused;if(a>=k?(this._totalTime=this._time=k,this._reversed||this._hasPausedChild()||(f=!0,i="onComplete",0===this._duration&&(0===a||this._rawPrevTime<0||this._rawPrevTime===e)&&this._rawPrevTime!==a&&this._first&&(j=!0,this._rawPrevTime>e&&(i="onReverseComplete"))),this._rawPrevTime=this._duration||!b||a||this._rawPrevTime===a?a:e,a=k+1e-4):1e-7>a?(this._totalTime=this._time=0,(0!==l||0===this._duration&&this._rawPrevTime!==e&&(this._rawPrevTime>0||0>a&&this._rawPrevTime>=0))&&(i="onReverseComplete",f=this._reversed),0>a?(this._active=!1,0===this._duration&&this._rawPrevTime>=0&&this._first&&(j=!0),this._rawPrevTime=a):(this._rawPrevTime=this._duration||!b||a||this._rawPrevTime===a?a:e,a=0,this._initted||(j=!0))):this._totalTime=this._time=this._rawPrevTime=a,this._time!==l&&this._first||c||j){if(this._initted||(this._initted=!0),this._active||!this._paused&&this._time!==l&&a>0&&(this._active=!0),0===l&&this.vars.onStart&&0!==this._time&&(b||this.vars.onStart.apply(this.vars.onStartScope||this,this.vars.onStartParams||h)),this._time>=l)for(d=this._first;d&&(g=d._next,!this._paused||o);)(d._active||d._startTime<=this._time&&!d._paused&&!d._gc)&&(d._reversed?d.render((d._dirty?d.totalDuration():d._totalDuration)-(a-d._startTime)*d._timeScale,b,c):d.render((a-d._startTime)*d._timeScale,b,c)),d=g;else for(d=this._last;d&&(g=d._prev,!this._paused||o);)(d._active||d._startTime<=l&&!d._paused&&!d._gc)&&(d._reversed?d.render((d._dirty?d.totalDuration():d._totalDuration)-(a-d._startTime)*d._timeScale,b,c):d.render((a-d._startTime)*d._timeScale,b,c)),
-d=g;this._onUpdate&&(b||this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||h)),i&&(this._gc||(m===this._startTime||n!==this._timeScale)&&(0===this._time||k>=this.totalDuration())&&(f&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!b&&this.vars[i]&&this.vars[i].apply(this.vars[i+"Scope"]||this,this.vars[i+"Params"]||h)))}},m._hasPausedChild=function(){for(var a=this._first;a;){if(a._paused||a instanceof d&&a._hasPausedChild())return!0;a=a._next}return!1},m.getChildren=function(a,b,d,e){e=e||-9999999999;for(var f=[],g=this._first,h=0;g;)g._startTime<e||(g instanceof c?b!==!1&&(f[h++]=g):(d!==!1&&(f[h++]=g),a!==!1&&(f=f.concat(g.getChildren(!0,b,d)),h=f.length))),g=g._next;return f},m.getTweensOf=function(a,b){var d,e,f=this._gc,g=[],h=0;for(f&&this._enabled(!0,!0),d=c.getTweensOf(a),e=d.length;--e>-1;)(d[e].timeline===this||b&&this._contains(d[e]))&&(g[h++]=d[e]);return f&&this._enabled(!1,!0),g},m._contains=function(a){for(var b=a.timeline;b;){if(b===this)return!0;b=b.timeline}return!1},m.shiftChildren=function(a,b,c){c=c||0;for(var d,e=this._first,f=this._labels;e;)e._startTime>=c&&(e._startTime+=a),e=e._next;if(b)for(d in f)f[d]>=c&&(f[d]+=a);return this._uncache(!0)},m._kill=function(a,b){if(!a&&!b)return this._enabled(!1,!1);for(var c=b?this.getTweensOf(b):this.getChildren(!0,!0,!1),d=c.length,e=!1;--d>-1;)c[d]._kill(a,b)&&(e=!0);return e},m.clear=function(a){var b=this.getChildren(!1,!0,!0),c=b.length;for(this._time=this._totalTime=0;--c>-1;)b[c]._enabled(!1,!1);return a!==!1&&(this._labels={}),this._uncache(!0)},m.invalidate=function(){for(var a=this._first;a;)a.invalidate(),a=a._next;return this},m._enabled=function(a,c){if(a===this._gc)for(var d=this._first;d;)d._enabled(a,!0),d=d._next;return b.prototype._enabled.call(this,a,c)},m.duration=function(a){return arguments.length?(0!==this.duration()&&0!==a&&this.timeScale(this._duration/a),this):(this._dirty&&this.totalDuration(),this._duration)},m.totalDuration=function(a){if(!arguments.length){if(this._dirty){for(var b,c,d=0,e=this._last,f=999999999999;e;)b=e._prev,e._dirty&&e.totalDuration(),e._startTime>f&&this._sortChildren&&!e._paused?this.add(e,e._startTime-e._delay):f=e._startTime,e._startTime<0&&!e._paused&&(d-=e._startTime,this._timeline.smoothChildTiming&&(this._startTime+=e._startTime/this._timeScale),this.shiftChildren(-e._startTime,!1,-9999999999),f=0),c=e._startTime+e._totalDuration/e._timeScale,c>d&&(d=c),e=b;this._duration=this._totalDuration=d,this._dirty=!1}return this._totalDuration}return 0!==this.totalDuration()&&0!==a&&this.timeScale(this._totalDuration/a),this},m.usesFrames=function(){for(var b=this._timeline;b._timeline;)b=b._timeline;return b===a._rootFramesTimeline},m.rawTime=function(){return this._paused?this._totalTime:(this._timeline.rawTime()-this._startTime)*this._timeScale},d},!0),window._gsDefine("TimelineMax",["TimelineLite","TweenLite","easing.Ease"],function(a,b,c){var d=function(b){a.call(this,b),this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._cycle=0,this._yoyo=this.vars.yoyo===!0,this._dirty=!0},e=1e-10,f=[],g=new c(null,null,1,0),h=d.prototype=new a;return h.constructor=d,h.kill()._gc=!1,d.version="1.12.1",h.invalidate=function(){return this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._uncache(!0),a.prototype.invalidate.call(this)},h.addCallback=function(a,c,d,e){return this.add(b.delayedCall(0,a,d,e),c)},h.removeCallback=function(a,b){if(a)if(null==b)this._kill(null,a);else for(var c=this.getTweensOf(a,!1),d=c.length,e=this._parseTimeOrLabel(b);--d>-1;)c[d]._startTime===e&&c[d]._enabled(!1,!1);return this},h.tweenTo=function(a,c){c=c||{};var d,e,h,i={ease:g,overwrite:c.delay?2:1,useFrames:this.usesFrames(),immediateRender:!1};for(e in c)i[e]=c[e];return i.time=this._parseTimeOrLabel(a),d=Math.abs(Number(i.time)-this._time)/this._timeScale||.001,h=new b(this,d,i),i.onStart=function(){h.target.paused(!0),h.vars.time!==h.target.time()&&d===h.duration()&&h.duration(Math.abs(h.vars.time-h.target.time())/h.target._timeScale),c.onStart&&c.onStart.apply(c.onStartScope||h,c.onStartParams||f)},h},h.tweenFromTo=function(a,b,c){c=c||{},a=this._parseTimeOrLabel(a),c.startAt={onComplete:this.seek,onCompleteParams:[a],onCompleteScope:this},c.immediateRender=c.immediateRender!==!1;var d=this.tweenTo(b,c);return d.duration(Math.abs(d.vars.time-a)/this._timeScale||.001)},h.render=function(a,b,c){this._gc&&this._enabled(!0,!1);var d,g,h,i,j,k,l=this._dirty?this.totalDuration():this._totalDuration,m=this._duration,n=this._time,o=this._totalTime,p=this._startTime,q=this._timeScale,r=this._rawPrevTime,s=this._paused,t=this._cycle;if(a>=l?(this._locked||(this._totalTime=l,this._cycle=this._repeat),this._reversed||this._hasPausedChild()||(g=!0,i="onComplete",0===this._duration&&(0===a||0>r||r===e)&&r!==a&&this._first&&(j=!0,r>e&&(i="onReverseComplete"))),this._rawPrevTime=this._duration||!b||a||this._rawPrevTime===a?a:e,this._yoyo&&0!==(1&this._cycle)?this._time=a=0:(this._time=m,a=m+1e-4)):1e-7>a?(this._locked||(this._totalTime=this._cycle=0),this._time=0,(0!==n||0===m&&r!==e&&(r>0||0>a&&r>=0)&&!this._locked)&&(i="onReverseComplete",g=this._reversed),0>a?(this._active=!1,0===m&&r>=0&&this._first&&(j=!0),this._rawPrevTime=a):(this._rawPrevTime=m||!b||a||this._rawPrevTime===a?a:e,a=0,this._initted||(j=!0))):(0===m&&0>r&&(j=!0),this._time=this._rawPrevTime=a,this._locked||(this._totalTime=a,0!==this._repeat&&(k=m+this._repeatDelay,this._cycle=this._totalTime/k>>0,0!==this._cycle&&this._cycle===this._totalTime/k&&this._cycle--,this._time=this._totalTime-this._cycle*k,this._yoyo&&0!==(1&this._cycle)&&(this._time=m-this._time),this._time>m?(this._time=m,a=m+1e-4):this._time<0?this._time=a=0:a=this._time))),this._cycle!==t&&!this._locked){var u=this._yoyo&&0!==(1&t),v=u===(this._yoyo&&0!==(1&this._cycle)),w=this._totalTime,x=this._cycle,y=this._rawPrevTime,z=this._time;if(this._totalTime=t*m,this._cycle<t?u=!u:this._totalTime+=m,this._time=n,this._rawPrevTime=0===m?r-1e-4:r,this._cycle=t,this._locked=!0,n=u?0:m,this.render(n,b,0===m),b||this._gc||this.vars.onRepeat&&this.vars.onRepeat.apply(this.vars.onRepeatScope||this,this.vars.onRepeatParams||f),v&&(n=u?m+1e-4:-1e-4,this.render(n,!0,!1)),this._locked=!1,this._paused&&!s)return;this._time=z,this._totalTime=w,this._cycle=x,this._rawPrevTime=y}if(!(this._time!==n&&this._first||c||j))return void(o!==this._totalTime&&this._onUpdate&&(b||this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||f)));if(this._initted||(this._initted=!0),this._active||!this._paused&&this._totalTime!==o&&a>0&&(this._active=!0),0===o&&this.vars.onStart&&0!==this._totalTime&&(b||this.vars.onStart.apply(this.vars.onStartScope||this,this.vars.onStartParams||f)),this._time>=n)for(d=this._first;d&&(h=d._next,!this._paused||s);)(d._active||d._startTime<=this._time&&!d._paused&&!d._gc)&&(d._reversed?d.render((d._dirty?d.totalDuration():d._totalDuration)-(a-d._startTime)*d._timeScale,b,c):d.render((a-d._startTime)*d._timeScale,b,c)),d=h;else for(d=this._last;d&&(h=d._prev,!this._paused||s);)(d._active||d._startTime<=n&&!d._paused&&!d._gc)&&(d._reversed?d.render((d._dirty?d.totalDuration():d._totalDuration)-(a-d._startTime)*d._timeScale,b,c):d.render((a-d._startTime)*d._timeScale,b,c)),d=h;this._onUpdate&&(b||this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||f)),i&&(this._locked||this._gc||(p===this._startTime||q!==this._timeScale)&&(0===this._time||l>=this.totalDuration())&&(g&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!b&&this.vars[i]&&this.vars[i].apply(this.vars[i+"Scope"]||this,this.vars[i+"Params"]||f)))},h.getActive=function(a,b,c){null==a&&(a=!0),null==b&&(b=!0),null==c&&(c=!1);var d,e,f=[],g=this.getChildren(a,b,c),h=0,i=g.length;for(d=0;i>d;d++)e=g[d],e.isActive()&&(f[h++]=e);return f},h.getLabelAfter=function(a){a||0!==a&&(a=this._time);var b,c=this.getLabelsArray(),d=c.length;for(b=0;d>b;b++)if(c[b].time>a)return c[b].name;return null},h.getLabelBefore=function(a){null==a&&(a=this._time);for(var b=this.getLabelsArray(),c=b.length;--c>-1;)if(b[c].time<a)return b[c].name;return null},h.getLabelsArray=function(){var a,b=[],c=0;for(a in this._labels)b[c++]={time:this._labels[a],name:a};return b.sort(function(a,b){return a.time-b.time}),b},h.progress=function(a){return arguments.length?this.totalTime(this.duration()*(this._yoyo&&0!==(1&this._cycle)?1-a:a)+this._cycle*(this._duration+this._repeatDelay),!1):this._time/this.duration()},h.totalProgress=function(a){return arguments.length?this.totalTime(this.totalDuration()*a,!1):this._totalTime/this.totalDuration()},h.totalDuration=function(b){return arguments.length?-1===this._repeat?this:this.duration((b-this._repeat*this._repeatDelay)/(this._repeat+1)):(this._dirty&&(a.prototype.totalDuration.call(this),this._totalDuration=-1===this._repeat?999999999999:this._duration*(this._repeat+1)+this._repeatDelay*this._repeat),this._totalDuration)},h.time=function(a,b){return arguments.length?(this._dirty&&this.totalDuration(),a>this._duration&&(a=this._duration),this._yoyo&&0!==(1&this._cycle)?a=this._duration-a+this._cycle*(this._duration+this._repeatDelay):0!==this._repeat&&(a+=this._cycle*(this._duration+this._repeatDelay)),this.totalTime(a,b)):this._time},h.repeat=function(a){return arguments.length?(this._repeat=a,this._uncache(!0)):this._repeat},h.repeatDelay=function(a){return arguments.length?(this._repeatDelay=a,this._uncache(!0)):this._repeatDelay},h.yoyo=function(a){return arguments.length?(this._yoyo=a,this):this._yoyo},h.currentLabel=function(a){return arguments.length?this.seek(a,!0):this.getLabelBefore(this._time+1e-8)},d},!0),function(){var a=180/Math.PI,b=[],c=[],d=[],e={},f=function(a,b,c,d){this.a=a,this.b=b,this.c=c,this.d=d,this.da=d-a,this.ca=c-a,this.ba=b-a},g=",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",h=function(a,b,c,d){var e={a:a},f={},g={},h={c:d},i=(a+b)/2,j=(b+c)/2,k=(c+d)/2,l=(i+j)/2,m=(j+k)/2,n=(m-l)/8;return e.b=i+(a-i)/4,f.b=l+n,e.c=f.a=(e.b+f.b)/2,f.c=g.a=(l+m)/2,g.b=m-n,h.b=k+(d-k)/4,g.c=h.a=(g.b+h.b)/2,[e,f,g,h]},i=function(a,e,f,g,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w=a.length-1,x=0,y=a[0].a;for(j=0;w>j;j++)n=a[x],k=n.a,l=n.d,m=a[x+1].d,i?(t=b[j],u=c[j],v=(u+t)*e*.25/(g?.5:d[j]||.5),o=l-(l-k)*(g?.5*e:0!==t?v/t:0),p=l+(m-l)*(g?.5*e:0!==u?v/u:0),q=l-(o+((p-o)*(3*t/(t+u)+.5)/4||0))):(o=l-(l-k)*e*.5,p=l+(m-l)*e*.5,q=l-(o+p)/2),o+=q,p+=q,n.c=r=o,0!==j?n.b=y:n.b=y=n.a+.6*(n.c-n.a),n.da=l-k,n.ca=r-k,n.ba=y-k,f?(s=h(k,y,r,l),a.splice(x,1,s[0],s[1],s[2],s[3]),x+=4):x++,y=p;n=a[x],n.b=y,n.c=y+.4*(n.d-y),n.da=n.d-n.a,n.ca=n.c-n.a,n.ba=y-n.a,f&&(s=h(n.a,y,n.c,n.d),a.splice(x,1,s[0],s[1],s[2],s[3]))},j=function(a,d,e,g){var h,i,j,k,l,m,n=[];if(g)for(a=[g].concat(a),i=a.length;--i>-1;)"string"==typeof(m=a[i][d])&&"="===m.charAt(1)&&(a[i][d]=g[d]+Number(m.charAt(0)+m.substr(2)));if(h=a.length-2,0>h)return n[0]=new f(a[0][d],0,0,a[-1>h?0:1][d]),n;for(i=0;h>i;i++)j=a[i][d],k=a[i+1][d],n[i]=new f(j,0,0,k),e&&(l=a[i+2][d],b[i]=(b[i]||0)+(k-j)*(k-j),c[i]=(c[i]||0)+(l-k)*(l-k));return n[i]=new f(a[i][d],0,0,a[i+1][d]),n},k=function(a,f,h,k,l,m){var n,o,p,q,r,s,t,u,v={},w=[],x=m||a[0];l="string"==typeof l?","+l+",":g,null==f&&(f=1);for(o in a[0])w.push(o);if(a.length>1){for(u=a[a.length-1],t=!0,n=w.length;--n>-1;)if(o=w[n],Math.abs(x[o]-u[o])>.05){t=!1;break}t&&(a=a.concat(),m&&a.unshift(m),a.push(a[1]),m=a[a.length-3])}for(b.length=c.length=d.length=0,n=w.length;--n>-1;)o=w[n],e[o]=-1!==l.indexOf(","+o+","),v[o]=j(a,o,e[o],m);for(n=b.length;--n>-1;)b[n]=Math.sqrt(b[n]),c[n]=Math.sqrt(c[n]);if(!k){for(n=w.length;--n>-1;)if(e[o])for(p=v[w[n]],s=p.length-1,q=0;s>q;q++)r=p[q+1].da/c[q]+p[q].da/b[q],d[q]=(d[q]||0)+r*r;for(n=d.length;--n>-1;)d[n]=Math.sqrt(d[n])}for(n=w.length,q=h?4:1;--n>-1;)o=w[n],p=v[o],i(p,f,h,k,e[o]),t&&(p.splice(0,q),p.splice(p.length-q,q));return v},l=function(a,b,c){b=b||"soft";var d,e,g,h,i,j,k,l,m,n,o,p={},q="cubic"===b?3:2,r="soft"===b,s=[];if(r&&c&&(a=[c].concat(a)),null==a||a.length<q+1)throw"invalid Bezier data";for(m in a[0])s.push(m);for(j=s.length;--j>-1;){for(m=s[j],p[m]=i=[],n=0,l=a.length,k=0;l>k;k++)d=null==c?a[k][m]:"string"==typeof(o=a[k][m])&&"="===o.charAt(1)?c[m]+Number(o.charAt(0)+o.substr(2)):Number(o),r&&k>1&&l-1>k&&(i[n++]=(d+i[n-2])/2),i[n++]=d;for(l=n-q+1,n=0,k=0;l>k;k+=q)d=i[k],e=i[k+1],g=i[k+2],h=2===q?0:i[k+3],i[n++]=o=3===q?new f(d,e,g,h):new f(d,(2*e+d)/3,(2*e+g)/3,g);i.length=n}return p},m=function(a,b,c){for(var d,e,f,g,h,i,j,k,l,m,n,o=1/c,p=a.length;--p>-1;)for(m=a[p],f=m.a,g=m.d-f,h=m.c-f,i=m.b-f,d=e=0,k=1;c>=k;k++)j=o*k,l=1-j,d=e-(e=(j*j*g+3*l*(j*h+l*i))*j),n=p*c+k-1,b[n]=(b[n]||0)+d*d},n=function(a,b){b=b>>0||6;var c,d,e,f,g=[],h=[],i=0,j=0,k=b-1,l=[],n=[];for(c in a)m(a[c],g,b);for(e=g.length,d=0;e>d;d++)i+=Math.sqrt(g[d]),f=d%b,n[f]=i,f===k&&(j+=i,f=d/b>>0,l[f]=n,h[f]=j,i=0,n=[]);return{length:j,lengths:h,segments:l}},o=window._gsDefine.plugin({propName:"bezier",priority:-1,version:"1.3.2",API:2,global:!0,init:function(a,b,c){this._target=a,b instanceof Array&&(b={values:b}),this._func={},this._round={},this._props=[],this._timeRes=null==b.timeResolution?6:parseInt(b.timeResolution,10);var d,e,f,g,h,i=b.values||[],j={},m=i[0],o=b.autoRotate||c.vars.orientToBezier;this._autoRotate=o?o instanceof Array?o:[["x","y","rotation",o===!0?0:Number(o)||0]]:null;for(d in m)this._props.push(d);for(f=this._props.length;--f>-1;)d=this._props[f],this._overwriteProps.push(d),e=this._func[d]="function"==typeof a[d],j[d]=e?a[d.indexOf("set")||"function"!=typeof a["get"+d.substr(3)]?d:"get"+d.substr(3)]():parseFloat(a[d]),h||j[d]!==i[0][d]&&(h=j);if(this._beziers="cubic"!==b.type&&"quadratic"!==b.type&&"soft"!==b.type?k(i,isNaN(b.curviness)?1:b.curviness,!1,"thruBasic"===b.type,b.correlate,h):l(i,b.type,j),this._segCount=this._beziers[d].length,this._timeRes){var p=n(this._beziers,this._timeRes);this._length=p.length,this._lengths=p.lengths,this._segments=p.segments,this._l1=this._li=this._s1=this._si=0,this._l2=this._lengths[0],this._curSeg=this._segments[0],this._s2=this._curSeg[0],this._prec=1/this._curSeg.length}if(o=this._autoRotate)for(this._initialRotations=[],o[0]instanceof Array||(this._autoRotate=o=[o]),f=o.length;--f>-1;){for(g=0;3>g;g++)d=o[f][g],this._func[d]="function"==typeof a[d]?a[d.indexOf("set")||"function"!=typeof a["get"+d.substr(3)]?d:"get"+d.substr(3)]:!1;d=o[f][2],this._initialRotations[f]=this._func[d]?this._func[d].call(this._target):this._target[d]}return this._startRatio=c.vars.runBackwards?1:0,!0},set:function(b){var c,d,e,f,g,h,i,j,k,l,m=this._segCount,n=this._func,o=this._target,p=b!==this._startRatio;if(this._timeRes){if(k=this._lengths,l=this._curSeg,b*=this._length,e=this._li,b>this._l2&&m-1>e){for(j=m-1;j>e&&(this._l2=k[++e])<=b;);this._l1=k[e-1],this._li=e,this._curSeg=l=this._segments[e],this._s2=l[this._s1=this._si=0]}else if(b<this._l1&&e>0){for(;e>0&&(this._l1=k[--e])>=b;);0===e&&b<this._l1?this._l1=0:e++,this._l2=k[e],this._li=e,this._curSeg=l=this._segments[e],this._s1=l[(this._si=l.length-1)-1]||0,this._s2=l[this._si]}if(c=e,b-=this._l1,e=this._si,b>this._s2&&e<l.length-1){for(j=l.length-1;j>e&&(this._s2=l[++e])<=b;);this._s1=l[e-1],this._si=e}else if(b<this._s1&&e>0){for(;e>0&&(this._s1=l[--e])>=b;);0===e&&b<this._s1?this._s1=0:e++,this._s2=l[e],this._si=e}h=(e+(b-this._s1)/(this._s2-this._s1))*this._prec}else c=0>b?0:b>=1?m-1:m*b>>0,h=(b-c*(1/m))*m;for(d=1-h,e=this._props.length;--e>-1;)f=this._props[e],g=this._beziers[f][c],i=(h*h*g.da+3*d*(h*g.ca+d*g.ba))*h+g.a,this._round[f]&&(i=Math.round(i)),n[f]?o[f](i):o[f]=i;if(this._autoRotate){var q,r,s,t,u,v,w,x=this._autoRotate;for(e=x.length;--e>-1;)f=x[e][2],v=x[e][3]||0,w=x[e][4]===!0?1:a,g=this._beziers[x[e][0]],q=this._beziers[x[e][1]],g&&q&&(g=g[c],q=q[c],r=g.a+(g.b-g.a)*h,t=g.b+(g.c-g.b)*h,r+=(t-r)*h,t+=(g.c+(g.d-g.c)*h-t)*h,s=q.a+(q.b-q.a)*h,u=q.b+(q.c-q.b)*h,s+=(u-s)*h,u+=(q.c+(q.d-q.c)*h-u)*h,i=p?Math.atan2(u-s,t-r)*w+v:this._initialRotations[e],n[f]?o[f](i):o[f]=i)}}}),p=o.prototype;o.bezierThrough=k,o.cubicToQuadratic=h,o._autoCSS=!0,o.quadraticToCubic=function(a,b,c){return new f(a,(2*b+a)/3,(2*b+c)/3,c)},o._cssRegister=function(){var a=window._gsDefine.globals.CSSPlugin;if(a){var b=a._internals,c=b._parseToProxy,d=b._setPluginRatio,e=b.CSSPropTween;b._registerComplexSpecialProp("bezier",{parser:function(a,b,f,g,h,i){b instanceof Array&&(b={values:b}),i=new o;var j,k,l,m=b.values,n=m.length-1,p=[],q={};if(0>n)return h;for(j=0;n>=j;j++)l=c(a,m[j],g,h,i,n!==j),p[j]=l.end;for(k in b)q[k]=b[k];return q.values=p,h=new e(a,"bezier",0,0,l.pt,2),h.data=l,h.plugin=i,h.setRatio=d,0===q.autoRotate&&(q.autoRotate=!0),!q.autoRotate||q.autoRotate instanceof Array||(j=q.autoRotate===!0?0:Number(q.autoRotate),q.autoRotate=null!=l.end.left?[["left","top","rotation",j,!1]]:null!=l.end.x?[["x","y","rotation",j,!1]]:!1),q.autoRotate&&(g._transform||g._enableTransforms(!1),l.autoRotate=g._target._gsTransform),i._onInitTween(l.proxy,q,g._tween),h}})}},p._roundProps=function(a,b){for(var c=this._overwriteProps,d=c.length;--d>-1;)(a[c[d]]||a.bezier||a.bezierThrough)&&(this._round[c[d]]=b)},p._kill=function(a){var b,c,d=this._props;for(b in this._beziers)if(b in a)for(delete this._beziers[b],delete this._func[b],c=d.length;--c>-1;)d[c]===b&&d.splice(c,1);return this._super._kill.call(this,a)}}(),window._gsDefine("plugins.CSSPlugin",["plugins.TweenPlugin","TweenLite"],function(a,b){var c,d,e,f,g=function(){a.call(this,"css"),this._overwriteProps.length=0,this.setRatio=g.prototype.setRatio},h={},i=g.prototype=new a("css");i.constructor=g,g.version="1.12.1",g.API=2,g.defaultTransformPerspective=0,g.defaultSkewType="compensated",i="px",g.suffixMap={top:i,right:i,bottom:i,left:i,width:i,height:i,fontSize:i,padding:i,margin:i,perspective:i,lineHeight:""};var j,k,l,m,n,o,p=/(?:\d|\-\d|\.\d|\-\.\d)+/g,q=/(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,r=/(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi,s=/[^\d\-\.]/g,t=/(?:\d|\-|\+|=|#|\.)*/g,u=/opacity *= *([^)]*)/i,v=/opacity:([^;]*)/i,w=/alpha\(opacity *=.+?\)/i,x=/^(rgb|hsl)/,y=/([A-Z])/g,z=/-([a-z])/gi,A=/(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi,B=function(a,b){return b.toUpperCase()},C=/(?:Left|Right|Width)/i,D=/(M11|M12|M21|M22)=[\d\-\.e]+/gi,E=/progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,F=/,(?=[^\)]*(?:\(|$))/gi,G=Math.PI/180,H=180/Math.PI,I={},J=document,K=J.createElement("div"),L=J.createElement("img"),M=g._internals={_specialProps:h},N=navigator.userAgent,O=function(){var a,b=N.indexOf("Android"),c=J.createElement("div");return l=-1!==N.indexOf("Safari")&&-1===N.indexOf("Chrome")&&(-1===b||Number(N.substr(b+8,1))>3),n=l&&Number(N.substr(N.indexOf("Version/")+8,1))<6,m=-1!==N.indexOf("Firefox"),/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(N)&&(o=parseFloat(RegExp.$1)),c.innerHTML="<a style='top:1px;opacity:.55;'>a</a>",a=c.getElementsByTagName("a")[0],a?/^0.55/.test(a.style.opacity):!1}(),P=function(a){return u.test("string"==typeof a?a:(a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100:1},Q=function(a){window.console},R="",S="",T=function(a,b){b=b||K;var c,d,e=b.style;if(void 0!==e[a])return a;for(a=a.charAt(0).toUpperCase()+a.substr(1),c=["O","Moz","ms","Ms","Webkit"],d=5;--d>-1&&void 0===e[c[d]+a];);return d>=0?(S=3===d?"ms":c[d],R="-"+S.toLowerCase()+"-",S+a):null},U=J.defaultView?J.defaultView.getComputedStyle:function(){},V=g.getStyle=function(a,b,c,d,e){var f;return O||"opacity"!==b?(!d&&a.style[b]?f=a.style[b]:(c=c||U(a))?f=c[b]||c.getPropertyValue(b)||c.getPropertyValue(b.replace(y,"-$1").toLowerCase()):a.currentStyle&&(f=a.currentStyle[b]),null==e||f&&"none"!==f&&"auto"!==f&&"auto auto"!==f?f:e):P(a)},W=M.convertToPixels=function(a,c,d,e,f){if("px"===e||!e)return d;if("auto"===e||!d)return 0;var h,i,j,k=C.test(c),l=a,m=K.style,n=0>d;if(n&&(d=-d),"%"===e&&-1!==c.indexOf("border"))h=d/100*(k?a.clientWidth:a.clientHeight);else{if(m.cssText="border:0 solid red;position:"+V(a,"position")+";line-height:0;","%"!==e&&l.appendChild)m[k?"borderLeftWidth":"borderTopWidth"]=d+e;else{if(l=a.parentNode||J.body,i=l._gsCache,j=b.ticker.frame,i&&k&&i.time===j)return i.width*d/100;m[k?"width":"height"]=d+e}l.appendChild(K),h=parseFloat(K[k?"offsetWidth":"offsetHeight"]),l.removeChild(K),k&&"%"===e&&g.cacheWidths!==!1&&(i=l._gsCache=l._gsCache||{},i.time=j,i.width=h/d*100),0!==h||f||(h=W(a,c,d,e,!0))}return n?-h:h},X=M.calculateOffset=function(a,b,c){if("absolute"!==V(a,"position",c))return 0;var d="left"===b?"Left":"Top",e=V(a,"margin"+d,c);return a["offset"+d]-(W(a,b,parseFloat(e),e.replace(t,""))||0)},Y=function(a,b){var c,d,e={};if(b=b||U(a,null))if(c=b.length)for(;--c>-1;)e[b[c].replace(z,B)]=b.getPropertyValue(b[c]);else for(c in b)e[c]=b[c];else if(b=a.currentStyle||a.style)for(c in b)"string"==typeof c&&void 0===e[c]&&(e[c.replace(z,B)]=b[c]);return O||(e.opacity=P(a)),d=ya(a,b,!1),e.rotation=d.rotation,e.skewX=d.skewX,e.scaleX=d.scaleX,e.scaleY=d.scaleY,e.x=d.x,e.y=d.y,wa&&(e.z=d.z,e.rotationX=d.rotationX,e.rotationY=d.rotationY,e.scaleZ=d.scaleZ),e.filters&&delete e.filters,e},Z=function(a,b,c,d,e){var f,g,h,i={},j=a.style;for(g in c)"cssText"!==g&&"length"!==g&&isNaN(g)&&(b[g]!==(f=c[g])||e&&e[g])&&-1===g.indexOf("Origin")&&("number"==typeof f||"string"==typeof f)&&(i[g]="auto"!==f||"left"!==g&&"top"!==g?""!==f&&"auto"!==f&&"none"!==f||"string"!=typeof b[g]||""===b[g].replace(s,"")?f:0:X(a,g),void 0!==j[g]&&(h=new la(j,g,j[g],h)));if(d)for(g in d)"className"!==g&&(i[g]=d[g]);return{difs:i,firstMPT:h}},$={width:["Left","Right"],height:["Top","Bottom"]},_=["marginLeft","marginRight","marginTop","marginBottom"],aa=function(a,b,c){var d=parseFloat("width"===b?a.offsetWidth:a.offsetHeight),e=$[b],f=e.length;for(c=c||U(a,null);--f>-1;)d-=parseFloat(V(a,"padding"+e[f],c,!0))||0,d-=parseFloat(V(a,"border"+e[f]+"Width",c,!0))||0;return d},ba=function(a,b){(null==a||""===a||"auto"===a||"auto auto"===a)&&(a="0 0");var c=a.split(" "),d=-1!==a.indexOf("left")?"0%":-1!==a.indexOf("right")?"100%":c[0],e=-1!==a.indexOf("top")?"0%":-1!==a.indexOf("bottom")?"100%":c[1];return null==e?e="0":"center"===e&&(e="50%"),("center"===d||isNaN(parseFloat(d))&&-1===(d+"").indexOf("="))&&(d="50%"),b&&(b.oxp=-1!==d.indexOf("%"),b.oyp=-1!==e.indexOf("%"),b.oxr="="===d.charAt(1),b.oyr="="===e.charAt(1),b.ox=parseFloat(d.replace(s,"")),b.oy=parseFloat(e.replace(s,""))),d+" "+e+(c.length>2?" "+c[2]:"")},ca=function(a,b){return"string"==typeof a&&"="===a.charAt(1)?parseInt(a.charAt(0)+"1",10)*parseFloat(a.substr(2)):parseFloat(a)-parseFloat(b)},da=function(a,b){return null==a?b:"string"==typeof a&&"="===a.charAt(1)?parseInt(a.charAt(0)+"1",10)*Number(a.substr(2))+b:parseFloat(a)},ea=function(a,b,c,d){var e,f,g,h,i=1e-6;return null==a?h=b:"number"==typeof a?h=a:(e=360,f=a.split("_"),g=Number(f[0].replace(s,""))*(-1===a.indexOf("rad")?1:H)-("="===a.charAt(1)?0:b),f.length&&(d&&(d[c]=b+g),-1!==a.indexOf("short")&&(g%=e,g!==g%(e/2)&&(g=0>g?g+e:g-e)),-1!==a.indexOf("_cw")&&0>g?g=(g+9999999999*e)%e-(g/e|0)*e:-1!==a.indexOf("ccw")&&g>0&&(g=(g-9999999999*e)%e-(g/e|0)*e)),h=b+g),i>h&&h>-i&&(h=0),h},fa={aqua:[0,255,255],lime:[0,255,0],silver:[192,192,192],black:[0,0,0],maroon:[128,0,0],teal:[0,128,128],blue:[0,0,255],navy:[0,0,128],white:[255,255,255],fuchsia:[255,0,255],olive:[128,128,0],yellow:[255,255,0],orange:[255,165,0],gray:[128,128,128],purple:[128,0,128],green:[0,128,0],red:[255,0,0],pink:[255,192,203],cyan:[0,255,255],transparent:[255,255,255,0]},ga=function(a,b,c){return a=0>a?a+1:a>1?a-1:a,255*(1>6*a?b+(c-b)*a*6:.5>a?c:2>3*a?b+(c-b)*(2/3-a)*6:b)+.5|0},ha=function(a){var b,c,d,e,f,g;return a&&""!==a?"number"==typeof a?[a>>16,a>>8&255,255&a]:(","===a.charAt(a.length-1)&&(a=a.substr(0,a.length-1)),fa[a]?fa[a]:"#"===a.charAt(0)?(4===a.length&&(b=a.charAt(1),c=a.charAt(2),d=a.charAt(3),a="#"+b+b+c+c+d+d),a=parseInt(a.substr(1),16),[a>>16,a>>8&255,255&a]):"hsl"===a.substr(0,3)?(a=a.match(p),e=Number(a[0])%360/360,f=Number(a[1])/100,g=Number(a[2])/100,c=.5>=g?g*(f+1):g+f-g*f,b=2*g-c,a.length>3&&(a[3]=Number(a[3])),a[0]=ga(e+1/3,b,c),a[1]=ga(e,b,c),a[2]=ga(e-1/3,b,c),a):(a=a.match(p)||fa.transparent,a[0]=Number(a[0]),a[1]=Number(a[1]),a[2]=Number(a[2]),a.length>3&&(a[3]=Number(a[3])),a)):fa.black},ia="(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#.+?\\b";for(i in fa)ia+="|"+i+"\\b";ia=new RegExp(ia+")","gi");var ja=function(a,b,c,d){if(null==a)return function(a){return a};var e,f=b?(a.match(ia)||[""])[0]:"",g=a.split(f).join("").match(r)||[],h=a.substr(0,a.indexOf(g[0])),i=")"===a.charAt(a.length-1)?")":"",j=-1!==a.indexOf(" ")?" ":",",k=g.length,l=k>0?g[0].replace(p,""):"";return k?e=b?function(a){var b,m,n,o;if("number"==typeof a)a+=l;else if(d&&F.test(a)){for(o=a.replace(F,"|").split("|"),n=0;n<o.length;n++)o[n]=e(o[n]);return o.join(",")}if(b=(a.match(ia)||[f])[0],m=a.split(b).join("").match(r)||[],n=m.length,k>n--)for(;++n<k;)m[n]=c?m[(n-1)/2|0]:g[n];return h+m.join(j)+j+b+i+(-1!==a.indexOf("inset")?" inset":"")}:function(a){var b,f,m;if("number"==typeof a)a+=l;else if(d&&F.test(a)){for(f=a.replace(F,"|").split("|"),m=0;m<f.length;m++)f[m]=e(f[m]);return f.join(",")}if(b=a.match(r)||[],m=b.length,k>m--)for(;++m<k;)b[m]=c?b[(m-1)/2|0]:g[m];return h+b.join(j)+i}:function(a){return a}},ka=function(a){return a=a.split(","),function(b,c,d,e,f,g,h){var i,j=(c+"").split(" ");for(h={},i=0;4>i;i++)h[a[i]]=j[i]=j[i]||j[(i-1)/2>>0];return e.parse(b,h,f,g)}},la=(M._setPluginRatio=function(a){this.plugin.setRatio(a);for(var b,c,d,e,f=this.data,g=f.proxy,h=f.firstMPT,i=1e-6;h;)b=g[h.v],h.r?b=Math.round(b):i>b&&b>-i&&(b=0),h.t[h.p]=b,h=h._next;if(f.autoRotate&&(f.autoRotate.rotation=g.rotation),1===a)for(h=f.firstMPT;h;){if(c=h.t,c.type){if(1===c.type){for(e=c.xs0+c.s+c.xs1,d=1;d<c.l;d++)e+=c["xn"+d]+c["xs"+(d+1)];c.e=e}}else c.e=c.s+c.xs0;h=h._next}},function(a,b,c,d,e){this.t=a,this.p=b,this.v=c,this.r=e,d&&(d._prev=this,this._next=d)}),ma=(M._parseToProxy=function(a,b,c,d,e,f){var g,h,i,j,k,l=d,m={},n={},o=c._transform,p=I;for(c._transform=null,I=b,d=k=c.parse(a,b,d,e),I=p,f&&(c._transform=o,l&&(l._prev=null,l._prev&&(l._prev._next=null)));d&&d!==l;){if(d.type<=1&&(h=d.p,n[h]=d.s+d.c,m[h]=d.s,f||(j=new la(d,"s",h,j,d.r),d.c=0),1===d.type))for(g=d.l;--g>0;)i="xn"+g,h=d.p+"_"+i,n[h]=d.data[i],m[h]=d[i],f||(j=new la(d,i,h,j,d.rxp[i]));d=d._next}return{proxy:m,end:n,firstMPT:j,pt:k}},M.CSSPropTween=function(a,b,d,e,g,h,i,j,k,l,m){this.t=a,this.p=b,this.s=d,this.c=e,this.n=i||b,a instanceof ma||f.push(this.n),this.r=j,this.type=h||0,k&&(this.pr=k,c=!0),this.b=void 0===l?d:l,this.e=void 0===m?d+e:m,g&&(this._next=g,g._prev=this)}),na=g.parseComplex=function(a,b,c,d,e,f,g,h,i,k){c=c||f||"",g=new ma(a,b,0,0,g,k?2:1,null,!1,h,c,d),d+="";var l,m,n,o,r,s,t,u,v,w,y,z,A=c.split(", ").join(",").split(" "),B=d.split(", ").join(",").split(" "),C=A.length,D=j!==!1;for((-1!==d.indexOf(",")||-1!==c.indexOf(","))&&(A=A.join(" ").replace(F,", ").split(" "),B=B.join(" ").replace(F,", ").split(" "),C=A.length),C!==B.length&&(A=(f||"").split(" "),C=A.length),g.plugin=i,g.setRatio=k,l=0;C>l;l++)if(o=A[l],r=B[l],u=parseFloat(o),u||0===u)g.appendXtra("",u,ca(r,u),r.replace(q,""),D&&-1!==r.indexOf("px"),!0);else if(e&&("#"===o.charAt(0)||fa[o]||x.test(o)))z=","===r.charAt(r.length-1)?"),":")",o=ha(o),r=ha(r),v=o.length+r.length>6,v&&!O&&0===r[3]?(g["xs"+g.l]+=g.l?" transparent":"transparent",g.e=g.e.split(B[l]).join("transparent")):(O||(v=!1),g.appendXtra(v?"rgba(":"rgb(",o[0],r[0]-o[0],",",!0,!0).appendXtra("",o[1],r[1]-o[1],",",!0).appendXtra("",o[2],r[2]-o[2],v?",":z,!0),v&&(o=o.length<4?1:o[3],g.appendXtra("",o,(r.length<4?1:r[3])-o,z,!1)));else if(s=o.match(p)){if(t=r.match(q),!t||t.length!==s.length)return g;for(n=0,m=0;m<s.length;m++)y=s[m],w=o.indexOf(y,n),g.appendXtra(o.substr(n,w-n),Number(y),ca(t[m],y),"",D&&"px"===o.substr(w+y.length,2),0===m),n=w+y.length;g["xs"+g.l]+=o.substr(n)}else g["xs"+g.l]+=g.l?" "+o:o;if(-1!==d.indexOf("=")&&g.data){for(z=g.xs0+g.data.s,l=1;l<g.l;l++)z+=g["xs"+l]+g.data["xn"+l];g.e=z+g["xs"+l]}return g.l||(g.type=-1,g.xs0=g.e),g.xfirst||g},oa=9;for(i=ma.prototype,i.l=i.pr=0;--oa>0;)i["xn"+oa]=0,i["xs"+oa]="";i.xs0="",i._next=i._prev=i.xfirst=i.data=i.plugin=i.setRatio=i.rxp=null,i.appendXtra=function(a,b,c,d,e,f){var g=this,h=g.l;return g["xs"+h]+=f&&h?" "+a:a||"",c||0===h||g.plugin?(g.l++,g.type=g.setRatio?2:1,g["xs"+g.l]=d||"",h>0?(g.data["xn"+h]=b+c,g.rxp["xn"+h]=e,g["xn"+h]=b,g.plugin||(g.xfirst=new ma(g,"xn"+h,b,c,g.xfirst||g,0,g.n,e,g.pr),g.xfirst.xs0=0),g):(g.data={s:b+c},g.rxp={},g.s=b,g.c=c,g.r=e,g)):(g["xs"+h]+=b+(d||""),g)};var pa=function(a,b){b=b||{},this.p=b.prefix?T(a)||a:a,h[a]=h[this.p]=this,this.format=b.formatter||ja(b.defaultValue,b.color,b.collapsible,b.multi),b.parser&&(this.parse=b.parser),this.clrs=b.color,this.multi=b.multi,this.keyword=b.keyword,this.dflt=b.defaultValue,this.pr=b.priority||0},qa=M._registerComplexSpecialProp=function(a,b,c){"object"!=typeof b&&(b={parser:c});var d,e,f=a.split(","),g=b.defaultValue;for(c=c||[g],d=0;d<f.length;d++)b.prefix=0===d&&b.prefix,b.defaultValue=c[d]||g,e=new pa(f[d],b)},ra=function(a){if(!h[a]){var b=a.charAt(0).toUpperCase()+a.substr(1)+"Plugin";qa(a,{parser:function(a,c,d,e,f,g,i){var j=(window.GreenSockGlobals||window).com.greensock.plugins[b];return j?(j._cssRegister(),h[d].parse(a,c,d,e,f,g,i)):(Q("Error: "+b+" js file not loaded."),f)}})}};i=pa.prototype,i.parseComplex=function(a,b,c,d,e,f){var g,h,i,j,k,l,m=this.keyword;if(this.multi&&(F.test(c)||F.test(b)?(h=b.replace(F,"|").split("|"),i=c.replace(F,"|").split("|")):m&&(h=[b],i=[c])),i){for(j=i.length>h.length?i.length:h.length,g=0;j>g;g++)b=h[g]=h[g]||this.dflt,c=i[g]=i[g]||this.dflt,m&&(k=b.indexOf(m),l=c.indexOf(m),k!==l&&(c=-1===l?i:h,c[g]+=" "+m));b=h.join(", "),c=i.join(", ")}return na(a,this.p,b,c,this.clrs,this.dflt,d,this.pr,e,f)},i.parse=function(a,b,c,d,f,g,h){return this.parseComplex(a.style,this.format(V(a,this.p,e,!1,this.dflt)),this.format(b),f,g)},g.registerSpecialProp=function(a,b,c){qa(a,{parser:function(a,d,e,f,g,h,i){var j=new ma(a,e,0,0,g,2,e,!1,c);return j.plugin=h,j.setRatio=b(a,d,f._tween,e),j},priority:c})};var sa="scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective".split(","),ta=T("transform"),ua=R+"transform",va=T("transformOrigin"),wa=null!==T("perspective"),xa=M.Transform=function(){this.skewY=0},ya=M.getTransform=function(a,b,c,d){if(a._gsTransform&&c&&!d)return a._gsTransform;var e,f,h,i,j,k,l,m,n,o,p,q,r,s=c?a._gsTransform||new xa:new xa,t=s.scaleX<0,u=2e-5,v=1e5,w=179.99,x=w*G,y=wa?parseFloat(V(a,va,b,!1,"0 0 0").split(" ")[2])||s.zOrigin||0:0;for(ta?e=V(a,ua,b,!0):a.currentStyle&&(e=a.currentStyle.filter.match(D),e=e&&4===e.length?[e[0].substr(4),Number(e[2].substr(4)),Number(e[1].substr(4)),e[3].substr(4),s.x||0,s.y||0].join(","):""),f=(e||"").match(/(?:\-|\b)[\d\-\.e]+\b/gi)||[],h=f.length;--h>-1;)i=Number(f[h]),f[h]=(j=i-(i|=0))?(j*v+(0>j?-.5:.5)|0)/v+i:i;if(16===f.length){var z=f[8],A=f[9],B=f[10],C=f[12],E=f[13],F=f[14];if(s.zOrigin&&(F=-s.zOrigin,C=z*F-f[12],E=A*F-f[13],F=B*F+s.zOrigin-f[14]),!c||d||null==s.rotationX){var I,J,K,L,M,N,O,P=f[0],Q=f[1],R=f[2],S=f[3],T=f[4],U=f[5],W=f[6],X=f[7],Y=f[11],Z=Math.atan2(W,B),$=-x>Z||Z>x;s.rotationX=Z*H,Z&&(L=Math.cos(-Z),M=Math.sin(-Z),I=T*L+z*M,J=U*L+A*M,K=W*L+B*M,z=T*-M+z*L,A=U*-M+A*L,B=W*-M+B*L,Y=X*-M+Y*L,T=I,U=J,W=K),Z=Math.atan2(z,P),s.rotationY=Z*H,Z&&(N=-x>Z||Z>x,L=Math.cos(-Z),M=Math.sin(-Z),I=P*L-z*M,J=Q*L-A*M,K=R*L-B*M,A=Q*M+A*L,B=R*M+B*L,Y=S*M+Y*L,P=I,Q=J,R=K),Z=Math.atan2(Q,U),s.rotation=Z*H,Z&&(O=-x>Z||Z>x,L=Math.cos(-Z),M=Math.sin(-Z),P=P*L+T*M,J=Q*L+U*M,U=Q*-M+U*L,W=R*-M+W*L,Q=J),O&&$?s.rotation=s.rotationX=0:O&&N?s.rotation=s.rotationY=0:N&&$&&(s.rotationY=s.rotationX=0),s.scaleX=(Math.sqrt(P*P+Q*Q)*v+.5|0)/v,s.scaleY=(Math.sqrt(U*U+A*A)*v+.5|0)/v,s.scaleZ=(Math.sqrt(W*W+B*B)*v+.5|0)/v,
-s.skewX=0,s.perspective=Y?1/(0>Y?-Y:Y):0,s.x=C,s.y=E,s.z=F}}else if((!wa||d||!f.length||s.x!==f[4]||s.y!==f[5]||!s.rotationX&&!s.rotationY)&&(void 0===s.x||"none"!==V(a,"display",b))){var _=f.length>=6,aa=_?f[0]:1,ba=f[1]||0,ca=f[2]||0,da=_?f[3]:1;s.x=f[4]||0,s.y=f[5]||0,k=Math.sqrt(aa*aa+ba*ba),l=Math.sqrt(da*da+ca*ca),m=aa||ba?Math.atan2(ba,aa)*H:s.rotation||0,n=ca||da?Math.atan2(ca,da)*H+m:s.skewX||0,o=k-Math.abs(s.scaleX||0),p=l-Math.abs(s.scaleY||0),Math.abs(n)>90&&Math.abs(n)<270&&(t?(k*=-1,n+=0>=m?180:-180,m+=0>=m?180:-180):(l*=-1,n+=0>=n?180:-180)),q=(m-s.rotation)%180,r=(n-s.skewX)%180,(void 0===s.skewX||o>u||-u>o||p>u||-u>p||q>-w&&w>q&&q*v|!1||r>-w&&w>r&&r*v|!1)&&(s.scaleX=k,s.scaleY=l,s.rotation=m,s.skewX=n),wa&&(s.rotationX=s.rotationY=s.z=0,s.perspective=parseFloat(g.defaultTransformPerspective)||0,s.scaleZ=1)}s.zOrigin=y;for(h in s)s[h]<u&&s[h]>-u&&(s[h]=0);return c&&(a._gsTransform=s),s},za=function(a){var b,c,d=this.data,e=-d.rotation*G,f=e+d.skewX*G,g=1e5,h=(Math.cos(e)*d.scaleX*g|0)/g,i=(Math.sin(e)*d.scaleX*g|0)/g,j=(Math.sin(f)*-d.scaleY*g|0)/g,k=(Math.cos(f)*d.scaleY*g|0)/g,l=this.t.style,m=this.t.currentStyle;if(m){c=i,i=-j,j=-c,b=m.filter,l.filter="";var n,p,q=this.t.offsetWidth,r=this.t.offsetHeight,s="absolute"!==m.position,v="progid:DXImageTransform.Microsoft.Matrix(M11="+h+", M12="+i+", M21="+j+", M22="+k,w=d.x,x=d.y;if(null!=d.ox&&(n=(d.oxp?q*d.ox*.01:d.ox)-q/2,p=(d.oyp?r*d.oy*.01:d.oy)-r/2,w+=n-(n*h+p*i),x+=p-(n*j+p*k)),s?(n=q/2,p=r/2,v+=", Dx="+(n-(n*h+p*i)+w)+", Dy="+(p-(n*j+p*k)+x)+")"):v+=", sizingMethod='auto expand')",-1!==b.indexOf("DXImageTransform.Microsoft.Matrix(")?l.filter=b.replace(E,v):l.filter=v+" "+b,(0===a||1===a)&&1===h&&0===i&&0===j&&1===k&&(s&&-1===v.indexOf("Dx=0, Dy=0")||u.test(b)&&100!==parseFloat(RegExp.$1)||-1===b.indexOf(b.indexOf("Alpha"))&&l.removeAttribute("filter")),!s){var y,z,A,B=8>o?1:-1;for(n=d.ieOffsetX||0,p=d.ieOffsetY||0,d.ieOffsetX=Math.round((q-((0>h?-h:h)*q+(0>i?-i:i)*r))/2+w),d.ieOffsetY=Math.round((r-((0>k?-k:k)*r+(0>j?-j:j)*q))/2+x),oa=0;4>oa;oa++)z=_[oa],y=m[z],c=-1!==y.indexOf("px")?parseFloat(y):W(this.t,z,parseFloat(y),y.replace(t,""))||0,A=c!==d[z]?2>oa?-d.ieOffsetX:-d.ieOffsetY:2>oa?n-d.ieOffsetX:p-d.ieOffsetY,l[z]=(d[z]=Math.round(c-A*(0===oa||2===oa?1:B)))+"px"}}},Aa=M.set3DTransformRatio=function(a){var b,c,d,e,f,g,h,i,j,k,l,n,o,p,q,r,s,t,u,v,w,x,y,z=this.data,A=this.t.style,B=z.rotation*G,C=z.scaleX,D=z.scaleY,E=z.scaleZ,F=z.perspective;if((1===a||0===a)&&"auto"===z.force3D&&!(z.rotationY||z.rotationX||1!==E||F||z.z))return void Ba.call(this,a);if(m){var H=1e-4;H>C&&C>-H&&(C=E=2e-5),H>D&&D>-H&&(D=E=2e-5),!F||z.z||z.rotationX||z.rotationY||(F=0)}if(B||z.skewX)t=Math.cos(B),u=Math.sin(B),b=t,f=u,z.skewX&&(B-=z.skewX*G,t=Math.cos(B),u=Math.sin(B),"simple"===z.skewType&&(v=Math.tan(z.skewX*G),v=Math.sqrt(1+v*v),t*=v,u*=v)),c=-u,g=t;else{if(!(z.rotationY||z.rotationX||1!==E||F))return void(A[ta]="translate3d("+z.x+"px,"+z.y+"px,"+z.z+"px)"+(1!==C||1!==D?" scale("+C+","+D+")":""));b=g=1,c=f=0}l=1,d=e=h=i=j=k=n=o=p=0,q=F?-1/F:0,r=z.zOrigin,s=1e5,B=z.rotationY*G,B&&(t=Math.cos(B),u=Math.sin(B),j=l*-u,o=q*-u,d=b*u,h=f*u,l*=t,q*=t,b*=t,f*=t),B=z.rotationX*G,B&&(t=Math.cos(B),u=Math.sin(B),v=c*t+d*u,w=g*t+h*u,x=k*t+l*u,y=p*t+q*u,d=c*-u+d*t,h=g*-u+h*t,l=k*-u+l*t,q=p*-u+q*t,c=v,g=w,k=x,p=y),1!==E&&(d*=E,h*=E,l*=E,q*=E),1!==D&&(c*=D,g*=D,k*=D,p*=D),1!==C&&(b*=C,f*=C,j*=C,o*=C),r&&(n-=r,e=d*n,i=h*n,n=l*n+r),e=(v=(e+=z.x)-(e|=0))?(v*s+(0>v?-.5:.5)|0)/s+e:e,i=(v=(i+=z.y)-(i|=0))?(v*s+(0>v?-.5:.5)|0)/s+i:i,n=(v=(n+=z.z)-(n|=0))?(v*s+(0>v?-.5:.5)|0)/s+n:n,A[ta]="matrix3d("+[(b*s|0)/s,(f*s|0)/s,(j*s|0)/s,(o*s|0)/s,(c*s|0)/s,(g*s|0)/s,(k*s|0)/s,(p*s|0)/s,(d*s|0)/s,(h*s|0)/s,(l*s|0)/s,(q*s|0)/s,e,i,n,F?1+-n/F:1].join(",")+")"},Ba=M.set2DTransformRatio=function(a){var b,c,d,e,f,g=this.data,h=this.t,i=h.style;return g.rotationX||g.rotationY||g.z||g.force3D===!0||"auto"===g.force3D&&1!==a&&0!==a?(this.setRatio=Aa,void Aa.call(this,a)):void(g.rotation||g.skewX?(b=g.rotation*G,c=b-g.skewX*G,d=1e5,e=g.scaleX*d,f=g.scaleY*d,i[ta]="matrix("+(Math.cos(b)*e|0)/d+","+(Math.sin(b)*e|0)/d+","+(Math.sin(c)*-f|0)/d+","+(Math.cos(c)*f|0)/d+","+g.x+","+g.y+")"):i[ta]="matrix("+g.scaleX+",0,0,"+g.scaleY+","+g.x+","+g.y+")")};qa("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType",{parser:function(a,b,c,d,f,h,i){if(d._transform)return f;var j,k,l,m,n,o,p,q=d._transform=ya(a,e,!0,i.parseTransform),r=a.style,s=1e-6,t=sa.length,u=i,v={};if("string"==typeof u.transform&&ta)l=K.style,l[ta]=u.transform,l.display="block",l.position="absolute",J.body.appendChild(K),j=ya(K,null,!1),J.body.removeChild(K);else if("object"==typeof u){if(j={scaleX:da(null!=u.scaleX?u.scaleX:u.scale,q.scaleX),scaleY:da(null!=u.scaleY?u.scaleY:u.scale,q.scaleY),scaleZ:da(u.scaleZ,q.scaleZ),x:da(u.x,q.x),y:da(u.y,q.y),z:da(u.z,q.z),perspective:da(u.transformPerspective,q.perspective)},p=u.directionalRotation,null!=p)if("object"==typeof p)for(l in p)u[l]=p[l];else u.rotation=p;j.rotation=ea("rotation"in u?u.rotation:"shortRotation"in u?u.shortRotation+"_short":"rotationZ"in u?u.rotationZ:q.rotation,q.rotation,"rotation",v),wa&&(j.rotationX=ea("rotationX"in u?u.rotationX:"shortRotationX"in u?u.shortRotationX+"_short":q.rotationX||0,q.rotationX,"rotationX",v),j.rotationY=ea("rotationY"in u?u.rotationY:"shortRotationY"in u?u.shortRotationY+"_short":q.rotationY||0,q.rotationY,"rotationY",v)),j.skewX=null==u.skewX?q.skewX:ea(u.skewX,q.skewX),j.skewY=null==u.skewY?q.skewY:ea(u.skewY,q.skewY),(k=j.skewY-q.skewY)&&(j.skewX+=k,j.rotation+=k)}for(wa&&null!=u.force3D&&(q.force3D=u.force3D,o=!0),q.skewType=u.skewType||q.skewType||g.defaultSkewType,n=q.force3D||q.z||q.rotationX||q.rotationY||j.z||j.rotationX||j.rotationY||j.perspective,n||null==u.scale||(j.scaleZ=1);--t>-1;)c=sa[t],m=j[c]-q[c],(m>s||-s>m||null!=I[c])&&(o=!0,f=new ma(q,c,q[c],m,f),c in v&&(f.e=v[c]),f.xs0=0,f.plugin=h,d._overwriteProps.push(f.n));return m=u.transformOrigin,(m||wa&&n&&q.zOrigin)&&(ta?(o=!0,c=va,m=(m||V(a,c,e,!1,"50% 50%"))+"",f=new ma(r,c,0,0,f,-1,"transformOrigin"),f.b=r[c],f.plugin=h,wa?(l=q.zOrigin,m=m.split(" "),q.zOrigin=(m.length>2&&(0===l||"0px"!==m[2])?parseFloat(m[2]):l)||0,f.xs0=f.e=m[0]+" "+(m[1]||"50%")+" 0px",f=new ma(q,"zOrigin",0,0,f,-1,f.n),f.b=l,f.xs0=f.e=q.zOrigin):f.xs0=f.e=m):ba(m+"",q)),o&&(d._transformType=n||3===this._transformType?3:2),f},prefix:!0}),qa("boxShadow",{defaultValue:"0px 0px 0px 0px #999",prefix:!0,color:!0,multi:!0,keyword:"inset"}),qa("borderRadius",{defaultValue:"0px",parser:function(a,b,c,f,g,h){b=this.format(b);var i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y=["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],z=a.style;for(q=parseFloat(a.offsetWidth),r=parseFloat(a.offsetHeight),i=b.split(" "),j=0;j<y.length;j++)this.p.indexOf("border")&&(y[j]=T(y[j])),m=l=V(a,y[j],e,!1,"0px"),-1!==m.indexOf(" ")&&(l=m.split(" "),m=l[0],l=l[1]),n=k=i[j],o=parseFloat(m),t=m.substr((o+"").length),u="="===n.charAt(1),u?(p=parseInt(n.charAt(0)+"1",10),n=n.substr(2),p*=parseFloat(n),s=n.substr((p+"").length-(0>p?1:0))||""):(p=parseFloat(n),s=n.substr((p+"").length)),""===s&&(s=d[c]||t),s!==t&&(v=W(a,"borderLeft",o,t),w=W(a,"borderTop",o,t),"%"===s?(m=v/q*100+"%",l=w/r*100+"%"):"em"===s?(x=W(a,"borderLeft",1,"em"),m=v/x+"em",l=w/x+"em"):(m=v+"px",l=w+"px"),u&&(n=parseFloat(m)+p+s,k=parseFloat(l)+p+s)),g=na(z,y[j],m+" "+l,n+" "+k,!1,"0px",g);return g},prefix:!0,formatter:ja("0px 0px 0px 0px",!1,!0)}),qa("backgroundPosition",{defaultValue:"0 0",parser:function(a,b,c,d,f,g){var h,i,j,k,l,m,n="background-position",p=e||U(a,null),q=this.format((p?o?p.getPropertyValue(n+"-x")+" "+p.getPropertyValue(n+"-y"):p.getPropertyValue(n):a.currentStyle.backgroundPositionX+" "+a.currentStyle.backgroundPositionY)||"0 0"),r=this.format(b);if(-1!==q.indexOf("%")!=(-1!==r.indexOf("%"))&&(m=V(a,"backgroundImage").replace(A,""),m&&"none"!==m)){for(h=q.split(" "),i=r.split(" "),L.setAttribute("src",m),j=2;--j>-1;)q=h[j],k=-1!==q.indexOf("%"),k!==(-1!==i[j].indexOf("%"))&&(l=0===j?a.offsetWidth-L.width:a.offsetHeight-L.height,h[j]=k?parseFloat(q)/100*l+"px":parseFloat(q)/l*100+"%");q=h.join(" ")}return this.parseComplex(a.style,q,r,f,g)},formatter:ba}),qa("backgroundSize",{defaultValue:"0 0",formatter:ba}),qa("perspective",{defaultValue:"0px",prefix:!0}),qa("perspectiveOrigin",{defaultValue:"50% 50%",prefix:!0}),qa("transformStyle",{prefix:!0}),qa("backfaceVisibility",{prefix:!0}),qa("userSelect",{prefix:!0}),qa("margin",{parser:ka("marginTop,marginRight,marginBottom,marginLeft")}),qa("padding",{parser:ka("paddingTop,paddingRight,paddingBottom,paddingLeft")}),qa("clip",{defaultValue:"rect(0px,0px,0px,0px)",parser:function(a,b,c,d,f,g){var h,i,j;return 9>o?(i=a.currentStyle,j=8>o?" ":",",h="rect("+i.clipTop+j+i.clipRight+j+i.clipBottom+j+i.clipLeft+")",b=this.format(b).split(",").join(j)):(h=this.format(V(a,this.p,e,!1,this.dflt)),b=this.format(b)),this.parseComplex(a.style,h,b,f,g)}}),qa("textShadow",{defaultValue:"0px 0px 0px #999",color:!0,multi:!0}),qa("autoRound,strictUnits",{parser:function(a,b,c,d,e){return e}}),qa("border",{defaultValue:"0px solid #000",parser:function(a,b,c,d,f,g){return this.parseComplex(a.style,this.format(V(a,"borderTopWidth",e,!1,"0px")+" "+V(a,"borderTopStyle",e,!1,"solid")+" "+V(a,"borderTopColor",e,!1,"#000")),this.format(b),f,g)},color:!0,formatter:function(a){var b=a.split(" ");return b[0]+" "+(b[1]||"solid")+" "+(a.match(ia)||["#000"])[0]}}),qa("borderWidth",{parser:ka("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}),qa("float,cssFloat,styleFloat",{parser:function(a,b,c,d,e,f){var g=a.style,h="cssFloat"in g?"cssFloat":"styleFloat";return new ma(g,h,0,0,e,-1,c,!1,0,g[h],b)}});var Ca=function(a){var b,c=this.t,d=c.filter||V(this.data,"filter"),e=this.s+this.c*a|0;100===e&&(-1===d.indexOf("atrix(")&&-1===d.indexOf("radient(")&&-1===d.indexOf("oader(")?(c.removeAttribute("filter"),b=!V(this.data,"filter")):(c.filter=d.replace(w,""),b=!0)),b||(this.xn1&&(c.filter=d=d||"alpha(opacity="+e+")"),-1===d.indexOf("pacity")?0===e&&this.xn1||(c.filter=d+" alpha(opacity="+e+")"):c.filter=d.replace(u,"opacity="+e))};qa("opacity,alpha,autoAlpha",{defaultValue:"1",parser:function(a,b,c,d,f,g){var h=parseFloat(V(a,"opacity",e,!1,"1")),i=a.style,j="autoAlpha"===c;return"string"==typeof b&&"="===b.charAt(1)&&(b=("-"===b.charAt(0)?-1:1)*parseFloat(b.substr(2))+h),j&&1===h&&"hidden"===V(a,"visibility",e)&&0!==b&&(h=0),O?f=new ma(i,"opacity",h,b-h,f):(f=new ma(i,"opacity",100*h,100*(b-h),f),f.xn1=j?1:0,i.zoom=1,f.type=2,f.b="alpha(opacity="+f.s+")",f.e="alpha(opacity="+(f.s+f.c)+")",f.data=a,f.plugin=g,f.setRatio=Ca),j&&(f=new ma(i,"visibility",0,0,f,-1,null,!1,0,0!==h?"inherit":"hidden",0===b?"hidden":"inherit"),f.xs0="inherit",d._overwriteProps.push(f.n),d._overwriteProps.push(c)),f}});var Da=function(a,b){b&&(a.removeProperty?("ms"===b.substr(0,2)&&(b="M"+b.substr(1)),a.removeProperty(b.replace(y,"-$1").toLowerCase())):a.removeAttribute(b))},Ea=function(a){if(this.t._gsClassPT=this,1===a||0===a){this.t.setAttribute("class",0===a?this.b:this.e);for(var b=this.data,c=this.t.style;b;)b.v?c[b.p]=b.v:Da(c,b.p),b=b._next;1===a&&this.t._gsClassPT===this&&(this.t._gsClassPT=null)}else this.t.getAttribute("class")!==this.e&&this.t.setAttribute("class",this.e)};qa("className",{parser:function(a,b,d,f,g,h,i){var j,k,l,m,n,o=a.getAttribute("class")||"",p=a.style.cssText;if(g=f._classNamePT=new ma(a,d,0,0,g,2),g.setRatio=Ea,g.pr=-11,c=!0,g.b=o,k=Y(a,e),l=a._gsClassPT){for(m={},n=l.data;n;)m[n.p]=1,n=n._next;l.setRatio(1)}return a._gsClassPT=g,g.e="="!==b.charAt(1)?b:o.replace(new RegExp("\\s*\\b"+b.substr(2)+"\\b"),"")+("+"===b.charAt(0)?" "+b.substr(2):""),f._tween._duration&&(a.setAttribute("class",g.e),j=Z(a,k,Y(a),i,m),a.setAttribute("class",o),g.data=j.firstMPT,a.style.cssText=p,g=g.xfirst=f.parse(a,j.difs,g,h)),g}});var Fa=function(a){if((1===a||0===a)&&this.data._totalTime===this.data._totalDuration&&"isFromStart"!==this.data.data){var b,c,d,e,f=this.t.style,g=h.transform.parse;if("all"===this.e)f.cssText="",e=!0;else for(b=this.e.split(","),d=b.length;--d>-1;)c=b[d],h[c]&&(h[c].parse===g?e=!0:c="transformOrigin"===c?va:h[c].p),Da(f,c);e&&(Da(f,ta),this.t._gsTransform&&delete this.t._gsTransform)}};for(qa("clearProps",{parser:function(a,b,d,e,f){return f=new ma(a,d,0,0,f,2),f.setRatio=Fa,f.e=b,f.pr=-10,f.data=e._tween,c=!0,f}}),i="bezier,throwProps,physicsProps,physics2D".split(","),oa=i.length;oa--;)ra(i[oa]);i=g.prototype,i._firstPT=null,i._onInitTween=function(a,b,h){if(!a.nodeType)return!1;this._target=a,this._tween=h,this._vars=b,j=b.autoRound,c=!1,d=b.suffixMap||g.suffixMap,e=U(a,""),f=this._overwriteProps;var i,m,o,p,q,r,s,t,u,w=a.style;if(k&&""===w.zIndex&&(i=V(a,"zIndex",e),("auto"===i||""===i)&&this._addLazySet(w,"zIndex",0)),"string"==typeof b&&(p=w.cssText,i=Y(a,e),w.cssText=p+";"+b,i=Z(a,i,Y(a)).difs,!O&&v.test(b)&&(i.opacity=parseFloat(RegExp.$1)),b=i,w.cssText=p),this._firstPT=m=this.parse(a,b,null),this._transformType){for(u=3===this._transformType,ta?l&&(k=!0,""===w.zIndex&&(s=V(a,"zIndex",e),("auto"===s||""===s)&&this._addLazySet(w,"zIndex",0)),n&&this._addLazySet(w,"WebkitBackfaceVisibility",this._vars.WebkitBackfaceVisibility||(u?"visible":"hidden"))):w.zoom=1,o=m;o&&o._next;)o=o._next;t=new ma(a,"transform",0,0,null,2),this._linkCSSP(t,null,o),t.setRatio=u&&wa?Aa:ta?Ba:za,t.data=this._transform||ya(a,e,!0),f.pop()}if(c){for(;m;){for(r=m._next,o=p;o&&o.pr>m.pr;)o=o._next;(m._prev=o?o._prev:q)?m._prev._next=m:p=m,(m._next=o)?o._prev=m:q=m,m=r}this._firstPT=p}return!0},i.parse=function(a,b,c,f){var g,i,k,l,m,n,o,p,q,r,s=a.style;for(g in b)n=b[g],i=h[g],i?c=i.parse(a,n,g,this,c,f,b):(m=V(a,g,e)+"",q="string"==typeof n,"color"===g||"fill"===g||"stroke"===g||-1!==g.indexOf("Color")||q&&x.test(n)?(q||(n=ha(n),n=(n.length>3?"rgba(":"rgb(")+n.join(",")+")"),c=na(s,g,m,n,!0,"transparent",c,0,f)):!q||-1===n.indexOf(" ")&&-1===n.indexOf(",")?(k=parseFloat(m),o=k||0===k?m.substr((k+"").length):"",(""===m||"auto"===m)&&("width"===g||"height"===g?(k=aa(a,g,e),o="px"):"left"===g||"top"===g?(k=X(a,g,e),o="px"):(k="opacity"!==g?0:1,o="")),r=q&&"="===n.charAt(1),r?(l=parseInt(n.charAt(0)+"1",10),n=n.substr(2),l*=parseFloat(n),p=n.replace(t,"")):(l=parseFloat(n),p=q?n.substr((l+"").length)||"":""),""===p&&(p=g in d?d[g]:o),n=l||0===l?(r?l+k:l)+p:b[g],o!==p&&""!==p&&(l||0===l)&&k&&(k=W(a,g,k,o),"%"===p?(k/=W(a,g,100,"%")/100,b.strictUnits!==!0&&(m=k+"%")):"em"===p?k/=W(a,g,1,"em"):"px"!==p&&(l=W(a,g,l,p),p="px"),r&&(l||0===l)&&(n=l+k+p)),r&&(l+=k),!k&&0!==k||!l&&0!==l?void 0!==s[g]&&(n||n+""!="NaN"&&null!=n)?(c=new ma(s,g,l||k||0,0,c,-1,g,!1,0,m,n),c.xs0="none"!==n||"display"!==g&&-1===g.indexOf("Style")?n:m):Q("invalid "+g+" tween value: "+b[g]):(c=new ma(s,g,k,l-k,c,0,g,j!==!1&&("px"===p||"zIndex"===g),0,m,n),c.xs0=p)):c=na(s,g,m,n,!0,null,c,0,f)),f&&c&&!c.plugin&&(c.plugin=f);return c},i.setRatio=function(a){var b,c,d,e=this._firstPT,f=1e-6;if(1!==a||this._tween._time!==this._tween._duration&&0!==this._tween._time)if(a||this._tween._time!==this._tween._duration&&0!==this._tween._time||this._tween._rawPrevTime===-1e-6)for(;e;){if(b=e.c*a+e.s,e.r?b=Math.round(b):f>b&&b>-f&&(b=0),e.type)if(1===e.type)if(d=e.l,2===d)e.t[e.p]=e.xs0+b+e.xs1+e.xn1+e.xs2;else if(3===d)e.t[e.p]=e.xs0+b+e.xs1+e.xn1+e.xs2+e.xn2+e.xs3;else if(4===d)e.t[e.p]=e.xs0+b+e.xs1+e.xn1+e.xs2+e.xn2+e.xs3+e.xn3+e.xs4;else if(5===d)e.t[e.p]=e.xs0+b+e.xs1+e.xn1+e.xs2+e.xn2+e.xs3+e.xn3+e.xs4+e.xn4+e.xs5;else{for(c=e.xs0+b+e.xs1,d=1;d<e.l;d++)c+=e["xn"+d]+e["xs"+(d+1)];e.t[e.p]=c}else-1===e.type?e.t[e.p]=e.xs0:e.setRatio&&e.setRatio(a);else e.t[e.p]=b+e.xs0;e=e._next}else for(;e;)2!==e.type?e.t[e.p]=e.b:e.setRatio(a),e=e._next;else for(;e;)2!==e.type?e.t[e.p]=e.e:e.setRatio(a),e=e._next},i._enableTransforms=function(a){this._transformType=a||3===this._transformType?3:2,this._transform=this._transform||ya(this._target,e,!0)};var Ga=function(a){this.t[this.p]=this.e,this.data._linkCSSP(this,this._next,null,!0)};i._addLazySet=function(a,b,c){var d=this._firstPT=new ma(a,b,0,0,this._firstPT,2);d.e=c,d.setRatio=Ga,d.data=this},i._linkCSSP=function(a,b,c,d){return a&&(b&&(b._prev=a),a._next&&(a._next._prev=a._prev),a._prev?a._prev._next=a._next:this._firstPT===a&&(this._firstPT=a._next,d=!0),c?c._next=a:d||null!==this._firstPT||(this._firstPT=a),a._next=b,a._prev=c),a},i._kill=function(b){var c,d,e,f=b;if(b.autoAlpha||b.alpha){f={};for(d in b)f[d]=b[d];f.opacity=1,f.autoAlpha&&(f.visibility=1)}return b.className&&(c=this._classNamePT)&&(e=c.xfirst,e&&e._prev?this._linkCSSP(e._prev,c._next,e._prev._prev):e===this._firstPT&&(this._firstPT=c._next),c._next&&this._linkCSSP(c._next,c._next._next,e._prev),this._classNamePT=null),a.prototype._kill.call(this,f)};var Ha=function(a,b,c){var d,e,f,g;if(a.slice)for(e=a.length;--e>-1;)Ha(a[e],b,c);else for(d=a.childNodes,e=d.length;--e>-1;)f=d[e],g=f.type,f.style&&(b.push(Y(f)),c&&c.push(f)),1!==g&&9!==g&&11!==g||!f.childNodes.length||Ha(f,b,c)};return g.cascadeTo=function(a,c,d){var e,f,g,h=b.to(a,c,d),i=[h],j=[],k=[],l=[],m=b._internals.reservedProps;for(a=h._targets||h.target,Ha(a,j,l),h.render(c,!0),Ha(a,k),h.render(0,!0),h._enabled(!0),e=l.length;--e>-1;)if(f=Z(l[e],j[e],k[e]),f.firstMPT){f=f.difs;for(g in d)m[g]&&(f[g]=d[g]);i.push(b.to(l[e],c,f))}return i},a.activate([g]),g},!0),function(){var a=window._gsDefine.plugin({propName:"roundProps",priority:-1,API:2,init:function(a,b,c){return this._tween=c,!0}}),b=a.prototype;b._onInitAllProps=function(){for(var a,b,c,d=this._tween,e=d.vars.roundProps instanceof Array?d.vars.roundProps:d.vars.roundProps.split(","),f=e.length,g={},h=d._propLookup.roundProps;--f>-1;)g[e[f]]=1;for(f=e.length;--f>-1;)for(a=e[f],b=d._firstPT;b;)c=b._next,b.pg?b.t._roundProps(g,!0):b.n===a&&(this._add(b.t,a,b.s,b.c),c&&(c._prev=b._prev),b._prev?b._prev._next=c:d._firstPT===b&&(d._firstPT=c),b._next=b._prev=null,d._propLookup[a]=h),b=c;return!1},b._add=function(a,b,c,d){this._addTween(a,b,c,c+d,b,!0),this._overwriteProps.push(b)}}(),window._gsDefine.plugin({propName:"attr",API:2,version:"0.3.2",init:function(a,b,c){var d,e,f;if("function"!=typeof a.setAttribute)return!1;this._target=a,this._proxy={},this._start={},this._end={};for(d in b)this._start[d]=this._proxy[d]=e=a.getAttribute(d),f=this._addTween(this._proxy,d,parseFloat(e),b[d],d),this._end[d]=f?f.s+f.c:b[d],this._overwriteProps.push(d);return!0},set:function(a){this._super.setRatio.call(this,a);for(var b,c=this._overwriteProps,d=c.length,e=1===a?this._end:a?this._proxy:this._start;--d>-1;)b=c[d],this._target.setAttribute(b,e[b]+"")}}),window._gsDefine.plugin({propName:"directionalRotation",API:2,version:"0.2.0",init:function(a,b,c){"object"!=typeof b&&(b={rotation:b}),this.finals={};var d,e,f,g,h,i,j=b.useRadians===!0?2*Math.PI:360,k=1e-6;for(d in b)"useRadians"!==d&&(i=(b[d]+"").split("_"),e=i[0],f=parseFloat("function"!=typeof a[d]?a[d]:a[d.indexOf("set")||"function"!=typeof a["get"+d.substr(3)]?d:"get"+d.substr(3)]()),g=this.finals[d]="string"==typeof e&&"="===e.charAt(1)?f+parseInt(e.charAt(0)+"1",10)*Number(e.substr(2)):Number(e)||0,h=g-f,i.length&&(e=i.join("_"),-1!==e.indexOf("short")&&(h%=j,h!==h%(j/2)&&(h=0>h?h+j:h-j)),-1!==e.indexOf("_cw")&&0>h?h=(h+9999999999*j)%j-(h/j|0)*j:-1!==e.indexOf("ccw")&&h>0&&(h=(h-9999999999*j)%j-(h/j|0)*j)),(h>k||-k>h)&&(this._addTween(a,d,f,f+h,d),this._overwriteProps.push(d)));return!0},set:function(a){var b;if(1!==a)this._super.setRatio.call(this,a);else for(b=this._firstPT;b;)b.f?b.t[b.p](this.finals[b.p]):b.t[b.p]=this.finals[b.p],b=b._next}})._autoCSS=!0,window._gsDefine("easing.Back",["easing.Ease"],function(a){var b,c,d,e=window.GreenSockGlobals||window,f=e.com.greensock,g=2*Math.PI,h=Math.PI/2,i=f._class,j=function(b,c){var d=i("easing."+b,function(){},!0),e=d.prototype=new a;return e.constructor=d,e.getRatio=c,d},k=a.register||function(){},l=function(a,b,c,d,e){var f=i("easing."+a,{easeOut:new b,easeIn:new c,easeInOut:new d},!0);return k(f,a),f},m=function(a,b,c){this.t=a,this.v=b,c&&(this.next=c,c.prev=this,this.c=c.v-b,this.gap=c.t-a)},n=function(b,c){var d=i("easing."+b,function(a){this._p1=a||0===a?a:1.70158,this._p2=1.525*this._p1},!0),e=d.prototype=new a;return e.constructor=d,e.getRatio=c,e.config=function(a){return new d(a)},d},o=l("Back",n("BackOut",function(a){return(a-=1)*a*((this._p1+1)*a+this._p1)+1}),n("BackIn",function(a){return a*a*((this._p1+1)*a-this._p1)}),n("BackInOut",function(a){return(a*=2)<1?.5*a*a*((this._p2+1)*a-this._p2):.5*((a-=2)*a*((this._p2+1)*a+this._p2)+2)})),p=i("easing.SlowMo",function(a,b,c){b=b||0===b?b:.7,null==a?a=.7:a>1&&(a=1),this._p=1!==a?b:0,this._p1=(1-a)/2,this._p2=a,this._p3=this._p1+this._p2,this._calcEnd=c===!0},!0),q=p.prototype=new a;return q.constructor=p,q.getRatio=function(a){var b=a+(.5-a)*this._p;return a<this._p1?this._calcEnd?1-(a=1-a/this._p1)*a:b-(a=1-a/this._p1)*a*a*a*b:a>this._p3?this._calcEnd?1-(a=(a-this._p3)/this._p1)*a:b+(a-b)*(a=(a-this._p3)/this._p1)*a*a*a:this._calcEnd?1:b},p.ease=new p(.7,.7),q.config=p.config=function(a,b,c){return new p(a,b,c)},b=i("easing.SteppedEase",function(a){a=a||1,this._p1=1/a,this._p2=a+1},!0),q=b.prototype=new a,q.constructor=b,q.getRatio=function(a){return 0>a?a=0:a>=1&&(a=.999999999),(this._p2*a>>0)*this._p1},q.config=b.config=function(a){return new b(a)},c=i("easing.RoughEase",function(b){b=b||{};for(var c,d,e,f,g,h,i=b.taper||"none",j=[],k=0,l=0|(b.points||20),n=l,o=b.randomize!==!1,p=b.clamp===!0,q=b.template instanceof a?b.template:null,r="number"==typeof b.strength?.4*b.strength:.4;--n>-1;)c=o?Math.random():1/l*n,d=q?q.getRatio(c):c,"none"===i?e=r:"out"===i?(f=1-c,e=f*f*r):"in"===i?e=c*c*r:.5>c?(f=2*c,e=f*f*.5*r):(f=2*(1-c),e=f*f*.5*r),o?d+=Math.random()*e-.5*e:n%2?d+=.5*e:d-=.5*e,p&&(d>1?d=1:0>d&&(d=0)),j[k++]={x:c,y:d};for(j.sort(function(a,b){return a.x-b.x}),h=new m(1,1,null),n=l;--n>-1;)g=j[n],h=new m(g.x,g.y,h);this._prev=new m(0,0,0!==h.t?h:h.next)},!0),q=c.prototype=new a,q.constructor=c,q.getRatio=function(a){var b=this._prev;if(a>b.t){for(;b.next&&a>=b.t;)b=b.next;b=b.prev}else for(;b.prev&&a<=b.t;)b=b.prev;return this._prev=b,b.v+(a-b.t)/b.gap*b.c},q.config=function(a){return new c(a)},c.ease=new c,l("Bounce",j("BounceOut",function(a){return 1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375}),j("BounceIn",function(a){return(a=1-a)<1/2.75?1-7.5625*a*a:2/2.75>a?1-(7.5625*(a-=1.5/2.75)*a+.75):2.5/2.75>a?1-(7.5625*(a-=2.25/2.75)*a+.9375):1-(7.5625*(a-=2.625/2.75)*a+.984375)}),j("BounceInOut",function(a){var b=.5>a;return a=b?1-2*a:2*a-1,a=1/2.75>a?7.5625*a*a:2/2.75>a?7.5625*(a-=1.5/2.75)*a+.75:2.5/2.75>a?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375,b?.5*(1-a):.5*a+.5})),l("Circ",j("CircOut",function(a){return Math.sqrt(1-(a-=1)*a)}),j("CircIn",function(a){return-(Math.sqrt(1-a*a)-1)}),j("CircInOut",function(a){return(a*=2)<1?-.5*(Math.sqrt(1-a*a)-1):.5*(Math.sqrt(1-(a-=2)*a)+1)})),d=function(b,c,d){var e=i("easing."+b,function(a,b){this._p1=a||1,this._p2=b||d,this._p3=this._p2/g*(Math.asin(1/this._p1)||0)},!0),f=e.prototype=new a;return f.constructor=e,f.getRatio=c,f.config=function(a,b){return new e(a,b)},e},l("Elastic",d("ElasticOut",function(a){return this._p1*Math.pow(2,-10*a)*Math.sin((a-this._p3)*g/this._p2)+1},.3),d("ElasticIn",function(a){return-(this._p1*Math.pow(2,10*(a-=1))*Math.sin((a-this._p3)*g/this._p2))},.3),d("ElasticInOut",function(a){return(a*=2)<1?-.5*(this._p1*Math.pow(2,10*(a-=1))*Math.sin((a-this._p3)*g/this._p2)):this._p1*Math.pow(2,-10*(a-=1))*Math.sin((a-this._p3)*g/this._p2)*.5+1},.45)),l("Expo",j("ExpoOut",function(a){return 1-Math.pow(2,-10*a)}),j("ExpoIn",function(a){return Math.pow(2,10*(a-1))-.001}),j("ExpoInOut",function(a){return(a*=2)<1?.5*Math.pow(2,10*(a-1)):.5*(2-Math.pow(2,-10*(a-1)))})),l("Sine",j("SineOut",function(a){return Math.sin(a*h)}),j("SineIn",function(a){return-Math.cos(a*h)+1}),j("SineInOut",function(a){return-.5*(Math.cos(Math.PI*a)-1)})),i("easing.EaseLookup",{find:function(b){return a.map[b]}},!0),k(e.SlowMo,"SlowMo","ease,"),k(c,"RoughEase","ease,"),k(b,"SteppedEase","ease,"),o},!0)}),function(a){"use strict";var b=a.GreenSockGlobals||a;if(!b.TweenLite){var c,d,e,f,g,h=function(a){var c,d=a.split("."),e=b;for(c=0;c<d.length;c++)e[d[c]]=e=e[d[c]]||{};return e},i=h("com.greensock"),j=1e-10,k=[].slice,l=function(){},m=function(){var a=Object.prototype.toString,b=a.call([]);return function(c){return null!=c&&(c instanceof Array||"object"==typeof c&&!!c.push&&a.call(c)===b)}}(),n={},o=function(c,d,e,f){this.sc=n[c]?n[c].sc:[],n[c]=this,this.gsClass=null,this.func=e;var g=[];this.check=function(i){for(var j,k,l,m,p=d.length,q=p;--p>-1;)(j=n[d[p]]||new o(d[p],[])).gsClass?(g[p]=j.gsClass,q--):i&&j.sc.push(this);if(0===q&&e)for(k=("com.greensock."+c).split("."),l=k.pop(),m=h(k.join("."))[l]=this.gsClass=e.apply(e,g),f&&(b[l]=m,"function"==typeof define&&define.amd?define((a.GreenSockAMDPath?a.GreenSockAMDPath+"/":"")+c.split(".").join("/"),[],function(){return m}):"undefined"!=typeof module&&module.exports&&(module.exports=m)),p=0;p<this.sc.length;p++)this.sc[p].check()},this.check(!0)},p=a._gsDefine=function(a,b,c,d){return new o(a,b,c,d)},q=i._class=function(a,b,c){return b=b||function(){},p(a,[],function(){return b},c),b};p.globals=b;var r=[0,0,1,1],s=[],t=q("easing.Ease",function(a,b,c,d){this._func=a,this._type=c||0,this._power=d||0,this._params=b?r.concat(b):r},!0),u=t.map={},v=t.register=function(a,b,c,d){for(var e,f,g,h,j=b.split(","),k=j.length,l=(c||"easeIn,easeOut,easeInOut").split(",");--k>-1;)for(f=j[k],e=d?q("easing."+f,null,!0):i.easing[f]||{},g=l.length;--g>-1;)h=l[g],u[f+"."+h]=u[h+f]=e[h]=a.getRatio?a:a[h]||new a};for(e=t.prototype,e._calcEnd=!1,e.getRatio=function(a){if(this._func)return this._params[0]=a,this._func.apply(null,this._params);var b=this._type,c=this._power,d=1===b?1-a:2===b?a:.5>a?2*a:2*(1-a);return 1===c?d*=d:2===c?d*=d*d:3===c?d*=d*d*d:4===c&&(d*=d*d*d*d),1===b?1-d:2===b?d:.5>a?d/2:1-d/2},c=["Linear","Quad","Cubic","Quart","Quint,Strong"],d=c.length;--d>-1;)e=c[d]+",Power"+d,v(new t(null,null,1,d),e,"easeOut",!0),v(new t(null,null,2,d),e,"easeIn"+(0===d?",easeNone":"")),v(new t(null,null,3,d),e,"easeInOut");u.linear=i.easing.Linear.easeIn,u.swing=i.easing.Quad.easeInOut;var w=q("events.EventDispatcher",function(a){this._listeners={},this._eventTarget=a||this});e=w.prototype,e.addEventListener=function(a,b,c,d,e){e=e||0;var h,i,j=this._listeners[a],k=0;for(null==j&&(this._listeners[a]=j=[]),i=j.length;--i>-1;)h=j[i],h.c===b&&h.s===c?j.splice(i,1):0===k&&h.pr<e&&(k=i+1);j.splice(k,0,{c:b,s:c,up:d,pr:e}),this!==f||g||f.wake()},e.removeEventListener=function(a,b){var c,d=this._listeners[a];if(d)for(c=d.length;--c>-1;)if(d[c].c===b)return void d.splice(c,1)},e.dispatchEvent=function(a){var b,c,d,e=this._listeners[a];if(e)for(b=e.length,c=this._eventTarget;--b>-1;)d=e[b],d.up?d.c.call(d.s||c,{type:a,target:c}):d.c.call(d.s||c)};var x=a.requestAnimationFrame,y=a.cancelAnimationFrame,z=Date.now||function(){return(new Date).getTime()},A=z();for(c=["ms","moz","webkit","o"],d=c.length;--d>-1&&!x;)x=a[c[d]+"RequestAnimationFrame"],y=a[c[d]+"CancelAnimationFrame"]||a[c[d]+"CancelRequestAnimationFrame"];q("Ticker",function(a,b){var c,d,e,h,i,k=this,m=z(),n=b!==!1&&x,o=500,p=33,q=function(a){var b,f,g=z()-A;g>o&&(m+=g-p),A+=g,k.time=(A-m)/1e3,b=k.time-i,(!c||b>0||a===!0)&&(k.frame++,i+=b+(b>=h?.004:h-b),f=!0),a!==!0&&(e=d(q)),f&&k.dispatchEvent("tick")};w.call(k),k.time=k.frame=0,k.tick=function(){q(!0)},k.lagSmoothing=function(a,b){o=a||1/j,p=Math.min(b,o,0)},k.sleep=function(){null!=e&&(n&&y?y(e):clearTimeout(e),d=l,e=null,k===f&&(g=!1))},k.wake=function(){null!==e?k.sleep():k.frame>10&&(A=z()-o+5),d=0===c?l:n&&x?x:function(a){return setTimeout(a,1e3*(i-k.time)+1|0)},k===f&&(g=!0),q(2)},k.fps=function(a){return arguments.length?(c=a,h=1/(c||60),i=this.time+h,void k.wake()):c},k.useRAF=function(a){return arguments.length?(k.sleep(),n=a,void k.fps(c)):n},k.fps(a),setTimeout(function(){n&&(!e||k.frame<5)&&k.useRAF(!1)},1500)}),e=i.Ticker.prototype=new i.events.EventDispatcher,e.constructor=i.Ticker;var B=q("core.Animation",function(a,b){if(this.vars=b=b||{},this._duration=this._totalDuration=a||0,this._delay=Number(b.delay)||0,this._timeScale=1,this._active=b.immediateRender===!0,this.data=b.data,this._reversed=b.reversed===!0,Q){g||f.wake();var c=this.vars.useFrames?P:Q;c.add(this,c._time),this.vars.paused&&this.paused(!0)}});f=B.ticker=new i.Ticker,e=B.prototype,e._dirty=e._gc=e._initted=e._paused=!1,e._totalTime=e._time=0,e._rawPrevTime=-1,e._next=e._last=e._onUpdate=e._timeline=e.timeline=null,e._paused=!1;var C=function(){g&&z()-A>2e3&&f.wake(),setTimeout(C,2e3)};C(),e.play=function(a,b){return null!=a&&this.seek(a,b),this.reversed(!1).paused(!1)},e.pause=function(a,b){return null!=a&&this.seek(a,b),this.paused(!0)},e.resume=function(a,b){return null!=a&&this.seek(a,b),this.paused(!1)},e.seek=function(a,b){return this.totalTime(Number(a),b!==!1)},e.restart=function(a,b){return this.reversed(!1).paused(!1).totalTime(a?-this._delay:0,b!==!1,!0)},e.reverse=function(a,b){return null!=a&&this.seek(a||this.totalDuration(),b),this.reversed(!0).paused(!1)},e.render=function(a,b,c){},e.invalidate=function(){return this},e.isActive=function(){var a,b=this._timeline,c=this._startTime;return!b||!this._gc&&!this._paused&&b.isActive()&&(a=b.rawTime())>=c&&a<c+this.totalDuration()/this._timeScale},e._enabled=function(a,b){return g||f.wake(),this._gc=!a,this._active=this.isActive(),b!==!0&&(a&&!this.timeline?this._timeline.add(this,this._startTime-this._delay):!a&&this.timeline&&this._timeline._remove(this,!0)),!1},e._kill=function(a,b){return this._enabled(!1,!1)},e.kill=function(a,b){return this._kill(a,b),this},e._uncache=function(a){for(var b=a?this:this.timeline;b;)b._dirty=!0,b=b.timeline;return this},e._swapSelfInParams=function(a){for(var b=a.length,c=a.concat();--b>-1;)"{self}"===a[b]&&(c[b]=this);return c},e.eventCallback=function(a,b,c,d){if("on"===(a||"").substr(0,2)){var e=this.vars;if(1===arguments.length)return e[a];null==b?delete e[a]:(e[a]=b,e[a+"Params"]=m(c)&&-1!==c.join("").indexOf("{self}")?this._swapSelfInParams(c):c,e[a+"Scope"]=d),"onUpdate"===a&&(this._onUpdate=b)}return this},e.delay=function(a){return arguments.length?(this._timeline.smoothChildTiming&&this.startTime(this._startTime+a-this._delay),this._delay=a,this):this._delay},e.duration=function(a){return arguments.length?(this._duration=this._totalDuration=a,this._uncache(!0),this._timeline.smoothChildTiming&&this._time>0&&this._time<this._duration&&0!==a&&this.totalTime(this._totalTime*(a/this._duration),!0),this):(this._dirty=!1,this._duration)},e.totalDuration=function(a){return this._dirty=!1,arguments.length?this.duration(a):this._totalDuration},e.time=function(a,b){return arguments.length?(this._dirty&&this.totalDuration(),this.totalTime(a>this._duration?this._duration:a,b)):this._time},e.totalTime=function(a,b,c){if(g||f.wake(),!arguments.length)return this._totalTime;if(this._timeline){if(0>a&&!c&&(a+=this.totalDuration()),this._timeline.smoothChildTiming){this._dirty&&this.totalDuration();var d=this._totalDuration,e=this._timeline;if(a>d&&!c&&(a=d),this._startTime=(this._paused?this._pauseTime:e._time)-(this._reversed?d-a:a)/this._timeScale,e._dirty||this._uncache(!1),e._timeline)for(;e._timeline;)e._timeline._time!==(e._startTime+e._totalTime)/e._timeScale&&e.totalTime(e._totalTime,!0),e=e._timeline}this._gc&&this._enabled(!0,!1),(this._totalTime!==a||0===this._duration)&&(this.render(a,b,!1),H.length&&R())}return this},e.progress=e.totalProgress=function(a,b){return arguments.length?this.totalTime(this.duration()*a,b):this._time/this.duration()},e.startTime=function(a){return arguments.length?(a!==this._startTime&&(this._startTime=a,
-this.timeline&&this.timeline._sortChildren&&this.timeline.add(this,a-this._delay)),this):this._startTime},e.timeScale=function(a){if(!arguments.length)return this._timeScale;if(a=a||j,this._timeline&&this._timeline.smoothChildTiming){var b=this._pauseTime,c=b||0===b?b:this._timeline.totalTime();this._startTime=c-(c-this._startTime)*this._timeScale/a}return this._timeScale=a,this._uncache(!1)},e.reversed=function(a){return arguments.length?(a!=this._reversed&&(this._reversed=a,this.totalTime(this._timeline&&!this._timeline.smoothChildTiming?this.totalDuration()-this._totalTime:this._totalTime,!0)),this):this._reversed},e.paused=function(a){if(!arguments.length)return this._paused;if(a!=this._paused&&this._timeline){g||a||f.wake();var b=this._timeline,c=b.rawTime(),d=c-this._pauseTime;!a&&b.smoothChildTiming&&(this._startTime+=d,this._uncache(!1)),this._pauseTime=a?c:null,this._paused=a,this._active=this.isActive(),!a&&0!==d&&this._initted&&this.duration()&&this.render(b.smoothChildTiming?this._totalTime:(c-this._startTime)/this._timeScale,!0,!0)}return this._gc&&!a&&this._enabled(!0,!1),this};var D=q("core.SimpleTimeline",function(a){B.call(this,0,a),this.autoRemoveChildren=this.smoothChildTiming=!0});e=D.prototype=new B,e.constructor=D,e.kill()._gc=!1,e._first=e._last=null,e._sortChildren=!1,e.add=e.insert=function(a,b,c,d){var e,f;if(a._startTime=Number(b||0)+a._delay,a._paused&&this!==a._timeline&&(a._pauseTime=a._startTime+(this.rawTime()-a._startTime)/a._timeScale),a.timeline&&a.timeline._remove(a,!0),a.timeline=a._timeline=this,a._gc&&a._enabled(!0,!0),e=this._last,this._sortChildren)for(f=a._startTime;e&&e._startTime>f;)e=e._prev;return e?(a._next=e._next,e._next=a):(a._next=this._first,this._first=a),a._next?a._next._prev=a:this._last=a,a._prev=e,this._timeline&&this._uncache(!0),this},e._remove=function(a,b){return a.timeline===this&&(b||a._enabled(!1,!0),a.timeline=null,a._prev?a._prev._next=a._next:this._first===a&&(this._first=a._next),a._next?a._next._prev=a._prev:this._last===a&&(this._last=a._prev),this._timeline&&this._uncache(!0)),this},e.render=function(a,b,c){var d,e=this._first;for(this._totalTime=this._time=this._rawPrevTime=a;e;)d=e._next,(e._active||a>=e._startTime&&!e._paused)&&(e._reversed?e.render((e._dirty?e.totalDuration():e._totalDuration)-(a-e._startTime)*e._timeScale,b,c):e.render((a-e._startTime)*e._timeScale,b,c)),e=d},e.rawTime=function(){return g||f.wake(),this._totalTime};var E=q("TweenLite",function(b,c,d){if(B.call(this,c,d),this.render=E.prototype.render,null==b)throw"Cannot tween a null target.";this.target=b="string"!=typeof b?b:E.selector(b)||b;var e,f,g,h=b.jquery||b.length&&b!==a&&b[0]&&(b[0]===a||b[0].nodeType&&b[0].style&&!b.nodeType),i=this.vars.overwrite;if(this._overwrite=i=null==i?O[E.defaultOverwrite]:"number"==typeof i?i>>0:O[i],(h||b instanceof Array||b.push&&m(b))&&"number"!=typeof b[0])for(this._targets=g=k.call(b,0),this._propLookup=[],this._siblings=[],e=0;e<g.length;e++)f=g[e],f?"string"!=typeof f?f.length&&f!==a&&f[0]&&(f[0]===a||f[0].nodeType&&f[0].style&&!f.nodeType)?(g.splice(e--,1),this._targets=g=g.concat(k.call(f,0))):(this._siblings[e]=S(f,this,!1),1===i&&this._siblings[e].length>1&&T(f,this,null,1,this._siblings[e])):(f=g[e--]=E.selector(f),"string"==typeof f&&g.splice(e+1,1)):g.splice(e--,1);else this._propLookup={},this._siblings=S(b,this,!1),1===i&&this._siblings.length>1&&T(b,this,null,1,this._siblings);(this.vars.immediateRender||0===c&&0===this._delay&&this.vars.immediateRender!==!1)&&(this._time=-j,this.render(-this._delay))},!0),F=function(b){return b.length&&b!==a&&b[0]&&(b[0]===a||b[0].nodeType&&b[0].style&&!b.nodeType)},G=function(a,b){var c,d={};for(c in a)N[c]||c in b&&"transform"!==c&&"x"!==c&&"y"!==c&&"width"!==c&&"height"!==c&&"className"!==c&&"border"!==c||!(!K[c]||K[c]&&K[c]._autoCSS)||(d[c]=a[c],delete a[c]);a.css=d};e=E.prototype=new B,e.constructor=E,e.kill()._gc=!1,e.ratio=0,e._firstPT=e._targets=e._overwrittenProps=e._startAt=null,e._notifyPluginsOfEnabled=e._lazy=!1,E.version="1.12.1",E.defaultEase=e._ease=new t(null,null,1,1),E.defaultOverwrite="auto",E.ticker=f,E.autoSleep=!0,E.lagSmoothing=function(a,b){f.lagSmoothing(a,b)},E.selector=a.$||a.jQuery||function(b){return a.$?(E.selector=a.$,a.$(b)):a.document?a.document.getElementById("#"===b.charAt(0)?b.substr(1):b):b};var H=[],I={},J=E._internals={isArray:m,isSelector:F,lazyTweens:H},K=E._plugins={},L=J.tweenLookup={},M=0,N=J.reservedProps={ease:1,delay:1,overwrite:1,onComplete:1,onCompleteParams:1,onCompleteScope:1,useFrames:1,runBackwards:1,startAt:1,onUpdate:1,onUpdateParams:1,onUpdateScope:1,onStart:1,onStartParams:1,onStartScope:1,onReverseComplete:1,onReverseCompleteParams:1,onReverseCompleteScope:1,onRepeat:1,onRepeatParams:1,onRepeatScope:1,easeParams:1,yoyo:1,immediateRender:1,repeat:1,repeatDelay:1,data:1,paused:1,reversed:1,autoCSS:1,lazy:1},O={none:0,all:1,auto:2,concurrent:3,allOnStart:4,preexisting:5,"true":1,"false":0},P=B._rootFramesTimeline=new D,Q=B._rootTimeline=new D,R=function(){var a=H.length;for(I={};--a>-1;)c=H[a],c&&c._lazy!==!1&&(c.render(c._lazy,!1,!0),c._lazy=!1);H.length=0};Q._startTime=f.time,P._startTime=f.frame,Q._active=P._active=!0,setTimeout(R,1),B._updateRoot=E.render=function(){var a,b,c;if(H.length&&R(),Q.render((f.time-Q._startTime)*Q._timeScale,!1,!1),P.render((f.frame-P._startTime)*P._timeScale,!1,!1),H.length&&R(),!(f.frame%120)){for(c in L){for(b=L[c].tweens,a=b.length;--a>-1;)b[a]._gc&&b.splice(a,1);0===b.length&&delete L[c]}if(c=Q._first,(!c||c._paused)&&E.autoSleep&&!P._first&&1===f._listeners.tick.length){for(;c&&c._paused;)c=c._next;c||f.sleep()}}},f.addEventListener("tick",B._updateRoot);var S=function(a,b,c){var d,e,f=a._gsTweenID;if(L[f||(a._gsTweenID=f="t"+M++)]||(L[f]={target:a,tweens:[]}),b&&(d=L[f].tweens,d[e=d.length]=b,c))for(;--e>-1;)d[e]===b&&d.splice(e,1);return L[f].tweens},T=function(a,b,c,d,e){var f,g,h,i;if(1===d||d>=4){for(i=e.length,f=0;i>f;f++)if((h=e[f])!==b)h._gc||h._enabled(!1,!1)&&(g=!0);else if(5===d)break;return g}var k,l=b._startTime+j,m=[],n=0,o=0===b._duration;for(f=e.length;--f>-1;)(h=e[f])===b||h._gc||h._paused||(h._timeline!==b._timeline?(k=k||U(b,0,o),0===U(h,k,o)&&(m[n++]=h)):h._startTime<=l&&h._startTime+h.totalDuration()/h._timeScale>l&&((o||!h._initted)&&l-h._startTime<=2e-10||(m[n++]=h)));for(f=n;--f>-1;)h=m[f],2===d&&h._kill(c,a)&&(g=!0),(2!==d||!h._firstPT&&h._initted)&&h._enabled(!1,!1)&&(g=!0);return g},U=function(a,b,c){for(var d=a._timeline,e=d._timeScale,f=a._startTime;d._timeline;){if(f+=d._startTime,e*=d._timeScale,d._paused)return-100;d=d._timeline}return f/=e,f>b?f-b:c&&f===b||!a._initted&&2*j>f-b?j:(f+=a.totalDuration()/a._timeScale/e)>b+j?0:f-b-j};e._init=function(){var a,b,c,d,e,f=this.vars,g=this._overwrittenProps,h=this._duration,i=!!f.immediateRender,j=f.ease;if(f.startAt){this._startAt&&(this._startAt.render(-1,!0),this._startAt.kill()),e={};for(d in f.startAt)e[d]=f.startAt[d];if(e.overwrite=!1,e.immediateRender=!0,e.lazy=i&&f.lazy!==!1,e.startAt=e.delay=null,this._startAt=E.to(this.target,0,e),i)if(this._time>0)this._startAt=null;else if(0!==h)return}else if(f.runBackwards&&0!==h)if(this._startAt)this._startAt.render(-1,!0),this._startAt.kill(),this._startAt=null;else{c={};for(d in f)N[d]&&"autoCSS"!==d||(c[d]=f[d]);if(c.overwrite=0,c.data="isFromStart",c.lazy=i&&f.lazy!==!1,c.immediateRender=i,this._startAt=E.to(this.target,0,c),i){if(0===this._time)return}else this._startAt._init(),this._startAt._enabled(!1)}if(j?j instanceof t?this._ease=f.easeParams instanceof Array?j.config.apply(j,f.easeParams):j:this._ease="function"==typeof j?new t(j,f.easeParams):u[j]||E.defaultEase:this._ease=E.defaultEase,this._easeType=this._ease._type,this._easePower=this._ease._power,this._firstPT=null,this._targets)for(a=this._targets.length;--a>-1;)this._initProps(this._targets[a],this._propLookup[a]={},this._siblings[a],g?g[a]:null)&&(b=!0);else b=this._initProps(this.target,this._propLookup,this._siblings,g);if(b&&E._onPluginEvent("_onInitAllProps",this),g&&(this._firstPT||"function"!=typeof this.target&&this._enabled(!1,!1)),f.runBackwards)for(c=this._firstPT;c;)c.s+=c.c,c.c=-c.c,c=c._next;this._onUpdate=f.onUpdate,this._initted=!0},e._initProps=function(b,c,d,e){var f,g,h,i,j,k;if(null==b)return!1;I[b._gsTweenID]&&R(),this.vars.css||b.style&&b!==a&&b.nodeType&&K.css&&this.vars.autoCSS!==!1&&G(this.vars,b);for(f in this.vars){if(k=this.vars[f],N[f])k&&(k instanceof Array||k.push&&m(k))&&-1!==k.join("").indexOf("{self}")&&(this.vars[f]=k=this._swapSelfInParams(k,this));else if(K[f]&&(i=new K[f])._onInitTween(b,this.vars[f],this)){for(this._firstPT=j={_next:this._firstPT,t:i,p:"setRatio",s:0,c:1,f:!0,n:f,pg:!0,pr:i._priority},g=i._overwriteProps.length;--g>-1;)c[i._overwriteProps[g]]=this._firstPT;(i._priority||i._onInitAllProps)&&(h=!0),(i._onDisable||i._onEnable)&&(this._notifyPluginsOfEnabled=!0)}else this._firstPT=c[f]=j={_next:this._firstPT,t:b,p:f,f:"function"==typeof b[f],n:f,pg:!1,pr:0},j.s=j.f?b[f.indexOf("set")||"function"!=typeof b["get"+f.substr(3)]?f:"get"+f.substr(3)]():parseFloat(b[f]),j.c="string"==typeof k&&"="===k.charAt(1)?parseInt(k.charAt(0)+"1",10)*Number(k.substr(2)):Number(k)-j.s||0;j&&j._next&&(j._next._prev=j)}return e&&this._kill(e,b)?this._initProps(b,c,d,e):this._overwrite>1&&this._firstPT&&d.length>1&&T(b,this,c,this._overwrite,d)?(this._kill(c,b),this._initProps(b,c,d,e)):(this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration)&&(I[b._gsTweenID]=!0),h)},e.render=function(a,b,c){var d,e,f,g,h=this._time,i=this._duration,k=this._rawPrevTime;if(a>=i)this._totalTime=this._time=i,this.ratio=this._ease._calcEnd?this._ease.getRatio(1):1,this._reversed||(d=!0,e="onComplete"),0===i&&(this._initted||!this.vars.lazy||c)&&(this._startTime===this._timeline._duration&&(a=0),(0===a||0>k||k===j)&&k!==a&&(c=!0,k>j&&(e="onReverseComplete")),this._rawPrevTime=g=!b||a||k===a?a:j);else if(1e-7>a)this._totalTime=this._time=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0,(0!==h||0===i&&k>0&&k!==j)&&(e="onReverseComplete",d=this._reversed),0>a?(this._active=!1,0===i&&(this._initted||!this.vars.lazy||c)&&(k>=0&&(c=!0),this._rawPrevTime=g=!b||a||k===a?a:j)):this._initted||(c=!0);else if(this._totalTime=this._time=a,this._easeType){var l=a/i,m=this._easeType,n=this._easePower;(1===m||3===m&&l>=.5)&&(l=1-l),3===m&&(l*=2),1===n?l*=l:2===n?l*=l*l:3===n?l*=l*l*l:4===n&&(l*=l*l*l*l),1===m?this.ratio=1-l:2===m?this.ratio=l:.5>a/i?this.ratio=l/2:this.ratio=1-l/2}else this.ratio=this._ease.getRatio(a/i);if(this._time!==h||c){if(!this._initted){if(this._init(),!this._initted||this._gc)return;if(!c&&this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration))return this._time=this._totalTime=h,this._rawPrevTime=k,H.push(this),void(this._lazy=a);this._time&&!d?this.ratio=this._ease.getRatio(this._time/i):d&&this._ease._calcEnd&&(this.ratio=this._ease.getRatio(0===this._time?0:1))}for(this._lazy!==!1&&(this._lazy=!1),this._active||!this._paused&&this._time!==h&&a>=0&&(this._active=!0),0===h&&(this._startAt&&(a>=0?this._startAt.render(a,b,c):e||(e="_dummyGS")),this.vars.onStart&&(0!==this._time||0===i)&&(b||this.vars.onStart.apply(this.vars.onStartScope||this,this.vars.onStartParams||s))),f=this._firstPT;f;)f.f?f.t[f.p](f.c*this.ratio+f.s):f.t[f.p]=f.c*this.ratio+f.s,f=f._next;this._onUpdate&&(0>a&&this._startAt&&this._startTime&&this._startAt.render(a,b,c),b||(this._time!==h||d)&&this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||s)),e&&(this._gc||(0>a&&this._startAt&&!this._onUpdate&&this._startTime&&this._startAt.render(a,b,c),d&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!b&&this.vars[e]&&this.vars[e].apply(this.vars[e+"Scope"]||this,this.vars[e+"Params"]||s),0===i&&this._rawPrevTime===j&&g!==j&&(this._rawPrevTime=0)))}},e._kill=function(a,b){if("all"===a&&(a=null),null==a&&(null==b||b===this.target))return this._lazy=!1,this._enabled(!1,!1);b="string"!=typeof b?b||this._targets||this.target:E.selector(b)||b;var c,d,e,f,g,h,i,j;if((m(b)||F(b))&&"number"!=typeof b[0])for(c=b.length;--c>-1;)this._kill(a,b[c])&&(h=!0);else{if(this._targets){for(c=this._targets.length;--c>-1;)if(b===this._targets[c]){g=this._propLookup[c]||{},this._overwrittenProps=this._overwrittenProps||[],d=this._overwrittenProps[c]=a?this._overwrittenProps[c]||{}:"all";break}}else{if(b!==this.target)return!1;g=this._propLookup,d=this._overwrittenProps=a?this._overwrittenProps||{}:"all"}if(g){i=a||g,j=a!==d&&"all"!==d&&a!==g&&("object"!=typeof a||!a._tempKill);for(e in i)(f=g[e])&&(f.pg&&f.t._kill(i)&&(h=!0),f.pg&&0!==f.t._overwriteProps.length||(f._prev?f._prev._next=f._next:f===this._firstPT&&(this._firstPT=f._next),f._next&&(f._next._prev=f._prev),f._next=f._prev=null),delete g[e]),j&&(d[e]=1);!this._firstPT&&this._initted&&this._enabled(!1,!1)}}return h},e.invalidate=function(){return this._notifyPluginsOfEnabled&&E._onPluginEvent("_onDisable",this),this._firstPT=null,this._overwrittenProps=null,this._onUpdate=null,this._startAt=null,this._initted=this._active=this._notifyPluginsOfEnabled=this._lazy=!1,this._propLookup=this._targets?{}:[],this},e._enabled=function(a,b){if(g||f.wake(),a&&this._gc){var c,d=this._targets;if(d)for(c=d.length;--c>-1;)this._siblings[c]=S(d[c],this,!0);else this._siblings=S(this.target,this,!0)}return B.prototype._enabled.call(this,a,b),this._notifyPluginsOfEnabled&&this._firstPT?E._onPluginEvent(a?"_onEnable":"_onDisable",this):!1},E.to=function(a,b,c){return new E(a,b,c)},E.from=function(a,b,c){return c.runBackwards=!0,c.immediateRender=0!=c.immediateRender,new E(a,b,c)},E.fromTo=function(a,b,c,d){return d.startAt=c,d.immediateRender=0!=d.immediateRender&&0!=c.immediateRender,new E(a,b,d)},E.delayedCall=function(a,b,c,d,e){return new E(b,0,{delay:a,onComplete:b,onCompleteParams:c,onCompleteScope:d,onReverseComplete:b,onReverseCompleteParams:c,onReverseCompleteScope:d,immediateRender:!1,useFrames:e,overwrite:0})},E.set=function(a,b){return new E(a,0,b)},E.getTweensOf=function(a,b){if(null==a)return[];a="string"!=typeof a?a:E.selector(a)||a;var c,d,e,f;if((m(a)||F(a))&&"number"!=typeof a[0]){for(c=a.length,d=[];--c>-1;)d=d.concat(E.getTweensOf(a[c],b));for(c=d.length;--c>-1;)for(f=d[c],e=c;--e>-1;)f===d[e]&&d.splice(c,1)}else for(d=S(a).concat(),c=d.length;--c>-1;)(d[c]._gc||b&&!d[c].isActive())&&d.splice(c,1);return d},E.killTweensOf=E.killDelayedCallsTo=function(a,b,c){"object"==typeof b&&(c=b,b=!1);for(var d=E.getTweensOf(a,b),e=d.length;--e>-1;)d[e]._kill(c,a)};var V=q("plugins.TweenPlugin",function(a,b){this._overwriteProps=(a||"").split(","),this._propName=this._overwriteProps[0],this._priority=b||0,this._super=V.prototype},!0);if(e=V.prototype,V.version="1.10.1",V.API=2,e._firstPT=null,e._addTween=function(a,b,c,d,e,f){var g,h;return null!=d&&(g="number"==typeof d||"="!==d.charAt(1)?Number(d)-c:parseInt(d.charAt(0)+"1",10)*Number(d.substr(2)))?(this._firstPT=h={_next:this._firstPT,t:a,p:b,s:c,c:g,f:"function"==typeof a[b],n:e||b,r:f},h._next&&(h._next._prev=h),h):void 0},e.setRatio=function(a){for(var b,c=this._firstPT,d=1e-6;c;)b=c.c*a+c.s,c.r?b=Math.round(b):d>b&&b>-d&&(b=0),c.f?c.t[c.p](b):c.t[c.p]=b,c=c._next},e._kill=function(a){var b,c=this._overwriteProps,d=this._firstPT;if(null!=a[this._propName])this._overwriteProps=[];else for(b=c.length;--b>-1;)null!=a[c[b]]&&c.splice(b,1);for(;d;)null!=a[d.n]&&(d._next&&(d._next._prev=d._prev),d._prev?(d._prev._next=d._next,d._prev=null):this._firstPT===d&&(this._firstPT=d._next)),d=d._next;return!1},e._roundProps=function(a,b){for(var c=this._firstPT;c;)(a[this._propName]||null!=c.n&&a[c.n.split(this._propName+"_").join("")])&&(c.r=b),c=c._next},E._onPluginEvent=function(a,b){var c,d,e,f,g,h=b._firstPT;if("_onInitAllProps"===a){for(;h;){for(g=h._next,d=e;d&&d.pr>h.pr;)d=d._next;(h._prev=d?d._prev:f)?h._prev._next=h:e=h,(h._next=d)?d._prev=h:f=h,h=g}h=b._firstPT=e}for(;h;)h.pg&&"function"==typeof h.t[a]&&h.t[a]()&&(c=!0),h=h._next;return c},V.activate=function(a){for(var b=a.length;--b>-1;)a[b].API===V.API&&(K[(new a[b])._propName]=a[b]);return!0},p.plugin=function(a){if(!(a&&a.propName&&a.init&&a.API))throw"illegal plugin definition.";var b,c=a.propName,d=a.priority||0,e=a.overwriteProps,f={init:"_onInitTween",set:"setRatio",kill:"_kill",round:"_roundProps",initAll:"_onInitAllProps"},g=q("plugins."+c.charAt(0).toUpperCase()+c.substr(1)+"Plugin",function(){V.call(this,c,d),this._overwriteProps=e||[]},a.global===!0),h=g.prototype=new V(c);h.constructor=g,g.API=a.API;for(b in f)"function"==typeof a[b]&&(h[f[b]]=a[b]);return g.version=a.version,V.activate([g]),g},c=a._gsQueue){for(d=0;d<c.length;d++)c[d]();for(e in n)!n[e].func}g=!1}}(window),angular.module("att.abs.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)},100),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]).factory("$scrollTo",["$window",function(a){var b=function(b,c,d){TweenMax.to(a,d||1,{scrollTo:{y:c,x:b},ease:Power4.easeOut})};return b}]).factory("animation",function(){return TweenMax}).factory("$progressBar",function(){var a=function(a){var b=function(b,c){TweenMax.to({},c,{onUpdateParams:["{self}"],onUpdate:a,onComplete:b})};return function(){return b}()};return a}).factory("$height",function(){var a=function(a,b,c,d){TweenMax.to(a,b,{height:c,autoAlpha:d},0)};return a}),angular.module("att.abs.accordion",["att.abs.utilities","att.abs.position","att.abs.transition"]).constant("accordionConfig",{closeOthers:!1}).controller("AccordionController",["$scope","$attrs","accordionConfig","$log",function(a,b,c,d){this.groups=[],this.index=-1,this.scope=a,a.forceExpand=!1,this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&!a.forceExpand&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)}),this.groups.indexOf(d)===this.groups.length-1&&a.forceExpand&&(a.forceExpand=!1)},this.expandAll=function(){a.forceExpand=!0,angular.forEach(this.groups,function(a){a.isOpen=!0})},this.collapseAll=function(){angular.forEach(this.groups,function(a){a.isOpen=!1})},this.focus=function(a){var b=this;angular.forEach(this.groups,function(c,d){c!==a?c.focused=!1:(b.index=d,c.focused=!0)})},this.blur=function(a){a.focused=!1,this.index=-1,d.log("accordion.blur()",a)},this.cycle=function(b,c,d){if(c)if(this.index===this.groups.length-1){if(d)return this.index=0,b.focused=!1,void a.$apply();this.index=0}else this.index++;else this.index<=0&&!d?this.index=this.groups.length-1:this.index--;b.focused=!1,this.groups[this.index].setFocus=!0,this.groups[this.index].focused=!0,a.$apply()},this.addGroup=function(a){var b=this;a.index=this.groups.length,a.focused=!1,this.groups.push(a),this.groups.length>0&&(this.index=0),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(this.groups.indexOf(a),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,scope:{cClass:"@css",expandAll:"=?",collapseAll:"=?"},template:'<div class="{{cClass}}" ng-transclude></div>',link:function(a,b,c,d){a.$watch("expandAll",function(b){b&&(d.expandAll(),a.expandAll=!1)}),a.$watch("collapseAll",function(b){b&&(d.collapseAll(),a.collapseAll=!1)})}}}).directive("accordionGroup",[function(){return{require:["^accordion","accordionGroup"],restrict:"EA",transclude:!0,replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/accordion/accordion.html",scope:{heading:"@",isOpen:"=?"},controller:["$scope",function(a){a.showicon=!0,this.setHeading=function(b){this.heading=b,a.showicon=!1},this.isIsOpen=function(){return a.isOpen}}],link:function(a,b,c,d){var e=d[0],f=d[1],g={tab:9,enter:13,esc:27,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,up:38,right:39,down:40},h=b.children().eq(0);a.setFocus=!1;var i=function(b){var c=!0;switch(b.keyCode){case g.enter:b.preventDefault(),a.toggle(),a.$apply();break;case g.up:case g.left:b.preventDefault(),e.cycle(a,!1);break;case g.down:case g.right:b.preventDefault(),e.cycle(a,!0);break;default:c=!1}return b.stopPropagation(),c};angular.isUndefined(a.isOpen)&&(a.isOpen=!1),h.bind("keydown",i),e.addGroup(a),0===a.index&&(a.focused=!0),f.toggle=a.toggle=function(){return a.isOpen=!a.isOpen,e.focus(a),a.isOpen},a.$watch("isOpen",function(b){b&&e.closeOthers(a)}),a.$watch("focused",function(b){b?(h.attr("tabindex","0"),a.setFocus&&h[0].focus()):(a.setFocus=!1,h.attr("tabindex","-1"))})}}}]).directive("accordionToggle",function(){return{restrict:"EA",require:"^accordionGroup",scope:{expandIcon:"@",collapseIcon:"@"},link:function(a,b,c,d){var e=function(c){a.expandIcon&&a.collapseIcon&&(c?(b.removeClass(a.expandIcon),b.addClass(a.collapseIcon)):(b.removeClass(a.collapseIcon),b.addClass(a.expandIcon)))};b.bind("click",function(){d.toggle(),a.$apply()}),a.$watch(function(){return d.isIsOpen()},function(a){e(a)})}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",require:"^accordionGroup",compile:function(a,b,c){var d=function(a,b,d,e){c(a,function(a){b.append(a),e.setHeading(b)})};return d}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&b.find("span").eq(0).prepend(a)})}}}).directive("attGoTop",["$scrollTo",function(a){return{restrict:"A",transclude:!1,link:function(b,c,d){c.bind("click",function(){a(0,d.attGoTop)})}}}]).directive("attGoTo",["$anchorScroll","$location",function(a,b){return{restrict:"A",transclude:!1,link:function(c,d,e){d.bind("click",function(){var c=e.attGoTo;b.hash()!==c?b.hash(e.attGoTo):a()})}}}]).directive("freeStanding",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:!0,template:"<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n<div class='section-toggle'>\n<button class='section-toggle__button' ng-click='fsToggle()'>\n {{btnText}}<i style='font-size:0.875rem' ng-class='{\"icon-chevron-up\": showAccordion,\"icon-chevron-down\": !showAccordion, }'></i> \n</button>\n</div></div>",compile:function(a,b,c){var d=function(a,b,d){a.content="",c(a,function(a){b.find("span").append(a)}),a.showAccordion=!1,a.btnText=a.showAccordion?d.hideMsg:d.showMsg,a.fsToggle=function(){a.showAccordion=!a.showAccordion,a.btnText=a.showAccordion?d.hideMsg:d.showMsg}};return d}}}).directive("expanders",function(){return{restrict:"EA",replace:!0,transclude:!0,template:"<div ng-transclude></div>",controller:["$scope",function(a){var b=null;this.setScope=function(a){b=a},this.toggle=function(){return a.isOpen=b.isOpen=!b.isOpen,b.isOpen}}],link:function(a){a.isOpen=!1}}}).directive("expanderHeading",function(){return{require:"^expanders",restrict:"EA",replace:!0,transclude:!0,scope:!0,template:"<div style='padding:10px !important' ng-transclude></div>"}}).directive("expanderBody",function(){return{restrict:"EA",require:"^expanders",replace:!0,transclude:!0,scope:{},template:"<div collapse='!isOpen'><div ng-transclude></div></div>",link:function(a,b,c,d){a.isOpen=!1,d.setScope(a)}}}).directive("expanderToggle",function(){return{restrict:"EA",require:"^expanders",scope:{expandIcon:"@",collapseIcon:"@"},link:function(a,b,c,d){var e=!1,f=function(){a.expandIcon&&a.collapseIcon&&(e?(b.removeClass(a.expandIcon),b.addClass(a.collapseIcon)):(b.removeClass(a.collapseIcon),b.addClass(a.expandIcon)))};b.bind("keydown",function(b){13===b.keyCode&&a.toggleit()}),b.bind("click",function(){a.toggleit()}),a.toggleit=function(){e=d.toggle(),f(),a.$apply()},f()}}}).directive("collapse",["$transition",function(a){var b={open:{marginTop:null,marginBottom:null,paddingTop:null,paddingBottom:null,display:"block"},closed:{marginTop:0,marginBottom:0,paddingTop:0,paddingBottom:0,display:"none"}},c=function(a,c,d){c.removeClass("collapse"),c.css({height:d}),0===d?c.css(b.closed):c.css(b.open),c.addClass("collapse")};return{link:function(d,e,f){var g,h=!0;d.$watch(function(){return e[0].scrollHeight},function(){0===e[0].scrollHeight||g||(h?c(d,e,e[0].scrollHeight+"px"):c(d,e,"auto"))});var i,j=function(b){return i&&i.cancel(),i=a(e,b),i.then(function(){i=void 0},function(){i=void 0}),i},k=function(){d.postTransition=!0,h?(h=!1,g||c(d,e,"auto")):j(angular.extend({height:e[0].scrollHeight+"px"},b.open)).then(function(){g||c(d,e,"auto")}),g=!1},l=function(){g=!0,h?(h=!1,c(d,e,0)):(c(d,e,e[0].scrollHeight+"px"),j(angular.extend({height:0},b.closed)).then(function(){d.postTransition=!1}))};d.$watch(f.collapse,function(a){a?l():k()})}}}]).directive("attAccord",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{},controller:"AttAccordCtrl",templateUrl:"app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html"}}).controller("AttAccordCtrl",[function(){this.type="attAccord",this.headerCtrl,this.bodyCtrl;var a=!0;this.toggleBody=function(){a?this.expandBody():this.collapseBody(),a=!a},this.expandBody=function(){this.bodyCtrl.expand()},this.collapseBody=function(){this.bodyCtrl.collapse()}}]).controller("AttAccordHeaderCtrl",[function(){this.type="header"}]).directive("attAccordHeader",["keymap","events",function(a,b){return{restrict:"EA",transclude:!0,replace:!0,require:["^attAccord","attAccordHeader"],controller:"AttAccordHeaderCtrl",templateUrl:"app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",link:function(b,c,d,e){var f=e[0],g=e[1];f.headerCtrl=g;var h=c.children().eq(0);b.clickFunc=function(){f.toggleBody()};var i=function(c){var d=!0;switch(c.keyCode){case a.KEY.ENTER:c.preventDefault(),b.clickFunc(),b.$apply();break;default:d=!1}return c.stopPropagation(),d};angular.isUndefined(b.isOpen)&&(b.isOpen=!1),h.bind("keydown",i)}}}]).controller("AttAccordBodyCtrl",["$scope",function(a){this.type="body",this.expand=function(){a.expand()},this.collapse=function(){a.collapse()}}]).directive("attAccordBody",["$timeout","$height",function(a,b){return{restrict:"EA",transclude:!0,replace:!0,require:["^attAccord","attAccordBody"],controller:"AttAccordBodyCtrl",templateUrl:"app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",link:function(c,d,e,f){var g=f[0],h=f[1];g.bodyCtrl=h;var i;a(function(){i=d[0].offsetHeight,b(d,0,0,0)}),c.expand=function(){b(d,.05,i,1)},c.collapse=function(){b(d,.25,0,0)}}}}]),angular.module("att.abs.alert",[]).directive("attAlert",[function(){return{restrict:"EA",replace:!0,transclude:!0,scope:{alertType:"@type",showTop:"@topPos",showAlert:"="},templateUrl:"app/scripts/ng_js_att_tpls/alert/alert.html",link:function(a){"true"===a.showTop?a.cssStyle={top:"50px"}:a.cssStyle={top:"0px"},a.close=function(){a.showAlert=!1}}}}]),angular.module("att.abs.boardStrip",["att.abs.utilities"]).constant("BoardStripConfig",{maxVisibleBoards:4,boardsToScroll:1,boardLength:140,boardMargin:15}).directive("attBoard",[function(){return{restrict:"AE",replace:!0,transclude:!0,require:"^attBoardStrip",scope:{boardIndex:"=",boardLabel:"="},templateUrl:"app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",link:function(a,b,c,d){var e=d;a.getCurrentIndex=function(){return e.getCurrentIndex()},a.selectBoard=function(a){isNaN(a)||e.setCurrentIndex(a)},a.isInView=function(a){return e.isInView(a)}}}}]).directive("attBoardStrip",["BoardStripConfig","$timeout","$ieVersion",function(a,b,c){return{restrict:"AE",replace:!0,transclude:!0,scope:{currentIndex:"=selectedIndex",boardsMasterArray:"=",onAddBoard:"&?"},templateUrl:"app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",controller:function(b){if(angular.isDefined(b.boardsMasterArray)||(b.boardsMasterArray=[]),this.rectifyMaxVisibleBoards=function(){this.maxVisibleIndex>=b.boardsMasterArray.length&&(this.maxVisibleIndex=b.boardsMasterArray.length-1),this.maxVisibleIndex<0&&(this.maxVisibleIndex=0)},this.resetBoardStrip=function(){b.currentIndex=0,this.maxVisibleIndex=a.maxVisibleBoards-1,this.minVisibleIndex=0,this.rectifyMaxVisibleBoards()},b.currentIndex>0){var c=b.currentIndex;this.resetBoardStrip(),c>b.boardsMasterArray.length?b.currentIndex=b.boardsMasterArray.length-1:b.currentIndex=c}else this.resetBoardStrip();this.getCurrentIndex=function(){return b.currentIndex},this.setCurrentIndex=function(a){b.currentIndex=a},this.isInView=function(a){return a<=this.maxVisibleIndex&&a>=this.minVisibleIndex},this.getBoardsMasterArrayLength=function(){return b.boardsMasterArray.length}},link:function(d,e,f,g){var h,i=c(),j=1e3;i&&10>i&&(j=0);var k=function(b){return b*(a.boardLength+a.boardMargin)};e[0].querySelector(".board-viewport")&&angular.element(e[0].querySelector(".board-viewport")).css({width:k(a.maxVisibleBoards)+"px"});var l=function(b){return b*(a.boardLength+a.boardMargin)};e[0].querySelector(".boardstrip-container")&&(angular.element(e[0].querySelector(".boardstrip-container")).css({width:l(g.getBoardsMasterArrayLength())+"px"}),angular.element(e[0].querySelector(".boardstrip-container")).css({left:"0px"}));var m=function(){var b;return b=g.getBoardsMasterArrayLength()<=a.maxVisibleBoards?0:g.minVisibleIndex*(a.boardLength+a.boardMargin)*-1},n=function(a,b,c){for(var d=0;d<a.length;d++)angular.element(a[d]).attr("tabindex","-1");for(var d=b;c>=d;d++)angular.element(a[d]).attr("tabindex","0")};d.$watchCollection("boardsMasterArray",function(c,d){c!==d&&(c.length<d.length?(g.resetBoardStrip(),b(function(){var a=e[0].querySelectorAll("[att-board]");if(0!==a.length){var c=angular.element(e[0].querySelector(".boardstrip-container"))[0].style.left,d=m();c!==d+"px"?(angular.element(e[0].querySelector(".boardstrip-container")).css({left:d+"px"}),b.cancel(h),h=b(function(){a[0].focus()},j)):a[0].focus()}else e[0].querySelector("div.boardstrip-item--add").focus();angular.element(e[0].querySelector(".boardstrip-container")).css({width:l(g.getBoardsMasterArrayLength())+"px"})})):(g.maxVisibleIndex=g.getBoardsMasterArrayLength()-1,g.minVisibleIndex=Math.max(g.maxVisibleIndex-a.maxVisibleBoards+1,0),g.setCurrentIndex(g.maxVisibleIndex),b(function(){angular.element(e[0].querySelector(".boardstrip-container")).css({width:l(g.getBoardsMasterArrayLength())+"px"});var a=angular.element(e[0].querySelector(".boardstrip-container"))[0].style.left,c=m(),d=e[0].querySelectorAll("[att-board]");a!==c+"px"?(angular.element(e[0].querySelector(".boardstrip-container")).css({left:c+"px"}),b.cancel(h),h=b(function(){d[d.length-1].focus()},j)):d[d.length-1].focus(),n(d,g.minVisibleIndex,g.maxVisibleIndex)})))}),d.nextBoard=function(){g.maxVisibleIndex+=a.boardsToScroll,g.rectifyMaxVisibleBoards(),g.minVisibleIndex=g.maxVisibleIndex-(a.maxVisibleBoards-1),b.cancel(h),angular.element(e[0].querySelector(".boardstrip-container")).css({left:m()+"px"}),b(function(){var a=e[0].querySelectorAll("[att-board]");if(n(a,g.minVisibleIndex,g.maxVisibleIndex),!d.isNextBoard())try{a[a.length-1].focus()}catch(b){}},j)},d.prevBoard=function(){g.minVisibleIndex-=a.boardsToScroll,g.minVisibleIndex<0&&(g.minVisibleIndex=0),g.maxVisibleIndex=g.minVisibleIndex+a.maxVisibleBoards-1,g.rectifyMaxVisibleBoards(),b.cancel(h),angular.element(e[0].querySelector(".boardstrip-container")).css({left:m()+"px"}),b(function(){var a=e[0].querySelectorAll("[att-board]");if(n(a,g.minVisibleIndex,g.maxVisibleIndex),
-0===g.minVisibleIndex)try{e[0].querySelector("div.boardstrip-item--add").focus()}catch(b){}})},d.isPrevBoard=function(){return g.minVisibleIndex>0},d.isNextBoard=function(){return g.getBoardsMasterArrayLength()-1>g.maxVisibleIndex}}}}]).directive("attAddBoard",["BoardStripConfig","$parse","$timeout",function(a,b,c){return{restrict:"AE",replace:!0,require:"^attBoardStrip",scope:{onAddBoard:"&?"},templateUrl:"app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",link:function(a,c,d,e){a.addBoard=function(){d.onAddBoard&&(a.onAddBoard=b(a.onAddBoard),a.onAddBoard())}}}}]).directive("attBoardNavigation",["keymap","events",function(a,b){return{restrict:"AE",link:function(c,d){var e=a.KEY.LEFT,f=a.KEY.RIGHT;d.bind("keydown",function(a){switch(a.keyCode||(a.keyCode=a.which),a.keyCode){case f:if(b.preventDefault(a),b.stopPropagation(a),d[0].nextElementSibling&&parseInt(angular.element(d[0].nextElementSibling).attr("tabindex"))>=0)angular.element(d[0])[0].nextElementSibling.focus();else{var c=angular.element(d[0])[0];do{if(!c.nextSibling)break;c=c.nextSibling}while(c&&"LI"!==c.tagName);c.tagName&&"LI"===c.tagName&&parseInt(angular.element(c).attr("tabindex"))>=0&&c.focus()}break;case e:if(b.preventDefault(a),b.stopPropagation(a),d[0].previousElementSibling&&parseInt(angular.element(d[0].previousElementSibling).attr("tabindex"))>=0)angular.element(d[0])[0].previousElementSibling.focus();else{var g=angular.element(d[0])[0];do{if(!g.previousSibling)break;g=g.previousSibling}while(g&&"LI"!==g.tagName);g.tagName&&"LI"===g.tagName&&parseInt(angular.element(c).attr("tabindex"))>=0&&g.focus()}}})}}}]),angular.module("att.abs.breadCrumbs",[]).constant("classConstant",{defaultClass:"breadcrumbs__link",activeClass:"breadcrumbs__link--active"}).directive("attCrumb",["classConstant",function(a){return{restrict:"A",link:function(b,c,d){c.addClass(a.defaultClass),"active"===d.attCrumb&&c.addClass(a.activeClass),c.hasClass("last")||c.after('<i class="breadcrumbs__item"></i>')}}}]),angular.module("att.abs.buttons",["att.abs.position","att.abs.utilities"]).constant("btnConfig",{btnClass:"button",btnPrimaryClass:"button--primary",btnSecondaryClass:"button--secondary",btnDisabledClass:"button--inactive",btnSmallClass:"button--small"}).directive("attButton",["btnConfig",function(a){return{restrict:"A",link:function(b,c,d){c.addClass(a.btnClass),"small"===d.size&&c.addClass(a.btnSmallClass),d.$observe("btnType",function(b){"primary"===b?(c.addClass(a.btnPrimaryClass),c.removeClass(a.btnSecondaryClass),c.removeClass(a.btnDisabledClass),c.removeAttr("disabled")):"secondary"===b?(c.addClass(a.btnSecondaryClass),c.removeClass(a.btnPrimaryClass),c.removeClass(a.btnDisabledClass),c.removeAttr("disabled")):"disabled"===b&&(c.addClass(a.btnDisabledClass),c.removeClass(a.btnPrimaryClass),c.removeClass(a.btnSecondaryClass),c.attr("disabled","disabled"))})}}}]).directive("attButtonLoader",[function(){return{restrict:"A",replace:!1,scope:{size:"@"},template:"<div ng-class=\"{'button--loading': size === 'large','button--loading__small': size === 'small'}\"><i></i><i class=\"second__loader\"></i><i></i></div>",link:function(a,b){b.addClass("button button--inactive")}}}]).directive("attButtonHero",[function(){return{restrict:"A",replace:!1,transclude:!0,scope:{icon:"@"},template:"<div class=\"button--hero__inner\"><span ng-transclude></span> <i ng-class=\"{'icon-arrow-right': icon === 'arrow-right','icon-cart': icon === 'cart'}\"></i></div>",link:function(a,b){b.addClass("button button--hero"),b.attr("tabindex","0")}}}]).directive("attBtnDropdown",["$document","$timeout","$isElement","$documentBind","keymap","events",function(a,b,c,d,e,f){return{restrict:"EA",scope:{type:"@dropdowntype"},replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",link:function(g,h){g.isOpen=!1;var i=-1,j=[],k=void 0;b(function(){j=h.find("li"),k=h.find("button")[0]},10);var l=g.toggle=function(a){angular.isUndefined(a)||""===a?g.isOpen=!g.isOpen:g.isOpen=a},m=function(){i+1<j.length&&(i++,j[i].focus())},n=function(){i-1>=0&&(i--,j[i].focus())};h.bind("keydown",function(a){var b=a.keyCode;if(e.isAllowedKey(b)||e.isControl(a)||e.isFunctionKey(a))switch(b){case e.KEY.ENTER:i>0&&(k.focus(),g.$apply());break;case e.KEY.ESC:l(!1),i=-1,k.focus(),g.$apply();break;case e.KEY.DOWN:m(),g.$apply(),f.preventDefault(a),f.stopPropagation(a);break;case e.KEY.UP:n(),g.$apply(),f.preventDefault(a),f.stopPropagation(a)}else b===e.KEY.TAB&&(l(!1),i=-1,g.$apply())});var o=function(b){var d=c(angular.element(b.target),h,a);if(!d){l(!1),i=-1;for(var e=0;e<j.length;e++)angular.element(j[e]).removeClass("selected");k.focus(),g.$apply()}};d.click("isOpen",o,g)}}}]),angular.module("att.abs.checkbox",[]).constant("attCheckboxConfig",{activeClass:"att-checkbox--on",disabledClass:"att-checkbox--disabled"}).directive("checkboxLimit",function(){return{scope:{checkboxLimit:"=",selectLimit:"@?",maxSelected:"&?"},restrict:"A",require:"checkboxLimit",controller:["$scope",function(a){a.limit=!0,this.getMaxLimits=function(){return a.limit},this.setMaxLimits=function(b){a.limit=b},this.maxCheckboxSelected=function(){a.maxSelected()}}],link:function(a,b,c,d){a.$watch("checkboxLimit",function(){var b=0;for(var c in a.checkboxLimit)a.checkboxLimit.hasOwnProperty(c)&&a.checkboxLimit[c]&&(b+=1);b>=parseInt(a.selectLimit)?d.setMaxLimits(!1):d.setMaxLimits(!0)},!0)}}}).directive("attCheckbox",["$compile","attCheckboxConfig",function(a,b){return{scope:{},restrict:"A",require:["ngModel","^?checkboxLimit"],link:function(c,d,e,f){var g=f[0],h=f[1],i=a('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" aria-label="Checkbox" ng-click="updateModel($event)" class="att-checkbox"></div>')(c);d.css({display:"none"}),d.wrap(i),d.parent().append('<div class="att-checkbox__indicator"></div>'),d.parent().attr("title",e.title),d.parent().attr("aria-label",e.title),d.parent().attr("id",e.id),d.removeAttr("id"),g.$render=function(){var a=g.$modelValue?!0:!1;d.parent().toggleClass(b.activeClass,a),d.parent().attr("aria-checked",a)},c.updateModel=function(a){c.disabled||(g.$setViewValue(d.parent().hasClass(b.activeClass)?!1:!0),h&&!h.getMaxLimits()&&g.$modelValue?(h.maxCheckboxSelected(),g.$setViewValue(d.parent().hasClass(b.activeClass)?!0:!1)):g.$render()),a.preventDefault()},e.$observe("disabled",function(a){c.disabled=a||"disabled"===a||"true"===a,d.parent().toggleClass(b.disabledClass,c.disabled),d.parent().attr("tabindex",c.disabled?"-1":"0")})}}}]).directive("checkboxGroup",["$compile",function(a){return{scope:{checkboxGroup:"=",checkboxGroupValue:"=?"},restrict:"A",link:function(b,c,d){b.checkboxState="none",void 0===b.checkboxGroupValue&&(b.checkboxGroupValue="indeterminate"),c.css({display:"none"}),c.wrap(a('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(b)),c.parent().append('<div class="att-checkbox__indicator"></div>'),c.parent().attr("title",d.title),c.parent().attr("aria-label",d.title),b.$watch("checkboxState",function(a){"all"===a?(c.parent().addClass("att-checkbox--on"),c.parent().removeClass("att-checkbox--indeterminate"),c.parent().attr("aria-checked",!0)):"none"===a?(c.parent().removeClass("att-checkbox--on"),c.parent().removeClass("att-checkbox--indeterminate"),c.parent().attr("aria-checked",!1)):"indeterminate"===a&&(c.parent().removeClass("att-checkbox--on"),c.parent().addClass("att-checkbox--indeterminate"),c.parent().attr("aria-checked",!0))}),b.updateModel=function(a){if(c.parent().hasClass("att-checkbox--on")){c.parent().removeClass("att-checkbox--on");for(var d in b.checkboxGroup)b.checkboxGroup.hasOwnProperty(d)&&(b.checkboxGroup[d]=!1)}else{c.parent().addClass("att-checkbox--on");for(var e in b.checkboxGroup)b.checkboxGroup.hasOwnProperty(e)&&(b.checkboxGroup[e]=!0)}a.preventDefault()},b.$watch("checkboxGroupValue",function(a){if(a===!1){c.parent().removeClass("att-checkbox--on");for(var d in b.checkboxGroup)b.checkboxGroup.hasOwnProperty(d)&&(b.checkboxGroup[d]=!1)}else if(a===!0){c.parent().addClass("att-checkbox--on");for(var e in b.checkboxGroup)b.checkboxGroup.hasOwnProperty(e)&&(b.checkboxGroup[e]=!0)}}),b.$watch("checkboxGroup",function(){var a=0,c=0,d=0;for(var e in b.checkboxGroup)b.checkboxGroup.hasOwnProperty(e)&&(d+=1,b.checkboxGroup[e]?a+=1:b.checkboxGroup[e]||(c+=1));d===a?(b.checkboxState="all",b.checkboxGroupValue=!0):d===c?(b.checkboxState="none",b.checkboxGroupValue=!1):(b.checkboxState="indeterminate",b.checkboxGroupValue="indeterminate")},!0)}}}]),angular.module("att.abs.colorselector",[]).directive("colorSelectorWrapper",[function(){return{scope:{selected:"=",iconColor:"@"},restrict:"AE",transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/colorselector/colorselector.html",link:function(a){a.applycolor={"background-color":a.iconColor},a.selectedcolor=function(b){a.selected=b}}}}]).directive("colorSelector",["$compile",function(a){return{restrict:"A",scope:{colorSelector:"@",ngModel:"="},link:function(b,c,d){c.removeAttr("color-selector");var e=d.title,f=angular.element('<color-selector-wrapper selected="ngModel" title="'+e+'" icon-color="{{colorSelector}}">'+c.prop("outerHTML")+"</color-selector-wrapper>"),g=a(f)(b);c.replaceWith(g)}}}]),angular.module("att.abs.datepicker",["att.abs.position","att.abs.utilities"]).constant("datepickerConfig",{dateFormat:"MM/dd/yyyy",dayFormat:"d",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEEE",dayTitleFormat:"MMMM yyyy",disableWeekend:!1,disableSunday:!1,startingDay:0,minDate:null,maxDate:null,mode:0,dateFilter:{defaultText:"Select from list"},datepickerEvalAttributes:["dateFormat","dayFormat","monthFormat","yearFormat","dayHeaderFormat","dayTitleFormat","disableWeekend","disableSunday","startingDay","mode"],datepickerWatchAttributes:["min","max"]}).factory("datepickerService",["datepickerConfig","dateFilter",function(a,b){var c=function(b,c){if(angular.isDefined(b)&&null!==b&&angular.isDefined(c)&&null!==c){var d=a.datepickerEvalAttributes.concat(a.datepickerWatchAttributes);for(var e in b){var f=b[e];-1!==d.indexOf(e)&&angular.isDefined(f)&&c.attr(e.toSnakeCase(),e)}}},d=function(b,c){if(angular.isDefined(b)&&null!==b&&angular.isDefined(c)&&null!==c){var d=function(a,b){c[a]=c.$parent.$eval(b)},e=function(a,b){c.$parent.$watch(b,function(b){c[a]=b}),c.$watch(a,function(a){c.$parent[b]=a})},f=a.datepickerEvalAttributes,g=a.datepickerWatchAttributes;for(var h in b){var i=b[h];-1!==f.indexOf(h)&&angular.isDefined(i)?d(h,i):-1!==g.indexOf(h)&&angular.isDefined(i)&&e(h,i)}}},e=function(a,c){if(a&&c){var d;-1!==c.indexOf("/")?d="/":-1!==c.indexOf("-")?d="-":-1!==c.indexOf(".")&&(d=".");var e=a.split(d),f=c.split(d);if(e.length!==f.length)return!1;for(var g=0;g<e.length;g++)e[g]=e[g].lPad(f[g].length,"0");var h=e.join(d),i=b(new Date(h),c);return h===i}};return{setAttributes:c,bindScope:d,validateDateString:e}}]).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(a,b,c,d){function e(b,c){return angular.isDefined(b)?a.$parent.$eval(b):c}function f(a,b){return new Date(a,b,0).getDate()}function g(a,b){for(var c=[],d=a,e=0;b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(b){return b&&angular.isDate(a.currentDate)&&0===u(b,a.currentDate)?!0:!1}function i(b){return b&&angular.isDate(a.fromDate)&&0===u(b,a.fromDate)?!0:!1}function j(b){return b&&angular.isDate(a.fromDate)&&angular.isDate(a.currentDate)&&0===u(b,a.currentDate)?!0:!1}function k(b){return b&&angular.isDate(a.fromDate)&&angular.isDate(a.currentDate)&&u(b,a.fromDate)>=0&&u(b,a.currentDate)<=0?!0:!1}function l(a){return"Saturday"===c(a,s.dayHeader)||"Sunday"===c(a,s.dayHeader)?!0:!1}function m(b){return 0===u(b,a.resetTime(new Date))?!0:!1}function n(b){return b&&angular.isDate(a.focusedDate)&&0===u(b,a.focusedDate)?!0:!1}function o(b,c){return a.minDate&&a.minDate.getTime()>=b.getTime()&&a.minDate.getTime()<=c.getTime()}function p(b,c){return a.maxDate&&a.maxDate.getTime()>=b.getTime()&&a.maxDate.getTime()<=c.getTime()}function q(a){if(a){var b={pre:a.substr(0,3),post:a};return b}}function r(a){return{date:a.date,label:c(a.date,a.formatDay),header:c(a.date,a.formatHeader),focused:!!a.isFocused,selected:!!a.isSelected,from:!!a.isFromDate,to:!!a.isToDate,dateRange:!!a.isDateRange,oldMonth:!!a.oldMonth,nextMonth:!!a.newMonth,disabled:!!a.isDisabled,today:!!a.isToday,weekend:!!a.isWeakend}}var s={date:e(b.dateFormat,d.dateFormat),day:e(b.dayFormat,d.dayFormat),month:e(b.monthFormat,d.monthFormat),year:e(b.yearFormat,d.yearFormat),dayHeader:e(b.dayHeaderFormat,d.dayHeaderFormat),dayTitle:e(b.dayTitleFormat,d.dayTitleFormat),disableWeekend:e(b.disableWeekend,d.disableWeekend),disableSunday:e(b.disableSunday,d.disableSunday)},t=e(b.startingDay,d.startingDay);a.mode=e(b.mode,d.mode),a.minDate=d.minDate?a.resetTime(d.minDate):null,a.maxDate=d.maxDate?a.resetTime(d.maxDate):null;var u=this.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},v=this.isDisabled=function(b){return s.disableWeekend!==!0||"Saturday"!==c(b,s.dayHeader)&&"Sunday"!==c(b,s.dayHeader)?s.disableSunday===!0&&"Sunday"===c(b,s.dayHeader)?!0:a.minDate&&u(b,a.minDate)<0||a.maxDate&&u(b,a.maxDate)>0:!0};this.modes=[{name:"day",getVisibleDates:function(b,d){var e=b.getFullYear(),u=b.getMonth(),w=new Date(e,u,1),x=new Date(e,u+1,0),y=t-w.getDay(),z=y>0?7-y:-y,A=new Date(w),B=0;z>0&&(A.setDate(-z+1),B+=z),B+=f(e,u+1),B+=(7-B%7)%7;for(var C=g(A,B),D=[],E=0;B>E;E++){var F=new Date(C[E]);C[E]=r({date:F,formatDay:s.day,formatHeader:s.dayHeader,isFocused:n(F),isSelected:h(F),isFromDate:i(F),isToDate:j(F),isDateRange:k(F),oldMonth:new Date(F.getFullYear(),F.getMonth(),1,0,0,0).getTime()<new Date(e,u,1,0,0,0).getTime(),newMonth:new Date(F.getFullYear(),F.getMonth(),1,0,0,0).getTime()>new Date(e,u,1,0,0,0).getTime(),isDisabled:v(F),isToday:m(F),isWeakend:l(F)})}for(var G=0;7>G;G++)D[G]=q(c(C[G].date,s.dayHeader));return"top"===d?(a.disablePrevTop=o(w,x),a.disableNextTop=p(w,x)):"bottom"===d?(a.disablePrevBottom=o(w,x),a.disableNextBottom=p(w,x)):(a.disablePrevTop=a.disablePrevBottom=o(w,x),a.disableNextTop=a.disableNextBottom=p(w,x)),a.disablePrev=a.disablePrevTop||a.disablePrevBottom,a.disableNext=a.disableNextTop||a.disableNextBottom,{objects:C,title:c(b,s.dayTitle),labels:D}},split:7,step:{months:1}},{name:"month",getVisibleDates:function(a){for(var b=[],d=[],e=a.getFullYear(),f=0;12>f;f++){var g=new Date(e,f,1);b[f]=r({date:g,formatDay:s.month,formatHeader:s.month,isFocused:n(g),isSelected:h(g),isFromDate:i(g),isToDate:j(g),isDateRange:k(g),oldMonth:!1,newMonth:!1,isDisabled:v(g),isToday:m(g),isWeakend:!1})}return{objects:b,title:c(a,s.year),labels:d}},split:3,step:{years:1}}]}]).directive("datepicker",["$timeout",function(a){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/datepicker/datepicker.html",scope:{currentDate:"=?current",fromDate:"=?from"},require:"datepicker",controller:"DatepickerController",link:function(b,c,d,e){function f(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c}function g(a){if(angular.isDate(a)&&!isNaN(a)?h=new Date(a):h||(h=new Date),h){var c;1===b.mode?(h=new Date,c=k(angular.copy(h),-1)):c=angular.copy(h);var d=i.modes[b.mode],e=d.getVisibleDates(c,"top");b.currentRows=f(e.objects,d.split),b.currentTitle=e.title,b.labels=e.labels||[];var g=d.getVisibleDates(k(angular.copy(c),1),"bottom");b.nextRows=f(g.objects,d.split),b.nextTitle=g.title}}var h,i=e,j=!1;b.focusedDate,b.resetTime=function(a){var c;return isNaN(new Date(a))?null:(c=new Date(a),c=1===b.mode?new Date(c.getFullYear(),c.getMonth()):new Date(c.getFullYear(),c.getMonth(),c.getDate()))},d.min&&b.$parent.$watch(d.min,function(a){b.minDate=a?b.resetTime(a):null,g()}),d.max&&b.$parent.$watch(d.max,function(a){b.maxDate=a?b.resetTime(a):null,g()});var k=function(a,c){var d=i.modes[b.mode].step;return a.setDate(1),a.setMonth(a.getMonth()+c*(d.months||0)),a.setFullYear(a.getFullYear()+c*(d.years||0)),a},l=function(a){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate());b.currentDate=c},m=function(a){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate());b.fromDate=c};b.select=function(a){j=!0,d.from?angular.isDate(b.fromDate)&&angular.isDate(b.currentDate)||(angular.isDate(b.fromDate)?l(a):angular.isDate(b.fromDate)||m(a)):l(a),b.focusedDate=a};var n=function(c,d){m(d),a(function(){j=!0,b.focusedDate=d,l(c)})};b.move=function(a){h=k(angular.copy(h),a),g()},b.$watch("currentDate",function(a){return angular.isDate(a)&&!isNaN(a)&&i.isDisabled(a)?void(b.currentDate=null):d.from&&!isNaN(a)&&!isNaN(b.fromDate)&&i.compare(a,b.fromDate)<0?void n(b.fromDate,a):(j?(g(),j=!1):angular.isDefined(a)&&null!==a?g(a):g(),void(b.focusedDate=void 0))}),b.$watch("fromDate",function(a){if(angular.isDate(a)&&!isNaN(a)&&i.isDisabled(a))return void(b.fromDate=null);if(d.from){if(!isNaN(b.currentDate)&&!isNaN(a)&&i.compare(b.currentDate,a)<0)return void n(a,b.currentDate);j?(g(),j=!1):angular.isDefined(a)&&null!==a?g(a):g()}b.focusedDate=void 0})}}}]).directive("datepickerPopup",["$document","datepickerService","$isElement","$documentBind",function(a,b,c,d){var e=function(e,f,g){b.bindScope(g,e),e.isOpen=!1;var h=e.toggle=function(a){a===!0||a===!1?e.isOpen=a:e.isOpen=!e.isOpen};e.$watch("current",function(){h(!1)});var i=function(b){var d=c(angular.element(b.target),f,a);d||(h(!1),e.$apply())};d.click("isOpen",i,e)};return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",scope:{current:"=current"},compile:function(a,c){var d=a.find("span").eq(1);return d.attr("current","current"),b.setAttributes(c,d),e}}}]).directive("attDatepicker",["$log",function(a){return{restrict:"A",require:"ngModel",scope:{},controller:["$scope","$element","$attrs","$compile","datepickerConfig","datepickerService",function(a,b,c,d,e,f){var g=angular.isDefined(c.dateFormat)?a.$parent.$eval(c.dateFormat):e.dateFormat,h='<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \''+g+"'}}</div>";b.removeAttr("att-datepicker"),b.removeAttr("ng-model"),b.attr("ng-model","$parent.current"),b.attr("aria-describedby","datepicker"),b.attr("format-date",g),b.attr("att-input-deny","[^0-9/-]"),b.attr("maxlength",10);var i=angular.element("<div></div>");i.attr("datepicker-popup",""),i.attr("current","current"),f.setAttributes(c,i),f.bindScope(c,a),i.html(""),i.append(b.prop("outerHTML")),null===navigator.userAgent.match(/MSIE 8/)&&i.append(h);var j=i.prop("outerHTML");j=d(j)(a),b.replaceWith(j)}],link:function(b,c,d,e){return e?(b.$watch("current",function(a){e.$setViewValue(a)}),void(e.$render=function(){b.current=e.$viewValue})):void a.error("ng-model is required.")}}}]).directive("formatDate",["dateFilter","datepickerService",function(a,b){return{restrict:"A",require:"ngModel",link:function(c,d,e,f){var g="";e.$observe("formatDate",function(a){g=a});var h=function(b){return b?(f.$setValidity("invalidDate",!0),a(b,g)):(f.$setValidity("invalidDate",!1),d.val())},i=function(a){return b.validateDateString(a,g)?(f.$setValidity("invalidDate",!0),new Date(a)):(f.$setValidity("invalidDate",!1),null)};f.$formatters.unshift(h),f.$parsers.unshift(i)}}}]).directive("attDateFilter",["$document","dateFilter","datepickerConfig","datepickerService","$isElement","$documentBind",function(a,b,c,d,e,f){var g=function(g,h,i,j){d.bindScope(i,g),g.selectedOption=c.dateFilter.defaultText,g.showDropdownList=!1,g.showCalendar=!1,g.applyButtonType="disabled",g.currentSelection="";var k=angular.isDefined(i.dateFormat)?g.$parent.$eval(i.dateFormat):c.dateFormat,l=!1,m=function(a){if(!l){var c=k.toUpperCase(),d=k.toUpperCase();isNaN(new Date(g.fromDate))||(c=b(g.fromDate,k)),isNaN(new Date(g.currentDate))||(d=b(g.currentDate,k)),"Custom Single Date"===a?(j.$setValidity("invalidDate",!0),g.maxLength=10,g.selectedOption=d):"Custom Range"===a&&(j.$setValidity("invalidDate",!0),j.$setValidity("invalidDateRange",!0),g.maxLength=21,g.selectedOption=c+"-"+d)}},n=g.clear=function(a){g.fromDate=void 0,g.currentDate=void 0,g.applyButtonType="disabled",a||(j.$setValidity("invalidDate",!0),j.$setValidity("invalidDateRange",!0),m(g.currentSelection))},o=function(){g.showCalendar=!0},p=function(){g.showCalendar=!1,"Custom Single Date"!==g.currentSelection&&"Custom Range"!==g.currentSelection&&n(!0)},q=g.showDropdown=function(a){a===!0||a===!1?g.showDropdownList=a:g.showDropdownList=!g.showDropdownList,g.showDropdownList?("Custom Single Date"===g.currentSelection||"Custom Range"===g.currentSelection)&&o():(g.focusInputButton=!0,p())};g.resetTime=function(a){var b;return isNaN(new Date(a))?null:(b=new Date(a),new Date(b.getFullYear(),b.getMonth(),b.getDate()))},g.getDropdownText=function(){l=!0;var a=g.selectedOption;if("Custom Single Date"===g.currentSelection)!isNaN(new Date(a))&&d.validateDateString(a,k)?(j.$setValidity("invalidDate",!0),g.fromDate=void 0,g.currentDate=new Date(a)):(j.$setValidity("invalidDate",!1),n(!0));else if("Custom Range"===g.currentSelection)if(-1===a.indexOf("-")||2!==a.split("-").length&&6!==a.split("-").length)j.$setValidity("invalidDateRange",!1),n(!0);else{j.$setValidity("invalidDateRange",!0);var b=a.split("-");if(2===b.length)b[0]=b[0].trim(),b[1]=b[1].trim();else if(6===b.length){var c=b[0].trim()+"-"+b[1].trim()+"-"+b[2].trim(),e=b[3].trim()+"-"+b[4].trim()+"-"+b[5].trim();b[0]=c,b[1]=e}if(!isNaN(new Date(b[0]))&&!isNaN(new Date(b[1]))&&d.validateDateString(b[0],k)&&d.validateDateString(b[1],k)){j.$setValidity("invalidDate",!0);var f=new Date(b[0]),h=new Date(b[1]);f.getTime()<h.getTime()?(j.$setValidity("invalidDateRange",!0),g.fromDate=f,g.currentDate=h):(j.$setValidity("invalidDateRange",!1),n(!0))}else j.$setValidity("invalidDate",!1),n(!0)}},g.untrackInputChange=function(){l=!1},g.selectAdvancedOption=function(a,b){g.currentSelection=a,b||(n(),o()),g.$watch("currentDate",function(b){isNaN(new Date(b))||(g.applyButtonType="primary",m(a),l||(g.focusApplyButton=!0))}),g.$watch("fromDate",function(b){isNaN(new Date(b))||m(a)}),"Custom Single Date"===a?g.focusSingleDateCalendar=!0:"Custom Range"===a&&(g.focusRangeCalendar=!0)},g.resetFocus=function(){g.focusSingleDateCalendar=!1,g.focusRangeCalendar=!1,g.focusApplyButton=!1},g.apply=function(){g.dateRange.selection=g.selectedOption,isNaN(new Date(g.fromDate))?(g.from=void 0,g.dateRange.from=void 0):(g.from=g.fromDate,g.dateRange.from=g.fromDate),isNaN(new Date(g.currentDate))?(g.current=void 0,g.dateRange.current=void 0):(g.current=g.currentDate,g.dateRange.current=g.currentDate),q()},g.$watchCollection(function(){return g.dateRange},function(a){if(j){var b=angular.copy(a);j.$setViewValue(b)}}),j.$render=function(){if(j.$viewValue){var a=j.$viewValue;g.selectedOption=a.selection,g.fromDate=a.from,g.currentDate=a.current,void 0!==g.fromDate&&void 0!==g.currentDate?(g.selectAdvancedOption("Custom Range",!0),g.dateRange.from=g.fromDate,g.dateRange.current=g.currentDate):void 0!==g.currentDate&&(g.selectAdvancedOption("Custom Single Date",!0),g.dateRange.from=void 0,g.dateRange.current=g.currentDate)}},g.cancel=function(){g.currentSelection="",g.selectedOption=c.dateFilter.defaultText,q()};var r=function(b){var c=e(angular.element(b.target),h,a);c||(g.cancel(),g.$apply())};f.click("showDropdownList",r,g)};return{restrict:"EA",scope:{from:"=?from",current:"=?current"},replace:!0,require:"?ngModel",transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",controller:["$scope","$element","$attrs",function(a){a.dateRange={selection:void 0,from:void 0,current:void 0},this.selectOption=function(b,c,d){a.selectedOption=d,a.currentSelection=d,a.dateRange.selection=d,a.dateRange.current=a.resetTime(c),a.dateRange.from=a.resetTime(b),a.showDropdown()},a.checkCurrentSelection=this.checkCurrentSelection=function(b){return b===a.currentSelection?!0:!1}}],compile:function(a,b){var c=a.find("span").eq(4),e=a.find("span").eq(5);return e.attr("from","fromDate"),c.attr("current","currentDate"),e.attr("current","currentDate"),d.setAttributes(b,c),d.setAttributes(b,e),g}}}]).directive("attDateFilterList",function(){return{restrict:"EA",scope:{fromDate:"=fromDate",toDate:"=toDate",caption:"=caption",disabled:"=disabled"},require:"^attDateFilter",transclude:!0,replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",link:function(a,b,c,d){a.selectOption=function(a,b,c){d.selectOption(a,b,c)},a.checkCurrentSelection=d.checkCurrentSelection}}}),angular.module("att.abs.devNotes",[]).directive("attDevNotes",function(){return{restrict:"EA",transclude:!0,scope:{},controller:function(a){var b=a.panes=[];a.select=function(a){angular.forEach(b,function(a){a.selected=!1}),a.selected=!0},this.addPane=function(c){0===b.length&&a.select(c),b.push(c)}},template:'<div><ul class="tabs"><li ng-repeat="pane in panes" ng-class="{active:pane.selected}"><a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a></li></ul><div ng-transclude></div></div>',replace:!0}}).directive("pane",function(){return{require:"^attDevNotes",restrict:"EA",transclude:!0,scope:{title:"@"},link:function(a,b,c,d){d.addPane(a)},template:'<div class="tab-pane" ng-class="{active: selected}">'+"<pre ng-class=\"{'language-markup':title=='HTML','language-javascript':title=='JavaScript','language-json':title=='JSON'}\" class=\" line-numbers\"><code ng-transclude></code></pre></div>",replace:!0}}),angular.module("att.abs.dividerLines",[]).directive("attDividerLines",[function(){return{scope:{attDividerLines:"@"},restrict:"A",replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",link:function(a,b,c){a.lightContainer=c.attDividerLines}}}]),angular.module("att.abs.dragdrop",[]).directive("attFileDrop",["$parse",function(a){return{restrict:"A",scope:{fileModel:"=",onDrop:"&",attFileDrop:"&"},controller:["$scope","$attrs",function(a,b){""!==b.attFileDrop&&(a.onDrop=a.attFileDrop),this.onDrop=a.onDrop}],link:function(b,c){c.addClass("dragdrop"),c.bind("dragover",function(a){return a.originalEvent&&(a.dataTransfer=a.originalEvent.dataTransfer),a.dataTransfer.dropEffect="move",a.preventDefault&&a.preventDefault(),c.addClass("dragdrop-over"),!1}),c.bind("dragenter",function(a){return a.preventDefault&&a.preventDefault(),c.addClass("dragdrop-over"),!1}),c.bind("dragleave",function(){return c.removeClass("dragdrop-over"),!1}),c.bind("drop",function(d){return d.preventDefault&&d.preventDefault(),d.stopPropagation&&d.stopPropagation(),d.originalEvent&&(d.dataTransfer=d.originalEvent.dataTransfer),c.removeClass("dragdrop-over"),d.dataTransfer.files&&d.dataTransfer.files.length>0&&(b.fileModel=d.dataTransfer.files[0],b.$apply(),"function"==typeof b.onDrop&&(b.onDrop=a(b.onDrop),b.onDrop())),!1})}}}]).directive("attFileLink",[function(){return{restrict:"EA",require:"^?attFileDrop",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",scope:{fileModel:"=?",onFileSelect:"&",attFileLink:"&"},controller:["$scope","$parse",function(a,b){this.setFileModel=function(b){a.takeFileModelFromParent?(a.$parent.fileModel=b,a.$parent.$apply()):(a.fileModel=b,a.$apply())},this.callbackFunction=function(){"function"==typeof a.onFileSelect&&(a.onFileSelect=b(a.onFileSelect),a.onFileSelect())}}],link:function(a,b,c,d){a.takeFileModelFromParent=!1,!c.fileModel&&d&&(a.takeFileModelFromParent=!0),""!==c.attFileLink?a.onFileSelect=a.attFileLink:!c.onFileSelect&&d&&(a.onFileSelect=d.onDrop)}}}]).directive("attFileChange",["$log","$rootScope",function(a,b){return{restrict:"A",require:"^attFileLink",link:function(c,d,e,f){function g(c){if(c.target.files&&c.target.files.length>0)f.setFileModel(c.target.files[0]),f.callbackFunction();else{var d=c.target.value;try{var e=new ActiveXObject("Scripting.FileSystemObject");f.setFileModel(e.getFile(d)),f.callbackFunction()}catch(c){var g="Error: Please follow the guidelines of Drag and Drop component on Sandbox demo page.";a.error(g),b.$broadcast("att-file-link-failure",g)}}}d.bind("change",g)}}}]),angular.module("att.abs.drawer",["att.abs.utilities"]).directive("attDrawer",["$document","$timeout","DOMHelper",function(a,b,c){return{restrict:"EA",replace:!0,transclude:!0,scope:{drawerOpen:"=?",drawerAutoClose:"&?"},template:'<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',link:function(a,d,e){function f(b,c){b&&0!==b.style.width&&0!==b.style.height&&(m.style.display="none","right"===c.side||"left"===c.side?b.style.width="0px":("top"===c.side||"bottom"===c.side)&&(b.style.height="0px")),a.drawerOpen=!1,angular.isDefined(k)&&null!=k&&k.focus()}function g(a,c){k=document.activeElement,0!==a.style.width&&0!==a.style.height&&("right"===c.side||"left"===c.side?a.style.width=c.size:("top"===c.side||"bottom"===c.side)&&(a.style.height=c.size),b(function(){m.style.display="block",angular.isDefined(j)&&null!=j&&j.focus()},1e3*c.speed))}function h(a){var b={};return a&&"[object Function]"===b.toString.call(a)}var i={},j=void 0,k=void 0;i.side=e.drawerSlide||"top",i.speed=e.drawerSpeed||"0.25",i.size=e.drawerSize||"300px",i.zindex=e.drawerZindex||1e3,i.className=e.drawerClass||"att-drawer";var l=d.eq(0).children()[0],m=angular.element(l).children()[0];l.className=i.className,l.style.transitionDuration=i.speed+"s",l.style.webkitTransitionDuration=i.speed+"s",l.style.zIndex=i.zindex,l.style.position="fixed",l.style.width=0,l.style.height=0,l.style.transitionProperty="width, height","right"===i.side||"left"===i.side?(l.style.height=e.drawerCustomHeight||"100%",l.style.top=e.drawerCustomTop||"0px",l.style.bottom=e.drawerCustomBottom||"0px",l.style.right=e.drawerCustomRight||"0px"):("top"===i.side||"bottom"===i.side)&&(l.style.width=e.drawerCustomWidth||"100%",l.style.left=e.drawerCustomLeft||"0px",l.style.top=e.drawerCustomTop||"0px",l.style.right=e.drawerCustomRight||"0px"),b(function(){j=c.firstTabableElement(d[0])},10,!1),e.drawerSize&&a.$watch(function(){return e.drawerSize},function(b){i.size=b,a.drawerOpen&&g(l,i)}),a.$watch("drawerOpen",function(a){a?g(l,i):f(l,i)}),a.drawerAutoClose&&(a.$on("$locationChangeStart",function(){f(l,i),h(a.drawerAutoClose)&&a.drawerAutoClose()}),a.$on("$stateChangeStart",function(){f(l,i),h(a.drawerAutoClose)&&a.drawerAutoClose()}))}}}]),angular.module("att.abs.message",[]).directive("attMessages",[function(){return{restrict:"EA",scope:{messageType:"=?"},controller:["$scope","$element","$attrs",function(a,b,c){a.messageScope=[],this.registerScope=function(b){a.messageScope.push(b)},a.$parent.$watchCollection(c["for"],function(b){for(var c in b){if(b[c]){a.error=c;break}a.error=null}for(var d=0;d<a.messageScope.length;d++)a.messageScope[d].when===a.error?(a.messageScope[d].show(),a.setMessageType(a.messageScope[d].type)):a.messageScope[d].hide();null===a.error&&a.setMessageType(null)}),a.setMessageType=this.setMessageType=function(b){c.messageType&&(a.messageType=b)}}]}}]).directive("attMessage",[function(){return{restrict:"EA",scope:{},require:"^attMessages",link:function(a,b,c,d){d.registerScope(a),a.when=c.when||c.attMessage,a.type=c.type,a.show=function(){b.css({display:"block"})},a.hide=function(){b.css({display:"none"})},a.hide()}}}]),angular.module("att.abs.formField",["att.abs.message","att.abs.utilities"]).directive("attFormField",[function(){return{priority:101,restrict:"A",controller:function(){},link:function(a,b,c){b.wrap('<div class="form-field"></div>'),b.parent().append('<label class="form-field__label">'+c.placeholder||c.attFormField+"</label>"),b.wrap('<div class="form-field-input-container"></div>'),b.bind("keyup",function(){""!==this.value?b.parent().parent().find("label").addClass("form-field__label--show").removeClass("form-field__label--hide"):b.parent().parent().find("label").addClass("form-field__label--hide").removeClass("form-field__label--show")}),b.bind("blur",function(){
-""===this.value&&b.parent().parent().find("label").removeClass("form-field__label--hide")})}}}]).directive("attFormFieldValidation",["$compile","$log",function(a,b){return{priority:102,scope:{},restrict:"A",require:["?ngModel","?attFormField"],link:function(c,d,e,f){var g=f[0],h=f[1];return c.valid="",g?h?(d.parent().append(a(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(c)),d.parent().append(a(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(c)),c.$watch("valid",function(a){a?d.parent().parent().addClass("success"):a===!1?d.parent().parent().addClass("error"):d.parent().parent().removeClass("success").removeClass("error")}),void d.bind("keyup",function(){g.$valid?c.valid=!0:g.$invalid?c.valid=!1:c.valid="",c.$apply()})):void b.error("att-form-field-validation :: att-form-field directive is required."):void b.error("att-form-field-validation :: ng-model directive is required.")}}}]).directive("attFormFieldValidationAlert",["$timeout",function(a){return{scope:{messageType:"=?"},restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",link:function(b,c,d,e){b.showLabel=!1,b.hideLabel=!1,b.errorMessage=!1,b.warningMessage=!1;var f=function(){var a=b.messageType;"error"===a?(b.errorMessage=!0,b.warningMessage=!1):"warning"===a?(b.errorMessage=!1,b.warningMessage=!0):(b.errorMessage=!1,b.warningMessage=!1)},g=-1!==navigator.userAgent.toLowerCase().indexOf("msie 8.0");c.find("label").text(c.find("input").attr("placeholder")),c.find("input").bind("keyup",function(){""!==this.value?(b.showLabel=!0,b.hideLabel=!1,g&&c.find("label").css({top:"-20px"})):(b.showLabel=!1,b.hideLabel=!0,g&&c.find("label").css({top:"0px"})),f(),b.$apply()}),c.find("input").bind("blur",function(){""===this.value&&(b.showLabel=!1,b.hideLabel=!1),b.$apply()}),a(function(){f()},100)}}}]).constant("CoreFormsUiConfig",{phoneMask:"(___) ___-____"}).directive("attPhoneMask",["$parse","CoreFormsUiConfig",function(a,b){return{require:"ngModel",scope:{ngModel:"="},link:function(a,c,d,e){var f=navigator.userAgent.toLowerCase(),g=f.indexOf("android")>-1,h=(-1!==f.indexOf("msie 8.0"),""),i=!1;h=g?"__________":b.phoneMask,c.attr("maxlength",h.length);var j=function(a){var b=!1;return a&&(b=10===a.length),e.$setValidity("invalidPhoneNumber",i),e.$setValidity("mask",b),b},k=function(){var a,b=e.$modelValue;if(b.length){var c,d,f,g,i;for(g=[],f=h.split(""),i=f.length,c=b.substring(0,h.length),d=b.replace(/[^0-9]/g,"").split(""),a=0;i>a&&(g.push("_"===f[a]?d.shift():f[a]),0!==d.length);a++);return b=g.join(""),"("===b&&(b=""),e.$setViewValue(b),e.$render(),b}},l=function(b){b.which&&((b.which<48||b.which>57)&&(b.which<96||b.which>105)?8===b.which||9===b.which||46===b.which||13===b.which||37===b.which||39===b.which||b.ctrlKey===!0||"118"===b.which&&"86"===b.which||b.ctrlKey===!0||"99"===b.which&&"67"===b.which||b.ctrlKey===!0||"120"===b.which&&"88"===b.which||(b.preventDefault?b.preventDefault():b.returnValue=!1,c.attr("aria-label","Only numbers are allowed"),i=!1):(c.removeAttr("aria-label"),i=!0)),a.$apply()},m=function(a){var b=/^[A-Za-z]+$/,c=/^[0-9]+$/;a.match(b)&&(i=!1),a.match(c)&&(i=!0);var d="";return a&&a.length>0&&(d=a.replace(/[^0-9]/g,"")),j(d),d},n=function(a){var b="";return j(a),a&&(b=k()),b};e.$parsers.push(m),e.$formatters.push(n),c.bind("keyup",k),c.bind("keydown",l),c.bind("input",function(a){k(a),l(a)})}}}]).constant("validationTypeInt",{validationNum:{number:"1",text:"2",email:"3"}}).directive("attFormFieldPrv",["keyMapAc","validationTypeInt",function(a,b){return{priority:101,restrict:"AE",controller:["$scope",function(c){this.showHideErrorMessage=function(a){null!=c.$$prevSibling&&angular.isDefined(c.$$prevSibling)&&angular.isDefined(c.$$prevSibling.hideErrorMsg)&&(c.$$prevSibling.hideErrorMsg=a,c.$apply())},this.findAllowedCharactor=function(b){var d=a.keys;if(angular.isDefined(c.allowedSpecialCharacters)&&angular.isDefined(c.allowedSpecialCharacters.length)&&c.allowedSpecialCharacters.length>0){for(var e=c.allowedSpecialCharacters,f=!1,g=0;g<e.length;g++)if(e[g]===d[b]){f=!0;break}return f}return!1},this.validateText=function(a,b,c,d){if(angular.isDefined(b)&&0===b.length){var e=/^[a-zA-Z0-9]*$/i;return e.test(c)}var f="^[a-zA-Z0-9"+d+"]*$",g=new RegExp(f,"i");return g.test(c)},this.validateNumber=function(a,b,c,d){if(angular.isDefined(b)&&0===b.length){var e=/^[0-9\.]+$/;return e.test(c)}var f="^[0-9."+d+"]*$",g=new RegExp(f,"i");return g.test(c)},this.validateEmail=function(a,b,c,d){if(angular.isDefined(b)&&0===b.length){var e=/(([a-zA-Z0-9\-?\.?]+)@(([a-zA-Z0-9\-_]+\.)+)([a-z]{2,3}))+$/;return e.test(c)}var f="(([a-z"+d+"A-Z0-9-?.?]+)@(([a-z"+d+"A-Z0-9-_]+.)+)(["+d+"a-z]{2,3}))+$",g=new RegExp(f,"i");return g.test(c)},this.validateInput=function(a,c,d){var e="",f=!1;if(angular.isDefined(c)&&angular.isDefined(c.length)&&c.length>0)for(var g=0;g<c.length;g++)e+="\\"+c[g];switch(b.validationNum[a]){case b.validationNum.text:f=this.validateText(a,c,d,e);break;case b.validationNum.number:f=this.validateNumber(a,c,d,e);break;case b.validationNum.email:f=this.validateEmail(a,c,d,e)}return f}}],link:function(a,b,c){b.parent().prepend('<label class="form-field__label">'+c.placeholder+"</label>"),b.wrap('<div class="form-field-input-container"></div>'),b.parent().parent().find("label").addClass("form-field__label--show")}}}]).directive("attFormFieldValidationPrv",["keyMapAc","validationTypeInt",function(a,b){return{priority:202,scope:{validationType:"=",allowedChars:"="},restrict:"A",require:["?ngModel","^attFormFieldPrv"],link:function(c,d,e,f){var g=f[1];d.bind("keyup",function(){g.validateInput(c.validationType,c.allowedChars,d[0].value)?g.showHideErrorMessage(!1):g.showHideErrorMessage(!0)});var h=a.keyRange,i=a.allowedKeys,j=function(a,b){var c=b.which<h.startNum||b.which>h.endNum,d=b.which<h.startCapitalLetters||b.which>h.endCapitalLetters,e=b.which<h.startSmallLetters||b.which>h.endSmallLetters,f=c&&d&&e;return f&&!a},k=function(a,b){return(b.which<h.startNum||b.which>h.endNum)&&!a},l=function(a,b){var c="-"!==String.fromCharCode(b.which)&&"_"!==String.fromCharCode(b.which),d="@"!==String.fromCharCode(b.which)&&"."!==String.fromCharCode(b.which),e=c&&d,f=j(a,b);return!a&&e&&f},m=function(a,c,d){switch(a){case b.validationNum.text:if(j(c,d))return!0;break;case b.validationNum.number:if(k(c,d))return!0;break;case b.validationNum.email:if(l(c,d))return!0}return!1};d.bind("keypress",function(a){a.which||(a.keyCode?a.which=a.keyCode:a.charCode&&(a.which=a.charCode));var d=g.findAllowedCharactor(a.which),e=angular.isDefined(c.validationType)&&""!==c.validationType,f=a.which!==i.TAB&&a.which!==i.BACKSPACE&&a.which!==i.DELETE,h=e&&f;h&&m(b.validationNum[c.validationType],d,a)&&a.preventDefault()})}}}]).directive("attFormFieldValidationAlertPrv",[function(){return{restrict:"A",scope:{errorMessage:"="},transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",link:function(a){a.errorMessage=a.errorMessage,angular.isDefined(a.$parent.hideErrorMsg)?a.hideErrorMsg=a.$parent.hideErrorMsg:a.hideErrorMsg=!0}}}]).factory("Cards",[function(){var a=/(\d{1,4})/g,b=/(?:^|\s)(\d{4})$/,c=[{type:"discover",pattern:/^(6011|65|64[4-9]|622)/,format:a,inputFormat:b,length:[16],cvcLength:[3],cvcSecurityImg:"visaI",zipLength:[5],luhn:!0},{type:"mc",pattern:/^5[1-5]/,format:a,inputFormat:b,length:[16],cvcLength:[3],cvcSecurityImg:"visaI",zipLength:[5],luhn:!0},{type:"amex",pattern:/^3[47]/,format:/(\d{1,4})(\d{1,6})?(\d{1,5})?/,inputFormat:/^(\d{4}|\d{4}\s\d{6})$/,length:[15],cvcLength:[4],cvcSecurityImg:"amexI",zipLength:[5],luhn:!0},{type:"visa",pattern:/^4/,format:a,inputFormat:b,length:[16],cvcLength:[3],cvcSecurityImg:"visaI",zipLength:[5],luhn:!0}],d=function(a){var b,d,e;for(a=(a+"").replace(/\D/g,""),d=0,e=c.length;e>d;d++)if(b=c[d],b.pattern.test(a))return b},e=function(a){var b,d,e;for(d=0,e=c.length;e>d;d++)if(b=c[d],b.type===a)return b};return{fromNumber:function(a){return d(a)},fromType:function(a){return e(a)},defaultFormat:function(){return a},defaultInputFormat:function(){return b}}}]).factory("_Validate",["Cards","$parse",function(a,b){var c=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},d=function(a){var b,c,d,e,f,g;for(d=!0,e=0,c=(a+"").split("").reverse(),f=0,g=c.length;g>f;f++)b=c[f],b=parseInt(b,10),(d=!d)&&(b*=2),b>9&&(b-=9),e+=b;return e%10===0},e={};return e.cvc=function(d,e,f,g){var h,i;if(angular.isUndefined(d)||null===d||0===d.length)return!0;if(!/^\d+$/.test(d))return!1;var j;if(g.paymentsTypeModel){var k=b(g.paymentsTypeModel);j=k(f)}return j?(i=a.fromType(j),h=d.length,c.call(null!==i?i.cvcLength:void 0,h)>=0):d.length>=3&&d.length<=4},e.zip=function(d,e,f,g){var h,i;if(angular.isUndefined(d)||null===d||0===d.length)return!0;if(!/^\d+$/.test(d))return!1;var j;if(g.paymentsTypeModel){var k=b(g.paymentsTypeModel);j=k(f)}return j?(i=a.fromType(j),h=d.length,c.call(null!==i?i.zipLength:void 0,h)>=0):d.length<6},e.card=function(e,f,g,h){var i,j,k;h.paymentsTypeModel&&(k=b(h.paymentsTypeModel));var l=function(){k&&k.assign(g,null),f.$card=null};return angular.isUndefined(e)||null===e||0===e.length?(l(),!0):(e=(e+"").replace(/\s+|-/g,""),/^\d+$/.test(e)&&(i=a.fromNumber(e))?(f.$card=angular.copy(i),k&&k.assign(g,i.type),ret=(j=e.length,c.call(i.length,j)>=0&&(i.luhn===!1||d(e))),ret):(l(),!1))},function(a,b,c,d,f){if(!e[a])throw types=Object.keys(e),errstr='Unknown type for validation: "'+a+'". ',errstr+='Should be one of: "'+types.join('", "')+'"',errstr;return e[a](b,c,d,f)}}]).factory("_ValidateWatch",["_Validate",function(a){var b={};return b.cvc=function(b,c,d,e){e.paymentsTypeModel&&d.$watch(e.paymentsTypeModel,function(f,g){if(f!==g){var h=a(b,c.$modelValue,c,d,e);c.$setValidity(b,h)}})},b.zip=function(b,c,d,e){e.paymentsTypeModel&&d.$watch(e.paymentsTypeModel,function(f,g){if(f!==g){var h=a(b,c.$modelValue,c,d,e);c.$setValidity(b,h)}})},function(a,c,d,e){return b[a]?b[a](a,c,d,e):void 0}}]).directive("validateCard",["$window","_Validate","_ValidateWatch",function(a,b,c){return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=e.validateCard;c(g,f,a,e);var h=function(c){var h=b(g,c,f,a,e);return f.$setValidity(g,h),"card"===g&&(null===f.$card?null==c||""===c||""===c?(a.invalidCardError="",a.invalidCard=""):c.length>=1&&(a.invalidCardError="error",a.invalidCard="The number entered is not a recognized credit card number."):h?(a.invalidCardError="",a.invalidCard=""):f.$card.length.indexOf(c.length)>=0?(a.invalidCardError="error",a.invalidCard="The number entered is not a recognized credit card number."):(a.invalidCardError="",a.invalidCard=""),d.bind("blur",function(){h&&null!==f.$card?(a.invalidCardError="",a.invalidCard=""):(a.invalidCardError="error",a.invalidCard="The number entered is not a recognized credit card number.")})),h?c:void 0};f.$formatters.push(h),f.$parsers.push(h)}}}]).directive("creditCardImage",function(){return{templateUrl:"app/scripts/ng_js_att_tpls/formField/creditCardImage.html",replace:!1,transclude:!1,link:function(a,b,c){a.$watch(c.creditCardImage,function(b,c){b!==c&&(a.cvc="",angular.isUndefined(b)||null===b||(a.newValCCI="show-"+b),null===b&&(a.newValCCI=""))})}}}).directive("securityCodeImage",["$document",function(a){return{templateUrl:"app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",replace:!1,transclude:!1,link:function(b,c,d){b.$watch(d.securityCodeImage,function(a,c){a!==c&&(angular.isUndefined(a)||null===a||("amexI"===a?(b.newValI="ccv2-security-amex",b.newValIAlt="The 4 digit CVC security code is on the front of the card.",b.cvcPlaceholder="4 digits",b.cvcMaxlength=4):"visaI"===a&&(b.newValI="ccv2-security",b.newValIAlt="The CVC security code is on the back of your card right after the credit card number.",b.cvcPlaceholder="3 digits",b.cvcMaxlength=3)),null===a&&(b.newValI="ccv2-security",b.cvcPlaceholder="3 digits",b.cvcMaxlength=3,b.newValIAlt="The CVC security code is on the back of your card right after the credit card number."))}),c.bind("click",function(a){a.preventDefault(),c.find("button").hasClass("active")?c.find("button").removeClass("active"):c.find("button").addClass("active")});var e=angular.element(a);e.bind("click",function(a){var b=a.target.className;"btn btn-alt btn-tooltip active"!==b&&c.find("button").hasClass("active")&&c.find("button").removeClass("active")})}}}]),angular.module("att.abs.hourpicker",["att.abs.utilities"]).constant("hourpickerConfig",{days:["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],customOption:"Custom"}).controller("hourPickerController",["$scope",function(a){a.options=[],this.setOptions=function(b,c,d,e,f,g){a.options.push(b),void 0!==e&&(a.preselect=e);var h;if(void 0!==c){a.fromtime=c;for(h in a.days)a.days.hasOwnProperty(h)&&(a.FrtimeList[a.days[h]]={},void 0!==f?(a.FrtimeList[a.days[h]].value=f,a.selectedFromOption[a.days[h]]=f):(a.FrtimeList[a.days[h]].value=c[0].value,a.selectedFromOption[a.days[h]]=c[0].value))}if(void 0!==d){a.totime=d;for(h in a.days)a.days.hasOwnProperty(h)&&(a.TotimeList[a.days[h]]={},void 0!==g?(a.TotimeList[a.days[h]].value=g,a.selectedToOption[a.days[h]]=g):(a.TotimeList[a.days[h]].value=d[0].value,a.selectedToOption[a.days[h]]=d[0].value),a.showToTimeErrorDay[a.days[h]]=!1)}void 0!==f&&(a.uncheckedFromTime=f),void 0!==g&&(a.uncheckedToTime=g)},this.getSelectedOption=function(){return a.selectedOption},this.setToTimeErrorDay=function(b,c){a.showToTimeErrorDay[b]=c}}]).directive("attHourpickerOption",[function(){return{restrict:"EA",require:"^attHourpicker",scope:{option:"=option",fromtime:"=fromtime",totime:"=totime",preselect:"=preselect",uncheckedFromTime:"=",uncheckedToTime:"="},link:function(a,b,c,d){d.setOptions(a.option,a.fromtime,a.totime,a.preselect,a.uncheckedFromTime,a.uncheckedToTime)}}}]).directive("attHourpicker",["hourpickerConfig","$document","$log","$documentBind","$timeout",function(a,b,c,d,e){return{require:"ngModel",restrict:"EA",controller:"hourPickerController",transclude:!0,scope:{model:"=ngModel",resetFlag:"=?"},templateUrl:"app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",link:function(b,c,f,g){var h=!1;b.isFromDropDownOpen=!1,b.isToDropDownOpen=!1;var i="",j={};b.days=a.days,b.daysList={},b.FrtimeList={},b.FrtimeListDay={},b.TotimeListDay={},b.selectedFromOption={},b.selectedToOption={},b.TotimeList={},b.selectedIndex=0,b.selectedOption="Select from list",b.customTime=[],b.resetFlag=!1,b.showToTimeErrorDay={},b.validatedCustomPreselect=[],b.$watch("resetFlag",function(c,d){if(c!==d){if(c&&b.selectedOption===a.customOption){for(day in b.daysList)b.daysList.hasOwnProperty(day)&&(b.daysList[day]=!1,b.addSelectedValue(day));b.preselectUpdateFxn(b.preselect)}b.resetFlag=!1}}),b.$watch("selCategory",function(a){a&&g.$setViewValue(a)},!0),b.updateData=function(c){if(c.constructor===Array){b.showDaysSelector=!0,b.selectedOption=a.customOption;for(var d in c)if(c.hasOwnProperty(d)){var e=c[d].day;"boolean"==typeof c[d].preEnabled&&c[d].preEnabled?b.daysList[e]=!0:b.daysList[e]=!1;for(var f in b.fromtime)b.fromtime[f].value!==c[d].FromTime||b.uncheckedFromTime||(b.FrtimeList[e].value=b.fromtime[f].value,b.selectedFromOption[e]=b.FrtimeList[e].value);for(var g in b.totime)b.totime[g].value!==c[d].ToTime||b.uncheckedToTime||(b.TotimeList[e].value=b.totime[g].value,b.selectedToOption[e]=b.TotimeList[e].value);if(b.addSelectedValue(e,c[d].FromTime,c[d].ToTime),parseInt(d)+1===c.length)break}}else b.selectOption(c.day)},b.$watch("preselect",function(a){b.preselectUpdateFxn(a)}),b.preselectUpdateFxn=function(a){if(void 0!==a){if(b.options&&(a=b.validatePreselectData(a)),""===a)return;b.updateData(a)}},b.validatePreselectData=function(a){if(a.constructor===Array){for(var c in a)if(a.hasOwnProperty(c)){var d=a[c].day,e=!1,f=!1,g=!1;for(var h in b.days)if(b.days[h]===d){e=!0;break}if(!e){a.splice(c,1);continue}for(var i in b.fromtime)if(b.fromtime[i].value===a[c].FromTime){f=!0;break}f||(a[c].FromTime=b.fromtime[0].value);for(var j in b.totime)if(b.totime[j].value===a[c].ToTime){g=!0;break}if(g||(a[c].ToTime=b.totime[0].value),"boolean"==typeof a[c].preEnabled&&a[c].preEnabled?a[c].preEnabled=!0:a[c].preEnabled=!1,b.validatedCustomPreselect[d]={},b.validatedCustomPreselect[d].FromTime=a[c].FromTime,b.validatedCustomPreselect[d].ToTime=a[c].ToTime,parseInt(c)+1===a.length)break}}else{var k=!1;for(var l in b.options)if(b.options[l]===a.day){k=!0;break}k||(a="")}return a},b.selectPrevNextValue=function(a,b,c){var d,e=0;if(38===a.keyCode)d=-1;else{if(40!==a.keyCode)return c;d=1}if(-1!==b.indexOf(c))e=b.indexOf(c)+d;else for(var f in b)if(b[f].value===c){e=parseInt(f)+d;break}return e===b.length?e-=1:-1===e&&(e+=1),a.preventDefault(),b[e].value?b[e].value:b[e]},b.showDropdown=function(){b.showlist=!b.showlist,h=!h},b.showfromDayDropdown=function(a){for(count in b.FrtimeListDay)count!==a&&b.FrtimeListDay[count]&&(b.FrtimeListDay[count]=!1);for(count in b.TotimeListDay)b.TotimeListDay[count]&&(b.TotimeListDay[count]=!1);b.FrtimeListDay[a]=!b.FrtimeListDay[a],h=!h,b.showlist=!1,b.FrtimeListDay[a]?(b.isFromDropDownOpen=!0,i=a):b.isFromDropDownOpen=!1,e(function(){if(b.FrtimeListDay[a]){var d=angular.element(c)[0].querySelector(".customdays-width"),e=angular.element(d.querySelector(".select2-container-active")).parent()[0].querySelector("ul"),f=angular.element(e.querySelector(".selectedItemInDropDown"))[0].offsetTop;angular.element(e)[0].scrollTop=f}})},b.showtoDayDropdown=function(a){for(count in b.TotimeListDay)count!==a&&b.TotimeListDay[count]&&(b.TotimeListDay[count]=!1);for(count in b.FrtimeListDay)b.FrtimeListDay[count]&&(b.FrtimeListDay[count]=!1);b.TotimeListDay[a]=!b.TotimeListDay[a],h=!h,b.showlist=!1,b.TotimeListDay[a]?(b.isToDropDownOpen=!0,i=a):b.isToDropDownOpen=!1,e(function(){if(b.TotimeListDay[a]){var d=angular.element(c)[0].querySelector(".customdays-width"),e=angular.element(d.querySelector(".select2-container-active")).parent()[0].querySelector("ul"),f=angular.element(e.querySelector(".selectedItemInDropDown"))[0].offsetTop;angular.element(e)[0].scrollTop=f}})},b.selectFromDayOption=function(a,c){b.selectedFromOption[a]=c,b.FrtimeList[a].value=c,b.FrtimeListDay[a]=!1,b.isFromDropDownOpen=!1},b.selectToDayOption=function(a,c){b.selectedToOption[a]=c,b.TotimeList[a].value=c,b.TotimeListDay[a]=!1,b.isToDropDownOpen=!1},b.addSelectedValue=function(a,c,d){var e,f;if(void 0===b.daysList[a]||b.daysList[a]){for(b.selectedFromOption[a]===b.uncheckedFromTime&&(angular.isDefined(b.validatedCustomPreselect[a])?(b.selectedFromOption[a]=b.validatedCustomPreselect[a].FromTime,c=b.validatedCustomPreselect[a].FromTime,b.FrtimeList[a].value=b.validatedCustomPreselect[a].FromTime):(b.selectedFromOption[a]=b.fromtime[0].value,c=b.fromtime[0].value,b.FrtimeList[a].value=b.fromtime[0].value)),b.selectedToOption[a]===b.uncheckedToTime&&(angular.isDefined(b.validatedCustomPreselect[a])?(b.selectedToOption[a]=b.validatedCustomPreselect[a].ToTime,d=b.validatedCustomPreselect[a].ToTime,b.TotimeList[a].value=b.validatedCustomPreselect[a].ToTime):(b.selectedToOption[a]=b.totime[0].value,d=b.totime[0].value,b.TotimeList[a].value=b.totime[0].value)),j.day=a,j.FromTime=b.FrtimeList[a].value,j.ToTime=b.TotimeList[a].value,e=0,f=b.customTime.length;f>e;e++)if(b.customTime[e].day===a){b.customTime[e].FromTime=j.FromTime,b.customTime[e].ToTime=j.ToTime;break}if(e===f){var g=angular.copy(j);b.customTime.push(g)}}else for(e=0,f=b.customTime.length;f>e;e++)if(b.customTime[e].day===a){b.uncheckedFromTime?b.selectedFromOption[b.customTime[e].day]=b.uncheckedFromTime:b.selectedFromOption[b.customTime[e].day]=b.FrtimeList[b.customTime[e].day].value,b.uncheckedToTime?b.selectedToOption[b.customTime[e].day]=b.uncheckedToTime:b.selectedToOption[b.customTime[e].day]=b.TotimeList[b.customTime[e].day].value,b.customTime.splice(e,1);break}b.selCategory=b.customTime};var k=function(){b.showlist&&b.$apply(function(){b.showlist=!1})};d.click("showlist",k,b);var l=function(){b.$apply(function(){b.isFromDropDownOpen&&(b.FrtimeListDay[i]=!1,b.isFromDropDownOpen=!1)})};d.click("isFromDropDownOpen",l,b);var m=function(){b.$apply(function(){b.isToDropDownOpen&&(b.TotimeListDay[i]=!1,b.isToDropDownOpen=!1)})};d.click("isToDropDownOpen",m,b),b.selectOption=function(c){if(c===a.customOption)b.showDaysSelector=!0,b.selCategory=b.customTime;else{b.showDaysSelector=!1;var d=/[0-9]\s?am/i.exec(c),e=/[0-9]\s?pm/i.exec(c);b.selCategory={day:c,FromTime:null===d?"NA":d[0],ToTime:null===e?"NA":e[0]}}b.showlist=!1,h=!1,b.selectedOption=c}}}}]).directive("attHourpickerValidator",["hourpickerConfig",function(a){return{restrict:"A",require:["attHourpicker","ngModel"],link:function(b,c,d,e){var f=e[0],g=e[1],h=function(a){var b=Number(a.match(/^(\d+)/)[1]),c=Number(a.match(/:(\d+)/)[1]),d=a.match(/\s(.*)$/)[1].toUpperCase();"PM"===d&&12>b&&(b+=12),"AM"===d&&12===b&&(b-=12);var e=b.toString(),f=c.toString();return 10>b&&(e="0"+e),10>c&&(f="0"+f),parseInt(e+f,10)},i=function(a,b){var c=h(a),d=h(b);return d-c},j=function(b){if(f.getSelectedOption()===a.customOption){var c=0;for(var d in b)b.hasOwnProperty(d)&&(i(b[d].FromTime,b[d].ToTime)<=0?(f.setToTimeErrorDay(b[d].day,!0),c++):f.setToTimeErrorDay(b[d].day,!1));return c>0?(g.$setValidity("validationStatus",!1),[]):(g.$setValidity("validationStatus",!0),b)}return g.$setValidity("validationStatus",!0),b};g.$parsers.unshift(j)}}}]),angular.module("att.abs.iconButtons",[]).constant("buttonConfig",{activeClass:"active--button",toggleEvent:"click"}).directive("attIconBtnRadio",["buttonConfig",function(a){var b=a.activeClass||"active--button",c=a.toggleEvent||"click";return{require:"ngModel",link:function(a,d,e,f){d.attr("tabindex","0"),d.append("<span class='hidden-spoken'>"+e.attIconBtnRadio+"</span>"),f.$render=function(){d.parent().toggleClass(b,angular.equals(f.$modelValue,e.attIconBtnRadio))},d.parent().bind(c,function(){d.parent().hasClass(b)||a.$apply(function(){f.$setViewValue(e.attIconBtnRadio),f.$render()})})}}}]).directive("attIconBtnCheckbox",["buttonConfig",function(a){var b=a.activeClass||"active--button",c=a.toggleEvent||"click";return{require:"ngModel",link:function(a,d,e,f){function g(){var b=a.$eval(e.btnCheckboxTrue);return angular.isDefined(b)?b:!0}function h(){var b=a.$eval(e.btnCheckboxFalse);return angular.isDefined(b)?b:!1}d.attr("tabindex","0"),d.append("<span class='hidden-spoken'>"+e.attIconBtnCheckbox+"</span>"),f.$render=function(){d.parent().toggleClass(b,angular.equals(f.$modelValue,g()))},d.parent().bind(c,function(){a.$apply(function(){f.$setViewValue(d.parent().hasClass(b)?h():g()),f.$render()})})}}}]),angular.module("att.abs.links",["ngSanitize"]).directive("attLink",[function(){return{restrict:"A",link:function(a,b){b.addClass("link"),b.attr("href")||b.attr("tabindex","0")}}}]).directive("attLinkVisited",[function(){return{restrict:"A",link:function(a,b){b.addClass("link--visited"),b.attr("href")||b.attr("tabindex","0")}}}]).directive("attReadmore",["$timeout",function(a){return{restrict:"A",scope:{lines:"@noOfLines",textModel:"=",isOpen:"="},templateUrl:"app/scripts/ng_js_att_tpls/links/readMore.html",link:function(b,c){var d=1;b.$watch("textModel",function(e){e?("function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),b.textToDisplay=e.trim(),b.readFlag=!0,a(function(){var a=c[0].children[0].children[0];1===d&&(d=window.getComputedStyle?parseInt(b.lines)*parseFloat(window.getComputedStyle(a,null).getPropertyValue("height")):parseInt(b.lines)*parseFloat(a.currentStyle.height),b.elemHeight=d,b.readLinkStyle={height:b.elemHeight+"px"})}),b.readMoreLink=!0,b.readLessLink=!1):(b.textToDisplay="",b.readMoreLink=!1,b.readLessLink=!1,b.readFlag=!1)});var e=c.parent();e.hasClass("att-accordion__body")&&b.$watch("isOpen",function(a){a||(b.readMoreLink=!0,b.readLessLink=!1,b.readLinkStyle={height:b.elemHeight+"px"},b.readFlag=!0)}),b.readMore=function(){b.readMoreLink=!1,b.readLessLink=!0,b.readLinkStyle={height:"auto"},b.readFlag=!1;var d=angular.element(c).children().eq(1).find("a")[0];a(function(){d.focus()})},b.readLess=function(){b.readMoreLink=!0,b.readLessLink=!1,b.readLinkStyle={height:b.elemHeight+"px"},b.readFlag=!0;var d=angular.element(c).children().eq(0).find("a")[0];a(function(){d.focus()})}}}}]).directive("attLinksList",[function(){return{restrict:"A",controller:function(){},link:function(a,b){b.addClass("links-list")}}}]).directive("attLinksListItem",[function(){return{restrict:"A",require:"^attLinksList",link:function(a,b){b.addClass("links-list__item"),b.attr("href")||b.attr("tabindex","0")}}}]),angular.module("att.abs.loading",[]).directive("attLoading",["$window",function(a){return{restrict:"A",replace:!0,scope:{icon:"@attLoading",progressStatus:"=?",colorClass:"=?"},templateUrl:"app/scripts/ng_js_att_tpls/loading/loading.html",link:function(b,c){var d=b.progressStatus;if(b.progressStatus=Math.min(100,Math.max(0,d)),-1!==a.navigator.userAgent.indexOf("MSIE 8.")){var e=0,f=36*b.progressStatus;c.css({"background-position-x":e,"background-position-y":-f})}}}}]),angular.module("att.abs.modal",["att.abs.utilities"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b===a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b===a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}).directive("modalBackdrop",["$timeout",function(a){return{restrict:"EA",replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/modal/backdrop.html",link:function(b){b.animate=!1,a(function(){b.animate=!0})}}}]).directive("modalWindow",["$modalStack","$timeout","$document",function(a,b,c){return{restrict:"EA",scope:{index:"@",modalTitle:"@?"},replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/modal/window.html",link:function(d,e,f){d.windowClass=f.windowClass||"",f.modalTitle&&""!==f.modalTitle&&(e[0].setAttribute("aria-label",f.modalTitle),e[0].removeAttribute("modal-title")),b(function(){d.focusModalFlag=!0,d.animate=!0}),c.on("focus keydown",function(a){9===a.which&&(String.prototype.contains=function(a){return-1!==this.indexOf(a)},e[0]===a.target||e[0].contains(a.target)||e[0].focus())}),d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!=c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault?(b.preventDefault(),b.stopPropagation()):b.returnValue=!1,a.dismiss(c.key,"backdrop click"))}}}}]).factory("$modalStack",["$document","$compile","$rootScope","$$stackedMap","events","keymap",function(a,b,c,d,e,f){function g(){for(var a=-1,b=m.keys(),c=0;c<b.length;c++)m.get(b[c]).value.backdrop&&(a=c);return a}function h(b){var c=a.find("body").eq(0),d=a.find("html").eq(0),e=m.get(b).value;m.remove(b),e.modalDomEl.remove(),c.toggleClass(k,m.length()>0),d.css({overflow:"scroll"}),j&&-1==g()&&(j.remove(),j=void 0),e.modalScope.$destroy(),angular.isDefined(o)&&null!=o&&o.focus()}var i,j,k="modal-open",l=c.$new(!0),m=d.createNew(),n={},o=void 0;return c.$watch(g,function(a){l.index=a}),a.bind("keydown",function(a){var b;if(27===a.which)b=m.top(),b&&b.value.keyboard&&c.$apply(function(){n.dismiss(b.key)});else if(a.keyCode===f.KEY.BACKSPACE){var d,g=!1,h=a.srcElement||a.target;g=void 0===h.type?!0:"INPUT"===h.tagName.toUpperCase()&&("TEXT"===(d=h.type.toUpperCase())||"PASSWORD"===d||"FILE"===d||"SEARCH"===d||"EMAIL"===d||"NUMBER"===d||"DATE"===d||"TEL"===d||"URL"===d||"TIME"===d)||"TEXTAREA"===h.tagName.toUpperCase()?h.readOnly||h.disabled:!0,g&&e.preventDefault(a)}}),n.open=function(c,d){m.add(c,{deferred:d.deferred,modalScope:d.scope,backdrop:d.backdrop,keyboard:d.keyboard}),o=document.activeElement;var e=a.find("body").eq(0),f=a.find("html").eq(0);g()>=0&&!j&&(i=angular.element("<div modal-backdrop></div>"),j=b(i)(l),e.append(j));var h=angular.element("<div modal-window></div>");h.attr("window-class",d.windowClass),h.attr("index",m.length()-1),h.attr("modal-title",d.modalTitle),h.html(d.content);var n=b(h)(d.scope);m.top().value.modalDomEl=n,e.append(n),e.addClass(k),f.css({overflow:"hidden"})},n.close=function(a,b){var c=m.get(a);c&&(c.value.deferred.resolve(b),h(a))},n.dismiss=function(a,b){var c=m.get(a).value;c&&(c.deferred.reject(b),h(a))},n.getTop=function(){return m.top()},n}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass,modalTitle:b.modalTitle})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}).directive("simpleModal",["$modal",function(a){return{restrict:"EA",scope:{simpleModal:"@",backdrop:"@",keyboard:"@",modalOk:"&",modalCancel:"&",windowClass:"@",controller:"@",modalTitle:"@?"},link:function(b,c){c.bind("click",function(d){d.preventDefault(),angular.isDefined(c.attr("href"))&&""!==c.attr("href")&&(b.simpleModal=c.attr("href")),"false"===b.backdrop?b.backdropclick="static":b.backdropclick=!0,"false"===b.keyboard?b.keyboardev=!1:b.keyboardev=!0,a.open({templateUrl:b.simpleModal,backdrop:b.backdropclick,keyboard:b.keyboardev,windowClass:b.windowClass,controller:b.controller,modalTitle:b.modalTitle}).result.then(b.modalOk,b.modalCancel)})}}}]).directive("tabbedItem",["$modal","$log",function(a,b){return{restrict:"AE",replace:!0,scope:{items:"=items",controller:"@",templateId:"@",modalTitle:"@?"},templateUrl:"app/scripts/ng_js_att_tpls/modal/tabbedItem.html",controller:["$scope","$rootScope","$attrs",function(c){c.clickTab=function(d){for(var e=0;e<c.items.length;e++)e===d?(c.items[e].isTabOpen=!0,c.items[e].showData=!0):(c.items[e].isTabOpen=!1,c.items[e].showData=!1);var f=a.open({templateUrl:c.templateId,controller:c.controller,windowClass:"tabbedOverlay_modal",modalTitle:c.modalTitle,resolve:{items:function(){return c.items}}});f.result.then(function(a){c.selected=a},function(){b.info("Modal dismissed at: "+new Date)})},c.isActiveTab=function(a){return c.items&&c.items[a]&&c.items[a].isTabOpen}}]}}]).directive("tabbedOverlay",[function(){return{restrict:"AE",replace:!0,scope:{items:"="},transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",controller:["$scope",function(a){a.clickTab=function(b){for(var c=0;c<a.items.length;c++)c===b?(a.items[c].isTabOpen=!0,a.items[c].showData=!0):(a.items[c].isTabOpen=!1,a.items[c].showData=!1)},a.isActiveTab=function(b){return a.items&&a.items[b]&&a.items[b].isTabOpen}}]}}]),angular.module("att.abs.pagination",["att.abs.utilities"]).directive("attPagination",[function(){return{restrict:"EA",scope:{totalPages:"=",currentPage:"=",showInput:"=",clickHandler:"=?"},replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/pagination/pagination.html",
-link:function(a){function b(b){angular.isDefined(b)&&null!==b&&((!b||1>b)&&(b=1),b>a.totalPages&&(b=a.totalPages),a.currentPage!==b&&(a.currentPage=b,c(a.currentPage)),a.totalPages>7&&(b<a.pages[0]&&b>3?a.pages=[b,b+1,b+2]:b>a.pages[2]&&b<a.totalPages-2?a.pages=[b-2,b-1,b]:3>=b?a.pages=[1,2,3]:b>=a.totalPages-2&&(a.pages=[a.totalPages-2,a.totalPages-1,a.totalPages])))}a.focusedPage,a.$watch("totalPages",function(c){if(angular.isDefined(c)&&null!==c){if(a.pages=[],1>c)return void(a.totalPages=1);if(7>=c)for(var d=1;c>=d;d++)a.pages.push(d);else if(c>7){var e=Math.ceil(c/2);a.pages=[e-1,e,e+1]}b(1)}}),a.$watch("currentPage",function(a){b(a)});var c=function(b){angular.isFunction(a.clickHandler)&&a.clickHandler(b)};a.next=function(b){b.preventDefault(),a.currentPage<a.totalPages&&(a.currentPage+=1,c(a.currentPage))},a.prev=function(b){b.preventDefault(),a.currentPage>1&&(a.currentPage-=1,c(a.currentPage))},a.selectPage=function(b,d){d.preventDefault(),a.currentPage=b,a.focusedPage=b,c(a.currentPage)},a.checkSelectedPage=function(b){return a.currentPage===b?!0:!1},a.isFocused=function(b){return a.focusedPage===b}}}}]),angular.module("att.abs.paneSelector",["att.abs.utilities"]).constant("paneGroupConstants",{SIDE_WIDTH_DEFAULT:"33%",INNER_PANE_DEFAULT:"67%",SIDE_PANE_ID:"sidePane",NO_DRILL_DOWN:"none"}).factory("animation",function(){return TweenLite}).directive("attPaneAccessibility",["keymap","$window",function(a,b){return{restrict:"A",require:["^?sidePane","^?innerPane"],link:function(b,c,d,e){var f=e[0],g=e[1],h=!1;b.ie=function(){for(var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");c.innerHTML="<!--[if gt IE "+ ++b+"]><i></i>< ![endif]-->",d[0];);return b>4?b:a}(),h=8===b.ie?!0:!1,c.bind("keydown",function(b){if(a.isAllowedKey(b.keyCode)||a.isControl(b)||a.isFunctionKey(b)){b.preventDefault(),b.stopPropagation();var d;switch(b.keyCode){case a.KEY.DOWN:if(d=angular.element(c[0])[0],d&&d.nextElementSibling&&d.nextElementSibling.focus(),h){do{if(!d||!d.nextSibling)break;d=d.nextSibling}while(d&&"DIV"!==d.tagName);d.focus()}break;case a.KEY.UP:if(d=angular.element(c[0])[0],d&&d.previousElementSibling&&d.previousElementSibling.focus(),h){do{if(!d||!d.previousSibling)break;d=d.previousSibling}while(d&&"DIV"!==d.tagName);d.focus()}break;case a.KEY.RIGHT:angular.isDefined(f)&&(d=f.getElement()[0]),angular.isDefined(g)&&(d=g.getElement()[0]);do{if(!d||!d.nextElementSibling)break;d=d.nextElementSibling}while("none"===window.getComputedStyle(d,null).getPropertyValue("display"));if(h)do{if(!d||!d.nextSibling)break;d=d.nextSibling}while(d&&"DIV"==d.tagName&&"none"==d.currentStyle.display);d&&d.querySelector("[att-pane-accessibility]").focus();break;case a.KEY.LEFT:angular.isDefined(f)&&(d=f.getElement()[0]),angular.isDefined(g)&&(d=g.getElement()[0]);do{if(!d||!d.previousElementSibling)break;d=d.previousElementSibling}while("none"==window.getComputedStyle(d,null).getPropertyValue("display"));if(h)do{if(!d||!d.previousSibling)break;d=d.previousSibling}while(d&&"DIV"==d.tagName&&"none"==d.currentStyle.display);d&&d.querySelector("[att-pane-accessibility]").focus()}}})}}}]).directive("sideRow",[function(){return{restrict:"A",replace:!0,require:["^sidePane","^paneGroup"],link:function(a,b,c,d){var e=d[0],f=d[1];a.$first&&(e.sidePaneIds=[]);var g=c.paneId,h=c.drillDownTo;e.sidePaneRows.push({paneId:g,drillDownTo:h}),b.on("click",function(){e.currentSelectedRowPaneId=g,f.slideOutPane(g,!0)})}}}]).controller("SidePaneCtrl",["$scope","$element","animation","paneGroupConstants",function(a,b,c,d){this.getElement=function(){return b},this.sidePaneTracker={},this.currentWidth=d.SIDE_WIDTH_DEFAULT,this.paneId=d.SIDE_PANE_ID,this.currentSelectedRowPaneId,this.drillDownToMapper={},this.sidePaneRows=[],this.init=function(){var a=this.sidePaneRows;if(a)for(var b in a)if(a.hasOwnProperty(b)){var c=a[b].paneId,d=a[b].drillDownTo;this.drillDownToMapper[c]=d,0==b&&(this.currentSelectedRowPaneId=c,this.sidePaneTracker[c]=[])}},this.getSidePanesList=function(){return this.sidePaneTracker[this.currentSelectedRowPaneId]},this.addToSidePanesList=function(a){void 0===this.sidePaneTracker[this.currentSelectedRowPaneId]?this.sidePaneTracker[this.currentSelectedRowPaneId]=[]:a&&this.sidePaneTracker[this.currentSelectedRowPaneId].push(a)},this.setWidth=function(a){a&&(this.currentWidth=a),c.set(b,{width:this.currentWidth})},this.resizeWidth=function(a){a&&(this.currentWidth=a),c.to(b,.5,{width:a})}}]).directive("sidePane",["paneGroupConstants",function(a){return{restrict:"EA",transclude:!0,replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",require:["^paneGroup","sidePane"],controller:"SidePaneCtrl",scope:{},link:function(b,c,d,e){var f=e[0],g=e[1];f.addPaneCtrl(a.SIDE_PANE_ID,g)}}}]).directive("drillDownRow",["$parse","paneGroupConstants",function(a,b){return{restrict:"A",replace:!0,require:["^innerPane","^paneGroup"],link:function(a,c,d,e){var f=e[0],g=e[1];c.on("click",function(){var a=f.drillDownTo;f.drillDownTo!==b.NO_DRILL_DOWN&&g.slideOutPane(a),c[0].focus()})}}}]).controller("InnerPaneCtrl",["$scope","$element","animation","paneGroupConstants",function(a,b,c,d){this.getElement=function(){return b},this.paneId=a.paneId,this.drillDownTo,this.currentWidth=d.INNER_PANE_DEFAULT,this.setWidth=function(a){a&&(this.currentWidth=a),c.set(b,{width:this.currentWidth})},this.resizeWidth=function(a,d){c.to(b,.25,{width:a,onComplete:d})},this.displayNone=function(){c.set(b,{display:"none"})},this.displayBlock=function(){c.set(b,{display:"block"}),this&&this.hideRightBorder()},this.floatLeft=function(){c.set(b,{"float":"left"})},this.hideLeftBorder=function(){c.set(b,{borderLeftWidth:"0px"})},this.showLeftBorder=function(){c.set(b,{borderLeftWidth:"1px"})},this.hideRightBorder=function(){c.set(b,{borderRightWidth:"0px"})},this.showRightBorder=function(){c.set(b,{borderRightWidth:"1px"})},this.slideFromRight=function(){c.set(b,{"float":"right"}),c.set(b,{width:this.currentWidth})},this.startOpen=function(){return a.startOpen}}]).directive("innerPane",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",require:["^paneGroup","innerPane"],controller:"InnerPaneCtrl",scope:{paneId:"@"},link:function(a,b,c,d){""===c.startOpen&&(a.startOpen=!0);var e=d[0],f=d[1];e.addPaneCtrl(a.paneId,f)}}}).controller("PaneGroupCtrl",["$scope","$element","paneGroupConstants",function(a,b,c){this.panes={},this.accountLevelPaneModel=[],this.title=a.title,this.init=function(){function a(a,b){var c,d=[];for(c in a.sidePaneRows)if(a.sidePaneRows.hasOwnProperty(c)){var e=a.sidePaneRows[c];c>0&&b[e.paneId].startOpen&&b[e.paneId].startOpen()&&(d.push(e),a.addToSidePanesList(e.paneId))}if(f)for(c in d)if(d.hasOwnProperty(c)){var g=d[c].paneId,h=b[g];h&&h.setWidth&&h.displayBlock&&(h.setWidth(f),h.displayBlock())}}var b=this.panes[c.SIDE_PANE_ID];if(b){b.init();var d,e=1;for(d in this.panes)this.panes[d].startOpen&&this.panes[d].startOpen()&&e++;var f;if(e>=3&&(f=100/e+"%"),this.panes[b.currentSelectedRowPaneId]){f?(b.setWidth(f),this.panes[b.currentSelectedRowPaneId].setWidth(f)):(b.setWidth(),this.panes[b.currentSelectedRowPaneId].setWidth()),this.panes[b.currentSelectedRowPaneId].displayBlock();for(d in this.panes)d!==c.SIDE_PANE_ID&&d!==b.currentSelectedRowPaneId&&this.panes[d].displayNone(),this.panes[d].drillDownTo=b.drillDownToMapper[d]}a(b,this.panes)}},this.resetPanes=function(){for(var a in this.panes)if(this.panes.hasOwnProperty(a)){var b=this.panes[a];b&&b.paneId!==c.SIDE_PANE_ID&&(b.floatLeft(),b.displayNone())}this.panes[c.SIDE_PANE_ID]&&this.panes[c.SIDE_PANE_ID].setWidth(c.SIDE_WIDTH_DEFAULT)},this.addPaneCtrl=function(a,b){this.panes[a]=b},this._slideOutPane=function(a,b){this.resetPanes();var d;if(b)if(this.panes[c.SIDE_PANE_ID]&&(d=this.panes[c.SIDE_PANE_ID].getSidePanesList()),d){if(this.panes&&this.panes[c.SIDE_PANE_ID])if(0===d.length&&this.panes[a])this.panes[c.SIDE_PANE_ID].setWidth(c.SIDE_WIDTH_DEFAULT),this.panes[a].displayBlock(),this.panes[a].setWidth(c.INNER_PANE_DEFAULT);else{var e=d.length+2,f=100/e+"%";this.panes[c.SIDE_PANE_ID].setWidth(f),this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId]&&(this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock(),this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(f));for(var g in d)this.panes[d[g]]&&(this.panes[d[g]].displayBlock(),this.panes[d[g]].setWidth(f))}}else this.panes&&this.panes[c.SIDE_PANE_ID]&&this.panes[a]&&(this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId=a,this.panes[c.SIDE_PANE_ID].addToSidePanesList(),this.panes[a].slideFromRight(),this.panes[a].displayBlock(),this.panes[a].setWidth(c.INNER_PANE_DEFAULT));else{var h,i=!1;this.panes[c.SIDE_PANE_ID]&&(h=this.panes[c.SIDE_PANE_ID].getSidePanesList());for(var j in h)if(h.hasOwnProperty(j)){var k=h[j];if(k===a){i=!0;break}}!i&&this.panes[c.SIDE_PANE_ID]&&this.panes[c.SIDE_PANE_ID].addToSidePanesList(a);var l;this.panes[c.SIDE_PANE_ID]&&(l=this.panes[c.SIDE_PANE_ID].getSidePanesList().length);var m=l+2,n=100/m+"%";this.panes[c.SIDE_PANE_ID]&&this.panes[c.SIDE_PANE_ID].setWidth(n);var o;this.panes[c.SIDE_PANE_ID]&&(o=this.panes[c.SIDE_PANE_ID].getSidePanesList()[l-1]);var p=this;p.panes[c.SIDE_PANE_ID]&&(d=p.panes[c.SIDE_PANE_ID].getSidePanesList());for(var q in d)if(d.hasOwnProperty(q)){var r=d[q],s=this.panes[r];r!==o&&s&&(s.setWidth(n),s.displayBlock(),s.floatLeft())}this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId]&&(this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock(),this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder(),this.panes[this.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(n,function(){p.panes[o]&&p.panes[p.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId]&&(p.panes[p.panes[c.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder(),p.panes[o].setWidth(n),p.panes[o].slideFromRight(),p.panes[o].displayBlock(),p.panes[o].floatLeft())}))}},this.slideOutPane=function(a,b){this._slideOutPane(a,b)}}]).directive("paneGroup",["$timeout",function(a){return{restrict:"EA",transclude:!0,replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",scope:{},controller:"PaneGroupCtrl",link:function(b,c,d,e){function f(){e.init()}a(f,100)}}}]),angular.module("att.abs.tooltip",["att.abs.position","att.abs.utilities","ngSanitize"]).constant("tooltipDefaultOptions",{placement:"above",animation:!1,popupDelay:0,stylett:"dark",appendToBody:!0}).provider("$tooltip",["tooltipDefaultOptions",function(a){function b(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var c={mouseenter:"mouseleave",click:"click",focus:"blur",mouseover:"mouseout"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate","$attElementDetach",function(e,f,g,h,i,j,k,l){return function(e,m,n){function o(a){var b=a||p.trigger||n,d=c[b]||b;return{show:b,hide:d}}var p=angular.extend({},a,d),q=b(e),r=k.startSymbol(),s=k.endSymbol();return{restrict:"EA",scope:!0,link:function(a,b,c){function d(){a.tt_isOpen?n():k()}function k(){(!F||a.$eval(c[m+"Enable"]))&&(a.tt_popupDelay?y=g(t,a.tt_popupDelay):a.$apply(t))}function n(){a.$apply(function(){u()})}function t(){var c,d,e,f;if(a.tt_content){x&&g.cancel(x),B.css({top:0,left:0,display:"block","z-index":9999}),C?(z=z||i.find("body"),z.append(B)):b.after(B),c=C?j.offset(b):j.position(b),d=B.prop("offsetWidth"),e=B.prop("offsetHeight");var h=10;switch(a.tt_placement){case"right":f=C?{top:c.top+c.height/2-e/2,left:c.left+c.width+G}:{top:c.top+c.height/2-e/2,left:c.left+c.width+h+G};break;case"below":f=C?{top:c.top+c.height+G,left:c.left+c.width/2-d/2}:{top:c.top+c.height+h+G,left:c.left+c.width/2-d/2};break;case"left":f=C?{top:c.top+c.height/2-e/2,left:c.left-d-G}:{top:c.top+c.height/2-e/2,left:c.left-d-h-G};break;default:f=C?{top:c.top-e-G,left:c.left+c.width/2-d/2}:{top:c.top-e-h-G,left:c.left+c.width/2-d/2}}f.top+="px",f.left+="px",B.css(f),a.tt_isOpen=!0}}function u(){a.tt_isOpen=!1,g.cancel(y),angular.isDefined(a.tt_animation)&&a.tt_animation()?x=g(function(){l(B[0])},500):l(B[0])}function v(){b.removeAttr("title"),w||(H?b.attr("title",a.tooltipAriaLabel):b.attr("title",a.tt_content))}b.attr("tabindex")||b.attr("tabindex","0");var w=!1;b.bind("mouseenter",function(){w=!0,b.removeAttr("title")}),b.bind("mouseleave",function(){w=!1,v()}),a.parentAttrs=c;var x,y,z,A="<div "+q+'-popup title="'+r+"tt_title"+s+'" content="'+r+"tt_content"+s+'" placement="'+r+"tt_placement"+s+'" animation="tt_animation()" is-open="tt_isOpen" stylett="'+r+"tt_style"+s+'" ></div>',B=f(A)(a),C=angular.isDefined(p.appendToBody)?p.appendToBody:!1,D=o(void 0),E=!1,F=angular.isDefined(c[m+"Enable"]),G=0,H=!1;a.tt_isOpen=!1,a.$watch("tt_isOpen",function(a,b){a===b||a||l(B[0])}),c.$observe(e,function(b){b?(a.tt_content=b,v()):a.tt_isOpen&&u()}),c.$observe(m+"Title",function(b){a.tt_title=b}),c.$observe(m+"Placement",function(b){a.tt_placement=angular.isDefined(b)?b:p.placement}),c.$observe(m+"Style",function(b){a.tt_style=angular.isDefined(b)?b:p.stylett}),c.$observe(m+"Animation",function(b){a.tt_animation=angular.isDefined(b)?h(b):function(){return p.animation}}),c.$observe(m+"PopupDelay",function(b){var c=parseInt(b,10);a.tt_popupDelay=isNaN(c)?p.popupDelay:c}),c.$observe(m+"Trigger",function(a){E&&(b.unbind(D.show,k),b.unbind(D.hide,n)),D=o(a),"focus"===D.show?(b.bind("focus",k),b.bind("blur",n),b.bind("click",function(a){a.stopPropagation()})):D.show===D.hide?b.bind(D.show,d):(b.bind(D.show,k),b.bind(D.hide,n)),E=!0}),c.$observe(m+"AppendToBody",function(b){C=angular.isDefined(b)?h(b)(a):C}),c.$observe(m+"Offset",function(a){G=angular.isDefined(a)?parseInt(a,10):0}),c.$observe(m+"AriaLabel",function(b){angular.isDefined(b)?(a.tooltipAriaLabel=b,H=!0):H=!1,v()}),C&&a.$on("$locationChangeSuccess",function(){a.tt_isOpen&&u()}),a.$on("$destroy",function(){a.tt_isOpen?u():B.remove()})}}}}]}]).directive("tooltipPopup",["$document","$documentBind",function(a,b){return{restrict:"EA",replace:!0,transclude:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"=",stylett:"@"},templateUrl:"app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",link:function(a,c){a.$watch("isOpen",function(){a.isOpen}),c.bind("click",function(a){a.stopPropagation()});var d=function(){a.$apply(function(){a.isOpen=!1})};b.event("click","isOpen",d,a,!0,10)}}}]).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipCondition",["$timeout",function(a){return{restrict:"EA",replace:!0,scope:{tooltipCondition:"@?"},template:'<p><span tooltip="{{tooltipCondition}}" ng-if="showpop">{{tooltipCondition}}</span><span id="innerElement" ng-hide="showpop">{{tooltipCondition}}</span></p>',link:function(b,c,d){b.showpop=!1,"true"===d.height?a(function(){var a=c[0].offsetHeight,d=c.children(0)[0].offsetHeight;d>a&&(b.showpop=!0)}):b.tooltipCondition.length>=25&&(b.showpop=!0)}}}]),angular.module("att.abs.popOvers",["att.abs.tooltip","att.abs.utilities","ngSanitize"]).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]).directive("popoverPopup",["$document","$documentBind","$timeout","events","DOMHelper",function(a,b,c,d,e){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/popOvers/popOvers.html",scope:{content:"@",placement:"@",animation:"&",isOpen:"=",stylett:"@"},link:function(a,f,g,h){a.closeable=!1;try{a.closeable=""===a.$parent.parentAttrs.closeable?!0:!1}catch(i){}var j=void 0,k=void 0,l=function(b){a.$apply(function(){a.isOpen=!1})},m=function(b){(27===b.which||27===b.keyCode)&&(console.log("ESC was pressed!"),a.$apply(function(){a.isOpen=!1}))};c(function(){k=e.firstTabableElement(f)},10,!1),a.$watch("isOpen",function(b){if(a.isOpen){if(j=document.activeElement,angular.isDefined(k))try{k.focus()}catch(c){}}else if(angular.isDefined(j))try{j.focus()}catch(c){}}),a.$watch("stylett",function(b){a.popOverStyle=b}),a.$watch("placement",function(b){a.popOverPlacement=b}),a.closeMe=function(){a.isOpen=!1},f.bind("click",function(a){d.stopPropagation(a)}),b.event("click","isOpen",l,a,!0,10),b.event("keydown","isOpen",m,a,!0,10)}}}]),angular.module("att.abs.profileCard",[]).constant("profileStatus",{status:{ACTIVE:{status:"Active",color:"green"},DEACTIVATED:{status:"Deactivated",color:"red"},LOCKED:{status:"Locked",color:"red"},IDLE:{status:"Idle",color:"yellow"},PENDING:{status:"Pending",color:"blue"}},role:"COMPANY ADMINISTRATOR"}).directive("profileCard",["$http","$q","profileStatus",function(a,b,c){return{restrict:"EA",replace:"true",templateUrl:function(a,b){return b.addUser?"app/scripts/ng_js_att_tpls/profileCard/addUser.html":"app/scripts/ng_js_att_tpls/profileCard/profileCard.html"},scope:{profile:"="},link:function(a,d,e){function f(a){var c=b.defer(),d=new Image;return d.onerror=function(){c.reject(!1)},d.onload=function(){c.resolve(!0)},void 0!==a&&a.length>0?d.src=a:c.reject(!1),c.promise}if(a.image=!0,!e.addUser){a.image=!1,f(a.profile.img).then(function(b){a.image=b});var g=a.profile.name.split(" ");a.initials="";for(var h=0;h<g.length;h++)a.initials+=g[h][0];a.profile.role.toUpperCase()===c.role&&(a.badge=!0);var i=c.status[a.profile.state.toUpperCase()];i&&(a.profile.state=c.status[a.profile.state.toUpperCase()].status,a.colorIcon=c.status[a.profile.state.toUpperCase()].color,(a.profile.state.toUpperCase()===c.status.PENDING.status.toUpperCase()||a.profile.state.toUpperCase()===c.status.LOCKED.status.toUpperCase())&&(a.profile.lastLogin=a.profile.state));var j=(new Date).getTime(),k=new Date(a.profile.lastLogin).getTime(),l=(j-k)/864e5;1>=l?a.profile.lastLogin="Today":2>=l&&(a.profile.lastLogin="Yesterday")}}}}]),angular.module("att.abs.progressBars",[]).directive("attProgressBar",[function(){return{restrict:"A",replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/progressBars/progressBars.html"}}]),angular.module("att.abs.radio",[]).constant("attRadioConfig",{activeClass:"att-radio--on",disabledClass:"att-radio--disabled"}).directive("attRadio",["$compile","attRadioConfig",function(a,b){return{scope:{},restrict:"A",require:"ngModel",link:function(c,d,e,f){var g=f;c.radioVal="";var h=angular.element('<div att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>');d.attr("value",e.attRadio),d.removeAttr("att-radio"),d.removeAttr("title"),d.attr("ng-model","radioVal"),h.append(d.prop("outerHTML")),h.append('<div class="att-radio__indicator"></div>'),h.attr("title",e.title);var i=h.prop("outerHTML");i=a(i)(c),d=d.replaceWith(i);var j=i.find("input");j.on("focus",function(){i.css("outline","thin dotted #333"),i.css("outline","-webkit-focus-ring-color auto 5px")}),j.on("blur",function(){i.css("outline","none")}),g.$render=function(){c.radioVal=g.$modelValue;var a=angular.equals(g.$modelValue,e.attRadio);i.toggleClass(b.activeClass,a)},c.updateModel=function(){j[0].focus();var a=i.hasClass(b.activeClass);a||c.disabled||(g.$setViewValue(a?null:e.attRadio),g.$render())},e.$observe("disabled",function(a){c.disabled=a||"disabled"===a||"true"===a,c.disabled&&(i.addClass(b.disabledClass),i.attr("tabindex","-1"))})}}}]),angular.module("att.abs.scrollbar",["att.abs.position"]).constant("attScrollbarConstant",{defaults:{axis:"y",navigation:!1,wheel:!0,wheelSpeed:40,wheelLock:!0,scrollInvert:!1,trackSize:!1,thumbSize:!1,alwaysVisible:!0}}).directive("attScrollbar",["$window","$timeout","$parse","$animate","attScrollbarConstant","$position",function(a,b,c,d,e,f){return{restrict:"A",scope:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",controller:["$scope","$element","$attrs",function(g,h,i){function j(){w.contentRatio<=1&&w.contentPosition>w.contentSize-w.viewportSize?w.contentPosition=w.contentSize-w.viewportSize:w.contentRatio>1&&w.contentPosition>0&&(w.contentPosition=0),w.contentPosition<=0?g.prevAvailable=!1:g.prevAvailable=!0,w.contentPosition>=w.contentSize-w.viewportSize?g.nextAvailable=!1:g.nextAvailable=!0}function k(){F?(z.on("touchstart",m),C.on("touchstart",m)):(C.on("mousedown",n),B.on("mousedown",r)),angular.element(a).on("resize",l),w.options.wheel&&h.on(G,o)}function l(){w.update()}function m(a){1===a.touches.length&&(a.stopPropagation(),n(a.touches[0]))}function n(a){x.addClass("scroll-no-select"),h.addClass("scroll-no-select"),w.options.alwaysVisible||B.addClass("visible"),D=E?a.clientX:a.clientY,w.thumbPosition=parseInt(C.css(J),10)||0,F?(L=!1,K=!1,z.on("touchmove",p),z.on("touchend",s),C.on("touchmove",q),C.on("touchend",s)):(y.on("mousemove",r),y.on("mouseup",s),C.on("mouseup",s))}function o(c){if(!(w.contentRatio>=1)){w.options.alwaysVisible||(v&&b.cancel(v),B.addClass("visible"),v=b(function(){B.removeClass("visible")},100));var d=c&&c.originalEvent||c||a.event,e=w.options.axis.toUpperCase(),f={X:d.deltaX||0,Y:d.deltaY||0},i=0===d.deltaMode?w.options.wheelSpeed:1;w.options.scrollInvert&&(i*=-1),"mousewheel"===G&&(f.Y=-1*d.wheelDelta/40,d.wheelDeltaX&&(f.X=-1*d.wheelDeltaX/40)),f.X*=-1/i,f.Y*=-1/i;var k=f[e];w.contentPosition-=k*w.options.wheelSpeed,w.contentPosition=Math.min(w.contentSize-w.viewportSize,Math.max(0,w.contentPosition)),fireEvent(h[0],"move"),j(),C.css(J,w.contentPosition/w.trackRatio+"px"),A.css(J,-w.contentPosition+"px"),(w.options.wheelLock||w.contentPosition!==w.contentSize-w.viewportSize&&0!==w.contentPosition)&&d.preventDefault(),g.$apply()}}function p(a){a.preventDefault(),L=!0,r(a.touches[0])}function q(a){a.preventDefault(),K=!0,r(a.touches[0])}function r(a){if(!(w.contentRatio>=1)){var b=E?a.clientX:a.clientY,c=b-D;(w.options.scrollInvert&&!F||F&&!w.options.scrollInvert)&&(c=D-b),L&&F&&(c=D-b),K&&F&&(c=b-D);var d=Math.min(w.trackSize-w.thumbSize,Math.max(0,w.thumbPosition+c));w.contentPosition=d*w.trackRatio,fireEvent(h[0],"move"),j(),C.css(J,d+"px"),A.css(J,-w.contentPosition+"px"),g.$apply()}}function s(){x.removeClass("scroll-no-select"),h.removeClass("scroll-no-select"),w.options.alwaysVisible||B.removeClass("visible"),y.off("mousemove",r),y.off("mouseup",s),C.off("mouseup",s),y.off("touchmove",p),y.off("ontouchend",s),C.off("touchmove",q),C.off("touchend",s)}var t={axis:i.attScrollbar||e.defaults.axis,navigation:i.navigation||e.defaults.navigation,wheel:e.defaults.wheel,wheelSpeed:e.defaults.wheelSpeed,wheelLock:e.defaults.wheelLock,scrollInvert:e.defaults.scrollInvert,trackSize:e.defaults.trackSize,thumbSize:e.defaults.thumbSize,alwaysVisible:e.defaults.alwaysVisible},u=i.scrollbar;u=u?c(u)(g):{},this.options=angular.extend({},t,u),this._defaults=t;var v,w=this,x=angular.element(document.querySelectorAll("body")[0]),y=angular.element(document),z=angular.element(h[0].querySelectorAll(".scroll-viewport")[0]),A=angular.element(h[0].querySelectorAll(".scroll-overview")[0]),B=angular.element(h[0].querySelectorAll(".scroll-bar")[0]),C=angular.element(h[0].querySelectorAll(".scroll-thumb")[0]),D=0,E="x"===this.options.axis,F=!1,G="onwheel"in document?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll",H=E?"width":"height",I=H.charAt(0).toUpperCase()+H.slice(1).toLowerCase(),J=E?"left":"top",K=!1,L=!1;("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)&&(F=!0),this.contentPosition=0,this.viewportSize=0,this.contentSize=0,this.contentRatio=0,this.trackSize=0,this.trackRatio=0,this.thumbSize=0,this.thumbPosition=0,this.initialize=function(){return this.options.alwaysVisible||B.css("opacity",0),w.update(),k(),w},this.setSizeData=function(){this.viewportSize=z.prop("offset"+I)||1,this.contentSize=A.prop("scroll"+I)||1,this.contentRatio=this.viewportSize/this.contentSize,this.trackSize=this.options.trackSize||this.viewportSize,this.thumbSize=Math.min(this.trackSize,Math.max(0,this.options.thumbSize||this.trackSize*this.contentRatio)),this.trackRatio=this.options.thumbSize?(this.contentSize-this.viewportSize)/(this.trackSize-this.thumbSize):this.contentSize/this.trackSize},this.update=function(a){return w.setSizeData(),D=B.prop("offsetTop"),B.toggleClass("disable",this.contentRatio>=1||isNaN(this.contentRatio)),!this.options.alwaysVisible&&this.contentRatio<1&&this.viewportSize>0&&d.addClass(B,"visible").then(function(){d.removeClass(B,"visible"),g.$digest()}),null!==a&&("bottom"===a?this.contentPosition=this.contentSize-this.viewportSize:this.contentPosition=parseInt(a,10)||0),j(),C.css(J,w.contentPosition/w.trackRatio+"px"),B.css(H,w.trackSize+"px"),C.css(H,w.thumbSize+"px"),A.css(J,-w.contentPosition+"px"),this},fireEvent=function(a,b){var c,d=a;document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(b,!0,!1),d.dispatchEvent(c)):document.createEventObject&&(c=document.createEventObject(),d.fireEvent("on"+b,c))},g.customScroll=function(a){if(!(w.contentRatio>=1)){var b,c=f.position(z);b=E?c.width:c.height,a?w.contentPosition+=b:w.contentPosition-=b,w.contentPosition=Math.min(w.contentSize-w.viewportSize,Math.max(0,w.contentPosition)),fireEvent(h[0],"move"),j(),C.css(J,w.contentPosition/w.trackRatio+"px"),A.css(J,-w.contentPosition+"px")}},this.cleanup=function(){z.off("touchstart",m),C.off("mousedown",n),B.off("mousedown",r),C.off("touchmove",q),C.off("touchend",s),angular.element(a).off("resize",l),h.off(G,o),w.options.alwaysVisible=!0,s()}}],link:function(a,c,d,e){a.navigation=e.options.navigation,a.viewportHeight=d.viewportHeight,a.viewportWidth=d.viewportWidth,a.scrollbarAxis=e.options.axis,"x"===a.scrollbarAxis?c.addClass("horizontal"):"y"===a.scrollbarAxis&&c.addClass("vertical");var f=c.css("position");"relative"!==f&&"absolute"!==f&&c.css("position","relative"),a.$watch(function(){b(g,100,!1)});var g=function(){var b=angular.element(c[0].querySelectorAll(".scroll-overview")[0]),d=b.prop("scrollHeight"),f=a.oldValue;d!==f&&(a.oldValue=d,e.update())};e.initialize(),c.on("$destroy",function(){e.cleanup()})}}}]),angular.module("att.abs.search",["att.abs.utilities","att.abs.position","att.abs.utilities"]).directive("attSearch",["$document","$filter","$isElement","$documentBind","$timeout","$log","keymap",function(a,b,c,d,e,f,g){return{restrict:"A",scope:{cName:"=attSearch"},transclude:!1,replace:!1,require:"ngModel",templateUrl:"app/scripts/ng_js_att_tpls/search/search.html",link:function(b,h,i,j){b.selectedIndex=-1,b.selectedOption=i.placeholder,b.isDisabled=!1,b.className="select2-match",b.showSearch=!1,b.showlist=!1;var k="",l=new Date,m=void 0,n=[];e(function(){n=h.find("li")},10),f.warn("attSearch is deprecated, please use attSelect instead. This component will be removed by version 2.7."),i.noFilter||"true"===i.noFilter?b.noFilter=!0:b.noFilter=!1,"false"===i.placeholderAsOption?b.selectedOption=i.placeholder:b.selectMsg=i.placeholder,(i.startsWithFilter||"true"===i.startsWithFilter)&&(b.startsWithFilter=!0),"true"===i.showInputFilter&&(b.showSearch=!1,f.warn("showInputFilter functionality has been removed from the library.")),i.disabled&&(b.isDisabled=!0),m=angular.element(h).children().eq(0).find("a")[0];var o=0,p=function(){if(b.noFilter){var a=k,c=0;for(c=o;c<b.cName.length;c++)if(b.cName[c].title.startsWith(a)&&c!==b.selectedIndex){b.selectOption(b.cName[c],c,b.showlist),o=c,k="";break}(c>=b.cName.length||!b.cName[c+1].title.startsWith(a))&&o>0&&(o=0)}};b.showDropdown=function(){i.disabled||(b.showlist=!b.showlist,b.setSelectTop())},h.bind("keydown",function(a){if(g.isAllowedKey(a.keyCode)||g.isControl(a)||g.isFunctionKey(a))switch(a.preventDefault(),a.stopPropagation(),a.keyCode){case g.KEY.DOWN:b.selectNext();break;case g.KEY.UP:b.selectPrev(),k="";break;case g.KEY.ENTER:b.selectCurrent(),k="";break;case g.KEY.BACKSPACE:b.title="",k="",b.$apply();break;case g.KEY.SPACE:b.noFilter||(b.title+=" "),b.$apply();break;case g.KEY.ESC:""===b.title||void 0===b.title?(b.showlist=!1,m.focus(),b.$apply()):(b.title="",b.$apply()),b.noFilter&&(k="",m.focus(),b.showlist=!1)}else if(9!==a.keyCode){if(b.noFilter){var c=new Date,d=Math.abs(l.getMilliseconds()-c.getMilliseconds());l=c,d>100&&(k=""),k=k?k+String.fromCharCode(a.keyCode):String.fromCharCode(a.keyCode),k.length>2&&(k=k.substring(0,2)),p()}else b.showlist=!0,b.title=b.title?b.title+String.fromCharCode(a.keyCode):String.fromCharCode(a.keyCode);b.$apply()}else 9===a.keyCode&&(b.showlist=!1,b.title="",b.$apply())}),b.selectOption=function(a,c,d){-1===c||"-1"===c?(b.selCategory="",b.selectedIndex=-1,j.$setViewValue(""),"false"!==i.placeholderAsOption&&(b.selectedOption=b.selectMsg)):(b.selCategory=b.cName[c],b.selectedIndex=c,j.$setViewValue(b.selCategory),b.selectedOption=b.selCategory.title,angular.isDefined(n[c])&&n[c].focus()),b.title="",d||(b.showlist=!1,m.focus()),b.$apply()},b.selectCurrent=function(){b.showlist?(b.selectOption(b.selectMsg,b.selectedIndex,!1),b.$apply()):(b.showlist=!0,b.setSelectTop(),b.$apply())},b.hoverIn=function(a){b.selectedIndex=a,b.focusme()},b.setSelectTop=function(){e(function(){if(b.showlist&&!b.noFilter){var a=angular.element(h)[0].querySelector(".select2-results");if(angular.element(a.querySelector(".select2-result-current"))[0])var c=angular.element(a.querySelector(".select2-result-current"))[0].offsetTop;angular.element(a)[0].scrollTop=c}})},b.setCurrentTop=function(){e(function(){if(b.showlist){var a=angular.element(h)[0].querySelector(".select2-results");if(angular.element(a.querySelector(".hovstyle"))[0])var c=angular.element(a.querySelector(".hovstyle"))[0].offsetTop;c<angular.element(a)[0].scrollTop?angular.element(a)[0].scrollTop-=30:c+30>angular.element(a)[0].clientHeight&&(angular.element(a)[0].scrollTop+=30)}})},b.selectNext=function(){b.selectedIndex+1<=b.cName.length-1&&(b.selectedIndex+=1,b.showlist||b.selectOption(b.selectMsg,b.selectedIndex,!1),b.focusme(),b.$apply()),b.setCurrentTop()},b.selectPrev=function(){b.selectedIndex-1>=0?(b.selectedIndex-=1,b.showlist||b.selectOption(b.selectMsg,b.selectedIndex,!1),b.focusme(),b.$apply()):b.selectedIndex-1<0&&(void 0===i.placeholderAsOption||"true"===i.placeholderAsOption?b.selectedIndex=-1:b.selectedIndex=0,b.showlist||b.selectOption(b.selectMsg,b.selectedIndex,!1),b.focusme(),b.$apply()),b.setCurrentTop()},b.updateSelection=function(a){b.selectedOption=a.title,b.title=""},b.focusme=function(){e(function(){var a=angular.element(h).find("ul").find("li"),c=b.selectedIndex+2;b.noFilter&&(c=b.selectedIndex),angular.isDefined(a[c])&&a[c].focus()})},b.$watch("selCategory",function(a){a&&b.updateSelection(a)}),j.$viewChangeListeners.push(function(){b.$eval(i.ngChange)}),j.$render=function(){b.selCategory=j.$viewValue};var q=function(d){var e=c(angular.element(d.target),h,a);e||(b.showlist=!1,m.focus(),b.$apply())};d.click("showlist",q,b)}}}]),angular.module("att.abs.select",["att.abs.utilities","att.abs.position","att.abs.utilities"]).directive("attSelect",["$document","$filter","$isElement","$documentBind","$timeout","keymap","$log",function(a,b,c,d,e,f,g){return{restrict:"A",scope:{cName:"=attSelect"},transclude:!1,replace:!1,require:"ngModel",templateUrl:"app/scripts/ng_js_att_tpls/select/select.html",link:function(h,i,j,k){h.selectedIndex=-1,h.selectedOption=j.placeholder,h.isDisabled=!1,h.className="select2-match",h.showSearch=!1,h.showlist=!1;var l="",m=new Date,n=void 0,o=[];e(function(){o=i.find("li")},10),j.noFilter||"true"===j.noFilter?h.noFilter=!0:h.noFilter=!1,"false"===j.placeholderAsOption?h.selectedOption=j.placeholder:h.selectMsg=j.placeholder,(j.startsWithFilter||"true"===j.startsWithFilter)&&(h.startsWithFilter=!0),"true"===j.showInputFilter&&(h.showSearch=!1,g.warn("showInputFilter functionality has been removed from the library.")),j.disabled&&(h.isDisabled=!0);var p=function(){return h.startsWithFilter?"startsWith":"filter"};n=angular.element(i).children().eq(0).find("span")[0];var q=0,r=function(){if(h.noFilter){var a=l,b=0;for(b=q;b<h.cName.length;b++)if(h.cName[b].title.startsWith(a)&&b!==h.selectedIndex){
-h.selectOption(h.cName[b],b,h.showlist),q=b,l="";break}(b>=h.cName.length||!h.cName[b+1].title.startsWith(a))&&q>0&&(q=0)}};h.showDropdown=function(){j.disabled||(h.showlist=!h.showlist,h.setSelectTop(),h.focusme())},i.bind("keydown",function(a){if(f.isAllowedKey(a.keyCode)||f.isControl(a)||f.isFunctionKey(a))switch(a.preventDefault(),a.stopPropagation(),a.keyCode){case f.KEY.DOWN:h.selectNext();break;case f.KEY.UP:h.selectPrev(),l="";break;case f.KEY.ENTER:h.selectCurrent(),l="";break;case f.KEY.BACKSPACE:h.title="",l="",h.$apply();break;case f.KEY.SPACE:h.noFilter||(h.title+=" "),h.$apply();break;case f.KEY.ESC:""===h.title||void 0===h.title?(h.showlist=!1,n.focus(),h.$apply()):(h.title="",h.$apply()),h.noFilter&&(l="",n.focus(),h.showlist=!1)}else if(a.keyCode!==f.KEY.TAB){if(h.noFilter){var c=new Date,d=Math.abs(m.getMilliseconds()-c.getMilliseconds());m=c,d>100&&(l=""),l=l?l+String.fromCharCode(a.keyCode):String.fromCharCode(a.keyCode),l.length>2&&(l=l.substring(0,2)),r()}else if(h.showlist=!0,h.title=h.title?h.title+String.fromCharCode(a.keyCode):String.fromCharCode(a.keyCode),""!=h.title)for(var e=b(p())(h.cName,h.title),g=0;g<e.length;g++)for(var i=0;i<h.cName.length&&angular.isDefined(h.cName[h.selectedIndex]);i++)if(e[g].title===h.cName[h.selectedIndex].title){h.selectedIndex=g,h.focusme();break}h.$apply()}else a.keyCode===f.KEY.TAB&&(h.showlist=!1,h.title="",h.$apply())}),h.selectOption=function(a,c,d){if(-1===c||"-1"===c)h.selCategory="",h.selectedIndex=-1,k.$setViewValue(""),"false"!==j.placeholderAsOption&&(h.selectedOption=h.selectMsg);else{if(""!=h.title){var f=b(p())(h.cName,h.title);if(angular.isDefined(f)&&angular.isDefined(f[c]))for(var g=0;g<h.cName.length;g++)if(f[c].title===h.cName[g].title){c=g;break}}h.selCategory=h.cName[c],h.selectedIndex=c,k.$setViewValue(h.selCategory),h.selectedOption=h.selCategory.title,e(function(){if(angular.isDefined(o[c]))try{o[index].focus()}catch(a){}})}h.title="",d||(h.showlist=!1,n.focus())},h.selectCurrent=function(){h.showlist?h.selectOption(h.selectMsg,h.selectedIndex,!1):(h.showlist=!0,h.setSelectTop()),h.$apply()},h.hoverIn=function(a){h.selectedIndex=a,h.focusme()},h.setSelectTop=function(){e(function(){if(h.showlist&&!h.noFilter){var a=angular.element(i)[0].querySelector(".select2-results");if(angular.element(a.querySelector(".select2-result-current"))[0])var b=angular.element(a.querySelector(".select2-result-current"))[0].offsetTop;angular.element(a)[0].scrollTop=b}})},h.setCurrentTop=function(){e(function(){if(h.showlist){var a=angular.element(i)[0].querySelector(".select2-results");if(angular.element(a.querySelector(".hovstyle"))[0])var b=angular.element(a.querySelector(".hovstyle"))[0].offsetTop;b<angular.element(a)[0].scrollTop?angular.element(a)[0].scrollTop-=30:b+30>angular.element(a)[0].clientHeight&&(angular.element(a)[0].scrollTop+=30)}})},h.selectNext=function(){h.cName.length;if(h.selectedIndex+1<=h.cName.length-1){h.selectedIndex+=1;var a=h.cName[h.selectedIndex].disabled;a&&(h.selectedIndex+=1),h.showlist||h.selectOption(h.selectMsg,h.selectedIndex,!1),h.focusme(),h.$apply()}h.setCurrentTop()},h.selectPrev=function(){if(h.selectedIndex-1>=0){h.selectedIndex-=1;var a=h.cName[h.selectedIndex].disabled;a&&(h.selectedIndex-=1),h.showlist||h.selectOption(h.selectMsg,h.selectedIndex,!1),h.focusme(),h.$apply()}else h.selectedIndex-1<0&&(void 0===j.placeholderAsOption||"true"===j.placeholderAsOption?void 0===j.placeholder?h.selectedIndex=0:h.selectedIndex=-1:h.selectedIndex=0,h.showlist||h.selectOption(h.selectMsg,h.selectedIndex,!1),h.focusme(),h.$apply());h.setCurrentTop()},h.updateSelection=function(a){h.selectedOption=a.title,h.title="",a.index<0&&h.selectOption(h.selectMsg,a.index,h.showlist)},h.focusme=function(){e(function(){var a=angular.element(i).find("ul").find("li"),b=h.selectedIndex+2;if(h.noFilter&&(b=h.selectedIndex),angular.isDefined(a[b]))try{a[b].focus()}catch(c){}})},h.$watch("selCategory",function(a){a&&h.updateSelection(a)}),k.$viewChangeListeners.push(function(){h.$eval(j.ngChange)}),k.$render=function(){h.selCategory=k.$viewValue};var s=function(b){var d=c(angular.element(b.target),i,a);d||(h.showlist=!1,n.focus(),h.$apply())};d.click("showlist",s,h)}}}]).directive("textDropdown",["$document","$isElement","$documentBind","keymap",function(a,b,c,d){return{restrict:"EA",replace:!0,scope:{actions:"=actions",defaultAction:"=defaultAction",onActionClicked:"=?"},templateUrl:"app/scripts/ng_js_att_tpls/select/textDropdown.html",link:function(e,f,g){e.selectedIndex=0,e.selectedOption=g.placeholder,e.isDisabled=!1,e.isActionsShown=!1;var h=void 0;if(g.disabled&&(e.isDisabled=!0),h=f.find("div")[0],angular.isDefined(e.defaultAction))if(angular.isDefined(e.defaultAction)||""!==e.defaultAction){for(var i in e.actions)if(e.actions[i]===e.defaultAction){e.currentAction=e.actions[i],e.selectedIndex=e.actions.indexOf(i),e.isActionsShown=!1;break}}else e.currentAction=e.actions[0];else e.currentAction=e.actions[0],e.selectedIndex=0;e.toggle=function(){e.isActionsShown=!e.isActionsShown},e.chooseAction=function(a,b,c){null!=a?(e.currentAction=b,e.selectedIndex=c):e.currentAction=e.actions[e.selectedIndex],angular.isFunction(e.onActionClicked)&&e.onActionClicked(e.currentAction),e.toggle()},e.isCurrentAction=function(a){return a===e.currentAction},f.bind("keydown",function(a){if(d.isAllowedKey(a.keyCode)||d.isControl(a)||d.isFunctionKey(a)){switch(a.preventDefault(),a.stopPropagation(),a.keyCode){case d.KEY.DOWN:e.selectNext();break;case d.KEY.UP:e.selectPrev();break;case d.KEY.ENTER:e.selectCurrent();break;case d.KEY.ESC:e.isActionsShown=!1,h.focus(),e.$apply()}return void e.$apply()}a.keyCode===d.KEY.TAB&&(e.isActionsShown=!1,e.$apply())}),e.selectCurrent=function(){e.selectedIndex<0&&(e.selectedIndex=0),e.isActionsShown?e.chooseAction(null,e.currentAction):e.toggle()},e.selectNext=function(){e.isActionsShown&&(e.selectedIndex+1<e.actions.length?e.selectedIndex+=1:e.selectedIndex=e.actions.length-1,e.$apply())},e.selectPrev=function(){e.isActionsShown&&(e.selectedIndex-1>=0?e.selectedIndex-=1:e.selectedIndex-1<0&&(e.selectedIndex=0),e.$apply())},e.hoverIn=function(a){e.selectedIndex=a};var j=function(c){var d=b(angular.element(c.target),f,a);d||(e.toggle(),e.$apply())};c.click("isActionsShown",j,e)}}}]),angular.module("att.abs.slider",["att.abs.position"]).constant("sliderDefaultOptions",{width:300,step:1,precision:0,disabledWidth:116}).directive("attSlider",["sliderDefaultOptions","$position","$document",function(a,b,c){return{restrict:"EA",replace:!0,transclude:!0,scope:{floor:"=",ceiling:"=",step:"@",precision:"@",width:"@",textDisplay:"=",value:"=",ngModelSingle:"=?",ngModelLow:"=?",ngModelHigh:"=?",ngModelDisabled:"=?"},templateUrl:"app/scripts/ng_js_att_tpls/slider/slider.html",link:function(d,e,f){var g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y=0,z=!1;d.minPtrOffset=0,d.maxPtrOffset=0;var A=a.disabledWidth,B=e.children();n=B[0].children,n=angular.element(n[0]),x=B[1].children,w=angular.element(x[0]),v=angular.element(x[1]),u=angular.element(x[2]),o=null==f.ngModelSingle&&null==f.ngModelLow&&null==f.ngModelHigh&&null!=f.ngModelDisabled,r=null==f.ngModelSingle&&null!=f.ngModelLow&&null!=f.ngModelHigh,s="ngModelLow",t="ngModelHigh",r?w.remove():(v.remove(),u.remove()),o?(d.disabledStyle={width:A+"px",zIndex:1},d.handleStyle={left:A+"px"}):n.remove(),p=parseFloat(d.floor),q=parseFloat(d.ceiling),m=q-p,g=0,h=void 0!==f.width?f.width:0!==e[0].clientWidth?e[0].clientWidth:a.width,l=h-g,d.keyDown=function(c){if(39===c.keyCode){var f=b.position(e).left;if(i)"ngModelLow"===d.ref?(j=a.step+j,i=j):"ngModelHigh"===d.ref?(k=a.step+k,i=k):i=a.step+i;else{if(r&&"ngModelLow"===d.ref)return;i=a.step+f,j=k=i}}else if(37===c.keyCode){var g=b.position(w).left;i?0>=i||("ngModelLow"===d.ref?(j-=a.step,i=j):"ngModelHigh"===d.ref?(k-=a.step,i=k):(i-=a.step,j=k=i)):i=g-a.step}i>=0&&d.ptrOffset(i)},d.mouseDown=function(a,b){d.ref=b,z=!0,y=r?d.ref===s?a.clientX-d.minPtrOffset:a.clientX-d.maxPtrOffset:i?a.clientX-i:a.clientX,o&&(d.ref="ngModelDisabled",d.disabledStyle={width:A+"px",zIndex:1})},d.moveElem=function(a){if(z){var b;b=a.clientX,i=b-y,d.ptrOffset(i)}},d.focus=function(a,b){console.log(b),d.ref=b},d.mouseUp=function(a){z=!1,v.removeClass("dragging"),u.removeClass("dragging"),w.removeClass("dragging"),c.off("mousemove")},d.keyUp=function(a){z=!1,v.removeClass("dragging"),u.removeClass("dragging"),w.removeClass("dragging"),c.off("mousemove")},d.calStep=function(a,b,c,d){var e,f,g,h;return null===d&&(d=0),null===c&&(c=1/Math.pow(10,b)),f=(a-d)%c,h=f>c/2?a+c-f:a-f,e=Math.pow(10,b),g=h*e/e,g.toFixed(b)},d.percentOffset=function(a){return(a-g)/l*100},d.ptrOffset=function(b){var c,e;if(b=Math.max(Math.min(b,h),g),c=d.percentOffset(b),e=p+m*c/100,r){var f;d.ref===s?(d.minHandleStyle={left:b+"px"},d.minNewVal=e,d.minPtrOffset=b,v.addClass("dragging"),e>d.maxNewVal&&(d.ref=t,u[0].focus(),d.maxNewVal=e,d.maxPtrOffset=b,u.addClass("dragging"),v.removeClass("dragging"),d.maxHandleStyle={left:b+"px"})):(d.maxHandleStyle={left:b+"px"},d.maxNewVal=e,d.maxPtrOffset=b,u.addClass("dragging"),e<d.minNewVal&&(d.ref=s,v[0].focus(),d.minVal=e,d.minPtrOffset=b,v.addClass("dragging"),u.removeClass("dragging"),d.minHandleStyle={left:b+"px"})),f=parseInt(d.maxPtrOffset)-parseInt(d.minPtrOffset),d.rangeStyle={width:f+"px",left:d.minPtrOffset+"px"}}else o&&b>A?d.rangeStyle={width:b+"px",zIndex:0}:(w.addClass("dragging"),d.rangeStyle={width:b+"px"}),d.handleStyle={left:b+"px"};(void 0===d.precision||void 0===d.step)&&(d.precision=a.precision,d.step=a.step),e=d.calStep(e,parseInt(d.precision),parseFloat(d.step),parseFloat(d.floor)),d[d.ref]=e}}}}]).directive("attSliderMin",[function(){return{require:"^attSlider",restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/slider/minContent.html"}}]).directive("attSliderMax",[function(){return{require:"^attSlider",restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/slider/maxContent.html"}}]),angular.module("att.abs.splitButtonDropdown",["att.abs.utilities","att.abs.position"]).directive("attButtonDropdown",["$document","$parse","$documentBind","$timeout","$isElement",function(a,b,c,d,e){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",scope:{btnText:"@",btnType:"@",btnLink:"@",btnClick:"&",toggleTitle:"@"},controller:["$scope","$element",function(a,b){this.cSelected=0,this.closeAndFocusDropdown=function(){a.isDropDownOpen&&a.$apply(function(){a.isDropDownOpen=!1,angular.element(b[0].querySelector("a.dropdown-toggle"))[0].focus()})},this.focusNext=function(){this.cSelected=this.cSelected+1>=this.childScopes.length?a.cycleSelection===!0?0:this.childScopes.length-1:this.cSelected+1,this.childScopes[this.cSelected].sFlag=!0,this.resetFlag(this.cSelected)},this.focusPrev=function(){this.cSelected=this.cSelected-1<0?a.cycleSelection===!0?this.childScopes.length-1:0:this.cSelected-1,this.childScopes[this.cSelected].sFlag=!0,this.resetFlag(this.cSelected)},this.childScopes=[],this.registerScope=function(a){this.childScopes.push(a)},this.resetFlag=function(a){for(var b=0;b<this.childScopes.length;b++)b!==a&&(this.childScopes[b].sFlag=!1)}}],link:function(f,g,h){f.isSmall=""===h.small?!0:!1,f.multiselect=""===h.multiselect?!0:!1,f.cycleSelection=""===h.cycleSelection?!0:!1,f.isDropDownOpen=!1,f.isActionDropdown=!1,f.btnText||(f.isActionDropdown=!0),f.clickFxn=function(){"function"!=typeof f.btnClick||f.btnLink||(f.btnClick=b(f.btnClick),f.btnClick()),f.multiselect===!0&&(f.isDropDownOpen=!1)},f.toggleDropdown=function(){"disabled"!==f.btnType&&(f.isDropDownOpen=!f.isDropDownOpen,f.isDropDownOpen&&d(function(){angular.element(g[0].querySelector("li"))[0].focus()}))},f.btnTypeSelector=function(a,b){""!==a?f.btnTypeFinal=a:f.btnTypeFinal=b};var i=function(b){var c=e(angular.element(b.target),g.find("ul").eq(0),a);c||(f.isDropDownOpen=!1,f.$apply())};c.click("isDropDownOpen",i,f),h.$observe("btnType",function(a){f.btnType=a}),h.$observe("attButtonDropdown",function(a){h.attButtonDropdown=a,f.btnTypeSelector(h.attButtonDropdown,f.btnType)})}}}]).directive("attButtonDropdownItem",["$location","keymap",function(a,b){return{restrict:"EA",require:["^attButtonDropdown","?ngModel"],replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",scope:{itemLink:"@"},link:function(a,c,d,e){angular.element(c[0].querySelector("a"));a.sFlag=!1,e[0].registerScope(a);e[1]?a.isSelected=e[1].$viewValue:a.isSelected=!1,c.bind("keydown",function(c){if(b.isAllowedKey(c.keyCode)||b.isControl(c)||b.isFunctionKey(c))switch(c.preventDefault(),c.stopPropagation(),c.keyCode){case b.KEY.DOWN:e[0].focusNext();break;case b.KEY.UP:e[0].focusPrev();break;case b.KEY.ENTER:a.selectItem();break;case b.KEY.ESC:e[0].closeAndFocusDropdown()}a.$apply()}),a.selectItem=function(){e[1]&&a.$evalAsync(function(){e[1].$setViewValue(!e[1].$viewValue)})}}}}]),angular.module("att.abs.splitIconButton",["att.abs.utilities"]).constant("iconStateConstants",{MIDDLE:"middle",LEFT:"left",RIGHT:"right",NEXT_TO_DROPDOWN:"next-to-dropdown",LEFT_NEXT_TO_DROPDOWN:"left-next-to-dropdown",DIR_TYPE:{LEFT:"left",RIGHT:"right",BUTTON:"button"},SPLIT_ICON_BTN_EVENT_EMITTER_KEY:"splitIconButtonTap"}).directive("expandableLine",[function(){return{restrict:"EA",replace:!0,priority:300,require:["^attSplitIconButton","expandableLine"],controller:["$scope",function(a){a.isActive=!1,this.setActiveState=function(b){a.isActive=b},this.isActive=a.isActive,this.dirType=a.dirType}],template:"<div ng-class=\"{'expand-line-container': !isActive, 'expand-line-container-active': isActive}\"> <div ng-class=\"{'hovered-line':isActive, 'vertical-line':!isActive}\"> </div></div>",scope:{dirType:"@"},link:function(a,b,c,d){var e=d[0],f=d[1];e.addSubCtrl(f)}}}]).controller("AttSplitIconCtrl",["$scope",function(a){this.setType=function(b){a.type=b},this.isDropdown=function(b){a.isDropdown=b},this.dropDownClicked=function(){a.dropDownClicked&&a.dropDownClicked()},this.dirType=a.dirType}]).directive("attSplitIcon",["$document","$timeout","iconStateConstants","$documentBind","events","keymap",function(a,b,c,d,e,f){return{restrict:"EA",replace:!0,priority:200,transclude:!0,require:["^attSplitIconButton","attSplitIcon"],templateUrl:"app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",scope:{icon:"@",iconTitle:"@title",hoverWatch:"=",dropDownWatch:"=",dirType:"@"},controller:"AttSplitIconCtrl",link:function(a,b,g,h){var i=h[0],j=h[1];i.addSubCtrl(j),a.iconStateConstants=c;var k,l=0,m=!1;a.isDropdown=!1,a.isDropdownOpen=!1;var n=function(b){a.isDropdown&&(m?(m=!1,a.toggleDropdown()):a.toggleDropdown(!1),a.$apply())};g.dropDownId&&""!==g.dropDownId&&(a.dropDownId=g.dropDownId,a.isDropdown=!0),a.$on(c.SPLIT_ICON_BTN_EVENT_EMITTER_KEY,function(c,d){function g(b){switch(b.which){case f.KEY.TAB:a.toggleDropdown(!1),a.$digest();break;case f.KEY.ESC:n();break;case f.KEY.ENTER:a.isDropDownOpen&&h();break;case f.KEY.UP:b.preventDefault(),e.stopPropagation(b),a.isDropDownOpen&&a.previousItemInDropdown();break;case f.KEY.DOWN:b.preventDefault(),e.stopPropagation(b),a.isDropDownOpen?a.nextItemInDropdown():(m=!0,n(),h())}}function h(){if(void 0===k){k=[];for(var a=b.find("li"),c=0;c<a.length;c++)k.push(a.eq(c));k[l].children().eq(0).addClass("selected-item")}}if("boolean"==typeof d&&d)a.dropDownClicked(),a.isDropDownOpen&&k[l].eq(0).find("a")[0].click();else{var i=d;a.isDropdown&&g(i)}}),a.nextItemInDropdown=function(){k&&l<k.length-1&&(l++,k[l-1].children().eq(0).removeClass("selected-item"),k[l].children().eq(0).addClass("selected-item"))},a.previousItemInDropdown=function(){l>0&&(l--,k[l].children().eq(0).addClass("selected-item"),l+1<k.length&&k[l+1].children().eq(0).removeClass("selected-item"))},a.$watch("isIconHovered",function(b){a.hoverWatch=b}),a.$watch("type",function(b){function c(b,c,d,e,f){a.isMiddle=b,a.isNextToDropDown=c,a.isRight=d,a.isLeft=e,a.isLeftNextDropdown=f}switch(b){case a.iconStateConstants.MIDDLE:c(!0,!1,!1,!0,!1);break;case a.iconStateConstants.LEFT:c(!1,!1,!1,!0,!1);break;case a.iconStateConstants.RIGHT:c(!1,!1,!0,!1,!1);break;case a.iconStateConstants.NEXT_TO_DROPDOWN:c(!1,!0,!0,!0,!1);break;case a.iconStateConstants.LEFT_NEXT_TO_DROPDOWN:c(!1,!1,!1,!0,!0)}}),a.dropDownClicked=function(){m=!0},a.toggleDropdown=function(b){void 0!==b?a.isDropDownOpen=b:a.isDropDownOpen=!a.isDropDownOpen,a.dropDownWatch=a.isDropDownOpen},d.click("isDropdown",n,a)}}}]).controller("AttSplitIconButtonCtrl",["$scope","iconStateConstants",function(a,b){function c(a){var b=-1;for(var c in d.subCtrls){var e=d.subCtrls[c];if(e.dirType===a){b=c;break}}return b}this.subCtrls=[],a.isLeftLineShown=!0,a.isRightLineShown=!0,a.childrenScopes=[];var d=this;this.addSubCtrl=function(a){this.subCtrls.push(a)},this.isLeftLineShown=function(b){return void 0===b?a.isLeftLineShown:void(a.isLeftLineShown=b)},this.isRightLineShown=function(b){return void 0===b?a.isRightLineShown:void(a.isRightLineShown=b)},this.setLeftLineHover=function(d){var e=c(b.DIR_TYPE.LEFT);a.isLeftLineShown&&this.subCtrls[e]&&this.subCtrls[e].setActiveState&&this.subCtrls[e].setActiveState(d)},this.setRightLineHover=function(d){var e=c(b.DIR_TYPE.RIGHT);a.isRightLineShown&&this.subCtrls[e]&&this.subCtrls[e].setActiveState&&this.subCtrls[e].setActiveState(d)},this.toggleLines=function(d,e,f,g){function h(){for(var a=0;j>a;a++)if(i[a]===f){j-1>=a+1&&i[a+1].isLeftLineShown()&&i[a+1].subCtrls[k]&&i[a+1].subCtrls[k].setActiveState&&i[a+1].subCtrls[k].setActiveState(d),a-1>=0&&i[a-1].isRightLineShown()&&i[a-1].subCtrls[l]&&i[a-1].subCtrls[l].setActiveState&&i[a-1].subCtrls[l].setActiveState(d);break}}var i=e.subIconButtons,j=i.length,k=c(b.DIR_TYPE.LEFT),l=c(b.DIR_TYPE.RIGHT);g?i[j-2]==f?i[j-2].isLeftLineShown()?i[j-2].subCtrls[k].setActiveState(d):j-3>=0&&i[j-3].isRightLineShown()&&i[j-3].subCtrls[l].setActiveState(d):(h(),a.isLeftLineShown&&this.subCtrls[k].setActiveState(d),a.isRightLineShown&&this.subCtrls[l].setActiveState(d)):(a.isLeftLineShown||a.isRightLineShown||h(),a.isLeftLineShown&&this.subCtrls[k].setActiveState&&this.subCtrls[k].setActiveState(d),a.isRightLineShown&&this.subCtrls[l].setActiveState&&this.subCtrls[l].setActiveState(d))},this.setButtonType=function(a){var d=c(b.DIR_TYPE.BUTTON);this.subCtrls[d]&&this.subCtrls[d].setType&&this.subCtrls[d].setType(a)}}]).directive("attSplitIconButton",["$document","iconStateConstants","keymap",function(a,b,c){return{restrict:"EA",replace:!0,priority:100,transclude:!0,require:["^attSplitIconButtonGroup","attSplitIconButton"],controller:"AttSplitIconButtonCtrl",templateUrl:"app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",scope:{icon:"@",title:"@",dropDownId:"@"},link:function(a,d,e,f){a.title||(a.title=a.icon);var g=f[0],h=f[1];g.addIconButton(h),d.bind("keydown",function(d){(d.which===c.KEY.ESC||d.which===c.KEY.DOWN||d.which===c.KEY.ENTER||d.which===c.KEY.UP||d.which===c.KEY.TAB)&&(a.clickHandler(),a.$broadcast(b.SPLIT_ICON_BTN_EVENT_EMITTER_KEY,d))}),a.dropDownWatch=!1,a.iconStateConstants=b,a.clickHandler=function(){g.hideLeftLineRightButton(h)},a.$watch("isHovered",function(a){a?h.toggleLines(a,g,h,g.isDropDownOpen):h.toggleLines(a,g,h,g.isDropDownOpen)}),a.$watch("dropDownWatch",function(a){g.isDropDownOpen=a,g.toggleDropdownState(a)})}}}]).controller("AttSplitIconButtonGroupCtrl",["$scope","iconStateConstants",function(a,b){this.subIconButtons=[],this.addIconButton=function(a){this.subIconButtons.push(a)},this.isDropDownOpen=!1,this.hideLeftLineRightButton=function(a){var b=this.subIconButtons.length,c=this.subIconButtons[b-2],d=this.subIconButtons[b-1];a!=c&&a!=d&&d.setLeftLineHover(!1)},this.toggleDropdownState=function(a){var c=this.subIconButtons.length;c>2?a?(this.subIconButtons[c-2].isRightLineShown()?this.subIconButtons[c-2].setRightLineHover(!0):this.subIconButtons[c-1].setLeftLineHover(!0),this.subIconButtons[c-2].setButtonType(b.NEXT_TO_DROPDOWN)):(this.subIconButtons[c-1].setLeftLineHover(!1),this.subIconButtons[c-2].setButtonType(b.MIDDLE)):a?(this.subIconButtons[0].setRightLineHover(!0),this.subIconButtons[0].setButtonType(b.LEFT_NEXT_TO_DROPDOWN)):this.subIconButtons[0].setButtonType(b.LEFT)}}]).directive("attSplitIconButtonGroup",["$document","$timeout","iconStateConstants",function(a,b,c){return{restrict:"EA",replace:!0,priority:50,transclude:!0,require:"attSplitIconButtonGroup",controller:"AttSplitIconButtonGroupCtrl",templateUrl:"app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",scope:{},link:function(a,d,e,f){function g(){var a=f.subIconButtons,b=0,e=a.length-1;if(a[b].setButtonType(c.LEFT),a[b].isLeftLineShown(!1),a[b].isRightLineShown(!0),a[e].setButtonType(c.RIGHT),a[e].isRightLineShown(!1),a[e].isLeftLineShown(!1),e>=2){for(var g=1;e>g;)a[g].setButtonType(c.MIDDLE),a[g].isRightLineShown(!1),a[g].isLeftLineShown(!1),g++;for(var h=2;e>=h;)h==e?a[h].isLeftLineShown(!0):(a[h].isRightLineShown(!0),a[h].isLeftLineShown(!0)),h+=2}var i=d.find("ul");if(i.length>0){var j=e+1;if(j>2){var k=34*j-70+j/1.5+.5,l=k+"px";angular.element(i).css("left",l),angular.element(i).css("border-top-left-radius","0px")}else angular.element(i).css("left","0px")}}b(g,100)}}}]),angular.module("att.abs.stepSlider",["att.abs.position"]).constant("sliderConstants",{SLIDER:{settings:{from:1,to:40,step:1,smooth:!0,limits:!0,value:"3",dimension:"",vertical:!1},className:"jslider",selector:".jslider-"},EVENTS:{},COLORS:{GREEN:"green",BLUE_HIGHLIGHT:"blue",MAGENTA:"magenta",GOLD:"gold",PURPLE:"purple",DARK_BLUE:"dark-blue",REGULAR:"regular",WHITE:"white"}}).factory("utils",function(){return{offset:function(a){var b=a[0],c=0,d=0,e=document.documentElement||document.body,f=window.pageXOffset||e.scrollLeft,g=window.pageYOffset||e.scrollTop;return c=b.getBoundingClientRect().left+f,d=b.getBoundingClientRect().top+g,{left:c,top:d}},roundUpToScale:function(a,b,c,d){function e(a,b){var c=.1;return Math.abs(b-a)<=c?!0:!1}for(var f,g,h,i,j=1;j<b.length;j++){if(f=b[j-1],g=b[j],i=.5*(g-f)+f,0===f&&i>=a||e(f,a)){h=f;break}if(a>f&&(g>a||e(a,g))){h=g;break}}return c&&c>h?b[d]:h},valueForDifferentScale:function(a,b,c,d){var e=c/100;return 0===e?a:d[c]},convertToMbpsGbps:function(a,b,c){function d(a,b){var c=Math.pow(10,b);return~~(a*c)/c}var e=3;return c&&(e=c),a>1024&&1e6>a&&angular.equals(b,"Kbps")?(a=d(a/1e3,e),b="Mbps"):a>1024&&1e6>a&&angular.equals(b,"Mbps")?(a=d(a/1e3,e),b="Mbps"):b=(1024>=a&&angular.equals(b,"Mbps"),"Kbps"),a>=1e6&&angular.equals(b,"Kbps")&&(a=d(a/1e6,e),b="Gbps"),{unitValue:a,unitLabel:b}},getConversionFactorValue:function(a,b,c){if(a<=b[0].startVal)return{scaledVal:a,scaledDimension:c};var d=0;for(var e in b){var f=b[e];a>f.startVal&&(d=e)}var g=b[d].scaleFactor,h=a/g,i=b[d].dimension;return{scaledVal:h,scaledDimension:i}}}}).factory("sliderDraggable",["utils",function(a){function b(){this._init.apply(this,arguments)}return b.prototype.oninit=function(){},b.prototype.events=function(){},b.prototype.onmousedown=function(){this.ptr.css({position:"absolute"})},b.prototype.onmousemove=function(a,b,c){this.ptr.css({left:b,top:c})},b.prototype.onmouseup=function(){},b.prototype.isDefault={drag:!1,clicked:!1,toclick:!0,mouseup:!1},b.prototype._init=function(){if(arguments.length>0){if(this.ptr=arguments[0],this.parent=arguments[2],!this.ptr)return;this.is={},angular.extend(this.is,this.isDefault);var b=a.offset(this.ptr);this.d={left:b.left,top:b.top,width:this.ptr[0].clientWidth,height:this.ptr[0].clientHeight},this.oninit.apply(this,arguments),this._events()}},b.prototype._getPageCoords=function(a){var b={};return b=a.targetTouches&&a.targetTouches[0]?{x:a.targetTouches[0].pageX,y:a.targetTouches[0].pageY}:{x:a.pageX,y:a.pageY}},b.prototype._bindEvent=function(a,b,c){this.supportTouches_?a[0].attachEvent(this.events_[b],c):a.bind&&a.bind(this.events_[b],c)},b.prototype._events=function(){var a=this;this.supportTouches_="ontouchend"in document,this.events_={click:this.supportTouches_?"touchstart":"click",down:this.supportTouches_?"touchstart":"mousedown",move:this.supportTouches_?"touchmove":"mousemove",up:this.supportTouches_?"touchend":"mouseup",mousedown:(this.supportTouches_,"mousedown")};var b=angular.element(window.document);this._bindEvent(b,"move",function(b){a.is.drag&&(b.stopPropagation(),b.preventDefault(),a.parent.disabled||a._mousemove(b))}),this._bindEvent(b,"down",function(b){a.is.drag&&(b.stopPropagation(),b.preventDefault())}),this._bindEvent(b,"up",function(b){a._mouseup(b)}),this._bindEvent(this.ptr,"down",function(b){return a._mousedown(b),!1}),this._bindEvent(this.ptr,"up",function(b){a._mouseup(b)}),this.events()},b.prototype._mousedown=function(a){this.is.drag=!0,this.is.clicked=!1,this.is.mouseup=!1;var b=this._getPageCoords(a);this.cx=b.x-this.ptr[0].offsetLeft,this.cy=b.y-this.ptr[0].offsetTop,angular.extend(this.d,{left:this.ptr[0].offsetLeft,top:this.ptr[0].offsetTop,width:this.ptr[0].clientWidth,height:this.ptr[0].clientHeight}),this.outer&&this.outer.get(0)&&this.outer.css({height:Math.max(this.outer.height(),$(document.body).height()),overflow:"hidden"}),this.onmousedown(a)},b.prototype._mousemove=function(a){if(0!==this.uid){this.is.toclick=!1;var b=this._getPageCoords(a);this.onmousemove(a,b.x-this.cx,b.y-this.cy)}},b.prototype._mouseup=function(a){this.is.drag&&(this.is.drag=!1,this.outer&&this.outer.get(0)&&($.browser.mozilla?this.outer.css({overflow:"hidden"}):this.outer.css({overflow:"visible"}),$.browser.msie&&"6.0"===$.browser.version?this.outer.css({height:"100%"}):this.outer.css({height:"auto"})),this.onmouseup(a))},b}]).factory("sliderPointer",["sliderDraggable","utils",function(a,b){function c(){a.apply(this,arguments)}return c.prototype=new a,c.prototype.oninit=function(a,b,c){this.uid=b,this.parent=c,this.value={},this.settings=angular.copy(c.settings)},c.prototype.onmousedown=function(a){var c=b.offset(this.parent.domNode),d={left:c.left,top:c.top,width:this.parent.domNode[0].clientWidth,height:this.parent.domNode[0].clientHeight};this._parent={offset:d,width:d.width,height:d.height},this.ptr.addClass("jslider-pointer-hover"),this.setIndexOver()},c.prototype.onmousemove=function(a,c,d){var e=this._getPageCoords(a),f=this.calc(e.x);this.parent.settings.smooth||(f=b.roundUpToScale(f,this.parent.settings.scale,this.parent.settings.cutOffWidth,this.parent.settings.cutOffIndex));var g=this.parent.settings.cutOffWidth;g&&g>f&&(f=g),this._set(f)},c.prototype.onmouseup=function(a){if(this.settings.callback&&angular.isFunction(this.settings.callback)){var b=this.parent.getValue();this.settings.callback.call(this.parent,b)}this.ptr.removeClass("jslider-pointer-hover")},c.prototype.setIndexOver=function(){this.parent.setPointersIndex(1),this.index(2)},c.prototype.index=function(a){},c.prototype.limits=function(a){return this.parent.limits(a,this)},c.prototype.calc=function(a){var b=a-this._parent.offset.left,c=this.limits(100*b/this._parent.width);return c},c.prototype.set=function(a,b){this.value.origin=this.parent.round(a),this._set(this.parent.valueToPrc(a,this),b)},c.prototype._set=function(a,b){b||(this.value.origin=this.parent.prcToValue(a)),this.value.prc=a,this.ptr.css({left:a+"%"}),this.parent.redraw(this)},c}]).factory("slider",["sliderPointer","sliderConstants","utils",function(a,b,c){function d(){return this.init.apply(this,arguments)}function e(a){f.css("width",a)}var f;return d.prototype.changeCutOffWidth=e,d.prototype.init=function(a,c,d){this.settings=b.SLIDER.settings,angular.extend(this.settings,angular.copy(d)),this.inputNode=a,this.inputNode.addClass("ng-hide"),this.settings.interval=this.settings.to-this.settings.from,this.settings.calculate&&$.isFunction(this.settings.calculate)&&(this.nice=this.settings.calculate),this.settings.onstatechange&&$.isFunction(this.settings.onstatechange)&&(this.onstatechange=this.settings.onstatechange),this.is={init:!1},this.o={},this.create(c)},d.prototype.create=function(b){var d=this;this.domNode=b;var e=c.offset(this.domNode),g={left:e.left,top:e.top,width:this.domNode[0].clientWidth,height:this.domNode[0].clientHeight};this.sizes={domWidth:this.domNode[0].clientWidth,domOffset:g},angular.extend(this.o,{pointers:{},labels:{0:{o:angular.element(this.domNode.find("div")[5])},1:{o:angular.element(this.domNode.find("div")[6])}},limits:{0:angular.element(this.domNode.find("div")[3]),1:angular.element(this.domNode.find("div")[5])}}),angular.extend(this.o.labels[0],{value:this.o.labels[0].o.find("span")}),angular.extend(this.o.labels[1],{value:this.o.labels[1].o.find("span")}),d.settings.value.split(";")[1]||(this.settings.single=!0);var h=this.domNode.find("div");f=angular.element(h[8]),f&&f.css&&f.css("width","0%");var i=[angular.element(h[1]),angular.element(h[2])];angular.forEach(i,function(b,c){d.settings=angular.copy(d.settings);var e=d.settings.value.split(";")[c];if(e){d.o.pointers[c]=new a(b,c,d);var f=d.settings.value.split(";")[c-1];f&&parseInt(e,10)<parseInt(f,10)&&(e=f);var g=e<d.settings.from?d.settings.from:e;g=e>d.settings.to?d.settings.to:e,d.o.pointers[c].set(g,!0),0===c&&d.domNode.bind("mousedown",d.clickHandler.apply(d))}}),this.o.value=angular.element(this.domNode.find("i")[2]),this.is.init=!0,angular.forEach(this.o.pointers,function(a){d.redraw(a)})},d.prototype.clickHandler=function(){var a=this;return function(b){if(!a.disabled){var d=b.target.className,e=0;d.indexOf("jslider-pointer-to")>0&&(e=1);var f=c.offset(a.domNode),g={left:f.left,top:f.top,width:a.domNode[0].clientWidth,height:a.domNode[0].clientHeight};e=1;var h=a.o.pointers[e];return h._parent={offset:g,width:g.width,height:g.height},h._mousemove(b),h.onmouseup(),!1}}},d.prototype.disable=function(a){this.disabled=a},d.prototype.nice=function(a){return a},d.prototype.onstatechange=function(){},d.prototype.limits=function(a,b){if(!this.settings.smooth){var c=100*this.settings.step/this.settings.interval;a=Math.round(a/c)*c}var d=this.o.pointers[1-b.uid];d&&b.uid&&a<d.value.prc&&(a=d.value.prc),d&&!b.uid&&a>d.value.prc&&(a=d.value.prc),0>a&&(a=0),a>100&&(a=100);var e=Math.round(10*a)/10;return e},d.prototype.setPointersIndex=function(a){angular.forEach(this.getPointers(),function(a,b){a.index(b)})},d.prototype.getPointers=function(){return this.o.pointers},d.prototype.onresize=function(){var a=this;this.sizes={domWidth:this.domNode[0].clientWidth,domHeight:this.domNode[0].clientHeight,domOffset:{left:this.domNode[0].offsetLeft,top:this.domNode[0].offsetTop,width:this.domNode[0].clientWidth,height:this.domNode[0].clientHeight}},angular.forEach(this.o.pointers,function(b,c){a.redraw(b)})},d.prototype.update=function(){this.onresize(),this.drawScale()},d.prototype.drawScale=function(){},d.prototype.redraw=function(a){if(!this.settings.smooth){var b=c.roundUpToScale(a.value.prc,this.settings.scale,this.settings.cutOffWidth,this.settings.cutOffIndex);a.value.origin=b,a.value.prc=b}if(!this.is.init)return!1;this.setValue();var d=this.o.pointers[1].value.prc,e={left:"0%",width:d+"%"};this.o.value.css(e);var f=this.nice(a.value.origin),g=this.settings.firstDimension;if(this.settings.stepWithDifferentScale&&!this.settings.smooth&&(f=c.valueForDifferentScale(this.settings.from,this.settings.to,f,this.settings.prcToValueMapper)),this.settings.realtimeCallback&&angular.isFunction(this.settings.realtimeCallback)&&void 0!==this.settings.cutOffVal&&1===a.uid&&this.settings.realtimeCallback(f),this.settings.conversion){var h=c.getConversionFactorValue(parseInt(f),this.settings.conversion,this.settings.firstDimension);f=h.scaledVal,g=h.scaledDimension}f=parseFloat(f);var i=c.convertToMbpsGbps(f,g,this.settings.decimalPlaces);this.o.labels[a.uid].value.html(i.unitValue+" "+i.unitLabel),this.redrawLabels(a)},d.prototype.redrawLabels=function(a){function b(a,b,d){b.margin=-b.label/2;var e=c.sizes.domWidth,f=b.border+b.margin;return 0>f&&(b.margin-=f),b.border+b.label/2>e?(b.margin=0,b.right=!0):b.right=!1,b.margin=-(a.o[0].clientWidth/2-a.o[0].clientWidth/20),
-a.o.css({left:d+"%",marginLeft:b.margin,right:"auto"}),b.right&&a.o.css({left:"auto",right:0}),b}var c=this,d=this.o.labels[a.uid],e=a.value.prc,f={label:d.o[0].offsetWidth,right:!1,border:e*i/100},g=null,h=null;if(!this.settings.single)switch(h=this.o.pointers[1-a.uid],g=this.o.labels[h.uid],a.uid){case 0:f.border+f.label/2>g.o[0].offsetLeft-this.sizes.domOffset.left?(g.o.css({visibility:"hidden"}),g.value.html(this.nice(h.value.origin)),d.o.css({visibility:"hidden"}),e=(h.value.prc-e)/2+e,h.value.prc!==a.value.prc&&(d.value.html(this.nice(a.value.origin)+"&nbsp;&ndash;&nbsp;"+this.nice(h.value.origin)),f.label=d.o[0].clientWidth,f.border=e*i/100)):g.o.css({visibility:"visible"});break;case 1:f.border-f.label/2<g.o[0].offsetLeft-this.sizes.domOffset.left+g.o[0].clientWidth?(g.o.css({visibility:"hidden"}),g.value.html(this.nice(h.value.origin)),d.o.css({visibility:"visible"}),e=(e-h.value.prc)/2+h.value.prc,h.value.prc!==a.value.prc&&(d.value.html(this.nice(h.value.origin)+"&nbsp;&ndash;&nbsp;"+this.nice(a.value.origin)),f.label=d.o[0].clientWidth,f.border=e*i/100)):g.o.css({visibility:"visible"})}f=b(d,f,e);var i=c.sizes.domWidth;g&&(f={label:g.o[0].clientWidth,right:!1,border:h.value.prc*this.sizes.domWidth/100},f=b(g,f,h.value.prc))},d.prototype.redrawLimits=function(){if(this.settings.limits){var a=[!0,!0];for(var b in this.o.pointers)if(!this.settings.single||0===b){var c=this.o.pointers[b],d=this.o.labels[c.uid],e=d.o[0].offsetLeft-this.sizes.domOffset.left,f=this.o.limits[0];e<f[0].clientWidth&&(a[0]=!1),f=this.o.limits[1],e+d.o[0].clientWidth>this.sizes.domWidth-f[0].clientWidth&&(a[1]=!1)}for(var g=0;g<a.length;g++)a[g]?angular.element(this.o.limits[g]).addClass("animate-show"):angular.element(this.o.limits[g]).addClass("animate-hidde")}},d.prototype.setValue=function(){var a=this.getValue();this.inputNode.attr("value",a),this.onstatechange.call(this,a,this.inputNode)},d.prototype.getValue=function(){if(!this.is.init)return!1;var a=this,b="";return angular.forEach(this.o.pointers,function(d,e){if(void 0!==d.value.prc&&!isNaN(d.value.prc)){var f=d.value.prc,g=a.prcToValue(f);if(!a.settings.smooth)var g=c.valueForDifferentScale(a.settings.from,a.settings.to,f,a.settings.prcToValueMapper);b+=(e>0?";":"")+g}}),b},d.prototype.getPrcValue=function(){if(!this.is.init)return!1;var a="";return $.each(this.o.pointers,function(b){void 0===this.value.prc||isNaN(this.value.prc)||(a+=(b>0?";":"")+this.value.prc)}),a},d.prototype.prcToValue=function(a){var b;if(this.settings.heterogeneity&&this.settings.heterogeneity.length>0)for(var c=this.settings.heterogeneity,d=0,e=this.settings.from,f=0;f<=c.length;f++){var g;g=c[f]?c[f].split("/"):[100,this.settings.to],a>=d&&a<=g[0]&&(b=e+(a-d)*(g[1]-e)/(g[0]-d)),d=g[0],e=g[1]}else b=this.settings.from+a*this.settings.interval/100;var h=this.round(b);return h},d.prototype.valueToPrc=function(a,b){var c;if(this.settings.heterogeneity&&this.settings.heterogeneity.length>0)for(var d=this.settings.heterogeneity,e=0,f=this.settings.from,g=0;g<=d.length;g++){var h;h=d[g]?d[g].split("/"):[100,this.settings.to],a>=f&&a<=h[1]&&(c=b.limits(e+(a-f)*(h[0]-e)/(h[1]-f))),e=h[0],f=h[1]}else c=b.limits(100*(a-this.settings.from)/this.settings.interval);return c},d.prototype.round=function(a){return a=Math.round(a/this.settings.step)*this.settings.step,a=this.settings.round?Math.round(a*Math.pow(10,this.settings.round))/Math.pow(10,this.settings.round):Math.round(a)},d}]).directive("attStepSlider",["$compile","$templateCache","$timeout","$window","slider","sliderConstants","utils",function(a,b,c,d,e,f,g){var h="app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html";return{restrict:"AE",require:"?ngModel",scope:{options:"=",cutOff:"="},priority:1,templateUrl:h,link:function(i,j,k,l){function m(){angular.element(d).bind("resize",function(a){i.slider.onresize()})}if(l){i.mainSliderClass="step-slider",j.after(a(b.get(h))(i,function(a,b){b.tmplElt=a})),l.$render=function(){if(l.$viewValue.split&&1===l.$viewValue.split(";").length?l.$viewValue="0;"+l.$viewValue:"number"==typeof l.$viewValue&&(l.$viewValue="0;"+l.$viewValue),(l.$viewValue||0===l.$viewValue)&&("number"==typeof l.$viewValue&&(l.$viewValue=""+l.$viewValue),i.slider)){var a="0";if(i.slider.getPointers()[0].set(a,!0),l.$viewValue.split(";")[1]){var b=l.$viewValue.split(";")[1];b.length>=4&&(b=b.substring(0,2)),i.options.realtime||i.options.callback(parseFloat(l.$viewValue.split(";")[1])),i.slider.getPointers()[1].set(l.$viewValue.split(";")[1],!0)}}};var n=function(){function a(){0!==d[0]&&d.splice(0,0,0),100!==d[d.length-1]&&d.splice(d.length,0,100)}function b(){if(d[d.length-1]!==i.options.to&&d.splice(d.length,0,i.options.to),i.options.displayScaledvalues){for(var a in d)h.push(Math.log2(d[a]));var b=h[h.length-1]}for(var a in d){var c,e=d[a]/i.options.from,f=d[a]/i.options.to;c=i.options.displayScaledvalues?h[a]/b*100:(d[a]-i.options.from)/(i.options.to-i.options.from)*100;var g=d[a];1===f?c=100:1===e&&(c=0),d[a]=c,k[""+c]=g}}i.from=""+i.options.from,i.to=""+i.options.to,i.options.calculate&&"function"==typeof i.options.calculate&&(i.from=i.options.calculate(i.from),i.to=i.options.calculate(i.to)),i.showDividers=i.options.showDividers,i.COLORS=f.COLORS,i.sliderColor=i.options.sliderColor,i.sliderColor||(i.sliderColor=f.COLORS.REGULAR);var d=i.options.scale,e=[],h=[],k={};for(var n in d){var p=d[n];e.push(p)}0===i.options.from&&100===i.options.to||!i.options.smooth?0===i.options.from&&100===i.options.to||i.options.smooth?(b(),a()):(i.options.stepWithDifferentScale=!0,b(),a()):(a(),i.options.stepWithDifferentScale=!0);var q=0;if(i.options.decimalPlaces&&(q=i.options.decimalPlaces),i.endDimension=i.options.dimension,i.options.conversion){var r=i.options.conversion.length-1,s=i.options.conversion[r].dimension,t=i.options.conversion[r].scaleFactor;i.endDimension=" "+s;var u=(i.to/t).toFixed(q);i.toStr=u}else i.toStr=i.options.to;var v=g.convertToMbpsGbps(i.toStr,i.endDimension,i.options.decimalPlaces);i.toStr=v.unitValue,i.endDimension=" "+v.unitLabel;var w={from:i.options.from,to:i.options.to,step:i.options.step,smooth:i.options.smooth,limits:!0,stepWithDifferentScale:i.options.stepWithDifferentScale,round:i.options.round||!1,value:l.$viewValue,scale:i.options.scale,nonPercentScaleArray:e,prcToValueMapper:k,firstDimension:i.options.dimension,decimalPlaces:q,conversion:i.options.conversion,realtimeCallback:i.options.callback};angular.isFunction(i.options.realtime)?w.realtimeCallback=function(a){l.$setViewValue(a),i.options.callback(a)}:w.callback=o,w.calculate=i.options.calculate||void 0,w.onstatechange=i.options.onstatechange||void 0,c(function(){var a=i.tmplElt.find("div")[7];w.conversion||(i.tmplElt.find("div").eq(6).find("span").eq(0).css("padding-left","10px"),i.tmplElt.find("div").eq(6).find("span").eq(0).css("padding-right","15px")),i.slider=angular.element.slider(j,i.tmplElt,w),angular.element(a).html(i.generateScale()),i.drawScale(a),m(),i.$watch("options.disable",function(a){i.slider&&(i.tmplElt.toggleClass("disabled",a),i.slider.disable(a))}),i.$watch("cutOff",function(a){if(a&&a>0){var b=(a-i.slider.settings.from)/(i.slider.settings.to-i.slider.settings.from);if(b=100*b,i.isCutOffSlider=!0,i.slider.settings.cutOffWidth=b,i.cutOffVal=a,i.options.conversion){var c=g.getConversionFactorValue(a,i.options.conversion,i.options.dimension);c.scaledVal=parseFloat(c.scaledVal).toFixed(i.options.decimalPlaces),i.cutOffVal=c.scaledVal+" "+c.scaledDimension}i.slider.settings.cutOffVal=a,i.slider.changeCutOffWidth(b+"%");var d=i.slider.settings.nonPercentScaleArray;for(var e in d)if(e>=1){var f=d[e-1],h=d[e];a>f&&h>=a&&(i.slider.settings.cutOffIndex=e)}}else i.slider.settings.cutOffVal=0})})};i.generateScale=function(){if(i.options.scale&&i.options.scale.length>0){for(var a="",b=i.options.scale,c="left",d=0;d<b.length;d++)if(0!==d&&d!==b.length-1){var e=(b[d]-i.from)/(i.to-i.from)*100;i.options.stepWithDifferentScale&&!i.options.smooth&&(e=b[d]),a+='<span style="'+c+": "+e+'%"></span>'}return a}return""},i.drawScale=function(a){angular.forEach(angular.element(a).find("ins"),function(a,b){a.style.marginLeft=-a.clientWidth/2})};var o=function(a){var b=a.split(";")[1];i.$apply(function(){l.$setViewValue(parseInt(b))}),i.options.callback&&i.options.callback(parseInt(b))};i.$watch("options",function(a){n()}),angular.element.slider=function(a,b,c){b.data("jslider")||b.data("jslider",new e(a,b,c));var d=b.data("jslider");return d}}}}}]),angular.module("att.abs.steptracker",["att.abs.transition"]).directive("steptracker",["$timeout",function(a){return{priority:100,scope:{sdata:"=sdata",cstep:"=currentStep",clickHandler:"=?",disableClick:"=?"},restrict:"EA",replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",link:function(b,c){void 0===b.disableClick&&(b.disableClick=!1),a(function(){function a(a){return angular.element(g[a-1])}function d(){if(b.cstep>0&&b.cstep<=b.sdata.length-1&&j>0){var c=j/k*100+"%";l=a(b.cstep),l.css("width",c)}}function e(){b.cstep<=b.sdata.length&&(j=b.sdata[b.cstep-1].currentPage,k=b.sdata[b.cstep-1].totalPages)}b.cstep<1?b.cstep=1:b.cstep>b.sdata.length&&(b.cstep=b.sdata.length);var f=c.find("div"),g=[];for(var h in f)if(f.eq(h)[0]){var i=f.eq(h)[0].className;i.indexOf("track ng-scope")>-1&&g.push(f.eq(h))}var j,k,l=a(b.cstep);b.set_width=function(a){var c=100/(b.sdata.length-1)+"%";return b.sdata.length-1>a?{width:c}:void 0},b.$watch("sdata",function(){e();var a=b.cstep;if(1>j&&(j=1,1!==b.cstep&&(b.cstep--,e())),j>k){if(b.cstep>b.sdata.length-1)return void b.cstep++;j=k,d(),b.cstep++,e(),d()}1>j&&a===b.cstep&&(j=1,b.cstep>1&&(b.cstep--,b.sdata[b.cstep-1].currentPage=b.sdata[b.cstep-1].totalPages,b.sdata[b.cstep].currentPage=1)),d()},!0),b.activestep=function(a){return a===b.cstep-1},b.donesteps=function(a){return a<b.cstep-1},b.laststep=function(a){return a===b.sdata.length-1},b.isIncomplete=function(a){if(a===b.cstep-1)return!1;if(a>=0&&a<b.sdata.length-1){var c=b.sdata[a];return c.currentPage<=c.totalPages}},b.stepclick=function(a,c){if(c<b.cstep){for(var f=b.cstep-1;f>c;f--)b.sdata[f].currentPage=1;b.sdata[c].currentPage--}angular.isFunction(b.clickHandler)&&b.clickHandler(a,c),b.cstep=c+1,b.cstep<=b.sdata.length&&b.sdata[b.cstep].currentPage<1&&(b.sdata[b.cstep].currentPage=1),e(),d()}},100)}}}]).constant("timelineConstants",{STEP_TYPE:{ALERT:"alert",COMPLETED:"completed",CANCELLED:"cancelled"}}).controller("AttTimelineCtrl",["$scope","$timeout",function(a,b){function c(){function b(a,b){return a.order<b.order?-1:a.order>b.order?1:0}f.sort(b),e.sort(b),a.$parent.animate&&d(),a.$watch("trigger",function(b){b?a.resetTimeline():a.$parent.animate=!1})}function d(){function c(){for(var a in f){var b=f[a];if(a%2===0?b.unhoveredStateForBelow(.25):b.unhoveredStateForAbove(.25),b.isStop())break}}function d(a,h){return 0===a?function(){f[a+1].isStop()&&f[a+1].isCancelled()&&e[a].isCancelled(!0),e[a].animate(d(a+1,h),h)}:a===e.length-1?function(){f[0].isCurrentStep()&&f[0].isCurrentStep(!1),f[a].isStop()?(f[a-1].shrinkAnimate(g),f[a].isCurrentStep(!0)):(f[a-1].shrinkAnimate(g),e[a].animate(d(a+1,h),h)),f[a].expandedAnimate(g),b(function(){c()},500)}:a===e.length?function(){f[0].isCurrentStep()&&f[0].isCurrentStep(!1),f[a-1].shrinkAnimate(g),f[a].expandedAnimate(g),f[a].isCurrentStep(!0),b(function(){c()},500)}:function(){f[0].isCurrentStep()&&f[0].isCurrentStep(!1),f[a].isStop()?(f[a-1].shrinkAnimate(g),f[a].expandedAnimate(g),f[a].isCurrentStep(!0),b(function(){c()},500)):(f[a+1].isStop()&&f[a+1].isCancelled()&&e[a].isCancelled(!0),f[a-1].shrinkAnimate(g),e[a].animate(d(a+1,h),h),f[a].expandedAnimate(g))}}var g=.25,h=.25;"number"==typeof a.barAnimateDuration&&(h=a.barAnimateDuration);var i=d(0,h);i()}var e=[],f=[];this.numSteps=0,this.isAlternate=function(){return a.alternate},this.addTimelineBarCtrls=function(a){e.push(a)},this.addTimelineDotCtrls=function(a){f.push(a)},b(c,200)}]).directive("attTimeline",["$timeout","$compile",function(a,b){return{restrict:"EA",replace:!0,scope:{steps:"=",trigger:"=",alternate:"=",barAnimateDuration:"="},templateUrl:"app/scripts/ng_js_att_tpls/steptracker/timeline.html",controller:"AttTimelineCtrl",link:function(a,c,d,e){var f=function(){for(var b=a.steps,c=[],d=1;d<b.length;d++){var f=b[d];c.push(f)}a.middleSteps=c,e.numSteps=b.length-1};f(),a.resetTimeline=function(){a.animate=!0,b(c)(a)}}}}]).controller("TimelineBarCtrl",["$scope",function(a){this.type="timelinebar",this.order=parseInt(a.order),this.animate=function(b,c){a.loadingAnimation(b,c)},this.isCancelled=function(b){a.isCancelled=b}}]).directive("timelineBar",["animation","$progressBar",function(a,b){return{restrict:"EA",replace:!0,templateUrl:"app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",scope:{order:"@"},require:["^attTimeline","timelineBar"],controller:"TimelineBarCtrl",link:function(c,d,e,f){var g=f[0],h=f[1];g.addTimelineBarCtrls(h),c.isCompleted=!0;var i=100/g.numSteps-3;d.css("width",i+"%");var j=d.find("div").eq(0);a.set(j,{opacity:0});var k=function(b){a.set(j,{opacity:1}),a.set(j,{scaleX:b.progress(),transformOrigin:"left"})};c.loadingAnimation=b(k)}}}]).controller("TimelineDotCtrl",["$scope","$timeout","timelineConstants",function(a,b,c){this.type="dot",this.order=parseInt(a.order);var d=this;b(function(){0!==d.order&&(d.order%2!==0?a.initializeAboveForAnimation():a.initializeBelowForAnimation())}),this.expandedAnimate=function(b){a.setColor(),a.expandedAnimate(b),0===d.order||a.isStepsLessThanFive()||(d.order%2!==0?a.expandContentForAbove(b):a.expandContentForBelow(b))},this.unhoveredStateForAbove=function(b){a.unhoveredStateForAbove(b)},this.unhoveredStateForBelow=function(b){a.unhoveredStateForBelow(b)},this.shrinkAnimate=function(b){a.shrinkAnimate(b)},this.setExpanded=function(){a.setSize(3)},this.isStop=function(){return a.isStop},this.isCancelled=function(){return a.type===c.STEP_TYPE.CANCELLED},this.isAlert=function(){return a.type===c.STEP_TYPE.ALERT},this.isCurrentStep=function(b){return void 0!==b&&(a.isCurrentStep=b),a.isCurrentStep}}]).directive("timelineDot",["animation","timelineConstants",function(a,b){return{restrict:"EA",replace:!0,scope:{order:"@",title:"@",description:"@",by:"@",date:"@",type:"@"},templateUrl:"app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",require:["^attTimeline","timelineDot"],controller:"TimelineDotCtrl",link:function(c,d,e,f){function g(){return c.description||c.by||c.date?!1:!0}var h=f[0],i=f[1];h.addTimelineDotCtrls(i),c.numSteps=h.numSteps+1,c.isCurrentStep=!1,c.isCompleted=!1,c.isStop=!1,(c.type===b.STEP_TYPE.ALERT||c.type===b.STEP_TYPE.CANCELLED)&&(c.isStop=!0),c.isInactive=!0;var j=d.find("div"),k=j.eq(0),l=j.eq(2),m=j.eq(3),n=j.eq(5),o=j.eq(6),p=j.eq(9);c.isStepsLessThanFive=function(){return c.numSteps<5?!0:!1},c.titleMouseover=function(a){c.isStepsLessThanFive()||g()||(1===a&&c.order%2===0&&c.expandContentForBelow(.25),2===a&&c.order%2!==0&&c.expandContentForAbove(.25))},c.titleMouseleave=function(){c.order%2===0?c.unhoveredStateForBelow(.25):c.unhoveredStateForAbove(.25)},c.initializeAboveForAnimation=function(){if(!c.isStepsLessThanFive()&&h.isAlternate()&&(a.set(o,{opacity:0}),a.set(p,{opacity:0}),!g())){var b=o[0].offsetHeight+p[0].offsetHeight;a.set(n,{top:b})}},c.expandContentForAbove=function(b){!c.isStepsLessThanFive()&&h.isAlternate()&&(a.to(n,b,{top:0}),a.to(o,b,{opacity:1}),a.to(p,b,{opacity:1}))},c.unhoveredStateForAbove=function(b){if(!c.isStepsLessThanFive()&&h.isAlternate()){a.set(o,{opacity:0}),a.set(p,{opacity:1});var d=o[0].offsetHeight;a.to(n,b,{top:d})}},c.initializeBelowForAnimation=function(){!c.isStepsLessThanFive()&&h.isAlternate()&&(a.set(o,{height:"0%",opacity:0,top:"-20px"}),a.set(p,{opacity:0}))},c.expandContentForBelow=function(b){!c.isStepsLessThanFive()&&h.isAlternate()&&(a.set(p,{opacity:1}),a.to(o,b,{height:"auto",opacity:1,top:"0px"}))},c.unhoveredStateForBelow=function(b){!c.isStepsLessThanFive()&&h.isAlternate()&&(a.to(o,b,{height:"0%",opacity:0,top:"-20px",position:"relative"}),a.set(p,{opacity:1}))},g()&&c.order%2!==0&&h.isAlternate()&&m.css("top","-47px"),c.order%2!==0&&h.isAlternate()?c.isBelowInfoBoxShown=!1:c.isBelowInfoBoxShown=!0,c.isStepsLessThanFive()&&!h.isAlternate()&&a.set(p,{marginTop:10}),a.set(k,{opacity:".5"}),a.set(l,{opacity:"0.0"}),a.set(l,{scale:.1}),0===c.order&&(a.set(l,{opacity:"1.0"}),a.set(l,{scale:1}),a.set(k,{scale:3}),c.isCurrentStep=!0,c.isInactive=!1,c.isCompleted=!0),c.setColor=function(){c.isInactive=!1,c.type===b.STEP_TYPE.CANCELLED?c.isCancelled=!0:c.type===b.STEP_TYPE.ALERT?c.isAlert=!0:c.isCompleted=!0,c.$phase||c.$apply()},c.setSize=function(b){a.set(biggerCircle,{scale:b})},c.setExpandedCircle=function(){a.set(l,{opacity:"1.0"}),a.set(l,{scale:1})},c.expandedAnimate=function(b){a.to(k,b,{scale:3}),a.set(l,{opacity:"1.0"}),a.to(l,b,{scale:1})},c.shrinkAnimate=function(b){a.to(k,b,{scale:1})}}}}]),angular.module("att.abs.table",["att.abs.utilities"]).constant("tableConfig",{defaultSortPattern:!1,highlightSearchStringClass:"tablesorter-search-highlight"}).directive("attTable",["$filter",function(a){return{restrict:"EA",replace:!0,transclude:!0,scope:{tableData:"=",viewPerPage:"=",currentPage:"=",totalPage:"=",searchCategory:"=",searchString:"="},require:"attTable",templateUrl:"app/scripts/ng_js_att_tpls/table/attTable.html",controller:["$scope",function(a){this.headers=[],this.currentSortIndex=null,this.setIndex=function(a){this.headers.push(a)},this.getIndex=function(a){for(var b=0;b<this.headers.length;b++)if(this.headers[b].headerName===a)return this.headers[b].index;return null},this.sortData=function(b,c){a.$parent.columnIndex=b,a.$parent.reverse=c,this.currentSortIndex=b,a.currentPage=1,this.resetSortPattern()},this.getSearchString=function(){return a.searchString},this.resetSortPattern=function(){for(var a=0;a<this.headers.length;a++){var b=this.headers[a];b.index!==this.currentSortIndex&&b.resetSortPattern()}}}],link:function(b,c,d,e){b.searchCriteria={},b.$watchCollection("tableData",function(a){a&&!isNaN(a.length)&&(b.totalRows=a.length)}),b.$watch("currentPage",function(a){b.$parent.currentPage=a}),b.$watch("viewPerPage",function(a){b.$parent.viewPerPage=a}),b.$watch(function(){return b.totalRows/b.viewPerPage},function(a){isNaN(a)||(b.totalPage=Math.ceil(a),b.currentPage=1)});var f=function(a){return angular.isDefined(a)&&null!==a&&""!==a?!0:void 0},g=function(a,c){if(f(a)&&f(c)){var d=e.getIndex(c);b.searchCriteria={},null!==d&&(b.searchCriteria[d]=a)}else!f(a)||angular.isDefined(c)&&null!==c&&""!==c?b.searchCriteria={}:b.searchCriteria={$:a}};b.$watch("searchCategory",function(a,c){a!==c&&g(b.searchString,a)}),b.$watch("searchString",function(a,c){a!==c&&g(a,b.searchCategory)}),b.$watchCollection("searchCriteria",function(c){b.$parent.searchCriteria=c,b.totalRows=b.tableData&&a("filter")(b.tableData,c,!1).length||0,b.currentPage=1})}}}]).directive("attTableRow",[function(){return{restrict:"EA",compile:function(a,b){if("header"===b.type)a.find("tr").eq(0).addClass("tablesorter-headerRow");else if("body"===b.type){var c=a.children();b.rowRepeat&&(b.trackBy?c.attr("ng-repeat",b.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by "+b.trackBy)):c.attr("ng-repeat",b.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by $index"))),c.attr("ng-class","{'alt-row': $even,'normal-row': $odd}"),a.append(c)}}}}]).directive("attTableHeader",["tableConfig",function(a){return{restrict:"EA",replace:!0,transclude:!0,scope:{sortable:"@",defaultSort:"@",index:"@key"},require:"^attTable",templateUrl:"app/scripts/ng_js_att_tpls/table/attTableHeader.html",link:function(b,c,d,e){var f=a.defaultSortPattern;b.headerName=c.text(),b.sortPattern=null,e.setIndex(b),b.$watch(function(){return c.text()},function(a){b.headerName=a}),b.sort=function(a){"boolean"==typeof a&&(f=a),e.sortData(b.index,f),b.sortPattern=f?"desc":"asc",f=!f},b.$watch(function(){return e.currentSortIndex},function(a){a!==b.index&&(b.sortPattern=null)}),"false"!==b.sortable&&("A"===b.defaultSort||"a"===b.defaultSort?b.sort(!1):("D"===b.defaultSort||"d"===b.defaultSort)&&b.sort(!0)),b.resetSortPattern=function(){f=a.defaultSortPattern}}}}]).directive("attTableBody",["$filter","$timeout","tableConfig",function(a,b,c){return{restrict:"EA",require:"^attTable",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/table/attTableBody.html",link:function(d,e,f,g){var h=c.highlightSearchStringClass,i="",j=function(b){var c=b.text();b.html(a("highlight")(c,i,h))},k=function(a){var b=a.children();if(!(b.length>0))return void j(a);for(var c=0;c<b.length;c++)k(b.eq(c))},l=function(a){for(var b=a.find("*"),c=0;c<b.length;c++)if(b.eq(c).attr("class")&&-1!==b.eq(c).attr("class").indexOf(h)){var d=b.eq(c).text();b.eq(c).replaceWith(d)}};b(function(){var a=e.children();d.$watch(function(){return g.getSearchString()},function(b){i=b,l(e),a.length>0?k(e):j(e)})},50)}}}]),angular.module("att.abs.tableMessages",["att.abs.utilities"]).constant("messageConstants",{TABLE_MESSAGE_TYPES:{noMatching:1,errorLoading:2,magnifySearch:3,isLoading:4},USER_MESSAGE_TYPES:{success:1,error:0}}).directive("attTableMessage",["messageConstants",function(a){return{restrict:"AE",replace:!0,transclude:!0,scope:{msgType:"=",onRefreshClick:"&"},templateUrl:"app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",link:function(b){b.messageConstants=a,b.refreshAction=function(a){b.onRefreshClick(a)}}}}]).directive("attUserMessage",["messageConstants","$timeout","DOMHelper",function(a,b,c){return{restrict:"AE",replace:!0,transclude:!0,scope:{thetitle:"=",type:"=",message:"=",trigger:"="},templateUrl:"app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",link:function(d,e){var f=void 0,g=void 0;d.messageConstants=a,b(function(){g=c.firstTabableElement(e[0])},10),d.$watch("trigger",function(){d.trigger?(f=document.activeElement,angular.isDefined(g)&&g.focus()):angular.isDefined(f)&&f.focus()})}}}]),angular.module("att.abs.tabs",["att.abs.utilities"]).directive("attTabs",function(){return{restrict:"EA",transclude:!1,replace:!0,scope:{tabs:"=title"},controller:["$scope",function(a){this.getData=function(){return a.tabs},this.onClickTab=function(b){return a.currentTab=b.url,a.currentTab},this.isActiveTab=function(b){return b===a.currentTab}}],link:function(a){for(var b=0;b<a.tabs.length;b++)a.tabs[b].selected&&a.tabs[b].url&&(a.currentTab=a.tabs[b].url)}}}).directive("floatingTabs",function(){return{require:"^attTabs",restrict:"EA",transclude:!1,replace:!0,scope:{size:"@"},templateUrl:"app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",link:function(a,b,c,d){a.tabs=d.getData(),a.onClickTab=d.onClickTab,a.isActiveTab=d.isActiveTab}}}).directive("simplifiedTabs",function(){return{require:"^attTabs",restrict:"EA",transclude:!1,replace:!0,scope:{ctab:"=ngModel"},templateUrl:"app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",link:function(a,b,c,d){a.tabs=d.getData(),a.clickTab=function(b){return a.ctab=b.id,a.ctab},a.isActive=function(b){return b===a.ctab}}}}).directive("genericTabs",function(){return{require:"^attTabs",restrict:"EA",transclude:!1,replace:!0,scope:{ctab:"=ngModel"},templateUrl:"app/scripts/ng_js_att_tpls/tabs/genericTabs.html",link:function(a,b,c,d){a.tabs=d.getData(),a.clickTab=function(b){return a.ctab=b.id,a.ctab},a.isActive=function(b){return b===a.ctab}}}}).directive("skipNavigation",function(){return{link:function(a,b,c){b.bind("click",function(){var a=angular.element(b.parent().parent().parent().parent())[0].querySelector("a.skiptoBody");angular.element(a).attr("tabindex",-1),a.focus()})}}}).directive("parentTab",[function(){return{restrict:"EA",scope:{menuItems:"=",activeSubMenu:"=",activeMenu:"="},controller:["$scope",function(a){a.megaMenu=a.menuItems,a.megaMenuTab,a.megaMenuHoverTab,this.setMenu=function(){a.menuItems=a.megaMenu,a.activeSubMenu.scroll=!1;for(var b=0;b<a.menuItems.length;b++)a.menuItems[b].active&&(a.activeMenu=a.menuItems[b]);this.setSubMenuStatus(!1),a.$apply()},this.setActiveMenu=function(){if(void 0!==a.megaMenuTab&&null!==a.megaMenuTab)a.menuItems=[a.megaMenuTab],a.megaMenuTab.scroll=!0,a.activeMenu={},a.activeSubMenu=a.megaMenuTab,this.setSubMenuStatus(!0);else{for(var b=0;b<a.menuItems.length;b++)if(a.menuItems[b].active=!1,a.menuItems[b].subItems)for(var c=0;c<a.menuItems[b].subItems.length;c++)a.menuItems[b].subItems[c].active=!1;a.menuItems=a.megaMenu}a.$apply()};var b=!1;this.setSubMenuStatus=function(a){b=a},this.getSubMenuStatus=function(){return b},this.setActiveMenuTab=function(b){a.megaMenuTab=b},this.setActiveMenuHoverTab=function(b){a.megaMenuHoverTab=b},this.setActiveSubMenuTab=function(){a.megaMenuTab=a.megaMenuHoverTab},this.resetMenuTab=function(){a.megaMenuTab=void 0},this.clearSubMenu=function(){a.$evalAsync(function(){a.megaMenuTab=void 0,a.megaMenuHoverTab=void 0})}}]}}]).directive("parentmenuTabs",[function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{megaMenu:"@",menuItems:"="},controller:["$scope",function(a){this.getMenu=function(){return a.menuItems},this.setMenu=function(b){a.menuItems=b}}],templateUrl:"app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html"}}]).directive("menuTabs",["$window","$document","events","keymap",function(a,b,c,d){return{restrict:"EA",transclude:!0,replace:!0,require:["^?parentTab","^?parentmenuTabs"],scope:{activeMenu:"=",menuItem:"=",subMenu:"@",subItemActive:"@",tabName:"=?",tabUrl:"=?"},templateUrl:function(a,b){return b.megaMenu?"app/scripts/ng_js_att_tpls/tabs/menuTab.html":"app/scripts/ng_js_att_tpls/tabs/submenuTab.html"},link:function(e,f,g,h){function i(a,b){clearTimeout(a._tId),a._tId=setTimeout(function(){k.setMenu()},b)}function j(a,b){clearTimeout(a._tId),a._tId=setTimeout(function(){k.setActiveMenu()},b)}var k=h[0],l=h[1];e.clickInactive=!0,e.showHoverChild=function(a){e.clickInactive=!1,e.hoverChild=h[0].getSubMenuStatus(),"mouseover"===a.type&&h[0].getSubMenuStatus()&&e.showChildren(a)},e.showChildren=function(a){e.parentMenuItems=l.getMenu();for(var b=0;b<e.parentMenuItems.length;b++){if(e.parentMenuItems[b].active=!1,e.parentMenuItems[b].subItems)for(var c=0;c<e.parentMenuItems[b].subItems.length;c++)e.parentMenuItems[b].subItems[c].active=!1;e.clickInactive=!0}e.menuItem.active=!0,e.activeMenu=e.menuItem,a.stopPropagation()},e.$watch("subItemActive",function(a){"true"===a&&"true"===e.subMenu&&k.setActiveMenuHoverTab(e.menuItem)}),e.showMenuClick=function(a){k.setActiveMenuTab(e.menuItem),a.stopPropagation()},e.showSubMenuClick=function(a){k.setActiveSubMenuTab(),a.stopPropagation()},e.resetMenu=function(a){k.resetMenuTab(),a.stopPropagation()},b.bind("scroll",function(){0===a.pageYOffset?i(k.setMenu,100):a.pageYOffset>1&&a.pageYOffset<1500&&j(k.setActiveMenu,100)}),f.bind("keydown",function(a){switch(a.keyCode||(a.keyCode=a.which),a.keyCode!==d.KEY.TAB&&(c.preventDefault(a),c.stopPropagation(a)),a.keyCode){case d.KEY.ESC:var b;f.attr("mega-menu")?"item"===f.attr("menu-item")&&(b=angular.element(f.parent().parent().parent().parent())[0].querySelector("a.skiptoBody"),angular.element(b).attr("tabindex",-1),b.focus()):"true"===f.attr("sub-menu")?(b=angular.element(f.parent().parent().parent().parent().parent().parent().parent())[0].querySelector("a.skiptoBody"),angular.element(b).attr("tabindex",-1),b.focus()):void 0===f.attr("sub-menu")&&(b=angular.element(f.parent().parent().parent().parent().parent().parent().parent().parent().parent().parent())[0].querySelector("a.skiptoBody"),angular.element(b).attr("tabindex",-1),b.focus());break;case d.KEY.RIGHT:if(f.attr("mega-menu")){if("item"===f.attr("menu-item")){var g=angular.element(f)[0];if(g.nextElementSibling)null==g.nextElementSibling.querySelector("span")||g.nextElementSibling.querySelector("span").focus();else{do{if(!g||!g.nextSibling)break;g=g.nextSibling}while(g&&"LI"!==g.tagName);g&&(null===g.querySelector("span")||g.querySelector("span").focus()),c.preventDefault(a),c.stopPropagation(a)}}}else{var g=angular.element(f)[0];if("true"===f.attr("sub-menu")){if(null===g.nextElementSibling)break;if(g.nextElementSibling)g.nextElementSibling.querySelector("a").focus();else{do{if(!g||!g.nextSibling)break;g=g.nextSibling}while(g&&"LI"!==g.tagName);g&&(null==g.querySelector("a")||g.querySelector("a").focus()),c.preventDefault(a),c.stopPropagation(a)}}else if(void 0===f.attr("sub-menu")){if(null===g.nextElementSibling)break;if(g.nextElementSibling)g.nextElementSibling.querySelector("a").focus();else{do{if(!g||!g.nextSibling)break;g=g.nextSibling}while(g&&"LI"!==g.tagName);g&&(null==g.querySelector("a")||g.querySelector("a").focus())}}}break;case d.KEY.DOWN:if(f.attr("mega-menu"))angular.element(f)[0].querySelectorAll(".megamenu__items")[0].querySelector("a").focus();else if(void 0===f.attr("sub-menu")){var g=document.activeElement;if(null===g.nextElementSibling)break;if(g.nextElementSibling)g.nextElementSibling.focus();else{do{if(!g||!g.nextSibling)break;g=g.nextSibling}while(g&&"A"!==g.tagName);null!==g.attributes&&g.focus(),c.stopPropagation(a)}}else if("true"===f.attr("sub-menu")){var h=angular.element(f)[0].querySelector("span").querySelector("a");if(null===h)break;h.focus()}break;case d.KEY.LEFT:if(f.attr("mega-menu")){if("item"===f.attr("menu-item")){var g=angular.element(f)[0];if(g.previousElementSibling)null===g.previousElementSibling.querySelector("span")||g.previousElementSibling.querySelector("span").focus();else{do{if(!g||!g.previousSibling)break;g=g.previousSibling}while(g&&"LI"!==g.tagName);g&&(null===g.querySelector("span")||g.querySelector("span").focus()),c.preventDefault(a),c.stopPropagation(a)}}}else{var g=angular.element(f)[0];if("true"===f.attr("sub-menu")){if(null===g.previousElementSibling)break;if(g.previousElementSibling)g.previousElementSibling.querySelector("a").focus();else{do{if(!g||!g.previousSibling)break;g=g.previousSibling}while(g&&"LI"!==g.tagName);g&&(null==g.querySelector("a")||g.querySelector("a").focus()),c.preventDefault(a),c.stopPropagation(a)}}else if(void 0===f.attr("sub-menu")){if(null===g.previousElementSibling)break;if(g.previousElementSibling)g.previousElementSibling.querySelector("a").focus();else{do{if(!g||!g.previousSibling)break;g=g.previousSibling}while(g&&"LI"!==g.tagName);g&&(null==g.querySelector("a")||g.querySelector("a").focus())}}}break;case d.KEY.UP:if("true"===f.attr("sub-menu")){var g=document.activeElement,i=angular.element(f.parent().parent().parent().parent())[0].querySelector("span");i.focus(),k.clearSubMenu(),e.menuItem.active=!1;break}if(void 0===f.attr("sub-menu")){var g=document.activeElement,i=angular.element(f.parent().parent().parent().parent())[0].querySelector("a");if(document.activeElement===angular.element(g).parent().parent()[0].querySelectorAll("a")[0]){i.focus();break}if(g.previousElementSibling){g.previousElementSibling;null!=g.previousElementSibling?g.previousElementSibling.focus():i.focus()}else{do{if(!g||!g.previousSibling)break;g=g.previousSibling}while(g&&"A"!==g.tagName);g&&3!==g.nodeType&&g.focus(),c.preventDefault(a),c.stopPropagation(a)}break}}})}}}]),angular.module("att.abs.tagBadges",[]).directive("tagBadges",["$parse","$timeout",function(a,b){return{restrict:"EA",replace:!1,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",scope:{styleType:"@",onClose:"&"},link:function(c,d,e){c.isSmall=!1,c.isIcon=!1,c.isColor=!1,c.display=!0,c.isClosable=!1,c.isHighlight=!1,c.customColor=!1,""===e.small&&(c.isSmall=!0),"icon"===c.styleType?c.isIcon=!0:"color"===c.styleType&&(c.isColor=!0,void 0!==e.color&&""!==e.color&&(c.customColor=!0,e.$observe("color",function(a){c.border_type_borderColor=a,c.background_type_backgroundColor=a,c.background_type_borderColor=a}))),c.activeHighlight=function(a){c.customColor&&(a?c.isHighlight=!0:c.isHighlight=!1)},""===e.closable&&(c.isClosable=!0,c.closeMe=function(){c.display=!1,b(function(){
-d.attr("tabindex","0"),d[0].focus(),d.bind("blur",function(){d.remove()})}),e.onClose&&(c.onClose=a(c.onClose),c.onClose())})}}}]),angular.module("att.abs.textOverflow",[]).constant("textDefaultOptions",{width:"50%"}).directive("attTextOverflow",["textDefaultOptions","$compile",function(a,b){return{restrict:"A",link:function(c,d,e){var f=d.text();if(d.addClass("text-ellipsis"),e.$observe("attTextOverflow",function(b){b?d.css({width:b}):d.css({width:a.width})}),!d.attr("tooltip")){d.attr("tooltip",f),d.attr("tooltip-placement","above");var g=angular.element(d);b(g)(c)}}}}]),angular.module("att.abs.toggle",["angular-gestures","att.abs.position"]).directive("attToggleTemplate",["$compile","$log","$position",function(a,b,c){return{restrict:"A",require:"ngModel",transclude:!0,scope:{modelVal:"=ngModel"},templateUrl:"app/scripts/ng_js_att_tpls/toggle/demoToggle.html",link:function(a,b,d){a.initialDragPosition=0;var e=0,f=c.offset(b.children().eq(1).children().eq(0)).width-1,g=function(){a.attrValue===d.ngTrueValue||a.attrValue?a.modelVal=!1:a.modelVal=!0};a.updateModel=function(a){1!==e&&(g(),e=0),a.preventDefault()},a.drag=function(d){if(e=1,"dragstart"===d.type)a.initialDragPosition=c.position(b.children().eq(1)).left,b.children().eq(1).addClass("dragging");else if("drag"===d.type){var h=Math.min(0,Math.max(a.initialDragPosition+d.gesture.deltaX,-f));b.children().eq(1).css({left:h+"px"})}else if("dragend"===d.type){var i=c.position(b.children().eq(1)).left>-1*f/2;b.children().eq(1).removeClass("dragging"),TweenMax.to(b.children().eq(1),.1,{left:i?0:-1*f,ease:Power4.easeOut,onComplete:function(){b.children().eq(1).css({left:""})}}),(i||!i&&"left"===d.gesture.direction)&&g(),e=0}return!1},a.directiveValue=d.attToggleTemplate,a.on=d.trueValue,a.off=d.falseValue;var h=-1*f+"px";a.$watch("modelVal",function(c){if(a.attrValue=c,c===d.ngTrueValue||c){b.children().eq(1).css({left:"0px"}),b.addClass("att-checkbox--on");var f=b.find("div").find("div").eq(1);f.attr("aria-checked",!0),e=0}else{b.children().eq(1).css({left:h}),b.removeClass("att-checkbox--on");var f=b.find("div").find("div").eq(1);f.attr("aria-checked",!1),e=0}b.children().eq(1).css({left:""})})}}}]).directive("attToggleMain",["$compile",function(a){return{restrict:"A",require:"ngModel",transclude:!0,replace:!0,scope:{modelValue:"=ngModel",trueValue:"=ngTrueValue",falseValue:"=ngFalseValue"},link:function(b,c,d){var e="",f="";c.removeAttr("att-toggle-main"),b.on=d.ngTrueValue,b.off=d.ngFalseValue,b.largeValue=d.attToggleMain,angular.isDefined(d.ngTrueValue)&&(e+=' true-value="{{on}}" false-value="{{off}}"'),void 0!==b.largeValue&&(f+=' ="{{largeValue}}"'),c.css({display:"none"});var g=angular.element('<div class="att-switch att-switch-alt" ng-class="{\'large\' : largeValue == \'large\'}" ng-model="modelValue"'+e+" att-toggle-template"+f+">"+c.prop("outerHTML")+"</div>");g=a(g)(b),c.replaceWith(g)}}}]),angular.module("att.abs.treeview",[]).directive("treeView",function(){return{restrict:"A",link:function(a,b){function c(){f.reversed()?f.play():f.reverse()}function d(a){a.stopPropagation(),void 0!==angular.element(a.target).attr("tree-view")&&(b.hasClass("minus")?b.removeClass("minus"):b.addClass("minus"),c())}var e=b.children("ul li"),f=TweenMax.from(e,.2,{display:"none",paused:!0,reversed:!0});b.attr("tabindex","0"),b.on("click",function(a){d(a)}),b.on("keypress",function(a){var b=a.keyCode?a.keyCode:a.charCode,c=[13,32];c.length>0&&b&&c.indexOf(b)>-1&&(d(a),a.preventDefault())})}}}),angular.module("att.abs.typeAhead",["att.abs.tagBadges"]).directive("focusMe",["$timeout","$parse",function(a,b){return{link:function(c,d,e){var f=b(e.focusMe);c.$watch(f,function(b){b&&a(function(){d[0].focus(),c.inputActive=!0})}),d.bind("blur",function(){f.assign(c,!1),c.inputActive=!1,c.$digest()})}}}]).directive("typeAhead",["$timeout","$log",function(a,b){return{restrict:"EA",templateUrl:"app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",replace:!0,scope:{items:"=",title:"@?",titleName:"@",subtitle:"@",model:"=",emailIdList:"=",emailMessage:"="},link:function(c,d){!angular.isDefined(c.titleName)&&angular.isDefined(c.title)&&a(function(){c.titleName=c.title,b.warn("title attribute is deprecated and title-name attribute is used instead as it is conflicting with html title attribute")}),c.lineItems=[],c.filteredListLength=-1,c.filteredList=[],c.setFocus=function(){c.clickFocus=!0},c.setFocus(),c.handleSelection=function(a,b){c.lineItems.push(a),c.emailIdList.push(b),c.model="",c.current=0,c.selected=!0,c.clickFocus=!0},c.theMethodToBeCalled=function(b){var d=c.lineItems.slice();c.emailIdList.splice(b,1),d.splice(b,1),a(function(){c.lineItems=[],c.$apply(),c.lineItems=c.lineItems.concat(d)})},c.current=0,c.selected=!0,c.isCurrent=function(a,b,d,e){return c.current===a&&(c.itemName=b,c.itemEmail=d),c.dropdownLength=e,c.current===a},c.setCurrent=function(a){c.current=a},c.selectionIndex=function(a){38===a.keyCode&&c.current>0?(a.preventDefault(),c.current=c.current-1,c.isCurrent(c.current)):9===a.keyCode?c.selected=!0:13===a.keyCode&&c.dropdownLength!==c.items.length?c.handleSelection(c.itemName,c.itemEmail):8===a.keyCode&&0===c.model.length||46===a.keyCode?c.theMethodToBeCalled(c.lineItems.length-1):40===a.keyCode&&c.current<c.dropdownLength-1&&(a.preventDefault(),c.current=c.current+1,c.isCurrent(c.current)),d[0].querySelector(".list-scrollable").scrollTop=35*(c.current-1)}}}}]),angular.module("att.abs.verticalSteptracker",["ngSanitize"]).directive("verticalSteptracker",[function(){return{restrict:"EA",transclude:!0,replace:!1,scope:{},template:'<div class="vertical-nav"><ul ng-transclude arial-label="step list" role="presentation" class="tickets-list-height"></ul></div>',link:function(){}}}]).directive("verticalSteptrackerStep",[function(){return{restrict:"EA",transclude:!0,replace:!1,scope:{type:"=type",id:"=id"},templateUrl:"app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",link:function(){}}}]).directive("attAbsLink",[function(){return{restrict:"EA",transclude:!0,replace:!1,template:'<span ng-transclude class="view-log"></span>'}}]),angular.module("att.abs.videoControls",[]).config(["$compileProvider",function(a){a.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/)}]).directive("videoControls",[function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/videoControls/videoControls.html"}}]).directive("photoControls",[function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"app/scripts/ng_js_att_tpls/videoControls/photoControls.html",scope:{prevLink:"@",nextLink:"@"},link:function(a,b,c){c.prevLink||(a.prevLink="javascript:void(0)"),c.nextLink||(a.nextLink="javascript:void(0)"),a.links={prevLink:a.prevLink,nextLink:a.nextLink}}}}]),angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",'<div class="att-accordion__group tabpanel" ng-class="{\'att-accordion__group att-accordion__group--open\':isOpen,\'att-accordion__group\':!isOpen }">\n <a ng-show="showicon" \n class="toggle-header att-accordion__heading att-accordion__toggle noafter" \n aria-selected="{{focused}}" \n aria-controls="panel{{index}}" \n aria-expanded="{{isOpen}}" \n ng-class="{focus: focused, selected: focused}" \n role="tab" \n ng-click="toggle()" \n accordion-transclude="heading" \n style="cursor:pointer; text-decoration:none">\n <span>{{heading}}</span>\n <i ng-class="{\'icon-chevron-down\':!isOpen,\'icon-chevron-up\':isOpen }" class="pull-right"></i>\n </a>\n <div ng-show="!showicon" \n ng-class="{focus: focused, selected: focused}" \n style="text-decoration:none" \n accordion-transclude="heading" \n role="tab" \n aria-expanded="{{isOpen}}"\n aria-selected="{{focused}}" \n aria-controls="panel{{index}}" \n class="toggle-header att-accordion__heading att-accordion__toggle noafter">\n <span>{{heading}}</span>\n </div> \n <div aria-label="{{heading}}" \n aria-hidden="{{!isOpen}}" \n role="tabpanel" \n collapse="!isOpen" \n class="att-accordion__body" \n id="panel{{index}}" \n ng-transclude>\n </div>\n <div class="att-accordion__bottom--border"></div> \n</div> ')}]),angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",'<div class="att-accordion__group tabpanel" ng-class="{\'att-accordion__group att-accordion__group--open\':isOpen,\'att-accordion__group\':!isOpen }">\n <a class="toggle-header att-accordion__heading att-accordion__toggle" \n aria-selected="{{focused}}" \n aria-controls="panel{{index}}" \n ng-class="{focus: focused, selected: focused}" \n aria-expanded="{{isOpen}}" \n role="tab" \n ng-click="toggle()" \n accordion-transclude="heading"> \n </a>\n <span>{{heading}}</span>\n <div aria-label="{{heading}}" \n aria-hidden="{{!isOpen}}" \n role="tabpanel" \n collapse="!isOpen" \n class="att-accordion__body" \n id="panel{{index}}" \n ng-transclude>\n </div>\n</div> ')}]),angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html","<div ng-transclude></div>")}]),angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html","<div ng-transclude></div>")}]),angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",'<div ng-click="clickFunc()">\n <div ng-transclude>\n <i class="icon-chevron-down"></i>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/alert/alert.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/alert/alert.html","<div class=\"alert\" ng-class=\"{'alert-success': alertType === 'success', 'alert-warning': alertType === 'warning', 'alert-error': alertType === 'error', 'alert-info': alertType === 'info', 'alert-inplace': showTop !== 'true'}\" ng-show=\"showAlert\" ng-style=\"cssStyle\">\n <div class=\"container\">\n"+' <a href="javascript:void(0)" alt="close" class="close-role" ng-click="close()" tabindex="0" att-accessibility-click="32,13">Dismiss <i class="icon-circle-action-close"></i></a>\n <span ng-transclude> </span>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",'<div tabindex="0" att-accessibility-click="13,32" ng-click="addBoard()" aria-label="Add Board" class="boardstrip-item--add">\n <i aria-hidden="true" class="icon-add centered"></i>\n <br/>\n <div class="centered">Add board</div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",'<li att-board-navigation tabindex="0" aria-label="{{boardLabel}}" att-accessibility-click="13,32" ng-click="selectBoard(boardIndex)" class="board-item" ng-class="{\'selected\': getCurrentIndex()===boardIndex}">\n <div ng-transclude></div>\n <div class="board-caret" ng-if="getCurrentIndex()===boardIndex">\n <div class="board-caret-indicator"></div>\n <div class="board-caret-arrow-up"></div>\n </div>\n</li>')}]),angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",'<div class="att-boardstrip">\n <div class="boardstrip-reel">\n <div class="prev-items" ng-if="isPrevBoard()">\n <i tabindex="0" aria-label="Scroll Boardstrip Left" att-accessibility-click="13,32" ng-click="prevBoard()" class="arrow icon-arrow-left-circle"></i>\n </div>\n <div att-add-board on-add-board="onAddBoard()"></div>\n <div class="board-viewport"><ul role="presentation" class="boardstrip-container" ng-transclude></ul></div>\n <div class="next-items" ng-if="isNextBoard()">\n <i tabindex="0" aria-label="Scroll Boardstrip Right" att-accessibility-click="13,32" ng-click="nextBoard()" class="arrow icon-arrow-right-circle"></i>\n </div>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",'<div class="att-btn-dropdown">\n <div class="buttons-dropdown--small btn-group" ng-class="{\'open\': isOpen}" att-accessibility-click="13,32" ng-click="toggle()">\n \n <button role="menu" class="button button--secondary button--small buttons-dropdown__drop dropdown-toggle" ng-if="type===\'dots\'" alt="Click for Options" >\n \n <div class="circle"></div>\n <div class="circle"></div>\n <div class="circle"></div>\n </button>\n <button role="menu" class="button button--secondary button--small buttons-dropdown__drop dropdown-toggle ng-isolate-scope actions-title" ng-if="type === \'actions\'" alt="Actions dropdown Buttons">Actions</button>\n \n\n'+" <ul ng-class=\"{'dropdown-menu dots-dropdwn': type==='dots', 'dropdown-menu actions-dropdwn': type === 'actions'}\" ng-transclude></ul>\n </div>\n \n</div>\n")}]),angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",'<div class="att-radio att-color-selector__item" \n ng-class="{\'att-radio--on\': (iconColor === selected)}">\n <div class="att-radio__indicator" tabindex="0" att-accessibility-click="32,13" ng-click="selectedcolor(iconColor)" \n ng-style="applycolor" ng-transclude></div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",'<div class="calendar" ng-class="{\'monthpicker\':mode === 1}">\n <div class="select2-container" ng-class="{\'select2-container-active select2-dropdown-open\': showDropdownList}" style="width: 100%; z-index:0">\n <a tabindex="0" id="select2-choice" class="select2-choice" href="javascript:void(0)" att-element-focus="focusInputButton" ng-show="!showCalendar" att-accessibility-click="13,32" ng-click="showDropdown()" ng-blur="focusInputButton=false">\n <span class="select2-chosen" ng-show="!showCalendar">{{selectedOption}}</span>\n <input type="text" ng-show="showCalendar" ng-blur="untrackInputChange($event)" att-input-deny="[^0-9\\/-]" maxlength="{{maxLength}}" ng-model="selectedOption" aria-labelledby="select2-choice" ng-change="getDropdownText()" />\n <abbr class="select2-search-choice-close"></abbr>\n <span ng-class="{\'select2-arrow\': mode !== 1, \'calendar-icon\': mode === 1}"><b></b></span>\n </a>\n <a id="select2-chosen" class="select2-choice" href="javascript:void(0)" ng-show="showCalendar">\n <span class="select2-chosen" ng-show="!showCalendar">{{selectedOption}}</span>\n <input type="text" ng-show="showCalendar" ng-blur="untrackInputChange($event)" att-input-deny="[^0-9\\/-]" maxlength="{{maxLength}}" ng-model="selectedOption" aria-labelledby="select2-chosen" ng-change="getDropdownText()" />\n <abbr class="select2-search-choice-close"></abbr>\n <span tabindex="0" ng-class="{\'select2-arrow\': mode !== 1, \'calendar-icon\': mode === 1}" att-accessibility-click="13,32" ng-click="showDropdown()"><b></b></span>\n </a>\n </div>\n <div class="select2-drop select2-drop-active select2-display-none" ng-style="{display: (showDropdownList && \'block\') || \'none\', \'border-radius\': showCalendar && \'0 0 0 6px\'}" style="width: 100%">\n <div id="dateFilterList" att-scrollbar ><ul class="select2-results options" ng-transclude></ul></div>\n <ul class="select2-results sttings" style="margin-top:0px">\n <li tabindex="0" class="select2-result select2-highlighted greyBorder" ng-class="{\'select2-result-current\': checkCurrentSelection(\'Custom Single Date\')}" att-accessibility-click="13,32" ng-click="selectAdvancedOption(\'Custom Single Date\')">\n <div class="select2-result-label" ng-if="mode !== 1">Custom Single Date...</div>\n <div class="select2-result-label" ng-if="mode === 1">Custom single month...</div>\n </li>\n <li tabindex="0" class="select2-result select2-highlighted" ng-class="{\'select2-result-current\': checkCurrentSelection(\'Custom Range\')}" att-accessibility-click="13,32" ng-click="selectAdvancedOption(\'Custom Range\')">\n <div class="select2-result-label" ng-if="mode !== 1">Custom Range...</div>\n <div class="select2-result-label" ng-if="mode === 1">Custom month range...</div>\n </li>\n <li class="select2-result select2-highlighted btnContainer" ng-style="{display: (showCalendar && \'block\') || \'none\'}">\n <button tabindex="0" ng-blur="resetFocus($event)" att-element-focus="focusApplyButton" att-button="" btn-type="{{applyButtonType}}" size="small" att-accessibility-click="13,32" ng-click="apply()">Apply</button>\n <button tabindex="0" att-button="" btn-type="secondary" size="small" att-accessibility-click="13,32" ng-click="cancel()">Cancel</button>\n <div>\n <a tabindex="0" href="javascript:void(0)" ng-if="mode !== 1" style="text-decoration:underline;" att-accessibility-click="13,32" ng-click="clear()">Clear Dates</a>\n <a tabindex="0" href="javascript:void(0)" ng-if="mode === 1" style="text-decoration:underline;" att-accessibility-click="13,32" ng-click="clear()">Clear Months</a>\n </div>\n </li>\n </ul>\n </div>\n <div class="datepicker-wrapper show-right" ng-style="{display: (showCalendar && \'block\') || \'none\'}">\n <span datepicker ng-blur="resetFocus($event)" att-element-focus="focusSingleDateCalendar" ng-show="checkCurrentSelection(\'Custom Single Date\')"></span>\n <span datepicker ng-blur="resetFocus($event)" att-element-focus="focusRangeCalendar" ng-show="checkCurrentSelection(\'Custom Range\')"></span>\n </div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",'<li ng-click="!disabled && selectOption(fromDate,toDate,caption)" att-accessibility-click="13,32" ng-class="{\'select2-result-current\': checkCurrentSelection(caption)}" class="select2-result select2-highlighted ng-scope" tabindex="{{!disabled?\'0\':\'-1\'}}">\n <div class="select2-result-label" ng-class="{\'disabled\':disabled}" ng-transclude></div>\n</li>')}]),angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",'<div id="datepicker" class="datepicker" ng-class="{\'monthpicker\': mode === 1}" aria-hidden="false" role="dialog" tabindex="-1" aria-labelledby="datepicker">\n <div class="datepicker-days" style="display: block;">\n <table class="table-condensed">\n <thead>\n <tr>\n <th id="month" tabindex="0" class="datepicker-switch" colspan="{{(mode !== 1) && (currentRows[0].length - 2) || (currentRows[0].length)}}" style="text-align:left">{{currentTitle}}</th>\n <th ng-if="mode !== 1" id="prev" aria-hidden="{{!disablePrev && \'false\'|| \'true\'}}" tabindex="{{!disablePrev && \'0\'|| \'-1\'}}" att-accessibility-click="13,32" ng-click="!disablePrev && move(-1)">\n <div class="icons-list" data-size="medium"><i class="icon-arrow-left-circle" ng-class="{\'disabled\': disablePrev}" alt="Left Arrow"></i>\n </div><span class="hidden-spoken">Previous Month</span>\n </th>\n <th ng-if="mode !== 1" id="next" aria-hidden="{{!disableNext && \'false\'|| \'true\'}}" tabindex="{{!disableNext && \'0\'|| \'-1\'}}" att-accessibility-click="13,32" ng-click="!disableNext && move(1)">\n <div class="icons-list" data-size="medium"><i class="icon-arrow-right-circle" ng-class="{\'disabled\': disableNext}" alt="Right Arrow"></i>\n </div><span class="hidden-spoken">Next Month</span>\n </th>\n </tr>\n <tr ng-if="labels.length > 0">\n <th tabindex="-1" class="dow weekday" ng-repeat="label in labels"><span>{{label.pre}}</span></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td id="datepickerBody" att-scrollbar colspan="{{currentRows[0].length}}" style="padding: 0px;" headers="">\n <table ng-class="{\'table-condensed\': mode === 0, \'monthtable-condensed\': mode === 1}" style="padding: 0px;">\n <thead class="hidden-spoken">\n <tr ng-show="labels.length > 0">\n <th id="{{label.post}}" tabindex="-1" class="dow weekday" ng-repeat="label in labels"></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in currentRows">\n <td headers="{{(mode === 0) && dt.header || \'month\'}}" att-element-focus="dt.focused" aria-hidden="{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && \'false\') || \'true\'}}" tabindex="{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && \'0\') || \'-1\'}}" ng-repeat="dt in row" class="days" ng-class="{\'active\': dt.selected || dt.from || dt.to, \'from\': dt.from, \'to\': dt.to, \'range\': dt.dateRange, \'prev-month \': dt.oldMonth, \'next-month\': dt.nextMonth, \'disabled\': dt.disabled, \'today\': dt.today, \'weekend\': dt.weekend}" ng-click="!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)" att-accessibility-click="13,32" aria-label="{{dt.date | date : \'EEEE, MMMM d\'}}"><span class="day">{{dt.label}}</span></td>\n </tr>\n <tr ng-if="mode === 1" class="divider"><td colspan="{{nextRows[0].length}}"><hr></td></tr>\n <tr>\n <th id="month" tabindex="0" class="datepicker-switch internal" colspan="{{nextRows[0].length}}" style="text-align:left">{{nextTitle}}</th>\n </tr>\n <tr ng-repeat="row in nextRows">\n'+" <td headers=\"{{(mode === 0) && dt.header || 'month'}}\" att-element-focus=\"dt.focused\" aria-hidden=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && 'false') || 'true'}}\" tabindex=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && '0') || '-1'}}\" ng-repeat=\"dt in row\" class=\"days\" ng-class=\"{'active': dt.selected || dt.from || dt.to, 'from': dt.from, 'to': dt.to, 'range': dt.dateRange, 'prev-month ': dt.oldMonth, 'next-month': dt.nextMonth, 'disabled': dt.disabled, 'today': dt.today, 'weekend': dt.weekend}\" ng-click=\"!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)\" att-accessibility-click=\"13,32\" aria-label=\"{{dt.date | date : 'EEEE, MMMM d'}}\"><span class=\"day\">{{dt.label}}</span></td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n")}]),angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",'<div class="calendar">\n <div class="box" ng-class="{\'active\': isOpen}">\n <span ng-transclude></span>\n <i class="calendar-icon" tabindex="0" att-accessibility-click="13,32" ng-click="toggle()" alt="Calendar Icon"></i>\n </div>\n <div class="datepicker-wrapper datepicker-wrapper-display-none" ng-style="{display: (isOpen && \'block\') || \'none\'}" aria-hidden="false" role="dialog" tabindex="-1">\n <span datepicker></span>\n </div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",'<div class="divider-container" ng-class="{\'divider-container-light\': lightContainer}">\n <hr ng-class="{\'divider-light\': lightContainer}">\n</div>\n\n')}]),angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",'<label class="fileContainer"><span ng-transclude></span><input type="file" att-file-change></label>')}]),angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",'<div class="form-field" ng-class="{\'error\': errorMessage, \'warning\': warningMessage}">\n <label class="form-field__label" ng-class="{\'form-field__label--show\': showLabel, \'form-field__label--hide\': hideLabel}"></label>\n <div class="form-field-input-container" ng-transclude></div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",'<div class="form-field" ng-class="{\'error\':hideErrorMsg}">\n <div class="form-field-input-container" ng-transclude></div>\n <div class="form-field__message error" type="error" ng-show="hideErrorMsg" >\n <i class="icon-info-alert"></i>{{errorMessage}}\n </div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/formField/creditCardImage.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/formField/creditCardImage.html",'<span class="css-sprite pull-right">\n<span class="hidden-spoken">We accept</span>\n<ul class="{{newValCCI}}">\n <li class="css-sprite-mc"><span class="hidden-spoken">MasterCard</span></li>\n <li class="css-sprite-visa"><span class="hidden-spoken">Visa</span></li>\n <li class="css-sprite-amex"><span class="hidden-spoken">American Express</span></li>\n <li class="css-sprite-discover"><span class="hidden-spoken">Discover</span></li> \n</ul>\n</span>\n<label for="ccForm.card" class="pull-left">Card number</label>')}]),angular.module("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",'<div>\n<button type="button" class="btn btn-alt btn-tooltip" style="padding-top:16px" title="Help"><i class="hidden-spoken">Help</i></button>\n<div class="helpertext" role="tooltip">\n<div class="popover-title"></div>\n<div class="popover-content">\n <p class="text-legal cvc-cc">\n <img ng-src="images/{{newValI}}.png" alt="{{newValIAlt}}">\n </p>\n</div>\n</div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",'<div class="hourpicker">\n <div class="dropdown-width">\n <div ng-model="showlist" class="select2-container topDropDownWidth" ng-class="{\'select2-dropdown-open select2-container-active\': showlist}" >\n <a class="select2-choice" href="javascript:void(0)" id="customSelect" ng-keydown="selectOption(selectPrevNextValue($event,options,selectedOption))" att-accessibility-click="13" ng-click="showDropdown()">\n <span class="select2-chosen">{{selectedOption}}</span>\n <span class="select2-arrow"><b></b></span>\n </a>\n </div> \n <div class="select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth" ng-show="showlist"> \n <ul class="select2-results resultTopMargin" > \n <li ng-model="ListType" ng-repeat="option in options" att-accessibility-click="13" ng-click="selectOption(option,$index)" class="select2-results-dept-0 select2-result select2-result-selectable"><div class="select2-result-label"><span >{{option}}</span></div></li> \n </ul>\n </div>\n </div>\n <div ng-show="showDaysSelector" class="customdays-width">\n <div att-divider-lines class="divider-margin-f"></div> \n <div class="col-md-3 fromto-margin">\n <div>From</div> <br>\n <div>To</div>\n </div>\n <div ng-repeat="day in days">\n <div class="col-md-3 col-md-days">\n <div class="col-md-1 daysselect-margin">\n <input type="checkbox" ng-model="daysList[day]" title="Day selection {{$index}}" att-checkbox ng-change="addSelectedValue(day)"> \n </div>\n <span>{{day}}</span><br>\n \n <div class="dropDownMarginBottom">\n <div class="select2-container topDropDownWidth" ng-class="{\'select2-dropdown-open select2-container-active\': FrtimeListDay[day]}" >\n <a class="select2-choice selectDropDown" href="javascript:void(0)" tabindex="{{daysList[day] ? \'0\' : \'-1\'}}" att-accessibility-click="13" ng-click="daysList[day] && showfromDayDropdown(day)" ng-class="{\'select2-chosen-disabled\':!daysList[day]}" ng-keydown="daysList[day] && selectFromDayOption(day , selectPrevNextValue($event,fromtime,selectedFromOption[day]));daysList[day] && addSelectedValue(day);">\n <span class="select2-chosen dropDownMarginRight" >{{selectedFromOption[day]}} <i ng-if="daysList[day]" ng-class="FrtimeListDay[day] ? \'icon-dropdown-up\' : \'ion-arrow-down-b\'"></i></span>\n </a>\n </div> \n \n <div class="select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown" ng-show="FrtimeListDay[day]"> \n <ul class="select2-results resultTopMargin" > \n <li ng-click="selectFromDayOption(day,time.value);addSelectedValue(day);" ng-repeat="time in fromtime" class="select2-results-dept-0 select2-result select2-result-selectable"><div class="select2-result-label" ng-class="{\'selectedItemInDropDown\': (time.value==selectedFromOption[day])}"><span >{{time.value}}</span></div></li> \n </ul>\n </div>\n </div>\n \n <div class="dropDownMarginBottom">\n <div class="select2-container topDropDownWidth" ng-class="{\'select2-dropdown-open select2-container-active\': TotimeListDay[day]}" >\n <a class="select2-choice selectDropDown" href="javascript:void(0)" tabindex="{{daysList[day] ? \'0\' : \'-1\'}}" att-accessibility-click="13" ng-click="daysList[day] && showtoDayDropdown(day)" ng-class="{\'select2-chosen-disabled\':!daysList[day], \'selectDropDown-error\':daysList[day] && showToTimeErrorDay[day]}" ng-keydown="daysList[day] && selectToDayOption(day , selectPrevNextValue($event,totime,selectedToOption[day]));daysList[day] && addSelectedValue(day);">\n <span class="select2-chosen dropDownMarginRight">{{selectedToOption[day]}} <i ng-if="daysList[day]" ng-class="TotimeListDay[day] ? \'icon-dropdown-up\' : \'ion-arrow-down-b\'" ></i></span>\n </a>\n </div>\n \n <div class="select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown" ng-show="TotimeListDay[day]"> \n <ul class="select2-results resultTopMargin" > \n <li ng-click="selectToDayOption(day,time.value);addSelectedValue(day);" ng-repeat="time in totime" class="select2-results-dept-0 select2-result select2-result-selectable"><div class="select2-result-label" ng-class="{\'selectedItemInDropDown\': (time.value==selectedToOption[day])}"><span >{{time.value}}</span></div></li> \n </ul>\n </div>\n </div>\n </div> \n </div> \n <div att-divider-lines class="divider-margin-s"></div>\n </div>\n <div ng-transclude></div>\n</div>');
-}]),angular.module("app/scripts/ng_js_att_tpls/links/readMore.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/links/readMore.html",'<div>\n <div ng-bind-html="textToDisplay" ng-class="{\'att--readMore\': readFlag, \'att--readLess\': !readFlag}" ng-style="readLinkStyle"></div>\n <span class="att--readmore__link" ng-show="readMoreLink">… <a href="javascript:void(0);" ng-click="readMore()" att-accessbility-click="32,13">Read More</a>\n </span>\n</div>\n<span class="att--readless__link" ng-show="readLessLink">\n <a href="javascript:void(0);" ng-click="readLess()" att-accessbility-click="32,13">Read Less</a>\n</span>')}]),angular.module("app/scripts/ng_js_att_tpls/loading/loading.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/loading/loading.html",'<div data-progress="{{progressStatus}}" class="{{colorClass}}" ng-class="{\'att-loading-count\':icon == \'count\',\'loading--small\':icon == \'small\',\'loading\': icon != \'count\'}" alt="Loading">\n <div class="att-loading-circle" ng-if="icon == \'count\'">\n <div class="att-loading-circle__mask att-loading-circle__full">\n <div class="att-loading-circle__fill"></div>\n </div>\n <div class="att-loading-circle__mask att-loading-circle__half">\n <div class="att-loading-circle__fill"></div>\n <div class="att-loading-circle__fill att-loading-circle__fix"></div>\n </div>\n </div>\n <div ng-class="{\'att-loading-inset\':icon == \'count\',\'loading__inside\':icon != \'count\'}"><div class="att-loading-inset__percentage" ng-if="icon == \'count\'" alt="Loading with Count"></div></div>\n</div>\n\n')}]),angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",'<div class="overlayed" ng-class="{show: animate}" \n'+" ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\"> \n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/modal/tabbedItem.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/modal/tabbedItem.html",'<div>\n <ul class="tabs_overlay">\n <li ng-repeat="item in items" class="tabs_overlay__item two__item" ng-class="{\'active\':isActiveTab($index)}" ng-click="clickTab($index)">\n <i class="{{item.iconClass}}"></i>\n {{item.title}} ({{item.number}})\n <a class="viewLink" att-link>Show</a>\n </li>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",'<div>\n <ul class="tabs_overlay">\n <li ng-repeat="item in items" class="tabs_overlay__item two__item" ng-class="{\'active\':isActiveTab($index)}" ng-click="clickTab($index)">\n <i class="{{item.iconClass}}"></i>\n {{item.title}} ({{item.number}})\n <a class="viewLink" att-link>Show</a>\n </li>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/modal/window.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/modal/window.html",'<div tabindex="-1" role="dialog" att-element-focus="focusModalFlag" class="modals {{ windowClass }}" ng-class="{show: animate}" \n ng-style="{\'z-index\': 2010 + index*10}" ng-click="close($event)" ng-transclude> \n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",'<div class="pager">\n <a tabindex="0" href="javascript:void(0)" class="pager__item--prev" att-accessibility-click="13,32" ng-click="prev($event)" ng-if="currentPage > 1"><i class="icon-arrow-left"></i> Previous</a>\n <a tabindex="0" href="javascript:void(0)" class="pager__item pager__item--link" ng-if="totalPages > 7 && currentPage > 3" att-accessibility-click="13,32" ng-click="selectPage(1, $event)">1</a>\n <span class="pager__item" ng-if="totalPages > 7 && currentPage > 3">...</span>\n <a tabindex="0" href="javascript:void(0)" class="pager__item pager__item--link" att-element-focus="isFocused(page)" ng-repeat="page in pages" ng-class="{\'pager__item--active\': checkSelectedPage(page)}" att-accessibility-click="13,32" ng-click="selectPage(page, $event)">{{page}}</a>\n <span class="pager__item" ng-if="totalPages > 7 && currentPage < totalPages - 2 && showInput !== true">...</span>\n <span ng-show="totalPages > 7 && showInput === true"><input class="pager__item--input" type="text" placeholder="..." maxlength="2" ng-model="currentPage" aria-label="Current page count"/></span>\n <a tabindex="0" href="javascript:void(0)" class="pager__item pager__item--link" ng-if="totalPages > 7 && currentPage < totalPages - 2" att-accessibility-click="13,32" ng-click="selectPage(totalPages, $event)">{{totalPages}}</a>\n <a tabindex="0" href="javascript:void(0)" class="pager__item--next" att-accessibility-click="13,32" ng-click="next($event)" ng-if="currentPage < totalPages">Next <i class="icon-arrow-right"></i></a>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html","<div class='inner-pane' ng-transclude></div>")}]),angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html","<div class='pane-group' ng-transclude></div>")}]),angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html","<div class='side-pane' ng-transclude></div>")}]),angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html","<div class=\"att-tooltip \" \n ng-class=\"{ 'att-tooltip--on': isOpen, \n 'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n 'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n 'att-tooltip--left':placement=='left', \n 'att-tooltip--above':placement=='above', \n 'att-tooltip--right':placement=='right', \n 'att-tooltip--below':placement=='below'}\" \n ng-bind-html=\"content | unsafe\" ></div>")}]),angular.module("app/scripts/ng_js_att_tpls/popOvers/popOvers.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/popOvers/popOvers.html","<div class=\"att-popover popover-demo\" ng-style=\"{backgroundColor:popOverStyle}\"\n ng-class=\"{'att-tooltip--dark':popOverStyle==='grey',\n 'att-pop-over--left':popOverPlacement==='left', \n 'att-pop-over--above':popOverPlacement==='above', \n 'att-pop-over--right':popOverPlacement==='right'}\" \n style='position: absolute; max-width: 490px;'>\n <div class=\"pop-over-caret\"\n ng-class=\"{'pop-over-caret-border--left':popOverPlacement==='left', \n 'pop-over-caret-border--above':popOverPlacement==='above', \n 'pop-over-caret-border--right':popOverPlacement==='right', \n 'pop-over-caret-border--below':popOverPlacement==='below'}\">\n </div>\n <div class=\"pop-over-caret\" ng-style=\"popOverPlacement=='below' && {borderBottom:'6px solid ' +popOverStyle}||popOverPlacement=='left' && {borderLeft:'6px solid ' +popOverStyle}||popOverPlacement=='right' && {borderRight:'6px solid ' +popOverStyle}||popOverPlacement=='above' && {borderTop:'6px solid ' +popOverStyle}\"\n ng-class=\"{'pop-over-caret--left':popOverPlacement==='left', \n 'pop-over-caret--above':popOverPlacement==='above', \n 'pop-over-caret--right':popOverPlacement==='right', \n 'pop-over-caret--below':popOverPlacement==='below'}\"></div>\n \n <div class=\"att-popover-content\">\n"+' <a ng-if="closeable" href="javascript:void(0)" class="icon-close att-popover__close" ng-click="closeMe();$event.preventDefault()"></a>\n <div class="popover-packages__container" ng-include="content"></div>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",'<div class="col-md-9 profile-card add-user">\n <div class="atcenter">\n <div><i class="icon-add"></i></div>\n <span>add User</span>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",'<div class="col-md-9 profile-card">\n <div class="top-block">\n <div class="profile-image">\n <img ng-if="image" profile-name="{{profile.name}}" ng-src="{{profile.img}}" alt="{{profile.name}}">\n <span ng-hide="image" class="default-img">{{initials}}</span>\n <p class="name" tooltip-condition="{{profile.name}}" height="true"></p>\n <p class="status">\n <span class="status-icon" ng-class="{\'icon-green\':colorIcon===\'green\',\'icon-red\':colorIcon===\'red\',\'icon-blue\':colorIcon===\'blue\',\'icon-yellow\':colorIcon===\'yellow\'}"> \n </span>\n <span>{{profile.state}}<span ng-if="badge" class="status-badge">Admin</span></span>\n </p>\n </div>\n </div>\n <div class="bottom-block">\n <div class="profile-details">\n <label>Username</label>\n <p att-text-overflow="92%" tooltip-condition="{{profile.userName}}">{{profile.userName}}</p>\n <label>Email</label>\n <p att-text-overflow="92%" tooltip-condition="{{profile.email}}">{{profile.email}}</p>\n <label>Role</label>\n <p att-text-overflow="92%" tooltip-condition="{{profile.role}}">{{profile.role}}</p>\n <label>Last Login</label>\n <p att-text-overflow="92%" tooltip-condition="{{profile.lastLogin}}">{{profile.lastLogin}}</p>\n </div>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",'<div class="att-progress">\n <div class="att-progress-value">&nbsp;</div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",'<div class="scroll-bar" style="position: absolute">\n <div class="scroll-thumb" style="position: absolute; overflow: hidden"></div>\n</div>\n<div class="prev icons-list" data-size="medium" ng-show="navigation && prevAvailable" ng-style="{height: scrollbarAxis === \'x\' && position.height + \'px\'}">\n <a href="javascript:void(0);" ng-click="customScroll(false)" aria-label="Scroll" aria-hidden="true">\n <i ng-class="{\'icon-chevron-up\': (scrollbarAxis === \'y\'), \'icon-chevron-left\': (scrollbarAxis === \'x\')}"></i>\n </a>\n</div>\n<div class="scroll-viewport" ng-style="{height: (scrollbarAxis === \'x\' && position.height + \'px\') || viewportHeight, width: viewportWidth}" style="position: relative; overflow: hidden">\n <div class="scroll-overview" style="position: absolute; display: table; width: 100%" att-position="position" ng-transclude></div>\n</div>\n<div class=\'next icons-list\' data-size="medium" ng-show="navigation && nextAvailable" ng-style="{height: scrollbarAxis === \'x\' && position.height + \'px\'}">\n <a href="javascript:void(0);" ng-click="customScroll(true)" aria-label="Scroll" aria-hidden="true">\n'+" <i ng-class=\"{'icon-chevron-down': (scrollbarAxis === 'y'), 'icon-chevron-right': (scrollbarAxis === 'x')}\"></i>\n </a>\n</div>\n")}]),angular.module("app/scripts/ng_js_att_tpls/search/search.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/search/search.html",'<div class="select2-container show-search" ng-class="{\'select2-dropdown-open\': (showlist && !isDisabled),\'select2-container-disabled\':isDisabled, \'select2-container-active\': isact}" ng-init="isact=false;" style="width: 100%;">\n <a href="javascript:void(0)" class="select2-choice needsclick" tabindex="0" ng-click="showDropdown()" ng-class="{\'select2-chosen-disabled\':isDisabled}" role="combobox" aria-expanded="{{showlist}}" aria-owns="inList" aria-label="{{selectedOption}} selected" ng-focus="isact=true;" ng-blur="isact=false;">\n <span class="select2-chosen needsclick" aria-hidden = "true">{{selectedOption}}</span>\n <abbr class="select2-search-choice-close needsclick"></abbr>\n <span class="select2-arrow needsclick" role="presentation">\n <b role="presentation" class="needsclick"></b>\n </span>\n </a> \n <input class="select2-focusser select2-offscreen" \n tabindex="-1" \n type="text" \n aria-hidden="true" \n title="hidden" \n aria-haspopup="true" \n role="button"> \n</div>\n\n<div class="select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active" ng-class="{\'select2-display-none\':(!showlist || isDisabled)}" style="width:100%;z-index: 10">\n <div class="select2-search">\n <label ng-if="!noFilter" class="select2-offscreen" aria-label="Inline Search Field" aria-hidden="true">Inline Search Field</label>\n <input ng-if="!noFilter" ng-model="title" aria-label="title" typeahead="c.title for c in cName | filter:$viewValue:startsWith" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" aria-autocomplete="list" placeholder="">\n </div>\n <ul id="inList" class="select2-results" role="listbox">\n <li ng-show="filteredName.length === 0" class="select2-no-results" tabindex="-1">No matches found</li>\n <li class="select2-results-dept-0 select2-result select2-result-selectable" role="presentation" ng-model="ListType" ng-show="selectMsg && filteredName.length > 0" ng-click="selectOption(selectMsg, \'-1\')" ng-class="{\'select2-result-current\': selectedOption === selectMsg, \'hovstyle\': selectedIndex === -1}" ng-mouseover="hoverIn(-1)" aria-label="{{selectMsg}}" tabindex="-1">\n <div ng-if="startsWithFilter" class="select2-result-label" ng-bind-html="selectMsg | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n <div ng-if="!startsWithFilter" class="select2-result-label" ng-bind-html="selectMsg | highlight:title:className | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n\n <li role="menuitem" ng-if="startsWithFilter" class="select2-results-dept-0 select2-result select2-result-selectable" role="presentation" ng-model="ListType" ng-repeat="(fIndex, item) in filteredName = (cName | startsWith:title:item)" ng-class="{\'select2-result-current\': selectedOption === item.title,\'hovstyle\': selectedIndex === item.index,\'disable\': item.disabled}" ng-click="item.disabled || selectOption(item.title,item.index)" ng-mouseover="hoverIn(item.index)" aria-label="{{item.title}}" tabindex="-1">\n <div class="select2-result-label" ng-bind-html="item.title | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n\n <li role="menuitem" ng-if="!startsWithFilter" class="select2-results-dept-0 select2-result select2-result-selectable" role="presentation" ng-model="ListType" ng-repeat="(fIndex, item) in filteredName = (cName | filter:title)" ng-class="{\'select2-result-current\': selectedOption === item.title,\'hovstyle\': selectedIndex === item.index,\'disable\': item.disabled}" ng-click="item.disabled || selectOption(item.title,item.index)" ng-mouseover="hoverIn(item.index)" aria-label="{{item.title}}" tabindex="-1">\n <div class="select2-result-label" ng-bind-html="item.title | highlight:title:className | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/select/select.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/select/select.html",'<div class="select2-container show-search" ng-class="{\'select2-dropdown-open\': (showlist && !isDisabled),\'select2-container-disabled\': isDisabled, \'select2-container-active\': isact}" ng-init="isact=false;">\n <span class="select2-choice needsclick" tabindex="{{isDisabled ? -1 : 0}}" ng-click="showDropdown()" ng-class="{\'select2-chosen-disabled\':isDisabled}" role="combobox" aria-expanded="{{showlist}}" aria-owns="inList" aria-label="{{selectedOption}} selected" ng-focus="isact=true;" ng-blur="isact=false;">\n <span class="select2-chosen needsclick" aria-hidden="true">{{selectedOption}}</span>\n <abbr class="select2-search-choice-close needsclick"></abbr>\n <span class="select2-arrow needsclick" role="presentation">\n <b role="presentation" class="needsclick"></b>\n </span>\n </span> \n <input class="select2-focusser select2-offscreen" \n tabindex="-1" \n type="text" \n aria-hidden="true" \n title="hidden" \n aria-haspopup="true" \n role="button"> \n</div>\n\n<div class="select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active" ng-class="{\'select2-display-none\':(!showlist || isDisabled)}" style="width:100%;z-index: 10">\n <div class="select2-search">\n <label ng-if="!noFilter" class="select2-offscreen" aria-label="Inline Search Field" aria-hidden="true">Inline Search Field</label>\n <input ng-if="!noFilter" ng-model="title" aria-label="title" typeahead="c.title for c in cName | filter:$viewValue:startsWith" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" aria-autocomplete="list" placeholder="">\n </div>\n <ul id="inList" class="select2-results" role="listbox">\n <li ng-if="!noFilter" ng-show="filteredName.length === 0" class="select2-no-results" tabindex="-1">No matches found</li>\n <li ng-if="!noFilter" class="select2-results-dept-0 select2-result select2-result-selectable" role="presentation" ng-model="ListType" ng-show="selectMsg && filteredName.length > 0" ng-click="selectOption(selectMsg, \'-1\')" ng-class="{\'select2-result-current\': selectedOption === selectMsg, \'hovstyle\': selectedIndex === -1}" ng-mouseover="hoverIn(-1)" aria-label="{{selectMsg}}" tabindex="-1">\n <div ng-if="startsWithFilter" class="select2-result-label" ng-bind-html="selectMsg | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n <div ng-if="!startsWithFilter" class="select2-result-label" ng-bind-html="selectMsg | highlight:title:className | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n\n <li role="menuitem" ng-if="startsWithFilter" class="select2-results-dept-0 select2-result select2-result-selectable" ng-model="ListType" ng-repeat="(fIndex, item) in filteredName = (cName | startsWith:title:item)" ng-class="{\'select2-result-current\': selectedOption === item.title,\'hovstyle\': selectedIndex === item.index,\'disable\': item.disabled}" ng-click="item.disabled || selectOption(item.title,item.index)" ng-mouseover="hoverIn(item.index)" tabindex="-1">\n <div class="select2-result-label" ng-bind-html="item.title | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n\n <li role="menuitem" ng-if="!startsWithFilter" class="select2-results-dept-0 select2-result select2-result-selectable" ng-model="ListType" ng-repeat="(fIndex, item) in filteredName = (cName | filter:title)" ng-class="{\'select2-result-current\': selectedOption === item.title,\'hovstyle\': selectedIndex === item.index,\'disable\': item.disabled}" ng-click="item.disabled || selectOption(item.title,item.index)" ng-mouseover="hoverIn(item.index)" tabindex="-1">\n <div class="select2-result-label" ng-bind-html="item.title | highlight:title:className | unsafe" role="option">\n <span class="select2-match"></span>\n </div>\n </li>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",'<div tabindex="0" class="text-dropdown">\n <div class="dropdown" ng-class="{\'not-visible\': isActionsShown}" ng-click="toggle()">\n <span class="action--selected" ng-bind="currentAction"></span>\n <i ng-class="isActionsShown ? \'icon-dropdown-up\' : \'ion-arrow-down-b\'"></i>\n </div>\n <ul ng-class="isActionsShown ? \'actionsOpened\' : \'actionsClosed\'" ng-show="isActionsShown">\n <li ng-class="{\'highlight\': selectedIndex==$index}" ng-repeat="action in actions track by $index" ng-click="chooseAction($event, action, $index)" ng-mouseover="hoverIn($index)">{{action}}<i ng-class="{\'icon-included-checkmark\': isCurrentAction(action)}" att-accessibility-click="13,32"></i></li>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",'<div class="att-slider__label att-slider__label--max att-slider__label--below" ng-transclude></div>')}]),angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/slider/minContent.html",'<div class="att-slider__label att-slider__label--min att-slider__label--below" ng-transclude></div>')}]),angular.module("app/scripts/ng_js_att_tpls/slider/slider.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/slider/slider.html",'<div class="att-slider" ng-mousemove="moveElem($event)" ng-mouseup="mouseUp($event)">\n <div class="att-slider__track">\n <div class="att-slider__range att-slider__range--disabled" ng-style="disabledStyle"></div>\n <div class="att-slider__range" ng-style="rangeStyle"></div>\n </div>\n <div class="att-slider__handles-container">\n <div role="menuitem" aria-label="{{ngModelSingle}}" class="att-slider__handle" ng-style="handleStyle" ng-mousedown="mouseDown($event,\'ngModelSingle\')" ng-mousemove="moveElem($event)" ng-mouseup="mouseUp($event)" tabindex="0" ng-keydown="keyDown($event,\'ngModelSingle\')"></div>\n <div role="menuitem" aria-label="Minimum Value- {{ngModelLow}}" class="att-slider__handle" ng-style="minHandleStyle" ng-mousedown="mouseDown($event,\'ngModelLow\')" ng-focus="focus($event,\'ngModelLow\')" ng-mousemove="moveElem($event)" ng-mouseup="mouseUp($event)" tabindex="0" ng-keyup="keyUp($event,\'ngModelLow\')" ng-keydown="keyDown($event,\'ngModelLow\')"></div>\n <div role="menuitem" aria-label="Maximum Value- {{ngModelHigh}}" class="att-slider__handle" ng-style="maxHandleStyle" ng-mousedown="mouseDown($event,\'ngModelHigh\')" ng-focus="focus($event,\'ngModelHigh\')" ng-mousemove="moveElem($event)" ng-mouseup="mouseUp($event)" tabindex="0" ng-keyup="keyUp($event,\'ngModelHigh\')" ng-keydown="keyDown($event,\'ngModelHigh\')"></div>\n </div>\n <div ng-transclude></div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",'<div class=" btn-group" \n ng-class="{\'buttons-dropdown--large\':!isSmall, \n \'buttons-dropdown--small\':isSmall, \n \'action-dropdown\':(isActionDropdown), \n \'open\':isDropDownOpen}">\n <a tabindex="0" href="javascript:void(0)" class="button btn buttons-dropdown__split" \n ng-class="{\'button--primary\':(btnType==undefined || btnType==\'primary\'), \n \'button--secondary\':btnType==\'secondary\', \n \'button--disabled\':btnType==\'disabled\', \n \'button--small\':isSmall}" \n ng-if="!isActionDropdown"\n ng-click="btnType===\'disabled\'?undefined:clickFxn()" att-accessibility-click="13,32">{{btnText}}</a>\n <a tabindex="0" href="javascript:void(0)" role="button" aria-label="Toggle Dropdown" aria-haspopup="true" class="button buttons-dropdown__drop dropdown-toggle" \n ng-class="{\'button--primary\':(btnType==undefined || btnType==\'primary\'), \n \'button--secondary\':btnType==\'secondary\', \n \'button--disabled\':btnType==\'disabled\', \n \'button--small\':isSmall}" ng-click="toggleDropdown()" att-accessibility-click="13,32">{{toggleTitle}} </a>\n <ul class="dropdown-menu" ng-class="{\'align-right\':multiselect ===true}" aria-expanded="{{isDropDownOpen}}" ng-click="hideDropdown()" role="menu" ng-transclude></ul>\n</div> ')}]),angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",'<li role="menuitem" att-element-focus="sFlag" tabindex="0" ng-transclude></li>')}]),angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html","<div class='split-icon-button-container'>\n\n <div class='split-icon-button' ng-class=\"{'icon-with-chevron': isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown, 'split-icon-button-middle':isMiddle, 'split-icon-button-right':isRight, 'split-icon-button-left':isLeft, 'split-icon-button-left-dropdown': isLeftNextDropdown ,'split-icon-button-next-dropdown': isNextToDropDown,'split-icon-button-dropdown': isDropDownOpen,'split-icon-button-hover':isIconHovered || isDropDownOpen}\" ng-mouseover='isIconHovered = true;' ng-mouseleave='isIconHovered = false;' tabindex=\"-1\" att-accessibility-click=\"13,32\" ng-click='dropDownClicked();'>\n <a class='{{icon}}' title='{{iconTitle}}' tabindex=\"0\"></a>\n <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n ng-class=\"isDropDownOpen ? 'icon-dropdown-up' : 'ion-arrow-down-b'\"> </i>\n </div> \n\n <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n isDropDownOpen' ng-click='toggleDropdown(false)' role=\"presentation\" ng-transclude>\n </ul>\n\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html","<div>\n <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n <div ng-click='clickHandler()' att-split-icon icon='{{icon}}' title='{{title}}' dir-type='{{iconStateConstants.DIR_TYPE.BUTTON}}' hover-watch='isHovered' drop-down-watch='dropDownWatch' drop-down-id='{{dropDownId}}'>\n <div ng-transclude>\n </div>\n </div>\n <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html","<div ng-transclude>\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",'<span ng-class="mainSliderClass">\n <table>\n <tr>\n <td>\n <div class="jslider-bg">\n <i class="l"></i>\n <i class="r"></i>\n <i class="v" ng-class="{\'step-slider-green\':sliderColor == COLORS.GREEN, \'step-slider-blue\': sliderColor == COLORS.BLUE_HIGHLIGHT, \'step-slider-magenta\': sliderColor == COLORS.MAGENTA, \'step-slider-gold\': sliderColor == COLORS.GOLD, \'step-slider-purple\': sliderColor == COLORS.PURPLE, \'step-slider-dark-blue\': sliderColor == COLORS.DARK_BLUE, \'step-slider-regular\': sliderColor == COLORS.REGULAR, \'step-slider-white\': sliderColor == COLORS.WHITE, \'cutoff-slider\': isCutOffSlider}"></i>\n </div>\n <div class="jslider-pointer" id="left-pointer"></div>\n <div class="jslider-pointer jslider-pointer-to" ng-class="{\'step-slider-green\':sliderColor == COLORS.GREEN, \'step-slider-blue\': sliderColor == COLORS.BLUE_HIGHLIGHT, \'step-slider-magenta\': sliderColor == COLORS.MAGENTA, \'step-slider-gold\': sliderColor == COLORS.GOLD, \'step-slider-purple\': sliderColor == COLORS.PURPLE, \'step-slider-dark-blue\': sliderColor == COLORS.DARK_BLUE, \'step-slider-regular\': sliderColor == COLORS.REGULAR, \'step-slider-white\':sliderColor == COLORS.WHITE ,\'cutoff-slider\': isCutOffSlider}"></div>\n <div class="jslider-label"><span ng-bind="from"></span><span ng-bind="options.dimension"></span></div>\n <div class="jslider-label jslider-label-to"><span ng-bind="toStr"></span><span ng-bind="endDimension"></span></div>\n <div class="jslider-value" id="jslider-value-left"><span></span>{{options.dimension}}</div>\n <div class="jslider-value jslider-value-to"><span></span>{{toolTipDimension}}</div>\n <div class="jslider-scale" ng-class="{\'show-dividers\': showDividers, \'cutoff-slider-dividers\':isCutOffSlider}">\n </div>\n <div class="jslider-cutoff">\n <div class="jslider-label jslider-label-cutoff">\n <span ng-bind="cutOffVal"></span>\n </div>\n </div>\n </td>\n </tr>\n </table>\n</span>\n')}]),angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",'<div class="steptracker1">\n <div class="steptracker-bg">\n <div tabindex="0" ng-click="stepclick($event, $index);" att-accessibility-click="13,23" class="steptracker-track size-onethird" ng-repeat="step in sdata"\n ng-style="set_width($index)"\n ng-class="{\'last\':laststep($index),\'done\':donesteps($index),\'active\':activestep($index), \'incomplete\': isIncomplete($index), \'disabled\': disableClick}">\n <div class="circle">{{($index) + 1}}<span>{{step.title}}</span></div>\n <div ng-if="!laststep($index)" class="track"></div>\n </div>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/steptracker/step.html",'<div class="steptracker1">\n <div class="steptracker-bg">\n <div class="steptracker-track size-onethird" \n ng-class="{\'last\':laststep($index),\'done\':donesteps($index),\'active\':activestep($index)}">\n <div class="circle" tabindex="0" \n ng-click="stepclick($event, $index);" \n att-accessibility-click="13,23">{{($index) + 1}}<span>{{step.title}}</span></div>\n <div ng-if="!laststep($index)" class="track"></div>\n </div>\n </div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html",[]).run(["$templateCache",function(a){
-a.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html","<div class='att-timeline'>\n <div timeline-dot order='0' title='{{steps[0].title}}' description='{{steps[0].description}}' by='{{steps[0].by}}' date='{{steps[0].date}}' type='{{steps[0].type}}'></div>\n\n <div ng-repeat=\"m in middleSteps track by $index\">\n <div timeline-bar order='{{$index}}'></div>\n <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n </div>\n </div>\n\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html","<div class='timeline-bar'>\n <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n </div>\n <hr></hr>\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html","<div class='timeline-dot'>\n\n <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n </div>\n\n <div class='inactive-circle'>\n </div>\n\n <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n </div>\n\n <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\" tabindex=\"0\">\n \n <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n </div>\n\n <div class='info-container' ng-init='isContentShown=false'>\n <div ng-class=\"{'current-step-title':isCurrentStep, 'title':!isCurrentStep,'completed-color-text':isCompleted,'cancelled-color-text':isCancelled,'alert-color-text':isAlert, 'inactive-color-text':isInactive}\" ng-mouseover='titleMouseover(1)' ng-mouseleave='titleMouseleave()' ng-bind='title' ></div>\n <div class='content'>\n <div class='description' ng-bind='description'></div>\n <div class='submitter' ng-bind='by'></div>\n </div>\n <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave()' ng-bind='date'></div>\n </div>\n\n <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n </div>\n </div>\n\n</div>")}]),angular.module("app/scripts/ng_js_att_tpls/table/attTable.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/table/attTable.html",'<table class="tablesorter tablesorter-default" ng-transclude></table>\n')}]),angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/table/attTableBody.html","<td ng-transclude></td>\n")}]),angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html","<th role=\"button\" aria-label=\"column header {{headerName}} {{sortable !== 'false' && '' || 'sortable'}} {{sortPattern !== 'null' && '' || sortPattern}}\" tabindex=\"{{sortable !== 'false' && '0' || '-1'}}\" class=\"tablesorter-header\" ng-class=\"{'tablesorter-headerAsc': sortPattern === 'asc', 'tablesorter-headerDesc': sortPattern === 'desc', 'tablesort-sortable': sortable !== 'false', 'sorter-false': sortable === 'false'}\" att-accessibility-click=\"13,32\" ng-click=\"(sortable !== 'false') && sort();\"><div class=\"tablesorter-header-inner\" ng-transclude></div></th>")}]),angular.module("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",'<div class="att-table-message">\n <div class="message" ng-if="msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching">\n <div class="img-magnify-glass"></div> \n <div>\n <div ng-transclude></div>\n </div>\n </div>\n <div class="message" ng-if="msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading">\n <div class="img-oops-exclamation" tabindex="0" aria-label="Oops! The information could not load at this time. Please click link to refresh the page."></div> \n <div>Oops!</div>\n <div>The information could not load at this time.</div>\n <div>Please <a href="javascript:void(0)" ng-click="refreshAction($event)">refresh the page</a>\n </div>\n </div>\n <div class="message" ng-if="msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch">\n <div class="img-magnify-glass"></div>\n <div>\n <p class="title" tabindex="0">Please input values to <br/> begin your search.</p>\n </div>\n </div>\n <div class="message loading-message" ng-if="msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading">\n <div class="img-loading-dots"></div>\n <div ng-transclude></div>\n </div>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",'<div class="att-user-message">\n <div ng-class="type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? \'message-wrapper-error\' : \'hidden\'">\n <div class="message-icon-error"> <i class="icon-info-alert"></i> </div>\n\n <div class="message-body-wrapper">\n <div class="message-title-error" ng-if="thetitle && thetitle.length > 0"> <span ng-bind="thetitle" tabindex="0" aria-label="{{thetitle}}"></span> </div>\n <div class="message-msg" ng-bind="message" ng-if="message && message.length > 0" tabindex="0"></div>\n <div class="message-bottom">\n <div ng-transclude></div>\n </div>\n </div>\n\n </div>\n <div ng-class="type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? \'message-wrapper-success\' : \'hidden\'">\n <div class="message-icon-success"> <i class="icon-included-checkmark"></i></div>\n\n <div class="message-body-wrapper">\n <div class="message-title-success" ng-if="thetitle && thetitle.length > 0" >\n <span ng-bind="thetitle" tabindex="0" aria-label="{{thetitle}}"></span>\n </div>\n <div class="message-msg" ng-bind="message" ng-if="message && message.length > 0" tabindex="0"></div>\n <div class="message-bottom">\n <div ng-transclude></div>\n </div>\n </div>\n\n </div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html","<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActiveTab(tab.url), 'tabsbid__item': !isActiveTab(tab.url)}\" ng-click=\"onClickTab(tab)\">\n"+' <a class="tabsbid__item-link" href="{{tab.url}}" tabindex="0" att-accessibility-click="32,13">{{tab.title}}</a>\n </li>\n</ul>')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html","<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActive(tab.id), 'tabsbid__item': !isActive(tab.id),'tabs__item--active': isActive(tab.id)}\" ng-click=\"clickTab(tab)\">\n"+' <a class="tabsbid__item-link" href="{{tab.url}}" tabindex="0" att-accessibility-click="32,13">{{tab.title}}</a>\n </li>\n</ul>\n')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",'<li class="megamenu__item" ng-mouseover="showHoverChild($event)" ng-class="{\'tabs__item--active\': menuItem.active==true && !hoverChild==true}">\n <span role="menuitem" att-accessibility-click="13,32" tabindex="0" ng-click="showChildren($event);!clickInactive||resetMenu($event)">{{tabName}}</span>\n <div ng-transclude></div>\n</li>\n')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",'<div ng-class="{\'megamenu-tabs\': megaMenu,\'submenu-tabs\': !megaMenu}">\n <ul class="megamenu__items" role="presentation" ng-transclude>\n </ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",'<div class="simplified-tabs">\n<ul class="simplified-tabs__items" role="tablist">\n <li ng-repeat="tab in tabs" role="tab" class="simplified-tabs__item" ng-class="{\'tabs__item--active\': isActive(tab.id)}" ng-click="clickTab(tab)" tabindex="0" att-accessibility-click="32,13">{{tab.title}}</li>\n <li class="tabs__pointer"></li>\n</ul>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",'<li class="tabsbid__item megamenu__item" ng-class="{\'subMenuHover\': menuItem.active==true}">\n<a ng-href="{{tabUrl}}" role="menuitem" ng-if="subMenu === true" ng-mouseover="!subMenu || showChildren($event)" ng-focus="!subMenu ||showChildren($event)" tabindex="{{subMenu==\'true\'?0:-1}}" ng-click="!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)" att-accessibility-click="13,32">{{tabName}}</a>\n<a ng-href="{{tabUrl}}" role="menuitem" ng-if="!menuItem.leafNode && subMenu !== true" ng-mouseover="!subMenu || showChildren($event)" ng-focus="!subMenu ||showChildren($event)" tabindex="{{subMenu==\'true\'?0:-1}}" ng-click="!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)" att-accessibility-click="13,32">{{tabName}}</a>\n<span ng-transclude></span>\n</li>\n')}]),angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html","<div class=\"tags__item\" \n ng-class=\"{'tags__item--small':isSmall, \n 'tags__item--color':isColor, \n 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n ng-if=\"display\" \n ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n"+' ng-mousedown="activeHighlight(true)" role="presentation" ng-mouseup="activeHighlight(false)">\n <i class="icon-filter tags__item--icon" ng-if="isIcon">&nbsp;</i>\n <i class="tags__item--color-icon" ng-if="isColor" ng-style="{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}"></i>\n <span class="tags__item--title" role="presentation" tabindex=0 aria-label="tag" ng-mousedown="activeHighlight(true)" ng-mouseup="activeHighlight(false)" ng-transclude></span>\n <a href="javascript:void(0)" title="Dismiss Link" class="tags__item--action" ng-click="closeMe();$event.preventDefault()" ng-if="isClosable"\n ng-style="{color: (isHighlight && \'#444\') || \'#888\' , borderLeft: (isHighlight && \'1px solid #444\')|| \'1px solid #888\' }">\n <i class="icon-erase">&nbsp;</i>\n </a>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",'<span ng-transclude></span>\n<div class="att-switch-content" hm-drag = "drag($event)" att-accessibility-click="13,32" ng-click="updateModel($event)" hm-dragstart="alert(\'hello\')" hm-dragend="drag($event)" ng-class="{\'large\' : directiveValue == \'large\'}" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">\n <div class="att-switch-onText" ng-style="" ng-class="{\'icon-included-checkmark ico\' : on === undefined,\'large\' : directiveValue == \'large\'}">{{on}}<span class="hidden-spoken">{{directiveValue}} when checked.</span></div>\n <div class="att-switch-thumb" tabindex="0" title="Toggle switch" role="checkbox" ng-class="{\'large\' : directiveValue == \'large\'}"></div>\n <div class="att-switch-offText" ng-class="{\'icon-erase ico\' : on === undefined,\'large\' : directiveValue == \'large\'}">{{off}}<span class="hidden-spoken">{{directiveValue}} when unchecked.</span></div>\n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",'<div class="typeahead mainContainerOuter">\n <span class="message">To</span>\n <div class=\'maincontainer\' ng-click="setFocus()" ng-focus="inputActive=true" ng-class ="{\'typeahed_active\':inputActive || (lineItems.length && inputActive)}">\n <span tag-badges closable ng-repeat ="lineItem in lineItems track by $index" on-close="theMethodToBeCalled($index)" >{{lineItem}}</span>\n <input type="text" focus-me="clickFocus" ng-focus="inputActive=true" ng-model="model" ng-keydown="selected = false; selectionIndex($event)"/><br/> \n </div>\n <div ng-hide="!model.length || selected">\n <div class="filtercontainer list-scrollable" ng-show="( items | filter:model).length">\n <div class="item" ng-repeat="item in items| filter:model track by $index" ng-click="handleSelection(item[titleName],item[subtitle])" att-accessibility-click="13,32" ng-class="{active:isCurrent($index,item[titleName],item[subtitle],( items | filter:model).length)}"ng-mouseenter="setCurrent($index)">\n <span class="title" >{{item[titleName]}}</span>\n <span class="subtitle">{{item[subtitle]}}</span>\n </div> \n </div>\n </div>\n \n <div class="textAreaEmailContentDiv">\n <span class="message">Message</span>\n <textarea rows="4" cols="50" role="textarea" class="textAreaEmailContent" ng-model="emailMessage">To send \n a text, picture, or video message1 to a wireless device from your email:my message.</textarea>\n \n </div>\n \n</div>\n')}]),angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html","<li>\n <i ng-class=\"{'icon-tickets-active' : type == 'actual' && id =='Active','icon-tickets-referred' : type == 'actual' && id =='Requested Closed','icon-ticket-regular' : type == 'progress' && id =='In Progress','icon-tickets-contested' : type == 'actual' && id =='Contested','icon-tickets-returned' : type == 'actual' && id =='Deferred','icon-tickets-closed' : type == 'actual' && id =='Ready to Close','icon-tickets-cleared' : type == 'actual' && id =='Cleared'}\"></i>\n <span ng-transclude></span>\n</li>\n \n")}]),angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",'<div>\n <a title="{{links.prevLink}}" aria-label="Previous Link" ng-href="{{links.prevLink}}"><i alt="previous" class="icon-arrow-left">&nbsp;</i></a>\n <span ng-transclude></span>\n <a title="{{links.nextLink}}" aria-label="Next Link" ng-href="{{links.nextLink}}"><i alt="next" class="icon-arrow-right">&nbsp;</i></a>\n</div>')}]),angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",[]).run(["$templateCache",function(a){a.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",'<div class="video-player">\n <div class="video-player__control video-player__play-button">\n <a class="video-player__button gigant-play" data-toggle-buttons="icon-play, icon-pause" data-target="i"><i class="icon-play" alt="Play/Pause Button"></i></a>\n </div>\n <div class="video-player__control video-player__track">\n\n <div class="video-player__track--inner">\n <div class="video-player__track--loaded" style="width: 75%"></div>\n <div class="video-player__track--played" style="width: 40%">\n <div class="att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip" ng-transclude></div>\n <div class="video-player__track-handle"></div>\n </div>\n </div>\n </div>\n <a class="video-player__time" ng-transclude></a>\n <div class="video-player__control video-player__volume_icon">\n <a class="video-player__button" data-toggle-buttons="icon-volume-mute, icon-volume-up" data-target="i"><i class="icon-volume-up" alt="Volume Button"></i></a>\n </div>\n <ul class="video-player__control video-player__volume">\n <li class="video-player__volume-bar video-player__volume-bar--full">&nbsp;</li>\n <li class="video-player__volume-bar video-player__volume-bar--full">&nbsp;</li>\n <li class="video-player__volume-bar">&nbsp;</li>\n <li class="video-player__volume-bar">&nbsp;</li>\n <li class="video-player__volume-bar">&nbsp;</li>\n </ul>\n <div class="video-player__control video-player__toggle-fullscreen-button">\n <a class="video-player__button" data-toggle-buttons="icon-full-screen, icon-normal-screen" data-target="i"><i class="icon-full-screen" alt="Full Screen Button">&nbsp;</i></a>\n </div>\n</div>')}]);
-return {}
-})(angular, window); \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/base.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/base.css
deleted file mode 100644
index fc4b1c3d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/base.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:active,a:hover{outline:0}h1{margin:.67em 0}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}button,input,select,textarea{margin:0}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:transparent}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:focus,a:hover{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail,.thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:6px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#c09853}.text-warning:hover{color:#a47e3c}.text-danger{color:#b94a48}.text-danger:hover{color:#953b39}.text-success{color:#468847}.text-success:hover{color:#356635}.text-info{color:#3a87ad}.text-info:hover{color:#2d6987}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:700;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-bottom:20px}dd,dt{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{content:" ";display:table}.dl-horizontal dd:after{clear:both}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right .small,blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right .small:before,blockquote.pull-right small:before{content:''}blockquote.pull-right .small:after,blockquote.pull-right small:after{content:'\00A0 \2014'}blockquote:after,blockquote:before{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:6px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:6px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:10px;padding-right:10px}.container:after,.container:before{content:" ";display:table}.container:after{clear:both}.row{margin-left:-10px;margin-right:-10px}.row:after,.row:before{content:" ";display:table}.row:after{clear:both}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-13,.col-lg-14,.col-lg-15,.col-lg-16,.col-lg-17,.col-lg-18,.col-lg-19,.col-lg-2,.col-lg-20,.col-lg-21,.col-lg-22,.col-lg-23,.col-lg-24,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-13,.col-md-14,.col-md-15,.col-md-16,.col-md-17,.col-md-18,.col-md-19,.col-md-2,.col-md-20,.col-md-21,.col-md-22,.col-md-23,.col-md-24,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-13,.col-sm-14,.col-sm-15,.col-sm-16,.col-sm-17,.col-sm-18,.col-sm-19,.col-sm-2,.col-sm-20,.col-sm-21,.col-sm-22,.col-sm-23,.col-sm-24,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-13,.col-xs-14,.col-xs-15,.col-xs-16,.col-xs-17,.col-xs-18,.col-xs-19,.col-xs-2,.col-xs-20,.col-xs-21,.col-xs-22,.col-xs-23,.col-xs-24,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-left:10px;padding-right:10px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-13,.col-xs-14,.col-xs-15,.col-xs-16,.col-xs-17,.col-xs-18,.col-xs-19,.col-xs-2,.col-xs-20,.col-xs-21,.col-xs-22,.col-xs-23,.col-xs-24,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-1{width:4.1666666667%}.col-xs-2{width:8.3333333333%}.col-xs-3{width:12.5%}.col-xs-4{width:16.6666666667%}.col-xs-5{width:20.8333333333%}.col-xs-6{width:25%}.col-xs-7{width:29.1666666667%}.col-xs-8{width:33.3333333333%}.col-xs-9{width:37.5%}.col-xs-10{width:41.6666666667%}.col-xs-11{width:45.8333333333%}.col-xs-12{width:50%}.col-xs-13{width:54.1666666667%}.col-xs-14{width:58.3333333333%}.col-xs-15{width:62.5%}.col-xs-16{width:66.6666666667%}.col-xs-17{width:70.8333333333%}.col-xs-18{width:75%}.col-xs-19{width:79.1666666667%}.col-xs-20{width:83.3333333333%}.col-xs-21{width:87.5%}.col-xs-22{width:91.6666666667%}.col-xs-23{width:95.8333333333%}.col-xs-24{width:100%}.col-xs-pull-0{right:0}.col-xs-pull-1{right:4.1666666667%}.col-xs-pull-2{right:8.3333333333%}.col-xs-pull-3{right:12.5%}.col-xs-pull-4{right:16.6666666667%}.col-xs-pull-5{right:20.8333333333%}.col-xs-pull-6{right:25%}.col-xs-pull-7{right:29.1666666667%}.col-xs-pull-8{right:33.3333333333%}.col-xs-pull-9{right:37.5%}.col-xs-pull-10{right:41.6666666667%}.col-xs-pull-11{right:45.8333333333%}.col-xs-pull-12{right:50%}.col-xs-pull-13{right:54.1666666667%}.col-xs-pull-14{right:58.3333333333%}.col-xs-pull-15{right:62.5%}.col-xs-pull-16{right:66.6666666667%}.col-xs-pull-17{right:70.8333333333%}.col-xs-pull-18{right:75%}.col-xs-pull-19{right:79.1666666667%}.col-xs-pull-20{right:83.3333333333%}.col-xs-pull-21{right:87.5%}.col-xs-pull-22{right:91.6666666667%}.col-xs-pull-23{right:95.8333333333%}.col-xs-pull-24{right:100%}.col-xs-push-0{left:0}.col-xs-push-1{left:4.1666666667%}.col-xs-push-2{left:8.3333333333%}.col-xs-push-3{left:12.5%}.col-xs-push-4{left:16.6666666667%}.col-xs-push-5{left:20.8333333333%}.col-xs-push-6{left:25%}.col-xs-push-7{left:29.1666666667%}.col-xs-push-8{left:33.3333333333%}.col-xs-push-9{left:37.5%}.col-xs-push-10{left:41.6666666667%}.col-xs-push-11{left:45.8333333333%}.col-xs-push-12{left:50%}.col-xs-push-13{left:54.1666666667%}.col-xs-push-14{left:58.3333333333%}.col-xs-push-15{left:62.5%}.col-xs-push-16{left:66.6666666667%}.col-xs-push-17{left:70.8333333333%}.col-xs-push-18{left:75%}.col-xs-push-19{left:79.1666666667%}.col-xs-push-20{left:83.3333333333%}.col-xs-push-21{left:87.5%}.col-xs-push-22{left:91.6666666667%}.col-xs-push-23{left:95.8333333333%}.col-xs-push-24{left:100%}.col-xs-offset-0{margin-left:0}.col-xs-offset-1{margin-left:4.1666666667%}.col-xs-offset-2{margin-left:8.3333333333%}.col-xs-offset-3{margin-left:12.5%}.col-xs-offset-4{margin-left:16.6666666667%}.col-xs-offset-5{margin-left:20.8333333333%}.col-xs-offset-6{margin-left:25%}.col-xs-offset-7{margin-left:29.1666666667%}.col-xs-offset-8{margin-left:33.3333333333%}.col-xs-offset-9{margin-left:37.5%}.col-xs-offset-10{margin-left:41.6666666667%}.col-xs-offset-11{margin-left:45.8333333333%}.col-xs-offset-12{margin-left:50%}.col-xs-offset-13{margin-left:54.1666666667%}.col-xs-offset-14{margin-left:58.3333333333%}.col-xs-offset-15{margin-left:62.5%}.col-xs-offset-16{margin-left:66.6666666667%}.col-xs-offset-17{margin-left:70.8333333333%}.col-xs-offset-18{margin-left:75%}.col-xs-offset-19{margin-left:79.1666666667%}.col-xs-offset-20{margin-left:83.3333333333%}.col-xs-offset-21{margin-left:87.5%}.col-xs-offset-22{margin-left:91.6666666667%}.col-xs-offset-23{margin-left:95.8333333333%}.col-xs-offset-24{margin-left:100%}@media (min-width:768px){.container{width:740px}.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-13,.col-sm-14,.col-sm-15,.col-sm-16,.col-sm-17,.col-sm-18,.col-sm-19,.col-sm-2,.col-sm-20,.col-sm-21,.col-sm-22,.col-sm-23,.col-sm-24,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-1{width:4.1666666667%}.col-sm-2{width:8.3333333333%}.col-sm-3{width:12.5%}.col-sm-4{width:16.6666666667%}.col-sm-5{width:20.8333333333%}.col-sm-6{width:25%}.col-sm-7{width:29.1666666667%}.col-sm-8{width:33.3333333333%}.col-sm-9{width:37.5%}.col-sm-10{width:41.6666666667%}.col-sm-11{width:45.8333333333%}.col-sm-12{width:50%}.col-sm-13{width:54.1666666667%}.col-sm-14{width:58.3333333333%}.col-sm-15{width:62.5%}.col-sm-16{width:66.6666666667%}.col-sm-17{width:70.8333333333%}.col-sm-18{width:75%}.col-sm-19{width:79.1666666667%}.col-sm-20{width:83.3333333333%}.col-sm-21{width:87.5%}.col-sm-22{width:91.6666666667%}.col-sm-23{width:95.8333333333%}.col-sm-24{width:100%}.col-sm-pull-0{right:0}.col-sm-pull-1{right:4.1666666667%}.col-sm-pull-2{right:8.3333333333%}.col-sm-pull-3{right:12.5%}.col-sm-pull-4{right:16.6666666667%}.col-sm-pull-5{right:20.8333333333%}.col-sm-pull-6{right:25%}.col-sm-pull-7{right:29.1666666667%}.col-sm-pull-8{right:33.3333333333%}.col-sm-pull-9{right:37.5%}.col-sm-pull-10{right:41.6666666667%}.col-sm-pull-11{right:45.8333333333%}.col-sm-pull-12{right:50%}.col-sm-pull-13{right:54.1666666667%}.col-sm-pull-14{right:58.3333333333%}.col-sm-pull-15{right:62.5%}.col-sm-pull-16{right:66.6666666667%}.col-sm-pull-17{right:70.8333333333%}.col-sm-pull-18{right:75%}.col-sm-pull-19{right:79.1666666667%}.col-sm-pull-20{right:83.3333333333%}.col-sm-pull-21{right:87.5%}.col-sm-pull-22{right:91.6666666667%}.col-sm-pull-23{right:95.8333333333%}.col-sm-pull-24{right:100%}.col-sm-push-0{left:0}.col-sm-push-1{left:4.1666666667%}.col-sm-push-2{left:8.3333333333%}.col-sm-push-3{left:12.5%}.col-sm-push-4{left:16.6666666667%}.col-sm-push-5{left:20.8333333333%}.col-sm-push-6{left:25%}.col-sm-push-7{left:29.1666666667%}.col-sm-push-8{left:33.3333333333%}.col-sm-push-9{left:37.5%}.col-sm-push-10{left:41.6666666667%}.col-sm-push-11{left:45.8333333333%}.col-sm-push-12{left:50%}.col-sm-push-13{left:54.1666666667%}.col-sm-push-14{left:58.3333333333%}.col-sm-push-15{left:62.5%}.col-sm-push-16{left:66.6666666667%}.col-sm-push-17{left:70.8333333333%}.col-sm-push-18{left:75%}.col-sm-push-19{left:79.1666666667%}.col-sm-push-20{left:83.3333333333%}.col-sm-push-21{left:87.5%}.col-sm-push-22{left:91.6666666667%}.col-sm-push-23{left:95.8333333333%}.col-sm-push-24{left:100%}.col-sm-offset-0{margin-left:0}.col-sm-offset-1{margin-left:4.1666666667%}.col-sm-offset-2{margin-left:8.3333333333%}.col-sm-offset-3{margin-left:12.5%}.col-sm-offset-4{margin-left:16.6666666667%}.col-sm-offset-5{margin-left:20.8333333333%}.col-sm-offset-6{margin-left:25%}.col-sm-offset-7{margin-left:29.1666666667%}.col-sm-offset-8{margin-left:33.3333333333%}.col-sm-offset-9{margin-left:37.5%}.col-sm-offset-10{margin-left:41.6666666667%}.col-sm-offset-11{margin-left:45.8333333333%}.col-sm-offset-12{margin-left:50%}.col-sm-offset-13{margin-left:54.1666666667%}.col-sm-offset-14{margin-left:58.3333333333%}.col-sm-offset-15{margin-left:62.5%}.col-sm-offset-16{margin-left:66.6666666667%}.col-sm-offset-17{margin-left:70.8333333333%}.col-sm-offset-18{margin-left:75%}.col-sm-offset-19{margin-left:79.1666666667%}.col-sm-offset-20{margin-left:83.3333333333%}.col-sm-offset-21{margin-left:87.5%}.col-sm-offset-22{margin-left:91.6666666667%}.col-sm-offset-23{margin-left:95.8333333333%}.col-sm-offset-24{margin-left:100%}}@media (min-width:992px){.container{width:980px}.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-13,.col-md-14,.col-md-15,.col-md-16,.col-md-17,.col-md-18,.col-md-19,.col-md-2,.col-md-20,.col-md-21,.col-md-22,.col-md-23,.col-md-24,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-1{width:4.1666666667%}.col-md-2{width:8.3333333333%}.col-md-3{width:12.5%}.col-md-4{width:16.6666666667%}.col-md-5{width:20.8333333333%}.col-md-6{width:25%}.col-md-7{width:29.1666666667%}.col-md-8{width:33.3333333333%}.col-md-9{width:37.5%}.col-md-10{width:41.6666666667%}.col-md-11{width:45.8333333333%}.col-md-12{width:50%}.col-md-13{width:54.1666666667%}.col-md-14{width:58.3333333333%}.col-md-15{width:62.5%}.col-md-16{width:66.6666666667%}.col-md-17{width:70.8333333333%}.col-md-18{width:75%}.col-md-19{width:79.1666666667%}.col-md-20{width:83.3333333333%}.col-md-21{width:87.5%}.col-md-22{width:91.6666666667%}.col-md-23{width:95.8333333333%}.col-md-24{width:100%}.col-md-pull-0{right:0}.col-md-pull-1{right:4.1666666667%}.col-md-pull-2{right:8.3333333333%}.col-md-pull-3{right:12.5%}.col-md-pull-4{right:16.6666666667%}.col-md-pull-5{right:20.8333333333%}.col-md-pull-6{right:25%}.col-md-pull-7{right:29.1666666667%}.col-md-pull-8{right:33.3333333333%}.col-md-pull-9{right:37.5%}.col-md-pull-10{right:41.6666666667%}.col-md-pull-11{right:45.8333333333%}.col-md-pull-12{right:50%}.col-md-pull-13{right:54.1666666667%}.col-md-pull-14{right:58.3333333333%}.col-md-pull-15{right:62.5%}.col-md-pull-16{right:66.6666666667%}.col-md-pull-17{right:70.8333333333%}.col-md-pull-18{right:75%}.col-md-pull-19{right:79.1666666667%}.col-md-pull-20{right:83.3333333333%}.col-md-pull-21{right:87.5%}.col-md-pull-22{right:91.6666666667%}.col-md-pull-23{right:95.8333333333%}.col-md-pull-24{right:100%}.col-md-push-0{left:0}.col-md-push-1{left:4.1666666667%}.col-md-push-2{left:8.3333333333%}.col-md-push-3{left:12.5%}.col-md-push-4{left:16.6666666667%}.col-md-push-5{left:20.8333333333%}.col-md-push-6{left:25%}.col-md-push-7{left:29.1666666667%}.col-md-push-8{left:33.3333333333%}.col-md-push-9{left:37.5%}.col-md-push-10{left:41.6666666667%}.col-md-push-11{left:45.8333333333%}.col-md-push-12{left:50%}.col-md-push-13{left:54.1666666667%}.col-md-push-14{left:58.3333333333%}.col-md-push-15{left:62.5%}.col-md-push-16{left:66.6666666667%}.col-md-push-17{left:70.8333333333%}.col-md-push-18{left:75%}.col-md-push-19{left:79.1666666667%}.col-md-push-20{left:83.3333333333%}.col-md-push-21{left:87.5%}.col-md-push-22{left:91.6666666667%}.col-md-push-23{left:95.8333333333%}.col-md-push-24{left:100%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:4.1666666667%}.col-md-offset-2{margin-left:8.3333333333%}.col-md-offset-3{margin-left:12.5%}.col-md-offset-4{margin-left:16.6666666667%}.col-md-offset-5{margin-left:20.8333333333%}.col-md-offset-6{margin-left:25%}.col-md-offset-7{margin-left:29.1666666667%}.col-md-offset-8{margin-left:33.3333333333%}.col-md-offset-9{margin-left:37.5%}.col-md-offset-10{margin-left:41.6666666667%}.col-md-offset-11{margin-left:45.8333333333%}.col-md-offset-12{margin-left:50%}.col-md-offset-13{margin-left:54.1666666667%}.col-md-offset-14{margin-left:58.3333333333%}.col-md-offset-15{margin-left:62.5%}.col-md-offset-16{margin-left:66.6666666667%}.col-md-offset-17{margin-left:70.8333333333%}.col-md-offset-18{margin-left:75%}.col-md-offset-19{margin-left:79.1666666667%}.col-md-offset-20{margin-left:83.3333333333%}.col-md-offset-21{margin-left:87.5%}.col-md-offset-22{margin-left:91.6666666667%}.col-md-offset-23{margin-left:95.8333333333%}.col-md-offset-24{margin-left:100%}}@media (min-width:768px){.container{width:980px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-13,.col-lg-14,.col-lg-15,.col-lg-16,.col-lg-17,.col-lg-18,.col-lg-19,.col-lg-2,.col-lg-20,.col-lg-21,.col-lg-22,.col-lg-23,.col-lg-24,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-1{width:4.1666666667%}.col-lg-2{width:8.3333333333%}.col-lg-3{width:12.5%}.col-lg-4{width:16.6666666667%}.col-lg-5{width:20.8333333333%}.col-lg-6{width:25%}.col-lg-7{width:29.1666666667%}.col-lg-8{width:33.3333333333%}.col-lg-9{width:37.5%}.col-lg-10{width:41.6666666667%}.col-lg-11{width:45.8333333333%}.col-lg-12{width:50%}.col-lg-13{width:54.1666666667%}.col-lg-14{width:58.3333333333%}.col-lg-15{width:62.5%}.col-lg-16{width:66.6666666667%}.col-lg-17{width:70.8333333333%}.col-lg-18{width:75%}.col-lg-19{width:79.1666666667%}.col-lg-20{width:83.3333333333%}.col-lg-21{width:87.5%}.col-lg-22{width:91.6666666667%}.col-lg-23{width:95.8333333333%}.col-lg-24{width:100%}.col-lg-pull-0{right:0}.col-lg-pull-1{right:4.1666666667%}.col-lg-pull-2{right:8.3333333333%}.col-lg-pull-3{right:12.5%}.col-lg-pull-4{right:16.6666666667%}.col-lg-pull-5{right:20.8333333333%}.col-lg-pull-6{right:25%}.col-lg-pull-7{right:29.1666666667%}.col-lg-pull-8{right:33.3333333333%}.col-lg-pull-9{right:37.5%}.col-lg-pull-10{right:41.6666666667%}.col-lg-pull-11{right:45.8333333333%}.col-lg-pull-12{right:50%}.col-lg-pull-13{right:54.1666666667%}.col-lg-pull-14{right:58.3333333333%}.col-lg-pull-15{right:62.5%}.col-lg-pull-16{right:66.6666666667%}.col-lg-pull-17{right:70.8333333333%}.col-lg-pull-18{right:75%}.col-lg-pull-19{right:79.1666666667%}.col-lg-pull-20{right:83.3333333333%}.col-lg-pull-21{right:87.5%}.col-lg-pull-22{right:91.6666666667%}.col-lg-pull-23{right:95.8333333333%}.col-lg-pull-24{right:100%}.col-lg-push-0{left:0}.col-lg-push-1{left:4.1666666667%}.col-lg-push-2{left:8.3333333333%}.col-lg-push-3{left:12.5%}.col-lg-push-4{left:16.6666666667%}.col-lg-push-5{left:20.8333333333%}.col-lg-push-6{left:25%}.col-lg-push-7{left:29.1666666667%}.col-lg-push-8{left:33.3333333333%}.col-lg-push-9{left:37.5%}.col-lg-push-10{left:41.6666666667%}.col-lg-push-11{left:45.8333333333%}.col-lg-push-12{left:50%}.col-lg-push-13{left:54.1666666667%}.col-lg-push-14{left:58.3333333333%}.col-lg-push-15{left:62.5%}.col-lg-push-16{left:66.6666666667%}.col-lg-push-17{left:70.8333333333%}.col-lg-push-18{left:75%}.col-lg-push-19{left:79.1666666667%}.col-lg-push-20{left:83.3333333333%}.col-lg-push-21{left:87.5%}.col-lg-push-22{left:91.6666666667%}.col-lg-push-23{left:95.8333333333%}.col-lg-push-24{left:100%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:4.1666666667%}.col-lg-offset-2{margin-left:8.3333333333%}.col-lg-offset-3{margin-left:12.5%}.col-lg-offset-4{margin-left:16.6666666667%}.col-lg-offset-5{margin-left:20.8333333333%}.col-lg-offset-6{margin-left:25%}.col-lg-offset-7{margin-left:29.1666666667%}.col-lg-offset-8{margin-left:33.3333333333%}.col-lg-offset-9{margin-left:37.5%}.col-lg-offset-10{margin-left:41.6666666667%}.col-lg-offset-11{margin-left:45.8333333333%}.col-lg-offset-12{margin-left:50%}.col-lg-offset-13{margin-left:54.1666666667%}.col-lg-offset-14{margin-left:58.3333333333%}.col-lg-offset-15{margin-left:62.5%}.col-lg-offset-16{margin-left:66.6666666667%}.col-lg-offset-17{margin-left:70.8333333333%}.col-lg-offset-18{margin-left:75%}.col-lg-offset-19{margin-left:79.1666666667%}.col-lg-offset-20{margin-left:83.3333333333%}.col-lg-offset-21{margin-left:87.5%}.col-lg-offset-22{margin-left:91.6666666667%}.col-lg-offset-23{margin-left:95.8333333333%}.col-lg-offset-24{margin-left:100%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{float:none;display:table-column}table td[class*=col-],table th[class*=col-]{float:none;display:table-cell}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-size:inherit;font-style:inherit;font-family:inherit}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:6px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.checkbox,.radio{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle}.checkbox label,.radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{float:left;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline[disabled],.checkbox[disabled],.radio-inline[disabled],.radio[disabled],fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.input-group-sm>.input-group-btn>select.btn,.input-group-sm>select.form-control,.input-group-sm>select.input-group-addon,select.input-sm{height:30px;line-height:30px}.input-group-sm>.input-group-btn>textarea.btn,.input-group-sm>textarea.form-control,.input-group-sm>textarea.input-group-addon,textarea.input-sm{height:auto}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.input-group-lg>.input-group-btn>select.btn,.input-group-lg>select.form-control,.input-group-lg>select.input-group-addon,select.input-lg{height:45px;line-height:45px}.input-group-lg>.input-group-btn>textarea.btn,.input-group-lg>textarea.form-control,.input-group-lg>textarea.input-group-addon,textarea.input-lg{height:auto}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group,.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control,.navbar-form .form-control{display:inline-block}.form-inline .checkbox,.form-inline .radio,.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio],.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .form-group{margin-left:-10px;margin-right:-10px}.form-horizontal .form-group:after,.form-horizontal .form-group:before{content:" ";display:table}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:6px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default:active,.btn-default:focus,.btn-default:hover,.open .btn-default.dropdown-toggle{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default.active,.btn-default:active,.open .btn-default.dropdown-toggle{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary.active,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open .btn-primary.dropdown-toggle{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary.active,.btn-primary:active,.open .btn-primary.dropdown-toggle{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open .btn-warning.dropdown-toggle{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open .btn-warning.dropdown-toggle{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open .btn-danger.dropdown-toggle{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open .btn-danger.dropdown-toggle{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success:active,.btn-success:focus,.btn-success:hover,.open .btn-success.dropdown-toggle{color:#fff;background-color:#47a447;border-color:#398439}.btn-success.active,.btn-success:active,.open .btn-success.dropdown-toggle{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info:active,.btn-info:focus,.btn-info:hover,.open .btn-info.dropdown-toggle{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info.active,.btn-info:active,.open .btn-info.dropdown-toggle{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group-sm>.btn,.btn-group-xs>.btn,.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;border-bottom:0 dotted}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:6px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#999}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-danger .caret,.btn-info .caret,.btn-primary .caret,.btn-success .caret,.btn-warning .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-danger .caret,.dropup .btn-info .caret,.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group-vertical>.btn:focus,.btn-group>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:after,.btn-toolbar:before{content:" ";display:table}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group-lg.btn-group>.btn+.dropdown-toggle,.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-group-lg>.btn .caret,.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-group-lg>.btn .caret,.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before{content:" ";display:table}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:6px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:6px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified .btn{float:none;display:table-cell;width:1%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-left:0;padding-right:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:6px}.input-group-addon.input-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:active,.input-group-btn>.btn:hover{z-index:2}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav:after,.nav:before{content:" ";display:table}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#428bca}.nav .open>a .caret,.nav .open>a:focus .caret,.nav .open>a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:6px 6px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:6px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#428bca}.nav-pills>li.active>a .caret,.nav-pills>li.active>a:focus .caret,.nav-pills>li.active>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified,.nav-tabs.nav-justified{width:100%}.nav-justified>li,.nav-tabs.nav-justified>li{float:none}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li,.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified,.nav-tabs.nav-justified{border-bottom:0}.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:6px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:6px 6px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:after,.navbar:before{content:" ";display:table}.navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:6px}}.navbar-header:after,.navbar-header:before{content:" ";display:table}.navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:10px;padding-left:10px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse:after,.navbar-collapse:before{content:" ";display:table}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:auto}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-10px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-10px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-collapse,.container>.navbar-header{margin-right:-10px;margin-left:-10px}@media (min-width:768px){.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 10px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-10px}}.navbar-toggle{position:relative;float:right;margin-right:10px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:6px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -10px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-10px;margin-right:-10px;padding:10px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{left:auto;right:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{margin-left:10px;margin-right:10px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.dropdown>a:focus .caret,.navbar-default .navbar-nav>.dropdown>a:hover .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{background-color:#e7e7e7;color:#555}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:focus .caret,.navbar-default .navbar-nav>.open>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#090909}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#090909;color:#fff}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:6px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:6px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{background-color:#eee}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager:after,.pager:before{content:" ";display:table}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:focus,.label[href]:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:focus,.label-default[href]:hover{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}.nav-pills>.active>a>.badge,a.list-group-item.active>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:block;margin-bottom:20px}.thumbnail>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#333}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#428bca}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:6px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#c09853}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#a47e3c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#b94a48}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:6px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:6px;border-top-left-radius:6px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:6px;border-bottom-left-radius:6px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:focus,a.list-group-item.active:hover{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:focus .list-group-item-text,a.list-group-item.active:hover .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:6px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-body:after,.panel-body:before{content:" ";display:table}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th{border-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:5px;border-top-left-radius:5px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:5px;border-bottom-left-radius:5px}.panel-group .panel{margin-bottom:0;border-radius:6px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-heading>.dropdown .caret{border-color:#333 transparent}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-heading>.dropdown .caret{border-color:#fff transparent}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading>.dropdown .caret{border-color:#468847 transparent}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading>.dropdown .caret{border-color:#c09853 transparent}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading>.dropdown .caret{border-color:#b94a48 transparent}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading>.dropdown .caret{border-color:#3a87ad transparent}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:6px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;margin-left:auto;margin-right:auto;width:auto;padding:10px;z-index:1050}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:after,.modal-footer:before{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:6px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;max-width:100%;height:auto;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs,td.visible-lg,td.visible-md,td.visible-sm,td.visible-xs,th.visible-lg,th.visible-md,th.visible-sm,th.visible-xs,tr.visible-lg,tr.visible-md,tr.visible-sm,tr.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:767px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media (min-width:768px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:767px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media (min-width:768px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:767px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:768px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:767px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media (min-width:768px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}td.hidden-xs,th.hidden-xs{display:table-cell!important}@media (max-width:767px){.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:767px){.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media (min-width:768px){.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}td.hidden-sm,th.hidden-sm{display:table-cell!important}@media (max-width:767px){.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:767px){.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media (min-width:768px){.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}td.hidden-md,th.hidden-md{display:table-cell!important}@media (max-width:767px){.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:767px){.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media (min-width:768px){.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}td.hidden-lg,th.hidden-lg{display:table-cell!important}@media (max-width:767px){.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:767px){.hidden-lg.hidden-md,td.hidden-lg.hidden-md,th.hidden-lg.hidden-md,tr.hidden-lg.hidden-md{display:none!important}}@media (min-width:768px){.hidden-lg,td.hidden-lg,th.hidden-lg,tr.hidden-lg{display:none!important}}.visible-print,td.visible-print,th.visible-print,tr.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}.hidden-print,td.hidden-print,th.hidden-print,tr.hidden-print{display:none!important}}#sidebar-nav>li>a>i{background-color:#999;border-radius:100%;color:transparent;cursor:pointer;display:inline-block;font:0/0 Arial;height:12px;letter-spacing:0;padding:0;margin:0;position:absolute;top:8px;right:4px;vertical-align:middle;width:12px}#sidebar-nav>li>a>i:before{border:1px solid #fff;content:" ";display:block;height:0;left:50%;margin-left:-3px;margin-top:-1px;position:absolute;top:50%;width:6px}#sidebar-nav>li>a>i:after{border:1px solid #fff;content:" ";display:block;height:6px;left:50%;margin-left:-1px;margin-top:-3px;position:absolute;top:50%;width:0}#sidebar-nav>li>a.active>i:after{display:none}.css-sprite ul{height:24px;width:auto;margin:-5px 0 0}.css-sprite-amex,.css-sprite-discover,.css-sprite-mc,.css-sprite-visa,.css-sprite-visa-gift-card{background-image:url(//0.ecom.attccc.com/styles/att/assets3.2.0/images/cc-images-sprite.png?build_date=1429672365397);background-repeat:no-repeat;background-size:164px 48px;width:38px;height:24px;display:inline-block}@media \0screen\,screen\8{.css-sprite-amex,.css-sprite-discover,.css-sprite-mc,.css-sprite-visa,.css-sprite-visa-gift-card{background-image:url(//0.ecom.attccc.com/styles/att/assets3.2.0/images/cc-images-sprite-ie8.png?build_date=1429672365397)}}.css-sprite-mc{background-position:0 -24px}.css-sprite-visa{background-position:-42px -24px}.css-sprite-amex{background-position:-84px -24px}.css-sprite-discover{background-position:-126px -24px}.css-sprite-visa-gift-card{background-position:-168px -24px}.show-mc .css-sprite-mc{background-position:0 0}.show-visa .css-sprite-visa{background-position:-42px 0}.show-amex .css-sprite-amex{background-position:-84px 0}.show-discover .css-sprite-discover{background-position:-126px 0}.show-visa-gift-card .css-sprite-visa-gift-card{background-position:-168px 0}.cvc-amex img,.cvc-cc img{margin:10px -8px 0 0} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/btn.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/btn.css
deleted file mode 100644
index 368e3d52..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/btn.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "UTF-8";address,blockquote,dd,h1,h2,h3,h4,h5,h6,ol,p,pre,table,ul{margin:0;padding:0;margin-bottom:24px;margin-bottom:1.5rem}html{font-size:1em;line-height:1.5}body{margin:0}h1{font-size:48px;font-size:3rem;line-height:1}h2{font-size:36px;font-size:2.25rem;line-height:1.3333333333}h3{font-size:30px;font-size:1.875rem;line-height:1.6}h4{font-size:24px;font-size:1.5rem;line-height:1}h5{font-size:20px;font-size:1.25rem;line-height:1.2}h6{font-size:18px;font-size:1.125rem;line-height:1.3333333333}dd,ol,ul{margin-left:48px;margin-left:3rem}li>ol,li>ul{margin-bottom:0}code,kbd,pre,samp{font-family:monospace,monospace}blockquote{text-indent:-.41em;quotes:"“" "â€";margin-left:48px;margin-left:3rem}blockquote p:before{content:"“";content:open-quote}blockquote p:after{content:"";content:no-close-quote}blockquote p:last-of-type:after{content:"â€";content:close-quote}q{quotes:"‘" "’" "“" "â€"}q:before{content:"‘";content:open-quote}q:after{content:"’";content:close-quote}q q:before{content:"“";content:open-quote}q q:after{content:"â€";content:close-quote}q:first-child{display:inline-block;text-indent:-.22em}table{width:100%;border-collapse:collapse;border-spacing:0}td,th{padding:12px}#grid{position:absolute;top:0;left:50%;width:980px;margin-left:-490px;counter-reset:section;z-index:9999!important;pointer-events:none;outline:1px solid rgba(0,206,209,.1)}#grid:after{position:fixed;top:0;left:0;content:'Column: 20px Gutter: 20px Margin: 20px';display:block;max-width:90px;padding:3px;background-color:#000;color:#fff;font-size:10px;font-family:monospace;z-index:9999}#grid div.vert{width:20px;outline:solid rgba(0,206,209,.3);outline-width:1px;margin-right:20px;position:relative;background:rgba(255,0,0,.05);counter-increment:section}#grid div.vert.first-line{margin-left:20px}#grid div.vert::after{position:fixed;display:block;text-align:center;color:#fff;width:20px;content:counter(section);top:5px;font-size:8px;font-family:monospace}#grid div.vert:nth-child(24){position:absolute;top:0;right:0}#grid div.vert:nth-child(1),#grid div.vert:nth-child(10),#grid div.vert:nth-child(11),#grid div.vert:nth-child(12),#grid div.vert:nth-child(13),#grid div.vert:nth-child(14),#grid div.vert:nth-child(15),#grid div.vert:nth-child(16),#grid div.vert:nth-child(17),#grid div.vert:nth-child(18),#grid div.vert:nth-child(19),#grid div.vert:nth-child(2),#grid div.vert:nth-child(20),#grid div.vert:nth-child(21),#grid div.vert:nth-child(22),#grid div.vert:nth-child(23),#grid div.vert:nth-child(24),#grid div.vert:nth-child(3),#grid div.vert:nth-child(4),#grid div.vert:nth-child(5),#grid div.vert:nth-child(6),#grid div.vert:nth-child(7),#grid div.vert:nth-child(8),#grid div.vert:nth-child(9){display:inline-block!important}#grid div.vert:nth-child(25),#grid div.vert:nth-child(26),#grid div.vert:nth-child(27),#grid div.vert:nth-child(28),#grid div.vert:nth-child(29),#grid div.vert:nth-child(30),#grid div.vert:nth-child(31){display:none!important}#grid div.horiz{height:10px;border-bottom:1px dotted rgba(100,100,100,.2);margin:0;padding:0}.bg-prime-blue{background-color:#067ab4}.bg-secondary-gray{background-color:#666}.bg-light-blue{background-color:#bcc9d5}.bg-dark-gray{background-color:#444}.bg-dusty-blue{background-color:#97b1cf}.bg-warm-gray{background-color:#cccb9b}.bg-taupe{background-color:#cccb6c}.bg-green-highlight{background-color:#c4d63f}.bg-lime-highlight{background-color:#dad632}.bg-purple-highlight{background-color:#b6539c}.bg-magenta{background-color:#d71481}.bg-blue-highlight{background-color:#4cc8f3}.bg-ochre{background-color:#fab230}.bg-green{background-color:#4fa721}.bg-lime{background-color:#b6bd26}.bg-purple{background-color:#7f0e7c}.bg-burgundy{background-color:#b1103e}.bg-dark-blue{background-color:#0e2875}.bg-gold{background-color:#fd9827}.bg-teal{background-color:#20c6b2}.bg-mint-green{background-color:#9cfecd}.bg-yellow{background-color:#feed35}.bg-white{background-color:#fff}.alt.inline-list>li{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;float:none}.text-upper{text-transform:uppercase!important}body{font-family:Arial}.font-showcase h1,.font-showcase h2,.font-showcase h3,.font-showcase h4,.font-showcase h5,.font-showcase h6{font-weight:100;letter-spacing:-1px;margin:10px 0;-webkit-font-smoothing:antialiased}.font-showcase h1{font-family:omnes_att_light;font-size:48px;font-size:3rem;line-height:48px}.font-showcase h2,.price{font-family:omnes_att_light;font-size:36px;font-size:2.25rem;line-height:36px}.font-showcase h3{font-family:omnes_att_regular;font-size:24px;font-size:1.5rem;line-height:28px}.font-showcase h4,.font-showcase h4.font-showcase-font-example,.font-showcase h4.font-showcase-font-name{font-family:Arial;font-size:18px;font-size:1.125rem;line-height:22px;-webkit-font-smoothing:antialiased}.font-showcase h5{font-family:Arial;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.font-showcase h6{font-family:Arial;font-size:11px;font-size:.6875rem;line-height:30px;font-weight:100;-webkit-font-smoothing:antialiased}.body-copy,.font-showcase p{font-family:Arial;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.body-copy-short{font-family:Arial;font-size:12px;font-size:.75rem;line-height:15px;-webkit-font-smoothing:antialiased}p [class*=icon]{display:inline-block;vertical-align:middle;margin-top:-4px}.details-label{display:block;font-family:Arial;font-size:11px;font-size:.6875rem;line-height:15px}.details-label+.price{line-height:28px}.price{letter-spacing:-1px;-webkit-font-smoothing:antialiased}.price sup{font-size:18px;font-size:1.125rem;vertical-align:baseline;top:-11px;margin:0 2px}.price-alt{font-size:24px;font-size:1.5rem;line-height:24px}.price-alt sup{font-size:12px;font-size:.75rem;top:-8px}.promo-tagline{font-family:omnes_att_medium_italic;font-size:16px;font-size:1rem;line-height:20px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.promo-text{font-family:clearview_att_italic;font-size:12px;font-size:.75rem;line-height:15px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.divider,.divider-dark,hr{border:0;border-bottom:1px solid #d3d3d3}.divider-light{border-color:#e5e5e5}dl{font-family:Arial;color:#444;font-size:12px;font-size:.75rem}dt{font-family:Arial;font-size:11px;font-size:.6875rem;display:block!important;margin:10px 0 5px!important;width:auto!important;text-transform:uppercase}dt a{font-family:Arial;color:#067ab4;text-transform:none}dd{display:inline!important;line-height:20px}[data-highlight]{background-color:#c9e9f9;-webkit-animation:highlight-fade 3s infinite}@-webkit-keyframes highlight-fade{100%,80%{background-color:transparent}}.button--group{vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;display:inline-block;margin-bottom:20px}.button--group .btn{margin-bottom:10px}.bg-light-gray .button,.button{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background-color .3s ease-out;-moz-transition:background-color .3s ease-out;transition:background-color .3s ease-out;font-size:18px;font-size:1.125rem;vertical-align:middle;line-height:1;text-align:center;cursor:pointer;padding:11px 30px;background-color:#888;color:#f2f2f2;border-radius:6px;position:relative;border:0;text-decoration:none;letter-spacing:0;font-family:clearview_att_light}.bg-light-gray .button:hover,.button:hover{background-color:#666;color:#f2f2f2}.bg-light-gray .button:focus,.button:focus{outline:1px solid #39b1ec!important;outline-offset:2px;text-decoration:none}.bg-light-gray .button:active,.button:active{-webkit-transition:background-color 0;-moz-transition:background-color 0;transition:background-color 0;background-color:#bbb;box-shadow:none;color:#f2f2f2}.bg-light-gray .button:visited,.button:visited{color:#fff}.lt-ie9 .bg-light-gray .button,.lt-ie9 .button{min-width:64px}.bg-light-gray .button [class*=icon-],.button [class*=icon-]{display:inline-block;vertical-align:middle}.button--small,[class*=bg-] .button--small{font-size:14px;font-size:.875rem;height:30px;padding:8px 20px}.lt-ie9 .button--small,.lt-ie9 [class*=bg-] .button--small{min-width:85px}.button--disabled,.button:disabled,.button[disabled]{background-color:#d3d3d3;color:#888!important;pointer-events:none;cursor:not-allowed!important}.buttons-dropdown--large .button--disabled,.buttons-dropdown--small .button--disabled{cursor:not-allowed!important;pointer-events:all!important;background-color:#d3d3d3!important}.button--square{border-radius:0;padding-left:15px;padding-right:15px}.button--primary{background-color:#0574AC!important;min-width:100px}.button--primary:hover{background-color:#0091d9!important}.button--primary:active{background-color:#44c8f5!important;color:#fff}.button--primary:focus{color:#fff}.bg-prime-blue .button.button--primary{background-color:#fafafa!important;color:#067ab4;min-width:100px}.bg-prime-blue .button.button--primary:hover{background-color:#CAE0EB!important;color:#067ab4}.bg-prime-blue .button.button--primary:active{background-color:#1792D6!important;color:#fff}.bg-prime-blue .button.button--primary.button--inactive,.bg-prime-blue .button.button--primary:disabled{background-color:#d3d3d3!important;color:#888;cursor:not-allowed!important}.bg-prime-blue .button.button--primary:focus{outline:1px solid #99C4D9!important;outline-offset:2px}.button.button--secondary{background:#fff;border:1px solid #157BB2;color:#067ab4}.button.button--secondary:hover{background:#F7F7F7;border-color:#0091d9;color:#0091d9}.button.button--secondary:active{background:#E5E5E5;border-color:#0574AC;color:#0574AC}.button--hero{background-color:#ef6f00!important;min-width:100px!important;height:40px;overflow:hidden}.button--hero .button--hero__inner{height:60px;-webkit-transition:width 1s,height 1s,-webkit-transform .2s;-moz-transition:width 1s,height 1s,-moz-transform .2s}.button--hero .button--hero__inner [class*=icon-]{line-height:40px;display:block}.button--hero:hover>.button--hero__inner{-webkit-transform:translate(0px,-29px);-moz-transform:translate(0px,-29px);transform:translate(0px,-29px)}.button--hero:active>.button--hero__inner{-webkit-transform:translate(0px,0);-moz-transform:translate(0px,0);transform:translate(0px,0)}.button--hero:hover{background-color:#ef6f00!important}.button--hero:active{background-color:#fcb314!important;color:#fff}.button--hero:focus{color:#fff}.bg-secondary-gray .button.button--secondary:focus{outline:1px solid #BDBDBD!important;outline-offset:2px}.bg-secondary-gray .button.button--secondary:disabled{color:#f2f2f2}.button--icon{font-size:14px;font-size:.875rem;width:30px;height:30px;border-radius:50%;font-family:atticons;line-height:30px;min-width:0;padding:0}.button--icon [class^=icon-]{vertical-align:baseline}.button--large.button--icon{font-size:28px;font-size:1.75rem;width:40px;height:40px;line-height:40px}.button--inactive{background-color:#ddd!important;color:#999!important;cursor:not-allowed!important;min-width:100px}.bg-secondary-gray .button{background-color:#fff}.bg-secondary-gray .button:hover{background-color:#F7F7F7}.bg-secondary-gray .button.button--inactive,.bg-secondary-gray .button:active,.bg-secondary-gray .button:disabled{background-color:#E5E5E5;cursor:not-allowed;pointer-events:all}.bg-light-blue .button{background-color:#626870}.bg-light-blue .button:hover{background-color:#8a939c}.bg-light-blue .button.button--inactive,.bg-light-blue .button:active,.bg-light-blue .button:disabled{background-color:#d7dfe6;cursor:not-allowed;pointer-events:all}.bg-dark-gray .button{background-color:#fff}.bg-dark-gray .button:hover{background-color:#f4f4f4}.bg-dark-gray .button.button--inactive,.bg-dark-gray .button:active,.bg-dark-gray .button:disabled{background-color:#E5E5E5;cursor:not-allowed;pointer-events:all}.bg-dusty-blue .button{background-color:#4e5c6b}.bg-dusty-blue .button:hover{background-color:#6f8298}.bg-dusty-blue .button.button--inactive,.bg-dusty-blue .button:active,.bg-dusty-blue .button:disabled{background-color:#c0d0e2;cursor:not-allowed;pointer-events:all}.bg-warm-gray .button{background-color:#6a6950}.bg-warm-gray .button:hover{background-color:#969572}.bg-warm-gray .button.button--inactive,.bg-warm-gray .button:active,.bg-warm-gray .button:disabled{background-color:#e0dfc3;cursor:not-allowed;pointer-events:all}.bg-taupe .button{background-color:#6a6938}.bg-taupe .button:hover{background-color:#96954f}.bg-taupe .button.button--inactive,.bg-taupe .button:active,.bg-taupe .button:disabled{background-color:#e0dfa6;cursor:not-allowed;pointer-events:all}.bg-green-highlight .button{background-color:#666f20}.bg-green-highlight .button:hover{background-color:#909c2e}.bg-green-highlight .button.button--inactive,.bg-green-highlight .button:active,.bg-green-highlight .button:disabled{background-color:#dce787;cursor:not-allowed;pointer-events:all}.bg-lime-highlight .button{background-color:#726f17}.bg-lime-highlight .button:hover{background-color:#a19c23}.bg-lime-highlight .button.button--inactive,.bg-lime-highlight .button:active,.bg-lime-highlight .button:disabled{background-color:#e9e678;cursor:not-allowed;pointer-events:all}.bg-purple-highlight .button{background-color:#49213e}.bg-purple-highlight .button:hover{background-color:#7a3768}.bg-purple-highlight .button.button--inactive,.bg-purple-highlight .button:active,.bg-purple-highlight .button:disabled{background-color:#d397c4;cursor:not-allowed;pointer-events:all}.bg-magenta .button{background-color:#560333}.bg-magenta .button:hover{background-color:#8f0956}.bg-magenta .button.button--inactive,.bg-magenta .button:active,.bg-magenta .button:disabled{background-color:#eb82bf;cursor:not-allowed;pointer-events:all}.bg-blue-highlight .button{background-color:#27687e}.bg-blue-highlight .button:hover{background-color:#3893b2}.bg-blue-highlight .button.button--inactive,.bg-blue-highlight .button:active,.bg-blue-highlight .button:disabled{background-color:#92def7;cursor:not-allowed;pointer-events:all}.bg-ochre .button{background-color:#825c17}.bg-ochre .button:hover{background-color:#b88222}.bg-ochre .button.button--inactive,.bg-ochre .button:active,.bg-ochre .button:disabled{background-color:#fcd079;cursor:not-allowed;pointer-events:all}.bg-green .button{background-color:#1f430a}.bg-green .button:hover{background-color:#357014}.bg-green .button.button--inactive,.bg-green .button:active,.bg-green .button:disabled{background-color:#96c278;cursor:not-allowed;pointer-events:all}.bg-lime .button{background-color:#5f620f}.bg-lime .button:hover{background-color:#797e16}.bg-lime .button.button--inactive,.bg-lime .button:active,.bg-lime .button:disabled{background-color:#cacd74;cursor:not-allowed;pointer-events:all}.bg-purple .button{background-color:#c149be}.bg-purple .button:hover{background-color:#d259cf}.bg-purple .button.button--inactive,.bg-purple .button:active,.bg-purple .button:disabled{background-color:#ae71ad;cursor:not-allowed;pointer-events:all}.bg-burgundy .button{background-color:#e84575}.bg-burgundy .button:hover{background-color:#f65383}.bg-burgundy .button.button--inactive,.bg-burgundy .button:active,.bg-burgundy .button:disabled{background-color:#c6758d;cursor:not-allowed;pointer-events:all}.bg-dark-blue .button{background-color:#5b75c2}.bg-dark-blue .button:hover{background-color:#6e88d5}.bg-dark-blue .button.button--inactive,.bg-dark-blue .button:active,.bg-dark-blue .button:disabled{background-color:#7582a8;cursor:not-allowed;pointer-events:all}.bg-gold .button{background-color:#844e0f}.bg-gold .button:hover{background-color:#a96517}.bg-gold .button.button--inactive,.bg-gold .button:active,.bg-gold .button:disabled{background-color:#edba74;cursor:not-allowed;pointer-events:all}.bg-teal .button{background-color:#0b685c}.bg-teal .button:hover{background-color:#159183}.bg-teal .button.button--inactive,.bg-teal .button:active,.bg-teal .button:disabled{background-color:#1aab9a;cursor:not-allowed;pointer-events:all}.bg-mint-green .button{background-color:#51846a}.bg-mint-green .button:hover{background-color:#72ba97}.bg-mint-green .button.button--inactive,.bg-mint-green .button:active,.bg-mint-green .button:disabled{background-color:#88dcb2;cursor:not-allowed;pointer-events:all}.bg-yellow .button{background-color:#847c17}.bg-yellow .button:hover{background-color:#baae24}.bg-yellow .button.button--inactive,.bg-yellow .button:active,.bg-yellow .button:disabled{background-color:#dccd2c;cursor:not-allowed;pointer-events:all}.button--bordered{border:1px solid #d4d4d4}.button__scroll-top-right{position:fixed;top:50%;right:-50px;background:#f2f2f2;border:1px solid #888;border-radius:2px;color:#444;cursor:pointer;padding:7px 58px 7px 11px;z-index:3}.csstransitions .button__scroll-top-right{-webkit-transition:right .3s ease-out;-moz-transition:right .3s ease-out;transition:right .3s ease-out;right:-50px}.button__scroll-top-right.visible{right:20px}.button__scroll-top-right:hover{background:#b2b2b2;color:#000}.button__scroll-top-right:active{background:#0574AC;color:#fff}.button__scroll-top-right .icon-arrow-double-right{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);font-size:14px}.button__scroll-top{background:#f2f2f2;border:1px solid #888;border-radius:2px;color:#444;cursor:pointer;padding:7px 9px;z-index:3}.csstransitions .button__scroll-top{-webkit-transition:right .3s ease-out;-moz-transition:right .3s ease-out;transition:right .3s ease-out;right:-50px}.button__scroll-top.visible{right:20px}.button__scroll-top:hover{background:#b2b2b2;color:#000}.button__scroll-top:active{background:#0574AC;color:#fff}.button__scroll-top .icon-arrow-double-right{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);font-size:14px}.button--danger{background-color:#ff6151!important}.button--danger:focus,.button--danger:hover{background-color:#eb4539!important}.button--light,.button--light:focus,.button--light:hover{background-color:#fff!important;color:#666}.button.button--link,[class^=bg-] .button.button--link{background:none!important;min-width:0;padding-left:10px;padding-right:10px}.button--loading{display:inline-block;width:100%}.button--loading i{-webkit-animation-name:loading-item;-webkit-animation-duration:1s;-webkit-animation-timing-function:ease-out;-webkit-animation-iteration-count:infinite;-webkit-transform:scale(0,0);-moz-animation-name:loading-item;-moz-animation-duration:1s;-moz-animation-timing-function:ease-out;-moz-animation-iteration-count:infinite;-moz-transform:scale(0,0);animation-name:loading-item;animation-duration:1s;animation-timing-function:ease-out;animation-iteration-count:infinite;transform:scale(0,0);width:8px;height:8px;background:#000;border-radius:50%;float:right;margin-right:6px}.button--loading__small i{-webkit-animation-name:loading-item;-webkit-animation-duration:1s;-webkit-animation-timing-function:ease-out;-webkit-animation-iteration-count:infinite;-webkit-transform:scale(0,0);-moz-animation-name:loading-item;-moz-animation-duration:1s;-moz-animation-timing-function:ease-out;-moz-animation-iteration-count:infinite;-moz-transform:scale(0,0);animation-name:loading-item;animation-duration:1s;animation-timing-function:ease-out;animation-iteration-count:infinite;transform:scale(0,0);width:5px;height:5px;background:#000;border-radius:50%;float:right;margin-right:4px}@-webkit-keyframes loading-item{0%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);transform:scale(1,1)}20%{-webkit-transform:scale(0.8,.8);-moz-transform:scale(0.8,.8);transform:scale(0.8,.8)}40%,60%{-webkit-transform:scale(0.6,.6);-moz-transform:scale(0.6,.6);transform:scale(0.6,.6)}80%{-webkit-transform:scale(0.8,.8);-moz-transform:scale(0.8,.8);transform:scale(0.8,.8)}100%{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);transform:scale(1,1)}}i:nth-child(3){-webkit-animation-delay:.8s;-moz-animation-delay:.8s;animation-delay:.8s}i:nth-child(2){-webkit-animation-delay:1s;-moz-animation-delay:1s;animation-delay:1s}i:nth-child(1){-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s;animation-delay:1.2s;margin-right:0}.button-secondary,.button.button-secondary{background-color:#666;color:#f2f2f2}.button-secondary:hover,.button.button-secondary:hover{background-color:#888;color:#f2f2f2}.button-secondary:focus,.button.button-secondary:focus{outline:1px solid #d3d3d3;outline-offset:2px;color:#f2f2f2}.button-secondary:active,.button.button-secondary:active{background-color:#666;color:#f2f2f2}.button-secondary:disabled,.button.button-secondary:disabled{background-color:#d3d3d3;color:#888}.buttons-dropdown--large a{font-size:18px;font-size:1.125rem}.buttons-dropdown--large .buttons-dropdown__split{min-width:inherit;padding:11px 29px}.buttons-dropdown--large .buttons-dropdown__drop{padding:11px 12px;min-width:34px;margin-left:1px!important}.buttons-dropdown--large .buttons-dropdown__drop:after{content:"\e6bf";font-family:atticons;font-size:10px;font-size:.625rem}.buttons-dropdown--large ul{min-width:inherit;top:0;left:100%;margin-left:-34px;margin-top:0;border-top-left-radius:0;overflow:hidden;padding:0;border:1px solid #0091d9}.buttons-dropdown--large ul li{text-align:left}.buttons-dropdown--large ul li a{color:#666;padding:10px;font-size:14px;font-size:.875rem;background:#fff}.buttons-dropdown--large ul li a:hover{background-color:#0091d9;color:#f2f2f2}.buttons-dropdown--small a{font-size:14px;font-size:.875rem;font-size:14px}.buttons-dropdown--small .buttons-dropdown__split{min-width:inherit;padding:8px 20px}.buttons-dropdown--small .buttons-dropdown__drop{padding:8px 12px;min-width:34px;margin-left:1px!important}.buttons-dropdown--small .buttons-dropdown__drop:after{content:"\e6bf";font-family:atticons;font-size:10px;font-size:.625rem}.buttons-dropdown--small ul{min-width:inherit;top:0;left:100%;margin-left:-34px;margin-top:0;border-top-left-radius:0;overflow:hidden;padding:0;border:1px solid #0091d9}.buttons-dropdown--small ul li{text-align:left}.buttons-dropdown--small ul li a{color:#666;padding:6px 10px;font-size:12px;font-size:.75rem;background:#fff}.buttons-dropdown--small ul li a:hover{background-color:#0091d9;color:#f2f2f2}.buttons-dropdown--large .button--secondary.buttons-dropdown__drop,.buttons-dropdown--small .button--secondary.buttons-dropdown__drop{margin-left:-1px!important}.action-dropdown-link,.buttons-dropdown--large.action-dropdown.open a,.buttons-dropdown--small.action-dropdown.open a{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom-color:#AAA;z-index:2}.action-dropdown-list,.buttons-dropdown--large.action-dropdown.open ul,.buttons-dropdown--small.action-dropdown.open ul{border-top-left-radius:6px;border-top-right-radius:0;z-index:1}.buttons-dropdown--small.action-dropdown.open a.buttons-dropdown__drop:after{content:'\e6be'}.buttons-dropdown--small.action-dropdown.open ul{margin-left:-118px;margin-left:-117px\9;margin-top:29px;min-width:118px}.buttons-dropdown--large.action-dropdown.open a.buttons-dropdown__drop:after{content:'\e6be'}.buttons-dropdown--large.action-dropdown.open ul{margin-left:-133px;margin-left:-132px\9;margin-top:41px}.buttons-dropdown--large.action-dropdown a.buttons-dropdown__drop.button--primary{border:1px solid #157bb2}.att-btn-dropdown .btn-group{width:53px;min-width:53px;height:30px;min-height:30px}.att-btn-dropdown .dropdown-menu{border-top-right-radius:0;border-top-left-radius:6px}.att-btn-dropdown ul{min-width:130px;top:29px}.att-btn-dropdown ul li{color:#067AB4}.att-btn-dropdown ul li:focus,.att-btn-dropdown ul li:hover{color:#fff;background-color:#067AB4;cursor:pointer}.att-btn-dropdown ul.dots-dropdwn{left:-45px}.att-btn-dropdown ul.actions-dropdwn{left:3px}.att-btn-dropdown .button.button--secondary,.att-btn-dropdown .buttons-dropdown__drop button{color:#067ab4}.att-btn-dropdown button.button.button--secondary.button--small.buttons-dropdown__drop.dropdown-toggle.actions-title{min-width:100px}.att-btn-dropdown div.open .buttons-dropdown__drop:after{content:"\e6be";color:#067AB4}.att-btn-dropdown div.open button{border-bottom-left-radius:0;border-bottom-right-radius:0}.att-btn-dropdown div.open .circle{background:#067AB4}.att-btn-dropdown .circle{background:#067ab4;border-radius:50%;width:3px;height:3px;display:inline-block;margin-left:1px;margin-bottom:1px;margin-top:5px;float:left}.att-btn-dropdown div.circle:nth-child(1){margin-left:0}.att-btn-dropdown div.circle:nth-child(3){margin-right:3px}.expand-line-container{background-color:#fff;float:left;height:30px;position:relative;border-bottom:1px solid #aaa;border-top:1px solid #aaa}.expand-line-container .vertical-line{width:0;float:left;height:20px;margin-top:4px;border-left:1px solid #067AB4}.expand-line-container-active{background-color:#fff;float:left;height:30px;position:relative;border-bottom:1px solid #057ab4;border-top:1px solid #057ab4}.expand-line-container-active .hovered-line{width:0;float:left;height:29px;margin-top:0;border-left:1px solid #057ab4}.split-icon-button-container{position:relative;text-align:initial}.split-icon-button-container .selected-item{background-color:#0091d9!important;color:#f2f2f2!important}.split-icon-button-container .split-icon-button{background-color:#fff;border:1px solid #067AB4;border-radius:3px;float:left;height:30px;width:34px;cursor:pointer}.split-icon-button-container .split-icon-button a{font-size:15px;margin-left:7px;position:relative;top:8px;color:#067AB4}.split-icon-button-container .split-icon-button-middle{border-radius:0;border-left:0;border-right:0}.split-icon-button-container .split-icon-button-left{border-top-right-radius:0;border-bottom-right-radius:0;border-right:0}.split-icon-button-container .split-icon-button-right{border-top-left-radius:0;border-bottom-left-radius:0;border-left:0}.split-icon-button-container .split-icon-button-next-dropdown{border-radius:0;border-left:0;border-right:0;border-bottom-color:#067AB4}.split-icon-button-container .split-icon-button-left-dropdown{border-bottom-color:#057ab4}.split-icon-button-container .split-icon-button-dropdown{border-bottom-right-radius:0;border-bottom-left-radius:0;border-top:1px solid #067AB4;border-right:1px solid #067AB4;border-bottom:0}.split-icon-button-container .icon-with-chevron{width:45px}.split-icon-button-container .icon-dropdown-down,.split-icon-button-container .icon-dropdown-up{font-size:12px;position:relative;top:5px;right:2px;color:#067AB4}.split-icon-button-container .dropdown-menu{position:absolute;top:28px;left:-36px;display:block;min-width:80px;width:80px;border-top-right-radius:0;border-top:0;border-color:#067AB4;overflow:hidden;padding-top:0;padding-bottom:0}.split-icon-button-container .dropdown-menu li{font-family:Arial;font-size:12px;color:#666;line-height:30px;margin-left:0}.split-icon-button-container .dropdown-menu li a{color:#666;padding:6px 10px;background:#fff;overflow:hidden;text-overflow:ellipsis;font-size:12px;line-height:30px;font-family:Arial;white-space:nowrap;display:block}.split-icon-button-container .dropdown-menu li a:hover{background-color:#0091d9;color:#f2f2f2} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/demo.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/demo.css
deleted file mode 100644
index f85ce896..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/demo.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Style Guide Styles */
-.editTNModal{width:624px \9!important;margin:5% auto}.editTNModal .button--disabled,.editTNModal .button--disabled:active,.editTNModal .button--disabled:hover{background-color:#d3d3d3!important}.editTNModal h2{font-weight:400;line-height:36px}.editTNModal h6{line-height:15px;font-size:12px;font-family:omnes_att_regular;font-weight:400;margin-bottom:3px}.editTNModal label{font-size:11px;font-family:omnes_att_regular;margin-bottom:0;font-weight:400}.editTNModal .icon-circle-action-close{font-size:28px}.editTNModal .saveTNs-container button{margin-left:10px}.editTNModal .middleBlock{margin-top:89px}.editTNModal .editSettings{width:85% \9}.editTNModal .editSettings label{font-family:omnes_att_bold}.editTNModal .editSettings .ng-isolate-scope{position:relative}.editTNModal .editSettings .save-cnam-lidb button{margin-left:10px}.editTNModal .editSettings .col-md-16{width:68% \9}.editTNModal .size-threefourth{width:75%}.editTNModal .alt-rows{height:293px;background:#fff;border:1px solid #BBB;margin-left:0;border-radius:5px;overflow-x:hidden;overflow-y:auto}.editTNModal .alt-rows li.even{background-color:#f2f2f2}.editTNModal .alt-rows li.item-selected{background-color:#0091d9}.editTNModal .alt-rows li.item-selected a{color:#fff}.editTNModal .alt-rows li a{display:block;padding:11px 0 11px 10px;font-size:12px;color:#444;line-height:15px}.editTNModal .alt-rows li a:focus{text-decoration:none}.editTNModal .alt-rows .scroll-viewport{height:100%}.editTNModal .leftBlock button,.editTNModal .rightBlock button{min-width:100%!important;padding:8px 10px;width:100%;margin-left:-1px}.editTNModal .leftBlock .form-field input[type=text],.editTNModal .rightBlock .form-field input[type=text]{border-radius:6px 0 0 6px}.editTNModal .middleBlock button{width:110px}.editTNModal .newCNAM span.text-right{display:block;font-size:11px}.margin-bottom20{margin-bottom:20px}.margin-bottom10{margin-bottom:10px}.margin-bottom30{margin-bottom:30px}.margin-bottom40{margin-bottom:40px}.margin-bottom80{margin-bottom:80px}.drawer{margin-left:20%;margin-right:20%}.drawer .title{font-family:omnes_att_regular;font-size:36px;margin:0;border-top:26px solid #fff}.drawer .containerContent{font-family:clearview_att_regular;font-size:14px;margin:0;margin-top:20px;margin-bottom:25px}.drawer .smallText{font-family:clearview_att_regular;font-size:12px;margin:0;margin-bottom:7px}.drawer .textCount{font-family:clearview_att_regular;font-size:12px;text-align:right;margin-right:42%}.drawer .cancelButton{background-color:#000}.drawer .datepicker1{width:200px;height:40px;margin:0;margin-bottom:5px}.att-drawer{background-color:#fff;box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3);-webkit-box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3);-moz-box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3)}.drawer-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(255,255,255,.6);z-index:999}#divider-lines .divider-container{padding:20px 40px;background:#f2f2f2}#divider-lines .divider-container-light{background-color:#fff}#tooltips-and-hints .att-tooltip{z-index:0;margin:0}.popover-packages.att-tooltip{border:0;padding:0}.popover-packages__container{background:#fff}.popover-packages__header{background:#0574ac;height:150px;padding:50px;position:relative;text-align:center;width:100%}.popover-packages__header h3{color:#fff;margin:0}.popover-packages__text-block{background:0 0;overflow:hidden;padding:50px}.popover-packages__text-block-row{float:left;width:100%}.text-block-row__title{float:left;margin-bottom:10px;width:auto}.text-block-row__info{float:right;margin-bottom:10px;width:auto}.popover-packages__text-block-price{float:left;margin-top:30px;width:100%}.text-block-price__title{float:left;font-family:Arial;margin-bottom:10px;width:auto}.text-block-price__price{float:right;margin-bottom:10px;position:relative;width:auto}pre.code-preview{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:6px}.popover-demo-container [data-preview-element]{height:auto}.popover-demo{position:relative}.popover-demo.att-popover{max-width:320px}.popover-demo .att-popover-content{display:block!important}.popover-demo .popover-packages__container{background:0 0}.popover-demo .popover-packages__container p{color:#444}.popover-demo .popover-packages__text-block{padding:5px 0 0}.popover-demo .popover-packages__text-block-row p{font-size:12px}.popover-demo hr{border-bottom:1px solid #b2b2b2;margin:10px 0 25px}.price--large{font-size:2.25rem;font-family:omnes_att_light;line-height:36px;word-spacing:2px;letter-spacing:-1px}.price--large sup{font-size:1.125rem;line-height:22px;letter-spacing:0;font-family:omnes_att_light;margin:0 2px;top:-11px;vertical-align:baseline}.price--large sup:nth-child(2):before{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);content:'.';display:inline;height:1px;overflow:hidden;position:absolute;width:1px}.bg-standard{background-color:#f2f2f2}.margin-top{margin-top:10px} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/dtpk.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/dtpk.css
deleted file mode 100644
index 194c849f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/dtpk.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/*!
- * Datepicker for Bootstrap
- *
- * Copyright 2012 Stefan Petre
- * Improvements by Andrew Rowls
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- */.jshook-return-focus-here{display:block}.datepicker table tr td.days.range.from .day,.datepicker table tr td.days.range.to .day,.range-inherit{color:#fff;background-color:#067ab4}.greyBorder{border-top:solid 1px #d3d3d3}.datepicker{background-color:#fff;padding:0;border-radius:5px;direction:ltr;outline:0;margin:0;width:300px}.datepicker.datepicker-rtl{direction:rtl}.datepicker .weekday{height:21px;margin:0 auto;font-family:clearview_att_regular;font-size:14px;line-height:20px;color:#444}.datepicker .icons-list{margin-top:0;cursor:pointer}.datepicker .icons-list .disabled{color:#d3d3d3;cursor:default}.datepicker table{padding:16px 10px;border-spacing:0;border-collapse:separate;font-family:clearview_att_regular;width:auto;margin:0}.datepicker table th.datepicker-switch{width:198px;font-size:14px;font-weight:400;line-height:20px;padding-bottom:13px;font-family:clearview_att_regular;color:#444;cursor:default!important}.datepicker table th.datepicker-switch.internal{padding-bottom:5px}.datepicker table tr td.days{background-color:#fff;color:#444;font-size:14px;width:32px;text-align:center;overflow:hidden}.datepicker table tr td.days.weekend{background-color:#f2f2f2}.datepicker table tr td.days.weekend.disabled .day:hover{background-color:#f2f2f2!important}.datepicker table tr td.days.disabled{color:#d3d3d3}.datepicker table tr td.days.disabled .day:hover{background-color:#fff;color:#d3d3d3;outline:0;cursor:default}.datepicker table tr td.days .day{width:30px;height:29;display:block;line-height:28px;border-radius:100%}.datepicker table tr td.days .day:hover{background-color:#bbb;color:#444;cursor:pointer;outline:2px solid #bbb;outline-offset:2px;-moz-outline-radius:100%}.datepicker table tr td.days.active{background-color:#067ab4;color:#fff;border-radius:100%}.datepicker table tr td.days.active .day:hover{cursor:default}.datepicker table tr td.days.range{background-color:#44c8f5}.datepicker table tr td.days.range.from{border-radius:20px 0 0 20px}.datepicker table tr td.days.range.from .day:hover{cursor:default}.datepicker table tr td.days.range.to{border-radius:0 20px 20px 0}.datepicker table tr td.days.range.to .day:hover{cursor:default}.datepicker table tr td.days.range .day{color:#444}.datepicker table tr td.days.range .day:hover{background-color:#bbb;color:#444}.datepicker table tr td.days.next-month,.datepicker table tr td.days.prev-month{color:#fff;opacity:0}.datepicker table tr td.days.next-month .day:hover,.datepicker table tr td.days.prev-month .day:hover{background-color:#fff!important;color:#fff;outline:0;cursor:default;opacity:0}.datepicker table tr td.today{color:#444;text-decoration:underline;-moz-text-decoration-color:#444;text-decoration-color:#444}.datepicker .dow{height:23px;width:31px;font-weight:400;position:relative;border-top:solid 1px #bbb;border-bottom:solid 1px #bbb;margin-top:13px}.datepicker .dow .hidden-spoken{display:block;letter-spacing:-6px;overflow:hidden;position:absolute;top:5px;left:17px}.datepicker .due-date:after{border:2px solid #cf2a2a;border-radius:100%;content:" ";display:block;height:30px;left:3px;position:absolute;top:2px;width:30px;text-indent:-9999px;-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.datepicker .due-date.old:after{visibility:hidden}.datepicker .due-date.active:after{border-color:#fff}.datepicker .due-date.active.focused{color:#0577b2!important}.datepicker .due-date.active.focused:after{border-color:#cf2a2a!important}.datepicker i.legend-due-date{border:1px solid #ccc;height:20px;width:20px;display:inline-block;margin-right:5px;margin-top:4px;position:absolute;left:0;top:0}.datepicker i.legend-due-date:after{border:1px solid #cf2a2a;border-radius:100%;display:block;content:" ";height:16px;left:1px;position:absolute;top:1px;width:16px;text-indent:-9999px}.datepicker .calendar-legend li{position:relative;padding-left:30px;padding-top:5px;margin-bottom:5px;font-weight:400;font-size:12px}.monthpicker table{width:100%}.monthpicker table tr td.days{width:33%;padding:0}.monthpicker .datepicker-switch{padding:0}.monthpicker table tr td.days.active{border-radius:25px}.monthpicker table tr td.days .day{line-height:20px;width:auto;border-radius:25px}.monthpicker table tr td.days .day:hover{border-radius:20px;-moz-outline-radius:20px}.monthpicker .monthtable-condensed{border-spacing:0 5px}.monthpicker .divider td{padding:0}.monthpicker .divider hr{margin:10px 0}.calendar.monthpicker .btnContainer{margin:8px 0}.calendar.monthpicker ul.select2-results.sttings li:last-child{margin-bottom:0}.calendar.monthpicker .btnContainer div{margin:12px 0}.calendar{position:relative;display:inline-block;width:270px}.calendar .box{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;position:relative;zoom:1;vertical-align:middle;display:inline-block}.calendar .box.active{z-index:0}.calendar .box.active input[type=text]{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important;border:solid 1px #067ab4;border-bottom:1px solid lightgrey}.calendar .calendar-icon{cursor:pointer;background:url(images/calendar-icon.png) no-repeat right top;width:30px;z-index:100;height:30px;position:absolute;right:3px;top:5px;background-color:#fff;background-size:30px 30px}.calendar .datepicker-wrapper{height:auto;width:302px;border:solid 1px #067ab4;background:none repeat scroll 0 0 #fff;border-radius:0 0 6px 6px;border-top:1px solid lightgrey;margin-top:-2px;z-index:1000;position:absolute;-webkit-box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px;-moz-box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px;box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px}.calendar .datepicker-wrapper.show-right{right:-301px;border-bottom-left-radius:0!important;border-left:1px solid lightgrey;border-top:solid 1px #067ab4;top:41px}.calendar .datepicker-wrapper.datepicker-wrapper-display-none{display:none}.calendar .select2-results{border-radius:0;margin:0;overflow:hidden}.calendar .select2-result:focus{background:#1792D6!important;color:#fff!important}.calendar .select2-results.options{box-shadow:none}.calendar ul.select2-results.options li:last-child{margin-bottom:0}.calendar ul.select2-results.options li .disabled{color:#a0a0a0}.calendar ul.select2-results.sttings li:last-child{margin-bottom:35px}.btnContainer{line-height:14px;margin:9px 0 0;padding:8px 10px}.btnContainer div{margin-top:35px}.datepicker-inline{width:220px}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:" ";display:inline-block;border-left:12px solid transparent;border-right:12px solid transparent;border-bottom:12px solid #ccc;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:" ";display:inline-block;border-left:12px solid transparent;border-right:12px solid transparent;border-bottom:12px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:after,.datepicker-dropdown.datepicker-orient-left:before{left:58px}.datepicker-dropdown.datepicker-orient-right:after,.datepicker-dropdown.datepicker-orient-right:before{right:58px}.datepicker-dropdown.datepicker-orient-top:before{top:-13px}.datepicker-dropdown.datepicker-orient-top:after{top:-12px}.datepicker-dropdown.datepicker-orient-bottom:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-bottom:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker>div{display:none}.datepicker.days div.datepicker-days,.datepicker.months div.datepicker-months,.datepicker.years div.datepicker-years{display:block}.datepicker .next{padding-bottom:13px;background-size:10px 15px;background-position:10px 12px;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}@media \0screen\,screen\8{.datepicker .next{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAPCAYAAADd/14OAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMNJREFUeNpiZC3fxAAEykA8CYhbgPg4AxbABMRqQLwBiL2AeCUQG+FSOBWIdaB8WSDeiE0xSGErEL9GEpOBKjZAV3gAiIOwKN6AZBNYIQgcwaJYHog3wxQzIUnAFD9CElOAKjZmZraJRHYKSBEzELshiQkAsToTmudsgDgPTewBEBezoClaB8SiaIp8gfgKEx5FD2GKYJ5xwKLoCRAHwBTBFFZjUeQPxBfQAzwbSedjqKJz2KLwFtSabUAcjk0RCAAEGADBuyhEiJHd4gAAAABJRU5ErkJggg==)}}.datepicker .prev{background-size:10px 15px;background-position:20px 12px;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}@media \0screen\,screen\8{.datepicker .prev{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAPCAYAAADd/14OAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALxJREFUeNpiZC3fxIADWAJxDRDnAfFdFhyKjIB4JRDLArEcEAez4FC0EYhloHwdIJ7KhKbIAE0RCLwG4lZkE0E6N2BRFATER5iQFG0GYnlsikAckEJjqCIFJEWPkBXBFPaiKQKBSciKYAqLgfgBmkJQ2NmgKzwLxL5oikFhtw5ZMcwzV6CKHyIpFkVWjByOIMUBQPwEi2IH9AC/AMT+WBRXM2GJwnNQxY+RbMpmwpEoQIrDgXgb1Dm3AAIMALk+J8MvzLwTAAAAAElFTkSuQmCC)}}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.input-group.date .input-group-addon i{cursor:pointer;width:16px;height:16px}.datepicker.dropdown-menu{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;top:100%;left:0;float:left;display:none;margin-top:5px;width:290px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;color:#333;font-size:13px;line-height:1.428571429;z-index:1050}.datepicker.dropdown-menu td,.datepicker.dropdown-menu th{padding:4px 5px;display:block;position:relative;float:left}.datepicker .text-left{width:100%}.hidden-spoken,.hidden-text-spoken{position:absolute!important;clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;padding:0!important;overflow:hidden!important;border:0!important;letter-spacing:0;line-height:0}#dateFilterList .scroll-viewport{height:120px;width:100%}#dateFilterList .scroll-bar.disable+div.scroll-viewport{width:268px}#dateFilterList .scroll-bar{width:6px;background-color:#fff}#dateFilterList .scroll-thumb{width:4px;background-color:#999}#datepickerBody .scroll-bar{right:-8px;width:6px;background-color:#fff}#datepickerBody .scroll-thumb{width:4px;background-color:#999}#datepickerBody .scroll-viewport{height:218px;width:280px}.monthpicker #datepickerBody .scroll-viewport{height:208px} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/frms.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/frms.css
deleted file mode 100644
index ce1c42d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/frms.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "UTF-8";address,blockquote,dd,h1,h2,h3,h4,h5,h6,ol,p,pre,table,ul{margin:0;padding:0;margin-bottom:24px;margin-bottom:1.5rem}html{font-size:1em;line-height:1.5}body{margin:0}h1{font-size:48px;font-size:3rem;line-height:1}h2{font-size:36px;font-size:2.25rem;line-height:1.3333333333}h3{font-size:30px;font-size:1.875rem;line-height:1.6}h4{font-size:24px;font-size:1.5rem;line-height:1}h5{font-size:20px;font-size:1.25rem;line-height:1.2}h6{font-size:18px;font-size:1.125rem;line-height:1.3333333333}dd,ol,ul{margin-left:48px;margin-left:3rem}li>ol,li>ul{margin-bottom:0}code,kbd,pre,samp{font-family:monospace,monospace}blockquote{text-indent:-.41em;quotes:"“" "â€";margin-left:48px;margin-left:3rem}blockquote p:before{content:"“";content:open-quote}blockquote p:after{content:"";content:no-close-quote}blockquote p:last-of-type:after{content:"â€";content:close-quote}q{quotes:"‘" "’" "“" "â€"}q:before{content:"‘";content:open-quote}q:after{content:"’";content:close-quote}q q:before{content:"“";content:open-quote}q q:after{content:"â€";content:close-quote}q:first-child{display:inline-block;text-indent:-.22em}table{width:100%;border-collapse:collapse;border-spacing:0}td,th{padding:12px}#grid{position:absolute;top:0;left:50%;width:980px;margin-left:-490px;counter-reset:section;z-index:9999!important;pointer-events:none;outline:1px solid rgba(0,206,209,.1)}#grid:after{position:fixed;top:0;left:0;content:'Column: 20px Gutter: 20px Margin: 20px';display:block;max-width:90px;padding:3px;background-color:#000;color:#fff;font-size:10px;font-family:monospace;z-index:9999}#grid div.vert{width:20px;outline:solid rgba(0,206,209,.3);outline-width:1px;margin-right:20px;position:relative;background:rgba(255,0,0,.05);counter-increment:section}#grid div.vert.first-line{margin-left:20px}#grid div.vert::after{position:fixed;display:block;text-align:center;color:#fff;width:20px;content:counter(section);top:5px;font-size:8px;font-family:monospace}#grid div.vert:nth-child(24){position:absolute;top:0;right:0}#grid div.vert:nth-child(1),#grid div.vert:nth-child(10),#grid div.vert:nth-child(11),#grid div.vert:nth-child(12),#grid div.vert:nth-child(13),#grid div.vert:nth-child(14),#grid div.vert:nth-child(15),#grid div.vert:nth-child(16),#grid div.vert:nth-child(17),#grid div.vert:nth-child(18),#grid div.vert:nth-child(19),#grid div.vert:nth-child(2),#grid div.vert:nth-child(20),#grid div.vert:nth-child(21),#grid div.vert:nth-child(22),#grid div.vert:nth-child(23),#grid div.vert:nth-child(24),#grid div.vert:nth-child(3),#grid div.vert:nth-child(4),#grid div.vert:nth-child(5),#grid div.vert:nth-child(6),#grid div.vert:nth-child(7),#grid div.vert:nth-child(8),#grid div.vert:nth-child(9){display:inline-block!important}#grid div.vert:nth-child(25),#grid div.vert:nth-child(26),#grid div.vert:nth-child(27),#grid div.vert:nth-child(28),#grid div.vert:nth-child(29),#grid div.vert:nth-child(30),#grid div.vert:nth-child(31){display:none!important}#grid div.horiz{height:10px;border-bottom:1px dotted rgba(100,100,100,.2);margin:0;padding:0}.bg-prime-blue{background-color:#067ab4}.bg-secondary-gray{background-color:#666}.bg-light-blue{background-color:#bcc9d5}.bg-dark-gray{background-color:#444}.bg-dusty-blue{background-color:#97b1cf}.bg-warm-gray{background-color:#cccb9b}.bg-taupe{background-color:#cccb6c}.bg-green-highlight{background-color:#c4d63f}.bg-lime-highlight{background-color:#dad632}.bg-purple-highlight{background-color:#b6539c}.bg-magenta{background-color:#d71481}.bg-blue-highlight{background-color:#4cc8f3}.bg-ochre{background-color:#fab230}.bg-green{background-color:#4fa721}.bg-lime{background-color:#b6bd26}.bg-purple{background-color:#7f0e7c}.bg-burgundy{background-color:#b1103e}.bg-dark-blue{background-color:#0e2875}.bg-gold{background-color:#fd9827}.bg-teal{background-color:#20c6b2}.bg-mint-green{background-color:#9cfecd}.bg-yellow{background-color:#feed35}.bg-white{background-color:#fff}.alt.inline-list>li{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;float:none}.text-upper{text-transform:uppercase!important}body{font-family:clearview_att_regular}.font-showcase h1,.font-showcase h2,.font-showcase h3,.font-showcase h4,.font-showcase h5,.font-showcase h6{font-weight:100;letter-spacing:-1px;margin:10px 0;-webkit-font-smoothing:antialiased}.font-showcase h1{font-family:omnes_att_light;font-size:48px;font-size:3rem;line-height:48px}.font-showcase h2,.price{font-family:omnes_att_light;font-size:36px;font-size:2.25rem;line-height:36px}.font-showcase h3{font-family:omnes_att_regular;font-size:24px;font-size:1.5rem;line-height:28px}.font-showcase h4,.font-showcase h4.font-showcase-font-example,.font-showcase h4.font-showcase-font-name{font-family:clearview_att_regular;font-size:18px;font-size:1.125rem;line-height:22px;-webkit-font-smoothing:antialiased}.font-showcase h5{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.font-showcase h6{font-family:Arial;font-size:11px;font-size:.6875rem;line-height:30px;font-weight:100;-webkit-font-smoothing:antialiased}.body-copy,.font-showcase p{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.body-copy-short{font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:15px;-webkit-font-smoothing:antialiased}p [class*=icon]{display:inline-block;vertical-align:middle;margin-top:-4px}.details-label{display:block;font-family:clearview_att_regular;font-size:11px;font-size:.6875rem;line-height:15px}.details-label+.price{line-height:28px}.price{letter-spacing:-1px;-webkit-font-smoothing:antialiased}.price sup{font-size:18px;font-size:1.125rem;vertical-align:baseline;top:-11px;margin:0 2px}.price-alt{font-size:24px;font-size:1.5rem;line-height:24px}.price-alt sup{font-size:12px;font-size:.75rem;top:-8px}.promo-tagline{font-family:omnes_att_medium_italic;font-size:16px;font-size:1rem;line-height:20px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.promo-text{font-family:clearview_att_italic;font-size:12px;font-size:.75rem;line-height:15px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.divider,.divider-dark,hr{border:0;border-bottom:1px solid #d3d3d3}.divider-light{border-color:#e5e5e5}dl{font-family:clearview_att_regular;color:#444;font-size:12px;font-size:.75rem}dt{font-family:Arial;font-size:11px;font-size:.6875rem;display:block!important;margin:10px 0 5px!important;width:auto!important;text-transform:uppercase}dt a{font-family:clearview_att_regular;color:#067ab4;text-transform:none}dd{display:inline!important;line-height:20px}[data-highlight]{background-color:#c9e9f9;-webkit-animation:highlight-fade 3s infinite}@-webkit-keyframes highlight-fade{100%,80%{background-color:transparent}}.form-field{margin-bottom:10px}.form-field [class^=icon-]{font-size:14px;font-size:.875rem;-webkit-font-smoothing:antialiased;bottom:0;color:#888;height:40px;line-height:40px;pointer-events:none;position:absolute;right:0;text-align:center;margin-right:2px;margin-left:-1px;width:30px;z-index:3}.form-field,.form-field-input-container{position:relative;display:inline-block;width:270px}.form-field .hide-field,.form-field-input-container .hide-field{display:none}.form-field--has-left-icon .select2-choice .select2-chosen,.form-field--has-left-icon input[type=color],.form-field--has-left-icon input[type=date],.form-field--has-left-icon input[type=datetime-local],.form-field--has-left-icon input[type=datetime],.form-field--has-left-icon input[type=email],.form-field--has-left-icon input[type=month],.form-field--has-left-icon input[type=number],.form-field--has-left-icon input[type=password],.form-field--has-left-icon input[type=search],.form-field--has-left-icon input[type=tel],.form-field--has-left-icon input[type=text],.form-field--has-left-icon input[type=time],.form-field--has-left-icon input[type=url],.form-field--has-left-icon input[type=week]{padding-left:31px;padding-right:29px}.form-field .form-field-right-icon{color:#444}.form-field__left-icon{left:0;text-indent:12px;right:auto!important}.form-field .icon-checkbox-checkmark,.form-field .icon-cross{font-size:24px;font-size:1.5rem}.form-field .icon-help,.form-field .icon-help-outline{pointer-events:all}.form-field__label{font-size:12px;font-size:.75rem;visibility:hidden;display:block;font-family:clearview_att_regular;margin-bottom:3px;position:absolute;top:0;-webkit-transition:width 1s,height 1s,-webkit-transform .1s}.form-field__label--show{visibility:visible;-moz-transform:translateX(0px) translateY(-20px);-webkit-transform:translateX(0px) translateY(-20px);-o-transform:translateX(0px) translateY(-20px);-ms-transform:translateX(0px) translateY(-20px);transform:translateX(0px) translateY(-20px)}.form-field__label--hide{visibility:visible;-moz-transform:translateX(0px) translateY(0px);-webkit-transform:translateX(0px) translateY(0px);-o-transform:translateX(0px) translateY(0px);-ms-transform:translateX(0px) translateY(0px);transform:translateX(0px) translateY(0px)}[class^=icon-].success{color:#008a06}[class^=icon-].error{color:#e00000}[class^=icon-].info{color:#0a7cb5}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{font-size:14px;font-size:.875rem;-webkit-transition:all .04 ease-out;-moz-transition:all .04 ease-out;transition:all .04 ease-out;background:#fff;border-radius:6px;border:1px solid #888;color:#444;font-family:clearview_att_regular;width:100%;outline:0;padding:7px 10px;text-transform:none;z-index:0;height:40px;position:relative}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled],select[disabled],textarea[disabled]{border:1px solid #aaa;background:#f2f2f2;color:#a0a0a0;box-shadow:0 0 #d9d9d9 inset}textarea{resize:vertical}select{-webkit-transition-property:all,z-index,background-position;-moz-transition-property:all,z-index,background-position;transition-property:all,z-index,background-position;-webkit-transition-delay:.4s,0,0;-moz-transition-delay:.4s,0,0;transition-delay:.4s,0,0;-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;transition-timing-function:ease-out}input[type=color]:hover,input[type=date]:hover,input[type=datetime-local]:hover,input[type=datetime]:hover,input[type=email]:hover,input[type=month]:hover,input[type=number]:hover,input[type=password]:hover,input[type=search]:hover,input[type=tel]:hover,input[type=text]:hover,input[type=time]:hover,input[type=url]:hover,input[type=week]:hover,select:hover,textarea:hover{border:1px solid #444;z-index:1}input[type=color]:hover[disabled],input[type=date]:hover[disabled],input[type=datetime-local]:hover[disabled],input[type=datetime]:hover[disabled],input[type=email]:hover[disabled],input[type=month]:hover[disabled],input[type=number]:hover[disabled],input[type=password]:hover[disabled],input[type=search]:hover[disabled],input[type=tel]:hover[disabled],input[type=text]:hover[disabled],input[type=time]:hover[disabled],input[type=url]:hover[disabled],input[type=week]:hover[disabled],select:hover[disabled],textarea:hover[disabled]{border:1px solid #a0a0a0;background:#f2f2f2;color:#a0a0a0}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus,select:focus,textarea:focus{border:1px solid #0574AC;color:#444;z-index:1}select{width:100%;position:relative;background-image:url(images/select-arrows.png);background-position:100% -1px;background-repeat:no-repeat;-webkit-appearance:none}.form-field.error input[type=email],.form-field.error input[type=password],.form-field.error input[type=text],.form-field.error select{border:1px solid #e00000}.form-field.warning{color:#444}.form-field.success input[type=email],.form-field.success input[type=password],.form-field.success input[type=text],.form-field.success select{border:1px solid #008a06}.form-field__glued{width:100%;margin-bottom:0}.form-field__glued input[type=email],.form-field__glued input[type=password],.form-field__glued input[type=text],.form-field__glued select{position:relative;margin-top:-1px;border-radius:0}.form-field__glued:first-child input[type=email],.form-field__glued:first-child input[type=password],.form-field__glued:first-child input[type=text],.form-field__glued:first-child select{margin-top:0;border-radius:5px 5px 0 0}.form-field__glued:last-child input[type=email],.form-field__glued:last-child input[type=password],.form-field__glued:last-child input[type=text],.form-field__glued:last-child select{border-radius:0 0 5px 5px}.form-field__glued.pull-left{margin-right:-1px}.form-field__glued.pull-left .select2-choice,.form-field__glued.pull-left input[type=email],.form-field__glued.pull-left input[type=password],.form-field__glued.pull-left input[type=text],.form-field__glued.pull-left select{border-radius:0;margin-top:0}.form-field__glued.pull-left:first-child .select2-choice,.form-field__glued.pull-left:first-child input[type=password],.form-field__glued.pull-left:first-child input[type=text],.form-field__glued.pull-left:first-child select{border-radius:5px 0 0 5px}.form-field__glued.pull-left:last-child .select2-choice,.form-field__glued.pull-left:last-child input[type=password],.form-field__glued.pull-left:last-child input[type=text],.form-field__glued.pull-left:last-child select{border-radius:0 5px 5px 0}::-webkit-input-placeholder{color:#444;opacity:.54}:-moz-placeholder{color:#444;opacity:.54}::-moz-placeholder{color:#444;opacity:.54}:-ms-input-placeholder{color:#444;opacity:.54;-ms-filter:'alpha(Opacity=54)'}[disabled]::-webkit-input-placeholder{color:#888}[disabled]:-moz-placeholder{color:#888}[disabled]::-moz-placeholder{color:#888}[disabled]:-ms-input-placeholder{color:#888}.form-field .form-field__message span{vertical-align:middle}.form-field .form-field__message{border-radius:4px;min-width:150px;max-width:280px;display:block;padding:10px;margin:12px 0 0;font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:10px;color:#666;text-transform:none;background:#fff;position:absolute;z-index:1;-moz-box-sizing:border-box;box-sizing:border-box}.form-field .form-field__message:after{content:'';position:absolute;left:10px;top:-7px;border-style:solid;border-width:0 7px 7px;border-color:transparent transparent #fff}.form-field .form-field__message [class*=icon-]{color:#fff;position:relative;margin-right:9px;line-height:0!important;vertical-align:middle}.form-field .form-field__message.error{color:#fff;background:#e00000}.form-field .form-field__message.error:after{border-bottom:7px solid #e00000}.form-field .form-field__message.warning{color:#444;background:#FCB123}.form-field .form-field__message.warning:after{border-bottom:7px solid #FCB123}.form-field .form-field__message.warning [class*=icon-]{color:#444}.form-field .form-field__message.alert{position:absolute;bottom:-45px;left:0;z-index:1;box-shadow:0 5px 10px 0 rgba(0,0,0,.25)}.form-field .form-field__message.success{color:#fff;background:#008a06}.form-field .form-field__message.success:after{border-bottom:7px solid #008a06}.form-field .form-field__message.info{color:#fff;background:#0a7cb5}.form-field .form-field__message [class^=icon-]{height:30px;line-height:30px}.form-field-loading>[class*=icon-]:not(.form-field-left-icon){opacity:0}.form-field-loading:after{content:'';position:absolute;top:2px;right:5px;width:25px;height:25px;background:url(images/loader.gif) center center no-repeat;background-size:20px}.fix-height{height:110px}.form-field__message-login{width:100%;display:block;position:relative;padding:7px 12px 3px;margin:-1px 0 -1px 0;font-family:clearview_att_regular;font-size:12px;font-size:.75rem;color:#666;text-transform:none;background:#fff;z-index:1;-moz-box-sizing:border-box;box-sizing:border-box}.form-field__message-login:after{content:'';position:absolute;right:10px;top:-7px;border-style:solid;border-width:0 7px 7px;border-color:transparent transparent #fff;z-index:2}.form-field__message-login [class*=icon-]{color:#fff;position:absolute;margin-right:5px}.form-field__message-login.incorrect{color:#fff;background:#e00000;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.form-field__message-login.incorrect:after{border-bottom:7px solid #e00000}.form-field__message-login.unregistered{color:#444;background:#fcb134}.form-field__message-login.unregistered:after{border-bottom:7px solid #fcb134}.form-field__glued:first-child:hover+.form-field__message-login{margin:0 0 -1px 0}.form-field__login-field{width:200px}.form-field__login-field input[type=color],.form-field__login-field input[type=date],.form-field__login-field input[type=datetime-local],.form-field__login-field input[type=datetime],.form-field__login-field input[type=email],.form-field__login-field input[type=month],.form-field__login-field input[type=number],.form-field__login-field input[type=password],.form-field__login-field input[type=search],.form-field__login-field input[type=tel],.form-field__login-field input[type=text],.form-field__login-field input[type=time],.form-field__login-field input[type=url],.form-field__login-field input[type=week],.form-field__login-field select,.form-field__login-field textarea{height:35px;width:200px;font-size:12px;font-size:.75rem}.form-field__login-field [class^=icon-]{height:35px;line-height:35px} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/ie/backgroundsize.min.htc b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/ie/backgroundsize.min.htc
deleted file mode 100644
index baa93ada..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/ie/backgroundsize.min.htc
+++ /dev/null
@@ -1,12 +0,0 @@
-<!-- background-size-polyfill v0.2.0 | (c) 2012-2013 Louis-Rémi Babé | MIT License -->
-<PUBLIC:COMPONENT lightWeight="true">
-<PUBLIC:ATTACH EVENT="oncontentready" ONEVENT="o.init()" />
-<PUBLIC:ATTACH EVENT="ondocumentready" ONEVENT="o.init()" />
-<PUBLIC:ATTACH EVENT="onpropertychange" ONEVENT="o.handlePropertychange()" />
-<PUBLIC:ATTACH EVENT="ondetach" ONEVENT="o.restore()" />
-<PUBLIC:ATTACH EVENT="onresize" FOR="window" ONEVENT="o.handleResize()" />
-<PUBLIC:EVENT NAME="onbackgroundupdate" ID="updateEvent" />
-<script type="text/javascript">
-var o;!function(a,b){var c=/url\(["']?(.*?)["']?\)/,d=/^\s\s*/,e=/\s\s*$/,f=/\s\s*/g,g=/%$/,h={top:0,left:0,bottom:1,right:1,center:.5},i=a.document,j="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",k="background-size-polyfill",l=function(){},m=100,n,p,q,r;function s(){var b=i.createElement("div"),c=i.createElement("img"),d=b.style,e=a.style,f=a.currentStyle,g=a.bgsExpando,h=a.firstChild;g&&(g.restore&&(e.backgroundImage=g.restore.backgroundImage,e.position=g.restore.position,e.zIndex=g.restore.zIndex),h&&"DIV"===(h.nodeName||"").toUpperCase()&&h.className===k&&a.removeChild(h)),t(b),b.className=k,d.top=d.right=d.bottom=d.left=0,d.position="fixed",t(c),c.alt="",b.appendChild(c),a.insertBefore(b,a.firstChild),a.bgsExpando=g={wrapper:b,img:c,restore:{backgroundImage:e.backgroundImage,position:e.position,zIndex:e.zIndex},current:{},next:null,processing:!1,loadImg:null,display:!1,changed:!1,ignore:!1,canFixed:"BODY"===a.nodeName.toUpperCase()&&b.offsetHeight>0},d.position="absolute","auto"===f.zIndex&&(e.zIndex=0),"static"===f.position&&(e.position="relative"),o={init:l,handlePropertychange:D,restore:F,handleResize:E},D()}function t(a){var b=a.style;b.position="absolute",b.display="block",b.zIndex=-1,b.overflow="hidden",b.visibility="inherit",b.width=b.height=b.top=b.right=b.bottom=b.left=b.cursor="auto",b.margin=b.padding=b.border=b.outline=b.minWidth=b.minHeight=0,b.background=b.maxWidth=b.maxHeight="none",b.fontSize=b.lineHeight="1em"}function u(a,c,d){var e;c?(e=i.createElement("img"),e.onload=e.onerror=function(){var c=this.width,e=this.height;"error"===b.event.type&&(c=e=0),a.loadImg=this.onload=this.onerror=null,d(c,e)},e.src=c):e={callbackId:b.setTimeout(function(){a.loadImg=null,d(0,0)},0)},a.loadImg=e,e=null}function v(a){var b=o.handlePropertychange;o.handlePropertychange=l,a(),o.handlePropertychange=b}function w(a,b){var c=a.currentStyle.display;return c!==b.display&&(b.display=c,b.changed=!0),"none"!==c}function x(a,b){var d=a.style,e=a.currentStyle,f=b.restore,i=y(e["background-size"]),k=i.split(" "),l={innerWidth:a.offsetWidth-(parseFloat(e.borderLeftWidth)||0)-(parseFloat(e.borderRightWidth)||0),innerHeight:a.offsetHeight-(parseFloat(e.borderTopWidth)||0)-(parseFloat(e.borderBottomWidth)||0),size:i,sizeIsKeyword:"contain"===i||"cover"===i,sizeX:k[0],sizeY:k.length>1?k[1]:"auto",posX:e.backgroundPositionX,posY:e.backgroundPositionY,attachment:e.backgroundAttachment,src:"",imgWidth:0,imgHeight:0};return l.sizeIsKeyword||((parseFloat(l.sizeX)>=0||"auto"===l.sizeX)&&(parseFloat(l.sizeY)>=0||"auto"===l.sizeY)||(l.sizeX=l.sizeY="auto"),g.test(l.sizeX)&&(l.sizeX=(l.innerWidth*parseFloat(l.sizeX)/100||0)+"px"),g.test(l.sizeY)&&(l.sizeY=(l.innerHeight*parseFloat(l.sizeY)/100||0)+"px")),(l.posX in h||g.test(l.posX))&&(l.posX=h[l.posX]||parseFloat(l.posX)/100||0),(l.posY in h||g.test(l.posY))&&(l.posY=h[l.posY]||parseFloat(l.posY)/100||0),(c.exec(d.backgroundImage)||[])[1]===j?v(function(){d.backgroundImage=f.backgroundImage}):f.backgroundImage=d.backgroundImage,l.src=(c.exec(e.backgroundImage)||[])[1],v(function(){d.backgroundImage="url("+j+")"}),l}function y(a){return String(a).replace(d,"").replace(e,"").replace(f," ")}function z(a,c){var d=c.next;function e(){p=b.setTimeout(function(){c.processing=!1,z(a,c)},0)}!c.processing&&d&&(c.next=null,c.processing=!0,u(c,d.src,function(b,f){d.imgWidth=b,d.imgHeight=f,A(c,d)?B(a,c,d,e):e()}))}function A(a,b){var c=a.current,d=!1,e;if(a.changed)a.changed=!1,d=!0;else for(e in b)if(b[e]!==c[e]){d=!0;break}return d}function B(a,c,d,e){var f=c.img,g=f.style,h=d.size,i=d.innerWidth,j=d.innerHeight,k=d.imgWidth,l=d.imgHeight,m=d.posX,n=d.posY,o="number"==typeof m,p="number"==typeof n,s="none",t=0,u=0,v="auto",w="auto",x="px",y="100%",z,A;i&&j&&k&&l&&(c.wrapper.style.position="fixed"===d.attachment&&c.canFixed?"fixed":"absolute",f.src=d.src,d.sizeIsKeyword?(z=i/j,A=k/l,"contain"===h&&A>z||"cover"===h&&z>A?(u=C((j-i/A)*n)+x,v=y):(t=C((i-j*A)*m)+x,w=y),g.left=o?t:m,g.top=p?u:n,g.width=v,g.height=w,s="block"):(g.display="block",g.width=d.sizeX,g.height=d.sizeY,k=f.width,l=f.height,k&&l&&(g.left=o?C((i-k)*m)+x:m,g.top=p?C((j-l)*n)+x:n,s="block"))),g.display=s,c.current=d,q=b.setTimeout(function(){r=b.setTimeout(e,0),updateEvent.fire()},0)}function C(a){var b=0>a;return a=Math.floor(Math.abs(a)),b?-a:a}function D(){var c=a.bgsExpando,d=(b.event||{}).propertyName,e="style.backgroundImage";c.ignore&&(c.ignore=!1,d===e)||(d===e&&a.style.backgroundImage&&(c.ignore=!0),w(a,c)&&(c.next=x(a,c),z(a,c)))}function E(){b.clearTimeout(n),n=b.setTimeout(D,m)}function F(){var c=a.bgsExpando,d,e,f;o={init:l,handlePropertychange:l,restore:l,handleResize:l},b.clearTimeout(n),b.clearTimeout(p),b.clearTimeout(q),b.clearTimeout(r);try{c&&(d=c.loadImg,d&&(d.onload=d.onerror=null,b.clearTimeout(d.callbackId)),e=a.style,f=c.restore,e&&(e.backgroundImage=f.backgroundImage,e.position=f.position,e.zIndex=f.zIndex),a.removeChild(c.wrapper)),a.bgsExpando=null}catch(g){}a=b=i=l=null}o={init:"print"!==i.media?s:l,handlePropertychange:l,restore:l,handleResize:l},"complete"===a.readyState&&o.init()}(element,window);</script>
-<script type="text/vbscript"></script>
-</PUBLIC:COMPONENT>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/images/upanddown.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/images/upanddown.png
deleted file mode 100644
index ce9f4e7e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/images/upanddown.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/pages/iconography.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/pages/iconography.css
deleted file mode 100644
index bff182d8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/pages/iconography.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Style Guide Styles */
-.icons-list{list-style:none;margin:20px 0 0;padding:0;font-size:0}.icons-list li{font-size:14px;display:inline-block;width:20%;box-sizing:border-box;vertical-align:top;padding:20px;margin-bottom:20px;cursor:default;min-height:130px;position:relative;overflow:hidden;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out}.icons-list li:hover{background:#fff;color:#199DDF;border-color:#d3d3d3}.icons-list [class*=icon]{display:inline-block;vertical-align:middle;-webkit-transition:font-size .2s ease-out;-moz-transition:font-size .2s ease-out;transition:font-size .2s ease-out}.icons-list[data-size=small] [class*=icon]{font-size:14px}.icons-list[data-size=medium] [class*=icon]{font-size:28px}.icons-list[data-size=large] [class*=icon]{font-size:56px}.icons-list.small-icons [class*=icon]{font-size:56px!important}.icons-list li [class*=icon]:hover{outline:1px dotted #444;color:#199DDF}.icons-list [data-role=title]{font-family:Arial;font-size:14px;margin-top:15px;display:block}.icons-list[data-display=list] li{display:block;margin-bottom:0;width:100%;min-height:0}.icons-list[data-display=list] [data-role=title]{display:inline-block;vertical-align:middle;margin:0;margin-left:15px}.icons-list [data-role=css-class]{display:none;font-size:11px;background:rgba(0,0,0,.8);color:#fff;margin-top:10px;text-align:center;box-sizing:border-box;position:absolute;left:0;right:0;bottom:-30px;padding:0 10px;height:25px;padding-top:7px;white-space:nowrap;overflow-x:auto;-webkit-transition:bottom .2s ease-out;-moz-transition:bottom .2s ease-out;transition:bottom .2s ease-out}.icons-list li:hover [data-role=css-class]{bottom:0}.icons-list[data-display=list] [data-role=css-class]{left:auto;top:50%;right:25px;margin-top:-12px;background:#d3d3d3;color:#444;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.show-dev-notes .icons-list [data-role=css-class]{display:block}.icons-list [data-role=css-class]::selection{background:#666}.icons-list[data-display=list] [data-role=css-class]::selection{background:#d3d3d3}.label-icon{display:block}.tabs-icon.tabs>li a{height:40px;line-height:40px;font-size:14px} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/sldr.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/sldr.css
deleted file mode 100644
index 151e394f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/sldr.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "UTF-8";address,blockquote,dd,h1,h2,h3,h4,h5,h6,ol,p,pre,table,ul{margin:0;padding:0;margin-bottom:24px;margin-bottom:1.5rem}html{font-size:1em;line-height:1.5}body{margin:0}h1{font-size:48px;font-size:3rem;line-height:1}h2{font-size:36px;font-size:2.25rem;line-height:1.3333333333}h3{font-size:30px;font-size:1.875rem;line-height:1.6}h4{font-size:24px;font-size:1.5rem;line-height:1}h5{font-size:20px;font-size:1.25rem;line-height:1.2}h6{font-size:18px;font-size:1.125rem;line-height:1.3333333333}dd,ol,ul{margin-left:48px;margin-left:3rem}li>ol,li>ul{margin-bottom:0}code,kbd,pre,samp{font-family:monospace,monospace}blockquote{text-indent:-.41em;quotes:"“" "â€";margin-left:48px;margin-left:3rem}blockquote p:before{content:"“";content:open-quote}blockquote p:after{content:"";content:no-close-quote}blockquote p:last-of-type:after{content:"â€";content:close-quote}q{quotes:"‘" "’" "“" "â€"}q:before{content:"‘";content:open-quote}q:after{content:"’";content:close-quote}q q:before{content:"“";content:open-quote}q q:after{content:"â€";content:close-quote}q:first-child{display:inline-block;text-indent:-.22em}table{width:100%;border-collapse:collapse;border-spacing:0}td,th{padding:12px}#grid{position:absolute;top:0;left:50%;width:980px;margin-left:-490px;counter-reset:section;z-index:9999!important;pointer-events:none;outline:1px solid rgba(0,206,209,.1)}#grid:after{position:fixed;top:0;left:0;content:'Column: 20px Gutter: 20px Margin: 20px';display:block;max-width:90px;padding:3px;background-color:#000;color:#fff;font-size:10px;font-family:monospace;z-index:9999}#grid div.vert{width:20px;outline:solid rgba(0,206,209,.3);outline-width:1px;margin-right:20px;position:relative;background:rgba(255,0,0,.05);counter-increment:section}#grid div.vert.first-line{margin-left:20px}#grid div.vert::after{position:fixed;display:block;text-align:center;color:#fff;width:20px;content:counter(section);top:5px;font-size:8px;font-family:monospace}#grid div.vert:nth-child(24){position:absolute;top:0;right:0}#grid div.vert:nth-child(1),#grid div.vert:nth-child(10),#grid div.vert:nth-child(11),#grid div.vert:nth-child(12),#grid div.vert:nth-child(13),#grid div.vert:nth-child(14),#grid div.vert:nth-child(15),#grid div.vert:nth-child(16),#grid div.vert:nth-child(17),#grid div.vert:nth-child(18),#grid div.vert:nth-child(19),#grid div.vert:nth-child(2),#grid div.vert:nth-child(20),#grid div.vert:nth-child(21),#grid div.vert:nth-child(22),#grid div.vert:nth-child(23),#grid div.vert:nth-child(24),#grid div.vert:nth-child(3),#grid div.vert:nth-child(4),#grid div.vert:nth-child(5),#grid div.vert:nth-child(6),#grid div.vert:nth-child(7),#grid div.vert:nth-child(8),#grid div.vert:nth-child(9){display:inline-block!important}#grid div.vert:nth-child(25),#grid div.vert:nth-child(26),#grid div.vert:nth-child(27),#grid div.vert:nth-child(28),#grid div.vert:nth-child(29),#grid div.vert:nth-child(30),#grid div.vert:nth-child(31){display:none!important}#grid div.horiz{height:10px;border-bottom:1px dotted rgba(100,100,100,.2);margin:0;padding:0}.bg-prime-blue{background-color:#067ab4}.bg-secondary-gray{background-color:#666}.bg-light-blue{background-color:#bcc9d5}.bg-dark-gray{background-color:#444}.bg-dusty-blue{background-color:#97b1cf}.bg-warm-gray{background-color:#cccb9b}.bg-taupe{background-color:#cccb6c}.bg-green-highlight{background-color:#c4d63f}.bg-lime-highlight{background-color:#dad632}.bg-purple-highlight{background-color:#b6539c}.bg-magenta{background-color:#d71481}.bg-blue-highlight{background-color:#4cc8f3}.bg-ochre{background-color:#fab230}.bg-green{background-color:#4fa721}.bg-lime{background-color:#b6bd26}.bg-purple{background-color:#7f0e7c}.bg-burgundy{background-color:#b1103e}.bg-dark-blue{background-color:#0e2875}.bg-gold{background-color:#fd9827}.bg-teal{background-color:#20c6b2}.bg-mint-green{background-color:#9cfecd}.bg-yellow{background-color:#feed35}.bg-white{background-color:#fff}.alt.inline-list>li{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;float:none}.text-upper{text-transform:uppercase!important}body{font-family:clearview_att_regular}.font-showcase h1,.font-showcase h2,.font-showcase h3,.font-showcase h4,.font-showcase h5,.font-showcase h6{font-weight:100;letter-spacing:-1px;margin:10px 0;-webkit-font-smoothing:antialiased}.font-showcase h1{font-family:omnes_att_light;font-size:48px;font-size:3rem;line-height:48px}.font-showcase h2,.price{font-family:omnes_att_light;font-size:36px;font-size:2.25rem;line-height:36px}.font-showcase h3{font-family:omnes_att_regular;font-size:24px;font-size:1.5rem;line-height:28px}.font-showcase h4,.font-showcase h4.font-showcase-font-example,.font-showcase h4.font-showcase-font-name{font-family:clearview_att_regular;font-size:18px;font-size:1.125rem;line-height:22px;-webkit-font-smoothing:antialiased}.font-showcase h5{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.font-showcase h6{font-family:Arial;font-size:11px;font-size:.6875rem;line-height:30px;font-weight:100;-webkit-font-smoothing:antialiased}.body-copy,.font-showcase p{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.body-copy-short{font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:15px;-webkit-font-smoothing:antialiased}p [class*=icon]{display:inline-block;vertical-align:middle;margin-top:-4px}.details-label{display:block;font-family:clearview_att_regular;font-size:11px;font-size:.6875rem;line-height:15px}.details-label+.price{line-height:28px}.price{letter-spacing:-1px;-webkit-font-smoothing:antialiased}.price sup{font-size:18px;font-size:1.125rem;vertical-align:baseline;top:-11px;margin:0 2px}.price-alt{font-size:24px;font-size:1.5rem;line-height:24px}.price-alt sup{font-size:12px;font-size:.75rem;top:-8px}.promo-tagline{font-family:omnes_att_medium_italic;font-size:16px;font-size:1rem;line-height:20px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.promo-text{font-family:clearview_att_italic;font-size:12px;font-size:.75rem;line-height:15px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.divider,.divider-dark,hr{border:0;border-bottom:1px solid #d3d3d3}.divider-light{border-color:#e5e5e5}dl{font-family:clearview_att_regular;color:#444;font-size:12px;font-size:.75rem}dt{font-family:Arial;font-size:11px;font-size:.6875rem;display:block!important;margin:10px 0 5px!important;width:auto!important;text-transform:uppercase}dt a{font-family:clearview_att_regular;color:#067ab4;text-transform:none}dd{display:inline!important;line-height:20px}[data-highlight]{background-color:#c9e9f9;-webkit-animation:highlight-fade 3s infinite}@-webkit-keyframes highlight-fade{100%,80%{background-color:transparent}}.att-slider{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;height:10px;margin:120px 0;position:relative}.att-slider:first-child{margin:0}.att-slider__track{position:absolute;top:0;right:0;bottom:0;left:0;background-color:none}.att-slider__range{position:absolute;left:0;-webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);background:#157BB2;border-radius:5px;height:100%;z-index:1}.att-slider__range--disabled{background-color:#D3D3D3}.att-slider__handles-container{height:100%;position:relative;border:1px solid #888;border-radius:5px}.att-slider__handle{-webkit-transition:background-color .2s ease-out;-moz-transition:background-color .2s ease-out;transition:background-color .2s ease-out;box-shadow:0 0 0 1px #fff;background:#157BB2;border-radius:100%;cursor:pointer;height:16px;margin:-4px 0 0 -7px;position:absolute;width:15px;z-index:1}.att-slider__handle--dragging,.att-slider__handle:hover{z-index:2;background-color:#158BC3}.att-slider__handle--disabled,.att-slider__handle--disabled:hover{box-shadow:none;background:0 0;cursor:default;z-index:1}.att-slider__handle.att-slider-handle-disabled{width:0;margin:0}.att-slider__range.att-slider__range--disabled{border-top-right-radius:0;border-bottom-right-radius:0}.att-slider__handle .att-tooltip--textonly,.att-slider__label{position:absolute;top:-25px;font-size:12px;font-size:.75rem;color:#6f6f6f;font-family:clearview_att_regular;margin:0;text-align:left;z-index:0}.att-slider__label:after{position:absolute;bottom:-5px;background-color:#888;content:'';display:block;height:5px;width:1px}.att-slider__label--max,.att-slider__label--max:after{right:0}.att-slider__label--below{bottom:-34px;top:auto}.att-slider__label--below:after{bottom:auto;top:-7px;left:50%}.att-slider__handle .att-tooltip{white-space:nowrap}.att-slider__handle .att-tooltip--textonly:after{position:absolute;bottom:-5px;left:50%;background-color:#888;border:0;content:'';display:block;height:5px;margin:0 0 0 -1px;width:1px}.step-slider.disabled{opacity:.5}.step-slider.disabled .jslider-value-to{display:none}.step-slider.disabled .jslider-bg i.v,.step-slider.disabled .jslider-pointer-to{background-color:#AAA}.step-slider{display:block;width:100%;height:1em;position:relative;top:.6em;font-family:Arial,sans-serif}.step-slider table{width:100%;border-collapse:collapse;border:0}.step-slider td,.step-slider th{padding:0;vertical-align:top;text-align:left;border:0}.step-slider .step-slider-green{background-color:#4CA90C}.step-slider .step-slider-blue{background-color:#44C8F5}.step-slider .step-slider-magenta{background-color:#DA0081}.step-slider .step-slider-gold{background-color:#F90}.step-slider .step-slider-purple{background-color:#81017E}.step-slider .step-slider-dark-blue{background-color:#0C2577}.step-slider .step-slider-regular{background-color:#0574AC}.step-slider .step-slider-white{background-color:#fff}.step-slider .cutoff-slider{border:1px solid #000!important}.step-slider .cutoff-slider-dividers span{height:7px!important}.step-slider .jslider-label-cutoff{position:relative!important;float:right}.step-slider .jslider-cutoff{position:relative;height:7px;top:0;background-color:#0574AC;border-bottom-left-radius:5px;border-top-left-radius:5px;border-bottom-right-radius:5px;border-top-right-radius:5px}.step-slider .jslider-limitless .jslider-label,.step-slider .jslider-single .jslider-bg .v,.step-slider .jslider-single .jslider-pointer-to,.step-slider .jslider-single .jslider-value-to{display:none}.step-slider .jslider-pointer-to{left:80%;top:-6px}.step-slider .jslider-pointer{border-radius:100%;border:2px solid #fff;top:-5px;width:15px;height:15px;z-index:10;background-position:0 -60px;position:absolute;left:20%;margin-left:-6px;cursor:pointer}.step-slider .jslider-bg{position:relative;height:100%}.step-slider .jslider-bg i{height:5px;position:absolute;width:5px}.step-slider .jslider-bg i.l{height:6px;background-color:#E5E5E5;border-top-left-radius:3px;border-bottom-left-radius:3px;width:50%;background-position:0 0;left:0}.step-slider .jslider-bg i.r{height:6px;background-color:#E5E5E5;border-top-right-radius:3px;border-bottom-right-radius:3px;width:50%;left:50%;background-position:right 0}.step-slider .jslider-bg i.v{border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute;width:60%;left:20%;top:0;height:5px;background-repeat:repeat-x;background-position:0 -40px}.step-slider .jslider-scale{position:relative;top:9px;z-index:9}.step-slider .jslider-scale span{top:-9px;width:1px;border-left:0;position:absolute;height:5px;font-size:0}.step-slider .show-dividers span{background-color:#FFF}.step-slider .jslider-label{top:15px;font-size:9px;line-height:12px;color:#000;opacity:.4;white-space:nowrap;padding:0 2px;position:absolute;left:0}.step-slider .jslider-label-to{left:auto;right:0}.step-slider #jslider-value-left,.step-slider #left-pointer{display:none}.step-slider .jslider-value{font-size:9px;white-space:nowrap;padding:1px 2px 0;position:absolute;top:-19px;left:20%;background:#fff;line-height:12px;-moz-border-radius:2px;-webkit-border-radius:2px;-o-border-radius:2px;border-radius:2px}.step-slider .jslider-value-to{margin-left:-31px;-webkit-background-clip:border-box;-webkit-background-origin:padding-box;-webkit-background-size:auto;-webkit-box-shadow:rgba(0,0,0,.298039) 0 4px 5px 0;-webkit-transition-delay:0s;-webkit-transition-duration:.2s;-webkit-transition-property:opacity;-webkit-transition-timing-function:ease-out;background-attachment:scroll;background-clip:border-box;background-color:#fefefe;background-image:none;background-origin:padding-box;background-size:auto;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top-left-radius:5px;border-top-right-radius:5px;box-shadow:rgba(0,0,0,.298039) 0 4px 5px 0;box-sizing:border-box;color:#444;display:block;font-family:clearview_att_regular;font-size:9px;line-height:15px;max-width:215px;opacity:1;padding:5px;position:absolute;z-index:0;top:-38px}.step-slider .jslider-value-to::after{content:'';border-bottom-color:transparent;border-bottom-style:solid;border-bottom-width:6px;border-image-outset:0;border-image-repeat:stretch;border-image-slice:100%;border-image-source:none;border-image-width:1;border-left-color:transparent;border-left-style:solid;border-left-width:6px;border-right-color:transparent;border-right-style:solid;border-right-width:6px;border-top-color:#fefefe;border-top-style:solid;border-top-width:6px;bottom:-12px;box-sizing:border-box;display:block;height:12px;left:40%;margin-top:-7px;position:absolute;top:auto;width:12px} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/style.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/style.css
deleted file mode 100644
index 289a1160..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/style.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "UTF-8";code[class*=language-],pre[class*=language-]{color:#f8f8f2;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono',monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#f8f8f2}.namespace{opacity:.7}.token.constant,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.important{font-weight:700}.token.entity{cursor:help}pre.line-numbers{position:relative;counter-reset:linenumber}pre.line-numbers>code{position:relative}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.alert,.alert-success{position:fixed;top:0;left:0;right:0;z-index:2;background-color:#e9eee3;color:#444;font-family:clearview_att_regular;font-size:12px;padding:0;border:0;border-radius:0}.alert-warning{background-color:#fff3d9}.alert-error{background-color:#f3e6e5}.alert-info{background-color:#dfeff7}.alert .container{padding:15px 90px 15px 60px}.alert .container:before{content:'\e69c';position:absolute;top:14px;left:25px;font-family:"Ionicons";font-size:14px;color:#6ebb1f}.alert-warning .container:before{content:'\e69d';color:#fcb314}.alert-error .container:before{content:'\e69d';color:#ff4539}.alert-info .container:before{content:'\e69b';color:#067ab4}.alert strong{font-family:Arial;font-size:11px;font-weight:100;text-transform:uppercase}.alert a{color:#067ab4}.alert a:hover{color:#199ddf}.alert [data-role=close]{position:absolute;top:13px;right:20px;font-size:11px;height:20px;line-height:23px;border:0}.alert [data-role=close] [class^=icon-]{font-size:20px;width:15px;color:#777;margin:0;vertical-align:middle;display:inline-block;margin-top:-4px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out}.alert [data-role=close]:hover [class^=icon-]{color:#199DDF}.alert .container,.alert-inplace{position:relative}.alert-inplace{z-index:1}.alert-inplace .container{width:100%}.tabs{display:inline-block;list-style:none;margin:0;padding:0;font-size:0}.tabs>li{padding:0;margin:0;display:inline-block}.tabs>li a{height:30px;width:auto;margin:0 0 0 -1px;padding:0 30px;background:#f2f2f2;border:1px solid #e7e6e6;text-align:center;font-size:11px;font-size:1.1rem;color:#6f6f6f;text-transform:uppercase;line-height:31px;cursor:pointer;display:inline-block}.tabs>li.first a,.tabs>li:first-child a{border-radius:4px 0 0 4px;margin-left:0}.tabs>li.last a,.tabs>li:last-child a{border-radius:0 4px 4px 0}.tabs>li a:hover{background:#e5e5e5;text-decoration:none;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out}.tabs>li.active a{background:#f8f8f8;color:#067ab4}.tabs-alt>li a,.tabs-small>li a{padding:0 15px}.tabs-light>li a{background-color:#fff}.tabs-icons>li a,.tabs-icons>li a:hover,.tabs-icons>li.active a{padding:0;border:0;background:0 0;font-size:28px;line-height:36px;margin-right:10px}.tabs-icons>li a i{vertical-align:middle}.tabs-icons>li a:hover{color:#067ab4}.tab-pane{display:none}.tab-pane.active{display:block}.tab-pane.html{padding:20px;border:1px solid #ddd;border-top:10px solid #272822;border-radius:0 0 3px 3px}address,blockquote,dd,h1,h2,h3,h4,h5,h6,ol,p,pre,table,ul{margin:0;padding:0;margin-bottom:24px;margin-bottom:1.5rem}html{font-size:1em;line-height:1.5}h1{font-size:48px;font-size:3rem;line-height:1}h2{line-height:1.3333333333}h3{line-height:1.6}h4{line-height:1}h5{font-size:20px;font-size:1.25rem;line-height:1.2}h6{font-size:18px;font-size:1.125rem;line-height:1.3333333333}dd,ol,ul{margin-left:48px;margin-left:3rem}li>ol,li>ul{margin-bottom:0}code,kbd,pre,samp{font-family:monospace,monospace}blockquote{text-indent:-.41em;quotes:"“" "â€";margin-left:48px;margin-left:3rem}blockquote p:before{content:"“";content:open-quote}blockquote p:after{content:"";content:no-close-quote}blockquote p:last-of-type:after{content:"â€";content:close-quote}q{quotes:"‘" "’" "“" "â€"}q:before{content:"‘";content:open-quote}q:after{content:"’";content:close-quote}q q:before{content:"“";content:open-quote}q q:after{content:"â€";content:close-quote}q:first-child{display:inline-block;text-indent:-.22em}table{width:100%;border-collapse:collapse;border-spacing:0}td,th{padding:12px}#grid{position:absolute;top:0;left:50%;width:980px;margin-left:-490px;counter-reset:section;z-index:9999!important;pointer-events:none;outline:1px solid rgba(0,206,209,.1)}#grid:after{position:fixed;top:0;left:0;content:'Column: 20px Gutter: 20px Margin: 20px';display:block;max-width:90px;padding:3px;background-color:#000;color:#fff;font-size:10px;font-family:monospace;z-index:9999}#grid div.vert{width:20px;outline:solid rgba(0,206,209,.3);outline-width:1px;margin-right:20px;position:relative;background:rgba(255,0,0,.05);counter-increment:section}#grid div.vert.first-line{margin-left:20px}#grid div.vert::after{position:fixed;display:block;text-align:center;color:#fff;width:20px;content:counter(section);top:5px;font-size:8px;font-family:monospace}#grid div.vert:nth-child(24){position:absolute;top:0;right:0}#grid div.vert:nth-child(1),#grid div.vert:nth-child(10),#grid div.vert:nth-child(11),#grid div.vert:nth-child(12),#grid div.vert:nth-child(13),#grid div.vert:nth-child(14),#grid div.vert:nth-child(15),#grid div.vert:nth-child(16),#grid div.vert:nth-child(17),#grid div.vert:nth-child(18),#grid div.vert:nth-child(19),#grid div.vert:nth-child(2),#grid div.vert:nth-child(20),#grid div.vert:nth-child(21),#grid div.vert:nth-child(22),#grid div.vert:nth-child(23),#grid div.vert:nth-child(24),#grid div.vert:nth-child(3),#grid div.vert:nth-child(4),#grid div.vert:nth-child(5),#grid div.vert:nth-child(6),#grid div.vert:nth-child(7),#grid div.vert:nth-child(8),#grid div.vert:nth-child(9){display:inline-block!important}#grid div.vert:nth-child(25),#grid div.vert:nth-child(26),#grid div.vert:nth-child(27),#grid div.vert:nth-child(28),#grid div.vert:nth-child(29),#grid div.vert:nth-child(30),#grid div.vert:nth-child(31){display:none!important}#grid div.horiz{height:10px;border-bottom:1px dotted rgba(100,100,100,.2);margin:0;padding:0}.bg-prime-blue{background-color:#067ab4}.bg-secondary-gray{background-color:#666}.bg-light-blue{background-color:#bcc9d5}.bg-dark-gray{background-color:#444}.bg-dusty-blue{background-color:#97b1cf}.bg-warm-gray{background-color:#cccb9b}.bg-taupe{background-color:#cccb6c}.bg-green-highlight{background-color:#c4d63f}.bg-lime-highlight{background-color:#dad632}.bg-purple-highlight{background-color:#b6539c}.bg-magenta{background-color:#d71481}.bg-blue-highlight{background-color:#4cc8f3}.bg-ochre{background-color:#fab230}.bg-green{background-color:#4fa721}.bg-lime{background-color:#b6bd26}.bg-purple{background-color:#7f0e7c}.bg-burgundy{background-color:#b1103e}.bg-dark-blue{background-color:#0e2875}.bg-gold{background-color:#fd9827}.bg-teal{background-color:#20c6b2}.bg-mint-green{background-color:#9cfecd}.bg-yellow{background-color:#feed35}.bg-white{background-color:#fff}html{background:#fff;overflow:auto}body{background-color:#fff;font-size:14px;font-size:.875rem;margin:0;padding:105px 0 20px;position:relative}.alt.inline-list>li{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;float:none}.text-upper{text-transform:uppercase!important}body{font-family:clearview_att_regular}.font-showcase h1,.font-showcase h2,.font-showcase h3,.font-showcase h4,.font-showcase h5,.font-showcase h6{font-weight:100;letter-spacing:-1px;margin:10px 0;-webkit-font-smoothing:antialiased}.font-showcase h1{font-family:omnes_att_light;font-size:48px;font-size:3rem;line-height:48px}.font-showcase h2,.price{font-family:omnes_att_light;font-size:36px;font-size:2.25rem;line-height:36px}.font-showcase h3{font-family:omnes_att_regular;font-size:24px;font-size:1.5rem;line-height:28px}.font-showcase h4,.font-showcase h4.font-showcase-font-example,.font-showcase h4.font-showcase-font-name{font-family:clearview_att_regular;font-size:18px;font-size:1.125rem;line-height:22px;-webkit-font-smoothing:antialiased}.font-showcase h5{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.font-showcase h6{font-family:Arial;font-size:11px;font-size:.6875rem;line-height:30px;font-weight:100;-webkit-font-smoothing:antialiased}.body-copy,.font-showcase p{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.body-copy-short{font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:15px;-webkit-font-smoothing:antialiased}p [class*=icon]{display:inline-block;vertical-align:middle;margin-top:-4px}.details-label{display:block;font-family:clearview_att_regular;font-size:11px;font-size:.6875rem;line-height:15px}.details-label+.price{line-height:28px}.price{letter-spacing:-1px;-webkit-font-smoothing:antialiased}.price sup{font-size:18px;font-size:1.125rem;vertical-align:baseline;top:-11px;margin:0 2px}.price-alt{font-size:24px;font-size:1.5rem;line-height:24px}.price-alt sup{font-size:12px;font-size:.75rem;top:-8px}.promo-tagline{font-family:omnes_att_medium_italic;font-size:16px;font-size:1rem;line-height:20px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.promo-text{font-family:clearview_att_italic;font-size:12px;font-size:.75rem;line-height:15px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.divider,.divider-dark,hr{border:0;border-bottom:1px solid #d3d3d3}.divider-light{border-color:#e5e5e5}dl{font-family:clearview_att_regular;color:#444;font-size:12px;font-size:.75rem}dt{font-family:Arial;font-size:11px;font-size:.6875rem;display:block!important;margin:10px 0 5px!important;width:auto!important;text-transform:uppercase}dt a{font-family:clearview_att_regular;color:#067ab4;text-transform:none}dd{display:inline!important;line-height:20px}[data-highlight]{background-color:#c9e9f9;-webkit-animation:highlight-fade 3s infinite}@-webkit-keyframes highlight-fade{100%,80%{background-color:transparent}}.changelog .title{border-bottom:1px solid #aaa;margin:50px 0 20px;padding-bottom:10px}.changelog:first-child .title{margin-top:0}.changelog:first-child .title a{color:#333}.changelog .title a:hover{color:#199DDF}.changelog .title a:hover:after{content:'#';margin-left:5px}.changelog .group{margin-bottom:20px}.changelog .changes-list{margin-bottom:30px}.changelog .changes-list li{margin-bottom:10px}.changelog .changes-list li:first-letter{text-transform:capitalize}.changelog .label-info{background-color:#333}.profile-card{height:380px;width:219px;border-radius:3px;margin:10px;border:solid 1px lightgrey;padding:0!important}.profile-card .top-block{padding:15px 20px;background-color:#e5e5e5;height:185px}.profile-card .bottom-block{padding:15px 20px;background-color:#fff}.profile-image{background:#e5e5e5;margin-bottom:15px;text-align:center}.profile-image .default-img,.profile-image img{display:inline-block;width:60px;height:60px;margin-bottom:10px;background-size:cover;text-align:center;background-position:center;border:6px solid #eee;border-radius:99em;-webkit-border-radius:99em;-moz-border-radius:99em;background-color:#eee}.profile-image .default-img{font-family:omnes_att_regular;color:#AAA;size:24px;line-height:22px;padding:15px;width:60px;height:60px}.profile-image .name{font-family:clearview-att_regular;font-size:18px;line-height:22px;color:#444;text-align:center;margin-bottom:5px;overflow:hidden;max-height:43px;word-break:break-word;white-space:normal}.profile-image .status-icon{border-radius:10px;border:1px solid #fff;margin:0 3px 0 0;width:10px;height:10px}.profile-image .status-icon.icon-green{background:#0c0}.profile-image .status-icon.icon-red{background:red}.profile-image .status-icon.icon-blue{background:#00f}.profile-image .status-icon.icon-yellow{background:#ff0}.profile-image .status{font-family:clearview_att_regular;font-size:12px;line-height:15px;text-align:center;margin:0 15px 0 0;color:#444}.profile-image .status .status-badge{margin-left:5px;border:dotted 1px #444;background-color:transparent;font-weight:400;color:#444;height:17px;padding:0 5px;border-radius:4px;font-size:11px}.profile-details{background:#fff}.profile-details label{display:block;font-family:Arial;font-size:12px;color:#444;padding:0;margin:0}.profile-details p{margin:0;font-family:clearview_att_regular;font-size:12px;color:#444;padding-bottom:6.5px}.add-user{background:#e5e5e5;border-style:dotted;font:clearview_att_regular;size:18px;line-height:21.6px;color:#666}.add-user i{font-size:30px;padding-bottom:15px}.atcenter{padding-top:150px;text-align:center}.scroll-viewport{overflow:hidden;position:relative}.scroll-overview{position:absolute;left:0;top:0;padding:0;margin:0;width:100%;display:table}.scroll-bar{background-color:#eaeaea;border-radius:5px;position:absolute;z-index:10;-webkit-transition:.6s ease-in-out opacity;transition:.6s ease-in-out opacity}.scroll-bar.disable{display:none}.scroll-bar.visible,.scroll-bar:hover{opacity:1!important}.scroll-thumb{background-color:#067ab4;border-radius:5px;cursor:pointer;overflow:hidden;position:absolute;top:0;left:1px}body.scroll-no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.next,.prev{position:absolute}.vertical .scroll-bar{top:0;right:0;width:8px;height:100%}.vertical .scroll-thumb{height:20px;width:6px}.vertical .prev{top:-70px;left:0}.vertical .next{bottom:-50px;left:0}.horizontal .scroll-bar{left:0;bottom:0;width:100%;height:8px;border-radius:0;background-color:transparent}.horizontal .scroll-thumb{height:6px;width:20px}.horizontal .prev{left:-26px;top:0;height:inherit;background-color:#999;margin:0;z-index:1;width:26px;border-radius:6px 0 0 6px}.horizontal .next{right:-26px;top:0;height:inherit;background-color:#999;margin:0;z-index:1;width:26px;box-shadow:-7px 0 0 rgba(0,0,0,.2);border-radius:0 6px 6px 0}.horizontal .next:hover,.horizontal .prev:hover{background:#067ab4}.horizontal .next a,.horizontal .prev a{background:inherit;display:block;margin-top:-14px;padding-bottom:20px;padding-top:20px;position:absolute;top:50%;border-radius:6px;color:#fff}.horizontal .next a{right:-15px}.horizontal .prev a{left:-15px}.container{padding-left:20px;padding-right:20px}.att--readless__link,.att--readmore__link,.link{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;font-size:12px;font-size:.75rem;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;color:#0574AC;cursor:pointer;line-height:15px;border-bottom:solid 1px}.att--readless__link:hover,.att--readmore__link:hover,.link:hover{color:#0091d9;border-bottom:dotted 1px}.link--large{font-size:14px;font-size:.875rem;line-height:20px}.link--right{*zoom:1;float:right}.link--right:after,.link--right:before{content:" ";display:table}.link--right:after{clear:both}.links-list__item,.links-list__item a{font-size:12px;font-size:.75rem;border-top:1px solid #444;cursor:pointer;display:block;line-height:30px}.links-list__item a a:hover,.links-list__item a:hover,.links-list__item:hover{color:#0091d9}.links-list__item a:first-child,.links-list__item:first-child{border:0}.links-list__item,.links-list__item a{color:#444;text-decoration:none}.link--visited,.link:visited{color:#0c2577;border-color:#0c2577;border-bottom:solid 1px}.link--visited:hover,.link:visited:hover{color:#0091d9;border-bottom:dotted 1px}.body-copy .link{font-size:14px;font-size:.875rem;font-family:clearview_att_regular;letter-spacing:0;line-height:17px}.att--readmore__link{margin-left:5px;margin-bottom:10px;-webkit-transition:width 2s ease,height 2s ease;-moz-transition:width 2s ease,height 2s ease;-o-transition:width 2s ease,height 2s ease;transition:width 2s ease,height 2s ease}.show-more-snippet{height:35px;width:300px;overflow:hidden}.wrapper{width:60%;margin:0 auto}.att--readMore{text-overflow:ellipsis;overflow:hidden;margin-bottom:20px;font-size:12px;font-size:.75rem;line-height:2;height:24px}.att--readLess{height:auto;overflow:visible;margin-bottom:20px;font-size:12px;font-size:.75rem;line-height:2}.navbar{position:fixed;top:0;right:0;left:0;z-index:2000;color:#f8f8f8;height:50px;font-size:12px;font-size:.75rem;background:#000;border:0;border-radius:0}.navbar-brand{display:block;line-height:50px;padding:0;font-size:12px;font-size:.75rem;font-weight:400;color:#f8f8f8;margin-left:0!important;padding-left:40px;background:url(images/logo.png) 0 center no-repeat}.nav{list-style:none;margin:0;padding:0}.navbar li{margin:0;float:left}.navbar li:first-child{margin-left:0}.navbar li>a{display:block;height:50px;line-height:50px;padding:0 10px;color:#bbb;-moz-box-sizing:border-box;box-sizing:border-box}.navbar li.active>a{border-bottom:4px solid #FC411E}.navbar li>a:focus,.navbar li>a:hover{background-color:#181818}.navbar li.active>a,.navbar li>a:hover{color:#f8f8f8}.navbar .dropdown{position:relative;margin:0 0 0 10px}.navbar .dropdown:hover>a{-webkit-transition:none;-moz-transition:none;transition:none;background-color:#474747}.navbar .dropdown:hover .dropdown-menu{display:block}.navbar .dropdown-menu{position:absolute;list-style:none;margin:0;padding:0;min-width:120px;display:none;border:0;border-radius:0}.pull-right .dropdown-menu{left:auto;right:0;top:100%;background-color:#474747}.navbar .dropdown-menu li{display:block;float:none;margin:0;width:100%}.navbar .dropdown-menu li a:hover{background-color:#FC411E}.att-tooltip{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;font-size:12px;font-size:.75rem;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out;box-shadow:0 4px 5px 0 rgba(0,0,0,.3);-webkit-box-shadow:0 4px 5px 0 rgba(0,0,0,.3);-moz-box-shadow:0 4px 5px 0 rgba(0,0,0,.3);background:#ddd;border-radius:5px;color:#444;display:block;line-height:15px;margin:10px 0 0;max-width:215px;opacity:0;padding:7px 10px;position:absolute;z-index:5}.att-tooltip:after,.att-tooltip:before{position:absolute;left:50%;content:'';margin-left:-7px;border:6px solid transparent}.att-tooltip:before{top:-12px;border-bottom-color:#ccc}.att-tooltip:after{top:-12px;border-bottom-color:#ddd}.att-tooltip--on{opacity:1}.att-tooltip--right{margin:0 0 0 10px}.att-tooltip--right:after,.att-tooltip--right:before{top:50%;left:-5px;margin-top:-7px;border-bottom-color:transparent}.att-tooltip--right:before{border-right-color:#ccc;left:-5px}.att-tooltip--right:after{border-right-color:#ddd}.att-tooltip--left{margin:0 0 0 -10px}.att-tooltip--left:after,.att-tooltip--left:before{top:50%;left:auto;right:-12px;margin-top:-7px;border-bottom-color:transparent}.att-tooltip--left:before{border-left-color:#ccc;right:-12px}.att-tooltip--left:after{border-left-color:#ddd}.att-tooltip--above{margin:-10px 0 0 0}.att-tooltip--above:after,.att-tooltip--above:before{top:auto;bottom:-12px;margin-top:-7px;border-bottom-color:transparent}.att-tooltip--above:before{border-top-color:#ccc;bottom:-12px}.att-tooltip--above:after{border-top-color:#ddd}.att-tooltip--light{background-color:#fefefe}.att-tooltip--light.att-tooltip--above:after{border-top-color:#fefefe}.att-tooltip--light.att-tooltip--below:after{border-bottom-color:#fefefe}.att-tooltip--light.att-tooltip--right:after{border-right-color:#fefefe}.att-tooltip--light.att-tooltip--left:after{border-left-color:#fefefe}.att-tooltip--dark{background-color:#6d6d6d;color:#fefefe}.att-tooltip--dark.att-tooltip--above:after{border-top-color:#6d6d6d}.att-tooltip--dark.att-tooltip--below:after{border-bottom-color:#6d6d6d}.att-tooltip--dark.att-tooltip--right:after{border-right-color:#6d6d6d}.att-tooltip--dark.att-tooltip--left:after{border-left-color:#6d6d6d}.att-tooltip--light--hover:hover{padding:6px 9px;border:1px solid #8d8d8d}.att-tooltip--light--hover:hover.att-tooltip--left:before{border-left-color:#8d8d8d;margin-right:-1px}.att-tooltip--light--hover:hover.att-tooltip--right:before{border-right-color:#8d8d8d;margin-left:-8px}.att-tooltip--light--hover:hover.att-tooltip--above:before{border-top-color:#8d8d8d;margin-bottom:-1px}.att-tooltip--light--hover:hover.att-tooltip--below:before{border-bottom-color:#8d8d8d;margin-top:-1px}.att-tooltip--dark--hover:hover{padding:6px 9px;border:1px solid #404040}.att-tooltip--dark--hover:hover.att-tooltip--left:before{border-left-color:#404040;margin-right:-1px}.att-tooltip--dark--hover:hover.att-tooltip--right:before{border-right-color:#404040;margin-left:-8px}.att-tooltip--dark--hover:hover.att-tooltip--above:before{border-top-color:#404040;margin-bottom:-1px}.att-tooltip--dark--hover:hover.att-tooltip--below:before{border-bottom-color:#404040;margin-top:-1px}.att-tooltip--active--dark{width:60px;min-width:60px;max-width:300px;background-color:#6d6d6d;color:#fff;border:0}.att-tooltip--active--dark:focus{outline:0}.att-tooltip--active--light{width:60px;min-width:60px;max-width:300px;background-color:#fefefe;border:0}.att-tooltip--active--light:focus{outline:0}.att-tooltip--textonly{background:0 0;border-color:transparent;padding:0}.att-tooltip--textonly:after,.att-tooltip--textonly:before{display:none}.button.button--small.att-tooltip--button{min-width:60px!important}.lt-ie9 .pop-over-caret--above{bottom:-5px!important}.lt-ie9 .pop-over-caret-border--above{bottom:-6px!important}.lt-ie9 .pop-over-caret--below{top:-5px!important}.lt-ie9 .pop-over-caret-border--below{top:-6px!important}.lt-ie9 .pop-over-caret--right{left:-5px!important}.lt-ie9 .pop-over-caret-border--right{left:-6px!important}.att-pop-over--above{margin:-10px 0 0 1px!important}.att-pop-over--left{margin:-7px 0 0 -6px!important}.att-pop-over--right{margin:-7px 0 0 6px!important}.att-popover{border:1px solid #d3d3d3;max-width:490px;padding:19px;pointer-events:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;font-size:12px;font-size:.75rem;-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;transition:opacity .2s ease-out;background:#fff;border-radius:5px;box-shadow:0 5px 6px 0 rgba(0,0,0,.25);color:#444;display:table;line-height:15px;margin:6px 0 0;min-height:29px;position:absolute!important;z-index:5;opacity:1}.att-popover:focus{outline:0}.att-popover .pop-over-caret{width:0;height:0;position:absolute}.att-popover .pop-over-caret.pop-over-caret-border--below{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #d3d3d3;top:-7px;left:50%}.att-popover .pop-over-caret.pop-over-caret-border--above{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #d3d3d3;bottom:-7px;left:50%;margin-left:-7px}.att-popover .pop-over-caret.pop-over-caret-border--left{border-top:6px solid transparent;border-left:6px solid #d3d3d3;border-bottom:6px solid transparent;right:-6px;top:50%}.att-popover .pop-over-caret.pop-over-caret-border--right{border-right:6px solid #d3d3d3;border-top:6px solid transparent;border-bottom:6px solid transparent;left:-7px;top:50%}.att-popover .pop-over-caret.pop-over-caret--below{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #f2f2f2;top:-6px;left:50%}.att-popover .pop-over-caret.pop-over-caret--above{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #f2f2f2;bottom:-6px;left:50%;margin-left:-7px}.att-popover .pop-over-caret.pop-over-caret--left{border-top:6px solid transparent;border-left:6px solid #f2f2f2;border-bottom:6px solid transparent;right:-5px;top:50%}.att-popover .pop-over-caret.pop-over-caret--right{border-right:6px solid #f2f2f2;border-top:6px solid transparent;border-bottom:6px solid transparent;left:-6px;top:50%}.att-popover .att--readless__link,.att-popover .att--readmore__link,.att-popover .link{color:#0574AC}.att-popover .att--readless__link:hover,.att-popover .att--readless__link:hover:visited,.att-popover .att--readmore__link:hover,.att-popover .att--readmore__link:hover:visited,.att-popover .link:hover,.att-popover .link:hover:visited{color:#0091d9}.att-popover .att--readless__link--visited,.att-popover .att--readless__link:visited,.att-popover .att--readmore__link--visited,.att-popover .att--readmore__link:visited,.att-popover .link--visited,.att-popover .link:visited{color:#0c2577}.att-popover .att--readless__link--visited:hover,.att-popover .att--readless__link:visited:hover,.att-popover .att--readmore__link--visited:hover,.att-popover .att--readmore__link:visited:hover,.att-popover .link--visited:hover,.att-popover .link:visited:hover{color:#0091d9}.att-tooltip.att-popover{pointer-events:auto}.att-popover-content{display:none!important;text-align:left}.att-popover--with-header.att-tooltip--below:below{display:none}.att-popover--with-header.att-tooltip--below:after{border-bottom-color:#0574AC}.att-popover.att-popover--value-selector{max-width:220px;padding:20px;text-align:center}.att-popover.att-popover--value-selector .att-color-selector__item{width:40px;height:40px;-webkit-transition:none;-moz-transition:none;transition:none;background:0 0;border:0;position:relative}.att-popover.att-popover--value-selector .att-color-selector__item:before{position:absolute;-webkit-transition:border-color .3s ease-out;-moz-transition:border-color .3s ease-out;transition:border-color .3s ease-out;border:3px solid transparent;border-radius:50%;content:''}.att-popover.att-popover--value-selector .att-color-selector__item .att-radio__indicator{-webkit-transform:scale3d(1,1,1);-moz-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);-o-transform:scale3d(1,1,1);transform:scale3d(1,1,1);width:38px;height:38px;border:1px solid #444;border-radius:38px;display:block;-ms-filter:none;filter:none;left:50%;margin:-19px 0 0 -19px;opacity:1;top:50%}.att-popover.att-popover--value-selector .att-radio--on.att-color-selector__item:before{border-color:#0574AC}.att-popover.att-popover--value-selector .att-radio--on.att-color-selector__item .att-radio__indicator{width:28px;height:28px;margin:-14px 0 0 -14px}.att-popover.att-popover--value-selector .att-radio.att-value-selector__item{width:40px;height:40px;background:0 0;border:2px solid transparent;color:#666;padding:1px}.att-popover.att-popover--value-selector .att-radio.att-value-selector__item .att-radio__indicator{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:none;-moz-transition:none;transition:none;width:40px;height:40px;background:0 0;border:1px solid #666;border-radius:50%;color:#666;-ms-filter:none;filter:none;margin:0;opacity:1;padding-top:5px;position:static}.att-popover.att-popover--value-selector .att-radio--on.att-value-selector__item .att-radio__indicator{background:#0574AC;border-color:#0574AC;color:#fff}.att-popover__close{position:absolute;top:9px;right:9px;font-size:14px;font-size:.875rem;color:#444}.popover-demo .att-popover-content{display:block!important}.popover-demo .popover-packages__container{background:0 0}.popover-demo .popover-packages__container p{color:#444}.popover-demo .popover-packages__text-block{padding:5px 0 0}.popover-demo .popover-packages__text-block-row p{font-size:12px}.popover-demo hr{border-bottom:1px solid #b2b2b2;margin:10px 0 25px}.icon-close:before{content:'\e6d5'}.breadcrumbs{color:#444;height:50px;list-style:none;text-align:right}.breadcrumbs__item{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto}.breadcrumbs__item:before{font-size:11px;font-size:.6875rem;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;content:'>';margin-left:10px;vertical-align:middle}.breadcrumbs__item:first-child:before{display:none}.breadcrumbs__link{font-size:12px;font-size:.75rem;font-family:clearview_att_regular;color:#666;margin-left:10px}.breadcrumbs__link:hover{color:#0574AC;text-decoration:underline}.breadcrumbs__link--active,.breadcrumbs__link--active:hover{color:#444;text-decoration:none}.pager{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:0;list-style:none;margin:10px 0 0}.pager--dark{background-color:#000;padding:10px 10px 10px 5px}.pager__item{font-size:12px;font-size:.75rem;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;cursor:default;color:#4b4b4b;margin-left:12px;text-align:center;width:33px;height:33px;border-radius:6px;padding:7px}.pager__item [class^=icon-]{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:12px;font-size:.75rem;color:#888}.pager__item--link{border-radius:50px;border:1px solid transparent;color:#4b4b4b;cursor:pointer}.pager__item--link:hover{background:#b2b2b2;color:#4b4b4b}.pager__item--active{background:#067AB4;color:#fff;cursor:default}.pager__item--active:hover{background:#b2b2b2;color:#4b4b4b}.pager__item--active:focus{color:#fff}.pager__item--input{color:#067ab4;margin-left:12px;padding-left:12px;padding-right:12px;text-align:center;max-width:40px;max-height:29px}.pager__item--next,.pager__item--prev{font-size:12px;cursor:pointer;padding:12px;color:#888}.pager__item--next:hover,.pager__item--prev:hover{background:0 0;border-color:none;color:#0574AC}.pager__item--next:hover [class^=icon-],.pager__item--prev:hover [class^=icon-]{color:#0574AC}.views-per-page__item--active a::after,.views-per-page__item--active:hover a::after{border-bottom-color:#0574ac;border-bottom-width:2px;color:#0574ac;opacity:1}.views-per-page{display:inline-block;font-size:0}.views-per-page__item{display:inline-block;font-size:14px;margin-left:3px;text-align:center;width:33px}.views-per-page__item a{color:#444;outline:0 none;position:relative}.views-per-page__item a:focus::before{opacity:1}.views-per-page__item a::after{border-bottom:1px solid #0091d9;bottom:0;content:"";left:0;opacity:0;position:absolute;right:0;top:18px;transition:all .2s ease-out 0s}.views-per-page__item a::before{border:1px solid #44c8f5;border-radius:0;bottom:auto;content:"";display:inline-block;height:38px;left:50%;margin:-19px;opacity:0;position:absolute;right:auto;top:50%;transform:scale3d(1,1,1);width:38px}.views-per-page__item:hover{cursor:pointer}.views-per-page__item:hover a{color:#0091d9}.views-per-page__item:hover a::after{opacity:1}.views-per-page__item:first-child{margin-left:0;width:auto}.views-per-page__item:first-child:hover{color:#444;cursor:inherit}.views-per-page__item:first-child:hover::after{opacity:0}.lt-ie9 .views-per-page__item a::after,.lt-ie9 .views-per-page__item a::before{content:none}.lt-ie9 .views-per-page__item a:focus::before,.lt-ie9 .views-per-page__item--active a::after,.lt-ie9 .views-per-page__item--active:hover a::after,.lt-ie9 .views-per-page__item:hover a::after{content:""}.views-per-page__item--active a,.views-per-page__item--active:hover a{color:#0574ac}.sidebar{width:230px;padding:15px;background-color:#f2f2f2}.sidebar>.nav{margin-top:30px}.sidebar .nav a{color:#6f6f6f;display:block;padding:2px 0}.sidebar .nav .nav{display:none;margin:0 0 10px}.sidebar .nav .nav a{font-size:12px;font-size:.75rem;color:#999}.sidebar .nav a:hover,.sidebar>.nav .active>a{color:#FC411E;text-decoration:underline}.sidebar>.nav>.active .nav{display:block}.steptracker{padding:0;font-size:0;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.steptracker-bg{padding:0;font-size:0;position:relative}.steptracker-bg:before{content:'';position:absolute;height:4px;background:#e5e5e5;top:50%;right:0;left:0;margin-top:-2px;width:100%}.steptracker-track .circle{display:block;max-width:40px;max-height:40px;padding:11px 0;-moz-box-sizing:border-box;box-sizing:border-box;background:#e5e5e5;border-radius:20px;position:relative;font-size:11px;font-size:.6875rem;line-height:15px;color:#999;text-align:center;border:1px solid transparent;z-index:2}.steptracker-track .circle span{display:block;font-size:10px;font-size:.625rem;line-height:20px;text-align:left;color:#999;position:absolute;height:18px;width:65px;top:18px;left:0;padding-top:20px;cursor:default}.steptracker-track .track{content:'';position:absolute;height:4px;top:50%;left:0;width:0;margin-top:-2px;margin-left:20px;background:#e5e5e5;border-radius:2px;-webkit-transition:all .2s ease-in-out 0s;-moz-transition:all .2s ease-in-out 0s;transition:all .2s ease-in-out 0s}.steptracker-track.incomplete .track{background:#e5e5e5}.steptracker-track.done .track{background:#1b7e28;width:100%}.steptracker-track.active .track{background:#0574ac}.lt-ie9 .steptracker-track .circle span{left:-20px}.steptracker-track .circle,.steptracker-track .circle span{-webkit-transition:background-color .3s ease-out,color .3s ease-out;-moz-transition:background-color .3s ease-out,color .3s ease-out;transition:background-color .3s ease-out,color .3s ease-out}.steptracker-track{display:inline-block;font-size:15px;font-size:.9375rem;position:relative}.steptracker-track.active:before,.steptracker-track.done:before{width:101%}.steptracker-track.last{margin-right:-40px;width:40px}.steptracker-track.done .circle{background:#1b7e28;color:#fff;cursor:pointer}.steptracker-track.done .circle:hover{background:#199ddf;color:#fff}.steptracker-track.done .circle span{color:#444;cursor:pointer}.steptracker-track.incomplete .circle{background:#e5e5e5;color:#999}.steptracker-track.done .circle span:hover{color:#199ddf}.steptracker-track.active .circle{background:#0574ac;color:#fff}.steptracker-track.active .circle:hover{background:#199ddf;color:#fff}.steptracker-track.active .circle span{color:#0574ac}.steptracker-track.disabled{pointer-events:none;cursor:not-allowed}.att-timeline{position:relative}.att-timeline .completed-color{background-color:#1B7E28}.att-timeline .alert-color{background-color:#E00000}.att-timeline .cancelled-color{background-color:#999}.att-timeline .completed-color-text{color:#1B7E28}.att-timeline .alert-color-text{color:#E00000}.att-timeline .cancelled-color-text{color:#666}.att-timeline .inactive-color-text{color:#AAA}.att-timeline .timeline-bar{width:30%;float:left;position:relative}.att-timeline .timeline-bar .progress-bar{width:100%;height:2px;position:relative;z-index:100}.att-timeline .timeline-bar hr{border:0;border-top:2px dotted #AAA;position:relative;top:-20px;z-index:50px}.att-timeline .timeline-dot{width:10px;height:30px;top:-4px;position:relative;float:left}.att-timeline .timeline-dot .bigger-circle{width:10px;height:10px;border-radius:25px;z-index:50;position:absolute;opacity:.5}.att-timeline .timeline-dot .inactive-circle{width:10px;height:10px;border-radius:25px;border:1px solid #AAA;background-color:#fff;z-index:100;position:absolute}.att-timeline .timeline-dot .expandable-circle{width:10px;height:10px;border-radius:25px;z-index:150;position:absolute}.att-timeline .timeline-dot .below-info-box{position:relative;top:10px;left:4.5px;width:auto;min-width:150px}.att-timeline .timeline-dot .below-info-box .vertical-line{border-left:1px solid #AAA;width:1px;height:25px}.att-timeline .timeline-dot .below-info-box .info-container .title{position:relative;font-size:18px;line-height:22px;z-index:100;width:50%;font-family:clearview_att_regular}.att-timeline .timeline-dot .below-info-box .info-container .current-step-title{position:relative;font-size:18px;line-height:22px;z-index:100;width:50%;font-family:Arial}.att-timeline .timeline-dot .below-info-box .info-container .content{font-size:14px;color:#444;line-height:20px;position:relative}.att-timeline .timeline-dot .below-info-box .info-container .date{font-size:14px;color:#444;line-height:20px;position:relative;width:100%}.att-timeline .timeline-dot .above-info-box{position:relative;top:-105px;left:3.5px;width:auto;min-width:150px}.att-timeline .timeline-dot .above-info-box .vertical-line{border-left:1px solid #AAA;width:1px;height:25px}.att-timeline .timeline-dot .above-info-box .info-container .title{position:relative;font-size:18px;line-height:22px;z-index:100;width:50%;font-family:clearview_att_regular}.att-timeline .timeline-dot .above-info-box .info-container .current-step-title{position:relative;font-size:18px;line-height:22px;z-index:100;width:50%;font-family:Arial}.att-timeline .timeline-dot .above-info-box .info-container .content{font-size:14px;color:#444;line-height:20px;position:relative}.att-timeline .timeline-dot .above-info-box .info-container .date{font-size:14px;color:#444;line-height:20px;position:relative;width:100%}.vertical-nav{padding:11px 0;font-family:clearview_att_regular;font-size:11px}.vertical-nav ul{display:block;margin:0;padding:0 0 0 7px}.vertical-nav ul.tickets-list-height{height:221px;overflow-y:hidden}.vertical-nav ul.tickets-list-height-auto{height:auto}.vertical-nav ul li{display:block;padding:0 0 0 20px;height:41px;border-left:solid 1px #666;margin-top:3px;position:relative}.vertical-nav ul li i{position:absolute;left:-8px;top:2px;background-color:#f2f2f2;outline:3px solid #f2f2f2;outline-offset:0}.vertical-nav ul li i.icon-ticket-regular{border-radius:100%;width:6px;height:6px;background-color:#666;top:3px;left:-4px}.vertical-nav ul li .ticket-title{font-family:Arial;font-size:12px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;width:45%}.vertical-nav ul li .ticket-title-regular{font-family:clearview_att_regular;font-size:11px;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;width:45%}.vertical-nav ul li .ticket-timestamp{font-size:11px;line-height:15px;padding:3px 0}.vertical-nav .view-log{position:absolute;right:0;bottom:4px}.vertical-nav .view-log a{text-decoration:underline}.tags__item{font-size:12px;font-size:.75rem;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;border-radius:5px;border:1px solid #666;color:#444;margin:3px 5px 3px 0;padding:2px 10px}.tags__item a:hover{color:#666}.tags__item:last-child{margin-right:0}.tags__item:hover{background:#D3D3D3}.tags__item:active{background:#BBB}.tags__item:active>.tag__item--action,.tags__item:active>.tags__item--icon,.tags__item:hover>.tags__item--action,.tags__item:hover>.tags__item--icon{color:#444;border-color:#444}.tags__item.tags__item--color{border:1px solid #118817}.tags__item.tags__item--color .tags__item--title{padding-left:18px}.tags__item.tags__item--color .tags__item--color-icon{background:#118817;border:1px solid #118817;border-radius:100%;cursor:pointer;height:12px;width:12px;margin:6px 0 0;position:absolute;z-index:1}.tags__item.tags__item--color .active{background:#118817;color:#fff}.tags__item.tags__item--color .active>.tags__item--action{color:#fff;border-left:1px solid #fff}.tags__item.tags__item--color .active>.tags__item--color-icon,.tags__item.tags__item--color:hover>.tags__item--color-icon{border:1px solid #fff}.tags__item.tags__item--color:active{background:#118817;color:#fff}.tags__item.tags__item--color:active>.tags__item--action{color:#fff;border-left:1px solid #fff}.tags__item.tags__item--color:active>.tags__item--color-icon{border:1px solid #fff}.tags__item.tags__item--small{height:24px;padding:0 10px}.tags__item.tags__item--cloud .active{background:#157BB2;border-color:#157BB2}.tags__item.tags__item--cloud .active>.tags__item--icon,.tags__item.tags__item--cloud .active>.tags__item--title{color:#fff}.tags__item.tags__item--cloud:active{background:#157BB2;border-color:#157BB2}.tags__item.tags__item--cloud:active>.tags__item--icon,.tags__item.tags__item--cloud:active>.tags__item--title{color:#fff}.tags__item--action,.tags__item--icon,.tags__item--title{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;font-size:14px;font-size:.875rem;line-height:1.7142857143;vertical-align:middle;margin:0}.tags__item--icon{font-size:14px;font-size:.875rem;line-height:1.7142857143;color:#888}.tags__item--action{border-left:1px solid #888;color:#888;cursor:pointer;margin-left:5px;text-align:center;width:18px}.tags__item--action [class^=icon-]{font-size:14px;font-size:.875rem;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;margin-left:5px;margin-top:-2px;vertical-align:middle;width:14px}.lt-ie9 .tags__item--action [class^=icon-]{margin-top:4px}.att-progress{height:21px;background-color:#ddd;border-radius:21px;position:relative}.att-progress-value{border-radius:27px;background-color:#067ab4;width:0;min-width:21px;height:21px;-webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);-webkit-animation:att-progress 1s ease-out 0s infinite alternate,att-progress-width 10s ease-out infinite;-moz-animation:att-progress 1s ease-out 0s infinite alternate,att-progress-width 10s ease-out infinite;animation:att-progress 1s ease-out 0s infinite alternate,att-progress-width 10s ease-out infinite}@-webkit-keyframes att-progress{from{background-color:#067ab4}to{background-color:#199ddf}}@-moz-keyframes att-progress{from{background-color:#067ab4}to{background-color:#199ddf}}@keyframes att-progress{from{background-color:#067ab4}to{background-color:#199ddf}}@-webkit-keyframes att-progress-width{0%{width:0}100%,70%{width:100%}}@-moz-keyframes att-progress-width{0%{width:0}100%,70%{width:100%}}@keyframes att-progress-width{0%{width:0}100%,70%{width:100%}}.loader{display:inline-block;vertical-align:middle;background:url(images/loader.gif) center center no-repeat;min-width:75px;min-height:75px}.loading{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto}.loading .loading__inside,.loading:after,.loading:before{-webkit-animation:loading-item 1s infinite ease-out;-moz-animation:loading-item 1s infinite ease-out;animation:loading-item 1s infinite ease-out;width:8px;height:8px;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;background:#000;border-radius:50%;content:'';margin-left:6px;vertical-align:middle}.loading:before{-webkit-animation-delay:1s;-moz-animation-delay:1s;animation-delay:1s;margin-left:0}.loading .loading__inside{-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s;animation-delay:1.2s}.loading:after{-webkit-animation-delay:1.4s;-moz-animation-delay:1.4s;animation-delay:1.4s}.ie .loading{width:46px;height:20px;background:url(images/loading_balls_black.gif) center center no-repeat}.ie .loading .loading__inside,.ie .loading:after,.ie .loading:before{display:none}.loading--small .loading__inside,.loading--small:after,.loading--small:before{width:5px;height:5px;margin-left:4px}.ie .loading--small{width:37px;height:18px;background:url(images/loading_balls_black-small.gif) center center no-repeat}.ie .loading--small.att-loading--blue{background:url(images/loading_balls_blue-small.gif) center center no-repeat}.ie .loading--small.att-loading--white{background:url(images/loading_balls_white-small.gif) center center no-repeat}@-webkit-keyframes loading-item{0%{-webkit-transform:scale(1)}20%{-webkit-transform:scale(.8)}40%,60%{-webkit-transform:scale(.6)}80%{-webkit-transform:scale(.8)}100%{-webkit-transform:scale(1)}}@-moz-keyframes loading-item{0%{-moz-transform:scale(1)}20%{-moz-transform:scale(.8)}40%,60%{-moz-transform:scale(.6)}80%{-moz-transform:scale(.8)}100%{-moz-transform:scale(1)}}@-o-keyframes loading-item{0%{-o-transform:scale(1)}20%{-o-transform:scale(.8)}40%,60%{-o-transform:scale(.6)}80%{-o-transform:scale(.8)}100%{-o-transform:scale(1)}}@keyframes loading-item{0%{transform:scale(1)}20%{transform:scale(.8)}40%,60%{transform:scale(.6)}80%{transform:scale(.8)}100%{transform:scale(1)}}.att-loading-count{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;background-color:transparent;border-radius:50%;height:36px;position:relative;width:36px}.att-loading-count .att-loading-circle__fill,.att-loading-count .att-loading-circle__mask{height:36px;position:absolute;width:36px;-webkit-transition:transform 1s;-moz-transition:transform 1s;transition:transform 1s;-webkit-backface-visibility:hidden;border-radius:50%}.att-loading-count .att-loading-circle__mask{clip:rect(0,36px,36px,18px)}.att-loading-count .att-loading-circle__mask .att-loading-circle__fill{background-color:#444;clip:rect(0,18px,36px,0)}.att-loading-count .att-loading-inset{background-color:#f2f2f2;border-radius:50%;height:32px;left:0;margin-left:2px;margin-top:2px;position:absolute;top:0;width:32px}.lt-ie9 .att-loading-count .att-loading-inset{height:0;width:0}.att-loading-count .att-loading-inset__percentage{position:absolute;top:10px;left:1px;color:#444;font-size:12px;font-weight:800;line-height:1;text-align:center;width:30px}.att-loading-count[data-progress="0"] .att-loading-circle__fill,.att-loading-count[data-progress="0"] .att-loading-circle__fill.att-loading-circle__fix,.att-loading-count[data-progress="0"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}.att-loading-count[data-progress="0"] .att-loading-inset .att-loading-inset__percentage:before{content:"0"}.att-loading-count[data-progress="1"] .att-loading-circle__fill,.att-loading-count[data-progress="1"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(1.8deg);-moz-transform:rotate(1.8deg);-ms-transform:rotate(1.8deg);-o-transform:rotate(1.8deg);transform:rotate(1.8deg)}.att-loading-count[data-progress="1"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(3.6deg);-moz-transform:rotate(3.6deg);-ms-transform:rotate(3.6deg);-o-transform:rotate(3.6deg);transform:rotate(3.6deg)}.att-loading-count[data-progress="1"] .att-loading-inset .att-loading-inset__percentage:before{content:"1"}.att-loading-count[data-progress="2"] .att-loading-circle__fill,.att-loading-count[data-progress="2"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(3.6deg);-moz-transform:rotate(3.6deg);-ms-transform:rotate(3.6deg);-o-transform:rotate(3.6deg);transform:rotate(3.6deg)}.att-loading-count[data-progress="2"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(7.2deg);-moz-transform:rotate(7.2deg);-ms-transform:rotate(7.2deg);-o-transform:rotate(7.2deg);transform:rotate(7.2deg)}.att-loading-count[data-progress="2"] .att-loading-inset .att-loading-inset__percentage:before{content:"2"}.att-loading-count[data-progress="3"] .att-loading-circle__fill,.att-loading-count[data-progress="3"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(5.4deg);-moz-transform:rotate(5.4deg);-ms-transform:rotate(5.4deg);-o-transform:rotate(5.4deg);transform:rotate(5.4deg)}.att-loading-count[data-progress="3"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(10.8deg);-moz-transform:rotate(10.8deg);-ms-transform:rotate(10.8deg);-o-transform:rotate(10.8deg);transform:rotate(10.8deg)}.att-loading-count[data-progress="3"] .att-loading-inset .att-loading-inset__percentage:before{content:"3"}.att-loading-count[data-progress="4"] .att-loading-circle__fill,.att-loading-count[data-progress="4"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(7.2deg);-moz-transform:rotate(7.2deg);-ms-transform:rotate(7.2deg);-o-transform:rotate(7.2deg);transform:rotate(7.2deg)}.att-loading-count[data-progress="4"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(14.4deg);-moz-transform:rotate(14.4deg);-ms-transform:rotate(14.4deg);-o-transform:rotate(14.4deg);transform:rotate(14.4deg)}.att-loading-count[data-progress="4"] .att-loading-inset .att-loading-inset__percentage:before{content:"4"}.att-loading-count[data-progress="5"] .att-loading-circle__fill,.att-loading-count[data-progress="5"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(9deg);-moz-transform:rotate(9deg);-ms-transform:rotate(9deg);-o-transform:rotate(9deg);transform:rotate(9deg)}.att-loading-count[data-progress="5"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(18deg);-moz-transform:rotate(18deg);-ms-transform:rotate(18deg);-o-transform:rotate(18deg);transform:rotate(18deg)}.att-loading-count[data-progress="5"] .att-loading-inset .att-loading-inset__percentage:before{content:"5"}.att-loading-count[data-progress="6"] .att-loading-circle__fill,.att-loading-count[data-progress="6"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(10.8deg);-moz-transform:rotate(10.8deg);-ms-transform:rotate(10.8deg);-o-transform:rotate(10.8deg);transform:rotate(10.8deg)}.att-loading-count[data-progress="6"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(21.6deg);-moz-transform:rotate(21.6deg);-ms-transform:rotate(21.6deg);-o-transform:rotate(21.6deg);transform:rotate(21.6deg)}.att-loading-count[data-progress="6"] .att-loading-inset .att-loading-inset__percentage:before{content:"6"}.att-loading-count[data-progress="7"] .att-loading-circle__fill,.att-loading-count[data-progress="7"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(12.6deg);-moz-transform:rotate(12.6deg);-ms-transform:rotate(12.6deg);-o-transform:rotate(12.6deg);transform:rotate(12.6deg)}.att-loading-count[data-progress="7"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(25.2deg);-moz-transform:rotate(25.2deg);-ms-transform:rotate(25.2deg);-o-transform:rotate(25.2deg);transform:rotate(25.2deg)}.att-loading-count[data-progress="7"] .att-loading-inset .att-loading-inset__percentage:before{content:"7"}.att-loading-count[data-progress="8"] .att-loading-circle__fill,.att-loading-count[data-progress="8"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(14.4deg);-moz-transform:rotate(14.4deg);-ms-transform:rotate(14.4deg);-o-transform:rotate(14.4deg);transform:rotate(14.4deg)}.att-loading-count[data-progress="8"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(28.8deg);-moz-transform:rotate(28.8deg);-ms-transform:rotate(28.8deg);-o-transform:rotate(28.8deg);transform:rotate(28.8deg)}.att-loading-count[data-progress="8"] .att-loading-inset .att-loading-inset__percentage:before{content:"8"}.att-loading-count[data-progress="9"] .att-loading-circle__fill,.att-loading-count[data-progress="9"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(16.2deg);-moz-transform:rotate(16.2deg);-ms-transform:rotate(16.2deg);-o-transform:rotate(16.2deg);transform:rotate(16.2deg)}.att-loading-count[data-progress="9"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(32.4deg);-moz-transform:rotate(32.4deg);-ms-transform:rotate(32.4deg);-o-transform:rotate(32.4deg);transform:rotate(32.4deg)}.att-loading-count[data-progress="9"] .att-loading-inset .att-loading-inset__percentage:before{content:"9"}.att-loading-count[data-progress="10"] .att-loading-circle__fill,.att-loading-count[data-progress="10"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(18deg);-moz-transform:rotate(18deg);-ms-transform:rotate(18deg);-o-transform:rotate(18deg);transform:rotate(18deg)}.att-loading-count[data-progress="10"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(36deg);-moz-transform:rotate(36deg);-ms-transform:rotate(36deg);-o-transform:rotate(36deg);transform:rotate(36deg)}.att-loading-count[data-progress="10"] .att-loading-inset .att-loading-inset__percentage:before{content:"10"}.att-loading-count[data-progress="11"] .att-loading-circle__fill,.att-loading-count[data-progress="11"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(19.8deg);-moz-transform:rotate(19.8deg);-ms-transform:rotate(19.8deg);-o-transform:rotate(19.8deg);transform:rotate(19.8deg)}.att-loading-count[data-progress="11"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(39.6deg);-moz-transform:rotate(39.6deg);-ms-transform:rotate(39.6deg);-o-transform:rotate(39.6deg);transform:rotate(39.6deg)}.att-loading-count[data-progress="11"] .att-loading-inset .att-loading-inset__percentage:before{content:"11"}.att-loading-count[data-progress="12"] .att-loading-circle__fill,.att-loading-count[data-progress="12"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(21.6deg);-moz-transform:rotate(21.6deg);-ms-transform:rotate(21.6deg);-o-transform:rotate(21.6deg);transform:rotate(21.6deg)}.att-loading-count[data-progress="12"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(43.2deg);-moz-transform:rotate(43.2deg);-ms-transform:rotate(43.2deg);-o-transform:rotate(43.2deg);transform:rotate(43.2deg)}.att-loading-count[data-progress="12"] .att-loading-inset .att-loading-inset__percentage:before{content:"12"}.att-loading-count[data-progress="13"] .att-loading-circle__fill,.att-loading-count[data-progress="13"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(23.4deg);-moz-transform:rotate(23.4deg);-ms-transform:rotate(23.4deg);-o-transform:rotate(23.4deg);transform:rotate(23.4deg)}.att-loading-count[data-progress="13"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(46.8deg);-moz-transform:rotate(46.8deg);-ms-transform:rotate(46.8deg);-o-transform:rotate(46.8deg);transform:rotate(46.8deg)}.att-loading-count[data-progress="13"] .att-loading-inset .att-loading-inset__percentage:before{content:"13"}.att-loading-count[data-progress="14"] .att-loading-circle__fill,.att-loading-count[data-progress="14"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(25.2deg);-moz-transform:rotate(25.2deg);-ms-transform:rotate(25.2deg);-o-transform:rotate(25.2deg);transform:rotate(25.2deg)}.att-loading-count[data-progress="14"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(50.4deg);-moz-transform:rotate(50.4deg);-ms-transform:rotate(50.4deg);-o-transform:rotate(50.4deg);transform:rotate(50.4deg)}.att-loading-count[data-progress="14"] .att-loading-inset .att-loading-inset__percentage:before{content:"14"}.att-loading-count[data-progress="15"] .att-loading-circle__fill,.att-loading-count[data-progress="15"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(27deg);-moz-transform:rotate(27deg);-ms-transform:rotate(27deg);-o-transform:rotate(27deg);transform:rotate(27deg)}.att-loading-count[data-progress="15"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(54deg);-moz-transform:rotate(54deg);-ms-transform:rotate(54deg);-o-transform:rotate(54deg);transform:rotate(54deg)}.att-loading-count[data-progress="15"] .att-loading-inset .att-loading-inset__percentage:before{content:"15"}.att-loading-count[data-progress="16"] .att-loading-circle__fill,.att-loading-count[data-progress="16"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(28.8deg);-moz-transform:rotate(28.8deg);-ms-transform:rotate(28.8deg);-o-transform:rotate(28.8deg);transform:rotate(28.8deg)}.att-loading-count[data-progress="16"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(57.6deg);-moz-transform:rotate(57.6deg);-ms-transform:rotate(57.6deg);-o-transform:rotate(57.6deg);transform:rotate(57.6deg)}.att-loading-count[data-progress="16"] .att-loading-inset .att-loading-inset__percentage:before{content:"16"}.att-loading-count[data-progress="17"] .att-loading-circle__fill,.att-loading-count[data-progress="17"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(30.6deg);-moz-transform:rotate(30.6deg);-ms-transform:rotate(30.6deg);-o-transform:rotate(30.6deg);transform:rotate(30.6deg)}.att-loading-count[data-progress="17"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(61.2deg);-moz-transform:rotate(61.2deg);-ms-transform:rotate(61.2deg);-o-transform:rotate(61.2deg);transform:rotate(61.2deg)}.att-loading-count[data-progress="17"] .att-loading-inset .att-loading-inset__percentage:before{content:"17"}.att-loading-count[data-progress="18"] .att-loading-circle__fill,.att-loading-count[data-progress="18"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(32.4deg);-moz-transform:rotate(32.4deg);-ms-transform:rotate(32.4deg);-o-transform:rotate(32.4deg);transform:rotate(32.4deg)}.att-loading-count[data-progress="18"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(64.8deg);-moz-transform:rotate(64.8deg);-ms-transform:rotate(64.8deg);-o-transform:rotate(64.8deg);transform:rotate(64.8deg)}.att-loading-count[data-progress="18"] .att-loading-inset .att-loading-inset__percentage:before{content:"18"}.att-loading-count[data-progress="19"] .att-loading-circle__fill,.att-loading-count[data-progress="19"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(34.2deg);-moz-transform:rotate(34.2deg);-ms-transform:rotate(34.2deg);-o-transform:rotate(34.2deg);transform:rotate(34.2deg)}.att-loading-count[data-progress="19"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(68.4deg);-moz-transform:rotate(68.4deg);-ms-transform:rotate(68.4deg);-o-transform:rotate(68.4deg);transform:rotate(68.4deg)}.att-loading-count[data-progress="19"] .att-loading-inset .att-loading-inset__percentage:before{content:"19"}.att-loading-count[data-progress="20"] .att-loading-circle__fill,.att-loading-count[data-progress="20"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(36deg);-moz-transform:rotate(36deg);-ms-transform:rotate(36deg);-o-transform:rotate(36deg);transform:rotate(36deg)}.att-loading-count[data-progress="20"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(72deg);-moz-transform:rotate(72deg);-ms-transform:rotate(72deg);-o-transform:rotate(72deg);transform:rotate(72deg)}.att-loading-count[data-progress="20"] .att-loading-inset .att-loading-inset__percentage:before{content:"20"}.att-loading-count[data-progress="21"] .att-loading-circle__fill,.att-loading-count[data-progress="21"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(37.8deg);-moz-transform:rotate(37.8deg);-ms-transform:rotate(37.8deg);-o-transform:rotate(37.8deg);transform:rotate(37.8deg)}.att-loading-count[data-progress="21"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(75.6deg);-moz-transform:rotate(75.6deg);-ms-transform:rotate(75.6deg);-o-transform:rotate(75.6deg);transform:rotate(75.6deg)}.att-loading-count[data-progress="21"] .att-loading-inset .att-loading-inset__percentage:before{content:"21"}.att-loading-count[data-progress="22"] .att-loading-circle__fill,.att-loading-count[data-progress="22"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(39.6deg);-moz-transform:rotate(39.6deg);-ms-transform:rotate(39.6deg);-o-transform:rotate(39.6deg);transform:rotate(39.6deg)}.att-loading-count[data-progress="22"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(79.2deg);-moz-transform:rotate(79.2deg);-ms-transform:rotate(79.2deg);-o-transform:rotate(79.2deg);transform:rotate(79.2deg)}.att-loading-count[data-progress="22"] .att-loading-inset .att-loading-inset__percentage:before{content:"22"}.att-loading-count[data-progress="23"] .att-loading-circle__fill,.att-loading-count[data-progress="23"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(41.4deg);-moz-transform:rotate(41.4deg);-ms-transform:rotate(41.4deg);-o-transform:rotate(41.4deg);transform:rotate(41.4deg)}.att-loading-count[data-progress="23"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(82.8deg);-moz-transform:rotate(82.8deg);-ms-transform:rotate(82.8deg);-o-transform:rotate(82.8deg);transform:rotate(82.8deg)}.att-loading-count[data-progress="23"] .att-loading-inset .att-loading-inset__percentage:before{content:"23"}.att-loading-count[data-progress="24"] .att-loading-circle__fill,.att-loading-count[data-progress="24"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(43.2deg);-moz-transform:rotate(43.2deg);-ms-transform:rotate(43.2deg);-o-transform:rotate(43.2deg);transform:rotate(43.2deg)}.att-loading-count[data-progress="24"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(86.4deg);-moz-transform:rotate(86.4deg);-ms-transform:rotate(86.4deg);-o-transform:rotate(86.4deg);transform:rotate(86.4deg)}.att-loading-count[data-progress="24"] .att-loading-inset .att-loading-inset__percentage:before{content:"24"}.att-loading-count[data-progress="25"] .att-loading-circle__fill,.att-loading-count[data-progress="25"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.att-loading-count[data-progress="25"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.att-loading-count[data-progress="25"] .att-loading-inset .att-loading-inset__percentage:before{content:"25"}.att-loading-count[data-progress="26"] .att-loading-circle__fill,.att-loading-count[data-progress="26"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(46.8deg);-moz-transform:rotate(46.8deg);-ms-transform:rotate(46.8deg);-o-transform:rotate(46.8deg);transform:rotate(46.8deg)}.att-loading-count[data-progress="26"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(93.6deg);-moz-transform:rotate(93.6deg);-ms-transform:rotate(93.6deg);-o-transform:rotate(93.6deg);transform:rotate(93.6deg)}.att-loading-count[data-progress="26"] .att-loading-inset .att-loading-inset__percentage:before{content:"26"}.att-loading-count[data-progress="27"] .att-loading-circle__fill,.att-loading-count[data-progress="27"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(48.6deg);-moz-transform:rotate(48.6deg);-ms-transform:rotate(48.6deg);-o-transform:rotate(48.6deg);transform:rotate(48.6deg)}.att-loading-count[data-progress="27"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(97.2deg);-moz-transform:rotate(97.2deg);-ms-transform:rotate(97.2deg);-o-transform:rotate(97.2deg);transform:rotate(97.2deg)}.att-loading-count[data-progress="27"] .att-loading-inset .att-loading-inset__percentage:before{content:"27"}.att-loading-count[data-progress="28"] .att-loading-circle__fill,.att-loading-count[data-progress="28"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(50.4deg);-moz-transform:rotate(50.4deg);-ms-transform:rotate(50.4deg);-o-transform:rotate(50.4deg);transform:rotate(50.4deg)}.att-loading-count[data-progress="28"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(100.8deg);-moz-transform:rotate(100.8deg);-ms-transform:rotate(100.8deg);-o-transform:rotate(100.8deg);transform:rotate(100.8deg)}.att-loading-count[data-progress="28"] .att-loading-inset .att-loading-inset__percentage:before{content:"28"}.att-loading-count[data-progress="29"] .att-loading-circle__fill,.att-loading-count[data-progress="29"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(52.2deg);-moz-transform:rotate(52.2deg);-ms-transform:rotate(52.2deg);-o-transform:rotate(52.2deg);transform:rotate(52.2deg)}.att-loading-count[data-progress="29"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(104.4deg);-moz-transform:rotate(104.4deg);-ms-transform:rotate(104.4deg);-o-transform:rotate(104.4deg);transform:rotate(104.4deg)}.att-loading-count[data-progress="29"] .att-loading-inset .att-loading-inset__percentage:before{content:"29"}.att-loading-count[data-progress="30"] .att-loading-circle__fill,.att-loading-count[data-progress="30"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(54deg);-moz-transform:rotate(54deg);-ms-transform:rotate(54deg);-o-transform:rotate(54deg);transform:rotate(54deg)}.att-loading-count[data-progress="30"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(108deg);-moz-transform:rotate(108deg);-ms-transform:rotate(108deg);-o-transform:rotate(108deg);transform:rotate(108deg)}.att-loading-count[data-progress="30"] .att-loading-inset .att-loading-inset__percentage:before{content:"30"}.att-loading-count[data-progress="31"] .att-loading-circle__fill,.att-loading-count[data-progress="31"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(55.8deg);-moz-transform:rotate(55.8deg);-ms-transform:rotate(55.8deg);-o-transform:rotate(55.8deg);transform:rotate(55.8deg)}.att-loading-count[data-progress="31"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(111.6deg);-moz-transform:rotate(111.6deg);-ms-transform:rotate(111.6deg);-o-transform:rotate(111.6deg);transform:rotate(111.6deg)}.att-loading-count[data-progress="31"] .att-loading-inset .att-loading-inset__percentage:before{content:"31"}.att-loading-count[data-progress="32"] .att-loading-circle__fill,.att-loading-count[data-progress="32"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(57.6deg);-moz-transform:rotate(57.6deg);-ms-transform:rotate(57.6deg);-o-transform:rotate(57.6deg);transform:rotate(57.6deg)}.att-loading-count[data-progress="32"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(115.2deg);-moz-transform:rotate(115.2deg);-ms-transform:rotate(115.2deg);-o-transform:rotate(115.2deg);transform:rotate(115.2deg)}.att-loading-count[data-progress="32"] .att-loading-inset .att-loading-inset__percentage:before{content:"32"}.att-loading-count[data-progress="33"] .att-loading-circle__fill,.att-loading-count[data-progress="33"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(59.4deg);-moz-transform:rotate(59.4deg);-ms-transform:rotate(59.4deg);-o-transform:rotate(59.4deg);transform:rotate(59.4deg)}.att-loading-count[data-progress="33"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(118.8deg);-moz-transform:rotate(118.8deg);-ms-transform:rotate(118.8deg);-o-transform:rotate(118.8deg);transform:rotate(118.8deg)}.att-loading-count[data-progress="33"] .att-loading-inset .att-loading-inset__percentage:before{content:"33"}.att-loading-count[data-progress="34"] .att-loading-circle__fill,.att-loading-count[data-progress="34"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(61.2deg);-moz-transform:rotate(61.2deg);-ms-transform:rotate(61.2deg);-o-transform:rotate(61.2deg);transform:rotate(61.2deg)}.att-loading-count[data-progress="34"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(122.4deg);-moz-transform:rotate(122.4deg);-ms-transform:rotate(122.4deg);-o-transform:rotate(122.4deg);transform:rotate(122.4deg)}.att-loading-count[data-progress="34"] .att-loading-inset .att-loading-inset__percentage:before{content:"34"}.att-loading-count[data-progress="35"] .att-loading-circle__fill,.att-loading-count[data-progress="35"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(63deg);-moz-transform:rotate(63deg);-ms-transform:rotate(63deg);-o-transform:rotate(63deg);transform:rotate(63deg)}.att-loading-count[data-progress="35"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(126deg);-moz-transform:rotate(126deg);-ms-transform:rotate(126deg);-o-transform:rotate(126deg);transform:rotate(126deg)}.att-loading-count[data-progress="35"] .att-loading-inset .att-loading-inset__percentage:before{content:"35"}.att-loading-count[data-progress="36"] .att-loading-circle__fill,.att-loading-count[data-progress="36"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(64.8deg);-moz-transform:rotate(64.8deg);-ms-transform:rotate(64.8deg);-o-transform:rotate(64.8deg);transform:rotate(64.8deg)}.att-loading-count[data-progress="36"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(129.6deg);-moz-transform:rotate(129.6deg);-ms-transform:rotate(129.6deg);-o-transform:rotate(129.6deg);transform:rotate(129.6deg)}.att-loading-count[data-progress="36"] .att-loading-inset .att-loading-inset__percentage:before{content:"36"}.att-loading-count[data-progress="37"] .att-loading-circle__fill,.att-loading-count[data-progress="37"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(66.6deg);-moz-transform:rotate(66.6deg);-ms-transform:rotate(66.6deg);-o-transform:rotate(66.6deg);transform:rotate(66.6deg)}.att-loading-count[data-progress="37"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(133.2deg);-moz-transform:rotate(133.2deg);-ms-transform:rotate(133.2deg);-o-transform:rotate(133.2deg);transform:rotate(133.2deg)}.att-loading-count[data-progress="37"] .att-loading-inset .att-loading-inset__percentage:before{content:"37"}.att-loading-count[data-progress="38"] .att-loading-circle__fill,.att-loading-count[data-progress="38"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(68.4deg);-moz-transform:rotate(68.4deg);-ms-transform:rotate(68.4deg);-o-transform:rotate(68.4deg);transform:rotate(68.4deg)}.att-loading-count[data-progress="38"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(136.8deg);-moz-transform:rotate(136.8deg);-ms-transform:rotate(136.8deg);-o-transform:rotate(136.8deg);transform:rotate(136.8deg)}.att-loading-count[data-progress="38"] .att-loading-inset .att-loading-inset__percentage:before{content:"38"}.att-loading-count[data-progress="39"] .att-loading-circle__fill,.att-loading-count[data-progress="39"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(70.2deg);-moz-transform:rotate(70.2deg);-ms-transform:rotate(70.2deg);-o-transform:rotate(70.2deg);transform:rotate(70.2deg)}.att-loading-count[data-progress="39"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(140.4deg);-moz-transform:rotate(140.4deg);-ms-transform:rotate(140.4deg);-o-transform:rotate(140.4deg);transform:rotate(140.4deg)}.att-loading-count[data-progress="39"] .att-loading-inset .att-loading-inset__percentage:before{content:"39"}.att-loading-count[data-progress="40"] .att-loading-circle__fill,.att-loading-count[data-progress="40"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(72deg);-moz-transform:rotate(72deg);-ms-transform:rotate(72deg);-o-transform:rotate(72deg);transform:rotate(72deg)}.att-loading-count[data-progress="40"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(144deg);-moz-transform:rotate(144deg);-ms-transform:rotate(144deg);-o-transform:rotate(144deg);transform:rotate(144deg)}.att-loading-count[data-progress="40"] .att-loading-inset .att-loading-inset__percentage:before{content:"40"}.att-loading-count[data-progress="41"] .att-loading-circle__fill,.att-loading-count[data-progress="41"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(73.8deg);-moz-transform:rotate(73.8deg);-ms-transform:rotate(73.8deg);-o-transform:rotate(73.8deg);transform:rotate(73.8deg)}.att-loading-count[data-progress="41"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(147.6deg);-moz-transform:rotate(147.6deg);-ms-transform:rotate(147.6deg);-o-transform:rotate(147.6deg);transform:rotate(147.6deg)}.att-loading-count[data-progress="41"] .att-loading-inset .att-loading-inset__percentage:before{content:"41"}.att-loading-count[data-progress="42"] .att-loading-circle__fill,.att-loading-count[data-progress="42"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(75.6deg);-moz-transform:rotate(75.6deg);-ms-transform:rotate(75.6deg);-o-transform:rotate(75.6deg);transform:rotate(75.6deg)}.att-loading-count[data-progress="42"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(151.2deg);-moz-transform:rotate(151.2deg);-ms-transform:rotate(151.2deg);-o-transform:rotate(151.2deg);transform:rotate(151.2deg)}.att-loading-count[data-progress="42"] .att-loading-inset .att-loading-inset__percentage:before{content:"42"}.att-loading-count[data-progress="43"] .att-loading-circle__fill,.att-loading-count[data-progress="43"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(77.4deg);-moz-transform:rotate(77.4deg);-ms-transform:rotate(77.4deg);-o-transform:rotate(77.4deg);transform:rotate(77.4deg)}.att-loading-count[data-progress="43"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(154.8deg);-moz-transform:rotate(154.8deg);-ms-transform:rotate(154.8deg);-o-transform:rotate(154.8deg);transform:rotate(154.8deg)}.att-loading-count[data-progress="43"] .att-loading-inset .att-loading-inset__percentage:before{content:"43"}.att-loading-count[data-progress="44"] .att-loading-circle__fill,.att-loading-count[data-progress="44"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(79.2deg);-moz-transform:rotate(79.2deg);-ms-transform:rotate(79.2deg);-o-transform:rotate(79.2deg);transform:rotate(79.2deg)}.att-loading-count[data-progress="44"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(158.4deg);-moz-transform:rotate(158.4deg);-ms-transform:rotate(158.4deg);-o-transform:rotate(158.4deg);transform:rotate(158.4deg)}.att-loading-count[data-progress="44"] .att-loading-inset .att-loading-inset__percentage:before{content:"44"}.att-loading-count[data-progress="45"] .att-loading-circle__fill,.att-loading-count[data-progress="45"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(81deg);-moz-transform:rotate(81deg);-ms-transform:rotate(81deg);-o-transform:rotate(81deg);transform:rotate(81deg)}.att-loading-count[data-progress="45"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(162deg);-moz-transform:rotate(162deg);-ms-transform:rotate(162deg);-o-transform:rotate(162deg);transform:rotate(162deg)}.att-loading-count[data-progress="45"] .att-loading-inset .att-loading-inset__percentage:before{content:"45"}.att-loading-count[data-progress="46"] .att-loading-circle__fill,.att-loading-count[data-progress="46"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(82.8deg);-moz-transform:rotate(82.8deg);-ms-transform:rotate(82.8deg);-o-transform:rotate(82.8deg);transform:rotate(82.8deg)}.att-loading-count[data-progress="46"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(165.6deg);-moz-transform:rotate(165.6deg);-ms-transform:rotate(165.6deg);-o-transform:rotate(165.6deg);transform:rotate(165.6deg)}.att-loading-count[data-progress="46"] .att-loading-inset .att-loading-inset__percentage:before{content:"46"}.att-loading-count[data-progress="47"] .att-loading-circle__fill,.att-loading-count[data-progress="47"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(84.6deg);-moz-transform:rotate(84.6deg);-ms-transform:rotate(84.6deg);-o-transform:rotate(84.6deg);transform:rotate(84.6deg)}.att-loading-count[data-progress="47"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(169.2deg);-moz-transform:rotate(169.2deg);-ms-transform:rotate(169.2deg);-o-transform:rotate(169.2deg);transform:rotate(169.2deg)}.att-loading-count[data-progress="47"] .att-loading-inset .att-loading-inset__percentage:before{content:"47"}.att-loading-count[data-progress="48"] .att-loading-circle__fill,.att-loading-count[data-progress="48"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(86.4deg);-moz-transform:rotate(86.4deg);-ms-transform:rotate(86.4deg);-o-transform:rotate(86.4deg);transform:rotate(86.4deg)}.att-loading-count[data-progress="48"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(172.8deg);-moz-transform:rotate(172.8deg);-ms-transform:rotate(172.8deg);-o-transform:rotate(172.8deg);transform:rotate(172.8deg)}.att-loading-count[data-progress="48"] .att-loading-inset .att-loading-inset__percentage:before{content:"48"}.att-loading-count[data-progress="49"] .att-loading-circle__fill,.att-loading-count[data-progress="49"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(88.2deg);-moz-transform:rotate(88.2deg);-ms-transform:rotate(88.2deg);-o-transform:rotate(88.2deg);transform:rotate(88.2deg)}.att-loading-count[data-progress="49"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(176.4deg);-moz-transform:rotate(176.4deg);-ms-transform:rotate(176.4deg);-o-transform:rotate(176.4deg);transform:rotate(176.4deg)}.att-loading-count[data-progress="49"] .att-loading-inset .att-loading-inset__percentage:before{content:"49"}.att-loading-count[data-progress="50"] .att-loading-circle__fill,.att-loading-count[data-progress="50"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.att-loading-count[data-progress="50"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.att-loading-count[data-progress="50"] .att-loading-inset .att-loading-inset__percentage:before{content:"50"}.att-loading-count[data-progress="51"] .att-loading-circle__fill,.att-loading-count[data-progress="51"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(91.8deg);-moz-transform:rotate(91.8deg);-ms-transform:rotate(91.8deg);-o-transform:rotate(91.8deg);transform:rotate(91.8deg)}.att-loading-count[data-progress="51"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(183.6deg);-moz-transform:rotate(183.6deg);-ms-transform:rotate(183.6deg);-o-transform:rotate(183.6deg);transform:rotate(183.6deg)}.att-loading-count[data-progress="51"] .att-loading-inset .att-loading-inset__percentage:before{content:"51"}.att-loading-count[data-progress="52"] .att-loading-circle__fill,.att-loading-count[data-progress="52"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(93.6deg);-moz-transform:rotate(93.6deg);-ms-transform:rotate(93.6deg);-o-transform:rotate(93.6deg);transform:rotate(93.6deg)}.att-loading-count[data-progress="52"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(187.2deg);-moz-transform:rotate(187.2deg);-ms-transform:rotate(187.2deg);-o-transform:rotate(187.2deg);transform:rotate(187.2deg)}.att-loading-count[data-progress="52"] .att-loading-inset .att-loading-inset__percentage:before{content:"52"}.att-loading-count[data-progress="53"] .att-loading-circle__fill,.att-loading-count[data-progress="53"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(95.4deg);-moz-transform:rotate(95.4deg);-ms-transform:rotate(95.4deg);-o-transform:rotate(95.4deg);transform:rotate(95.4deg)}.att-loading-count[data-progress="53"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(190.8deg);-moz-transform:rotate(190.8deg);-ms-transform:rotate(190.8deg);-o-transform:rotate(190.8deg);transform:rotate(190.8deg)}.att-loading-count[data-progress="53"] .att-loading-inset .att-loading-inset__percentage:before{content:"53"}.att-loading-count[data-progress="54"] .att-loading-circle__fill,.att-loading-count[data-progress="54"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(97.2deg);-moz-transform:rotate(97.2deg);-ms-transform:rotate(97.2deg);-o-transform:rotate(97.2deg);transform:rotate(97.2deg)}.att-loading-count[data-progress="54"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(194.4deg);-moz-transform:rotate(194.4deg);-ms-transform:rotate(194.4deg);-o-transform:rotate(194.4deg);transform:rotate(194.4deg)}.att-loading-count[data-progress="54"] .att-loading-inset .att-loading-inset__percentage:before{content:"54"}.att-loading-count[data-progress="55"] .att-loading-circle__fill,.att-loading-count[data-progress="55"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(99deg);-moz-transform:rotate(99deg);-ms-transform:rotate(99deg);-o-transform:rotate(99deg);transform:rotate(99deg)}.att-loading-count[data-progress="55"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(198deg);-moz-transform:rotate(198deg);-ms-transform:rotate(198deg);-o-transform:rotate(198deg);transform:rotate(198deg)}.att-loading-count[data-progress="55"] .att-loading-inset .att-loading-inset__percentage:before{content:"55"}.att-loading-count[data-progress="56"] .att-loading-circle__fill,.att-loading-count[data-progress="56"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(100.8deg);-moz-transform:rotate(100.8deg);-ms-transform:rotate(100.8deg);-o-transform:rotate(100.8deg);transform:rotate(100.8deg)}.att-loading-count[data-progress="56"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(201.6deg);-moz-transform:rotate(201.6deg);-ms-transform:rotate(201.6deg);-o-transform:rotate(201.6deg);transform:rotate(201.6deg)}.att-loading-count[data-progress="56"] .att-loading-inset .att-loading-inset__percentage:before{content:"56"}.att-loading-count[data-progress="57"] .att-loading-circle__fill,.att-loading-count[data-progress="57"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(102.6deg);-moz-transform:rotate(102.6deg);-ms-transform:rotate(102.6deg);-o-transform:rotate(102.6deg);transform:rotate(102.6deg)}.att-loading-count[data-progress="57"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(205.2deg);-moz-transform:rotate(205.2deg);-ms-transform:rotate(205.2deg);-o-transform:rotate(205.2deg);transform:rotate(205.2deg)}.att-loading-count[data-progress="57"] .att-loading-inset .att-loading-inset__percentage:before{content:"57"}.att-loading-count[data-progress="58"] .att-loading-circle__fill,.att-loading-count[data-progress="58"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(104.4deg);-moz-transform:rotate(104.4deg);-ms-transform:rotate(104.4deg);-o-transform:rotate(104.4deg);transform:rotate(104.4deg)}.att-loading-count[data-progress="58"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(208.8deg);-moz-transform:rotate(208.8deg);-ms-transform:rotate(208.8deg);-o-transform:rotate(208.8deg);transform:rotate(208.8deg)}.att-loading-count[data-progress="58"] .att-loading-inset .att-loading-inset__percentage:before{content:"58"}.att-loading-count[data-progress="59"] .att-loading-circle__fill,.att-loading-count[data-progress="59"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(106.2deg);-moz-transform:rotate(106.2deg);-ms-transform:rotate(106.2deg);-o-transform:rotate(106.2deg);transform:rotate(106.2deg)}.att-loading-count[data-progress="59"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(212.4deg);-moz-transform:rotate(212.4deg);-ms-transform:rotate(212.4deg);-o-transform:rotate(212.4deg);transform:rotate(212.4deg)}.att-loading-count[data-progress="59"] .att-loading-inset .att-loading-inset__percentage:before{content:"59"}.att-loading-count[data-progress="60"] .att-loading-circle__fill,.att-loading-count[data-progress="60"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(108deg);-moz-transform:rotate(108deg);-ms-transform:rotate(108deg);-o-transform:rotate(108deg);transform:rotate(108deg)}.att-loading-count[data-progress="60"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(216deg);-moz-transform:rotate(216deg);-ms-transform:rotate(216deg);-o-transform:rotate(216deg);transform:rotate(216deg)}.att-loading-count[data-progress="60"] .att-loading-inset .att-loading-inset__percentage:before{content:"60"}.att-loading-count[data-progress="61"] .att-loading-circle__fill,.att-loading-count[data-progress="61"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(109.8deg);-moz-transform:rotate(109.8deg);-ms-transform:rotate(109.8deg);-o-transform:rotate(109.8deg);transform:rotate(109.8deg)}.att-loading-count[data-progress="61"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(219.6deg);-moz-transform:rotate(219.6deg);-ms-transform:rotate(219.6deg);-o-transform:rotate(219.6deg);transform:rotate(219.6deg)}.att-loading-count[data-progress="61"] .att-loading-inset .att-loading-inset__percentage:before{content:"61"}.att-loading-count[data-progress="62"] .att-loading-circle__fill,.att-loading-count[data-progress="62"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(111.6deg);-moz-transform:rotate(111.6deg);-ms-transform:rotate(111.6deg);-o-transform:rotate(111.6deg);transform:rotate(111.6deg)}.att-loading-count[data-progress="62"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(223.2deg);-moz-transform:rotate(223.2deg);-ms-transform:rotate(223.2deg);-o-transform:rotate(223.2deg);transform:rotate(223.2deg)}.att-loading-count[data-progress="62"] .att-loading-inset .att-loading-inset__percentage:before{content:"62"}.att-loading-count[data-progress="63"] .att-loading-circle__fill,.att-loading-count[data-progress="63"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(113.4deg);-moz-transform:rotate(113.4deg);-ms-transform:rotate(113.4deg);-o-transform:rotate(113.4deg);transform:rotate(113.4deg)}.att-loading-count[data-progress="63"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(226.8deg);-moz-transform:rotate(226.8deg);-ms-transform:rotate(226.8deg);-o-transform:rotate(226.8deg);transform:rotate(226.8deg)}.att-loading-count[data-progress="63"] .att-loading-inset .att-loading-inset__percentage:before{content:"63"}.att-loading-count[data-progress="64"] .att-loading-circle__fill,.att-loading-count[data-progress="64"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(115.2deg);-moz-transform:rotate(115.2deg);-ms-transform:rotate(115.2deg);-o-transform:rotate(115.2deg);transform:rotate(115.2deg)}.att-loading-count[data-progress="64"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(230.4deg);-moz-transform:rotate(230.4deg);-ms-transform:rotate(230.4deg);-o-transform:rotate(230.4deg);transform:rotate(230.4deg)}.att-loading-count[data-progress="64"] .att-loading-inset .att-loading-inset__percentage:before{content:"64"}.att-loading-count[data-progress="65"] .att-loading-circle__fill,.att-loading-count[data-progress="65"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(117deg);-moz-transform:rotate(117deg);-ms-transform:rotate(117deg);-o-transform:rotate(117deg);transform:rotate(117deg)}.att-loading-count[data-progress="65"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(234deg);-moz-transform:rotate(234deg);-ms-transform:rotate(234deg);-o-transform:rotate(234deg);transform:rotate(234deg)}.att-loading-count[data-progress="65"] .att-loading-inset .att-loading-inset__percentage:before{content:"65"}.att-loading-count[data-progress="66"] .att-loading-circle__fill,.att-loading-count[data-progress="66"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(118.8deg);-moz-transform:rotate(118.8deg);-ms-transform:rotate(118.8deg);-o-transform:rotate(118.8deg);transform:rotate(118.8deg)}.att-loading-count[data-progress="66"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(237.6deg);-moz-transform:rotate(237.6deg);-ms-transform:rotate(237.6deg);-o-transform:rotate(237.6deg);transform:rotate(237.6deg)}.att-loading-count[data-progress="66"] .att-loading-inset .att-loading-inset__percentage:before{content:"66"}.att-loading-count[data-progress="67"] .att-loading-circle__fill,.att-loading-count[data-progress="67"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(120.6deg);-moz-transform:rotate(120.6deg);-ms-transform:rotate(120.6deg);-o-transform:rotate(120.6deg);transform:rotate(120.6deg)}.att-loading-count[data-progress="67"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(241.2deg);-moz-transform:rotate(241.2deg);-ms-transform:rotate(241.2deg);-o-transform:rotate(241.2deg);transform:rotate(241.2deg)}.att-loading-count[data-progress="67"] .att-loading-inset .att-loading-inset__percentage:before{content:"67"}.att-loading-count[data-progress="68"] .att-loading-circle__fill,.att-loading-count[data-progress="68"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(122.4deg);-moz-transform:rotate(122.4deg);-ms-transform:rotate(122.4deg);-o-transform:rotate(122.4deg);transform:rotate(122.4deg)}.att-loading-count[data-progress="68"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(244.8deg);-moz-transform:rotate(244.8deg);-ms-transform:rotate(244.8deg);-o-transform:rotate(244.8deg);transform:rotate(244.8deg)}.att-loading-count[data-progress="68"] .att-loading-inset .att-loading-inset__percentage:before{content:"68"}.att-loading-count[data-progress="69"] .att-loading-circle__fill,.att-loading-count[data-progress="69"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(124.2deg);-moz-transform:rotate(124.2deg);-ms-transform:rotate(124.2deg);-o-transform:rotate(124.2deg);transform:rotate(124.2deg)}.att-loading-count[data-progress="69"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(248.4deg);-moz-transform:rotate(248.4deg);-ms-transform:rotate(248.4deg);-o-transform:rotate(248.4deg);transform:rotate(248.4deg)}.att-loading-count[data-progress="69"] .att-loading-inset .att-loading-inset__percentage:before{content:"69"}.att-loading-count[data-progress="70"] .att-loading-circle__fill,.att-loading-count[data-progress="70"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(126deg);-moz-transform:rotate(126deg);-ms-transform:rotate(126deg);-o-transform:rotate(126deg);transform:rotate(126deg)}.att-loading-count[data-progress="70"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(252deg);-moz-transform:rotate(252deg);-ms-transform:rotate(252deg);-o-transform:rotate(252deg);transform:rotate(252deg)}.att-loading-count[data-progress="70"] .att-loading-inset .att-loading-inset__percentage:before{content:"70"}.att-loading-count[data-progress="71"] .att-loading-circle__fill,.att-loading-count[data-progress="71"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(127.8deg);-moz-transform:rotate(127.8deg);-ms-transform:rotate(127.8deg);-o-transform:rotate(127.8deg);transform:rotate(127.8deg)}.att-loading-count[data-progress="71"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(255.6deg);-moz-transform:rotate(255.6deg);-ms-transform:rotate(255.6deg);-o-transform:rotate(255.6deg);transform:rotate(255.6deg)}.att-loading-count[data-progress="71"] .att-loading-inset .att-loading-inset__percentage:before{content:"71"}.att-loading-count[data-progress="72"] .att-loading-circle__fill,.att-loading-count[data-progress="72"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(129.6deg);-moz-transform:rotate(129.6deg);-ms-transform:rotate(129.6deg);-o-transform:rotate(129.6deg);transform:rotate(129.6deg)}.att-loading-count[data-progress="72"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(259.2deg);-moz-transform:rotate(259.2deg);-ms-transform:rotate(259.2deg);-o-transform:rotate(259.2deg);transform:rotate(259.2deg)}.att-loading-count[data-progress="72"] .att-loading-inset .att-loading-inset__percentage:before{content:"72"}.att-loading-count[data-progress="73"] .att-loading-circle__fill,.att-loading-count[data-progress="73"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(131.4deg);-moz-transform:rotate(131.4deg);-ms-transform:rotate(131.4deg);-o-transform:rotate(131.4deg);transform:rotate(131.4deg)}.att-loading-count[data-progress="73"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(262.8deg);-moz-transform:rotate(262.8deg);-ms-transform:rotate(262.8deg);-o-transform:rotate(262.8deg);transform:rotate(262.8deg)}.att-loading-count[data-progress="73"] .att-loading-inset .att-loading-inset__percentage:before{content:"73"}.att-loading-count[data-progress="74"] .att-loading-circle__fill,.att-loading-count[data-progress="74"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(133.2deg);-moz-transform:rotate(133.2deg);-ms-transform:rotate(133.2deg);-o-transform:rotate(133.2deg);transform:rotate(133.2deg)}.att-loading-count[data-progress="74"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(266.4deg);-moz-transform:rotate(266.4deg);-ms-transform:rotate(266.4deg);-o-transform:rotate(266.4deg);transform:rotate(266.4deg)}.att-loading-count[data-progress="74"] .att-loading-inset .att-loading-inset__percentage:before{content:"74"}.att-loading-count[data-progress="75"] .att-loading-circle__fill,.att-loading-count[data-progress="75"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);-o-transform:rotate(135deg);transform:rotate(135deg)}.att-loading-count[data-progress="75"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.att-loading-count[data-progress="75"] .att-loading-inset .att-loading-inset__percentage:before{content:"75"}.att-loading-count[data-progress="76"] .att-loading-circle__fill,.att-loading-count[data-progress="76"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(136.8deg);-moz-transform:rotate(136.8deg);-ms-transform:rotate(136.8deg);-o-transform:rotate(136.8deg);transform:rotate(136.8deg)}.att-loading-count[data-progress="76"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(273.6deg);-moz-transform:rotate(273.6deg);-ms-transform:rotate(273.6deg);-o-transform:rotate(273.6deg);transform:rotate(273.6deg)}.att-loading-count[data-progress="76"] .att-loading-inset .att-loading-inset__percentage:before{content:"76"}.att-loading-count[data-progress="77"] .att-loading-circle__fill,.att-loading-count[data-progress="77"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(138.6deg);-moz-transform:rotate(138.6deg);-ms-transform:rotate(138.6deg);-o-transform:rotate(138.6deg);transform:rotate(138.6deg)}.att-loading-count[data-progress="77"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(277.2deg);-moz-transform:rotate(277.2deg);-ms-transform:rotate(277.2deg);-o-transform:rotate(277.2deg);transform:rotate(277.2deg)}.att-loading-count[data-progress="77"] .att-loading-inset .att-loading-inset__percentage:before{content:"77"}.att-loading-count[data-progress="78"] .att-loading-circle__fill,.att-loading-count[data-progress="78"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(140.4deg);-moz-transform:rotate(140.4deg);-ms-transform:rotate(140.4deg);-o-transform:rotate(140.4deg);transform:rotate(140.4deg)}.att-loading-count[data-progress="78"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(280.8deg);-moz-transform:rotate(280.8deg);-ms-transform:rotate(280.8deg);-o-transform:rotate(280.8deg);transform:rotate(280.8deg)}.att-loading-count[data-progress="78"] .att-loading-inset .att-loading-inset__percentage:before{content:"78"}.att-loading-count[data-progress="79"] .att-loading-circle__fill,.att-loading-count[data-progress="79"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(142.2deg);-moz-transform:rotate(142.2deg);-ms-transform:rotate(142.2deg);-o-transform:rotate(142.2deg);transform:rotate(142.2deg)}.att-loading-count[data-progress="79"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(284.4deg);-moz-transform:rotate(284.4deg);-ms-transform:rotate(284.4deg);-o-transform:rotate(284.4deg);transform:rotate(284.4deg)}.att-loading-count[data-progress="79"] .att-loading-inset .att-loading-inset__percentage:before{content:"79"}.att-loading-count[data-progress="80"] .att-loading-circle__fill,.att-loading-count[data-progress="80"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(144deg);-moz-transform:rotate(144deg);-ms-transform:rotate(144deg);-o-transform:rotate(144deg);transform:rotate(144deg)}.att-loading-count[data-progress="80"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(288deg);-moz-transform:rotate(288deg);-ms-transform:rotate(288deg);-o-transform:rotate(288deg);transform:rotate(288deg)}.att-loading-count[data-progress="80"] .att-loading-inset .att-loading-inset__percentage:before{content:"80"}.att-loading-count[data-progress="81"] .att-loading-circle__fill,.att-loading-count[data-progress="81"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(145.8deg);-moz-transform:rotate(145.8deg);-ms-transform:rotate(145.8deg);-o-transform:rotate(145.8deg);transform:rotate(145.8deg)}.att-loading-count[data-progress="81"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(291.6deg);-moz-transform:rotate(291.6deg);-ms-transform:rotate(291.6deg);-o-transform:rotate(291.6deg);transform:rotate(291.6deg)}.att-loading-count[data-progress="81"] .att-loading-inset .att-loading-inset__percentage:before{content:"81"}.att-loading-count[data-progress="82"] .att-loading-circle__fill,.att-loading-count[data-progress="82"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(147.6deg);-moz-transform:rotate(147.6deg);-ms-transform:rotate(147.6deg);-o-transform:rotate(147.6deg);transform:rotate(147.6deg)}.att-loading-count[data-progress="82"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(295.2deg);-moz-transform:rotate(295.2deg);-ms-transform:rotate(295.2deg);-o-transform:rotate(295.2deg);transform:rotate(295.2deg)}.att-loading-count[data-progress="82"] .att-loading-inset .att-loading-inset__percentage:before{content:"82"}.att-loading-count[data-progress="83"] .att-loading-circle__fill,.att-loading-count[data-progress="83"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(149.4deg);-moz-transform:rotate(149.4deg);-ms-transform:rotate(149.4deg);-o-transform:rotate(149.4deg);transform:rotate(149.4deg)}.att-loading-count[data-progress="83"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(298.8deg);-moz-transform:rotate(298.8deg);-ms-transform:rotate(298.8deg);-o-transform:rotate(298.8deg);transform:rotate(298.8deg)}.att-loading-count[data-progress="83"] .att-loading-inset .att-loading-inset__percentage:before{content:"83"}.att-loading-count[data-progress="84"] .att-loading-circle__fill,.att-loading-count[data-progress="84"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(151.2deg);-moz-transform:rotate(151.2deg);-ms-transform:rotate(151.2deg);-o-transform:rotate(151.2deg);transform:rotate(151.2deg)}.att-loading-count[data-progress="84"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(302.4deg);-moz-transform:rotate(302.4deg);-ms-transform:rotate(302.4deg);-o-transform:rotate(302.4deg);transform:rotate(302.4deg)}.att-loading-count[data-progress="84"] .att-loading-inset .att-loading-inset__percentage:before{content:"84"}.att-loading-count[data-progress="85"] .att-loading-circle__fill,.att-loading-count[data-progress="85"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(153deg);-moz-transform:rotate(153deg);-ms-transform:rotate(153deg);-o-transform:rotate(153deg);transform:rotate(153deg)}.att-loading-count[data-progress="85"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(306deg);-moz-transform:rotate(306deg);-ms-transform:rotate(306deg);-o-transform:rotate(306deg);transform:rotate(306deg)}.att-loading-count[data-progress="85"] .att-loading-inset .att-loading-inset__percentage:before{content:"85"}.att-loading-count[data-progress="86"] .att-loading-circle__fill,.att-loading-count[data-progress="86"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(154.8deg);-moz-transform:rotate(154.8deg);-ms-transform:rotate(154.8deg);-o-transform:rotate(154.8deg);transform:rotate(154.8deg)}.att-loading-count[data-progress="86"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(309.6deg);-moz-transform:rotate(309.6deg);-ms-transform:rotate(309.6deg);-o-transform:rotate(309.6deg);transform:rotate(309.6deg)}.att-loading-count[data-progress="86"] .att-loading-inset .att-loading-inset__percentage:before{content:"86"}.att-loading-count[data-progress="87"] .att-loading-circle__fill,.att-loading-count[data-progress="87"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(156.6deg);-moz-transform:rotate(156.6deg);-ms-transform:rotate(156.6deg);-o-transform:rotate(156.6deg);transform:rotate(156.6deg)}.att-loading-count[data-progress="87"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(313.2deg);-moz-transform:rotate(313.2deg);-ms-transform:rotate(313.2deg);-o-transform:rotate(313.2deg);transform:rotate(313.2deg)}.att-loading-count[data-progress="87"] .att-loading-inset .att-loading-inset__percentage:before{content:"87"}.att-loading-count[data-progress="88"] .att-loading-circle__fill,.att-loading-count[data-progress="88"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(158.4deg);-moz-transform:rotate(158.4deg);-ms-transform:rotate(158.4deg);-o-transform:rotate(158.4deg);transform:rotate(158.4deg)}.att-loading-count[data-progress="88"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(316.8deg);-moz-transform:rotate(316.8deg);-ms-transform:rotate(316.8deg);-o-transform:rotate(316.8deg);transform:rotate(316.8deg)}.att-loading-count[data-progress="88"] .att-loading-inset .att-loading-inset__percentage:before{content:"88"}.att-loading-count[data-progress="89"] .att-loading-circle__fill,.att-loading-count[data-progress="89"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(160.2deg);-moz-transform:rotate(160.2deg);-ms-transform:rotate(160.2deg);-o-transform:rotate(160.2deg);transform:rotate(160.2deg)}.att-loading-count[data-progress="89"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(320.4deg);-moz-transform:rotate(320.4deg);-ms-transform:rotate(320.4deg);-o-transform:rotate(320.4deg);transform:rotate(320.4deg)}.att-loading-count[data-progress="89"] .att-loading-inset .att-loading-inset__percentage:before{content:"89"}.att-loading-count[data-progress="90"] .att-loading-circle__fill,.att-loading-count[data-progress="90"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(162deg);-moz-transform:rotate(162deg);-ms-transform:rotate(162deg);-o-transform:rotate(162deg);transform:rotate(162deg)}.att-loading-count[data-progress="90"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(324deg);-moz-transform:rotate(324deg);-ms-transform:rotate(324deg);-o-transform:rotate(324deg);transform:rotate(324deg)}.att-loading-count[data-progress="90"] .att-loading-inset .att-loading-inset__percentage:before{content:"90"}.att-loading-count[data-progress="91"] .att-loading-circle__fill,.att-loading-count[data-progress="91"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(163.8deg);-moz-transform:rotate(163.8deg);-ms-transform:rotate(163.8deg);-o-transform:rotate(163.8deg);transform:rotate(163.8deg)}.att-loading-count[data-progress="91"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(327.6deg);-moz-transform:rotate(327.6deg);-ms-transform:rotate(327.6deg);-o-transform:rotate(327.6deg);transform:rotate(327.6deg)}.att-loading-count[data-progress="91"] .att-loading-inset .att-loading-inset__percentage:before{content:"91"}.att-loading-count[data-progress="92"] .att-loading-circle__fill,.att-loading-count[data-progress="92"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(165.6deg);-moz-transform:rotate(165.6deg);-ms-transform:rotate(165.6deg);-o-transform:rotate(165.6deg);transform:rotate(165.6deg)}.att-loading-count[data-progress="92"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(331.2deg);-moz-transform:rotate(331.2deg);-ms-transform:rotate(331.2deg);-o-transform:rotate(331.2deg);transform:rotate(331.2deg)}.att-loading-count[data-progress="92"] .att-loading-inset .att-loading-inset__percentage:before{content:"92"}.att-loading-count[data-progress="93"] .att-loading-circle__fill,.att-loading-count[data-progress="93"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(167.4deg);-moz-transform:rotate(167.4deg);-ms-transform:rotate(167.4deg);-o-transform:rotate(167.4deg);transform:rotate(167.4deg)}.att-loading-count[data-progress="93"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(334.8deg);-moz-transform:rotate(334.8deg);-ms-transform:rotate(334.8deg);-o-transform:rotate(334.8deg);transform:rotate(334.8deg)}.att-loading-count[data-progress="93"] .att-loading-inset .att-loading-inset__percentage:before{content:"93"}.att-loading-count[data-progress="94"] .att-loading-circle__fill,.att-loading-count[data-progress="94"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(169.2deg);-moz-transform:rotate(169.2deg);-ms-transform:rotate(169.2deg);-o-transform:rotate(169.2deg);transform:rotate(169.2deg)}.att-loading-count[data-progress="94"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(338.4deg);-moz-transform:rotate(338.4deg);-ms-transform:rotate(338.4deg);-o-transform:rotate(338.4deg);transform:rotate(338.4deg)}.att-loading-count[data-progress="94"] .att-loading-inset .att-loading-inset__percentage:before{content:"94"}.att-loading-count[data-progress="95"] .att-loading-circle__fill,.att-loading-count[data-progress="95"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(171deg);-moz-transform:rotate(171deg);-ms-transform:rotate(171deg);-o-transform:rotate(171deg);transform:rotate(171deg)}.att-loading-count[data-progress="95"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(342deg);-moz-transform:rotate(342deg);-ms-transform:rotate(342deg);-o-transform:rotate(342deg);transform:rotate(342deg)}.att-loading-count[data-progress="95"] .att-loading-inset .att-loading-inset__percentage:before{content:"95"}.att-loading-count[data-progress="96"] .att-loading-circle__fill,.att-loading-count[data-progress="96"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(172.8deg);-moz-transform:rotate(172.8deg);-ms-transform:rotate(172.8deg);-o-transform:rotate(172.8deg);transform:rotate(172.8deg)}.att-loading-count[data-progress="96"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(345.6deg);-moz-transform:rotate(345.6deg);-ms-transform:rotate(345.6deg);-o-transform:rotate(345.6deg);transform:rotate(345.6deg)}.att-loading-count[data-progress="96"] .att-loading-inset .att-loading-inset__percentage:before{content:"96"}.att-loading-count[data-progress="97"] .att-loading-circle__fill,.att-loading-count[data-progress="97"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(174.6deg);-moz-transform:rotate(174.6deg);-ms-transform:rotate(174.6deg);-o-transform:rotate(174.6deg);transform:rotate(174.6deg)}.att-loading-count[data-progress="97"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(349.2deg);-moz-transform:rotate(349.2deg);-ms-transform:rotate(349.2deg);-o-transform:rotate(349.2deg);transform:rotate(349.2deg)}.att-loading-count[data-progress="97"] .att-loading-inset .att-loading-inset__percentage:before{content:"97"}.att-loading-count[data-progress="98"] .att-loading-circle__fill,.att-loading-count[data-progress="98"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(176.4deg);-moz-transform:rotate(176.4deg);-ms-transform:rotate(176.4deg);-o-transform:rotate(176.4deg);transform:rotate(176.4deg)}.att-loading-count[data-progress="98"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(352.8deg);-moz-transform:rotate(352.8deg);-ms-transform:rotate(352.8deg);-o-transform:rotate(352.8deg);transform:rotate(352.8deg)}.att-loading-count[data-progress="98"] .att-loading-inset .att-loading-inset__percentage:before{content:"98"}.att-loading-count[data-progress="99"] .att-loading-circle__fill,.att-loading-count[data-progress="99"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(178.2deg);-moz-transform:rotate(178.2deg);-ms-transform:rotate(178.2deg);-o-transform:rotate(178.2deg);transform:rotate(178.2deg)}.att-loading-count[data-progress="99"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(356.4deg);-moz-transform:rotate(356.4deg);-ms-transform:rotate(356.4deg);-o-transform:rotate(356.4deg);transform:rotate(356.4deg)}.att-loading-count[data-progress="99"] .att-loading-inset .att-loading-inset__percentage:before{content:"99"}.att-loading-count[data-progress="100"] .att-loading-circle__fill,.att-loading-count[data-progress="100"] .att-loading-circle__mask.att-loading-circle__full{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.att-loading-count[data-progress="100"] .att-loading-circle__fill.att-loading-circle__fix{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-ms-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}.att-loading-count[data-progress="100"] .att-loading-inset .att-loading-inset__percentage:before{content:"100"}@keyframes loadingCounter{0% .att-loading-inset .att-loading-inset__percentage:before{content:"0"}1% .att-loading-inset .att-loading-inset__percentage:before{content:"1"}2% .att-loading-inset .att-loading-inset__percentage:before{content:"2"}3% .att-loading-inset .att-loading-inset__percentage:before{content:"3"}4% .att-loading-inset .att-loading-inset__percentage:before{content:"4"}5% .att-loading-inset .att-loading-inset__percentage:before{content:"5"}6% .att-loading-inset .att-loading-inset__percentage:before{content:"6"}7% .att-loading-inset .att-loading-inset__percentage:before{content:"7"}8% .att-loading-inset .att-loading-inset__percentage:before{content:"8"}9% .att-loading-inset .att-loading-inset__percentage:before{content:"9"}10% .att-loading-inset .att-loading-inset__percentage:before{content:"10"}11% .att-loading-inset .att-loading-inset__percentage:before{content:"11"}12% .att-loading-inset .att-loading-inset__percentage:before{content:"12"}13% .att-loading-inset .att-loading-inset__percentage:before{content:"13"}14% .att-loading-inset .att-loading-inset__percentage:before{content:"14"}15% .att-loading-inset .att-loading-inset__percentage:before{content:"15"}16% .att-loading-inset .att-loading-inset__percentage:before{content:"16"}17% .att-loading-inset .att-loading-inset__percentage:before{content:"17"}18% .att-loading-inset .att-loading-inset__percentage:before{content:"18"}19% .att-loading-inset .att-loading-inset__percentage:before{content:"19"}20% .att-loading-inset .att-loading-inset__percentage:before{content:"20"}21% .att-loading-inset .att-loading-inset__percentage:before{content:"21"}22% .att-loading-inset .att-loading-inset__percentage:before{content:"22"}23% .att-loading-inset .att-loading-inset__percentage:before{content:"23"}24% .att-loading-inset .att-loading-inset__percentage:before{content:"24"}25% .att-loading-inset .att-loading-inset__percentage:before{content:"25"}26% .att-loading-inset .att-loading-inset__percentage:before{content:"26"}27% .att-loading-inset .att-loading-inset__percentage:before{content:"27"}28% .att-loading-inset .att-loading-inset__percentage:before{content:"28"}29% .att-loading-inset .att-loading-inset__percentage:before{content:"29"}30% .att-loading-inset .att-loading-inset__percentage:before{content:"30"}31% .att-loading-inset .att-loading-inset__percentage:before{content:"31"}32% .att-loading-inset .att-loading-inset__percentage:before{content:"32"}33% .att-loading-inset .att-loading-inset__percentage:before{content:"33"}34% .att-loading-inset .att-loading-inset__percentage:before{content:"34"}35% .att-loading-inset .att-loading-inset__percentage:before{content:"35"}36% .att-loading-inset .att-loading-inset__percentage:before{content:"36"}37% .att-loading-inset .att-loading-inset__percentage:before{content:"37"}38% .att-loading-inset .att-loading-inset__percentage:before{content:"38"}39% .att-loading-inset .att-loading-inset__percentage:before{content:"39"}40% .att-loading-inset .att-loading-inset__percentage:before{content:"40"}41% .att-loading-inset .att-loading-inset__percentage:before{content:"41"}42% .att-loading-inset .att-loading-inset__percentage:before{content:"42"}43% .att-loading-inset .att-loading-inset__percentage:before{content:"43"}44% .att-loading-inset .att-loading-inset__percentage:before{content:"44"}45% .att-loading-inset .att-loading-inset__percentage:before{content:"45"}46% .att-loading-inset .att-loading-inset__percentage:before{content:"46"}47% .att-loading-inset .att-loading-inset__percentage:before{content:"47"}48% .att-loading-inset .att-loading-inset__percentage:before{content:"48"}49% .att-loading-inset .att-loading-inset__percentage:before{content:"49"}50% .att-loading-inset .att-loading-inset__percentage:before{content:"50"}51% .att-loading-inset .att-loading-inset__percentage:before{content:"51"}52% .att-loading-inset .att-loading-inset__percentage:before{content:"52"}53% .att-loading-inset .att-loading-inset__percentage:before{content:"53"}54% .att-loading-inset .att-loading-inset__percentage:before{content:"54"}55% .att-loading-inset .att-loading-inset__percentage:before{content:"55"}56% .att-loading-inset .att-loading-inset__percentage:before{content:"56"}57% .att-loading-inset .att-loading-inset__percentage:before{content:"57"}58% .att-loading-inset .att-loading-inset__percentage:before{content:"58"}59% .att-loading-inset .att-loading-inset__percentage:before{content:"59"}60% .att-loading-inset .att-loading-inset__percentage:before{content:"60"}61% .att-loading-inset .att-loading-inset__percentage:before{content:"61"}62% .att-loading-inset .att-loading-inset__percentage:before{content:"62"}63% .att-loading-inset .att-loading-inset__percentage:before{content:"63"}64% .att-loading-inset .att-loading-inset__percentage:before{content:"64"}65% .att-loading-inset .att-loading-inset__percentage:before{content:"65"}66% .att-loading-inset .att-loading-inset__percentage:before{content:"66"}67% .att-loading-inset .att-loading-inset__percentage:before{content:"67"}68% .att-loading-inset .att-loading-inset__percentage:before{content:"68"}69% .att-loading-inset .att-loading-inset__percentage:before{content:"69"}70% .att-loading-inset .att-loading-inset__percentage:before{content:"70"}71% .att-loading-inset .att-loading-inset__percentage:before{content:"71"}72% .att-loading-inset .att-loading-inset__percentage:before{content:"72"}73% .att-loading-inset .att-loading-inset__percentage:before{content:"73"}74% .att-loading-inset .att-loading-inset__percentage:before{content:"74"}75% .att-loading-inset .att-loading-inset__percentage:before{content:"75"}76% .att-loading-inset .att-loading-inset__percentage:before{content:"76"}77% .att-loading-inset .att-loading-inset__percentage:before{content:"77"}78% .att-loading-inset .att-loading-inset__percentage:before{content:"78"}79% .att-loading-inset .att-loading-inset__percentage:before{content:"79"}80% .att-loading-inset .att-loading-inset__percentage:before{content:"80"}81% .att-loading-inset .att-loading-inset__percentage:before{content:"81"}82% .att-loading-inset .att-loading-inset__percentage:before{content:"82"}83% .att-loading-inset .att-loading-inset__percentage:before{content:"83"}84% .att-loading-inset .att-loading-inset__percentage:before{content:"84"}85% .att-loading-inset .att-loading-inset__percentage:before{content:"85"}86% .att-loading-inset .att-loading-inset__percentage:before{content:"86"}87% .att-loading-inset .att-loading-inset__percentage:before{content:"87"}88% .att-loading-inset .att-loading-inset__percentage:before{content:"88"}89% .att-loading-inset .att-loading-inset__percentage:before{content:"89"}90% .att-loading-inset .att-loading-inset__percentage:before{content:"90"}91% .att-loading-inset .att-loading-inset__percentage:before{content:"91"}92% .att-loading-inset .att-loading-inset__percentage:before{content:"92"}93% .att-loading-inset .att-loading-inset__percentage:before{content:"93"}94% .att-loading-inset .att-loading-inset__percentage:before{content:"94"}95% .att-loading-inset .att-loading-inset__percentage:before{content:"95"}96% .att-loading-inset .att-loading-inset__percentage:before{content:"96"}97% .att-loading-inset .att-loading-inset__percentage:before{content:"97"}98% .att-loading-inset .att-loading-inset__percentage:before{content:"98"}99% .att-loading-inset .att-loading-inset__percentage:before{content:"99"}100% .att-loading-inset .att-loading-inset__percentage:before{content:"100"}}.att-loading--dark .att-loading-circle__mask .att-loading-circle__fill,.att-loading--dark .loading__inside,.att-loading--dark:after,.att-loading--dark:before{background:#444}.att-loading--dark .att-loading-inset__percentage{color:#444}.lt-ie9 .att-loading--dark{background:url(images/loading_balls_black.gif) center center no-repeat}.att-loading--blue .att-loading-circle__mask .att-loading-circle__fill,.att-loading--blue .loading__inside,.att-loading--blue:after,.att-loading--blue:before{background:#0574AC}.att-loading--blue .att-loading-inset__percentage{color:#0574AC}.lt-ie9 .att-loading--blue{background:url(images/loading_balls_blue.gif) center center no-repeat}.att-loading--white{background-color:#888}.att-loading--white.att-loading-count .att-loading-inset{background-color:inherit}.att-loading--white .att-loading-circle__mask .att-loading-circle__fill,.att-loading--white .loading__inside,.att-loading--white:after,.att-loading--white:before{background:#fff}.att-loading--white .att-loading-inset__percentage{color:#fff}.lt-ie9 .att-loading--white{background:url(images/loading_balls_white.gif) center center no-repeat}.lt-ie9 .att-loading-count{background:url(images/loading_counter.png);overflow:hidden}.lt-ie9 .att-loading-count .att-loading-inset__percentage:before{margin-left:-2px}.video-player{position:relative}.video-player__control{display:inline-block;margin-right:-5px;background-color:#444}.video-player__button{-webkit-transition:background-color .3s ease-out;-moz-transition:background-color .3s ease-out;transition:background-color .3s ease-out;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;font-size:14px;font-size:.875rem;vertical-align:middle;color:#f2f2f2;text-decoration:none;cursor:pointer}.video-player__button:hover{color:#44c8f5}.video-player__button:active{-webkit-transition-property:none;-moz-transition-property:none;transition-property:none;color:#44c8f5}.video-player__button [class*=icon]{display:inline-block}.video-player__play-button{border-radius:3px 0 0 3px;border-right:1px solid #f2f2f2;padding:10px 24px 5px}.gigant-play{font-size:25px}.video-player__volume_icon{border-left:1px solid #f2f2f2;padding:17px 0 13px 11px;margin:0 -5px 0 -5px}.video-player__toggle-fullscreen-button{padding:17px 0 13px 15px;border-radius:0 3px 3px 0}.video-player__volume{padding:24px 0 17px 8px;font-size:0;background-color:#444;margin-left:0;opacity:1}.video-player__volume_icon:hover .video-player__volume{opacity:0}.video-player__volume-bar{-webkit-animation:video__volume-bar .3s reverse;-moz-animation:video__volume-bar .3s reverse;animation:video__volume-bar .3s reverse;-webkit-transform-origin:center bottom;-moz-transform-origin:center bottom;-ms-transform-origin:center bottom;-o-transform-origin:center bottom;transform-origin:center bottom;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;width:4px;height:14px;background-color:#777;margin:-5px 0 0 7px}.video-player__volume-bar:first-child{margin-left:0}.video-player__volume-bar:hover{-webkit-animation:video__volume-bar .3s 1;-moz-animation:video__volume-bar .3s 1;animation:video__volume-bar .3s 1;-webkit-transform:scaleY(1.3);-moz-transform:scaleY(1.3);-ms-transform:scaleY(1.3);-o-transform:scaleY(1.3);transform:scaleY(1.3);-webkit-transform-origin:center;-moz-transform-origin:center;-ms-transform-origin:center;-o-transform-origin:center;transform-origin:center;background-color:#44c8f5}.video-player__volume-bar--full{background-color:#f2f2f2}@-webkit-keyframes video__volume-bar{0%{-webkit-transform:scaleY(1)}50%{-webkit-transform:scaleY(1.3)}100%{-webkit-transform:scaleY(1)}}@-moz-keyframes video__volume-bar{0%{-moz-transform:scaleY(1)}50%{-moz-transform:scaleY(1.3)}100%{-moz-transform:scaleY(1)}}@-o-keyframes video__volume-bar{0%{-o-transform:scaleY(1)}50%{-o-transform:scaleY(1.3)}100%{-o-transform:scaleY(1)}}@keyframes video__volume-bar{0%{transform:scaleY(1)}50%{transform:scaleY(1.3)}100%{transform:scaleY(1)}}.video-player__track{padding:21px 0 21px 21px;margin-bottom:-19px;width:350px}.video-player__track--inner{position:relative;height:8px;border:1px solid #a0a0a0;border-radius:2px;margin:0}.video-player__track--loaded,.video-player__track--played{position:absolute;height:8px;background-color:#a0a0a0;border-radius:2px;margin:-1px 0 0 -1px;left:1px}.video-player__track--played{background-color:#f2f2f2}.video-player__track--played:hover{background-color:#44c8f5}.video-player__track-tooltip{-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;transition:opacity .1s ease-out;position:absolute;top:-35px;right:-22px;font-size:12px;font-size:.75rem;opacity:0}.lt-ie9 .video-player__track-tooltip{display:none}.video-player__track--played:hover .video-player__track-tooltip{opacity:1}.lt-ie9 .video-player__track--played:hover .video-player__track-tooltip{display:block}.video-player__track-handle{-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;transition:opacity .1s ease-out;position:absolute;top:-4px;right:-7px;opacity:0;background:#f2f2f2;width:16px;height:16px;border-radius:50%}.video-player__track--played:hover .video-player__track-handle{opacity:1}.video-player__time{font-size:14px;font-size:.875rem;color:#f2f2f2;padding:18px 20px 15px;background-color:#444}.video-player__time:hover{color:#fff}.alert-inplace .container{padding-right:30px}.alert .close-role{position:absolute;top:13px;right:20px;font-size:11px;height:20px;line-height:23px;border:0}.alert .close-role [class^=icon-]{font-size:20px;width:15px;color:#777;margin:0;vertical-align:middle;display:inline-block;margin-top:-4px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out}.alert .close-role:hover [class^=icon-]{color:#199DDF}.att-checkbox,.att-radio{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;width:21px;height:21px;background-color:#fff;border-radius:21px;border:1px solid #888;cursor:pointer;line-height:21px;text-align:center;vertical-align:middle}.att-checkbox:hover,.att-radio:hover{border-color:#444}.att-checkbox:active,.att-radio:active{border-color:#0574AC}.att-checkbox{border-radius:3px}.att-checkbox__indicator,.att-radio__indicator{opacity:0;-webkit-transition:all .2s cubic-bezier(0.175,.885,.32,1.275);-moz-transition:all .2s cubic-bezier(0.175,.885,.32,1.275);transition:all .2s cubic-bezier(0.175,.885,.32,1.275);top:50%;left:50%;width:7px;height:7px;background:#0574AC;border-radius:7px;position:initial;margin:6px;-ms-filter:"alpha(Opacity=0)"}.csstransforms .att-checkbox__indicator,.csstransforms .att-radio__indicator{-webkit-transform:scale3d(0,0,0);-moz-transform:scale3d(0,0,0);-ms-transform:scale3d(0,0,0);-o-transform:scale3d(0,0,0);transform:scale3d(0,0,0);opacity:0;display:none}.att-checkbox__indicator{width:21px;height:21px;background:0 0;left:0;margin:0;overflow:hidden;position:relative;top:0}.att-checkbox__indicator:after{content:'\f121';position:absolute;display:block;width:21px;left:-18px;color:#0574AC;text-align:center;font-family:"Ionicons";font-size:56px}.att-checkbox--on .att-checkbox__indicator,.att-radio--on .att-radio__indicator{opacity:1;-ms-filter:"alpha(Opacity=100)"}.csstransforms .att-checkbox--on .att-checkbox__indicator,.csstransforms .att-radio--on .att-radio__indicator{-webkit-transform:scale3d(1,1,1);-moz-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);-o-transform:scale3d(1,1,1);transform:scale3d(1,1,1);display:block}.att-checkbox input,.att-radio input{left:-9999px;position:absolute}.att-checkbox.att-checkbox--disabled,.att-radio.att-radio--disabled{background-color:#f2f2f2;border:1px solid #DDD;cursor:not-allowed}.att-checkbox.att-checkbox--disabled:active,.att-checkbox.att-checkbox--disabled:hover,.att-radio.att-radio--disabled:active,.att-radio.att-radio--disabled:hover{border-color:#DDD}.att-radio--disabled .att-radio__indicator,.att-radio--on.att-radio--disabled .att-radio__indicator{background:#DDD}.att-checkbox--disabled .att-checkbox__indicator:after,.att-checkbox--on.att-checkbox--disabled .att-checkbox__indicator:after{color:#DDD}.accordion-color-icon-green{background:green;border-radius:100%;height:12px;width:12px;margin:3px 0 0 10px;position:absolute}.accordion-color-icon-yellow{background:#ff0;border-radius:100%;height:12px;width:12px;margin:3px 0 0 10px;position:absolute}.accordion-color-icon-blue{background:#00f;border-radius:100%;height:12px;width:12px;margin:3px 0 0 10px;position:absolute}.accordion-color-icon-red{background:red;border-radius:100%;height:12px;width:12px;margin:3px 0 0 10px;position:absolute}.show-true{padding-left:20px}.att-checkbox--indeterminate:after{content:'-';position:absolute;top:-2px;font-weight:700;color:#067ab4;font-size:40px;left:2px}.dropdown{position:relative}.dropdown:focus,.dropdown:hover{z-index:1}.dropdown:focus>.dropdown__menu,.dropdown:hover>.dropdown__menu{display:block}.dropdown__caret{font-size:10px;margin-left:5px}.dropdown__menu{position:absolute;top:100%;left:0;background-color:#fff;display:none;list-style:none;min-width:150px;text-align:left;z-index:5}.nav--text-right .dropdown__menu{left:auto;right:0}.dropdown__menu-link{display:block;padding:0 20px}select[data-dropdown]{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;width:auto;opacity:0}.no-js select[data-dropdown]{opacity:1}.att-dropdown{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;position:relative}.att-dropdown select{position:absolute;top:-10000px;left:-10000px;color:transparent;font:0/0 a;text-shadow:none}.att-dropdown__selection{font-size:48px;font-size:3rem;font-family:omnes_att_light;line-height:48px;letter-spacing:-2px;display:block;color:#444;cursor:pointer}.att-dropdown__selection:after{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;font-size:14px;font-size:.875rem;margin-left:10px;vertical-align:middle}.att-dropdown__selection.att-dropdown--focus,.att-dropdown__selection.att-dropdown--focus:visited{color:#444;outline:0}.att-dropdown__items{position:absolute;top:-10000px;left:-10000px;background-color:#0574AC;border-radius:6px;color:#fff;opacity:0;visibility:hidden;list-style:none;z-index:6;min-width:100px;margin:-10px}.att-dropdown__items.att-dropdown--open{visibility:visible;opacity:1;outline:0}.att-dropdown__item{font-size:48px;font-size:3rem;font-family:omnes_att_light;letter-spacing:-2px;cursor:default;display:block;line-height:48px;margin-top:-1px;overflow:hidden;padding:10px 50px 17px 10px;position:relative}.att-dropdown__item:first-child{border-top-left-radius:6px;border-top-right-radius:6px}.att-dropdown__item:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}.att-dropdown__item:before{position:absolute;top:0;right:10px;left:10px;content:'';display:block;height:1px;border-top:1px solid #0e2875}.att-dropdown__item:first-child:before{display:none}.att-dropdown__item.att-dropdown__item--active{background-color:#0e2875}.att-dropdown__item.att-dropdown__item--selected:after{font-size:28px;font-size:1.75rem;display:inline-block;vertical-align:middle;margin-top:-2px;margin-left:20px}.att-dropdown--h2 .att-dropdown__item,.att-dropdown--h2 .att-dropdown__selection{font-size:36px;font-size:2.25rem;font-family:omnes_att_light;line-height:36px;letter-spacing:-2px}.att-dropdown--h3 .att-dropdown__item,.att-dropdown--h3 .att-dropdown__selection{font-size:24px;font-size:1.5rem;font-family:omnes_att_regular;line-height:26px;letter-spacing:0}.att-dropdown__overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.1);display:none;z-index:5}.select2-container.select2-container-disabled .select2-choice{z-index:0}.select2-container{margin:0;position:relative;display:inline-block;zoom:1;*display:inline;vertical-align:middle;width:100%}.select2-container,.select2-drop,.select2-search,.select2-search input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.select2-container .select2-choice{overflow:hidden;white-space:nowrap;line-height:26px;color:#444;text-decoration:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.select2-container.select2-drop-above .select2-choice{border-bottom-color:#aaa;border-radius:0 0 4px 4px;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0,#eee),color-stop(0.9,#fff));background-image:-webkit-linear-gradient(center bottom,#eee 0,#fff 90%);background-image:-moz-linear-gradient(center bottom,#eee 0,#fff 90%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);background-image:linear,to bottom,#eee 0,#fff 90%}.select2-container.select2-allowclear .select2-choice .select2-chosen{margin-right:42px}.select2-container .select2-choice>.select2-chosen{margin-right:26px;display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.select2-container .select2-choice abbr{display:none;width:12px;height:12px;position:absolute;right:24px;top:8px;font-size:1px;text-decoration:none;border:0;background:url(select2.png) right top no-repeat;cursor:pointer;outline:0}.select2-container.select2-allowclear .select2-choice abbr{display:inline-block}.select2-container .select2-choice abbr:hover{background-position:right -11px;cursor:pointer}.select2-drop-mask{border:0;margin:0;padding:0;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;background-color:#fff}.select2-drop{width:100%;position:absolute;top:100%;color:#000;border:1px solid #aaa;-webkit-box-shadow:0 4px 5px rgba(0,0,0,.15);box-shadow:0 4px 5px rgba(0,0,0,.15)}.select2-drop.select2-drop-above{margin-top:1px;border-radius:4px 4px 0 0;-webkit-box-shadow:0 -4px 5px rgba(0,0,0,.15);box-shadow:0 -4px 5px rgba(0,0,0,.15)}.select2-drop-active{border:1px solid #5897fb;border-top:0}.select2-drop.select2-drop-above.select2-drop-active{border-top:1px solid #5897fb}.select2-drop-auto-width{border-top:1px solid #aaa;width:auto}.select2-drop-auto-width .select2-search{padding-top:4px}.select2-container .select2-choice .select2-arrow{display:inline-block;height:100%;position:absolute;right:0;top:0;border-radius:0 4px 4px 0}.select2-container .select2-choice .select2-arrow b{display:block;width:100%;height:100%;background:url(select2.png) no-repeat 0 1px}.select2-search{display:inline-block;width:100%;margin:0;padding-left:4px;padding-right:4px;position:relative;z-index:10000;white-space:nowrap}.select2-search input{width:100%;outline:0;font-family:sans-serif;font-size:1em;border:1px solid #aaa;border-radius:0;-webkit-box-shadow:none;box-shadow:none;background:#fff url(select2.png) no-repeat 100% -22px;background:url(select2.png) no-repeat 100% -22px,-webkit-gradient(linear,left bottom,left top,color-stop(0.85,#fff),color-stop(0.99,#eee));background:url(select2.png) no-repeat 100% -22px,-webkit-linear-gradient(center bottom,#fff 85%,#eee 99%);background:url(select2.png) no-repeat 100% -22px,-moz-linear-gradient(center bottom,#fff 85%,#eee 99%);background:url(select2.png) no-repeat 100% -22px,linear,to bottom,#fff 85%,#eee 99% 0 0}.select2-drop.select2-drop-above .select2-search input{margin-top:4px}.select2-search input.select2-active{background:#fff url(select2-spinner.gif) no-repeat 100%;background:url(select2-spinner.gif) no-repeat 100%,-webkit-gradient(linear,left bottom,left top,color-stop(0.85,#fff),color-stop(0.99,#eee));background:url(select2-spinner.gif) no-repeat 100%,-webkit-linear-gradient(center bottom,#fff 85%,#eee 99%);background:url(select2-spinner.gif) no-repeat 100%,-moz-linear-gradient(center bottom,#fff 85%,#eee 99%);background:url(select2-spinner.gif) no-repeat 100%,linear,to bottom,#fff 85%,#eee 99% 0 0}.select2-container-active .select2-choice,.select2-container-active .select2-choices{border:1px solid #5897fb;outline:0;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.select2-dropdown-open .select2-choice{border-bottom-color:transparent;-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset;background-color:#eee;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0,#fff),color-stop(0.5,#eee));background-image:-webkit-linear-gradient(center bottom,#fff 0,#eee 50%);background-image:-moz-linear-gradient(center bottom,#fff 0,#eee 50%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);background-image:linear,to top,#fff 0,#eee 50%}.select2-dropdown-open.select2-drop-above .select2-choice,.select2-dropdown-open.select2-drop-above .select2-choices{border:1px solid #5897fb;border-top-color:transparent;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(0.5,#eee));background-image:-webkit-linear-gradient(center top,#fff 0,#eee 50%);background-image:-moz-linear-gradient(center top,#fff 0,#eee 50%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);background-image:linear,to bottom,#fff 0,#eee 50%}.select2-dropdown-open .select2-choice .select2-arrow{background:0 0;border-left:0;filter:none}.select2-dropdown-open .select2-choice .select2-arrow b{background-position:-18px 1px}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.select2-results{max-height:200px;position:relative;overflow-x:hidden;overflow-y:auto;-webkit-tap-highlight-color:transparent}.select2-results ul.select2-result-sub{margin:0;padding-left:0}.select2-results ul.select2-result-sub>li .select2-result-label{padding-left:20px}.select2-results ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:40px}.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:60px}.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:80px}.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:100px}.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:110px}.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label{padding-left:120px}.select2-results li{list-style:none;display:list-item;background-image:none}.select2-results li.select2-result-with-children>.select2-result-label{font-weight:700}.select2-results .select2-result-label{padding:3px 7px 4px;margin:0;cursor:pointer;min-height:1em;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.select2-results .select2-highlighted{background:#3875d7;color:#fff}.select2-results li em{background:#feffde;font-style:normal}.select2-results .select2-highlighted em{background:0 0}.select2-results .select2-highlighted ul{background:#fff;color:#000}.select2-results .select2-no-results,.select2-results .select2-searching,.select2-results .select2-selection-limit{background:#f4f4f4;display:list-item;padding-left:5px}.select2-results .select2-disabled.select2-highlighted{color:#666;background:#f4f4f4;display:list-item;cursor:not-allowed}.select2-results .select2-disabled{background:#f4f4f4;display:list-item;cursor:not-allowed}.select2-results .select2-selected{display:none}.select2-more-results.select2-active{background:#f4f4f4 url(select2-spinner.gif) no-repeat 100%}.select2-more-results{background:#f4f4f4;display:list-item}.select2-container.select2-container-disabled .select2-choice{background-color:#f4f4f4;background-image:none;border:1px solid #ddd;cursor:not-allowed}.select2-container.select2-container-disabled .select2-choice abbr{display:none}.select2-container-multi .select2-choices{height:auto!important;height:1%;margin:0;padding:0;position:relative;border:1px solid #aaa;cursor:text;overflow:hidden;background-color:#fff;background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(top,#eee 1%,#fff 15%);background-image:-moz-linear-gradient(top,#eee 1%,#fff 15%);background-image:linear,to bottom,#eee 1%,#fff 15%}.select2-locked{padding:3px 5px!important}.select2-container-multi .select2-choices{min-height:26px}.select2-container-multi.select2-container-active .select2-choices{border:1px solid #5897fb;outline:0;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.select2-container-multi .select2-choices li{float:left;list-style:none}html[dir=rtl] .select2-container-multi .select2-choices li{float:right}.select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}.select2-container-multi .select2-choices .select2-search-field input{padding:5px;margin:1px 0;font-family:sans-serif;font-size:100%;color:#666;outline:0;border:0;-webkit-box-shadow:none;box-shadow:none;background:transparent!important}.select2-container-multi .select2-choices .select2-search-field input.select2-active{background:#fff url(select2-spinner.gif) no-repeat 100%!important}.select2-default{color:#999!important}.select2-container-multi .select2-choices .select2-search-choice{padding:3px 5px 3px 18px;margin:3px 0 3px 5px;position:relative;line-height:13px;color:#333;cursor:default;border:1px solid #aaa;border-radius:3px;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);background-clip:padding-box;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#e4e4e4;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear,to top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%}html[dir=rtl] .select2-container-multi .select2-choices .select2-search-choice{margin-left:0;margin-right:5px}.select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}.select2-container-multi .select2-choices .select2-search-choice-focus{background:#d4d4d4}.select2-search-choice-close{display:block;width:12px;height:13px;position:absolute;right:3px;top:4px;font-size:1px;outline:0;background:url(select2.png) right top no-repeat}html[dir=rtl] .select2-search-choice-close{right:auto;left:3px}.select2-container-multi .select2-search-choice-close{left:3px}.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover,.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}.select2-container-multi.select2-container-disabled .select2-choices{background-color:#f4f4f4;background-image:none;border:1px solid #ddd;cursor:not-allowed}.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice{padding:3px 5px;border:1px solid #ddd;background-image:none;background-color:#f4f4f4}.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:0 0}.select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;border:0!important;margin:0!important;padding:0!important;overflow:hidden!important;position:absolute!important;outline:0!important;left:0!important;top:0!important}.select2-display-none{display:none}.select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:2dppx){.select2-container .select2-choice .select2-arrow b,.select2-container .select2-choice abbr,.select2-search input,.select2-search-choice-close{background-image:url(select2x2.png)!important;background-repeat:no-repeat!important;background-size:60px 40px!important}.select2-search input{background-position:100% -21px!important}}.select2-container .select2-choice{-webkit-transition:border-color .2s ease-out;-moz-transition:border-color .2s ease-out;transition:border-color .2s ease-out;background:#fff;border-radius:6px;display:block;border:1px solid #888;box-shadow:none;filter:none;height:40px;padding:0;position:relative;z-index:5;cursor:pointer}.select2-container-active .select2-choice{border-color:#0091d9;z-index:1}.select2-dropdown-open .select2-choice{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}.select2-dropdown-open.select2-drop-above .select2-choice{border-top-left-radius:0!important;border-top-right-radius:0!important}.select2-container .select2-chosen,.select2-container input{font-size:12px;font-size:.75rem;color:#444;height:100%;line-height:39px;padding-left:10px;text-align:left}.select2-container input,.select2-container input:hover{border:0!important;line-height:inherit}.text-separator-subtitle .select2-chosen{font-size:18px;font-size:1.125rem}.hovstyle{background:#1792d6!important;color:#fff!important}.hovstyle.disable{background:transparent!important;color:#c4c4c4!important}.select2-container .select2-choice .select2-arrow,.select2-container.select2-container-disabled .select2-choice .select2-arrow{-webkit-transition:none;-moz-transition:none;transition:none;background:0 0;border:0;filter:none;width:25px;z-index:10}.select2-container .select2-choice .select2-arrow b:after,.select2-container.select2-container-disabled .select2-choice .select2-arrow b:after{font-size:14px;font-size:.875rem;content:'\f104';font-family:"Ionicons";position:absolute;top:0;right:0;width:25px;height:40px;line-height:40px;background:0 0;text-align:center;color:#888}.select2-dropdown-open .select2-choice .select2-arrow b:after{content:'\f10d'}.select2-container.select2-container-disabled .select2-chosen{color:#a0a0a0}.select2-drop{margin-top:-1px;background:#fff;border-top:1px solid #d3d3d3;border-radius:0 0 6px 6px;z-index:4}.select2-drop-mask{z-index:3}.select2-drop.select2-drop-above{border-top:0;border-bottom:1px solid #d3d3d3}.select2-search{height:0;min-height:0;overflow:hidden}.select2-search input{margin:0;padding:7px 10px;height:40px!important;line-height:12px;line-height:1.2rem;min-height:0!important}.select2-results{padding:0;margin:-19px 0 0 0;border-radius:0 0 6px 6px;-webkit-box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px;-moz-box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px;box-shadow:rgba(0,0,0,.25) 0 8px 10px -3px}.select2-drop-above .select2-results{border-radius:6px 6px 0 0}.select2-drop-above.select2-dropdown-open .select2-choice{border-radius:0 0 6px 6px!important;background:#fff}.select2-drop-above.select2-drop{border-radius:6px 6px 0 0;margin-top:0;overflow:hidden}.select2-drop.show-search .select2-search{height:auto;overflow:visible;padding:5px}.select2-drop.show-search .select2-results{margin-top:0}.select2-results .select2-result{background:0 0}.select2-result .select2-result-label{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;font-size:12px;font-size:.75rem;color:#444;display:block;line-height:14px;margin:0;padding:8px 10px}.select2-result.select2-result-current .select2-result-label{background:#fff;color:#1792D6}.select2-result.select2-result-current .select2-result-label:after{content:'\f121';font-family:"Ionicons";font-size:8px;vertical-align:bottom;margin-left:5px;background:0 0;text-align:center;color:#1792D6}.select2-result-current .select2-result-label{font-family:clearview_att_regular;padding-right:5px;color:#067ab4}.select2-no-results{font-size:12px;font-size:.75rem;color:#777;font-family:Arial;line-height:12px;padding:10px}.select2-result-selectable .select2-match,.select2-result-unselectable .select2-match{background-color:#c9e9f9;text-decoration:none}.select2-container .color-circle,.select2-results .color-circle{width:15px;height:15px;display:inline-block;zoom:1;*display:inline;*vertical-align:auto;border-radius:15px;margin-right:10px;vertical-align:middle}.select2-container .option-extra,.select2-results .option-extra{float:right}.select2-container .price,.select2-results .price{color:#888}.select2-container.select--clean{border-color:transparent;background:0 0;width:auto}.select2-container.select--clean .select2-choice{background:0 0;border-color:transparent;height:auto}.select2-container.select--clean .select2-drop{margin-top:5px}.select2-container.select--h1 .select2-chosen{font-size:48px;font-size:3rem;font-family:omnes_att_light;line-height:48px;letter-spacing:-2px}.select2-container.select--h2 .select2-chosen{font-size:36px;font-size:2.25rem;font-family:omnes_att_light;line-height:36px;letter-spacing:-2px}.select2-container.select--h3 .select2-chosen{font-size:24px;font-size:1.5rem;font-family:omnes_att_regular;line-height:26px;letter-spacing:0}.select2-container.select--h4 .select2-chosen{font-size:18px;font-size:1.125rem;font-family:clearview_att_regular;line-height:22px;letter-spacing:0}.select2-drop.select--clean{margin-top:5px}.select2-container .select2-choice .select2-arrow b,.select2-container .select2-choice abbr,.select2-container-multi .select2-choices .select2-search-field input.select2-active,.select2-more-results.select2-active,.select2-search input,.select2-search input.select2-active,.select2-search-choice-close{background-image:none!important}.select2-container.select2--small .select2-choice{height:30px;z-index:1}.select2-container.select2--small .select2-chosen{line-height:29px}.select2-container.select2--small .select2-choice .select2-arrow b:after,.select2-container.select2--small.select2-container-disabled .select2-choice .select2-arrow b:after{height:30px;line-height:30px}.select2-container.select2--small .select2-search input{height:30px!important}.select2-container .select2-choice.select2-chosen-disabled{margin-right:26px;display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.75rem;height:100%;line-height:39px;padding-left:10px;text-align:left;color:#c4c4c4;background-color:#e4e4e4;border:1px solid #d4d4d4;cursor:not-allowed}.select2-result.disable .select2-result-label{color:#c4c4c4;cursor:not-allowed}ul.select2-results li:last-child{margin-bottom:10px}.text-dropdown{display:block;font-family:omnes_att_light;font-size:48px;color:#067AB4;line-height:40px}.text-dropdown .not-visible{visibility:hidden}.text-dropdown .actions-opened{display:block;width:auto;position:relative;margin-top:-35px;margin-left:20px}.text-dropdown .actions-opened li i{margin-left:20px}.text-dropdown .actions-closed{display:none}.text-dropdown .action--selected{text-decoration:underline;color:#0574AC}.text-dropdown ul{margin-left:-35px;margin-top:-40px;padding-left:0;position:absolute;list-style-type:none;-moz-border-radius:6px;-webkit-border-radius:6px;border:1px solid #0574AC;box-shadow:0 2px 10px -2px;-webkit-box-shadow:0 2px 10px -2px;-moz-box-shadow:0 2px 10px -2px}.text-dropdown li{white-space:nowrap;height:auto;background-color:#0F7EB6;color:#FFF;font-size:48px;font-family:omnes_att_light;line-height:48px;letter-spacing:-1px;padding-left:20px;cursor:pointer}.text-dropdown li i{margin-left:15px;font-size:30px}.text-dropdown .highlight{background-color:#0F2A7B}.text-dropdown .icon-included-checkmark{color:#fff;font-size:30px}.text-dropdown .dropdown{display:inline-block;cursor:pointer}.text-dropdown .dropdown i{font-size:20px;position:relative;top:-10px}.att-accordion{background:#fff;position:relative;border-radius:6px;border-width:1px;border-color:#888;border-style:solid;overflow:hidden}.att-accordion__freestanding{display:block;min-height:50px;margin-bottom:19px}.att-accordion__group{padding-left:20px;padding-right:20px;margin-top:-1px;position:relative}.att-accordion__group.first,.att-accordion__group:first-child{margin-top:0}.att-accordion__group:hover{background-color:#bbb;z-index:1}.att-accordion__group--open{z-index:1}.att-accordion__group--open.att-accordion__group:hover{background-color:transparent}.att-accordion__inner,.att-accordion__toggle{margin:10px 0;text-transform:none}.att-accordion__toggle{font-size:14px;font-size:.875rem;color:#666;display:inline-block;font-family:clearview_att_regular;position:relative;width:100%}.att-accordion__toggle:after{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;font-size:14px;font-size:.875rem;position:absolute;top:50%;right:20px;font-family:"Ionicons";content:"\e6dc";height:14px;margin-top:-7px;color:#0574AC}.att-accordion__toggle:hover{color:#0091d9}.att-accordion__toggle.noafter:after{content:none}.att-accordion__toggle.noafter i{color:#067ab4}.att-accordion__group--open .att-accordion__toggle:after{-webkit-transform:rotate(-180deg);-moz-transform:rotate(-180deg);-ms-transform:rotate(-180deg);-o-transform:rotate(-180deg);transform:rotate(-180deg)}.no-csstransforms .att-accordion__heading .att-accordion__toggle:after{-webkit-transition:none;-moz-transition:none;transition:none}.att-accordion__body{display:none;padding-top:0;padding-bottom:14px}.att-accordion__body p{margin-bottom:15px}.att-accordion__inner{padding-top:0}.att-accordion__inner>*{margin:0}.att-accordion__bottom--border{border-bottom:1px solid #888;position:absolute;left:20px;right:20px}.att-accordion--no-box .att-accordion__bottom--border{border-bottom:0}.att-accordion--no-box{background:0 0}.att-accordion--no-box .att-accordion__group{border:0;border-bottom:1px solid #bbb;margin-top:-1px;position:relative;padding-left:0!important;padding-right:0!important}.att-accordion--no-box .att-accordion__group.last,.att-accordion--no-box .att-accordion__group:last-child{border-radius:0}.att-accordion--no-box .att-accordion__group:hover{border-color:#bbb;background-color:transparent}.att-accordion--no-box .att-accordion__group--open{border-color:#bbb}.att-accordion--no-box .att-accordion__toggle:active{color:#0574AC}.att-accordion--no-box .att-accordion__toggle:hover{color:#0091d9}.att-accordion--no-box .att-accordion__group--open .att-accordion__toggle{color:#199DDF}.att-accordion--no-box .att-accordion__inner{margin:10px 0!important;text-transform:none}.att-accordion--no-box .att-accordion__toggle:after{position:absolute;top:50%;right:0}.att-accord-header{width:600px;height:50px;background-color:#f2f2f2;border-left:2px solid gray;border-right:2px solid gray;border-top:2px solid gray;border-bottom:2px solid gray;cursor:pointer}.att-accord-header-closed{border-bottom:0}.att-accord-header i{float:right;margin-right:20px;margin-top:-15px}.att-accord-body-inner-text{margin-left:50px;margin-right:50px;height:32px;border-bottom:1px solid gray}.att-accord-body-inner-end{margin-left:50px;margin-right:50px;height:32px;border-bottom:0}.att-accord-header-child{margin-left:50px;margin-top:14px}.att-accord-body{width:600px;height:100px;background-color:#fff;border-left:2px solid gray;border-right:2px solid gray}.att-accord-body-last{border-bottom:2px solid gray}.hourpicker .customdays-width{width:700px}.hourpicker .dropdown-width{width:32%;position:relative}.hourpicker .col-md-days{width:13.4%;padding-left:0;padding-right:0}.hourpicker .divider-margin-f{margin-top:30px;margin-bottom:20px}.hourpicker .divider-margin-s{margin-top:155px}.hourpicker .fromto-margin{width:6%;margin-top:45px;padding:0}.hourpicker .days-margin{margin-right:3px}.hourpicker .daysselect-margin{margin-bottom:20px;margin-right:25px;padding:0}.hourpicker .topDropDownWidth{width:100%;z-index:0}.hourpicker .resultTopMargin{margin-top:0;max-height:205px}.hourpicker .resultTopWidth{display:block;width:100%;position:absolute;background:#fff;z-index:999}.hourpicker .dropDownMarginBottom{width:80px;margin-bottom:10px}.hourpicker .dropDownMarginRight{margin-right:0!important;line-height:30px}.hourpicker .resultToDropDown{display:block;width:80px;position:absolute;background:#fff;z-index:99;top:111px}.hourpicker .resultFromDropDown{display:block;width:80px;position:absolute;background:#fff;z-index:99;top:71px}.hourpicker .selectDropDown{height:30px!important;width:80px;padding-left:0!important}.hourpicker .selectDropDown.selectDropDown-error{border:red solid 1px}.hourpicker .selectedItemInDropDown{background:#1792D6;color:#fff}.hourpicker .select2-container .select2-chosen{padding-left:4px!important}.hourpicker .select2-result .select2-result-label{padding:8px 3px!important}.hourpicker.hourpicker-error-msg{width:100%;border-radius:4px;display:block;padding:10px;font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:10px;color:#666;text-transform:none;background:#fff;position:absolute;z-index:1;-moz-box-sizing:border-box;box-sizing:border-box;text-align:center}.hourpicker.hourpicker-error-msg [class*=icon-]{color:#fff;position:relative;margin-right:9px;line-height:0!important;vertical-align:middle}.hourpicker.hourpicker-error-msg span{vertical-align:middle}.hourpicker.hourpicker-error-msg.error{color:#fff;background:#e00000}.hourpicker.hourpicker-error-msg.warning{color:#444;background:#FCB123}.hourpicker.hourpicker-error-msg.warning [class*=icon-]{color:#444}.hourpicker.hourpicker-error-msg.success{color:#fff;background:#008a06}.hourpicker.hourpicker-error-msg.info{color:#fff;background:#0a7cb5}.hourpicker.hourpicker-error-msg [class^=icon-]{height:30px;line-height:30px}.att-switch{display:inline-block;vertical-align:middle;width:77px;height:20px;line-height:20px;background-color:#666;border-radius:2px;position:relative;overflow:hidden;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.att-switch.large{width:83px;height:30px}.ie .att-switch{border:0}.att-switch-content{position:absolute;width:131px;font-size:0;top:0;left:-52px;overflow:hidden;-webkit-transition:left .2s ease-in-out 0;-moz-transition:left .2s ease-in-out 0;transition:left .2s ease-in-out 0}.att-switch-content.large{width:135px}.att-switch-content.dragging{-webkit-transition:left;-moz-transition:left 0;transition:left 0}.att-switch.att-checkbox--on .att-switch-content{left:0}.att-switch-offText,.att-switch-onText,.att-switch-thumb{display:inline-block;vertical-align:middle;font-size:11px;font-size:.6875rem;width:53px;height:21px;text-align:center;cursor:pointer;color:#fafafa;margin:0;-webkit-transition:background-color .2s ease-out,color .2s ease-out;-moz-transition:background-color .2s ease-out,color .2s ease-out;transition:background-color .2s ease-out,color .2s ease-out}.ie .att-switch-thumb,.lt-ie9 .att-switch-offText,.lt-ie9 .att-switch-onText,.lt-ie9 .att-switch-thumb{margin-top:-1px}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.att-switch-thumb{margin-top:-1px}}.att-switch-thumb{width:23px;height:18px;border-radius:2px;background:#fafafa;top:0;position:relative;overflow:hidden;font-size:12px;font-size:.75rem;color:#afafaf}.att-switch-thumb:focus{color:#0091d9}.att-switch-thumb:after{content:'III';letter-spacing:1px;line-height:17px;position:absolute;left:7px;top:1px}.att-switch-thumb.large{margin-top:1px;width:29px;height:28px}.att-switch-thumb.large:after{font-size:16px;font-size:1rem;content:'III';letter-spacing:1px;line-height:26px;position:absolute;left:7px;top:1px}.att-switch.att-checkbox--on{background:#118817}.att-switch .att-switch-thumb:hover,.att-switch.att-checkbox--on .att-switch-thumb:hover{color:#0091d9}.ico{font-size:15px;font-size:.9375rem;-webkit-font-smoothing:antialiased;color:#fff;line-height:20px;pointer-events:none;width:53px;z-index:3}.att-switch-onText{text-indent:4px}.att-switch-offText{text-indent:-4px}.att-switch input{visibility:hidden;position:absolute;left:-100px}.navbar .dev-notes-toggle{color:#6f6f6f;display:inline-block;vertical-align:middle;height:50px;line-height:49px}.navbar .dev-notes-toggle label{display:inline-block;vertical-align:middle;font-family:'Helvetica Neue LT Std','Helvetica Neue',Helvetica;font-size:12px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.navbar .att-switch{margin-top:-1px;margin-left:5px;background-color:#333;outline:1px solid #333}.button--search{border-radius:0 5px 5px 0}.form-field.form-field__small input[type=color],.form-field.form-field__small input[type=date],.form-field.form-field__small input[type=datetime-local],.form-field.form-field__small input[type=datetime],.form-field.form-field__small input[type=email],.form-field.form-field__small input[type=month],.form-field.form-field__small input[type=number],.form-field.form-field__small input[type=password],.form-field.form-field__small input[type=search],.form-field.form-field__small input[type=tel],.form-field.form-field__small input[type=text],.form-field.form-field__small input[type=time],.form-field.form-field__small input[type=url],.form-field.form-field__small input[type=week],.form-field.form-field__small select,.form-field.form-field__small textarea{height:30px;font-size:12px;font-size:.75rem}.form-field.form-field__small [class^=icon-]{height:30px;line-height:30px}.att-value-selector{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:16px;font-size:1rem}.att-value-selector .att-radio{width:48px;height:48px;background:0 0;border:2px solid transparent;color:#bbb;padding:1px}.att-value-selector .att-radio:hover{border-color:#bababa;color:#444}.att-value-selector .att-radio.att-radio--on{border-color:#0574AC;color:#444}.att-value-selector .att-radio__indicator{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:none;-moz-transition:none;transition:none;width:42px;height:42px;-ms-filter:none;filter:none;background:0 0;border-radius:40px;border:1px solid #bababa;margin:0;opacity:1;padding-top:5px;position:static}.att-value-selector.att-radio--on .att-radio__indicator{-ms-filter:none;filter:none}.att-value-selector__item{text-align:center}.att-value-selector__unit,.att-value-selector__value{font-size:16px;font-size:1rem;display:block;font-family:clearview_att_regular;line-height:18px;margin:0}.att-value-selector__unit{font-size:12px;font-size:.75rem;line-height:12px}.att-color-selector{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:16px;font-size:1rem}.att-color-selector__item{width:30px;height:30px;-webkit-transition:none;-moz-transition:none;transition:none;margin-bottom:5px;background:0 0;border:0;position:relative}.att-color-selector__item:hover{border:2px solid #999;box-shadow:none}.att-radio.att-color-selector__item:hover>.att-radio__indicator{border:0;margin:-11px 0 0 -11px;width:22px;height:22px;border-radius:22px}.att-radio--on.att-color-selector__item{border:2px solid #157BB2}.att-radio--on.att-color-selector__item .att-radio__indicator{border:0;margin:-11px 0 0 -11px;width:22px;height:22px;border-radius:22px}.att-color-selector .att-radio__indicator,[data-color-selector] .att-radio__indicator{-webkit-transform:none;-moz-transform:none;-ms-transform:none;-o-transform:none;transform:none;-webkit-transition:none;-moz-transition:none;transition:none;width:30px;height:30px;border:1px solid #474747;border-radius:30px;display:block;left:50%;margin:-16px 0 0 -16px;opacity:1;top:50%;position:absolute;-ms-filter:"alpha(Opacity=100)"}.att-value-selector__popover-toggle{width:40px;height:40px;display:block;white-space:nowrap}.att-value-selector__popover-toggle [class^=icon-]{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;position:static;vertical-align:middle;width:auto}.att-value-selector__popover-toggle--single{cursor:default}.att-value-selector__selected-circle{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;width:40px;height:40px;border-radius:40px;border:2px solid #999;color:#444;text-align:center;vertical-align:middle}.att-value-selector__selected-circle .att-value-selector__value{line-height:14px;margin-top:5px}.att-color-selector .att-value-selector__selected-circle{border:0}.overlayed{position:absolute;top:0;right:0;bottom:0;left:0;background:none repeat scroll 0 0 rgba(242,242,242,.95);z-index:90;display:none}.modals{top:0;bottom:0;left:0;right:0;position:fixed;z-index:100;overflow-x:auto;overflow-y:scroll;display:none}.modal__informative,.modal__warning{background:#fff;width:380px;box-shadow:0 2px 5px 0 #BEBEBE;border:1px solid #E6E6E6;padding:35px;border-radius:5px;margin:5% auto}.modal__informative{color:#157BB2}.modal__informative .modal__header--icon{background:url(images/icon-informative-modal.png) center center no-repeat}.modal__warning{color:#ED6F20}.modal__warning .modal__header--icon{background:url(images/icon-warning-modal.png) center center no-repeat}.modal__header{display:inline-table;position:relative;width:73%}.modal__header h2{width:220px;display:inline-block;margin:0}.modal__header .modal__header--icon{position:absolute;display:inline-block;height:65px;width:110px;bottom:0}.modal__header .modal__header--close{color:#888;font-size:28px;position:absolute;right:-112px;top:-24px;cursor:pointer}.modal__header .modal__header--close:hover{color:#444}.modal__content{padding-top:8px;color:#444}.modal__footer{padding-top:35px}.modal__footer a{margin-right:5px}.modal-open,.modal-open .navbar{padding-right:17px}.custom_modal{background:none repeat scroll 0 0 #f2f2f2;opacity:.91}.custom_modal .modal__header h2{width:inherit;margin-bottom:12px}.custom_modal .modal__warning{color:inherit;padding:0;width:980px;background:0 0;border:0;border-radius:none;box-shadow:none}.custom_modal .modal__content{width:100%;padding-top:11px;display:inline-block}.custom_modal .size-onethird .button--primary{min-width:92px}.custom_modal .size-onethird .button--small{padding:8px 0}.custom_modal .accordian{background-color:#fff;margin:30px 5px 0;padding:0;border:1px solid #bbb;border-radius:3px 3px 0 0;border-bottom:0}.custom_modal .accordianheader{background:none repeat scroll 0 0 #666;color:#fff;padding:11px;border-radius:3px 3px 0 0}.custom_modal .att-accordion__bottom--border{border:0}.custom_modal .att-accordion__body,.custom_modal .att-accordion__heading{top:3px}.custom_modal .att-accordion__heading{padding:12px;margin:0}.custom_modal .att-accordion__body{padding:5px;background-color:#f2f2f2}.custom_modal .icon-chevron-down,.custom_modal .icon-chevron-up{right:24px;position:absolute}.custom_modal .button--square{border-bottom:1px solid #bbb;margin:14px 20px;padding:0}.custom_modal .button--square>label{margin-bottom:14px}.custom_modal .select2-container .select2-choice{height:30px}.custom_modal .select2-chosen{position:relative;top:-4px}.custom_modal .select2-arrow>b{position:relative;top:-6px}.custom_modal .att-accordion--no-box .att-accordion__group--open .att-accordion__toggle{background-color:#44C9F6;color:#444}.custom_modal .att-accordion__toggle{position:static}.custom_modal .acc_checkboxgroup .scroll-viewport{height:250px;width:960px}.att--tree ul{margin:0 0 0 10px!important;padding:0!important;list-style-type:none!important}.att--tree li{font-size:12px;font-size:.75rem;cursor:pointer;position:relative;text-decoration:none;color:#888;padding-left:24px;padding-top:2px}.att--tree li:hover{color:#0091d9}.att--tree__plus:before{font-size:14px;font-size:.875rem;font-family:"Ionicons";content:"\e63b";display:inline-block;margin-right:8px;vertical-align:middle}.att--tree__plus:hover{color:#0091d9}.att--tree__arrow{-moz-box-sizing:border-box;box-sizing:border-box;background:url(images/treearrow.png) no-repeat;display:block;margin-left:-10px}.att--tree a{font-size:12px;font-size:.75rem;cursor:pointer;position:relative;display:inline-block;padding:5px 3px;text-decoration:none;color:#888}.att--tree a:hover{color:#0091d9}.att--tree{width:-webkit-fit-content}.att--tree__plus.minus{color:#39b1ec}.att--tree__plus.minus:before{font-size:14px;font-size:.875rem;font-family:"Ionicons";content:"\e63c";display:inline-block;margin-right:8px;vertical-align:middle}.tablesorter-default{font-size:12px;font-size:.75rem;font-family:clearview_att_regular;width:100%;color:#333;background-color:#fff;margin:10px 0 15px;text-align:left;cursor:pointer}.tablesorter-default th,.tablesorter-default thead td{color:#fff;background-color:#666;border-collapse:collapse;padding:0;font-weight:700}.tablesorter-default tfoot td,.tablesorter-default tfoot th{border:0}.tablesorter-default .tablesorter-header.sorter-false .tablesorter-header-inner{background:0 0;cursor:default}.tablesorter-default .tablesorter-header .tablesorter-header-inner{background-image:url(images/upanddown.png);background-position:center right;background-repeat:no-repeat;cursor:pointer;white-space:normal;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;padding:12px 16px}.tablesorter-default thead .headerSortUp .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerAsc .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerSortUp .tablesorter-header-inner{background-image:url(images/up.png)}.tablesorter-default thead .headerSortDown .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerDesc .tablesorter-header-inner,.tablesorter-default thead .tablesorter-headerSortDown .tablesorter-header-inner{background-image:url(images/down.png)}.tablesorter-default tfoot .tablesorter-headerAsc,.tablesorter-default tfoot .tablesorter-headerDesc,.tablesorter-default tfoot .tablesorter-headerSortDown,.tablesorter-default tfoot .tablesorter-headerSortUp{border-top:#000 2px solid}.tablesorter-default td{background-color:#fff;border-bottom:#aaa 1px solid;padding:4px;vertical-align:top}.tablesorter-default tbody>tr.even:hover>td,.tablesorter-default tbody>tr.odd:hover>td,.tablesorter-default tbody>tr:hover>td{background:#BBB;color:#000}.tablesorter-default tbody tr.normal-row td{background:#fff;padding:12px 16px}.tablesorter-default tbody tr.alt-row td{background:#f2f2f2;padding:12px 16px}.tablesorter-default tr.odd td{background-color:#dfdfdf}.tablesorter-default tr.even td{background-color:#efefef}.tablesorter-default tr.odd td.primary{background-color:#bfbfbf}.tablesorter-default td.primary,.tablesorter-default tr.even td.primary,.tablesorter-default tr.odd td.secondary{background-color:#d9d9d9}.tablesorter-default td.secondary,.tablesorter-default tr.even td.secondary,.tablesorter-default tr.odd td.tertiary{background-color:#e6e6e6}.tablesorter-default td.tertiary,.tablesorter-default tr.even td.tertiary{background-color:#f2f2f2}caption{background:#fff}.tablesorter-default .tablesorter-filter-row td{background:#eee;border-bottom:#ccc 1px solid;line-height:normal;text-align:center;-webkit-transition:line-height .1s ease;-moz-transition:line-height .1s ease;-o-transition:line-height .1s ease;transition:line-height .1s ease}.tablesorter-default .tablesorter-filter-row .disabled{opacity:.5;cursor:not-allowed}.tablesorter-default .tablesorter-filter-row.hideme td{padding:2px;margin:0;line-height:0;cursor:pointer}.tablesorter-default .tablesorter-filter-row.hideme .tablesorter-filter{height:1px;min-height:0;border:0;padding:0;margin:0;opacity:0}.tablesorter-default .tablesorter-filter{width:95%;height:auto;margin:4px;padding:4px;background-color:#fff;border:1px solid #bbb;color:#333;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:height .1s ease;-moz-transition:height .1s ease;-o-transition:height .1s ease;transition:height .1s ease}.tablesorter .filtered{display:none}.tablesorter .tablesorter-errorRow td{text-align:center;cursor:pointer;background-color:#e6bf99}.tablesorter-search-highlight{font-weight:700}.scrolling-table{width:700px}.scrolling-table .scroll-viewport{height:200px!important;width:99.5%!important;background-color:#fff}.scrolling-table .scroll-overview{margin-top:-14px!important}.scrolling-table .scroll-viewport:hover{background-color:#fff}.scrolling-table #att-scroll-table-content{height:200px;position:absolute!important;width:700px;padding-left:0;padding-top:0;padding-bottom:0;padding-right:5px}.icon--button{display:inline-block;margin-left:-6px;background-color:#fff;border:1px solid #888;height:40px;width:40px;line-height:39px;text-align:center;cursor:pointer;font-size:20px}.icon--button a{color:#888}.icon--button.first,.icon--button:first-child{border-radius:6px 0 0 6px}.icon--button.last,.icon--button:last-child{border-radius:0 6px 6px 0}.icon--button:hover{background-color:#bbb}.icon--button:hover>a{color:#444}.icon--button:active{background-color:#0574AC}.icon--button:active>a{color:#fff}.icon--button.active--button{background-color:#0574AC}.icon--button.active--button>a{color:#fff}.icon--button.icon--button__small{height:30px;width:34px;line-height:29px;font-size:14px}.icon--button__single-dropdown{font-size:14px;font-size:.875rem;display:inline-block;background-color:#fff;border:1px solid #888;height:30px;width:53px;line-height:29px;border-radius:6px;cursor:pointer}.icon--button__single-dropdown:after{font-size:14px;font-size:.875rem;font-family:"Ionicons";content:'\f104';color:#888;margin-left:-4px}.icon--button__single-dropdown:after:hover:after{color:#444}.icon--button__single-dropdown:after:active:after{content:"\f10d";color:#0091d9}.icon--button__single-dropdown a{color:#888;padding-left:10px}.icon--button__single-dropdown:hover{background-color:#bbb}.icon--button__single-dropdown:hover>a{color:#444}.icon--button__single-dropdown:active{background-color:#fff;border-radius:6px 6px 0 0;border-top:1px solid #0091d9;border-left:1px solid #0091d9;border-right:1px solid #0091d9;border-bottom:1px solid #bbb}.icon--button__single-dropdown:active>a{color:#0574AC}.icon--button__dropdown-list{position:absolute;display:none}.icon--button__dropdown-list ul{left:-webkit-calc("-100% + 52px");left:-moz-calc("-100% + 52px");left:calc("-100% + 52px");position:relative;list-style:none;margin-left:0;margin-top:-1px;padding-left:0;border-radius:6px 0 6px 6px;border:1px solid #0091d9}.icon--button__dropdown-list ul li{font-size:12px;text-align:left;height:30px;padding:0 10px}.icon--button__dropdown-list ul li a{color:#888;line-height:30px;padding:0}.icon--button__dropdown-list ul li:hover{background-color:#0091d9}.icon--button__dropdown-list ul li:hover>a{color:#fff}.section-toggle{border-top:1px solid #888;text-align:center}.section-toggle--disabled{border-top-color:#d3d3d3}.section-toggle__button{font-size:12px;font-size:.75rem;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;background:#fff;border-radius:0 0 3px 3px;border:1px solid #888;color:#444;cursor:pointer;margin:0 auto;padding:5px 10px;position:relative;text-align:center;top:-1px}.section-toggle__button:hover{border-color:#0091d9}.section-toggle__button:active{outline:0}.section-toggle__button:focus{outline:1px solid #39b1ec;outline-offset:2px;text-decoration:none}.section-toggle__button .icon-chevron-down,.section-toggle__button .icon-chevron-up{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle}.section-toggle--disabled .section-toggle__button{display:none}.icons-list{list-style:none;margin:20px 0 0;padding:0;font-size:0}.icons-list li{font-size:14px;display:inline-block;width:20%;box-sizing:border-box;vertical-align:top;padding:20px;margin-bottom:20px;cursor:default;min-height:130px;position:relative;overflow:hidden;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out}.icons-list li:hover{background:#fff;color:#199DDF;border-color:#d3d3d3}.icons-list [class*=icon]{display:inline-block;vertical-align:middle;-webkit-transition:font-size .2s ease-out;-moz-transition:font-size .2s ease-out;transition:font-size .2s ease-out}.icons-list[data-size=small] [class*=icon]{font-size:14px}.icons-list[data-size=medium] [class*=icon]{font-size:28px}.icons-list[data-size=large] [class*=icon]{font-size:56px}.icons-list.small-icons [class*=icon]{font-size:56px!important}.icons-list li [class*=icon]:hover{outline:1px dotted #444;color:#199DDF}.icons-list [data-role=title]{font-family:clearview_att_regular;font-size:14px;margin-top:15px;display:block}.icons-list[data-display=list] li{display:block;margin-bottom:0;width:100%;min-height:0}.icons-list[data-display=list] [data-role=title]{display:inline-block;vertical-align:middle;margin:0;margin-left:15px}.icons-list [data-role=css-class]{display:none;font-size:11px;background:rgba(0,0,0,.8);color:#fff;margin-top:10px;text-align:center;box-sizing:border-box;position:absolute;left:0;right:0;bottom:-30px;padding:0 10px;height:25px;padding-top:7px;white-space:nowrap;overflow-x:auto;-webkit-transition:bottom .2s ease-out;-moz-transition:bottom .2s ease-out;transition:bottom .2s ease-out}.icons-list li:hover [data-role=css-class]{bottom:0}.icons-list[data-display=list] [data-role=css-class]{left:auto;top:50%;right:25px;margin-top:-12px;background:#d3d3d3;color:#444;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.show-dev-notes .icons-list [data-role=css-class]{display:block}.icons-list [data-role=css-class]::selection{background:#666}.icons-list[data-display=list] [data-role=css-class]::selection{background:#d3d3d3}.label-icon{display:block}.tabs-icon.tabs>li a{height:40px;line-height:40px;font-size:14px}.dragdrop{border:1px dashed #bbb;border-radius:5px;padding:0;text-align:center;color:#bbb;position:relative}.dragdrop-over{background:#0091d9;color:#006496}.dragdrop-over:after{content:"Drop the file";color:#fff;width:80px;height:20px;overflow:hidden;margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}.fileContainer{position:relative;overflow:hidden;display:inline-table;font-weight:400}.fileContainer [type=file]{position:absolute;cursor:inherit;display:block;font-size:0;opacity:0;height:0;width:0;left:0;top:0;-ms-filter:"alpha(Opacity=0)"}.att-table-message .img-magnify-glass{background:url(images/magnify_glass.png) center center no-repeat;height:50px}.att-table-message .img-oops-exclamation{background:url(images/oops-exclamation.png) center center no-repeat;height:50px}.att-table-message .img-loading-dots{background:url(images/loading_dots.gif) center center no-repeat;height:50px}.att-table-message .message{text-align:center;padding-top:40px;border-style:solid;border-width:1px;border-top:0;padding-bottom:45px;border-color:#d2d2d2;width:100%;min-height:220px}.att-table-message .loading-message{background:#f2f2f2;background:rgba(242,242,242,.5)}.att-table-message .error-title{font-family:omnes_att_regular,Fallback,sans-serif;font-size:24px;color:#444;line-height:26px}.att-table-message .title{font-size:24px;color:#444;font-family:omnes_att_regular}.att-user-message .hidden{visibility:hidden}.att-user-message .message-wrapper-success{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;opacity:.95;background-color:#fff;-webkit-box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);-moz-box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);float:right;margin-top:-50px;min-width:220px;max-width:360px;max-height:196px;border:solid #54AD18 1px}.att-user-message .message-wrapper-error{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;opacity:.95;background-color:#fff;-webkit-box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);-moz-box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);box-shadow:0 6px 6px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.3);float:right;margin-top:-50px;min-width:220px;max-width:360px;max-height:196px;border:solid #FE9E0C 1px}.att-user-message .message-icon-success{float:left;margin-top:10px;margin-left:10px;margin-right:10px;font-size:27px;color:#54AD18}.att-user-message .message-icon-error{float:left;margin-top:10px;margin-left:10px;margin-right:10px;font-size:27px;color:#FE9E0C}.att-user-message .message-title-success{font-family:clearview_att_regular;font-size:18px;line-height:15px;word-wrap:break-word;width:100%;color:#008A06}.att-user-message .message-title-error{font-family:clearview_att_regular;font-size:18px;line-height:15px;word-wrap:break-word;width:100%;color:#EF6F00}.att-user-message .message-body-wrapper{max-width:280px;margin-top:15px;margin-right:20px;margin-bottom:15px;float:left}.att-user-message .message-msg{color:#444;font-family:clearview_att_regular;font-size:12px;line-height:15px;margin-top:3px;margin-bottom:15px;word-wrap:break-word}.text-ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-ms-text-overflow:ellipsis;display:block;width:45%}.pane-group{height:100%;width:100%;border:1px solid #D3D3D3;border-radius:3px;background-color:#FFF}.pane-group .side-pane{position:relative;width:33%;height:100%;float:left}.pane-group .side-pane .header{padding:20px;font-family:Arial;font-size:14px;color:#444;line-height:20px}.pane-group .side-pane .body div{line-height:20px;font-family:clearview_att_regular;font-size:14px;color:#444;padding-top:10px;padding-bottom:10px;padding-left:20px}.pane-group .side-pane .body div:hover{background-color:#067AB4;cursor:pointer;color:#FFF}.pane-group .inner-pane{position:relative;display:none;width:300px;height:100%;border-left-width:1px;border-right-width:1px;border-left-style:solid;border-right-style:solid;border-color:#D3D3D3;float:left}.pane-group .inner-pane .header{padding:20px;font-family:Arial;font-size:14px;color:#444;line-height:20px}.pane-group .inner-pane .body div{line-height:20px;font-family:clearview_att_regular;font-size:14px;color:#444;padding-top:10px;padding-bottom:10px;padding-left:20px}.pane-group .inner-pane .body div:hover{background-color:#067AB4;cursor:pointer;color:#FFF}.pane-account-selector{width:940px;height:435px;margin-left:10%}.pane-account-selector .line{margin-left:20px;margin-right:20px}.pane-account-selector .side-pane .body .side-row-selected{background-color:#067AB4;color:#FFF}.pane-account-selector .side-pane .body .side-row-selected .chevron-mark{color:#FFF}.pane-account-selector .side-pane .body .chevron-mark{float:right;margin-right:10px;color:#067AB4}.pane-account-selector .side-pane .body div:hover .chevron-mark{color:#FFF}.pane-account-selector .inner-pane{height:434px}.pane-account-selector .inner-pane .header .form-field{width:100%;min-width:190px;max-width:270px;margin-top:10px}.pane-account-selector .inner-pane .header a{font-size:12px;font-family:clearview_att_regular;text-decoration:underline;color:#067AB4}.pane-account-selector .inner-pane .header .verticalLine{border-left:2px solid #D3D3D3;padding-left:2px;padding-right:4x}.pane-account-selector .inner-pane .body .chevron-mark{float:right;margin-right:20px;margin-left:20px;color:#067AB4}.pane-account-selector .inner-pane .body div:hover .chevron-mark{color:#FFF}.pane-account-selector .inner-pane .body .att-radio,.pane-account-selector .inner-pane .body .att-radio__indicator{padding:0}.pane-account-selector .inner-pane hr{margin-top:0;margin-bottom:0}.att-drawer{background-color:#fff;box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3);-webkit-box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3);-moz-box-shadow:0 4px 5px rgba(0,0,0,.2),inset 0 1px rgba(0,0,0,.3)}.drawer-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(255,255,255,.6);z-index:999}.loading_div{display:block;margin:10px 0}.typeahead span[tag-badges]{margin-right:5px}.typeahead .tag{margin:0}.typeahead.mainContainerOuter{position:relative;margin-top:35px}.typeahead .maincontainer{text-align:left;width:700px;border:1px solid #888;border-radius:5px;background:#FFF;max-height:220px;overflow:auto;padding:8px 10px 7px;margin-top:3px}.typeahead .maincontainer:focus{border:1px solid #0091d9}.typeahead .typeahed_active{border:1px solid #0574ac}.typeahead .maincontainer>br{display:none}.typeahead .maincontiner>span{font-size:15px;display:inline-block;padding-right:10px}.typeahead input{padding:5px!important;font-size:14px!important;outline:0!important;background:transparent!important;width:auto!important;border:0!important;height:25px!important}.typeahead ::-ms-clear{display:none}.typeahead .item{width:100%;box-sizing:border-box;margin:auto;text-align:left;height:30px;background:#FFF;padding:4px}.typeahead .item.title{font-size:18px;font-weight:700}.typeahead .subtitle{font-size:14px;color:#444}.typeahead .active{background-color:#4180C4;color:#f2f2f2}.typeahead .filtercontainer{position:absolute;left:0;margin-top:-5px;max-height:160px;overflow:auto;width:100%;background:#FFF;z-index:999;border-radius:0 0 5px 5px;border:1px solid #0091d9}.typeahead .dynamiccss{width:120px;height:30px;border:2px #000 solid;display:inline;margin-left:2px}.typeahead .textAreaEmailContent{font-size:14px;height:80px;line-height:20px;color:#444;width:700px;font-family:clearview_att_regular;margin-top:3px;padding:10px}.typeahead .btnEmailSend{margin-top:70px}.typeahead .message{font-size:12px;line-height:20px;color:#444;font-family:clearview_att_regular}.typeahead .textAreaEmailContentDiv{margin-top:17px}.att-modal__close.typeahead-close{position:absolute;left:initial;bottom:initial;right:0;top:0;color:#000}.typeahead-modal-container{position:relative;width:700px;margin:30px auto}.typeahead-heading{font-size:36px;line-height:20px;color:#444;font-family:omnes_att_light;margin:0}.typeahead-paragraph{font-size:14px;line-height:20px;color:#444;font-family:clearview_att_regular;margin-top:7px;margin-bottom:0}.typeahead-modal-footer{padding-top:40px}.type_ahead-cancel{margin-left:10px}.tabs_overlay{list-style:none;margin:0;padding:0;font-size:0;display:block;border:1px solid #888;border-radius:3px}.tabs_overlay .tabs_overlay__item{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:18px;font-size:1.125rem;padding:10px 15px;border-left:1px solid #d3d3d3}.tabs_overlay .tabs_overlay__item.two__item{width:50%}.tabs_overlay .tabs_overlay__item.three__item{width:33.3%}.tabs_overlay .tabs_overlay__item.active{background-color:#0574AC;color:#fff}.tabs_overlay .tabs_overlay__item.active .icon-included-checkmark,.tabs_overlay .tabs_overlay__item.active .icon-orders,.tabs_overlay .tabs_overlay__item.active a.viewLink{color:#fff}.tabs_overlay .tabs_overlay__item a.viewLink{float:right;padding-top:2px;font-size:14px;font-size:.875rem}.tabs_overlay .tabs_overlay__item .icon-orders{color:#0574AC}.tabs_overlay .tabs_overlay__item .icon-included-checkmark{color:#4ca90c}.tabbedOverlay_modal{background:none repeat scroll 0 0 #f2f2f2;opacity:.91}.tabbedOverlay_modal .modal__main{color:inherit;padding:0;width:936px;background:0 0;border:0;border-radius:none;box-shadow:none;margin:5% auto}.tabbedOverlay_modal .modal__content{width:100%;background-color:#fff;display:inline-block;padding:0;margin-top:30px}.tabbedOverlay_modal .modal__content .body__content{padding:20px 8px}.tabbedOverlay_modal .icon-circle-action-close{font-size:28px}.tabbedOverlay_modal .icon-trash{font-size:14px;color:#0574AC;border:solid 1px #0574AC;border-radius:6px;padding:5px}.att-boardstrip{display:inline-block;width:100%;border-bottom:1px solid #9d9d9d;position:relative;padding-top:15px}.att-boardstrip .boardstrip-reel{margin-bottom:15px}.att-boardstrip .boardstrip-item--add{border:1px dashed #CCC!important;background:#F2F2F2;color:#444545;width:140px;height:80px;font-size:12px;font-family:clearview_att_regular;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:absolute;left:50px;top:15px}.att-boardstrip .boardstrip-item--add:hover{background-color:#39b1ec;cursor:pointer;color:#fff}.att-boardstrip .boardstrip-item--add i{font-size:30px;margin-left:auto;margin-right:auto}.att-boardstrip .boardstrip-item--add .centered{margin-left:auto;margin-right:auto;margin-top:8px;margin-bottom:-12px;display:block}.att-boardstrip .board-viewport{float:left;margin-left:210px;max-height:95px;position:relative;height:95px;overflow:hidden;width:0}.att-boardstrip .board-viewport .boardstrip-container{width:0;margin-left:0;left:0;position:absolute;list-style:none;-webkit-transition:left 1000ms;-moz-transition:left 1000ms;transition:left 1000ms}.att-boardstrip .board-viewport .board-item{width:140px;height:80px;border:1px solid #000;margin:0 15px 15px 0;background-color:#efefef;border-radius:3px;float:left;overflow:hidden}.att-boardstrip .board-viewport .board-item:focus,.att-boardstrip .board-viewport .board-item:hover{border:2px solid #0091d9;background-color:#fff;cursor:pointer}.att-boardstrip .board-viewport .board-item .board-img{width:61px;height:40px;margin:0 auto}.att-boardstrip .board-viewport .board-item .board-img img{max-width:100%}.att-boardstrip .board-viewport .board-item .title{margin:0 auto;display:block;text-align:center;line-height:16px;color:#555545;font-size:12px;font-family:clearview_att_regular;padding:10px 0}.att-boardstrip .board-viewport .board-item.selected{background-color:#fff;border:2px solid #0091d9}.att-boardstrip .board-viewport .board-item .board-caret{cursor:default;outline:0;position:absolute;bottom:7px}.att-boardstrip .board-viewport .board-item .board-caret .board-caret-indicator{border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #999;width:0;height:0;position:absolute;left:61px;bottom:-7px}.att-boardstrip .board-viewport .board-item .board-caret .board-caret-arrow-up{width:0;height:0;border-style:solid;border-width:0 8px 8px;border-color:transparent transparent #f2f2f2;left:61px;position:absolute}.att-boardstrip .arrow{font-size:32px;cursor:pointer}.att-boardstrip .arrow:hover{color:#0091d9}.att-boardstrip .prev-items{display:inline-block;margin-top:auto;margin-bottom:auto;margin-right:15px;margin-right:15px;position:absolute;left:0;top:36px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.att-boardstrip .next-items{display:inline-block;margin-top:auto;margin-bottom:auto;margin-left:15px;position:absolute;right:0;top:36px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.att-boardstrip .centered{display:table-cell;text-align:center;vertical-align:middle}.content{color:#444}section{margin-bottom:60px}a:hover{text-decoration:none}a:focus{outline:-webkit-focus-ring-color auto 5px}h2,h3,h4{margin:0 0 20px}h2{font-family:'Helvetica Neue',Helvetica;font-size:36px;font-size:2.25rem}h3{font-size:18px;font-size:1.125rem;font-weight:400}h4{font-size:14px;font-size:.875rem;font-weight:600;margin:0}dl{margin:5px 0 20px}dd,dt{display:inline-block;margin:0;width:80px}dd{width:150px}.font-clearview p{font-size:12px;font-size:.75rem;line-height:20px}.row{position:relative}.section-row{padding:20px 0;position:relative}.section-row:first-child{padding-top:0}.section-row:first-child h2{margin-top:-5px}.section-row h4{text-transform:uppercase}.section-description{line-height:20px}.section-row-description{font-size:12px;font-size:.75rem;line-height:18px;margin:5px 0}.section-row-description+.section-row-description{margin-top:20px}.section-buttons,.section-download-button{margin-top:5px;position:absolute;right:10px}.section-image{margin:20px 0;width:100%}.font-face-showcase{font-size:44px;font-size:2.75rem;line-height:54px;margin:20px 0}#pill-buttons{background:url(images/pill-buttons-diagram.png) 360px 50px no-repeat}#pill-buttons h2{margin-top:0}#pill-buttons .section-row .icon-cross{color:#888;font-size:30px;font-size:1.875rem}.colored-buttons-wrapper{margin-bottom:40px}.colored-buttons-container{-webkit-transition:background .3s ease-out;-moz-transition:background .3s ease-out;transition:background .3s ease-out;margin:0 0 20px;overflow:hidden;padding:20px 0}#forms{background:url(images/forms-diagram.png) 360px 100px no-repeat}.switches label{display:inline-block;margin:10px 0 15px;text-align:center;width:100%}.switches .span2{text-align:center}.dev-notes{background:#eaeaea;border-radius:3px;display:none;margin-bottom:50px;padding:20px}.show-dev-notes .dev-notes{display:block}.dev-notes .tabs{margin-top:20px}.dev-notes .tabs li a{background:#aaa;border:0;border-bottom:0;border-radius:0;color:#333;font-family:clearview_att_regular;font-size:10px;font-size:.625rem;height:auto;line-height:18px;margin-left:2px;padding:5px 15px 2px}.dev-notes .tabs li:first-child a{margin-left:0}.dev-notes .tabs li:hover a{background:#181818}.dev-notes .tabs li.active a{background:#272822}.dev-notes .tabs li.active a,.dev-notes .tabs li:hover a{color:#fff}pre.line-numbers{background-color:#272822;border-radius:0 0 3px 3px;border:0;margin:0;padding-bottom:30px;padding-left:50px;padding-top:30px;word-wrap:normal}pre.line-numbers.with-example{border-radius:0 0 3px 3px;overflow:visible;padding-bottom:10px;padding-left:40px;position:relative}pre.notes{padding-top:0;padding-bottom:0}.dev-notes-header{margin:0 0 10px;z-index:10;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.dev-notes.with-tabs .dev-notes-header{margin:0;padding-bottom:0}.dev-notes .title,.dev-notes p{margin:10px 0 0;color:#777;font-size:12px;font-size:.75rem}.dev-notes p:first-of-type{margin-top:0}.dev-notes .title{font-weight:600;margin:0 0 5px}.dev-notes .title:before{content:'Dev Notes: '}.dev-notes .close{position:absolute;top:0;right:0;color:#777;font-size:12px;font-size:.75rem;padding:7px 0 7px 10px;text-align:right}.dev-notes .close:hover{color:#F9432C}.dev-notes-example-title{margin:0 0 10px;color:#777}.dev-notes-wrapper{margin:0;background:#272822;padding:20px;border-radius:0 3px 3px}.dev-notes-example{margin:0;padding:20px;background:#fff;position:relative;overflow:hidden}.dev-notes-example:last-child{margin-bottom:0}.dev-notes-js-link{position:absolute;right:10px;top:10px;font-family:clearview_att_regular;font-size:10px;font-size:.625rem;color:#444;padding:5px;background:#ddd;border:1px solid #ccc;border-radius:3px}.dev-notes-js-link:hover{background-color:#fff}.navbar .body-color-selector>a{color:#6f6f6f}.navbar .body-color-selector-item{height:50px;padding:0 10px;-moz-box-sizing:border-box;box-sizing:border-box}.navbar .body-color-selector-color{text-indent:-9999px;width:25px;height:25px;border-radius:100%;float:right;margin-top:12px;background-color:#DADADA}.body-color-selector-gray .body-color-selector-color{background-color:#DADADA}.body-color-selector-white .body-color-selector-color{background-color:#fff}.font-showcase-row>[class*=span]:first-child{border-top:1px solid #d3d3d3;padding-top:35px}.font-showcase-row h4{font-family:Arial;font-size:12px;font-size:.75rem;font-weight:100;text-transform:uppercase}h4.font-showcase-font-example,h4.font-showcase-font-name{text-transform:none}.font-showcase-info{font-family:clearview_att_regular;font-size:12px;font-size:.75rem;color:#888}.h6 .font-showcase-info{margin-top:-10px}.font-showcase-row .section-row-description{margin-bottom:20px}.font-showcase-row.display-prices .right-col .size-half{margin-bottom:15px}.font-showcase-row .display-prices-small{margin-top:30px}.font-showcase-details .details-label{margin-top:22px}.color-circle{display:inline-block;width:100px;height:100px;border-radius:100%}.next-section-link{margin-top:50px;display:inline-block;text-decoration:none;border-bottom:1px solid transparent}.next-section-link:hover{color:#FC411E;border-bottom-color:#FC411E;text-decoration:none}.next-section-link:after{content:'\e6da';font-family:"Ionicons";font-size:12px;font-size:.75rem;margin-left:5px}#breadcrumbs .section-row{padding-top:0}#breadcrumbs .section-description{margin:0}#photo-video-controls{background:url(../images/video-photo-controls.png) right 60px no-repeat}#photo-video-controls .section-description{margin-bottom:70px}[data-role=actions-bar]{background:#F2F2F2;position:relative;z-index:1;padding-top:0;padding-bottom:25px;margin-bottom:10px;overflow:hidden}[data-role=actions-bar]:after{content:'';position:absolute;display:block;bottom:0;left:10px;right:10px;border-bottom:1px solid #d3d3d3}.color-white [data-role=actions-bar]{background:#fff}[data-role=actions-bar] label{position:relative}[data-role=actions-bar] label span{text-transform:none;font-size:10px;font-size:.625rem}#iconography.affix{position:relative;padding-top:87px}#iconography.affix [data-role=actions-bar]{width:720px;top:50px;z-index:1;position:fixed;padding-top:35px;padding-bottom:25px}#total-icons-found{position:absolute;right:0}#iconography .section-row:first-child h2{margin-bottom:0}.columns{font-size:0}.columns.text-center{margin:0 auto}.col{display:inline-block;vertical-align:top;font-size:14px;font-size:.875rem;box-sizing:border-box}.size-col-10,.size-full{width:100%}.size-twofifths{width:40%}.size-threefifths{width:60%}.size-fourfifths{width:90%}.size-col-1,.size-onetenth{width:10%}.size-col-2,.size-twotenths{width:20%}.size-col-3,.size-threetenths{width:30%}.size-col-4,.size-fourtenths{width:40%}.size-col-5,.size-fivetenths{width:50%}.size-col-6,.size-sixtenths{width:60%}.size-col-7,.size-seventenths{width:70%}.size-col-8,.size-eighttenths{width:80%}.size-col-9,.size-ninetenths{width:90%}.no-margin{margin:0}.pull-right{float:right}.pull-left{float:left}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-uppercase{text-transform:uppercase}.text-underline{text-decoration:underline}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}.font-clearview{font-family:clearview_att_regular}.font-omnes{font-family:omnes_att_regular}.font-omnes-light{font-family:omnes_att_light}.note{font-size:12px;font-size:.75rem;color:#ff3000}.size-full{width:100%}.size-half{width:50%}.size-onethird{width:33.333333%}.size-twothirds{width:66.666666%}.size-onefourth{width:25%}.size-onefifth{width:20%}.size-onesixth{width:16.666666%}.size-oneseventh{width:14.285714%}.size-oneeighth{width:12.5%}.size-onenineth{width:11.111111%}.size-onetenth{width:10%}.bg-color-primary{background-color:#067ab4}.bg-color-primary-hover{background-color:#199ddf}.bg-color-text{background-color:#444}.bg-color-inactive{background-color:#ddd}.bg-color-uielements{background-color:#777}.bg-color-table-hover{background-color:#e5e5e5}.bg-color-subtle-hover{background-color:#bbb}.bg-color-background{background-color:#ddd}.bg-color-buynow{background-color:#ff7200}.bg-color-warning{background-color:#fcb134}.bg-color-error{background-color:#ff4539}.bg-color-success{background-color:#6ebb1f}.text-color-primary{color:#067ab4}.text-color-primary-hover{color:#199ddf}.text-color-text{color:#444}.text-color-inactive{color:#ddd}.text-color-uielements{color:#777}.text-color-table-hover{color:#e5e5e5}.text-color-subtle-hover{color:#bbb}.text-color-background{color:#ddd}.text-color-buynow{color:#ff7200}.text-color-warning{color:#fcb134}.text-color-error{color:#ff4539}.text-color-success{color:#6ebb1f}.align-right{margin-left:0!important;left:-100%!important;right:0!important}.align-left{left:-1px!important;right:0!important;margin-left:0!important;border-top-right-radius:6px!important;border-top-left-radius:0!important}#horizontalScroll{height:80px;width:100px;border:1px solid #000;overflow-y:hidden}#horizontalScroll #dynamicWidth{border:0}#horizontalScroll div{width:40px;height:100%;border:1px dashed #000}#utilities ul{height:80px;width:100px;border:1px solid #000;margin-left:0}#utilities .accessibility-div{min-width:100px;min-height:100px;width:100px;height:100px;border:1px solid #000}#utilities .circle{display:block;max-width:40px;max-height:40px;padding:11px 0;-moz-box-sizing:border-box;box-sizing:border-box;background:#e5e5e5;border-radius:20px;position:relative;line-height:15px;color:#999;text-align:center;border:1px solid transparent;cursor:pointer}#utilities .circle span{display:block;font-size:10px;line-height:10px;text-align:center;color:#999;border:1px solid #999;position:absolute;height:18px;width:65px;top:18px;left:0;padding-top:20px;cursor:pointer}#utilities .color-on-focus:focus{background:#0574AC;border-color:#fff} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/tbs.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/tbs.css
deleted file mode 100644
index 98202e6a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ebz/sandbox/styles/tbs.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "UTF-8";address,blockquote,dd,h1,h2,h3,h4,h5,h6,ol,p,pre,table,ul{margin:0;padding:0;margin-bottom:24px;margin-bottom:1.5rem}html{font-size:1em;line-height:1.5}body{margin:0}h1{font-size:48px;font-size:3rem;line-height:1}h2{font-size:36px;font-size:2.25rem;line-height:1.3333333333}h3{font-size:30px;font-size:1.875rem;line-height:1.6}h4{font-size:24px;font-size:1.5rem;line-height:1}h5{font-size:20px;font-size:1.25rem;line-height:1.2}h6{font-size:18px;font-size:1.125rem;line-height:1.3333333333}dd,ol,ul{margin-left:48px;margin-left:3rem}li>ol,li>ul{margin-bottom:0}code,kbd,pre,samp{font-family:monospace,monospace}blockquote{text-indent:-.41em;quotes:"“" "â€";margin-left:48px;margin-left:3rem}blockquote p:before{content:"“";content:open-quote}blockquote p:after{content:"";content:no-close-quote}blockquote p:last-of-type:after{content:"â€";content:close-quote}q{quotes:"‘" "’" "“" "â€"}q:before{content:"‘";content:open-quote}q:after{content:"’";content:close-quote}q q:before{content:"“";content:open-quote}q q:after{content:"â€";content:close-quote}q:first-child{display:inline-block;text-indent:-.22em}table{width:100%;border-collapse:collapse;border-spacing:0}td,th{padding:12px}#grid{position:absolute;top:0;left:50%;width:980px;margin-left:-490px;counter-reset:section;z-index:9999!important;pointer-events:none;outline:1px solid rgba(0,206,209,.1)}#grid:after{position:fixed;top:0;left:0;content:'Column: 20px Gutter: 20px Margin: 20px';display:block;max-width:90px;padding:3px;background-color:#000;color:#fff;font-size:10px;font-family:monospace;z-index:9999}#grid div.vert{width:20px;outline:solid rgba(0,206,209,.3);outline-width:1px;margin-right:20px;position:relative;background:rgba(255,0,0,.05);counter-increment:section}#grid div.vert.first-line{margin-left:20px}#grid div.vert::after{position:fixed;display:block;text-align:center;color:#fff;width:20px;content:counter(section);top:5px;font-size:8px;font-family:monospace}#grid div.vert:nth-child(24){position:absolute;top:0;right:0}#grid div.vert:nth-child(1),#grid div.vert:nth-child(10),#grid div.vert:nth-child(11),#grid div.vert:nth-child(12),#grid div.vert:nth-child(13),#grid div.vert:nth-child(14),#grid div.vert:nth-child(15),#grid div.vert:nth-child(16),#grid div.vert:nth-child(17),#grid div.vert:nth-child(18),#grid div.vert:nth-child(19),#grid div.vert:nth-child(2),#grid div.vert:nth-child(20),#grid div.vert:nth-child(21),#grid div.vert:nth-child(22),#grid div.vert:nth-child(23),#grid div.vert:nth-child(24),#grid div.vert:nth-child(3),#grid div.vert:nth-child(4),#grid div.vert:nth-child(5),#grid div.vert:nth-child(6),#grid div.vert:nth-child(7),#grid div.vert:nth-child(8),#grid div.vert:nth-child(9){display:inline-block!important}#grid div.vert:nth-child(25),#grid div.vert:nth-child(26),#grid div.vert:nth-child(27),#grid div.vert:nth-child(28),#grid div.vert:nth-child(29),#grid div.vert:nth-child(30),#grid div.vert:nth-child(31){display:none!important}#grid div.horiz{height:10px;border-bottom:1px dotted rgba(100,100,100,.2);margin:0;padding:0}.bg-prime-blue{background-color:#067ab4}.bg-secondary-gray{background-color:#666}.bg-light-blue{background-color:#bcc9d5}.bg-dark-gray{background-color:#444}.bg-dusty-blue{background-color:#97b1cf}.bg-warm-gray{background-color:#cccb9b}.bg-taupe{background-color:#cccb6c}.bg-green-highlight{background-color:#c4d63f}.bg-lime-highlight{background-color:#dad632}.bg-purple-highlight{background-color:#b6539c}.bg-magenta{background-color:#d71481}.bg-blue-highlight{background-color:#4cc8f3}.bg-ochre{background-color:#fab230}.bg-green{background-color:#4fa721}.bg-lime{background-color:#b6bd26}.bg-purple{background-color:#7f0e7c}.bg-burgundy{background-color:#b1103e}.bg-dark-blue{background-color:#0e2875}.bg-gold{background-color:#fd9827}.bg-teal{background-color:#20c6b2}.bg-mint-green{background-color:#9cfecd}.bg-yellow{background-color:#feed35}.bg-white{background-color:#fff}.alt.inline-list>li{display:inline-block;zoom:1;*display:inline;*vertical-align:auto;vertical-align:middle;float:none}.text-upper{text-transform:uppercase!important}body{font-family:clearview_att_regular}.font-showcase h1,.font-showcase h2,.font-showcase h3,.font-showcase h4,.font-showcase h5,.font-showcase h6{font-weight:100;letter-spacing:-1px;margin:10px 0;-webkit-font-smoothing:antialiased}.font-showcase h1{font-family:omnes_att_light;font-size:48px;font-size:3rem;line-height:48px}.font-showcase h2,.price{font-family:omnes_att_light;font-size:36px;font-size:2.25rem;line-height:36px}.font-showcase h3{font-family:omnes_att_regular;font-size:24px;font-size:1.5rem;line-height:28px}.font-showcase h4,.font-showcase h4.font-showcase-font-example,.font-showcase h4.font-showcase-font-name{font-family:clearview_att_regular;font-size:18px;font-size:1.125rem;line-height:22px;-webkit-font-smoothing:antialiased}.font-showcase h5{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.font-showcase h6{font-family:Arial;font-size:11px;font-size:.6875rem;line-height:30px;font-weight:100;-webkit-font-smoothing:antialiased}.body-copy,.font-showcase p{font-family:clearview_att_regular;font-size:14px;font-size:.875rem;line-height:20px;-webkit-font-smoothing:antialiased}.body-copy-short{font-family:clearview_att_regular;font-size:12px;font-size:.75rem;line-height:15px;-webkit-font-smoothing:antialiased}p [class*=icon]{display:inline-block;vertical-align:middle;margin-top:-4px}.details-label{display:block;font-family:clearview_att_regular;font-size:11px;font-size:.6875rem;line-height:15px}.details-label+.price{line-height:28px}.price{letter-spacing:-1px;-webkit-font-smoothing:antialiased}.price sup{font-size:18px;font-size:1.125rem;vertical-align:baseline;top:-11px;margin:0 2px}.price-alt{font-size:24px;font-size:1.5rem;line-height:24px}.price-alt sup{font-size:12px;font-size:.75rem;top:-8px}.promo-tagline{font-family:omnes_att_medium_italic;font-size:16px;font-size:1rem;line-height:20px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.promo-text{font-family:clearview_att_italic;font-size:12px;font-size:.75rem;line-height:15px;display:inline-block;margin-bottom:5px;-webkit-font-smoothing:antialiased}.divider,.divider-dark,hr{border:0;border-bottom:1px solid #d3d3d3}.divider-light{border-color:#e5e5e5}dl{font-family:clearview_att_regular;color:#444;font-size:12px;font-size:.75rem}dt{font-family:Arial;font-size:11px;font-size:.6875rem;display:block!important;margin:10px 0 5px!important;width:auto!important;text-transform:uppercase}dt a{font-family:clearview_att_regular;color:#067ab4;text-transform:none}dd{display:inline!important;line-height:20px}[data-highlight]{background-color:#c9e9f9;-webkit-animation:highlight-fade 3s infinite}@-webkit-keyframes highlight-fade{100%,80%{background-color:transparent}}.tabsbid{vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;list-style:none;margin:0;padding:0;font-size:0;display:-webkit-inline-box}.simplified-tabs__item .active{border-bottom:solid 4px #444}.tabsbid--right{float:right}.tabsbid__item{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;padding:0;margin:0}.tabsbid__item-link{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;font-size:14px;font-size:.875rem;background-color:#f2f2f2;border:1px solid #888;color:#666;cursor:pointer;height:40px;line-height:39px;margin:0 0 0 -1px;padding:0 20px;text-align:center;text-decoration:none;text-transform:none;width:auto}.tabsbid__item--first .tabsbid__item-link,.tabsbid__item:first-child .tabsbid__item-link{border-radius:4px 0 0 4px;margin-left:0}.tabsbid__item--last .tabsbid__item-link,.tabsbid__item:last-child .tabsbid__item-link{border-radius:0 4px 4px 0}.tabsbid__item-link:hover{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#b2b2b2;color:#000;text-decoration:none}.tabsbid__item--active .tabsbid__item-link{background-color:#0574AC;border:1px solid #0574AC;color:#fff}.tabsbid--small .tabsbid__item-link{font-size:11px;font-size:.6875rem;padding:0 15px;height:30px;line-height:29px;margin:0 0 0 -5px}.tabsbid--light .tabsbid__item-link{background-color:#fff}.tabsbid--links{text-align:left;border-bottom:1px solid #888}.tabsbid--links .tabsbid__item-link{font-size:14px;font-size:.875rem;background-color:none;border:0;padding:0 15px 0 0}.tabsbid--links .tabsbid__item-link:hover{-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;transition:all .3s ease-out;background:0 0;color:#067ab4;text-decoration:none}.tabsbid--links .tabsbid__item--active .tabsbid__item-link{background:0 0;color:#067ab4}.tabsbid--icons .tabsbid__item--active .tabsbid__item-link,.tabsbid--icons .tabsbid__item-link,.tabsbid--icons .tabsbid__item-link:hover{font-size:28px;font-size:1.75rem;background:0 0;border:0;line-height:36px;margin-right:10px;padding:0}.tabsbid--icons .tabsbid__item-link [class^=icon-]{vertical-align:middle}.tabsbid--icons .tabsbid__item-link:hover{color:#067ab4}.tabsbid__content{width:100%}.tabsbid__pane{display:none}.tabsbid__pane--active{display:block}.tabsbid--image{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;clear:both;float:none;list-style:none;margin:0;padding:20px 0 0;font-size:0}.tabsbid__item--image{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;position:relative}.tabsbid__item--image img{margin:0 auto;opacity:.3}.tabsbid__item--image-title{color:#888}.tabsbid__item--image.tabsbid__item--active img,.tabsbid__item--image:hover img{margin:0 auto;opacity:1}.tabsbid__item--image.tabsbid__item--active .tabsbid__item--image-title,.tabsbid__item--image:hover .tabsbid__item--image-title{color:#067ab4}.tabsbid__item--image .tabsbid__item--image-link,.tabsbid__item--image.tabsbid__item--active{position:relative}.tabsbid__item--image.tabsbid__item--active:after,.tabsbid__item--image.tabsbid__item--active:before{position:absolute;bottom:-24px;left:50%;content:'';margin-left:-8px;border:8px solid transparent;z-index:3}.tabsbid__item--image.tabsbid__item--active:before{bottom:-23px;border-bottom-color:#d3d3d3}.tabsbid__item--image.tabsbid__item--active:after{border-bottom-color:#f2f2f2}.tabsbid__content--image{padding:15px 0;width:100%}.simplified-tabs{background-color:#f2f2f2;position:relative}.simplified-tabs:after{position:absolute;right:0;bottom:0;left:0;border-bottom:1px solid #888;content:''}.simplified-tabs .simplified-tabs__items{border-spacing:30px 0;display:table;list-style:none;margin:0;padding:0;margin-left:-30px;position:relative;table-layout:fixed}.simplified-tabs .simplified-tabs__items:after{position:absolute;right:40px;bottom:0;left:30px;border-bottom:1px solid #888;content:''}.simplified-tabs .simplified-tabs__item{width:auto;height:100%;-webkit-transition:color .15s ease-in-out;-moz-transition:color .15s ease-in-out;transition:color .15s ease-in-out;font-size:14px;font-size:.875rem;display:table-cell;font-family:clearview_att_regular;padding-bottom:17px;position:relative;text-align:center}.simplified-tabs .simplified-tabs__item:before{height:0;width:0;border-color:transparent;border-style:solid;border-width:10px;border-bottom-color:#888;position:absolute;right:0;bottom:0;left:50%;content:'';display:none;margin-left:-11px;z-index:1}.simplified-tabs .simplified-tabs__item:after{height:0;width:0;border-color:transparent;border-style:solid;border-width:10px;border-bottom-color:#f2f2f2;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;position:absolute;right:0;bottom:-1px;left:50%;content:'';display:none;margin-left:-11px;z-index:1}.simplified-tabs .simplified-tabs__item:hover{color:#0091d9;cursor:pointer}.simplified-tabs .simplified-tabs__item a{color:inherit;outline:0;position:relative}.simplified-tabs .simplified-tabs__item a:before{position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;border:1px solid #39b1ec;content:'';opacity:0}.lt-ie9 .simplified-tabs .simplified-tabs__item a:before{content:none}.simplified-tabs .simplified-tabs__item a:focus:before{opacity:1}.lt-ie9 .simplified-tabs .simplified-tabs__item a:focus:before{content:''}.simplified-tabs .simplified-tabs__item.tabs__item--active{color:#0574AC;font-family:Arial}.simplified-tabs .simplified-tabs__item.tabs__item--active:after,.simplified-tabs .simplified-tabs__item.tabs__item--active:before{display:block}.lt-ie9 .simplified-tabs .simplified-tabs__item.tabs__item--active:after,.lt-ie9 .simplified-tabs .simplified-tabs__item.tabs__item--active:before{content:' '}.simplified-tabs+.tabs__content{padding-top:19px}.simplified-tabs .tabs__pointer{width:20px;height:11px;left:-11px}.simplified-tabs .tabs__pointer:before{height:0;width:0;border-color:transparent;border-style:solid;border-width:10px;border-bottom-color:#888;left:-11px}.simplified-tabs .tabs__pointer:after{height:0;width:0;border-color:transparent;border-style:solid;border-width:10px;border-bottom-color:#f2f2f2;left:-11px}.tabs__pointer{width:28px;height:15px;position:absolute;bottom:0;left:-14px;display:none}.tabs__pointer:after,.tabs__pointer:before{content:'';z-index:3}.tabs__pointer:before{height:0;width:0;border-color:transparent;border-style:solid;border-width:14px;border-bottom-color:#6f6f6f;position:absolute;bottom:0;left:-14px}.tabs__pointer:after{height:0;width:0;border-color:transparent;border-style:solid;border-width:14px;border-bottom-color:#f2f2f2;position:absolute;bottom:-1px;left:-14px}.tabs--no-pointer .simplified-tabs__item:after,.tabs--no-pointer .simplified-tabs__item:before,.tabs--no-pointer .tabs__item--image:after,.tabs--no-pointer .tabs__item--image:before{display:none}.gtabs{margin-left:-30px}.gtabs .tabsbid__item{position:relative;bottom:-1px}.gtabs li.tabsbid__item--active{border-bottom:0}.gtabs ul{border-bottom:1px solid #888}.gtabs .tabsbid__item--first .tabsbid__item-link,.tabsbid__item:first-child .tabsbid__item-link{border-radius:4px 0 0}.gtabs .tabsbid__item--last .tabsbid__item-link,.tabsbid__item:last-child .tabsbid__item-link{border-radius:0 4px 0 0}.gtabs .tabsbid__item--active .tabsbid__item-link{background:#f2f2f2;border:1px solid #888;border-bottom:0;color:inherit;z-index:-2}.gtabs .tabsbid__item-link{background:#fff}.gtabs .tabsbid__item-link:hover{background-color:#bbb;color:#000;text-decoration:none}.tabsbid__item a:focus{text-decoration:none}.top-megamenu .megamenu-tabs{background-color:#067ab4;position:relative}.top-megamenu .megamenu-tabs ul{width:980px;margin:0 auto;display:block;list-style:none;padding:0}.top-megamenu .megamenu-tabs ul li{display:inline-block;text-align:left}.megamenu-tabs{background-color:#067ab4;position:relative}.megamenu-tabs ul{width:auto;display:block;list-style:none;padding:0}.megamenu-tabs ul li{display:inline-block;text-align:left}.megamenu-tabs .megamenu__items{border-spacing:30px 0}.megamenu-tabs .megamenu__item{width:auto;height:100%;-webkit-transition:color .15s ease-in-out;-moz-transition:color .15s ease-in-out;transition:color .15s ease-in-out;font-family:clearview_att_regular;font-size:16px;cursor:pointer;padding:13px 0;margin-right:30px;color:#fff}.megamenu-tabs .megamenu__item:hover{color:#BFE7FB;cursor:pointer}.megamenu-tabs .megamenu__item a{font-size:16px;color:#fff}position:relative .megamenu-tabs .megamenu__item a:focus:before{opacity:1}.lt-ie9 position:relative .megamenu-tabs .megamenu__item a:focus:before{content:''}.megamenu-tabs .megamenu__item.skip{text-align:left;text-indent:-9999px;color:transparent}.megamenu-tabs .megamenu__item.skip:focus{color:#fff;text-indent:0}.megamenu-tabs .megamenu__item.tabs__item--active{color:#fff}.megamenu-tabs .megamenu__item.tabs__item--active:after{height:0;width:0;border-color:transparent;border-style:solid;border-width:10px;border-bottom-color:#fff;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;transition:all .2s ease-out;content:'';margin-left:12px;z-index:1;position:absolute;top:35px}.lt-ie9 .megamenu-tabs .megamenu__item.tabs__item--active:after{content:' '}.submenu-tabs{background-color:#fff;position:absolute;width:100%;left:0;top:55px;z-index:999;border-bottom:solid 1px #ddd}.submenu-tabs .megamenu__item{width:auto;height:100%;-webkit-transition:color .15s ease-in-out;-moz-transition:color .15s ease-in-out;transition:color .15s ease-in-out;color:#666;border-bottom:3px solid transparent;margin-right:40px;font-family:clearview_att_regular;font-size:16px;cursor:pointer;padding:14px 0 10px}.submenu-tabs .megamenu__item:hover{color:#444;cursor:pointer;font-family:Arial}.submenu-tabs .megamenu__item a{font-size:16px;color:#000;position:relative}.submenu-tabs .megamenu__item a:focus:before{opacity:1}.lt-ie9 .submenu-tabs .megamenu__item a:focus:before{content:''}.submenu-tabs .megamenu__item.tabs__item--active{color:#fff;font-family:clearview_att_regular}.submenu-tabs .megamenu__item.tabs__item--active:after,.submenu-tabs .megamenu__item.tabs__item--active:before{display:none}.lt-ie9 .submenu-tabs .megamenu__item.tabs__item--active:after{content:' '}.submenu-tabs .sub__menu{position:absolute;z-index:999;left:0;width:100%;top:50px;background-color:#fff}.submenu-tabs .sub__menu .tabsbid__item{display:inline-block;vertical-align:baseline;zoom:1;*display:inline;*vertical-align:auto;width:auto;float:left;margin:20px 0 0;padding-right:20px}.submenu-tabs .sub__menu .tabsbid__item .links-list__item{border:0;color:#000;font-size:12px;font-family:clearview_att_regular}.submenu-tabs .sub__menu .tabsbid__item .links-list__item:hover{color:#199ddf;border:0}.submenu-tabs .sub__menu .tabsbid__item .title{font-family:Arial;font-size:14px}.ie .submenu-tabs .sub__menu{top:51px}.subMenuHover{font-family:Arial!important;color:#444!important;border-bottom:3px solid #067ab4!important;cursor:pointer!important}.skiptoBody{position:absolute;top:-1000px;left:-1000px;height:1px;width:1px;text-align:left;overflow:hidden}a.skiptoBody:focus{height:1px;width:1px;text-align:left;overflow:hidden} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/.gitignore b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/.gitignore
deleted file mode 100644
index 790a4b0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-_site
-.sass-cache
-*.scssc
-*.swp \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/LICENSE b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/LICENSE
deleted file mode 100644
index 18ab118e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Drifty (http://drifty.com/)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/bower.json b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/bower.json
deleted file mode 100644
index 9417a8e4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/bower.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "ignore": [
- "**/.*",
- "builder",
- "node_modules",
- "bower_components",
- "test",
- "tests"
- ],
- "version": "2.0.0",
- "name": "Ionicons",
- "license": "MIT",
- "authors": [
- "Ben Sperry <ben@drifty.com>",
- "Adam Bradley <adam@drifty.com>",
- "Max Lynch <max@drifty.com>"
- ],
- "keywords": [
- "fonts",
- "icon font",
- "icons",
- "ionic",
- "web font"
- ],
- "main": [
- "css/ionicons.css",
- "fonts/*"
- ],
- "homepage": "https://github.com/driftyco/ionicons",
- "description": "Ionicons - free and beautiful icons from the creators of Ionic Framework"
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/component.json b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/component.json
deleted file mode 100644
index 5f4f5445..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/component.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "repo": "driftyco/ionicons",
- "development": {},
- "version": "2.0.0",
- "styles": [
- "css/ionicons.css"
- ],
- "name": "Ionicons",
- "dependencies": {},
- "keywords": [],
- "license": "MIT",
- "fonts": [
- "fonts/ionicons.eot",
- "fonts/ionicons.svg",
- "fonts/ionicons.ttf",
- "fonts/ionicons.woff"
- ],
- "description": "The premium icon font for Ionic Framework."
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/composer.json b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/composer.json
deleted file mode 100644
index 1161e9ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/composer.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "name": "driftyco/ionicons",
- "license": [
- "MIT"
- ],
- "extra": {},
- "authors": [
- {
- "homepage": "https://twitter.com/benjsperry",
- "role": "Designer",
- "name": "Ben Sperry",
- "email": "ben@drifty.com"
- },
- {
- "homepage": "https://twitter.com/adamdbradley",
- "role": "Developer",
- "name": "Adam Bradley",
- "email": "adam@drifty.com"
- },
- {
- "homepage": "https://twitter.com/maxlynch",
- "role": "Developer",
- "name": "Max Lynch",
- "email": "max@drifty.com"
- }
- ],
- "keywords": [
- "fonts",
- "icon font",
- "icons",
- "ionic",
- "web font"
- ],
- "homepage": "http://ionicons.com/",
- "description": "The premium icon font for Ionic Framework."
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.css
deleted file mode 100644
index 885aa6bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.css
+++ /dev/null
@@ -1,1480 +0,0 @@
-@charset "UTF-8";
-/*!
- Ionicons, v2.0.0
- Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
- https://twitter.com/benjsperry https://twitter.com/ionicframework
- MIT License: https://github.com/driftyco/ionicons
-
- Android-style icons originally built by Google’s
- Material Design Icons: https://github.com/google/material-design-icons
- used under CC BY http://creativecommons.org/licenses/by/4.0/
- Modified icons to fit ionicon’s grid from original.
-*/
-@font-face { font-family: "Ionicons"; src: url("../fonts/ionicons.eot?v=2.0.0"); src: url("../fonts/ionicons.eot?v=2.0.0#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=2.0.0") format("truetype"), url("../fonts/ionicons.woff?v=2.0.0") format("woff"), url("../fonts/ionicons.svg?v=2.0.0#Ionicons") format("svg"); font-weight: normal; font-style: normal; }
-.ion, .ionicons, .ion-alert:before, .ion-alert-circled:before, .ion-android-add:before, .ion-android-add-circle:before, .ion-android-alarm-clock:before, .ion-android-alert:before, .ion-android-apps:before, .ion-android-archive:before, .ion-android-arrow-back:before, .ion-android-arrow-down:before, .ion-android-arrow-dropdown:before, .ion-android-arrow-dropdown-circle:before, .ion-android-arrow-dropleft:before, .ion-android-arrow-dropleft-circle:before, .ion-android-arrow-dropright:before, .ion-android-arrow-dropright-circle:before, .ion-android-arrow-dropup:before, .ion-android-arrow-dropup-circle:before, .ion-android-arrow-forward:before, .ion-android-arrow-up:before, .ion-android-attach:before, .ion-android-bar:before, .ion-android-bicycle:before, .ion-android-boat:before, .ion-android-bookmark:before, .ion-android-bulb:before, .ion-android-bus:before, .ion-android-calendar:before, .ion-android-call:before, .ion-android-camera:before, .ion-android-cancel:before, .ion-android-car:before, .ion-android-cart:before, .ion-android-chat:before, .ion-android-checkbox:before, .ion-android-checkbox-blank:before, .ion-android-checkbox-outline:before, .ion-android-checkbox-outline-blank:before, .ion-android-checkmark-circle:before, .ion-android-clipboard:before, .ion-android-close:before, .ion-android-cloud:before, .ion-android-cloud-circle:before, .ion-android-cloud-done:before, .ion-android-cloud-outline:before, .ion-android-color-palette:before, .ion-android-compass:before, .ion-android-contact:before, .ion-android-contacts:before, .ion-android-contract:before, .ion-android-create:before, .ion-android-delete:before, .ion-android-desktop:before, .ion-android-document:before, .ion-android-done:before, .ion-android-done-all:before, .ion-android-download:before, .ion-android-drafts:before, .ion-android-exit:before, .ion-android-expand:before, .ion-android-favorite:before, .ion-android-favorite-outline:before, .ion-android-film:before, .ion-android-folder:before, .ion-android-folder-open:before, .ion-android-funnel:before, .ion-android-globe:before, .ion-android-hand:before, .ion-android-hangout:before, .ion-android-happy:before, .ion-android-home:before, .ion-android-image:before, .ion-android-laptop:before, .ion-android-list:before, .ion-android-locate:before, .ion-android-lock:before, .ion-android-mail:before, .ion-android-map:before, .ion-android-menu:before, .ion-android-microphone:before, .ion-android-microphone-off:before, .ion-android-more-horizontal:before, .ion-android-more-vertical:before, .ion-android-navigate:before, .ion-android-notifications:before, .ion-android-notifications-none:before, .ion-android-notifications-off:before, .ion-android-open:before, .ion-android-options:before, .ion-android-people:before, .ion-android-person:before, .ion-android-person-add:before, .ion-android-phone-landscape:before, .ion-android-phone-portrait:before, .ion-android-pin:before, .ion-android-plane:before, .ion-android-playstore:before, .ion-android-print:before, .ion-android-radio-button-off:before, .ion-android-radio-button-on:before, .ion-android-refresh:before, .ion-android-remove:before, .ion-android-remove-circle:before, .ion-android-restaurant:before, .ion-android-sad:before, .ion-android-search:before, .ion-android-send:before, .ion-android-settings:before, .ion-android-share:before, .ion-android-share-alt:before, .ion-android-star:before, .ion-android-star-half:before, .ion-android-star-outline:before, .ion-android-stopwatch:before, .ion-android-subway:before, .ion-android-sunny:before, .ion-android-sync:before, .ion-android-textsms:before, .ion-android-time:before, .ion-android-train:before, .ion-android-unlock:before, .ion-android-upload:before, .ion-android-volume-down:before, .ion-android-volume-mute:before, .ion-android-volume-off:before, .ion-android-volume-up:before, .ion-android-walk:before, .ion-android-warning:before, .ion-android-watch:before, .ion-android-wifi:before, .ion-aperture:before, .ion-archive:before, .ion-arrow-down-a:before, .ion-arrow-down-b:before, .ion-arrow-down-c:before, .ion-arrow-expand:before, .ion-arrow-graph-down-left:before, .ion-arrow-graph-down-right:before, .ion-arrow-graph-up-left:before, .ion-arrow-graph-up-right:before, .ion-arrow-left-a:before, .ion-arrow-left-b:before, .ion-arrow-left-c:before, .ion-arrow-move:before, .ion-arrow-resize:before, .ion-arrow-return-left:before, .ion-arrow-return-right:before, .ion-arrow-right-a:before, .ion-arrow-right-b:before, .ion-arrow-right-c:before, .ion-arrow-shrink:before, .ion-arrow-swap:before, .ion-arrow-up-a:before, .ion-arrow-up-b:before, .ion-arrow-up-c:before, .ion-asterisk:before, .ion-at:before, .ion-backspace:before, .ion-backspace-outline:before, .ion-bag:before, .ion-battery-charging:before, .ion-battery-empty:before, .ion-battery-full:before, .ion-battery-half:before, .ion-battery-low:before, .ion-beaker:before, .ion-beer:before, .ion-bluetooth:before, .ion-bonfire:before, .ion-bookmark:before, .ion-bowtie:before, .ion-briefcase:before, .ion-bug:before, .ion-calculator:before, .ion-calendar:before, .ion-camera:before, .ion-card:before, .ion-cash:before, .ion-chatbox:before, .ion-chatbox-working:before, .ion-chatboxes:before, .ion-chatbubble:before, .ion-chatbubble-working:before, .ion-chatbubbles:before, .ion-checkmark:before, .ion-checkmark-circled:before, .ion-checkmark-round:before, .ion-chevron-down:before, .ion-chevron-left:before, .ion-chevron-right:before, .ion-chevron-up:before, .ion-clipboard:before, .ion-clock:before, .ion-close:before, .ion-close-circled:before, .ion-close-round:before, .ion-closed-captioning:before, .ion-cloud:before, .ion-code:before, .ion-code-download:before, .ion-code-working:before, .ion-coffee:before, .ion-compass:before, .ion-compose:before, .ion-connection-bars:before, .ion-contrast:before, .ion-crop:before, .ion-cube:before, .ion-disc:before, .ion-document:before, .ion-document-text:before, .ion-drag:before, .ion-earth:before, .ion-easel:before, .ion-edit:before, .ion-egg:before, .ion-eject:before, .ion-email:before, .ion-email-unread:before, .ion-erlenmeyer-flask:before, .ion-erlenmeyer-flask-bubbles:before, .ion-eye:before, .ion-eye-disabled:before, .ion-female:before, .ion-filing:before, .ion-film-marker:before, .ion-fireball:before, .ion-flag:before, .ion-flame:before, .ion-flash:before, .ion-flash-off:before, .ion-folder:before, .ion-fork:before, .ion-fork-repo:before, .ion-forward:before, .ion-funnel:before, .ion-gear-a:before, .ion-gear-b:before, .ion-grid:before, .ion-hammer:before, .ion-happy:before, .ion-happy-outline:before, .ion-headphone:before, .ion-heart:before, .ion-heart-broken:before, .ion-help:before, .ion-help-buoy:before, .ion-help-circled:before, .ion-home:before, .ion-icecream:before, .ion-image:before, .ion-images:before, .ion-information:before, .ion-information-circled:before, .ion-ionic:before, .ion-ios-alarm:before, .ion-ios-alarm-outline:before, .ion-ios-albums:before, .ion-ios-albums-outline:before, .ion-ios-americanfootball:before, .ion-ios-americanfootball-outline:before, .ion-ios-analytics:before, .ion-ios-analytics-outline:before, .ion-ios-arrow-back:before, .ion-ios-arrow-down:before, .ion-ios-arrow-forward:before, .ion-ios-arrow-left:before, .ion-ios-arrow-right:before, .ion-ios-arrow-thin-down:before, .ion-ios-arrow-thin-left:before, .ion-ios-arrow-thin-right:before, .ion-ios-arrow-thin-up:before, .ion-ios-arrow-up:before, .ion-ios-at:before, .ion-ios-at-outline:before, .ion-ios-barcode:before, .ion-ios-barcode-outline:before, .ion-ios-baseball:before, .ion-ios-baseball-outline:before, .ion-ios-basketball:before, .ion-ios-basketball-outline:before, .ion-ios-bell:before, .ion-ios-bell-outline:before, .ion-ios-body:before, .ion-ios-body-outline:before, .ion-ios-bolt:before, .ion-ios-bolt-outline:before, .ion-ios-book:before, .ion-ios-book-outline:before, .ion-ios-bookmarks:before, .ion-ios-bookmarks-outline:before, .ion-ios-box:before, .ion-ios-box-outline:before, .ion-ios-briefcase:before, .ion-ios-briefcase-outline:before, .ion-ios-browsers:before, .ion-ios-browsers-outline:before, .ion-ios-calculator:before, .ion-ios-calculator-outline:before, .ion-ios-calendar:before, .ion-ios-calendar-outline:before, .ion-ios-camera:before, .ion-ios-camera-outline:before, .ion-ios-cart:before, .ion-ios-cart-outline:before, .ion-ios-chatboxes:before, .ion-ios-chatboxes-outline:before, .ion-ios-chatbubble:before, .ion-ios-chatbubble-outline:before, .ion-ios-checkmark:before, .ion-ios-checkmark-empty:before, .ion-ios-checkmark-outline:before, .ion-ios-circle-filled:before, .ion-ios-circle-outline:before, .ion-ios-clock:before, .ion-ios-clock-outline:before, .ion-ios-close:before, .ion-ios-close-empty:before, .ion-ios-close-outline:before, .ion-ios-cloud:before, .ion-ios-cloud-download:before, .ion-ios-cloud-download-outline:before, .ion-ios-cloud-outline:before, .ion-ios-cloud-upload:before, .ion-ios-cloud-upload-outline:before, .ion-ios-cloudy:before, .ion-ios-cloudy-night:before, .ion-ios-cloudy-night-outline:before, .ion-ios-cloudy-outline:before, .ion-ios-cog:before, .ion-ios-cog-outline:before, .ion-ios-color-filter:before, .ion-ios-color-filter-outline:before, .ion-ios-color-wand:before, .ion-ios-color-wand-outline:before, .ion-ios-compose:before, .ion-ios-compose-outline:before, .ion-ios-contact:before, .ion-ios-contact-outline:before, .ion-ios-copy:before, .ion-ios-copy-outline:before, .ion-ios-crop:before, .ion-ios-crop-strong:before, .ion-ios-download:before, .ion-ios-download-outline:before, .ion-ios-drag:before, .ion-ios-email:before, .ion-ios-email-outline:before, .ion-ios-eye:before, .ion-ios-eye-outline:before, .ion-ios-fastforward:before, .ion-ios-fastforward-outline:before, .ion-ios-filing:before, .ion-ios-filing-outline:before, .ion-ios-film:before, .ion-ios-film-outline:before, .ion-ios-flag:before, .ion-ios-flag-outline:before, .ion-ios-flame:before, .ion-ios-flame-outline:before, .ion-ios-flask:before, .ion-ios-flask-outline:before, .ion-ios-flower:before, .ion-ios-flower-outline:before, .ion-ios-folder:before, .ion-ios-folder-outline:before, .ion-ios-football:before, .ion-ios-football-outline:before, .ion-ios-game-controller-a:before, .ion-ios-game-controller-a-outline:before, .ion-ios-game-controller-b:before, .ion-ios-game-controller-b-outline:before, .ion-ios-gear:before, .ion-ios-gear-outline:before, .ion-ios-glasses:before, .ion-ios-glasses-outline:before, .ion-ios-grid-view:before, .ion-ios-grid-view-outline:before, .ion-ios-heart:before, .ion-ios-heart-outline:before, .ion-ios-help:before, .ion-ios-help-empty:before, .ion-ios-help-outline:before, .ion-ios-home:before, .ion-ios-home-outline:before, .ion-ios-infinite:before, .ion-ios-infinite-outline:before, .ion-ios-information:before, .ion-ios-information-empty:before, .ion-ios-information-outline:before, .ion-ios-ionic-outline:before, .ion-ios-keypad:before, .ion-ios-keypad-outline:before, .ion-ios-lightbulb:before, .ion-ios-lightbulb-outline:before, .ion-ios-list:before, .ion-ios-list-outline:before, .ion-ios-location:before, .ion-ios-location-outline:before, .ion-ios-locked:before, .ion-ios-locked-outline:before, .ion-ios-loop:before, .ion-ios-loop-strong:before, .ion-ios-medical:before, .ion-ios-medical-outline:before, .ion-ios-medkit:before, .ion-ios-medkit-outline:before, .ion-ios-mic:before, .ion-ios-mic-off:before, .ion-ios-mic-outline:before, .ion-ios-minus:before, .ion-ios-minus-empty:before, .ion-ios-minus-outline:before, .ion-ios-monitor:before, .ion-ios-monitor-outline:before, .ion-ios-moon:before, .ion-ios-moon-outline:before, .ion-ios-more:before, .ion-ios-more-outline:before, .ion-ios-musical-note:before, .ion-ios-musical-notes:before, .ion-ios-navigate:before, .ion-ios-navigate-outline:before, .ion-ios-nutrition:before, .ion-ios-nutrition-outline:before, .ion-ios-paper:before, .ion-ios-paper-outline:before, .ion-ios-paperplane:before, .ion-ios-paperplane-outline:before, .ion-ios-partlysunny:before, .ion-ios-partlysunny-outline:before, .ion-ios-pause:before, .ion-ios-pause-outline:before, .ion-ios-paw:before, .ion-ios-paw-outline:before, .ion-ios-people:before, .ion-ios-people-outline:before, .ion-ios-person:before, .ion-ios-person-outline:before, .ion-ios-personadd:before, .ion-ios-personadd-outline:before, .ion-ios-photos:before, .ion-ios-photos-outline:before, .ion-ios-pie:before, .ion-ios-pie-outline:before, .ion-ios-pint:before, .ion-ios-pint-outline:before, .ion-ios-play:before, .ion-ios-play-outline:before, .ion-ios-plus:before, .ion-ios-plus-empty:before, .ion-ios-plus-outline:before, .ion-ios-pricetag:before, .ion-ios-pricetag-outline:before, .ion-ios-pricetags:before, .ion-ios-pricetags-outline:before, .ion-ios-printer:before, .ion-ios-printer-outline:before, .ion-ios-pulse:before, .ion-ios-pulse-strong:before, .ion-ios-rainy:before, .ion-ios-rainy-outline:before, .ion-ios-recording:before, .ion-ios-recording-outline:before, .ion-ios-redo:before, .ion-ios-redo-outline:before, .ion-ios-refresh:before, .ion-ios-refresh-empty:before, .ion-ios-refresh-outline:before, .ion-ios-reload:before, .ion-ios-reverse-camera:before, .ion-ios-reverse-camera-outline:before, .ion-ios-rewind:before, .ion-ios-rewind-outline:before, .ion-ios-rose:before, .ion-ios-rose-outline:before, .ion-ios-search:before, .ion-ios-search-strong:before, .ion-ios-settings:before, .ion-ios-settings-strong:before, .ion-ios-shuffle:before, .ion-ios-shuffle-strong:before, .ion-ios-skipbackward:before, .ion-ios-skipbackward-outline:before, .ion-ios-skipforward:before, .ion-ios-skipforward-outline:before, .ion-ios-snowy:before, .ion-ios-speedometer:before, .ion-ios-speedometer-outline:before, .ion-ios-star:before, .ion-ios-star-half:before, .ion-ios-star-outline:before, .ion-ios-stopwatch:before, .ion-ios-stopwatch-outline:before, .ion-ios-sunny:before, .ion-ios-sunny-outline:before, .ion-ios-telephone:before, .ion-ios-telephone-outline:before, .ion-ios-tennisball:before, .ion-ios-tennisball-outline:before, .ion-ios-thunderstorm:before, .ion-ios-thunderstorm-outline:before, .ion-ios-time:before, .ion-ios-time-outline:before, .ion-ios-timer:before, .ion-ios-timer-outline:before, .ion-ios-toggle:before, .ion-ios-toggle-outline:before, .ion-ios-trash:before, .ion-ios-trash-outline:before, .ion-ios-undo:before, .ion-ios-undo-outline:before, .ion-ios-unlocked:before, .ion-ios-unlocked-outline:before, .ion-ios-upload:before, .ion-ios-upload-outline:before, .ion-ios-videocam:before, .ion-ios-videocam-outline:before, .ion-ios-volume-high:before, .ion-ios-volume-low:before, .ion-ios-wineglass:before, .ion-ios-wineglass-outline:before, .ion-ios-world:before, .ion-ios-world-outline:before, .ion-ipad:before, .ion-iphone:before, .ion-ipod:before, .ion-jet:before, .ion-key:before, .ion-knife:before, .ion-laptop:before, .ion-leaf:before, .ion-levels:before, .ion-lightbulb:before, .ion-link:before, .ion-load-a:before, .ion-load-b:before, .ion-load-c:before, .ion-load-d:before, .ion-location:before, .ion-lock-combination:before, .ion-locked:before, .ion-log-in:before, .ion-log-out:before, .ion-loop:before, .ion-magnet:before, .ion-male:before, .ion-man:before, .ion-map:before, .ion-medkit:before, .ion-merge:before, .ion-mic-a:before, .ion-mic-b:before, .ion-mic-c:before, .ion-minus:before, .ion-minus-circled:before, .ion-minus-round:before, .ion-model-s:before, .ion-monitor:before, .ion-more:before, .ion-mouse:before, .ion-music-note:before, .ion-navicon:before, .ion-navicon-round:before, .ion-navigate:before, .ion-network:before, .ion-no-smoking:before, .ion-nuclear:before, .ion-outlet:before, .ion-paintbrush:before, .ion-paintbucket:before, .ion-paper-airplane:before, .ion-paperclip:before, .ion-pause:before, .ion-person:before, .ion-person-add:before, .ion-person-stalker:before, .ion-pie-graph:before, .ion-pin:before, .ion-pinpoint:before, .ion-pizza:before, .ion-plane:before, .ion-planet:before, .ion-play:before, .ion-playstation:before, .ion-plus:before, .ion-plus-circled:before, .ion-plus-round:before, .ion-podium:before, .ion-pound:before, .ion-power:before, .ion-pricetag:before, .ion-pricetags:before, .ion-printer:before, .ion-pull-request:before, .ion-qr-scanner:before, .ion-quote:before, .ion-radio-waves:before, .ion-record:before, .ion-refresh:before, .ion-reply:before, .ion-reply-all:before, .ion-ribbon-a:before, .ion-ribbon-b:before, .ion-sad:before, .ion-sad-outline:before, .ion-scissors:before, .ion-search:before, .ion-settings:before, .ion-share:before, .ion-shuffle:before, .ion-skip-backward:before, .ion-skip-forward:before, .ion-social-android:before, .ion-social-android-outline:before, .ion-social-angular:before, .ion-social-angular-outline:before, .ion-social-apple:before, .ion-social-apple-outline:before, .ion-social-bitcoin:before, .ion-social-bitcoin-outline:before, .ion-social-buffer:before, .ion-social-buffer-outline:before, .ion-social-chrome:before, .ion-social-chrome-outline:before, .ion-social-codepen:before, .ion-social-codepen-outline:before, .ion-social-css3:before, .ion-social-css3-outline:before, .ion-social-designernews:before, .ion-social-designernews-outline:before, .ion-social-dribbble:before, .ion-social-dribbble-outline:before, .ion-social-dropbox:before, .ion-social-dropbox-outline:before, .ion-social-euro:before, .ion-social-euro-outline:before, .ion-social-facebook:before, .ion-social-facebook-outline:before, .ion-social-foursquare:before, .ion-social-foursquare-outline:before, .ion-social-freebsd-devil:before, .ion-social-github:before, .ion-social-github-outline:before, .ion-social-google:before, .ion-social-google-outline:before, .ion-social-googleplus:before, .ion-social-googleplus-outline:before, .ion-social-hackernews:before, .ion-social-hackernews-outline:before, .ion-social-html5:before, .ion-social-html5-outline:before, .ion-social-instagram:before, .ion-social-instagram-outline:before, .ion-social-javascript:before, .ion-social-javascript-outline:before, .ion-social-linkedin:before, .ion-social-linkedin-outline:before, .ion-social-markdown:before, .ion-social-nodejs:before, .ion-social-octocat:before, .ion-social-pinterest:before, .ion-social-pinterest-outline:before, .ion-social-python:before, .ion-social-reddit:before, .ion-social-reddit-outline:before, .ion-social-rss:before, .ion-social-rss-outline:before, .ion-social-sass:before, .ion-social-skype:before, .ion-social-skype-outline:before, .ion-social-snapchat:before, .ion-social-snapchat-outline:before, .ion-social-tumblr:before, .ion-social-tumblr-outline:before, .ion-social-tux:before, .ion-social-twitch:before, .ion-social-twitch-outline:before, .ion-social-twitter:before, .ion-social-twitter-outline:before, .ion-social-usd:before, .ion-social-usd-outline:before, .ion-social-vimeo:before, .ion-social-vimeo-outline:before, .ion-social-whatsapp:before, .ion-social-whatsapp-outline:before, .ion-social-windows:before, .ion-social-windows-outline:before, .ion-social-wordpress:before, .ion-social-wordpress-outline:before, .ion-social-yahoo:before, .ion-social-yahoo-outline:before, .ion-social-yen:before, .ion-social-yen-outline:before, .ion-social-youtube:before, .ion-social-youtube-outline:before, .ion-soup-can:before, .ion-soup-can-outline:before, .ion-speakerphone:before, .ion-speedometer:before, .ion-spoon:before, .ion-star:before, .ion-stats-bars:before, .ion-steam:before, .ion-stop:before, .ion-thermometer:before, .ion-thumbsdown:before, .ion-thumbsup:before, .ion-toggle:before, .ion-toggle-filled:before, .ion-transgender:before, .ion-trash-a:before, .ion-trash-b:before, .ion-trophy:before, .ion-tshirt:before, .ion-tshirt-outline:before, .ion-umbrella:before, .ion-university:before, .ion-unlocked:before, .ion-upload:before, .ion-usb:before, .ion-videocamera:before, .ion-volume-high:before, .ion-volume-low:before, .ion-volume-medium:before, .ion-volume-mute:before, .ion-wand:before, .ion-waterdrop:before, .ion-wifi:before, .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, .ion-xbox:before { display: inline-block; font-family: "Ionicons"; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; text-rendering: auto; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
-
-.ion-alert:before { content: "\f101"; }
-
-.ion-alert-circled:before { content: "\f100"; }
-
-.ion-android-add:before { content: "\f2c7"; }
-
-.ion-android-add-circle:before { content: "\f359"; }
-
-.ion-android-alarm-clock:before { content: "\f35a"; }
-
-.ion-android-alert:before { content: "\f35b"; }
-
-.ion-android-apps:before { content: "\f35c"; }
-
-.ion-android-archive:before { content: "\f2c9"; }
-
-.ion-android-arrow-back:before { content: "\f2ca"; }
-
-.ion-android-arrow-down:before { content: "\f35d"; }
-
-.ion-android-arrow-dropdown:before { content: "\f35f"; }
-
-.ion-android-arrow-dropdown-circle:before { content: "\f35e"; }
-
-.ion-android-arrow-dropleft:before { content: "\f361"; }
-
-.ion-android-arrow-dropleft-circle:before { content: "\f360"; }
-
-.ion-android-arrow-dropright:before { content: "\f363"; }
-
-.ion-android-arrow-dropright-circle:before { content: "\f362"; }
-
-.ion-android-arrow-dropup:before { content: "\f365"; }
-
-.ion-android-arrow-dropup-circle:before { content: "\f364"; }
-
-.ion-android-arrow-forward:before { content: "\f30f"; }
-
-.ion-android-arrow-up:before { content: "\f366"; }
-
-.ion-android-attach:before { content: "\f367"; }
-
-.ion-android-bar:before { content: "\f368"; }
-
-.ion-android-bicycle:before { content: "\f369"; }
-
-.ion-android-boat:before { content: "\f36a"; }
-
-.ion-android-bookmark:before { content: "\f36b"; }
-
-.ion-android-bulb:before { content: "\f36c"; }
-
-.ion-android-bus:before { content: "\f36d"; }
-
-.ion-android-calendar:before { content: "\f2d1"; }
-
-.ion-android-call:before { content: "\f2d2"; }
-
-.ion-android-camera:before { content: "\f2d3"; }
-
-.ion-android-cancel:before { content: "\f36e"; }
-
-.ion-android-car:before { content: "\f36f"; }
-
-.ion-android-cart:before { content: "\f370"; }
-
-.ion-android-chat:before { content: "\f2d4"; }
-
-.ion-android-checkbox:before { content: "\f374"; }
-
-.ion-android-checkbox-blank:before { content: "\f371"; }
-
-.ion-android-checkbox-outline:before { content: "\f373"; }
-
-.ion-android-checkbox-outline-blank:before { content: "\f372"; }
-
-.ion-android-checkmark-circle:before { content: "\f375"; }
-
-.ion-android-clipboard:before { content: "\f376"; }
-
-.ion-android-close:before { content: "\f2d7"; }
-
-.ion-android-cloud:before { content: "\f37a"; }
-
-.ion-android-cloud-circle:before { content: "\f377"; }
-
-.ion-android-cloud-done:before { content: "\f378"; }
-
-.ion-android-cloud-outline:before { content: "\f379"; }
-
-.ion-android-color-palette:before { content: "\f37b"; }
-
-.ion-android-compass:before { content: "\f37c"; }
-
-.ion-android-contact:before { content: "\f2d8"; }
-
-.ion-android-contacts:before { content: "\f2d9"; }
-
-.ion-android-contract:before { content: "\f37d"; }
-
-.ion-android-create:before { content: "\f37e"; }
-
-.ion-android-delete:before { content: "\f37f"; }
-
-.ion-android-desktop:before { content: "\f380"; }
-
-.ion-android-document:before { content: "\f381"; }
-
-.ion-android-done:before { content: "\f383"; }
-
-.ion-android-done-all:before { content: "\f382"; }
-
-.ion-android-download:before { content: "\f2dd"; }
-
-.ion-android-drafts:before { content: "\f384"; }
-
-.ion-android-exit:before { content: "\f385"; }
-
-.ion-android-expand:before { content: "\f386"; }
-
-.ion-android-favorite:before { content: "\f388"; }
-
-.ion-android-favorite-outline:before { content: "\f387"; }
-
-.ion-android-film:before { content: "\f389"; }
-
-.ion-android-folder:before { content: "\f2e0"; }
-
-.ion-android-folder-open:before { content: "\f38a"; }
-
-.ion-android-funnel:before { content: "\f38b"; }
-
-.ion-android-globe:before { content: "\f38c"; }
-
-.ion-android-hand:before { content: "\f2e3"; }
-
-.ion-android-hangout:before { content: "\f38d"; }
-
-.ion-android-happy:before { content: "\f38e"; }
-
-.ion-android-home:before { content: "\f38f"; }
-
-.ion-android-image:before { content: "\f2e4"; }
-
-.ion-android-laptop:before { content: "\f390"; }
-
-.ion-android-list:before { content: "\f391"; }
-
-.ion-android-locate:before { content: "\f2e9"; }
-
-.ion-android-lock:before { content: "\f392"; }
-
-.ion-android-mail:before { content: "\f2eb"; }
-
-.ion-android-map:before { content: "\f393"; }
-
-.ion-android-menu:before { content: "\f394"; }
-
-.ion-android-microphone:before { content: "\f2ec"; }
-
-.ion-android-microphone-off:before { content: "\f395"; }
-
-.ion-android-more-horizontal:before { content: "\f396"; }
-
-.ion-android-more-vertical:before { content: "\f397"; }
-
-.ion-android-navigate:before { content: "\f398"; }
-
-.ion-android-notifications:before { content: "\f39b"; }
-
-.ion-android-notifications-none:before { content: "\f399"; }
-
-.ion-android-notifications-off:before { content: "\f39a"; }
-
-.ion-android-open:before { content: "\f39c"; }
-
-.ion-android-options:before { content: "\f39d"; }
-
-.ion-android-people:before { content: "\f39e"; }
-
-.ion-android-person:before { content: "\f3a0"; }
-
-.ion-android-person-add:before { content: "\f39f"; }
-
-.ion-android-phone-landscape:before { content: "\f3a1"; }
-
-.ion-android-phone-portrait:before { content: "\f3a2"; }
-
-.ion-android-pin:before { content: "\f3a3"; }
-
-.ion-android-plane:before { content: "\f3a4"; }
-
-.ion-android-playstore:before { content: "\f2f0"; }
-
-.ion-android-print:before { content: "\f3a5"; }
-
-.ion-android-radio-button-off:before { content: "\f3a6"; }
-
-.ion-android-radio-button-on:before { content: "\f3a7"; }
-
-.ion-android-refresh:before { content: "\f3a8"; }
-
-.ion-android-remove:before { content: "\f2f4"; }
-
-.ion-android-remove-circle:before { content: "\f3a9"; }
-
-.ion-android-restaurant:before { content: "\f3aa"; }
-
-.ion-android-sad:before { content: "\f3ab"; }
-
-.ion-android-search:before { content: "\f2f5"; }
-
-.ion-android-send:before { content: "\f2f6"; }
-
-.ion-android-settings:before { content: "\f2f7"; }
-
-.ion-android-share:before { content: "\f2f8"; }
-
-.ion-android-share-alt:before { content: "\f3ac"; }
-
-.ion-android-star:before { content: "\f2fc"; }
-
-.ion-android-star-half:before { content: "\f3ad"; }
-
-.ion-android-star-outline:before { content: "\f3ae"; }
-
-.ion-android-stopwatch:before { content: "\f2fd"; }
-
-.ion-android-subway:before { content: "\f3af"; }
-
-.ion-android-sunny:before { content: "\f3b0"; }
-
-.ion-android-sync:before { content: "\f3b1"; }
-
-.ion-android-textsms:before { content: "\f3b2"; }
-
-.ion-android-time:before { content: "\f3b3"; }
-
-.ion-android-train:before { content: "\f3b4"; }
-
-.ion-android-unlock:before { content: "\f3b5"; }
-
-.ion-android-upload:before { content: "\f3b6"; }
-
-.ion-android-volume-down:before { content: "\f3b7"; }
-
-.ion-android-volume-mute:before { content: "\f3b8"; }
-
-.ion-android-volume-off:before { content: "\f3b9"; }
-
-.ion-android-volume-up:before { content: "\f3ba"; }
-
-.ion-android-walk:before { content: "\f3bb"; }
-
-.ion-android-warning:before { content: "\f3bc"; }
-
-.ion-android-watch:before { content: "\f3bd"; }
-
-.ion-android-wifi:before { content: "\f305"; }
-
-.ion-aperture:before { content: "\f313"; }
-
-.ion-archive:before { content: "\f102"; }
-
-.ion-arrow-down-a:before { content: "\f103"; }
-
-.ion-arrow-down-b:before { content: "\f104"; }
-
-.ion-arrow-down-c:before { content: "\f105"; }
-
-.ion-arrow-expand:before { content: "\f25e"; }
-
-.ion-arrow-graph-down-left:before { content: "\f25f"; }
-
-.ion-arrow-graph-down-right:before { content: "\f260"; }
-
-.ion-arrow-graph-up-left:before { content: "\f261"; }
-
-.ion-arrow-graph-up-right:before { content: "\f262"; }
-
-.ion-arrow-left-a:before { content: "\f106"; }
-
-.ion-arrow-left-b:before { content: "\f107"; }
-
-.ion-arrow-left-c:before { content: "\f108"; }
-
-.ion-arrow-move:before { content: "\f263"; }
-
-.ion-arrow-resize:before { content: "\f264"; }
-
-.ion-arrow-return-left:before { content: "\f265"; }
-
-.ion-arrow-return-right:before { content: "\f266"; }
-
-.ion-arrow-right-a:before { content: "\f109"; }
-
-.ion-arrow-right-b:before { content: "\f10a"; }
-
-.ion-arrow-right-c:before { content: "\f10b"; }
-
-.ion-arrow-shrink:before { content: "\f267"; }
-
-.ion-arrow-swap:before { content: "\f268"; }
-
-.ion-arrow-up-a:before { content: "\f10c"; }
-
-.ion-arrow-up-b:before { content: "\f10d"; }
-
-.ion-arrow-up-c:before { content: "\f10e"; }
-
-.ion-asterisk:before { content: "\f314"; }
-
-.ion-at:before { content: "\f10f"; }
-
-.ion-backspace:before { content: "\f3bf"; }
-
-.ion-backspace-outline:before { content: "\f3be"; }
-
-.ion-bag:before { content: "\f110"; }
-
-.ion-battery-charging:before { content: "\f111"; }
-
-.ion-battery-empty:before { content: "\f112"; }
-
-.ion-battery-full:before { content: "\f113"; }
-
-.ion-battery-half:before { content: "\f114"; }
-
-.ion-battery-low:before { content: "\f115"; }
-
-.ion-beaker:before { content: "\f269"; }
-
-.ion-beer:before { content: "\f26a"; }
-
-.ion-bluetooth:before { content: "\f116"; }
-
-.ion-bonfire:before { content: "\f315"; }
-
-.ion-bookmark:before { content: "\f26b"; }
-
-.ion-bowtie:before { content: "\f3c0"; }
-
-.ion-briefcase:before { content: "\f26c"; }
-
-.ion-bug:before { content: "\f2be"; }
-
-.ion-calculator:before { content: "\f26d"; }
-
-.ion-calendar:before { content: "\f117"; }
-
-.ion-camera:before { content: "\f118"; }
-
-.ion-card:before { content: "\f119"; }
-
-.ion-cash:before { content: "\f316"; }
-
-.ion-chatbox:before { content: "\f11b"; }
-
-.ion-chatbox-working:before { content: "\f11a"; }
-
-.ion-chatboxes:before { content: "\f11c"; }
-
-.ion-chatbubble:before { content: "\f11e"; }
-
-.ion-chatbubble-working:before { content: "\f11d"; }
-
-.ion-chatbubbles:before { content: "\f11f"; }
-
-.ion-checkmark:before { content: "\f122"; }
-
-.ion-checkmark-circled:before { content: "\f120"; }
-
-.ion-checkmark-round:before { content: "\f121"; }
-
-.ion-chevron-down:before { content: "\f123"; }
-
-.ion-chevron-left:before { content: "\f124"; }
-
-.ion-chevron-right:before { content: "\f125"; }
-
-.ion-chevron-up:before { content: "\f126"; }
-
-.ion-clipboard:before { content: "\f127"; }
-
-.ion-clock:before { content: "\f26e"; }
-
-.ion-close:before { content: "\f12a"; }
-
-.ion-close-circled:before { content: "\f128"; }
-
-.ion-close-round:before { content: "\f129"; }
-
-.ion-closed-captioning:before { content: "\f317"; }
-
-.ion-cloud:before { content: "\f12b"; }
-
-.ion-code:before { content: "\f271"; }
-
-.ion-code-download:before { content: "\f26f"; }
-
-.ion-code-working:before { content: "\f270"; }
-
-.ion-coffee:before { content: "\f272"; }
-
-.ion-compass:before { content: "\f273"; }
-
-.ion-compose:before { content: "\f12c"; }
-
-.ion-connection-bars:before { content: "\f274"; }
-
-.ion-contrast:before { content: "\f275"; }
-
-.ion-crop:before { content: "\f3c1"; }
-
-.ion-cube:before { content: "\f318"; }
-
-.ion-disc:before { content: "\f12d"; }
-
-.ion-document:before { content: "\f12f"; }
-
-.ion-document-text:before { content: "\f12e"; }
-
-.ion-drag:before { content: "\f130"; }
-
-.ion-earth:before { content: "\f276"; }
-
-.ion-easel:before { content: "\f3c2"; }
-
-.ion-edit:before { content: "\f2bf"; }
-
-.ion-egg:before { content: "\f277"; }
-
-.ion-eject:before { content: "\f131"; }
-
-.ion-email:before { content: "\f132"; }
-
-.ion-email-unread:before { content: "\f3c3"; }
-
-.ion-erlenmeyer-flask:before { content: "\f3c5"; }
-
-.ion-erlenmeyer-flask-bubbles:before { content: "\f3c4"; }
-
-.ion-eye:before { content: "\f133"; }
-
-.ion-eye-disabled:before { content: "\f306"; }
-
-.ion-female:before { content: "\f278"; }
-
-.ion-filing:before { content: "\f134"; }
-
-.ion-film-marker:before { content: "\f135"; }
-
-.ion-fireball:before { content: "\f319"; }
-
-.ion-flag:before { content: "\f279"; }
-
-.ion-flame:before { content: "\f31a"; }
-
-.ion-flash:before { content: "\f137"; }
-
-.ion-flash-off:before { content: "\f136"; }
-
-.ion-folder:before { content: "\f139"; }
-
-.ion-fork:before { content: "\f27a"; }
-
-.ion-fork-repo:before { content: "\f2c0"; }
-
-.ion-forward:before { content: "\f13a"; }
-
-.ion-funnel:before { content: "\f31b"; }
-
-.ion-gear-a:before { content: "\f13d"; }
-
-.ion-gear-b:before { content: "\f13e"; }
-
-.ion-grid:before { content: "\f13f"; }
-
-.ion-hammer:before { content: "\f27b"; }
-
-.ion-happy:before { content: "\f31c"; }
-
-.ion-happy-outline:before { content: "\f3c6"; }
-
-.ion-headphone:before { content: "\f140"; }
-
-.ion-heart:before { content: "\f141"; }
-
-.ion-heart-broken:before { content: "\f31d"; }
-
-.ion-help:before { content: "\f143"; }
-
-.ion-help-buoy:before { content: "\f27c"; }
-
-.ion-help-circled:before { content: "\f142"; }
-
-.ion-home:before { content: "\f144"; }
-
-.ion-icecream:before { content: "\f27d"; }
-
-.ion-image:before { content: "\f147"; }
-
-.ion-images:before { content: "\f148"; }
-
-.ion-information:before { content: "\f14a"; }
-
-.ion-information-circled:before { content: "\f149"; }
-
-.ion-ionic:before { content: "\f14b"; }
-
-.ion-ios-alarm:before { content: "\f3c8"; }
-
-.ion-ios-alarm-outline:before { content: "\f3c7"; }
-
-.ion-ios-albums:before { content: "\f3ca"; }
-
-.ion-ios-albums-outline:before { content: "\f3c9"; }
-
-.ion-ios-americanfootball:before { content: "\f3cc"; }
-
-.ion-ios-americanfootball-outline:before { content: "\f3cb"; }
-
-.ion-ios-analytics:before { content: "\f3ce"; }
-
-.ion-ios-analytics-outline:before { content: "\f3cd"; }
-
-.ion-ios-arrow-back:before { content: "\f3cf"; }
-
-.ion-ios-arrow-down:before { content: "\f3d0"; }
-
-.ion-ios-arrow-forward:before { content: "\f3d1"; }
-
-.ion-ios-arrow-left:before { content: "\f3d2"; }
-
-.ion-ios-arrow-right:before { content: "\f3d3"; }
-
-.ion-ios-arrow-thin-down:before { content: "\f3d4"; }
-
-.ion-ios-arrow-thin-left:before { content: "\f3d5"; }
-
-.ion-ios-arrow-thin-right:before { content: "\f3d6"; }
-
-.ion-ios-arrow-thin-up:before { content: "\f3d7"; }
-
-.ion-ios-arrow-up:before { content: "\f3d8"; }
-
-.ion-ios-at:before { content: "\f3da"; }
-
-.ion-ios-at-outline:before { content: "\f3d9"; }
-
-.ion-ios-barcode:before { content: "\f3dc"; }
-
-.ion-ios-barcode-outline:before { content: "\f3db"; }
-
-.ion-ios-baseball:before { content: "\f3de"; }
-
-.ion-ios-baseball-outline:before { content: "\f3dd"; }
-
-.ion-ios-basketball:before { content: "\f3e0"; }
-
-.ion-ios-basketball-outline:before { content: "\f3df"; }
-
-.ion-ios-bell:before { content: "\f3e2"; }
-
-.ion-ios-bell-outline:before { content: "\f3e1"; }
-
-.ion-ios-body:before { content: "\f3e4"; }
-
-.ion-ios-body-outline:before { content: "\f3e3"; }
-
-.ion-ios-bolt:before { content: "\f3e6"; }
-
-.ion-ios-bolt-outline:before { content: "\f3e5"; }
-
-.ion-ios-book:before { content: "\f3e8"; }
-
-.ion-ios-book-outline:before { content: "\f3e7"; }
-
-.ion-ios-bookmarks:before { content: "\f3ea"; }
-
-.ion-ios-bookmarks-outline:before { content: "\f3e9"; }
-
-.ion-ios-box:before { content: "\f3ec"; }
-
-.ion-ios-box-outline:before { content: "\f3eb"; }
-
-.ion-ios-briefcase:before { content: "\f3ee"; }
-
-.ion-ios-briefcase-outline:before { content: "\f3ed"; }
-
-.ion-ios-browsers:before { content: "\f3f0"; }
-
-.ion-ios-browsers-outline:before { content: "\f3ef"; }
-
-.ion-ios-calculator:before { content: "\f3f2"; }
-
-.ion-ios-calculator-outline:before { content: "\f3f1"; }
-
-.ion-ios-calendar:before { content: "\f3f4"; }
-
-.ion-ios-calendar-outline:before { content: "\f3f3"; }
-
-.ion-ios-camera:before { content: "\f3f6"; }
-
-.ion-ios-camera-outline:before { content: "\f3f5"; }
-
-.ion-ios-cart:before { content: "\f3f8"; }
-
-.ion-ios-cart-outline:before { content: "\f3f7"; }
-
-.ion-ios-chatboxes:before { content: "\f3fa"; }
-
-.ion-ios-chatboxes-outline:before { content: "\f3f9"; }
-
-.ion-ios-chatbubble:before { content: "\f3fc"; }
-
-.ion-ios-chatbubble-outline:before { content: "\f3fb"; }
-
-.ion-ios-checkmark:before { content: "\f3ff"; }
-
-.ion-ios-checkmark-empty:before { content: "\f3fd"; }
-
-.ion-ios-checkmark-outline:before { content: "\f3fe"; }
-
-.ion-ios-circle-filled:before { content: "\f400"; }
-
-.ion-ios-circle-outline:before { content: "\f401"; }
-
-.ion-ios-clock:before { content: "\f403"; }
-
-.ion-ios-clock-outline:before { content: "\f402"; }
-
-.ion-ios-close:before { content: "\f406"; }
-
-.ion-ios-close-empty:before { content: "\f404"; }
-
-.ion-ios-close-outline:before { content: "\f405"; }
-
-.ion-ios-cloud:before { content: "\f40c"; }
-
-.ion-ios-cloud-download:before { content: "\f408"; }
-
-.ion-ios-cloud-download-outline:before { content: "\f407"; }
-
-.ion-ios-cloud-outline:before { content: "\f409"; }
-
-.ion-ios-cloud-upload:before { content: "\f40b"; }
-
-.ion-ios-cloud-upload-outline:before { content: "\f40a"; }
-
-.ion-ios-cloudy:before { content: "\f410"; }
-
-.ion-ios-cloudy-night:before { content: "\f40e"; }
-
-.ion-ios-cloudy-night-outline:before { content: "\f40d"; }
-
-.ion-ios-cloudy-outline:before { content: "\f40f"; }
-
-.ion-ios-cog:before { content: "\f412"; }
-
-.ion-ios-cog-outline:before { content: "\f411"; }
-
-.ion-ios-color-filter:before { content: "\f414"; }
-
-.ion-ios-color-filter-outline:before { content: "\f413"; }
-
-.ion-ios-color-wand:before { content: "\f416"; }
-
-.ion-ios-color-wand-outline:before { content: "\f415"; }
-
-.ion-ios-compose:before { content: "\f418"; }
-
-.ion-ios-compose-outline:before { content: "\f417"; }
-
-.ion-ios-contact:before { content: "\f41a"; }
-
-.ion-ios-contact-outline:before { content: "\f419"; }
-
-.ion-ios-copy:before { content: "\f41c"; }
-
-.ion-ios-copy-outline:before { content: "\f41b"; }
-
-.ion-ios-crop:before { content: "\f41e"; }
-
-.ion-ios-crop-strong:before { content: "\f41d"; }
-
-.ion-ios-download:before { content: "\f420"; }
-
-.ion-ios-download-outline:before { content: "\f41f"; }
-
-.ion-ios-drag:before { content: "\f421"; }
-
-.ion-ios-email:before { content: "\f423"; }
-
-.ion-ios-email-outline:before { content: "\f422"; }
-
-.ion-ios-eye:before { content: "\f425"; }
-
-.ion-ios-eye-outline:before { content: "\f424"; }
-
-.ion-ios-fastforward:before { content: "\f427"; }
-
-.ion-ios-fastforward-outline:before { content: "\f426"; }
-
-.ion-ios-filing:before { content: "\f429"; }
-
-.ion-ios-filing-outline:before { content: "\f428"; }
-
-.ion-ios-film:before { content: "\f42b"; }
-
-.ion-ios-film-outline:before { content: "\f42a"; }
-
-.ion-ios-flag:before { content: "\f42d"; }
-
-.ion-ios-flag-outline:before { content: "\f42c"; }
-
-.ion-ios-flame:before { content: "\f42f"; }
-
-.ion-ios-flame-outline:before { content: "\f42e"; }
-
-.ion-ios-flask:before { content: "\f431"; }
-
-.ion-ios-flask-outline:before { content: "\f430"; }
-
-.ion-ios-flower:before { content: "\f433"; }
-
-.ion-ios-flower-outline:before { content: "\f432"; }
-
-.ion-ios-folder:before { content: "\f435"; }
-
-.ion-ios-folder-outline:before { content: "\f434"; }
-
-.ion-ios-football:before { content: "\f437"; }
-
-.ion-ios-football-outline:before { content: "\f436"; }
-
-.ion-ios-game-controller-a:before { content: "\f439"; }
-
-.ion-ios-game-controller-a-outline:before { content: "\f438"; }
-
-.ion-ios-game-controller-b:before { content: "\f43b"; }
-
-.ion-ios-game-controller-b-outline:before { content: "\f43a"; }
-
-.ion-ios-gear:before { content: "\f43d"; }
-
-.ion-ios-gear-outline:before { content: "\f43c"; }
-
-.ion-ios-glasses:before { content: "\f43f"; }
-
-.ion-ios-glasses-outline:before { content: "\f43e"; }
-
-.ion-ios-grid-view:before { content: "\f441"; }
-
-.ion-ios-grid-view-outline:before { content: "\f440"; }
-
-.ion-ios-heart:before { content: "\f443"; }
-
-.ion-ios-heart-outline:before { content: "\f442"; }
-
-.ion-ios-help:before { content: "\f446"; }
-
-.ion-ios-help-empty:before { content: "\f444"; }
-
-.ion-ios-help-outline:before { content: "\f445"; }
-
-.ion-ios-home:before { content: "\f448"; }
-
-.ion-ios-home-outline:before { content: "\f447"; }
-
-.ion-ios-infinite:before { content: "\f44a"; }
-
-.ion-ios-infinite-outline:before { content: "\f449"; }
-
-.ion-ios-information:before { content: "\f44d"; }
-
-.ion-ios-information-empty:before { content: "\f44b"; }
-
-.ion-ios-information-outline:before { content: "\f44c"; }
-
-.ion-ios-ionic-outline:before { content: "\f44e"; }
-
-.ion-ios-keypad:before { content: "\f450"; }
-
-.ion-ios-keypad-outline:before { content: "\f44f"; }
-
-.ion-ios-lightbulb:before { content: "\f452"; }
-
-.ion-ios-lightbulb-outline:before { content: "\f451"; }
-
-.ion-ios-list:before { content: "\f454"; }
-
-.ion-ios-list-outline:before { content: "\f453"; }
-
-.ion-ios-location:before { content: "\f456"; }
-
-.ion-ios-location-outline:before { content: "\f455"; }
-
-.ion-ios-locked:before { content: "\f458"; }
-
-.ion-ios-locked-outline:before { content: "\f457"; }
-
-.ion-ios-loop:before { content: "\f45a"; }
-
-.ion-ios-loop-strong:before { content: "\f459"; }
-
-.ion-ios-medical:before { content: "\f45c"; }
-
-.ion-ios-medical-outline:before { content: "\f45b"; }
-
-.ion-ios-medkit:before { content: "\f45e"; }
-
-.ion-ios-medkit-outline:before { content: "\f45d"; }
-
-.ion-ios-mic:before { content: "\f461"; }
-
-.ion-ios-mic-off:before { content: "\f45f"; }
-
-.ion-ios-mic-outline:before { content: "\f460"; }
-
-.ion-ios-minus:before { content: "\f464"; }
-
-.ion-ios-minus-empty:before { content: "\f462"; }
-
-.ion-ios-minus-outline:before { content: "\f463"; }
-
-.ion-ios-monitor:before { content: "\f466"; }
-
-.ion-ios-monitor-outline:before { content: "\f465"; }
-
-.ion-ios-moon:before { content: "\f468"; }
-
-.ion-ios-moon-outline:before { content: "\f467"; }
-
-.ion-ios-more:before { content: "\f46a"; }
-
-.ion-ios-more-outline:before { content: "\f469"; }
-
-.ion-ios-musical-note:before { content: "\f46b"; }
-
-.ion-ios-musical-notes:before { content: "\f46c"; }
-
-.ion-ios-navigate:before { content: "\f46e"; }
-
-.ion-ios-navigate-outline:before { content: "\f46d"; }
-
-.ion-ios-nutrition:before { content: "\f470"; }
-
-.ion-ios-nutrition-outline:before { content: "\f46f"; }
-
-.ion-ios-paper:before { content: "\f472"; }
-
-.ion-ios-paper-outline:before { content: "\f471"; }
-
-.ion-ios-paperplane:before { content: "\f474"; }
-
-.ion-ios-paperplane-outline:before { content: "\f473"; }
-
-.ion-ios-partlysunny:before { content: "\f476"; }
-
-.ion-ios-partlysunny-outline:before { content: "\f475"; }
-
-.ion-ios-pause:before { content: "\f478"; }
-
-.ion-ios-pause-outline:before { content: "\f477"; }
-
-.ion-ios-paw:before { content: "\f47a"; }
-
-.ion-ios-paw-outline:before { content: "\f479"; }
-
-.ion-ios-people:before { content: "\f47c"; }
-
-.ion-ios-people-outline:before { content: "\f47b"; }
-
-.ion-ios-person:before { content: "\f47e"; }
-
-.ion-ios-person-outline:before { content: "\f47d"; }
-
-.ion-ios-personadd:before { content: "\f480"; }
-
-.ion-ios-personadd-outline:before { content: "\f47f"; }
-
-.ion-ios-photos:before { content: "\f482"; }
-
-.ion-ios-photos-outline:before { content: "\f481"; }
-
-.ion-ios-pie:before { content: "\f484"; }
-
-.ion-ios-pie-outline:before { content: "\f483"; }
-
-.ion-ios-pint:before { content: "\f486"; }
-
-.ion-ios-pint-outline:before { content: "\f485"; }
-
-.ion-ios-play:before { content: "\f488"; }
-
-.ion-ios-play-outline:before { content: "\f487"; }
-
-.ion-ios-plus:before { content: "\f48b"; }
-
-.ion-ios-plus-empty:before { content: "\f489"; }
-
-.ion-ios-plus-outline:before { content: "\f48a"; }
-
-.ion-ios-pricetag:before { content: "\f48d"; }
-
-.ion-ios-pricetag-outline:before { content: "\f48c"; }
-
-.ion-ios-pricetags:before { content: "\f48f"; }
-
-.ion-ios-pricetags-outline:before { content: "\f48e"; }
-
-.ion-ios-printer:before { content: "\f491"; }
-
-.ion-ios-printer-outline:before { content: "\f490"; }
-
-.ion-ios-pulse:before { content: "\f493"; }
-
-.ion-ios-pulse-strong:before { content: "\f492"; }
-
-.ion-ios-rainy:before { content: "\f495"; }
-
-.ion-ios-rainy-outline:before { content: "\f494"; }
-
-.ion-ios-recording:before { content: "\f497"; }
-
-.ion-ios-recording-outline:before { content: "\f496"; }
-
-.ion-ios-redo:before { content: "\f499"; }
-
-.ion-ios-redo-outline:before { content: "\f498"; }
-
-.ion-ios-refresh:before { content: "\f49c"; }
-
-.ion-ios-refresh-empty:before { content: "\f49a"; }
-
-.ion-ios-refresh-outline:before { content: "\f49b"; }
-
-.ion-ios-reload:before { content: "\f49d"; }
-
-.ion-ios-reverse-camera:before { content: "\f49f"; }
-
-.ion-ios-reverse-camera-outline:before { content: "\f49e"; }
-
-.ion-ios-rewind:before { content: "\f4a1"; }
-
-.ion-ios-rewind-outline:before { content: "\f4a0"; }
-
-.ion-ios-rose:before { content: "\f4a3"; }
-
-.ion-ios-rose-outline:before { content: "\f4a2"; }
-
-.ion-ios-search:before { content: "\f4a5"; }
-
-.ion-ios-search-strong:before { content: "\f4a4"; }
-
-.ion-ios-settings:before { content: "\f4a7"; }
-
-.ion-ios-settings-strong:before { content: "\f4a6"; }
-
-.ion-ios-shuffle:before { content: "\f4a9"; }
-
-.ion-ios-shuffle-strong:before { content: "\f4a8"; }
-
-.ion-ios-skipbackward:before { content: "\f4ab"; }
-
-.ion-ios-skipbackward-outline:before { content: "\f4aa"; }
-
-.ion-ios-skipforward:before { content: "\f4ad"; }
-
-.ion-ios-skipforward-outline:before { content: "\f4ac"; }
-
-.ion-ios-snowy:before { content: "\f4ae"; }
-
-.ion-ios-speedometer:before { content: "\f4b0"; }
-
-.ion-ios-speedometer-outline:before { content: "\f4af"; }
-
-.ion-ios-star:before { content: "\f4b3"; }
-
-.ion-ios-star-half:before { content: "\f4b1"; }
-
-.ion-ios-star-outline:before { content: "\f4b2"; }
-
-.ion-ios-stopwatch:before { content: "\f4b5"; }
-
-.ion-ios-stopwatch-outline:before { content: "\f4b4"; }
-
-.ion-ios-sunny:before { content: "\f4b7"; }
-
-.ion-ios-sunny-outline:before { content: "\f4b6"; }
-
-.ion-ios-telephone:before { content: "\f4b9"; }
-
-.ion-ios-telephone-outline:before { content: "\f4b8"; }
-
-.ion-ios-tennisball:before { content: "\f4bb"; }
-
-.ion-ios-tennisball-outline:before { content: "\f4ba"; }
-
-.ion-ios-thunderstorm:before { content: "\f4bd"; }
-
-.ion-ios-thunderstorm-outline:before { content: "\f4bc"; }
-
-.ion-ios-time:before { content: "\f4bf"; }
-
-.ion-ios-time-outline:before { content: "\f4be"; }
-
-.ion-ios-timer:before { content: "\f4c1"; }
-
-.ion-ios-timer-outline:before { content: "\f4c0"; }
-
-.ion-ios-toggle:before { content: "\f4c3"; }
-
-.ion-ios-toggle-outline:before { content: "\f4c2"; }
-
-.ion-ios-trash:before { content: "\f4c5"; }
-
-.ion-ios-trash-outline:before { content: "\f4c4"; }
-
-.ion-ios-undo:before { content: "\f4c7"; }
-
-.ion-ios-undo-outline:before { content: "\f4c6"; }
-
-.ion-ios-unlocked:before { content: "\f4c9"; }
-
-.ion-ios-unlocked-outline:before { content: "\f4c8"; }
-
-.ion-ios-upload:before { content: "\f4cb"; }
-
-.ion-ios-upload-outline:before { content: "\f4ca"; }
-
-.ion-ios-videocam:before { content: "\f4cd"; }
-
-.ion-ios-videocam-outline:before { content: "\f4cc"; }
-
-.ion-ios-volume-high:before { content: "\f4ce"; }
-
-.ion-ios-volume-low:before { content: "\f4cf"; }
-
-.ion-ios-wineglass:before { content: "\f4d1"; }
-
-.ion-ios-wineglass-outline:before { content: "\f4d0"; }
-
-.ion-ios-world:before { content: "\f4d3"; }
-
-.ion-ios-world-outline:before { content: "\f4d2"; }
-
-.ion-ipad:before { content: "\f1f9"; }
-
-.ion-iphone:before { content: "\f1fa"; }
-
-.ion-ipod:before { content: "\f1fb"; }
-
-.ion-jet:before { content: "\f295"; }
-
-.ion-key:before { content: "\f296"; }
-
-.ion-knife:before { content: "\f297"; }
-
-.ion-laptop:before { content: "\f1fc"; }
-
-.ion-leaf:before { content: "\f1fd"; }
-
-.ion-levels:before { content: "\f298"; }
-
-.ion-lightbulb:before { content: "\f299"; }
-
-.ion-link:before { content: "\f1fe"; }
-
-.ion-load-a:before { content: "\f29a"; }
-
-.ion-load-b:before { content: "\f29b"; }
-
-.ion-load-c:before { content: "\f29c"; }
-
-.ion-load-d:before { content: "\f29d"; }
-
-.ion-location:before { content: "\f1ff"; }
-
-.ion-lock-combination:before { content: "\f4d4"; }
-
-.ion-locked:before { content: "\f200"; }
-
-.ion-log-in:before { content: "\f29e"; }
-
-.ion-log-out:before { content: "\f29f"; }
-
-.ion-loop:before { content: "\f201"; }
-
-.ion-magnet:before { content: "\f2a0"; }
-
-.ion-male:before { content: "\f2a1"; }
-
-.ion-man:before { content: "\f202"; }
-
-.ion-map:before { content: "\f203"; }
-
-.ion-medkit:before { content: "\f2a2"; }
-
-.ion-merge:before { content: "\f33f"; }
-
-.ion-mic-a:before { content: "\f204"; }
-
-.ion-mic-b:before { content: "\f205"; }
-
-.ion-mic-c:before { content: "\f206"; }
-
-.ion-minus:before { content: "\f209"; }
-
-.ion-minus-circled:before { content: "\f207"; }
-
-.ion-minus-round:before { content: "\f208"; }
-
-.ion-model-s:before { content: "\f2c1"; }
-
-.ion-monitor:before { content: "\f20a"; }
-
-.ion-more:before { content: "\f20b"; }
-
-.ion-mouse:before { content: "\f340"; }
-
-.ion-music-note:before { content: "\f20c"; }
-
-.ion-navicon:before { content: "\f20e"; }
-
-.ion-navicon-round:before { content: "\f20d"; }
-
-.ion-navigate:before { content: "\f2a3"; }
-
-.ion-network:before { content: "\f341"; }
-
-.ion-no-smoking:before { content: "\f2c2"; }
-
-.ion-nuclear:before { content: "\f2a4"; }
-
-.ion-outlet:before { content: "\f342"; }
-
-.ion-paintbrush:before { content: "\f4d5"; }
-
-.ion-paintbucket:before { content: "\f4d6"; }
-
-.ion-paper-airplane:before { content: "\f2c3"; }
-
-.ion-paperclip:before { content: "\f20f"; }
-
-.ion-pause:before { content: "\f210"; }
-
-.ion-person:before { content: "\f213"; }
-
-.ion-person-add:before { content: "\f211"; }
-
-.ion-person-stalker:before { content: "\f212"; }
-
-.ion-pie-graph:before { content: "\f2a5"; }
-
-.ion-pin:before { content: "\f2a6"; }
-
-.ion-pinpoint:before { content: "\f2a7"; }
-
-.ion-pizza:before { content: "\f2a8"; }
-
-.ion-plane:before { content: "\f214"; }
-
-.ion-planet:before { content: "\f343"; }
-
-.ion-play:before { content: "\f215"; }
-
-.ion-playstation:before { content: "\f30a"; }
-
-.ion-plus:before { content: "\f218"; }
-
-.ion-plus-circled:before { content: "\f216"; }
-
-.ion-plus-round:before { content: "\f217"; }
-
-.ion-podium:before { content: "\f344"; }
-
-.ion-pound:before { content: "\f219"; }
-
-.ion-power:before { content: "\f2a9"; }
-
-.ion-pricetag:before { content: "\f2aa"; }
-
-.ion-pricetags:before { content: "\f2ab"; }
-
-.ion-printer:before { content: "\f21a"; }
-
-.ion-pull-request:before { content: "\f345"; }
-
-.ion-qr-scanner:before { content: "\f346"; }
-
-.ion-quote:before { content: "\f347"; }
-
-.ion-radio-waves:before { content: "\f2ac"; }
-
-.ion-record:before { content: "\f21b"; }
-
-.ion-refresh:before { content: "\f21c"; }
-
-.ion-reply:before { content: "\f21e"; }
-
-.ion-reply-all:before { content: "\f21d"; }
-
-.ion-ribbon-a:before { content: "\f348"; }
-
-.ion-ribbon-b:before { content: "\f349"; }
-
-.ion-sad:before { content: "\f34a"; }
-
-.ion-sad-outline:before { content: "\f4d7"; }
-
-.ion-scissors:before { content: "\f34b"; }
-
-.ion-search:before { content: "\f21f"; }
-
-.ion-settings:before { content: "\f2ad"; }
-
-.ion-share:before { content: "\f220"; }
-
-.ion-shuffle:before { content: "\f221"; }
-
-.ion-skip-backward:before { content: "\f222"; }
-
-.ion-skip-forward:before { content: "\f223"; }
-
-.ion-social-android:before { content: "\f225"; }
-
-.ion-social-android-outline:before { content: "\f224"; }
-
-.ion-social-angular:before { content: "\f4d9"; }
-
-.ion-social-angular-outline:before { content: "\f4d8"; }
-
-.ion-social-apple:before { content: "\f227"; }
-
-.ion-social-apple-outline:before { content: "\f226"; }
-
-.ion-social-bitcoin:before { content: "\f2af"; }
-
-.ion-social-bitcoin-outline:before { content: "\f2ae"; }
-
-.ion-social-buffer:before { content: "\f229"; }
-
-.ion-social-buffer-outline:before { content: "\f228"; }
-
-.ion-social-chrome:before { content: "\f4db"; }
-
-.ion-social-chrome-outline:before { content: "\f4da"; }
-
-.ion-social-codepen:before { content: "\f4dd"; }
-
-.ion-social-codepen-outline:before { content: "\f4dc"; }
-
-.ion-social-css3:before { content: "\f4df"; }
-
-.ion-social-css3-outline:before { content: "\f4de"; }
-
-.ion-social-designernews:before { content: "\f22b"; }
-
-.ion-social-designernews-outline:before { content: "\f22a"; }
-
-.ion-social-dribbble:before { content: "\f22d"; }
-
-.ion-social-dribbble-outline:before { content: "\f22c"; }
-
-.ion-social-dropbox:before { content: "\f22f"; }
-
-.ion-social-dropbox-outline:before { content: "\f22e"; }
-
-.ion-social-euro:before { content: "\f4e1"; }
-
-.ion-social-euro-outline:before { content: "\f4e0"; }
-
-.ion-social-facebook:before { content: "\f231"; }
-
-.ion-social-facebook-outline:before { content: "\f230"; }
-
-.ion-social-foursquare:before { content: "\f34d"; }
-
-.ion-social-foursquare-outline:before { content: "\f34c"; }
-
-.ion-social-freebsd-devil:before { content: "\f2c4"; }
-
-.ion-social-github:before { content: "\f233"; }
-
-.ion-social-github-outline:before { content: "\f232"; }
-
-.ion-social-google:before { content: "\f34f"; }
-
-.ion-social-google-outline:before { content: "\f34e"; }
-
-.ion-social-googleplus:before { content: "\f235"; }
-
-.ion-social-googleplus-outline:before { content: "\f234"; }
-
-.ion-social-hackernews:before { content: "\f237"; }
-
-.ion-social-hackernews-outline:before { content: "\f236"; }
-
-.ion-social-html5:before { content: "\f4e3"; }
-
-.ion-social-html5-outline:before { content: "\f4e2"; }
-
-.ion-social-instagram:before { content: "\f351"; }
-
-.ion-social-instagram-outline:before { content: "\f350"; }
-
-.ion-social-javascript:before { content: "\f4e5"; }
-
-.ion-social-javascript-outline:before { content: "\f4e4"; }
-
-.ion-social-linkedin:before { content: "\f239"; }
-
-.ion-social-linkedin-outline:before { content: "\f238"; }
-
-.ion-social-markdown:before { content: "\f4e6"; }
-
-.ion-social-nodejs:before { content: "\f4e7"; }
-
-.ion-social-octocat:before { content: "\f4e8"; }
-
-.ion-social-pinterest:before { content: "\f2b1"; }
-
-.ion-social-pinterest-outline:before { content: "\f2b0"; }
-
-.ion-social-python:before { content: "\f4e9"; }
-
-.ion-social-reddit:before { content: "\f23b"; }
-
-.ion-social-reddit-outline:before { content: "\f23a"; }
-
-.ion-social-rss:before { content: "\f23d"; }
-
-.ion-social-rss-outline:before { content: "\f23c"; }
-
-.ion-social-sass:before { content: "\f4ea"; }
-
-.ion-social-skype:before { content: "\f23f"; }
-
-.ion-social-skype-outline:before { content: "\f23e"; }
-
-.ion-social-snapchat:before { content: "\f4ec"; }
-
-.ion-social-snapchat-outline:before { content: "\f4eb"; }
-
-.ion-social-tumblr:before { content: "\f241"; }
-
-.ion-social-tumblr-outline:before { content: "\f240"; }
-
-.ion-social-tux:before { content: "\f2c5"; }
-
-.ion-social-twitch:before { content: "\f4ee"; }
-
-.ion-social-twitch-outline:before { content: "\f4ed"; }
-
-.ion-social-twitter:before { content: "\f243"; }
-
-.ion-social-twitter-outline:before { content: "\f242"; }
-
-.ion-social-usd:before { content: "\f353"; }
-
-.ion-social-usd-outline:before { content: "\f352"; }
-
-.ion-social-vimeo:before { content: "\f245"; }
-
-.ion-social-vimeo-outline:before { content: "\f244"; }
-
-.ion-social-whatsapp:before { content: "\f4f0"; }
-
-.ion-social-whatsapp-outline:before { content: "\f4ef"; }
-
-.ion-social-windows:before { content: "\f247"; }
-
-.ion-social-windows-outline:before { content: "\f246"; }
-
-.ion-social-wordpress:before { content: "\f249"; }
-
-.ion-social-wordpress-outline:before { content: "\f248"; }
-
-.ion-social-yahoo:before { content: "\f24b"; }
-
-.ion-social-yahoo-outline:before { content: "\f24a"; }
-
-.ion-social-yen:before { content: "\f4f2"; }
-
-.ion-social-yen-outline:before { content: "\f4f1"; }
-
-.ion-social-youtube:before { content: "\f24d"; }
-
-.ion-social-youtube-outline:before { content: "\f24c"; }
-
-.ion-soup-can:before { content: "\f4f4"; }
-
-.ion-soup-can-outline:before { content: "\f4f3"; }
-
-.ion-speakerphone:before { content: "\f2b2"; }
-
-.ion-speedometer:before { content: "\f2b3"; }
-
-.ion-spoon:before { content: "\f2b4"; }
-
-.ion-star:before { content: "\f24e"; }
-
-.ion-stats-bars:before { content: "\f2b5"; }
-
-.ion-steam:before { content: "\f30b"; }
-
-.ion-stop:before { content: "\f24f"; }
-
-.ion-thermometer:before { content: "\f2b6"; }
-
-.ion-thumbsdown:before { content: "\f250"; }
-
-.ion-thumbsup:before { content: "\f251"; }
-
-.ion-toggle:before { content: "\f355"; }
-
-.ion-toggle-filled:before { content: "\f354"; }
-
-.ion-transgender:before { content: "\f4f5"; }
-
-.ion-trash-a:before { content: "\f252"; }
-
-.ion-trash-b:before { content: "\f253"; }
-
-.ion-trophy:before { content: "\f356"; }
-
-.ion-tshirt:before { content: "\f4f7"; }
-
-.ion-tshirt-outline:before { content: "\f4f6"; }
-
-.ion-umbrella:before { content: "\f2b7"; }
-
-.ion-university:before { content: "\f357"; }
-
-.ion-unlocked:before { content: "\f254"; }
-
-.ion-upload:before { content: "\f255"; }
-
-.ion-usb:before { content: "\f2b8"; }
-
-.ion-videocamera:before { content: "\f256"; }
-
-.ion-volume-high:before { content: "\f257"; }
-
-.ion-volume-low:before { content: "\f258"; }
-
-.ion-volume-medium:before { content: "\f259"; }
-
-.ion-volume-mute:before { content: "\f25a"; }
-
-.ion-wand:before { content: "\f358"; }
-
-.ion-waterdrop:before { content: "\f25b"; }
-
-.ion-wifi:before { content: "\f25c"; }
-
-.ion-wineglass:before { content: "\f2b9"; }
-
-.ion-woman:before { content: "\f25d"; }
-
-.ion-wrench:before { content: "\f2ba"; }
-
-.ion-xbox:before { content: "\f30c"; }
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.min.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.min.css
deleted file mode 100644
index baba9e93..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/css/ionicons.min.css
+++ /dev/null
@@ -1,11 +0,0 @@
-@charset "UTF-8";/*!
- Ionicons, v2.0.0
- Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
- https://twitter.com/benjsperry https://twitter.com/ionicframework
- MIT License: https://github.com/driftyco/ionicons
-
- Android-style icons originally built by Google’s
- Material Design Icons: https://github.com/google/material-design-icons
- used under CC BY http://creativecommons.org/licenses/by/4.0/
- Modified icons to fit ionicon’s grid from original.
-*/@font-face{font-family:"Ionicons";src:url("../fonts/ionicons.eot?v=2.0.0");src:url("../fonts/ionicons.eot?v=2.0.0#iefix") format("embedded-opentype"),url("../fonts/ionicons.ttf?v=2.0.0") format("truetype"),url("../fonts/ionicons.woff?v=2.0.0") format("woff"),url("../fonts/ionicons.svg?v=2.0.0#Ionicons") format("svg");font-weight:normal;font-style:normal}.ion,.ionicons,.ion-alert:before,.ion-alert-circled:before,.ion-android-add:before,.ion-android-add-circle:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done:before,.ion-android-done-all:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite:before,.ion-android-favorite-outline:before,.ion-android-film:before,.ion-android-folder:before,.ion-android-folder-open:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone:before,.ion-android-microphone-off:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person:before,.ion-android-person-add:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove:before,.ion-android-remove-circle:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share:before,.ion-android-share-alt:before,.ion-android-star:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace:before,.ion-backspace-outline:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox:before,.ion-chatbox-working:before,.ion-chatboxes:before,.ion-chatbubble:before,.ion-chatbubble-working:before,.ion-chatbubbles:before,.ion-checkmark:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close:before,.ion-close-circled:before,.ion-close-round:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code:before,.ion-code-download:before,.ion-code-working:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document:before,.ion-document-text:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email:before,.ion-email-unread:before,.ion-erlenmeyer-flask:before,.ion-erlenmeyer-flask-bubbles:before,.ion-eye:before,.ion-eye-disabled:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash:before,.ion-flash-off:before,.ion-folder:before,.ion-fork:before,.ion-fork-repo:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy:before,.ion-happy-outline:before,.ion-headphone:before,.ion-heart:before,.ion-heart-broken:before,.ion-help:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information:before,.ion-information-circled:before,.ion-ionic:before,.ion-ios-alarm:before,.ion-ios-alarm-outline:before,.ion-ios-albums:before,.ion-ios-albums-outline:before,.ion-ios-americanfootball:before,.ion-ios-americanfootball-outline:before,.ion-ios-analytics:before,.ion-ios-analytics-outline:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at:before,.ion-ios-at-outline:before,.ion-ios-barcode:before,.ion-ios-barcode-outline:before,.ion-ios-baseball:before,.ion-ios-baseball-outline:before,.ion-ios-basketball:before,.ion-ios-basketball-outline:before,.ion-ios-bell:before,.ion-ios-bell-outline:before,.ion-ios-body:before,.ion-ios-body-outline:before,.ion-ios-bolt:before,.ion-ios-bolt-outline:before,.ion-ios-book:before,.ion-ios-book-outline:before,.ion-ios-bookmarks:before,.ion-ios-bookmarks-outline:before,.ion-ios-box:before,.ion-ios-box-outline:before,.ion-ios-briefcase:before,.ion-ios-briefcase-outline:before,.ion-ios-browsers:before,.ion-ios-browsers-outline:before,.ion-ios-calculator:before,.ion-ios-calculator-outline:before,.ion-ios-calendar:before,.ion-ios-calendar-outline:before,.ion-ios-camera:before,.ion-ios-camera-outline:before,.ion-ios-cart:before,.ion-ios-cart-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatbubble:before,.ion-ios-chatbubble-outline:before,.ion-ios-checkmark:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock:before,.ion-ios-clock-outline:before,.ion-ios-close:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-cloud:before,.ion-ios-cloud-download:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloudy:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-outline:before,.ion-ios-cog:before,.ion-ios-cog-outline:before,.ion-ios-color-filter:before,.ion-ios-color-filter-outline:before,.ion-ios-color-wand:before,.ion-ios-color-wand-outline:before,.ion-ios-compose:before,.ion-ios-compose-outline:before,.ion-ios-contact:before,.ion-ios-contact-outline:before,.ion-ios-copy:before,.ion-ios-copy-outline:before,.ion-ios-crop:before,.ion-ios-crop-strong:before,.ion-ios-download:before,.ion-ios-download-outline:before,.ion-ios-drag:before,.ion-ios-email:before,.ion-ios-email-outline:before,.ion-ios-eye:before,.ion-ios-eye-outline:before,.ion-ios-fastforward:before,.ion-ios-fastforward-outline:before,.ion-ios-filing:before,.ion-ios-filing-outline:before,.ion-ios-film:before,.ion-ios-film-outline:before,.ion-ios-flag:before,.ion-ios-flag-outline:before,.ion-ios-flame:before,.ion-ios-flame-outline:before,.ion-ios-flask:before,.ion-ios-flask-outline:before,.ion-ios-flower:before,.ion-ios-flower-outline:before,.ion-ios-folder:before,.ion-ios-folder-outline:before,.ion-ios-football:before,.ion-ios-football-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-b:before,.ion-ios-game-controller-b-outline:before,.ion-ios-gear:before,.ion-ios-gear-outline:before,.ion-ios-glasses:before,.ion-ios-glasses-outline:before,.ion-ios-grid-view:before,.ion-ios-grid-view-outline:before,.ion-ios-heart:before,.ion-ios-heart-outline:before,.ion-ios-help:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-home:before,.ion-ios-home-outline:before,.ion-ios-infinite:before,.ion-ios-infinite-outline:before,.ion-ios-information:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-ionic-outline:before,.ion-ios-keypad:before,.ion-ios-keypad-outline:before,.ion-ios-lightbulb:before,.ion-ios-lightbulb-outline:before,.ion-ios-list:before,.ion-ios-list-outline:before,.ion-ios-location:before,.ion-ios-location-outline:before,.ion-ios-locked:before,.ion-ios-locked-outline:before,.ion-ios-loop:before,.ion-ios-loop-strong:before,.ion-ios-medical:before,.ion-ios-medical-outline:before,.ion-ios-medkit:before,.ion-ios-medkit-outline:before,.ion-ios-mic:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-minus:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-monitor:before,.ion-ios-monitor-outline:before,.ion-ios-moon:before,.ion-ios-moon-outline:before,.ion-ios-more:before,.ion-ios-more-outline:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate:before,.ion-ios-navigate-outline:before,.ion-ios-nutrition:before,.ion-ios-nutrition-outline:before,.ion-ios-paper:before,.ion-ios-paper-outline:before,.ion-ios-paperplane:before,.ion-ios-paperplane-outline:before,.ion-ios-partlysunny:before,.ion-ios-partlysunny-outline:before,.ion-ios-pause:before,.ion-ios-pause-outline:before,.ion-ios-paw:before,.ion-ios-paw-outline:before,.ion-ios-people:before,.ion-ios-people-outline:before,.ion-ios-person:before,.ion-ios-person-outline:before,.ion-ios-personadd:before,.ion-ios-personadd-outline:before,.ion-ios-photos:before,.ion-ios-photos-outline:before,.ion-ios-pie:before,.ion-ios-pie-outline:before,.ion-ios-pint:before,.ion-ios-pint-outline:before,.ion-ios-play:before,.ion-ios-play-outline:before,.ion-ios-plus:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetags:before,.ion-ios-pricetags-outline:before,.ion-ios-printer:before,.ion-ios-printer-outline:before,.ion-ios-pulse:before,.ion-ios-pulse-strong:before,.ion-ios-rainy:before,.ion-ios-rainy-outline:before,.ion-ios-recording:before,.ion-ios-recording-outline:before,.ion-ios-redo:before,.ion-ios-redo-outline:before,.ion-ios-refresh:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-reload:before,.ion-ios-reverse-camera:before,.ion-ios-reverse-camera-outline:before,.ion-ios-rewind:before,.ion-ios-rewind-outline:before,.ion-ios-rose:before,.ion-ios-rose-outline:before,.ion-ios-search:before,.ion-ios-search-strong:before,.ion-ios-settings:before,.ion-ios-settings-strong:before,.ion-ios-shuffle:before,.ion-ios-shuffle-strong:before,.ion-ios-skipbackward:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipforward:before,.ion-ios-skipforward-outline:before,.ion-ios-snowy:before,.ion-ios-speedometer:before,.ion-ios-speedometer-outline:before,.ion-ios-star:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-stopwatch:before,.ion-ios-stopwatch-outline:before,.ion-ios-sunny:before,.ion-ios-sunny-outline:before,.ion-ios-telephone:before,.ion-ios-telephone-outline:before,.ion-ios-tennisball:before,.ion-ios-tennisball-outline:before,.ion-ios-thunderstorm:before,.ion-ios-thunderstorm-outline:before,.ion-ios-time:before,.ion-ios-time-outline:before,.ion-ios-timer:before,.ion-ios-timer-outline:before,.ion-ios-toggle:before,.ion-ios-toggle-outline:before,.ion-ios-trash:before,.ion-ios-trash-outline:before,.ion-ios-undo:before,.ion-ios-undo-outline:before,.ion-ios-unlocked:before,.ion-ios-unlocked-outline:before,.ion-ios-upload:before,.ion-ios-upload-outline:before,.ion-ios-videocam:before,.ion-ios-videocam-outline:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass:before,.ion-ios-wineglass-outline:before,.ion-ios-world:before,.ion-ios-world-outline:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon:before,.ion-navicon-round:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person:before,.ion-person-add:before,.ion-person-stalker:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply:before,.ion-reply-all:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad:before,.ion-sad-outline:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android:before,.ion-social-android-outline:before,.ion-social-angular:before,.ion-social-angular-outline:before,.ion-social-apple:before,.ion-social-apple-outline:before,.ion-social-bitcoin:before,.ion-social-bitcoin-outline:before,.ion-social-buffer:before,.ion-social-buffer-outline:before,.ion-social-chrome:before,.ion-social-chrome-outline:before,.ion-social-codepen:before,.ion-social-codepen-outline:before,.ion-social-css3:before,.ion-social-css3-outline:before,.ion-social-designernews:before,.ion-social-designernews-outline:before,.ion-social-dribbble:before,.ion-social-dribbble-outline:before,.ion-social-dropbox:before,.ion-social-dropbox-outline:before,.ion-social-euro:before,.ion-social-euro-outline:before,.ion-social-facebook:before,.ion-social-facebook-outline:before,.ion-social-foursquare:before,.ion-social-foursquare-outline:before,.ion-social-freebsd-devil:before,.ion-social-github:before,.ion-social-github-outline:before,.ion-social-google:before,.ion-social-google-outline:before,.ion-social-googleplus:before,.ion-social-googleplus-outline:before,.ion-social-hackernews:before,.ion-social-hackernews-outline:before,.ion-social-html5:before,.ion-social-html5-outline:before,.ion-social-instagram:before,.ion-social-instagram-outline:before,.ion-social-javascript:before,.ion-social-javascript-outline:before,.ion-social-linkedin:before,.ion-social-linkedin-outline:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest:before,.ion-social-pinterest-outline:before,.ion-social-python:before,.ion-social-reddit:before,.ion-social-reddit-outline:before,.ion-social-rss:before,.ion-social-rss-outline:before,.ion-social-sass:before,.ion-social-skype:before,.ion-social-skype-outline:before,.ion-social-snapchat:before,.ion-social-snapchat-outline:before,.ion-social-tumblr:before,.ion-social-tumblr-outline:before,.ion-social-tux:before,.ion-social-twitch:before,.ion-social-twitch-outline:before,.ion-social-twitter:before,.ion-social-twitter-outline:before,.ion-social-usd:before,.ion-social-usd-outline:before,.ion-social-vimeo:before,.ion-social-vimeo-outline:before,.ion-social-whatsapp:before,.ion-social-whatsapp-outline:before,.ion-social-windows:before,.ion-social-windows-outline:before,.ion-social-wordpress:before,.ion-social-wordpress-outline:before,.ion-social-yahoo:before,.ion-social-yahoo-outline:before,.ion-social-yen:before,.ion-social-yen-outline:before,.ion-social-youtube:before,.ion-social-youtube-outline:before,.ion-soup-can:before,.ion-soup-can-outline:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle:before,.ion-toggle-filled:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt:before,.ion-tshirt-outline:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before{display:inline-block;font-family:"Ionicons";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-font.less b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-font.less
deleted file mode 100644
index 1d9bf7ee..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-font.less
+++ /dev/null
@@ -1,27 +0,0 @@
-// Ionicons Font Path
-// --------------------------
-
-@font-face {
- font-family: @ionicons-font-family;
- src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}");
- src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}#iefix") format("embedded-opentype"),
- url("@{ionicons-font-path}/ionicons.ttf?v=@{ionicons-version}") format("truetype"),
- url("@{ionicons-font-path}/ionicons.woff?v=@{ionicons-version}") format("woff"),
- url("@{ionicons-font-path}/ionicons.svg?v=@{ionicons-version}#Ionicons") format("svg");
- font-weight: normal;
- font-style: normal;
-}
-
-.ion {
- display: inline-block;
- font-family: @ionicons-font-family;
- speak: none;
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- text-transform: none;
- text-rendering: auto;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-icons.less b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-icons.less
deleted file mode 100644
index 5e6052e9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-icons.less
+++ /dev/null
@@ -1,1473 +0,0 @@
-// Ionicons Icons
-// --------------------------
-
-.ionicons,
-.@{ionicons-prefix}alert:before,
-.@{ionicons-prefix}alert-circled:before,
-.@{ionicons-prefix}android-add:before,
-.@{ionicons-prefix}android-add-circle:before,
-.@{ionicons-prefix}android-alarm-clock:before,
-.@{ionicons-prefix}android-alert:before,
-.@{ionicons-prefix}android-apps:before,
-.@{ionicons-prefix}android-archive:before,
-.@{ionicons-prefix}android-arrow-back:before,
-.@{ionicons-prefix}android-arrow-down:before,
-.@{ionicons-prefix}android-arrow-dropdown:before,
-.@{ionicons-prefix}android-arrow-dropdown-circle:before,
-.@{ionicons-prefix}android-arrow-dropleft:before,
-.@{ionicons-prefix}android-arrow-dropleft-circle:before,
-.@{ionicons-prefix}android-arrow-dropright:before,
-.@{ionicons-prefix}android-arrow-dropright-circle:before,
-.@{ionicons-prefix}android-arrow-dropup:before,
-.@{ionicons-prefix}android-arrow-dropup-circle:before,
-.@{ionicons-prefix}android-arrow-forward:before,
-.@{ionicons-prefix}android-arrow-up:before,
-.@{ionicons-prefix}android-attach:before,
-.@{ionicons-prefix}android-bar:before,
-.@{ionicons-prefix}android-bicycle:before,
-.@{ionicons-prefix}android-boat:before,
-.@{ionicons-prefix}android-bookmark:before,
-.@{ionicons-prefix}android-bulb:before,
-.@{ionicons-prefix}android-bus:before,
-.@{ionicons-prefix}android-calendar:before,
-.@{ionicons-prefix}android-call:before,
-.@{ionicons-prefix}android-camera:before,
-.@{ionicons-prefix}android-cancel:before,
-.@{ionicons-prefix}android-car:before,
-.@{ionicons-prefix}android-cart:before,
-.@{ionicons-prefix}android-chat:before,
-.@{ionicons-prefix}android-checkbox:before,
-.@{ionicons-prefix}android-checkbox-blank:before,
-.@{ionicons-prefix}android-checkbox-outline:before,
-.@{ionicons-prefix}android-checkbox-outline-blank:before,
-.@{ionicons-prefix}android-checkmark-circle:before,
-.@{ionicons-prefix}android-clipboard:before,
-.@{ionicons-prefix}android-close:before,
-.@{ionicons-prefix}android-cloud:before,
-.@{ionicons-prefix}android-cloud-circle:before,
-.@{ionicons-prefix}android-cloud-done:before,
-.@{ionicons-prefix}android-cloud-outline:before,
-.@{ionicons-prefix}android-color-palette:before,
-.@{ionicons-prefix}android-compass:before,
-.@{ionicons-prefix}android-contact:before,
-.@{ionicons-prefix}android-contacts:before,
-.@{ionicons-prefix}android-contract:before,
-.@{ionicons-prefix}android-create:before,
-.@{ionicons-prefix}android-delete:before,
-.@{ionicons-prefix}android-desktop:before,
-.@{ionicons-prefix}android-document:before,
-.@{ionicons-prefix}android-done:before,
-.@{ionicons-prefix}android-done-all:before,
-.@{ionicons-prefix}android-download:before,
-.@{ionicons-prefix}android-drafts:before,
-.@{ionicons-prefix}android-exit:before,
-.@{ionicons-prefix}android-expand:before,
-.@{ionicons-prefix}android-favorite:before,
-.@{ionicons-prefix}android-favorite-outline:before,
-.@{ionicons-prefix}android-film:before,
-.@{ionicons-prefix}android-folder:before,
-.@{ionicons-prefix}android-folder-open:before,
-.@{ionicons-prefix}android-funnel:before,
-.@{ionicons-prefix}android-globe:before,
-.@{ionicons-prefix}android-hand:before,
-.@{ionicons-prefix}android-hangout:before,
-.@{ionicons-prefix}android-happy:before,
-.@{ionicons-prefix}android-home:before,
-.@{ionicons-prefix}android-image:before,
-.@{ionicons-prefix}android-laptop:before,
-.@{ionicons-prefix}android-list:before,
-.@{ionicons-prefix}android-locate:before,
-.@{ionicons-prefix}android-lock:before,
-.@{ionicons-prefix}android-mail:before,
-.@{ionicons-prefix}android-map:before,
-.@{ionicons-prefix}android-menu:before,
-.@{ionicons-prefix}android-microphone:before,
-.@{ionicons-prefix}android-microphone-off:before,
-.@{ionicons-prefix}android-more-horizontal:before,
-.@{ionicons-prefix}android-more-vertical:before,
-.@{ionicons-prefix}android-navigate:before,
-.@{ionicons-prefix}android-notifications:before,
-.@{ionicons-prefix}android-notifications-none:before,
-.@{ionicons-prefix}android-notifications-off:before,
-.@{ionicons-prefix}android-open:before,
-.@{ionicons-prefix}android-options:before,
-.@{ionicons-prefix}android-people:before,
-.@{ionicons-prefix}android-person:before,
-.@{ionicons-prefix}android-person-add:before,
-.@{ionicons-prefix}android-phone-landscape:before,
-.@{ionicons-prefix}android-phone-portrait:before,
-.@{ionicons-prefix}android-pin:before,
-.@{ionicons-prefix}android-plane:before,
-.@{ionicons-prefix}android-playstore:before,
-.@{ionicons-prefix}android-print:before,
-.@{ionicons-prefix}android-radio-button-off:before,
-.@{ionicons-prefix}android-radio-button-on:before,
-.@{ionicons-prefix}android-refresh:before,
-.@{ionicons-prefix}android-remove:before,
-.@{ionicons-prefix}android-remove-circle:before,
-.@{ionicons-prefix}android-restaurant:before,
-.@{ionicons-prefix}android-sad:before,
-.@{ionicons-prefix}android-search:before,
-.@{ionicons-prefix}android-send:before,
-.@{ionicons-prefix}android-settings:before,
-.@{ionicons-prefix}android-share:before,
-.@{ionicons-prefix}android-share-alt:before,
-.@{ionicons-prefix}android-star:before,
-.@{ionicons-prefix}android-star-half:before,
-.@{ionicons-prefix}android-star-outline:before,
-.@{ionicons-prefix}android-stopwatch:before,
-.@{ionicons-prefix}android-subway:before,
-.@{ionicons-prefix}android-sunny:before,
-.@{ionicons-prefix}android-sync:before,
-.@{ionicons-prefix}android-textsms:before,
-.@{ionicons-prefix}android-time:before,
-.@{ionicons-prefix}android-train:before,
-.@{ionicons-prefix}android-unlock:before,
-.@{ionicons-prefix}android-upload:before,
-.@{ionicons-prefix}android-volume-down:before,
-.@{ionicons-prefix}android-volume-mute:before,
-.@{ionicons-prefix}android-volume-off:before,
-.@{ionicons-prefix}android-volume-up:before,
-.@{ionicons-prefix}android-walk:before,
-.@{ionicons-prefix}android-warning:before,
-.@{ionicons-prefix}android-watch:before,
-.@{ionicons-prefix}android-wifi:before,
-.@{ionicons-prefix}aperture:before,
-.@{ionicons-prefix}archive:before,
-.@{ionicons-prefix}arrow-down-a:before,
-.@{ionicons-prefix}arrow-down-b:before,
-.@{ionicons-prefix}arrow-down-c:before,
-.@{ionicons-prefix}arrow-expand:before,
-.@{ionicons-prefix}arrow-graph-down-left:before,
-.@{ionicons-prefix}arrow-graph-down-right:before,
-.@{ionicons-prefix}arrow-graph-up-left:before,
-.@{ionicons-prefix}arrow-graph-up-right:before,
-.@{ionicons-prefix}arrow-left-a:before,
-.@{ionicons-prefix}arrow-left-b:before,
-.@{ionicons-prefix}arrow-left-c:before,
-.@{ionicons-prefix}arrow-move:before,
-.@{ionicons-prefix}arrow-resize:before,
-.@{ionicons-prefix}arrow-return-left:before,
-.@{ionicons-prefix}arrow-return-right:before,
-.@{ionicons-prefix}arrow-right-a:before,
-.@{ionicons-prefix}arrow-right-b:before,
-.@{ionicons-prefix}arrow-right-c:before,
-.@{ionicons-prefix}arrow-shrink:before,
-.@{ionicons-prefix}arrow-swap:before,
-.@{ionicons-prefix}arrow-up-a:before,
-.@{ionicons-prefix}arrow-up-b:before,
-.@{ionicons-prefix}arrow-up-c:before,
-.@{ionicons-prefix}asterisk:before,
-.@{ionicons-prefix}at:before,
-.@{ionicons-prefix}backspace:before,
-.@{ionicons-prefix}backspace-outline:before,
-.@{ionicons-prefix}bag:before,
-.@{ionicons-prefix}battery-charging:before,
-.@{ionicons-prefix}battery-empty:before,
-.@{ionicons-prefix}battery-full:before,
-.@{ionicons-prefix}battery-half:before,
-.@{ionicons-prefix}battery-low:before,
-.@{ionicons-prefix}beaker:before,
-.@{ionicons-prefix}beer:before,
-.@{ionicons-prefix}bluetooth:before,
-.@{ionicons-prefix}bonfire:before,
-.@{ionicons-prefix}bookmark:before,
-.@{ionicons-prefix}bowtie:before,
-.@{ionicons-prefix}briefcase:before,
-.@{ionicons-prefix}bug:before,
-.@{ionicons-prefix}calculator:before,
-.@{ionicons-prefix}calendar:before,
-.@{ionicons-prefix}camera:before,
-.@{ionicons-prefix}card:before,
-.@{ionicons-prefix}cash:before,
-.@{ionicons-prefix}chatbox:before,
-.@{ionicons-prefix}chatbox-working:before,
-.@{ionicons-prefix}chatboxes:before,
-.@{ionicons-prefix}chatbubble:before,
-.@{ionicons-prefix}chatbubble-working:before,
-.@{ionicons-prefix}chatbubbles:before,
-.@{ionicons-prefix}checkmark:before,
-.@{ionicons-prefix}checkmark-circled:before,
-.@{ionicons-prefix}checkmark-round:before,
-.@{ionicons-prefix}chevron-down:before,
-.@{ionicons-prefix}chevron-left:before,
-.@{ionicons-prefix}chevron-right:before,
-.@{ionicons-prefix}chevron-up:before,
-.@{ionicons-prefix}clipboard:before,
-.@{ionicons-prefix}clock:before,
-.@{ionicons-prefix}close:before,
-.@{ionicons-prefix}close-circled:before,
-.@{ionicons-prefix}close-round:before,
-.@{ionicons-prefix}closed-captioning:before,
-.@{ionicons-prefix}cloud:before,
-.@{ionicons-prefix}code:before,
-.@{ionicons-prefix}code-download:before,
-.@{ionicons-prefix}code-working:before,
-.@{ionicons-prefix}coffee:before,
-.@{ionicons-prefix}compass:before,
-.@{ionicons-prefix}compose:before,
-.@{ionicons-prefix}connection-bars:before,
-.@{ionicons-prefix}contrast:before,
-.@{ionicons-prefix}crop:before,
-.@{ionicons-prefix}cube:before,
-.@{ionicons-prefix}disc:before,
-.@{ionicons-prefix}document:before,
-.@{ionicons-prefix}document-text:before,
-.@{ionicons-prefix}drag:before,
-.@{ionicons-prefix}earth:before,
-.@{ionicons-prefix}easel:before,
-.@{ionicons-prefix}edit:before,
-.@{ionicons-prefix}egg:before,
-.@{ionicons-prefix}eject:before,
-.@{ionicons-prefix}email:before,
-.@{ionicons-prefix}email-unread:before,
-.@{ionicons-prefix}erlenmeyer-flask:before,
-.@{ionicons-prefix}erlenmeyer-flask-bubbles:before,
-.@{ionicons-prefix}eye:before,
-.@{ionicons-prefix}eye-disabled:before,
-.@{ionicons-prefix}female:before,
-.@{ionicons-prefix}filing:before,
-.@{ionicons-prefix}film-marker:before,
-.@{ionicons-prefix}fireball:before,
-.@{ionicons-prefix}flag:before,
-.@{ionicons-prefix}flame:before,
-.@{ionicons-prefix}flash:before,
-.@{ionicons-prefix}flash-off:before,
-.@{ionicons-prefix}folder:before,
-.@{ionicons-prefix}fork:before,
-.@{ionicons-prefix}fork-repo:before,
-.@{ionicons-prefix}forward:before,
-.@{ionicons-prefix}funnel:before,
-.@{ionicons-prefix}gear-a:before,
-.@{ionicons-prefix}gear-b:before,
-.@{ionicons-prefix}grid:before,
-.@{ionicons-prefix}hammer:before,
-.@{ionicons-prefix}happy:before,
-.@{ionicons-prefix}happy-outline:before,
-.@{ionicons-prefix}headphone:before,
-.@{ionicons-prefix}heart:before,
-.@{ionicons-prefix}heart-broken:before,
-.@{ionicons-prefix}help:before,
-.@{ionicons-prefix}help-buoy:before,
-.@{ionicons-prefix}help-circled:before,
-.@{ionicons-prefix}home:before,
-.@{ionicons-prefix}icecream:before,
-.@{ionicons-prefix}image:before,
-.@{ionicons-prefix}images:before,
-.@{ionicons-prefix}information:before,
-.@{ionicons-prefix}information-circled:before,
-.@{ionicons-prefix}ionic:before,
-.@{ionicons-prefix}ios-alarm:before,
-.@{ionicons-prefix}ios-alarm-outline:before,
-.@{ionicons-prefix}ios-albums:before,
-.@{ionicons-prefix}ios-albums-outline:before,
-.@{ionicons-prefix}ios-americanfootball:before,
-.@{ionicons-prefix}ios-americanfootball-outline:before,
-.@{ionicons-prefix}ios-analytics:before,
-.@{ionicons-prefix}ios-analytics-outline:before,
-.@{ionicons-prefix}ios-arrow-back:before,
-.@{ionicons-prefix}ios-arrow-down:before,
-.@{ionicons-prefix}ios-arrow-forward:before,
-.@{ionicons-prefix}ios-arrow-left:before,
-.@{ionicons-prefix}ios-arrow-right:before,
-.@{ionicons-prefix}ios-arrow-thin-down:before,
-.@{ionicons-prefix}ios-arrow-thin-left:before,
-.@{ionicons-prefix}ios-arrow-thin-right:before,
-.@{ionicons-prefix}ios-arrow-thin-up:before,
-.@{ionicons-prefix}ios-arrow-up:before,
-.@{ionicons-prefix}ios-at:before,
-.@{ionicons-prefix}ios-at-outline:before,
-.@{ionicons-prefix}ios-barcode:before,
-.@{ionicons-prefix}ios-barcode-outline:before,
-.@{ionicons-prefix}ios-baseball:before,
-.@{ionicons-prefix}ios-baseball-outline:before,
-.@{ionicons-prefix}ios-basketball:before,
-.@{ionicons-prefix}ios-basketball-outline:before,
-.@{ionicons-prefix}ios-bell:before,
-.@{ionicons-prefix}ios-bell-outline:before,
-.@{ionicons-prefix}ios-body:before,
-.@{ionicons-prefix}ios-body-outline:before,
-.@{ionicons-prefix}ios-bolt:before,
-.@{ionicons-prefix}ios-bolt-outline:before,
-.@{ionicons-prefix}ios-book:before,
-.@{ionicons-prefix}ios-book-outline:before,
-.@{ionicons-prefix}ios-bookmarks:before,
-.@{ionicons-prefix}ios-bookmarks-outline:before,
-.@{ionicons-prefix}ios-box:before,
-.@{ionicons-prefix}ios-box-outline:before,
-.@{ionicons-prefix}ios-briefcase:before,
-.@{ionicons-prefix}ios-briefcase-outline:before,
-.@{ionicons-prefix}ios-browsers:before,
-.@{ionicons-prefix}ios-browsers-outline:before,
-.@{ionicons-prefix}ios-calculator:before,
-.@{ionicons-prefix}ios-calculator-outline:before,
-.@{ionicons-prefix}ios-calendar:before,
-.@{ionicons-prefix}ios-calendar-outline:before,
-.@{ionicons-prefix}ios-camera:before,
-.@{ionicons-prefix}ios-camera-outline:before,
-.@{ionicons-prefix}ios-cart:before,
-.@{ionicons-prefix}ios-cart-outline:before,
-.@{ionicons-prefix}ios-chatboxes:before,
-.@{ionicons-prefix}ios-chatboxes-outline:before,
-.@{ionicons-prefix}ios-chatbubble:before,
-.@{ionicons-prefix}ios-chatbubble-outline:before,
-.@{ionicons-prefix}ios-checkmark:before,
-.@{ionicons-prefix}ios-checkmark-empty:before,
-.@{ionicons-prefix}ios-checkmark-outline:before,
-.@{ionicons-prefix}ios-circle-filled:before,
-.@{ionicons-prefix}ios-circle-outline:before,
-.@{ionicons-prefix}ios-clock:before,
-.@{ionicons-prefix}ios-clock-outline:before,
-.@{ionicons-prefix}ios-close:before,
-.@{ionicons-prefix}ios-close-empty:before,
-.@{ionicons-prefix}ios-close-outline:before,
-.@{ionicons-prefix}ios-cloud:before,
-.@{ionicons-prefix}ios-cloud-download:before,
-.@{ionicons-prefix}ios-cloud-download-outline:before,
-.@{ionicons-prefix}ios-cloud-outline:before,
-.@{ionicons-prefix}ios-cloud-upload:before,
-.@{ionicons-prefix}ios-cloud-upload-outline:before,
-.@{ionicons-prefix}ios-cloudy:before,
-.@{ionicons-prefix}ios-cloudy-night:before,
-.@{ionicons-prefix}ios-cloudy-night-outline:before,
-.@{ionicons-prefix}ios-cloudy-outline:before,
-.@{ionicons-prefix}ios-cog:before,
-.@{ionicons-prefix}ios-cog-outline:before,
-.@{ionicons-prefix}ios-color-filter:before,
-.@{ionicons-prefix}ios-color-filter-outline:before,
-.@{ionicons-prefix}ios-color-wand:before,
-.@{ionicons-prefix}ios-color-wand-outline:before,
-.@{ionicons-prefix}ios-compose:before,
-.@{ionicons-prefix}ios-compose-outline:before,
-.@{ionicons-prefix}ios-contact:before,
-.@{ionicons-prefix}ios-contact-outline:before,
-.@{ionicons-prefix}ios-copy:before,
-.@{ionicons-prefix}ios-copy-outline:before,
-.@{ionicons-prefix}ios-crop:before,
-.@{ionicons-prefix}ios-crop-strong:before,
-.@{ionicons-prefix}ios-download:before,
-.@{ionicons-prefix}ios-download-outline:before,
-.@{ionicons-prefix}ios-drag:before,
-.@{ionicons-prefix}ios-email:before,
-.@{ionicons-prefix}ios-email-outline:before,
-.@{ionicons-prefix}ios-eye:before,
-.@{ionicons-prefix}ios-eye-outline:before,
-.@{ionicons-prefix}ios-fastforward:before,
-.@{ionicons-prefix}ios-fastforward-outline:before,
-.@{ionicons-prefix}ios-filing:before,
-.@{ionicons-prefix}ios-filing-outline:before,
-.@{ionicons-prefix}ios-film:before,
-.@{ionicons-prefix}ios-film-outline:before,
-.@{ionicons-prefix}ios-flag:before,
-.@{ionicons-prefix}ios-flag-outline:before,
-.@{ionicons-prefix}ios-flame:before,
-.@{ionicons-prefix}ios-flame-outline:before,
-.@{ionicons-prefix}ios-flask:before,
-.@{ionicons-prefix}ios-flask-outline:before,
-.@{ionicons-prefix}ios-flower:before,
-.@{ionicons-prefix}ios-flower-outline:before,
-.@{ionicons-prefix}ios-folder:before,
-.@{ionicons-prefix}ios-folder-outline:before,
-.@{ionicons-prefix}ios-football:before,
-.@{ionicons-prefix}ios-football-outline:before,
-.@{ionicons-prefix}ios-game-controller-a:before,
-.@{ionicons-prefix}ios-game-controller-a-outline:before,
-.@{ionicons-prefix}ios-game-controller-b:before,
-.@{ionicons-prefix}ios-game-controller-b-outline:before,
-.@{ionicons-prefix}ios-gear:before,
-.@{ionicons-prefix}ios-gear-outline:before,
-.@{ionicons-prefix}ios-glasses:before,
-.@{ionicons-prefix}ios-glasses-outline:before,
-.@{ionicons-prefix}ios-grid-view:before,
-.@{ionicons-prefix}ios-grid-view-outline:before,
-.@{ionicons-prefix}ios-heart:before,
-.@{ionicons-prefix}ios-heart-outline:before,
-.@{ionicons-prefix}ios-help:before,
-.@{ionicons-prefix}ios-help-empty:before,
-.@{ionicons-prefix}ios-help-outline:before,
-.@{ionicons-prefix}ios-home:before,
-.@{ionicons-prefix}ios-home-outline:before,
-.@{ionicons-prefix}ios-infinite:before,
-.@{ionicons-prefix}ios-infinite-outline:before,
-.@{ionicons-prefix}ios-information:before,
-.@{ionicons-prefix}ios-information-empty:before,
-.@{ionicons-prefix}ios-information-outline:before,
-.@{ionicons-prefix}ios-ionic-outline:before,
-.@{ionicons-prefix}ios-keypad:before,
-.@{ionicons-prefix}ios-keypad-outline:before,
-.@{ionicons-prefix}ios-lightbulb:before,
-.@{ionicons-prefix}ios-lightbulb-outline:before,
-.@{ionicons-prefix}ios-list:before,
-.@{ionicons-prefix}ios-list-outline:before,
-.@{ionicons-prefix}ios-location:before,
-.@{ionicons-prefix}ios-location-outline:before,
-.@{ionicons-prefix}ios-locked:before,
-.@{ionicons-prefix}ios-locked-outline:before,
-.@{ionicons-prefix}ios-loop:before,
-.@{ionicons-prefix}ios-loop-strong:before,
-.@{ionicons-prefix}ios-medical:before,
-.@{ionicons-prefix}ios-medical-outline:before,
-.@{ionicons-prefix}ios-medkit:before,
-.@{ionicons-prefix}ios-medkit-outline:before,
-.@{ionicons-prefix}ios-mic:before,
-.@{ionicons-prefix}ios-mic-off:before,
-.@{ionicons-prefix}ios-mic-outline:before,
-.@{ionicons-prefix}ios-minus:before,
-.@{ionicons-prefix}ios-minus-empty:before,
-.@{ionicons-prefix}ios-minus-outline:before,
-.@{ionicons-prefix}ios-monitor:before,
-.@{ionicons-prefix}ios-monitor-outline:before,
-.@{ionicons-prefix}ios-moon:before,
-.@{ionicons-prefix}ios-moon-outline:before,
-.@{ionicons-prefix}ios-more:before,
-.@{ionicons-prefix}ios-more-outline:before,
-.@{ionicons-prefix}ios-musical-note:before,
-.@{ionicons-prefix}ios-musical-notes:before,
-.@{ionicons-prefix}ios-navigate:before,
-.@{ionicons-prefix}ios-navigate-outline:before,
-.@{ionicons-prefix}ios-nutrition:before,
-.@{ionicons-prefix}ios-nutrition-outline:before,
-.@{ionicons-prefix}ios-paper:before,
-.@{ionicons-prefix}ios-paper-outline:before,
-.@{ionicons-prefix}ios-paperplane:before,
-.@{ionicons-prefix}ios-paperplane-outline:before,
-.@{ionicons-prefix}ios-partlysunny:before,
-.@{ionicons-prefix}ios-partlysunny-outline:before,
-.@{ionicons-prefix}ios-pause:before,
-.@{ionicons-prefix}ios-pause-outline:before,
-.@{ionicons-prefix}ios-paw:before,
-.@{ionicons-prefix}ios-paw-outline:before,
-.@{ionicons-prefix}ios-people:before,
-.@{ionicons-prefix}ios-people-outline:before,
-.@{ionicons-prefix}ios-person:before,
-.@{ionicons-prefix}ios-person-outline:before,
-.@{ionicons-prefix}ios-personadd:before,
-.@{ionicons-prefix}ios-personadd-outline:before,
-.@{ionicons-prefix}ios-photos:before,
-.@{ionicons-prefix}ios-photos-outline:before,
-.@{ionicons-prefix}ios-pie:before,
-.@{ionicons-prefix}ios-pie-outline:before,
-.@{ionicons-prefix}ios-pint:before,
-.@{ionicons-prefix}ios-pint-outline:before,
-.@{ionicons-prefix}ios-play:before,
-.@{ionicons-prefix}ios-play-outline:before,
-.@{ionicons-prefix}ios-plus:before,
-.@{ionicons-prefix}ios-plus-empty:before,
-.@{ionicons-prefix}ios-plus-outline:before,
-.@{ionicons-prefix}ios-pricetag:before,
-.@{ionicons-prefix}ios-pricetag-outline:before,
-.@{ionicons-prefix}ios-pricetags:before,
-.@{ionicons-prefix}ios-pricetags-outline:before,
-.@{ionicons-prefix}ios-printer:before,
-.@{ionicons-prefix}ios-printer-outline:before,
-.@{ionicons-prefix}ios-pulse:before,
-.@{ionicons-prefix}ios-pulse-strong:before,
-.@{ionicons-prefix}ios-rainy:before,
-.@{ionicons-prefix}ios-rainy-outline:before,
-.@{ionicons-prefix}ios-recording:before,
-.@{ionicons-prefix}ios-recording-outline:before,
-.@{ionicons-prefix}ios-redo:before,
-.@{ionicons-prefix}ios-redo-outline:before,
-.@{ionicons-prefix}ios-refresh:before,
-.@{ionicons-prefix}ios-refresh-empty:before,
-.@{ionicons-prefix}ios-refresh-outline:before,
-.@{ionicons-prefix}ios-reload:before,
-.@{ionicons-prefix}ios-reverse-camera:before,
-.@{ionicons-prefix}ios-reverse-camera-outline:before,
-.@{ionicons-prefix}ios-rewind:before,
-.@{ionicons-prefix}ios-rewind-outline:before,
-.@{ionicons-prefix}ios-rose:before,
-.@{ionicons-prefix}ios-rose-outline:before,
-.@{ionicons-prefix}ios-search:before,
-.@{ionicons-prefix}ios-search-strong:before,
-.@{ionicons-prefix}ios-settings:before,
-.@{ionicons-prefix}ios-settings-strong:before,
-.@{ionicons-prefix}ios-shuffle:before,
-.@{ionicons-prefix}ios-shuffle-strong:before,
-.@{ionicons-prefix}ios-skipbackward:before,
-.@{ionicons-prefix}ios-skipbackward-outline:before,
-.@{ionicons-prefix}ios-skipforward:before,
-.@{ionicons-prefix}ios-skipforward-outline:before,
-.@{ionicons-prefix}ios-snowy:before,
-.@{ionicons-prefix}ios-speedometer:before,
-.@{ionicons-prefix}ios-speedometer-outline:before,
-.@{ionicons-prefix}ios-star:before,
-.@{ionicons-prefix}ios-star-half:before,
-.@{ionicons-prefix}ios-star-outline:before,
-.@{ionicons-prefix}ios-stopwatch:before,
-.@{ionicons-prefix}ios-stopwatch-outline:before,
-.@{ionicons-prefix}ios-sunny:before,
-.@{ionicons-prefix}ios-sunny-outline:before,
-.@{ionicons-prefix}ios-telephone:before,
-.@{ionicons-prefix}ios-telephone-outline:before,
-.@{ionicons-prefix}ios-tennisball:before,
-.@{ionicons-prefix}ios-tennisball-outline:before,
-.@{ionicons-prefix}ios-thunderstorm:before,
-.@{ionicons-prefix}ios-thunderstorm-outline:before,
-.@{ionicons-prefix}ios-time:before,
-.@{ionicons-prefix}ios-time-outline:before,
-.@{ionicons-prefix}ios-timer:before,
-.@{ionicons-prefix}ios-timer-outline:before,
-.@{ionicons-prefix}ios-toggle:before,
-.@{ionicons-prefix}ios-toggle-outline:before,
-.@{ionicons-prefix}ios-trash:before,
-.@{ionicons-prefix}ios-trash-outline:before,
-.@{ionicons-prefix}ios-undo:before,
-.@{ionicons-prefix}ios-undo-outline:before,
-.@{ionicons-prefix}ios-unlocked:before,
-.@{ionicons-prefix}ios-unlocked-outline:before,
-.@{ionicons-prefix}ios-upload:before,
-.@{ionicons-prefix}ios-upload-outline:before,
-.@{ionicons-prefix}ios-videocam:before,
-.@{ionicons-prefix}ios-videocam-outline:before,
-.@{ionicons-prefix}ios-volume-high:before,
-.@{ionicons-prefix}ios-volume-low:before,
-.@{ionicons-prefix}ios-wineglass:before,
-.@{ionicons-prefix}ios-wineglass-outline:before,
-.@{ionicons-prefix}ios-world:before,
-.@{ionicons-prefix}ios-world-outline:before,
-.@{ionicons-prefix}ipad:before,
-.@{ionicons-prefix}iphone:before,
-.@{ionicons-prefix}ipod:before,
-.@{ionicons-prefix}jet:before,
-.@{ionicons-prefix}key:before,
-.@{ionicons-prefix}knife:before,
-.@{ionicons-prefix}laptop:before,
-.@{ionicons-prefix}leaf:before,
-.@{ionicons-prefix}levels:before,
-.@{ionicons-prefix}lightbulb:before,
-.@{ionicons-prefix}link:before,
-.@{ionicons-prefix}load-a:before,
-.@{ionicons-prefix}load-b:before,
-.@{ionicons-prefix}load-c:before,
-.@{ionicons-prefix}load-d:before,
-.@{ionicons-prefix}location:before,
-.@{ionicons-prefix}lock-combination:before,
-.@{ionicons-prefix}locked:before,
-.@{ionicons-prefix}log-in:before,
-.@{ionicons-prefix}log-out:before,
-.@{ionicons-prefix}loop:before,
-.@{ionicons-prefix}magnet:before,
-.@{ionicons-prefix}male:before,
-.@{ionicons-prefix}man:before,
-.@{ionicons-prefix}map:before,
-.@{ionicons-prefix}medkit:before,
-.@{ionicons-prefix}merge:before,
-.@{ionicons-prefix}mic-a:before,
-.@{ionicons-prefix}mic-b:before,
-.@{ionicons-prefix}mic-c:before,
-.@{ionicons-prefix}minus:before,
-.@{ionicons-prefix}minus-circled:before,
-.@{ionicons-prefix}minus-round:before,
-.@{ionicons-prefix}model-s:before,
-.@{ionicons-prefix}monitor:before,
-.@{ionicons-prefix}more:before,
-.@{ionicons-prefix}mouse:before,
-.@{ionicons-prefix}music-note:before,
-.@{ionicons-prefix}navicon:before,
-.@{ionicons-prefix}navicon-round:before,
-.@{ionicons-prefix}navigate:before,
-.@{ionicons-prefix}network:before,
-.@{ionicons-prefix}no-smoking:before,
-.@{ionicons-prefix}nuclear:before,
-.@{ionicons-prefix}outlet:before,
-.@{ionicons-prefix}paintbrush:before,
-.@{ionicons-prefix}paintbucket:before,
-.@{ionicons-prefix}paper-airplane:before,
-.@{ionicons-prefix}paperclip:before,
-.@{ionicons-prefix}pause:before,
-.@{ionicons-prefix}person:before,
-.@{ionicons-prefix}person-add:before,
-.@{ionicons-prefix}person-stalker:before,
-.@{ionicons-prefix}pie-graph:before,
-.@{ionicons-prefix}pin:before,
-.@{ionicons-prefix}pinpoint:before,
-.@{ionicons-prefix}pizza:before,
-.@{ionicons-prefix}plane:before,
-.@{ionicons-prefix}planet:before,
-.@{ionicons-prefix}play:before,
-.@{ionicons-prefix}playstation:before,
-.@{ionicons-prefix}plus:before,
-.@{ionicons-prefix}plus-circled:before,
-.@{ionicons-prefix}plus-round:before,
-.@{ionicons-prefix}podium:before,
-.@{ionicons-prefix}pound:before,
-.@{ionicons-prefix}power:before,
-.@{ionicons-prefix}pricetag:before,
-.@{ionicons-prefix}pricetags:before,
-.@{ionicons-prefix}printer:before,
-.@{ionicons-prefix}pull-request:before,
-.@{ionicons-prefix}qr-scanner:before,
-.@{ionicons-prefix}quote:before,
-.@{ionicons-prefix}radio-waves:before,
-.@{ionicons-prefix}record:before,
-.@{ionicons-prefix}refresh:before,
-.@{ionicons-prefix}reply:before,
-.@{ionicons-prefix}reply-all:before,
-.@{ionicons-prefix}ribbon-a:before,
-.@{ionicons-prefix}ribbon-b:before,
-.@{ionicons-prefix}sad:before,
-.@{ionicons-prefix}sad-outline:before,
-.@{ionicons-prefix}scissors:before,
-.@{ionicons-prefix}search:before,
-.@{ionicons-prefix}settings:before,
-.@{ionicons-prefix}share:before,
-.@{ionicons-prefix}shuffle:before,
-.@{ionicons-prefix}skip-backward:before,
-.@{ionicons-prefix}skip-forward:before,
-.@{ionicons-prefix}social-android:before,
-.@{ionicons-prefix}social-android-outline:before,
-.@{ionicons-prefix}social-angular:before,
-.@{ionicons-prefix}social-angular-outline:before,
-.@{ionicons-prefix}social-apple:before,
-.@{ionicons-prefix}social-apple-outline:before,
-.@{ionicons-prefix}social-bitcoin:before,
-.@{ionicons-prefix}social-bitcoin-outline:before,
-.@{ionicons-prefix}social-buffer:before,
-.@{ionicons-prefix}social-buffer-outline:before,
-.@{ionicons-prefix}social-chrome:before,
-.@{ionicons-prefix}social-chrome-outline:before,
-.@{ionicons-prefix}social-codepen:before,
-.@{ionicons-prefix}social-codepen-outline:before,
-.@{ionicons-prefix}social-css3:before,
-.@{ionicons-prefix}social-css3-outline:before,
-.@{ionicons-prefix}social-designernews:before,
-.@{ionicons-prefix}social-designernews-outline:before,
-.@{ionicons-prefix}social-dribbble:before,
-.@{ionicons-prefix}social-dribbble-outline:before,
-.@{ionicons-prefix}social-dropbox:before,
-.@{ionicons-prefix}social-dropbox-outline:before,
-.@{ionicons-prefix}social-euro:before,
-.@{ionicons-prefix}social-euro-outline:before,
-.@{ionicons-prefix}social-facebook:before,
-.@{ionicons-prefix}social-facebook-outline:before,
-.@{ionicons-prefix}social-foursquare:before,
-.@{ionicons-prefix}social-foursquare-outline:before,
-.@{ionicons-prefix}social-freebsd-devil:before,
-.@{ionicons-prefix}social-github:before,
-.@{ionicons-prefix}social-github-outline:before,
-.@{ionicons-prefix}social-google:before,
-.@{ionicons-prefix}social-google-outline:before,
-.@{ionicons-prefix}social-googleplus:before,
-.@{ionicons-prefix}social-googleplus-outline:before,
-.@{ionicons-prefix}social-hackernews:before,
-.@{ionicons-prefix}social-hackernews-outline:before,
-.@{ionicons-prefix}social-html5:before,
-.@{ionicons-prefix}social-html5-outline:before,
-.@{ionicons-prefix}social-instagram:before,
-.@{ionicons-prefix}social-instagram-outline:before,
-.@{ionicons-prefix}social-javascript:before,
-.@{ionicons-prefix}social-javascript-outline:before,
-.@{ionicons-prefix}social-linkedin:before,
-.@{ionicons-prefix}social-linkedin-outline:before,
-.@{ionicons-prefix}social-markdown:before,
-.@{ionicons-prefix}social-nodejs:before,
-.@{ionicons-prefix}social-octocat:before,
-.@{ionicons-prefix}social-pinterest:before,
-.@{ionicons-prefix}social-pinterest-outline:before,
-.@{ionicons-prefix}social-python:before,
-.@{ionicons-prefix}social-reddit:before,
-.@{ionicons-prefix}social-reddit-outline:before,
-.@{ionicons-prefix}social-rss:before,
-.@{ionicons-prefix}social-rss-outline:before,
-.@{ionicons-prefix}social-sass:before,
-.@{ionicons-prefix}social-skype:before,
-.@{ionicons-prefix}social-skype-outline:before,
-.@{ionicons-prefix}social-snapchat:before,
-.@{ionicons-prefix}social-snapchat-outline:before,
-.@{ionicons-prefix}social-tumblr:before,
-.@{ionicons-prefix}social-tumblr-outline:before,
-.@{ionicons-prefix}social-tux:before,
-.@{ionicons-prefix}social-twitch:before,
-.@{ionicons-prefix}social-twitch-outline:before,
-.@{ionicons-prefix}social-twitter:before,
-.@{ionicons-prefix}social-twitter-outline:before,
-.@{ionicons-prefix}social-usd:before,
-.@{ionicons-prefix}social-usd-outline:before,
-.@{ionicons-prefix}social-vimeo:before,
-.@{ionicons-prefix}social-vimeo-outline:before,
-.@{ionicons-prefix}social-whatsapp:before,
-.@{ionicons-prefix}social-whatsapp-outline:before,
-.@{ionicons-prefix}social-windows:before,
-.@{ionicons-prefix}social-windows-outline:before,
-.@{ionicons-prefix}social-wordpress:before,
-.@{ionicons-prefix}social-wordpress-outline:before,
-.@{ionicons-prefix}social-yahoo:before,
-.@{ionicons-prefix}social-yahoo-outline:before,
-.@{ionicons-prefix}social-yen:before,
-.@{ionicons-prefix}social-yen-outline:before,
-.@{ionicons-prefix}social-youtube:before,
-.@{ionicons-prefix}social-youtube-outline:before,
-.@{ionicons-prefix}soup-can:before,
-.@{ionicons-prefix}soup-can-outline:before,
-.@{ionicons-prefix}speakerphone:before,
-.@{ionicons-prefix}speedometer:before,
-.@{ionicons-prefix}spoon:before,
-.@{ionicons-prefix}star:before,
-.@{ionicons-prefix}stats-bars:before,
-.@{ionicons-prefix}steam:before,
-.@{ionicons-prefix}stop:before,
-.@{ionicons-prefix}thermometer:before,
-.@{ionicons-prefix}thumbsdown:before,
-.@{ionicons-prefix}thumbsup:before,
-.@{ionicons-prefix}toggle:before,
-.@{ionicons-prefix}toggle-filled:before,
-.@{ionicons-prefix}transgender:before,
-.@{ionicons-prefix}trash-a:before,
-.@{ionicons-prefix}trash-b:before,
-.@{ionicons-prefix}trophy:before,
-.@{ionicons-prefix}tshirt:before,
-.@{ionicons-prefix}tshirt-outline:before,
-.@{ionicons-prefix}umbrella:before,
-.@{ionicons-prefix}university:before,
-.@{ionicons-prefix}unlocked:before,
-.@{ionicons-prefix}upload:before,
-.@{ionicons-prefix}usb:before,
-.@{ionicons-prefix}videocamera:before,
-.@{ionicons-prefix}volume-high:before,
-.@{ionicons-prefix}volume-low:before,
-.@{ionicons-prefix}volume-medium:before,
-.@{ionicons-prefix}volume-mute:before,
-.@{ionicons-prefix}wand:before,
-.@{ionicons-prefix}waterdrop:before,
-.@{ionicons-prefix}wifi:before,
-.@{ionicons-prefix}wineglass:before,
-.@{ionicons-prefix}woman:before,
-.@{ionicons-prefix}wrench:before,
-.@{ionicons-prefix}xbox:before
-{
- &:extend(.ion);
-}
-.@{ionicons-prefix}alert:before { content: @ionicon-var-alert; }
-.@{ionicons-prefix}alert-circled:before { content: @ionicon-var-alert-circled; }
-.@{ionicons-prefix}android-add:before { content: @ionicon-var-android-add; }
-.@{ionicons-prefix}android-add-circle:before { content: @ionicon-var-android-add-circle; }
-.@{ionicons-prefix}android-alarm-clock:before { content: @ionicon-var-android-alarm-clock; }
-.@{ionicons-prefix}android-alert:before { content: @ionicon-var-android-alert; }
-.@{ionicons-prefix}android-apps:before { content: @ionicon-var-android-apps; }
-.@{ionicons-prefix}android-archive:before { content: @ionicon-var-android-archive; }
-.@{ionicons-prefix}android-arrow-back:before { content: @ionicon-var-android-arrow-back; }
-.@{ionicons-prefix}android-arrow-down:before { content: @ionicon-var-android-arrow-down; }
-.@{ionicons-prefix}android-arrow-dropdown:before { content: @ionicon-var-android-arrow-dropdown; }
-.@{ionicons-prefix}android-arrow-dropdown-circle:before { content: @ionicon-var-android-arrow-dropdown-circle; }
-.@{ionicons-prefix}android-arrow-dropleft:before { content: @ionicon-var-android-arrow-dropleft; }
-.@{ionicons-prefix}android-arrow-dropleft-circle:before { content: @ionicon-var-android-arrow-dropleft-circle; }
-.@{ionicons-prefix}android-arrow-dropright:before { content: @ionicon-var-android-arrow-dropright; }
-.@{ionicons-prefix}android-arrow-dropright-circle:before { content: @ionicon-var-android-arrow-dropright-circle; }
-.@{ionicons-prefix}android-arrow-dropup:before { content: @ionicon-var-android-arrow-dropup; }
-.@{ionicons-prefix}android-arrow-dropup-circle:before { content: @ionicon-var-android-arrow-dropup-circle; }
-.@{ionicons-prefix}android-arrow-forward:before { content: @ionicon-var-android-arrow-forward; }
-.@{ionicons-prefix}android-arrow-up:before { content: @ionicon-var-android-arrow-up; }
-.@{ionicons-prefix}android-attach:before { content: @ionicon-var-android-attach; }
-.@{ionicons-prefix}android-bar:before { content: @ionicon-var-android-bar; }
-.@{ionicons-prefix}android-bicycle:before { content: @ionicon-var-android-bicycle; }
-.@{ionicons-prefix}android-boat:before { content: @ionicon-var-android-boat; }
-.@{ionicons-prefix}android-bookmark:before { content: @ionicon-var-android-bookmark; }
-.@{ionicons-prefix}android-bulb:before { content: @ionicon-var-android-bulb; }
-.@{ionicons-prefix}android-bus:before { content: @ionicon-var-android-bus; }
-.@{ionicons-prefix}android-calendar:before { content: @ionicon-var-android-calendar; }
-.@{ionicons-prefix}android-call:before { content: @ionicon-var-android-call; }
-.@{ionicons-prefix}android-camera:before { content: @ionicon-var-android-camera; }
-.@{ionicons-prefix}android-cancel:before { content: @ionicon-var-android-cancel; }
-.@{ionicons-prefix}android-car:before { content: @ionicon-var-android-car; }
-.@{ionicons-prefix}android-cart:before { content: @ionicon-var-android-cart; }
-.@{ionicons-prefix}android-chat:before { content: @ionicon-var-android-chat; }
-.@{ionicons-prefix}android-checkbox:before { content: @ionicon-var-android-checkbox; }
-.@{ionicons-prefix}android-checkbox-blank:before { content: @ionicon-var-android-checkbox-blank; }
-.@{ionicons-prefix}android-checkbox-outline:before { content: @ionicon-var-android-checkbox-outline; }
-.@{ionicons-prefix}android-checkbox-outline-blank:before { content: @ionicon-var-android-checkbox-outline-blank; }
-.@{ionicons-prefix}android-checkmark-circle:before { content: @ionicon-var-android-checkmark-circle; }
-.@{ionicons-prefix}android-clipboard:before { content: @ionicon-var-android-clipboard; }
-.@{ionicons-prefix}android-close:before { content: @ionicon-var-android-close; }
-.@{ionicons-prefix}android-cloud:before { content: @ionicon-var-android-cloud; }
-.@{ionicons-prefix}android-cloud-circle:before { content: @ionicon-var-android-cloud-circle; }
-.@{ionicons-prefix}android-cloud-done:before { content: @ionicon-var-android-cloud-done; }
-.@{ionicons-prefix}android-cloud-outline:before { content: @ionicon-var-android-cloud-outline; }
-.@{ionicons-prefix}android-color-palette:before { content: @ionicon-var-android-color-palette; }
-.@{ionicons-prefix}android-compass:before { content: @ionicon-var-android-compass; }
-.@{ionicons-prefix}android-contact:before { content: @ionicon-var-android-contact; }
-.@{ionicons-prefix}android-contacts:before { content: @ionicon-var-android-contacts; }
-.@{ionicons-prefix}android-contract:before { content: @ionicon-var-android-contract; }
-.@{ionicons-prefix}android-create:before { content: @ionicon-var-android-create; }
-.@{ionicons-prefix}android-delete:before { content: @ionicon-var-android-delete; }
-.@{ionicons-prefix}android-desktop:before { content: @ionicon-var-android-desktop; }
-.@{ionicons-prefix}android-document:before { content: @ionicon-var-android-document; }
-.@{ionicons-prefix}android-done:before { content: @ionicon-var-android-done; }
-.@{ionicons-prefix}android-done-all:before { content: @ionicon-var-android-done-all; }
-.@{ionicons-prefix}android-download:before { content: @ionicon-var-android-download; }
-.@{ionicons-prefix}android-drafts:before { content: @ionicon-var-android-drafts; }
-.@{ionicons-prefix}android-exit:before { content: @ionicon-var-android-exit; }
-.@{ionicons-prefix}android-expand:before { content: @ionicon-var-android-expand; }
-.@{ionicons-prefix}android-favorite:before { content: @ionicon-var-android-favorite; }
-.@{ionicons-prefix}android-favorite-outline:before { content: @ionicon-var-android-favorite-outline; }
-.@{ionicons-prefix}android-film:before { content: @ionicon-var-android-film; }
-.@{ionicons-prefix}android-folder:before { content: @ionicon-var-android-folder; }
-.@{ionicons-prefix}android-folder-open:before { content: @ionicon-var-android-folder-open; }
-.@{ionicons-prefix}android-funnel:before { content: @ionicon-var-android-funnel; }
-.@{ionicons-prefix}android-globe:before { content: @ionicon-var-android-globe; }
-.@{ionicons-prefix}android-hand:before { content: @ionicon-var-android-hand; }
-.@{ionicons-prefix}android-hangout:before { content: @ionicon-var-android-hangout; }
-.@{ionicons-prefix}android-happy:before { content: @ionicon-var-android-happy; }
-.@{ionicons-prefix}android-home:before { content: @ionicon-var-android-home; }
-.@{ionicons-prefix}android-image:before { content: @ionicon-var-android-image; }
-.@{ionicons-prefix}android-laptop:before { content: @ionicon-var-android-laptop; }
-.@{ionicons-prefix}android-list:before { content: @ionicon-var-android-list; }
-.@{ionicons-prefix}android-locate:before { content: @ionicon-var-android-locate; }
-.@{ionicons-prefix}android-lock:before { content: @ionicon-var-android-lock; }
-.@{ionicons-prefix}android-mail:before { content: @ionicon-var-android-mail; }
-.@{ionicons-prefix}android-map:before { content: @ionicon-var-android-map; }
-.@{ionicons-prefix}android-menu:before { content: @ionicon-var-android-menu; }
-.@{ionicons-prefix}android-microphone:before { content: @ionicon-var-android-microphone; }
-.@{ionicons-prefix}android-microphone-off:before { content: @ionicon-var-android-microphone-off; }
-.@{ionicons-prefix}android-more-horizontal:before { content: @ionicon-var-android-more-horizontal; }
-.@{ionicons-prefix}android-more-vertical:before { content: @ionicon-var-android-more-vertical; }
-.@{ionicons-prefix}android-navigate:before { content: @ionicon-var-android-navigate; }
-.@{ionicons-prefix}android-notifications:before { content: @ionicon-var-android-notifications; }
-.@{ionicons-prefix}android-notifications-none:before { content: @ionicon-var-android-notifications-none; }
-.@{ionicons-prefix}android-notifications-off:before { content: @ionicon-var-android-notifications-off; }
-.@{ionicons-prefix}android-open:before { content: @ionicon-var-android-open; }
-.@{ionicons-prefix}android-options:before { content: @ionicon-var-android-options; }
-.@{ionicons-prefix}android-people:before { content: @ionicon-var-android-people; }
-.@{ionicons-prefix}android-person:before { content: @ionicon-var-android-person; }
-.@{ionicons-prefix}android-person-add:before { content: @ionicon-var-android-person-add; }
-.@{ionicons-prefix}android-phone-landscape:before { content: @ionicon-var-android-phone-landscape; }
-.@{ionicons-prefix}android-phone-portrait:before { content: @ionicon-var-android-phone-portrait; }
-.@{ionicons-prefix}android-pin:before { content: @ionicon-var-android-pin; }
-.@{ionicons-prefix}android-plane:before { content: @ionicon-var-android-plane; }
-.@{ionicons-prefix}android-playstore:before { content: @ionicon-var-android-playstore; }
-.@{ionicons-prefix}android-print:before { content: @ionicon-var-android-print; }
-.@{ionicons-prefix}android-radio-button-off:before { content: @ionicon-var-android-radio-button-off; }
-.@{ionicons-prefix}android-radio-button-on:before { content: @ionicon-var-android-radio-button-on; }
-.@{ionicons-prefix}android-refresh:before { content: @ionicon-var-android-refresh; }
-.@{ionicons-prefix}android-remove:before { content: @ionicon-var-android-remove; }
-.@{ionicons-prefix}android-remove-circle:before { content: @ionicon-var-android-remove-circle; }
-.@{ionicons-prefix}android-restaurant:before { content: @ionicon-var-android-restaurant; }
-.@{ionicons-prefix}android-sad:before { content: @ionicon-var-android-sad; }
-.@{ionicons-prefix}android-search:before { content: @ionicon-var-android-search; }
-.@{ionicons-prefix}android-send:before { content: @ionicon-var-android-send; }
-.@{ionicons-prefix}android-settings:before { content: @ionicon-var-android-settings; }
-.@{ionicons-prefix}android-share:before { content: @ionicon-var-android-share; }
-.@{ionicons-prefix}android-share-alt:before { content: @ionicon-var-android-share-alt; }
-.@{ionicons-prefix}android-star:before { content: @ionicon-var-android-star; }
-.@{ionicons-prefix}android-star-half:before { content: @ionicon-var-android-star-half; }
-.@{ionicons-prefix}android-star-outline:before { content: @ionicon-var-android-star-outline; }
-.@{ionicons-prefix}android-stopwatch:before { content: @ionicon-var-android-stopwatch; }
-.@{ionicons-prefix}android-subway:before { content: @ionicon-var-android-subway; }
-.@{ionicons-prefix}android-sunny:before { content: @ionicon-var-android-sunny; }
-.@{ionicons-prefix}android-sync:before { content: @ionicon-var-android-sync; }
-.@{ionicons-prefix}android-textsms:before { content: @ionicon-var-android-textsms; }
-.@{ionicons-prefix}android-time:before { content: @ionicon-var-android-time; }
-.@{ionicons-prefix}android-train:before { content: @ionicon-var-android-train; }
-.@{ionicons-prefix}android-unlock:before { content: @ionicon-var-android-unlock; }
-.@{ionicons-prefix}android-upload:before { content: @ionicon-var-android-upload; }
-.@{ionicons-prefix}android-volume-down:before { content: @ionicon-var-android-volume-down; }
-.@{ionicons-prefix}android-volume-mute:before { content: @ionicon-var-android-volume-mute; }
-.@{ionicons-prefix}android-volume-off:before { content: @ionicon-var-android-volume-off; }
-.@{ionicons-prefix}android-volume-up:before { content: @ionicon-var-android-volume-up; }
-.@{ionicons-prefix}android-walk:before { content: @ionicon-var-android-walk; }
-.@{ionicons-prefix}android-warning:before { content: @ionicon-var-android-warning; }
-.@{ionicons-prefix}android-watch:before { content: @ionicon-var-android-watch; }
-.@{ionicons-prefix}android-wifi:before { content: @ionicon-var-android-wifi; }
-.@{ionicons-prefix}aperture:before { content: @ionicon-var-aperture; }
-.@{ionicons-prefix}archive:before { content: @ionicon-var-archive; }
-.@{ionicons-prefix}arrow-down-a:before { content: @ionicon-var-arrow-down-a; }
-.@{ionicons-prefix}arrow-down-b:before { content: @ionicon-var-arrow-down-b; }
-.@{ionicons-prefix}arrow-down-c:before { content: @ionicon-var-arrow-down-c; }
-.@{ionicons-prefix}arrow-expand:before { content: @ionicon-var-arrow-expand; }
-.@{ionicons-prefix}arrow-graph-down-left:before { content: @ionicon-var-arrow-graph-down-left; }
-.@{ionicons-prefix}arrow-graph-down-right:before { content: @ionicon-var-arrow-graph-down-right; }
-.@{ionicons-prefix}arrow-graph-up-left:before { content: @ionicon-var-arrow-graph-up-left; }
-.@{ionicons-prefix}arrow-graph-up-right:before { content: @ionicon-var-arrow-graph-up-right; }
-.@{ionicons-prefix}arrow-left-a:before { content: @ionicon-var-arrow-left-a; }
-.@{ionicons-prefix}arrow-left-b:before { content: @ionicon-var-arrow-left-b; }
-.@{ionicons-prefix}arrow-left-c:before { content: @ionicon-var-arrow-left-c; }
-.@{ionicons-prefix}arrow-move:before { content: @ionicon-var-arrow-move; }
-.@{ionicons-prefix}arrow-resize:before { content: @ionicon-var-arrow-resize; }
-.@{ionicons-prefix}arrow-return-left:before { content: @ionicon-var-arrow-return-left; }
-.@{ionicons-prefix}arrow-return-right:before { content: @ionicon-var-arrow-return-right; }
-.@{ionicons-prefix}arrow-right-a:before { content: @ionicon-var-arrow-right-a; }
-.@{ionicons-prefix}arrow-right-b:before { content: @ionicon-var-arrow-right-b; }
-.@{ionicons-prefix}arrow-right-c:before { content: @ionicon-var-arrow-right-c; }
-.@{ionicons-prefix}arrow-shrink:before { content: @ionicon-var-arrow-shrink; }
-.@{ionicons-prefix}arrow-swap:before { content: @ionicon-var-arrow-swap; }
-.@{ionicons-prefix}arrow-up-a:before { content: @ionicon-var-arrow-up-a; }
-.@{ionicons-prefix}arrow-up-b:before { content: @ionicon-var-arrow-up-b; }
-.@{ionicons-prefix}arrow-up-c:before { content: @ionicon-var-arrow-up-c; }
-.@{ionicons-prefix}asterisk:before { content: @ionicon-var-asterisk; }
-.@{ionicons-prefix}at:before { content: @ionicon-var-at; }
-.@{ionicons-prefix}backspace:before { content: @ionicon-var-backspace; }
-.@{ionicons-prefix}backspace-outline:before { content: @ionicon-var-backspace-outline; }
-.@{ionicons-prefix}bag:before { content: @ionicon-var-bag; }
-.@{ionicons-prefix}battery-charging:before { content: @ionicon-var-battery-charging; }
-.@{ionicons-prefix}battery-empty:before { content: @ionicon-var-battery-empty; }
-.@{ionicons-prefix}battery-full:before { content: @ionicon-var-battery-full; }
-.@{ionicons-prefix}battery-half:before { content: @ionicon-var-battery-half; }
-.@{ionicons-prefix}battery-low:before { content: @ionicon-var-battery-low; }
-.@{ionicons-prefix}beaker:before { content: @ionicon-var-beaker; }
-.@{ionicons-prefix}beer:before { content: @ionicon-var-beer; }
-.@{ionicons-prefix}bluetooth:before { content: @ionicon-var-bluetooth; }
-.@{ionicons-prefix}bonfire:before { content: @ionicon-var-bonfire; }
-.@{ionicons-prefix}bookmark:before { content: @ionicon-var-bookmark; }
-.@{ionicons-prefix}bowtie:before { content: @ionicon-var-bowtie; }
-.@{ionicons-prefix}briefcase:before { content: @ionicon-var-briefcase; }
-.@{ionicons-prefix}bug:before { content: @ionicon-var-bug; }
-.@{ionicons-prefix}calculator:before { content: @ionicon-var-calculator; }
-.@{ionicons-prefix}calendar:before { content: @ionicon-var-calendar; }
-.@{ionicons-prefix}camera:before { content: @ionicon-var-camera; }
-.@{ionicons-prefix}card:before { content: @ionicon-var-card; }
-.@{ionicons-prefix}cash:before { content: @ionicon-var-cash; }
-.@{ionicons-prefix}chatbox:before { content: @ionicon-var-chatbox; }
-.@{ionicons-prefix}chatbox-working:before { content: @ionicon-var-chatbox-working; }
-.@{ionicons-prefix}chatboxes:before { content: @ionicon-var-chatboxes; }
-.@{ionicons-prefix}chatbubble:before { content: @ionicon-var-chatbubble; }
-.@{ionicons-prefix}chatbubble-working:before { content: @ionicon-var-chatbubble-working; }
-.@{ionicons-prefix}chatbubbles:before { content: @ionicon-var-chatbubbles; }
-.@{ionicons-prefix}checkmark:before { content: @ionicon-var-checkmark; }
-.@{ionicons-prefix}checkmark-circled:before { content: @ionicon-var-checkmark-circled; }
-.@{ionicons-prefix}checkmark-round:before { content: @ionicon-var-checkmark-round; }
-.@{ionicons-prefix}chevron-down:before { content: @ionicon-var-chevron-down; }
-.@{ionicons-prefix}chevron-left:before { content: @ionicon-var-chevron-left; }
-.@{ionicons-prefix}chevron-right:before { content: @ionicon-var-chevron-right; }
-.@{ionicons-prefix}chevron-up:before { content: @ionicon-var-chevron-up; }
-.@{ionicons-prefix}clipboard:before { content: @ionicon-var-clipboard; }
-.@{ionicons-prefix}clock:before { content: @ionicon-var-clock; }
-.@{ionicons-prefix}close:before { content: @ionicon-var-close; }
-.@{ionicons-prefix}close-circled:before { content: @ionicon-var-close-circled; }
-.@{ionicons-prefix}close-round:before { content: @ionicon-var-close-round; }
-.@{ionicons-prefix}closed-captioning:before { content: @ionicon-var-closed-captioning; }
-.@{ionicons-prefix}cloud:before { content: @ionicon-var-cloud; }
-.@{ionicons-prefix}code:before { content: @ionicon-var-code; }
-.@{ionicons-prefix}code-download:before { content: @ionicon-var-code-download; }
-.@{ionicons-prefix}code-working:before { content: @ionicon-var-code-working; }
-.@{ionicons-prefix}coffee:before { content: @ionicon-var-coffee; }
-.@{ionicons-prefix}compass:before { content: @ionicon-var-compass; }
-.@{ionicons-prefix}compose:before { content: @ionicon-var-compose; }
-.@{ionicons-prefix}connection-bars:before { content: @ionicon-var-connection-bars; }
-.@{ionicons-prefix}contrast:before { content: @ionicon-var-contrast; }
-.@{ionicons-prefix}crop:before { content: @ionicon-var-crop; }
-.@{ionicons-prefix}cube:before { content: @ionicon-var-cube; }
-.@{ionicons-prefix}disc:before { content: @ionicon-var-disc; }
-.@{ionicons-prefix}document:before { content: @ionicon-var-document; }
-.@{ionicons-prefix}document-text:before { content: @ionicon-var-document-text; }
-.@{ionicons-prefix}drag:before { content: @ionicon-var-drag; }
-.@{ionicons-prefix}earth:before { content: @ionicon-var-earth; }
-.@{ionicons-prefix}easel:before { content: @ionicon-var-easel; }
-.@{ionicons-prefix}edit:before { content: @ionicon-var-edit; }
-.@{ionicons-prefix}egg:before { content: @ionicon-var-egg; }
-.@{ionicons-prefix}eject:before { content: @ionicon-var-eject; }
-.@{ionicons-prefix}email:before { content: @ionicon-var-email; }
-.@{ionicons-prefix}email-unread:before { content: @ionicon-var-email-unread; }
-.@{ionicons-prefix}erlenmeyer-flask:before { content: @ionicon-var-erlenmeyer-flask; }
-.@{ionicons-prefix}erlenmeyer-flask-bubbles:before { content: @ionicon-var-erlenmeyer-flask-bubbles; }
-.@{ionicons-prefix}eye:before { content: @ionicon-var-eye; }
-.@{ionicons-prefix}eye-disabled:before { content: @ionicon-var-eye-disabled; }
-.@{ionicons-prefix}female:before { content: @ionicon-var-female; }
-.@{ionicons-prefix}filing:before { content: @ionicon-var-filing; }
-.@{ionicons-prefix}film-marker:before { content: @ionicon-var-film-marker; }
-.@{ionicons-prefix}fireball:before { content: @ionicon-var-fireball; }
-.@{ionicons-prefix}flag:before { content: @ionicon-var-flag; }
-.@{ionicons-prefix}flame:before { content: @ionicon-var-flame; }
-.@{ionicons-prefix}flash:before { content: @ionicon-var-flash; }
-.@{ionicons-prefix}flash-off:before { content: @ionicon-var-flash-off; }
-.@{ionicons-prefix}folder:before { content: @ionicon-var-folder; }
-.@{ionicons-prefix}fork:before { content: @ionicon-var-fork; }
-.@{ionicons-prefix}fork-repo:before { content: @ionicon-var-fork-repo; }
-.@{ionicons-prefix}forward:before { content: @ionicon-var-forward; }
-.@{ionicons-prefix}funnel:before { content: @ionicon-var-funnel; }
-.@{ionicons-prefix}gear-a:before { content: @ionicon-var-gear-a; }
-.@{ionicons-prefix}gear-b:before { content: @ionicon-var-gear-b; }
-.@{ionicons-prefix}grid:before { content: @ionicon-var-grid; }
-.@{ionicons-prefix}hammer:before { content: @ionicon-var-hammer; }
-.@{ionicons-prefix}happy:before { content: @ionicon-var-happy; }
-.@{ionicons-prefix}happy-outline:before { content: @ionicon-var-happy-outline; }
-.@{ionicons-prefix}headphone:before { content: @ionicon-var-headphone; }
-.@{ionicons-prefix}heart:before { content: @ionicon-var-heart; }
-.@{ionicons-prefix}heart-broken:before { content: @ionicon-var-heart-broken; }
-.@{ionicons-prefix}help:before { content: @ionicon-var-help; }
-.@{ionicons-prefix}help-buoy:before { content: @ionicon-var-help-buoy; }
-.@{ionicons-prefix}help-circled:before { content: @ionicon-var-help-circled; }
-.@{ionicons-prefix}home:before { content: @ionicon-var-home; }
-.@{ionicons-prefix}icecream:before { content: @ionicon-var-icecream; }
-.@{ionicons-prefix}image:before { content: @ionicon-var-image; }
-.@{ionicons-prefix}images:before { content: @ionicon-var-images; }
-.@{ionicons-prefix}information:before { content: @ionicon-var-information; }
-.@{ionicons-prefix}information-circled:before { content: @ionicon-var-information-circled; }
-.@{ionicons-prefix}ionic:before { content: @ionicon-var-ionic; }
-.@{ionicons-prefix}ios-alarm:before { content: @ionicon-var-ios-alarm; }
-.@{ionicons-prefix}ios-alarm-outline:before { content: @ionicon-var-ios-alarm-outline; }
-.@{ionicons-prefix}ios-albums:before { content: @ionicon-var-ios-albums; }
-.@{ionicons-prefix}ios-albums-outline:before { content: @ionicon-var-ios-albums-outline; }
-.@{ionicons-prefix}ios-americanfootball:before { content: @ionicon-var-ios-americanfootball; }
-.@{ionicons-prefix}ios-americanfootball-outline:before { content: @ionicon-var-ios-americanfootball-outline; }
-.@{ionicons-prefix}ios-analytics:before { content: @ionicon-var-ios-analytics; }
-.@{ionicons-prefix}ios-analytics-outline:before { content: @ionicon-var-ios-analytics-outline; }
-.@{ionicons-prefix}ios-arrow-back:before { content: @ionicon-var-ios-arrow-back; }
-.@{ionicons-prefix}ios-arrow-down:before { content: @ionicon-var-ios-arrow-down; }
-.@{ionicons-prefix}ios-arrow-forward:before { content: @ionicon-var-ios-arrow-forward; }
-.@{ionicons-prefix}ios-arrow-left:before { content: @ionicon-var-ios-arrow-left; }
-.@{ionicons-prefix}ios-arrow-right:before { content: @ionicon-var-ios-arrow-right; }
-.@{ionicons-prefix}ios-arrow-thin-down:before { content: @ionicon-var-ios-arrow-thin-down; }
-.@{ionicons-prefix}ios-arrow-thin-left:before { content: @ionicon-var-ios-arrow-thin-left; }
-.@{ionicons-prefix}ios-arrow-thin-right:before { content: @ionicon-var-ios-arrow-thin-right; }
-.@{ionicons-prefix}ios-arrow-thin-up:before { content: @ionicon-var-ios-arrow-thin-up; }
-.@{ionicons-prefix}ios-arrow-up:before { content: @ionicon-var-ios-arrow-up; }
-.@{ionicons-prefix}ios-at:before { content: @ionicon-var-ios-at; }
-.@{ionicons-prefix}ios-at-outline:before { content: @ionicon-var-ios-at-outline; }
-.@{ionicons-prefix}ios-barcode:before { content: @ionicon-var-ios-barcode; }
-.@{ionicons-prefix}ios-barcode-outline:before { content: @ionicon-var-ios-barcode-outline; }
-.@{ionicons-prefix}ios-baseball:before { content: @ionicon-var-ios-baseball; }
-.@{ionicons-prefix}ios-baseball-outline:before { content: @ionicon-var-ios-baseball-outline; }
-.@{ionicons-prefix}ios-basketball:before { content: @ionicon-var-ios-basketball; }
-.@{ionicons-prefix}ios-basketball-outline:before { content: @ionicon-var-ios-basketball-outline; }
-.@{ionicons-prefix}ios-bell:before { content: @ionicon-var-ios-bell; }
-.@{ionicons-prefix}ios-bell-outline:before { content: @ionicon-var-ios-bell-outline; }
-.@{ionicons-prefix}ios-body:before { content: @ionicon-var-ios-body; }
-.@{ionicons-prefix}ios-body-outline:before { content: @ionicon-var-ios-body-outline; }
-.@{ionicons-prefix}ios-bolt:before { content: @ionicon-var-ios-bolt; }
-.@{ionicons-prefix}ios-bolt-outline:before { content: @ionicon-var-ios-bolt-outline; }
-.@{ionicons-prefix}ios-book:before { content: @ionicon-var-ios-book; }
-.@{ionicons-prefix}ios-book-outline:before { content: @ionicon-var-ios-book-outline; }
-.@{ionicons-prefix}ios-bookmarks:before { content: @ionicon-var-ios-bookmarks; }
-.@{ionicons-prefix}ios-bookmarks-outline:before { content: @ionicon-var-ios-bookmarks-outline; }
-.@{ionicons-prefix}ios-box:before { content: @ionicon-var-ios-box; }
-.@{ionicons-prefix}ios-box-outline:before { content: @ionicon-var-ios-box-outline; }
-.@{ionicons-prefix}ios-briefcase:before { content: @ionicon-var-ios-briefcase; }
-.@{ionicons-prefix}ios-briefcase-outline:before { content: @ionicon-var-ios-briefcase-outline; }
-.@{ionicons-prefix}ios-browsers:before { content: @ionicon-var-ios-browsers; }
-.@{ionicons-prefix}ios-browsers-outline:before { content: @ionicon-var-ios-browsers-outline; }
-.@{ionicons-prefix}ios-calculator:before { content: @ionicon-var-ios-calculator; }
-.@{ionicons-prefix}ios-calculator-outline:before { content: @ionicon-var-ios-calculator-outline; }
-.@{ionicons-prefix}ios-calendar:before { content: @ionicon-var-ios-calendar; }
-.@{ionicons-prefix}ios-calendar-outline:before { content: @ionicon-var-ios-calendar-outline; }
-.@{ionicons-prefix}ios-camera:before { content: @ionicon-var-ios-camera; }
-.@{ionicons-prefix}ios-camera-outline:before { content: @ionicon-var-ios-camera-outline; }
-.@{ionicons-prefix}ios-cart:before { content: @ionicon-var-ios-cart; }
-.@{ionicons-prefix}ios-cart-outline:before { content: @ionicon-var-ios-cart-outline; }
-.@{ionicons-prefix}ios-chatboxes:before { content: @ionicon-var-ios-chatboxes; }
-.@{ionicons-prefix}ios-chatboxes-outline:before { content: @ionicon-var-ios-chatboxes-outline; }
-.@{ionicons-prefix}ios-chatbubble:before { content: @ionicon-var-ios-chatbubble; }
-.@{ionicons-prefix}ios-chatbubble-outline:before { content: @ionicon-var-ios-chatbubble-outline; }
-.@{ionicons-prefix}ios-checkmark:before { content: @ionicon-var-ios-checkmark; }
-.@{ionicons-prefix}ios-checkmark-empty:before { content: @ionicon-var-ios-checkmark-empty; }
-.@{ionicons-prefix}ios-checkmark-outline:before { content: @ionicon-var-ios-checkmark-outline; }
-.@{ionicons-prefix}ios-circle-filled:before { content: @ionicon-var-ios-circle-filled; }
-.@{ionicons-prefix}ios-circle-outline:before { content: @ionicon-var-ios-circle-outline; }
-.@{ionicons-prefix}ios-clock:before { content: @ionicon-var-ios-clock; }
-.@{ionicons-prefix}ios-clock-outline:before { content: @ionicon-var-ios-clock-outline; }
-.@{ionicons-prefix}ios-close:before { content: @ionicon-var-ios-close; }
-.@{ionicons-prefix}ios-close-empty:before { content: @ionicon-var-ios-close-empty; }
-.@{ionicons-prefix}ios-close-outline:before { content: @ionicon-var-ios-close-outline; }
-.@{ionicons-prefix}ios-cloud:before { content: @ionicon-var-ios-cloud; }
-.@{ionicons-prefix}ios-cloud-download:before { content: @ionicon-var-ios-cloud-download; }
-.@{ionicons-prefix}ios-cloud-download-outline:before { content: @ionicon-var-ios-cloud-download-outline; }
-.@{ionicons-prefix}ios-cloud-outline:before { content: @ionicon-var-ios-cloud-outline; }
-.@{ionicons-prefix}ios-cloud-upload:before { content: @ionicon-var-ios-cloud-upload; }
-.@{ionicons-prefix}ios-cloud-upload-outline:before { content: @ionicon-var-ios-cloud-upload-outline; }
-.@{ionicons-prefix}ios-cloudy:before { content: @ionicon-var-ios-cloudy; }
-.@{ionicons-prefix}ios-cloudy-night:before { content: @ionicon-var-ios-cloudy-night; }
-.@{ionicons-prefix}ios-cloudy-night-outline:before { content: @ionicon-var-ios-cloudy-night-outline; }
-.@{ionicons-prefix}ios-cloudy-outline:before { content: @ionicon-var-ios-cloudy-outline; }
-.@{ionicons-prefix}ios-cog:before { content: @ionicon-var-ios-cog; }
-.@{ionicons-prefix}ios-cog-outline:before { content: @ionicon-var-ios-cog-outline; }
-.@{ionicons-prefix}ios-color-filter:before { content: @ionicon-var-ios-color-filter; }
-.@{ionicons-prefix}ios-color-filter-outline:before { content: @ionicon-var-ios-color-filter-outline; }
-.@{ionicons-prefix}ios-color-wand:before { content: @ionicon-var-ios-color-wand; }
-.@{ionicons-prefix}ios-color-wand-outline:before { content: @ionicon-var-ios-color-wand-outline; }
-.@{ionicons-prefix}ios-compose:before { content: @ionicon-var-ios-compose; }
-.@{ionicons-prefix}ios-compose-outline:before { content: @ionicon-var-ios-compose-outline; }
-.@{ionicons-prefix}ios-contact:before { content: @ionicon-var-ios-contact; }
-.@{ionicons-prefix}ios-contact-outline:before { content: @ionicon-var-ios-contact-outline; }
-.@{ionicons-prefix}ios-copy:before { content: @ionicon-var-ios-copy; }
-.@{ionicons-prefix}ios-copy-outline:before { content: @ionicon-var-ios-copy-outline; }
-.@{ionicons-prefix}ios-crop:before { content: @ionicon-var-ios-crop; }
-.@{ionicons-prefix}ios-crop-strong:before { content: @ionicon-var-ios-crop-strong; }
-.@{ionicons-prefix}ios-download:before { content: @ionicon-var-ios-download; }
-.@{ionicons-prefix}ios-download-outline:before { content: @ionicon-var-ios-download-outline; }
-.@{ionicons-prefix}ios-drag:before { content: @ionicon-var-ios-drag; }
-.@{ionicons-prefix}ios-email:before { content: @ionicon-var-ios-email; }
-.@{ionicons-prefix}ios-email-outline:before { content: @ionicon-var-ios-email-outline; }
-.@{ionicons-prefix}ios-eye:before { content: @ionicon-var-ios-eye; }
-.@{ionicons-prefix}ios-eye-outline:before { content: @ionicon-var-ios-eye-outline; }
-.@{ionicons-prefix}ios-fastforward:before { content: @ionicon-var-ios-fastforward; }
-.@{ionicons-prefix}ios-fastforward-outline:before { content: @ionicon-var-ios-fastforward-outline; }
-.@{ionicons-prefix}ios-filing:before { content: @ionicon-var-ios-filing; }
-.@{ionicons-prefix}ios-filing-outline:before { content: @ionicon-var-ios-filing-outline; }
-.@{ionicons-prefix}ios-film:before { content: @ionicon-var-ios-film; }
-.@{ionicons-prefix}ios-film-outline:before { content: @ionicon-var-ios-film-outline; }
-.@{ionicons-prefix}ios-flag:before { content: @ionicon-var-ios-flag; }
-.@{ionicons-prefix}ios-flag-outline:before { content: @ionicon-var-ios-flag-outline; }
-.@{ionicons-prefix}ios-flame:before { content: @ionicon-var-ios-flame; }
-.@{ionicons-prefix}ios-flame-outline:before { content: @ionicon-var-ios-flame-outline; }
-.@{ionicons-prefix}ios-flask:before { content: @ionicon-var-ios-flask; }
-.@{ionicons-prefix}ios-flask-outline:before { content: @ionicon-var-ios-flask-outline; }
-.@{ionicons-prefix}ios-flower:before { content: @ionicon-var-ios-flower; }
-.@{ionicons-prefix}ios-flower-outline:before { content: @ionicon-var-ios-flower-outline; }
-.@{ionicons-prefix}ios-folder:before { content: @ionicon-var-ios-folder; }
-.@{ionicons-prefix}ios-folder-outline:before { content: @ionicon-var-ios-folder-outline; }
-.@{ionicons-prefix}ios-football:before { content: @ionicon-var-ios-football; }
-.@{ionicons-prefix}ios-football-outline:before { content: @ionicon-var-ios-football-outline; }
-.@{ionicons-prefix}ios-game-controller-a:before { content: @ionicon-var-ios-game-controller-a; }
-.@{ionicons-prefix}ios-game-controller-a-outline:before { content: @ionicon-var-ios-game-controller-a-outline; }
-.@{ionicons-prefix}ios-game-controller-b:before { content: @ionicon-var-ios-game-controller-b; }
-.@{ionicons-prefix}ios-game-controller-b-outline:before { content: @ionicon-var-ios-game-controller-b-outline; }
-.@{ionicons-prefix}ios-gear:before { content: @ionicon-var-ios-gear; }
-.@{ionicons-prefix}ios-gear-outline:before { content: @ionicon-var-ios-gear-outline; }
-.@{ionicons-prefix}ios-glasses:before { content: @ionicon-var-ios-glasses; }
-.@{ionicons-prefix}ios-glasses-outline:before { content: @ionicon-var-ios-glasses-outline; }
-.@{ionicons-prefix}ios-grid-view:before { content: @ionicon-var-ios-grid-view; }
-.@{ionicons-prefix}ios-grid-view-outline:before { content: @ionicon-var-ios-grid-view-outline; }
-.@{ionicons-prefix}ios-heart:before { content: @ionicon-var-ios-heart; }
-.@{ionicons-prefix}ios-heart-outline:before { content: @ionicon-var-ios-heart-outline; }
-.@{ionicons-prefix}ios-help:before { content: @ionicon-var-ios-help; }
-.@{ionicons-prefix}ios-help-empty:before { content: @ionicon-var-ios-help-empty; }
-.@{ionicons-prefix}ios-help-outline:before { content: @ionicon-var-ios-help-outline; }
-.@{ionicons-prefix}ios-home:before { content: @ionicon-var-ios-home; }
-.@{ionicons-prefix}ios-home-outline:before { content: @ionicon-var-ios-home-outline; }
-.@{ionicons-prefix}ios-infinite:before { content: @ionicon-var-ios-infinite; }
-.@{ionicons-prefix}ios-infinite-outline:before { content: @ionicon-var-ios-infinite-outline; }
-.@{ionicons-prefix}ios-information:before { content: @ionicon-var-ios-information; }
-.@{ionicons-prefix}ios-information-empty:before { content: @ionicon-var-ios-information-empty; }
-.@{ionicons-prefix}ios-information-outline:before { content: @ionicon-var-ios-information-outline; }
-.@{ionicons-prefix}ios-ionic-outline:before { content: @ionicon-var-ios-ionic-outline; }
-.@{ionicons-prefix}ios-keypad:before { content: @ionicon-var-ios-keypad; }
-.@{ionicons-prefix}ios-keypad-outline:before { content: @ionicon-var-ios-keypad-outline; }
-.@{ionicons-prefix}ios-lightbulb:before { content: @ionicon-var-ios-lightbulb; }
-.@{ionicons-prefix}ios-lightbulb-outline:before { content: @ionicon-var-ios-lightbulb-outline; }
-.@{ionicons-prefix}ios-list:before { content: @ionicon-var-ios-list; }
-.@{ionicons-prefix}ios-list-outline:before { content: @ionicon-var-ios-list-outline; }
-.@{ionicons-prefix}ios-location:before { content: @ionicon-var-ios-location; }
-.@{ionicons-prefix}ios-location-outline:before { content: @ionicon-var-ios-location-outline; }
-.@{ionicons-prefix}ios-locked:before { content: @ionicon-var-ios-locked; }
-.@{ionicons-prefix}ios-locked-outline:before { content: @ionicon-var-ios-locked-outline; }
-.@{ionicons-prefix}ios-loop:before { content: @ionicon-var-ios-loop; }
-.@{ionicons-prefix}ios-loop-strong:before { content: @ionicon-var-ios-loop-strong; }
-.@{ionicons-prefix}ios-medical:before { content: @ionicon-var-ios-medical; }
-.@{ionicons-prefix}ios-medical-outline:before { content: @ionicon-var-ios-medical-outline; }
-.@{ionicons-prefix}ios-medkit:before { content: @ionicon-var-ios-medkit; }
-.@{ionicons-prefix}ios-medkit-outline:before { content: @ionicon-var-ios-medkit-outline; }
-.@{ionicons-prefix}ios-mic:before { content: @ionicon-var-ios-mic; }
-.@{ionicons-prefix}ios-mic-off:before { content: @ionicon-var-ios-mic-off; }
-.@{ionicons-prefix}ios-mic-outline:before { content: @ionicon-var-ios-mic-outline; }
-.@{ionicons-prefix}ios-minus:before { content: @ionicon-var-ios-minus; }
-.@{ionicons-prefix}ios-minus-empty:before { content: @ionicon-var-ios-minus-empty; }
-.@{ionicons-prefix}ios-minus-outline:before { content: @ionicon-var-ios-minus-outline; }
-.@{ionicons-prefix}ios-monitor:before { content: @ionicon-var-ios-monitor; }
-.@{ionicons-prefix}ios-monitor-outline:before { content: @ionicon-var-ios-monitor-outline; }
-.@{ionicons-prefix}ios-moon:before { content: @ionicon-var-ios-moon; }
-.@{ionicons-prefix}ios-moon-outline:before { content: @ionicon-var-ios-moon-outline; }
-.@{ionicons-prefix}ios-more:before { content: @ionicon-var-ios-more; }
-.@{ionicons-prefix}ios-more-outline:before { content: @ionicon-var-ios-more-outline; }
-.@{ionicons-prefix}ios-musical-note:before { content: @ionicon-var-ios-musical-note; }
-.@{ionicons-prefix}ios-musical-notes:before { content: @ionicon-var-ios-musical-notes; }
-.@{ionicons-prefix}ios-navigate:before { content: @ionicon-var-ios-navigate; }
-.@{ionicons-prefix}ios-navigate-outline:before { content: @ionicon-var-ios-navigate-outline; }
-.@{ionicons-prefix}ios-nutrition:before { content: @ionicon-var-ios-nutrition; }
-.@{ionicons-prefix}ios-nutrition-outline:before { content: @ionicon-var-ios-nutrition-outline; }
-.@{ionicons-prefix}ios-paper:before { content: @ionicon-var-ios-paper; }
-.@{ionicons-prefix}ios-paper-outline:before { content: @ionicon-var-ios-paper-outline; }
-.@{ionicons-prefix}ios-paperplane:before { content: @ionicon-var-ios-paperplane; }
-.@{ionicons-prefix}ios-paperplane-outline:before { content: @ionicon-var-ios-paperplane-outline; }
-.@{ionicons-prefix}ios-partlysunny:before { content: @ionicon-var-ios-partlysunny; }
-.@{ionicons-prefix}ios-partlysunny-outline:before { content: @ionicon-var-ios-partlysunny-outline; }
-.@{ionicons-prefix}ios-pause:before { content: @ionicon-var-ios-pause; }
-.@{ionicons-prefix}ios-pause-outline:before { content: @ionicon-var-ios-pause-outline; }
-.@{ionicons-prefix}ios-paw:before { content: @ionicon-var-ios-paw; }
-.@{ionicons-prefix}ios-paw-outline:before { content: @ionicon-var-ios-paw-outline; }
-.@{ionicons-prefix}ios-people:before { content: @ionicon-var-ios-people; }
-.@{ionicons-prefix}ios-people-outline:before { content: @ionicon-var-ios-people-outline; }
-.@{ionicons-prefix}ios-person:before { content: @ionicon-var-ios-person; }
-.@{ionicons-prefix}ios-person-outline:before { content: @ionicon-var-ios-person-outline; }
-.@{ionicons-prefix}ios-personadd:before { content: @ionicon-var-ios-personadd; }
-.@{ionicons-prefix}ios-personadd-outline:before { content: @ionicon-var-ios-personadd-outline; }
-.@{ionicons-prefix}ios-photos:before { content: @ionicon-var-ios-photos; }
-.@{ionicons-prefix}ios-photos-outline:before { content: @ionicon-var-ios-photos-outline; }
-.@{ionicons-prefix}ios-pie:before { content: @ionicon-var-ios-pie; }
-.@{ionicons-prefix}ios-pie-outline:before { content: @ionicon-var-ios-pie-outline; }
-.@{ionicons-prefix}ios-pint:before { content: @ionicon-var-ios-pint; }
-.@{ionicons-prefix}ios-pint-outline:before { content: @ionicon-var-ios-pint-outline; }
-.@{ionicons-prefix}ios-play:before { content: @ionicon-var-ios-play; }
-.@{ionicons-prefix}ios-play-outline:before { content: @ionicon-var-ios-play-outline; }
-.@{ionicons-prefix}ios-plus:before { content: @ionicon-var-ios-plus; }
-.@{ionicons-prefix}ios-plus-empty:before { content: @ionicon-var-ios-plus-empty; }
-.@{ionicons-prefix}ios-plus-outline:before { content: @ionicon-var-ios-plus-outline; }
-.@{ionicons-prefix}ios-pricetag:before { content: @ionicon-var-ios-pricetag; }
-.@{ionicons-prefix}ios-pricetag-outline:before { content: @ionicon-var-ios-pricetag-outline; }
-.@{ionicons-prefix}ios-pricetags:before { content: @ionicon-var-ios-pricetags; }
-.@{ionicons-prefix}ios-pricetags-outline:before { content: @ionicon-var-ios-pricetags-outline; }
-.@{ionicons-prefix}ios-printer:before { content: @ionicon-var-ios-printer; }
-.@{ionicons-prefix}ios-printer-outline:before { content: @ionicon-var-ios-printer-outline; }
-.@{ionicons-prefix}ios-pulse:before { content: @ionicon-var-ios-pulse; }
-.@{ionicons-prefix}ios-pulse-strong:before { content: @ionicon-var-ios-pulse-strong; }
-.@{ionicons-prefix}ios-rainy:before { content: @ionicon-var-ios-rainy; }
-.@{ionicons-prefix}ios-rainy-outline:before { content: @ionicon-var-ios-rainy-outline; }
-.@{ionicons-prefix}ios-recording:before { content: @ionicon-var-ios-recording; }
-.@{ionicons-prefix}ios-recording-outline:before { content: @ionicon-var-ios-recording-outline; }
-.@{ionicons-prefix}ios-redo:before { content: @ionicon-var-ios-redo; }
-.@{ionicons-prefix}ios-redo-outline:before { content: @ionicon-var-ios-redo-outline; }
-.@{ionicons-prefix}ios-refresh:before { content: @ionicon-var-ios-refresh; }
-.@{ionicons-prefix}ios-refresh-empty:before { content: @ionicon-var-ios-refresh-empty; }
-.@{ionicons-prefix}ios-refresh-outline:before { content: @ionicon-var-ios-refresh-outline; }
-.@{ionicons-prefix}ios-reload:before { content: @ionicon-var-ios-reload; }
-.@{ionicons-prefix}ios-reverse-camera:before { content: @ionicon-var-ios-reverse-camera; }
-.@{ionicons-prefix}ios-reverse-camera-outline:before { content: @ionicon-var-ios-reverse-camera-outline; }
-.@{ionicons-prefix}ios-rewind:before { content: @ionicon-var-ios-rewind; }
-.@{ionicons-prefix}ios-rewind-outline:before { content: @ionicon-var-ios-rewind-outline; }
-.@{ionicons-prefix}ios-rose:before { content: @ionicon-var-ios-rose; }
-.@{ionicons-prefix}ios-rose-outline:before { content: @ionicon-var-ios-rose-outline; }
-.@{ionicons-prefix}ios-search:before { content: @ionicon-var-ios-search; }
-.@{ionicons-prefix}ios-search-strong:before { content: @ionicon-var-ios-search-strong; }
-.@{ionicons-prefix}ios-settings:before { content: @ionicon-var-ios-settings; }
-.@{ionicons-prefix}ios-settings-strong:before { content: @ionicon-var-ios-settings-strong; }
-.@{ionicons-prefix}ios-shuffle:before { content: @ionicon-var-ios-shuffle; }
-.@{ionicons-prefix}ios-shuffle-strong:before { content: @ionicon-var-ios-shuffle-strong; }
-.@{ionicons-prefix}ios-skipbackward:before { content: @ionicon-var-ios-skipbackward; }
-.@{ionicons-prefix}ios-skipbackward-outline:before { content: @ionicon-var-ios-skipbackward-outline; }
-.@{ionicons-prefix}ios-skipforward:before { content: @ionicon-var-ios-skipforward; }
-.@{ionicons-prefix}ios-skipforward-outline:before { content: @ionicon-var-ios-skipforward-outline; }
-.@{ionicons-prefix}ios-snowy:before { content: @ionicon-var-ios-snowy; }
-.@{ionicons-prefix}ios-speedometer:before { content: @ionicon-var-ios-speedometer; }
-.@{ionicons-prefix}ios-speedometer-outline:before { content: @ionicon-var-ios-speedometer-outline; }
-.@{ionicons-prefix}ios-star:before { content: @ionicon-var-ios-star; }
-.@{ionicons-prefix}ios-star-half:before { content: @ionicon-var-ios-star-half; }
-.@{ionicons-prefix}ios-star-outline:before { content: @ionicon-var-ios-star-outline; }
-.@{ionicons-prefix}ios-stopwatch:before { content: @ionicon-var-ios-stopwatch; }
-.@{ionicons-prefix}ios-stopwatch-outline:before { content: @ionicon-var-ios-stopwatch-outline; }
-.@{ionicons-prefix}ios-sunny:before { content: @ionicon-var-ios-sunny; }
-.@{ionicons-prefix}ios-sunny-outline:before { content: @ionicon-var-ios-sunny-outline; }
-.@{ionicons-prefix}ios-telephone:before { content: @ionicon-var-ios-telephone; }
-.@{ionicons-prefix}ios-telephone-outline:before { content: @ionicon-var-ios-telephone-outline; }
-.@{ionicons-prefix}ios-tennisball:before { content: @ionicon-var-ios-tennisball; }
-.@{ionicons-prefix}ios-tennisball-outline:before { content: @ionicon-var-ios-tennisball-outline; }
-.@{ionicons-prefix}ios-thunderstorm:before { content: @ionicon-var-ios-thunderstorm; }
-.@{ionicons-prefix}ios-thunderstorm-outline:before { content: @ionicon-var-ios-thunderstorm-outline; }
-.@{ionicons-prefix}ios-time:before { content: @ionicon-var-ios-time; }
-.@{ionicons-prefix}ios-time-outline:before { content: @ionicon-var-ios-time-outline; }
-.@{ionicons-prefix}ios-timer:before { content: @ionicon-var-ios-timer; }
-.@{ionicons-prefix}ios-timer-outline:before { content: @ionicon-var-ios-timer-outline; }
-.@{ionicons-prefix}ios-toggle:before { content: @ionicon-var-ios-toggle; }
-.@{ionicons-prefix}ios-toggle-outline:before { content: @ionicon-var-ios-toggle-outline; }
-.@{ionicons-prefix}ios-trash:before { content: @ionicon-var-ios-trash; }
-.@{ionicons-prefix}ios-trash-outline:before { content: @ionicon-var-ios-trash-outline; }
-.@{ionicons-prefix}ios-undo:before { content: @ionicon-var-ios-undo; }
-.@{ionicons-prefix}ios-undo-outline:before { content: @ionicon-var-ios-undo-outline; }
-.@{ionicons-prefix}ios-unlocked:before { content: @ionicon-var-ios-unlocked; }
-.@{ionicons-prefix}ios-unlocked-outline:before { content: @ionicon-var-ios-unlocked-outline; }
-.@{ionicons-prefix}ios-upload:before { content: @ionicon-var-ios-upload; }
-.@{ionicons-prefix}ios-upload-outline:before { content: @ionicon-var-ios-upload-outline; }
-.@{ionicons-prefix}ios-videocam:before { content: @ionicon-var-ios-videocam; }
-.@{ionicons-prefix}ios-videocam-outline:before { content: @ionicon-var-ios-videocam-outline; }
-.@{ionicons-prefix}ios-volume-high:before { content: @ionicon-var-ios-volume-high; }
-.@{ionicons-prefix}ios-volume-low:before { content: @ionicon-var-ios-volume-low; }
-.@{ionicons-prefix}ios-wineglass:before { content: @ionicon-var-ios-wineglass; }
-.@{ionicons-prefix}ios-wineglass-outline:before { content: @ionicon-var-ios-wineglass-outline; }
-.@{ionicons-prefix}ios-world:before { content: @ionicon-var-ios-world; }
-.@{ionicons-prefix}ios-world-outline:before { content: @ionicon-var-ios-world-outline; }
-.@{ionicons-prefix}ipad:before { content: @ionicon-var-ipad; }
-.@{ionicons-prefix}iphone:before { content: @ionicon-var-iphone; }
-.@{ionicons-prefix}ipod:before { content: @ionicon-var-ipod; }
-.@{ionicons-prefix}jet:before { content: @ionicon-var-jet; }
-.@{ionicons-prefix}key:before { content: @ionicon-var-key; }
-.@{ionicons-prefix}knife:before { content: @ionicon-var-knife; }
-.@{ionicons-prefix}laptop:before { content: @ionicon-var-laptop; }
-.@{ionicons-prefix}leaf:before { content: @ionicon-var-leaf; }
-.@{ionicons-prefix}levels:before { content: @ionicon-var-levels; }
-.@{ionicons-prefix}lightbulb:before { content: @ionicon-var-lightbulb; }
-.@{ionicons-prefix}link:before { content: @ionicon-var-link; }
-.@{ionicons-prefix}load-a:before { content: @ionicon-var-load-a; }
-.@{ionicons-prefix}load-b:before { content: @ionicon-var-load-b; }
-.@{ionicons-prefix}load-c:before { content: @ionicon-var-load-c; }
-.@{ionicons-prefix}load-d:before { content: @ionicon-var-load-d; }
-.@{ionicons-prefix}location:before { content: @ionicon-var-location; }
-.@{ionicons-prefix}lock-combination:before { content: @ionicon-var-lock-combination; }
-.@{ionicons-prefix}locked:before { content: @ionicon-var-locked; }
-.@{ionicons-prefix}log-in:before { content: @ionicon-var-log-in; }
-.@{ionicons-prefix}log-out:before { content: @ionicon-var-log-out; }
-.@{ionicons-prefix}loop:before { content: @ionicon-var-loop; }
-.@{ionicons-prefix}magnet:before { content: @ionicon-var-magnet; }
-.@{ionicons-prefix}male:before { content: @ionicon-var-male; }
-.@{ionicons-prefix}man:before { content: @ionicon-var-man; }
-.@{ionicons-prefix}map:before { content: @ionicon-var-map; }
-.@{ionicons-prefix}medkit:before { content: @ionicon-var-medkit; }
-.@{ionicons-prefix}merge:before { content: @ionicon-var-merge; }
-.@{ionicons-prefix}mic-a:before { content: @ionicon-var-mic-a; }
-.@{ionicons-prefix}mic-b:before { content: @ionicon-var-mic-b; }
-.@{ionicons-prefix}mic-c:before { content: @ionicon-var-mic-c; }
-.@{ionicons-prefix}minus:before { content: @ionicon-var-minus; }
-.@{ionicons-prefix}minus-circled:before { content: @ionicon-var-minus-circled; }
-.@{ionicons-prefix}minus-round:before { content: @ionicon-var-minus-round; }
-.@{ionicons-prefix}model-s:before { content: @ionicon-var-model-s; }
-.@{ionicons-prefix}monitor:before { content: @ionicon-var-monitor; }
-.@{ionicons-prefix}more:before { content: @ionicon-var-more; }
-.@{ionicons-prefix}mouse:before { content: @ionicon-var-mouse; }
-.@{ionicons-prefix}music-note:before { content: @ionicon-var-music-note; }
-.@{ionicons-prefix}navicon:before { content: @ionicon-var-navicon; }
-.@{ionicons-prefix}navicon-round:before { content: @ionicon-var-navicon-round; }
-.@{ionicons-prefix}navigate:before { content: @ionicon-var-navigate; }
-.@{ionicons-prefix}network:before { content: @ionicon-var-network; }
-.@{ionicons-prefix}no-smoking:before { content: @ionicon-var-no-smoking; }
-.@{ionicons-prefix}nuclear:before { content: @ionicon-var-nuclear; }
-.@{ionicons-prefix}outlet:before { content: @ionicon-var-outlet; }
-.@{ionicons-prefix}paintbrush:before { content: @ionicon-var-paintbrush; }
-.@{ionicons-prefix}paintbucket:before { content: @ionicon-var-paintbucket; }
-.@{ionicons-prefix}paper-airplane:before { content: @ionicon-var-paper-airplane; }
-.@{ionicons-prefix}paperclip:before { content: @ionicon-var-paperclip; }
-.@{ionicons-prefix}pause:before { content: @ionicon-var-pause; }
-.@{ionicons-prefix}person:before { content: @ionicon-var-person; }
-.@{ionicons-prefix}person-add:before { content: @ionicon-var-person-add; }
-.@{ionicons-prefix}person-stalker:before { content: @ionicon-var-person-stalker; }
-.@{ionicons-prefix}pie-graph:before { content: @ionicon-var-pie-graph; }
-.@{ionicons-prefix}pin:before { content: @ionicon-var-pin; }
-.@{ionicons-prefix}pinpoint:before { content: @ionicon-var-pinpoint; }
-.@{ionicons-prefix}pizza:before { content: @ionicon-var-pizza; }
-.@{ionicons-prefix}plane:before { content: @ionicon-var-plane; }
-.@{ionicons-prefix}planet:before { content: @ionicon-var-planet; }
-.@{ionicons-prefix}play:before { content: @ionicon-var-play; }
-.@{ionicons-prefix}playstation:before { content: @ionicon-var-playstation; }
-.@{ionicons-prefix}plus:before { content: @ionicon-var-plus; }
-.@{ionicons-prefix}plus-circled:before { content: @ionicon-var-plus-circled; }
-.@{ionicons-prefix}plus-round:before { content: @ionicon-var-plus-round; }
-.@{ionicons-prefix}podium:before { content: @ionicon-var-podium; }
-.@{ionicons-prefix}pound:before { content: @ionicon-var-pound; }
-.@{ionicons-prefix}power:before { content: @ionicon-var-power; }
-.@{ionicons-prefix}pricetag:before { content: @ionicon-var-pricetag; }
-.@{ionicons-prefix}pricetags:before { content: @ionicon-var-pricetags; }
-.@{ionicons-prefix}printer:before { content: @ionicon-var-printer; }
-.@{ionicons-prefix}pull-request:before { content: @ionicon-var-pull-request; }
-.@{ionicons-prefix}qr-scanner:before { content: @ionicon-var-qr-scanner; }
-.@{ionicons-prefix}quote:before { content: @ionicon-var-quote; }
-.@{ionicons-prefix}radio-waves:before { content: @ionicon-var-radio-waves; }
-.@{ionicons-prefix}record:before { content: @ionicon-var-record; }
-.@{ionicons-prefix}refresh:before { content: @ionicon-var-refresh; }
-.@{ionicons-prefix}reply:before { content: @ionicon-var-reply; }
-.@{ionicons-prefix}reply-all:before { content: @ionicon-var-reply-all; }
-.@{ionicons-prefix}ribbon-a:before { content: @ionicon-var-ribbon-a; }
-.@{ionicons-prefix}ribbon-b:before { content: @ionicon-var-ribbon-b; }
-.@{ionicons-prefix}sad:before { content: @ionicon-var-sad; }
-.@{ionicons-prefix}sad-outline:before { content: @ionicon-var-sad-outline; }
-.@{ionicons-prefix}scissors:before { content: @ionicon-var-scissors; }
-.@{ionicons-prefix}search:before { content: @ionicon-var-search; }
-.@{ionicons-prefix}settings:before { content: @ionicon-var-settings; }
-.@{ionicons-prefix}share:before { content: @ionicon-var-share; }
-.@{ionicons-prefix}shuffle:before { content: @ionicon-var-shuffle; }
-.@{ionicons-prefix}skip-backward:before { content: @ionicon-var-skip-backward; }
-.@{ionicons-prefix}skip-forward:before { content: @ionicon-var-skip-forward; }
-.@{ionicons-prefix}social-android:before { content: @ionicon-var-social-android; }
-.@{ionicons-prefix}social-android-outline:before { content: @ionicon-var-social-android-outline; }
-.@{ionicons-prefix}social-angular:before { content: @ionicon-var-social-angular; }
-.@{ionicons-prefix}social-angular-outline:before { content: @ionicon-var-social-angular-outline; }
-.@{ionicons-prefix}social-apple:before { content: @ionicon-var-social-apple; }
-.@{ionicons-prefix}social-apple-outline:before { content: @ionicon-var-social-apple-outline; }
-.@{ionicons-prefix}social-bitcoin:before { content: @ionicon-var-social-bitcoin; }
-.@{ionicons-prefix}social-bitcoin-outline:before { content: @ionicon-var-social-bitcoin-outline; }
-.@{ionicons-prefix}social-buffer:before { content: @ionicon-var-social-buffer; }
-.@{ionicons-prefix}social-buffer-outline:before { content: @ionicon-var-social-buffer-outline; }
-.@{ionicons-prefix}social-chrome:before { content: @ionicon-var-social-chrome; }
-.@{ionicons-prefix}social-chrome-outline:before { content: @ionicon-var-social-chrome-outline; }
-.@{ionicons-prefix}social-codepen:before { content: @ionicon-var-social-codepen; }
-.@{ionicons-prefix}social-codepen-outline:before { content: @ionicon-var-social-codepen-outline; }
-.@{ionicons-prefix}social-css3:before { content: @ionicon-var-social-css3; }
-.@{ionicons-prefix}social-css3-outline:before { content: @ionicon-var-social-css3-outline; }
-.@{ionicons-prefix}social-designernews:before { content: @ionicon-var-social-designernews; }
-.@{ionicons-prefix}social-designernews-outline:before { content: @ionicon-var-social-designernews-outline; }
-.@{ionicons-prefix}social-dribbble:before { content: @ionicon-var-social-dribbble; }
-.@{ionicons-prefix}social-dribbble-outline:before { content: @ionicon-var-social-dribbble-outline; }
-.@{ionicons-prefix}social-dropbox:before { content: @ionicon-var-social-dropbox; }
-.@{ionicons-prefix}social-dropbox-outline:before { content: @ionicon-var-social-dropbox-outline; }
-.@{ionicons-prefix}social-euro:before { content: @ionicon-var-social-euro; }
-.@{ionicons-prefix}social-euro-outline:before { content: @ionicon-var-social-euro-outline; }
-.@{ionicons-prefix}social-facebook:before { content: @ionicon-var-social-facebook; }
-.@{ionicons-prefix}social-facebook-outline:before { content: @ionicon-var-social-facebook-outline; }
-.@{ionicons-prefix}social-foursquare:before { content: @ionicon-var-social-foursquare; }
-.@{ionicons-prefix}social-foursquare-outline:before { content: @ionicon-var-social-foursquare-outline; }
-.@{ionicons-prefix}social-freebsd-devil:before { content: @ionicon-var-social-freebsd-devil; }
-.@{ionicons-prefix}social-github:before { content: @ionicon-var-social-github; }
-.@{ionicons-prefix}social-github-outline:before { content: @ionicon-var-social-github-outline; }
-.@{ionicons-prefix}social-google:before { content: @ionicon-var-social-google; }
-.@{ionicons-prefix}social-google-outline:before { content: @ionicon-var-social-google-outline; }
-.@{ionicons-prefix}social-googleplus:before { content: @ionicon-var-social-googleplus; }
-.@{ionicons-prefix}social-googleplus-outline:before { content: @ionicon-var-social-googleplus-outline; }
-.@{ionicons-prefix}social-hackernews:before { content: @ionicon-var-social-hackernews; }
-.@{ionicons-prefix}social-hackernews-outline:before { content: @ionicon-var-social-hackernews-outline; }
-.@{ionicons-prefix}social-html5:before { content: @ionicon-var-social-html5; }
-.@{ionicons-prefix}social-html5-outline:before { content: @ionicon-var-social-html5-outline; }
-.@{ionicons-prefix}social-instagram:before { content: @ionicon-var-social-instagram; }
-.@{ionicons-prefix}social-instagram-outline:before { content: @ionicon-var-social-instagram-outline; }
-.@{ionicons-prefix}social-javascript:before { content: @ionicon-var-social-javascript; }
-.@{ionicons-prefix}social-javascript-outline:before { content: @ionicon-var-social-javascript-outline; }
-.@{ionicons-prefix}social-linkedin:before { content: @ionicon-var-social-linkedin; }
-.@{ionicons-prefix}social-linkedin-outline:before { content: @ionicon-var-social-linkedin-outline; }
-.@{ionicons-prefix}social-markdown:before { content: @ionicon-var-social-markdown; }
-.@{ionicons-prefix}social-nodejs:before { content: @ionicon-var-social-nodejs; }
-.@{ionicons-prefix}social-octocat:before { content: @ionicon-var-social-octocat; }
-.@{ionicons-prefix}social-pinterest:before { content: @ionicon-var-social-pinterest; }
-.@{ionicons-prefix}social-pinterest-outline:before { content: @ionicon-var-social-pinterest-outline; }
-.@{ionicons-prefix}social-python:before { content: @ionicon-var-social-python; }
-.@{ionicons-prefix}social-reddit:before { content: @ionicon-var-social-reddit; }
-.@{ionicons-prefix}social-reddit-outline:before { content: @ionicon-var-social-reddit-outline; }
-.@{ionicons-prefix}social-rss:before { content: @ionicon-var-social-rss; }
-.@{ionicons-prefix}social-rss-outline:before { content: @ionicon-var-social-rss-outline; }
-.@{ionicons-prefix}social-sass:before { content: @ionicon-var-social-sass; }
-.@{ionicons-prefix}social-skype:before { content: @ionicon-var-social-skype; }
-.@{ionicons-prefix}social-skype-outline:before { content: @ionicon-var-social-skype-outline; }
-.@{ionicons-prefix}social-snapchat:before { content: @ionicon-var-social-snapchat; }
-.@{ionicons-prefix}social-snapchat-outline:before { content: @ionicon-var-social-snapchat-outline; }
-.@{ionicons-prefix}social-tumblr:before { content: @ionicon-var-social-tumblr; }
-.@{ionicons-prefix}social-tumblr-outline:before { content: @ionicon-var-social-tumblr-outline; }
-.@{ionicons-prefix}social-tux:before { content: @ionicon-var-social-tux; }
-.@{ionicons-prefix}social-twitch:before { content: @ionicon-var-social-twitch; }
-.@{ionicons-prefix}social-twitch-outline:before { content: @ionicon-var-social-twitch-outline; }
-.@{ionicons-prefix}social-twitter:before { content: @ionicon-var-social-twitter; }
-.@{ionicons-prefix}social-twitter-outline:before { content: @ionicon-var-social-twitter-outline; }
-.@{ionicons-prefix}social-usd:before { content: @ionicon-var-social-usd; }
-.@{ionicons-prefix}social-usd-outline:before { content: @ionicon-var-social-usd-outline; }
-.@{ionicons-prefix}social-vimeo:before { content: @ionicon-var-social-vimeo; }
-.@{ionicons-prefix}social-vimeo-outline:before { content: @ionicon-var-social-vimeo-outline; }
-.@{ionicons-prefix}social-whatsapp:before { content: @ionicon-var-social-whatsapp; }
-.@{ionicons-prefix}social-whatsapp-outline:before { content: @ionicon-var-social-whatsapp-outline; }
-.@{ionicons-prefix}social-windows:before { content: @ionicon-var-social-windows; }
-.@{ionicons-prefix}social-windows-outline:before { content: @ionicon-var-social-windows-outline; }
-.@{ionicons-prefix}social-wordpress:before { content: @ionicon-var-social-wordpress; }
-.@{ionicons-prefix}social-wordpress-outline:before { content: @ionicon-var-social-wordpress-outline; }
-.@{ionicons-prefix}social-yahoo:before { content: @ionicon-var-social-yahoo; }
-.@{ionicons-prefix}social-yahoo-outline:before { content: @ionicon-var-social-yahoo-outline; }
-.@{ionicons-prefix}social-yen:before { content: @ionicon-var-social-yen; }
-.@{ionicons-prefix}social-yen-outline:before { content: @ionicon-var-social-yen-outline; }
-.@{ionicons-prefix}social-youtube:before { content: @ionicon-var-social-youtube; }
-.@{ionicons-prefix}social-youtube-outline:before { content: @ionicon-var-social-youtube-outline; }
-.@{ionicons-prefix}soup-can:before { content: @ionicon-var-soup-can; }
-.@{ionicons-prefix}soup-can-outline:before { content: @ionicon-var-soup-can-outline; }
-.@{ionicons-prefix}speakerphone:before { content: @ionicon-var-speakerphone; }
-.@{ionicons-prefix}speedometer:before { content: @ionicon-var-speedometer; }
-.@{ionicons-prefix}spoon:before { content: @ionicon-var-spoon; }
-.@{ionicons-prefix}star:before { content: @ionicon-var-star; }
-.@{ionicons-prefix}stats-bars:before { content: @ionicon-var-stats-bars; }
-.@{ionicons-prefix}steam:before { content: @ionicon-var-steam; }
-.@{ionicons-prefix}stop:before { content: @ionicon-var-stop; }
-.@{ionicons-prefix}thermometer:before { content: @ionicon-var-thermometer; }
-.@{ionicons-prefix}thumbsdown:before { content: @ionicon-var-thumbsdown; }
-.@{ionicons-prefix}thumbsup:before { content: @ionicon-var-thumbsup; }
-.@{ionicons-prefix}toggle:before { content: @ionicon-var-toggle; }
-.@{ionicons-prefix}toggle-filled:before { content: @ionicon-var-toggle-filled; }
-.@{ionicons-prefix}transgender:before { content: @ionicon-var-transgender; }
-.@{ionicons-prefix}trash-a:before { content: @ionicon-var-trash-a; }
-.@{ionicons-prefix}trash-b:before { content: @ionicon-var-trash-b; }
-.@{ionicons-prefix}trophy:before { content: @ionicon-var-trophy; }
-.@{ionicons-prefix}tshirt:before { content: @ionicon-var-tshirt; }
-.@{ionicons-prefix}tshirt-outline:before { content: @ionicon-var-tshirt-outline; }
-.@{ionicons-prefix}umbrella:before { content: @ionicon-var-umbrella; }
-.@{ionicons-prefix}university:before { content: @ionicon-var-university; }
-.@{ionicons-prefix}unlocked:before { content: @ionicon-var-unlocked; }
-.@{ionicons-prefix}upload:before { content: @ionicon-var-upload; }
-.@{ionicons-prefix}usb:before { content: @ionicon-var-usb; }
-.@{ionicons-prefix}videocamera:before { content: @ionicon-var-videocamera; }
-.@{ionicons-prefix}volume-high:before { content: @ionicon-var-volume-high; }
-.@{ionicons-prefix}volume-low:before { content: @ionicon-var-volume-low; }
-.@{ionicons-prefix}volume-medium:before { content: @ionicon-var-volume-medium; }
-.@{ionicons-prefix}volume-mute:before { content: @ionicon-var-volume-mute; }
-.@{ionicons-prefix}wand:before { content: @ionicon-var-wand; }
-.@{ionicons-prefix}waterdrop:before { content: @ionicon-var-waterdrop; }
-.@{ionicons-prefix}wifi:before { content: @ionicon-var-wifi; }
-.@{ionicons-prefix}wineglass:before { content: @ionicon-var-wineglass; }
-.@{ionicons-prefix}woman:before { content: @ionicon-var-woman; }
-.@{ionicons-prefix}wrench:before { content: @ionicon-var-wrench; }
-.@{ionicons-prefix}xbox:before { content: @ionicon-var-xbox; } \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-variables.less b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-variables.less
deleted file mode 100644
index 91195271..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/_ionicons-variables.less
+++ /dev/null
@@ -1,747 +0,0 @@
-/*!
-Ionicons, v2.0.0
-Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
-https://twitter.com/benjsperry https://twitter.com/ionicframework
-MIT License: https://github.com/driftyco/ionicons
-*/
-// Ionicons Variables
-// --------------------------
-
-@ionicons-font-path: "../fonts";
-@ionicons-font-family: "Ionicons";
-@ionicons-version: "2.0.0";
-@ionicons-prefix: ion-;
-
-@ionicon-var-alert: "\f101";
-@ionicon-var-alert-circled: "\f100";
-@ionicon-var-android-add: "\f2c7";
-@ionicon-var-android-add-circle: "\f359";
-@ionicon-var-android-alarm-clock: "\f35a";
-@ionicon-var-android-alert: "\f35b";
-@ionicon-var-android-apps: "\f35c";
-@ionicon-var-android-archive: "\f2c9";
-@ionicon-var-android-arrow-back: "\f2ca";
-@ionicon-var-android-arrow-down: "\f35d";
-@ionicon-var-android-arrow-dropdown: "\f35f";
-@ionicon-var-android-arrow-dropdown-circle: "\f35e";
-@ionicon-var-android-arrow-dropleft: "\f361";
-@ionicon-var-android-arrow-dropleft-circle: "\f360";
-@ionicon-var-android-arrow-dropright: "\f363";
-@ionicon-var-android-arrow-dropright-circle: "\f362";
-@ionicon-var-android-arrow-dropup: "\f365";
-@ionicon-var-android-arrow-dropup-circle: "\f364";
-@ionicon-var-android-arrow-forward: "\f30f";
-@ionicon-var-android-arrow-up: "\f366";
-@ionicon-var-android-attach: "\f367";
-@ionicon-var-android-bar: "\f368";
-@ionicon-var-android-bicycle: "\f369";
-@ionicon-var-android-boat: "\f36a";
-@ionicon-var-android-bookmark: "\f36b";
-@ionicon-var-android-bulb: "\f36c";
-@ionicon-var-android-bus: "\f36d";
-@ionicon-var-android-calendar: "\f2d1";
-@ionicon-var-android-call: "\f2d2";
-@ionicon-var-android-camera: "\f2d3";
-@ionicon-var-android-cancel: "\f36e";
-@ionicon-var-android-car: "\f36f";
-@ionicon-var-android-cart: "\f370";
-@ionicon-var-android-chat: "\f2d4";
-@ionicon-var-android-checkbox: "\f374";
-@ionicon-var-android-checkbox-blank: "\f371";
-@ionicon-var-android-checkbox-outline: "\f373";
-@ionicon-var-android-checkbox-outline-blank: "\f372";
-@ionicon-var-android-checkmark-circle: "\f375";
-@ionicon-var-android-clipboard: "\f376";
-@ionicon-var-android-close: "\f2d7";
-@ionicon-var-android-cloud: "\f37a";
-@ionicon-var-android-cloud-circle: "\f377";
-@ionicon-var-android-cloud-done: "\f378";
-@ionicon-var-android-cloud-outline: "\f379";
-@ionicon-var-android-color-palette: "\f37b";
-@ionicon-var-android-compass: "\f37c";
-@ionicon-var-android-contact: "\f2d8";
-@ionicon-var-android-contacts: "\f2d9";
-@ionicon-var-android-contract: "\f37d";
-@ionicon-var-android-create: "\f37e";
-@ionicon-var-android-delete: "\f37f";
-@ionicon-var-android-desktop: "\f380";
-@ionicon-var-android-document: "\f381";
-@ionicon-var-android-done: "\f383";
-@ionicon-var-android-done-all: "\f382";
-@ionicon-var-android-download: "\f2dd";
-@ionicon-var-android-drafts: "\f384";
-@ionicon-var-android-exit: "\f385";
-@ionicon-var-android-expand: "\f386";
-@ionicon-var-android-favorite: "\f388";
-@ionicon-var-android-favorite-outline: "\f387";
-@ionicon-var-android-film: "\f389";
-@ionicon-var-android-folder: "\f2e0";
-@ionicon-var-android-folder-open: "\f38a";
-@ionicon-var-android-funnel: "\f38b";
-@ionicon-var-android-globe: "\f38c";
-@ionicon-var-android-hand: "\f2e3";
-@ionicon-var-android-hangout: "\f38d";
-@ionicon-var-android-happy: "\f38e";
-@ionicon-var-android-home: "\f38f";
-@ionicon-var-android-image: "\f2e4";
-@ionicon-var-android-laptop: "\f390";
-@ionicon-var-android-list: "\f391";
-@ionicon-var-android-locate: "\f2e9";
-@ionicon-var-android-lock: "\f392";
-@ionicon-var-android-mail: "\f2eb";
-@ionicon-var-android-map: "\f393";
-@ionicon-var-android-menu: "\f394";
-@ionicon-var-android-microphone: "\f2ec";
-@ionicon-var-android-microphone-off: "\f395";
-@ionicon-var-android-more-horizontal: "\f396";
-@ionicon-var-android-more-vertical: "\f397";
-@ionicon-var-android-navigate: "\f398";
-@ionicon-var-android-notifications: "\f39b";
-@ionicon-var-android-notifications-none: "\f399";
-@ionicon-var-android-notifications-off: "\f39a";
-@ionicon-var-android-open: "\f39c";
-@ionicon-var-android-options: "\f39d";
-@ionicon-var-android-people: "\f39e";
-@ionicon-var-android-person: "\f3a0";
-@ionicon-var-android-person-add: "\f39f";
-@ionicon-var-android-phone-landscape: "\f3a1";
-@ionicon-var-android-phone-portrait: "\f3a2";
-@ionicon-var-android-pin: "\f3a3";
-@ionicon-var-android-plane: "\f3a4";
-@ionicon-var-android-playstore: "\f2f0";
-@ionicon-var-android-print: "\f3a5";
-@ionicon-var-android-radio-button-off: "\f3a6";
-@ionicon-var-android-radio-button-on: "\f3a7";
-@ionicon-var-android-refresh: "\f3a8";
-@ionicon-var-android-remove: "\f2f4";
-@ionicon-var-android-remove-circle: "\f3a9";
-@ionicon-var-android-restaurant: "\f3aa";
-@ionicon-var-android-sad: "\f3ab";
-@ionicon-var-android-search: "\f2f5";
-@ionicon-var-android-send: "\f2f6";
-@ionicon-var-android-settings: "\f2f7";
-@ionicon-var-android-share: "\f2f8";
-@ionicon-var-android-share-alt: "\f3ac";
-@ionicon-var-android-star: "\f2fc";
-@ionicon-var-android-star-half: "\f3ad";
-@ionicon-var-android-star-outline: "\f3ae";
-@ionicon-var-android-stopwatch: "\f2fd";
-@ionicon-var-android-subway: "\f3af";
-@ionicon-var-android-sunny: "\f3b0";
-@ionicon-var-android-sync: "\f3b1";
-@ionicon-var-android-textsms: "\f3b2";
-@ionicon-var-android-time: "\f3b3";
-@ionicon-var-android-train: "\f3b4";
-@ionicon-var-android-unlock: "\f3b5";
-@ionicon-var-android-upload: "\f3b6";
-@ionicon-var-android-volume-down: "\f3b7";
-@ionicon-var-android-volume-mute: "\f3b8";
-@ionicon-var-android-volume-off: "\f3b9";
-@ionicon-var-android-volume-up: "\f3ba";
-@ionicon-var-android-walk: "\f3bb";
-@ionicon-var-android-warning: "\f3bc";
-@ionicon-var-android-watch: "\f3bd";
-@ionicon-var-android-wifi: "\f305";
-@ionicon-var-aperture: "\f313";
-@ionicon-var-archive: "\f102";
-@ionicon-var-arrow-down-a: "\f103";
-@ionicon-var-arrow-down-b: "\f104";
-@ionicon-var-arrow-down-c: "\f105";
-@ionicon-var-arrow-expand: "\f25e";
-@ionicon-var-arrow-graph-down-left: "\f25f";
-@ionicon-var-arrow-graph-down-right: "\f260";
-@ionicon-var-arrow-graph-up-left: "\f261";
-@ionicon-var-arrow-graph-up-right: "\f262";
-@ionicon-var-arrow-left-a: "\f106";
-@ionicon-var-arrow-left-b: "\f107";
-@ionicon-var-arrow-left-c: "\f108";
-@ionicon-var-arrow-move: "\f263";
-@ionicon-var-arrow-resize: "\f264";
-@ionicon-var-arrow-return-left: "\f265";
-@ionicon-var-arrow-return-right: "\f266";
-@ionicon-var-arrow-right-a: "\f109";
-@ionicon-var-arrow-right-b: "\f10a";
-@ionicon-var-arrow-right-c: "\f10b";
-@ionicon-var-arrow-shrink: "\f267";
-@ionicon-var-arrow-swap: "\f268";
-@ionicon-var-arrow-up-a: "\f10c";
-@ionicon-var-arrow-up-b: "\f10d";
-@ionicon-var-arrow-up-c: "\f10e";
-@ionicon-var-asterisk: "\f314";
-@ionicon-var-at: "\f10f";
-@ionicon-var-backspace: "\f3bf";
-@ionicon-var-backspace-outline: "\f3be";
-@ionicon-var-bag: "\f110";
-@ionicon-var-battery-charging: "\f111";
-@ionicon-var-battery-empty: "\f112";
-@ionicon-var-battery-full: "\f113";
-@ionicon-var-battery-half: "\f114";
-@ionicon-var-battery-low: "\f115";
-@ionicon-var-beaker: "\f269";
-@ionicon-var-beer: "\f26a";
-@ionicon-var-bluetooth: "\f116";
-@ionicon-var-bonfire: "\f315";
-@ionicon-var-bookmark: "\f26b";
-@ionicon-var-bowtie: "\f3c0";
-@ionicon-var-briefcase: "\f26c";
-@ionicon-var-bug: "\f2be";
-@ionicon-var-calculator: "\f26d";
-@ionicon-var-calendar: "\f117";
-@ionicon-var-camera: "\f118";
-@ionicon-var-card: "\f119";
-@ionicon-var-cash: "\f316";
-@ionicon-var-chatbox: "\f11b";
-@ionicon-var-chatbox-working: "\f11a";
-@ionicon-var-chatboxes: "\f11c";
-@ionicon-var-chatbubble: "\f11e";
-@ionicon-var-chatbubble-working: "\f11d";
-@ionicon-var-chatbubbles: "\f11f";
-@ionicon-var-checkmark: "\f122";
-@ionicon-var-checkmark-circled: "\f120";
-@ionicon-var-checkmark-round: "\f121";
-@ionicon-var-chevron-down: "\f123";
-@ionicon-var-chevron-left: "\f124";
-@ionicon-var-chevron-right: "\f125";
-@ionicon-var-chevron-up: "\f126";
-@ionicon-var-clipboard: "\f127";
-@ionicon-var-clock: "\f26e";
-@ionicon-var-close: "\f12a";
-@ionicon-var-close-circled: "\f128";
-@ionicon-var-close-round: "\f129";
-@ionicon-var-closed-captioning: "\f317";
-@ionicon-var-cloud: "\f12b";
-@ionicon-var-code: "\f271";
-@ionicon-var-code-download: "\f26f";
-@ionicon-var-code-working: "\f270";
-@ionicon-var-coffee: "\f272";
-@ionicon-var-compass: "\f273";
-@ionicon-var-compose: "\f12c";
-@ionicon-var-connection-bars: "\f274";
-@ionicon-var-contrast: "\f275";
-@ionicon-var-crop: "\f3c1";
-@ionicon-var-cube: "\f318";
-@ionicon-var-disc: "\f12d";
-@ionicon-var-document: "\f12f";
-@ionicon-var-document-text: "\f12e";
-@ionicon-var-drag: "\f130";
-@ionicon-var-earth: "\f276";
-@ionicon-var-easel: "\f3c2";
-@ionicon-var-edit: "\f2bf";
-@ionicon-var-egg: "\f277";
-@ionicon-var-eject: "\f131";
-@ionicon-var-email: "\f132";
-@ionicon-var-email-unread: "\f3c3";
-@ionicon-var-erlenmeyer-flask: "\f3c5";
-@ionicon-var-erlenmeyer-flask-bubbles: "\f3c4";
-@ionicon-var-eye: "\f133";
-@ionicon-var-eye-disabled: "\f306";
-@ionicon-var-female: "\f278";
-@ionicon-var-filing: "\f134";
-@ionicon-var-film-marker: "\f135";
-@ionicon-var-fireball: "\f319";
-@ionicon-var-flag: "\f279";
-@ionicon-var-flame: "\f31a";
-@ionicon-var-flash: "\f137";
-@ionicon-var-flash-off: "\f136";
-@ionicon-var-folder: "\f139";
-@ionicon-var-fork: "\f27a";
-@ionicon-var-fork-repo: "\f2c0";
-@ionicon-var-forward: "\f13a";
-@ionicon-var-funnel: "\f31b";
-@ionicon-var-gear-a: "\f13d";
-@ionicon-var-gear-b: "\f13e";
-@ionicon-var-grid: "\f13f";
-@ionicon-var-hammer: "\f27b";
-@ionicon-var-happy: "\f31c";
-@ionicon-var-happy-outline: "\f3c6";
-@ionicon-var-headphone: "\f140";
-@ionicon-var-heart: "\f141";
-@ionicon-var-heart-broken: "\f31d";
-@ionicon-var-help: "\f143";
-@ionicon-var-help-buoy: "\f27c";
-@ionicon-var-help-circled: "\f142";
-@ionicon-var-home: "\f144";
-@ionicon-var-icecream: "\f27d";
-@ionicon-var-image: "\f147";
-@ionicon-var-images: "\f148";
-@ionicon-var-information: "\f14a";
-@ionicon-var-information-circled: "\f149";
-@ionicon-var-ionic: "\f14b";
-@ionicon-var-ios-alarm: "\f3c8";
-@ionicon-var-ios-alarm-outline: "\f3c7";
-@ionicon-var-ios-albums: "\f3ca";
-@ionicon-var-ios-albums-outline: "\f3c9";
-@ionicon-var-ios-americanfootball: "\f3cc";
-@ionicon-var-ios-americanfootball-outline: "\f3cb";
-@ionicon-var-ios-analytics: "\f3ce";
-@ionicon-var-ios-analytics-outline: "\f3cd";
-@ionicon-var-ios-arrow-back: "\f3cf";
-@ionicon-var-ios-arrow-down: "\f3d0";
-@ionicon-var-ios-arrow-forward: "\f3d1";
-@ionicon-var-ios-arrow-left: "\f3d2";
-@ionicon-var-ios-arrow-right: "\f3d3";
-@ionicon-var-ios-arrow-thin-down: "\f3d4";
-@ionicon-var-ios-arrow-thin-left: "\f3d5";
-@ionicon-var-ios-arrow-thin-right: "\f3d6";
-@ionicon-var-ios-arrow-thin-up: "\f3d7";
-@ionicon-var-ios-arrow-up: "\f3d8";
-@ionicon-var-ios-at: "\f3da";
-@ionicon-var-ios-at-outline: "\f3d9";
-@ionicon-var-ios-barcode: "\f3dc";
-@ionicon-var-ios-barcode-outline: "\f3db";
-@ionicon-var-ios-baseball: "\f3de";
-@ionicon-var-ios-baseball-outline: "\f3dd";
-@ionicon-var-ios-basketball: "\f3e0";
-@ionicon-var-ios-basketball-outline: "\f3df";
-@ionicon-var-ios-bell: "\f3e2";
-@ionicon-var-ios-bell-outline: "\f3e1";
-@ionicon-var-ios-body: "\f3e4";
-@ionicon-var-ios-body-outline: "\f3e3";
-@ionicon-var-ios-bolt: "\f3e6";
-@ionicon-var-ios-bolt-outline: "\f3e5";
-@ionicon-var-ios-book: "\f3e8";
-@ionicon-var-ios-book-outline: "\f3e7";
-@ionicon-var-ios-bookmarks: "\f3ea";
-@ionicon-var-ios-bookmarks-outline: "\f3e9";
-@ionicon-var-ios-box: "\f3ec";
-@ionicon-var-ios-box-outline: "\f3eb";
-@ionicon-var-ios-briefcase: "\f3ee";
-@ionicon-var-ios-briefcase-outline: "\f3ed";
-@ionicon-var-ios-browsers: "\f3f0";
-@ionicon-var-ios-browsers-outline: "\f3ef";
-@ionicon-var-ios-calculator: "\f3f2";
-@ionicon-var-ios-calculator-outline: "\f3f1";
-@ionicon-var-ios-calendar: "\f3f4";
-@ionicon-var-ios-calendar-outline: "\f3f3";
-@ionicon-var-ios-camera: "\f3f6";
-@ionicon-var-ios-camera-outline: "\f3f5";
-@ionicon-var-ios-cart: "\f3f8";
-@ionicon-var-ios-cart-outline: "\f3f7";
-@ionicon-var-ios-chatboxes: "\f3fa";
-@ionicon-var-ios-chatboxes-outline: "\f3f9";
-@ionicon-var-ios-chatbubble: "\f3fc";
-@ionicon-var-ios-chatbubble-outline: "\f3fb";
-@ionicon-var-ios-checkmark: "\f3ff";
-@ionicon-var-ios-checkmark-empty: "\f3fd";
-@ionicon-var-ios-checkmark-outline: "\f3fe";
-@ionicon-var-ios-circle-filled: "\f400";
-@ionicon-var-ios-circle-outline: "\f401";
-@ionicon-var-ios-clock: "\f403";
-@ionicon-var-ios-clock-outline: "\f402";
-@ionicon-var-ios-close: "\f406";
-@ionicon-var-ios-close-empty: "\f404";
-@ionicon-var-ios-close-outline: "\f405";
-@ionicon-var-ios-cloud: "\f40c";
-@ionicon-var-ios-cloud-download: "\f408";
-@ionicon-var-ios-cloud-download-outline: "\f407";
-@ionicon-var-ios-cloud-outline: "\f409";
-@ionicon-var-ios-cloud-upload: "\f40b";
-@ionicon-var-ios-cloud-upload-outline: "\f40a";
-@ionicon-var-ios-cloudy: "\f410";
-@ionicon-var-ios-cloudy-night: "\f40e";
-@ionicon-var-ios-cloudy-night-outline: "\f40d";
-@ionicon-var-ios-cloudy-outline: "\f40f";
-@ionicon-var-ios-cog: "\f412";
-@ionicon-var-ios-cog-outline: "\f411";
-@ionicon-var-ios-color-filter: "\f414";
-@ionicon-var-ios-color-filter-outline: "\f413";
-@ionicon-var-ios-color-wand: "\f416";
-@ionicon-var-ios-color-wand-outline: "\f415";
-@ionicon-var-ios-compose: "\f418";
-@ionicon-var-ios-compose-outline: "\f417";
-@ionicon-var-ios-contact: "\f41a";
-@ionicon-var-ios-contact-outline: "\f419";
-@ionicon-var-ios-copy: "\f41c";
-@ionicon-var-ios-copy-outline: "\f41b";
-@ionicon-var-ios-crop: "\f41e";
-@ionicon-var-ios-crop-strong: "\f41d";
-@ionicon-var-ios-download: "\f420";
-@ionicon-var-ios-download-outline: "\f41f";
-@ionicon-var-ios-drag: "\f421";
-@ionicon-var-ios-email: "\f423";
-@ionicon-var-ios-email-outline: "\f422";
-@ionicon-var-ios-eye: "\f425";
-@ionicon-var-ios-eye-outline: "\f424";
-@ionicon-var-ios-fastforward: "\f427";
-@ionicon-var-ios-fastforward-outline: "\f426";
-@ionicon-var-ios-filing: "\f429";
-@ionicon-var-ios-filing-outline: "\f428";
-@ionicon-var-ios-film: "\f42b";
-@ionicon-var-ios-film-outline: "\f42a";
-@ionicon-var-ios-flag: "\f42d";
-@ionicon-var-ios-flag-outline: "\f42c";
-@ionicon-var-ios-flame: "\f42f";
-@ionicon-var-ios-flame-outline: "\f42e";
-@ionicon-var-ios-flask: "\f431";
-@ionicon-var-ios-flask-outline: "\f430";
-@ionicon-var-ios-flower: "\f433";
-@ionicon-var-ios-flower-outline: "\f432";
-@ionicon-var-ios-folder: "\f435";
-@ionicon-var-ios-folder-outline: "\f434";
-@ionicon-var-ios-football: "\f437";
-@ionicon-var-ios-football-outline: "\f436";
-@ionicon-var-ios-game-controller-a: "\f439";
-@ionicon-var-ios-game-controller-a-outline: "\f438";
-@ionicon-var-ios-game-controller-b: "\f43b";
-@ionicon-var-ios-game-controller-b-outline: "\f43a";
-@ionicon-var-ios-gear: "\f43d";
-@ionicon-var-ios-gear-outline: "\f43c";
-@ionicon-var-ios-glasses: "\f43f";
-@ionicon-var-ios-glasses-outline: "\f43e";
-@ionicon-var-ios-grid-view: "\f441";
-@ionicon-var-ios-grid-view-outline: "\f440";
-@ionicon-var-ios-heart: "\f443";
-@ionicon-var-ios-heart-outline: "\f442";
-@ionicon-var-ios-help: "\f446";
-@ionicon-var-ios-help-empty: "\f444";
-@ionicon-var-ios-help-outline: "\f445";
-@ionicon-var-ios-home: "\f448";
-@ionicon-var-ios-home-outline: "\f447";
-@ionicon-var-ios-infinite: "\f44a";
-@ionicon-var-ios-infinite-outline: "\f449";
-@ionicon-var-ios-information: "\f44d";
-@ionicon-var-ios-information-empty: "\f44b";
-@ionicon-var-ios-information-outline: "\f44c";
-@ionicon-var-ios-ionic-outline: "\f44e";
-@ionicon-var-ios-keypad: "\f450";
-@ionicon-var-ios-keypad-outline: "\f44f";
-@ionicon-var-ios-lightbulb: "\f452";
-@ionicon-var-ios-lightbulb-outline: "\f451";
-@ionicon-var-ios-list: "\f454";
-@ionicon-var-ios-list-outline: "\f453";
-@ionicon-var-ios-location: "\f456";
-@ionicon-var-ios-location-outline: "\f455";
-@ionicon-var-ios-locked: "\f458";
-@ionicon-var-ios-locked-outline: "\f457";
-@ionicon-var-ios-loop: "\f45a";
-@ionicon-var-ios-loop-strong: "\f459";
-@ionicon-var-ios-medical: "\f45c";
-@ionicon-var-ios-medical-outline: "\f45b";
-@ionicon-var-ios-medkit: "\f45e";
-@ionicon-var-ios-medkit-outline: "\f45d";
-@ionicon-var-ios-mic: "\f461";
-@ionicon-var-ios-mic-off: "\f45f";
-@ionicon-var-ios-mic-outline: "\f460";
-@ionicon-var-ios-minus: "\f464";
-@ionicon-var-ios-minus-empty: "\f462";
-@ionicon-var-ios-minus-outline: "\f463";
-@ionicon-var-ios-monitor: "\f466";
-@ionicon-var-ios-monitor-outline: "\f465";
-@ionicon-var-ios-moon: "\f468";
-@ionicon-var-ios-moon-outline: "\f467";
-@ionicon-var-ios-more: "\f46a";
-@ionicon-var-ios-more-outline: "\f469";
-@ionicon-var-ios-musical-note: "\f46b";
-@ionicon-var-ios-musical-notes: "\f46c";
-@ionicon-var-ios-navigate: "\f46e";
-@ionicon-var-ios-navigate-outline: "\f46d";
-@ionicon-var-ios-nutrition: "\f470";
-@ionicon-var-ios-nutrition-outline: "\f46f";
-@ionicon-var-ios-paper: "\f472";
-@ionicon-var-ios-paper-outline: "\f471";
-@ionicon-var-ios-paperplane: "\f474";
-@ionicon-var-ios-paperplane-outline: "\f473";
-@ionicon-var-ios-partlysunny: "\f476";
-@ionicon-var-ios-partlysunny-outline: "\f475";
-@ionicon-var-ios-pause: "\f478";
-@ionicon-var-ios-pause-outline: "\f477";
-@ionicon-var-ios-paw: "\f47a";
-@ionicon-var-ios-paw-outline: "\f479";
-@ionicon-var-ios-people: "\f47c";
-@ionicon-var-ios-people-outline: "\f47b";
-@ionicon-var-ios-person: "\f47e";
-@ionicon-var-ios-person-outline: "\f47d";
-@ionicon-var-ios-personadd: "\f480";
-@ionicon-var-ios-personadd-outline: "\f47f";
-@ionicon-var-ios-photos: "\f482";
-@ionicon-var-ios-photos-outline: "\f481";
-@ionicon-var-ios-pie: "\f484";
-@ionicon-var-ios-pie-outline: "\f483";
-@ionicon-var-ios-pint: "\f486";
-@ionicon-var-ios-pint-outline: "\f485";
-@ionicon-var-ios-play: "\f488";
-@ionicon-var-ios-play-outline: "\f487";
-@ionicon-var-ios-plus: "\f48b";
-@ionicon-var-ios-plus-empty: "\f489";
-@ionicon-var-ios-plus-outline: "\f48a";
-@ionicon-var-ios-pricetag: "\f48d";
-@ionicon-var-ios-pricetag-outline: "\f48c";
-@ionicon-var-ios-pricetags: "\f48f";
-@ionicon-var-ios-pricetags-outline: "\f48e";
-@ionicon-var-ios-printer: "\f491";
-@ionicon-var-ios-printer-outline: "\f490";
-@ionicon-var-ios-pulse: "\f493";
-@ionicon-var-ios-pulse-strong: "\f492";
-@ionicon-var-ios-rainy: "\f495";
-@ionicon-var-ios-rainy-outline: "\f494";
-@ionicon-var-ios-recording: "\f497";
-@ionicon-var-ios-recording-outline: "\f496";
-@ionicon-var-ios-redo: "\f499";
-@ionicon-var-ios-redo-outline: "\f498";
-@ionicon-var-ios-refresh: "\f49c";
-@ionicon-var-ios-refresh-empty: "\f49a";
-@ionicon-var-ios-refresh-outline: "\f49b";
-@ionicon-var-ios-reload: "\f49d";
-@ionicon-var-ios-reverse-camera: "\f49f";
-@ionicon-var-ios-reverse-camera-outline: "\f49e";
-@ionicon-var-ios-rewind: "\f4a1";
-@ionicon-var-ios-rewind-outline: "\f4a0";
-@ionicon-var-ios-rose: "\f4a3";
-@ionicon-var-ios-rose-outline: "\f4a2";
-@ionicon-var-ios-search: "\f4a5";
-@ionicon-var-ios-search-strong: "\f4a4";
-@ionicon-var-ios-settings: "\f4a7";
-@ionicon-var-ios-settings-strong: "\f4a6";
-@ionicon-var-ios-shuffle: "\f4a9";
-@ionicon-var-ios-shuffle-strong: "\f4a8";
-@ionicon-var-ios-skipbackward: "\f4ab";
-@ionicon-var-ios-skipbackward-outline: "\f4aa";
-@ionicon-var-ios-skipforward: "\f4ad";
-@ionicon-var-ios-skipforward-outline: "\f4ac";
-@ionicon-var-ios-snowy: "\f4ae";
-@ionicon-var-ios-speedometer: "\f4b0";
-@ionicon-var-ios-speedometer-outline: "\f4af";
-@ionicon-var-ios-star: "\f4b3";
-@ionicon-var-ios-star-half: "\f4b1";
-@ionicon-var-ios-star-outline: "\f4b2";
-@ionicon-var-ios-stopwatch: "\f4b5";
-@ionicon-var-ios-stopwatch-outline: "\f4b4";
-@ionicon-var-ios-sunny: "\f4b7";
-@ionicon-var-ios-sunny-outline: "\f4b6";
-@ionicon-var-ios-telephone: "\f4b9";
-@ionicon-var-ios-telephone-outline: "\f4b8";
-@ionicon-var-ios-tennisball: "\f4bb";
-@ionicon-var-ios-tennisball-outline: "\f4ba";
-@ionicon-var-ios-thunderstorm: "\f4bd";
-@ionicon-var-ios-thunderstorm-outline: "\f4bc";
-@ionicon-var-ios-time: "\f4bf";
-@ionicon-var-ios-time-outline: "\f4be";
-@ionicon-var-ios-timer: "\f4c1";
-@ionicon-var-ios-timer-outline: "\f4c0";
-@ionicon-var-ios-toggle: "\f4c3";
-@ionicon-var-ios-toggle-outline: "\f4c2";
-@ionicon-var-ios-trash: "\f4c5";
-@ionicon-var-ios-trash-outline: "\f4c4";
-@ionicon-var-ios-undo: "\f4c7";
-@ionicon-var-ios-undo-outline: "\f4c6";
-@ionicon-var-ios-unlocked: "\f4c9";
-@ionicon-var-ios-unlocked-outline: "\f4c8";
-@ionicon-var-ios-upload: "\f4cb";
-@ionicon-var-ios-upload-outline: "\f4ca";
-@ionicon-var-ios-videocam: "\f4cd";
-@ionicon-var-ios-videocam-outline: "\f4cc";
-@ionicon-var-ios-volume-high: "\f4ce";
-@ionicon-var-ios-volume-low: "\f4cf";
-@ionicon-var-ios-wineglass: "\f4d1";
-@ionicon-var-ios-wineglass-outline: "\f4d0";
-@ionicon-var-ios-world: "\f4d3";
-@ionicon-var-ios-world-outline: "\f4d2";
-@ionicon-var-ipad: "\f1f9";
-@ionicon-var-iphone: "\f1fa";
-@ionicon-var-ipod: "\f1fb";
-@ionicon-var-jet: "\f295";
-@ionicon-var-key: "\f296";
-@ionicon-var-knife: "\f297";
-@ionicon-var-laptop: "\f1fc";
-@ionicon-var-leaf: "\f1fd";
-@ionicon-var-levels: "\f298";
-@ionicon-var-lightbulb: "\f299";
-@ionicon-var-link: "\f1fe";
-@ionicon-var-load-a: "\f29a";
-@ionicon-var-load-b: "\f29b";
-@ionicon-var-load-c: "\f29c";
-@ionicon-var-load-d: "\f29d";
-@ionicon-var-location: "\f1ff";
-@ionicon-var-lock-combination: "\f4d4";
-@ionicon-var-locked: "\f200";
-@ionicon-var-log-in: "\f29e";
-@ionicon-var-log-out: "\f29f";
-@ionicon-var-loop: "\f201";
-@ionicon-var-magnet: "\f2a0";
-@ionicon-var-male: "\f2a1";
-@ionicon-var-man: "\f202";
-@ionicon-var-map: "\f203";
-@ionicon-var-medkit: "\f2a2";
-@ionicon-var-merge: "\f33f";
-@ionicon-var-mic-a: "\f204";
-@ionicon-var-mic-b: "\f205";
-@ionicon-var-mic-c: "\f206";
-@ionicon-var-minus: "\f209";
-@ionicon-var-minus-circled: "\f207";
-@ionicon-var-minus-round: "\f208";
-@ionicon-var-model-s: "\f2c1";
-@ionicon-var-monitor: "\f20a";
-@ionicon-var-more: "\f20b";
-@ionicon-var-mouse: "\f340";
-@ionicon-var-music-note: "\f20c";
-@ionicon-var-navicon: "\f20e";
-@ionicon-var-navicon-round: "\f20d";
-@ionicon-var-navigate: "\f2a3";
-@ionicon-var-network: "\f341";
-@ionicon-var-no-smoking: "\f2c2";
-@ionicon-var-nuclear: "\f2a4";
-@ionicon-var-outlet: "\f342";
-@ionicon-var-paintbrush: "\f4d5";
-@ionicon-var-paintbucket: "\f4d6";
-@ionicon-var-paper-airplane: "\f2c3";
-@ionicon-var-paperclip: "\f20f";
-@ionicon-var-pause: "\f210";
-@ionicon-var-person: "\f213";
-@ionicon-var-person-add: "\f211";
-@ionicon-var-person-stalker: "\f212";
-@ionicon-var-pie-graph: "\f2a5";
-@ionicon-var-pin: "\f2a6";
-@ionicon-var-pinpoint: "\f2a7";
-@ionicon-var-pizza: "\f2a8";
-@ionicon-var-plane: "\f214";
-@ionicon-var-planet: "\f343";
-@ionicon-var-play: "\f215";
-@ionicon-var-playstation: "\f30a";
-@ionicon-var-plus: "\f218";
-@ionicon-var-plus-circled: "\f216";
-@ionicon-var-plus-round: "\f217";
-@ionicon-var-podium: "\f344";
-@ionicon-var-pound: "\f219";
-@ionicon-var-power: "\f2a9";
-@ionicon-var-pricetag: "\f2aa";
-@ionicon-var-pricetags: "\f2ab";
-@ionicon-var-printer: "\f21a";
-@ionicon-var-pull-request: "\f345";
-@ionicon-var-qr-scanner: "\f346";
-@ionicon-var-quote: "\f347";
-@ionicon-var-radio-waves: "\f2ac";
-@ionicon-var-record: "\f21b";
-@ionicon-var-refresh: "\f21c";
-@ionicon-var-reply: "\f21e";
-@ionicon-var-reply-all: "\f21d";
-@ionicon-var-ribbon-a: "\f348";
-@ionicon-var-ribbon-b: "\f349";
-@ionicon-var-sad: "\f34a";
-@ionicon-var-sad-outline: "\f4d7";
-@ionicon-var-scissors: "\f34b";
-@ionicon-var-search: "\f21f";
-@ionicon-var-settings: "\f2ad";
-@ionicon-var-share: "\f220";
-@ionicon-var-shuffle: "\f221";
-@ionicon-var-skip-backward: "\f222";
-@ionicon-var-skip-forward: "\f223";
-@ionicon-var-social-android: "\f225";
-@ionicon-var-social-android-outline: "\f224";
-@ionicon-var-social-angular: "\f4d9";
-@ionicon-var-social-angular-outline: "\f4d8";
-@ionicon-var-social-apple: "\f227";
-@ionicon-var-social-apple-outline: "\f226";
-@ionicon-var-social-bitcoin: "\f2af";
-@ionicon-var-social-bitcoin-outline: "\f2ae";
-@ionicon-var-social-buffer: "\f229";
-@ionicon-var-social-buffer-outline: "\f228";
-@ionicon-var-social-chrome: "\f4db";
-@ionicon-var-social-chrome-outline: "\f4da";
-@ionicon-var-social-codepen: "\f4dd";
-@ionicon-var-social-codepen-outline: "\f4dc";
-@ionicon-var-social-css3: "\f4df";
-@ionicon-var-social-css3-outline: "\f4de";
-@ionicon-var-social-designernews: "\f22b";
-@ionicon-var-social-designernews-outline: "\f22a";
-@ionicon-var-social-dribbble: "\f22d";
-@ionicon-var-social-dribbble-outline: "\f22c";
-@ionicon-var-social-dropbox: "\f22f";
-@ionicon-var-social-dropbox-outline: "\f22e";
-@ionicon-var-social-euro: "\f4e1";
-@ionicon-var-social-euro-outline: "\f4e0";
-@ionicon-var-social-facebook: "\f231";
-@ionicon-var-social-facebook-outline: "\f230";
-@ionicon-var-social-foursquare: "\f34d";
-@ionicon-var-social-foursquare-outline: "\f34c";
-@ionicon-var-social-freebsd-devil: "\f2c4";
-@ionicon-var-social-github: "\f233";
-@ionicon-var-social-github-outline: "\f232";
-@ionicon-var-social-google: "\f34f";
-@ionicon-var-social-google-outline: "\f34e";
-@ionicon-var-social-googleplus: "\f235";
-@ionicon-var-social-googleplus-outline: "\f234";
-@ionicon-var-social-hackernews: "\f237";
-@ionicon-var-social-hackernews-outline: "\f236";
-@ionicon-var-social-html5: "\f4e3";
-@ionicon-var-social-html5-outline: "\f4e2";
-@ionicon-var-social-instagram: "\f351";
-@ionicon-var-social-instagram-outline: "\f350";
-@ionicon-var-social-javascript: "\f4e5";
-@ionicon-var-social-javascript-outline: "\f4e4";
-@ionicon-var-social-linkedin: "\f239";
-@ionicon-var-social-linkedin-outline: "\f238";
-@ionicon-var-social-markdown: "\f4e6";
-@ionicon-var-social-nodejs: "\f4e7";
-@ionicon-var-social-octocat: "\f4e8";
-@ionicon-var-social-pinterest: "\f2b1";
-@ionicon-var-social-pinterest-outline: "\f2b0";
-@ionicon-var-social-python: "\f4e9";
-@ionicon-var-social-reddit: "\f23b";
-@ionicon-var-social-reddit-outline: "\f23a";
-@ionicon-var-social-rss: "\f23d";
-@ionicon-var-social-rss-outline: "\f23c";
-@ionicon-var-social-sass: "\f4ea";
-@ionicon-var-social-skype: "\f23f";
-@ionicon-var-social-skype-outline: "\f23e";
-@ionicon-var-social-snapchat: "\f4ec";
-@ionicon-var-social-snapchat-outline: "\f4eb";
-@ionicon-var-social-tumblr: "\f241";
-@ionicon-var-social-tumblr-outline: "\f240";
-@ionicon-var-social-tux: "\f2c5";
-@ionicon-var-social-twitch: "\f4ee";
-@ionicon-var-social-twitch-outline: "\f4ed";
-@ionicon-var-social-twitter: "\f243";
-@ionicon-var-social-twitter-outline: "\f242";
-@ionicon-var-social-usd: "\f353";
-@ionicon-var-social-usd-outline: "\f352";
-@ionicon-var-social-vimeo: "\f245";
-@ionicon-var-social-vimeo-outline: "\f244";
-@ionicon-var-social-whatsapp: "\f4f0";
-@ionicon-var-social-whatsapp-outline: "\f4ef";
-@ionicon-var-social-windows: "\f247";
-@ionicon-var-social-windows-outline: "\f246";
-@ionicon-var-social-wordpress: "\f249";
-@ionicon-var-social-wordpress-outline: "\f248";
-@ionicon-var-social-yahoo: "\f24b";
-@ionicon-var-social-yahoo-outline: "\f24a";
-@ionicon-var-social-yen: "\f4f2";
-@ionicon-var-social-yen-outline: "\f4f1";
-@ionicon-var-social-youtube: "\f24d";
-@ionicon-var-social-youtube-outline: "\f24c";
-@ionicon-var-soup-can: "\f4f4";
-@ionicon-var-soup-can-outline: "\f4f3";
-@ionicon-var-speakerphone: "\f2b2";
-@ionicon-var-speedometer: "\f2b3";
-@ionicon-var-spoon: "\f2b4";
-@ionicon-var-star: "\f24e";
-@ionicon-var-stats-bars: "\f2b5";
-@ionicon-var-steam: "\f30b";
-@ionicon-var-stop: "\f24f";
-@ionicon-var-thermometer: "\f2b6";
-@ionicon-var-thumbsdown: "\f250";
-@ionicon-var-thumbsup: "\f251";
-@ionicon-var-toggle: "\f355";
-@ionicon-var-toggle-filled: "\f354";
-@ionicon-var-transgender: "\f4f5";
-@ionicon-var-trash-a: "\f252";
-@ionicon-var-trash-b: "\f253";
-@ionicon-var-trophy: "\f356";
-@ionicon-var-tshirt: "\f4f7";
-@ionicon-var-tshirt-outline: "\f4f6";
-@ionicon-var-umbrella: "\f2b7";
-@ionicon-var-university: "\f357";
-@ionicon-var-unlocked: "\f254";
-@ionicon-var-upload: "\f255";
-@ionicon-var-usb: "\f2b8";
-@ionicon-var-videocamera: "\f256";
-@ionicon-var-volume-high: "\f257";
-@ionicon-var-volume-low: "\f258";
-@ionicon-var-volume-medium: "\f259";
-@ionicon-var-volume-mute: "\f25a";
-@ionicon-var-wand: "\f358";
-@ionicon-var-waterdrop: "\f25b";
-@ionicon-var-wifi: "\f25c";
-@ionicon-var-wineglass: "\f2b9";
-@ionicon-var-woman: "\f25d";
-@ionicon-var-wrench: "\f2ba";
-@ionicon-var-xbox: "\f30c"; \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/ionicons.less b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/ionicons.less
deleted file mode 100644
index 163b80e7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/less/ionicons.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import "_ionicons-variables";
-@import "_ionicons-font";
-@import "_ionicons-icons";
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert-circled.png
deleted file mode 100644
index 7cdd286a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert.png
deleted file mode 100644
index a0c06feb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/alert.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add-contact.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add-contact.png
deleted file mode 100644
index 7dea968f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add-contact.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add.png
deleted file mode 100644
index 03838f73..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-alarm.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-alarm.png
deleted file mode 100644
index bc3f06f3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-alarm.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-archive.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-archive.png
deleted file mode 100644
index ef651170..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-archive.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-back.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-back.png
deleted file mode 100644
index 19de4b02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-back.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-left.png
deleted file mode 100644
index 4e5ef0c9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-right.png
deleted file mode 100644
index ba22a1a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-down-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-forward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-forward.png
deleted file mode 100644
index b85834e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-forward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-left.png
deleted file mode 100644
index eb93ab54..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-right.png
deleted file mode 100644
index 0f105d77..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-arrow-up-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-battery.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-battery.png
deleted file mode 100644
index ddeaa1e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-battery.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-book.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-book.png
deleted file mode 100644
index 4764f96a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-book.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-calendar.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-calendar.png
deleted file mode 100644
index 547edc56..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-calendar.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-call.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-call.png
deleted file mode 100644
index 1d514da3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-call.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-camera.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-camera.png
deleted file mode 100644
index e3e8227c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-camera.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-chat.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-chat.png
deleted file mode 100644
index 8b7d7b95..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-chat.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-checkmark.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-checkmark.png
deleted file mode 100644
index bec7334c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-checkmark.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-clock.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-clock.png
deleted file mode 100644
index 44976052..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-clock.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-close.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-close.png
deleted file mode 100644
index f8a96b2a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-close.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contact.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contact.png
deleted file mode 100644
index fa8c8fa2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contact.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contacts.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contacts.png
deleted file mode 100644
index b06e4f4d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-contacts.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-data.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-data.png
deleted file mode 100644
index 8fcf7c4f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-data.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-developer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-developer.png
deleted file mode 100644
index 294ffe28..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-developer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-display.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-display.png
deleted file mode 100644
index ff0893d1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-display.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-download.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-download.png
deleted file mode 100644
index 3b156cfe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-download.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-drawer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-drawer.png
deleted file mode 100644
index 7b0c8b95..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-drawer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-dropdown.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-dropdown.png
deleted file mode 100644
index e4078816..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-dropdown.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-earth.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-earth.png
deleted file mode 100644
index 1f392124..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-earth.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-folder.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-folder.png
deleted file mode 100644
index 6c05cd4e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-folder.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-forums.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-forums.png
deleted file mode 100644
index 766b84d9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-forums.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-friends.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-friends.png
deleted file mode 100644
index 2e4e4e31..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-friends.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-hand.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-hand.png
deleted file mode 100644
index 5ebb0c52..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-hand.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-image.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-image.png
deleted file mode 100644
index d3b1af9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-image.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-inbox.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-inbox.png
deleted file mode 100644
index 1ca66de4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-inbox.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-information.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-information.png
deleted file mode 100644
index 9d9c923b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-information.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-keypad.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-keypad.png
deleted file mode 100644
index cd22f55a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-keypad.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-lightbulb.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-lightbulb.png
deleted file mode 100644
index 963b2445..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-lightbulb.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-locate.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-locate.png
deleted file mode 100644
index 5288a280..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-locate.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-location.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-location.png
deleted file mode 100644
index 05cc5b62..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-location.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mail.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mail.png
deleted file mode 100644
index 894b1216..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mail.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-microphone.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-microphone.png
deleted file mode 100644
index b99bf614..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-microphone.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mixer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mixer.png
deleted file mode 100644
index 5b910d5a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-mixer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-more.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-more.png
deleted file mode 100644
index a3ac53af..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-more.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-note.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-note.png
deleted file mode 100644
index 75643c53..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-note.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-playstore.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-playstore.png
deleted file mode 100644
index 9202fc61..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-playstore.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-printer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-printer.png
deleted file mode 100644
index a653818b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-printer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-promotion.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-promotion.png
deleted file mode 100644
index b65d1e8a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-promotion.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-reminder.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-reminder.png
deleted file mode 100644
index 41aadaa0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-reminder.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-remove.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-remove.png
deleted file mode 100644
index 467d7763..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-remove.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-search.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-search.png
deleted file mode 100644
index 148264d8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-search.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-send.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-send.png
deleted file mode 100644
index 3c668db0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-send.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-settings.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-settings.png
deleted file mode 100644
index 0090ed8d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-settings.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-share.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-share.png
deleted file mode 100644
index 3f7773c4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-share.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social-user.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social-user.png
deleted file mode 100644
index db31a6b4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social-user.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social.png
deleted file mode 100644
index 4dd3c374..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-social.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-sort.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-sort.png
deleted file mode 100644
index cb68046b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-sort.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stair-drawer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stair-drawer.png
deleted file mode 100644
index 8b339ea2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stair-drawer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-star.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-star.png
deleted file mode 100644
index aee429c2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-star.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stopwatch.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stopwatch.png
deleted file mode 100644
index ca404d97..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-stopwatch.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-storage.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-storage.png
deleted file mode 100644
index af2db373..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-storage.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-back.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-back.png
deleted file mode 100644
index a7b22bf8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-back.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-home.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-home.png
deleted file mode 100644
index 54fa3237..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-home.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-windows.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-windows.png
deleted file mode 100644
index 4ea950c7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-system-windows.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-timer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-timer.png
deleted file mode 100644
index 6584dc79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-timer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-trash.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-trash.png
deleted file mode 100644
index d8434981..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-trash.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-user-menu.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-user-menu.png
deleted file mode 100644
index 8ddb33a7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-user-menu.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-volume.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-volume.png
deleted file mode 100644
index 8faa6040..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-volume.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-wifi.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-wifi.png
deleted file mode 100644
index f9a9a1f3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/android-wifi.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/aperture.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/aperture.png
deleted file mode 100644
index cb0f5482..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/aperture.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/archive.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/archive.png
deleted file mode 100644
index 7e52197b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/archive.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-a.png
deleted file mode 100644
index c6c25131..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-b.png
deleted file mode 100644
index da3041f5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-c.png
deleted file mode 100644
index 3643857b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-down-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-expand.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-expand.png
deleted file mode 100644
index 4db52ab6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-expand.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-left.png
deleted file mode 100644
index 060d13c6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-right.png
deleted file mode 100644
index 346f70d1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-down-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-left.png
deleted file mode 100644
index b0247c3a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-right.png
deleted file mode 100644
index d7dbb221..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-graph-up-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-a.png
deleted file mode 100644
index d56a7c9b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-b.png
deleted file mode 100644
index fdb927c2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-c.png
deleted file mode 100644
index c75bfc0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-left-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-move.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-move.png
deleted file mode 100644
index 6c2902a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-move.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-resize.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-resize.png
deleted file mode 100644
index 1aabbfff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-resize.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-left.png
deleted file mode 100644
index ad1d02ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-right.png
deleted file mode 100644
index 8e37cc55..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-return-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-a.png
deleted file mode 100644
index d6dacc1c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-b.png
deleted file mode 100644
index 00e90696..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-c.png
deleted file mode 100644
index dfb3242c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-right-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-shrink.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-shrink.png
deleted file mode 100644
index e1de18d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-shrink.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-swap.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-swap.png
deleted file mode 100644
index cb7a2ece..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-swap.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-a.png
deleted file mode 100644
index 6d128915..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-b.png
deleted file mode 100644
index a2b84ac5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-c.png
deleted file mode 100644
index 8e0ccc7e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/arrow-up-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/asterisk.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/asterisk.png
deleted file mode 100644
index 7cb3636e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/asterisk.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/at.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/at.png
deleted file mode 100644
index ae4bbe3e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/at.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bag.png
deleted file mode 100644
index 26128312..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-charging.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-charging.png
deleted file mode 100644
index c91d30e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-charging.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-empty.png
deleted file mode 100644
index 72d01979..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-full.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-full.png
deleted file mode 100644
index eb5bbd8b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-full.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-half.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-half.png
deleted file mode 100644
index 28e9073b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-half.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-low.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-low.png
deleted file mode 100644
index 12c507a1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/battery-low.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beaker.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beaker.png
deleted file mode 100644
index edfb857c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beaker.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beer.png
deleted file mode 100644
index caa7b8e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/beer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bluetooth.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bluetooth.png
deleted file mode 100644
index 139d5429..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bonfire.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bonfire.png
deleted file mode 100644
index 5dcf8fa7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bonfire.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bookmark.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bookmark.png
deleted file mode 100644
index 35af5d79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bookmark.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/briefcase.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/briefcase.png
deleted file mode 100644
index 439c2125..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/briefcase.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bug.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bug.png
deleted file mode 100644
index 8dc4d27a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/bug.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calculator.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calculator.png
deleted file mode 100644
index 8c425e51..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calculator.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calendar.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calendar.png
deleted file mode 100644
index 2700f1bb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/calendar.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/camera.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/camera.png
deleted file mode 100644
index 522071f9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/camera.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/card.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/card.png
deleted file mode 100644
index 536ed7e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/card.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cash.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cash.png
deleted file mode 100644
index 2c43f2a9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cash.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox-working.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox-working.png
deleted file mode 100644
index c54cba42..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox-working.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox.png
deleted file mode 100644
index 9d80dd80..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbox.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatboxes.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatboxes.png
deleted file mode 100644
index 4cf816ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatboxes.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble-working.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble-working.png
deleted file mode 100644
index 5b973d75..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble-working.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble.png
deleted file mode 100644
index ba0ebed0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubble.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubbles.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubbles.png
deleted file mode 100644
index 4d0c4c0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chatbubbles.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-circled.png
deleted file mode 100644
index ca761f9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-round.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-round.png
deleted file mode 100644
index bf6361e7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark-round.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark.png
deleted file mode 100644
index 34d15d39..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/checkmark.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-down.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-down.png
deleted file mode 100644
index dec11dc9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-down.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-left.png
deleted file mode 100644
index 93547200..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-right.png
deleted file mode 100644
index 2a5caff5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-up.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-up.png
deleted file mode 100644
index a047b094..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/chevron-up.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clipboard.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clipboard.png
deleted file mode 100644
index ae22e994..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clipboard.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clock.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clock.png
deleted file mode 100644
index 508d32af..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/clock.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-circled.png
deleted file mode 100644
index e764171a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-round.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-round.png
deleted file mode 100644
index 81aa3670..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close-round.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close.png
deleted file mode 100644
index b8a65df7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/close.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/closed-captioning.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/closed-captioning.png
deleted file mode 100644
index 8a8c3030..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/closed-captioning.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cloud.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cloud.png
deleted file mode 100644
index e693d348..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cloud.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-download.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-download.png
deleted file mode 100644
index 43f45359..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-download.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-working.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-working.png
deleted file mode 100644
index b462cb3e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code-working.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code.png
deleted file mode 100644
index 5633483b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/code.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/coffee.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/coffee.png
deleted file mode 100644
index 578375bc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/coffee.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compass.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compass.png
deleted file mode 100644
index dcfa3e07..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compass.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compose.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compose.png
deleted file mode 100644
index f9c6ecae..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/compose.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/connection-bars.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/connection-bars.png
deleted file mode 100644
index 6ab10412..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/connection-bars.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/contrast.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/contrast.png
deleted file mode 100644
index 6d375648..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/contrast.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cube.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cube.png
deleted file mode 100644
index a9164ca4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/cube.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/disc.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/disc.png
deleted file mode 100644
index 3d2b9b97..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/disc.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document-text.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document-text.png
deleted file mode 100644
index 02318c2b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document-text.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document.png
deleted file mode 100644
index 0f37ec2d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/document.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/drag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/drag.png
deleted file mode 100644
index 3a94a3bc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/drag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/earth.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/earth.png
deleted file mode 100644
index 87a4057b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/earth.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/edit.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/edit.png
deleted file mode 100644
index 9f32a2a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/edit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/egg.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/egg.png
deleted file mode 100644
index 8710c887..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/egg.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eject.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eject.png
deleted file mode 100644
index 063c2f86..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eject.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/email.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/email.png
deleted file mode 100644
index 972cd315..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/email.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye-disabled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye-disabled.png
deleted file mode 100644
index d973e415..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye-disabled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye.png
deleted file mode 100644
index 13be6456..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/eye.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/female.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/female.png
deleted file mode 100644
index 53f972fa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/female.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/filing.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/filing.png
deleted file mode 100644
index 7678ba72..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/filing.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/film-marker.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/film-marker.png
deleted file mode 100644
index ebaf3e62..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/film-marker.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fireball.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fireball.png
deleted file mode 100644
index 8cc28779..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fireball.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flag.png
deleted file mode 100644
index 28aa3304..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flame.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flame.png
deleted file mode 100644
index 6efca560..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flame.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash-off.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash-off.png
deleted file mode 100644
index 878e0415..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash-off.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash.png
deleted file mode 100644
index 1cef7acf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flash.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flask.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flask.png
deleted file mode 100644
index 2f93ab69..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/flask.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/folder.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/folder.png
deleted file mode 100644
index 35ffec5d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/folder.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork-repo.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork-repo.png
deleted file mode 100644
index 9b954522..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork-repo.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork.png
deleted file mode 100644
index 4e966221..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/fork.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/forward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/forward.png
deleted file mode 100644
index 9a583b36..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/forward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/funnel.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/funnel.png
deleted file mode 100644
index bdc73be3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/funnel.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-a.png
deleted file mode 100644
index cca34443..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-b.png
deleted file mode 100644
index 54cd8810..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/game-controller-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-a.png
deleted file mode 100644
index 1e3d229a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-b.png
deleted file mode 100644
index d7fb8e0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/gear-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/grid.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/grid.png
deleted file mode 100644
index 05962156..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/grid.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/hammer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/hammer.png
deleted file mode 100644
index 1bd23c2f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/hammer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/happy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/happy.png
deleted file mode 100644
index 42f4b719..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/happy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/headphone.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/headphone.png
deleted file mode 100644
index fbf54fcd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/headphone.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart-broken.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart-broken.png
deleted file mode 100644
index 24abdfe1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart-broken.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart.png
deleted file mode 100644
index 8a444fb7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/heart.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-buoy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-buoy.png
deleted file mode 100644
index eef82ae3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-buoy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-circled.png
deleted file mode 100644
index 5fb5e853..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help.png
deleted file mode 100644
index 8b9179db..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/help.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/home.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/home.png
deleted file mode 100644
index ad02c46a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/home.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icecream.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icecream.png
deleted file mode 100644
index da3ae9d3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icecream.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus-outline.png
deleted file mode 100644
index 9eeb43ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus.png
deleted file mode 100644
index e79ca447..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/icon-social-google-plus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/image.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/image.png
deleted file mode 100644
index eb11e5fa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/image.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/images.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/images.png
deleted file mode 100644
index 21dcd601..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/images.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information-circled.png
deleted file mode 100644
index a85ad30b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information.png
deleted file mode 100644
index 8e03190a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/information.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ionic.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ionic.png
deleted file mode 100644
index 95d70760..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ionic.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm-outline.png
deleted file mode 100644
index 2809a5b9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm.png
deleted file mode 100644
index 6c7415f9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-alarm.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums-outline.png
deleted file mode 100644
index 41b5a845..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums.png
deleted file mode 100644
index bdc76725..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-albums.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball-outline.png
deleted file mode 100644
index 14c625d8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball.png
deleted file mode 100644
index 81834cf3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-americanfootball.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics-outline.png
deleted file mode 100644
index 38534a19..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics.png
deleted file mode 100644
index ffcd2817..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-analytics.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-back.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-back.png
deleted file mode 100644
index 4051ab2c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-back.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-down.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-down.png
deleted file mode 100644
index 093eb0b0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-down.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-forward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-forward.png
deleted file mode 100644
index aedf67a5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-forward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-left.png
deleted file mode 100644
index acc8354c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-right.png
deleted file mode 100644
index 6144fbd4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-down.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-down.png
deleted file mode 100644
index 8a5c17cb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-down.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-left.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-left.png
deleted file mode 100644
index 4f8bf90f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-left.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-right.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-right.png
deleted file mode 100644
index b97e69c9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-right.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-up.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-up.png
deleted file mode 100644
index 61bb13a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-thin-up.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-up.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-up.png
deleted file mode 100644
index b4733f2e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-arrow-up.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at-outline.png
deleted file mode 100644
index 22346e27..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at.png
deleted file mode 100644
index be38570c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-at.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode-outline.png
deleted file mode 100644
index 95c6c04e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode.png
deleted file mode 100644
index 5c7d72f0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-barcode.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball-outline.png
deleted file mode 100644
index 6bc6a21d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball.png
deleted file mode 100644
index b83d5366..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-baseball.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball-outline.png
deleted file mode 100644
index a1999bc5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball.png
deleted file mode 100644
index 3c8af3d0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-basketball.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell-outline.png
deleted file mode 100644
index f84935b9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell.png
deleted file mode 100644
index d96c352c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bell.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt-outline.png
deleted file mode 100644
index bdf98cfd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt.png
deleted file mode 100644
index 723a27d7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bolt.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks-outline.png
deleted file mode 100644
index d9701947..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks.png
deleted file mode 100644
index a53199af..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-bookmarks.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box-outline.png
deleted file mode 100644
index b45b8e91..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box.png
deleted file mode 100644
index 5e2ed571..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-box.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase-outline.png
deleted file mode 100644
index f224f4ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase.png
deleted file mode 100644
index b6e581d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-briefcase.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers-outline.png
deleted file mode 100644
index 9c0e68be..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers.png
deleted file mode 100644
index 4c527101..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-browsers.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator-outline.png
deleted file mode 100644
index 0492f78e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator.png
deleted file mode 100644
index ee55f2f0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calculator.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar-outline.png
deleted file mode 100644
index 593bfe44..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar.png
deleted file mode 100644
index bbc6f864..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-calendar.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera-outline.png
deleted file mode 100644
index f835f6e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera.png
deleted file mode 100644
index 59bdf3da..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-camera.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart-outline.png
deleted file mode 100644
index 24f9d675..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart.png
deleted file mode 100644
index 2e7cec12..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cart.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes-outline.png
deleted file mode 100644
index 5fca4b96..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes.png
deleted file mode 100644
index d87b7efb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatboxes.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble-outline.png
deleted file mode 100644
index 447f9cda..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble.png
deleted file mode 100644
index 33f3b2d3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-chatbubble.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-empty.png
deleted file mode 100644
index f3d5c0c0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-outline.png
deleted file mode 100644
index 1601cfec..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark.png
deleted file mode 100644
index 23e7de37..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-checkmark.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-filled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-filled.png
deleted file mode 100644
index ce8b1033..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-filled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-outline.png
deleted file mode 100644
index c2fcf18d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-circle-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock-outline.png
deleted file mode 100644
index 61892f08..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock.png
deleted file mode 100644
index fc174560..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-clock.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-empty.png
deleted file mode 100644
index e64d614e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-outline.png
deleted file mode 100644
index de8b8467..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close.png
deleted file mode 100644
index 6465d425..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-close.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download-outline.png
deleted file mode 100644
index 02274e23..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download.png
deleted file mode 100644
index df81fd78..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-download.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-outline.png
deleted file mode 100644
index a2649227..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload-outline.png
deleted file mode 100644
index 905eb55f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload.png
deleted file mode 100644
index c3c80715..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud-upload.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud.png
deleted file mode 100644
index 318bc14a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloud.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night-outline.png
deleted file mode 100644
index c2612d70..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night.png
deleted file mode 100644
index 05b03d65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-night.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-outline.png
deleted file mode 100644
index 3a003181..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy.png
deleted file mode 100644
index 746c333c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cloudy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog-outline.png
deleted file mode 100644
index a137d1eb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog.png
deleted file mode 100644
index 30697710..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-cog.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose-outline.png
deleted file mode 100644
index 004ec82b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose.png
deleted file mode 100644
index 7b1072ab..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-compose.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact-outline.png
deleted file mode 100644
index ec8ce437..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact.png
deleted file mode 100644
index 5b4f6db8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-contact.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy-outline.png
deleted file mode 100644
index 90221899..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy.png
deleted file mode 100644
index 842aa205..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-copy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download-outline.png
deleted file mode 100644
index 7fbbaf5a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download.png
deleted file mode 100644
index 40a5a698..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-download.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-drag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-drag.png
deleted file mode 100644
index d71784be..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-drag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email-outline.png
deleted file mode 100644
index 0d4838e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email.png
deleted file mode 100644
index 5e92b0f2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-email.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-expand.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-expand.png
deleted file mode 100644
index d52bb235..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-expand.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye-outline.png
deleted file mode 100644
index 2c9dfc14..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye.png
deleted file mode 100644
index 1c111914..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-eye.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward-outline.png
deleted file mode 100644
index fc06c60b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward.png
deleted file mode 100644
index ce34f232..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-fastforward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing-outline.png
deleted file mode 100644
index 6c84c246..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing.png
deleted file mode 100644
index d01cfc0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-filing.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film-outline.png
deleted file mode 100644
index 750fe600..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film.png
deleted file mode 100644
index 4c28280a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-film.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag-outline.png
deleted file mode 100644
index 39c2ebeb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag.png
deleted file mode 100644
index eef93be9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-flag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder-outline.png
deleted file mode 100644
index 46746af2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder.png
deleted file mode 100644
index a2d93665..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-folder.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football-outline.png
deleted file mode 100644
index 426f6d3a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football.png
deleted file mode 100644
index e424b7f9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-football.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear-outline.png
deleted file mode 100644
index 5c82237a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear.png
deleted file mode 100644
index 784a0e32..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-gear.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses-outline.png
deleted file mode 100644
index 1f2cfa79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses.png
deleted file mode 100644
index f0b3074b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-glasses.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart-outline.png
deleted file mode 100644
index c3a25335..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart.png
deleted file mode 100644
index b3dbf4e4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-heart.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-empty.png
deleted file mode 100644
index 5690a69d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-outline.png
deleted file mode 100644
index 432abf85..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help.png
deleted file mode 100644
index b5d9a448..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-help.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home-outline.png
deleted file mode 100644
index 56b27f95..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home.png
deleted file mode 100644
index 8061aa82..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-home.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite-outline.png
deleted file mode 100644
index 8c251df0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite.png
deleted file mode 100644
index bd2eec56..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-infinite.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-empty.png
deleted file mode 100644
index 70af5a5a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-outline.png
deleted file mode 100644
index a1cb7267..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information.png
deleted file mode 100644
index 43f3e2d7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-information.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-ionic-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-ionic-outline.png
deleted file mode 100644
index cea7341f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-ionic-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad-outline.png
deleted file mode 100644
index 4bc381ca..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad.png
deleted file mode 100644
index af76a7b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-keypad.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb-outline.png
deleted file mode 100644
index e7a13c8f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb.png
deleted file mode 100644
index 3a3e8bf3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-lightbulb.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location-outline.png
deleted file mode 100644
index 727ff055..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location.png
deleted file mode 100644
index 01260396..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-location.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked-outline.png
deleted file mode 100644
index e688f73c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked.png
deleted file mode 100644
index ebeb2cc3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-locked.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop-strong.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop-strong.png
deleted file mode 100644
index 0fa94175..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop-strong.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop.png
deleted file mode 100644
index 416c23df..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-loop.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit-outline.png
deleted file mode 100644
index 255d84b8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit.png
deleted file mode 100644
index 56b038e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-medkit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-off.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-off.png
deleted file mode 100644
index 07685a65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-off.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-outline.png
deleted file mode 100644
index c2520030..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic.png
deleted file mode 100644
index 78708232..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-mic.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-empty.png
deleted file mode 100644
index 74f32838..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-outline.png
deleted file mode 100644
index d6a2d87f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus.png
deleted file mode 100644
index a5f67182..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-minus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor-outline.png
deleted file mode 100644
index 4762d1d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor.png
deleted file mode 100644
index 0e2f28e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-monitor.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon-outline.png
deleted file mode 100644
index 0bbd6d62..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon.png
deleted file mode 100644
index 5e1e1b04..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-moon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more-outline.png
deleted file mode 100644
index 8d3c9bf7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more.png
deleted file mode 100644
index d681b001..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-more.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-note.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-note.png
deleted file mode 100644
index 24186f23..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-note.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-notes.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-notes.png
deleted file mode 100644
index 51470ab8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-musical-notes.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate-outline.png
deleted file mode 100644
index f3b40b1c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate.png
deleted file mode 100644
index 8df442a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-navigate.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper-outline.png
deleted file mode 100644
index 6e08ebed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper.png
deleted file mode 100644
index a5c0762c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paper.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane-outline.png
deleted file mode 100644
index b4c73c1a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane.png
deleted file mode 100644
index 6b1b858f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paperplane.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny-outline.png
deleted file mode 100644
index 2efcc2cd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny.png
deleted file mode 100644
index 13a269ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-partlysunny.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause-outline.png
deleted file mode 100644
index e20b3abe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause.png
deleted file mode 100644
index 317a9854..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pause.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw-outline.png
deleted file mode 100644
index f5736efe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw.png
deleted file mode 100644
index bfd64fe6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-paw.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people-outline.png
deleted file mode 100644
index 58178653..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people.png
deleted file mode 100644
index 053e7705..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-people.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person-outline.png
deleted file mode 100644
index a9c4a0ac..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person.png
deleted file mode 100644
index baa6cf6b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-person.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd-outline.png
deleted file mode 100644
index 679b6e47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd.png
deleted file mode 100644
index 354e6355..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-personadd.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos-outline.png
deleted file mode 100644
index a6a872ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos.png
deleted file mode 100644
index 1eb0f7ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-photos.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie-outline.png
deleted file mode 100644
index 8470a2f9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie.png
deleted file mode 100644
index f7ab6890..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pie.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play-outline.png
deleted file mode 100644
index a484b4e4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play.png
deleted file mode 100644
index b6110aab..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-play.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-empty.png
deleted file mode 100644
index 92f40304..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-outline.png
deleted file mode 100644
index d6c97ce5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus.png
deleted file mode 100644
index 2eaa563c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-plus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag-outline.png
deleted file mode 100644
index 5184cc79..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag.png
deleted file mode 100644
index dbcbc688..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags-outline.png
deleted file mode 100644
index 380d9682..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags.png
deleted file mode 100644
index 0942729b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pricetags.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer-outline.png
deleted file mode 100644
index c759d046..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer.png
deleted file mode 100644
index 79847d9d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-printer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse-strong.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse-strong.png
deleted file mode 100644
index 350b165d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse-strong.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse.png
deleted file mode 100644
index c5ffc503..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-pulse.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy-outline.png
deleted file mode 100644
index 7dc31109..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy.png
deleted file mode 100644
index cf0e12e7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rainy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording-outline.png
deleted file mode 100644
index 4b647f55..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording.png
deleted file mode 100644
index dfe84b18..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-recording.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo-outline.png
deleted file mode 100644
index 235373ee..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo.png
deleted file mode 100644
index c003ff3d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-redo.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-empty.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-empty.png
deleted file mode 100644
index 93df8b16..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-empty.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-outline.png
deleted file mode 100644
index f815ba7d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh.png
deleted file mode 100644
index 3e98749a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-refresh.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reload.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reload.png
deleted file mode 100644
index a109314b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reload.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera-outline.png
deleted file mode 100644
index f801e3a2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera.png
deleted file mode 100644
index b222f5c9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-reverse-camera.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind-outline.png
deleted file mode 100644
index cf4181dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind.png
deleted file mode 100644
index 05cd9463..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-rewind.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search-strong.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search-strong.png
deleted file mode 100644
index d59cc8f8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search-strong.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search.png
deleted file mode 100644
index 3b97bca8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-search.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings-strong.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings-strong.png
deleted file mode 100644
index 4f3e9487..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings-strong.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings.png
deleted file mode 100644
index 588e3492..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-settings.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-shrink.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-shrink.png
deleted file mode 100644
index 8ccd4d3f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-shrink.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward-outline.png
deleted file mode 100644
index 7597d711..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward.png
deleted file mode 100644
index 0deff517..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipbackward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward-outline.png
deleted file mode 100644
index 96e1aef8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward.png
deleted file mode 100644
index 95c308a6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-skipforward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-snowy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-snowy.png
deleted file mode 100644
index 311b8bd2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-snowy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer-outline.png
deleted file mode 100644
index a7120de6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer.png
deleted file mode 100644
index bc5a2a20..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-speedometer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-half.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-half.png
deleted file mode 100644
index 346cc8fa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-half.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-outline.png
deleted file mode 100644
index 6d9cd2a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star.png
deleted file mode 100644
index 4a28feed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-star.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch-outline.png
deleted file mode 100644
index 8660b246..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch.png
deleted file mode 100644
index 0bd2f224..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-stopwatch.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny-outline.png
deleted file mode 100644
index 8c1943df..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny.png
deleted file mode 100644
index 95f8ba63..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-sunny.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone-outline.png
deleted file mode 100644
index d3a1d989..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone.png
deleted file mode 100644
index 983f2c28..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-telephone.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball-outline.png
deleted file mode 100644
index de9c07a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball.png
deleted file mode 100644
index 42906a47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-tennisball.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm-outline.png
deleted file mode 100644
index 2a8d9db6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm.png
deleted file mode 100644
index 315acf05..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-thunderstorm.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time-outline.png
deleted file mode 100644
index 6234a758..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time.png
deleted file mode 100644
index 1dc05273..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-time.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer-outline.png
deleted file mode 100644
index 64be9827..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer.png
deleted file mode 100644
index e916b521..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-timer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle-outline.png
deleted file mode 100644
index 1202cfe7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle.png
deleted file mode 100644
index a7b91c83..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-toggle.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash-outline.png
deleted file mode 100644
index ce2dc7a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash.png
deleted file mode 100644
index 58c4346f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-trash.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo-outline.png
deleted file mode 100644
index db79f3d7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo.png
deleted file mode 100644
index efaf7c0d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-undo.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked-outline.png
deleted file mode 100644
index e66c3861..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked.png
deleted file mode 100644
index fb97492f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-unlocked.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload-outline.png
deleted file mode 100644
index 09cc277d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload.png
deleted file mode 100644
index b37773fc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-upload.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam-outline.png
deleted file mode 100644
index 0bf6d154..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam.png
deleted file mode 100644
index 680a8df4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-videocam.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-high.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-high.png
deleted file mode 100644
index 0568110c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-high.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-low.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-low.png
deleted file mode 100644
index 34a294e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-volume-low.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass-outline.png
deleted file mode 100644
index 22b9fc51..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass.png
deleted file mode 100644
index 4dbd6202..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-wineglass.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world-outline.png
deleted file mode 100644
index d14a6505..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world.png
deleted file mode 100644
index 4491e61f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ios7-world.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipad.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipad.png
deleted file mode 100644
index 85e09151..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipad.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/iphone.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/iphone.png
deleted file mode 100644
index 7f538baa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/iphone.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipod.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipod.png
deleted file mode 100644
index cf3c3aeb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ipod.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/jet.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/jet.png
deleted file mode 100644
index 166e1951..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/jet.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/key.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/key.png
deleted file mode 100644
index 3ae67379..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/key.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/knife.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/knife.png
deleted file mode 100644
index 9f13a0ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/knife.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/laptop.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/laptop.png
deleted file mode 100644
index a8ec9630..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/laptop.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/leaf.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/leaf.png
deleted file mode 100644
index 3bf3801c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/leaf.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/levels.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/levels.png
deleted file mode 100644
index 79d4b3e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/levels.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/lightbulb.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/lightbulb.png
deleted file mode 100644
index d103bfe6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/lightbulb.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/link.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/link.png
deleted file mode 100644
index 34459387..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/link.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-a.png
deleted file mode 100644
index f5cda196..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-b.png
deleted file mode 100644
index 7931879c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-c.png
deleted file mode 100644
index 39a59963..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-d.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-d.png
deleted file mode 100644
index 8d96f0de..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/load-d.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/location.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/location.png
deleted file mode 100644
index 5acf20aa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/location.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/locked.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/locked.png
deleted file mode 100644
index e78f8158..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/locked.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-in.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-in.png
deleted file mode 100644
index 592e30cb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-in.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-out.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-out.png
deleted file mode 100644
index 1d41c22e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/log-out.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/loop.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/loop.png
deleted file mode 100644
index d30a7a9f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/loop.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/magnet.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/magnet.png
deleted file mode 100644
index 8925becd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/magnet.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/male.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/male.png
deleted file mode 100644
index ea0eab33..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/male.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/man.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/man.png
deleted file mode 100644
index f0b46451..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/man.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/map.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/map.png
deleted file mode 100644
index 2aff1761..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/map.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/medkit.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/medkit.png
deleted file mode 100644
index b03b2efa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/medkit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/merge.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/merge.png
deleted file mode 100644
index 318a59fc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/merge.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-a.png
deleted file mode 100644
index 1034de7b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-b.png
deleted file mode 100644
index ea04074e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-c.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-c.png
deleted file mode 100644
index c545bfd4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mic-c.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-circled.png
deleted file mode 100644
index fd9e8400..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-round.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-round.png
deleted file mode 100644
index 88e67810..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus-round.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus.png
deleted file mode 100644
index 67337156..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/minus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/model-s.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/model-s.png
deleted file mode 100644
index ed021952..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/model-s.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/monitor.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/monitor.png
deleted file mode 100644
index 6a77e997..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/monitor.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/more.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/more.png
deleted file mode 100644
index dd48f034..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/more.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mouse.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mouse.png
deleted file mode 100644
index 55e7a47d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/mouse.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/music-note.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/music-note.png
deleted file mode 100644
index d65191a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/music-note.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon-round.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon-round.png
deleted file mode 100644
index 82c3d404..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon-round.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon.png
deleted file mode 100644
index 2696c4dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navicon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navigate.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navigate.png
deleted file mode 100644
index 8a3b385a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/navigate.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/network.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/network.png
deleted file mode 100644
index 7cbc5cdd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/network.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/no-smoking.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/no-smoking.png
deleted file mode 100644
index d13e35ec..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/no-smoking.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/nuclear.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/nuclear.png
deleted file mode 100644
index a2a1783e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/nuclear.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/outlet.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/outlet.png
deleted file mode 100644
index b3fc9057..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/outlet.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paper-airplane.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paper-airplane.png
deleted file mode 100644
index 76fa2e90..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paper-airplane.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paperclip.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paperclip.png
deleted file mode 100644
index f11b9095..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/paperclip.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pause.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pause.png
deleted file mode 100644
index ab8f58ac..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pause.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-add.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-add.png
deleted file mode 100644
index 07c07f1d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-stalker.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-stalker.png
deleted file mode 100644
index c097f820..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person-stalker.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person.png
deleted file mode 100644
index 2f01007a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/person.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pie-graph.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pie-graph.png
deleted file mode 100644
index 37d84198..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pie-graph.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pin.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pin.png
deleted file mode 100644
index 22c05077..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pin.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pinpoint.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pinpoint.png
deleted file mode 100644
index b2420fcf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pinpoint.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pizza.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pizza.png
deleted file mode 100644
index 41e9966f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pizza.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plane.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plane.png
deleted file mode 100644
index 2c12610a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plane.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/planet.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/planet.png
deleted file mode 100644
index 90374532..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/planet.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/play.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/play.png
deleted file mode 100644
index 5da06aa0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/play.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/playstation.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/playstation.png
deleted file mode 100644
index 70e00042..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/playstation.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-circled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-circled.png
deleted file mode 100644
index 203c3a97..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-circled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-round.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-round.png
deleted file mode 100644
index 8dee00d4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus-round.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus.png
deleted file mode 100644
index a76887a0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/plus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/podium.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/podium.png
deleted file mode 100644
index b34511be..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/podium.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pound.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pound.png
deleted file mode 100644
index 6d729a10..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pound.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/power.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/power.png
deleted file mode 100644
index f90d4234..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/power.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetag.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetag.png
deleted file mode 100644
index 05946eb5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetag.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetags.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetags.png
deleted file mode 100644
index b3cca2df..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pricetags.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/printer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/printer.png
deleted file mode 100644
index 96264b7d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/printer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pull-request.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pull-request.png
deleted file mode 100644
index f1e00b47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/pull-request.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/qr-scanner.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/qr-scanner.png
deleted file mode 100644
index 65eada55..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/qr-scanner.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/quote.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/quote.png
deleted file mode 100644
index ba43394f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/quote.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/radio-waves.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/radio-waves.png
deleted file mode 100644
index 1695cf04..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/radio-waves.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/record.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/record.png
deleted file mode 100644
index 06d6b508..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/record.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/refresh.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/refresh.png
deleted file mode 100644
index 35515efa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/refresh.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply-all.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply-all.png
deleted file mode 100644
index 68a1f070..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply-all.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply.png
deleted file mode 100644
index a6bd5aa1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/reply.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-a.png
deleted file mode 100644
index 16243e00..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-b.png
deleted file mode 100644
index d92ceac4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/ribbon-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/sad.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/sad.png
deleted file mode 100644
index f15f6d0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/sad.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/scissors.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/scissors.png
deleted file mode 100644
index 0dfeef2b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/scissors.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/search.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/search.png
deleted file mode 100644
index 4ec105d4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/search.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/settings.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/settings.png
deleted file mode 100644
index 88ad0b13..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/settings.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/share.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/share.png
deleted file mode 100644
index 35f9b3f2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/share.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/shuffle.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/shuffle.png
deleted file mode 100644
index d03aadff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/shuffle.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-backward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-backward.png
deleted file mode 100644
index 4b9b2bd6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-backward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-forward.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-forward.png
deleted file mode 100644
index 771fae7c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/skip-forward.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android-outline.png
deleted file mode 100644
index d5abc210..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android.png
deleted file mode 100644
index d7b7c425..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-android.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple-outline.png
deleted file mode 100644
index e6232292..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple.png
deleted file mode 100644
index 074e4e7a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-apple.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin-outline.png
deleted file mode 100644
index 7e429cce..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin.png
deleted file mode 100644
index d4311986..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-bitcoin.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer-outline.png
deleted file mode 100644
index a83d91a3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer.png
deleted file mode 100644
index ec962e66..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-buffer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews-outline.png
deleted file mode 100644
index 87799f54..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews.png
deleted file mode 100644
index 8a036dd1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-designernews.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble-outline.png
deleted file mode 100644
index f8c0ba5b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble.png
deleted file mode 100644
index f5d30bb2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dribbble.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox-outline.png
deleted file mode 100644
index f92b0569..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox.png
deleted file mode 100644
index 5507c5c4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-dropbox.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook-outline.png
deleted file mode 100644
index 293001aa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook.png
deleted file mode 100644
index 6c41f80c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-facebook.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare-outline.png
deleted file mode 100644
index 28766334..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare.png
deleted file mode 100644
index 0e671c69..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-foursquare.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-freebsd-devil.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-freebsd-devil.png
deleted file mode 100644
index 27008652..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-freebsd-devil.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github-outline.png
deleted file mode 100644
index 915f3bf0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github.png
deleted file mode 100644
index 87b4c754..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-github.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google-outline.png
deleted file mode 100644
index 08d50ba1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google.png
deleted file mode 100644
index b788fb9a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-google.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus-outline.png
deleted file mode 100644
index 9eeb43ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus.png
deleted file mode 100644
index e79ca447..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-googleplus.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews-outline.png
deleted file mode 100644
index 06f43197..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews.png
deleted file mode 100644
index 52902fe3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-hackernews.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram-outline.png
deleted file mode 100644
index bf75435b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram.png
deleted file mode 100644
index 76e1ab87..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-instagram.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin-outline.png
deleted file mode 100644
index 88d8169b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin.png
deleted file mode 100644
index 8e2eedf0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-linkedin.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest-outline.png
deleted file mode 100644
index 75321dcf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest.png
deleted file mode 100644
index 6bb578d5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-pinterest.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit-outline.png
deleted file mode 100644
index 1ffca7bb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit.png
deleted file mode 100644
index 2c96b336..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-reddit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss-outline.png
deleted file mode 100644
index 11c22757..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss.png
deleted file mode 100644
index 55fdf00f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-rss.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype-outline.png
deleted file mode 100644
index bc605c82..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype.png
deleted file mode 100644
index 60eb1a83..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-skype.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr-outline.png
deleted file mode 100644
index 1b3f4c03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr.png
deleted file mode 100644
index 79e3a2a9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tumblr.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tux.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tux.png
deleted file mode 100644
index 615e0ce9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-tux.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter-outline.png
deleted file mode 100644
index d279ae03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter.png
deleted file mode 100644
index a96d561e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-twitter.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd-outline.png
deleted file mode 100644
index ca5241d6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd.png
deleted file mode 100644
index 740f5bef..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-usd.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo-outline.png
deleted file mode 100644
index 50a61d16..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo.png
deleted file mode 100644
index ce7fbefa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-vimeo.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows-outline.png
deleted file mode 100644
index e0e98e4d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows.png
deleted file mode 100644
index 3b033a93..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-windows.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress-outline.png
deleted file mode 100644
index 76e9939e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress.png
deleted file mode 100644
index f1663108..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-wordpress.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo-outline.png
deleted file mode 100644
index defd58d8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo.png
deleted file mode 100644
index ea210fe8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-yahoo.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube-outline.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube-outline.png
deleted file mode 100644
index 7708d48b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube-outline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube.png
deleted file mode 100644
index b025720c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/social-youtube.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speakerphone.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speakerphone.png
deleted file mode 100644
index 7766a2b7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speakerphone.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speedometer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speedometer.png
deleted file mode 100644
index 29625aff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/speedometer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/spoon.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/spoon.png
deleted file mode 100644
index 98178e08..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/spoon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/star.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/star.png
deleted file mode 100644
index 7d877199..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/star.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stats-bars.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stats-bars.png
deleted file mode 100644
index 0a4134d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stats-bars.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/steam.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/steam.png
deleted file mode 100644
index 8ffa6843..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/steam.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stop.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stop.png
deleted file mode 100644
index dd58b88a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/stop.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thermometer.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thermometer.png
deleted file mode 100644
index 9ba62b09..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thermometer.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsdown.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsdown.png
deleted file mode 100644
index 8e8cc85f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsdown.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsup.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsup.png
deleted file mode 100644
index da425557..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/thumbsup.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle-filled.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle-filled.png
deleted file mode 100644
index caff1e93..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle-filled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle.png
deleted file mode 100644
index f8350b08..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/toggle.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-a.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-a.png
deleted file mode 100644
index f9660b6f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-a.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-b.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-b.png
deleted file mode 100644
index 7a81ffe4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trash-b.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trophy.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trophy.png
deleted file mode 100644
index f6406f8e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/trophy.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/umbrella.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/umbrella.png
deleted file mode 100644
index 6b1c5b4c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/umbrella.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/university.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/university.png
deleted file mode 100644
index 6e74e340..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/university.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/unlocked.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/unlocked.png
deleted file mode 100644
index 83c0d487..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/unlocked.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/upload.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/upload.png
deleted file mode 100644
index 0519cbf9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/upload.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/usb.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/usb.png
deleted file mode 100644
index 87857b46..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/usb.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/videocamera.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/videocamera.png
deleted file mode 100644
index 9f5c333f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/videocamera.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-high.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-high.png
deleted file mode 100644
index 3a2da41a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-high.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-low.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-low.png
deleted file mode 100644
index 0faf9d3b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-low.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-medium.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-medium.png
deleted file mode 100644
index b4e0d44d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-medium.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-mute.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-mute.png
deleted file mode 100644
index 722f7372..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/volume-mute.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wand.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wand.png
deleted file mode 100644
index 0dbe13cf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wand.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/waterdrop.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/waterdrop.png
deleted file mode 100644
index deaf4075..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/waterdrop.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wifi.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wifi.png
deleted file mode 100644
index 19bedd87..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wifi.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wineglass.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wineglass.png
deleted file mode 100644
index 881b6673..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wineglass.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/woman.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/woman.png
deleted file mode 100644
index 0cab2b5d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/woman.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wrench.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wrench.png
deleted file mode 100644
index 3071cc58..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/wrench.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/xbox.png b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/xbox.png
deleted file mode 100644
index 22d1f851..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/png/512/xbox.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/readme.md b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/readme.md
deleted file mode 100644
index f530251c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/readme.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# Ionicons
-
-
-The premium icon font for [Ionic](http://ionicframework.com/). Designed by [@benjsperry](https://twitter.com/benjsperry).
-
-Note: All brand icons are trademarks of their respective owners. The use of these trademarks does not indicate endorsement of the trademark holder by Drifty, nor vice versa.
-
-Visit [ionicons.com](http://ionicons.com) and check out the search feature, which has keywords identifying common icon names and styles. For example, if you search for “arrow†we call up every icon that could possibly be used as an arrow. We’ve also included each icon’s class name for easy copy/pasting when you’re developing!
-
-We intend for this icon pack to be used with [Ionic](http://ionicframework.com/), but it’s by no means limited to it. Use them wherever you see fit, personal or commercial. They are free to use and licensed under [MIT](http://opensource.org/licenses/MIT).
-
-
-## Getting Started
-
- 1. Download and extract the font pack
- 2. Copy the `ionicons.css` to your project
- 3. Copy the `fonts` folder to your project
- 4. Ensure the font urls within `ionicons.css` properly reference the `fonts` path within your project.
- 5. Include a reference to the `ionicons.css` file from every webpage you need to use it.
-
-Or install with [component](https://github.com/component/component):
-
- $ component install driftyco/ionicons
-
-Or perhaps you're known to use [bower](http://bower.io/)?
-
- $ bower install ionicons
-
-
-## HTML Example
-
-You can use [ionicons.com](http://ionicons.com) to easily find the icon you want to use. Once you've copied the desired icon's CSS classname, simply add the `icon` and icon's classname, such as `ion-home` to an HTML element.
-
- <i class="icon ion-home"></i>
-
-
-## Build Instructions
-
-This repo already comes with all the files built and ready to go, but can also build the fonts from the source. Requires Python, FontForge and Sass:
-
-1) Install FontForge, which is the program that creates the font files from the SVG files:
-
- $ brew install fontforge ttfautohint
-
-2) Install [Sass](http://sass-lang.com/)
-
- $ gem install sass
-
-3) Add or subtract files from the `src/` folder you'd like to be apart of the font files.
-
-4) Modify any settings in the `builder/manifest.json` file. You can change the name of the font-family and CSS classname prefix.
-
-5) Run the build command:
-
- python ./builder/generate.py
-
-
-## License
-
-Ionicons is licensed under the [MIT license](http://opensource.org/licenses/MIT).
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-font.scss b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-font.scss
deleted file mode 100644
index 76ec6ebd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-font.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-// Ionicons Font Path
-// --------------------------
-
-@font-face {
- font-family: $ionicons-font-family;
- src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}");
- src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}#iefix") format("embedded-opentype"),
- url("#{$ionicons-font-path}/ionicons.ttf?v=#{$ionicons-version}") format("truetype"),
- url("#{$ionicons-font-path}/ionicons.woff?v=#{$ionicons-version}") format("woff"),
- url("#{$ionicons-font-path}/ionicons.svg?v=#{$ionicons-version}#Ionicons") format("svg");
- font-weight: normal;
- font-style: normal;
-}
-
-.ion {
- display: inline-block;
- font-family: $ionicons-font-family;
- speak: none;
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- text-transform: none;
- text-rendering: auto;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-icons.scss b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-icons.scss
deleted file mode 100644
index d08d4f0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-icons.scss
+++ /dev/null
@@ -1,1473 +0,0 @@
-// Ionicons Icons
-// --------------------------
-
-.ionicons,
-.#{$ionicons-prefix}alert:before,
-.#{$ionicons-prefix}alert-circled:before,
-.#{$ionicons-prefix}android-add:before,
-.#{$ionicons-prefix}android-add-circle:before,
-.#{$ionicons-prefix}android-alarm-clock:before,
-.#{$ionicons-prefix}android-alert:before,
-.#{$ionicons-prefix}android-apps:before,
-.#{$ionicons-prefix}android-archive:before,
-.#{$ionicons-prefix}android-arrow-back:before,
-.#{$ionicons-prefix}android-arrow-down:before,
-.#{$ionicons-prefix}android-arrow-dropdown:before,
-.#{$ionicons-prefix}android-arrow-dropdown-circle:before,
-.#{$ionicons-prefix}android-arrow-dropleft:before,
-.#{$ionicons-prefix}android-arrow-dropleft-circle:before,
-.#{$ionicons-prefix}android-arrow-dropright:before,
-.#{$ionicons-prefix}android-arrow-dropright-circle:before,
-.#{$ionicons-prefix}android-arrow-dropup:before,
-.#{$ionicons-prefix}android-arrow-dropup-circle:before,
-.#{$ionicons-prefix}android-arrow-forward:before,
-.#{$ionicons-prefix}android-arrow-up:before,
-.#{$ionicons-prefix}android-attach:before,
-.#{$ionicons-prefix}android-bar:before,
-.#{$ionicons-prefix}android-bicycle:before,
-.#{$ionicons-prefix}android-boat:before,
-.#{$ionicons-prefix}android-bookmark:before,
-.#{$ionicons-prefix}android-bulb:before,
-.#{$ionicons-prefix}android-bus:before,
-.#{$ionicons-prefix}android-calendar:before,
-.#{$ionicons-prefix}android-call:before,
-.#{$ionicons-prefix}android-camera:before,
-.#{$ionicons-prefix}android-cancel:before,
-.#{$ionicons-prefix}android-car:before,
-.#{$ionicons-prefix}android-cart:before,
-.#{$ionicons-prefix}android-chat:before,
-.#{$ionicons-prefix}android-checkbox:before,
-.#{$ionicons-prefix}android-checkbox-blank:before,
-.#{$ionicons-prefix}android-checkbox-outline:before,
-.#{$ionicons-prefix}android-checkbox-outline-blank:before,
-.#{$ionicons-prefix}android-checkmark-circle:before,
-.#{$ionicons-prefix}android-clipboard:before,
-.#{$ionicons-prefix}android-close:before,
-.#{$ionicons-prefix}android-cloud:before,
-.#{$ionicons-prefix}android-cloud-circle:before,
-.#{$ionicons-prefix}android-cloud-done:before,
-.#{$ionicons-prefix}android-cloud-outline:before,
-.#{$ionicons-prefix}android-color-palette:before,
-.#{$ionicons-prefix}android-compass:before,
-.#{$ionicons-prefix}android-contact:before,
-.#{$ionicons-prefix}android-contacts:before,
-.#{$ionicons-prefix}android-contract:before,
-.#{$ionicons-prefix}android-create:before,
-.#{$ionicons-prefix}android-delete:before,
-.#{$ionicons-prefix}android-desktop:before,
-.#{$ionicons-prefix}android-document:before,
-.#{$ionicons-prefix}android-done:before,
-.#{$ionicons-prefix}android-done-all:before,
-.#{$ionicons-prefix}android-download:before,
-.#{$ionicons-prefix}android-drafts:before,
-.#{$ionicons-prefix}android-exit:before,
-.#{$ionicons-prefix}android-expand:before,
-.#{$ionicons-prefix}android-favorite:before,
-.#{$ionicons-prefix}android-favorite-outline:before,
-.#{$ionicons-prefix}android-film:before,
-.#{$ionicons-prefix}android-folder:before,
-.#{$ionicons-prefix}android-folder-open:before,
-.#{$ionicons-prefix}android-funnel:before,
-.#{$ionicons-prefix}android-globe:before,
-.#{$ionicons-prefix}android-hand:before,
-.#{$ionicons-prefix}android-hangout:before,
-.#{$ionicons-prefix}android-happy:before,
-.#{$ionicons-prefix}android-home:before,
-.#{$ionicons-prefix}android-image:before,
-.#{$ionicons-prefix}android-laptop:before,
-.#{$ionicons-prefix}android-list:before,
-.#{$ionicons-prefix}android-locate:before,
-.#{$ionicons-prefix}android-lock:before,
-.#{$ionicons-prefix}android-mail:before,
-.#{$ionicons-prefix}android-map:before,
-.#{$ionicons-prefix}android-menu:before,
-.#{$ionicons-prefix}android-microphone:before,
-.#{$ionicons-prefix}android-microphone-off:before,
-.#{$ionicons-prefix}android-more-horizontal:before,
-.#{$ionicons-prefix}android-more-vertical:before,
-.#{$ionicons-prefix}android-navigate:before,
-.#{$ionicons-prefix}android-notifications:before,
-.#{$ionicons-prefix}android-notifications-none:before,
-.#{$ionicons-prefix}android-notifications-off:before,
-.#{$ionicons-prefix}android-open:before,
-.#{$ionicons-prefix}android-options:before,
-.#{$ionicons-prefix}android-people:before,
-.#{$ionicons-prefix}android-person:before,
-.#{$ionicons-prefix}android-person-add:before,
-.#{$ionicons-prefix}android-phone-landscape:before,
-.#{$ionicons-prefix}android-phone-portrait:before,
-.#{$ionicons-prefix}android-pin:before,
-.#{$ionicons-prefix}android-plane:before,
-.#{$ionicons-prefix}android-playstore:before,
-.#{$ionicons-prefix}android-print:before,
-.#{$ionicons-prefix}android-radio-button-off:before,
-.#{$ionicons-prefix}android-radio-button-on:before,
-.#{$ionicons-prefix}android-refresh:before,
-.#{$ionicons-prefix}android-remove:before,
-.#{$ionicons-prefix}android-remove-circle:before,
-.#{$ionicons-prefix}android-restaurant:before,
-.#{$ionicons-prefix}android-sad:before,
-.#{$ionicons-prefix}android-search:before,
-.#{$ionicons-prefix}android-send:before,
-.#{$ionicons-prefix}android-settings:before,
-.#{$ionicons-prefix}android-share:before,
-.#{$ionicons-prefix}android-share-alt:before,
-.#{$ionicons-prefix}android-star:before,
-.#{$ionicons-prefix}android-star-half:before,
-.#{$ionicons-prefix}android-star-outline:before,
-.#{$ionicons-prefix}android-stopwatch:before,
-.#{$ionicons-prefix}android-subway:before,
-.#{$ionicons-prefix}android-sunny:before,
-.#{$ionicons-prefix}android-sync:before,
-.#{$ionicons-prefix}android-textsms:before,
-.#{$ionicons-prefix}android-time:before,
-.#{$ionicons-prefix}android-train:before,
-.#{$ionicons-prefix}android-unlock:before,
-.#{$ionicons-prefix}android-upload:before,
-.#{$ionicons-prefix}android-volume-down:before,
-.#{$ionicons-prefix}android-volume-mute:before,
-.#{$ionicons-prefix}android-volume-off:before,
-.#{$ionicons-prefix}android-volume-up:before,
-.#{$ionicons-prefix}android-walk:before,
-.#{$ionicons-prefix}android-warning:before,
-.#{$ionicons-prefix}android-watch:before,
-.#{$ionicons-prefix}android-wifi:before,
-.#{$ionicons-prefix}aperture:before,
-.#{$ionicons-prefix}archive:before,
-.#{$ionicons-prefix}arrow-down-a:before,
-.#{$ionicons-prefix}arrow-down-b:before,
-.#{$ionicons-prefix}arrow-down-c:before,
-.#{$ionicons-prefix}arrow-expand:before,
-.#{$ionicons-prefix}arrow-graph-down-left:before,
-.#{$ionicons-prefix}arrow-graph-down-right:before,
-.#{$ionicons-prefix}arrow-graph-up-left:before,
-.#{$ionicons-prefix}arrow-graph-up-right:before,
-.#{$ionicons-prefix}arrow-left-a:before,
-.#{$ionicons-prefix}arrow-left-b:before,
-.#{$ionicons-prefix}arrow-left-c:before,
-.#{$ionicons-prefix}arrow-move:before,
-.#{$ionicons-prefix}arrow-resize:before,
-.#{$ionicons-prefix}arrow-return-left:before,
-.#{$ionicons-prefix}arrow-return-right:before,
-.#{$ionicons-prefix}arrow-right-a:before,
-.#{$ionicons-prefix}arrow-right-b:before,
-.#{$ionicons-prefix}arrow-right-c:before,
-.#{$ionicons-prefix}arrow-shrink:before,
-.#{$ionicons-prefix}arrow-swap:before,
-.#{$ionicons-prefix}arrow-up-a:before,
-.#{$ionicons-prefix}arrow-up-b:before,
-.#{$ionicons-prefix}arrow-up-c:before,
-.#{$ionicons-prefix}asterisk:before,
-.#{$ionicons-prefix}at:before,
-.#{$ionicons-prefix}backspace:before,
-.#{$ionicons-prefix}backspace-outline:before,
-.#{$ionicons-prefix}bag:before,
-.#{$ionicons-prefix}battery-charging:before,
-.#{$ionicons-prefix}battery-empty:before,
-.#{$ionicons-prefix}battery-full:before,
-.#{$ionicons-prefix}battery-half:before,
-.#{$ionicons-prefix}battery-low:before,
-.#{$ionicons-prefix}beaker:before,
-.#{$ionicons-prefix}beer:before,
-.#{$ionicons-prefix}bluetooth:before,
-.#{$ionicons-prefix}bonfire:before,
-.#{$ionicons-prefix}bookmark:before,
-.#{$ionicons-prefix}bowtie:before,
-.#{$ionicons-prefix}briefcase:before,
-.#{$ionicons-prefix}bug:before,
-.#{$ionicons-prefix}calculator:before,
-.#{$ionicons-prefix}calendar:before,
-.#{$ionicons-prefix}camera:before,
-.#{$ionicons-prefix}card:before,
-.#{$ionicons-prefix}cash:before,
-.#{$ionicons-prefix}chatbox:before,
-.#{$ionicons-prefix}chatbox-working:before,
-.#{$ionicons-prefix}chatboxes:before,
-.#{$ionicons-prefix}chatbubble:before,
-.#{$ionicons-prefix}chatbubble-working:before,
-.#{$ionicons-prefix}chatbubbles:before,
-.#{$ionicons-prefix}checkmark:before,
-.#{$ionicons-prefix}checkmark-circled:before,
-.#{$ionicons-prefix}checkmark-round:before,
-.#{$ionicons-prefix}chevron-down:before,
-.#{$ionicons-prefix}chevron-left:before,
-.#{$ionicons-prefix}chevron-right:before,
-.#{$ionicons-prefix}chevron-up:before,
-.#{$ionicons-prefix}clipboard:before,
-.#{$ionicons-prefix}clock:before,
-.#{$ionicons-prefix}close:before,
-.#{$ionicons-prefix}close-circled:before,
-.#{$ionicons-prefix}close-round:before,
-.#{$ionicons-prefix}closed-captioning:before,
-.#{$ionicons-prefix}cloud:before,
-.#{$ionicons-prefix}code:before,
-.#{$ionicons-prefix}code-download:before,
-.#{$ionicons-prefix}code-working:before,
-.#{$ionicons-prefix}coffee:before,
-.#{$ionicons-prefix}compass:before,
-.#{$ionicons-prefix}compose:before,
-.#{$ionicons-prefix}connection-bars:before,
-.#{$ionicons-prefix}contrast:before,
-.#{$ionicons-prefix}crop:before,
-.#{$ionicons-prefix}cube:before,
-.#{$ionicons-prefix}disc:before,
-.#{$ionicons-prefix}document:before,
-.#{$ionicons-prefix}document-text:before,
-.#{$ionicons-prefix}drag:before,
-.#{$ionicons-prefix}earth:before,
-.#{$ionicons-prefix}easel:before,
-.#{$ionicons-prefix}edit:before,
-.#{$ionicons-prefix}egg:before,
-.#{$ionicons-prefix}eject:before,
-.#{$ionicons-prefix}email:before,
-.#{$ionicons-prefix}email-unread:before,
-.#{$ionicons-prefix}erlenmeyer-flask:before,
-.#{$ionicons-prefix}erlenmeyer-flask-bubbles:before,
-.#{$ionicons-prefix}eye:before,
-.#{$ionicons-prefix}eye-disabled:before,
-.#{$ionicons-prefix}female:before,
-.#{$ionicons-prefix}filing:before,
-.#{$ionicons-prefix}film-marker:before,
-.#{$ionicons-prefix}fireball:before,
-.#{$ionicons-prefix}flag:before,
-.#{$ionicons-prefix}flame:before,
-.#{$ionicons-prefix}flash:before,
-.#{$ionicons-prefix}flash-off:before,
-.#{$ionicons-prefix}folder:before,
-.#{$ionicons-prefix}fork:before,
-.#{$ionicons-prefix}fork-repo:before,
-.#{$ionicons-prefix}forward:before,
-.#{$ionicons-prefix}funnel:before,
-.#{$ionicons-prefix}gear-a:before,
-.#{$ionicons-prefix}gear-b:before,
-.#{$ionicons-prefix}grid:before,
-.#{$ionicons-prefix}hammer:before,
-.#{$ionicons-prefix}happy:before,
-.#{$ionicons-prefix}happy-outline:before,
-.#{$ionicons-prefix}headphone:before,
-.#{$ionicons-prefix}heart:before,
-.#{$ionicons-prefix}heart-broken:before,
-.#{$ionicons-prefix}help:before,
-.#{$ionicons-prefix}help-buoy:before,
-.#{$ionicons-prefix}help-circled:before,
-.#{$ionicons-prefix}home:before,
-.#{$ionicons-prefix}icecream:before,
-.#{$ionicons-prefix}image:before,
-.#{$ionicons-prefix}images:before,
-.#{$ionicons-prefix}information:before,
-.#{$ionicons-prefix}information-circled:before,
-.#{$ionicons-prefix}ionic:before,
-.#{$ionicons-prefix}ios-alarm:before,
-.#{$ionicons-prefix}ios-alarm-outline:before,
-.#{$ionicons-prefix}ios-albums:before,
-.#{$ionicons-prefix}ios-albums-outline:before,
-.#{$ionicons-prefix}ios-americanfootball:before,
-.#{$ionicons-prefix}ios-americanfootball-outline:before,
-.#{$ionicons-prefix}ios-analytics:before,
-.#{$ionicons-prefix}ios-analytics-outline:before,
-.#{$ionicons-prefix}ios-arrow-back:before,
-.#{$ionicons-prefix}ios-arrow-down:before,
-.#{$ionicons-prefix}ios-arrow-forward:before,
-.#{$ionicons-prefix}ios-arrow-left:before,
-.#{$ionicons-prefix}ios-arrow-right:before,
-.#{$ionicons-prefix}ios-arrow-thin-down:before,
-.#{$ionicons-prefix}ios-arrow-thin-left:before,
-.#{$ionicons-prefix}ios-arrow-thin-right:before,
-.#{$ionicons-prefix}ios-arrow-thin-up:before,
-.#{$ionicons-prefix}ios-arrow-up:before,
-.#{$ionicons-prefix}ios-at:before,
-.#{$ionicons-prefix}ios-at-outline:before,
-.#{$ionicons-prefix}ios-barcode:before,
-.#{$ionicons-prefix}ios-barcode-outline:before,
-.#{$ionicons-prefix}ios-baseball:before,
-.#{$ionicons-prefix}ios-baseball-outline:before,
-.#{$ionicons-prefix}ios-basketball:before,
-.#{$ionicons-prefix}ios-basketball-outline:before,
-.#{$ionicons-prefix}ios-bell:before,
-.#{$ionicons-prefix}ios-bell-outline:before,
-.#{$ionicons-prefix}ios-body:before,
-.#{$ionicons-prefix}ios-body-outline:before,
-.#{$ionicons-prefix}ios-bolt:before,
-.#{$ionicons-prefix}ios-bolt-outline:before,
-.#{$ionicons-prefix}ios-book:before,
-.#{$ionicons-prefix}ios-book-outline:before,
-.#{$ionicons-prefix}ios-bookmarks:before,
-.#{$ionicons-prefix}ios-bookmarks-outline:before,
-.#{$ionicons-prefix}ios-box:before,
-.#{$ionicons-prefix}ios-box-outline:before,
-.#{$ionicons-prefix}ios-briefcase:before,
-.#{$ionicons-prefix}ios-briefcase-outline:before,
-.#{$ionicons-prefix}ios-browsers:before,
-.#{$ionicons-prefix}ios-browsers-outline:before,
-.#{$ionicons-prefix}ios-calculator:before,
-.#{$ionicons-prefix}ios-calculator-outline:before,
-.#{$ionicons-prefix}ios-calendar:before,
-.#{$ionicons-prefix}ios-calendar-outline:before,
-.#{$ionicons-prefix}ios-camera:before,
-.#{$ionicons-prefix}ios-camera-outline:before,
-.#{$ionicons-prefix}ios-cart:before,
-.#{$ionicons-prefix}ios-cart-outline:before,
-.#{$ionicons-prefix}ios-chatboxes:before,
-.#{$ionicons-prefix}ios-chatboxes-outline:before,
-.#{$ionicons-prefix}ios-chatbubble:before,
-.#{$ionicons-prefix}ios-chatbubble-outline:before,
-.#{$ionicons-prefix}ios-checkmark:before,
-.#{$ionicons-prefix}ios-checkmark-empty:before,
-.#{$ionicons-prefix}ios-checkmark-outline:before,
-.#{$ionicons-prefix}ios-circle-filled:before,
-.#{$ionicons-prefix}ios-circle-outline:before,
-.#{$ionicons-prefix}ios-clock:before,
-.#{$ionicons-prefix}ios-clock-outline:before,
-.#{$ionicons-prefix}ios-close:before,
-.#{$ionicons-prefix}ios-close-empty:before,
-.#{$ionicons-prefix}ios-close-outline:before,
-.#{$ionicons-prefix}ios-cloud:before,
-.#{$ionicons-prefix}ios-cloud-download:before,
-.#{$ionicons-prefix}ios-cloud-download-outline:before,
-.#{$ionicons-prefix}ios-cloud-outline:before,
-.#{$ionicons-prefix}ios-cloud-upload:before,
-.#{$ionicons-prefix}ios-cloud-upload-outline:before,
-.#{$ionicons-prefix}ios-cloudy:before,
-.#{$ionicons-prefix}ios-cloudy-night:before,
-.#{$ionicons-prefix}ios-cloudy-night-outline:before,
-.#{$ionicons-prefix}ios-cloudy-outline:before,
-.#{$ionicons-prefix}ios-cog:before,
-.#{$ionicons-prefix}ios-cog-outline:before,
-.#{$ionicons-prefix}ios-color-filter:before,
-.#{$ionicons-prefix}ios-color-filter-outline:before,
-.#{$ionicons-prefix}ios-color-wand:before,
-.#{$ionicons-prefix}ios-color-wand-outline:before,
-.#{$ionicons-prefix}ios-compose:before,
-.#{$ionicons-prefix}ios-compose-outline:before,
-.#{$ionicons-prefix}ios-contact:before,
-.#{$ionicons-prefix}ios-contact-outline:before,
-.#{$ionicons-prefix}ios-copy:before,
-.#{$ionicons-prefix}ios-copy-outline:before,
-.#{$ionicons-prefix}ios-crop:before,
-.#{$ionicons-prefix}ios-crop-strong:before,
-.#{$ionicons-prefix}ios-download:before,
-.#{$ionicons-prefix}ios-download-outline:before,
-.#{$ionicons-prefix}ios-drag:before,
-.#{$ionicons-prefix}ios-email:before,
-.#{$ionicons-prefix}ios-email-outline:before,
-.#{$ionicons-prefix}ios-eye:before,
-.#{$ionicons-prefix}ios-eye-outline:before,
-.#{$ionicons-prefix}ios-fastforward:before,
-.#{$ionicons-prefix}ios-fastforward-outline:before,
-.#{$ionicons-prefix}ios-filing:before,
-.#{$ionicons-prefix}ios-filing-outline:before,
-.#{$ionicons-prefix}ios-film:before,
-.#{$ionicons-prefix}ios-film-outline:before,
-.#{$ionicons-prefix}ios-flag:before,
-.#{$ionicons-prefix}ios-flag-outline:before,
-.#{$ionicons-prefix}ios-flame:before,
-.#{$ionicons-prefix}ios-flame-outline:before,
-.#{$ionicons-prefix}ios-flask:before,
-.#{$ionicons-prefix}ios-flask-outline:before,
-.#{$ionicons-prefix}ios-flower:before,
-.#{$ionicons-prefix}ios-flower-outline:before,
-.#{$ionicons-prefix}ios-folder:before,
-.#{$ionicons-prefix}ios-folder-outline:before,
-.#{$ionicons-prefix}ios-football:before,
-.#{$ionicons-prefix}ios-football-outline:before,
-.#{$ionicons-prefix}ios-game-controller-a:before,
-.#{$ionicons-prefix}ios-game-controller-a-outline:before,
-.#{$ionicons-prefix}ios-game-controller-b:before,
-.#{$ionicons-prefix}ios-game-controller-b-outline:before,
-.#{$ionicons-prefix}ios-gear:before,
-.#{$ionicons-prefix}ios-gear-outline:before,
-.#{$ionicons-prefix}ios-glasses:before,
-.#{$ionicons-prefix}ios-glasses-outline:before,
-.#{$ionicons-prefix}ios-grid-view:before,
-.#{$ionicons-prefix}ios-grid-view-outline:before,
-.#{$ionicons-prefix}ios-heart:before,
-.#{$ionicons-prefix}ios-heart-outline:before,
-.#{$ionicons-prefix}ios-help:before,
-.#{$ionicons-prefix}ios-help-empty:before,
-.#{$ionicons-prefix}ios-help-outline:before,
-.#{$ionicons-prefix}ios-home:before,
-.#{$ionicons-prefix}ios-home-outline:before,
-.#{$ionicons-prefix}ios-infinite:before,
-.#{$ionicons-prefix}ios-infinite-outline:before,
-.#{$ionicons-prefix}ios-information:before,
-.#{$ionicons-prefix}ios-information-empty:before,
-.#{$ionicons-prefix}ios-information-outline:before,
-.#{$ionicons-prefix}ios-ionic-outline:before,
-.#{$ionicons-prefix}ios-keypad:before,
-.#{$ionicons-prefix}ios-keypad-outline:before,
-.#{$ionicons-prefix}ios-lightbulb:before,
-.#{$ionicons-prefix}ios-lightbulb-outline:before,
-.#{$ionicons-prefix}ios-list:before,
-.#{$ionicons-prefix}ios-list-outline:before,
-.#{$ionicons-prefix}ios-location:before,
-.#{$ionicons-prefix}ios-location-outline:before,
-.#{$ionicons-prefix}ios-locked:before,
-.#{$ionicons-prefix}ios-locked-outline:before,
-.#{$ionicons-prefix}ios-loop:before,
-.#{$ionicons-prefix}ios-loop-strong:before,
-.#{$ionicons-prefix}ios-medical:before,
-.#{$ionicons-prefix}ios-medical-outline:before,
-.#{$ionicons-prefix}ios-medkit:before,
-.#{$ionicons-prefix}ios-medkit-outline:before,
-.#{$ionicons-prefix}ios-mic:before,
-.#{$ionicons-prefix}ios-mic-off:before,
-.#{$ionicons-prefix}ios-mic-outline:before,
-.#{$ionicons-prefix}ios-minus:before,
-.#{$ionicons-prefix}ios-minus-empty:before,
-.#{$ionicons-prefix}ios-minus-outline:before,
-.#{$ionicons-prefix}ios-monitor:before,
-.#{$ionicons-prefix}ios-monitor-outline:before,
-.#{$ionicons-prefix}ios-moon:before,
-.#{$ionicons-prefix}ios-moon-outline:before,
-.#{$ionicons-prefix}ios-more:before,
-.#{$ionicons-prefix}ios-more-outline:before,
-.#{$ionicons-prefix}ios-musical-note:before,
-.#{$ionicons-prefix}ios-musical-notes:before,
-.#{$ionicons-prefix}ios-navigate:before,
-.#{$ionicons-prefix}ios-navigate-outline:before,
-.#{$ionicons-prefix}ios-nutrition:before,
-.#{$ionicons-prefix}ios-nutrition-outline:before,
-.#{$ionicons-prefix}ios-paper:before,
-.#{$ionicons-prefix}ios-paper-outline:before,
-.#{$ionicons-prefix}ios-paperplane:before,
-.#{$ionicons-prefix}ios-paperplane-outline:before,
-.#{$ionicons-prefix}ios-partlysunny:before,
-.#{$ionicons-prefix}ios-partlysunny-outline:before,
-.#{$ionicons-prefix}ios-pause:before,
-.#{$ionicons-prefix}ios-pause-outline:before,
-.#{$ionicons-prefix}ios-paw:before,
-.#{$ionicons-prefix}ios-paw-outline:before,
-.#{$ionicons-prefix}ios-people:before,
-.#{$ionicons-prefix}ios-people-outline:before,
-.#{$ionicons-prefix}ios-person:before,
-.#{$ionicons-prefix}ios-person-outline:before,
-.#{$ionicons-prefix}ios-personadd:before,
-.#{$ionicons-prefix}ios-personadd-outline:before,
-.#{$ionicons-prefix}ios-photos:before,
-.#{$ionicons-prefix}ios-photos-outline:before,
-.#{$ionicons-prefix}ios-pie:before,
-.#{$ionicons-prefix}ios-pie-outline:before,
-.#{$ionicons-prefix}ios-pint:before,
-.#{$ionicons-prefix}ios-pint-outline:before,
-.#{$ionicons-prefix}ios-play:before,
-.#{$ionicons-prefix}ios-play-outline:before,
-.#{$ionicons-prefix}ios-plus:before,
-.#{$ionicons-prefix}ios-plus-empty:before,
-.#{$ionicons-prefix}ios-plus-outline:before,
-.#{$ionicons-prefix}ios-pricetag:before,
-.#{$ionicons-prefix}ios-pricetag-outline:before,
-.#{$ionicons-prefix}ios-pricetags:before,
-.#{$ionicons-prefix}ios-pricetags-outline:before,
-.#{$ionicons-prefix}ios-printer:before,
-.#{$ionicons-prefix}ios-printer-outline:before,
-.#{$ionicons-prefix}ios-pulse:before,
-.#{$ionicons-prefix}ios-pulse-strong:before,
-.#{$ionicons-prefix}ios-rainy:before,
-.#{$ionicons-prefix}ios-rainy-outline:before,
-.#{$ionicons-prefix}ios-recording:before,
-.#{$ionicons-prefix}ios-recording-outline:before,
-.#{$ionicons-prefix}ios-redo:before,
-.#{$ionicons-prefix}ios-redo-outline:before,
-.#{$ionicons-prefix}ios-refresh:before,
-.#{$ionicons-prefix}ios-refresh-empty:before,
-.#{$ionicons-prefix}ios-refresh-outline:before,
-.#{$ionicons-prefix}ios-reload:before,
-.#{$ionicons-prefix}ios-reverse-camera:before,
-.#{$ionicons-prefix}ios-reverse-camera-outline:before,
-.#{$ionicons-prefix}ios-rewind:before,
-.#{$ionicons-prefix}ios-rewind-outline:before,
-.#{$ionicons-prefix}ios-rose:before,
-.#{$ionicons-prefix}ios-rose-outline:before,
-.#{$ionicons-prefix}ios-search:before,
-.#{$ionicons-prefix}ios-search-strong:before,
-.#{$ionicons-prefix}ios-settings:before,
-.#{$ionicons-prefix}ios-settings-strong:before,
-.#{$ionicons-prefix}ios-shuffle:before,
-.#{$ionicons-prefix}ios-shuffle-strong:before,
-.#{$ionicons-prefix}ios-skipbackward:before,
-.#{$ionicons-prefix}ios-skipbackward-outline:before,
-.#{$ionicons-prefix}ios-skipforward:before,
-.#{$ionicons-prefix}ios-skipforward-outline:before,
-.#{$ionicons-prefix}ios-snowy:before,
-.#{$ionicons-prefix}ios-speedometer:before,
-.#{$ionicons-prefix}ios-speedometer-outline:before,
-.#{$ionicons-prefix}ios-star:before,
-.#{$ionicons-prefix}ios-star-half:before,
-.#{$ionicons-prefix}ios-star-outline:before,
-.#{$ionicons-prefix}ios-stopwatch:before,
-.#{$ionicons-prefix}ios-stopwatch-outline:before,
-.#{$ionicons-prefix}ios-sunny:before,
-.#{$ionicons-prefix}ios-sunny-outline:before,
-.#{$ionicons-prefix}ios-telephone:before,
-.#{$ionicons-prefix}ios-telephone-outline:before,
-.#{$ionicons-prefix}ios-tennisball:before,
-.#{$ionicons-prefix}ios-tennisball-outline:before,
-.#{$ionicons-prefix}ios-thunderstorm:before,
-.#{$ionicons-prefix}ios-thunderstorm-outline:before,
-.#{$ionicons-prefix}ios-time:before,
-.#{$ionicons-prefix}ios-time-outline:before,
-.#{$ionicons-prefix}ios-timer:before,
-.#{$ionicons-prefix}ios-timer-outline:before,
-.#{$ionicons-prefix}ios-toggle:before,
-.#{$ionicons-prefix}ios-toggle-outline:before,
-.#{$ionicons-prefix}ios-trash:before,
-.#{$ionicons-prefix}ios-trash-outline:before,
-.#{$ionicons-prefix}ios-undo:before,
-.#{$ionicons-prefix}ios-undo-outline:before,
-.#{$ionicons-prefix}ios-unlocked:before,
-.#{$ionicons-prefix}ios-unlocked-outline:before,
-.#{$ionicons-prefix}ios-upload:before,
-.#{$ionicons-prefix}ios-upload-outline:before,
-.#{$ionicons-prefix}ios-videocam:before,
-.#{$ionicons-prefix}ios-videocam-outline:before,
-.#{$ionicons-prefix}ios-volume-high:before,
-.#{$ionicons-prefix}ios-volume-low:before,
-.#{$ionicons-prefix}ios-wineglass:before,
-.#{$ionicons-prefix}ios-wineglass-outline:before,
-.#{$ionicons-prefix}ios-world:before,
-.#{$ionicons-prefix}ios-world-outline:before,
-.#{$ionicons-prefix}ipad:before,
-.#{$ionicons-prefix}iphone:before,
-.#{$ionicons-prefix}ipod:before,
-.#{$ionicons-prefix}jet:before,
-.#{$ionicons-prefix}key:before,
-.#{$ionicons-prefix}knife:before,
-.#{$ionicons-prefix}laptop:before,
-.#{$ionicons-prefix}leaf:before,
-.#{$ionicons-prefix}levels:before,
-.#{$ionicons-prefix}lightbulb:before,
-.#{$ionicons-prefix}link:before,
-.#{$ionicons-prefix}load-a:before,
-.#{$ionicons-prefix}load-b:before,
-.#{$ionicons-prefix}load-c:before,
-.#{$ionicons-prefix}load-d:before,
-.#{$ionicons-prefix}location:before,
-.#{$ionicons-prefix}lock-combination:before,
-.#{$ionicons-prefix}locked:before,
-.#{$ionicons-prefix}log-in:before,
-.#{$ionicons-prefix}log-out:before,
-.#{$ionicons-prefix}loop:before,
-.#{$ionicons-prefix}magnet:before,
-.#{$ionicons-prefix}male:before,
-.#{$ionicons-prefix}man:before,
-.#{$ionicons-prefix}map:before,
-.#{$ionicons-prefix}medkit:before,
-.#{$ionicons-prefix}merge:before,
-.#{$ionicons-prefix}mic-a:before,
-.#{$ionicons-prefix}mic-b:before,
-.#{$ionicons-prefix}mic-c:before,
-.#{$ionicons-prefix}minus:before,
-.#{$ionicons-prefix}minus-circled:before,
-.#{$ionicons-prefix}minus-round:before,
-.#{$ionicons-prefix}model-s:before,
-.#{$ionicons-prefix}monitor:before,
-.#{$ionicons-prefix}more:before,
-.#{$ionicons-prefix}mouse:before,
-.#{$ionicons-prefix}music-note:before,
-.#{$ionicons-prefix}navicon:before,
-.#{$ionicons-prefix}navicon-round:before,
-.#{$ionicons-prefix}navigate:before,
-.#{$ionicons-prefix}network:before,
-.#{$ionicons-prefix}no-smoking:before,
-.#{$ionicons-prefix}nuclear:before,
-.#{$ionicons-prefix}outlet:before,
-.#{$ionicons-prefix}paintbrush:before,
-.#{$ionicons-prefix}paintbucket:before,
-.#{$ionicons-prefix}paper-airplane:before,
-.#{$ionicons-prefix}paperclip:before,
-.#{$ionicons-prefix}pause:before,
-.#{$ionicons-prefix}person:before,
-.#{$ionicons-prefix}person-add:before,
-.#{$ionicons-prefix}person-stalker:before,
-.#{$ionicons-prefix}pie-graph:before,
-.#{$ionicons-prefix}pin:before,
-.#{$ionicons-prefix}pinpoint:before,
-.#{$ionicons-prefix}pizza:before,
-.#{$ionicons-prefix}plane:before,
-.#{$ionicons-prefix}planet:before,
-.#{$ionicons-prefix}play:before,
-.#{$ionicons-prefix}playstation:before,
-.#{$ionicons-prefix}plus:before,
-.#{$ionicons-prefix}plus-circled:before,
-.#{$ionicons-prefix}plus-round:before,
-.#{$ionicons-prefix}podium:before,
-.#{$ionicons-prefix}pound:before,
-.#{$ionicons-prefix}power:before,
-.#{$ionicons-prefix}pricetag:before,
-.#{$ionicons-prefix}pricetags:before,
-.#{$ionicons-prefix}printer:before,
-.#{$ionicons-prefix}pull-request:before,
-.#{$ionicons-prefix}qr-scanner:before,
-.#{$ionicons-prefix}quote:before,
-.#{$ionicons-prefix}radio-waves:before,
-.#{$ionicons-prefix}record:before,
-.#{$ionicons-prefix}refresh:before,
-.#{$ionicons-prefix}reply:before,
-.#{$ionicons-prefix}reply-all:before,
-.#{$ionicons-prefix}ribbon-a:before,
-.#{$ionicons-prefix}ribbon-b:before,
-.#{$ionicons-prefix}sad:before,
-.#{$ionicons-prefix}sad-outline:before,
-.#{$ionicons-prefix}scissors:before,
-.#{$ionicons-prefix}search:before,
-.#{$ionicons-prefix}settings:before,
-.#{$ionicons-prefix}share:before,
-.#{$ionicons-prefix}shuffle:before,
-.#{$ionicons-prefix}skip-backward:before,
-.#{$ionicons-prefix}skip-forward:before,
-.#{$ionicons-prefix}social-android:before,
-.#{$ionicons-prefix}social-android-outline:before,
-.#{$ionicons-prefix}social-angular:before,
-.#{$ionicons-prefix}social-angular-outline:before,
-.#{$ionicons-prefix}social-apple:before,
-.#{$ionicons-prefix}social-apple-outline:before,
-.#{$ionicons-prefix}social-bitcoin:before,
-.#{$ionicons-prefix}social-bitcoin-outline:before,
-.#{$ionicons-prefix}social-buffer:before,
-.#{$ionicons-prefix}social-buffer-outline:before,
-.#{$ionicons-prefix}social-chrome:before,
-.#{$ionicons-prefix}social-chrome-outline:before,
-.#{$ionicons-prefix}social-codepen:before,
-.#{$ionicons-prefix}social-codepen-outline:before,
-.#{$ionicons-prefix}social-css3:before,
-.#{$ionicons-prefix}social-css3-outline:before,
-.#{$ionicons-prefix}social-designernews:before,
-.#{$ionicons-prefix}social-designernews-outline:before,
-.#{$ionicons-prefix}social-dribbble:before,
-.#{$ionicons-prefix}social-dribbble-outline:before,
-.#{$ionicons-prefix}social-dropbox:before,
-.#{$ionicons-prefix}social-dropbox-outline:before,
-.#{$ionicons-prefix}social-euro:before,
-.#{$ionicons-prefix}social-euro-outline:before,
-.#{$ionicons-prefix}social-facebook:before,
-.#{$ionicons-prefix}social-facebook-outline:before,
-.#{$ionicons-prefix}social-foursquare:before,
-.#{$ionicons-prefix}social-foursquare-outline:before,
-.#{$ionicons-prefix}social-freebsd-devil:before,
-.#{$ionicons-prefix}social-github:before,
-.#{$ionicons-prefix}social-github-outline:before,
-.#{$ionicons-prefix}social-google:before,
-.#{$ionicons-prefix}social-google-outline:before,
-.#{$ionicons-prefix}social-googleplus:before,
-.#{$ionicons-prefix}social-googleplus-outline:before,
-.#{$ionicons-prefix}social-hackernews:before,
-.#{$ionicons-prefix}social-hackernews-outline:before,
-.#{$ionicons-prefix}social-html5:before,
-.#{$ionicons-prefix}social-html5-outline:before,
-.#{$ionicons-prefix}social-instagram:before,
-.#{$ionicons-prefix}social-instagram-outline:before,
-.#{$ionicons-prefix}social-javascript:before,
-.#{$ionicons-prefix}social-javascript-outline:before,
-.#{$ionicons-prefix}social-linkedin:before,
-.#{$ionicons-prefix}social-linkedin-outline:before,
-.#{$ionicons-prefix}social-markdown:before,
-.#{$ionicons-prefix}social-nodejs:before,
-.#{$ionicons-prefix}social-octocat:before,
-.#{$ionicons-prefix}social-pinterest:before,
-.#{$ionicons-prefix}social-pinterest-outline:before,
-.#{$ionicons-prefix}social-python:before,
-.#{$ionicons-prefix}social-reddit:before,
-.#{$ionicons-prefix}social-reddit-outline:before,
-.#{$ionicons-prefix}social-rss:before,
-.#{$ionicons-prefix}social-rss-outline:before,
-.#{$ionicons-prefix}social-sass:before,
-.#{$ionicons-prefix}social-skype:before,
-.#{$ionicons-prefix}social-skype-outline:before,
-.#{$ionicons-prefix}social-snapchat:before,
-.#{$ionicons-prefix}social-snapchat-outline:before,
-.#{$ionicons-prefix}social-tumblr:before,
-.#{$ionicons-prefix}social-tumblr-outline:before,
-.#{$ionicons-prefix}social-tux:before,
-.#{$ionicons-prefix}social-twitch:before,
-.#{$ionicons-prefix}social-twitch-outline:before,
-.#{$ionicons-prefix}social-twitter:before,
-.#{$ionicons-prefix}social-twitter-outline:before,
-.#{$ionicons-prefix}social-usd:before,
-.#{$ionicons-prefix}social-usd-outline:before,
-.#{$ionicons-prefix}social-vimeo:before,
-.#{$ionicons-prefix}social-vimeo-outline:before,
-.#{$ionicons-prefix}social-whatsapp:before,
-.#{$ionicons-prefix}social-whatsapp-outline:before,
-.#{$ionicons-prefix}social-windows:before,
-.#{$ionicons-prefix}social-windows-outline:before,
-.#{$ionicons-prefix}social-wordpress:before,
-.#{$ionicons-prefix}social-wordpress-outline:before,
-.#{$ionicons-prefix}social-yahoo:before,
-.#{$ionicons-prefix}social-yahoo-outline:before,
-.#{$ionicons-prefix}social-yen:before,
-.#{$ionicons-prefix}social-yen-outline:before,
-.#{$ionicons-prefix}social-youtube:before,
-.#{$ionicons-prefix}social-youtube-outline:before,
-.#{$ionicons-prefix}soup-can:before,
-.#{$ionicons-prefix}soup-can-outline:before,
-.#{$ionicons-prefix}speakerphone:before,
-.#{$ionicons-prefix}speedometer:before,
-.#{$ionicons-prefix}spoon:before,
-.#{$ionicons-prefix}star:before,
-.#{$ionicons-prefix}stats-bars:before,
-.#{$ionicons-prefix}steam:before,
-.#{$ionicons-prefix}stop:before,
-.#{$ionicons-prefix}thermometer:before,
-.#{$ionicons-prefix}thumbsdown:before,
-.#{$ionicons-prefix}thumbsup:before,
-.#{$ionicons-prefix}toggle:before,
-.#{$ionicons-prefix}toggle-filled:before,
-.#{$ionicons-prefix}transgender:before,
-.#{$ionicons-prefix}trash-a:before,
-.#{$ionicons-prefix}trash-b:before,
-.#{$ionicons-prefix}trophy:before,
-.#{$ionicons-prefix}tshirt:before,
-.#{$ionicons-prefix}tshirt-outline:before,
-.#{$ionicons-prefix}umbrella:before,
-.#{$ionicons-prefix}university:before,
-.#{$ionicons-prefix}unlocked:before,
-.#{$ionicons-prefix}upload:before,
-.#{$ionicons-prefix}usb:before,
-.#{$ionicons-prefix}videocamera:before,
-.#{$ionicons-prefix}volume-high:before,
-.#{$ionicons-prefix}volume-low:before,
-.#{$ionicons-prefix}volume-medium:before,
-.#{$ionicons-prefix}volume-mute:before,
-.#{$ionicons-prefix}wand:before,
-.#{$ionicons-prefix}waterdrop:before,
-.#{$ionicons-prefix}wifi:before,
-.#{$ionicons-prefix}wineglass:before,
-.#{$ionicons-prefix}woman:before,
-.#{$ionicons-prefix}wrench:before,
-.#{$ionicons-prefix}xbox:before
-{
- @extend .ion;
-}
-.#{$ionicons-prefix}alert:before { content: $ionicon-var-alert; }
-.#{$ionicons-prefix}alert-circled:before { content: $ionicon-var-alert-circled; }
-.#{$ionicons-prefix}android-add:before { content: $ionicon-var-android-add; }
-.#{$ionicons-prefix}android-add-circle:before { content: $ionicon-var-android-add-circle; }
-.#{$ionicons-prefix}android-alarm-clock:before { content: $ionicon-var-android-alarm-clock; }
-.#{$ionicons-prefix}android-alert:before { content: $ionicon-var-android-alert; }
-.#{$ionicons-prefix}android-apps:before { content: $ionicon-var-android-apps; }
-.#{$ionicons-prefix}android-archive:before { content: $ionicon-var-android-archive; }
-.#{$ionicons-prefix}android-arrow-back:before { content: $ionicon-var-android-arrow-back; }
-.#{$ionicons-prefix}android-arrow-down:before { content: $ionicon-var-android-arrow-down; }
-.#{$ionicons-prefix}android-arrow-dropdown:before { content: $ionicon-var-android-arrow-dropdown; }
-.#{$ionicons-prefix}android-arrow-dropdown-circle:before { content: $ionicon-var-android-arrow-dropdown-circle; }
-.#{$ionicons-prefix}android-arrow-dropleft:before { content: $ionicon-var-android-arrow-dropleft; }
-.#{$ionicons-prefix}android-arrow-dropleft-circle:before { content: $ionicon-var-android-arrow-dropleft-circle; }
-.#{$ionicons-prefix}android-arrow-dropright:before { content: $ionicon-var-android-arrow-dropright; }
-.#{$ionicons-prefix}android-arrow-dropright-circle:before { content: $ionicon-var-android-arrow-dropright-circle; }
-.#{$ionicons-prefix}android-arrow-dropup:before { content: $ionicon-var-android-arrow-dropup; }
-.#{$ionicons-prefix}android-arrow-dropup-circle:before { content: $ionicon-var-android-arrow-dropup-circle; }
-.#{$ionicons-prefix}android-arrow-forward:before { content: $ionicon-var-android-arrow-forward; }
-.#{$ionicons-prefix}android-arrow-up:before { content: $ionicon-var-android-arrow-up; }
-.#{$ionicons-prefix}android-attach:before { content: $ionicon-var-android-attach; }
-.#{$ionicons-prefix}android-bar:before { content: $ionicon-var-android-bar; }
-.#{$ionicons-prefix}android-bicycle:before { content: $ionicon-var-android-bicycle; }
-.#{$ionicons-prefix}android-boat:before { content: $ionicon-var-android-boat; }
-.#{$ionicons-prefix}android-bookmark:before { content: $ionicon-var-android-bookmark; }
-.#{$ionicons-prefix}android-bulb:before { content: $ionicon-var-android-bulb; }
-.#{$ionicons-prefix}android-bus:before { content: $ionicon-var-android-bus; }
-.#{$ionicons-prefix}android-calendar:before { content: $ionicon-var-android-calendar; }
-.#{$ionicons-prefix}android-call:before { content: $ionicon-var-android-call; }
-.#{$ionicons-prefix}android-camera:before { content: $ionicon-var-android-camera; }
-.#{$ionicons-prefix}android-cancel:before { content: $ionicon-var-android-cancel; }
-.#{$ionicons-prefix}android-car:before { content: $ionicon-var-android-car; }
-.#{$ionicons-prefix}android-cart:before { content: $ionicon-var-android-cart; }
-.#{$ionicons-prefix}android-chat:before { content: $ionicon-var-android-chat; }
-.#{$ionicons-prefix}android-checkbox:before { content: $ionicon-var-android-checkbox; }
-.#{$ionicons-prefix}android-checkbox-blank:before { content: $ionicon-var-android-checkbox-blank; }
-.#{$ionicons-prefix}android-checkbox-outline:before { content: $ionicon-var-android-checkbox-outline; }
-.#{$ionicons-prefix}android-checkbox-outline-blank:before { content: $ionicon-var-android-checkbox-outline-blank; }
-.#{$ionicons-prefix}android-checkmark-circle:before { content: $ionicon-var-android-checkmark-circle; }
-.#{$ionicons-prefix}android-clipboard:before { content: $ionicon-var-android-clipboard; }
-.#{$ionicons-prefix}android-close:before { content: $ionicon-var-android-close; }
-.#{$ionicons-prefix}android-cloud:before { content: $ionicon-var-android-cloud; }
-.#{$ionicons-prefix}android-cloud-circle:before { content: $ionicon-var-android-cloud-circle; }
-.#{$ionicons-prefix}android-cloud-done:before { content: $ionicon-var-android-cloud-done; }
-.#{$ionicons-prefix}android-cloud-outline:before { content: $ionicon-var-android-cloud-outline; }
-.#{$ionicons-prefix}android-color-palette:before { content: $ionicon-var-android-color-palette; }
-.#{$ionicons-prefix}android-compass:before { content: $ionicon-var-android-compass; }
-.#{$ionicons-prefix}android-contact:before { content: $ionicon-var-android-contact; }
-.#{$ionicons-prefix}android-contacts:before { content: $ionicon-var-android-contacts; }
-.#{$ionicons-prefix}android-contract:before { content: $ionicon-var-android-contract; }
-.#{$ionicons-prefix}android-create:before { content: $ionicon-var-android-create; }
-.#{$ionicons-prefix}android-delete:before { content: $ionicon-var-android-delete; }
-.#{$ionicons-prefix}android-desktop:before { content: $ionicon-var-android-desktop; }
-.#{$ionicons-prefix}android-document:before { content: $ionicon-var-android-document; }
-.#{$ionicons-prefix}android-done:before { content: $ionicon-var-android-done; }
-.#{$ionicons-prefix}android-done-all:before { content: $ionicon-var-android-done-all; }
-.#{$ionicons-prefix}android-download:before { content: $ionicon-var-android-download; }
-.#{$ionicons-prefix}android-drafts:before { content: $ionicon-var-android-drafts; }
-.#{$ionicons-prefix}android-exit:before { content: $ionicon-var-android-exit; }
-.#{$ionicons-prefix}android-expand:before { content: $ionicon-var-android-expand; }
-.#{$ionicons-prefix}android-favorite:before { content: $ionicon-var-android-favorite; }
-.#{$ionicons-prefix}android-favorite-outline:before { content: $ionicon-var-android-favorite-outline; }
-.#{$ionicons-prefix}android-film:before { content: $ionicon-var-android-film; }
-.#{$ionicons-prefix}android-folder:before { content: $ionicon-var-android-folder; }
-.#{$ionicons-prefix}android-folder-open:before { content: $ionicon-var-android-folder-open; }
-.#{$ionicons-prefix}android-funnel:before { content: $ionicon-var-android-funnel; }
-.#{$ionicons-prefix}android-globe:before { content: $ionicon-var-android-globe; }
-.#{$ionicons-prefix}android-hand:before { content: $ionicon-var-android-hand; }
-.#{$ionicons-prefix}android-hangout:before { content: $ionicon-var-android-hangout; }
-.#{$ionicons-prefix}android-happy:before { content: $ionicon-var-android-happy; }
-.#{$ionicons-prefix}android-home:before { content: $ionicon-var-android-home; }
-.#{$ionicons-prefix}android-image:before { content: $ionicon-var-android-image; }
-.#{$ionicons-prefix}android-laptop:before { content: $ionicon-var-android-laptop; }
-.#{$ionicons-prefix}android-list:before { content: $ionicon-var-android-list; }
-.#{$ionicons-prefix}android-locate:before { content: $ionicon-var-android-locate; }
-.#{$ionicons-prefix}android-lock:before { content: $ionicon-var-android-lock; }
-.#{$ionicons-prefix}android-mail:before { content: $ionicon-var-android-mail; }
-.#{$ionicons-prefix}android-map:before { content: $ionicon-var-android-map; }
-.#{$ionicons-prefix}android-menu:before { content: $ionicon-var-android-menu; }
-.#{$ionicons-prefix}android-microphone:before { content: $ionicon-var-android-microphone; }
-.#{$ionicons-prefix}android-microphone-off:before { content: $ionicon-var-android-microphone-off; }
-.#{$ionicons-prefix}android-more-horizontal:before { content: $ionicon-var-android-more-horizontal; }
-.#{$ionicons-prefix}android-more-vertical:before { content: $ionicon-var-android-more-vertical; }
-.#{$ionicons-prefix}android-navigate:before { content: $ionicon-var-android-navigate; }
-.#{$ionicons-prefix}android-notifications:before { content: $ionicon-var-android-notifications; }
-.#{$ionicons-prefix}android-notifications-none:before { content: $ionicon-var-android-notifications-none; }
-.#{$ionicons-prefix}android-notifications-off:before { content: $ionicon-var-android-notifications-off; }
-.#{$ionicons-prefix}android-open:before { content: $ionicon-var-android-open; }
-.#{$ionicons-prefix}android-options:before { content: $ionicon-var-android-options; }
-.#{$ionicons-prefix}android-people:before { content: $ionicon-var-android-people; }
-.#{$ionicons-prefix}android-person:before { content: $ionicon-var-android-person; }
-.#{$ionicons-prefix}android-person-add:before { content: $ionicon-var-android-person-add; }
-.#{$ionicons-prefix}android-phone-landscape:before { content: $ionicon-var-android-phone-landscape; }
-.#{$ionicons-prefix}android-phone-portrait:before { content: $ionicon-var-android-phone-portrait; }
-.#{$ionicons-prefix}android-pin:before { content: $ionicon-var-android-pin; }
-.#{$ionicons-prefix}android-plane:before { content: $ionicon-var-android-plane; }
-.#{$ionicons-prefix}android-playstore:before { content: $ionicon-var-android-playstore; }
-.#{$ionicons-prefix}android-print:before { content: $ionicon-var-android-print; }
-.#{$ionicons-prefix}android-radio-button-off:before { content: $ionicon-var-android-radio-button-off; }
-.#{$ionicons-prefix}android-radio-button-on:before { content: $ionicon-var-android-radio-button-on; }
-.#{$ionicons-prefix}android-refresh:before { content: $ionicon-var-android-refresh; }
-.#{$ionicons-prefix}android-remove:before { content: $ionicon-var-android-remove; }
-.#{$ionicons-prefix}android-remove-circle:before { content: $ionicon-var-android-remove-circle; }
-.#{$ionicons-prefix}android-restaurant:before { content: $ionicon-var-android-restaurant; }
-.#{$ionicons-prefix}android-sad:before { content: $ionicon-var-android-sad; }
-.#{$ionicons-prefix}android-search:before { content: $ionicon-var-android-search; }
-.#{$ionicons-prefix}android-send:before { content: $ionicon-var-android-send; }
-.#{$ionicons-prefix}android-settings:before { content: $ionicon-var-android-settings; }
-.#{$ionicons-prefix}android-share:before { content: $ionicon-var-android-share; }
-.#{$ionicons-prefix}android-share-alt:before { content: $ionicon-var-android-share-alt; }
-.#{$ionicons-prefix}android-star:before { content: $ionicon-var-android-star; }
-.#{$ionicons-prefix}android-star-half:before { content: $ionicon-var-android-star-half; }
-.#{$ionicons-prefix}android-star-outline:before { content: $ionicon-var-android-star-outline; }
-.#{$ionicons-prefix}android-stopwatch:before { content: $ionicon-var-android-stopwatch; }
-.#{$ionicons-prefix}android-subway:before { content: $ionicon-var-android-subway; }
-.#{$ionicons-prefix}android-sunny:before { content: $ionicon-var-android-sunny; }
-.#{$ionicons-prefix}android-sync:before { content: $ionicon-var-android-sync; }
-.#{$ionicons-prefix}android-textsms:before { content: $ionicon-var-android-textsms; }
-.#{$ionicons-prefix}android-time:before { content: $ionicon-var-android-time; }
-.#{$ionicons-prefix}android-train:before { content: $ionicon-var-android-train; }
-.#{$ionicons-prefix}android-unlock:before { content: $ionicon-var-android-unlock; }
-.#{$ionicons-prefix}android-upload:before { content: $ionicon-var-android-upload; }
-.#{$ionicons-prefix}android-volume-down:before { content: $ionicon-var-android-volume-down; }
-.#{$ionicons-prefix}android-volume-mute:before { content: $ionicon-var-android-volume-mute; }
-.#{$ionicons-prefix}android-volume-off:before { content: $ionicon-var-android-volume-off; }
-.#{$ionicons-prefix}android-volume-up:before { content: $ionicon-var-android-volume-up; }
-.#{$ionicons-prefix}android-walk:before { content: $ionicon-var-android-walk; }
-.#{$ionicons-prefix}android-warning:before { content: $ionicon-var-android-warning; }
-.#{$ionicons-prefix}android-watch:before { content: $ionicon-var-android-watch; }
-.#{$ionicons-prefix}android-wifi:before { content: $ionicon-var-android-wifi; }
-.#{$ionicons-prefix}aperture:before { content: $ionicon-var-aperture; }
-.#{$ionicons-prefix}archive:before { content: $ionicon-var-archive; }
-.#{$ionicons-prefix}arrow-down-a:before { content: $ionicon-var-arrow-down-a; }
-.#{$ionicons-prefix}arrow-down-b:before { content: $ionicon-var-arrow-down-b; }
-.#{$ionicons-prefix}arrow-down-c:before { content: $ionicon-var-arrow-down-c; }
-.#{$ionicons-prefix}arrow-expand:before { content: $ionicon-var-arrow-expand; }
-.#{$ionicons-prefix}arrow-graph-down-left:before { content: $ionicon-var-arrow-graph-down-left; }
-.#{$ionicons-prefix}arrow-graph-down-right:before { content: $ionicon-var-arrow-graph-down-right; }
-.#{$ionicons-prefix}arrow-graph-up-left:before { content: $ionicon-var-arrow-graph-up-left; }
-.#{$ionicons-prefix}arrow-graph-up-right:before { content: $ionicon-var-arrow-graph-up-right; }
-.#{$ionicons-prefix}arrow-left-a:before { content: $ionicon-var-arrow-left-a; }
-.#{$ionicons-prefix}arrow-left-b:before { content: $ionicon-var-arrow-left-b; }
-.#{$ionicons-prefix}arrow-left-c:before { content: $ionicon-var-arrow-left-c; }
-.#{$ionicons-prefix}arrow-move:before { content: $ionicon-var-arrow-move; }
-.#{$ionicons-prefix}arrow-resize:before { content: $ionicon-var-arrow-resize; }
-.#{$ionicons-prefix}arrow-return-left:before { content: $ionicon-var-arrow-return-left; }
-.#{$ionicons-prefix}arrow-return-right:before { content: $ionicon-var-arrow-return-right; }
-.#{$ionicons-prefix}arrow-right-a:before { content: $ionicon-var-arrow-right-a; }
-.#{$ionicons-prefix}arrow-right-b:before { content: $ionicon-var-arrow-right-b; }
-.#{$ionicons-prefix}arrow-right-c:before { content: $ionicon-var-arrow-right-c; }
-.#{$ionicons-prefix}arrow-shrink:before { content: $ionicon-var-arrow-shrink; }
-.#{$ionicons-prefix}arrow-swap:before { content: $ionicon-var-arrow-swap; }
-.#{$ionicons-prefix}arrow-up-a:before { content: $ionicon-var-arrow-up-a; }
-.#{$ionicons-prefix}arrow-up-b:before { content: $ionicon-var-arrow-up-b; }
-.#{$ionicons-prefix}arrow-up-c:before { content: $ionicon-var-arrow-up-c; }
-.#{$ionicons-prefix}asterisk:before { content: $ionicon-var-asterisk; }
-.#{$ionicons-prefix}at:before { content: $ionicon-var-at; }
-.#{$ionicons-prefix}backspace:before { content: $ionicon-var-backspace; }
-.#{$ionicons-prefix}backspace-outline:before { content: $ionicon-var-backspace-outline; }
-.#{$ionicons-prefix}bag:before { content: $ionicon-var-bag; }
-.#{$ionicons-prefix}battery-charging:before { content: $ionicon-var-battery-charging; }
-.#{$ionicons-prefix}battery-empty:before { content: $ionicon-var-battery-empty; }
-.#{$ionicons-prefix}battery-full:before { content: $ionicon-var-battery-full; }
-.#{$ionicons-prefix}battery-half:before { content: $ionicon-var-battery-half; }
-.#{$ionicons-prefix}battery-low:before { content: $ionicon-var-battery-low; }
-.#{$ionicons-prefix}beaker:before { content: $ionicon-var-beaker; }
-.#{$ionicons-prefix}beer:before { content: $ionicon-var-beer; }
-.#{$ionicons-prefix}bluetooth:before { content: $ionicon-var-bluetooth; }
-.#{$ionicons-prefix}bonfire:before { content: $ionicon-var-bonfire; }
-.#{$ionicons-prefix}bookmark:before { content: $ionicon-var-bookmark; }
-.#{$ionicons-prefix}bowtie:before { content: $ionicon-var-bowtie; }
-.#{$ionicons-prefix}briefcase:before { content: $ionicon-var-briefcase; }
-.#{$ionicons-prefix}bug:before { content: $ionicon-var-bug; }
-.#{$ionicons-prefix}calculator:before { content: $ionicon-var-calculator; }
-.#{$ionicons-prefix}calendar:before { content: $ionicon-var-calendar; }
-.#{$ionicons-prefix}camera:before { content: $ionicon-var-camera; }
-.#{$ionicons-prefix}card:before { content: $ionicon-var-card; }
-.#{$ionicons-prefix}cash:before { content: $ionicon-var-cash; }
-.#{$ionicons-prefix}chatbox:before { content: $ionicon-var-chatbox; }
-.#{$ionicons-prefix}chatbox-working:before { content: $ionicon-var-chatbox-working; }
-.#{$ionicons-prefix}chatboxes:before { content: $ionicon-var-chatboxes; }
-.#{$ionicons-prefix}chatbubble:before { content: $ionicon-var-chatbubble; }
-.#{$ionicons-prefix}chatbubble-working:before { content: $ionicon-var-chatbubble-working; }
-.#{$ionicons-prefix}chatbubbles:before { content: $ionicon-var-chatbubbles; }
-.#{$ionicons-prefix}checkmark:before { content: $ionicon-var-checkmark; }
-.#{$ionicons-prefix}checkmark-circled:before { content: $ionicon-var-checkmark-circled; }
-.#{$ionicons-prefix}checkmark-round:before { content: $ionicon-var-checkmark-round; }
-.#{$ionicons-prefix}chevron-down:before { content: $ionicon-var-chevron-down; }
-.#{$ionicons-prefix}chevron-left:before { content: $ionicon-var-chevron-left; }
-.#{$ionicons-prefix}chevron-right:before { content: $ionicon-var-chevron-right; }
-.#{$ionicons-prefix}chevron-up:before { content: $ionicon-var-chevron-up; }
-.#{$ionicons-prefix}clipboard:before { content: $ionicon-var-clipboard; }
-.#{$ionicons-prefix}clock:before { content: $ionicon-var-clock; }
-.#{$ionicons-prefix}close:before { content: $ionicon-var-close; }
-.#{$ionicons-prefix}close-circled:before { content: $ionicon-var-close-circled; }
-.#{$ionicons-prefix}close-round:before { content: $ionicon-var-close-round; }
-.#{$ionicons-prefix}closed-captioning:before { content: $ionicon-var-closed-captioning; }
-.#{$ionicons-prefix}cloud:before { content: $ionicon-var-cloud; }
-.#{$ionicons-prefix}code:before { content: $ionicon-var-code; }
-.#{$ionicons-prefix}code-download:before { content: $ionicon-var-code-download; }
-.#{$ionicons-prefix}code-working:before { content: $ionicon-var-code-working; }
-.#{$ionicons-prefix}coffee:before { content: $ionicon-var-coffee; }
-.#{$ionicons-prefix}compass:before { content: $ionicon-var-compass; }
-.#{$ionicons-prefix}compose:before { content: $ionicon-var-compose; }
-.#{$ionicons-prefix}connection-bars:before { content: $ionicon-var-connection-bars; }
-.#{$ionicons-prefix}contrast:before { content: $ionicon-var-contrast; }
-.#{$ionicons-prefix}crop:before { content: $ionicon-var-crop; }
-.#{$ionicons-prefix}cube:before { content: $ionicon-var-cube; }
-.#{$ionicons-prefix}disc:before { content: $ionicon-var-disc; }
-.#{$ionicons-prefix}document:before { content: $ionicon-var-document; }
-.#{$ionicons-prefix}document-text:before { content: $ionicon-var-document-text; }
-.#{$ionicons-prefix}drag:before { content: $ionicon-var-drag; }
-.#{$ionicons-prefix}earth:before { content: $ionicon-var-earth; }
-.#{$ionicons-prefix}easel:before { content: $ionicon-var-easel; }
-.#{$ionicons-prefix}edit:before { content: $ionicon-var-edit; }
-.#{$ionicons-prefix}egg:before { content: $ionicon-var-egg; }
-.#{$ionicons-prefix}eject:before { content: $ionicon-var-eject; }
-.#{$ionicons-prefix}email:before { content: $ionicon-var-email; }
-.#{$ionicons-prefix}email-unread:before { content: $ionicon-var-email-unread; }
-.#{$ionicons-prefix}erlenmeyer-flask:before { content: $ionicon-var-erlenmeyer-flask; }
-.#{$ionicons-prefix}erlenmeyer-flask-bubbles:before { content: $ionicon-var-erlenmeyer-flask-bubbles; }
-.#{$ionicons-prefix}eye:before { content: $ionicon-var-eye; }
-.#{$ionicons-prefix}eye-disabled:before { content: $ionicon-var-eye-disabled; }
-.#{$ionicons-prefix}female:before { content: $ionicon-var-female; }
-.#{$ionicons-prefix}filing:before { content: $ionicon-var-filing; }
-.#{$ionicons-prefix}film-marker:before { content: $ionicon-var-film-marker; }
-.#{$ionicons-prefix}fireball:before { content: $ionicon-var-fireball; }
-.#{$ionicons-prefix}flag:before { content: $ionicon-var-flag; }
-.#{$ionicons-prefix}flame:before { content: $ionicon-var-flame; }
-.#{$ionicons-prefix}flash:before { content: $ionicon-var-flash; }
-.#{$ionicons-prefix}flash-off:before { content: $ionicon-var-flash-off; }
-.#{$ionicons-prefix}folder:before { content: $ionicon-var-folder; }
-.#{$ionicons-prefix}fork:before { content: $ionicon-var-fork; }
-.#{$ionicons-prefix}fork-repo:before { content: $ionicon-var-fork-repo; }
-.#{$ionicons-prefix}forward:before { content: $ionicon-var-forward; }
-.#{$ionicons-prefix}funnel:before { content: $ionicon-var-funnel; }
-.#{$ionicons-prefix}gear-a:before { content: $ionicon-var-gear-a; }
-.#{$ionicons-prefix}gear-b:before { content: $ionicon-var-gear-b; }
-.#{$ionicons-prefix}grid:before { content: $ionicon-var-grid; }
-.#{$ionicons-prefix}hammer:before { content: $ionicon-var-hammer; }
-.#{$ionicons-prefix}happy:before { content: $ionicon-var-happy; }
-.#{$ionicons-prefix}happy-outline:before { content: $ionicon-var-happy-outline; }
-.#{$ionicons-prefix}headphone:before { content: $ionicon-var-headphone; }
-.#{$ionicons-prefix}heart:before { content: $ionicon-var-heart; }
-.#{$ionicons-prefix}heart-broken:before { content: $ionicon-var-heart-broken; }
-.#{$ionicons-prefix}help:before { content: $ionicon-var-help; }
-.#{$ionicons-prefix}help-buoy:before { content: $ionicon-var-help-buoy; }
-.#{$ionicons-prefix}help-circled:before { content: $ionicon-var-help-circled; }
-.#{$ionicons-prefix}home:before { content: $ionicon-var-home; }
-.#{$ionicons-prefix}icecream:before { content: $ionicon-var-icecream; }
-.#{$ionicons-prefix}image:before { content: $ionicon-var-image; }
-.#{$ionicons-prefix}images:before { content: $ionicon-var-images; }
-.#{$ionicons-prefix}information:before { content: $ionicon-var-information; }
-.#{$ionicons-prefix}information-circled:before { content: $ionicon-var-information-circled; }
-.#{$ionicons-prefix}ionic:before { content: $ionicon-var-ionic; }
-.#{$ionicons-prefix}ios-alarm:before { content: $ionicon-var-ios-alarm; }
-.#{$ionicons-prefix}ios-alarm-outline:before { content: $ionicon-var-ios-alarm-outline; }
-.#{$ionicons-prefix}ios-albums:before { content: $ionicon-var-ios-albums; }
-.#{$ionicons-prefix}ios-albums-outline:before { content: $ionicon-var-ios-albums-outline; }
-.#{$ionicons-prefix}ios-americanfootball:before { content: $ionicon-var-ios-americanfootball; }
-.#{$ionicons-prefix}ios-americanfootball-outline:before { content: $ionicon-var-ios-americanfootball-outline; }
-.#{$ionicons-prefix}ios-analytics:before { content: $ionicon-var-ios-analytics; }
-.#{$ionicons-prefix}ios-analytics-outline:before { content: $ionicon-var-ios-analytics-outline; }
-.#{$ionicons-prefix}ios-arrow-back:before { content: $ionicon-var-ios-arrow-back; }
-.#{$ionicons-prefix}ios-arrow-down:before { content: $ionicon-var-ios-arrow-down; }
-.#{$ionicons-prefix}ios-arrow-forward:before { content: $ionicon-var-ios-arrow-forward; }
-.#{$ionicons-prefix}ios-arrow-left:before { content: $ionicon-var-ios-arrow-left; }
-.#{$ionicons-prefix}ios-arrow-right:before { content: $ionicon-var-ios-arrow-right; }
-.#{$ionicons-prefix}ios-arrow-thin-down:before { content: $ionicon-var-ios-arrow-thin-down; }
-.#{$ionicons-prefix}ios-arrow-thin-left:before { content: $ionicon-var-ios-arrow-thin-left; }
-.#{$ionicons-prefix}ios-arrow-thin-right:before { content: $ionicon-var-ios-arrow-thin-right; }
-.#{$ionicons-prefix}ios-arrow-thin-up:before { content: $ionicon-var-ios-arrow-thin-up; }
-.#{$ionicons-prefix}ios-arrow-up:before { content: $ionicon-var-ios-arrow-up; }
-.#{$ionicons-prefix}ios-at:before { content: $ionicon-var-ios-at; }
-.#{$ionicons-prefix}ios-at-outline:before { content: $ionicon-var-ios-at-outline; }
-.#{$ionicons-prefix}ios-barcode:before { content: $ionicon-var-ios-barcode; }
-.#{$ionicons-prefix}ios-barcode-outline:before { content: $ionicon-var-ios-barcode-outline; }
-.#{$ionicons-prefix}ios-baseball:before { content: $ionicon-var-ios-baseball; }
-.#{$ionicons-prefix}ios-baseball-outline:before { content: $ionicon-var-ios-baseball-outline; }
-.#{$ionicons-prefix}ios-basketball:before { content: $ionicon-var-ios-basketball; }
-.#{$ionicons-prefix}ios-basketball-outline:before { content: $ionicon-var-ios-basketball-outline; }
-.#{$ionicons-prefix}ios-bell:before { content: $ionicon-var-ios-bell; }
-.#{$ionicons-prefix}ios-bell-outline:before { content: $ionicon-var-ios-bell-outline; }
-.#{$ionicons-prefix}ios-body:before { content: $ionicon-var-ios-body; }
-.#{$ionicons-prefix}ios-body-outline:before { content: $ionicon-var-ios-body-outline; }
-.#{$ionicons-prefix}ios-bolt:before { content: $ionicon-var-ios-bolt; }
-.#{$ionicons-prefix}ios-bolt-outline:before { content: $ionicon-var-ios-bolt-outline; }
-.#{$ionicons-prefix}ios-book:before { content: $ionicon-var-ios-book; }
-.#{$ionicons-prefix}ios-book-outline:before { content: $ionicon-var-ios-book-outline; }
-.#{$ionicons-prefix}ios-bookmarks:before { content: $ionicon-var-ios-bookmarks; }
-.#{$ionicons-prefix}ios-bookmarks-outline:before { content: $ionicon-var-ios-bookmarks-outline; }
-.#{$ionicons-prefix}ios-box:before { content: $ionicon-var-ios-box; }
-.#{$ionicons-prefix}ios-box-outline:before { content: $ionicon-var-ios-box-outline; }
-.#{$ionicons-prefix}ios-briefcase:before { content: $ionicon-var-ios-briefcase; }
-.#{$ionicons-prefix}ios-briefcase-outline:before { content: $ionicon-var-ios-briefcase-outline; }
-.#{$ionicons-prefix}ios-browsers:before { content: $ionicon-var-ios-browsers; }
-.#{$ionicons-prefix}ios-browsers-outline:before { content: $ionicon-var-ios-browsers-outline; }
-.#{$ionicons-prefix}ios-calculator:before { content: $ionicon-var-ios-calculator; }
-.#{$ionicons-prefix}ios-calculator-outline:before { content: $ionicon-var-ios-calculator-outline; }
-.#{$ionicons-prefix}ios-calendar:before { content: $ionicon-var-ios-calendar; }
-.#{$ionicons-prefix}ios-calendar-outline:before { content: $ionicon-var-ios-calendar-outline; }
-.#{$ionicons-prefix}ios-camera:before { content: $ionicon-var-ios-camera; }
-.#{$ionicons-prefix}ios-camera-outline:before { content: $ionicon-var-ios-camera-outline; }
-.#{$ionicons-prefix}ios-cart:before { content: $ionicon-var-ios-cart; }
-.#{$ionicons-prefix}ios-cart-outline:before { content: $ionicon-var-ios-cart-outline; }
-.#{$ionicons-prefix}ios-chatboxes:before { content: $ionicon-var-ios-chatboxes; }
-.#{$ionicons-prefix}ios-chatboxes-outline:before { content: $ionicon-var-ios-chatboxes-outline; }
-.#{$ionicons-prefix}ios-chatbubble:before { content: $ionicon-var-ios-chatbubble; }
-.#{$ionicons-prefix}ios-chatbubble-outline:before { content: $ionicon-var-ios-chatbubble-outline; }
-.#{$ionicons-prefix}ios-checkmark:before { content: $ionicon-var-ios-checkmark; }
-.#{$ionicons-prefix}ios-checkmark-empty:before { content: $ionicon-var-ios-checkmark-empty; }
-.#{$ionicons-prefix}ios-checkmark-outline:before { content: $ionicon-var-ios-checkmark-outline; }
-.#{$ionicons-prefix}ios-circle-filled:before { content: $ionicon-var-ios-circle-filled; }
-.#{$ionicons-prefix}ios-circle-outline:before { content: $ionicon-var-ios-circle-outline; }
-.#{$ionicons-prefix}ios-clock:before { content: $ionicon-var-ios-clock; }
-.#{$ionicons-prefix}ios-clock-outline:before { content: $ionicon-var-ios-clock-outline; }
-.#{$ionicons-prefix}ios-close:before { content: $ionicon-var-ios-close; }
-.#{$ionicons-prefix}ios-close-empty:before { content: $ionicon-var-ios-close-empty; }
-.#{$ionicons-prefix}ios-close-outline:before { content: $ionicon-var-ios-close-outline; }
-.#{$ionicons-prefix}ios-cloud:before { content: $ionicon-var-ios-cloud; }
-.#{$ionicons-prefix}ios-cloud-download:before { content: $ionicon-var-ios-cloud-download; }
-.#{$ionicons-prefix}ios-cloud-download-outline:before { content: $ionicon-var-ios-cloud-download-outline; }
-.#{$ionicons-prefix}ios-cloud-outline:before { content: $ionicon-var-ios-cloud-outline; }
-.#{$ionicons-prefix}ios-cloud-upload:before { content: $ionicon-var-ios-cloud-upload; }
-.#{$ionicons-prefix}ios-cloud-upload-outline:before { content: $ionicon-var-ios-cloud-upload-outline; }
-.#{$ionicons-prefix}ios-cloudy:before { content: $ionicon-var-ios-cloudy; }
-.#{$ionicons-prefix}ios-cloudy-night:before { content: $ionicon-var-ios-cloudy-night; }
-.#{$ionicons-prefix}ios-cloudy-night-outline:before { content: $ionicon-var-ios-cloudy-night-outline; }
-.#{$ionicons-prefix}ios-cloudy-outline:before { content: $ionicon-var-ios-cloudy-outline; }
-.#{$ionicons-prefix}ios-cog:before { content: $ionicon-var-ios-cog; }
-.#{$ionicons-prefix}ios-cog-outline:before { content: $ionicon-var-ios-cog-outline; }
-.#{$ionicons-prefix}ios-color-filter:before { content: $ionicon-var-ios-color-filter; }
-.#{$ionicons-prefix}ios-color-filter-outline:before { content: $ionicon-var-ios-color-filter-outline; }
-.#{$ionicons-prefix}ios-color-wand:before { content: $ionicon-var-ios-color-wand; }
-.#{$ionicons-prefix}ios-color-wand-outline:before { content: $ionicon-var-ios-color-wand-outline; }
-.#{$ionicons-prefix}ios-compose:before { content: $ionicon-var-ios-compose; }
-.#{$ionicons-prefix}ios-compose-outline:before { content: $ionicon-var-ios-compose-outline; }
-.#{$ionicons-prefix}ios-contact:before { content: $ionicon-var-ios-contact; }
-.#{$ionicons-prefix}ios-contact-outline:before { content: $ionicon-var-ios-contact-outline; }
-.#{$ionicons-prefix}ios-copy:before { content: $ionicon-var-ios-copy; }
-.#{$ionicons-prefix}ios-copy-outline:before { content: $ionicon-var-ios-copy-outline; }
-.#{$ionicons-prefix}ios-crop:before { content: $ionicon-var-ios-crop; }
-.#{$ionicons-prefix}ios-crop-strong:before { content: $ionicon-var-ios-crop-strong; }
-.#{$ionicons-prefix}ios-download:before { content: $ionicon-var-ios-download; }
-.#{$ionicons-prefix}ios-download-outline:before { content: $ionicon-var-ios-download-outline; }
-.#{$ionicons-prefix}ios-drag:before { content: $ionicon-var-ios-drag; }
-.#{$ionicons-prefix}ios-email:before { content: $ionicon-var-ios-email; }
-.#{$ionicons-prefix}ios-email-outline:before { content: $ionicon-var-ios-email-outline; }
-.#{$ionicons-prefix}ios-eye:before { content: $ionicon-var-ios-eye; }
-.#{$ionicons-prefix}ios-eye-outline:before { content: $ionicon-var-ios-eye-outline; }
-.#{$ionicons-prefix}ios-fastforward:before { content: $ionicon-var-ios-fastforward; }
-.#{$ionicons-prefix}ios-fastforward-outline:before { content: $ionicon-var-ios-fastforward-outline; }
-.#{$ionicons-prefix}ios-filing:before { content: $ionicon-var-ios-filing; }
-.#{$ionicons-prefix}ios-filing-outline:before { content: $ionicon-var-ios-filing-outline; }
-.#{$ionicons-prefix}ios-film:before { content: $ionicon-var-ios-film; }
-.#{$ionicons-prefix}ios-film-outline:before { content: $ionicon-var-ios-film-outline; }
-.#{$ionicons-prefix}ios-flag:before { content: $ionicon-var-ios-flag; }
-.#{$ionicons-prefix}ios-flag-outline:before { content: $ionicon-var-ios-flag-outline; }
-.#{$ionicons-prefix}ios-flame:before { content: $ionicon-var-ios-flame; }
-.#{$ionicons-prefix}ios-flame-outline:before { content: $ionicon-var-ios-flame-outline; }
-.#{$ionicons-prefix}ios-flask:before { content: $ionicon-var-ios-flask; }
-.#{$ionicons-prefix}ios-flask-outline:before { content: $ionicon-var-ios-flask-outline; }
-.#{$ionicons-prefix}ios-flower:before { content: $ionicon-var-ios-flower; }
-.#{$ionicons-prefix}ios-flower-outline:before { content: $ionicon-var-ios-flower-outline; }
-.#{$ionicons-prefix}ios-folder:before { content: $ionicon-var-ios-folder; }
-.#{$ionicons-prefix}ios-folder-outline:before { content: $ionicon-var-ios-folder-outline; }
-.#{$ionicons-prefix}ios-football:before { content: $ionicon-var-ios-football; }
-.#{$ionicons-prefix}ios-football-outline:before { content: $ionicon-var-ios-football-outline; }
-.#{$ionicons-prefix}ios-game-controller-a:before { content: $ionicon-var-ios-game-controller-a; }
-.#{$ionicons-prefix}ios-game-controller-a-outline:before { content: $ionicon-var-ios-game-controller-a-outline; }
-.#{$ionicons-prefix}ios-game-controller-b:before { content: $ionicon-var-ios-game-controller-b; }
-.#{$ionicons-prefix}ios-game-controller-b-outline:before { content: $ionicon-var-ios-game-controller-b-outline; }
-.#{$ionicons-prefix}ios-gear:before { content: $ionicon-var-ios-gear; }
-.#{$ionicons-prefix}ios-gear-outline:before { content: $ionicon-var-ios-gear-outline; }
-.#{$ionicons-prefix}ios-glasses:before { content: $ionicon-var-ios-glasses; }
-.#{$ionicons-prefix}ios-glasses-outline:before { content: $ionicon-var-ios-glasses-outline; }
-.#{$ionicons-prefix}ios-grid-view:before { content: $ionicon-var-ios-grid-view; }
-.#{$ionicons-prefix}ios-grid-view-outline:before { content: $ionicon-var-ios-grid-view-outline; }
-.#{$ionicons-prefix}ios-heart:before { content: $ionicon-var-ios-heart; }
-.#{$ionicons-prefix}ios-heart-outline:before { content: $ionicon-var-ios-heart-outline; }
-.#{$ionicons-prefix}ios-help:before { content: $ionicon-var-ios-help; }
-.#{$ionicons-prefix}ios-help-empty:before { content: $ionicon-var-ios-help-empty; }
-.#{$ionicons-prefix}ios-help-outline:before { content: $ionicon-var-ios-help-outline; }
-.#{$ionicons-prefix}ios-home:before { content: $ionicon-var-ios-home; }
-.#{$ionicons-prefix}ios-home-outline:before { content: $ionicon-var-ios-home-outline; }
-.#{$ionicons-prefix}ios-infinite:before { content: $ionicon-var-ios-infinite; }
-.#{$ionicons-prefix}ios-infinite-outline:before { content: $ionicon-var-ios-infinite-outline; }
-.#{$ionicons-prefix}ios-information:before { content: $ionicon-var-ios-information; }
-.#{$ionicons-prefix}ios-information-empty:before { content: $ionicon-var-ios-information-empty; }
-.#{$ionicons-prefix}ios-information-outline:before { content: $ionicon-var-ios-information-outline; }
-.#{$ionicons-prefix}ios-ionic-outline:before { content: $ionicon-var-ios-ionic-outline; }
-.#{$ionicons-prefix}ios-keypad:before { content: $ionicon-var-ios-keypad; }
-.#{$ionicons-prefix}ios-keypad-outline:before { content: $ionicon-var-ios-keypad-outline; }
-.#{$ionicons-prefix}ios-lightbulb:before { content: $ionicon-var-ios-lightbulb; }
-.#{$ionicons-prefix}ios-lightbulb-outline:before { content: $ionicon-var-ios-lightbulb-outline; }
-.#{$ionicons-prefix}ios-list:before { content: $ionicon-var-ios-list; }
-.#{$ionicons-prefix}ios-list-outline:before { content: $ionicon-var-ios-list-outline; }
-.#{$ionicons-prefix}ios-location:before { content: $ionicon-var-ios-location; }
-.#{$ionicons-prefix}ios-location-outline:before { content: $ionicon-var-ios-location-outline; }
-.#{$ionicons-prefix}ios-locked:before { content: $ionicon-var-ios-locked; }
-.#{$ionicons-prefix}ios-locked-outline:before { content: $ionicon-var-ios-locked-outline; }
-.#{$ionicons-prefix}ios-loop:before { content: $ionicon-var-ios-loop; }
-.#{$ionicons-prefix}ios-loop-strong:before { content: $ionicon-var-ios-loop-strong; }
-.#{$ionicons-prefix}ios-medical:before { content: $ionicon-var-ios-medical; }
-.#{$ionicons-prefix}ios-medical-outline:before { content: $ionicon-var-ios-medical-outline; }
-.#{$ionicons-prefix}ios-medkit:before { content: $ionicon-var-ios-medkit; }
-.#{$ionicons-prefix}ios-medkit-outline:before { content: $ionicon-var-ios-medkit-outline; }
-.#{$ionicons-prefix}ios-mic:before { content: $ionicon-var-ios-mic; }
-.#{$ionicons-prefix}ios-mic-off:before { content: $ionicon-var-ios-mic-off; }
-.#{$ionicons-prefix}ios-mic-outline:before { content: $ionicon-var-ios-mic-outline; }
-.#{$ionicons-prefix}ios-minus:before { content: $ionicon-var-ios-minus; }
-.#{$ionicons-prefix}ios-minus-empty:before { content: $ionicon-var-ios-minus-empty; }
-.#{$ionicons-prefix}ios-minus-outline:before { content: $ionicon-var-ios-minus-outline; }
-.#{$ionicons-prefix}ios-monitor:before { content: $ionicon-var-ios-monitor; }
-.#{$ionicons-prefix}ios-monitor-outline:before { content: $ionicon-var-ios-monitor-outline; }
-.#{$ionicons-prefix}ios-moon:before { content: $ionicon-var-ios-moon; }
-.#{$ionicons-prefix}ios-moon-outline:before { content: $ionicon-var-ios-moon-outline; }
-.#{$ionicons-prefix}ios-more:before { content: $ionicon-var-ios-more; }
-.#{$ionicons-prefix}ios-more-outline:before { content: $ionicon-var-ios-more-outline; }
-.#{$ionicons-prefix}ios-musical-note:before { content: $ionicon-var-ios-musical-note; }
-.#{$ionicons-prefix}ios-musical-notes:before { content: $ionicon-var-ios-musical-notes; }
-.#{$ionicons-prefix}ios-navigate:before { content: $ionicon-var-ios-navigate; }
-.#{$ionicons-prefix}ios-navigate-outline:before { content: $ionicon-var-ios-navigate-outline; }
-.#{$ionicons-prefix}ios-nutrition:before { content: $ionicon-var-ios-nutrition; }
-.#{$ionicons-prefix}ios-nutrition-outline:before { content: $ionicon-var-ios-nutrition-outline; }
-.#{$ionicons-prefix}ios-paper:before { content: $ionicon-var-ios-paper; }
-.#{$ionicons-prefix}ios-paper-outline:before { content: $ionicon-var-ios-paper-outline; }
-.#{$ionicons-prefix}ios-paperplane:before { content: $ionicon-var-ios-paperplane; }
-.#{$ionicons-prefix}ios-paperplane-outline:before { content: $ionicon-var-ios-paperplane-outline; }
-.#{$ionicons-prefix}ios-partlysunny:before { content: $ionicon-var-ios-partlysunny; }
-.#{$ionicons-prefix}ios-partlysunny-outline:before { content: $ionicon-var-ios-partlysunny-outline; }
-.#{$ionicons-prefix}ios-pause:before { content: $ionicon-var-ios-pause; }
-.#{$ionicons-prefix}ios-pause-outline:before { content: $ionicon-var-ios-pause-outline; }
-.#{$ionicons-prefix}ios-paw:before { content: $ionicon-var-ios-paw; }
-.#{$ionicons-prefix}ios-paw-outline:before { content: $ionicon-var-ios-paw-outline; }
-.#{$ionicons-prefix}ios-people:before { content: $ionicon-var-ios-people; }
-.#{$ionicons-prefix}ios-people-outline:before { content: $ionicon-var-ios-people-outline; }
-.#{$ionicons-prefix}ios-person:before { content: $ionicon-var-ios-person; }
-.#{$ionicons-prefix}ios-person-outline:before { content: $ionicon-var-ios-person-outline; }
-.#{$ionicons-prefix}ios-personadd:before { content: $ionicon-var-ios-personadd; }
-.#{$ionicons-prefix}ios-personadd-outline:before { content: $ionicon-var-ios-personadd-outline; }
-.#{$ionicons-prefix}ios-photos:before { content: $ionicon-var-ios-photos; }
-.#{$ionicons-prefix}ios-photos-outline:before { content: $ionicon-var-ios-photos-outline; }
-.#{$ionicons-prefix}ios-pie:before { content: $ionicon-var-ios-pie; }
-.#{$ionicons-prefix}ios-pie-outline:before { content: $ionicon-var-ios-pie-outline; }
-.#{$ionicons-prefix}ios-pint:before { content: $ionicon-var-ios-pint; }
-.#{$ionicons-prefix}ios-pint-outline:before { content: $ionicon-var-ios-pint-outline; }
-.#{$ionicons-prefix}ios-play:before { content: $ionicon-var-ios-play; }
-.#{$ionicons-prefix}ios-play-outline:before { content: $ionicon-var-ios-play-outline; }
-.#{$ionicons-prefix}ios-plus:before { content: $ionicon-var-ios-plus; }
-.#{$ionicons-prefix}ios-plus-empty:before { content: $ionicon-var-ios-plus-empty; }
-.#{$ionicons-prefix}ios-plus-outline:before { content: $ionicon-var-ios-plus-outline; }
-.#{$ionicons-prefix}ios-pricetag:before { content: $ionicon-var-ios-pricetag; }
-.#{$ionicons-prefix}ios-pricetag-outline:before { content: $ionicon-var-ios-pricetag-outline; }
-.#{$ionicons-prefix}ios-pricetags:before { content: $ionicon-var-ios-pricetags; }
-.#{$ionicons-prefix}ios-pricetags-outline:before { content: $ionicon-var-ios-pricetags-outline; }
-.#{$ionicons-prefix}ios-printer:before { content: $ionicon-var-ios-printer; }
-.#{$ionicons-prefix}ios-printer-outline:before { content: $ionicon-var-ios-printer-outline; }
-.#{$ionicons-prefix}ios-pulse:before { content: $ionicon-var-ios-pulse; }
-.#{$ionicons-prefix}ios-pulse-strong:before { content: $ionicon-var-ios-pulse-strong; }
-.#{$ionicons-prefix}ios-rainy:before { content: $ionicon-var-ios-rainy; }
-.#{$ionicons-prefix}ios-rainy-outline:before { content: $ionicon-var-ios-rainy-outline; }
-.#{$ionicons-prefix}ios-recording:before { content: $ionicon-var-ios-recording; }
-.#{$ionicons-prefix}ios-recording-outline:before { content: $ionicon-var-ios-recording-outline; }
-.#{$ionicons-prefix}ios-redo:before { content: $ionicon-var-ios-redo; }
-.#{$ionicons-prefix}ios-redo-outline:before { content: $ionicon-var-ios-redo-outline; }
-.#{$ionicons-prefix}ios-refresh:before { content: $ionicon-var-ios-refresh; }
-.#{$ionicons-prefix}ios-refresh-empty:before { content: $ionicon-var-ios-refresh-empty; }
-.#{$ionicons-prefix}ios-refresh-outline:before { content: $ionicon-var-ios-refresh-outline; }
-.#{$ionicons-prefix}ios-reload:before { content: $ionicon-var-ios-reload; }
-.#{$ionicons-prefix}ios-reverse-camera:before { content: $ionicon-var-ios-reverse-camera; }
-.#{$ionicons-prefix}ios-reverse-camera-outline:before { content: $ionicon-var-ios-reverse-camera-outline; }
-.#{$ionicons-prefix}ios-rewind:before { content: $ionicon-var-ios-rewind; }
-.#{$ionicons-prefix}ios-rewind-outline:before { content: $ionicon-var-ios-rewind-outline; }
-.#{$ionicons-prefix}ios-rose:before { content: $ionicon-var-ios-rose; }
-.#{$ionicons-prefix}ios-rose-outline:before { content: $ionicon-var-ios-rose-outline; }
-.#{$ionicons-prefix}ios-search:before { content: $ionicon-var-ios-search; }
-.#{$ionicons-prefix}ios-search-strong:before { content: $ionicon-var-ios-search-strong; }
-.#{$ionicons-prefix}ios-settings:before { content: $ionicon-var-ios-settings; }
-.#{$ionicons-prefix}ios-settings-strong:before { content: $ionicon-var-ios-settings-strong; }
-.#{$ionicons-prefix}ios-shuffle:before { content: $ionicon-var-ios-shuffle; }
-.#{$ionicons-prefix}ios-shuffle-strong:before { content: $ionicon-var-ios-shuffle-strong; }
-.#{$ionicons-prefix}ios-skipbackward:before { content: $ionicon-var-ios-skipbackward; }
-.#{$ionicons-prefix}ios-skipbackward-outline:before { content: $ionicon-var-ios-skipbackward-outline; }
-.#{$ionicons-prefix}ios-skipforward:before { content: $ionicon-var-ios-skipforward; }
-.#{$ionicons-prefix}ios-skipforward-outline:before { content: $ionicon-var-ios-skipforward-outline; }
-.#{$ionicons-prefix}ios-snowy:before { content: $ionicon-var-ios-snowy; }
-.#{$ionicons-prefix}ios-speedometer:before { content: $ionicon-var-ios-speedometer; }
-.#{$ionicons-prefix}ios-speedometer-outline:before { content: $ionicon-var-ios-speedometer-outline; }
-.#{$ionicons-prefix}ios-star:before { content: $ionicon-var-ios-star; }
-.#{$ionicons-prefix}ios-star-half:before { content: $ionicon-var-ios-star-half; }
-.#{$ionicons-prefix}ios-star-outline:before { content: $ionicon-var-ios-star-outline; }
-.#{$ionicons-prefix}ios-stopwatch:before { content: $ionicon-var-ios-stopwatch; }
-.#{$ionicons-prefix}ios-stopwatch-outline:before { content: $ionicon-var-ios-stopwatch-outline; }
-.#{$ionicons-prefix}ios-sunny:before { content: $ionicon-var-ios-sunny; }
-.#{$ionicons-prefix}ios-sunny-outline:before { content: $ionicon-var-ios-sunny-outline; }
-.#{$ionicons-prefix}ios-telephone:before { content: $ionicon-var-ios-telephone; }
-.#{$ionicons-prefix}ios-telephone-outline:before { content: $ionicon-var-ios-telephone-outline; }
-.#{$ionicons-prefix}ios-tennisball:before { content: $ionicon-var-ios-tennisball; }
-.#{$ionicons-prefix}ios-tennisball-outline:before { content: $ionicon-var-ios-tennisball-outline; }
-.#{$ionicons-prefix}ios-thunderstorm:before { content: $ionicon-var-ios-thunderstorm; }
-.#{$ionicons-prefix}ios-thunderstorm-outline:before { content: $ionicon-var-ios-thunderstorm-outline; }
-.#{$ionicons-prefix}ios-time:before { content: $ionicon-var-ios-time; }
-.#{$ionicons-prefix}ios-time-outline:before { content: $ionicon-var-ios-time-outline; }
-.#{$ionicons-prefix}ios-timer:before { content: $ionicon-var-ios-timer; }
-.#{$ionicons-prefix}ios-timer-outline:before { content: $ionicon-var-ios-timer-outline; }
-.#{$ionicons-prefix}ios-toggle:before { content: $ionicon-var-ios-toggle; }
-.#{$ionicons-prefix}ios-toggle-outline:before { content: $ionicon-var-ios-toggle-outline; }
-.#{$ionicons-prefix}ios-trash:before { content: $ionicon-var-ios-trash; }
-.#{$ionicons-prefix}ios-trash-outline:before { content: $ionicon-var-ios-trash-outline; }
-.#{$ionicons-prefix}ios-undo:before { content: $ionicon-var-ios-undo; }
-.#{$ionicons-prefix}ios-undo-outline:before { content: $ionicon-var-ios-undo-outline; }
-.#{$ionicons-prefix}ios-unlocked:before { content: $ionicon-var-ios-unlocked; }
-.#{$ionicons-prefix}ios-unlocked-outline:before { content: $ionicon-var-ios-unlocked-outline; }
-.#{$ionicons-prefix}ios-upload:before { content: $ionicon-var-ios-upload; }
-.#{$ionicons-prefix}ios-upload-outline:before { content: $ionicon-var-ios-upload-outline; }
-.#{$ionicons-prefix}ios-videocam:before { content: $ionicon-var-ios-videocam; }
-.#{$ionicons-prefix}ios-videocam-outline:before { content: $ionicon-var-ios-videocam-outline; }
-.#{$ionicons-prefix}ios-volume-high:before { content: $ionicon-var-ios-volume-high; }
-.#{$ionicons-prefix}ios-volume-low:before { content: $ionicon-var-ios-volume-low; }
-.#{$ionicons-prefix}ios-wineglass:before { content: $ionicon-var-ios-wineglass; }
-.#{$ionicons-prefix}ios-wineglass-outline:before { content: $ionicon-var-ios-wineglass-outline; }
-.#{$ionicons-prefix}ios-world:before { content: $ionicon-var-ios-world; }
-.#{$ionicons-prefix}ios-world-outline:before { content: $ionicon-var-ios-world-outline; }
-.#{$ionicons-prefix}ipad:before { content: $ionicon-var-ipad; }
-.#{$ionicons-prefix}iphone:before { content: $ionicon-var-iphone; }
-.#{$ionicons-prefix}ipod:before { content: $ionicon-var-ipod; }
-.#{$ionicons-prefix}jet:before { content: $ionicon-var-jet; }
-.#{$ionicons-prefix}key:before { content: $ionicon-var-key; }
-.#{$ionicons-prefix}knife:before { content: $ionicon-var-knife; }
-.#{$ionicons-prefix}laptop:before { content: $ionicon-var-laptop; }
-.#{$ionicons-prefix}leaf:before { content: $ionicon-var-leaf; }
-.#{$ionicons-prefix}levels:before { content: $ionicon-var-levels; }
-.#{$ionicons-prefix}lightbulb:before { content: $ionicon-var-lightbulb; }
-.#{$ionicons-prefix}link:before { content: $ionicon-var-link; }
-.#{$ionicons-prefix}load-a:before { content: $ionicon-var-load-a; }
-.#{$ionicons-prefix}load-b:before { content: $ionicon-var-load-b; }
-.#{$ionicons-prefix}load-c:before { content: $ionicon-var-load-c; }
-.#{$ionicons-prefix}load-d:before { content: $ionicon-var-load-d; }
-.#{$ionicons-prefix}location:before { content: $ionicon-var-location; }
-.#{$ionicons-prefix}lock-combination:before { content: $ionicon-var-lock-combination; }
-.#{$ionicons-prefix}locked:before { content: $ionicon-var-locked; }
-.#{$ionicons-prefix}log-in:before { content: $ionicon-var-log-in; }
-.#{$ionicons-prefix}log-out:before { content: $ionicon-var-log-out; }
-.#{$ionicons-prefix}loop:before { content: $ionicon-var-loop; }
-.#{$ionicons-prefix}magnet:before { content: $ionicon-var-magnet; }
-.#{$ionicons-prefix}male:before { content: $ionicon-var-male; }
-.#{$ionicons-prefix}man:before { content: $ionicon-var-man; }
-.#{$ionicons-prefix}map:before { content: $ionicon-var-map; }
-.#{$ionicons-prefix}medkit:before { content: $ionicon-var-medkit; }
-.#{$ionicons-prefix}merge:before { content: $ionicon-var-merge; }
-.#{$ionicons-prefix}mic-a:before { content: $ionicon-var-mic-a; }
-.#{$ionicons-prefix}mic-b:before { content: $ionicon-var-mic-b; }
-.#{$ionicons-prefix}mic-c:before { content: $ionicon-var-mic-c; }
-.#{$ionicons-prefix}minus:before { content: $ionicon-var-minus; }
-.#{$ionicons-prefix}minus-circled:before { content: $ionicon-var-minus-circled; }
-.#{$ionicons-prefix}minus-round:before { content: $ionicon-var-minus-round; }
-.#{$ionicons-prefix}model-s:before { content: $ionicon-var-model-s; }
-.#{$ionicons-prefix}monitor:before { content: $ionicon-var-monitor; }
-.#{$ionicons-prefix}more:before { content: $ionicon-var-more; }
-.#{$ionicons-prefix}mouse:before { content: $ionicon-var-mouse; }
-.#{$ionicons-prefix}music-note:before { content: $ionicon-var-music-note; }
-.#{$ionicons-prefix}navicon:before { content: $ionicon-var-navicon; }
-.#{$ionicons-prefix}navicon-round:before { content: $ionicon-var-navicon-round; }
-.#{$ionicons-prefix}navigate:before { content: $ionicon-var-navigate; }
-.#{$ionicons-prefix}network:before { content: $ionicon-var-network; }
-.#{$ionicons-prefix}no-smoking:before { content: $ionicon-var-no-smoking; }
-.#{$ionicons-prefix}nuclear:before { content: $ionicon-var-nuclear; }
-.#{$ionicons-prefix}outlet:before { content: $ionicon-var-outlet; }
-.#{$ionicons-prefix}paintbrush:before { content: $ionicon-var-paintbrush; }
-.#{$ionicons-prefix}paintbucket:before { content: $ionicon-var-paintbucket; }
-.#{$ionicons-prefix}paper-airplane:before { content: $ionicon-var-paper-airplane; }
-.#{$ionicons-prefix}paperclip:before { content: $ionicon-var-paperclip; }
-.#{$ionicons-prefix}pause:before { content: $ionicon-var-pause; }
-.#{$ionicons-prefix}person:before { content: $ionicon-var-person; }
-.#{$ionicons-prefix}person-add:before { content: $ionicon-var-person-add; }
-.#{$ionicons-prefix}person-stalker:before { content: $ionicon-var-person-stalker; }
-.#{$ionicons-prefix}pie-graph:before { content: $ionicon-var-pie-graph; }
-.#{$ionicons-prefix}pin:before { content: $ionicon-var-pin; }
-.#{$ionicons-prefix}pinpoint:before { content: $ionicon-var-pinpoint; }
-.#{$ionicons-prefix}pizza:before { content: $ionicon-var-pizza; }
-.#{$ionicons-prefix}plane:before { content: $ionicon-var-plane; }
-.#{$ionicons-prefix}planet:before { content: $ionicon-var-planet; }
-.#{$ionicons-prefix}play:before { content: $ionicon-var-play; }
-.#{$ionicons-prefix}playstation:before { content: $ionicon-var-playstation; }
-.#{$ionicons-prefix}plus:before { content: $ionicon-var-plus; }
-.#{$ionicons-prefix}plus-circled:before { content: $ionicon-var-plus-circled; }
-.#{$ionicons-prefix}plus-round:before { content: $ionicon-var-plus-round; }
-.#{$ionicons-prefix}podium:before { content: $ionicon-var-podium; }
-.#{$ionicons-prefix}pound:before { content: $ionicon-var-pound; }
-.#{$ionicons-prefix}power:before { content: $ionicon-var-power; }
-.#{$ionicons-prefix}pricetag:before { content: $ionicon-var-pricetag; }
-.#{$ionicons-prefix}pricetags:before { content: $ionicon-var-pricetags; }
-.#{$ionicons-prefix}printer:before { content: $ionicon-var-printer; }
-.#{$ionicons-prefix}pull-request:before { content: $ionicon-var-pull-request; }
-.#{$ionicons-prefix}qr-scanner:before { content: $ionicon-var-qr-scanner; }
-.#{$ionicons-prefix}quote:before { content: $ionicon-var-quote; }
-.#{$ionicons-prefix}radio-waves:before { content: $ionicon-var-radio-waves; }
-.#{$ionicons-prefix}record:before { content: $ionicon-var-record; }
-.#{$ionicons-prefix}refresh:before { content: $ionicon-var-refresh; }
-.#{$ionicons-prefix}reply:before { content: $ionicon-var-reply; }
-.#{$ionicons-prefix}reply-all:before { content: $ionicon-var-reply-all; }
-.#{$ionicons-prefix}ribbon-a:before { content: $ionicon-var-ribbon-a; }
-.#{$ionicons-prefix}ribbon-b:before { content: $ionicon-var-ribbon-b; }
-.#{$ionicons-prefix}sad:before { content: $ionicon-var-sad; }
-.#{$ionicons-prefix}sad-outline:before { content: $ionicon-var-sad-outline; }
-.#{$ionicons-prefix}scissors:before { content: $ionicon-var-scissors; }
-.#{$ionicons-prefix}search:before { content: $ionicon-var-search; }
-.#{$ionicons-prefix}settings:before { content: $ionicon-var-settings; }
-.#{$ionicons-prefix}share:before { content: $ionicon-var-share; }
-.#{$ionicons-prefix}shuffle:before { content: $ionicon-var-shuffle; }
-.#{$ionicons-prefix}skip-backward:before { content: $ionicon-var-skip-backward; }
-.#{$ionicons-prefix}skip-forward:before { content: $ionicon-var-skip-forward; }
-.#{$ionicons-prefix}social-android:before { content: $ionicon-var-social-android; }
-.#{$ionicons-prefix}social-android-outline:before { content: $ionicon-var-social-android-outline; }
-.#{$ionicons-prefix}social-angular:before { content: $ionicon-var-social-angular; }
-.#{$ionicons-prefix}social-angular-outline:before { content: $ionicon-var-social-angular-outline; }
-.#{$ionicons-prefix}social-apple:before { content: $ionicon-var-social-apple; }
-.#{$ionicons-prefix}social-apple-outline:before { content: $ionicon-var-social-apple-outline; }
-.#{$ionicons-prefix}social-bitcoin:before { content: $ionicon-var-social-bitcoin; }
-.#{$ionicons-prefix}social-bitcoin-outline:before { content: $ionicon-var-social-bitcoin-outline; }
-.#{$ionicons-prefix}social-buffer:before { content: $ionicon-var-social-buffer; }
-.#{$ionicons-prefix}social-buffer-outline:before { content: $ionicon-var-social-buffer-outline; }
-.#{$ionicons-prefix}social-chrome:before { content: $ionicon-var-social-chrome; }
-.#{$ionicons-prefix}social-chrome-outline:before { content: $ionicon-var-social-chrome-outline; }
-.#{$ionicons-prefix}social-codepen:before { content: $ionicon-var-social-codepen; }
-.#{$ionicons-prefix}social-codepen-outline:before { content: $ionicon-var-social-codepen-outline; }
-.#{$ionicons-prefix}social-css3:before { content: $ionicon-var-social-css3; }
-.#{$ionicons-prefix}social-css3-outline:before { content: $ionicon-var-social-css3-outline; }
-.#{$ionicons-prefix}social-designernews:before { content: $ionicon-var-social-designernews; }
-.#{$ionicons-prefix}social-designernews-outline:before { content: $ionicon-var-social-designernews-outline; }
-.#{$ionicons-prefix}social-dribbble:before { content: $ionicon-var-social-dribbble; }
-.#{$ionicons-prefix}social-dribbble-outline:before { content: $ionicon-var-social-dribbble-outline; }
-.#{$ionicons-prefix}social-dropbox:before { content: $ionicon-var-social-dropbox; }
-.#{$ionicons-prefix}social-dropbox-outline:before { content: $ionicon-var-social-dropbox-outline; }
-.#{$ionicons-prefix}social-euro:before { content: $ionicon-var-social-euro; }
-.#{$ionicons-prefix}social-euro-outline:before { content: $ionicon-var-social-euro-outline; }
-.#{$ionicons-prefix}social-facebook:before { content: $ionicon-var-social-facebook; }
-.#{$ionicons-prefix}social-facebook-outline:before { content: $ionicon-var-social-facebook-outline; }
-.#{$ionicons-prefix}social-foursquare:before { content: $ionicon-var-social-foursquare; }
-.#{$ionicons-prefix}social-foursquare-outline:before { content: $ionicon-var-social-foursquare-outline; }
-.#{$ionicons-prefix}social-freebsd-devil:before { content: $ionicon-var-social-freebsd-devil; }
-.#{$ionicons-prefix}social-github:before { content: $ionicon-var-social-github; }
-.#{$ionicons-prefix}social-github-outline:before { content: $ionicon-var-social-github-outline; }
-.#{$ionicons-prefix}social-google:before { content: $ionicon-var-social-google; }
-.#{$ionicons-prefix}social-google-outline:before { content: $ionicon-var-social-google-outline; }
-.#{$ionicons-prefix}social-googleplus:before { content: $ionicon-var-social-googleplus; }
-.#{$ionicons-prefix}social-googleplus-outline:before { content: $ionicon-var-social-googleplus-outline; }
-.#{$ionicons-prefix}social-hackernews:before { content: $ionicon-var-social-hackernews; }
-.#{$ionicons-prefix}social-hackernews-outline:before { content: $ionicon-var-social-hackernews-outline; }
-.#{$ionicons-prefix}social-html5:before { content: $ionicon-var-social-html5; }
-.#{$ionicons-prefix}social-html5-outline:before { content: $ionicon-var-social-html5-outline; }
-.#{$ionicons-prefix}social-instagram:before { content: $ionicon-var-social-instagram; }
-.#{$ionicons-prefix}social-instagram-outline:before { content: $ionicon-var-social-instagram-outline; }
-.#{$ionicons-prefix}social-javascript:before { content: $ionicon-var-social-javascript; }
-.#{$ionicons-prefix}social-javascript-outline:before { content: $ionicon-var-social-javascript-outline; }
-.#{$ionicons-prefix}social-linkedin:before { content: $ionicon-var-social-linkedin; }
-.#{$ionicons-prefix}social-linkedin-outline:before { content: $ionicon-var-social-linkedin-outline; }
-.#{$ionicons-prefix}social-markdown:before { content: $ionicon-var-social-markdown; }
-.#{$ionicons-prefix}social-nodejs:before { content: $ionicon-var-social-nodejs; }
-.#{$ionicons-prefix}social-octocat:before { content: $ionicon-var-social-octocat; }
-.#{$ionicons-prefix}social-pinterest:before { content: $ionicon-var-social-pinterest; }
-.#{$ionicons-prefix}social-pinterest-outline:before { content: $ionicon-var-social-pinterest-outline; }
-.#{$ionicons-prefix}social-python:before { content: $ionicon-var-social-python; }
-.#{$ionicons-prefix}social-reddit:before { content: $ionicon-var-social-reddit; }
-.#{$ionicons-prefix}social-reddit-outline:before { content: $ionicon-var-social-reddit-outline; }
-.#{$ionicons-prefix}social-rss:before { content: $ionicon-var-social-rss; }
-.#{$ionicons-prefix}social-rss-outline:before { content: $ionicon-var-social-rss-outline; }
-.#{$ionicons-prefix}social-sass:before { content: $ionicon-var-social-sass; }
-.#{$ionicons-prefix}social-skype:before { content: $ionicon-var-social-skype; }
-.#{$ionicons-prefix}social-skype-outline:before { content: $ionicon-var-social-skype-outline; }
-.#{$ionicons-prefix}social-snapchat:before { content: $ionicon-var-social-snapchat; }
-.#{$ionicons-prefix}social-snapchat-outline:before { content: $ionicon-var-social-snapchat-outline; }
-.#{$ionicons-prefix}social-tumblr:before { content: $ionicon-var-social-tumblr; }
-.#{$ionicons-prefix}social-tumblr-outline:before { content: $ionicon-var-social-tumblr-outline; }
-.#{$ionicons-prefix}social-tux:before { content: $ionicon-var-social-tux; }
-.#{$ionicons-prefix}social-twitch:before { content: $ionicon-var-social-twitch; }
-.#{$ionicons-prefix}social-twitch-outline:before { content: $ionicon-var-social-twitch-outline; }
-.#{$ionicons-prefix}social-twitter:before { content: $ionicon-var-social-twitter; }
-.#{$ionicons-prefix}social-twitter-outline:before { content: $ionicon-var-social-twitter-outline; }
-.#{$ionicons-prefix}social-usd:before { content: $ionicon-var-social-usd; }
-.#{$ionicons-prefix}social-usd-outline:before { content: $ionicon-var-social-usd-outline; }
-.#{$ionicons-prefix}social-vimeo:before { content: $ionicon-var-social-vimeo; }
-.#{$ionicons-prefix}social-vimeo-outline:before { content: $ionicon-var-social-vimeo-outline; }
-.#{$ionicons-prefix}social-whatsapp:before { content: $ionicon-var-social-whatsapp; }
-.#{$ionicons-prefix}social-whatsapp-outline:before { content: $ionicon-var-social-whatsapp-outline; }
-.#{$ionicons-prefix}social-windows:before { content: $ionicon-var-social-windows; }
-.#{$ionicons-prefix}social-windows-outline:before { content: $ionicon-var-social-windows-outline; }
-.#{$ionicons-prefix}social-wordpress:before { content: $ionicon-var-social-wordpress; }
-.#{$ionicons-prefix}social-wordpress-outline:before { content: $ionicon-var-social-wordpress-outline; }
-.#{$ionicons-prefix}social-yahoo:before { content: $ionicon-var-social-yahoo; }
-.#{$ionicons-prefix}social-yahoo-outline:before { content: $ionicon-var-social-yahoo-outline; }
-.#{$ionicons-prefix}social-yen:before { content: $ionicon-var-social-yen; }
-.#{$ionicons-prefix}social-yen-outline:before { content: $ionicon-var-social-yen-outline; }
-.#{$ionicons-prefix}social-youtube:before { content: $ionicon-var-social-youtube; }
-.#{$ionicons-prefix}social-youtube-outline:before { content: $ionicon-var-social-youtube-outline; }
-.#{$ionicons-prefix}soup-can:before { content: $ionicon-var-soup-can; }
-.#{$ionicons-prefix}soup-can-outline:before { content: $ionicon-var-soup-can-outline; }
-.#{$ionicons-prefix}speakerphone:before { content: $ionicon-var-speakerphone; }
-.#{$ionicons-prefix}speedometer:before { content: $ionicon-var-speedometer; }
-.#{$ionicons-prefix}spoon:before { content: $ionicon-var-spoon; }
-.#{$ionicons-prefix}star:before { content: $ionicon-var-star; }
-.#{$ionicons-prefix}stats-bars:before { content: $ionicon-var-stats-bars; }
-.#{$ionicons-prefix}steam:before { content: $ionicon-var-steam; }
-.#{$ionicons-prefix}stop:before { content: $ionicon-var-stop; }
-.#{$ionicons-prefix}thermometer:before { content: $ionicon-var-thermometer; }
-.#{$ionicons-prefix}thumbsdown:before { content: $ionicon-var-thumbsdown; }
-.#{$ionicons-prefix}thumbsup:before { content: $ionicon-var-thumbsup; }
-.#{$ionicons-prefix}toggle:before { content: $ionicon-var-toggle; }
-.#{$ionicons-prefix}toggle-filled:before { content: $ionicon-var-toggle-filled; }
-.#{$ionicons-prefix}transgender:before { content: $ionicon-var-transgender; }
-.#{$ionicons-prefix}trash-a:before { content: $ionicon-var-trash-a; }
-.#{$ionicons-prefix}trash-b:before { content: $ionicon-var-trash-b; }
-.#{$ionicons-prefix}trophy:before { content: $ionicon-var-trophy; }
-.#{$ionicons-prefix}tshirt:before { content: $ionicon-var-tshirt; }
-.#{$ionicons-prefix}tshirt-outline:before { content: $ionicon-var-tshirt-outline; }
-.#{$ionicons-prefix}umbrella:before { content: $ionicon-var-umbrella; }
-.#{$ionicons-prefix}university:before { content: $ionicon-var-university; }
-.#{$ionicons-prefix}unlocked:before { content: $ionicon-var-unlocked; }
-.#{$ionicons-prefix}upload:before { content: $ionicon-var-upload; }
-.#{$ionicons-prefix}usb:before { content: $ionicon-var-usb; }
-.#{$ionicons-prefix}videocamera:before { content: $ionicon-var-videocamera; }
-.#{$ionicons-prefix}volume-high:before { content: $ionicon-var-volume-high; }
-.#{$ionicons-prefix}volume-low:before { content: $ionicon-var-volume-low; }
-.#{$ionicons-prefix}volume-medium:before { content: $ionicon-var-volume-medium; }
-.#{$ionicons-prefix}volume-mute:before { content: $ionicon-var-volume-mute; }
-.#{$ionicons-prefix}wand:before { content: $ionicon-var-wand; }
-.#{$ionicons-prefix}waterdrop:before { content: $ionicon-var-waterdrop; }
-.#{$ionicons-prefix}wifi:before { content: $ionicon-var-wifi; }
-.#{$ionicons-prefix}wineglass:before { content: $ionicon-var-wineglass; }
-.#{$ionicons-prefix}woman:before { content: $ionicon-var-woman; }
-.#{$ionicons-prefix}wrench:before { content: $ionicon-var-wrench; }
-.#{$ionicons-prefix}xbox:before { content: $ionicon-var-xbox; } \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-variables.scss b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-variables.scss
deleted file mode 100644
index a4601a94..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/_ionicons-variables.scss
+++ /dev/null
@@ -1,741 +0,0 @@
-// Ionicons Variables
-// --------------------------
-
-$ionicons-font-path: "../fonts" !default;
-$ionicons-font-family: "Ionicons" !default;
-$ionicons-version: "2.0.0" !default;
-$ionicons-prefix: ion- !default;
-
-$ionicon-var-alert: "\f101";
-$ionicon-var-alert-circled: "\f100";
-$ionicon-var-android-add: "\f2c7";
-$ionicon-var-android-add-circle: "\f359";
-$ionicon-var-android-alarm-clock: "\f35a";
-$ionicon-var-android-alert: "\f35b";
-$ionicon-var-android-apps: "\f35c";
-$ionicon-var-android-archive: "\f2c9";
-$ionicon-var-android-arrow-back: "\f2ca";
-$ionicon-var-android-arrow-down: "\f35d";
-$ionicon-var-android-arrow-dropdown: "\f35f";
-$ionicon-var-android-arrow-dropdown-circle: "\f35e";
-$ionicon-var-android-arrow-dropleft: "\f361";
-$ionicon-var-android-arrow-dropleft-circle: "\f360";
-$ionicon-var-android-arrow-dropright: "\f363";
-$ionicon-var-android-arrow-dropright-circle: "\f362";
-$ionicon-var-android-arrow-dropup: "\f365";
-$ionicon-var-android-arrow-dropup-circle: "\f364";
-$ionicon-var-android-arrow-forward: "\f30f";
-$ionicon-var-android-arrow-up: "\f366";
-$ionicon-var-android-attach: "\f367";
-$ionicon-var-android-bar: "\f368";
-$ionicon-var-android-bicycle: "\f369";
-$ionicon-var-android-boat: "\f36a";
-$ionicon-var-android-bookmark: "\f36b";
-$ionicon-var-android-bulb: "\f36c";
-$ionicon-var-android-bus: "\f36d";
-$ionicon-var-android-calendar: "\f2d1";
-$ionicon-var-android-call: "\f2d2";
-$ionicon-var-android-camera: "\f2d3";
-$ionicon-var-android-cancel: "\f36e";
-$ionicon-var-android-car: "\f36f";
-$ionicon-var-android-cart: "\f370";
-$ionicon-var-android-chat: "\f2d4";
-$ionicon-var-android-checkbox: "\f374";
-$ionicon-var-android-checkbox-blank: "\f371";
-$ionicon-var-android-checkbox-outline: "\f373";
-$ionicon-var-android-checkbox-outline-blank: "\f372";
-$ionicon-var-android-checkmark-circle: "\f375";
-$ionicon-var-android-clipboard: "\f376";
-$ionicon-var-android-close: "\f2d7";
-$ionicon-var-android-cloud: "\f37a";
-$ionicon-var-android-cloud-circle: "\f377";
-$ionicon-var-android-cloud-done: "\f378";
-$ionicon-var-android-cloud-outline: "\f379";
-$ionicon-var-android-color-palette: "\f37b";
-$ionicon-var-android-compass: "\f37c";
-$ionicon-var-android-contact: "\f2d8";
-$ionicon-var-android-contacts: "\f2d9";
-$ionicon-var-android-contract: "\f37d";
-$ionicon-var-android-create: "\f37e";
-$ionicon-var-android-delete: "\f37f";
-$ionicon-var-android-desktop: "\f380";
-$ionicon-var-android-document: "\f381";
-$ionicon-var-android-done: "\f383";
-$ionicon-var-android-done-all: "\f382";
-$ionicon-var-android-download: "\f2dd";
-$ionicon-var-android-drafts: "\f384";
-$ionicon-var-android-exit: "\f385";
-$ionicon-var-android-expand: "\f386";
-$ionicon-var-android-favorite: "\f388";
-$ionicon-var-android-favorite-outline: "\f387";
-$ionicon-var-android-film: "\f389";
-$ionicon-var-android-folder: "\f2e0";
-$ionicon-var-android-folder-open: "\f38a";
-$ionicon-var-android-funnel: "\f38b";
-$ionicon-var-android-globe: "\f38c";
-$ionicon-var-android-hand: "\f2e3";
-$ionicon-var-android-hangout: "\f38d";
-$ionicon-var-android-happy: "\f38e";
-$ionicon-var-android-home: "\f38f";
-$ionicon-var-android-image: "\f2e4";
-$ionicon-var-android-laptop: "\f390";
-$ionicon-var-android-list: "\f391";
-$ionicon-var-android-locate: "\f2e9";
-$ionicon-var-android-lock: "\f392";
-$ionicon-var-android-mail: "\f2eb";
-$ionicon-var-android-map: "\f393";
-$ionicon-var-android-menu: "\f394";
-$ionicon-var-android-microphone: "\f2ec";
-$ionicon-var-android-microphone-off: "\f395";
-$ionicon-var-android-more-horizontal: "\f396";
-$ionicon-var-android-more-vertical: "\f397";
-$ionicon-var-android-navigate: "\f398";
-$ionicon-var-android-notifications: "\f39b";
-$ionicon-var-android-notifications-none: "\f399";
-$ionicon-var-android-notifications-off: "\f39a";
-$ionicon-var-android-open: "\f39c";
-$ionicon-var-android-options: "\f39d";
-$ionicon-var-android-people: "\f39e";
-$ionicon-var-android-person: "\f3a0";
-$ionicon-var-android-person-add: "\f39f";
-$ionicon-var-android-phone-landscape: "\f3a1";
-$ionicon-var-android-phone-portrait: "\f3a2";
-$ionicon-var-android-pin: "\f3a3";
-$ionicon-var-android-plane: "\f3a4";
-$ionicon-var-android-playstore: "\f2f0";
-$ionicon-var-android-print: "\f3a5";
-$ionicon-var-android-radio-button-off: "\f3a6";
-$ionicon-var-android-radio-button-on: "\f3a7";
-$ionicon-var-android-refresh: "\f3a8";
-$ionicon-var-android-remove: "\f2f4";
-$ionicon-var-android-remove-circle: "\f3a9";
-$ionicon-var-android-restaurant: "\f3aa";
-$ionicon-var-android-sad: "\f3ab";
-$ionicon-var-android-search: "\f2f5";
-$ionicon-var-android-send: "\f2f6";
-$ionicon-var-android-settings: "\f2f7";
-$ionicon-var-android-share: "\f2f8";
-$ionicon-var-android-share-alt: "\f3ac";
-$ionicon-var-android-star: "\f2fc";
-$ionicon-var-android-star-half: "\f3ad";
-$ionicon-var-android-star-outline: "\f3ae";
-$ionicon-var-android-stopwatch: "\f2fd";
-$ionicon-var-android-subway: "\f3af";
-$ionicon-var-android-sunny: "\f3b0";
-$ionicon-var-android-sync: "\f3b1";
-$ionicon-var-android-textsms: "\f3b2";
-$ionicon-var-android-time: "\f3b3";
-$ionicon-var-android-train: "\f3b4";
-$ionicon-var-android-unlock: "\f3b5";
-$ionicon-var-android-upload: "\f3b6";
-$ionicon-var-android-volume-down: "\f3b7";
-$ionicon-var-android-volume-mute: "\f3b8";
-$ionicon-var-android-volume-off: "\f3b9";
-$ionicon-var-android-volume-up: "\f3ba";
-$ionicon-var-android-walk: "\f3bb";
-$ionicon-var-android-warning: "\f3bc";
-$ionicon-var-android-watch: "\f3bd";
-$ionicon-var-android-wifi: "\f305";
-$ionicon-var-aperture: "\f313";
-$ionicon-var-archive: "\f102";
-$ionicon-var-arrow-down-a: "\f103";
-$ionicon-var-arrow-down-b: "\f104";
-$ionicon-var-arrow-down-c: "\f105";
-$ionicon-var-arrow-expand: "\f25e";
-$ionicon-var-arrow-graph-down-left: "\f25f";
-$ionicon-var-arrow-graph-down-right: "\f260";
-$ionicon-var-arrow-graph-up-left: "\f261";
-$ionicon-var-arrow-graph-up-right: "\f262";
-$ionicon-var-arrow-left-a: "\f106";
-$ionicon-var-arrow-left-b: "\f107";
-$ionicon-var-arrow-left-c: "\f108";
-$ionicon-var-arrow-move: "\f263";
-$ionicon-var-arrow-resize: "\f264";
-$ionicon-var-arrow-return-left: "\f265";
-$ionicon-var-arrow-return-right: "\f266";
-$ionicon-var-arrow-right-a: "\f109";
-$ionicon-var-arrow-right-b: "\f10a";
-$ionicon-var-arrow-right-c: "\f10b";
-$ionicon-var-arrow-shrink: "\f267";
-$ionicon-var-arrow-swap: "\f268";
-$ionicon-var-arrow-up-a: "\f10c";
-$ionicon-var-arrow-up-b: "\f10d";
-$ionicon-var-arrow-up-c: "\f10e";
-$ionicon-var-asterisk: "\f314";
-$ionicon-var-at: "\f10f";
-$ionicon-var-backspace: "\f3bf";
-$ionicon-var-backspace-outline: "\f3be";
-$ionicon-var-bag: "\f110";
-$ionicon-var-battery-charging: "\f111";
-$ionicon-var-battery-empty: "\f112";
-$ionicon-var-battery-full: "\f113";
-$ionicon-var-battery-half: "\f114";
-$ionicon-var-battery-low: "\f115";
-$ionicon-var-beaker: "\f269";
-$ionicon-var-beer: "\f26a";
-$ionicon-var-bluetooth: "\f116";
-$ionicon-var-bonfire: "\f315";
-$ionicon-var-bookmark: "\f26b";
-$ionicon-var-bowtie: "\f3c0";
-$ionicon-var-briefcase: "\f26c";
-$ionicon-var-bug: "\f2be";
-$ionicon-var-calculator: "\f26d";
-$ionicon-var-calendar: "\f117";
-$ionicon-var-camera: "\f118";
-$ionicon-var-card: "\f119";
-$ionicon-var-cash: "\f316";
-$ionicon-var-chatbox: "\f11b";
-$ionicon-var-chatbox-working: "\f11a";
-$ionicon-var-chatboxes: "\f11c";
-$ionicon-var-chatbubble: "\f11e";
-$ionicon-var-chatbubble-working: "\f11d";
-$ionicon-var-chatbubbles: "\f11f";
-$ionicon-var-checkmark: "\f122";
-$ionicon-var-checkmark-circled: "\f120";
-$ionicon-var-checkmark-round: "\f121";
-$ionicon-var-chevron-down: "\f123";
-$ionicon-var-chevron-left: "\f124";
-$ionicon-var-chevron-right: "\f125";
-$ionicon-var-chevron-up: "\f126";
-$ionicon-var-clipboard: "\f127";
-$ionicon-var-clock: "\f26e";
-$ionicon-var-close: "\f12a";
-$ionicon-var-close-circled: "\f128";
-$ionicon-var-close-round: "\f129";
-$ionicon-var-closed-captioning: "\f317";
-$ionicon-var-cloud: "\f12b";
-$ionicon-var-code: "\f271";
-$ionicon-var-code-download: "\f26f";
-$ionicon-var-code-working: "\f270";
-$ionicon-var-coffee: "\f272";
-$ionicon-var-compass: "\f273";
-$ionicon-var-compose: "\f12c";
-$ionicon-var-connection-bars: "\f274";
-$ionicon-var-contrast: "\f275";
-$ionicon-var-crop: "\f3c1";
-$ionicon-var-cube: "\f318";
-$ionicon-var-disc: "\f12d";
-$ionicon-var-document: "\f12f";
-$ionicon-var-document-text: "\f12e";
-$ionicon-var-drag: "\f130";
-$ionicon-var-earth: "\f276";
-$ionicon-var-easel: "\f3c2";
-$ionicon-var-edit: "\f2bf";
-$ionicon-var-egg: "\f277";
-$ionicon-var-eject: "\f131";
-$ionicon-var-email: "\f132";
-$ionicon-var-email-unread: "\f3c3";
-$ionicon-var-erlenmeyer-flask: "\f3c5";
-$ionicon-var-erlenmeyer-flask-bubbles: "\f3c4";
-$ionicon-var-eye: "\f133";
-$ionicon-var-eye-disabled: "\f306";
-$ionicon-var-female: "\f278";
-$ionicon-var-filing: "\f134";
-$ionicon-var-film-marker: "\f135";
-$ionicon-var-fireball: "\f319";
-$ionicon-var-flag: "\f279";
-$ionicon-var-flame: "\f31a";
-$ionicon-var-flash: "\f137";
-$ionicon-var-flash-off: "\f136";
-$ionicon-var-folder: "\f139";
-$ionicon-var-fork: "\f27a";
-$ionicon-var-fork-repo: "\f2c0";
-$ionicon-var-forward: "\f13a";
-$ionicon-var-funnel: "\f31b";
-$ionicon-var-gear-a: "\f13d";
-$ionicon-var-gear-b: "\f13e";
-$ionicon-var-grid: "\f13f";
-$ionicon-var-hammer: "\f27b";
-$ionicon-var-happy: "\f31c";
-$ionicon-var-happy-outline: "\f3c6";
-$ionicon-var-headphone: "\f140";
-$ionicon-var-heart: "\f141";
-$ionicon-var-heart-broken: "\f31d";
-$ionicon-var-help: "\f143";
-$ionicon-var-help-buoy: "\f27c";
-$ionicon-var-help-circled: "\f142";
-$ionicon-var-home: "\f144";
-$ionicon-var-icecream: "\f27d";
-$ionicon-var-image: "\f147";
-$ionicon-var-images: "\f148";
-$ionicon-var-information: "\f14a";
-$ionicon-var-information-circled: "\f149";
-$ionicon-var-ionic: "\f14b";
-$ionicon-var-ios-alarm: "\f3c8";
-$ionicon-var-ios-alarm-outline: "\f3c7";
-$ionicon-var-ios-albums: "\f3ca";
-$ionicon-var-ios-albums-outline: "\f3c9";
-$ionicon-var-ios-americanfootball: "\f3cc";
-$ionicon-var-ios-americanfootball-outline: "\f3cb";
-$ionicon-var-ios-analytics: "\f3ce";
-$ionicon-var-ios-analytics-outline: "\f3cd";
-$ionicon-var-ios-arrow-back: "\f3cf";
-$ionicon-var-ios-arrow-down: "\f3d0";
-$ionicon-var-ios-arrow-forward: "\f3d1";
-$ionicon-var-ios-arrow-left: "\f3d2";
-$ionicon-var-ios-arrow-right: "\f3d3";
-$ionicon-var-ios-arrow-thin-down: "\f3d4";
-$ionicon-var-ios-arrow-thin-left: "\f3d5";
-$ionicon-var-ios-arrow-thin-right: "\f3d6";
-$ionicon-var-ios-arrow-thin-up: "\f3d7";
-$ionicon-var-ios-arrow-up: "\f3d8";
-$ionicon-var-ios-at: "\f3da";
-$ionicon-var-ios-at-outline: "\f3d9";
-$ionicon-var-ios-barcode: "\f3dc";
-$ionicon-var-ios-barcode-outline: "\f3db";
-$ionicon-var-ios-baseball: "\f3de";
-$ionicon-var-ios-baseball-outline: "\f3dd";
-$ionicon-var-ios-basketball: "\f3e0";
-$ionicon-var-ios-basketball-outline: "\f3df";
-$ionicon-var-ios-bell: "\f3e2";
-$ionicon-var-ios-bell-outline: "\f3e1";
-$ionicon-var-ios-body: "\f3e4";
-$ionicon-var-ios-body-outline: "\f3e3";
-$ionicon-var-ios-bolt: "\f3e6";
-$ionicon-var-ios-bolt-outline: "\f3e5";
-$ionicon-var-ios-book: "\f3e8";
-$ionicon-var-ios-book-outline: "\f3e7";
-$ionicon-var-ios-bookmarks: "\f3ea";
-$ionicon-var-ios-bookmarks-outline: "\f3e9";
-$ionicon-var-ios-box: "\f3ec";
-$ionicon-var-ios-box-outline: "\f3eb";
-$ionicon-var-ios-briefcase: "\f3ee";
-$ionicon-var-ios-briefcase-outline: "\f3ed";
-$ionicon-var-ios-browsers: "\f3f0";
-$ionicon-var-ios-browsers-outline: "\f3ef";
-$ionicon-var-ios-calculator: "\f3f2";
-$ionicon-var-ios-calculator-outline: "\f3f1";
-$ionicon-var-ios-calendar: "\f3f4";
-$ionicon-var-ios-calendar-outline: "\f3f3";
-$ionicon-var-ios-camera: "\f3f6";
-$ionicon-var-ios-camera-outline: "\f3f5";
-$ionicon-var-ios-cart: "\f3f8";
-$ionicon-var-ios-cart-outline: "\f3f7";
-$ionicon-var-ios-chatboxes: "\f3fa";
-$ionicon-var-ios-chatboxes-outline: "\f3f9";
-$ionicon-var-ios-chatbubble: "\f3fc";
-$ionicon-var-ios-chatbubble-outline: "\f3fb";
-$ionicon-var-ios-checkmark: "\f3ff";
-$ionicon-var-ios-checkmark-empty: "\f3fd";
-$ionicon-var-ios-checkmark-outline: "\f3fe";
-$ionicon-var-ios-circle-filled: "\f400";
-$ionicon-var-ios-circle-outline: "\f401";
-$ionicon-var-ios-clock: "\f403";
-$ionicon-var-ios-clock-outline: "\f402";
-$ionicon-var-ios-close: "\f406";
-$ionicon-var-ios-close-empty: "\f404";
-$ionicon-var-ios-close-outline: "\f405";
-$ionicon-var-ios-cloud: "\f40c";
-$ionicon-var-ios-cloud-download: "\f408";
-$ionicon-var-ios-cloud-download-outline: "\f407";
-$ionicon-var-ios-cloud-outline: "\f409";
-$ionicon-var-ios-cloud-upload: "\f40b";
-$ionicon-var-ios-cloud-upload-outline: "\f40a";
-$ionicon-var-ios-cloudy: "\f410";
-$ionicon-var-ios-cloudy-night: "\f40e";
-$ionicon-var-ios-cloudy-night-outline: "\f40d";
-$ionicon-var-ios-cloudy-outline: "\f40f";
-$ionicon-var-ios-cog: "\f412";
-$ionicon-var-ios-cog-outline: "\f411";
-$ionicon-var-ios-color-filter: "\f414";
-$ionicon-var-ios-color-filter-outline: "\f413";
-$ionicon-var-ios-color-wand: "\f416";
-$ionicon-var-ios-color-wand-outline: "\f415";
-$ionicon-var-ios-compose: "\f418";
-$ionicon-var-ios-compose-outline: "\f417";
-$ionicon-var-ios-contact: "\f41a";
-$ionicon-var-ios-contact-outline: "\f419";
-$ionicon-var-ios-copy: "\f41c";
-$ionicon-var-ios-copy-outline: "\f41b";
-$ionicon-var-ios-crop: "\f41e";
-$ionicon-var-ios-crop-strong: "\f41d";
-$ionicon-var-ios-download: "\f420";
-$ionicon-var-ios-download-outline: "\f41f";
-$ionicon-var-ios-drag: "\f421";
-$ionicon-var-ios-email: "\f423";
-$ionicon-var-ios-email-outline: "\f422";
-$ionicon-var-ios-eye: "\f425";
-$ionicon-var-ios-eye-outline: "\f424";
-$ionicon-var-ios-fastforward: "\f427";
-$ionicon-var-ios-fastforward-outline: "\f426";
-$ionicon-var-ios-filing: "\f429";
-$ionicon-var-ios-filing-outline: "\f428";
-$ionicon-var-ios-film: "\f42b";
-$ionicon-var-ios-film-outline: "\f42a";
-$ionicon-var-ios-flag: "\f42d";
-$ionicon-var-ios-flag-outline: "\f42c";
-$ionicon-var-ios-flame: "\f42f";
-$ionicon-var-ios-flame-outline: "\f42e";
-$ionicon-var-ios-flask: "\f431";
-$ionicon-var-ios-flask-outline: "\f430";
-$ionicon-var-ios-flower: "\f433";
-$ionicon-var-ios-flower-outline: "\f432";
-$ionicon-var-ios-folder: "\f435";
-$ionicon-var-ios-folder-outline: "\f434";
-$ionicon-var-ios-football: "\f437";
-$ionicon-var-ios-football-outline: "\f436";
-$ionicon-var-ios-game-controller-a: "\f439";
-$ionicon-var-ios-game-controller-a-outline: "\f438";
-$ionicon-var-ios-game-controller-b: "\f43b";
-$ionicon-var-ios-game-controller-b-outline: "\f43a";
-$ionicon-var-ios-gear: "\f43d";
-$ionicon-var-ios-gear-outline: "\f43c";
-$ionicon-var-ios-glasses: "\f43f";
-$ionicon-var-ios-glasses-outline: "\f43e";
-$ionicon-var-ios-grid-view: "\f441";
-$ionicon-var-ios-grid-view-outline: "\f440";
-$ionicon-var-ios-heart: "\f443";
-$ionicon-var-ios-heart-outline: "\f442";
-$ionicon-var-ios-help: "\f446";
-$ionicon-var-ios-help-empty: "\f444";
-$ionicon-var-ios-help-outline: "\f445";
-$ionicon-var-ios-home: "\f448";
-$ionicon-var-ios-home-outline: "\f447";
-$ionicon-var-ios-infinite: "\f44a";
-$ionicon-var-ios-infinite-outline: "\f449";
-$ionicon-var-ios-information: "\f44d";
-$ionicon-var-ios-information-empty: "\f44b";
-$ionicon-var-ios-information-outline: "\f44c";
-$ionicon-var-ios-ionic-outline: "\f44e";
-$ionicon-var-ios-keypad: "\f450";
-$ionicon-var-ios-keypad-outline: "\f44f";
-$ionicon-var-ios-lightbulb: "\f452";
-$ionicon-var-ios-lightbulb-outline: "\f451";
-$ionicon-var-ios-list: "\f454";
-$ionicon-var-ios-list-outline: "\f453";
-$ionicon-var-ios-location: "\f456";
-$ionicon-var-ios-location-outline: "\f455";
-$ionicon-var-ios-locked: "\f458";
-$ionicon-var-ios-locked-outline: "\f457";
-$ionicon-var-ios-loop: "\f45a";
-$ionicon-var-ios-loop-strong: "\f459";
-$ionicon-var-ios-medical: "\f45c";
-$ionicon-var-ios-medical-outline: "\f45b";
-$ionicon-var-ios-medkit: "\f45e";
-$ionicon-var-ios-medkit-outline: "\f45d";
-$ionicon-var-ios-mic: "\f461";
-$ionicon-var-ios-mic-off: "\f45f";
-$ionicon-var-ios-mic-outline: "\f460";
-$ionicon-var-ios-minus: "\f464";
-$ionicon-var-ios-minus-empty: "\f462";
-$ionicon-var-ios-minus-outline: "\f463";
-$ionicon-var-ios-monitor: "\f466";
-$ionicon-var-ios-monitor-outline: "\f465";
-$ionicon-var-ios-moon: "\f468";
-$ionicon-var-ios-moon-outline: "\f467";
-$ionicon-var-ios-more: "\f46a";
-$ionicon-var-ios-more-outline: "\f469";
-$ionicon-var-ios-musical-note: "\f46b";
-$ionicon-var-ios-musical-notes: "\f46c";
-$ionicon-var-ios-navigate: "\f46e";
-$ionicon-var-ios-navigate-outline: "\f46d";
-$ionicon-var-ios-nutrition: "\f470";
-$ionicon-var-ios-nutrition-outline: "\f46f";
-$ionicon-var-ios-paper: "\f472";
-$ionicon-var-ios-paper-outline: "\f471";
-$ionicon-var-ios-paperplane: "\f474";
-$ionicon-var-ios-paperplane-outline: "\f473";
-$ionicon-var-ios-partlysunny: "\f476";
-$ionicon-var-ios-partlysunny-outline: "\f475";
-$ionicon-var-ios-pause: "\f478";
-$ionicon-var-ios-pause-outline: "\f477";
-$ionicon-var-ios-paw: "\f47a";
-$ionicon-var-ios-paw-outline: "\f479";
-$ionicon-var-ios-people: "\f47c";
-$ionicon-var-ios-people-outline: "\f47b";
-$ionicon-var-ios-person: "\f47e";
-$ionicon-var-ios-person-outline: "\f47d";
-$ionicon-var-ios-personadd: "\f480";
-$ionicon-var-ios-personadd-outline: "\f47f";
-$ionicon-var-ios-photos: "\f482";
-$ionicon-var-ios-photos-outline: "\f481";
-$ionicon-var-ios-pie: "\f484";
-$ionicon-var-ios-pie-outline: "\f483";
-$ionicon-var-ios-pint: "\f486";
-$ionicon-var-ios-pint-outline: "\f485";
-$ionicon-var-ios-play: "\f488";
-$ionicon-var-ios-play-outline: "\f487";
-$ionicon-var-ios-plus: "\f48b";
-$ionicon-var-ios-plus-empty: "\f489";
-$ionicon-var-ios-plus-outline: "\f48a";
-$ionicon-var-ios-pricetag: "\f48d";
-$ionicon-var-ios-pricetag-outline: "\f48c";
-$ionicon-var-ios-pricetags: "\f48f";
-$ionicon-var-ios-pricetags-outline: "\f48e";
-$ionicon-var-ios-printer: "\f491";
-$ionicon-var-ios-printer-outline: "\f490";
-$ionicon-var-ios-pulse: "\f493";
-$ionicon-var-ios-pulse-strong: "\f492";
-$ionicon-var-ios-rainy: "\f495";
-$ionicon-var-ios-rainy-outline: "\f494";
-$ionicon-var-ios-recording: "\f497";
-$ionicon-var-ios-recording-outline: "\f496";
-$ionicon-var-ios-redo: "\f499";
-$ionicon-var-ios-redo-outline: "\f498";
-$ionicon-var-ios-refresh: "\f49c";
-$ionicon-var-ios-refresh-empty: "\f49a";
-$ionicon-var-ios-refresh-outline: "\f49b";
-$ionicon-var-ios-reload: "\f49d";
-$ionicon-var-ios-reverse-camera: "\f49f";
-$ionicon-var-ios-reverse-camera-outline: "\f49e";
-$ionicon-var-ios-rewind: "\f4a1";
-$ionicon-var-ios-rewind-outline: "\f4a0";
-$ionicon-var-ios-rose: "\f4a3";
-$ionicon-var-ios-rose-outline: "\f4a2";
-$ionicon-var-ios-search: "\f4a5";
-$ionicon-var-ios-search-strong: "\f4a4";
-$ionicon-var-ios-settings: "\f4a7";
-$ionicon-var-ios-settings-strong: "\f4a6";
-$ionicon-var-ios-shuffle: "\f4a9";
-$ionicon-var-ios-shuffle-strong: "\f4a8";
-$ionicon-var-ios-skipbackward: "\f4ab";
-$ionicon-var-ios-skipbackward-outline: "\f4aa";
-$ionicon-var-ios-skipforward: "\f4ad";
-$ionicon-var-ios-skipforward-outline: "\f4ac";
-$ionicon-var-ios-snowy: "\f4ae";
-$ionicon-var-ios-speedometer: "\f4b0";
-$ionicon-var-ios-speedometer-outline: "\f4af";
-$ionicon-var-ios-star: "\f4b3";
-$ionicon-var-ios-star-half: "\f4b1";
-$ionicon-var-ios-star-outline: "\f4b2";
-$ionicon-var-ios-stopwatch: "\f4b5";
-$ionicon-var-ios-stopwatch-outline: "\f4b4";
-$ionicon-var-ios-sunny: "\f4b7";
-$ionicon-var-ios-sunny-outline: "\f4b6";
-$ionicon-var-ios-telephone: "\f4b9";
-$ionicon-var-ios-telephone-outline: "\f4b8";
-$ionicon-var-ios-tennisball: "\f4bb";
-$ionicon-var-ios-tennisball-outline: "\f4ba";
-$ionicon-var-ios-thunderstorm: "\f4bd";
-$ionicon-var-ios-thunderstorm-outline: "\f4bc";
-$ionicon-var-ios-time: "\f4bf";
-$ionicon-var-ios-time-outline: "\f4be";
-$ionicon-var-ios-timer: "\f4c1";
-$ionicon-var-ios-timer-outline: "\f4c0";
-$ionicon-var-ios-toggle: "\f4c3";
-$ionicon-var-ios-toggle-outline: "\f4c2";
-$ionicon-var-ios-trash: "\f4c5";
-$ionicon-var-ios-trash-outline: "\f4c4";
-$ionicon-var-ios-undo: "\f4c7";
-$ionicon-var-ios-undo-outline: "\f4c6";
-$ionicon-var-ios-unlocked: "\f4c9";
-$ionicon-var-ios-unlocked-outline: "\f4c8";
-$ionicon-var-ios-upload: "\f4cb";
-$ionicon-var-ios-upload-outline: "\f4ca";
-$ionicon-var-ios-videocam: "\f4cd";
-$ionicon-var-ios-videocam-outline: "\f4cc";
-$ionicon-var-ios-volume-high: "\f4ce";
-$ionicon-var-ios-volume-low: "\f4cf";
-$ionicon-var-ios-wineglass: "\f4d1";
-$ionicon-var-ios-wineglass-outline: "\f4d0";
-$ionicon-var-ios-world: "\f4d3";
-$ionicon-var-ios-world-outline: "\f4d2";
-$ionicon-var-ipad: "\f1f9";
-$ionicon-var-iphone: "\f1fa";
-$ionicon-var-ipod: "\f1fb";
-$ionicon-var-jet: "\f295";
-$ionicon-var-key: "\f296";
-$ionicon-var-knife: "\f297";
-$ionicon-var-laptop: "\f1fc";
-$ionicon-var-leaf: "\f1fd";
-$ionicon-var-levels: "\f298";
-$ionicon-var-lightbulb: "\f299";
-$ionicon-var-link: "\f1fe";
-$ionicon-var-load-a: "\f29a";
-$ionicon-var-load-b: "\f29b";
-$ionicon-var-load-c: "\f29c";
-$ionicon-var-load-d: "\f29d";
-$ionicon-var-location: "\f1ff";
-$ionicon-var-lock-combination: "\f4d4";
-$ionicon-var-locked: "\f200";
-$ionicon-var-log-in: "\f29e";
-$ionicon-var-log-out: "\f29f";
-$ionicon-var-loop: "\f201";
-$ionicon-var-magnet: "\f2a0";
-$ionicon-var-male: "\f2a1";
-$ionicon-var-man: "\f202";
-$ionicon-var-map: "\f203";
-$ionicon-var-medkit: "\f2a2";
-$ionicon-var-merge: "\f33f";
-$ionicon-var-mic-a: "\f204";
-$ionicon-var-mic-b: "\f205";
-$ionicon-var-mic-c: "\f206";
-$ionicon-var-minus: "\f209";
-$ionicon-var-minus-circled: "\f207";
-$ionicon-var-minus-round: "\f208";
-$ionicon-var-model-s: "\f2c1";
-$ionicon-var-monitor: "\f20a";
-$ionicon-var-more: "\f20b";
-$ionicon-var-mouse: "\f340";
-$ionicon-var-music-note: "\f20c";
-$ionicon-var-navicon: "\f20e";
-$ionicon-var-navicon-round: "\f20d";
-$ionicon-var-navigate: "\f2a3";
-$ionicon-var-network: "\f341";
-$ionicon-var-no-smoking: "\f2c2";
-$ionicon-var-nuclear: "\f2a4";
-$ionicon-var-outlet: "\f342";
-$ionicon-var-paintbrush: "\f4d5";
-$ionicon-var-paintbucket: "\f4d6";
-$ionicon-var-paper-airplane: "\f2c3";
-$ionicon-var-paperclip: "\f20f";
-$ionicon-var-pause: "\f210";
-$ionicon-var-person: "\f213";
-$ionicon-var-person-add: "\f211";
-$ionicon-var-person-stalker: "\f212";
-$ionicon-var-pie-graph: "\f2a5";
-$ionicon-var-pin: "\f2a6";
-$ionicon-var-pinpoint: "\f2a7";
-$ionicon-var-pizza: "\f2a8";
-$ionicon-var-plane: "\f214";
-$ionicon-var-planet: "\f343";
-$ionicon-var-play: "\f215";
-$ionicon-var-playstation: "\f30a";
-$ionicon-var-plus: "\f218";
-$ionicon-var-plus-circled: "\f216";
-$ionicon-var-plus-round: "\f217";
-$ionicon-var-podium: "\f344";
-$ionicon-var-pound: "\f219";
-$ionicon-var-power: "\f2a9";
-$ionicon-var-pricetag: "\f2aa";
-$ionicon-var-pricetags: "\f2ab";
-$ionicon-var-printer: "\f21a";
-$ionicon-var-pull-request: "\f345";
-$ionicon-var-qr-scanner: "\f346";
-$ionicon-var-quote: "\f347";
-$ionicon-var-radio-waves: "\f2ac";
-$ionicon-var-record: "\f21b";
-$ionicon-var-refresh: "\f21c";
-$ionicon-var-reply: "\f21e";
-$ionicon-var-reply-all: "\f21d";
-$ionicon-var-ribbon-a: "\f348";
-$ionicon-var-ribbon-b: "\f349";
-$ionicon-var-sad: "\f34a";
-$ionicon-var-sad-outline: "\f4d7";
-$ionicon-var-scissors: "\f34b";
-$ionicon-var-search: "\f21f";
-$ionicon-var-settings: "\f2ad";
-$ionicon-var-share: "\f220";
-$ionicon-var-shuffle: "\f221";
-$ionicon-var-skip-backward: "\f222";
-$ionicon-var-skip-forward: "\f223";
-$ionicon-var-social-android: "\f225";
-$ionicon-var-social-android-outline: "\f224";
-$ionicon-var-social-angular: "\f4d9";
-$ionicon-var-social-angular-outline: "\f4d8";
-$ionicon-var-social-apple: "\f227";
-$ionicon-var-social-apple-outline: "\f226";
-$ionicon-var-social-bitcoin: "\f2af";
-$ionicon-var-social-bitcoin-outline: "\f2ae";
-$ionicon-var-social-buffer: "\f229";
-$ionicon-var-social-buffer-outline: "\f228";
-$ionicon-var-social-chrome: "\f4db";
-$ionicon-var-social-chrome-outline: "\f4da";
-$ionicon-var-social-codepen: "\f4dd";
-$ionicon-var-social-codepen-outline: "\f4dc";
-$ionicon-var-social-css3: "\f4df";
-$ionicon-var-social-css3-outline: "\f4de";
-$ionicon-var-social-designernews: "\f22b";
-$ionicon-var-social-designernews-outline: "\f22a";
-$ionicon-var-social-dribbble: "\f22d";
-$ionicon-var-social-dribbble-outline: "\f22c";
-$ionicon-var-social-dropbox: "\f22f";
-$ionicon-var-social-dropbox-outline: "\f22e";
-$ionicon-var-social-euro: "\f4e1";
-$ionicon-var-social-euro-outline: "\f4e0";
-$ionicon-var-social-facebook: "\f231";
-$ionicon-var-social-facebook-outline: "\f230";
-$ionicon-var-social-foursquare: "\f34d";
-$ionicon-var-social-foursquare-outline: "\f34c";
-$ionicon-var-social-freebsd-devil: "\f2c4";
-$ionicon-var-social-github: "\f233";
-$ionicon-var-social-github-outline: "\f232";
-$ionicon-var-social-google: "\f34f";
-$ionicon-var-social-google-outline: "\f34e";
-$ionicon-var-social-googleplus: "\f235";
-$ionicon-var-social-googleplus-outline: "\f234";
-$ionicon-var-social-hackernews: "\f237";
-$ionicon-var-social-hackernews-outline: "\f236";
-$ionicon-var-social-html5: "\f4e3";
-$ionicon-var-social-html5-outline: "\f4e2";
-$ionicon-var-social-instagram: "\f351";
-$ionicon-var-social-instagram-outline: "\f350";
-$ionicon-var-social-javascript: "\f4e5";
-$ionicon-var-social-javascript-outline: "\f4e4";
-$ionicon-var-social-linkedin: "\f239";
-$ionicon-var-social-linkedin-outline: "\f238";
-$ionicon-var-social-markdown: "\f4e6";
-$ionicon-var-social-nodejs: "\f4e7";
-$ionicon-var-social-octocat: "\f4e8";
-$ionicon-var-social-pinterest: "\f2b1";
-$ionicon-var-social-pinterest-outline: "\f2b0";
-$ionicon-var-social-python: "\f4e9";
-$ionicon-var-social-reddit: "\f23b";
-$ionicon-var-social-reddit-outline: "\f23a";
-$ionicon-var-social-rss: "\f23d";
-$ionicon-var-social-rss-outline: "\f23c";
-$ionicon-var-social-sass: "\f4ea";
-$ionicon-var-social-skype: "\f23f";
-$ionicon-var-social-skype-outline: "\f23e";
-$ionicon-var-social-snapchat: "\f4ec";
-$ionicon-var-social-snapchat-outline: "\f4eb";
-$ionicon-var-social-tumblr: "\f241";
-$ionicon-var-social-tumblr-outline: "\f240";
-$ionicon-var-social-tux: "\f2c5";
-$ionicon-var-social-twitch: "\f4ee";
-$ionicon-var-social-twitch-outline: "\f4ed";
-$ionicon-var-social-twitter: "\f243";
-$ionicon-var-social-twitter-outline: "\f242";
-$ionicon-var-social-usd: "\f353";
-$ionicon-var-social-usd-outline: "\f352";
-$ionicon-var-social-vimeo: "\f245";
-$ionicon-var-social-vimeo-outline: "\f244";
-$ionicon-var-social-whatsapp: "\f4f0";
-$ionicon-var-social-whatsapp-outline: "\f4ef";
-$ionicon-var-social-windows: "\f247";
-$ionicon-var-social-windows-outline: "\f246";
-$ionicon-var-social-wordpress: "\f249";
-$ionicon-var-social-wordpress-outline: "\f248";
-$ionicon-var-social-yahoo: "\f24b";
-$ionicon-var-social-yahoo-outline: "\f24a";
-$ionicon-var-social-yen: "\f4f2";
-$ionicon-var-social-yen-outline: "\f4f1";
-$ionicon-var-social-youtube: "\f24d";
-$ionicon-var-social-youtube-outline: "\f24c";
-$ionicon-var-soup-can: "\f4f4";
-$ionicon-var-soup-can-outline: "\f4f3";
-$ionicon-var-speakerphone: "\f2b2";
-$ionicon-var-speedometer: "\f2b3";
-$ionicon-var-spoon: "\f2b4";
-$ionicon-var-star: "\f24e";
-$ionicon-var-stats-bars: "\f2b5";
-$ionicon-var-steam: "\f30b";
-$ionicon-var-stop: "\f24f";
-$ionicon-var-thermometer: "\f2b6";
-$ionicon-var-thumbsdown: "\f250";
-$ionicon-var-thumbsup: "\f251";
-$ionicon-var-toggle: "\f355";
-$ionicon-var-toggle-filled: "\f354";
-$ionicon-var-transgender: "\f4f5";
-$ionicon-var-trash-a: "\f252";
-$ionicon-var-trash-b: "\f253";
-$ionicon-var-trophy: "\f356";
-$ionicon-var-tshirt: "\f4f7";
-$ionicon-var-tshirt-outline: "\f4f6";
-$ionicon-var-umbrella: "\f2b7";
-$ionicon-var-university: "\f357";
-$ionicon-var-unlocked: "\f254";
-$ionicon-var-upload: "\f255";
-$ionicon-var-usb: "\f2b8";
-$ionicon-var-videocamera: "\f256";
-$ionicon-var-volume-high: "\f257";
-$ionicon-var-volume-low: "\f258";
-$ionicon-var-volume-medium: "\f259";
-$ionicon-var-volume-mute: "\f25a";
-$ionicon-var-wand: "\f358";
-$ionicon-var-waterdrop: "\f25b";
-$ionicon-var-wifi: "\f25c";
-$ionicon-var-wineglass: "\f2b9";
-$ionicon-var-woman: "\f25d";
-$ionicon-var-wrench: "\f2ba";
-$ionicon-var-xbox: "\f30c"; \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/ionicons.scss b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/ionicons.scss
deleted file mode 100644
index d2c79f9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/scss/ionicons.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-@import "ionicons-variables";
-/*!
- Ionicons, v#{$ionicons-version}
- Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
- https://twitter.com/benjsperry https://twitter.com/ionicframework
- MIT License: https://github.com/driftyco/ionicons
-
- Android-style icons originally built by Google’s
- Material Design Icons: https://github.com/google/material-design-icons
- used under CC BY http://creativecommons.org/licenses/by/4.0/
- Modified icons to fit ionicon’s grid from original.
-*/
-
-@import "ionicons-font";
-@import "ionicons-icons";
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert-circled.svg
deleted file mode 100644
index b6fccd72..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert-circled.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M476.7,422.2L270.1,72.7c-2.9-5-8.3-8.7-14.1-8.7c-5.9,0-11.3,3.7-14.1,8.7L35.3,422.2c-2.8,5-4.8,13-1.9,17.9
- c2.9,4.9,8.2,7.9,14,7.9h417.1c5.8,0,11.1-3,14-7.9C481.5,435.2,479.5,427.1,476.7,422.2z M288,400h-64v-48h64V400z M288,320h-64
- V176h64V320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert.svg
deleted file mode 100644
index b1a1c1f3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/alert.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M320,480H192v-96h128V480z M304,320h-96L192,32h128L304,320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add-circle.svg
deleted file mode 100644
index af6a7c65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add-circle.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M256,48C141.125,48,48,141.125,48,256s93.125,208,208,208s208-93.125,208-208S370.875,48,256,48z M363,277h-86v86h-42v-86
- h-86v-42h86v-86h42v86h86V277z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add.svg
deleted file mode 100644
index 3ef4c9df..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-add.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_7_">
- <g>
- <path d="M416,277.333H277.333V416h-42.666V277.333H96v-42.666h138.667V96h42.666v138.667H416V277.333z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alarm-clock.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alarm-clock.svg
deleted file mode 100644
index 395e52f4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alarm-clock.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_2_">
- <g>
- <path d="M470,124.837l-98.443-81.78l-27.814,32.931l98.442,81.769L470,124.837z M167.192,74.919L139.366,42L42,124.837
- l27.814,32.919L167.192,74.919z M266.701,172.628h-32.101v127.446l101.649,60.539l16.051-26.553l-85.6-49.917V172.628z
- M256,87.665c-107,0-192.601,86.021-192.601,191.166C63.399,383.98,149,470,256,470c105.936,0,192.601-86.02,192.601-191.169
- C448.601,173.687,361.936,87.665,256,87.665z M256,427.52c-82.393,0-149.8-66.906-149.8-148.688
- c0-81.777,67.407-148.684,149.8-148.684c82.394,0,149.8,66.906,149.8,148.684C405.8,361.671,338.394,427.52,256,427.52z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alert.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alert.svg
deleted file mode 100644
index 00671978..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-alert.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_30_">
- <g>
- <path d="M256,48C141.6,48,48,141.601,48,256s93.6,208,208,208c114.4,0,208-93.601,208-208S370.4,48,256,48z M280,360h-48v-40h48
- V360z M280,272h-48V144h48V272z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-apps.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-apps.svg
deleted file mode 100644
index db32fe51..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-apps.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon">
- <g>
- <path d="M96,176h80V96H96V176z M216,416h80v-80h-80V416z M96,416h80v-80H96V416z M96,296h80v-80H96V296z M216,296h80v-80h-80V296z
- M336,96v80h80V96H336z M216,176h80V96h-80V176z M336,296h80v-80h-80V296z M336,416h80v-80h-80V416z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-archive.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-archive.svg
deleted file mode 100644
index 1f0ce3ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-archive.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M453.594,100.001l-32.353-39.299C415.469,52.627,405.083,48,394.664,48H117.335c-10.416,0-20.801,4.627-26.576,12.702
- l-32.351,39.299C51.468,106.923,48,117.335,48,128.886v288.89C48,443.2,68.8,464,94.225,464h323.553
- C443.202,464,464,443.2,464,417.775v-288.89C464,117.335,460.537,106.923,453.594,100.001z M256,383.109L128.89,256h80.89v-46.224
- h92.443V256h80.89L256,383.109z M96.534,94.221l18.486-23.111h277.331l21.965,23.111H96.534z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-back.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-back.svg
deleted file mode 100644
index 309afd31..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-back.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_8_">
- <g>
- <path d="M427,234.625H167.296l119.702-119.702L256,85L85,256l171,171l29.922-29.924L167.296,277.375H427V234.625z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-down.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-down.svg
deleted file mode 100644
index 9e9a2cdf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-down.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_8_">
- <g>
- <path d="M277.375,85v259.704l119.702-119.702L427,256L256,427L85,256l29.924-29.922l119.701,118.626V85H277.375z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown-circle.svg
deleted file mode 100644
index 6393ec77..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown-circle.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48C141.125,48,48,141.125,48,256s93.125,208,208,208s208-93.125,208-208S370.875,48,256,48z M256,320l-96-96h192
- L256,320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown.svg
deleted file mode 100644
index 55ee520d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropdown.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="128,192 256,320 384,192 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft-circle.svg
deleted file mode 100644
index 9dd3aaba..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft-circle.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M464,256c0-114.875-93.125-208-208-208S48,141.125,48,256s93.125,208,208,208S464,370.875,464,256z M192,256l96-96v192
- L192,256z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft.svg
deleted file mode 100644
index d693f531..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropleft.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="320,128 192,256 320,384 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright-circle.svg
deleted file mode 100644
index 932b7917..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright-circle.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,464c114.875,0,208-93.125,208-208S370.875,48,256,48S48,141.125,48,256S141.125,464,256,464z M224,352V160l96,96
- L224,352z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright.svg
deleted file mode 100644
index 88fc3b84..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropright.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="192,128 320,256 192,384 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup-circle.svg
deleted file mode 100644
index 4633fba3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup-circle.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M464,256c0-114.875-93.125-208-208-208S48,141.125,48,256s93.125,208,208,208S464,370.875,464,256z M352,288H160l96-96
- L352,288z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup.svg
deleted file mode 100644
index 1400388c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-dropup.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="128,320 256,192 384,320 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-forward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-forward.svg
deleted file mode 100644
index e40696fd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-forward.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_8_">
- <g>
- <path d="M85,277.375h259.704L225.002,397.077L256,427l171-171L256,85l-29.922,29.924l118.626,119.701H85V277.375z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-up.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-up.svg
deleted file mode 100644
index e63ef5aa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-arrow-up.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_8_">
- <g>
- <path d="M277.375,427V167.296l119.702,119.702L427,256L256,85L85,256l29.924,29.922l119.701-118.626V427H277.375z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-attach.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-attach.svg
deleted file mode 100644
index ae889ab1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-attach.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_3_">
- <g>
- <path d="M341.334,128v234.666C341.334,409.604,302.938,448,256,448c-46.937,0-85.333-38.396-85.333-85.334V117.334
- C170.667,87.469,194.135,64,224,64c29.864,0,53.333,23.469,53.333,53.334v245.333c0,11.729-9.605,21.333-21.334,21.333
- c-11.729,0-21.333-9.604-21.333-21.333V160h-32v202.667C202.667,392.531,226.135,416,256,416
- c29.865,0,53.334-23.469,53.334-53.333V117.334C309.334,70.401,270.938,32,224,32c-46.938,0-85.334,38.401-85.334,85.334v245.332
- C138.667,427.729,190.938,480,256,480c65.062,0,117.334-52.271,117.334-117.334V128H341.334z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bar.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bar.svg
deleted file mode 100644
index a1f2bce0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bar.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_37_">
- <g>
- <path d="M234.667,277.333V408H128v40h256v-40H277.333V277.333L448,106.667V64H64v42.667L234.667,277.333z M160,149.333
- l-42.667-42.666h277.334L352,149.333H160z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bicycle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bicycle.svg
deleted file mode 100644
index fa8400a7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bicycle.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_13_">
- <g>
- <path d="M330.666,131.202c18.668,0,33.598-14.935,33.598-33.601S349.334,64,330.666,64C312,64,297.07,78.935,297.07,97.601
- S312,131.202,330.666,131.202z M386.666,261.334c-51.332,0-93.332,42-93.332,93.333s42,93.333,93.332,93.333
- C438,448,480,406,480,354.667S438,261.334,386.666,261.334z M386.666,420c-36.402,0-65.332-28.93-65.332-65.333
- s28.93-65.333,65.332-65.333c36.404,0,65.334,28.93,65.334,65.333S423.07,420,386.666,420z M305.597,224H384v-32h-58.845
- l-34.62-60.134c-5.605-9.333-15.869-15.864-27.07-15.864c-8.399,0-16.798,3.732-22.399,9.333l-71.732,69.065
- c-5.601,5.601-9.333,14-9.333,22.399c0,12.131,9.202,21.465,18.535,27.065L240,282.134V368h32V256l-39.333-32l42.929-44.533
- L305.597,224z M125.333,261.334C74,261.334,32,303.334,32,354.667S74,448,125.333,448c51.333,0,93.333-42,93.333-93.333
- S176.667,261.334,125.333,261.334z M125.333,420C88.934,420,60,391.07,60,354.667s28.934-65.333,65.333-65.333
- c36.399,0,65.333,28.93,65.333,65.333S161.732,420,125.333,420z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-boat.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-boat.svg
deleted file mode 100644
index 23000b4a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-boat.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M84.255,413h1.063c34.123,0,63.977-19.021,85.305-42.494c21.325,23.473,51.18,42.762,85.304,42.762
- s63.979-19.334,85.305-42.806C362.559,393.934,392.412,413,426.535,413h1.062l51.253-138.78c2.126-5.329,1.063-11.641-1.07-16.976
- c-2.136-5.333-7.237-8.487-12.567-10.623L427,234.133v-98.15C427,112.51,407.344,93,383.884,93h-63.979l-15.993-53h-95.969
- l-15.995,53h-63.979C104.511,93,85,112.51,85,135.982v98.15l-38.074,12.533c-5.33,2.136-10.582,5.334-12.718,10.667
- c-2.135,5.335-3.158,10.49-1.031,16.887L84.255,413z M128,136h256v84.261l-128-41.605l-128,41.605V136z"/>
- <path d="M341.231,408.007c-52.253,36.267-118.356,36.258-170.608-0.009c0,0-57.638,64.002-106.632,64.002h21.327
- c29.854,0,58.646-11.726,85.305-25.594c53.315,27.734,117.293,27.728,170.608-0.007C367.89,460.268,396.681,472,426.535,472h21.328
- C400.212,472,341.231,408.007,341.231,408.007z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bookmark.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bookmark.svg
deleted file mode 100644
index 799c8823..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bookmark.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M360,64H152c-22.002,0-40,17.998-40,40v344l144-64l144,64V104C400,81.998,382.002,64,360,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bulb.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bulb.svg
deleted file mode 100644
index 248bae16..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bulb.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_26_">
- <g>
- <path d="M256,170.136c25.499,0,49.567,10.025,67.771,28.229C341.975,216.568,352,240.637,352,266.136
- c0,17.621-4.422,34.031-13.144,48.773c-8.339,14.098-20.437,26.036-34.985,34.526L288,358.697v18.376V448h-64v-70.927v-18.376
- l-15.871-9.262C178.442,332.111,160,300.192,160,266.136c0-25.499,10.025-49.567,28.229-67.771
- C206.433,180.161,230.501,170.136,256,170.136 M277.333,32c-6.396,0-42.666,0-42.666,0v64h42.666V32L277.333,32z M406.396,85.864
- L368,124.271l29.864,29.865l38.406-38.396L406.396,85.864L406.396,85.864z M105.604,85.864l-29.875,29.875l38.406,38.396
- L144,124.271L105.604,85.864L105.604,85.864z M256,138.136c-70.396,0-128,57.604-128,128c0,46.938,25.604,88.531,64,110.938V480
- h128V377.073c38.396-22.406,64-62.938,64-110.938C384,195.739,326.396,138.136,256,138.136L256,138.136z M480,244.802h-64v42.667
- h64V244.802L480,244.802z M96,244.802H32v42.667h64V244.802L96,244.802z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bus.svg
deleted file mode 100644
index b55c0c20..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-bus.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_14_">
- <g>
- <g>
- <path d="M80,352c0,19.198,13.864,24.531,26.667,36.271v38.396c0,11.729,9.599,21.334,21.333,21.334h21.333
- c11.734,0,21.334-9.604,21.334-21.334v-21.333h170.666v21.333c0,11.729,9.604,21.334,21.334,21.334H384
- c11.729,0,21.333-9.604,21.333-21.334v-38.396C418.136,376.531,432,370.136,432,352V148.334C432,73.667,349.864,64,256,64
- S80,73.667,80,148.334V352z M160,367.989c-18.136,0-32-13.864-32-32c0-18.135,13.864-32,32-32s32,13.865,32,32
- C192,354.125,178.136,367.989,160,367.989z M352,367.989c-18.136,0-32-13.864-32-32c0-18.135,13.864-32,32-32s32,13.865,32,32
- C384,354.125,370.136,367.989,352,367.989z M384,245.333H128V138.667h256V245.333z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-calendar.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-calendar.svg
deleted file mode 100644
index 5fd9ed68..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-calendar.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M368.005,272h-96v96h96V272z M336.005,64v32h-160V64h-48v32h-24.01c-22.002,0-40,17.998-40,40v272
- c0,22.002,17.998,40,40,40h304.01c22.002,0,40-17.998,40-40V136c0-22.002-17.998-40-40-40h-24V64H336.005z M408.005,408h-304.01
- V196h304.01V408z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-call.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-call.svg
deleted file mode 100644
index e687edf4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-call.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M426.666,330.667c-26.666,0-52.271-4.271-75.729-11.729c-7.469-2.136-16-1.073-21.332,5.333l-46.939,46.928
- c-60.802-30.928-109.864-80-140.802-140.803l46.939-46.927c5.332-5.333,7.462-13.864,5.332-21.333
- c-8.537-24.531-12.802-50.136-12.802-76.803C181.333,73.604,171.734,64,160,64H85.333C73.599,64,64,73.604,64,85.333
- C64,285.864,226.136,448,426.666,448c11.73,0,21.334-9.604,21.334-21.333V352C448,340.271,438.396,330.667,426.666,330.667z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-camera.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-camera.svg
deleted file mode 100644
index 2dd4720a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-camera.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="256" cy="280" r="63"/>
- <path d="M440,96h-88l-32-32H192l-32,32H72c-22.092,0-40,17.908-40,40v272c0,22.092,17.908,40,40,40h368c22.092,0,40-17.908,40-40
- V136C480,113.908,462.092,96,440,96z M256,392c-61.855,0-112-50.145-112-112s50.145-112,112-112s112,50.145,112,112
- S317.855,392,256,392z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cancel.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cancel.svg
deleted file mode 100644
index ddcbee55..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cancel.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48C140.559,48,48,140.559,48,256c0,115.436,92.559,208,208,208c115.435,0,208-92.564,208-208
- C464,140.559,371.436,48,256,48z M360.002,330.881l-29.12,29.117L256,285.117l-74.881,74.881l-29.121-29.117L226.881,256
- l-74.883-74.881l29.121-29.116L256,226.881l74.881-74.878l29.12,29.116L285.119,256L360.002,330.881z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-car.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-car.svg
deleted file mode 100644
index 7b66a2e4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-car.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_15_">
- <g>
- <path d="M403.208,117.333c-4.271-12.802-16-21.333-29.875-21.333H138.667c-13.875,0-25.604,8.531-29.875,21.333L64,234.667v160
- C64,406.396,73.604,416,85.333,416h21.334c11.729,0,21.333-9.604,21.333-21.333V384h256v10.667
- c0,11.729,9.604,21.333,21.333,21.333h21.334c11.729,0,21.333-9.604,21.333-21.333v-160L403.208,117.333z M138.667,320
- c-18.125,0-32-13.865-32-32s13.875-32,32-32s32,13.866,32,32S156.792,320,138.667,320z M373.333,320c-18.125,0-32-13.865-32-32
- s13.875-32,32-32s32,13.866,32,32S391.458,320,373.333,320z M106.667,213.333l32-85.333h234.666l32,85.333H106.667z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cart.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cart.svg
deleted file mode 100644
index 1d97e720..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cart.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path fill="#010101" d="M169.6,377.6c-22.882,0-41.6,18.718-41.6,41.601c0,22.882,18.718,41.6,41.6,41.6s41.601-18.718,41.601-41.6
- C211.2,396.317,192.481,377.6,169.6,377.6z M48,51.2v41.6h41.6l74.883,151.682l-31.308,50.954c-3.118,5.2-5.2,12.482-5.2,19.765
- c0,27.85,19.025,41.6,44.825,41.6H416v-40H177.893c-3.118,0-5.2-2.082-5.2-5.2c0-1.036,2.207-5.2,2.207-5.2l20.782-32.8h154.954
- c15.601,0,29.128-8.317,36.4-21.836l74.882-128.8c1.237-2.461,2.082-6.246,2.082-10.399c0-11.446-9.364-19.765-20.8-19.765H135.364
- L115.6,51.2H48z M374.399,377.6c-22.882,0-41.6,18.718-41.6,41.601c0,22.882,18.718,41.6,41.6,41.6S416,442.082,416,419.2
- C416,396.317,397.281,377.6,374.399,377.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-chat.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-chat.svg
deleted file mode 100644
index 66d00096..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-chat.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M391.553,64H57.607C53.131,64,48,67.745,48,72.159v214.217c0,4.413,5.131,8.624,9.607,8.624H115v88.894L205.128,295
- h186.425c4.477,0,7.447-4.211,7.447-8.624V72.159C399,67.745,396.029,64,391.553,64z"/>
- <path d="M456.396,127H424v166.57c0,15.987-6.915,26.43-25.152,26.43H218.096l-38.905,39h129.688L399,448v-89h57.396
- c4.478,0,7.604-4.262,7.604-8.682V136.103C464,131.689,460.874,127,456.396,127z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-blank.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-blank.svg
deleted file mode 100644
index ff50d6bb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-blank.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_23_">
- <g>
- <path d="M405.333,64H106.667C83.198,64,64,83.198,64,106.667v298.666C64,428.802,83.198,448,106.667,448h298.666
- C428.802,448,448,428.802,448,405.333V106.667C448,83.198,428.802,64,405.333,64z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline-blank.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline-blank.svg
deleted file mode 100644
index dfce6d6a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline-blank.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_25_">
- <g>
- <path d="M405.333,106.667v298.666H106.667V106.667H405.333 M405.333,64H106.667C83.198,64,64,83.198,64,106.667v298.666
- C64,428.802,83.198,448,106.667,448h298.666C428.802,448,448,428.802,448,405.333V106.667C448,83.198,428.802,64,405.333,64
- L405.333,64z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline.svg
deleted file mode 100644
index 96fb444e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_24_">
- <g>
- <path d="M168.531,215.469l-29.864,29.864l96,96L448,128l-29.864-29.864L234.667,280.531L168.531,215.469z M405.333,405.333
- H106.667V106.667H320V64H106.667C83.198,64,64,83.198,64,106.667v298.666C64,428.802,83.198,448,106.667,448h298.666
- C428.802,448,448,428.802,448,405.333V234.667h-42.667V405.333z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox.svg
deleted file mode 100644
index f7718a02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkbox.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_22_">
- <g>
- <path d="M405.333,64H106.667C83.198,64,64,83.198,64,106.667v298.666C64,428.802,83.198,448,106.667,448h298.666
- C428.802,448,448,428.802,448,405.333V106.667C448,83.198,428.802,64,405.333,64z M213.333,362.667L106.667,256l29.864-29.864
- l76.802,76.802l162.136-162.136l29.864,29.865L213.333,362.667z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkmark-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkmark-circle.svg
deleted file mode 100644
index 32fe509c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-checkmark-circle.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M170.718,216.482L141.6,245.6L235.2,339.2l208-208l-29.118-29.118L235.2,279.918L170.718,216.482z M422.4,256
- c0,91.518-74.883,166.4-166.4,166.4S89.6,347.518,89.6,256S164.482,89.6,256,89.6c15.6,0,31.2,2.082,45.764,6.241L334,63.6
- C310.082,53.2,284.082,48,256,48C141.6,48,48,141.6,48,256s93.6,208,208,208s208-93.6,208-208H422.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-clipboard.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-clipboard.svg
deleted file mode 100644
index 97f22819..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-clipboard.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M405.333,80h-87.35C310.879,52.396,285.821,32,256,32s-54.879,20.396-61.983,48h-87.35C83.198,80,64,99.198,64,122.667
- v314.665C64,460.801,83.198,480,106.667,480h298.666C428.802,480,448,460.801,448,437.332V122.667C448,99.198,428.802,80,405.333,80
- z M256,80c11.729,0,21.333,9.599,21.333,21.333s-9.604,21.334-21.333,21.334s-21.333-9.6-21.333-21.334S244.271,80,256,80z M408,440
- H104V120h40v72h224v-72h40V440z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-close.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-close.svg
deleted file mode 100644
index 3184bc13..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-close.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_5_">
- <g>
- <polygon points="405,136.798 375.202,107 256,226.202 136.798,107 107,136.798 226.202,256 107,375.202 136.798,405 256,285.798
- 375.202,405 405,375.202 285.798,256 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-circle.svg
deleted file mode 100644
index bd8a656e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-circle.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_32_">
- <g>
- <g>
- <path d="M256,48C141.6,48,48,141.6,48,256s93.6,208,208,208c114.4,0,208-93.6,208-208S370.4,48,256,48z M349.6,339.2
- c0,0-175.759,0-176.799,0c-34.318,0-62.4-28.082-62.4-62.399c0-34.319,28.082-62.4,62.4-62.4c1.041,0,2.082,0,3.117,0
- c9.364-36.4,41.601-62.399,80.083-62.399c45.764,0,83.199,37.435,83.199,83.198h10.4c29.118,0,52,22.882,52,52.001
- C401.6,316.318,378.718,339.2,349.6,339.2z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-done.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-done.svg
deleted file mode 100644
index 8aa97173..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-done.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M403.002,217.001C388.998,148.002,328.998,96,256,96c-57.998,0-107.998,32.998-132.998,81.001
- C63.002,183.002,16,233.998,16,296c0,65.996,53.999,120,120,120h260c55,0,100-45,100-100
- C496,263.002,455.004,219.999,403.002,217.001z M213.333,362.667L138.667,288l29.864-29.864l44.802,44.802L324.271,192
- l29.865,29.864L213.333,362.667z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-outline.svg
deleted file mode 100644
index 98b34b15..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_9_">
- <g>
- <g>
- <path d="M403.001,217.001C388.997,148.002,328.998,96,256,96c-57.998,0-107.999,32.998-132.997,81
- C63.002,183.002,16,233.998,16,296c0,65.996,54.004,120,120,120h260c55,0,100-45,100-100.001
- C496,263.002,455.003,220,403.001,217.001z M396,376H136c-44.004,0-80-35.996-80-80c0-44,35.996-80,80-80h14.004
- c12.998-46,55-80,105.996-80c60.996,0,110,49,110,110v10h30c32.998,0,60,27.003,60,60C456,348.998,428.998,376,396,376z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud.svg
deleted file mode 100644
index 0869972a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-cloud.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M403.002,217.001C388.998,148.002,328.998,96,256,96c-57.998,0-107.998,32.998-132.998,81.001
- C63.002,183.002,16,233.998,16,296c0,65.996,53.999,120,120,120h260c55,0,100-45,100-100
- C496,263.002,455.004,219.999,403.002,217.001z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-color-palette.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-color-palette.svg
deleted file mode 100644
index fddb19cf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-color-palette.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_12_">
- <g>
- <path d="M256,64C150.401,64,64,150.401,64,256c0,105.604,86.401,192,192,192c18.136,0,32-13.864,32-32
- c0-8.531-3.198-16-8.531-21.333c-5.333-5.334-8.531-12.803-8.531-21.334c0-18.135,13.864-32,32-32h38.396
- c58.667,0,106.667-48,106.667-106.666C448,140.802,361.604,64,256,64z M138.667,256c-18.136,0-32-13.864-32-32s13.864-32,32-32
- c18.135,0,32,13.864,32,32S156.802,256,138.667,256z M202.667,170.667c-18.136,0-32-13.865-32-32c0-18.136,13.864-32,32-32
- c18.135,0,32,13.864,32,32C234.667,156.802,220.802,170.667,202.667,170.667z M309.333,170.667c-18.135,0-32-13.865-32-32
- c0-18.136,13.865-32,32-32c18.136,0,32,13.864,32,32C341.333,156.802,327.469,170.667,309.333,170.667z M373.333,256
- c-18.135,0-32-13.864-32-32s13.865-32,32-32c18.136,0,32,13.864,32,32S391.469,256,373.333,256z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-compass.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-compass.svg
deleted file mode 100644
index 6ae34a9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-compass.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,231.358c-13.442,0-24.643,11.2-24.643,24.642s11.2,24.643,24.643,24.643s24.643-11.2,24.643-24.643
- S269.442,231.358,256,231.358z M256,32C132.8,32,32,132.8,32,256s100.8,224,224,224s224-100.8,224-224S379.2,32,256,32z
- M305.284,305.284L121.6,390.4l85.116-183.679L390.4,121.6L305.284,305.284z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contact.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contact.svg
deleted file mode 100644
index 3b9b5aec..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contact.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M331.08,338.205c-22.156,12.594-47.777,19.783-75.084,19.783c-27.302,0-52.919-7.182-75.073-19.771
- C122.153,356.152,77.262,396,64,448h384C434.745,396,389.854,356.131,331.08,338.205z"/>
- <g>
- <path d="M255.996,64c-72.871,0-131.945,59.127-131.945,132.013c0,72.887,59.074,131.972,131.945,131.972
- s131.945-59.085,131.945-131.972C387.941,123.127,328.867,64,255.996,64z M255.996,294.986c-41.958,0-77.813-25.986-92.209-62.986
- h184.418C333.809,269,297.953,294.986,255.996,294.986z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contacts.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contacts.svg
deleted file mode 100644
index 271a5405..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contacts.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M239.208,343.937c-17.78,10.103-38.342,15.876-60.255,15.876c-21.909,0-42.467-5.771-60.246-15.87
- C71.544,358.331,42.643,406,32,448h293.912C315.273,406,286.375,358.317,239.208,343.937z"/>
- <g>
- <path d="M178.953,120.035c-58.479,0-105.886,47.394-105.886,105.858c0,58.464,47.407,105.857,105.886,105.857
- c58.479,0,105.886-47.394,105.886-105.857C284.839,167.429,237.431,120.035,178.953,120.035z M178.953,306.523
- c-33.671,0-62.445-22.513-73.997-50.523H252.95C241.396,284.011,212.624,306.523,178.953,306.523z"/>
- </g>
- </g>
- <g>
- <g>
- <path d="M322.602,384H480c-10.638-42-39.537-81.691-86.703-96.072c-17.781,10.104-38.343,15.873-60.256,15.873
- c-14.823,0-29.024-2.654-42.168-7.49c-7.445,12.47-16.927,25.592-27.974,34.906C289.245,341.354,309.146,364,322.602,384z"/>
- </g>
- <path d="M306.545,200h100.493c-11.554,28-40.327,50.293-73.997,50.293c-8.875,0-17.404-1.692-25.375-4.51
- c-1.338,8.709-3.543,17.07-6.52,25.118c10.066,3.174,20.779,4.862,31.895,4.862c58.479,0,105.886-47.41,105.886-105.872
- c0-58.465-47.407-105.866-105.886-105.866c-37.49,0-70.427,19.703-89.243,49.09C275.607,131.383,298.961,163,306.545,200z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contract.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contract.svg
deleted file mode 100644
index 8c4708c7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-contract.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_2_">
- <g>
- <path d="M64,371.2h76.795V448H192V320H64V371.2z M140.795,140.8H64V192h128V64h-51.205V140.8z M320,448h51.2v-76.8H448V320H320
- V448z M371.2,140.8V64H320v128h128v-51.2H371.2z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-create.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-create.svg
deleted file mode 100644
index d2cc74e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-create.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_6_">
- <g>
- <path fill="#010101" d="M64,368v80h80l235.727-235.729l-79.999-79.998L64,368z M441.602,150.398
- c8.531-8.531,8.531-21.334,0-29.865l-50.135-50.135c-8.531-8.531-21.334-8.531-29.865,0l-39.468,39.469l79.999,79.998
- L441.602,150.398z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-delete.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-delete.svg
deleted file mode 100644
index 9159a485..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-delete.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M128,405.429C128,428.846,147.198,448,170.667,448h170.667C364.802,448,384,428.846,384,405.429V160H128V405.429z M416,96
- h-80l-26.785-32H202.786L176,96H96v32h320V96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-desktop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-desktop.svg
deleted file mode 100644
index adcd30ee..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-desktop.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_28_">
- <g>
- <path d="M437.333,32H74.667C51.198,32,32,51.197,32,74.666v282.667C32,380.802,51.198,400,74.667,400h138.666l-42.666,48v32
- h170.666v-32l-42.666-48h138.666C460.802,400,480,380.802,480,357.333V74.666C480,51.197,460.802,32,437.333,32z M437.333,320
- H74.667V74.666h362.666V320z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-document.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-document.svg
deleted file mode 100644
index 91cd9d03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-document.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M288,48H136c-22.092,0-40,17.908-40,40v336c0,22.092,17.908,40,40,40h240c22.092,0,40-17.908,40-40V176L288,48z M272,192
- V80l112,112H272z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done-all.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done-all.svg
deleted file mode 100644
index 8260759d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done-all.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_4_">
- <g>
- <path d="M387.581,139.712L356.755,109L216.913,248.319l30.831,30.719L387.581,139.712z M481.172,109L247.744,340.469
- l-91.39-91.051l-30.827,30.715L247.744,403L512,139.712L481.172,109z M0,280.133L123.321,403l30.829-30.713L31.934,249.418
- L0,280.133z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done.svg
deleted file mode 100644
index fbd6e5cd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-done.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_1_">
- <g>
- <g>
- <polygon points="186.301,339.893 96,249.461 64,279.968 186.301,402 448,140.506 416,110 "/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-download.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-download.svg
deleted file mode 100644
index 2d629944..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-download.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M403.002,217.001C388.998,148.002,328.998,96,256,96c-57.998,0-107.998,32.998-132.998,81.001
- C63.002,183.002,16,233.998,16,296c0,65.996,53.999,120,120,120h260c55,0,100-45,100-100
- C496,263.002,455.004,219.999,403.002,217.001z M224,268v-76h64v76h68L256,368L156,268H224z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-drafts.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-drafts.svg
deleted file mode 100644
index 18745a76..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-drafts.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_18_">
- <g>
- <g>
- <path d="M480,201.667c0-14.933-7.469-28.803-20.271-36.266L256,64L52.271,165.401C40.531,172.864,32,186.734,32,201.667v203.666
- C32,428.802,51.197,448,74.666,448h362.668C460.803,448,480,428.802,480,405.333V201.667z M256,304L84.631,192L256,106.667
- L427.369,192L256,304z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-exit.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-exit.svg
deleted file mode 100644
index cf92b342..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-exit.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M215.469,332.802l29.863,29.864L352,256L245.332,149.333l-29.863,29.865l55.469,55.469H64v42.666h205.864L215.469,332.802z
- M405.334,64H106.666C83.198,64,64,83.198,64,106.666V192h42.666v-85.333h298.668v298.668H106.666V320H64v85.334
- C64,428.802,83.198,448,106.666,448h298.668C428.802,448,448,428.802,448,405.334V106.666C448,83.198,428.802,64,405.334,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-expand.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-expand.svg
deleted file mode 100644
index beb08b2e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-expand.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="396.795,396.8 320,396.8 320,448 448,448 448,320 396.795,320 "/>
- <polygon points="396.8,115.205 396.8,192 448,192 448,64 320,64 320,115.205 "/>
- <polygon points="115.205,115.2 192,115.2 192,64 64,64 64,192 115.205,192 "/>
- <polygon points="115.2,396.795 115.2,320 64,320 64,448 192,448 192,396.795 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite-outline.svg
deleted file mode 100644
index 15d6e6b9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M349.6,64c-36.4,0-70.718,16.742-93.6,43.947C233.117,80.742,198.8,64,162.4,64C97.918,64,48,114.221,48,179.095
- c0,79.516,70.718,143.348,177.836,241.694L256,448l30.164-27.211C393.281,322.442,464,258.61,464,179.095
- C464,114.221,414.082,64,349.6,64z M268.836,393.257l-4.219,3.873L256,404.903l-8.616-7.772l-4.214-3.869
- c-50.418-46.282-93.961-86.254-122.746-121.994C92.467,236.555,80,208.128,80,179.095c0-22.865,8.422-43.931,23.715-59.316
- C118.957,104.445,139.798,96,162.4,96c26.134,0,51.97,12.167,69.11,32.545L256,157.661l24.489-29.116
- C297.63,108.167,323.465,96,349.6,96c22.603,0,43.443,8.445,58.686,23.778C423.578,135.164,432,156.229,432,179.095
- c0,29.033-12.467,57.459-40.422,92.171C362.794,307.006,319.253,346.975,268.836,393.257z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite.svg
deleted file mode 100644
index 3b836628..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-favorite.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,448l-30.164-27.211C118.718,322.442,48,258.61,48,179.095C48,114.221,97.918,64,162.4,64
- c36.399,0,70.717,16.742,93.6,43.947C278.882,80.742,313.199,64,349.6,64C414.082,64,464,114.221,464,179.095
- c0,79.516-70.719,143.348-177.836,241.694L256,448z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-film.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-film.svg
deleted file mode 100644
index 13fbeb63..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-film.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path fill="#010101" d="M376,64v42.667h-40V64H176v42.667h-40V64H96v384h40v-42.666h40V448h160v-42.666h40V448h40V64H376z
- M176,362.667h-40V320h40V362.667z M176,277.334h-40v-42.667h40V277.334z M176,192h-40v-42.666h40V192z M376,362.667h-40V320h40
- V362.667z M376,277.334h-40v-42.667h40V277.334z M376,192h-40v-42.666h40V192z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder-open.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder-open.svg
deleted file mode 100644
index 19545aa6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder-open.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M437.334,144H256.006l-42.668-48H74.666C51.197,96,32,115.198,32,138.667v234.666C32,396.802,51.197,416,74.666,416h362.668
- C460.803,416,480,396.802,480,373.333V186.667C480,163.198,460.803,144,437.334,144z M448,373.333
- c0,5.782-4.885,10.667-10.666,10.667H74.666C68.884,384,64,379.115,64,373.333V176h373.334c5.781,0,10.666,4.885,10.666,10.667
- V373.333z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder.svg
deleted file mode 100644
index eb17131f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-folder.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_10_">
- <g>
- <g>
- <path d="M213.338,96H74.666C51.197,96,32,115.198,32,138.667v234.666C32,396.802,51.197,416,74.666,416h362.668
- C460.803,416,480,396.802,480,373.333V186.667C480,163.198,460.803,144,437.334,144H256.006L213.338,96z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-funnel.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-funnel.svg
deleted file mode 100644
index 0c9f0e1a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-funnel.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M208,400h96v-47.994h-96V400z M32,112v47.994h448V112H32z M112,280.783h288v-49.555H112V280.783z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-globe.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-globe.svg
deleted file mode 100644
index c65393e3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-globe.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C141.124,48,48,141.125,48,256c0,114.875,93.124,208,208,208c114.875,0,208-93.125,208-208
- C464,141.125,370.875,48,256,48z M234.451,432.999c-39.464-4.726-75.978-22.392-104.519-50.932
- C96.258,348.393,77.714,303.622,77.714,256c0-42.87,15.036-83.424,42.601-115.659c0.71,8.517,2.463,17.648,2.014,24.175
- c-1.64,23.795-3.988,38.687,9.94,58.762c5.426,7.819,6.759,19.028,9.4,28.078c2.583,8.854,12.902,13.498,20.019,18.953
- c14.359,11.009,28.096,23.805,43.322,33.494c10.049,6.395,16.326,9.576,13.383,21.839c-2.367,9.862-3.028,15.937-8.13,24.723
- c-1.557,2.681,5.877,19.918,8.351,22.392c7.498,7.497,14.938,14.375,23.111,21.125C254.396,404.351,240.494,417.954,234.451,432.999
- z M382.067,382.067c-25.633,25.633-57.699,42.486-92.556,49.081c4.94-12.216,13.736-23.07,21.895-29.362
- c7.097-5.476,15.986-16.009,19.693-24.352c3.704-8.332,8.611-15.555,13.577-23.217c7.065-10.899-17.419-27.336-25.353-30.781
- c-17.854-7.751-31.294-18.21-47.161-29.375c-11.305-7.954-34.257,4.154-47.02-1.417c-17.481-7.633-31.883-20.896-47.078-32.339
- c-15.68-11.809-14.922-25.576-14.922-42.997c12.282,0.453,29.754-3.399,37.908,6.478c2.573,3.117,11.42,17.042,17.342,12.094
- c4.838-4.043-3.585-20.249-5.212-24.059c-5.005-11.715,11.404-16.284,19.803-24.228c10.96-10.364,34.47-26.618,32.612-34.047
- s-23.524-28.477-36.249-25.193c-1.907,0.492-18.697,18.097-21.941,20.859c0.086-5.746,0.172-11.491,0.26-17.237
- c0.055-3.628-6.768-7.352-6.451-9.692c0.8-5.914,17.262-16.647,21.357-21.357c-2.869-1.793-12.659-10.202-15.622-8.968
- c-7.174,2.99-15.276,5.05-22.45,8.039c0-2.488-0.302-4.825-0.662-7.133c14.376-6.365,29.587-10.791,45.31-13.152l14.084,5.66
- l9.944,11.801l9.924,10.233l8.675,2.795l13.779-12.995L282,87.929v-8.339c27.25,3.958,52.984,14.124,75.522,29.8
- c-4.032,0.361-8.463,0.954-13.462,1.59c-2.065-1.22-4.714-1.774-6.965-2.623c6.531,14.042,13.343,27.89,20.264,41.746
- c7.393,14.801,23.793,30.677,26.673,46.301c3.394,18.416,1.039,35.144,2.896,56.811c1.788,20.865,23.524,44.572,23.524,44.572
- s10.037,3.419,18.384,2.228C421.055,330.798,405.103,359.029,382.067,382.067z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hand.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hand.svg
deleted file mode 100644
index 5fdc8100..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hand.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M450.679,273.5c-14.585-14.577-36.054-15.89-50.639-1.312l-41.687,41.664c-10.852,10.836-23.93,10.859-31.564,1.852
- c-5.057-5.968-3.061-24.374-1.644-36.049l20.907-171.849c1.867-15.353-9.07-30.185-24.43-32.051
- c-15.358-1.867-29.322,9.939-31.191,25.289L267.37,236.021c-1.205,3.358-3.79,3.938-4.081-0.582L255.44,60
- c0-15.465-12.542-28-28.014-28c-15.473,0-28.015,12.535-28.015,28l-0.552,176.752c0.146,2.04-1.604,2.624-1.92,0.294L172.016,99.077
- c-2.75-15.219-17.323-26.203-32.548-23.453c-15.227,2.748-25.339,18.187-22.591,33.403l22.193,161.455
- c0.023,2.872-0.941,4.513-2.308,0.831l-33.109-88.517c-5.18-14.572-21.196-23.065-35.776-17.889
- c-14.579,5.177-22.201,22.061-17.023,36.631l58.042,189.625c0.303,1.046,0.624,2.085,0.953,3.118l0.121,0.39
- c0.011,0.031,0.025,0.058,0.035,0.088C126.079,444.233,172.57,480,227.427,480c35.116,0,71.591-12.378,99.357-33.672
- c0.001,0,0.003-0.002,0.003-0.002c29.99-18.051,126.071-121.347,126.071-121.347C467.445,310.402,465.266,288.08,450.679,273.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hangout.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hangout.svg
deleted file mode 100644
index 08ba43be..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-hangout.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48c-97.321,0-176,77.114-176,172.487c0,95.38,78.679,172.487,176,172.487V464c100.425-47.689,176-152.195,176-243.513
- C432,125.114,353.321,48,256,48z M246,230.633L224.943,271H193.88l20.712-40H184v-61h62V230.633z M328,230.633L307.768,271h-31.063
- l20.704-40H266v-61h62V230.633z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-happy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-happy.svg
deleted file mode 100644
index 26072707..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-happy.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C140.563,48,48,141.6,48,256c0,114.4,92.563,208,208,208s208-93.6,208-208C464,141.6,370.401,48,256,48z M256,422.4
- c-91.518,0-166.404-74.883-166.404-166.4c0-91.518,74.887-166.4,166.404-166.4S422.404,164.482,422.404,256
- C422.404,347.518,347.518,422.4,256,422.4z M328.8,235.2c17.683,0,31.201-13.518,31.201-31.2s-13.519-31.2-31.201-31.2
- c-17.682,0-31.2,13.518-31.2,31.2S311.118,235.2,328.8,235.2z M183.2,235.2c17.682,0,31.2-13.518,31.2-31.2s-13.519-31.2-31.2-31.2
- c-17.683,0-31.201,13.518-31.201,31.2S165.518,235.2,183.2,235.2z M256,370.4c48.883,0,89.436-30.164,106.081-72.801H149.919
- C166.564,340.236,207.117,370.4,256,370.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-home.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-home.svg
deleted file mode 100644
index 44d4234d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-home.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="208,448 208,320 304,320 304,448 401.6,448 401.6,256 464,256 256,64 48,256 110.4,256 110.4,448 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-image.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-image.svg
deleted file mode 100644
index 568dfe46..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-image.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_8_">
- <g>
- <path d="M448,405.333V106.667C448,83.198,428.802,64,405.333,64H106.667C83.198,64,64,83.198,64,106.667v298.666
- C64,428.802,83.198,448,106.667,448h298.666C428.802,448,448,428.802,448,405.333z M181.333,288l53.334,64l74.666-96l96,128
- H106.667L181.333,288z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-laptop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-laptop.svg
deleted file mode 100644
index 07dcfb54..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-laptop.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_29_">
- <g>
- <path d="M437.334,416C460.803,416,480,396.803,480,373.334V106.668C480,83.199,460.803,64,437.334,64H74.666
- C51.197,64,32,83.199,32,106.668v266.666C32,396.803,51.197,416,74.666,416H0c0,23.469,64,32,96,32h320c32,0,96-8.531,96-32
- H437.334z M74.666,106.668h362.668v271.998H74.666V106.668z M256,434.666c-11.729,0-21.333-9.604-21.333-21.334
- c0-11.729,9.604-21.332,21.333-21.332s21.333,9.604,21.333,21.332C277.333,425.062,267.729,434.666,256,434.666z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-list.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-list.svg
deleted file mode 100644
index 95a27cc2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-list.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M408,64H104c-22.091,0-40,17.908-40,40v304c0,22.092,17.909,40,40,40h304c22.092,0,40-17.908,40-40V104
- C448,81.908,430.092,64,408,64z M304,368H144v-48h160V368z M368,280H144v-48h224V280z M368,192H144v-48h224V192z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-locate.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-locate.svg
deleted file mode 100644
index a7b72bc4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-locate.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon">
- <g>
- <path d="M256,176c-44.004,0-80.001,36-80.001,80c0,44.004,35.997,80,80.001,80c44.005,0,79.999-35.996,79.999-80
- C335.999,212,300.005,176,256,176z M446.938,234.667c-9.605-88.531-81.074-160-169.605-169.599V32h-42.666v33.067
- c-88.531,9.599-160,81.068-169.604,169.599H32v42.667h33.062c9.604,88.531,81.072,160,169.604,169.604V480h42.666v-33.062
- c88.531-9.604,160-81.073,169.605-169.604H480v-42.667H446.938z M256,405.333c-82.137,0-149.334-67.198-149.334-149.333
- c0-82.136,67.197-149.333,149.334-149.333c82.135,0,149.332,67.198,149.332,149.333C405.332,338.135,338.135,405.333,256,405.333z
- "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-lock.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-lock.svg
deleted file mode 100644
index fbc6418d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-lock.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M376,186h-20v-40c0-55-45-100-100-100S156,91,156,146v40h-20c-22.002,0-40,17.998-40,40v200c0,22.002,17.998,40,40,40h240
- c22.002,0,40-17.998,40-40V226C416,203.998,398.002,186,376,186z M256,368c-22.002,0-40-17.998-40-40s17.998-40,40-40
- s40,17.998,40,40S278.002,368,256,368z M318.002,186H193.998v-40c0-34.004,28.003-62.002,62.002-62.002
- c34.004,0,62.002,27.998,62.002,62.002V186z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-mail.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-mail.svg
deleted file mode 100644
index 1afcfa1e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-mail.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_19_">
- <g>
- <path d="M437.332,80H74.668C51.199,80,32,99.198,32,122.667v266.666C32,412.802,51.199,432,74.668,432h362.664
- C460.801,432,480,412.802,480,389.333V122.667C480,99.198,460.801,80,437.332,80z M432,170.667L256,288L80,170.667V128
- l176,117.333L432,128V170.667z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-map.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-map.svg
deleted file mode 100644
index 5be7a01b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-map.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_34_">
- <g>
- <g>
- <path d="M437.333,64c-2.176,0-4.396,1.369-9.176,3.207S320,108.802,320,108.802L192,64L71.469,104.531
- C67.197,105.604,64,109.864,64,115.197v322.136C64,443.729,68.271,448,74.666,448c1.828,0,6.505-2.33,9.087-3.319
- S192,403.197,192,403.197L320,448l120.531-40.531c4.271-1.073,7.469-5.334,7.469-10.667V74.666C448,68.271,443.729,64,437.333,64
- z M320,405.333l-128-44.802V106.666l128,44.803V405.333z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-menu.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-menu.svg
deleted file mode 100644
index 4d1cb7c0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-menu.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_3_">
- <g>
- <path d="M64,384h384v-42.666H64V384z M64,277.334h384v-42.667H64V277.334z M64,128v42.665h384V128H64z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone-off.svg
deleted file mode 100644
index 297562b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone-off.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M367.951,354.654l-26.616-26.562l-9.568-9.548l-4.698-4.706L187,174.041v0.346L76.112,63.531L51.921,87.572L187,222.47
- v28.816c0,37.79,31.121,68.714,68.91,68.714c8.61,0,16.952-1.62,24.565-4.545l32.389,32.274
- c-17.333,8.793-36.812,13.86-56.782,13.86c-62.986,0-121.365-48.59-121.365-116.59H95.773C95.773,322,158,387.701,233,398.013V480
- h46v-81.987c22-3.352,43.066-11.222,61.627-22.622l95.278,95.078l24.033-24l-33.847-33.785l-58.216-57.959l58.224,57.959
- L367.951,354.654z"/>
- <path d="M325,251.286V100.714C325,62.924,293.791,32,256,32s-69,30.924-69,68.714v25.244l137.109,136.968
- C324.779,259.135,325,255.247,325,251.286z"/>
- <path d="M416.439,245h-38.941c0,20.496-5.498,39.676-14.931,56.197l27.572,27.516C406.662,304.603,416.439,275.926,416.439,245z"/>
- <polygon points="459.999,446.427 426.102,412.684 459.957,446.469 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone.svg
deleted file mode 100644
index 35881609..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-microphone.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,320c37.712,0,68.571-30.924,68.571-68.714V100.714C324.571,62.924,293.712,32,256,32s-68.571,30.924-68.571,68.714
- v150.572C187.429,289.076,218.288,320,256,320z M377.139,244.548c0,68.714-58.282,116.815-121.139,116.815
- s-121.139-48.102-121.139-116.815H96c0,77.873,61.719,143.153,137.144,153.465V480h45.713v-81.987
- C354.281,386.561,416,322.421,416,244.548H377.139z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-horizontal.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-horizontal.svg
deleted file mode 100644
index c6f4af42..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-horizontal.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M136,216c-22.002,0-40,17.998-40,40s17.998,40,40,40s40-17.998,40-40S158.002,216,136,216z M376,216
- c-22.002,0-40,17.998-40,40s17.998,40,40,40s40-17.998,40-40S398.002,216,376,216z M256,216c-22.002,0-40,17.998-40,40
- s17.998,40,40,40s40-17.998,40-40S278.002,216,256,216z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-vertical.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-vertical.svg
deleted file mode 100644
index fbca23d0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-more-vertical.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M296,136c0-22.002-17.998-40-40-40s-40,17.998-40,40s17.998,40,40,40S296,158.002,296,136z M296,376
- c0-22.002-17.998-40-40-40s-40,17.998-40,40s17.998,40,40,40S296,398.002,296,376z M296,256c0-22.002-17.998-40-40-40
- s-40,17.998-40,40s17.998,40,40,40S296,278.002,296,256z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-navigate.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-navigate.svg
deleted file mode 100644
index 8bf06e12..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-navigate.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_5_">
- <g>
- <polygon points="256,64 96,433.062 110.938,448 256,384 401.062,448 416,433.062 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-none.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-none.svg
deleted file mode 100644
index d0400309..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-none.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M257,120.471c7.083,0,23.911,4.479,23.911,4.479c45.589,10.447,77.678,52.439,77.678,99.85v114.4v13.212l9.321,9.364
- l7.788,7.823H136.302l7.788-7.823l9.321-9.364V339.2V224.8c0-47.41,32.089-89.403,77.678-99.85c0,0,18.043-4.479,23.911-4.479
- M256,48c-17.602,0-31.059,13.518-31.059,31.2v14.559c-59.015,13.523-103.53,67.601-103.53,131.041v114.4L80,380.8v20.8h352v-20.8
- l-41.411-41.6V224.8c0-63.44-44.516-117.518-103.53-131.041V79.2C287.059,61.518,273.602,48,256,48L256,48z M297.411,422.4h-82.823
- c0,22.881,18.633,41.6,41.412,41.6S297.411,445.281,297.411,422.4L297.411,422.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-off.svg
deleted file mode 100644
index 5b65dd80..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications-off.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,463.656c22.814,0,41.475-18.656,41.475-41.656h-82.95C214.525,445,233.186,463.656,256,463.656z"/>
- <path d="M131.083,107.172l0.053,0.074L98.09,74.277L74.004,98.383l63.042,63.153C126.888,180.521,121,202.196,121,225.07v114.555
- l-41,41.656V402h297.743l36.182,36.33l24.079-24.301L425.9,402h0.316L131.083,107.172z"/>
- <path d="M391,225.07c0-63.526-45-117.677-104-131.218V79.274c0-17.706-13.371-31.243-31-31.243c-17.628,0-31,13.537-31,31.243
- v14.578c-15,3.438-29.048,9.501-41.75,17.663L391,319.355V225.07z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications.svg
deleted file mode 100644
index eb28dd22..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-notifications.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,464c22.779,0,41.411-18.719,41.411-41.6h-82.823C214.588,445.281,233.221,464,256,464z M390.589,339.2V224.8
- c0-63.44-44.516-117.518-103.53-131.041V79.2c0-17.682-13.457-31.2-31.059-31.2s-31.059,13.518-31.059,31.2v14.559
- c-59.015,13.523-103.53,67.601-103.53,131.041v114.4L80,380.8v20.8h352v-20.8L390.589,339.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-open.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-open.svg
deleted file mode 100644
index b004029c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-open.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M405.34,405.332H106.66V106.668H240V64H106.66C83.191,64,64,83.197,64,106.668v298.664C64,428.803,83.191,448,106.66,448
- h298.68c23.469,0,42.66-19.197,42.66-42.668V272h-42.66V405.332z M288,64v42.668h87.474L159.999,322.133l29.866,29.866
- l215.476-215.47V224H448V64H288z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-options.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-options.svg
deleted file mode 100644
index e95040b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-options.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <rect x="32" y="384" width="272" height="32"/>
- <rect x="400" y="384" width="80" height="32"/>
- <path d="M384,447.5c0,17.949-14.327,32.5-32,32.5l0,0c-17.673,0-32-14.551-32-32.5v-95c0-17.949,14.327-32.5,32-32.5l0,0
- c17.673,0,32,14.551,32,32.5V447.5z"/>
- </g>
- <g>
- <rect x="32" y="240" width="80" height="32"/>
- <rect x="208" y="240" width="272" height="32"/>
- <path d="M192,303.5c0,17.949-14.327,32.5-32,32.5l0,0c-17.673,0-32-14.551-32-32.5v-95c0-17.949,14.327-32.5,32-32.5l0,0
- c17.673,0,32,14.551,32,32.5V303.5z"/>
- </g>
- <g>
- <rect x="32" y="96" width="272" height="32"/>
- <rect x="400" y="96" width="80" height="32"/>
- <path d="M384,159.5c0,17.949-14.327,32.5-32,32.5l0,0c-17.673,0-32-14.551-32-32.5v-95c0-17.949,14.327-32.5,32-32.5l0,0
- c17.673,0,32,14.551,32,32.5V159.5z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-people.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-people.svg
deleted file mode 100644
index 0897dfd0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-people.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M337.454,232c33.599,0,61.092-27.002,61.092-60c0-32.997-27.493-60-61.092-60s-61.09,27.003-61.09,60
- C276.364,204.998,303.855,232,337.454,232z M174.546,232c33.599,0,61.09-27.002,61.09-60c0-32.997-27.491-60-61.09-60
- s-61.092,27.003-61.092,60C113.454,204.998,140.947,232,174.546,232z M174.546,276C126.688,276,32,298.998,32,346v54h288v-54
- C320,298.998,222.401,276,174.546,276z M337.454,287.003c-6.105,0-10.325,0-17.454,0.997c23.426,17.002,32,28,32,58v54h128v-54
- C480,298.998,385.312,287.003,337.454,287.003z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person-add.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person-add.svg
deleted file mode 100644
index e5ac6c6e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person-add.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M304,256c52.805,0,96-43.201,96-96s-43.195-96-96-96s-96,43.201-96,96S251.195,256,304,256z M304,304
- c-63.598,0-192,32.402-192,96v48h384v-48C496,336.402,367.598,304,304,304z"/>
- </g>
- <g id="Icon_16_">
- <g>
- <path d="M112,224v-64H80v64H16v32h64v64h32v-64h64v-32H112z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person.svg
deleted file mode 100644
index ac083d29..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-person.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,256c52.805,0,96-43.201,96-96s-43.195-96-96-96s-96,43.201-96,96S203.195,256,256,256z M256,304
- c-63.598,0-192,32.402-192,96v48h384v-48C448,336.402,319.598,304,256,304z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-landscape.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-landscape.svg
deleted file mode 100644
index 1311cb62..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-landscape.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_6_">
- <g>
- <path d="M480,358.856V153.143C480,130.512,461.674,112,439.272,112H72.728C50.326,112,32,130.512,32,153.143v205.713
- C32,381.488,50.326,400,72.728,400h366.545C461.674,400,480,381.488,480,358.856z M112,364V148h288v216H112z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-portrait.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-portrait.svg
deleted file mode 100644
index ff141828..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-phone-portrait.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_6_">
- <g>
- <path d="M358.856,32H153.143C130.512,32,112,50.326,112,72.728v366.545C112,461.674,130.512,480,153.143,480h205.713
- C381.488,480,400,461.674,400,439.272V72.728C400,50.326,381.488,32,358.856,32z M364,400H148V112h216V400z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-pin.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-pin.svg
deleted file mode 100644
index 54c59a8f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-pin.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,32c-88.004,0-160,70.557-160,156.801C96,306.4,256,480,256,480s160-173.6,160-291.199C416,102.557,344.004,32,256,32z
- M256,244.801c-31.996,0-57.144-24.645-57.144-56c0-31.357,25.147-56,57.144-56s57.144,24.643,57.144,56
- C313.144,220.156,287.996,244.801,256,244.801z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-plane.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-plane.svg
deleted file mode 100644
index bbe5d47e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-plane.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_36_">
- <g>
- <path d="M448,336v-40L288,192V79.2c0-17.683-14.82-31.2-32-31.2c-17.179,0-32,13.518-32,31.2V192L64,296v40l160-48v113.602
- l-48,31.199V464l80-16l80,16v-31.199l-48-31.199V288L448,336z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-playstore.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-playstore.svg
deleted file mode 100644
index a1ad5dc0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-playstore.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M464,152H360c0-57-46.562-103.859-104-103.859C198.562,48.141,152,95,152,152H48C66.688,368,61,464,61,464h389.999
- C450.998,464,445.311,366,464,152z M256,74.105c43.008,0,77.999,34.895,77.999,77.895H178C178,109,212.991,74.105,256,74.105z
- M204,397.64V228.867l142.999,84.387L204,397.64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-print.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-print.svg
deleted file mode 100644
index 89fa7e03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-print.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M399.95,160h-287.9C76.824,160,48,188.803,48,224v138.667h79.899V448h256.201v-85.333H464V224
- C464,188.803,435.175,160,399.95,160z M352,416H160V288h192V416z M384.101,64H127.899v80h256.201V64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-off.svg
deleted file mode 100644
index 59042e31..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-off.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_20_">
- <g>
- <path d="M256,48C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.399
- c-91.518,0-166.399-74.882-166.399-166.399S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.399,256,422.399z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-on.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-on.svg
deleted file mode 100644
index 06c0235e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-radio-button-on.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_21_">
- <g>
- <path d="M256,152c-57.2,0-104,46.8-104,104s46.8,104,104,104s104-46.8,104-104S313.2,152,256,152z M256,48
- C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.4
- c-91.518,0-166.4-74.883-166.4-166.4S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.4,256,422.4z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-refresh.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-refresh.svg
deleted file mode 100644
index 5b8867c2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-refresh.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,388c-72.597,0-132-59.405-132-132c0-72.601,59.403-132,132-132c36.3,0,69.299,15.4,92.406,39.601L278,234h154V80
- l-51.698,51.702C348.406,99.798,304.406,80,256,80c-96.797,0-176,79.203-176,176s78.094,176,176,176
- c81.045,0,148.287-54.134,169.401-128H378.85C360.105,353.561,311.712,388,256,388z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove-circle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove-circle.svg
deleted file mode 100644
index 341b22ea..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove-circle.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48C141.125,48,48,141.125,48,256s93.125,208,208,208s208-93.125,208-208S370.875,48,256,48z M363,277H149v-42h214V277
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove.svg
deleted file mode 100644
index d3cacf5f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-remove.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<rect x="96" y="235" width="320" height="42"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-restaurant.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-restaurant.svg
deleted file mode 100644
index 582e9bff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-restaurant.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_38_">
- <g>
- <g>
- <path d="M164.852,279.939l61.834-60.251L73.72,71.706c-33.626,32.764-33.626,86.677,0,119.44L164.852,279.939z"/>
- <path d="M312.389,241.88c33.636,14.802,80.283,4.232,113.91-29.593c41.222-40.165,49.909-98.303,17.363-128.96
- c-31.465-31.71-91.131-23.245-132.354,16.921c-34.718,33.825-45.566,79.276-30.374,110.986
- C233.195,258.802,69.382,418.407,69.382,418.407L99.759,448l149.71-145.866L399.177,448l30.374-29.593L279.842,272.538
- L312.389,241.88z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sad.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sad.svg
deleted file mode 100644
index 11a9d9e1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sad.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,288c-45.443,0-83.675,26.076-102.205,64h204.41C339.675,314.076,301.443,288,256,288z"/>
- <path d="M256,48C140.563,48,48,141.6,48,256c0,114.4,92.563,208,208,208s208-93.6,208-208C464,141.6,370.401,48,256,48z M256,422.4
- c-91.518,0-166.404-74.883-166.404-166.4c0-91.518,74.887-166.4,166.404-166.4S422.404,164.482,422.404,256
- C422.404,347.518,347.518,422.4,256,422.4z"/>
- <path d="M328.8,235.2c17.683,0,31.201-13.518,31.201-31.2s-13.519-31.2-31.201-31.2c-17.682,0-31.2,13.518-31.2,31.2
- S311.118,235.2,328.8,235.2z"/>
- <path d="M183.2,235.2c17.682,0,31.2-13.518,31.2-31.2s-13.519-31.2-31.2-31.2c-17.683,0-31.201,13.518-31.201,31.2
- S165.518,235.2,183.2,235.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-search.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-search.svg
deleted file mode 100644
index ef9d3f66..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-search.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_4_">
- <g>
- <g>
- <g>
- <path d="M337.509,305.372h-17.501l-6.571-5.486c20.791-25.232,33.922-57.054,33.922-93.257
- C347.358,127.632,283.896,64,205.135,64C127.452,64,64,127.632,64,206.629s63.452,142.628,142.225,142.628
- c35.011,0,67.831-13.167,92.991-34.008l6.561,5.487v17.551L415.18,448L448,415.086L337.509,305.372z M206.225,305.372
- c-54.702,0-98.463-43.887-98.463-98.743c0-54.858,43.761-98.742,98.463-98.742c54.7,0,98.462,43.884,98.462,98.742
- C304.687,261.485,260.925,305.372,206.225,305.372z"/>
- </g>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-send.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-send.svg
deleted file mode 100644
index 8f80fb4b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-send.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<polygon points="48,448 464,256 48,64 48,213.333 346,256 48,298.667 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-settings.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-settings.svg
deleted file mode 100644
index c16b089b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-settings.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M413.967,276.8c1.06-6.235,1.06-13.518,1.06-20.8s-1.06-13.518-1.06-20.8l44.667-34.318
- c4.26-3.118,5.319-8.317,2.13-13.518L418.215,115.6c-2.129-4.164-8.507-6.235-12.767-4.164l-53.186,20.801
- c-10.638-8.318-23.394-15.601-36.16-20.801l-7.448-55.117c-1.06-4.154-5.319-8.318-10.638-8.318h-85.098
- c-5.318,0-9.577,4.164-10.637,8.318l-8.508,55.117c-12.767,5.2-24.464,12.482-36.171,20.801l-53.186-20.801
- c-5.319-2.071-10.638,0-12.767,4.164l-42.549,71.765c-2.119,4.153-1.061,10.399,2.129,13.518L96.97,235.2
- c0,7.282-1.06,13.518-1.06,20.8s1.06,13.518,1.06,20.8l-44.668,34.318c-4.26,3.118-5.318,8.317-2.13,13.518L92.721,396.4
- c2.13,4.164,8.508,6.235,12.767,4.164l53.187-20.801c10.637,8.318,23.394,15.601,36.16,20.801l8.508,55.117
- c1.069,5.2,5.318,8.318,10.637,8.318h85.098c5.319,0,9.578-4.164,10.638-8.318l8.518-55.117c12.757-5.2,24.464-12.482,36.16-20.801
- l53.187,20.801c5.318,2.071,10.637,0,12.767-4.164l42.549-71.765c2.129-4.153,1.06-10.399-2.13-13.518L413.967,276.8z
- M255.468,328.8c-41.489,0-74.46-32.235-74.46-72.8s32.971-72.8,74.46-72.8s74.461,32.235,74.461,72.8S296.957,328.8,255.468,328.8
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share-alt.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share-alt.svg
deleted file mode 100644
index 821b4e21..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share-alt.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_33_">
- <g>
- <path d="M383.822,344.427c-16.045,0-31.024,5.326-41.721,15.979l-152.957-88.42c1.071-5.328,2.142-9.593,2.142-14.919
- c0-5.328-1.071-9.593-2.142-14.919l150.826-87.35c11.762,10.653,26.741,17.041,43.852,17.041c35.295,0,64.178-28.766,64.178-63.92
- C448,72.767,419.117,44,383.822,44c-35.297,0-64.179,28.767-64.179,63.92c0,5.327,1.065,9.593,2.142,14.919l-150.821,87.35
- c-11.767-10.654-26.741-17.041-43.856-17.041c-35.296,0-63.108,28.766-63.108,63.92c0,35.153,28.877,63.92,64.178,63.92
- c17.115,0,32.089-6.389,43.856-17.042l151.891,88.421c-1.076,4.255-2.141,8.521-2.141,13.847
- c0,34.094,27.806,61.787,62.037,61.787c34.229,0,62.036-27.693,62.036-61.787C445.858,372.12,418.052,344.427,383.822,344.427z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share.svg
deleted file mode 100644
index a38c4aba..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-share.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_17_">
- <g>
- <path d="M448,248L288,96v85.334C138.666,202.667,85.333,309.334,64,416c53.333-74.666,117.333-108.802,224-108.802v87.469L448,248
- z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-half.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-half.svg
deleted file mode 100644
index 53a14d00..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-half.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M458,210.409l-145.267-12.476L256,64l-56.743,133.934L54,210.409l110.192,95.524L131.161,448L256,372.686L380.83,448
- l-33.021-142.066L458,210.409z M272.531,345.287L256,335.313l-0.002-189.277l27.27,64.379l7.52,17.751l19.208,1.65l69.846,5.998
- l-52.993,45.939l-14.576,12.636l4.367,18.788l15.875,68.299L272.531,345.287z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-outline.svg
deleted file mode 100644
index 3a143120..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M458,210.409l-145.267-12.476L256,64l-56.743,133.934L54,210.409l110.192,95.524L131.161,448L256,372.686L380.83,448
- l-33.021-142.066L458,210.409z M272.531,345.286L256,335.312l-16.53,9.973l-59.988,36.191l15.879-68.296l4.369-18.79l-14.577-12.637
- l-52.994-45.939l69.836-5.998l19.206-1.65l7.521-17.75l27.276-64.381l27.27,64.379l7.52,17.751l19.208,1.65l69.846,5.998
- l-52.993,45.939l-14.576,12.636l4.367,18.788l15.875,68.299L272.531,345.286z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star.svg
deleted file mode 100644
index 4e0265f6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-star.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="256,372.686 380.83,448 347.809,305.934 458,210.409 312.733,197.934 256,64 199.257,197.934 54,210.409
- 164.192,305.934 131.161,448 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-stopwatch.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-stopwatch.svg
deleted file mode 100644
index 93a6fd44..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-stopwatch.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g id="Icon_7_">
- <g>
- <path d="M232,306.667h48V176h-48V306.667z"/>
- </g>
- </g>
- <g>
- <path d="M407.67,170.271l30.786-30.786l-33.942-33.941l-30.785,30.786C341.217,111.057,300.369,96,256,96
- C149.961,96,64,181.961,64,288s85.961,192,192,192s192-85.961,192-192C448,243.631,432.943,202.783,407.67,170.271z
- M362.066,394.066C333.734,422.398,296.066,438,256,438s-77.735-15.602-106.066-43.934C121.602,365.735,106,328.066,106,288
- s15.602-77.735,43.934-106.066C178.265,153.602,215.934,138,256,138s77.734,15.602,106.066,43.934
- C390.398,210.265,406,247.934,406,288S390.398,365.735,362.066,394.066z"/>
- <rect x="192" y="32" width="128" height="48"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-subway.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-subway.svg
deleted file mode 100644
index ad497847..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-subway.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48c-93.864,0-176,10.668-176,85.334v213.332c0,41.604,33.062,74.666,74.667,74.666L128,448v16h256v-16l-26.667-26.668
- c41.604,0,74.667-33.062,74.667-74.666V133.334C432,58.668,349.864,48,256,48z M160,384c-18.136,0-32-13.865-32-32
- c0-18.137,13.864-32,32-32s32,13.863,32,32C192,370.135,178.136,384,160,384z M240,240H128v-96h112V240z M352,384
- c-18.136,0-32-13.865-32-32c0-18.137,13.864-32,32-32s32,13.863,32,32C384,370.135,370.136,384,352,384z M384,240H272v-96h112V240z
- "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sunny.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sunny.svg
deleted file mode 100644
index c40c5807..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sunny.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_27_">
- <g>
- <path d="M256,160c25.499,0,49.567,10.025,67.771,28.229C341.975,206.433,352,230.501,352,256s-10.025,49.567-28.229,67.771
- C305.567,341.975,281.499,352,256,352s-49.567-10.025-67.771-28.229C170.025,305.567,160,281.499,160,256
- s10.025-49.567,28.229-67.771C206.433,170.025,230.501,160,256,160 M277.333,32h-42.666v64h42.666V32L277.333,32z M406.396,75.729
- L368,114.135L397.864,144l38.406-38.396L406.396,75.729L406.396,75.729z M105.604,75.729l-29.875,29.875L114.136,144L144,114.135
- L105.604,75.729L105.604,75.729z M256,128c-70.396,0-128,57.604-128,128s57.604,128,128,128s128-57.604,128-128
- S326.396,128,256,128L256,128z M480,234.666h-64v42.668h64V234.666L480,234.666z M96,234.666H32v42.668h64V234.666L96,234.666z
- M397.864,368L368,397.865l38.396,38.406l29.875-29.875L397.864,368L397.864,368z M114.136,368l-38.406,38.396l29.875,29.875
- L144,397.865L114.136,368L114.136,368z M277.333,416h-42.666v64c6.396,0,42.666,0,42.666,0V416L277.333,416z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sync.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sync.svg
deleted file mode 100644
index d91eeec0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-sync.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,93.09V32l-80,81.454l80,81.456v-61.093c65.996,0,120,54.982,120,122.183c0,20.363-5,39.714-14.004,57.016L391,342.547
- c15.996-25.457,25-54.988,25-86.547C416,166.401,343.998,93.09,256,93.09z M256,378.184c-66.001,0-120-54.988-120-122.184
- c0-20.363,5-39.709,13.999-57.02L121,169.454C104.999,193.89,96,224.436,96,256c0,89.599,72.002,162.91,160,162.91V480l80-81.453
- l-80-81.457V378.184z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-textsms.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-textsms.svg
deleted file mode 100644
index 294516bc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-textsms.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M408,64H96c-22.002,0-32,17.998-32,40v344l64-64h280c22.002,0,40-17.998,40-40V104C448,81.998,430.002,64,408,64z
- M198.4,242H160v-40h38.4V242z M275.2,242h-38.4v-40h38.4V242z M352,242h-38.4v-40H352V242z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-time.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-time.svg
deleted file mode 100644
index 929b2370..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-time.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_1_">
- <g>
- <g>
- <path fill-opacity="0.9" d="M256,43C137.789,43,43,138.851,43,256s94.789,213,213,213s213-95.851,213-213S373.149,43,256,43z
- M256,426.4c-93.718,0-170.4-76.683-170.4-170.4S162.282,85.6,256,85.6S426.4,162.282,426.4,256S349.718,426.4,256,426.4z"/>
- </g>
- <polygon fill-opacity="0.9" points="266.65,149.5 234.7,149.5 234.7,277.3 346.525,344.393 362.5,317.768 266.65,261.324 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-train.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-train.svg
deleted file mode 100644
index 1cd6da6d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-train.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_35_">
- <g>
- <g>
- <path d="M80,346.666c0,41.604,33.062,74.666,74.667,74.666L128,448v16h256v-16l-26.667-26.668
- c41.604,0,74.667-33.062,74.667-74.666V133.334C432,58.668,349.864,48,256,48S80,58.668,80,133.334V346.666z M256,376
- c-22.002,0-40-17.997-40-39.999S233.998,296,256,296s40,17.999,40,40.001S278.002,376,256,376z M384,224H128v-96h256V224z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-unlock.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-unlock.svg
deleted file mode 100644
index 6b816ac2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-unlock.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M376,186h-20v-40c0-55-45-100-100-100S156,91,156,146h37.998c0-34.004,28.003-62.002,62.002-62.002
- c34.004,0,62.002,27.998,62.002,62.002H318v40H136c-22.002,0-40,17.998-40,40v200c0,22.002,17.998,40,40,40h240
- c22.002,0,40-17.998,40-40V226C416,203.998,398.002,186,376,186z M256,368c-22.002,0-40-17.998-40-40s17.998-40,40-40
- s40,17.998,40,40S278.002,368,256,368z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-upload.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-upload.svg
deleted file mode 100644
index ed7edd2a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-upload.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M403.002,217.001C388.998,148.002,328.998,96,256,96c-57.998,0-107.998,32.998-132.998,81.001
- C63.002,183.002,16,233.998,16,296c0,65.996,53.999,120,120,120h260c55,0,100-45,100-100
- C496,263.002,455.004,219.999,403.002,217.001z M288,276v76h-64v-76h-68l100-100l100,100H288z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-down.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-down.svg
deleted file mode 100644
index ceac980e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-down.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M64,192v128h85.334L256,431.543V80.458L149.334,192H64z M352,256c0-38.399-21.333-72.407-53.333-88.863v176.636
- C330.667,328.408,352,294.4,352,256z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-mute.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-mute.svg
deleted file mode 100644
index 6cb847b7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-mute.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M64,192v128h85.334L256,431.543V80.458L149.334,192H64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-off.svg
deleted file mode 100644
index 517c3138..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-off.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M405.5,256c0,22.717-4.883,44.362-13.603,63.855l31.88,31.88C439.283,323.33,448,290.653,448,256
- c0-93.256-64-172.254-149-192v44.978C361,127.632,405.5,186.882,405.5,256z"/>
- <polygon points="256,80.458 204.979,132.938 256,183.957 "/>
- <path d="M420.842,396.885L91.116,67.157l-24,24l90.499,90.413l-8.28,10.43H64v128h85.334L256,431.543V280l94.915,94.686
- C335.795,387.443,318,397.213,299,403.022V448c31-7.172,58.996-22.163,82.315-42.809l39.61,39.693l24-24.043l-24.002-24.039
- L420.842,396.885z"/>
- <path d="M352.188,256c0-38.399-21.188-72.407-53.188-88.863v59.82l50.801,50.801C351.355,270.739,352.188,263.454,352.188,256z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-up.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-up.svg
deleted file mode 100644
index 0a8b8b53..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-volume-up.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M64,192v128h85.334L256,431.543V80.458L149.334,192H64z M352,256c0-38.399-21.333-72.407-53.333-88.863v176.636
- C330.667,328.408,352,294.4,352,256z M298.667,64v44.978C360.531,127.632,405.334,186.882,405.334,256
- c0,69.119-44.803,128.369-106.667,147.022V448C384,428.254,448,349.257,448,256C448,162.744,384,83.746,298.667,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-walk.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-walk.svg
deleted file mode 100644
index 38252ac8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-walk.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M288,112c22.223,0,39.997-17.776,39.997-40c0-22.225-17.774-40-39.997-40s-40.003,17.775-40.003,40
- C247.997,94.224,265.777,112,288,112z"/>
- <path d="M288,232h104v-40h-72l-44.802-69.333c-7.698-11.667-18.136-18.136-30.933-18.136c-3.198,0-8.828,0.531-12.799,1.747
- L120,144v112h40v-80l40.531-16L120,480h40l56.698-164.271L267,384v96h38V352l-57.031-96l19.745-61.864L288,232z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-warning.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-warning.svg
deleted file mode 100644
index 1525a3eb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-warning.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_31_">
- <g>
- <path d="M32,464h448L256,48L32,464z M280,400h-48v-48h48V400z M280,320h-48v-96h48V320z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-watch.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-watch.svg
deleted file mode 100644
index 6ecfdf7c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-watch.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon_11_">
- <g>
- <g>
- <path d="M416,256c0-51.001-24.004-96.001-60.996-125L336,16H176l-19.004,115C120.004,159.999,96,204.999,96,256
- c0,50.996,24.004,95.996,60.996,125L176,496h160l19.004-115C391.996,351.996,416,306.996,416,256z M136,256
- c0-66.001,54.004-120,120-120s120,53.999,120,120c0,65.996-54.004,120-120,120S136,321.996,136,256z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-wifi.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-wifi.svg
deleted file mode 100644
index 73615429..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/android-wifi.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,228.719c-22.879,0-41.597,18.529-41.597,41.18c0,22.652,18.718,41.182,41.597,41.182
- c22.878,0,41.597-18.529,41.597-41.182C297.597,247.248,278.878,228.719,256,228.719z M380.8,269.898
- c0-67.946-56.163-123.539-124.8-123.539s-124.8,55.593-124.8,123.539c0,45.303,24.961,85.447,62.396,107.072l20.807-36.032
- c-24.972-14.417-41.604-40.153-41.604-71.04c0-45.295,37.433-82.358,83.201-82.358c45.771,0,83.201,37.063,83.201,82.358
- c0,30.887-16.633,56.623-41.604,71.04l20.807,36.032C355.837,355.346,380.8,315.201,380.8,269.898z M256,64
- C141.597,64,48,156.654,48,269.898C48,346.085,89.592,411.968,152,448l20.799-36.032c-49.919-28.824-83.207-81.324-83.207-142.069
- c0-90.593,74.891-164.718,166.408-164.718c91.517,0,166.406,74.125,166.406,164.718c0,60.745-33.284,114.271-83.205,142.069L360,448
- c62.406-36.032,104-101.915,104-178.102C464,156.654,370.403,64,256,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/aperture.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/aperture.svg
deleted file mode 100644
index 41cf7ebe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/aperture.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M391.765,391.765
- C355.5,428.028,307.285,448,256,448s-99.5-19.972-135.765-56.235C83.972,355.5,64,307.285,64,256s19.972-99.5,56.235-135.765
- C156.5,83.972,204.715,64,256,64s99.5,19.972,135.765,56.235C428.028,156.5,448,204.715,448,256S428.028,355.5,391.765,391.765z"/>
- <g>
- <path d="M200.043,106.067c-40.631,15.171-73.434,46.382-90.717,85.933H256L200.043,106.067z"/>
- <path d="M412.797,288c2.099-10.34,3.203-21.041,3.203-32c0-36.624-12.314-70.367-33.016-97.334L311,288H412.797z"/>
- <path d="M359.973,134.395C332.007,110.461,295.694,96,256,96c-7.966,0-15.794,0.591-23.448,1.715L310.852,224L359.973,134.395z"/>
- <path d="M99.204,224C97.104,234.34,96,245.041,96,256c0,36.639,12.324,70.394,33.041,97.366L201,224H99.204z"/>
- <path d="M311.959,405.932c40.631-15.171,73.433-46.382,90.715-85.932H256L311.959,405.932z"/>
- <path d="M152.046,377.621C180.009,401.545,216.314,416,256,416c7.969,0,15.799-0.592,23.456-1.716L201.164,288L152.046,377.621z"
- />
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/archive.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/archive.svg
deleted file mode 100644
index 44eb44b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/archive.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="256,307.7 384,192 304,192 304,96 207.6,96 207.6,192 128,192 "/>
- <path d="M465.4,297.2l-71.4-55h-42l62,61.8h-50.6c-2.3,0-4.3,1.2-5.4,2.9l-18.4,45.5H172.1l-18.4-45.5c-1-1.8-3.1-2.9-5.4-2.9H97.8
- l62.2-61.8h-42.2l-71.4,55c-10.6,6.2-15.8,19-14.1,31.6l8.7,66.9c2.3,13.1,9.7,20.3,28.1,20.3h373.8c19.1,0,25.8-7.6,28.1-20.3
- l8.7-66.9C481.4,315.9,476,303.4,465.4,297.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-a.svg
deleted file mode 100644
index 7d476caf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-a.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="256.5,448.5 448.5,256.5 336.5,256.5 336.5,64.5 176.5,64.5 176.5,256.5 64.5,256.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-b.svg
deleted file mode 100644
index 247b81f4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-b.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M98.9,184.7l1.8,2.1l136,156.5c4.6,5.3,11.5,8.6,19.2,8.6c7.7,0,14.6-3.4,19.2-8.6L411,187.1l2.3-2.6
- c1.7-2.5,2.7-5.5,2.7-8.7c0-8.7-7.4-15.8-16.6-15.8v0H112.6v0c-9.2,0-16.6,7.1-16.6,15.8C96,179.1,97.1,182.2,98.9,184.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-c.svg
deleted file mode 100644
index d8ef45b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-down-c.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M383.6,322.7L278.6,423c-5.8,6-13.7,9-22.4,9c-8.7,0-16.5-3-22.4-9L128.4,322.7c-12.5-11.9-12.5-31.3,0-43.2
- c12.5-11.9,32.7-11.9,45.2,0l50.4,48.2v-217c0-16.9,14.3-30.6,32-30.6c17.7,0,32,13.7,32,30.6v217l50.4-48.2
- c12.5-11.9,32.7-11.9,45.2,0C396.1,291.4,396.1,310.7,383.6,322.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-expand.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-expand.svg
deleted file mode 100644
index 268973dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-expand.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="274,209.7 337.9,145.9 288,96 416,96 416,224 366.1,174.1 302.3,238 "/>
- <polygon points="274,302.3 337.9,366.1 288,416 416,416 416,288 366.1,337.9 302.3,274 "/>
- <polygon points="238,302.3 174.1,366.1 224,416 96,416 96,288 145.9,337.9 209.7,274 "/>
- <polygon points="238,209.7 174.1,145.9 224,96 96,96 96,224 145.9,174.1 209.7,238 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-left.svg
deleted file mode 100644
index 85f8dce0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-left.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="32,384 32,224 92.8,284.8 223.7,144 330.7,256 480,128 330.7,330.7 223.7,224 130.2,322.2 192,384 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-right.svg
deleted file mode 100644
index bd77539a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-down-right.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="320,384 381.8,322.2 288.3,224 181.3,330.7 32,128 181.3,256 288.3,144 419.2,284.8 480,224 480,384 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-left.svg
deleted file mode 100644
index 57ea68cb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-left.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="192,128 130.2,189.8 223.7,288 330.7,181.3 480,384 330.7,256 223.7,368 92.8,227.2 32,288 32,128 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-right.svg
deleted file mode 100644
index 689af444..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-graph-up-right.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="320,128 381.8,189.8 288.3,288 181.3,181.3 32,384 181.3,256 288.3,368 419.2,227.2 480,288 480,128 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-a.svg
deleted file mode 100644
index ad3fb71f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-a.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="64.5,256.5 256.5,448.5 256.5,336.5 448.5,336.5 448.5,176.5 256.5,176.5 256.5,64.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-b.svg
deleted file mode 100644
index 43602dbe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-b.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M327.3,98.9l-2.1,1.8l-156.5,136c-5.3,4.6-8.6,11.5-8.6,19.2c0,7.7,3.4,14.6,8.6,19.2L324.9,411l2.6,2.3
- c2.5,1.7,5.5,2.7,8.7,2.7c8.7,0,15.8-7.4,15.8-16.6h0V112.6h0c0-9.2-7.1-16.6-15.8-16.6C332.9,96,329.8,97.1,327.3,98.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-c.svg
deleted file mode 100644
index b4a07c85..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-left-c.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M189.3,128.4L89,233.4c-6,5.8-9,13.7-9,22.4c0,8.7,3,16.5,9,22.4l100.3,105.4c11.9,12.5,31.3,12.5,43.2,0
- c11.9-12.5,11.9-32.7,0-45.2L184.4,288h217c16.9,0,30.6-14.3,30.6-32c0-17.7-13.7-32-30.6-32h-217l48.2-50.4
- c11.9-12.5,11.9-32.7,0-45.2C220.6,115.9,201.3,115.9,189.3,128.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-move.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-move.svg
deleted file mode 100644
index 52541875..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-move.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="480,256 384,160 384,236 276,236 276,128 352,128 256,32 160,128 236,128 236,236 128,236 128,160 32,256 128,352
- 128,276 236,276 236,384 160,384 256,480 352,384 275.8,384 275.4,275.5 384,275.8 384,352 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-resize.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-resize.svg
deleted file mode 100644
index 24feb255..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-resize.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="288,96 337.9,145.9 274,209.7 274,209.7 145.9,337.9 96,288 96,416 224,416 174.1,366.1 357.4,182.9 366.1,174.1
- 416,224 416,96 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-left.svg
deleted file mode 100644
index a2dbb861..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-left.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M192,96v64h248c4.4,0,8,3.6,8,8v240c0,4.4-3.6,8-8,8H136c-4.4,0-8-3.6-8-8v-48c0-4.4,3.6-8,8-8h248V224H192v64L64,192
- L192,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-right.svg
deleted file mode 100644
index 79deb8b8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-return-right.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448,192l-128,96v-64H128v128h248c4.4,0,8,3.6,8,8v48c0,4.4-3.6,8-8,8H72c-4.4,0-8-3.6-8-8V168c0-4.4,3.6-8,8-8h248V96
- L448,192z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-a.svg
deleted file mode 100644
index fb6d0d67..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-a.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="448.5,256.5 256.5,64.5 256.5,176.5 64.5,176.5 64.5,336.5 256.5,336.5 256.5,448.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-b.svg
deleted file mode 100644
index 847718b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-b.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M184.7,413.1l2.1-1.8l156.5-136c5.3-4.6,8.6-11.5,8.6-19.2c0-7.7-3.4-14.6-8.6-19.2L187.1,101l-2.6-2.3
- C182,97,179,96,175.8,96c-8.7,0-15.8,7.4-15.8,16.6h0v286.8h0c0,9.2,7.1,16.6,15.8,16.6C179.1,416,182.2,414.9,184.7,413.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-c.svg
deleted file mode 100644
index 97f20cad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-right-c.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M322.7,128.4L423,233.4c6,5.8,9,13.7,9,22.4c0,8.7-3,16.5-9,22.4L322.7,383.6c-11.9,12.5-31.3,12.5-43.2,0
- c-11.9-12.5-11.9-32.7,0-45.2l48.2-50.4h-217C93.7,288,80,273.7,80,256c0-17.7,13.7-32,30.6-32h217l-48.2-50.4
- c-11.9-12.5-11.9-32.7,0-45.2C291.4,115.9,310.7,115.9,322.7,128.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-shrink.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-shrink.svg
deleted file mode 100644
index 5c29eddb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-shrink.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="448,92.3 366.1,174.1 416,224 288,224 288,96 337.9,145.9 419.7,64 "/>
- <polygon points="448,419.7 366.1,337.9 416,288 288,288 288,416 337.9,366.1 419.7,448 "/>
- <polygon points="64,419.7 145.9,337.9 96,288 224,288 224,416 174.1,366.1 92.3,448 "/>
- <polygon points="64,92.3 145.9,174.1 96,224 224,224 224,96 174.1,145.9 92.3,64 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-swap.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-swap.svg
deleted file mode 100644
index aabe881e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-swap.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,328v48c0,4.4,3.6,8,8,8h248v64l128-96l-128-96v64H72C67.6,320,64,323.6,64,328z"/>
- <path d="M448,184v-48c0-4.4-3.6-8-8-8H192V64L64,160l128,96v-64h248C444.4,192,448,188.4,448,184z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-a.svg
deleted file mode 100644
index f908a1bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-a.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="256.5,64.5 64.5,256.5 176.5,256.5 176.5,448.5 336.5,448.5 336.5,256.5 448.5,256.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-b.svg
deleted file mode 100644
index 01b790de..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-b.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M413.1,327.3l-1.8-2.1l-136-156.5c-4.6-5.3-11.5-8.6-19.2-8.6c-7.7,0-14.6,3.4-19.2,8.6L101,324.9l-2.3,2.6
- C97,330,96,333,96,336.2c0,8.7,7.4,15.8,16.6,15.8v0h286.8v0c9.2,0,16.6-7.1,16.6-15.8C416,332.9,414.9,329.8,413.1,327.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-c.svg
deleted file mode 100644
index cc291b3d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/arrow-up-c.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M128.4,189.3L233.4,89c5.8-6,13.7-9,22.4-9c8.7,0,16.5,3,22.4,9l105.4,100.3c12.5,11.9,12.5,31.3,0,43.2
- c-12.5,11.9-32.7,11.9-45.2,0L288,184.4v217c0,16.9-14.3,30.6-32,30.6c-17.7,0-32-13.7-32-30.6v-217l-50.4,48.2
- c-12.5,11.9-32.7,11.9-45.2,0C115.9,220.6,115.9,201.3,128.4,189.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/asterisk.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/asterisk.svg
deleted file mode 100644
index 34f54922..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/asterisk.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<polygon points="480,224 293.172,231.487 401.688,64 342.441,32 256,208 169.824,32 110.328,64 218.828,231.487 32,224 32,288
- 217.537,277.934 113.65,448 169.619,480 256,304 342.381,480 398.33,448 294.463,277.934 480,288 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/at.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/at.svg
deleted file mode 100644
index 7d8a68b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/at.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M453.8,407.1c-23.9,25.3-52.3,43.8-85.2,55.4C335.7,474.2,301,480,264.5,480c-34.9,0-66.7-5.5-95.3-16.6
- c-28.6-11-53.1-26.4-73.3-46.1c-20.3-19.7-36-43.3-47.2-70.8c-11.2-27.5-16.7-57.5-16.7-90c0-32.1,6.1-61.8,18.3-89.1
- c12.2-27.3,28.8-51,49.9-71.1c21.1-20.1,45.7-35.8,74-47.3C202.3,37.7,232.5,32,264.5,32c27.6,0,54.4,4,80.3,12
- c26,8,49,20.1,69.1,36.1c20.1,16.1,36.1,36.1,48.1,60.2c12,24.1,18,52.4,18,84.9c0,24.1-3.3,45.4-10,63.8
- c-6.7,18.5-15.6,33.9-26.8,46.4c-11.2,12.5-23.9,21.8-38.3,28c-14.4,6.2-29.5,9.3-45.3,9.3c-16.2,0-29.2-3.8-39-11.4
- c-9.7-7.6-14.6-17.3-14.6-28.9h-3c-6.1,9.6-15.4,18.8-28,27.4c-12.6,8.6-28,13-46.3,13c-27.6,0-48.9-9-63.9-27.1
- c-15-18.1-22.5-41.5-22.5-70.5c0-16.9,2.8-33.5,8.5-50c5.7-16.5,13.8-31.1,24.3-44c10.5-12.8,23.1-23.2,37.7-31
- c14.6-7.8,30.8-11.7,48.7-11.7c15.4,0,28.4,3.2,39,9.6c10.5,6.4,17.4,14.3,20.7,23.5h0.6l4.9-24.1h54.2L357,261.4
- c-0.8,5.6-1.9,11.8-3.3,18.7c-1.4,6.8-2.1,13.2-2.1,19.3c0,6.8,1.3,12.5,4,17.2c2.6,4.6,7.8,6.9,15.5,6.9
- c15.8,0,28.9-8.4,39.3-25.3c10.3-16.9,15.5-39.5,15.5-68c0-24.1-4.1-45.5-12.2-64.1c-8.1-18.7-19.4-34.3-33.8-47
- c-14.4-12.6-31.6-22.2-51.4-28.6c-19.9-6.4-41.6-9.6-65.1-9.6c-25.6,0-49,4.5-70.3,13.5s-39.5,21.5-54.5,37.3
- c-15,15.9-26.7,34.5-35,56C95.2,209.1,91,232.3,91,257.2c0,26.5,4.4,50.4,13.1,71.7c8.7,21.3,21,39.4,36.8,54.5
- c15.8,15.1,34.7,26.6,56.6,34.6c21.9,8,46.1,12,72.4,12c32.9,0,61.2-5.2,84.9-15.7c23.7-10.4,45.5-24.9,65.4-43.4L453.8,407.1z
- M263.3,188c-9.7,0-18.3,2.8-25.6,8.4c-7.3,5.6-13.5,12.7-18.6,21.4c-5.1,8.6-8.9,18.2-11.6,28.6c-2.6,10.4-4,20.5-4,30.1
- c0,4.8,0.5,9.9,1.5,15.4c1,5.4,3,10.4,6.1,15.1c3,4.6,7,8.4,11.9,11.4c4.9,3,11.4,4.5,19.5,4.5c11,0,20.3-2.7,28-8.1
- c7.7-5.4,14-12.2,18.9-20.5c4.9-8.2,8.4-17.2,10.7-26.8c2.2-9.6,3.3-18.5,3.3-26.5c0-6.4-0.6-12.7-1.8-19
- c-1.2-6.2-3.3-11.8-6.4-16.9c-3-5-7.2-9.1-12.5-12.3C277.5,189.6,271,188,263.3,188z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace-outline.svg
deleted file mode 100644
index 19d2fe2c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace-outline.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M413.442,332.307c1.528,1.51,2.372,3.562,2.372,5.71c0,2.151-0.844,4.203-2.372,5.707l-21.823,21.905
- c-1.575,1.586-3.625,2.371-5.691,2.371c-2.071,0-4.138-0.785-5.695-2.371l-76.23-76.461l-76.23,76.461
- c-1.558,1.586-3.625,2.371-5.695,2.371c-2.066,0-4.117-0.785-5.692-2.371l-21.824-21.905c-1.527-1.504-2.373-3.556-2.373-5.707
- c0-2.148,0.846-4.2,2.373-5.71L271.098,256l-76.738-76.297c-3.146-3.153-3.146-8.273,0-11.427l21.807-21.919
- c1.516-1.511,3.552-2.357,5.696-2.357c2.152,0,4.189,0.847,5.691,2.357l76.448,75.533l76.447-75.533
- c1.504-1.511,3.541-2.357,5.693-2.357c2.143,0,4.179,0.847,5.695,2.357l21.807,21.919c3.146,3.153,3.146,8.273,0,11.427
- L336.904,256L413.442,332.307z"/>
- </g>
- <path d="M498.941,93.559C490.037,84.654,478.696,80,465.875,80H168c-24.303,0-43.717,9.402-57.706,28.441L0,255.938l110.4,146.528
- l0.18,0.231l0.184,0.232c6.904,8.855,14.424,15.701,22.99,20.417C143.883,428.924,155.405,432,168,432h298
- c26.191,0,46-22.257,46-49V127C512,114.179,507.846,102.463,498.941,93.559z M480,383c0,8.837-5.163,17-14,17H168
- c-15.167,0-24.333-6.666-32-16.5L40,256l96-128.438c9.5-13,21.167-15.562,32-15.562h297.5c8.837,0,14.5,6.163,14.5,15V383z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace.svg
deleted file mode 100644
index f02fff97..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/backspace.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M498.941,93.559C490.037,84.654,478.696,80,465.875,80H168c-24.303,0-43.717,9.402-57.706,28.441L0,255.938l110.4,146.528
- l0.18,0.231l0.184,0.232c6.904,8.855,14.424,15.701,22.99,20.417C143.883,428.924,155.405,432,168,432h298
- c26.191,0,46-22.257,46-49V127C512,114.179,507.846,102.463,498.941,93.559z M413.442,332.307c1.528,1.51,2.372,3.562,2.372,5.71
- c0,2.151-0.844,4.203-2.372,5.707l-21.823,21.905c-1.575,1.586-3.625,2.371-5.691,2.371c-2.071,0-4.138-0.785-5.695-2.371
- l-76.23-76.461l-76.23,76.461c-1.558,1.586-3.625,2.371-5.695,2.371c-2.066,0-4.117-0.785-5.692-2.371l-21.824-21.905
- c-1.527-1.504-2.373-3.556-2.373-5.707c0-2.148,0.846-4.2,2.373-5.71L271.098,256l-76.738-76.297
- c-3.146-3.153-3.146-8.273,0-11.427l21.807-21.919c1.516-1.511,3.552-2.357,5.696-2.357c2.152,0,4.189,0.847,5.691,2.357
- l76.448,75.533l76.447-75.533c1.504-1.511,3.541-2.357,5.693-2.357c2.143,0,4.179,0.847,5.695,2.357l21.807,21.919
- c3.146,3.153,3.146,8.273,0,11.427L336.904,256L413.442,332.307z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bag.svg
deleted file mode 100644
index f66c5ac3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bag.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448,160h-64v-4.5C384,87,329,32,260.5,32h-8C184,32,128,87,128,155.5v4.5H64L32,480h448L448,160z M160,155.5
- c0-50.7,41.8-91.5,92.5-91.5h7.5h0.5c50.7,0,91.5,40.8,91.5,91.5v4.5H160V155.5z M67.8,448l24.9-256H128v36.3
- c-9.6,5.5-16,15.9-16,27.7c0,17.7,14.3,32,32,32s32-14.3,32-32c0-11.8-6.4-22.2-16-27.7V192h192v36.3c-9.6,5.5-16,15.9-16,27.7
- c0,17.7,14.3,32,32,32s32-14.3,32-32c0-11.8-6.4-22.2-16-27.7V192h35.4l24.9,256H67.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-charging.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-charging.svg
deleted file mode 100644
index 01586130..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-charging.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M42.1,384h381.1c5.5,0,9.9-4.5,9.9-10v-54h36.9c5.6,0,10.1-4.5,10.1-10V202c0-5.5-4.5-10-10.1-10H433v-54
- c0-5.5-4.3-10-9.9-10H42.1c-5.6,0-10.1,4.5-10.1,10v236C32,379.5,36.5,384,42.1,384z M257.4,160l-27.9,81H291L190.6,352l27.9-81H157
- L257.4,160z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-empty.svg
deleted file mode 100644
index 6659cb26..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-empty.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M469.9,192H433v-54c0-5.5-4.3-10-9.9-10H42.1c-5.6,0-10.1,4.5-10.1,10v236c0,5.5,4.5,10,10.1,10h381.1c5.5,0,9.9-4.5,9.9-10
- v-54h36.9c5.6,0,10.1-4.5,10.1-10V202C480,196.5,475.5,192,469.9,192z M448,288h-14.8H401v32v32H64V160h337v32v32h32.2H448V288z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-full.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-full.svg
deleted file mode 100644
index a833ec4d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-full.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M469.9,192H433v-54c0-5.5-4.3-10-9.9-10H42.1c-5.6,0-10.1,4.5-10.1,10v236c0,5.5,4.5,10,10.1,10h381.1c5.5,0,9.9-4.5,9.9-10
- v-54h36.9c5.6,0,10.1-4.5,10.1-10V202C480,196.5,475.5,192,469.9,192z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-half.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-half.svg
deleted file mode 100644
index 9b992d00..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-half.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M469.9,192H433v-54c0-5.5-4.3-10-9.9-10H42.1c-5.6,0-10.1,4.5-10.1,10v236c0,5.5,4.5,10,10.1,10h381.1c5.5,0,9.9-4.5,9.9-10
- v-54h36.9c5.6,0,10.1-4.5,10.1-10V202C480,196.5,475.5,192,469.9,192z M448,288h-14.8H401v32v32h-49l-32-192h81v32v32h32.2H448V288z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-low.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-low.svg
deleted file mode 100644
index 7848ebbb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/battery-low.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M42.1,384h381.1c5.5,0,9.9-4.5,9.9-10v-54h36.9c5.6,0,10.1-4.5,10.1-10V202c0-5.5-4.5-10-10.1-10H433v-54
- c0-5.5-4.3-10-9.9-10H42.1c-5.6,0-10.1,4.5-10.1,10v236C32,379.5,36.5,384,42.1,384z M401,160v32v32h32.2H448v64h-14.8H401v32v32
- H224l-32-192H401z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beaker.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beaker.svg
deleted file mode 100644
index ecc33942..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beaker.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M143.5,192.5V416c0,8.836,7.851,16.5,16.688,16.5h208c8.836,0,15.312-7.664,15.312-16.5V192.5H143.5z M359.5,344
- c0,4.418-3.582,8-8,8s-8-3.582-8-8v-48c0-4.418,3.582-8,8-8s8,3.582,8,8V344z M352.188,272c-4.418,0-8-3.581-8-8s3.582-8,8-8
- s8,3.581,8,8S356.605,272,352.188,272z"/>
- </g>
- <g>
- <path d="M445.078,32.5H128.438c-54.345,0-64.594,27.426-64.594,39.75C94.094,76.5,95.5,77,95.5,109c0,16,0,307,0,307
- c0,35.346,29.341,64.5,64.688,64.5h207.75c35.346,0,63.562-29.154,63.562-64.5c0,0,0-316.75,0-335.5
- c0-20.349,12.298-38.276,13.516-40.183c1.219-1.906,3-3.798,3-4.958C448.016,34.188,447.6,32.5,445.078,32.5z M399.5,80.5V416
- c0,17.92-12.443,32.5-29.812,32.5h-209.5c-17.617,0-32.688-14.883-32.688-32.5V109c0-11.812,1.094-37.25-3.828-43.957
- c0.921-0.793,3.114-0.543,4.516-0.543h272.66C400.112,64.5,399.5,75.299,399.5,80.5z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beer.svg
deleted file mode 100644
index be420d0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/beer.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M416,160h-32v-16c14.5-3.5,32-24.3,32-48c0-35.3-28.7-64-64-64c-16.3,0-31.1,6.1-42.4,16.1C297.2,38,281.4,32,264.2,32
- c-15.8,0-30.4,5.1-42.3,13.7c-9.9-8.5-22.9-13.7-37-13.7c-17.1,0-32.4,7.6-42.8,19.5C130.4,39.5,114.1,32,96,32
- c-35.3,0-64,28.7-64,64c0,16.2,6.1,31,16,42.3c0,0.2,0,0.4,0,0.7v54c0,26.5,21.5,48,48,48v223c0,8.8,7.2,16,16,16h256
- c8.8,0,16-7.2,16-16v-80h32c35.3,0,64-28.7,64-64v-96C480,188.7,451.3,160,416,160z M327.8,304c-1.6,0-3-0.6-4.3-1.4
- c-2.2-1.4-3.5-4-3.5-6.8V248c0-4.4,3.6-8,8-8c4.4,0,8,3.6,8,8v48.1l0,0C336,301.1,332.2,304,327.8,304z M335,228.4
- c-1.2,1.8-3,3-5.1,3.5c-2.1,0.4-4.3,0-6-1.1c-1.8-1.2-3-3-3.5-5.1c-0.4-2.1,0-4.3,1.1-6c1.2-1.8,3-3,5.1-3.5c2.1-0.4,4.3,0,6,1.1
- c1.8,1.2,3,3,3.5,5.1C336.6,224.4,336.2,226.6,335,228.4z M352,160v32H224.2c-0.1-4.3-3.6-7.8-8-7.8c-4.4,0-7.9,3.5-8,7.8H128v-9
- v-31.6c6.5-3.8,12.3-8.6,17-14.3c1.2-1.5,2.4-3,3.5-4.6c1.5,1.2,3,2.4,4.6,3.4c9.1,6.1,20,9.7,31.7,9.7c6.4,0,12.6-1.1,18.3-3
- c12.8,20.2,35.3,33.7,61,33.7c22,0,41.7-9.9,54.9-25.4c5.7-6.7,10.2-14.4,13.1-22.9H352V160z M382.6,105.2
- c-2.5-5.5-8.1-9.2-14.6-9.2h-48h-7c0,0-8.7-0.7-8.7,8.2s-2.9,17.1-7.8,23.7c-7.3,9.9-19.1,16.4-32.4,16.4
- c-14.9,0-27.9-8.1-34.8-20.2c-1.6-2.7-2.8-5.6-3.7-8.6c-0.1-0.6-0.3-1.1-0.4-1.6c-2-5.9-7.5-10.2-14.1-10.2c-3.9,0-7.5,1.5-10.2,4
- c0,0,0,0-0.1,0.1c-2.4,2.1-5.3,3.7-8.4,4.7c-2.4,0.8-5,1.2-7.7,1.2c-7.5,0-14.7-4-18.8-8.6c-10-11.4-23.7-6.8-29.7-5.5
- s-12.2,11.7-12.2,11.7c-1.1,2.1-2.5,4-4,5.8c-5.9,6.7-14.5,11-24.1,11v32v23v26c-8.8,0-16-7.2-16-16v-35v-34.3
- c-7.7-4.5-13.4-12.1-15.3-21c-0.5-2.1-0.7-4.4-0.7-6.7c0-17.6,14.4-32,32-32c11.8,0,23.3,7.7,30.1,15.4s26.7,7.7,33.9,0
- c6.8-7.3,14.3-15.4,24.8-15.4c6,0,11.6,2.2,15.9,5.8c1.9,1.6,3.6,3.5,4.9,5.6c1.1,1.8,2,4.2,3.1,5.8c2.7,3.4,6.5,5.5,11.2,5.5
- c4.4,0,8.3-1.9,11-5c0.6-0.7,1.2-1.5,1.7-2.3c2-2.5,4.2-4.8,6.7-6.8c6.8-5.4,15.5-8.6,24.8-8.6c10.6,0,20.2,4.1,27.4,10.9
- c1.7,1.6,6.7,4.5,13.2,5.1c4.5,0.4,6.1,0.3,8.2,0c10.3-1.3,14.4-4.7,16.4-6.6c5.8-5.8,13.8-9.4,22.6-9.4c17.6,0,32,14.4,32,32
- C384,99.2,383.5,102.3,382.6,105.2z M448,320c0,17.7-14.3,32-32,32h-32V192h32c17.7,0,32,14.3,32,32V320z"/>
- <circle cx="168.2" cy="168.2" r="8"/>
- <circle cx="328.2" cy="168.2" r="8"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bluetooth.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bluetooth.svg
deleted file mode 100644
index 798ef293..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bluetooth.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M140,143.6c-15.9,15.9-11.7,17.3-10.6,18.4c1.1,1.1,89.8,85.6,89.8,85.6s3.9,3.4,3.9,8.4h0c0,5-3.9,8.4-3.9,8.4
- s-88.7,84.5-89.8,85.6c-1.1,1.1-5.3,2.5,10.6,18.4c15.9,15.9,18.4,12.2,19.2,11.4l67.4-64.3c0.1-0.1,0.2-0.2,0.3-0.3
- c0.1-0.1,0.3-0.2,0.4-0.3c2.3-1.9,9.8-10.6,9.8-3.2c0,7.3,0,151.8,0,156.4v0.1v1.7c0,5.5,5.2,10.1,11.6,10.1c3.5,0,6.7-1.3,8.9-3.5
- l0,0c0,0,118.2-112.8,122.8-117.2c4.6-4.4,5-10.7,1-14.7l-83.9-80.3c0,0-4.4-4.3-4.4-8.3s4.4-8.3,4.4-8.3l83.9-80.3
- c4-4,3.6-10.4-1-14.7c-4.6-4.4-122.8-117.2-122.8-117.2l0,0c-2.1-2.1-5.3-3.5-8.8-3.5c-6.4,0-11.6,4.6-11.6,10.1v1.7V44
- c0,4.6,0,149.1,0,156.4c0,7.4-7.5-1.3-9.8-3.2c-0.1-0.1-0.3-0.2-0.4-0.3c-0.1-0.1-0.2-0.2-0.3-0.3l-67.4-64.3
- C158.3,131.4,155.9,127.7,140,143.6z M280,119.9c0-6.6,7.5,2.3,9.8,4.4l30.5,29.2c2.1,2,2.9,4.7,2.9,7.2c0,2.5-1,5.6-2.8,7.3
- c-1.8,1.7-30.8,29.5-30.8,29.5c-2.3,1.8-9.6,9.8-9.6,1.7C280,199.2,280,126.5,280,119.9z M280,312.8c0-8.2,7.2-0.2,9.6,1.7
- c0,0,29.1,27.8,30.9,29.5c1.8,1.7,2.8,4.9,2.8,7.3s-0.8,5.2-2.9,7.2l-30.5,29.2c-2.3,2.1-9.8,11-9.8,4.4
- C280,385.5,280,312.8,280,312.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bonfire.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bonfire.svg
deleted file mode 100644
index e3a69b89..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bonfire.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M270.93,350.601C270.219,342.42,263.364,336,255,336c-7.635,0-14.01,5.352-15.605,12.506l-0.007-0.002l-15.612,92.502
- C223.273,443.258,223,445.597,223,448c0,17.673,14.327,32,32,32s32-14.327,32-32c0-2.899-0.393-5.705-1.115-8.377L270.93,350.601z"
- />
- <polygon points="305.904,355.046 305.903,355.044 305.9,355.046 "/>
- <path d="M392.875,390.261c-1.718-1.407-3.3-2.881-5.138-3.94l-63.629-47.507c-5.775-3.796-11.997-3.689-16.527,0.85
- c-4.131,4.143-4.686,10.369-1.678,15.381l48.959,65.763c0.946,1.494,2.166,2.799,3.366,4.195c7.802,9.071,25.08,9.588,34.646-0.007
- C402.445,415.409,402.305,397.986,392.875,390.261z"/>
- <polygon points="372.511,335.018 372.509,335.018 372.509,335.02 "/>
- <path d="M435.428,322.475l-59.521-2.284c-3.891-0.558-7.4,2.053-8.065,6.011c-0.604,3.611,1.347,7.138,4.668,8.816l0.013-0.039
- c0.041,0.019,0.062,0.006,0.105,0.025l57.717,17.756c8.289,1.93,17.656-2.343,17.656-11.648
- C448,329.328,444.917,323.667,435.428,322.475z"/>
- <polygon points="139.222,335.02 139.222,335.018 139.22,335.018 "/>
- <path d="M139.209,334.979l0.013,0.039c3.321-1.679,5.272-5.205,4.668-8.816c-0.665-3.958-4.175-6.568-8.065-6.011l-59.521,2.284
- C66.813,323.667,64,329.328,64,341.111c0,9.306,9.098,13.578,17.387,11.648l57.717-17.756
- C139.146,334.984,139.168,334.997,139.209,334.979z"/>
- <path d="M187.903,338.807l-63.597,47.431c-1.838,1.057-3.569,2.362-5.137,3.931c-9.563,9.567-9.566,25.088-0.004,34.65
- c9.561,9.571,25.055,9.578,34.618,0.007c1.3-1.299,2.405-2.694,3.352-4.185L206.097,355c3.007-5,2.452-11.213-1.677-15.346
- C199.893,335.126,192.712,334.762,187.903,338.807z"/>
- <path d="M352,128c0-61-72.35-96-96-96c12.017,85.553-101.667,119.667-112,192s48,96,48,96
- c16.333-59.896,72.386-79.997,109.667-105.667C342.333,186.333,352,160.061,352,128z"/>
- <path d="M352,256c5.03-15.613,4.91-49,0-64c-8.999,18.5-26.287,34.3-47.186,48.689c-8.584,5.911-19.859,11.443-28.83,16.797
- c-18.714,11.165-34.984,21.848-47.329,36.4C240.001,311.25,256.973,320,272,320C307.999,320,336,305.662,352,256z"/>
- <path d="M152.037,160c11.722-15.952,24.856-25.209,38.19-38.362c13.436-13.254,22.077-22.471,27.464-33.173
- C207.025,67.134,189.842,61.857,176,64c2.333,30.334-29.97,46.567-32,68.657C142.773,146,146.5,156,152.037,160z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bookmark.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bookmark.svg
deleted file mode 100644
index 425f97e5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bookmark.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M344,64H168c-4.4,0-8,3.6-8,8v56h192V72C352,67.6,348.4,64,344,64z"/>
- <polygon points="160,448 256,352 352,448 352,144 160,144 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bowtie.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bowtie.svg
deleted file mode 100644
index 0c9a67ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bowtie.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M223.955,212.011c0,0,8.054-4.679,19.985-7.011c21.318-4.166,39.472-5.5,47.466,8.5c9.777,17.124,18.402,53.417,16.488,85.5
- c-1,16.75-4.622,22.125-4.622,22.125s-15.333,9.525-47.341,6.875c-34.725-2.875-39.971-15.004-39.971-15.004
- s4.497-11.305,7.995-42.499C227.452,239.303,223.955,212.011,223.955,212.011z"/>
-<g>
- <path d="M183.984,285c12.546-3.323,23.03-7.189,27.659-8.985c0.693-4.707,1.28-9.718,1.694-15.015
- c0.271-3.461,0.465-6.754,0.602-9.896c-6.854-2.333-13.534-4.851-28.769-10.104c-38.66-13.333-57.146-17-57.146-17
- s14.24-2.5,42.219,3c19.986,3.929,34.392,9.5,43.947,14.333c0.771-15.999-2.477-32.583-2.477-32.583
- C189.729,168.5,119.53,112,84.368,112C57.888,112,32,180.5,32,256s23.03,144,51.51,144c33.356,0,116.463-80,116.463-80
- s5.738-12.578,9.879-33.572c-18.788,5.198-63.84,8.572-63.84,8.572S166.996,289.5,183.984,285z"/>
- <path d="M427.632,112c-36.37,0-102.363,56.5-124.348,96.75l-0.761,1.375c0,0,1.389,2.527,1.873,3.375
- c3.424,5.996,6.704,14.348,9.442,24.041c8.115-2.805,23.599-8.164,37.523-13.041c19.985-7,34.975-9.5,34.975-9.5
- s-52.982,23.741-69.605,34.264c2.169,10.159,3.693,21.199,4.218,32.242c5.423,2.216,16.551,6.475,29.914,9.994
- c18.986,5,40.398,11.5,40.398,11.5s-54.202-5.27-70.114-12.522c-0.013,2.862-0.095,5.709-0.263,8.522
- c-0.997,16.719-4.608,22.104-4.622,22.124C323.883,331.667,391.262,400,428.49,400C456.97,400,480,331.5,480,256
- S454.112,112,427.632,112z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/briefcase.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/briefcase.svg
deleted file mode 100644
index 8b3875dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/briefcase.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M272,272h-32v-8H32v176c0,4.4,3.3,8,7.8,8h432.5c4.4,0,7.7-3.6,7.7-8V264H272V272z"/>
- <path d="M472.2,144H352v-30.7C351,85.1,330.3,64,300.8,64h-89.6c-29.4,0-50.2,21.1-51.2,49.3V144H39.8c-4.4,0-7.8,3.6-7.8,8v96h208
- v-8h32v8h208v-96C480,147.6,476.7,144,472.2,144z M320,116.2c0,0.3,0,0.6,0,1V144H192v-26.8c0-0.4,0-0.7,0-1c0-0.3,0-0.6,0-1
- c0-9.7,8.6-19.2,18.8-19.2h90.4c10.1,0,18.8,9.4,18.8,19.2C320,115.6,320,115.9,320,116.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bug.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bug.svg
deleted file mode 100644
index 837bc7e5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/bug.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M374.64,127.327C345.365,88.512,303.062,64,256,64s-89.365,24.512-118.64,63.327c6.354,15.64,15.833,30,28.13,42.297
- c24.176,24.176,56.319,37.49,90.51,37.49s66.334-13.314,90.51-37.49C358.807,157.327,368.286,142.966,374.64,127.327z"/>
- <path d="M126.836,142.824c-1.725,2.827-3.396,5.703-4.992,8.644c-2.926-1.84-5.319-3.74-7.745-5.773
- c-1.171-0.981-2.954-3.949-4.546-7.35c5.41-11.314,1.181-25.037-9.914-31.261c-11.561-6.484-26.188-2.372-32.674,9.189
- c-6.485,11.56-2.371,26.188,9.187,32.673c1.251,0.702,2.539,1.272,3.847,1.729c2.816,6.269,7.32,14.331,13.548,19.547
- c4.184,3.507,8.792,7.117,15.204,10.674c-7.195,20.259-11.576,42.303-12.545,65.427c-11.026,0.207-18.619,2.1-25.474,4.122
- c-4.16,1.227-8.192,3.395-11.823,5.852c-0.954-0.115-1.923-0.182-2.908-0.182c-13.255,0-24,10.745-24,24s10.745,24,24,24
- c12.93,0,23.467-10.227,23.976-23.032c5.046-1.482,9.888-2.659,17.095-2.774c3.167,33.015,13.304,63.483,28.613,89.224
- c-14.166,11.006-22.882,23.016-26.605,36.317c0,0-0.75,0.438-1.873,1.366c-0.982,0.794-1.932,1.65-2.804,2.619
- c-8.865,9.855-8.062,25.031,1.793,33.895c9.854,8.865,25.028,8.062,33.893-1.793c8.087-8.988,8.095-22.381,0.558-31.395
- c3.074-5.562,6.236-9.014,13.67-14.961C171.368,425.235,207.723,445.619,248,448V222.872
- C194.764,219.954,149.229,188.138,126.836,142.824z"/>
- <path d="M456,256.114c-0.985,0-1.954,0.066-2.908,0.182c-3.631-2.457-7.663-4.625-11.823-5.852
- c-6.854-2.021-14.447-3.915-25.474-4.122c-0.969-23.125-5.35-45.168-12.545-65.427c6.412-3.557,11.021-7.167,15.204-10.674
- c6.228-5.216,10.731-13.278,13.548-19.547c1.308-0.458,2.596-1.028,3.847-1.729c11.558-6.485,15.672-21.114,9.187-32.673
- c-6.485-11.561-21.113-15.673-32.674-9.189c-11.095,6.225-15.324,19.947-9.914,31.261c-1.592,3.401-3.375,6.369-4.546,7.35
- c-2.426,2.033-4.819,3.933-7.745,5.773c-1.596-2.941-3.268-5.817-4.992-8.644c-22.393,45.314-67.928,77.13-121.164,80.048V448
- c40.277-2.381,76.632-22.765,103.686-54.42c7.434,5.947,10.596,9.399,13.67,14.961c-7.537,9.014-7.529,22.406,0.558,31.395
- c8.864,9.855,24.038,10.658,33.893,1.793c9.854-8.863,10.658-24.039,1.793-33.895c-0.872-0.969-1.821-1.825-2.804-2.619
- c-1.123-0.929-1.873-1.366-1.873-1.366c-3.724-13.302-12.439-25.312-26.605-36.317c15.31-25.74,25.446-56.209,28.613-89.224
- c7.207,0.115,12.049,1.292,17.095,2.774c0.509,12.806,11.046,23.032,23.976,23.032c13.255,0,24-10.745,24-24
- S469.255,256.114,456,256.114z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calculator.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calculator.svg
deleted file mode 100644
index 93ef2c0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calculator.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M400,32H112c-8.8,0-16,7.2-16,16v416c0,8.8,7.2,16,16,16h288c8.8,0,16-7.2,16-16V48C416,39.2,408.8,32,400,32z M144,208h32
- v32h-32V208z M144,272h32v32h-32V272z M144,336h32v32h-32V336z M240,432h-96v-32h96V432z M240,368h-32v-32h32V368z M240,304h-32v-32
- h32V304z M240,240h-32v-32h32V240z M304,432h-32v-32h32V432z M304,368h-32v-32h32V368z M304,304h-32v-32h32V304z M304,240h-32v-32
- h32V240z M368,432h-32v-96h32V432z M368,304h-32v-32h32V304z M368,240h-32v-32h32V240z M368,160H144V80h224V160z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calendar.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calendar.svg
deleted file mode 100644
index e6e173a1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/calendar.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M144,128c17.7,0,32-14.3,32-32V64c0-17.7-14.3-32-32-32s-32,14.3-32,32v32C112,113.7,126.3,128,144,128z"/>
- <path d="M368,128c17.7,0,32-14.3,32-32V64c0-17.7-14.3-32-32-32s-32,14.3-32,32v32C336,113.7,350.3,128,368,128z"/>
- <path d="M472,64h-56v40.7c0,22.5-23.2,39.3-47.2,39.3S320,127.2,320,104.7V64H192v40.7c0,22.5-24,39.3-48,39.3s-48-16.8-48-39.3V64
- H40c-4.4,0-8,3.6-8,8v400c0,4.4,3.6,8,8,8h432c4.4,0,8-3.6,8-8V72C480,67.6,476.4,64,472,64z M432,432H80V176h352V432z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/camera.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/camera.svg
deleted file mode 100644
index 7857f61a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/camera.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M430.4,147h-67.5l-40.4-40.8c0,0-0.2-0.2-0.3-0.2l-0.2-0.2v0c-6-6-14.1-9.8-23.3-9.8h-84c-9.8,0-18.5,4.2-24.6,10.9l0,0.1
- l-39.5,40H81.6C63,147,48,161.6,48,180.2v202.1c0,18.6,15,33.7,33.6,33.7h348.8c18.5,0,33.6-15.1,33.6-33.7V180.2
- C464,161.6,448.9,147,430.4,147z M256,365.5c-50.9,0-92.4-41.6-92.4-92.6c0-51.1,41.5-92.6,92.4-92.6c51,0,92.4,41.5,92.4,92.6
- C348.4,323.9,307,365.5,256,365.5z M424.1,200.5c-7.7,0-14-6.3-14-14.1s6.3-14.1,14-14.1c7.7,0,14,6.3,14,14.1
- S431.8,200.5,424.1,200.5z"/>
- <path d="M256,202.9c-38.6,0-69.8,31.3-69.8,70c0,38.6,31.2,70,69.8,70c38.5,0,69.8-31.3,69.8-70C325.8,234.2,294.5,202.9,256,202.9
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/card.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/card.svg
deleted file mode 100644
index e18e8486..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/card.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M452,96H60c-15.5,0-27.9,12.5-28,28l0,0v0.3v263.4v0.3l0,0c0.2,15.5,12.5,28,28,28h392c15.6,0,28-12.7,28-28.3v0V124.3v0
- C480,108.7,467.6,96,452,96z M77.1,128h357.7c6.9,0,12.1,5.1,13.1,12v20H64v-20.3C65,132.9,70.3,128,77.1,128z M434.9,384H77.1
- c-6.9,0-12.1-4.9-13.1-11.7V256h384v116C447,378.9,441.7,384,434.9,384z"/>
- <rect x="96" y="304" width="192" height="16"/>
- <rect x="96" y="336" width="96" height="16"/>
- <rect x="352" y="304" width="64" height="48"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cash.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cash.svg
deleted file mode 100644
index 3618133a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cash.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M0,96v256h512V96H0z M192.508,320H80.129c0-26.582-21.549-48.129-48.129-48.129V192c35.346,0,64-28.653,64-64h96.509
- C172.576,151.455,160,185.767,160,224S172.576,296.545,192.508,320z M298.089,261.248c-2.582,4.182-5.978,7.602-10.189,10.257
- c-4.214,2.655-9.004,4.607-14.375,5.835c-2.812,0.644-5.654,1.119-8.524,1.432V288h-18v-9.43c-2.768-0.357-5.461-0.863-8.072-1.541
- c-5.688-1.475-10.641-3.659-14.851-6.709c-4.214-3.047-7.584-6.803-10.11-11.573C211.548,254.186,210.24,248,210.04,243h19.735
- c0.096,3,0.828,6.532,2.201,9.184c1.473,2.853,3.526,4.883,6.16,6.7c2.572,1.78,5.532,3.082,8.863,3.919v-34.358
- c-2.436-0.601-5.016-1.245-7.758-1.938c-4.846-1.18-8.873-2.729-12.085-4.646c-3.214-1.918-5.766-4.057-7.661-6.417
- c-1.896-2.359-3.238-4.867-4.028-7.522c-0.791-2.656-1.186-5.358-1.186-8.113c0-5.31,1.186-9.905,3.556-13.791
- c2.368-3.883,5.502-7.104,9.398-9.662c3.895-2.556,8.319-4.448,13.27-5.679c2.154-0.534,4.319-0.945,6.494-1.248V160h18v9.499
- c2.46,0.353,4.856,0.838,7.18,1.473c5.215,1.427,9.796,3.563,13.744,6.414c3.95,2.854,7.083,6.364,9.4,10.542
- c2.109,3.811,3.258,8.072,3.445,13.072h-19.866c-0.753-6-3.175-10.326-7.274-12.923c-1.966-1.246-4.186-2.196-6.629-2.887v30.368
- c2.589,0.639,5.15,1.268,7.654,1.878c3.421,0.836,5.87,1.453,7.346,1.844c3.686,1.083,6.897,2.558,9.637,4.425
- c2.737,1.869,5.028,4.008,6.873,6.417c1.841,2.411,3.21,4.992,4.107,7.744c0.893,2.753,1.343,5.51,1.343,8.262
- C301.96,252.027,300.668,257.07,298.089,261.248z M480,271.871c-26,0-48,21.547-48,48.129H319.491
- C339.424,296.545,352,262.233,352,224s-12.576-72.545-32.51-96H416c0,35.347,28.653,64,64,64V271.871z"/>
- <circle cx="96" cy="224" r="32"/>
- <circle cx="416" cy="224" r="32"/>
- <path d="M272.893,235.21c-2.395-0.823-5.029-1.618-7.893-2.389v30.856c1.592-0.23,3.069-0.547,4.416-0.959
- c3.053-0.934,5.529-2.139,7.425-3.613s3.264-3.171,4.107-5.089c0.842-1.917,1.263-3.858,1.263-5.827
- c0-4.031-0.975-7.006-2.921-8.924C277.34,237.349,275.206,235.999,272.893,235.21z"/>
- <path d="M236.004,190.959c-1.318,1.771-1.975,3.982-1.975,6.638c0,3.738,1.236,6.663,3.712,8.776
- c2.377,2.034,5.468,3.583,9.259,4.661v-26.356c-2.18,0.45-4.192,1.135-6.02,2.078C238.979,187.788,237.32,189.189,236.004,190.959z
- "/>
- <rect y="384" width="512" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox-working.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox-working.svg
deleted file mode 100644
index 1a6d1a66..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox-working.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M124.3,400H277c14.4,0,14.4,0.1,21.3,5.2S384,464,384,464v-64h3.7c42.2,0,76.3-31.8,76.3-71.4V119.7
- c0-39.6-34.2-71.7-76.3-71.7H124.3C82.2,48,48,80.1,48,119.7v208.9C48,368.2,82.2,400,124.3,400z M352.1,192c17.7,0,32,14.3,32,32
- c0,17.7-14.3,32-32,32c-17.7,0-32-14.3-32-32C320.1,206.3,334.4,192,352.1,192z M256.1,192c17.7,0,32,14.3,32,32
- c0,17.7-14.3,32-32,32c-17.7,0-32-14.3-32-32C224.1,206.3,238.4,192,256.1,192z M160.1,192c17.7,0,32,14.3,32,32
- c0,17.7-14.3,32-32,32c-17.7,0-32-14.3-32-32C128.1,206.3,142.4,192,160.1,192z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox.svg
deleted file mode 100644
index 4e3070b4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbox.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M124.3,400H277c14.4,0,14.4,0.1,21.3,5.2S384,464,384,464v-64h3.7c42.2,0,76.3-31.8,76.3-71.4V119.7
- c0-39.6-34.2-71.7-76.3-71.7H124.3C82.2,48,48,80.1,48,119.7v208.9C48,368.2,82.2,400,124.3,400z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatboxes.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatboxes.svg
deleted file mode 100644
index 259cc814..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatboxes.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M294.1,365.5c-2.6-1.8-7.2-4.5-17.5-4.5H160.5c-34.7,0-64.5-26.1-64.5-59.2V201h-1.8C67.9,201,48,221.5,48,246.5v128.9
- c0,25,21.4,40.6,47.7,40.6H112v48l53.1-45c1.9-1.4,5.3-3,13.2-3h89.8c23,0,47.4-11.4,51.9-32L294.1,365.5z"/>
- <path d="M401,48H183.7C149,48,128,74.8,128,107.8v69.7V276c0,33.1,28,60,62.7,60h101.1c10.4,0,15,2.3,17.5,4.2L384,400v-64h17
- c34.8,0,63-26.9,63-59.9V107.8C464,74.8,435.8,48,401,48z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble-working.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble-working.svg
deleted file mode 100644
index da15d59e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble-working.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,449.4c28.9,0,56.4-5.7,81.3-15.9c0.6-0.3,1.1-0.5,1.7-0.7c0.1,0,0.2,0,0.2-0.1c3.5-1.3,7.3-2,11.2-2
- c4.3,0,8.4,0.8,12.1,2.4l84,30.9l-22.1-88.4c0-5.3,1.5-10.3,3.9-14.6c0,0,0,0,0,0c0.8-1.3,1.6-2.6,2.5-3.7
- c20.9-31.3,33-68.5,33-108.4C464,137.9,370.9,48,256,48C141.1,48,48,137.9,48,248.7C48,359.6,141.1,449.4,256,449.4z M352,224
- c17.7,0,32,14.3,32,32c0,17.7-14.3,32-32,32c-17.7,0-32-14.3-32-32C320,238.3,334.3,224,352,224z M256,224c17.7,0,32,14.3,32,32
- c0,17.7-14.3,32-32,32c-17.7,0-32-14.3-32-32C224,238.3,238.3,224,256,224z M160,224c17.7,0,32,14.3,32,32c0,17.7-14.3,32-32,32
- c-17.7,0-32-14.3-32-32C128,238.3,142.3,224,160,224z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble.svg
deleted file mode 100644
index f9ab693a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubble.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,449.4c28.9,0,56.4-5.7,81.3-15.9c0.6-0.3,1.1-0.5,1.7-0.7c0.1,0,0.2,0,0.2-0.1c3.5-1.3,7.3-2,11.2-2
- c4.3,0,8.4,0.8,12.1,2.4l84,30.9l-22.1-88.4c0-5.3,1.5-10.3,3.9-14.6c0,0,0,0,0,0c0.8-1.3,1.6-2.6,2.5-3.7
- c20.9-31.3,33-68.5,33-108.4C464,137.9,370.9,48,256,48C141.1,48,48,137.9,48,248.7C48,359.6,141.1,449.4,256,449.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubbles.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubbles.svg
deleted file mode 100644
index d1a8ba84..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chatbubbles.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M73.3,391C73.3,391,73.3,391,73.3,391c1.8,3,2.8,6.4,2.8,10.2L64,464l56.2-22.1c2.7-1.1,5.6-1.7,8.7-1.7
- c2.8,0,5.5,0.5,8,1.4c0,0,0.1,0,0.2,0c0.4,0.2,0.8,0.3,1.2,0.5c17.8,7.3,37.4,11.4,57.9,11.4c46.3,0,87.6-20.5,114.8-52.6
- c-14.1,3.6-28.9,5.7-44.1,5.7c-95.9,0-173.7-75-173.7-167.5c0-11.8,1.3-23.2,3.7-34.3C66.9,230.9,48,268.6,48,310.6
- c0,28.4,8.6,55.2,23.5,77.5C72.1,388.9,72.7,390,73.3,391z"/>
- <path d="M290.3,48c-83.7,0-153.6,57.2-170,133.2c-2.4,11.1-3.7,22.5-3.7,34.3c0,92.5,77.7,167.5,173.7,167.5
- c15.3,0,30-2.1,44.1-5.7c8.1-2.1,16.1-4.5,23.8-7.6c0.5-0.2,0.9-0.4,1.4-0.6c0.1,0,0.2,0,0.2-0.1c2.9-1.1,6.1-1.7,9.3-1.7
- c3.6,0,7,0.7,10.1,2l68.6,25.8l-17-73.8c0-4.4,1.2-8.6,3.3-12.2c0,0,0,0,0,0c0.6-1.1,1.4-2.1,2.1-3.1
- c17.4-26.1,27.5-57.2,27.5-90.5C464,123,386.3,48,290.3,48z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-circled.svg
deleted file mode 100644
index 818f4e30..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-circled.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224C480,132.3,379.7,32,256,32z
- M370.9,181.1L231.8,359.6c-1.1,1.1-2.9,3.5-5.1,3.5c-2.3,0-3.8-1.6-5.1-2.9c-1.3-1.3-78.9-75.9-78.9-75.9l-1.5-1.5
- c-0.6-0.9-1.1-2-1.1-3.2c0-1.2,0.5-2.3,1.1-3.2c0.4-0.4,0.7-0.7,1.1-1.2c7.7-8.1,23.3-24.5,24.3-25.5c1.3-1.3,2.4-3,4.8-3
- c2.5,0,4.1,2.1,5.3,3.3c1.2,1.2,45,43.3,45,43.3l111.3-143c1-0.8,2.2-1.4,3.5-1.4c1.3,0,2.5,0.5,3.5,1.3l30.6,24.1
- c0.8,1,1.3,2.2,1.3,3.5C372,179.1,371.5,180.2,370.9,181.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-round.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-round.svg
deleted file mode 100644
index 0f9e5e0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark-round.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448,71.9c-17.3-13.4-41.5-9.3-54.1,9.1L214,344.2l-99.1-107.3c-14.6-16.6-39.1-17.4-54.7-1.8
- c-15.6,15.5-16.4,41.6-1.7,58.1c0,0,120.4,133.6,137.7,147c17.3,13.4,41.5,9.3,54.1-9.1l206.3-301.7
- C469.2,110.9,465.3,85.2,448,71.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark.svg
deleted file mode 100644
index 5d091529..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/checkmark.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M461.6,109.6l-54.9-43.3c-1.7-1.4-3.8-2.4-6.2-2.4c-2.4,0-4.6,1-6.3,2.5L194.5,323c0,0-78.5-75.5-80.7-77.7
- c-2.2-2.2-5.1-5.9-9.5-5.9c-4.4,0-6.4,3.1-8.7,5.4c-1.7,1.8-29.7,31.2-43.5,45.8c-0.8,0.9-1.3,1.4-2,2.1c-1.2,1.7-2,3.6-2,5.7
- c0,2.2,0.8,4,2,5.7l2.8,2.6c0,0,139.3,133.8,141.6,136.1c2.3,2.3,5.1,5.2,9.2,5.2c4,0,7.3-4.3,9.2-6.2L462,121.8
- c1.2-1.7,2-3.6,2-5.8C464,113.5,463,111.4,461.6,109.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-down.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-down.svg
deleted file mode 100644
index 4d96e34b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-down.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,298.3L256,298.3L256,298.3l174.2-167.2c4.3-4.2,11.4-4.1,15.8,0.2l30.6,29.9c4.4,4.3,4.5,11.3,0.2,15.5L264.1,380.9
- c-2.2,2.2-5.2,3.2-8.1,3c-3,0.1-5.9-0.9-8.1-3L35.2,176.7c-4.3-4.2-4.2-11.2,0.2-15.5L66,131.3c4.4-4.3,11.5-4.4,15.8-0.2L256,298.3
- z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-left.svg
deleted file mode 100644
index 2a5847d3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-left.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M213.7,256L213.7,256L213.7,256L380.9,81.9c4.2-4.3,4.1-11.4-0.2-15.8l-29.9-30.6c-4.3-4.4-11.3-4.5-15.5-0.2L131.1,247.9
- c-2.2,2.2-3.2,5.2-3,8.1c-0.1,3,0.9,5.9,3,8.1l204.2,212.7c4.2,4.3,11.2,4.2,15.5-0.2l29.9-30.6c4.3-4.4,4.4-11.5,0.2-15.8
- L213.7,256z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-right.svg
deleted file mode 100644
index c7806956..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-right.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M298.3,256L298.3,256L298.3,256L131.1,81.9c-4.2-4.3-4.1-11.4,0.2-15.8l29.9-30.6c4.3-4.4,11.3-4.5,15.5-0.2l204.2,212.7
- c2.2,2.2,3.2,5.2,3,8.1c0.1,3-0.9,5.9-3,8.1L176.7,476.8c-4.2,4.3-11.2,4.2-15.5-0.2L131.3,446c-4.3-4.4-4.4-11.5-0.2-15.8
- L298.3,256z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-up.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-up.svg
deleted file mode 100644
index 7ab9d97d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/chevron-up.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,213.7L256,213.7L256,213.7l174.2,167.2c4.3,4.2,11.4,4.1,15.8-0.2l30.6-29.9c4.4-4.3,4.5-11.3,0.2-15.5L264.1,131.1
- c-2.2-2.2-5.2-3.2-8.1-3c-3-0.1-5.9,0.9-8.1,3L35.2,335.3c-4.3,4.2-4.2,11.2,0.2,15.5L66,380.7c4.4,4.3,11.5,4.4,15.8,0.2L256,213.7
- z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clipboard.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clipboard.svg
deleted file mode 100644
index abebc336..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clipboard.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M161,160.5h192c-1.688-20-9.729-35.45-27.921-40.356c-0.446-0.119-1.12-0.424-1.567-0.541
- c-12.004-3.424-21.012-7.653-21.012-20.781V78.227C302.5,52.691,281.976,32,256.49,32c-25.466,0-45.99,20.691-45.99,46.227v20.595
- c0,13.128-8.592,17.169-20.597,20.593c-0.447,0.117-0.8,0.61-1.266,0.729C170.446,125.05,162.927,140.5,161,160.5z M256.99,64.395
- c7.615,0,13.791,6.195,13.791,13.832c0,7.654-6.176,13.85-13.791,13.85c-7.614,0-13.772-6.195-13.772-13.85
- C243.218,70.59,249.376,64.395,256.99,64.395z"/>
- <path d="M405.611,63.5H331.5v13.988c0,10.583,9.193,19.012,19.507,19.012h37.212c6.667,0,12.099,5.435,12.44,12.195l0.085,327.1
- c-0.322,6.432-5.303,11.546-11.514,12.017l-264.418,0.031c-6.211-0.471-11.149-5.695-11.472-12.126l-0.085-327.014
- c0.322-6.761,5.858-12.203,12.506-12.203h37.231c10.313,0,18.507-8.429,18.507-19.012V63.5h-73.131
- C93.25,63.5,80.5,76.058,80.5,91.575v360.38c0,15.502,12.75,28.545,27.869,28.545H256.99h148.621
- c15.138,0,26.889-13.043,26.889-28.545V91.575C432.5,76.058,420.749,63.5,405.611,63.5z"/>
- <rect x="144.5" y="192.5" width="112" height="32"/>
- <rect x="144.5" y="384.5" width="160" height="32"/>
- <rect x="144.5" y="320.5" width="129" height="32"/>
- <rect x="144.5" y="256.5" width="208" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clock.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clock.svg
deleted file mode 100644
index 717c3189..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/clock.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M255.988,32C132.285,32,32,132.298,32,256c0,123.715,100.285,224,223.988,224C379.703,480,480,379.715,480,256
- C480,132.298,379.703,32,255.988,32z M391.761,391.765c-10.099,10.098-21.126,18.928-32.886,26.42l-15.946-27.62l-13.856,8
- l15.955,27.636c-24.838,13.03-52.372,20.455-81.027,21.624V416h-16v31.825c-28.656-1.166-56.191-8.59-81.03-21.62l15.958-27.641
- l-13.856-8l-15.949,27.625c-11.761-7.492-22.79-16.324-32.889-26.424c-10.099-10.099-18.93-21.127-26.422-32.889l27.624-15.949
- l-8-13.855L85.796,345.03c-13.03-24.839-20.454-52.374-21.621-81.03H96v-16H64.175c1.167-28.655,8.592-56.19,21.623-81.029
- l27.638,15.958l8-13.856l-27.623-15.948c7.492-11.76,16.322-22.787,26.419-32.885c10.1-10.101,21.129-18.933,32.89-26.426
- l15.949,27.624l13.856-8l-15.958-27.64C191.81,72.765,219.345,65.34,248,64.175V96h16V64.176
- c28.654,1.169,56.188,8.595,81.026,21.626l-15.954,27.634l13.856,8l15.945-27.618c11.76,7.492,22.787,16.323,32.886,26.421
- c10.1,10.099,18.931,21.126,26.424,32.887l-27.619,15.946l8,13.856l27.636-15.956c13.031,24.839,20.457,52.373,21.624,81.027H416
- v16h31.824c-1.167,28.655-8.592,56.189-21.622,81.028l-27.637-15.957l-8,13.856l27.621,15.947
- C410.693,370.637,401.861,381.665,391.761,391.765z"/>
- <path d="M400,241H284.268c-2.818-5.299-7.083-9.708-12.268-12.708V160h-32v68.292c-9.562,5.534-16,15.866-16,27.708
- c0,17.673,14.327,32,32,32c11.425,0,21.444-5.992,27.106-15H400V241z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-circled.svg
deleted file mode 100644
index 8705b057..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-circled.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,33C132.3,33,32,133.3,32,257c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224C480,133.3,379.7,33,256,33z
- M364.3,332.5c1.5,1.5,2.3,3.5,2.3,5.6c0,2.1-0.8,4.2-2.3,5.6l-21.6,21.7c-1.6,1.6-3.6,2.3-5.6,2.3c-2,0-4.1-0.8-5.6-2.3L256,289.8
- l-75.4,75.7c-1.5,1.6-3.6,2.3-5.6,2.3c-2,0-4.1-0.8-5.6-2.3l-21.6-21.7c-1.5-1.5-2.3-3.5-2.3-5.6c0-2.1,0.8-4.2,2.3-5.6l75.7-76
- l-75.9-75c-3.1-3.1-3.1-8.2,0-11.3l21.6-21.7c1.5-1.5,3.5-2.3,5.6-2.3c2.1,0,4.1,0.8,5.6,2.3l75.7,74.7l75.7-74.7
- c1.5-1.5,3.5-2.3,5.6-2.3c2.1,0,4.1,0.8,5.6,2.3l21.6,21.7c3.1,3.1,3.1,8.2,0,11.3l-75.9,75L364.3,332.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-round.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-round.svg
deleted file mode 100644
index e011f7bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close-round.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5
- c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9
- c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close.svg
deleted file mode 100644
index aa6b81c1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/close.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4
- L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1
- c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1
- c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/closed-captioning.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/closed-captioning.svg
deleted file mode 100644
index dc1c9394..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/closed-captioning.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M0,64v384h512V64H0z M464,255.825c0.045,26.724-1.547,47.143-3.797,80.223S441,392.5,401.097,396.168
- C361.201,399.835,305.369,400.12,256,400c-49,0.12-105.198-0.165-145.094-3.832c-39.903-3.668-56.855-27.04-59.105-60.12
- s-3.841-53.499-3.796-80.223c-0.045-26.725,0.095-44.124,3.798-80.224s23.01-56.267,59.106-59.934S201.842,112,248.704,112
- c2.431,0,5.296,0,7.296,0c2.437,0,4.871,0,7.302,0c46.862,0,101.698,0,137.795,3.667s55.403,23.833,59.106,59.934
- S464.045,229.1,464,255.825z"/>
- </g>
- <g>
- <path d="M372,283.846v0.766c0,18.639-11.581,29.566-27.003,29.566c-15.418,0-25.808-12.309-27.284-29.566
- c0,0-1.335-9.078-1.335-27.298s1.546-29.759,1.546-29.759c2.711-19.473,12.188-29.566,27.607-29.566
- c15.367,0,27.584,13.262,27.584,33.388c0.023,0.086,0.01,0.624,0.01,0.624h51.541c0-25-6.309-47.556-18.92-61.746
- c-12.617-14.183-31.403-21.273-56.369-21.273c-12.483,0-23.93,1.654-34.33,4.942c-10.404,3.295-19.376,9.062-26.916,17.291
- c-7.545,8.234-13.397,19.254-17.555,33.059c-4.162,13.809-6.242,31.224-6.242,52.247c0,20.52,1.688,37.684,5.072,51.488
- c3.377,13.811,8.388,24.83,15.018,33.059c6.632,8.234,14.953,13.935,24.967,17.1c10.01,3.163,21.779,4.748,35.304,4.748
- c28.604,0,49.089-7.258,61.443-21.318C418.486,327.537,424.666,307,424.666,280H372C372,280,372,282.876,372,283.846z"/>
- <path d="M195,283.846v0.766c0,18.639-11.581,29.566-27.003,29.566c-15.418,0-25.808-12.309-27.284-29.566
- c0,0-1.335-9.078-1.335-27.298s1.546-29.759,1.546-29.759c2.711-19.473,12.188-29.566,27.607-29.566
- c15.367,0,27.584,13.262,27.584,33.388c0.023,0.086,0.01,0.624,0.01,0.624h51.541c0-25-6.309-47.556-18.92-61.746
- c-12.617-14.183-31.403-21.273-56.369-21.273c-12.483,0-23.93,1.654-34.33,4.942c-10.404,3.295-19.376,9.062-26.916,17.291
- c-7.545,8.234-13.397,19.254-17.555,33.059c-4.162,13.809-6.242,31.224-6.242,52.247c0,20.52,1.688,37.684,5.072,51.488
- c3.377,13.811,8.388,24.83,15.018,33.059c6.632,8.234,14.953,13.935,24.967,17.1c10.01,3.163,21.779,4.748,35.304,4.748
- c28.604,0,49.089-7.258,61.443-21.318C241.486,327.537,247.666,307,247.666,280H195C195,280,195,282.876,195,283.846z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cloud.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cloud.svg
deleted file mode 100644
index 7a687a60..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cloud.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M398.1,233.2c0-1.2,0.2-2.4,0.2-3.6c0-65-51.8-117.6-115.7-117.6c-46.1,0-85.7,27.4-104.3,67c-8.1-4.1-17.2-6.5-26.8-6.5
- c-29.5,0-54.1,21.9-58.8,50.5C57.3,235.2,32,269.1,32,309c0,50.2,40.1,90.9,89.5,91h276.7l0,0c45.2-0.2,81.7-37.5,81.7-83.4
- C480,270.6,443.3,233.3,398.1,233.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-download.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-download.svg
deleted file mode 100644
index bcdd4ac0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-download.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M330.967,284.104c6.48-6.467,6.48-16.951,0-23.422c-6.48-6.467-17.342-6.467-23.823,0L272,295.432V176.58
- c0-9.151-6.839-16.56-15.999-16.56c-9.162,0-16.001,7.408-16.001,16.56v118.852l-35.005-34.75
- c-6.481-6.467-17.095-6.467-23.573,0c-6.482,6.471-6.539,16.955-0.057,23.422l63.07,63.023c0.02,0.02,0.028,0.037,0.05,0.057
- c0.725,0.716,1.513,1.367,2.368,1.945c0.102,0.067,0.2,0.134,0.302,0.2c0.322,0.206,0.651,0.403,0.99,0.587
- c0.117,0.064,0.231,0.133,0.35,0.193c0.421,0.218,0.849,0.423,1.292,0.605c0.002,0.001,0.004,0.001,0.006,0.002
- c0.405,0.167,0.817,0.308,1.233,0.442c0.112,0.037,0.222,0.085,0.335,0.118c0.151,0.047,0.307,0.074,0.461,0.115
- c1.424,0.385,2.872,0.588,4.315,0.588c1.442,0,2.89-0.203,4.312-0.588c0.153-0.041,0.312-0.068,0.464-0.115
- c0.113-0.033,0.224-0.081,0.335-0.118c0.416-0.135,0.829-0.275,1.233-0.442c0.002-0.001,0.004-0.001,0.007-0.002
- c0.441-0.183,0.87-0.387,1.289-0.604c0.122-0.064,0.24-0.133,0.36-0.198c0.332-0.185,0.658-0.376,0.975-0.579
- c0.109-0.069,0.217-0.14,0.323-0.212c0.408-0.274,0.806-0.562,1.184-0.872c0.004-0.002,0.007-0.004,0.011-0.006
- c0.406-0.332,0.791-0.684,1.162-1.051c0.024-0.022,0.051-0.043,0.074-0.066L330.967,284.104z"/>
- </g>
- </g>
- <g>
- <path d="M168,392c-6.143,0-12.285-2.344-16.971-7.029l-112-112c-9.373-9.373-9.373-24.569,0-33.941l112-112
- c9.373-9.372,24.568-9.372,33.941,0c9.371,9.372,9.371,24.568,0,33.941L89.941,256l95.029,95.029
- c9.371,9.372,9.371,24.568,0,33.941C180.283,389.656,174.143,392,168,392z"/>
- <path d="M344,392c6.143,0,12.285-2.344,16.971-7.029l112-112c9.373-9.373,9.373-24.569,0-33.941l-112-112
- c-9.373-9.372-24.568-9.372-33.941,0c-9.371,9.372-9.371,24.568,0,33.941L422.059,256l-95.029,95.029
- c-9.371,9.372-9.371,24.568,0,33.941C331.717,389.656,337.857,392,344,392z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-working.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-working.svg
deleted file mode 100644
index b0d367a3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code-working.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <circle cx="184.166" cy="256.166" r="24"/>
- <circle cx="256.166" cy="256.166" r="24"/>
- <circle cx="328.166" cy="256.166" r="24"/>
- </g>
- <g>
- <path d="M168,392c-6.143,0-12.285-2.344-16.971-7.029l-112-112c-9.373-9.373-9.373-24.569,0-33.941l112-112
- c9.373-9.372,24.568-9.372,33.941,0c9.371,9.372,9.371,24.568,0,33.941L89.941,256l95.029,95.029
- c9.371,9.372,9.371,24.568,0,33.941C180.283,389.656,174.143,392,168,392z"/>
- <path d="M344,392c6.143,0,12.285-2.344,16.971-7.029l112-112c9.373-9.373,9.373-24.569,0-33.941l-112-112
- c-9.373-9.372-24.568-9.372-33.941,0c-9.371,9.372-9.371,24.568,0,33.941L422.059,256l-95.029,95.029
- c-9.371,9.372-9.371,24.568,0,33.941C331.717,389.656,337.857,392,344,392z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code.svg
deleted file mode 100644
index 26cbd299..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/code.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M168,392c-6.143,0-12.285-2.344-16.971-7.029l-112-112c-9.373-9.373-9.373-24.569,0-33.941l112-112
- c9.373-9.372,24.568-9.372,33.941,0c9.371,9.372,9.371,24.568,0,33.941L89.941,256l95.029,95.029
- c9.371,9.373,9.371,24.568,0,33.941C180.283,389.656,174.143,392,168,392z"/>
- <path d="M344,392c6.143,0,12.285-2.344,16.971-7.029l112-112c9.373-9.373,9.373-24.569,0-33.941l-112-112
- c-9.373-9.372-24.568-9.372-33.941,0c-9.371,9.372-9.371,24.568,0,33.941L422.059,256l-95.029,95.029
- c-9.371,9.373-9.371,24.568,0,33.941C331.717,389.656,337.857,392,344,392z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/coffee.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/coffee.svg
deleted file mode 100644
index 2a69c9f4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/coffee.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M383.1,257.4c0.6-5.4,0.9-10,0.9-13.8c0-19.6-3.3-19.7-16-19.7h-75.5c7.3-12,11.5-24.4,11.5-37c0-37.9-57.3-56.4-57.3-88
- c0-11.7,5.1-21.3,9.3-34.9c-26.5,7-47.4,33.5-47.4,61.6c0,48.3,56.3,48.7,56.3,84.8c0,4.5-1.4,8.5-2.1,13.5h-55.9
- c0.8-3,1.3-6.2,1.3-9.3c0-22.8-39.1-33.9-39.1-52.8c0-7,1-12.8,3.2-21c-12.9,5.1-28.3,20-28.3,36.8c0,26.7,31.9,29.3,36.8,46.3H80
- c-12.7,0-16,0.1-16,19.7c0,19.6,7.7,61.3,28.3,111c20.6,49.7,44.4,71.6,61.2,86.2l0.1-0.2c5.1,4.6,11.8,7.3,19.2,7.3h102.4
- c7.4,0,14.1-2.7,19.2-7.3l0.1,0.2c9-7.8,20-17.8,31.4-32.9c4.7,2,9.8,3.7,15.4,5c8.4,2,16.8,3,24.8,3c24,0,45.6-9.2,60.8-25.8
- c13.4-14.6,21.1-34.4,21.1-54.2C448,297,420,264.5,383.1,257.4z M366.1,384.2c-8.6,0-15.6-1.2-22.1-4.2c4-8,7.9-15.9,11.7-25.1
- c10.1-24.4,17.1-47,21.6-65.8c22,4.3,38.7,23.8,38.7,47.1C416,358.9,398.8,384.2,366.1,384.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compass.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compass.svg
deleted file mode 100644
index 89bde8b0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compass.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M256,32c-39,0-75.6,10-107.5,27.4C136.9,42.9,117.7,32,96,32c-35.3,0-64,28.7-64,64c0,21.7,10.9,40.9,27.4,52.5
- C42,180.4,32,217,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224C480,132.3,379.7,32,256,32z M64,96
- c0-17.7,14.3-32,32-32c10.5,0,19.8,5,25.6,12.8c-17,12.7-32.1,27.8-44.8,44.8C69,115.8,64,106.5,64,96z M391.8,391.8
- C355.5,428,307.3,448,256,448c-51.3,0-99.5-20-135.8-56.2C84,355.5,64,307.3,64,256c0-51.3,20-99.5,56.2-135.8
- C156.5,84,204.7,64,256,64c51.3,0,99.5,20,135.8,56.2C428,156.5,448,204.7,448,256C448,307.3,428,355.5,391.8,391.8z"/>
- </g>
- <path d="M352,128c0,0-101.6,83.7-120,104s-72,152-72,152s102.4-82.3,120-104S352,128,352,128z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compose.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compose.svg
deleted file mode 100644
index 82f190dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/compose.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M442.8,99.6l-30.4-30.4c-7-6.9-18.2-6.9-25.1,0L355.5,101l55.5,55.5l31.8-31.7C449.7,117.7,449.7,106.5,442.8,99.6z"/>
- <g>
- <polygon points="346.1,110.5 174.1,288 160,352 224,337.9 400.6,164.9 "/>
- </g>
- <path d="M384,256v150c0,5.1-3.9,10.1-9.2,10.1s-269-0.1-269-0.1c-5.6,0-9.8-5.4-9.8-10s0-268,0-268c0-5,4.7-10,10.6-10H256l32-32
- H87.4c-13,0-23.4,10.3-23.4,23.3v305.3c0,12.9,10.5,23.4,23.4,23.4h305.3c12.9,0,23.3-10.5,23.3-23.4V224L384,256z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/connection-bars.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/connection-bars.svg
deleted file mode 100644
index ffd98bed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/connection-bars.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="80" y="352" width="64" height="64"/>
- <rect x="176" y="288" width="64" height="128"/>
- <rect x="272" y="192" width="64" height="224"/>
- <rect x="368" y="96" width="64" height="320"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/contrast.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/contrast.svg
deleted file mode 100644
index ffcecdf7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/contrast.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224C480,132.3,379.7,32,256,32z
- M391.8,391.8C355.5,428,307,448,256,448V64c51,0,99.5,20,135.8,56.2C428,156.5,448,204.7,448,256C448,307.3,428,355.5,391.8,391.8z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/crop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/crop.svg
deleted file mode 100644
index 6892bc8d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/crop.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="352" y="432" width="64" height="48"/>
- <polygon points="416,352 416,96 176,96 176,160 352,160 352,352 160,352 160,32 96,32 96,96 32,96 32,160 96,160 96,416 480,416
- 480,352 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cube.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cube.svg
deleted file mode 100644
index cf94545d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/cube.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M467.301,168.084c-1.805,0-3.516,0.329-5.07,0.962l-2.281,1.15l-171.475,88.938l-3.888,1.996c0,0-0.052,0.023-0.052,0.047
- c-7.56,4.668-12.535,12.506-12.535,21.425v185.854c0,6.382,5.649,11.544,12.69,11.544c2.178,0,4.251-0.513,6.065-1.404
- c0.155-0.095,0.363-0.188,0.519-0.282l174.731-92.694l0.259-0.141c8.241-4.504,13.735-12.742,13.735-22.105V179.582
- C480,173.223,474.299,168.084,467.301,168.084z"/>
- <path d="M454.273,118.521l-181.7-81.731c0,0-10.659-4.79-16.577-4.79s-16.526,4.79-16.526,4.79L57.614,118.521
- c0,0-7.989,3.292-7.989,9.479c0,6.562,8.3,11.5,8.3,11.5l182.582,96.371l2.902,1.479c3.784,1.687,8.077,2.649,12.587,2.649
- c4.561,0,8.915-0.963,12.742-2.696l2.539-1.315l182.893-96.536c0,0,7.508-4.036,7.508-11.453
- C461.678,121.5,454.273,118.521,454.273,118.521z"/>
- <path d="M227.466,261.178l-3.992-2.043L52.042,170.197l-2.28-1.15c-1.495-0.634-3.258-0.962-5.071-0.962
- c-6.997,0-12.69,5.138-12.69,11.497v183.792c0,9.388,5.485,17.602,13.727,22.105l0.208,0.141l174.739,92.694l0,0
- c1.918,1.08,4.199,1.687,6.636,1.687c6.989,0,12.69-5.162,12.69-11.544V282.603C240,273.684,235.024,265.846,227.466,261.178z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/disc.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/disc.svg
deleted file mode 100644
index ef17856a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/disc.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,158.9c-53.7,0-97.2,43.5-97.2,97.2c0,53.7,43.5,97.1,97.2,97.1c53.7,0,97.2-43.5,97.2-97.1
- C353.2,202.4,309.7,158.9,256,158.9z M256,299.5c-24,0-43.5-19.5-43.5-43.5c0-24,19.5-43.5,43.5-43.5c24,0,43.5,19.5,43.5,43.5
- C299.5,280,280,299.5,256,299.5z"/>
- <path d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224s224-100.3,224-224C480,132.3,379.7,32,256,32z M256,378.8
- c-67.8,0-122.8-55-122.8-122.8c0-67.8,55-122.8,122.8-122.8c67.8,0,122.8,55,122.8,122.8C378.8,323.8,323.8,378.8,256,378.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document-text.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document-text.svg
deleted file mode 100644
index 1a037e5b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document-text.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M398.6,169.2c-0.9-2.2-2-4.3-3.5-6.1l-83.8-91.7c-1.9-2.1-4.2-3.6-6.7-4.9c-2.9-1.5-6.1-2.1-9.5-2.1H135.2
- c-12.4,0-22.7,10.6-22.7,23.9v335.2c0,13.4,10.3,24.9,22.7,24.9h243.1c12.4,0,22.2-11.5,22.2-24.9V179.4
- C400.5,175.8,400,172.3,398.6,169.2z M160.5,178.6c0-1.5,1.8-2.1,3.4-2.1h70.8c1.6,0,2.8,0.6,2.8,2.1v10.8c0,1.4-1.1,3.1-2.8,3.1
- h-70.8c-1.6,0-3.4-1.7-3.4-3.1V178.6z M160.5,306.6c0-1.5,1.8-2.1,3.4-2.1h122.2c1.6,0,2.4,0.6,2.4,2.1v10.8c0,1.4-0.7,3.1-2.4,3.1
- H163.9c-1.6,0-3.4-1.7-3.4-3.1V306.6z M320.5,381.4c0,1.4-0.7,3.1-2.4,3.1H163.9c-1.6,0-3.4-1.7-3.4-3.1v-10.8
- c0-1.5,1.8-2.1,3.4-2.1h154.2c1.6,0,2.4,0.6,2.4,2.1V381.4z M352.5,253.4c0,1.4-0.7,3.1-2.4,3.1H163.9c-1.6,0-3.4-1.7-3.4-3.1
- v-10.8c0-1.5,1.8-2.1,3.4-2.1h186.2c1.6,0,2.4,0.6,2.4,2.1V253.4z M305.6,177.5c-5.6,0-11.1-5.2-11.1-11.3v-66l71.2,77.3H305.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document.svg
deleted file mode 100644
index ed201709..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/document.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M399.3,168.9c-0.7-2.9-2-5-3.5-6.8l-83.7-91.7c-1.9-2.1-4.1-3.1-6.6-4.4c-2.9-1.5-6.1-1.6-9.4-1.6H136.2
- c-12.4,0-23.7,9.6-23.7,22.9v335.2c0,13.4,11.3,25.9,23.7,25.9h243.1c12.4,0,21.2-12.5,21.2-25.9V178.4
- C400.5,174.8,400.1,172.2,399.3,168.9z M305.5,111l58,63.5h-58V111z M144.5,416.5v-320h129v81.7c0,14.8,13.4,28.3,28.1,28.3h66.9
- v210H144.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/drag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/drag.svg
deleted file mode 100644
index 2961cd43..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/drag.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect y="144" width="512" height="32"/>
- <rect y="240" width="512" height="32"/>
- <rect y="336" width="512" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/earth.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/earth.svg
deleted file mode 100644
index 81258dc6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/earth.svg
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M357.275,125.525c-2.209-3.986-9.498-11.837-13.977-13.325c-5.979-0.921-2.398,4.413-2.398,6.7
- c-1.543,1.157-3.941,2.454-5.102,4c-0.699,0.6,1.704,6.103,6.337,4.335s1.964,1.799,5.164,8.865s9.607,7.207,12.49,5.067
- C363.444,138.455,359.286,129.155,357.275,125.525z"/>
- <path d="M375.8,170.6c-0.001,0.006-0.004,0.011-0.005,0.017C375.795,170.629,375.797,170.629,375.8,170.6z"/>
- <path d="M434.6,197.1C435,197.1,432.8,196.7,434.6,197.1L434.6,197.1z"/>
- <path d="M256,32C132.3,32,32,132.3,32,256c0,123.701,100.3,224,224,224c123.701,0,224-100.299,224-224C480,132.3,379.701,32,256,32
- z M173.399,429.424c-5.515-3.133-9.374-7.56-10.961-15.929c-3.947-20.808-0.303-32.067,17.962-44.245
- c8.604-5.736,10.022-12.672,16.9-19.55c1.685-2.14,6.211-10.374,9.2-10.8c3.637-0.779,13.709-2.527,15.7-6.5
- c3.79-5.146,12.127-27.398,15.8-29.602c5.997-3.925,14.419-15.96,8.3-23.1c-7.021-8.643-16.799-8.766-25.9-13.301
- c-8.015-4.008-11.574-22.281-17.7-28.601c-11.912-12.136-29.999-19.199-45-26.7c-8.116-3.25-7.344-4.256-13.7,2.1
- c-8.162,8.162-20.093-2.067-21.3-10.5c-0.09-2.802-3.296-18.216-1.4-19.4c17.956-11.225-8.328-8.64-10.5-13.8
- c-5.355-14.993,13.008-26.86,25.4-28.1c13.885-1.738,16.784,21.895,22.1,19.9c2.556-1.276,2.566-12.394,2.9-14.8
- c1.267-8.029,3.588-9.273,11.4-12.175c9.098-3.379,16.063-7.617,25.7-9.225c11.006-3.195,20.317-1.533,28.8-8.6
- c3.888-2.915,6.704,1.58,10.4,2.4c7.999,1.599,9.7-11.1,9.7-15.9c-0.034-4.665,1.265-8.63-4.7-13.6
- c-7.806-6.069-19.029-0.869-25.3,5.4c-7.574,7.035-16.357,6.55-13.8-5.6c0.634-4.433,10.209-9.587,14-12
- c3.7-2.222,5.904,2.522,10.4,1.4c6.579-1.463,9.034,4.735,16.8,4.8c3.233-0.731,14.796-6.881,8.614-19.366
- C254.143,64.021,255.07,64,256,64c1.855,0,3.707,0.034,5.555,0.086c2.805,8.881-5.965,16.443-1.555,27.614
- c8.79,21.475,15.992,3.014,24.7-7c2.849-2.849,4.633-2.211,9.3-3.1c2.896-0.483,7.055-9.27,8.393-11.982
- c20.058,4.956,39.121,13.127,56.567,24.255c-7.447,0.792-9.348-1.396-9.234,7.377c0.042,3.317,0.297,13.319,5.274,14.15
- c8.277,0.975,6.781,6.832,14.551,7.85c7.443,0.976,2.816,7.553,5.851,14.05c3.393,10.227-19.806,13.302-24.302,14.8
- c-13.64,4.554,6.34,24.41,15.2,22.3c2.817-0.704,12.215-1.902,12.867-5.067c-0.011-0.323-1.836-11.012-0.867-12.233
- c1.533-1.934,5.123-2.946,10.776,0.255c13.374,7.573,20.146,25.7,35.897,29.295c2.146,0.489,5.86-0.15,8.494,2.033
- c2.231,3.015,7.92,8.416,1.131,8.416c-9.017-2.003-13.78,0.859-21.198-4.874c-7.733-5.977-12.543-10.891-22.75-11.076
- c-8.79-0.159-16.68-3.819-25.738-2.35c-5.05,0.819-10.038,2.811-14.912,4.3c-4.617,1.538-5.51,9.765-10.2,10.7
- c-19.467,4.581-15.261,23.169-18.773,37.913c-1.351,5.662-6.025,21.003-0.926,26.087c9.12,8.854,19.783,21.035,33.176,22.963
- c7.206,1.037,22.954-4.576,27.823,2.737c2.062,4.104,7.447-3.03,8.9,0.601c3.663,10.988-4.263,18.186-4.337,28.551
- c-0.11,15.203,9.178,20.57-3.263,34.148c-13.642,13.607-4.333,30.788-11.9,47c-4.042,8.337-4.808,19.894-10.872,23.777
- c-13.321,8.532-27.7,15.399-42.714,20.384c-26.627,8.838-55.155,11.672-83.017,8.456c-14.619-1.688-29.041-5.057-42.88-10.065
- c-3.769-1.363-7.28-2.505-10.472-3.704C178.143,431.619,175.759,430.55,173.399,429.424z M131.699,402.329
- c-0.468-0.397-0.935-0.796-1.399-1.198c-3.444-2.992-6.802-6.113-10.06-9.371c-3.388-3.388-6.634-6.881-9.734-10.471
- c-0.035-0.041-0.07-0.082-0.105-0.123c-0.637-0.738-1.257-1.486-1.882-2.234C56.834,316.471,49.259,225.004,92.6,155.1
- c6.078,6.078-4.101,18.024,7.5,26c5.124,3.606,10.021,2.159,9,8.8c-0.993,6.449,5.355,6.335,6.3,12
- c2.842,12.429,19.207,18.642,9.9,32.6c-9.118,12.625-16.992,26.729-10.1,42.8c2.254,5.86,7.919,11.858,12.222,16.244
- c7.813,7.966,7.377,3.188,7.377,13.256c-0.156,4.373,5.261,8.897,4.7,11.7c-1.001,8.011-2.904,15.93-3.9,23.9
- c-1.792,28.638-0.129,56.662,21.3,78.1c-7.969-4.806-15.636-10.249-22.968-16.29C133.183,403.591,132.44,402.961,131.699,402.329z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/easel.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/easel.svg
deleted file mode 100644
index 75301a32..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/easel.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="80" y="144" width="352" height="192"/>
- <path d="M464,96H48c-8.837,0-16,7.163-16,16v256c0,8.837,6.932,16,15.768,16H464c8.837,0,16-7.163,16-16V112
- C480,103.163,472.837,96,464,96z M448,352H64V128h384V352z"/>
- <polygon points="80,480 112,480 140.147,400 108.835,400 "/>
- <polygon points="270.83,32 241.472,32 224.171,80 288.099,80 "/>
- <polygon points="371.853,400 400,480 432,480 403.22,400 "/>
- <rect x="240" y="400" width="32" height="48"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/edit.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/edit.svg
deleted file mode 100644
index 50d410ce..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/edit.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
-
- <rect x="178.846" y="92.087" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 224.3476 631.1498)" width="128.085" height="354.049"/>
- <path d="M471.723,88.393l-48.115-48.114c-11.723-11.724-31.558-10.896-44.304,1.85l-45.202,45.203l90.569,90.568l45.202-45.202
- C482.616,119.952,483.445,100.116,471.723,88.393z"/>
- <polygon points="64.021,363.252 32,480 148.737,447.979 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/egg.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/egg.svg
deleted file mode 100644
index 4ac5a56f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/egg.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C192,32,96,165.2,96,288.9C96,412.6,160,480,256,480s160-67.4,160-191.1C416,165.2,320,32,256,32z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eject.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eject.svg
deleted file mode 100644
index c9e173e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eject.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M399,320L399,320c10,0,16.8-7.1,16.8-15.9c0-3.3-1.1-6.1-2.8-9L275.3,104.7c-4.6-5.3-11.5-8.7-19.3-8.7
- c-7.7,0-14.6,3.4-19.2,8.7l-138,190.8c-1.7,2.6-2.6,5.5-2.6,8.7c0,8.7,6.8,15.8,16.8,15.8v0H399z"/>
- <path d="M403.7,352H108.4c-6.8,0-12.4,5.4-12.4,12.2v39.6c0,6.7,5.5,12.2,12.4,12.2h295.3c6.8,0,12.3-5.5,12.3-12.2v-39.6
- C416,357.4,410.5,352,403.7,352z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email-unread.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email-unread.svg
deleted file mode 100644
index ea4b15b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email-unread.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="432" cy="160" r="64"/>
- <g>
- <path d="M225,160H33.799c-11.1,0-13.898,3-11.299,10.5c1.5,4.4,8.4,8.1,12.5,10.2c11,5.8,163.799,89.1,169.5,92.1
- c5.699,3,11.5,4.4,20.5,4.4s14.799-1.4,20.5-4.4c3.79-1.995,72.625-39.497,121.559-66.107C357.594,193.551,352,177.433,352,160
- H225z"/>
- <path d="M293.199,273.3l82.201,92.5c2,2,2.898,4.4,1.799,5.601c-1.199,1.1-3.799,0.5-5.9-1.4l-98.6-83.2
- c-14.9,9.601-25.4,16.2-27.199,17.2c-7.701,3.9-13.1,4.4-20.5,4.4s-12.801-0.5-20.5-4.4c-1.9-1-12.301-7.6-27.201-17.2l-98.6,83.2
- c-2,2-4.699,2.6-5.9,1.4C71.6,370.3,72.5,367.8,74.5,365.8l82.1-92.5C107.9,241.8,33.5,189.4,25.299,185.2
- C16.5,180.7,16,186,16,190.1c0,4.101,0,205,0,205C16,404.4,29.699,416,39.5,416H225h185.5c9.799,0,21.5-11.7,21.5-20.9
- c0,0,0-94.398,0-155.1c-21.726,0-41.416-8.673-55.832-22.729C350.167,235.173,318.36,257.025,293.199,273.3z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email.svg
deleted file mode 100644
index e99edb3a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/email.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M67,148.7c11,5.8,163.8,89.1,169.5,92.1c5.7,3,11.5,4.4,20.5,4.4c9,0,14.8-1.4,20.5-4.4c5.7-3,158.5-86.3,169.5-92.1
- c4.1-2.1,11-5.9,12.5-10.2c2.6-7.6-0.2-10.5-11.3-10.5H257H65.8c-11.1,0-13.9,3-11.3,10.5C56,142.9,62.9,146.6,67,148.7z"/>
- <path d="M455.7,153.2c-8.2,4.2-81.8,56.6-130.5,88.1l82.2,92.5c2,2,2.9,4.4,1.8,5.6c-1.2,1.1-3.8,0.5-5.9-1.4l-98.6-83.2
- c-14.9,9.6-25.4,16.2-27.2,17.2c-7.7,3.9-13.1,4.4-20.5,4.4c-7.4,0-12.8-0.5-20.5-4.4c-1.9-1-12.3-7.6-27.2-17.2l-98.6,83.2
- c-2,2-4.7,2.6-5.9,1.4c-1.2-1.1-0.3-3.6,1.7-5.6l82.1-92.5c-48.7-31.5-123.1-83.9-131.3-88.1c-8.8-4.5-9.3,0.8-9.3,4.9
- c0,4.1,0,205,0,205c0,9.3,13.7,20.9,23.5,20.9H257h185.5c9.8,0,21.5-11.7,21.5-20.9c0,0,0-201,0-205
- C464,153.9,464.6,148.7,455.7,153.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask-bubbles.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask-bubbles.svg
deleted file mode 100644
index a7ae8868..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask-bubbles.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M445.9,427.1L328,227.9V78c0-7.7-6.5-14-14.5-14c-8,0-14.5,6.2-14.5,14v153.6c0,1.8,0.6,3.6,1.3,5.3
- c-7.6-11.1-20.6-18.4-35.4-18.4c-23.5,0-42.5,18.3-42.5,41c0,16.8,10.5,31.5,25.4,37.5h-72l35-58.5c1.2-2.1,2.1-4.5,2.1-6.9v-30.4
- c4,3.2,10,5.1,16.1,5.1c15.3,0,27.5-11.9,27.5-26.6c0-14.7-12.2-26.6-27.5-26.6c-6.1,0-12.1,1.9-16.1,5.1V78c0-7.7-6.5-14-14.5-14
- c-8,0-14.5,6.2-14.5,14v149.9L66.1,427.1c-2.5,4.3-2.6,9.6,0,13.9c2.6,4.3,7.2,7,12.4,7H256h177.5c5.1,0,9.8-2.6,12.4-7
- C448.5,436.8,448.4,431.4,445.9,427.1z M282.2,297c14.9-6,25.4-20.8,25.4-37.5c0-5.7-1.2-11.2-3.4-16.1l31,53.6H282.2z"/>
- <path d="M265.1,128.6c12,0,21.7-9.4,21.7-20.9c0-11.6-9.7-20.9-21.7-20.9c-12,0-21.7,9.4-21.7,20.9
- C243.3,119.2,253.1,128.6,265.1,128.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask.svg
deleted file mode 100644
index dba43584..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/erlenmeyer-flask.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M438.815,395.7L338.509,246.2c-12.8-20.3-19.009-44.4-19.009-70.2c0,0,0-73.5,0-93s12.592-33.25,15.009-42.083
- c2.296-8.392,0.512-8.417-15.188-8.417H192.526c-15.999,0-18.548,0.009-16.311,8.416C178.633,50,191.5,64.3,191.5,83.5
- s0,92.5,0,92.5c0,25.8-7.285,49.8-20.085,70.2l-49.279,76.5L73.035,395.6c-5.8,9-9.051,20.7-9.051,32.2
- c0,28,16.347,52.7,63.246,52.7h257.589c46.998,0,63.197-24.7,63.197-52.7C447.916,416.3,444.615,404.7,438.815,395.7z M409.218,441
- c-4.4,4.2-11.602,7.5-24.499,7.5h-257.59c-12.8,0-20.8-3.5-25.199-7.7c-2.7-2.6-6-7.05-6-13.35c0-5,1.4-10.125,3.9-14.125
- l99.039-150.392c15.699-25.199,24.632-55.231,24.632-86.932V64.5h64v111.4c0,31.199,7.761,61.3,23.859,87l100.523,150
- c2.499,4,3.968,9.25,3.968,14.25C415.85,433.55,411.918,438.4,409.218,441z"/>
- <path d="M389.217,411.301c0.051,0.075,0.1,0.397,0,0.249L307.345,288.5H203.698l-81.069,123.151c-1.5,2.1-2.3,5.175-2.3,7.974
- c0,7.5,6.288,13.875,13.687,13.875h244c7.5,0,13.599-6.725,13.599-14.125C391.614,416.875,390.516,413.301,389.217,411.301z
- M302.021,341.7c-1.5-1.5-2.3-3.601-2.3-5.7s0.899-4.2,2.3-5.7c1.5-1.5,3.6-2.3,5.6-2.3c2.102,0,4.2,0.8,5.602,2.3
- c1.5,1.5,2.299,3.601,2.299,5.7s-0.899,4.2-2.299,5.7c-1.5,1.5-3.5,2.3-5.602,2.3C305.621,344,303.521,343.1,302.021,341.7z
- M348.92,400.7c-1.4,0.898-2.9,1.3-4.302,1.3c-2.499,0-5.099-1.3-6.598-3.6l-23.499-35.9c-2.4-3.7-1.4-8.7,2.299-11.1
- c1.4-0.9,2.9-1.301,4.4-1.301c2.6,0,5.1,1.301,6.5,3.601L351.22,389.6C353.618,393.299,352.618,398.299,348.92,400.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye-disabled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye-disabled.svg
deleted file mode 100644
index bdb110dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye-disabled.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M376.4,158.3L448,86.6L425.4,64l-77.6,77.6C320,127.7,289.5,119,256,119c-81.9,0-145.7,52.2-224,137
- c34.8,37.4,66.8,72.7,103.3,98.1L64,425.4L86.6,448l76.9-76.9c27,13.7,57,21.9,92.5,21.9c99.9,0,173.4-81.8,224-135.5
- C452,223.4,417.6,185.7,376.4,158.3z M166.4,256c0-50.4,40.2-91.3,89.6-91.3c19.3,0,37.2,6.2,51.8,16.9l-50.7,50.7
- c-0.7-2.6-1.1-5.4-1.1-8.3c0-7.9,2.9-15.1,7.6-20.7c-2.5-0.4-5-0.6-7.6-0.6c-28.8,0-52.3,23.9-52.3,53.3c0,8.6,2,16.8,5.6,24
- L182,307.4C172.2,292.7,166.4,275,166.4,256z M256,347.3c-19.3,0-37.2-6.2-51.8-16.9l27.4-27.4c7.3,4,15.6,6.2,24.4,6.2
- c28.8,0,52.3-23.9,52.3-53.3c0-2.3-0.2-4.6-0.4-6.9c-5.5,4.3-12.3,6.9-19.8,6.9c-2.9,0-5.6-0.4-8.3-1.1l50.3-50.3
- c9.8,14.6,15.6,32.3,15.6,51.4C345.6,306.4,305.4,347.3,256,347.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye.svg
deleted file mode 100644
index 4b83a783..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/eye.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,128c-81.9,0-145.7,48.8-224,128c67.4,67.7,124,128,224,128c99.9,0,173.4-76.4,224-126.6
- C428.2,198.6,354.8,128,256,128z M256,347.3c-49.4,0-89.6-41-89.6-91.3c0-50.4,40.2-91.3,89.6-91.3s89.6,41,89.6,91.3
- C345.6,306.4,305.4,347.3,256,347.3z"/>
- <g>
- <path d="M256,224c0-7.9,2.9-15.1,7.6-20.7c-2.5-0.4-5-0.6-7.6-0.6c-28.8,0-52.3,23.9-52.3,53.3c0,29.4,23.5,53.3,52.3,53.3
- s52.3-23.9,52.3-53.3c0-2.3-0.2-4.6-0.4-6.9c-5.5,4.3-12.3,6.9-19.8,6.9C270.3,256,256,241.7,256,224z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/female.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/female.svg
deleted file mode 100644
index 2e8af488..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/female.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M288,284c55.2-14.2,96-64.3,96-124c0-70.7-57.3-128-128-128S128,89.3,128,160c0,59.6,40.8,109.7,96,124v68h-64v64h64v64h64
- v-64h64v-64h-64V284z M256,240c-44.1,0-80-35.9-80-80s35.9-80,80-80s80,35.9,80,80S300.1,240,256,240z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/filing.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/filing.svg
deleted file mode 100644
index 89a2b2ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/filing.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M381,128.6H132.1c-12.1,0-19.5,0-19.5,20.4v28.1h288V149C400.6,128.6,393.2,128.6,381,128.6z"/>
- <path d="M333,96.5H180c-13.1,0-19.5,0.3-19.5,18.7h192C352.4,96.8,346.1,96.5,333,96.5z"/>
- <path d="M432.4,169.6l-15.9-9.4v32.3h-321v-32.3l-15.2,9.4c-14.3,8.9-17.8,15.3-15,40.9l17.5,184.8c3.7,20.7,15.9,21.2,24,21.2
- h299.9c8.1,0,20.2-0.5,23.9-21.2l17.2-184.4C450.1,186.5,445.8,178.1,432.4,169.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/film-marker.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/film-marker.svg
deleted file mode 100644
index 73814adc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/film-marker.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448.4,208h-344l341.2-68c8.5-1.6,14-9.7,12.4-18.1l-8.9-45.4c-1.6-8.4-9.8-13.8-18.3-12.2L60.7,137.9
- c-8.5,1.6-14,9.7-12.4,18l8.9,45.4c0.6,2.8,2.1,5.2,3.9,7.2c-7.4,1.2-13.1,7.2-13.1,14.9v209.2c0,8.5,7,15.4,15.6,15.4h384.8
- c8.6,0,15.6-6.9,15.6-15.4V223.4C464,214.9,457,208,448.4,208z M305,402.4l-50.7-36.3l-50.7,36.3l19.5-58.4l-50.8-36H235l19.2-58.4
- l19.3,58.4h62.7l-50.8,36L305,402.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fireball.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fireball.svg
deleted file mode 100644
index 97b5521b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fireball.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M393.267,238.088l-0.231,10.404c-0.814,11.65-3.797,31.912-14.102,54.736c3.251-15.208,4.978-30.982,4.978-47.164
- c0-12.096-0.958-23.968-2.799-35.544c-15.091-94.901-89.626-169.923-184.138-185.518C185.706,32.285,179.048,32,179.048,32
- c0.238,0.281,0.465,0.562,0.7,0.844c39.458,47.181,44.1,96.656,37.744,131.85c-2.281,12.629-5.978,23.421-9.991,31.605
- c0,0,3.359-13.911,3.035-29.72c-0.293-14.234-3.572-30.006-14.986-38.552c3.497,18.378-0.752,33.501-9.121,47.729
- C161.69,217.808,101,249.386,96,327.408v3.836c0,53.692,25.624,98.979,68.719,125.012c-6.85-12.344-14.964-35.207-8.733-60.151
- c3.998,23.669,9.951,36.045,20.879,51.756c8.153,11.721,19.104,19.269,33.095,24.934S238.995,480,255.889,480
- c55.809,0,105.228-28.567,133.845-71.952l0.267,0.061v-0.007c16-25.254,26.1-55.5,26.1-88.019
- C416.1,290.112,407.596,262.071,393.267,238.088z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flag.svg
deleted file mode 100644
index 5f7ded31..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flag.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M426.4,182.5c-35.8,5.9-94.2,7.5-133-66.1c-41.6-79.1-108.8-81.5-148.1-74.3c-19.1,3.5-33.4,19.5-33.4,35v196.6
- c11.3,4.3,23.4-0.2,26.5-0.8c0.8-0.2,1.5-0.3,2.4-0.5c25-5.5,51.4-8.1,116.8,23.3c82,39.3,153.8-33.1,181.6-83.5
- c2-3.5,8.7-20.2,8.7-36.2C438.2,180,426.4,182.5,426.4,182.5z"/>
- <path d="M88,32H72c-4.4,0-8,3.6-8,8v432c0,4.4,3.6,8,8,8h16c4.4,0,8-3.6,8-8V40C96,35.6,92.4,32,88,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flame.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flame.svg
deleted file mode 100644
index 5b7c6401..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flame.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M128.922,320c13.05,134,103.764,160,126.932,160c23.168,0,127.457-40.49,128.142-160c0.836-146-121.586-143-95.895-288
- C201.427,96,118.289,210.816,128.922,320z M215.667,368c0-44.183,40.187-80,40.187-80s40.701,35.817,40.701,80
- c0,44.184-40.701,80-40.701,80S215.667,412.184,215.667,368z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash-off.svg
deleted file mode 100644
index eca230e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash-off.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M147.4,451.9c0.4,0.2,0.7,0.5,1.1,0.7c10.9,6,22.5,10.7,34.4,14.8c1.8,0.6,3.6,1.2,5.4,1.8c21.4,6.8,44,10.9,67.7,10.9
- c123.7,0,224-100.3,224-224c0-84.3-46.6-157.7-115.5-195.9c-0.4-0.2-0.7-0.4-1-0.6c-10.9-6-22.5-10.7-34.4-14.8
- c-1.8-0.6-3.6-1.2-5.4-1.8C302.3,36.1,279.6,32,256,32C132.3,32,32,132.3,32,256C32,340.3,78.6,413.6,147.4,451.9z M118.2,156.6
- l54.4,54.4l36.3-40.5l-52.4-52.4c28-20.2,62.1-32.6,99.4-32.6c9.3,0,18.3,0.9,27.2,2.4c9.8,1.6,19.3,4.1,28.5,7.3
- c1.8,0.6,3.7,1.2,5.6,1.9c6.2,2.4,12.2,5,18,8.1c54.2,28.5,91.2,85.3,91.2,150.8c0,37.2-12.4,71.3-32.7,99.4l-54.4-54.4L303,341.4
- l52.4,52.4c-28,20.3-62.2,32.7-99.4,32.7c-9.3,0-18.4-0.9-27.2-2.4c-9.8-1.6-19.3-4.1-28.5-7.3c-1.9-0.6-3.8-1.2-5.6-1.9
- c-6.5-2.5-12.9-5.3-19-8.6c-53.6-28.7-90.1-85.2-90.1-150.3C85.6,218.8,98,184.7,118.2,156.6z"/>
- <polygon points="209.7,389.8 348.9,235 263.6,235 302.2,122.2 163.1,277 248.4,277 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash.svg
deleted file mode 100644
index 84c0032b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/flash.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="96,288 243,288 191.9,480 416,224 269,224 320,32 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/folder.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/folder.svg
deleted file mode 100644
index 0cb47be8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/folder.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M430.1,192H81.9c-17.7,0-18.6,9.2-17.6,20.5l13,183c0.9,11.2,3.5,20.5,21.1,20.5h316.2c18,0,20.1-9.2,21.1-20.5l12.1-185.3
- C448.7,199,447.8,192,430.1,192z"/>
- <g>
- <path d="M426.2,143.3c-0.5-12.4-4.5-15.3-15.1-15.3c0,0-121.4,0-143.2,0c-21.8,0-24.4,0.3-40.9-17.4C213.3,95.8,218.7,96,190.4,96
- c-22.6,0-75.3,0-75.3,0c-17.4,0-23.6-1.5-25.2,16.6c-1.5,16.7-5,57.2-5.5,63.4h343.4L426.2,143.3z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork-repo.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork-repo.svg
deleted file mode 100644
index 7136045b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork-repo.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <polygon class="st0" points="416,80 368,80 368,32 304,32 304,80 256,80 256,144 304,144 304,192 368,192 368,144 416,144 "/>
- <path class="st0" d="M304,240c0,38.6-4.5,42.3-14.4,50.3c-7.4,6-22.2,7.1-39.4,8.3c-9.5,0.7-20.4,1.5-31.4,3.3
- c-9.4,1.5-18.4,4.7-26.8,8.8V151.4c19.1-11.1,32-31.7,32-55.4c0-35.3-28.7-64-64-64S96,60.7,96,96c0,23.7,12.9,44.3,32,55.4v209.2
- c-19.1,11.1-32,31.7-32,55.4c0,35.3,28.7,64,64,64s64-28.7,64-64c0-15.7-5.7-30.1-15-41.2c6.7-4.8,13.9-8.7,20.2-9.7
- c8.1-1.3,16.6-1.9,25.6-2.6c24.4-1.7,52.1-3.7,75.2-22.5c30.9-25.1,37.5-52.1,38-94.9l0,0V240H304z M160,64c17.6,0,32,14.4,32,32
- s-14.4,32-32,32s-32-14.4-32-32S142.4,64,160,64z M160,448c-17.6,0-32-14.4-32-32s14.4-32,32-32s32,14.4,32,32S177.6,448,160,448z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork.svg
deleted file mode 100644
index 79f076ea..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/fork.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M270.2,148.9C270.2,149,270.1,149,270.2,148.9v0.1V148.9z"/>
- <path d="M320,166c0-43.2-15-93.2-24-133.7V32h-8l-0.2,116.9c0,6.1-2.9,11.1-9,11.1c-5.7,0-8-4.3-8.6-9.9c-0.1-0.4,0-0.8,0-1.2
- L259.9,32h-8l-9,117l-0.1,1.1c-0.6,5.6-3.7,9.9-9.5,9.9c-6.1,0-9.1-5-9.1-11.1L223.8,32h-8C207,73,192,122.9,192,166.1
- c0,25.7,14.6,48.1,36.7,58.2c11.2,5.1,11.3,10.3,11.3,10.3s-16,201.7-16,213.1c0,11.4,4,18.5,9.5,24s14.2,8.2,22.4,8.2
- c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0c8.2,0,16.8-2.7,22.4-8.2c5.5-5.5,9.3-10.9,9.3-24c0-13.1-16-213.1-16-213.1s-1-5,11.4-10.6
- C305,214.2,320,191.8,320,166z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/forward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/forward.svg
deleted file mode 100644
index 55f0815e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/forward.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M288,298.1v92.3L448,256L288,112v80C100.8,192,64,400,64,400C117,307,186.4,298.1,288,298.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/funnel.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/funnel.svg
deleted file mode 100644
index 0174f908..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/funnel.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256.085,32c-123.79,0-224.096,35.817-224.096,80c0,8.476,3.729,16.642,10.573,24.309l-0.061,0.008
- C74.408,175.213,192,313,192,352v87l0,0c0,22.688,28.891,41,64,41s64-18.312,64-41l0,0v-83.088c0-1.241,0.008-2.54,0.008-3.912
- C320.008,313,436,177.432,471,134.062v-0.002c6-7.007,8.977-14.408,8.977-22.06C479.977,67.817,379.875,32,256.085,32z
- M256.178,160c-92.058,0-176.112-22-176.112-48s83.053-48,176.112-48c93.06,0,176.111,22.413,176.111,48S348.236,160,256.178,160z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-a.svg
deleted file mode 100644
index d8953415..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-a.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M411.1,256c0-23.9,14.8-42.8,36.9-55.8c-4-13.3-9.3-26.2-15.8-38.2c-24.9,6.5-45-3.2-62-20.2c-16.9-16.9-22.1-37.1-15.6-62
- C342.6,73.3,329.8,68,316.4,64c-13,22.2-36.4,36.9-60.4,36.9c-23.9,0-47.4-14.7-60.4-36.9c-13.4,4-26.2,9.3-38.2,15.8
- c6.5,24.9,1.3,45-15.6,62c-16.9,16.9-37.1,26.7-61.9,20.2C73.3,174,68,186.8,64,200.2c22.2,13,37,31.9,37,55.8
- c0,23.9-14.8,47.4-37,60.4c4,13.4,9.3,26.2,15.8,38.2c24.9-6.5,45-1.3,61.9,15.6c17,16.9,22.1,37.1,15.6,62
- c12.1,6.5,24.8,11.8,38.2,15.8c13-22.2,36.5-36.9,60.4-36.9c23.9,0,47.4,14.7,60.4,36.9c13.4-4,26.2-9.3,38.2-15.8
- c-6.5-24.9-1.3-45,15.6-62c16.9-16.9,37.1-26.7,62-20.2c6.5-12.1,11.8-24.9,15.8-38.2C425.8,298.8,411.1,279.9,411.1,256z
- M256,354.3c-54.2,0-98.3-44-98.3-98.3c0-54.3,44-98.3,98.3-98.3c54.3,0,98.3,44,98.3,98.3C354.3,310.3,310.3,354.3,256,354.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-b.svg
deleted file mode 100644
index 88b31299..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/gear-b.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448,294.4v-76.8h-42.8c-3.4-14.4-8.9-28-16.1-40.5l29.8-29.7l-54.3-54.3l-29.1,29.1c-12.6-7.7-26.4-13.5-41.1-17.3V64
- h-76.8v40.9c-14.7,3.8-28.5,9.7-41.1,17.3l-29.1-29.1l-54.3,54.3l29.8,29.7c-7.2,12.5-12.6,26.1-16.1,40.5H64v76.8h44.1
- c3.8,13.7,9.5,26.6,16.7,38.6l-31.7,31.7l54.3,54.3l32.3-32.3c11.7,6.8,24.5,11.9,37.9,15.4v46h76.8v-46
- c13.5-3.5,26.2-8.6,37.9-15.4l32.3,32.3l54.3-54.3L387.3,333c7.2-11.9,12.9-24.8,16.7-38.6H448z M256,309.8
- c-29.7,0-53.7-24.1-53.7-53.8s24-53.8,53.7-53.8s53.8,24.1,53.8,53.8S285.7,309.8,256,309.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/grid.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/grid.svg
deleted file mode 100644
index 7100f22e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/grid.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M160,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
- />
- <path d="M288,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
- />
- <path d="M416,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
- />
- </g>
- <g>
- <path d="M160,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
- />
- <path d="M288,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
- />
- <path d="M416,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
- />
- </g>
- <g>
- <path d="M160,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
- />
- <path d="M288,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
- />
- <path d="M416,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
- />
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/hammer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/hammer.svg
deleted file mode 100644
index a6b2d085..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/hammer.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M410,32h-52c-3.3,0-6,2.7-6,6v5.6c-4,4-10.9,9.8-17.8,9.8c-10.5,0-14.8-16.4-26.1-18.4s-27.2-3-37.9-3s-52,0.7-102,21.5
- c-50,20.8-71.7,64.9-72.3,81.4c-0.3,8.7,2.7,21.1,10,11.1c7.3-10,35.3-42.3,57.7-44.7c22.3-2.3,45.7,0.8,63.7,17.2
- c17.3,15.7,21.3,30.8,21.3,73.5l-6.6,2c-4.3,1.3-7,5.7-7,9c0,0-0.2,6.5-0.2,70.4C234.8,368,224,474,224,474c0,3.3,2.7,6,6,6h84
- c3.3,0,6-2.7,6-6c0,0-10.8-106-10.8-200.6c0-63.9-0.2-70.4-0.2-70.4c0-3.3-2.3-7.8-7-9l-8-2c0-38.2-0.4-54,6.3-65.9
- c7-12.4,22.3-22.9,29.7-25.1c5.9-1.8,16,1.3,22,6.5V122c0,3.3,2.7,6,6,6h52c3.3,0,6-2.7,6-6V38C416,34.7,413.3,32,410,32z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy-outline.svg
deleted file mode 100644
index f5d7cc4b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy-outline.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M387.469,289.593c-2.248-1.175-4.775-1.796-7.308-1.796c-5.956,0-11.358,3.287-14.104,8.588
- C347.804,331.731,304.605,352,256.004,352c-49.734,0-93.84-20.562-109.757-54.997c-2.589-5.589-8.244-9.199-14.407-9.199
- c-2.294,0-4.521,0.485-6.658,1.463c-7.926,3.674-11.397,13.117-7.734,21.057C138.454,355.765,194.135,384,256.004,384
- c60.34,0,114.604-27.281,138.241-73.055C398.254,303.184,395.201,293.598,387.469,289.593z"/>
- <path d="M412.793,231.174C402.312,217.593,389.024,208,368.137,208c-20.887,0-34.062,9.573-44.611,23.117
- c-5.502,7.062-4.525,16.633,3.746,22.207c2.914,1.963,6.347,2.676,9.928,2.676c5.395-0.001,10.507-2.109,13.67-6.179
- c3.45-4.435,7.707-9.821,17.268-9.821c9.61,0,13.832,5.361,17.23,9.777c3.178,4.104,8.305,6.223,13.717,6.223
- c3.581,0,7.007-0.708,9.922-2.683C416.558,248.185,418.257,238.25,412.793,231.174z"/>
- <path d="M188.792,231.174C178.312,217.593,165.024,208,144.137,208s-34.063,9.573-44.612,23.117
- c-5.501,7.062-4.525,16.633,3.747,22.207c2.914,1.963,6.346,2.676,9.927,2.676c5.395-0.001,10.507-2.109,13.669-6.179
- c3.451-4.435,7.708-9.821,17.269-9.821c9.61,0,13.832,5.361,17.23,9.777c3.177,4.104,8.304,6.223,13.716,6.223
- c3.582,0,7.007-0.708,9.922-2.683C192.558,248.185,194.257,238.25,188.792,231.174z"/>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M391.765,391.765
- C355.5,428.028,307.285,448,256,448s-99.5-19.972-135.765-56.235C83.972,355.5,64,307.285,64,256s19.972-99.5,56.235-135.765
- C156.5,83.972,204.715,64,256,64s99.5,19.972,135.765,56.235C428.028,156.5,448,204.715,448,256S428.028,355.5,391.765,391.765z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy.svg
deleted file mode 100644
index cba963ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/happy.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M103.272,253.324
- c-8.272-5.574-9.249-15.145-3.747-22.207C110.074,217.573,123.25,208,144.137,208s34.174,9.593,44.655,23.174
- c5.464,7.076,3.765,17.011-3.787,22.144c-2.915,1.975-6.341,2.683-9.922,2.683c-5.412,0-10.539-2.119-13.716-6.223
- c-3.398-4.416-7.621-9.777-17.23-9.777c-9.561,0-13.818,5.387-17.269,9.821c-3.163,4.069-8.274,6.178-13.669,6.179
- C109.618,256,106.186,255.287,103.272,253.324z M394.245,310.945C370.607,356.719,316.344,384,256.004,384
- c-61.869,0-117.55-28.235-138.556-73.677c-3.663-7.939-0.191-17.383,7.734-21.057c2.137-0.978,4.363-1.463,6.658-1.463
- c6.163,0,11.818,3.61,14.407,9.199C162.164,331.438,206.27,352,256.004,352c48.602,0,91.8-20.269,110.053-55.615
- c2.746-5.301,8.148-8.588,14.104-8.588c2.532,0,5.06,0.621,7.308,1.796C395.201,293.598,398.254,303.184,394.245,310.945z
- M409.006,253.317c-2.915,1.975-6.341,2.683-9.922,2.683c-5.412,0-10.539-2.119-13.717-6.223c-3.398-4.416-7.62-9.777-17.23-9.777
- c-9.561,0-13.817,5.387-17.268,9.821c-3.163,4.069-8.275,6.178-13.67,6.179c-3.581,0-7.014-0.713-9.928-2.676
- c-8.271-5.574-9.248-15.145-3.746-22.207C334.074,217.573,347.25,208,368.137,208c20.888,0,34.175,9.593,44.656,23.174
- C418.257,238.25,416.558,248.185,409.006,253.317z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/headphone.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/headphone.svg
deleted file mode 100644
index b49c9340..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/headphone.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M447.4,238.2c-3.2-59.8-21.9-108.6-56-145.2c-0.1-0.1-0.1-0.1-0.2-0.2c-7.7-8.4-16.1-15.9-24.8-22.6
- c-9-6.9-18.6-13-28.5-18.1c-25.3-13.1-53-20-82.1-20c-29,0-56.6,6.9-81.9,20c-9.9,5.1-19.4,11.2-28.4,18.1
- c-8.7,6.7-17,14.2-24.7,22.6c-0.1,0.1-0.1,0.1-0.2,0.2c-34,36.6-52.7,85.5-55.9,145.2C61.9,288.9,68,368,77.7,400
- c20.3,67,40.4,80,72.1,80s58.2-26.4,58.2-58.9V315.1c0-32.5-23.3-59-53.3-59c-18,0-34,9.7-43.8,24.4c0,0-11.1-8.1-13.1-23
- c-2.1-14.9-3.1-32.4,5.6-63c8.7-30.5,20.8-20.2,35.6-39c2.5-3.3,5.2-6.4,8-9.5c3.2-3.4,6.4-6.7,9.8-9.7c1.6-1.5,3.2-2.8,4.8-4.2
- c11-9.3,21-17,33.7-22.8c18.9-8.6,39.4-13.3,60.5-13.3c21,0,41.7,4.7,60.7,13.3c12.7,5.8,22.9,13.5,33.9,22.8
- c1.6,1.4,3.2,2.7,4.8,4.2c3.4,3,6.6,6.3,9.8,9.7c2.8,3.1,5.5,6.2,8,9.5c14.8,18.8,26.9,8.5,35.6,39c8.7,30.5,7.6,48.1,5.6,63
- c-2.1,14.9-13.1,23-13.1,23c-9.8-14.7-25.7-24.4-43.8-24.4c-30,0-53.3,26.4-53.3,59v106.1c0,32.4,26.5,58.9,58.2,58.9
- c31.7,0,51.8-13,72.1-80C444,368,450.1,288.9,447.4,238.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart-broken.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart-broken.svg
deleted file mode 100644
index 984e31aa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart-broken.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M229,288c1-18,0-38,8-55c2-5,1-10,1-15c-4-21-14-40-15-60c0-1.39,1.004-4.771,1.005-6.157
- c-3.216,2.234-7.607,4.024-11.005,5.157c-20,6-17.51,2.573-34.51,13.573l-11.933,7.228c16.343-17.939,38.528-24.781,56.525-38.714
- c0.194-15.438,0.858-30.677,3.137-45.84C185.61,53.496,121.785,54.268,82.123,95.57c-45.497,47.344-45.497,124.101,0,171.445
- l152.849,159.096c-0.085-10.656-0.443-21.176-1.972-31.111C227,359,229,324,229,288z"/>
- <path d="M322,301c-11-26-33-44-63-50c-0.85,0-1.879-0.543-2.936-1.319c-0.023,0.107-0.041,0.213-0.064,0.319c-11,48-23,94-21,142
- c0,12.227,3.983,25.117,3.833,38.131L256,448l104-108.25C345.153,329.271,330.428,318.621,322,301z"/>
- <path d="M429.874,95.57c-40.426-42.094-105.989-42.094-146.408,0L264,115.403c0.075,13.175,0.213,26.202-3,38.597
- c-2,10-19,19-16,31c3.003,13.213,8.166,25.705,10.732,38.559C271.014,232.084,284.771,242.896,297,256
- c22.801,26.766,37.747,57.459,65.283,81.371l67.591-70.355C475.375,219.671,475.375,142.914,429.874,95.57z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart.svg
deleted file mode 100644
index 945b5103..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/heart.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M429.9,95.6c-40.4-42.1-106-42.1-146.4,0L256,124.1l-27.5-28.6c-40.5-42.1-106-42.1-146.4,0c-45.5,47.3-45.5,124.1,0,171.4
- L256,448l173.9-181C475.4,219.7,475.4,142.9,429.9,95.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-buoy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-buoy.svg
deleted file mode 100644
index 106cff94..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-buoy.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,132.3,32,256s100.3,224,224,224s224-100.3,224-224S379.7,32,256,32z M434.3,184.5l-61.5,18.9
- c-6.3-14-15.1-26.8-26.3-38c-11.2-11.2-24-20-38-26.3l18.9-61.5c23.8,9.5,45.6,23.9,64.3,42.5C410.4,138.9,424.8,160.7,434.3,184.5z
- M256,352c-53,0-96-43-96-96c0-53,43-96,96-96s96,43,96,96C352,309,309,352,256,352z M120.2,120.2c18.7-18.7,40.5-33,64.3-42.5
- l18.9,61.5c-14,6.3-26.8,15.1-38,26.3c-11.2,11.2-20,24-26.3,38l-61.5-18.9C87.2,160.7,101.6,138.9,120.2,120.2z M77.7,327.5
- l61.5-18.9c6.3,14,15.1,26.8,26.3,38s24,20,38,26.3l-18.9,61.5c-23.8-9.5-45.6-23.9-64.3-42.5C101.6,373.1,87.2,351.3,77.7,327.5z
- M391.8,391.8c-18.7,18.7-40.5,33-64.3,42.5l-18.9-61.5c14-6.3,26.8-15.1,38-26.3s20-24,26.3-38l61.5,18.9
- C424.8,351.3,410.4,373.1,391.8,391.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-circled.svg
deleted file mode 100644
index f70e8313..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help-circled.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32C132.3,32,32,132.3,32,256s100.3,224,224,224c123.7,0,224-100.3,224-224S379.7,32,256,32z M276.2,358.7
- c-0.5,17.8-13.7,28.8-30.8,28.3c-16.4-0.5-29.3-12.2-28.8-30.1c0.5-17.8,14.1-29.1,30.5-28.6C264.3,328.8,276.8,340.9,276.2,358.7z
- M324.9,231.4c-4.2,5.9-13.6,13.5-25.4,22.7l-13.1,9c-6.4,4.9-10.4,10.7-12.5,17.3c-1.1,3.5-1.9,12.6-2.1,18.7
- c-0.1,1.2-0.8,3.9-4.5,3.9c-3.7,0-35,0-39.1,0c-4.1,0-4.6-2.4-4.5-3.6c0.6-16.6,3-30.3,9.9-41.3c9.3-14.8,35.5-30.4,35.5-30.4
- c4-3,7.1-6.2,9.5-9.7c4.4-6,8-12.7,8-19.9c0-8.3-2-16.2-7.3-22.8c-6.2-7.7-12.9-11.4-25.8-11.4c-12.7,0-20.1,6.4-25.4,14.8
- c-5.3,8.4-4.4,18.3-4.4,27.3H175c0-34,8.9-55.7,27.7-68.5c12.7-8.7,28.9-12.5,47.8-12.5c24.8,0,44.5,4.6,61.9,17.8
- c16.1,12.2,24.6,29.4,24.6,52.6C337,209.7,332,221.7,324.9,231.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help.svg
deleted file mode 100644
index cd4dcb8b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/help.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M345.1,77.1C317.6,56.2,286.6,49,247.3,49c-29.8,0-55.3,6.1-75.5,19.7C142,89,128,123.1,128,177h76.8
- c0-14.4-1.4-29.9,7-43.2c8.4-13.3,20.1-23.5,40.2-23.5c20.4,0,30.9,5.9,40.8,18.1c8.4,10.4,11.6,22.8,11.6,36
- c0,11.4-5.8,21.9-12.7,31.4c-3.8,5.6-8.8,10.6-15.1,15.4c0,0-41.5,24.7-56.1,48.1c-10.9,17.4-14.8,39.2-15.7,65.3
- c-0.1,1.9,0.6,5.8,7.2,5.8c6.5,0,56,0,61.8,0c5.8,0,7-4.4,7.1-6.2c0.4-9.5,1.6-24.1,3.3-29.6c3.3-10.4,9.7-19.5,19.7-27.3
- l20.7-14.3c18.7-14.6,33.6-26.5,40.2-35.9c11.3-15.4,19.2-34.4,19.2-56.9C384,123.5,370.5,96.4,345.1,77.1z M242,370.2
- c-25.9-0.8-47.3,17.2-48.2,45.3c-0.8,28.2,19.5,46.7,45.5,47.5c27,0.8,47.9-16.6,48.7-44.7C288.8,390.2,269,371,242,370.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/home.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/home.svg
deleted file mode 100644
index 7a642ddf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/home.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="448,288 256,64 64,288 112,288 112,448 208,448 208,320 304,320 304,448 400,448 400,288 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/icecream.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/icecream.svg
deleted file mode 100644
index 21bfc9aa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/icecream.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="128,256 256,480 384,256 "/>
- <g>
- <path d="M402.5,172.6c-0.8-0.4-1.5-0.8-2.3-1.3c-4.4-2.8-8.4-8.5-8.7-12.7l0.1-0.7c3.2-9,5-19.2,5-29.8c0-53.1-43-96.1-96.1-96.1
- c-31.4,0-59.2,15-76.8,38.3c0,0-9.1,14-10.8,29c0,0,1.1-19.4,4.2-31.5c-7.4-2.5-15.4-3.8-23.6-3.8c-41.7,0-75.6,33.8-75.6,75.6
- c0,6.4,0.8,12.6,2.3,18.5c0,0.4-0.1,0.7-0.2,1c-0.9,5.1-4,9.5-8.4,12.3c-0.7,0.5-1.5,0.9-2.2,1.3c-8.2,5-13.5,13.6-13.5,23.4
- c0,15.4,13.5,28,29.9,28h4.1h252h4.1c16.4,0,29.8-12.5,29.8-28C416,186.3,410.6,177.6,402.5,172.6z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/image.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/image.svg
deleted file mode 100644
index 7faf9bb3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/image.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M368,224c26.5,0,48-21.5,48-48c0-26.5-21.5-48-48-48c-26.5,0-48,21.5-48,48C320,202.5,341.5,224,368,224z"/>
- <path d="M452,64H60c-15.6,0-28,12.7-28,28.3v327.4c0,15.6,12.4,28.3,28,28.3h392c15.6,0,28-12.7,28-28.3V92.3
- C480,76.7,467.6,64,452,64z M348.9,261.7c-3-3.5-7.6-6.2-12.8-6.2c-5.1,0-8.7,2.4-12.8,5.7l-18.7,15.8c-3.9,2.8-7,4.7-11.5,4.7
- c-4.3,0-8.2-1.6-11-4.1c-1-0.9-2.8-2.6-4.3-4.1L224,215.3c-4-4.6-10-7.5-16.7-7.5c-6.7,0-12.9,3.3-16.8,7.8L64,368.2V107.7
- c1-6.8,6.3-11.7,13.1-11.7h357.7c6.9,0,12.5,5.1,12.9,12l0.3,260.4L348.9,261.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/images.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/images.svg
deleted file mode 100644
index c14db6c6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/images.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M457.6,140.2l-82.5-4l-4.8-53.8c-1-11.3-11.1-19.2-22.9-18.3L51.4,88.4c-11.8,1-20.3,10.5-19.4,21.7l21.2,235.8
- c1,11.3,11.2,19.2,22.9,18.3l15-1.2l-2.4,45.8c-0.6,12.6,9.2,22.8,22.4,23.5L441.3,448c13.2,0.6,24.1-8.6,24.8-21.2L480,163.5
- C480.6,151,470.7,140.8,457.6,140.2z M102.6,145.5l-7.1,134.8L78.1,305l-16-178c0-0.2,0-0.3,0-0.5s0-0.3,0-0.5
- c0.5-5,4.3-9,9.5-9.4l261-21.4c5.2-0.4,9.7,3,10.5,7.9c0,0.2,0.3,0.2,0.3,0.4c0,0.1,0.3,0.2,0.3,0.4l2.7,30.8l-219-10.5
- C114.2,123.8,103.2,133,102.6,145.5z M436.7,382.4l-46.7-55.3l-27.5-32.7c-2.4-2.9-6.3-5.3-10.6-5.5c-4.3-0.2-7.5,1.5-11.1,4.1
- l-16.4,11.9c-3.5,2.1-6.2,3.5-9.9,3.3c-3.6-0.2-6.8-1.6-9.1-3.8c-0.8-0.8-2.3-2.2-3.5-3.4l-42.8-48.9c-3.1-3.9-8.2-6.4-13.8-6.7
- c-5.7-0.3-11.2,2.1-14.8,5.6L129.4,359.8l-6.8,7.4l0.3-6.8l6.8-128.9l3.3-62.9c0-0.2,0-0.4,0-0.5c0-0.2,0-0.4,0-0.5
- c1.4-5.4,6.2-9.3,11.9-9l204.2,9.8l28.7,1.4l58.3,2.8c5.8,0.3,10.3,4.7,10.4,10.2c0,0.2,0.3,0.3,0.3,0.5c0,0.2,0.3,0.3,0.3,0.5
- L436.7,382.4z"/>
- </g>
- <path d="M373.2,262.3c19.4,0,35.2-15.8,35.2-35.2s-15.7-35.2-35.2-35.2c-19.4,0-35.2,15.7-35.2,35.2S353.7,262.3,373.2,262.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information-circled.svg
deleted file mode 100644
index bed4eda7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information-circled.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M480,253C478.3,129.3,376.7,30.4,253,32S30.4,135.3,32,259c1.7,123.7,103.3,222.6,227,221C382.7,478.3,481.7,376.7,480,253
- z M256,111.9c17.7,0,32,14.3,32,32s-14.3,32-32,32c-17.7,0-32-14.3-32-32S238.3,111.9,256,111.9z M300,395h-88v-11h22V224h-22v-12
- h66v172h22V395z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information.svg
deleted file mode 100644
index 6a72ba5f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/information.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="288,448 288,192 192,192 192,208 224,208 224,448 192,448 192,464 320,464 320,448 "/>
- <path d="M255.8,144.5c26.6,0,48.2-21.6,48.2-48.2s-21.6-48.2-48.2-48.2c-26.6,0-48.2,21.6-48.2,48.2S229.2,144.5,255.8,144.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ionic.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ionic.svg
deleted file mode 100644
index 1db7b69a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ionic.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M423.592,132.804C427.006,127.714,429,121.59,429,115c0-17.675-14.33-32-32-32c-6.59,0-12.714,1.994-17.805,5.409
- C344.709,63.015,302.11,48,256,48C141.125,48,48,141.125,48,256c0,114.877,93.125,208,208,208c114.873,0,208-93.123,208-208
- C464,209.889,448.984,167.29,423.592,132.804z M391.83,391.832c-17.646,17.646-38.191,31.499-61.064,41.174
- c-23.672,10.012-48.826,15.089-74.766,15.089c-25.94,0-51.095-5.077-74.767-15.089c-22.873-9.675-43.417-23.527-61.064-41.174
- s-31.5-38.191-41.174-61.064C68.982,307.096,63.905,281.94,63.905,256c0-25.94,5.077-51.095,15.089-74.767
- c9.674-22.873,23.527-43.417,41.174-61.064s38.191-31.5,61.064-41.174C204.905,68.982,230.06,63.905,256,63.905
- c25.939,0,51.094,5.077,74.766,15.089c13.446,5.687,26.08,12.83,37.802,21.327C366.293,104.719,365,109.707,365,115
- c0,17.675,14.327,32,32,32c5.293,0,10.28-1.293,14.678-3.568c8.498,11.721,15.641,24.355,21.327,37.801
- c10.013,23.672,15.09,48.827,15.09,74.767c0,25.939-5.077,51.096-15.09,74.768C423.33,353.641,409.478,374.186,391.83,391.832z"/>
- <circle cx="256.003" cy="256" r="96"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm-outline.svg
deleted file mode 100644
index e53ca3e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm-outline.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M438.4,192.4c12.2-14.2,19.6-32.3,19.6-52.2c0.1-43.8-35.5-79.6-80.4-82.1c-1.6-0.1-3.1-0.1-4.8-0.1
- c-20.4-0.1-39.1,6.8-53.8,18.1l53.8,52.4l-10.5,10.4c-25.7-19.4-57-32-91-34.9v-0.1c0-8.5-7-15.5-15.5-15.5
- c-8.5,0-15.5,7-15.5,15.5v0.1c-33.9,2.9-65.1,15.5-90.7,34.9l-10.4-10.4l53.8-52.4c-14.7-11.4-33.4-18.2-53.7-18.1
- c-1.6,0-3.2,0.1-4.8,0.1c-45,2.5-80.6,38.3-80.4,82.1c0,19.8,7.4,38,19.6,52.2l54-52.6l9.5,9.5c-35.1,31.9-57.1,78-57.1,129.2
- c0,43.9,16.2,84,43,114.7l-36.4,44.6L99,448l35.2-42.9c31.6,30.2,74.4,48.9,121.6,48.9h0.1c0,0,0.2,0,0.3,0
- c47.2,0,90.2-18.7,121.8-48.9l35.2,43l12.3-10.1L389,393.3c26.8-30.8,43-70.9,43-114.7c0-51.1-22-97.3-57.2-129.3l9.5-9.5
- L438.4,192.4z M76.2,167.8c-4.2-8.6-6.4-18.4-6.5-28c-0.1-35.1,28.4-64.6,65.5-66.8c12.7-0.7,23.1,1.4,32.1,6.1L76.2,167.8z
- M415.9,276.5c0,87.7-72,157.1-160.1,157.1C167.8,433.6,96,364.2,96,276.5c0-87.7,71.8-158.7,159.9-158.7
- C344,117.8,415.9,188.7,415.9,276.5z M344.7,79.2c8.8-4.8,19.3-6.8,32.1-6.1c37.2,2,65.6,31.5,65.5,66.8c0,9.6-2.3,19.4-6.5,28.1
- L344.7,79.2z"/>
- </g>
- <polygon points="256,160 256,288 160,288 160,304 272,304 272,160 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm.svg
deleted file mode 100644
index b8339b6a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-alarm.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M438.4,192.4c12.2-14.2,19.6-32.3,19.6-52.2c0.1-43.8-35.5-79.6-80.4-82.1c-1.6-0.1-3.1-0.1-4.8-0.1
- c-20.4-0.1-39.1,6.8-53.8,18.1l53.8,52.4l-10.6,10.4c-25.7-19.4-57.2-32-91.2-34.9v-0.1c0-8.5-7-15.5-15.5-15.5s-15.5,7-15.5,15.5
- v0.1c-34,2.9-65,15.5-90.6,34.9L139,128.6l53.8-52.4c-14.7-11.4-33.4-18.2-53.7-18.1c-1.6,0-3.2,0.1-4.8,0.1
- c-45,2.5-80.6,38.3-80.4,82.1c0,19.8,7.4,38,19.6,52.2l54-52.6l9.5,9.5c-35.1,31.9-57.1,78-57.1,129.2c0,43.9,16.2,84,43,114.7
- l-36.4,44.6L99,448l35.2-42.9c31.6,30.2,74.4,48.9,121.6,48.9h0.1c0,0,0.2,0,0.3,0c47.2,0,90.2-18.7,121.8-48.9l35.2,43l12.3-10.1
- L389,393.3c26.8-30.8,43-70.9,43-114.7c0-51.1-22-97.3-57.2-129.3l9.5-9.5L438.4,192.4z M272,304H160v-16h96V160h16V304z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums-outline.svg
deleted file mode 100644
index d0d248fd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M464,144v288H48V144H464 M480,128H32v320h448V128L480,128z"/>
- <rect x="72" y="96" width="368" height="16"/>
- <rect x="104" y="64" width="304" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums.svg
deleted file mode 100644
index 5b2b384a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-albums.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M480,128H32v320h448V128L480,128z"/>
- <rect x="72" y="96" width="368" height="16"/>
- <rect x="104" y="64" width="304" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball-outline.svg
deleted file mode 100644
index 0f98a8bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M378.605,133.395C305.902,60.691,189.38,47.998,116.85,48c-38.926,0.001-65.191,3.658-65.191,3.658
- s-29.984,215.227,81.736,326.947C206.099,451.309,322.617,464,395.149,464c38.926,0,65.192-3.658,65.192-3.658
- S490.326,245.116,378.605,133.395z M65.142,65.208C76.137,64.194,94.374,63,116.856,63H117l-0.068-0.071
- c27.167,0,53.167,1.754,77.792,5.22l-126.6,126.581c-1.025-7.283-1.91-14.697-2.64-22.246
- C60.898,125.049,63.398,84.256,65.142,65.208z M143.9,368.102c-23.85-23.852-42.793-54.938-56.304-92.396
- c-6.973-19.332-12.51-40.373-16.57-62.866L212.838,71.05c10.672,1.929,21.064,4.191,31.141,6.804
- c52.027,13.492,93.783,35.708,124.139,66.064c23.851,23.85,42.786,54.928,56.297,92.386c6.974,19.333,12.509,40.375,16.567,62.871
- L299.17,440.986c-10.66-1.93-21.041-4.191-31.104-6.801C216.036,420.696,174.26,398.459,143.9,368.102z M446.861,446.868
- c-10.994,1.012-29.23,2.275-51.71,2.275c-27.192,0-53.225-1.77-77.876-5.25l126.607-126.607c1.024,7.279,1.908,14.688,2.638,22.233
- C451.108,386.956,448.606,427.817,446.861,446.868z"/>
- <polygon points="307.304,317.847 329.929,340.479 301.275,369.131 312.59,380.445 380.471,312.564 369.157,301.25 340.436,329.971
- 317.811,307.34 346.527,278.623 335.214,267.31 306.499,296.024 283.866,273.386 312.568,244.684 301.255,233.37 272.555,262.07
- 249.929,239.439 278.626,210.742 267.312,199.429 238.618,228.124 215.987,205.487 244.674,176.8 233.361,165.487 204.676,194.172
- 182.052,171.542 210.734,142.86 199.421,131.547 131.538,199.429 142.852,210.743 171.545,182.049 194.169,204.679 165.478,233.37
- 176.791,244.683 205.48,215.994 228.11,238.631 199.432,267.31 210.745,278.623 239.422,249.946 262.048,272.577 233.374,301.251
- 244.688,312.564 273.359,283.893 295.992,306.531 267.332,335.191 278.646,346.505 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball.svg
deleted file mode 100644
index 635968b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-americanfootball.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M378.605,133.395C305.902,60.691,189.381,47.998,116.85,48c-38.926,0.001-65.191,3.658-65.191,3.658
- s-29.984,215.227,81.736,326.947C206.099,451.309,322.617,464,395.148,464c38.927,0,65.193-3.658,65.193-3.658
- S490.327,245.116,378.605,133.395z M68.124,194.728L194.707,68.146c6.123,0.861,12.164,1.825,18.112,2.899L71.025,212.838
- C69.955,206.901,68.987,200.862,68.124,194.728z M267.312,335.195l28.688-28.688l-22.627-22.628l-28.688,28.688l-11.313-11.312
- l28.688-28.688l-22.627-22.627l-28.688,28.688l-11.313-11.312l28.688-28.688l-22.628-22.628l-28.688,28.688l-11.313-11.312
- l28.689-28.689l-22.628-22.627l-28.688,28.688l-11.314-11.313l67.884-67.883l11.313,11.314l-28.688,28.688l22.628,22.627
- l28.688-28.688l11.313,11.313l-28.688,28.688l22.628,22.628l28.688-28.688l11.314,11.313l-28.688,28.688l22.627,22.627
- l28.688-28.688l11.313,11.312l-28.688,28.688l22.628,22.628l28.688-28.688l11.312,11.313l-28.688,28.688l22.627,22.627
- l28.688-28.688l11.314,11.312l-67.883,67.884l-11.313-11.313l28.688-28.688l-22.628-22.628l-28.688,28.688L267.312,335.195z
- M317.259,443.891c-6.121-0.863-12.159-1.83-18.104-2.906L440.979,299.16c1.071,5.938,2.038,11.977,2.901,18.111L317.259,443.891z
- "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics-outline.svg
deleted file mode 100644
index da7dca0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48c28.087,0,55.325,5.497,80.958,16.339c24.767,10.476,47.013,25.476,66.12,44.583s34.107,41.354,44.583,66.12
- C458.503,200.675,464,227.913,464,256s-5.497,55.325-16.339,80.958c-10.476,24.767-25.476,47.013-44.583,66.12
- s-41.354,34.107-66.12,44.583C311.325,458.503,284.087,464,256,464s-55.325-5.497-80.958-16.339
- c-24.767-10.476-47.013-25.476-66.12-44.583s-34.107-41.354-44.583-66.12C53.497,311.325,48,284.087,48,256
- s5.497-55.325,16.339-80.958c10.476-24.767,25.476-47.013,44.583-66.12s41.354-34.107,66.12-44.583
- C200.675,53.497,227.913,48,256,48 M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224
- S379.712,32,256,32L256,32z"/>
- <path d="M107.776,320c-25.252,0-41.168-18.448-41.902-19.317c-2.841-3.359-2.401-8.371,0.982-11.192
- c3.374-2.813,8.401-2.388,11.248,0.948c0.604,0.701,14.606,16.597,35.606,13.186c12.104-1.964,28.08-25.681,38.652-41.376
- c4.251-6.311,7.922-11.761,11.215-15.856c16.773-20.865,33.899-23.333,45.325-21.726c24.139,3.394,44.358,27.498,53.689,49.882
- c7.454,17.884,19.042,28.256,32.628,29.208c15.408,1.061,31.539-9.885,43.105-29.336c1.228-2.064,2.562-4.496,3.978-7.07
- c9.482-17.262,23.814-43.35,51.75-43.35c31.146,0,51.957,34.286,52.828,35.746c2.252,3.774,0.996,8.648-2.806,10.885
- c-3.8,2.237-8.708,0.988-10.96-2.786c-0.037-0.062-4.493-7.413-11.859-14.568c-6.286-6.107-16.108-13.387-27.203-13.387
- c-18.438,0-29.121,19.445-37.705,35.07c-1.48,2.696-2.88,5.243-4.245,7.538c-14.718,24.751-36.4,38.635-58.01,37.108
- c-19.951-1.398-36.389-15.242-46.284-38.98c-10.013-24.02-28.279-38.417-41.149-40.228c-10.6-1.494-20.895,3.861-30.578,15.906
- c-2.872,3.573-6.539,9.017-10.421,14.779c-13.549,20.114-30.411,45.146-49.37,48.223C113.349,319.784,110.507,320,107.776,320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics.svg
deleted file mode 100644
index 578484b5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-analytics.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,32C141.174,32,46.544,118.404,33.54,229.739C32.534,238.354,32,247.114,32,256c0,1.783,0.026,3.561,0.067,5.333
- C34.901,382.581,134.071,480,256,480c105.255,0,193.537-72.602,217.542-170.454c1.337-5.451,2.474-10.979,3.404-16.579
- C478.943,280.939,480,268.594,480,256C480,132.288,379.712,32,256,32z M462.585,280.352c-7.265-7.807-13.064-16.09-15.702-20.429
- c-0.871-1.47-21.682-35.994-52.828-35.994c-27.937,0-42.269,26.269-51.751,43.65c-1.415,2.593-2.75,5.041-3.978,7.118
- c-11.566,19.587-27.693,30.608-43.105,29.541c-13.586-0.959-25.174-11.403-32.628-29.41c-9.331-22.54-29.551-46.812-53.689-50.229
- c-11.428-1.619-28.553,0.866-45.325,21.876c-3.293,4.124-6.964,9.612-11.215,15.967c-10.572,15.804-26.549,39.686-38.653,41.663
- c-21.02,3.438-35.021-12.596-35.583-13.249l-0.487-0.58l-0.587-0.479c-0.208-0.17-15.041-12.417-29.047-33.334
- c0-0.155-0.006-0.31-0.006-0.464c0-28.087,5.497-55.325,16.339-80.958c10.476-24.767,25.476-47.013,44.583-66.12
- s41.354-34.107,66.12-44.583C200.675,53.497,227.913,48,256,48s55.325,5.497,80.958,16.339
- c24.767,10.476,47.013,25.476,66.12,44.583s34.107,41.354,44.583,66.12C458.503,200.675,464,227.913,464,256
- C464,264.197,463.518,272.318,462.585,280.352z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-back.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-back.svg
deleted file mode 100644
index ab05ca65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-back.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="352,128.4 319.7,96 160,256 160,256 160,256 319.7,416 352,383.6 224.7,256 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-down.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-down.svg
deleted file mode 100644
index f956e925..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-down.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="396.6,160 416,180.7 256,352 96,180.7 115.3,160 256,310.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-forward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-forward.svg
deleted file mode 100644
index 68fd7eb5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-forward.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="160,128.4 192.3,96 352,256 352,256 352,256 192.3,416 160,383.6 287.3,256 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-left.svg
deleted file mode 100644
index 840ed365..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-left.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="352,115.4 331.3,96 160,256 331.3,416 352,396.7 201.5,256 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-right.svg
deleted file mode 100644
index 489f14c9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-right.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="160,115.4 180.7,96 352,256 180.7,416 160,396.7 310.5,256 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-down.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-down.svg
deleted file mode 100644
index bd1634e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-down.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M349.7,322.2c-3.1-3.1-8-3-11.3,0L264,388.6V104c0-4.4-3.6-8-8-8c-4.4,0-8,3.6-8,8v284.6l-74.4-66.3
- c-3.4-2.9-8.1-3.2-11.2-0.1c-3.1,3.1-3.3,8.5-0.1,11.4c0,0,87,79.2,88,80s2.8,2.4,5.7,2.4s4.9-1.6,5.7-2.4s88-80,88-80
- c1.5-1.5,2.3-3.6,2.3-5.7C352,325.8,351.2,323.8,349.7,322.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-left.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-left.svg
deleted file mode 100644
index d1223cd6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-left.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M189.8,349.7c3.1-3.1,3-8,0-11.3L123.4,264H408c4.4,0,8-3.6,8-8c0-4.4-3.6-8-8-8H123.4l66.3-74.4c2.9-3.4,3.2-8.1,0.1-11.2
- c-3.1-3.1-8.5-3.3-11.4-0.1c0,0-79.2,87-80,88S96,253.1,96,256s1.6,4.9,2.4,5.7s80,88,80,88c1.5,1.5,3.6,2.3,5.7,2.3
- C186.2,352,188.2,351.2,189.8,349.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-right.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-right.svg
deleted file mode 100644
index ae5e0497..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-right.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M322.2,349.7c-3.1-3.1-3-8,0-11.3l66.4-74.4H104c-4.4,0-8-3.6-8-8c0-4.4,3.6-8,8-8h284.6l-66.3-74.4
- c-2.9-3.4-3.2-8.1-0.1-11.2c3.1-3.1,8.5-3.3,11.4-0.1c0,0,79.2,87,80,88s2.4,2.8,2.4,5.7s-1.6,4.9-2.4,5.7s-80,88-80,88
- c-1.5,1.5-3.6,2.3-5.7,2.3C325.8,352,323.8,351.2,322.2,349.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-up.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-up.svg
deleted file mode 100644
index 38ed41e4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-thin-up.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M349.7,189.8c-3.1,3.1-8,3-11.3,0L264,123.4V408c0,4.4-3.6,8-8,8c-4.4,0-8-3.6-8-8V123.4l-74.4,66.3
- c-3.4,2.9-8.1,3.2-11.2,0.1c-3.1-3.1-3.3-8.5-0.1-11.4c0,0,87-79.2,88-80s2.8-2.4,5.7-2.4s4.9,1.6,5.7,2.4s88,80,88,80
- c1.5,1.5,2.3,3.6,2.3,5.7C352,186.2,351.2,188.2,349.7,189.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-up.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-up.svg
deleted file mode 100644
index 9d53f771..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-arrow-up.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="396.6,352 416,331.3 256,160 96,331.3 115.3,352 256,201.5 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at-outline.svg
deleted file mode 100644
index 9d3b02f1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at-outline.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M364.4,320.9c-5.3,7.5-11.6,14.7-18.8,21.4c-7.1,6.6-15.1,12.5-23.7,17.4c-8.6,4.9-17.9,8.8-27.5,11.5s-19.8,4.1-30.3,4.1
- c-15.9,0-31.2-2.6-45.5-7.6c-14.2-5-26.8-12.5-37.5-22.4c-10.7-9.8-21.7-25.9-28.2-41c-5.8-13.4-8.1-27.8-8.1-49.5
- c0-15.6,3.6-33,9.8-47.6c6-14,14.3-26.4,24.9-36.9c10.4-10.3,23-18.6,37.6-24.8c13.1-5.5,28.5-8.2,47.1-8.2c14.9,0,29,2.4,41.9,7
- c12.8,4.6,23.9,11.2,33.1,19.6c8.7,7.9,14,17.4,19.7,30.2c5,11.2,6.8,20.9,6.8,35.9c0,12.4-2.2,24.1-6.5,34.9
- c-4.3,10.6-7.5,17-14,25c-6.6,7.9-10.6,12.7-18.1,17.1c-8.6,5-15.3,7.4-21,7.4c-3.6,0-6.3-0.7-7.8-2c-1.5-1.3-2.4-3-2.7-5.4
- c-0.4-2.8-0.1-6.3,1-10.4c1.1-4.4,2.8-8.6,4.9-13.7L339.4,181h-17.8l-6.2,16.5c-3.8-6.1-9.1-11.5-15.9-15.5
- c-10.5-6.1-19.5-8.8-31.2-8.8c-13.5,0-26,3.5-37.2,10.4c-11,6.8-20.5,15.6-28.2,26.3c-7.5,10.3-9.3,15.7-12.9,26.4l-0.6,1.7
- c-4.2,12.4-6.3,24.6-6.3,36.2c0,7.7,1.4,15,4.1,21.8c2.7,6.8,6.4,12.8,11.1,17.8c4.7,5.1,10.4,9.1,16.9,12.1s13.7,4.5,21.3,4.5
- c8.5,0,16.6-1.4,26.1-4.7c6.3-2.2,11.9-5.8,17.4-11.4c1,3.2,2.7,6,5.3,8.5c5,5,11.7,7.6,19.9,7.6c8.6,0,17.8-3,29-9.3
- c9.9-5.6,15.7-12,23.3-21.1c8.2-9.8,12.3-18,16.9-29.7c5-12.5,7.5-26,7.5-40.3c0-18-2.4-30.2-8.5-43.6c-6.6-14.3-13.2-25.8-24-35.4
- c-10.9-9.6-23.9-17.1-38.5-22.3c-14.5-5.1-30.3-7.7-46.7-7.7c-20.1,0-37.2,3-52.2,9.1c-16.5,6.7-30.9,16-43,27.6
- c-12.2,11.8-22,25.9-29,41.9c-7.3,16.6-11.4,36.7-11.4,55.1c0,25.1,3.1,42.6,10.3,58.4c8,17.3,21,35.4,33.3,46
- c12.6,10.9,27.1,19.1,43.2,24.2c15.9,5.1,32.3,7.7,48.8,7.7c11.4,0,22.8-1.6,34-4.6c11.2-3.1,22-7.4,32.1-13.1
- c10.1-5.6,19.5-12.5,28.2-20.6c8.6-8.1,18.6-20.8,22-26.9c1.3-2.4,2.2-4.3,2.9-5.8h-18.5L364.4,320.9z M275.8,294.4
- c-4.4,5.6-7.7,9.5-11.8,12.2c-4.4,3-7.9,4.9-12.4,5.9c-4.6,1.2-9.3,1.7-13.7,1.7c-5.6,0-10.8-1-15.4-3c-4.7-2-8.7-4.8-12.1-8.4
- c-3.4-3.6-6.1-7.9-8.1-12.7c-1.9-4.8-2.9-10.2-2.9-16c0-9.5,1.8-19.7,5.3-30.3c0.4-1.2,0.8-2.4,1.1-3.4c2.8-8.6,4.3-11.5,9.5-20
- c5.7-9.4,14.1-16.6,23-22.5c8.6-5.8,18.2-8.7,28.5-8.7c4.2,0,8.6,0.5,13.2,1.5c3.6,0.8,5.6,1.9,9,3.9c0.6,0.3,1.1,0.6,1.7,1
- c3.9,2.2,7.4,5.1,10.4,8.7c2.7,3.2,4.8,7.4,6.3,12.3l-20.6,57.8C283.6,282.5,279.9,289.2,275.8,294.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at.svg
deleted file mode 100644
index 917d984c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-at.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M356,320c-9.7,13.3-29.9,28.5-38.1,33.1s-16.9,8.3-26,10.8c-9,2.5-18.6,3.9-28.4,3.9c-14.9,0-29.4-2.4-43-7.2
- c-13.3-4.7-25.2-11.8-35.1-21c-9.9-9-20.3-24.2-26.5-38.5c-5.3-12.4-7.6-25.8-7.6-46.5c0-14.7,3.4-30.9,9.2-44.7
- c5.6-13.2,13.5-24.9,23.3-34.6c9.7-9.6,21.6-17.5,35.3-23.3c12.3-5.1,26.7-7.7,44.4-7.7c13.9,0,27.2,2.2,39.4,6.6
- c11.9,4.3,22.3,10.4,30.9,18.3c8,7.3,12.9,16.1,18.2,28.1c4.6,10.2,6.3,19.2,6.3,33.3c0,11.5-2,22.4-6,32.4c-4,9.8-7,15.8-13,23.3
- c-6.3,7.6-9.8,11.8-16.5,15.6c-7.8,4.6-13.7,6.7-18.5,6.7c-3.8,0-5-0.9-5.1-1c-0.6-0.5-1.1-1.2-1.4-2.8c-0.3-2.2,0-5.2,0.9-8.6
- c1-3.9,2.4-7.7,4.6-12.9L342.3,179h-25.6l-4.5,12c-3.5-4.1-7.7-7.5-12.4-10.2c-11.1-6.4-20.4-9-32.3-9c-13.8,0-26.7,3.6-38.2,10.7
- c-11.2,6.9-20.8,15.8-28.5,26.5c-7.6,10.5-9.5,16.1-13,26.5l-0.6,1.8c-4.2,12.4-6.3,24.7-6.3,36.4c0,7.9,1.5,15.5,4.3,22.6
- c2.8,7.2,6.7,13.4,11.6,18.5c4.8,5.2,10.7,9.4,17.7,12.6c6.8,3.1,14.3,4.8,22.4,4.8c8.9,0,17.1-1.5,26.7-4.8
- c5.3-1.8,9.9-4.5,14.4-8.3c1,1.7,2.2,3.1,3.7,4.5c5.6,5.6,13.1,8.5,22.1,8.5c8.9,0,18.6-3,30.2-9.5c10.3-5.8,16.3-12.5,23.7-21.4
- c8.4-10,12.5-18.6,17-29.9c5.1-12.5,7.6-26.2,7.6-40.6c0-18.1-2.4-30.4-8.7-44c-6.6-14.4-13.3-25.9-24.3-35.6
- c-10.9-9.7-23.9-17.2-38.7-22.4c-14.6-5.1-30.3-7.7-46.7-7.7c-20,0-37.2,3-52.2,9.1c-16.3,6.6-30.8,15.9-43.1,27.6
- c-12.3,11.8-22.1,26-29.1,42c-7.3,16.5-11.4,36.5-11.4,55.1c0,25,3.1,42.4,10.4,58.4c8.1,17.5,21.2,35.5,33.4,45.9
- c12.7,11.1,27.3,19.2,43.4,24.3c15.9,5.1,32.3,7.7,48.6,7.7c11.2,0,22.7-1.6,34.1-4.6c11.6-3.2,22.4-7.6,32.1-13.1
- c9.9-5.5,19.5-12.4,28.2-20.6c8.8-8.2,19.4-20.9,22.9-27.1c1.2-2.3,2.2-4.2,2.8-5.6H356z M271.9,290.6c-4.4,5.5-7.2,8.9-10.6,11.2
- c-3.8,2.6-6.8,4.2-10.7,5.2h-0.1c-3.9,1-8.1,1.5-12.4,1.5c-5,0-9.4-0.9-13.4-2.7c-4.1-1.7-7.5-4.1-10.5-7.3
- c-2.9-3.1-5.4-6.8-7.1-11.1c-1.7-4.3-2.5-9-2.5-14.1c0-8.7,1.7-18.3,5-28.2c0.4-1.2,0.8-2.4,1.1-3.3c2.6-8.1,4-10.6,8.9-18.6
- c4.5-7.4,11.5-14.2,21.2-20.7c7.7-5.1,16.2-7.8,25.6-7.8c3.8,0,7.8,0.5,12,1.4c3,0.7,4.6,1.6,7.6,3.3l0.2,0.1
- c0.4,0.2,0.8,0.4,1.3,0.7l0.3,0.2c3.4,1.9,6.4,4.5,9,7.6c2,2.4,3.7,5.5,5,9.4L282,272.2C279,279.6,275.6,285.8,271.9,290.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode-outline.svg
deleted file mode 100644
index fcdfd3f5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="48,384 128,384 128,368 64,368 64,144 128,144 128,128 48,128 "/>
- <polygon points="384,128 384,144 448,144 448,368 384,368 384,384 464,384 464,128 "/>
- <rect x="112" y="192" width="16" height="128"/>
- <rect x="384" y="192" width="16" height="128"/>
- <rect x="320" y="160" width="16" height="192"/>
- <rect x="176" y="160" width="16" height="192"/>
- <rect x="247" y="176" width="16" height="160"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode.svg
deleted file mode 100644
index 16d59dff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-barcode.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M48,128v256h416V128H48z M128,320h-16V192h16V320z M192,352h-16V160h16V352z M263,336h-16V176h16V336z M336,352h-16V160h16
- V352z M400,320h-16V192h16V320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball-outline.svg
deleted file mode 100644
index a992fea7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball-outline.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M462.686,279.369c0.132-1.182,0.257-2.365,0.369-3.554c0.004-0.038,0.007-0.078,0.011-0.117
- C463.675,269.213,464,262.645,464,256c0-114.863-93.13-208-208-208c-7.951,0-15.792,0.462-23.512,1.331
- c-0.089,0.01-0.18,0.018-0.27,0.028c0,0.001,0,0.002,0,0.003C135.207,60.409,58.442,138.199,48.989,235.687
- c-0.001,0-0.003,0-0.004,0c-0.072,0.748-0.131,1.497-0.195,2.246c-0.136,1.576-0.253,3.157-0.353,4.743
- c-0.026,0.418-0.056,0.835-0.08,1.254c-0.064,1.121-0.116,2.245-0.163,3.371c-0.011,0.281-0.021,0.562-0.032,0.843
- C48.065,250.751,48,253.368,48,256c0,114.863,93.137,208,208,208c2.627,0,5.239-0.065,7.843-0.162
- c0.293-0.011,0.586-0.021,0.878-0.033c1.11-0.046,2.219-0.098,3.324-0.16c0.454-0.025,0.906-0.058,1.359-0.086
- c1.604-0.103,3.201-0.222,4.795-0.36c0.704-0.061,1.41-0.115,2.113-0.184c0-0.001,0-0.003,0-0.004
- c97.494-9.452,175.279-86.216,186.326-183.229c0.001,0,0.002,0,0.004,0C462.658,279.645,462.67,279.507,462.686,279.369z
- M446.665,256c0,2.568-0.066,5.122-0.167,7.666c-10.334-0.468-20.552-1.69-30.614-3.664l6.11-19.056l-15.232-4.884l-6.488,20.235
- c-7.591-2.112-15.08-4.651-22.442-7.638c-4.976-2.018-9.851-4.223-14.625-6.604l11.518-17.003l-13.247-8.974l-12.359,18.246
- c-12.241-7.35-23.703-15.977-34.305-25.812l14.73-14.73l-11.313-11.313l-14.73,14.73c-9.555-10.297-17.964-21.408-25.175-33.254
- l18.487-12.522l-8.972-13.246l-17.324,11.735c-2.597-5.131-4.998-10.375-7.174-15.74c-2.843-7.009-5.276-14.134-7.327-21.352
- l20.812-6.673l-4.885-15.234l-19.711,6.32c-2.104-10.423-3.41-21.014-3.896-31.729c2.544-0.101,5.097-0.167,7.665-0.167
- C361.132,65.335,446.665,150.869,446.665,256z M65.337,256c0-1.317,0.023-2.629,0.05-3.939c9.064,0.559,18.039,1.687,26.891,3.409
- l-7.115,22.191l15.235,4.885l7.5-23.391c7.692,2.128,15.28,4.696,22.738,7.721c5.175,2.099,10.239,4.404,15.197,6.896l-13.405,19.79
- l13.246,8.973l14.219-20.992c12.038,7.279,23.32,15.793,33.765,25.483l-16.853,16.853l11.313,11.314l16.854-16.854
- c9.968,10.744,18.7,22.369,26.114,34.796l-20.753,14.058l8.972,13.246l19.473-13.19c2.283,4.611,4.4,9.317,6.347,14.116
- c3.161,7.795,5.834,15.729,8.016,23.778l-22.832,7.32l4.884,15.233l21.531-6.903c1.608,8.506,2.679,17.122,3.215,25.822
- c-1.311,0.026-2.622,0.05-3.939,0.05C150.87,446.664,65.336,361.13,65.337,256z M275.893,445.629
- c-0.621-9.974-1.911-19.911-3.859-29.746l24.1-7.727l-4.884-15.232l-22.896,7.341c-3.946-14.415-9.356-28.51-16.234-42.054
- l20.172-13.664l-8.973-13.246l-18.988,12.862c-7.888-13.094-17.233-25.552-28.04-37.145l17.081-17.081l-11.313-11.313
- l-17.082,17.081c-11.288-10.521-23.393-19.66-36.108-27.414l12.696-18.743l-13.246-8.972l-13.446,19.85
- c-13.548-6.974-27.659-12.467-42.094-16.494l7.158-22.325l-15.235-4.885l-7.52,23.452c-10.181-2.068-20.477-3.424-30.81-4.067
- c9.168-88.037,78.492-158.454,166.023-169.311c0.574,11.858,2.095,23.676,4.543,35.339l-25.935,8.316l4.885,15.234l24.903-7.985
- c4.045,14.144,9.504,27.967,16.386,41.246l-22.322,15.121l8.973,13.246l21.236-14.385c7.688,12.528,16.735,24.455,27.116,35.59
- l-19.204,19.204l11.313,11.314l19.204-19.205c11.447,10.669,23.735,19.921,36.647,27.745l-14.555,21.486l13.248,8.974l15.328-22.628
- c13.28,6.789,27.1,12.155,41.229,16.118l-8.168,25.477l15.232,4.884l8.525-26.59c11.301,2.312,22.744,3.754,34.224,4.31
- C434.347,367.137,363.93,436.46,275.893,445.629z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball.svg
deleted file mode 100644
index 49a50bb2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-baseball.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48c-8.044,0-15.975,0.473-23.782,1.361l0,0l0,0C128.555,61.166,48,149.18,48,256c0,114.863,93.137,208,208,208
- c106.827,0,194.833-80.553,206.638-184.218l0,0l0,0C463.527,271.977,464,264.045,464,256C464,141.137,370.87,48,256,48z
- M259.939,446.614c-0.539-8.693-1.605-17.305-3.209-25.804l-21.511,6.896l-4.885-15.234l22.812-7.314
- c-2.183-8.056-4.856-15.994-8.02-23.794c-1.943-4.794-4.061-9.497-6.341-14.105l-19.464,13.186l-8.972-13.247l20.744-14.054
- c-7.416-12.429-16.149-24.057-26.119-34.803l-16.852,16.853l-11.313-11.313l16.852-16.852c-10.442-9.689-21.721-18.202-33.757-25.48
- l-14.216,20.988l-13.247-8.973l13.403-19.788c-4.96-2.491-10.027-4.799-15.206-6.9c-7.455-3.021-15.038-5.59-22.725-7.717
- l-7.5,23.392l-15.236-4.885l7.115-22.192c-8.856-1.723-17.835-2.853-26.904-3.412c0.109-5.373,0.438-10.695,0.984-15.953
- c10.339,0.647,20.639,1.998,30.827,4.068l7.518-23.454l15.237,4.886l-7.159,22.328c14.433,4.027,28.542,9.521,42.09,16.494
- l13.449-19.854l13.248,8.973l-12.7,18.748c12.712,7.754,24.815,16.892,36.1,27.411l17.082-17.082l11.314,11.314l-17.083,17.082
- c10.809,11.595,20.156,24.055,28.044,37.151l18.999-12.869l8.973,13.248l-20.183,13.67c6.878,13.546,12.289,27.642,16.232,42.058
- l22.919-7.349l4.885,15.236l-24.122,7.734c1.947,9.828,3.231,19.761,3.854,29.727C270.637,446.177,265.314,446.504,259.939,446.614z
- M410.961,275.293l-8.529,26.604l-15.236-4.885l8.174-25.493c-14.124-3.964-27.94-9.329-41.218-16.116l-15.335,22.641l-13.248-8.973
- l14.564-21.499c-12.912-7.826-25.199-17.077-36.644-27.746l-19.205,19.204l-11.312-11.314l19.202-19.203
- c-10.381-11.135-19.427-23.062-27.114-35.59l-21.248,14.393l-8.974-13.248l22.335-15.127c-6.881-13.278-12.339-27.099-16.384-41.241
- l-24.918,7.99l-4.885-15.237l25.951-8.321c-2.447-11.663-3.943-23.482-4.522-35.337c5.189-0.644,10.446-1.068,15.754-1.284
- c0.507,10.743,1.859,21.334,3.972,31.807l19.744-6.359l4.907,15.212l-20.789,6.658c2.051,7.218,4.491,14.338,7.333,21.348
- c2.176,5.363,4.578,10.603,7.174,15.731l17.315-11.729l8.973,13.246l-18.477,12.516c7.209,11.846,15.619,22.957,25.174,33.254
- l14.729-14.731l11.314,11.313l-14.732,14.731c10.602,9.836,22.062,18.463,34.302,25.813l12.352-18.235l13.248,8.973l-11.512,16.994
- c4.777,2.383,9.656,4.589,14.635,6.608c7.354,2.982,14.837,5.521,22.421,7.631l6.484-20.22l15.233,4.885l-6.104,19.043
- c10.116,1.984,20.286,3.311,30.626,3.824c-0.215,5.312-0.643,10.572-1.285,15.768C433.72,279.028,422.269,277.607,410.961,275.293z"
- />
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball-outline.svg
deleted file mode 100644
index 9c171547..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball-outline.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C141.137,48,48,141.136,48,256s93.137,208,208,208c114.871,0,208-93.138,208-208S370.871,48,256,48z M446.664,256
- c0,0.048-0.002,0.097-0.002,0.145c-22.315-1.721-43.989-6.972-64.62-15.699c-17.888-7.566-34.453-17.505-49.479-29.634
- c20.69-29.501,38.442-61.212,52.824-94.715C423.045,150.95,446.664,200.766,446.664,256z M372.606,105.261
- c-0.28,0.676-0.55,1.354-0.835,2.028c-13.908,32.883-31.062,63.956-51.286,92.987c-1.538-1.449-3.063-2.914-4.563-4.413
- c-19.107-19.107-34.107-41.354-44.583-66.12c-8.697-20.563-13.933-42.163-15.671-64.401c0.111,0,0.221-0.004,0.332-0.004
- C299.884,65.337,340.347,80.249,372.606,105.261z M239.675,66.044c4.431,58.126,31.044,110.041,71.391,147.312
- c-9.495,12.749-19.609,25.076-30.319,36.965c-47.554-50.032-104.815-90.746-168.767-119.132
- C143.616,94.733,188.833,70.375,239.675,66.044z M280.687,273.84c36.229,40.67,65.48,86.438,87.185,136.453
- c-25.4,18.467-55.51,30.829-88.162,34.898c-2.272-47.816-19.521-91.707-47.179-127.071
- C249.483,304.357,265.568,289.567,280.687,273.84z M262.039,270.039c-12.704,12.703-25.977,24.662-39.778,35.87
- c-38.737-42.885-93.831-70.706-155.45-73.635c4.07-32.646,16.432-62.75,34.896-88.146c59.195,25.688,112.445,61.947,158.332,107.833
- c3.323,3.323,6.59,6.689,9.812,10.089C267.277,264.736,264.677,267.401,262.039,270.039z M65.508,248.23
- c25.238,1.145,49.436,6.797,71.45,16.109c24.767,10.476,47.013,25.476,66.12,44.583c2.254,2.254,4.445,4.555,6.584,6.895
- c-31.414,23.915-65.427,44.049-101.708,60.182C81.322,343.205,65.336,301.437,65.336,256
- C65.336,253.396,65.404,250.809,65.508,248.23z M119.067,388.526c35.988-16.434,69.81-36.787,100.914-60.521
- c11.249,14.372,20.522,30.115,27.68,47.037c9.614,22.729,15.013,46.724,16.114,71.45c-2.58,0.104-5.17,0.172-7.775,0.172
- C202.317,446.664,153.751,424.353,119.067,388.526z M380.81,400.021c-22.489-50.671-52.72-97.14-89.191-137.909
- c11.101-12.269,21.634-25.061,31.556-38.336c34.171,27.342,76.521,44.885,122.801,48.363
- C441.686,323.058,417.311,368.347,380.81,400.021z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball.svg
deleted file mode 100644
index 9d749565..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-basketball.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C141.137,48,48,141.136,48,256s93.137,208,208,208c114.871,0,208-93.138,208-208S370.871,48,256,48z
- M380.797,400.032c-4.158,3.608-8.48,7.029-12.942,10.272c-21.704-50.015-50.938-95.795-87.168-136.465
- c-15.118,15.728-31.203,30.518-48.156,44.28c27.659,35.364,44.916,79.254,47.189,127.069c-5.252,0.655-10.571,1.086-15.944,1.303
- c-1.103-24.727-6.5-48.721-16.114-71.45c-7.158-16.922-16.431-32.665-27.68-47.037c-31.104,23.733-64.923,44.093-100.91,60.526
- c-3.883-4.011-7.592-8.191-11.115-12.529c36.28-16.134,70.291-36.271,101.705-60.186c-2.139-2.34-4.33-4.641-6.584-6.895
- c-19.107-19.107-41.354-34.107-66.12-44.583c-22.015-9.312-46.212-14.964-71.45-16.108c0.217-5.379,0.648-10.703,1.303-15.959
- c61.62,2.929,116.713,30.753,155.45,73.638c13.802-11.208,27.075-23.167,39.778-35.87c2.638-2.638,5.238-5.303,7.812-7.988
- c-3.223-3.4-6.489-6.767-9.812-10.09c-45.887-45.886-99.137-82.145-158.332-107.832c3.243-4.461,6.665-8.782,10.272-12.939
- c63.951,28.387,121.212,69.101,168.767,119.132c10.711-11.889,20.824-24.216,30.319-36.965
- c-40.347-37.271-66.956-89.188-71.388-147.312c5.273-0.449,10.604-0.692,15.99-0.702c1.738,22.238,6.974,43.838,15.671,64.401
- c10.476,24.767,25.476,47.013,44.583,66.12c1.5,1.5,3.025,2.965,4.562,4.413c20.226-29.031,37.379-60.104,51.287-92.987
- c0.285-0.674,0.555-1.353,0.835-2.028c4.419,3.426,8.681,7.042,12.779,10.835c-14.383,33.502-32.132,65.215-52.822,94.716
- c15.026,12.13,31.591,22.068,49.479,29.635c20.631,8.727,42.305,13.978,64.62,15.698c-0.004,5.387-0.243,10.717-0.688,15.991
- c-46.278-3.479-88.631-21.018-122.801-48.359c-9.922,13.275-20.455,26.067-31.556,38.336
- C328.091,302.883,358.307,349.36,380.797,400.032z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell-outline.svg
deleted file mode 100644
index bf8fae90..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M381.7,225.9c0-97.6-52.5-130.8-101.6-138.2c0-0.5,0.1-1,0.1-1.6c0-12.3-10.9-22.1-24.2-22.1c-13.3,0-23.8,9.8-23.8,22.1
- c0,0.6,0,1.1,0.1,1.6c-49.2,7.5-102,40.8-102,138.4c0,113.8-28.3,126-66.3,158h384C410.2,352,381.7,339.7,381.7,225.9z M107.2,368
- c8.6-9,16.4-18.4,22.7-31.8c12-25.3,17.4-59.2,17.4-110.2c0-46.4,12.5-80.4,37.1-101.2c22.9-19.3,51.7-23.3,71.8-23.3
- c20.1,0,48.9,4,71.6,23.3c24.5,20.7,37,54.5,37,100.9c0,83.8,14.9,117.3,40.3,142.3H107.2z"/>
- <path d="M256.2,448c26.8,0,48.8-19.9,51.7-43H204.5C207.3,428.1,229.4,448,256.2,448z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell.svg
deleted file mode 100644
index f9e21a5a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bell.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M381.7,225.9c0-97.6-52.5-130.8-101.6-138.2c0-0.5,0.1-1,0.1-1.6c0-12.3-10.9-22.1-24.2-22.1c-13.3,0-23.8,9.8-23.8,22.1
- c0,0.6,0,1.1,0.1,1.6c-49.2,7.5-102,40.8-102,138.4c0,113.8-28.3,126-66.3,158h384C410.2,352,381.7,339.7,381.7,225.9z"/>
- <path d="M256.2,448c26.8,0,48.8-19.9,51.7-43H204.5C207.3,428.1,229.4,448,256.2,448z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body-outline.svg
deleted file mode 100644
index 809da99c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body-outline.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,47.959c17.645,0,32,14.351,32,31.991c0,17.64-14.355,31.99-32,31.99s-32-14.351-32-31.99
- C224,62.31,238.355,47.959,256,47.959 M256,31.964c-26.51,0-48,21.483-48,47.986c0,26.502,21.49,47.985,48,47.985
- s48-21.483,48-47.985C304,53.447,282.51,31.964,256,31.964L256,31.964z"/>
- <path d="M424,144H88c-13.255,0-24,10.747-24,24s10.745,24,24,24h100.451c5.549,0,13.197,4.295,17.216,14.708
- c4.651,12.055,2.37,33.33-0.539,51.444l-3.923,21.26c-0.019,0.104-0.205,0.1-0.205,0.203l-32.229,172.238
- c-2.303,13.051,6.487,25.494,19.54,27.797c1.408,0.248,2.844,0.367,4.218,0.367c11.357,0,20.917-8.19,22.97-19.836L236,340.242
- v0.166c0,0,7.25-31.408,19.452-31.408h1.096C269,309,274,340.408,274,340.408v-0.082l21.483,119.895
- c2.052,11.642,12.331,19.815,23.763,19.815c1.387,0,2.855-0.121,4.268-0.368c13.053-2.303,21.821-14.76,19.519-27.811
- l-32.349-172.251c-0.002-0.008,0.011-0.02,0.009-0.027c-0.019-0.104-0.032-0.217-0.052-0.322l-3.771-21.411
- c-2.909-18.119-5.188-39.083-0.538-51.137C310.351,196.295,318.5,192,323.549,192H424c13.255,0,24-10.747,24-24
- S437.255,144,424,144z M88,176.113c-4.411,0-8-3.646-8-8.057c0-4.411,3.589-8.057,8-8.057h336c4.411,0,8,3.59,8,8s-3.589,8-8,8
- H322.5c-15.538,0-27.438,14.738-30.982,23.922c-4.846,12.557-5.004,31.942-0.388,60.688l-0.009,0.104l0.006,0.11l3.367,19.138
- l0.562,3.241l32.252,171.628c0.5,2.834-0.62,4.961-1.332,5.977c-0.713,1.017-2.335,2.799-5.179,3.301
- c-0.476,0.083-0.955,0.126-1.427,0.126c-3.893,0-7.207-2.639-7.883-6.472L290.255,338h-0.015c-0.271-2-1.828-10.05-5.022-18.771
- c-2.278-6.217-4.844-11.034-7.844-15.005C270.283,294.836,262.135,293,256.548,293h-1.096c-5.47,0-13.503,1.731-20.71,10.938
- c-3.05,3.896-5.729,8.671-8.19,14.802c-3.628,9.037-5.505,17.654-5.708,18.613l-0.11,0.369l-20.728,119.9
- c-0.693,3.886-3.75,6.596-7.441,6.596c-0.459,0-0.932-0.043-1.403-0.127c-2.84-0.5-4.455-2.275-5.165-3.288
- c-0.709-1.013-1.824-3.136-1.323-5.975l32.257-171.562l0.004-0.019l0.174-0.927l3.775-21.33l0.022-0.125l0.021-0.126
- c4.629-28.829,4.527-48.3-0.332-60.891c-3.543-9.181-13.576-23.737-31.76-23.737"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body.svg
deleted file mode 100644
index c47f4c67..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-body.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="256" cy="79.838" r="48"/>
- <path d="M424,144H88c-13.255,0-24,10.745-24,24s10.745,24,24,24h98.451c5.579,1,13.197,3.837,17.216,14.252
- c4.651,12.056,2.37,33.606-0.539,51.727l-3.775,21.395c-0.019,0.104-0.039,0.207-0.058,0.311c-0.002,0.008-0.002,0.012-0.004,0.02
- l-30.375,172.268c-2.303,13.053,6.414,25.5,19.467,27.803c13.055,2.301,25.333-6.416,27.634-19.471L237,340.348v0.167
- c0,0,6.25-32.515,18.452-32.515h1.096C269,308,275,340.515,275,340.515v-0.083l20.983,119.913
- c2.301,13.055,14.663,21.749,27.718,19.448c13.053-2.303,21.728-14.762,19.425-27.814L312.73,279.703
- c-0.002-0.008-0.013-0.02-0.015-0.027c-0.019-0.104-0.044-0.217-0.063-0.322l-3.777-21.414
- c-2.909-18.121-5.191-39.631-0.541-51.688C312.354,195.838,319.97,193,325.549,192H424c13.255,0,24-10.745,24-24
- S437.255,144,424,144z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt-outline.svg
deleted file mode 100644
index 52bd7b43..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M273.9,132l-16.5,89.1L254,240h19.2h64.8l-99.8,140l16.5-89.1L258,272h-19.2h-64.7L273.9,132 M302.7,64L143,288h95.8
- l-29.5,160L369,224h-95.8L302.7,64L302.7,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt.svg
deleted file mode 100644
index 51a27ee9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bolt.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M302.7,64L143,288h95.8l-29.5,160L369,224h-95.8L302.7,64L302.7,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book-outline.svg
deleted file mode 100644
index d2857099..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M347.621,64c-40.941,0-79.121,14-91.578,44.495C242.5,78,205.408,64,164.466,64C109.265,64,64,89.98,64,143v1v8.995V417v9
- h6.215h10.958h4.967c12.86-26.334,44.238-42,78.325-42c40.224,0,73.877,27.528,81.617,64h19.714c7.739-36.472,41.495-64,81.722-64
- c34.085,0,61.149,11.666,78.429,42h4.967h10.959H448v-17V148v-4v-1C448,89.98,402.823,64,347.621,64z M248,410.926
- C230,385.055,199.27,368,164.5,368c-34.769,0-64.5,10.055-83.5,35.926l-1,0.537V142l0,0v-1c3-41.825,40.089-61,84.293-61
- c45.162,0,82.145,18.708,83.363,61.808c-0.017,0.729,0.016,1.459,0.016,2.192L248,157.103V410.926z M432,148v255.926
- C414,378.055,382.269,368,347.5,368c-34.77,0-65.5,17.055-83.5,42.926V145v-1c0-44.112,37.659-64,83.587-64
- C391.79,80,429,91.175,432,133v1V148z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book.svg
deleted file mode 100644
index b8c6da3f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-book.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M164.466,64C109.266,64,64,89.98,64,143v1v8.994V417v9h6.215h10.959h4.967c12.86-26.334,44.238-42,78.325-42
- c40.224,0,73.877,27.528,81.616,64H248V95.346C230.76,73.951,198.981,64,164.466,64z"/>
- <path d="M347.621,64c-34.332,0-66.713,9.851-83.621,31.011V448h1.797c7.739-36.472,41.495-64,81.722-64
- c34.085,0,61.149,11.666,78.429,42h4.967h10.959H448v-17V148v-4v-1C448,89.98,402.823,64,347.621,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks-outline.svg
deleted file mode 100644
index ee4fba02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M432,64H281.6c-10.3,0-19.3,4.6-25.6,11.7l0,0l0,0c-6.2-7.2-15.3-11.7-25.6-11.7H80c-18.8,0-33,13.3-33,32v286.1
- c0,18.8,14.2,33.9,33,33.9c0,0,129.5,0,143.3,0c13.8,0,24.7,4.2,24.7,19.4c0,9.1,0,12.6,0,12.6h8h8c0,0,0-3.4,0-12.6
- c0-15.3,10.9-19.4,24.7-19.4s143.3,0,143.3,0c18.8,0,33-15.1,33-33.9V96C465,77.3,450.8,64,432,64z M248,411.1
- c-4.7-7.8-13.5-11.1-23.8-11.1H80c-9.4,0-16-8.5-16-17.9V96c0-9.4,6.6-16,16-16c0,0,130.6,0,143.3,0c12.8,0,24.7,12.8,24.7,22.2
- V411.1z M320,80c18.8,0,43,0,64,0v100.4l-22.9-14.5l-9.1-6.4l-9.1,6.4L320,180.4V80z M448,382.1c0,9.4-6.6,17.9-16,17.9H287.8
- c-10.3,0-19.1,2.3-23.8,11.1V102.2c0-9.4,11.9-22.2,24.7-22.2c2.2,0,7.7,0,15.3,0v131l48-32l48,32V80c18.6,0,32,0,32,0
- c9.4,0,16,6.7,16,16V382.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks.svg
deleted file mode 100644
index bb680400..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-bookmarks.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M342.9,165.4l9.1-6.4l9.1,6.4l22.9,14.5V64c-20.7,0-44.5,0-64,0v115.9L342.9,165.4z"/>
- <path d="M432,64c0,0-13.3,0-32,0v146.5l-48-32l-48,32V64c-12.1,0-20.6,0-22.4,0c-8.1,0-17.6,7.2-17.6,15s0,329,0,329l-8,5.5l-8-5.5
- c0,0,0-322,0-329s-9.2-15-17.6-15S80,64,80,64c-18.8,0-33,13.3-33,32v286.1c0,18.8,14.2,33.9,33,33.9c0,0,129.5,0,143.3,0
- c13.8,0,24.7,4.2,24.7,19.4c0,9.1,0,12.6,0,12.6h8h8c0,0,0-3.4,0-12.6c0-15.3,10.9-19.4,24.7-19.4s143.3,0,143.3,0
- c18.8,0,33-15.1,33-33.9V96C465,77.3,450.8,64,432,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box-outline.svg
deleted file mode 100644
index 1045d489..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M287.8,240c8.8,0,16.1,7.2,16.1,16s-7,16-15.9,16h-64c-8.8,0-16-7.2-16-16s7.2-16,16-16h63 M288,224h-64
- c-17.6,0-32,14.4-32,32s14.4,32,32,32h64c17.6,0,32-14.4,32-32S305.6,224,288,224L288,224z"/>
- <g>
- <path d="M416,112H96v80h16v208h288V192h16V112z M384,384H128V192h256V384z M400,176H112v-48h288V176z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box.svg
deleted file mode 100644
index 7ed0eb52..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-box.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M112,400h288V208H112V400z M224,240h64c8.8,0,16,7.2,16,16s-7.2,16-16,16h-64c-8.8,0-16-7.2-16-16S215.2,240,224,240z"/>
- <polygon points="96,112 96,192 112,192 400,192 416,192 416,112 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase-outline.svg
deleted file mode 100644
index b9ccbd2b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M416,128v-16h-32v16h-48V98.1V96c-0.5-18.2-13.6-32-32.2-32h-99.1C186.1,64,176,77.7,176,96v2.1V128h-48v-16H96v16H48v320
- h416V128H416z M192,127.5V98.1c0-10.2,2.9-18.1,13.7-18.1h97.1c10.4,0,17.2,7.7,17.2,18.1v29.4v0.5H192V127.5z M448,432H64V208h384
- V432z M448,192H64v-48h32v16h32v-16h256v16h32v-16h32V192z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase.svg
deleted file mode 100644
index 90b9cf20..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-briefcase.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="96" y="112" width="32" height="16"/>
- <rect x="48" y="208" width="416" height="240"/>
- <rect x="384" y="112" width="32" height="16"/>
- <path d="M416,128v32h-32v-32h-48V98.1V96c-0.5-18.2-13.6-32-32.2-32h-99.1C186.1,64,176,77.7,176,96v2.1V128h-48v32H96v-32H48v64
- h416v-64H416z M320,127.5v0.5H192v-0.5V98.1c0-10.2,2.9-18.1,13.7-18.1h97.1c10.4,0,17.2,7.7,17.2,18.1V127.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers-outline.svg
deleted file mode 100644
index 3c29db9a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,144v304h303.9V144H64z M351.9,432H80V160h271.9V432z"/>
- <g>
- <polygon points="448,64 144,64 144,128 160,128 160,80 432,80 432,352 384,352 384,368 448,368 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers.svg
deleted file mode 100644
index 36ab92e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-browsers.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,144v304h303.9V144H64z"/>
- <polygon points="144,64 144,128 384,128 384,368 448,368 448,64 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator-outline.svg
deleted file mode 100644
index 9006a345..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M144,160h224V96H144V160z M160,112h192v32H160V112z"/>
- <path d="M368,64H144c-17.7,0-32,14.3-32,32v320c0,17.7,14.3,32,32,32h224c17.7,0,32-14.3,32-32V96C400,78.3,385.7,64,368,64z
- M384,416c0,8.8-7.2,16-16,16H144c-8.8,0-16-7.2-16-16V96c0-8.8,7.2-16,16-16h224c8.8,0,16,7.2,16,16V416z"/>
- <polygon points="160,240 160,208 160,192 144,192 144,256 208,256 208,240 192,240 "/>
- <polygon points="160,320 160,288 160,272 144,272 144,336 208,336 208,320 192,320 "/>
- <polygon points="160,400 160,368 160,352 144,352 144,416 208,416 208,400 192,400 "/>
- <polygon points="240,240 240,208 240,192 224,192 224,256 288,256 288,240 272,240 "/>
- <polygon points="320,240 320,208 320,192 304,192 304,256 368,256 368,240 352,240 "/>
- <polygon points="240,320 240,288 240,272 224,272 224,336 288,336 288,320 272,320 "/>
- <polygon points="240,400 240,368 240,352 224,352 224,416 288,416 288,400 272,400 "/>
- <polygon points="320,400 320,368 320,272 304,272 304,416 368,416 368,400 352,400 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator.svg
deleted file mode 100644
index 64b08607..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calculator.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M368,64H144c-17.7,0-32,14.3-32,32v320c0,17.7,14.3,32,32,32h224c17.7,0,32-14.3,32-32V96C400,78.3,385.7,64,368,64z
- M360,280v128h-48V280H360z M360,200v48h-48v-48H360z M280,360v48h-48v-48H280z M280,280v48h-48v-48H280z M280,200v48h-48v-48H280z
- M200,360v48h-48v-48H200z M200,280v48h-48v-48H200z M200,200v48h-48v-48H200z M152,152v-48h208v48H152z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar-outline.svg
deleted file mode 100644
index cd81cbd1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:none;}
-]]>
-</style>
-<polyline class="st0" points="80,112 80,176 432,176 432,112 "/>
-<path d="M352,96V64h-16v32H176V64h-16v32H64v352h384V96H352z M432,432H80V192h352V432z M432,176H80v-64h80v32h16v-32h160v32h16v-32
- h80V176z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar.svg
deleted file mode 100644
index 8fd1de32..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-calendar.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="64" y="192" width="384" height="256"/>
- <polygon points="448,96 352,96 352,144 336,144 336,96 176,96 176,144 160,144 160,96 64,96 64,176 448,176 "/>
- <rect x="160" y="64" width="16" height="32"/>
- <rect x="336" y="64" width="16" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera-outline.svg
deleted file mode 100644
index 3feed556..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M417.5,160h-61.7c-32.1-36-42.2-48-54.5-48h-88.5c-12.3,0-22.2,12-54.5,48H145v-16h-34v16H97.5C79.9,160,64,173.2,64,190.7
- v176c0,17.5,15.9,33.3,33.5,33.3h320c17.6,0,30.5-15.8,30.5-33.3v-176C448,173.2,435.1,160,417.5,160z M432,366.7
- c0,9.3-6.2,17.3-14.5,17.3h-320c-8.7,0-17.5-8.7-17.5-17.3v-176c0-8.2,8.1-14.7,17.5-14.7h60.7h7.1l4.8-3.2c4-4.5,7.7-10,11.1-13.8
- c11.3-12.7,19.5-21.7,25.3-26.9c4.7-4.2,6.2-4.1,6.2-4.1h88.5c0,0,1.6-0.1,6.7,4.5c6.1,5.5,14.7,16.5,26.6,29.8
- c2.9,3.3,6,6.8,9.3,10.5l4.8,3.2h7.2h61.7c8.8,0,14.5,6,14.5,14.7V366.7z"/>
- <path d="M256,189.5c-47.1,0-85.5,38.4-85.5,85.5s38.4,85.5,85.5,85.5s85.5-38.4,85.5-85.5S303.1,189.5,256,189.5z M256,344.5
- c-38.4,0-69.5-31.1-69.5-69.5s31.1-69.5,69.5-69.5s69.5,31.1,69.5,69.5S294.4,344.5,256,344.5z"/>
- <rect x="352" y="192" width="17" height="17"/>
- <circle cx="256" cy="275" r="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera.svg
deleted file mode 100644
index 11ce8753..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-camera.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M417.5,160h-61.7c-32.1-36-42.2-48-54.5-48h-88.5c-12.3,0-22.2,12-54.5,48H145v-16h-34v16H97.5C79.9,160,64,173.2,64,190.7
- v176c0,17.5,15.9,33.3,33.5,33.3h320c17.6,0,30.5-15.8,30.5-33.3v-176C448,173.2,435.1,160,417.5,160z M256,360.5
- c-47.1,0-85.5-38.4-85.5-85.5s38.4-85.5,85.5-85.5s85.5,38.4,85.5,85.5S303.1,360.5,256,360.5z M369,209h-17v-17h17V209z"/>
- <path d="M256,205.5c-38.4,0-69.5,31.1-69.5,69.5s31.1,69.5,69.5,69.5s69.5-31.1,69.5-69.5S294.4,205.5,256,205.5z M256,307
- c-17.7,0-32-14.3-32-32s14.3-32,32-32s32,14.3,32,32S273.7,307,256,307z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart-outline.svg
deleted file mode 100644
index 9fe49fb7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M160,400c-13.248,0-24,10.752-24,24s10.752,24,24,24s24-10.752,24-24S173.248,400,160,400z M160,432c-4.411,0-8-3.589-8-8
- s3.589-8,8-8s8,3.589,8,8S164.411,432,160,432z"/>
- <path d="M384.5,400c-13.248,0-24,10.752-24,24s10.752,24,24,24s24-10.752,24-24S397.748,400,384.5,400z M384.5,432
- c-4.411,0-8-3.589-8-8s3.589-8,8-8s8,3.589,8,8S388.911,432,384.5,432z"/>
- <path d="M448,128L123.177,95.646c-1.628-6.972-4.369-14.66-11.838-20.667C102.025,67.489,86.982,64,64,64v16.001
- c18.614,0,31.167,2.506,37.312,7.447c4.458,3.585,5.644,8.423,7.165,15.989l-0.024,0.004l42.052,233.638
- c2.413,14.422,7.194,25.209,13.291,32.986C171.043,379.312,180.533,384,192,384h240v-16H192c-4.727,0-19.136,0.123-25.749-33.755
- l-5.429-30.16L432,256L448,128z M418.59,242.348l-260.601,45.99l-31.732-176.3l303.869,30.608L418.59,242.348z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart.svg
deleted file mode 100644
index b7fdd4b8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cart.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M160,400c-13.248,0-24,10.752-24,24s10.752,24,24,24s24-10.752,24-24S173.248,400,160,400z"/>
- <path d="M384.5,400c-13.248,0-24,10.752-24,24s10.752,24,24,24s24-10.752,24-24S397.748,400,384.5,400z"/>
- <path d="M448,128L123.177,95.646c-1.628-6.972-4.369-14.66-11.838-20.667C102.025,67.489,86.982,64,64,64v16.001
- c18.614,0,31.167,2.506,37.312,7.447c4.458,3.585,5.644,8.423,7.165,15.989l-0.024,0.004l42.052,233.638
- c2.413,14.422,7.194,25.209,13.291,32.986C171.043,379.312,180.533,384,192,384h240v-16H192c-4.727,0-19.136,0.123-25.749-33.755
- l-5.429-30.16L432,256L448,128z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes-outline.svg
deleted file mode 100644
index d87a8861..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="64,64 320,64 320,160 336,160 336,48 48,48 48,272 160,272 160,256 64,256 "/>
- <path d="M176,176v224h162.6l64,64H416v-64h48V176H176z M448,384h-48v54.6L345,384H192V192h256V384z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes.svg
deleted file mode 100644
index 1e975b1b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatboxes.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="336,48 48,48 48,272 160,272 160,160 336,160 "/>
- <path d="M176,176v224h162.6l64,64H416v-64h48V176H176z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble-outline.svg
deleted file mode 100644
index 251db96a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,112c97,0,176,62,176,138.3c0,35.9-17.6,69.2-49.5,93.9c-32.8,25.4-77.4,39.3-125.5,39.3c-28.9,0-51-3-69.7-9.3
- c-0.6-0.2-1.3-0.5-2-0.7c-0.3-0.1-0.6-0.2-0.8-0.2c-4.7-1.4-9.7-2.1-14.7-2.1c-5.6,0-11.1,0.9-16.3,2.6l0,0l-0.3,0.1
- c-0.6,0.2-8.9,3.3-11,4.3l0,0l-39.6,17.2c13.8-43.9,13.8-44.8,13.8-47.6c0-7.1-2.2-14.1-6.3-20.2c-0.5-0.7-1-1.4-1.6-2.1
- c-0.7-0.9-1.3-1.7-1.8-2.3c-17.4-21.9-26.6-47.1-26.6-73C80,174,159,112,256,112 M256,96C149.9,96,64,165.1,64,250.3
- c0,30.7,11.2,59.3,30.4,83.3c0.9,0.9,2.9,3.8,3.6,4.9c0,0-1-1.6-1.1-1.9c0,0,0,0,0,0l0,0c0,0,0,0,0,0c2.3,3.3,3.6,7.1,3.6,11.2
- c0,1.4-17.9,58-17.9,58l0,0c-1.3,4.4,2.1,8.9,7.6,10c0.8,0.2,1.6,0.2,2.4,0.2c1.3,0,2.5-0.2,3.7-0.5l1.6-0.6l50.6-22
- c0.9-0.4,9-3.5,10-3.9c0,0,0.6-0.2,0.6-0.2c0,0-0.1,0-0.6,0.2c3.4-1.2,7.2-1.8,11.2-1.8c3.6,0,7.1,0.5,10.3,1.5c0.1,0,0.2,0,0.2,0.1
- c0.5,0.2,1,0.3,1.5,0.5c23.1,7.9,48.4,10.3,75.1,10.3c106,0,191-64.1,191-149.3C448,165.1,362,96,256,96L256,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble.svg
deleted file mode 100644
index c2efd7f2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-chatbubble.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,96C149.9,96,64,165.1,64,250.3c0,30.7,11.2,59.3,30.4,83.3c0.9,0.9,2.9,3.8,3.6,4.9c0,0-1-1.6-1.1-1.9c0,0,0,0,0,0l0,0
- c0,0,0,0,0,0c2.3,3.3,3.6,7.1,3.6,11.2c0,1.4-17.9,58-17.9,58l0,0c-1.3,4.4,2.1,8.9,7.6,10c0.8,0.2,1.6,0.2,2.4,0.2
- c1.3,0,2.5-0.2,3.7-0.5l1.6-0.6l50.6-22c0.9-0.4,9-3.5,10-3.9c0,0,0.6-0.2,0.6-0.2c0,0-0.1,0-0.6,0.2c3.4-1.2,7.2-1.8,11.2-1.8
- c3.6,0,7.1,0.5,10.3,1.5c0.1,0,0.2,0,0.2,0.1c0.5,0.2,1,0.3,1.5,0.5c23.1,7.9,48.4,10.3,75.1,10.3c106,0,191-64.1,191-149.3
- C448,165.1,362,96,256,96L256,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-empty.svg
deleted file mode 100644
index baf44785..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-empty.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M223.9,329.7c-2.4,2.4-5.8,4.4-8.8,4.4s-6.4-2.1-8.9-4.5l-56-56l17.8-17.8l47.2,47.2l124.8-125.7l17.5,18.1L223.9,329.7z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-outline.svg
deleted file mode 100644
index 57145a66..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M340.1,177.3L215.3,303l-47.2-47.2l-17.8,17.8l56,56c2.5,2.5,5.9,4.5,8.9,4.5s6.3-2,8.8-4.4l133.7-134.4L340.1,177.3z"/>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark.svg
deleted file mode 100644
index 42e46244..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-checkmark.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M223.9,329.7
- c-2.4,2.4-5.8,4.4-8.8,4.4s-6.4-2.1-8.9-4.5l-56-56l17.8-17.8l47.2,47.2l124.8-125.7l17.5,18.1L223.9,329.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-filled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-filled.svg
deleted file mode 100644
index 0cebbc00..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-filled.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
-</g>
-<g>
- <g>
- <path d="M256,96c-88.4,0-160,71.6-160,160c0,88.4,71.6,160,160,160c88.4,0,160-71.6,160-160C416,167.6,344.4,96,256,96z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-outline.svg
deleted file mode 100644
index ce8c36e8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-circle-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock-outline.svg
deleted file mode 100644
index 4db33fc8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- <polygon points="256,256 160,256 160,273.3 273.3,273.3 273.3,128 256,128 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock.svg
deleted file mode 100644
index a083faa1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-clock.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M273,273H160v-17h96V128h17
- V273z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-empty.svg
deleted file mode 100644
index 71c7d70f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-empty.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<polygon class="st0" points="340.2,160 255.8,244.3 171.8,160.4 160,172.2 244,256 160,339.9 171.8,351.6 255.8,267.8 340.2,352
- 352,340.3 267.6,256 352,171.8 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-outline.svg
deleted file mode 100644
index d67ac63f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <g>
- <path class="st0" d="M403.1,108.9c-81.2-81.2-212.9-81.2-294.2,0s-81.2,212.9,0,294.2c81.2,81.2,212.9,81.2,294.2,0
- S484.3,190.1,403.1,108.9z M390.8,390.8c-74.3,74.3-195.3,74.3-269.6,0c-74.3-74.3-74.3-195.3,0-269.6s195.3-74.3,269.6,0
- C465.2,195.5,465.2,316.5,390.8,390.8z"/>
- </g>
- <polygon class="st0" points="340.2,160 255.8,244.2 171.8,160.4 160,172.2 244,256 160,339.8 171.8,351.6 255.8,267.8 340.2,352
- 352,340.2 267.6,256 352,171.8 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close.svg
deleted file mode 100644
index eb4d0e6c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-close.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M403.1,108.9c-81.2-81.2-212.9-81.2-294.2,0s-81.2,212.9,0,294.2c81.2,81.2,212.9,81.2,294.2,0
- S484.3,190.1,403.1,108.9z M352,340.2L340.2,352l-84.4-84.2l-84,83.8L160,339.8l84-83.8l-84-83.8l11.8-11.8l84,83.8l84.4-84.2
- l11.8,11.8L267.6,256L352,340.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download-outline.svg
deleted file mode 100644
index c1629540..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <polygon points="193.2,381.2 181.6,392.6 256.1,466 330.6,392.6 319,381.2 264.3,435 264.3,192.9 247.9,192.9 247.9,435 "/>
- </g>
- <g>
- <path d="M399.2,164.4c0-1.2,0.2-2.3,0.2-3.5C399.4,97.4,346.5,46,282.6,46c-46.1,0-85.8,26.8-104.4,65.4c-8.1-4-17.1-6.3-26.8-6.3
- c-29.6,0-54.1,23.3-58.9,51.3c-35.2,12-60.6,43.4-60.6,82.4c0,49.1,40.1,89.2,89.6,89.2H213v-16h-90.7
- c-40.9,0-74.2-33.2-74.2-73.7c0-31.4,20.2-57.5,50.2-67.7l8.4-2.8l1.5-8.7c3.6-21.3,22.1-38.8,43.9-38.8c6.9,0,13.7,1.6,19.9,4.7
- l13.5,6.7l6.5-13.6c16.6-34.4,52.1-56.6,90.4-56.6c55.3,0,100.9,42.8,100.9,97.6c0,13.1-0.2,20.1-0.2,20.1l15.2,0.1
- c36.7,0.5,65.6,30,65.6,66.4c0,36.3-29.8,66.1-66.5,66.3l-3.2,0.1H297v16h101h0c45,0,81.9-37.2,81.9-82.1
- C479.9,201,444.5,164.5,399.2,164.4z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download.svg
deleted file mode 100644
index 526465a7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-download.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="248,435 193.3,381.2 181.6,392.6 256.1,466 330.6,392.6 318.8,381.2 264,435 264,328 248,328 "/>
- <path d="M399.2,164.4c0-1.2,0.2-2.3,0.2-3.5C399.4,97.4,346.5,46,282.6,46c-46.1,0-85.8,26.8-104.4,65.4c-8.1-4-17.1-6.3-26.8-6.3
- c-29.6,0-54.1,23.3-58.9,51.3c-35.2,12-60.6,43.4-60.6,82.4c0,49.1,40.1,89.2,89.6,89.2H192h21h35V193h16v135h134
- c45,0,81.9-37.2,81.9-82.1C479.9,201,444.5,164.5,399.2,164.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-outline.svg
deleted file mode 100644
index 1665c917..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M399.3,232.8c0-1.2,0.2-2.4,0.2-3.6c0-64.3-52.8-117.2-116.8-117.2c-46.1,0-85.8,27.9-104.4,67c-8.1-4.1-17.1-6.4-26.8-6.4
- c-29.6,0-54.1,23.7-58.9,52C57.4,236.8,32,268.8,32,308.4c0,49.8,40.1,91.6,89.6,91.6H398c45,0,82-38.9,82-84.3
- C480,270.1,444.6,232.9,399.3,232.8z M397.5,383.6l-3.2,0.4H122.4c-40.9,0-74.2-34.9-74.2-76.1c0-31.9,20.2-58.4,50.2-68.8l8.4-3
- l1.5-8.8c3.6-21.6,22.1-39.3,43.9-39.3c6.9,0,13.7,1.6,19.9,4.8l13.5,6.8l6.5-13.7c16.6-34.9,52.1-58.2,90.4-58.2
- c55.3,0,100.9,44.1,100.9,99.7c0,13.3-0.2,20.3-0.2,20.3l15.2,0.1c36.7,0.5,65.6,30.5,65.6,67.4C464,352.1,434.2,383.4,397.5,383.6z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload-outline.svg
deleted file mode 100644
index 5cb54317..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <polygon points="193.3,260.4 181.7,248.8 256.2,174.5 330.7,248.8 319,260.4 264.4,205.8 264.4,447.6 247.9,447.6 247.9,205.8
- "/>
- </g>
- <g>
- <path d="M399.3,183.6c0-1.2,0.2-2.4,0.2-3.6c0-64.3-52.8-116.4-116.8-116.4c-46.1,0-85.8,27.1-104.4,66.3
- c-8.1-4.1-17.1-6.4-26.8-6.4c-29.6,0-54.1,23.6-58.9,52C57.4,187.6,32,222.2,32,261.8c0,49.7,40.1,90.2,89.6,90.2H213v-16h-90.6
- c-40.9,0-74.2-33.5-74.2-74.6c0-31.8,20.2-61.2,50.2-71.6l8.4-2.9l1.5-8.8c3.6-21.6,22.1-39.3,43.9-39.3c6.9,0,13.7,1.6,19.9,4.8
- l13.5,6.8l6.5-13.7c16.6-34.9,52.1-57.4,90.4-57.4c55.3,0,100.9,43.3,100.9,98.9c0,13.3-0.2,20.3-0.2,20.3l15.2,0.1
- C435,199.1,464,232,464,268.9c0,36.8-29.8,66.9-66.5,67.1l-3.2,0H297v16h101h0c45,0,82-37.3,82-82.8
- C480,223.7,444.5,183.7,399.3,183.6z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload.svg
deleted file mode 100644
index cff5dc7a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud-upload.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="248" y="352" width="16" height="96"/>
- <path d="M399.3,183.6c0-1.2,0.2-2.4,0.2-3.6c0-64.3-52.8-116.4-116.8-116.4c-46.1,0-85.8,27.1-104.4,66.3
- c-8.1-4.1-17.1-6.4-26.8-6.4c-29.6,0-54.1,23.6-58.9,52C57.4,187.6,32,222.2,32,261.8c0,49.7,40.1,90.2,89.6,90.2H182h31h35V205.8
- l-54.7,54.5l-11.6-11.6l74.5-74.3l74.5,74.3l-11.8,11.6L264,205.8V352h134c45,0,82-37.3,82-82.8C480,223.7,444.5,183.7,399.3,183.6
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud.svg
deleted file mode 100644
index 29b64a67..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloud.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M399.3,232.8c0-1.2,0.2-2.4,0.2-3.6c0-64.3-52.8-117.2-116.8-117.2c-46.1,0-85.8,27.9-104.4,67c-8.1-4.1-17.1-6.4-26.8-6.4
- c-29.6,0-54.1,23.7-58.9,52C57.4,236.8,32,268.8,32,308.4c0,49.8,40.1,91.6,89.6,91.6H398c45,0,82-38.9,82-84.3
- C480,270.1,444.6,232.9,399.3,232.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night-outline.svg
deleted file mode 100644
index c45c348a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M189,223.8c14.5,0,28.1,4.8,39.3,13.9c10.9,8.9,18.6,21.3,21.7,34.9l3.1,14l14.2-1.8c2.1-0.3,4.1-0.4,6.1-0.4
- c26.9,0,48.8,22.1,48.8,49.2c0,27.1-21.9,49.2-48.8,49.2H115.7c-9.5,0-18.5-3.9-25.4-10.8c-6.8-7-10.6-16.2-10.6-25.9
- c0-18.6,14.5-33.8,33.2-36.9c1.6-0.3,8.8-1.2,14.2-1.7c0,0-0.5-5.3-0.6-9.6c-0.1-4.3-0.1-9.4-0.1-11.5
- C126.5,252,154.5,223.8,189,223.8 M189,208c-43.3,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8C84.7,296.7,64,319.8,64,346.9
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7c0-35.8-28.9-65.3-64.6-65.3c-2.7,0-5.4,0-8,0.3
- C257.5,234.3,226.3,208,189,208L189,208z"/>
- <path class="st0" d="M424.6,305.6c-2,0.1-3.9,0.1-5.9,0.1c-32.3,0-62.7-12.6-85.5-35.5c-22.8-22.9-35.4-53.3-35.4-85.7
- c0-18.4,4.1-36.2,11.8-52.4c3.4-7.1,7.5-13.9,12.3-20.2c-8.4,0.9-16.6,2.7-24.4,5.1c-37.2,11.8-67.1,40.2-81,76.5
- c5.9,1.2,11.6,3,17,5.4c10.1-25.5,29.4-46.4,53.8-58.6c-4.6,13.9-7.1,28.7-7.1,44.1c0,27.3,7.9,52.8,21.4,74.2
- c13.8,21.8,33.5,39.5,56.8,50.9c15.3,7.4,32.2,12.1,50,13.5c-14,12.2-31.2,20.9-50,24.8c-1.9,6.9-4.9,13.4-8.6,19.3
- c33.6-3.6,63.3-20.1,84-44.6c5.4-6.3,10.2-13.2,14.2-20.5C440.4,304.1,432.6,305.2,424.6,305.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night.svg
deleted file mode 100644
index 51a16221..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-night.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M424.6,305.6c-2,0.1-3.9,0.1-5.9,0.1c-32.3,0-62.7-12.6-85.5-35.5c-22.8-22.9-35.4-53.3-35.4-85.7
- c0-18.4,4.1-36.2,11.8-52.4c3.4-7.1,7.5-13.9,12.3-20.2c-8.4,0.9-16.6,2.7-24.4,5.1c-37.2,11.8-67.1,40.2-81,76.5
- c-0.3,0.8-0.6,1.5-0.9,2.3c11.9,3.5,23.1,9.4,32.8,17.3c13,10.6,22.9,24.5,28.8,40.1c20.1,0.9,38.9,9.4,53.3,24
- c15.2,15.4,23.5,35.9,23.5,57.4c0,11.4-2.4,22.5-6.8,32.8c0.8-0.1,1.6-0.1,2.5-0.2c33.6-3.6,63.3-20.1,84-44.6
- c5.4-6.3,10.2-13.2,14.2-20.5C440.4,304.1,432.6,305.2,424.6,305.6z"/>
-</g>
-<path class="st0" d="M189,209c-43.3,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8C84.7,297.7,64,320.8,64,347.9
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7c0-35.8-28.9-65.3-64.6-65.3c-2.7,0-5.4,0-8,0.3
- C257.5,235.3,226.3,209,189,209L189,209z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-outline.svg
deleted file mode 100644
index 2bfbadd7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M244,175.8c14.5,0,28.1,4.8,39.3,13.9c10.9,8.9,18.6,21.3,21.7,34.9l3.1,14l14.2-1.8c2.1-0.3,4.1-0.4,6.1-0.4
- c26.9,0,48.8,22.1,48.8,49.2c0,27.1-21.9,49.2-48.8,49.2H170.7c-9.5,0-18.5-3.9-25.4-10.8c-6.8-7-10.6-16.2-10.6-25.9
- c0-18.6,14.5-33.8,33.2-36.9c1.6-0.3,8.7-1.2,14.2-1.7c0,0-0.5-5.3-0.6-9.6c-0.1-4.3-0.1-9.4-0.1-11.5
- C181.5,204,209.5,175.8,244,175.8 M244,160c-43,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8c-26.4,2.3-47.1,25.5-47.1,52.6
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7S364.1,221,328.4,221c-2.7,0-5.4,0-8,0.3C312.5,186.3,281,160,244,160
- L244,160z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy.svg
deleted file mode 100644
index 634632e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cloudy.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M244,160c-43,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8c-26.4,2.3-47.1,25.5-47.1,52.6
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7S364.1,221,328.4,221c-2.7,0-5.4,0-8,0.3C312.5,186.3,281,160,244,160
- L244,160z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog-outline.svg
deleted file mode 100644
index cca3e715..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog-outline.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M448,272.754v-32.008l-33.291-8.703l-2.601-13.204l27.594-20.905l-12.197-29.608l-34.392,4.802l-7.498-10.603
- l17.696-29.708l-22.594-22.605l-30.192,17.404l-10.697-7.302l5.298-35.009l-29.492-12.303L294.04,101.31l-12.297-2.601L273.045,64
- h-31.991l-9.197,34.909l-12.098,2.4l-21.494-29.008l-29.592,12.304l4.799,35.709l-11.697,7.202l-31.292-18.705l-22.594,22.606
- l18.795,31.508l-6.698,10.502l-35.49-5.001l-12.197,29.608l28.893,21.706l-2.399,12.203L64,240.846v32.008l34.69,8.903l2.4,12.503
- l-28.394,21.306l12.297,29.508l34.991-5.002l7.099,11.303l-17.896,30.608l22.595,22.605l30.192-18.204l11.196,7.302l-4.498,34.31
- l29.592,12.202l20.595-27.807l13.396,2.5L241.054,448h31.991l8.298-33.109l13.597-2.601l20.694,27.107l29.593-12.204l-4.998-33.708
- l10.196-7.401l28.992,16.904l22.595-22.606l-16.795-28.907l7.896-11.403l33.791,4.802l12.298-29.508l-27.193-20.506l2.7-13.503
- L448,272.754z M419.707,320.767l-2.8,6.702l-31.891-4.501l-18.896,27.807l15.695,27.106l-5.198,5.202l-27.293-15.904
- l-26.593,18.204l4.799,31.809l-6.698,2.802l-19.595-25.607l-32.892,6.501l-7.798,31.209h-7.198l-8.397-31.309l-32.592-6.501
- l-19.495,26.406l-6.698-2.801l4.399-32.509l-27.493-18.304l-28.793,17.504l-5.099-5.101l16.996-29.108l-18.096-27.606
- l-33.191,4.701l-2.699-6.603l26.894-20.205l-6.199-31.809l-32.991-8.502v-7.202l32.991-8.402l6.299-31.608l-27.293-20.505
- l2.699-6.602l33.691,4.801l17.796-26.807l-17.996-30.008l4.999-5.001l20.595,12.303l9.197,5.501l27.893-18.205l-4.499-33.809
- l6.699-2.8l20.294,27.407l31.492-6.102l8.798-33.208h7.198l8.298,33.008l31.691,6.301l20.095-26.807l6.598,2.801l-4.999,33.108
- l27.193,18.105l28.292-16.205l5.1,5.102l-16.695,28.007l18.396,27.007l32.491-4.601l2.799,6.702l-26.193,19.705l6.498,32.508
- l31.292,8.102v7.202l-31.391,8.103l-6.499,32.709L419.707,320.767z"/>
- <path d="M256,128c-70.692,0-128,57.308-128,128c0,70.693,57.308,128,128,128s128-57.307,128-128C384,185.308,326.692,128,256,128z
- M144,256c0-29.916,11.65-58.042,32.804-79.195C197.958,155.65,226.084,144,256,144c7.496,0,14.88,0.732,22.069,2.161L250.3,250.1
- l-104.155,27.888C144.727,270.824,144,263.468,144,256z M256,368c-29.917,0-58.042-11.65-79.196-32.804
- c-11.927-11.926-20.831-26.069-26.331-41.499L253.9,266.2l74.935,74.889C308.558,358.501,283.009,368,256,368z M340.154,329.901
- L265.2,254.9l28.05-104.58c15.604,5.487,29.904,14.443,41.945,26.484C356.35,197.958,368,226.084,368,256
- C368,283.486,358.159,309.457,340.154,329.901z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog.svg
deleted file mode 100644
index e0d22afb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-cog.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M293.25,150.32L265.2,254.9l74.954,75C358.159,309.457,368,283.486,368,256c0-29.916-11.65-58.042-32.805-79.196
- C323.154,164.763,308.854,155.807,293.25,150.32z"/>
- <path d="M278.068,146.161C270.88,144.732,263.496,144,256,144c-29.916,0-58.042,11.65-79.196,32.805
- C155.65,197.958,144,226.084,144,256c0,7.468,0.727,14.824,2.145,21.988L250.3,250.1L278.068,146.161z"/>
- <path d="M150.473,293.697c5.5,15.43,14.404,29.572,26.331,41.498C197.958,356.35,226.083,368,256,368
- c27.009,0,52.558-9.499,72.835-26.911L253.9,266.2L150.473,293.697z"/>
- <path d="M448,272.754v-32.008l-33.291-8.703l-2.601-13.204l27.594-20.905l-12.197-29.608l-34.392,4.802l-7.498-10.603
- l17.695-29.708l-22.594-22.605l-30.191,17.404l-10.697-7.302l5.298-35.009l-29.492-12.303L294.04,101.31l-12.297-2.601L273.045,64
- h-31.991l-9.197,34.909l-12.098,2.4l-21.494-29.008l-29.592,12.304l4.799,35.709l-11.697,7.202l-31.292-18.705l-22.594,22.606
- l18.795,31.508l-6.698,10.502l-35.49-5.001l-12.197,29.608l28.893,21.706l-2.399,12.203L64,240.846v32.007l34.69,8.903l2.4,12.503
- l-28.394,21.307l12.297,29.508l34.991-5.002l7.099,11.303l-17.896,30.607l22.595,22.605l30.192-18.204l11.196,7.302l-4.498,34.311
- l29.592,12.202l20.595-27.808l13.396,2.5L241.054,448h31.991l8.298-33.109l13.597-2.601l20.694,27.106l29.593-12.203l-4.998-33.709
- l10.196-7.4l28.992,16.904l22.595-22.606l-16.795-28.907l7.896-11.402l33.791,4.802l12.298-29.508l-27.193-20.507l2.7-13.502
- L448,272.754z M256,384c-70.692,0-128-57.307-128-128c0-70.692,57.308-128,128-128c70.692,0,128,57.308,128,128
- C384,326.693,326.692,384,256,384z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter-outline.svg
deleted file mode 100644
index 2d44608e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter-outline.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M366.195,212.122c1.185-6.528,1.806-13.252,1.806-20.122c0-61.856-50.145-112.001-112.001-112.001
- S143.999,130.144,143.999,192c0,6.87,0.621,13.594,1.806,20.122C98.616,225.302,63.999,268.606,63.999,320
- c0,61.856,50.145,112.001,112.001,112.001c31.342,0,59.671-12.879,80-33.627c20.329,20.748,48.658,33.627,80,33.627
- c61.856,0,112.001-50.145,112.001-112.001C448.001,268.606,413.384,225.303,366.195,212.122z M159.999,192
- c0-52.935,43.065-96.001,96.001-96.001s96.001,43.066,96.001,96.001c0,5.776-0.513,11.435-1.495,16.933
- c-4.749-0.614-9.59-0.934-14.506-0.934c-31.342,0-59.671,12.879-80,33.627c-20.329-20.748-48.658-33.627-80-33.627
- c-4.916,0-9.757,0.319-14.506,0.934C160.512,203.435,159.999,197.776,159.999,192z M272.001,320c0,19.58-5.896,37.806-16.001,53.006
- c-10.104-15.2-16.001-33.426-16.001-53.006c0-5.776,0.513-11.435,1.495-16.933c4.749,0.614,9.59,0.934,14.506,0.934
- s9.757-0.319,14.506-0.934C271.488,308.565,272.001,314.224,272.001,320z M256,288.001c-3.484,0-6.925-0.191-10.314-0.556
- c2.626-7.262,6.105-14.119,10.314-20.451c4.21,6.332,7.688,13.189,10.314,20.451C262.925,287.81,259.484,288.001,256,288.001z
- M229.791,284.364c-29.756-8.455-53.666-30.937-64.105-59.81c3.39-0.364,6.83-0.556,10.314-0.556
- c27.353,0,52.069,11.5,69.572,29.917C238.847,263.104,233.484,273.351,229.791,284.364z M266.428,253.917
- c17.503-18.418,42.219-29.918,69.572-29.918c3.484,0,6.925,0.191,10.314,0.556c-10.439,28.873-34.35,51.354-64.105,59.81
- C278.516,273.351,273.153,263.104,266.428,253.917z M176,416.001c-52.936,0-96.001-43.065-96.001-96.001
- c0-43.852,29.555-80.931,69.792-92.364c11.732,34.983,40.265,62.257,76.014,72.243c-1.185,6.527-1.806,13.252-1.806,20.121
- c0,24.717,8.013,47.559,21.573,66.084C228.069,404.501,203.353,416.001,176,416.001z M336,416.001
- c-27.354,0-52.069-11.5-69.572-29.918c13.561-18.524,21.573-41.366,21.573-66.083c0-6.869-0.621-13.594-1.806-20.121
- c35.749-9.986,64.281-37.26,76.014-72.243c40.237,11.434,69.792,48.513,69.792,92.364C432.001,372.936,388.936,416.001,336,416.001z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter.svg
deleted file mode 100644
index eee02aa4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-filter.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M366.194,212.122c1.185-6.528,1.807-13.252,1.807-20.122c0-61.856-50.146-112-112.001-112
- c-61.857,0-112.001,50.144-112.001,112c0,6.87,0.622,13.594,1.806,20.122C98.618,225.302,64,268.606,64,320
- c0,61.855,50.144,112,112,112c31.341,0,59.67-12.879,80-33.627C276.328,419.121,304.658,432,335.999,432
- C397.854,432,448,381.855,448,320C448,268.606,413.381,225.303,366.194,212.122z M255.998,395.373
- c-0.484,0.495-0.979,0.982-1.475,1.469c-3.201-3.394-6.189-6.987-8.951-10.759c-13.561-18.525-21.574-41.366-21.574-66.083
- c0-6.869,0.622-13.594,1.807-20.121c-35.749-9.986-64.281-37.26-76.014-72.243c-1.594-4.752-2.872-9.647-3.822-14.659
- c0.942-0.29,1.882-0.589,2.835-0.854c-0.046-0.252-0.085-0.507-0.129-0.759c4.186-1.049,8.463-1.867,12.82-2.43
- C166.243,208.319,171.084,208,176,208c31.341,0,59.67,12.878,80,33.626C276.328,220.878,304.658,208,335.999,208
- c4.916,0,9.757,0.319,14.506,0.934c4.355,0.563,8.633,1.38,12.816,2.429c-0.043,0.253-0.082,0.507-0.129,0.76
- c0.955,0.267,1.895,0.564,2.838,0.855c-0.949,5.012-2.229,9.907-3.822,14.658c-11.732,34.983-40.266,62.257-76.013,72.242
- c1.185,6.528,1.807,13.253,1.807,20.122c0,24.717-8.014,47.558-21.574,66.083c-2.762,3.772-5.752,7.367-8.953,10.76
- C256.979,396.356,256.484,395.869,255.998,395.373z"/>
- <path d="M270.506,303.067c-4.749,0.614-9.59,0.934-14.506,0.934s-9.758-0.319-14.506-0.934c-0.982,5.498-1.496,11.156-1.496,16.933
- c0,19.58,5.898,37.806,16.002,53.005c10.104-15.199,16.002-33.425,16.002-53.005C272.002,314.224,271.488,308.565,270.506,303.067z
- "/>
- <path d="M346.313,224.555c-3.39-0.364-6.83-0.556-10.314-0.556c-27.354,0-52.069,11.5-69.571,29.917
- c6.725,9.188,12.088,19.434,15.781,30.448C311.964,275.909,335.874,253.428,346.313,224.555z"/>
- <path d="M266.314,287.445c-2.625-7.262-6.105-14.119-10.314-20.451c-4.209,6.332-7.689,13.189-10.314,20.451
- c3.389,0.364,6.83,0.556,10.314,0.556S262.925,287.81,266.314,287.445z"/>
- <path d="M176,223.999c-3.484,0-6.925,0.191-10.314,0.556c10.439,28.873,34.349,51.354,64.106,59.81
- c3.693-11.015,9.055-21.261,15.781-30.448C228.07,235.499,203.353,223.999,176,223.999z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand-outline.svg
deleted file mode 100644
index 6583acb6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M192.011,149.661l-34.043,34.041l256.097,256.096L448,405.757L192.011,149.661z M212.596,215.702l11.415-11.414
- l201.468,201.469l-11.414,11.414L212.596,215.702z"/>
- <rect x="184" y="64" width="16" height="40"/>
- <rect x="184" y="268" width="16" height="40"/>
- <rect x="280" y="176" width="40" height="16"/>
- <rect x="64" y="176" width="40" height="16"/>
- <rect x="111.875" y="94.077" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 285.3039 109.9734)" width="16" height="40"/>
- <rect x="111.877" y="238.327" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 21.9762 525.7571)" width="15.998" height="40"/>
- <rect x="256.126" y="94.077" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 370.226 381.506)" width="16" height="39.999"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand.svg
deleted file mode 100644
index 1865c8bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-color-wand.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="198.011,159.22 163.968,193.337 420.064,450 454,415.883 "/>
- <rect x="182" y="62" width="32" height="64"/>
- <rect x="182" y="266" width="32" height="64"/>
- <rect x="274" y="178" width="64" height="32"/>
- <polygon points="303.941,112.143 281.314,89.465 236.06,134.82 258.687,157.498 "/>
- <polygon points="92.06,112.143 137.314,157.498 159.941,134.82 114.687,89.465 "/>
- <polygon points="92.06,279.141 114.687,301.816 159.941,256.462 137.314,233.784 "/>
- <rect x="58" y="178" width="64" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose-outline.svg
deleted file mode 100644
index c11f6394..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="368,416 80,416 80,144 304.117,144 320.117,128 64,128 64,432 384,432 384,191.883 368,207.883 "/>
- <polygon points="237.623,284.084 227.917,274.377 399.24,103.054 387.927,91.74 208,271.651 208,304 240.216,304 420.261,124.016
- 408.947,112.73 "/>
- <path d="M444.213,80.312l-12.465-12.466C429.084,65.467,425.556,64,421.746,64c-3.812,0-7.304,1.468-9.929,3.85L399.666,80
- l0.08,0.08l11.293,11.293l21.02,21.02l12.15-12.15c2.383-2.625,3.791-6.117,3.791-9.929C448,86.504,446.592,82.975,444.213,80.312z
- "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose.svg
deleted file mode 100644
index 08d818ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-compose.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="256,320 192,320 192,256 320,128 64,128 64,432 384,432 384,192 "/>
- <polygon points="387.927,91.74 208,271.651 208,304 240.216,304 420.261,124.016 "/>
- <path d="M444.213,80.312l-12.465-12.466C429.084,65.467,425.556,64,421.746,64c-3.812,0-7.304,1.468-9.929,3.85L399.666,80
- l0.08,0.08l11.293,11.293l21.02,21.02l12.15-12.15c2.383-2.625,3.791-6.117,3.791-9.929C448,86.504,446.592,82.975,444.213,80.312z
- "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact-outline.svg
deleted file mode 100644
index 79ae9110..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z M256,65.3
- c105.1,0,190.7,85.5,190.7,190.7c0,46.5-16.7,89.1-44.4,122.2c-20-8.2-65.9-24.1-92.9-32.1c-2.4-0.7-2.7-0.9-2.7-10.7
- c0-8.1,3.3-16.3,6.6-23.3c3.6-7.5,7.7-20.2,9.2-31.6c4.2-4.9,10-14.5,13.6-32.9c3.2-16.2,1.7-22.1-0.4-27.6
- c-0.2-0.6-0.5-1.2-0.6-1.7c-0.8-3.8,0.3-23.5,3.1-38.8c1.9-10.5-0.5-32.8-14.9-51.3c-9.1-11.7-26.6-26-58.5-28l-17.5,0
- c-31.4,2-48.8,16.3-58,28c-14.5,18.5-16.9,40.8-15,51.3c2.8,15.3,3.9,35,3.1,38.8c-0.2,0.7-0.4,1.2-0.6,1.8
- c-2.1,5.5-3.7,11.4-0.4,27.6c3.7,18.4,9.4,28,13.6,32.9c1.5,11.4,5.7,24,9.2,31.6c2.6,5.5,3.8,13,3.8,23.6c0,9.9-0.4,10-2.6,10.7
- c-28.1,8.3-72.6,24.3-90.4,32C82.1,345.3,65.3,302.6,65.3,256C65.3,150.9,150.9,65.3,256,65.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact.svg
deleted file mode 100644
index 61829b03..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-contact.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M256,446.7c-58.6,0-111.1-26.6-146.1-68.3c17.8-7.7,62.2-23.7,90.3-31.9c2.2-0.7,2.6-0.8,2.6-10.7c0-10.6-1.2-18.1-3.8-23.6
- c-3.5-7.5-7.7-20.2-9.2-31.6c-4.2-4.9-9.9-14.5-13.6-32.9c-3.2-16.2-1.7-22.1,0.4-27.6c0.2-0.6,0.5-1.2,0.6-1.8
- c0.8-3.7-0.3-23.5-3.1-38.8c-1.9-10.5,0.5-32.8,15-51.3c9.1-11.7,26.6-26,58-28l17.5,0c31.9,2,49.4,16.3,58.5,28
- c14.5,18.5,16.9,40.8,14.9,51.3c-2.8,15.3-3.9,35-3.1,38.8c0.1,0.6,0.4,1.2,0.6,1.7c2.1,5.5,3.7,11.4,0.4,27.6
- c-3.7,18.4-9.4,28-13.6,32.9c-1.5,11.4-5.7,24-9.2,31.6c-3.3,6.9-6.6,15.1-6.6,23.3c0,9.9,0.4,10,2.7,10.7
- c26.7,7.9,72.7,23.8,93,32.1C367.2,420,314.7,446.7,256,446.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy-outline.svg
deleted file mode 100644
index 75b8c0ba..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="304,96 288,96 288,176 368,176 368,160 304,160 "/>
- <path d="M325.3,64H160v48h-48v336h240v-48h48V139L325.3,64z M336,432H128V128h32v272h176V432z M384,384H176V80h142.7l65.3,65.6V384
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy.svg
deleted file mode 100644
index 57132a74..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-copy.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="144,416 144,400 144,112 112,112 112,448 352,448 352,416 160,416 "/>
- <g>
- <path d="M325.3,64H160v48v288h192h48V139L325.3,64z M368,176h-80V96h16v64h64V176z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop-strong.svg
deleted file mode 100644
index fcb8b3a2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop-strong.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="128" y="64" width="32" height="48"/>
- <polygon points="160,352 160,176 128,176 128,384 336,384 336,352 "/>
- <rect x="400" y="352" width="48" height="32"/>
- <polygon points="64,128 64,160 352,160 352,448 384,448 384,128 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop.svg
deleted file mode 100644
index 735b51a6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-crop.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="128" y="64" width="16" height="48"/>
- <polygon points="144,368 144,160 128,160 128,384 352,384 352,368 "/>
- <rect x="400" y="368" width="48" height="16"/>
- <polygon points="64,128 64,144 368,144 368,448 384,448 384,128 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download-outline.svg
deleted file mode 100644
index 7ca9a121..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <polygon points="288,144 288,160 400,160 400,432 112,432 112,160 224,160 224,144 96,144 96,448 416,448 416,144 "/>
- </g>
- <g>
- <polygon points="193.1,252.3 181.5,263.9 256,338.4 330.5,263.9 318.9,252.3 264.2,307 264.2,64 247.8,64 247.8,307 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download.svg
deleted file mode 100644
index 0ffdb50a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-download.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="264,144 264,307 318.8,252.3 330.4,263.9 256,338.4 181.5,263.9 193.2,252.3 248,307 248,144 96,144 96,448
- 416,448 416,144 "/>
- <rect x="248" y="64" width="16" height="80"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-drag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-drag.svg
deleted file mode 100644
index 1cd687a8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-drag.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="80" y="304" width="352" height="16"/>
- <rect x="80" y="248" width="352" height="16"/>
- <rect x="80" y="192" width="352" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email-outline.svg
deleted file mode 100644
index 1f3dcfdc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M64,128v256h384V128H64z M256,267.9L93.2,144h325.6L256,267.9z M80,368V154.1l115.1,87.6L127,319l2,2l78.9-69.6L256,288
- l48.1-36.6L383,321l2-2l-68.1-77.4L432,154.1V368H80z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email.svg
deleted file mode 100644
index 049197b2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-email.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="448,384 448,141.8 316.9,241.6 385,319 383,321 304.1,251.4 256,288 207.9,251.4 129,321 127,319 195,241.6
- 64,142 64,384 "/>
- <polygon points="439.7,128 72,128 256,267.9 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye-outline.svg
deleted file mode 100644
index 1bb77f68..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye-outline.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M447.1,256.2C401.8,204,339.2,144,256,144c-33.6,0-64.4,9.5-96.9,29.8C131.7,191,103.6,215.2,65,255l-1,1l6.7,6.9
- C125.8,319.3,173.4,368,256,368c36.5,0,71.9-11.9,108.2-36.4c30.9-20.9,57.2-47.4,78.3-68.8l5.5-5.5L447.1,256.2z M256,160
- c33.1,0,64.9,9.5,97.2,30.6c23.9,15.6,47.4,36.7,73.7,66.1C388.6,295.4,331.1,352,256,352c-34.2,0-64.2-8.4-94.2-28.2
- c-27.5-18.1-52.3-43.3-76.2-67.8C144.7,196.3,194,160,256,160z"/>
- <path d="M256,336c44.1,0,80-35.9,80-80c0-44.1-35.9-80-80-80c-44.1,0-80,35.9-80,80C176,300.1,211.9,336,256,336z M256,192.3
- c35.2,0,64,28.6,64,63.7c0,35.1-28.8,63.7-64,63.7c-35.2,0-63.9-28.6-63.9-63.7C192.1,220.9,220.8,192.3,256,192.3z"/>
- </g>
- <path d="M288,256L288,256c0,17.5-14.4,32-31.8,32S224,272.8,224,255.3s15.8-31.3,32-31.3l0-16c-26.5,0-47.9,21.6-47.9,48.2
- c0,26.6,21.5,48.1,47.9,48.1s48-21.6,48-48.1V256H288z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye.svg
deleted file mode 100644
index e3267565..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-eye.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M447.1,256.2C401.8,204,339.2,144,256,144c-33.6,0-64.4,9.5-96.9,29.8C131.7,191,103.6,215.2,65,255l-1,1l6.7,6.9
- C125.8,319.3,173.4,368,256,368c36.5,0,71.9-11.9,108.2-36.4c30.9-20.9,57.2-47.4,78.3-68.8l5.5-5.5L447.1,256.2z M256,336
- c-44.1,0-80-35.9-80-80c0-44.1,35.9-80,80-80c44.1,0,80,35.9,80,80C336,300.1,300.1,336,256,336z"/>
- <path d="M250.4,226.8c0-6.9,2-13.4,5.5-18.8c-26.5,0-47.9,21.6-47.9,48.2c0,26.6,21.5,48.1,47.9,48.1s48-21.5,48-48.1v0
- c-5.4,3.5-11.9,5.5-18.8,5.5C266,261.6,250.4,246,250.4,226.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward-outline.svg
deleted file mode 100644
index dff7d376..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M48,155l183.5,101L48,356.9V155 M272,155.8L448,256L272,356.4v-95.6v-27.1V156 M256,128v123.2L32,128v256l224-123.2V384
- l224-128L256,128L256,128z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward.svg
deleted file mode 100644
index ddbdc86f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-fastforward.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,128v123.2L32,128v256l224-123.2V384l224-128L256,128L256,128z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing-outline.svg
deleted file mode 100644
index 31d8329c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing-outline.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M368.5,128h-225L80,224v160h176h176V224L368.5,128z M413.4,224H368v-68L413.4,224z M160,144h192v80h-48
- c0,26.5-21.5,48-48,48s-48-21.5-48-48h-48V144z M144,156v68H98.6L144,156z M416,368H256H96V240h98c7.1,27.6,32.2,48,62,48
- s54.9-20.4,62-48h98V368z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing.svg
deleted file mode 100644
index 8857ecbd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-filing.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,288c-29.8,0-54.9-20.4-62-48H80v144h176h176V240H318C310.9,267.6,285.8,288,256,288z"/>
- <path d="M144,224h16h9h39c0,26.5,21.5,48,48,48s48-21.5,48-48h40h8h16h8h56l-63.5-96H368v80h-16v-80H160v80h-16v-80h-0.5L80,224h57
- H144z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film-outline.svg
deleted file mode 100644
index 2d257378..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film-outline.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M56,88v336h400V88H56z M128,408H72v-48h56V408z M128,344H72v-48h56V344z M128,280H72v-48h56V280z M128,216H72v-48h56V216z
- M128,152H72v-48h56V152z M368,408H144V264h224V408z M368,248H144V104h224V248z M440,408h-56v-48h56V408z M440,344h-56v-48h56V344z
- M440,280h-56v-48h56V280z M440,216h-56v-48h56V216z M440,152h-56v-48h56V152z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film.svg
deleted file mode 100644
index 081f1d2c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-film.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M56,88v336h400V88H56z M128,408H72v-48h56V408z M128,344H72v-48h56V344z M128,280H72v-48h56V280z M128,216H72v-48h56V216z
- M128,152H72v-48h56V152z M368,264H144v-16h224V264z M440,408h-56v-48h56V408z M440,344h-56v-48h56V344z M440,280h-56v-48h56V280z
- M440,216h-56v-48h56V216z M440,152h-56v-48h56V152z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag-outline.svg
deleted file mode 100644
index 2ecb7d2f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M368,112c-11,1.4-24.9,3.5-39.7,3.5c-23.1,0-44-5.7-65.2-10.2c-21.5-4.6-43.7-9.3-67.2-9.3c-46.9,0-62.8,10.1-64.4,11.2
- l-3.4,2.4v2.6v161.7V416h16V272.7c6-2.5,21.8-6.9,51.9-6.9c21.8,0,42.2,8.3,63.9,13c22,4.7,44.8,9.6,69.5,9.6
- c14.7,0,27.7-2,38.7-3.3c6-0.7,11.3-1.4,16-2.2V126v-16.5C379.4,110.4,374,111.2,368,112z M368,269c-11,1.4-23.9,3.5-38.7,3.5
- c-23.1,0-45-4.7-66.2-9.2c-21.5-4.6-43.6-13.3-67.1-13.3c-25.7,0-41.9,3-51.9,6V118.7c6-2.5,21.9-6.8,51.9-6.8
- c21.8,0,42.2,4.3,63.9,9c22,4.7,43.8,10.6,68.5,10.6c14.7,0,28.7-2,39.7-3.3L368,269L368,269z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag.svg
deleted file mode 100644
index 8ed7781e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flag.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M368,112c-11,1.4-24.9,3.5-39.7,3.5c-23.1,0-44-5.7-65.2-10.2c-21.5-4.6-43.7-9.3-67.2-9.3c-46.9,0-62.8,10.1-64.4,11.2
- l-3.4,2.4v2.6v161.7V416h16V272.7c6-2.5,21.8-6.9,51.9-6.9c21.8,0,42.2,8.3,63.9,13c22,4.7,44.8,9.6,69.5,9.6
- c14.7,0,27.7-2,38.7-3.3c6-0.7,11.3-1.4,16-2.2V126v-16.5C379.4,110.4,374,111.2,368,112z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame-outline.svg
deleted file mode 100644
index f774dbc5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M223.899,32c25.691,145-96.732,142-95.895,288c0.686,119.51,104.975,160,128.143,160c23.166,0,113.88-26,126.931-160
- C393.711,210.816,310.572,96,223.899,32z M256.147,472c0,0-40.701-35.816-40.701-80c0-44.183,40.555-80,40.555-80
- s40.332,35.817,40.332,80C296.332,436.184,256.147,472,256.147,472z M367.153,318.449c-2.823,28.988-9.704,54.523-20.45,75.894
- c-8.749,17.397-20.084,32.114-33.692,43.743c-6.522,5.575-13.255,10.115-19.771,13.749c10.039-15.938,19.093-36.72,19.093-59.835
- c0-50.788-43.842-90.307-45.708-91.963l-10.594-9.41l-10.621,9.381c-1.877,1.657-45.963,41.178-45.963,91.992
- c0,21.842,8.168,41.594,17.636,57.152c-7.381-4.326-15.215-9.748-22.986-16.451c-14.688-12.67-26.365-27.608-34.708-44.402
- c-10.063-20.255-15.239-43.265-15.383-68.391c-0.367-63.986,24.09-95.746,49.983-129.369c24.568-31.903,49.829-64.7,49.458-122.113
- c32.513,28.827,61.257,63.03,82.822,98.877C357.576,219.35,371.715,271.615,367.153,318.449z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame.svg
deleted file mode 100644
index 4004d5ba..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flame.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M223.899,32c25.691,145-96.732,142-95.895,288c0.686,119.51,104.975,160,128.143,160c23.166,0,113.88-26,126.931-160
- C393.711,210.816,310.572,96,223.899,32z M256.147,472c0,0-40.701-35.816-40.701-80c0-44.183,40.555-80,40.555-80
- s40.332,35.817,40.332,80C296.332,436.184,256.147,472,256.147,472z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask-outline.svg
deleted file mode 100644
index 1b3faa07..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M436.912,370.441L320,175V48h16V32h-16.009H304v16v131.418l2.514,3.791l116.575,194.834
- c6.75,12.818,9.314,25.95,9.001,37.957c-0.243,9.339-1.958,17.938-6.545,25.569C417.076,455.666,402.33,464,384.981,464H129.093
- c-17.504,0-32.461-8.435-41.035-22.705c-11.897-19.801-10.889-38.145,2.275-63.139L181.821,224H240v-16h-48.683l14.687-24.756
- L208,179.4V176h48v-16h-48v-32h32v-16h-32V80h48V64h-48V48V32h-15.989H176v16h16v127L76.126,370.441
- C67.714,386.268,63.615,401.814,64.027,416c1.061,36.511,28.702,64,65.065,64h255.889c36.291,0,62.131-27.598,62.992-64
- C448.311,401.756,445.367,386.349,436.912,370.441z"/>
- <path d="M108.292,374.616c-6.907,10.542-10.936,24.095-10.936,33.55c0,27.584,15.82,39.834,45.682,39.834h225.932
- c29.804,0,44.975-15.711,45.681-39.959c0.277-9.488-3.143-22.729-10.086-33.324L332.729,256H179.5L108.292,374.616z M323.705,272
- l67.168,110.87l0.151,0.124l0.159,0.182c5.382,8.212,7.647,18.275,7.476,24.18c-0.229,7.839-2.477,13.98-6.683,17.795
- c-4.774,4.328-12.729,6.85-23.008,6.85H143.037c-11.064,0-19.27-2.236-23.73-5.996c-1.472-1.24-5.954-5.143-5.954-18.088
- c0-5.943,2.857-16.383,8.319-24.717l0.177-0.302l0.166-0.042L188.564,272H323.705z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask.svg
deleted file mode 100644
index 1a5e04ff..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flask.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M391.016,382.994l-0.15-0.124L323.7,272H188.554l-66.549,110.855l-0.166,0.042l-0.177,0.302
- c-5.461,8.334-8.319,18.773-8.319,24.717c0,12.945,4.481,16.848,5.954,18.088c4.46,3.76,12.667,5.996,23.731,5.996H368.96
- c10.278,0,18.232-2.521,23.007-6.85c4.205-3.814,6.454-9.956,6.683-17.795c0.172-5.904-2.093-15.968-7.476-24.18L391.016,382.994z"
- />
- <path d="M436.912,370.441L320,175V48h16V32H176v16h16v127L76.125,370.441C67.715,386.268,63.616,401.814,64.028,416
- c1.061,36.511,28.701,64,65.065,64h255.888c36.292,0,62.132-27.598,62.993-64C448.312,401.756,445.367,386.349,436.912,370.441z
- M208,64h48v16h-48V64z M208,112h32v16h-32V112z M208,160h48v16h-48V160z M191.261,208H240v16h-58.179L191.261,208z
- M414.64,408.041C413.934,432.289,398.763,448,368.96,448H143.027c-29.862,0-45.682-12.25-45.682-39.834
- c0-9.455,4.029-23.008,10.937-33.55L179.49,256h153.228l71.836,118.717C411.497,385.312,414.916,398.553,414.64,408.041z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower-outline.svg
deleted file mode 100644
index 83f58dd0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower-outline.svg
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M395.057,284.252c55.929,0,84.943-11.62,84.943-28.002s-29.016-28.003-84.943-28.003c-28.732,0-64.708,7.391-92.902,14.578
- c-0.975-3.419-2.305-6.688-3.973-9.75c25.009-14.852,55.645-35.05,75.947-55.353c39.547-39.547,52.023-68.458,40.44-80.042
- c-2.747-2.748-6.472-4.142-11.079-4.142c-14.818,0-38.796,14.415-68.963,44.582c-20.282,20.282-40.459,50.873-55.307,75.869
- c-3.062-1.696-6.33-3.062-9.755-4.062c7.175-28.17,14.535-64.059,14.535-92.735C284.002,61.266,272.382,32,256,32
- s-28.002,29.266-28.002,85.194c0,28.676,7.362,64.565,14.536,92.735c-3.425,1-6.693,2.365-9.755,4.062
- c-14.847-24.996-35.023-55.587-55.305-75.869C147.309,107.957,123.33,93.54,108.51,93.54c-4.609,0-8.331,1.394-11.079,4.142
- c-11.584,11.583,0.894,40.494,40.44,80.041c20.303,20.303,50.938,40.501,75.947,55.353c-1.668,3.062-2.999,6.331-3.974,9.75
- c-28.194-7.188-64.169-14.578-92.901-14.578C61.016,228.247,32,239.618,32,256s29.016,28.252,84.944,28.252
- c28.777,0,64.82-7.413,93.034-14.611c1.003,3.392,2.368,6.625,4.055,9.656c-25.048,14.863-55.801,35.119-76.161,55.479
- c-39.547,39.548-52.023,68.459-40.44,80.043c2.748,2.748,6.471,4.142,11.078,4.142c14.819,0,38.796-14.415,68.963-44.583
- c20.382-20.381,40.659-51.177,55.526-76.238c3.032,1.657,6.267,2.988,9.651,3.967c-7.211,28.238-14.654,64.367-14.654,93.201
- C227.998,451.234,239.618,480,256,480s28.002-28.766,28.002-84.693c0-28.834-7.441-64.963-14.652-93.201
- c3.385-0.979,6.618-2.31,9.65-3.967c14.867,25.062,35.145,55.857,55.527,76.239c30.164,30.165,54.144,44.582,68.963,44.582
- c4.608,0,8.33-1.394,11.078-4.142c11.584-11.584-0.894-40.495-40.439-80.043c-20.361-20.359-51.114-40.615-76.162-55.479
- c1.688-3.031,3.053-6.266,4.055-9.656C330.237,276.839,366.28,284.252,395.057,284.252z M319.992,254.941
- c30.144-7.014,55.893-10.694,75.064-10.694c21.329,0,39.453,1.806,52.41,5.222c9.705,2.559,14.005,5.317,15.736,6.781
- c-1.731,1.463-6.031,4.221-15.736,6.779c-12.958,3.416-31.081,5.223-52.41,5.223c-19.176,0-44.927-3.68-75.075-10.695
- L319.992,254.941z M345.841,149.436c35.382-35.383,52.682-39.412,56.818-39.846c-0.211,2.305-1.343,7.326-6.404,15.991
- c-6.786,11.62-18.35,25.738-33.439,40.828c-13.533,13.534-34.3,29.111-60.513,45.438c-0.619-0.648-1.25-1.283-1.895-1.904
- C316.732,183.729,332.309,162.968,345.841,149.436z M209.698,211.846c-26.213-16.326-46.979-31.904-60.512-45.437
- c-15.09-15.091-26.653-29.208-33.439-40.828c-5.061-8.665-6.194-13.687-6.404-15.992c4.138,0.435,21.436,4.463,56.818,39.845
- c13.533,13.533,29.108,34.295,45.433,60.507C210.948,210.563,210.316,211.198,209.698,211.846z M116.944,268.252
- c-21.339,0-39.483-1.845-52.471-5.335c-9.689-2.604-13.961-5.394-15.675-6.87c1.75-1.451,6.077-4.177,15.796-6.689
- c12.927-3.343,31.029-5.11,52.351-5.11c19.172,0,44.922,3.68,75.064,10.694l0.01,2.615
- C161.87,264.572,136.12,268.252,116.944,268.252z M166.16,363.064c-35.383,35.382-52.68,39.41-56.818,39.846
- c0.21-2.305,1.343-7.326,6.404-15.992c6.786-11.619,18.349-25.736,33.439-40.828c13.587-13.586,34.457-29.229,60.815-45.625
- c0.584,0.604,1.181,1.197,1.789,1.779C195.394,328.604,179.749,349.475,166.16,363.064z M302,300.465
- c26.356,16.395,47.227,32.037,60.814,45.625c15.091,15.092,26.653,29.209,33.439,40.828c5.062,8.666,6.193,13.688,6.403,15.992
- c-4.138-0.436-21.436-4.464-56.817-39.846c-13.589-13.59-29.234-34.463-45.63-60.82C300.818,301.663,301.415,301.068,302,300.465z
- M249.222,64.678c2.548-9.703,5.297-14.055,6.778-15.834c1.48,1.78,4.23,6.131,6.777,15.834
- c3.418,13.015,5.225,31.174,5.225,52.516c0,19.117-3.66,44.781-10.637,74.821h-2.73c-6.977-30.04-10.638-55.704-10.638-74.821
- C243.998,95.853,245.804,77.693,249.222,64.678z M262.782,447.612c-2.569,9.707-5.339,13.954-6.782,15.636
- c-1.444-1.682-4.212-5.929-6.782-15.636c-3.415-12.901-5.22-30.988-5.22-52.308c0-19.228,3.701-45.066,10.752-75.316h2.5
- c7.052,30.25,10.752,56.089,10.752,75.316C268.002,416.624,266.197,434.711,262.782,447.612z M256,288c-17.673,0-32-14.327-32-32
- s14.327-32,32-32s32,14.327,32,32S273.673,288,256,288z"/>
- <path d="M344.86,405.678c-24.529-17.674-48.394-51.732-48.394-51.732s7.031,41.059,1.854,75.946
- c11.678,21.779,26.139,35.253,36.643,35.253c1.749,0,3.432-0.324,5.042-0.976C351.879,459.372,354.39,439.185,344.86,405.678z
- M333.738,448.566c-2.738-1.46-9.407-6.369-18.992-22.27c0.688-7.872,1.098-16.337,1.219-25.282
- c5.012,4.88,9.947,9.437,14.747,13.613C335.816,434.408,334.954,444.779,333.738,448.566z"/>
- <path d="M213.679,82.608c-13.292-23.51-26.139-35.255-36.644-35.255c-1.749,0-3.431,0.325-5.042,0.976
- c-11.868,4.795-14.497,23.211-4.87,58.441c21.252,15.98,48.374,51.55,48.374,51.55S207.75,117.5,213.679,82.608z M196.038,111.369
- c-5.001-4.856-9.943-9.398-14.769-13.574c-5.084-19.731-4.223-30.082-3.008-33.863c2.737,1.459,9.407,6.369,18.994,22.27
- C196.568,94.04,196.161,102.466,196.038,111.369z"/>
- <path d="M82.357,298.568c-27.422,15.505-38.836,30.402-34.277,41.687c2.806,6.944,10.913,10.675,23.842,10.675
- c9.182,0,22.434-1.559,34.672-5.826c17.405-23.934,51.712-48.387,51.712-48.387S116.999,302.836,82.357,298.568z M97.637,330.956
- c-10.088,2.606-18.909,3.974-25.716,3.974c-4.092,0-6.733-0.502-8.223-0.97c1.477-2.755,6.407-9.411,22.253-18.966
- c7.872,0.689,16.338,1.099,25.284,1.22C106.365,321.218,101.815,326.15,97.637,330.956z"/>
- <path d="M463.92,172.245c-2.806-6.945-10.914-10.675-23.844-10.675c-9.178,0-21.4,1.715-34.654,5.822
- c-18.088,23.774-51.699,48.387-51.699,48.387s40.778-7.28,75.918-1.849C457.064,198.426,468.479,183.528,463.92,172.245z
- M426.047,197.504c-7.867-0.689-16.327-1.097-25.267-1.218c4.869-5.004,9.42-9.939,13.6-14.749
- c10.081-2.602,18.895-3.968,25.697-3.968c4.093,0,6.733,0.502,8.225,0.97C446.824,181.294,441.893,187.951,426.047,197.504z"/>
- <path d="M163.135,408.98c-8.42,30.34-5.956,48.938,5.244,53.69c1.674,0.711,3.437,1.066,5.275,1.066
- c11.107,0,24.698-13.124,39.528-39.015c-4.184-32.22,2.351-70.779,2.351-70.779S193.999,385.336,163.135,408.98z M174.981,447.207
- c-0.904-2.966-2.147-11.15,2.312-29.159c6.048-5.079,12.323-10.782,18.743-17.032c0.095,6.979,0.366,13.687,0.81,20.039
- C186.466,438.66,178.52,445.39,174.981,447.207z"/>
- <path d="M343.622,49.826c-1.674-0.71-3.438-1.066-5.274-1.066c-11.105,0-26.207,14.287-39.527,39.013
- c4.514,22.894-2.393,71.053-2.393,71.053s23.239-34.326,52.342-54.956C357.167,72,354.865,54.599,343.622,49.826z M334.627,94.781
- c-6.029,5.051-12.277,10.72-18.66,16.931c-0.092-7.062-0.364-13.846-0.812-20.269c10.379-17.607,18.327-24.336,21.864-26.153
- C337.93,68.274,339.186,76.541,334.627,94.781z"/>
- <path d="M103.209,163.367C93,159.5,80.717,158.366,72.457,158.366c-12.267,0-20.042,3.573-22.881,10.261
- c-5.004,11.792,9.97,29.985,37.948,44.805c29.726-3.932,70.688,2.336,70.688,2.336S121,187.067,103.209,163.367z M65.034,175.215
- c1.381-0.414,3.775-0.848,7.424-0.848c5.815,0,13.242,1.088,21.687,3.165c5.077,6.049,10.781,12.33,17.034,18.754
- c-6.959,0.096-13.648,0.367-19.984,0.81C73.563,186.7,66.84,178.745,65.034,175.215z"/>
- <path d="M424.477,299.066c-25.307,5.6-70.78-2.35-70.78-2.35s34.638,25.615,55.014,52.393c11.959,4.223,22.555,5.022,30.833,5.022
- c12.266,0,20.041-3.573,22.88-10.261C467.428,332.08,454.283,315.801,424.477,299.066z M439.542,338.132
- c-5.833,0-13.287-1.095-21.765-3.185c-5.078-6.053-10.774-12.326-17.013-18.734c6.98-0.095,13.688-0.365,20.041-0.811
- c17.631,10.396,24.354,18.352,26.158,21.882C445.585,337.697,443.19,338.132,439.542,338.132z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower.svg
deleted file mode 100644
index 38029b5b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-flower.svg
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M395.057,228.247c-28.651,0-64.502,7.35-92.66,14.518c-0.98-3.443-2.321-6.734-4.001-9.817
- c24.97-14.84,55.487-34.98,75.733-55.224c39.547-39.547,52.023-68.458,40.44-80.042c-11.584-11.583-40.495,0.893-80.042,40.44
- c-20.225,20.225-40.343,50.698-55.178,75.654c-3.082-1.708-6.373-3.083-9.822-4.089c7.156-28.133,14.475-63.897,14.475-92.492
- C284.002,61.266,272.382,32,256,32s-28.002,29.266-28.002,85.194c0,28.595,7.319,64.359,14.475,92.492
- c-3.449,1.006-6.74,2.381-9.822,4.089c-14.835-24.956-34.953-55.43-55.176-75.653c-39.548-39.547-68.458-52.024-80.042-40.44
- c-11.584,11.583,0.894,40.494,40.44,80.041c20.246,20.244,50.762,40.384,75.732,55.224c-1.68,3.083-3.021,6.374-4.001,9.817
- c-28.158-7.168-64.008-14.518-92.659-14.518C61.016,228.247,32,239.618,32,256s29.016,28.252,84.944,28.252
- c28.697,0,64.613-7.371,92.792-14.551c1.01,3.414,2.384,6.671,4.083,9.724c-25.009,14.852-55.645,35.049-75.946,55.351
- c-39.547,39.548-52.023,68.459-40.44,80.043c11.584,11.584,40.495-0.895,80.042-40.441c20.323-20.323,40.542-51.001,55.398-76.024
- c3.053,1.671,6.31,3.01,9.718,3.995c-7.192,28.203-14.592,64.207-14.592,92.959c0,55.929,11.62,84.693,28.002,84.693
- s28.002-28.766,28.002-84.693c0-28.752-7.4-64.756-14.592-92.959c3.408-0.985,6.665-2.324,9.718-3.995
- c14.855,25.023,35.073,55.701,55.399,76.025c39.547,39.547,68.457,52.024,80.041,40.44s-0.894-40.495-40.439-80.043
- c-20.304-20.302-50.938-40.499-75.947-55.351c1.699-3.053,3.073-6.31,4.083-9.724c28.18,7.18,64.096,14.551,92.792,14.551
- c55.929,0,84.943-11.62,84.943-28.002S450.984,228.247,395.057,228.247z"/>
- <path d="M296.467,353.945c0,0,7.031,41.059,1.854,75.946c11.678,21.779,26.139,35.253,36.643,35.253
- c1.749,0,3.432-0.324,5.042-0.976c11.874-4.797,14.385-24.984,4.855-58.491C320.331,388.004,296.467,353.945,296.467,353.945z"/>
- <path d="M215.497,158.32c0,0-7.747-40.82-1.818-75.712c-13.292-23.51-26.139-35.255-36.644-35.255
- c-1.749,0-3.431,0.325-5.042,0.976c-11.868,4.795-14.497,23.211-4.87,58.441C188.375,122.75,215.497,158.32,215.497,158.32z"/>
- <path d="M158.306,296.717c0,0-41.308,6.119-75.949,1.852c-27.422,15.505-38.836,30.402-34.277,41.687
- c2.806,6.944,10.913,10.675,23.842,10.675c9.182,0,22.434-1.559,34.672-5.826C123.999,321.17,158.306,296.717,158.306,296.717z"/>
- <path d="M353.723,215.779c0,0,40.778-7.28,75.918-1.849c27.424-15.504,38.838-30.402,34.279-41.685
- c-2.806-6.945-10.914-10.675-23.844-10.675c-9.178,0-21.4,1.715-34.654,5.822C387.334,191.166,353.723,215.779,353.723,215.779z"/>
- <path d="M163.135,408.98c-8.42,30.34-5.956,48.938,5.244,53.69c1.674,0.711,3.437,1.066,5.275,1.066
- c11.107,0,24.698-13.124,39.528-39.015c-4.184-32.22,2.351-70.779,2.351-70.779S193.999,385.336,163.135,408.98z"/>
- <path d="M348.77,103.87c8.397-31.87,6.096-49.271-5.147-54.044c-1.674-0.71-3.438-1.066-5.274-1.066
- c-11.105,0-26.207,14.287-39.527,39.013c4.514,22.894-2.393,71.053-2.393,71.053S319.667,124.5,348.77,103.87z"/>
- <path d="M87.524,213.432c29.726-3.932,70.688,2.336,70.688,2.336S121,187.067,103.209,163.367
- C93,159.5,80.717,158.366,72.457,158.366c-12.267,0-20.042,3.573-22.881,10.261C44.572,180.419,59.546,198.612,87.524,213.432z"/>
- <path d="M424.477,299.066c-25.307,5.6-70.78-2.35-70.78-2.35s34.638,25.615,55.014,52.393c11.959,4.223,22.555,5.022,30.833,5.022
- c12.266,0,20.041-3.573,22.88-10.261C467.428,332.08,454.283,315.801,424.477,299.066z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder-outline.svg
deleted file mode 100644
index c337acbe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M457,96H215c-2.791,0-4.271-0.585-6.094-2.408l-22.501-22.501l-0.168-0.162C181.365,66.333,177.361,64,169,64H57
- c-13.785,0-25,10.317-25,23v336c0,13.317,11.683,25,25,25h400c12.683,0,23-11.215,23-25V119C480,105.673,470.327,96,457,96z M57,80
- h112c3.497,0,3.737,0.189,6.175,2.488l22.417,22.418c4.84,4.84,10.372,7.094,17.408,7.094h242c4.448,0,7,2.552,7,7v42.376
- c-2.504-0.888-5.195-1.376-8-1.376H56c-2.805,0-5.496,0.488-8,1.376V87C48,82.677,52.672,80,57,80z M464,423c0,4.328-2.677,9-7,9H57
- c-4.458,0-9-4.542-9-9V184c0-4.411,3.589-8,8-8h400c4.411,0,8,3.589,8,8V423z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder.svg
deleted file mode 100644
index bd31bf59..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-folder.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M472,176H40c-4.411,0-8,3.589-8,8v239c0,13.317,11.683,25,25,25h400c12.683,0,23-11.215,23-25V184
- C480,179.589,476.411,176,472,176z"/>
- <path d="M457,96H215c-2.791,0-4.271-0.585-6.094-2.408l-22.501-22.501l-0.168-0.162C181.365,66.333,177.361,64,169,64H57
- c-13.785,0-25,10.317-25,23v74.376c2.504-0.888,5.195-1.376,8-1.376h432c2.805,0,5.496,0.488,8,1.376V119
- C480,105.673,470.327,96,457,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football-outline.svg
deleted file mode 100644
index 23844844..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C141.137,48,48,141.136,48,256c0,114.864,93.137,208,208,208c114.872,0,208-93.138,208-208
- C464,141.138,370.87,48,256,48z M297.151,442.179c-13.514,2.657-30.327,4.187-44,4.45c-13.198-0.195-26.074-1.735-38.5-4.493
- c-2.144-0.549-4.383-1.138-6.805-1.777l-24.417-65.435L203.074,336h105.854l0.57,1.076l19.34,38.852L305.22,440.21
- C302.553,440.924,299.862,441.579,297.151,442.179z M89.317,163.522l18.188,52.284l0.175,0.504L65.376,252.92
- C65.892,220.535,74.52,190.088,89.317,163.522z M189.578,77.28L247,116.576v58.147l-70.997,60.067L126.6,212.28l-4.167-1.899
- l-22.332-64.019C122.11,115.158,153.239,90.83,189.578,77.28z M325.025,247.206l0.921,0.765L307.569,320H204.431l-18.485-72.453
- l0.445-0.376l68.873-58.27L325.025,247.206z M446.626,252.921l-42.454-36.738l0.127-0.364l18.298-52.451
- C437.447,189.972,446.109,220.473,446.626,252.921z M411.564,146.067l-22.432,64.483l-53.992,24.388L264,174.723v-58.147
- l57.596-39.415C357.958,90.644,389.501,114.913,411.564,146.067z M66.144,273.414l53.756-46.518l49.539,22.599l0.559,0.255
- l19.718,77.287l-20.433,38.529l-69.86-0.915C81.075,338.291,69.209,307.105,66.144,273.414z M342.719,365.565l-20.434-38.529
- l19.752-77.416l49.997-22.781l53.822,46.575c-3.065,33.691-14.932,64.877-33.277,91.236L342.719,365.565z M255.257,102.67
- l-46.126-31.498c15-3.806,30.701-5.836,46.869-5.835c15.961,0,31.466,1.982,46.293,5.694L255.257,102.67z M166.423,381.529
- l0.848,2.511l19.946,49.781c-29.239-11.351-55.011-29.704-75.232-53.006L166.423,381.529z M324.563,433.904l17.934-48.608
- l1.627-3.748l55.892-0.732C379.744,404.175,353.893,422.562,324.563,433.904z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football.svg
deleted file mode 100644
index 34151ac0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-football.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,48C141.137,48,48,141.136,48,256c0,114.864,93.137,208,208,208c114.872,0,208-93.138,208-208
- C464,141.138,370.87,48,256,48z M297.151,442.179c-13.514,2.657-30.327,4.187-44,4.45c-13.198-0.195-26.074-1.735-38.5-4.493
- c-2.144-0.549-4.383-1.138-6.805-1.777l-24.417-65.435L203.074,336h105.854l0.57,1.076l19.34,38.852L305.22,440.21
- C302.553,440.924,299.862,441.579,297.151,442.179z M189.578,77.28L247,116.576v58.147l-70.997,60.067L126.6,212.28l-4.167-1.899
- l-22.332-64.019C122.11,115.158,153.239,90.83,189.578,77.28z M411.564,146.067l-22.432,64.483l-53.992,24.388L264,174.723v-58.147
- l57.596-39.415C357.958,90.644,389.501,114.913,411.564,146.067z M66.144,273.414l53.756-46.518l49.539,22.599l0.559,0.255
- l19.718,77.287l-20.433,38.529l-69.86-0.915C81.075,338.291,69.209,307.105,66.144,273.414z M342.719,365.565l-20.434-38.529
- l19.752-77.416l49.997-22.781l53.822,46.575c-3.065,33.691-14.932,64.877-33.277,91.236L342.719,365.565z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a-outline.svg
deleted file mode 100644
index 9721587c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a-outline.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M194.822,240H160v-34.762c0-2.817-2.604-5.238-5.303-5.238h-22.145c-2.698,0-4.552,2.372-4.552,5.178V240H92.533
- c-2.615,0-4.533,2.143-4.533,4.771v21.427c0,2.698,2.031,5.803,4.861,5.803H128v35.467c0,2.615,2.143,4.533,4.771,4.533h21.427
- c2.698,0,5.803-2.031,5.803-4.861V272h34.762c2.817,0,5.238-2.604,5.238-5.303v-22.145C200,241.854,197.628,240,194.822,240z"/>
- <path d="M362.314,279.063c-10.736,0-19.451,8.515-19.451,19.153c0,10.555,8.715,19.084,19.451,19.084
- c10.783,0,19.498-8.529,19.498-19.084C381.812,287.578,373.098,279.063,362.314,279.063z"/>
- <path d="M319.766,237.165c-10.736,0-19.451,8.603-19.451,19.168c0,10.566,8.715,19.153,19.451,19.153
- c10.783,0,19.498-8.587,19.498-19.153C339.264,245.768,330.549,237.165,319.766,237.165z"/>
- <path d="M404.862,237.165c-10.729,0-19.442,8.603-19.442,19.168c0,10.566,8.714,19.153,19.442,19.153
- c10.737,0,19.452-8.587,19.452-19.153C424.314,245.768,415.6,237.165,404.862,237.165z"/>
- <path d="M362.314,195.301c-10.736,0-19.451,8.602-19.451,19.169c0,10.566,8.715,19.146,19.451,19.146
- c10.783,0,19.498-8.579,19.498-19.146C381.812,203.902,373.098,195.301,362.314,195.301z"/>
- </g>
- <path d="M369.269,162c25.838,0,49.704,9.314,67.204,26.229C454.225,205.386,464,229.247,464,255.418
- c0,26.303-9.806,50.405-27.611,67.869c-17.563,17.226-41.4,26.713-67.12,26.713H142.739c-25.712,0-49.548-9.487-67.117-26.715
- C57.81,305.818,48,281.717,48,255.418c0-26.167,9.78-50.028,27.539-67.188C93.043,171.315,116.909,162,142.739,162H369.269
- M369.269,146H142.739C81.541,146,32,191.458,32,255.418C32,319.419,81.541,366,142.739,366h226.529
- C430.49,366,480,319.419,480,255.418C480,191.458,430.49,146,369.269,146L369.269,146z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a.svg
deleted file mode 100644
index db7240be..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-a.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M369.269,146H142.739C81.541,146,32,191.458,32,255.418C32,319.419,81.541,366,142.739,366h226.529
- C430.49,366,480,319.419,480,255.418C480,191.458,430.49,146,369.269,146z M200,266.697c0,2.698-2.421,5.303-5.238,5.303H160
- v35.139c0,2.83-3.104,4.861-5.803,4.861h-21.427c-2.628,0-4.771-1.918-4.771-4.533V272H92.861c-2.83,0-4.861-3.104-4.861-5.803
- v-21.427c0-2.628,1.918-4.771,4.533-4.771H128v-34.822c0-2.806,1.854-5.178,4.553-5.178h22.145c2.698,0,5.303,2.421,5.303,5.238
- V240h34.822c2.806,0,5.178,1.854,5.178,4.553V266.697z M319.766,275.486c-10.736,0-19.451-8.587-19.451-19.153
- c0-10.565,8.715-19.168,19.451-19.168c10.783,0,19.498,8.603,19.498,19.168C339.264,266.899,330.549,275.486,319.766,275.486z
- M362.314,317.301c-10.736,0-19.451-8.529-19.451-19.084c0-10.639,8.715-19.153,19.451-19.153c10.783,0,19.498,8.515,19.498,19.153
- C381.812,308.771,373.098,317.301,362.314,317.301z M362.314,233.615c-10.736,0-19.451-8.579-19.451-19.146
- c0-10.567,8.715-19.169,19.451-19.169c10.783,0,19.498,8.602,19.498,19.169C381.812,225.036,373.098,233.615,362.314,233.615z
- M404.862,275.486c-10.729,0-19.442-8.587-19.442-19.153c0-10.565,8.714-19.168,19.442-19.168c10.737,0,19.452,8.603,19.452,19.168
- C424.314,266.899,415.6,275.486,404.862,275.486z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b-outline.svg
deleted file mode 100644
index e462f00c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b-outline.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M308.076,203.929c-11.058,0-20.076,9.014-20.076,20.104c0,11.089,9.019,20.107,20.076,20.107
- c11.131,0,20.148-9.019,20.148-20.107C328.225,212.942,319.207,203.929,308.076,203.929z"/>
- <path d="M351.988,247.878c-11.058,0-20.053,8.949-20.053,20.106c0,11.064,8.995,20.016,20.053,20.016
- c11.146,0,20.148-8.951,20.148-20.016C372.137,256.827,363.134,247.878,351.988,247.878z"/>
- <path d="M135.234,184.367C113.594,184.367,96,202.17,96,224.01c0,21.865,17.594,39.623,39.234,39.623
- c21.655,0,39.249-17.758,39.249-39.623C174.483,202.17,156.89,184.367,135.234,184.367z M135.123,243.457
- c-10.688,0-19.343-8.721-19.343-19.447c0-10.725,8.655-19.441,19.343-19.441c10.641,0,19.297,8.717,19.297,19.441
- C154.42,234.736,145.764,243.457,135.123,243.457z"/>
- <path d="M351.988,160c-11.058,0-20.053,9.014-20.053,20.107c0,11.09,8.995,20.083,20.053,20.083
- c11.146,0,20.148-8.993,20.148-20.083C372.137,169.014,363.134,160,351.988,160z"/>
- <path d="M395.947,203.929c-11.105,0-20.101,9.014-20.101,20.104c0,11.089,8.995,20.107,20.101,20.107
- c11.059,0,20.053-9.019,20.053-20.107C416,212.942,407.006,203.929,395.947,203.929z"/>
- </g>
- <path d="M466.279,248.866c-21.157-88.471-43.631-135.489-88.454-148.83C368.06,97.135,359.748,96,352.076,96
- c-27.598,0-46.938,14.683-96.08,14.683c-49.174,0-68.502-14.681-96.062-14.683c-7.665,0-15.963,1.135-25.721,4.036
- c-44.869,13.341-67.342,60.359-88.461,148.83c-21.181,88.473-17.334,152.363,7.679,164.289C57.502,415.1,61.662,416,65.885,416
- c21.694,0,45.139-23.838,67.659-52.047C159.198,331.848,165.658,331,243.822,331h24.343c78.147,0,84.628,0.846,110.282,32.953
- c22.526,28.207,45.97,52.004,67.665,52.004c4.226,0,8.384-0.879,12.457-2.823C483.574,401.208,487.421,337.339,466.279,248.866z
- M451.677,398.716c-1.835,0.876-3.604,1.284-5.564,1.284c-6.022,0-14.077-4.049-23.295-11.708
- c-9.181-7.63-19.307-18.509-31.87-34.239c-12.959-16.22-23.667-28.229-43.528-33.949c-16.647-4.793-38.624-5.104-79.254-5.104
- h-24.343c-40.633,0-62.611,0.311-79.259,5.105c-19.853,5.719-30.56,17.685-43.523,33.908
- c-12.556,15.727-22.68,26.627-31.862,34.258c-9.216,7.658-17.27,11.718-23.293,11.718c-1.932,0-3.751-0.415-5.568-1.282
- c-9.556-4.557-22.572-47.673,0.998-146.129c21.387-89.591,42.381-126.777,77.459-137.207c7.633-2.27,14.554-3.372,21.159-3.372
- c9.742,0,18.599,2.317,29.812,5.249c16.07,4.203,36.072,9.435,66.252,9.435c30.148,0,50.146-5.228,66.215-9.429
- c11.229-2.936,20.1-5.254,29.865-5.254c6.618,0,13.551,1.104,21.185,3.371c35.037,10.428,56.03,47.617,77.456,137.214
- C474.244,351.041,461.23,394.16,451.677,398.716z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b.svg
deleted file mode 100644
index 97fdcaee..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-game-controller-b.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M135.123,204.568c-10.688,0-19.343,8.717-19.343,19.441c0,10.727,8.655,19.447,19.343,19.447
- c10.641,0,19.297-8.721,19.297-19.447C154.42,213.285,145.764,204.568,135.123,204.568z"/>
- <path d="M466.279,248.866c-21.157-88.471-43.631-135.489-88.454-148.83C368.06,97.135,359.748,96,352.076,96
- c-27.598,0-46.938,14.683-96.08,14.683c-49.174,0-68.502-14.681-96.062-14.683c-7.665,0-15.963,1.135-25.721,4.036
- c-44.869,13.341-67.342,60.359-88.461,148.83c-21.181,88.473-17.334,152.363,7.679,164.289C57.502,415.1,61.662,416,65.885,416
- c21.694,0,45.139-23.838,67.659-52.047C159.198,331.848,165.658,331,243.822,331h24.343c78.147,0,84.628,0.846,110.282,32.953
- c22.526,28.207,45.97,52.004,67.665,52.004c4.226,0,8.384-0.879,12.457-2.823C483.574,401.208,487.421,337.339,466.279,248.866z
- M135.234,263.633C113.594,263.633,96,245.875,96,224.01c0-21.84,17.594-39.643,39.234-39.643
- c21.655,0,39.249,17.803,39.249,39.643C174.483,245.875,156.89,263.633,135.234,263.633z M308.076,244.14
- c-11.058,0-20.076-9.019-20.076-20.107c0-11.09,9.019-20.104,20.076-20.104c11.131,0,20.148,9.014,20.148,20.104
- C328.225,235.121,319.207,244.14,308.076,244.14z M351.988,288c-11.058,0-20.053-8.951-20.053-20.016
- c0-11.157,8.995-20.106,20.053-20.106c11.146,0,20.148,8.949,20.148,20.106C372.137,279.049,363.134,288,351.988,288z
- M351.988,200.19c-11.058,0-20.053-8.993-20.053-20.083c0-11.094,8.995-20.107,20.053-20.107c11.146,0,20.148,9.014,20.148,20.107
- C372.137,191.197,363.134,200.19,351.988,200.19z M395.947,244.14c-11.105,0-20.101-9.019-20.101-20.107
- c0-11.09,8.995-20.104,20.101-20.104c11.059,0,20.053,9.014,20.053,20.104C416,235.121,407.006,244.14,395.947,244.14z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear-outline.svg
deleted file mode 100644
index e5473bc4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear-outline.svg
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M256.9,159.9c-25.701,0-49.801,10-67.9,28.1s-28.1,42.199-28.1,67.9c0,25.699,10,49.699,28.1,67.9
- c18.1,18.1,42.301,28.1,67.9,28.1c25.699,0,49.799-10,67.9-28.1c18.1-18.102,28.1-42.201,28.1-67.9c0-25.701-10-49.701-28.1-67.9
- C306.699,169.9,282.6,159.9,256.9,159.9z M256.9,335.9c-44.301,0-80-35.9-80-80c0-44.101,35.699-80,80-80
- c44.299,0,80,35.899,80,80C336.9,300,301.199,335.9,256.9,335.9z"/>
- </g>
- <g>
- <path d="M201.787,82.828c4.458,6.628,10.119,12.406,16.775,17.069c11.012,7.715,23.957,11.793,37.438,11.793
- c13.481,0,26.428-4.078,37.439-11.793c6.654-4.663,12.316-10.441,16.773-17.068c10.326,3.228,20.334,7.378,29.927,12.411
- c-1.532,7.84-1.614,15.93-0.203,23.933c2.333,13.235,8.604,25.269,18.133,34.798c12.335,12.336,28.737,19.129,46.185,19.129
- c4.242,0,8.424-0.399,12.52-1.195c5.032,9.6,9.181,19.613,12.405,29.947c-6.622,4.46-12.396,10.121-17.054,16.776
- c-7.705,11.008-11.777,23.946-11.776,37.418c0,13.467,4.069,26.401,11.768,37.406c4.653,6.651,10.421,12.312,17.036,16.771
- c-3.232,10.34-7.387,20.354-12.428,29.957c-4.081-0.789-8.246-1.187-12.472-1.187c-17.448,0-33.85,6.795-46.183,19.131
- c-9.515,9.514-15.781,21.527-18.123,34.74c-1.415,7.988-1.343,16.065,0.176,23.895c-9.607,5.04-19.627,9.192-29.967,12.421
- c-4.461-6.61-10.121-12.374-16.771-17.022c-11-7.689-23.928-11.754-37.386-11.754c-13.457,0-26.385,4.064-37.385,11.755
- c-6.649,4.648-12.31,10.412-16.771,17.021c-10.339-3.228-20.359-7.381-29.966-12.42c1.519-7.829,1.591-15.906,0.176-23.895
- c-2.342-13.214-8.608-25.228-18.123-34.741c-12.335-12.336-28.737-19.13-46.185-19.13c-4.226,0-8.39,0.396-12.471,1.187
- c-5.04-9.602-9.195-19.618-12.428-29.958c6.615-4.46,12.383-10.119,17.036-16.771c7.699-11.004,11.769-23.939,11.769-37.408
- c0-13.471-4.072-26.41-11.777-37.418c-4.658-6.654-10.432-12.316-17.054-16.776c3.225-10.333,7.372-20.346,12.405-29.946
- c4.096,0.796,8.277,1.196,12.521,1.196c17.446,0,33.849-6.794,46.185-19.13c9.529-9.53,15.799-21.563,18.133-34.799
- c1.411-8.003,1.33-16.093-0.203-23.932C181.455,90.207,191.461,86.057,201.787,82.828 M302.074,64
- C294.971,82.529,277.027,95.69,256,95.69c-21.025,0-38.969-13.161-46.073-31.69c-20.466,4.895-39.692,12.973-57.128,23.688
- c8.068,18.122,4.682,40.104-10.182,54.97c-9.631,9.631-22.25,14.443-34.87,14.443c-6.854,0-13.706-1.419-20.083-4.255
- C76.958,170.284,68.887,189.517,64,209.984c18.51,7.112,31.652,25.049,31.652,46.062c0,21.008-13.133,38.936-31.631,46.054
- c4.898,20.466,12.977,39.692,23.693,57.128c6.36-2.821,13.197-4.232,20.031-4.232c12.621,0,25.238,4.812,34.871,14.443
- c14.841,14.841,18.238,36.781,10.215,54.889c17.438,10.71,36.664,18.783,57.131,23.673c7.127-18.479,25.046-31.596,46.037-31.596
- c20.992,0,38.91,13.115,46.037,31.596c20.468-4.89,39.693-12.964,57.132-23.675c-8.023-18.106-4.626-40.046,10.216-54.887
- c9.629-9.632,22.248-14.444,34.868-14.444c6.836,0,13.67,1.411,20.033,4.233c10.716-17.436,18.794-36.662,23.692-57.128
- c-18.498-7.118-31.63-25.048-31.63-46.054c-0.001-21.013,13.143-38.948,31.651-46.062c-4.887-20.466-12.957-39.7-23.664-57.139
- c-6.375,2.836-13.23,4.254-20.082,4.254c-12.621,0-25.238-4.811-34.871-14.442c-14.863-14.863-18.248-36.846-10.18-54.97
- C341.768,76.973,322.54,68.895,302.074,64L302.074,64z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear.svg
deleted file mode 100644
index 857d91ed..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-gear.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M416.349,256.046c-0.001-21.013,13.143-38.948,31.651-46.062c-4.887-20.466-12.957-39.7-23.664-57.139
- c-6.375,2.836-13.23,4.254-20.082,4.254c-12.621,0-25.238-4.811-34.871-14.442c-14.863-14.863-18.248-36.846-10.18-54.97
- C341.768,76.973,322.54,68.895,302.074,64C294.971,82.529,277.027,95.69,256,95.69c-21.025,0-38.969-13.161-46.073-31.69
- c-20.466,4.895-39.693,12.973-57.128,23.688c8.068,18.122,4.683,40.104-10.181,54.97c-9.631,9.631-22.25,14.443-34.871,14.443
- c-6.854,0-13.706-1.419-20.083-4.255C76.958,170.284,68.886,189.517,64,209.984c18.509,7.112,31.652,25.049,31.652,46.062
- c0,21.008-13.132,38.936-31.63,46.054c4.898,20.466,12.976,39.692,23.692,57.128c6.361-2.821,13.198-4.232,20.032-4.232
- c12.622,0,25.239,4.812,34.871,14.443c14.841,14.841,18.239,36.781,10.215,54.889c17.438,10.71,36.664,18.783,57.13,23.673
- c7.128-18.479,25.046-31.596,46.038-31.596c20.992,0,38.91,13.115,46.037,31.596c20.468-4.89,39.693-12.964,57.132-23.675
- c-8.023-18.106-4.626-40.046,10.216-54.887c9.629-9.632,22.248-14.444,34.868-14.444c6.836,0,13.67,1.411,20.033,4.233
- c10.716-17.436,18.794-36.662,23.692-57.128C429.48,294.981,416.349,277.052,416.349,256.046z M256.9,335.9c-44.3,0-80-35.9-80-80
- c0-44.101,35.7-80,80-80c44.299,0,80,35.899,80,80C336.9,300,301.199,335.9,256.9,335.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses-outline.svg
deleted file mode 100644
index e492b987..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M465.4,247c-2.2-22-12.4-43-28.9-58.4c-17.1-15.9-39.3-24.7-62.7-24.7c-41.5,0-77.3,27.4-88.5,67c-7-7-18.5-11.7-29.3-11.7
- c-10.8,0-22.3,4.7-29.3,11.7c-11.2-39.6-47-67-88.5-67c-23.3,0-45.6,8.7-62.7,24.6C59,204,48.8,225,46.6,247H32v18h14.6
- c2.2,22,12.4,43,28.9,58.4c17.1,15.9,39.3,24.7,62.7,24.7c50.8,0,92.1-41.2,92.1-92c0-0.1,0-0.1,0-0.1h0c0-9.9,11.5-21.6,25.7-21.6
- s25.7,11.7,25.7,21.6h0c0,0,0,0,0,0.1c0,50.8,41.3,92,92.1,92c23.3,0,45.6-8.7,62.7-24.7c16.5-15.4,26.7-36.5,28.9-58.5H480v-18
- H465.4z M373.8,333c-42.5,0-77-34.6-77-77c0-42.5,34.6-77,77-77c42.5,0,77,34.6,77,77C450.8,298.5,416.3,333,373.8,333z M138.2,333
- c-42.5,0-77-34.6-77-77c0-42.5,34.6-77,77-77c42.5,0,77,34.6,77,77C215.2,298.5,180.7,333,138.2,333z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses.svg
deleted file mode 100644
index 0bf51ee9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-glasses.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M465.4,247c-2.2-22-12.4-43-28.9-58.4c-17.1-15.9-39.3-24.7-62.7-24.7c-41.5,0-77.3,27.4-88.5,67c-7-7-18.5-11.7-29.3-11.7
- c-10.8,0-22.3,4.7-29.3,11.7c-11.2-39.6-47-67-88.5-67c-23.3,0-45.6,8.7-62.7,24.6C59,204,48.8,225,46.6,247H32v18h14.6
- c2.2,22,12.4,43,28.9,58.4c17.1,15.9,39.3,24.7,62.7,24.7c50.8,0,92.1-41.2,92.1-92c0-0.1,0-0.1,0-0.1h0c0-9.9,11.5-21.6,25.7-21.6
- s25.7,11.7,25.7,21.6h0c0,0,0,0,0,0.1c0,50.8,41.3,92,92.1,92c23.3,0,45.6-8.7,62.7-24.7c16.5-15.4,26.7-36.5,28.9-58.5H480v-18
- H465.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view-outline.svg
deleted file mode 100644
index 86f4b545..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,192v-16H336V64h-16v112H192V64h-16v112H64v16h112v128H64v16h112v112h16V336h128v112h16V336h112v-16H336V192H448z
- M320,320H192V192h128V320z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view.svg
deleted file mode 100644
index e384d4b1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-grid-view.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="192" y="192" width="128" height="128"/>
- <path d="M64,64v384h384V64H64z M416,192h-80v128h80v16h-80v80h-16v-80H192v80h-16v-80H96v-16h80V192H96v-16h80V96h16v80h128V96h16
- v80h80V192z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart-outline.svg
deleted file mode 100644
index 227163dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M359.385,80C319.966,80,277.171,97.599,256,132.8C234.83,97.599,192.034,80,152.615,80C83.647,80,32,123.238,32,195.779
- c0,31.288,12.562,71.924,40.923,105.657c28.359,33.735,45.229,51.7,100.153,88C228,425.738,256,432,256,432s28-6.262,82.924-42.564
- c54.923-36.3,71.794-54.265,100.153-88C467.438,267.703,480,227.067,480,195.779C480,123.238,428.353,80,359.385,80z
- M426.83,291.141c-26.852,31.94-42.18,48.895-96.729,84.947c-40.237,26.596-65.252,36.301-74.102,39.233
- c-8.85-2.933-33.864-12.639-74.102-39.233c-54.548-36.052-69.876-53.006-96.729-84.948c-12.065-14.351-21.857-31.274-28.316-48.943
- C51.062,226.355,48,210.304,48,195.779c0-30.284,10.131-55.643,29.297-73.335c9.14-8.437,20.158-14.992,32.752-19.484
- C122.994,98.341,137.315,96,152.615,96c38.018,0,73.217,17.682,89.674,45.046L256,163.844l13.711-22.798
- C286.169,113.682,321.368,96,359.385,96c15.3,0,29.621,2.341,42.566,6.959c12.594,4.493,23.612,11.048,32.752,19.484
- C453.869,140.136,464,165.495,464,195.779c0,14.525-3.062,30.576-8.854,46.418C448.688,259.865,438.896,276.789,426.83,291.141z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart.svg
deleted file mode 100644
index 73b087ae..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-heart.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M359.385,80C319.966,80,277.171,97.599,256,132.8C234.83,97.599,192.034,80,152.615,80C83.647,80,32,123.238,32,195.779
- c0,31.288,12.562,71.924,40.923,105.657c28.359,33.735,45.229,51.7,100.153,88C228,425.738,256,432,256,432s28-6.262,82.924-42.564
- c54.923-36.3,71.794-54.265,100.153-88C467.438,267.703,480,227.067,480,195.779C480,123.238,428.353,80,359.385,80z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-empty.svg
deleted file mode 100644
index a1ec8ddd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-empty.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M260.3,366c-9.4,0-17-7.5-17-16.9c0-9.3,7.6-16.8,17-16.8c9.4,0,17,7.5,17,16.8C277.3,358.5,269.7,366,260.3,366z
- M294.1,250.7c-22.8,22.5-22.2,27.4-23.3,53.3h-19c1.1-28.5,7.5-43.7,30.1-64.5c11-10.3,19.4-22.7,19.4-38.1
- c0-23.6-19.4-39.9-42.6-39.9c-32.4,0-48.5,16.4-47.9,46.4H192c0.3-42,24.4-62.1,67.6-62.1c33,0,60.4,20.4,60.4,54.6
- C320,222.3,309.3,236.6,294.1,250.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-outline.svg
deleted file mode 100644
index 63574389..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M256,446.7c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
- </g>
- <g>
- <path d="M259.6,146c-43.2,0-67.3,20.3-67.6,62.2h18.8c-0.6-30.4,15.5-46.5,47.9-46.5c23.2,0,42.6,16.2,42.6,39.8
- c0,15.3-8.3,27.7-19.4,38.1c-22.6,20.8-29,36-30.1,64.5h19c1.1-25.8,0.5-30.7,23.3-53.3c15.2-14.2,25.9-28.3,25.9-50.2
- C320,166.4,292.6,146,259.6,146z"/>
- <path d="M260.3,332.3c-9.4,0-17,7.5-17,16.8c0,9.3,7.6,16.9,17,16.9c9.4,0,17-7.5,17-16.9C277.3,339.8,269.7,332.3,260.3,332.3z"
- />
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help.svg
deleted file mode 100644
index acc21edf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-help.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M260.3,366c-9.4,0-17-7.5-17-16.9c0-9.3,7.6-16.8,17-16.8c9.4,0,17,7.5,17,16.8C277.3,358.5,269.7,366,260.3,366z M294.1,250.7
- c-22.8,22.5-22.2,27.4-23.3,53.3h-19c1.1-28.5,7.5-43.7,30.1-64.5c11-10.3,19.4-22.7,19.4-38.1c0-23.6-19.4-39.9-42.6-39.9
- c-32.4,0-48.5,16.4-47.9,46.4H192c0.3-42,24.4-62.1,67.6-62.1c33,0,60.4,20.4,60.4,54.6C320,222.3,309.3,236.6,294.1,250.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home-outline.svg
deleted file mode 100644
index fdb70719..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,112L96,240v208h112V320h96v128h112V240L256,112z M400,432h-80V304H192v128h-80V247.69l144-115.2l144,115.2V432z"/>
- <path d="M256,64l-96,76.8V96H96v95.999l-32,25.499l11.51,11.384L256,84.49l180.49,144.393L448,217.498L256,64z M144,153.599
- l-32,25.6V112h32V153.599z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home.svg
deleted file mode 100644
index 5fb5efbf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-home.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,112L96,240v208h112V320h96v128h112V240L256,112z"/>
- <path d="M256,64l-96,76.8V96H96v95.999l-32,25.499l11.51,11.384L256,84.49l180.49,144.393L448,217.498L256,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite-outline.svg
deleted file mode 100644
index fac58bbb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M451.229,188.098C432.682,169.967,407.95,160,381.585,160c-26.363,0-51.095,9.967-69.642,28.098l-42.229,41.187
- l13.649,13.447l42.229-41.306c14.933-14.529,34.764-22.573,55.878-22.573c21.113,0,40.946,8.044,55.878,22.573
- c30.797,30.139,30.797,79.13,0,109.148c-14.932,14.529-34.765,22.573-55.878,22.573c-21.114,0-40.945-8.044-55.878-22.573
- L200.071,188.098C181.406,169.967,156.675,160,130.427,160c-26.363,0-51.095,9.967-69.643,28.098
- C41.615,206.809,32.021,231.441,32,256c-0.021,24.611,9.573,49.149,28.784,67.902C79.332,342.032,104.063,352,130.427,352
- c26.365,0,51.095-9.968,69.645-28.098l42.111-41.186l-13.647-13.329l-42.229,41.187c-14.932,14.529-34.764,22.573-55.879,22.573
- c-21.113,0-40.944-8.044-55.876-22.573c-30.799-30.14-30.799-79.13,0-109.148c14.932-14.529,34.763-22.573,55.876-22.573
- c21.115,0,40.947,8.044,55.879,22.573l125.52,122.477C330.49,342.032,355.222,352,381.47,352c26.363,0,51.095-9.968,69.643-28.098
- C470.361,305.23,479.985,280.6,480,256C480.015,231.399,470.42,206.83,451.229,188.098z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite.svg
deleted file mode 100644
index aae8d1d3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-infinite.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M456.821,182.377C436.782,162.788,410.062,152,381.585,152c-28.477,0-55.195,10.788-75.21,30.354l-39.106,37.885
- l25.06,24.689l38.843-37.769c13.458-13.095,31.321-20.307,50.299-20.307c18.979,0,36.841,7.212,50.282,20.291
- c13.363,13.077,20.712,30.468,20.693,48.97c-0.019,18.443-7.363,35.75-20.677,48.728c-13.458,13.095-31.32,20.307-50.299,20.307
- c-18.978,0-36.841-7.212-50.291-20.299L205.646,182.359C185.491,162.782,158.778,152,130.427,152
- c-28.477,0-55.195,10.788-75.23,30.373C35.103,201.986,24.023,228.132,24,255.993c-0.024,27.822,11.055,53.973,31.192,73.63
- C75.232,349.212,101.951,360,130.427,360c28.475,0,55.194-10.788,75.223-30.363l38.994-37.909l-25.088-24.502l-38.829,37.615
- c-13.458,13.095-31.321,20.307-50.3,20.307c-18.977,0-36.839-7.212-50.28-20.291c-13.364-13.077-20.714-30.469-20.694-48.971
- c0.019-18.443,7.363-35.749,20.678-48.727c13.458-13.095,31.32-20.307,50.297-20.307c18.979,0,36.842,7.212,50.292,20.299
- l125.532,122.489C326.406,349.218,353.119,360,381.47,360c28.476,0,55.194-10.788,75.213-30.355
- c20.179-19.573,31.301-45.727,31.317-73.64C488.017,228.167,476.942,202.018,456.821,182.377z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-empty.svg
deleted file mode 100644
index 387abc47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-empty.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <circle cx="251.5" cy="172" r="20"/>
- <polygon points="272,344 272,216 224,216 224,224 240,224 240,344 224,344 224,352 288,352 288,344 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-outline.svg
deleted file mode 100644
index b16b6c44..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <circle cx="251.5" cy="172" r="20"/>
- <polygon points="272,344 272,216 224,216 224,224 240,224 240,344 224,344 224,352 288,352 288,344 "/>
- </g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M256,446.7c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information.svg
deleted file mode 100644
index 2ef04fc8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-information.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M251.5,152c11.1,0,20,9,20,20s-9,20-20,20c-11,0-20-9-20-20S240.4,152,251.5,152z M288,352h-64v-8h16V224h-16v-8h48v128h16V352z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-ionic-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-ionic-outline.svg
deleted file mode 100644
index 694a603c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-ionic-outline.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M425.5,134.8c4.7-5.9,7.5-13.5,7.5-21.6c0-19.2-15.6-34.9-34.8-34.9c-8.2,0-15.7,2.8-21.6,7.5c-34-24.2-75-37.8-119.9-37.8
- C141.8,48,48,140.5,48,255.6C48,370.7,141.7,464,256.6,464C371.5,464,464,370.7,464,255.6C464,210.6,449.7,168.9,425.5,134.8z
- M398,91.3c12.2,0,22,9.9,22,22c0,12.2-9.9,22-22,22c-12.2,0-22-9.9-22-22C376,101.2,385.8,91.3,398,91.3z M391.8,391.7
- c-17.6,17.6-38.2,31.6-61.1,41.3c-23.7,10-48.2,15.2-74.2,15.2c-25.9,0-51.7-5.1-75.4-15.2c-22.9-9.7-43.4-23.5-61.1-41.3
- c-17.6-17.6-31.5-38.3-41.2-61.2c-10-23.7-15.1-48.9-15.1-74.9c0-25.9,5.1-51.2,15.1-74.9c9.7-22.9,23.5-43.5,41.2-61.2
- s38.2-31.6,61.1-41.3c23.7-10,49.4-14.1,75.4-14.1c25.9,0,50.5,4,74.2,14.1c12.7,5.4,24.7,12.1,35.9,20c-2.1,4.5-3.3,9.5-3.3,14.9
- c0,19.2,15.6,34.9,34.8,34.9c5.3,0,10.3-1.2,14.9-3.3c7.9,11.2,14.6,23.2,20,36c10,23.7,15.1,48.9,15.1,74.9
- c0,25.9-5.1,51.2-15.1,74.9C423.3,353.4,409.5,374,391.8,391.7z"/>
- <path d="M256.5,160.1c-53,0-96,42.8-96,95.9s42.9,96.1,96,96.1c53,0,96-43,96-96.1S309.5,160.1,256.5,160.1z M256.5,335.8
- c-44.1,0-79.7-35.8-79.7-79.8c0-44.1,35.6-79.6,79.7-79.6s79.7,35.6,79.7,79.6C336.2,300.1,300.5,335.8,256.5,335.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad-outline.svg
deleted file mode 100644
index d6556355..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad-outline.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M394.6,341.2c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S424.1,341.2,394.6,341.2z
- M394.6,432c-20.6,0-37.4-16.8-37.4-37.4c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C432,415.2,415.2,432,394.6,432z"/>
- <path d="M256,341.2c-29.5,0-53.4,23.9-53.4,53.4S226.5,448,256,448c29.5,0,53.4-23.9,53.4-53.4S285.5,341.2,256,341.2z M256,432
- c-20.6,0-37.4-16.8-37.4-37.4c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C293.4,415.2,276.6,432,256,432z"/>
- <path d="M117.4,341.2c-29.5,0-53.4,23.9-53.4,53.4S87.9,448,117.4,448c29.5,0,53.4-23.9,53.4-53.4S146.9,341.2,117.4,341.2z
- M117.4,432C96.8,432,80,415.2,80,394.6c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C154.8,415.2,138.1,432,117.4,432z"/>
- <path d="M394.6,202.6c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S424.1,202.6,394.6,202.6z
- M394.6,293.4c-20.6,0-37.4-16.8-37.4-37.4c0-20.6,16.8-37.4,37.4-37.4S432,235.4,432,256C432,276.6,415.2,293.4,394.6,293.4z"/>
- <path d="M256,202.6c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S285.5,202.6,256,202.6z
- M256,293.4c-20.6,0-37.4-16.8-37.4-37.4c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C293.4,276.6,276.6,293.4,256,293.4z"/>
- <path d="M117.4,202.6C87.9,202.6,64,226.5,64,256s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S146.9,202.6,117.4,202.6z
- M117.4,293.4C96.8,293.4,80,276.6,80,256c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C154.8,276.6,138.1,293.4,117.4,293.4z"
- />
- <path d="M394.6,170.8c29.5,0,53.4-23.9,53.4-53.4c0-29.5-23.9-53.4-53.4-53.4c-29.5,0-53.4,23.9-53.4,53.4
- C341.2,146.9,365.1,170.8,394.6,170.8z M394.6,80c20.6,0,37.4,16.8,37.4,37.4c0,20.6-16.8,37.4-37.4,37.4s-37.4-16.8-37.4-37.4
- C357.2,96.8,373.9,80,394.6,80z"/>
- <path d="M256,64c-29.5,0-53.4,23.9-53.4,53.4c0,29.5,23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4C309.4,87.9,285.5,64,256,64z
- M256,154.8c-20.6,0-37.4-16.8-37.4-37.4c0-20.6,16.8-37.4,37.4-37.4s37.4,16.8,37.4,37.4C293.4,138,276.6,154.8,256,154.8z"/>
- <path d="M117.4,64C87.9,64,64,87.9,64,117.4c0,29.5,23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4C170.8,87.9,146.9,64,117.4,64z
- M117.4,154.8C96.8,154.8,80,138,80,117.4C80,96.8,96.8,80,117.4,80s37.4,16.8,37.4,37.4C154.8,138,138.1,154.8,117.4,154.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad.svg
deleted file mode 100644
index 9eae5d1b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-keypad.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M394.6,341.2c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S424.1,341.2,394.6,341.2z"/>
- <path d="M256,341.2c-29.5,0-53.4,23.9-53.4,53.4S226.5,448,256,448c29.5,0,53.4-23.9,53.4-53.4S285.5,341.2,256,341.2z"/>
- <path d="M117.4,341.2c-29.5,0-53.4,23.9-53.4,53.4S87.9,448,117.4,448c29.5,0,53.4-23.9,53.4-53.4S146.9,341.2,117.4,341.2z"/>
- <path d="M394.6,202.6c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S424.1,202.6,394.6,202.6z"/>
- <path d="M256,202.6c-29.5,0-53.4,23.9-53.4,53.4s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S285.5,202.6,256,202.6z"/>
- <path d="M117.4,202.6C87.9,202.6,64,226.5,64,256s23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4S146.9,202.6,117.4,202.6z"/>
- <path d="M394.6,170.8c29.5,0,53.4-23.9,53.4-53.4c0-29.5-23.9-53.4-53.4-53.4c-29.5,0-53.4,23.9-53.4,53.4
- C341.2,146.9,365.1,170.8,394.6,170.8z"/>
- <path d="M256,64c-29.5,0-53.4,23.9-53.4,53.4c0,29.5,23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4C309.4,87.9,285.5,64,256,64z"
- />
- <path d="M117.4,64C87.9,64,64,87.9,64,117.4c0,29.5,23.9,53.4,53.4,53.4c29.5,0,53.4-23.9,53.4-53.4C170.8,87.9,146.9,64,117.4,64z
- "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb-outline.svg
deleted file mode 100644
index 8390f3ef..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M400,172.9C400,95.1,333.9,32,256,32c-77.9,0-144,63.1-144,141c0,31,13.2,59,30.2,83h-0.3c10.9,15,21.4,27.7,31.5,45
- c22,37.8,18.6,74.3,18.7,81.6v1.4h128v-1.4c0-8.9-3.6-43.8,18.4-81.6c10.1-17.3,20.6-30,31.5-45h-0.1C386.8,232,400,204,400,172.9z
- M351,254.4c-0.6,0.8-1.1,1.5-1.7,2.3c-8.1,10.9-16.5,22.2-24.7,36.1c-17.3,29.7-20.4,57.9-20.8,75.1H288V256l32-64h-16.6L272,256
- v112h-32V256l-31.4-64H192l32,64v112h-15.9c-0.5-17.2-3.9-45.7-20.9-75c-4.5-7.7-9.1-15-13.7-21h0.2l-18.6-25.6
- c-15.8-21.6-27.1-47.1-27.1-73.6c0-33.4,16-64.8,39.6-88.4s55-36.7,88.4-36.7c33.4,0,64.8,13.1,88.4,36.7
- c23.6,23.6,39.6,55,39.6,88.4c0,26.5-11.3,51.9-27.1,73.5L351,254.4z"/>
- <rect x="224" y="464" width="64" height="16"/>
- <rect x="208" y="432" width="96" height="16"/>
- <rect x="208" y="400" width="96" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb.svg
deleted file mode 100644
index b6580713..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-lightbulb.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M400,172.9C400,95.1,333.9,32,256,32c-77.9,0-144,63.1-144,141c0,31,13.2,59,30.2,83h-0.3c10.9,15,21.4,27.7,31.5,45
- c22,37.8,18.6,74.3,18.7,81.6v1.4h32V256l-32-64h16.6l31.4,64v128h32V256l31.4-64H320l-32,64v128h32v-1.4
- c0-8.9-3.6-43.8,18.4-81.6c10.1-17.3,20.6-30,31.5-45h-0.1C386.8,232,400,204,400,172.9z"/>
- </g>
- <rect x="224" y="464" width="64" height="16"/>
- <rect x="208" y="432" width="96" height="16"/>
- <rect x="208" y="400" width="96" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list-outline.svg
deleted file mode 100644
index 38049cc9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list-outline.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M432,80v352H80V80H432 M448,64H64v384h384V64L448,64z"/>
- <g>
- <rect x="192" y="152" width="192" height="16"/>
- </g>
- <g>
- <rect x="192" y="248" width="192" height="16"/>
- </g>
- <g>
- <rect x="192" y="344" width="192" height="16"/>
- </g>
- </g>
- <circle cx="144" cy="160" r="16"/>
- <circle cx="144" cy="256" r="16"/>
- <circle cx="144" cy="352" r="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list.svg
deleted file mode 100644
index ba40a539..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-list.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M64,64v384h384V64H64z M144,368c-8.836,0-16-7.164-16-16s7.164-16,16-16s16,7.164,16,16S152.836,368,144,368z M144,272
- c-8.836,0-16-7.164-16-16s7.164-16,16-16s16,7.164,16,16S152.836,272,144,272z M144,176c-8.836,0-16-7.164-16-16s7.164-16,16-16
- s16,7.164,16,16S152.836,176,144,176z M384,360H192v-16h192V360z M384,264H192v-16h192V264z M384,168H192v-16h192V168z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location-outline.svg
deleted file mode 100644
index 98751071..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,48c34.19,0,66.334,13.314,90.51,37.49S384,141.81,384,176c0,42.92-24.092,107.127-69.67,185.68
- c-22.279,38.396-44.771,71.634-58.332,90.931c-13.518-19.232-35.912-52.327-58.161-90.645C152.149,283.281,128,218.976,128,176
- c0-34.19,13.314-66.334,37.49-90.51S221.81,48,256,48 M256,32c-79.529,0-144,64.471-144,144c0,112,144,304,144,304s144-192,144-304
- C400,96.471,335.529,32,256,32L256,32z"/>
- <path d="M256,112c-35.3,0-64,28.7-64,64s28.7,64,64,64s64-28.7,64-64S291.3,112,256,112z M256,222.9c-25.9,0-46.9-21-46.9-46.9
- s21-46.9,46.9-46.9s46.9,21,46.9,46.9S281.9,222.9,256,222.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location.svg
deleted file mode 100644
index d15131c7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-location.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M256,32c-79.529,0-144,64.471-144,144c0,112,144,304,144,304s144-192,144-304C400,96.471,335.529,32,256,32z M256,222.9
- c-25.9,0-46.9-21-46.9-46.9s21-46.9,46.9-46.9s46.9,21,46.9,46.9S281.9,222.9,256,222.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked-outline.svg
deleted file mode 100644
index 8c951256..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M360,224v-72c0-57.43-46.562-104-103.984-104C198.562,48,152,94.57,152,152v72H96v240h320V224H360z M168,152
- c0-48.523,39.484-88,88.016-88C304.531,64,344,103.477,344,152v72H168V152z M400,448H112V240h288V448z"/>
- </g>
- <path d="M256,288c-17.673,0-32,14.327-32,32c0,14.91,10.198,27.439,24,30.992V384h16v-33.008c13.802-3.553,24-16.082,24-30.992
- C288,302.327,273.673,288,256,288z M256,336c-8.822,0-16-7.178-16-16s7.178-16,16-16s16,7.178,16,16S264.822,336,256,336z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked.svg
deleted file mode 100644
index 621572fd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-locked.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M360,224v-72c0-57.43-46.562-104-103.984-104C198.562,48,152,94.57,152,152v72H96v240h320V224H360z M264,350.992V384h-16
- v-33.008c-13.802-3.553-24-16.082-24-30.992c0-17.673,14.327-32,32-32s32,14.327,32,32C288,334.91,277.802,347.439,264,350.992z
- M344,224H168v-72c0-48.523,39.484-88,88.016-88C304.531,64,344,103.477,344,152V224z"/>
- <path d="M256,304c-8.822,0-16,7.178-16,16s7.178,16,16,16s16-7.178,16-16S264.822,304,256,304z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop-strong.svg
deleted file mode 100644
index 9edcdfaa..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop-strong.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M256,48c-75.033,0-144.531,40.658-181.373,106.107l-1.963,3.485l20.915,11.771l1.962-3.485
- C128.138,107.973,189.621,72,256,72c101.458,0,184,82.542,184,184c0,12.509-1.262,25.007-3.749,37.147l-0.803,3.918l23.511,4.819
- l0.804-3.919C462.574,284.244,464,270.125,464,256C464,141.309,370.691,48,256,48z"/>
- <path d="M416.459,346.119C383.862,404.027,322.379,440,256,440c-101.458,0-184-82.542-184-184c0-12.512,1.262-25.011,3.75-37.15
- l0.803-3.918l-23.511-4.819l-0.804,3.918C49.426,227.75,48,241.87,48,256c0,114.691,93.309,208,208,208
- c75.033,0,144.531-40.658,181.373-106.109l1.963-3.485l-20.915-11.771L416.459,346.119z"/>
- </g>
- <polygon points="384,256 448,320 512,256 "/>
- <polygon points="0,256 64,192 128,256 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop.svg
deleted file mode 100644
index 18efda65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-loop.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="489.373,256 448,297.373 405.627,256 394.813,266.813 448,320 500.687,267.313 "/>
- <g>
- <path d="M459.994,255.509c-0.002-0.577,0.013-1.157,0.007-1.733l-0.029-0.003C458.771,142.311,367.742,52,256,52
- c-73.59,0-141.753,39.878-177.888,104.071l13.943,7.848C125.359,104.754,188.18,68,256,68
- c103.273,0,187.355,83.708,187.985,186.836c0.038,6.882-0.281,13.83-1.017,20.831l15.912,1.674
- c0.755-7.168,1.105-14.286,1.111-21.341H460C460,255.836,459.994,255.673,459.994,255.509z"/>
- <path d="M419.944,348.081C386.641,407.246,323.82,444,256,444c-103.475,0-187.688-84.032-187.993-187.437
- c-0.015-6.686,0.31-13.434,1.024-20.23l-15.912-1.674c-0.754,7.168-1.104,14.286-1.108,21.341H52c0,0.472,0.015,0.939,0.018,1.41
- c0.006,0.975-0.006,1.952,0.015,2.924l0.022-0.003C54.369,370.825,144.962,460,256,460c73.59,0,141.753-39.878,177.888-104.071
- L419.944,348.081z"/>
- <g>
- <polygon points="64,192 11.313,244.687 22.627,256 64,214.627 105.373,256 116.687,244.687 "/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical-outline.svg
deleted file mode 100644
index 831a19da..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M438,187.713l-31.927-55.426L288,200.574V64h-64v136.574l-118.073-68.287l-31.938,55.426L192.092,256L73.998,324.287
- l31.928,55.426L224,311.426V448h64V311.426l118.072,68.287l31.939-55.426L319.908,256L438,187.713z M416.176,330.125l-15.963,27.866
- L272,284v148h-32V284l-128.213,74l-15.969-27.785l128.228-74.197L95.822,181.861l15.964-27.859L240,228V80h32v148l128.213-74
- l15.969,27.785l-128.228,74.179L416.176,330.125z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical.svg
deleted file mode 100644
index f713d868..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medical.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M438,187.713l-31.927-55.426L288,200.574V64h-64v136.574l-118.073-68.287l-31.938,55.426L192.092,256L73.998,324.287
- l31.928,55.426L224,311.426V448h64V311.426l118.072,68.287l31.939-55.426L319.908,256L438,187.713z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit-outline.svg
deleted file mode 100644
index 40c58517..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M272,208v48v16h16h48v32h-48h-16v16v48h-32v-48v-16h-16h-48v-32h48h16v-16v-48H272 M288,192h-64v64h-64v64h64v64h64v-64
- h64v-64h-64V192L288,192z"/>
- </g>
- <path d="M336,128V96c-0.5-18.2-13.6-32-32.2-32h-99.1C186.1,64,176,77.7,176,96v32H48v320h416V128H336z M192,98.1
- c0-10.2,2.9-18.1,13.7-18.1h97.1c10.4,0,17.2,7.7,17.2,18.1V128H192V98.1z M448,432H64V144h384V432z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit.svg
deleted file mode 100644
index 4eb5d94e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-medkit.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="272,272 272,256 272,208 240,208 240,256 240,272 224,272 176,272 176,304 224,304 240,304 240,320 240,368
- 272,368 272,320 272,304 288,304 336,304 336,272 288,272 "/>
- <path d="M336,128V96c-0.5-18.2-13.6-32-32.2-32h-99.1C186.1,64,176,77.7,176,96v32H48v320h416V128H336z M192,98.1
- c0-10.2,2.9-18.1,13.7-18.1h97.1c10.4,0,17.2,7.7,17.2,18.1V128H192V98.1z M352,320h-64v64h-64v-64h-64v-64h64v-64h64v64h64V320z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-off.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-off.svg
deleted file mode 100644
index da69e6c3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-off.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="264.2" y="1.1" transform="matrix(0.8629 -0.5053 0.5053 0.8629 -92.0515 172.66)" width="16" height="509.8"/>
- <path d="M256.2,353.4c12.3,0,23.8-2.9,34.2-8.2L177,152.4V270C177,316,212.4,353.4,256.2,353.4z"/>
- <path d="M335,270V115.5c0-46-35.2-83.5-79-83.5c-25.4,0-47.8,12.6-62.3,32.2l136.9,233.3C333.5,288.9,335,279.6,335,270z"/>
- <path d="M384,271.7V192h-17v79.7c0,21.5-6.2,41.6-17.1,58.5l9.9,17C375.1,326,384,299.9,384,271.7z"/>
- <path d="M267,399.2c17-1.2,33-5.8,47.3-13l-9.4-16.1c-14.5,7-30.7,10.9-47.7,10.9c-60.3,0-110.1-49-110.1-109.1V192h-19v79.7
- c0,67.2,53,122.6,120,127.4V462h-73v18h161v-18h-69V399.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-outline.svg
deleted file mode 100644
index 829d61b9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32c-43.7,0-79,37.5-79,83.5V270c0,46,35.3,83.5,79,83.5c43.7,0,79-37.5,79-83.5V115.5C335,69.5,299.7,32,256,32z
- M319,270c0,37.2-28.3,67.5-63,67.5c-34.7,0-63-30.3-63-67.5V115.5c0-37.2,28.3-67.5,63-67.5c34.7,0,63,30.3,63,67.5V270z"/>
- <path d="M367,192v79.7c0,60.2-49.8,109.2-110,109.2c-60.2,0-110-49-110-109.2V192h-19v79.7c0,67.2,53,122.6,120,127.5V462h-73v18
- h161v-18h-69v-62.8c66-4.9,117-60.3,117-127.5V192H367z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic.svg
deleted file mode 100644
index cf73a7b8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-mic.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,353.5c43.7,0,79-37.5,79-83.5V115.5c0-46-35.3-83.5-79-83.5c-43.7,0-79,37.5-79,83.5V270
- C177,316,212.3,353.5,256,353.5z"/>
- <path d="M367,192v79.7c0,60.2-49.8,109.2-110,109.2c-60.2,0-110-49-110-109.2V192h-19v79.7c0,67.2,53,122.6,120,127.5V462h-73v18
- h161v-18h-69v-62.8c66-4.9,117-60.3,117-127.5V192H367z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-empty.svg
deleted file mode 100644
index 7c294f8f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-empty.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M384,265H128v-17h256V265z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-outline.svg
deleted file mode 100644
index 668b4045..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
- </g>
- <rect x="128" y="248" width="256" height="17"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus.svg
deleted file mode 100644
index 077900dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-minus.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M384,265H128v-17h256V265z"
- />
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor-outline.svg
deleted file mode 100644
index 386e94f4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor-outline.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M496,384V96H16v288h175v16h-64v16h257v-16h-64v-16H496z M32,112h448v256H32V112z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor.svg
deleted file mode 100644
index 9bd65ed2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-monitor.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M496,384V96H16v288h175v16h-64v16h257v-16h-64v-16H496z M32,112h448v256H32V112z"/>
-<g>
- <rect x="48" y="128" width="416" height="224"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon-outline.svg
deleted file mode 100644
index 5b8e1de2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M343.1,315c-1.8,0.1-3.5,0.1-5.3,0.1c-29.1,0-56.5-11.3-77.1-31.9c-20.6-20.6-31.9-48-31.9-77.1
- c0-16.6,3.7-32.6,10.6-47.1c3.1-6.4,6.8-12.5,11.1-18.2c-7.6,0.8-14.9,2.4-22,4.6c-46.8,14.8-80.7,58.5-80.7,110.2
- c0,63.8,51.7,115.5,115.5,115.5c35.3,0,66.8-15.8,88-40.7c4.8-5.7,9.2-11.9,12.8-18.5C357.3,313.6,350.3,314.7,343.1,315z
- M263.3,355.1c-54.9,0-99.5-44.6-99.5-99.5c0-39.1,22.6-72.9,55.4-89.2c-4.2,12.5-6.4,25.8-6.4,39.7c0,65.9,51,119.9,115.6,124.7
- C311,346,288.2,355.1,263.3,355.1z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon.svg
deleted file mode 100644
index 059f2b9a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-moon.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M343.1,315c-1.8,0.1-3.5,0.1-5.3,0.1c-29.1,0-56.5-11.3-77.1-31.9c-20.6-20.6-31.9-48-31.9-77.1
- c0-16.6,3.7-32.6,10.6-47.1c3.1-6.4,6.8-12.5,11.1-18.2c-7.6,0.8-14.9,2.4-22,4.6c-46.8,14.8-80.7,58.5-80.7,110.2
- c0,63.8,51.7,115.5,115.5,115.5c35.3,0,66.8-15.8,88-40.7c4.8-5.7,9.2-11.9,12.8-18.5C357.3,313.6,350.3,314.7,343.1,315z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more-outline.svg
deleted file mode 100644
index 010cd1ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,238c9.9,0,18,8.1,18,18s-8.1,18-18,18s-18-8.1-18-18S246.1,238,256,238 M256,224c-17.7,0-32,14.3-32,32s14.3,32,32,32
- c17.7,0,32-14.3,32-32S273.7,224,256,224L256,224z"/>
- <path d="M128.4,238c9.9,0,18,8.1,18,18s-8.1,18-18,18c-9.9,0-18-8.1-18-18S118.5,238,128.4,238 M128.4,224c-17.7,0-32,14.3-32,32
- s14.3,32,32,32c17.7,0,32-14.3,32-32S146,224,128.4,224L128.4,224z"/>
- <path d="M384,238c9.9,0,18,8.1,18,18s-8.1,18-18,18s-18-8.1-18-18S374.1,238,384,238 M384,224c-17.7,0-32,14.3-32,32s14.3,32,32,32
- s32-14.3,32-32S401.7,224,384,224L384,224z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more.svg
deleted file mode 100644
index 9768cd87..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-more.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,224c-17.7,0-32,14.3-32,32s14.3,32,32,32c17.7,0,32-14.3,32-32S273.7,224,256,224L256,224z"/>
- <path d="M128.4,224c-17.7,0-32,14.3-32,32s14.3,32,32,32c17.7,0,32-14.3,32-32S146,224,128.4,224L128.4,224z"/>
- <path d="M384,224c-17.7,0-32,14.3-32,32s14.3,32,32,32s32-14.3,32-32S401.7,224,384,224L384,224z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-note.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-note.svg
deleted file mode 100644
index 2ee22164..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-note.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M352.1,102.3c0-0.1,0-0.2,0-0.2c-0.1-0.3-0.1-0.5-0.2-0.8c0,0,0-0.1,0-0.1c-0.6-1.5-1.8-3-3.5-3.4l-2-0.4L256,78v272.6
- c-8,0-22.4,0.4-44.5,1.3c-41.8,1.6-51.4,21.6-51.4,40.9c0,24.6,13.2,43.1,61.5,41c51.8-2.3,51.4-48.5,51.4-81.7V159.6l73.6,13.5l0,0
- c3,0.6,5.4-2.3,5.4-5.3v-64.4C352,103,352.1,102.6,352.1,102.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-notes.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-notes.svg
deleted file mode 100644
index 0fe310c5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-musical-notes.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M416,319.9V78l-224,34.6v237.2c-9,0-20.9,0.4-43.5,1.3c-42.6,1.6-52.5,21.8-52.5,41.3c0,24.9,13.5,43.5,62.6,41.4
- c52.8-2.3,50.3-49,50.3-82.5V189.8l191-32v160.6c-9,0-19.9,0.4-42.6,1.3c-42.6,1.6-52.5,21.8-52.5,41.3c0,24.9,13,43.5,62.2,41.4
- C420,400.1,416,353.4,416,319.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate-outline.svg
deleted file mode 100644
index 74e4180b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,64.5c51.1,0,99.2,19.9,135.4,56.1s56.1,84.2,56.1,135.4s-19.9,99.2-56.1,135.4s-84.2,56.1-135.4,56.1
- s-99.2-19.9-135.4-56.1C84.5,355.2,64.5,307.1,64.5,256s19.9-99.2,56.1-135.4C156.8,84.5,204.9,64.5,256,64.5 M256,48
- C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48L256,48z"/>
- <polygon points="352,160 128.3,256 256,256 256,384 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate.svg
deleted file mode 100644
index 2a265c9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-navigate.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z M256,384
- V256H128.3L352,160L256,384z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition-outline.svg
deleted file mode 100644
index b8d04ea4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition-outline.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M358,233.855l0.413-0.039c-0.137-0.137-0.046-0.101-0.185-0.237L279.798,155h-0.004c-5.833-6-14.193-10.154-23.485-10.154
- c-11.811,0-22.115,6.154-27.635,16.154h-0.007c0,0-7.09,10.994-18.27,28.874l32.531,39.637c2.939,3.769,3.296,7.801,1.411,9.689
- l-0.114,0.071c-0.909,0.909-2.021,1.33-3.274,1.33c-1.908,0-4.142-0.99-6.485-2.768l-35.872-29.418
- c-23.546,37.655-56.677,90.634-83.45,133.451l19.072,23.337c2.939,3.77,3.296,7.884,1.41,9.772l-0.114,0.114
- c-0.911,0.913-2.028,1.342-3.287,1.342c-1.905,0-4.136-0.981-6.472-2.755l-21.067-16.533C84.734,389.051,70,412.464,68,414.366
- v0.003c-3,5.062-4.085,11.132-4.085,17.664c0,17.655,14.657,31.967,32.285,31.967c7.821,0,14.57-3.395,20.799-7.5l114.651-84.109
- l-28.838-35.358c-2.94-3.769-3.268-7.887-1.382-9.775l0.128-0.114c0.912-0.912,2.034-1.341,3.294-1.341
- c1.905,0,4.14,0.981,6.476,2.755l37.864,31.59C304.03,319.902,355.082,283,355.082,283h0.005c7.839-6,12.473-15.711,12.473-26.238
- c0-8.704-3.56-17.14-9.56-22.904V233.855z M345.531,269.834c-2.664,1.934-46.692,33.932-95.764,69.899l-28.272-23.483l-0.26-0.223
- l-0.274-0.211c-5.245-3.981-10.663-5.998-16.108-5.998c-5.465,0-10.592,2.097-14.458,5.909l-0.064,0.062l-0.083,0.082l-0.083,0.083
- c-7.808,7.821-7.761,20.823,0.111,30.917l0.11,0.143l0.113,0.138l18.223,22.312l-100.656,73.896
- c-5.066,3.304-8.427,4.657-11.542,4.657c-8.822,0-16-7.171-16-15.983c0-3.086,0.694-6.045,2.017-8.623
- c2.391-3.161,6.6-9.876,18.655-29.351c2.543-4.108,5.252-8.487,8.134-13.129l6.39,5.176l0.195,0.156l0.2,0.152
- c5.245,3.981,10.665,6,16.111,6c5.517,0,10.692-2.139,14.571-6.023l0.114-0.113c7.806-7.817,7.756-20.82-0.118-30.916l-0.113-0.144
- l-0.115-0.142l-11.814-14.455l43.693-69.872l24.059-38.474l21.855,17.922l0.231,0.19l0.24,0.181
- c5.254,3.988,10.678,6.01,16.123,6.01c4.954,0,9.631-1.725,13.339-4.89l0.461-0.337l0.871-0.874
- c7.79-7.803,7.74-20.778-0.118-30.854l-0.12-0.153l-0.124-0.15l-25.239-30.539c2.957-4.703,5.457-8.491,7.405-11.488l5.209-8.494
- c2.777-5.025,7.761-8.157,13.673-8.157c4.367,0,8.76,2.042,12.057,5.43l4.701,4.928h0.122L342,240.286v0.376l5.186,4.716
- c2.793,2.69,4.539,6.782,4.539,11.227C351.725,261.801,349.467,266.728,345.531,269.834z"/>
- <polygon points="439.994,115.175 435.216,117.938 343.578,170.93 407.313,60.358 409.83,55.992 396.011,48 393.523,52.313
- 322.748,175.098 339.418,191.794 443.38,131.674 447.974,129.018 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition.svg
deleted file mode 100644
index 375b45e5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-nutrition.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M359,233.62l-0.106-0.039c-0.136-0.138-0.306-0.443-0.444-0.579L279.551,154h-0.004c-5.848-6-14.23-10.168-23.547-10.168
- c-11.842,0-22.174,6.168-27.708,16.168h-0.007c0,0-7.109,11.351-18.318,29.249l32.617,39.85c2.947,3.772,3.305,7.895,1.414,9.785
- l-0.114,0.114c-2.296,2.296-5.894,1.535-9.785-1.414l-35.967-29.439c-23.608,37.693-56.827,90.731-83.671,133.592l19.123,23.362
- c2.947,3.772,3.305,7.895,1.414,9.785l-0.114,0.114c-2.296,2.296-5.894,1.535-9.785-1.414l-20.22-16.55
- C84.874,388.974,70.194,412.411,69,414.315v0.003c-3,5.066-5,11.144-5,17.682c0,17.674,14.244,32,31.918,32
- c7.842,0,14.383-3.398,20.628-7.508l114.842-84.195l-28.971-35.395c-2.947-3.772-3.305-7.895-1.414-9.785l0.114-0.114
- c2.296-2.296,5.894-1.534,9.785,1.415l37.963,31.215C303.85,319.348,355.035,282,355.035,282h0.005
- c7.859-6,13.024-15.319,13.024-25.857c0-8.713-3.064-16.75-9.064-22.521V233.62z"/>
- <polygon points="448,138.781 431.514,111.087 365.284,149.299 414.515,64.086 386.896,48 316.897,169.084 345.485,197.672 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper-outline.svg
deleted file mode 100644
index 7704053f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M112,64v16v320h16V80h304v337.143c0,8.205-6.652,14.857-14.857,14.857H94.857C86.652,432,80,425.348,80,417.143V128h16v-16
- H64v305.143C64,434.157,77.843,448,94.857,448h322.285C434.157,448,448,434.157,448,417.143V64H112z"/>
- <rect x="160" y="112" width="128" height="16"/>
- <rect x="160" y="192" width="240" height="16"/>
- <rect x="160" y="272" width="192" height="16"/>
- <rect x="160" y="352" width="240" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper.svg
deleted file mode 100644
index 5c0f3bfb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paper.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M112,64v16v32v288H96V112H64v305.143C64,434.157,77.843,448,94.857,448h322.285C434.157,448,448,434.157,448,417.143V64H112
- z M160,112h128v16H160V112z M160,272h192v16H160V272z M400,368H160v-16h240V368z M400,208H160v-16h240V208z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane-outline.svg
deleted file mode 100644
index ceb46f16..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M96,249.6l116.6,51.3L269.8,416L416,96L96,249.6z M228.1,296.5l155.7-166.2L269.2,379.2L228.1,296.5z M381.8,128.3
- L216.8,285.4L134,249L381.8,128.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane.svg
deleted file mode 100644
index 6b74591d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paperplane.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="96,249.6 202,296.3 416,96 "/>
- <polygon points="416,96 217.9,311.7 269.8,416 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny-outline.svg
deleted file mode 100644
index f5010f9d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny-outline.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <g>
- <g>
- <rect x="208" y="96" class="st0" width="16" height="54"/>
- <rect x="64" y="240" class="st0" width="55" height="16"/>
- <polygon class="st0" points="107.5,149.1 118.5,138 149.9,169.6 138.9,180.7 "/>
- <polygon class="st0" points="287.4,179.7 276.4,168.6 307.7,137 318.8,148.1 "/>
- <polygon class="st0" points="120.5,352.5 109.5,341.4 140.9,309.8 151.9,320.9 "/>
- </g>
- <g>
- <path class="st0" d="M192.6,294.9c-20.2-8.1-34.6-27.9-34.6-51.1c0-30.3,24.5-55,54.7-55c15.6,0,29.7,6.6,39.6,17.2
- c4.8-3.5,9.5-6.2,13.6-8.2c-12.9-15.1-32-24.7-53.3-24.7c-38.7,0-70.3,31.7-70.3,70.7c0,27.4,15.6,51.2,38.3,62.9
- C184.3,301.5,188.5,297.7,192.6,294.9z"/>
- </g>
- </g>
- <path class="st0" d="M299,239.8c14.5,0,28.1,4.8,39.3,13.9c10.9,8.9,18.6,21.3,21.7,34.9l3.1,14l14.2-1.8c2.1-0.3,4.1-0.4,6.1-0.4
- c26.9,0,48.8,22.1,48.8,49.2c0,27.1-21.9,49.2-48.8,49.2H225.7c-9.5,0-18.5-3.9-25.4-10.8c-6.8-7-10.6-16.2-10.6-25.9
- c0-18.6,14.5-33.8,33.2-36.9c1.6-0.3,8.8-1.2,14.2-1.7c0,0-0.5-5.3-0.6-9.6c-0.1-4.3-0.1-9.4-0.1-11.5
- C236.5,268,264.5,239.8,299,239.8 M299,224c-43.3,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8c-26.4,2.3-47.1,25.5-47.1,52.6
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7c0-35.8-28.9-65.3-64.6-65.3c-2.7,0-5.4,0-8,0.3
- C367.5,250.3,336.3,224,299,224L299,224z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny.svg
deleted file mode 100644
index 1f20c73f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-partlysunny.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <g>
- <g>
- <rect x="208" y="96" class="st0" width="16" height="54"/>
- <rect x="64" y="240" class="st0" width="55" height="16"/>
- <polygon class="st0" points="107.5,149.1 118.5,138 149.9,169.6 138.9,180.7 "/>
- <polygon class="st0" points="287.4,179.7 276.4,168.6 307.7,137 318.8,148.1 "/>
- <polygon class="st0" points="120.5,352.5 109.5,341.4 140.9,309.8 151.9,320.9 "/>
- </g>
- <path class="st0" d="M299,224c-43.3,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8c-26.4,2.3-47.1,25.5-47.1,52.6
- c0,28.6,23.2,53.1,51.7,53.1h157.7c35.7,0,64.6-29.9,64.6-65.7c0-35.8-28.9-65.3-64.6-65.3c-2.7,0-5.4,0-8,0.3
- C367.5,250.3,336.3,224,299,224L299,224z"/>
- </g>
- <path class="st0" d="M264.7,196.3c-12.9-14.3-31.4-23.3-52-23.3c-38.7,0-70.3,31.7-70.3,70.7c0,27.4,15.6,51.2,38.3,62.9
- c0,0,0-0.1,0-0.1c0,0,0.1,0.1,0.1,0.1c4.5-12.1,11.4-19.8,22.6-25.6c0.2-0.1,0.4-0.2,0.7-0.4c0.2-0.1,0.5-0.2,0.7-0.3
- c-0.2-2.3-0.3-4.7-0.3-7c-0.3-31.9,30.2-70.5,61-75.4c0.1-0.1,0.3-0.1,0.4-0.2C265.5,197.3,265.1,196.8,264.7,196.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause-outline.svg
deleted file mode 100644
index c1907cf6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M191,112v288h-47V112H191 M207,96h-79v320h79V96L207,96z"/>
- <path d="M368,112v288h-47V112H368 M384,96h-79v320h79V96L384,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause.svg
deleted file mode 100644
index acf5ee2b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pause.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="128" y="96" width="79" height="320"/>
- <rect x="305" y="96" width="79" height="320"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw-outline.svg
deleted file mode 100644
index 78d693c1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw-outline.svg
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M443.827,195.5c-4.383-11.73-11.753-20.212-21.317-24.524c-4.389-1.975-8.995-2.976-13.688-2.976
- c-20.025,0-40.372,18.667-50.632,46.454c-12.698,34.42-5.315,68.135,17.173,78.423c4.522,2.071,9.365,3.123,14.394,3.123
- c20.396,0,41.126-17.119,51.581-42.596C449.238,234.121,450.168,212.477,443.827,195.5z M426.214,246.295
- c-7.836,18.898-22.994,32.098-36.862,32.098c-2.809,0-5.488-0.569-7.968-1.694c-14.121-6.394-17.862-31.059-8.518-56.152
- c7.775-20.817,22.448-35.355,35.683-35.355c2.51,0,4.979,0.533,7.34,1.588c6.88,3.067,10.622,9.712,12.551,14.745
- C433.35,214.332,432.518,231.068,426.214,246.295z"/>
- <path d="M153.811,214.454C143.551,186.667,123.204,168,103.179,168c-4.693,0-9.3,1.001-13.689,2.976
- c-9.565,4.312-16.934,12.794-21.317,24.524c-6.341,16.977-5.411,38.621,2.49,57.904C81.118,278.881,101.848,296,122.244,296
- c5.028,0,9.871-1.052,14.394-3.123C159.126,282.589,166.509,248.874,153.811,214.454z M130.616,276.698
- c-2.479,1.125-5.16,1.694-7.968,1.694c-13.868,0-29.026-13.199-36.862-32.098c-6.304-15.227-7.136-31.963-2.226-44.771
- c1.929-5.033,5.671-11.678,12.551-14.745c2.361-1.055,4.83-1.588,7.34-1.588c13.234,0,27.907,14.538,35.683,35.355
- C148.479,245.64,144.737,270.305,130.616,276.698z"/>
- <path d="M198.347,210.601c1.855,0.081,3.727,0.03,5.563-0.151c10.787-1.059,20.54-6.594,28.207-16.008
- c12.371-15.191,15.806-38.974,13.201-63.439C241.336,93.3,221.469,65.161,194.776,64c0,0-3.811,0.008-5.75,0.193
- c-11.776,1.164-22.481,7.283-30.957,17.695c-12.291,15.101-18.198,37.57-15.803,60.104
- C146.202,179.269,170.836,209.404,198.347,210.601z M171.047,91.831c3.923-4.739,10.51-10.577,19.62-11.476
- c1.143-0.113,2.288-0.146,3.404-0.098c18.207,0.792,31.859,23.271,34.936,52.428c2.146,20.15-0.148,40.055-9.845,51.779
- c-4.874,5.898-10.556,9.204-16.881,9.825c-1.081,0.104-2.167,0.133-3.229,0.087c-19.257-0.838-37.414-25.091-40.473-54.067
- C156.611,121.779,161.273,103.656,171.047,91.831z"/>
- <path d="M256,240c-64,0-128,76.074-128,149.128c0,21.798,10.932,39.331,21.667,46.517C162.925,444.516,172.269,448,191.704,448
- c23.093,0,29.325-8.078,40.136-15.205c7.819-5.152,14.572-9.605,24.161-9.605s16.342,4.453,24.16,9.605
- C290.972,439.922,297.203,448,320.297,448c19.434,0,28.778-3.484,42.036-12.355C373.068,428.459,384,410.926,384,389.128
- C384,316.074,320,240,256,240z M353.963,420.776c-10.964,7.337-17.366,9.778-33.666,9.778c-14.225,0-18.624-3.201-25.911-8.51
- c-1.848-1.344-3.759-2.736-5.946-4.177c-8.619-5.682-18.39-12.123-32.439-12.123s-23.82,6.441-32.438,12.121
- c-2.189,1.442-4.1,2.835-5.947,4.179c-7.287,5.309-11.686,8.51-25.911,8.51c-16.3,0-22.703-2.441-33.667-9.778
- C152.395,417,144,405.456,144,389.128c0-30.277,13.377-64.231,35.783-90.823c10.886-12.921,23.517-23.6,36.526-30.885
- C229.713,259.917,243.067,256,256,256c12.934,0,26.287,3.917,39.691,11.42c13.01,7.285,25.64,17.964,36.525,30.885
- C354.623,324.896,368,358.851,368,389.128C368,405.456,359.605,417,353.963,420.776z"/>
- <path d="M308.281,210.265c1.836,0.182,3.709,0.232,5.563,0.151c27.511-1.196,52.146-31.332,56.081-68.607
- c2.395-22.534-3.514-45.004-15.804-60.104c-8.476-10.412-18.783-16.228-30.56-17.392c-1.939-0.186-6.146-0.312-6.146-0.312
- c-26.693,1.161-46.561,29.115-50.542,66.817c-2.604,24.466,0.83,48.248,13.2,63.439
- C287.741,203.671,297.494,209.206,308.281,210.265z M283.186,132.501c3.076-29.156,16.729-51.636,34.936-52.428
- c1.115-0.048,2.261-0.016,3.404,0.098c9.109,0.898,15.696,6.736,19.619,11.476c9.774,11.825,14.436,29.948,12.468,48.479
- c-3.06,28.977-21.216,53.229-40.474,54.067c-1.061,0.046-2.146,0.017-3.229-0.087c-6.324-0.621-12.007-3.927-16.881-9.825
- C283.334,172.556,281.039,152.651,283.186,132.501z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw.svg
deleted file mode 100644
index c83a883e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-paw.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M443.827,195.5c-4.383-11.73-11.753-20.212-21.317-24.524c-4.389-1.975-8.995-2.976-13.688-2.976
- c-20.025,0-40.372,18.667-50.632,46.454c-12.698,34.42-5.315,68.135,17.173,78.423c4.522,2.071,9.365,3.123,14.394,3.123
- c20.396,0,41.126-17.119,51.581-42.596C449.238,234.121,450.168,212.477,443.827,195.5z"/>
- <path d="M153.811,214.454C143.551,186.667,123.204,168,103.179,168c-4.693,0-9.3,1.001-13.689,2.976
- c-9.565,4.312-16.934,12.794-21.317,24.524c-6.341,16.977-5.411,38.621,2.49,57.904C81.118,278.881,101.848,296,122.244,296
- c5.028,0,9.871-1.052,14.394-3.123C159.126,282.589,166.509,248.874,153.811,214.454z"/>
- <path d="M198.347,210.601c1.855,0.081,3.727,0.03,5.563-0.151c10.787-1.059,20.54-6.594,28.207-16.008
- c12.371-15.191,15.806-38.974,13.201-63.439C241.336,93.3,221.469,65.161,194.776,64c0,0-3.811,0.008-5.75,0.193
- c-11.776,1.164-22.481,7.283-30.957,17.695c-12.291,15.101-18.198,37.57-15.803,60.104
- C146.202,179.269,170.836,209.404,198.347,210.601z"/>
- <path d="M256,240c-64,0-128,76.074-128,149.128c0,21.798,10.932,39.331,21.667,46.517C162.925,444.516,172.269,448,191.704,448
- c23.093,0,29.325-8.078,40.136-15.205c7.819-5.152,14.572-9.605,24.161-9.605s16.342,4.453,24.16,9.605
- C290.972,439.922,297.203,448,320.297,448c19.434,0,28.778-3.484,42.036-12.355C373.068,428.459,384,410.926,384,389.128
- C384,316.074,320,240,256,240z"/>
- <path d="M308.281,210.265c1.836,0.182,3.709,0.232,5.563,0.151c27.511-1.196,52.146-31.332,56.081-68.607
- c2.395-22.534-3.514-45.004-15.804-60.104c-8.476-10.412-18.783-16.228-30.56-17.392c-1.939-0.186-6.146-0.312-6.146-0.312
- c-26.693,1.161-46.561,29.115-50.542,66.817c-2.604,24.466,0.83,48.248,13.2,63.439
- C287.741,203.671,297.494,209.206,308.281,210.265z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people-outline.svg
deleted file mode 100644
index df702908..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people-outline.svg
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M256,112L256,112L256,112z"/>
- <path d="M349.2,334.8c-13.5-4.7-28.1-5-41.6-9.7c-4.1-1.4-12.2-3.1-13.9-7.8c-1.6-4.6-1.6-10-1.9-14.8c-0.2-3.8-0.3-7.6-0.3-11.4
- c0-2.5,6.4-7.8,7.8-10.1c5.4-9,5.9-21.1,6.9-31.3c8.7,2.4,9.8-13.7,11.3-18.6c1.1-3.4,7.8-26.8-2.6-23.6c2.5-4.4,3.5-9.8,4.2-14.7
- c2-12.8,2.8-26.8-1.1-39.3c-8.1-26-33-40.6-59.3-41.4c-26.7-0.9-53.5,11.9-63.5,37.8c-4.8,12.6-4.4,26.3-2.8,39.5
- c0.7,6,1.7,12.7,4.7,18.1c-9.7-2.9-4.5,17.7-3.4,21.3c1.6,5.1,3,23.4,12.1,20.9c0.8,8.1,1.7,16.4,3.9,24.3
- c1.5,5.3,4.6,9.8,8.2,13.9c1.8,2,2.7,2.2,2.6,4.8c-0.1,7.8,0.1,16.2-1.9,23.8c-2,7.6-18.7,10.8-25.4,12.2
- c-18,3.7-34.6,5.4-49.6,16.6C126.1,358.2,117,378.3,117,400c83.3,0,166.6,0,249.9,0c9.4,0,18.7,0,28.1,0
- C395,370.5,377.2,344.5,349.2,334.8C338,330.9,360.5,338.7,349.2,334.8z M147.1,363.6c5.6-5.9,12.7-11.1,20.4-14
- c10.5-4,22.4-3.8,33.3-6.6c9-2.3,20.2-5.9,27.2-12.4c6.4-6,7.1-15.2,7.7-23.5c0.5-7,0.4-13.9,0.4-20.9c0-4.9-5.7-7.7-8.5-11.6
- c-4.5-6.1-4.7-15.2-5.6-22.5c-0.4-3.2-0.5-7.3-3.2-9.5c-3-2.4-5.2-3.7-6.7-7.5c-2-5.2-2.7-10.8-4.3-16.2c-1-3.5,2.5-6.8,3.9-9.7
- c2.6-5.3-1.9-13.5-2.8-19c-2.8-16.4-2.7-34.3,9.1-47.3c23.7-26.2,78-17.9,85.8,18.9c2.4,11.5,0.9,24.9-2.3,36.1
- c-1.4,4.8-3,8.3-0.2,13c4.2,6.8,2.4,11.2,0.4,18.8c-1.6,6.3-3.6,9.1-8.4,13c-4,3.2-3.4,11.2-4.1,15.8c-0.8,5.6-1.3,11.5-4.7,16.2
- c-1.3,1.8-8.4,7.4-8.4,9.3c0,11-0.5,22.2,1.4,33.1c2.6,15.5,15.6,19.2,28.6,24.5c13.2,5.1,28.5,3.2,41.3,9.5
- c13.2,6.5,25.9,18.4,29.7,33.1c-79.3,0-158.6,0-237.9,0c-1.4,0-2.8,0-4.2,0C136.9,375.9,141.5,369.6,147.1,363.6
- C156.3,353.9,141.2,369.9,147.1,363.6z"/>
- </g>
- <path d="M144.1,322c7-3.5,14.6-4.3,22.3-5.1c2.8-0.3,4.1-2.2,2-4.9c-4-5.1-17.8-6.1-23.6-8.4c-3.6-1.4-4.6-2.7-4.9-6.7
- c-0.1-1.8-1.1-9.8,0.3-11.1c1-1,7.3-0.6,8.7-0.8c5.7-0.7,11.5-1.9,16.9-4c2.3-0.9,4.5-2,6.5-3.4c2.4-1.8-1.8-6.2-2.9-8.6
- c-3.4-7.5-4.9-15.7-5.4-23.9c-1-16.1,1.5-32.3-1.5-48.3c-4.5-24.5-23.4-36.8-47.5-36.8c-14.9,0-29.6,5.1-37.9,18.1
- c-9.2,14.3-8.7,32.1-8.2,48.4c0.3,9.3,0.7,18.7-0.6,28c-0.6,4-1.5,7.9-2.9,11.7c-1.1,2.9-6.7,10.1-4.5,11.6
- c8.3,5.9,22.3,7.9,32.3,7.1c0.3,4.9,1.2,11.2-0.6,15.8c-2.8,7.2-23.7,9.1-30,11.2C45,317.8,32,332.5,32,352c18.3,0,36.5,0,54.8,0
- c8.2,0,16.4,0,24.7,0c1.3,0,6.3-9.3,7.7-10.8C126.2,333.4,134.8,326.7,144.1,322C153.1,317.5,129.5,329.4,144.1,322z M102.8,336
- c-16.3,0-32.6,0-48.9,0c7.1-11.8,24.9-11,36.6-15.2c10.8-3.9,17.7-10.5,18.8-22c0.1-1.3,0.2-29.2-0.9-29.2
- c-8.7-0.3-17.8-0.1-26.5-1.4c6.9-22.3,0.3-45.3,4-67.8c2.7-16.3,13.1-25.3,29.7-25.3c15.9,0,27.7,7.4,31.1,23.4
- c4.8,23.2-2,46.9,5.4,69.9c-5.5,1.4-11.3,1.6-17,1.8c-2.8,0.1-5.7,0.2-8.5,0.3c-1.8,0.1-1.2,3.2-1.3,4.7c-1,10.9-5,28.1,3.7,36.9
- C119.4,318.1,109,326.4,102.8,336z"/>
- <path d="M399.8,352c26.7,0,53.5,0,80.2,0c0-19.5-13.1-34.3-30.7-40.1c-8.1-2.6-23.7-3.4-29.5-10.4c-2.9-3.5-1.3-12.4-1-16.6
- c4.4,0.4,9.2-0.3,13.7-0.9c4.1-0.6,8.1-1.4,12-2.8c1.8-0.7,3.6-1.4,5.3-2.4c3.9-2.3,2.1-2.7,0.1-6.1c-10.9-18.3-6-41.5-6.5-61.6
- c-0.4-16.7-4.8-35-20-44.4c-13.7-8.5-34-8.8-48.7-2.8c-42.4,17-17.4,73.2-31.9,105.4c-2.5,5.4-6.1,7.3,0.2,10.5
- c3.5,1.8,7.3,3,11.1,3.9c5.8,1.4,11.8,2.2,17.8,2.4c1,0,0.3,12.6,0,13.9c-1.1,4.9-11.8,6.3-15.8,7.4c-4.1,1.1-10.9,1.4-12.9,5.7
- c-3,6.4,9.9,4.8,13.1,5.4c10.3,1.9,19.4,7.6,27.4,14.1C389.6,337.4,397.6,344.2,399.8,352z M399.4,324.9c-5.1-4.7-10.4-9.3-16.3-13
- c8.8-8.8,4.7-25.9,3.7-36.9c-0.6-6.3-2-4.7-8.3-4.9c-6-0.2-12.8,0.1-18.5-1.8c7.2-22.3,1.3-45.2,5-67.9
- c2.8-17.1,14.5-25.5,31.5-25.5c15.4,0,26,7.7,29.2,23c4.9,23.1-2.6,47,4.5,70c-8.5,1.3-17.3,1-25.9,1.3c-2.1,0.1-1.9,25.1-1.7,27.3
- c0.7,11.7,6.1,18.8,17.2,23.3c12.1,4.9,31,3.6,38.4,15.9c-9.3,0-18.5,0-27.8,0c-5.6,0-11.2,0-16.9,0
- C406.4,335.8,404.6,329.6,399.4,324.9C394.4,320.3,403.4,328.5,399.4,324.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people.svg
deleted file mode 100644
index d478f537..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-people.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M349.2,334.8C360.5,338.7,338,330.9,349.2,334.8L349.2,334.8z"/>
- <path d="M349.2,334.8c-13.5-4.7-28.1-5-41.6-9.7c-4.1-1.4-12.2-3.1-13.9-7.8c-1.6-4.6-1.6-10-1.9-14.8c-0.2-3.8-0.3-7.6-0.3-11.4
- c0-2.5,6.4-7.8,7.8-10.1c5.4-9,5.9-21.1,6.9-31.3c8.7,2.4,9.8-13.7,11.3-18.6c1.1-3.4,7.8-26.8-2.6-23.6c2.5-4.4,3.5-9.8,4.2-14.7
- c2-12.8,2.8-26.8-1.1-39.3c-8.1-26-33-40.6-59.3-41.4c-26.7-0.9-53.5,11.9-63.5,37.8c-4.8,12.6-4.4,26.3-2.8,39.5
- c0.7,6,1.7,12.7,4.7,18.1c-9.7-2.9-4.5,17.7-3.4,21.3c1.6,5.1,3,23.4,12.1,20.9c0.8,8.1,1.7,16.4,3.9,24.3
- c1.5,5.3,4.6,9.8,8.2,13.9c1.8,2,2.7,2.2,2.6,4.8c-0.1,7.8,0.1,16.2-1.9,23.8c-2,7.6-18.7,10.8-25.4,12.2
- c-18,3.7-34.6,5.4-49.6,16.6C126.1,358.2,117,378.3,117,400c83.3,0,166.6,0,249.9,0c9.4,0,18.7,0,28.1,0
- C395,370.5,377.2,344.5,349.2,334.8z"/>
- <path d="M143.3,322.5c0.6-0.3,1.2-0.6,1.6-0.8c-0.3,0.1-0.6,0.3-0.8,0.4C143.8,322.2,143.6,322.3,143.3,322.5z"/>
- <path d="M143.3,322.5c-3.4,1.7-7.5,3.8,0.8-0.4c3-1.5,2.4-1.2,0.8-0.4c6.8-3.2,14.1-4,21.4-4.7c2.8-0.3,4.1-2.2,2-4.9
- c-4-5.1-17.8-6.1-23.6-8.4c-3.6-1.4-4.6-2.7-4.9-6.7c-0.1-1.8-1.1-9.8,0.3-11.1c1-1,7.3-0.6,8.7-0.8c5.7-0.7,11.5-1.9,16.9-4
- c2.3-0.9,4.5-2,6.5-3.4c2.4-1.8-1.8-6.2-2.9-8.6c-3.4-7.5-4.9-15.7-5.4-23.9c-1-16.1,1.5-32.3-1.5-48.3
- c-4.5-24.5-23.4-36.8-47.5-36.8c-14.9,0-29.6,5.1-37.9,18.1c-9.2,14.3-8.7,32.1-8.2,48.4c0.3,9.3,0.7,18.7-0.6,28
- c-0.6,4-1.5,7.9-2.9,11.7c-1.1,2.9-6.7,10.1-4.5,11.6c8.3,5.9,22.3,7.9,32.3,7.1c0.3,4.9,1.2,11.2-0.6,15.8
- c-2.8,7.2-23.7,9.1-30,11.2C45,317.8,32,332,32,352c18.3,0,36.5,0,54.8,0c8.2,0,16.4,0,24.7,0c1.3,0,6.3-9.3,7.7-10.8
- C126,333.7,134.3,327.2,143.3,322.5z"/>
- <path d="M449.3,311.9c-8.1-2.6-23.7-3.4-29.5-10.4c-2.9-3.5-1.3-12.4-1-16.6c4.4,0.4,9.2-0.3,13.7-0.9c4.1-0.6,8.1-1.4,12-2.8
- c1.8-0.7,3.6-1.4,5.3-2.4c3.9-2.3,2.1-2.7,0.1-6.1c-10.9-18.3-6-41.5-6.5-61.6c-0.4-16.7-4.8-35-20-44.4c-13.7-8.5-34-8.8-48.7-2.8
- c-42.4,17-17.4,73.2-31.9,105.4c-2.5,5.4-6.1,7.3,0.2,10.5c3.5,1.8,7.3,3,11.1,3.9c5.8,1.4,11.8,2.2,17.8,2.4c1,0,0.3,12.6,0,13.9
- c-1.1,4.9-11.8,6.3-15.8,7.4c-4.1,1.1-10.9,1.4-12.9,5.7c-3,6.4,9.9,4.8,13.1,5.4c10.3,1.9,19.4,7.6,27.4,14.1
- c6,4.9,14.1,11.5,16.3,19.5c26.7,0,53.5,0,80.2,0C480,332,466.9,317.7,449.3,311.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person-outline.svg
deleted file mode 100644
index 23a0bc19..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M202.4,201.7L202.4,201.7L202.4,201.7z"/>
- <path d="M363.3,363.9c-12.9-4.6-31.4-6.2-43.2-8.8c-6.8-1.5-16.7-5.3-20-9.2c-3.3-4-1.3-40.9-1.3-40.9s6.1-9.6,9.4-18
- s6.9-31.4,6.9-31.4s6.8,0,9.2-11.9c2.6-13,6.6-18.4,6.1-28.1c-0.5-9-5.2-9.5-5.7-9.5l0,0c0,0,4.9-13.6,5.6-42.4
- C331.1,129.6,305,96,256,96s-75,33.5-74.3,67.6c0.6,28.7,5.6,42.4,5.6,42.4l0,0c-0.5,0-5.2,0.5-5.7,9.5c-0.5,9.7,3.6,14.9,6.1,27.9
- c2.4,11.9,9.2,12,9.2,12s3.6,23.1,6.9,31.5c3.3,8.5,9.4,18,9.4,18s2,36.9-1.3,40.9c-3.3,4-13.2,7.7-20,9.2
- c-11.9,2.6-30.3,4.3-43.2,8.9C135.8,368.5,96,384,96,416h160h160C416,384,376.2,368.5,363.3,363.9z M256,400H118.7
- c2-3,4.7-5.1,8.2-7.6c7-5.1,16.1-9.8,27.1-13.6c6.8-2.4,16.7-4,25.4-5.3c5.7-0.9,11.1-1.7,15.9-2.8c3.4-0.8,20.8-5,28.8-14.6
- c4.5-5.4,5.8-12.7,5.6-32.3c-0.1-10-0.6-19.3-0.6-19.7l-0.2-4.2l-2.3-3.5c-1.5-2.3-5.8-9.5-8-15.3c-1.8-4.7-4.6-19.2-6-28.1
- c0,0,0.4,1-0.5-3.7c-0.9-4.7-8.4-4.3-9.4-8c-0.9-3.6-1.8-6.9-4.3-18.2c-2.5-11.3,2.8-11.2,3.9-16.2c0.6-3.1,0-5.7,0-5.8l0,0
- c-0.3-1-4.1-13.4-4.7-37.7c-0.3-13.2,4.6-25.6,13.8-34.9c10.6-10.8,26-16.5,44.5-16.5c19,0,34,5.7,44.6,16.5
- c9.2,9.3,14.1,21.7,13.8,34.9c-0.5,24.2-4.3,36.6-4.7,37.7l0,0c0,0.1-0.6,1.7-0.4,5.2c0.2,5.4,6.8,5.5,4.3,16.8
- c-2.5,11.3-3.4,14.6-4.3,18.2c-0.9,3.6-8.5,3.3-9.4,8c-0.9,4.7-0.5,3.7-0.5,3.7c-1.4,8.9-4.2,23.4-6,28.1c-2.3,5.8-6.6,13-8,15.3
- l-2.3,3.5l-0.2,4.2c0,0.4-0.5,9.7-0.6,19.7c-0.2,19.6,1.1,26.9,5.6,32.3c8,9.5,25.4,13.8,28.8,14.6c4.8,1.1,10.2,1.9,15.9,2.8
- c8.7,1.3,18.6,2.9,25.4,5.3c11,3.9,20.2,8.6,27.1,13.7c3.5,2.5,6.2,4.6,8.2,7.6L256,400L256,400z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person.svg
deleted file mode 100644
index d9b5d999..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-person.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M363.3,363.9c-12.9-4.6-31.4-6.2-43.2-8.8c-6.8-1.5-16.7-5.3-20-9.2c-3.3-4-1.3-40.9-1.3-40.9s6.1-9.6,9.4-18
- s6.9-31.4,6.9-31.4s6.8,0,9.2-11.9c2.6-13,6.6-18.4,6.1-28.1c-0.5-9-5.2-9.5-5.7-9.5l0,0c0,0,4.9-13.6,5.6-42.4
- C331.1,129.6,305,96,256,96s-75,33.5-74.3,67.6c0.6,28.7,5.6,42.4,5.6,42.4l0,0c-0.5,0-5.2,0.5-5.7,9.5c-0.5,9.7,3.6,14.9,6.1,27.9
- c2.4,11.9,9.2,12,9.2,12s3.6,23.1,6.9,31.5c3.3,8.5,9.4,18,9.4,18s2,36.9-1.3,40.9c-3.3,4-13.2,7.7-20,9.2
- c-11.9,2.6-30.3,4.3-43.2,8.9C135.8,368.5,96,384,96,416h160h160C416,384,376.2,368.5,363.3,363.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd-outline.svg
deleted file mode 100644
index acd809d8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd-outline.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="416,153 391,153 391,128 377,128 377,153 352,153 352,167 377,167 377,192 391,192 391,167 416,167 "/>
- <g>
- <path d="M202.4,201.7C202.4,201.7,202.4,201.7,202.4,201.7L202.4,201.7z"/>
- <path d="M363.3,363.9c-12.9-4.6-31.4-6.2-43.2-8.8c-6.8-1.5-16.7-5.3-20-9.2c-3.3-4-1.3-40.9-1.3-40.9s6.1-9.6,9.4-18
- c3.3-8.4,6.9-31.4,6.9-31.4s6.8,0,9.2-11.9c2.6-13,6.6-18.4,6.1-28.1c-0.5-9-5.2-9.5-5.7-9.5c0,0,0,0,0,0s4.9-13.6,5.6-42.4
- C331.1,129.6,305,96,256,96c-49,0-75,33.5-74.3,67.6c0.6,28.7,5.6,42.4,5.6,42.4s0,0,0,0c-0.5,0-5.2,0.5-5.7,9.5
- c-0.5,9.7,3.6,14.9,6.1,27.9c2.4,11.9,9.2,12,9.2,12s3.6,23.1,6.9,31.5c3.3,8.5,9.4,18,9.4,18s2,36.9-1.3,40.9
- c-3.3,4-13.2,7.7-20,9.2c-11.9,2.6-30.3,4.3-43.2,8.9C135.8,368.5,96,384,96,416h160h160C416,384,376.2,368.5,363.3,363.9z
- M256,400H118.7c2-3,4.7-5.1,8.2-7.6c7-5.1,16.1-9.8,27.1-13.6c6.8-2.4,16.7-4,25.4-5.3c5.7-0.9,11.1-1.7,15.9-2.8
- c3.4-0.8,20.8-5,28.8-14.6c4.5-5.4,5.8-12.7,5.6-32.3c-0.1-10-0.6-19.3-0.6-19.7l-0.2-4.2l-2.3-3.5c-1.5-2.3-5.8-9.5-8-15.3
- c-1.8-4.7-4.6-19.2-6-28.1c0,0,0.4,1-0.5-3.7c-0.9-4.7-8.4-4.3-9.4-8c-0.9-3.6-1.8-6.9-4.3-18.2c-2.5-11.3,2.8-11.2,3.9-16.2
- c0.6-3.1,0-5.7,0-5.8c0,0,0,0,0,0c-0.3-1-4.1-13.4-4.7-37.7c-0.3-13.2,4.6-25.6,13.8-34.9c10.6-10.8,26-16.5,44.5-16.5
- c19,0,34,5.7,44.6,16.5c9.2,9.3,14.1,21.7,13.8,34.9c-0.5,24.2-4.3,36.6-4.7,37.7c0,0,0,0,0,0c0,0.1-0.6,1.7-0.4,5.2
- c0.2,5.4,6.8,5.5,4.3,16.8c-2.5,11.3-3.4,14.6-4.3,18.2c-0.9,3.6-8.5,3.3-9.4,8s-0.5,3.7-0.5,3.7c-1.4,8.9-4.2,23.4-6,28.1
- c-2.3,5.8-6.6,13-8,15.3l-2.3,3.5l-0.2,4.2c0,0.4-0.5,9.7-0.6,19.7c-0.2,19.6,1.1,26.9,5.6,32.3c8,9.5,25.4,13.8,28.8,14.6
- c4.8,1.1,10.2,1.9,15.9,2.8c8.7,1.3,18.6,2.9,25.4,5.3c11,3.9,20.2,8.6,27.1,13.7c3.5,2.5,6.2,4.6,8.2,7.6H256z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd.svg
deleted file mode 100644
index 1ecf3429..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-personadd.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="416,153 391,153 391,128 377,128 377,153 352,153 352,167 377,167 377,192 391,192 391,167 416,167 "/>
- <g>
- <path d="M363.3,363.9c-12.9-4.6-31.4-6.2-43.2-8.8c-6.8-1.5-16.7-5.3-20-9.2c-3.3-4-1.3-40.9-1.3-40.9s6.1-9.6,9.4-18
- c3.3-8.4,6.9-31.4,6.9-31.4s6.8,0,9.2-11.9c2.6-13,6.6-18.4,6.1-28.1c-0.5-9-5.2-9.5-5.7-9.5c0,0,0,0,0,0s4.9-13.6,5.6-42.4
- C331.1,129.6,305,96,256,96c-49,0-75,33.5-74.3,67.6c0.6,28.7,5.6,42.4,5.6,42.4s0,0,0,0c-0.5,0-5.2,0.5-5.7,9.5
- c-0.5,9.7,3.6,14.9,6.1,27.9c2.4,11.9,9.2,12,9.2,12s3.6,23.1,6.9,31.5c3.3,8.5,9.4,18,9.4,18s2,36.9-1.3,40.9
- c-3.3,4-13.2,7.7-20,9.2c-11.9,2.6-30.3,4.3-43.2,8.9C135.8,368.5,96,384,96,416h160h160C416,384,376.2,368.5,363.3,363.9z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos-outline.svg
deleted file mode 100644
index df323c13..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M96,128v320h384V128H96z M464,432H112V144h352V432z"/>
- <polygon points="32,64 32,384 80,384 80,368 48,368 48,80 400,80 400,112 416,112 416,64 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos.svg
deleted file mode 100644
index 9a3b09e9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-photos.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M96,128v320h384V128H96z"/>
- <polygon points="416,64 32,64 32,384 80,384 80,112 416,112 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie-outline.svg
deleted file mode 100644
index 6c79a5d9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M288,80.826c45.293,3.705,87.354,23.024,119.809,55.494C444.044,172.57,464,220.744,464,272.043
- c0,25.924-5.08,51.042-15.099,74.703c-9.68,22.859-23.54,43.384-41.194,61.024c-17.654,17.639-38.204,31.481-61.08,41.151
- c-23.673,10.01-48.823,15.081-74.752,15.081c-41.193,0-80.47-12.847-113.584-37.146c-15.95-11.705-29.957-25.733-41.633-41.692
- c-8.378-11.453-15.422-23.724-21.041-36.634l180.259-45.008L288,300.496V288V81 M272,64v224L74.245,337.376
- C101.653,420.221,179.841,480,271.875,480C386.75,480,480,386.875,480,272S387,64,272,64L272,64z"/>
- <path d="M240,48.181v214.943L59.658,308.854c-9.117-23.568-11.197-56.973-11.158-69.496v-0.036v-0.035
- c0-47.311,16.465-93.746,45.173-127.398c16.735-19.618,37.502-34.981,61.721-45.663C180.099,55.331,208.519,49.274,240,48.181
- M256,32h-5.5C90.5,32,32,148.25,32,239.287c0,0,0.25,56.666,18.91,88.291L256,275.573V32L256,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie.svg
deleted file mode 100644
index 13e2e345..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pie.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M272,64v224L74.245,337.376C101.653,420.221,179.841,480,271.875,480C386.75,480,480,386.875,480,272S387,64,272,64L272,64
- z"/>
- <path d="M256,32h-5.5C90.5,32,32,148.25,32,239.287c0,0,0.25,56.666,18.91,88.291L256,275.573V32L256,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint-outline.svg
deleted file mode 100644
index 63753e05..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M368,170.085c0-21.022-0.973-88.554-19.308-125.013C344.244,36.228,336.25,32,316.999,32H195.001
- c-19.25,0-27.246,4.197-31.693,13.041C144.973,81.5,144,149.25,144,170.272c0,98,32,100.353,32,180.853c0,39.5-16,71.402-16,99.402
- c0,27,9,29.473,32,29.473h128c23,0,32-2.535,32-29.535c0-28-16-59.715-16-99.215C336,270.75,368,268.085,368,170.085z
- M177.602,51.983c0.778-1.546,1.339-1.763,2.53-2.295c1.977-0.884,6.161-1.688,14.869-1.688h121.998
- c8.708,0,12.893,0.803,14.869,1.687c1.19,0.532,1.752,0.872,2.53,2.418c8.029,15.967,13.601,42.611,16.105,75.896H161.496
- C164.001,94.653,169.572,67.951,177.602,51.983z M334.631,462.636C332.76,463.377,327.844,464,320,464H192
- c-7.844,0-12.761-0.623-14.639-1.359c-0.394-0.93-1.361-4.166-1.361-12.27c0-10.856,3.016-23.16,6.508-37.334
- c4.449-18.059,9.492-38.557,9.492-61.943c0-40.997-7.993-63.802-15.724-85.842C168.274,242.438,160,218.838,160,170.155
- c0-9.025,0.191-17.756,0.558-26.155h190.886c0.365,8.376,0.557,17.083,0.557,26.085c0,48.688-8.276,72.302-16.28,95.169
- c-7.728,22.079-15.72,44.895-15.72,85.887c0,23.39,5.043,43.822,9.493,61.856c3.491,14.15,6.507,26.368,6.507,37.222
- C336,458.355,335.024,461.713,334.631,462.636z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint.svg
deleted file mode 100644
index 0f6f784e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pint.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M368,170.085c0-21.022-0.973-88.554-19.308-125.013C344.244,36.228,336.25,32,316.999,32H195.001
- c-19.25,0-27.246,4.197-31.693,13.041C144.973,81.5,144,149.25,144,170.272c0,98,32,100.353,32,180.853c0,39.5-16,71.402-16,99.402
- c0,27,9,29.473,32,29.473h128c23,0,32-2.535,32-29.535c0-28-16-59.715-16-99.215C336,270.75,368,268.085,368,170.085z
- M177.602,51.983c0.778-1.546,1.339-1.763,2.53-2.295c1.977-0.884,6.161-1.688,14.869-1.688h121.998
- c8.708,0,12.893,0.803,14.869,1.687c1.19,0.532,1.752,0.872,2.53,2.418c8.029,15.967,13.601,42.611,16.105,75.896H161.496
- C164.001,94.653,169.572,67.951,177.602,51.983z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play-outline.svg
deleted file mode 100644
index 8e95177e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play-outline.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M144,124.9L353.8,256L144,387.1V124.9 M128,96v320l256-160L128,96L128,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play.svg
deleted file mode 100644
index 48366336..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-play.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M128,96v320l256-160L128,96L128,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-empty.svg
deleted file mode 100644
index 4fdb3bf4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-empty.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M384,265H264v119h-17V265H128v-17h119V128h17v120h120V265z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-outline.svg
deleted file mode 100644
index 3979af47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus-outline.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7S150.9,65.3,256,65.3S446.7,150.9,446.7,256S361.1,446.7,256,446.7z"/>
- </g>
- </g>
- <g>
- <polygon points="264.1,128 247.3,128 247.3,247.9 128,247.9 128,264.7 247.3,264.7 247.3,384 264.1,384 264.1,264.7 384,264.7
- 384,247.9 264.1,247.9 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus.svg
deleted file mode 100644
index 73f7272c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-plus.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M384,265H264v119h-17V265
- H128v-17h119V128h17v120h120V265z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag-outline.svg
deleted file mode 100644
index 59e41e33..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M464,32H304L48,320l160,160l256-288V32z M448,184L208.125,456L72.062,320L311.587,48H448V184z"/>
- <path d="M368,160c17.645,0,32-14.355,32-32s-14.355-32-32-32s-32,14.355-32,32S350.355,160,368,160z M368,112
- c8.836,0,16,7.163,16,16s-7.164,16-16,16s-16-7.163-16-16S359.164,112,368,112z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag.svg
deleted file mode 100644
index 577a9c70..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetag.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="368" cy="128" r="16"/>
- <path d="M304,32L48,320l160,160l256-288V32H304z M368,160c-17.645,0-32-14.355-32-32s14.355-32,32-32s32,14.355,32,32
- S385.645,160,368,160z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags-outline.svg
deleted file mode 100644
index ea8650c2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M448,64V32H288L32,320l160,160l23.471-23.904L240,480l240-272V64H448z M192,457.371L54.39,320L294.621,48H432v16v16
- v105.377l-216.555,247.99l-11.34,11.363L192,457.371z M464,201.377L240,457.371l-13.182-12.65L448,192V80h16V201.377z"/>
- <path d="M352,160c17.645,0,32-14.355,32-32s-14.355-32-32-32s-32,14.355-32,32S334.355,160,352,160z M352,112
- c8.836,0,16,7.163,16,16s-7.164,16-16,16s-16-7.163-16-16S343.164,112,352,112z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags.svg
deleted file mode 100644
index 67f45a46..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pricetags.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <polygon points="464,64 464,201.377 227.153,467.48 240,480 480,208 480,64 "/>
- </g>
- <g>
- <path d="M288,32L32,320l160,160l23.471-23.904l11.348-11.375L448,192V80V64V32H288z M352,160c-17.645,0-32-14.355-32-32
- s14.355-32,32-32s32,14.355,32,32S369.645,160,352,160z"/>
- <circle cx="352" cy="128" r="16"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer-outline.svg
deleted file mode 100644
index a0530d7a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M432.5,112H400V64H112v48H80.5C62.9,112,48,125.8,48,143.3v158.4c0,17.5,14.9,32.3,32.5,32.3H128v114h256V334h48.5
- c17.6,0,31.5-14.8,31.5-32.3V143.3C464,125.8,450.1,112,432.5,112z M128,80h256v32H128V80z M368,432H144V240h224V432z M448,301.7
- c0,8.7-6.7,16.3-15.5,16.3H384v-94H128v94H80.5c-8.8,0-16.5-7.6-16.5-16.3V143.3c0-8.7,7.7-15.3,16.5-15.3H432h0.5
- c8.8,0,15.5,6.6,15.5,15.3V301.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer.svg
deleted file mode 100644
index 70b36892..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-printer.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="128" y="224" width="256" height="224"/>
-</g>
-<g>
- <rect x="127.5" y="224.5" width="256" height="224"/>
- <g>
- <rect x="111.5" y="64.5" width="288" height="32"/>
- <path d="M432.5,112.5h-352c-17.645,0-33,12.842-33,30.309v158.393c0,17.468,15.355,33.299,33,33.299h31v-126h288v126h33
- c17.645,0,31-15.831,31-33.299V142.809C463.5,125.342,450.145,112.5,432.5,112.5z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse-strong.svg
deleted file mode 100644
index c1542904..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse-strong.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,273.001c-21.27,0-39.296,13.999-45.596,32.999h-38.857l-28.361-85.417c-2.176-6.553-8.303-10.956-15.183-10.956
- c-0.112,0-0.224,0-0.335,0.004c-7.016,0.145-13.117,4.844-15.049,11.588l-44.484,155.262L207.782,62.373
- C206.535,54.893,200.333,48,192,48s-13.693,5.776-15.525,13.135L115.496,306H16v31.999h112c7.348,0,13.75-5.003,15.525-12.134
- l45.368-182.177l51.324,307.94c1.229,7.377,7.397,11.92,14.864,12.344C255.389,463.99,255.695,464,256,464
- c7.097,0,13.406-3.701,15.381-10.594l49.744-173.617l15.689,47.252c2.173,6.543,8.292,10.958,15.186,10.958h51.108
- C409.973,355.999,427.477,369,448,369c26.511,0,48-22.492,48-49C496,293.491,474.511,273.001,448,273.001z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse.svg
deleted file mode 100644
index f347850a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-pulse.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,288c-15.268,0-28.029,10.695-31.223,25h-59.004l-30.181-90.896c-1.105-3.329-4.246-5.543-7.759-5.478
- c-3.508,0.072-6.559,2.422-7.524,5.795L258.067,411.74L199.892,62.685c-0.624-3.74-3.787-6.528-7.576-6.679
- c-3.809-0.139-7.161,2.382-8.078,6.061L121.748,313H32v16h96c3.674,0,6.875-2.502,7.763-6.066l54.685-219.591l57.661,345.973
- c0.615,3.688,3.703,6.459,7.437,6.672c0.153,0.009,0.307,0.013,0.459,0.013c3.549,0,6.699-2.35,7.687-5.797l56.872-198.496
- l23.845,71.813c1.087,3.271,4.146,5.479,7.593,5.479h65.292c3.89,13.289,16.161,23,30.708,23c17.674,0,32-14.327,32-32
- S465.674,288,448,288z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy-outline.svg
deleted file mode 100644
index 815f6aa7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M332.1,179.4c-2.8,0-5.7-0.1-8.4,0.3c-8.3-36.8-35.2-67.6-80.3-67.6c-50.9,0-82.3,38-82.3,83.6
- c0,2.8,0.1,5.5,0.4,8.2c-27.7,2.5-49.5,31.3-49.5,59.8c0,29.2,22.9,54.6,51.6,56.2l-24.5,34.4c-1.1,1.6-2,3.4-2,5.5
- c0,4.6,3.7,8.3,8.3,8.3c3,0,5.6-1.6,7.1-4l31-43.8h36.1l-46.1,65.8c-1.2,1.6-2.1,3.6-2.1,5.6c0,4.6,3.7,8.3,8.3,8.3
- c3,0,5.6-1.8,7.2-4.3l52.6-75.5h37.9l-24.9,34.4c-1.2,1.6-2.2,3.8-2.2,5.6c0,4.6,3.7,8.3,8.3,8.3c3.1,0,5.4-1.7,7.2-4.1l31.6-44.3
- h34.7c0.1,0,0.3-0.1,0.4-0.1l-46.1,65.9c-1.3,1.7-2.3,3.6-2.3,5.8c0,4.6,3.7,8.3,8.3,8.3c3.2,0,5.5-2,7.4-4.5l55.5-79.8
- c26-9.9,44.6-35.8,44.6-65.2C400,212.8,369.6,179.4,332.1,179.4z M332.1,302.1H290l-0.1-0.1l-0.1,0.1H166.4
- c-10,0-19.5-4.6-26.7-11.9c-7.2-7.3-11.1-17.2-11.1-27.4c0-19.6,15.2-39.8,34.9-43c1.7-0.3,9.2-1.4,15-1.9c0,0-0.5-5.6-0.7-10.2
- c-0.1-4.6-0.1-9.9-0.1-12.1c0-36.4,29.5-66.9,65.8-66.9c15.2,0,29.5,5.1,41.3,14.7c11.5,9.3,19.6,25.4,22.8,39.7l3.3,14.7l14.9-1.9
- c2.2-0.3,4.3-0.4,6.4-0.4c28.3,0,51.3,25.9,51.3,54.4C383.4,278.3,360.4,302.1,332.1,302.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy.svg
deleted file mode 100644
index 143caf0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rainy.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M332.1,179.4c-2.8,0-5.7-0.1-8.4,0.3c-8.3-36.8-35.2-67.6-80.3-67.6c-50.9,0-82.3,38-82.3,83.6
- c0,2.8,0.1,5.5,0.4,8.2c-27.7,2.5-49.5,31.3-49.5,59.8c0,29.2,22.9,54.6,51.6,56.2l-24.5,34.4c-1.1,1.6-2,3.4-2,5.5
- c0,4.6,3.7,8.3,8.3,8.3c3,0,5.6-1.6,7.1-4l31-43.8h36.1l-46.1,65.8c-1.2,1.6-2.1,3.6-2.1,5.6c0,4.6,3.7,8.3,8.3,8.3
- c3,0,5.6-1.8,7.2-4.3l52.6-75.5h37.9l-24.9,34.4c-1.2,1.6-2.2,3.8-2.2,5.6c0,4.6,3.7,8.3,8.3,8.3c3.1,0,5.4-1.7,7.2-4.1l31.6-44.3
- h34.7c0.1,0,0.3-0.1,0.4-0.1l-46.1,65.9c-1.3,1.7-2.3,3.6-2.3,5.8c0,4.6,3.7,8.3,8.3,8.3c3.2,0,5.5-2,7.4-4.5l55.5-79.8
- c26-9.9,44.6-35.8,44.6-65.2C400,212.8,369.6,179.4,332.1,179.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording-outline.svg
deleted file mode 100644
index 20995a38..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M386.2,144c-60.6,0-109.8,50.1-109.8,112c0,40.4,21,75.7,52.5,95.4H183.1c31.5-19.7,52.5-55,52.5-95.4
- c0-61.9-49.2-112-109.8-112C65.2,144,16,194.1,16,256c0,61.9,49.2,112,109.8,112h260.4c60.6,0,109.8-50.1,109.8-112
- C496,194.1,446.8,144,386.2,144z M32.3,256c0-52.6,42-95.4,93.5-95.4c51.6,0,93.5,42.8,93.5,95.4s-42,95.4-93.5,95.4
- C74.2,351.4,32.3,308.6,32.3,256z M386.2,351.4c-51.6,0-93.5-42.8-93.5-95.4s42-95.4,93.5-95.4s93.5,42.8,93.5,95.4
- S437.8,351.4,386.2,351.4z"/>
-<path d="M384,208c26.5,0,48,21.5,48,48c0,26.5-21.5,48-48,48s-48-21.5-48-48C336,229.5,357.5,208,384,208 M384,192
- c-35.3,0-64,28.7-64,64c0,35.3,28.7,64,64,64s64-28.7,64-64C448,220.7,419.3,192,384,192L384,192z"/>
-<path d="M128,208c26.5,0,48,21.5,48,48c0,26.5-21.5,48-48,48s-48-21.5-48-48C80,229.5,101.5,208,128,208 M128,192
- c-35.3,0-64,28.7-64,64c0,35.3,28.7,64,64,64s64-28.7,64-64C192,220.7,163.3,192,128,192L128,192z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording.svg
deleted file mode 100644
index 97ecfed7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-recording.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M386.2,144c-60.6,0-109.8,49.9-109.8,111.8c0,40.4,21,76.2,52.5,95.2H183.1c31.5-19,52.5-54.8,52.5-95.2
- c0-61.9-49.2-111.9-109.8-111.9C65.2,143.9,16,194.1,16,255.9C16,317.8,65.2,368,125.8,368h260.4c60.6,0,109.8-50.1,109.8-112
- C496,194.1,446.8,144,386.2,144z M128,320c-35.3,0-64-28.7-64-64c0-35.3,28.7-64,64-64s64,28.7,64,64C192,291.3,163.3,320,128,320z
- M384,320c-35.3,0-64-28.7-64-64c0-35.3,28.7-64,64-64s64,28.7,64,64C448,291.3,419.3,320,384,320z"/>
- <path d="M384,208c-26.5,0-48,21.5-48,48c0,26.5,21.5,48,48,48s48-21.5,48-48C432,229.5,410.5,208,384,208z"/>
- <path d="M128,208c-26.5,0-48,21.5-48,48c0,26.5,21.5,48,48,48s48-21.5,48-48C176,229.5,154.5,208,128,208z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo-outline.svg
deleted file mode 100644
index 02a6d2cc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,400h10.3l19.2-31.2c20.5-32.7,44.9-62.8,75.8-76.6c24.4-10.9,46.7-18.9,86.7-20V352l192-128L256,96v80.3
- c-63,2.8-108.1,20.7-143.3,56.2c-52.3,52.7-48.7,119-48.7,135.7C64.1,377.1,64,389.9,64,400z M272,192v-64.7l148.1,96.8L272,320.8
- V256c-91,0-144.6,24.6-192.2,105.4C79.8,361.4,71,192,272,192z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo.svg
deleted file mode 100644
index abd3c15a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-redo.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,400h10.3l19.2-31.2c20.5-32.7,44.9-62.8,75.8-76.6c24.4-10.9,46.7-18.9,86.7-20V352l192-128L256,96v80.3
- c-63,2.8-108.1,20.7-143.3,56.2c-52.3,52.7-48.7,119-48.7,135.7C64.1,377.1,64,389.9,64,400z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-empty.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-empty.svg
deleted file mode 100644
index bf6b8410..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-empty.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,384.1c-70.7,0-128-57.3-128-128.1c0-70.8,57.3-128.1,128-128.1V84l96,64l-96,55.7v-55.8
- c-59.6,0-108.1,48.5-108.1,108.1c0,59.6,48.5,108.1,108.1,108.1S364.1,316,364.1,256H384C384,327,326.7,384.1,256,384.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-outline.svg
deleted file mode 100644
index c2048a17..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M364.1,256c0,60-48.5,108.2-108.1,108.2S147.9,315.7,147.9,256c0-59.6,48.5-108.1,108.1-108.1v55.8l96-55.7l-96-64v44
- c-70.7,0-128,57.4-128,128.1c0,70.8,57.3,128.1,128,128.1c70.7,0,128-57.1,128-128.1H364.1z"/>
-<g>
- <g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,446.7
- c-105.1,0-190.7-85.5-190.7-190.7c0-105.1,85.5-190.7,190.7-190.7c105.1,0,190.7,85.5,190.7,190.7
- C446.7,361.1,361.1,446.7,256,446.7z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh.svg
deleted file mode 100644
index 95bc848a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-refresh.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48C141.1,48,48,141.1,48,256s93.1,208,208,208c114.9,0,208-93.1,208-208S370.9,48,256,48z M256,384.1
- c-70.7,0-128-57.3-128-128.1c0-70.8,57.3-128.1,128-128.1V84l96,64l-96,55.7v-55.8c-59.6,0-108.1,48.5-108.1,108.1
- c0,59.6,48.5,108.1,108.1,108.1S364.1,316,364.1,256H384C384,327,326.7,384.1,256,384.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reload.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reload.svg
deleted file mode 100644
index c730d6db..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reload.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g id="PL_x5F_Reset_1_">
- <path d="M256,64c105.9,0,191.7,85.7,191.9,191.5l55-52.5l9,9.1L441.6,280L375,212.1l9-9.1l51.1,52.4
- C434.8,156.9,354.6,76.8,256,76.8c-98.8,0-179.2,80.4-179.2,179.2c0,98.8,80.4,179.2,179.2,179.2c78.6,0,145.5-51,169.5-121.6
- l12.4,3.5C412.3,393.2,340.6,448,256,448c-106,0-192-86-192-192S150,64,256,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera-outline.svg
deleted file mode 100644
index 49dd4b14..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M301.815,318.608c-13.114,11.029-28.956,17.356-45.815,17.356c-36.36,0-66.286-28.965-70.89-61.965h30.61l-38.87-50
- l-37.534,50h29.479c4.696,42,41.717,78,87.205,78c20.9,0,41.17-7.566,57.076-21.218l2.37-2.159l-11.599-11.662L301.815,318.608z"/>
- <path d="M315.736,198.885c-16.188-14.775-37.402-22.839-59.736-22.839c-20.9,0-41.169,7.556-57.075,21.206l-2.371,2.052
- l11.599,11.61l2.033-1.706c12.927-10.872,29.197-17.005,45.814-17.005c36.343,0,66.274,28.797,70.891,63.797h-30.644l38.846,51.225
- L372.719,256h-29.512C340.966,236,331.275,213.064,315.736,198.885z"/>
- <path d="M417.5,160h-61.725c-32.105-36-42.219-48-54.525-48h-88.5c-12.314,0-22.167,12-54.521,48H145v-16h-34v16H97.5
- C79.855,160,64,173.217,64,190.684v176.018C64,384.169,79.855,400,97.5,400h320c17.645,0,30.5-15.831,30.5-33.299V190.684
- C448,173.217,435.145,160,417.5,160z M432,366.701c0,9.263-6.229,17.299-14.5,17.299h-320c-8.738,0-17.5-8.664-17.5-17.299V190.684
- C80,182.518,88.126,176,97.5,176h60.729c0,0,4.124,0,6.133,0s3.225-0.199,5.768-3.2s7.702-10.008,11.08-13.795
- c11.296-12.666,19.457-21.915,25.316-27.132c4.746-4.225,6.211-3.873,6.225-3.873h88.5c0.016,0,1.611-0.363,6.709,4.219
- c6.141,5.521,14.705,16.84,26.558,30.198c2.888,3.255,7.214,8.11,9.317,10.44s4.252,3.143,5.771,3.143s6.17,0,6.17,0H417.5
- c8.832,0,14.5,5.965,14.5,14.684V366.701z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera.svg
deleted file mode 100644
index 4acec0a6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-reverse-camera.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M417.5,160h-61.725c-32.105-36-42.219-48-54.525-48h-88.5c-12.314,0-22.167,12-54.521,48H145v-16h-34v16H97.5
- C79.855,160,64,173.217,64,190.684v176.018C64,384.169,79.855,400,97.5,400h320c17.645,0,30.5-15.831,30.5-33.299V190.684
- C448,173.217,435.145,160,417.5,160z M313.076,330.782C297.17,344.434,276.9,352,256,352c-45.487,0-82.509-36-87.205-78h-29.479
- l37.534-50l38.87,50h-30.61c4.604,33,34.53,61.965,70.89,61.965c16.859,0,32.701-6.327,45.815-17.356l2.032-1.647l11.599,11.662
- L313.076,330.782z M335.094,307.225L296.248,256h30.644c-4.617-35-34.548-63.797-70.891-63.797
- c-16.618,0-32.888,6.133-45.814,17.005l-2.033,1.706l-11.599-11.61l2.371-2.052c15.905-13.65,36.175-21.206,57.075-21.206
- c22.333,0,43.548,8.063,59.736,22.839C331.275,213.064,340.966,236,343.207,256h29.512L335.094,307.225z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind-outline.svg
deleted file mode 100644
index 2b722c86..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M464,155v201.9L280.5,256L464,155 M240,156v77.7v27.1v95.6L64,256l176-100.2 M256,128L32,256l224,128V260.8L480,384V128
- L256,251.2V128L256,128z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind.svg
deleted file mode 100644
index 808e3a4e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rewind.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,128L32,256l224,128V260.8L480,384V128L256,251.2V128L256,128z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose-outline.svg
deleted file mode 100644
index 30e04110..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose-outline.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M379.769,153.431c-29.777,55.586-17.604,99.504-6.645,139.039C378.717,312.648,384,331.708,384,351.889
- c0,15.897-2.956,30.873-8.785,44.51c-5.727,13.396-14.104,25.212-24.898,35.12C327.169,452.768,294.555,464,256,464
- s-71.169-11.232-94.316-32.481c-10.795-9.908-19.172-21.725-24.898-35.12c-5.829-13.637-8.785-28.612-8.785-44.51
- c0-31.65,6.92-55.999,21.775-76.626c13.061-18.134,32.646-34.094,63.505-51.749l6.506-3.725
- c20.197-11.57,27.001-15.467,43.976-23.588c31.845-15.234,66.513-28.387,103.041-39.094
- C371.088,155.851,375.412,154.625,379.769,153.431 M416,128c-18.863,4.163-36.75,8.786-53.697,13.753
- c-40.457,11.858-75.509,25.693-105.445,40.015c-19.271,9.219-26.236,13.393-51.522,27.859C147.001,243,112,278.926,112,351.889
- S167.635,480,256,480s144-55.148,144-128.111S338.999,224,416,128L416,128z"/>
- <path d="M133.516,123.147c21.432,6.955,47.724,16.977,69.799,29.846c6.385,3.723,12.092,7.493,17.092,11.291
- c-5.504,2.905-10.895,5.855-16.138,8.833c-7.212,4.096-14.359,8.362-21.243,12.679c-10.484,6.574-20.435,13.308-29.789,20.156
- C152.637,180.034,147.555,151.15,133.516,123.147 M96,96c41.475,47.079,44.624,103.891,39.382,144.741
- c12.772-11.274,31.177-25.734,56.144-41.389c6.442-4.041,13.312-8.158,20.645-12.322c11.578-6.575,23.538-12.822,35.834-18.765
- c-9.113-10.898-22.07-20.606-36.631-29.095C162.631,110.756,96,96,96,96L96,96z"/>
- <path d="M344.629,80.697c5.309,7.227,12.393,17.661,17.66,27.726c-29.863,8.433-65.994,21.145-94.967,33.476
- c-5.963-6.235-12.982-12.294-21.006-18.135c17.437-15.757,38.773-27.668,63.652-35.506
- C324.518,83.675,337.016,81.612,344.629,80.697 M352,64c0,0-78.623,2.321-130.681,62.469c16.629,9.903,29.735,20.503,38.959,31.533
- l2.724,3.257c37.152-16.794,88.131-34.085,120.998-42.009C377.617,95.827,352,64,352,64L352,64z"/>
- <path d="M181.229,53.532c9.241,6.122,22.68,16.481,35.999,31.924c-4.851,4.201-9.487,8.623-13.888,13.247
- c-14.024-7.088-24.951-12.192-36.826-16.602C170.174,73.63,175.095,63.788,181.229,53.532 M176,32
- c-15.256,22.406-25.684,45.299-30.336,59.997c21.111,6.355,35.475,13.215,61.389,26.574c9.505-11.4,20.415-21.626,32.605-30.543
- C210.342,47.655,176,32,176,32L176,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose.svg
deleted file mode 100644
index 7bf76c5f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-rose.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M416,128c-18.863,4.163-36.75,8.786-53.697,13.753c-40.457,11.858-75.509,25.693-105.445,40.015
- c-19.271,9.219-26.236,13.393-51.522,27.859C147.001,243,112,278.926,112,351.889S167.635,480,256,480s144-55.148,144-128.111
- S338.999,224,416,128L416,128z"/>
- <path d="M96,96c41.475,47.079,44.624,103.891,39.382,144.741c12.772-11.274,31.177-25.734,56.144-41.389
- c6.442-4.041,13.312-8.158,20.645-12.322c11.578-6.575,23.538-12.822,35.834-18.765c-9.113-10.898-22.07-20.606-36.631-29.095
- C162.631,110.756,96,96,96,96L96,96z"/>
- <path d="M352,64c0,0-78.623,2.321-130.681,62.469c16.629,9.903,29.735,20.503,38.959,31.533l2.724,3.257
- c37.152-16.794,88.131-34.085,120.998-42.009C377.617,95.827,352,64,352,64L352,64z"/>
- <path d="M176,32c-15.256,22.406-25.684,45.299-30.336,59.997c21.111,6.355,35.475,13.215,61.389,26.574
- c9.505-11.4,20.415-21.626,32.605-30.543C210.342,47.655,176,32,176,32L176,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search-strong.svg
deleted file mode 100644
index 6960eb1a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search-strong.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M344.5,298c15-23.6,23.8-51.6,23.8-81.7c0-84.1-68.1-152.3-152.1-152.3C132.1,64,64,132.2,64,216.3
- c0,84.1,68.1,152.3,152.1,152.3c30.5,0,58.9-9,82.7-24.4l6.9-4.8L414.3,448l33.7-34.3L339.5,305.1L344.5,298z M301.4,131.2
- c22.7,22.7,35.2,52.9,35.2,85c0,32.1-12.5,62.3-35.2,85c-22.7,22.7-52.9,35.2-85,35.2c-32.1,0-62.3-12.5-85-35.2
- c-22.7-22.7-35.2-52.9-35.2-85c0-32.1,12.5-62.3,35.2-85c22.7-22.7,52.9-35.2,85-35.2C248.5,96,278.7,108.5,301.4,131.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search.svg
deleted file mode 100644
index ff477918..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-search.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448.3,424.7L335,311.3c20.8-26,33.3-59.1,33.3-95.1c0-84.1-68.1-152.2-152-152.2c-84,0-152,68.2-152,152.2
- s68.1,152.2,152,152.2c36.2,0,69.4-12.7,95.5-33.8L425,448L448.3,424.7z M120.1,312.6c-25.7-25.7-39.8-59.9-39.8-96.3
- s14.2-70.6,39.8-96.3S180,80,216.3,80c36.3,0,70.5,14.2,96.2,39.9s39.8,59.9,39.8,96.3s-14.2,70.6-39.8,96.3
- c-25.7,25.7-59.9,39.9-96.2,39.9C180,352.5,145.8,338.3,120.1,312.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings-strong.svg
deleted file mode 100644
index cb15e18b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings-strong.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M32,376h283.35c6.186-14.112,20.281-24,36.65-24s30.465,9.888,36.65,24H480v32h-91.35c-6.186,14.112-20.281,24-36.65,24
- s-30.465-9.888-36.65-24H32"/>
- <path d="M32,240h91.35c6.186-14.112,20.281-24,36.65-24s30.465,9.888,36.65,24H480v32H196.65c-6.186,14.112-20.281,24-36.65,24
- s-30.465-9.888-36.65-24H32"/>
- <path d="M32,104h283.35c6.186-14.112,20.281-24,36.65-24s30.465,9.888,36.65,24H480v32h-91.35c-6.186,14.112-20.281,24-36.65,24
- s-30.465-9.888-36.65-24H32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings.svg
deleted file mode 100644
index bb60a997..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-settings.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M352,104c8.837,0,16,7.163,16,16s-7.163,16-16,16s-16-7.163-16-16S343.163,104,352,104 M352,88c-17.645,0-32,14.355-32,32
- s14.355,32,32,32s32-14.355,32-32S369.645,88,352,88L352,88z"/>
- <path d="M352,376c8.837,0,16,7.163,16,16s-7.163,16-16,16s-16-7.163-16-16S343.163,376,352,376 M352,360c-17.645,0-32,14.355-32,32
- s14.355,32,32,32s32-14.355,32-32S369.645,360,352,360L352,360z"/>
- <g>
- <path d="M160,240c8.837,0,16,7.163,16,16s-7.163,16-16,16s-16-7.163-16-16S151.163,240,160,240 M160,224
- c-17.645,0-32,14.355-32,32s14.355,32,32,32s32-14.355,32-32S177.645,224,160,224L160,224z"/>
- <g>
- <path d="M207.32,248H480v16H207.32c0.439-2.604,0.68-5.273,0.68-8S207.76,250.604,207.32,248z"/>
- <path d="M112,256c0,2.727,0.24,5.396,0.68,8H32v-16h80.68C112.24,250.604,112,253.273,112,256z"/>
- <path d="M399.32,384H480v16h-80.68c0.439-2.604,0.68-5.273,0.68-8S399.76,386.604,399.32,384z"/>
- <path d="M304,392c0,2.727,0.24,5.396,0.68,8H32v-16h272.68C304.24,386.604,304,389.273,304,392z"/>
- <path d="M399.32,112H480v16h-80.68c0.439-2.604,0.68-5.273,0.68-8S399.76,114.604,399.32,112z"/>
- <path d="M304.68,112c-0.439,2.604-0.68,5.273-0.68,8s0.24,5.396,0.68,8H32v-16H304.68z"/>
- </g>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle-strong.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle-strong.svg
deleted file mode 100644
index 006b090d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle-strong.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M365.419,152h13.81l-50.738,41.584l20.308,24.572L448,136l-99.136-84l-20.368,24.978L379.679,120h-14.26
- c-103.727,0-146.494,79.62-180.857,143.727c-1.362,2.542-2.715,4.99-4.06,7.488l-0.059,0.095c-1.591,2.953-3.176,6.114-4.76,9.038
- c-35.562,65.63-66.893,83.214-111.684,83.641V396c37.625,0,57.563-9.451,72.236-18.178c24.935-14.831,47.042-44.559,67.583-82.467
- c1.541-2.844,3.083-5.752,4.632-8.626l0.225-0.438c1.459-2.711,2.922-5.273,4.39-8.014C246.369,216.113,280.808,152,365.419,152z"
- />
- <path d="M348.798,293.844l-20.308,24.572L379.229,360h-13.81c-70.728,0-106.396-44.801-135.649-95.812l-17.648,32.618
- C243.556,346.626,287.116,392,365.419,392h14.26l-51.183,43.022L348.864,460L448,376L348.798,293.844z"/>
- <path d="M175.684,231.652c1.584,2.924,3.169,6.085,4.76,9.038l0.059,0.095c1.218,2.262,2.442,4.49,3.675,6.777
- c5.82-10.73,11.98-21.748,18.695-32.649c-20.273-37.079-42.083-66.132-66.636-80.735C121.563,125.451,101.625,116,64,116v32.011
- C108.791,148.438,140.122,166.022,175.684,231.652z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle.svg
deleted file mode 100644
index 84bdbcbc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-shuffle.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M362.121,207.146L352,194.854L413.784,144h-46.117c-93.327,0-129.147,74.511-163.787,138.832
- c-1.62,3.008-3.233,6.004-4.846,8.979c-19.836,36.607-40.979,61.242-64.64,75.314C120.573,375.346,101.401,384,64,384v-16.25
- c47.937,0,83.098-13.673,120.966-83.561c1.606-2.965,3.214-5.949,4.827-8.944C224.943,209.977,264.784,128,367.667,128h46.28
- L352,76.146L362.121,64L448,136L362.121,207.146z"/>
- <g>
- <path d="M199.034,220.189c-19.836-36.607-40.979-61.242-64.64-75.314C120.573,136.654,101.401,128,64,128v16.25
- c47.937,0,83.098,13.673,120.966,83.561c1.606,2.964,3.214,5.948,4.827,8.944c0.438,0.812,0.875,1.627,1.314,2.444
- c3.01-5.438,6.107-10.917,9.339-16.394C199.977,221.935,199.504,221.056,199.034,220.189z"/>
- <path d="M362.121,304.854L352,317.146L413.784,368h-46.117c-72.693,0-110.496-45.207-140.028-95.592
- c-1.768,3.275-3.525,6.551-5.273,9.814c-1.175,2.192-2.344,4.37-3.513,6.545C249.621,338.777,291.254,384,367.667,384h46.28
- L352,435.854L362.121,448L448,376L362.121,304.854z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward-outline.svg
deleted file mode 100644
index 2bbaa94a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M96,96v320h79V274.2L416,416V96L175,237.8V96H96z M175.6,256l7.6-4.4L400,124v0v264L183.1,260.4L175.6,256z M112,112h47
- v125.8v28v8.5V400h-47V112z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward.svg
deleted file mode 100644
index 6f8dc87f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipbackward.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M96,96v320h79V274.2L416,416V96L175,237.8V96H96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward-outline.svg
deleted file mode 100644
index 1c9e1f5b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M337,96v141.8L96,96v320l241-141.8V416h79V96H337z M328.9,260.4L112,388V124v0l216.9,127.6l7.6,4.4L328.9,260.4z M400,400
- h-47V274.2v-8.5v-28V112h47V400z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward.svg
deleted file mode 100644
index 139a170b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-skipforward.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M337,96v141.8L96,96v320l241-141.8V416h79V96H337z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-snowy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-snowy.svg
deleted file mode 100644
index 2dd8a843..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-snowy.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M379.9,317l-28.7-16.3c6.1-5.8,13-9.7,20.7-12.3c4.3-1.4,6.5-5.9,5.1-10.1c-1.4-4.2-6-6.5-10.3-5.1
- c-11.6,3.8-22.2,11-30.1,19.2L272.3,256l64.2-36.4c8.4,9.1,18.6,15.4,30.2,19.2c4.3,1.4,8.9-0.8,10.3-5c1.4-4.2-0.8-8.7-5.1-10.1
- c-7.8-2.6-14.8-6.5-20.9-12.3l28.8-16.3c3.9-2.2,5.2-7.1,3-10.9s-7.2-5.1-11.1-2.9L343,197.3c-2-8.1-2.1-15.9-0.5-23.8
- c0.9-4.3-2-8.5-6.4-9.4c-4.4-0.9-8.7,1.9-9.6,6.2c-2.4,11.8-1.4,24.4,1.8,35.2L264,242.2v-73c11-2.7,22.4-8.1,31.5-16.1
- c3.3-2.9,3.6-8,0.7-11.3c-2.9-3.3-7.9-3.6-11.3-0.7c-6,5.3-12.9,9.2-20.9,11.5V120c0-4.4-3.6-8-8-8c-4.4,0-8,3.6-8,8v32.7
- c-8-2.3-14.8-6.2-20.9-11.6c-3.3-2.9-8.4-2.6-11.3,0.7c-2.9,3.3-2.6,8.4,0.7,11.3c9.1,8,19.5,13.5,31.5,16.1v73l-64.5-36.6
- c3.2-10.9,4.2-23.5,1.9-35.2c-0.9-4.3-5.2-7.1-9.6-6.2c-4.4,0.9-7.2,5-6.4,9.4c1.6,7.9,1.6,15.7-0.5,23.8L140.3,181
- c-3.9-2.2-8.9-0.9-11.1,2.9c-2.2,3.8-0.9,8.7,3,10.9l28.8,16.3c-6.1,5.8-13,9.7-20.8,12.3c-4.3,1.4-6.5,6-5.1,10.1
- c1.4,4.2,6.1,6.4,10.3,5c11.6-3.9,21.8-10.1,30.2-19.2l64.3,36.5l-64.4,36.5c-7.9-8.2-18.6-15.3-30.1-19.2
- c-4.3-1.4-8.8,0.9-10.3,5.1c-1.4,4.2,0.8,8.7,5.1,10.1c7.7,2.6,14.6,6.5,20.7,12.3l-28.7,16.3c-3.9,2.2-5.2,7.1-3,10.9
- s7.2,5.1,11.1,2.9l28.8-16.3c2.1,8.1,2.1,15.9,0.4,23.9c-0.9,4.3,2,8.5,6.4,9.4c4.4,0.9,8.7-1.9,9.6-6.3c2.4-11.8,1.9-23.6-1.9-35.3
- l64.5-36.6v73.1c-12,2.6-22.4,8.1-31.5,16.1c-3.3,2.9-3.6,8-0.7,11.3c2.9,3.3,7.9,3.6,11.3,0.7c6.1-5.4,12.9-9.3,20.9-11.6V392
- c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8v-32.6c8,2.3,14.8,6.2,20.9,11.5c3.3,2.9,8.3,2.6,11.3-0.7c2.9-3.3,2.6-8.4-0.7-11.3
- c-9-7.9-20.4-13.4-31.4-16.1v-73.1l64.4,36.5c-3.8,11.7-4.2,23.5-1.8,35.3c0.9,4.3,5.2,7.1,9.6,6.3c4.4-0.9,7.3-5.1,6.4-9.4
- c-1.6-8-1.6-15.8,0.4-23.9l28.8,16.3c3.9,2.2,8.9,0.9,11.1-2.9C385.2,324.1,383.8,319.2,379.9,317z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer-outline.svg
deleted file mode 100644
index 28949166..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,64C132.288,64,32,164.226,32,287.938c0,56.975,21.283,108.97,56.316,148.5c3.551,4.006,7.241,7.82,11.066,11.562
- c3.059-3.49,6.232-6.834,9.539-10.141c0.48-0.48,0.972-0.947,1.456-1.422c18.78-18.426,40.521-32.949,64.664-43.161
- c25.633-10.842,52.871-16.339,80.958-16.339s55.325,5.497,80.958,16.339c24.144,10.212,45.884,24.735,64.664,43.161
- c0.484,0.475,0.976,0.941,1.456,1.422c3.307,3.307,6.48,6.65,9.539,10.141c3.825-3.742,7.516-7.557,11.066-11.562
- c35.033-39.53,56.316-91.525,56.316-148.5C480,164.226,379.712,64,256,64z M447.661,369.177
- c-8.663,20.481-20.429,39.092-35.044,55.776c-40.39-39.51-95.653-63.945-156.617-63.945s-116.228,24.33-156.617,63.84
- c-14.615-16.685-26.381-35.172-35.044-55.653c-9.81-23.19-15.228-47.694-16.173-72.694H79.5v-16H48.166
- c0.945-25,6.363-50.048,16.173-73.239c9.372-22.157,22.376-42.431,38.692-60.11l26.932,26.893l5.496-5.538l5.277-5.264l-0.02-0.027
- l0.547-0.552l-26.951-26.984c17.862-16.647,38.004-29.894,60.479-39.4c23.191-9.81,47.708-15.229,72.708-16.174V117.5h16V80.104
- c26,0.945,50.017,6.363,73.208,16.173c22.437,9.49,42.921,22.706,60.762,39.312l-26.975,27.069l0.577,0.547l-0.004,0.019
- l5.285,5.246l5.5,5.503l27.026-27.057c16.356,17.703,29.392,38.148,38.78,60.345c9.81,23.191,15.229,48.239,16.174,73.239H431.5v16
- h32.334C462.889,321.5,457.471,345.986,447.661,369.177z"/>
- <path d="M368.479,174.545l-85.484,73.727c-7.697-5.255-16.992-8.334-26.994-8.334c-26.467,0-48,21.533-48,48
- c0,10.479,3.385,20.178,9.106,28.08l-11.948,11.948l11.312,11.313l12.033-12.033c7.795,5.469,17.273,8.691,27.496,8.691
- c26.467,0,48-21.533,48-48c0-10.387-3.327-20.005-8.956-27.868l74.849-84.11L368.479,174.545z M256,319.938
- c-17.673,0-32-14.326-32-32c0-17.673,14.327-32,32-32s32,14.327,32,32C288,305.611,273.673,319.938,256,319.938z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer.svg
deleted file mode 100644
index 4117c002..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-speedometer.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M417,278.742V278h29.814c-0.931-23-6.056-45.609-14.831-66.151c-8.643-20.228-20.503-38.665-35.257-54.562l-24.867,24.646
- l-11.229-10.992l24.788-24.679c-16.187-14.836-34.86-26.742-55.515-35.392C308.479,101.897,286,97.092,263,96.186V130h-1.008H248
- V96.186c-23,0.894-44.95,5.699-66.404,14.685c-20.353,8.523-38.958,20.457-55.315,35.471l24.796,24.583l-0.549,0.549l0.001,0.006
- l-0.29,0.335l-10.27,10.203l-24.779-24.479c-14.77,15.932-26.604,34.243-35.176,54.309C71.241,232.388,66.117,255,65.187,278H94v16
- h-0.776H65.187c0.926,22,5.915,44.432,14.829,65.297c7.689,18.001,18.398,34.664,31.831,49.926
- c38.785-37.377,89.958-57.928,144.154-57.928c54.113,0,105.286,20.676,144.154,58.135c13.354-15.175,24.061-31.979,31.83-50.166
- C440.9,338.396,445.889,316,446.814,294H417V278.742z M304,287.938c0,26.467-21.533,48-48,48c-10.223,0-19.701-3.223-27.496-8.691
- l-12.033,12.033l-11.312-11.313l11.948-11.948c-5.722-7.902-9.106-17.602-9.106-28.08c0-26.467,21.533-48,48-48
- c10.002,0,19.297,3.079,26.994,8.334l73.484-65.727l1.414,1.414l-62.849,76.11C300.673,267.933,304,277.551,304,287.938z"/>
- <path d="M256,64C132.288,64,32,164.226,32,287.938c0,56.975,21.283,108.97,56.316,148.5c3.551,4.006,7.241,7.82,11.066,11.562
- h22.193c31.713-39.103,80.144-64.096,134.424-64.096S358.711,408.897,390.424,448h22.193c3.825-3.742,7.516-7.557,11.066-11.562
- c35.033-39.53,56.316-91.525,56.316-148.5C480,164.226,379.712,64,256,64z M410.744,420.797
- c-3.051,3.408-6.392,6.863-10.213,10.564l-0.376,0.365l-0.348-0.393c-2.629-2.97-5.493-5.985-8.759-9.22
- c-0.275-0.271-0.555-0.539-0.834-0.807l-0.504-0.485c-17.258-16.766-37.234-29.967-59.375-39.238
- c-23.535-9.856-48.545-14.854-74.336-14.854c-25.791,0-50.801,4.998-74.336,14.854c-22.14,9.271-42.117,22.473-59.375,39.238
- l-0.504,0.485c-0.279,0.268-0.558,0.535-0.833,0.807c-3.266,3.234-6.13,6.25-8.759,9.22l-0.348,0.393l-0.377-0.365
- c-3.821-3.701-7.162-7.156-10.212-10.564c-33.514-37.441-51.971-85.629-51.971-135.685c0-54.666,21.502-106.053,60.545-144.694
- C148.87,101.779,200.781,80.5,256,80.5c55.22,0,107.13,21.279,146.17,59.918c39.043,38.642,60.545,90.029,60.545,144.694
- C462.715,335.168,444.259,383.355,410.744,420.797z"/>
- <circle cx="256" cy="287.938" r="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-half.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-half.svg
deleted file mode 100644
index 183b2f55..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-half.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M172.248,304.931l-54.677,159.073L256,365.37l138.445,98.634L339.76,304.937L480,207H308.613L256,48.005L203.402,207H32
- L172.248,304.931z M256,100.75L297,224h131l-108,74.711l42.623,122.481L256,345.257V100.75z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-outline.svg
deleted file mode 100644
index 868de184..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star-outline.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M480,207H308.6L256,47.9L203.4,207H32l140.2,97.9L117.6,464L256,365.4L394.4,464l-54.7-159.1L480,207z M362.6,421.2
- l-106.6-76l-106.6,76L192,298.7L84,224h131l41-123.3L297,224h131l-108,74.6L362.6,421.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star.svg
deleted file mode 100644
index 74f7f026..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-star.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M480,207H308.6L256,47.9L203.4,207H32l140.2,97.9L117.6,464L256,365.4L394.4,464l-54.7-159.1L480,207z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch-outline.svg
deleted file mode 100644
index 66cf46da..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M397.6,146.7l-1.8-1.7h18.4l8.5,7.8l22.5-22.8l-40.8-40.3L381.2,112l8.8,9.2v18.6l-5-4.7c-31.3-28.3-70-45.2-113-48.9V48
- h-32v38h-2c-43.7,3-85,22.5-116,53v-17.8l8.9-9.2L108,89.8L67.2,130l22.5,22.8l8.5-7.8H116c-0.3,0-0.7,0.7-1,1.1
- C82.2,181.2,64,227,64,274.6C64,379,150.1,464,256.1,464C361.9,464,448,379.1,448,274.7C448,227.1,430,181.6,397.6,146.7z
- M256.3,445.7c-95.5,0-173.1-76.7-173.1-170.9c0-94.3,77.7-170.9,173.1-170.9c95.5,0,173.1,76.7,173.1,170.9
- C429.5,369,351.8,445.7,256.3,445.7z"/>
- <path d="M264,257.3V128h-16v129.4c-12.5,4.3-24,16.5-24,30.3c0,14.7,10,27,24,30.5l8,17.8l0,0l8-17.8c14-3.5,24-15.8,24-30.5
- C288,273.2,277.5,261,264,257.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch.svg
deleted file mode 100644
index ff2e680a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-stopwatch.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M397.6,146.7l-1.8-1.7h18.4l8.5,7.8l22.5-22.8l-40.8-40.3L381.2,112l8.8,9.2v18.6l-5-4.7c-31.3-28.3-70-45.2-113-48.9V48
- h-32v38h-2c-43.7,3-85,22.5-116,53v-17.8l8.9-9.2L108,89.8L67.2,130l22.5,22.8l8.5-7.8H116c-0.3,0-0.7,0.7-1,1.1
- C82.2,181.2,64,227,64,274.6C64,379,150.1,464,256.1,464C361.9,464,448,379.1,448,274.7C448,227.1,430,181.6,397.6,146.7z
- M264,318.2l-8,17.8l-8-17.8c-14-3.5-24-15.8-24-30.5c0-13.8,11.5-26,24-30.3V128h16v129.3c13.5,3.7,24,15.9,24,30.4
- C288,302.4,278,314.7,264,318.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny-outline.svg
deleted file mode 100644
index 3beb31f4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny-outline.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <rect x="247" y="96" class="st0" width="18" height="56"/>
- <rect x="247" y="356" class="st0" width="18" height="60"/>
- <rect x="360" y="247" class="st0" width="56" height="18"/>
- <rect x="96" y="247" class="st0" width="60" height="18"/>
-
- <rect x="339" y="317.4" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 834.4009 337.0126)" class="st0" width="16.8" height="47.8"/>
-
- <rect x="162.2" y="140.7" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 407.7248 160.277)" class="st0" width="16.8" height="47.9"/>
-
- <rect x="339" y="140.7" transform="matrix(0.7071 0.7071 -0.7071 0.7071 218.1171 -197.4504)" class="st0" width="16.8" height="47.8"/>
-
- <rect x="162.2" y="317.4" transform="matrix(0.707 0.7072 -0.7072 0.707 291.3531 -20.7056)" class="st0" width="16.8" height="47.9"/>
- <path class="st0" d="M256,331.8c-41.8,0-75.8-34-75.8-75.8s34-75.8,75.8-75.8c41.8,0,75.8,34,75.8,75.8S297.8,331.8,256,331.8z
- M256,197.1c-32.5,0-58.9,26.4-58.9,58.9s26.4,58.9,58.9,58.9c32.5,0,58.9-26.4,58.9-58.9S288.5,197.1,256,197.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny.svg
deleted file mode 100644
index 5793306e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-sunny.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <rect x="247" y="96" class="st0" width="18" height="56"/>
- <rect x="247" y="356" class="st0" width="18" height="60"/>
- <rect x="360" y="247" class="st0" width="56" height="18"/>
- <rect x="96" y="247" class="st0" width="60" height="18"/>
-
- <rect x="339" y="317.4" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 834.4009 337.0126)" class="st0" width="16.8" height="47.8"/>
-
- <rect x="162.2" y="140.7" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 407.7248 160.277)" class="st0" width="16.8" height="47.9"/>
-
- <rect x="339" y="140.7" transform="matrix(0.7071 0.7071 -0.7071 0.7071 218.1171 -197.4504)" class="st0" width="16.8" height="47.8"/>
-
- <rect x="162.2" y="317.4" transform="matrix(0.707 0.7072 -0.7072 0.707 291.3531 -20.7056)" class="st0" width="16.8" height="47.9"/>
- <path class="st0" d="M256,331.8c-41.8,0-75.8-34-75.8-75.8s34-75.8,75.8-75.8c41.8,0,75.8,34,75.8,75.8S297.8,331.8,256,331.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone-outline.svg
deleted file mode 100644
index d34da021..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M415.9,335.5c-14.6-15-56.1-43.1-83.3-43.1c-6.3,0-11.8,1.4-16.3,4.3c-13.3,8.5-23.9,15.1-29,15.1c-2.8,0-5.8-2.5-12.4-8.2
- l-1.1-1c-18.3-15.9-22.2-20-29.3-27.4l-1.8-1.9c-1.3-1.3-2.4-2.5-3.5-3.6c-6.2-6.4-10.7-11-26.6-29l-0.7-0.8
- c-7.6-8.6-12.6-14.2-12.9-18.3c-0.3-4,3.2-10.5,12.1-22.6c10.8-14.6,11.2-32.6,1.3-53.5c-7.9-16.5-20.8-32.3-32.2-46.2l-1-1.2
- c-9.8-12-21.2-18-33.9-18c-14.1,0-25.8,7.6-32,11.6c-0.5,0.3-1,0.7-1.5,1c-13.9,8.8-24,20.9-27.8,33.2c-5.7,18.5-9.5,42.5,17.8,92.4
- c23.6,43.2,45,72.2,79,107.1c32,32.8,46.2,43.4,78,66.4c35.4,25.6,69.4,40.3,93.2,40.3c22.1,0,39.5,0,64.3-29.9
- C442.3,370.8,431.5,351.6,415.9,335.5z M404.4,391.4c-20,24.2-31.5,24.2-52.3,24.2c-20.3,0-51.8-14-84.2-37.3
- c-31-22.4-44.8-32.7-75.9-64.6c-32.9-33.7-53.6-61.8-76.4-103.5c-24.1-44.1-21.4-63.4-16.5-79.3c2.6-8.5,10.4-17.6,21-24.2
- c0.5-0.3,1-0.7,1.6-1c5.3-3.4,14.1-9.1,23.7-9.1c8,0,15.1,4,21.9,12.3l1,1.2c25.5,31.2,45.4,58.8,30.4,79.2
- c-10.6,14.3-16.2,24-15.3,34c0.8,9.7,7.3,17,17.1,28l0.7,0.8c16.1,18.2,20.7,23,27.1,29.5c1.1,1.1,2.2,2.3,3.5,3.6l1.8,1.9
- c7.4,7.7,11.5,11.9,30.3,28.4l1.1,1c8,7,13.9,12.1,22.5,12.1c8.9,0,18.7-5.6,37.3-17.5c1.9-1.2,4.6-1.9,8-1.9
- c21.7,0,59.1,24.8,72.2,38.3C417,359.7,423,368.9,404.4,391.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone.svg
deleted file mode 100644
index 794e51a7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-telephone.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M415.9,335.5c-14.6-15-56.1-43.1-83.3-43.1c-6.3,0-11.8,1.4-16.3,4.3c-13.3,8.5-23.9,15.1-29,15.1c-2.8,0-5.8-2.5-12.4-8.2
- l-1.1-1c-18.3-15.9-22.2-20-29.3-27.4l-1.8-1.9c-1.3-1.3-2.4-2.5-3.5-3.6c-6.2-6.4-10.7-11-26.6-29l-0.7-0.8
- c-7.6-8.6-12.6-14.2-12.9-18.3c-0.3-4,3.2-10.5,12.1-22.6c10.8-14.6,11.2-32.6,1.3-53.5c-7.9-16.5-20.8-32.3-32.2-46.2l-1-1.2
- c-9.8-12-21.2-18-33.9-18c-14.1,0-25.8,7.6-32,11.6c-0.5,0.3-1,0.7-1.5,1c-13.9,8.8-24,20.9-27.8,33.2c-5.7,18.5-9.5,42.5,17.8,92.4
- c23.6,43.2,45,72.2,79,107.1c32,32.8,46.2,43.4,78,66.4c35.4,25.6,69.4,40.3,93.2,40.3c22.1,0,39.5,0,64.3-29.9
- C442.3,370.8,431.5,351.6,415.9,335.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball-outline.svg
deleted file mode 100644
index aa743654..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M464,256c0-114.863-93.13-208-208-208C141.137,48,48,141.136,48,256c0,114.863,93.137,208,208,208
- c2.541,0,5.068-0.062,7.587-0.152c0.479-0.017,0.957-0.034,1.435-0.055c0.942-0.04,1.884-0.083,2.823-0.136
- c0.85-0.047,1.698-0.104,2.547-0.161c0.639-0.044,1.279-0.08,1.917-0.13c1.354-0.104,2.705-0.221,4.055-0.352
- c0-0.003,0-0.006,0-0.009c97.47-9.474,175.229-86.229,186.274-183.223c0.02-0.001,0.038,0,0.057-0.001
- c0.604-5.315,1.002-10.667,1.196-16.05c-0.016,0.001-0.032,0.001-0.049,0.001C463.937,261.166,464,258.591,464,256z M446.665,256
- c0,2.568-0.066,5.121-0.167,7.664c-23.639-1.076-46.677-6.106-68.616-15.005c-25.791-10.458-48.938-25.831-68.797-45.691
- c-19.86-19.86-35.233-43.007-45.692-68.797c-8.903-21.956-13.935-45.014-15.006-68.67c2.527-0.1,5.063-0.165,7.614-0.165
- C361.13,65.335,446.665,150.869,446.665,256z M65.337,256c0-1.318,0.023-2.631,0.05-3.942c22.476,1.379,44.388,6.337,65.3,14.817
- c25.791,10.458,48.938,25.831,68.798,45.691c19.86,19.859,35.232,43.007,45.691,68.798c8.474,20.896,13.43,42.792,14.814,65.249
- c-1.328,0.027-2.656,0.051-3.99,0.051C150.87,446.664,65.336,361.13,65.337,256z M275.943,445.623
- c-3.273-52.566-24.974-104.198-65.145-144.369c-40.186-40.186-91.84-61.889-144.427-65.15
- c9.172-88.053,78.52-158.478,166.074-169.313c2.595,53.64,24.36,106.525,65.326,147.49c40.949,40.952,93.811,62.713,147.433,65.322
- C434.351,367.118,363.957,436.432,275.943,445.623z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball.svg
deleted file mode 100644
index 1939c456..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-tennisball.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M48.05,251.556c-0.001,0.039-0.003,0.077-0.004,0.116c0,0,0.002,0,0.003,0C48.049,251.634,48.049,251.595,48.05,251.556z"
- />
- <path d="M260.311,463.915c0.066-0.002,0.133-0.006,0.199-0.007c-0.066,0.001-0.133,0.001-0.199,0.004
- C260.311,463.912,260.311,463.913,260.311,463.915z"/>
- <path d="M256,48.001c-2.586,0-5.29,0.064-7.852,0.158L248,48.153c0,0.003,0,0.004,0,0.006c-5,0.199-10,0.602-16,1.205
- c0-0.002,0-0.004,0-0.008c0,0.005,0.083,0.008,0.072,0.012c-96.974,11.061-173.654,88.975-183.13,186.41
- c-0.004,0.018,0.045,0.222,0.042,0.222c0.003,0,0.004,0,0.007,0c-0.513,5-0.826,10-0.936,16c-0.001,0-0.003,0-0.004,0l0.003-0.152
- c-0.028,1.43-0.054,2.777-0.054,4.215c0,114.852,92.977,207.938,207.841,207.938c6.856,0,14.159-0.383,20.159-1.031
- c0,0.002,0,0.006,0,0.006c0-0.004,0.213-0.008,0.24-0.014c97.436-9.486,175.247-86.086,186.312-183.036
- c0.004-0.014,0.088,0.074,0.092,0.074c-0.002,0-0.006,0-0.008,0c0.889-8,1.363-15.859,1.363-23.904
- C464,141.245,370.87,48.001,256,48.001z M130.63,266.853c-20.895-8.474-42.788-13.43-65.244-14.816
- c0.11-5.374,0.438-10.695,0.986-15.952c52.568,3.275,104.203,24.977,144.375,65.146c40.172,40.169,61.876,91.797,65.152,144.359
- c-5.257,0.548-10.579,0.876-15.954,0.985c-1.385-22.453-6.342-44.344-14.816-65.236c-10.459-25.79-25.834-48.937-45.696-68.795
- C179.572,292.684,156.423,277.311,130.63,266.853z M297.722,214.265c-40.964-40.959-62.731-93.835-65.332-147.467
- c5.25-0.652,10.568-1.08,15.941-1.293c1.073,23.65,6.105,46.702,15.007,68.654c10.461,25.79,25.835,48.936,45.696,68.795
- c19.862,19.859,43.01,35.232,68.803,45.691c21.954,8.901,45.008,13.933,68.66,15.007c-0.213,5.37-0.643,10.689-1.293,15.939
- C391.564,276.989,338.686,255.225,297.722,214.265z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm-outline.svg
deleted file mode 100644
index f49c64ea..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <polygon class="st0" points="312,272 272,272 288,224 216,224 201,304 253.3,304 224,400 "/>
- <g>
- <path class="st0" d="M328.4,172.7c-2.7,0-5.4,0-8,0.3c-7.9-35-39.1-61.4-76.4-61.4c-43.3,0-78.3,35.2-78.3,78.5
- c0,2.6,0.1,5.2,0.4,7.8c-26.4,2.3-47.1,25.7-47.1,52.8c0,28.6,23.2,53.3,51.7,53.3H182v-17h-11.3c-9.5,0-18.5-4.1-25.4-11
- c-6.8-7-10.6-16.3-10.6-26c0-18.6,14.5-33.8,33.2-36.9c1.6-0.3,8.8-1.3,14.2-1.8c0,0-0.5-5.3-0.6-9.6c-0.1-4.3-0.1-9.4-0.1-11.5
- c0-34.6,28.1-62.7,62.6-62.7c14.5,0,28.1,4.8,39.3,13.9c10.9,8.9,18.6,21.3,21.7,34.9l3.1,14l14.2-1.8c2.1-0.3,4.1-0.4,6.1-0.4
- c26.9,0,48.8,22.3,48.8,49.4c0,27.1-21.9,49.4-48.8,49.4H320v17h8.4c35.7,0,64.6-30.1,64.6-65.9
- C393,202.4,364.1,172.7,328.4,172.7z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm.svg
deleted file mode 100644
index 73afbf0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-thunderstorm.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <polygon class="st0" points="272,272 288,224 216,224 201,304 253.3,304 224,400 290,304 312,272 "/>
- <path class="st0" d="M202.7,208l107.5,0l-16,48H312h30.4l-33,48h19c35.7,0,64.6-30.1,64.6-65.9c0-35.8-28.9-65.5-64.6-65.5
- c-2.7,0-5.4,0-8,0.3c-7.9-35-39.1-61.4-76.4-61.4c-43.3,0-78.3,35.2-78.3,78.5c0,2.6,0.1,5.2,0.4,7.8
- c-26.4,2.3-47.1,25.7-47.1,52.8c0,28.6,23.2,53.3,51.7,53.3h14"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time-outline.svg
deleted file mode 100644
index 9276bc63..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time-outline.svg
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <g>
- <path class="st0" d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224
- C480,132.3,379.7,32,256,32z M403.1,403.1c-19.1,19.1-41.4,34.1-66.1,44.6c-25.6,10.8-52.9,16.3-81,16.3c-28.1,0-55.3-5.5-81-16.3
- c-24.8-10.5-47-25.5-66.1-44.6C89.8,384,74.8,361.7,64.3,337C53.5,311.3,48,284.1,48,256c0-28.1,5.5-55.3,16.3-81
- c10.5-24.8,25.5-47,44.6-66.1C128,89.8,150.3,74.8,175,64.3C200.7,53.5,227.9,48,256,48c28.1,0,55.3,5.5,81,16.3
- c24.8,10.5,47,25.5,66.1,44.6c19.1,19.1,34.1,41.4,44.6,66.1c10.8,25.6,16.3,52.9,16.3,81c0,28.1-5.5,55.3-16.3,81
- C437.2,361.7,422.2,384,403.1,403.1z"/>
- <circle class="st0" cx="256" cy="80" r="8"/>
- <circle class="st0" cx="256" cy="432" r="8"/>
- <circle class="st0" cx="432" cy="256" r="8"/>
- <circle class="st0" cx="80" cy="256" r="8"/>
- <circle class="st0" cx="168" cy="103.6" r="8"/>
- <circle class="st0" cx="344" cy="408.4" r="8"/>
- <circle class="st0" cx="408.4" cy="168" r="8"/>
- <circle class="st0" cx="103.6" cy="344" r="8"/>
- <circle class="st0" cx="103.6" cy="168" r="8"/>
- <circle class="st0" cx="408.4" cy="344" r="8"/>
- <circle class="st0" cx="344" cy="103.6" r="8"/>
- <circle class="st0" cx="168" cy="408.4" r="8"/>
- </g>
- <path class="st0" d="M269.9,248c-2.9-5-8.1-7.8-13.4-8l-38-63.4c-2.3-3.8-7.2-5-11-2.7c-3.8,2.3-5,7.2-2.7,11l37.6,62.9
- c-2.9,4.8-3.2,11.1-0.2,16.3c1.5,2.5,3.5,4.5,5.9,5.8V392c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8V269.9
- C271.7,265.4,274.3,255.7,269.9,248z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time.svg
deleted file mode 100644
index 0d0bc47b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-time.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224
- C480,132.3,379.7,32,256,32z M256,72c4.4,0,8,3.6,8,8s-3.6,8-8,8s-8-3.6-8-8S251.6,72,256,72z M80,264c-4.4,0-8-3.6-8-8
- c0-4.4,3.6-8,8-8s8,3.6,8,8C88,260.4,84.4,264,80,264z M107.6,350.9c-3.8,2.2-8.7,0.9-10.9-2.9c-2.2-3.8-0.9-8.7,2.9-10.9
- c3.8-2.2,8.7-0.9,10.9,2.9C112.7,343.8,111.4,348.7,107.6,350.9z M110.5,172c-2.2,3.8-7.1,5.1-10.9,2.9c-3.8-2.2-5.1-7.1-2.9-10.9
- s7.1-5.1,10.9-2.9C111.4,163.3,112.7,168.2,110.5,172z M164,96.7c3.8-2.2,8.7-0.9,10.9,2.9c2.2,3.8,0.9,8.7-2.9,10.9
- c-3.8,2.2-8.7,0.9-10.9-2.9C158.9,103.8,160.2,98.9,164,96.7z M174.9,412.4c-2.2,3.8-7.1,5.1-10.9,2.9c-3.8-2.2-5.1-7.1-2.9-10.9
- c2.2-3.8,7.1-5.1,10.9-2.9S177.1,408.6,174.9,412.4z M256,440c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S260.4,440,256,440z M264,269.9
- V392c0,4.4-3.6,8-8,8c-4.4,0-8-3.6-8-8V269.8c-2.4-1.4-4.4-3.3-5.9-5.8c-3-5.2-2.7-11.5,0.2-16.3l-37.6-62.9c-2.3-3.8-1-8.7,2.7-11
- c3.8-2.3,8.7-1,11,2.7l38,63.4c5.4,0.1,10.6,3,13.4,8C274.3,255.7,271.7,265.4,264,269.9z M348,415.3c-3.8,2.2-8.7,0.9-10.9-2.9
- c-2.2-3.8-0.9-8.7,2.9-10.9c3.8-2.2,8.7-0.9,10.9,2.9C353.1,408.2,351.8,413.1,348,415.3z M350.9,107.6c-2.2,3.8-7.1,5.1-10.9,2.9
- c-3.8-2.2-5.1-7.1-2.9-10.9c2.2-3.8,7.1-5.1,10.9-2.9C351.8,98.9,353.1,103.8,350.9,107.6z M415.3,348c-2.2,3.8-7.1,5.1-10.9,2.9
- c-3.8-2.2-5.1-7.1-2.9-10.9c2.2-3.8,7.1-5.1,10.9-2.9C416.2,339.3,417.6,344.2,415.3,348z M412.4,174.9c-3.8,2.2-8.7,0.9-10.9-2.9
- c-2.2-3.8-0.9-8.7,2.9-10.9c3.8-2.2,8.7-0.9,10.9,2.9C417.6,167.8,416.2,172.7,412.4,174.9z M432,264c-4.4,0-8-3.6-8-8
- c0-4.4,3.6-8,8-8s8,3.6,8,8C440,260.4,436.4,264,432,264z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer-outline.svg
deleted file mode 100644
index d2d852c9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M236.6,271.6c4.6,5.7,11.5,9.4,19.4,9.4c13.8,0,25-11.2,25-25c0-7.3-3.2-13.8-8.2-18.4c-0.6-0.7-1.3-1.5-2.2-2.2
- c0,0-117.7-87.5-120.3-85.2c-2.6,2.3,85.3,120.2,85.3,120.2C235.8,270.8,236.3,271.2,236.6,271.6z"/>
-<path d="M256.2,48L256.2,48H256v112h16V65.3c97.8,8.3,175.3,90.5,175.3,190.5c0,105.5-85.7,191.4-191.2,191.4
- c-105.5,0-191.3-85.8-191.3-191.3c0-52.8,21.5-100.6,56.1-135.2L109,108.9C71.3,146.6,48,198.6,48,256c0,114.9,93.1,208,208,208
- c114.9,0,208-93.1,208-208C464,141.1,371,48,256.2,48z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer.svg
deleted file mode 100644
index 10ebab9e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-timer.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,48C141.1,48,48,141.1,48,256c0,114.9,93.1,208,208,208c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z
- M150.5,150.5c2.6-2.3,119.9,84.9,119.9,84.9c1,0.7,1.6,1.5,2.2,2.2c5,4.6,8.2,11,8.2,18.3c0,13.7-11.1,24.9-24.9,24.9
- c-7.8,0-14.7-3.7-19.3-9.4c-0.4-0.4-0.8-0.7-1.1-1.1C235.6,270.4,148,152.9,150.5,150.5z M256.1,447.2
- c-105.7,0-191.4-85.7-191.4-191.4c0-52.8,21.4-100.7,56-135.3l11.8,11.8c-31.6,31.6-51.2,75.3-51.2,123.5
- c0,96.3,78.4,174.7,174.7,174.7s174.5-78.4,174.5-174.7c0-90.3-70.5-165.1-158.5-174V160h-16V64.4c105.7,0,191.5,85.7,191.5,191.4
- C447.5,361.5,361.7,447.2,256.1,447.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle-outline.svg
deleted file mode 100644
index 2677364c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M128,320c26.467,0,48,21.533,48,48s-21.533,48-48,48s-48-21.533-48-48S101.533,320,128,320 M128,304
- c-35.346,0-64,28.654-64,64c0,35.347,28.654,64,64,64s64-28.653,64-64C192,332.654,163.346,304,128,304L128,304z"/>
- <path d="M383.25,288c44.388,0,80.625,36.112,80.625,80.5S427.888,448,383.5,448h-255C84.112,448,48,412.888,48,368.5
- S84.112,288,128.5,288H383 M383.5,272h-255C75.205,272,32,315.205,32,368.5S75.205,464,128.5,464h255
- c53.295,0,96.5-42.205,96.5-95.5S436.795,272,383.5,272L383.5,272z"/>
- </g>
- <g>
- <path d="M384,96c26.467,0,48,21.533,48,48s-21.533,48-48,48s-48-21.533-48-48S357.533,96,384,96 M384,80
- c-35.346,0-64,28.654-64,64c0,35.347,28.654,64,64,64s64-28.653,64-64C448,108.654,419.346,80,384,80L384,80z"/>
- <path d="M129,64h254.5c44.388,0,80.5,36.112,80.5,80.5S427.888,224,383.5,224h-255c-44.388,0-80.375-35.112-80.375-79.5
- S84.362,64,128.75,64 M128.5,48C75.205,48,32,91.205,32,144.5S75.205,240,128.5,240h255c53.295,0,96.5-42.205,96.5-95.5
- S436.795,48,383.5,48H128.5L128.5,48z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle.svg
deleted file mode 100644
index f4374246..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-toggle.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M128,320c-26.467,0-48,21.533-48,48s21.533,48,48,48s48-21.533,48-48S154.467,320,128,320z"/>
- <path d="M383.5,272h-255C75.205,272,32,315.205,32,368.5S75.205,464,128.5,464h255c53.295,0,96.5-42.205,96.5-95.5
- S436.795,272,383.5,272z M128,432c-35.346,0-64-28.653-64-64c0-35.346,28.654-64,64-64s64,28.654,64,64
- C192,403.347,163.346,432,128,432z"/>
- <path d="M384,192c26.467,0,48-21.533,48-48s-21.533-48-48-48s-48,21.533-48,48S357.533,192,384,192z"/>
- <path d="M128.5,240h255c53.295,0,96.5-42.205,96.5-95.5S436.795,48,383.5,48h-255C75.205,48,32,91.205,32,144.5
- S75.205,240,128.5,240z M384,80c35.346,0,64,28.654,64,64c0,35.347-28.654,64-64,64s-64-28.653-64-64
- C320,108.654,348.654,80,384,80z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash-outline.svg
deleted file mode 100644
index 2b362bbf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M400,113.3h-80v-20c0-16.2-13.1-29.3-29.3-29.3h-69.5C205.1,64,192,77.1,192,93.3v20h-80V128h21.1l23.6,290.7
- c0,16.2,13.1,29.3,29.3,29.3h141c16.2,0,29.3-13.1,29.3-29.3L379.6,128H400V113.3z M206.6,93.3c0-8.1,6.6-14.7,14.6-14.7h69.5
- c8.1,0,14.6,6.6,14.6,14.7v20h-98.7V93.3z M341.6,417.9l0,0.4v0.4c0,8.1-6.6,14.7-14.6,14.7H186c-8.1,0-14.6-6.6-14.6-14.7v-0.4
- l0-0.4L147.7,128h217.2L341.6,417.9z"/>
- <g>
- <rect x="249" y="160" width="14" height="241"/>
- <polygon points="320,160 305.4,160 294.7,401 309.3,401 "/>
- <polygon points="206.5,160 192,160 202.7,401 217.3,401 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash.svg
deleted file mode 100644
index 1b645676..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-trash.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M320,113V93.3c0-16.2-13.1-29.3-29.3-29.3h-69.5C205.1,64,192,77.1,192,93.3V113h-80v15h21.1l23.6,290.7
- c0,16.2,13.1,29.3,29.3,29.3h141c16.2,0,29.3-13.1,29.3-29.3L379.6,128H400v-15H320z M207,93.3c0-8.1,6.2-14.3,14.3-14.3h69.5
- c8.1,0,14.3,6.2,14.3,14.3V113h-98V93.3H207z M202.7,401L192,160h14.5l10.9,241H202.7z M263,401h-14V160h14V401z M309.3,401h-14.6
- l10.8-241H320L309.3,401z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo-outline.svg
deleted file mode 100644
index 03c35e30..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M447.9,368.2c0-16.8,3.6-83.1-48.7-135.7c-35.2-35.4-80.3-53.4-143.3-56.2V96L64,224l192,128v-79.8
- c40,1.1,62.4,9.1,86.7,20c30.9,13.8,55.3,44,75.8,76.6l19.2,31.2H448C448,389.9,447.9,377.1,447.9,368.2z M432.2,361.4
- C384.6,280.6,331,256,240,256v64.8L91.9,224.1L240,127.3V192C441,192,432.2,361.4,432.2,361.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo.svg
deleted file mode 100644
index e1bd3f15..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-undo.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M447.9,368.2c0-16.8,3.6-83.1-48.7-135.7c-35.2-35.4-80.3-53.4-143.3-56.2V96L64,224l192,128v-79.8
- c40,1.1,62.4,9.1,86.7,20c30.9,13.8,55.3,44,75.8,76.6l19.2,31.2H448C448,389.9,447.9,377.1,447.9,368.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked-outline.svg
deleted file mode 100644
index ed67ed4f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,288c-17.673,0-32,14.327-32,32c0,14.91,10.198,27.439,24,30.992V384h16v-33.008c13.802-3.553,24-16.082,24-30.992
- C288,302.327,273.673,288,256,288z M256,336c-8.822,0-16-7.178-16-16s7.178-16,16-16s16,7.178,16,16S264.822,336,256,336z"/>
- <g>
- <path d="M168,224v-72c0-48.523,39.484-88,88.016-88C304.531,64,344,103.477,344,152v8h16v-8c0-57.43-46.562-104-103.984-104
- C198.562,48,152,94.57,152,152v72H96v240h320V224H168z M400,448H112V240h288V448z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked.svg
deleted file mode 100644
index e547e801..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-unlocked.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,304c-8.822,0-16,7.178-16,16s7.178,16,16,16s16-7.178,16-16S264.822,304,256,304z"/>
- <path d="M168,224v-72c0-48.523,39.484-88,88.016-88C304.531,64,344,103.477,344,152v8h16v-8c0-57.43-46.562-104-103.984-104
- C198.562,48,152,94.57,152,152v72H96v240h320V224H168z M264,350.992V384h-16v-33.008c-13.802-3.553-24-16.082-24-30.992
- c0-17.673,14.327-32,32-32s32,14.327,32,32C288,334.91,277.802,347.439,264,350.992z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload-outline.svg
deleted file mode 100644
index e836efa4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <polygon points="288,144 288,160 400,160 400,432 112,432 112,160 224,160 224,144 96,144 96,448 416,448 416,144 "/>
- </g>
- <g>
- <polygon points="193.1,118.1 181.5,106.5 256,32 330.5,106.5 318.9,118.1 264.2,63.4 264.2,306.4 247.8,306.4 247.8,63.4 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload.svg
deleted file mode 100644
index 5352c0af..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-upload.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="264,144 264,306 248,306 248,144 96,144 96,448 416,448 416,144 "/>
- <polygon points="264,63.4 318.8,118.1 330.4,106.5 256,32 181.5,106.5 193.2,118.1 248,63.4 248,144 264,144 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam-outline.svg
deleted file mode 100644
index 11cc9bbe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M303.7,128h-221C63.9,128,47,142.1,47,160.7v187.9c0,18.6,16.9,35.4,35.7,35.4h221c18.8,0,33.3-16.8,33.3-35.4V160.7
- C337,142.1,322.5,128,303.7,128z M320,348.6c0,9.3-6.9,18.4-16.3,18.4h-221c-9.4,0-18.7-9.1-18.7-18.4V160.7
- c0-9.3,9-15.5,18.4-15.5l221,0.1c9.4,0,16.6,6.1,16.6,15.4V348.6z"/>
- <path d="M367,213v85.6l98,53.4V160L367,213z M448,190v132.3l-64-33.5v-65.6l64.1-33.6L448,190z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam.svg
deleted file mode 100644
index dbcbceec..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-videocam.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M303.7,128h-221C63.9,128,47,142.1,47,160.7v187.9c0,18.6,16.9,35.4,35.7,35.4h221c18.8,0,33.3-16.8,33.3-35.4V160.7
- C337,142.1,322.5,128,303.7,128z"/>
- <path d="M367,213v85.6l98,53.4V160L367,213z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-high.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-high.svg
deleted file mode 100644
index 7f62cac4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-high.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M374.1,128l-13.6,10.3C384.6,171.2,399,211.9,399,256c0,44.1-14.4,84.8-38.6,117.7l13.6,10.3c26.3-35.7,41.9-80,41.9-128
- C415.9,208,400.4,163.7,374.1,128z"/>
- <path d="M320,351.8c20-26.8,32-59.9,32-95.8s-12-69-32-95.8l-13.6,10.1c17.9,24,28.6,53.6,28.6,85.7s-10.7,61.7-28.6,85.7
- L320,351.8z"/>
- <path d="M273.1,319.9c13.7-17.9,21.9-39.9,21.9-63.9c0-24-8.2-46-21.9-63.9l-13.5,9.8c11.6,15.1,18.5,33.8,18.5,54.1
- s-6.9,38.9-18.5,54.1L273.1,319.9z"/>
- </g>
- </g>
- <polygon points="153.9,216 96,216 96,296 153.9,296 224,352 224,160 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-low.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-low.svg
deleted file mode 100644
index 127e9766..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-volume-low.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="249.9,216 192,216 192,296 249.9,296 320,352 320,160 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass-outline.svg
deleted file mode 100644
index c193875c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M264,308.988c0-21.975,20.458-38.674,40.247-54.824c7.907-6.453,15.37-12.547,21.519-18.962
- C352.313,207.505,352,183.458,352,164.144V160c0-44.25-30.816-124.558-32.02-128H256h-64c-1.203,3.442-32,83.5-32,128v4.144
- c0,19.273-0.323,43.361,26.225,71.059c6.148,6.415,13.617,12.509,21.523,18.962c19.789,16.15,40.252,32.85,40.252,54.824V464h-72v16
- h80h80v-16h-72V308.988z M202.729,48H256h53.251c5.359,15.99,19.509,62.712,24.836,96H177.894
- C183.221,110.712,197.37,63.99,202.729,48z M256,273.416c-2.968,0-5.248-0.92-7.17-2.754c0.001,0.009,0.003,0.018,0.005,0.026
- c-8.804-10.807-20.234-20.158-30.971-28.92c-7.517-6.135-14.617-11.929-20.089-17.637c-22.054-23.008-21.928-40.916-21.795-59.875
- c0.01-1.428-0.068-2.849,0.02-4.255h159.98c0.088,1.406,0.01,2.828,0.021,4.255c0.133,18.959,0.259,36.867-21.795,59.875
- c-5.472,5.708-12.57,11.502-20.087,17.637c-10.737,8.762-22.165,18.114-30.969,28.92c0.002-0.009,0.009-0.018,0.01-0.026
- C261.238,272.496,259,273.416,256,273.416z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass.svg
deleted file mode 100644
index 4ac498d6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-wineglass.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M264,308.988c0-21.975,20.458-38.674,40.247-54.824c7.907-6.453,15.37-12.547,21.519-18.962
- C352.313,207.505,352,183.458,352,164.144V160c0-44.25-30.816-124.558-32.02-128H256h-64c-1.203,3.442-32,83.5-32,128v4.144
- c0,19.273-0.323,43.361,26.225,71.059c6.148,6.415,13.617,12.509,21.523,18.962c19.789,16.15,40.252,32.85,40.252,54.824V464h-72v16
- h80h80v-16h-72V308.988z M202.729,48H256h53.251c5.359,15.99,19.509,62.712,24.836,96H177.894
- C183.221,110.712,197.37,63.99,202.729,48z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world-outline.svg
deleted file mode 100644
index a90af05c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,48c-0.1,0-0.1,0-0.2,0c0,0,0,0-0.1,0c-0.1,0-0.2,0-0.2,0C140.8,48.3,48,141.3,48,256c0,114.7,92.8,207.7,207.5,208
- c0.1,0,0.2,0,0.2,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z M264.3,172.5
- c22.1-0.6,43.5-3.5,64.2-8.5c6.2,24.5,10.1,52.8,10.7,83.8h-74.9V172.5z M264.3,155.8V66c22.4,6.2,45.2,36.1,59.6,82
- C304.7,152.6,284.8,155.2,264.3,155.8z M247.7,65.8v90.1c-20.7-0.6-40.8-3.3-60.1-8C202.2,101.7,225.1,71.6,247.7,65.8z
- M247.7,172.5v75.2h-75.4c0.6-31,4.5-59.3,10.7-83.8C203.8,168.9,225.5,171.9,247.7,172.5z M155.5,247.7H64.9
- c1.8-42.8,17.8-82,43.3-113c18.5,10.2,38.2,18.6,58.8,24.8C160.2,186,156.2,215.9,155.5,247.7z M155.5,264.3
- c0.6,31.7,4.6,61.7,11.4,88.2c-20.6,6.3-40.2,14.6-58.8,24.8c-25.5-31-41.4-70.2-43.3-113H155.5z M172.3,264.3h75.4v75.1
- c-22.2,0.6-43.9,3.6-64.7,8.7C176.8,323.6,172.9,295.3,172.3,264.3z M247.7,356.1v90.2c-22.6-5.9-45.5-35.9-60.1-82.1
- C206.9,359.4,227,356.7,247.7,356.1z M264.3,446v-90c20.5,0.6,40.4,3.3,59.7,7.9C309.5,409.9,286.8,439.8,264.3,446z M264.3,339.4
- v-75.1h74.9c-0.6,30.9-4.5,59.2-10.7,83.7C307.8,343,286.4,340,264.3,339.4z M355.9,264.3h91.2c-1.8,42.8-17.8,81.9-43.3,113
- c-18.7-10.3-38.5-18.7-59.3-25C351.3,325.8,355.3,296,355.9,264.3z M355.9,247.7c-0.6-31.7-4.6-61.6-11.3-88.1
- c20.8-6.3,40.6-14.7,59.2-24.9c25.5,31,41.5,70.2,43.3,113.1H355.9z M392.4,121.9c-16.6,8.8-34,16.1-52.3,21.6
- c-9.7-31.3-23.4-56.8-39.5-73.6C336,78.4,367.6,96.8,392.4,121.9z M210.8,70.1c-16.1,16.7-29.7,42.2-39.3,73.3
- c-18.1-5.5-35.4-12.7-51.8-21.5C144.2,96.9,175.6,78.6,210.8,70.1z M119.6,390c16.4-8.8,33.8-16,51.8-21.5
- c9.7,31.2,23.3,56.6,39.4,73.4C175.6,433.4,144.2,415.1,119.6,390z M300.6,442.1c16.2-16.8,29.8-42.3,39.6-73.7
- c18.3,5.5,35.7,12.8,52.3,21.6C367.7,415.2,336,433.6,300.6,442.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world.svg
deleted file mode 100644
index 97d6a83c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ios-world.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,48c-0.1,0-0.1,0-0.2,0c0,0,0,0-0.1,0c-0.1,0-0.2,0-0.2,0C140.8,48.3,48,141.3,48,256c0,114.7,92.8,207.7,207.5,208
- c0.1,0,0.2,0,0.2,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0c114.9,0,208-93.1,208-208C464,141.1,370.9,48,256,48z M256,447.4
- c-0.1,0-0.1,0-0.2,0c0,0,0,0-0.1,0c-0.1,0-0.2,0-0.2,0C150.1,447.1,64.6,361.5,64.6,256c0-105.5,85.4-191.1,190.9-191.3
- c0.1,0,0.1,0,0.2,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0c105.7,0,191.4,85.7,191.4,191.4C447.4,361.7,361.7,447.4,256,447.4z"/>
- <path d="M322.3,171.8c-18.7,4.5-38,7.2-57.9,7.8v68.1H332C331.4,219.6,327.9,194.1,322.3,171.8z"/>
- <path d="M264.3,82.5v81.9c18.5-0.6,36.5-3,53.8-7.2C305,115.8,284.6,88.6,264.3,82.5z"/>
- <path d="M193.4,157.1c17.5,4.2,35.6,6.7,54.2,7.3V82.3C227.3,88.2,206.6,115.4,193.4,157.1z"/>
- <path d="M380.6,133.4c-22.6-23-51.5-39.8-83.9-47.5c14.8,15.3,27.2,38.7,36.1,67.3C349.5,148.1,365.5,141.5,380.6,133.4z"/>
- <path d="M347.3,247.7h83.3c-1.8-38.8-16.3-74.4-39.5-102.6c-17.1,9.4-35.2,17.1-54.1,22.8C343.1,191.9,346.7,219,347.3,247.7z"/>
- <path d="M179.5,247.7h68.2v-68.1c-20.1-0.6-39.6-3.3-58.4-7.9C183.6,194,180.1,219.6,179.5,247.7z"/>
- <path d="M332,264.3h-67.7v68c19.9,0.6,39.3,3.2,58,7.8C327.9,317.9,331.4,292.3,332,264.3z"/>
- <path d="M189.3,340.2c18.8-4.6,38.3-7.3,58.4-7.9v-68h-68.2C180.1,292.4,183.6,318,189.3,340.2z"/>
- <path d="M247.7,429.6v-82.1c-18.6,0.6-36.8,3.1-54.3,7.3C206.6,396.5,227.3,423.8,247.7,429.6z"/>
- <path d="M296.7,426.1c32.4-7.8,61.3-24.5,84-47.6c-15.1-8.1-31.1-14.7-47.8-19.8C324,387.4,311.5,410.7,296.7,426.1z"/>
- <path d="M214.7,86.1c-32.1,7.8-60.8,24.5-83.3,47.4c15,8,30.8,14.6,47.3,19.6C187.6,124.6,200,101.4,214.7,86.1z"/>
- <path d="M337,344.1c19,5.7,37.1,13.4,54.2,22.8c23.2-28.2,37.7-63.8,39.5-102.6h-83.3C346.7,293,343.1,320,337,344.1z"/>
- <path d="M264.3,347.5v82c20.3-6.1,40.7-33.3,53.8-74.8C300.8,350.5,282.8,348.1,264.3,347.5z"/>
- <path d="M174.6,167.8c-18.8-5.7-36.8-13.3-53.7-22.7c-23.2,28.2-37.7,63.8-39.5,102.6h82.9C164.8,218.9,168.5,191.8,174.6,167.8z"
- />
- <path d="M164.2,264.3H81.3c1.8,38.8,16.3,74.4,39.5,102.6c16.9-9.3,34.9-17,53.7-22.7C168.5,320.2,164.8,293.1,164.2,264.3z"/>
- <path d="M131.3,378.5c22.5,22.9,51.2,39.6,83.4,47.4c-14.7-15.3-27.1-38.6-36-67.1C162.2,363.9,146.3,370.5,131.3,378.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipad.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipad.svg
deleted file mode 100644
index b1263d90..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipad.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M112,72.8v366.4c0,4.9,3.9,8.8,8.8,8.8h270.4c4.9,0,8.8-3.9,8.8-8.8V72.8c0-4.9-3.9-8.8-8.8-8.8H120.8
- C115.9,64,112,67.9,112,72.8z M256,437.6c-7.5,0-13.6-6-13.6-13.5c0-7.5,6.1-13.6,13.6-13.6c7.4,0,13.5,6.1,13.5,13.6
- C269.6,431.6,263.5,437.6,256,437.6z M144,118.6c0-3.5,2.7-6.6,6-6.6h211.2c3.4,0,6.8,3.1,6.8,6.6v275.2c0,3.5-3.4,6.3-6.8,6.3H150
- c-3.4,0-6-2.8-6-6.3V118.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/iphone.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/iphone.svg
deleted file mode 100644
index 31b50736..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/iphone.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M328.2,64H183.8C170.7,64,160,74.7,160,87.9v336.3c0,13.1,10.7,23.8,23.8,23.8h144.3c13.1,0,23.8-10.7,23.8-23.8V87.9
- C352,74.7,341.3,64,328.2,64z M240,99.9c0-2.1,1.7-3.9,3.9-3.9h24.3c2.1,0,3.9,1.7,3.9,3.9v0.3c0,2.1-1.7,3.9-3.9,3.9h-24.3
- c-2.1,0-3.9-1.7-3.9-3.9V99.9z M228,96c2.2,0,4,1.8,4,4c0,2.2-1.8,4-4,4s-4-1.8-4-4C224,97.8,225.8,96,228,96z M256,432.1
- c-8.9,0-16.1-7.2-16.1-16.1c0-8.9,7.2-16.1,16.1-16.1c8.9,0,16.1,7.2,16.1,16.1C272.1,424.9,264.8,432.1,256,432.1z M336,384H176
- V128h160V384z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipod.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipod.svg
deleted file mode 100644
index ad02aec3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ipod.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,311c-17.7,0-32,14.3-32,32c0,17.6,14.3,32,32,32c17.6,0,32-14.3,32-32C288,325.3,273.7,311,256,311z"/>
- <path d="M340.4,64H171.6C156.4,64,144,76.2,144,91.7v328.7c0,15.5,12.4,27.7,27.6,27.7h168.8c15.2,0,27.6-12.2,27.6-27.7V91.7
- C368,76.2,355.6,64,340.4,64z M256.1,416.1c-39.8,0-72.1-32.2-72.1-72c0-39.7,32.3-72,72.1-72c39.7,0,71.9,32.3,71.9,72
- C328,383.9,295.8,416.1,256.1,416.1z M335.9,226.8c-0.8,7.6-7,13.2-14.7,13.2h-131c-8.2,0-14.2-6.2-14.2-14.6V110.9
- c0-7.5,5-13.7,12-14.9l135.8,0c6.5,1.2,11.5,6.6,12.2,13.3L335.9,226.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/jet.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/jet.svg
deleted file mode 100644
index c7238e20..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/jet.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M314.8,368.5L419,403l-3-52.7L302,247c0,0-25.9-173.7-28.2-192.3C268.5,14.4,255.9,0,255.9,0
- s-12.5,14.4-17.6,54.6C235.9,73.3,210,247,210,247L96,350.3L93,403l104.2-34.5l1.4,12.3l-52.7,58.3l18.3,27.4l73.3-9.1l18.3,54.6
- l18.5-54.6l73.4,9.1l18.3-27.4l-52.7-58.3L314.8,368.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/key.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/key.svg
deleted file mode 100644
index 3bc445dc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/key.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M304.3,301c0,0-5.4-28-7.3-90c-1.9-62-9-142.5-9-142.5c-2.5-28-11.8-36.5-32-36.5c-9.4,0-20.5,2.3-23.3,3.3
- c-9.4,3.6-8.7,11.6-8.7,22.5l0,17.8c0,3.2,1.2,6,3.2,8.2l0.8,0.8l4.1,4.1c0.4,0.3,0.1,0.7,0.4,1c1.9,2.2,3.1,5,3.1,8.1l0,24.5
- c0,3.2-1.2,3.2-3.2,5.3c-0.2,0.3-0.5,0.6-0.8,0.8l-4.4,4.4c-0.1,0.1-0.3,0.3-0.4,0.4c-2.1,2.2-3.4,5.2-3.4,8.4l0,7.2
- c0,3.1,1.1,5.9,3.1,8.1c0,0,0.1,0.1,0.1,0.1l0.8,0.8c0,0,0.1,0.1,0.1,0.1l4,4c0.4,0.3,0.7,0.7,1,1c1.9,2.2,3.1,5,3.1,8.1
- c0,0.7-0.1,8.1-0.2,8.8c-0.4,2.3-1.5,4.4-3,6.1c-0.2,0.3-0.5,0.6-0.8,0.8l-3.9,3.9l-1.4,1.5c-0.5,0.6-0.7,1.3-1.1,2.1
- c-0.9,1.7-1.2,3.7-1.2,5.9v7.8c0,2.9-0.1,5.7-0.2,8.6c0.2,2.4,7.2,5.7,7.2,10.5v20.4c0,6.2-10.5,7-11,11.3
- c-4.7,25.4-11.9,41.8-11.9,41.8c-28.7,16.6-48,47.6-48,83.2c0,53,43,96,96,96s96-43,96-96C352,348.6,332.8,317.7,304.3,301z
- M256,448c-17.7,0-32-14.3-32-32s14.3-32,32-32s32,14.3,32,32S273.7,448,256,448z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/knife.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/knife.svg
deleted file mode 100644
index c70faa3b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/knife.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M285.7,32c-3.3,0-6,1.4-8,3.8C259,58.7,224,116.1,224,250.1c0,39.2,33,39.2,32,69.4c0,0.1,0,0.3,0,0.4
- c-2,47.1-14.9,111.1-16,130.3c-0.4,15.2,9.7,29.8,24.1,29.8c0.1,0,0.1,0,0.2,0c0,0,0.1,0,0.2,0c14.4,0,23.5-14.4,23.5-29.6V38.3
- C288,33.3,287.5,32,285.7,32z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/laptop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/laptop.svg
deleted file mode 100644
index 669df211..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/laptop.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M480,106.3c0-5.6-4.1-10.3-9.6-10.3H42.2c-5.5,0-10.2,4.6-10.2,10.3V368h448V106.3z M448,336H64V128h384V336z"/>
- <path d="M0,388.7C70.2,408.6,115.8,416,256,416c140.2,0,185.8-7.3,256-27.3V384H0V388.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/leaf.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/leaf.svg
deleted file mode 100644
index da913165..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/leaf.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M456.7,378.7c-52.5-8-56.5-15.7-56.5-15.7c10.8-64.9-22.7-147.1-77.4-191.6c-72.8-59.2-183.5-16.2-269.7-106.2
- c-20.1-21-8.4,235.5,99.5,332.7c78.9,71,171.8,49.2,197.3,37.6c23.1-10.6,39.3-29.9,39.3-29.9c42.1,13,62.9,12.2,62.9,12.2
- C466.9,419.6,474.4,381.4,456.7,378.7z M360.6,383.1c-138.2-40.9-242.1-184.5-242.1-184.5s91.2,107.7,252,160.2
- C370.7,366.9,365.9,378.5,360.6,383.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/levels.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/levels.svg
deleted file mode 100644
index 34d7254f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/levels.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M127,99.2V80c0-8.8-7.2-16-16-16s-16,7.2-16,16v21.5c-8.5,5.8-14,15.5-14,26.5s5.5,20.7,14,26.5V432c0,8.8,7.2,16,16,16
- s16-7.2,16-16V156.8c10.7-5.2,18-16.1,18-28.8S137.7,104.4,127,99.2z"/>
- <path d="M223,292.9V80c0-8.8-7.2-16-16-16s-16,7.2-16,16v211.7c-10.1,5.4-17,16-17,28.3s6.9,22.9,17,28.3V432c0,8.8,7.2,16,16,16
- s16-7.2,16-16v-84.9c9-5.7,15-15.7,15-27.1S232,298.6,223,292.9z"/>
- <path d="M319,163.3V80c0-8.8-7.2-16-16-16s-16,7.2-16,16v83.3c-9.6,5.5-16,15.9-16,27.7s6.4,22.2,16,27.7V432c0,8.8,7.2,16,16,16
- s16-7.2,16-16V218.7c9.6-5.5,16-15.9,16-27.7S328.6,168.8,319,163.3z"/>
- <path d="M431,383c0-11.8-6.4-22.2-16-27.7V80c0-8.8-7.2-16-16-16s-16,7.2-16,16v275.3c-9.6,5.5-16,15.9-16,27.7s6.4,22.2,16,27.7
- V432c0,8.8,7.2,16,16,16s16-7.2,16-16v-21.3C424.6,405.2,431,394.8,431,383z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lightbulb.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lightbulb.svg
deleted file mode 100644
index 65d968b1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lightbulb.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32c-70.7,0-128,55.4-128,123.8c0,4.9,0.3,9.7,0.9,14.5c0.6,5.4,1.6,10.6,3,15.7c0.1,0.5,0.3,1.1,0.4,1.6
- c16.6,62.8,45.3,71.5,58.9,167.6c0,0.2,0.1,0.4,0.1,0.5c1.5,9.2,9.8,12.3,19.8,12.3H301c10,0,18.2-3.1,19.7-12.3
- c0-0.2,0.1-0.4,0.1-0.5c13.6-96.1,42.3-104.7,58.9-167.6c0.2-0.5,0.3-1,0.4-1.6c1.3-5.1,2.3-10.4,3-15.7c0.6-4.7,0.9-9.6,0.9-14.5
- C384,87.4,326.7,32,256,32z"/>
- <path d="M317.8,396.5c0.1-0.2,0.3-0.4,0.4-0.6c1.1-1.7,1.7-3.6,1.7-5.7c0-3.5,1.6-6.2-6.5-6.2H198.6c-8.1,0-6.5,2.1-6.5,6.2
- c0,2.1,0.6,4,1.7,5.7c0.1,0.2,0.3,0.4,0.5,0.6c0,0.1,0.1,0.1,0.1,0.2c1.7,2.6,2.7,4.4,2.7,7.6c0,3.1-0.9,4.9-2.6,7.5
- c-0.3,0.4-0.5,0.7-0.7,1c-1,1.7-1.6,3.6-1.6,5.6c0,2.1,0.6,4,1.7,5.8c0.1,0.2,0.3,0.4,0.4,0.6c1.8,2.7,2.8,4.5,2.8,7.8
- c0,3.1-0.9,4.9-2.6,7.4c-0.2,0.4-0.5,0.7-0.8,1.1c-1,1.7-1.6,3.6-1.6,5.6c0,5.4,4.3,10.1,10.2,11.6c0.3,0.1,0.6,0.1,0.9,0.2
- c6,1.4,12.2,1.6,18.5,2.5c0.7,0.1,1.4,0.2,2.2,0.3c5.6,1,10.3,3.9,13.4,7.7l0,0c3.8,5.3,10.8,11,18.8,11c7.6,0,14.3-5.4,18.2-10.4
- h0c3-4.2,8-7.3,13.9-8.4c0.7-0.1,1.4-0.3,2.2-0.3c6.3-0.9,12.5-1.1,18.5-2.5c0.3-0.1,0.6-0.1,0.9-0.2c5.9-1.6,10.2-6.2,10.2-11.6
- c0-2-0.6-3.9-1.6-5.6c-0.3-0.4-0.5-0.7-0.8-1.1c-1.6-2.6-2.6-4.3-2.6-7.4c0-3.2,1-5.1,2.8-7.8c0.1-0.2,0.3-0.4,0.4-0.6
- c1.1-1.7,1.7-3.7,1.7-5.8c0-2-0.6-3.9-1.6-5.6c-0.3-0.3-0.5-0.7-0.7-1c-1.6-2.6-2.6-4.3-2.6-7.5c0-3.2,1-5,2.7-7.6
- C317.7,396.7,317.7,396.6,317.8,396.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/link.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/link.svg
deleted file mode 100644
index 97465186..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/link.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256.5,208H256v0C256.2,208,256.3,208,256.5,208z"/>
- <path d="M368.5,160H320c0,0,26,17,31.6,48H368h0.5c17.6,0,31.5,13.9,31.5,31.5v32c0,17.6-13.9,32.5-31.5,32.5h-112
- c-17.6,0-32.5-14.9-32.5-32.5V240h-48v31.5c0,11.5,2.5,22.5,6.9,32.5c12.6,28.2,40.9,48,73.6,48h112c44.2,0,79.5-36.3,79.5-80.5
- v-32C448,195.3,412.7,160,368.5,160z"/>
- <path d="M329.6,208c-12.1-28.3-40.1-48-73.1-48h-112c-44.2,0-80.5,35.3-80.5,79.5v32c0,44.2,36.3,80.5,80.5,80.5H192
- c0,0-25.8-17-32.1-48h-15.4c-17.6,0-32.5-14.9-32.5-32.5v-32c0-17.6,14.9-31.5,32.5-31.5H256h0.5c17.6,0,31.5,13.9,31.5,31.5v32
- c0,0.2,0,0.3,0,0.5h48c0-0.2,0-0.3,0-0.5v-32C336,228.3,333.7,217.6,329.6,208z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-a.svg
deleted file mode 100644
index b41fdfc3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-a.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <circle cx="256" cy="96" r="64"/>
- <circle cx="96" cy="256" r="48"/>
- <circle cx="368" cy="144" r="8"/>
- <path d="M180.1,107.6c-19.9-20.1-52.2-20.1-72.1,0c-19.9,20.1-19.9,52.7,0,72.8c19.9,20.1,52.2,20.1,72.1,0
- C200,160.3,200,127.7,180.1,107.6z"/>
- <circle cx="416" cy="256" r="16"/>
- <circle cx="369" cy="369" r="24"/>
- <circle cx="256" cy="416" r="32"/>
- <circle cx="144" cy="368" r="40"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-b.svg
deleted file mode 100644
index b3254f65..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-b.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M288,160c0,17.7-14.3,32-32,32l0,0c-17.7,0-32-14.3-32-32V64c0-17.7,14.3-32,32-32l0,0c17.7,0,32,14.3,32,32V160z"/>
- <path d="M256,320c-17.7,0-32,14.3-32,32v96c0,17.7,14.3,32,32,32s32-14.3,32-32v-96C288,334.3,273.7,320,256,320L256,320z"/>
- <path d="M448,224h-96c-17.7,0-32,14.3-32,32s14.3,32,32,32h96c17.7,0,32-14.3,32-32S465.7,224,448,224L448,224z"/>
- <path d="M160,224H64c-17.7,0-32,14.3-32,32s14.3,32,32,32h96c17.7,0,32-14.3,32-32S177.7,224,160,224L160,224z"/>
- <path d="M346.5,210.7c-12.5,12.5-32.8,12.5-45.3,0l0,0c-12.5-12.5-12.5-32.8,0-45.3l67.9-67.9c12.5-12.5,32.8-12.5,45.3,0l0,0
- c12.5,12.5,12.5,32.8,0,45.3L346.5,210.7z"/>
- <path d="M210.7,301.3c-12.5-12.5-32.8-12.5-45.3,0l-67.9,67.9c-12.5,12.5-12.5,32.8,0,45.3c12.5,12.5,32.8,12.5,45.3,0l67.9-67.9
- C223.2,334,223.2,313.8,210.7,301.3L210.7,301.3z"/>
- <path d="M414.4,369.1l-67.9-67.9c-12.5-12.5-32.8-12.5-45.3,0c-12.5,12.5-12.5,32.8,0,45.3l67.9,67.9c12.5,12.5,32.8,12.5,45.3,0
- C426.9,401.9,426.9,381.6,414.4,369.1L414.4,369.1z"/>
- <path d="M210.7,165.5l-67.9-67.9c-12.5-12.5-32.8-12.5-45.3,0c-12.5,12.5-12.5,32.8,0,45.3l67.9,67.9c12.5,12.5,32.8,12.5,45.3,0
- S223.2,178,210.7,165.5L210.7,165.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-c.svg
deleted file mode 100644
index e8cf4ebc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-c.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M479.8,226.1c-1.4-8.7-3.1-17.3-5.3-25.8c-2.8-10.8-6.4-21.5-10.8-31.8c-8.9-21.2-21.1-41-35.9-58.6
- c-16-18.9-35.3-35.2-56.7-47.7C350,49.8,327,41,303,36.1c-12.4-2.5-24.9-4-37.6-4.1c-9.9-0.1-19.8,0.3-29.6,1.2
- c-25.5,2.5-50.7,9.6-73.9,20.5c-19.9,9.4-38.4,21.6-54.8,36.2c-16.4,14.6-30.7,31.6-42.2,50.3c-12.7,20.8-22.2,43.5-27.4,67.3
- c-4.2,19-6.2,38.6-5.2,58.1c0.9,18.9,3.8,37.8,9.5,55.9c3.6,11.5,7.9,22.7,13.3,33.6c5.3,10.7,11.5,21,18.4,30.7
- c13.8,19.3,30.6,36.4,49.8,50.5c19.6,14.5,41.7,25.7,64.9,33.1c24.2,7.7,49.9,11.3,75.3,10.4c24.8-0.8,49.4-5.6,72.6-14.5
- c22.3-8.6,43.2-20.9,61.5-36.3c9.2-7.8,17.4-16.6,25.1-25.9c7.8-9.4,14.8-19.3,20.6-30c5-9.2,9.2-18.8,12.8-28.5
- c1.8-4.8,3.5-9.6,4.9-14.6c1.5-5.3,2.6-10.8,3.6-16.2c1.5-8.5,2.1-17.3,1.3-25.9c-0.7,3.8-1.3,7.5-2.2,11.2
- c-1.1,4.3-2.5,8.5-4.1,12.6c-3.2,8.7-7.2,17.1-11,25.5c-4.9,10.7-10.6,20.9-16.8,30.8c-3.2,5.1-6.5,10.1-10.1,14.9
- c-3.6,4.8-7.7,9.4-11.8,13.9c-8.2,9.1-17.1,17.2-27,24.4c-10.1,7.4-20.8,13.9-32.1,19.3c-22.6,11-47.3,17.6-72.3,19.8
- c-25.6,2.2-51.7-0.3-76.3-7.6c-23.4-6.9-45.6-18.1-65.1-32.8c-18.9-14.3-35.3-31.9-48.2-51.8C75.4,347.8,66.1,324.9,61,301
- c-1.3-6.2-2.3-12.6-3-18.9c-0.6-5.4-1.1-10.9-1.3-16.4c-0.3-11.3,0.4-23,2.1-34.2c3.7-24.6,11.7-48.3,24.1-69.9
- c11-19.3,25.3-36.7,42.1-51.4c16.8-14.8,36-26.7,56.8-35.1c12-4.9,24.6-8.5,37.4-10.9c6.5-1.2,13-2.2,19.5-2.7
- c3.2-0.3,6.3-0.3,9.5-0.6c1.3,0,2.6,0.1,3.9,0.1c21.7-0.4,43.5,2.4,64.2,8.9c22.3,7,43.3,18.3,61.5,33c19.1,15.4,35,34.4,47,55.8
- c10.2,18.2,17.5,37.8,21.9,58.2c1,4.7,1.8,9.4,2.6,14.1c0.7,4.3,3.1,8.3,6.8,10.7c7.8,5.2,18.7,1.7,22.5-6.7
- C479.9,232.1,480.3,229,479.8,226.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-d.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-d.svg
deleted file mode 100644
index bdedb934..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/load-d.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M432,240h-80c-8.8,0-16,7.2-16,16s7.2,16,16,16h80c8.8,0,16-7.2,16-16S440.8,240,432,240z"/>
- <path d="M176,256c0-8.8-7.2-16-16-16H80c-8.8,0-16,7.2-16,16s7.2,16,16,16h80C168.8,272,176,264.8,176,256z"/>
- <path d="M256,336c-8.8,0-16,7.2-16,16v80c0,8.8,7.2,16,16,16s16-7.2,16-16v-80C272,343.2,264.8,336,256,336z"/>
- <path d="M256,64c-8.8,0-16,7.2-16,16v80c0,8.8,7.2,16,16,16s16-7.2,16-16V80C272,71.2,264.8,64,256,64z"/>
- <path d="M325.3,216c4.4,7.7,14.2,10.3,21.9,5.9l69.3-40c7.7-4.4,10.3-14.2,5.9-21.9s-14.2-10.3-21.9-5.9l-69.3,40
- C323.5,198.6,320.9,208.3,325.3,216z"/>
- <path d="M186.7,296c-4.4-7.7-14.2-10.3-21.9-5.9l-69.3,40c-7.7,4.4-10.3,14.2-5.9,21.9s14.2,10.3,21.9,5.9l69.3-40
- C188.5,313.4,191.1,303.7,186.7,296z"/>
- <path d="M317.9,331.1c-4.4-7.7-14.2-10.3-21.9-5.9s-10.3,14.2-5.9,21.9l40,69.3c4.4,7.7,14.2,10.3,21.9,5.9
- c7.7-4.4,10.3-14.2,5.9-21.9L317.9,331.1z"/>
- <path d="M181.9,95.6c-4.4-7.7-14.2-10.3-21.9-5.9c-7.7,4.4-10.3,14.2-5.9,21.9l40,69.3c4.4,7.7,14.2,10.3,21.9,5.9
- s10.3-14.2,5.9-21.9L181.9,95.6z"/>
- <path d="M296,186.7c7.7,4.4,17.4,1.8,21.9-5.9l40-69.3c4.4-7.7,1.8-17.4-5.9-21.9c-7.7-4.4-17.4-1.8-21.9,5.9l-40,69.3
- C285.7,172.5,288.3,182.3,296,186.7z"/>
- <path d="M216,325.3c-7.7-4.4-17.4-1.8-21.9,5.9l-40,69.3c-4.4,7.7-1.8,17.4,5.9,21.9c7.7,4.4,17.4,1.8,21.9-5.9l40-69.3
- C226.3,339.5,223.7,329.7,216,325.3z"/>
- <path d="M416.4,330.1l-69.3-40c-7.7-4.4-17.4-1.8-21.9,5.9c-4.4,7.7-1.8,17.4,5.9,21.9l69.3,40c7.7,4.4,17.4,1.8,21.9-5.9
- C426.7,344.3,424.1,334.6,416.4,330.1z"/>
- <path d="M95.6,181.9l69.3,40c7.7,4.4,17.4,1.8,21.9-5.9s1.8-17.4-5.9-21.9l-69.3-40c-7.7-4.4-17.4-1.8-21.9,5.9
- C85.3,167.7,87.9,177.4,95.6,181.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/location.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/location.svg
deleted file mode 100644
index 60c274d2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/location.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,64c-65.9,0-119.3,53.7-119.3,120c0,114.6,119.3,264,119.3,264s119.3-149.4,119.3-264C375.3,117.7,321.9,64,256,64z
- M256,242.2c-31.2,0-56.4-25.4-56.4-56.7c0-31.3,25.3-56.8,56.4-56.8c31.2,0,56.4,25.4,56.4,56.8
- C312.4,216.8,287.2,242.2,256,242.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lock-combination.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lock-combination.svg
deleted file mode 100644
index c06e0009..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/lock-combination.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M384,176.905V128C384,57.308,326.692,0,256,0S128,57.308,128,128v48.906C88.725,212.062,64,263.141,64,320
- c0,106.039,85.962,192,192,192c106.039,0,192-85.961,192-192C448,263.141,423.275,212.062,384,176.905z M160,128
- c0-52.935,43.065-96,96-96s96,43.065,96,96v25.692C323.759,137.355,290.973,128,256,128s-67.759,9.355-96,25.693V128z M256,480
- c-88.366,0-160-71.634-160-160s71.634-160,160-160s160,71.634,160,160S344.366,480,256,480z"/>
- <path d="M256,176c-79.529,0-144,64.472-144,144s64.471,144,144,144s144-64.472,144-144S335.529,176,256,176z M378.533,353.487
- l-24.12-7.896l-3.926,12.19l24.161,7.912c-3.661,9.776-8.462,18.965-14.252,27.409l-10.56-7.737l-3.74,5.184l10.555,7.734
- c-6.129,8.047-13.189,15.324-21.028,21.682l-14.982-20.787l-10.284,7.532l14.976,20.776c-8.479,5.556-17.657,10.12-27.398,13.532
- l-3.96-12.294l-6.049,1.982l4.924,12.262C283.335,445.77,273,447.497,264,448v-12.659V429h-16v6.341V448
- c-11-0.506-19.705-2.244-29.243-5.065l3.948-11.206l-6.25-2.106l-3.539,11.224c-9.557-3.393-18.531-7.895-26.864-13.359
- l14.997-20.774l-10.27-7.534l-14.977,20.787c-7.809-6.333-14.841-13.575-20.953-21.583l9.556-6.998l-3.971-5.507l-9.562,7
- c-5.718-8.381-10.469-17.497-14.093-27.186l24.162-7.914l-3.926-12.188l-24.121,7.897c-2.49-9.431-3.954-18.488-4.258-29.487H134
- v-6.805l-5.993-0.002c0.223-10.606,0.672-20.88,3.266-30.682l24.921,7.9l4.347-12.188l-23.966-7.914
- c3.585-9.57,8.36-18.583,13.985-26.879l10.339,7.533l3.759-5.184l-10.292-7.545c6.221-8.253,13.424-15.707,21.434-22.197
- l14.984,20.787l10.284-7.536l-14.975-20.774c8.405-5.514,17.512-10.05,27.16-13.449l3.955,12.247l6.044-1.98l-4.62-12.231
- C228.21,194.258,237,192.508,248,192v12.66V211h16v-6.34V192c9,0.498,19.159,2.198,28.585,4.951l-4.761,13.28l6.182,2.106
- l4.174-13.312c9.696,3.408,18.778,7.957,27.208,13.491l-15.002,20.775l10.267,7.535l14.975-20.787
- c7.935,6.432,15.069,13.812,21.255,21.977l-11.299,8.268l3.975,5.512l11.276-8.26c5.595,8.271,10.247,17.243,13.816,26.775
- l-24.165,7.914l3.928,12.188l24.12-7.9c2.586,9.802,5.251,20.075,5.47,30.683L376,317.192V324h6.789
- C382.486,334.999,381.02,344.057,378.533,353.487z"/>
- <circle cx="256" cy="320" r="81"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/locked.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/locked.svg
deleted file mode 100644
index 4690abc8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/locked.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M86.4,480h339.2c12.3,0,22.4-9.9,22.4-22.1V246c0-12.2-10-22-22.4-22H404v-30.9c0-41.5-16.2-87.6-42.6-115.4
- C335.1,49.9,297.4,32,256.1,32c-0.1,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0c-41.3,0-79,17.9-105.3,45.6c-26.4,27.8-42.6,73.9-42.6,115.4V224
- H89h-2.6C74,224,64,233.9,64,246v211.9C64,470.1,74,480,86.4,480z M161,193.1c0-27.3,9.9-61.1,28.1-80.3l0,0l0-0.3
- C206.7,93.9,231,83,255.9,83h0.1h0.1c24.9,0,49.2,10.9,66.8,29.5l0,0.2l-0.1,0.1c18.3,19.2,28.1,53,28.1,80.3V224h-17.5h-155H161
- V193.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-in.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-in.svg
deleted file mode 100644
index 580dfe25..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-in.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M255.988,32C160.473,32,78.934,91.804,46.727,176h34.639c9.396-20.484,22.457-39.35,38.868-55.762
- C156.497,83.973,204.709,64,255.988,64c51.286,0,99.504,19.973,135.771,56.239C428.027,156.505,448,204.719,448,256
- c0,51.285-19.973,99.501-56.239,135.765C355.494,428.029,307.275,448,255.988,448c-51.281,0-99.493-19.971-135.755-56.234
- C103.821,375.354,90.76,356.486,81.362,336H46.725c32.206,84.201,113.746,144,209.264,144C379.703,480,480,379.715,480,256
- C480,132.298,379.703,32,255.988,32z"/>
- <polygon points="206.863,323.883 229.49,346.51 320,256 229.49,165.49 206.862,188.118 258.745,240 32,240 32,272 258.745,272 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-out.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-out.svg
deleted file mode 100644
index e8a3d06a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/log-out.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="366.863,323.883 389.49,346.51 480,256 389.49,165.49 366.862,188.118 418.745,240 192,240 192,272 418.745,272
- "/>
- <g>
- <path d="M391.491,391.766C355.229,428.029,307.018,448,255.736,448c-51.287,0-99.506-19.971-135.772-56.235
- C83.697,355.501,64,307.285,64,256c0-51.281,19.697-99.495,55.965-135.761C156.232,83.973,204.45,64,255.736,64
- c51.279,0,99.491,19.973,135.755,56.238c2.527,2.528,4.966,5.121,7.333,7.762h40.731c-40.474-58.028-107.709-96-183.819-96
- C132.021,32,32,132.298,32,256c0,123.715,100.021,224,223.736,224c76.112,0,143.35-37.97,183.822-96h-40.73
- C396.46,386.643,394.021,389.236,391.491,391.766z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/loop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/loop.svg
deleted file mode 100644
index 72ccc5f0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/loop.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M273.4,300.5l-0.3,58c48.9-8.2,86.3-51,86.3-102.5c0-15.9-3.6-31-10-44.5c-2.8-5.8-6-11.3-9.8-16.5l47.1-43.5
- c1.1,1.3,2.1,2.7,3.1,4c20.9,28,33.2,62.8,33.2,100.5c0,1.2,0,2.5,0,3.7c-1.5,71.5-47.6,132-111.4,154.6
- c-12.3,4.3-25.2,7.3-38.5,8.7l-0.1,57l-76.2-67L170.6,390l44.4-38.7L273.4,300.5z"/>
- <path d="M89,252.3c1.6-72.1,48.3-133,112.9-155.2c11.7-4,24-6.8,36.8-8.1l0.1-57l76.1,66.9l26.2,23.1l-44.3,38.6l-58.4,50.9
- l0.2-57.9c-48.8,8.3-86,51.1-86,102.4c0,16,3.6,31.1,10.1,44.7c2.7,5.8,6,11.2,9.7,16.3l-47,43.6c-1.3-1.6-2.6-3.3-3.8-5
- C101.1,327.7,89,293.3,89,256C89,254.8,89,253.5,89,252.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/magnet.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/magnet.svg
deleted file mode 100644
index 3696d318..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/magnet.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C141,32.5,64,109.6,64,231.8c0,48.8,2.1,76.8,14.5,127.8c15.9,65.7,39.1,113.3,39.1,113.3l0.6,1.3
- c1.9,3.4,5.5,5.8,9.8,5.8c1.4,0,2.7-0.2,4-0.7l1.7-0.8l50.3-20.7l1.8-0.8c3.3-1.9,5.5-5.3,5.5-9.3c-0.2-1.4-0.4-2.8-1-4
- c-0.1-0.1-0.1-0.2-0.2-0.4c-7-16-27.2-59.2-37-101.1c-9.9-41.9-13.5-62.4-13.5-107.7C139.6,163.4,192,112,256,112
- c64,0,116.4,51.4,116.4,122.5c0,45.3-3.7,65.8-13.6,107.7c-9.9,41.9-30,85.2-37,101.1c-0.1,0.2-0.1,0.3-0.2,0.4
- c-0.6,1.2-0.8,2.6-1,4c0,4,2.2,7.4,5.5,9.3l1.8,0.8l50.3,20.7l1.7,0.8c1.3,0.5,2.6,0.7,4,0.7c4.3,0,7.9-2.4,9.8-5.8l0.6-1.3
- c0,0,23.2-47.6,39.1-113.3c12.4-51,14.5-79,14.5-127.8C448,109.6,371,32.5,256,32z M173,444.2c0.1,0.2,0.2,0.5,0.3,0.7l-42.8,17.6
- c-5.4-11.8-22.7-51-35.7-104.4l42.5-12.3C146.5,385,164.4,425,173,444.2z M381.4,462.5l-42.8-17.6c0.1-0.2,0.2-0.4,0.3-0.7
- c8.6-19.2,26.4-59.2,35.6-98.4l42.5,12.3C404.1,411.5,386.8,450.7,381.4,462.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/male.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/male.svg
deleted file mode 100644
index 941be49e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/male.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M480,192V32H320l63,63l-68.7,68.7C284.8,141.3,247.9,128,208,128c-97.2,0-176,78.8-176,176s78.8,176,176,176
- s176-78.8,176-176c0-39.9-13.3-76.8-35.7-106.3L417,129L480,192z M298.5,394.5C274.3,418.7,242.2,432,208,432s-66.3-13.3-90.5-37.5
- C93.3,370.3,80,338.2,80,304s13.3-66.3,37.5-90.5c24.2-24.2,56.3-37.5,90.5-37.5s66.3,13.3,90.5,37.5S336,269.8,336,304
- S322.7,370.3,298.5,394.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/man.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/man.svg
deleted file mode 100644
index b4a02cf7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/man.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,106.6c20.6,0.1,37.3-16.6,37.3-37.3c0-20.6-16.7-37.3-37.3-37.3c-20.6,0-37.3,16.7-37.3,37.3
- C218.7,89.9,235.4,106.6,256,106.6z"/>
-<g>
- <path d="M293.4,115H256h-37.4c-28.2,0-46.6,24.8-46.6,48.4V277c0,22,31,22,31,0V172h6v285.6c0,30.4,42,29.4,43,0V293h7h1v164.7
- c1.7,31.2,43,28.2,43-0.1V172h5v105c0,22,32,22,32,0V163.4C340,139.9,321.5,115,293.4,115z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/map.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/map.svg
deleted file mode 100644
index 40f3363a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/map.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M473.152,136.58L368.594,66.307c-4.644-3.076-10.365-3.076-15.031,0l-97.094,65.195l-97.109-65.195
- c-4.643-3.076-10.444-3.076-15.062,0L39.344,136.58c-4.399,2.949-7.344,8.272-7.344,14.05V431.6c0,5.904,3.07,11.347,7.663,14.271
- c4.62,2.877,10.382,2.829,14.904-0.223l97.188-65.197l97.181,65.197c4.666,3.1,10.44,3.1,15.084,0l97.158-65.197l97.151,65.197
- c2.311,1.55,4.912,2.353,7.538,2.353c2.455,0,4.709-0.747,6.969-2.13c4.594-2.924,7.165-8.366,7.165-14.271v-280.97
- C480,144.852,477.575,139.529,473.152,136.58z M135,353.248l-71,49.404v-241.75l71-49.428V353.248z M167,352.766v-122.7
- c1.167,0.756,2.31,1.526,3.389,2.301l9.333-12.996c-3.904-2.804-8.292-5.501-12.722-7.705V110.992l73,48.992v108.574
- c-5.372-1.855-10.586-4.37-15.893-7.682l-8.471,13.574c6.848,4.273,13.621,7.467,20.704,9.765l3.66-11.286v128.806L167,352.766z
- M272,401.734V288.369c0.349-0.021,0.693-0.03,1.043-0.054c2.91-0.198,5.777-0.517,8.518-0.946l-2.479-15.807
- c-2.268,0.355-4.65,0.619-7.082,0.786V159.984l73-48.992V229.78l-4.844-4.372c-2.997,3.319-5.833,6.575-8.575,9.725
- c-1.806,2.073-3.578,4.108-5.339,6.095l11.974,10.613c1.791-2.021,3.595-4.091,5.431-6.2c0.443-0.509,0.905-1.035,1.354-1.549
- v108.675L272,401.734z M448,401.652l-71-48.438v-136.91c3.785-1.715,7.679-2.992,11.639-3.792l-3.166-15.683
- c-2.858,0.577-5.687,1.339-8.473,2.281v-87.671l71,48.461V401.652z"/>
- <path d="M129.285,221.111c2.218-1.195-1.353-1.071,1.012-1.837l-4.928-15.222c-3.282,1.062-6.502,2.439-9.571,4.093
- c-3.824,2.062-7.745,4.916-11.339,8.253l10.888,11.724C117.963,225.694,126.639,222.538,129.285,221.111z"/>
- <path d="M296.802,266.127l6.985,14.395c6.596-3.201,12.842-7.445,19.095-12.974l-10.599-11.987
- C307.135,260.113,302.071,263.569,296.802,266.127z"/>
- <path d="M99.364,256.006c1.893-5.926,3.528-11.044,7.129-16.304l-13.204-9.037c-4.924,7.194-7.081,13.944-9.167,20.471
- l-0.242,0.758l15.238,4.879L99.364,256.006z"/>
- <path d="M198.311,237.753c-1.007-1.204-2.014-2.408-3.032-3.603l-12.178,10.379c0.986,1.156,1.961,2.322,2.936,3.488
- c3.593,4.296,7.308,8.739,11.61,12.809l10.996-11.624C205.02,245.775,201.761,241.878,198.311,237.753z"/>
- <polygon points="408.156,229.657 418.5,219.314 428.844,229.657 440.156,218.342 429.814,208 440.156,197.657 428.844,186.342
- 418.5,196.685 408.156,186.342 396.844,197.657 407.186,208 396.844,218.342 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/medkit.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/medkit.svg
deleted file mode 100644
index 1e827a75..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/medkit.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M472.2,144H352v-30.7C351,85.1,330.3,64,300.8,64H256h-44.8c-29.4,0-50.2,21.1-51.2,49.3V144H39.8c-4.4,0-7.8,3.6-7.8,8
- v288c0,4.4,3.3,8,7.8,8h432.5c4.4,0,7.8-3.6,7.8-8V152C480,147.6,476.7,144,472.2,144z M192,117.2c0-0.4,0-0.7,0-1s0-0.6,0-1
- c0-9.7,8.6-19.3,18.8-19.3H256h45.2c10.1,0,18.8,9.5,18.8,19.3c0,0.3,0,0.6,0,1s0,0.6,0,1V144H192V117.2z M352,320h-64v64h-64v-64
- h-64v-64h64v-64h64v64h64V320z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/merge.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/merge.svg
deleted file mode 100644
index d055d31b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/merge.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M384,224c-23.637,0-44.307,12.89-55.391,32H319c-42.464,0-79.99-17.904-111.535-53.214
- c-20.356-22.787-33.493-48.869-37.856-58.218C183.301,132.822,192,115.413,192,96c0-35.29-28.71-64-64-64S64,60.71,64,96
- c0,23.637,12.89,44.307,32,55.391v209.219C76.89,371.693,64,392.363,64,416c0,35.29,28.71,64,64,64s64-28.71,64-64
- c0-23.637-12.89-44.307-32-55.391V245.692C203.553,294.307,258.468,320,319,320h9.609c11.084,19.11,31.754,32,55.391,32
- c35.29,0,64-28.71,64-64S419.29,224,384,224z M128,64c17.673,0,32,14.327,32,32s-14.327,32-32,32s-32-14.327-32-32
- S110.327,64,128,64z M128,448c-17.673,0-32-14.327-32-32s14.327-32,32-32s32,14.327,32,32S145.673,448,128,448z M384,320
- c-17.673,0-32-14.327-32-32s14.327-32,32-32s32,14.327,32,32S401.673,320,384,320z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-a.svg
deleted file mode 100644
index 32dbe94d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-a.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M112.1,238.1l-0.1,13.6c0.1,65.6,46,120.6,108.1,136.2c1.3,0.1,2.6,0.5,3.8,0.9c5.9,2,10.1,6.9,12.1,12.8v58.7
- c0,10.9,8.9,19.7,20,19.7h0.1c11.1,0,19.9-8.8,19.9-19.7v-58.8c2-5.9,6.1-10.7,12-12.7c1.2-0.4,2.5-0.8,3.9-0.9
- C354,372.3,400,317.3,400,251.7v-13.6c0-10.4-8.9-18.9-19.5-18.9c-10.6,0-19.5,8.4-19.5,18.9v13.6c0,28.5-11.5,54.1-30.6,72.8
- c-19.2,18.6-45.3,30.2-74.5,30.2c-29.2,0-55.1-11.5-74.2-30.2c-19.1-18.7-30.7-44.4-30.7-72.8v-13.6c0-10.4-8.8-18.9-19.5-18.9
- C120.9,219.2,112.1,227.7,112.1,238.1z"/>
- <path d="M179,107.7v143.8c0,41.8,34.7,75.7,77.5,75.7c42.8,0,77.5-33.9,77.5-75.7V107.7c0-41.8-34.7-75.7-77.5-75.7
- C213.7,32,179,65.9,179,107.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-b.svg
deleted file mode 100644
index c4a9e812..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-b.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256.4,32c-35.1,0.1-65.8,23.2-76.8,59.3c-5.6,18.5-3.5,44.8-1.2,54.5c2.3,9.7,7.3,19.9,13.2,28.3
- c2.8,4.2,6.7,7.4,11.2,9.2c0.6,0.3,1.3,0.5,2,0.8c3.3,1.1,6.5,2.2,10.1,3.1c11.8,3,27.1,4.7,41.1,4.8v0c0,0,0.6,0,0.7,0
- c0.3,0,0.3,0,1.3,0v-0.1c14-0.1,27.3-1.7,39.1-4.8c3.6-0.9,6.9-2,10.2-3.1c0.7-0.2,1.3-0.5,1.9-0.8c4.5-1.8,8.4-5,11.2-9.2
- c5.9-8.4,10.8-18.6,13.2-28.3c2.3-9.7,4.4-36-1.2-54.5C321.4,55.2,291.6,32.1,256.4,32z"/>
- <path d="M295.3,201.1c-0.4,0-0.7,0-1.1,0.1c-0.6,0.1-1.3,0.3-1.9,0.4c-2,0.4-4.1,0.8-6.1,1.2c-9.2,1.5-18.9,2.3-29,2.4
- c-10.1-0.1-22.3-0.9-31-2.4c-2.1-0.4-4.2-0.8-6.2-1.2c-0.6-0.1-1.3-0.3-1.9-0.4c-0.4-0.1-0.8-0.1-1.1-0.1c-6.1,0-11,5.3-11.2,11.9
- c0.1,0.8,0.2,1.6,0.2,2.4c4.8,67.2,16.8,240.7,18.2,252c0,0,2.8,12.7,32.1,12.6c0,0,0,0,0,0c29.2,0.1,32.1-12.6,32.1-12.6
- c1.4-11.3,13.4-184.8,18.2-252c0-0.8,0.1-1.6,0.2-2.4C306.3,206.4,301.4,201.1,295.3,201.1z M266,281.7c0,6-4.5,10.9-10,10.9
- c-5.5,0-10-4.9-10-10.9V249c0-6,4.5-10.9,10-10.9c5.5,0,10,4.9,10,10.9V281.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-c.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-c.svg
deleted file mode 100644
index 42f1b046..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mic-c.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M329.2,32H182.9C152.5,32,128,55.4,128,84.4V112h152v37H128v43h152v37H128v43h152v37H128v41.8c0,29,24.5,52.2,54.9,52.2H213
- v77h86v-77h30.2c30.3,0,54.8-23.2,54.8-52.2V309h-59v-37h59v-43h-59v-37h59v-43h-59v-37h59V84.4C384,55.4,359.5,32,329.2,32z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-circled.svg
deleted file mode 100644
index ccfc53fc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-circled.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32C132.3,32,32,132.3,32,256s100.3,224,224,224s224-100.3,224-224S379.7,32,256,32z M384,272H128v-32h256V272z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-round.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-round.svg
deleted file mode 100644
index 3364cd29..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus-round.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M417.4,224H94.6C77.7,224,64,238.3,64,256c0,17.7,13.7,32,30.6,32h322.8c16.9,0,30.6-14.3,30.6-32
- C448,238.3,434.3,224,417.4,224z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus.svg
deleted file mode 100644
index 0ef5565b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/minus.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<rect x="64" y="224" width="384" height="64"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/model-s.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/model-s.svg
deleted file mode 100644
index 085b1347..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/model-s.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M508.8,390.9c-0.6,4.1-1.6,8.1-3.1,11.2c-2.7,5.5-5.3,6-15.5,5.5c-13.2-0.6-32.1,0-52.1,0.8c0,5.5,0.2,8.1,0.2,8.1
- c1.3,15.1,8.1,15.6,10.8,15.6c3,0,39.2,0,43,0s7.3,0,10-1.8c3.5-2.3,5-9,6.3-20.7c0.2-1.7,0.3-3.9,0.4-6.5c0,0,0-0.1,0-0.1
- c0-0.8,0.1-1.8,0.1-2.9c0-0.4,0-0.8,0-1.1c0,0,0,0,0,0C508.9,396.3,508.9,393.3,508.8,390.9z"/>
- <path d="M3,390.9c0.6,4.1,1.6,8.1,3.1,11.2c2.7,5.5,5.3,6,15.5,5.5c13.2-0.6,32.1,0,52.1,0.8c0,5.5-0.2,8.1-0.2,8.1
- c-1.3,15.1-8.1,15.6-10.8,15.6c-3,0-39.2,0-43,0s-7,0-10-1.8c-3.6-2.1-5-9-6.3-20.7c-0.2-1.7-0.3-3.9-0.4-6.5c0,0,0-0.1,0-0.1
- c0-0.8-0.1-1.8-0.1-2.9c0-0.4,0-0.8,0-1.1c0,0,0,0,0,0C3,396.3,3,393.3,3,390.9z"/>
- <path d="M512,296.6c0-30.7-4-60.7-5.6-64c-1.2-2.4-8.9-8.7-26.4-20.6c-17.7-12.1-17.3-10.3-20.5-18.2c2.9-0.9,5.7-2.6,7.4-2.8
- c3.8-0.4,4,3.2,11.9,3.2s25-2.1,28.5-5.6c3.5-3.5,4.6-4.7,4.6-7.8s-1.8-9.5-5.2-13.3s-17.9-5.7-26.4-6.8s-9.7,0-11.9,1.4
- c-3.5,2.2-3.7,22.3-3.7,22.3l-8.3,0.2c-5.4-13.3-12.9-40.1-24.6-61.2c-12.8-23-26.2-30.2-31.8-32c-5.5-1.7-10.5-2.9-48-6.7
- c-38.3-4-68.8-4.5-96-4.5s-57.7,0.6-96,4.5c-37.5,3.9-42.5,5-48,6.7c-5.5,1.7-19,9-31.8,32c-11.7,21.1-19.2,47.9-24.6,61.2
- l-8.3-0.2c0,0-0.1-20.1-3.7-22.3c-2.2-1.4-3.4-2.6-11.9-1.4s-23,3-26.4,6.8s-5.2,10.2-5.2,13.3s1.1,4.4,4.6,7.8
- c3.5,3.5,20.6,5.6,28.5,5.6s8.1-3.6,11.9-3.2c1.7,0.2,4.6,1.9,7.4,2.8c-3.3,7.9-2.8,6.1-20.5,18.2c-17.5,12-25.3,18.2-26.4,20.6
- C4,235.9,0,265.9,0,296.6s2.2,58.3,2.2,68.1c0,4.1,0,11.3,0.9,18.2c0.6,4.1,1.5,8.1,3.1,11.2c2.7,5.5,5.2,6,15.5,5.5
- c13.2-0.6,32.3,0,52,0.8c13.2,0.5,26.7,1,38.7,1.3c30,0.6,21.2-4.4,34-4.2c12.8,0.2,63.3,2.3,109.5,2.3s96.8-2.1,109.5-2.3
- c12.8-0.2,4,4.8,34,4.2c12-0.2,25.5-0.8,38.7-1.3c19.7-0.7,38.9-1.4,52-0.8c10.3,0.5,12.8,0,15.5-5.5c1.5-3.1,2.5-7.1,3.1-11.2
- c1-6.9,0.9-14.1,0.9-18.2C509.8,355,512,327.3,512,296.6z M86.2,145.2c4.8-11.2,19.2-33.7,26.2-37.7c1.7-1,16.6-5.7,53.9-8.2
- c34.3-2.3,72.2-3.2,89.8-3.2s55.5,0.9,89.8,3.2c37.2,2.5,52.3,7.1,53.9,8.2c9,6.2,21.4,26.5,26.2,37.7c4.8,11.2,11.2,33.2,10,36.2
- c-1.2,3,1.2,4.5-15,3.2c-16.1-1.2-117.2-2.5-164.8-2.5c-47.5,0-148.6,1.3-164.8,2.5c-16.2,1.2-13.8-0.2-15-3.2
- C75,178.4,81.4,156.5,86.2,145.2z M123,270.4c-7.2,1.8-11.5,5.7-20.5,5.6c-9,0-33.3-4.1-38.5-4.3c-5.2-0.2-9.8,3.5-12.5,4.2
- s-8-1.2-16-3.7s-12.7-1.8-15.3-12.7c-2.7-10.8,0-26.3,0-26.3c17.3-0.8,34,0.8,65.3,9.6c31.3,8.8,48.7,25.7,48.7,25.7
- S130.2,268.6,123,270.4z M358.2,349.2c-14.3,1.9-74.2,2.4-102.2,2.4c-28,0-87.9-0.6-102.2-2.4c-14.6-1.9-33.6-19.4-20.5-33.3
- c17.7-18.9,14.4-18.3,54.6-23.5c34.8-4.5,61.2-4.7,68.1-4.7c6.8,0,33.3,0.3,68.1,4.7c40.2,5.2,36.9,4.6,54.6,23.5
- C391.8,329.8,372.8,347.3,358.2,349.2z M491.8,259.6c-2.7,10.8-7.3,10.2-15.3,12.7s-13.3,4.3-16,3.7s-7.3-4.3-12.5-4.2
- c-5.2,0.2-29.5,4.3-38.5,4.3c-9,0-13.3-3.8-20.5-5.6c-7.2-1.8-11.2-1.8-11.2-1.8s17.3-17,48.7-25.7c31.3-8.8,48-10.4,65.3-9.6
- C491.8,233.2,494.5,248.7,491.8,259.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/monitor.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/monitor.svg
deleted file mode 100644
index acd51f7f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/monitor.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M468.7,64H43.3c-6,0-11.3,5-11.3,11.1v265.7c0,6.2,5.2,11.1,11.3,11.1h425.4c6,0,11.3-5,11.3-11.1V75.1
- C480,69,474.8,64,468.7,64z M448,320H64V96h384V320z"/>
- <path d="M302.5,448c28-0.5,41.5-3.9,29-12.5c-12.5-8.7-28.5-15.3-29-22.5c-0.3-3.7-1.7-45-1.7-45H256h-44.8c0,0-1.5,41.3-1.7,45
- c-0.5,7.1-16.5,13.8-29,22.5c-12.5,8.7,1,12,29,12.5H302.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/more.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/more.svg
deleted file mode 100644
index 55294f5d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/more.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M113.7,304C86.2,304,64,282.6,64,256c0-26.5,22.2-48,49.7-48c27.6,0,49.8,21.5,49.8,48C163.5,282.6,141.3,304,113.7,304z"
- />
- <path d="M256,304c-27.5,0-49.8-21.4-49.8-48c0-26.5,22.3-48,49.8-48c27.5,0,49.7,21.5,49.7,48C305.7,282.6,283.5,304,256,304z"/>
- <path d="M398.2,304c-27.5,0-49.8-21.4-49.8-48c0-26.5,22.2-48,49.8-48c27.5,0,49.8,21.5,49.8,48C448,282.6,425.8,304,398.2,304z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mouse.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mouse.svg
deleted file mode 100644
index 31585834..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/mouse.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,32c-0.46,0-0.917,0.011-1.376,0.015l5.747,0.057C258.92,32.029,257.464,32,256,32z"/>
- <path d="M378.553,193.211c-0.195,0.064-0.414,0.16-0.619,0.269c-34.234,13.289-76.337,22.52-121.886,22.475
- c-45.52-0.076-87.626-9.398-121.81-22.772c-0.19-0.104-0.429-0.192-0.647-0.265c-1.531-0.554-3.146-0.897-4.841-0.917
- c-0.254-0.001-0.5-0.013-0.75,0v176.012C128,429.892,185.308,480,256,480c21.992,0,42.687-4.803,60.766-13.355
- c0.095-0.045,0.191-0.087,0.286-0.133c0.026-0.013,0.054-0.026,0.08-0.039c4.87-2.344,9.581-4.963,14.122-7.828
- C363.219,438.275,384,405.271,384,368.012V192c-0.191-0.008-0.496,0-0.689,0C381.584,192.014,380.092,192.651,378.553,193.211z
- M317.132,466.424c-0.026,0.013-0.054,0.026-0.08,0.039c-0.095,0.045-0.191,0.088-0.286,0.133c0.095-0.045,0.191-0.088,0.286-0.133
- C317.078,466.45,317.105,466.437,317.132,466.424c4.87-2.342,9.581-4.961,14.122-7.825
- C326.758,461.463,322.044,464.083,317.132,466.424z"/>
- <path d="M331.254,458.599c-4.541,2.864-9.252,5.483-14.122,7.825C322.044,464.083,326.758,461.463,331.254,458.599z"/>
- <path d="M260.371,32.072l-5.747-0.057C184.566,32.662,128,82.547,128,144v22.708c2.158,2.024,4.593,3.755,7.251,5.115
- c0.673,0.337,1.386,0.659,2.059,0.996c0.032,0.027,0.077,0.01,0.109,0.036c22.757,10.35,51.429,15.801,83.415,19.006
- c0.694,0.078,1.397,0.107,2.148,0.12C234.24,191.997,239.996,192,240,181.411V96c0-8.836,7.164-16,16-16c8.836,0,16,7.164,16,16
- v86.328c-0.088,9.672,5.926,9.72,17.2,9.749c0.717-0.016,1.415-0.045,2.081-0.105c0.062-0.003,0.141,0.005,0.244-0.02
- c31.682-3.119,60.143-8.405,82.808-18.59c1.162-0.545,2.291-1.056,3.407-1.581c2.271-1.232,4.365-2.743,6.26-4.466V144
- C384,83.425,329.039,34.09,260.371,32.072z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/music-note.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/music-note.svg
deleted file mode 100644
index 51a07b97..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/music-note.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M426,32.1c-2.2,0-5.1,0.6-5.1,0.6L203.3,65.9C189.5,69.6,177,83,176,97.5V384h-61v-0.1c-28,0-51.1,20-51.1,48
- s23.1,48,51.3,48h36.2c15.3,0,28.9-6.9,38.3-17.5c0.1-0.1,0.3-0.1,0.4-0.2c0.6-0.6,1-1.5,1.5-2.1c1.3-1.6,2.4-3.2,3.4-5
- C204.6,441,208,422.3,208,414V182l208-38c0,0,0,136,0,192h-60.5c-28.3,0-51.2,19.9-51.2,48s22.9,48,51.2,48h37.2
- c18.2,0,34.1-6,43.2-21c0,0,0.1,0,0.2,0c9-12,12-30.2,12-54.9c0-24.8,0-302.8,0-302.8C448,41.6,438.1,32.1,426,32.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon-round.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon-round.svg
deleted file mode 100644
index f3adc265..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon-round.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M417.4,224H94.6C77.7,224,64,238.3,64,256c0,17.7,13.7,32,30.6,32h322.8c16.9,0,30.6-14.3,30.6-32
- C448,238.3,434.3,224,417.4,224z"/>
- <path d="M417.4,96H94.6C77.7,96,64,110.3,64,128c0,17.7,13.7,32,30.6,32h322.8c16.9,0,30.6-14.3,30.6-32
- C448,110.3,434.3,96,417.4,96z"/>
- <path d="M417.4,352H94.6C77.7,352,64,366.3,64,384c0,17.7,13.7,32,30.6,32h322.8c16.9,0,30.6-14.3,30.6-32
- C448,366.3,434.3,352,417.4,352z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon.svg
deleted file mode 100644
index 7323a62d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navicon.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="96" y="241" width="320" height="32"/>
- <rect x="96" y="145" width="320" height="32"/>
- <rect x="96" y="337" width="320" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navigate.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navigate.svg
deleted file mode 100644
index ad3338f1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/navigate.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="480,32 32,224 288,224 288,480 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/network.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/network.svg
deleted file mode 100644
index c00db46e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/network.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,96c0-35.29-28.71-64-64-64s-64,28.71-64,64c0,23.637,12.89,44.307,32,55.391v52.832l-96,48l-96-48v-52.832
- c19.11-11.084,32-31.754,32-55.391c0-35.29-28.71-64-64-64S64,60.71,64,96c0,23.637,12.89,44.307,32,55.391v92.387l128,64v52.832
- c-19.11,11.084-32,31.754-32,55.391c0,35.29,28.71,64,64,64s64-28.71,64-64c0-23.637-12.89-44.307-32-55.391v-52.832l128-64v-92.387
- C435.11,140.307,448,119.637,448,96z M128,64c17.673,0,32,14.327,32,32s-14.327,32-32,32s-32-14.327-32-32S110.327,64,128,64z
- M256,448c-17.673,0-32-14.327-32-32s14.327-32,32-32s32,14.327,32,32S273.673,448,256,448z M384,128c-17.673,0-32-14.327-32-32
- s14.327-32,32-32s32,14.327,32,32S401.673,128,384,128z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/no-smoking.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/no-smoking.svg
deleted file mode 100644
index 3cd5697e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/no-smoking.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <rect x="360" y="256" class="st0" width="16" height="48"/>
- <polygon class="st0" points="112,304 249.6,304 201.6,256 112,256 "/>
- <path class="st0" d="M364.5,60.1c-0.4-0.2-0.7-0.4-1-0.6c-10.9-6-22.5-10.7-34.4-14.8c-1.8-0.6-3.6-1.2-5.4-1.8
- C302.3,36.1,279.6,32,256,32C132.3,32,32,132.3,32,256c0,84.3,46.6,157.6,115.4,195.8c0.4,0.2,0.7,0.5,1.1,0.7
- c10.9,6,22.5,10.7,34.4,14.8c1.8,0.6,3.6,1.2,5.4,1.8c21.4,6.8,44,10.9,67.7,10.9c123.7,0,224-100.3,224-224
- C480,171.7,433.4,98.3,364.5,60.1z M256,426.4c-9.3,0-18.4-0.9-27.2-2.4c-9.8-1.6-19.3-4.1-28.5-7.3c-1.9-0.6-3.8-1.2-5.6-1.9
- c-6.5-2.5-12.9-5.3-19-8.6c-53.6-28.7-90.1-85.2-90.1-150.3c0-37.2,12.4-71.4,32.7-99.4l237.2,237.2
- C327.4,414,293.2,426.4,256,426.4z M393.8,355.4L156.6,118.2c28-20.2,62.1-32.6,99.4-32.6c9.3,0,18.3,0.9,27.2,2.4
- c9.8,1.6,19.3,4.1,28.5,7.3c1.8,0.6,3.7,1.2,5.6,1.9c6.2,2.4,12.2,5,18,8.1c54.2,28.5,91.2,85.3,91.2,150.8
- C426.4,293.3,414,327.4,393.8,355.4z"/>
- <polygon class="st0" points="352,298 352,256 310,256 "/>
- <rect x="384" y="256" class="st0" width="16" height="48"/>
- <path class="st0" d="M360.1,212.7c-8.8-4.1-22-5.7-45.6-5.7c-1.2,0-2.4,0-3.6,0c-12.7,0.1-15.9-0.1-20-6.1
- c-2.8-4.2-1-14.8,3.7-21.9c1.6-2.4,1.8-5.6,0.4-8.2c-1.4-2.6-4.1-4.2-7-4.3c-0.1,0-9.4-0.1-18.3-3.9c-10.6-4.5-15.6-12.1-15.6-23.1
- c0-25.8,21.8-27.7,22.8-27.7v-16c-12,0-38.8,11-38.8,43.7c0,17.5,9,31,25.7,38c4.2,1.7,8.4,2.9,12,3.6c-3.3,9.8-3.6,20.9,1.7,28.7
- c9,13.3,20.3,13.2,33.3,13.1c1.1,0,2.3,0,3.5,0c26.3,0,34.6,2.3,38.9,4.3c5.7,2.6,6.8,11.5,6.6,19.7c0,0.7,0,0.4,0,1h16
- c0-0.4,0-0.4,0-1C375.8,239.8,376.1,220.1,360.1,212.7z"/>
- <path class="st0" d="M400,248c0-25.7-3-43.2-9.1-53.6C382.3,180,368.5,172,352,172h-17.4c2.9-8.3,5.4-19.8,3.5-30.9
- c-3.2-18.8-19.1-30-43.1-30v16c21,0,26.1,9.1,27.4,16.7c2.5,14.5-6.8,32.1-6.9,32.3c-1.4,2.5-1.3,5.5,0.1,7.9
- c1.4,2.4,4.1,3.9,6.9,3.9H352c10.9,0,19.4,4.9,25.1,14.6c3.1,5.3,6.9,17.5,6.9,45.4H400z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/nuclear.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/nuclear.svg
deleted file mode 100644
index ef31f138..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/nuclear.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <circle cx="256" cy="272" r="48"/>
- <circle cx="256" cy="272" r="48"/>
- </g>
- <g>
- <path d="M480,272H320c0,23.9-13.1,44.7-32.6,55.7L365.6,464C433.1,425.4,480,355.3,480,272z"/>
- <path d="M256,208c11.7,0,22.7,3.2,32.1,8.7l80.6-138.3C335.6,59.1,297.1,48,256,48c-41.2,0-79.9,11.2-113.1,30.6l79.8,138.8
- C232.4,211.4,243.8,208,256,208z"/>
- <path d="M192,272H32c0,83.3,46.9,153.4,114.4,192l78.2-136.3C205.1,316.7,192,295.9,192,272z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/outlet.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/outlet.svg
deleted file mode 100644
index 990f64d5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/outlet.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M369.541,32H142.359C81.521,32,32,82.574,32,144.604v222.79C32,429.426,81.521,480,142.359,480h227.182
- C430.479,480,480,429.426,480,367.395v-222.79C480,82.574,430.479,32,369.541,32z M175,250.954v0.67
- c0,10.882-9.09,20.376-19.875,20.376h-23.27C121.073,272,112,262.506,112,251.624v-0.67V149.512v-1.351
- c1-10.768,9.193-20.161,19.855-20.161h23.27c10.886,0,19.875,9.847,19.875,20.831V250.954z M297,395.74v2.68
- c0,11.439-8.872,17.58-20.1,17.58H256h-20.898C223.872,416,215,407.859,215,396.42v-0.68v-28.637
- c0-23.33,18.118-42.287,40.999-42.287c22.883,0,41.001,18.957,41.001,42.287V395.74z M400,250.954v0.67
- c0,10.882-9.071,20.376-19.855,20.376h-24.27C345.093,272,336,262.506,336,251.624v-0.67V149.512v-1.351
- c1-10.768,9.215-20.161,19.875-20.161h24.27c10.784,0,19.855,9.847,19.855,20.831V250.954z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbrush.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbrush.svg
deleted file mode 100644
index 597f84ae..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbrush.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M149.515,283.349c-51.921,0-83.939,45.661-83.939,95.085c0,22.691-10.071,39.153-33.575,48.104
- c17.907,34.678,87.777,41.157,117.515,35.797c35.642-6.426,80.077-24.873,90.654-76.969
- C252.48,324.739,201.434,283.349,149.515,283.349z"/>
- <path d="M467.638,60.356c-12.955-12.948-29.964-17.292-44.92-5.35L247.598,209.1c-8.648-2.371-16.525-1.869-22.909,2.346
- L165.896,260.4c-1.611,1.611-1.545,4.304,0.066,5.914c0.499,0.501,1.064,0.79,1.697,0.98c0.642,0.034,1.264,0.059,1.899,0.103
- c0.019-0.002,0.036-0.01,0.054-0.014c47.938,3.432,91.034,36.754,89.3,89.506c-0.016,0.505-0.029,1.007-0.054,1.516
- c0.123,0.848,0.5,1.664,1.149,2.315c1.595,1.593,4.168,1.605,5.781,0.044c0.018-0.018,0.037-0.027,0.055-0.044
- c0.063-0.063,0.106-0.137,0.164-0.2l50.457-57.342c4.216-6.374,4.72-14.24,2.355-22.875l154.169-175.047
- C484.939,90.308,480.592,73.308,467.638,60.356z"/>
- <polygon points="165.887,260.409 165.896,260.4 165.888,260.407 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbucket.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbucket.svg
deleted file mode 100644
index 046eea6f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paintbucket.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M128,64l39.667,72.102L16,288l197.604,192l163.328-160l58.33-12.307L160,32L128,64z M325.131,288H104.857L215,177.863
- L325.131,288z"/>
- <path d="M435.262,307.693c0,0-60.734,66.179-60.732,99.207c0,33.028,27.192,59.803,60.731,59.801
- c33.548,0.002,60.74-26.772,60.739-59.801C496.001,373.872,435.262,307.693,435.262,307.693z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paper-airplane.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paper-airplane.svg
deleted file mode 100644
index 47c1973f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paper-airplane.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M32,272l128,48l16,160l80-112l112,112L480,32L32,272z M350.7,417.4L256,320l128-176L192,297.8l-82.6-31
- l322-172.5L350.7,417.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paperclip.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paperclip.svg
deleted file mode 100644
index ee1bd36f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/paperclip.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M324.6,154.9c-6.3-0.1-11.4,5.1-11.4,11.6L313,361.3c-0.1,43.8-29.7,63.4-57.2,63.2c-27.5-0.3-57.1-20.4-57-64.1
- c0-33.5,0.2-167.7,0.3-234.8c0-15.4,6-27.4,16.8-33.7c10.6-6.2,24.4-6.1,35,0.3c10.8,6.5,16.7,18.6,16.7,34l-0.3,224.5
- c0,7.3-1.7,13.3-4.7,17.1c-1.9,2.4-4.4,3.8-6.9,3.8c-5.6-0.1-11.4-7.3-11.3-20.8c0,0,0.2-166.3,0.3-172.7c0-6.5-5.1-11.8-11.4-11.8
- c-6.3,0-11.4,5.2-11.4,11.7l-0.3,172.7c0,29,17.2,44.3,34.2,44.5c9.4,0.1,18.3-4.4,24.6-12.4c6.3-8,9.7-19,9.7-31.8l0.3-224.5
- c0-23.8-10.2-43.6-28.1-54.3c-17.5-10.6-40.3-10.8-57.9-0.5c-17.9,10.5-28.2,30.1-28.3,53.9c-0.1,67-0.2,201.2-0.3,234.8
- c-0.1,57.2,40.1,87.4,79.8,87.8c20.5,0.2,41.1-7.7,56.3-23.1c14.2-14.5,23.7-35.7,23.7-63.4l0.1-194.9
- C336,160.2,330.9,154.9,324.6,154.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pause.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pause.svg
deleted file mode 100644
index dd8b47dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pause.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M224,435.8V76.1c0-6.7-5.4-12.1-12.2-12.1h-71.6c-6.8,0-12.2,5.4-12.2,12.1v359.7c0,6.7,5.4,12.2,12.2,12.2h71.6
- C218.6,448,224,442.6,224,435.8z"/>
- <path d="M371.8,64h-71.6c-6.7,0-12.2,5.4-12.2,12.1v359.7c0,6.7,5.4,12.2,12.2,12.2h71.6c6.7,0,12.2-5.4,12.2-12.2V76.1
- C384,69.4,378.6,64,371.8,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-add.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-add.svg
deleted file mode 100644
index 2e1520ea..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-add.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="429,328 429,277 480,277 480,235 429,235 429,184 387,184 387,235 336,235 336,277 387,277 387,328 "/>
- <path d="M416,448c0,0,0-26.4-2.2-40.2c-1.8-10.9-16.9-25.3-81.1-48.9c-63.2-23.2-59.3-11.9-59.3-54.6c0-27.7,14.1-11.6,23.1-64.2
- c3.5-20.7,6.3-6.9,13.9-40.1c4-17.4-2.7-18.7-1.9-27c0.8-8.3,1.6-15.7,3.1-32.7C313.4,119.3,293.9,64,224,64
- c-69.9,0-89.4,55.3-87.5,76.4c1.5,16.9,2.3,24.4,3.1,32.7c0.8,8.3-5.9,9.6-1.9,27c7.6,33.1,10.4,19.3,13.9,40.1
- c9,52.6,23.1,36.5,23.1,64.2c0,42.8,3.9,31.5-59.3,54.6c-64.2,23.5-79.4,38-81.1,48.9C32,421.6,32,448,32,448h192H416z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-stalker.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-stalker.svg
deleted file mode 100644
index c4606769..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person-stalker.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M425.3,324.8c-41.4-15.7-38.9-9.4-38.9-38.5c0-18.8,9.3-11.9,15.2-47.7c2.3-14.1,4.2-4.7,9.1-27.3
- c2.6-11.8-1.8-12.7-1.2-18.3c0.5-5.6,1-10.7,2-22.2c1.2-14.4-11.6-52-57.4-52c-45.8,0-58.6,37.6-57.4,52c0.9,11.6,1.5,16.6,2,22.2
- c0.5,5.6-3.8,6.5-1.2,18.3c4.9,22.6,6.8,13.1,9.1,27.3c5.9,35.8,15.1,29,15.1,47.7c0,13.4,3.1,19-14.9,27.5
- c5.4,1.9,11.7,4.2,19.3,7.1c54.4,20.7,53.1,40.8,54.5,50.3c1,6.5,1.5,58.3,1.7,76.8H480c0,0,0-80.5-1.5-89.9
- C477.4,350.7,467.5,340.9,425.3,324.8z"/>
- <path d="M357,448c0,0,0-14.1-0.2-30.4c-0.2-18.6-0.7-40-1.7-46.4c-1.5-9.5-14.3-22.2-68.6-42.9c-7.5-2.8-13.8-5.1-19.3-7.1
- c-33.3-11.8-30.9-15.7-30.9-48c0-24.3,12-8.5,19.6-54.6c3-18.2,5.4-6.1,11.7-35.2c3.4-15.2-2.3-16.4-1.6-23.7
- c0.7-7.3,1.4-13.8,2.6-28.7c1.6-18.5-14.9-67.1-74.1-67.1c-59.2,0-75.6,48.5-74.1,67.1c1.2,14.9,1.9,21.4,2.7,28.7
- c0.7,7.3-5,8.4-1.6,23.7c6.4,29.1,8.8,17,11.8,35.2c7.6,46.1,19.5,30.3,19.5,54.6c0,37.6,3.3,34.8-50.2,55.1
- c-54.3,20.7-67.1,33.4-68.6,42.9C32,383.3,32,448,32,448h162.5H357z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person.svg
deleted file mode 100644
index aac76d4c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/person.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M448,448c0,0,0-26.4-2.2-40.2c-1.8-10.9-16.9-25.3-81.1-48.9c-63.2-23.2-59.3-11.9-59.3-54.6c0-27.7,14.1-11.6,23.1-64.2
- c3.5-20.7,6.3-6.9,13.9-40.1c4-17.4-2.7-18.7-1.9-27c0.8-8.3,1.6-15.7,3.1-32.7C345.4,119.3,325.9,64,256,64
- c-69.9,0-89.4,55.3-87.5,76.4c1.5,16.9,2.3,24.4,3.1,32.7c0.8,8.3-5.9,9.6-1.9,27c7.6,33.1,10.4,19.3,13.9,40.1
- c9,52.6,23.1,36.5,23.1,64.2c0,42.8,3.9,31.5-59.3,54.6c-64.2,23.5-79.4,38-81.1,48.9C64,421.6,64,448,64,448h192H448z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pie-graph.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pie-graph.svg
deleted file mode 100644
index 5054884e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pie-graph.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M32.6,256h32H256V64.6v-32c-5-0.4-10.6-0.6-16-0.6C125.1,32,32,125.1,32,240C32,245.4,32.2,251,32.6,256z"/>
- <path d="M109.8,402.2C147.9,449.6,206.4,480,272,480c114.9,0,208-93.1,208-208c0-65.6-30.4-124.1-77.8-162.2
- C370.5,84.3,331,67.9,288,64.6V288H64.6C67.9,331,84.3,370.5,109.8,402.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pin.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pin.svg
deleted file mode 100644
index 7bdc8775..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pin.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M331.8,228C331.8,228,331.8,228,331.8,228c-1.2-0.5-2.4-1-3.5-1.7c-7-4-12.2-10.9-13.9-19.2L295.9,89.4l-0.2-5.8
- c0-7.1,4.1-10.2,10-13l0,0c0.7-0.3,1.4-0.6,2.1-0.9c7.2-3.4,12.1-7.8,12.1-16.3c0-20.1-6.5-21.4-18.2-21.4h-91.3
- c-11.7,0-18.2,1.2-18.2,21.4c0,8.5,4.9,12.9,12.1,16.3c0.7,0.3,1.4,0.5,2.1,0.9c0,0,0,0,0,0c5.9,2.9,10,6,10,13l-0.2,5.8
- l-18.5,117.7c-1.7,8.3-6.9,15.2-13.9,19.2c-1.1,0.7-2.3,1.2-3.5,1.7c0,0,0,0,0,0c-19.7,10.2-36.2,30.8-36.2,54.7
- c0,15.9,3.5,21.3,15.2,21.3H240l12,176h8l12-176h80.8c11.7,0,15.2-4.7,15.2-21.3C368,258.8,351.5,238.2,331.8,228z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pinpoint.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pinpoint.svg
deleted file mode 100644
index d18b9bbd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pinpoint.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,132.3,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224C480,132.3,379.7,32,256,32z
- M391.8,391.8c-32.5,32.5-74.6,51.9-119.8,55.6L264,384h-16l-7.9,63.3c-45.3-3.7-87.4-23.1-119.8-55.6
- c-32.5-32.5-51.9-74.6-55.6-119.8L128,264v-16l-63.3-7.9c3.7-45.3,23.1-87.4,55.6-119.8c32.5-32.5,74.6-51.9,119.8-55.6L248,128h16
- l7.9-63.3c45.3,3.7,87.4,23.1,119.8,55.6c32.5,32.5,51.9,74.6,55.6,119.8L384,248v16l63.3,7.9C443.6,317.2,424.2,359.3,391.8,391.8z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pizza.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pizza.svg
deleted file mode 100644
index 4595a207..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pizza.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M394.619,130.445c-42.658-18.924-89.266-28.472-138.649-28.425c-49.373-0.047-99.27,10.262-138.641,27.979
- c-7.396,3.312-14.004,8.957-9.296,19.479S255.941,480,255.941,480l147.621-329.874C406.452,143.25,404.318,134.748,394.619,130.445
- z M191.983,192.015c-17.67,0-31.995-14.323-31.995-31.993c0-17.669,14.325-31.992,31.995-31.992
- c17.671,0,31.996,14.323,31.996,31.992C223.979,177.691,209.654,192.015,191.983,192.015z M255.975,338.981
- c-17.671,0-31.995-14.323-31.995-31.993s14.324-31.992,31.995-31.992c17.67,0,31.995,14.322,31.995,31.992
- S273.645,338.981,255.975,338.981z M319.965,224.007c-17.67,0-31.995-14.322-31.995-31.992s14.325-31.993,31.995-31.993
- c17.671,0,31.996,14.323,31.996,31.993S337.636,224.007,319.965,224.007z"/>
- <path d="M421.79,66c-47.808-20.603-106.867-33.977-165.811-34c-58.931,0-116.944,12.136-165.82,33.446
- C85.83,67.334,80,71.016,80,79.227c0,2.523,0.907,4.922,0.907,4.922l7.98,19.194c2.531,4.865,7.944,8.18,13.798,8.18
- c1.645,0,3.936-0.331,6.65-1.476c44.9-18.929,94.471-29.588,146.644-29.564c52.175-0.023,105.63,11.64,146.634,29.561
- c3.296,1.44,5.173,1.472,6.663,1.472c6.009,0,11.158-3.274,13.727-8.053l8.04-19.342c0.577-1.558,0.957-3.287,0.957-4.768
- C432,72,427.614,68.51,421.79,66z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plane.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plane.svg
deleted file mode 100644
index 6f577479..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plane.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M281.7,311.9c0.4-6.9,8.3-4.5,8.3-4.5l62,12.6l128,48.7c0-24-3.8-26.5-9.4-30.7L288,207c0,0-4.9-60-4.9-112.9
- c0-24.5-11.8-78.1-27.1-78.1s-27.1,54.4-27.1,78.1c0,50.2-4.9,112.9-4.9,112.9L41.4,338c-7.1,5-9.4,7.7-9.4,30.7L160,320l61.9-12.6
- c0,0,7.9-2.4,8.3,4.5c0.4,6.9-1.2,69.1,5.9,102.1c0.9,4.4-2.5,4.7-4.8,7.4l-51.9,32.8c-1.7,1.9-2.5,7.3-2.5,7.3l-1,18.5l68-16l12,32
- l12-32l68,16l-1-18.5c0.1,0-0.7-5.4-2.4-7.3l-51.9-32.8c-2.3-2.7-5.7-3-4.8-7.4C282.7,381,281.3,318.8,281.7,311.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/planet.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/planet.svg
deleted file mode 100644
index 8a9dfad0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/planet.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M96.298,265.705C101.315,349.55,170.887,416,255.988,416c37.957,0,72.818-13.227,100.25-35.311
- C317.23,369.554,274,353.922,229.562,334.617C180.731,313.404,134.957,289.677,96.298,265.705z"/>
- <path d="M107.381,196.629c39.911,27.11,92.07,55.13,147.679,79.287c43.591,18.938,87.113,34.555,125.859,45.164
- c6.496,1.779,12.834,3.406,18.988,4.883c1.685-3.462,3.249-6.994,4.688-10.591c7.341-18.358,11.386-38.393,11.386-59.372
- c0-3.26-0.109-6.493-0.301-9.705C410.661,162.45,341.09,96,255.988,96c-37.956,0-72.817,13.227-100.248,35.311
- c-18.296,14.729-33.284,33.398-43.67,54.726C110.383,189.499,108.819,193.032,107.381,196.629z"/>
- <path d="M429.667,284.531c-1.256,11.562-2.377,13.627-5.891,24.695c16.878,12.039,31.032,23.706,41.137,33.938
- c3.285,3.328,5.875,6.225,7.912,8.702c-1.684,0.084-3.557,0.133-5.631,0.133c-21.886,0-54.026-5.5-90.501-15.488
- c-39.467-10.806-83.73-26.685-128.008-45.92c-58.931-25.6-114.158-55.541-155.51-84.307c-19.081-13.275-35.027-26.226-46.113-37.45
- c-3.285-3.328-5.875-6.225-7.912-8.702c1.683-0.084,3.556-0.133,5.632-0.133c15.308,0,35.637,2.694,58.952,7.729
- c5.825-10.004,6.979-12.701,14.663-21.409C92.663,137,66.625,130.522,44.784,128c-24.403-2.818-40.34,5.521-43.984,17.14
- C-10.274,180.457,95,258.718,235.936,319.942C330.498,361.022,417.104,384,467.194,384c24.565,0,40.338-5.521,43.982-17.141
- C517.516,346.643,486.965,320,429.667,284.531z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/play.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/play.svg
deleted file mode 100644
index c7817bdd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/play.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M405.2,232.9L126.8,67.2c-3.4-2-6.9-3.2-10.9-3.2c-10.9,0-19.8,9-19.8,20H96v344h0.1c0,11,8.9,20,19.8,20
- c4.1,0,7.5-1.4,11.2-3.4l278.1-165.5c6.6-5.5,10.8-13.8,10.8-23.1C416,246.7,411.8,238.5,405.2,232.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/playstation.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/playstation.svg
deleted file mode 100644
index f29f851f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/playstation.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M399.8,203c-0.8-17.1-3.3-34.5-10.8-50.1c-4.1-8.6-9.7-16.5-16.5-23.2c-6.3-6.4-13.6-11.7-21.3-16.3
- c-17.1-10.2-37.5-17-84.4-31S192,64,192,64v358.3l79.9,25.7c0,0,0.1-198.8,0.1-299.5v-3.8c0-9.3,7.5-16.8,16.1-16.8h0.5
- c8.5,0,15.5,7.5,15.5,16.8v2.2v131.1c11,5.3,29.2,9.3,41.8,9.1c8.3,0.2,16.7-1.7,24-5.7c7.6-4.1,13.9-10.4,18.4-17.8
- c5.1-8.3,8.2-17.8,9.9-27.3C400.1,225.5,400.2,214.2,399.8,203z"/>
- <path class="st0" d="M86.7,357.8c27.4-9.8,89.3-29.5,89.3-29.5v-47.2c0,0-76.5,24.8-111.3,37.1c-8.6,3.1-17.3,5.9-25.7,9.5
- c-9.8,4.1-19.4,8.7-28.1,14.8c-3.8,2.6-7.2,5.9-9.2,10.1c-2,4.2-2.2,9.2-0.5,13.6c2,5.1,5.8,9.3,10.1,12.6
- c7.8,5.9,17.1,9.5,26.4,12.2c28.4,9.4,58.4,14,88.4,13.3c14.5-0.2,36-1.9,50-4.4v-42c0,0-11,2.5-41.3,12.5c-4.6,1.5-9.2,3.3-14,4.3
- c-7.1,1.6-14.4,2.1-21.6,2.2c-6.5-0.3-13.2-0.7-19.3-3.1c-2.2-1-4.6-2.2-5.5-4.6c-0.8-2,0.3-4,1.7-5.4
- C78.9,360.9,82.9,359.3,86.7,357.8z"/>
- <path class="st0" d="M512,345.9c-0.1-6-3.7-11.2-7.9-15c-7.1-6.3-15.9-10.3-24.7-13.5c-5.5-1.9-9.3-3.3-14.7-5
- c-25.2-8.2-51.9-11.2-78.3-11.3c-8,0.3-23.1,0.5-31,1.4c-21.9,2.5-67.3,15.4-67.3,15.4v48.8c0,0,67.5-21.6,96.5-31.8
- c9.7-3.3,20.1-4.6,30.3-4.6c6.5,0.2,13.2,0.7,19.4,3.1c2.2,0.9,4.5,2.2,5.5,4.5c0.9,2.6-0.9,5-2.9,6.5c-4.7,3.8-10.7,5.3-16.2,7.4
- C379.7,366.3,288,396.5,288,396.5v47c0,0,117.2-39.6,170.8-58.8c8.9-3.3,17.9-6.1,26.4-10.4c7.9-4,15.8-8.6,21.8-15.3
- C510.1,355.4,512,351,512,345.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-circled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-circled.svg
deleted file mode 100644
index 4550c4b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-circled.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32C132.3,32,32,132.3,32,256s100.3,224,224,224s224-100.3,224-224S379.7,32,256,32z M384,272H272v112h-32V272H128v-32
- h112V128h32v112h112V272z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-round.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-round.svg
deleted file mode 100644
index b2d86e50..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus-round.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M417.4,224H288V94.6c0-16.9-14.3-30.6-32-30.6c-17.7,0-32,13.7-32,30.6V224H94.6C77.7,224,64,238.3,64,256
- c0,17.7,13.7,32,30.6,32H224v129.4c0,16.9,14.3,30.6,32,30.6c17.7,0,32-13.7,32-30.6V288h129.4c16.9,0,30.6-14.3,30.6-32
- C448,238.3,434.3,224,417.4,224z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus.svg
deleted file mode 100644
index c4b273c4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/plus.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon points="448,224 288,224 288,64 224,64 224,224 64,224 64,288 224,288 224,448 288,448 288,288 448,288 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/podium.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/podium.svg
deleted file mode 100644
index 482b3d75..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/podium.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <rect x="32" y="256" width="128" height="192"/>
- <rect x="192" y="160" width="128" height="288"/>
- <rect x="352" y="320" width="128" height="128"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pound.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pound.svg
deleted file mode 100644
index 14138467..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pound.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M125.2,352.3H32v-54.6h101.2l13.1-83.3H47v-54.6h107.2L176,32h63.9l-21.8,127.7h105.6L345.5,32h63.1l-21.8,127.7H480v54.6
- H378.1l-12.3,83.3H465v54.6H358.5L336,480h-63.1l21.8-127.7H188.3L166.5,480h-63.1L125.2,352.3z M209.4,214.3L197,297.7h105.6
- l12.3-83.3H209.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/power.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/power.svg
deleted file mode 100644
index 636b2876..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/power.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,256c-17.7,0-32-14.3-32-32V64c0-17.7,14.3-32,32-32s32,14.3,32,32v160C288,241.7,273.7,256,256,256z"/>
- <path d="M379,68.8L379,68.8c-5-3-10.8-4.8-17-4.8c-17.7,0-32,14.3-32,32c0,6.2,1.8,12,4.8,16.9c2,3.2,4.6,6.1,7.6,8.4
- c1.2,0.9,2.4,1.7,3.7,2.5c8.1,5.6,15.8,11.9,23,19.1C399.4,173.1,416,213.3,416,256c0,42.7-16.6,82.9-46.9,113.1
- C338.9,399.4,298.7,416,256,416c-42.7,0-82.9-16.6-113.1-46.9C112.6,338.9,96,298.7,96,256c0-42.7,16.6-82.9,46.9-113.1
- c7.1-7.1,14.8-13.5,22.9-19c1.4-0.8,2.6-1.6,3.9-2.6c3-2.3,5.5-5.1,7.5-8.3c3.1-4.9,4.8-10.7,4.8-16.9c0-17.7-14.3-32-32-32
- c-6.2,0-12,1.8-16.9,4.8l-0.1-0.1C72.2,108.8,32,177.7,32,256c0,123.7,100.3,224,224,224c123.7,0,224-100.3,224-224
- C480,177.7,439.8,108.8,379,68.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetag.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetag.svg
deleted file mode 100644
index 22335f43..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetag.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M471,261.4L471,261.4C471,261.4,471,261.4,471,261.4L260.9,49.8c0,0,0,0,0,0l-1.5-1.5c0,0-0.4,0-0.4,0
- c-8.3-7.9-17.9-12-29.9-12.3v0l-99.7-3.7l-4.4-0.2c-11.2,0.2-22.2,4.5-30.7,13.1L45.1,94.3c-9,9-13.1,20.9-13.1,32.7c0,0,0,0,0,0.1
- l0.3,4.2l6.7,97.3c0,0.1,0,0.2,0,0.2v1.9c0,0,0,0,0,0c1,8.7,4.5,17.3,10.4,24.4l5.5,5.4l206.3,208.8l3.1,3.1
- c11.9,10.5,30,10,41.3-1.4l165.4-166.6C482.8,292.6,483,273.3,471,261.4z M144,192c-26.5,0-48-21.5-48-48s21.5-48,48-48
- s48,21.5,48,48S170.5,192,144,192z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetags.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetags.svg
deleted file mode 100644
index e62d8c41..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pricetags.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M472,239.2L472,239.2C472,239.2,471.9,239.2,472,239.2L282.1,48.1c0,0,0,0,0,0l-1.4-1.4c0,0-0.5,0-0.5,0
- c-7.5-7.2-16.1-10.9-27.1-11.1v0l-89.9-3.3l-3.9-0.1c-10.1,0.1-20,4.1-27.7,11.8l-27.1,27.2c7.4-6.6,16.6-10,26-10.1l3.8,0.1
- l89.8,3.3v0c11,0.2,19.7,3.9,27.2,11.1c0,0,0.4,0,0.5,0l1.4,1.4c0,0,0,0,0,0L443,268.1c0,0,0,0,0,0v0c10,10.8,10.7,28.2,0,38.9
- l29-28.9C482.6,267.4,482,250,472,239.2z"/>
- <path d="M428,282.5c0,0,0.3,0,0.3,0L238.6,91.4c0,0,0,0,0,0l-1.3-1.4c0,0-0.3,0-0.3,0c-7.5-7.2-15.9-10.9-26.9-11.1v0l-90.1-3.3
- l-4-0.1c-9.2,0.1-18.2,3.4-25.6,9.8c-0.3,0.3-0.7,0.6-1,0.9c-0.4,0.4-0.8,0.8-1.2,1.2l-44.3,44.5c-8.1,8.1-11.9,18.9-11.9,29.5
- c0,0,0,0,0,0.1l0.1,3.8l5.9,87.9c0,0.1,0,0.1,0,0.2v1.7c0,0,0,0,0,0c1,7.9,4.2,15.6,9.6,22l5.1,4.9L239,470.4l2.8,2.8
- c10.7,9.4,27.1,9,37.3-1.3l13.1-13.2c0.5-0.4,0.9-0.8,1.4-1.3l26.9-27c-0.2,0.1-0.3,0.2-0.5,0.4l108.3-109.3
- C438.9,310.8,439,293.3,428,282.5L428,282.5z M110.6,139.5c6.6-4,14.3-6.3,22.6-6.3c23.9,0,43.4,19.4,43.4,43.4
- c0,8.3-2.3,16-6.3,22.6c-7.6,12.5-21.3,20.8-37,20.8c-23.9,0-43.4-19.4-43.4-43.4C89.8,160.8,98.1,147.1,110.6,139.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/printer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/printer.svg
deleted file mode 100644
index 4f270765..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/printer.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M423.8,128H384V64H128v64H88.2C60.3,128,32,144.9,32,182.6v123.8c0,38,28.3,61.6,56.2,61.6c0,0,30.4,0,39.8,0v112h5h11h224
- h8h8V368c10.3,0,39.8,0,39.8,0c27.9,0,56.2-22.6,56.2-53.6V182.6C480,146.9,451.8,128,423.8,128z M368,464H144V288h224V464z
- M368,128H144V80h224V128z M416,192h-17v-16h17V192z"/>
- <rect x="160" y="320" width="192" height="16"/>
- <rect x="160" y="368" width="192" height="16"/>
- <rect x="160" y="416" width="192" height="16"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pull-request.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pull-request.svg
deleted file mode 100644
index c311934e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/pull-request.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M128,64c-35.29,0-64,28.71-64,64c0,23.637,12.89,44.307,32,55.391v177.219C76.89,371.693,64,392.363,64,416
- c0,35.29,28.71,64,64,64s64-28.71,64-64c0-23.637-12.89-44.307-32-55.391V183.391c19.11-11.084,32-31.754,32-55.391
- C192,92.71,163.29,64,128,64z M128,448c-17.673,0-32-14.327-32-32s14.327-32,32-32s32,14.327,32,32S145.673,448,128,448z M128,160
- c-17.673,0-32-14.327-32-32s14.327-32,32-32s32,14.327,32,32S145.673,160,128,160z"/>
- <path d="M415,360.034V204.989c0-33.987-10.49-61.002-31.18-80.294c-22.111-20.618-54.314-30.388-95.82-29.106V32l-96,96l96,96v-64
- c26.5,0,42.67,2.642,52.175,11.504c7.183,6.698,10.825,17.964,10.825,33.485v156.196c-18.562,11.217-31,31.589-31,54.814
- c0,35.29,28.71,64,64,64s64-28.71,64-64C448,391.951,434.662,370.969,415,360.034z M384,448c-17.673,0-32-14.327-32-32
- s14.327-32,32-32s32,14.327,32,32S401.673,448,384,448z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/qr-scanner.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/qr-scanner.svg
deleted file mode 100644
index 82a6cd13..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/qr-scanner.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M96,124.171c0-6.938,5.232-12.171,12.171-12.171H176V64h-66.829C75.717,64,48,90.717,48,124.171V192h48V124.171z"/>
- <path d="M403.579,64H336v48h67.219c6.938,0,12.781,5.232,12.781,12.171V192h48v-67.829C464,90.717,437.033,64,403.579,64z"/>
- <path d="M416,386.829c0,6.938-5.232,12.171-12.171,12.171H336v49h67.829C437.283,448,464,420.283,464,386.829V320h-48V386.829z"/>
- <path d="M108.171,399C101.232,399,96,393.768,96,386.829V320H48v66.829C48,420.283,75.717,448,109.171,448H176v-49H108.171z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/quote.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/quote.svg
deleted file mode 100644
index 74b11a06..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/quote.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M192,64c-40.646,0-72.483,11.229-94.627,33.373C75.229,119.517,64,151.354,64,192v256h160V192h-96
- c0-23.056,4.922-39.666,14.627-49.373C152.334,132.922,168.944,128,192,128"/>
- </g>
- <g>
- <path d="M416,64c-40.646,0-72.483,11.229-94.627,33.373C299.229,119.517,288,151.354,288,192v256h160V192h-96
- c0-23.056,4.922-39.666,14.627-49.373C376.334,132.922,392.944,128,416,128"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/radio-waves.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/radio-waves.svg
deleted file mode 100644
index aad96c68..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/radio-waves.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="256" cy="256" r="64"/>
- <g>
- <path d="M144,256c0-36.9,18.553-69.208,46.314-87.034l-23.141-24.512c-6.26,4.608-12.18,9.833-17.684,15.663
- C125.314,185.729,112,219.781,112,256c0,36.219,13.314,70.271,37.49,95.883c5.504,5.829,11.424,11.055,17.684,15.662
- l23.141-24.511C162.553,325.208,144,292.9,144,256z"/>
- <path d="M368,256c0,36.9-18.553,69.208-46.314,87.034l23.141,24.511c6.26-4.607,12.18-9.833,17.684-15.662
- C386.686,326.271,400,292.219,400,256c0-36.219-13.314-70.271-37.49-95.882c-5.504-5.83-11.424-11.055-17.684-15.663
- l-23.141,24.512C349.447,186.792,368,219.1,368,256z"/>
- <path d="M64,256c0-55.578,25.251-104.907,64.263-135.817L105.433,96c-5.999,5-11.739,10.396-17.197,16.178
- c-17.622,18.669-31.462,40.417-41.134,64.641C37.081,201.917,32,228.556,32,256c0,27.443,5.081,54.084,15.102,79.181
- c9.672,24.226,23.512,45.973,41.134,64.642c5.458,5.781,11.198,11.177,17.197,16.178l22.829-24.183
- C89.251,360.907,64,311.578,64,256z"/>
- <path d="M448,256c0,55.578-25.251,104.907-64.262,135.817l22.828,23.848c6-5.001,11.74-10.062,17.198-15.843
- c17.622-18.669,31.462-40.416,41.134-64.642C474.918,310.084,480,283.443,480,256c0-27.444-5.082-54.083-15.102-79.181
- c-9.672-24.225-23.512-45.972-41.134-64.641C418.307,106.396,412.566,101,406.566,96l-22.829,24.183
- C422.749,151.093,448,200.422,448,256z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/record.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/record.svg
deleted file mode 100644
index 44b9b41f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/record.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,464c114.9,0,208-93.1,208-208c0-114.9-93.1-208-208-208C141.1,48,48,141.1,48,256C48,370.9,141.1,464,256,464z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/refresh.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/refresh.svg
deleted file mode 100644
index c3f07c66..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/refresh.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M416,352l96-111.9h-64.7c-2.3-27.9-10.5-54-23.5-77.3c-27.4-49.2-75.8-85.1-133-95.6c-0.7-0.1-1.5-0.3-2.2-0.4
- c-0.5-0.1-0.9-0.2-1.4-0.2C277.1,64.9,266.6,64,256,64c-0.1,0-0.3,0-0.4,0c0,0,0,0,0,0c-90.9,0.2-167,63.6-186.7,148.6
- c0,0,0,0.1,0,0.1c-0.3,1.1-0.5,2.2-0.7,3.3c-0.1,0.5-0.2,0.9-0.3,1.4c-0.1,0.7-0.3,1.4-0.4,2.1c-0.2,0.9-0.3,1.7-0.5,2.6
- c-0.1,0.4-0.1,0.7-0.2,1.1c-0.2,1.2-0.4,2.4-0.6,3.6c0,0.1,0,0.1,0,0.2c-1,6.3-1.6,12.7-1.9,19.1c0,0.3,0,0.6,0,0.8
- c-0.1,1.4-0.1,2.7-0.2,4.1c0,1.6-0.1,3.3-0.1,5c0,1.7,0,3.3,0.1,5c0,1.4,0.1,2.7,0.2,4.1c0,0.3,0,0.6,0,0.9c0.3,6.5,1,12.9,1.9,19.1
- c0,0.1,0,0.1,0,0.2c0.2,1.2,0.4,2.4,0.6,3.6c0.1,0.4,0.1,0.7,0.2,1.1c0.2,0.9,0.3,1.8,0.5,2.6c0.1,0.7,0.3,1.4,0.4,2.1
- c0.1,0.5,0.2,1,0.3,1.4c0.2,1.1,0.5,2.2,0.7,3.2c0,0,0,0.1,0,0.1c19.7,85,96.1,148.4,187.1,148.6c42.9-0.1,83.1-14.2,116.9-40.7
- l7.5-5.9l-43.2-46.2l-6.2,4.6c-22.1,16.3-47.5,24.2-75,24.2c-70.6,0-128-57-128-128c0-71,57.4-128,128-128
- c66.4,0,122.8,46.6,129.5,112H312L416,352z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply-all.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply-all.svg
deleted file mode 100644
index 17286eeb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply-all.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M304.5,192v-80L152.7,255.8L304.5,390v-91.9c68,0,107.9,8.9,159.1,101.9C463.6,400,457.5,192,304.5,192z"/>
- <g>
- <polygon points="47.5,256 191.5,382.5 191.5,324 109.3,256 191.5,177.4 191.5,120.4 "/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply.svg
deleted file mode 100644
index 39e4e581..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/reply.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M448,400c0,0-36.8-208-224-208v-80L64,256l160,134.4v-92.3C325.6,298.1,395,307,448,400z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-a.svg
deleted file mode 100644
index 24d1e1b0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-a.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M352,32l-82.9,176.612c39.996,3.608,75.273,23.554,99.096,53.128L432,128L352,32z"/>
- <path d="M160,32l82.9,176.612c-39.996,3.608-75.273,23.554-99.096,53.128L80,128L160,32z"/>
- <polygon points="269.092,32 256,32 176,32 228.572,144 256,144 283.428,144 336,32 "/>
- <path d="M256,224c-70.692,0-128,57.308-128,128s57.308,128,128,128s128-57.308,128-128S326.692,224,256,224z M256,448
- c-53.02,0-96-42.98-96-96s42.98-96,96-96s96,42.98,96,96S309.02,448,256,448z"/>
- <path d="M256,264c-48.523,0-88,39.477-88,88s39.477,88,88,88s88-39.477,88-88S304.523,264,256,264z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-b.svg
deleted file mode 100644
index 9e7a4b63..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/ribbon-b.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M256,72c-48.523,0-88,39.477-88,88s39.477,88,88,88s88-39.477,88-88S304.523,72,256,72z"/>
- <path d="M256,32c-70.692,0-128,57.308-128,128s57.308,128,128,128s128-57.308,128-128S326.692,32,256,32z M256,256
- c-53.02,0-96-42.98-96-96s42.98-96,96-96s96,42.98,96,96S309.02,256,256,256z"/>
- </g>
- <g>
- <path d="M147.092,254.21L64,400h96l48,80l48-105.807l33.641-74.154C278.848,302.623,267.585,304,256,304
- C212.495,304,173.497,284.707,147.092,254.21z"/>
- <path d="M364.908,254.211c-15.077,17.412-34.26,31.172-56.043,39.774l-44.752,98.092L304,480l48-80h96L364.908,254.211z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad-outline.svg
deleted file mode 100644
index 86ae5761..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad-outline.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <g>
- <path d="M399.283,283.797c-5.1-16.379-14.22-29.995-33.802-37.263s-35.265-2.877-49.868,6.15
- c-7.615,4.707-10.029,14.019-4.214,22.123c2.049,2.854,5.019,4.717,8.376,5.963c5.059,1.876,10.584,1.678,14.965-1.036
- c4.778-2.957,10.644-6.526,19.607-3.199c9.01,3.343,11.103,9.839,12.752,15.161c1.551,4.952,5.62,8.724,10.693,10.606
- c3.357,1.246,6.816,1.774,10.236,0.938C396.895,301.056,401.944,292.333,399.283,283.797z"/>
- <path d="M196.549,252.685c-14.603-9.027-30.286-13.418-49.868-6.15s-28.702,20.884-33.802,37.263
- c-2.661,8.536,2.389,17.259,11.255,19.443c3.42,0.837,6.878,0.309,10.236-0.938c5.073-1.883,9.143-5.654,10.693-10.606
- c1.649-5.322,3.743-11.818,12.752-15.161c8.964-3.327,14.829,0.242,19.607,3.199c4.381,2.714,9.907,2.912,14.965,1.036
- c3.357-1.246,6.327-3.108,8.376-5.963C206.578,266.703,204.164,257.392,196.549,252.685z"/>
- </g>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M391.765,391.765
- C355.5,428.028,307.285,448,256,448s-99.5-19.972-135.765-56.235C83.972,355.5,64,307.285,64,256s19.972-99.5,56.235-135.765
- C156.5,83.972,204.715,64,256,64s99.5,19.972,135.765,56.235C428.028,156.5,448,204.715,448,256S428.028,355.5,391.765,391.765z"
- />
- </g>
- <path d="M349.119,359.176C348.013,357.59,321,320,256,320c-65.261,0-92.014,37.59-93.121,39.176
- c-5.057,7.247-3.283,17.221,3.963,22.278c2.789,1.946,5.982,2.881,9.143,2.881c5.052,0,10.024-2.388,13.135-6.845
- C189.296,377.239,208.02,352,256,352c48,0,66.703,25.239,66.879,25.49c3.11,4.457,8.081,6.845,13.134,6.845
- c3.161,0,6.354-0.935,9.144-2.881C352.402,376.396,354.177,366.423,349.119,359.176z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad.svg
deleted file mode 100644
index ca584516..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/sad.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M145.062,291.696
- c-1.551,4.952-5.62,8.724-10.693,10.606c-3.358,1.246-6.816,1.774-10.236,0.938c-8.866-2.185-13.916-10.907-11.255-19.443
- c5.101-16.379,14.22-29.995,33.802-37.263s35.265-2.877,49.868,6.15c7.615,4.707,10.029,14.019,4.214,22.123
- c-2.049,2.854-5.019,4.717-8.376,5.963c-5.059,1.876-10.584,1.678-14.965-1.036c-4.778-2.957-10.643-6.526-19.607-3.199
- C148.805,279.878,146.712,286.374,145.062,291.696z M345.156,381.454c-2.789,1.946-5.982,2.881-9.144,2.881
- c-5.053,0-10.023-2.388-13.134-6.845C322.703,377.239,304,352,256,352c-47.98,0-66.704,25.239-66.879,25.49
- c-3.111,4.457-8.083,6.845-13.135,6.845c-3.161,0-6.354-0.935-9.143-2.881c-7.246-5.058-9.021-15.031-3.963-22.278
- C163.986,357.59,190.739,320,256,320c65,0,92.013,37.59,93.119,39.176C354.177,366.423,352.402,376.396,345.156,381.454z
- M388.029,303.24c-3.42,0.837-6.879,0.309-10.236-0.938c-5.073-1.883-9.143-5.654-10.693-10.606
- c-1.649-5.322-3.742-11.818-12.752-15.161c-8.964-3.327-14.829,0.242-19.607,3.199c-4.381,2.714-9.906,2.912-14.965,1.036
- c-3.357-1.246-6.327-3.108-8.376-5.963c-5.815-8.104-3.401-17.416,4.214-22.123c14.604-9.027,30.286-13.418,49.868-6.15
- s28.702,20.884,33.802,37.263C401.944,292.333,396.895,301.056,388.029,303.24z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/scissors.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/scissors.svg
deleted file mode 100644
index 264e7c2b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/scissors.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M405.178,115.667c13.314-32.667,17.309-64-5.326-83.667L255.726,224l-16.976,23c0,0-27.627,40.011-37.28,58.667
- s-19.306,39.333-27.294,54c-7.01,12.871-10.438,15.221-14.322,11.548c-0.506-0.591-1.026-1.168-1.553-1.736
- c-0.037-0.047-0.073-0.09-0.11-0.138c-1.143-1.472-2.75-3.002-4.635-4.467C144.195,356.795,132.548,352,119.92,352
- C89.037,352,64,380.653,64,416s25.037,64,55.92,64c25.282,0,46.635-19.205,53.553-45.561l-0.004,0.043
- c0,0,13.355-41.482,32.661-71.482c19.306-30,49.596-43,49.596-43l31.954-32C287.68,288,391.863,148.334,405.178,115.667z
- M119.92,448c-15.418,0-27.918-14.353-27.918-32s12.5-32,27.918-32c15.419,0,27.918,14.353,27.918,32S135.339,448,119.92,448z
- M256,288c-8.836,0-16-7.163-16-16c0-8.836,7.164-16,16-16c8.837,0,16,7.164,16,16C272,280.837,264.837,288,256,288z"/>
- <path d="M207.28,265.255c9.18-14.114,17.671-26.43,18.304-27.346l0.143-0.208l0.15-0.203l16.976-23l0.038-0.052l0.039-0.052
- l2.941-3.918L111.896,32c-22.634,19.667-18.64,51-5.326,83.667C116.523,140.087,177.249,224.29,207.28,265.255z"/>
- <path d="M391.828,352c-12.628,0-24.275,4.795-33.637,12.874c-1.885,1.465-3.492,2.995-4.635,4.467
- c-0.037,0.048-0.072,0.091-0.109,0.138c-0.526,0.568-1.047,1.146-1.553,1.736c-3.884,3.673-7.312,1.323-14.322-11.548
- c-7.988-14.667-17.641-35.344-27.294-54c-1.77-3.421-4.146-7.561-6.843-12.038c-1.272,1.712-2.264,3.043-2.932,3.938l-0.688,0.924
- l-0.813,0.815l-28.688,28.729c10.433,6.855,24.565,18.276,35.306,34.965c19.305,30,32.66,71.482,32.66,71.482l-0.004-0.043
- C345.193,460.795,366.546,480,391.828,480C422.711,480,448,451.347,448,416S422.711,352,391.828,352z M391.828,448
- c-15.42,0-27.918-14.353-27.918-32s12.498-32,27.918-32c15.418,0,27.918,14.353,27.918,32S407.246,448,391.828,448z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/search.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/search.svg
deleted file mode 100644
index 92fd69d9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/search.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
- c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
- C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
- C125.8,169.4,169.2,125.9,222.6,125.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/settings.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/settings.svg
deleted file mode 100644
index 33485603..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/settings.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M450,138.3l-47.7,48.5l-2.7,2.8l-1.6,1.7c-1.1,0.8-2.4,1.2-3.9,1.2c-1.6,0-3.1-0.6-4.3-1.6l-0.9-0.9l-2.7-2.7l-41.3-42.1
- l-2.2-2.2l-1.7-1.7c-1-1.5-1.6-3.4-1.6-5.3c0-1.7,0.6-3.2,1.6-4.4l0.7-0.8l2.6-2.6l47.9-48.7c-5.1-10.1-24.7-14.9-35.1-14.1
- c-17.1,1.3-34.7,7-52.8,25.5c-0.7,0.8-1.5,1.6-2.2,2.3C277.5,120,272.6,156,282.6,189c0.7,1.4,1.3,3.1,1.6,4.6
- c1.1,5.5-0.4,10.2-4,13.5l-37.9,36.4c-11.8-12-13.5-13.6-13.5-13.6c-2-2-6-3.3-9.5-1.2l-5.9,3.6c-22.7-23.1-32.3-32.4-35.4-43.6
- c-3.2-11.7-0.3-27.3,2.7-33.1c2.5-4.6,10.3-8.9,16.9-9.4l8.6,8.8c2,2,5.1,2,7.1,0l30.9-31.4c2-2,2-5.3,0-7.3l-49.9-50.7
- c-2-2-5.2-2-7.1,0l-30.9,31.4c-2,2-2,5.3,0,7.3l3.3,3.4c0,4.9-0.7,12.5-4.7,16.6c-6.2,6.3-18.5-1-26.5,4.7
- c-7.9,5.6-17.9,14.6-24.3,21c-6.3,6.4-30.5,31.8-47.8,74.6c-17.3,42.8-4,82.5,5.4,92.9c5,5.5,14.1,11.1,12.5,0.7
- c-1.6-10.5-4.2-46.9,7.7-61.8c11.9-14.9,27.6-27.1,48-28.1c19.6-1,30.9,5.7,56.3,31.5l-2.8,5.2c-1.8,3.4-0.8,7.7,1.2,9.7
- c0,0,1.5,1.6,12.1,12.4l-97.2,93.2c-16.2,14.3-15.3,40.5-0.3,56c15.2,15.2,41.1,16.3,55.2-0.2l91.4-98.6
- c49.1,52.3,93.3,107.4,93.3,107.4c2,2,5.2,2,7.1,0l49.9-50.7c2-2,2-5.2,0-7.3c0,0-55.2-45.7-107-96.2l35.5-38.3
- c3.3-3.7,7.9-5.2,13.3-4.1c1.5,0.3,3.1,1,4.5,1.7c32.4,10.2,67.8,5.2,94-19.8c0.8-0.7,1.5-1.5,2.3-2.3c18.1-18.4,23.7-36.4,25-53.8
- C464.7,163.5,460.2,143.8,450,138.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/share.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/share.svg
deleted file mode 100644
index f0e12669..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/share.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M352,377.9H102.4V198.2h57.5c0,0,14.1-19.7,42.7-38.2H83.2c-10.6,0-19.2,8.5-19.2,19.1v217.9c0,10.5,8.6,19.1,19.2,19.1
- h288c10.6,0,19.2-8.5,19.2-19.1V288L352,319.4V377.9z M320,224v63.9l128-95.5L320,96v59.7C165.2,155.7,160,320,160,320
- C203.8,248.5,236,224,320,224z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/shuffle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/shuffle.svg
deleted file mode 100644
index 039ee28a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/shuffle.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M370.1,181.3H399v47.3l81-83.2L399,64v54h-28.9c-82.7,0-129.4,61.9-170.6,116.5c-37,49.1-69,95.4-120.6,95.4H32v63.3h46.9
- c82.7,0,129.4-65.8,170.6-120.4C286.5,223.7,318.4,181.3,370.1,181.3z M153.2,217.5c3.5-4.6,7.1-9.3,10.7-14.1
- c8.8-11.6,18-23.9,28-36.1c-29.6-27.9-65.3-48.5-113-48.5H32v63.3c0,0,13.3-0.6,46.9,0C111.4,182.8,131.8,196.2,153.2,217.5z
- M399,330.4h-28.9c-31.5,0-55.7-15.8-78.2-39.3c-2.2,3-4.5,6-6.8,9c-9.9,13.1-20.5,27.2-32.2,41.1c30.4,29.9,67.2,52.5,117.2,52.5
- H399V448l81-81.4l-81-83.2V330.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-backward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-backward.svg
deleted file mode 100644
index 065d3443..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-backward.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M75.7,96h8.1c6.7,0,12.2,5,12.2,11.7v113.5L283.1,98.7c2.5-1.7,5.1-2.3,8.1-2.3c8.3,0,15.4,7,15.4,17v63.1
- l118.5-78.2c2.5-1.7,5-2.3,8.1-2.3c8.3,0,14.9,7.4,14.9,17.4v286c0,10-6.7,16.5-15,16.5c-3.1,0-5.4-1.2-8.2-2.9l-118.3-77.6v64
- c0,10-7.2,16.5-15.5,16.5c-3.1,0-5.5-1.2-8.2-2.9L96,290.8v113c0,6.7-5.4,12.2-12.2,12.2h-8.1c-6.7,0-11.7-5.5-11.7-12.2V107.7
- C64,101,68.9,96,75.7,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-forward.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-forward.svg
deleted file mode 100644
index e563a047..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/skip-forward.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M436.3,96h-8.1c-6.7,0-12.2,5-12.2,11.7v113.5L228.9,98.7c-2.5-1.7-5.1-2.3-8.1-2.3c-8.3,0-15.4,7-15.4,17v63.1
- L86.9,98.3c-2.5-1.7-5.1-2.3-8.1-2.3c-8.3,0-14.9,7.4-14.9,17.4v286c0,10,6.7,16.5,15,16.5c3.1,0,5.4-1.2,8.2-2.9l118.3-77.6v64
- c0,10,7.2,16.5,15.5,16.5c3.1,0,5.5-1.2,8.2-2.9L416,290.8v113c0,6.7,5.4,12.2,12.2,12.2h8.1c6.7,0,11.7-5.5,11.7-12.2V107.7
- C448,101,443.1,96,436.3,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android-outline.svg
deleted file mode 100644
index 3cb896bc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android-outline.svg
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M352,208v60.5V357h-22.5H313v15.5V424c0,4.4-3,7.9-7.3,8l0,0l-0.1,0c-0.1,0-0.2,0-0.3,0c-1.6,0-3.1-0.6-4.3-1.6l-0.1-0.1
- l-0.4-0.1c-2-1.6-3.4-4-3.4-6.2v-51.5V357h-15.5h-49H216v15.5V424c0,4.4-3.6,8-8,8s-8-3.6-8-8v-51.5V357h-15.5H160v-88.6V208H352
- M368,192H144v76.4V358c0,6.9,5.5,15,12.4,15H184v51c0,13.3,10.7,24,24,24s24-10.7,24-24v-51h49v51c0,7.5,3.9,14.2,9.3,18.6
- c3.9,3.4,9.3,5.4,15,5.4c0.1,0,0.3,0,0.4,0c0.1,0-0.3,0-0.2,0c13.3,0,23.6-10.7,23.6-24v-51h28.6c7,0,10.4-8.1,10.4-14.9v-89.6
- V192L368,192z"/>
- <path d="M408,192c4.4,0,8,3.6,8,8v96c0,4.4-3.6,8-8,8s-8-3.6-8-8v-96C400,195.6,403.6,192,408,192 M408,176c-13.3,0-24,10.7-24,24
- v96c0,13.3,10.7,24,24,24s24-10.7,24-24v-96C432,186.7,421.3,176,408,176L408,176z"/>
- <path d="M104,192c4.4,0,8,3.6,8,8v96c0,4.4-3.6,8-8,8s-8-3.6-8-8v-96C96,195.6,99.6,192,104,192 M104,176c-13.3,0-24,10.7-24,24
- v96c0,13.3,10.7,24,24,24s24-10.7,24-24v-96C128,186.7,117.3,176,104,176L104,176z"/>
- </g>
- <g>
- <path d="M255,94.3l0.9,0h0h0c14.2,0,27.3,1.9,38.8,5.6l10,4.4c28.7,12.6,39.9,37.4,44.4,55.7H162.8c4.4-18.6,15.6-43.6,44.1-56
- l10.3-4.5C228.5,96.1,241.2,94.3,255,94.3 M185.4,64c-0.5,0-1.2,0.2-1.8,0.8c-1.1,0.8-1.7,1.8-1.3,2.5l18.3,22.1
- c-48.2,20.9-55.4,71.7-56.4,86.7h223.6c-1.1-15-8.2-65.1-56.6-86.4l18.5-22.2c0.4-0.5-0.2-1.7-1.3-2.6c-0.7-0.5-1.5-0.8-2-0.8
- c-0.3,0-0.5,0.1-0.7,0.3l-19.2,22.7c-13.6-5.4-30.2-8.8-50.6-8.8c-0.3,0-0.6,0-1,0c-20,0-36.4,3.3-49.8,8.5l-19-22.5
- C186.1,64.1,185.8,64,185.4,64L185.4,64z"/>
- </g>
-</g>
-<path d="M206.6,138.9c-7.4,0-13.5-6-13.5-13.3c0-7.3,6-13.3,13.5-13.3c7.4,0,13.5,6,13.5,13.3C220.1,132.9,214.1,138.9,206.6,138.9z
- "/>
-<path d="M305,138.9c-7.4,0-13.5-6-13.5-13.3c0-7.3,6-13.3,13.5-13.3c7.4,0,13.5,6,13.5,13.3C318.5,132.9,312.4,138.9,305,138.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android.svg
deleted file mode 100644
index 37681c0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-android.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M144,268.4V358c0,6.9,4.5,14,11.4,14H184v52c0,13.3,10.7,24,24,24s24-10.7,24-24v-52h49v52c0,7.5,3.4,14.2,8.8,18.6
- c3.9,3.4,9.1,5.4,14.7,5.4c0.1,0,0.2,0,0.3,0c0.1,0,0.1,0,0.2,0c13.3,0,24-10.7,24-24v-52h27.6c7,0,11.4-7.1,11.4-13.9v-89.6V192
- H144V268.4z"/>
- <path d="M408,176c-13.3,0-24,10.7-24,24v96c0,13.3,10.7,24,24,24s24-10.7,24-24v-96C432,186.7,421.3,176,408,176z"/>
- <path d="M104,176c-13.3,0-24,10.7-24,24v96c0,13.3,10.7,24,24,24s24-10.7,24-24v-96C128,186.7,117.3,176,104,176z"/>
- </g>
- <g>
- <path d="M311.2,89.1l18.5-21.9c0.4-0.5-0.2-1.6-1.3-2.5c-1.1-0.8-2.4-1-2.7-0.4l-19.2,22.8c-13.6-5.4-30.2-8.8-50.6-8.8
- c-20.5-0.1-37.2,3.2-50.8,8.5l-19-22.4c-0.4-0.5-1.6-0.4-2.7,0.4c-1.1,0.8-1.7,1.8-1.3,2.5l18.3,21.6
- c-48.2,20.9-55.4,72.2-56.4,87.2h223.6C366.7,161,359.6,110.4,311.2,89.1z M206.8,138.9c-7.4,0-13.5-6-13.5-13.3
- c0-7.3,6-13.3,13.5-13.3c7.4,0,13.5,6,13.5,13.3C220.3,132.9,214.3,138.9,206.8,138.9z M305.2,138.9c-7.4,0-13.5-6-13.5-13.3
- c0-7.3,6-13.3,13.5-13.3c7.4,0,13.5,6,13.5,13.3C318.7,132.9,312.6,138.9,305.2,138.9z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular-outline.svg
deleted file mode 100644
index 8124cc7b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M255.982,64l187.967,69.105l-39.17,230.389l-148.881,79.949l-148.812-80.051L68.031,133.11L255.982,64 M255.981,32L32,112
- l46.12,272L256,480l177.75-96L480,112L255.981,32L255.981,32z"/>
- <path d="M344,352h40L256,72L128,352h40l26.584-56h122.827L344,352z M213.573,256l42.419-89.356L298.419,256H213.573z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular.svg
deleted file mode 100644
index 9ed830a3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-angular.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="213.573,256 298.419,256 255.992,166.644 "/>
- <path d="M255.981,32L32,112l46.12,272L256,480l177.75-96L480,112L255.981,32z M344,352l-26.589-56H194.584L168,352h-40L256,72
- l128,280H344z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple-outline.svg
deleted file mode 100644
index aecaec8f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple-outline.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M333.6,169.9c16.3,0,33.2,7.4,47.4,20.4c-9.9,8.5-17.9,18.7-23.7,30.2c-8,16-11.6,34.3-10.2,52.7
- c1.3,18.7,7.6,36.6,18,51.8c8,11.6,18.2,21.2,30,28.3c-5,10.7-9.2,18.4-16.8,30.5c-8.4,13.1-30.5,48-52,48.2l-0.4,0
- c-7.4,0-12.2-2.2-19.3-5.6c-10-4.7-22.3-10.6-43.4-10.6l-0.6,0c-21.1,0.1-33.8,5.9-43.9,10.6c-7.4,3.4-12.3,5.7-19.9,5.7l-0.4,0
- c-19.6-0.2-37.5-24.3-50.8-45.2c-19.3-30.4-31.7-65.6-34.9-99.1c-2.9-30.5,2-58.5,13.5-76.7c8-12.7,18.5-23.3,30.4-30.6
- c11.2-6.8,23-10.4,34.2-10.4c12.4,0,22.7,3.8,33.7,7.8c11.5,4.2,23.5,8.6,37.7,8.6c13.6,0,24.3-4.2,34.6-8.2
- C308,173.9,318.2,169.9,333.6,169.9 M333.6,153.9c-33.6,0-47.8,16.5-71.2,16.5c-24,0-42.3-16.4-71.4-16.4
- c-28.5,0-58.9,17.9-78.2,48.4c-27.1,43-22.5,124,21.4,193c15.7,24.7,36.7,52.4,64.2,52.7c0.2,0,0.3,0,0.5,0
- c23.9,0,31-16.1,63.9-16.3c0.2,0,0.3,0,0.5,0c32.4,0,38.9,16.2,62.7,16.2c0.2,0,0.3,0,0.5,0c27.5-0.3,49.6-31,65.3-55.6
- c11.3-17.7,15.5-26.6,24.2-46.6c-63.5-24.8-73.7-117.4-10.9-152.9C385.9,168.2,359,153.9,333.6,153.9L333.6,153.9z"/>
- <path d="M309.9,84.5c-2.7,14.9-10.5,26.8-14.6,32.2c-7.4,9.8-18,17.4-28.8,21.1c0.5-3,1.3-6.1,2.4-9.2c3.5-10.2,8.9-18.2,12.8-23.1
- C288.8,96.7,299.3,89.1,309.9,84.5 M326.2,64c-20,1.4-43.3,14.5-57,31.6c-12.4,15.5-22.6,38.5-18.6,60.8c0.5,0,1,0,1.6,0
- c21.3,0,43.1-13.2,55.8-30.1C320.3,110.2,329.6,87.4,326.2,64L326.2,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple.svg
deleted file mode 100644
index 68ab6482..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-apple.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M333.6,153.9c-33.6,0-47.8,16.5-71.2,16.5c-24,0-42.3-16.4-71.4-16.4c-28.5,0-58.9,17.9-78.2,48.4
- c-27.1,43-22.5,124,21.4,193c15.7,24.7,36.7,52.4,64.2,52.7c0.2,0,0.3,0,0.5,0c23.9,0,31-16.1,63.9-16.3c0.2,0,0.3,0,0.5,0
- c32.4,0,38.9,16.2,62.7,16.2c0.2,0,0.3,0,0.5,0c27.5-0.3,49.6-31,65.3-55.6c11.3-17.7,15.5-26.6,24.2-46.6
- c-63.5-24.8-73.7-117.4-10.9-152.9C385.9,168.2,359,153.9,333.6,153.9L333.6,153.9z"/>
- <path d="M326.2,64c-20,1.4-43.3,14.5-57,31.6c-12.4,15.5-22.6,38.5-18.6,60.8c0.5,0,1,0,1.6,0c21.3,0,43.1-13.2,55.8-30.1
- C320.3,110.2,329.6,87.4,326.2,64L326.2,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin-outline.svg
deleted file mode 100644
index f990a441..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin-outline.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M279.7,48v47v15.1l15.1,0.8c16.9,0.9,28.8,3.3,40.7,7.9c13.8,5.3,24.2,12.6,31.1,21.7c5.7,7.6,9,19.4,10,36.2
- c0.6,8.8-1,17.1-2.6,22c-1.5,4.4-5.3,11.3-11.1,16.4c-5.4,4.8-8.6,6.7-12.3,8.4l-42.1,19.3l45,10.8c7.4,1.8,14,4.4,21.4,8.5
- c13.2,7.3,18,15.1,21.2,22.5c2.9,6.7,4.6,22.2,3.9,36.2c-0.7,13.4-4.4,31.5-12.6,42.3c-8.6,11.2-21.3,20.1-37.8,26.3
- c-13.6,5.1-31.1,8.1-54.5,9.3l-15.2,0.7v15.2V464h-8v-48v-16h-16H224h-16v16v48h-9v-48v-16h-16h-67.2l3-16h12.8
- c8.6,0,12.1-0.4,17.5-3c0.2-0.1,0.4-0.2,0.7-0.3c8.1-3.7,11-10.6,12.2-13.6c0.1-0.3,0.3-0.7,0.3-0.8c2.9-5.9,3-13.1,3-24.4v-178
- c0-11.7-0.1-13.6-3.1-19.5c-2.9-5.8-7.3-10.1-13.4-13c-5.9-2.8-13.2-3.4-24.5-3.4h-12.9v-16h71.6h16V96V48h9v48v16h16h31.8h16V96
- V48H279.7 M295.7,32h-39.9v64H224V32h-40.9v64H96v48h28.4c8.7,0,14.5,0.3,17.6,1.8c3.1,1.5,4.7,3.3,6,5.8c1.3,2.5,1.4,3.1,1.4,12.3
- v178c0,9-0.1,14.7-0.9,17.6c-1.2,2.7-2.2,5.2-5.3,6.6c-3.1,1.4-2.9,1.9-11.6,1.9h-27.4L96,416h87.1v64H224v-64h31.8v64h39.9v-65.4
- c26-1.3,44.4-4.7,59.3-10.3c19.3-7.2,34.3-17.7,44.9-31.5c10.5-13.8,15-34.9,15.9-51.2c0.8-14.5-0.7-33.2-5.2-43.4
- c-5-11.5-12.7-21.6-28.1-30.1c-8.1-4.5-16.1-7.8-25.4-10c5.4-2.5,9.9-5.4,16.3-11c7.5-6.6,13-15.7,15.6-23.3
- c2.6-7.5,4.1-18,3.5-28.2c-1.1-16.8-4.4-33.1-13.2-44.8c-8.8-11.7-21.7-20.7-38.1-27c-12.6-4.8-25.5-7.8-45.5-8.9V32L295.7,32z"/>
- <g>
- <polygon points="256,150 224,150 224,224 256,224 256,150 "/>
- <path d="M256,272h-32v90h32V272L256,272z"/>
- <path d="M296,153.9v65.6c6-2.9,9.5-6.8,13.3-11.7c4.6-6,7-12.9,7-20.7c0-8.1-2.4-15-6.7-20.8C305.7,161.2,302,156.4,296,153.9
- L296,153.9z"/>
- <path d="M296,273.6v82.8c2-0.6,3.8-0.8,5.8-1.6c9.8-3.8,15.8-7.9,23.6-14.7c7.5-6.6,9.7-15.9,9.7-26.6c0-9.1-3.3-16.9-7.9-23.2
- c-4.6-6.3-11.7-9.9-19.4-13.2C304.1,275.4,301,274.4,296,273.6L296,273.6z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin.svg
deleted file mode 100644
index e31622f7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-bitcoin.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M410.5,279.2c-5-11.5-12.7-21.6-28.1-30.1c-8.2-4.5-16.1-7.8-25.4-10c5.4-2.5,10-5.4,16.3-11c7.5-6.6,13.1-15.7,15.6-23.3
- c2.6-7.5,4.1-18,3.5-28.2c-1.1-16.8-4.4-33.1-13.2-44.8c-8.8-11.7-21.2-20.7-37.6-27c-12.6-4.8-25.5-7.8-45.5-8.9V32h-40v64h-32V32
- h-41v64H96v48h27.9c8.7,0,14.6,0.8,17.6,2.3c3.1,1.5,5.3,3.5,6.5,6c1.3,2.5,1.9,8.4,1.9,17.5V343c0,9-0.6,14.8-1.9,17.4
- c-1.3,2.6-2,4.9-5.1,6.3c-3.1,1.4-3.2,1.3-11.8,1.3h-26.4L96,416h87v64h41v-64h32v64h40v-64.4c26-1.3,44.5-4.7,59.4-10.3
- c19.3-7.2,34.1-17.7,44.7-31.5c10.6-13.8,14.9-34.9,15.8-51.2C416.6,308.1,415,289.4,410.5,279.2z M224,150h32v74h-32V150z M224,362
- v-90h32v90H224z M296,153.9c6,2.5,9.9,7.5,13.8,12.7c4.3,5.7,6.5,13.3,6.5,21.4c0,7.8-2.9,14.5-7.5,20.5c-3.8,4.9-6.8,8.3-12.8,11.1
- V153.9z M324.8,340.6c-7.8,6.9-12.3,10.1-22.1,13.8c-2,0.8-4.7,1.4-6.7,1.9v-82.8c5,0.8,7.6,1.8,11.3,3.4
- c7.8,3.3,15.2,6.9,19.8,13.2c4.6,6.3,8,15.6,8,24.7C335.1,325.7,332.3,334,324.8,340.6z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer-outline.svg
deleted file mode 100644
index b6bef7d7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M70.7,164.5l169.2,81.7c4.4,2.1,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7c8.9-4.3,8.9-11.3,0-15.6L272.1,67.2
- c-4.4-2.1-10.3-3.2-16.1-3.2s-11.7,1.1-16.1,3.2L70.7,148.9C61.8,153.2,61.8,160.2,70.7,164.5z M246.8,81.6
- c1.6-0.8,4.9-1.6,9.2-1.6c4.3,0,7.5,0.8,9.2,1.6l155.5,75.1l-155.5,75.1c-1.6,0.8-4.9,1.6-9.2,1.6c-4.3,0-7.5-0.8-9.2-1.6
- L91.3,156.7L246.8,81.6z"/>
- <path d="M441.3,248.2c0,0-30.9-14.9-35-16.9s-5.2-1.9-9.5,0.1s-124.8,60.2-124.8,60.2c-4.5,2.1-10.3,3.2-16.1,3.2
- s-11.7-1.1-16.1-3.2c0,0-117.3-56.6-122.8-59.3c-6-2.9-7.7-2.9-13.1-0.3c-5.6,2.7-33.4,16.1-33.4,16.1c-8.9,4.3-8.9,11.3,0,15.6
- l169.2,81.7c4.4,2.1,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7C450.2,259.5,450.2,252.5,441.3,248.2z M265.2,331.1
- c-1.6,0.8-4.9,1.6-9.2,1.6c-4.3,0-7.5-0.8-9.2-1.6L91.3,256l18.9-9.1l122.7,59.3c6.4,3.1,14.6,4.8,23.1,4.8s16.6-1.7,23.1-4.8
- l122.7-59.3l18.9,9.1L265.2,331.1z"/>
- </g>
- <path d="M441.3,347.5c0,0-30.9-14.9-35-16.9s-5.2-1.9-9.5,0.1S272.1,391,272.1,391c-4.5,2.1-10.3,3.2-16.1,3.2s-11.7-1.1-16.1-3.2
- c0,0-117.3-56.6-122.8-59.3c-6-2.9-7.7-2.9-13.1-0.3c-5.6,2.7-33.4,16.1-33.4,16.1c-8.9,4.3-8.9,11.3,0,15.6l169.2,81.7
- c4.4,2.2,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7C450.2,358.8,450.2,351.8,441.3,347.5z M265.2,430.4
- c-1.6,0.8-4.9,1.6-9.2,1.6c-4.3,0-7.5-0.8-9.2-1.6L91.3,355.3l18.9-9.1l122.7,59.3c6.4,3.1,14.6,4.8,23.1,4.8s16.6-1.7,23.1-4.8
- l122.7-59.3l18.9,9.1L265.2,430.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer.svg
deleted file mode 100644
index 595b1410..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-buffer.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M70.7,164.5l169.2,81.7c4.4,2.1,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7c8.9-4.3,8.9-11.3,0-15.6L272.1,67.2
- c-4.4-2.1-10.3-3.2-16.1-3.2s-11.7,1.1-16.1,3.2L70.7,148.9C61.8,153.2,61.8,160.2,70.7,164.5z"/>
- <path d="M441.3,248.2c0,0-30.9-14.9-35-16.9s-5.2-1.9-9.5,0.1s-124.8,60.2-124.8,60.2c-4.5,2.1-10.3,3.2-16.1,3.2
- s-11.7-1.1-16.1-3.2c0,0-117.3-56.6-122.8-59.3c-6-2.9-7.7-2.9-13.1-0.3c-5.6,2.7-33.4,16.1-33.4,16.1c-8.9,4.3-8.9,11.3,0,15.6
- l169.2,81.7c4.4,2.1,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7C450.2,259.5,450.2,252.5,441.3,248.2z"/>
- </g>
- <path d="M441.3,347.5c0,0-30.9-14.9-35-16.9s-5.2-1.9-9.5,0.1S272.1,391,272.1,391c-4.5,2.1-10.3,3.2-16.1,3.2s-11.7-1.1-16.1-3.2
- c0,0-117.3-56.6-122.8-59.3c-6-2.9-7.7-2.9-13.1-0.3c-5.6,2.7-33.4,16.1-33.4,16.1c-8.9,4.3-8.9,11.3,0,15.6l169.2,81.7
- c4.4,2.2,10.3,3.2,16.1,3.2s11.7-1.1,16.1-3.2l169.2-81.7C450.2,358.8,450.2,351.8,441.3,347.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome-outline.svg
deleted file mode 100644
index 161af4d1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g id="Icon">
- <g>
- <path d="M256,32C132.8,32,32,132.8,32,256s100.8,224,224,224s224-100.8,224-224S379.2,32,256,32z M256,76.799
- c66.084,0,124.315,35.843,154.558,89.602H256c-43.685,0-79.517,31.358-87.358,71.684l-53.758-92.969
- C147.358,103.685,198.884,76.799,256,76.799z M323.2,256c0,36.957-30.243,67.2-67.2,67.2s-67.2-30.243-67.2-67.2
- s30.243-67.2,67.2-67.2S323.2,219.043,323.2,256z M76.799,256c0-32.484,8.958-62.716,24.644-89.6L178.715,300.8l0,0
- c15.685,26.885,43.685,44.8,77.285,44.8c10.085,0,20.157-2.241,29.116-5.6l-53.758,92.958C144,421.758,76.799,346.715,76.799,256z
- M256,435.201L333.285,300.8l0,0c7.831-13.442,12.314-28,12.314-44.8c0-26.885-12.314-50.399-31.358-67.2h107.517
- c8.957,21.284,13.443,43.685,13.443,67.2C435.201,354.557,354.557,435.201,256,435.201z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome.svg
deleted file mode 100644
index 7ee33d6c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-chrome.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M188.8,255.925c0,36.946,30.243,67.178,67.2,67.178s67.199-30.231,67.199-67.178c0-36.945-30.242-67.179-67.199-67.179
- S188.8,218.98,188.8,255.925z"/>
- <path d="M476.752,217.795c-0.009,0.005-0.016,0.038-0.024,0.042c-1.701-9.877-4.04-19.838-6.989-28.838h-0.107
- c2.983,9,5.352,19,7.072,29h-0.002c-1.719-10-4.088-20-7.07-29h-155.39c19.044,17,31.358,40.175,31.358,67.052
- c0,16.796-4.484,31.284-12.314,44.724L231.044,478.452c0,0-0.009,0.264-0.014,0.264l-0.01,0.284c0.005,0,0.009,0,0.015,0
- l-0.005-0.262c8.203,0.92,16.531,1.262,24.97,1.262c6.842,0,13.609-0.393,20.299-1.002c10.135-0.911,20.077-2.519,29.777-4.733
- C405.68,451.525,480,362.404,480,255.941C480,242.942,478.879,230.188,476.752,217.795z"/>
- <path d="M256,345.496c-33.601,0-61.601-17.91-77.285-44.785L76.006,123.047l-0.137-0.236
- c-10.293,13.896-19.015,29.022-25.903,45.123C38.407,194.945,32,224.686,32,255.925c0,62.695,25.784,119.36,67.316,160.009
- c29.342,28.719,66.545,49.433,108.088,58.619l0.029-0.051l77.683-134.604C276.157,343.256,266.085,345.496,256,345.496z"/>
- <path d="M91.292,104.575l77.35,133.25C176.483,197.513,212.315,166,256,166h205.172c-6.921-15-15.594-30.324-25.779-43.938
- c0.039,0.021,0.078,0.053,0.117,0.074C445.644,135.712,454.278,151,461.172,166h0.172c-6.884-15-15.514-30.38-25.668-43.99
- c-0.115-0.06-0.229-0.168-0.342-0.257C394.475,67.267,329.359,32,256,32c-26.372,0-51.673,4.569-75.172,12.936
- c-34.615,12.327-65.303,32.917-89.687,59.406l0.142,0.243C91.286,104.581,91.289,104.578,91.292,104.575z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen-outline.svg
deleted file mode 100644
index a76d0235..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen-outline.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path fill-rule="evenodd" clip-rule="evenodd" d="M387.547,203.724c-41.135-27.326-82.225-54.721-123.261-82.195
- c-5.844-3.912-11.12-3.802-16.938,0.095c-40.785,27.313-81.818,54.546-122.724,81.676c-5.103,3.384-7.624,7.575-7.624,13.716
- v79.729c0,6.174,2.484,10.342,7.594,13.73c40.906,27.13,81.841,54.361,122.625,81.676c5.81,3.891,11.131,4.055,16.984,0.137
- c41.035-27.474,82.145-54.873,123.286-82.188c4.858-3.226,7.511-7.309,7.511-13.094v-80.623
- C395,210.667,392.225,206.83,387.547,203.724z M268,152.484l93.055,62.218l-39.751,26.467c-0.919,0.603-2.923,0.604-3.839,0
- c-15.944-10.501-31.816-21.113-47.627-31.815c-1.033-0.699-1.828-2.319-1.838-3.52V152.484z M244,152.765v51.706
- c-0.024,1.825-1.313,4.316-2.799,5.334c-15.258,10.451-30.655,20.701-46.109,30.86c-1.17,0.77-3.547,1.148-4.566,0.485
- c-13.116-8.531-26.087-17.284-39.787-26.443C181.967,193.889,244,152.765,244,152.765z M141,237.116l29.622,19.771L141,276.725
- V237.116z M244,361.317c0,0-62.034-41.412-93.196-62.187l38.871-26.154c2.072-1.442,3.473-1.344,5.502,0.029
- c15.32,10.36,30.74,20.572,46.062,30.93c1.208,0.815,2.749,2.371,2.761,3.596V361.317z M258.949,282.892
- c-1.824,1.108-4.512,1.046-6.26-0.111l-38.842-25.865c0,0,17.108-11.493,25.356-17.023c4.701-3.152,9.346-6.393,14.164-9.355
- c1.132-0.696,3.532-0.97,4.743-0.168c5.773,3.829,39.854,26.53,39.854,26.53L258.949,282.892z M268,361.102v-51.346
- c-0.026-2.871,0.449-4.602,2.861-6.189c15.198-10.006,30.332-20.11,45.386-30.332c2.335-1.586,3.92-1.623,6.265-0.019
- l38.527,25.882L268,361.102z M370,276.676l-29.59-19.743L370,237.06V276.676z"/>
- <path d="M256,64c51.285,0,99.5,19.972,135.765,56.235C428.028,156.5,448,204.715,448,256s-19.972,99.5-56.235,135.765
- C355.5,428.028,307.285,448,256,448s-99.5-19.972-135.765-56.235C83.972,355.5,64,307.285,64,256s19.972-99.5,56.235-135.765
- C156.5,83.972,204.715,64,256,64 M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32
- L256,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen.svg
deleted file mode 100644
index 5f56bfbb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-codepen.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M241.239,303.936c-15.322-10.357-30.742-20.569-46.062-30.93c-2.03-1.373-3.43-1.472-5.502-0.029l-38.871,26.154
- C181.966,319.905,244,361.317,244,361.317v-53.786C243.988,306.307,242.447,304.751,241.239,303.936z"/>
- <path d="M195.092,240.666c15.454-10.16,30.851-20.409,46.109-30.86c1.486-1.018,2.775-3.509,2.799-5.334v-51.706
- c0,0-62.033,41.124-93.262,61.942c13.7,9.159,26.671,17.913,39.787,26.443C191.545,241.813,193.921,241.435,195.092,240.666z"/>
- <path d="M269.838,209.354c15.811,10.703,31.683,21.314,47.627,31.815c0.916,0.604,2.92,0.602,3.839,0l39.751-26.467L268,152.484
- v53.35C268.01,207.035,268.805,208.655,269.838,209.354z"/>
- <path d="M258.109,230.369c-1.21-0.802-3.611-0.528-4.743,0.168c-4.817,2.962-9.463,6.203-14.164,9.355
- c-8.248,5.53-25.356,17.023-25.356,17.023l38.842,25.865c1.748,1.157,4.436,1.22,6.26,0.111l39.014-25.993
- C297.963,256.898,263.883,234.197,258.109,230.369z"/>
- <polygon points="141,237.116 141,276.725 170.622,256.887 "/>
- <path d="M256,32C132.288,32,32,132.288,32,256s100.288,224,224,224s224-100.288,224-224S379.712,32,256,32z M395,297.006
- c0,5.785-2.652,9.868-7.511,13.094c-41.142,27.314-82.251,54.714-123.286,82.188c-5.854,3.918-11.174,3.754-16.984-0.137
- c-40.783-27.314-81.719-54.546-122.625-81.676c-5.11-3.389-7.594-7.557-7.594-13.73v-79.729c0-6.141,2.521-10.332,7.624-13.716
- c40.906-27.13,81.939-54.363,122.724-81.676c5.818-3.896,11.094-4.007,16.938-0.095c41.036,27.474,82.126,54.869,123.261,82.195
- c4.678,3.106,7.453,6.943,7.453,12.66V297.006z"/>
- <path d="M316.247,273.234c-15.054,10.222-30.188,20.326-45.386,30.332c-2.412,1.588-2.888,3.318-2.861,6.189v51.346l93.039-62.004
- l-38.527-25.882C320.167,271.611,318.582,271.648,316.247,273.234z"/>
- <polygon points="370,276.676 370,237.06 340.41,256.933 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3-outline.svg
deleted file mode 100644
index 37c25cf1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M354.676,366.898l-98.608,28.125l-98.458-28.248L150.864,289h48.253l3.433,39.563l53.586,15.163l0.132,0.273h0.034
- l53.467-14.852L315.381,265H203l-4-50h120.646l4.396-51H140l-4-49h240.58L354.676,366.898z"/>
- <path d="M64,32l34.936,403.301L255.769,480l157.245-44.705L448,32H64z M383.041,410.51l-127.262,36.187l-126.867-36.169L98.896,64
- H413.1L383.041,410.51z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3.svg
deleted file mode 100644
index df8a1d0a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-css3.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g transform="translate(336 96)">
- <g id="icon-css3">
- <path d="M-79.718,243.488L-79.718,243.488z"/>
- <path d="M-272-64l34.946,403.219L-80.233,384l157.259-44.85L112-64H-272z M18.676,270.898l-98.607,28.125l-98.458-28.248
- L-185.136,193h48.253l3.433,39.562l53.586,15.163l0.132,0.273h0.034l53.467-14.852L-20.619,169H-133l-4-50h120.646l4.396-51H-196
- l-4-49H40.58L18.676,270.898z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews-outline.svg
deleted file mode 100644
index 82b63233..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews-outline.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="290.9,145.9 226.5,96 291.1,198.8 "/>
- <g>
- <path d="M32.5,260"/>
- <path d="M329,96v80.3V260h-35.9l-63.2-98l1.7,98H191V152.9l-37.1-29.1c1,1.2,2.1,2.4,3,3.6c10,13.8,15,30.7,15,50.5
- c0,48.9-30.5,82-76.8,82H32l200.1,156H480V214.7L329,96z M464,400H237.7L78.6,276h16.5c13.5,0,26.2-2.7,37.7-7.4
- c11.5-4.7,21.4-11.8,29.8-20.7c4.8-5.1,9.4-11,12.4-17.1v28.7V276h16.2h40.4H248l-0.3-16.5l-0.7-41.9l32.6,50.7l4.7,7.6h8.8h36.8
- H345v-16.5v-83.1v-47l0.2,0.3L464,222.4V400z"/>
- </g>
- <path d="M90.6,150.4c11,0,23.7,3.2,23.7,28.8c0,6.9-1,16.3-6,21.8c-3.6,3.9-9.6,6-17.7,6H87v-57h3 M90.7,134H71v89h19.5
- c26,0,39.9-15.6,39.9-43.9C130.4,150.3,116.1,134,90.7,134L90.7,134z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews.svg
deleted file mode 100644
index a8edefc9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-designernews.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <polygon points="290.4,145 227,96 290.6,198.2 "/>
- </g>
- <g>
- <path d="M329,96v79.6V259h-36.4l-63.2-98.6l1.7,98.6H191V152l-37.3-29.3c1,1.2,2,2.4,2.9,3.7c10,13.9,15,30.5,15,50.5
- c0,49.2-30.6,82.1-76.9,82.1H32v0.4L231.6,416H480V214.1L329,96z"/>
- </g>
- <g>
- <path d="M129.9,178.1c0-29-14.2-45.1-39.7-45.1H71v89h19C116,222,129.9,206.6,129.9,178.1z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble-outline.svg
deleted file mode 100644
index 92477c8c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble-outline.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,64C150,64,64,150,64,256c0,106.1,86,192,192,192s192-85.9,192-192C448,150,362,64,256,64z M377.9,152.5
- c21.6,25.4,35.3,57.6,37.7,92.9c-34.6-1.8-76-1.8-109.2,1.3c-4.2-10.6-8.5-21-13.2-31C331.5,199.1,361,177.3,377.9,152.5z M256,96
- c38.8,0,74.4,13.8,102.1,36.8c-17.4,22-44.7,41.1-78.7,55.6c-18.6-34.4-40-64-62.8-87.3C229.3,97.9,242.4,96,256,96z M183.6,113.5
- c23.1,23,44.8,52.3,63.8,86.6c-36.1,11-77.5,17.3-121.7,17.3c-8.4,0-16.6-0.3-24.7-0.8C112.5,171.5,143,134.1,183.6,113.5z
- M96.3,248.4c9.1,0.4,18.3,0.6,27.6,0.5c50.4-0.6,97.3-8.5,137.6-21.4c3.8,7.9,7.4,16,10.8,24.3c-5.5,1.3-10.4,2.7-14.3,4.3
- c-55.1,23.1-98.5,60.4-122,105.5c-24.8-28.2-40-65.1-40-105.6C96,253.4,96.1,250.9,96.3,248.4z M256,416c-37,0-71-12.6-98.1-33.7
- c21.3-42.2,59.3-77.1,107.2-98.8c4.5-2.1,10.5-3.8,17.4-5.3c5.7,15.8,10.8,32.2,15.3,49.2c6.9,26.5,11.8,52.7,14.8,78.1
- C295,412.2,276,416,256,416z M342.5,390.5c-3-25.7-7.9-52.1-14.9-78.9c-3.4-13-7.3-25.6-11.5-37.9c31.4-2.6,69-2.2,98.9,0
- C409.6,322.8,382,365,342.5,390.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble.svg
deleted file mode 100644
index 8cfe9742..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dribbble.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M256,64C150,64,64,150,64,256c0,106.1,86,192,192,192s192-85.9,192-192C448,150,362,64,256,64z M256,415.5
- c-88.1,0-159.5-71.4-159.5-159.5c0-88.1,71.4-159.5,159.5-159.5c88.1,0,159.5,71.4,159.5,159.5C415.5,344.1,344.1,415.5,256,415.5
- z"/>
- </g>
- <g>
- <path d="M306.3,246.7c23.4-2.2,50.9-2.9,77.2-2.4c-2.3-25.4-12-48.7-27-67.6c-16.5,14.9-38,28.1-63.3,39
- C297.8,225.7,302.1,236.1,306.3,246.7z"/>
- <path d="M335.4,155.6C313.6,138.3,286,128,256,128c-5.1,0-10.2,0.3-15.2,0.9c13.8,17.7,26.7,37.6,38.6,59.5
- C301.1,179.2,320,168.1,335.4,155.6z"/>
- <path d="M205.9,138.2c-34.1,14.5-60.7,43.4-72,79.1c41.1-0.7,79.6-7,113.4-17.3C234.7,177,220.7,156.3,205.9,138.2z"/>
- <path d="M383,272.2c-22.3-0.6-46-0.2-66.9,1.5c4.1,12.3,8.1,24.9,11.5,37.9c3.8,14.6,7,29.1,9.6,43.4
- C361.8,334.7,378.8,305.4,383,272.2z"/>
- <path d="M258,256.1c3.9-1.6,8.8-3,14.3-4.3c-3.4-8.3-7.1-16.4-10.8-24.3c-39.1,12.6-84.6,20.3-133.3,21.3
- c-0.1,2.4-0.2,4.8-0.2,7.3c0,29.1,9.7,55.9,26,77.4C178.9,301,214.9,274.2,258,256.1z"/>
- <path d="M282.6,278.2c-6.9,1.5-12.9,3.2-17.4,5.3c-37.1,16.8-68.3,41.6-90.4,71.5c22.1,18.2,50.4,29,81.2,29
- c18.5,0,36-3.9,51.8-10.9c-2.7-15.1-6-30.3-10-45.7C293.4,310.5,288.2,294,282.6,278.2z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox-outline.svg
deleted file mode 100644
index 7f0f67bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M177,77.1L64,151l78.3,63L256,143.2L177,77.1z M91.4,153.3l84.5-56.8l52.9,46L143.4,195L91.4,153.3z"/>
- <path d="M369.8,213L256,284.1l79,66.1l19-12.6v20.2L256,417l-98-58.5V338l19,12.2l79-66.1L142.2,213L64,276.3l78,51.5v39.4
- l114,67.8l114-68.5v-39.2l78-51.2L369.8,213z M143.4,230.9l85.4,55.4l-52.9,44.1l-84.5-55.8L143.4,230.9z M283.2,286.3l85.4-55.4
- l52.1,43.6l-84.5,55.8L283.2,286.3z"/>
- <path d="M448,151L335,77.1l-79,66.1l113.8,70.8L448,151z M283.2,142.6l52.9-46l84.5,56.8L368.6,195L283.2,142.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox.svg
deleted file mode 100644
index df15e205..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-dropbox.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="177,77 64,150.9 142.1,213.6 256,143.1 "/>
- <polygon points="64,276.3 177,350.2 256,284.1 142.1,213.6 "/>
- <polygon points="256,284.1 335,350.2 448,276.3 369.9,213.6 "/>
- <polygon points="448,150.9 335,77 256,143.1 369.9,213.6 "/>
- <polygon points="256.2,298.3 176.4,364.3 142,342.1 142,367 256,435 370,367 370,342.1 335.8,364.3 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro-outline.svg
deleted file mode 100644
index 91fcf4a2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M310.143,64c31.337,0,59.096,2.607,88.137,8.364l-5.06,34.148c-29.405-4.319-55.659-6.429-79.853-6.429
- c-35.025,0-58.535,6.153-74.129,19.365C220.142,135.627,218,158.428,218,174.17v2.33V193h15.867h120.184l-2.383,16H233.867H218
- v15.5v48V289h15.867h105.885l-2.384,16H233.867H218v15.5v12.33c0,19.546,2.338,44.061,21.084,60.274
- c15.042,13.01,37.921,18.812,74.258,18.812c24.534,0,50.197-2.055,79.771-6.42l5.014,34.138
- c-29.031,5.759-56.741,8.366-87.977,8.366c-52.591,0-91.43-9.08-115.565-26.987C172.615,404.711,162,380.361,162,346.57V320.5V305
- h-16.133H112v-16h33.867H162v-16.5v-48V209h-16.133H112v-16h33.867H162v-16.5v-11.07c0-33.791,10.613-58.142,32.582-74.442
- C218.715,73.08,257.552,64,310.143,64 M310.209,48C195.479,48,146,89.225,146,165.43V177H96v48h50v48H96v48h50v25.57
- C146,422.774,195.481,464,310.211,464c35.25,0,67.777-3.123,105.789-11.866l-9.411-64.96c-37.323,6.244-66.942,8.742-93.206,8.742
- c-64.275,0-79.383-18.739-79.383-63.086V321h117.162l7.148-48H234v-48h131.461l7.149-48H234v-2.83
- c0-35.92,15.159-58.086,79.434-58.086c26.264,0,55.959,2.498,93.281,8.742L416,60C377.988,51.257,345.458,48,310.209,48L310.209,48
- z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro.svg
deleted file mode 100644
index 7609507d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-euro.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M234,272v-48h131.094l7.149-48H234v-1.83c0-35.92,14.975-58.086,79.25-58.086c26.264,0,55.867,2.498,93.189,8.742
- L416,59.866C377.988,51.123,345.306,48,310.057,48C195.326,48,146,89.225,146,165.43V176H96v48h50v48H96v48h50v26.57
- C146,422.774,195.297,464,310.027,464c35.25,0,67.848-3.123,105.859-11.866l-9.619-64.96c-37.322,6.244-66.781,8.742-93.045,8.742
- c-64.276,0-79.223-18.739-79.223-63.086V320h116.795l7.148-48H234z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook-outline.svg
deleted file mode 100644
index d50fae4a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook-outline.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M288,192v-38.1c0-17.2,3.8-25.9,30.5-25.9H352V64h-55.9c-68.5,0-91.1,31.4-91.1,85.3V192h-45v64h45v192h83V256h56.4l7.6-64
- H288z M330.2,240h-41.1H272v15.5V432h-51V255.5V240h-14.9H176v-32h30.1H221v-16.5v-42.2c0-24.5,5.4-41.2,15.5-51.8
- C247.7,85.5,267.6,80,296.1,80H336v32h-17.5c-12,0-27.5,1.1-37.1,11.7c-8.1,9-9.4,20.1-9.4,30.1v37.6V208h17.1H334L330.2,240z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook.svg
deleted file mode 100644
index ae3d5ed8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-facebook.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M288,192v-38.1c0-17.2,3.8-25.9,30.5-25.9H352V64h-55.9c-68.5,0-91.1,31.4-91.1,85.3V192h-45v64h45v192h83V256h56.4l7.6-64
- H288z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare-outline.svg
deleted file mode 100644
index 43959e11..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M398.484,164.452l-27.399,137.185C372.848,294.486,386.545,224.793,398.484,164.452z"/>
- <path d="M376.764,32c0,0-205.353,0-238.223,0C105.666,32,96,56.798,96,72.414c0,15.627,0,379.64,0,379.64
- c0,17.591,9.425,24.117,14.718,26.267c5.299,2.155,19.916,3.971,28.673-6.168c0,0,112.469-131.09,114.4-133.027
- c2.921-2.931,2.921-3.125,5.844-3.125c5.843,0,49.192,0,72.766,0c30.575,0,35.49-21.676,38.684-34.559l27.399-137.087
- c6.074-30.702,11.693-58.938,15.053-75.325C421.143,51.944,411.744,32,376.764,32z M376.426,96c0,0-31.575,156.209-36.034,176.834
- C335,297.771,332.75,304,307,304c-17.605,0-62.375,0-62.375,0c-2.747,0-3.868-0.147-6.049,2.041
- c-1.443,1.447-78.168,89.562-78.168,89.562c-19.034,23.396-26.909,31.795-29.033,31.795s-3.375,0-3.375-38.408V91.708
- C128,67.034,128.3,64,157.198,64C181.748,64,352,64,352,64C382,64,382.834,64.833,376.426,96z"/>
- <path d="M398.484,164.452l15.053-75.374C410.178,105.466,404.559,133.75,398.484,164.452z"/>
- <path d="M328.573,96c-5.571,0-157.995,0-157.995,0C164.091,96,160,101.594,160,106.586v231.255c0,0.67,0.402,0.975,0.935,0.36
- c0,0,48.202-55.725,54.056-63.021c5.848-7.289,8.491-8.182,17.233-8.182c0,0,56.695,0,62.212,0c6.549,0,10.24-5.75,10.913-8.982
- c0.671-3.228,10.536-48.213,11.732-54.119c1.191-5.897-4.214-11.898-9.722-11.898c-5.5,0-64.805,0-64.805,0
- c-7.803,0-7.554-5.653-7.554-13.476v-5.512c0-7.815-0.282-13.012,7.516-13.012c0,0,70.403,0,75.313,0
- c4.911,0,10.208-4.442,11.102-8.662l8.468-44.042C338.739,100.823,333.828,96,328.573,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare.svg
deleted file mode 100644
index 840febfc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-foursquare.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M376.764,32c0,0-205.353,0-238.223,0C105.666,32,96,56.798,96,72.414c0,15.627,0,379.64,0,379.64
- c0,17.591,9.425,24.117,14.718,26.267c5.299,2.155,19.916,3.971,28.673-6.168c0,0,112.469-130.895,114.4-132.834
- c2.921-2.93,2.921-2.93,5.844-2.93c5.844,0,49.192,0,72.767,0c30.574,0,35.49-21.869,38.684-34.752
- c2.659-10.789,32.489-163.962,42.452-212.559C421.143,51.993,411.745,32,376.764,32z M371.086,301.637
- c2.659-10.789,32.489-163.962,42.452-212.559 M362.692,96.67l-9.999,51.734c-1.195,5.65-8.287,11.595-14.863,11.595
- c-6.575,0-95.917,0-95.917,0C231.473,160,224,166.138,224,176.602v13.448c0,10.473,7.519,17.894,17.965,17.894
- c0,0,74.482,0,81.848,0c7.374,0,14.61,8.109,13.016,16.005c-1.602,7.908-9.086,46.569-9.984,50.89
- c-0.902,4.328-5.845,11.725-14.611,11.725c-7.388,0-64.269,0-64.269,0c-11.705,0-15.244,1.533-23.074,11.293
- c-7.837,9.77-78.256,94.592-78.256,94.592c-0.713,0.822-1.41,0.584-1.41-0.312V95.896c0-6.684,5.793-14.523,14.479-14.523
- c0,0,183.713,0,191.173,0C357.912,81.372,364.488,88.004,362.692,96.67z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-freebsd-devil.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-freebsd-devil.svg
deleted file mode 100644
index 4f7b5ed7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-freebsd-devil.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path class="st0" d="M502.6,115c-22.5-43.7-58-51-58-51s15.5,32,16,51c0.4,16.1-5.5,28-27.2,33.5s-30.8-2-47.8-17.5
- S344,104.5,313,103c-40-2-77,9-77,9c-20-25,20-80,20-80c-74.5,29.5-93.7,83.3-96,113.7c-1.9,24.1,8.5,40.8,8.5,40.8s-0.5,27.8-5,42
- c-3.1,9.8-16.9,25-26,34.5c-12.2,12.7-12.5,38.5,0,57s44,27.5,67,39.5s31.5,21,31.5,21s1,8.3,0.5,15.3s-3.2,14-9,18.2
- c-5.5,3.9-15.5,0.5-20.5-2s-5-6.2-10.5-8s-7.3-4-6.5-11s2-9-3.5-18.5s-18.5-9.5-29.5-8s-17.3,6.8-17.3,6.8l-16.3-10
- c0,0,8.5-15.6,5.2-35.6c-7.3-43.8-50-62.8-50-62.8l10.4,44.4c0,0,1.1-2.6,6.4-6.4s8.1-3.6,8.1-3.6s6.6,7.6,9.1,25.3
- c2.5,18-6.7,27.2-6.7,27.2l-28.3-18l1-14.5L39.8,309L56,345.7l15-4l24,22.7c0,0-15.7,11.7-33,11.7c-11,0-22-6-22-6s-1.4-1-0.8-5.5
- c0.7-5,6.8-12.5,6.8-12.5H0c0,0,27.3,38.7,65,38.7c31,0,44.2-12.5,44.2-12.5L128,397c0,0,3,5.5,0,7s-7,3.5-9,15s18,29,18,29
- c21.8,17.8,7,32,7,32h272c-9-13-22.5-18-32-32c0,0-44.8-58.4-1.8-90.4c57.4-42.7,42.8-69.4,41.2-101.4c0,0,31.8-6.6,59.3-33.6
- S521.6,151.8,502.6,115z M195,203c-16.9,4.5-22.5,35.5-22.5,35.5c1.5-63,57.5-93,65-89s-6.5,39-21,64
- C216.5,213.5,208.5,199.4,195,203z M232,218c0,0,18-56,37.5-59.5s41.5,21,41.5,62s-26,65.4-42.8,69.2c-16.5,3.8-23,2-23,2
- s27.5-21.6,23.5-56.8C265.9,210.2,237.3,210.7,232,218z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github-outline.svg
deleted file mode 100644
index 4e0257a4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github-outline.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,134.9,32,261.7c0,101.5,64.2,187.5,153.2,217.9c1.4,0.3,2.6,0.4,3.8,0.4c8.3,0,11.5-6.1,11.5-11.4
- c0-5.5-0.2-19.9-0.3-39.1c-8.4,1.9-15.9,2.7-22.6,2.7c-43.1,0-52.9-33.5-52.9-33.5c-10.2-26.5-24.9-33.6-24.9-33.6
- c-19.5-13.7-0.1-14.1,1.4-14.1c0.1,0,0.1,0,0.1,0c22.5,2,34.3,23.8,34.3,23.8c11.2,19.6,26.2,25.1,39.6,25.1c10.5,0,20-3.4,25.6-6
- c2-14.8,7.8-24.9,14.2-30.7c-49.7-5.8-102-25.5-102-113.5c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,1.6-0.5,5-0.5
- c8.1,0,26.4,3.1,56.6,24.1c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7c30.2-21,48.5-24.1,56.6-24.1c3.4,0,5,0.5,5,0.5
- c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3c8,7.1,15.2,21.1,15.2,42.5
- c0,30.7-0.3,55.5-0.3,63c0,5.4,3.1,11.5,11.4,11.5c1.2,0,2.6-0.1,4-0.4C415.9,449.2,480,363.1,480,261.7C480,134.9,379.7,32,256,32z
- M177.6,448.1c2.2,0,4.4-0.1,6.7-0.2c0,2.8,0,5.5,0.1,7.9c0,2.4,0,4.6,0.1,6.5c-15.6-5.8-30.3-13.5-44.1-23
- C150.2,444.6,162.5,448.1,177.6,448.1z M189,375.2c-0.8,2.2-1.5,4.5-2.1,6.9c-3.4,1-7.5,1.8-11.7,1.8c-10.9,0-19-5.4-25.6-16.9
- c-2.4-4.6-6.8-10.7-12.9-16.3C153.5,364.8,173,371.6,189,375.2z M379,434.1c-15.8,11.9-33,21.3-51,28.2c0-1.9,0-4.1,0-6.5
- c0-11.9,0-29.8,0-50.4c0-12.4-2.1-22.5-5-30.5c37.2-8.3,92-33.7,92-125.4c0-24.6-7.1-46.5-21.2-65.1c3.1-12.9,5.5-35.6-5.1-63
- l-2.7-7.1l-7.2-2.4c-1.5-0.5-4.8-1.3-10-1.3c-11.5,0-30.9,4.1-59.5,22.8c-17-4.2-34.8-6.4-53.1-6.4H256h-0.1
- c-18.3,0-36.2,2.2-53.1,6.4c-28.6-18.7-48-22.8-59.5-22.8c-5.2,0-8.5,0.9-10,1.4l-7.2,2.4l-2.7,7.1c-10.6,27.5-8.2,50.2-5.1,63
- c-14.1,18.7-21.2,40.6-21.2,65.1c0,49.6,16,79.9,36.6,98.5c-8.1-6.6-18.6-12.1-31.2-13H102h-0.5h-0.3c-13.1,0-22.3,5.4-25.2,14.7
- c-4.7,14.8,9.8,25,14.6,28.4l0.5,0.6l1.5,0.6c1.6,1,10.1,7,16.9,24.5c2,6.2,6.3,14.5,13.6,22.2c-13.1-11.2-24.8-24-34.9-38.1
- C61.9,351.2,48,307.5,48,261.7c0-28.9,5.5-56.9,16.4-83.3c10.5-25.5,25.5-48.3,44.7-67.9c19.1-19.6,41.4-35,66.1-45.7
- C200.8,53.7,228,48,256,48s55.2,5.6,80.8,16.7c24.8,10.7,47,26.1,66.1,45.7c19.1,19.6,34.2,42.5,44.7,67.9
- c10.9,26.4,16.4,54.4,16.4,83.3c0,45.8-13.8,89.5-40.1,126.3C411.3,405.6,396.2,421.1,379,434.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github.svg
deleted file mode 100644
index 34579ced..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-github.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,134.9,32,261.7c0,101.5,64.2,187.5,153.2,217.9c1.4,0.3,2.6,0.4,3.8,0.4c8.3,0,11.5-6.1,11.5-11.4
- c0-5.5-0.2-19.9-0.3-39.1c-8.4,1.9-15.9,2.7-22.6,2.7c-43.1,0-52.9-33.5-52.9-33.5c-10.2-26.5-24.9-33.6-24.9-33.6
- c-19.5-13.7-0.1-14.1,1.4-14.1c0.1,0,0.1,0,0.1,0c22.5,2,34.3,23.8,34.3,23.8c11.2,19.6,26.2,25.1,39.6,25.1c10.5,0,20-3.4,25.6-6
- c2-14.8,7.8-24.9,14.2-30.7c-49.7-5.8-102-25.5-102-113.5c0-25.1,8.7-45.6,23-61.6c-2.3-5.8-10-29.2,2.2-60.8c0,0,1.6-0.5,5-0.5
- c8.1,0,26.4,3.1,56.6,24.1c17.9-5.1,37-7.6,56.1-7.7c19,0.1,38.2,2.6,56.1,7.7c30.2-21,48.5-24.1,56.6-24.1c3.4,0,5,0.5,5,0.5
- c12.2,31.6,4.5,55,2.2,60.8c14.3,16.1,23,36.6,23,61.6c0,88.2-52.4,107.6-102.3,113.3c8,7.1,15.2,21.1,15.2,42.5
- c0,30.7-0.3,55.5-0.3,63c0,5.4,3.1,11.5,11.4,11.5c1.2,0,2.6-0.1,4-0.4C415.9,449.2,480,363.1,480,261.7C480,134.9,379.7,32,256,32z
- "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google-outline.svg
deleted file mode 100644
index 4dfb1387..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M319.408,82.141c11.779,9.576,36.43,29.718,36.43,68.043c0,37.295-21.547,54.934-43.094,71.545
- c-6.695,6.561-14.385,13.608-14.385,24.701c0,11.092,7.689,17.153,13.336,21.671l18.473,14.108
- c22.598,18.641,43.125,35.795,43.125,70.559c0,47.373-46.721,95.232-135.003,95.232c-74.428,0-110.343-34.766-110.343-72.061
- c0-18.139,9.245-43.827,39.525-61.48c31.798-19.142,74.952-21.657,98.023-23.172c-7.178-9.078-15.382-18.67-15.382-34.265
- c0-8.577,2.557-13.609,5.12-19.655c-5.648,0.5-11.283,1-16.42,1c-54.408,0-85.214-39.811-85.214-79.107
- c0-23.186,10.802-48.902,32.856-67.543C215.724,68.031,250.637,64,278.328,64h105.725l-32.846,18.141H319.408z M282.955,305.896
- c-4.137-0.501-6.684-0.501-11.793-0.501c-4.629,0-32.348,1.002-53.895,8.049c-11.3,4.046-44.146,16.125-44.146,51.918
- c0,35.78,35.393,61.467,90.339,61.467c49.283,0,75.432-23.156,75.432-54.404C338.893,346.707,321.971,333.113,282.955,305.896
- M297.834,210.148c11.824-11.592,12.844-27.73,12.844-36.793c0-36.281-22.086-92.73-64.671-92.73
- c-13.339,0-27.724,6.547-35.948,16.639c-8.722,10.593-11.284,24.188-11.284,37.281c0,33.764,20.005,89.727,64.163,89.727
- C275.764,224.271,289.594,218.212,297.834,210.148"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google.svg
deleted file mode 100644
index 360427ee..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-google.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M325.862,275.558l-18.187-13.653l-0.063-0.051c-5.827-4.579-9.952-8.313-9.952-14.685c0-6.979,5.049-11.824,10.896-17.436
- l0.466-0.449c20.025-15.171,44.726-34.286,44.726-74.556c0-26.934-11.916-44.729-23.28-57.729h12.969l60.322-33H270.308
- c-25.324,0-62.68,3.225-94.561,28.576l-0.128,0.25c-21.809,18.111-34.828,44.584-34.828,70.691
- c0,21.197,8.706,42.159,23.885,57.447c21.428,21.579,48.302,26.127,67.074,26.127c1.462,0,2.956-0.028,4.47-0.093
- c-0.759,2.969-1.25,6.321-1.25,10.321c0,10.926,3.628,19.301,8.083,26.195c-23.963,1.932-58.148,6.477-84.897,22.278
- c-39.335,22.562-42.396,55.875-42.396,65.551c0,38.207,35.707,76.762,115.479,76.762c91.611,0,139.543-49.792,139.543-98.979
- C370.781,311.966,347.945,293.457,325.862,275.558z M200.485,139.894c0-13.359,3.02-23.457,9.255-30.9
- c6.514-7.852,18.18-13.129,29.028-13.129c19.881,0,32.938,15.008,40.388,27.598c9.199,15.539,14.913,36.095,14.913,53.643
- c0,4.942,0,19.983-10.188,29.796c-6.951,6.686-18.707,11.353-28.59,11.353c-20.503,0-33.453-14.705-40.707-27.041
- C204.189,173.53,200.485,153.109,200.485,139.894z M321.6,367.974c0,27.444-25.212,44.493-65.799,44.493
- c-48.058,0-80.347-20.603-80.347-51.265c0-26.14,21.54-36.789,37.8-42.521c18.944-6.064,44.297-7.305,50.062-7.305
- c3.907,0,6.087,0,8.683,0.229C308.7,336.816,321.6,347.733,321.6,367.974z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus-outline.svg
deleted file mode 100644
index 6757ede3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus-outline.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M223.5,82.1c11.8,9.6,36.4,29.7,36.4,68c0,37.3-21.5,54.9-43.1,71.5c-6.7,6.6-14.4,13.6-14.4,24.7
- c0,11.1,7.7,17.2,13.3,21.7l18.5,14.1c22.6,18.6,43.1,35.8,43.1,70.6c0,47.4-46.7,95.2-135,95.2C67.9,448,32,413.2,32,375.9
- c0-18.1,9.2-43.8,39.5-61.5c31.8-19.1,75-21.7,98-23.2c-7.2-9.1-15.4-18.7-15.4-34.3c0-8.6,2.6-13.6,5.1-19.7
- c-5.6,0.5-11.3,1-16.4,1c-54.4,0-85.2-39.8-85.2-79.1c0-23.2,10.8-48.9,32.9-67.5C119.8,68,154.7,64,182.4,64h105.7l-32.8,18.1
- H223.5z M187,305.9c-4.1-0.5-6.7-0.5-11.8-0.5c-4.6,0-32.3,1-53.9,8c-11.3,4-44.1,16.1-44.1,51.9c0,35.8,35.4,61.5,90.3,61.5
- c49.3,0,75.4-23.2,75.4-54.4C242.9,346.7,226,333.1,187,305.9 M201.9,210.1c11.8-11.6,12.8-27.7,12.8-36.8
- c0-36.3-22.1-92.7-64.7-92.7c-13.3,0-27.7,6.5-35.9,16.6c-8.7,10.6-11.3,24.2-11.3,37.3c0,33.8,20,89.7,64.2,89.7
- C179.8,224.3,193.6,218.2,201.9,210.1"/>
- <polygon points="480,142.3 401.7,142.3 401.7,64.1 384,64.1 384,142.3 304.3,142.3 304.3,160.1 384,160.1 384,241 401.7,241
- 401.7,160.1 480,160.1 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus.svg
deleted file mode 100644
index 8bfd88d1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-googleplus.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M242.1,275.6l-18.2-13.7l-0.1-0.1c-5.8-4.6-10-8.3-10-14.7c0-7,5-11.8,10.9-17.4l0.5-0.4c20-15.2,44.7-34.3,44.7-74.6
- c0-26.9-11.9-44.7-23.3-57.7h13L320,64H186.5c-25.3,0-62.7,3.2-94.6,28.6l-0.1,0.3C70,110.9,57,137.4,57,163.5
- c0,21.2,8.7,42.2,23.9,57.4c21.4,21.6,48.3,26.1,67.1,26.1c1.5,0,3,0,4.5-0.1c-0.8,3-1.2,6.3-1.2,10.3c0,10.9,3.6,19.3,8.1,26.2
- c-24,1.9-58.1,6.5-84.9,22.3C35.1,328.4,32,361.7,32,371.3c0,38.2,35.7,76.8,115.5,76.8c91.6,0,139.5-49.8,139.5-99
- C287,312,264.2,293.5,242.1,275.6z M116.7,139.9c0-13.4,3-23.5,9.3-30.9c6.5-7.9,18.2-13.1,29-13.1c19.9,0,32.9,15,40.4,27.6
- c9.2,15.5,14.9,36.1,14.9,53.6c0,4.9,0,20-10.2,29.8c-7,6.7-18.7,11.4-28.6,11.4c-20.5,0-33.5-14.7-40.7-27
- C120.4,173.5,116.7,153.1,116.7,139.9z M237.8,368c0,27.4-25.2,44.5-65.8,44.5c-48.1,0-80.3-20.6-80.3-51.3
- c0-26.1,21.5-36.8,37.8-42.5c18.9-6.1,44.3-7.3,50.1-7.3c3.9,0,6.1,0,8.7,0.2C224.9,336.8,237.8,347.7,237.8,368z"/>
- <polygon points="402,142 402,64 368,64 368,142 288,142 288,176 368,176 368,257 402,257 402,176 480,176 480,142 "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews-outline.svg
deleted file mode 100644
index 43083521..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M416,96v320H96V96H416 M448,64H64v384h384V64L448,64z"/>
- <g>
- <path d="M296.7,159H342l-63.9,120v72h-39.9v-72L172,159h47.1l39.7,83.6L296.7,159z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews.svg
deleted file mode 100644
index 48f9a28b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-hackernews.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M64,64v384h384V64H64z M278,279v72h-40v-72l-66-120h47.1l39.7,83.6l38-83.6H342L278,279z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5-outline.svg
deleted file mode 100644
index 6d3cca4a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M64,32l34.936,403.301L255.769,480l157.245-44.705L448,32H64z M383.041,410.51l-127.262,36.187l-126.867-36.169L98.896,64
- H413.1L383.041,410.51z"/>
- <polygon points="147.991,264 314.984,264 309.411,327.986 255.991,342.734 202.225,328.064 198.801,289 150.55,289
- 157.313,366.336 255.991,394.146 354.486,366.163 367.991,215 191.991,215 188,164 371.991,164 376.199,114.316 135.421,114.188
- "/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5.svg
deleted file mode 100644
index 3cc836db..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-html5.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M64,32l34.936,403.213L255.769,480l157.245-44.854L448,32H64z M371.997,164h-184l3.991,51h176.008l-13.505,151.386
- l-98.5,28.094l-98.682-27.976L150.545,289h48.254l3.423,39.287l53.769,14.781l53.422-14.915L314.987,264H147.986l-12.571-149.589
- l240.789,0.016L371.997,164z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram-outline.svg
deleted file mode 100644
index 231a34e0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram-outline.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path fill="#231F20" d="M448.5,112c0-26.233-21.267-47.5-47.5-47.5H112c-26.233,0-47.5,21.267-47.5,47.5v289
- c0,26.233,21.267,47.5,47.5,47.5h289c26.233,0,47.5-21.267,47.5-47.5V112z M257,175.833c44.182,0,80,35.816,80,80s-35.818,80-80,80
- s-80-35.816-80-80S212.818,175.833,257,175.833z M416.5,160.5c0,8.836-7.163,16-16,16h-48c-8.837,0-16-7.164-16-16v-48
- c0-8.836,7.163-16,16-16h48c8.837,0,16,7.164,16,16V160.5z M401.5,416.5h-288c-8.822,0-17-8.178-17-17v-175h53.072
- c-3.008,10-4.572,20.647-4.572,31.583C145,286,156.65,314,177.805,335.154s49.279,32.741,79.195,32.741s58.041-11.681,79.195-32.835
- S369,286.016,369,256.099c0-10.936-1.563-21.599-4.572-31.599H416.5v175C416.5,408.322,410.322,416.5,401.5,416.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram.svg
deleted file mode 100644
index 570d2ca2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-instagram.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <circle cx="256" cy="255.833" r="80"/>
-</g>
-<g>
- <path d="M177.805,176.887c21.154-21.154,49.279-32.929,79.195-32.929s58.041,11.837,79.195,32.991
- c13.422,13.422,23.011,29.551,28.232,47.551H448.5v-113c0-26.51-20.49-47-47-47h-288c-26.51,0-49,20.49-49,47v113h85.072
- C154.794,206.5,164.383,190.309,177.805,176.887z M416.5,147.7c0,7.069-5.73,12.8-12.8,12.8h-38.4c-7.069,0-12.8-5.73-12.8-12.8
- v-38.4c0-7.069,5.73-12.8,12.8-12.8h38.4c7.069,0,12.8,5.73,12.8,12.8V147.7z"/>
- <path d="M336.195,335.279c-21.154,21.154-49.279,32.679-79.195,32.679s-58.041-11.462-79.195-32.616
- c-21.115-21.115-32.759-49.842-32.803-78.842H64.5v143c0,26.51,22.49,49,49,49h288c26.51,0,47-22.49,47-49v-143h-79.502
- C368.955,285.5,357.311,314.164,336.195,335.279z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript-outline.svg
deleted file mode 100644
index df1bd87d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript-outline.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g transform="translate(384 48)">
- <g id="icon-javascript_1_1_">
- <path d="M-192,56.001v197.017c0,41.567-9.644,71.988-28.662,90.417c-17.06,16.53-42.061,24.565-76.431,24.565
- c-12.002,0-25.78-1.496-37.185-3.886l4.09-30.505c7.146,1.269,15.465,2.149,24.774,2.149c21.92,0,37.892-6.459,48.827-19.745
- C-245.27,302.268-240,282.085-240,252.499V56.001H-192 M-176,40.001h-80v212.498c0,52.58-18.032,67.261-49.412,67.261
- c-14.705,0-27.948-2.521-38.25-6.063L-352,375.904c14.7,5.062,37.259,8.096,54.907,8.096C-225.045,384-176,350.129-176,253.02
- V40.001L-176,40.001z"/>
- <path d="M-1.537,48c24.458,0,45.898,3.146,65.1,9.585l-9.581,32.062C40.37,84.142,21.446,78.71-2.504,78.71
- c-18.607,0-34.462,4.584-45.849,13.256c-11.732,8.936-18.194,21.583-18.194,35.613c0,34.974,33.062,48.149,71.347,63.405
- l0.107,0.043l0.108,0.041c26.977,10.299,45.938,22.261,57.969,36.572C74.593,241.451,80,257.543,80,278.284
- c0,25.177-9.333,46.71-26.99,62.274C32.66,358.497,1.593,367.98-36.833,367.98c-28.052,0-54.698-6.427-72.615-13.979l7.593-31.603
- c17.579,7.248,41.882,14.382,69.438,14.382c20.28,0,36.629-4.478,48.591-13.306c12.807-9.45,19.857-23.697,19.857-40.119
- c0-15.348-6.041-27.922-18.469-38.444c-10.157-8.603-24.801-16.048-47.467-24.136c-26.86-9.904-47.359-21.947-60.934-35.795
- C-105.078,170.455-112,153.829-112,134.154c0-24.149,9.831-45.101,28.43-60.591C-63.49,56.839-35.124,48-1.537,48 M-1.537,32
- C-78.98,32-128,75.998-128,134.154c0,50.083,37.751,81.44,92.641,101.665c39.7,14.158,55.392,26.808,55.392,47.539
- c0,22.756-18.139,37.425-52.448,37.425c-31.863,0-60.789-10.64-80.394-21.255v-0.021L-128,362.727
- c18.639,10.638,53.441,21.255,91.167,21.255C53.854,383.98,96,335.43,96,278.284c0-48.55-26.958-79.9-85.278-102.163
- c-43.139-17.191-61.27-26.795-61.27-48.542c0-17.2,15.688-32.869,48.043-32.869c31.846,0,53.744,10.707,66.505,17.291l19.125-64
- C63.125,39.22,36.188,32-1.537,32L-1.537,32z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript.svg
deleted file mode 100644
index 0a20e9ce..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-javascript.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g transform="translate(384 48)">
- <g id="icon-javascript_1_1_">
- <path d="M-176,40.001h-80v212.498c0,52.58-18.032,67.261-49.412,67.261c-14.705,0-27.948-2.521-38.25-6.063L-352,375.904
- c14.7,5.062,37.259,8.096,54.907,8.096C-225.045,384-176,350.129-176,253.02V40.001L-176,40.001z"/>
- <path d="M-1.537,32C-78.98,32-128,75.998-128,134.154c0,50.083,37.751,81.44,92.641,101.665
- c39.7,14.158,55.392,26.808,55.392,47.539c0,22.756-18.139,37.425-52.448,37.425c-31.863,0-60.789-10.64-80.394-21.255v-0.021
- L-128,362.727c18.639,10.638,53.441,21.255,91.167,21.255C53.854,383.98,96,335.43,96,278.284c0-48.55-26.958-79.9-85.278-102.163
- c-43.139-17.191-61.27-26.795-61.27-48.542c0-17.2,15.688-32.869,48.043-32.869c31.846,0,53.744,10.707,66.505,17.291l19.125-64
- C63.125,39.22,36.188,32-1.537,32L-1.537,32z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin-outline.svg
deleted file mode 100644
index 8c3dbc77..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill-rule:evenodd;clip-rule:evenodd;}
-]]>
-</style>
-<g>
- <g>
- <path class="st0" d="M182.8,384V212.9h-54.9V384H182.8L182.8,384z M157.4,187c18.3,0,29.7-13.1,29.7-29.5
- c-0.3-16.7-11.4-29.5-29.4-29.5c-18,0-29.7,12.8-29.7,29.5c0,16.4,11.4,29.5,29,29.5H157.4L157.4,187z"/>
- <path class="st0" d="M320.6,209c-29.1,0-41.6,16.4-49.6,27.8V213h-55v171h55v-97.4c0-5,0.4-10,1.9-13.5c4-10,13-20.3,28.2-20.3
- c19.9,0,27.9,15.3,27.9,37.7V384h55v-99.9C384,232.8,356.8,209,320.6,209z"/>
- </g>
- <path d="M417.2,64H96.8C79.3,64,64,76.6,64,93.9v321.1c0,17.4,15.3,32.9,32.8,32.9h320.3c17.6,0,30.8-15.6,30.8-32.9V93.9
- C448,76.6,434.7,64,417.2,64z M414,416c-1.1,0-313.1,0-314.9,0s-3.1-1.4-3.1-3.1S96,99.1,96,98s1-2,2-2s315,0,316,0s2,1,2,2
- c0,23.3,0,314.9,0,316C416,414.9,415.1,416,414,416z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin.svg
deleted file mode 100644
index 72cd8239..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-linkedin.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M417.2,64H96.8C79.3,64,64,76.6,64,93.9v321.1c0,17.4,15.3,32.9,32.8,32.9h320.3c17.6,0,30.8-15.6,30.8-32.9V93.9
- C448,76.6,434.7,64,417.2,64z M183,384h-55V213h55V384z M157.4,187H157c-17.6,0-29-13.1-29-29.5c0-16.7,11.7-29.5,29.7-29.5
- c18,0,29,12.7,29.4,29.5C187.1,173.9,175.7,187,157.4,187z M384,384h-55v-93.5c0-22.4-8-37.7-27.9-37.7
- c-15.2,0-24.2,10.3-28.2,20.3c-1.5,3.6-1.9,8.5-1.9,13.5V384h-55V213h55v23.8c8-11.4,20.5-27.8,49.6-27.8
- c36.1,0,63.4,23.8,63.4,75.1V384z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-markdown.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-markdown.svg
deleted file mode 100644
index fff5d364..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-markdown.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g transform="translate(96 48)">
- <g id="icon-markdown">
- <path fill="#231F20" d="M351.659,48H-31.659C-49.496,48-64,62.484-64,80.308v255.349C-64,353.493-49.496,368-31.659,368h383.318
- C369.496,368,384,353.493,384,335.656V80.308C384,62.484,369.496,48,351.659,48z M188.023,304h-56.048v-96l-42.04,53.878
- L47.913,208v96H-8.131V112h56.044l42.022,67.98l42.04-67.98h56.048V304L188.023,304z M271.68,304l-69.635-96h42v-96h56.043v96
- h42.027l-70.453,96H271.68z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-nodejs.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-nodejs.svg
deleted file mode 100644
index 2829f03a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-nodejs.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g transform="translate(96 96)">
- <g id="icon-nodejs_small">
- <path d="M159.917,384c-5.77,0-11.536-1.562-16.633-4.599l-52.985-32.44c-7.914-4.562-4.023-6.203-1.443-7.141
- c10.565-3.781,13.713-5.657,24.947-12.285c1.206-0.667,2.747-0.424,3.955,0.322l39.71,23.504c1.476,0.85,3.557,0.85,4.931,0
- l155.188-92.246c1.475-0.877,2.415-2.646,2.415-4.441V67.869c0-1.85-0.94-3.592-2.449-4.528L162.433-31.331
- c-1.478-0.894-3.421-0.894-4.898,0L2.516,63.374C0.972,64.277,0,66.072,0,67.869v186.805c0,1.813,0.972,3.513,2.481,4.389
- l39.929,23.972C66.02,295.239,80,282.865,80,268.424V84.725c0-2.652,2.047-4.727,4.596-4.727h22.809
- c2.515,0,4.597,2.072,4.597,4.727v183.698c0,32.563-19.353,51.248-49.199,51.248c-9.156,0-16.397,0-36.552-10.279l-41.584-24.781
- C-25.629,278.459-32,266.965-32,254.656V65.191c0-12.316,6.371-23.784,16.665-29.917L143.35-59.59
- c10.027-5.88,23.374-5.88,33.332,0l158.65,94.864C345.63,41.423,352,52.899,352,65.191v189.465c0,12.309-6.37,23.75-16.668,29.953
- l-158.65,94.774c-5.097,3.036-10.832,4.599-16.698,4.599L159.917,384z"/>
- <path d="M208.943,255.998c-64.61,0-84.006-31.61-84.006-59.271c0-2.629,2.048-4.729,4.562-4.729h20.521
- c2.282,0,4.227,1.7,4.562,4.016c3.084,21.602,16.748,31.15,54.324,31.15c33.399,0,47.091-10.346,47.091-28.684
- c0-10.592-3.463-18.424-55.407-23.697c-43.427-4.441-70.288-14.373-70.288-50.295c0-33.135,26.996-52.49,72.234-52.49
- c46.128,0,76.462,14,79.173,50.829c0.102,1.337-0.368,2.629-1.241,3.644c-0.871,0.965-2.078,1.527-3.353,1.527h-20.591
- c-2.146,0-4.024-1.562-4.459-3.713c-4.401-16.953-16.97-23.402-49.563-23.402c-36.486,0-40.746,12.753-40.746,22.607
- c0,11.963,5.031,15.441,54.294,22.172c48.761,6.663,71.933,16.117,71.933,51.552c0,35.781-28.808,58.783-79.075,58.783
- L208.943,255.998L208.943,255.998z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-octocat.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-octocat.svg
deleted file mode 100644
index 57ac1631..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-octocat.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path fill="#231F20" d="M178.354,287.478c-9.123,0-16.928,4.207-23.201,12.833c-6.291,8.478-9.398,18.973-9.398,31.431
- c0,12.474,3.166,23.008,9.398,31.509c6.273,8.54,14.039,12.771,23.201,12.771c8.494,0,15.889-4.27,22.121-12.771
- c6.271-8.501,9.398-19.035,9.398-31.509c0-12.419-3.166-22.93-9.398-31.431C194.242,291.724,186.908,287.478,178.354,287.478z"/>
- <path fill="#231F20" d="M334.668,287.478c-9.045,0-16.891,4.207-23.182,12.833c-6.271,8.478-9.359,18.973-9.359,31.431
- c0,12.474,3.186,23.008,9.359,31.509c6.291,8.54,14.098,12.771,23.182,12.771c8.533,0,15.906-4.27,22.178-12.771
- c6.293-8.501,9.418-19.035,9.418-31.509c0-12.419-3.164-22.93-9.418-31.431C350.574,291.724,343.299,287.478,334.668,287.478z"/>
- <path fill="#231F20" d="M445.777,172h-0.059c0,0,2.793-14.264,0.314-39.18c-2.182-24.916-7.471-47.838-16.123-68.82
- c0,0-4.422,0.76-12.76,2.896s-22.08,6.299-40.938,14.768c-18.541,8.54-37.986,19.788-58.297,33.505
- c-13.803-3.934-34.408-5.939-61.994-5.939c-26.289,0-46.914,2.012-61.977,5.945c-44.592-30.859-81.832-47.945-112.092-51.175
- c-8.594,20.982-13.883,43.991-16.045,68.97c-2.398,24.939,0.432,39.329,0.432,39.329C41.979,198.551,32,236.541,32,267.793
- c0,24.244,0.658,46.078,6.125,65.48c5.564,19.31,12.662,35.13,21.098,47.221c8.611,12.121,19.012,22.788,31.576,31.938
- c12.467,9.314,23.988,15.962,34.389,20.216c10.461,4.372,22.375,7.602,35.982,9.861c13.33,2.386,23.438,3.645,30.477,3.996
- c0,0,28,1.494,64.354,1.494c36.354,0,64.295-1.494,64.295-1.494c7.02-0.352,17.145-1.634,30.535-3.996
- c13.547-2.299,25.521-5.607,35.941-9.861c10.402-4.293,21.943-10.901,34.469-20.216c12.523-9.032,22.906-19.739,31.518-31.938
- c8.436-12.091,15.494-27.911,21.098-47.221c5.486-19.402,6.145-41.385,6.145-65.629C480,237.389,469.982,199,445.777,172z
- M380.383,405.645C352.521,418.736,311.486,424,257.061,424l-2.143-0.039c-54.443,0-95.361-5.248-122.848-18.41
- c-27.508-13.092-41.271-40.057-41.271-80.738c0-24.33,8.572-43.99,25.482-59.107c7.354-6.515,16.438-11.019,27.645-13.717
- c11.129-2.558,21.354-2.762,30.969-2.465c9.398,0.415,22.551,2.196,39.344,3.464C231.029,254.285,243.535,256,256,256
- c11.698,0,27.213-1.957,52.104-3.959c24.99-1.971,43.494-2.971,55.467-1c12.289,2.002,22.986,6.202,32.129,14.742
- c17.734,15.751,26.602,35.505,26.602,59.084C422.301,365.533,408.164,392.537,380.383,405.645z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest-outline.svg
deleted file mode 100644
index e6d63055..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest-outline.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M256,32C132.3,32,32,132.3,32,256s100.3,224,224,224s224-100.3,224-224S379.7,32,256,32z M391.8,391.8
- C355.5,428,307.3,448,256,448c-16.2,0-32.1-2-47.4-5.9c2.8-6.3,5.2-12.8,7-19.3c2.8-10,15.8-61.6,15.8-61.6
- c7.8,14.8,30.5,27.9,54.7,27.9c72,0,120.9-65.6,120.9-153.5c0-66.4-56.3-128.3-141.8-128.3c-106.4,0-160.1,76.3-160.1,139.9
- c0,38.5,14.6,72.8,45.9,85.6c5.1,2.1,9.7,0.1,11.2-5.6c1-3.9,3.5-13.9,4.6-18c1.5-5.6,0.9-7.6-3.2-12.5c-9-10.7-14.8-24.4-14.8-43.9
- c0-56.6,42.3-107.3,110.3-107.3c60.1,0,93.2,36.7,93.2,85.8c0,64.6-28.6,119.1-71,119.1c-23.4,0-41-19.4-35.4-43.1
- c6.7-28.4,19.8-59,19.8-79.5c0-18.3-9.8-33.6-30.2-33.6c-24,0-43.2,24.8-43.2,58c0,21.1,7.2,35.4,7.2,35.4s-24.5,103.9-28.8,122.1
- c-1.3,5.5-2.2,11.1-2.9,16.8c-17.3-9-33.3-20.6-47.4-34.8C84,355.5,64,307.3,64,256s20-99.5,56.2-135.8C156.5,84,204.7,64,256,64
- s99.5,20,135.8,56.2C428,156.5,448,204.7,448,256S428,355.5,391.8,391.8z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest.svg
deleted file mode 100644
index 1f992aa6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-pinterest.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256,32C132.3,32,32,132.3,32,256c0,91.7,55.2,170.5,134.1,205.2c-0.6-15.6-0.1-34.4,3.9-51.4
- c4.3-18.2,28.8-122.1,28.8-122.1s-7.2-14.3-7.2-35.4c0-33.2,19.2-58,43.2-58c20.4,0,30.2,15.3,30.2,33.6
- c0,20.5-13.1,51.1-19.8,79.5c-5.6,23.8,11.9,43.1,35.4,43.1c42.4,0,71-54.5,71-119.1c0-49.1-33.1-85.8-93.2-85.8
- c-67.9,0-110.3,50.7-110.3,107.3c0,19.5,5.8,33.3,14.8,43.9c4.1,4.9,4.7,6.9,3.2,12.5c-1.1,4.1-3.5,14-4.6,18
- c-1.5,5.7-6.1,7.7-11.2,5.6c-31.3-12.8-45.9-47-45.9-85.6c0-63.6,53.7-139.9,160.1-139.9c85.5,0,141.8,61.9,141.8,128.3
- c0,87.9-48.9,153.5-120.9,153.5c-24.2,0-46.9-13.1-54.7-27.9c0,0-13,51.6-15.8,61.6c-4.7,17.3-14,34.5-22.5,48
- c20.1,5.9,41.4,9.2,63.5,9.2c123.7,0,224-100.3,224-224C480,132.3,379.7,32,256,32z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-python.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-python.svg
deleted file mode 100644
index ab523e4b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-python.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M193.46,249.056c3.723-0.67,7.589-1.041,11.586-1.041L201.924,248h103.823c4.503,0,8.806-0.617,12.908-1.754
- c19.37-5.363,33.345-22.537,33.345-43.663v-30.822v-56.402c0-24.832-21.15-43.484-46.289-47.606
- c-15.931-2.624-39.258-3.827-55.089-3.749c-15.829,0.086-30.981,1.404-44.277,3.749C167.143,74.576,160,88.928,160,115.359V144h96
- v16H128.82c-35.628,0-64.538,42.571-64.813,95.242C64.005,255.495,64,255.747,64,256c0,9.523,0.94,18.72,2.685,27.404
- C74.648,323.07,99.451,352,128.82,352H144v-2.662v-43.273C144,279.238,164.146,254.332,193.46,249.056z M203.656,127.002
- c-9.592,0-17.384-7.785-17.384-17.403c0-9.664,7.774-17.52,17.384-17.52c9.574,0,17.399,7.855,17.399,17.52
- C221.056,119.217,213.246,127.002,203.656,127.002z"/>
- <path d="M443.951,222.543C434.78,186.021,411.033,160,383.18,160H368v2.626v38.046c0,33.915-22.286,58.474-49.489,62.681
- c-2.737,0.424-5.483,0.646-8.301,0.646H206.351c-4.518,0-8.904,0.584-13.049,1.672C174.18,270.689,160,286.6,160,307.236v32.922
- v54.305c0,24.832,24.977,39.426,49.481,46.551c29.327,8.531,61.267,10.068,96.366,0C329.15,434.354,352,420.893,352,394.463V368
- h-96v-16h127.18c25.24,0,47.107-21.365,57.814-52.549C445.474,286.404,448,271.641,448,256
- C448,244.232,446.567,232.962,443.951,222.543z M307.867,382.82c9.59,0,17.381,7.785,17.381,17.4
- c0,9.65-7.791,17.521-17.381,17.521c-9.577,0-17.399-7.871-17.399-17.521C290.468,390.59,298.274,382.82,307.867,382.82z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit-outline.svg
deleted file mode 100644
index 40553cc1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit-outline.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <circle cx="322.3" cy="288.4" r="31.8"/>
- <circle cx="190.3" cy="288.4" r="31.8"/>
- <g>
- <path d="M480.5,251c0-27.7-22.2-50.2-49.5-50.2c-13,0-24.7,5-33.6,13.3c-33.2-23.4-78.4-38.5-128.7-40.7L292,95.7l69.6,13.9
- c0.2,24.7,20.1,44.7,44.5,44.7c24.6,0,44.5-20.2,44.5-45.1S430.7,64,406.1,64c-18.6,0-34.5,11.6-41.2,28l-85.2-17l-29.4,98.2
- l-7.1,0.2c-50.3,2.2-95.5,17.4-128.7,40.7c-8.8-8.3-20.6-13.3-33.6-13.3c-27.3,0-49.5,22.5-49.5,50.2c0,19.6,11,36.5,27.1,44.8
- c-0.8,4.9-1.2,9.8-1.2,14.8C57.5,386.4,146.4,448,256,448s198.5-61.6,198.5-137.5c0-5-0.4-9.9-1.1-14.8
- C469.5,287.4,480.5,270.5,480.5,251z M406.1,81.9c14.8,0,26.8,12.2,26.8,27.2c0,15-12,27.2-26.8,27.2c-14.8,0-26.8-12.2-26.8-27.2
- C379.3,94.1,391.3,81.9,406.1,81.9z M49.2,251c0-17.8,14.3-32.2,31.8-32.2c7.2,0,13.9,2.5,19.2,6.6c-17.3,15.2-30.1,33-37,52.4
- C54.8,271.9,49.2,262.1,49.2,251z M386.4,392.9c-34.6,23.9-80.9,37.1-130.4,37.1s-95.8-13.2-130.4-37.1
- c-32.5-22.5-50.4-51.8-50.4-82.4c0-3.2,0.2-6.5,0.6-9.7c0.7-6,2.2-11.9,4.3-17.7c5.6-15.6,16-30.3,30.7-43.4
- c4.4-3.9,9.2-7.7,14.4-11.3c0.1-0.1,0.3-0.2,0.4-0.3C160.2,204.2,206.5,191,256,191c49.5,0,95.8,13.2,130.4,37.1
- c0.1,0.1,0.3,0.2,0.4,0.3c5.2,3.6,10,7.4,14.4,11.3c14.7,13.1,25.1,27.8,30.7,43.4c2.1,5.8,3.5,11.7,4.3,17.7
- c0.4,3.2,0.6,6.4,0.6,9.7C436.8,341.1,418.9,370.4,386.4,392.9z M448.8,277.7c-6.9-19.4-19.7-37.2-37-52.4
- c5.3-4.1,12-6.6,19.2-6.6c17.5,0,31.8,14.5,31.8,32.2C462.8,262.1,457.2,271.9,448.8,277.7z"/>
- <path d="M320.5,357.9c-0.2,0.2-24.2,24.2-64.5,24.4c-40.9-0.2-64.4-24.2-64.6-24.4l-12.6,12.4c1.2,1.2,29.6,29.5,77.2,29.7
- c47.6-0.2,75.9-28.5,77.1-29.7L320.5,357.9z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit.svg
deleted file mode 100644
index e85c3ce1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-reddit.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M480.5,251c0-27.7-22.2-50.2-49.5-50.2c-13,0-24.7,5-33.6,13.3c-32.4-22.8-76.1-37.8-124.9-40.6l21.9-73.2l67.1,13.5
- c2.3,22.7,21.2,40.4,44.3,40.4c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0c24.6,0,44.5-20.2,44.5-45.1S430.7,64,406.1,64
- c-0.1,0-0.1,0-0.2,0c0,0-0.1,0-0.1,0c-17.2,0-32,9.8-39.5,24.3l-89.7-18l-30.8,103l-2.5,0.1c-50.3,2.2-95.5,17.4-128.7,40.7
- c-8.8-8.3-20.6-13.3-33.6-13.3c-27.3,0-49.5,22.5-49.5,50.2c0,19.6,11,36.5,27.1,44.8c-0.8,4.9-1.2,9.8-1.2,14.8
- C57.5,386.4,146.4,448,256,448s198.5-61.6,198.5-137.5c0-5-0.4-9.9-1.1-14.8C469.5,287.4,480.5,270.5,480.5,251z M65.8,271.1
- c-6.6-4.5-10.9-12.1-10.9-20.8c0-13.8,11.1-25.1,24.7-25.1c5.6,0,10.8,1.9,15,5.1C81.1,242.2,71.1,256,65.8,271.1z M389.3,109.1
- c0-9.2,7.4-16.8,16.5-16.8s16.5,7.5,16.5,16.8c0,9.2-7.4,16.8-16.5,16.8S389.3,118.4,389.3,109.1z M158.5,288.4
- c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8c0,17.6-14.2,31.8-31.8,31.8S158.5,306,158.5,288.4z M256,400
- c-47.6-0.2-76-28.5-77.2-29.7l12.6-12.4c0.2,0.2,23.7,24.2,64.6,24.4c40.3-0.2,64.2-24.2,64.5-24.4l12.6,12.4
- C331.9,371.5,303.6,399.8,256,400z M322.3,320.2c-17.6,0-31.8-14.2-31.8-31.8c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8
- C354.1,306,339.8,320.2,322.3,320.2z M446.4,271.5c-5.4-15.3-15.6-29.4-29.3-41.4c4.2-3.3,9.5-5.2,15.2-5.2
- c13.9,0,25.1,11.4,25.1,25.5C457.5,259.2,453.1,266.9,446.4,271.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss-outline.svg
deleted file mode 100644
index efca1cc8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M119.9,336.1c-30.8,0-55.9,25.1-55.9,55.8c0,30.8,25.1,55.6,55.9,55.6c30.9,0,55.9-24.9,55.9-55.6
- C175.8,361.2,150.8,336.1,119.9,336.1z M119.9,431.5c-22,0-39.9-17.8-39.9-39.6c0-21.9,17.9-39.8,39.9-39.8
- c22,0,39.9,17.9,39.9,39.8C159.8,413.7,141.9,431.5,119.9,431.5z"/>
- <path d="M64,192v79.9c48,0,94.1,14.2,128,48.1c33.9,33.9,48,79.9,48,128h80C320,308.1,204,192,64,192z M303.5,432h-48
- c-3.1-49.7-21-92.1-52.2-123.3C172.1,277.4,130,259.5,80,256.4v-47.8c26,1.8,52.1,8,76.7,18.5c28.5,12.2,54.2,29.6,76.4,51.8
- c22.2,22.2,39.6,47.9,51.8,76.4C295.5,379.9,301.7,405.6,303.5,432z"/>
- <path d="M64,64v79.9c171,0,303.9,133,303.9,304.1H448C448,236.3,276,64,64,64z M291.4,220.5C235.4,164.4,161,132,80,128.2V80.3
- C270,88.5,423.5,241.8,431.7,432h-48.2C379.7,351.1,347.3,276.5,291.4,220.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss.svg
deleted file mode 100644
index 487aa707..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-rss.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M119.9,336.1c-30.8,0-55.9,25.1-55.9,55.8c0,30.8,25.1,55.6,55.9,55.6c30.9,0,55.9-24.9,55.9-55.6
- C175.8,361.2,150.8,336.1,119.9,336.1z"/>
- <path d="M64,192v79.9c48,0,94.1,14.2,128,48.1c33.9,33.9,48,79.9,48,128h80C320,308.1,204,192,64,192z"/>
- <path d="M64,64v79.9c171,0,303.9,133,303.9,304.1H448C448,236.3,276,64,64,64z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-sass.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-sass.svg
deleted file mode 100644
index 08e1dfa8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-sass.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path fill="#231F20" d="M511.784,329.108c-1.67-13.599-9.236-24.146-20.795-32.416c2.857,2.04,5.275,3.766-0.055-0.041
- c-7.189-5.131-3.38-2.411-0.047-0.032c-28.5-20.301-65.676-15.789-96.733-4.511c-12.447-20.295-12.987-35.783-5.816-57.937
- c0.929-2.8,0.295-4.354-2.624-5.604c-7.086-3.03-17.291-1.427-24.422,0.463c-2.462,0.646-4.254,1.9-4.8,4.381
- c-5.154,24.243-21.009,46.448-34.828,66.886c-9.731-18.652-8.96-33.087-2.414-52.516c0.798-2.366,0.431-3.624-1.937-4.879
- c-7.26-3.757-18.401-1.912-25.8,0.276c-8.509,2.482-21.29,44.594-25.372,52.946c-8.531,17.442-16.091,44.665-30.585,58.502
- c-12.3-15.807,22.526-51.517,10.882-65.851c-3.938-4.848-11.063-4.723-15.586-0.616c1.085-7.608,1.648-12.609-0.32-19.063
- c-2.081-6.79-7.361-10.687-15.09-10.49c-17.995,0.527-33.843,13.815-44.641,26.397c-10.277,12.105-37.381,19.627-51.953,26.927
- c-25.032-21.807-79.221-44.947-80.632-82.081c-1.528-41.846,48.319-70.245,81.597-87.228
- c43.28-22.104,109.961-49.608,159.138-25.436c13.049,6.414,18.299,20.171,14.707,33.348c-9.368,34.366-47.198,57.293-80.103,67.807
- c-16.189,5.175-33.969,9.027-51.1,8.026c-22.955-1.343-40.83-15.224-43.281-16.086c-2.049-0.389-1.888,2.261-1.347,3.664
- c23.816,62.433,144.417,16.681,175.956-15.371c15.189-15.421,24.413-30.365,28.351-53.894c4.616-27.583-15.634-44.842-31.004-51.957
- C213.212,56.65,105.494,103.89,46.577,152.049c-25.568,20.901-57.552,54.11-42.874,88.946c15.93,37.805,64.736,57.19,96.503,80.312
- C74.502,334.08,42.344,347.29,25.688,371.24c-9.524,13.729-12.903,28.359-5.811,43.966c12.572,27.568,58.285,15.622,77.573,3.471
- c17.67-11.13,29.563-26.07,34.7-45.228c4.455-16.609,3.541-33.866-3.856-49.512l28.585-14.458
- c-7.697,23.076-11.097,52.003,4.881,72.855c6.402,8.338,23.017,8.675,29.817,0.311c8.816-10.943,14.664-24.655,20.503-37.206
- c-0.682,9.373-1.856,19.996,1.377,28.165c3.71,9.373,12.126,11.291,20.792,5.343c26.52-18.203,43.398-68.652,56.463-98.062
- c3.552,12.829,7.473,24.548,13.957,36.376c1.602,2.903,1.407,4.774-0.796,7.195c-9.685,10.675-32.826,28.479-35.069,42.899
- c-0.524,3.371,1.713,6.599,5.686,7.37c15.573,3.108,32.838-2.531,45.482-11.078c13.188-8.922,17.446-21.087,14.245-35.515
- c-4.576-20.771,10.993-43.98,25.801-61.03c2.719,12.908,6.816,25.331,14.143,36.606c-13.075,11.483-32.58,27.764-29.779,46.939
- c0.988,6.865,7.135,11.301,14.514,9.736c15.783-3.324,29.416-10.113,39.37-22.146c9.023-10.855,5.792-22.701,1.856-34.635
- c23.872-6.815,48.022-8.177,71.831-0.027c11.495,3.91,20.755,10.5,26.248,20.818c6.726,12.644,2.939,24.292-10.05,32.604
- c-3.287,2.104-5.562,3.833-4.45,4.743c1.112,0.911,4.9,2.113,13.284-3.152c8.384-5.267,13.51-12.383,14.823-21.725
- C512.071,334.28,512.063,331.696,511.784,329.108z M112.946,354.367c-1.358,16.673-9.636,30.193-23.175,41.114
- c-7.617,6.158-17.102,11.176-26.52,12.092c-9.418,0.917-16.751-1.461-17.378-11.23c-1.764-27.493,40.923-54.424,64.625-62.533
- c2.02,6.86,3.011,13.666,2.432,20.587L112.946,354.367z M216.048,281.914c-3.903,22.309-14.83,62.347-32.314,78.336
- c-2.356,2.143-4.61,2.018-5.809-0.771c-10.345-24.059,3.671-73.669,33.082-81.328C214.464,277.262,216.609,278.733,216.048,281.914z
- M286.359,363.682c8.422-8.962,16.834-17.916,25.269-26.927C312.671,346.776,294.057,366.719,286.359,363.682z M367.073,345.986
- c-2.348,1.273-7.621,2.515-7.827,0.835c-1.482-12.085,11.816-24.874,20.067-30.867C383.766,327.297,378.495,339.788,367.073,345.986
- z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype-outline.svg
deleted file mode 100644
index 27e3015a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype-outline.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M170.2,96c14,0,27.7,3.9,39.6,11.3l10.3,6.4l12-2c8.5-1.5,17.2-2.2,25.9-2.2c40.5,0,78.5,15.5,107,43.7
- c28.4,28,44.1,65.3,44.1,104.9c0,10.7-1.2,21.4-3.5,31.8l-2.5,11.1l5.1,10.2c5.1,10.1,7.7,20.9,7.7,32.2
- c0,40.1-33.3,72.7-74.2,72.7c-12.5,0-24.3-2.9-35.2-8.7l-9.8-5.2l-10.9,2c-9.1,1.7-18.5,2.5-27.8,2.5c-40.5,0-78.5-15.5-107-43.7
- c-28.4-28-44.1-65.3-44.1-104.9c0-10,1-20.1,3-29.9l2.5-12.2l-6.4-10.7C99.5,194.2,96,181.6,96,168.7C96,128.6,129.3,96,170.2,96
- M170.2,64C111.6,64,64,110.9,64,168.7c0,19.4,5.3,37.5,14.6,53c-2.4,11.7-3.7,23.9-3.7,36.3c0,99.8,82,180.6,183.1,180.6
- c11.5,0,22.7-1,33.5-3c15,7.9,32.1,12.4,50.2,12.4c58.7,0,106.2-46.9,106.2-104.7c0-16.7-4-32.5-11.1-46.5
- c2.8-12.5,4.2-25.4,4.2-38.7c0-99.7-82-180.6-183.2-180.6c-10.7,0-21.1,0.9-31.3,2.6C210.3,69.9,191,64,170.2,64L170.2,64z"/>
- <path d="M351.9,344.1c-8.5,11.8-21,21.2-37.2,27.8c-16.1,6.6-35.3,9.9-57.3,9.9c-26.3,0-48.3-4.6-65.6-13.6
- c-12.3-6.6-22.4-15.4-30.2-26.4c-7.8-11-11.7-22-11.7-32.6c0-6.6,2.6-12.3,7.6-17.1c5-4.6,11.5-7,19.1-7c6.3,0,11.7,1.8,16.1,5.5
- c4.2,3.5,7.8,8.7,10.7,15.5c3.3,7.3,6.8,13.5,10.6,18.4c3.6,4.7,8.7,8.6,15.3,11.7c6.7,3.1,15.6,4.7,26.6,4.7
- c15.1,0,27.5-3.2,36.8-9.5c9.2-6.1,13.6-13.5,13.6-22.5c0-7.1-2.3-12.7-7.1-17.1c-5-4.6-11.5-8.2-19.6-10.6
- c-8.3-2.6-19.6-5.3-33.6-8.2c-19-4-35.1-8.8-48-14.2c-13.1-5.5-23.7-13.2-31.5-22.7C159,226.5,155,214.3,155,200
- c0-13.7,4.2-25.9,12.4-36.5c8.2-10.5,20.1-18.7,35.6-24.3c15.2-5.6,33.3-8.4,53.7-8.4c16.4,0,30.7,1.9,42.7,5.5
- c12.1,3.7,22.2,8.7,30.3,14.9c8,6.2,14,12.8,17.8,19.7c3.8,7,5.7,13.9,5.7,20.6c0,6.4-2.5,12.3-7.5,17.4c-5,5.1-11.3,7.8-18.8,7.8
- c-6.8,0-12.1-1.6-15.8-4.8c-3.4-3-7-7.6-10.9-14.3c-4.6-8.5-10.1-15.3-16.4-20.1c-6.2-4.6-16.4-7-30.6-7c-13.1,0-23.8,2.6-31.7,7.7
- c-7.6,4.9-11.3,10.6-11.3,17.3c0,4.1,1.2,7.5,3.7,10.5c2.6,3.1,6.2,5.9,10.9,8.2c4.8,2.4,9.8,4.3,14.7,5.6
- c5.1,1.4,13.6,3.5,25.3,6.1c14.9,3.1,28.5,6.7,40.5,10.4c12.2,3.9,22.7,8.6,31.3,14.1c8.8,5.6,15.7,12.9,20.7,21.5
- c4.9,8.6,7.4,19.4,7.4,31.8C364.7,318.7,360.4,332.3,351.9,344.1z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype.svg
deleted file mode 100644
index 810a7210..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-skype.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M436.9,296.8c2.8-12.5,4.2-25.4,4.2-38.7c0-99.7-82-180.6-183.2-180.6c-10.7,0-21.1,0.9-31.3,2.6
- C210.3,69.9,191,64,170.2,64C111.6,64,64,110.9,64,168.7c0,19.4,5.3,37.5,14.6,53c-2.4,11.7-3.7,23.9-3.7,36.3
- c0,99.8,82,180.6,183.1,180.6c11.5,0,22.7-1,33.5-3c15,7.9,32.1,12.4,50.2,12.4c58.7,0,106.2-46.9,106.2-104.7
- C448,326.6,444,310.8,436.9,296.8z M351.9,344.3c-8.5,11.8-21,21.2-37.2,27.8c-16.1,6.6-35.3,9.9-57.3,9.9
- c-26.3,0-48.3-4.6-65.6-13.6c-12.3-6.6-22.4-15.4-30.2-26.4c-7.8-11-11.7-22-11.7-32.6c0-6.6,2.6-12.3,7.6-17.1c5-4.6,11.5-7,19.1-7
- c6.3,0,11.7,1.8,16.1,5.5c4.2,3.5,7.8,8.7,10.7,15.5c3.3,7.3,6.8,13.5,10.6,18.4c3.6,4.7,8.7,8.6,15.3,11.7
- c6.7,3.1,15.6,4.7,26.6,4.7c15.1,0,27.5-3.2,36.8-9.5c9.2-6.1,13.6-13.5,13.6-22.5c0-7.1-2.3-12.7-7.1-17.1
- c-5-4.6-11.5-8.2-19.6-10.6c-8.3-2.6-19.6-5.3-33.6-8.2c-19-4-35.1-8.8-48-14.2c-13.1-5.5-23.7-13.2-31.5-22.7
- c-7.9-9.7-11.8-21.9-11.8-36.2c0-13.7,4.2-25.9,12.4-36.5c8.2-10.5,20.1-18.7,35.6-24.3c15.2-5.6,33.3-8.4,53.7-8.4
- c16.4,0,30.7,1.9,42.7,5.5c12.1,3.7,22.2,8.7,30.3,14.9c8,6.2,14,12.8,17.8,19.7c3.8,7,5.7,13.9,5.7,20.6c0,6.4-2.5,12.3-7.5,17.4
- c-5,5.1-11.3,7.8-18.8,7.8c-6.8,0-12.1-1.6-15.8-4.8c-3.4-3-7-7.6-10.9-14.3c-4.6-8.5-10.1-15.3-16.4-20.1c-6.2-4.6-16.4-7-30.6-7
- c-13.1,0-23.8,2.6-31.7,7.7c-7.6,4.9-11.3,10.6-11.3,17.3c0,4.1,1.2,7.5,3.7,10.5c2.6,3.1,6.2,5.9,10.9,8.2
- c4.8,2.4,9.8,4.3,14.7,5.6c5.1,1.4,13.6,3.5,25.3,6.1c14.9,3.1,28.5,6.7,40.5,10.4c12.2,3.9,22.7,8.6,31.3,14.1
- c8.8,5.6,15.7,12.9,20.7,21.5c4.9,8.6,7.4,19.4,7.4,31.8C364.8,318.9,360.5,332.5,351.9,344.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat-outline.svg
deleted file mode 100644
index 773d5d76..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat-outline.svg
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M256.283,47.553c70.693,0,128,54.682,118,128.931c-2.072,15.388-3.422,31.483-4.26,44.759c0,0,2.402,4.253,12.664,4.253
- c6.071,0,14.895-1.543,27.596-6.354c2.236-0.847,4.377-1.241,6.377-1.241c7.918,0,13.615,5.931,14.123,12.271
- c0.426,5.31-4.564,11.199-8.371,13.009c-13.766,6.542-46.991,10.063-46.991,32.638c0,22.576,22.362,46.656,40.862,63.713
- S480,360.602,480,360.602s0.283,21.57-31.717,29.097c-32,7.524-32.1,5.712-33.25,13.796c-2.133,14.979-1.535,21.378-11.248,21.378
- c-1.672,0-3.651-0.19-6.002-0.558c-8.23-1.291-19.239-3.644-31.121-3.644c-11.216,0-23.21,2.097-34.379,9.161
- c-23,14.549-41.283,34.114-76.283,34.114s-53-19.565-76-34.114c-11.17-7.065-23.162-9.161-34.379-9.161
- c-11.88,0-22.892,2.353-31.121,3.644c-2.352,0.367-4.33,0.558-6.002,0.558c-9.71,0-9.115-6.399-11.248-21.378
- c-1.151-8.084-1.25-6.27-33.25-13.795s-32-29.097-32-29.097s45.5-4.012,64-21.068c18.5-17.058,40.862-41.134,40.862-63.71
- c0-22.575-33.226-26.09-46.991-32.632c-3.807-1.81-8.796-7.687-8.371-12.997c0.507-6.336,6.196-12.251,14.107-12.25
- c2.004,0,4.152,0.38,6.393,1.229c12.749,4.829,21.588,6.342,27.662,6.342c10.204,0,12.598-4.273,12.598-4.273
- c-0.837-13.275-2.187-29.371-4.259-44.759c-10-74.249,47.307-128.931,118-128.931l0,0 M256.283,32H256
- c-41.093,0-79.215,16.208-104.591,45.341c-23.982,27.534-34.375,63.345-29.265,101.292c1.416,10.51,2.46,21.231,3.21,30.618
- c-3.97-0.559-9.686-1.998-17.703-5.034c-3.965-1.502-8.017-2.295-12.043-2.295c-15.641-0.001-28.844,11.852-30.057,27.003
- c-1.027,12.818,8.235,24.393,17.47,28.783c4.251,2.02,9.181,3.578,14.4,5.232c6.707,2.125,14.309,4.532,19.293,7.703
- c4.147,2.639,4.147,4.168,4.147,5.182c0,8.66-6.191,24.691-35.688,51.888c-10.499,9.681-39.055,15.501-54.588,16.897l-14.572,1.311
- L16,360.603c0,1.679,0.312,10.546,6.485,20.319c5.246,8.306,16.073,19.283,37.863,24.407c6.179,1.453,11.186,2.563,15.208,3.454
- c2.306,0.512,4.555,1.01,6.454,1.453c0.027,0.209,0.054,0.417,0.081,0.623c0.9,7.004,1.611,12.535,4.392,17.75
- c2.453,4.6,8.574,12.316,22.015,12.316c2.478,0,5.249-0.246,8.472-0.751c1.672-0.263,3.386-0.554,5.2-0.863
- c7.116-1.212,15.182-2.587,23.451-2.587c10.277,0,18.732,2.188,25.846,6.688c4.531,2.867,8.892,5.972,13.509,9.26
- C202.967,465.481,223.358,480,256,480c32.726,0,53.293-14.582,71.439-27.446c4.576-3.244,8.898-6.309,13.377-9.142
- c7.113-4.5,15.568-6.688,25.846-6.688c8.27,0,16.334,1.375,23.449,2.586c1.814,0.311,3.529,0.602,5.202,0.864
- c3.223,0.505,5.993,0.751,8.472,0.751c13.44,0,19.562-7.715,22.015-12.313c2.781-5.214,3.492-10.746,4.392-17.749
- c0.027-0.208,0.055-0.418,0.082-0.629c1.898-0.441,4.148-0.941,6.455-1.452c4.023-0.892,9.029-2.001,15.206-3.454
- c21.851-5.139,32.611-16.17,37.79-24.518c6.098-9.828,6.296-18.736,6.273-20.422l-0.189-14.501l-14.398-1.278
- c-15.413-1.396-43.8-7.219-54.301-16.9c-16.281-15.011-35.688-36.199-35.688-51.893c0-1.014,0-2.546,4.15-5.186
- c4.985-3.174,12.589-5.584,19.297-7.71c5.217-1.654,10.144-3.217,14.394-5.236c9.236-4.39,18.498-15.978,17.471-28.807
- c-1.215-15.166-14.424-27.046-30.072-27.046c-4.021,0-8.068,0.76-12.027,2.259c-8.027,3.041-13.743,4.41-17.705,4.962
- c0.747-9.319,1.791-20.12,3.211-30.67c5.111-37.948-5.281-73.509-29.264-101.042C335.498,48.208,297.376,32,256.283,32L256.283,32z
- "/>
- <path d="M256,229c-20.838,0-40.604-8.29-55.657-23.343c-3.125-3.124-3.124-8.189,0-11.313c3.125-3.124,8.19-3.124,11.313,0
- C223.688,206.374,239.436,213,256,213c16.387,0,32.15-6.64,44.385-18.698c3.148-3.102,8.213-3.063,11.312,0.082
- c3.102,3.147,3.064,8.212-0.082,11.313C296.368,220.725,276.617,229,256,229z"/>
- <ellipse cx="208" cy="152" rx="16" ry="24"/>
- <ellipse cx="304" cy="152" rx="16" ry="24"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat.svg
deleted file mode 100644
index 3cfb04fb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-snapchat.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M495.998,360.389l-0.189-14.501l-14.398-1.278c-15.413-1.396-43.8-7.219-54.301-16.9
- c-16.281-15.011-35.688-36.199-35.688-51.893c0-1.014,0-2.546,4.15-5.186c4.985-3.174,12.589-5.584,19.297-7.71
- c5.217-1.654,10.144-3.217,14.394-5.236c9.236-4.39,18.498-15.978,17.471-28.807c-1.215-15.166-14.424-27.046-30.072-27.046
- c-4.021,0-8.068,0.76-12.027,2.259c-8.027,3.041-13.743,4.41-17.705,4.962c0.747-9.319,1.791-20.12,3.211-30.67
- c5.111-37.948-5.281-73.509-29.264-101.042C335.498,48.208,297.376,32,256.283,32H256c-41.093,0-79.215,16.208-104.591,45.341
- c-23.982,27.534-34.375,63.345-29.265,101.292c1.416,10.51,2.46,21.231,3.21,30.618c-3.97-0.559-9.686-1.998-17.703-5.034
- c-3.965-1.502-8.017-2.295-12.043-2.295c-15.641-0.001-28.844,11.852-30.057,27.003c-1.027,12.818,8.235,24.393,17.47,28.783
- c4.251,2.02,9.181,3.578,14.4,5.232c6.707,2.125,14.309,4.532,19.293,7.703c4.147,2.639,4.147,4.168,4.147,5.182
- c0,8.66-6.191,24.691-35.688,51.888c-10.499,9.681-39.055,15.501-54.588,16.897l-14.572,1.311L16,360.603
- c0,1.679,0.312,10.546,6.485,20.319c5.246,8.306,16.073,19.283,37.863,24.407c6.179,1.453,11.186,2.563,15.208,3.454
- c2.306,0.512,4.555,1.01,6.454,1.453c0.027,0.209,0.054,0.417,0.081,0.623c0.9,7.004,1.611,12.535,4.392,17.75
- c2.453,4.6,8.574,12.316,22.015,12.316c2.478,0,5.249-0.246,8.472-0.751c1.672-0.263,3.386-0.554,5.2-0.863
- c7.116-1.212,15.182-2.587,23.451-2.587c10.277,0,18.732,2.188,25.846,6.688c4.531,2.867,8.892,5.972,13.509,9.26
- C202.967,465.481,223.358,480,256,480c32.726,0,53.293-14.582,71.439-27.446c4.576-3.244,8.898-6.309,13.377-9.142
- c7.113-4.5,15.568-6.688,25.846-6.688c8.27,0,16.334,1.375,23.449,2.586c1.814,0.311,3.529,0.602,5.202,0.864
- c3.223,0.505,5.993,0.751,8.472,0.751c13.44,0,19.562-7.715,22.015-12.313c2.781-5.214,3.492-10.746,4.392-17.749
- c0.027-0.208,0.055-0.418,0.082-0.629c1.898-0.441,4.148-0.941,6.455-1.452c4.023-0.892,9.029-2.001,15.206-3.454
- c21.851-5.139,32.611-16.17,37.79-24.518C495.822,370.982,496.021,362.074,495.998,360.389z M208,128c8.836,0,16,10.745,16,24
- s-7.164,24-16,24s-16-10.745-16-24S199.164,128,208,128z M311.615,205.698C296.368,220.725,276.617,229,256,229
- c-20.838,0-40.604-8.29-55.657-23.343c-3.125-3.124-3.124-8.189,0-11.313c3.125-3.124,8.19-3.124,11.313,0
- C223.688,206.374,239.436,213,256,213c16.387,0,32.15-6.64,44.385-18.698c3.148-3.102,8.213-3.063,11.312,0.082
- C314.799,197.531,314.762,202.597,311.615,205.698z M304,176c-8.836,0-16-10.746-16-24s7.164-24,16-24s16,10.746,16,24
- S312.836,176,304,176z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr-outline.svg
deleted file mode 100644
index 9f327c28..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M321.2,396.3c-11.8,0-22.4-2.8-31.5-8.3c-6.9-4.1-11.5-9.6-14-16.4c-2.6-6.9-3.6-22.3-3.6-46.4V224h96v-64h-96V48h-61.9
- c-2.7,21.5-7.5,44.7-14.5,58.6s-14,25.8-25.6,35.7c-11.6,9.9-25.6,17.9-41.9,23.3V224h48v140.4c0,19,2,33.5,5.9,43.5
- c4,10,11.1,19.5,21.4,28.4c10.3,8.9,22.8,15.7,37.3,20.5c14.6,4.8,31.4,7.2,50.4,7.2c16.7,0,30.3-1.7,44.7-5.1
- c14.4-3.4,30.5-9.3,48.2-17.6v-65.6C363.2,389.4,342.3,396.3,321.2,396.3z M368,431c-13.1,5.7-25.1,9.9-35.9,12.4
- c-13.1,3.1-25.6,4.6-41.1,4.6c-17.2,0-32.5-2.2-45.4-6.4c-12.5-4.1-23.2-10-31.9-17.5c-8.3-7.2-14-14.6-17-22.2
- c-2.2-5.5-4.8-16.6-4.8-37.6V208H144v-31.3c13.4-5.6,25.5-13,36.3-22.2c13.2-11.2,21.6-24.9,29.6-40.7c7.1-14,11.6-34,14.1-49.8h32
- v112h96v32h-96v117.1c0,34.6,2.4,46,4.6,52c3.8,10.3,10.8,18.6,21,24.6c11.7,7,25,10.5,39.7,10.5c15.7,0,31.3-3.3,46.7-9.8V431z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr.svg
deleted file mode 100644
index 3cd85083..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tumblr.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M321.2,396.3c-11.8,0-22.4-2.8-31.5-8.3c-6.9-4.1-11.5-9.6-14-16.4c-2.6-6.9-3.6-22.3-3.6-46.4V224h96v-64h-96V48h-61.9
- c-2.7,21.5-7.5,44.7-14.5,58.6c-7,13.9-14,25.8-25.6,35.7c-11.6,9.9-25.6,17.9-41.9,23.3V224h48v140.4c0,19,2,33.5,5.9,43.5
- c4,10,11.1,19.5,21.4,28.4c10.3,8.9,22.8,15.7,37.3,20.5c14.6,4.8,31.4,7.2,50.4,7.2c16.7,0,30.3-1.7,44.7-5.1
- c14.4-3.4,30.5-9.3,48.2-17.6v-65.6C363.2,389.4,342.3,396.3,321.2,396.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tux.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tux.svg
deleted file mode 100644
index 2fb3e4e2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-tux.svg
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path fill="#010101" d="M254.7,101.3c-0.6,1-1.2,2-1.7,3.1c1.8-3.5,4.3-6.5,7.4-8.7C258.3,97,256.3,98.8,254.7,101.3
- C254.1,102.3,256.3,98.8,254.7,101.3z"/>
- <path fill="#010101" d="M426.3,396c-6.7-4-13.2-11-12-18.8c2.3-15.3,2.5-21.5-0.2-25.8c-1.899-3.2-5.5-5-8.6-5.801
- c2-2.5,3.1-5.399,3.8-10.899c1.842-14.168-3.239-30.67-6.61-44.243c-4.445-17.9-10.319-34.014-20.432-49.522
- c-16.489-25.288-37.253-46.804-51.857-73.435c-9.7-29-4.301-47.1-4.801-66.2C324.7,64,298.7,32,261,32h-14c-37.5,0-58,26.9-58,60
- c0.697,16.666,1.352,33.333,2,50c0.769,19.756,1.98,37.667-8,55.3c-7.033,12.488-19.571,22.43-28.592,33.478
- c-9.525,11.665-13.06,23.669-17.859,37.619c-5.987,17.401-21.275,30.906-24.886,48.929c-1.658,8.271,2.726,17.857-0.83,24.693
- c-3.698,7.109-0.813,14.469-2.833,21.682c-3.505,11.729-20.731,10.729-30.215,11.508c-17.602,1.443-11.051,17.988-7.843,29.701
- c5.598,20.435-19.54,42.078,11.032,50.471c13.989,3.84,28.586,5.13,42.727,8.32c13.981,3.154,26.917,8.612,40.396,13.262
- c10.469,3.611,20.262,4.146,30.323-1.232c10.982-5.87,18.947-15.083,31.691-17c24.707-3.716,54.829-4.169,79.373,0.63
- c7.507,1.468,10.075,6.525,14.905,11.766c8.145,8.838,21.514,10.125,32.794,8.22c11.89-2.01,20.846-9.466,29.686-17.112
- c12.526-10.835,26.137-17.996,40.791-25.547c7.439-3.833,22.178-9.388,24.159-18.903C450.151,406.573,433.642,400.383,426.3,396z
- M202,451.3c-1.3,13-13.9,20.3-25.4,19.3c-19.502-1.649-37.86-12.237-57.164-15.75c-9.393-1.709-47.351-3.173-46.943-17.079
- c0.215-7.361,5.751-11.666,7.567-18.415c2.811-10.449-5.753-19.932-6.32-30.16c-0.447-8.081,10.73-7.607,16.288-8.053
- c8.761-0.702,19.157-2.012,23.572-11.043c1.6-3.3-0.5-15,1.9-21.8c3.527-10.155,15.489-8.949,23.3-4.899
- c17.762,9.067,28.943,35.546,38.533,51.821C187.058,411.728,204.045,430.843,202,451.3z M318.3,385.7
- c2.289,11.787,4.224,24.387,1.7,36.3c-2.016,9.516-8.562,15.614-12.7,24c-2.2-6.8,11.3-16.7,9.8-33.7
- c-0.042-0.475-0.947-10.882-1.036-10.834c-1.979,1.082-3.825,5.075-5.304,6.73c-4.809,5.383-10.771,9.658-16.729,13.677
- c-13.797,9.306-29.221,15.058-45.83,16.627c-21,2-38-10.5-38-10.5c2.517,8.305,8.992,21,1.1,28.3
- c1.743-15.648-4.876-28.06-11.6-41.7c46.374-24.639-41.363-64.397-53-79.8c-10.476-13.896-5.553-31.83-2.7-43.5
- c-3.443,13.775-3.959,41.956,14,46.8c7.922,2.169,5.605-37.071,5.984-41.463c1.58-18.312,7.721-35.997,18.343-51.015
- c3.399-4.806,1.863-9.533,2.673-15.322c1.693-10.668,7.295-20.547,13.488-29.225c5.169-7.243,1.735-12.618,3.014-21.055
- c0.727-4.795,5.118,3.193,5.798,4.279c4,6.5,16.7,22.7,24.7,22c13.277-1.161,24.692-15.938,36.015-22.046
- c3.591-1.937,14.41-5.242,15.866-9.632c1.768-5.33-12.666-0.161-14.114,0.583c-10.782,5.535-31.018,21.448-43.867,15.295
- c-8.762-4.195-10.691-14.994-17.2-20.5c15.4,13.6,21.5,10.5,27.6,9.1c9.665-2.182,18.797-6.486,27.8-10.5
- c4.217-1.88,20.107-4.041,22.301-8.7c2.745-5.834-5.05-6.726-8.068-3.58c-6.251,6.515-15.853,8.981-24.097,11.787
- c-18.885,6.427-37.644,9.131-51.835-8.607c-8.354-10.212,15.558-22.504,22.2-28.8c0,0,1-7.2-0.6-12.7c-1.9-6.5-7.8-9.3-11.9-8.1
- c-4.1,1.1-8,5.5-6.8,14.8c1,8.3,7,11,7,11s-2.7,3.5-5.2,4.7c0,0-0.8-0.3-3.5-6.3c-2.7-6-6.6-19.5-0.3-31.1
- c6.3-11.6,19.6-5.2,23.8,3.8c3.9,8.3,2.4,22.7,2.4,22.7c3.358-0.843,6.835-1.3,10.3-1.3c4.242,0,6.814,4.563,10.6,4.8
- c-0.635,0-0.564-18.124-0.233-20.078c1.099-6.49,4.112-13.619,9.933-17.222c16.087-11.491,34.6,3.916,34.6,21.2
- c0.024,4.486-0.137,9.215-1.199,13.6c-0.659,2.637-1.582,8.469-5.114,9.177c-1.145,0.23-10.683-0.431-7.985-3.277
- c12.807-12.812-1.822-38.207-17.4-24.5c-5.601,4.199-5.483,13.833-4.801,20c1.098,9.141,20.51,11.541,26.852,13.78
- c8.224,2.903,7.943,9.626,6.679,17.116c-1.9,11.26-2.815,18.792,4.381,28.214c7.344,9.616,12.929,20.086,15.915,31.878
- c1.483,5.859,1.665,10.843,5.621,15.57c5.983,7.151,10.619,14.805,13.291,23.817c5.225,17.621,6.513,35.422,6.162,53.625
- c-0.5,8.199-2.1,15,8.3,9.699c4-2,6.5-2.899,11-3.699c3.101-6.301,4.4-18.301,4.5-24.301c0.2-13.5-0.3-41.5-27.699-71.5
- c0,0,28.5,21.7,33,62c2.5,22.301-2,34.4-2,34.4c5.3,1.3,10.8,5.3,13.6,9.8c-0.133-0.22,1.038,1.748,1.179,1.864
- c-9.811-8.171-31.708-12.859-39.679,0.236c-2,3.3-3.1,7.6-3.2,11.699c-7.1-1.199-12.399,0-16.8,4.9
- C313.5,358.1,316.3,375.3,318.3,385.7C320.3,396,316.3,375.3,318.3,385.7z M220.6,124.9c-0.2-4.9-2.1-9-4.7-10.8
- c0.3-0.3,0.8-0.7,1.7-0.4c1.4,0.4,3.5,2.7,4.3,6.3c0.7,2.9,0.4,7.7-1.4,7.7C220.498,126.766,220.531,125.833,220.6,124.9
- C220.4,120,220.6,125.8,220.6,124.9z M275.3,112.9c0.4-0.3,1.101-0.6,2.3-0.3c1.801,0.4,4.4,2.8,5.301,6.2
- c0.699,2.8,0.1,7.4-2.2,7.3c-0.005-0.903,0.062-1.803,0.2-2.7C280.8,118.8,278.6,114.8,275.3,112.9
- C275.7,112.6,278.6,114.8,275.3,112.9z M412.4,432.9c-17.504,7.553-31.304,19.968-47.117,30.19
- c-13.824,8.937-38.156,8.313-40.022-12.879c-1.565-17.776,4.184-35.288,1.84-53.357c-1.587-12.239-8.534-28.906-2.301-40.854
- c2.7-5.1,8.101-5.5,12.5-4c3.193,13.267,13.932,23.6,28,23.6c17.031,0,23.542-14.008,34-24.5c3.4,0.2,7.4,1.101,8.8,4.801
- c2.301,5.8-1.899,17.5-1.8,22.3c0.3,15.7,9,19.2,26.4,29C448,416,436.9,422.3,412.4,432.9C388.3,443.3,436.9,422.3,412.4,432.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch-outline.svg
deleted file mode 100644
index 9f85d6a2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch-outline.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <g>
- <path d="M80,32l-32,80v304h96v64h64l64-64h80l112-112V32H80z M416,288l-64,64h-96.001L192,416v-64h-80V80h304V288z"/>
- </g>
- <rect x="320" y="143" width="48" height="129"/>
- <rect x="208" y="143" width="48" height="129"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch.svg
deleted file mode 100644
index b3cf6a74..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitch.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M80,32l-32,80v304h96v64h64l64-64h80l112-112V32H80z M256,272h-48V143h48V272z M368,272h-48V143h48V272z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter-outline.svg
deleted file mode 100644
index cb687a71..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter-outline.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M492,109.5c-17.4,7.7-36,12.9-55.6,15.3c20-12,35.4-31,42.6-53.6c-18.7,11.1-39.4,19.2-61.5,23.5
- C399.8,75.8,374.5,64,346.8,64c-53.5,0-96.8,43.4-96.8,96.9c0,7.6,0.8,15,2.5,22.1C172,179,100.5,140.4,52.8,81.7
- c-8.3,14.3-13.1,31-13.1,48.7c0,33.6,17.1,63.3,43.1,80.7C67,210.7,52,206.3,39,199c0,0.4,0,0.8,0,1.2c0,47,33.4,86.1,77.7,95
- c-8.1,2.2-16.7,3.4-25.5,3.4c-6.2,0-12.3-0.6-18.2-1.8c12.3,38.5,48.1,66.5,90.5,67.3c-33.1,26-74.9,41.5-120.3,41.5
- c-7.8,0-15.5-0.5-23.1-1.4C62.8,432,113.7,448,168.3,448C346.5,448,444,300.3,444,172.2c0-4.2-0.1-8.4-0.3-12.5
- C462.5,146,479,129,492,109.5z M434.2,146.7l-7,5.1l0.4,8.6c0.2,3.8,0.3,7.8,0.3,11.8c0,30.2-5.9,61.8-17,91.5
- c-11.7,31.2-28.5,59.4-50,83.8c-23,26.1-50.2,46.5-81.1,60.8c-33.8,15.7-71.3,23.6-111.5,23.6c-28.9,0-57.4-4.8-84.5-14.2
- c9.9-1.9,19.6-4.6,29.1-7.9c21.7-7.6,41.9-18.7,60.1-33l35.3-27.7l-44.9-0.8c-26.1-0.5-49.7-13.4-64.3-33.9
- c7.3-0.5,14.5-1.8,21.5-3.7l60.7-20.2l-61.7-10.9c-29.6-5.9-52.8-27.9-61.3-55.8c7.8,2,15.4,2.8,23.9,3.3c0,0,31.8,1.4,55.8-0.1
- c-13-6.2-46.4-29.2-46.4-29.2c-22.5-15.1-36-40.2-36-67.4c0-6.4,0.8-12.8,2.2-19c21.9,22.4,47,41.1,75.1,55.5
- c37,19.1,76.9,29.8,118.6,31.9l21.2,1.1l-4.8-20.7c-1.4-5.9-2.1-12.1-2.1-18.5c0-44.4,36.3-80.7,80.9-80.7c22.3,0,43.8,9.3,59,25.6
- l6.1,6.5l8.7-1.7c4.5-0.9,8.9-1.9,13.3-3.1c-1,1.4-5.7,6.1-11,10.8c-4.5,4-17.8,16.5-17.8,16.5s13,4.1,21.1,5
- c8.1,0.9,17.4-0.6,18.9-0.8C442.2,141.1,437.2,144.6,434.2,146.7z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter.svg
deleted file mode 100644
index c9fb08a8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-twitter.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M492,109.5c-17.4,7.7-36,12.9-55.6,15.3c20-12,35.4-31,42.6-53.6c-18.7,11.1-39.4,19.2-61.5,23.5
- C399.8,75.8,374.6,64,346.8,64c-53.5,0-96.8,43.4-96.8,96.9c0,7.6,0.8,15,2.5,22.1c-80.5-4-151.9-42.6-199.6-101.3
- c-8.3,14.3-13.1,31-13.1,48.7c0,33.6,17.2,63.3,43.2,80.7C67,210.7,52,206.3,39,199c0,0.4,0,0.8,0,1.2c0,47,33.4,86.1,77.7,95
- c-8.1,2.2-16.7,3.4-25.5,3.4c-6.2,0-12.3-0.6-18.2-1.8c12.3,38.5,48.1,66.5,90.5,67.3c-33.1,26-74.9,41.5-120.3,41.5
- c-7.8,0-15.5-0.5-23.1-1.4C62.8,432,113.7,448,168.3,448C346.6,448,444,300.3,444,172.2c0-4.2-0.1-8.4-0.3-12.5
- C462.6,146,479,129,492,109.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd-outline.svg
deleted file mode 100644
index 0bf1882a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd-outline.svg
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M220.746,102.625c-7.788,1.683-17.44,4.813-24.641,8.529c-9.018,4.649-16.411,10.965-22.604,19.295
- c-6.706,9.002-10.105,19.989-10.105,32.657c0,17.916,6.197,32.288,18.405,42.702c9.334,7.983,21.504,14.431,36.687,19.165
- L240,230.667V100.244C240,100.244,231.766,100.244,220.746,102.625z M224,209.699c-12-3.743-23.912-9.088-32.051-16.048
- c-8.621-7.355-12.673-17.534-12.673-30.545c0-9.241,2.414-16.94,7.004-23.102c4.58-6.161,9.912-11.038,16.88-14.631
- c6.18-3.189,13.84-5.565,20.84-7.138V209.699z"/>
- <path d="M348.217,296.725c-8.432-8.289-18.002-14.296-28.414-17.84c-8.949-3.075-17.441-5.848-27.465-8.477L272,265.145v145.188
- c0,0,12.051-0.642,18.371-1.476s10.703-1.971,16.67-3.798c12.727-3.89,23.309-9.02,31.32-15.25
- c8.678-6.747,15.145-14.785,19.164-23.907c3.775-8.595,5.706-17.581,5.706-26.711C363.231,320.822,358.188,306.536,348.217,296.725
- z M342.902,359.471c-2.939,6.673-7.699,12.576-14.303,17.711c-6.602,5.133-15.744,9.328-26.377,12.577
- c-4.5,1.378-8.223,2.444-14.223,3.236v-107.11c10,2.624,18.18,5.332,26.326,8.131c8.062,2.744,15.748,7.443,22.537,14.116
- c6.785,6.676,10.309,17.03,10.309,31.06C347.172,346.042,345.834,352.797,342.902,359.471z"/>
- <path d="M411.387,303.256c-3.119-9.577-7.891-18.561-14.301-26.952c-6.422-8.382-14.396-15.826-23.93-22.331
- c-9.539-6.498-20.721-11.63-33.553-15.4c-5.143-1.363-14.189-3.506-26.104-6.418c-8.516-2.074-16.5-4.2-25.5-6.367V120.065
- c9,2.396,15.252,6.202,21.926,10.43c14.279,9.04,23.232,24.505,25.855,45.505h69.174c-0.654-18-4.65-32.76-11.996-46.02
- c-8.07-14.543-18.977-27.024-32.73-36.956c-13.75-9.922-30.225-17.49-48.377-22.455C303.967,68.416,297,66.605,288,65.386V32h-64
- v33.167c-7,1.044-15.148,2.445-22.426,4.25c-17.242,4.283-32.388,10.868-45.951,19.764c-13.571,8.905-24.352,20.112-32.604,33.627
- c-8.251,13.523-12.312,29.52-12.312,48c0,9.585,1.407,18.993,4.157,28.235c2.752,9.241,7.442,17.967,14.042,26.181
- c6.603,8.214,15.495,15.658,26.687,22.332c11.183,6.672,24.705,12.064,41.576,16.171c9.287,2.345,18.83,4.534,26.83,6.576v119.586
- c-11-2.919-21.889-7.399-30.678-13.479c-9.17-6.327-16.066-13.953-21.198-23.884c-4.779-9.229-7.073-20.526-7.407-32.526H96
- c0.695,21,5.25,39.494,13.672,55.371c8.799,16.604,20.533,29.96,35.204,40.562c14.662,10.613,31.393,18.356,51.198,23.491
- c8.885,2.304,18.926,3.96,27.926,5.23V480h64v-34.54c10-1.069,18.957-2.69,28.527-4.879c18.701-4.273,35.645-11.036,50.316-20.276
- c14.662-9.24,26.621-21.128,35.611-35.681c8.98-14.541,13.545-32.085,13.545-52.619C416,322.427,414.498,312.841,411.387,303.256z
- M388.904,376.218c-7.623,12.34-17.873,22.619-30.457,30.55c-13.035,8.21-28.248,14.339-45.219,18.217
- c-9.059,2.071-17.285,3.564-26.654,4.566L272,431.08V464h-32v-33.244l-13.508-1.943c-9.256-1.307-18.671-2.968-26.271-4.938
- c-17.865-4.633-32.876-11.51-46.031-21.032c-12.845-9.283-22.77-20.551-30.408-34.967c-5.004-9.437-8.418-20.876-10.268-31.876
- h36.714c1.529,8,4.162,16.837,7.804,23.869c6.324,12.239,14.979,21.914,26.441,29.823c10.145,7.017,23.81,12.64,35.676,15.724
- S240,408.667,240,408.667V257.874l-11.786-3.074c-4.952-1.263-11.074-2.583-16.558-3.96c-3.395-0.854-6.814-1.729-10.37-2.626
- l-0.033-0.017l-0.051-0.017c-14.952-3.64-27.533-8.472-37.411-14.365c-9.487-5.657-17.021-11.92-22.399-18.611
- c-5.271-6.56-9.029-13.533-11.17-20.722c-2.307-7.755-3.476-15.721-3.476-23.675c0-15.66,3.274-28.636,10.002-39.665
- c7.097-11.622,16.187-20.973,27.786-28.585c12.201-8.003,25.666-13.764,41.155-17.611c6.334-1.571,12.865-2.901,19.926-3.954
- L240,78.958V48h32v31.363l13.127,1.877c7.371,0.999,14.236,2.404,22.637,4.699c16.389,4.482,30.91,11.189,43.023,19.929
- c11.691,8.443,21.182,19.333,28.133,31.862c3.805,6.865,6.504,14.27,8.137,22.27h-38.119c-5.078-19-15.352-33.637-30.172-43.021
- c-9.254-5.861-17.561-9.215-27.373-12.251C281.766,101.75,272,101.25,272,101.25v137.142l12.529,2.951
- c7.631,1.837,14.184,3.644,21.453,5.415l3.92,0.938l0.812,0.19c11.373,2.78,19.651,4.799,24.558,6.096
- c11.084,3.275,20.8,7.721,28.851,13.204c8.078,5.513,14.895,11.853,20.236,18.828c5.291,6.925,9.264,14.393,11.801,22.179
- c2.562,7.898,3.863,15.91,3.863,23.812C400.023,349.395,396.283,364.271,388.904,376.218z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd.svg
deleted file mode 100644
index 91ba62e1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-usd.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M411.387,303.256c-3.119-9.577-7.891-18.561-14.301-26.952c-6.422-8.382-14.396-15.826-23.93-22.331
- c-9.539-6.498-20.721-11.63-33.553-15.4c-5.143-1.363-14.189-3.506-26.104-6.418c-8.516-2.074-16.5-4.2-25.5-6.367V120.065
- c9,2.396,15.252,6.202,21.926,10.43c14.279,9.04,23.232,24.505,25.855,45.505h69.174c-0.654-18-4.65-32.76-11.996-46.02
- c-8.07-14.543-18.977-27.024-32.73-36.956c-13.75-9.922-30.225-17.49-48.377-22.455C303.967,68.416,297,66.605,288,65.386V32h-64
- v33.167c-7,1.044-15.148,2.445-22.426,4.25c-17.242,4.283-32.388,10.868-45.951,19.764c-13.571,8.905-24.352,20.112-32.604,33.627
- c-8.251,13.523-12.312,29.52-12.312,48c0,9.585,1.407,18.993,4.157,28.235c2.752,9.241,7.442,17.967,14.042,26.181
- c6.603,8.214,15.495,15.658,26.687,22.332c11.183,6.672,24.705,12.064,41.576,16.171c9.287,2.345,18.83,4.534,26.83,6.576v119.586
- c-11-2.919-21.889-7.399-30.678-13.479c-9.17-6.327-16.066-13.953-21.198-23.884c-4.779-9.229-7.073-20.526-7.407-32.526H96
- c0.695,21,5.25,39.494,13.672,55.371c8.799,16.604,20.533,29.96,35.204,40.562c14.662,10.613,31.393,18.356,51.198,23.491
- c8.885,2.304,18.926,3.96,27.926,5.23V480h64v-34.54c10-1.069,18.957-2.69,28.527-4.879c18.701-4.273,35.645-11.036,50.316-20.276
- c14.662-9.24,26.621-21.128,35.611-35.681c8.98-14.541,13.545-32.085,13.545-52.619C416,322.427,414.498,312.841,411.387,303.256z
- M224,209.699c-12-3.743-23.912-9.088-32.051-16.048c-8.621-7.355-12.673-17.534-12.673-30.545c0-9.241,2.414-16.94,7.004-23.102
- c4.58-6.161,9.912-11.038,16.88-14.631c6.18-3.189,13.84-5.565,20.84-7.138V209.699z M342.902,359.471
- c-2.939,6.673-7.699,12.576-14.303,17.711c-6.602,5.133-15.744,9.328-26.377,12.577c-4.5,1.378-8.223,2.444-14.223,3.236v-107.11
- c10,2.624,18.18,5.332,26.326,8.131c8.062,2.744,15.748,7.443,22.537,14.116c6.785,6.676,10.309,17.03,10.309,31.06
- C347.172,346.042,345.834,352.797,342.902,359.471z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo-outline.svg
deleted file mode 100644
index 91cb5eda..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo-outline.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M476.9,114c-5-23.4-17.5-38.8-40.6-46.3c-7.4-2.4-16.7-3.7-26.9-3.7c-21.7,0-47.4,6-67.2,20.5
- c-29.9,21.8-47.6,59.7-53.8,83.8c12.2-5.3,20.8-7.1,31.9-7.1c2.2,0,4.6,0.1,7.1,0.2c15,0.8,24.5,12,24.9,25.3
- c0.3,9.8-0.2,18.7-3.6,27.7c-10.8,28.7-27.7,56.5-47.6,80.8c-2.9,3.6-6.4,6.9-10,9.9c-4.1,3.4-8,5-11.6,5c-5.2,0-9.9-3.5-13.8-10.2
- c-5.4-9.3-9-18.9-12.2-29.1c-12.4-39.7-16.8-80.9-23.8-121.6c-3.3-19.5-7-39.8-18-56.9c-10-15.4-24-22.6-41.5-22.6
- c-2.8,0-5.6,0.2-8.6,0.5c-14.7,1.8-36.9,17.5-47.8,26.4c0,0-56,46.9-81.8,71.4l21.2,27c0,0,17.9-12.5,27.5-18.3
- c2.9-1.8,6.1-2.8,9.2-2.8c2.9,0,5.7,0.9,8,3c4.5,3.9,9.6,9,12.3,14.1c5.7,10.7,11.2,21.9,14.7,33.4c13.2,44.3,25.5,88.7,37.8,133.3
- c6.3,22.8,13.9,44.2,28,63.6c13.2,18.2,26.9,26.8,44.3,26.8c8,0,16.8-1.8,26.6-5.4c25.4-9.1,46.6-26.2,66-43.9
- c33.1-30.2,59.1-65.4,85.5-101.2c20.4-27.7,37.3-55.7,51.4-87C478.5,179.8,484,147.3,476.9,114z M450,203.9
- c-13.3,29.4-29.1,56.2-49.7,84.1l-0.3,0.4c-26.4,35.7-51.3,69.5-83.1,98.5c-17.8,16.3-37.5,32.4-60.6,40.7c-8.3,3-15.2,4.4-21.2,4.4
- c-8.2,0-18.4-2.4-31.4-20.2c-13.4-18.4-20.2-39-25.5-58.4c-12.4-45.1-24.6-89.2-37.9-133.6c-3.9-13.2-10.2-25.8-15.9-36.4
- c-3.2-5.9-8.4-12-15.9-18.6c-5.2-4.5-11.6-6.9-18.6-6.9c-5.9,0-12,1.8-17.5,5.1c-4.5,2.7-10.5,6.7-15.9,10.3l-2.8-3.6
- c26.9-24.4,68.3-59.1,70.3-60.8C138.8,96.8,155.8,87,163.5,86c2.3-0.3,4.5-0.4,6.6-0.4c12.4,0,21.3,4.9,28.1,15.3
- c9.5,14.7,12.8,33.9,15.7,50.9c1.6,9.7,3.2,19.6,4.7,29.1c4.8,31.1,9.8,63.3,19.6,94.6c3,9.7,7,21.2,13.6,32.5
- c8.8,15,19.9,18.1,27.6,18.1c7.4,0,14.7-2.9,21.7-8.6c4.6-3.7,8.7-7.8,12.3-12.2c21.9-26.8,39.3-56.3,50.2-85.3
- c4.5-12,4.9-23.3,4.6-33.8c-0.6-22.4-17.4-39.6-40-40.9c-2.9-0.2-5.5-0.2-8-0.2c-2.2,0-4.3,0.1-6.3,0.2
- c8.8-18.1,21.7-36.3,37.7-47.9c15-10.9,36.6-17.5,57.8-17.5c8.3,0,16.1,1,21.9,2.9c17,5.5,26,15.8,29.9,34.4
- C467.2,145.1,463.4,174.2,450,203.9z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo.svg
deleted file mode 100644
index ef74f0bb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-vimeo.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill-rule:evenodd;clip-rule:evenodd;}
-]]>
-</style>
-<path class="st0" d="M476.9,114c-5-23.4-17.5-38.8-40.6-46.3c-23.1-7.5-64.9-4.5-94.1,16.8c-29.9,21.8-47.6,59.7-53.8,83.8
- c14.7-6.3,24-7.7,39-6.9c15,0.8,24.5,12,24.9,25.3c0.3,9.8-0.2,18.7-3.6,27.7c-10.8,28.7-27.7,56.5-47.6,80.8
- c-2.9,3.6-6.4,6.9-10,9.9c-10.2,8.3-18.8,6.1-25.4-5.2c-5.4-9.3-9-18.9-12.2-29.1c-12.4-39.7-16.8-80.9-23.8-121.6
- c-3.3-19.5-7-39.8-18-56.9c-11.6-17.8-28.6-24.6-50-22c-14.7,1.8-36.9,17.5-47.8,26.4c0,0-56,46.9-81.8,71.4l21.2,27
- c0,0,17.9-12.5,27.5-18.3c5.7-3.4,12.4-4.1,17.2,0.2c4.5,3.9,9.6,9,12.3,14.1c5.7,10.7,11.2,21.9,14.7,33.4
- c13.2,44.3,25.5,88.7,37.8,133.3c6.3,22.8,13.9,44.2,28,63.6c19.3,26.6,39.6,32.7,70.9,21.5c25.4-9.1,46.6-26.2,66-43.9
- c33.1-30.2,59.1-65.4,85.5-101.2c20.4-27.7,37.3-55.7,51.4-87C478.5,179.8,484,147.3,476.9,114z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp-outline.svg
deleted file mode 100644
index 3792dec5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp-outline.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path fill-rule="evenodd" clip-rule="evenodd" d="M209.877,154.114c-4.258-11.323-9.176-10.515-12.45-10.639
- c-3.277-0.121-6.146-0.061-10.573,0.011c-3.746,0.061-9.882,1.026-15.232,6.413c-5.357,5.378-20.366,18.312-21.404,45.725
- c-1.031,27.408,18.08,54.643,20.749,58.455c2.667,3.826,36.494,63.236,92.719,87.67c56.231,24.427,56.525,16.981,66.84,16.435
- c10.325-0.54,33.726-12.246,38.899-25.073c5.172-12.827,5.588-23.979,4.271-26.358c-1.316-2.371-5-3.911-10.51-6.9
- c-5.516-2.995-32.595-17.498-37.673-19.55c-5.081-2.044-8.787-3.108-12.742,2.329c-3.957,5.422-15.191,17.569-18.596,21.168
- c-3.42,3.6-6.711,3.934-12.226,0.93c-5.5-2.988-23.373-9.548-44.098-29.317c-16.126-15.38-26.711-34.043-29.779-39.736
- c-3.069-5.697-0.02-8.604,2.9-11.269c2.618-2.407,5.857-6.301,8.792-9.449c2.919-3.148,3.949-5.43,5.961-9.083
- c2.007-3.645,1.2-6.932-0.102-9.771C224.32,193.267,214.133,165.437,209.877,154.114z"/>
- <g>
- <path d="M260.062,64c50.249,0,97.478,19.402,132.982,54.632C428.482,153.796,448,200.533,448,250.232
- c0,49.694-19.518,96.43-54.956,131.596c-35.507,35.232-82.735,54.637-132.982,54.637c-31.806,0-63.24-8.023-90.906-23.201
- l-12.017-6.593l-13.063,4.149l-61.452,19.522l19.375-57.149l4.798-14.151l-7.771-12.763
- c-17.593-28.898-26.892-62.111-26.892-96.047c0-49.699,19.518-96.436,54.957-131.601C162.596,83.402,209.819,64,260.062,64
- M260.062,32C138.605,32,40.134,129.701,40.134,250.232c0,41.229,11.532,79.791,31.559,112.687L32,480l121.764-38.682
- c31.508,17.285,67.745,27.146,106.298,27.146C381.535,468.464,480,370.749,480,250.232C480,129.701,381.535,32,260.062,32
- L260.062,32z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp.svg
deleted file mode 100644
index 27b2ac50..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-whatsapp.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M260.062,32C138.605,32,40.134,129.701,40.134,250.232c0,41.23,11.532,79.79,31.559,112.687L32,480l121.764-38.682
- c31.508,17.285,67.745,27.146,106.298,27.146C381.535,468.464,480,370.749,480,250.232C480,129.701,381.535,32,260.062,32z
- M369.424,333.11c-5.174,12.827-28.574,24.533-38.899,25.072c-10.314,0.547-10.608,7.994-66.84-16.434
- c-56.225-24.434-90.052-83.844-92.719-87.67c-2.669-3.812-21.78-31.047-20.749-58.455c1.038-27.413,16.047-40.346,21.404-45.725
- c5.351-5.387,11.486-6.352,15.232-6.413c4.428-0.072,7.296-0.132,10.573-0.011c3.274,0.124,8.192-0.685,12.45,10.639
- c4.256,11.323,14.443,39.153,15.746,41.989c1.302,2.839,2.108,6.126,0.102,9.771c-2.012,3.653-3.042,5.935-5.961,9.083
- c-2.935,3.148-6.174,7.042-8.792,9.449c-2.92,2.665-5.97,5.572-2.9,11.269c3.068,5.693,13.653,24.356,29.779,39.736
- c20.725,19.771,38.598,26.329,44.098,29.317c5.515,3.004,8.806,2.67,12.226-0.929c3.404-3.599,14.639-15.746,18.596-21.169
- c3.955-5.438,7.661-4.373,12.742-2.329c5.078,2.052,32.157,16.556,37.673,19.551c5.51,2.989,9.193,4.529,10.51,6.9
- C375.012,309.131,374.596,320.282,369.424,333.11z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows-outline.svg
deleted file mode 100644
index 9e10792f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows-outline.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M464,281v180.5l-216-31.3V281H464 M480,265H232v179l248,36V265L480,265z"/>
- <path class="st0" d="M200,281v142.2L48,401.2V281H200 M216,265H32v150l184,26.7V265L216,265z"/>
- <path class="st0" d="M464,50v183H248V81.3l216-30.9 M480,32L232,67.4V249h248V32L480,32z"/>
- <path class="st0" d="M200,88v145H48V109.9l152-21.7 M216,69.7L32,96v153h184V69.7L216,69.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows.svg
deleted file mode 100644
index bf14576b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-windows.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M480,265H232v179l248,36V265L480,265z"/>
- <path class="st0" d="M216,265H32v150l184,26.7V265L216,265z"/>
- <path class="st0" d="M480,32L232,67.4V249h248V32L480,32z"/>
- <path class="st0" d="M216,69.7L32,96v153h184V69.7L216,69.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress-outline.svg
deleted file mode 100644
index 1d6a91bb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress-outline.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M255.9,64C150.2,64,64,150.2,64,256.1C64,361.9,150.2,448,255.9,448c8.5,0,16.8-0.5,24.9-1.8
- c85.7-11,153.8-78.7,165.3-164.1c1.3-8.5,1.9-17.2,1.9-26C448,150.2,361.8,64,255.9,64z M83.4,256.1c0-25,5.4-48.8,15-70.2
- l82.3,225.5C123.1,383.4,83.4,324.3,83.4,256.1z M278.3,427.3c-7.3,0.9-14.8,1.4-22.4,1.4c-16.9,0-33.2-2.5-48.6-7.1l18.8-55h0.1
- l32.7-95.5L312,416.5c0.4,0.8,0.9,1.6,1.3,2.3C302.1,422.8,290.4,425.6,278.3,427.3z M279.8,175.1c10.4-0.5,19.7-1.6,19.7-1.6
- c9.4-1,8.2-14.8-1.1-14.2c0,0-28,2.2-46,2.2c-16.9,0-45.5-2.2-45.5-2.2c-9.2-0.6-10.4,13.7-1,14.2c0,0,8.7,1.1,18.1,1.6l26.9,73.7
- l-37.8,113.3l-62.9-187c10.5-0.5,19.8-1.6,19.8-1.6c9.2-1,8.2-14.8-1.1-14.2c0,0-27.9,2.2-46,2.2c-3.3,0-7.1-0.1-11.1-0.2
- c30.8-46.8,83.9-77.7,144.1-77.7c45,0,85.9,17.2,116.6,45.2c-0.8,0-1.5-0.1-2.3-0.1c-17,0-29,14.8-29,30.7
- c0,14.2,8.2,26.2,16.9,40.4c6.6,11.5,14.3,26.3,14.3,47.6c0,14.8-4.4,33.4-13.1,55.7l-17.3,57.6L279.8,175.1z M342.7,405.3
- l13.7-39.7l39-112.8c9.9-24.6,13.1-44.3,13.1-61.8c0-6.3-0.4-12.3-1.1-17.8c13.5,24.6,21.2,52.8,21.2,82.9c0,8-0.5,15.8-1.5,23.5
- C419.7,333.3,387.6,379.2,342.7,405.3z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress.svg
deleted file mode 100644
index ab77d7e7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-wordpress.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M259,271.3L226.2,367h-0.1l-25.4,73.1c1.8,0.5,3.5,0.9,5.3,1.4c0.1,0,0.2,0,0.3,0c15.8,4.2,32.4,6.5,49.5,6.5
- c8.5,0,16.8-0.5,24.9-1.8c11.2-1.4,22-3.8,32.5-7.1c0,0,0,0,0,0c2.6-0.8,5.2-1.7,7.8-2.6c-2.8-6-8.8-19.3-9.1-19.9L259,271.3z"/>
- <path d="M80.8,180.5c-10,22.6-16.8,50.4-16.8,75.5c0,6.3,0.3,12.6,0.9,18.8c6.9,71.2,52.9,131,116.1,157.9c2.6,1.1,5.3,2.2,8,3.2
- L96,180.6C88,180.3,86.5,180.8,80.8,180.5z"/>
- <path d="M430.2,175.4c-4.3-9.3-9.4-18.2-15.1-26.6c-1.6-2.4-3.4-4.8-5.1-7.2c-21.5-28.8-50.8-51.4-84.9-64.6
- C303.7,68.6,280.3,64,255.9,64c-60.3,0-114.2,28-149.4,71.7c-6.5,8-12.3,16.6-17.5,25.6c14.2,0.1,31.8,0.1,33.8,0.1
- c18.1,0,46-2.2,46-2.2c9.4-0.6,10.4,13.1,1.1,14.2c0,0-9.4,1.1-19.8,1.6l62.9,187l37.8-113.3L224,175.1c-9.4-0.5-18.1-1.6-18.1-1.6
- c-9.4-0.5-8.2-14.8,1-14.2c0,0,28.5,2.2,45.5,2.2c18.1,0,46-2.2,46-2.2c9.3-0.6,10.5,13.1,1.1,14.2c0,0-9.3,1.1-19.7,1.6
- l62.3,185.6l17.3-57.6c8.7-22.4,13.1-40.9,13.1-55.7c0-21.3-7.7-36.1-14.3-47.6c-8.7-14.3-16.9-26.3-16.9-40.4
- c0-15.9,12-30.7,29-30.7c0.7,0,1.5,0,2.2,0c26.2-0.7,34.8,25.3,35.9,43c0,0,0,0.4,0,0.6c0.4,7.2,0.1,12.5,0.1,18.8
- c0,17.4-3.3,37.1-13.1,61.8l-39,112.8l-22.3,65.7c1.8-0.8,3.5-1.6,5.3-2.5c56.7-27.4,98-82,106.7-146.7c1.3-8.5,1.9-17.2,1.9-26
- C448,227.3,441.6,199.9,430.2,175.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo-outline.svg
deleted file mode 100644
index 97ea51f8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo-outline.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M384.6,68.4c-11.3,0-22.5-0.8-32.6-4.4l-96,160L160,64c-10.1,3.6-20.7,4.4-32,4.4c-11.1,0-22.1-0.9-32-4.4l128,212.7V448
- c10-3.5,20.8-4.4,32-4.4s22,0.9,32,4.4V277L416,64C406.1,67.4,395.7,68.4,384.6,68.4z M274.2,268.5l-2.2,4v4.4v151.3
- c-5-0.6-11.2-0.7-16-0.7c-4.8,0-10,0.1-16,0.7V276.7v-4.4l-2.4-3.8L127,84.4c0.3,0,0.7,0,1,0c7.6,0,16-0.3,24.7-1.9l89.8,149.8
- l13.4,22.8l14-22.9l89.8-149.9c9,1.6,17.6,1.7,24.8,1.7c0.2,0,0.3,0,0.5,0L274.2,268.5z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo.svg
deleted file mode 100644
index ef498565..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yahoo.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M384.6,68.4c-11.3,0-22.5-0.8-32.6-4.4l-96,160L160,64c-10.1,3.6-20.7,4.4-32,4.4c-11.1,0-22.1-0.9-32-4.4l128,212.7V448
- c10-3.5,20.8-4.4,32-4.4s22,0.9,32,4.4V277L416,64C406.1,67.4,395.7,68.4,384.6,68.4z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen-outline.svg
deleted file mode 100644
index 1d087801..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen-outline.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,32h-80L256,253.128L144,32H64l112.368,208H128v48h73.564L216,319v17h-88v48h88v96h80v-96h88v-48h-88v-17l14.891-31H384
- v-48h-48.289L448,32z M368,256v16h-67l-21,43v37h88v16h-88v96h-48v-96h-88v-16h88v-35.75L212,272h-68v-16h59.197l-12.752-23.605
- L90.829,48H134l122,240L378,48h43h0.18l-99.548,184.399L308.891,256H368z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen.svg
deleted file mode 100644
index ac2b0294..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-yen.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M448,32h-80L256,253.128L144,32H64l112.368,208H128v48h73.564L216,319v17h-88v48h88v96h80v-96h88v-48h-88v-17l14.891-31H384
- v-48h-48.289L448,32z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube-outline.svg
deleted file mode 100644
index d8833633..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube-outline.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M265,96c65.3,0,118.7,1.1,168.1,3.3l0.7,0h0.7c23.1,0,42,22,42,49.1v1.1l0.1,1.1c2.3,34,3.4,69.3,3.4,104.9v0v0
- c0.1,35.6-1.1,70.9-3.4,104.9l-0.1,1.1v1.1c0,13.8-4.7,26.6-13.4,36.1c-7.8,8.6-18,13.4-28.6,13.4h-0.8l-0.8,0
- c-52.9,2.5-108.8,3.8-166.4,3.8c-3.5,0-7.1,0-10.6,0H256h-0.1c-3.6,0-7.2,0-10.8,0c-57.8,0-113.7-1.3-166.2-3.7l-0.8,0h-0.8
- c-10.6,0-20.7-4.8-28.5-13.4c-8.6-9.5-13.4-22.3-13.4-36.1v-1.1l-0.1-1.1c-2.4-34.1-3.5-69.4-3.3-104.7v-0.1v-0.1
- c-0.1-35.3,1-70.5,3.3-104.6l0.1-1.1v-1.1c0-27.2,18.8-49.3,41.9-49.3H78l0.7,0c49.5-2.3,102.9-3.3,168.2-3.3h9H265 M265,64
- c-3,0-6,0-9,0s-6,0-9,0c-57.6,0-114.2,0.8-169.6,3.3c-40.8,0-73.9,36.3-73.9,81.3C1,184.4-0.1,220,0,255.7
- c-0.1,35.7,0.9,71.3,3.4,107c0,45,33.1,81.6,73.9,81.6c54.8,2.6,110.7,3.8,167.8,3.8c3.6,0,7.3,0,10.9,0c3.6,0,7.2,0,10.7,0
- c57.1,0,113-1.2,167.9-3.8c40.9,0,74-36.6,74-81.6c2.4-35.7,3.5-71.4,3.4-107.1c0.1-35.7-1-71.3-3.4-107.1c0-45-33.1-81.1-74-81.1
- C379.2,64.8,322.7,64,265,64L265,64z"/>
- </g>
- <g>
- <path d="M207,353.8V157.4l145,98.2L207,353.8z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube.svg
deleted file mode 100644
index 2347549f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/social-youtube.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M508.6,148.8c0-45-33.1-81.2-74-81.2C379.2,65,322.7,64,265,64c-3,0-6,0-9,0s-6,0-9,0c-57.6,0-114.2,1-169.6,3.6
- c-40.8,0-73.9,36.4-73.9,81.4C1,184.6-0.1,220.2,0,255.8C-0.1,291.4,1,327,3.4,362.7c0,45,33.1,81.5,73.9,81.5
- c58.2,2.7,117.9,3.9,178.6,3.8c60.8,0.2,120.3-1,178.6-3.8c40.9,0,74-36.5,74-81.5c2.4-35.7,3.5-71.3,3.4-107
- C512.1,220.1,511,184.5,508.6,148.8z M207,353.9V157.4l145,98.2L207,353.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can-outline.svg
deleted file mode 100644
index b1bf3a96..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can-outline.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M255.82,144c88.269,0,159.824-28.654,159.824-64S344.089,16,255.82,16C167.552,16,95.997,44.654,95.997,80
- S167.552,144,255.82,144z M255.82,33.041c69.729,0,126.26,19.234,126.26,42.959s-56.531,42.959-126.26,42.959
- c-69.729,0-126.258-19.234-126.258-42.959S186.091,33.041,255.82,33.041z"/>
- <path d="M256.57,160c-88.269,0-160.567-28.654-160.567-64c0,0-0.003,33.999,7.997,40v240c0,35.346,63.732,64,152,64
- c88.269,0,152-28.654,152-64V136c8-7.438,7.708-34.853,7.817-40C414.665,130.946,344.116,160,256.57,160z M376,375.588
- c0,2.232-7.961,10.682-29.423,18.688C322.853,403.126,290.812,408,256.273,408c-34.539,0-66.83-4.874-90.554-13.725
- C144.257,386.27,137,377.82,136,375.588v-79.564c18,9.721,42.742,17.115,72.156,20.979l1.588,0.237
- C215.487,337.308,233.936,352,255.826,352c21.89,0,40.338-14.689,46.084-34.754l1.755-0.244
- C333.08,313.139,358,305.744,376,296.023V375.588z M376,264.023c-18,9.831-43.476,17.284-73.325,21.11l-2.61,0.195
- C292.791,268.097,275.723,256,255.859,256c-19.867,0-36.919,12.102-44.19,29.34l-2.514-0.206
- c-29.85-3.826-55.155-11.279-73.155-21.11v-91.265C170,185.25,211.923,192,256.499,192C300.665,192,343,185.287,376,173.045
- V264.023z"/>
- <g>
- <path d="M274.002,463.58"/>
- <path d="M256.272,464c0.293,0,0.583-0.006,0.876-0.007c-0.351,0.001-0.699,0.005-1.051,0.005
- C256.156,463.998,256.214,464,256.272,464z"/>
- <path d="M408,415.999V400c0,36.001-63.432,64-152,64c-88.569,0-152-28.654-152-64v15.999L96.261,432
- c0,6.994,2.938,13.725,8.117,20.025C125.37,477.562,185.471,496,256.273,496c70.801,0,130.87-18.438,151.863-43.975
- c5.18-6.301,7.923-13.031,7.923-20.025L408,415.999z"/>
- </g>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can.svg
deleted file mode 100644
index 53e3c291..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/soup-can.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <ellipse cx="256" cy="80" rx="160" ry="64"/>
- <path d="M256,440c88.365,0,152-28.654,152-64V248c0,28.581-41.612,52.783-104.26,61.002C301.238,333.16,280.82,352,256,352
- s-45.238-18.84-47.74-42.998C145.612,300.783,104,276.581,104,248v128C104,411.346,167.634,440,256,440z"/>
- <path d="M256,160c-88.366,0-160-28.654-160-64c0,0,0,32.834,8,40v96c0,28.732,42.049,53.042,105.25,61.134
- C214.176,271.861,233.229,256,256,256s41.824,15.861,46.75,37.134C365.951,285.042,408,260.732,408,232v-96c8-8.25,8-40,8-40
- C416,131.346,344.365,160,256,160z"/>
- <path d="M408,392c0,35.346-63.635,64-152,64c-88.366,0-152-28.654-152-64v23.999L96,432c0,6.994,2.815,13.725,8,20.025
- C125.016,477.562,185.121,496,256,496c70.879,0,130.984-18.438,152-43.975c5.186-6.301,8-13.031,8-20.025l-8-16.001V392z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speakerphone.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speakerphone.svg
deleted file mode 100644
index b41b235c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speakerphone.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M70.9,181.5c0-41,25-76.5,60.6-91.5h-7.7c-41.1,0-75.1,32.8-81.1,75.2c-6,1-10.7,7.9-10.7,16.1c0,8.6,5.1,15.4,11.6,15.9
- c7.2,36.4,35.1,65.8,69.7,68.8c0,0,0.1,0,0.1,0c1.4,0,2.8,0.6,4.2,0.9c1.1,0.2,2.2,0.4,3.3,0.7C91,250.5,70.9,218.4,70.9,181.5z"/>
- <path d="M465.1,91c-1.1-2.9-2.3-5.6-3.5-8.3c-6.5-14.4-14.4-26-23.4-34.6C427,37.6,414.1,32,400.8,32c-8.3,0-16.4,2.2-24.1,6.4
- c0,0,0,0-0.1,0c-1.2,0.7-2.4,1.3-3.6,2c-49,29-104.1,46.2-162.6,49.4c-6.5,0.4-13,0.2-19.5,0.2h-42.3c-34,15-59,50.5-59,91.5
- c0,36.8,19.2,69.1,47.8,86.1c13,10.9,41.7,11.7,40,23.9c-1.9,13.2-5.5,21.9-7.8,30.7c-1.3,4.8-23.6,72.9-25.3,144.7
- c0,2,0,3.7,0.2,6.6c0.2,2.9,2.2,6.4,8.5,6.4h76.8c6.6,0,9.7-3.3,9.3-9.3c-0.2-1.9-0.6-4.3-0.8-6.5c-2.4-23.1-4.6-49.8-3.3-81.6
- c1.3-34,5.2-51.9,7-61.3c2.1-10.4,7.6-22.4,12.1-30.3c30.8,0.9,92.9,19.3,115.1,28.9c0,0,7.2,3.4,10.1,5.2c7,3.4,14.2,5.1,21.6,5.1
- c0.9,0,1.8,0,2.7-0.1c12.3-0.7,24.2-9.7,34.7-19.5c9.1-8.5,16.9-20.2,23.4-34.6c1.2-2.8,2.4-5.6,3.5-8.6
- c9.6-25,14.8-55.9,14.8-88.1C480,147,474.8,116,465.1,91z M442,267.5c-7.8,18.5-18.2,33.3-29.5,33.3c-11.3,0-21.6-14.7-29.4-33.3
- c-9.1-21.6-14.9-53.1-14.9-88.1c0-35.2,5.8-66.8,15-88.4c7.8-18.4,18.1-29.5,29.3-29.5c11.3,0,21.5,11.2,29.4,29.5
- c9.2,21.6,15,53.2,15,88.4C456.9,214.4,451.1,245.9,442,267.5z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speedometer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speedometer.svg
deleted file mode 100644
index 977e00a2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/speedometer.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M344,256l-84.4,64.2c-1.2-0.1-2.4-0.2-3.6-0.2c-17.7,0-32,14.3-32,32c0,17.7,14.3,32,32,32c17.7,0,32-14.3,32-32
- c0-1.2-0.1-2.4-0.2-3.6L352,264L344,256z"/>
- <path d="M256,96C132.3,96,32,196.3,32,320c0,34.4,7.8,66.9,21.6,96h36.1c-15.4-26.6-24.2-56.6-25.5-88H96v-16H64.2
- c1.2-28.8,8.7-56.5,21.8-81.4l27.5,15.9l8-13.9L94,216.8c7.4-11.6,16.2-22.6,26.2-32.6c10.2-10.1,21.3-19,33.1-26.5l15.8,27.3
- l13.9-8l-15.8-27.3c24.8-13,52.2-20.3,80.8-21.5V160h16v-31.8c28.6,1.2,56,8.6,80.8,21.5L329.1,177l13.9,8l15.8-27.3
- c11.8,7.5,22.9,16.4,33.1,26.5c10,10,18.7,20.9,26.2,32.6l-27.4,15.8l8,13.9l27.5-15.9c13.1,24.9,20.6,52.6,21.8,81.4H416v16h31.8
- c-1.3,31.4-10.1,61.4-25.5,88h36.1c13.8-29.1,21.6-61.6,21.6-96C480,196.3,379.7,96,256,96z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/spoon.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/spoon.svg
deleted file mode 100644
index 21e19ed8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/spoon.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M320,160C320,96,293.5,32,256,32s-64,64-64,128l0,0c0.9,25,15.7,54.3,36.6,64.3c0.5,0.2,0.9,0.4,1.4,0.6c0,0,0,0,0.1,0
- c3.4,1.9,9.8,5.5,9.8,9.7c0,0-16,198.7-16,210.1s5,20.5,10.5,26c5.5,5.5,13.1,9.2,21.3,9.2c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0
- c8.2,0,15.8-3.7,21.4-9.2c5.5-5.5,10.3-12.9,10.3-26s-16-210.1-16-210.1c0-4.2,6.4-7.9,9.8-9.8l1.7-0.9C304.9,214,320,186,320,160"
- />
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/star.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/star.svg
deleted file mode 100644
index b8285b7b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/star.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<polygon points="480,200 308.519,200 256.029,32 203.519,200 32,200 170.946,304.209 116,480 256,368 396,480 341.073,304.195 "/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stats-bars.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stats-bars.svg
deleted file mode 100644
index 59b2c544..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stats-bars.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <rect x="176" y="96" width="64" height="320"/>
- <rect x="80" y="320" width="64" height="96"/>
- <rect x="272" y="256" width="64" height="160"/>
- <rect x="368" y="192" width="64" height="224"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/steam.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/steam.svg
deleted file mode 100644
index b04c04f2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/steam.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<path id="Gears" class="st0" d="M480,208.2c0,20.5-16.6,37.2-37.2,37.2c-20.5,0-37.2-16.6-37.2-37.2c0-20.5,16.6-37.2,37.2-37.2
- C463.3,171,480,187.7,480,208.2z M442.6,139c-38.1,0-69,30.7-69.4,68.7L330,269.7c-1.8-0.2-3.6-0.3-5.4-0.3
- c-9.7,0-18.7,2.7-26.4,7.3l-195.8-78.7c-5.1-23.2-25.9-40.7-50.6-40.7C23.3,157.2,0,180.6,0,209.1c0,28.5,23.3,51.8,51.8,51.8
- c9.7,0,18.7-2.7,26.4-7.3L274,332.2c5.1,23.3,25.8,40.8,50.6,40.8c26.8,0,49-20.6,51.5-46.7l66.5-48.6c38.3,0,69.4-31,69.4-69.3
- C512,170.1,480.9,139,442.6,139z M442.6,161.9c25.7,0,46.5,20.9,46.5,46.5c0,25.7-20.9,46.4-46.5,46.4c-25.7,0-46.5-20.8-46.5-46.4
- C396.1,182.7,416.9,161.9,442.6,161.9z M51.8,170.9c14.6,0,27.3,8.2,33.7,20.2l-18.9-7.6v0.1c-15.3-5.5-32.2,2-38.3,17.1
- c-6.1,15.2,0.9,32.3,15.7,38.9v0.1l16.1,6.4c-2.6,0.6-5.4,0.9-8.2,0.9c-21.1,0-38.1-17-38.1-38.1C13.7,188,30.7,170.9,51.8,170.9z
- M324.6,283.1c21.1,0,38.1,17,38.1,38.1c0,21.1-17,38.1-38.1,38.1c-14.7,0-27.4-8.2-33.7-20.3c6.3,2.5,12.5,5,18.8,7.6
- c15.5,6.2,33.2-1.3,39.4-16.8c6.2-15.5-1.3-33.1-16.9-39.4l-15.9-6.4C319.1,283.5,321.8,283.1,324.6,283.1z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stop.svg
deleted file mode 100644
index 2f1ac061..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/stop.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M437.4,64H74.6C68.7,64,64,68.7,64,74.6v362.8c0,5.9,4.7,10.6,10.6,10.6h362.8c5.8,0,10.6-4.7,10.6-10.6V74.6
- C448,68.7,443.2,64,437.4,64z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thermometer.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thermometer.svg
deleted file mode 100644
index 115493d3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thermometer.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M303,335.6V78.4c0-25.7-21-46.5-47-46.5c-26,0-47,20.8-47,46.5v256.8c-20,14.5-32.9,38.2-32.9,64.9c0,44.2,36,80,80.2,80
- c44.2,0,79.8-35.8,79.8-80C336,373.6,323,350.1,303,335.6z M241,78.4c0-8,6.7-14.5,15-14.5s15,6.5,15,14.5V128h-30V78.4z M272,288
- h-16v-16h16V288z M272,256h-16v-64h16V256z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsdown.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsdown.svg
deleted file mode 100644
index 2902b020..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsdown.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M87.8,252.7C74,257.2,64,270.2,64,285.5c0,19,15.4,34.5,34.5,34.5h102.6c-2,25-10,53.6-1.1,87.3
- c7.5,28.4,39.4,49.7,52.4,36.8c5-4.9,3.5-15.2,3.5-33.8c0-42.8,17.8-86.1,39.8-108.7c9.4-9.7,25.2-13,40.2-13.6v16h112V64H336v32
- c-20.6,0.5-52.6-5.2-75.8-6.6c-52-3.1-102,2.4-126.3,8.1c-24.3,5.7-35,13-35,30.6c0,6.4,1.9,12.3,5.1,17.3
- c-11.8,4.7-20.1,16.2-20.1,29.7c0,7.2,2.4,13.8,6.4,19.2c-11.9,4.6-20.4,16.2-20.4,29.8C70,236.6,77.3,247.5,87.8,252.7z M400,96.3
- c8.8,0,16,7.1,16,16c0,8.8-7.2,16-16,16s-16-7.1-16-16C384,103.5,391.2,96.3,400,96.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsup.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsup.svg
deleted file mode 100644
index bf01b9bf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/thumbsup.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M424.2,259.3c13.8-4.5,23.8-17.5,23.8-32.8c0-19-15.4-34.5-34.5-34.5H310.9c2-25,10-53.6,1.1-87.3
- c-7.5-28.4-39.4-49.7-52.4-36.8c-5,4.9-3.5,15.2-3.5,33.8c0,42.8-17.8,86.1-39.8,108.7c-9.4,9.7-25.2,13-40.2,13.6v-16H64v240h112
- v-32c20.6-0.5,52.6,5.2,75.8,6.6c52,3.1,102-2.4,126.3-8.1c24.3-5.7,35-13,35-30.6c0-6.4-1.9-12.3-5.1-17.3
- c11.8-4.7,20.1-16.2,20.1-29.7c0-7.2-2.4-13.8-6.4-19.2c11.9-4.6,20.4-16.2,20.4-29.8C442,275.4,434.7,264.5,424.2,259.3z
- M112,415.7c-8.8,0-16-7.1-16-16c0-8.8,7.2-16,16-16s16,7.1,16,16C128,408.5,120.8,415.7,112,415.7z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle-filled.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle-filled.svg
deleted file mode 100644
index 6680dda0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle-filled.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M352,208c-26.467,0-48,21.533-48,48c0,26.467,21.533,48,48,48s48-21.533,48-48C400,229.533,378.467,208,352,208z"/>
- <path d="M352,128H160c-70.692,0-128,57.308-128,128s57.308,128,128,128h192c70.692,0,128-57.308,128-128S422.692,128,352,128z
- M352,336c-44.183,0-80-35.817-80-80s35.817-80,80-80s80,35.817,80,80S396.183,336,352,336z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle.svg
deleted file mode 100644
index b177aa94..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/toggle.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <path d="M352,160c52.934,0,96,43.065,96,96s-43.066,96-96,96H160c-52.935,0-96-43.065-96-96s43.065-96,96-96H352 M352,128H160
- c-70.692,0-128,57.308-128,128s57.308,128,128,128h192c70.692,0,128-57.308,128-128S422.692,128,352,128L352,128z"/>
- <path d="M160,208c26.467,0,48,21.533,48,48c0,26.467-21.533,48-48,48s-48-21.533-48-48C112,229.533,133.533,208,160,208 M160,176
- c-44.183,0-80,35.817-80,80s35.817,80,80,80s80-35.817,80-80S204.183,176,160,176L160,176z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/transgender.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/transgender.svg
deleted file mode 100644
index 5a43b009..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/transgender.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M368,0v40h69.873l-93.046,91.97c-8.529-8.249-15.132-12.586-15.132-12.586C308.841,104.694,283.422,96,256,96
- c-34.525,0-65.86,13.669-88.903,35.894l-17.333-17.131l35.833-35.833L153.07,46.403l-36.022,36.021L74.127,40H144V0H0v144h40V67.806
- l46.085,45.582L50.402,149.07l32.526,32.526l35.862-35.861l22.185,21.942c-8.395,17.065-13.118,36.267-13.118,56.578
- C127.857,286.884,173,338.989,232,350.25V402h-72v46h72v64h48v-64h72v-46h-72v-51.75c58-11.261,104.222-63.397,104.222-126.025
- c0-20.202-4.794-39.738-13.094-56.649L472,67.806V144h40V0H368z M255.929,304.402c-44.156,0-80.079-35.968-80.079-80.178
- c0-44.211,35.923-80.18,80.079-80.18c44.155,0,80.078,35.969,80.078,80.18C336.007,268.435,300.084,304.402,255.929,304.402z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-a.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-a.svg
deleted file mode 100644
index 1631e74d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-a.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M341,128V99c0-19.1-14.5-35-34.5-35H205.4C185.5,64,171,79.9,171,99v29H80v32h9.2c0,0,5.4,0.6,8.2,3.4c2.8,2.8,3.9,9,3.9,9
- l19,241.7c1.5,29.4,1.5,33.9,36,33.9h199.4c34.5,0,34.5-4.4,36-33.8l19-241.6c0,0,1.1-6.3,3.9-9.1c2.8-2.8,8.2-3.4,8.2-3.4h9.2v-32
- h-91V128z M192,99c0-9.6,7.8-15,17.7-15h91.7c9.9,0,18.6,5.5,18.6,15v29H192V99z M183.5,384l-10.3-192h20.3L204,384H183.5z
- M267.1,384h-22V192h22V384z M328.7,384h-20.4l10.5-192h20.3L328.7,384z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-b.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-b.svg
deleted file mode 100644
index f75e2f83..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trash-b.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M413.7,133.4c-2.4-9-4-14-4-14c-2.6-9.3-9.2-9.3-19-10.9l-53.1-6.7c-6.6-1.1-6.6-1.1-9.2-6.8c-8.7-19.6-11.4-31-20.9-31
- h-103c-9.5,0-12.1,11.4-20.8,31.1c-2.6,5.6-2.6,5.6-9.2,6.8l-53.2,6.7c-9.7,1.6-16.7,2.5-19.3,11.8c0,0-1.2,4.1-3.7,13
- c-3.2,11.9-4.5,10.6,6.5,10.6h302.4C418.2,144.1,417,145.3,413.7,133.4z"/>
- <path d="M379.4,176H132.6c-16.6,0-17.4,2.2-16.4,14.7l18.7,242.6c1.6,12.3,2.8,14.8,17.5,14.8h207.2c14.7,0,15.9-2.5,17.5-14.8
- l18.7-242.6C396.8,178.1,396,176,379.4,176z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trophy.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trophy.svg
deleted file mode 100644
index b1600f40..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/trophy.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M479.863,103.342c-0.051-2.833-0.096-5.279-0.096-7.342h-80.835c1.56-34.617,0.512-64,0.512-64s-95.591,0-142.568,0
- c-0.337,0-0.669,0.022-1,0.056c-0.33-0.034-0.662-0.056-1-0.056c-46.977,0-142.931,0-142.931,0s-1.048,29.383,0.512,64H32.232H32
- v20.548c0,0.114,0,0.228,0,0.342V128h0.161c0.811,26.096,4.98,60.999,22.333,96.729c14.718,30.307,35.912,55.664,62.996,75.367
- c22.422,16.312,48.041,28.064,76.205,35.084C209.96,352.539,226,362.109,240,365.957v35.625C238,412.165,225.86,448,141.234,448H128
- v32h256v-32h-13.178C271.538,448,272,398.666,272,398.666v-32.714c14-3.843,29.73-13.374,45.91-30.644
- c28.369-7.004,54.072-18.801,76.633-35.213c27.082-19.703,48.262-45.06,62.98-75.367
- C481.203,175.967,480.326,128.723,479.863,103.342z M83.262,210.745C68.802,180.966,65.018,150.996,64.187,128h50.487
- c0.868,8.914,1.966,17.701,3.356,25.98c8.513,50.709,20.213,95.493,42.354,135.009C126.546,271.848,99.97,245.149,83.262,210.745z
- M428.737,210.745c-16.807,34.61-43.603,61.421-77.729,78.55c22.215-39.591,33.816-84.475,42.352-135.314
- c1.39-8.28,2.488-17.067,3.356-25.98h51.096C446.981,150.996,443.198,180.966,428.737,210.745z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt-outline.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt-outline.svg
deleted file mode 100644
index 2d2863f2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt-outline.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M178.249,85.534c18.761,22.976,43.909,34.009,77.445,34.572l0.269-0.106h0.269c22.638,0,41.169-4.861,56.653-15.091
- c7.801-5.154,14.721-11.47,21.029-19.382l104.461,31.367L426.59,149.41l-38.743-4.685l-37.912-4.589l2.114,38.133L366.176,433
- H145.824l14.127-254.729l2.106-37.981l-37.782,4.428l-38.854,4.553l-11.767-32.358L178.249,85.534 M320,48
- c-13.988,27.227-30.771,40.223-63.769,40.223C223.723,87.676,205.722,75,192,48L32,96l32,88l64-7.5L112,465h288l-16-288.5l64,7.75
- L480,96L320,48L320,48z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt.svg
deleted file mode 100644
index 6a38c489..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/tshirt.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<path d="M480,96L320,48c-13.988,27.227-30.771,40.223-63.769,40.223C223.723,87.676,205.722,75,192,48L32,96l32,88l64-8l-16,288h288
- l-16-288l64,8L480,96z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/umbrella.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/umbrella.svg
deleted file mode 100644
index df578e51..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/umbrella.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <g>
- <path d="M376.2,288c0,0.1,0,0.2,0,0.4C376.2,288.2,376.2,288.1,376.2,288L376.2,288z"/>
- <path d="M136.2,288c0,0.1,0,0.2,0,0.4C136.2,288.2,136.2,288.1,136.2,288L136.2,288z"/>
- </g>
- <path d="M272,48.8c0-0.3,0-0.5,0-0.8c0-8.8-7.2-16-16-16c-8.8,0-16,7.2-16,16c0,0.2,0,0.5,0,0.7c-116.3,8-208,103.1-208,221.4
- c0,3.6,0.2,14.2,0.4,17.8c2.7-26.3,24.7-51.7,51.7-51.7c28.7,0,51.9,23.1,52.1,51.7h0c0.2-28.6,23.4-51.7,52.1-51.7
- c26.5,0,50.9,21.1,51.7,45.5V416c0,17.9-14.1,32-32,32c-17.1,0-31-14.4-31-32c0-8.8-7.2-16-16-16s-16,7.2-16,16
- c0,35.3,28.3,64,63,64c17.3,0,33.5-6.7,45.5-18.8c11.9-12,18.5-28.1,18.5-45.2l0-135.3c3.3-32.7,23.4-44.4,52.1-44.4
- c28.7,0,51.9,23.1,52.1,51.7h0c0.2-28.6,23.4-51.7,52.1-51.7c26.1,0,47.6,26.7,51.4,51.7c0.1-2.8,0.2-9.1,0.2-11.8
- C480,157.8,388.2,57.3,272,48.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/university.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/university.svg
deleted file mode 100644
index ca0a190f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/university.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
- <polygon points="256,64 32,176.295 64,197.367 64,400 96,416 96,217.849 255.852,320 387.996,234.549 480,174.727 "/>
- <path d="M390.13,256L256,343.768L120.531,256L112,337.529C128,349.984,224,416,256.002,448C288,416,384,350.031,400,337.561
- L390.13,256z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/unlocked.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/unlocked.svg
deleted file mode 100644
index 51938827..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/unlocked.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M86.4,480h339.2c12.3,0,22.4-9.9,22.4-22.1V246c0-12.2-10-22-22.4-22H161v-30.9c0-27.3,9.9-61.1,28.1-80.3l0,0l0-0.3
- C206.7,93.9,231,83,255.9,83h0.1h0.1c24.9,0,49.2,10.9,66.8,29.5l0,0.2l0,0.1c11.3,11.9,19.4,29.3,24,47.3h53.4
- c-5.9-31.3-19.7-61.8-39.2-82.4C334.9,49.9,297.4,32,256.1,32c-0.1,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0c-41.3,0-79,17.9-105.3,45.6
- c-26.4,27.8-42.6,73.9-42.6,115.4V224H89h-2.6C74,224,64,233.9,64,246v211.9C64,470.1,74,480,86.4,480z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/upload.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/upload.svg
deleted file mode 100644
index 12baaf39..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/upload.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M398.1,233.2c0-1.2,0.2-2.4,0.2-3.6c0-65-51.8-117.6-115.7-117.6c-46.1,0-85.7,27.4-104.3,67c-8.1-4.1-17.2-6.5-26.8-6.5
- c-29.5,0-54.1,21.9-58.8,50.5C57.3,235.2,32,269.1,32,309c0,50.2,40.1,91,89.5,91H224v-80l-48.2,0l80.2-83.7l80.2,83.6l-48.2,0v80
- h110.3c45.2,0,81.7-37.5,81.7-83.4C480,270.6,443.3,233.3,398.1,233.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/usb.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/usb.svg
deleted file mode 100644
index b4318480..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/usb.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M144,220C144,220,144.1,220.1,144,220L144,220z"/>
- <path d="M384,128.3c0-17.8-14.4-32.2-32.1-32.2c-17.7,0-32.1,14.4-32.1,32.1c0,12.1,6.7,22.7,16.6,28.2c1.3,1.5,2.2,4.5,2.2,6
- c0,0.1,0,0.2,0,0.4c-0.8,17.6-3.8,31.9-7.1,41.7c-4.3,12.6-38.2,39.6-51.5,42.2c-5.8,1.2-7.9-0.6-7.9-10.2c0,0,0-138.9,0-140.4
- s0.2-3.5,1.9-5c0,0,0,0,0,0c8.6-5.8,14.3-15.6,14.3-26.8c0-17.8-14.4-32.2-32.1-32.2c-17.7,0-32.1,14.4-32.1,32.2
- c0,11.3,5.8,21.3,14.6,27c0,0,0.1,0.1,0.1,0.1c0.1,0.1,0.2,0.1,0.4,0.2c0.2,0.1,0.4,0.2,0.6,0.4c2.3,1.5,3.3,3,3.3,4.2
- c0,1.3,0,189.3,0,196.3s-1.1,12.3-8.4,11.8s-41.7-23.5-51.4-44.1c-4.5-9.5-6.8-18.8-6.8-28h0c0,0,0-0.4,0-0.5
- c0-3.1,0-11.3,3.2-13.6c7.8-5.9,12.8-15.2,12.8-25.7c0-17.8-14.4-32.2-32.1-32.2S128,174.4,128,192.2c0,11.9,6.5,22.3,16,27.8
- c2.4,1.5,3,2.9,3.8,10.6s3,24.6,9.1,39.9c7.3,18.6,20.9,32.6,39.7,45.2c13.6,9.3,25.3,16.6,32.1,26.4s10.2,13.5,10.2,27
- c0,0,0-0.9,0,0c0,12.8-4,14-9.3,17.8c-14.1,8.7-23.5,24.2-23.5,42c0,0.1,0,0.3,0,0.4c0,0.2,0,0.5,0,0.7c0,27.5,22.3,49.8,49.8,49.8
- c27.5,0,49.8-22.3,49.8-49.8c0-13.3-5.2-25.4-13.7-34.3c-2.9-3.2-6-6-9.6-8.3c-7.5-5.2-10.3-11.5-10.3-18.1v-24.1
- c0-25.1,4.1-41.1,11.1-53.3c7.3-12.7,18.3-22.6,35.4-34.2c18.8-12.6,32.2-26.6,39.6-45.2c5.7-14.4,7.6-31,8.6-50.9
- c0.1-1.8,1.4-5.8,3.3-6.8h0C378.4,149,384,139.3,384,128.3z M160.1,208.3c-8.9,0-16.1-7.3-16.1-16.2s7.2-16.2,16.1-16.2
- s16.1,7.3,16.1,16.2S169,208.3,160.1,208.3z M256,80.3c-8.9,0-16.1-7.3-16.1-16.2S247.1,48,256,48s16.1,7.3,16.1,16.2
- S264.9,80.3,256,80.3z M351.9,144.3c-8.9,0-16.1-7.3-16.1-16.2S343,112,351.9,112s16.1,7.3,16.1,16.2S360.8,144.3,351.9,144.3z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/videocamera.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/videocamera.svg
deleted file mode 100644
index 3d2633e7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/videocamera.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M367,185.3c0-5.1-4-9.3-9.2-9.3H306v-32.2c0-35.2-29.3-63.8-64.9-63.8H63v48h176.1c4.5,0,9.9,5.6,9.9,10.1V176H41.4
- c-5.2,0-9.4,4.2-9.4,9.3v170.4v55.7v11.3c0,5.1,4.2,9.3,9.4,9.3h316.4c5.2,0,9.2-4.2,9.2-9.3v-64.5l113,34.7v-88.2v-88.2l-113,34.7
- V185.3z M258.2,341h-10.9H152h-11.9c-19.8,0-35.9-16-35.9-35.8s16.1-35.8,35.9-35.8c19.8,0,35.9,16.2,35.9,36
- c0,10-4.2,18.6-10.8,25.6h67.9c-6.6-7-10.8-15.6-10.8-25.6c0-19.8,16.1-35.9,35.9-35.9c19.8,0,35.9,15.9,35.9,35.7
- S278,341,258.2,341z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-high.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-high.svg
deleted file mode 100644
index 07323442..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-high.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="231,407.8 231,104.3 136.1,192 32,192 32,320 136.1,320 "/>
- <path d="M287.1,355.7c20.5-27.9,32.8-62.3,32.8-99.7c0-37.4-12.3-71.8-32.8-99.7l-20.4,15.3c17.4,23.6,27.8,52.7,27.8,84.4
- c0,31.6-10.4,60.8-27.8,84.3L287.1,355.7z"/>
- <path d="M353.7,401.7c30-40.7,48-91.1,48-145.7s-18-104.9-48-145.7l-20.4,15.3c26.9,36.4,43,81.5,43,130.4
- c0,48.9-16.1,93.9-43,130.3L353.7,401.7z"/>
- <path d="M396.7,79.4c36.4,49.3,57.9,110.5,57.9,176.6c0,66.1-21.5,127.2-57.9,176.6l20.5,15.4c39.4-53.6,62.8-120,62.8-192
- c0-72-23.4-138.4-62.8-192L396.7,79.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-low.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-low.svg
deleted file mode 100644
index c96ed47e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-low.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="311,407.7 311,104.4 216.2,192 112,192 112,320 216.2,320 "/>
- <path d="M367.2,355.6c20.5-27.8,32.8-62.3,32.8-99.6c0-37.4-12.3-71.8-32.8-99.6l-20.4,15.3c17.4,23.6,27.8,52.7,27.8,84.3
- c0,31.6-10.4,60.7-27.8,84.3L367.2,355.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-medium.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-medium.svg
deleted file mode 100644
index 24388ea0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-medium.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="270,407.7 270,104.4 175.3,192 71,192 71,320 175.3,320 "/>
- <path d="M326.3,355.6c20.5-27.8,32.8-62.3,32.8-99.6c0-37.4-12.3-71.8-32.8-99.6l-20.4,15.3c17.4,23.6,27.8,52.7,27.8,84.3
- c0,31.6-10.4,60.7-27.8,84.3L326.3,355.6z"/>
- <path d="M392.8,401.6c30-40.7,48-91,48-145.6s-18-104.9-48-145.6l-20.4,15.3c26.9,36.4,43,81.4,43,130.3c0,48.9-16.1,93.8-43,130.3
- L392.8,401.6z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-mute.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-mute.svg
deleted file mode 100644
index 317b0617..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/volume-mute.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <polygon points="255.9,217 191,217 191,295 255.9,295 303,346.3 303,165.7 "/>
- <path d="M364.5,60.1c-0.4-0.2-0.7-0.4-1.1-0.6C331.5,42,294.9,32,256,32C132.3,32,32,132.3,32,256c0,84.3,46.6,157.6,115.4,195.9
- c0.4,0.2,0.7,0.5,1.1,0.7C180.5,470,217.1,480,256,480c123.7,0,224-100.3,224-224C480,171.7,433.4,98.3,364.5,60.1z M393.9,355.4
- L336,297.1v76.7l19.6,19.9c-28,20.3-62.3,32.7-99.5,32.7c-21.6,0-42.3-4.2-61.3-11.5c-6.5-2.5-12.9-5.3-19-8.6
- c-53.6-28.7-90.1-85.2-90.1-150.3c0-37.2,12.4-71.4,32.7-99.4l35.3,35.4h76.7l-73.6-73.8c28-20.2,62.1-32.6,99.4-32.6
- c21.6,0,42.2,4.2,61.3,11.5c6.1,2.4,12.2,5,17.9,8c54.2,28.5,91.3,85.3,91.3,150.8C426.5,293.3,414.2,327.4,393.9,355.4z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wand.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wand.svg
deleted file mode 100644
index e21ddb9a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wand.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
-<g>
-
- <rect x="238.059" y="206.059" transform="matrix(0.7071 0.7071 -0.7071 0.7071 249.3726 -122.0387)" width="67.882" height="67.882"/>
-
- <rect x="110.058" y="243.549" transform="matrix(0.7071 0.7071 -0.7071 0.7071 302.3989 5.9646)" width="67.884" height="248.901"/>
- <rect x="256" y="32" width="32" height="64"/>
- <rect x="380.451" y="83.55" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 595.0701 477.5923)" width="32" height="63.999"/>
- <rect x="131.549" y="83.549" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -38.4898 138.1746)" width="32" height="64"/>
- <rect x="380.451" y="332.451" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -141.5881 387.0668)" width="32" height="64"/>
- <rect x="416" y="224" width="64" height="32"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/waterdrop.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/waterdrop.svg
deleted file mode 100644
index be14c5eb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/waterdrop.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M271,38.6c-0.3-0.4-0.7-0.7-0.9-1c0,0-0.1-0.1-0.1-0.1c-3.6-3.4-8.5-5.5-13.9-5.5c-5.5,0-10.4,2.1-13.9,5.5
- c0,0-0.1,0.1-0.1,0.1c-0.3,0.3-0.6,0.6-0.9,1c-6.1,6.3-13.8,14.4-22.4,24.1c-17.4,19.7-38.6,46-58.5,76.8
- c-33.4,51.8-62.9,116.1-64.1,183.1c0,1.3-0.1,2.7-0.1,4c0,19.7,3.9,38.5,10.9,55.8c4.1,10,9.2,19.4,15.2,28.2
- C150.7,452.4,200,480,256,480c88.4,0,160-68.7,160-153.4C416,198.7,310.8,79.2,271,38.6z M256,424c-15.8,0-30.7-3.7-43.9-10.1
- c65.9-14.4,118.4-64.7,135.8-129.5c5.2,12.1,8.2,25.5,8.2,39.6C356,379.2,311.2,424,256,424z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wifi.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wifi.svg
deleted file mode 100644
index 6f6bc923..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wifi.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M256.1,96L256.1,96c-79.9,0-155.7,29.9-213.9,84.1L32,189.6l9.9,9.8l32.3,32l9.3,9.2l9.6-8.8
- c44.5-40.9,102.3-63.5,162.8-63.5c60.5,0,118.4,22.6,162.8,63.5l9.6,8.8l9.3-9.2l32.3-32l9.9-9.8l-10.2-9.5
- C411.6,125.9,335.7,96,256.1,96z"/>
- <path d="M397.4,256.4c-38.8-35.1-88.9-54.4-141.1-54.4h-0.1h-0.3h-8.5l-0.1,0.2c-49.2,2-96,21.1-132.6,54.2l-10.5,9.5l10.1,10
- l32.7,32.4l9.1,9l9.6-8.4c25.3-22.2,57.4-34.5,90.3-34.5c33.1,0,65.2,12.3,90.5,34.5l9.6,8.4l9.1-9l32.7-32.4l10.1-10L397.4,256.4z
- "/>
- <path d="M256.2,416l9.6-9.5l52.8-52.2l10.6-10.5l-11.6-9.5c-15.4-11.4-32.4-20-61.5-20c-29,0-44.9,9.4-61.5,20l-11.5,9.5l10.6,10.5
- l52.8,52.2L256.2,416z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wineglass.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wineglass.svg
deleted file mode 100644
index 9148d207..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wineglass.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M294.9,295.4c11-4.1,18-6.9,26.2-11.7c12-6.9,22.8-15.8,31.9-26.1c20.4-22.9,31-51.1,31-86.1c0-49.9-3.7-101.1-8.1-114.7
- C371.5,43,362.4,32,345.2,32H166.7c-17.1,0-26.2,11.1-30.6,24.6c-4.4,13.5-8.1,64.9-8.1,114.8c0,35.1,10.6,63.2,30.9,86.1
- c9.1,10.3,19.9,19.1,31.8,26c8.2,4.8,15.1,7.8,26,11.7s22.3,7.5,22.3,31.8v94.2c0,10.7-2.9,19-11.1,24.8c-2.8,2.1-6.3,4.3-14.3,6.5
- c-31.5,8.6-46.9,15.6-49.2,17.2c-2,1.4-4.5,3.6-4.5,7.1c0,0,13.8,3.1,96.2,3.1c82.4,0,96-3.1,96-3.1c0-3.5-2.5-5.7-4.6-7.1
- c-2.3-1.6-17.8-8.6-49.4-17.2c-8-2.2-12.2-4.4-15.1-6.5C275,440.3,271,432,271,421.3v-94.2C271,303.1,283.9,299.4,294.9,295.4z
- M255.9,270.3c-25.4,0-48.5-10-65.5-26.3c-2.7-2.4-5.2-5-7.6-7.7c-15.6-17.5-22.4-36.7-23.1-64.8C159,143.3,159.6,99,167,64h177
- c6.3,24,9.1,76.8,7.7,107.2c-1.4,30.5-7.2,47.3-22.8,64.9c-2,2.2-3.9,4.3-6.1,6.4C305.7,259.7,282,270.3,255.9,270.3z"/>
- <path d="M336.2,170.6c0-7.5-0.1-31.9-1.3-52.6c-0.5-8.4-1.2-16-2.1-22h-153c-0.9,3-1.8,11.6-2.5,22c-1.3,18.9-2.1,43.9-1.5,52.9
- c0.9,13.8,1.5,20.6,4.5,29.4c3.1,9.1,8,17.3,14.6,24.7c2,2.3,4.1,4.4,6.4,6.4c14.2,13.6,33.5,22,54.7,22c21.8,0,41.5-8.8,55.9-23.1
- c1.8-1.7,3.5-3.5,5.2-5.3c6.6-7.4,11.4-15.5,14.5-24.6C334.7,191.4,336.2,181.1,336.2,170.6z M320,179c0,5-3.9,8.1-8.3,8.1
- c-1.6,0-3-0.5-4.3-1.3c-2.2-1.4-3.5-3.9-3.5-6.7v-26c0-4.4,3.6-8,8-8s8,3.6,8,8V179z M318.9,131.8c-1.2,1.8-3,3-5.1,3.5
- c-2.1,0.4-4.3,0-6-1.1c-1.8-1.2-3-3-3.5-5.1c-0.4-2.1,0-4.3,1.1-6c1.2-1.8,3-3,5.1-3.5c2.1-0.4,4.3,0,6,1.1c1.8,1.2,3,3,3.5,5.1
- C320.5,127.8,320.1,130,318.9,131.8z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/woman.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/woman.svg
deleted file mode 100644
index 0819b61d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/woman.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
- <path d="M190.4,148.6L161,252.9c-6.3,22.8,20.7,31.7,27.3,10.3l26.3-96.2h7.4l-45.2,169H219v127c0,23,32,23,32,0V336h10v127
- c0,23,31,23,31,0V336h43.4l-46.2-169h8.4l26.3,96.2c6.5,21.9,33.3,12.5,27.3-10.2l-29.4-104.4c-4-11.8-18.2-32.6-42-33.6h-47.3
- C207.9,116,193.8,136.6,190.4,148.6z"/>
- <path d="M292.6,69.2c0-20.6-16.4-37.3-36.6-37.3c-20.2,0-36.6,16.7-36.6,37.3c0,20.6,16.4,37.3,36.6,37.3
- C276.2,106.5,292.6,89.8,292.6,69.2z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wrench.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wrench.svg
deleted file mode 100644
index 11458e24..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/wrench.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path d="M461.9,114.9l-56.5,56.7l-55.1-10l-9.9-55.1l56.5-56.7c-12.7-12.7-30.8-18.5-44.2-17.8c-13.5,0.7-42.3,8.3-64.6,32
- c-21.6,22.8-44.3,65.3-24.2,112.5c2.4,5.7,5.1,13.2-2.9,21.2c-8.1,8-215,202.8-215,202.8c-19.4,16.7-18,47.6-0.1,65.6
- c18.2,17.9,48.9,19,65.6-0.3c0,0,193.2-205.8,202.7-215.1c8.5-8.3,16.1-5.5,21.2-2.9c35.6,18.4,86.3,2.4,112.6-23.9
- c26.3-26.3,31.1-51.7,31.9-64.7C480.7,146.3,476.2,129.2,461.9,114.9z M91.3,443.2c-6.3,6.2-16.5,6.2-22.7,0
- c-6.2-6.3-6.2-16.5,0-22.7c6.3-6.2,16.5-6.2,22.7,0C97.5,426.8,97.5,437,91.3,443.2z"/>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/xbox.svg b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/xbox.svg
deleted file mode 100644
index 41a4bd31..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/ionicons-2.0.1/src/xbox.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<style type="text/css">
-<![CDATA[
- .st0{fill:#010101;}
-]]>
-</style>
-<g>
- <path class="st0" d="M126.8,248.3c39.7-58.6,77.9-92.8,77.9-92.8s-42.1-48.9-92.8-67.4l-3.3-0.8C61.7,128.4,32,188.7,32,256
- c0,50.7,16.9,97.5,45.2,135C77.2,386.6,77.8,320.7,126.8,248.3z"/>
- <path class="st0" d="M480,256c0-67.3-29.7-127.6-76.6-168.7l-3.2,0.9c-50.7,18.5-92.9,67.4-92.9,67.4s38.2,34.2,77.9,92.8
- c49,72.4,49.6,138.3,49.5,142.7C463.2,353.5,480,306.7,480,256z"/>
- <path class="st0" d="M201.2,80.9c29.3,13.1,54.6,34.6,54.6,34.6s25.5-21.4,54.8-34.6c36.8-16.5,64.9-11.3,72.3-9.5
- C346.8,46.6,303.1,32,256,32c-47.1,0-90.8,14.6-126.9,39.4C136.3,69.6,164.3,64.3,201.2,80.9z"/>
- <path class="st0" d="M358.7,292.9C312.4,236,255.8,199,255.8,199s-56.3,37-102.7,93.9c-39.8,48.9-54.6,84.8-62.6,107.8l-1.3,4.8
- c41,45.7,100.5,74.5,166.8,74.5c66.3,0,125.8-28.8,166.8-74.5l-1.4-4.8C413.4,377.7,398.5,341.8,358.7,292.9z"/>
-</g>
-</svg>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/utils/js/browserCheck.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/utils/js/browserCheck.js
deleted file mode 100644
index ad88b2d4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/external/utils/js/browserCheck.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
-var isFirefox = typeof window.InstallTrigger !== 'undefined';
-var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
-var isChrome = !!window.chrome && !isOpera;
-var isIE = !!document.documentMode;
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js
deleted file mode 100644
index ee8b46a9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
-
- //.when('/notebook-frame/:id/:key/:value',{
- //.when('/notebook-frame/:nid/:qprms',{
- /*.when('/notebook-frame',{
- templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
- controller: 'notebookFrameController'
- })*/
-
- .otherwise({
- templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-viz.html',
- controller: 'notebookFrameController'
- });
-})
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js
deleted file mode 100644
index d8492404..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/nbookController.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-
-app.config(function($routeProvider) {
- $routeProvider
-
- //.when('/notebook-frame/:id/:key/:value',{
- //.when('/notebook-frame/:nid/:qprms',{
- /*.when('/notebook-frame',{
- templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
- controller: 'notebookFrameController'
- })*/
-
- .otherwise({
- // templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebook-frame.html',
- templateUrl: 'app/fusion/notebook-integration/scripts/view-models/notebookInputs.html',
- controller: 'nbookController'
- });
-}).controller('nbookController', ['$scope', '$location','$window','$http', function ($scope,$location,$window,$http) {
-
- $scope.keyValueList = [{}];
- console.log('onload nbookController');
- $scope.submitParameters = function() {
-
- $scope.iframevisibility = false;
- console.log('Inside nbook invoke save');
-
- $scope.postData = {};
-
- $scope.additionalqueryParams = {};
-
- //Use this if there is only one 1 query param key value pair
- $scope.additionalqueryParams.paramKey = $scope.qparamKey;
- $scope.additionalqueryParams.paramVal = $scope.qparamVal;
-
-
- // console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
- console.log('$scope.notebookvalue',$scope.notebookvalue);
-
-
- //$scope.postData['notebookid'] = 'a06a9cf14211012e221bf842c168849d';
- //$scope.postData['param1'] = 'p1';
- //$scope.postData['param2'] = 'p2';
-
- //console.log('Report Schedule object', $scope.reportScheduleObject);
-
-
- /* if ($window.location.search.substr($window.location.search.indexOf("=")+1)) {
- $scope.queryParams = $window.location.search;
-
- if ($window.location.search.indexOf("&")!=-1) {
- $scope.notebookparam = $window.location.search.substring($window.location.search.indexOf("?")+1,$window.location.search.indexOf("&"));
- $scope.additionalqueryParams = JSON.parse('{"' + decodeURI($scope.queryParams.substr($scope.queryParams.indexOf("&")+1).replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}');
- console.log('Additional parameters present');
- }
- else {
- $scope.notebookparam = $window.location.search.substr($window.location.search.indexOf("?")+1);
- console.log('Additional parameters absent');
- }
- console.log('add parameters',$scope.additionalqueryParams);
- // $scope.notebookid = $scope.notebookparam.substring(0,$scope.notebookparam.indexOf("="));
- $scope.notebookvalue = $scope.notebookparam.substr($scope.notebookparam.indexOf("=")+1);
- $scope.postData = $window.location.search.substr($window.location.search.indexOf("=")+1);
- console.log('Notebook value present ',$scope.notebookvalue);
- }
- else {
- $scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
- console.log('Notebook value absent ',$scope.notebookvalue);
- }*/
-
- // $http.get("notebook.htm#/notebook-frame", {params : {"a" : "b"}})
-
- /* $http.get("app/fusion/notebook-integration/scripts/view-models/notebook-frame.html", {params : {"a" : "b"}})
- .then(function(response) {
- console.log("Got response from http get ");
- // window.open ('notebook.htm#/notebook-frame','_self',false);
- }); */
-
- // $location.search(1, $scope.additionalqueryParams);
-// }
- console.log('$scope.additionalqueryParams',$scope.additionalqueryParams);
-// $scope.invokeSaveNotebook() = function() {
- // window.open ('notebook.htm#/notebook-frame/1/2/3','_self',false);
-
- //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue;
- //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+encodeURIComponent(JSON.stringify($scope.additionalqueryParams));
- // var testurl = 'notebook.htm#/notebook-frame/' + $scope.notebookvalue + '/' + encodeURIComponent(JSON.stringify($scope.additionalqueryParams));
-
- console.log('$scope.keyValueList',$scope.keyValueList);
-
- /*for (var obj in $scope.keyValueList) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
- console.log('property',obj[prop]);
- //console.log("prop: " + prop.qk + " value: " + obj[prop.qk]);
- }
- }
- }*/
-
- console.log('$scope.keyValueList.length',$scope.keyValueList.length);
-
- var qryStr = '';
- for(var i = 0; i < $scope.keyValueList.length; i++) {
- var obj = $scope.keyValueList[i];
- //console.log('obj.qK',obj.qK);
- if (obj.qK != undefined && obj.qV != undefined) {
- //console.log('Inside qk defined');
- if (qryStr!='')
- qryStr = qryStr+'&'+obj.qK+'='+obj.qV;
- else
- qryStr = obj.qK+'='+obj.qV;
-
- }
-
- }
- console.log('qryStr',qryStr);
-
-
-
- //var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&k1='+$scope.additionalqueryParams.paramKey+'&v1='+$scope.additionalqueryParams.paramVal;
-
- // var testurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+$scope.additionalqueryParams.paramKey+'='+$scope.additionalqueryParams.paramVal;
-
- var queryurl = 'nbooktest.htm?nid='+$scope.notebookvalue+'&'+qryStr;
-
- // var testurl = 'notebook.htm#/notebook-frame';
-
- window.open (queryurl,'_self',false);
-
-
- }
-
- $scope.addKeyValuePairs = function (kv) {
-
-
- if ($scope.keyValueList.length < 9) {
- $scope.keyValueList.push({
-
- });
- // alert($scope.reportRunJson.rangeAxisList.length);
- // console.log('$scope.keyValueList',$scope.keyValueList);
-
- } else {
- //document.getElementById("addbtn").disabled = true;
- // $scope.btnactive = false;
- document.getElementById("addbtn")["disabled"] = true;
- //document.getElementById("addbtn")["style.background-color"] = "#FFFF00";
-
- //$('#addbtn').btn('type') = "disabled";
- }
- }
-
- $scope.removeKeyValuePairs = function (index) {
- $scope.keyValueList.splice(index, 1);
- if ($scope.keyValueList.length == 8) {
- document.getElementById("addbtn")["disabled"] = false;
- }
- //console.log($scope.hardCodeReport.rangeAxisList)
- }
-
-}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js
deleted file mode 100644
index 1285cb02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('notebookFrameController', function ($scope,$location,$window,$http,$routeParams) {
-
- //alert($location.search(1, $scope.additionalqueryParams));
- //var nid = $routeParams.nid;
- //var qprms = $routeParams.qprms;
- //var value = $routeParams.value;
- //console.log('check id ');
- var nid = $window.location.search.substr($window.location.search.indexOf("=")+1);
- console.log('nid',nid);
- //console.log('qprms',qprms);
-
- if ($window.location.search.substr($window.location.search.indexOf("=")+1)) {
- $scope.queryParams = $window.location.search;
-
- if ($window.location.search.indexOf("&")!=-1) {
- $scope.notebookparam = $window.location.search.substring($window.location.search.indexOf("?")+1,$window.location.search.indexOf("&"));
- $scope.additionalqueryParams = JSON.parse('{"' + decodeURI($scope.queryParams.substr($scope.queryParams.indexOf("&")+1).replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}');
- console.log('Additional parameters present');
- }
- else {
- $scope.notebookparam = $window.location.search.substr($window.location.search.indexOf("?")+1);
- console.log('Additional parameters absent');
- }
- console.log('add parameters',$scope.additionalqueryParams);
- // $scope.notebookid = $scope.notebookparam.substring(0,$scope.notebookparam.indexOf("="));
- $scope.notebookvalue = $scope.notebookparam.substr($scope.notebookparam.indexOf("=")+1);
- //$scope.postData = $window.location.search.substr($window.location.search.indexOf("=")+1);
- console.log('Notebook value present ',$scope.notebookvalue);
- }
- else {
- $scope.notebookvalue = '833c0a69ec1433fbb2f8752af733cf0e';
- console.log('Notebook value absent ',$scope.notebookvalue);
- }
-
-
-
- $http({method:'POST', url:'rNotebookFE/authCr', data: $scope.notebookvalue, params:{'qparams' : $scope.additionalqueryParams}}).success(function(data, status) {
- console.log('Data received', data);
- console.log('Status ', status);
- document.getElementById('itestframe').src = data;
-
- })
-
-
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html
deleted file mode 100644
index 5428c6c6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-frame.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!-- <!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
-<head>
-<meta charset="ISO-8859-1">
-<title>Insert title here</title>
-</head>
-<body>
-<div style="min-height:500px" data-ng-init="invokeSaveNotebook()">
-
-
- <div><iframe id='itestfr' width="1400" height="1400"></iframe></div>
-
-
- </div>
-
-</body>
-</html> -->
-
-<!-- <div ng-controller="notebookFrameController" style="min-height:500px">
-
-
- <div><iframe id='itestframe' width="1400" height="1400"></iframe></div>
-
-
- </div> -->
-
-<!DOCTYPE html>
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache"/>
-
- <script src= "app/fusion/scripts/utils/page-resource.js"></script>
-
- <script>
- // loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookController.js", "js");
-
- loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookFrameController.js", "js");
- loadjscssfile("app/fusion/notebook-integration/scripts/controllers/nbook-framecontroller.js", "js");
-
- </script>
-
-
-
-
- </head>
- <body class="appBody" ng-app="abs">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:110px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
-
-
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html
deleted file mode 100644
index 3c0afd29..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook-viz.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
- <div style="min-height:500px">
-
-
- <div><iframe id='itestframe' width="1400" height="1400"></iframe></div>
-
-
- </div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm
deleted file mode 100644
index bfd74ad3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebook.htm
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache"/>
-
- <script src= "app/fusion/scripts/utils/page-resource.js"></script>
- <!-- Icons -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
- <script>
- // loadjscssfile("app/fusion/notebook-integration/scripts/controllers/notebookController.js", "js");
- loadjscssfile("app/fusion/notebook-integration/scripts/controllers/nbookController.js", "js");
- </script>
-
-
-
-
- </head>
- <body class="appBody" ng-app="abs">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_edit.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:110px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html
deleted file mode 100644
index 0a28b50e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/notebook-integration/scripts/view-models/notebookInputs.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
-<head>
-<meta charset="ISO-8859-1">
-<title></title>
-</head>
-<body>
-
-<div style="min-height:500px">
- <br>
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Notebook ID:</label><BR>
- <input type="text" name="notebookid" maxlength=200 ng-model="notebookvalue" style="width:180px"/>
- </div>
- <BR>
-
- <!-- Use this for only 1 key value query parameter
- <div class="fn-ebz-container">
-
- <label class="fn-ebz-text-label">Key</label><BR>
- <input type="text" name="key" maxlength=200 ng-model="qparamKey" style="width:180px"/>
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Value</label><BR>
- <input type="text" name="val" maxlength=200 ng-model="qparamVal" style="width:180px"/>
- </div> -->
-
-
-
- <!-- Use this for multiple key value query parameters -->
- <div style="border:2px;border-style:solid;border-color:#808080;margin-bottom:9px">
- <div ng-repeat="kv in keyValueList">
- <div style="margin-left:5px">
-
- <div class="fn-ebz-container">
-
- <label class="fn-ebz-text-label">Key</label><BR>
- <input type="text" name="key" maxlength=100 ng-model="kv.qK" style="width:180px"/>
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Value</label><BR>
- <input type="text" name="val" maxlength=100 ng-model="kv.qV" style="width:180px"/>
- </div>
-
- <div class="fn-ebz-container" style="position:relative; top: 25px;">
- <button href="javascript:void(0)" id="addbtn" ng-show="{{$index==0}}" style="float: right;" att-button size="small" att-accessibility-click="13,32"
- ng-click="addKeyValuePairs(kv);" >Add</button>
- <a href="javascript:void(0)" ng-show="{{$index>0}}" style="float: right;" att-button size="small" att-accessibility-click="13,32" ng-click="removeKeyValuePairs($index);" >
- Remove</a>
- </div>
- </div>
- </div>
- </div>
-
-
-
-
- <BR>
-
- <div class="fn-ebz-container">
- <a att-button btn-type="primary" att-accessibility-click="13,32" ng-click="submitParameters();">Submit</a>
- </div>
-
- <!-- <div ng-show="iframevisibility"><iframe id='itestfr' width="1400" height="1400"></iframe></div> -->
-
-</div>
-</body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/adminController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/adminController.js
deleted file mode 100644
index a99be9fe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/adminController.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
-
-
- .when('/role_function_list', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/role_function_list.html',
- controller: 'roleFunctionListController'
- })
-
- .when('/admin_menu_edit', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/admin_menu_edit.html',
- controller: 'AdminMenuEditController'
- })
- .when('/role/:roleId', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/role.html',
- controller: 'roleController'
- })
- .when('/jcs_admin', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/jcs_admin.html',
- controller: 'cacheAdminController'
- })
- .when('/broadcast_list', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/broadcast_list.html',
- controller: 'broadcastListController'
- })
- .when('/broadcast/:messageLocationId/:messageLocation/:messageId', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/broadcast.html',
- controller: 'broadcastController'
- })
- .when('/broadcast/:messageLocationId/:messageLocation', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/broadcast.html',
- controller: 'broadcastController'
- })
- .when('/collaborate_list', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/collaborate_list.html',
- controller: 'collaborateListController'
- })
- .when('/usage_list', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/usage_list.html',
- controller: 'usageListController'
- })
- .otherwise({
- templateUrl: 'app/fusion/scripts/view-models/profile-page/role_list.html',
- controller : "roleListController"
- });
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/admin_menu_edit.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/admin_menu_edit.js
deleted file mode 100644
index 54d58a45..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/admin_menu_edit.js
+++ /dev/null
@@ -1,230 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('AdminMenuEditController', function ($scope, AdminService, modalService, $modal, $route){
- $( "#dialog" ).hide();
-
-/* AdminService.getRoleFunctionList().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.availableRoleFunctions =JSON.parse($scope.data.availableRoleFunctions);
-
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });*/
- $scope.init = function () {
- $scope.numberOfRecordstoShow=20;
- AdminService.getFnMenuItems().then(function(data){
- var j = data;
- $scope.data =JSON.parse(j.data);
- $scope.fnMenuItems =($scope.data.fnMenuItems);
-
- },function(error){
- console.log("failed");
- //reloadPageOnce();
- });
- }
- $scope.init();
- $scope.mapActiveStatus = function(status){
- if(status)
- status = "Y";
- else
- status = "N";
- return status;
-
- };
-
-
- $scope.addNewFnMenuItemModalPopup = function(availableFnMenuItem) {
- $scope.editFnMenuItem = null;
- var modalInstance = $modal.open({
- templateUrl: 'fn_menu_add_popup.html',
- controller: 'fn_menu_popupController',
- resolve: {
- message: function () {
- var message = {
- availableFnMenuItem: $scope.editFnMenuItem
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.availableFnMenuItems=response.availableFnMenuItems;
- $route.reload();
- });
- };
-
- $scope.removeMenuItem = function(fnMenuItem) {
- modalService.popupConfirmWin("Confirm","You are about to delete the menu item "+fnMenuItem.label+". Do you want to continue?",
- function(){
- var uuu = "admin_fn_menu/removeMenuItem.htm";
- var postData={fnMenuItem: fnMenuItem};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.fnMenuItem=data.fnMenuItem;});
- $route.reload();
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
-
- };
-
- $scope.editRoleFunction = null;
- var dialog = null;
- $scope.editRoleFunctionPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.editMenuItemModalPopup = function(availableFnMenuItem) {
- $scope.editFnMenuItem = availableFnMenuItem;
- var modalInstance = $modal.open({
- templateUrl: 'fn_menu_add_popup.html',
- controller: 'fn_menu_popupController',
- resolve: {
- message: function () {
- var message = {
- availableFnMenuItem: $scope.editFnMenuItem
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- $scope.availableFnMenuItems=response.availableFnMenuItems;
- $route.reload();
- });
- };
-
- $scope.editRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- });
- };
-
- $scope.addNewRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = null;
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- });
- };
-
- $scope.addNewRoleFunctionPopup = function() {
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.saveRoleFunction = function(availableRoleFunction) {
- var uuu = "role_function_list/saveRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.availableRoleFunctions=[];$scope.$apply();
- $scope.availableRoleFunctions=data.availableRoleFunctions;});
- //alert("Update Successful.") ;
- console.log($scope.availableRoleFunctions);
-
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog("close");
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
-
- $scope.removeRole = function(availableRoleFunction) {
- modalService.popupConfirmWin("Confirm","You are about to delete the role function "+availableRoleFunction.name+". Do you want to continue?",
- function(){
- var uuu = "role_function_list/removeRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.availableRoleFunctions=data.availableRoleFunctions;});
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
-
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js
deleted file mode 100644
index 45fc31ac..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/ase-controller.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('aseCtrl', function ($scope){
-/* do nothing yet*/
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js
deleted file mode 100644
index 77ee22f5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/broadcast-controller.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('broadcastController', function ($scope, modalService, $modal,AdminService,$routeParams){
- //$scope.broadcastMessage=${broadcastMessage};
- //$scope.broadcastSites=${broadcastSites};
- //console.log($scope.broadcastMessage);
- $scope.broadcastMessage=[];
- $scope.broadcastSites=[];
- AdminService.getBroadcast($routeParams.messageLocationId, $routeParams.messageLocation, $routeParams.messageId).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.broadcastMessage=JSON.parse($scope.data.broadcastMessage);
- $scope.broadcastSites=JSON.parse($scope.data.broadcastSites);
- console.log($scope.broadcastMessage);
- console.log($scope.broadcastMessage.id);
- console.log($scope.broadcastSites);
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.save = function() {
- var uuu = "broadcast/save";
- var postData={broadcastMessage: $scope.broadcastMessage};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- window.location.href = "admin#/broadcast_list";
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
- $scope.close = function() {
- window.location.href = "admin#/broadcast_list";
-};
-
-});
-
-$(function() {
- $( "#startDatepicker" ).datepicker();
- $( "#endDatepicker" ).datepicker();
-
- $( "#startDatepicker" ).change(function() {
- var tempStartDate = moment($( "#startDatepicker" ).val()).format('YYYY-MM-DD hh:mm:ss.S');
- $( "#startDateHidden" ).val(tempStartDate.toString());
- //alert( $( "#startDateHidden" ).val() );
- });
- $( "#endDatepicker" ).change(function() {
- var tempEndDate = moment($( "#endDatepicker" ).val()).format('YYYY-MM-DD hh:mm:ss.S');
- $( "#endDateHidden" ).val(tempEndDate.toString());
- //alert( $( "#endDateHidden" ).val() );
- });
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js
deleted file mode 100644
index 5b0b9342..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/collaborate-list-controller.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller("collaborateListController", function ($scope,$http,modalService, $modal,AdminService) {
- // Table Data
- AdminService.getCollaborateList().then(function(data){
-
- var j = data;
- $scope.tableData = JSON.parse(j.data);
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.viewPerPage = 20;
- $scope.scrollViewsPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- /* modalService.showSuccess('','Modal Sample') ; */
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- $scope.openCollaboration = function(chatId){
- openInNewTab('collaboration?chat_id=' + chatId);
- }
-
- $scope.toggleProfileActive = function(profileId) {
- modalService.popupConfirmWin("Confirm","You are about to change user's active status. Do you want to continue?",
- function(){
- $http.get("profile/toggleProfileActive?profile_id="+profileId).success(function(){});
-
- })
- };
-
-});
-
-function openInNewTab(url) {
- var win = window.open(url, '_blank');
- win.focus();
-};
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/fn_menu_add_popup_controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/fn_menu_add_popup_controller.js
deleted file mode 100644
index e0179946..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/fn_menu_add_popup_controller.js
+++ /dev/null
@@ -1,281 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var fn_menu_popupController = function ($scope, $modalInstance, message, $http){ /// examine the LeftMenuService
- if(message.availableFnMenuItem==null)
- $scope.label='Add New Menu Item'
-
- else{
- $scope.label='Edit Menu Item'
- //$scope.disableParentId=true;
- }
-
- $scope.getParentData = function(){
- var uuu = "admin_fn_menu/get_parent_list"
- $.ajax({
- type : 'GET',
- url : uuu,
- dataType: 'json', // data type expected from server
- contentType: 'application/json',
- //data: JSON.stringify(postData), // data type sent to server
- success : function(data){
- $scope.$apply(function(){
- //$scope.availableRoleFunctions=[];$scope.$apply();
- $scope.parentListSelectData=data; // data from server
- menuItems = $scope.parentListSelectData;
- var heirarchicalMenuItems = [];
- var children = [];
- for ( var i=0; i<menuItems.length; i++){
- for(var j=0; j<menuItems.length; j++){
- if(menuItems[j][2]==menuItems[i][0])
- children.push(
- {
- menuId: menuItems[j][0],
- label: menuItems[j][1]
- }
- );
- }
- if(children.length!=0){
- heirarchicalMenuItems.push(
- {
-
- menuId: menuItems[i][0],
- label: menuItems[i][1],
- children: children.sort($scope.sortItems("label"))
- }
-
- );
- }
- children = [];
-
- }
- heirarchicalMenuItems.sort($scope.sortItems("label"));
- $scope.childListSelectData = heirarchicalMenuItems;
- //console.log(data);
- });
- //$scope.editRoleFunction = null;
- ///$modalInstance.close({functionCDselectData:$scope.functionCDselectData});
- },
- error : function(data){
- alert("Parent Data not available !");
- }
- });
-
- };
-
- $scope.sortItems = function(prop){
- return function(a, b) {
- if (a[prop] > b[prop]) {
- return 1;
- } else if (a[prop] < b[prop]) {
- return -1;
- }
- return 0;
- }
-
- };
-
- $scope.getParentLabel = function(parentId, parentListSelectData){
- var element;
- element = parentListSelectData[0];
- for (var i=0; i<parentListSelectData.length; i++){
-
- element = parentListSelectData[i];
- if (element[0] == parentId)
- return element[1];
- else "---";
- }
- };
-
-
- $scope.getFunctionCDselectData = function(){
- var uuu = "admin_fn_menu/get_function_cd_list"
- $.ajax({
- type : 'GET',
- url : uuu,
- dataType: 'json', // data type expected from server
- contentType: 'application/json',
- //data: JSON.stringify(postData), // data type sent to server
- success : function(data){
- $scope.$apply(function(){
- //$scope.availableRoleFunctions=[];$scope.$apply();
- $scope.functionCDselectData=data;
- });
- //alert("Update Successful.") ;
- //$scope.editRoleFunction = null;
- ///$modalInstance.close({functionCDselectData:$scope.functionCDselectData});
- },
- error : function(data){
- alert("Function Code Data not available !");
- }
- });
-
- };
-
- if(message.availableFnMenuItem){
- $scope.addFnMenuItem = message.availableFnMenuItem;
- } else {
- $scope.addFnMenuItem = {};
- }
- $scope.addFnMenuItem.menuSetCode = "APP";
-
- $scope.statusOptions = [
- {index: 0, value: 'true', title: 'Y'},
- {index: 1, value: 'false', title: 'N'}
- ];
- $scope.selectedValue = $scope.statusOptions[0];
-
- $scope.separator = {
- availableOptions:[
- {value: 'true', name: 'Y'},
- {value: 'false', name: 'N'}
- ],
-
- selectedOption: {value: 'true', name: 'Y'}
-
- };
-
-
- $scope.activeStatusOptions = [
- {index: 0, value: 'true', title: 'Y'},
- {index: 1, value: 'false', title: 'N'}
- ];
- $scope.activeSelectedValue = $scope.activeStatusOptions[0];
-
- $scope.separatorStatusOptions = [
- {index: 0, value: 'true', title: 'Y'},
- {index: 1, value: 'false', title: 'N'}
- ];
- $scope.separatorSelectedValue = $scope.separatorStatusOptions[1];
-
- $scope.active = {
- availableOptions:[
- {value: 'true', name: 'Y'},
- {value: 'false', name: 'N'}
- ],
-
- selectedOption: {value: 'true', name: 'Y'}
-
- };
-
-
- $scope.updateFnMenu = function(availableFnMenuItem) {
- // form validation
- if( document.getElementById("popupAddMenuItemImageSrc").value == "" ) availableFnMenuItem.imageSrc = "N/A";
- if( document.getElementById("popupAddMenuItemTarget").value == "" ) availableFnMenuItem.target = "N/A";
- if( document.getElementById("popupAddMenuItemExternalUrl").value == "" ) availableFnMenuItem.externalUrl = "N/A";
- if( document.getElementById("popupAddMenuItemQueryString").value == "" ) availableFnMenuItem.queryString = "N/A";
- if( document.getElementById("popupAddMenuItemServlet").value == "" ) availableFnMenuItem.servlet = "N/A";
-
- validationRule = /^\S{3,}$/;
- var selectedFunction = document.getElementById("repeatSelect");
- var selectedFunctionText = selectedFunction.options[selectedFunction.selectedIndex].text;
- if(
- (document.getElementById("popupAddMenuItemLabel").value == "" || document.getElementById("popupAddMenuItemLabel").value.replace(" ", "").length == 0 ) ||//!validationRule.test(document.getElementById("popupAddMenuItemLabel").value)) ||
- document.getElementById("popupAddMenuItemParentId").value == "" ||
- document.getElementById("popupAddMenuItemAction").value == "" ||
- selectedFunctionText == "" ||
- document.getElementById("popupAddMenuItemSortOrder").value == "" ||
- document.getElementById("popupAddMenuItemMenuSetCode").value == ""
- )
- {
- alert("please provide valid entries !");
- }
-
- else{
- var uuu = "admin_fn_menu/updateFnMenu.htm";
- var postData={availableFnMenuItem: availableFnMenuItem};
-
- $.ajax({
- type : 'POST',
- url : uuu,
- //dataType: 'json', // data type expected from server
- contentType: 'application/json',
- data: JSON.stringify(postData), // data type sent to server
- success : function(data){
- $scope.$apply(function(){
- $scope.availableFnMenuItems=data.availableFnMenuItems;
- });
-
- $modalInstance.close({availableFnMenuItems:$scope.availableRoleFunctions});
- },
- error : function(data){
- alert("Error while saving.");
- }
- });
-
- }
- $scope.getLeftMenuItems(); // get left menu items again from database
-
- };
-
- $scope.getLeftMenuItems = function() {
- return $http.get('get_menu')
- .then(function(response) {
- if (typeof response.data === 'object') {
- var leftChildData=[];
- var leftParentData=[];
- var leftMenuItems = [];
- var j = response;
- try{
- if(j && j !== "null" && j!== "undefined"){
- leftParentData = JSON.parse(j.data);
- leftChildData = JSON.parse(j.data2);
- }else{
- throw "Get Left Menu respsone is not an object/is empty";
- }
- try{
- var leftChildItemList = leftChildData;
- var pageUrl = window.location.href.split('/')[window.location.href.split('/').length-1];
- var leftParentList = leftParentData;
- for (var i = 0; i < leftParentList.length; i++) {
- $scope.item = {
- parentLabel : leftParentList[i].label,
- parentAction : leftParentList[i].action,
- parentImageSrc : leftParentList[i].imageSrc,
- open:pageUrl==leftParentList[i].action?true:false,
- childItemList : leftChildItemList[i]==null?'x':leftChildItemList[i]
- }
- leftMenuItems.push($scope.item);
- };
-
- $scope.leftMenuItems = leftMenuItems;
-
- }catch(err){
- console.log("error happened while trying to set left menu structure: "+err);
- }
- }catch (e) {
- console.log("error happened while trying to get left menu items: "+e);
- reloadPageOnce();
- return;
- }
- return response.data;
- } else {
- return $q.reject(response.data);
- }
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- };
-
- $scope.close = function() {
- $modalInstance.close();
- };
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/jcs-admin-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/jcs-admin-controller.js
deleted file mode 100644
index 3891c5eb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/jcs-admin-controller.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('cacheAdminController', function ($scope,$interval,$http,$modal,modalService,AdminService){
-
- AdminService.getCacheRegions().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.regions =$scope.data;
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
- $scope.clearAll = function() {
- modalService.popupConfirmWin("Confirm",'You are about to clear all of the items for all cache regions. Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearAll").success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.clearRegion = function(cacheName) {
- modalService.popupConfirmWin("Confirm",'You are about to clear all of the items in the cache region "' + cacheName + '". Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearRegion?cacheName="+cacheName).success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.clearItem = function(cacheName,key) {
- modalService.popupConfirmWin("Confirm",'You are about to clear this item from the cache region "' + cacheName + '". Do you want to continue?',
- function(){
- $http.get("jcs_admin/clearItem?keyName="+key+"&cacheName="+cacheName).success(function(response){$scope.regions=response;});
-
- })
- };
-
- $scope.showRegionDetails = function(cacheName) {
- $http.get("jcs_admin/showRegionDetails?cacheName="+cacheName).success(function(response){modalService.showSuccess('',response);});
- };
-
- $scope.showItemDetails = function(cacheName,key) {
- $http.get("jcs_admin/showItemDetails?keyName="+key+"&cacheName="+cacheName).success(function(response){
- var message = "CacheName: "+ response.cacheName
- +"\nkey: "+response.key
- +"\nIS_SPOOL: "+response.attr.IS_SPOOL
- +"\nIS_LATERAL: "+response.attr.IS_LATERAL
- +"\nIS_REMOTE: "+response.attr.IS_REMOTE
- +"\nIS_ETERNAL: "+response.attr.IS_ETERNAL
- +"\nversion: "+response.attr.version
- +"\nmaxLifeSeconds: "+response.attr.maxLifeSeconds
- +"\nmaxIdleTimeSeconds: "+response.attr.maxIdleTimeSeconds
- +"\nsize: "+response.attr.size
- +"\ncreateTime: "+response.attr.createTime
- +"\nlastAccessTime: "+response.attr.lastAccessTime
- +"\nidleTime: "+response.attr.idleTime
- +"\ntimeToLiveSeconds: "+response.attr.timeToLiveSeconds
- +"\nisSpool: "+response.attr.isSpool
- +"\nisLateral: "+response.attr.isLateral
- +"\nisRemote: "+response.attr.isRemote
- +"\nisEternal: "+response.attr.isEternal;
- modalService.showSuccess('',message);});
- };
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js
deleted file mode 100644
index 8d66d728..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/modelpopupController.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var modalpopupController = function ($scope, $modalInstance, message){
-
- $scope.message = message;
-
-
- $scope.hello = function () {
- $modalInstance.close($scope.digitPattern);
- };
- $modalInstance.ok = function() {
- //add the ok functionality
- alert("Logout");
- };
- $modalInstance.cancel = function() {
- //add the cancel functionality
- alert("Keep Log in");
- };
- $modalInstance.cancelbutton = function() {
- //add the cancel functionality
- alert("Modal Waring popup close event");
- };
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/post-search-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/post-search-controller.js
deleted file mode 100644
index edb2cc53..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/post-search-controller.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('postSearchCtrl', function ($scope,$http,ProfileService,modalService){
-
- $scope.viewPerPage = 200;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
-
- $scope.noResultsString = "";
-
- ProfileService.getPostProfile().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
-
- $scope.postSearchBean =JSON.parse($scope.data.postSearchBean);
- $scope.profileList =JSON.parse($scope.data.profileList);
- $scope.ngexistingUsers=JSON.parse($scope.data.existingUsers);
- $scope.ocisortByList=JSON.parse($scope.data.sortByList);
-
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.sortByList = [];
- if($scope.ocisortByList)
- $.each($scope.ocisortByList, function(i, a){
- var sortBy = {"index":i, "value":a.value, "title":a.label};
- $scope.sortByList.push(sortBy);
- });
- ;
-
- $scope.search = function(postSearchBean) {
- console.log(postSearchBean);
- var uuu = "post_search/search";
- var postData={postSearchBean:postSearchBean};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profileList=data.users;
- //$scope.postSearchBean={};
- console.log($scope.profileList);
- if($scope.profileList.length == 0)
- $scope.noResultsString = "There is currently no one in WEBPHONE matching your search criteria.";
- else
- $scope.noResultsString = "";
- });
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while searching: "+ data.responseText);
- }
- });
-
- };
-
- $scope.reset = function() {
- $scope.postSearchBean={};
- $scope.profileList=[];
- $scope.noResultsString = "";
- //console.log($scope.postSearchBean);
- };
-
- $scope.process = function() {
- $scope.prepareProfileSelection();
- var uuu = "post_search/process";
- var postData={postSearchBean:$scope.postSearchBean};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profileList=data.users;
- //$scope.postSearchBean={};
- $scope.ngexistingUsers=data.existingUsers;
- $scope.postSearchBean.selected=null;
- });
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while searching: "+ data.responseText);
- }
- });
-
- };
- $scope.importProfileList=[];
- $scope.toggleSelection = function(profile) {
- if(profile.selected)
- $scope.importProfileList.push(profile);
- else{
- var index = $scope.importProfileList.indexOf(profile);
- if(index>=0)
- $scope.importProfileList.splice(index, 1);
- }
- };
-
- $scope.prepareProfileSelection = function() {
- if($scope.importProfileList)
- $.each($scope.importProfileList, function(i, profile){
- $scope.preparePostSearchBean(profile);
- });
- ;
- }
-
- $scope.preparePostSearchBean = function(profile) {
- //console.log('Importing: '+profile.orgUserId);
- //console.log('ngexistinguser:'+$scope.ngexistingUsers[profile.orgUserId])
- if($scope.postSearchBean.selected==null){
- $scope.postSearchBean.selected=[];
- $scope.postSearchBean.postOrgUserId=[];
- $scope.postSearchBean.postHrid=[];
- $scope.postSearchBean.postFirstName=[];
- $scope.postSearchBean.postLastName=[];
- $scope.postSearchBean.postOrgCode=[];
- $scope.postSearchBean.postPhone=[];
- $scope.postSearchBean.postEmail=[];
- $scope.postSearchBean.postAddress1=[];
- $scope.postSearchBean.postAddress2=[];
- $scope.postSearchBean.postCity=[];
- $scope.postSearchBean.postState=[];
- $scope.postSearchBean.postZipCode=[];
- $scope.postSearchBean.postLocationClli=[];
- $scope.postSearchBean.postBusinessCountryCode=[];
- $scope.postSearchBean.postBusinessCountryName=[];
- $scope.postSearchBean.postDepartment=[];
- $scope.postSearchBean.postDepartmentName=[];
- $scope.postSearchBean.postBusinessUnit=[];
- $scope.postSearchBean.postBusinessUnitName=[];
- $scope.postSearchBean.postJobTitle=[];
- $scope.postSearchBean.postOrgManagerUserId=[];
- $scope.postSearchBean.postCommandChain=[];
- $scope.postSearchBean.postCompanyCode=[];
- $scope.postSearchBean.postCompany=[];
- $scope.postSearchBean.postCostCenter=[];
- $scope.postSearchBean.postSiloStatus=[];
- $scope.postSearchBean.postFinancialLocCode=[];
- }
-
- $scope.postSearchBean.selected.push(profile.orgUserId);
- $scope.postSearchBean.postOrgUserId.push(profile.orgUserId);
- $scope.postSearchBean.postHrid.push(profile.hrid);
- $scope.postSearchBean.postFirstName.push(profile.firstName);
- $scope.postSearchBean.postLastName.push(profile.lastName);
- $scope.postSearchBean.postOrgCode.push(profile.orgCode);
- $scope.postSearchBean.postPhone.push(profile.phone);
- $scope.postSearchBean.postEmail.push(profile.email);
- $scope.postSearchBean.postAddress1.push(profile.address1);
- $scope.postSearchBean.postAddress2.push(profile.address2);
- $scope.postSearchBean.postCity.push(profile.city);
- $scope.postSearchBean.postState.push(profile.state);
- if(profile.zipCodeSuffix==null)
- $scope.postSearchBean.postZipCode.push(profile.zipCode);
- else
- $scope.postSearchBean.postZipCode.push(profile.zipCode+'-'+profile.zipCodeSuffix);
- $scope.postSearchBean.postLocationClli.push(profile.locationClli);
- $scope.postSearchBean.postBusinessCountryCode.push(profile.businessCountryCode);
- $scope.postSearchBean.postBusinessCountryName.push(profile.businessCountryName);
- $scope.postSearchBean.postDepartment.push(profile.department);
- $scope.postSearchBean.postDepartmentName.push(profile.departmentName);
- $scope.postSearchBean.postBusinessUnit.push(profile.businessUnit);
- $scope.postSearchBean.postBusinessUnitName.push(profile.businessUnitName);
- $scope.postSearchBean.postJobTitle.push(profile.jobTitle);
- $scope.postSearchBean.postOrgManagerUserId.push(profile.orgManagerUserId);
- $scope.postSearchBean.postCommandChain.push(profile.commandChain);
- $scope.postSearchBean.postCompanyCode.push(profile.companyCode);
- $scope.postSearchBean.postCompany.push(profile.company);
- $scope.postSearchBean.postCostCenter.push(profile.costCenter);
- $scope.postSearchBean.postSiloStatus.push(profile.siloStatus);
- $scope.postSearchBean.postFinancialLocCode.push(profile.financialLocCode);
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-controller.js
deleted file mode 100644
index aa0066b0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-controller.js
+++ /dev/null
@@ -1,286 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('profileController', function ($scope,$http,ProfileService,$routeParams,modalService){
- $scope.tableData=[];
- $scope.profile=[];
- $scope.ociavailableRoles=[];
- $scope.ociTimeZones;
- $scope.ociCountries;
- var stateList=[];
- $scope.availableRoles = [];
- $scope.timeZones = [];
- $scope.selectedTimeZone = null;
- $scope.countries = [];
- $scope.selectedCountry = null;
-
- ProfileService.getProfileDetail($routeParams.profileId).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.profile =JSON.parse($scope.data.profile);
- $scope.ociavailableRoles =JSON.parse($scope.data.availableRoles);
- $scope.ociTimeZones=JSON.parse($scope.data.timeZones);
- $scope.ociCountries=JSON.parse($scope.data.countries);
- stateList=JSON.parse($scope.data.stateList);
- $scope.orgUserId=$scope.profile.orgUserId;
- $scope.orgManagerUserId=$scope.profile.orgManagerUserId;
-
-
- if($scope.ociavailableRoles)
- $.each($scope.ociavailableRoles, function(i, a){
- var availableRole = a;
- availableRole.selected = false;
- $.each($scope.profile.roles, function(j, b){
- if(a.id === b.id) {
- availableRole.selected = true;
- }
- });
- $scope.availableRoles.push(availableRole);
- });
- ;
-
- /*$scope.ociTimeZones = ${model.timeZones};*/
-
- if($scope.ociTimeZones){
- $.each($scope.ociTimeZones, function(i, a){
- var timeZone = {"index":i, "value":a.value, "title":a.label};
- $scope.timeZones.push(timeZone);
- if($scope.profile.timeZoneId !== null && a.value === $scope.profile.timeZoneId.toString()){
- $scope.selectedTimeZone = timeZone;
- }
- });
- };
-
- /*$scope.ociCountries = ${model.countries};*/
-
- //alert($scope.ociCountries[0].label);
- if($scope.ociCountries)
- $.each($scope.ociCountries, function(i, a){
- var country = {"index":i, "value":a.value, "title":a.label};
- $scope.countries.push(country);
- if(a.value === $scope.profile.country){
- $scope.selectedCountry = country;
- }
- });
- ;
-
- /*var stateList=${model.stateList};*/
- //alert(stateList[0].label);
- stateList = stateList== null? []: stateList;
- var selectedState= $scope.profile.state ? $scope.profile.state:"";
- $scope.stateList = initDropdownWithLookUp(stateList,selectedState );
-
- //$scope.resetMenu();
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- /*$scope.profile=${model.profile};*/
- $scope.orgUserId=$scope.profile.orgUserId;
- $scope.orgManagerUserId=$scope.profile.orgManagerUserId;
-
- $scope.viewPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
-
- $( "#dialog" ).hide();
-
- /*$scope.ociavailableRoles=${model.availableRoles};*/
- //modalService.showFailure('Error','') ;
-
-
- $scope.saveProfile = function() {
- var uuu = "profile/saveProfile?profile_id=" + $routeParams.profileId;
- var postData={profile: $scope.profile,
- selectedCountry:$scope.selectedCountry!=null?$scope.selectedCountry.value:"",
- selectedState:$scope.stateList.selected!=null?$scope.stateList.selected.value:"",
- selectedTimeZone:$scope.selectedTimeZone!=null?$scope.selectedTimeZone.value:""
- };
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- modalService.showSuccess("Success","Update Successful.");
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
- $scope.addNewRolePopup = function(role) {
- $( "#dialog" ).dialog({
- modal: true,
- width: 500,
- height:600
- });
- $(".ui-dialog").css("z-index",2001);
- $(".ui-dialog-titlebar").hide();
- };
-
- $scope.toggleRole = function(selected,availableRole) {
- $scope.profileTemp=$scope.profile;
- $scope.profile={};
- //alert('toggleRole: '+selected);
- if(!selected) {
- //remove role
- var uuu = "profile/removeRole?profile_id=" + $routeParams.profileId;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to remove the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- $scope.$apply(function(){$scope.profile=$scope.profileTemp;});
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- },
- function(){
- availableRole.selected=!availableRole.selected;
- });
-
-
- } else {
- //add role
- var uuu = "profile/addNewRole?profile_id=" + $routeParams.profileId;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to add the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- $scope.$apply(function(){$scope.profile=$scope.profileTemp;});
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },function(){
- availableRole.selected=!availableRole.selected;
- })
-
- }
-
-
- };
-
- $scope.removeRole = function(role) {
-
-
- modalService.popupConfirmWin("Confirm","You are about to remove the role "+role.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- $scope.profileTemp=$scope.profile;
- $scope.profile={};
- var uuu = "profile/removeRole?profile_id=" + $routeParams.profileId;
- var postData={role:role};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profile=data;
- $.each($scope.availableRoles, function(k, c){
- if(c.id === role.id) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- $scope.$apply(function(){$scope.profile=$scope.profileTemp;});
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
-
- };
-
- function initDropdownWithLookUp(arr,selectedValue){
- var dropdownArray=[];
- var selected = null;
- if(arr){
- for(var i = 0,l = arr.length; i < l; i++) {
- var option = {
- "index" : i ,
- "value" : arr[i].value,
- "title" : arr[i].label
- };
- dropdownArray.push(option);
- if(arr[i].value === selectedValue){
- selected = option;
- }
- }
- }
- var dropDown={};
- dropDown.options = dropdownArray;
- dropDown.selected = selected;
- return dropDown;
- };
-
- $scope.doRolePopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'roles_popup.html',
- controller: 'rolepopupController',
- resolve: {
- message: function () {
- var message ={
- availableRoles: $scope.availableRoles
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function (opts) {
- if(opts!=null){
- $scope.profile=opts.profile;
- }
- });
- }
-
- $scope.close = function(){
- $('#dialog').dialog('close');
- }
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-search-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-search-controller.js
deleted file mode 100644
index 6da82dcc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profile-search-controller.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('profileSearchCtrl', function($scope, $http,ProfileService,modalService){
-
- $scope.showInput = true;
- $scope.totalPages1 = 5;
- $scope.viewPerPage1 = 8;
- $scope.currentPage1 = 1;
-
- $scope.$watch('viewPerPage1', function(val) {
- ProfileService.getProfilePagination($scope.currentPage1, val).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.tableData =JSON.parse($scope.data.profileList);
- $scope.totalPages1 =JSON.parse($scope.data.totalPage);
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- });
-
- $scope.customHandler = function(num) {
- $scope.currentPage1 = num;
- ProfileService.getProfilePagination($scope.currentPage1,$scope.viewPerPage1).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.tableData =JSON.parse($scope.data.profileList);
- $scope.totalPages1 =JSON.parse($scope.data.totalPage);
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- };
-
- $scope.editRow = function(profileId){
- window.location = 'userProfile#/profile/' + profileId;
- };
-
- $scope.toggleProfileActive = function(rowData) {
- modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?",
- function(){
- $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){});
- },
- function(){
- rowData.active=!rowData.active;
- })
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profileController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profileController.js
deleted file mode 100644
index 4b30e40e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/profileController.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
- .when('/profile/:profileId', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/profile_detail.html',
- controller: 'profileController'
- })
- .when('/post_search', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/post_search.html',
- controller: 'postSearchCtrl'
- })
- .when('/self_profile', {
- templateUrl: 'app/fusion/scripts/view-models/profile-page/self_profile.html',
- controller: 'selfProfileController'
- })
- .otherwise({
- templateUrl: 'app/fusion/scripts/view-models/profile-page/profile_search.html',
- controller : "profileSearchCtrl"
- });
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-controller.js
deleted file mode 100644
index 50913af8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-controller.js
+++ /dev/null
@@ -1,226 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('roleController', function ($scope, modalService, $modal, AdminService,$routeParams){
- //$scope.role=${role};
- //console.log($scope.role.roleFunctions);
-
- $( "#dialogRoleFunction" ).hide();
- $( "#dialogChildRole" ).hide();
-
- //$scope.ociavailableRoleFunctions=${availableRoleFunctions};
-
- AdminService.getRole($routeParams.roleId).then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
-
- $scope.role =JSON.parse($scope.data.role);
- console.log($scope.role);
-
- $scope.ociavailableRoleFunctions =JSON.parse($scope.data.availableRoleFunctions);
- console.log($scope.ociavailableRoleFunctions);
- $scope.availableRoleFunctions=[];
-
- if($scope.ociavailableRoleFunctions)
- $.each($scope.ociavailableRoleFunctions, function(i, a){
- var availableRoleFunction = a;
- availableRoleFunction.selected = false;
- $.each($scope.role.roleFunctions, function(j, b){
- if(a.code === b.code) {
- availableRoleFunction.selected = true;
- }
- });
- $scope.availableRoleFunctions.push(availableRoleFunction);
- });
-
-
- $scope.ociavailableRoles=JSON.parse($scope.data.availableRoles);
- console.log($scope.ociavailableRoles);
- console.log("testing roles if exist");
- $scope.availableRoles=[];
-
- if($scope.ociavailableRoles)
- $.each($scope.ociavailableRoles, function(i, a){
- var availableRole = a;
- availableRole.selected = false;
- if($scope.role.childRoles){
- $.each($scope.role.childRoles, function(j, b){
- if(a.id === b.id) {
- availableRole.selected = true;
- }
- });
- };
- $scope.availableRoles.push(availableRole);
- });
-
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.saveRole = function() {
- var exists = false;
- for(x in $scope.availableRoles){
- console.log($scope.availableRoles[x].name);
- if($scope.availableRoles[x].name==$scope.role.name){
- modalService.showFailure("Warning", "Role already exists.");
- exists = true;
- //$modalInstance.close({availableRoleFunctions:message.availableRoleFunctions});
- }
- }
- if(!exists){
- var uuu = "role/saveRole.htm?role_id="+$routeParams.roleId;
- var postData={role: $scope.role, childRoles: $scope.role.childRoles, roleFunctions : $scope.role.roleFunctions};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- modalService.showSuccess("Success","Update Successful.");
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- }
-
- };
-
- $scope.addNewRoleFunctionModalPopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'role_functions_popup.html',
- controller: 'rolepopupController',
- backdrop: 'static',
- resolve: {
- roleId: function () {
- return $routeParams.roleId;
- },
- role: function () {
- return $scope.role;
- },
- availableRoles: function () {
- return $scope.ociavailableRoles;
- },
- availableRoleFunctions: function () {
- return $scope.ociavailableRoleFunctions;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.role=response.role;
- });
- };
-
- $scope.addNewChildRoleModalPopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'child_roles_popup.html',
- controller: 'rolepopupController',
- backdrop: 'static',
- resolve: {
- roleId: function () {
- return $routeParams.roleId;
- },
- role: function () {
- return $scope.role;
- },
- availableRoles: function () {
- return $scope.ociavailableRoles;
- },
- availableRoleFunctions: function () {
- return $scope.ociavailableRoleFunctions;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- $scope.role=response.role;
- });
- };
-
-
-
- $scope.removeRoleFunction = function(roleFunction) {
- modalService.popupConfirmWin("Confirm","You are about to remove the role function "+roleFunction.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var uuu = "role/removeRoleFunction.htm?role_id=" + $routeParams.roleId;
- var postData={roleFunction:roleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.role=data.role;
- $.each($scope.availableRoleFunctions, function(k, c){
- if(c.code === roleFunction.code) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
- };
-
- $scope.removeChildRole = function(childRole) {
- modalService.popupConfirmWin("Confirm","You are about to remove the child role "+childRole.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var uuu = "role/removeChildRole.htm?role_id=" + $routeParams.roleId;
- var postData={childRole:childRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.role=data.role;
- $.each($scope.availableRoles, function(k, c){
- if(c.id === childRole.id) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-function-list-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-function-list-controller.js
deleted file mode 100644
index eedac3e0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-function-list-controller.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('roleFunctionListController', function ($scope, AdminService, modalService, $modal){
- $( "#dialog" ).hide();
-
- AdminService.getRoleFunctionList().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.availableRoleFunctions =JSON.parse($scope.data.availableRoleFunctions);
-
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.editRoleFunction = null;
- var dialog = null;
- $scope.editRoleFunctionPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.editRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = availableRoleFunction;
- $scope.availableRoleFunctionsTemp=$scope.availableRoleFunctions;
- $scope.availableRoleFunctions={};
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction,
- availableRoleFunctions: $scope.availableRoleFunctionsTemp
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- if(response!=null)
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- else
- $scope.availableRoleFunctions=$scope.availableRoleFunctionsTemp;
- });
- };
-
- $scope.addNewRoleFunctionModalPopup = function(availableRoleFunction) {
- $scope.editRoleFunction = null;
- $scope.availableRoleFunctionsTemp=$scope.availableRoleFunctions;
- $scope.availableRoleFunctions={};
- var modalInstance = $modal.open({
- templateUrl: 'edit_role_function_popup.html',
- controller: 'rolefunctionpopupController',
- resolve: {
- message: function () {
- var message = {
- availableRoleFunction: $scope.editRoleFunction,
- availableRoleFunctions: $scope.availableRoleFunctionsTemp
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function(response){
- console.log('response', response);
- if(response!=null)
- $scope.availableRoleFunctions=response.availableRoleFunctions;
- else
- $scope.availableRoleFunctions=$scope.availableRoleFunctionsTemp;
- });
- };
-
- $scope.addNewRoleFunctionPopup = function() {
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog({
- modal: true
- });
- };
-
- $scope.saveRoleFunction = function(availableRoleFunction) {
- var uuu = "role_function_list/saveRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.availableRoleFunctions=[];$scope.$apply();
- $scope.availableRoleFunctions=data.availableRoleFunctions;});
- //alert("Update Successful.") ;
- console.log($scope.availableRoleFunctions);
-
- $scope.editRoleFunction = null;
- $( "#dialog" ).dialog("close");
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
-
- $scope.removeRole = function(availableRoleFunction) {
- modalService.popupConfirmWin("Confirm","You are about to delete the role function "+availableRoleFunction.name+". Do you want to continue?",
- function(){
- $scope.availableRoleFunctionsTemp=$scope.availableRoleFunctions;
- $scope.availableRoleFunctions={};
- var uuu = "role_function_list/removeRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.availableRoleFunctions=data.availableRoleFunctions;});
- },
- error : function(data){
- console.log(data);
- $scope.$apply(function(){$scope.availableRoleFunctions=$scope.availableRoleFunctionsTemp;});
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
-
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-list-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-list-controller.js
deleted file mode 100644
index a16d61ef..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/role-list-controller.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('roleListController', function ($scope,AdminService,modalService){
-
- AdminService.getRoles().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.availableRoles =JSON.parse($scope.data.availableRoles);
-
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- //console.log($scope.availableRoles);
- $scope.toggleRole = function(selected,availableRole) {
- //alert('toggleRole: '+selected);
- var toggleType = null;
- if(selected) {
- toggleType = "activate";
- } else {
- toggleType = "inactivate";
- }
-
- modalService.popupConfirmWinWithCancel("Confirm","You are about to "+toggleType+" the test role "+availableRole.name+". Do you want to continue?",
- function(){
- var uuu = "role_list/toggleRole";
-
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- console.log(data);
- $scope.$apply(function(){$scope.availableRoles=data.availableRoles;});
- console.log($scope.availableRoles);
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRole.active=!availableRole.active;
- })
-
-
- };
-
- $scope.removeRole = function(role) {
-
- modalService.popupConfirmWin("Confirm","You are about to delete the role "+role.name+". Do you want to continue?",
- function(){
- var uuu = "role_list/removeRole";
- var postData={role:role};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.availableRoles=data.availableRoles;});
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while deleting: "+ data.responseText);
- }
- });
-
- })
-
-
- };
-
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolefunctionpopupController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolefunctionpopupController.js
deleted file mode 100644
index 14aea22c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolefunctionpopupController.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var rolefunctionpopupController = function ($scope, modalService, $modalInstance, message, $http,AdminService){
- if(message.availableRoleFunction==null) {
- $scope.label='Add Role Function';
- var tempText = "";
- }
- else{
- $scope.label='Edit Role Function'
- $scope.disableCd=true;
- var tempText = new String(message.availableRoleFunction.name);
- $scope.editRoleFunction = message.availableRoleFunction;
- }
-
- $scope.tempText = tempText;
-
- $scope.saveRoleFunction = function(availableRoleFunction) {
- var uuu = "role_function_list/saveRoleFunction.htm";
- var postData={availableRoleFunction: availableRoleFunction};
-
- if(availableRoleFunction==null){
- modalService.showFailure("Warning", "Please enter valid role function details.");
- }
- var exists = false;
- for(x in message.availableRoleFunctions){
- console.log(message.availableRoleFunctions[x].name);
- if(message.availableRoleFunctions[x].name==availableRoleFunction.name){
- modalService.showFailure("Warning", "Role Function already exists.");
- exists = true;
- availableRoleFunction.name = $scope.tempText;
- }
- }
-
- if(!exists && availableRoleFunction.name.trim() != '' && availableRoleFunction.code.trim() != ''){
- $http.post(uuu, JSON.stringify(postData)).then(function(res){
- console.log("data");
-// console.log(res.data);
-// $scope.availableRoleFunctionsTemp = res.data.availableRoleFunctions;
- AdminService.getRoleFunctionList().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.availableRoleFunctions =JSON.parse($scope.data.availableRoleFunctions);
-
- //$scope.resetMenu();
- $modalInstance.close();
- },function(error){
- console.log("failed");
- reloadPageOnce();
- $modalInstance.close();
- });
-
-
- });
-
-
-
-
- }
- };
-
-
-
- $scope.close = function() {
- $modalInstance.close();
- };
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolepopupmodelController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolepopupmodelController.js
deleted file mode 100644
index f8ecfadd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/rolepopupmodelController.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var rolepopupController = function ($scope, $modalInstance, role, roleId, availableRoles, availableRoleFunctions,AdminService,modalService){
-
- $scope.role = role;
- console.log($scope.role);
- if($scope.role.childRoles==null){
- $scope.role.childRoles=[];
- }
-
- $scope.ociavailableRoles=availableRoles;
- console.log($scope.ociavailableRoles);
-
- $scope.availableRoles=[];
- if($scope.ociavailableRoles)
- $.each($scope.ociavailableRoles, function(i, a){
- var availableRole = a;
- availableRole.selected = false;
- if($scope.role.childRoles){
- $.each($scope.role.childRoles, function(j, b){
- if(a.id === b.id) {
- availableRole.selected = true;
- }
- });
- };
- $scope.availableRoles.push(availableRole);
- });
-
- $scope.ociavailableRoleFunctions = availableRoleFunctions;
- console.log($scope.ociavailableRoleFunctions);
- $scope.availableRoleFunctions = [];
- if($scope.ociavailableRoleFunctions)
- $.each($scope.ociavailableRoleFunctions, function(i, a){
- var availableRoleFunction = a;
- availableRoleFunction.selected = false;
- $.each($scope.role.roleFunctions, function(j, b){
- if(a.code === b.code) {
- availableRoleFunction.selected = true;
- }
- });
- $scope.availableRoleFunctions.push(availableRoleFunction);
- });
- //$scope.resetMenu();
-
- $scope.toggleRoleFunction = function(selected,availableRoleFunction) {
- //alert('toggleRole: '+selected);
-
- if(!selected) {
- //remove role function
- if(role.id==null){
- var index = $scope.role.roleFunctions.indexOf(availableRoleFunction);
- if(index>=0)
- $scope.role.roleFunctions.splice(index, 1);
- return;
- }
- var uuu = "role/removeRoleFunction.htm?role_id=" + roleId;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to remove the role function "+availableRoleFunction.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var postData={roleFunction:availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.role=data.role;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRoleFunction.selected=!availableRoleFunction.selected;
- })
-
- } else {
- //add role function
- if(role.id==null){
- $scope.role.roleFunctions.push(availableRoleFunction);
- return;
- }
- var uuu = "role/addRoleFunction.htm?role_id=" + roleId;
-
- modalService.popupConfirmWinWithCancel("Confirm","You are about to add the role function "+availableRoleFunction.name+" to the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var postData={roleFunction:availableRoleFunction};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.role=data.role;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRoleFunction.selected=!availableRoleFunction.selected;
- })
- }
-
-
- };
-
- $scope.toggleChildRole = function(selected,availableRole) {
- //alert('toggleRole: '+selected);
-
- if(!selected) {
- //remove role
- if(role.id==null){
- var index = $scope.role.childRoles.indexOf(availableRole);
- if(index>=0)
- $scope.role.childRoles.splice(index, 1);
- return;
- }
- var uuu = "role/removeChildRole.htm?role_id=" + roleId;
-
- modalService.popupConfirmWinWithCancel("Confirm","You are about to remove the child role "+availableRole.name+" from the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var postData={childRole:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- console.log('role',data.role);
- $scope.$apply(function(){$scope.role=data.role;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRole.selected=true;
- })
-
- } else {
- //add role
- if(role.id==null){
- $scope.role.childRoles.push(availableRole);
- return;
- }
- var uuu = "role/addChildRole.htm?role_id=" + roleId;
-
- modalService.popupConfirmWinWithCancel("Confirm","You are about to add the child role "+availableRole.name+" to the role for "+$scope.role.name+". Do you want to continue?",
- function(){
- var postData={childRole:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.role=data.role;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },
- function(){
- availableRole.selected=false;
- })
- }
-
-
- };
-
- $scope.close = function() {
- console.log('role', $scope.role);
- $modalInstance.close({role:$scope.role});
- };
-
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/self-profile-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/self-profile-controller.js
deleted file mode 100644
index b82dae30..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/self-profile-controller.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('selfProfileController', function ($scope,$http,ProfileService,$routeParams,modalService){
- $scope.tableData=[];
- $scope.profile=[];
- $scope.ociavailableRoles=[];
- $scope.ociTimeZones;
- $scope.ociCountries;
- var stateList=[];
- $scope.availableRoles = [];
- $scope.timeZones = [];
- $scope.selectedTimeZone = null;
- $scope.countries = [];
- $scope.selectedCountry = null;
- $scope.isUserSystemAdmin = false;
-
- ProfileService.getSelfProfileDetail().then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.profile =JSON.parse($scope.data.profile);
- $scope.profileId = $scope.profile.id;
- $scope.ociavailableRoles =JSON.parse($scope.data.availableRoles);
- $scope.ociTimeZones=JSON.parse($scope.data.timeZones);
- $scope.ociCountries=JSON.parse($scope.data.countries);
- stateList=JSON.parse($scope.data.stateList);
- $scope.orgUserId=$scope.profile.orgUserId;
- $scope.orgManagerUserId=$scope.profile.orgManagerUserId;
-
- if($scope.ociavailableRoles)
- $.each($scope.ociavailableRoles, function(i, a){
- var availableRole = a;
- availableRole.selected = false;
- $.each($scope.profile.roles, function(j, b){
- if(a.id === b.id) {
- availableRole.selected = true;
- if(a.id === 1){
- $scope.isUserSystemAdmin = true;
- }
- }
- });
- $scope.availableRoles.push(availableRole);
- });
- ;
-
- /*$scope.ociTimeZones = ${model.timeZones};*/
-
- if($scope.ociTimeZones){
- $.each($scope.ociTimeZones, function(i, a){
- var timeZone = {"index":i, "value":a.value, "title":a.label};
- $scope.timeZones.push(timeZone);
- if($scope.profile.timeZoneId !== null && a.value === $scope.profile.timeZoneId.toString()){
- $scope.selectedTimeZone = timeZone;
- }
- });
- };
-
- /*$scope.ociCountries = ${model.countries};*/
-
- //alert($scope.ociCountries[0].label);
- if($scope.ociCountries)
- $.each($scope.ociCountries, function(i, a){
- var country = {"index":i, "value":a.value, "title":a.label};
- $scope.countries.push(country);
- if(a.value === $scope.profile.country){
- $scope.selectedCountry = country;
- }
- });
- ;
-
- /*var stateList=${model.stateList};*/
- //alert(stateList[0].label);
- stateList = stateList== null? []: stateList;
- var selectedState= $scope.profile.state ? $scope.profile.state:"";
- $scope.stateList = initDropdownWithLookUp(stateList,selectedState );
-
- //$scope.resetMenu();
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- /*$scope.profile=${model.profile};*/
- $scope.orgUserId=$scope.profile.orgUserId;
- $scope.orgManagerUserId=$scope.profile.orgManagerUserId;
-
- $scope.viewPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
-
- $( "#dialog" ).hide();
-
- /*$scope.ociavailableRoles=${model.availableRoles};*/
- //modalService.showFailure('Error','') ;
-
-
- $scope.saveProfile = function() {
- var uuu = "profile/saveProfile?profile_id=" + $scope.profileId;;
- var postData={profile: $scope.profile,
- selectedCountry:$scope.selectedCountry!=null?$scope.selectedCountry.value:"",
- selectedState:$scope.stateList.selected!=null?$scope.stateList.selected.value:"",
- selectedTimeZone:$scope.selectedTimeZone!=null?$scope.selectedTimeZone.value:""
- };
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- modalService.showSuccess("Success","Update Successful.");
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- };
-
- $scope.addNewRolePopup = function(role) {
- $( "#dialog" ).dialog({
- modal: true,
- width: 500,
- height:600
- });
-
- $(".ui-dialog").css("z-index",10002);
- $(".ui-dialog-titlebar").hide();
- };
-
- $scope.toggleRole = function(selected,availableRole) {
- //alert('toggleRole: '+selected);
- if(!selected) {
- //remove role
- var uuu = "profile/removeRole?profile_id=" + $scope.profileId;;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to remove the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
- },
- function(){
- availableRole.selected=!availableRole.selected;
- });
-
-
- } else {
- //add role
- var uuu = "profile/addNewRole?profile_id=" + $scope.profileId;;
- modalService.popupConfirmWinWithCancel("Confirm","You are about to add the role "+availableRole.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var postData={role:availableRole};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){$scope.profile=data;});
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- },function(){
- availableRole.selected=!availableRole.selected;
- })
-
- }
-
-
- };
-
- $scope.removeRole = function(role) {
-
-
- modalService.popupConfirmWin("Confirm","You are about to remove the role "+role.name+" from the profile for "+$scope.profile.firstName+" "+$scope.profile.lastName+". Do you want to continue?",
- function(){
- var uuu = "profile/removeRole?profile_id=" + $scope.profileId;;
- var postData={role:role};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.profile=data;
- $.each($scope.availableRoles, function(k, c){
- if(c.id === role.id) {
- c.selected = false;
- }
- });
- });
-
- },
- error : function(data){
- modalService.showFailure("Fail","Error while saving.");
- }
- });
-
- })
-
-
- };
-
- function initDropdownWithLookUp(arr,selectedValue){
- var dropdownArray=[];
- var selected = null;
- if(arr){
- for(var i = 0,l = arr.length; i < l; i++) {
- var option = {
- "index" : i ,
- "value" : arr[i].value,
- "title" : arr[i].label
- };
- dropdownArray.push(option);
- if(arr[i].value === selectedValue){
- selected = option;
- }
- }
- }
- var dropDown={};
- dropDown.options = dropdownArray;
- dropDown.selected = selected;
- return dropDown;
- };
-
- $scope.doRolePopup = function() {
- var modalInstance = $modal.open({
- templateUrl: 'roles_popup.html',
- controller: 'rolepopupController',
- resolve: {
- message: function () {
- var message ={
- availableRoles: $scope.availableRoles
- };
- return message;
- }
- }
- });
- modalInstance.result.then(function (opts) {
- if(opts!=null){
- $scope.profile=opts.profile;
- }
- });
- }
-
- $scope.close = function(){
- $('#dialog').dialog('close');
- }
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/usage-list-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/usage-list-controller.js
deleted file mode 100644
index b495b934..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/usage-list-controller.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('usageListController', function ($scope,$interval,$http,$modal,modalService,AdminService){
-
- AdminService.getUsageList().then(function(data){
-
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.users =$scope.data;
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.removeSession = function(sessionId) {
- modalService.popupConfirmWin("Confirm","You are about to expel this user from the application. All of their unsaved data will be lost. Do you want to continue?",
- function(){
- $http.get("usage_list/removeSession?deleteSessionId="+sessionId).success(function(response){$scope.users=response;});
- })
-
- }
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowApp.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowApp.js
deleted file mode 100644
index 0a5c8019..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowApp.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-angular.module('att.abs.helper', []);
-angular.module('quantum', []);
-
-var app=angular.module("workflowApp", ["att.abs", "att.abs.helper","modalServices",
- "att.gridster","checklist-model","ngRoute", "ui.bootstrap"]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowController.js
deleted file mode 100644
index 169a8868..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowController.js
+++ /dev/null
@@ -1,509 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('workflowsController', function($scope, $http, $uibModal, $log, modalService, $modal) {
-
- $scope.viewPerPage = 5;
- $scope.scrollViewsPerPage = 20;
- $scope.currentPage = 2;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- $scope.radio = {
- value: ""
- };
-
-
- $scope.showModal = false;
- $scope.toggleModal = function(){
- $scope.showModal = !$scope.showModal;
- };
-
- $scope.workflow = {};
- $scope.workflow.active = "true";
-
- $scope.updateAllWorkflowStatus = function() {
- angular.forEach($scope.workflows,function(value){
- $scope.checkWorkflowStatus(value);
- })
- }
-
- $scope.fetchWorkflowsList = function() {
- $http.get('workflows/list').then(function(workflowList){
- console.log('Got new list from server = ' + workflowList.data);
- $scope.workflows = workflowList.data;
- $scope.updateAllWorkflowStatus();
- });
- };
-
- $scope.addNewWorkflow = function(newWorkflow) {
- $http.post('workflows/addWorkflow/', JSON.stringify(newWorkflow)).success(function() {
- $scope.fetchWorkflowsList();
- });
-
- $scope.workflow.name = '';
-
- };
-
- $scope.updateWorkflow = function (workflowToEdit) {
- //workflowToEdit.active='true';
- var modalInstance = $uibModal.open({
- animation: $scope.animationsEnabled,
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-new.html',
- //size : modalSize,
- controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
- $scope.workflow = workflowToEdit;
- $scope.ok = function() {
- console.log('Updating existing workflow ... ' + JSON.stringify($scope.workflow));
- $http.post('workflows/editWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
- console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
- $uibModalInstance.close($scope.workflow);
- });
- };
-
- $scope.cancel = function() {
- $uibModalInstance.dismiss();
- };
- }],
- //End of inner controller
- resolve: {
- workflow: function() {
- console.log('Passing ' + JSON.stringify($scope.workflow));
- return $scope.workflow;
- }
- }
- });
-
- modalInstance.result.then(function (editedWorkFlow) {
- //Need to convert to proper date - later
- delete editedWorkFlow.created;
- delete editedWorkFlow.updated;
-
- delete editedWorkFlow.createdBy;
- delete editedWorkFlow.modifiedBy;
-
- console.log('selected Item ' + JSON.stringify(editedWorkFlow));
- $scope.$emit('workflowAdded', editedWorkFlow);
-
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
- };
-
- $scope.reset = function(){
- console.log("Resetting ....");
- };
-
- $scope.update = function(){
- console.log("updating ....");
- };
-
- $scope.createWorkflow = function (modalSize) {
-
- var modalInstance = $uibModal.open({
- animation: $scope.animationsEnabled,
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-new.html',
- size : modalSize,
- controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
- $scope.workflow = {};
- $scope.workflow.active = 'true';
- $scope.ok = function() {
- console.log('Saving new workflow ... ' + JSON.stringify($scope.workflow));
- $http.post('workflows/addWorkflow/', JSON.stringify($scope.workflow)).then(function(returnedWorkflow){
- console.log('Returned Workflow = ' + JSON.stringify(returnedWorkflow));
- $uibModalInstance.close($scope.workflow);
- });
- };
-/* console.log(size);*/
- $scope.cancel = function() {
- $uibModalInstance.dismiss();
- };
- }],
- //End of inner controller
- resolve: {
- workflow: function() {
- console.log('Passing ' + JSON.stringify($scope.workflow));
- return $scope.workflow;
- }
- }
- });
-
- modalInstance.result.then(function (newWorkflow) {
- console.log('selected Item ' + JSON.stringify(newWorkflow));
- $scope.$emit('workflowAdded', newWorkflow);
-
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
- };//End of createWorkflow function
-
-
- $scope.removeWorkflow = function(workflowToRemove){
- var modalInstance = $uibModal.open({
- animation: $scope.animationsEnabled,
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-remove.html',
- controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
- $scope.workflowToRemove = workflowToRemove;
- $scope.ok = function() {
- console.log('Removing workflow ... ' + JSON.stringify($scope.workflowToRemove) + ' on client request.');
- $http.post('workflows/removeWorkflow/', JSON.stringify($scope.workflowToRemove.id)).then(function(){
- console.log('Workflow successfully removed !!!');
- $uibModalInstance.close();
- });
- };
-
- $scope.cancel = function() {
- $uibModalInstance.dismiss();
- };
- }]
- });
-
- modalInstance.result.then(function () {
- $scope.$emit('workflowRemoved');
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
-
- };
-
-
-
- $scope.scheduleWorkflow = function(workflowToSchedule){
- var modalInstance = $uibModal.open({
- animation: $scope.animationsEnabled,
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-schedule.html',
- size:'lg',
-
- controller: ['$scope', '$uibModalInstance', '$http','dateFilter', function ($scope, $uibModalInstance, $http,dateFilter) {
-
- $scope.workflowToSchedule = workflowToSchedule;
- $scope.dt = new Date();
- $scope.dt2 = new Date();
- $scope.dateformat = 'MM/dd/yyyy',
- $scope.datetimeformat = "hh:mm a";
-
- $scope.recurrenceOptions =[{
- index:0, value:'One-Time', title:'One-Time'
- },{
- index:1, value: 'Hourly',title:'Hourly'
- },{
- index:2, value: 'Daily',title:'Daily'
- },{
- index:3, value: 'Weekly',title:'Weekly'
- }]
- $scope.selectRecurrenceOpt = $scope.recurrenceOptions[0];
-
- $scope.hours = [];
- for (var i=0; i<24; i++){
- var newObj={}
- newObj.index = i;
- newObj.value = ""+i;
- newObj.title = ""+i;
- $scope.hours.push(newObj);
- }
-
- $scope.minutes = [];
- for (var i=0; i<60; i++){
- var newObj={}
- newObj.index = i;
- newObj.value = ""+i;
- newObj.title = ""+i;
- $scope.minutes.push(newObj);
- }
-
- $scope.AMPMOptions =[
- {
- index:0, value:'AM', title:'AM'
- },{
- index:1, value: 'PM',title:'PM'
- }]
-
- $scope.selectFirstHour =$scope.hours[0];
- $scope.selectFirstMinute =$scope.minutes[0];
-
- $scope.selectLastHour =$scope.hours[0];
- $scope.selectLastMinute =$scope.minutes[0];
-
- $scope.selectStartAMPMOption=$scope.AMPMOptions[0];
- $scope.selectLastAMPMOption=$scope.AMPMOptions[0];
-
- var GenerateCronExpression = function(trigger_dt, RecurrenceOpt) {
- var CRON_sec = trigger_dt.getSeconds();
- var CRON_min = trigger_dt.getMinutes();
- var CRON_hr = trigger_dt.getHours();
- var CRON_date= trigger_dt.getDate();
- var CRON_month = trigger_dt.toLocaleString('en-US', {month: 'short'}).toUpperCase();
- var CRON_day = trigger_dt.toLocaleString('en-US', {weekday: 'short'}).toUpperCase();
- var CRON_year = trigger_dt.getFullYear();
- if (RecurrenceOpt ==="One-Time") {
- CRON_day = '?'
- } else {
- if (RecurrenceOpt ==="Hourly") {
- CRON_hr = '*';
- CRON_date = '*'
- CRON_month = '*'
- CRON_day = '?'
- CRON_year = '*'
- } else if (RecurrenceOpt ==="Daily") {
- CRON_date = '*'
- CRON_month = '*'
- CRON_day = '?'
- CRON_year = '*'
- } else if (RecurrenceOpt ==="Weekly") {
- CRON_date = '*'
- CRON_month = '*'
- CRON_year = '*'
- }
- }
-
- var CRON_Expression = [CRON_sec, CRON_min, CRON_hr, CRON_date, CRON_month, CRON_day, CRON_year];
- return CRON_Expression.join(" ");
- }
-
- $scope.ok = function() {
-
- // DateTime for the start time: it should be noted that the start time
- // for a CRON job should be prior to the trigger time.
- $scope.trigger_dt = new Date( $scope.dt.getFullYear() +
- "-" + ("0"+($scope.dt.getMonth()+1)).slice(-2) +
- "-" +("0"+ $scope.dt.getDate()).slice(-2) +
- " " + ("0" + $scope.selectFirstHour.value).slice(-2) +
- ":" +("0" + $scope.selectFirstMinute.value).slice(-2) +
- ":00.0");
-
- $scope.startDateTime_CRON = GenerateCronExpression($scope.trigger_dt, $scope.selectRecurrenceOpt.value)
-
- //roll back the the start date time by 30 seconds (start time should be 30 seconds prior to trigger time)
- dt_st = new Date($scope.trigger_dt - 30*1000)
-
- startDateTime = dt_st.getFullYear() +
- "-" + ("0"+(dt_st.getMonth()+1)).slice(-2) +
- "-" +("0"+ dt_st.getDate()).slice(-2) +
- " " + ("0" + dt_st.getHours()).slice(-2) +
- ":" +("0" + dt_st.getMinutes()).slice(-2) +
- ":" + ("0" + dt_st.getSeconds()).slice(-2) +".0";
- $scope.startDateTime = startDateTime;
-
- $scope.endDateTime = $scope.dt2.getFullYear() +
- "-" + ("0"+($scope.dt2.getMonth()+1)).slice(-2) +
- "-" +("0"+ $scope.dt2.getDate()).slice(-2) +
- " " + ("0"+ $scope.selectLastHour.value).slice(-2) +
- ":" +("0" + $scope.selectLastMinute.value).slice(-2) +
- ":00.0"
-
- $scope.WorkflowScheduleObject = {};
- $scope.WorkflowScheduleObject['startDateTime_CRON'] = $scope.startDateTime_CRON;
- $scope.WorkflowScheduleObject['startDateTime'] = $scope.startDateTime;
- $scope.WorkflowScheduleObject['endDateTime'] = $scope.endDateTime;
- $scope.WorkflowScheduleObject['workflowKey'] = $scope.workflowToSchedule.workflowKey;
- $scope.WorkflowScheduleObject['recurrence'] = $scope.selectRecurrenceOpt.value;
- $scope.WorkflowScheduleObject['workflow_arguments'] = "test";
- $scope.WorkflowScheduleObject['workflow_server_url'] = $scope.workflowToSchedule.runLink;
-
-
- TimeFromNowToStart = new Date($scope.startDateTime)-new Date()
- TimeStartToEnd = new Date($scope.endDateTime)-new Date($scope.startDateTime)
-
- if (TimeFromNowToStart<=0) {
- console.log("invalid start time input")
- alert("Please ensure the scheduled start date time is later than current time.")
- return;
- }
- if (TimeStartToEnd<=0) {
- console.log("invalid end time input")
- alert("Please ensure the schduled end date time is later than the start time.")
- return;
- }
- // if successful then save and close
- $scope.saveCronJob($scope.WorkflowScheduleObject);
- $uibModalInstance.close();
-
- };
-
- $scope.saveCronJob = function(cronJobData){
-
- console.log('saving cron job data: ' + cronJobData);
- var uuu = "workflows/saveCronJob.htm";
- var postData={cronJobDataObj: cronJobData};
- $.ajax({
- type : 'POST',
- url : uuu,
- //dataType: 'json', // data type expected from server
- contentType: 'application/json',
- data: JSON.stringify(postData), // data type sent to server
- success : function(data){
- $scope.$apply(function(){
- //$scope.availableRoleFunctions=[];$scope.$apply();
- // new // $scope.availableFnMenuItems=data.availableFnMenuItems;
- }
- );
- //alert("Update Successful.") ;
- //$scope.editRoleFunction = null;
- // new /// $modalInstance.close({availableFnMenuItems:$scope.availableRoleFunctions});
- },
- error : function(data){
- alert("Error while saving.");
- }
- });
-
- };
-
- $scope.cancel = function() {
- console.log("cancel triggered")
- $uibModalInstance.dismiss();
- };
- }]
- });
-
- modalInstance.result.then(function () {
- $scope.$emit('workflowRemoved');
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
-
- };
-
-
-
-
-
-
-
-
- $scope.previewWorkflow = function(workflowToPreview,modalSize){
- var modalInstance = $uibModal.open({
- animation: $scope.animationsEnabled,
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-preview.html',
- size:modalSize,
- controller: ['$scope', '$uibModalInstance', '$http', function ($scope, $uibModalInstance, $http) {
- $scope.workflowToPreview = workflowToPreview;
- console.log('previewWorkFlow invoked');
- console.log($scope.workflowToPreview);
-
- $scope.cancel = function() {
- $uibModalInstance.dismiss();
- };
- }]
- });
-
- modalInstance.result.then(function () {
- $scope.$emit('workflowRemoved');
- }, function () {
- $log.info('Modal dismissed at: ' + new Date());
- });
-
- };
-
-
- /* change work flow status based on the boolean variable "suspendBool" which corresponds whether
- * we would like to suspend or activate a workflow specified by key. */
- $scope.changeWorkflowStatus = function(workflowToChangeStatus,suspendBool){
- if (workflowToChangeStatus!==null) {
- var statusUrl= workflowToChangeStatus.runLink+"/engine-rest/process-definition/key/"+workflowToChangeStatus.workflowKey
- var suspendedUrl= statusUrl+"/suspended"
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open('PUT', suspendedUrl, false);
- xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
- xmlHttp.onload = function() {
- if (suspendBool) {
- console.log("process definition is now suspended");
- workflowToChangeStatus.active="false"
- } else {
- console.log("process definition is now activated");
- workflowToChangeStatus.active="true"
- }
- };
- xmlHttp.send(JSON.stringify({
- "suspended" : suspendBool,
- "includeProcessInstances" : true,
- "executionDate" : "2013-11-21T10:49:45"
- }));
- }
-
- };
-
- $scope.activateWorkflow = function(workflowToActivate){
- $scope.changeWorkflowStatus(workflowToActivate,false)
-
- };
-
- $scope.suspendWorkflow = function(workflowToActivate){
- $scope.changeWorkflowStatus(workflowToActivate,true)
- };
-
- $scope.checkWorkflowStatus = function(workflow) {
- if (workflow!==null) {
- var statusUrl= workflow.runLink+"/engine-rest/process-definition/key/"+workflow.workflowKey
- var xmlHttp3 = new XMLHttpRequest();
- xmlHttp3.open('GET', statusUrl, true);
- xmlHttp3.withCredentials = true;
- xmlHttp3.send();
- xmlHttp3.onreadystatechange = function() {
- if (xmlHttp3.readyState == 4 && xmlHttp3.status == 200) {
- // do something with the response in the variable data
- var temp = JSON.parse(xmlHttp3.responseText)
- if (temp.suspended == false){
- console.log("Activated")
- workflow.active="true"
- } else {
- console.log("Suspended")
- workflow.active="false"
- }
- }
- }
- }
- };
-
- $scope.StartWorkflowInstance = function(workflowToStart){
- if (workflowToStart!==null) {
- var statusUrl= workflowToStart.runLink+"/engine-rest/process-definition/key/"+workflowToStart.workflowKey
- var suspendedUrl= statusUrl+"/submit-form"
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open('POST', suspendedUrl, false);
- xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
- xmlHttp.onload = function() {
- };
- xmlHttp.send(JSON.stringify({
- "variables": {
- "customerId": {"value":"asdasda","type":"String"},
- "amount":{"value":"100","type":"String"}
- }
- }));
- }
-
- };
-
-
- $scope.$on('workflowAdded', function(event, newWorkflow) {
- console.log("New Workflow to be added in list scope " + JSON.stringify(newWorkflow));
- //$scope.workflows.push(newWorkflow);
- $scope.fetchWorkflowsList();
- console.log('newly added workflow = ' + JSON.stringify(newWorkflow));
- });
-
- $scope.$on('workflowRemoved', function(event) {
- $scope.fetchWorkflowsList();
- });
-
- $scope.fetchWorkflowsList();
-
-
-
-});
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowRouting.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowRouting.js
deleted file mode 100644
index 81fe4e28..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/controllers/workflows/workflowRouting.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
- .when('/all', {
- templateUrl: 'app/fusion/scripts/view-models/workflows/workflow-listing.html',
- controller: 'workflowsController'
- })
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/footer.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/footer.js
deleted file mode 100644
index a2dab75c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/directives/footer.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.directive('qFooter', function () {
- return {
- restrict: 'A', //This menas that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
- replace: false,
- templateUrl: "app/fusion/scripts/view-models/footer.html",
- controller: ['$scope', '$filter', function ($scope, $filter) {
- // Your behaviour goes here :)
- }]
- }
-});
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/adminService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/adminService.js
deleted file mode 100644
index 85a4d1bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/adminService.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.factory('AdminService', function ($http, $q) {
- return {
- getRoles: function() {
- return $http.get('get_roles')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getRoleFunctionList: function() {
- return $http.get('get_role_functions')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getFnMenuItems: function(){
-
- return $http.get('admin_fn_menu')
- .then(function(response) {
- if (typeof response.data === 'object') {
-
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getCacheRegions: function() {
- return $http.get('get_regions')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getUsageList: function() {
- return $http.get('get_usage_list')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getBroadcastList: function() {
- return $http.get('get_broadcast_list')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getBroadcast: function(messageLocationId, messageLocation, messageId) {
- return $http.get('get_broadcast?message_location_id='+messageLocationId + '&message_location=' + messageLocation + ((messageId != null) ? '&message_id=' + messageId : ''))
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getCollaborateList: function() {
- return $http.get('get_collaborate_list')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getRole: function(roleId) {
-
- return $http.get('get_role?role_id=' + roleId)
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- }
- };
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/headerService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/headerService.js
deleted file mode 100644
index 4b4a2ec4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/headerService.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-var menuStructureConvert = function(menuItems) {
- var megaMenuDataObjectTemp = [
- {
- text: "ECOMP",
- children:menuItems
- },
- {
- text: "Help",
- children: [{
- text:"Contact Us",
- url:"javascript:angular.element('[ng-controller=headerController]').scope().redirectLink('contact');"
- },
- {
- text:"Get Access",
- url:"javascript:angular.element('[ng-controller=headerController]').scope().redirectLink('access');"
- }]
- }
- ];
- return megaMenuDataObjectTemp;
-};
-var unflatten = function( array, parent, tree ){
- tree = typeof tree !== 'undefined' ? tree : [];
- parent = typeof parent !== 'undefined' ? parent : { menuId: null };
- var children = _.filter( array, function(child){ return child.parentMenuId == parent.menuId; });
-
- if( !_.isEmpty( children ) ){
- if( parent.menuId === null ){
- tree = children;
- }else{
- parent['children'] = children
- }
- _.each( children, function( child ){ unflatten( array, child ) } );
- }
-
- return tree;
- }
-app.service('HeaderService', function ($http,$log, $q,UserInfoService) {
- return{
-
- getUserNameFromSession : function(){
- UserInfoService.getFunctionalMenuStaticDetailSession()
- .then(function (res) {
- $scope.userName = res.userName;
- $scope.redirectUrl = res.portalUrl;
- });
- },
- getTopMenuStaticInfo:function() {
- var promise = UserInfoService.getFunctionalMenuStaticDetailShareContext();
- promise.then(
- function(res) {
- if(res==null || res==''){
- $log.info('failed getting static User information');
- this.getUserNameFromSession();
- }else{
- $log.info('Received static User information');
- var resData = res;
- $scope.inputUserInfo(resData);
- $scope.userProfile.fullName = $scope.userProfile.firstName+ ' '+ $scope.userProfile.lastName;
- return $scope.userProfile;
- }
- },
- function(err) {
- $log.info('failed getting static User information');
- }
- );
- }
- }
- }
-);
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/leftMenuService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/leftMenuService.js
deleted file mode 100644
index 17e53c7d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/leftMenuService.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-function isRealValue(obj){
- return obj && obj !== "null" && obj!== "undefined";
-}
-app.factory('LeftMenuService', function ($http,$log, $q) {
- return {
- getLeftMenu: function() {
- return $http.get('get_menu')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
- getAppName: function() {
- return $http.get('get_app_name')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- }
-
- };
-});
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/profileService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/profileService.js
deleted file mode 100644
index 7c73bed9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/profileService.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-
-app.factory('ProfileService', function ($http, $q) {
- return {
- getProfile: function() {
- return $http.get('get_user')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getProfilePagination: function(pageNum,viewPerPage) {
- return $http.get('get_user_pagination?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage)
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getPostProfile: function() {
- return $http.get('post_search_sample')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getProfileDetail: function(profileId) {
- return $http.get('get_profile?profile_id='+profileId)
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getSelfProfileDetail: function() {
- return $http.get('get_self_profile')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- }
- };
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/userInfoService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/userInfoService.js
deleted file mode 100644
index 9c0d3c02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/services/userInfoService.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.factory('UserInfoService', function ($http, $q,$log) {
- return {
- getFunctionalMenuStaticDetailShareContext: function(contextId,key) {
- var deferred = $q.defer();
- $http({
- method: "GET",
- url: "get_userinfo",
- }).success( function(res) {
- if(res==null || res=='')
- $log.info('Not be able to get User Info via shared context');
- deferred.resolve(res);
- }).error( function(status) {
- deferred.reject(status);
- });
- return deferred.promise;
- },
- getFunctionalMenuStaticDetailSession: function() {
- var deferred = $q.defer();
- $http({
- method: "GET",
- url: "get_topMenuInfo",
- }).success(function(res) {
- if(res==null || res=='')
- $log.info('Not be able to get User Info via shared context');
- deferred.resolve(res);
- }).error( function(status) {
- deferred.reject(status);
- });
- return deferred.promise;
- }
- };
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js
deleted file mode 100644
index 46fa5c92..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/socket/peerBroadcast.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-
-var output = $('#peerBroadcastSection');
-var websocket = '';
-var currentUser = '';
-var remoteUser = '';
-var f = '';
-var popupService;
-
-function setPopupService(_popupService) {
- popupService = _popupService;
-}
-
-function socketSetup(initialPageVisit,_currentUser, _remoteUser, _f) {
-
-
-
- if( true) {
-
- var href = window.location.href;
- var hostPatt = new RegExp(window.location.host +"/[^/]*");
- var res = hostPatt.exec(href);
- var protocol = window.location.protocol.replace("http","ws");
-
- var signalingServerPath = protocol + "//" + res + "/contact";
- var wsUri = signalingServerPath;
- console.log("Connecting to " + wsUri);
- websocket = new WebSocket(wsUri);
- //localStorage.notifySocket = JSON.stringify(websocket);
- //window.top.notifySocket = websocket;
-
- currentUser = _currentUser;
- remoteUser = _remoteUser;
- f = socketSend;
-
-
- }
-
- //var websocket = JSON.parse(localStorage.notifySocket || "{}") ;
- if( websocket != null) {
- websocket.onopen = function(evt) { onOpen(evt); };
- websocket.onmessage = function(evt) { onMessage(evt); };
- websocket.onerror = function(evt) { onError(evt); };
-
- }
-
- //if(f != undefined)
- // f();
-
- //window.top.notifySocket.send("");
-}
-
-
-function socketSend(currentUser, remoteUser) {
-
-
-
- websocket.send(JSON.stringify({
- from: currentUser,
- to: remoteUser
- }));
-
- //window.top.notifySocket.send("");
-}
-
-
-
-
-function onOpen(evt) {
- console.log("onOpen");
- //writeToScreen("CONNECTED");
-
- if(f != undefined)
- f(currentUser, remoteUser);
-
-}
-
-function onMessage(evt) {
- if (typeof evt.data == "string") {
- writeToScreen("RECEIVED (text): " + evt.data);
-
- if(popupService != undefined) {
- popupService.showMessage("Call Request","You are being contacted by " + JSON.parse(evt.data).from + ". Please click on the online icon and then click view");
-
- }
- //if (confirm("You are being contacted by " + JSON.parse(evt.data).from )) {
-
- //}
-
- } else {
- writeToScreen("RECEIVED (binary): " + evt.data);
- }
-}
-
-function onError(evt) {
- writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
-}
-
-function writeToScreen(message) {
- var pre = document.createElement("p");
- pre.style.wordWrap = "break-word";
- pre.innerHTML = message;
- output.append(pre);
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/page-resource.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/page-resource.js
deleted file mode 100644
index 8449ecfc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/utils/page-resource.js
+++ /dev/null
@@ -1,95 +0,0 @@
-function loadjscssfile(filename, filetype){
- if (filetype=="js"){ //if filename is a external JavaScript file
- var done = false;
- var script = document.createElement('script');
- script.src = filename;
- script.async = false;
- document.head.appendChild(script);
- }else if (filetype=="css"){ //if filename is an external CSS file
- var fileref=document.createElement("link")
- fileref.setAttribute("rel", "stylesheet")
- fileref.setAttribute("type", "text/css")
- fileref.setAttribute("async", false)
- fileref.setAttribute("href", filename)
- document.head.appendChild(fileref);
- }
-}
-
-function loadResource(){
- //css
- loadjscssfile("app/fusion/external/ebz/fn-ebz.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/demo.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/base.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/btn.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/dtpk.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/frms.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/sldr.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/style.css", "css");
- loadjscssfile("app/fusion/external/ebz/sandbox/styles/tbs.css", "css");
- loadjscssfile("app/fusion/external/ebz/ebz_header/portal_ebz_header.css", "css");
- loadjscssfile("static/fusion/css/jquery-ui.css", "css");
-
-
- loadjscssfile("app/fusion/external/ebz/ebz_header/header.css", "css");
- loadjscssfile("app/fusion/external/ebz/ebz_header/footer.css", "css");
- // Basic AngularJS -->
- loadjscssfile("app/fusion/external/ebz/angular_js/angular.js", "js");
- loadjscssfile("app/fusion/external/ebz/angular_js/angular-sanitize.js", "js");
- loadjscssfile("app/fusion/external/ebz/angular_js/angular-route.min.js", "js");
- loadjscssfile("app/fusion/external/ebz/angular_js/angular-cookies.js", "js");
- loadjscssfile("app/fusion/external/ebz/angular_js/gestures.js", "js");
- loadjscssfile("app/fusion/external/ebz/angular_js/app.js", "js");
-
- loadjscssfile("app/fusion/external/ebz/sandbox/att-abs-tpls.js", "js");
-
- // jQuery -->
- loadjscssfile("static/js/jquery-1.10.2.js", "js");
- loadjscssfile("static/js/jquery.mask.min.js", "js");
- loadjscssfile("static/js/jquery-ui.js", "js");
-
- // AngularJS Gridster -->
- loadjscssfile("static/fusion/js/att_angular_gridster/ui-gridster-tpls.js", "js");
- loadjscssfile("static/fusion/js/att_angular_gridster/angular-gridster.js", "js");
-
- // AngularJS Config -->
- loadjscssfile("app/fusion/external/ebz/angular_js/checklist-model.js", "js");
-
- // Utility -->
- loadjscssfile("app/fusion/scripts/modalService.js", "js");
- loadjscssfile("app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js", "js");
-
- // Controller js -->
- loadjscssfile("app/fusion/scripts/controllers/profile-search-controller.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/profile-controller.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/post-search-controller.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/self-profile-controller.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/rolefunctionpopupController.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/modelpopupController.js", "js");
-
- // Header and Footer -->
- loadjscssfile("app/fusion/scripts/directives/footer.js", "js");
- loadjscssfile("app/fusion/external/ebz/js/footer.js", "js");
- loadjscssfile("app/fusion/scripts/directives/header.js", "js");
- loadjscssfile("app/fusion/scripts/directives/leftMenu.js", "js");
-
- // Services -->
- loadjscssfile("app/fusion/scripts/services/profileService.js", "js");
- loadjscssfile("app/fusion/scripts/services/userInfoService.js", "js");
- loadjscssfile("app/fusion/scripts/services/leftMenuService.js", "js");
- loadjscssfile("app/fusion/scripts/controllers/profileController.js", "js");
-}
-
-window.onload = loadResource();
-window.onload = function(){
- var appLoadingInterval = setInterval(function(){ loadApp() }, 500);
- var count=0;
- function loadApp(){
- count++
- if(typeof angular !== 'undefined') {
- angular.bootstrap(document, ['abs']);
- clearInterval(appLoadingInterval);
- }else if(count>10){
- clearInterval(appLoadingInterval);
- }
- }
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/admin.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/admin.html
deleted file mode 100644
index f83888d9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/admin.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache"/>
- <!-- CSS -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/demo.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/base.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/btn.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/dtpk.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/frms.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/sldr.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
- <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
- <!-- Basic AngularJS -->
- <script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-cookies.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
- <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
- <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/0.10.0/lodash.min.js"></script>
- <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
-
- <!-- jQuery -->
- <script src="static/js/jquery-1.10.2.js"></script>
- <script src="static/js/jquery.mask.min.js" type="text/javascript"></script>
- <script src="static/js/jquery-ui.js" type="text/javascript"></script>
- <!-- AngularJS Gridster -->
- <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
- <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
- <!-- AngularJS Config -->
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
- <!-- Utility -->
- <script src="app/fusion/scripts/modalService.js"></script>
- <!-- Controller js -->
- <script src="app/fusion/scripts/controllers/fn_menu_add_popup_controller.js"></script>
- <script src="app/fusion/scripts/controllers/admin_menu_edit.js"></script>
- <script src="app/fusion/scripts/controllers/profile-search-controller.js"></script>
- <script src="app/fusion/scripts/controllers/profile-controller.js"></script>
- <script src="app/fusion/scripts/controllers/post-search-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-function-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/rolefunctionpopupController.js"></script>
- <script src="app/fusion/scripts/controllers/modelpopupController.js"></script>
- <script src="app/fusion/scripts/controllers/jcs-admin-controller.js"></script>
- <script src="app/fusion/scripts/controllers/broadcast-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/broadcast-controller.js"></script>
- <script src="app/fusion/scripts/controllers/usage-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/collaborate-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-controller.js"></script>
- <script src="app/fusion/scripts/controllers/rolepopupmodelController.js"></script>
- <!-- Header and Footer -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
- <script src="app/fusion/scripts/directives/footer.js"></script>
- <script src="app/fusion/external/ebz/js/footer.js"></script>
- <script src="app/fusion/scripts/directives/header.js"></script>
- <script src="app/fusion/scripts/directives/leftMenu.js"></script>
- <script src="app/fusion/scripts/services/leftMenuService.js"></script>
- <link rel="import" href="app/fusion/scripts/view-models/header.html">
- <!-- Services -->
- <script src="app/fusion/scripts/services/profileService.js"></script>
- <script src="app/fusion/scripts/services/adminService.js"></script>
- <script src="app/fusion/scripts/services/userInfoService.js"></script>
- <!-- Controller -->
- <script src="app/fusion/scripts/controllers/adminController.js"></script>
- <!-- other js lib -->
- <script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
- <script src="app/fusion/scripts/moment.min.js"></script>
-
- <!-- Icon -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
-
- </head>
- <body class="appBody" ng-app="abs">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view id="rightContentAdmin" style="min-height: 450px;margin-top:-100px;margin-left:210px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/profile.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/profile.html
deleted file mode 100644
index 56c06ebc..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/admin-page/profile.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache" />
-
- <!-- Resources -->
- <script src= "app/fusion/scripts/utils/page-resource.js"></script>
-
- <script>
- loadjscssfile("app/fusion/scripts/controllers/profileController.js", "js");
- </script>
-
- <!-- Icon -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
-
- </head>
- <body class="appBody">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view id="rightContentProfile" style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:110px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/footer.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/footer.html
deleted file mode 100644
index 56148731..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/footer.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<div>
-
-<div class="footerContainer" id="footerContainer" style="z-index:1000">
- <div class="footerWrapper" id="footerWrapper">
-
- <div class="footerItem">
-
- </div>
- <div class="attFooterInfo">
- <div class="footerLastSection">
- <div id="attFooterLogo" class="attLogo" tabindex='0'></div>
-
- <br>
- <div class="privacyPolicy">
-
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/left_menu.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/left_menu.html
deleted file mode 100644
index 84ee6ead..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/left_menu.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-cloak>
- <span ng-style="adjustHLeftMenu('burgerIcon')" style="z-index:998; position:fixed; left:0%; font-size:35px; margin-left:10px;text-decoration:none;">
- <a ng-click="toggleDrawer();isOpen = !isOpen" href="javascript:void(0);" class="arrow-icon-left" >
- <span class="ion-navicon-round"></span></a>
- <span ng-init="isOpen = true" ng-show="isOpen" style="font-size:16px; position:relative; top:-8px; left:-15px;">&nbsp&nbsp&nbsp {{app_name}}</span>
- </span>
- <div att-drawer drawer-slide="left" drawer-custom-top="{{drawer_custom_top}}px" drawer-size="200px" drawer-open="drawerOpen" drawer-custom-height="100%" >
- <div ng-style="adjustHLeftMenu('leftMenu')">
- <div class="attDrawer" style="z-index:998">
- <div class="appLeftMenuAccordDiv">
- <accordion close-others="true" css="att-accordion--no-box">
- <accordion-group ng-repeat="parent in leftMenuItems" heading="{{parent.parentLabel}}" parent-link="{{parent.parentAction}}" image-source="{{parent.parentImageSrc}}" child-length="{{parent.childItemList.length}}" is-open="parent.open">
- <div ng-repeat="subMenu in parent.childItemList" style="font-size:12px; margin-left:10px;">
- <a href="{{subMenu.action}}" style="font-size:12px; color:#666666;" >{{subMenu.label}}</a>
- </div>
- </accordion-group>
- </accordion>
- </div>
- </div>
- </div>
- </div>
-</div> \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_menu_edit.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_menu_edit.html
deleted file mode 100644
index ee23635f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/admin_menu_edit.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<div ng-controller="AdminMenuEditController" >
- <div class="pageTitle">
- <br>
- <h1 class="heading1" style="margin-left:0px">Admin Menu Items</h1>
- <br/>
- <div style="margin-right: 20px;text-align: justify;text-align-last:auto;">
- <strong>Add menu item here:</strong>
- </div>
- <br/>
- <a ng-click="addNewFnMenuItemModalPopup();" class="ion-android-apps" style="font-size:40px;" ></a>
- </div>
- <br>
- <div style="margin-right: 20px;text-align: justify;text-align-last:auto;">
- <strong>Existing menu items:</strong>
- </div>
- <br>
-
-
-
-<div style="width: 30%;">
-<table>
- <tr>
- <div style="width: 60%;">
- <td>Number of records to show:</td>
- </div>
- <td>
- <div style="width: 40%;">
- <input type="text" id="numberOfRecordstoShow" name="numberOfRecordstoShow" ng-model="numberOfRecordstoShow">
- </div>
- </td>
- </tr>
-</table>
-
-</div>
-
-<!-- freeze header
-<div class="scrolling-table" style="width: 100%;">
- <table att-table table-data="fnMenuItems" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row>
- <tr align="left">
- <th att-table-header sortable="true" key="id" default-sort="a">Menu ID</th>
- <th att-table-header sortable="true" key="label">Label</th>
- <th att-table-header sortable="true" key="ParentId">ParentId</th>
- <th att-table-header sortable="true" key="sortOrder">Sort Order</th>
- <th att-table-header sortable="true" key="action">Action</th>
- <th att-table-header sortable="true" key="functionCd">Function</th>
- <th att-table-header sortable="true" key="active">Active</th>
- <th att-table-header sortable="true" key="servlet">Servlet</th>
- <th att-table-header sortable="true" key="queryString">Query String</th>
- <th att-table-header sortable="true" key="externalUrl">External URL</th>
- <th att-table-header sortable="true" key="target">Target</th>
- <th att-table-header sortable="true" key="menuSetCode">Menu Set Code</th>
- <th att-table-header sortable="true" key="separator">Separator</th>
- <th att-table-header sortable="true" key="imageSrc">Image Source</th>
-
- <th att-table-header sortable="false" key="edit">Edit</th>
- <th att-table-header sortable="false" key="delete">Delete</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" >
- <tr>
- <td id="att-scroll-table-content" att-scrollbar style="width: 86.5%;padding-right:1%;">
- <table att-table table-data="fnMenuItems" border="1" view-per-page="scrollViewsPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <tbody att-table-row type="body" row-repeat="fnMenuItem in fnMenuItems | limitTo : numberOfRecordstoShow">
- <tr align="left">
- <td att-table-body width="1%" >{{ fnMenuItem.id }}</td>
- <td att-table-body width="3%" align="left" style="word-break:break-all;">{{ fnMenuItem.label }}</td>
- <td att-table-body width="1%" align="left">{{ fnMenuItem.parentId }}</td>
- <td att-table-body width="1%" align="left">{{ fnMenuItem.sortOrder }}</td>
- <td att-table-body width="3%" style="word-break:break-all;">{{ fnMenuItem.action }}</td>
- <td att-table-body width="1%" style="word-break:break-all;">{{ fnMenuItem.functionCd }}</td>
- <td att-table-body width="1%" style="word-break:break-all;" align="left">{{ fnMenuItem.active ? "Y" : "N"}}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.servlet }}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.queryString }}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.externalUrl }}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.target }}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.menuSetCode }}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.separator ? "Y" : "N"}}</td>
- <td att-table-body width="3%" style="word-break:break-all;" align="left">{{ fnMenuItem.imageSrc }}</td>
-
- <td att-table-body width="1%" align="right">
- <div ng-click="editMenuItemModalPopup(fnMenuItem);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-edit"></a></div>
- </td>
- <td att-table-body width="1%" align="right">
- <div ng-click="removeMenuItem(fnMenuItem);" style="font-size:20px;"><a href="javascript:void(0)" class="icon-trash"></a></div>
- </td>
-
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- </tbody>
- </table>
-</div>
-
-
-
-<br><br><br><br><br><br><br><br><br><br><br><br>
-
--->
- <div id="menusTable" title="Menu Items">
- <table att-table table-data="fnMenuItems" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="true" key="id" default-sort="a">Menu ID</th>
- <th att-table-header sortable="true" key="label">Label</th>
- <th att-table-header sortable="true" key="ParentId">ParentId</th>
- <th att-table-header sortable="true" key="sortOrder">Sort Order</th>
- <th att-table-header sortable="true" key="action">Action</th>
- <th att-table-header sortable="true" key="functionCd">Function</th>
- <th att-table-header sortable="true" key="active">Active</th>
- <th att-table-header sortable="true" key="servlet">Servlet</th>
- <th att-table-header sortable="true" key="queryString">Query String</th>
- <th att-table-header sortable="true" key="externalUrl">External URL</th>
- <th att-table-header sortable="true" key="target">Target</th>
- <th att-table-header sortable="true" key="menuSetCode">Menu Set Code</th>
- <th att-table-header sortable="true" key="separator">Separator</th>
- <th att-table-header sortable="true" key="imageSrc">Image Source</th>
-
- <th att-table-header sortable="false" key="edit">Edit</th>
- <th att-table-header sortable="false" key="delete">Delete</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="fnMenuItem in fnMenuItems | limitTo : numberOfRecordstoShow">
- <tr>
- <td att-table-body width="1%" style="word-break:break-all;" ng-bind="fnMenuItem.id"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.label"></td>
- <td att-table-body width="1%" style="word-break:break-all;" ng-bind="fnMenuItem.parentId"></td>
- <td att-table-body width="1%" style="word-break:break-all;" ng-bind="fnMenuItem.sortOrder"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.action"></td>
- <td att-table-body width="1%" style="word-break:break-all;" ng-bind="fnMenuItem.functionCd"></td>
- <td att-table-body width="1%" style="word-break:break-all;" ng-bind="fnMenuItem.active ? 'Y' : 'N'"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.servlet"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.queryString"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.externalUrl"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.target"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.menuSetCode"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.separator ? 'Y' : 'N'"></td>
- <td att-table-body width="3%" style="word-break:break-all;" ng-bind="fnMenuItem.imageSrc"></td>
-
- <td att-table-body width="1%">
- <div ng-click="editMenuItemModalPopup(fnMenuItem);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-edit"></a></div>
- </td>
- <td att-table-body width="1%">
- <div ng-click="removeMenuItem(fnMenuItem);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
-
- </table>
- </div>
-
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html
deleted file mode 100644
index a14da056..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div style="width:80%;margin-bottom:20px">
- <br/>
- <h1 class="heading1">Broadcast Message Edit</h1>
- <br/>
-
- <div ng-controller="broadcastController" >
- Please edit the broadcast message details below:&nbsp;<br><br>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Message Text:</label><BR>
- <textarea name="comment" ng-model="broadcastMessage.messageText" rows="5" cols="200" style="height:100px"></textarea>
- </div>
- <br>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Start Date:</label><BR>
- <input type="hidden" name="startDateHidden" ng-model="broadcastMessage.startDate">
- <input type="text" class="fn-ebz-text" id="startDatepicker" />
- </div>
-
- <div class="fn-ebz-container" style="margin-left:3em" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>End Date:</label><BR>
- <input type="hidden" name="endDateHidden" ng-model="broadcastMessage.endDate">
- <input type="text" class="fn-ebz-text" id="endDatepicker" />
- </div>
-
- <div class="fn-ebz-container" style="margin-left:3em" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Sort Order:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="broadcastMessage.sortOrder"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" style="margin-left:1em" >
- <label class="fn-ebz-text-label">Server:</label><BR>
- <div class="form-field" att-select="broadcastSites" ng-model="broadcastMessage.siteCd"></div>
- </div>
-
- <br>
- <div align="left" >
- <button type="submit" ng-click="save();" att-button btn-type="primary" size="small">Save</button>
- <button class="button button--information button--small" herf="javascript:void(0)" ng-click="close();">Cancel</button>
- </div>
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html
deleted file mode 100644
index e9c4c291..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/broadcast_list.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div style="width:80%;">
-
-<div ng-controller="broadcastListController" >
-
- <h1 class="heading1">Broadcast Messages</h1>
- <br>
- <div ng-repeat="location in messageLocations" >
- {{location.label}} Messages
- <div title="{{location.label}} Messages">
-
- <table att-table table-data="location.messages" current-page="1">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%">No.</th>
- <th att-table-header sortable="false" width="30%">Message Text</th>
- <th att-table-header sortable="false" width="10%">Start Date</th>
- <th att-table-header sortable="false" width="10%">End Date</th>
- <th att-table-header sortable="false" width="10%">Sort Order</th>
- <th att-table-header sortable="false" width="10%">Server</th>
- <th att-table-header sortable="false" width="10%">Active?</th>
- <th att-table-header sortable="false" width="10%">Delete?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="message in location.messages" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- {{message.id}}
- <td width="10%"><a href="javascript:editMessage({{location.value}},'{{location.label}}',{{message.id}});">{{$index+1}}</a></td>
- <td width="30%">{{message.messageText}}</td>
- <td width="10%">
- {{message.displayStartDate}}
- </td>
- <td width="10%">{{message.displayEndDate}}</td>
- <td width="10%">{{message.sortOrder}}</td>
- <td width="10%">{{message.siteCd}}</td>
- <td width="10%">
- <div ng-click="toggleActive(message);">
- <input type="checkbox" ng-model="message.active" att-toggle-main ng-true-value="on" ng-false-value="off">
- </div>
- </td>
- <td att-table-body width="10%">
- <div ng-click="remove(message);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
-
- </tbody>
- </table>
- </div>
- <input att-button btn-type="primary" size="small" class="button" type="button" value="Add" ng-click="editMessage(location);"/>
- <br/><br/><br/>
- </div>
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/collaborate_list.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/collaborate_list.html
deleted file mode 100644
index 5f07a47b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/collaborate_list.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="collaborateListController">
- <div>
- <h1 class="heading1" style="margin-top:20px;">User List</h1>
- <div style="margin-top:30px">
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="id">User ID</th>
- <th att-table-header key="lastName">Last Name</th>
- <th att-table-header key="firstName">First Name</th>
- <th att-table-header key="email">Email</th>
- <th att-table-header key="orgUserId">User ID</th>
- <th att-table-header key="online">Online/Offline</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body ng-bind="rowData['id']">{{rowData.id}}</td>
- <td att-table-body ng-bind="rowData['lastName']">{{rowData.lastName}}</td>
- <td att-table-body ng-bind="rowData['firstName']">{{rowData.firstName}}</td>
- <td att-table-body ng-bind="rowData['email']">{{rowData.email}}</td>
- <td att-table-body ng-bind="rowData['orgUserId']">{{rowData.orgUserId}}</td>
- <td att-table-body >
- <tag-badges ng-hide="rowData.online" style-type="color" class="lred" ng-click="rowData.isActive=true;openCollaboration(rowData.chatId)">Offline</tag-badges>
- <tag-badges ng-show="rowData.online" style-type="color" class="lgreen" ng-click="rowData.isActive=false;openCollaboration(rowData.chatId)">Online</tag-badges>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <input ng-model="currentPage"></input>
-
- <a href="JavaScript:void(0);" style= "color:#00547A" onClick="window.open('https://chrome.google.com/webstore/detail/icgmlogfeajbfdffajhoebcfbibfhaen')" id="install-button">
- Add the Chrome Extension for DescktopCapture and refresh page</a>
-</div>
-<div id="peerBroadcastSection"></div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/jcs_admin.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/jcs_admin.html
deleted file mode 100644
index 7da45780..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/jcs_admin.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="cacheAdminController">
-
- <h1 class="heading1" >Cache Regions</h1>
- <br/>
- <div style="margin-right:20px;text-align: justify;text-align-last:auto;">
- These are the regions which are currently defined in the cache. 'Items' and 'Bytes' refer to the elements currently in memory (not spooled).
- You can clear all items for a region by clicking on the Clear icon next to the desired region below. You can also <a href="#" ng-click="clearAll();">clear all regions</a>
- which empties the entire cache.
- </div>
-
- <div style="width: 86%; border-top: 1px solid #c4c4c4; margin-top: 0px; margin-bottom:30px; margin-right: 20px; background-color: #fff; padding: 10px 0; color: #646464s">
- <div style="margin: 0 20px 10px 0px; font-size: 80%; float: left; width: 97%;">
- <div class="col-md-4"><b>Cache Name</b></div>
- <div class="col-md-2"><b># of Items</b></div>
- <div class="col-md-2"><b>Bytes</b></div>
- <div class="col-md-2"><b>Status</b></div>
- <div class="col-md-3"><b>Memory Hits</b></div>
- <div class="col-md-3"><b>Aux Hits</b></div>
- <div class="col-md-3"><b>Not Found Misses</b></div>
- <div class="col-md-3"><b>Expired Misses</b></div>
- <div class="col-md-1"><b>Clear?</b></div>
- <div class="col-md-1"><b>Items</b></div>
- </div>
- <div ng-repeat="region in regions">
- <div style="margin: 0 20px 10px 0px; font-size: 80%; float: left; width: 97%;">
- <div class="col-md-4"><a href="#" tooltip="Click to Show Region Details" ng-click="showRegionDetails(region.cacheName);">{{region.cacheName}}</a></div>
- <div class="col-md-2">{{region.size}}</div>
- <div class="col-md-2">{{region.byteCount}}</div>
- <div class="col-md-2">{{region.status}}</div>
- <div class="col-md-3">{{region.hitCountRam}}</div>
- <div class="col-md-3">{{region.hitCountAux}}</div>
- <div class="col-md-3">{{region.missCountNotFound}}</div>
- <div class="col-md-3">{{region.missCountExpired}}</div>
- <div class="col-md-1">
- <div ng-click="clearRegion(region.cacheName);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </div>
- <div class="col-md-1">
- <span class="ion-plus-circled col-md-1" ng-class="{minus: bling$index}" ng-hide="plusSign" ng-click="bling$index = !bling$index; plusSign=true" style="display: block;"></span>
- <span class="ion-minus-circled col-md-1" ng-class="{minus: bling$index}" ng-show="plusSign" ng-click="bling$index = !bling$index; plusSign=false" style="display: block;"></span>
- </div>
- </div>
- <div style="margin: 0px 20px 0px 30px; font-size: 80%; float: left; width: 95%; border-top: 1px solid #e4e4e4; padding-top: 10px"
- ng-show="bling$index">
- <span class="att--tree__arrow" style="height: 20px; width: 20px; display: inline-block; float: left"></span>
- <div class="col-md-12"><b>Key</b></div>
- <div class="col-md-2"><b>Eternal?</b></div>
- <div class="col-md-4"><b>Created</b></div>
- <div class="col-md-2"><b>Max Life</b></div>
- <div class="col-md-2"><b>Expires</b></div>
- <div class="col-md-1"><b>Clear?</b></div>
- </div>
- <div ng-repeat="item in region.items">
- <div style="margin: 0px 20px 0px 30px; font-size: 80%; float: left; width: 95%;" ng-show="bling$index">
- <span class="att--tree__arrow" style="height: 20px; width: 20px; display: inline-block; float: left"></span>
- <div class="col-md-12"><a href="#" tooltip="Click to Show Item Details" ng-click="showItemDetails(region.cacheName,item.key);">{{item.key}}</a></div>
- <div class="col-md-2">{{item.eternal}}</div>
- <div class="col-md-4">{{item.createTime}}</div>
- <div class="col-md-2">{{item.maxLifeSeconds}}</div>
- <div class="col-md-2">{{item.expiresInSeconds}}</div>
- <div class="col-md-1">
- <div ng-click="clearItem(region.cacheName,item.key);" style="font-size:20px;"><a href="javascript:void(0)" class=""></a></div>
- </div>
- </div>
- </div>
- <div style="clear: both"></div>
- </div>
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html
deleted file mode 100644
index 4663bd46..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_role.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<script type="text/ng-template" id="role_functions_popup.html">
- <div class="modal__informative font-showcase" style="width:700px;height:500px;overflow:scroll">
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="width: 500px;">Select Role Functions</h2>
- </div>
- <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- <div class="divider-container"><hr> </div>
- <div class="modal__content">
- <table table-data="availableRoleFunctions" att-table>
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role Function</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRoleFunction in availableRoleFunctions" style="max-height: 980px;" >
- <tr>
-
- <td width="10%">
- <div ng-click="toggleRoleFunction(availableRoleFunction.selected,availableRoleFunction);">
- <input type="checkbox" ng-model="availableRoleFunction.selected" att-toggle-main>
- </div>
- </td>
- <td width="90%">{{ availableRoleFunction.name }}</td>
-
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-</script>
-
-
-<script type="text/ng-template" id="child_roles_popup.html">
- <div class="modal__informative font-showcase" style="width:700px;height:500px;overflow:scroll">
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="width: 500px;">Select Child Roles</h2>
- </div>
- <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- <div class="divider-container"><hr> </div>
- <div class="modal__content">
- <table table-data="availableRoles" att-table>
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" >
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleChildRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-</script>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html
deleted file mode 100644
index b9e8ef0e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<script type="text/ng-template" id="edit_role_function_popup.html">
- <div class="modal__informative font-showcase" style="width:400px;">
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="width: 500px;">{{label}}</h2>
- </div>
- <div class="divider-container"><hr> </div>
- <div class="modal__content">
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.name"
- maxlength="30" />
- </div>
- <br/>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Code:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.code" ng-disabled="disableCd"
- maxlength="30" />
- </div>
- </div>
- <div class="modal__footer">
- <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="saveRoleFunction(editRoleFunction);">Save</button>
- <button class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- </div>
- </div>
-</script>
-
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/post_search.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/post_search.html
deleted file mode 100644
index 2c4846dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/post_search.html
+++ /dev/null
@@ -1,139 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div style="margin-bottom:20px;">
-<h1 class="heading1">User Search</h1>
- <br>
- Please enter search criteria below:<br/>
-
- <div class="fn-ebz-container">
- Last Name:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.lastName" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- First Name:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.firstName" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- User ID:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgUserId" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Manager User ID:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgManagerUserId" value="" size="25">
- </div>
- <br>
- <div class="fn-ebz-container">
- Organization:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.orgCode" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Email:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postSearchBean.email" value="" size="25">
- </div>
- <br>
- <div>
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Search" ng-click="search(postSearchBean);" />
-
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Reset" ng-click="reset();"/>
- </div>
- <br>
-
- {{noResultsString}}
-
- <div ng-if="profileList.length != 0">
- <table att-table table-data="profileList" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header" >
- <tr>
- <th att-table-header width="5%" align="left">No</th>
- <th att-table-header width="30%" key="lastName" align="left">Name</th>
- <th att-table-header width="5%" key="orgUserId" align="left">OrgUserId</th>
- <th att-table-header width="10%" key="orgCode" align="left">Organization</th>
- <th att-table-header width="20%" align="left">Phone</th>
- <th att-table-header width="20%" key="email" align="left">Email</th>
- <th att-table-header width="10%" align="left">Import?</th>
- </tr>
- </thead>
-
- <tbody att-table-row type="body" row-repeat="profile in profileList" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr >
- <td att-table-body width="5%" align="left">
- {{$index + 1}}
- </td>
- <td att-table-body width="30%" align="left">
- <div ng-if="ngexistingUsers[profile.orgUserId] == null">
- {{profile.lastName}},&nbsp;{{profile.firstName}}
- </div>
- <div ng-if="ngexistingUsers[profile.orgUserId] != null">
- <a href="profile.htm?profile_id={{ngexistingUsers[profile.orgUserId]}}" alt="View/Edit Profile">
- {{profile.lastName}},&nbsp;{{profile.firstName}}
- </a>
- </div>
-
- </td>
- <td att-table-body width="5%" align="left">
- {{profile.orgUserId}}
- </td>
- <td att-table-body width="10%" align="left">
- {{profile.orgCode}}
- </td>
- <td att-table-body width="20%" align="left">
- {{profile.phone}}
- </td>
- <td att-table-body width="20%" align="left">
- {{profile.email}}
- </td>
-
- <td att-table-body width="10%" align="left">
- <div ng-if="ngexistingUsers[profile.orgUserId] == null">
- <div ng-click="toggleSelection(profile);">
- <input name="selected" type="checkbox" ng-model="profile.selected" att-checkbox/>
- </div>
- </div>
- <div ng-if="ngexistingUsers[profile.orgUserId] != null">
- Exists
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage" size="5" readonly="true" style="width: 47px;">
- </div>
-
- <div ng-if="profileList.length != 0">
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Import" ng-click="process();"/>
- </div>
-
- </div>
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_detail.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_detail.html
deleted file mode 100644
index c5ef97a7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_detail.html
+++ /dev/null
@@ -1,188 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="profileController" >
- <br/>
- <h1 class="heading1">Profile Edit</h1>
- <br/>
- Please edit the profile details below:&nbsp;<br><br>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>First Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.firstName"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Last Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.lastName"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">User ID:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgUserId"
- maxlength="30" style="margin-right:0px;" readonly="true"/>
- </div>
- &nbsp;
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Manager User ID:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgManagerUserId"
- maxlength="30" style="margin-right:0px;" readonly="true"/>
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Login Id:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.loginId"
- maxlength="30" readonly="true"/>
- </div>
-
- <div class="fn-ebz-container" style="margin-right:20px">
- <label class="fn-ebz-text-label">Password:</label><BR>
- <input type="password" ng-model="profile.loginPwd"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Phone:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.phone"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Fax:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.fax"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Cellular:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.cellular"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Email:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.email"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 1:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address1"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 2:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address2"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">City:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.city"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">State:</label><BR>
- <div class="form-field" att-select="stateList.options" ng-model="stateList.selected"></div>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Zip Code:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.zipCode"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Country:</label><BR>
- <div class="form-field" att-select="countries" ng-model="selectedCountry"></div>
- </div>
- <BR>
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Time Zone:</label><BR>
- <div class="form-field" att-select="timeZones" ng-model="selectedTimeZone"></div>
- </div>
-
- <div align="left" >
- <button type="submit" ng-click="saveProfile();" att-button
- btn-type="primary" size="small">Save</button>
- </div>
-
-<br>
- <div class="pageTitle">
- <label>Roles</label>
- <a ng-click="addNewRolePopup();" class="ion-plus" size="small"></a>
-
- </div>
-
- <table att-table table-data="profile.roles" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-<!-- <table border="1" class="hovertable_1"> -->
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="role in profile.roles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
-<!-- <tr ng-repeat="role in profile.roles track by role.id"> -->
- <tr>
- <td att-table-body width="90%" >{{ role.name }}</td>
- <td att-table-body width="10%">
- <a ng-click="removeRole(role);" ><img src="static/fusion/images/deleteicon.gif"></a>
- </td>
- </tr>
- </tbody>
- </table>
-
-
-
- <div id="dialog" style="overflow:scroll" class="modal__informative font-showcase" >
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="color:#157BB2">Select Roles</h2>
- </div>
- <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- <div class="divider-container"><hr></div>
- <div class="modal__content">
- <table table-data="availableRoles" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
-
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_search.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_search.html
deleted file mode 100644
index 9f49a80f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/profile_search.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="profileSearchCtrl">
-
- <h1 class="heading1" style="margin-top:10px;">Profile Search</h1>
-
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="true" key="id">User ID</th>
- <th att-table-header sortable="true" key="lastName">Last Name</th>
- <th att-table-header sortable="true" key="firstName">First Name</th>
- <th att-table-header sortable="true" key="email">Email</th>
- <th att-table-header sortable="true" key="orgUserId">User ID</th>
- <th att-table-header sortable="true" key="orgManagerUserId">Manager User ID</th>
- <th att-table-header >Edit</th>
- <th att-table-header sortable="true" key="active">Active?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body ng-bind="rowData['id']"></td>
- <td att-table-body ng-bind="rowData['lastName']"></td>
- <td att-table-body ng-bind="rowData['firstName']"></td>
- <td att-table-body ng-bind="rowData['email']"></td>
- <td att-table-body ng-bind="rowData['orgUserId']"></td>
- <td att-table-body ng-bind="rowData['orgManagerUserId']"></td>
- <td att-table-body ><a href="#/profile/{{rowData.id}}" class="ion-edit" style="color: #888;font-size:20px;"></a></td>
- <td att-table-body >
- <div ng-click="toggleProfileActive(rowData)">
- <input type="checkbox" ng-model="rowData.active" att-toggle-main>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
-
- <div class="fn-ebz-container">
- Records Per Page:
- <input class="fn-ebz-text" type="text" ng-model="viewPerPage1" size="5" style="width: 47px;">
- </div>
-<!-- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPage" size="5" style="width: 47px;">
- </div> -->
-<!-- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPage1" size="5" readonly="true" style="width: 47px;">
- </div> -->
-
-<!--Short page count-->
-<div att-pagination total-pages="totalPages1" current-page="currentPage1" click-handler="customHandler"></div>
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role.html
deleted file mode 100644
index c312f5b7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role.html
+++ /dev/null
@@ -1,118 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div>
- <div class="bc-style" style="margin-left:-60px;">
- <ul class="breadcrumb">
- <li><a href="welcome">Home</a></li>
- <li><a href="admin#/role_list">Roles</a></li>
- <li class="active">Role</li>
- </ul>
- </div>
- <h1 class="heading1">Role Edit</h1>
- <div ng-controller="roleController" >
- <br>
- Please edit the role details below:&nbsp;<br>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="role.name"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Priority:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="role.priority"
- maxlength="30" />
- </div>
-
- <div align="left" >
- <button type="submit" ng-click="saveRole();" att-button
- btn-type="primary" size="small">Save</button>
- </div>
-
- <br>
- <div class="pageTitle">
- <label>Role Functions</label>
- <a ng-click="addNewRoleFunctionModalPopup();" class="ion-plus" size="small"></a>
- </div>
-
- <table table-data="role.roleFunctions" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="roleFunction in role.roleFunctions" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="90%" >{{ roleFunction.name }}</td>
- <td att-table-body width="10%">
- <div ng-click="removeRoleFunction(roleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- <a href="admin#/role_function_list">Manage Role Functions</a><br><br>
-
- <div class="pageTitle">
- <label>Child Roles</label>
- <a ng-click="addNewChildRoleModalPopup();" class="ion-plus-round" size="small"></a>
- </div>
-
- <table table-data="role.childRoles" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="role in role.childRoles" style="max-height: 980px;" >
- <tr>
- <td att-table-body width="90%" >{{ role.name }}</td>
- <td att-table-body width="10%">
- <div ng-click="removeChildRole(role);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
-
- <div id="dialogChildRole" title="Select Child Roles">
- <table table-data="availableRoles" att-table>
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleChildRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
-
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_function_list.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_function_list.html
deleted file mode 100644
index b0851036..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_function_list.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="roleFunctionListController" style="width:95%;">
- <div class="pageTitle">
-
- <h1 class="heading1" style="margin-left:0px;">Role Functions</h1>
- <br/>
- <!-- <a ng-click="addNewRoleFunctionModalPopup();" class="icon-add" size="small" ></a> -->
- <div align="left" style="marin-bottom: 50px;">
- <button type="submit" ng-click="addNewRoleFunctionModalPopup();" att-button
- btn-type="primary" size="small">Create</button>
- </div>
- <br><br>
-
- </div>
-
- <br>
- <div style="margin-right: 20px;text-align: justify;text-align-last:auto;">
- Click on the edit icon to update a role function, the plus icon to add additional role functions, or the delete icon to remove them.
- </div>
- <br>
- <div id="rolesTable" title="Role Functions">
- <table att-table table-data="availableRoleFunctions" current-page="1">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header width="70%" key="name" sortable="true">Name</th>
- <th att-table-header width="10%" key="code" sortable="true">Code</th>
- <th att-table-header width="10%" sortable="false">Edit?</th>
- <th att-table-header width="10%" sortable="false">Delete?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRoleFunction in availableRoleFunctions" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="70%" ng-bind="availableRoleFunction['name']"></td>
- <td att-table-body width="10%" ng-bind="availableRoleFunction['code']"></td>
- <td att-table-body width="10%">
- <!-- <a ng-click="editRoleFunctionPopup(availableRoleFunction);" >
- <img src="static/fusion/images/editicon.gif">
- </a> -->
- <div ng-click="editRoleFunctionModalPopup(availableRoleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-edit"></a></div>
- </td>
- <td att-table-body width="10%">
- <!-- <a ng-click="removeRole(availableRoleFunction);" ><img src="static/fusion/images/deleteicon.gif"></a> -->
- <div ng-click="removeRole(availableRoleFunction);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-
-
- <div id="dialog" title="Add Role Function">
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Name:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.name"
- maxlength="30" />
- </div>
- <br/>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Code:</label><br>
- <input type="text" class="fn-ebz-text" ng-model="editRoleFunction.code" ng-disabled="editRoleFunction.code!=null"
- maxlength="30" />
- </div>
- <br/>
- <button type="submit" ng-click="saveRoleFunction(editRoleFunction);" att-button
- btn-type="primary" size="small">Save</button>
-
- </div>
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_list.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_list.html
deleted file mode 100644
index 1100cbb0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/role_list.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div class="pageTitle">
-
- <h1 class="heading1">Roles</h1>
-</div>
-<br>
-Click on a Role to view its details.
-
-<div ng-controller="roleListController" style="margin-bottom:20px;width:100%">
- <div id="dialog" title="Roles">
- <table att-table table-data="availableRoles" current-page="1">
- <thead att-table-row type="header">
- <tr>
- <th att-table-header width="70%" key="name" sortable="true">Name</th>
- <th att-table-header width="10%" key="priority" sortable="true">Priority</th>
- <th att-table-header width="10%" key="active" sortable="true">Active?</th>
- <th att-table-header width="10%" sortable="false">Delete?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
-<!-- <tr ng-repeat="availableRole in availableRoles track by availableRole.id"> -->
- <tr>
- <td width="70%"><a href="admin#/role/{{availableRole.id}}">{{ availableRole.name }}</a></td>
- <td width="10%">{{ availableRole.priority }}</td>
- <td width="10%">
- <div ng-click="toggleRole(availableRole.active,availableRole);">
- <input type="checkbox" ng-model="availableRole.active" att-toggle-main ng-true-value="on" ng-false-value="off">
- </div>
- </td>
- <td att-table-body width="10%">
- <div ng-click="removeRole(availableRole);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-
- <div align="left" style="marin-bottom: 50px;">
- <button type="submit" onClick="window.location='admin#/role/0';" att-button
- btn-type="primary" size="small">Create</button>
- </div>
-
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/self_profile.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/self_profile.html
deleted file mode 100644
index bc8ddd2f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/self_profile.html
+++ /dev/null
@@ -1,183 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-
- <h1 class="heading1">Self Profile</h1>
- <br>
- Please edit the profile details below:&nbsp;<br><br>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>First Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.firstName"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Last Name:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.lastName"
- maxlength="30"/>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">User ID:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgUserId"
- maxlength="30" style="margin-right:0px;" readonly="true"/>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Manager User ID:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.orgManagerUserId"
- maxlength="30" style="margin-right:0px;" readonly="true"/>
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Login Id:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.loginId"
- maxlength="30" readonly="true""/>
- </div>
-
- <div class="fn-ebz-container" style="margin-right:20px">
- <label class="fn-ebz-text-label">Password:</label><BR>
- <input type="password" ng-model="profile.loginPwd"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Phone:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.phone"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Fax:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.fax"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Cellular:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.cellular"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label"><sup><b>*</b></sup>Email:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.email"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 1:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address1"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Address 2:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.address2"
- maxlength="30" />
- </div>
-<BR>
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">City:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.city"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">State:</label><BR>
- <div class="form-field" att-select="stateList.options" ng-model="stateList.selected"></div>
- </div>
-
- <div class="fn-ebz-container" >
- <label class="fn-ebz-text-label">Zip Code:</label><BR>
- <input type="text" class="fn-ebz-text" ng-model="profile.zipCode"
- maxlength="30" />
- </div>
-
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Country:</label><BR>
- <div class="form-field" att-select="countries" ng-model="selectedCountry"></div>
- </div>
- <BR>
- <div class="fn-ebz-container">
- <label class="fn-ebz-text-label">Time Zone:</label><BR>
- <div class="form-field" att-select="timeZones" ng-model="selectedTimeZone"></div>
- </div>
-
- <div align="left" >
- <button type="submit" ng-click="saveProfile();" att-button
- btn-type="primary" size="small">Save</button>
- </div>
-
-<br>
- <div class="pageTitle">
- <label>Roles</label>
- <a ng-click="addNewRolePopup();" ng-show="isUserSystemAdmin" class="ion-plus-round" size="small"></a>
-
- </div>
-
- <table att-table table-data="profile.roles" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-<!-- <table border="1" class="hovertable_1"> -->
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" align="left" width="90%">Name</th>
- <th att-table-header sortable="false" width="10%">Remove?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="role in profile.roles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
-<!-- <tr ng-repeat="role in profile.roles track by role.id"> -->
- <tr>
- <td att-table-body width="90%" >{{ role.name }}</td>
- <td att-table-body width="10%">
- <a ng-click="removeRole(role);" ><img src="static/fusion/images/deleteicon.gif"></a>
- </td>
- </tr>
- </tbody>
- </table>
-
- <div id="dialog" style="height:500px;overflow:scroll" class="modal__informative font-showcase" >
- <div class="modal__header">
- <h2 class="font-showcase-font-name" style="color:#157BB2">Select Roles</h2>
- </div>
- <button align="right" class="button button--primary button--small" herf="javascript:void(0)" ng-click="close()">Close</button>
- <div class="modal__content">
- <table table-data="availableRoles" att-table >
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%"> </th>
- <th att-table-header sortable="false" width="90%">Role</th>
- </tr>
- </thead>
-
- <tbody att-table-row type="body" row-repeat="availableRole in availableRoles" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">
- <div ng-click="toggleRole(availableRole.selected,availableRole);">
- <input type="checkbox" ng-model="availableRole.selected" att-toggle-main>
- </div>
- </td>
- <td att-table-body width="90%">{{ availableRole.name }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/usage_list.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/usage_list.html
deleted file mode 100644
index 27ae72b5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/profile-page/usage_list.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="usageListController" >
- <br/>
- <h1 class="heading1">Users</h1>
- <br/>
-
- <div style="margin-right: 20px;text-align: justify;text-align-last:auto;">
- The following shows all users currently logged into the application. Click the icon to expel a user from the application.
- </div>
- <div title="Current User Sessions" style="width: 86%;">
- <table att-table table-data="users" current-page="1">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="false" width="10%" align="left">Current User Sessions</th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- <th att-table-header sortable="false" width="10%" align="center"></th>
- </tr>
- <tr>
- <th att-table-header sortable="false" width="10%" align="center">User Id</th>
- <th att-table-header sortable="false" width="10%" align="center">User Name</th>
- <th att-table-header sortable="false" width="10%" align="center">Email</th>
- <th att-table-header sortable="false" width="10%" align="center">Last Access Time (minutes)</th>
- <th att-table-header sortable="false" width="10%" align="center">Time Remaining (minutes)</th>
- <th att-table-header sortable="false" width="10%" align="center">Expire User Session?</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="user in users" style="max-height: 980px;" ><!-- background colors will alternate not properly with multiple tbody-->
- <tr>
- <td att-table-body width="10%">{{user.id}}</td>
- <td att-table-body width="10%">{{user.lastName}}</td>
- <td att-table-body width="10%">{{user.email}}</td>
- <td att-table-body width="10%">{{user.lastAccess}}</td>
- <td att-table-body width="10%">{{user.remaining}}</td>
- <td att-table-body width="10%"><div ng-hide="user.delete=='yes'">Current Session</div>
-
- <div ng-click="removeSession(user.sessionId);" ng-hide="user.delete=='no'" style="font-size:20px;text-align:center"><a href="javascript:void(0)" class="ion-trash-b"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-landing.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-landing.html
deleted file mode 100644
index 2b5e3b60..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-landing.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache"/>
- <!-- CSS -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/demo.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/base.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/btn.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/dtpk.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/frms.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/sldr.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
- <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
- <!-- Basic AngularJS -->
-
- <script src= "app/fusion/external/angular-1.5/angular.js"></script>
- <script src= "app/fusion/external/angular-1.5/angular-sanitize.js"></script>
- <script src= "app/fusion/external/angular-1.5/angular-route.min.js"></script>
- <script src= "app/fusion/external/angular-1.5/angular-cookies.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
- <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
- <!-- <script src= "app/fusion/external/scrollable-table/angular-scrollable-table.min.js"></script> -->
- <!-- jQuery -->
- <script src="static/js/jquery-1.10.2.js"></script>
- <script src="static/js/jquery.mask.min.js" type="text/javascript"></script>
- <script src="static/js/jquery-ui.js" type="text/javascript"></script>
- <!-- AngularJS Gridster -->
- <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
- <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
- <!-- AngularJS Config -->
-<!-- <script src= "app/fusion/external/ebz/angular_js/app.js"></script> -->
- <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
-
- <!-- Controller js -->
- <script src="app/fusion/scripts/controllers/fn_menu_add_popup_controller.js"></script>
- <script src="app/fusion/scripts/controllers/admin_menu_edit.js"></script>
- <script src="app/fusion/scripts/controllers/profile-search-controller.js"></script>
- <script src="app/fusion/scripts/controllers/profile-controller.js"></script>
- <script src="app/fusion/scripts/controllers/post-search-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-function-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/rolefunctionpopupController.js"></script>
- <script src="app/fusion/scripts/controllers/modelpopupController.js"></script>
- <script src="app/fusion/scripts/controllers/jcs-admin-controller.js"></script>
- <script src="app/fusion/scripts/controllers/broadcast-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/broadcast-controller.js"></script>
- <script src="app/fusion/scripts/controllers/usage-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/collaborate-list-controller.js"></script>
- <script src="app/fusion/scripts/controllers/role-controller.js"></script>
- <script src="app/fusion/scripts/controllers/rolepopupmodelController.js"></script>
- <!-- Header and Footer -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/bootstrap/bs.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/styles/workflows/workflows.css" >
-
- <script src="app/fusion/scripts/directives/footer.js"></script>
- <script src="app/fusion/external/ebz/js/footer.js"></script>
- <script src="app/fusion/scripts/directives/header.js"></script>
- <script src="app/fusion/scripts/directives/leftMenu.js"></script>
- <script src="app/fusion/scripts/services/leftMenuService.js"></script>
- <script src="app/fusion/scripts/modalService.js"></script>
- <link rel="import" href="app/fusion/scripts/view-models/header.html">
- <!-- Services -->
- <script src="app/fusion/scripts/services/profileService.js"></script>
- <script src="app/fusion/scripts/services/adminService.js"></script>
- <script src="app/fusion/scripts/services/userInfoService.js"></script>
- <!-- Controller -->
- <script src="app/fusion/scripts/controllers/workflows/workflowRouting.js"></script>
- <script src="app/fusion/scripts/controllers/workflows/workflowController.js"></script>
-
- <!-- Utility -->
- <script src="app/fusion/scripts/modalService.js"></script>
-
- <!-- other js lib -->
- <script type="text/javascript" src="app/fusion/scripts/socket/peerBroadcast.js"></script>
- <script src="app/fusion/scripts/moment.min.js"></script>
-
- <script src="app/fusion/external/angular-ui/ui-bootstrap-tpls-1.1.2.min.js"></script>
-
- <script src="static/fusion/raptor/ebz/date_time_picker.js"></script>
- <script src="static/fusion/raptor/ebz/moment.js"></script>
- <link rel="stylesheet" href="static/fusion/raptor/ebz/date_time_picker.css"/>
- <!-- Icons -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ionicons-2.0.1/css/ionicons.css" />
- <script>
- angular.module('abs').requires.push('quantum');
- </script>
-
- </head>
- <body class="appBody" ng-app="abs">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_fn_menu_add.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_role.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-listing.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-listing.html
deleted file mode 100644
index ceb88677..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-listing.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<br/>
-<div>
- <div>
- <div align="right">
- <h3>
- <button ng-click="createWorkflow('lg')" class="btn btn-primary">Create Workflow</button></h3>
- </div>
- <div>
- <form>
- <div class="form-group">
- <input type="text" ng-model="search" placeholder = "Current Workflows - Search one"/>
- </div>
- </form>
- </div>
- </div>
-</div>
-
-<!-- <table att-table table-data="tableData" view-per-page="viewPerPage"
- current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage" ng-show="workflows.length > 0">
- <thead att-table-row type="header"> -->
-
-
-<table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
- <thead att-table-row type="header">
- <tr class="info">
- <th att-table-header>Id</th>
- <th att-table-header>Name</th>
- <th>Key</th>
- <th>Description</th>
- <th>Workflow Server URL</th>
- <!-- <th>Suspend Link</th> -->
- <th>View</th>
- <th>Active</th>
- <th>Created </th>
- <th>Created By</th>
- <th>Action</th>
- <th>Schedule</th>
- <th>Edit</th>
- <th>Delete?</th>
-
-
- </tr>
- </thead>
-
-
- <tbody att-table-row type="body">
- <tr ng-repeat="workflow in workflows | filter: search">
- <td>{{workflow.id}}</td>
- <td>{{workflow.name}}</td>
- <td>{{workflow.workflowKey}}</td>
- <td>{{workflow.description}}</td>
- <td>{{workflow.runLink}}</td>
- <td><div ng-click="previewWorkflow(workflow,'lg');" style="font-size:20px;"><a href="javascript:void(0)" class="ion-eye"></a></div></td>
- <!-- <td>{{workflow.suspendLink}}</td> -->
- <td >{{workflow.active}}</td>
- <td>{{workflow.created}}</td>
- <td>{{workflow.createdBy}}</td>
- <td><div ng-show="workflow.active ==='false'" ng-click="activateWorkflow(workflow)" style="font-size:20px;"><a href="javascript:void(0)" class="ion-play"></a></div>
- <div ng-show="workflow.active ==='true'" ng-click="suspendWorkflow(workflow)" style="font-size:20px;"><a href="javascript:void(0)" class="ion-pause"></a></div></td>
- <td><div ng-click="scheduleWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-ios-time"></a></div></td>
- <td><div ng-click="updateWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-edit"></a></div></td>
- <td><div ng-click="removeWorkflow(workflow);" style="font-size:20px;"><a href="javascript:void(0)" class="ion-trash-b"></a></div></td>
- </tr>
- </tbody>
-</table>
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-new.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-new.html
deleted file mode 100644
index 4622b928..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-new.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div>
- <div class="modal-header">
- <h3 class="modal-title">Create Workflows</h3>
- </div>
- <div class="workflow-popup-body">
- <form name="workflowForm" class="css-form" novalidate>
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowName">Name*: </label>
-
- <div>
- <input type="text" id="workflowName" class="fn-ebz-text extra-large" ng-model="workflow.name"
- name="workflowName" required="required" placeholder="Workflow Name" />
-
- <div ng-show="workflowForm.$submitted || workflowForm.workflowName.$touched">
- <span ng-show="workflowForm.workflowName.$error.required">Workflow Name is required !!!</span>
- </div>
-
- </div>
- </div>
-
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowKey">Key*: </label>
- <div>
- <input type="text" id="workflowKey" ng-model="workflow.workflowKey" class="fn-ebz-text extra-large"
- name="workflowKey" required="required" placeholder="Workflow Key" />
-
- <div ng-show="workflowForm.$submitted || workflowForm.workflowKey.$touched">
- <span ng-show="workflowForm.workflowKey.$error.required">Workflow Key is required !!!</span>
- </div>
-
- </div>
- </div>
-
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowDescription">Description: </label>
-
- <div class="controls">
- <input type="text" ng-model="workflow.description" id = "workflowDescription" name="workflowDescription" class="fn-ebz-text extra-large" placeholder="Brief Description"/>
- </div>
- </div>
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowRunLink">Workflow Server URL*</label>
- <div class="controls">
- <input type = "url" ng-model = "workflow.runLink" id = "workflowRunLink" name = "workflowRunLink" required = "required" class="fn-ebz-text extra-large"/>
- </div>
-
- <div ng-show="workflowForm.$submitted || workflowForm.workflowRunLink.$touched">
- <span ng-show="workflowForm.workflowRunLink.$error.required">Run Link is required !!!</span>
- <span class="error" ng-show="workflowForm.workflowRunLink.$error.url">Not valid url!</span>
- </div>
-
- </div>
-
- <!-- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowSuspendLink">Suspend Link*</label>
- <div class="controls">
- <input type = "url" ng-model = "workflow.suspendLink" id = "workflowSuspendLink" name = "workflowSuspendLink" required = "required" class="fn-ebz-text extra-large"/>
- </div>
-
- <div ng-show="workflowForm.$submitted || workflowForm.workflowSuspendLink.$touched">
- <span ng-show="workflowForm.workflowSuspendLink.$error.required">Suspend Link is required !!!</span>
- <span class="error" ng-show="workflowForm.workflowSuspendLink.$error.url">Not valid url!</span>
- </div>
- </div> -->
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowActive">Active</label>
- <div class="controls">
- <!-- <input type = "text" ng-model = "workflow.active" id="workflowActive" name="workflowActive" class="fn-ebz-text extra-large"/> -->
-
- <input type="radio" ng-model="workflow.active" value="true">Active
- <input type="radio" ng-model="workflow.active" value="false">Inactive
-
-
- </div>
- </div>
-
- <div class="modal-footer">
- <a att-button btn-type="primary" ng-click="ok()">OK</a>
- <a att-button btn-type="primary" ng-click="cancel()">Cancel</a>
- </div>
- </form>
- <br />
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-preview.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-preview.html
deleted file mode 100644
index 80fece4e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-preview.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div>
- <div class="modal-header">
- <h3 class="modal-title">View Workflow</h3>
- </div>
- <div class="workflow-popup-body">
- <form name="workflowForm" class="css-form" novalidate>
-
- <div style="overflow:scroll">
- <img ng-src="{{workflowToPreview.runLink}}/engine-rest/process-definition/key/{{workflowToPreview.workflowKey}}/diagram">
- </div>
- <div class="modal-footer">
- <button class="fn-ebz-btn large" type="button" ng-click="cancel()">Close</button>
- </div>
- </form>
- <br />
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-remove.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-remove.html
deleted file mode 100644
index e21efad8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-remove.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div>
- <div class="modal-header">
- <h3 class="modal-title">Remove Workflow?</h3>
- </div>
- <div class="workflow-popup-body">
- <form name="workflowForm" class="css-form" novalidate>
-
- <div class="control-group">
- <label class="fn-ebz-text large" for="workflowName">Workflow "{{workflowToRemove.name}}" is going to be removed. Are you sure?</label>
- </div>
-
- <div class="modal-footer">
- <a att-button btn-type="primary" ng-click="ok()">OK</a>
- <a att-button btn-type="primary" ng-click="cancel()">Cancel</a>
- </div>
- </form>
- <br />
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-schedule.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-schedule.html
deleted file mode 100644
index aebc04fb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/scripts/view-models/workflows/workflow-schedule.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div>
- <div class="modal-header">
- <h3 class="modal-title">Workflow: {{workflowToSchedule.name}}</h3>
- <table style="width:60%">
- <tr><td>Workflow Key:</td> <td>{{workflowToSchedule.workflowKey}}</td></tr>
- <tr><td>Workflow Description:</td> <td>{{workflowToSchedule.description}}</td></tr>
- </table>
- </div>
-
- <div class="workflow-popup-body">
- <form name="workflowForm" class="css-form" novalidate>
-
- <table>
- <tr>
- <form name="myForm">
- <td>
- <label for="singleSelect"> Recurrence: </label>
- </td>
- <td>
-<div class="form-field" att-select="recurrenceOptions" ng-model="selectRecurrenceOpt" placeholder="Select an Option"></div>
- <br>
- </td>
- <td> </td>
- </form>
- </tr>
-<tr>
-<td>
-
-</td>
-<td>
-Pick a date:
-</td>
-<td>
-Hour:
-</td>
-<td>
-Minute:
-</td>
-</tr>
- <tr>
- <td>
- <form name="FirstScheduleForm">
- <label for="dateSelect"> First Schedule: </label>
- </form>
- </td>
- <td>
- <!--DATEPICKER POPUP-->
- <input id="datepicker1" type="text" ng-model="dt" att-datepicker>
- </td>
- <td>
- <div class="form-field" att-select="hours" ng-model="selectFirstHour" placeholder="Select an Option"></div>
- </td>
- <td>
- <div class="form-field" att-select="minutes" ng-model="selectFirstMinute" placeholder="Select an Option"></div>
- </td>
-<!-- <td>
- <div class="form-field" att-select="AMPMOptions" ng-model="selectStartAMPMOption" placeholder="Select an Option"></div>
- </td> -->
-</tr>
-<tr>
- <td>
- <form name="LastScheduleForm">
- <label for="dateSelect"> Last Schedule: </label>
- </form>
- </td>
- <td>
- <input id="datepicker2" type="text" ng-model="dt2" att-datepicker>
- </td>
- <td>
- <div class="form-field" att-select="hours" ng-model="selectLastHour" placeholder="Select an Option"></div>
- </td>
- <td>
- <div class="form-field" att-select="minutes" ng-model="selectLastMinute" placeholder="Select an Option"></div>
- </td>
- :
-<!-- <td>
- <div class="form-field" att-select="AMPMOptions" ng-model="selectLastAMPMOption" placeholder="Select an Option"></div>
- </td> -->
-
- </tr>
-<tr>
-<!-- <td>
- <input id="datepicker3" type="text" ng-model="dt3" date-format="datetimeformat" att-date-time-picker>
-</td>
- -->
-</tr>
-
-</table>
- <div class="modal-footer">
- <a att-button btn-type="primary" ng-click="ok()">OK</a>
- <a att-button btn-type="primary" ng-click="cancel()">Cancel</a>
- </div>
-
- </form>
- <br />
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/fusion-sunny.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/fusion-sunny.css
deleted file mode 100644
index c8306156..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/fusion-sunny.css
+++ /dev/null
@@ -1,362 +0,0 @@
- input, textarea, select, div {
- font-family: Arial;
- font-size: 11px;
- font-weight: normal;
- }
-
- form {
- margin-top: 5px;
- }
-
-
- .applicationWindow { border-width: 0px 0px 1px 0px;
- border-style: solid;
- border-color: #959595;
- box-shadow: inset 0 0 10px #000000;
- margin-top: 10px;
- margin-bottom: 10px;
- margin-left: 10px;
- margin-right: 10px;
- }
-
- .feedbackMessage { width: 99%;
- font-family: Arial;
- font-size: 11px;
- color: #1f1f1f;
- padding: 3px;
- border: 1px #eeb420 solid;
- margin: 3px;
- background: #fff9e5;
- }
-
- .menubar {
- border-width: 0px 0px 0px 1px; border-style: solid; border-color: #959595;
- }
-
- .footer {
- /*clear: both;*/
- border-width: 0px 1px 0px 1px; border-style: solid; border-color: #959595;
- font-family: Verdana,Arial,Helvetica, sans-serif;
- font-size: 9px;
- padding: 10px 10px 30px 10px;
- background: white;
- }
-
- .pageTitle {
- font-family: Arial;
- font-size: 18px;
- font-weight: bold;
- margin-top: 5px;
- }
-
- .content {
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- font-family: Arial;
- font-size: 11px;
- padding: 5px;
- background: white;
- /*height: 600px;*/
- }
-
- .popupContent {
- font-family: Arial;
- font-size: 11px;
- padding: 3px;
- }
-
- .logo {
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- text-align: right;
- }
-
- .sep {
- border: 1px solid black
- }
-
- .attLogo { /*position: relative;*/
- float:left;
- padding-top: 25px;
- padding-left: 25px;
- }
-
- .applicationLogo { float:right;
- padding-top: 25px;
- padding-right: 25px;
- }
-
- .applinkWhite { font-family: Arial;
- font-size: 13px;
- font-weight: 900;
- color: #FFFFFF;
- text-decoration: none; }
-
- .terms { font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 9px;
- }
-
- .broadcastMessage { color: red; }
- .broadcastMessageList { color: red; }
-
- .button {
- margin: 5px 1px 5px 1px;
- padding: 3px; }
-
- .toolbarbutton:hover {
- color:#005491;
- }
-
- .headerText { font-family: Arial;
- font-size: 15px;
- font-weight: 700;
- color: #000000; }
-
- .headerBackground { background: #336699; }
-
- .errorMessageText { font-family: Arial;
- font-size: 11px;
- font-weight: bold;
- color: red; }
-
-
- .normalText { font-family: Arial;
- font-size: 11px;
- color: #000000; }
-
- .normalTextRed { font-family: Arial;
- font-size: 11px;
- color: red; }
-
-
- .smallNormalText { font-family: Arial;
- font-size: 9px;
- color: #000000; }
-
- .tableBorder { border:1px outset teal }
-
- .validationError { background: #b9eaff; }
-
- .templatebody {
- background: url(../images/body_graphic.jpg) repeat-x;
- /*margin: 40px 80px 40px 80px;*/
- }
-
- /*--------------------- General Content ------------------------------------*/
-
- .relative {
- position:relative;
- }
-
- .clear{
- clear:both;
- }
-
- .left {
- float: left;
- }
-
- .leftCentered{
- float: left;
- text-align: center;
- }
-
- .right {
- float: right;
- }
-
- .rightAligned{
- text-align: right;
- }
-
- .centered {
- text-align: center;
- align: center;
- }
-
-
- .noWrap{
- white-space:nowrap;
- }
-
- .disabled {
- color:gray;
- cursor:hand;
- }
-
- /*--------------------- Tab styles -------------------------------------*/
-
- .current {
- font-weight: bold;
- border-width: 1px 1px 1px 1px;
- border-color: silver;
- border-style: solid;
- }
-
- .subTab {
- font-weight:bold;
- font-family: Arial;
- font-size: 11px;
- color: #0F3B82;
- }
-
-
- /*--------------------- Grid styles ------------------------------------*/
-
- /* Grid navigation and header styles */
- .gridFilterLabel {font-size: 7pt;
- font-align: justify;
- font-weight: bold;
- display: block;}
-
- .gridFilterText {height: 17px;
- font-size: 8pt;
- width: 60%;
- font-align: justify;}
-
- .gridNavigationBar { font-family:Arial,Verdana;
- font-size:11px;
- font-weight:normal;
- color:#000;
- margin: 0px;
- width: 100%;
- vertical-align: middle;
- }
-
- .gridNavigationBar .navLinks { float: left;
- margin-right:15px;
- padding-top: 2px;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageControls { float: left;
- margin-right: 15px;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageControls input { font-size: 8pt;
- height: 17px;
- vertical-align: middle;
- }
-
- .gridNavigationBar .pageInfo { float: right;
- vertical-align: middle;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageInfo input { font-size: 8pt;
- height: 17px;
- vertical-align: middle;
- }
-
-
- .gridNavigationBar span { padding: 3px; }
-
- .gridNavigationBar a {
- text-decoration:underline;
- color:#000;
- font-weight:normal;
- }
-
- .gridNavigationBar img { vertical-align: middle; }
-
- .gridBulkUpdateRow {
- height: 35px;
- line-height: 35px;
- }
-
- .gridBulkUpdateRow input {
- vertical-align: middle;
- }
-
-
- /* dummy class used to lock the form elements of a grid - ex. bulk transaction processing */
- .alwaysEnabled {}
-
- .hidden {
- display: none;
- }
-
- .selectedPage {
- background-color:#C4DFFB;
- color: white;
- border-style: solid;
- border-width: 1px;
- border-color: gray;
- padding-left: 3px;
- padding-right: 3px;
- vertical-align: middle;
- }
-
- .selectedRow{
- /*background-color:#C4DFFB;*/
- }
-
- /* Action Item styles */
- .actionList {
- margin-left: -20px;
- margin-right: -10px;
- padding-left: 5px;
- }
-
- .actionList li {
- float:left;
- padding-left: 3px;
- padding-right: 3px;
- }
-
- .actionList li a {
- text-decoration:none;
- color:#000;
- }
-
- /* Filter Operator List styles */
-
- .filterList {
- margin: 0px;
- }
-
- .filterList li {
- list-style-type: none;
- padding:3px 3px 3px 2px;
- cursor:hand;
- font-size:11px;
- }
-
- .filterList li:hover {
- background: #404040;
- }
-
- .filterList li a {
- color: #000;
- text-decoration: none;
- }
-
- .filterList li:hover a {
- color: white;
- }
-
- .filterList li a:hover {
- text-decoration: none;
- color: white;
- }
-
- .filterListItem a {
- text-decoration:none;
- padding:3px 2px 3px 2px;
- }
-
-
- /*---------------------- Customized ZK Styles ------------------------------*/
-
- .z-datebox input, .z-timebox input {
- font-family: Arial;
- font-size: 11px;
- height: 15px;
- margin-top:1px;
- }
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/workflows/workflows.css b/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/workflows/workflows.css
deleted file mode 100644
index b9d0146c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusion/styles/workflows/workflows.css
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-.scrolling-table{
- width: 1200px;
-}
-.scrolling-table .scroll-viewport {
- height: 200px !important;
- width: 99.5% !important;
- background-color:white;
-}
-
-.scrolling-table .scroll-overview{
- margin-top:-14px !important;
-}
-
-.scrolling-table .scroll-viewport:hover{
- background-color:white;
-}
-
-.scrolling-table #att-scroll-table-content{
- height:200px;
- position: absolute !important;
- width:700px;
- padding-left: 0px;
- padding-top: 0px;
- padding-bottom: 0px;
- padding-right:5px;
-}
-
-.workflow-popup-body{
- position: relative;
- padding: 30px;
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js
deleted file mode 100644
index 4e624345..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-list-controller.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller("droolsListController", function ($scope,$http,droolsService, modalService, $modal) {
- // Table Data
- droolsService.getDrools().then(function(data){
-
- var j = data;
- $scope.tableData = JSON.parse(j.data);
- //$scope.resetMenu();
-
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.viewPerPage = 20;
- $scope.scrollViewsPerPage = 2;
- $scope.currentPage = 1;
- $scope.totalPage;
- $scope.searchCategory = "";
- $scope.searchString = "";
- /* modalService.showSuccess('','Modal Sample') ; */
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- $scope.openDialog = function(droolFile){
- droolsService.setSelectedFile(droolFile);
- $modal.open({
- templateUrl: 'app/fusionapp/drools/view-models/droolsView.html',
- controller: 'droolsViewController'
-
- })
- }
-
-
-
-});
-
-function openInNewTab(url) {
- var win = window.open(url, '_blank');
- win.focus();
-};
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js
deleted file mode 100644
index c475e175..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/drools-view-controller.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('droolsViewController', function ($scope,modalService,droolsService){
-
-
- $scope.resultsString = "";
- // Table Data
- droolsService.getDroolDetails(droolsService.getSelectedFile()).then(function(data){
-
- var j = data;
- $scope.postDroolsBean = JSON.parse(j.data);
- //execute($scope.postDroolsBean);
-
- },function(error){
- console.log("failed");
- //reloadPageOnce();
- });
-
-
-
- $scope.execute = function(postDroolsBean) {
- console.log(postDroolsBean);
- var uuu = "post_drools/execute";
- var postData={postDroolsBean:postDroolsBean};
- $.ajax({
- type : 'POST',
- url : uuu,
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(postData),
- success : function(data){
- $scope.$apply(function(){
- $scope.resultsString=data.resultsString;
- console.log($scope.resultsString);
- });
- },
- error : function(data){
- console.log(data);
- modalService.showFailure("Fail","Error while executing: "+ data.responseText);
- }
- });
-
- };
-
-
-
- });
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/droolsController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/droolsController.js
deleted file mode 100644
index f9c0e234..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/controller/droolsController.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
- .when('/view', {
- templateUrl: 'app/fusionapp/drools/view-models/droolsView.html',
- controller : "droolsViewController"
- })
- .otherwise({
- templateUrl: 'app/fusionapp/drools/view-models/droolsList.html',
- controller : "droolsListController"
- });
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/services/droolsService.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/services/droolsService.js
deleted file mode 100644
index d1dbfa6c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/services/droolsService.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.factory('droolsService', function ($http, $q) {
- return {
- getDrools: function() {
- return $http.get('getDrools')
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getDroolDetails: function(selectedFile) {
- return $http.get('getDroolDetails'+'?selectedFile=' + selectedFile )
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getRole: function(roleId) {
-
- return $http.get('get_role?role_id=' + roleId)
- .then(function(response) {
- if (typeof response.data === 'object') {
- return response.data;
- } else {
- return $q.reject(response.data);
- }
-
- }, function(response) {
- // something went wrong
- return $q.reject(response.data);
- });
- },
-
- getSelectedFile: function() {
- return this.selectedFile;
- },
-
- setSelectedFile: function(_selectedFile) {
- this.selectedFile = _selectedFile;
- }
- };
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html
deleted file mode 100644
index ca06b3c3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsList.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="droolsListController">
- <div>
- <h1 class="heading1" style="margin-top:20px;">Drools List</h1>
- <div style="margin-top:30px">
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header key="droolsFile">Drools File Name</th>
- <th att-table-header key="className">Class Name</th>
- <th att-table-header key="selectedRules">Run Rule</th>
-
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body ng-bind="rowData['droolsFile']">{{rowData.droolsFile}}</td>
- <td att-table-body ng-bind="rowData['className']">{{rowData.className}}</td>
-
- <td att-table-body >
- <div ng-click="openDialog(rowData.droolsFile)" style="font-size:20px;"><a href="javascript:void(0)" class="icon-play"></a></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <input ng-model="currentPage"></input>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html
deleted file mode 100644
index dbe9121a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/drools/view-models/droolsView.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="droolsViewController" class="modal__informative font-showcase">
-
-<h1 class="heading1" style="margin-top:20px;">Drools Rule Engine</h1>
- <br>
- Please enter below details:<br/>
-
- <div class="fn-ebz-container">
- Drools File:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.droolsFile" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Class Name:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.className" value="" size="25">
- </div>
-
- <div class="fn-ebz-container">
- Selected Rules:<br/>
- <input class="fn-ebz-text" type="text" ng-model="postDroolsBean.selectedRules" value="" size="25">
- </div>
-
-
- <div>
- <input att-button btn-type="primary" size="small" class="button" type="submit" value="Execute Rules" ng-click="execute(postDroolsBean);" />
- </div>
- <br>
- {{resultsString}}
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
-
-
-
-
-</div>
-
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js
deleted file mode 100644
index 0ea98a9c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-controller.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('samplePageController', function($scope, $http,ProfileService,modalService){
- $scope.tableData=[];
- $scope.viewPerPage=20;
- $scope.scrollViewPerPage=2;
- $scope.currentPage=1;
- $scope.totalPage;
- $scope.searchCategory;
- $scope.searchString="";
- $scope.currentPageNum=1;
- ProfileService.getProfilePagination(1,$scope.viewPerPage).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.tableData =JSON.parse($scope.data.profileList);
- $scope.totalPages =JSON.parse($scope.data.totalPage);
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- //$scope.resetMenu();
- },function(error){
- console.log("failed");
- reloadPageOnce();
- });
-
- $scope.$watch('currentPageNum', function(val) {
-
- ProfileService.getProfilePagination(val,$scope.viewPerPage).then(function(data){
- var j = data;
- $scope.data = JSON.parse(j.data);
- $scope.tableData =JSON.parse($scope.data.profileList);
- $scope.totalPages =JSON.parse($scope.data.totalPage);
- for(x in $scope.tableData){
- if($scope.tableData[x].active_yn=='Y')
- $scope.tableData[x].active_yn=true;
- else
- $scope.tableData[x].active_yn=false;
- }
- //$scope.resetMenu();
- },function(error){
- console.log("failed");
- });
-
- });
-
- $scope.editRow = function(profileId){
- window.location = 'userProfile#/profile/' + profileId;
- }
-
- $scope.toggleProfileActive = function(rowData) {
- modalService.popupConfirmWinWithCancel("Confirm","You are about to change user's active status. Do you want to continue?",
- function(){
- $http.get("profile/toggleProfileActive?profile_id="+rowData.id).success(function(){});
- },
- function(){
- rowData.active=!rowData.active;
- })
- };
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js
deleted file mode 100644
index 4ff99cb4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sample-page-iframe-controller.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.controller('samplePageWithIframeController', function($scope, $http,ProfileService,modalService){
-
-
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js
deleted file mode 100644
index 3d3daf5f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/controller/sampleController.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-app.config(function($routeProvider) {
- $routeProvider
- .when('/iframe', {
- templateUrl: 'app/fusionapp/scripts/view-models/sampleWithIframe.html',
- controller : "samplePageWithIframeController"
- })
- .otherwise({
- templateUrl: 'app/fusionapp/scripts/view-models/sample.html',
- controller : "samplePageController"
- });
-});
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sample.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sample.html
deleted file mode 100644
index 5b555aa4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sample.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="samplePageController">
-
- <h1 class="heading1" style="margin-top:10px;">Profile Search</h1>
-
- <table att-table table-data="tableData" view-per-page="viewPerPage" current-page="currentPage" search-category="searchCategory" search-string="searchString" total-page="totalPage">
-
- <thead att-table-row type="header">
- <tr>
- <th att-table-header sortable="true" key="id">User ID</th>
- <th att-table-header sortable="true" key="lastName">Last Name</th>
- <th att-table-header sortable="true" key="firstName">First Name</th>
- <th att-table-header sortable="true" key="email">Email</th>
- <th att-table-header sortable="true" key="orgUserId">User ID</th>
- <th att-table-header sortable="true" key="org_manager_userid">Manager User ID</th>
- </tr>
- </thead>
- <tbody att-table-row type="body" row-repeat="rowData in tableData">
- <tr>
- <td att-table-body ng-bind="rowData['id']"></td>
- <td att-table-body ng-bind="rowData['lastName']"></td>
- <td att-table-body ng-bind="rowData['firstName']"></td>
- <td att-table-body ng-bind="rowData['email']"></td>
- <td att-table-body ng-bind="rowData['orgUserId']"></td>
- <td att-table-body ng-bind="rowData['managerId']"></td>
- </tr>
- </tbody>
- </table>
-
- <div class="fn-ebz-container">
- Rows Per Page:
- <input class="fn-ebz-text" readonly type="text" ng-model="viewPerPage" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Current Page:
- <input class="fn-ebz-text" type="text" ng-model="currentPageNum" size="5" style="width: 47px;">
- </div>
- <div class="fn-ebz-container">
- Total Page(s):
- <input class="fn-ebz-text" type="text" ng-model="totalPages" size="5" readonly="true" style="width: 47px;">
- </div>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html
deleted file mode 100644
index 612e6a8c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/sampleWithIframe.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-<div ng-controller="samplePageWithIframeController" style="margin-left: auto;margin-right: auto;height:700px;">
- <iframe style="margin-top:5px;width:100%;height:100%" frameBorder="0" vspace="0" src="user_profile"></iframe>
-</div>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/singlePageSample.html b/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/singlePageSample.html
deleted file mode 100644
index 7bded9d6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/app/fusionapp/scripts/view-models/singlePageSample.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<!--
- ================================================================================
- eCOMP Portal SDK
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ================================================================================
- -->
-
-<html>
- <head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta http-equiv="cache-control" content="max-age=0" />
- <meta http-equiv="cache-control" content="no-cache" />
- <meta http-equiv="expires" content="0" />
- <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
- <meta http-equiv="pragma" content="no-cache" />
- <!-- CSS -->
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/fn-ebz.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/demo.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/base.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/btn.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/dtpk.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/frms.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/sldr.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/tbs.css" >
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
- <link rel="stylesheet" type="text/css" href="static/fusion/css/jquery-ui.css">
- <!-- Basic AngularJS -->
- <script src= "app/fusion/external/ebz/angular_js/angular.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-sanitize.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/angular-route.min.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/gestures.js"></script>
- <script src= "app/fusion/external/ebz/sandbox/att-abs-tpls.js" type="text/javascript"></script>
- <!-- jQuery -->
- <script src="static/js/jquery-1.10.2.js"></script>
- <script src="static/js/jquery.mask.min.js" type="text/javascript"></script>
- <script src="static/js/jquery-ui.js" type="text/javascript"></script>
- <!-- AngularJS Gridster -->
- <script src="static/fusion/js/att_angular_gridster/ui-gridster-tpls.js"></script>
- <script src="static/fusion/js/att_angular_gridster/angular-gridster.js"></script>
- <!-- AngularJS Config -->
- <script src= "app/fusion/external/ebz/angular_js/app.js"></script>
- <script src= "app/fusion/external/ebz/angular_js/checklist-model.js"></script>
- <!-- Utility -->
- <script src="app/fusion/scripts/modalService.js"></script>
- <!-- Controller js -->
- <script src="app/fusion/scripts/controllers/rolefunctionpopupController.js"></script>
- <script src="app/fusion/scripts/controllers/modelpopupController.js"></script>
- <script src="app/fusionapp/scripts/controller/sampleController.js"></script>
- <script src="app/fusionapp/scripts/controller/sample-page-controller.js"></script>
- <script src="app/fusionapp/scripts/controller/sample-page-iframe-controller.js"></script>
- <!-- Header and Footer -->
-
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
- <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/footer.css" >
- <script src="app/fusion/scripts/directives/footer.js"></script>
- <script src="app/fusion/external/ebz/js/footer.js"></script>
- <script src="app/fusion/scripts/directives/header.js"></script>
- <script src="app/fusion/scripts/directives/leftMenu.js"></script>
- <!-- Services -->
- <script src="app/fusion/scripts/services/profileService.js"></script>
-
- </head>
- <body class="appBody" ng-app="abs">
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal_rolefunction.html'"></div>
- <div ng-include src="'app/fusion/scripts/view-models/profile-page/popup_modal.html'"></div>
- <div q-header></div>
- <div q-menu class="appLeftMenu"></div>
- <div ng-view style="min-height: 450px;margin-top:-50px;margin-left:210px;margin-right:10px;"></div>
- <div q-footer class="appFooter"></div>
- </body>
-</html>
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/fusion-sunny.css b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/fusion-sunny.css
deleted file mode 100644
index c8306156..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/fusion-sunny.css
+++ /dev/null
@@ -1,362 +0,0 @@
- input, textarea, select, div {
- font-family: Arial;
- font-size: 11px;
- font-weight: normal;
- }
-
- form {
- margin-top: 5px;
- }
-
-
- .applicationWindow { border-width: 0px 0px 1px 0px;
- border-style: solid;
- border-color: #959595;
- box-shadow: inset 0 0 10px #000000;
- margin-top: 10px;
- margin-bottom: 10px;
- margin-left: 10px;
- margin-right: 10px;
- }
-
- .feedbackMessage { width: 99%;
- font-family: Arial;
- font-size: 11px;
- color: #1f1f1f;
- padding: 3px;
- border: 1px #eeb420 solid;
- margin: 3px;
- background: #fff9e5;
- }
-
- .menubar {
- border-width: 0px 0px 0px 1px; border-style: solid; border-color: #959595;
- }
-
- .footer {
- /*clear: both;*/
- border-width: 0px 1px 0px 1px; border-style: solid; border-color: #959595;
- font-family: Verdana,Arial,Helvetica, sans-serif;
- font-size: 9px;
- padding: 10px 10px 30px 10px;
- background: white;
- }
-
- .pageTitle {
- font-family: Arial;
- font-size: 18px;
- font-weight: bold;
- margin-top: 5px;
- }
-
- .content {
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- font-family: Arial;
- font-size: 11px;
- padding: 5px;
- background: white;
- /*height: 600px;*/
- }
-
- .popupContent {
- font-family: Arial;
- font-size: 11px;
- padding: 3px;
- }
-
- .logo {
- border-width: 0px 1px 0px 1px;
- border-style: solid;
- border-color: #959595;
- text-align: right;
- }
-
- .sep {
- border: 1px solid black
- }
-
- .attLogo { /*position: relative;*/
- float:left;
- padding-top: 25px;
- padding-left: 25px;
- }
-
- .applicationLogo { float:right;
- padding-top: 25px;
- padding-right: 25px;
- }
-
- .applinkWhite { font-family: Arial;
- font-size: 13px;
- font-weight: 900;
- color: #FFFFFF;
- text-decoration: none; }
-
- .terms { font-family: Verdana, Arial, Helvetica, sans-serif;
- font-size: 9px;
- }
-
- .broadcastMessage { color: red; }
- .broadcastMessageList { color: red; }
-
- .button {
- margin: 5px 1px 5px 1px;
- padding: 3px; }
-
- .toolbarbutton:hover {
- color:#005491;
- }
-
- .headerText { font-family: Arial;
- font-size: 15px;
- font-weight: 700;
- color: #000000; }
-
- .headerBackground { background: #336699; }
-
- .errorMessageText { font-family: Arial;
- font-size: 11px;
- font-weight: bold;
- color: red; }
-
-
- .normalText { font-family: Arial;
- font-size: 11px;
- color: #000000; }
-
- .normalTextRed { font-family: Arial;
- font-size: 11px;
- color: red; }
-
-
- .smallNormalText { font-family: Arial;
- font-size: 9px;
- color: #000000; }
-
- .tableBorder { border:1px outset teal }
-
- .validationError { background: #b9eaff; }
-
- .templatebody {
- background: url(../images/body_graphic.jpg) repeat-x;
- /*margin: 40px 80px 40px 80px;*/
- }
-
- /*--------------------- General Content ------------------------------------*/
-
- .relative {
- position:relative;
- }
-
- .clear{
- clear:both;
- }
-
- .left {
- float: left;
- }
-
- .leftCentered{
- float: left;
- text-align: center;
- }
-
- .right {
- float: right;
- }
-
- .rightAligned{
- text-align: right;
- }
-
- .centered {
- text-align: center;
- align: center;
- }
-
-
- .noWrap{
- white-space:nowrap;
- }
-
- .disabled {
- color:gray;
- cursor:hand;
- }
-
- /*--------------------- Tab styles -------------------------------------*/
-
- .current {
- font-weight: bold;
- border-width: 1px 1px 1px 1px;
- border-color: silver;
- border-style: solid;
- }
-
- .subTab {
- font-weight:bold;
- font-family: Arial;
- font-size: 11px;
- color: #0F3B82;
- }
-
-
- /*--------------------- Grid styles ------------------------------------*/
-
- /* Grid navigation and header styles */
- .gridFilterLabel {font-size: 7pt;
- font-align: justify;
- font-weight: bold;
- display: block;}
-
- .gridFilterText {height: 17px;
- font-size: 8pt;
- width: 60%;
- font-align: justify;}
-
- .gridNavigationBar { font-family:Arial,Verdana;
- font-size:11px;
- font-weight:normal;
- color:#000;
- margin: 0px;
- width: 100%;
- vertical-align: middle;
- }
-
- .gridNavigationBar .navLinks { float: left;
- margin-right:15px;
- padding-top: 2px;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageControls { float: left;
- margin-right: 15px;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageControls input { font-size: 8pt;
- height: 17px;
- vertical-align: middle;
- }
-
- .gridNavigationBar .pageInfo { float: right;
- vertical-align: middle;
- height: 19px;
- line-height: 19px;
- }
-
- .gridNavigationBar .pageInfo input { font-size: 8pt;
- height: 17px;
- vertical-align: middle;
- }
-
-
- .gridNavigationBar span { padding: 3px; }
-
- .gridNavigationBar a {
- text-decoration:underline;
- color:#000;
- font-weight:normal;
- }
-
- .gridNavigationBar img { vertical-align: middle; }
-
- .gridBulkUpdateRow {
- height: 35px;
- line-height: 35px;
- }
-
- .gridBulkUpdateRow input {
- vertical-align: middle;
- }
-
-
- /* dummy class used to lock the form elements of a grid - ex. bulk transaction processing */
- .alwaysEnabled {}
-
- .hidden {
- display: none;
- }
-
- .selectedPage {
- background-color:#C4DFFB;
- color: white;
- border-style: solid;
- border-width: 1px;
- border-color: gray;
- padding-left: 3px;
- padding-right: 3px;
- vertical-align: middle;
- }
-
- .selectedRow{
- /*background-color:#C4DFFB;*/
- }
-
- /* Action Item styles */
- .actionList {
- margin-left: -20px;
- margin-right: -10px;
- padding-left: 5px;
- }
-
- .actionList li {
- float:left;
- padding-left: 3px;
- padding-right: 3px;
- }
-
- .actionList li a {
- text-decoration:none;
- color:#000;
- }
-
- /* Filter Operator List styles */
-
- .filterList {
- margin: 0px;
- }
-
- .filterList li {
- list-style-type: none;
- padding:3px 3px 3px 2px;
- cursor:hand;
- font-size:11px;
- }
-
- .filterList li:hover {
- background: #404040;
- }
-
- .filterList li a {
- color: #000;
- text-decoration: none;
- }
-
- .filterList li:hover a {
- color: white;
- }
-
- .filterList li a:hover {
- text-decoration: none;
- color: white;
- }
-
- .filterListItem a {
- text-decoration:none;
- padding:3px 2px 3px 2px;
- }
-
-
- /*---------------------- Customized ZK Styles ------------------------------*/
-
- .z-datebox input, .z-timebox input {
- font-family: Arial;
- font-size: 11px;
- height: 15px;
- margin-top:1px;
- }
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/jquery-ui.css b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/jquery-ui.css
deleted file mode 100644
index 1c22746c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/jquery-ui.css
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*! jQuery UI - v1.11.4 - 2015-03-11
-* http://jqueryui.com
-* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden {
- display: none;
-}
-.ui-helper-hidden-accessible {
- border: 0;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-.ui-helper-reset {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- line-height: 1.3;
- text-decoration: none;
- font-size: 100%;
- list-style: none;
-}
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
- content: "";
- display: table;
- border-collapse: collapse;
-}
-.ui-helper-clearfix:after {
- clear: both;
-}
-.ui-helper-clearfix {
- min-height: 0; /* support: IE7 */
-}
-.ui-helper-zfix {
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- position: absolute;
- opacity: 0;
- filter:Alpha(Opacity=0); /* support: IE8 */
-}
-
-.ui-front {
- z-index: 100;
-}
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
- cursor: default !important;
-}
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- display: block;
- text-indent: -99999px;
- overflow: hidden;
- background-repeat: no-repeat;
-}
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-.ui-accordion .ui-accordion-header {
- display: block;
- cursor: pointer;
- position: relative;
- margin: 2px 0 0 0;
- padding: .5em .5em .5em .7em;
- min-height: 0; /* support: IE7 */
- font-size: 100%;
-}
-.ui-accordion .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-icons .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
- position: absolute;
- left: .5em;
- top: 50%;
- margin-top: -8px;
-}
-.ui-accordion .ui-accordion-content {
- padding: 1em 2.2em;
- border-top: 0;
- overflow: auto;
-}
-.ui-autocomplete {
- position: absolute;
- top: 0;
- left: 0;
- cursor: default;
-}
-.ui-button {
- display: inline-block;
- position: relative;
- padding: 0;
- line-height: normal;
- margin-right: .1em;
- cursor: pointer;
- vertical-align: middle;
- text-align: center;
- overflow: visible; /* removes extra width in IE */
-}
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
- text-decoration: none;
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
- width: 2.2em;
-}
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
- width: 2.4em;
-}
-.ui-button-icons-only {
- width: 3.4em;
-}
-button.ui-button-icons-only {
- width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
- display: block;
- line-height: normal;
-}
-.ui-button-text-only .ui-button-text {
- padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
- padding: .4em;
- text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
- padding-left: 2.1em;
- padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
- padding: .4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
- position: absolute;
- top: 50%;
- margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
- left: 50%;
- margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
- left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
- right: .5em;
-}
-
-/* button sets */
-.ui-buttonset {
- margin-right: 7px;
-}
-.ui-buttonset .ui-button {
- margin-left: 0;
- margin-right: -.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-.ui-datepicker {
- width: 17em;
- padding: .2em .2em 0;
- display: none;
-}
-.ui-datepicker .ui-datepicker-header {
- position: relative;
- padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
- position: absolute;
- top: 2px;
- width: 1.8em;
- height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
- top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
- left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
- right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
- left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
- right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
- display: block;
- position: absolute;
- left: 50%;
- margin-left: -8px;
- top: 50%;
- margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
- margin: 0 2.3em;
- line-height: 1.8em;
- text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
- font-size: 1em;
- margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
- width: 45%;
-}
-.ui-datepicker table {
- width: 100%;
- font-size: .9em;
- border-collapse: collapse;
- margin: 0 0 .4em;
-}
-.ui-datepicker th {
- padding: .7em .3em;
- text-align: center;
- font-weight: bold;
- border: 0;
-}
-.ui-datepicker td {
- border: 0;
- padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
- display: block;
- padding: .2em;
- text-align: right;
- text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
- background-image: none;
- margin: .7em 0 0 0;
- padding: 0 .2em;
- border-left: 0;
- border-right: 0;
- border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
- float: right;
- margin: .5em .2em .4em;
- cursor: pointer;
- padding: .2em .6em .3em .6em;
- width: auto;
- overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
- float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
- width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
- float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
- width: 95%;
- margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
- width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
- width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
- width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
- border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
- clear: left;
-}
-.ui-datepicker-row-break {
- clear: both;
- width: 100%;
- font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
- direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
- right: 2px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
- left: 2px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
- right: 1px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
- left: 1px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
- clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
- float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
- float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
- border-right-width: 0;
- border-left-width: 1px;
-}
-.ui-dialog {
- overflow: hidden;
- position: absolute;
- top: 0;
- left: 0;
- padding: .2em;
- outline: 0;
-}
-.ui-dialog .ui-dialog-titlebar {
- padding: .4em 1em;
- position: relative;
-}
-.ui-dialog .ui-dialog-title {
- float: left;
- margin: .1em 0;
- white-space: nowrap;
- width: 90%;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.ui-dialog .ui-dialog-titlebar-close {
- position: absolute;
- right: .3em;
- top: 50%;
- width: 20px;
- margin: -10px 0 0 0;
- padding: 1px;
- height: 20px;
-}
-.ui-dialog .ui-dialog-content {
- position: relative;
- border: 0;
- padding: .5em 1em;
- background: none;
- overflow: auto;
-}
-.ui-dialog .ui-dialog-buttonpane {
- text-align: left;
- border-width: 1px 0 0 0;
- background-image: none;
- margin-top: .5em;
- padding: .3em 1em .5em .4em;
-}
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
- float: right;
-}
-.ui-dialog .ui-dialog-buttonpane button {
- margin: .5em .4em .5em 0;
- cursor: pointer;
-}
-.ui-dialog .ui-resizable-se {
- width: 12px;
- height: 12px;
- right: -5px;
- bottom: -5px;
- background-position: 16px 16px;
-}
-.ui-draggable .ui-dialog-titlebar {
- cursor: move;
-}
-.ui-draggable-handle {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-menu {
- list-style: none;
- padding: 0;
- margin: 0;
- display: block;
- outline: none;
-}
-.ui-menu .ui-menu {
- position: absolute;
-}
-.ui-menu .ui-menu-item {
- position: relative;
- margin: 0;
- padding: 3px 1em 3px .4em;
- cursor: pointer;
- min-height: 0; /* support: IE7 */
- /* support: IE10, see #8844 */
- list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
-}
-.ui-menu .ui-menu-divider {
- margin: 5px 0;
- height: 0;
- font-size: 0;
- line-height: 0;
- border-width: 1px 0 0 0;
-}
-.ui-menu .ui-state-focus,
-.ui-menu .ui-state-active {
- margin: -1px;
-}
-
-/* icon support */
-.ui-menu-icons {
- position: relative;
-}
-.ui-menu-icons .ui-menu-item {
- padding-left: 2em;
-}
-
-/* left-aligned */
-.ui-menu .ui-icon {
- position: absolute;
- top: 0;
- bottom: 0;
- left: .2em;
- margin: auto 0;
-}
-
-/* right-aligned */
-.ui-menu .ui-menu-icon {
- left: auto;
- right: 0;
-}
-.ui-progressbar {
- height: 2em;
- text-align: left;
- overflow: hidden;
-}
-.ui-progressbar .ui-progressbar-value {
- margin: -1px;
- height: 100%;
-}
-.ui-progressbar .ui-progressbar-overlay {
- background: url("data:image/gif;base64,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");
- height: 100%;
- filter: alpha(opacity=25); /* support: IE8 */
- opacity: 0.25;
-}
-.ui-progressbar-indeterminate .ui-progressbar-value {
- background-image: none;
-}
-.ui-resizable {
- position: relative;
-}
-.ui-resizable-handle {
- position: absolute;
- font-size: 0.1px;
- display: block;
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-resizable-disabled .ui-resizable-handle,
-.ui-resizable-autohide .ui-resizable-handle {
- display: none;
-}
-.ui-resizable-n {
- cursor: n-resize;
- height: 7px;
- width: 100%;
- top: -5px;
- left: 0;
-}
-.ui-resizable-s {
- cursor: s-resize;
- height: 7px;
- width: 100%;
- bottom: -5px;
- left: 0;
-}
-.ui-resizable-e {
- cursor: e-resize;
- width: 7px;
- right: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-w {
- cursor: w-resize;
- width: 7px;
- left: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-se {
- cursor: se-resize;
- width: 12px;
- height: 12px;
- right: 1px;
- bottom: 1px;
-}
-.ui-resizable-sw {
- cursor: sw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- bottom: -5px;
-}
-.ui-resizable-nw {
- cursor: nw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- top: -5px;
-}
-.ui-resizable-ne {
- cursor: ne-resize;
- width: 9px;
- height: 9px;
- right: -5px;
- top: -5px;
-}
-.ui-selectable {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-selectable-helper {
- position: absolute;
- z-index: 100;
- border: 1px dotted black;
-}
-.ui-selectmenu-menu {
- padding: 0;
- margin: 0;
- position: absolute;
- top: 0;
- left: 0;
- display: none;
-}
-.ui-selectmenu-menu .ui-menu {
- overflow: auto;
- /* Support: IE7 */
- overflow-x: hidden;
- padding-bottom: 1px;
-}
-.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
- font-size: 1em;
- font-weight: bold;
- line-height: 1.5;
- padding: 2px 0.4em;
- margin: 0.5em 0 0 0;
- height: auto;
- border: 0;
-}
-.ui-selectmenu-open {
- display: block;
-}
-.ui-selectmenu-button {
- display: inline-block;
- overflow: hidden;
- position: relative;
- text-decoration: none;
- cursor: pointer;
-}
-.ui-selectmenu-button span.ui-icon {
- right: 0.5em;
- left: auto;
- margin-top: -8px;
- position: absolute;
- top: 50%;
-}
-.ui-selectmenu-button span.ui-selectmenu-text {
- text-align: left;
- padding: 0.4em 2.1em 0.4em 1em;
- display: block;
- line-height: 1.4;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-.ui-slider {
- position: relative;
- text-align: left;
-}
-.ui-slider .ui-slider-handle {
- position: absolute;
- z-index: 2;
- width: 1.2em;
- height: 1.2em;
- cursor: default;
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-slider .ui-slider-range {
- position: absolute;
- z-index: 1;
- font-size: .7em;
- display: block;
- border: 0;
- background-position: 0 0;
-}
-
-/* support: IE8 - See #6727 */
-.ui-slider.ui-state-disabled .ui-slider-handle,
-.ui-slider.ui-state-disabled .ui-slider-range {
- filter: inherit;
-}
-
-.ui-slider-horizontal {
- height: .8em;
-}
-.ui-slider-horizontal .ui-slider-handle {
- top: -.3em;
- margin-left: -.6em;
-}
-.ui-slider-horizontal .ui-slider-range {
- top: 0;
- height: 100%;
-}
-.ui-slider-horizontal .ui-slider-range-min {
- left: 0;
-}
-.ui-slider-horizontal .ui-slider-range-max {
- right: 0;
-}
-
-.ui-slider-vertical {
- width: .8em;
- height: 100px;
-}
-.ui-slider-vertical .ui-slider-handle {
- left: -.3em;
- margin-left: 0;
- margin-bottom: -.6em;
-}
-.ui-slider-vertical .ui-slider-range {
- left: 0;
- width: 100%;
-}
-.ui-slider-vertical .ui-slider-range-min {
- bottom: 0;
-}
-.ui-slider-vertical .ui-slider-range-max {
- top: 0;
-}
-.ui-sortable-handle {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-spinner {
- position: relative;
- display: inline-block;
- overflow: hidden;
- padding: 0;
- vertical-align: middle;
-}
-.ui-spinner-input {
- border: none;
- background: none;
- color: inherit;
- padding: 0;
- margin: .2em 0;
- vertical-align: middle;
- margin-left: .4em;
- margin-right: 22px;
-}
-.ui-spinner-button {
- width: 16px;
- height: 50%;
- font-size: .5em;
- padding: 0;
- margin: 0;
- text-align: center;
- position: absolute;
- cursor: default;
- display: block;
- overflow: hidden;
- right: 0;
-}
-/* more specificity required here to override default borders */
-.ui-spinner a.ui-spinner-button {
- border-top: none;
- border-bottom: none;
- border-right: none;
-}
-/* vertically center icon */
-.ui-spinner .ui-icon {
- position: absolute;
- margin-top: -8px;
- top: 50%;
- left: 0;
-}
-.ui-spinner-up {
- top: 0;
-}
-.ui-spinner-down {
- bottom: 0;
-}
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
- /* need to fix icons sprite */
- background-position: -65px -16px;
-}
-.ui-tabs {
- position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
- padding: .2em;
-}
-.ui-tabs .ui-tabs-nav {
- margin: 0;
- padding: .2em .2em 0;
-}
-.ui-tabs .ui-tabs-nav li {
- list-style: none;
- float: left;
- position: relative;
- top: 0;
- margin: 1px .2em 0 0;
- border-bottom-width: 0;
- padding: 0;
- white-space: nowrap;
-}
-.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
- float: left;
- padding: .5em 1em;
- text-decoration: none;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active {
- margin-bottom: -1px;
- padding-bottom: 1px;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
- cursor: text;
-}
-.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
- cursor: pointer;
-}
-.ui-tabs .ui-tabs-panel {
- display: block;
- border-width: 0;
- padding: 1em 1.4em;
- background: none;
-}
-.ui-tooltip {
- padding: 8px;
- position: absolute;
- z-index: 9999;
- max-width: 300px;
- -webkit-box-shadow: 0 0 5px #aaa;
- box-shadow: 0 0 5px #aaa;
-}
-body .ui-tooltip {
- border-width: 2px;
-}
-
-/* Component containers
-----------------------------------*/
-.ui-widget {
- font-family: Verdana,Arial,sans-serif;
- font-size: 1.1em;
-}
-.ui-widget .ui-widget {
- font-size: 1em;
-}
-.ui-widget input,
-.ui-widget select,
-.ui-widget textarea,
-.ui-widget button {
- font-family: Verdana,Arial,sans-serif;
- font-size: 1em;
-}
-.ui-widget-content {
- border: 1px solid #aaaaaa;
- background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
- color: #222222;
-}
-.ui-widget-content a {
- color: #222222;
-}
-.ui-widget-header {
- border: 1px solid #aaaaaa;
- background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
- color: #222222;
- font-weight: bold;
-}
-.ui-widget-header a {
- color: #222222;
-}
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default,
-.ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
- border: 1px solid #d3d3d3;
- background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #555555;
-}
-.ui-state-default a,
-.ui-state-default a:link,
-.ui-state-default a:visited {
- color: #555555;
- text-decoration: none;
-}
-.ui-state-hover,
-.ui-widget-content .ui-state-hover,
-.ui-widget-header .ui-state-hover,
-.ui-state-focus,
-.ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
- border: 1px solid #999999;
- background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #212121;
-}
-.ui-state-hover a,
-.ui-state-hover a:hover,
-.ui-state-hover a:link,
-.ui-state-hover a:visited,
-.ui-state-focus a,
-.ui-state-focus a:hover,
-.ui-state-focus a:link,
-.ui-state-focus a:visited {
- color: #212121;
- text-decoration: none;
-}
-.ui-state-active,
-.ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
- border: 1px solid #aaaaaa;
- background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #212121;
-}
-.ui-state-active a,
-.ui-state-active a:link,
-.ui-state-active a:visited {
- color: #212121;
- text-decoration: none;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight,
-.ui-widget-content .ui-state-highlight,
-.ui-widget-header .ui-state-highlight {
- border: 1px solid #fcefa1;
- background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
- color: #363636;
-}
-.ui-state-highlight a,
-.ui-widget-content .ui-state-highlight a,
-.ui-widget-header .ui-state-highlight a {
- color: #363636;
-}
-.ui-state-error,
-.ui-widget-content .ui-state-error,
-.ui-widget-header .ui-state-error {
- border: 1px solid #cd0a0a;
- background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
- color: #cd0a0a;
-}
-.ui-state-error a,
-.ui-widget-content .ui-state-error a,
-.ui-widget-header .ui-state-error a {
- color: #cd0a0a;
-}
-.ui-state-error-text,
-.ui-widget-content .ui-state-error-text,
-.ui-widget-header .ui-state-error-text {
- color: #cd0a0a;
-}
-.ui-priority-primary,
-.ui-widget-content .ui-priority-primary,
-.ui-widget-header .ui-priority-primary {
- font-weight: bold;
-}
-.ui-priority-secondary,
-.ui-widget-content .ui-priority-secondary,
-.ui-widget-header .ui-priority-secondary {
- opacity: .7;
- filter:Alpha(Opacity=70); /* support: IE8 */
- font-weight: normal;
-}
-.ui-state-disabled,
-.ui-widget-content .ui-state-disabled,
-.ui-widget-header .ui-state-disabled {
- opacity: .35;
- filter:Alpha(Opacity=35); /* support: IE8 */
- background-image: none;
-}
-.ui-state-disabled .ui-icon {
- filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
-}
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- width: 16px;
- height: 16px;
-}
-.ui-icon,
-.ui-widget-content .ui-icon {
- background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-widget-header .ui-icon {
- background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-state-default .ui-icon {
- background-image: url("images/ui-icons_888888_256x240.png");
-}
-.ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
- background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-active .ui-icon {
- background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-highlight .ui-icon {
- background-image: url("images/ui-icons_2e83ff_256x240.png");
-}
-.ui-state-error .ui-icon,
-.ui-state-error-text .ui-icon {
- background-image: url("images/ui-icons_cd0a0a_256x240.png");
-}
-
-/* positioning */
-.ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-left,
-.ui-corner-tl {
- border-top-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-right,
-.ui-corner-tr {
- border-top-right-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-left,
-.ui-corner-bl {
- border-bottom-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-right,
-.ui-corner-br {
- border-bottom-right-radius: 4px;
-}
-
-/* Overlays */
-.ui-widget-overlay {
- background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30); /* support: IE8 */
-}
-.ui-widget-shadow {
- margin: -8px 0 0 -8px;
- padding: 8px;
- background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30); /* support: IE8 */
- border-radius: 8px;
-}
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/layout/layout-default-latest.css b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/layout/layout-default-latest.css
deleted file mode 100644
index aa382de3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/css/layout/layout-default-latest.css
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Default Layout Theme
- *
- * Created for jquery.layout
- *
- * Copyright (c) 2010
- * Fabrizio Balliano (http://www.fabrizioballiano.net)
- * Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * Last Updated: 2010-02-10
- * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
- */
-
-/*
- * DEFAULT FONT
- * Just to make demo-pages look better - not actually relevant to Layout!
- */
-body {
- font-family: Geneva, Arial, Helvetica, sans-serif;
- font-size: 100%;
- *font-size: 80%;
-}
-
-/*
- * PANES & CONTENT-DIVs
- */
-.ui-layout-pane { /* all 'panes' */
- background: #FFF;
- border: 1px solid #BBB;
- padding: 10px;
- overflow: auto;
- /* DO NOT add scrolling (or padding) to 'panes' that have a content-div,
- otherwise you may get double-scrollbars - on the pane AND on the content-div
- - use ui-layout-wrapper class if pane has a content-div
- - use ui-layout-container if pane has an inner-layout
- */
- }
- /* (scrolling) content-div inside pane allows for fixed header(s) and/or footer(s) */
- .ui-layout-content {
- padding: 10px;
- position: relative; /* contain floated or positioned elements */
- overflow: auto; /* add scrolling to content-div */
- }
-
-/*
- * UTILITY CLASSES
- * Must come AFTER pane-class above so will override
- * These classes are NOT auto-generated and are NOT used by Layout
- */
-.layout-child-container,
-.layout-content-container {
- padding: 0;
- overflow: hidden;
-}
-.layout-child-container {
- border: 0; /* remove border because inner-layout-panes probably have borders */
-}
-.layout-scroll {
- overflow: auto;
-}
-.layout-hide {
- display: none;
-}
-
-/*
- * RESIZER-BARS
- */
-.ui-layout-resizer { /* all 'resizer-bars' */
- background: #DDD;
- border: 1px solid #BBB;
- border-width: 0;
- }
- .ui-layout-resizer-drag { /* REAL resizer while resize in progress */
- }
- .ui-layout-resizer-hover { /* affects both open and closed states */
- }
- /* NOTE: It looks best when 'hover' and 'dragging' are set to the same color,
- otherwise color shifts while dragging when bar can't keep up with mouse */
- .ui-layout-resizer-open-hover , /* hover-color to 'resize' */
- .ui-layout-resizer-dragging { /* resizer beging 'dragging' */
- background: #C4E1A4;
- }
- .ui-layout-resizer-dragging { /* CLONED resizer being dragged */
- border: 1px solid #BBB;
- }
- .ui-layout-resizer-north-dragging,
- .ui-layout-resizer-south-dragging {
- border-width: 1px 0;
- }
- .ui-layout-resizer-west-dragging,
- .ui-layout-resizer-east-dragging {
- border-width: 0 1px;
- }
- /* NOTE: Add a 'dragging-limit' color to provide visual feedback when resizer hits min/max size limits */
- .ui-layout-resizer-dragging-limit { /* CLONED resizer at min or max size-limit */
- background: #E1A4A4; /* red */
- }
-
- .ui-layout-resizer-closed-hover { /* hover-color to 'slide open' */
- background: #EBD5AA;
- }
- .ui-layout-resizer-sliding { /* resizer when pane is 'slid open' */
- opacity: .10; /* show only a slight shadow */
- filter: alpha(opacity=10);
- }
- .ui-layout-resizer-sliding-hover { /* sliding resizer - hover */
- opacity: 1.00; /* on-hover, show the resizer-bar normally */
- filter: alpha(opacity=100);
- }
- /* sliding resizer - add 'outside-border' to resizer on-hover
- * this sample illustrates how to target specific panes and states */
- .ui-layout-resizer-north-sliding-hover { border-bottom-width: 1px; }
- .ui-layout-resizer-south-sliding-hover { border-top-width: 1px; }
- .ui-layout-resizer-west-sliding-hover { border-right-width: 1px; }
- .ui-layout-resizer-east-sliding-hover { border-left-width: 1px; }
-
-/*
- * TOGGLER-BUTTONS
- */
-.ui-layout-toggler {
- border: 1px solid #BBB; /* match pane-border */
- background-color: #BBB;
- }
- .ui-layout-resizer-hover .ui-layout-toggler {
- opacity: .60;
- filter: alpha(opacity=60);
- }
- .ui-layout-toggler-hover , /* need when NOT resizable */
- .ui-layout-resizer-hover .ui-layout-toggler-hover { /* need specificity when IS resizable */
- background-color: #FC6;
- opacity: 1.00;
- filter: alpha(opacity=100);
- }
- .ui-layout-toggler-north ,
- .ui-layout-toggler-south {
- border-width: 0 1px; /* left/right borders */
- }
- .ui-layout-toggler-west ,
- .ui-layout-toggler-east {
- border-width: 1px 0; /* top/bottom borders */
- }
- /* hide the toggler-button when the pane is 'slid open' */
- .ui-layout-resizer-sliding .ui-layout-toggler {
- display: none;
- }
- /*
- * style the text we put INSIDE the togglers
- */
- .ui-layout-toggler .content {
- color: #666;
- font-size: 12px;
- font-weight: bold;
- width: 100%;
- padding-bottom: 0.35ex; /* to 'vertically center' text inside text-span */
- }
-
-/*
- * PANE-MASKS
- * these styles are hard-coded on mask elems, but are also
- * included here as !important to ensure will overrides any generic styles
- */
-.ui-layout-mask {
- border: none !important;
- padding: 0 !important;
- margin: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- opacity: 0 !important;
- filter: Alpha(Opacity="0") !important;
-}
-.ui-layout-mask-inside-pane { /* masks always inside pane EXCEPT when pane is an iframe */
- top: 0 !important;
- left: 0 !important;
- width: 100% !important;
- height: 100% !important;
-}
-div.ui-layout-mask {} /* standard mask for iframes */
-iframe.ui-layout-mask {} /* extra mask for objects/applets */
-
-/*
- * Default printing styles
- */
-@media print {
- /*
- * Unless you want to print the layout as it appears onscreen,
- * these html/body styles are needed to allow the content to 'flow'
- */
- html {
- height: auto !important;
- overflow: visible !important;
- }
- body.ui-layout-container {
- position: static !important;
- top: auto !important;
- bottom: auto !important;
- left: auto !important;
- right: auto !important;
- /* only IE6 has container width & height set by Layout */
- _width: auto !important;
- _height: auto !important;
- }
- .ui-layout-resizer, .ui-layout-toggler {
- display: none !important;
- }
- /*
- * Default pane print styles disables positioning, borders and backgrounds.
- * You can modify these styles however it suit your needs.
- */
- .ui-layout-pane {
- border: none !important;
- background: transparent !important;
- position: relative !important;
- top: auto !important;
- bottom: auto !important;
- left: auto !important;
- right: auto !important;
- width: auto !important;
- height: auto !important;
- overflow: visible !important;
- }
-} \ No newline at end of file
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Rlogo.jpg b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Rlogo.jpg
deleted file mode 100644
index 656a6b1f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Rlogo.jpg
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Thumbs.db b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Thumbs.db
deleted file mode 100644
index f504b226..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/Thumbs.db
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_icon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_icon.png
deleted file mode 100644
index f2d1bc0b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_icon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_list_spacer.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_list_spacer.gif
deleted file mode 100644
index 0afdd23b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/action_list_spacer.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/active.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/active.png
deleted file mode 100644
index 45241776..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/active.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add.png
deleted file mode 100644
index 46d944b3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add_tool_button.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add_tool_button.png
deleted file mode 100644
index 1e7890dd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/add_tool_button.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/addicon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/addicon.png
deleted file mode 100644
index 6cb5042f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/addicon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/application_window_bg.jpg b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/application_window_bg.jpg
deleted file mode 100644
index c559e590..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/application_window_bg.jpg
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/backButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/backButton.png
deleted file mode 100644
index e27ea8cd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/backButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blueButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blueButton.png
deleted file mode 100644
index 0cfbee11..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/blueButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/bubble.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/bubble.png
deleted file mode 100644
index dd5abd37..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/bubble.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/cache.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/cache.png
deleted file mode 100644
index 67fb3550..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/cache.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/calendar.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/calendar.gif
deleted file mode 100644
index a90aef06..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/calendar.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/chevron.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/chevron.png
deleted file mode 100644
index 7f7ae156..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/chevron.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/close_container.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/close_container.gif
deleted file mode 100644
index e2f67d72..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/close_container.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/collapsed-icon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/collapsed-icon.png
deleted file mode 100644
index 000cbec5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/collapsed-icon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/column-bg.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/column-bg.png
deleted file mode 100644
index 1005ea7d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/column-bg.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-add.png
deleted file mode 100644
index 127cdac4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-search.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-search.png
deleted file mode 100644
index fb08f84e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers-search.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers.png
deleted file mode 100644
index f9bb5ef1..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/customers.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/decrypted.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/decrypted.png
deleted file mode 100644
index 236cbeb8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/decrypted.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/error_type.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/error_type.gif
deleted file mode 100644
index bd51e815..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/error_type.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/excelicon_multi.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/excelicon_multi.gif
deleted file mode 100644
index 1a4fbaab..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/excelicon_multi.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/expanded-icon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/expanded-icon.png
deleted file mode 100644
index 490e068f..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/expanded-icon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file-add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file-add.png
deleted file mode 100644
index 076bd898..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_save-all.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_save-all.png
deleted file mode 100644
index 3c300ecb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/file_save-all.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/filter_icon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/filter_icon.png
deleted file mode 100644
index c36ad2c2..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/filter_icon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_add.png
deleted file mode 100644
index 83761c29..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_closed.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_closed.png
deleted file mode 100644
index 1b365fd8..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_closed.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_delete.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_delete.png
deleted file mode 100644
index bb56a9e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_delete.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_edit.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_edit.png
deleted file mode 100644
index fe774a62..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_edit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_open.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_open.png
deleted file mode 100644
index f1ed9abe..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_open.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_user.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_user.png
deleted file mode 100644
index 2cd28412..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/folder_user.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/funnel.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/funnel.png
deleted file mode 100644
index 35f1d259..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/funnel.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/fusion.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/fusion.gif
deleted file mode 100644
index 368319e6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/fusion.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/grayButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/grayButton.png
deleted file mode 100644
index 83f2c45e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/grayButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/gray_add_tool_button.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/gray_add_tool_button.png
deleted file mode 100644
index 962b0a8a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/gray_add_tool_button.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/headerChatIcon.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/headerChatIcon.png
deleted file mode 100644
index 9b0840ad..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/headerChatIcon.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/icon_remove_all.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/icon_remove_all.gif
deleted file mode 100644
index 0912b4a3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/icon_remove_all.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/inactive.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/inactive.png
deleted file mode 100644
index e9920bf4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/inactive.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/info_type.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/info_type.gif
deleted file mode 100644
index 8dd66f30..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/info_type.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/leftButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/leftButton.png
deleted file mode 100644
index edf02c6c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/leftButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading_bar.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading_bar.gif
deleted file mode 100644
index eed8a505..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/loading_bar.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/login_button.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/login_button.gif
deleted file mode 100644
index 990b5227..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/login_button.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/m1.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/m1.gif
deleted file mode 100644
index f7161fd9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/m1.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/mail.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/mail.png
deleted file mode 100644
index bcf7d254..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/mail.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/map.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/map.png
deleted file mode 100644
index 9ecb79ab..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/map.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/no_favorites_star.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/no_favorites_star.png
deleted file mode 100644
index 4db05403..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/no_favorites_star.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-add.png
deleted file mode 100644
index 96bbaf47..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-search.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-search.png
deleted file mode 100644
index dbdab172..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note-search.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note.png
deleted file mode 100644
index f082b0e9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/note.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/notes.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/notes.png
deleted file mode 100644
index f54a9e8d..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/notes.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offline.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offline.png
deleted file mode 100644
index 4519ff32..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offline.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offlineMsg.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offlineMsg.gif
deleted file mode 100644
index dbbe02fb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/offlineMsg.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/online.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/online.png
deleted file mode 100644
index 7a74a9c5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/online.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/page.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/page.gif
deleted file mode 100644
index 10b36fa9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/page.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pagination.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pagination.png
deleted file mode 100644
index 4dc46107..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pagination.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-e-w-toggle.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-e-w-toggle.png
deleted file mode 100644
index b3863ee7..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-e-w-toggle.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-n-s-toggle.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-n-s-toggle.png
deleted file mode 100644
index b5d9c3c0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/panel-n-s-toggle.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pix.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pix.gif
deleted file mode 100644
index c7bee69b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/pix.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/printer.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/printer.gif
deleted file mode 100644
index 37f2d98a..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/printer.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/profile.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/profile.png
deleted file mode 100644
index a3998fca..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/profile.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-active.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-active.png
deleted file mode 100644
index 0e54592c..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-active.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-disabled.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-disabled.png
deleted file mode 100644
index f5610ff5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-first-disabled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-active.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-active.png
deleted file mode 100644
index 5ee5da40..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-active.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-disabled.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-disabled.png
deleted file mode 100644
index 8647a553..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-last-disabled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-active.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-active.png
deleted file mode 100644
index 3c079364..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-active.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-disabled.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-disabled.png
deleted file mode 100644
index 12f6d6b6..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-next-disabled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-active.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-active.png
deleted file mode 100644
index 2c7246af..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-active.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-disabled.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-disabled.png
deleted file mode 100644
index 46c82bd5..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/results-prev-disabled.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_last.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_last.png
deleted file mode 100644
index b8c4f099..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_last.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_previous.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_previous.png
deleted file mode 100644
index 73b83326..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/resultset_previous.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/return_to_top.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/return_to_top.gif
deleted file mode 100644
index f02defb9..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/return_to_top.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/rightButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/rightButton.png
deleted file mode 100644
index 9d868f9b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/rightButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search_profile.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search_profile.png
deleted file mode 100644
index 28852144..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/search_profile.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_asc.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_asc.gif
deleted file mode 100644
index 427928f3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_asc.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_desc.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_desc.gif
deleted file mode 100644
index 5aa81a18..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/sort_desc.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/spacer.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/spacer.gif
deleted file mode 100644
index fc256098..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/spacer.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/success_type.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/success_type.gif
deleted file mode 100644
index 2f72242b..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/success_type.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/swoosh.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/swoosh.gif
deleted file mode 100644
index 4b791772..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/swoosh.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-hm.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-hm.png
deleted file mode 100644
index 1e75d8d4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-hm.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-v-hm.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-v-hm.png
deleted file mode 100644
index df8c6cbf..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab-v-hm.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab.png
deleted file mode 100644
index 00eb6fcb..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tab.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-add.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-add.png
deleted file mode 100644
index 0c138576..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-add.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-delete.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-delete.png
deleted file mode 100644
index 917d7d28..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-delete.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-edit.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-edit.png
deleted file mode 100644
index 40dbc0bd..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table-edit.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table.png
deleted file mode 100644
index ff025e70..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/table.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tabs-bg.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tabs-bg.png
deleted file mode 100644
index f711bc02..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/tabs-bg.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.gif
deleted file mode 100644
index 6d3923ef..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.png
deleted file mode 100644
index afe4d7a3..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolbar.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolbar.png
deleted file mode 100644
index 3dde94c0..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/toolbar.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/users.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/users.png
deleted file mode 100644
index 13fec65e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/users.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/warning_type.gif b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/warning_type.gif
deleted file mode 100644
index fd7b9a05..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/warning_type.gif
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/webphone.ico b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/webphone.ico
deleted file mode 100644
index d58e62ab..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/webphone.ico
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/whiteButton.png b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/whiteButton.png
deleted file mode 100644
index ce8c9cb4..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/images/whiteButton.png
+++ /dev/null
Binary files differ
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/intro.js b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/intro.js
deleted file mode 100644
index af50383e..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/d3/js/intro.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(){
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js
deleted file mode 100644
index 531485ce..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/raptor/uigrid/ui-grid.js
+++ /dev/null
@@ -1,26735 +0,0 @@
-/*!
- * ui-grid - v3.0.7 - 2015-10-06
- * Copyright (c) 2015 ; License: MIT
- */
-
-(function () {
- 'use strict';
- angular.module('ui.grid.i18n', []);
- angular.module('ui.grid', ['ui.grid.i18n']);
-})();
-(function () {
- 'use strict';
- angular.module('ui.grid').constant('uiGridConstants', {
- LOG_DEBUG_MESSAGES: true,
- LOG_WARN_MESSAGES: true,
- LOG_ERROR_MESSAGES: true,
- CUSTOM_FILTERS: /CUSTOM_FILTERS/g,
- COL_FIELD: /COL_FIELD/g,
- MODEL_COL_FIELD: /MODEL_COL_FIELD/g,
- TOOLTIP: /title=\"TOOLTIP\"/g,
- DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,
- TEMPLATE_REGEXP: /<.+>/,
- FUNC_REGEXP: /(\([^)]*\))?$/,
- DOT_REGEXP: /\./g,
- APOS_REGEXP: /'/g,
- BRACKET_REGEXP: /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,
- COL_CLASS_PREFIX: 'ui-grid-col',
- events: {
- GRID_SCROLL: 'uiGridScroll',
- COLUMN_MENU_SHOWN: 'uiGridColMenuShown',
- ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged
- COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'
- },
- // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html
- keymap: {
- TAB: 9,
- STRG: 17,
- CAPSLOCK: 20,
- CTRL: 17,
- CTRLRIGHT: 18,
- CTRLR: 18,
- SHIFT: 16,
- RETURN: 13,
- ENTER: 13,
- BACKSPACE: 8,
- BCKSP: 8,
- ALT: 18,
- ALTR: 17,
- ALTRIGHT: 17,
- SPACE: 32,
- WIN: 91,
- MAC: 91,
- FN: null,
- PG_UP: 33,
- PG_DOWN: 34,
- UP: 38,
- DOWN: 40,
- LEFT: 37,
- RIGHT: 39,
- ESC: 27,
- DEL: 46,
- F1: 112,
- F2: 113,
- F3: 114,
- F4: 115,
- F5: 116,
- F6: 117,
- F7: 118,
- F8: 119,
- F9: 120,
- F10: 121,
- F11: 122,
- F12: 123
- },
- ASC: 'asc',
- DESC: 'desc',
- filter: {
- STARTS_WITH: 2,
- ENDS_WITH: 4,
- EXACT: 8,
- CONTAINS: 16,
- GREATER_THAN: 32,
- GREATER_THAN_OR_EQUAL: 64,
- LESS_THAN: 128,
- LESS_THAN_OR_EQUAL: 256,
- NOT_EQUAL: 512,
- SELECT: 'select',
- INPUT: 'input'
- },
-
- aggregationTypes: {
- sum: 2,
- count: 4,
- avg: 8,
- min: 16,
- max: 32
- },
-
- // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them?
- CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'],
-
- scrollDirection: {
- UP: 'up',
- DOWN: 'down',
- LEFT: 'left',
- RIGHT: 'right',
- NONE: 'none'
-
- },
-
- dataChange: {
- ALL: 'all',
- EDIT: 'edit',
- ROW: 'row',
- COLUMN: 'column',
- OPTIONS: 'options'
- },
- scrollbars: {
- NEVER: 0,
- ALWAYS: 1
- //WHEN_NEEDED: 2
- }
- });
-
-})();
-angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {
- var uiGridCell = {
- priority: 0,
- scope: false,
- require: '?^uiGrid',
- compile: function() {
- return {
- pre: function($scope, $elm, $attrs, uiGridCtrl) {
- function compileTemplate() {
- var compiledElementFn = $scope.col.compiledElementFn;
-
- compiledElementFn($scope, function(clonedElement, scope) {
- $elm.append(clonedElement);
- });
- }
-
- // If the grid controller is present, use it to get the compiled cell template function
- if (uiGridCtrl && $scope.col.compiledElementFn) {
- compileTemplate();
- }
- // No controller, compile the element manually (for unit tests)
- else {
- if ( uiGridCtrl && !$scope.col.compiledElementFn ){
- // gridUtil.logError('Render has been called before precompile. Please log a ui-grid issue');
-
- $scope.col.getCompiledElementFn()
- .then(function (compiledElementFn) {
- compiledElementFn($scope, function(clonedElement, scope) {
- $elm.append(clonedElement);
- });
- });
- }
- else {
- var html = $scope.col.cellTemplate
- .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))
- .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
-
- var cellElement = $compile(html)($scope);
- $elm.append(cellElement);
- }
- }
- },
- post: function($scope, $elm, $attrs, uiGridCtrl) {
- var initColClass = $scope.col.getColClass(false);
- $elm.addClass(initColClass);
-
- var classAdded;
- var updateClass = function( grid ){
- var contents = $elm;
- if ( classAdded ){
- contents.removeClass( classAdded );
- classAdded = null;
- }
-
- if (angular.isFunction($scope.col.cellClass)) {
- classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
- }
- else {
- classAdded = $scope.col.cellClass;
- }
- contents.addClass(classAdded);
- };
-
- if ($scope.col.cellClass) {
- updateClass();
- }
-
- // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
- var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);
-
- // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise
- // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things
- var cellChangeFunction = function( n, o ){
- if ( n !== o ) {
- if ( classAdded || $scope.col.cellClass ){
- updateClass();
- }
-
- // See if the column's internal class has changed
- var newColClass = $scope.col.getColClass(false);
- if (newColClass !== initColClass) {
- $elm.removeClass(initColClass);
- $elm.addClass(newColClass);
- initColClass = newColClass;
- }
- }
- };
-
- // TODO(c0bra): Turn this into a deep array watch
-/* shouldn't be needed any more given track by col.name
- var colWatchDereg = $scope.$watch( 'col', cellChangeFunction );
-*/
- var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );
-
-
- var deregisterFunction = function() {
- dataChangeDereg();
-// colWatchDereg();
- rowWatchDereg();
- };
-
- $scope.$on( '$destroy', deregisterFunction );
- $elm.on( '$destroy', deregisterFunction );
- }
- };
- }
- };
-
- return uiGridCell;
-}]);
-
-
-(function(){
-
-angular.module('ui.grid')
-.service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',
-function ( i18nService, uiGridConstants, gridUtil ) {
-/**
- * @ngdoc service
- * @name ui.grid.service:uiGridColumnMenuService
- *
- * @description Services for working with column menus, factored out
- * to make the code easier to understand
- */
-
- var service = {
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name initialize
- * @description Sets defaults, puts a reference to the $scope on
- * the uiGridController
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- * @param {controller} uiGridCtrl the uiGridController for the grid
- * we're on
- *
- */
- initialize: function( $scope, uiGridCtrl ){
- $scope.grid = uiGridCtrl.grid;
-
- // Store a reference to this link/controller in the main uiGrid controller
- // to allow showMenu later
- uiGridCtrl.columnMenuScope = $scope;
-
- // Save whether we're shown or not so the columns can check
- $scope.menuShown = false;
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name setColMenuItemWatch
- * @description Setup a watch on $scope.col.menuItems, and update
- * menuItems based on this. $scope.col needs to be set by the column
- * before calling the menu.
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- * @param {controller} uiGridCtrl the uiGridController for the grid
- * we're on
- *
- */
- setColMenuItemWatch: function ( $scope ){
- var deregFunction = $scope.$watch('col.menuItems', function (n, o) {
- if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {
- n.forEach(function (item) {
- if (typeof(item.context) === 'undefined' || !item.context) {
- item.context = {};
- }
- item.context.col = $scope.col;
- });
-
- $scope.menuItems = $scope.defaultMenuItems.concat(n);
- }
- else {
- $scope.menuItems = $scope.defaultMenuItems;
- }
- });
-
- $scope.$on( '$destroy', deregFunction );
- },
-
-
- /**
- * @ngdoc boolean
- * @name enableSorting
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) True by default. When enabled, this setting adds sort
- * widgets to the column header, allowing sorting of the data in the individual column.
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name sortable
- * @description determines whether this column is sortable
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- *
- */
- sortable: function( $scope ) {
- if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) {
- return true;
- }
- else {
- return false;
- }
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name isActiveSort
- * @description determines whether the requested sort direction is current active, to
- * allow highlighting in the menu
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- * @param {string} direction the direction that we'd have selected for us to be active
- *
- */
- isActiveSort: function( $scope, direction ){
- return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&
- typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);
-
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name suppressRemoveSort
- * @description determines whether we should suppress the removeSort option
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- *
- */
- suppressRemoveSort: function( $scope ) {
- if ($scope.col && $scope.col.suppressRemoveSort) {
- return true;
- }
- else {
- return false;
- }
- },
-
-
- /**
- * @ngdoc boolean
- * @name enableHiding
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column
- * using the column menu or the grid menu.
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name hideable
- * @description determines whether a column can be hidden, by checking the enableHiding columnDef option
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- *
- */
- hideable: function( $scope ) {
- if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) {
- return false;
- }
- else {
- return true;
- }
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name getDefaultMenuItems
- * @description returns the default menu items for a column menu
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- *
- */
- getDefaultMenuItems: function( $scope ){
- return [
- {
- title: i18nService.getSafeText('sort.ascending'),
- icon: 'ui-grid-icon-sort-alt-up',
- action: function($event) {
- $event.stopPropagation();
- $scope.sortColumn($event, uiGridConstants.ASC);
- },
- shown: function () {
- return service.sortable( $scope );
- },
- active: function() {
- return service.isActiveSort( $scope, uiGridConstants.ASC);
- }
- },
- {
- title: i18nService.getSafeText('sort.descending'),
- icon: 'ui-grid-icon-sort-alt-down',
- action: function($event) {
- $event.stopPropagation();
- $scope.sortColumn($event, uiGridConstants.DESC);
- },
- shown: function() {
- return service.sortable( $scope );
- },
- active: function() {
- return service.isActiveSort( $scope, uiGridConstants.DESC);
- }
- },
- {
- title: i18nService.getSafeText('sort.remove'),
- icon: 'ui-grid-icon-cancel',
- action: function ($event) {
- $event.stopPropagation();
- $scope.unsortColumn();
- },
- shown: function() {
- return service.sortable( $scope ) &&
- typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&
- typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&
- !service.suppressRemoveSort( $scope );
- }
- },
- {
- title: i18nService.getSafeText('column.hide'),
- icon: 'ui-grid-icon-cancel',
- shown: function() {
- return service.hideable( $scope );
- },
- action: function ($event) {
- $event.stopPropagation();
- $scope.hideColumn();
- }
- },
- {
- title: i18nService.getSafeText('columnMenu.close'),
- screenReaderOnly: true,
- shown: function(){
- return true;
- },
- action: function($event){
- $event.stopPropagation();
- }
- }
- ];
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name getColumnElementPosition
- * @description gets the position information needed to place the column
- * menu below the column header
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- * @param {GridCol} column the column we want to position below
- * @param {element} $columnElement the column element we want to position below
- * @returns {hash} containing left, top, offset, height, width
- *
- */
- getColumnElementPosition: function( $scope, column, $columnElement ){
- var positionData = {};
- positionData.left = $columnElement[0].offsetLeft;
- positionData.top = $columnElement[0].offsetTop;
- positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;
-
- // Get the grid scrollLeft
- positionData.offset = 0;
- if (column.grid.options.offsetLeft) {
- positionData.offset = column.grid.options.offsetLeft;
- }
-
- positionData.height = gridUtil.elementHeight($columnElement, true);
- positionData.width = gridUtil.elementWidth($columnElement, true);
-
- return positionData;
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:uiGridColumnMenuService
- * @name repositionMenu
- * @description Reposition the menu below the new column. If the menu has no child nodes
- * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again
- * later to fix it
- * @param {$scope} $scope the $scope from the uiGridColumnMenu
- * @param {GridCol} column the column we want to position below
- * @param {hash} positionData a hash containing left, top, offset, height, width
- * @param {element} $elm the column menu element that we want to reposition
- * @param {element} $columnElement the column element that we want to reposition underneath
- *
- */
- repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {
- var menu = $elm[0].querySelectorAll('.ui-grid-menu');
- var containerId = column.renderContainer ? column.renderContainer : 'body';
- var renderContainer = column.grid.renderContainers[containerId];
-
- // It's possible that the render container of the column we're attaching to is
- // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft
- // between the render container and the grid
- var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container');
- var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left;
-
- var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;
-
- // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170
- var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);
- var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
-
- if ( menu.length !== 0 ){
- var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');
- if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) {
- myWidth = gridUtil.elementWidth(menu, true);
- $scope.lastMenuWidth = myWidth;
- column.lastMenuWidth = myWidth;
-
- // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
- // Get the column menu right padding
- paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
- $scope.lastMenuPaddingRight = paddingRight;
- column.lastMenuPaddingRight = paddingRight;
- }
- }
-
- var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight;
- if (left < positionData.offset){
- left = positionData.offset;
- }
-
- $elm.css('left', left + 'px');
- $elm.css('top', (positionData.top + positionData.height) + 'px');
- }
-
- };
-
- return service;
-}])
-
-
-.directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',
-function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {
-/**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridColumnMenu
- * @description Provides the column menu framework, leverages uiGridMenu underneath
- *
- */
-
- var uiGridColumnMenu = {
- priority: 0,
- scope: true,
- require: '^uiGrid',
- templateUrl: 'ui-grid/uiGridColumnMenu',
- replace: true,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var self = this;
-
- uiGridColumnMenuService.initialize( $scope, uiGridCtrl );
-
- $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );
-
- // Set the menu items for use with the column menu. The user can later add additional items via the watch
- $scope.menuItems = $scope.defaultMenuItems;
- uiGridColumnMenuService.setColMenuItemWatch( $scope );
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.directive:uiGridColumnMenu
- * @name showMenu
- * @description Shows the column menu. If the menu is already displayed it
- * calls the menu to ask it to hide (it will animate), then it repositions the menu
- * to the right place whilst hidden (it will make an assumption on menu width),
- * then it asks the menu to show (it will animate), then it repositions the menu again
- * once we can calculate it's size.
- * @param {GridCol} column the column we want to position below
- * @param {element} $columnElement the column element we want to position below
- */
- $scope.showMenu = function(column, $columnElement, event) {
- // Swap to this column
- $scope.col = column;
-
- // Get the position information for the column element
- var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
-
- if ($scope.menuShown) {
- // we want to hide, then reposition, then show, but we want to wait for animations
- // we set a variable, and then rely on the menu-hidden event to call the reposition and show
- $scope.colElement = $columnElement;
- $scope.colElementPosition = colElementPosition;
- $scope.hideThenShow = true;
-
- $scope.$broadcast('hide-menu', { originalEvent: event });
- } else {
- self.shown = $scope.menuShown = true;
- uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement );
-
- $scope.colElement = $columnElement;
- $scope.colElementPosition = colElementPosition;
- $scope.$broadcast('show-menu', { originalEvent: event });
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.directive:uiGridColumnMenu
- * @name hideMenu
- * @description Hides the column menu.
- * @param {boolean} broadcastTrigger true if we were triggered by a broadcast
- * from the menu itself - in which case don't broadcast again as we'll get
- * an infinite loop
- */
- $scope.hideMenu = function( broadcastTrigger ) {
- $scope.menuShown = false;
- if ( !broadcastTrigger ){
- $scope.$broadcast('hide-menu');
- }
- };
-
-
- $scope.$on('menu-hidden', function() {
- if ( $scope.hideThenShow ){
- delete $scope.hideThenShow;
-
- uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
- $scope.$broadcast('show-menu');
-
- $scope.menuShown = true;
- } else {
- $scope.hideMenu( true );
-
- if ($scope.col) {
- //Focus on the menu button
- gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);
- }
- }
- });
-
- $scope.$on('menu-shown', function() {
- $timeout( function() {
- uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
- delete $scope.colElementPosition;
- delete $scope.columnElement;
- }, 200);
- });
-
-
- /* Column methods */
- $scope.sortColumn = function (event, dir) {
- event.stopPropagation();
-
- $scope.grid.sortColumn($scope.col, dir, true)
- .then(function () {
- $scope.grid.refresh();
- $scope.hideMenu();
- });
- };
-
- $scope.unsortColumn = function () {
- $scope.col.unsort();
-
- $scope.grid.refresh();
- $scope.hideMenu();
- };
-
- //Since we are hiding this column the default hide action will fail so we need to focus somewhere else.
- var setFocusOnHideColumn = function(){
- $timeout(function(){
- // Get the UID of the first
- var focusToGridMenu = function(){
- return gridUtil.focus.byId('grid-menu', $scope.grid);
- };
-
- var thisIndex;
- $scope.grid.columns.some(function(element, index){
- if (angular.equals(element, $scope.col)) {
- thisIndex = index;
- return true;
- }
- });
-
- var previousVisibleCol;
- // Try and find the next lower or nearest column to focus on
- $scope.grid.columns.some(function(element, index){
- if (!element.visible){
- return false;
- } // This columns index is below the current column index
- else if ( index < thisIndex){
- previousVisibleCol = element;
- } // This elements index is above this column index and we haven't found one that is lower
- else if ( index > thisIndex && !previousVisibleCol) {
- // This is the next best thing
- previousVisibleCol = element;
- // We've found one so use it.
- return true;
- } // We've reached an element with an index above this column and the previousVisibleCol variable has been set
- else if (index > thisIndex && previousVisibleCol) {
- // We are done.
- return true;
- }
- });
- // If found then focus on it
- if (previousVisibleCol){
- var colClass = previousVisibleCol.getColClass();
- gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason){
- if (reason !== 'canceled'){ // If this is canceled then don't perform the action
- //The fallback action is to focus on the grid menu
- return focusToGridMenu();
- }
- });
- } else {
- // Fallback action to focus on the grid menu
- focusToGridMenu();
- }
- });
- };
-
- $scope.hideColumn = function () {
- $scope.col.colDef.visible = false;
- $scope.col.visible = false;
-
- $scope.grid.queueGridRefresh();
- $scope.hideMenu();
- $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
- $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );
-
- // We are hiding so the default action of focusing on the button that opened this menu will fail.
- setFocusOnHideColumn();
- };
- },
-
-
-
- controller: ['$scope', function ($scope) {
- var self = this;
-
- $scope.$watch('menuItems', function (n, o) {
- self.menuItems = n;
- });
- }]
- };
-
- return uiGridColumnMenu;
-
-}]);
-
-})();
-
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {
-
- return {
- compile: function() {
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
- $scope.col.updateFilters = function( filterable ){
- $elm.children().remove();
- if ( filterable ){
- var template = $scope.col.filterHeaderTemplate;
-
- $elm.append($compile(template)($scope));
- }
- };
-
- $scope.$on( '$destroy', function() {
- delete $scope.col.updateFilters;
- });
- },
- post: function ($scope, $elm, $attrs, controllers){
- $scope.aria = i18nService.getSafeText('headerCell.aria');
- $scope.removeFilter = function(colFilter, index){
- colFilter.term = null;
- //Set the focus to the filter input after the action disables the button
- gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);
- };
- }
- };
- }
- };
- }]);
-})();
-
-(function () {
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',
- function ($timeout, gridUtil, uiGridConstants, $compile) {
- var uiGridFooterCell = {
- priority: 0,
- scope: {
- col: '=',
- row: '=',
- renderIndex: '='
- },
- replace: true,
- require: '^uiGrid',
- compile: function compile(tElement, tAttrs, transclude) {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- var cellFooter = $compile($scope.col.footerCellTemplate)($scope);
- $elm.append(cellFooter);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- //$elm.addClass($scope.col.getColClass(false));
- $scope.grid = uiGridCtrl.grid;
-
- var initColClass = $scope.col.getColClass(false);
- $elm.addClass(initColClass);
-
- // apply any footerCellClass
- var classAdded;
- var updateClass = function( grid ){
- var contents = $elm;
- if ( classAdded ){
- contents.removeClass( classAdded );
- classAdded = null;
- }
-
- if (angular.isFunction($scope.col.footerCellClass)) {
- classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
- }
- else {
- classAdded = $scope.col.footerCellClass;
- }
- contents.addClass(classAdded);
- };
-
- if ($scope.col.footerCellClass) {
- updateClass();
- }
-
- $scope.col.updateAggregationValue();
-
- // Watch for column changes so we can alter the col cell class properly
-/* shouldn't be needed any more, given track by col.name
- $scope.$watch('col', function (n, o) {
- if (n !== o) {
- // See if the column's internal class has changed
- var newColClass = $scope.col.getColClass(false);
- if (newColClass !== initColClass) {
- $elm.removeClass(initColClass);
- $elm.addClass(newColClass);
- initColClass = newColClass;
- }
- }
- });
-*/
-
-
- // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
- var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);
- // listen for visible rows change and update aggregation values
- $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );
- $scope.grid.api.core.on.rowsRendered( $scope, updateClass );
- $scope.$on( '$destroy', dataChangeDereg );
- }
- };
- }
- };
-
- return uiGridFooterCell;
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
-
- return {
- restrict: 'EA',
- replace: true,
- // priority: 1000,
- require: ['^uiGrid', '^uiGridRenderContainer'],
- scope: true,
- compile: function ($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- $scope.grid = uiGridCtrl.grid;
- $scope.colContainer = containerCtrl.colContainer;
-
- containerCtrl.footer = $elm;
-
- var footerTemplate = $scope.grid.options.footerTemplate;
- gridUtil.getTemplate(footerTemplate)
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
- $elm.append(newElm);
-
- if (containerCtrl) {
- // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
- var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
-
- if (footerViewport) {
- containerCtrl.footerViewport = footerViewport;
- }
- }
- });
- },
-
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- // gridUtil.logDebug('ui-grid-footer link');
-
- var grid = uiGridCtrl.grid;
-
- // Don't animate footer cells
- gridUtil.disableAnimations($elm);
-
- containerCtrl.footer = $elm;
-
- var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
- if (footerViewport) {
- containerCtrl.footerViewport = footerViewport;
- }
- }
- };
- }
- };
- }]);
-
-})();
-(function () {
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
-
- return {
- restrict: 'EA',
- replace: true,
- // priority: 1000,
- require: '^uiGrid',
- scope: true,
- compile: function ($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- $scope.grid = uiGridCtrl.grid;
-
-
-
- var footerTemplate = $scope.grid.options.gridFooterTemplate;
- gridUtil.getTemplate(footerTemplate)
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
- $elm.append(newElm);
- });
- },
-
- post: function ($scope, $elm, $attrs, controllers) {
-
- }
- };
- }
- };
- }]);
-
-})();
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridGroupPanel', ["$compile", "uiGridConstants", "gridUtil", function($compile, uiGridConstants, gridUtil) {
- var defaultTemplate = 'ui-grid/ui-grid-group-panel';
-
- return {
- restrict: 'EA',
- replace: true,
- require: '?^uiGrid',
- scope: false,
- compile: function($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- var groupPanelTemplate = $scope.grid.options.groupPanelTemplate || defaultTemplate;
-
- gridUtil.getTemplate(groupPanelTemplate)
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
- $elm.append(newElm);
- });
- },
-
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- $elm.bind('$destroy', function() {
- // scrollUnbinder();
- });
- }
- };
- }
- };
- }]);
-
-})();
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
- function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
- // Do stuff after mouse has been down this many ms on the header cell
- var mousedownTimeout = 500;
- var changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa
-
- var uiGridHeaderCell = {
- priority: 0,
- scope: {
- col: '=',
- row: '=',
- renderIndex: '='
- },
- require: ['^uiGrid', '^uiGridRenderContainer'],
- replace: true,
- compile: function() {
- return {
- pre: function ($scope, $elm, $attrs) {
- var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
- $elm.append(cellHeader);
- },
-
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var renderContainerCtrl = controllers[1];
-
- $scope.i18n = {
- headerCell: i18nService.getSafeText('headerCell'),
- sort: i18nService.getSafeText('sort')
- };
- $scope.getSortDirectionAriaLabel = function(){
- var col = $scope.col;
- //Trying to recreate this sort of thing but it was getting messy having it in the template.
- //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
- var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
- var label = sortDirectionText;
- //Append the priority if it exists
- if (col.sort.priority) {
- label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + col.sort.priority;
- }
- return label;
- };
-
- $scope.grid = uiGridCtrl.grid;
-
- $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];
-
- var initColClass = $scope.col.getColClass(false);
- $elm.addClass(initColClass);
-
- // Hide the menu by default
- $scope.menuShown = false;
-
- // Put asc and desc sort directions in scope
- $scope.asc = uiGridConstants.ASC;
- $scope.desc = uiGridConstants.DESC;
-
- // Store a reference to menu element
- var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );
-
- var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
-
-
- // apply any headerCellClass
- var classAdded;
- var previousMouseX;
-
- // filter watchers
- var filterDeregisters = [];
-
-
- /*
- * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
- * Once we have a down event, we need to work out whether we have a click, a drag, or a
- * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so
- * we ignore it. A hold would open the menu.
- *
- * So, on down event, we put in place handlers for move and up events, and a timer. If the
- * timer expires before we see a move or up, then we have a long press and hence a column menu open.
- * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
- * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
- * will handle it.
- *
- * To deal with touch enabled devices that also have mice, we only create our handlers when
- * we get the down event, and we create the corresponding handlers - if we're touchstart then
- * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
- *
- * We also suppress the click action whilst this is happening - otherwise after the mouseup there
- * will be a click event and that can cause the column menu to close
- *
- */
-
- $scope.downFn = function( event ){
- event.stopPropagation();
-
- if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
- event = event.originalEvent;
- }
-
- // Don't show the menu if it's not the left button
- if (event.button && event.button !== 0) {
- return;
- }
- previousMouseX = event.pageX;
-
- $scope.mousedownStartTime = (new Date()).getTime();
- $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);
-
- $scope.mousedownTimeout.then(function () {
- if ( $scope.colMenu ) {
- uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
- }
- });
-
- uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
-
- $scope.offAllEvents();
- if ( event.type === 'touchstart'){
- $document.on('touchend', $scope.upFn);
- $document.on('touchmove', $scope.moveFn);
- } else if ( event.type === 'mousedown' ){
- $document.on('mouseup', $scope.upFn);
- $document.on('mousemove', $scope.moveFn);
- }
- };
-
- $scope.upFn = function( event ){
- event.stopPropagation();
- $timeout.cancel($scope.mousedownTimeout);
- $scope.offAllEvents();
- $scope.onDownEvents(event.type);
-
- var mousedownEndTime = (new Date()).getTime();
- var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;
-
- if (mousedownTime > mousedownTimeout) {
- // long click, handled above with mousedown
- }
- else {
- // short click
- if ( $scope.sortable ){
- $scope.handleClick(event);
- }
- }
- };
-
- $scope.moveFn = function( event ){
- // Chrome is known to fire some bogus move events.
- var changeValue = event.pageX - previousMouseX;
- if ( changeValue === 0 ){ return; }
-
- // we're a move, so do nothing and leave for column move (if enabled) to take over
- $timeout.cancel($scope.mousedownTimeout);
- $scope.offAllEvents();
- $scope.onDownEvents(event.type);
- };
-
- $scope.clickFn = function ( event ){
- event.stopPropagation();
- $contentsElm.off('click', $scope.clickFn);
- };
-
-
- $scope.offAllEvents = function(){
- $contentsElm.off('touchstart', $scope.downFn);
- $contentsElm.off('mousedown', $scope.downFn);
-
- $document.off('touchend', $scope.upFn);
- $document.off('mouseup', $scope.upFn);
-
- $document.off('touchmove', $scope.moveFn);
- $document.off('mousemove', $scope.moveFn);
-
- $contentsElm.off('click', $scope.clickFn);
- };
-
- $scope.onDownEvents = function( type ){
- // If there is a previous event, then wait a while before
- // activating the other mode - i.e. if the last event was a touch event then
- // don't enable mouse events for a wee while (500ms or so)
- // Avoids problems with devices that emulate mouse events when you have touch events
-
- switch (type){
- case 'touchmove':
- case 'touchend':
- $contentsElm.on('click', $scope.clickFn);
- $contentsElm.on('touchstart', $scope.downFn);
- $timeout(function(){
- $contentsElm.on('mousedown', $scope.downFn);
- }, changeModeTimeout);
- break;
- case 'mousemove':
- case 'mouseup':
- $contentsElm.on('click', $scope.clickFn);
- $contentsElm.on('mousedown', $scope.downFn);
- $timeout(function(){
- $contentsElm.on('touchstart', $scope.downFn);
- }, changeModeTimeout);
- break;
- default:
- $contentsElm.on('click', $scope.clickFn);
- $contentsElm.on('touchstart', $scope.downFn);
- $contentsElm.on('mousedown', $scope.downFn);
- }
- };
-
-
- var updateHeaderOptions = function( grid ){
- var contents = $elm;
- if ( classAdded ){
- contents.removeClass( classAdded );
- classAdded = null;
- }
-
- if (angular.isFunction($scope.col.headerCellClass)) {
- classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
- }
- else {
- classAdded = $scope.col.headerCellClass;
- }
- contents.addClass(classAdded);
-
- var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
- $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
-
- // Figure out whether this column is sortable or not
- if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) {
- $scope.sortable = true;
- }
- else {
- $scope.sortable = false;
- }
-
- // Figure out whether this column is filterable or not
- var oldFilterable = $scope.filterable;
- if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
- $scope.filterable = true;
- }
- else {
- $scope.filterable = false;
- }
-
- if ( oldFilterable !== $scope.filterable){
- if ( typeof($scope.col.updateFilters) !== 'undefined' ){
- $scope.col.updateFilters($scope.filterable);
- }
-
- // if column is filterable add a filter watcher
- if ($scope.filterable) {
- $scope.col.filters.forEach( function(filter, i) {
- filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
- if (n !== o) {
- uiGridCtrl.grid.api.core.raise.filterChanged();
- uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
- uiGridCtrl.grid.queueGridRefresh();
- }
- }));
- });
- $scope.$on('$destroy', function() {
- filterDeregisters.forEach( function(filterDeregister) {
- filterDeregister();
- });
- });
- } else {
- filterDeregisters.forEach( function(filterDeregister) {
- filterDeregister();
- });
- }
-
- }
-
- // figure out whether we support column menus
- if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
- $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
- $scope.colMenu = true;
- } else {
- $scope.colMenu = false;
- }
-
- /**
- * @ngdoc property
- * @name enableColumnMenu
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description if column menus are enabled, controls the column menus for this specific
- * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
- * using this option. If gridOptions.enableColumnMenus === false then you get no column
- * menus irrespective of the value of this option ). Defaults to true.
- *
- */
- /**
- * @ngdoc property
- * @name enableColumnMenus
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Override for column menus everywhere - if set to false then you get no
- * column menus. Defaults to true.
- *
- */
-
- $scope.offAllEvents();
-
- if ($scope.sortable || $scope.colMenu) {
- $scope.onDownEvents();
-
- $scope.$on('$destroy', function () {
- $scope.offAllEvents();
- });
- }
- };
-
-/*
- $scope.$watch('col', function (n, o) {
- if (n !== o) {
- // See if the column's internal class has changed
- var newColClass = $scope.col.getColClass(false);
- if (newColClass !== initColClass) {
- $elm.removeClass(initColClass);
- $elm.addClass(newColClass);
- initColClass = newColClass;
- }
- }
- });
-*/
- updateHeaderOptions();
-
- // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
- var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);
-
- $scope.$on( '$destroy', dataChangeDereg );
-
- $scope.handleClick = function(event) {
- // If the shift key is being held down, add this column to the sort
- var add = false;
- if (event.shiftKey) {
- add = true;
- }
-
- // Sort this column then rebuild the grid's rows
- uiGridCtrl.grid.sortColumn($scope.col, add)
- .then(function () {
- if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
- uiGridCtrl.grid.refresh();
- });
- };
-
-
- $scope.toggleMenu = function(event) {
- event.stopPropagation();
-
- // If the menu is already showing...
- if (uiGridCtrl.columnMenuScope.menuShown) {
- // ... and we're the column the menu is on...
- if (uiGridCtrl.columnMenuScope.col === $scope.col) {
- // ... hide it
- uiGridCtrl.columnMenuScope.hideMenu();
- }
- // ... and we're NOT the column the menu is on
- else {
- // ... move the menu to our column
- uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
- }
- }
- // If the menu is NOT showing
- else {
- // ... show it on our column
- uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
- }
- };
- }
- };
- }
- };
-
- return uiGridHeaderCell;
- }]);
-
-})();
-
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',
- function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {
- var defaultTemplate = 'ui-grid/ui-grid-header';
- var emptyTemplate = 'ui-grid/ui-grid-no-header';
-
- return {
- restrict: 'EA',
- // templateUrl: 'ui-grid/ui-grid-header',
- replace: true,
- // priority: 1000,
- require: ['^uiGrid', '^uiGridRenderContainer'],
- scope: true,
- compile: function($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- $scope.grid = uiGridCtrl.grid;
- $scope.colContainer = containerCtrl.colContainer;
-
- updateHeaderReferences();
-
- var headerTemplate;
- if (!$scope.grid.options.showHeader) {
- headerTemplate = emptyTemplate;
- }
- else {
- headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
- }
-
- gridUtil.getTemplate(headerTemplate)
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
- $elm.replaceWith(newElm);
-
- // And update $elm to be the new element
- $elm = newElm;
-
- updateHeaderReferences();
-
- if (containerCtrl) {
- // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
- var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
-
-
- if (headerViewport) {
- containerCtrl.headerViewport = headerViewport;
- angular.element(headerViewport).on('scroll', scrollHandler);
- $scope.$on('$destroy', function () {
- angular.element(headerViewport).off('scroll', scrollHandler);
- });
- }
- }
-
- $scope.grid.queueRefresh();
- });
-
- function updateHeaderReferences() {
- containerCtrl.header = containerCtrl.colContainer.header = $elm;
-
- var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');
-
- if (headerCanvases.length > 0) {
- containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
- }
- else {
- containerCtrl.headerCanvas = null;
- }
- }
-
- function scrollHandler(evt) {
- if (uiGridCtrl.grid.isScrollingHorizontally) {
- return;
- }
- var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);
- var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);
-
- var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);
- scrollEvent.newScrollLeft = newScrollLeft;
- if ( horizScrollPercentage > -1 ){
- scrollEvent.x = { percentage: horizScrollPercentage };
- }
-
- uiGridCtrl.grid.scrollContainers(null, scrollEvent);
- }
- },
-
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- // gridUtil.logDebug('ui-grid-header link');
-
- var grid = uiGridCtrl.grid;
-
- // Don't animate header cells
- gridUtil.disableAnimations($elm);
-
- function updateColumnWidths() {
- // this styleBuilder always runs after the renderContainer, so we can rely on the column widths
- // already being populated correctly
-
- var columnCache = containerCtrl.colContainer.visibleColumnCache;
-
- // Build the CSS
- // uiGridCtrl.grid.columns.forEach(function (column) {
- var ret = '';
- var canvasWidth = 0;
- columnCache.forEach(function (column) {
- ret = ret + column.getColClassDefinition();
- canvasWidth += column.drawnWidth;
- });
-
- containerCtrl.colContainer.canvasWidth = canvasWidth;
-
- // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
- return ret;
- }
-
- containerCtrl.header = $elm;
-
- var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
- if (headerViewport) {
- containerCtrl.headerViewport = headerViewport;
- }
-
- //todo: remove this if by injecting gridCtrl into unit tests
- if (uiGridCtrl) {
- uiGridCtrl.grid.registerStyleComputation({
- priority: 15,
- func: updateColumnWidths
- });
- }
- }
- };
- }
- };
- }]);
-
-})();
-
-(function(){
-
-angular.module('ui.grid')
-.service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {
- /**
- * @ngdoc service
- * @name ui.grid.gridMenuService
- *
- * @description Methods for working with the grid menu
- */
-
- var service = {
- /**
- * @ngdoc method
- * @methodOf ui.grid.gridMenuService
- * @name initialize
- * @description Sets up the gridMenu. Most importantly, sets our
- * scope onto the grid object as grid.gridMenuScope, allowing us
- * to operate when passed only the grid. Second most importantly,
- * we register the 'addToGridMenu' and 'removeFromGridMenu' methods
- * on the core api.
- * @param {$scope} $scope the scope of this gridMenu
- * @param {Grid} grid the grid to which this gridMenu is associated
- */
- initialize: function( $scope, grid ){
- grid.gridMenuScope = $scope;
- $scope.grid = grid;
- $scope.registeredMenuItems = [];
-
- // not certain this is needed, but would be bad to create a memory leak
- $scope.$on('$destroy', function() {
- if ( $scope.grid && $scope.grid.gridMenuScope ){
- $scope.grid.gridMenuScope = null;
- }
- if ( $scope.grid ){
- $scope.grid = null;
- }
- if ( $scope.registeredMenuItems ){
- $scope.registeredMenuItems = null;
- }
- });
-
- $scope.registeredMenuItems = [];
-
- /**
- * @ngdoc function
- * @name addToGridMenu
- * @methodOf ui.grid.core.api:PublicApi
- * @description add items to the grid menu. Used by features
- * to add their menu items if they are enabled, can also be used by
- * end users to add menu items. This method has the advantage of allowing
- * remove again, which can simplify management of which items are included
- * in the menu when. (Noting that in most cases the shown and active functions
- * provide a better way to handle visibility of menu items)
- * @param {Grid} grid the grid on which we are acting
- * @param {array} items menu items in the format as described in the tutorial, with
- * the added note that if you want to use remove you must also specify an `id` field,
- * which is provided when you want to remove an item. The id should be unique.
- *
- */
- grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );
-
- /**
- * @ngdoc function
- * @name removeFromGridMenu
- * @methodOf ui.grid.core.api:PublicApi
- * @description Remove an item from the grid menu based on a provided id. Assumes
- * that the id is unique, removes only the last instance of that id. Does nothing if
- * the specified id is not found
- * @param {Grid} grid the grid on which we are acting
- * @param {string} id the id we'd like to remove from the menu
- *
- */
- grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );
- },
-
-
- /**
- * @ngdoc function
- * @name addToGridMenu
- * @propertyOf ui.grid.gridMenuService
- * @description add items to the grid menu. Used by features
- * to add their menu items if they are enabled, can also be used by
- * end users to add menu items. This method has the advantage of allowing
- * remove again, which can simplify management of which items are included
- * in the menu when. (Noting that in most cases the shown and active functions
- * provide a better way to handle visibility of menu items)
- * @param {Grid} grid the grid on which we are acting
- * @param {array} items menu items in the format as described in the tutorial, with
- * the added note that if you want to use remove you must also specify an `id` field,
- * which is provided when you want to remove an item. The id should be unique.
- *
- */
- addToGridMenu: function( grid, menuItems ) {
- if ( !angular.isArray( menuItems ) ) {
- gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');
- } else {
- if ( grid.gridMenuScope ){
- grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];
- grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );
- } else {
- gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid');
- }
- }
- },
-
-
- /**
- * @ngdoc function
- * @name removeFromGridMenu
- * @methodOf ui.grid.gridMenuService
- * @description Remove an item from the grid menu based on a provided id. Assumes
- * that the id is unique, removes only the last instance of that id. Does nothing if
- * the specified id is not found. If there is no gridMenuScope or registeredMenuItems
- * then do nothing silently - the desired result is those menu items not be present and they
- * aren't.
- * @param {Grid} grid the grid on which we are acting
- * @param {string} id the id we'd like to remove from the menu
- *
- */
- removeFromGridMenu: function( grid, id ){
- var foundIndex = -1;
-
- if ( grid && grid.gridMenuScope ){
- grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {
- if ( value.id === id ){
- if (foundIndex > -1) {
- gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );
- } else {
-
- foundIndex = index;
- }
- }
- });
- }
-
- if ( foundIndex > -1 ){
- grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );
- }
- },
-
-
- /**
- * @ngdoc array
- * @name gridMenuCustomItems
- * @propertyOf ui.grid.class:GridOptions
- * @description (optional) An array of menu items that should be added to
- * the gridMenu. Follow the format documented in the tutorial for column
- * menu customisation. The context provided to the action function will
- * include context.grid. An alternative if working with dynamic menus is to use the
- * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles
- * some of the management of items for you.
- *
- */
- /**
- * @ngdoc boolean
- * @name gridMenuShowHideColumns
- * @propertyOf ui.grid.class:GridOptions
- * @description true by default, whether the grid menu should allow hide/show
- * of columns
- *
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.gridMenuService
- * @name getMenuItems
- * @description Decides the menu items to show in the menu. This is a
- * combination of:
- *
- * - the default menu items that are always included,
- * - any menu items that have been provided through the addMenuItem api. These
- * are typically added by features within the grid
- * - any menu items included in grid.options.gridMenuCustomItems. These can be
- * changed dynamically, as they're always recalculated whenever we show the
- * menu
- * @param {$scope} $scope the scope of this gridMenu, from which we can find all
- * the information that we need
- * @returns {array} an array of menu items that can be shown
- */
- getMenuItems: function( $scope ) {
- var menuItems = [
- // this is where we add any menu items we want to always include
- ];
-
- if ( $scope.grid.options.gridMenuCustomItems ){
- if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ){
- gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');
- } else {
- menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );
- }
- }
-
- var clearFilters = [{
- title: i18nService.getSafeText('gridMenu.clearAllFilters'),
- action: function ($event) {
- $scope.grid.clearAllFilters(undefined, true, undefined);
- },
- shown: function() {
- return $scope.grid.options.enableFiltering;
- },
- order: 100
- }];
- menuItems = menuItems.concat( clearFilters );
-
- menuItems = menuItems.concat( $scope.registeredMenuItems );
-
- if ( $scope.grid.options.gridMenuShowHideColumns !== false ){
- menuItems = menuItems.concat( service.showHideColumns( $scope ) );
- }
-
- menuItems.sort(function(a, b){
- return a.order - b.order;
- });
-
- return menuItems;
- },
-
-
- /**
- * @ngdoc array
- * @name gridMenuTitleFilter
- * @propertyOf ui.grid.class:GridOptions
- * @description (optional) A function that takes a title string
- * (usually the col.displayName), and converts it into a display value. The function
- * must return either a string or a promise.
- *
- * Used for internationalization of the grid menu column names - for angular-translate
- * you can pass $translate as the function, for i18nService you can pass getSafeText as the
- * function
- * @example
- * <pre>
- * gridOptions = {
- * gridMenuTitleFilter: $translate
- * }
- * </pre>
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.gridMenuService
- * @name showHideColumns
- * @description Adds two menu items for each of the columns in columnDefs. One
- * menu item for hide, one menu item for show. Each is visible when appropriate
- * (show when column is not visible, hide when column is visible). Each toggles
- * the visible property on the columnDef using toggleColumnVisibility
- * @param {$scope} $scope of a gridMenu, which contains a reference to the grid
- */
- showHideColumns: function( $scope ){
- var showHideColumns = [];
- if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {
- return showHideColumns;
- }
-
- // add header for columns
- showHideColumns.push({
- title: i18nService.getSafeText('gridMenu.columns'),
- order: 300
- });
-
- $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };
-
- $scope.grid.options.columnDefs.forEach( function( colDef, index ){
- if ( colDef.enableHiding !== false ){
- // add hide menu item - shows an OK icon as we only show when column is already visible
- var menuItem = {
- icon: 'ui-grid-icon-ok',
- action: function($event) {
- $event.stopPropagation();
- service.toggleColumnVisibility( this.context.gridCol );
- },
- shown: function() {
- return this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined;
- },
- context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
- leaveOpen: true,
- order: 301 + index * 2
- };
- service.setMenuItemTitle( menuItem, colDef, $scope.grid );
- showHideColumns.push( menuItem );
-
- // add show menu item - shows no icon as we only show when column is invisible
- menuItem = {
- icon: 'ui-grid-icon-cancel',
- action: function($event) {
- $event.stopPropagation();
- service.toggleColumnVisibility( this.context.gridCol );
- },
- shown: function() {
- return !(this.context.gridCol.colDef.visible === true || this.context.gridCol.colDef.visible === undefined);
- },
- context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
- leaveOpen: true,
- order: 301 + index * 2 + 1
- };
- service.setMenuItemTitle( menuItem, colDef, $scope.grid );
- showHideColumns.push( menuItem );
- }
- });
- return showHideColumns;
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.gridMenuService
- * @name setMenuItemTitle
- * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu
- * item if it returns a string, otherwise waiting for the promise to resolve or reject then
- * putting the result into the title
- * @param {object} menuItem the menuItem we want to put the title on
- * @param {object} colDef the colDef from which we can get displayName, name or field
- * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter
- *
- */
- setMenuItemTitle: function( menuItem, colDef, grid ){
- var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );
-
- if ( typeof(title) === 'string' ){
- menuItem.title = title;
- } else if ( title.then ){
- // must be a promise
- menuItem.title = "";
- title.then( function( successValue ) {
- menuItem.title = successValue;
- }, function( errorValue ) {
- menuItem.title = errorValue;
- });
- } else {
- gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');
- menuItem.title = 'badconfig';
- }
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.gridMenuService
- * @name toggleColumnVisibility
- * @description Toggles the visibility of an individual column. Expects to be
- * provided a context that has on it a gridColumn, which is the column that
- * we'll operate upon. We change the visibility, and refresh the grid as appropriate
- * @param {GridCol} gridCol the column that we want to toggle
- *
- */
- toggleColumnVisibility: function( gridCol ) {
- gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );
-
- gridCol.grid.refresh();
- gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
- gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );
- }
- };
-
- return service;
-}])
-
-
-
-.directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',
-function (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {
-
- return {
- priority: 0,
- scope: true,
- require: ['^uiGrid'],
- templateUrl: 'ui-grid/ui-grid-menu-button',
- replace: true,
-
- link: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
-
- // For the aria label
- $scope.i18n = {
- aria: i18nService.getSafeText('gridMenu.aria')
- };
-
- uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
-
- $scope.shown = false;
-
- $scope.toggleMenu = function () {
- if ( $scope.shown ){
- $scope.$broadcast('hide-menu');
- $scope.shown = false;
- } else {
- $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
- $scope.$broadcast('show-menu');
- $scope.shown = true;
- }
- };
-
- $scope.$on('menu-hidden', function() {
- $scope.shown = false;
- gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
- });
- }
- };
-
-}]);
-
-})();
-
-(function(){
-
-/**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridMenu
- * @element style
- * @restrict A
- *
- * @description
- * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
- *
- * @example
- <doc:example module="app">
- <doc:source>
- <script>
- var app = angular.module('app', ['ui.grid']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
-
- }]);
- </script>
-
- <div ng-controller="MainCtrl">
- <div ui-grid-menu shown="true" ></div>
- </div>
- </doc:source>
- <doc:scenario>
- </doc:scenario>
- </doc:example>
- */
-angular.module('ui.grid')
-
-.directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',
-function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {
- var uiGridMenu = {
- priority: 0,
- scope: {
- // shown: '&',
- menuItems: '=',
- autoHide: '=?'
- },
- require: '?^uiGrid',
- templateUrl: 'ui-grid/uiGridMenu',
- replace: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var self = this;
- var menuMid;
- var $animate;
-
- $scope.i18n = {
- close: i18nService.getSafeText('columnMenu.close')
- };
-
- // *** Show/Hide functions ******
- self.showMenu = $scope.showMenu = function(event, args) {
- if ( !$scope.shown ){
-
- /*
- * In order to animate cleanly we remove the ng-if, wait a digest cycle, then
- * animate the removal of the ng-hide. We can't successfully (so far as I can tell)
- * animate removal of the ng-if, as the menu items aren't there yet. And we don't want
- * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated
- * on scroll events.
- *
- * Note when testing animation that animations don't run on the tutorials. When debugging it looks
- * like they do, but angular has a default $animate provider that is just a stub, and that's what's
- * being called. ALso don't be fooled by the fact that your browser has actually loaded the
- * angular-translate.js, it's not using it. You need to test animations in an external application.
- */
- $scope.shown = true;
-
- $timeout( function() {
- $scope.shownMid = true;
- $scope.$emit('menu-shown');
- });
- } else if ( !$scope.shownMid ) {
- // we're probably doing a hide then show, so we don't need to wait for ng-if
- $scope.shownMid = true;
- $scope.$emit('menu-shown');
- }
-
- var docEventType = 'click';
- if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {
- docEventType = args.originalEvent.type;
- }
-
- // Turn off an existing document click handler
- angular.element(document).off('click touchstart', applyHideMenu);
-
- // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
- $timeout(function() {
- angular.element(document).on(docEventType, applyHideMenu);
- });
- //automatically set the focus to the first button element in the now open menu.
- gridUtil.focus.bySelector($elm, 'button[type=button]', true);
- };
-
-
- self.hideMenu = $scope.hideMenu = function(event, args) {
- if ( $scope.shown ){
- /*
- * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
- * set the ng-if (shown = false) after the animation runs. In theory we can cascade off the
- * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.
- *
- * The user may have clicked on the menu again whilst
- * we're waiting, so we check that the mid isn't shown before applying the ng-if.
- */
- $scope.shownMid = false;
- $timeout( function() {
- if ( !$scope.shownMid ){
- $scope.shown = false;
- $scope.$emit('menu-hidden');
- }
- }, 200);
- }
-
- angular.element(document).off('click touchstart', applyHideMenu);
- };
-
- $scope.$on('hide-menu', function (event, args) {
- $scope.hideMenu(event, args);
- });
-
- $scope.$on('show-menu', function (event, args) {
- $scope.showMenu(event, args);
- });
-
-
- // *** Auto hide when click elsewhere ******
- var applyHideMenu = function(){
- if ($scope.shown) {
- $scope.$apply(function () {
- $scope.hideMenu();
- });
- }
- };
-
- if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
- $scope.autoHide = true;
- }
-
- if ($scope.autoHide) {
- angular.element($window).on('resize', applyHideMenu);
- }
-
- $scope.$on('$destroy', function () {
- angular.element(document).off('click touchstart', applyHideMenu);
- });
-
-
- $scope.$on('$destroy', function() {
- angular.element($window).off('resize', applyHideMenu);
- });
-
- if (uiGridCtrl) {
- $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));
- }
-
- $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));
- },
-
-
- controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
- var self = this;
- }]
- };
-
- return uiGridMenu;
-}])
-
-.directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {
- var uiGridMenuItem = {
- priority: 0,
- scope: {
- name: '=',
- active: '=',
- action: '=',
- icon: '=',
- shown: '=',
- context: '=',
- templateUrl: '=',
- leaveOpen: '=',
- screenReaderOnly: '='
- },
- require: ['?^uiGrid', '^uiGridMenu'],
- templateUrl: 'ui-grid/uiGridMenuItem',
- replace: false,
- compile: function($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0],
- uiGridMenuCtrl = controllers[1];
-
- if ($scope.templateUrl) {
- gridUtil.getTemplate($scope.templateUrl)
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
- $elm.replaceWith(newElm);
- });
- }
- },
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0],
- uiGridMenuCtrl = controllers[1];
-
- // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
- // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
- // throw new TypeError("$scope.shown is defined but not a function");
- // }
- if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {
- $scope.shown = function() { return true; };
- }
-
- $scope.itemShown = function () {
- var context = {};
- if ($scope.context) {
- context.context = $scope.context;
- }
-
- if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
- context.grid = uiGridCtrl.grid;
- }
-
- return $scope.shown.call(context);
- };
-
- $scope.itemAction = function($event,title) {
- gridUtil.logDebug('itemAction');
- $event.stopPropagation();
-
- if (typeof($scope.action) === 'function') {
- var context = {};
-
- if ($scope.context) {
- context.context = $scope.context;
- }
-
- // Add the grid to the function call context if the uiGrid controller is present
- if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
- context.grid = uiGridCtrl.grid;
- }
-
- $scope.action.call(context, $event, title);
-
- if ( !$scope.leaveOpen ){
- $scope.$emit('hide-menu');
- } else {
- /*
- * XXX: Fix after column refactor
- * Ideally the focus would remain on the item.
- * However, since there are two menu items that have their 'show' property toggled instead. This is a quick fix.
- */
- gridUtil.focus.bySelector(angular.element(gridUtil.closestElm($elm, ".ui-grid-menu-items")), 'button[type=button]', true);
- }
- }
- };
-
- $scope.i18n = i18nService.get();
- }
- };
- }
- };
-
- return uiGridMenuItem;
-}]);
-
-})();
-
-(function(){
- 'use strict';
- /**
- * @ngdoc overview
- * @name ui.grid.directive:uiGridOneBind
- * @summary A group of directives that provide a one time bind to a dom element.
- * @description A group of directives that provide a one time bind to a dom element.
- * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.
- * This is done to reduce the number of watchers on the dom.
- * <br/>
- * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>
- * <pre>
- <div ng-init="imageName = 'myImageDir.jpg'">
- <img ui-grid-one-bind-src="imageName"></img>
- </div>
- </pre>
- * Will become:
- * <pre>
- <div ng-init="imageName = 'myImageDir.jpg'">
- <img ui-grid-one-bind-src="imageName" src="myImageDir.jpg"></img>
- </div>
- </pre>
- </br>
- <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>
- * <pre>
- <div ng-init="text='Add this text'" ui-grid-one-bind-text="text"></div>
- </pre>
- * Will become:
- * <pre>
- <div ng-init="text='Add this text'" ui-grid-one-bind-text="text">Add this text</div>
- </pre>
- </br>
- * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}
- * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.
- *
- */
- //https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js
- var oneBinders = angular.module('ui.grid');
- angular.forEach([
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindSrc
- * @memberof ui.grid.directive:uiGridOneBind
- * @element img
- * @restrict A
- * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the src dom tag.
- *
- */
- {tag: 'Src', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindText
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the text dom tag.
- */
- {tag: 'Text', method: 'text'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindHref
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Href', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindClass
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.
- * this is to prevent the watcher from being removed before the scope is initialized.
- * @param {Array} uiGridOneBindClass An array of classes to bind to this element.
- * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Class', method: 'addClass'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindHtml
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Html', method: 'html'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAlt
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Alt', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindStyle
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Style', method: 'css'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindValue
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Value', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindId
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Id', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindIdGrid
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the id dom tag.
- * <h1>Important Note!</h1>
- * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring
- * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.
- * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.
- * This is done in order to ensure uniqueness of id tags across the grid.
- * This is to prevent two grids in the same document having duplicate id tags.
- */
- {tag: 'Id', directiveName:'IdGrid', method: 'attr', appendGridId: true},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindTitle
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- */
- {tag: 'Title', method: 'attr'},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAriaLabel
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- *<br/>
- * <pre>
- <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text"></div>
- </pre>
- * Will become:
- * <pre>
- <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text" aria-label="Add this text"></div>
- </pre>
- */
- {tag: 'Label', method: 'attr', aria:true},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAriaLabelledby
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- *<br/>
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId"></div>
- </pre>
- * Will become:
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId" aria-labelledby="gridID32"></div>
- </pre>
- */
- {tag: 'Labelledby', method: 'attr', aria:true},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid
- * @element div
- * @restrict A
- * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
- * grid id to each one.
- *<br/>
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId"></div>
- </pre>
- * Will become ([grid.id] will be replaced by the actual grid id):
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId" aria-labelledby-Grid="[grid.id]-gridID32"></div>
- </pre>
- */
- {tag: 'Labelledby', directiveName:'LabelledbyGrid', appendGridId:true, method: 'attr', aria:true},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAriaDescribedby
- * @element ANY
- * @restrict A
- * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- *<br/>
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId"></div>
- </pre>
- * Will become:
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId" aria-describedby="gridID32"></div>
- </pre>
- */
- {tag: 'Describedby', method: 'attr', aria:true},
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid
- * @element ANY
- * @restrict A
- * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
- * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
- * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
- * grid id to each one.
- *<br/>
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId"></div>
- </pre>
- * Will become ([grid.id] will be replaced by the actual grid id):
- * <pre>
- <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId" aria-describedby="[grid.id]-gridID32"></div>
- </pre>
- */
- {tag: 'Describedby', directiveName:'DescribedbyGrid', appendGridId:true, method: 'attr', aria:true}],
- function(v){
-
- var baseDirectiveName = 'uiGridOneBind';
- //If it is an aria tag then append the aria label seperately
- //This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.
- //If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't match up.
- var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);
- oneBinders.directive(directiveName, ['gridUtil', function(gridUtil){
- return {
- restrict: 'A',
- require: ['?uiGrid','?^uiGrid'],
- link: function(scope, iElement, iAttrs, controllers){
- /* Appends the grid id to the beginnig of the value. */
- var appendGridId = function(val){
- var grid; //Get an instance of the grid if its available
- //If its available in the scope then we don't need to try to find it elsewhere
- if (scope.grid) {
- grid = scope.grid;
- }
- //Another possible location to try to find the grid
- else if (scope.col && scope.col.grid){
- grid = scope.col.grid;
- }
- //Last ditch effort: Search through the provided controllers.
- else if (!controllers.some( //Go through the controllers till one has the element we need
- function(controller){
- if (controller && controller.grid) {
- grid = controller.grid;
- return true; //We've found the grid
- }
- })){
- //We tried our best to find it for you
- gridUtil.logError("["+directiveName+"] A valid grid could not be found to bind id. Are you using this directive " +
- "within the correct scope? Trying to generate id: [gridID]-" + val);
- throw new Error("No valid grid could be found");
- }
-
- if (grid){
- var idRegex = new RegExp(grid.id.toString());
- //If the grid id hasn't been appended already in the template declaration
- if (!idRegex.test(val)){
- val = grid.id.toString() + '-' + val;
- }
- }
- return val;
- };
-
- // The watch returns a function to remove itself.
- var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV){
- if (newV){
- //If we are trying to add an id element then we also apply the grid id if it isn't already there
- if (v.appendGridId) {
- var newIdString = null;
- //Append the id to all of the new ids.
- angular.forEach( newV.split(' '), function(s){
- newIdString = (newIdString ? (newIdString + ' ') : '') + appendGridId(s);
- });
- newV = newIdString;
- }
-
- // Append this newValue to the dom element.
- switch (v.method) {
- case 'attr': //The attr method takes two paraams the tag and the value
- if (v.aria) {
- //If it is an aria element then append the aria prefix
- iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);
- } else {
- iElement[v.method](v.tag.toLowerCase(),newV);
- }
- break;
- case 'addClass':
- //Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js
- if (angular.isObject(newV) && !angular.isArray(newV)) {
- var results = [];
- var nonNullFound = false; //We don't want to remove the binding unless the key is actually defined
- angular.forEach(newV, function (value, index) {
- if (value !== null && typeof(value) !== "undefined"){
- nonNullFound = true; //A non null value for a key was found so the object must have been initialized
- if (value) {results.push(index);}
- }
- });
- //A non null value for a key wasn't found so assume that the scope values haven't been fully initialized
- if (!nonNullFound){
- return; // If not initialized then the watcher should not be removed yet.
- }
- newV = results;
- }
-
- if (newV) {
- iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);
- } else {
- return;
- }
- break;
- default:
- iElement[v.method](newV);
- break;
- }
-
- //Removes the watcher on itself after the bind
- rmWatcher();
- }
- // True ensures that equality is determined using angular.equals instead of ===
- }, true); //End rm watchers
- } //End compile function
- }; //End directive return
- } // End directive function
- ]); //End directive
- }); // End angular foreach
-})();
-
-(function () {
- 'use strict';
-
- var module = angular.module('ui.grid');
-
- module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',
- function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {
- return {
- replace: true,
- transclude: true,
- templateUrl: 'ui-grid/uiGridRenderContainer',
- require: ['^uiGrid', 'uiGridRenderContainer'],
- scope: {
- containerId: '=',
- rowContainerName: '=',
- colContainerName: '=',
- bindScrollHorizontal: '=',
- bindScrollVertical: '=',
- enableVerticalScrollbar: '=',
- enableHorizontalScrollbar: '='
- },
- controller: 'uiGridRenderContainer as RenderContainer',
- compile: function () {
- return {
- pre: function prelink($scope, $elm, $attrs, controllers) {
-
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
- var grid = $scope.grid = uiGridCtrl.grid;
-
- // Verify that the render container for this element exists
- if (!$scope.rowContainerName) {
- throw "No row render container name specified";
- }
- if (!$scope.colContainerName) {
- throw "No column render container name specified";
- }
-
- if (!grid.renderContainers[$scope.rowContainerName]) {
- throw "Row render container '" + $scope.rowContainerName + "' is not registered.";
- }
- if (!grid.renderContainers[$scope.colContainerName]) {
- throw "Column render container '" + $scope.colContainerName + "' is not registered.";
- }
-
- var rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];
- var colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];
-
- containerCtrl.containerId = $scope.containerId;
- containerCtrl.rowContainer = rowContainer;
- containerCtrl.colContainer = colContainer;
- },
- post: function postlink($scope, $elm, $attrs, controllers) {
-
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- var grid = uiGridCtrl.grid;
- var rowContainer = containerCtrl.rowContainer;
- var colContainer = containerCtrl.colContainer;
- var scrollTop = null;
- var scrollLeft = null;
-
-
- var renderContainer = grid.renderContainers[$scope.containerId];
-
- // Put the container name on this element as a class
- $elm.addClass('ui-grid-render-container-' + $scope.containerId);
-
- // Scroll the render container viewport when the mousewheel is used
- gridUtil.on.mousewheel($elm, function (event) {
- var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);
- if (event.deltaY !== 0) {
- var scrollYAmount = event.deltaY * -1 * event.deltaFactor;
-
- scrollTop = containerCtrl.viewport[0].scrollTop;
-
- // Get the scroll percentage
- scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();
- var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;
-
- // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length
- // Viewports that have "overflow: hidden" don't let the mousewheel scroll all the way to the bottom without this check
- if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {
- containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;
- }
-
- // Keep scrollPercentage within the range 0-1.
- if (scrollYPercentage < 0) { scrollYPercentage = 0; }
- else if (scrollYPercentage > 1) { scrollYPercentage = 1; }
-
- scrollEvent.y = { percentage: scrollYPercentage, pixels: scrollYAmount };
- }
- if (event.deltaX !== 0) {
- var scrollXAmount = event.deltaX * event.deltaFactor;
-
- // Get the scroll percentage
- scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);
- scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
- var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;
-
- // Keep scrollPercentage within the range 0-1.
- if (scrollXPercentage < 0) { scrollXPercentage = 0; }
- else if (scrollXPercentage > 1) { scrollXPercentage = 1; }
-
- scrollEvent.x = { percentage: scrollXPercentage, pixels: scrollXAmount };
- }
-
- // Let the parent container scroll if the grid is already at the top/bottom
- if ((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||
- (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft)))) {
- //parent controller scrolls
- }
- else {
- event.preventDefault();
- event.stopPropagation();
- scrollEvent.fireThrottledScrollingEvent('', scrollEvent);
- }
-
- });
-
- $elm.bind('$destroy', function() {
- $elm.unbind('keydown');
-
- ['touchstart', 'touchmove', 'touchend','keydown', 'wheel', 'mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function (eventName) {
- $elm.unbind(eventName);
- });
- });
-
- // TODO(c0bra): Handle resizing the inner canvas based on the number of elements
- function update() {
- var ret = '';
-
- var canvasWidth = colContainer.canvasWidth;
- var viewportWidth = colContainer.getViewportWidth();
-
- var canvasHeight = rowContainer.getCanvasHeight();
-
- //add additional height for scrollbar on left and right container
- //if ($scope.containerId !== 'body') {
- // canvasHeight -= grid.scrollbarHeight;
- //}
-
- var viewportHeight = rowContainer.getViewportHeight();
- //shorten the height to make room for a scrollbar placeholder
- if (colContainer.needsHScrollbarPlaceholder()) {
- viewportHeight -= grid.scrollbarHeight;
- }
-
- var headerViewportWidth,
- footerViewportWidth;
- headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();
-
- // Set canvas dimensions
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';
-
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
-
- if (renderContainer.explicitHeaderCanvasHeight) {
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
- }
- else {
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-canvas { height: inherit; }';
- }
-
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';
-
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
- ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';
-
- return ret;
- }
-
- uiGridCtrl.grid.registerStyleComputation({
- priority: 6,
- func: update
- });
- }
- };
- }
- };
-
- }]);
-
- module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function ($scope, gridUtil) {
-
- }]);
-
-})();
-
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridRow', ['gridUtil', function(gridUtil) {
- return {
- replace: true,
- // priority: 2001,
- // templateUrl: 'ui-grid/ui-grid-row',
- require: ['^uiGrid', '^uiGridRenderContainer'],
- scope: {
- row: '=uiGridRow',
- //rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it
- rowRenderIndex: '='
- },
- compile: function() {
- return {
- pre: function($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- var grid = uiGridCtrl.grid;
-
- $scope.grid = uiGridCtrl.grid;
- $scope.colContainer = containerCtrl.colContainer;
-
- // Function for attaching the template to this scope
- var clonedElement, cloneScope;
- function compileTemplate() {
- $scope.row.getRowTemplateFn.then(function (compiledElementFn) {
- // var compiledElementFn = $scope.row.compiledElementFn;
-
- // Create a new scope for the contents of this row, so we can destroy it later if need be
- var newScope = $scope.$new();
-
- compiledElementFn(newScope, function (newElm, scope) {
- // If we already have a cloned element, we need to remove it and destroy its scope
- if (clonedElement) {
- clonedElement.remove();
- cloneScope.$destroy();
- }
-
- // Empty the row and append the new element
- $elm.empty().append(newElm);
-
- // Save the new cloned element and scope
- clonedElement = newElm;
- cloneScope = newScope;
- });
- });
- }
-
- // Initially attach the compiled template to this scope
- compileTemplate();
-
- // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
- $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {
- if (newFunc !== oldFunc) {
- compileTemplate();
- }
- });
- },
- post: function($scope, $elm, $attrs, controllers) {
-
- }
- };
- }
- };
- }]);
-
-})();
-(function(){
-// 'use strict';
-
- /**
- * @ngdoc directive
- * @name ui.grid.directive:uiGridStyle
- * @element style
- * @restrict A
- *
- * @description
- * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
- *
- * @example
- <doc:example module="app">
- <doc:source>
- <script>
- var app = angular.module('app', ['ui.grid']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.myStyle = '.blah { border: 1px solid }';
- }]);
- </script>
-
- <div ng-controller="MainCtrl">
- <style ui-grid-style>{{ myStyle }}</style>
- <span class="blah">I am in a box.</span>
- </div>
- </doc:source>
- <doc:scenario>
- it('should apply the right class to the element', function () {
- element(by.css('.blah')).getCssValue('border-top-width')
- .then(function(c) {
- expect(c).toContain('1px');
- });
- });
- </doc:scenario>
- </doc:example>
- */
-
-
- angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {
- return {
- // restrict: 'A',
- // priority: 1000,
- // require: '?^uiGrid',
- link: function($scope, $elm, $attrs, uiGridCtrl) {
- // gridUtil.logDebug('ui-grid-style link');
- // if (uiGridCtrl === undefined) {
- // gridUtil.logWarn('[ui-grid-style link] uiGridCtrl is undefined!');
- // }
-
- var interpolateFn = $interpolate($elm.text(), true);
-
- if (interpolateFn) {
- $scope.$watch(interpolateFn, function(value) {
- $elm.text(value);
- });
- }
-
- // uiGridCtrl.recalcRowStyles = function() {
- // var offset = (scope.options.offsetTop || 0) - (scope.options.excessRows * scope.options.rowHeight);
- // var rowHeight = scope.options.rowHeight;
-
- // var ret = '';
- // var rowStyleCount = uiGridCtrl.minRowsToRender() + (scope.options.excessRows * 2);
- // for (var i = 1; i <= rowStyleCount; i++) {
- // ret = ret + ' .grid' + scope.gridId + ' .ui-grid-row:nth-child(' + i + ') { top: ' + offset + 'px; }';
- // offset = offset + rowHeight;
- // }
-
- // scope.rowStyles = ret;
- // };
-
- // uiGridCtrl.styleComputions.push(uiGridCtrl.recalcRowStyles);
-
- }
- };
- }]);
-
-})();
-
-(function(){
- 'use strict';
-
- angular.module('ui.grid').directive('uiGridViewport', ['gridUtil','ScrollEvent','uiGridConstants', '$log',
- function(gridUtil, ScrollEvent, uiGridConstants, $log) {
- return {
- replace: true,
- scope: {},
- controllerAs: 'Viewport',
- templateUrl: 'ui-grid/uiGridViewport',
- require: ['^uiGrid', '^uiGridRenderContainer'],
- link: function($scope, $elm, $attrs, controllers) {
- // gridUtil.logDebug('viewport post-link');
-
- var uiGridCtrl = controllers[0];
- var containerCtrl = controllers[1];
-
- $scope.containerCtrl = containerCtrl;
-
- var rowContainer = containerCtrl.rowContainer;
- var colContainer = containerCtrl.colContainer;
-
- var grid = uiGridCtrl.grid;
-
- $scope.grid = uiGridCtrl.grid;
-
- // Put the containers in scope so we can get rows and columns from them
- $scope.rowContainer = containerCtrl.rowContainer;
- $scope.colContainer = containerCtrl.colContainer;
-
- // Register this viewport with its container
- containerCtrl.viewport = $elm;
-
-
- $elm.on('scroll', scrollHandler);
-
- var ignoreScroll = false;
-
- function scrollHandler(evt) {
- //Leaving in this commented code in case it can someday be used
- //It does improve performance, but because the horizontal scroll is normalized,
- // using this code will lead to the column header getting slightly out of line with columns
- //
- //if (ignoreScroll && (grid.isScrollingHorizontally || grid.isScrollingHorizontally)) {
- // //don't ask for scrollTop if we just set it
- // ignoreScroll = false;
- // return;
- //}
- //ignoreScroll = true;
-
- var newScrollTop = $elm[0].scrollTop;
- var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);
-
- var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
- var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);
-
- var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
- scrollEvent.newScrollLeft = newScrollLeft;
- scrollEvent.newScrollTop = newScrollTop;
- if ( horizScrollPercentage > -1 ){
- scrollEvent.x = { percentage: horizScrollPercentage };
- }
-
- if ( vertScrollPercentage > -1 ){
- scrollEvent.y = { percentage: vertScrollPercentage };
- }
-
- grid.scrollContainers($scope.$parent.containerId, scrollEvent);
- }
-
- if ($scope.$parent.bindScrollVertical) {
- grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);
- }
-
- if ($scope.$parent.bindScrollHorizontal) {
- grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);
- grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);
- grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);
- }
-
- function syncVerticalScroll(scrollEvent){
- containerCtrl.prevScrollArgs = scrollEvent;
- var newScrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);
- $elm[0].scrollTop = newScrollTop;
-
- }
-
- function syncHorizontalScroll(scrollEvent){
- containerCtrl.prevScrollArgs = scrollEvent;
- var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
- $elm[0].scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
- }
-
- function syncHorizontalHeader(scrollEvent){
- var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
- if (containerCtrl.headerViewport) {
- containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
- }
- }
-
- function syncHorizontalFooter(scrollEvent){
- var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
- if (containerCtrl.footerViewport) {
- containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
- }
- }
-
-
- },
- controller: ['$scope', function ($scope) {
- this.rowStyle = function (index) {
- var rowContainer = $scope.rowContainer;
- var colContainer = $scope.colContainer;
-
- var styles = {};
-
- if (index === 0 && rowContainer.currentTopRow !== 0) {
- // The row offset-top is just the height of the rows above the current top-most row, which are no longer rendered
- var hiddenRowWidth = (rowContainer.currentTopRow) * rowContainer.grid.options.rowHeight;
-
- // return { 'margin-top': hiddenRowWidth + 'px' };
- styles['margin-top'] = hiddenRowWidth + 'px';
- }
-
- if (colContainer.currentFirstColumn !== 0) {
- if (colContainer.grid.isRTL()) {
- styles['margin-right'] = colContainer.columnOffset + 'px';
- }
- else {
- styles['margin-left'] = colContainer.columnOffset + 'px';
- }
- }
-
- return styles;
- };
- }]
- };
- }
- ]);
-
-})();
-
-(function() {
-
-angular.module('ui.grid')
-.directive('uiGridVisible', function uiGridVisibleAction() {
- return function ($scope, $elm, $attr) {
- $scope.$watch($attr.uiGridVisible, function (visible) {
- // $elm.css('visibility', visible ? 'visible' : 'hidden');
- $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');
- });
- };
-});
-
-})();
-(function () {
- 'use strict';
-
- angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',
- '$templateCache', 'gridClassFactory', '$timeout', '$parse', '$compile',
- function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,
- $templateCache, gridClassFactory, $timeout, $parse, $compile) {
- // gridUtil.logDebug('ui-grid controller');
-
- var self = this;
-
- self.grid = gridClassFactory.createGrid($scope.uiGrid);
-
- //assign $scope.$parent if appScope not already assigned
- self.grid.appScope = self.grid.appScope || $scope.$parent;
-
- $elm.addClass('grid' + self.grid.id);
- self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';
-
-
- // angular.extend(self.grid.options, );
-
- //all properties of grid are available on scope
- $scope.grid = self.grid;
-
- if ($attrs.uiGridColumns) {
- $attrs.$observe('uiGridColumns', function(value) {
- self.grid.options.columnDefs = value;
- self.grid.buildColumns()
- .then(function(){
- self.grid.preCompileCellTemplates();
-
- self.grid.refreshCanvas(true);
- });
- });
- }
-
-
- // if fastWatch is set we watch only the length and the reference, not every individual object
- var deregFunctions = [];
- if (self.grid.options.fastWatch) {
- self.uiGrid = $scope.uiGrid;
- if (angular.isString($scope.uiGrid.data)) {
- deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );
- deregFunctions.push( $scope.$parent.$watch(function() {
- if ( self.grid.appScope[$scope.uiGrid.data] ){
- return self.grid.appScope[$scope.uiGrid.data].length;
- } else {
- return undefined;
- }
- }, dataWatchFunction) );
- } else {
- deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
- deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data.length; }, dataWatchFunction) );
- }
- deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
- deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs.length; }, columnDefsWatchFunction) );
- } else {
- if (angular.isString($scope.uiGrid.data)) {
- deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );
- } else {
- deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
- }
- deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
- }
-
-
- function columnDefsWatchFunction(n, o) {
- if (n && n !== o) {
- self.grid.options.columnDefs = n;
- self.grid.buildColumns({ orderByColumnDefs: true })
- .then(function(){
-
- self.grid.preCompileCellTemplates();
-
- self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);
- });
- }
- }
-
- function dataWatchFunction(newData) {
- // gridUtil.logDebug('dataWatch fired');
- var promises = [];
-
- if ( self.grid.options.fastWatch ){
- if (angular.isString($scope.uiGrid.data)) {
- newData = self.grid.appScope[$scope.uiGrid.data];
- } else {
- newData = $scope.uiGrid.data;
- }
- }
-
- if (newData) {
- // columns length is greater than the number of row header columns, which don't count because they're created automatically
- var hasColumns = self.grid.columns.length > (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0);
-
- if (
- // If we have no columns
- !hasColumns &&
- // ... and we don't have a ui-grid-columns attribute, which would define columns for us
- !$attrs.uiGridColumns &&
- // ... and we have no pre-defined columns
- self.grid.options.columnDefs.length === 0 &&
- // ... but we DO have data
- newData.length > 0
- ) {
- // ... then build the column definitions from the data that we have
- self.grid.buildColumnDefsFromData(newData);
- }
-
- // If we haven't built columns before and either have some columns defined or some data defined
- if (!hasColumns && (self.grid.options.columnDefs.length > 0 || newData.length > 0)) {
- // Build the column set, then pre-compile the column cell templates
- promises.push(self.grid.buildColumns()
- .then(function() {
- self.grid.preCompileCellTemplates();
- }));
- }
-
- $q.all(promises).then(function() {
- self.grid.modifyRows(newData)
- .then(function () {
- // if (self.viewport) {
- self.grid.redrawInPlace(true);
- // }
-
- $scope.$evalAsync(function() {
- self.grid.refreshCanvas(true);
- self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);
- });
- });
- });
- }
- }
-
- var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {
- self.grid.refreshCanvas(true);
- });
-
- $scope.$on('$destroy', function() {
- deregFunctions.forEach( function( deregFn ){ deregFn(); });
- styleWatchDereg();
- });
-
- self.fireEvent = function(eventName, args) {
- // Add the grid to the event arguments if it's not there
- if (typeof(args) === 'undefined' || args === undefined) {
- args = {};
- }
-
- if (typeof(args.grid) === 'undefined' || args.grid === undefined) {
- args.grid = self.grid;
- }
-
- $scope.$broadcast(eventName, args);
- };
-
- self.innerCompile = function innerCompile(elm) {
- $compile(elm)($scope);
- };
-
- }]);
-
-/**
- * @ngdoc directive
- * @name ui.grid.directive:uiGrid
- * @element div
- * @restrict EA
- * @param {Object} uiGrid Options for the grid to use
- *
- * @description Create a very basic grid.
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="{ data: data }"></div>
- </div>
- </file>
- </example>
- */
-angular.module('ui.grid').directive('uiGrid', uiGridDirective);
-
-uiGridDirective.$inject = ['$compile', '$templateCache', '$timeout', '$window', 'gridUtil', 'uiGridConstants'];
-function uiGridDirective($compile, $templateCache, $timeout, $window, gridUtil, uiGridConstants) {
- return {
- templateUrl: 'ui-grid/ui-grid',
- scope: {
- uiGrid: '='
- },
- replace: true,
- transclude: true,
- controller: 'uiGridController',
- compile: function () {
- return {
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- var grid = uiGridCtrl.grid;
- // Initialize scrollbars (TODO: move to controller??)
- uiGridCtrl.scrollbars = [];
- grid.element = $elm;
-
-
- // See if the grid has a rendered width, if not, wait a bit and try again
- var sizeCheckInterval = 100; // ms
- var maxSizeChecks = 20; // 2 seconds total
- var sizeChecks = 0;
-
- // Setup (event listeners) the grid
- setup();
-
- // And initialize it
- init();
-
- // Mark rendering complete so API events can happen
- grid.renderingComplete();
-
- // If the grid doesn't have size currently, wait for a bit to see if it gets size
- checkSize();
-
- /*-- Methods --*/
-
- function checkSize() {
- // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds
- if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {
- setTimeout(checkSize, sizeCheckInterval);
- sizeChecks++;
- }
- else {
- $timeout(init);
- }
- }
-
- // Setup event listeners and watchers
- function setup() {
- // Bind to window resize events
- angular.element($window).on('resize', gridResize);
-
- // Unbind from window resize events when the grid is destroyed
- $elm.on('$destroy', function () {
- angular.element($window).off('resize', gridResize);
- });
-
- // If we add a left container after render, we need to watch and react
- $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {
- if (newValue === oldValue) {
- return;
- }
- grid.refreshCanvas(true);
- });
-
- // If we add a right container after render, we need to watch and react
- $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {
- if (newValue === oldValue) {
- return;
- }
- grid.refreshCanvas(true);
- });
- }
-
- // Initialize the directive
- function init() {
- grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
-
- // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from
- grid.canvasWidth = uiGridCtrl.grid.gridWidth;
-
- grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
-
- // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows
- if (grid.gridHeight < grid.options.rowHeight && grid.options.enableMinHeightCheck) {
- autoAdjustHeight();
- }
-
- // Run initial canvas refresh
- grid.refreshCanvas(true);
- }
-
- // Set the grid's height ourselves in the case that its height would be unusably small
- function autoAdjustHeight() {
- // Figure out the new height
- var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;
- var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;
- var footerHeight = grid.calcFooterHeight();
-
- var scrollbarHeight = 0;
- if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
- scrollbarHeight = gridUtil.getScrollbarWidth();
- }
-
- var maxNumberOfFilters = 0;
- // Calculates the maximum number of filters in the columns
- angular.forEach(grid.options.columnDefs, function(col) {
- if (col.hasOwnProperty('filter')) {
- if (maxNumberOfFilters < 1) {
- maxNumberOfFilters = 1;
- }
- }
- else if (col.hasOwnProperty('filters')) {
- if (maxNumberOfFilters < col.filters.length) {
- maxNumberOfFilters = col.filters.length;
- }
- }
- });
-
- if (grid.options.enableFiltering) {
- var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.every(function(col) {
- return col.enableFiltering === false;
- });
-
- if (!allColumnsHaveFilteringTurnedOff) {
- maxNumberOfFilters++;
- }
- }
-
- var filterHeight = maxNumberOfFilters * headerHeight;
-
- var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;
-
- $elm.css('height', newHeight + 'px');
-
- grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
- }
-
- // Resize the grid on window resize events
- function gridResize($event) {
- grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
- grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
-
- grid.refreshCanvas(true);
- }
- }
- };
- }
- };
-}
-
-})();
-
-(function(){
- 'use strict';
-
- // TODO: rename this file to ui-grid-pinned-container.js
-
- angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {
- return {
- restrict: 'EA',
- replace: true,
- template: '<div class="ui-grid-pinned-container"><div ui-grid-render-container container-id="side" row-container-name="\'body\'" col-container-name="side" bind-scroll-vertical="true" class="{{ side }} ui-grid-render-container-{{ side }}"></div></div>',
- scope: {
- side: '=uiGridPinnedContainer'
- },
- require: '^uiGrid',
- compile: function compile() {
- return {
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');
-
- var grid = uiGridCtrl.grid;
-
- var myWidth = 0;
-
- $elm.addClass('ui-grid-pinned-container-' + $scope.side);
-
- // Monkey-patch the viewport width function
- if ($scope.side === 'left' || $scope.side === 'right') {
- grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;
- }
-
- function monkeyPatchedGetViewportWidth() {
- /*jshint validthis: true */
- var self = this;
-
- var viewportWidth = 0;
- self.visibleColumnCache.forEach(function (column) {
- viewportWidth += column.drawnWidth;
- });
-
- var adjustment = self.getViewportAdjustment();
-
- viewportWidth = viewportWidth + adjustment.width;
-
- return viewportWidth;
- }
-
- function updateContainerWidth() {
- if ($scope.side === 'left' || $scope.side === 'right') {
- var cols = grid.renderContainers[$scope.side].visibleColumnCache;
- var width = 0;
- for (var i = 0; i < cols.length; i++) {
- var col = cols[i];
- width += col.drawnWidth || col.width || 0;
- }
-
- return width;
- }
- }
-
- function updateContainerDimensions() {
- var ret = '';
-
- // Column containers
- if ($scope.side === 'left' || $scope.side === 'right') {
- myWidth = updateContainerWidth();
-
- // gridUtil.logDebug('myWidth', myWidth);
-
- // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it
- $elm.attr('style', null);
-
- // var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;
-
- ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';
- }
-
- return ret;
- }
-
- grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
- myWidth = updateContainerWidth();
-
- // Subtract our own width
- adjustment.width -= myWidth;
- adjustment.side = $scope.side;
-
- return adjustment;
- });
-
- // Register style computation to adjust for columns in `side`'s render container
- grid.registerStyleComputation({
- priority: 15,
- func: updateContainerDimensions
- });
- }
- };
- }
- };
- }]);
-})();
-
-(function(){
-
-angular.module('ui.grid')
-.factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',
- function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {
-
- /**
- * @ngdoc object
- * @name ui.grid.core.api:PublicApi
- * @description Public Api for the core grid features
- *
- */
-
- /**
- * @ngdoc function
- * @name ui.grid.class:Grid
- * @description Grid is the main viewModel. Any properties or methods needed to maintain state are defined in
- * this prototype. One instance of Grid is created per Grid directive instance.
- * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.
- */
- var Grid = function Grid(options) {
- var self = this;
- // Get the id out of the options, then remove it
- if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {
- if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {
- throw new Error("Grid id '" + options.id + '" is invalid. It must follow CSS selector syntax rules.');
- }
- }
- else {
- throw new Error('No ID provided. An ID must be given when creating a grid.');
- }
-
- self.id = options.id;
- delete options.id;
-
- // Get default options
- self.options = GridOptions.initialize( options );
-
- /**
- * @ngdoc object
- * @name appScope
- * @propertyOf ui.grid.class:Grid
- * @description reference to the application scope (the parent scope of the ui-grid element). Assigned in ui-grid controller
- * <br/>
- * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference
- */
- self.appScope = self.options.appScopeProvider;
-
- self.headerHeight = self.options.headerRowHeight;
-
-
- /**
- * @ngdoc object
- * @name footerHeight
- * @propertyOf ui.grid.class:Grid
- * @description returns the total footer height gridFooter + columnFooter
- */
- self.footerHeight = self.calcFooterHeight();
-
-
- /**
- * @ngdoc object
- * @name columnFooterHeight
- * @propertyOf ui.grid.class:Grid
- * @description returns the total column footer height
- */
- self.columnFooterHeight = self.calcColumnFooterHeight();
-
- self.rtl = false;
- self.gridHeight = 0;
- self.gridWidth = 0;
- self.columnBuilders = [];
- self.rowBuilders = [];
- self.rowsProcessors = [];
- self.columnsProcessors = [];
- self.styleComputations = [];
- self.viewportAdjusters = [];
- self.rowHeaderColumns = [];
- self.dataChangeCallbacks = {};
- self.verticalScrollSyncCallBackFns = {};
- self.horizontalScrollSyncCallBackFns = {};
-
- // self.visibleRowCache = [];
-
- // Set of 'render' containers for self grid, which can render sets of rows
- self.renderContainers = {};
-
- // Create a
- self.renderContainers.body = new GridRenderContainer('body', self);
-
- self.cellValueGetterCache = {};
-
- // Cached function to use with custom row templates
- self.getRowTemplateFn = null;
-
-
- //representation of the rows on the grid.
- //these are wrapped references to the actual data rows (options.data)
- self.rows = [];
-
- //represents the columns on the grid
- self.columns = [];
-
- /**
- * @ngdoc boolean
- * @name isScrollingVertically
- * @propertyOf ui.grid.class:Grid
- * @description set to true when Grid is scrolling vertically. Set to false via debounced method
- */
- self.isScrollingVertically = false;
-
- /**
- * @ngdoc boolean
- * @name isScrollingHorizontally
- * @propertyOf ui.grid.class:Grid
- * @description set to true when Grid is scrolling horizontally. Set to false via debounced method
- */
- self.isScrollingHorizontally = false;
-
- /**
- * @ngdoc property
- * @name scrollDirection
- * @propertyOf ui.grid.class:Grid
- * @description set one of the uiGridConstants.scrollDirection values (UP, DOWN, LEFT, RIGHT, NONE), which tells
- * us which direction we are scrolling. Set to NONE via debounced method
- */
- self.scrollDirection = uiGridConstants.scrollDirection.NONE;
-
- //if true, grid will not respond to any scroll events
- self.disableScrolling = false;
-
-
- function vertical (scrollEvent) {
- self.isScrollingVertically = false;
- self.api.core.raise.scrollEnd(scrollEvent);
- self.scrollDirection = uiGridConstants.scrollDirection.NONE;
- }
-
- var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);
- var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);
-
- function horizontal (scrollEvent) {
- self.isScrollingHorizontally = false;
- self.api.core.raise.scrollEnd(scrollEvent);
- self.scrollDirection = uiGridConstants.scrollDirection.NONE;
- }
-
- var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);
- var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);
-
-
- /**
- * @ngdoc function
- * @name flagScrollingVertically
- * @methodOf ui.grid.class:Grid
- * @description sets isScrollingVertically to true and sets it to false in a debounced function
- */
- self.flagScrollingVertically = function(scrollEvent) {
- if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
- self.api.core.raise.scrollBegin(scrollEvent);
- }
- self.isScrollingVertically = true;
- if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
- debouncedVerticalMinDelay(scrollEvent);
- }
- else {
- debouncedVertical(scrollEvent);
- }
- };
-
- /**
- * @ngdoc function
- * @name flagScrollingHorizontally
- * @methodOf ui.grid.class:Grid
- * @description sets isScrollingHorizontally to true and sets it to false in a debounced function
- */
- self.flagScrollingHorizontally = function(scrollEvent) {
- if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
- self.api.core.raise.scrollBegin(scrollEvent);
- }
- self.isScrollingHorizontally = true;
- if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
- debouncedHorizontalMinDelay(scrollEvent);
- }
- else {
- debouncedHorizontal(scrollEvent);
- }
- };
-
- self.scrollbarHeight = 0;
- self.scrollbarWidth = 0;
- if (self.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
- self.scrollbarHeight = gridUtil.getScrollbarWidth();
- }
-
- if (self.options.enableVerticalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
- self.scrollbarWidth = gridUtil.getScrollbarWidth();
- }
-
-
-
- self.api = new GridApi(self);
-
- /**
- * @ngdoc function
- * @name refresh
- * @methodOf ui.grid.core.api:PublicApi
- * @description Refresh the rendered grid on screen.
- * The refresh method re-runs both the columnProcessors and the
- * rowProcessors, as well as calling refreshCanvas to update all
- * the grid sizing. In general you should prefer to use queueGridRefresh
- * instead, which is basically a debounced version of refresh.
- *
- * If you only want to resize the grid, not regenerate all the rows
- * and columns, you should consider directly calling refreshCanvas instead.
- *
- */
- self.api.registerMethod( 'core', 'refresh', this.refresh );
-
- /**
- * @ngdoc function
- * @name queueGridRefresh
- * @methodOf ui.grid.core.api:PublicApi
- * @description Request a refresh of the rendered grid on screen, if multiple
- * calls to queueGridRefresh are made within a digest cycle only one will execute.
- * The refresh method re-runs both the columnProcessors and the
- * rowProcessors, as well as calling refreshCanvas to update all
- * the grid sizing. In general you should prefer to use queueGridRefresh
- * instead, which is basically a debounced version of refresh.
- *
- */
- self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );
-
- /**
- * @ngdoc function
- * @name refreshRows
- * @methodOf ui.grid.core.api:PublicApi
- * @description Runs only the rowProcessors, columns remain as they were.
- * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.
- * @returns {promise} promise that is resolved when render completes?
- *
- */
- self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );
-
- /**
- * @ngdoc function
- * @name queueRefresh
- * @methodOf ui.grid.core.api:PublicApi
- * @description Requests execution of refreshCanvas, if multiple requests are made
- * during a digest cycle only one will run. RefreshCanvas updates the grid sizing.
- * @returns {promise} promise that is resolved when render completes?
- *
- */
- self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );
-
- /**
- * @ngdoc function
- * @name handleWindowResize
- * @methodOf ui.grid.core.api:PublicApi
- * @description Trigger a grid resize, normally this would be picked
- * up by a watch on window size, but in some circumstances it is necessary
- * to call this manually
- * @returns {promise} promise that is resolved when render completes?
- *
- */
- self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );
-
-
- /**
- * @ngdoc function
- * @name addRowHeaderColumn
- * @methodOf ui.grid.core.api:PublicApi
- * @description adds a row header column to the grid
- * @param {object} column def
- *
- */
- self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );
-
- /**
- * @ngdoc function
- * @name scrollToIfNecessary
- * @methodOf ui.grid.core.api:PublicApi
- * @description Scrolls the grid to make a certain row and column combo visible,
- * in the case that it is not completely visible on the screen already.
- * @param {GridRow} gridRow row to make visible
- * @param {GridCol} gridCol column to make visible
- * @returns {promise} a promise that is resolved when scrolling is complete
- *
- */
- self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );
-
- /**
- * @ngdoc function
- * @name scrollTo
- * @methodOf ui.grid.core.api:PublicApi
- * @description Scroll the grid such that the specified
- * row and column is in view
- * @param {object} rowEntity gridOptions.data[] array instance to make visible
- * @param {object} colDef to make visible
- * @returns {promise} a promise that is resolved after any scrolling is finished
- */
- self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);} );
-
- /**
- * @ngdoc function
- * @name registerRowsProcessor
- * @methodOf ui.grid.core.api:PublicApi
- * @description
- * Register a "rows processor" function. When the rows are updated,
- * the grid calls each registered "rows processor", which has a chance
- * to alter the set of rows (sorting, etc) as long as the count is not
- * modified.
- *
- * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
- * is run in the context of the grid (i.e. this for the function will be the grid), and must
- * return the updated rows list, which is passed to the next processor in the chain
- * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
- * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
- *
- * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,
- * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
- */
- self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor );
-
- /**
- * @ngdoc function
- * @name registerColumnsProcessor
- * @methodOf ui.grid.core.api:PublicApi
- * @description
- * Register a "columns processor" function. When the columns are updated,
- * the grid calls each registered "columns processor", which has a chance
- * to alter the set of columns as long as the count is not
- * modified.
- *
- * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which
- * is run in the context of the grid (i.e. this for the function will be the grid), and must
- * return the updated columns list, which is passed to the next processor in the chain
- * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
- * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
- *
- * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
- */
- self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor );
-
-
-
- /**
- * @ngdoc function
- * @name sortHandleNulls
- * @methodOf ui.grid.core.api:PublicApi
- * @description A null handling method that can be used when building custom sort
- * functions
- * @example
- * <pre>
- * mySortFn = function(a, b) {
- * var nulls = $scope.gridApi.core.sortHandleNulls(a, b);
- * if ( nulls !== null ){
- * return nulls;
- * } else {
- * // your code for sorting here
- * };
- * </pre>
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} null if there were no nulls/undefineds, otherwise returns
- * a sort value that should be passed back from the sort function
- *
- */
- self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );
-
-
- /**
- * @ngdoc function
- * @name sortChanged
- * @methodOf ui.grid.core.api:PublicApi
- * @description The sort criteria on one or more columns has
- * changed. Provides as parameters the grid and the output of
- * getColumnSorting, which is an array of gridColumns
- * that have sorting on them, sorted in priority order.
- *
- * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
- * @param {Function} callBack Will be called when the event is emited. The function passes back an array of columns with
- * sorts on them, in priority order.
- *
- * @example
- * <pre>
- * gridApi.core.on.sortChanged( $scope, function(sortColumns){
- * // do something
- * });
- * </pre>
- */
- self.api.registerEvent( 'core', 'sortChanged' );
-
- /**
- * @ngdoc function
- * @name columnVisibilityChanged
- * @methodOf ui.grid.core.api:PublicApi
- * @description The visibility of a column has changed,
- * the column itself is passed out as a parameter of the event.
- *
- * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
- * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.
- *
- * @example
- * <pre>
- * gridApi.core.on.columnVisibilityChanged( $scope, function (column) {
- * // do something
- * } );
- * </pre>
- */
- self.api.registerEvent( 'core', 'columnVisibilityChanged' );
-
- /**
- * @ngdoc method
- * @name notifyDataChange
- * @methodOf ui.grid.core.api:PublicApi
- * @description Notify the grid that a data or config change has occurred,
- * where that change isn't something the grid was otherwise noticing. This
- * might be particularly relevant where you've changed values within the data
- * and you'd like cell classes to be re-evaluated, or changed config within
- * the columnDef and you'd like headerCellClasses to be re-evaluated.
- * @param {string} type one of the
- * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN), which tells
- * us which refreshes to fire.
- *
- */
- self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );
-
- /**
- * @ngdoc method
- * @name clearAllFilters
- * @methodOf ui.grid.core.api:PublicApi
- * @description Clears all filters and optionally refreshes the visible rows.
- * @param {object} refreshRows Defaults to true.
- * @param {object} clearConditions Defaults to false.
- * @param {object} clearFlags Defaults to false.
- * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
- */
- self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);
-
- self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);
- self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);
- self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);
-
- self.registerStyleComputation({
- priority: 10,
- func: self.getFooterStyles
- });
- };
-
- Grid.prototype.calcFooterHeight = function () {
- if (!this.hasFooter()) {
- return 0;
- }
-
- var height = 0;
- if (this.options.showGridFooter) {
- height += this.options.gridFooterHeight;
- }
-
- height += this.calcColumnFooterHeight();
-
- return height;
- };
-
- Grid.prototype.calcColumnFooterHeight = function () {
- var height = 0;
-
- if (this.options.showColumnFooter) {
- height += this.options.columnFooterHeight;
- }
-
- return height;
- };
-
- Grid.prototype.getFooterStyles = function () {
- var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';
- style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';
- return style;
- };
-
- Grid.prototype.hasFooter = function () {
- return this.options.showGridFooter || this.options.showColumnFooter;
- };
-
- /**
- * @ngdoc function
- * @name isRTL
- * @methodOf ui.grid.class:Grid
- * @description Returns true if grid is RightToLeft
- */
- Grid.prototype.isRTL = function () {
- return this.rtl;
- };
-
-
- /**
- * @ngdoc function
- * @name registerColumnBuilder
- * @methodOf ui.grid.class:Grid
- * @description When the build creates columns from column definitions, the columnbuilders will be called to add
- * additional properties to the column.
- * @param {function(colDef, col, gridOptions)} columnBuilder function to be called
- */
- Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {
- this.columnBuilders.push(columnBuilder);
- };
-
- /**
- * @ngdoc function
- * @name buildColumnDefsFromData
- * @methodOf ui.grid.class:Grid
- * @description Populates columnDefs from the provided data
- * @param {function(colDef, col, gridOptions)} rowBuilder function to be called
- */
- Grid.prototype.buildColumnDefsFromData = function (dataRows){
- this.options.columnDefs = gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);
- };
-
- /**
- * @ngdoc function
- * @name registerRowBuilder
- * @methodOf ui.grid.class:Grid
- * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add
- * additional properties to the row.
- * @param {function(row, gridOptions)} rowBuilder function to be called
- */
- Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {
- this.rowBuilders.push(rowBuilder);
- };
-
-
- /**
- * @ngdoc function
- * @name registerDataChangeCallback
- * @methodOf ui.grid.class:Grid
- * @description When a data change occurs, the data change callbacks of the specified type
- * will be called. The rules are:
- *
- * - when the data watch fires, that is considered a ROW change (the data watch only notices
- * added or removed rows)
- * - when the api is called to inform us of a change, the declared type of that change is used
- * - when a cell edit completes, the EDIT callbacks are triggered
- * - when the columnDef watch fires, the COLUMN callbacks are triggered
- * - when the options watch fires, the OPTIONS callbacks are triggered
- *
- * For a given event:
- * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks
- * - ROW calls ROW and ALL callbacks
- * - EDIT calls EDIT and ALL callbacks
- * - COLUMN calls COLUMN and ALL callbacks
- * - OPTIONS calls OPTIONS and ALL callbacks
- *
- * @param {function(grid)} callback function to be called
- * @param {array} types the types of data change you want to be informed of. Values from
- * the uiGridConstants.dataChange values ( ALL, EDIT, ROW, COLUMN, OPTIONS ). Optional and defaults to
- * ALL
- * @returns {function} deregister function - a function that can be called to deregister this callback
- */
- Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {
- var uid = gridUtil.nextUid();
- if ( !types ){
- types = [uiGridConstants.dataChange.ALL];
- }
- if ( !Array.isArray(types)){
- gridUtil.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: " + types );
- }
- this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this:_this };
-
- var self = this;
- var deregisterFunction = function() {
- delete self.dataChangeCallbacks[uid];
- };
- return deregisterFunction;
- };
-
- /**
- * @ngdoc function
- * @name callDataChangeCallbacks
- * @methodOf ui.grid.class:Grid
- * @description Calls the callbacks based on the type of data change that
- * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the
- * event type is matching, or if the type is ALL.
- * @param {number} type the type of event that occurred - one of the
- * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)
- */
- Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {
- angular.forEach( this.dataChangeCallbacks, function( callback, uid ){
- if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||
- callback.types.indexOf( type ) !== -1 ||
- type === uiGridConstants.dataChange.ALL ) {
- if (callback._this) {
- callback.callback.apply(callback._this,this);
- }
- else {
- callback.callback( this );
- }
- }
- }, this);
- };
-
- /**
- * @ngdoc function
- * @name notifyDataChange
- * @methodOf ui.grid.class:Grid
- * @description Notifies us that a data change has occurred, used in the public
- * api for users to tell us when they've changed data or some other event that
- * our watches cannot pick up
- * @param {string} type the type of event that occurred - one of the
- * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN)
- */
- Grid.prototype.notifyDataChange = function notifyDataChange(type) {
- var constants = uiGridConstants.dataChange;
- if ( type === constants.ALL ||
- type === constants.COLUMN ||
- type === constants.EDIT ||
- type === constants.ROW ||
- type === constants.OPTIONS ){
- this.callDataChangeCallbacks( type );
- } else {
- gridUtil.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: " + type);
- }
- };
-
-
- /**
- * @ngdoc function
- * @name columnRefreshCallback
- * @methodOf ui.grid.class:Grid
- * @description refreshes the grid when a column refresh
- * is notified, which triggers handling of the visible flag.
- * This is called on uiGridConstants.dataChange.COLUMN, and is
- * registered as a dataChangeCallback in grid.js
- * @param {string} name column name
- */
- Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){
- grid.buildColumns();
- grid.queueGridRefresh();
- };
-
-
- /**
- * @ngdoc function
- * @name processRowsCallback
- * @methodOf ui.grid.class:Grid
- * @description calls the row processors, specifically
- * intended to reset the sorting when an edit is called,
- * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT
- * @param {string} name column name
- */
- Grid.prototype.processRowsCallback = function processRowsCallback( grid ){
- grid.queueGridRefresh();
- };
-
-
- /**
- * @ngdoc function
- * @name updateFooterHeightCallback
- * @methodOf ui.grid.class:Grid
- * @description recalculates the footer height,
- * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS
- * @param {string} name column name
- */
- Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ){
- grid.footerHeight = grid.calcFooterHeight();
- grid.columnFooterHeight = grid.calcColumnFooterHeight();
- };
-
-
- /**
- * @ngdoc function
- * @name getColumn
- * @methodOf ui.grid.class:Grid
- * @description returns a grid column for the column name
- * @param {string} name column name
- */
- Grid.prototype.getColumn = function getColumn(name) {
- var columns = this.columns.filter(function (column) {
- return column.colDef.name === name;
- });
- return columns.length > 0 ? columns[0] : null;
- };
-
- /**
- * @ngdoc function
- * @name getColDef
- * @methodOf ui.grid.class:Grid
- * @description returns a grid colDef for the column name
- * @param {string} name column.field
- */
- Grid.prototype.getColDef = function getColDef(name) {
- var colDefs = this.options.columnDefs.filter(function (colDef) {
- return colDef.name === name;
- });
- return colDefs.length > 0 ? colDefs[0] : null;
- };
-
- /**
- * @ngdoc function
- * @name assignTypes
- * @methodOf ui.grid.class:Grid
- * @description uses the first row of data to assign colDef.type for any types not defined.
- */
- /**
- * @ngdoc property
- * @name type
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description the type of the column, used in sorting. If not provided then the
- * grid will guess the type. Add this only if the grid guessing is not to your
- * satisfaction. One of:
- * - 'string'
- * - 'boolean'
- * - 'number'
- * - 'date'
- * - 'object'
- * - 'numberStr'
- * Note that if you choose date, your dates should be in a javascript date type
- *
- */
- Grid.prototype.assignTypes = function(){
- var self = this;
- self.options.columnDefs.forEach(function (colDef, index) {
-
- //Assign colDef type if not specified
- if (!colDef.type) {
- var col = new GridColumn(colDef, index, self);
- var firstRow = self.rows.length > 0 ? self.rows[0] : null;
- if (firstRow) {
- colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));
- }
- else {
- colDef.type = 'string';
- }
- }
- });
- };
-
-
- /**
- * @ngdoc function
- * @name isRowHeaderColumn
- * @methodOf ui.grid.class:Grid
- * @description returns true if the column is a row Header
- * @param {object} column column
- */
- Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {
- return this.rowHeaderColumns.indexOf(column) !== -1;
- };
-
- /**
- * @ngdoc function
- * @name addRowHeaderColumn
- * @methodOf ui.grid.class:Grid
- * @description adds a row header column to the grid
- * @param {object} column def
- */
- Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef) {
- var self = this;
- var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
- rowHeaderCol.isRowHeader = true;
- if (self.isRTL()) {
- self.createRightContainer();
- rowHeaderCol.renderContainer = 'right';
- }
- else {
- self.createLeftContainer();
- rowHeaderCol.renderContainer = 'left';
- }
-
- // relies on the default column builder being first in array, as it is instantiated
- // as part of grid creation
- self.columnBuilders[0](colDef,rowHeaderCol,self.options)
- .then(function(){
- rowHeaderCol.enableFiltering = false;
- rowHeaderCol.enableSorting = false;
- rowHeaderCol.enableHiding = false;
- self.rowHeaderColumns.push(rowHeaderCol);
- self.buildColumns()
- .then( function() {
- self.preCompileCellTemplates();
- self.queueGridRefresh();
- });
- });
- };
-
- /**
- * @ngdoc function
- * @name getOnlyDataColumns
- * @methodOf ui.grid.class:Grid
- * @description returns all columns except for rowHeader columns
- */
- Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {
- var self = this;
- var cols = [];
- self.columns.forEach(function (col) {
- if (self.rowHeaderColumns.indexOf(col) === -1) {
- cols.push(col);
- }
- });
- return cols;
- };
-
- /**
- * @ngdoc function
- * @name buildColumns
- * @methodOf ui.grid.class:Grid
- * @description creates GridColumn objects from the columnDefinition. Calls each registered
- * columnBuilder to further process the column
- * @param {object} options An object contains options to use when building columns
- *
- * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.
- *
- * @returns {Promise} a promise to load any needed column resources
- */
- Grid.prototype.buildColumns = function buildColumns(opts) {
- var options = {
- orderByColumnDefs: false
- };
-
- angular.extend(options, opts);
-
- // gridUtil.logDebug('buildColumns');
- var self = this;
- var builderPromises = [];
- var headerOffset = self.rowHeaderColumns.length;
- var i;
-
- // Remove any columns for which a columnDef cannot be found
- // Deliberately don't use forEach, as it doesn't like splice being called in the middle
- // Also don't cache columns.length, as it will change during this operation
- for (i = 0; i < self.columns.length; i++){
- if (!self.getColDef(self.columns[i].name)) {
- self.columns.splice(i, 1);
- i--;
- }
- }
-
- //add row header columns to the grid columns array _after_ columns without columnDefs have been removed
- self.rowHeaderColumns.forEach(function (rowHeaderColumn) {
- self.columns.unshift(rowHeaderColumn);
- });
-
-
- // look at each column def, and update column properties to match. If the column def
- // doesn't have a column, then splice in a new gridCol
- self.options.columnDefs.forEach(function (colDef, index) {
- self.preprocessColDef(colDef);
- var col = self.getColumn(colDef.name);
-
- if (!col) {
- col = new GridColumn(colDef, gridUtil.nextUid(), self);
- self.columns.splice(index + headerOffset, 0, col);
- }
- else {
- // tell updateColumnDef that the column was pre-existing
- col.updateColumnDef(colDef, false);
- }
-
- self.columnBuilders.forEach(function (builder) {
- builderPromises.push(builder.call(self, colDef, col, self.options));
- });
- });
-
- /*** Reorder columns if necessary ***/
- if (!!options.orderByColumnDefs) {
- // Create a shallow copy of the columns as a cache
- var columnCache = self.columns.slice(0);
-
- // We need to allow for the "row headers" when mapping from the column defs array to the columns array
- // If we have a row header in columns[0] and don't account for it we'll overwrite it with the column in columnDefs[0]
-
- // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then
- // columns will be shorter than columnDefs. In this situation we'll avoid an error, but the user will still get an unexpected result
- var len = Math.min(self.options.columnDefs.length, self.columns.length);
- for (i = 0; i < len; i++) {
- // If the column at this index has a different name than the column at the same index in the column defs...
- if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {
- // Replace the one in the cache with the appropriate column
- columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);
- }
- else {
- // Otherwise just copy over the one from the initial columns
- columnCache[i + headerOffset] = self.columns[i + headerOffset];
- }
- }
-
- // Empty out the columns array, non-destructively
- self.columns.length = 0;
-
- // And splice in the updated, ordered columns from the cache
- Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));
- }
-
- return $q.all(builderPromises).then(function(){
- if (self.rows.length > 0){
- self.assignTypes();
- }
- });
- };
-
-/**
- * @ngdoc function
- * @name preCompileCellTemplates
- * @methodOf ui.grid.class:Grid
- * @description precompiles all cell templates
- */
- Grid.prototype.preCompileCellTemplates = function() {
- var self = this;
-
- var preCompileTemplate = function( col ) {
- var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));
- html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
-
- var compiledElementFn = $compile(html);
- col.compiledElementFn = compiledElementFn;
-
- if (col.compiledElementFnDefer) {
- col.compiledElementFnDefer.resolve(col.compiledElementFn);
- }
- };
-
- this.columns.forEach(function (col) {
- if ( col.cellTemplate ){
- preCompileTemplate( col );
- } else if ( col.cellTemplatePromise ){
- col.cellTemplatePromise.then( function() {
- preCompileTemplate( col );
- });
- }
- });
- };
-
- /**
- * @ngdoc function
- * @name getGridQualifiedColField
- * @methodOf ui.grid.class:Grid
- * @description Returns the $parse-able accessor for a column within its $scope
- * @param {GridColumn} col col object
- */
- Grid.prototype.getQualifiedColField = function (col) {
- return 'row.entity.' + gridUtil.preEval(col.field);
- };
-
- /**
- * @ngdoc function
- * @name createLeftContainer
- * @methodOf ui.grid.class:Grid
- * @description creates the left render container if it doesn't already exist
- */
- Grid.prototype.createLeftContainer = function() {
- if (!this.hasLeftContainer()) {
- this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });
- }
- };
-
- /**
- * @ngdoc function
- * @name createRightContainer
- * @methodOf ui.grid.class:Grid
- * @description creates the right render container if it doesn't already exist
- */
- Grid.prototype.createRightContainer = function() {
- if (!this.hasRightContainer()) {
- this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });
- }
- };
-
- /**
- * @ngdoc function
- * @name hasLeftContainer
- * @methodOf ui.grid.class:Grid
- * @description returns true if leftContainer exists
- */
- Grid.prototype.hasLeftContainer = function() {
- return this.renderContainers.left !== undefined;
- };
-
- /**
- * @ngdoc function
- * @name hasRightContainer
- * @methodOf ui.grid.class:Grid
- * @description returns true if rightContainer exists
- */
- Grid.prototype.hasRightContainer = function() {
- return this.renderContainers.right !== undefined;
- };
-
-
- /**
- * undocumented function
- * @name preprocessColDef
- * @methodOf ui.grid.class:Grid
- * @description defaults the name property from field to maintain backwards compatibility with 2.x
- * validates that name or field is present
- */
- Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {
- var self = this;
-
- if (!colDef.field && !colDef.name) {
- throw new Error('colDef.name or colDef.field property is required');
- }
-
- //maintain backwards compatibility with 2.x
- //field was required in 2.x. now name is required
- if (colDef.name === undefined && colDef.field !== undefined) {
- // See if the column name already exists:
- var newName = colDef.field,
- counter = 2;
- while (self.getColumn(newName)) {
- newName = colDef.field + counter.toString();
- counter++;
- }
- colDef.name = newName;
- }
- };
-
- // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters
- Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {
- var self = this;
-
- var t = [];
- for (var i = 0; i < n.length; i++) {
- var nV = nAccessor ? n[i][nAccessor] : n[i];
-
- var found = false;
- for (var j = 0; j < o.length; j++) {
- var oV = oAccessor ? o[j][oAccessor] : o[j];
- if (self.options.rowEquality(nV, oV)) {
- found = true;
- break;
- }
- }
- if (!found) {
- t.push(nV);
- }
- }
-
- return t;
- };
-
- /**
- * @ngdoc function
- * @name getRow
- * @methodOf ui.grid.class:Grid
- * @description returns the GridRow that contains the rowEntity
- * @param {object} rowEntity the gridOptions.data array element instance
- * @param {array} rows [optional] the rows to look in - if not provided then
- * looks in grid.rows
- */
- Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {
- var self = this;
-
- lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;
-
- var rows = lookInRows.filter(function (row) {
- return self.options.rowEquality(row.entity, rowEntity);
- });
- return rows.length > 0 ? rows[0] : null;
- };
-
-
- /**
- * @ngdoc function
- * @name modifyRows
- * @methodOf ui.grid.class:Grid
- * @description creates or removes GridRow objects from the newRawData array. Calls each registered
- * rowBuilder to further process the row
- * @param {array} newRawData Modified set of data
- *
- * This method aims to achieve three things:
- * 1. the resulting rows array is in the same order as the newRawData, we'll call
- * rowsProcessors immediately after to sort the data anyway
- * 2. if we have row hashing available, we try to use the rowHash to find the row
- * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected
- *
- * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates
- * the newRows and newHash
- *
- * ```
- * newRawData.forEach newEntity
- * if (hashing enabled)
- * check oldHash for newEntity
- * else
- * look for old row directly in oldRows
- * if !oldRowFound // must be a new row
- * create newRow
- * append to the newRows and add to newHash
- * run the processors
- * ```
- *
- * Rows are identified using the hashKey if configured. If not configured, then rows
- * are identified using the gridOptions.rowEquality function
- *
- * This method is useful when trying to select rows immediately after loading data without
- * using a $timeout/$interval, e.g.:
- *
- * $scope.gridOptions.data = someData;
- * $scope.gridApi.grid.modifyRows($scope.gridOptions.data);
- * $scope.gridApi.selection.selectRow($scope.gridOptions.data[0]);
- *
- * OR to persist row selection after data update (e.g. rows selected, new data loaded, want
- * originally selected rows to be re-selected))
- */
- Grid.prototype.modifyRows = function modifyRows(newRawData) {
- var self = this;
- var oldRows = self.rows.slice(0);
- var oldRowHash = self.rowHashMap || self.createRowHashMap();
- self.rowHashMap = self.createRowHashMap();
- self.rows.length = 0;
-
- newRawData.forEach( function( newEntity, i ) {
- var newRow;
- if ( self.options.enableRowHashing ){
- // if hashing is enabled, then this row will be in the hash if we already know about it
- newRow = oldRowHash.get( newEntity );
- } else {
- // otherwise, manually search the oldRows to see if we can find this row
- newRow = self.getRow(newEntity, oldRows);
- }
-
- // if we didn't find the row, it must be new, so create it
- if ( !newRow ){
- newRow = self.processRowBuilders(new GridRow(newEntity, i, self));
- }
-
- self.rows.push( newRow );
- self.rowHashMap.put( newEntity, newRow );
- });
-
- self.assignTypes();
-
- var p1 = $q.when(self.processRowsProcessors(self.rows))
- .then(function (renderableRows) {
- return self.setVisibleRows(renderableRows);
- });
-
- var p2 = $q.when(self.processColumnsProcessors(self.columns))
- .then(function (renderableColumns) {
- return self.setVisibleColumns(renderableColumns);
- });
-
- return $q.all([p1, p2]);
- };
-
-
- /**
- * Private Undocumented Method
- * @name addRows
- * @methodOf ui.grid.class:Grid
- * @description adds the newRawData array of rows to the grid and calls all registered
- * rowBuilders. this keyword will reference the grid
- */
- Grid.prototype.addRows = function addRows(newRawData) {
- var self = this;
-
- var existingRowCount = self.rows.length;
- for (var i = 0; i < newRawData.length; i++) {
- var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));
-
- if (self.options.enableRowHashing) {
- var found = self.rowHashMap.get(newRow.entity);
- if (found) {
- found.row = newRow;
- }
- }
-
- self.rows.push(newRow);
- }
- };
-
- /**
- * @ngdoc function
- * @name processRowBuilders
- * @methodOf ui.grid.class:Grid
- * @description processes all RowBuilders for the gridRow
- * @param {GridRow} gridRow reference to gridRow
- * @returns {GridRow} the gridRow with all additional behavior added
- */
- Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {
- var self = this;
-
- self.rowBuilders.forEach(function (builder) {
- builder.call(self, gridRow, self.options);
- });
-
- return gridRow;
- };
-
- /**
- * @ngdoc function
- * @name registerStyleComputation
- * @methodOf ui.grid.class:Grid
- * @description registered a styleComputation function
- *
- * If the function returns a value it will be appended into the grid's `<style>` block
- * @param {function($scope)} styleComputation function
- */
- Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {
- this.styleComputations.push(styleComputationInfo);
- };
-
-
- // NOTE (c0bra): We already have rowBuilders. I think these do exactly the same thing...
- // Grid.prototype.registerRowFilter = function(filter) {
- // // TODO(c0bra): validate filter?
-
- // this.rowFilters.push(filter);
- // };
-
- // Grid.prototype.removeRowFilter = function(filter) {
- // var idx = this.rowFilters.indexOf(filter);
-
- // if (typeof(idx) !== 'undefined' && idx !== undefined) {
- // this.rowFilters.slice(idx, 1);
- // }
- // };
-
- // Grid.prototype.processRowFilters = function(rows) {
- // var self = this;
- // self.rowFilters.forEach(function (filter) {
- // filter.call(self, rows);
- // });
- // };
-
-
- /**
- * @ngdoc function
- * @name registerRowsProcessor
- * @methodOf ui.grid.class:Grid
- * @description
- *
- * Register a "rows processor" function. When the rows are updated,
- * the grid calls each registered "rows processor", which has a chance
- * to alter the set of rows (sorting, etc) as long as the count is not
- * modified.
- *
- * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
- * is run in the context of the grid (i.e. this for the function will be the grid), and must
- * return the updated rows list, which is passed to the next processor in the chain
- * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
- * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
- *
- * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
- *
- */
- Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {
- if (!angular.isFunction(processor)) {
- throw 'Attempt to register non-function rows processor: ' + processor;
- }
-
- this.rowsProcessors.push({processor: processor, priority: priority});
- this.rowsProcessors.sort(function sortByPriority( a, b ){
- return a.priority - b.priority;
- });
- };
-
- /**
- * @ngdoc function
- * @name removeRowsProcessor
- * @methodOf ui.grid.class:Grid
- * @param {function(renderableRows)} rows processor function
- * @description Remove a registered rows processor
- */
- Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {
- var idx = -1;
- this.rowsProcessors.forEach(function(rowsProcessor, index){
- if ( rowsProcessor.processor === processor ){
- idx = index;
- }
- });
-
- if ( idx !== -1 ) {
- this.rowsProcessors.splice(idx, 1);
- }
- };
-
- /**
- * Private Undocumented Method
- * @name processRowsProcessors
- * @methodOf ui.grid.class:Grid
- * @param {Array[GridRow]} The array of "renderable" rows
- * @param {Array[GridColumn]} The array of columns
- * @description Run all the registered rows processors on the array of renderable rows
- */
- Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {
- var self = this;
-
- // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
- var myRenderableRows = renderableRows.slice(0);
-
- // Return myRenderableRows with no processing if we have no rows processors
- if (self.rowsProcessors.length === 0) {
- return $q.when(myRenderableRows);
- }
-
- // Counter for iterating through rows processors
- var i = 0;
-
- // Promise for when we're done with all the processors
- var finished = $q.defer();
-
- // This function will call the processor in self.rowsProcessors at index 'i', and then
- // when done will call the next processor in the list, using the output from the processor
- // at i as the argument for 'renderedRowsToProcess' on the next iteration.
- //
- // If we're at the end of the list of processors, we resolve our 'finished' callback with
- // the result.
- function startProcessor(i, renderedRowsToProcess) {
- // Get the processor at 'i'
- var processor = self.rowsProcessors[i].processor;
-
- // Call the processor, passing in the rows to process and the current columns
- // (note: it's wrapped in $q.when() in case the processor does not return a promise)
- return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )
- .then(function handleProcessedRows(processedRows) {
- // Check for errors
- if (!processedRows) {
- throw "Processor at index " + i + " did not return a set of renderable rows";
- }
-
- if (!angular.isArray(processedRows)) {
- throw "Processor at index " + i + " did not return an array";
- }
-
- // Processor is done, increment the counter
- i++;
-
- // If we're not done with the processors, call the next one
- if (i <= self.rowsProcessors.length - 1) {
- return startProcessor(i, processedRows);
- }
- // We're done! Resolve the 'finished' promise
- else {
- finished.resolve(processedRows);
- }
- });
- }
-
- // Start on the first processor
- startProcessor(0, myRenderableRows);
-
- return finished.promise;
- };
-
- Grid.prototype.setVisibleRows = function setVisibleRows(rows) {
- var self = this;
-
- // Reset all the render container row caches
- for (var i in self.renderContainers) {
- var container = self.renderContainers[i];
-
- container.canvasHeightShouldUpdate = true;
-
- if ( typeof(container.visibleRowCache) === 'undefined' ){
- container.visibleRowCache = [];
- } else {
- container.visibleRowCache.length = 0;
- }
- }
-
- // rows.forEach(function (row) {
- for (var ri = 0; ri < rows.length; ri++) {
- var row = rows[ri];
-
- var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';
-
- // If the row is visible
- if (row.visible) {
- self.renderContainers[targetContainer].visibleRowCache.push(row);
- }
- }
- self.api.core.raise.rowsRendered(this.api);
- };
-
- /**
- * @ngdoc function
- * @name registerColumnsProcessor
- * @methodOf ui.grid.class:Grid
- * @param {function(renderedColumnsToProcess, rows)} columnProcessor column processor function, which
- * is run in the context of the grid (i.e. this for the function will be the grid), and
- * which must return an updated renderedColumnsToProcess which can be passed to the next processor
- * in the chain
- * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
- * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
- *
- * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
- * @description
-
- Register a "columns processor" function. When the columns are updated,
- the grid calls each registered "columns processor", which has a chance
- to alter the set of columns, as long as the count is not modified.
- */
- Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {
- if (!angular.isFunction(processor)) {
- throw 'Attempt to register non-function rows processor: ' + processor;
- }
-
- this.columnsProcessors.push({processor: processor, priority: priority});
- this.columnsProcessors.sort(function sortByPriority( a, b ){
- return a.priority - b.priority;
- });
- };
-
- Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {
- var idx = this.columnsProcessors.indexOf(processor);
-
- if (typeof(idx) !== 'undefined' && idx !== undefined) {
- this.columnsProcessors.splice(idx, 1);
- }
- };
-
- Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {
- var self = this;
-
- // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
- var myRenderableColumns = renderableColumns.slice(0);
-
- // Return myRenderableRows with no processing if we have no rows processors
- if (self.columnsProcessors.length === 0) {
- return $q.when(myRenderableColumns);
- }
-
- // Counter for iterating through rows processors
- var i = 0;
-
- // Promise for when we're done with all the processors
- var finished = $q.defer();
-
- // This function will call the processor in self.rowsProcessors at index 'i', and then
- // when done will call the next processor in the list, using the output from the processor
- // at i as the argument for 'renderedRowsToProcess' on the next iteration.
- //
- // If we're at the end of the list of processors, we resolve our 'finished' callback with
- // the result.
- function startProcessor(i, renderedColumnsToProcess) {
- // Get the processor at 'i'
- var processor = self.columnsProcessors[i].processor;
-
- // Call the processor, passing in the rows to process and the current columns
- // (note: it's wrapped in $q.when() in case the processor does not return a promise)
- return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )
- .then(function handleProcessedRows(processedColumns) {
- // Check for errors
- if (!processedColumns) {
- throw "Processor at index " + i + " did not return a set of renderable rows";
- }
-
- if (!angular.isArray(processedColumns)) {
- throw "Processor at index " + i + " did not return an array";
- }
-
- // Processor is done, increment the counter
- i++;
-
- // If we're not done with the processors, call the next one
- if (i <= self.columnsProcessors.length - 1) {
- return startProcessor(i, myRenderableColumns);
- }
- // We're done! Resolve the 'finished' promise
- else {
- finished.resolve(myRenderableColumns);
- }
- });
- }
-
- // Start on the first processor
- startProcessor(0, myRenderableColumns);
-
- return finished.promise;
- };
-
- Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {
- // gridUtil.logDebug('setVisibleColumns');
-
- var self = this;
-
- // Reset all the render container row caches
- for (var i in self.renderContainers) {
- var container = self.renderContainers[i];
-
- container.visibleColumnCache.length = 0;
- }
-
- for (var ci = 0; ci < columns.length; ci++) {
- var column = columns[ci];
-
- // If the column is visible
- if (column.visible) {
- // If the column has a container specified
- if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {
- self.renderContainers[column.renderContainer].visibleColumnCache.push(column);
- }
- // If not, put it into the body container
- else {
- self.renderContainers.body.visibleColumnCache.push(column);
- }
- }
- }
- };
-
- /**
- * @ngdoc function
- * @name handleWindowResize
- * @methodOf ui.grid.class:Grid
- * @description Triggered when the browser window resizes; automatically resizes the grid
- */
- Grid.prototype.handleWindowResize = function handleWindowResize($event) {
- var self = this;
-
- self.gridWidth = gridUtil.elementWidth(self.element);
- self.gridHeight = gridUtil.elementHeight(self.element);
-
- self.queueRefresh();
- };
-
- /**
- * @ngdoc function
- * @name queueRefresh
- * @methodOf ui.grid.class:Grid
- * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue
- */
- Grid.prototype.queueRefresh = function queueRefresh() {
- var self = this;
-
- if (self.refreshCanceller) {
- $timeout.cancel(self.refreshCanceller);
- }
-
- self.refreshCanceller = $timeout(function () {
- self.refreshCanvas(true);
- });
-
- self.refreshCanceller.then(function () {
- self.refreshCanceller = null;
- });
-
- return self.refreshCanceller;
- };
-
-
- /**
- * @ngdoc function
- * @name queueGridRefresh
- * @methodOf ui.grid.class:Grid
- * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue
- */
- Grid.prototype.queueGridRefresh = function queueGridRefresh() {
- var self = this;
-
- if (self.gridRefreshCanceller) {
- $timeout.cancel(self.gridRefreshCanceller);
- }
-
- self.gridRefreshCanceller = $timeout(function () {
- self.refresh(true);
- });
-
- self.gridRefreshCanceller.then(function () {
- self.gridRefreshCanceller = null;
- });
-
- return self.gridRefreshCanceller;
- };
-
-
- /**
- * @ngdoc function
- * @name updateCanvasHeight
- * @methodOf ui.grid.class:Grid
- * @description flags all render containers to update their canvas height
- */
- Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {
- var self = this;
-
- for (var containerId in self.renderContainers) {
- if (self.renderContainers.hasOwnProperty(containerId)) {
- var container = self.renderContainers[containerId];
- container.canvasHeightShouldUpdate = true;
- }
- }
- };
-
- /**
- * @ngdoc function
- * @name buildStyles
- * @methodOf ui.grid.class:Grid
- * @description calls each styleComputation function
- */
- // TODO: this used to take $scope, but couldn't see that it was used
- Grid.prototype.buildStyles = function buildStyles() {
- // gridUtil.logDebug('buildStyles');
-
- var self = this;
-
- self.customStyles = '';
-
- self.styleComputations
- .sort(function(a, b) {
- if (a.priority === null) { return 1; }
- if (b.priority === null) { return -1; }
- if (a.priority === null && b.priority === null) { return 0; }
- return a.priority - b.priority;
- })
- .forEach(function (compInfo) {
- // this used to provide $scope as a second parameter, but I couldn't find any
- // style builders that used it, so removed it as part of moving to grid from controller
- var ret = compInfo.func.call(self);
-
- if (angular.isString(ret)) {
- self.customStyles += '\n' + ret;
- }
- });
- };
-
-
- Grid.prototype.minColumnsToRender = function minColumnsToRender() {
- var self = this;
- var viewport = this.getViewportWidth();
-
- var min = 0;
- var totalWidth = 0;
- self.columns.forEach(function(col, i) {
- if (totalWidth < viewport) {
- totalWidth += col.drawnWidth;
- min++;
- }
- else {
- var currWidth = 0;
- for (var j = i; j >= i - min; j--) {
- currWidth += self.columns[j].drawnWidth;
- }
- if (currWidth < viewport) {
- min++;
- }
- }
- });
-
- return min;
- };
-
- Grid.prototype.getBodyHeight = function getBodyHeight() {
- // Start with the viewportHeight
- var bodyHeight = this.getViewportHeight();
-
- // Add the horizontal scrollbar height if there is one
- //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
- // bodyHeight = bodyHeight + this.horizontalScrollbarHeight;
- //}
-
- return bodyHeight;
- };
-
- // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)
- // TODO(c0bra): account for footer height
- Grid.prototype.getViewportHeight = function getViewportHeight() {
- var self = this;
-
- var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;
-
- // Account for native horizontal scrollbar, if present
- //if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
- // viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;
- //}
-
- var adjustment = self.getViewportAdjustment();
-
- viewPortHeight = viewPortHeight + adjustment.height;
-
- //gridUtil.logDebug('viewPortHeight', viewPortHeight);
-
- return viewPortHeight;
- };
-
- Grid.prototype.getViewportWidth = function getViewportWidth() {
- var self = this;
-
- var viewPortWidth = this.gridWidth;
-
- //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
- // viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;
- //}
-
- var adjustment = self.getViewportAdjustment();
-
- viewPortWidth = viewPortWidth + adjustment.width;
-
- //gridUtil.logDebug('getviewPortWidth', viewPortWidth);
-
- return viewPortWidth;
- };
-
- Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
- var viewPortWidth = this.getViewportWidth();
-
- //if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
- // viewPortWidth = viewPortWidth + this.verticalScrollbarWidth;
- //}
-
- return viewPortWidth;
- };
-
- Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {
- this.verticalScrollSyncCallBackFns[containerId] = callBackFn;
- };
-
- Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {
- this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;
- };
-
-/**
- * Scroll needed containers by calling their ScrollSyncs
- * @param sourceContainerId the containerId that has already set it's top/left.
- * can be empty string which means all containers need to set top/left
- * @param scrollEvent
- */
- Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {
-
- if (scrollEvent.y) {
- //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
- var verts = ['body','left', 'right'];
-
- this.flagScrollingVertically(scrollEvent);
-
- if (sourceContainerId === 'body') {
- verts = ['left', 'right'];
- }
- else if (sourceContainerId === 'left') {
- verts = ['body', 'right'];
- }
- else if (sourceContainerId === 'right') {
- verts = ['body', 'left'];
- }
-
- for (var i = 0; i < verts.length; i++) {
- var id = verts[i];
- if (this.verticalScrollSyncCallBackFns[id]) {
- this.verticalScrollSyncCallBackFns[id](scrollEvent);
- }
- }
-
- }
-
- if (scrollEvent.x) {
- //default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
- var horizs = ['body','bodyheader', 'bodyfooter'];
-
- this.flagScrollingHorizontally(scrollEvent);
- if (sourceContainerId === 'body') {
- horizs = ['bodyheader', 'bodyfooter'];
- }
-
- for (var j = 0; j < horizs.length; j++) {
- var idh = horizs[j];
- if (this.horizontalScrollSyncCallBackFns[idh]) {
- this.horizontalScrollSyncCallBackFns[idh](scrollEvent);
- }
- }
-
- }
-
- };
-
- Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
- this.viewportAdjusters.push(func);
- };
-
- Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {
- var idx = this.viewportAdjusters.indexOf(func);
-
- if (typeof(idx) !== 'undefined' && idx !== undefined) {
- this.viewportAdjusters.splice(idx, 1);
- }
- };
-
- Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {
- var self = this;
-
- var adjustment = { height: 0, width: 0 };
-
- self.viewportAdjusters.forEach(function (func) {
- adjustment = func.call(this, adjustment);
- });
-
- return adjustment;
- };
-
- Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {
- // var count = 0;
-
- // this.rows.forEach(function (row) {
- // if (row.visible) {
- // count++;
- // }
- // });
-
- // return this.visibleRowCache.length;
- return this.renderContainers.body.visibleRowCache.length;
- };
-
- Grid.prototype.getVisibleRows = function getVisibleRows() {
- return this.renderContainers.body.visibleRowCache;
- };
-
- Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {
- // var count = 0;
-
- // this.rows.forEach(function (row) {
- // if (row.visible) {
- // count++;
- // }
- // });
-
- // return this.visibleRowCache.length;
- return this.renderContainers.body.visibleColumnCache.length;
- };
-
-
- Grid.prototype.searchRows = function searchRows(renderableRows) {
- return rowSearcher.search(this, renderableRows, this.columns);
- };
-
- Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {
- return rowSorter.sort(this, renderableRows, this.columns);
- };
-
- /**
- * @ngdoc function
- * @name getCellValue
- * @methodOf ui.grid.class:Grid
- * @description Gets the value of a cell for a particular row and column
- * @param {GridRow} row Row to access
- * @param {GridColumn} col Column to access
- */
- Grid.prototype.getCellValue = function getCellValue(row, col){
- if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {
- return row.entity[ '$$' + col.uid].rendered;
- } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ){
- return row.entity[col.field];
- } else {
- if (!col.cellValueGetterCache) {
- col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));
- }
-
- return col.cellValueGetterCache(row);
- }
- };
-
- /**
- * @ngdoc function
- * @name getCellDisplayValue
- * @methodOf ui.grid.class:Grid
- * @description Gets the displayed value of a cell after applying any the `cellFilter`
- * @param {GridRow} row Row to access
- * @param {GridColumn} col Column to access
- */
- Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {
- if ( !col.cellDisplayGetterCache ) {
- var custom_filter = col.cellFilter ? " | " + col.cellFilter : "";
-
- if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {
- col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);
- } else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {
- col.cellDisplayGetterCache = $parse(row.entity[col.field] + custom_filter);
- } else {
- col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);
- }
- }
-
- return col.cellDisplayGetterCache(row);
- };
-
-
- Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {
- var self = this,
- p = 0;
-
- self.columns.forEach(function (col) {
- if (col.sort && col.sort.priority && col.sort.priority > p) {
- p = col.sort.priority;
- }
- });
-
- return p + 1;
- };
-
- /**
- * @ngdoc function
- * @name resetColumnSorting
- * @methodOf ui.grid.class:Grid
- * @description Return the columns that the grid is currently being sorted by
- * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset
- */
- Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {
- var self = this;
-
- self.columns.forEach(function (col) {
- if (col !== excludeCol && !col.suppressRemoveSort) {
- col.sort = {};
- }
- });
- };
-
- /**
- * @ngdoc function
- * @name getColumnSorting
- * @methodOf ui.grid.class:Grid
- * @description Return the columns that the grid is currently being sorted by
- * @returns {Array[GridColumn]} An array of GridColumn objects
- */
- Grid.prototype.getColumnSorting = function getColumnSorting() {
- var self = this;
-
- var sortedCols = [], myCols;
-
- // Iterate through all the columns, sorted by priority
- // Make local copy of column list, because sorting is in-place and we do not want to
- // change the original sequence of columns
- myCols = self.columns.slice(0);
- myCols.sort(rowSorter.prioritySort).forEach(function (col) {
- if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
- sortedCols.push(col);
- }
- });
-
- return sortedCols;
- };
-
- /**
- * @ngdoc function
- * @name sortColumn
- * @methodOf ui.grid.class:Grid
- * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.
- * Emits the sortChanged event whenever the sort criteria are changed.
- * @param {GridColumn} column Column to set the sorting on
- * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.
- * If not provided, the column will iterate through the sort directions
- * specified in the {@link ui.grid.class:GridOptions.columnDef#sortDirectionCycle sortDirectionCycle} attribute.
- * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort
- * by this column only
- * @returns {Promise} A resolved promise that supplies the column.
- */
-
- Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {
- var self = this,
- direction = null;
-
- if (typeof(column) === 'undefined' || !column) {
- throw new Error('No column parameter provided');
- }
-
- // Second argument can either be a direction or whether to add this column to the existing sort.
- // If it's a boolean, it's an add, otherwise, it's a direction
- if (typeof(directionOrAdd) === 'boolean') {
- add = directionOrAdd;
- }
- else {
- direction = directionOrAdd;
- }
-
- if (!add) {
- self.resetColumnSorting(column);
- column.sort.priority = 0;
- // Get the actual priority since there may be columns which have suppressRemoveSort set
- column.sort.priority = self.getNextColumnSortPriority();
- }
- else if (!column.sort.priority){
- column.sort.priority = self.getNextColumnSortPriority();
- }
-
- if (!direction) {
- // Find the current position in the cycle (or -1).
- var i = column.sortDirectionCycle.indexOf(column.sort.direction ? column.sort.direction : null);
- // Proceed to the next position in the cycle (or start at the beginning).
- i = (i+1) % column.sortDirectionCycle.length;
- // If suppressRemoveSort is set, and the next position in the cycle would
- // remove the sort, skip it.
- if (column.colDef && column.suppressRemoveSort && !column.sortDirectionCycle[i]) {
- i = (i+1) % column.sortDirectionCycle.length;
- }
-
- if (column.sortDirectionCycle[i]) {
- column.sort.direction = column.sortDirectionCycle[i];
- } else {
- column.sort = {};
- }
- }
- else {
- column.sort.direction = direction;
- }
-
- self.api.core.raise.sortChanged( self, self.getColumnSorting() );
-
- return $q.when(column);
- };
-
- /**
- * communicate to outside world that we are done with initial rendering
- */
- Grid.prototype.renderingComplete = function(){
- if (angular.isFunction(this.options.onRegisterApi)) {
- this.options.onRegisterApi(this.api);
- }
- this.api.core.raise.renderingComplete( this.api );
- };
-
- Grid.prototype.createRowHashMap = function createRowHashMap() {
- var self = this;
-
- var hashMap = new RowHashMap();
- hashMap.grid = self;
-
- return hashMap;
- };
-
-
- /**
- * @ngdoc function
- * @name refresh
- * @methodOf ui.grid.class:Grid
- * @description Refresh the rendered grid on screen.
- * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.
- */
- Grid.prototype.refresh = function refresh(rowsAltered) {
- var self = this;
-
- var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {
- self.setVisibleRows(renderableRows);
- });
-
- var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {
- self.setVisibleColumns(renderableColumns);
- });
-
- return $q.all([p1, p2]).then(function () {
- self.redrawInPlace(rowsAltered);
-
- self.refreshCanvas(true);
- });
- };
-
- /**
- * @ngdoc function
- * @name refreshRows
- * @methodOf ui.grid.class:Grid
- * @description Refresh the rendered rows on screen? Note: not functional at present
- * @returns {promise} promise that is resolved when render completes?
- *
- */
- Grid.prototype.refreshRows = function refreshRows() {
- var self = this;
-
- return self.processRowsProcessors(self.rows)
- .then(function (renderableRows) {
- self.setVisibleRows(renderableRows);
-
- self.redrawInPlace();
-
- self.refreshCanvas( true );
- });
- };
-
- /**
- * @ngdoc function
- * @name refreshCanvas
- * @methodOf ui.grid.class:Grid
- * @description Builds all styles and recalculates much of the grid sizing
- * @param {object} buildStyles optional parameter. Use TBD
- * @returns {promise} promise that is resolved when the canvas
- * has been refreshed
- *
- */
- Grid.prototype.refreshCanvas = function(buildStyles) {
- var self = this;
-
- if (buildStyles) {
- self.buildStyles();
- }
-
- var p = $q.defer();
-
- // Get all the header heights
- var containerHeadersToRecalc = [];
- for (var containerId in self.renderContainers) {
- if (self.renderContainers.hasOwnProperty(containerId)) {
- var container = self.renderContainers[containerId];
-
- // Skip containers that have no canvasWidth set yet
- if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
- continue;
- }
-
- if (container.header || container.headerCanvas) {
- container.explicitHeaderHeight = container.explicitHeaderHeight || null;
- container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;
-
- containerHeadersToRecalc.push(container);
- }
- }
- }
-
- /*
- *
- * Here we loop through the headers, measuring each element as well as any header "canvas" it has within it.
- *
- * If any header is less than the largest header height, it will be resized to that so that we don't have headers
- * with different heights, which looks like a rendering problem
- *
- * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas
- * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't
- * appear shorter than other cells.
- *
- */
- if (containerHeadersToRecalc.length > 0) {
- // Build the styles without the explicit header heights
- if (buildStyles) {
- self.buildStyles();
- }
-
- // Putting in a timeout as it's not calculating after the grid element is rendered and filled out
- $timeout(function() {
- // var oldHeaderHeight = self.grid.headerHeight;
- // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);
-
- var rebuildStyles = false;
-
- // Get all the header heights
- var maxHeaderHeight = 0;
- var maxHeaderCanvasHeight = 0;
- var i, container;
- var getHeight = function(oldVal, newVal){
- if ( oldVal !== newVal){
- rebuildStyles = true;
- }
- return newVal;
- };
- for (i = 0; i < containerHeadersToRecalc.length; i++) {
- container = containerHeadersToRecalc[i];
-
- // Skip containers that have no canvasWidth set yet
- if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
- continue;
- }
-
- if (container.header) {
- var headerHeight = container.headerHeight = getHeight(container.headerHeight, parseInt(gridUtil.outerElementHeight(container.header), 10));
-
- // Get the "inner" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height
- var topBorder = gridUtil.getBorderSize(container.header, 'top');
- var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');
- var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);
-
- innerHeaderHeight = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;
-
- container.innerHeaderHeight = innerHeaderHeight;
-
- // If the header doesn't have an explicit height set, save the largest header height for use later
- // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
- if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {
- maxHeaderHeight = innerHeaderHeight;
- }
- }
-
- if (container.headerCanvas) {
- var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));
-
-
- // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later
- // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
- if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {
- maxHeaderCanvasHeight = headerCanvasHeight;
- }
- }
- }
-
- // Go through all the headers
- for (i = 0; i < containerHeadersToRecalc.length; i++) {
- container = containerHeadersToRecalc[i];
-
- /* If:
- 1. We have a max header height
- 2. This container has a header height defined
- 3. And either this container has an explicit header height set, OR its header height is less than the max
-
- then:
-
- Give this container's header an explicit height so it will line up with the tallest header
- */
- if (
- maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&
- (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)
- ) {
- container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);
- }
-
- // Do the same as above except for the header canvas
- if (
- maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&
- (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)
- ) {
- container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);
- }
- }
-
- // Rebuild styles if the header height has changed
- // The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available
- if (buildStyles && rebuildStyles) {
- self.buildStyles();
- }
-
- p.resolve();
- });
- }
- else {
- // Timeout still needs to be here to trigger digest after styles have been rebuilt
- $timeout(function() {
- p.resolve();
- });
- }
-
- return p.promise;
- };
-
-
- /**
- * @ngdoc function
- * @name redrawCanvas
- * @methodOf ui.grid.class:Grid
- * @description Redraw the rows and columns based on our current scroll position
- * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated
- *
- */
- Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {
- // gridUtil.logDebug('redrawInPlace');
-
- var self = this;
-
- for (var i in self.renderContainers) {
- var container = self.renderContainers[i];
-
- // gridUtil.logDebug('redrawing container', i);
-
- if (rowsAdded) {
- container.adjustRows(container.prevScrollTop, null);
- container.adjustColumns(container.prevScrollLeft, null);
- }
- else {
- container.adjustRows(null, container.prevScrolltopPercentage);
- container.adjustColumns(null, container.prevScrollleftPercentage);
- }
- }
- };
-
- /**
- * @ngdoc function
- * @name hasLeftContainerColumns
- * @methodOf ui.grid.class:Grid
- * @description returns true if leftContainer has columns
- */
- Grid.prototype.hasLeftContainerColumns = function () {
- return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;
- };
-
- /**
- * @ngdoc function
- * @name hasRightContainerColumns
- * @methodOf ui.grid.class:Grid
- * @description returns true if rightContainer has columns
- */
- Grid.prototype.hasRightContainerColumns = function () {
- return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;
- };
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:Grid
- * @name scrollToIfNecessary
- * @description Scrolls the grid to make a certain row and column combo visible,
- * in the case that it is not completely visible on the screen already.
- * @param {GridRow} gridRow row to make visible
- * @param {GridCol} gridCol column to make visible
- * @returns {promise} a promise that is resolved when scrolling is complete
- */
- Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {
- var self = this;
-
- var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');
-
- // Alias the visible row and column caches
- var visRowCache = self.renderContainers.body.visibleRowCache;
- var visColCache = self.renderContainers.body.visibleColumnCache;
-
- /*-- Get the top, left, right, and bottom "scrolled" edges of the grid --*/
-
- // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards
- var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;
-
- // Don't the let top boundary be less than 0
- topBound = (topBound < 0) ? 0 : topBound;
-
- // The left boundary is the current X scroll position
- var leftBound = self.renderContainers.body.prevScrollLeft;
-
- // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.
- // Basically this is the viewport height added on to the scroll position
- var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight - self.scrollbarWidth;
-
- // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows
- //if (self.horizontalScrollbarHeight) {
- // bottomBound = bottomBound - self.horizontalScrollbarHeight;
- //}
-
- // The right position is the current X scroll position minus the grid width
- var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.renderContainers.body.getViewportWidth());
-
- // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells
- //if (self.verticalScrollbarWidth) {
- // rightBound = rightBound - self.verticalScrollbarWidth;
- //}
-
- // We were given a row to scroll to
- if (gridRow !== null) {
- // This is the index of the row we want to scroll to, within the list of rows that can be visible
- var seekRowIndex = visRowCache.indexOf(gridRow);
-
- // Total vertical scroll length of the grid
- var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());
-
- // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
- //if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {
- // scrollLength = scrollLength + self.horizontalScrollbarHeight;
- //}
-
- // This is the minimum amount of pixels we need to scroll vertical in order to see this row.
- var pixelsToSeeRow = ((seekRowIndex + 1) * self.options.rowHeight);
-
- // Don't let the pixels required to see the row be less than zero
- pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;
-
- var scrollPixels, percentage;
-
- // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
- if (pixelsToSeeRow < topBound) {
- // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
- // to get the full position we need
- scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);
-
- // Turn the scroll position into a percentage and make it an argument for a scroll event
- percentage = scrollPixels / scrollLength;
- scrollEvent.y = { percentage: percentage };
- }
- // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
- else if (pixelsToSeeRow > bottomBound) {
- // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
- // to get the full position we need
- scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;
-
- // Turn the scroll position into a percentage and make it an argument for a scroll event
- percentage = scrollPixels / scrollLength;
- scrollEvent.y = { percentage: percentage };
- }
- }
-
- // We were given a column to scroll to
- if (gridCol !== null) {
- // This is the index of the row we want to scroll to, within the list of rows that can be visible
- var seekColumnIndex = visColCache.indexOf(gridCol);
-
- // Total vertical scroll length of the grid
- var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());
-
- // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
- // if (self.verticalScrollbarWidth && self.verticalScrollbarWidth > 0) {
- // horizScrollLength = horizScrollLength + self.verticalScrollbarWidth;
- // }
-
- // This is the minimum amount of pixels we need to scroll vertical in order to see this column
- var columnLeftEdge = 0;
- for (var i = 0; i < seekColumnIndex; i++) {
- var col = visColCache[i];
- columnLeftEdge += col.drawnWidth;
- }
- columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;
-
- var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;
-
- // Don't let the pixels required to see the column be less than zero
- columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;
-
- var horizScrollPixels, horizPercentage;
-
- // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
- if (columnLeftEdge < leftBound) {
- // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
- // to get the full position we need
- horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);
-
- // Turn the scroll position into a percentage and make it an argument for a scroll event
- horizPercentage = horizScrollPixels / horizScrollLength;
- horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
- scrollEvent.x = { percentage: horizPercentage };
- }
- // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
- else if (columnRightEdge > rightBound) {
- // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
- // to get the full position we need
- horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;
-
- // Turn the scroll position into a percentage and make it an argument for a scroll event
- horizPercentage = horizScrollPixels / horizScrollLength;
- horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
- scrollEvent.x = { percentage: horizPercentage };
- }
- }
-
- var deferred = $q.defer();
-
- // If we need to scroll on either the x or y axes, fire a scroll event
- if (scrollEvent.y || scrollEvent.x) {
- scrollEvent.withDelay = false;
- self.scrollContainers('',scrollEvent);
- var dereg = self.api.core.on.scrollEnd(null,function() {
- deferred.resolve(scrollEvent);
- dereg();
- });
- }
- else {
- deferred.resolve();
- }
-
- return deferred.promise;
- };
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:Grid
- * @name scrollTo
- * @description Scroll the grid such that the specified
- * row and column is in view
- * @param {object} rowEntity gridOptions.data[] array instance to make visible
- * @param {object} colDef to make visible
- * @returns {promise} a promise that is resolved after any scrolling is finished
- */
- Grid.prototype.scrollTo = function (rowEntity, colDef) {
- var gridRow = null, gridCol = null;
-
- if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {
- gridRow = this.getRow(rowEntity);
- }
-
- if (colDef !== null && typeof(colDef) !== 'undefined' ) {
- gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);
- }
- return this.scrollToIfNecessary(gridRow, gridCol);
- };
-
- /**
- * @ngdoc function
- * @name clearAllFilters
- * @methodOf ui.grid.class:Grid
- * @description Clears all filters and optionally refreshes the visible rows.
- * @param {object} refreshRows Defaults to true.
- * @param {object} clearConditions Defaults to false.
- * @param {object} clearFlags Defaults to false.
- * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
- */
- Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {
- // Default `refreshRows` to true because it will be the most commonly desired behaviour.
- if (refreshRows === undefined) {
- refreshRows = true;
- }
- if (clearConditions === undefined) {
- clearConditions = false;
- }
- if (clearFlags === undefined) {
- clearFlags = false;
- }
-
- this.columns.forEach(function(column) {
- column.filters.forEach(function(filter) {
- filter.term = undefined;
-
- if (clearConditions) {
- filter.condition = undefined;
- }
-
- if (clearFlags) {
- filter.flags = undefined;
- }
- });
- });
-
- if (refreshRows) {
- return this.refreshRows();
- }
- };
-
-
- // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)
- function RowHashMap() {}
-
- RowHashMap.prototype = {
- /**
- * Store key value pair
- * @param key key to store can be any type
- * @param value value to store can be any type
- */
- put: function(key, value) {
- this[this.grid.options.rowIdentity(key)] = value;
- },
-
- /**
- * @param key
- * @returns {Object} the value for the key
- */
- get: function(key) {
- return this[this.grid.options.rowIdentity(key)];
- },
-
- /**
- * Remove the key/value pair
- * @param key
- */
- remove: function(key) {
- var value = this[key = this.grid.options.rowIdentity(key)];
- delete this[key];
- return value;
- }
- };
-
-
-
- return Grid;
-
-}]);
-
-})();
-
-(function () {
-
- angular.module('ui.grid')
- .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow', 'uiGridGridMenuService',
- function ($q, $rootScope, gridUtil, uiGridConstants, GridRow, uiGridGridMenuService) {
- /**
- * @ngdoc function
- * @name ui.grid.class:GridApi
- * @description GridApi provides the ability to register public methods events inside the grid and allow
- * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args){}.
- * <br/>
- * To listen to events, you must add a callback to gridOptions.onRegisterApi
- * <pre>
- * $scope.gridOptions.onRegisterApi = function(gridApi){
- * gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){
- * $log.log('navigation event');
- * });
- * };
- * </pre>
- * @param {object} grid grid that owns api
- */
- var GridApi = function GridApi(grid) {
- this.grid = grid;
- this.listeners = [];
-
- /**
- * @ngdoc function
- * @name renderingComplete
- * @methodOf ui.grid.core.api:PublicApi
- * @description Rendering is complete, called at the same
- * time as `onRegisterApi`, but provides a way to obtain
- * that same event within features without stopping end
- * users from getting at the onRegisterApi method.
- *
- * Included in gridApi so that it's always there - otherwise
- * there is still a timing problem with when a feature can
- * call this.
- *
- * @param {GridApi} gridApi the grid api, as normally
- * returned in the onRegisterApi method
- *
- * @example
- * <pre>
- * gridApi.core.on.renderingComplete( grid );
- * </pre>
- */
- this.registerEvent( 'core', 'renderingComplete' );
-
- /**
- * @ngdoc event
- * @name filterChanged
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised after the filter is changed. The nature
- * of the watch expression doesn't allow notification of what changed,
- * so the receiver of this event will need to re-extract the filter
- * conditions from the columns.
- *
- */
- this.registerEvent( 'core', 'filterChanged' );
-
- /**
- * @ngdoc function
- * @name setRowInvisible
- * @methodOf ui.grid.core.api:PublicApi
- * @description Sets an override on the row to make it always invisible,
- * which will override any filtering or other visibility calculations.
- * If the row is currently visible then sets it to invisible and calls
- * both grid refresh and emits the rowsVisibleChanged event
- * @param {object} rowEntity gridOptions.data[] array instance
- */
- this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );
-
- /**
- * @ngdoc function
- * @name clearRowInvisible
- * @methodOf ui.grid.core.api:PublicApi
- * @description Clears any override on visibility for the row so that it returns to
- * using normal filtering and other visibility calculations.
- * If the row is currently invisible then sets it to visible and calls
- * both grid refresh and emits the rowsVisibleChanged event
- * TODO: if a filter is active then we can't just set it to visible?
- * @param {object} rowEntity gridOptions.data[] array instance
- */
- this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );
-
- /**
- * @ngdoc function
- * @name getVisibleRows
- * @methodOf ui.grid.core.api:PublicApi
- * @description Returns all visible rows
- * @param {Grid} grid the grid you want to get visible rows from
- * @returns {array} an array of gridRow
- */
- this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );
-
- /**
- * @ngdoc event
- * @name rowsVisibleChanged
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised after the rows that are visible
- * change. The filtering is zero-based, so it isn't possible
- * to say which rows changed (unlike in the selection feature).
- * We can plausibly know which row was changed when setRowInvisible
- * is called, but in that situation the user already knows which row
- * they changed. When a filter runs we don't know what changed,
- * and that is the one that would have been useful.
- *
- */
- this.registerEvent( 'core', 'rowsVisibleChanged' );
-
- /**
- * @ngdoc event
- * @name rowsRendered
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised after the cache of visible rows is changed.
- */
- this.registerEvent( 'core', 'rowsRendered' );
-
-
- /**
- * @ngdoc event
- * @name scrollBegin
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised when scroll begins. Is throttled, so won't be raised too frequently
- */
- this.registerEvent( 'core', 'scrollBegin' );
-
- /**
- * @ngdoc event
- * @name scrollEnd
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised when scroll has finished. Is throttled, so won't be raised too frequently
- */
- this.registerEvent( 'core', 'scrollEnd' );
-
- /**
- * @ngdoc event
- * @name canvasHeightChanged
- * @eventOf ui.grid.core.api:PublicApi
- * @description is raised when the canvas height has changed
- * <br/>
- * arguments: oldHeight, newHeight
- */
- this.registerEvent( 'core', 'canvasHeightChanged');
- };
-
- /**
- * @ngdoc function
- * @name ui.grid.class:suppressEvents
- * @methodOf ui.grid.class:GridApi
- * @description Used to execute a function while disabling the specified event listeners.
- * Disables the listenerFunctions, executes the callbackFn, and then enables
- * the listenerFunctions again
- * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same
- * functions that were used in the .on.eventName method
- * @param {object} callBackFn function to execute
- * @example
- * <pre>
- * var navigate = function (newRowCol, oldRowCol){
- * //do something on navigate
- * }
- *
- * gridApi.cellNav.on.navigate(scope,navigate);
- *
- *
- * //call the scrollTo event and suppress our navigate listener
- * //scrollTo will still raise the event for other listeners
- * gridApi.suppressEvents(navigate, function(){
- * gridApi.cellNav.scrollTo(aRow, aCol);
- * });
- *
- * </pre>
- */
- GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {
- var self = this;
- var listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];
-
- //find all registered listeners
- var foundListeners = self.listeners.filter(function(listener) {
- return listeners.some(function(l) {
- return listener.handler === l;
- });
- });
-
- //deregister all the listeners
- foundListeners.forEach(function(l){
- l.dereg();
- });
-
- callBackFn();
-
- //reregister all the listeners
- foundListeners.forEach(function(l){
- l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);
- });
-
- };
-
- /**
- * @ngdoc function
- * @name registerEvent
- * @methodOf ui.grid.class:GridApi
- * @description Registers a new event for the given feature. The event will get a
- * .raise and .on prepended to it
- * <br>
- * .raise.eventName() - takes no arguments
- * <br/>
- * <br/>
- * .on.eventName(scope, callBackFn, _this)
- * <br/>
- * scope - a scope reference to add a deregister call to the scopes .$on('destroy'). Scope is optional and can be a null value,
- * but in this case you must deregister it yourself via the returned deregister function
- * <br/>
- * callBackFn - The function to call
- * <br/>
- * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context
- * <br/>
- * .on.eventName returns a dereg funtion that will remove the listener. It's not necessary to use it as the listener
- * will be removed when the scope is destroyed.
- * @param {string} featureName name of the feature that raises the event
- * @param {string} eventName name of the event
- */
- GridApi.prototype.registerEvent = function (featureName, eventName) {
- var self = this;
- if (!self[featureName]) {
- self[featureName] = {};
- }
-
- var feature = self[featureName];
- if (!feature.on) {
- feature.on = {};
- feature.raise = {};
- }
-
- var eventId = self.grid.id + featureName + eventName;
-
- // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);
- feature.raise[eventName] = function () {
- $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));
- };
-
- // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);
- feature.on[eventName] = function (scope, handler, _this) {
- if ( scope !== null && typeof(scope.$on) === 'undefined' ){
- gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\'t passed in the input parameters. It is legitimate to pass null, but you\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');
- return;
- }
- var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);
-
- //track our listener so we can turn off and on
- var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this:_this};
- self.listeners.push(listener);
-
- var removeListener = function(){
- listener.dereg();
- var index = self.listeners.indexOf(listener);
- self.listeners.splice(index,1);
- };
-
- //destroy tracking when scope is destroyed
- if (scope) {
- scope.$on('$destroy', function() {
- removeListener();
- });
- }
-
-
- return removeListener;
- };
- };
-
- function registerEventWithAngular(eventId, handler, grid, _this) {
- return $rootScope.$on(eventId, function (event) {
- var args = Array.prototype.slice.call(arguments);
- args.splice(0, 1); //remove evt argument
- handler.apply(_this ? _this : grid.api, args);
- });
- }
-
- /**
- * @ngdoc function
- * @name registerEventsFromObject
- * @methodOf ui.grid.class:GridApi
- * @description Registers features and events from a simple objectMap.
- * eventObjectMap must be in this format (multiple features allowed)
- * <pre>
- * {featureName:
- * {
- * eventNameOne:function(args){},
- * eventNameTwo:function(args){}
- * }
- * }
- * </pre>
- * @param {object} eventObjectMap map of feature/event names
- */
- GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {
- var self = this;
- var features = [];
- angular.forEach(eventObjectMap, function (featProp, featPropName) {
- var feature = {name: featPropName, events: []};
- angular.forEach(featProp, function (prop, propName) {
- feature.events.push(propName);
- });
- features.push(feature);
- });
-
- features.forEach(function (feature) {
- feature.events.forEach(function (event) {
- self.registerEvent(feature.name, event);
- });
- });
-
- };
-
- /**
- * @ngdoc function
- * @name registerMethod
- * @methodOf ui.grid.class:GridApi
- * @description Registers a new event for the given feature
- * @param {string} featureName name of the feature
- * @param {string} methodName name of the method
- * @param {object} callBackFn function to execute
- * @param {object} _this binds callBackFn 'this' to _this. Defaults to gridApi.grid
- */
- GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {
- if (!this[featureName]) {
- this[featureName] = {};
- }
-
- var feature = this[featureName];
-
- feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);
- };
-
- /**
- * @ngdoc function
- * @name registerMethodsFromObject
- * @methodOf ui.grid.class:GridApi
- * @description Registers features and methods from a simple objectMap.
- * eventObjectMap must be in this format (multiple features allowed)
- * <br>
- * {featureName:
- * {
- * methodNameOne:function(args){},
- * methodNameTwo:function(args){}
- * }
- * @param {object} eventObjectMap map of feature/event names
- * @param {object} _this binds this to _this for all functions. Defaults to gridApi.grid
- */
- GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {
- var self = this;
- var features = [];
- angular.forEach(methodMap, function (featProp, featPropName) {
- var feature = {name: featPropName, methods: []};
- angular.forEach(featProp, function (prop, propName) {
- feature.methods.push({name: propName, fn: prop});
- });
- features.push(feature);
- });
-
- features.forEach(function (feature) {
- feature.methods.forEach(function (method) {
- self.registerMethod(feature.name, method.name, method.fn, _this);
- });
- });
-
- };
-
- return GridApi;
-
- }]);
-
-})();
-
-(function(){
-
-angular.module('ui.grid')
-.factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {
-
- /**
- * ******************************************************************************************
- * PaulL1: Ugly hack here in documentation. These properties are clearly properties of GridColumn,
- * and need to be noted as such for those extending and building ui-grid itself.
- * However, from an end-developer perspective, they interact with all these through columnDefs,
- * and they really need to be documented there. I feel like they're relatively static, and
- * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each
- * comment block. Ugh.
- *
- */
-
- /**
- * @ngdoc property
- * @name name
- * @propertyOf ui.grid.class:GridColumn
- * @description (mandatory) each column should have a name, although for backward
- * compatibility with 2.x name can be omitted if field is present
- *
- */
-
- /**
- * @ngdoc property
- * @name name
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (mandatory) each column should have a name, although for backward
- * compatibility with 2.x name can be omitted if field is present
- *
- */
-
- /**
- * @ngdoc property
- * @name displayName
- * @propertyOf ui.grid.class:GridColumn
- * @description Column name that will be shown in the header. If displayName is not
- * provided then one is generated using the name.
- *
- */
-
- /**
- * @ngdoc property
- * @name displayName
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Column name that will be shown in the header. If displayName is not
- * provided then one is generated using the name.
- *
- */
-
- /**
- * @ngdoc property
- * @name field
- * @propertyOf ui.grid.class:GridColumn
- * @description field must be provided if you wish to bind to a
- * property in the data source. Should be an angular expression that evaluates against grid.options.data
- * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.
- * See the angular docs on binding expressions.
- *
- */
-
- /**
- * @ngdoc property
- * @name field
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description field must be provided if you wish to bind to a
- * property in the data source. Should be an angular expression that evaluates against grid.options.data
- * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>. * See the angular docs on binding expressions. *
- */
-
- /**
- * @ngdoc property
- * @name filter
- * @propertyOf ui.grid.class:GridColumn
- * @description Filter on this column.
- * @example
- * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text', flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>
- *
- */
-
- /**
- * @ngdoc object
- * @name ui.grid.class:GridColumn
- * @description Represents the viewModel for each column. Any state or methods needed for a Grid Column
- * are defined on this prototype
- * @param {ColumnDef} colDef the column def to associate with this column
- * @param {number} uid the unique and immutable uid we'd like to allocate to this column
- * @param {Grid} grid the grid we'd like to create this column in
- */
- function GridColumn(colDef, uid, grid) {
- var self = this;
-
- self.grid = grid;
- self.uid = uid;
-
- self.updateColumnDef(colDef, true);
-
- /**
- * @ngdoc function
- * @name hideColumn
- * @methodOf ui.grid.class:GridColumn
- * @description Hides the column by setting colDef.visible = false
- */
- GridColumn.prototype.hideColumn = function() {
- this.colDef.visible = false;
- };
-
- self.aggregationValue = undefined;
-
- // The footer cell registers to listen for the rowsRendered event, and calls this. Needed to be
- // in something with a scope so that the dereg would get called
- self.updateAggregationValue = function() {
-
- // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);
-
- /**
- * @ngdoc property
- * @name aggregationType
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description The aggregation that you'd like to show in the columnFooter for this
- * column. Valid values are in uiGridConstants, and currently include `uiGridConstants.aggregationTypes.count`,
- * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,
- * `uiGridConstants.aggregationTypes.max`.
- *
- * You can also provide a function as the aggregation type, in this case your function needs to accept the full
- * set of visible rows, and return a value that should be shown
- */
- if (!self.aggregationType) {
- self.aggregationValue = undefined;
- return;
- }
-
- var result = 0;
- var visibleRows = self.grid.getVisibleRows();
-
- var cellValues = function(){
- var values = [];
- visibleRows.forEach(function (row) {
- var cellValue = self.grid.getCellValue(row, self);
- var cellNumber = Number(cellValue);
- if (!isNaN(cellNumber)) {
- values.push(cellNumber);
- }
- });
- return values;
- };
-
- if (angular.isFunction(self.aggregationType)) {
- self.aggregationValue = self.aggregationType(visibleRows, self);
- }
- else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {
- self.aggregationValue = self.grid.getVisibleRowCount();
- }
- else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {
- cellValues().forEach(function (value) {
- result += value;
- });
- self.aggregationValue = result;
- }
- else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {
- cellValues().forEach(function (value) {
- result += value;
- });
- result = result / cellValues().length;
- self.aggregationValue = result;
- }
- else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {
- self.aggregationValue = Math.min.apply(null, cellValues());
- }
- else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {
- self.aggregationValue = Math.max.apply(null, cellValues());
- }
- else {
- self.aggregationValue = '\u00A0';
- }
- };
-
-// var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });
-
- /**
- * @ngdoc function
- * @name getAggregationValue
- * @methodOf ui.grid.class:GridColumn
- * @description gets the aggregation value based on the aggregation type for this column.
- * Debounced using scrollDebounce option setting
- */
- this.getAggregationValue = function() {
-// if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
-// throttledUpdateAggregationValue();
-// }
-
- return self.aggregationValue;
- };
- }
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:GridColumn
- * @name setPropertyOrDefault
- * @description Sets a property on the column using the passed in columnDef, and
- * setting the defaultValue if the value cannot be found on the colDef
- * @param {ColumnDef} colDef the column def to look in for the property value
- * @param {string} propName the property name we'd like to set
- * @param {object} defaultValue the value to use if the colDef doesn't provide the setting
- */
- GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {
- var self = this;
-
- // Use the column definition filter if we were passed it
- if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {
- self[propName] = colDef[propName];
- }
- // Otherwise use our own if it's set
- else if (typeof(self[propName]) !== 'undefined') {
- self[propName] = self[propName];
- }
- // Default to empty object for the filter
- else {
- self[propName] = defaultValue ? defaultValue : {};
- }
- };
-
-
-
- /**
- * @ngdoc property
- * @name width
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description sets the column width. Can be either
- * a number or a percentage, or an * for auto.
- * @example
- * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},
- * { field: 'field2', width: '20%'},
- * { field: 'field3', width: '*' }]; </pre>
- *
- */
-
- /**
- * @ngdoc property
- * @name minWidth
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description sets the minimum column width. Should be a number.
- * @example
- * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>
- *
- */
-
- /**
- * @ngdoc property
- * @name maxWidth
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description sets the maximum column width. Should be a number.
- * @example
- * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>
- *
- */
-
- /**
- * @ngdoc property
- * @name visible
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description sets whether or not the column is visible
- * </br>Default is true
- * @example
- * <pre> $scope.gridOptions.columnDefs = [
- * { field: 'field1', visible: true},
- * { field: 'field2', visible: false }
- * ]; </pre>
- *
- */
-
- /**
- * @ngdoc property
- * @name sort
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description An object of sort information, attributes are:
- *
- * - direction: values are uiGridConstants.ASC or uiGridConstants.DESC
- * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)
- * - priority: says what order to sort the columns in (lower priority gets sorted first).
- * @example
- * <pre>
- * $scope.gridOptions.columnDefs = [{
- * field: 'field1',
- * sort: {
- * direction: uiGridConstants.ASC,
- * ignoreSort: true,
- * priority: 0
- * }
- * }];
- * </pre>
- */
-
-
- /**
- * @ngdoc property
- * @name sortingAlgorithm
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters
- * like any normal sorting function with additional 'rowA', 'rowB', and 'direction' parameters
- * that are the row objects and the current direction of the sort respectively.
- *
- */
-
- /**
- * @ngdoc array
- * @name filters
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Specify multiple filter fields.
- * @example
- * <pre>$scope.gridOptions.columnDefs = [
- * {
- * field: 'field1', filters: [
- * {
- * term: 'aa',
- * condition: uiGridConstants.filter.STARTS_WITH,
- * placeholder: 'starts with...',
- * ariaLabel: 'Filter for field1',
- * flags: { caseSensitive: false },
- * type: uiGridConstants.filter.SELECT,
- * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
- * },
- * {
- * condition: uiGridConstants.filter.ENDS_WITH,
- * placeholder: 'ends with...'
- * }
- * ]
- * }
- * ]; </pre>
- *
- *
- */
-
- /**
- * @ngdoc array
- * @name filters
- * @propertyOf ui.grid.class:GridColumn
- * @description Filters for this column. Includes 'term' property bound to filter input elements.
- * @example
- * <pre>[
- * {
- * term: 'foo', // ngModel for <input>
- * condition: uiGridConstants.filter.STARTS_WITH,
- * placeholder: 'starts with...',
- * ariaLabel: 'Filter for foo',
- * flags: { caseSensitive: false },
- * type: uiGridConstants.filter.SELECT,
- * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
- * },
- * {
- * term: 'baz',
- * condition: uiGridConstants.filter.ENDS_WITH,
- * placeholder: 'ends with...'
- * }
- * ] </pre>
- *
- *
- */
-
- /**
- * @ngdoc array
- * @name menuItems
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description used to add menu items to a column. Refer to the tutorial on this
- * functionality. A number of settings are supported:
- *
- * - title: controls the title that is displayed in the menu
- * - icon: the icon shown alongside that title
- * - action: the method to call when the menu is clicked
- * - shown: a function to evaluate to determine whether or not to show the item
- * - active: a function to evaluate to determine whether or not the item is currently selected
- * - context: context to pass to the action function, available in this.context in your handler
- * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false
- * @example
- * <pre> $scope.gridOptions.columnDefs = [
- * { field: 'field1', menuItems: [
- * {
- * title: 'Outer Scope Alert',
- * icon: 'ui-grid-icon-info-circled',
- * action: function($event) {
- * this.context.blargh(); // $scope.blargh() would work too, this is just an example
- * },
- * shown: function() { return true; },
- * active: function() { return true; },
- * context: $scope
- * },
- * {
- * title: 'Grid ID',
- * action: function() {
- * alert('Grid ID: ' + this.grid.id);
- * }
- * }
- * ] }]; </pre>
- *
- */
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:GridColumn
- * @name updateColumnDef
- * @description Moves settings from the columnDef down onto the column,
- * and sets properties as appropriate
- * @param {ColumnDef} colDef the column def to look in for the property value
- * @param {boolean} isNew whether the column is being newly created, if not
- * we're updating an existing column, and some items such as the sort shouldn't
- * be copied down
- */
- GridColumn.prototype.updateColumnDef = function(colDef, isNew) {
- var self = this;
-
- self.colDef = colDef;
-
- if (colDef.name === undefined) {
- throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));
- }
-
- self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
-
- if (!angular.isNumber(self.width) || !self.hasCustomWidth || colDef.allowCustomWidthOverride) {
- var colDefWidth = colDef.width;
- var parseErrorMsg = "Cannot parse column width '" + colDefWidth + "' for column named '" + colDef.name + "'";
- self.hasCustomWidth = false;
-
- if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {
- self.width = '*';
- } else if (angular.isString(colDefWidth)) {
- // See if it ends with a percent
- if (gridUtil.endsWith(colDefWidth, '%')) {
- // If so we should be able to parse the non-percent-sign part to a number
- var percentStr = colDefWidth.replace(/%/g, '');
- var percent = parseInt(percentStr, 10);
- if (isNaN(percent)) {
- throw new Error(parseErrorMsg);
- }
- self.width = colDefWidth;
- }
- // And see if it's a number string
- else if (colDefWidth.match(/^(\d+)$/)) {
- self.width = parseInt(colDefWidth.match(/^(\d+)$/)[1], 10);
- }
- // Otherwise it should be a string of asterisks
- else if (colDefWidth.match(/^\*+$/)) {
- self.width = colDefWidth;
- }
- // No idea, throw an Error
- else {
- throw new Error(parseErrorMsg);
- }
- }
- // Is a number, use it as the width
- else {
- self.width = colDefWidth;
- }
- }
-
- ['minWidth', 'maxWidth'].forEach(function (name) {
- var minOrMaxWidth = colDef[name];
- var parseErrorMsg = "Cannot parse column " + name + " '" + minOrMaxWidth + "' for column named '" + colDef.name + "'";
-
- if (!angular.isString(minOrMaxWidth) && !angular.isNumber(minOrMaxWidth)) {
- //Sets default minWidth and maxWidth values
- self[name] = ((name === 'minWidth') ? 30 : 9000);
- } else if (angular.isString(minOrMaxWidth)) {
- if (minOrMaxWidth.match(/^(\d+)$/)) {
- self[name] = parseInt(minOrMaxWidth.match(/^(\d+)$/)[1], 10);
- } else {
- throw new Error(parseErrorMsg);
- }
- } else {
- self[name] = minOrMaxWidth;
- }
- });
-
- //use field if it is defined; name if it is not
- self.field = (colDef.field === undefined) ? colDef.name : colDef.field;
-
- if ( typeof( self.field ) !== 'string' ){
- gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );
- }
-
- self.name = colDef.name;
-
- // Use colDef.displayName as long as it's not undefined, otherwise default to the field name
- self.displayName = (colDef.displayName === undefined) ? gridUtil.readableColumnName(colDef.name) : colDef.displayName;
-
- //self.originalIndex = index;
-
- self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;
- self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;
-
- /**
- * @ngdoc property
- * @name cellTooltip
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Whether or not to show a tooltip when a user hovers over the cell.
- * If set to false, no tooltip. If true, the cell value is shown in the tooltip (useful
- * if you have long values in your cells), if a function then that function is called
- * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,
- * if it is a static string then displays that static string.
- *
- * Defaults to false
- *
- */
- if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {
- self.cellTooltip = false;
- } else if ( colDef.cellTooltip === true ){
- self.cellTooltip = function(row, col) {
- return self.grid.getCellValue( row, col );
- };
- } else if (typeof(colDef.cellTooltip) === 'function' ){
- self.cellTooltip = colDef.cellTooltip;
- } else {
- self.cellTooltip = function ( row, col ){
- return col.colDef.cellTooltip;
- };
- }
-
- /**
- * @ngdoc property
- * @name headerTooltip
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Whether or not to show a tooltip when a user hovers over the header cell.
- * If set to false, no tooltip. If true, the displayName is shown in the tooltip (useful
- * if you have long values in your headers), if a function then that function is called
- * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,
- * if a static string then shows that static string.
- *
- * Defaults to false
- *
- */
- if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {
- self.headerTooltip = false;
- } else if ( colDef.headerTooltip === true ){
- self.headerTooltip = function(col) {
- return col.displayName;
- };
- } else if (typeof(colDef.headerTooltip) === 'function' ){
- self.headerTooltip = colDef.headerTooltip;
- } else {
- self.headerTooltip = function ( col ) {
- return col.colDef.headerTooltip;
- };
- }
-
-
- /**
- * @ngdoc property
- * @name footerCellClass
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description footerCellClass can be a string specifying the class to append to a cell
- * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
- *
- */
- self.footerCellClass = colDef.footerCellClass;
-
- /**
- * @ngdoc property
- * @name cellClass
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description cellClass can be a string specifying the class to append to a cell
- * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
- *
- */
- self.cellClass = colDef.cellClass;
-
- /**
- * @ngdoc property
- * @name headerCellClass
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description headerCellClass can be a string specifying the class to append to a cell
- * or it can be a function(row,rowRenderIndex, col, colRenderIndex) that returns a class name
- *
- */
- self.headerCellClass = colDef.headerCellClass;
-
- /**
- * @ngdoc property
- * @name cellFilter
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description cellFilter is a filter to apply to the content of each cell
- * @example
- * <pre>
- * gridOptions.columnDefs[0].cellFilter = 'date'
- *
- */
- self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
-
- /**
- * @ngdoc boolean
- * @name sortCellFiltered
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
- * sorting the data. Note that when using this option uiGrid will assume that the displayed value is
- * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible
- * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}
- * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`
- * found in the {@link ui.grid.RowSorter rowSorter} service.
- */
- self.sortCellFiltered = colDef.sortCellFiltered ? true : false;
-
- /**
- * @ngdoc boolean
- * @name filterCellFiltered
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
- * applying "search" `filters`.
- */
- self.filterCellFiltered = colDef.filterCellFiltered ? true : false;
-
- /**
- * @ngdoc property
- * @name headerCellFilter
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description headerCellFilter is a filter to apply to the content of the column header
- * @example
- * <pre>
- * gridOptions.columnDefs[0].headerCellFilter = 'translate'
- *
- */
- self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : "";
-
- /**
- * @ngdoc property
- * @name footerCellFilter
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description footerCellFilter is a filter to apply to the content of the column footer
- * @example
- * <pre>
- * gridOptions.columnDefs[0].footerCellFilter = 'date'
- *
- */
- self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : "";
-
- self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;
-
- self.headerClass = colDef.headerClass;
- //self.cursor = self.sortable ? 'pointer' : 'default';
-
- // Turn on sorting by default
- self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : true;
- self.sortingAlgorithm = colDef.sortingAlgorithm;
-
- /**
- * @ngdoc property
- * @name sortDirectionCycle
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) An array of sort directions, specifying the order that they
- * should cycle through as the user repeatedly clicks on the column heading.
- * The default is `[null, uiGridConstants.ASC, uiGridConstants.DESC]`. Null
- * refers to the unsorted state. This does not affect the initial sort
- * direction; use the {@link ui.grid.class:GridOptions.columnDef#sort sort}
- * property for that. If
- * {@link ui.grid.class:GridOptions.columnDef#suppressRemoveSort suppressRemoveSort}
- * is also set, the unsorted state will be skipped even if it is listed here.
- * Each direction may not appear in the list more than once (e.g. `[ASC,
- * DESC, DESC]` is not allowed), and the list may not be empty.
- */
- self.sortDirectionCycle = typeof(colDef.sortDirectionCycle) !== 'undefined' ?
- colDef.sortDirectionCycle :
- [null, uiGridConstants.ASC, uiGridConstants.DESC];
-
- /**
- * @ngdoc boolean
- * @name suppressRemoveSort
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description (optional) False by default. When enabled, this setting hides the removeSort option
- * in the menu, and prevents users from manually removing the sort
- */
- if ( typeof(self.suppressRemoveSort) === 'undefined'){
- self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;
- }
-
- /**
- * @ngdoc property
- * @name enableFiltering
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description turn off filtering for an individual column, where
- * you've turned on filtering for the overall grid
- * @example
- * <pre>
- * gridOptions.columnDefs[0].enableFiltering = false;
- *
- */
- // Turn on filtering by default (it's disabled by default at the Grid level)
- self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;
-
- // self.menuItems = colDef.menuItems;
- self.setPropertyOrDefault(colDef, 'menuItems', []);
-
- // Use the column definition sort if we were passed it, but only if this is a newly added column
- if ( isNew ){
- self.setPropertyOrDefault(colDef, 'sort');
- }
-
- // Set up default filters array for when one is not provided.
- // In other words, this (in column def):
- //
- // filter: { term: 'something', flags: {}, condition: [CONDITION] }
- //
- // is just shorthand for this:
- //
- // filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]
- //
- var defaultFilters = [];
- if (colDef.filter) {
- defaultFilters.push(colDef.filter);
- }
- else if ( colDef.filters ){
- defaultFilters = colDef.filters;
- } else {
- // Add an empty filter definition object, which will
- // translate to a guessed condition and no pre-populated
- // value for the filter <input>.
- defaultFilters.push({});
- }
-
- /**
- * @ngdoc property
- * @name filter
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description Specify a single filter field on this column.
- *
- * A filter consists of a condition, a term, and a placeholder:
- *
- * - condition defines how rows are chosen as matching the filter term. This can be set to
- * one of the constants in uiGridConstants.filter, or you can supply a custom filter function
- * that gets passed the following arguments: [searchTerm, cellValue, row, column].
- * - term: If set, the filter field will be pre-populated
- * with this value.
- * - placeholder: String that will be set to the `<input>.placeholder` attribute.
- * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.
- * - noTerm: set this to true if you have defined a custom function in condition, and
- * your custom function doesn't require a term (so it can run even when the term is null)
- * - flags: only flag currently available is `caseSensitive`, set to false if you don't want
- * case sensitive matching
- * - type: defaults to uiGridConstants.filter.INPUT, which gives a text box. If set to uiGridConstants.filter.SELECT
- * then a select box will be shown with options selectOptions
- * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`. No i18n filter is provided, you need
- * to perform the i18n on the values before you provide them
- * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter
- * will not be shown.
- * @example
- * <pre>$scope.gridOptions.columnDefs = [
- * {
- * field: 'field1',
- * filter: {
- * term: 'xx',
- * condition: uiGridConstants.filter.STARTS_WITH,
- * placeholder: 'starts with...',
- * ariaLabel: 'Starts with filter for field1',
- * flags: { caseSensitive: false },
- * type: uiGridConstants.filter.SELECT,
- * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],
- * disableCancelFilterButton: true
- * }
- * }
- * ]; </pre>
- *
- */
-
- /*
-
-
- /*
-
- self.filters = [
- {
- term: 'search term'
- condition: uiGridConstants.filter.CONTAINS,
- placeholder: 'my placeholder',
- ariaLabel: 'Starts with filter for field1',
- flags: {
- caseSensitive: true
- }
- }
- ]
-
- */
-
- // Only set filter if this is a newly added column, if we're updating an existing
- // column then we don't want to put the default filter back if the user may have already
- // removed it.
- // However, we do want to keep the settings if they change, just not the term
- if ( isNew ) {
- self.setPropertyOrDefault(colDef, 'filter');
- self.setPropertyOrDefault(colDef, 'filters', defaultFilters);
- } else if ( self.filters.length === defaultFilters.length ) {
- self.filters.forEach( function( filter, index ){
- if (typeof(defaultFilters[index].placeholder) !== 'undefined') {
- filter.placeholder = defaultFilters[index].placeholder;
- }
- if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {
- filter.ariaLabel = defaultFilters[index].ariaLabel;
- }
- if (typeof(defaultFilters[index].flags) !== 'undefined') {
- filter.flags = defaultFilters[index].flags;
- }
- if (typeof(defaultFilters[index].type) !== 'undefined') {
- filter.type = defaultFilters[index].type;
- }
- if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {
- filter.selectOptions = defaultFilters[index].selectOptions;
- }
- });
- }
-
- // Remove this column from the grid sorting, include inside build columns so has
- // access to self - all seems a bit dodgy but doesn't work otherwise so have left
- // as is
- GridColumn.prototype.unsort = function () {
- this.sort = {};
- self.grid.api.core.raise.sortChanged( self.grid, self.grid.getColumnSorting() );
- };
-
- };
-
-
- /**
- * @ngdoc function
- * @name getColClass
- * @methodOf ui.grid.class:GridColumn
- * @description Returns the class name for the column
- * @param {bool} prefixDot if true, will return .className instead of className
- */
- GridColumn.prototype.getColClass = function (prefixDot) {
- var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;
-
- return prefixDot ? '.' + cls : cls;
- };
-
- /**
- * @ngdoc function
- * @name isPinnedLeft
- * @methodOf ui.grid.class:GridColumn
- * @description Returns true if column is in the left render container
- */
- GridColumn.prototype.isPinnedLeft = function () {
- return this.renderContainer === 'left';
- };
-
- /**
- * @ngdoc function
- * @name isPinnedRight
- * @methodOf ui.grid.class:GridColumn
- * @description Returns true if column is in the right render container
- */
- GridColumn.prototype.isPinnedRight = function () {
- return this.renderContainer === 'right';
- };
-
-
- /**
- * @ngdoc function
- * @name getColClassDefinition
- * @methodOf ui.grid.class:GridColumn
- * @description Returns the class definition for th column
- */
- GridColumn.prototype.getColClassDefinition = function () {
- return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';
- };
-
- /**
- * @ngdoc function
- * @name getRenderContainer
- * @methodOf ui.grid.class:GridColumn
- * @description Returns the render container object that this column belongs to.
- *
- * Columns will be default be in the `body` render container if they aren't allocated to one specifically.
- */
- GridColumn.prototype.getRenderContainer = function getRenderContainer() {
- var self = this;
-
- var containerId = self.renderContainer;
-
- if (containerId === null || containerId === '' || containerId === undefined) {
- containerId = 'body';
- }
-
- return self.grid.renderContainers[containerId];
- };
-
- /**
- * @ngdoc function
- * @name showColumn
- * @methodOf ui.grid.class:GridColumn
- * @description Makes the column visible by setting colDef.visible = true
- */
- GridColumn.prototype.showColumn = function() {
- this.colDef.visible = true;
- };
-
-
- /**
- * @ngdoc property
- * @name aggregationHideLabel
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description defaults to false, if set to true hides the label text
- * in the aggregation footer, so only the value is displayed.
- *
- */
- /**
- * @ngdoc function
- * @name getAggregationText
- * @methodOf ui.grid.class:GridColumn
- * @description Gets the aggregation label from colDef.aggregationLabel if
- * specified or by using i18n, including deciding whether or not to display
- * based on colDef.aggregationHideLabel.
- *
- * @param {string} label the i18n lookup value to use for the column label
- *
- */
- GridColumn.prototype.getAggregationText = function () {
- var self = this;
- if ( self.colDef.aggregationHideLabel ){
- return '';
- }
- else if ( self.colDef.aggregationLabel ) {
- return self.colDef.aggregationLabel;
- }
- else {
- switch ( self.colDef.aggregationType ){
- case uiGridConstants.aggregationTypes.count:
- return i18nService.getSafeText('aggregation.count');
- case uiGridConstants.aggregationTypes.sum:
- return i18nService.getSafeText('aggregation.sum');
- case uiGridConstants.aggregationTypes.avg:
- return i18nService.getSafeText('aggregation.avg');
- case uiGridConstants.aggregationTypes.min:
- return i18nService.getSafeText('aggregation.min');
- case uiGridConstants.aggregationTypes.max:
- return i18nService.getSafeText('aggregation.max');
- default:
- return '';
- }
- }
- };
-
- GridColumn.prototype.getCellTemplate = function () {
- var self = this;
-
- return self.cellTemplatePromise;
- };
-
- GridColumn.prototype.getCompiledElementFn = function () {
- var self = this;
-
- return self.compiledElementFnDefer.promise;
- };
-
- return GridColumn;
-}]);
-
-})();
-
- (function(){
-
-angular.module('ui.grid')
-.factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil,uiGridConstants) {
-
- /**
- * @ngdoc function
- * @name ui.grid.class:GridOptions
- * @description Default GridOptions class. GridOptions are defined by the application developer and overlaid
- * over this object. Setting gridOptions within your controller is the most common method for an application
- * developer to configure the behaviour of their ui-grid
- *
- * @example To define your gridOptions within your controller:
- * <pre>$scope.gridOptions = {
- * data: $scope.myData,
- * columnDefs: [
- * { name: 'field1', displayName: 'pretty display name' },
- * { name: 'field2', visible: false }
- * ]
- * };</pre>
- *
- * You can then use this within your html template, when you define your grid:
- * <pre>&lt;div ui-grid="gridOptions"&gt;&lt;/div&gt;</pre>
- *
- * To provide default options for all of the grids within your application, use an angular
- * decorator to modify the GridOptions factory.
- * <pre>
- * app.config(function($provide){
- * $provide.decorator('GridOptions',function($delegate){
- * var gridOptions;
- * gridOptions = angular.copy($delegate);
- * gridOptions.initialize = function(options) {
- * var initOptions;
- * initOptions = $delegate.initialize(options);
- * initOptions.enableColumnMenus = false;
- * return initOptions;
- * };
- * return gridOptions;
- * });
- * });
- * </pre>
- */
- return {
- initialize: function( baseOptions ){
- /**
- * @ngdoc function
- * @name onRegisterApi
- * @propertyOf ui.grid.class:GridOptions
- * @description A callback that returns the gridApi once the grid is instantiated, which is
- * then used to interact with the grid programatically.
- *
- * Note that the gridApi.core.renderingComplete event is identical to this
- * callback, but has the advantage that it can be called from multiple places
- * if needed
- *
- * @example
- * <pre>
- * $scope.gridOptions.onRegisterApi = function ( gridApi ) {
- * $scope.gridApi = gridApi;
- * $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );
- * };
- * </pre>
- *
- */
- baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();
-
- /**
- * @ngdoc object
- * @name data
- * @propertyOf ui.grid.class:GridOptions
- * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for
- * the grid.
- *
- * Most commonly the data is an array of objects, where each object has a number of attributes.
- * Each attribute automatically becomes a column in your grid. This array could, for example, be sourced from
- * an angularJS $resource query request. The array can also contain complex objects, refer the binding tutorial
- * for examples of that.
- *
- * The most flexible usage is to set your data on $scope:
- *
- * `$scope.data = data;`
- *
- * And then direct the grid to resolve whatever is in $scope.data:
- *
- * `$scope.gridOptions.data = 'data';`
- *
- * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without
- * getting pointer issues.
- *
- * Alternatively you can directly set the data array:
- *
- * `$scope.gridOptions.data = [ ];`
- * or
- *
- * `$http.get('/data/100.json')
- * .success(function(data) {
- * $scope.myData = data;
- * $scope.gridOptions.data = $scope.myData;
- * });`
- *
- * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other
- * array, you need to update $scope.gridOptions.data to point to that new array as well.
- *
- */
- baseOptions.data = baseOptions.data || [];
-
- /**
- * @ngdoc array
- * @name columnDefs
- * @propertyOf ui.grid.class:GridOptions
- * @description Array of columnDef objects. Only required property is name.
- * The individual options available in columnDefs are documented in the
- * {@link ui.grid.class:GridOptions.columnDef columnDef} section
- * </br>_field property can be used in place of name for backwards compatibility with 2.x_
- * @example
- *
- * <pre>var columnDefs = [{name:'field1'}, {name:'field2'}];</pre>
- *
- */
- baseOptions.columnDefs = baseOptions.columnDefs || [];
-
- /**
- * @ngdoc object
- * @name ui.grid.class:GridOptions.columnDef
- * @description Definition / configuration of an individual column, which would typically be
- * one of many column definitions within the gridOptions.columnDefs array
- * @example
- * <pre>{name:'field1', field: 'field1', filter: { term: 'xxx' }}</pre>
- *
- */
-
-
- /**
- * @ngdoc array
- * @name excludeProperties
- * @propertyOf ui.grid.class:GridOptions
- * @description Array of property names in data to ignore when auto-generating column names. Provides the
- * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns
- * to exclude.
- *
- * If columnDefs is defined, this will be ignored.
- *
- * Defaults to ['$$hashKey']
- */
-
- baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];
-
- /**
- * @ngdoc boolean
- * @name enableRowHashing
- * @propertyOf ui.grid.class:GridOptions
- * @description True by default. When enabled, this setting allows uiGrid to add
- * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows
- * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.
- *
- * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF
- * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows
- * and are altering the data set often.
- */
- baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;
-
- /**
- * @ngdoc function
- * @name rowIdentity
- * @methodOf ui.grid.class:GridOptions
- * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).
- *
- * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one
- */
- baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {
- return gridUtil.hashKey(row);
- };
-
- /**
- * @ngdoc function
- * @name getRowIdentity
- * @methodOf ui.grid.class:GridOptions
- * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.
- *
- * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.
- */
- baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {
- return row.$$hashKey;
- };
-
- /**
- * @ngdoc property
- * @name flatEntityAccess
- * @propertyOf ui.grid.class:GridOptions
- * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.
- * each of your columns associate directly with a property on each of the entities in your data array.
- *
- * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,
- * which can provide a significant speed improvement with large data sets when filtering or sorting.
- *
- * By default false
- */
- baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;
-
- /**
- * @ngdoc property
- * @name showHeader
- * @propertyOf ui.grid.class:GridOptions
- * @description True by default. When set to false, this setting will replace the
- * standard header template with '<div></div>', resulting in no header being shown.
- */
- baseOptions.showHeader = typeof(baseOptions.showHeader) !== "undefined" ? baseOptions.showHeader : true;
-
- /* (NOTE): Don't show this in the docs. We only use it internally
- * @ngdoc property
- * @name headerRowHeight
- * @propertyOf ui.grid.class:GridOptions
- * @description The height of the header in pixels, defaults to 30
- *
- */
- if (!baseOptions.showHeader) {
- baseOptions.headerRowHeight = 0;
- }
- else {
- baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== "undefined" ? baseOptions.headerRowHeight : 30;
- }
-
- /**
- * @ngdoc property
- * @name rowHeight
- * @propertyOf ui.grid.class:GridOptions
- * @description The height of the row in pixels, defaults to 30
- *
- */
- baseOptions.rowHeight = baseOptions.rowHeight || 30;
-
- /**
- * @ngdoc integer
- * @name minRowsToShow
- * @propertyOf ui.grid.class:GridOptions
- * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to "10".
- */
- baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== "undefined" ? baseOptions.minRowsToShow : 10;
-
- /**
- * @ngdoc property
- * @name showGridFooter
- * @propertyOf ui.grid.class:GridOptions
- * @description Whether or not to show the footer, defaults to false
- * The footer display Total Rows and Visible Rows (filtered rows)
- */
- baseOptions.showGridFooter = baseOptions.showGridFooter === true;
-
- /**
- * @ngdoc property
- * @name showColumnFooter
- * @propertyOf ui.grid.class:GridOptions
- * @description Whether or not to show the column footer, defaults to false
- * The column footer displays column aggregates
- */
- baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;
-
- /**
- * @ngdoc property
- * @name columnFooterHeight
- * @propertyOf ui.grid.class:GridOptions
- * @description The height of the footer rows (column footer and grid footer) in pixels
- *
- */
- baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== "undefined" ? baseOptions.columnFooterHeight : 30;
- baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== "undefined" ? baseOptions.gridFooterHeight : 30;
-
- baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== "undefined" ? baseOptions.columnWidth : 50;
-
- /**
- * @ngdoc property
- * @name maxVisibleColumnCount
- * @propertyOf ui.grid.class:GridOptions
- * @description Defaults to 200
- *
- */
- baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== "undefined" ? baseOptions.maxVisibleColumnCount : 200;
-
- /**
- * @ngdoc property
- * @name virtualizationThreshold
- * @propertyOf ui.grid.class:GridOptions
- * @description Turn virtualization on when number of data elements goes over this number, defaults to 20
- */
- baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== "undefined" ? baseOptions.virtualizationThreshold : 20;
-
- /**
- * @ngdoc property
- * @name columnVirtualizationThreshold
- * @propertyOf ui.grid.class:GridOptions
- * @description Turn virtualization on when number of columns goes over this number, defaults to 10
- */
- baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== "undefined" ? baseOptions.columnVirtualizationThreshold : 10;
-
- /**
- * @ngdoc property
- * @name excessRows
- * @propertyOf ui.grid.class:GridOptions
- * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.
- * Defaults to 4
- */
- baseOptions.excessRows = typeof(baseOptions.excessRows) !== "undefined" ? baseOptions.excessRows : 4;
- /**
- * @ngdoc property
- * @name scrollThreshold
- * @propertyOf ui.grid.class:GridOptions
- * @description Defaults to 4
- */
- baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== "undefined" ? baseOptions.scrollThreshold : 4;
-
- /**
- * @ngdoc property
- * @name excessColumns
- * @propertyOf ui.grid.class:GridOptions
- * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.
- * Defaults to 4
- */
- baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== "undefined" ? baseOptions.excessColumns : 4;
- /**
- * @ngdoc property
- * @name horizontalScrollThreshold
- * @propertyOf ui.grid.class:GridOptions
- * @description Defaults to 4
- */
- baseOptions.horizontalScrollThreshold = typeof(baseOptions.horizontalScrollThreshold) !== "undefined" ? baseOptions.horizontalScrollThreshold : 2;
-
-
- /**
- * @ngdoc property
- * @name aggregationCalcThrottle
- * @propertyOf ui.grid.class:GridOptions
- * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms
- */
- baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== "undefined" ? baseOptions.aggregationCalcThrottle : 500;
-
- /**
- * @ngdoc property
- * @name wheelScrollThrottle
- * @propertyOf ui.grid.class:GridOptions
- * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms
- */
- baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== "undefined" ? baseOptions.wheelScrollThrottle : 70;
-
-
- /**
- * @ngdoc property
- * @name scrollDebounce
- * @propertyOf ui.grid.class:GridOptions
- * @description Default time in milliseconds to debounce scroll events, defaults to 300ms
- */
- baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== "undefined" ? baseOptions.scrollDebounce : 300;
-
- /**
- * @ngdoc boolean
- * @name enableSorting
- * @propertyOf ui.grid.class:GridOptions
- * @description True by default. When enabled, this setting adds sort
- * widgets to the column headers, allowing sorting of the data for the entire grid.
- * Sorting can then be disabled on individual columns using the columnDefs.
- */
- baseOptions.enableSorting = baseOptions.enableSorting !== false;
-
- /**
- * @ngdoc boolean
- * @name enableFiltering
- * @propertyOf ui.grid.class:GridOptions
- * @description False by default. When enabled, this setting adds filter
- * boxes to each column header, allowing filtering within the column for the entire grid.
- * Filtering can then be disabled on individual columns using the columnDefs.
- */
- baseOptions.enableFiltering = baseOptions.enableFiltering === true;
-
- /**
- * @ngdoc boolean
- * @name enableColumnMenus
- * @propertyOf ui.grid.class:GridOptions
- * @description True by default. When enabled, this setting displays a column
- * menu within each column.
- */
- baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;
-
- /**
- * @ngdoc boolean
- * @name enableVerticalScrollbar
- * @propertyOf ui.grid.class:GridOptions
- * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the vertical scrollbar for the grid.
- * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
- */
- baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== "undefined" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;
-
- /**
- * @ngdoc boolean
- * @name enableHorizontalScrollbar
- * @propertyOf ui.grid.class:GridOptions
- * @description uiGridConstants.scrollbars.ALWAYS by default. This settings controls the horizontal scrollbar for the grid.
- * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER
- */
- baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== "undefined" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;
-
- /**
- * @ngdoc boolean
- * @name enableMinHeightCheck
- * @propertyOf ui.grid.class:GridOptions
- * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display
- * at least one row of data. If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number
- * of rows.
- */
- baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;
-
- /**
- * @ngdoc boolean
- * @name minimumColumnSize
- * @propertyOf ui.grid.class:GridOptions
- * @description Columns can't be smaller than this, defaults to 10 pixels
- */
- baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== "undefined" ? baseOptions.minimumColumnSize : 10;
-
- /**
- * @ngdoc function
- * @name rowEquality
- * @methodOf ui.grid.class:GridOptions
- * @description By default, rows are compared using object equality. This option can be overridden
- * to compare on any data item property or function
- * @param {object} entityA First Data Item to compare
- * @param {object} entityB Second Data Item to compare
- */
- baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {
- return entityA === entityB;
- };
-
- /**
- * @ngdoc string
- * @name headerTemplate
- * @propertyOf ui.grid.class:GridOptions
- * @description Null by default. When provided, this setting uses a custom header
- * template, rather than the default template. Can be set to either the name of a template file:
- * <pre> $scope.gridOptions.headerTemplate = 'header_template.html';</pre>
- * inline html
- * <pre> $scope.gridOptions.headerTemplate = '<div class="ui-grid-top-panel" style="text-align: center">I am a Custom Grid Header</div>'</pre>
- * or the id of a precompiled template (TBD how to use this).
- * </br>Refer to the custom header tutorial for more information.
- * If you want no header at all, you can set to an empty div:
- * <pre> $scope.gridOptions.headerTemplate = '<div></div>';</pre>
- *
- * If you want to only have a static header, then you can set to static content. If
- * you want to tailor the existing column headers, then you should look at the
- * current 'ui-grid-header.html' template in github as your starting point.
- *
- */
- baseOptions.headerTemplate = baseOptions.headerTemplate || null;
-
- /**
- * @ngdoc string
- * @name footerTemplate
- * @propertyOf ui.grid.class:GridOptions
- * @description (optional) ui-grid/ui-grid-footer by default. This footer shows the per-column
- * aggregation totals.
- * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html
- * <pre>'<div class="ui-grid-bottom-panel" style="text-align: center">I am a Custom Grid Footer</div>'</pre>, or the id
- * of a precompiled template (TBD how to use this). Refer to the custom footer tutorial for more information.
- */
- baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';
-
- /**
- * @ngdoc string
- * @name gridFooterTemplate
- * @propertyOf ui.grid.class:GridOptions
- * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the
- * total items at the bottom of the grid, and the selected items if selection is enabled.
- */
- baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';
-
- /**
- * @ngdoc string
- * @name rowTemplate
- * @propertyOf ui.grid.class:GridOptions
- * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a
- * custom row template. Can be set to either the name of a template file:
- * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>
- * inline html
- * <pre> $scope.gridOptions.rowTemplate = '<div style="background-color: aquamarine" ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ui-grid-cell></div>';</pre>
- * or the id of a precompiled template (TBD how to use this) can be provided.
- * </br>Refer to the custom row template tutorial for more information.
- */
- baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';
-
- /**
- * @ngdoc object
- * @name appScopeProvider
- * @propertyOf ui.grid.class:GridOptions
- * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope
- * this property allows you to assign any reference you want to grid.appScope
- */
- baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;
-
- return baseOptions;
- }
- };
-
-
-}]);
-
-})();
-
-(function(){
-
-angular.module('ui.grid')
-
- /**
- * @ngdoc function
- * @name ui.grid.class:GridRenderContainer
- * @description The grid has render containers, allowing the ability to have pinned columns. If the grid
- * is right-to-left then there may be a right render container, if left-to-right then there may
- * be a left render container. There is always a body render container.
- * @param {string} name The name of the render container ('body', 'left', or 'right')
- * @param {Grid} grid the grid the render container is in
- * @param {object} options the render container options
- */
-.factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
- function GridRenderContainer(name, grid, options) {
- var self = this;
-
- // if (gridUtil.type(grid) !== 'Grid') {
- // throw new Error('Grid argument is not a Grid object');
- // }
-
- self.name = name;
-
- self.grid = grid;
-
- // self.rowCache = [];
- // self.columnCache = [];
-
- self.visibleRowCache = [];
- self.visibleColumnCache = [];
-
- self.renderedRows = [];
- self.renderedColumns = [];
-
- self.prevScrollTop = 0;
- self.prevScrolltopPercentage = 0;
- self.prevRowScrollIndex = 0;
-
- self.prevScrollLeft = 0;
- self.prevScrollleftPercentage = 0;
- self.prevColumnScrollIndex = 0;
-
- self.columnStyles = "";
-
- self.viewportAdjusters = [];
-
- /**
- * @ngdoc boolean
- * @name hasHScrollbar
- * @propertyOf ui.grid.class:GridRenderContainer
- * @description flag to signal that container has a horizontal scrollbar
- */
- self.hasHScrollbar = false;
-
- /**
- * @ngdoc boolean
- * @name hasVScrollbar
- * @propertyOf ui.grid.class:GridRenderContainer
- * @description flag to signal that container has a vertical scrollbar
- */
- self.hasVScrollbar = false;
-
- /**
- * @ngdoc boolean
- * @name canvasHeightShouldUpdate
- * @propertyOf ui.grid.class:GridRenderContainer
- * @description flag to signal that container should recalculate the canvas size
- */
- self.canvasHeightShouldUpdate = true;
-
- /**
- * @ngdoc boolean
- * @name canvasHeight
- * @propertyOf ui.grid.class:GridRenderContainer
- * @description last calculated canvas height value
- */
- self.$$canvasHeight = 0;
-
- if (options && angular.isObject(options)) {
- angular.extend(self, options);
- }
-
- grid.registerStyleComputation({
- priority: 5,
- func: function () {
- self.updateColumnWidths();
- return self.columnStyles;
- }
- });
- }
-
-
- GridRenderContainer.prototype.reset = function reset() {
- // this.rowCache.length = 0;
- // this.columnCache.length = 0;
-
- this.visibleColumnCache.length = 0;
- this.visibleRowCache.length = 0;
-
- this.renderedRows.length = 0;
- this.renderedColumns.length = 0;
- };
-
- // TODO(c0bra): calculate size?? Should this be in a stackable directive?
-
-
- GridRenderContainer.prototype.containsColumn = function (col) {
- return this.visibleColumnCache.indexOf(col) !== -1;
- };
-
- GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {
- var self = this;
- var minRows = 0;
- var rowAddedHeight = 0;
- var viewPortHeight = self.getViewportHeight();
- for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {
- rowAddedHeight += self.visibleRowCache[i].height;
- minRows++;
- }
- return minRows;
- };
-
- GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {
- var self = this;
- var viewportWidth = this.getViewportWidth();
-
- var min = 0;
- var totalWidth = 0;
- // self.columns.forEach(function(col, i) {
- for (var i = 0; i < self.visibleColumnCache.length; i++) {
- var col = self.visibleColumnCache[i];
-
- if (totalWidth < viewportWidth) {
- totalWidth += col.drawnWidth ? col.drawnWidth : 0;
- min++;
- }
- else {
- var currWidth = 0;
- for (var j = i; j >= i - min; j--) {
- currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;
- }
- if (currWidth < viewportWidth) {
- min++;
- }
- }
- }
-
- return min;
- };
-
- GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {
- return this.visibleRowCache.length;
- };
-
- /**
- * @ngdoc function
- * @name registerViewportAdjuster
- * @methodOf ui.grid.class:GridRenderContainer
- * @description Registers an adjuster to the render container's available width or height. Adjusters are used
- * to tell the render container that there is something else consuming space, and to adjust it's size
- * appropriately.
- * @param {function} func the adjuster function we want to register
- */
-
- GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
- this.viewportAdjusters.push(func);
- };
-
- /**
- * @ngdoc function
- * @name removeViewportAdjuster
- * @methodOf ui.grid.class:GridRenderContainer
- * @description Removes an adjuster, should be used when your element is destroyed
- * @param {function} func the adjuster function we want to remove
- */
- GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {
- var idx = this.viewportAdjusters.indexOf(func);
-
- if (idx > -1) {
- this.viewportAdjusters.splice(idx, 1);
- }
- };
-
- /**
- * @ngdoc function
- * @name getViewportAdjustment
- * @methodOf ui.grid.class:GridRenderContainer
- * @description Gets the adjustment based on the viewportAdjusters.
- * @returns {object} a hash of { height: x, width: y }. Usually the values will be negative
- */
- GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {
- var self = this;
-
- var adjustment = { height: 0, width: 0 };
-
- self.viewportAdjusters.forEach(function (func) {
- adjustment = func.call(this, adjustment);
- });
-
- return adjustment;
- };
-
- GridRenderContainer.prototype.getMargin = function getMargin(side) {
- var self = this;
-
- var amount = 0;
-
- self.viewportAdjusters.forEach(function (func) {
- var adjustment = func.call(this, { height: 0, width: 0 });
-
- if (adjustment.side && adjustment.side === side) {
- amount += adjustment.width * -1;
- }
- });
-
- return amount;
- };
-
- GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {
- var self = this;
-
- var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;
-
- var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;
-
-
- var adjustment = self.getViewportAdjustment();
-
- viewPortHeight = viewPortHeight + adjustment.height;
-
- return viewPortHeight;
- };
-
- GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {
- var self = this;
-
- var viewportWidth = self.grid.gridWidth;
-
- //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
- // viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;
- //}
-
- // var viewportWidth = 0;\
- // self.visibleColumnCache.forEach(function (column) {
- // viewportWidth += column.drawnWidth;
- // });
-
- var adjustment = self.getViewportAdjustment();
-
- viewportWidth = viewportWidth + adjustment.width;
-
- return viewportWidth;
- };
-
- GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
- var self = this;
-
- var viewportWidth = this.getViewportWidth();
-
- //if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined && self.grid.verticalScrollbarWidth > 0) {
- // viewPortWidth = viewPortWidth + self.grid.verticalScrollbarWidth;
- //}
-
- // var adjustment = self.getViewportAdjustment();
- // viewPortWidth = viewPortWidth + adjustment.width;
-
- return viewportWidth;
- };
-
-
- /**
- * @ngdoc function
- * @name getCanvasHeight
- * @methodOf ui.grid.class:GridRenderContainer
- * @description Returns the total canvas height. Only recalculates if canvasHeightShouldUpdate = false
- * @returns {number} total height of all the visible rows in the container
- */
- GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {
- var self = this;
-
- if (!self.canvasHeightShouldUpdate) {
- return self.$$canvasHeight;
- }
-
- var oldCanvasHeight = self.$$canvasHeight;
-
- self.$$canvasHeight = 0;
-
- self.visibleRowCache.forEach(function(row){
- self.$$canvasHeight += row.height;
- });
-
-
- self.canvasHeightShouldUpdate = false;
-
- self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);
-
- return self.$$canvasHeight;
- };
-
- GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {
- return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight;
- };
-
- GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {
- var self = this;
-
- var ret = self.canvasWidth;
-
- return ret;
- };
-
- GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {
- this.renderedRows.length = newRows.length;
- for (var i = 0; i < newRows.length; i++) {
- this.renderedRows[i] = newRows[i];
- }
- };
-
- GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {
- var self = this;
-
- // OLD:
- this.renderedColumns.length = newColumns.length;
- for (var i = 0; i < newColumns.length; i++) {
- this.renderedColumns[i] = newColumns[i];
- }
-
- this.updateColumnOffset();
- };
-
- GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {
- // Calculate the width of the columns on the left side that are no longer rendered.
- // That will be the offset for the columns as we scroll horizontally.
- var hiddenColumnsWidth = 0;
- for (var i = 0; i < this.currentFirstColumn; i++) {
- hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;
- }
-
- this.columnOffset = hiddenColumnsWidth;
- };
-
- GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {
- var vertScrollPercentage = -1;
-
- if (newScrollTop !== this.prevScrollTop) {
- var yDiff = newScrollTop - this.prevScrollTop;
-
- if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }
- if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }
-
- var vertScrollLength = this.getVerticalScrollLength();
-
- vertScrollPercentage = newScrollTop / vertScrollLength;
-
- // console.log('vert', vertScrollPercentage, newScrollTop, vertScrollLength);
-
- if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }
- if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }
-
- this.adjustScrollVertical(newScrollTop, vertScrollPercentage);
- return vertScrollPercentage;
- }
- };
-
- GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft){
- var horizScrollPercentage = -1;
-
- // Handle RTL here
-
- if (newScrollLeft !== this.prevScrollLeft) {
- var xDiff = newScrollLeft - this.prevScrollLeft;
-
- if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }
- if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }
-
- var horizScrollLength = (this.canvasWidth - this.getViewportWidth());
- if (horizScrollLength !== 0) {
- horizScrollPercentage = newScrollLeft / horizScrollLength;
- }
- else {
- horizScrollPercentage = 0;
- }
-
- this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);
- return horizScrollPercentage;
- }
- };
-
- GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {
- if (this.prevScrollTop === scrollTop && !force) {
- return;
- }
-
- if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {
- scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;
- }
-
- this.adjustRows(scrollTop, scrollPercentage, false);
-
- this.prevScrollTop = scrollTop;
- this.prevScrolltopPercentage = scrollPercentage;
-
- this.grid.queueRefresh();
- };
-
- GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {
- if (this.prevScrollLeft === scrollLeft && !force) {
- return;
- }
-
- if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {
- scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;
- }
-
- this.adjustColumns(scrollLeft, scrollPercentage);
-
- this.prevScrollLeft = scrollLeft;
- this.prevScrollleftPercentage = scrollPercentage;
-
- this.grid.queueRefresh();
- };
-
- GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {
- var self = this;
-
- var minRows = self.minRowsToRender();
-
- var rowCache = self.visibleRowCache;
-
- var maxRowIndex = rowCache.length - minRows;
-
- // console.log('scroll%1', scrollPercentage);
-
- // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided
- if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {
- scrollPercentage = scrollTop / self.getVerticalScrollLength();
- }
-
- var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));
-
- // console.log('maxRowIndex / scroll%', maxRowIndex, scrollPercentage, rowIndex);
-
- // Define a max row index that we can't scroll past
- if (rowIndex > maxRowIndex) {
- rowIndex = maxRowIndex;
- }
-
- var newRange = [];
- if (rowCache.length > self.grid.options.virtualizationThreshold) {
- if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {
- // Have we hit the threshold going down?
- if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
- return;
- }
- //Have we hit the threshold going up?
- if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
- return;
- }
- }
- var rangeStart = {};
- var rangeEnd = {};
-
- rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);
- rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);
-
- newRange = [rangeStart, rangeEnd];
- }
- else {
- var maxLen = self.visibleRowCache.length;
- newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];
- }
-
- self.updateViewableRowRange(newRange);
-
- self.prevRowScrollIndex = rowIndex;
- };
-
- GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {
- var self = this;
-
- var minCols = self.minColumnsToRender();
-
- var columnCache = self.visibleColumnCache;
- var maxColumnIndex = columnCache.length - minCols;
-
- // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided
- if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {
- var horizScrollLength = (self.getCanvasWidth() - self.getViewportWidth());
- scrollPercentage = scrollLeft / horizScrollLength;
- }
-
- var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));
-
- // Define a max row index that we can't scroll past
- if (colIndex > maxColumnIndex) {
- colIndex = maxColumnIndex;
- }
-
- var newRange = [];
- if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {
- /* Commented the following lines because otherwise the moved column wasn't visible immediately on the new position
- * in the case of many columns with horizontal scroll, one had to scroll left or right and then return in order to see it
- // Have we hit the threshold going down?
- if (self.prevScrollLeft < scrollLeft && colIndex < self.prevColumnScrollIndex + self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
- return;
- }
- //Have we hit the threshold going up?
- if (self.prevScrollLeft > scrollLeft && colIndex > self.prevColumnScrollIndex - self.grid.options.horizontalScrollThreshold && colIndex < maxColumnIndex) {
- return;
- }*/
-
- var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);
- var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);
-
- newRange = [rangeStart, rangeEnd];
- }
- else {
- var maxLen = self.visibleColumnCache.length;
-
- newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];
- }
-
- self.updateViewableColumnRange(newRange);
-
- self.prevColumnScrollIndex = colIndex;
- };
-
- // Method for updating the visible rows
- GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {
- // Slice out the range of rows from the data
- // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);
- var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);
-
- // Define the top-most rendered row
- this.currentTopRow = renderedRange[0];
-
- this.setRenderedRows(rowArr);
- };
-
- // Method for updating the visible columns
- GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {
- // Slice out the range of rows from the data
- // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);
- var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);
-
- // Define the left-most rendered columns
- this.currentFirstColumn = renderedRange[0];
-
- this.setRenderedColumns(columnArr);
- };
-
- GridRenderContainer.prototype.headerCellWrapperStyle = function () {
- var self = this;
-
- if (self.currentFirstColumn !== 0) {
- var offset = self.columnOffset;
-
- if (self.grid.isRTL()) {
- return { 'margin-right': offset + 'px' };
- }
- else {
- return { 'margin-left': offset + 'px' };
- }
- }
-
- return null;
- };
-
- /**
- * @ngdoc boolean
- * @name updateColumnWidths
- * @propertyOf ui.grid.class:GridRenderContainer
- * @description Determine the appropriate column width of each column across all render containers.
- *
- * Column width is easy when each column has a specified width. When columns are variable width (i.e.
- * have an * or % of the viewport) then we try to calculate so that things fit in. The problem is that
- * we have multiple render containers, and we don't want one render container to just take the whole viewport
- * when it doesn't need to - we want things to balance out across the render containers.
- *
- * To do this, we use this method to calculate all the renderContainers, recognising that in a given render
- * cycle it'll get called once per render container, so it needs to return the same values each time.
- *
- * The constraints on this method are therefore:
- * - must return the same value when called multiple times, to do this it needs to rely on properties of the
- * columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)
- *
- * The general logic of this method is:
- * - calculate our total available width
- * - look at all the columns across all render containers, and work out which have widths and which have
- * constraints such as % or * or something else
- * - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array
- * - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max
- * - for those with manual width (in pixels) we set the drawnWidth to the specified width
- * - we end up with an asterisks array still to process
- * - we look at our remaining width. If it's greater than zero, we divide it up among the asterisk columns, then process
- * them for min and max width constraints
- * - if it's zero or less, we set the asterisk columns to their minimum widths
- * - we use parseInt quite a bit, as we try to make all our column widths integers
- */
- GridRenderContainer.prototype.updateColumnWidths = function () {
- var self = this;
-
- var asterisksArray = [],
- asteriskNum = 0,
- usedWidthSum = 0,
- ret = '';
-
- // Get the width of the viewport
- var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;
-
- // get all the columns across all render containers, we have to calculate them all or one render container
- // could consume the whole viewport
- var columnCache = [];
- angular.forEach(self.grid.renderContainers, function( container, name){
- columnCache = columnCache.concat(container.visibleColumnCache);
- });
-
- // look at each column, process any manual values or %, put the * into an array to look at later
- columnCache.forEach(function(column, i) {
- var width = 0;
- // Skip hidden columns
- if (!column.visible) { return; }
-
- if (angular.isNumber(column.width)) {
- // pixel width, set to this value
- width = parseInt(column.width, 10);
- usedWidthSum = usedWidthSum + width;
- column.drawnWidth = width;
-
- } else if (gridUtil.endsWith(column.width, "%")) {
- // percentage width, set to percentage of the viewport
- width = parseInt(parseInt(column.width.replace(/%/g, ''), 10) / 100 * availableWidth);
-
- if ( width > column.maxWidth ){
- width = column.maxWidth;
- }
-
- if ( width < column.minWidth ){
- width = column.minWidth;
- }
-
- usedWidthSum = usedWidthSum + width;
- column.drawnWidth = width;
- } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {
- // is an asterisk column, the gridColumn already checked the string consists only of '****'
- asteriskNum = asteriskNum + column.width.length;
- asterisksArray.push(column);
- }
- });
-
- // Get the remaining width (available width subtracted by the used widths sum)
- var remainingWidth = availableWidth - usedWidthSum;
-
- var i, column, colWidth;
-
- if (asterisksArray.length > 0) {
- // the width that each asterisk value would be assigned (this can be negative)
- var asteriskVal = remainingWidth / asteriskNum;
-
- asterisksArray.forEach(function( column ){
- var width = parseInt(column.width.length * asteriskVal, 10);
-
- if ( width > column.maxWidth ){
- width = column.maxWidth;
- }
-
- if ( width < column.minWidth ){
- width = column.minWidth;
- }
-
- usedWidthSum = usedWidthSum + width;
- column.drawnWidth = width;
- });
- }
-
- // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
- // calculated widths would have the grid narrower than the available space,
- // dole the remainder out one by one to make everything fit
- var processColumnUpwards = function(column){
- if ( column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
- column.drawnWidth++;
- usedWidthSum++;
- leftoverWidth--;
- columnsToChange = true;
- }
- };
-
- var leftoverWidth = availableWidth - usedWidthSum;
- var columnsToChange = true;
-
- while (leftoverWidth > 0 && columnsToChange) {
- columnsToChange = false;
- asterisksArray.forEach(processColumnUpwards);
- }
-
- // We can end up with too much width even though some columns aren't at their max width, in this situation
- // we can trim the columns a little
- var processColumnDownwards = function(column){
- if ( column.drawnWidth > column.minWidth && excessWidth > 0) {
- column.drawnWidth--;
- usedWidthSum--;
- excessWidth--;
- columnsToChange = true;
- }
- };
-
- var excessWidth = usedWidthSum - availableWidth;
- columnsToChange = true;
-
- while (excessWidth > 0 && columnsToChange) {
- columnsToChange = false;
- asterisksArray.forEach(processColumnDownwards);
- }
-
-
- // all that was across all the renderContainers, now we need to work out what that calculation decided for
- // our renderContainer
- var canvasWidth = 0;
- self.visibleColumnCache.forEach(function(column){
- if ( column.visible ){
- canvasWidth = canvasWidth + column.drawnWidth;
- }
- });
-
- // Build the CSS
- columnCache.forEach(function (column) {
- ret = ret + column.getColClassDefinition();
- });
-
- self.canvasWidth = canvasWidth;
-
- // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
- // return ret;
-
- // Set this render container's column styles so they can be used in style computation
- this.columnStyles = ret;
- };
-
- GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {
- return this.grid.options.enableHorizontalScrollbar && !this.hasHScrollbar && !this.grid.disableScrolling;
- };
-
- GridRenderContainer.prototype.getViewportStyle = function () {
- var self = this;
- var styles = {};
-
- self.hasHScrollbar = false;
- self.hasVScrollbar = false;
-
- if (self.grid.disableScrolling) {
- styles['overflow-x'] = 'hidden';
- styles['overflow-y'] = 'hidden';
- return styles;
- }
-
- if (self.name === 'body') {
- self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;
- if (!self.grid.isRTL()) {
- if (!self.grid.hasRightContainerColumns()) {
- self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
- }
- }
- else {
- if (!self.grid.hasLeftContainerColumns()) {
- self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
- }
- }
- }
- else if (self.name === 'left') {
- self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
- }
- else {
- self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
- }
-
- styles['overflow-x'] = self.hasHScrollbar ? 'scroll' : 'hidden';
- styles['overflow-y'] = self.hasVScrollbar ? 'scroll' : 'hidden';
-
-
- return styles;
-
-
- };
-
- return GridRenderContainer;
-}]);
-
-})();
-
-(function(){
-
-angular.module('ui.grid')
-.factory('GridRow', ['gridUtil', function(gridUtil) {
-
- /**
- * @ngdoc function
- * @name ui.grid.class:GridRow
- * @description GridRow is the viewModel for one logical row on the grid. A grid Row is not necessarily a one-to-one
- * relation to gridOptions.data.
- * @param {object} entity the array item from GridOptions.data
- * @param {number} index the current position of the row in the array
- * @param {Grid} reference to the parent grid
- */
- function GridRow(entity, index, grid) {
-
- /**
- * @ngdoc object
- * @name grid
- * @propertyOf ui.grid.class:GridRow
- * @description A reference back to the grid
- */
- this.grid = grid;
-
- /**
- * @ngdoc object
- * @name entity
- * @propertyOf ui.grid.class:GridRow
- * @description A reference to an item in gridOptions.data[]
- */
- this.entity = entity;
-
- /**
- * @ngdoc object
- * @name uid
- * @propertyOf ui.grid.class:GridRow
- * @description UniqueId of row
- */
- this.uid = gridUtil.nextUid();
-
- /**
- * @ngdoc object
- * @name visible
- * @propertyOf ui.grid.class:GridRow
- * @description If true, the row will be rendered
- */
- // Default to true
- this.visible = true;
-
-
- this.$$height = grid.options.rowHeight;
-
- }
-
- /**
- * @ngdoc object
- * @name height
- * @propertyOf ui.grid.class:GridRow
- * @description height of each individual row. changing the height will flag all
- * row renderContainers to recalculate their canvas height
- */
- Object.defineProperty(GridRow.prototype, 'height', {
- get: function() {
- return this.$$height;
- },
- set: function(height) {
- if (height !== this.$$height) {
- this.grid.updateCanvasHeight();
- this.$$height = height;
- }
- }
- });
-
- /**
- * @ngdoc function
- * @name getQualifiedColField
- * @methodOf ui.grid.class:GridRow
- * @description returns the qualified field name as it exists on scope
- * ie: row.entity.fieldA
- * @param {GridCol} col column instance
- * @returns {string} resulting name that can be evaluated on scope
- */
- GridRow.prototype.getQualifiedColField = function(col) {
- return 'row.' + this.getEntityQualifiedColField(col);
- };
-
- /**
- * @ngdoc function
- * @name getEntityQualifiedColField
- * @methodOf ui.grid.class:GridRow
- * @description returns the qualified field name minus the row path
- * ie: entity.fieldA
- * @param {GridCol} col column instance
- * @returns {string} resulting name that can be evaluated against a row
- */
- GridRow.prototype.getEntityQualifiedColField = function(col) {
- return gridUtil.preEval('entity.' + col.field);
- };
-
-
- /**
- * @ngdoc function
- * @name setRowInvisible
- * @methodOf ui.grid.class:GridRow
- * @description Sets an override on the row that forces it to always
- * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
- *
- * This method can be called from the api, passing in the gridRow we want
- * altered. It should really work by calling gridRow.setRowInvisible, but that's
- * not the way I coded it, and too late to change now. Changed to just call
- * the internal function row.setThisRowInvisible().
- *
- * @param {GridRow} row the row we want to set to invisible
- *
- */
- GridRow.prototype.setRowInvisible = function ( row ) {
- if (row && row.setThisRowInvisible){
- row.setThisRowInvisible( 'user' );
- }
- };
-
-
- /**
- * @ngdoc function
- * @name clearRowInvisible
- * @methodOf ui.grid.class:GridRow
- * @description Clears an override on the row that forces it to always
- * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
- *
- * This method can be called from the api, passing in the gridRow we want
- * altered. It should really work by calling gridRow.clearRowInvisible, but that's
- * not the way I coded it, and too late to change now. Changed to just call
- * the internal function row.clearThisRowInvisible().
- *
- * @param {GridRow} row the row we want to clear the invisible flag
- *
- */
- GridRow.prototype.clearRowInvisible = function ( row ) {
- if (row && row.clearThisRowInvisible){
- row.clearThisRowInvisible( 'user' );
- }
- };
-
-
- /**
- * @ngdoc function
- * @name setThisRowInvisible
- * @methodOf ui.grid.class:GridRow
- * @description Sets an override on the row that forces it to always
- * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility
- *
- * @param {string} reason the reason (usually the module) for the row to be invisible.
- * E.g. grouping, user, filter
- * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
- */
- GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {
- if ( !this.invisibleReason ){
- this.invisibleReason = {};
- }
- this.invisibleReason[reason] = true;
- this.evaluateRowVisibility( fromRowsProcessor);
- };
-
-
- /**
- * @ngdoc function
- * @name clearRowInvisible
- * @methodOf ui.grid.class:GridRow
- * @description Clears any override on the row visibility, returning it
- * to normal visibility calculations. Emits the rowsVisibleChanged
- * event
- *
- * @param {string} reason the reason (usually the module) for the row to be invisible.
- * E.g. grouping, user, filter
- * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
- */
- GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {
- if (typeof(this.invisibleReason) !== 'undefined' ) {
- delete this.invisibleReason[reason];
- }
- this.evaluateRowVisibility( fromRowsProcessor );
- };
-
-
- /**
- * @ngdoc function
- * @name evaluateRowVisibility
- * @methodOf ui.grid.class:GridRow
- * @description Determines whether the row should be visible based on invisibleReason,
- * and if it changes the row visibility, then emits the rowsVisibleChanged event.
- *
- * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.
- * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the
- * row processor does that already
- */
- GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {
- var newVisibility = true;
- if ( typeof(this.invisibleReason) !== 'undefined' ){
- angular.forEach(this.invisibleReason, function( value, key ){
- if ( value ){
- newVisibility = false;
- }
- });
- }
-
- if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ){
- this.visible = newVisibility;
- if ( !fromRowProcessor ){
- this.grid.queueGridRefresh();
- this.grid.api.core.raise.rowsVisibleChanged(this);
- }
- }
- };
-
-
- return GridRow;
-}]);
-
-})();
-
-(function(){
- 'use strict';
- /**
- * @ngdoc object
- * @name ui.grid.class:GridRowColumn
- * @param {GridRow} row The row for this pair
- * @param {GridColumn} column The column for this pair
- * @description A row and column pair that represents the intersection of these two entities.
- * Must be instantiated as a constructor using the `new` keyword.
- */
- angular.module('ui.grid')
- .factory('GridRowColumn', ['$parse', '$filter',
- function GridRowColumnFactory($parse, $filter){
- var GridRowColumn = function GridRowColumn(row, col) {
- if ( !(this instanceof GridRowColumn)){
- throw "Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";
- }
-
- /**
- * @ngdoc object
- * @name row
- * @propertyOf ui.grid.class:GridRowColumn
- * @description {@link ui.grid.class:GridRow }
- */
- this.row = row;
- /**
- * @ngdoc object
- * @name col
- * @propertyOf ui.grid.class:GridRowColumn
- * @description {@link ui.grid.class:GridColumn }
- */
- this.col = col;
- };
-
- /**
- * @ngdoc function
- * @name getIntersectionValueRaw
- * @methodOf ui.grid.class:GridRowColumn
- * @description Gets the intersection of where the row and column meet.
- * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
- * If the column has a cellFilter this will NOT return the filtered value.
- */
- GridRowColumn.prototype.getIntersectionValueRaw = function(){
- var getter = $parse(this.row.getEntityQualifiedColField(this.col));
- var context = this.row;
- return getter(context);
- };
- /**
- * @ngdoc function
- * @name getIntersectionValueFiltered
- * @methodOf ui.grid.class:GridRowColumn
- * @description Gets the intersection of where the row and column meet.
- * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
- * If the column has a cellFilter this will also apply the filter to it and return the value that the filter displays.
- */
- GridRowColumn.prototype.getIntersectionValueFiltered = function(){
- var value = this.getIntersectionValueRaw();
- if (this.col.cellFilter && this.col.cellFilter !== ''){
- var getFilterIfExists = function(filterName){
- try {
- return $filter(filterName);
- } catch (e){
- return null;
- }
- };
- var filter = getFilterIfExists(this.col.cellFilter);
- if (filter) { // Check if this is filter name or a filter string
- value = filter(value);
- } else { // We have the template version of a filter so we need to parse it apart
- // Get the filter params out using a regex
- // Test out this regex here https://regex101.com/r/rC5eR5/2
- var re = /([^:]*):([^:]*):?([\s\S]+)?/;
- var matches;
- if ((matches = re.exec(this.col.cellFilter)) !== null) {
- // View your result using the matches-variable.
- // eg matches[0] etc.
- value = $filter(matches[1])(value, matches[2], matches[3]);
- }
- }
- }
- return value;
- };
- return GridRowColumn;
- }
- ]);
-})();
-
-(function () {
- angular.module('ui.grid')
- .factory('ScrollEvent', ['gridUtil', function (gridUtil) {
-
- /**
- * @ngdoc function
- * @name ui.grid.class:ScrollEvent
- * @description Model for all scrollEvents
- * @param {Grid} grid that owns the scroll event
- * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null
- * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null
- * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName
- */
- function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {
- var self = this;
- if (!grid) {
- throw new Error("grid argument is required");
- }
-
- /**
- * @ngdoc object
- * @name grid
- * @propertyOf ui.grid.class:ScrollEvent
- * @description A reference back to the grid
- */
- self.grid = grid;
-
-
-
- /**
- * @ngdoc object
- * @name source
- * @propertyOf ui.grid.class:ScrollEvent
- * @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources
- */
- self.source = source;
-
-
- /**
- * @ngdoc object
- * @name noDelay
- * @propertyOf ui.grid.class:ScrollEvent
- * @description most scroll events from the mouse or trackpad require delay to operate properly
- * set to false to eliminate delay. Useful for scroll events that the grid causes, such as scrolling to make a row visible.
- */
- self.withDelay = true;
-
- self.sourceRowContainer = sourceRowContainer;
- self.sourceColContainer = sourceColContainer;
-
- self.newScrollLeft = null;
- self.newScrollTop = null;
- self.x = null;
- self.y = null;
-
- self.verticalScrollLength = -9999999;
- self.horizontalScrollLength = -999999;
-
-
- /**
- * @ngdoc function
- * @name fireThrottledScrollingEvent
- * @methodOf ui.grid.class:ScrollEvent
- * @description fires a throttled event using grid.api.core.raise.scrollEvent
- */
- self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {
- self.grid.scrollContainers(sourceContainerId, self);
- }, self.grid.options.wheelScrollThrottle, {trailing: true});
-
- }
-
-
- /**
- * @ngdoc function
- * @name getNewScrollLeft
- * @methodOf ui.grid.class:ScrollEvent
- * @description returns newScrollLeft property if available; calculates a new value if it isn't
- */
- ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport){
- var self = this;
-
- if (!self.newScrollLeft){
- var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
-
- var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);
-
- var scrollXPercentage;
- if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {
- scrollXPercentage = self.x.percentage;
- }
- else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {
- scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;
- }
- else {
- throw new Error("No percentage or pixel value provided for scroll event X axis");
- }
-
- return Math.max(0, scrollXPercentage * scrollWidth);
- }
-
- return self.newScrollLeft;
- };
-
-
- /**
- * @ngdoc function
- * @name getNewScrollTop
- * @methodOf ui.grid.class:ScrollEvent
- * @description returns newScrollTop property if available; calculates a new value if it isn't
- */
- ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport){
- var self = this;
-
-
- if (!self.newScrollTop){
- var scrollLength = rowContainer.getVerticalScrollLength();
-
- var oldScrollTop = viewport[0].scrollTop;
-
- var scrollYPercentage;
- if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {
- scrollYPercentage = self.y.percentage;
- }
- else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {
- scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;
- }
- else {
- throw new Error("No percentage or pixel value provided for scroll event Y axis");
- }
-
- return Math.max(0, scrollYPercentage * scrollLength);
- }
-
- return self.newScrollTop;
- };
-
- ScrollEvent.prototype.atTop = function(scrollTop) {
- return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
- };
-
- ScrollEvent.prototype.atBottom = function(scrollTop) {
- return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
- };
-
- ScrollEvent.prototype.atLeft = function(scrollLeft) {
- return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);
- };
-
- ScrollEvent.prototype.atRight = function(scrollLeft) {
- return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);
- };
-
-
- ScrollEvent.Sources = {
- ViewPortScroll: 'ViewPortScroll',
- RenderContainerMouseWheel: 'RenderContainerMouseWheel',
- RenderContainerTouchMove: 'RenderContainerTouchMove',
- Other: 99
- };
-
- return ScrollEvent;
- }]);
-
-
-
-})();
-
-(function () {
- 'use strict';
- /**
- * @ngdoc object
- * @name ui.grid.service:gridClassFactory
- *
- * @description factory to return dom specific instances of a grid
- *
- */
- angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',
- function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {
-
- var service = {
- /**
- * @ngdoc method
- * @name createGrid
- * @methodOf ui.grid.service:gridClassFactory
- * @description Creates a new grid instance. Each instance will have a unique id
- * @param {object} options An object map of options to pass into the created grid instance.
- * @returns {Grid} grid
- */
- createGrid : function(options) {
- options = (typeof(options) !== 'undefined') ? options : {};
- options.id = gridUtil.newId();
- var grid = new Grid(options);
-
- // NOTE/TODO: rowTemplate should always be defined...
- if (grid.options.rowTemplate) {
- var rowTemplateFnPromise = $q.defer();
- grid.getRowTemplateFn = rowTemplateFnPromise.promise;
-
- gridUtil.getTemplate(grid.options.rowTemplate)
- .then(
- function (template) {
- var rowTemplateFn = $compile(template);
- rowTemplateFnPromise.resolve(rowTemplateFn);
- },
- function (res) {
- // Todo handle response error here?
- throw new Error("Couldn't fetch/use row template '" + grid.options.rowTemplate + "'");
- });
- }
-
- grid.registerColumnBuilder(service.defaultColumnBuilder);
-
- // Row builder for custom row templates
- grid.registerRowBuilder(service.rowTemplateAssigner);
-
- // Reset all rows to visible initially
- grid.registerRowsProcessor(function allRowsVisible(rows) {
- rows.forEach(function (row) {
- row.evaluateRowVisibility( true );
- }, 50);
-
- return rows;
- });
-
- grid.registerColumnsProcessor(function allColumnsVisible(columns) {
- columns.forEach(function (column) {
- column.visible = true;
- });
-
- return columns;
- }, 50);
-
- grid.registerColumnsProcessor(function(renderableColumns) {
- renderableColumns.forEach(function (column) {
- if (column.colDef.visible === false) {
- column.visible = false;
- }
- });
-
- return renderableColumns;
- }, 50);
-
-
- grid.registerRowsProcessor(grid.searchRows, 100);
-
- // Register the default row processor, it sorts rows by selected columns
- if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {
- grid.registerRowsProcessor(grid.options.externalSort, 200);
- }
- else {
- grid.registerRowsProcessor(grid.sortByColumn, 200);
- }
-
- return grid;
- },
-
- /**
- * @ngdoc function
- * @name defaultColumnBuilder
- * @methodOf ui.grid.service:gridClassFactory
- * @description Processes designTime column definitions and applies them to col for the
- * core grid features
- * @param {object} colDef reference to column definition
- * @param {GridColumn} col reference to gridCol
- * @param {object} gridOptions reference to grid options
- */
- defaultColumnBuilder: function (colDef, col, gridOptions) {
-
- var templateGetPromises = [];
-
- // Abstracts the standard template processing we do for every template type.
- var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {
- if ( !colDef[templateType] ){
- col[providedType] = defaultTemplate;
- } else {
- col[providedType] = colDef[templateType];
- }
-
- templateGetPromises.push(gridUtil.getTemplate(col[providedType])
- .then(
- function (template) {
- if ( angular.isFunction(template) ) { template = template(); }
- var tooltipCall = ( tooltipType === 'cellTooltip' ) ? 'col.cellTooltip(row,col)' : 'col.headerTooltip(col)';
- if ( tooltipType && col[tooltipType] === false ){
- template = template.replace(uiGridConstants.TOOLTIP, '');
- } else if ( tooltipType && col[tooltipType] ){
- template = template.replace(uiGridConstants.TOOLTIP, 'title="{{' + tooltipCall + ' CUSTOM_FILTERS }}"');
- }
-
- if ( filterType ){
- col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {
- return col[filterType] ? "|" + col[filterType] : "";
- });
- } else {
- col[templateType] = template;
- }
- },
- function (res) {
- throw new Error("Couldn't fetch/use colDef." + templateType + " '" + colDef[templateType] + "'");
- })
- );
-
- };
-
-
- /**
- * @ngdoc property
- * @name cellTemplate
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description a custom template for each cell in this column. The default
- * is ui-grid/uiGridCell. If you are using the cellNav feature, this template
- * must contain a div that can receive focus.
- *
- */
- processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );
- col.cellTemplatePromise = templateGetPromises[0];
-
- /**
- * @ngdoc property
- * @name headerCellTemplate
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description a custom template for the header for this column. The default
- * is ui-grid/uiGridHeaderCell
- *
- */
- processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );
-
- /**
- * @ngdoc property
- * @name footerCellTemplate
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description a custom template for the footer for this column. The default
- * is ui-grid/uiGridFooterCell
- *
- */
- processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );
-
- /**
- * @ngdoc property
- * @name filterHeaderTemplate
- * @propertyOf ui.grid.class:GridOptions.columnDef
- * @description a custom template for the filter input. The default is ui-grid/ui-grid-filter
- *
- */
- processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );
-
- // Create a promise for the compiled element function
- col.compiledElementFnDefer = $q.defer();
-
- return $q.all(templateGetPromises);
- },
-
-
- rowTemplateAssigner: function rowTemplateAssigner(row) {
- var grid = this;
-
- // Row has no template assigned to it
- if (!row.rowTemplate) {
- // Use the default row template from the grid
- row.rowTemplate = grid.options.rowTemplate;
-
- // Use the grid's function for fetching the compiled row template function
- row.getRowTemplateFn = grid.getRowTemplateFn;
- }
- // Row has its own template assigned
- else {
- // Create a promise for the compiled row template function
- var perRowTemplateFnPromise = $q.defer();
- row.getRowTemplateFn = perRowTemplateFnPromise.promise;
-
- // Get the row template
- gridUtil.getTemplate(row.rowTemplate)
- .then(function (template) {
- // Compile the template
- var rowTemplateFn = $compile(template);
-
- // Resolve the compiled template function promise
- perRowTemplateFnPromise.resolve(rowTemplateFn);
- },
- function (res) {
- // Todo handle response error here?
- throw new Error("Couldn't fetch/use row template '" + row.rowTemplate + "'");
- });
- }
-
- return row.getRowTemplateFn;
- }
- };
-
- //class definitions (moved to separate factories)
-
- return service;
- }]);
-
-})();
-
-(function() {
-
-var module = angular.module('ui.grid');
-
-function escapeRegExp(str) {
- return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
-}
-
-
-/**
- * @ngdoc service
- * @name ui.grid.service:rowSearcher
- *
- * @description Service for searching/filtering rows based on column value conditions.
- */
-module.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {
- var defaultCondition = uiGridConstants.filter.CONTAINS;
-
- var rowSearcher = {};
-
- /**
- * @ngdoc function
- * @name getTerm
- * @methodOf ui.grid.service:rowSearcher
- * @description Get the term from a filter
- * Trims leading and trailing whitespace
- * @param {object} filter object to use
- * @returns {object} Parsed term
- */
- rowSearcher.getTerm = function getTerm(filter) {
- if (typeof(filter.term) === 'undefined') { return filter.term; }
-
- var term = filter.term;
-
- // Strip leading and trailing whitespace if the term is a string
- if (typeof(term) === 'string') {
- term = term.trim();
- }
-
- return term;
- };
-
- /**
- * @ngdoc function
- * @name stripTerm
- * @methodOf ui.grid.service:rowSearcher
- * @description Remove leading and trailing asterisk (*) from the filter's term
- * @param {object} filter object to use
- * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
- */
- rowSearcher.stripTerm = function stripTerm(filter) {
- var term = rowSearcher.getTerm(filter);
-
- if (typeof(term) === 'string') {
- return escapeRegExp(term.replace(/(^\*|\*$)/g, ''));
- }
- else {
- return term;
- }
- };
-
-
- /**
- * @ngdoc function
- * @name guessCondition
- * @methodOf ui.grid.service:rowSearcher
- * @description Guess the condition for a filter based on its term
- * <br>
- * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).
- * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).
- * @param {object} filter object to use
- * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
- */
- rowSearcher.guessCondition = function guessCondition(filter) {
- if (typeof(filter.term) === 'undefined' || !filter.term) {
- return defaultCondition;
- }
-
- var term = rowSearcher.getTerm(filter);
-
- if (/\*/.test(term)) {
- var regexpFlags = '';
- if (!filter.flags || !filter.flags.caseSensitive) {
- regexpFlags += 'i';
- }
-
- var reText = term.replace(/(\\)?\*/g, function ($0, $1) { return $1 ? $0 : '[\\s\\S]*?'; });
- return new RegExp('^' + reText + '$', regexpFlags);
- }
- // Otherwise default to default condition
- else {
- return defaultCondition;
- }
- };
-
-
- /**
- * @ngdoc function
- * @name setupFilters
- * @methodOf ui.grid.service:rowSearcher
- * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),
- * do all the parsing and pre-processing and store that data into a new filters object. The object
- * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.
- *
- * We could use a forEach in here, since it's much less performance sensitive, but since we're using
- * for loops everywhere else in this module...
- *
- * @param {array} filters the filters from the column (col.filters or [col.filter])
- * @returns {array} An array of parsed/preprocessed filters
- */
- rowSearcher.setupFilters = function setupFilters( filters ){
- var newFilters = [];
-
- var filtersLength = filters.length;
- for ( var i = 0; i < filtersLength; i++ ){
- var filter = filters[i];
-
- if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ){
- var newFilter = {};
-
- var regexpFlags = '';
- if (!filter.flags || !filter.flags.caseSensitive) {
- regexpFlags += 'i';
- }
-
- if ( !gridUtil.isNullOrUndefined(filter.term) ){
- // it is possible to have noTerm. We don't need to copy that across, it was just a flag to avoid
- // getting the filter ignored if the filter was a function that didn't use a term
- newFilter.term = rowSearcher.stripTerm(filter);
- }
-
- if ( filter.condition ){
- newFilter.condition = filter.condition;
- } else {
- newFilter.condition = rowSearcher.guessCondition(filter);
- }
-
- newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );
-
- if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {
- newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);
- }
-
- if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {
- newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);
- }
-
- if (newFilter.condition === uiGridConstants.filter.CONTAINS) {
- newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);
- }
-
- if (newFilter.condition === uiGridConstants.filter.EXACT) {
- newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);
- }
-
- newFilters.push(newFilter);
- }
- }
- return newFilters;
- };
-
-
- /**
- * @ngdoc function
- * @name runColumnFilter
- * @methodOf ui.grid.service:rowSearcher
- * @description Runs a single pre-parsed filter against a cell, returning true
- * if the cell matches that one filter.
- *
- * @param {Grid} grid the grid we're working against
- * @param {GridRow} row the row we're matching against
- * @param {GridCol} column the column that we're working against
- * @param {object} filter the specific, preparsed, filter that we want to test
- * @returns {boolean} true if we match (row stays visible)
- */
- rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {
- // Cache typeof condition
- var conditionType = typeof(filter.condition);
-
- // Term to search for.
- var term = filter.term;
-
- // Get the column value for this row
- var value;
- if ( column.filterCellFiltered ){
- value = grid.getCellDisplayValue(row, column);
- } else {
- value = grid.getCellValue(row, column);
- }
-
-
- // If the filter's condition is a RegExp, then use it
- if (filter.condition instanceof RegExp) {
- return filter.condition.test(value);
- }
-
- // If the filter's condition is a function, run it
- if (conditionType === 'function') {
- return filter.condition(term, value, row, column);
- }
-
- if (filter.startswithRE) {
- return filter.startswithRE.test(value);
- }
-
- if (filter.endswithRE) {
- return filter.endswithRE.test(value);
- }
-
- if (filter.containsRE) {
- return filter.containsRE.test(value);
- }
-
- if (filter.exactRE) {
- return filter.exactRE.test(value);
- }
-
- if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {
- var regex = new RegExp('^' + term + '$');
- return !regex.exec(value);
- }
-
- if (typeof(value) === 'number' && typeof(term) === 'string' ){
- // if the term has a decimal in it, it comes through as '9\.4', we need to take out the \
- // the same for negative numbers
- // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?
- var tempFloat = parseFloat(term.replace(/\\\./,'.').replace(/\\\-/,'-'));
- if (!isNaN(tempFloat)) {
- term = tempFloat;
- }
- }
-
- if (filter.flags.date === true) {
- value = new Date(value);
- // If the term has a dash in it, it comes through as '\-' -- we need to take out the '\'.
- term = new Date(term.replace(/\\/g, ''));
- }
-
- if (filter.condition === uiGridConstants.filter.GREATER_THAN) {
- return (value > term);
- }
-
- if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {
- return (value >= term);
- }
-
- if (filter.condition === uiGridConstants.filter.LESS_THAN) {
- return (value < term);
- }
-
- if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {
- return (value <= term);
- }
-
- return true;
- };
-
-
- /**
- * @ngdoc boolean
- * @name useExternalFiltering
- * @propertyOf ui.grid.class:GridOptions
- * @description False by default. When enabled, this setting suppresses the internal filtering.
- * All UI logic will still operate, allowing filter conditions to be set and modified.
- *
- * The external filter logic can listen for the `filterChange` event, which fires whenever
- * a filter has been adjusted.
- */
- /**
- * @ngdoc function
- * @name searchColumn
- * @methodOf ui.grid.service:rowSearcher
- * @description Process provided filters on provided column against a given row. If the row meets
- * the conditions on all the filters, return true.
- * @param {Grid} grid Grid to search in
- * @param {GridRow} row Row to search on
- * @param {GridCol} column Column with the filters to use
- * @param {array} filters array of pre-parsed/preprocessed filters to apply
- * @returns {boolean} Whether the column matches or not.
- */
- rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {
- if (grid.options.useExternalFiltering) {
- return true;
- }
-
- var filtersLength = filters.length;
- for (var i = 0; i < filtersLength; i++) {
- var filter = filters[i];
-
- var ret = rowSearcher.runColumnFilter(grid, row, column, filter);
- if (!ret) {
- return false;
- }
- }
-
- return true;
- };
-
-
- /**
- * @ngdoc function
- * @name search
- * @methodOf ui.grid.service:rowSearcher
- * @description Run a search across the given rows and columns, marking any rows that don't
- * match the stored col.filters or col.filter as invisible.
- * @param {Grid} grid Grid instance to search inside
- * @param {Array[GridRow]} rows GridRows to filter
- * @param {Array[GridColumn]} columns GridColumns with filters to process
- */
- rowSearcher.search = function search(grid, rows, columns) {
- /*
- * Added performance optimisations into this code base, as this logic creates deeply nested
- * loops and is therefore very performance sensitive. In particular, avoiding forEach as
- * this impacts some browser optimisers (particularly Chrome), using iterators instead
- */
-
- // Don't do anything if we weren't passed any rows
- if (!rows) {
- return;
- }
-
- // don't filter if filtering currently disabled
- if (!grid.options.enableFiltering){
- return rows;
- }
-
- // Build list of filters to apply
- var filterData = [];
-
- var colsLength = columns.length;
-
- var hasTerm = function( filters ) {
- var hasTerm = false;
-
- filters.forEach( function (filter) {
- if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ){
- hasTerm = true;
- }
- });
-
- return hasTerm;
- };
-
- for (var i = 0; i < colsLength; i++) {
- var col = columns[i];
-
- if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {
- filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );
- }
- }
-
- if (filterData.length > 0) {
- // define functions outside the loop, performance optimisation
- var foreachRow = function(grid, row, col, filters){
- if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {
- row.visible = false;
- }
- };
-
- var foreachFilterCol = function(grid, filterData){
- var rowsLength = rows.length;
- for ( var i = 0; i < rowsLength; i++){
- foreachRow(grid, rows[i], filterData.col, filterData.filters);
- }
- };
-
- // nested loop itself - foreachFilterCol, which in turn calls foreachRow
- var filterDataLength = filterData.length;
- for ( var j = 0; j < filterDataLength; j++){
- foreachFilterCol( grid, filterData[j] );
- }
-
- if (grid.api.core.raise.rowsVisibleChanged) {
- grid.api.core.raise.rowsVisibleChanged();
- }
-
- // drop any invisible rows
- // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter
- // rows = rows.filter(function(row){ return row.visible; });
-
- }
-
- return rows;
- };
-
- return rowSearcher;
-}]);
-
-})();
-
-(function() {
-
-var module = angular.module('ui.grid');
-
-/**
- * @ngdoc object
- * @name ui.grid.class:RowSorter
- * @description RowSorter provides the default sorting mechanisms,
- * including guessing column types and applying appropriate sort
- * algorithms
- *
- */
-
-module.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {
- var currencyRegexStr =
- '(' +
- uiGridConstants.CURRENCY_SYMBOLS
- .map(function (a) { return '\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)
- .join('|') + // Join all the symbols together with |s
- ')?';
-
- // /^[-+]?[£$¤¥]?[\d,.]+%?$/
- var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\d,.]+' + currencyRegexStr + '%?$');
-
- var rowSorter = {
- // Cache of sorting functions. Once we create them, we don't want to keep re-doing it
- // this takes a piece of data from the cell and tries to determine its type and what sorting
- // function to use for it
- colSortFnCache: {}
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name guessSortFn
- * @description Assigns a sort function to use based on the itemType in the column
- * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'. And
- * error will be thrown for any other type.
- * @returns {function} a sort function that will sort that type
- */
- rowSorter.guessSortFn = function guessSortFn(itemType) {
- switch (itemType) {
- case "number":
- return rowSorter.sortNumber;
- case "numberStr":
- return rowSorter.sortNumberStr;
- case "boolean":
- return rowSorter.sortBool;
- case "string":
- return rowSorter.sortAlpha;
- case "date":
- return rowSorter.sortDate;
- case "object":
- return rowSorter.basicSort;
- default:
- throw new Error('No sorting function found for type:' + itemType);
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name handleNulls
- * @description Sorts nulls and undefined to the bottom (top when
- * descending). Called by each of the internal sorters before
- * attempting to sort. Note that this method is available on the core api
- * via gridApi.core.sortHandleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} null if there were no nulls/undefineds, otherwise returns
- * a sort value that should be passed back from the sort function
- */
- rowSorter.handleNulls = function handleNulls(a, b) {
- // We want to allow zero values and false values to be evaluated in the sort function
- if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {
- // We want to force nulls and such to the bottom when we sort... which effectively is "greater than"
- if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {
- return 0;
- }
- else if (!a && a !== 0 && a !== false) {
- return 1;
- }
- else if (!b && b !== 0 && b !== false) {
- return -1;
- }
- }
- return null;
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name basicSort
- * @description Sorts any values that provide the < method, including strings
- * or numbers. Handles nulls and undefined through calling handleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.basicSort = function basicSort(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- if (a === b) {
- return 0;
- }
- if (a < b) {
- return -1;
- }
- return 1;
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sortNumber
- * @description Sorts numerical values. Handles nulls and undefined through calling handleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.sortNumber = function sortNumber(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- return a - b;
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sortNumberStr
- * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).
- * Handles nulls and undefined through calling handleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.sortNumberStr = function sortNumberStr(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- var numA, // The parsed number form of 'a'
- numB, // The parsed number form of 'b'
- badA = false,
- badB = false;
-
- // Try to parse 'a' to a float
- numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
-
- // If 'a' couldn't be parsed to float, flag it as bad
- if (isNaN(numA)) {
- badA = true;
- }
-
- // Try to parse 'b' to a float
- numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
-
- // If 'b' couldn't be parsed to float, flag it as bad
- if (isNaN(numB)) {
- badB = true;
- }
-
- // We want bad ones to get pushed to the bottom... which effectively is "greater than"
- if (badA && badB) {
- return 0;
- }
-
- if (badA) {
- return 1;
- }
-
- if (badB) {
- return -1;
- }
-
- return numA - numB;
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sortAlpha
- * @description Sorts string values. Handles nulls and undefined through calling handleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.sortAlpha = function sortAlpha(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- var strA = a.toString().toLowerCase(),
- strB = b.toString().toLowerCase();
-
- return strA === strB ? 0 : (strA < strB ? -1 : 1);
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sortDate
- * @description Sorts date values. Handles nulls and undefined through calling handleNulls.
- * Handles date strings by converting to Date object if not already an instance of Date
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.sortDate = function sortDate(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- if (!(a instanceof Date)) {
- a = new Date(a);
- }
- if (!(b instanceof Date)){
- b = new Date(b);
- }
- var timeA = a.getTime(),
- timeB = b.getTime();
-
- return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sortBool
- * @description Sorts boolean values, true is considered larger than false.
- * Handles nulls and undefined through calling handleNulls
- * @param {object} a sort value a
- * @param {object} b sort value b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.sortBool = function sortBool(a, b) {
- var nulls = rowSorter.handleNulls(a, b);
- if ( nulls !== null ){
- return nulls;
- } else {
- if (a && b) {
- return 0;
- }
-
- if (!a && !b) {
- return 0;
- }
- else {
- return a ? 1 : -1;
- }
- }
- };
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name getSortFn
- * @description Get the sort function for the column. Looks first in
- * rowSorter.colSortFnCache using the column name, failing that it
- * looks at col.sortingAlgorithm (and puts it in the cache), failing that
- * it guesses the sort algorithm based on the data type.
- *
- * The cache currently seems a bit pointless, as none of the work we do is
- * processor intensive enough to need caching. Presumably in future we might
- * inspect the row data itself to guess the sort function, and in that case
- * it would make sense to have a cache, the infrastructure is in place to allow
- * that.
- *
- * @param {Grid} grid the grid to consider
- * @param {GridCol} col the column to find a function for
- * @param {array} rows an array of grid rows. Currently unused, but presumably in future
- * we might inspect the rows themselves to decide what sort of data might be there
- * @returns {function} the sort function chosen for the column
- */
- rowSorter.getSortFn = function getSortFn(grid, col, rows) {
- var sortFn, item;
-
- // See if we already figured out what to use to sort the column and have it in the cache
- if (rowSorter.colSortFnCache[col.colDef.name]) {
- sortFn = rowSorter.colSortFnCache[col.colDef.name];
- }
- // If the column has its OWN sorting algorithm, use that
- else if (col.sortingAlgorithm !== undefined) {
- sortFn = col.sortingAlgorithm;
- rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;
- }
- // Always default to sortAlpha when sorting after a cellFilter
- else if ( col.sortCellFiltered && col.cellFilter ){
- sortFn = rowSorter.sortAlpha;
- rowSorter.colSortFnCache[col.colDef.name] = sortFn;
- }
- // Try and guess what sort function to use
- else {
- // Guess the sort function
- sortFn = rowSorter.guessSortFn(col.colDef.type);
-
- // If we found a sort function, cache it
- if (sortFn) {
- rowSorter.colSortFnCache[col.colDef.name] = sortFn;
- }
- else {
- // We assign the alpha sort because anything that is null/undefined will never get passed to
- // the actual sorting function. It will get caught in our null check and returned to be sorted
- // down to the bottom
- sortFn = rowSorter.sortAlpha;
- }
- }
-
- return sortFn;
- };
-
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name prioritySort
- * @description Used where multiple columns are present in the sort criteria,
- * we determine which column should take precedence in the sort by sorting
- * the columns based on their sort.priority
- *
- * @param {gridColumn} a column a
- * @param {gridColumn} b column b
- * @returns {number} normal sort function, returns -ve, 0, +ve
- */
- rowSorter.prioritySort = function (a, b) {
- // Both columns have a sort priority
- if (a.sort.priority !== undefined && b.sort.priority !== undefined) {
- // A is higher priority
- if (a.sort.priority < b.sort.priority) {
- return -1;
- }
- // Equal
- else if (a.sort.priority === b.sort.priority) {
- return 0;
- }
- // B is higher
- else {
- return 1;
- }
- }
- // Only A has a priority
- else if (a.sort.priority || a.sort.priority === 0) {
- return -1;
- }
- // Only B has a priority
- else if (b.sort.priority || b.sort.priority === 0) {
- return 1;
- }
- // Neither has a priority
- else {
- return 0;
- }
- };
-
-
- /**
- * @ngdoc object
- * @name useExternalSorting
- * @propertyOf ui.grid.class:GridOptions
- * @description Prevents the internal sorting from executing. Events will
- * still be fired when the sort changes, and the sort information on
- * the columns will be updated, allowing an external sorter (for example,
- * server sorting) to be implemented. Defaults to false.
- *
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.class:RowSorter
- * @name sort
- * @description sorts the grid
- * @param {Object} grid the grid itself
- * @param {array} rows the rows to be sorted
- * @param {array} columns the columns in which to look
- * for sort criteria
- * @returns {array} sorted rows
- */
- rowSorter.sort = function rowSorterSort(grid, rows, columns) {
- // first make sure we are even supposed to do work
- if (!rows) {
- return;
- }
-
- if (grid.options.useExternalSorting){
- return rows;
- }
-
- // Build the list of columns to sort by
- var sortCols = [];
- columns.forEach(function (col) {
- if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
- sortCols.push(col);
- }
- });
-
- // Sort the "sort columns" by their sort priority
- sortCols = sortCols.sort(rowSorter.prioritySort);
-
- // Now rows to sort by, maintain original order
- if (sortCols.length === 0) {
- return rows;
- }
-
- // Re-usable variables
- var col, direction;
-
- // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
- var setIndex = function( row, idx ){
- row.entity.$$uiGridIndex = idx;
- };
- rows.forEach(setIndex);
-
- // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference
- // var d = data.slice(0);
- var r = rows.slice(0);
-
- // Now actually sort the data
- var rowSortFn = function (rowA, rowB) {
- var tem = 0,
- idx = 0,
- sortFn;
-
- while (tem === 0 && idx < sortCols.length) {
- // grab the metadata for the rest of the logic
- col = sortCols[idx];
- direction = sortCols[idx].sort.direction;
-
- sortFn = rowSorter.getSortFn(grid, col, r);
-
- var propA, propB;
-
- if ( col.sortCellFiltered ){
- propA = grid.getCellDisplayValue(rowA, col);
- propB = grid.getCellDisplayValue(rowB, col);
- } else {
- propA = grid.getCellValue(rowA, col);
- propB = grid.getCellValue(rowB, col);
- }
-
- tem = sortFn(propA, propB, rowA, rowB, direction);
-
- idx++;
- }
-
- // Chrome doesn't implement a stable sort function. If our sort returns 0
- // (i.e. the items are equal), and we're at the last sort column in the list,
- // then return the previous order using our custom
- // index variable
- if (tem === 0 ) {
- return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;
- }
-
- // Made it this far, we don't have to worry about null & undefined
- if (direction === uiGridConstants.ASC) {
- return tem;
- } else {
- return 0 - tem;
- }
- };
-
- var newRows = rows.sort(rowSortFn);
-
- // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
- var clearIndex = function( row, idx ){
- delete row.entity.$$uiGridIndex;
- };
- rows.forEach(clearIndex);
-
- return newRows;
- };
-
- return rowSorter;
-}]);
-
-})();
-
-(function() {
-
-var module = angular.module('ui.grid');
-
-var bindPolyfill;
-if (typeof Function.prototype.bind !== "function") {
- bindPolyfill = function() {
- var slice = Array.prototype.slice;
- return function(context) {
- var fn = this,
- args = slice.call(arguments, 1);
- if (args.length) {
- return function() {
- return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);
- };
- }
- return function() {
- return arguments.length ? fn.apply(context, arguments) : fn.call(context);
- };
- };
- };
-}
-
-function getStyles (elem) {
- var e = elem;
- if (typeof(e.length) !== 'undefined' && e.length) {
- e = elem[0];
- }
-
- return e.ownerDocument.defaultView.getComputedStyle(e, null);
-}
-
-var rnumnonpx = new RegExp( "^(" + (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source + ")(?!px)[a-z%]+$", "i" ),
- // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
- // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
- rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,
- cssShow = { position: "absolute", visibility: "hidden", display: "block" };
-
-function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
- var i = extra === ( isBorderBox ? 'border' : 'content' ) ?
- // If we already have the right measurement, avoid augmentation
- 4 :
- // Otherwise initialize for horizontal or vertical properties
- name === 'width' ? 1 : 0,
-
- val = 0;
-
- var sides = ['Top', 'Right', 'Bottom', 'Left'];
-
- for ( ; i < 4; i += 2 ) {
- var side = sides[i];
- // dump('side', side);
-
- // both box models exclude margin, so add it if we want it
- if ( extra === 'margin' ) {
- var marg = parseFloat(styles[extra + side]);
- if (!isNaN(marg)) {
- val += marg;
- }
- }
- // dump('val1', val);
-
- if ( isBorderBox ) {
- // border-box includes padding, so remove it if we want content
- if ( extra === 'content' ) {
- var padd = parseFloat(styles['padding' + side]);
- if (!isNaN(padd)) {
- val -= padd;
- // dump('val2', val);
- }
- }
-
- // at this point, extra isn't border nor margin, so remove border
- if ( extra !== 'margin' ) {
- var bordermarg = parseFloat(styles['border' + side + 'Width']);
- if (!isNaN(bordermarg)) {
- val -= bordermarg;
- // dump('val3', val);
- }
- }
- }
- else {
- // at this point, extra isn't content, so add padding
- var nocontentPad = parseFloat(styles['padding' + side]);
- if (!isNaN(nocontentPad)) {
- val += nocontentPad;
- // dump('val4', val);
- }
-
- // at this point, extra isn't content nor padding, so add border
- if ( extra !== 'padding') {
- var nocontentnopad = parseFloat(styles['border' + side + 'Width']);
- if (!isNaN(nocontentnopad)) {
- val += nocontentnopad;
- // dump('val5', val);
- }
- }
- }
- }
-
- // dump('augVal', val);
-
- return val;
-}
-
-function getWidthOrHeight( elem, name, extra ) {
- // Start with offset property, which is equivalent to the border-box value
- var valueIsBorderBox = true,
- val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,
- styles = getStyles(elem),
- isBorderBox = styles['boxSizing'] === 'border-box';
-
- // some non-html elements return undefined for offsetWidth, so check for null/undefined
- // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
- // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
- if ( val <= 0 || val == null ) {
- // Fall back to computed then uncomputed css if necessary
- val = styles[name];
- if ( val < 0 || val == null ) {
- val = elem.style[ name ];
- }
-
- // Computed unit is not pixels. Stop here and return.
- if ( rnumnonpx.test(val) ) {
- return val;
- }
-
- // we need the check for style in case a browser which returns unreliable values
- // for getComputedStyle silently falls back to the reliable elem.style
- valueIsBorderBox = isBorderBox &&
- ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'
-
- // Normalize "", auto, and prepare for extra
- val = parseFloat( val ) || 0;
- }
-
- // use the active box-sizing model to add/subtract irrelevant styles
- var ret = ( val +
- augmentWidthOrHeight(
- elem,
- name,
- extra || ( isBorderBox ? "border" : "content" ),
- valueIsBorderBox,
- styles
- )
- );
-
- // dump('ret', ret, val);
- return ret;
-}
-
-function getLineHeight(elm) {
- elm = angular.element(elm)[0];
- var parent = elm.parentElement;
-
- if (!parent) {
- parent = document.getElementsByTagName('body')[0];
- }
-
- return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;
-}
-
-var uid = ['0', '0', '0', '0'];
-var uidPrefix = 'uiGrid-';
-
-/**
- * @ngdoc service
- * @name ui.grid.service:GridUtil
- *
- * @description Grid utility functions
- */
-module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',
- function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {
- var s = {
-
- augmentWidthOrHeight: augmentWidthOrHeight,
-
- getStyles: getStyles,
-
- /**
- * @ngdoc method
- * @name createBoundedWrapper
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {object} Object to bind 'this' to
- * @param {method} Method to bind
- * @returns {Function} The wrapper that performs the binding
- *
- * @description
- * Binds given method to given object.
- *
- * By means of a wrapper, ensures that ``method`` is always bound to
- * ``object`` regardless of its calling environment.
- * Iow, inside ``method``, ``this`` always points to ``object``.
- *
- * See http://alistapart.com/article/getoutbindingsituations
- *
- */
- createBoundedWrapper: function(object, method) {
- return function() {
- return method.apply(object, arguments);
- };
- },
-
-
- /**
- * @ngdoc method
- * @name readableColumnName
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {string} columnName Column name as a string
- * @returns {string} Column name appropriately capitalized and split apart
- *
- @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid']);
-
- app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {
- $scope.name = 'firstName';
- $scope.columnName = function(name) {
- return gridUtil.readableColumnName(name);
- };
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <strong>Column name:</strong> <input ng-model="name" />
- <br>
- <strong>Output:</strong> <span ng-bind="columnName(name)"></span>
- </div>
- </file>
- </example>
- */
- readableColumnName: function (columnName) {
- // Convert underscores to spaces
- if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }
-
- if (typeof(columnName) !== 'string') {
- columnName = String(columnName);
- }
-
- return columnName.replace(/_+/g, ' ')
- // Replace a completely all-capsed word with a first-letter-capitalized version
- .replace(/^[A-Z]+$/, function (match) {
- return angular.lowercase(angular.uppercase(match.charAt(0)) + match.slice(1));
- })
- // Capitalize the first letter of words
- .replace(/([\w\u00C0-\u017F]+)/g, function (match) {
- return angular.uppercase(match.charAt(0)) + match.slice(1);
- })
- // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')
- // .replace(/([A-Z]|[A-Z]\w+)([A-Z])/g, "$1 $2");
- // .replace(/(\w+?|\w)([A-Z])/g, "$1 $2");
- .replace(/(\w+?(?=[A-Z]))/g, '$1 ');
- },
-
- /**
- * @ngdoc method
- * @name getColumnsFromData
- * @methodOf ui.grid.service:GridUtil
- * @description Return a list of column names, given a data set
- *
- * @param {string} data Data array for grid
- * @returns {Object} Column definitions with field accessor and column name
- *
- * @example
- <pre>
- var data = [
- { firstName: 'Bob', lastName: 'Jones' },
- { firstName: 'Frank', lastName: 'Smith' }
- ];
-
- var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);
-
- columnDefs == [
- {
- field: 'firstName',
- name: 'First Name'
- },
- {
- field: 'lastName',
- name: 'Last Name'
- }
- ];
- </pre>
- */
- getColumnsFromData: function (data, excludeProperties) {
- var columnDefs = [];
-
- if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }
- if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }
-
- var item = data[0];
-
- angular.forEach(item,function (prop, propName) {
- if ( excludeProperties.indexOf(propName) === -1){
- columnDefs.push({
- name: propName
- });
- }
- });
-
- return columnDefs;
- },
-
- /**
- * @ngdoc method
- * @name newId
- * @methodOf ui.grid.service:GridUtil
- * @description Return a unique ID string
- *
- * @returns {string} Unique string
- *
- * @example
- <pre>
- var id = GridUtil.newId();
-
- # 1387305700482;
- </pre>
- */
- newId: (function() {
- var seedId = new Date().getTime();
- return function() {
- return seedId += 1;
- };
- })(),
-
-
- /**
- * @ngdoc method
- * @name getTemplate
- * @methodOf ui.grid.service:GridUtil
- * @description Get's template from cache / element / url
- *
- * @param {string|element|promise} Either a string representing the template id, a string representing the template url,
- * an jQuery/Angualr element, or a promise that returns the template contents to use.
- * @returns {object} a promise resolving to template contents
- *
- * @example
- <pre>
- GridUtil.getTemplate(url).then(function (contents) {
- alert(contents);
- })
- </pre>
- */
- getTemplate: function (template) {
- // Try to fetch the template out of the templateCache
- if ($templateCache.get(template)) {
- return s.postProcessTemplate($templateCache.get(template));
- }
-
- // See if the template is itself a promise
- if (template.hasOwnProperty('then')) {
- return template.then(s.postProcessTemplate);
- }
-
- // If the template is an element, return the element
- try {
- if (angular.element(template).length > 0) {
- return $q.when(template).then(s.postProcessTemplate);
- }
- }
- catch (err){
- //do nothing; not valid html
- }
-
- s.logDebug('fetching url', template);
-
- // Default to trying to fetch the template as a url with $http
- return $http({ method: 'GET', url: template})
- .then(
- function (result) {
- var templateHtml = result.data.trim();
- //put in templateCache for next call
- $templateCache.put(template, templateHtml);
- return templateHtml;
- },
- function (err) {
- throw new Error("Could not get template " + template + ": " + err);
- }
- )
- .then(s.postProcessTemplate);
- },
-
- //
- postProcessTemplate: function (template) {
- var startSym = $interpolate.startSymbol(),
- endSym = $interpolate.endSymbol();
-
- // If either of the interpolation symbols have been changed, we need to alter this template
- if (startSym !== '{{' || endSym !== '}}') {
- template = template.replace(/\{\{/g, startSym);
- template = template.replace(/\}\}/g, endSym);
- }
-
- return $q.when(template);
- },
-
- /**
- * @ngdoc method
- * @name guessType
- * @methodOf ui.grid.service:GridUtil
- * @description guesses the type of an argument
- *
- * @param {string/number/bool/object} item variable to examine
- * @returns {string} one of the following
- * - 'string'
- * - 'boolean'
- * - 'number'
- * - 'date'
- * - 'object'
- */
- guessType : function (item) {
- var itemType = typeof(item);
-
- // Check for numbers and booleans
- switch (itemType) {
- case "number":
- case "boolean":
- case "string":
- return itemType;
- default:
- if (angular.isDate(item)) {
- return "date";
- }
- return "object";
- }
- },
-
-
- /**
- * @ngdoc method
- * @name elementWidth
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {element} element DOM element
- * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
- *
- * @returns {number} Element width in pixels, accounting for any borders, etc.
- */
- elementWidth: function (elem) {
-
- },
-
- /**
- * @ngdoc method
- * @name elementHeight
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {element} element DOM element
- * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
- *
- * @returns {number} Element height in pixels, accounting for any borders, etc.
- */
- elementHeight: function (elem) {
-
- },
-
- // Thanks to http://stackoverflow.com/a/13382873/888165
- getScrollbarWidth: function() {
- var outer = document.createElement("div");
- outer.style.visibility = "hidden";
- outer.style.width = "100px";
- outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
-
- document.body.appendChild(outer);
-
- var widthNoScroll = outer.offsetWidth;
- // force scrollbars
- outer.style.overflow = "scroll";
-
- // add innerdiv
- var inner = document.createElement("div");
- inner.style.width = "100%";
- outer.appendChild(inner);
-
- var widthWithScroll = inner.offsetWidth;
-
- // remove divs
- outer.parentNode.removeChild(outer);
-
- return widthNoScroll - widthWithScroll;
- },
-
- swap: function( elem, options, callback, args ) {
- var ret, name,
- old = {};
-
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- ret = callback.apply( elem, args || [] );
-
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
-
- return ret;
- },
-
- fakeElement: function( elem, options, callback, args ) {
- var ret, name,
- newElement = angular.element(elem).clone()[0];
-
- for ( name in options ) {
- newElement.style[ name ] = options[ name ];
- }
-
- angular.element(document.body).append(newElement);
-
- ret = callback.call( newElement, newElement );
-
- angular.element(newElement).remove();
-
- return ret;
- },
-
- /**
- * @ngdoc method
- * @name normalizeWheelEvent
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {event} event A mouse wheel event
- *
- * @returns {event} A normalized event
- *
- * @description
- * Given an event from this list:
- *
- * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`
- *
- * "normalize" it
- * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)
- */
- normalizeWheelEvent: function (event) {
- // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
- // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
- var lowestDelta, lowestDeltaXY;
-
- var orgEvent = event || window.event,
- args = [].slice.call(arguments, 1),
- delta = 0,
- deltaX = 0,
- deltaY = 0,
- absDelta = 0,
- absDeltaXY = 0,
- fn;
-
- // event = $.event.fix(orgEvent);
- // event.type = 'mousewheel';
-
- // NOTE: jQuery masks the event and stores it in the event as originalEvent
- if (orgEvent.originalEvent) {
- orgEvent = orgEvent.originalEvent;
- }
-
- // Old school scrollwheel delta
- if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
- if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
-
- // At a minimum, setup the deltaY to be delta
- deltaY = delta;
-
- // Firefox < 17 related to DOMMouseScroll event
- if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
- deltaY = 0;
- deltaX = delta * -1;
- }
-
- // New school wheel delta (wheel event)
- if ( orgEvent.deltaY ) {
- deltaY = orgEvent.deltaY * -1;
- delta = deltaY;
- }
- if ( orgEvent.deltaX ) {
- deltaX = orgEvent.deltaX;
- delta = deltaX * -1;
- }
-
- // Webkit
- if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
- if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }
-
- // Look for lowest delta to normalize the delta values
- absDelta = Math.abs(delta);
- if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
- absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
- if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
-
- // Get a whole value for the deltas
- fn = delta > 0 ? 'floor' : 'ceil';
- delta = Math[fn](delta / lowestDelta);
- deltaX = Math[fn](deltaX / lowestDeltaXY);
- deltaY = Math[fn](deltaY / lowestDeltaXY);
-
- return {
- delta: delta,
- deltaX: deltaX,
- deltaY: deltaY
- };
- },
-
- // Stolen from Modernizr
- // TODO: make this, and everythign that flows from it, robust
- //http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
- isTouchEnabled: function() {
- var bool;
-
- if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {
- bool = true;
- }
-
- return bool;
- },
-
- isNullOrUndefined: function(obj) {
- if (obj === undefined || obj === null) {
- return true;
- }
- return false;
- },
-
- endsWith: function(str, suffix) {
- if (!str || !suffix || typeof str !== "string") {
- return false;
- }
- return str.indexOf(suffix, str.length - suffix.length) !== -1;
- },
-
- arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {
- var found = false;
- angular.forEach(array, function (object) {
- if (object[propertyName] === propertyValue) {
- found = true;
- }
- });
- return found;
- },
-
- //// Shim requestAnimationFrame
- //requestAnimationFrame: $window.requestAnimationFrame && $window.requestAnimationFrame.bind($window) ||
- // $window.webkitRequestAnimationFrame && $window.webkitRequestAnimationFrame.bind($window) ||
- // function(fn) {
- // return $timeout(fn, 10, false);
- // },
-
- numericAndNullSort: function (a, b) {
- if (a === null) { return 1; }
- if (b === null) { return -1; }
- if (a === null && b === null) { return 0; }
- return a - b;
- },
-
- // Disable ngAnimate animations on an element
- disableAnimations: function (element) {
- var $animate;
- try {
- $animate = $injector.get('$animate');
- // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
- if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
- $animate.enabled(element, false);
- } else {
- $animate.enabled(false, element);
- }
- }
- catch (e) {}
- },
-
- enableAnimations: function (element) {
- var $animate;
- try {
- $animate = $injector.get('$animate');
- // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
- if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
- $animate.enabled(element, true);
- } else {
- $animate.enabled(true, element);
- }
- return $animate;
- }
- catch (e) {}
- },
-
- // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
- nextUid: function nextUid() {
- var index = uid.length;
- var digit;
-
- while (index) {
- index--;
- digit = uid[index].charCodeAt(0);
- if (digit === 57 /*'9'*/) {
- uid[index] = 'A';
- return uidPrefix + uid.join('');
- }
- if (digit === 90 /*'Z'*/) {
- uid[index] = '0';
- } else {
- uid[index] = String.fromCharCode(digit + 1);
- return uidPrefix + uid.join('');
- }
- }
- uid.unshift('0');
-
- return uidPrefix + uid.join('');
- },
-
- // Blatantly stolen from Angular as it isn't exposed (yet. 2.0 maybe?)
- hashKey: function hashKey(obj) {
- var objType = typeof obj,
- key;
-
- if (objType === 'object' && obj !== null) {
- if (typeof (key = obj.$$hashKey) === 'function') {
- // must invoke on object to keep the right this
- key = obj.$$hashKey();
- }
- else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {
- key = obj.$$hashKey;
- }
- else if (key === undefined) {
- key = obj.$$hashKey = s.nextUid();
- }
- }
- else {
- key = obj;
- }
-
- return objType + ':' + key;
- },
-
- resetUids: function () {
- uid = ['0', '0', '0'];
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil
- * @name logError
- * @description wraps the $log method, allowing us to choose different
- * treatment within ui-grid if we so desired. At present we only log
- * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true
- * @param {string} logMessage message to be logged to the console
- *
- */
- logError: function( logMessage ){
- if ( uiGridConstants.LOG_ERROR_MESSAGES ){
- $log.error( logMessage );
- }
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil
- * @name logWarn
- * @description wraps the $log method, allowing us to choose different
- * treatment within ui-grid if we so desired. At present we only log
- * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true
- * @param {string} logMessage message to be logged to the console
- *
- */
- logWarn: function( logMessage ){
- if ( uiGridConstants.LOG_WARN_MESSAGES ){
- $log.warn( logMessage );
- }
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil
- * @name logDebug
- * @description wraps the $log method, allowing us to choose different
- * treatment within ui-grid if we so desired. At present we only log
- * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true
- *
- */
- logDebug: function() {
- if ( uiGridConstants.LOG_DEBUG_MESSAGES ){
- $log.debug.apply($log, arguments);
- }
- }
-
- };
-
- /**
- * @ngdoc object
- * @name focus
- * @propertyOf ui.grid.service:GridUtil
- * @description Provies a set of methods to set the document focus inside the grid.
- * See {@link ui.grid.service:GridUtil.focus} for more information.
- */
-
- /**
- * @ngdoc object
- * @name ui.grid.service:GridUtil.focus
- * @description Provies a set of methods to set the document focus inside the grid.
- * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.
- * e.g. click events that need to run before the focus or
- * inputs elements that are in a disabled state but are enabled when those events
- * are triggered.
- */
- s.focus = {
- queue: [],
- //http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil.focus
- * @name byId
- * @description Sets the focus of the document to the given id value.
- * If provided with the grid object it will automatically append the grid id.
- * This is done to encourage unique dom id's as it allows for multiple grids on a
- * page.
- * @param {String} id the id of the dom element to set the focus on
- * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}
- * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.
- * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
- * then the promise will fail with the `'canceled'` reason.
- */
- byId: function (id, Grid) {
- this._purgeQueue();
- var promise = $timeout(function() {
- var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;
- var element = $window.document.getElementById(elementID);
- if (element) {
- element.focus();
- } else {
- s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');
- }
- });
- this.queue.push(promise);
- return promise;
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil.focus
- * @name byElement
- * @description Sets the focus of the document to the given dom element.
- * @param {(element|angular.element)} element the DOM element to set the focus on
- * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
- * then the promise will fail with the `'canceled'` reason.
- */
- byElement: function(element){
- if (!angular.isElement(element)){
- s.logWarn("Trying to focus on an element that isn\'t an element.");
- return $q.reject('not-element');
- }
- element = angular.element(element);
- this._purgeQueue();
- var promise = $timeout(function(){
- if (element){
- element[0].focus();
- }
- });
- this.queue.push(promise);
- return promise;
- },
- /**
- * @ngdoc method
- * @methodOf ui.grid.service:GridUtil.focus
- * @name bySelector
- * @description Sets the focus of the document to the given dom element.
- * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector
- * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}
- * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately
- * then the focus will be called.
- * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
- * then the promise will fail with the `'canceled'` reason.
- */
- bySelector: function(parentElement, querySelector, aSync){
- var self = this;
- if (!angular.isElement(parentElement)){
- throw new Error("The parent element is not an element.");
- }
- // Ensure that this is an angular element.
- // It is fine if this is already an angular element.
- parentElement = angular.element(parentElement);
- var focusBySelector = function(){
- var element = parentElement[0].querySelector(querySelector);
- return self.byElement(element);
- };
- this._purgeQueue();
- if (aSync){ //Do this asynchronysly
- var promise = $timeout(focusBySelector);
- this.queue.push($timeout(focusBySelector));
- return promise;
- } else {
- return focusBySelector();
- }
- },
- _purgeQueue: function(){
- this.queue.forEach(function(element){
- $timeout.cancel(element);
- });
- this.queue = [];
- }
- };
-
-
- ['width', 'height'].forEach(function (name) {
- var capsName = angular.uppercase(name.charAt(0)) + name.substr(1);
- s['element' + capsName] = function (elem, extra) {
- var e = elem;
- if (e && typeof(e.length) !== 'undefined' && e.length) {
- e = elem[0];
- }
-
- if (e) {
- var styles = getStyles(e);
- return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?
- s.swap(e, cssShow, function() {
- return getWidthOrHeight(e, name, extra );
- }) :
- getWidthOrHeight( e, name, extra );
- }
- else {
- return null;
- }
- };
-
- s['outerElement' + capsName] = function (elem, margin) {
- return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;
- };
- });
-
- // http://stackoverflow.com/a/24107550/888165
- s.closestElm = function closestElm(el, selector) {
- if (typeof(el.length) !== 'undefined' && el.length) {
- el = el[0];
- }
-
- var matchesFn;
-
- // find vendor prefix
- ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
- if (typeof document.body[fn] === 'function') {
- matchesFn = fn;
- return true;
- }
- return false;
- });
-
- // traverse parents
- var parent;
- while (el !== null) {
- parent = el.parentElement;
- if (parent !== null && parent[matchesFn](selector)) {
- return parent;
- }
- el = parent;
- }
-
- return null;
- };
-
- s.type = function (obj) {
- var text = Function.prototype.toString.call(obj.constructor);
- return text.match(/function (.*?)\(/)[1];
- };
-
- s.getBorderSize = function getBorderSize(elem, borderType) {
- if (typeof(elem.length) !== 'undefined' && elem.length) {
- elem = elem[0];
- }
-
- var styles = getStyles(elem);
-
- // If a specific border is supplied, like 'top', read the 'borderTop' style property
- if (borderType) {
- borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);
- }
- else {
- borderType = 'border';
- }
-
- borderType += 'Width';
-
- var val = parseInt(styles[borderType], 10);
-
- if (isNaN(val)) {
- return 0;
- }
- else {
- return val;
- }
- };
-
- // http://stackoverflow.com/a/22948274/888165
- // TODO: Opera? Mobile?
- s.detectBrowser = function detectBrowser() {
- var userAgent = $window.navigator.userAgent;
-
- var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\//i};
-
- for (var key in browsers) {
- if (browsers[key].test(userAgent)) {
- return key;
- }
- }
-
- return 'unknown';
- };
-
- // Borrowed from https://github.com/othree/jquery.rtl-scroll-type
- // Determine the scroll "type" this browser is using for RTL
- s.rtlScrollType = function rtlScrollType() {
- if (rtlScrollType.type) {
- return rtlScrollType.type;
- }
-
- var definer = angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],
- type = 'reverse';
-
- document.body.appendChild(definer);
-
- if (definer.scrollLeft > 0) {
- type = 'default';
- }
- else {
- definer.scrollLeft = 1;
- if (definer.scrollLeft === 0) {
- type = 'negative';
- }
- }
-
- angular.element(definer).remove();
- rtlScrollType.type = type;
-
- return type;
- };
-
- /**
- * @ngdoc method
- * @name normalizeScrollLeft
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {element} element The element to get the `scrollLeft` from.
- * @param {grid} grid - grid used to normalize (uses the rtl property)
- *
- * @returns {number} A normalized scrollLeft value for the current browser.
- *
- * @description
- * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them
- */
- s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {
- if (typeof(element.length) !== 'undefined' && element.length) {
- element = element[0];
- }
-
- var scrollLeft = element.scrollLeft;
-
- if (grid.isRTL()) {
- switch (s.rtlScrollType()) {
- case 'default':
- return element.scrollWidth - scrollLeft - element.clientWidth;
- case 'negative':
- return Math.abs(scrollLeft);
- case 'reverse':
- return scrollLeft;
- }
- }
-
- return scrollLeft;
- };
-
- /**
- * @ngdoc method
- * @name denormalizeScrollLeft
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {element} element The element to normalize the `scrollLeft` value for
- * @param {number} scrollLeft The `scrollLeft` value to denormalize.
- * @param {grid} grid The grid that owns the scroll event.
- *
- * @returns {number} A normalized scrollLeft value for the current browser.
- *
- * @description
- * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.
- */
- s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {
- if (typeof(element.length) !== 'undefined' && element.length) {
- element = element[0];
- }
-
- if (grid.isRTL()) {
- switch (s.rtlScrollType()) {
- case 'default':
- // Get the max scroll for the element
- var maxScrollLeft = element.scrollWidth - element.clientWidth;
-
- // Subtract the current scroll amount from the max scroll
- return maxScrollLeft - scrollLeft;
- case 'negative':
- return scrollLeft * -1;
- case 'reverse':
- return scrollLeft;
- }
- }
-
- return scrollLeft;
- };
-
- /**
- * @ngdoc method
- * @name preEval
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {string} path Path to evaluate
- *
- * @returns {string} A path that is normalized.
- *
- * @description
- * Takes a field path and converts it to bracket notation to allow for special characters in path
- * @example
- * <pre>
- * gridUtil.preEval('property') == 'property'
- * gridUtil.preEval('nested.deep.prop-erty') = "nested['deep']['prop-erty']"
- * </pre>
- */
- s.preEval = function (path) {
- var m = uiGridConstants.BRACKET_REGEXP.exec(path);
- if (m) {
- return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);
- } else {
- path = path.replace(uiGridConstants.APOS_REGEXP, '\\\'');
- var parts = path.split(uiGridConstants.DOT_REGEXP);
- var preparsed = [parts.shift()]; // first item must be var notation, thus skip
- angular.forEach(parts, function (part) {
- preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\']$1'));
- });
- return preparsed.join('[\'');
- }
- };
-
- /**
- * @ngdoc method
- * @name debounce
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {function} func function to debounce
- * @param {number} wait milliseconds to delay
- * @param {boolean} immediate execute before delay
- *
- * @returns {function} A function that can be executed as debounced function
- *
- * @description
- * Copied from https://github.com/shahata/angular-debounce
- * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function
- * @example
- * <pre>
- * var debouncedFunc = gridUtil.debounce(function(){alert('debounced');}, 500);
- * debouncedFunc();
- * debouncedFunc();
- * debouncedFunc();
- * </pre>
- */
- s.debounce = function (func, wait, immediate) {
- var timeout, args, context, result;
- function debounce() {
- /* jshint validthis:true */
- context = this;
- args = arguments;
- var later = function () {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- }
- };
- var callNow = immediate && !timeout;
- if (timeout) {
- $timeout.cancel(timeout);
- }
- timeout = $timeout(later, wait);
- if (callNow) {
- result = func.apply(context, args);
- }
- return result;
- }
- debounce.cancel = function () {
- $timeout.cancel(timeout);
- timeout = null;
- };
- return debounce;
- };
-
- /**
- * @ngdoc method
- * @name throttle
- * @methodOf ui.grid.service:GridUtil
- *
- * @param {function} func function to throttle
- * @param {number} wait milliseconds to delay after first trigger
- * @param {Object} params to use in throttle.
- *
- * @returns {function} A function that can be executed as throttled function
- *
- * @description
- * Adapted from debounce function (above)
- * Potential keys for Params Object are:
- * trailing (bool) - whether to trigger after throttle time ends if called multiple times
- * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,
- * but not with $timeout
- *
- * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function
- * return from that call each time you need to call throttle. If you call throttle itself repeatedly, the lastCall
- * variable will get overwritten and the throttling won't work
- *
- * @example
- * <pre>
- * var throttledFunc = gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});
- * throttledFunc(); //=> logs throttled
- * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)
- * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.
- * </pre>
- */
- s.throttle = function(func, wait, options){
- options = options || {};
- var lastCall = 0, queued = null, context, args;
-
- function runFunc(endDate){
- lastCall = +new Date();
- func.apply(context, args);
- $interval(function(){ queued = null; }, 0, 1);
- }
-
- return function(){
- /* jshint validthis:true */
- context = this;
- args = arguments;
- if (queued === null){
- var sinceLast = +new Date() - lastCall;
- if (sinceLast > wait){
- runFunc();
- }
- else if (options.trailing){
- queued = $interval(runFunc, wait - sinceLast, 1);
- }
- }
- };
- };
-
- s.on = {};
- s.off = {};
- s._events = {};
-
- s.addOff = function (eventName) {
- s.off[eventName] = function (elm, fn) {
- var idx = s._events[eventName].indexOf(fn);
- if (idx > 0) {
- s._events[eventName].removeAt(idx);
- }
- };
- };
-
- var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
- nullLowestDeltaTimeout,
- lowestDelta;
-
- s.on.mousewheel = function (elm, fn) {
- if (!elm || !fn) { return; }
-
- var $elm = angular.element(elm);
-
- // Store the line height and page height for this particular element
- $elm.data('mousewheel-line-height', getLineHeight($elm));
- $elm.data('mousewheel-page-height', s.elementHeight($elm));
- if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }
-
- var cbs = $elm.data('mousewheel-callbacks');
- cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);
-
- // Bind all the mousew heel events
- for ( var i = mouseWheeltoBind.length; i; ) {
- $elm.on(mouseWheeltoBind[--i], cbs[fn]);
- }
- };
- s.off.mousewheel = function (elm, fn) {
- var $elm = angular.element(elm);
-
- var cbs = $elm.data('mousewheel-callbacks');
- var handler = cbs[fn];
-
- if (handler) {
- for ( var i = mouseWheeltoBind.length; i; ) {
- $elm.off(mouseWheeltoBind[--i], handler);
- }
- }
-
- delete cbs[fn];
-
- if (Object.keys(cbs).length === 0) {
- $elm.removeData('mousewheel-line-height');
- $elm.removeData('mousewheel-page-height');
- $elm.removeData('mousewheel-callbacks');
- }
- };
-
- function mousewheelHandler(fn, event) {
- var $elm = angular.element(this);
-
- var delta = 0,
- deltaX = 0,
- deltaY = 0,
- absDelta = 0,
- offsetX = 0,
- offsetY = 0;
-
- // jQuery masks events
- if (event.originalEvent) { event = event.originalEvent; }
-
- if ( 'detail' in event ) { deltaY = event.detail * -1; }
- if ( 'wheelDelta' in event ) { deltaY = event.wheelDelta; }
- if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY; }
- if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }
-
- // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
- if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
- deltaX = deltaY * -1;
- deltaY = 0;
- }
-
- // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
- delta = deltaY === 0 ? deltaX : deltaY;
-
- // New school wheel delta (wheel event)
- if ( 'deltaY' in event ) {
- deltaY = event.deltaY * -1;
- delta = deltaY;
- }
- if ( 'deltaX' in event ) {
- deltaX = event.deltaX;
- if ( deltaY === 0 ) { delta = deltaX * -1; }
- }
-
- // No change actually happened, no reason to go any further
- if ( deltaY === 0 && deltaX === 0 ) { return; }
-
- // Need to convert lines and pages to pixels if we aren't already in pixels
- // There are three delta modes:
- // * deltaMode 0 is by pixels, nothing to do
- // * deltaMode 1 is by lines
- // * deltaMode 2 is by pages
- if ( event.deltaMode === 1 ) {
- var lineHeight = $elm.data('mousewheel-line-height');
- delta *= lineHeight;
- deltaY *= lineHeight;
- deltaX *= lineHeight;
- }
- else if ( event.deltaMode === 2 ) {
- var pageHeight = $elm.data('mousewheel-page-height');
- delta *= pageHeight;
- deltaY *= pageHeight;
- deltaX *= pageHeight;
- }
-
- // Store lowest absolute delta to normalize the delta values
- absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
-
- if ( !lowestDelta || absDelta < lowestDelta ) {
- lowestDelta = absDelta;
-
- // Adjust older deltas if necessary
- if ( shouldAdjustOldDeltas(event, absDelta) ) {
- lowestDelta /= 40;
- }
- }
-
- // Get a whole, normalized value for the deltas
- delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
- deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
- deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
-
- event.deltaMode = 0;
-
- // Normalise offsetX and offsetY properties
- // if ($elm[0].getBoundingClientRect ) {
- // var boundingRect = $(elm)[0].getBoundingClientRect();
- // offsetX = event.clientX - boundingRect.left;
- // offsetY = event.clientY - boundingRect.top;
- // }
-
- // event.deltaX = deltaX;
- // event.deltaY = deltaY;
- // event.deltaFactor = lowestDelta;
-
- var newEvent = {
- originalEvent: event,
- deltaX: deltaX,
- deltaY: deltaY,
- deltaFactor: lowestDelta,
- preventDefault: function () { event.preventDefault(); },
- stopPropagation: function () { event.stopPropagation(); }
- };
-
- // Clearout lowestDelta after sometime to better
- // handle multiple device types that give
- // a different lowestDelta
- // Ex: trackpad = 3 and mouse wheel = 120
- if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
- nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
-
- fn.call($elm[0], newEvent);
- }
-
- function nullLowestDelta() {
- lowestDelta = null;
- }
-
- function shouldAdjustOldDeltas(orgEvent, absDelta) {
- // If this is an older event and the delta is divisable by 120,
- // then we are assuming that the browser is treating this as an
- // older mouse wheel event and that we should divide the deltas
- // by 40 to try and get a more usable deltaFactor.
- // Side note, this actually impacts the reported scroll distance
- // in older browsers and can cause scrolling to be slower than native.
- // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
- return orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
- }
-
- return s;
-}]);
-
-// Add 'px' to the end of a number string if it doesn't have it already
-module.filter('px', function() {
- return function(str) {
- if (str.match(/^[\d\.]+$/)) {
- return str + 'px';
- }
- else {
- return str;
- }
- };
-});
-
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- var lang = {
- aggregate: {
- label: 'položky'
- },
- groupPanel: {
- description: 'Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce.'
- },
- search: {
- placeholder: 'Hledat...',
- showingItems: 'Zobrazuji položky:',
- selectedItems: 'Vybrané položky:',
- totalItems: 'Celkem položek:',
- size: 'Velikost strany:',
- first: 'První strana',
- next: 'Další strana',
- previous: 'Předchozí strana',
- last: 'Poslední strana'
- },
- menu: {
- text: 'Vyberte sloupec:'
- },
- sort: {
- ascending: 'Seřadit od A-Z',
- descending: 'Seřadit od Z-A',
- remove: 'Odebrat seřazení'
- },
- column: {
- hide: 'Schovat sloupec'
- },
- aggregation: {
- count: 'celkem řádků: ',
- sum: 'celkem: ',
- avg: 'avg: ',
- min: 'min.: ',
- max: 'max.: '
- },
- pinning: {
- pinLeft: 'Zamknout vlevo',
- pinRight: 'Zamknout vpravo',
- unpin: 'Odemknout'
- },
- gridMenu: {
- columns: 'Sloupce:',
- importerTitle: 'Importovat soubor',
- exporterAllAsCsv: 'Exportovat všechna data do csv',
- exporterVisibleAsCsv: 'Exportovat viditelná data do csv',
- exporterSelectedAsCsv: 'Exportovat vybraná data do csv',
- exporterAllAsPdf: 'Exportovat všechna data do pdf',
- exporterVisibleAsPdf: 'Exportovat viditelná data do pdf',
- exporterSelectedAsPdf: 'Exportovat vybraná data do pdf',
- clearAllFilters: 'Odstranit všechny filtry'
- },
- importer: {
- noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',
- noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',
- invalidCsv: 'Soubor nelze zpracovat, jedná se o CSV?',
- invalidJson: 'Soubor nelze zpracovat, je to JSON?',
- jsonNotArray: 'Soubor musí obsahovat json. UkonÄuji..'
- },
- pagination: {
- sizes: 'položek na stránku',
- totalItems: 'položek'
- },
- grouping: {
- group: 'Seskupit',
- ungroup: 'Odebrat seskupení',
- aggregate_count: 'Agregace: Count',
- aggregate_sum: 'Agregace: Sum',
- aggregate_max: 'Agregace: Max',
- aggregate_min: 'Agregace: Min',
- aggregate_avg: 'Agregace: Avg',
- aggregate_remove: 'Agregace: Odebrat'
- }
- };
-
- // support varianty of different czech keys.
- $delegate.add('cs', lang);
- $delegate.add('cz', lang);
- $delegate.add('cs-cz', lang);
- $delegate.add('cs-CZ', lang);
- return $delegate;
- }]);
- }]);
-})();
-
-(function(){
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('da', {
- aggregate:{
- label: 'artikler'
- },
- groupPanel:{
- description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'
- },
- search:{
- placeholder: 'Søg...',
- showingItems: 'Viste rækker:',
- selectedItems: 'Valgte rækker:',
- totalItems: 'Rækker totalt:',
- size: 'Side størrelse:',
- first: 'Første side',
- next: 'Næste side',
- previous: 'Forrige side',
- last: 'Sidste side'
- },
- menu:{
- text: 'Vælg kolonner:'
- },
- column: {
- hide: 'Skjul kolonne'
- },
- aggregation: {
- count: 'samlede rækker: ',
- sum: 'smalede: ',
- avg: 'gns: ',
- min: 'min: ',
- max: 'max: '
- },
- gridMenu: {
- columns: 'Columns:',
- importerTitle: 'Import file',
- exporterAllAsCsv: 'Export all data as csv',
- exporterVisibleAsCsv: 'Export visible data as csv',
- exporterSelectedAsCsv: 'Export selected data as csv',
- exporterAllAsPdf: 'Export all data as pdf',
- exporterVisibleAsPdf: 'Export visible data as pdf',
- exporterSelectedAsPdf: 'Export selected data as pdf',
- clearAllFilters: 'Clear all filters'
- },
- importer: {
- noHeaders: 'Column names were unable to be derived, does the file have a header?',
- noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
- invalidCsv: 'File was unable to be processed, is it valid CSV?',
- invalidJson: 'File was unable to be processed, is it valid Json?',
- jsonNotArray: 'Imported json file must contain an array, aborting.'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function ($provide) {
- $provide.decorator('i18nService', ['$delegate', function ($delegate) {
- $delegate.add('de', {
- aggregate: {
- label: 'Eintrag'
- },
- groupPanel: {
- description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'
- },
- search: {
- placeholder: 'Suche...',
- showingItems: 'Zeige Einträge:',
- selectedItems: 'Ausgewählte Einträge:',
- totalItems: 'Einträge gesamt:',
- size: 'Einträge pro Seite:',
- first: 'Erste Seite',
- next: 'Nächste Seite',
- previous: 'Vorherige Seite',
- last: 'Letzte Seite'
- },
- menu: {
- text: 'Spalten auswählen:'
- },
- sort: {
- ascending: 'aufsteigend sortieren',
- descending: 'absteigend sortieren',
- remove: 'Sortierung zurücksetzen'
- },
- column: {
- hide: 'Spalte ausblenden'
- },
- aggregation: {
- count: 'Zeilen insgesamt: ',
- sum: 'gesamt: ',
- avg: 'Durchschnitt: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Links anheften',
- pinRight: 'Rechts anheften',
- unpin: 'Lösen'
- },
- gridMenu: {
- columns: 'Spalten:',
- importerTitle: 'Datei importieren',
- exporterAllAsCsv: 'Alle Daten als CSV exportieren',
- exporterVisibleAsCsv: 'sichtbare Daten als CSV exportieren',
- exporterSelectedAsCsv: 'markierte Daten als CSV exportieren',
- exporterAllAsPdf: 'Alle Daten als PDF exportieren',
- exporterVisibleAsPdf: 'sichtbare Daten als PDF exportieren',
- exporterSelectedAsPdf: 'markierte Daten als CSV exportieren',
- clearAllFilters: 'Alle filter reinigen'
- },
- importer: {
- noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',
- noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',
- invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',
- invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',
- jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'
- },
- pagination: {
- sizes: 'Einträge pro Seite',
- totalItems: 'Einträge'
- },
- grouping: {
- group: 'Gruppieren',
- ungroup: 'Gruppierung aufheben',
- aggregate_count: 'Agg: Anzahl',
- aggregate_sum: 'Agg: Summe',
- aggregate_max: 'Agg: Maximum',
- aggregate_min: 'Agg: Minimum',
- aggregate_avg: 'Agg: Mittelwert',
- aggregate_remove: 'Aggregation entfernen'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('en', {
- headerCell: {
- aria: {
- defaultFilterLabel: 'Filter for column',
- removeFilter: 'Remove Filter',
- columnMenuButtonLabel: 'Column Menu'
- },
- priority: 'Priority:',
- filterLabel: "Filter for column: "
- },
- aggregate: {
- label: 'items'
- },
- groupPanel: {
- description: 'Drag a column header here and drop it to group by that column.'
- },
- search: {
- placeholder: 'Search...',
- showingItems: 'Showing Items:',
- selectedItems: 'Selected Items:',
- totalItems: 'Total Items:',
- size: 'Page Size:',
- first: 'First Page',
- next: 'Next Page',
- previous: 'Previous Page',
- last: 'Last Page'
- },
- menu: {
- text: 'Choose Columns:'
- },
- sort: {
- ascending: 'Sort Ascending',
- descending: 'Sort Descending',
- none: 'Sort None',
- remove: 'Remove Sort'
- },
- column: {
- hide: 'Hide Column'
- },
- aggregation: {
- count: 'total rows: ',
- sum: 'total: ',
- avg: 'avg: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Pin Left',
- pinRight: 'Pin Right',
- unpin: 'Unpin'
- },
- columnMenu: {
- close: 'Close'
- },
- gridMenu: {
- aria: {
- buttonLabel: 'Grid Menu'
- },
- columns: 'Columns:',
- importerTitle: 'Import file',
- exporterAllAsCsv: 'Export all data as csv',
- exporterVisibleAsCsv: 'Export visible data as csv',
- exporterSelectedAsCsv: 'Export selected data as csv',
- exporterAllAsPdf: 'Export all data as pdf',
- exporterVisibleAsPdf: 'Export visible data as pdf',
- exporterSelectedAsPdf: 'Export selected data as pdf',
- clearAllFilters: 'Clear all filters'
- },
- importer: {
- noHeaders: 'Column names were unable to be derived, does the file have a header?',
- noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
- invalidCsv: 'File was unable to be processed, is it valid CSV?',
- invalidJson: 'File was unable to be processed, is it valid Json?',
- jsonNotArray: 'Imported json file must contain an array, aborting.'
- },
- pagination: {
- aria: {
- pageToFirst: 'Page to first',
- pageBack: 'Page back',
- pageSelected: 'Selected page',
- pageForward: 'Page forward',
- pageToLast: 'Page to last'
- },
- sizes: 'items per page',
- totalItems: 'items',
- through: 'through',
- of: 'of'
- },
- grouping: {
- group: 'Group',
- ungroup: 'Ungroup',
- aggregate_count: 'Agg: Count',
- aggregate_sum: 'Agg: Sum',
- aggregate_max: 'Agg: Max',
- aggregate_min: 'Agg: Min',
- aggregate_avg: 'Agg: Avg',
- aggregate_remove: 'Agg: Remove'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('es', {
- aggregate: {
- label: 'Artículos'
- },
- groupPanel: {
- description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'
- },
- search: {
- placeholder: 'Buscar...',
- showingItems: 'Artículos Mostrados:',
- selectedItems: 'Artículos Seleccionados:',
- totalItems: 'Artículos Totales:',
- size: 'Tamaño de Página:',
- first: 'Primera Página',
- next: 'Página Siguiente',
- previous: 'Página Anterior',
- last: 'Última Página'
- },
- menu: {
- text: 'Elegir columnas:'
- },
- sort: {
- ascending: 'Orden Ascendente',
- descending: 'Orden Descendente',
- remove: 'Sin Ordenar'
- },
- column: {
- hide: 'Ocultar la columna'
- },
- aggregation: {
- count: 'filas totales: ',
- sum: 'total: ',
- avg: 'media: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Fijar a la Izquierda',
- pinRight: 'Fijar a la Derecha',
- unpin: 'Quitar Fijación'
- },
- gridMenu: {
- columns: 'Columnas:',
- importerTitle: 'Importar archivo',
- exporterAllAsCsv: 'Exportar todo como csv',
- exporterVisibleAsCsv: 'Exportar vista como csv',
- exporterSelectedAsCsv: 'Exportar selección como csv',
- exporterAllAsPdf: 'Exportar todo como pdf',
- exporterVisibleAsPdf: 'Exportar vista como pdf',
- exporterSelectedAsPdf: 'Exportar selección como pdf',
- clearAllFilters: 'Limpiar todos los filtros'
- },
- importer: {
- noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',
- noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',
- invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',
- invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',
- jsonNotArray: 'El archivo json importado debe contener un array, abortando.'
- },
- pagination: {
- sizes: 'registros por página',
- totalItems: 'registros',
- of: 'de'
- },
- grouping: {
- group: 'Agrupar',
- ungroup: 'Desagrupar',
- aggregate_count: 'Agr: Cont',
- aggregate_sum: 'Agr: Sum',
- aggregate_max: 'Agr: Máx',
- aggregate_min: 'Agr: Min',
- aggregate_avg: 'Agr: Prom',
- aggregate_remove: 'Agr: Quitar'
- }
- });
- return $delegate;
- }]);
-}]);
-})();
-
-/**
- * Translated by: R. Salarmehr
- * M. Hosseynzade
- * Using Vajje.com online dictionary.
- */
-(function () {
- angular.module('ui.grid').config(['$provide', function ($provide) {
- $provide.decorator('i18nService', ['$delegate', function ($delegate) {
- $delegate.add('fa', {
- aggregate: {
- label: 'قلم'
- },
- groupPanel: {
- description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'
- },
- search: {
- placeholder: 'جستجو...',
- showingItems: 'نمایش اقلام:',
- selectedItems: 'قلم\u200cهای انتخاب شده:',
- totalItems: 'مجموع اقلام:',
- size: 'اندازه\u200cÛŒ صÙحه:',
- first: 'اولین صÙحه',
- next: 'صÙحه\u200cÛŒ\u200cبعدی',
- previous: 'صÙحه\u200cÛŒ\u200c قبلی',
- last: 'آخرین صÙحه'
- },
- menu: {
- text: 'ستون\u200cهای انتخابی:'
- },
- sort: {
- ascending: 'ترتیب صعودی',
- descending: 'ترتیب نزولی',
- remove: 'حذ٠مرتب کردن'
- },
- column: {
- hide: 'پنهان\u200cکردن ستون'
- },
- aggregation: {
- count: 'تعداد: ',
- sum: 'مجموع: ',
- avg: 'میانگین: ',
- min: 'کمترین: ',
- max: 'بیشترین: '
- },
- pinning: {
- pinLeft: 'پین کردن سمت چپ',
- pinRight: 'پین کردن سمت راست',
- unpin: 'حذ٠پین'
- },
- gridMenu: {
- columns: 'ستون\u200cها:',
- importerTitle: 'وارد کردن Ùایل',
- exporterAllAsCsv: 'خروجی تمام داده\u200cها در Ùایل csv',
- exporterVisibleAsCsv: 'خروجی داده\u200cهای قابل مشاهده در Ùایل csv',
- exporterSelectedAsCsv: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل csv',
- exporterAllAsPdf: 'خروجی تمام داده\u200cها در Ùایل pdf',
- exporterVisibleAsPdf: 'خروجی داده\u200cهای قابل مشاهده در Ùایل pdf',
- exporterSelectedAsPdf: 'خروجی داده\u200cهای انتخاب\u200cشده در Ùایل pdf',
- clearAllFilters: 'پاک کردن تمام Ùیلتر'
- },
- importer: {
- noHeaders: 'نام ستون قابل استخراج نیست. آیا Ùایل عنوان دارد؟',
- noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\u200cها در Ùایل داده وجود دارد؟',
- invalidCsv: 'Ùایل قابل پردازش نیست. آیا Ùرمت csv معتبر است؟',
- invalidJson: 'Ùایل قابل پردازش نیست. آیا Ùرمت json معتبر است؟',
- jsonNotArray: 'Ùایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'
- },
- pagination: {
- sizes: 'اقلام در هر صÙحه',
- totalItems: 'اقلام',
- of: 'از'
- },
- grouping: {
- group: 'گروه\u200cبندی',
- ungroup: 'حذ٠گروه\u200cبندی',
- aggregate_count: 'Agg: تعداد',
- aggregate_sum: 'Agg: جمع',
- aggregate_max: 'Agg: بیشینه',
- aggregate_min: 'Agg: کمینه',
- aggregate_avg: 'Agg: میانگین',
- aggregate_remove: 'Agg: حذÙ'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('fi', {
- aggregate: {
- label: 'rivit'
- },
- groupPanel: {
- description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'
- },
- search: {
- placeholder: 'Hae...',
- showingItems: 'Näytetään rivejä:',
- selectedItems: 'Valitut rivit:',
- totalItems: 'Rivejä yht.:',
- size: 'Näytä:',
- first: 'Ensimmäinen sivu',
- next: 'Seuraava sivu',
- previous: 'Edellinen sivu',
- last: 'Viimeinen sivu'
- },
- menu: {
- text: 'Valitse sarakkeet:'
- },
- sort: {
- ascending: 'Järjestä nouseva',
- descending: 'Järjestä laskeva',
- remove: 'Poista järjestys'
- },
- column: {
- hide: 'Piilota sarake'
- },
- aggregation: {
- count: 'Rivejä yht.: ',
- sum: 'Summa: ',
- avg: 'K.a.: ',
- min: 'Min: ',
- max: 'Max: '
- },
- pinning: {
- pinLeft: 'Lukitse vasemmalle',
- pinRight: 'Lukitse oikealle',
- unpin: 'Poista lukitus'
- },
- gridMenu: {
- columns: 'Sarakkeet:',
- importerTitle: 'Tuo tiedosto',
- exporterAllAsCsv: 'Vie tiedot csv-muodossa',
- exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',
- exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',
- exporterAllAsPdf: 'Vie tiedot pdf-muodossa',
- exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',
- exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa',
- clearAllFilters: 'Puhdista kaikki suodattimet'
- },
- importer: {
- noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',
- noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',
- invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',
- invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',
- jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('fr', {
- aggregate: {
- label: 'éléments'
- },
- groupPanel: {
- description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'
- },
- search: {
- placeholder: 'Recherche...',
- showingItems: 'Affichage des éléments :',
- selectedItems: 'Éléments sélectionnés :',
- totalItems: 'Nombre total d\'éléments:',
- size: 'Taille de page:',
- first: 'Première page',
- next: 'Page Suivante',
- previous: 'Page précédente',
- last: 'Dernière page'
- },
- menu: {
- text: 'Choisir des colonnes :'
- },
- sort: {
- ascending: 'Trier par ordre croissant',
- descending: 'Trier par ordre décroissant',
- remove: 'Enlever le tri'
- },
- column: {
- hide: 'Cacher la colonne'
- },
- aggregation: {
- count: 'lignes totales: ',
- sum: 'total: ',
- avg: 'moy: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Épingler à gauche',
- pinRight: 'Épingler à droite',
- unpin: 'Détacher'
- },
- gridMenu: {
- columns: 'Colonnes:',
- importerTitle: 'Importer un fichier',
- exporterAllAsCsv: 'Exporter toutes les données en CSV',
- exporterVisibleAsCsv: 'Exporter les données visibles en CSV',
- exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',
- exporterAllAsPdf: 'Exporter toutes les données en PDF',
- exporterVisibleAsPdf: 'Exporter les données visibles en PDF',
- exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF',
- clearAllFilters: 'Nettoyez tous les filtres'
- },
- importer: {
- noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',
- noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\'en-tête ?',
- invalidCsv: 'Le fichier n\'a pas pu être traité, le CSV est-il valide ?',
- invalidJson: 'Le fichier n\'a pas pu être traité, le JSON est-il valide ?',
- jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'
- },
- pagination: {
- sizes: 'éléments par page',
- totalItems: 'éléments',
- of: 'sur'
- },
- grouping: {
- group: 'Grouper',
- ungroup: 'Dégrouper',
- aggregate_count: 'Agg: Compte',
- aggregate_sum: 'Agg: Somme',
- aggregate_max: 'Agg: Max',
- aggregate_min: 'Agg: Min',
- aggregate_avg: 'Agg: Moy',
- aggregate_remove: 'Agg: Retirer'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function ($provide) {
- $provide.decorator('i18nService', ['$delegate', function ($delegate) {
- $delegate.add('he', {
- aggregate: {
- label: 'items'
- },
- groupPanel: {
- description: 'גרור עמודה לכ×ן ושחרר בכדי לקבץ עמודה זו.'
- },
- search: {
- placeholder: 'חפש...',
- showingItems: 'מציג:',
- selectedItems: 'סה"כ נבחרו:',
- totalItems: 'סה"כ רשומות:',
- size: 'תוצ×ות בדף:',
- first: 'דף ר×שון',
- next: 'דף הב×',
- previous: 'דף קוד×',
- last: 'דף ×חרון'
- },
- menu: {
- text: 'בחר עמודות:'
- },
- sort: {
- ascending: 'סדר עולה',
- descending: 'סדר יורד',
- remove: 'בטל'
- },
- column: {
- hide: 'טור הסתר'
- },
- aggregation: {
- count: 'total rows: ',
- sum: 'total: ',
- avg: 'avg: ',
- min: 'min: ',
- max: 'max: '
- },
- gridMenu: {
- columns: 'Columns:',
- importerTitle: 'Import file',
- exporterAllAsCsv: 'Export all data as csv',
- exporterVisibleAsCsv: 'Export visible data as csv',
- exporterSelectedAsCsv: 'Export selected data as csv',
- exporterAllAsPdf: 'Export all data as pdf',
- exporterVisibleAsPdf: 'Export visible data as pdf',
- exporterSelectedAsPdf: 'Export selected data as pdf',
- clearAllFilters: 'Clean all filters'
- },
- importer: {
- noHeaders: 'Column names were unable to be derived, does the file have a header?',
- noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
- invalidCsv: 'File was unable to be processed, is it valid CSV?',
- invalidJson: 'File was unable to be processed, is it valid Json?',
- jsonNotArray: 'Imported json file must contain an array, aborting.'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('hy', {
- aggregate: {
- label: 'Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€'
- },
- groupPanel: {
- description: 'Ô¸Õ½Õ¿ Õ½ÕµÕ¡Õ¶ Õ­Õ´Õ¢Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö„Õ¡Õ·Õ¥Ö„ Ö‡ Õ£ÖÕ¥Ö„ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰'
- },
- search: {
- placeholder: 'Õ“Õ¶Õ¿Ö€Õ¸Ö‚Õ´...',
- showingItems: 'Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ',
- selectedItems: 'Ô¸Õ¶Õ¿Ö€Õ¾Õ¡Õ®:',
- totalItems: 'Ô¸Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ',
- size: 'ÕÕ¸Õ²Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨ Õ§Õ»Õ¸Ö‚Õ´Õ',
- first: 'Ô±Õ¼Õ¡Õ»Õ«Õ¶ Õ§Õ»',
- next: 'Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ§Õ»',
- previous: 'Õ†Õ¡Õ­Õ¸Ö€Õ¤ Õ§Õ»',
- last: 'ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ§Õ»'
- },
- menu: {
- text: 'Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¥Ö€Õ¨:'
- },
- sort: {
- ascending: 'Ô±Õ³Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
- descending: 'Õ†Õ¾Õ¡Õ¦Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¸Õ¾',
- remove: 'Õ€Õ¡Õ¶Õ¥Õ¬ '
- },
- column: {
- hide: 'Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ½ÕµÕ¸Ö‚Õ¶Õ¨'
- },
- aggregation: {
- count: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨ Õ¿Õ¸Õ²Õ ',
- sum: 'Õ¨Õ¶Õ¤Õ¡Õ´Õ¥Õ¶Õ¨Õ ',
- avg: 'Õ´Õ«Õ»Õ«Õ¶Õ ',
- min: 'Õ´Õ«Õ¶Õ ',
- max: 'Õ´Õ¡Ö„Õ½Õ '
- },
- pinning: {
- pinLeft: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ±Õ¡Õ­ Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
- pinRight: 'Ô¿ÕºÖÕ¶Õ¥Õ¬ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´',
- unpin: 'Ô±Ö€Õ±Õ¡Õ¯Õ¥Õ¬'
- },
- gridMenu: {
- columns: 'ÕÕµÕ¸Ö‚Õ¶Õ¥Ö€:',
- importerTitle: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ Ö†Õ¡ÕµÕ¬',
- exporterAllAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨ CSV',
- exporterVisibleAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
- exporterSelectedAsCsv: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ CSV',
- exporterAllAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ PDF',
- exporterVisibleAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¥Ö€Ö‡Õ¡ÖÕ¸Õ² Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
- exporterSelectedAsPdf: 'Ô±Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ PDF',
- clearAllFilters: 'Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€Õ¨'
- },
- importer: {
- noHeaders: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ½ÕµÕ¡Õ¶ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¨ Õ¸Ö‚Õ¶Õ« Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ¥Ö€Ö‰',
- noObjects: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Ö†Õ¡ÕµÕ¬Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰',
- invalidCsv: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ CSV Õ§Ö‰',
- invalidJson: 'Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ´Õ·Õ¡Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨Ö‰ Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ¡ÕµÕ¶ Õ¾Õ¡Õ¾Õ¥Ö€ Json Õ§Ö‰',
- jsonNotArray: 'Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¾Õ¡Õ® json Ö†Õ¡ÕµÕ¬Õ¨ ÕºÕ¥Õ¿Ö„ Õ§ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ« Õ¦Õ¡Õ¶Õ£Õ¾Õ¡Õ®, Õ¯Õ¡Õ½Õ¥ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('it', {
- aggregate: {
- label: 'elementi'
- },
- groupPanel: {
- description: 'Trascina un\'intestazione all\'interno del gruppo della colonna.'
- },
- search: {
- placeholder: 'Ricerca...',
- showingItems: 'Mostra:',
- selectedItems: 'Selezionati:',
- totalItems: 'Totali:',
- size: 'Tot Pagine:',
- first: 'Prima',
- next: 'Prossima',
- previous: 'Precedente',
- last: 'Ultima'
- },
- menu: {
- text: 'Scegli le colonne:'
- },
- sort: {
- ascending: 'Asc.',
- descending: 'Desc.',
- remove: 'Annulla ordinamento'
- },
- column: {
- hide: 'Nascondi'
- },
- aggregation: {
- count: 'righe totali: ',
- sum: 'tot: ',
- avg: 'media: ',
- min: 'minimo: ',
- max: 'massimo: '
- },
- pinning: {
- pinLeft: 'Blocca a sx',
- pinRight: 'Blocca a dx',
- unpin: 'Blocca in alto'
- },
- gridMenu: {
- columns: 'Colonne:',
- importerTitle: 'Importa',
- exporterAllAsCsv: 'Esporta tutti i dati in CSV',
- exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',
- exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',
- exporterAllAsPdf: 'Esporta tutti i dati in PDF',
- exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',
- exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF',
- clearAllFilters: 'Pulire tutti i filtri'
- },
- importer: {
- noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\'interno del file?',
- noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\'interno del file?',
- invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',
- invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',
- jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'
- },
- grouping: {
- group: 'Raggruppa',
- ungroup: 'Separa',
- aggregate_count: 'Agg: N. Elem.',
- aggregate_sum: 'Agg: Somma',
- aggregate_max: 'Agg: Massimo',
- aggregate_min: 'Agg: Minimo',
- aggregate_avg: 'Agg: Media',
- aggregate_remove: 'Agg: Rimuovi'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function() {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('ja', {
- aggregate: {
- label: 'é …ç›®'
- },
- groupPanel: {
- description: 'ã“ã“ã«åˆ—ヘッダをドラッグアンドドロップã—ã¦ã€ãã®åˆ—ã§ã‚°ãƒ«ãƒ¼ãƒ—化ã—ã¾ã™ã€‚'
- },
- search: {
- placeholder: '検索...',
- showingItems: '表示中ã®é …ç›®:',
- selectedItems: 'é¸æŠžã—ãŸé …ç›®:',
- totalItems: 'é …ç›®ã®ç·æ•°:',
- size: 'ページサイズ:',
- first: '最åˆã®ãƒšãƒ¼ã‚¸',
- next: '次ã®ãƒšãƒ¼ã‚¸',
- previous: 'å‰ã®ãƒšãƒ¼ã‚¸',
- last: 'å‰ã®ãƒšãƒ¼ã‚¸'
- },
- menu: {
- text: '列ã®é¸æŠž:'
- },
- sort: {
- ascending: '昇順ã«ä¸¦ã¹æ›¿ãˆ',
- descending: 'é™é †ã«ä¸¦ã¹æ›¿ãˆ',
- remove: '並ã¹æ›¿ãˆã®è§£é™¤'
- },
- column: {
- hide: '列ã®éžè¡¨ç¤º'
- },
- aggregation: {
- count: 'åˆè¨ˆè¡Œæ•°: ',
- sum: 'åˆè¨ˆ: ',
- avg: 'å¹³å‡: ',
- min: '最å°: ',
- max: '最大: '
- },
- pinning: {
- pinLeft: 'å·¦ã«å›ºå®š',
- pinRight: 'å³ã«å›ºå®š',
- unpin: '固定解除'
- },
- gridMenu: {
- columns: '列:',
- importerTitle: 'ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ',
- exporterAllAsCsv: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- exporterVisibleAsCsv: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- exporterSelectedAsCsv: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- exporterAllAsPdf: 'ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- exporterVisibleAsPdf: '表示中ã®ãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- exporterSelectedAsPdf: 'é¸æŠžã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’PDFå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ',
- clearAllFilters: 'ã™ã¹ã¦ã®ãƒ•ã‚£ãƒ«ã‚¿ã‚’清掃ã—ã¦ãã ã•ã„'
- },
- importer: {
- noHeaders: '列åã‚’å–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
- noObjects: 'オブジェクトをå–å¾—ã§ãã¾ã›ã‚“。ファイルã«ãƒ˜ãƒƒãƒ€ä»¥å¤–ã®ãƒ‡ãƒ¼ã‚¿ãŒå«ã¾ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
- invalidCsv: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªCSVå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
- invalidJson: 'ファイルを処ç†ã§ãã¾ã›ã‚“。ファイルãŒæœ‰åŠ¹ãªJSONå½¢å¼ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。',
- jsonNotArray: 'インãƒãƒ¼ãƒˆã—ãŸJSONファイルã«ã¯é…列ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚処ç†ã‚’中止ã—ã¾ã™ã€‚'
- },
- pagination: {
- sizes: '項目/ページ',
- totalItems: 'é …ç›®'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('ko', {
- aggregate: {
- label: 'ì•„ì´í…œ'
- },
- groupPanel: {
- description: '컬럼으로 그룹핑하기 위해서는 컬럼 í—¤ë”를 ëŒì–´ 떨어뜨려 주세요.'
- },
- search: {
- placeholder: '검색...',
- showingItems: '항목 보여주기:',
- selectedItems: 'ì„ íƒ í•­ëª©:',
- totalItems: '전체 항목:',
- size: '페ì´ì§€ í¬ê¸°:',
- first: '첫번째 페ì´ì§€',
- next: 'ë‹¤ìŒ íŽ˜ì´ì§€',
- previous: 'ì´ì „ 페ì´ì§€',
- last: '마지막 페ì´ì§€'
- },
- menu: {
- text: 'ì»¬ëŸ¼ì„ ì„ íƒí•˜ì„¸ìš”:'
- },
- sort: {
- ascending: '오름차순 정렬',
- descending: '내림차순 정렬',
- remove: '소팅 제거'
- },
- column: {
- hide: '컬럼 제거'
- },
- aggregation: {
- count: '전체 갯수: ',
- sum: 'ì „ì²´: ',
- avg: 'í‰ê· : ',
- min: '최소: ',
- max: '최대: '
- },
- pinning: {
- pinLeft: '왼쪽 핀',
- pinRight: '오른쪽 핀',
- unpin: '핀 제거'
- },
- gridMenu: {
- columns: '컬럼:',
- importerTitle: 'íŒŒì¼ ê°€ì ¸ì˜¤ê¸°',
- exporterAllAsCsv: 'csvë¡œ 모든 ë°ì´í„° 내보내기',
- exporterVisibleAsCsv: 'csvë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
- exporterSelectedAsCsv: 'csvë¡œ ì„ íƒëœ ë°ì´í„° 내보내기',
- exporterAllAsPdf: 'pdfë¡œ 모든 ë°ì´í„° 내보내기',
- exporterVisibleAsPdf: 'pdfë¡œ ë³´ì´ëŠ” ë°ì´í„° 내보내기',
- exporterSelectedAsPdf: 'pdfë¡œ ì„ íƒ ë°ì´í„° 내보내기',
- clearAllFilters: '모든 필터를 청소'
- },
- importer: {
- noHeaders: 'ì»¬ëŸ¼ëª…ì´ ì§€ì •ë˜ì–´ 있지 않습니다. 파ì¼ì— í—¤ë”ê°€ 명시ë˜ì–´ 있는지 확ì¸í•´ 주세요.',
- noObjects: 'ë°ì´í„°ê°€ 지정ë˜ì–´ 있지 않습니다. ë°ì´í„°ê°€ 파ì¼ì— 있는지 확ì¸í•´ 주세요.',
- invalidCsv: '파ì¼ì„ 처리할 수 없습니다. 올바른 csvì¸ì§€ 확ì¸í•´ 주세요.',
- invalidJson: '파ì¼ì„ 처리할 수 없습니다. 올바른 jsonì¸ì§€ 확ì¸í•´ 주세요.',
- jsonNotArray: 'json 파ì¼ì€ ë°°ì—´ì„ í¬í•¨í•´ì•¼ 합니다.'
- },
- pagination: {
- sizes: '페ì´ì§€ë‹¹ 항목',
- totalItems: '전체 항목'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('nl', {
- aggregate: {
- label: 'items'
- },
- groupPanel: {
- description: 'Sleep hier een kolomnaam heen om op te groeperen.'
- },
- search: {
- placeholder: 'Zoeken...',
- showingItems: 'Getoonde items:',
- selectedItems: 'Geselecteerde items:',
- totalItems: 'Totaal aantal items:',
- size: 'Items per pagina:',
- first: 'Eerste pagina',
- next: 'Volgende pagina',
- previous: 'Vorige pagina',
- last: 'Laatste pagina'
- },
- menu: {
- text: 'Kies kolommen:'
- },
- sort: {
- ascending: 'Sorteer oplopend',
- descending: 'Sorteer aflopend',
- remove: 'Verwijder sortering'
- },
- column: {
- hide: 'Verberg kolom'
- },
- aggregation: {
- count: 'Aantal rijen: ',
- sum: 'Som: ',
- avg: 'Gemiddelde: ',
- min: 'Min: ',
- max: 'Max: '
- },
- pinning: {
- pinLeft: 'Zet links vast',
- pinRight: 'Zet rechts vast',
- unpin: 'Maak los'
- },
- gridMenu: {
- columns: 'Kolommen:',
- importerTitle: 'Importeer bestand',
- exporterAllAsCsv: 'Exporteer alle data als csv',
- exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',
- exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',
- exporterAllAsPdf: 'Exporteer alle data als pdf',
- exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',
- exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf',
- clearAllFilters: 'Reinig alle filters'
- },
- importer: {
- noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',
- noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',
- invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',
- invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',
- jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'
- },
- pagination: {
- sizes: 'items per pagina',
- totalItems: 'items',
- of: 'van de'
- },
- grouping: {
- group: 'Groepeer',
- ungroup: 'Groepering opheffen',
- aggregate_count: 'Agg: Aantal',
- aggregate_sum: 'Agg: Som',
- aggregate_max: 'Agg: Max',
- aggregate_min: 'Agg: Min',
- aggregate_avg: 'Agg: Gem',
- aggregate_remove: 'Agg: Verwijder'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('pt-br', {
- aggregate: {
- label: 'itens'
- },
- groupPanel: {
- description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
- },
- search: {
- placeholder: 'Procurar...',
- showingItems: 'Mostrando os Itens:',
- selectedItems: 'Items Selecionados:',
- totalItems: 'Total de Itens:',
- size: 'Tamanho da Página:',
- first: 'Primeira Página',
- next: 'Próxima Página',
- previous: 'Página Anterior',
- last: 'Última Página'
- },
- menu: {
- text: 'Selecione as colunas:'
- },
- sort: {
- ascending: 'Ordenar Ascendente',
- descending: 'Ordenar Descendente',
- remove: 'Remover Ordenação'
- },
- column: {
- hide: 'Esconder coluna'
- },
- aggregation: {
- count: 'total de linhas: ',
- sum: 'total: ',
- avg: 'med: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Fixar Esquerda',
- pinRight: 'Fixar Direita',
- unpin: 'Desprender'
- },
- gridMenu: {
- columns: 'Colunas:',
- importerTitle: 'Importar arquivo',
- exporterAllAsCsv: 'Exportar todos os dados como csv',
- exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
- exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
- exporterAllAsPdf: 'Exportar todos os dados como pdf',
- exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
- exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
- clearAllFilters: 'Limpar todos os filtros'
- },
- importer: {
- noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',
- noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',
- invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',
- invalidJson: 'Arquivo não pode ser processado. É um Json válido?',
- jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'
- },
- pagination: {
- sizes: 'itens por página',
- totalItems: 'itens'
- },
- grouping: {
- group: 'Agrupar',
- ungroup: 'Desagrupar',
- aggregate_count: 'Agr: Contar',
- aggregate_sum: 'Agr: Soma',
- aggregate_max: 'Agr: Max',
- aggregate_min: 'Agr: Min',
- aggregate_avg: 'Agr: Med',
- aggregate_remove: 'Agr: Remover'
- }
- });
- return $delegate;
- }]);
-}]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('pt', {
- aggregate: {
- label: 'itens'
- },
- groupPanel: {
- description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
- },
- search: {
- placeholder: 'Procurar...',
- showingItems: 'Mostrando os Itens:',
- selectedItems: 'Itens Selecionados:',
- totalItems: 'Total de Itens:',
- size: 'Tamanho da Página:',
- first: 'Primeira Página',
- next: 'Próxima Página',
- previous: 'Página Anterior',
- last: 'Última Página'
- },
- menu: {
- text: 'Selecione as colunas:'
- },
- sort: {
- ascending: 'Ordenar Ascendente',
- descending: 'Ordenar Descendente',
- remove: 'Remover Ordenação'
- },
- column: {
- hide: 'Esconder coluna'
- },
- aggregation: {
- count: 'total de linhas: ',
- sum: 'total: ',
- avg: 'med: ',
- min: 'min: ',
- max: 'max: '
- },
- pinning: {
- pinLeft: 'Fixar Esquerda',
- pinRight: 'Fixar Direita',
- unpin: 'Desprender'
- },
- gridMenu: {
- columns: 'Colunas:',
- importerTitle: 'Importar ficheiro',
- exporterAllAsCsv: 'Exportar todos os dados como csv',
- exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
- exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
- exporterAllAsPdf: 'Exportar todos os dados como pdf',
- exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
- exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
- clearAllFilters: 'Limpar todos os filtros'
- },
- importer: {
- noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',
- noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',
- invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',
- invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',
- jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'
- },
- pagination: {
- sizes: 'itens por página',
- totalItems: 'itens',
- of: 'de'
- },
- grouping: {
- group: 'Agrupar',
- ungroup: 'Desagrupar',
- aggregate_count: 'Agr: Contar',
- aggregate_sum: 'Agr: Soma',
- aggregate_max: 'Agr: Max',
- aggregate_min: 'Agr: Min',
- aggregate_avg: 'Agr: Med',
- aggregate_remove: 'Agr: Remover'
- }
- });
- return $delegate;
- }]);
-}]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('ru', {
- aggregate: {
- label: 'Ñлементы'
- },
- groupPanel: {
- description: 'Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ по Ñтолбцу перетащите Ñюда его название.'
- },
- search: {
- placeholder: 'ПоиÑк...',
- showingItems: 'Показать Ñлементы:',
- selectedItems: 'Выбранные Ñлементы:',
- totalItems: 'Ð’Ñего Ñлементов:',
- size: 'Размер Ñтраницы:',
- first: 'ÐŸÐµÑ€Ð²Ð°Ñ Ñтраница',
- next: 'Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница',
- previous: 'ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница',
- last: 'ПоÑледнÑÑ Ñтраница'
- },
- menu: {
- text: 'Выбрать Ñтолбцы:'
- },
- sort: {
- ascending: 'По возраÑтанию',
- descending: 'По убыванию',
- remove: 'Убрать Ñортировку'
- },
- column: {
- hide: 'СпрÑтать Ñтолбец'
- },
- aggregation: {
- count: 'вÑего Ñтрок: ',
- sum: 'итого: ',
- avg: 'Ñреднее: ',
- min: 'мин: ',
- max: 'макÑ: '
- },
- pinning: {
- pinLeft: 'Закрепить Ñлева',
- pinRight: 'Закрепить Ñправа',
- unpin: 'Открепить'
- },
- gridMenu: {
- columns: 'Столбцы:',
- importerTitle: 'Import file',
- exporterAllAsCsv: 'ЭкÑпортировать вÑÑ‘ в CSV',
- exporterVisibleAsCsv: 'ЭкÑпортировать видимые данные в CSV',
- exporterSelectedAsCsv: 'ЭкÑпортировать выбранные данные в CSV',
- exporterAllAsPdf: 'ЭкÑпортировать вÑÑ‘ в PDF',
- exporterVisibleAsPdf: 'ЭкÑпортировать видимые данные в PDF',
- exporterSelectedAsPdf: 'ЭкÑпортировать выбранные данные в PDF',
- clearAllFilters: 'ОчиÑтите вÑе фильтры'
- },
- importer: {
- noHeaders: 'Column names were unable to be derived, does the file have a header?',
- noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
- invalidCsv: 'File was unable to be processed, is it valid CSV?',
- invalidJson: 'File was unable to be processed, is it valid Json?',
- jsonNotArray: 'Imported json file must contain an array, aborting.'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('sk', {
- aggregate: {
- label: 'items'
- },
- groupPanel: {
- description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'
- },
- search: {
- placeholder: 'Hľadaj...',
- showingItems: 'Zobrazujem položky:',
- selectedItems: 'Vybraté položky:',
- totalItems: 'PoÄet položiek:',
- size: 'PoÄet:',
- first: 'Prvá strana',
- next: 'Ďalšia strana',
- previous: 'Predchádzajúca strana',
- last: 'Posledná strana'
- },
- menu: {
- text: 'Vyberte stĺpce:'
- },
- sort: {
- ascending: 'Zotriediť vzostupne',
- descending: 'Zotriediť zostupne',
- remove: 'Vymazať triedenie'
- },
- aggregation: {
- count: 'total rows: ',
- sum: 'total: ',
- avg: 'avg: ',
- min: 'min: ',
- max: 'max: '
- },
- gridMenu: {
- columns: 'Columns:',
- importerTitle: 'Import file',
- exporterAllAsCsv: 'Export all data as csv',
- exporterVisibleAsCsv: 'Export visible data as csv',
- exporterSelectedAsCsv: 'Export selected data as csv',
- exporterAllAsPdf: 'Export all data as pdf',
- exporterVisibleAsPdf: 'Export visible data as pdf',
- exporterSelectedAsPdf: 'Export selected data as pdf',
- clearAllFilters: 'Clear all filters'
- },
- importer: {
- noHeaders: 'Column names were unable to be derived, does the file have a header?',
- noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
- invalidCsv: 'File was unable to be processed, is it valid CSV?',
- invalidJson: 'File was unable to be processed, is it valid Json?',
- jsonNotArray: 'Imported json file must contain an array, aborting.'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('sv', {
- aggregate: {
- label: 'Artiklar'
- },
- groupPanel: {
- description: 'Dra en kolumnrubrik hit och släpp den för gruppera efter den kolumnen.'
- },
- search: {
- placeholder: 'Sök...',
- showingItems: 'Visar artiklar:',
- selectedItems: 'Valda artiklar:',
- totalItems: 'Antal artiklar:',
- size: 'Sidstorlek:',
- first: 'Första sidan',
- next: 'Nästa sida',
- previous: 'Föregående sida',
- last: 'Sista sidan'
- },
- menu: {
- text: 'Välj kolumner:'
- },
- sort: {
- ascending: 'Sortera stigande',
- descending: 'Sortera fallande',
- remove: 'Inaktivera sortering'
- },
- column: {
- hide: 'Göm kolumn'
- },
- aggregation: {
- count: 'Antal rader: ',
- sum: 'Summa: ',
- avg: 'Genomsnitt: ',
- min: 'Min: ',
- max: 'Max: '
- },
- pinning: {
- pinLeft: 'Fäst vänster',
- pinRight: 'Fäst höger',
- unpin: 'Lösgör'
- },
- gridMenu: {
- columns: 'Kolumner:',
- importerTitle: 'Importera fil',
- exporterAllAsCsv: 'Exportera all data som CSV',
- exporterVisibleAsCsv: 'Exportera synlig data som CSV',
- exporterSelectedAsCsv: 'Exportera markerad data som CSV',
- exporterAllAsPdf: 'Exportera all data som PDF',
- exporterVisibleAsPdf: 'Exportera synlig data som PDF',
- exporterSelectedAsPdf: 'Exportera markerad data som PDF',
- clearAllFilters: 'Rengör alla filter'
- },
- importer: {
- noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',
- noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',
- invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',
- invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',
- jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'
- },
- pagination: {
- sizes: 'Artiklar per sida',
- totalItems: 'Artiklar'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function () {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('ta', {
- aggregate: {
- label: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯'
- },
- groupPanel: {
- description: 'ஒர௠பதà¯à®¤à®¿à®¯à¯ˆ கà¯à®´à¯à®µà®¾à®• அமைகà¯à®• அபà¯à®ªà®¤à¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯ˆ இஙà¯à®•à¯‡ இழà¯à®¤à¯à®¤à¯ வரவà¯à®®à¯ '
- },
- search: {
- placeholder: 'தேடல௠...',
- showingItems: 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ˆ காணà¯à®ªà®¿à®¤à¯à®¤à®²à¯:',
- selectedItems: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
- totalItems: 'மொதà¯à®¤ உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯:',
- size: 'பகà¯à®• அளவà¯: ',
- first: 'à®®à¯à®¤à®²à¯ பகà¯à®•à®®à¯',
- next: 'அடà¯à®¤à¯à®¤ பகà¯à®•à®®à¯',
- previous: 'à®®à¯à®¨à¯à®¤à¯ˆà®¯ பகà¯à®•à®®à¯ ',
- last: 'இறà¯à®¤à®¿ பகà¯à®•à®®à¯'
- },
- menu: {
- text: 'பதà¯à®¤à®¿à®•à®³à¯ˆ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯:'
- },
- sort: {
- ascending: 'மேலிரà¯à®¨à¯à®¤à¯ கீழாக',
- descending: 'கீழிரà¯à®¨à¯à®¤à¯ மேலாக',
- remove: 'வரிசையை நீகà¯à®•à¯'
- },
- column: {
- hide: 'பதà¯à®¤à®¿à®¯à¯ˆ மறைதà¯à®¤à¯ வை '
- },
- aggregation: {
- count: 'மொதà¯à®¤ வரிகளà¯:',
- sum: 'மொதà¯à®¤à®®à¯: ',
- avg: 'சராசரி: ',
- min: 'கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®š: ',
- max: 'அதிகபடà¯à®š: '
- },
- pinning: {
- pinLeft: 'இடதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®• ',
- pinRight: 'வலதà¯à®ªà¯à®±à®®à®¾à®• தைகà¯à®•',
- unpin: 'பிரி'
- },
- gridMenu: {
- columns: 'பதà¯à®¤à®¿à®•à®³à¯:',
- importerTitle: 'கோபà¯à®ªà¯ : படிதà¯à®¤à®²à¯',
- exporterAllAsCsv: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
- exporterVisibleAsCsv: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
- exporterSelectedAsCsv: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: csv',
- exporterAllAsPdf: 'எலà¯à®²à®¾ தரவà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
- exporterVisibleAsPdf: 'இரà¯à®•à¯à®•à¯à®®à¯ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
- exporterSelectedAsPdf: 'தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ தரவà¯à®•à®³à¯ˆ கோபà¯à®ªà®¾à®•à¯à®•à¯: pdf',
- clearAllFilters: 'Clear all filters'
- },
- importer: {
- noHeaders: 'பதà¯à®¤à®¿à®¯à®¿à®©à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ பெற இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà®¿à®±à¯à®•à¯ தலைபà¯à®ªà¯ உளà¯à®³à®¤à®¾?',
- noObjects: 'இலகà¯à®•à¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ, கோபà¯à®ªà®¿à®²à¯ தலைபà¯à®ªà¯à®•à®³à¯ˆ தவிர தரவ௠à®à®¤à¯‡à®©à¯à®®à¯ உளà¯à®³à®¤à®¾? ',
- invalidCsv: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - csv',
- invalidJson: 'சரிவர நடைமà¯à®±à¯ˆ படà¯à®¤à¯à®¤ இயலவிலà¯à®²à¯ˆ, கோபà¯à®ªà¯ சரிதானா? - json',
- jsonNotArray: 'படிதà¯à®¤ கோபà¯à®ªà®¿à®²à¯ வரிசைகள௠உளà¯à®³à®¤à¯, நடைமà¯à®±à¯ˆ ரதà¯à®¤à¯ செய௠: json'
- },
- pagination: {
- sizes : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ / பகà¯à®•à®®à¯',
- totalItems : 'உரà¯à®ªà¯à®ªà®Ÿà®¿à®•à®³à¯ '
- },
- grouping: {
- group : 'கà¯à®´à¯',
- ungroup : 'பிரி',
- aggregate_count : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : எணà¯à®£à¯',
- aggregate_sum : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கூடà¯à®Ÿà®²à¯',
- aggregate_max : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : அதிகபடà¯à®šà®®à¯',
- aggregate_min : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯',
- aggregate_avg : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : சராசரி',
- aggregate_remove : 'மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯ : நீகà¯à®•à¯'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-/**
- * @ngdoc overview
- * @name ui.grid.i18n
- * @description
- *
- * # ui.grid.i18n
- * This module provides i18n functions to ui.grid and any application that wants to use it
-
- *
- * <div doc-module-components="ui.grid.i18n"></div>
- */
-
-(function () {
- var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];
- var FILTER_ALIASES = ['t', 'uiTranslate'];
-
- var module = angular.module('ui.grid.i18n');
-
-
- /**
- * @ngdoc object
- * @name ui.grid.i18n.constant:i18nConstants
- *
- * @description constants available in i18n module
- */
- module.constant('i18nConstants', {
- MISSING: '[MISSING]',
- UPDATE_EVENT: '$uiI18n',
-
- LOCALE_DIRECTIVE_ALIAS: 'uiI18n',
- // default to english
- DEFAULT_LANG: 'en'
- });
-
-// module.config(['$provide', function($provide) {
-// $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);
-
- /**
- * @ngdoc service
- * @name ui.grid.i18n.service:i18nService
- *
- * @description Services for i18n
- */
- module.service('i18nService', ['$log', 'i18nConstants', '$rootScope',
- function ($log, i18nConstants, $rootScope) {
-
- var langCache = {
- _langs: {},
- current: null,
- get: function (lang) {
- return this._langs[lang.toLowerCase()];
- },
- add: function (lang, strings) {
- var lower = lang.toLowerCase();
- if (!this._langs[lower]) {
- this._langs[lower] = {};
- }
- angular.extend(this._langs[lower], strings);
- },
- getAllLangs: function () {
- var langs = [];
- if (!this._langs) {
- return langs;
- }
-
- for (var key in this._langs) {
- langs.push(key);
- }
-
- return langs;
- },
- setCurrent: function (lang) {
- this.current = lang.toLowerCase();
- },
- getCurrentLang: function () {
- return this.current;
- }
- };
-
- var service = {
-
- /**
- * @ngdoc service
- * @name add
- * @methodOf ui.grid.i18n.service:i18nService
- * @description Adds the languages and strings to the cache. Decorate this service to
- * add more translation strings
- * @param {string} lang language to add
- * @param {object} stringMaps of strings to add grouped by property names
- * @example
- * <pre>
- * i18nService.add('en', {
- * aggregate: {
- * label1: 'items',
- * label2: 'some more items'
- * }
- * },
- * groupPanel: {
- * description: 'Drag a column header here and drop it to group by that column.'
- * }
- * }
- * </pre>
- */
- add: function (langs, stringMaps) {
- if (typeof(langs) === 'object') {
- angular.forEach(langs, function (lang) {
- if (lang) {
- langCache.add(lang, stringMaps);
- }
- });
- } else {
- langCache.add(langs, stringMaps);
- }
- },
-
- /**
- * @ngdoc service
- * @name getAllLangs
- * @methodOf ui.grid.i18n.service:i18nService
- * @description return all currently loaded languages
- * @returns {array} string
- */
- getAllLangs: function () {
- return langCache.getAllLangs();
- },
-
- /**
- * @ngdoc service
- * @name get
- * @methodOf ui.grid.i18n.service:i18nService
- * @description return all currently loaded languages
- * @param {string} lang to return. If not specified, returns current language
- * @returns {object} the translation string maps for the language
- */
- get: function (lang) {
- var language = lang ? lang : service.getCurrentLang();
- return langCache.get(language);
- },
-
- /**
- * @ngdoc service
- * @name getSafeText
- * @methodOf ui.grid.i18n.service:i18nService
- * @description returns the text specified in the path or a Missing text if text is not found
- * @param {string} path property path to use for retrieving text from string map
- * @param {string} lang to return. If not specified, returns current language
- * @returns {object} the translation for the path
- * @example
- * <pre>
- * i18nService.getSafeText('sort.ascending')
- * </pre>
- */
- getSafeText: function (path, lang) {
- var language = lang ? lang : service.getCurrentLang();
- var trans = langCache.get(language);
-
- if (!trans) {
- return i18nConstants.MISSING;
- }
-
- var paths = path.split('.');
- var current = trans;
-
- for (var i = 0; i < paths.length; ++i) {
- if (current[paths[i]] === undefined || current[paths[i]] === null) {
- return i18nConstants.MISSING;
- } else {
- current = current[paths[i]];
- }
- }
-
- return current;
-
- },
-
- /**
- * @ngdoc service
- * @name setCurrentLang
- * @methodOf ui.grid.i18n.service:i18nService
- * @description sets the current language to use in the application
- * $broadcasts the Update_Event on the $rootScope
- * @param {string} lang to set
- * @example
- * <pre>
- * i18nService.setCurrentLang('fr');
- * </pre>
- */
-
- setCurrentLang: function (lang) {
- if (lang) {
- langCache.setCurrent(lang);
- $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);
- }
- },
-
- /**
- * @ngdoc service
- * @name getCurrentLang
- * @methodOf ui.grid.i18n.service:i18nService
- * @description returns the current language used in the application
- */
- getCurrentLang: function () {
- var lang = langCache.getCurrentLang();
- if (!lang) {
- lang = i18nConstants.DEFAULT_LANG;
- langCache.setCurrent(lang);
- }
- return lang;
- }
-
- };
-
- return service;
-
- }]);
-
- var localeDirective = function (i18nService, i18nConstants) {
- return {
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs) {
- var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;
- // check for watchable property
- var lang = $scope.$eval($attrs[alias]);
- if (lang) {
- $scope.$watch($attrs[alias], function () {
- i18nService.setCurrentLang(lang);
- });
- } else if ($attrs.$$observers) {
- $attrs.$observe(alias, function () {
- i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);
- });
- }
- }
- };
- }
- };
- };
-
- module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);
-
- // directive syntax
- var uitDirective = function ($parse, i18nService, i18nConstants) {
- return {
- restrict: 'EA',
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs) {
- var alias1 = DIRECTIVE_ALIASES[0],
- alias2 = DIRECTIVE_ALIASES[1];
- var token = $attrs[alias1] || $attrs[alias2] || $elm.html();
- var missing = i18nConstants.MISSING + token;
- var observer;
- if ($attrs.$$observers) {
- var prop = $attrs[alias1] ? alias1 : alias2;
- observer = $attrs.$observe(prop, function (result) {
- if (result) {
- $elm.html($parse(result)(i18nService.getCurrentLang()) || missing);
- }
- });
- }
- var getter = $parse(token);
- var listener = $scope.$on(i18nConstants.UPDATE_EVENT, function (evt) {
- if (observer) {
- observer($attrs[alias1] || $attrs[alias2]);
- } else {
- // set text based on i18n current language
- $elm.html(getter(i18nService.get()) || missing);
- }
- });
- $scope.$on('$destroy', listener);
-
- $elm.html(getter(i18nService.get()) || missing);
- }
- };
- }
- };
- };
-
- angular.forEach( DIRECTIVE_ALIASES, function ( alias ) {
- module.directive( alias, ['$parse', 'i18nService', 'i18nConstants', uitDirective] );
- } );
-
- // optional filter syntax
- var uitFilter = function ($parse, i18nService, i18nConstants) {
- return function (data) {
- var getter = $parse(data);
- // set text based on i18n current language
- return getter(i18nService.get()) || i18nConstants.MISSING + data;
- };
- };
-
- angular.forEach( FILTER_ALIASES, function ( alias ) {
- module.filter( alias, ['$parse', 'i18nService', 'i18nConstants', uitFilter] );
- } );
-
-
-})();
-(function() {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('zh-cn', {
- headerCell: {
- aria: {
- defaultFilterLabel: '列过滤器',
- removeFilter: '移除过滤器',
- columnMenuButtonLabel: '列èœå•'
- },
- priority: '优先级:',
- filterLabel: "列过滤器: "
- },
- aggregate: {
- label: '行'
- },
- groupPanel: {
- description: '拖曳表头到此处进行分组'
- },
- search: {
- placeholder: '查找',
- showingItems: '已显示行数:',
- selectedItems: '已选择行数:',
- totalItems: '总行数:',
- size: 'æ¯é¡µæ˜¾ç¤ºè¡Œæ•°ï¼š',
- first: '首页',
- next: '下一页',
- previous: '上一页',
- last: '末页'
- },
- menu: {
- text: '选择列:'
- },
- sort: {
- ascending: 'å‡åº',
- descending: 'é™åº',
- none: 'æ— åº',
- remove: 'å–消排åº'
- },
- column: {
- hide: 'éšè—列'
- },
- aggregation: {
- count: '计数:',
- sum: '求和:',
- avg: 'å‡å€¼ï¼š',
- min: '最å°å€¼ï¼š',
- max: '最大值:'
- },
- pinning: {
- pinLeft: '左侧固定',
- pinRight: 'å³ä¾§å›ºå®š',
- unpin: 'å–消固定'
- },
- columnMenu: {
- close: '关闭'
- },
- gridMenu: {
- aria: {
- buttonLabel: '表格èœå•'
- },
- columns: '列:',
- importerTitle: '导入文件',
- exporterAllAsCsv: '导出全部数æ®åˆ°CSV',
- exporterVisibleAsCsv: '导出å¯è§æ•°æ®åˆ°CSV',
- exporterSelectedAsCsv: '导出已选数æ®åˆ°CSV',
- exporterAllAsPdf: '导出全部数æ®åˆ°PDF',
- exporterVisibleAsPdf: '导出å¯è§æ•°æ®åˆ°PDF',
- exporterSelectedAsPdf: '导出已选数æ®åˆ°PDF',
- clearAllFilters: '清除所有过滤器'
- },
- importer: {
- noHeaders: '无法获å–列å,确定文件包å«è¡¨å¤´ï¼Ÿ',
- noObjects: '无法获å–æ•°æ®ï¼Œç¡®å®šæ–‡ä»¶åŒ…å«æ•°æ®ï¼Ÿ',
- invalidCsv: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„CSV文件?',
- invalidJson: '无法处ç†æ–‡ä»¶ï¼Œç¡®å®šæ˜¯åˆæ³•çš„JSON文件?',
- jsonNotArray: '导入的文件ä¸æ˜¯JSON数组ï¼'
- },
- pagination: {
- aria: {
- pageToFirst: '第一页',
- pageBack: '上一页',
- pageSelected: '当å‰é¡µ',
- pageForward: '下一页',
- pageToLast: '最åŽä¸€é¡µ'
- },
- sizes: 'è¡Œæ¯é¡µ',
- totalItems: '行',
- through: '至',
- of: 'å…±'
- },
- grouping: {
- group: '分组',
- ungroup: 'å–消分组',
- aggregate_count: 'åˆè®¡: 计数',
- aggregate_sum: 'åˆè®¡: 求和',
- aggregate_max: 'åˆè®¡: 最大',
- aggregate_min: 'åˆè®¡: 最å°',
- aggregate_avg: 'åˆè®¡: å¹³å‡',
- aggregate_remove: 'åˆè®¡: 移除'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function() {
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('i18nService', ['$delegate', function($delegate) {
- $delegate.add('zh-tw', {
- aggregate: {
- label: '行'
- },
- groupPanel: {
- description: '拖曳表頭到此處進行分組'
- },
- search: {
- placeholder: '查找',
- showingItems: '已顯示行數:',
- selectedItems: 'å·²é¸æ“‡è¡Œæ•¸ï¼š',
- totalItems: '總行數:',
- size: 'æ¯é é¡¯ç¤ºè¡Œæ•¸ï¼š',
- first: '首é ',
- next: '下壹é ',
- previous: '上壹é ',
- last: '末é '
- },
- menu: {
- text: 'é¸æ“‡åˆ—:'
- },
- sort: {
- ascending: 'å‡åº',
- descending: 'é™åº',
- remove: 'å–消排åº'
- },
- column: {
- hide: 'éš±è—列'
- },
- aggregation: {
- count: '計數:',
- sum: '求和:',
- avg: 'å‡å€¼ï¼š',
- min: '最å°å€¼ï¼š',
- max: '最大值:'
- },
- pinning: {
- pinLeft: 'å·¦å´å›ºå®š',
- pinRight: 'å³å´å›ºå®š',
- unpin: 'å–消固定'
- },
- gridMenu: {
- columns: '列:',
- importerTitle: '導入文件',
- exporterAllAsCsv: '導出全部數據到CSV',
- exporterVisibleAsCsv: '導出å¯è¦‹æ•¸æ“šåˆ°CSV',
- exporterSelectedAsCsv: '導出已é¸æ•¸æ“šåˆ°CSV',
- exporterAllAsPdf: '導出全部數據到PDF',
- exporterVisibleAsPdf: '導出å¯è¦‹æ•¸æ“šåˆ°PDF',
- exporterSelectedAsPdf: '導出已é¸æ•¸æ“šåˆ°PDF',
- clearAllFilters: '清除所有过滤器'
- },
- importer: {
- noHeaders: '無法ç²å–列å,確定文件包å«è¡¨é ­ï¼Ÿ',
- noObjects: '無法ç²å–數據,確定文件包å«æ•¸æ“šï¼Ÿ',
- invalidCsv: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„CSV文件?',
- invalidJson: '無法處ç†æ–‡ä»¶ï¼Œç¢ºå®šæ˜¯åˆæ³•çš„JSON文件?',
- jsonNotArray: '導入的文件ä¸æ˜¯JSON數組ï¼'
- },
- pagination: {
- sizes: 'è¡Œæ¯é ',
- totalItems: '行'
- }
- });
- return $delegate;
- }]);
- }]);
-})();
-
-(function() {
- 'use strict';
- /**
- * @ngdoc overview
- * @name ui.grid.autoResize
- *
- * @description
- *
- * #ui.grid.autoResize
- *
- * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
- *
- * This module provides auto-resizing functionality to UI-Grid.
- */
- var module = angular.module('ui.grid.autoResize', ['ui.grid']);
-
-
- module.directive('uiGridAutoResize', ['$timeout', 'gridUtil', function ($timeout, gridUtil) {
- return {
- require: 'uiGrid',
- scope: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var prevGridWidth, prevGridHeight;
-
- function getDimensions() {
- prevGridHeight = gridUtil.elementHeight($elm);
- prevGridWidth = gridUtil.elementWidth($elm);
- }
-
- // Initialize the dimensions
- getDimensions();
-
- var resizeTimeoutId;
- function startTimeout() {
- clearTimeout(resizeTimeoutId);
-
- resizeTimeoutId = setTimeout(function () {
- var newGridHeight = gridUtil.elementHeight($elm);
- var newGridWidth = gridUtil.elementWidth($elm);
-
- if (newGridHeight !== prevGridHeight || newGridWidth !== prevGridWidth) {
- uiGridCtrl.grid.gridHeight = newGridHeight;
- uiGridCtrl.grid.gridWidth = newGridWidth;
-
- $scope.$apply(function () {
- uiGridCtrl.grid.refresh()
- .then(function () {
- getDimensions();
-
- startTimeout();
- });
- });
- }
- else {
- startTimeout();
- }
- }, 250);
- }
-
- startTimeout();
-
- $scope.$on('$destroy', function() {
- clearTimeout(resizeTimeoutId);
- });
- }
- };
- }]);
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.cellNav
- *
- * @description
-
- #ui.grid.cellNav
-
- <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
-
- This module provides auto-resizing functionality to UI-Grid.
- */
- var module = angular.module('ui.grid.cellNav', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.constant:uiGridCellNavConstants
- *
- * @description constants available in cellNav
- */
- module.constant('uiGridCellNavConstants', {
- FEATURE_NAME: 'gridCellNav',
- CELL_NAV_EVENT: 'cellNav',
- direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},
- EVENT_TYPE: {
- KEYDOWN: 0,
- CLICK: 1,
- CLEAR: 2
- }
- });
-
-
- module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'GridRowColumn', '$q',
- function (gridUtil, uiGridConstants, uiGridCellNavConstants, GridRowColumn, $q) {
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.object:CellNav
- * @description returns a CellNav prototype function
- * @param {object} rowContainer container for rows
- * @param {object} colContainer parent column container
- * @param {object} leftColContainer column container to the left of parent
- * @param {object} rightColContainer column container to the right of parent
- */
- var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {
- this.rows = rowContainer.visibleRowCache;
- this.columns = colContainer.visibleColumnCache;
- this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];
- this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];
- this.bodyContainer = rowContainer;
- };
-
- /** returns focusable columns of all containers */
- UiGridCellNav.prototype.getFocusableCols = function () {
- var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);
-
- return allColumns.filter(function (col) {
- return col.colDef.allowCellFocus;
- });
- };
-
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.api:GridRow
- *
- * @description GridRow settings for cellNav feature, these are available to be
- * set only internally (for example, by other features)
- */
-
- /**
- * @ngdoc object
- * @name allowCellFocus
- * @propertyOf ui.grid.cellNav.api:GridRow
- * @description Enable focus on a cell within this row. If set to false then no cells
- * in this row can be focused - group header rows as an example would set this to false.
- * <br/>Defaults to true
- */
- /** returns focusable rows */
- UiGridCellNav.prototype.getFocusableRows = function () {
- return this.rows.filter(function(row) {
- return row.allowCellFocus !== false;
- });
- };
-
- UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {
- switch (direction) {
- case uiGridCellNavConstants.direction.LEFT:
- return this.getRowColLeft(curRow, curCol);
- case uiGridCellNavConstants.direction.RIGHT:
- return this.getRowColRight(curRow, curCol);
- case uiGridCellNavConstants.direction.UP:
- return this.getRowColUp(curRow, curCol);
- case uiGridCellNavConstants.direction.DOWN:
- return this.getRowColDown(curRow, curCol);
- case uiGridCellNavConstants.direction.PG_UP:
- return this.getRowColPageUp(curRow, curCol);
- case uiGridCellNavConstants.direction.PG_DOWN:
- return this.getRowColPageDown(curRow, curCol);
- }
-
- };
-
- UiGridCellNav.prototype.initializeSelection = function () {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- if (focusableCols.length === 0 || focusableRows.length === 0) {
- return null;
- }
-
- var curRowIndex = 0;
- var curColIndex = 0;
- return new GridRowColumn(focusableRows[0], focusableCols[0]); //return same row
- };
-
- UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 1
- if (curColIndex === -1) {
- curColIndex = 1;
- }
-
- var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;
-
- //get column to left
- if (nextColIndex > curColIndex) {
- // On the first row
- // if (curRowIndex === 0 && curColIndex === 0) {
- // return null;
- // }
- if (curRowIndex === 0) {
- return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
- }
- else {
- //up one row and far right column
- return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);
- }
- }
- else {
- return new GridRowColumn(curRow, focusableCols[nextColIndex]);
- }
- };
-
-
-
- UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 0
- if (curColIndex === -1) {
- curColIndex = 0;
- }
- var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;
-
- if (nextColIndex < curColIndex) {
- if (curRowIndex === focusableRows.length - 1) {
- return new GridRowColumn(curRow, focusableCols[nextColIndex]); //return same row
- }
- else {
- //down one row and far left column
- return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);
- }
- }
- else {
- return new GridRowColumn(curRow, focusableCols[nextColIndex]);
- }
- };
-
- UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 0
- if (curColIndex === -1) {
- curColIndex = 0;
- }
-
- if (curRowIndex === focusableRows.length - 1) {
- return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
- }
- else {
- //down one row
- return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);
- }
- };
-
- UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 0
- if (curColIndex === -1) {
- curColIndex = 0;
- }
-
- var pageSize = this.bodyContainer.minRowsToRender();
- if (curRowIndex >= focusableRows.length - pageSize) {
- return new GridRowColumn(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); //return last row
- }
- else {
- //down one page
- return new GridRowColumn(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);
- }
- };
-
- UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 0
- if (curColIndex === -1) {
- curColIndex = 0;
- }
-
- if (curRowIndex === 0) {
- return new GridRowColumn(curRow, focusableCols[curColIndex]); //return same row
- }
- else {
- //up one row
- return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);
- }
- };
-
- UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {
- var focusableCols = this.getFocusableCols();
- var focusableRows = this.getFocusableRows();
- var curColIndex = focusableCols.indexOf(curCol);
- var curRowIndex = focusableRows.indexOf(curRow);
-
- //could not find column in focusable Columns so set it to 0
- if (curColIndex === -1) {
- curColIndex = 0;
- }
-
- var pageSize = this.bodyContainer.minRowsToRender();
- if (curRowIndex - pageSize < 0) {
- return new GridRowColumn(focusableRows[0], focusableCols[curColIndex]); //return first row
- }
- else {
- //up one page
- return new GridRowColumn(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);
- }
- };
- return UiGridCellNav;
- }]);
-
- /**
- * @ngdoc service
- * @name ui.grid.cellNav.service:uiGridCellNavService
- *
- * @description Services for cell navigation features. If you don't like the key maps we use,
- * or the direction cells navigation, override with a service decorator (see angular docs)
- */
- module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'GridRowColumn', 'ScrollEvent',
- function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, GridRowColumn, ScrollEvent) {
-
- var service = {
-
- initializeGrid: function (grid) {
- grid.registerColumnBuilder(service.cellNavColumnBuilder);
-
-
- /**
- * @ngdoc object
- * @name ui.grid.cellNav:Grid.cellNav
- * @description cellNav properties added to grid class
- */
- grid.cellNav = {};
- grid.cellNav.lastRowCol = null;
- grid.cellNav.focusedCells = [];
-
- service.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.api:PublicApi
- *
- * @description Public Api for cellNav feature
- */
- var publicApi = {
- events: {
- cellNav: {
- /**
- * @ngdoc event
- * @name navigate
- * @eventOf ui.grid.cellNav.api:PublicApi
- * @description raised when the active cell is changed
- * <pre>
- * gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol){})
- * </pre>
- * @param {object} newRowCol new position
- * @param {object} oldRowCol old position
- */
- navigate: function (newRowCol, oldRowCol) {},
- /**
- * @ngdoc event
- * @name viewPortKeyDown
- * @eventOf ui.grid.cellNav.api:PublicApi
- * @description is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid
- * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
- * event whenever you need a keydown event on a cell
- * <br/>
- * @param {object} event keydown event
- * @param {object} rowCol current rowCol position
- */
- viewPortKeyDown: function (event, rowCol) {},
-
- /**
- * @ngdoc event
- * @name viewPortKeyPress
- * @eventOf ui.grid.cellNav.api:PublicApi
- * @description is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid
- * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
- * event whenever you need a keypress event on a cell
- * <br/>
- * @param {object} event keypress event
- * @param {object} rowCol current rowCol position
- */
- viewPortKeyPress: function (event, rowCol) {}
- }
- },
- methods: {
- cellNav: {
- /**
- * @ngdoc function
- * @name scrollToFocus
- * @methodOf ui.grid.cellNav.api:PublicApi
- * @description brings the specified row and column into view, and sets focus
- * to that cell
- * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus
- * @param {object} colDef to make visible and set focus
- * @returns {promise} a promise that is resolved after any scrolling is finished
- */
- scrollToFocus: function (rowEntity, colDef) {
- return service.scrollToFocus(grid, rowEntity, colDef);
- },
-
- /**
- * @ngdoc function
- * @name getFocusedCell
- * @methodOf ui.grid.cellNav.api:PublicApi
- * @description returns the current (or last if Grid does not have focus) focused row and column
- * <br> value is null if no selection has occurred
- */
- getFocusedCell: function () {
- return grid.cellNav.lastRowCol;
- },
-
- /**
- * @ngdoc function
- * @name getCurrentSelection
- * @methodOf ui.grid.cellNav.api:PublicApi
- * @description returns an array containing the current selection
- * <br> array is empty if no selection has occurred
- */
- getCurrentSelection: function () {
- return grid.cellNav.focusedCells;
- },
-
- /**
- * @ngdoc function
- * @name rowColSelectIndex
- * @methodOf ui.grid.cellNav.api:PublicApi
- * @description returns the index in the order in which the GridRowColumn was selected, returns -1 if the GridRowColumn
- * isn't selected
- * @param {object} rowCol the rowCol to evaluate
- */
- rowColSelectIndex: function (rowCol) {
- //return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&
- var index = -1;
- for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {
- if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&
- grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {
- index = i;
- break;
- }
- }
- return index;
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- },
-
- defaultGridOptions: function (gridOptions) {
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.api:GridOptions
- *
- * @description GridOptions for cellNav feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name modifierKeysToMultiSelectCells
- * @propertyOf ui.grid.cellNav.api:GridOptions
- * @description Enable multiple cell selection only when using the ctrlKey or shiftKey.
- * <br/>Defaults to false
- */
- gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;
-
- },
-
- /**
- * @ngdoc service
- * @name decorateRenderContainers
- * @methodOf ui.grid.cellNav.service:uiGridCellNavService
- * @description decorates grid renderContainers with cellNav functions
- */
- decorateRenderContainers: function (grid) {
-
- var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;
- var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;
-
- if (leftContainer !== null) {
- grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);
- }
- if (rightContainer !== null) {
- grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);
- }
-
- grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);
- },
-
- /**
- * @ngdoc service
- * @name getDirection
- * @methodOf ui.grid.cellNav.service:uiGridCellNavService
- * @description determines which direction to for a given keyDown event
- * @returns {uiGridCellNavConstants.direction} direction
- */
- getDirection: function (evt) {
- if (evt.keyCode === uiGridConstants.keymap.LEFT ||
- (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {
- return uiGridCellNavConstants.direction.LEFT;
- }
- if (evt.keyCode === uiGridConstants.keymap.RIGHT ||
- evt.keyCode === uiGridConstants.keymap.TAB) {
- return uiGridCellNavConstants.direction.RIGHT;
- }
-
- if (evt.keyCode === uiGridConstants.keymap.UP ||
- (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {
- return uiGridCellNavConstants.direction.UP;
- }
-
- if (evt.keyCode === uiGridConstants.keymap.PG_UP){
- return uiGridCellNavConstants.direction.PG_UP;
- }
-
- if (evt.keyCode === uiGridConstants.keymap.DOWN ||
- evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {
- return uiGridCellNavConstants.direction.DOWN;
- }
-
- if (evt.keyCode === uiGridConstants.keymap.PG_DOWN){
- return uiGridCellNavConstants.direction.PG_DOWN;
- }
-
- return null;
- },
-
- /**
- * @ngdoc service
- * @name cellNavColumnBuilder
- * @methodOf ui.grid.cellNav.service:uiGridCellNavService
- * @description columnBuilder function that adds cell navigation properties to grid column
- * @returns {promise} promise that will load any needed templates when resolved
- */
- cellNavColumnBuilder: function (colDef, col, gridOptions) {
- var promises = [];
-
- /**
- * @ngdoc object
- * @name ui.grid.cellNav.api:ColumnDef
- *
- * @description Column Definitions for cellNav feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- /**
- * @ngdoc object
- * @name allowCellFocus
- * @propertyOf ui.grid.cellNav.api:ColumnDef
- * @description Enable focus on a cell within this column.
- * <br/>Defaults to true
- */
- colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;
-
- return $q.all(promises);
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.cellNav.service:uiGridCellNavService
- * @name scrollToFocus
- * @description Scroll the grid such that the specified
- * row and column is in view, and set focus to the cell in that row and column
- * @param {Grid} grid the grid you'd like to act upon, usually available
- * from gridApi.grid
- * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to
- * @param {object} colDef to make visible and set focus to
- * @returns {promise} a promise that is resolved after any scrolling is finished
- */
- scrollToFocus: function (grid, rowEntity, colDef) {
- var gridRow = null, gridCol = null;
-
- if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {
- gridRow = grid.getRow(rowEntity);
- }
-
- if (typeof(colDef) !== 'undefined' && colDef !== null) {
- gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);
- }
- return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {
- var rowCol = { row: gridRow, col: gridCol };
-
- // Broadcast the navigation
- if (gridRow !== null && gridCol !== null) {
- grid.cellNav.broadcastCellNav(rowCol);
- }
- });
-
-
-
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.cellNav.service:uiGridCellNavService
- * @name getLeftWidth
- * @description Get the current drawn width of the columns in the
- * grid up to the numbered column, and add an apportionment for the
- * column that we're on. So if we are on column 0, we want to scroll
- * 0% (i.e. exclude this column from calc). If we're on the last column
- * we want to scroll to 100% (i.e. include this column in the calc). So
- * we include (thisColIndex / totalNumberCols) % of this column width
- * @param {Grid} grid the grid you'd like to act upon, usually available
- * from gridApi.grid
- * @param {gridCol} upToCol the column to total up to and including
- */
- getLeftWidth: function (grid, upToCol) {
- var width = 0;
-
- if (!upToCol) {
- return width;
- }
-
- var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );
-
- // total column widths up-to but not including the passed in column
- grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {
- if ( index < lastIndex ){
- width += col.drawnWidth;
- }
- });
-
- // pro-rata the final column based on % of total columns.
- var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;
- width += upToCol.drawnWidth * percentage;
-
- return width;
- }
- };
-
- return service;
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.cellNav.directive:uiCellNav
- * @element div
- * @restrict EA
- *
- * @description Adds cell navigation features to the grid columns
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.columnDefs = [
- {name: 'name'},
- {name: 'title'}
- ];
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-cellnav></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn', '$timeout', '$compile',
- function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, GridRowColumn, $timeout, $compile) {
- return {
- replace: true,
- priority: -150,
- require: '^uiGrid',
- scope: false,
- controller: function () {},
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- var _scope = $scope;
-
- var grid = uiGridCtrl.grid;
- uiGridCellNavService.initializeGrid(grid);
-
- uiGridCtrl.cellNav = {};
-
- //Ensure that the object has all of the methods we expect it to
- uiGridCtrl.cellNav.makeRowCol = function (obj) {
- if (!(obj instanceof GridRowColumn)) {
- obj = new GridRowColumn(obj.row, obj.col);
- }
- return obj;
- };
-
- uiGridCtrl.cellNav.getActiveCell = function () {
- var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');
- if (elms.length > 0){
- return elms[0];
- }
-
- return undefined;
- };
-
- uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {
- modifierDown = !(modifierDown === undefined || !modifierDown);
-
- newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);
-
- uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);
- _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);
- };
-
- uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {
- grid.cellNav.focusedCells = [];
- _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);
- };
-
- uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {
- modifierDown = !(modifierDown === undefined || !modifierDown);
-
- rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);
-
- var row = rowCol.row,
- col = rowCol.col;
-
- var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
-
- if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1) {
- var newRowCol = new GridRowColumn(row, col);
-
- grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);
- grid.cellNav.lastRowCol = newRowCol;
- if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {
- grid.cellNav.focusedCells.push(rowCol);
- } else {
- grid.cellNav.focusedCells = [rowCol];
- }
- } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&
- rowColSelectIndex >= 0) {
-
- grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
- }
- };
-
- uiGridCtrl.cellNav.handleKeyDown = function (evt) {
- var direction = uiGridCellNavService.getDirection(evt);
- if (direction === null) {
- return null;
- }
-
- var containerId = 'body';
- if (evt.uiGridTargetRenderContainerId) {
- containerId = evt.uiGridTargetRenderContainerId;
- }
-
- // Get the last-focused row+col combo
- var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
- if (lastRowCol) {
- // Figure out which new row+combo we're navigating to
- var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);
- var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();
- var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
- // Shift+tab on top-left cell should exit cellnav on render container
- if (
- // Navigating left
- direction === uiGridCellNavConstants.direction.LEFT &&
- // New col is last col (i.e. wrap around)
- rowCol.col === focusableCols[focusableCols.length - 1] &&
- // Staying on same row, which means we're at first row
- rowCol.row === lastRowCol.row &&
- evt.keyCode === uiGridConstants.keymap.TAB &&
- evt.shiftKey
- ) {
- grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
- uiGridCtrl.cellNav.clearFocus();
- return true;
- }
- // Tab on bottom-right cell should exit cellnav on render container
- else if (
- direction === uiGridCellNavConstants.direction.RIGHT &&
- // New col is first col (i.e. wrap around)
- rowCol.col === focusableCols[0] &&
- // Staying on same row, which means we're at first row
- rowCol.row === lastRowCol.row &&
- evt.keyCode === uiGridConstants.keymap.TAB &&
- !evt.shiftKey
- ) {
- grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
- uiGridCtrl.cellNav.clearFocus();
- return true;
- }
-
- // Scroll to the new cell, if it's not completely visible within the render container's viewport
- grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {
- uiGridCtrl.cellNav.broadcastCellNav(rowCol);
- });
-
-
- evt.stopPropagation();
- evt.preventDefault();
-
- return false;
- }
- };
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- var _scope = $scope;
- var grid = uiGridCtrl.grid;
-
- function addAriaLiveRegion(){
- // Thanks to google docs for the inspiration behind how to do this
- // XXX: Why is this entire mess nessasary?
- // Because browsers take a lot of coercing to get them to read out live regions
- //http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
- var ariaNotifierDomElt = '<div ' +
- 'id="' + grid.id +'-aria-speakable" ' +
- 'class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" ' +
- 'aria-live="assertive" ' +
- 'role="region" ' +
- 'aria-atomic="true" ' +
- 'aria-hidden="false" ' +
- 'aria-relevant="additions" ' +
- '>' +
- '&nbsp;' +
- '</div>';
-
- var ariaNotifier = $compile(ariaNotifierDomElt)($scope);
- $elm.prepend(ariaNotifier);
- $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {
- /*
- * If the cell nav event was because of a focus event then we don't want to
- * change the notifier text.
- * Reasoning: Voice Over fires a focus events when moving arround the grid.
- * If the screen reader is handing the grid nav properly then we don't need to
- * use the alert to notify the user of the movement.
- * In all other cases we do want a notification event.
- */
- if (originEvt && originEvt.type === 'focus'){return;}
-
- function setNotifyText(text){
- if (text === ariaNotifier.text()){return;}
- ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';
- /*
- * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''
- */
- ariaNotifier[0].innerHTML = "";
- ariaNotifier[0].style.visibility = 'hidden';
- ariaNotifier[0].style.visibility = 'visible';
- if (text !== ''){
- ariaNotifier[0].style.clip = 'auto';
- /*
- * The space after the text is something that google docs does.
- */
- ariaNotifier[0].appendChild(document.createTextNode(text + " "));
- ariaNotifier[0].style.visibility = 'hidden';
- ariaNotifier[0].style.visibility = 'visible';
- }
- }
-
- var values = [];
- var currentSelection = grid.api.cellNav.getCurrentSelection();
- for (var i = 0; i < currentSelection.length; i++) {
- values.push(currentSelection[i].getIntersectionValueFiltered());
- }
- var cellText = values.toString();
- setNotifyText(cellText);
-
- });
- }
- addAriaLiveRegion();
- }
- };
- }
- };
- }]);
-
- module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',
- function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {
- return {
- replace: true,
- priority: -99999, //this needs to run very last
- require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],
- scope: false,
- compile: function () {
- return {
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0],
- renderContainerCtrl = controllers[1],
- uiGridCellnavCtrl = controllers[2];
-
- // Skip attaching cell-nav specific logic if the directive is not attached above us
- if (!uiGridCtrl.grid.api.cellNav) { return; }
-
- var containerId = renderContainerCtrl.containerId;
-
- var grid = uiGridCtrl.grid;
-
- //run each time a render container is created
- uiGridCellNavService.decorateRenderContainers(grid);
-
- // focusser only created for body
- if (containerId !== 'body') {
- return;
- }
-
-
-
- if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells){
- $elm.attr('aria-multiselectable', true);
- } else {
- $elm.attr('aria-multiselectable', false);
- }
-
- //add an element with no dimensions that can be used to set focus and capture keystrokes
- var focuser = $compile('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'" aria-owns="' + grid.id + '-grid-container' + '"></div>')($scope);
- $elm.append(focuser);
-
- focuser.on('focus', function (evt) {
- evt.uiGridTargetRenderContainerId = containerId;
- var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
- if (rowCol === null) {
- rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);
- if (rowCol.row && rowCol.col) {
- uiGridCtrl.cellNav.broadcastCellNav(rowCol);
- }
- }
- });
-
- uiGridCellnavCtrl.setAriaActivedescendant = function(id){
- $elm.attr('aria-activedescendant', id);
- };
-
- uiGridCellnavCtrl.removeAriaActivedescendant = function(id){
- if ($elm.attr('aria-activedescendant') === id){
- $elm.attr('aria-activedescendant', '');
- }
- };
-
-
- uiGridCtrl.focus = function () {
- gridUtil.focus.byElement(focuser[0]);
- //allow for first time grid focus
- };
-
- var viewPortKeyDownWasRaisedForRowCol = null;
- // Bind to keydown events in the render container
- focuser.on('keydown', function (evt) {
- evt.uiGridTargetRenderContainerId = containerId;
- var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
- var result = uiGridCtrl.cellNav.handleKeyDown(evt);
- if (result === null) {
- uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol);
- viewPortKeyDownWasRaisedForRowCol = rowCol;
- }
- });
- //Bind to keypress events in the render container
- //keypress events are needed by edit function so the key press
- //that initiated an edit is not lost
- //must fire the event in a timeout so the editor can
- //initialize and subscribe to the event on another event loop
- focuser.on('keypress', function (evt) {
- if (viewPortKeyDownWasRaisedForRowCol) {
- $timeout(function () {
- uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);
- },4);
-
- viewPortKeyDownWasRaisedForRowCol = null;
- }
- });
-
- $scope.$on('$destroy', function(){
- //Remove all event handlers associated with this focuser.
- focuser.off();
- });
-
- }
- };
- }
- };
- }]);
-
- module.directive('uiGridViewport', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants','$log','$compile',
- function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants, $log, $compile) {
- return {
- replace: true,
- priority: -99999, //this needs to run very last
- require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- },
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0],
- renderContainerCtrl = controllers[1];
-
- // Skip attaching cell-nav specific logic if the directive is not attached above us
- if (!uiGridCtrl.grid.api.cellNav) { return; }
-
- var containerId = renderContainerCtrl.containerId;
- //no need to process for other containers
- if (containerId !== 'body') {
- return;
- }
-
- var grid = uiGridCtrl.grid;
-
- grid.api.core.on.scrollBegin($scope, function (args) {
-
- // Skip if there's no currently-focused cell
- var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
- if (lastRowCol === null) {
- return;
- }
-
- //if not in my container, move on
- //todo: worry about horiz scroll
- if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
- return;
- }
-
- uiGridCtrl.cellNav.clearFocus();
-
- });
-
- grid.api.core.on.scrollEnd($scope, function (args) {
- // Skip if there's no currently-focused cell
- var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
- if (lastRowCol === null) {
- return;
- }
-
- //if not in my container, move on
- //todo: worry about horiz scroll
- if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
- return;
- }
-
- uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
-
- });
-
- grid.api.cellNav.on.navigate($scope, function () {
- //focus again because it can be lost
- uiGridCtrl.focus();
- });
-
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.cellNav.directive:uiGridCell
- * @element div
- * @restrict A
- * @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
- */
- module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn',
- function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, GridRowColumn) {
- return {
- priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
- restrict: 'A',
- require: ['^uiGrid', '?^uiGridCellnav'],
- scope: false,
- link: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0],
- uiGridCellnavCtrl = controllers[1];
- // Skip attaching cell-nav specific logic if the directive is not attached above us
- if (!uiGridCtrl.grid.api.cellNav) { return; }
-
- if (!$scope.col.colDef.allowCellFocus) {
- return;
- }
-
- //Convinience local variables
- var grid = uiGridCtrl.grid;
- $scope.focused = false;
-
- // Make this cell focusable but only with javascript/a mouse click
- $elm.attr('tabindex', -1);
-
- // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused
- $elm.find('div').on('click', function (evt) {
- uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);
-
- evt.stopPropagation();
- $scope.$apply();
- });
-
-
- /*
- * XXX Hack for screen readers.
- * This allows the grid to focus using only the screen reader cursor.
- * Since the focus event doesn't include key press information we can't use it
- * as our primary source of the event.
- */
- $elm.on('mousedown', preventMouseDown);
-
- //turn on and off for edit events
- if (uiGridCtrl.grid.api.edit) {
- uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {
- $elm.off('mousedown', preventMouseDown);
- });
-
- uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {
- $elm.on('mousedown', preventMouseDown);
- });
-
- uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {
- $elm.on('mousedown', preventMouseDown);
- });
- }
-
- function preventMouseDown(evt) {
- //Prevents the foucus event from firing if the click event is already going to fire.
- //If both events fire it will cause bouncing behavior.
- evt.preventDefault();
- }
-
- //You can only focus on elements with a tabindex value
- $elm.on('focus', function (evt) {
- uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), false, evt);
- evt.stopPropagation();
- $scope.$apply();
- });
-
- // This event is fired for all cells. If the cell matches, then focus is set
- $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown) {
- var isFocused = grid.cellNav.focusedCells.some(function(focusedRowCol, index){
- return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);
- });
- if (isFocused){
- setFocused();
- } else {
- clearFocus();
- }
- });
-
- function setFocused() {
- if (!$scope.focused){
- var div = $elm.find('div');
- div.addClass('ui-grid-cell-focus');
- $elm.attr('aria-selected', true);
- uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));
- $scope.focused = true;
- }
- }
-
- function clearFocus() {
- if ($scope.focused){
- var div = $elm.find('div');
- div.removeClass('ui-grid-cell-focus');
- $elm.attr('aria-selected', false);
- uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));
- $scope.focused = false;
- }
- }
-
- $scope.$on('$destroy', function () {
- //.off withouth paramaters removes all handlers
- $elm.find('div').off();
- $elm.off();
- });
- }
- };
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.edit
- * @description
- *
- * # ui.grid.edit
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via
- * a keyboard.
- * <br/>
- * <br/>
- * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the
- * user to key data and then tab, arrow, or enter to the cells beside or below.
- *
- * <div doc-module-components="ui.grid.edit"></div>
- */
-
- var module = angular.module('ui.grid.edit', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.edit.constant:uiGridEditConstants
- *
- * @description constants available in edit module
- */
- module.constant('uiGridEditConstants', {
- EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,
- //must be lowercase because template bulder converts to lower
- EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,
- events: {
- BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',
- END_CELL_EDIT: 'uiGridEventEndCellEdit',
- CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'
- }
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.edit.service:uiGridEditService
- *
- * @description Services for editing features
- */
- module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',
- function ($q, uiGridConstants, gridUtil) {
-
- var service = {
-
- initializeGrid: function (grid) {
-
- service.defaultGridOptions(grid.options);
-
- grid.registerColumnBuilder(service.editColumnBuilder);
- grid.edit = {};
-
- /**
- * @ngdoc object
- * @name ui.grid.edit.api:PublicApi
- *
- * @description Public Api for edit feature
- */
- var publicApi = {
- events: {
- edit: {
- /**
- * @ngdoc event
- * @name afterCellEdit
- * @eventOf ui.grid.edit.api:PublicApi
- * @description raised when cell editing is complete
- * <pre>
- * gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef){})
- * </pre>
- * @param {object} rowEntity the options.data element that was edited
- * @param {object} colDef the column that was edited
- * @param {object} newValue new value
- * @param {object} oldValue old value
- */
- afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {
- },
- /**
- * @ngdoc event
- * @name beginCellEdit
- * @eventOf ui.grid.edit.api:PublicApi
- * @description raised when cell editing starts on a cell
- * <pre>
- * gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef){})
- * </pre>
- * @param {object} rowEntity the options.data element that was edited
- * @param {object} colDef the column that was edited
- * @param {object} triggerEvent the event that triggered the edit. Useful to prevent losing keystrokes on some
- * complex editors
- */
- beginCellEdit: function (rowEntity, colDef, triggerEvent) {
- },
- /**
- * @ngdoc event
- * @name cancelCellEdit
- * @eventOf ui.grid.edit.api:PublicApi
- * @description raised when cell editing is cancelled on a cell
- * <pre>
- * gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef){})
- * </pre>
- * @param {object} rowEntity the options.data element that was edited
- * @param {object} colDef the column that was edited
- */
- cancelCellEdit: function (rowEntity, colDef) {
- }
- }
- },
- methods: {
- edit: { }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
- //grid.api.registerMethodsFromObject(publicApi.methods);
-
- },
-
- defaultGridOptions: function (gridOptions) {
-
- /**
- * @ngdoc object
- * @name ui.grid.edit.api:GridOptions
- *
- * @description Options for configuring the edit feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enableCellEdit
- * @propertyOf ui.grid.edit.api:GridOptions
- * @description If defined, sets the default value for the editable flag on each individual colDefs
- * if their individual enableCellEdit configuration is not defined. Defaults to undefined.
- */
-
- /**
- * @ngdoc object
- * @name cellEditableCondition
- * @propertyOf ui.grid.edit.api:GridOptions
- * @description If specified, either a value or function to be used by all columns before editing.
- * If falsy, then editing of cell is not allowed.
- * @example
- * <pre>
- * function($scope){
- * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
- * return true;
- * }
- * </pre>
- */
- gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;
-
- /**
- * @ngdoc object
- * @name editableCellTemplate
- * @propertyOf ui.grid.edit.api:GridOptions
- * @description If specified, cellTemplate to use as the editor for all columns.
- * <br/> defaults to 'ui-grid/cellTextEditor'
- */
-
- /**
- * @ngdoc object
- * @name enableCellEditOnFocus
- * @propertyOf ui.grid.edit.api:GridOptions
- * @description If true, then editor is invoked as soon as cell receives focus. Default false.
- * <br/>_requires cellNav feature and the edit feature to be enabled_
- */
- //enableCellEditOnFocus can only be used if cellnav module is used
- gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;
- },
-
- /**
- * @ngdoc service
- * @name editColumnBuilder
- * @methodOf ui.grid.edit.service:uiGridEditService
- * @description columnBuilder function that adds edit properties to grid column
- * @returns {promise} promise that will load any needed templates when resolved
- */
- editColumnBuilder: function (colDef, col, gridOptions) {
-
- var promises = [];
-
- /**
- * @ngdoc object
- * @name ui.grid.edit.api:ColumnDef
- *
- * @description Column Definition for edit feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- /**
- * @ngdoc object
- * @name enableCellEdit
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description enable editing on column
- */
- colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?
- (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;
-
- /**
- * @ngdoc object
- * @name cellEditableCondition
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description If specified, either a value or function evaluated before editing cell. If falsy, then editing of cell is not allowed.
- * @example
- * <pre>
- * function($scope){
- * //use $scope.row.entity and $scope.col.colDef to determine if editing is allowed
- * return true;
- * }
- * </pre>
- */
- colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition : colDef.cellEditableCondition;
-
- /**
- * @ngdoc object
- * @name editableCellTemplate
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description cell template to be used when editing this column. Can be Url or text template
- * <br/>Defaults to gridOptions.editableCellTemplate
- */
- if (colDef.enableCellEdit) {
- colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';
-
- promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)
- .then(
- function (template) {
- col.editableCellTemplate = template;
- },
- function (res) {
- // Todo handle response error here?
- throw new Error("Couldn't fetch/use colDef.editableCellTemplate '" + colDef.editableCellTemplate + "'");
- }));
- }
-
- /**
- * @ngdoc object
- * @name enableCellEditOnFocus
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @requires ui.grid.cellNav
- * @description If true, then editor is invoked as soon as cell receives focus. Default false.
- * <br>_requires both the cellNav feature and the edit feature to be enabled_
- */
- //enableCellEditOnFocus can only be used if cellnav module is used
- colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;
-
-
- /**
- * @ngdoc string
- * @name editModelField
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description a bindable string value that is used when binding to edit controls instead of colDef.field
- * <br/> example: You have a complex property on and object like state:{abbrev:'MS',name:'Mississippi'}. The
- * grid should display state.name in the cell and sort/filter based on the state.name property but the editor
- * requires the full state object.
- * <br/>colDef.field = 'state.name'
- * <br/>colDef.editModelField = 'state'
- */
- //colDef.editModelField
-
- return $q.all(promises);
- },
-
- /**
- * @ngdoc service
- * @name isStartEditKey
- * @methodOf ui.grid.edit.service:uiGridEditService
- * @description Determines if a keypress should start editing. Decorate this service to override with your
- * own key events. See service decorator in angular docs.
- * @param {Event} evt keydown event
- * @returns {boolean} true if an edit should start
- */
- isStartEditKey: function (evt) {
- if (evt.metaKey ||
- evt.keyCode === uiGridConstants.keymap.ESC ||
- evt.keyCode === uiGridConstants.keymap.SHIFT ||
- evt.keyCode === uiGridConstants.keymap.CTRL ||
- evt.keyCode === uiGridConstants.keymap.ALT ||
- evt.keyCode === uiGridConstants.keymap.WIN ||
- evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||
-
- evt.keyCode === uiGridConstants.keymap.LEFT ||
- (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||
-
- evt.keyCode === uiGridConstants.keymap.RIGHT ||
- evt.keyCode === uiGridConstants.keymap.TAB ||
-
- evt.keyCode === uiGridConstants.keymap.UP ||
- (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||
-
- evt.keyCode === uiGridConstants.keymap.DOWN ||
- evt.keyCode === uiGridConstants.keymap.ENTER) {
- return false;
-
- }
- return true;
- }
-
-
- };
-
- return service;
-
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridEdit
- * @element div
- * @restrict A
- *
- * @description Adds editing features to the ui-grid directive.
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.columnDefs = [
- {name: 'name', enableCellEdit: true},
- {name: 'title', enableCellEdit: true}
- ];
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridEditService.initializeGrid(uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridRenderContainer
- * @element div
- * @restrict A
- *
- * @description Adds keydown listeners to renderContainer element so we can capture when to begin edits
- *
- */
- module.directive('uiGridViewport', [ 'uiGridEditConstants',
- function ( uiGridEditConstants) {
- return {
- replace: true,
- priority: -99998, //run before cellNav
- require: ['^uiGrid', '^uiGridRenderContainer'],
- scope: false,
- compile: function () {
- return {
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
-
- // Skip attaching if edit and cellNav is not enabled
- if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }
-
- var containerId = controllers[1].containerId;
- //no need to process for other containers
- if (containerId !== 'body') {
- return;
- }
-
- //refocus on the grid
- $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
- uiGridCtrl.focus();
- });
- $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
- uiGridCtrl.focus();
- });
-
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridCell
- * @element div
- * @restrict A
- *
- * @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell
- * Editing Actions.
- *
- * Binds edit start events to the uiGridCell element. When the events fire, the gridCell element is appended
- * with the columnDef.editableCellTemplate element ('cellEditor.html' by default).
- *
- * The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\_CELL\_EDIT angular event
- * and do the initial steps needed to edit the cell (setfocus on input element, etc).
- *
- * When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)
- * it should emit the uiGridEditConstants.events.END\_CELL\_EDIT event.
- *
- * If editableCellTemplate recognizes that the editing has been cancelled (esc key)
- * it should emit the uiGridEditConstants.events.CANCEL\_CELL\_EDIT event. The original value
- * will be set back on the model by the uiGridCell directive.
- *
- * Events that invoke editing:
- * - dblclick
- * - F2 keydown (when using cell selection)
- *
- * Events that end editing:
- * - Dependent on the specific editableCellTemplate
- * - Standards should be blur and enter keydown
- *
- * Events that cancel editing:
- * - Dependent on the specific editableCellTemplate
- * - Standards should be Esc keydown
- *
- * Grid Events that end editing:
- * - uiGridConstants.events.GRID_SCROLL
- *
- */
-
- /**
- * @ngdoc object
- * @name ui.grid.edit.api:GridRow
- *
- * @description GridRow options for edit feature, these are available to be
- * set internally only, by other features
- */
-
- /**
- * @ngdoc object
- * @name enableCellEdit
- * @propertyOf ui.grid.edit.api:GridRow
- * @description enable editing on row, grouping for example might disable editing on group header rows
- */
-
- module.directive('uiGridCell',
- ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope',
- function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope) {
- var touchstartTimeout = 500;
- if ($injector.has('uiGridCellNavService')) {
- var uiGridCellNavService = $injector.get('uiGridCellNavService');
- }
-
- return {
- priority: -100, // run after default uiGridCell directive
- restrict: 'A',
- scope: false,
- require: '?^uiGrid',
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var html;
- var origCellValue;
- var inEdit = false;
- var cellModel;
- var cancelTouchstartTimeout;
-
- var editCellScope;
-
- if (!$scope.col.colDef.enableCellEdit) {
- return;
- }
-
- var cellNavNavigateDereg = function() {};
- var viewPortKeyDownDereg = function() {};
-
-
- var setEditable = function() {
- if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {
- if (!$scope.beginEditEventsWired) { //prevent multiple attachments
- registerBeginEditEvents();
- }
- } else {
- if ($scope.beginEditEventsWired) {
- cancelBeginEditEvents();
- }
- }
- };
-
- setEditable();
-
- var rowWatchDereg = $scope.$watch('row', function (n, o) {
- if (n !== o) {
- setEditable();
- }
- });
-
-
- $scope.$on( '$destroy', rowWatchDereg );
-
- function registerBeginEditEvents() {
- $elm.on('dblclick', beginEdit);
-
- // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit
- $elm.on('touchstart', touchStart);
-
- if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
-
- viewPortKeyDownDereg = uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
- if (rowCol === null) {
- return;
- }
-
- if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {
- //important to do this before scrollToIfNecessary
- beginEditKeyDown(evt);
- }
- });
-
- cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {
- if ($scope.col.colDef.enableCellEditOnFocus) {
- // Don't begin edit if the cell hasn't changed
- if ((!oldRowCol || newRowCol.row !== oldRowCol.row || newRowCol.col !== oldRowCol.col) &&
- newRowCol.row === $scope.row && newRowCol.col === $scope.col) {
- $timeout(function () {
- beginEdit();
- });
- }
- }
- });
- }
-
- $scope.beginEditEventsWired = true;
-
- }
-
- function touchStart(event) {
- // jQuery masks events
- if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
- event = event.originalEvent;
- }
-
- // Bind touchend handler
- $elm.on('touchend', touchEnd);
-
- // Start a timeout
- cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);
-
- // Timeout's done! Start the edit
- cancelTouchstartTimeout.then(function () {
- // Use setTimeout to start the edit because beginEdit expects to be outside of $digest
- setTimeout(beginEdit, 0);
-
- // Undbind the touchend handler, we don't need it anymore
- $elm.off('touchend', touchEnd);
- });
- }
-
- // Cancel any touchstart timeout
- function touchEnd(event) {
- $timeout.cancel(cancelTouchstartTimeout);
- $elm.off('touchend', touchEnd);
- }
-
- function cancelBeginEditEvents() {
- $elm.off('dblclick', beginEdit);
- $elm.off('keydown', beginEditKeyDown);
- $elm.off('touchstart', touchStart);
- cellNavNavigateDereg();
- viewPortKeyDownDereg();
- $scope.beginEditEventsWired = false;
- }
-
- function beginEditKeyDown(evt) {
- if (uiGridEditService.isStartEditKey(evt)) {
- beginEdit(evt);
- }
- }
-
- function shouldEdit(col, row) {
- return !row.isSaving &&
- ( angular.isFunction(col.colDef.cellEditableCondition) ?
- col.colDef.cellEditableCondition($scope) :
- col.colDef.cellEditableCondition );
- }
-
-
- function beginEdit(triggerEvent) {
- //we need to scroll the cell into focus before invoking the editor
- $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)
- .then(function () {
- beginEditAfterScroll(triggerEvent);
- });
- }
-
- /**
- * @ngdoc property
- * @name editDropdownOptionsArray
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description an array of values in the format
- * [ {id: xxx, value: xxx} ], which is populated
- * into the edit dropdown
- *
- */
- /**
- * @ngdoc property
- * @name editDropdownIdLabel
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description the label for the "id" field
- * in the editDropdownOptionsArray. Defaults
- * to 'id'
- * @example
- * <pre>
- * $scope.gridOptions = {
- * columnDefs: [
- * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
- * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
- * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
- * ],
- * </pre>
- *
- */
- /**
- * @ngdoc property
- * @name editDropdownRowEntityOptionsArrayPath
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description a path to a property on row.entity containing an
- * array of values in the format
- * [ {id: xxx, value: xxx} ], which will be used to populate
- * the edit dropdown. This can be used when the dropdown values are dependent on
- * the backing row entity.
- * If this property is set then editDropdownOptionsArray will be ignored.
- * @example
- * <pre>
- * $scope.gridOptions = {
- * columnDefs: [
- * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
- * editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',
- * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
- * ],
- * </pre>
- *
- */
- /**
- * @ngdoc property
- * @name editDropdownValueLabel
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description the label for the "value" field
- * in the editDropdownOptionsArray. Defaults
- * to 'value'
- * @example
- * <pre>
- * $scope.gridOptions = {
- * columnDefs: [
- * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
- * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
- * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
- * ],
- * </pre>
- *
- */
- /**
- * @ngdoc property
- * @name editDropdownFilter
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description A filter that you would like to apply to the values in the options list
- * of the dropdown. For example if you were using angular-translate you might set this
- * to `'translate'`
- * @example
- * <pre>
- * $scope.gridOptions = {
- * columnDefs: [
- * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
- * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
- * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }
- * ],
- * </pre>
- *
- */
- function beginEditAfterScroll(triggerEvent) {
- // If we are already editing, then just skip this so we don't try editing twice...
- if (inEdit) {
- return;
- }
-
- if (!shouldEdit($scope.col, $scope.row)) {
- return;
- }
-
-
- cellModel = $parse($scope.row.getQualifiedColField($scope.col));
- //get original value from the cell
- origCellValue = cellModel($scope);
-
- html = $scope.col.editableCellTemplate;
-
- if ($scope.col.colDef.editModelField) {
- html = html.replace(uiGridConstants.MODEL_COL_FIELD, gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField));
- }
- else {
- html = html.replace(uiGridConstants.MODEL_COL_FIELD, $scope.row.getQualifiedColField($scope.col));
- }
-
- html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
-
- var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';
- html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);
-
- var inputType = 'text';
- switch ($scope.col.colDef.type){
- case 'boolean':
- inputType = 'checkbox';
- break;
- case 'number':
- inputType = 'number';
- break;
- case 'date':
- inputType = 'date';
- break;
- }
- html = html.replace('INPUT_TYPE', inputType);
-
- var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;
- if (editDropdownRowEntityOptionsArrayPath) {
- $scope.editDropdownOptionsArray = resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);
- }
- else {
- $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;
- }
- $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';
- $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';
-
- var cellElement;
- var createEditor = function(){
- inEdit = true;
- cancelBeginEditEvents();
- var cellElement = angular.element(html);
- $elm.append(cellElement);
- editCellScope = $scope.$new();
- $compile(cellElement)(editCellScope);
- var gridCellContentsEl = angular.element($elm.children()[0]);
- gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');
- };
- if (!$rootScope.$$phase) {
- $scope.$apply(createEditor);
- } else {
- createEditor();
- }
-
- //stop editing when grid is scrolled
- var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {
- if ($scope.grid.disableScrolling) {
- return;
- }
- endEdit();
- $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
- deregOnGridScroll();
- deregOnEndCellEdit();
- deregOnCancelCellEdit();
- });
-
- //end editing
- var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
- endEdit();
- $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
- deregOnEndCellEdit();
- deregOnGridScroll();
- deregOnCancelCellEdit();
- });
-
- //cancel editing
- var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
- cancelEdit();
- deregOnCancelCellEdit();
- deregOnGridScroll();
- deregOnEndCellEdit();
- });
-
- $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);
- $timeout(function () {
- //execute in a timeout to give any complex editor templates a cycle to completely render
- $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);
- });
- }
-
- function endEdit() {
- $scope.grid.disableScrolling = false;
- if (!inEdit) {
- return;
- }
-
- //sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus
- //back to grid here. The focus call needs to be before the $destroy and removal of the control,
- //otherwise ng-model-options of UpdateOn: 'blur' will not work.
- if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
- uiGridCtrl.focus();
- }
-
- var gridCellContentsEl = angular.element($elm.children()[0]);
- //remove edit element
- editCellScope.$destroy();
- angular.element($elm.children()[1]).remove();
- gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');
- inEdit = false;
- registerBeginEditEvents();
- $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );
- }
-
- function cancelEdit() {
- $scope.grid.disableScrolling = false;
- if (!inEdit) {
- return;
- }
- cellModel.assign($scope, origCellValue);
- $scope.$apply();
-
- $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);
- endEdit();
- }
-
- // resolves a string path against the given object
- // shamelessly borrowed from
- // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
- function resolveObjectFromPath(object, path) {
- path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
- path = path.replace(/^\./, ''); // strip a leading dot
- var a = path.split('.');
- while (a.length) {
- var n = a.shift();
- if (n in object) {
- object = object[n];
- } else {
- return;
- }
- }
- return object;
- }
-
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridEditor
- * @element div
- * @restrict A
- *
- * @description input editor directive for editable fields.
- * Provides EndEdit and CancelEdit events
- *
- * Events that end editing:
- * blur and enter keydown
- *
- * Events that cancel editing:
- * - Esc keydown
- *
- */
- module.directive('uiGridEditor',
- ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',
- function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {
- return {
- scope: true,
- require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl, renderContainerCtrl, ngModel;
- if (controllers[0]) { uiGridCtrl = controllers[0]; }
- if (controllers[1]) { renderContainerCtrl = controllers[1]; }
- if (controllers[2]) { ngModel = controllers[2]; }
-
- //set focus at start of edit
- $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function (evt,triggerEvent) {
- $timeout(function () {
- $elm[0].focus();
- //only select text if it is not being replaced below in the cellNav viewPortKeyPress
- if ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav)) {
- $elm[0].select();
- }
- else {
- //some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...
- //fields should not allow setSelectionRange. We ignore the error for those browsers
- //https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796
- try {
- $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);
- }
- catch (ex) {
- //ignore
- }
- }
- });
-
- //set the keystroke that started the edit event
- //we must do this because the BeginEdit is done in a different event loop than the intitial
- //keydown event
- //fire this event for the keypress that is received
- if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
- var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {
- if (uiGridEditService.isStartEditKey(evt)) {
- ngModel.$setViewValue(String.fromCharCode(evt.keyCode), evt);
- ngModel.$render();
- }
- viewPortKeyDownUnregister();
- });
- }
-
- $elm.on('blur', function (evt) {
- $scope.stopEdit(evt);
- });
- });
-
-
- $scope.deepEdit = false;
-
- $scope.stopEdit = function (evt) {
- if ($scope.inputForm && !$scope.inputForm.$valid) {
- evt.stopPropagation();
- $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
- }
- else {
- $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
- }
- $scope.deepEdit = false;
- };
-
-
- $elm.on('click', function (evt) {
- if ($elm[0].type !== 'checkbox') {
- $scope.deepEdit = true;
- $timeout(function () {
- $scope.grid.disableScrolling = true;
- });
- }
- });
-
- $elm.on('keydown', function (evt) {
- switch (evt.keyCode) {
- case uiGridConstants.keymap.ESC:
- evt.stopPropagation();
- $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
- break;
- }
-
- if ($scope.deepEdit &&
- (evt.keyCode === uiGridConstants.keymap.LEFT ||
- evt.keyCode === uiGridConstants.keymap.RIGHT ||
- evt.keyCode === uiGridConstants.keymap.UP ||
- evt.keyCode === uiGridConstants.keymap.DOWN)) {
- evt.stopPropagation();
- }
- // Pass the keydown event off to the cellNav service, if it exists
- else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
- evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
- if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
- $scope.stopEdit(evt);
- }
- }
- else {
- //handle enter and tab for editing not using cellNav
- switch (evt.keyCode) {
- case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
- case uiGridConstants.keymap.TAB:
- evt.stopPropagation();
- evt.preventDefault();
- $scope.stopEdit(evt);
- break;
- }
- }
-
- return true;
- });
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:input
- * @element input
- * @restrict E
- *
- * @description directive to provide binding between input[date] value and ng-model for angular 1.2
- * It is similar to input[date] directive of angular 1.3
- *
- * Supported date format for input is 'yyyy-MM-dd'
- * The directive will set the $valid property of input element and the enclosing form to false if
- * model is invalid date or value of input is entered wrong.
- *
- */
- module.directive('uiGridEditor', ['$filter', function ($filter) {
- function parseDateString(dateString) {
- if (typeof(dateString) === 'undefined' || dateString === '') {
- return null;
- }
- var parts = dateString.split('-');
- if (parts.length !== 3) {
- return null;
- }
- var year = parseInt(parts[0], 10);
- var month = parseInt(parts[1], 10);
- var day = parseInt(parts[2], 10);
-
- if (month < 1 || year < 1 || day < 1) {
- return null;
- }
- return new Date(year, (month - 1), day);
- }
- return {
- priority: -100, // run after default uiGridEditor directive
- require: '?ngModel',
- link: function (scope, element, attrs, ngModel) {
-
- if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {
-
- ngModel.$formatters.push(function (modelValue) {
- ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));
- return $filter('date')(modelValue, 'yyyy-MM-dd');
- });
-
- ngModel.$parsers.push(function (viewValue) {
- if (viewValue && viewValue.length > 0) {
- var dateValue = parseDateString(viewValue);
- ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));
- return dateValue;
- }
- else {
- ngModel.$setValidity(null, true);
- return null;
- }
- });
- }
- }
- };
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridEditDropdown
- * @element div
- * @restrict A
- *
- * @description dropdown editor for editable fields.
- * Provides EndEdit and CancelEdit events
- *
- * Events that end editing:
- * blur and enter keydown, and any left/right nav
- *
- * Events that cancel editing:
- * - Esc keydown
- *
- */
- module.directive('uiGridEditDropdown',
- ['uiGridConstants', 'uiGridEditConstants',
- function (uiGridConstants, uiGridEditConstants) {
- return {
- require: ['?^uiGrid', '?^uiGridRenderContainer'],
- scope: true,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl = controllers[0];
- var renderContainerCtrl = controllers[1];
-
- //set focus at start of edit
- $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
- $elm[0].focus();
- $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';
- $elm.on('blur', function (evt) {
- $scope.stopEdit(evt);
- });
- });
-
-
- $scope.stopEdit = function (evt) {
- // no need to validate a dropdown - invalid values shouldn't be
- // available in the list
- $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
- };
-
- $elm.on('keydown', function (evt) {
- switch (evt.keyCode) {
- case uiGridConstants.keymap.ESC:
- evt.stopPropagation();
- $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
- break;
- }
- if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
- evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
- if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
- $scope.stopEdit(evt);
- }
- }
- else {
- //handle enter and tab for editing not using cellNav
- switch (evt.keyCode) {
- case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
- case uiGridConstants.keymap.TAB:
- evt.stopPropagation();
- evt.preventDefault();
- $scope.stopEdit(evt);
- break;
- }
- }
- return true;
- });
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.edit.directive:uiGridEditFileChooser
- * @element div
- * @restrict A
- *
- * @description input editor directive for editable fields.
- * Provides EndEdit and CancelEdit events
- *
- * Events that end editing:
- * blur and enter keydown
- *
- * Events that cancel editing:
- * - Esc keydown
- *
- */
- module.directive('uiGridEditFileChooser',
- ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout',
- function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout) {
- return {
- scope: true,
- require: ['?^uiGrid', '?^uiGridRenderContainer'],
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- var uiGridCtrl, renderContainerCtrl;
- if (controllers[0]) { uiGridCtrl = controllers[0]; }
- if (controllers[1]) { renderContainerCtrl = controllers[1]; }
- var grid = uiGridCtrl.grid;
-
- var handleFileSelect = function( event ){
- var target = event.srcElement || event.target;
-
- if (target && target.files && target.files.length > 0) {
- /**
- * @ngdoc property
- * @name editFileChooserCallback
- * @propertyOf ui.grid.edit.api:ColumnDef
- * @description A function that should be called when any files have been chosen
- * by the user. You should use this to process the files appropriately for your
- * application.
- *
- * It passes the gridCol, the gridRow (from which you can get gridRow.entity),
- * and the files. The files are in the format as returned from the file chooser,
- * an array of files, with each having useful information such as:
- * - `files[0].lastModifiedDate`
- * - `files[0].name`
- * - `files[0].size` (appears to be in bytes)
- * - `files[0].type` (MIME type by the looks)
- *
- * Typically you would do something with these files - most commonly you would
- * use the filename or read the file itself in. The example function does both.
- *
- * @example
- * <pre>
- * editFileChooserCallBack: function(gridRow, gridCol, files ){
- * // ignore all but the first file, it can only choose one anyway
- * // set the filename into this column
- * gridRow.entity.filename = file[0].name;
- *
- * // read the file and set it into a hidden column, which we may do stuff with later
- * var setFile = function(fileContent){
- * gridRow.entity.file = fileContent.currentTarget.result;
- * };
- * var reader = new FileReader();
- * reader.onload = setFile;
- * reader.readAsText( files[0] );
- * }
- * </pre>
- */
- if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {
- $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);
- } else {
- gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');
- }
-
- target.form.reset();
- $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
- } else {
- $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
- }
- };
-
- $elm[0].addEventListener('change', handleFileSelect, false); // TODO: why the false on the end? Google
-
- $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
- $elm[0].focus();
- $elm[0].select();
-
- $elm.on('blur', function (evt) {
- $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
- });
- });
- }
- };
- }
- };
- }]);
-
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.expandable
- * @description
- *
- * # ui.grid.expandable
- *
- * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
- *
- * This module provides the ability to create subgrids with the ability to expand a row
- * to show the subgrid.
- *
- * <div doc-module-components="ui.grid.expandable"></div>
- */
- var module = angular.module('ui.grid.expandable', ['ui.grid']);
-
- /**
- * @ngdoc service
- * @name ui.grid.expandable.service:uiGridExpandableService
- *
- * @description Services for the expandable grid
- */
- module.service('uiGridExpandableService', ['gridUtil', '$compile', function (gridUtil, $compile) {
- var service = {
- initializeGrid: function (grid) {
-
- grid.expandable = {};
- grid.expandable.expandedAll = false;
-
- /**
- * @ngdoc object
- * @name enableExpandable
- * @propertyOf ui.grid.expandable.api:GridOptions
- * @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids
- * within your application, or in specific modes on _this_ grid. Defaults to true.
- * @example
- * <pre>
- * $scope.gridOptions = {
- * enableExpandable: false
- * }
- * </pre>
- */
- grid.options.enableExpandable = grid.options.enableExpandable !== false;
-
- /**
- * @ngdoc object
- * @name expandableRowHeight
- * @propertyOf ui.grid.expandable.api:GridOptions
- * @description Height in pixels of the expanded subgrid. Defaults to
- * 150
- * @example
- * <pre>
- * $scope.gridOptions = {
- * expandableRowHeight: 150
- * }
- * </pre>
- */
- grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;
-
- /**
- * @ngdoc object
- * @name
- * @propertyOf ui.grid.expandable.api:GridOptions
- * @description Width in pixels of the expandable column. Defaults to 40
- * @example
- * <pre>
- * $scope.gridOptions = {
- * expandableRowHeaderWidth: 40
- * }
- * </pre>
- */
- grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;
-
- /**
- * @ngdoc object
- * @name expandableRowTemplate
- * @propertyOf ui.grid.expandable.api:GridOptions
- * @description Mandatory. The template for your expanded row
- * @example
- * <pre>
- * $scope.gridOptions = {
- * expandableRowTemplate: 'expandableRowTemplate.html'
- * }
- * </pre>
- */
- if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ){
- gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );
- grid.options.enableExpandable = false;
- }
-
- /**
- * @ngdoc object
- * @name ui.grid.expandable.api:PublicApi
- *
- * @description Public Api for expandable feature
- */
- /**
- * @ngdoc object
- * @name ui.grid.expandable.api:GridOptions
- *
- * @description Options for configuring the expandable feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
- var publicApi = {
- events: {
- expandable: {
- /**
- * @ngdoc event
- * @name rowExpandedStateChanged
- * @eventOf ui.grid.expandable.api:PublicApi
- * @description raised when cell editing is complete
- * <pre>
- * gridApi.expandable.on.rowExpandedStateChanged(scope,function(row){})
- * </pre>
- * @param {GridRow} row the row that was expanded
- */
- rowExpandedBeforeStateChanged: function(scope,row){
- },
- rowExpandedStateChanged: function (scope, row) {
- }
- }
- },
-
- methods: {
- expandable: {
- /**
- * @ngdoc method
- * @name toggleRowExpansion
- * @methodOf ui.grid.expandable.api:PublicApi
- * @description Toggle a specific row
- * <pre>
- * gridApi.expandable.toggleRowExpansion(rowEntity);
- * </pre>
- * @param {object} rowEntity the data entity for the row you want to expand
- */
- toggleRowExpansion: function (rowEntity) {
- var row = grid.getRow(rowEntity);
- if (row !== null) {
- service.toggleRowExpansion(grid, row);
- }
- },
-
- /**
- * @ngdoc method
- * @name expandAllRows
- * @methodOf ui.grid.expandable.api:PublicApi
- * @description Expand all subgrids.
- * <pre>
- * gridApi.expandable.expandAllRows();
- * </pre>
- */
- expandAllRows: function() {
- service.expandAllRows(grid);
- },
-
- /**
- * @ngdoc method
- * @name collapseAllRows
- * @methodOf ui.grid.expandable.api:PublicApi
- * @description Collapse all subgrids.
- * <pre>
- * gridApi.expandable.collapseAllRows();
- * </pre>
- */
- collapseAllRows: function() {
- service.collapseAllRows(grid);
- },
-
- /**
- * @ngdoc method
- * @name toggleAllRows
- * @methodOf ui.grid.expandable.api:PublicApi
- * @description Toggle all subgrids.
- * <pre>
- * gridApi.expandable.toggleAllRows();
- * </pre>
- */
- toggleAllRows: function() {
- service.toggleAllRows(grid);
- }
- }
- }
- };
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
- },
-
- toggleRowExpansion: function (grid, row) {
- // trigger the "before change" event. Can change row height dynamically this way.
- grid.api.expandable.raise.rowExpandedBeforeStateChanged(row);
- row.isExpanded = !row.isExpanded;
- if (angular.isUndefined(row.expandedRowHeight)){
- row.expandedRowHeight = grid.options.expandableRowHeight;
- }
-
- if (row.isExpanded) {
- row.height = row.grid.options.rowHeight + row.expandedRowHeight;
- }
- else {
- row.height = row.grid.options.rowHeight;
- grid.expandable.expandedAll = false;
- }
- grid.api.expandable.raise.rowExpandedStateChanged(row);
- },
-
- expandAllRows: function(grid, $scope) {
- grid.renderContainers.body.visibleRowCache.forEach( function(row) {
- if (!row.isExpanded) {
- service.toggleRowExpansion(grid, row);
- }
- });
- grid.expandable.expandedAll = true;
- grid.queueGridRefresh();
- },
-
- collapseAllRows: function(grid) {
- grid.renderContainers.body.visibleRowCache.forEach( function(row) {
- if (row.isExpanded) {
- service.toggleRowExpansion(grid, row);
- }
- });
- grid.expandable.expandedAll = false;
- grid.queueGridRefresh();
- },
-
- toggleAllRows: function(grid) {
- if (grid.expandable.expandedAll) {
- service.collapseAllRows(grid);
- }
- else {
- service.expandAllRows(grid);
- }
- }
- };
- return service;
- }]);
-
- /**
- * @ngdoc object
- * @name enableExpandableRowHeader
- * @propertyOf ui.grid.expandable.api:GridOptions
- * @description Show a rowHeader to provide the expandable buttons. If set to false then implies
- * you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.
- * @example
- * <pre>
- * $scope.gridOptions = {
- * enableExpandableRowHeader: false
- * }
- * </pre>
- */
- module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',
- function (uiGridExpandableService, $templateCache) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- if ( uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {
- var expandableRowHeaderColDef = {
- name: 'expandableButtons',
- displayName: '',
- exporterSuppressExport: true,
- enableColumnResizing: false,
- enableColumnMenu: false,
- width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 40
- };
- expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');
- expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');
- uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef);
- }
- uiGridExpandableService.initializeGrid(uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.expandable.directive:uiGrid
- * @description stacks on the uiGrid directive to register child grid with parent row when child is created
- */
- module.directive('uiGrid', ['uiGridExpandableService', '$templateCache',
- function (uiGridExpandableService, $templateCache) {
- return {
- replace: true,
- priority: 599,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {
- //if a parent grid row is on the scope, then add the parentRow property to this childGrid
- if ($scope.row && $scope.row.grid && $scope.row.grid.options && $scope.row.grid.options.enableExpandable) {
-
- /**
- * @ngdoc directive
- * @name ui.grid.expandable.class:Grid
- * @description Additional Grid properties added by expandable module
- */
-
- /**
- * @ngdoc object
- * @name parentRow
- * @propertyOf ui.grid.expandable.class:Grid
- * @description reference to the expanded parent row that owns this grid
- */
- uiGridCtrl.grid.parentRow = $scope.row;
-
- //todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event
- // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {
- // uiGridCtrl.grid.parentRow = newHeight;
- // });
- }
-
- });
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.expandable.directive:uiGridExpandableRow
- * @description directive to render the expandable row template
- */
- module.directive('uiGridExpandableRow',
- ['uiGridExpandableService', '$timeout', '$compile', 'uiGridConstants','gridUtil','$interval', '$log',
- function (uiGridExpandableService, $timeout, $compile, uiGridConstants, gridUtil, $interval, $log) {
-
- return {
- replace: false,
- priority: 0,
- scope: false,
-
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(
- function (template) {
- if ($scope.grid.options.expandableRowScope) {
- var expandableRowScope = $scope.grid.options.expandableRowScope;
- for (var property in expandableRowScope) {
- if (expandableRowScope.hasOwnProperty(property)) {
- $scope[property] = expandableRowScope[property];
- }
- }
- }
- var expandedRowElement = $compile(template)($scope);
- $elm.append(expandedRowElement);
- $scope.row.expandedRendered = true;
- });
- },
-
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- $scope.$on('$destroy', function() {
- $scope.row.expandedRendered = false;
- });
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.expandable.directive:uiGridRow
- * @description stacks on the uiGridRow directive to add support for expandable rows
- */
- module.directive('uiGridRow',
- ['$compile', 'gridUtil', '$templateCache',
- function ($compile, gridUtil, $templateCache) {
- return {
- priority: -200,
- scope: false,
- compile: function ($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
-
- $scope.expandableRow = {};
-
- $scope.expandableRow.shouldRenderExpand = function () {
- var ret = $scope.colContainer.name === 'body' && $scope.grid.options.enableExpandable !== false && $scope.row.isExpanded && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);
- return ret;
- };
-
- $scope.expandableRow.shouldRenderFiller = function () {
- var ret = $scope.row.isExpanded && ( $scope.colContainer.name !== 'body' || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));
- return ret;
- };
-
- /*
- * Commented out @PaulL1. This has no purpose that I can see, and causes #2964. If this code needs to be reinstated for some
- * reason it needs to use drawnWidth, not width, and needs to check column visibility. It should really use render container
- * visible column cache also instead of checking column.renderContainer.
- function updateRowContainerWidth() {
- var grid = $scope.grid;
- var colWidth = 0;
- grid.columns.forEach( function (column) {
- if (column.renderContainer === 'left') {
- colWidth += column.width;
- }
- });
- colWidth = Math.floor(colWidth);
- return '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.colContainer.name + ', .grid' + grid.id +
- ' .ui-grid-pinned-container-' + $scope.colContainer.name + ' .ui-grid-render-container-' + $scope.colContainer.name +
- ' .ui-grid-viewport .ui-grid-canvas .ui-grid-row { width: ' + colWidth + 'px; }';
- }
-
- if ($scope.colContainer.name === 'left') {
- $scope.grid.registerStyleComputation({
- priority: 15,
- func: updateRowContainerWidth
- });
- }*/
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.expandable.directive:uiGridViewport
- * @description stacks on the uiGridViewport directive to append the expandable row html elements to the
- * default gridRow template
- */
- module.directive('uiGridViewport',
- ['$compile', 'gridUtil', '$templateCache',
- function ($compile, gridUtil, $templateCache) {
- return {
- priority: -200,
- scope: false,
- compile: function ($elm, $attrs) {
- var rowRepeatDiv = angular.element($elm.children().children()[0]);
- var expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller');
- var expandedRowElement = $templateCache.get('ui-grid/expandableRow');
- rowRepeatDiv.append(expandedRowElement);
- rowRepeatDiv.append(expandedRowFillerElement);
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
- },
- post: function ($scope, $elm, $attrs, controllers) {
- }
- };
- }
- };
- }]);
-
-})();
-
-/* global console */
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.exporter
- * @description
- *
- * # ui.grid.exporter
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module provides the ability to exporter data from the grid.
- *
- * Data can be exported in a range of formats, and all data, visible
- * data, or selected rows can be exported, with all columns or visible
- * columns.
- *
- * No UI is provided, the caller should provide their own UI/buttons
- * as appropriate, or enable the gridMenu
- *
- * <br/>
- * <br/>
- *
- * <div doc-module-components="ui.grid.exporter"></div>
- */
-
- var module = angular.module('ui.grid.exporter', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.exporter.constant:uiGridExporterConstants
- *
- * @description constants available in exporter module
- */
- /**
- * @ngdoc property
- * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
- * @name ALL
- * @description export all data, including data not visible. Can
- * be set for either rowTypes or colTypes
- */
- /**
- * @ngdoc property
- * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
- * @name VISIBLE
- * @description export only visible data, including data not visible. Can
- * be set for either rowTypes or colTypes
- */
- /**
- * @ngdoc property
- * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
- * @name SELECTED
- * @description export all data, including data not visible. Can
- * be set only for rowTypes, selection of only some columns is
- * not supported
- */
- module.constant('uiGridExporterConstants', {
- featureName: 'exporter',
- ALL: 'all',
- VISIBLE: 'visible',
- SELECTED: 'selected',
- CSV_CONTENT: 'CSV_CONTENT',
- BUTTON_LABEL: 'BUTTON_LABEL',
- FILE_NAME: 'FILE_NAME'
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.exporter.service:uiGridExporterService
- *
- * @description Services for exporter feature
- */
- module.service('uiGridExporterService', ['$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',
- function ($q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {
-
- var service = {
-
- delay: 100,
-
- initializeGrid: function (grid) {
-
- //add feature namespace and any properties to grid for needed state
- grid.exporter = {};
- this.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.exporter.api:PublicApi
- *
- * @description Public Api for exporter feature
- */
- var publicApi = {
- events: {
- exporter: {
- }
- },
- methods: {
- exporter: {
- /**
- * @ngdoc function
- * @name csvExport
- * @methodOf ui.grid.exporter.api:PublicApi
- * @description Exports rows from the grid in csv format,
- * the data exported is selected based on the provided options
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
- */
- csvExport: function (rowTypes, colTypes) {
- service.csvExport(grid, rowTypes, colTypes);
- },
- /**
- * @ngdoc function
- * @name pdfExport
- * @methodOf ui.grid.exporter.api:PublicApi
- * @description Exports rows from the grid in pdf format,
- * the data exported is selected based on the provided options
- * Note that this function has a dependency on pdfMake, all
- * going well this has been installed for you.
- * The resulting pdf opens in a new browser window.
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
- */
- pdfExport: function (rowTypes, colTypes) {
- service.pdfExport(grid, rowTypes, colTypes);
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- if (grid.api.core.addToGridMenu){
- service.addToMenu( grid );
- } else {
- // order of registration is not guaranteed, register in a little while
- $interval( function() {
- if (grid.api.core.addToGridMenu){
- service.addToMenu( grid );
- }
- }, this.delay, 1);
- }
-
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.exporter.api:GridOptions
- *
- * @description GridOptions for exporter feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
- /**
- * @ngdoc object
- * @name ui.grid.exporter.api:ColumnDef
- * @description ColumnDef settings for exporter
- */
- /**
- * @ngdoc object
- * @name exporterSuppressMenu
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Don't show the export menu button, implying the user
- * will roll their own UI for calling the exporter
- * <br/>Defaults to false
- */
- gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;
- /**
- * @ngdoc object
- * @name exporterMenuLabel
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The text to show on the exporter menu button
- * link
- * <br/>Defaults to 'Export'
- */
- gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';
- /**
- * @ngdoc object
- * @name exporterSuppressColumns
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Columns that should not be exported. The selectionRowHeader is already automatically
- * suppressed, but if you had a button column or some other "system" column that shouldn't be shown in the
- * output then add it in this list. You should provide an array of column names.
- * <br/>Defaults to: []
- * <pre>
- * gridOptions.exporterSuppressColumns = [ 'buttons' ];
- * </pre>
- */
- gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];
- /**
- * @ngdoc object
- * @name exporterCsvColumnSeparator
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The character to use as column separator
- * link
- * <br/>Defaults to ','
- */
- gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';
- /**
- * @ngdoc object
- * @name exporterCsvFilename
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The default filename to use when saving the downloaded csv.
- * This will only work in some browsers.
- * <br/>Defaults to 'download.csv'
- */
- gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';
- /**
- * @ngdoc object
- * @name exporterPdfFilename
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)
- * <br/>Defaults to 'download.pdf'
- */
- gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';
- /**
- * @ngdoc object
- * @name exporterOlderExcelCompatibility
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes
- * through as  in the first column header. Setting this option to false will suppress this, at the
- * expense of proper utf-16 handling in applications that do recognise the BOM
- * <br/>Defaults to false
- */
- gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;
- /**
- * @ngdoc object
- * @name exporterPdfDefaultStyle
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The default style in pdfMake format
- * <br/>Defaults to:
- * <pre>
- * {
- * fontSize: 11
- * }
- * </pre>
- */
- gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };
- /**
- * @ngdoc object
- * @name exporterPdfTableStyle
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The table style in pdfMake format
- * <br/>Defaults to:
- * <pre>
- * {
- * margin: [0, 5, 0, 15]
- * }
- * </pre>
- */
- gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };
- /**
- * @ngdoc object
- * @name exporterPdfTableHeaderStyle
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The tableHeader style in pdfMake format
- * <br/>Defaults to:
- * <pre>
- * {
- * bold: true,
- * fontSize: 12,
- * color: 'black'
- * }
- * </pre>
- */
- gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };
- /**
- * @ngdoc object
- * @name exporterPdfHeader
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The header section for pdf exports. Can be
- * simple text:
- * <pre>
- * gridOptions.exporterPdfHeader = 'My Header';
- * </pre>
- * Can be a more complex object in pdfMake format:
- * <pre>
- * gridOptions.exporterPdfHeader = {
- * columns: [
- * 'Left part',
- * { text: 'Right part', alignment: 'right' }
- * ]
- * };
- * </pre>
- * Or can be a function, allowing page numbers and the like
- * <pre>
- * gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
- * </pre>
- */
- gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;
- /**
- * @ngdoc object
- * @name exporterPdfFooter
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The header section for pdf exports. Can be
- * simple text:
- * <pre>
- * gridOptions.exporterPdfFooter = 'My Footer';
- * </pre>
- * Can be a more complex object in pdfMake format:
- * <pre>
- * gridOptions.exporterPdfFooter = {
- * columns: [
- * 'Left part',
- * { text: 'Right part', alignment: 'right' }
- * ]
- * };
- * </pre>
- * Or can be a function, allowing page numbers and the like
- * <pre>
- * gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
- * </pre>
- */
- gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;
- /**
- * @ngdoc object
- * @name exporterPdfOrientation
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The orientation, should be a valid pdfMake value,
- * 'landscape' or 'portrait'
- * <br/>Defaults to landscape
- */
- gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';
- /**
- * @ngdoc object
- * @name exporterPdfPageSize
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The orientation, should be a valid pdfMake
- * paper size, usually 'A4' or 'LETTER'
- * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}
- * <br/>Defaults to A4
- */
- gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';
- /**
- * @ngdoc object
- * @name exporterPdfMaxGridWidth
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description The maxium grid width - the current grid width
- * will be scaled to match this, with any fixed width columns
- * being adjusted accordingly.
- * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER
- */
- gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;
- /**
- * @ngdoc object
- * @name exporterPdfTableLayout
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description A tableLayout in pdfMake format,
- * controls gridlines and the like. We use the default
- * layout usually.
- * <br/>Defaults to null, which means no layout
- */
-
- /**
- * @ngdoc object
- * @name exporterMenuAllData
- * @porpertyOf ui.grid.exporter.api:GridOptions
- * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
- */
- gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;
-
- /**
- * @ngdoc object
- * @name exporterMenuCsv
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Add csv export menu items to the ui-grid grid menu, if it's present. Defaults to true.
- */
- gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;
-
- /**
- * @ngdoc object
- * @name exporterMenuPdf
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Add pdf export menu items to the ui-grid grid menu, if it's present. Defaults to true.
- */
- gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;
-
- /**
- * @ngdoc object
- * @name exporterPdfCustomFormatter
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description A custom callback routine that changes the pdf document, adding any
- * custom styling or content that is supported by pdfMake. Takes in the complete docDefinition, and
- * must return an updated docDefinition ready for pdfMake.
- * @example
- * In this example we add a style to the style array, so that we can use it in our
- * footer definition.
- * <pre>
- * gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {
- * docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };
- * return docDefinition;
- * }
- *
- * gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }
- * </pre>
- */
- gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };
-
- /**
- * @ngdoc object
- * @name exporterHeaderFilterUseName
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.
- * If set to true, then will pass `name` instead.
- *
- *
- * @example
- * <pre>
- * gridOptions.exporterHeaderFilterUseName = true;
- * </pre>
- */
- gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;
-
- /**
- * @ngdoc object
- * @name exporterHeaderFilter
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description A function to apply to the header displayNames before exporting. Useful for internationalisation,
- * for example if you were using angular-translate you'd set this to `$translate.instant`. Note that this
- * call must be synchronous, it cannot be a call that returns a promise.
- *
- * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.
- *
- * @example
- * <pre>
- * gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };
- * </pre>
- * OR
- * <pre>
- * gridOptions.exporterHeaderFilter = $translate.instant;
- * </pre>
- */
-
- /**
- * @ngdoc function
- * @name exporterFieldCallback
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description A function to call for each field before exporting it. Allows
- * massaging of raw data into a display format, for example if you have applied
- * filters to convert codes into decodes, or you require
- * a specific date format in the exported content.
- *
- * The method is called once for each field exported, and provides the grid, the
- * gridCol and the GridRow for you to use as context in massaging the data.
- *
- * @param {Grid} grid provides the grid in case you have need of it
- * @param {GridRow} row the row from which the data comes
- * @param {GridCol} col the column from which the data comes
- * @param {object} value the value for your massaging
- * @returns {object} you must return the massaged value ready for exporting
- *
- * @example
- * <pre>
- * gridOptions.exporterFieldCallback = function ( grid, row, col, value ){
- * if ( col.name === 'status' ){
- * value = decodeStatus( value );
- * }
- * return value;
- * }
- * </pre>
- */
- gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : function( grid, row, col, value ) { return value; };
-
- /**
- * @ngdoc function
- * @name exporterAllDataFn
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description This promise is needed when exporting all rows,
- * and the data need to be provided by server side. Default is null.
- * @returns {Promise} a promise to load all data from server
- *
- * @example
- * <pre>
- * gridOptions.exporterAllDataFn = function () {
- * return $http.get('/data/100.json')
- * }
- * </pre>
- */
- gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;
-
- /**
- * @ngdoc function
- * @name exporterAllDataPromise
- * @propertyOf ui.grid.exporter.api:GridOptions
- * @description DEPRECATED - exporterAllDataFn used to be
- * called this, but it wasn't a promise, it was a function that returned
- * a promise. Deprecated, but supported for backward compatibility, use
- * exporterAllDataFn instead.
- * @returns {Promise} a promise to load all data from server
- *
- * @example
- * <pre>
- * gridOptions.exporterAllDataFn = function () {
- * return $http.get('/data/100.json')
- * }
- * </pre>
- */
- if ( gridOptions.exporterAllDataFn == null && gridOptions.exporterAllDataPromise ) {
- gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;
- }
- },
-
-
- /**
- * @ngdoc function
- * @name addToMenu
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Adds export items to the grid menu,
- * allowing the user to select export options
- * @param {Grid} grid the grid from which data should be exported
- */
- addToMenu: function ( grid ) {
- grid.api.core.addToGridMenu( grid, [
- {
- title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),
- action: function ($event) {
- this.grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
- },
- shown: function() {
- return this.grid.options.exporterMenuCsv && this.grid.options.exporterMenuAllData;
- },
- order: 200
- },
- {
- title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),
- action: function ($event) {
- this.grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
- },
- shown: function() {
- return this.grid.options.exporterMenuCsv;
- },
- order: 201
- },
- {
- title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),
- action: function ($event) {
- this.grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
- },
- shown: function() {
- return this.grid.options.exporterMenuCsv &&
- ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
- },
- order: 202
- },
- {
- title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),
- action: function ($event) {
- this.grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
- },
- shown: function() {
- return this.grid.options.exporterMenuPdf && this.grid.options.exporterMenuAllData;
- },
- order: 203
- },
- {
- title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),
- action: function ($event) {
- this.grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
- },
- shown: function() {
- return this.grid.options.exporterMenuPdf;
- },
- order: 204
- },
- {
- title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),
- action: function ($event) {
- this.grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
- },
- shown: function() {
- return this.grid.options.exporterMenuPdf &&
- ( this.grid.api.selection && this.grid.api.selection.getSelectedRows().length > 0 );
- },
- order: 205
- }
- ]);
- },
-
-
- /**
- * @ngdoc function
- * @name csvExport
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Exports rows from the grid in csv format,
- * the data exported is selected based on the provided options
- * @param {Grid} grid the grid from which data should be exported
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- */
- csvExport: function (grid, rowTypes, colTypes) {
- var self = this;
- this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
- var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
- var exportData = self.getData(grid, rowTypes, colTypes);
- var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);
-
- self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterOlderExcelCompatibility);
- });
- },
-
- /**
- * @ngdoc function
- * @name loadAllDataIfNeeded
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description When using server side pagination, use exporterAllDataFn to
- * load all data before continuing processing.
- * When using client side pagination, return a resolved promise so processing
- * continues immediately
- * @param {Grid} grid the grid from which data should be exported
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- */
- loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {
- if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {
- return grid.options.exporterAllDataFn()
- .then(function() {
- grid.modifyRows(grid.options.data);
- });
- } else {
- var deferred = $q.defer();
- deferred.resolve();
- return deferred.promise;
- }
- },
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.exporter.api:ColumnDef
- * @name exporterSuppressExport
- * @description Suppresses export for this column. Used by selection and expandable.
- */
-
- /**
- * @ngdoc function
- * @name getColumnHeaders
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Gets the column headers from the grid to use
- * as a title row for the exported file, all headers have
- * headerCellFilters applied as appropriate.
- *
- * Column headers are an array of objects, each object has
- * name, displayName, width and align attributes. Only name is
- * used for csv, all attributes are used for pdf.
- *
- * @param {Grid} grid the grid from which data should be exported
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- */
- getColumnHeaders: function (grid, colTypes) {
- var headers = [];
- var columns;
-
- if ( colTypes === uiGridExporterConstants.ALL ){
- columns = grid.columns;
- } else {
- var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
- var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
- var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
-
- columns = leftColumns.concat(bodyColumns,rightColumns);
- }
-
- columns.forEach( function( gridCol, index ) {
- if ( gridCol.colDef.exporterSuppressExport !== true &&
- grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
- headers.push({
- name: gridCol.field,
- displayName: grid.options.exporterHeaderFilter ? ( grid.options.exporterHeaderFilterUseName ? grid.options.exporterHeaderFilter(gridCol.name) : grid.options.exporterHeaderFilter(gridCol.displayName) ) : gridCol.displayName,
- width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,
- align: gridCol.colDef.type === 'number' ? 'right' : 'left'
- });
- }
- });
-
- return headers;
- },
-
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.exporter.api:ColumnDef
- * @name exporterPdfAlign
- * @description the alignment you'd like for this specific column when
- * exported into a pdf. Can be 'left', 'right', 'center' or any other
- * valid pdfMake alignment option.
- */
-
-
- /**
- * @ngdoc object
- * @name ui.grid.exporter.api:GridRow
- * @description GridRow settings for exporter
- */
- /**
- * @ngdoc object
- * @name exporterEnableExporting
- * @propertyOf ui.grid.exporter.api:GridRow
- * @description If set to false, then don't export this row, notwithstanding visible or
- * other settings
- * <br/>Defaults to true
- */
-
- /**
- * @ngdoc function
- * @name getData
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Gets data from the grid based on the provided options,
- * all cells have cellFilters applied as appropriate. Any rows marked
- * `exporterEnableExporting: false` will not be exported
- * @param {Grid} grid the grid from which data should be exported
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- */
- getData: function (grid, rowTypes, colTypes) {
- var data = [];
- var rows;
- var columns;
-
- switch ( rowTypes ) {
- case uiGridExporterConstants.ALL:
- rows = grid.rows;
- break;
- case uiGridExporterConstants.VISIBLE:
- rows = grid.getVisibleRows();
- break;
- case uiGridExporterConstants.SELECTED:
- if ( grid.api.selection ){
- rows = grid.api.selection.getSelectedGridRows();
- } else {
- gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');
- }
- break;
- }
-
- if ( colTypes === uiGridExporterConstants.ALL ){
- columns = grid.columns;
- } else {
- var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
- var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
- var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
-
- columns = leftColumns.concat(bodyColumns,rightColumns);
- }
-
- rows.forEach( function( row, index ) {
-
- if (row.exporterEnableExporting !== false) {
- var extractedRow = [];
-
-
- columns.forEach( function( gridCol, index ) {
- if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&
- gridCol.colDef.exporterSuppressExport !== true &&
- grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
- var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, grid.getCellValue( row, gridCol ) ) };
- if ( gridCol.colDef.exporterPdfAlign ) {
- extractedField.alignment = gridCol.colDef.exporterPdfAlign;
- }
- extractedRow.push(extractedField);
- }
- });
-
- data.push(extractedRow);
- }
- });
-
- return data;
- },
-
-
- /**
- * @ngdoc function
- * @name formatAsCSV
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Formats the column headers and data as a CSV,
- * and sends that data to the user
- * @param {array} exportColumnHeaders an array of column headers,
- * where each header is an object with name, width and maybe alignment
- * @param {array} exportData an array of rows, where each row is
- * an array of column data
- * @returns {string} csv the formatted csv as a string
- */
- formatAsCsv: function (exportColumnHeaders, exportData, separator) {
- var self = this;
-
- var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});
-
- var csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\n') : '';
-
- csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\n');
-
- return csv;
- },
-
- /**
- * @ngdoc function
- * @name formatRowAsCsv
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Renders a single field as a csv field, including
- * quotes around the value
- * @param {exporterService} exporter pass in exporter
- * @param {array} row the row to be turned into a csv string
- * @returns {string} a csv-ified version of the row
- */
- formatRowAsCsv: function (exporter, separator) {
- return function (row) {
- return row.map(exporter.formatFieldAsCsv).join(separator);
- };
- },
-
- /**
- * @ngdoc function
- * @name formatFieldAsCsv
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Renders a single field as a csv field, including
- * quotes around the value
- * @param {field} field the field to be turned into a csv string,
- * may be of any type
- * @returns {string} a csv-ified version of the field
- */
- formatFieldAsCsv: function (field) {
- if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
- return '';
- }
- if (typeof(field.value) === 'number') {
- return field.value;
- }
- if (typeof(field.value) === 'boolean') {
- return (field.value ? 'TRUE' : 'FALSE') ;
- }
- if (typeof(field.value) === 'string') {
- return '"' + field.value.replace(/"/g,'""') + '"';
- }
-
- return JSON.stringify(field.value);
- },
-
-
- /**
- * @ngdoc function
- * @name isIE
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Checks whether current browser is IE and returns it's version if it is
- */
- isIE: function () {
- var match = navigator.userAgent.match(/(?:MSIE |Trident\/.*; rv:)(\d+)/);
- return match ? parseInt(match[1]) : false;
- },
-
-
- /**
- * @ngdoc function
- * @name downloadFile
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Triggers download of a csv file. Logic provided
- * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391
- * @param {string} fileName the filename we'd like our file to be
- * given
- * @param {string} csvContent the csv content that we'd like to
- * download as a file
- * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\uFEFF)
- */
- downloadFile: function (fileName, csvContent, exporterOlderExcelCompatibility) {
- var D = document;
- var a = D.createElement('a');
- var strMimeType = 'application/octet-stream;charset=utf-8';
- var rawFile;
- var ieVersion;
-
- ieVersion = this.isIE();
- if (ieVersion && ieVersion < 10) {
- var frame = D.createElement('iframe');
- document.body.appendChild(frame);
-
- frame.contentWindow.document.open("text/html", "replace");
- frame.contentWindow.document.write('sep=,\r\n' + csvContent);
- frame.contentWindow.document.close();
- frame.contentWindow.focus();
- frame.contentWindow.document.execCommand('SaveAs', true, fileName);
-
- document.body.removeChild(frame);
- return true;
- }
-
- // IE10+
- if (navigator.msSaveBlob) {
- return navigator.msSaveOrOpenBlob(
- new Blob(
- [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
- { type: strMimeType } ),
- fileName
- );
- }
-
- //html5 A[download]
- if ('download' in a) {
- var blob = new Blob(
- [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
- { type: strMimeType }
- );
- rawFile = URL.createObjectURL(blob);
- a.setAttribute('download', fileName);
- } else {
- rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);
- a.setAttribute('target', '_blank');
- }
-
- a.href = rawFile;
- a.setAttribute('style', 'display:none;');
- D.body.appendChild(a);
- setTimeout(function() {
- if (a.click) {
- a.click();
- // Workaround for Safari 5
- } else if (document.createEvent) {
- var eventObj = document.createEvent('MouseEvents');
- eventObj.initEvent('click', true, true);
- a.dispatchEvent(eventObj);
- }
- D.body.removeChild(a);
-
- }, this.delay);
- },
-
- /**
- * @ngdoc function
- * @name pdfExport
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Exports rows from the grid in pdf format,
- * the data exported is selected based on the provided options.
- * Note that this function has a dependency on pdfMake, which must
- * be installed. The resulting pdf opens in a new
- * browser window.
- * @param {Grid} grid the grid from which data should be exported
- * @param {string} rowTypes which rows to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- * @param {string} colTypes which columns to export, valid values are
- * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
- * uiGridExporterConstants.SELECTED
- */
- pdfExport: function (grid, rowTypes, colTypes) {
- var self = this;
- this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {
- var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);
- var exportData = self.getData(grid, rowTypes, colTypes);
- var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);
-
- if (self.isIE()) {
- self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);
- } else {
- pdfMake.createPdf(docDefinition).open();
- }
- });
- },
-
-
- /**
- * @ngdoc function
- * @name downloadPdf
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Generates and retrieves the pdf as a blob, then downloads
- * it as a file. Only used in IE, in all other browsers we use the native
- * pdfMake.open function to just open the PDF
- * @param {string} fileName the filename to give to the pdf, can be set
- * through exporterPdfFilename
- * @param {object} docDefinition a pdf docDefinition that we can generate
- * and get a blob from
- */
- downloadPDF: function (fileName, docDefinition) {
- var D = document;
- var a = D.createElement('a');
- var strMimeType = 'application/octet-stream;charset=utf-8';
- var rawFile;
- var ieVersion;
-
- ieVersion = this.isIE();
- var doc = pdfMake.createPdf(docDefinition);
- var blob;
-
- doc.getBuffer( function (buffer) {
- blob = new Blob([buffer]);
-
- if (ieVersion && ieVersion < 10) {
- var frame = D.createElement('iframe');
- document.body.appendChild(frame);
-
- frame.contentWindow.document.open("text/html", "replace");
- frame.contentWindow.document.write(blob);
- frame.contentWindow.document.close();
- frame.contentWindow.focus();
- frame.contentWindow.document.execCommand('SaveAs', true, fileName);
-
- document.body.removeChild(frame);
- return true;
- }
-
- // IE10+
- if (navigator.msSaveBlob) {
- return navigator.msSaveBlob(
- blob, fileName
- );
- }
- });
- },
-
-
- /**
- * @ngdoc function
- * @name renderAsPdf
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Renders the data into a pdf, and opens that pdf.
- *
- * @param {Grid} grid the grid from which data should be exported
- * @param {array} exportColumnHeaders an array of column headers,
- * where each header is an object with name, width and maybe alignment
- * @param {array} exportData an array of rows, where each row is
- * an array of column data
- * @returns {object} a pdfMake format document definition, ready
- * for generation
- */
- prepareAsPdf: function(grid, exportColumnHeaders, exportData) {
- var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );
-
- var headerColumns = exportColumnHeaders.map( function( header ) {
- return { text: header.displayName, style: 'tableHeader' };
- });
-
- var stringData = exportData.map(this.formatRowAsPdf(this));
-
- var allData = [headerColumns].concat(stringData);
-
- var docDefinition = {
- pageOrientation: grid.options.exporterPdfOrientation,
- pageSize: grid.options.exporterPdfPageSize,
- content: [{
- style: 'tableStyle',
- table: {
- headerRows: 1,
- widths: headerWidths,
- body: allData
- }
- }],
- styles: {
- tableStyle: grid.options.exporterPdfTableStyle,
- tableHeader: grid.options.exporterPdfTableHeaderStyle
- },
- defaultStyle: grid.options.exporterPdfDefaultStyle
- };
-
- if ( grid.options.exporterPdfLayout ){
- docDefinition.layout = grid.options.exporterPdfLayout;
- }
-
- if ( grid.options.exporterPdfHeader ){
- docDefinition.header = grid.options.exporterPdfHeader;
- }
-
- if ( grid.options.exporterPdfFooter ){
- docDefinition.footer = grid.options.exporterPdfFooter;
- }
-
- if ( grid.options.exporterPdfCustomFormatter ){
- docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );
- }
- return docDefinition;
-
- },
-
-
- /**
- * @ngdoc function
- * @name calculatePdfHeaderWidths
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Determines the column widths base on the
- * widths we got from the grid. If the column is drawn
- * then we have a drawnWidth. If the column is not visible
- * then we have '*', 'x%' or a width. When columns are
- * not visible they don't contribute to the overall gridWidth,
- * so we need to adjust to allow for extra columns
- *
- * Our basic heuristic is to take the current gridWidth, plus
- * numeric columns and call this the base gridwidth.
- *
- * To that we add 100 for any '*' column, and x% of the base gridWidth
- * for any column that is a %
- *
- * @param {Grid} grid the grid from which data should be exported
- * @param {array} exportHeaders array of header information
- * @returns {object} an array of header widths
- */
- calculatePdfHeaderWidths: function ( grid, exportHeaders ) {
- var baseGridWidth = 0;
- exportHeaders.forEach( function(value){
- if (typeof(value.width) === 'number'){
- baseGridWidth += value.width;
- }
- });
-
- var extraColumns = 0;
- exportHeaders.forEach( function(value){
- if (value.width === '*'){
- extraColumns += 100;
- }
- if (typeof(value.width) === 'string' && value.width.match(/(\d)*%/)) {
- var percent = parseInt(value.width.match(/(\d)*%/)[0]);
-
- value.width = baseGridWidth * percent / 100;
- extraColumns += value.width;
- }
- });
-
- var gridWidth = baseGridWidth + extraColumns;
-
- return exportHeaders.map(function( header ) {
- return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;
- });
-
- },
-
- /**
- * @ngdoc function
- * @name formatRowAsPdf
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Renders a row in a format consumable by PDF,
- * mainly meaning casting everything to a string
- * @param {exporterService} exporter pass in exporter
- * @param {array} row the row to be turned into a csv string
- * @returns {string} a csv-ified version of the row
- */
- formatRowAsPdf: function ( exporter ) {
- return function( row ) {
- return row.map(exporter.formatFieldAsPdfString);
- };
- },
-
-
- /**
- * @ngdoc function
- * @name formatFieldAsCsv
- * @methodOf ui.grid.exporter.service:uiGridExporterService
- * @description Renders a single field as a pdf-able field, which
- * is different from a csv field only in that strings don't have quotes
- * around them
- * @param {field} field the field to be turned into a pdf string,
- * may be of any type
- * @returns {string} a string-ified version of the field
- */
- formatFieldAsPdfString: function (field) {
- var returnVal;
- if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
- returnVal = '';
- } else if (typeof(field.value) === 'number') {
- returnVal = field.value.toString();
- } else if (typeof(field.value) === 'boolean') {
- returnVal = (field.value ? 'TRUE' : 'FALSE') ;
- } else if (typeof(field.value) === 'string') {
- returnVal = field.value.replace(/"/g,'""');
- } else {
- returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
- }
-
- if (field.alignment && typeof(field.alignment) === 'string' ){
- returnVal = { text: returnVal, alignment: field.alignment };
- }
-
- return returnVal;
- }
- };
-
- return service;
-
- }
- ]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.exporter.directive:uiGridExporter
- * @element div
- * @restrict A
- *
- * @description Adds exporter features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.gridOptions = {
- enableGridMenu: true,
- exporterMenuCsv: false,
- columnDefs: [
- {name: 'name', enableCellEdit: true},
- {name: 'title', enableCellEdit: true}
- ],
- data: $scope.data
- };
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="gridOptions" ui-grid-exporter></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',
- function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridExporterService.initializeGrid(uiGridCtrl.grid);
- uiGridCtrl.grid.exporter.$scope = $scope;
- }
- };
- }
- ]);
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.grouping
- * @description
- *
- * # ui.grid.grouping
- *
- * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
- *
- * This module provides grouping of rows based on the data in them, similar
- * in concept to excel grouping. You can group multiple columns, resulting in
- * nested grouping.
- *
- * In concept this feature is similar to sorting + grid footer/aggregation, it
- * sorts the data based on the grouped columns, then creates group rows that
- * reflect a break in the data. Each of those group rows can have aggregations for
- * the data within that group.
- *
- * This feature leverages treeBase to provide the tree functionality itself,
- * the key thing this feature does therefore is to set treeLevels on the rows
- * and insert the group headers.
- *
- * Design information:
- * -------------------
- *
- * Each column will get new menu items - group by, and aggregate by. Group by
- * will cause this column to be sorted (if not already), and will move this column
- * to the front of the sorted columns (i.e. grouped columns take precedence over
- * sorted columns). It will respect the sort order already set if there is one,
- * and it will allow the sorting logic to change that sort order, it just forces
- * the column to the front of the sorting. You can group by multiple columns, the
- * logic will add this column to the sorting after any already grouped columns.
- *
- * Once a grouping is defined, grouping logic is added to the rowsProcessors. This
- * will process the rows, identifying a break in the data value, and inserting a grouping row.
- * Grouping rows have specific attributes on them:
- *
- * - internalRow = true: tells us that this isn't a real row, so we can ignore it
- * from any processing that it looking at core data rows. This is used by the core
- * logic (or will be one day), as it's not grouping specific
- * - groupHeader = true: tells us this is a groupHeader. This is used by the grouping logic
- * to know if this is a groupHeader row or not
- *
- * Since the logic is baked into the rowsProcessors, it should get triggered whenever
- * row order or filtering or anything like that is changed. In order to avoid the row instantiation
- * time, and to preserve state across invocations, we hold a cache of the rows that we created
- * last time, and we use them again this time if we can.
- *
- * By default rows are collapsed, which means all data rows have their visible property
- * set to false, and only level 0 group rows are set to visible.
- *
- * <br/>
- * <br/>
- *
- * <div doc-module-components="ui.grid.grouping"></div>
- */
-
- var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);
-
- /**
- * @ngdoc object
- * @name ui.grid.grouping.constant:uiGridGroupingConstants
- *
- * @description constants available in grouping module, this includes
- * all the constants declared in the treeBase module (these are manually copied
- * as there isn't an easy way to include constants in another constants file, and
- * we don't want to make users include treeBase)
- *
- */
- module.constant('uiGridGroupingConstants', {
- featureName: "grouping",
- rowHeaderColName: 'treeBaseRowHeaderCol',
- EXPANDED: 'expanded',
- COLLAPSED: 'collapsed',
- aggregation: {
- COUNT: 'count',
- SUM: 'sum',
- MAX: 'max',
- MIN: 'min',
- AVG: 'avg'
- }
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.grouping.service:uiGridGroupingService
- *
- * @description Services for grouping features
- */
- module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',
- function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {
-
- var service = {
-
- initializeGrid: function (grid, $scope) {
- uiGridTreeBaseService.initializeGrid( grid, $scope );
-
- //add feature namespace and any properties to grid for needed
- /**
- * @ngdoc object
- * @name ui.grid.grouping.grid:grouping
- *
- * @description Grid properties and functions added for grouping
- */
- grid.grouping = {};
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.grouping.grid:grouping
- * @name groupHeaderCache
- *
- * @description Cache that holds the group header rows we created last time, we'll
- * reuse these next time, not least because they hold our expanded states.
- *
- * We need to take care with these that they don't become a memory leak, we
- * create a new cache each time using the values from the old cache. This works
- * so long as we're creating group rows for invisible rows as well.
- *
- * The cache is a nested hash, indexed on the value we grouped by. So if we
- * grouped by gender then age, we'd maybe have something like:
- * ```
- * {
- * male: {
- * row: <pointer to the old row>,
- * children: {
- * 22: { row: <pointer to the old row> },
- * 31: { row: <pointer to the old row> }
- * },
- * female: {
- * row: <pointer to the old row>,
- * children: {
- * 28: { row: <pointer to the old row> },
- * 55: { row: <pointer to the old row> }
- * }
- * }
- * ```
- *
- * We create new rows for any missing rows, this means that they come in as collapsed.
- *
- */
- grid.grouping.groupHeaderCache = {};
-
- service.defaultGridOptions(grid.options);
-
- grid.registerRowsProcessor(service.groupRows, 400);
-
- grid.registerColumnBuilder( service.groupingColumnBuilder);
-
- grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);
-
- /**
- * @ngdoc object
- * @name ui.grid.grouping.api:PublicApi
- *
- * @description Public Api for grouping feature
- */
- var publicApi = {
- events: {
- grouping: {
- /**
- * @ngdoc event
- * @eventOf ui.grid.grouping.api:PublicApi
- * @name aggregationChanged
- * @description raised whenever aggregation is changed, added or removed from a column
- *
- * <pre>
- * gridApi.grouping.on.aggregationChanged(scope,function(col){})
- * </pre>
- * @param {gridCol} col the column which on which aggregation changed. The aggregation
- * type is available as `col.treeAggregation.type`
- */
- aggregationChanged: {},
- /**
- * @ngdoc event
- * @eventOf ui.grid.grouping.api:PublicApi
- * @name groupingChanged
- * @description raised whenever the grouped columns changes
- *
- * <pre>
- * gridApi.grouping.on.groupingChanged(scope,function(col){})
- * </pre>
- * @param {gridCol} col the column which on which grouping changed. The new grouping is
- * available as `col.grouping`
- */
- groupingChanged: {}
- }
- },
- methods: {
- grouping: {
- /**
- * @ngdoc function
- * @name getGrouping
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Get the grouping configuration for this grid,
- * used by the saveState feature. Adds expandedState to the information
- * provided by the internal getGrouping, and removes any aggregations that have a source
- * of grouping (i.e. will be automatically reapplied when we regroup the column)
- * Returned grouping is an object
- * `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`
- * where grouping contains an array of objects:
- * `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`
- * and aggregations contains an array of objects:
- * `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`
- * and expandedState is a hash of the currently expanded nodes
- *
- * The groupArray will be sorted by groupPriority.
- *
- * @param {boolean} getExpanded whether or not to return the expanded state
- * @returns {object} grouping configuration
- */
- getGrouping: function ( getExpanded ) {
- var grouping = service.getGrouping(grid);
-
- grouping.grouping.forEach( function( group ) {
- group.colName = group.col.name;
- delete group.col;
- });
-
- grouping.aggregations.forEach( function( aggregation ) {
- aggregation.colName = aggregation.col.name;
- delete aggregation.col;
- });
-
- grouping.aggregations = grouping.aggregations.filter( function( aggregation ){
- return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';
- });
-
- if ( getExpanded ){
- grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );
- }
-
- return grouping;
- },
-
- /**
- * @ngdoc function
- * @name setGrouping
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Set the grouping configuration for this grid,
- * used by the saveState feature, but can also be used by any
- * user to specify a combined grouping and aggregation configuration
- * @param {object} config the config you want to apply, in the format
- * provided out by getGrouping
- */
- setGrouping: function ( config ) {
- service.setGrouping(grid, config);
- },
-
- /**
- * @ngdoc function
- * @name groupColumn
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Adds this column to the existing grouping, at the end of the priority order.
- * If the column doesn't have a sort, adds one, by default ASC
- *
- * This column will move to the left of any non-group columns, the
- * move is handled in a columnProcessor, so gets called as part of refresh
- *
- * @param {string} columnName the name of the column we want to group
- */
- groupColumn: function( columnName ) {
- var column = grid.getColumn(columnName);
- service.groupColumn(grid, column);
- },
-
- /**
- * @ngdoc function
- * @name ungroupColumn
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Removes the groupPriority from this column. If the
- * column was previously aggregated the aggregation will come back.
- * The sort will remain.
- *
- * This column will move to the right of any other group columns, the
- * move is handled in a columnProcessor, so gets called as part of refresh
- *
- * @param {string} columnName the name of the column we want to ungroup
- */
- ungroupColumn: function( columnName ) {
- var column = grid.getColumn(columnName);
- service.ungroupColumn(grid, column);
- },
-
- /**
- * @ngdoc function
- * @name clearGrouping
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
- * as we don't know whether that sorting was added by grouping or was there beforehand
- *
- */
- clearGrouping: function() {
- service.clearGrouping(grid);
- },
-
- /**
- * @ngdoc function
- * @name aggregateColumn
- * @methodOf ui.grid.grouping.api:PublicApi
- * @description Sets the aggregation type on a column, if the
- * column is currently grouped then it removes the grouping first.
- * If the aggregationDef is null then will result in the aggregation
- * being removed
- *
- * @param {string} columnName the column we want to aggregate
- * @param {string} or {function} aggregationDef one of the recognised types
- * from uiGridGroupingConstants or a custom aggregation function.
- * @param {string} aggregationLabel (optional) The label to use for this aggregation.
- */
- aggregateColumn: function( columnName, aggregationDef, aggregationLabel){
- var column = grid.getColumn(columnName);
- service.aggregateColumn( grid, column, aggregationDef, aggregationLabel);
- }
-
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- grid.api.core.on.sortChanged( $scope, service.tidyPriorities);
-
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.grouping.api:GridOptions
- *
- * @description GridOptions for grouping feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enableGrouping
- * @propertyOf ui.grid.grouping.api:GridOptions
- * @description Enable row grouping for entire grid.
- * <br/>Defaults to true
- */
- gridOptions.enableGrouping = gridOptions.enableGrouping !== false;
-
- /**
- * @ngdoc object
- * @name groupingShowCounts
- * @propertyOf ui.grid.grouping.api:GridOptions
- * @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a
- * sortingAlgorithm which relies on a specific format or data type, showing counts may cause that
- * to break, since the group header rows will always be a string with groupingShowCounts enabled.
- * <br/>Defaults to true except on columns of type 'date'
- */
- gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;
-
- /**
- * @ngdoc object
- * @name groupingNullLabel
- * @propertyOf ui.grid.grouping.api:GridOptions
- * @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.
- * <br/>Defaults to "Null"
- */
- gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;
-
- /**
- * @ngdoc object
- * @name enableGroupHeaderSelection
- * @propertyOf ui.grid.grouping.api:GridOptions
- * @description Allows group header rows to be selected.
- * <br/>Defaults to false
- */
- gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;
- },
-
-
- /**
- * @ngdoc function
- * @name groupingColumnBuilder
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Sets the grouping defaults based on the columnDefs
- *
- * @param {object} colDef columnDef we're basing on
- * @param {GridCol} col the column we're to update
- * @param {object} gridOptions the options we should use
- * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
- */
- groupingColumnBuilder: function (colDef, col, gridOptions) {
- /**
- * @ngdoc object
- * @name ui.grid.grouping.api:ColumnDef
- *
- * @description ColumnDef for grouping feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- /**
- * @ngdoc object
- * @name enableGrouping
- * @propertyOf ui.grid.grouping.api:ColumnDef
- * @description Enable grouping on this column
- * <br/>Defaults to true.
- */
- if (colDef.enableGrouping === false){
- return;
- }
-
- /**
- * @ngdoc object
- * @name grouping
- * @propertyOf ui.grid.grouping.api:ColumnDef
- * @description Set the grouping for a column. Format is:
- * ```
- * {
- * groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>
- * }
- * ```
- *
- * **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation
- * setting in treeBase**
- *
- * We group in the priority order given, this will also put these columns to the high order of the sort irrespective
- * of the sort priority given them. If there is no sort defined then we sort ascending, if there is a sort defined then
- * we use that sort.
- *
- * If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the
- * aggregation types to determine what sort of aggregation we can do. Values are in the constants file, but
- * include SUM, COUNT, MAX, MIN
- *
- * groupPriorities should generally be sequential, if they're not then the next time getGrouping is called
- * we'll renumber them to be sequential.
- * <br/>Defaults to undefined.
- */
-
- if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {
- col.grouping = angular.copy(colDef.grouping);
- if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ){
- col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
- col.treeAggregationFinalizerFn = service.groupedFinalizerFn;
- }
- } else if (typeof(col.grouping) === 'undefined'){
- col.grouping = {};
- }
-
- if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0){
- col.suppressRemoveSort = true;
- }
-
- var groupColumn = {
- name: 'ui.grid.grouping.group',
- title: i18nService.get().grouping.group,
- icon: 'ui-grid-icon-indent-right',
- shown: function () {
- return typeof(this.context.col.grouping) === 'undefined' ||
- typeof(this.context.col.grouping.groupPriority) === 'undefined' ||
- this.context.col.grouping.groupPriority < 0;
- },
- action: function () {
- service.groupColumn( this.context.col.grid, this.context.col );
- }
- };
-
- var ungroupColumn = {
- name: 'ui.grid.grouping.ungroup',
- title: i18nService.get().grouping.ungroup,
- icon: 'ui-grid-icon-indent-left',
- shown: function () {
- return typeof(this.context.col.grouping) !== 'undefined' &&
- typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&
- this.context.col.grouping.groupPriority >= 0;
- },
- action: function () {
- service.ungroupColumn( this.context.col.grid, this.context.col );
- }
- };
-
- var aggregateRemove = {
- name: 'ui.grid.grouping.aggregateRemove',
- title: i18nService.get().grouping.aggregate_remove,
- shown: function () {
- return typeof(this.context.col.treeAggregationFn) !== 'undefined';
- },
- action: function () {
- service.aggregateColumn( this.context.col.grid, this.context.col, null);
- }
- };
-
- // generic adder for the aggregation menus, which follow a pattern
- var addAggregationMenu = function(type, title){
- title = title || i18nService.get().grouping['aggregate_' + type] || type;
- var menuItem = {
- name: 'ui.grid.grouping.aggregate' + type,
- title: title,
- shown: function () {
- return typeof(this.context.col.treeAggregation) === 'undefined' ||
- typeof(this.context.col.treeAggregation.type) === 'undefined' ||
- this.context.col.treeAggregation.type !== type;
- },
- action: function () {
- service.aggregateColumn( this.context.col.grid, this.context.col, type);
- }
- };
-
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {
- col.menuItems.push(menuItem);
- }
- };
-
- /**
- * @ngdoc object
- * @name groupingShowGroupingMenu
- * @propertyOf ui.grid.grouping.api:ColumnDef
- * @description Show the grouping (group and ungroup items) menu on this column
- * <br/>Defaults to true.
- */
- if ( col.colDef.groupingShowGroupingMenu !== false ){
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {
- col.menuItems.push(groupColumn);
- }
-
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {
- col.menuItems.push(ungroupColumn);
- }
- }
-
-
- /**
- * @ngdoc object
- * @name groupingShowAggregationMenu
- * @propertyOf ui.grid.grouping.api:ColumnDef
- * @description Show the aggregation menu on this column
- * <br/>Defaults to true.
- */
- if ( col.colDef.groupingShowAggregationMenu !== false ){
- angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name){
- addAggregationMenu(name);
- });
- angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name){
- addAggregationMenu(name, aggregationDef.menuTitle);
- });
-
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {
- col.menuItems.push(aggregateRemove);
- }
- }
- },
-
-
-
-
- /**
- * @ngdoc function
- * @name groupingColumnProcessor
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Moves the columns around based on which are grouped
- *
- * @param {array} columns the columns to consider rendering
- * @param {array} rows the grid rows, which we don't use but are passed to us
- * @returns {array} updated columns array
- */
- groupingColumnProcessor: function( columns, rows ) {
- var grid = this;
-
- columns = service.moveGroupColumns(this, columns, rows);
- return columns;
- },
-
- /**
- * @ngdoc function
- * @name groupedFinalizerFn
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Used on group columns to display the rendered value and optionally
- * display the count of rows.
- *
- * @param {aggregation} the aggregation entity for a grouped column
- */
- groupedFinalizerFn: function( aggregation ){
- var col = this;
-
- if ( typeof(aggregation.groupVal) !== 'undefined') {
- aggregation.rendered = aggregation.groupVal;
- if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' ){
- aggregation.rendered += (' (' + aggregation.value + ')');
- }
- } else {
- aggregation.rendered = null;
- }
- },
-
- /**
- * @ngdoc function
- * @name moveGroupColumns
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Moves the column order so that the grouped columns are lined up
- * to the left (well, unless you're RTL, then it's the right). By doing this in
- * the columnsProcessor, we make it transient - when the column is ungrouped it'll
- * go back to where it was.
- *
- * Does nothing if the option `moveGroupColumns` is set to false.
- *
- * @param {Grid} grid grid object
- * @param {array} columns the columns that we should process/move
- * @param {array} rows the grid rows
- * @returns {array} updated columns
- */
- moveGroupColumns: function( grid, columns, rows ){
- if ( grid.options.moveGroupColumns === false){
- return columns;
- }
-
- columns.forEach( function(column, index){
- // position used to make stable sort in moveGroupColumns
- column.groupingPosition = index;
- });
-
- columns.sort(function(a, b){
- var a_group, b_group;
- if (a.isRowHeader){
- a_group = -1000;
- }
- else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0){
- a_group = null;
- } else {
- a_group = a.grouping.groupPriority;
- }
-
- if (b.isRowHeader){
- b_group = -1000;
- }
- else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0){
- b_group = null;
- } else {
- b_group = b.grouping.groupPriority;
- }
-
- // groups get sorted to the top
- if ( a_group !== null && b_group === null) { return -1; }
- if ( b_group !== null && a_group === null) { return 1; }
- if ( a_group !== null && b_group !== null) {return a_group - b_group; }
-
- return a.groupingPosition - b.groupingPosition;
- });
-
- columns.forEach( function(column, index) {
- delete column.groupingPosition;
- });
-
- return columns;
- },
-
-
- /**
- * @ngdoc function
- * @name groupColumn
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Adds this column to the existing grouping, at the end of the priority order.
- * If the column doesn't have a sort, adds one, by default ASC
- *
- * This column will move to the left of any non-group columns, the
- * move is handled in a columnProcessor, so gets called as part of refresh
- *
- * @param {Grid} grid grid object
- * @param {GridCol} column the column we want to group
- */
- groupColumn: function( grid, column){
- if ( typeof(column.grouping) === 'undefined' ){
- column.grouping = {};
- }
-
- // set the group priority to the next number in the hierarchy
- var existingGrouping = service.getGrouping( grid );
- column.grouping.groupPriority = existingGrouping.grouping.length;
-
- // add sort if not present
- if ( !column.sort ){
- column.sort = { direction: uiGridConstants.ASC };
- } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ){
- column.sort.direction = uiGridConstants.ASC;
- }
-
- column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };
- column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
- column.treeAggregationFinalizerFn = service.groupedFinalizerFn;
-
- grid.api.grouping.raise.groupingChanged(column);
- // This indirectly calls service.tidyPriorities( grid );
- grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
-
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name ungroupColumn
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Removes the groupPriority from this column. If the
- * column was previously aggregated the aggregation will come back.
- * The sort will remain.
- *
- * This column will move to the right of any other group columns, the
- * move is handled in a columnProcessor, so gets called as part of refresh
- *
- * @param {Grid} grid grid object
- * @param {GridCol} column the column we want to ungroup
- */
- ungroupColumn: function( grid, column){
- if ( typeof(column.grouping) === 'undefined' ){
- return;
- }
-
- delete column.grouping.groupPriority;
- delete column.treeAggregation;
- delete column.customTreeAggregationFinalizer;
-
- service.tidyPriorities( grid );
-
- grid.api.grouping.raise.groupingChanged(column);
-
- grid.queueGridRefresh();
- },
-
- /**
- * @ngdoc function
- * @name aggregateColumn
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Sets the aggregation type on a column, if the
- * column is currently grouped then it removes the grouping first.
- *
- * @param {Grid} grid grid object
- * @param {GridCol} column the column we want to aggregate
- * @param {string} one of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions
- */
- aggregateColumn: function( grid, column, aggregationType){
-
- if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
- service.ungroupColumn( grid, column );
- }
-
- var aggregationDef = {};
- if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ){
- aggregationDef = grid.options.treeCustomAggregations[aggregationType];
- } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ){
- aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];
- }
-
- column.treeAggregation = { type: aggregationType, label: i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };
- column.treeAggregationFn = aggregationDef.aggregationFn;
- column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;
-
- grid.api.grouping.raise.aggregationChanged(column);
-
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name setGrouping
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Set the grouping based on a config object, used by the save state feature
- * (more specifically, by the restore function in that feature )
- *
- * @param {Grid} grid grid object
- * @param {object} config the config we want to set, same format as that returned by getGrouping
- */
- setGrouping: function ( grid, config ){
- if ( typeof(config) === 'undefined' ){
- return;
- }
-
- // first remove any existing grouping
- service.clearGrouping(grid);
-
- if ( config.grouping && config.grouping.length && config.grouping.length > 0 ){
- config.grouping.forEach( function( group ) {
- var col = grid.getColumn(group.colName);
-
- if ( col ) {
- service.groupColumn( grid, col );
- }
- });
- }
-
- if ( config.aggregations && config.aggregations.length ){
- config.aggregations.forEach( function( aggregation ) {
- var col = grid.getColumn(aggregation.colName);
-
- if ( col ) {
- service.aggregateColumn( grid, col, aggregation.aggregation.type );
- }
- });
- }
-
- if ( config.rowExpandedStates ){
- service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );
- }
- },
-
-
- /**
- * @ngdoc function
- * @name clearGrouping
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
- * as we don't know whether that sorting was added by grouping or was there beforehand
- *
- * @param {Grid} grid grid object
- */
- clearGrouping: function( grid ) {
- var currentGrouping = service.getGrouping(grid);
-
- if ( currentGrouping.grouping.length > 0 ){
- currentGrouping.grouping.forEach( function( group ) {
- if (!group.col){
- // should have a group.colName if there's no col
- group.col = grid.getColumn(group.colName);
- }
- service.ungroupColumn(grid, group.col);
- });
- }
-
- if ( currentGrouping.aggregations.length > 0 ){
- currentGrouping.aggregations.forEach( function( aggregation ){
- if (!aggregation.col){
- // should have a group.colName if there's no col
- aggregation.col = grid.getColumn(aggregation.colName);
- }
- service.aggregateColumn(grid, aggregation.col, null);
- });
- }
- },
-
-
- /**
- * @ngdoc function
- * @name tidyPriorities
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Renumbers groupPriority and sortPriority such that
- * groupPriority is contiguous, and sortPriority either matches
- * groupPriority (for group columns), and otherwise is contiguous and
- * higher than groupPriority.
- *
- * @param {Grid} grid grid object
- */
- tidyPriorities: function( grid ){
- // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined
- if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {
- grid = this.grid;
- }
-
- var groupArray = [];
- var sortArray = [];
-
- grid.columns.forEach( function(column, index){
- if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
- groupArray.push(column);
- } else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0){
- sortArray.push(column);
- }
- });
-
- groupArray.sort(function(a, b){ return a.grouping.groupPriority - b.grouping.groupPriority; });
- groupArray.forEach( function(column, index){
- column.grouping.groupPriority = index;
- column.suppressRemoveSort = true;
- if ( typeof(column.sort) === 'undefined'){
- column.sort = {};
- }
- column.sort.priority = index;
- });
-
- var i = groupArray.length;
- sortArray.sort(function(a, b){ return a.sort.priority - b.sort.priority; });
- sortArray.forEach( function(column, index){
- column.sort.priority = i;
- column.suppressRemoveSort = column.colDef.suppressRemoveSort;
- i++;
- });
- },
-
-
- /**
- * @ngdoc function
- * @name groupRows
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description The rowProcessor that creates the groupHeaders (i.e. does
- * the actual grouping).
- *
- * Assumes it is always called after the sorting processor, guaranteed by the priority setting
- *
- * Processes all the rows in order, inserting a groupHeader row whenever there is a change
- * in value of a grouped row, based on the sortAlgorithm used for the column. The group header row
- * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset
- * to {} if one is found.
- *
- * As it processes it maintains a `processingState` array. This records, for each level of grouping we're
- * working with, the following information:
- * ```
- * {
- * fieldName: name,
- * col: col,
- * initialised: boolean,
- * currentValue: value,
- * currentRow: gridRow,
- * }
- * ```
- * We look for changes in the currentValue at any of the levels. Where we find a change we:
- *
- * - create a new groupHeader row in the array
- *
- * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
- * @returns {array} the updated rows, including our new group rows
- */
- groupRows: function( renderableRows ) {
- if (renderableRows.length === 0){
- return renderableRows;
- }
-
- var grid = this;
- grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};
- grid.grouping.groupingHeaderCache = {};
-
- var processingState = service.initialiseProcessingState( grid );
-
- // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader
- // Broken out as shouldn't create functions in a loop.
- var updateProcessingState = function( groupFieldState, stateIndex ) {
- var fieldValue = grid.getCellValue(row, groupFieldState.col);
-
- // look for change of value - and insert a header
- if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ){
- service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );
- i++;
- }
- };
-
- // use a for loop because it's tolerant of the array length changing whilst we go - we can
- // manipulate the iterator when we insert groupHeader rows
- for (var i = 0; i < renderableRows.length; i++ ){
- var row = renderableRows[i];
-
- if ( row.visible ){
- processingState.forEach( updateProcessingState );
- }
- }
-
- delete grid.grouping.oldGroupingHeaderCache;
- return renderableRows;
- },
-
-
- /**
- * @ngdoc function
- * @name initialiseProcessingState
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Creates the processing state array that is used
- * for groupRows.
- *
- * @param {Grid} grid grid object
- * @returns {array} an array in the format described in the groupRows method,
- * initialised with blank values
- */
- initialiseProcessingState: function( grid ){
- var processingState = [];
- var columnSettings = service.getGrouping( grid );
-
- columnSettings.grouping.forEach( function( groupItem, index){
- processingState.push({
- fieldName: groupItem.field,
- col: groupItem.col,
- initialised: false,
- currentValue: null,
- currentRow: null
- });
- });
-
- return processingState;
- },
-
-
- /**
- * @ngdoc function
- * @name getGrouping
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Get the grouping settings from the columns. As a side effect
- * this always renumbers the grouping starting at 0
- * @param {Grid} grid grid object
- * @returns {array} an array of the group fields, in order of priority
- */
- getGrouping: function( grid ){
- var groupArray = [];
- var aggregateArray = [];
-
- // get all the grouping
- grid.columns.forEach( function(column, columnIndex){
- if ( column.grouping ){
- if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0){
- groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });
- }
- }
- if ( column.treeAggregation && column.treeAggregation.type ){
- aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });
- }
- });
-
- // sort grouping into priority order
- groupArray.sort( function(a, b){
- return a.groupPriority - b.groupPriority;
- });
-
- // renumber the priority in case it was somewhat messed up, then remove the grouping reference
- groupArray.forEach( function( group, index) {
- group.grouping.groupPriority = index;
- group.groupPriority = index;
- delete group.grouping;
- });
-
- return { grouping: groupArray, aggregations: aggregateArray };
- },
-
-
- /**
- * @ngdoc function
- * @name insertGroupHeader
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Create a group header row, and link it to the various configuration
- * items that we use.
- *
- * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.
- *
- * @param {Grid} grid grid object
- * @param {array} renderableRows the rows that we are processing
- * @param {number} rowIndex the row we were up to processing
- * @param {array} processingState the current processing state
- * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -
- * i.e. the column that we want to create a header for
- */
- insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {
- // set the value that caused the end of a group into the header row and the processing state
- var fieldName = processingState[stateIndex].fieldName;
- var col = processingState[stateIndex].col;
-
- var newValue = grid.getCellValue(renderableRows[rowIndex], col);
- var newDisplayValue = newValue;
- if ( typeof(newValue) === 'undefined' || newValue === null ) {
- newDisplayValue = grid.options.groupingNullLabel;
- }
-
- var cacheItem = grid.grouping.oldGroupingHeaderCache;
- for ( var i = 0; i < stateIndex; i++ ){
- if ( cacheItem && cacheItem[processingState[i].currentValue] ){
- cacheItem = cacheItem[processingState[i].currentValue].children;
- }
- }
-
- var headerRow;
- if ( cacheItem && cacheItem[newValue]){
- headerRow = cacheItem[newValue].row;
- headerRow.entity = {};
- } else {
- headerRow = new GridRow( {}, null, grid );
- gridClassFactory.rowTemplateAssigner.call(grid, headerRow);
- }
-
- headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };
- headerRow.treeLevel = stateIndex;
- headerRow.groupHeader = true;
- headerRow.internalRow = true;
- headerRow.enableCellEdit = false;
- headerRow.enableSelection = grid.options.enableGroupHeaderSelection;
- processingState[stateIndex].initialised = true;
- processingState[stateIndex].currentValue = newValue;
- processingState[stateIndex].currentRow = headerRow;
-
- // set all processing states below this one to not be initialised - change of this state
- // means all those need to start again
- service.finaliseProcessingState( processingState, stateIndex + 1);
-
- // insert our new header row
- renderableRows.splice(rowIndex, 0, headerRow);
-
- // add our new header row to the cache
- cacheItem = grid.grouping.groupingHeaderCache;
- for ( i = 0; i < stateIndex; i++ ){
- cacheItem = cacheItem[processingState[i].currentValue].children;
- }
- cacheItem[newValue] = { row: headerRow, children: {} };
- },
-
-
- /**
- * @ngdoc function
- * @name finaliseProcessingState
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Set all processing states lower than the one that had a break in value to
- * no longer be initialised. Render the counts into the entity ready for display.
- *
- * @param {Grid} grid grid object
- * @param {array} processingState the current processing state
- * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all
- * processing states after this need to be finalised
- */
- finaliseProcessingState: function( processingState, stateIndex ){
- for ( var i = stateIndex; i < processingState.length; i++){
- processingState[i].initialised = false;
- processingState[i].currentRow = null;
- processingState[i].currentValue = null;
- }
- },
-
-
- /**
- * @ngdoc function
- * @name getRowExpandedStates
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Extract the groupHeaderCache hash, pulling out only the states.
- *
- * The example below shows a grid that is grouped by gender then age
- *
- * <pre>
- * {
- * male: {
- * state: 'expanded',
- * children: {
- * 22: { state: 'expanded' },
- * 30: { state: 'collapsed' }
- * }
- * },
- * female: {
- * state: 'expanded',
- * children: {
- * 28: { state: 'expanded' },
- * 55: { state: 'collapsed' }
- * }
- * }
- * }
- * </pre>
- *
- * @param {Grid} grid grid object
- * @returns {hash} the expanded states as a hash
- */
- getRowExpandedStates: function(treeChildren){
- if ( typeof(treeChildren) === 'undefined' ){
- return {};
- }
-
- var newChildren = {};
-
- angular.forEach( treeChildren, function( value, key ){
- newChildren[key] = { state: value.row.treeNode.state };
- if ( value.children ){
- newChildren[key].children = service.getRowExpandedStates( value.children );
- } else {
- newChildren[key].children = {};
- }
- });
-
- return newChildren;
- },
-
-
- /**
- * @ngdoc function
- * @name applyRowExpandedStates
- * @methodOf ui.grid.grouping.service:uiGridGroupingService
- * @description Take a hash in the format as created by getRowExpandedStates,
- * and apply it to the grid.grouping.groupHeaderCache.
- *
- * Takes a treeSubset, and applies to a treeSubset - so can be called
- * recursively.
- *
- * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of
- * the children of that hash
- * @returns {hash} expandedStates can be the full expanded states, or children
- * of that expanded states (which hopefully matches the subset of the groupHeaderCache)
- */
- applyRowExpandedStates: function( currentNode, expandedStates ){
- if ( typeof(expandedStates) === 'undefined' ){
- return;
- }
-
- angular.forEach(expandedStates, function( value, key ) {
- if ( currentNode[key] ){
- currentNode[key].row.treeNode.state = value.state;
-
- if (value.children && currentNode[key].children){
- service.applyRowExpandedStates( currentNode[key].children, value.children );
- }
- }
- });
- }
-
-
- };
-
- return service;
-
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.grouping.directive:uiGridGrouping
- * @element div
- * @restrict A
- *
- * @description Adds grouping features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.columnDefs = [
- {name: 'name', enableCellEdit: true},
- {name: 'title', enableCellEdit: true}
- ];
-
- $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="gridOptions" ui-grid-grouping></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService', '$templateCache',
- function (uiGridGroupingConstants, uiGridGroupingService, $templateCache) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- if (uiGridCtrl.grid.options.enableGrouping !== false){
- uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);
- }
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.importer
- * @description
- *
- * # ui.grid.importer
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module provides the ability to import data into the grid. It
- * uses the column defs to work out which data belongs in which column,
- * and creates entities from a configured class (typically a $resource).
- *
- * If the rowEdit feature is enabled, it also calls save on those newly
- * created objects, and then displays any errors in the imported data.
- *
- * Currently the importer imports only CSV and json files, although provision has been
- * made to process other file formats, and these can be added over time.
- *
- * For json files, the properties within each object in the json must match the column names
- * (to put it another way, the importer doesn't process the json, it just copies the objects
- * within the json into a new instance of the specified object type)
- *
- * For CSV import, the default column identification relies on each column in the
- * header row matching a column.name or column.displayName. Optionally, a column identification
- * callback can be used. This allows matching using other attributes, which is particularly
- * useful if your application has internationalised column headings (i.e. the headings that
- * the user sees don't match the column names).
- *
- * The importer makes use of the grid menu as the UI for requesting an
- * import.
- *
- * <div ui-grid-importer></div>
- */
-
- var module = angular.module('ui.grid.importer', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.importer.constant:uiGridImporterConstants
- *
- * @description constants available in importer module
- */
-
- module.constant('uiGridImporterConstants', {
- featureName: 'importer'
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.importer.service:uiGridImporterService
- *
- * @description Services for importer feature
- */
- module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',
- function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {
-
- var service = {
-
- initializeGrid: function ($scope, grid) {
-
- //add feature namespace and any properties to grid for needed state
- grid.importer = {
- $scope: $scope
- };
-
- this.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.importer.api:PublicApi
- *
- * @description Public Api for importer feature
- */
- var publicApi = {
- events: {
- importer: {
- }
- },
- methods: {
- importer: {
- /**
- * @ngdoc function
- * @name importFile
- * @methodOf ui.grid.importer.api:PublicApi
- * @description Imports a file into the grid using the file object
- * provided. Bypasses the grid menu
- * @param {File} fileObject the file we want to import, as a javascript
- * File object
- */
- importFile: function ( fileObject ) {
- service.importThisFile( grid, fileObject );
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- if ( grid.options.enableImporter && grid.options.importerShowMenu ){
- if ( grid.api.core.addToGridMenu ){
- service.addToMenu( grid );
- } else {
- // order of registration is not guaranteed, register in a little while
- $interval( function() {
- if (grid.api.core.addToGridMenu){
- service.addToMenu( grid );
- }
- }, 100, 1);
- }
- }
- },
-
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.importer.api:GridOptions
- *
- * @description GridOptions for importer feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.importer.api:GridOptions
- * @name enableImporter
- * @description Whether or not importer is enabled. Automatically set
- * to false if the user's browser does not support the required fileApi.
- * Otherwise defaults to true.
- *
- */
- if (gridOptions.enableImporter || gridOptions.enableImporter === undefined) {
- if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {
- gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');
- gridOptions.enableImporter = false;
- } else {
- gridOptions.enableImporter = true;
- }
- } else {
- gridOptions.enableImporter = false;
- }
-
- /**
- * @ngdoc method
- * @name importerProcessHeaders
- * @methodOf ui.grid.importer.api:GridOptions
- * @description A callback function that will process headers using custom
- * logic. Set this callback function if the headers that your user will provide in their
- * import file don't necessarily match the grid header or field names. This might commonly
- * occur where your application is internationalised, and therefore the field names
- * that the user recognises are in a different language than the field names that
- * ui-grid knows about.
- *
- * Defaults to the internal `processHeaders` method, which seeks to match using both
- * displayName and column.name. Any non-matching columns are discarded.
- *
- * Your callback routine should respond by processing the header array, and returning an array
- * of matching column names. A null value in any given position means "don't import this column"
- *
- * <pre>
- * gridOptions.importerProcessHeaders: function( headerArray ) {
- * var myHeaderColumns = [];
- * var thisCol;
- * headerArray.forEach( function( value, index ) {
- * thisCol = mySpecialLookupFunction( value );
- * myHeaderColumns.push( thisCol.name );
- * });
- *
- * return myHeaderCols;
- * })
- * </pre>
- * @param {Grid} grid the grid we're importing into
- * @param {array} headerArray an array of the text from the first row of the csv file,
- * which you need to match to column.names
- * @returns {array} array of matching column names, in the same order as the headerArray
- *
- */
- gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;
-
- /**
- * @ngdoc method
- * @name importerHeaderFilter
- * @methodOf ui.grid.importer.api:GridOptions
- * @description A callback function that will filter (usually translate) a single
- * header. Used when you want to match the passed in column names to the column
- * displayName after the header filter.
- *
- * Your callback routine needs to return the filtered header value.
- * <pre>
- * gridOptions.importerHeaderFilter: function( displayName ) {
- * return $translate.instant( displayName );
- * })
- * </pre>
- *
- * or:
- * <pre>
- * gridOptions.importerHeaderFilter: $translate.instant
- * </pre>
- * @param {string} displayName the displayName that we'd like to translate
- * @returns {string} the translated name
- *
- */
- gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };
-
- /**
- * @ngdoc method
- * @name importerErrorCallback
- * @methodOf ui.grid.importer.api:GridOptions
- * @description A callback function that provides custom error handling, rather
- * than the standard grid behaviour of an alert box and a console message. You
- * might use this to internationalise the console log messages, or to write to a
- * custom logging routine that returned errors to the server.
- *
- * <pre>
- * gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {
- * myUserDisplayRoutine( errorKey );
- * myLoggingRoutine( consoleMessage, context );
- * })
- * </pre>
- * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages
- * in some way
- * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,
- * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray
- * @param {string} consoleMessage the English console message that importer would have written
- * @param {object} context the context data that importer would have appended to that console message,
- * often the file content itself or the element that is in error
- *
- */
- if ( !gridOptions.importerErrorCallback || typeof(gridOptions.importerErrorCallback) !== 'function' ){
- delete gridOptions.importerErrorCallback;
- }
-
- /**
- * @ngdoc method
- * @name importerDataAddCallback
- * @methodOf ui.grid.importer.api:GridOptions
- * @description A mandatory callback function that adds data to the source data array. The grid
- * generally doesn't add rows to the source data array, it is tidier to handle this through a user
- * callback.
- *
- * <pre>
- * gridOptions.importerDataAddCallback: function( grid, newObjects ) {
- * $scope.myData = $scope.myData.concat( newObjects );
- * })
- * </pre>
- * @param {Grid} grid the grid we're importing into, may be useful in some way
- * @param {array} newObjects an array of new objects that you should add to your data
- *
- */
- if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {
- gridUtil.logError("You have not set an importerDataAddCallback, importer is disabled");
- gridOptions.enableImporter = false;
- }
-
- /**
- * @ngdoc object
- * @name importerNewObject
- * @propertyOf ui.grid.importer.api:GridOptions
- * @description An object on which we call `new` to create each new row before inserting it into
- * the data array. Typically this would be a $resource entity, which means that if you're using
- * the rowEdit feature, you can directly call save on this entity when the save event is triggered.
- *
- * Defaults to a vanilla javascript object
- *
- * @example
- * <pre>
- * gridOptions.importerNewObject = MyRes;
- * </pre>
- *
- */
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.importer.api:GridOptions
- * @name importerShowMenu
- * @description Whether or not to show an item in the grid menu. Defaults to true.
- *
- */
- gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.importer.api:GridOptions
- * @name importerObjectCallback
- * @description A callback that massages the data for each object. For example,
- * you might have data stored as a code value, but display the decode. This callback
- * can be used to change the decoded value back into a code. Defaults to doing nothing.
- * @param {Grid} grid in case you need it
- * @param {object} newObject the new object as importer has created it, modify it
- * then return the modified version
- * @returns {object} the modified object
- * @example
- * <pre>
- * gridOptions.importerObjectCallback = function ( grid, newObject ) {
- * switch newObject.status {
- * case 'Active':
- * newObject.status = 1;
- * break;
- * case 'Inactive':
- * newObject.status = 2;
- * break;
- * }
- * return newObject;
- * };
- * </pre>
- */
- gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };
- },
-
-
- /**
- * @ngdoc function
- * @name addToMenu
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Adds import menu item to the grid menu,
- * allowing the user to request import of a file
- * @param {Grid} grid the grid into which data should be imported
- */
- addToMenu: function ( grid ) {
- grid.api.core.addToGridMenu( grid, [
- {
- title: i18nService.getSafeText('gridMenu.importerTitle'),
- order: 150
- },
- {
- templateUrl: 'ui-grid/importerMenuItemContainer',
- action: function ($event) {
- this.grid.api.importer.importAFile( grid );
- },
- order: 151
- }
- ]);
- },
-
-
- /**
- * @ngdoc function
- * @name importThisFile
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Imports the provided file into the grid using the file object
- * provided. Bypasses the grid menu
- * @param {Grid} grid the grid we're importing into
- * @param {File} fileObject the file we want to import, as returned from the File
- * javascript object
- */
- importThisFile: function ( grid, fileObject ) {
- if (!fileObject){
- gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');
- return;
- }
-
- var reader = new FileReader();
-
- switch ( fileObject.type ){
- case 'application/json':
- reader.onload = service.importJsonClosure( grid );
- break;
- default:
- reader.onload = service.importCsvClosure( grid );
- break;
- }
-
- reader.readAsText( fileObject );
- },
-
-
- /**
- * @ngdoc function
- * @name importJson
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Creates a function that imports a json file into the grid.
- * The json data is imported into new objects of type `gridOptions.importerNewObject`,
- * and if the rowEdit feature is enabled the rows are marked as dirty
- * @param {Grid} grid the grid we want to import into
- * @param {FileObject} importFile the file that we want to import, as
- * a FileObject
- */
- importJsonClosure: function( grid ) {
- return function( importFile ){
- var newObjects = [];
- var newObject;
-
- var importArray = service.parseJson( grid, importFile );
- if (importArray === null){
- return;
- }
- importArray.forEach( function( value, index ) {
- newObject = service.newObject( grid );
- angular.extend( newObject, value );
- newObject = grid.options.importerObjectCallback( grid, newObject );
- newObjects.push( newObject );
- });
-
- service.addObjects( grid, newObjects );
-
- };
- },
-
-
- /**
- * @ngdoc function
- * @name parseJson
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Parses a json file, returns the parsed data.
- * Displays an error if file doesn't parse
- * @param {Grid} grid the grid that we want to import into
- * @param {FileObject} importFile the file that we want to import, as
- * a FileObject
- * @returns {array} array of objects from the imported json
- */
- parseJson: function( grid, importFile ){
- var loadedObjects;
- try {
- loadedObjects = JSON.parse( importFile.target.result );
- } catch (e) {
- service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );
- return;
- }
-
- if ( !Array.isArray( loadedObjects ) ){
- service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );
- return [];
- } else {
- return loadedObjects;
- }
- },
-
-
-
- /**
- * @ngdoc function
- * @name importCsvClosure
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Creates a function that imports a csv file into the grid
- * (allowing it to be used in the reader.onload event)
- * @param {Grid} grid the grid that we want to import into
- * @param {FileObject} importFile the file that we want to import, as
- * a file object
- */
- importCsvClosure: function( grid ) {
- return function( importFile ){
- var importArray = service.parseCsv( importFile );
- if ( !importArray || importArray.length < 1 ){
- service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );
- return;
- }
-
- var newObjects = service.createCsvObjects( grid, importArray );
- if ( !newObjects || newObjects.length === 0 ){
- service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );
- return;
- }
-
- service.addObjects( grid, newObjects );
- };
- },
-
-
- /**
- * @ngdoc function
- * @name parseCsv
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Parses a csv file into an array of arrays, with the first
- * array being the headers, and the remaining arrays being the data.
- * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,
- * which is noted as being under the MIT license. The code is modified to pass the jscs yoda condition
- * checker
- * @param {FileObject} importFile the file that we want to import, as a
- * file object
- */
- parseCsv: function( importFile ) {
- var csv = importFile.target.result;
-
- // use the CSV-JS library to parse
- return CSV.parse(csv);
- },
-
-
- /**
- * @ngdoc function
- * @name createCsvObjects
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Converts an array of arrays (representing the csv file)
- * into a set of objects. Uses the provided `gridOptions.importerNewObject`
- * to create the objects, and maps the header row into the individual columns
- * using either `gridOptions.importerProcessHeaders`, or by using a native method
- * of matching to either the displayName, column name or column field of
- * the columns in the column defs. The resulting objects will have attributes
- * that are named based on the column.field or column.name, in that order.
- * @param {Grid} grid the grid that we want to import into
- * @param {Array} importArray the data that we want to import, as an array
- */
- createCsvObjects: function( grid, importArray ){
- // pull off header row and turn into headers
- var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );
- if ( !headerMapping || headerMapping.length === 0 ){
- service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );
- return [];
- }
-
- var newObjects = [];
- var newObject;
- importArray.forEach( function( row, index ) {
- newObject = service.newObject( grid );
- if ( row !== null ){
- row.forEach( function( field, index ){
- if ( headerMapping[index] !== null ){
- newObject[ headerMapping[index] ] = field;
- }
- });
- }
- newObject = grid.options.importerObjectCallback( grid, newObject );
- newObjects.push( newObject );
- });
-
- return newObjects;
- },
-
-
- /**
- * @ngdoc function
- * @name processHeaders
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Determines the columns that the header row from
- * a csv (or other) file represents.
- * @param {Grid} grid the grid we're importing into
- * @param {array} headerRow the header row that we wish to match against
- * the column definitions
- * @returns {array} an array of the attribute names that should be used
- * for that column, based on matching the headers or creating the headers
- *
- */
- processHeaders: function( grid, headerRow ) {
- var headers = [];
- if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ){
- // we are going to create new columnDefs for all these columns, so just remove
- // spaces from the names to create fields
- headerRow.forEach( function( value, index ) {
- headers.push( value.replace( /[^0-9a-zA-Z\-_]/g, '_' ) );
- });
- return headers;
- } else {
- var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );
- headerRow.forEach( function( value, index ) {
- if ( lookupHash[value] ) {
- headers.push( lookupHash[value] );
- } else if ( lookupHash[ value.toLowerCase() ] ) {
- headers.push( lookupHash[ value.toLowerCase() ] );
- } else {
- headers.push( null );
- }
- });
- return headers;
- }
- },
-
-
- /**
- * @name flattenColumnDefs
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Runs through the column defs and creates a hash of
- * the displayName, name and field, and of each of those values forced to lower case,
- * with each pointing to the field or name
- * (whichever is present). Used to lookup column headers and decide what
- * attribute name to give to the resulting field.
- * @param {Grid} grid the grid we're importing into
- * @param {array} columnDefs the columnDefs that we should flatten
- * @returns {hash} the flattened version of the column def information, allowing
- * us to look up a value by `flattenedHash[ headerValue ]`
- */
- flattenColumnDefs: function( grid, columnDefs ){
- var flattenedHash = {};
- columnDefs.forEach( function( columnDef, index) {
- if ( columnDef.name ){
- flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;
- flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;
- }
-
- if ( columnDef.field ){
- flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;
- flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;
- }
-
- if ( columnDef.displayName ){
- flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;
- flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;
- }
-
- if ( columnDef.displayName && grid.options.importerHeaderFilter ){
- flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;
- flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;
- }
- });
-
- return flattenedHash;
- },
-
-
- /**
- * @ngdoc function
- * @name addObjects
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Inserts our new objects into the grid data, and
- * sets the rows to dirty if the rowEdit feature is being used
- *
- * Does this by registering a watch on dataChanges, which essentially
- * is waiting on the result of the grid data watch, and downstream processing.
- *
- * When the callback is called, it deregisters itself - we don't want to run
- * again next time data is added.
- *
- * If we never get called, we deregister on destroy.
- *
- * @param {Grid} grid the grid we're importing into
- * @param {array} newObjects the objects we want to insert into the grid data
- * @returns {object} the new object
- */
- addObjects: function( grid, newObjects, $scope ){
- if ( grid.api.rowEdit ){
- var dataChangeDereg = grid.registerDataChangeCallback( function() {
- grid.api.rowEdit.setRowsDirty( newObjects );
- dataChangeDereg();
- }, [uiGridConstants.dataChange.ROW] );
-
- grid.importer.$scope.$on( '$destroy', dataChangeDereg );
- }
-
- grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );
-
- },
-
-
- /**
- * @ngdoc function
- * @name newObject
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Makes a new object based on `gridOptions.importerNewObject`,
- * or based on an empty object if not present
- * @param {Grid} grid the grid we're importing into
- * @returns {object} the new object
- */
- newObject: function( grid ){
- if ( typeof(grid.options) !== "undefined" && typeof(grid.options.importerNewObject) !== "undefined" ){
- return new grid.options.importerNewObject();
- } else {
- return {};
- }
- },
-
-
- /**
- * @ngdoc function
- * @name alertError
- * @methodOf ui.grid.importer.service:uiGridImporterService
- * @description Provides an internationalised user alert for the failure,
- * and logs a console message including diagnostic content.
- * Optionally, if the the `gridOptions.importerErrorCallback` routine
- * is defined, then calls that instead, allowing user specified error routines
- * @param {Grid} grid the grid we're importing into
- * @param {array} headerRow the header row that we wish to match against
- * the column definitions
- */
- alertError: function( grid, alertI18nToken, consoleMessage, context ){
- if ( grid.options.importerErrorCallback ){
- grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );
- } else {
- $window.alert(i18nService.getSafeText( alertI18nToken ));
- gridUtil.logError(consoleMessage + context );
- }
- }
- };
-
- return service;
-
- }
- ]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.importer.directive:uiGridImporter
- * @element div
- * @restrict A
- *
- * @description Adds importer features to grid
- *
- */
- module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
- function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);
- }
- };
- }
- ]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.importer.directive:uiGridImporterMenuItem
- * @element div
- * @restrict A
- *
- * @description Handles the processing from the importer menu item - once a file is
- * selected
- *
- */
- module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
- function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- templateUrl: 'ui-grid/importerMenuItem',
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var handleFileSelect = function( event ){
- var target = event.srcElement || event.target;
-
- if (target && target.files && target.files.length === 1) {
- var fileObject = target.files[0];
- uiGridImporterService.importThisFile( grid, fileObject );
- target.form.reset();
- }
- };
-
- var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');
- var grid = uiGridCtrl.grid;
-
- if ( fileChooser.length !== 1 ){
- gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');
- } else {
- fileChooser[0].addEventListener('change', handleFileSelect, false); // TODO: why the false on the end? Google
- }
- }
- };
- }
- ]);
-})();
-
-(function() {
- 'use strict';
- /**
- * @ngdoc overview
- * @name ui.grid.infiniteScroll
- *
- * @description
- *
- * #ui.grid.infiniteScroll
- *
- * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
- *
- * This module provides infinite scroll functionality to ui-grid
- *
- */
- var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);
- /**
- * @ngdoc service
- * @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- *
- * @description Service for infinite scroll features
- */
- module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$timeout', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $timeout, uiGridConstants, ScrollEvent, $q) {
-
- var service = {
-
- /**
- * @ngdoc function
- * @name initializeGrid
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description This method register events and methods into grid public API
- */
-
- initializeGrid: function(grid, $scope) {
- service.defaultGridOptions(grid.options);
-
- if (!grid.options.enableInfiniteScroll){
- return;
- }
-
- grid.infiniteScroll = { dataLoading: false };
- service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );
- grid.api.core.on.scrollEnd($scope, service.handleScroll);
-
- /**
- * @ngdoc object
- * @name ui.grid.infiniteScroll.api:PublicAPI
- *
- * @description Public API for infinite scroll feature
- */
- var publicApi = {
- events: {
- infiniteScroll: {
-
- /**
- * @ngdoc event
- * @name needLoadMoreData
- * @eventOf ui.grid.infiniteScroll.api:PublicAPI
- * @description This event fires when scroll reaches bottom percentage of grid
- * and needs to load data
- */
-
- needLoadMoreData: function ($scope, fn) {
- },
-
- /**
- * @ngdoc event
- * @name needLoadMoreDataTop
- * @eventOf ui.grid.infiniteScroll.api:PublicAPI
- * @description This event fires when scroll reaches top percentage of grid
- * and needs to load data
- */
-
- needLoadMoreDataTop: function ($scope, fn) {
- }
- }
- },
- methods: {
- infiniteScroll: {
-
- /**
- * @ngdoc function
- * @name dataLoaded
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Call this function when you have loaded the additional data
- * requested. You should set scrollUp and scrollDown to indicate
- * whether there are still more pages in each direction.
- *
- * If you call dataLoaded without first calling `saveScrollPercentage` then we will
- * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll
- * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and
- * on variable speed internet connections. Using `saveScrollPercentage` as demonstrated in the tutorial
- * should give a smoother scrolling experience for users.
- *
- * See infinite_scroll tutorial for example of usage
- * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire
- * any more infinite scroll events upward
- * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't
- * fire any more infinite scroll events downward
- * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted. If you're
- * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning
- */
- dataLoaded: function( scrollUp, scrollDown ) {
- service.setScrollDirections(grid, scrollUp, scrollDown);
-
- var promise = service.adjustScroll(grid).then(function() {
- grid.infiniteScroll.dataLoading = false;
- });
-
- return promise;
- },
-
- /**
- * @ngdoc function
- * @name resetScroll
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Call this function when you have taken some action that makes the current
- * scroll position invalid. For example, if you're using external sorting and you've resorted
- * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps
- * you've reused an existing grid for a new data set
- *
- * You must tell us whether there is data upwards or downwards after the reset
- *
- * @param {boolean} scrollUp flag that there are pages upwards, fire
- * infinite scroll events upward
- * @param {boolean} scrollDown flag that there are pages downwards, so
- * fire infinite scroll events downward
- * @returns {promise} promise that is resolved when the scroll reset is complete
- */
- resetScroll: function( scrollUp, scrollDown ) {
- service.setScrollDirections( grid, scrollUp, scrollDown);
-
- return service.adjustInfiniteScrollPosition(grid, 0);
- },
-
-
- /**
- * @ngdoc function
- * @name saveScrollPercentage
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Saves the scroll percentage and number of visible rows before you adjust the data,
- * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`
- */
- saveScrollPercentage: function() {
- grid.infiniteScroll.prevScrollTop = grid.renderContainers.body.prevScrollTop;
- grid.infiniteScroll.previousVisibleRows = grid.getVisibleRowCount();
- },
-
-
- /**
- * @ngdoc function
- * @name dataRemovedTop
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Adjusts the scroll position after you've removed data at the top
- * @param {boolean} scrollUp flag that there are pages upwards, fire
- * infinite scroll events upward
- * @param {boolean} scrollDown flag that there are pages downwards, so
- * fire infinite scroll events downward
- */
- dataRemovedTop: function( scrollUp, scrollDown ) {
- service.dataRemovedTop( grid, scrollUp, scrollDown );
- },
-
- /**
- * @ngdoc function
- * @name dataRemovedBottom
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Adjusts the scroll position after you've removed data at the bottom
- * @param {boolean} scrollUp flag that there are pages upwards, fire
- * infinite scroll events upward
- * @param {boolean} scrollDown flag that there are pages downwards, so
- * fire infinite scroll events downward
- */
- dataRemovedBottom: function( scrollUp, scrollDown ) {
- service.dataRemovedBottom( grid, scrollUp, scrollDown );
- },
-
- /**
- * @ngdoc function
- * @name setScrollDirections
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
- * and also sets the grid.suppressParentScroll
- * @param {boolean} scrollUp whether there are pages available up - defaults to false
- * @param {boolean} scrollDown whether there are pages available down - defaults to true
- */
- setScrollDirections: function ( scrollUp, scrollDown ) {
- service.setScrollDirections( grid, scrollUp, scrollDown );
- }
-
- }
- }
- };
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
- },
-
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.infiniteScroll.api:GridOptions
- *
- * @description GridOptions for infinite scroll feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enableInfiniteScroll
- * @propertyOf ui.grid.infiniteScroll.api:GridOptions
- * @description Enable infinite scrolling for this grid
- * <br/>Defaults to true
- */
- gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;
-
- /**
- * @ngdoc property
- * @name infiniteScrollRowsFromEnd
- * @propertyOf ui.grid.class:GridOptions
- * @description This setting controls how close to the end of the dataset a user gets before
- * more data is requested by the infinite scroll, whether scrolling up or down. This allows you to
- * 'prefetch' rows before the user actually runs out of scrolling.
- *
- * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting
- * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll
- * preserve that scroll position
- *
- * <br> Defaults to 20
- */
- gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;
-
- /**
- * @ngdoc property
- * @name infiniteScrollUp
- * @propertyOf ui.grid.class:GridOptions
- * @description Whether you allow infinite scroll up, implying that the first page of data
- * you have displayed is in the middle of your data set. If set to true then we trigger the
- * needMoreDataTop event when the user hits the top of the scrollbar.
- * <br> Defaults to false
- */
- gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;
-
- /**
- * @ngdoc property
- * @name infiniteScrollDown
- * @propertyOf ui.grid.class:GridOptions
- * @description Whether you allow infinite scroll down, implying that the first page of data
- * you have displayed is in the middle of your data set. If set to true then we trigger the
- * needMoreData event when the user hits the bottom of the scrollbar.
- * <br> Defaults to true
- */
- gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;
- },
-
-
- /**
- * @ngdoc function
- * @name setScrollDirections
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
- * and also sets the grid.suppressParentScroll
- * @param {grid} grid the grid we're operating on
- * @param {boolean} scrollUp whether there are pages available up - defaults to false
- * @param {boolean} scrollDown whether there are pages available down - defaults to true
- */
- setScrollDirections: function ( grid, scrollUp, scrollDown ) {
- grid.infiniteScroll.scrollUp = ( scrollUp === true );
- grid.suppressParentScrollUp = ( scrollUp === true );
-
- grid.infiniteScroll.scrollDown = ( scrollDown !== false);
- grid.suppressParentScrollDown = ( scrollDown !== false);
- },
-
-
- /**
- * @ngdoc function
- * @name handleScroll
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description Called whenever the grid scrolls, determines whether the scroll should
- * trigger an infinite scroll request for more data
- * @param {object} args the args from the event
- */
- handleScroll: function (args) {
- // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function
- if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ){
- return;
- }
-
- if (args.y) {
- var percentage;
- var targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;
- if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {
- percentage = args.y.percentage;
- if (percentage <= targetPercentage){
- service.loadData(args.grid);
- }
- } else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {
- percentage = 1 - args.y.percentage;
- if (percentage <= targetPercentage){
- service.loadData(args.grid);
- }
- }
- }
- },
-
-
- /**
- * @ngdoc function
- * @name loadData
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
- * and whether there are more pages upwards or downwards. It also stores the number of rows that we had previously,
- * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`
- * @param {Grid} grid the grid we're working on
- */
- loadData: function (grid) {
- // save number of currently visible rows to calculate new scroll position later - we know that we want
- // to be at approximately the row we're currently at
- grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;
- grid.infiniteScroll.direction = grid.scrollDirection;
- delete grid.infiniteScroll.prevScrollTop;
-
- if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {
- grid.infiniteScroll.dataLoading = true;
- grid.api.infiniteScroll.raise.needLoadMoreDataTop();
- } else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {
- grid.infiniteScroll.dataLoading = true;
- grid.api.infiniteScroll.raise.needLoadMoreData();
- }
- },
-
-
- /**
- * @ngdoc function
- * @name adjustScroll
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description Once we are informed that data has been loaded, adjust the scroll position to account for that
- * addition and to make things look clean.
- *
- * If we're scrolling up we scroll to the first row of the old data set -
- * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by
- * the time the data comes back. If we're scrolling down we scoll to the last row of the old data set - so we're
- * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time
- * the data comes back.
- *
- * Neither of these are good assumptions, but making this a smoother experience really requires
- * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end). Even then
- * it'd be better still to actually run into the end. But if the data takes a while to come back, they may have scrolled
- * somewhere else in the mean-time, in which case they'll get a jump back to the new data. Anyway, this will do for
- * now, until someone wants to do better.
- * @param {Grid} grid the grid we're working on
- * @returns {promise} a promise that is resolved when scrolling has finished
- */
- adjustScroll: function(grid){
- var promise = $q.defer();
- $timeout(function () {
- var newPercentage, viewportHeight, rowHeight, newVisibleRows, oldTop, newTop;
-
- viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight;
- rowHeight = grid.options.rowHeight;
-
- if ( grid.infiniteScroll.direction === undefined ){
- // called from initialize, tweak our scroll up a little
- service.adjustInfiniteScrollPosition(grid, 0);
- }
-
- newVisibleRows = grid.getVisibleRowCount();
-
- // in case not enough data is loaded to enable scroller - load more data
- var canvasHeight = rowHeight * newVisibleRows;
- if (grid.infiniteScroll.scrollDown && (viewportHeight > canvasHeight)) {
- grid.api.infiniteScroll.raise.needLoadMoreData();
- }
-
- if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ){
- oldTop = grid.infiniteScroll.prevScrollTop || 0;
- newTop = oldTop + (newVisibleRows - grid.infiniteScroll.previousVisibleRows)*rowHeight;
- service.adjustInfiniteScrollPosition(grid, newTop);
- $timeout( function() {
- promise.resolve();
- });
- }
-
- if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ){
- newTop = grid.infiniteScroll.prevScrollTop || (grid.infiniteScroll.previousVisibleRows*rowHeight - viewportHeight);
- service.adjustInfiniteScrollPosition(grid, newTop);
- $timeout( function() {
- promise.resolve();
- });
- }
- }, 0);
-
- return promise.promise;
- },
-
-
- /**
- * @ngdoc function
- * @name adjustInfiniteScrollPosition
- * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
- * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
- * @param {Grid} grid the grid we're working on
- * @param {number} scrollTop the position through the grid that we want to scroll to
- * @returns {promise} a promise that is resolved when the scrolling finishes
- */
- adjustInfiniteScrollPosition: function (grid, scrollTop) {
- var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition'),
- visibleRows = grid.getVisibleRowCount(),
- viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight,
- rowHeight = grid.options.rowHeight,
- scrollHeight = visibleRows*rowHeight-viewportHeight;
-
- //for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active
- if (scrollTop === 0 && grid.infiniteScroll.scrollUp) {
- // using pixels results in a relative scroll, hence we have to use percentage
- scrollEvent.y = {percentage: 1/scrollHeight};
- }
- else {
- scrollEvent.y = {percentage: scrollTop/scrollHeight};
- }
- grid.scrollContainers('', scrollEvent);
- },
-
-
- /**
- * @ngdoc function
- * @name dataRemovedTop
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Adjusts the scroll position after you've removed data at the top. You should
- * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
- * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
- * before you start removing data
- * @param {Grid} grid the grid we're working on
- * @param {boolean} scrollUp flag that there are pages upwards, fire
- * infinite scroll events upward
- * @param {boolean} scrollDown flag that there are pages downwards, so
- * fire infinite scroll events downward
- * @returns {promise} a promise that is resolved when the scrolling finishes
- */
- dataRemovedTop: function( grid, scrollUp, scrollDown ) {
- var newVisibleRows, oldTop, newTop, rowHeight;
- service.setScrollDirections( grid, scrollUp, scrollDown );
-
- newVisibleRows = grid.renderContainers.body.visibleRowCache.length;
- oldTop = grid.infiniteScroll.prevScrollTop;
- rowHeight = grid.options.rowHeight;
-
- // since we removed from the top, our new scroll row will be the old scroll row less the number
- // of rows removed
- newTop = oldTop - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows )*rowHeight;
-
- return service.adjustInfiniteScrollPosition( grid, newTop );
- },
-
- /**
- * @ngdoc function
- * @name dataRemovedBottom
- * @methodOf ui.grid.infiniteScroll.api:PublicAPI
- * @description Adjusts the scroll position after you've removed data at the bottom. You should
- * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
- * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
- * before you start removing data
- * @param {Grid} grid the grid we're working on
- * @param {boolean} scrollUp flag that there are pages upwards, fire
- * infinite scroll events upward
- * @param {boolean} scrollDown flag that there are pages downwards, so
- * fire infinite scroll events downward
- */
- dataRemovedBottom: function( grid, scrollUp, scrollDown ) {
- var newTop;
- service.setScrollDirections( grid, scrollUp, scrollDown );
-
- newTop = grid.infiniteScroll.prevScrollTop;
-
- return service.adjustInfiniteScrollPosition( grid, newTop );
- }
- };
- return service;
- }]);
- /**
- * @ngdoc directive
- * @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll
- * @element div
- * @restrict A
- *
- * @description Adds infinite scroll features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Alex', car: 'Toyota' },
- { name: 'Sam', car: 'Lexus' }
- ];
-
- $scope.columnDefs = [
- {name: 'name'},
- {name: 'car'}
- ];
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-infinite-scroll="20"></div>
- </div>
- </file>
- </example>
- */
-
- module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',
- function (uiGridInfiniteScrollService) {
- return {
- priority: -200,
- scope: false,
- require: '^uiGrid',
- compile: function($scope, $elm, $attr){
- return {
- pre: function($scope, $elm, $attr, uiGridCtrl) {
- uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);
- },
- post: function($scope, $elm, $attr) {
- }
- };
- }
- };
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.moveColumns
- * @description
- *
- * # ui.grid.moveColumns
- *
- * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
- *
- * This module provides column moving capability to ui.grid. It enables to change the position of columns.
- * <div doc-module-components="ui.grid.moveColumns"></div>
- */
- var module = angular.module('ui.grid.moveColumns', ['ui.grid']);
-
- /**
- * @ngdoc service
- * @name ui.grid.moveColumns.service:uiGridMoveColumnService
- * @description Service for column moving feature.
- */
- module.service('uiGridMoveColumnService', ['$q', '$timeout', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $timeout, $log, ScrollEvent, uiGridConstants, gridUtil) {
-
- var service = {
- initializeGrid: function (grid) {
- var self = this;
- this.registerPublicApi(grid);
- this.defaultGridOptions(grid.options);
- grid.moveColumns = {orderCache: []}; // Used to cache the order before columns are rebuilt
- grid.registerColumnBuilder(self.movableColumnBuilder);
- grid.registerDataChangeCallback(self.verifyColumnOrder, [uiGridConstants.dataChange.COLUMN]);
- },
- registerPublicApi: function (grid) {
- var self = this;
- /**
- * @ngdoc object
- * @name ui.grid.moveColumns.api:PublicApi
- * @description Public Api for column moving feature.
- */
- var publicApi = {
- events: {
- /**
- * @ngdoc event
- * @name columnPositionChanged
- * @eventOf ui.grid.moveColumns.api:PublicApi
- * @description raised when column is moved
- * <pre>
- * gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition){})
- * </pre>
- * @param {object} colDef the column that was moved
- * @param {integer} originalPosition of the column
- * @param {integer} finalPosition of the column
- */
- colMovable: {
- columnPositionChanged: function (colDef, originalPosition, newPosition) {
- }
- }
- },
- methods: {
- /**
- * @ngdoc method
- * @name moveColumn
- * @methodOf ui.grid.moveColumns.api:PublicApi
- * @description Method can be used to change column position.
- * <pre>
- * gridApi.colMovable.moveColumn(oldPosition, newPosition)
- * </pre>
- * @param {integer} originalPosition of the column
- * @param {integer} finalPosition of the column
- */
- colMovable: {
- moveColumn: function (originalPosition, finalPosition) {
- var columns = grid.columns;
- if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {
- gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');
- return;
- }
- var nonMovableColumns = 0;
- for (var i = 0; i < columns.length; i++) {
- if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {
- nonMovableColumns++;
- }
- }
- if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {
- gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');
- return;
- }
- var findPositionForRenderIndex = function (index) {
- var position = index;
- for (var i = 0; i <= position; i++) {
- if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
- position++;
- }
- }
- return position;
- };
- self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));
- }
- }
- }
- };
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
- },
- defaultGridOptions: function (gridOptions) {
- /**
- * @ngdoc object
- * @name ui.grid.moveColumns.api:GridOptions
- *
- * @description Options for configuring the move column feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
- /**
- * @ngdoc object
- * @name enableColumnMoving
- * @propertyOf ui.grid.moveColumns.api:GridOptions
- * @description If defined, sets the default value for the colMovable flag on each individual colDefs
- * if their individual enableColumnMoving configuration is not defined. Defaults to true.
- */
- gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;
- },
- movableColumnBuilder: function (colDef, col, gridOptions) {
- var promises = [];
- /**
- * @ngdoc object
- * @name ui.grid.moveColumns.api:ColumnDef
- *
- * @description Column Definition for move column feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
- /**
- * @ngdoc object
- * @name enableColumnMoving
- * @propertyOf ui.grid.moveColumns.api:ColumnDef
- * @description Enable column moving for the column.
- */
- colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving
- : colDef.enableColumnMoving;
- return $q.all(promises);
- },
- /**
- * @ngdoc method
- * @name updateColumnCache
- * @methodOf ui.grid.moveColumns
- * @description Cache the current order of columns, so we can restore them after new columnDefs are defined
- */
- updateColumnCache: function(grid){
- grid.moveColumns.orderCache = grid.getOnlyDataColumns();
- },
- /**
- * @ngdoc method
- * @name verifyColumnOrder
- * @methodOf ui.grid.moveColumns
- * @description dataChangeCallback which uses the cached column order to restore the column order
- * when it is reset by altering the columnDefs array.
- */
- verifyColumnOrder: function(grid){
- var headerRowOffset = grid.rowHeaderColumns.length;
- var newIndex;
-
- angular.forEach(grid.moveColumns.orderCache, function(cacheCol, cacheIndex){
- newIndex = grid.columns.indexOf(cacheCol);
- if ( newIndex !== -1 && newIndex - headerRowOffset !== cacheIndex ){
- var column = grid.columns.splice(newIndex, 1)[0];
- grid.columns.splice(cacheIndex + headerRowOffset, 0, column);
- }
- });
- },
- redrawColumnAtPosition: function (grid, originalPosition, newPosition) {
-
- var columns = grid.columns;
-
- var originalColumn = columns[originalPosition];
- if (originalColumn.colDef.enableColumnMoving) {
- if (originalPosition > newPosition) {
- for (var i1 = originalPosition; i1 > newPosition; i1--) {
- columns[i1] = columns[i1 - 1];
- }
- }
- else if (newPosition > originalPosition) {
- for (var i2 = originalPosition; i2 < newPosition; i2++) {
- columns[i2] = columns[i2 + 1];
- }
- }
- columns[newPosition] = originalColumn;
- service.updateColumnCache(grid);
- grid.queueGridRefresh();
- $timeout(function () {
- grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
- grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);
- });
- }
- }
- };
- return service;
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.moveColumns.directive:uiGridMoveColumns
- * @element div
- * @restrict A
- * @description Adds column moving features to the ui-grid directive.
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO', age: 45 },
- { name: 'Frank', title: 'Lowly Developer', age: 25 },
- { name: 'Jenny', title: 'Highly Developer', age: 35 }
- ];
- $scope.columnDefs = [
- {name: 'name'},
- {name: 'title'},
- {name: 'age'}
- ];
- }]);
- </file>
- <file name="main.css">
- .grid {
- width: 100%;
- height: 150px;
- }
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div class="grid" ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-move-columns></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.moveColumns.directive:uiGridHeaderCell
- * @element div
- * @restrict A
- *
- * @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.
- *
- * On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.
- * In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).
- * On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.
- *
- * Events that invoke cloning of header cell:
- * - mousedown
- *
- * Events that invoke movement of cloned header cell:
- * - mousemove
- *
- * Events that invoke repositioning of column:
- * - mouseup
- */
- module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',
- function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {
- return {
- priority: -10,
- require: '^uiGrid',
- compile: function () {
- return {
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- if ($scope.col.colDef.enableColumnMoving) {
-
- /*
- * Our general approach to column move is that we listen to a touchstart or mousedown
- * event over the column header. When we hear one, then we wait for a move of the same type
- * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for
- * a mousemove (i.e. a drag) before we decide that there's a move underway. If there's never a move,
- * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.
- *
- */
- var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
-
- var gridLeft;
- var previousMouseX;
- var totalMouseMovement;
- var rightMoveLimit;
- var elmCloned = false;
- var movingElm;
- var reducedWidth;
- var moveOccurred = false;
-
- var downFn = function( event ){
- //Setting some variables required for calculations.
- gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
- if ( $scope.grid.hasLeftContainer() ){
- gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;
- }
-
- previousMouseX = event.pageX;
- totalMouseMovement = 0;
- rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();
-
- if ( event.type === 'mousedown' ){
- $document.on('mousemove', moveFn);
- $document.on('mouseup', upFn);
- } else if ( event.type === 'touchstart' ){
- $document.on('touchmove', moveFn);
- $document.on('touchend', upFn);
- }
- };
-
- var moveFn = function( event ) {
- var changeValue = event.pageX - previousMouseX;
- if ( changeValue === 0 ){ return; }
- //Disable text selection in Chrome during column move
- document.onselectstart = function() { return false; };
-
- moveOccurred = true;
-
- if (!elmCloned) {
- cloneElement();
- }
- else if (elmCloned) {
- moveElement(changeValue);
- previousMouseX = event.pageX;
- }
- };
-
- var upFn = function( event ){
- //Re-enable text selection after column move
- document.onselectstart = null;
-
- //Remove the cloned element on mouse up.
- if (movingElm) {
- movingElm.remove();
- elmCloned = false;
- }
-
- offAllEvents();
- onDownEvents();
-
- if (!moveOccurred){
- return;
- }
-
- var columns = $scope.grid.columns;
- var columnIndex = 0;
- for (var i = 0; i < columns.length; i++) {
- if (columns[i].colDef.name !== $scope.col.colDef.name) {
- columnIndex++;
- }
- else {
- break;
- }
- }
-
- //Case where column should be moved to a position on its left
- if (totalMouseMovement < 0) {
- var totalColumnsLeftWidth = 0;
- for (var il = columnIndex - 1; il >= 0; il--) {
- if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
- totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
- if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
- uiGridMoveColumnService.redrawColumnAtPosition
- ($scope.grid, columnIndex, il + 1);
- break;
- }
- }
- }
- //Case where column should be moved to beginning of the grid.
- if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {
- uiGridMoveColumnService.redrawColumnAtPosition
- ($scope.grid, columnIndex, 0);
- }
- }
-
- //Case where column should be moved to a position on its right
- else if (totalMouseMovement > 0) {
- var totalColumnsRightWidth = 0;
- for (var ir = columnIndex + 1; ir < columns.length; ir++) {
- if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
- totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
- if (totalColumnsRightWidth > totalMouseMovement) {
- uiGridMoveColumnService.redrawColumnAtPosition
- ($scope.grid, columnIndex, ir - 1);
- break;
- }
- }
- }
- //Case where column should be moved to end of the grid.
- if (totalColumnsRightWidth < totalMouseMovement) {
- uiGridMoveColumnService.redrawColumnAtPosition
- ($scope.grid, columnIndex, columns.length - 1);
- }
- }
- };
-
- var onDownEvents = function(){
- $contentsElm.on('touchstart', downFn);
- $contentsElm.on('mousedown', downFn);
- };
-
- var offAllEvents = function() {
- $contentsElm.off('touchstart', downFn);
- $contentsElm.off('mousedown', downFn);
-
- $document.off('mousemove', moveFn);
- $document.off('touchmove', moveFn);
-
- $document.off('mouseup', upFn);
- $document.off('touchend', upFn);
- };
-
- onDownEvents();
-
-
- var cloneElement = function () {
- elmCloned = true;
-
- //Cloning header cell and appending to current header cell.
- movingElm = $elm.clone();
- $elm.parent().append(movingElm);
-
- //Left of cloned element should be aligned to original header cell.
- movingElm.addClass('movingColumn');
- var movingElementStyles = {};
- var elmLeft;
- if (gridUtil.detectBrowser() === 'safari') {
- //Correction for Safari getBoundingClientRect,
- //which does not correctly compute when there is an horizontal scroll
- elmLeft = $elm[0].offsetLeft + $elm[0].offsetWidth - $elm[0].getBoundingClientRect().width;
- }
- else {
- elmLeft = $elm[0].getBoundingClientRect().left;
- }
- movingElementStyles.left = (elmLeft - gridLeft) + 'px';
- var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
- var elmRight = $elm[0].getBoundingClientRect().right;
- if (elmRight > gridRight) {
- reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
- movingElementStyles.width = reducedWidth + 'px';
- }
- movingElm.css(movingElementStyles);
- };
-
- var moveElement = function (changeValue) {
- //Calculate total column width
- var columns = $scope.grid.columns;
- var totalColumnWidth = 0;
- for (var i = 0; i < columns.length; i++) {
- if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {
- totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;
- }
- }
-
- //Calculate new position of left of column
- var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
- var currentElmRight = movingElm[0].getBoundingClientRect().right;
- var newElementLeft;
-
- newElementLeft = currentElmLeft - gridLeft + changeValue;
- newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;
-
- //Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
- if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
- movingElm.css({visibility: 'visible', 'left': newElementLeft + 'px'});
- }
- else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {
- changeValue *= 8;
- var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');
- scrollEvent.x = {pixels: changeValue};
- scrollEvent.grid.scrollContainers('',scrollEvent);
- }
-
- //Calculate total width of columns on the left of the moving column and the mouse movement
- var totalColumnsLeftWidth = 0;
- for (var il = 0; il < columns.length; il++) {
- if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
- if (columns[il].colDef.name !== $scope.col.colDef.name) {
- totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
- }
- else {
- break;
- }
- }
- }
- if ($scope.newScrollLeft === undefined) {
- totalMouseMovement += changeValue;
- }
- else {
- totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;
- }
-
- //Increase width of moving column, in case the rightmost column was moved and its width was
- //decreased because of overflow
- if (reducedWidth < $scope.col.drawnWidth) {
- reducedWidth += Math.abs(changeValue);
- movingElm.css({'width': reducedWidth + 'px'});
- }
- };
- }
- }
- };
- }
- };
- }]);
-})();
-
-(function() {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.pagination
- *
- * @description
- *
- * # ui.grid.pagination
- *
- * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
- *
- * This module provides pagination support to ui-grid
- */
- var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);
-
- /**
- * @ngdoc service
- * @name ui.grid.pagination.service:uiGridPaginationService
- *
- * @description Service for the pagination feature
- */
- module.service('uiGridPaginationService', ['gridUtil',
- function (gridUtil) {
- var service = {
- /**
- * @ngdoc method
- * @name initializeGrid
- * @methodOf ui.grid.pagination.service:uiGridPaginationService
- * @description Attaches the service to a certain grid
- * @param {Grid} grid The grid we want to work with
- */
- initializeGrid: function (grid) {
- service.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.pagination.api:PublicAPI
- *
- * @description Public API for the pagination feature
- */
- var publicApi = {
- events: {
- pagination: {
- /**
- * @ngdoc event
- * @name paginationChanged
- * @eventOf ui.grid.pagination.api:PublicAPI
- * @description This event fires when the pageSize or currentPage changes
- * @param {int} currentPage requested page number
- * @param {int} pageSize requested page size
- */
- paginationChanged: function (currentPage, pageSize) { }
- }
- },
- methods: {
- pagination: {
- /**
- * @ngdoc method
- * @name getPage
- * @methodOf ui.grid.pagination.api:PublicAPI
- * @description Returns the number of the current page
- */
- getPage: function () {
- return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;
- },
- /**
- * @ngdoc method
- * @name getTotalPages
- * @methodOf ui.grid.pagination.api:PublicAPI
- * @description Returns the total number of pages
- */
- getTotalPages: function () {
- if (!grid.options.enablePagination) {
- return null;
- }
-
- return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);
- },
- /**
- * @ngdoc method
- * @name nextPage
- * @methodOf ui.grid.pagination.api:PublicAPI
- * @description Moves to the next page, if possible
- */
- nextPage: function () {
- if (!grid.options.enablePagination) {
- return;
- }
-
- if (grid.options.totalItems > 0) {
- grid.options.paginationCurrentPage = Math.min(
- grid.options.paginationCurrentPage + 1,
- publicApi.methods.pagination.getTotalPages()
- );
- } else {
- grid.options.paginationCurrentPage++;
- }
- },
- /**
- * @ngdoc method
- * @name previousPage
- * @methodOf ui.grid.pagination.api:PublicAPI
- * @description Moves to the previous page, if we're not on the first page
- */
- previousPage: function () {
- if (!grid.options.enablePagination) {
- return;
- }
-
- grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);
- },
- /**
- * @ngdoc method
- * @name seek
- * @methodOf ui.grid.pagination.api:PublicAPI
- * @description Moves to the requested page
- * @param {int} page The number of the page that should be displayed
- */
- seek: function (page) {
- if (!grid.options.enablePagination) {
- return;
- }
- if (!angular.isNumber(page) || page < 1) {
- throw 'Invalid page number: ' + page;
- }
-
- grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- var processPagination = function( renderableRows ){
- if (grid.options.useExternalPagination || !grid.options.enablePagination) {
- return renderableRows;
- }
- //client side pagination
- var pageSize = parseInt(grid.options.paginationPageSize, 10);
- var currentPage = parseInt(grid.options.paginationCurrentPage, 10);
-
- var visibleRows = renderableRows.filter(function (row) { return row.visible; });
- grid.options.totalItems = visibleRows.length;
-
- var firstRow = (currentPage - 1) * pageSize;
- if (firstRow > visibleRows.length) {
- currentPage = grid.options.paginationCurrentPage = 1;
- firstRow = (currentPage - 1) * pageSize;
- }
- return visibleRows.slice(firstRow, firstRow + pageSize);
- };
-
- grid.registerRowsProcessor(processPagination, 900 );
-
- },
- defaultGridOptions: function (gridOptions) {
- /**
- * @ngdoc object
- * @name ui.grid.pagination.api:GridOptions
- *
- * @description GridOptions for the pagination feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc property
- * @name enablePagination
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Enables pagination, defaults to true
- */
- gridOptions.enablePagination = gridOptions.enablePagination !== false;
- /**
- * @ngdoc property
- * @name enablePaginationControls
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Enables the paginator at the bottom of the grid. Turn this off, if you want to implement your
- * own controls outside the grid.
- */
- gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;
- /**
- * @ngdoc property
- * @name useExternalPagination
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Disables client side pagination. When true, handle the paginationChanged event and set data
- * and totalItems, defaults to `false`
- */
- gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;
- /**
- * @ngdoc property
- * @name totalItems
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Total number of items, set automatically when client side pagination, needs set by user
- * for server side pagination
- */
- if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {
- gridOptions.totalItems = 0;
- }
- /**
- * @ngdoc property
- * @name paginationPageSizes
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Array of page sizes, defaults to `[250, 500, 1000]`
- */
- if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {
- gridOptions.paginationPageSizes = [250, 500, 1000];
- }
- /**
- * @ngdoc property
- * @name paginationPageSize
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty
- */
- if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {
- if (gridOptions.paginationPageSizes.length > 0) {
- gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];
- } else {
- gridOptions.paginationPageSize = 0;
- }
- }
- /**
- * @ngdoc property
- * @name paginationCurrentPage
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description Current page number, defaults to 1
- */
- if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {
- gridOptions.paginationCurrentPage = 1;
- }
-
- /**
- * @ngdoc property
- * @name paginationTemplate
- * @propertyOf ui.grid.pagination.api:GridOptions
- * @description A custom template for the pager, defaults to `ui-grid/pagination`
- */
- if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {
- gridOptions.paginationTemplate = 'ui-grid/pagination';
- }
- },
- /**
- * @ngdoc method
- * @methodOf ui.grid.pagination.service:uiGridPaginationService
- * @name uiGridPaginationService
- * @description Raises paginationChanged and calls refresh for client side pagination
- * @param {Grid} grid the grid for which the pagination changed
- * @param {int} currentPage requested page number
- * @param {int} pageSize requested page size
- */
- onPaginationChanged: function (grid, currentPage, pageSize) {
- grid.api.pagination.raise.paginationChanged(currentPage, pageSize);
- if (!grid.options.useExternalPagination) {
- grid.queueGridRefresh(); //client side pagination
- }
- }
- };
-
- return service;
- }
- ]);
- /**
- * @ngdoc directive
- * @name ui.grid.pagination.directive:uiGridPagination
- * @element div
- * @restrict A
- *
- * @description Adds pagination features to grid
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Alex', car: 'Toyota' },
- { name: 'Sam', car: 'Lexus' },
- { name: 'Joe', car: 'Dodge' },
- { name: 'Bob', car: 'Buick' },
- { name: 'Cindy', car: 'Ford' },
- { name: 'Brian', car: 'Audi' },
- { name: 'Malcom', car: 'Mercedes Benz' },
- { name: 'Dave', car: 'Ford' },
- { name: 'Stacey', car: 'Audi' },
- { name: 'Amy', car: 'Acura' },
- { name: 'Scott', car: 'Toyota' },
- { name: 'Ryan', car: 'BMW' },
- ];
-
- $scope.gridOptions = {
- data: 'data',
- paginationPageSizes: [5, 10, 25],
- paginationPageSize: 5,
- columnDefs: [
- {name: 'name'},
- {name: 'car'}
- ]
- }
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="gridOptions" ui-grid-pagination></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',
- function (gridUtil, uiGridPaginationService) {
- return {
- priority: -200,
- scope: false,
- require: 'uiGrid',
- link: {
- pre: function ($scope, $elm, $attr, uiGridCtrl) {
- uiGridPaginationService.initializeGrid(uiGridCtrl.grid);
-
- gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
- .then(function (contents) {
- var template = angular.element(contents);
- $elm.append(template);
- uiGridCtrl.innerCompile(template);
- });
- }
- }
- };
- }
- ]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.pagination.directive:uiGridPager
- * @element div
- *
- * @description Panel for handling pagination
- */
- module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService',
- function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService) {
- return {
- priority: -200,
- scope: true,
- require: '^uiGrid',
- link: function ($scope, $elm, $attr, uiGridCtrl) {
- var defaultFocusElementSelector = '.ui-grid-pager-control-input';
- $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels
-
- $scope.paginationApi = uiGridCtrl.grid.api.pagination;
- $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');
- $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');
- $scope.paginationOf = i18nService.getSafeText('pagination.of');
- $scope.paginationThrough = i18nService.getSafeText('pagination.through');
-
- var options = uiGridCtrl.grid.options;
-
- uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
- adjustment.height = adjustment.height - gridUtil.elementHeight($elm);
- return adjustment;
- });
-
- var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
- if (!grid.options.useExternalPagination) {
- grid.options.totalItems = grid.rows.length;
- }
- }, [uiGridConstants.dataChange.ROW]);
-
- $scope.$on('$destroy', dataChangeDereg);
-
- var setShowing = function () {
- $scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1;
- $scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems);
- };
-
- var deregT = $scope.$watch('grid.options.totalItems + grid.options.paginationPageSize', setShowing);
-
- var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {
- if (newValues === oldValues || oldValues === undefined) {
- return;
- }
-
- if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {
- options.paginationCurrentPage = 1;
- return;
- }
-
- if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {
- options.paginationCurrentPage = $scope.paginationApi.getTotalPages();
- return;
- }
-
- setShowing();
- uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);
- }
- );
-
- $scope.$on('$destroy', function() {
- deregT();
- deregP();
- });
-
- $scope.cantPageForward = function () {
- if (options.totalItems > 0) {
- return options.paginationCurrentPage >= $scope.paginationApi.getTotalPages();
- } else {
- return options.data.length < 1;
- }
- };
-
- $scope.cantPageToLast = function () {
- if (options.totalItems > 0) {
- return $scope.cantPageForward();
- } else {
- return true;
- }
- };
-
- $scope.cantPageBackward = function () {
- return options.paginationCurrentPage <= 1;
- };
-
- var focusToInputIf = function(condition){
- if (condition){
- gridUtil.focus.bySelector($elm, defaultFocusElementSelector);
- }
- };
-
- //Takes care of setting focus to the middle element when focus is lost
- $scope.pageFirstPageClick = function () {
- $scope.paginationApi.seek(1);
- focusToInputIf($scope.cantPageBackward());
- };
-
- $scope.pagePreviousPageClick = function () {
- $scope.paginationApi.previousPage();
- focusToInputIf($scope.cantPageBackward());
- };
-
- $scope.pageNextPageClick = function () {
- $scope.paginationApi.nextPage();
- focusToInputIf($scope.cantPageForward());
- };
-
- $scope.pageLastPageClick = function () {
- $scope.paginationApi.seek($scope.paginationApi.getTotalPages());
- focusToInputIf($scope.cantPageToLast());
- };
-
- }
- };
- }
- ]);
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.pinning
- * @description
- *
- * # ui.grid.pinning
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module provides column pinning to the end user via menu options in the column header
- *
- * <div doc-module-components="ui.grid.pinning"></div>
- */
-
- var module = angular.module('ui.grid.pinning', ['ui.grid']);
-
- module.constant('uiGridPinningConstants', {
- container: {
- LEFT: 'left',
- RIGHT: 'right',
- NONE: ''
- }
- });
-
- module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {
- var service = {
-
- initializeGrid: function (grid) {
- service.defaultGridOptions(grid.options);
-
- // Register a column builder to add new menu items for pinning left and right
- grid.registerColumnBuilder(service.pinningColumnBuilder);
-
- /**
- * @ngdoc object
- * @name ui.grid.pinning.api:PublicApi
- *
- * @description Public Api for pinning feature
- */
- var publicApi = {
- events: {
- pinning: {
- /**
- * @ngdoc event
- * @name columnPin
- * @eventOf ui.grid.pinning.api:PublicApi
- * @description raised when column pin state has changed
- * <pre>
- * gridApi.pinning.on.columnPinned(scope, function(colDef){})
- * </pre>
- * @param {object} colDef the column that was changed
- * @param {string} container the render container the column is in ('left', 'right', '')
- */
- columnPinned: function(colDef, container) {
- }
- }
- },
- methods: {
- pinning: {
- /**
- * @ngdoc function
- * @name pinColumn
- * @methodOf ui.grid.pinning.api:PublicApi
- * @description pin column left, right, or none
- * <pre>
- * gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)
- * </pre>
- * @param {gridColumn} col the column being pinned
- * @param {string} container one of the recognised types
- * from uiGridPinningConstants
- */
- pinColumn: function(col, container) {
- service.pinColumn(grid, col, container);
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.pinning.api:GridOptions
- *
- * @description GridOptions for pinning feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enablePinning
- * @propertyOf ui.grid.pinning.api:GridOptions
- * @description Enable pinning for the entire grid.
- * <br/>Defaults to true
- */
- gridOptions.enablePinning = gridOptions.enablePinning !== false;
-
- },
-
- pinningColumnBuilder: function (colDef, col, gridOptions) {
- //default to true unless gridOptions or colDef is explicitly false
-
- /**
- * @ngdoc object
- * @name ui.grid.pinning.api:ColumnDef
- *
- * @description ColumnDef for pinning feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- /**
- * @ngdoc object
- * @name enablePinning
- * @propertyOf ui.grid.pinning.api:ColumnDef
- * @description Enable pinning for the individual column.
- * <br/>Defaults to true
- */
- colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;
-
-
- /**
- * @ngdoc object
- * @name pinnedLeft
- * @propertyOf ui.grid.pinning.api:ColumnDef
- * @description Column is pinned left when grid is rendered
- * <br/>Defaults to false
- */
-
- /**
- * @ngdoc object
- * @name pinnedRight
- * @propertyOf ui.grid.pinning.api:ColumnDef
- * @description Column is pinned right when grid is rendered
- * <br/>Defaults to false
- */
- if (colDef.pinnedLeft) {
- col.renderContainer = 'left';
- col.grid.createLeftContainer();
- }
- else if (colDef.pinnedRight) {
- col.renderContainer = 'right';
- col.grid.createRightContainer();
- }
-
- if (!colDef.enablePinning) {
- return;
- }
-
- var pinColumnLeftAction = {
- name: 'ui.grid.pinning.pinLeft',
- title: i18nService.get().pinning.pinLeft,
- icon: 'ui-grid-icon-left-open',
- shown: function () {
- return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';
- },
- action: function () {
- service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);
- }
- };
-
- var pinColumnRightAction = {
- name: 'ui.grid.pinning.pinRight',
- title: i18nService.get().pinning.pinRight,
- icon: 'ui-grid-icon-right-open',
- shown: function () {
- return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';
- },
- action: function () {
- service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);
- }
- };
-
- var removePinAction = {
- name: 'ui.grid.pinning.unpin',
- title: i18nService.get().pinning.unpin,
- icon: 'ui-grid-icon-cancel',
- shown: function () {
- return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';
- },
- action: function () {
- service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.UNPIN);
- }
- };
-
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {
- col.menuItems.push(pinColumnLeftAction);
- }
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {
- col.menuItems.push(pinColumnRightAction);
- }
- if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {
- col.menuItems.push(removePinAction);
- }
- },
-
- pinColumn: function(grid, col, container) {
- if (container === uiGridPinningConstants.container.NONE) {
- col.renderContainer = null;
- }
- else {
- col.renderContainer = container;
- if (container === uiGridPinningConstants.container.LEFT) {
- grid.createLeftContainer();
- }
- else if (container === uiGridPinningConstants.container.RIGHT) {
- grid.createRightContainer();
- }
- }
-
- grid.refresh()
- .then(function() {
- grid.api.pinning.raise.columnPinned( col.colDef, container );
- });
- }
- };
-
- return service;
- }]);
-
- module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',
- function (gridUtil, uiGridPinningService) {
- return {
- require: 'uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridPinningService.initializeGrid(uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
-
-})();
-
-(function(){
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.resizeColumns
- * @description
- *
- * # ui.grid.resizeColumns
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module allows columns to be resized.
- */
- var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);
-
- module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$timeout',
- function (gridUtil, $q, $timeout) {
-
- var service = {
- defaultGridOptions: function(gridOptions){
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.resizeColumns.api:GridOptions
- *
- * @description GridOptions for resizeColumns feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enableColumnResizing
- * @propertyOf ui.grid.resizeColumns.api:GridOptions
- * @description Enable column resizing on the entire grid
- * <br/>Defaults to true
- */
- gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;
-
- //legacy support
- //use old name if it is explicitly false
- if (gridOptions.enableColumnResize === false){
- gridOptions.enableColumnResizing = false;
- }
- },
-
- colResizerColumnBuilder: function (colDef, col, gridOptions) {
-
- var promises = [];
- /**
- * @ngdoc object
- * @name ui.grid.resizeColumns.api:ColumnDef
- *
- * @description ColumnDef for resizeColumns feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- /**
- * @ngdoc object
- * @name enableColumnResizing
- * @propertyOf ui.grid.resizeColumns.api:ColumnDef
- * @description Enable column resizing on an individual column
- * <br/>Defaults to GridOptions.enableColumnResizing
- */
- //default to true unless gridOptions or colDef is explicitly false
- colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;
-
-
- //legacy support of old option name
- if (colDef.enableColumnResize === false){
- colDef.enableColumnResizing = false;
- }
-
- return $q.all(promises);
- },
-
- registerPublicApi: function (grid) {
- /**
- * @ngdoc object
- * @name ui.grid.resizeColumns.api:PublicApi
- * @description Public Api for column resize feature.
- */
- var publicApi = {
- events: {
- /**
- * @ngdoc event
- * @name columnSizeChanged
- * @eventOf ui.grid.resizeColumns.api:PublicApi
- * @description raised when column is resized
- * <pre>
- * gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange){})
- * </pre>
- * @param {object} colDef the column that was resized
- * @param {integer} delta of the column size change
- */
- colResizable: {
- columnSizeChanged: function (colDef, deltaChange) {
- }
- }
- }
- };
- grid.api.registerEventsFromObject(publicApi.events);
- },
-
- fireColumnSizeChanged: function (grid, colDef, deltaChange) {
- $timeout(function () {
- if ( grid.api.colResizable ){
- grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);
- } else {
- gridUtil.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.");
- }
- });
- },
-
- // get either this column, or the column next to this column, to resize,
- // returns the column we're going to resize
- findTargetCol: function(col, position, rtlMultiplier){
- var renderContainer = col.getRenderContainer();
-
- if (position === 'left') {
- // Get the column to the left of this one
- var colIndex = renderContainer.visibleColumnCache.indexOf(col);
- return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];
- } else {
- return col;
- }
- }
-
- };
-
- return service;
-
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.resizeColumns.directive:uiGridResizeColumns
- * @element div
- * @restrict A
- * @description
- * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the
- * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.
- *
- * @example
- <doc:example module="app">
- <doc:source>
- <script>
- var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.gridOpts = {
- data: [
- { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
- { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
- { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
- { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
- ]
- };
- }]);
- </script>
-
- <div ng-controller="MainCtrl">
- <div class="testGrid" ui-grid="gridOpts" ui-grid-resize-columns ></div>
- </div>
- </doc:source>
- <doc:scenario>
-
- </doc:scenario>
- </doc:example>
- */
- module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);
- uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);
- uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
- // Extend the uiGridHeaderCell directive
- module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', '$timeout', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants, $timeout) {
- return {
- // Run after the original uiGridHeaderCell
- priority: -10,
- require: '^uiGrid',
- // scope: false,
- compile: function() {
- return {
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- var grid = uiGridCtrl.grid;
-
- if (grid.options.enableColumnResizing) {
- var columnResizerElm = $templateCache.get('ui-grid/columnResizer');
-
- var rtlMultiplier = 1;
- //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
- if (grid.isRTL()) {
- $scope.position = 'left';
- rtlMultiplier = -1;
- }
-
- var displayResizers = function(){
-
- // remove any existing resizers.
- var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');
- for ( var i = 0; i < resizers.length; i++ ){
- angular.element(resizers[i]).remove();
- }
-
- // get the target column for the left resizer
- var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);
- var renderContainer = $scope.col.getRenderContainer();
-
- // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled
- if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {
- var resizerLeft = angular.element(columnResizerElm).clone();
- resizerLeft.attr('position', 'left');
-
- $elm.prepend(resizerLeft);
- $compile(resizerLeft)($scope);
- }
-
- // Don't append the right resizer if this column has resizing disabled
- if ($scope.col.colDef.enableColumnResizing !== false) {
- var resizerRight = angular.element(columnResizerElm).clone();
- resizerRight.attr('position', 'right');
-
- $elm.append(resizerRight);
- $compile(resizerRight)($scope);
- }
- };
-
- displayResizers();
-
- var waitDisplay = function(){
- $timeout(displayResizers);
- };
-
- var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );
-
- $scope.$on( '$destroy', dataChangeDereg );
- }
- }
- };
- }
- };
- }]);
-
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.resizeColumns.directive:uiGridColumnResizer
- * @element div
- * @restrict A
- *
- * @description
- * Draggable handle that controls column resizing.
- *
- * @example
- <doc:example module="app">
- <doc:source>
- <script>
- var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.gridOpts = {
- enableColumnResizing: true,
- data: [
- { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
- { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
- { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
- { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
- ]
- };
- }]);
- </script>
-
- <div ng-controller="MainCtrl">
- <div class="testGrid" ui-grid="gridOpts"></div>
- </div>
- </doc:source>
- <doc:scenario>
- // TODO: e2e specs?
-
- // TODO: post-resize a horizontal scroll event should be fired
- </doc:scenario>
- </doc:example>
- */
- module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {
- var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');
-
- var resizer = {
- priority: 0,
- scope: {
- col: '=',
- position: '@',
- renderIndex: '='
- },
- require: '?^uiGrid',
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- var startX = 0,
- x = 0,
- gridLeft = 0,
- rtlMultiplier = 1;
-
- //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
- if (uiGridCtrl.grid.isRTL()) {
- $scope.position = 'left';
- rtlMultiplier = -1;
- }
-
- if ($scope.position === 'left') {
- $elm.addClass('left');
- }
- else if ($scope.position === 'right') {
- $elm.addClass('right');
- }
-
- // Refresh the grid canvas
- // takes an argument representing the diff along the X-axis that the resize had
- function refreshCanvas(xDiff) {
- // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
- uiGridCtrl.grid.refreshCanvas(true).then( function() {
- uiGridCtrl.grid.queueGridRefresh();
- });
- }
-
- // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
- // Returns the new recommended with, after constraints applied
- function constrainWidth(col, width){
- var newWidth = width;
-
- // If the new width would be less than the column's allowably minimum width, don't allow it
- if (col.minWidth && newWidth < col.minWidth) {
- newWidth = col.minWidth;
- }
- else if (col.maxWidth && newWidth > col.maxWidth) {
- newWidth = col.maxWidth;
- }
-
- return newWidth;
- }
-
-
- /*
- * Our approach to event handling aims to deal with both touch devices and mouse devices
- * We register down handlers on both touch and mouse. When a touchstart or mousedown event
- * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
- *
- * This way we can listen for both without worrying about the fact many touch devices also emulate
- * mouse events - basically whichever one we hear first is what we'll go with.
- */
- function moveFunction(event, args) {
- if (event.originalEvent) { event = event.originalEvent; }
- event.preventDefault();
-
- x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
-
- if (x < 0) { x = 0; }
- else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }
-
- var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
-
- // Don't resize if it's disabled on this column
- if (col.colDef.enableColumnResizing === false) {
- return;
- }
-
- if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
- uiGridCtrl.grid.element.addClass('column-resizing');
- }
-
- // Get the diff along the X axis
- var xDiff = x - startX;
-
- // Get the width that this mouse would give the column
- var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
-
- // check we're not outside the allowable bounds for this column
- x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;
-
- resizeOverlay.css({ left: x + 'px' });
-
- uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
- }
-
-
- function upFunction(event, args) {
- if (event.originalEvent) { event = event.originalEvent; }
- event.preventDefault();
-
- uiGridCtrl.grid.element.removeClass('column-resizing');
-
- resizeOverlay.remove();
-
- // Resize the column
- x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
- var xDiff = x - startX;
-
- if (xDiff === 0) {
- // no movement, so just reset event handlers, including turning back on both
- // down events - we turned one off when this event started
- offAllEvents();
- onDownEvents();
- return;
- }
-
- var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
-
- // Don't resize if it's disabled on this column
- if (col.colDef.enableColumnResizing === false) {
- return;
- }
-
- // Get the new width
- var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
-
- // check we're not outside the allowable bounds for this column
- col.width = constrainWidth(col, newWidth);
- col.hasCustomWidth = true;
-
- refreshCanvas(xDiff);
-
- uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
-
- // stop listening of up and move events - wait for next down
- // reset the down events - we will have turned one off when this event started
- offAllEvents();
- onDownEvents();
- }
-
-
- var downFunction = function(event, args) {
- if (event.originalEvent) { event = event.originalEvent; }
- event.stopPropagation();
-
- // Get the left offset of the grid
- // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
- gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;
-
- // Get the starting X position, which is the X coordinate of the click minus the grid's offset
- startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
-
- // Append the resizer overlay
- uiGridCtrl.grid.element.append(resizeOverlay);
-
- // Place the resizer overlay at the start position
- resizeOverlay.css({ left: startX });
-
- // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
- // we were touchdown then we listen for touchmove and touchup. Also remove the handler for the equivalent
- // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
- // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
- if ( event.type === 'touchstart' ){
- $document.on('touchend', upFunction);
- $document.on('touchmove', moveFunction);
- $elm.off('mousedown', downFunction);
- } else {
- $document.on('mouseup', upFunction);
- $document.on('mousemove', moveFunction);
- $elm.off('touchstart', downFunction);
- }
- };
-
- var onDownEvents = function() {
- $elm.on('mousedown', downFunction);
- $elm.on('touchstart', downFunction);
- };
-
- var offAllEvents = function() {
- $document.off('mouseup', upFunction);
- $document.off('touchend', upFunction);
- $document.off('mousemove', moveFunction);
- $document.off('touchmove', moveFunction);
- $elm.off('mousedown', downFunction);
- $elm.off('touchstart', downFunction);
- };
-
- onDownEvents();
-
-
- // On doubleclick, resize to fit all rendered cells
- var dblClickFn = function(event, args){
- event.stopPropagation();
-
- var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
-
- // Don't resize if it's disabled on this column
- if (col.colDef.enableColumnResizing === false) {
- return;
- }
-
- // Go through the rendered rows and find out the max size for the data in this column
- var maxWidth = 0;
- var xDiff = 0;
-
- // Get the parent render container element
- var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');
-
- // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present
- var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');
- Array.prototype.forEach.call(cells, function (cell) {
- // Get the cell width
- // gridUtil.logDebug('width', gridUtil.elementWidth(cell));
-
- // Account for the menu button if it exists
- var menuButton;
- if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {
- menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');
- }
-
- gridUtil.fakeElement(cell, {}, function(newElm) {
- // Make the element float since it's a div and can expand to fill its container
- var e = angular.element(newElm);
- e.attr('style', 'float: left');
-
- var width = gridUtil.elementWidth(e);
-
- if (menuButton) {
- var menuButtonWidth = gridUtil.elementWidth(menuButton);
- width = width + menuButtonWidth;
- }
-
- if (width > maxWidth) {
- maxWidth = width;
- xDiff = maxWidth - width;
- }
- });
- });
-
- // check we're not outside the allowable bounds for this column
- col.width = constrainWidth(col, maxWidth);
- col.hasCustomWidth = true;
-
- refreshCanvas(xDiff);
-
- uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff); };
- $elm.on('dblclick', dblClickFn);
-
- $elm.on('$destroy', function() {
- $elm.off('dblclick', dblClickFn);
- offAllEvents();
- });
- }
- };
-
- return resizer;
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.rowEdit
- * @description
- *
- * # ui.grid.rowEdit
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module extends the edit feature to provide tracking and saving of rows
- * of data. The tutorial provides more information on how this feature is best
- * used {@link tutorial/205_row_editable here}.
- * <br/>
- * This feature depends on usage of the ui-grid-edit feature, and also benefits
- * from use of ui-grid-cellNav to provide the full spreadsheet-like editing
- * experience
- *
- */
-
- var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
-
- /**
- * @ngdoc object
- * @name ui.grid.rowEdit.constant:uiGridRowEditConstants
- *
- * @description constants available in row edit module
- */
- module.constant('uiGridRowEditConstants', {
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.rowEdit.service:uiGridRowEditService
- *
- * @description Services for row editing features
- */
- module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',
- function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {
-
- var service = {
-
- initializeGrid: function (scope, grid) {
- /**
- * @ngdoc object
- * @name ui.grid.rowEdit.api:PublicApi
- *
- * @description Public Api for rowEdit feature
- */
-
- grid.rowEdit = {};
-
- var publicApi = {
- events: {
- rowEdit: {
- /**
- * @ngdoc event
- * @eventOf ui.grid.rowEdit.api:PublicApi
- * @name saveRow
- * @description raised when a row is ready for saving. Once your
- * row has saved you may need to use angular.extend to update the
- * data entity with any changed data from your save (for example,
- * lock version information if you're using optimistic locking,
- * or last update time/user information).
- *
- * Your method should call setSavePromise somewhere in the body before
- * returning control. The feature will then wait, with the gridRow greyed out
- * whilst this promise is being resolved.
- *
- * <pre>
- * gridApi.rowEdit.on.saveRow(scope,function(rowEntity){})
- * </pre>
- * and somewhere within the event handler:
- * <pre>
- * gridApi.rowEdit.setSavePromise( rowEntity, savePromise)
- * </pre>
- * @param {object} rowEntity the options.data element that was edited
- * @returns {promise} Your saveRow method should return a promise, the
- * promise should either be resolved (implying successful save), or
- * rejected (implying an error).
- */
- saveRow: function (rowEntity) {
- }
- }
- },
- methods: {
- rowEdit: {
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name setSavePromise
- * @description Sets the promise associated with the row save, mandatory that
- * the saveRow event handler calls this method somewhere before returning.
- * <pre>
- * gridApi.rowEdit.setSavePromise(rowEntity, savePromise)
- * </pre>
- * @param {object} rowEntity a data row from the grid for which a save has
- * been initiated
- * @param {promise} savePromise the promise that will be resolved when the
- * save is successful, or rejected if the save fails
- *
- */
- setSavePromise: function ( rowEntity, savePromise) {
- service.setSavePromise(grid, rowEntity, savePromise);
- },
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name getDirtyRows
- * @description Returns all currently dirty rows
- * <pre>
- * gridApi.rowEdit.getDirtyRows(grid)
- * </pre>
- * @returns {array} An array of gridRows that are currently dirty
- *
- */
- getDirtyRows: function () {
- return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];
- },
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name getErrorRows
- * @description Returns all currently errored rows
- * <pre>
- * gridApi.rowEdit.getErrorRows(grid)
- * </pre>
- * @returns {array} An array of gridRows that are currently in error
- *
- */
- getErrorRows: function () {
- return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];
- },
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name flushDirtyRows
- * @description Triggers a save event for all currently dirty rows, could
- * be used where user presses a save button or navigates away from the page
- * <pre>
- * gridApi.rowEdit.flushDirtyRows(grid)
- * </pre>
- * @returns {promise} a promise that represents the aggregate of all
- * of the individual save promises - i.e. it will be resolved when all
- * the individual save promises have been resolved.
- *
- */
- flushDirtyRows: function () {
- return service.flushDirtyRows(grid);
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name setRowsDirty
- * @description Sets each of the rows passed in dataRows
- * to be dirty. note that if you have only just inserted the
- * rows into your data you will need to wait for a $digest cycle
- * before the gridRows are present - so often you would wrap this
- * call in a $interval or $timeout
- * <pre>
- * $interval( function() {
- * gridApi.rowEdit.setRowsDirty(myDataRows);
- * }, 0, 1);
- * </pre>
- * @param {array} dataRows the data entities for which the gridRows
- * should be set dirty.
- *
- */
- setRowsDirty: function ( dataRows) {
- service.setRowsDirty(grid, dataRows);
- },
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.api:PublicApi
- * @name setRowsClean
- * @description Sets each of the rows passed in dataRows
- * to be clean, removing them from the dirty cache and the error cache,
- * and clearing the error flag and the dirty flag
- * <pre>
- * var gridRows = $scope.gridApi.rowEdit.getDirtyRows();
- * var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });
- * $scope.gridApi.rowEdit.setRowsClean( dataRows );
- * </pre>
- * @param {array} dataRows the data entities for which the gridRows
- * should be set clean.
- *
- */
- setRowsClean: function ( dataRows) {
- service.setRowsClean(grid, dataRows);
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- grid.api.core.on.renderingComplete( scope, function ( gridApi ) {
- grid.api.edit.on.afterCellEdit( scope, service.endEditCell );
- grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );
- grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );
-
- if ( grid.api.cellNav ) {
- grid.api.cellNav.on.navigate( scope, service.navigate );
- }
- });
-
- },
-
- defaultGridOptions: function (gridOptions) {
-
- /**
- * @ngdoc object
- * @name ui.grid.rowEdit.api:GridOptions
- *
- * @description Options for configuring the rowEdit feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name saveRow
- * @description Returns a function that saves the specified row from the grid,
- * and returns a promise
- * @param {object} grid the grid for which dirty rows should be flushed
- * @param {GridRow} gridRow the row that should be saved
- * @returns {function} the saveRow function returns a function. That function
- * in turn, when called, returns a promise relating to the save callback
- */
- saveRow: function ( grid, gridRow ) {
- var self = this;
-
- return function() {
- gridRow.isSaving = true;
-
- if ( gridRow.rowEditSavePromise ){
- // don't save the row again if it's already saving - that causes stale object exceptions
- return gridRow.rowEditSavePromise;
- }
-
- var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );
-
- if ( gridRow.rowEditSavePromise ){
- gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));
- } else {
- gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );
- }
- return promise;
- };
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name setSavePromise
- * @description Sets the promise associated with the row save, mandatory that
- * the saveRow event handler calls this method somewhere before returning.
- * <pre>
- * gridApi.rowEdit.setSavePromise(grid, rowEntity)
- * </pre>
- * @param {object} grid the grid for which dirty rows should be returned
- * @param {object} rowEntity a data row from the grid for which a save has
- * been initiated
- * @param {promise} savePromise the promise that will be resolved when the
- * save is successful, or rejected if the save fails
- *
- */
- setSavePromise: function (grid, rowEntity, savePromise) {
- var gridRow = grid.getRow( rowEntity );
- gridRow.rowEditSavePromise = savePromise;
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name processSuccessPromise
- * @description Returns a function that processes the successful
- * resolution of a save promise
- * @param {object} grid the grid for which the promise should be processed
- * @param {GridRow} gridRow the row that has been saved
- * @returns {function} the success handling function
- */
- processSuccessPromise: function ( grid, gridRow ) {
- var self = this;
-
- return function() {
- delete gridRow.isSaving;
- delete gridRow.isDirty;
- delete gridRow.isError;
- delete gridRow.rowEditSaveTimer;
- delete gridRow.rowEditSavePromise;
- self.removeRow( grid.rowEdit.errorRows, gridRow );
- self.removeRow( grid.rowEdit.dirtyRows, gridRow );
- };
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name processErrorPromise
- * @description Returns a function that processes the failed
- * resolution of a save promise
- * @param {object} grid the grid for which the promise should be processed
- * @param {GridRow} gridRow the row that is now in error
- * @returns {function} the error handling function
- */
- processErrorPromise: function ( grid, gridRow ) {
- return function() {
- delete gridRow.isSaving;
- delete gridRow.rowEditSaveTimer;
- delete gridRow.rowEditSavePromise;
-
- gridRow.isError = true;
-
- if (!grid.rowEdit.errorRows){
- grid.rowEdit.errorRows = [];
- }
- if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ){
- grid.rowEdit.errorRows.push( gridRow );
- }
- };
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name removeRow
- * @description Removes a row from a cache of rows - either
- * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows. If the row
- * is not present silently does nothing.
- * @param {array} rowArray the array from which to remove the row
- * @param {GridRow} gridRow the row that should be removed
- */
- removeRow: function( rowArray, removeGridRow ){
- if (typeof(rowArray) === 'undefined' || rowArray === null){
- return;
- }
-
- rowArray.forEach( function( gridRow, index ){
- if ( gridRow.uid === removeGridRow.uid ){
- rowArray.splice( index, 1);
- }
- });
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name isRowPresent
- * @description Checks whether a row is already present
- * in the given array
- * @param {array} rowArray the array in which to look for the row
- * @param {GridRow} gridRow the row that should be looked for
- */
- isRowPresent: function( rowArray, removeGridRow ){
- var present = false;
- rowArray.forEach( function( gridRow, index ){
- if ( gridRow.uid === removeGridRow.uid ){
- present = true;
- }
- });
- return present;
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name flushDirtyRows
- * @description Triggers a save event for all currently dirty rows, could
- * be used where user presses a save button or navigates away from the page
- * <pre>
- * gridApi.rowEdit.flushDirtyRows(grid)
- * </pre>
- * @param {object} grid the grid for which dirty rows should be flushed
- * @returns {promise} a promise that represents the aggregate of all
- * of the individual save promises - i.e. it will be resolved when all
- * the individual save promises have been resolved.
- *
- */
- flushDirtyRows: function(grid){
- var promises = [];
- grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ){
- service.saveRow( grid, gridRow )();
- promises.push( gridRow.rowEditSavePromise );
- });
-
- return $q.all( promises );
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name endEditCell
- * @description Receives an afterCellEdit event from the edit function,
- * and sets flags as appropriate. Only the rowEntity parameter
- * is processed, although other params are available. Grid
- * is automatically provided by the gridApi.
- * @param {object} rowEntity the data entity for which the cell
- * was edited
- */
- endEditCell: function( rowEntity, colDef, newValue, previousValue ){
- var grid = this.grid;
- var gridRow = grid.getRow( rowEntity );
- if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }
-
- if ( newValue !== previousValue || gridRow.isDirty ){
- if ( !grid.rowEdit.dirtyRows ){
- grid.rowEdit.dirtyRows = [];
- }
-
- if ( !gridRow.isDirty ){
- gridRow.isDirty = true;
- grid.rowEdit.dirtyRows.push( gridRow );
- }
-
- delete gridRow.isError;
-
- service.considerSetTimer( grid, gridRow );
- }
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name beginEditCell
- * @description Receives a beginCellEdit event from the edit function,
- * and cancels any rowEditSaveTimers if present, as the user is still editing
- * this row. Only the rowEntity parameter
- * is processed, although other params are available. Grid
- * is automatically provided by the gridApi.
- * @param {object} rowEntity the data entity for which the cell
- * editing has commenced
- */
- beginEditCell: function( rowEntity, colDef ){
- var grid = this.grid;
- var gridRow = grid.getRow( rowEntity );
- if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }
-
- service.cancelTimer( grid, gridRow );
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name cancelEditCell
- * @description Receives a cancelCellEdit event from the edit function,
- * and if the row was already dirty, restarts the save timer. If the row
- * was not already dirty, then it's not dirty now either and does nothing.
- *
- * Only the rowEntity parameter
- * is processed, although other params are available. Grid
- * is automatically provided by the gridApi.
- *
- * @param {object} rowEntity the data entity for which the cell
- * editing was cancelled
- */
- cancelEditCell: function( rowEntity, colDef ){
- var grid = this.grid;
- var gridRow = grid.getRow( rowEntity );
- if ( !gridRow ){ gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }
-
- service.considerSetTimer( grid, gridRow );
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name navigate
- * @description cellNav tells us that the selected cell has changed. If
- * the new row had a timer running, then stop it similar to in a beginCellEdit
- * call. If the old row is dirty and not the same as the new row, then
- * start a timer on it.
- * @param {object} newRowCol the row and column that were selected
- * @param {object} oldRowCol the row and column that was left
- *
- */
- navigate: function( newRowCol, oldRowCol ){
- var grid = this.grid;
- if ( newRowCol.row.rowEditSaveTimer ){
- service.cancelTimer( grid, newRowCol.row );
- }
-
- if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ){
- service.considerSetTimer( grid, oldRowCol.row );
- }
- },
-
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.rowEdit.api:GridOptions
- * @name rowEditWaitInterval
- * @description How long the grid should wait for another change on this row
- * before triggering a save (in milliseconds). If set to -1, then saves are
- * never triggered by timer (implying that the user will call flushDirtyRows()
- * manually)
- *
- * @example
- * Setting the wait interval to 4 seconds
- * <pre>
- * $scope.gridOptions = { rowEditWaitInterval: 4000 }
- * </pre>
- *
- */
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name considerSetTimer
- * @description Consider setting a timer on this row (if it is dirty). if there is a timer running
- * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is
- * dirty and not currently saving then set a new timer
- * @param {object} grid the grid for which we are processing
- * @param {GridRow} gridRow the row for which the timer should be adjusted
- *
- */
- considerSetTimer: function( grid, gridRow ){
- service.cancelTimer( grid, gridRow );
-
- if ( gridRow.isDirty && !gridRow.isSaving ){
- if ( grid.options.rowEditWaitInterval !== -1 ){
- var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;
- gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);
- }
- }
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name cancelTimer
- * @description cancel the $interval for any timer running on this row
- * then delete the timer itself
- * @param {object} grid the grid for which we are processing
- * @param {GridRow} gridRow the row for which the timer should be adjusted
- *
- */
- cancelTimer: function( grid, gridRow ){
- if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ){
- $interval.cancel(gridRow.rowEditSaveTimer);
- delete gridRow.rowEditSaveTimer;
- }
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name setRowsDirty
- * @description Sets each of the rows passed in dataRows
- * to be dirty. note that if you have only just inserted the
- * rows into your data you will need to wait for a $digest cycle
- * before the gridRows are present - so often you would wrap this
- * call in a $interval or $timeout
- * <pre>
- * $interval( function() {
- * gridApi.rowEdit.setRowsDirty( myDataRows);
- * }, 0, 1);
- * </pre>
- * @param {object} grid the grid for which rows should be set dirty
- * @param {array} dataRows the data entities for which the gridRows
- * should be set dirty.
- *
- */
- setRowsDirty: function( grid, myDataRows ) {
- var gridRow;
- myDataRows.forEach( function( value, index ){
- gridRow = grid.getRow( value );
- if ( gridRow ){
- if ( !grid.rowEdit.dirtyRows ){
- grid.rowEdit.dirtyRows = [];
- }
-
- if ( !gridRow.isDirty ){
- gridRow.isDirty = true;
- grid.rowEdit.dirtyRows.push( gridRow );
- }
-
- delete gridRow.isError;
-
- service.considerSetTimer( grid, gridRow );
- } else {
- gridUtil.logError( "requested row not found in rowEdit.setRowsDirty, row was: " + value );
- }
- });
- },
-
-
- /**
- * @ngdoc method
- * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
- * @name setRowsClean
- * @description Sets each of the rows passed in dataRows
- * to be clean, clearing the dirty flag and the error flag, and removing
- * the rows from the dirty and error caches.
- * @param {object} grid the grid for which rows should be set clean
- * @param {array} dataRows the data entities for which the gridRows
- * should be set clean.
- *
- */
- setRowsClean: function( grid, myDataRows ) {
- var gridRow;
-
- myDataRows.forEach( function( value, index ){
- gridRow = grid.getRow( value );
- if ( gridRow ){
- delete gridRow.isDirty;
- service.removeRow( grid.rowEdit.dirtyRows, gridRow );
- service.cancelTimer( grid, gridRow );
-
- delete gridRow.isError;
- service.removeRow( grid.rowEdit.errorRows, gridRow );
- } else {
- gridUtil.logError( "requested row not found in rowEdit.setRowsClean, row was: " + value );
- }
- });
- }
-
- };
-
- return service;
-
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.rowEdit.directive:uiGridEdit
- * @element div
- * @restrict A
- *
- * @description Adds row editing features to the ui-grid-edit directive.
- *
- */
- module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',
- function (gridUtil, uiGridRowEditService, uiGridEditConstants) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
- }
- };
- }
- };
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.rowEdit.directive:uiGridViewport
- * @element div
- *
- * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
- * for the grid row to allow coloring of saving and error rows
- */
- module.directive('uiGridViewport',
- ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
- function ($compile, uiGridConstants, gridUtil, $parse) {
- return {
- priority: -200, // run after default directive
- scope: false,
- compile: function ($elm, $attrs) {
- var rowRepeatDiv = angular.element($elm.children().children()[0]);
-
- var existingNgClass = rowRepeatDiv.attr("ng-class");
- var newNgClass = '';
- if ( existingNgClass ) {
- newNgClass = existingNgClass.slice(0, -1) + ", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
- } else {
- newNgClass = "{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
- }
- rowRepeatDiv.attr("ng-class", newNgClass);
-
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- }
- };
- }
- };
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.saveState
- * @description
- *
- * # ui.grid.saveState
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * This module provides the ability to save the grid state, and restore
- * it when the user returns to the page.
- *
- * No UI is provided, the caller should provide their own UI/buttons
- * as appropriate. Usually the navigate events would be used to save
- * the grid state and restore it.
- *
- * <br/>
- * <br/>
- *
- * <div doc-module-components="ui.grid.save-state"></div>
- */
-
- var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);
-
- /**
- * @ngdoc object
- * @name ui.grid.saveState.constant:uiGridSaveStateConstants
- *
- * @description constants available in save state module
- */
-
- module.constant('uiGridSaveStateConstants', {
- featureName: 'saveState'
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.saveState.service:uiGridSaveStateService
- *
- * @description Services for saveState feature
- */
- module.service('uiGridSaveStateService', ['$q', 'uiGridSaveStateConstants', 'gridUtil', '$compile', '$interval', 'uiGridConstants',
- function ($q, uiGridSaveStateConstants, gridUtil, $compile, $interval, uiGridConstants ) {
-
- var service = {
-
- initializeGrid: function (grid) {
-
- //add feature namespace and any properties to grid for needed state
- grid.saveState = {};
- this.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.saveState.api:PublicApi
- *
- * @description Public Api for saveState feature
- */
- var publicApi = {
- events: {
- saveState: {
- }
- },
- methods: {
- saveState: {
- /**
- * @ngdoc function
- * @name save
- * @methodOf ui.grid.saveState.api:PublicApi
- * @description Packages the current state of the grid into
- * an object, and provides it to the user for saving
- * @returns {object} the state as a javascript object that can be saved
- */
- save: function () {
- return service.save(grid);
- },
- /**
- * @ngdoc function
- * @name restore
- * @methodOf ui.grid.saveState.api:PublicApi
- * @description Restores the provided state into the grid
- * @param {scope} $scope a scope that we can broadcast on
- * @param {object} state the state that should be restored into the grid
- */
- restore: function ( $scope, state) {
- service.restore(grid, $scope, state);
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.saveState.api:GridOptions
- *
- * @description GridOptions for saveState feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
- /**
- * @ngdoc object
- * @name saveWidths
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the current column widths. Note that unless
- * you've provided the user with some way to resize their columns (say
- * the resize columns feature), then this makes little sense.
- * <br/>Defaults to true
- */
- gridOptions.saveWidths = gridOptions.saveWidths !== false;
- /**
- * @ngdoc object
- * @name saveOrder
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Restore the current column order. Note that unless
- * you've provided the user with some way to reorder their columns (for
- * example the move columns feature), this makes little sense.
- * <br/>Defaults to true
- */
- gridOptions.saveOrder = gridOptions.saveOrder !== false;
- /**
- * @ngdoc object
- * @name saveScroll
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the current scroll position. Note that this
- * is saved as the percentage of the grid scrolled - so if your
- * user returns to a grid with a significantly different number of
- * rows (perhaps some data has been deleted) then the scroll won't
- * actually show the same rows as before. If you want to scroll to
- * a specific row then you should instead use the saveFocus option, which
- * is the default.
- *
- * Note that this element will only be saved if the cellNav feature is
- * enabled
- * <br/>Defaults to false
- */
- gridOptions.saveScroll = gridOptions.saveScroll === true;
- /**
- * @ngdoc object
- * @name saveFocus
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the current focused cell. On returning
- * to this focused cell we'll also scroll. This option is
- * preferred to the saveScroll option, so is set to true by
- * default. If saveScroll is set to true then this option will
- * be disabled.
- *
- * By default this option saves the current row number and column
- * number, and returns to that row and column. However, if you define
- * a saveRowIdentity function, then it will return you to the currently
- * selected column within that row (in a business sense - so if some
- * rows have been deleted, it will still find the same data, presuming it
- * still exists in the list. If it isn't in the list then it will instead
- * return to the same row number - i.e. scroll percentage)
- *
- * Note that this option will do nothing if the cellNav
- * feature is not enabled.
- *
- * <br/>Defaults to true (unless saveScroll is true)
- */
- gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;
- /**
- * @ngdoc object
- * @name saveRowIdentity
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description A function that can be called, passing in a rowEntity,
- * and that will return a unique id for that row. This might simply
- * return the `id` field from that row (if you have one), or it might
- * concatenate some fields within the row to make a unique value.
- *
- * This value will be used to find the same row again and set the focus
- * to it, if it exists when we return.
- *
- * <br/>Defaults to undefined
- */
- /**
- * @ngdoc object
- * @name saveVisible
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save whether or not columns are visible.
- *
- * <br/>Defaults to true
- */
- gridOptions.saveVisible = gridOptions.saveVisible !== false;
- /**
- * @ngdoc object
- * @name saveSort
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the current sort state for each column
- *
- * <br/>Defaults to true
- */
- gridOptions.saveSort = gridOptions.saveSort !== false;
- /**
- * @ngdoc object
- * @name saveFilter
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the current filter state for each column
- *
- * <br/>Defaults to true
- */
- gridOptions.saveFilter = gridOptions.saveFilter !== false;
- /**
- * @ngdoc object
- * @name saveSelection
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the currently selected rows. If the `saveRowIdentity` callback
- * is defined, then it will save the id of the row and select that. If not, then
- * it will attempt to select the rows by row number, which will give the wrong results
- * if the data set has changed in the mean-time.
- *
- * Note that this option only does anything
- * if the selection feature is enabled.
- *
- * <br/>Defaults to true
- */
- gridOptions.saveSelection = gridOptions.saveSelection !== false;
- /**
- * @ngdoc object
- * @name saveGrouping
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the grouping configuration. If set to true and the
- * grouping feature is not enabled then does nothing.
- *
- * <br/>Defaults to true
- */
- gridOptions.saveGrouping = gridOptions.saveGrouping !== false;
- /**
- * @ngdoc object
- * @name saveGroupingExpandedStates
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the grouping row expanded states. If set to true and the
- * grouping feature is not enabled then does nothing.
- *
- * This can be quite a bit of data, in many cases you wouldn't want to save this
- * information.
- *
- * <br/>Defaults to false
- */
- gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;
- /**
- * @ngdoc object
- * @name savePinning
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save pinning state for columns.
- *
- * <br/>Defaults to true
- */
- gridOptions.savePinning = gridOptions.savePinning !== false;
- /**
- * @ngdoc object
- * @name saveTreeView
- * @propertyOf ui.grid.saveState.api:GridOptions
- * @description Save the treeView configuration. If set to true and the
- * treeView feature is not enabled then does nothing.
- *
- * <br/>Defaults to true
- */
- gridOptions.saveTreeView = gridOptions.saveTreeView !== false;
- },
-
-
-
- /**
- * @ngdoc function
- * @name save
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the current grid state into an object, and
- * passes that object back to the caller
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {object} the state ready to be saved
- */
- save: function (grid) {
- var savedState = {};
-
- savedState.columns = service.saveColumns( grid );
- savedState.scrollFocus = service.saveScrollFocus( grid );
- savedState.selection = service.saveSelection( grid );
- savedState.grouping = service.saveGrouping( grid );
- savedState.treeView = service.saveTreeView( grid );
-
- return savedState;
- },
-
-
- /**
- * @ngdoc function
- * @name restore
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Applies the provided state to the grid
- *
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {scope} $scope a scope that we can broadcast on
- * @param {object} state the state we'd like to restore
- */
- restore: function( grid, $scope, state ){
- if ( state.columns ) {
- service.restoreColumns( grid, state.columns );
- }
-
- if ( state.scrollFocus ){
- service.restoreScrollFocus( grid, $scope, state.scrollFocus );
- }
-
- if ( state.selection ){
- service.restoreSelection( grid, state.selection );
- }
-
- if ( state.grouping ){
- service.restoreGrouping( grid, state.grouping );
- }
-
- if ( state.treeView ){
- service.restoreTreeView( grid, state.treeView );
- }
-
- grid.refresh();
- },
-
-
- /**
- * @ngdoc function
- * @name saveColumns
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the column setup, including sort, filters, ordering,
- * pinning and column widths.
- *
- * Works through the current columns, storing them in order. Stores the
- * column name, then the visible flag, width, sort and filters for each column.
- *
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {array} the columns state ready to be saved
- */
- saveColumns: function( grid ) {
- var columns = [];
- grid.getOnlyDataColumns().forEach( function( column ) {
- var savedColumn = {};
- savedColumn.name = column.name;
-
- if ( grid.options.saveVisible ){
- savedColumn.visible = column.visible;
- }
-
- if ( grid.options.saveWidths ){
- savedColumn.width = column.width;
- }
-
- // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state
- if ( grid.options.saveSort ){
- savedColumn.sort = angular.copy( column.sort );
- }
-
- if ( grid.options.saveFilter ){
- savedColumn.filters = [];
- column.filters.forEach( function( filter ){
- var copiedFilter = {};
- angular.forEach( filter, function( value, key) {
- if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder'){
- copiedFilter[key] = value;
- }
- });
- savedColumn.filters.push(copiedFilter);
- });
- }
-
- if ( !!grid.api.pinning && grid.options.savePinning ){
- savedColumn.pinned = column.renderContainer ? column.renderContainer : '';
- }
-
- columns.push( savedColumn );
- });
-
- return columns;
- },
-
-
- /**
- * @ngdoc function
- * @name saveScrollFocus
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the currently scroll or focus.
- *
- * If cellNav isn't present then does nothing - we can't return
- * to the scroll position without cellNav anyway.
- *
- * If the cellNav module is present, and saveFocus is true, then
- * it saves the currently focused cell. If rowIdentity is present
- * then saves using rowIdentity, otherwise saves visibleRowNum.
- *
- * If the cellNav module is not present, and saveScroll is true, then
- * it approximates the current scroll row and column, and saves that.
- *
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {object} the selection state ready to be saved
- */
- saveScrollFocus: function( grid ){
- if ( !grid.api.cellNav ){
- return {};
- }
-
- var scrollFocus = {};
- if ( grid.options.saveFocus ){
- scrollFocus.focus = true;
- var rowCol = grid.api.cellNav.getFocusedCell();
- if ( rowCol !== null ) {
- if ( rowCol.col !== null ){
- scrollFocus.colName = rowCol.col.colDef.name;
- }
- if ( rowCol.row !== null ){
- scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );
- }
- }
- }
-
- if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {
- scrollFocus.focus = false;
- if ( grid.renderContainers.body.prevRowScrollIndex ){
- scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);
- }
-
- if ( grid.renderContainers.body.prevColScrollIndex ){
- scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;
- }
- }
-
- return scrollFocus;
- },
-
-
- /**
- * @ngdoc function
- * @name saveSelection
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the currently selected rows, if the selection feature is enabled
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {array} the selection state ready to be saved
- */
- saveSelection: function( grid ){
- if ( !grid.api.selection || !grid.options.saveSelection ){
- return [];
- }
-
- var selection = grid.api.selection.getSelectedGridRows().map( function( gridRow ) {
- return service.getRowVal( grid, gridRow );
- });
-
- return selection;
- },
-
-
- /**
- * @ngdoc function
- * @name saveGrouping
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the grouping state, if the grouping feature is enabled
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {object} the grouping state ready to be saved
- */
- saveGrouping: function( grid ){
- if ( !grid.api.grouping || !grid.options.saveGrouping ){
- return {};
- }
-
- return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );
- },
-
-
- /**
- * @ngdoc function
- * @name saveTreeView
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Saves the tree view state, if the tree feature is enabled
- * @param {Grid} grid the grid whose state we'd like to save
- * @returns {object} the tree view state ready to be saved
- */
- saveTreeView: function( grid ){
- if ( !grid.api.treeView || !grid.options.saveTreeView ){
- return {};
- }
-
- return grid.api.treeView.getTreeView();
- },
-
-
- /**
- * @ngdoc function
- * @name getRowVal
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Helper function that gets either the rowNum or
- * the saveRowIdentity, given a gridRow
- * @param {Grid} grid the grid the row is in
- * @param {GridRow} gridRow the row we want the rowNum for
- * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }
- *
- */
- getRowVal: function( grid, gridRow ){
- if ( !gridRow ) {
- return null;
- }
-
- var rowVal = {};
- if ( grid.options.saveRowIdentity ){
- rowVal.identity = true;
- rowVal.row = grid.options.saveRowIdentity( gridRow.entity );
- } else {
- rowVal.identity = false;
- rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );
- }
- return rowVal;
- },
-
-
- /**
- * @ngdoc function
- * @name restoreColumns
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Restores the columns, including order, visible, width,
- * pinning, sort and filters.
- *
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {object} columnsState the list of columns we had before, with their state
- */
- restoreColumns: function( grid, columnsState ){
- var isSortChanged = false;
-
- columnsState.forEach( function( columnState, index ) {
- var currentCol = grid.getColumn( columnState.name );
-
- if ( currentCol && !grid.isRowHeaderColumn(currentCol) ){
- if ( grid.options.saveVisible &&
- ( currentCol.visible !== columnState.visible ||
- currentCol.colDef.visible !== columnState.visible ) ){
- currentCol.visible = columnState.visible;
- currentCol.colDef.visible = columnState.visible;
- grid.api.core.raise.columnVisibilityChanged(currentCol);
- }
-
- if ( grid.options.saveWidths ){
- currentCol.width = columnState.width;
- }
-
- if ( grid.options.saveSort &&
- !angular.equals(currentCol.sort, columnState.sort) &&
- !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ){
- currentCol.sort = angular.copy( columnState.sort );
- isSortChanged = true;
- }
-
- if ( grid.options.saveFilter &&
- !angular.equals(currentCol.filters, columnState.filters ) ){
- columnState.filters.forEach( function( filter, index ){
- angular.extend( currentCol.filters[index], filter );
- if ( typeof(filter.term) === 'undefined' || filter.term === null ){
- delete currentCol.filters[index].term;
- }
- });
- grid.api.core.raise.filterChanged();
- }
-
- if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ){
- grid.api.pinning.pinColumn(currentCol, columnState.pinned);
- }
-
- var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );
- if (currentIndex !== -1) {
- if (grid.options.saveOrder && currentIndex !== index) {
- var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];
- grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);
- }
- }
- }
- });
-
- if ( isSortChanged ) {
- grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );
- }
- },
-
-
- /**
- * @ngdoc function
- * @name restoreScrollFocus
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Scrolls to the position that was saved. If focus is true, then
- * sets focus to the specified row/col. If focus is false, then scrolls to the
- * specified row/col.
- *
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {scope} $scope a scope that we can broadcast on
- * @param {object} scrollFocusState the scroll/focus state ready to be restored
- */
- restoreScrollFocus: function( grid, $scope, scrollFocusState ){
- if ( !grid.api.cellNav ){
- return;
- }
-
- var colDef, row;
- if ( scrollFocusState.colName ){
- var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });
- if ( colDefs.length > 0 ){
- colDef = colDefs[0];
- }
- }
-
- if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ){
- if ( scrollFocusState.rowVal.identity ){
- row = service.findRowByIdentity( grid, scrollFocusState.rowVal );
- } else {
- row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];
- }
- }
-
- var entity = row && row.entity ? row.entity : null ;
-
- if ( colDef || entity ) {
- if (scrollFocusState.focus ){
- grid.api.cellNav.scrollToFocus( entity, colDef );
- } else {
- grid.scrollTo( entity, colDef );
- }
- }
- },
-
-
- /**
- * @ngdoc function
- * @name restoreSelection
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Selects the rows that are provided in the selection
- * state. If you are using `saveRowIdentity` and more than one row matches the identity
- * function then only the first is selected.
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {object} selectionState the selection state ready to be restored
- */
- restoreSelection: function( grid, selectionState ){
- if ( !grid.api.selection ){
- return;
- }
-
- grid.api.selection.clearSelectedRows();
-
- selectionState.forEach( function( rowVal ) {
- if ( rowVal.identity ){
- var foundRow = service.findRowByIdentity( grid, rowVal );
-
- if ( foundRow ){
- grid.api.selection.selectRow( foundRow.entity );
- }
-
- } else {
- grid.api.selection.selectRowByVisibleIndex( rowVal.row );
- }
- });
- },
-
-
- /**
- * @ngdoc function
- * @name restoreGrouping
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Restores the grouping configuration, if the grouping feature
- * is enabled.
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {object} groupingState the grouping state ready to be restored
- */
- restoreGrouping: function( grid, groupingState ){
- if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ){
- return;
- }
-
- grid.api.grouping.setGrouping( groupingState );
- },
-
- /**
- * @ngdoc function
- * @name restoreTreeView
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Restores the tree view configuration, if the tree view feature
- * is enabled.
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {object} treeViewState the tree view state ready to be restored
- */
- restoreTreeView: function( grid, treeViewState ){
- if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ){
- return;
- }
-
- grid.api.treeView.setTreeView( treeViewState );
- },
-
- /**
- * @ngdoc function
- * @name findRowByIdentity
- * @methodOf ui.grid.saveState.service:uiGridSaveStateService
- * @description Finds a row given it's identity value, returns the first found row
- * if any are found, otherwise returns null if no rows are found.
- * @param {Grid} grid the grid whose state we'd like to restore
- * @param {object} rowVal the row we'd like to find
- * @returns {gridRow} the found row, or null if none found
- */
- findRowByIdentity: function( grid, rowVal ){
- if ( !grid.options.saveRowIdentity ){
- return null;
- }
-
- var filteredRows = grid.rows.filter( function( gridRow ) {
- if ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row ){
- return true;
- } else {
- return false;
- }
- });
-
- if ( filteredRows.length > 0 ){
- return filteredRows[0];
- } else {
- return null;
- }
- }
- };
-
- return service;
-
- }
- ]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.saveState.directive:uiGridSaveState
- * @element div
- * @restrict A
- *
- * @description Adds saveState features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.gridOptions = {
- columnDefs: [
- {name: 'name'},
- {name: 'title', enableCellEdit: true}
- ],
- data: $scope.data
- };
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="gridOptions" ui-grid-save-state></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',
- function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);
- }
- };
- }
- ]);
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.selection
- * @description
- *
- * # ui.grid.selection
- * This module provides row selection
- *
- * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
- *
- * <div doc-module-components="ui.grid.selection"></div>
- */
-
- var module = angular.module('ui.grid.selection', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.selection.constant:uiGridSelectionConstants
- *
- * @description constants available in selection module
- */
- module.constant('uiGridSelectionConstants', {
- featureName: "selection",
- selectionRowHeaderColName: 'selectionRowHeaderCol'
- });
-
- //add methods to GridRow
- angular.module('ui.grid').config(['$provide', function($provide) {
- $provide.decorator('GridRow', ['$delegate', function($delegate) {
-
- /**
- * @ngdoc object
- * @name ui.grid.selection.api:GridRow
- *
- * @description GridRow prototype functions added for selection
- */
-
- /**
- * @ngdoc object
- * @name enableSelection
- * @propertyOf ui.grid.selection.api:GridRow
- * @description Enable row selection for this row, only settable by internal code.
- *
- * The grouping feature, for example, might set group header rows to not be selectable.
- * <br/>Defaults to true
- */
-
- /**
- * @ngdoc object
- * @name isSelected
- * @propertyOf ui.grid.selection.api:GridRow
- * @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
- * <br/>Defaults to false
- */
-
-
- /**
- * @ngdoc function
- * @name setSelected
- * @methodOf ui.grid.selection.api:GridRow
- * @description Sets the isSelected property and updates the selectedCount
- * Changes to isSelected state should only be made via this function
- * @param {bool} selected value to set
- */
- $delegate.prototype.setSelected = function(selected) {
- this.isSelected = selected;
- if (selected) {
- this.grid.selection.selectedCount++;
- }
- else {
- this.grid.selection.selectedCount--;
- }
- };
-
- return $delegate;
- }]);
- }]);
-
- /**
- * @ngdoc service
- * @name ui.grid.selection.service:uiGridSelectionService
- *
- * @description Services for selection features
- */
- module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',
- function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {
-
- var service = {
-
- initializeGrid: function (grid) {
-
- //add feature namespace and any properties to grid for needed
- /**
- * @ngdoc object
- * @name ui.grid.selection.grid:selection
- *
- * @description Grid properties and functions added for selection
- */
- grid.selection = {};
- grid.selection.lastSelectedRow = null;
- grid.selection.selectAll = false;
-
-
- /**
- * @ngdoc object
- * @name selectedCount
- * @propertyOf ui.grid.selection.grid:selection
- * @description Current count of selected rows
- * @example
- * var count = grid.selection.selectedCount
- */
- grid.selection.selectedCount = 0;
-
- service.defaultGridOptions(grid.options);
-
- /**
- * @ngdoc object
- * @name ui.grid.selection.api:PublicApi
- *
- * @description Public Api for selection feature
- */
- var publicApi = {
- events: {
- selection: {
- /**
- * @ngdoc event
- * @name rowSelectionChanged
- * @eventOf ui.grid.selection.api:PublicApi
- * @description is raised after the row.isSelected state is changed
- * @param {GridRow} row the row that was selected/deselected
- * @param {Event} event object if raised from an event
- */
- rowSelectionChanged: function (scope, row, evt) {
- },
- /**
- * @ngdoc event
- * @name rowSelectionChangedBatch
- * @eventOf ui.grid.selection.api:PublicApi
- * @description is raised after the row.isSelected state is changed
- * in bulk, if the `enableSelectionBatchEvent` option is set to true
- * (which it is by default). This allows more efficient processing
- * of bulk events.
- * @param {array} rows the rows that were selected/deselected
- * @param {Event} event object if raised from an event
- */
- rowSelectionChangedBatch: function (scope, rows, evt) {
- }
- }
- },
- methods: {
- selection: {
- /**
- * @ngdoc function
- * @name toggleRowSelection
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Toggles data row as selected or unselected
- * @param {object} rowEntity gridOptions.data[] array instance
- * @param {Event} event object if raised from an event
- */
- toggleRowSelection: function (rowEntity, evt) {
- var row = grid.getRow(rowEntity);
- if (row !== null) {
- service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
- }
- },
- /**
- * @ngdoc function
- * @name selectRow
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Select the data row
- * @param {object} rowEntity gridOptions.data[] array instance
- * @param {Event} event object if raised from an event
- */
- selectRow: function (rowEntity, evt) {
- var row = grid.getRow(rowEntity);
- if (row !== null && !row.isSelected) {
- service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
- }
- },
- /**
- * @ngdoc function
- * @name selectRowByVisibleIndex
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Select the specified row by visible index (i.e. if you
- * specify row 0 you'll get the first visible row selected). In this context
- * visible means of those rows that are theoretically visible (i.e. not filtered),
- * rather than rows currently rendered on the screen.
- * @param {number} index index within the rowsVisible array
- * @param {Event} event object if raised from an event
- */
- selectRowByVisibleIndex: function ( rowNum, evt ) {
- var row = grid.renderContainers.body.visibleRowCache[rowNum];
- if (row !== null && typeof(row) !== 'undefined' && !row.isSelected) {
- service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
- }
- },
- /**
- * @ngdoc function
- * @name unSelectRow
- * @methodOf ui.grid.selection.api:PublicApi
- * @description UnSelect the data row
- * @param {object} rowEntity gridOptions.data[] array instance
- * @param {Event} event object if raised from an event
- */
- unSelectRow: function (rowEntity, evt) {
- var row = grid.getRow(rowEntity);
- if (row !== null && row.isSelected) {
- service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
- }
- },
- /**
- * @ngdoc function
- * @name selectAllRows
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Selects all rows. Does nothing if multiSelect = false
- * @param {Event} event object if raised from an event
- */
- selectAllRows: function (evt) {
- if (grid.options.multiSelect === false) {
- return;
- }
-
- var changedRows = [];
- grid.rows.forEach(function (row) {
- if ( !row.isSelected && row.enableSelection !== false ){
- row.setSelected(true);
- service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
- }
- });
- service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
- grid.selection.selectAll = true;
- },
- /**
- * @ngdoc function
- * @name selectAllVisibleRows
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Selects all visible rows. Does nothing if multiSelect = false
- * @param {Event} event object if raised from an event
- */
- selectAllVisibleRows: function (evt) {
- if (grid.options.multiSelect === false) {
- return;
- }
-
- var changedRows = [];
- grid.rows.forEach(function (row) {
- if (row.visible) {
- if (!row.isSelected && row.enableSelection !== false){
- row.setSelected(true);
- service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
- }
- } else {
- if (row.isSelected){
- row.setSelected(false);
- service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
- }
- }
- });
- service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
- grid.selection.selectAll = true;
- },
- /**
- * @ngdoc function
- * @name clearSelectedRows
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Unselects all rows
- * @param {Event} event object if raised from an event
- */
- clearSelectedRows: function (evt) {
- service.clearSelectedRows(grid, evt);
- },
- /**
- * @ngdoc function
- * @name getSelectedRows
- * @methodOf ui.grid.selection.api:PublicApi
- * @description returns all selectedRow's entity references
- */
- getSelectedRows: function () {
- return service.getSelectedRows(grid).map(function (gridRow) {
- return gridRow.entity;
- });
- },
- /**
- * @ngdoc function
- * @name getSelectedGridRows
- * @methodOf ui.grid.selection.api:PublicApi
- * @description returns all selectedRow's as gridRows
- */
- getSelectedGridRows: function () {
- return service.getSelectedRows(grid);
- },
- /**
- * @ngdoc function
- * @name setMultiSelect
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Sets the current gridOption.multiSelect to true or false
- * @param {bool} multiSelect true to allow multiple rows
- */
- setMultiSelect: function (multiSelect) {
- grid.options.multiSelect = multiSelect;
- },
- /**
- * @ngdoc function
- * @name setModifierKeysToMultiSelect
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false
- * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used
- */
- setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {
- grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;
- },
- /**
- * @ngdoc function
- * @name getSelectAllState
- * @methodOf ui.grid.selection.api:PublicApi
- * @description Returns whether or not the selectAll checkbox is currently ticked. The
- * grid doesn't automatically select rows when you add extra data - so when you add data
- * you need to explicitly check whether the selectAll is set, and then call setVisible rows
- * if it is
- */
- getSelectAllState: function () {
- return grid.selection.selectAll;
- }
-
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.selection.api:GridOptions
- *
- * @description GridOptions for selection feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name enableRowSelection
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable row selection for entire grid.
- * <br/>Defaults to true
- */
- gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;
- /**
- * @ngdoc object
- * @name multiSelect
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable multiple row selection for entire grid
- * <br/>Defaults to true
- */
- gridOptions.multiSelect = gridOptions.multiSelect !== false;
- /**
- * @ngdoc object
- * @name noUnselect
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Prevent a row from being unselected. Works in conjunction
- * with `multiselect = false` and `gridApi.selection.selectRow()` to allow
- * you to create a single selection only grid - a row is always selected, you
- * can only select different rows, you can't unselect the row.
- * <br/>Defaults to false
- */
- gridOptions.noUnselect = gridOptions.noUnselect === true;
- /**
- * @ngdoc object
- * @name modifierKeysToMultiSelect
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.
- * <br/>Defaults to false
- */
- gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;
- /**
- * @ngdoc object
- * @name enableRowHeaderSelection
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable a row header to be used for selection
- * <br/>Defaults to true
- */
- gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;
- /**
- * @ngdoc object
- * @name enableFullRowSelection
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable selection by clicking anywhere on the row. Defaults to
- * false if `enableRowHeaderSelection` is true, otherwise defaults to false.
- */
- if ( typeof(gridOptions.enableFullRowSelection) === 'undefined' ){
- gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
- }
- /**
- * @ngdoc object
- * @name enableSelectAll
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Enable the select all checkbox at the top of the selectionRowHeader
- * <br/>Defaults to true
- */
- gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;
- /**
- * @ngdoc object
- * @name enableSelectionBatchEvent
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description If selected rows are changed in bulk, either via the API or
- * via the selectAll checkbox, then a separate event is fired. Setting this
- * option to false will cause the rowSelectionChanged event to be called multiple times
- * instead
- * <br/>Defaults to true
- */
- gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;
- /**
- * @ngdoc object
- * @name selectionRowHeaderWidth
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description can be used to set a custom width for the row header selection column
- * <br/>Defaults to 30px
- */
- gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
-
- /**
- * @ngdoc object
- * @name enableFooterTotalSelected
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Shows the total number of selected items in footer if true.
- * <br/>Defaults to true.
- * <br/>GridOptions.showGridFooter must also be set to true.
- */
- gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
-
- /**
- * @ngdoc object
- * @name isRowSelectable
- * @propertyOf ui.grid.selection.api:GridOptions
- * @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
- */
-
- gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
- },
-
- /**
- * @ngdoc function
- * @name toggleRowSelection
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description Toggles row as selected or unselected
- * @param {Grid} grid grid object
- * @param {GridRow} row row to select or deselect
- * @param {Event} event object if resulting from event
- * @param {bool} multiSelect if false, only one row at time can be selected
- * @param {bool} noUnselect if true then rows cannot be unselected
- */
- toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
- var selected = row.isSelected;
-
- if ( row.enableSelection === false && !selected ){
- return;
- }
-
- var selectedRows;
- if (!multiSelect && !selected) {
- service.clearSelectedRows(grid, evt);
- } else if (!multiSelect && selected) {
- selectedRows = service.getSelectedRows(grid);
- if (selectedRows.length > 1) {
- selected = false; // Enable reselect of the row
- service.clearSelectedRows(grid, evt);
- }
- }
-
- if (selected && noUnselect){
- // don't deselect the row
- } else {
- row.setSelected(!selected);
- if (row.isSelected === true) {
- grid.selection.lastSelectedRow = row;
- }
-
- selectedRows = service.getSelectedRows(grid);
- grid.selection.selectAll = grid.rows.length === selectedRows.length;
-
- grid.api.selection.raise.rowSelectionChanged(row, evt);
- }
- },
- /**
- * @ngdoc function
- * @name shiftSelect
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description selects a group of rows from the last selected row using the shift key
- * @param {Grid} grid grid object
- * @param {GridRow} clicked row
- * @param {Event} event object if raised from an event
- * @param {bool} multiSelect if false, does nothing this is for multiSelect only
- */
- shiftSelect: function (grid, row, evt, multiSelect) {
- if (!multiSelect) {
- return;
- }
- var selectedRows = service.getSelectedRows(grid);
- var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;
- var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);
- //reverse select direction
- if (fromRow > toRow) {
- var tmp = fromRow;
- fromRow = toRow;
- toRow = tmp;
- }
-
- var changedRows = [];
- for (var i = fromRow; i <= toRow; i++) {
- var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
- if (rowToSelect) {
- if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){
- rowToSelect.setSelected(true);
- grid.selection.lastSelectedRow = rowToSelect;
- service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );
- }
- }
- }
- service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
- },
- /**
- * @ngdoc function
- * @name getSelectedRows
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description Returns all the selected rows
- * @param {Grid} grid grid object
- */
- getSelectedRows: function (grid) {
- return grid.rows.filter(function (row) {
- return row.isSelected;
- });
- },
-
- /**
- * @ngdoc function
- * @name clearSelectedRows
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description Clears all selected rows
- * @param {Grid} grid grid object
- * @param {Event} event object if raised from an event
- */
- clearSelectedRows: function (grid, evt) {
- var changedRows = [];
- service.getSelectedRows(grid).forEach(function (row) {
- if ( row.isSelected ){
- row.setSelected(false);
- service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
- }
- });
- service.decideRaiseSelectionBatchEvent( grid, changedRows, evt );
- grid.selection.selectAll = false;
- grid.selection.selectedCount = 0;
- },
-
- /**
- * @ngdoc function
- * @name decideRaiseSelectionEvent
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description Decides whether to raise a single event or a batch event
- * @param {Grid} grid grid object
- * @param {GridRow} row row that has changed
- * @param {array} changedRows an array to which we can append the changed
- * @param {Event} event object if raised from an event
- * row if we're doing batch events
- */
- decideRaiseSelectionEvent: function( grid, row, changedRows, evt ){
- if ( !grid.options.enableSelectionBatchEvent ){
- grid.api.selection.raise.rowSelectionChanged(row, evt);
- } else {
- changedRows.push(row);
- }
- },
-
- /**
- * @ngdoc function
- * @name raiseSelectionEvent
- * @methodOf ui.grid.selection.service:uiGridSelectionService
- * @description Decides whether we need to raise a batch event, and
- * raises it if we do.
- * @param {Grid} grid grid object
- * @param {array} changedRows an array of changed rows, only populated
- * @param {Event} event object if raised from an event
- * if we're doing batch events
- */
- decideRaiseSelectionBatchEvent: function( grid, changedRows, evt ){
- if ( changedRows.length > 0 ){
- grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);
- }
- }
- };
-
- return service;
-
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.selection.directive:uiGridSelection
- * @element div
- * @restrict A
- *
- * @description Adds selection features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.columnDefs = [
- {name: 'name', enableCellEdit: true},
- {name: 'title', enableCellEdit: true}
- ];
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-selection></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', '$templateCache', 'uiGridConstants',
- function (uiGridSelectionConstants, uiGridSelectionService, $templateCache, uiGridConstants) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- uiGridSelectionService.initializeGrid(uiGridCtrl.grid);
- if (uiGridCtrl.grid.options.enableRowHeaderSelection) {
- var selectionRowHeaderDef = {
- name: uiGridSelectionConstants.selectionRowHeaderColName,
- displayName: '',
- width: uiGridCtrl.grid.options.selectionRowHeaderWidth,
- minWidth: 10,
- cellTemplate: 'ui-grid/selectionRowHeader',
- headerCellTemplate: 'ui-grid/selectionHeaderCell',
- enableColumnResizing: false,
- enableColumnMenu: false,
- exporterSuppressExport: true,
- allowCellFocus: true
- };
-
- uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef);
- }
-
- var processorSet = false;
-
- var processSelectableRows = function( rows ){
- rows.forEach(function(row){
- row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);
- });
- return rows;
- };
-
- var updateOptions = function(){
- if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {
- uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);
- processorSet = true;
- }
- };
-
- updateOptions();
-
- var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback( updateOptions, [uiGridConstants.dataChange.OPTIONS] );
-
- $scope.$on( '$destroy', dataChangeDereg);
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- }
- };
- }
- };
- }]);
-
- module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',
- function ($templateCache, uiGridSelectionService, gridUtil) {
- return {
- replace: true,
- restrict: 'E',
- template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),
- scope: true,
- require: '^uiGrid',
- link: function($scope, $elm, $attrs, uiGridCtrl) {
- var self = uiGridCtrl.grid;
- $scope.selectButtonClick = selectButtonClick;
-
- // On IE, prevent mousedowns on the select button from starting a selection.
- // If this is not done and you shift+click on another row, the browser will select a big chunk of text
- if (gridUtil.detectBrowser() === 'ie') {
- $elm.on('mousedown', selectButtonMouseDown);
- }
-
-
- function selectButtonClick(row, evt) {
- evt.stopPropagation();
-
- if (evt.shiftKey) {
- uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
- }
- else if (evt.ctrlKey || evt.metaKey) {
- uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
- }
- else {
- uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
- }
- }
-
- function selectButtonMouseDown(evt) {
- if (evt.ctrlKey || evt.shiftKey) {
- evt.target.onselectstart = function () { return false; };
- window.setTimeout(function () { evt.target.onselectstart = null; }, 0);
- }
- }
- }
- };
- }]);
-
- module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',
- function ($templateCache, uiGridSelectionService) {
- return {
- replace: true,
- restrict: 'E',
- template: $templateCache.get('ui-grid/selectionSelectAllButtons'),
- scope: false,
- link: function($scope, $elm, $attrs, uiGridCtrl) {
- var self = $scope.col.grid;
-
- $scope.headerButtonClick = function(row, evt) {
- if ( self.selection.selectAll ){
- uiGridSelectionService.clearSelectedRows(self, evt);
- if ( self.options.noUnselect ){
- self.api.selection.selectRowByVisibleIndex(0, evt);
- }
- self.selection.selectAll = false;
- } else {
- if ( self.options.multiSelect ){
- self.api.selection.selectAllVisibleRows(evt);
- self.selection.selectAll = true;
- }
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.selection.directive:uiGridViewport
- * @element div
- *
- * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
- * for the grid row
- */
- module.directive('uiGridViewport',
- ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService',
- function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService) {
- return {
- priority: -200, // run after default directive
- scope: false,
- compile: function ($elm, $attrs) {
- var rowRepeatDiv = angular.element($elm.children().children()[0]);
-
- var existingNgClass = rowRepeatDiv.attr("ng-class");
- var newNgClass = '';
- if ( existingNgClass ) {
- newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-row-selected': row.isSelected}";
- } else {
- newNgClass = "{'ui-grid-row-selected': row.isSelected}";
- }
- rowRepeatDiv.attr("ng-class", newNgClass);
-
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- }
- };
- }
- };
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.selection.directive:uiGridCell
- * @element div
- * @restrict A
- *
- * @description Stacks on top of ui.grid.uiGridCell to provide selection feature
- */
- module.directive('uiGridCell',
- ['$compile', 'uiGridConstants', 'uiGridSelectionConstants', 'gridUtil', '$parse', 'uiGridSelectionService', '$timeout',
- function ($compile, uiGridConstants, uiGridSelectionConstants, gridUtil, $parse, uiGridSelectionService, $timeout) {
- return {
- priority: -200, // run after default uiGridCell directive
- restrict: 'A',
- require: '?^uiGrid',
- scope: false,
- link: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- var touchStartTime = 0;
- var touchTimeout = 300;
-
- // Bind to keydown events in the render container
- if (uiGridCtrl.grid.api.cellNav) {
-
- uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
- if (rowCol === null ||
- rowCol.row !== $scope.row ||
- rowCol.col !== $scope.col) {
- return;
- }
-
- if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
- uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
- $scope.$apply();
- }
-
- // uiGridCellNavService.scrollToIfNecessary(uiGridCtrl.grid, rowCol.row, rowCol.col);
- });
- }
-
- //$elm.bind('keydown', function (evt) {
- // if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
- // uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
- // $scope.$apply();
- // }
- //});
-
- var selectCells = function(evt){
- // if we get a click, then stop listening for touchend
- $elm.off('touchend', touchEnd);
-
- if (evt.shiftKey) {
- uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
- }
- else if (evt.ctrlKey || evt.metaKey) {
- uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
- }
- else {
- uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
- }
- $scope.$apply();
-
- // don't re-enable the touchend handler for a little while - some devices generate both, and it will
- // take a little while to move your hand from the mouse to the screen if you have both modes of input
- $timeout(function() {
- $elm.on('touchend', touchEnd);
- }, touchTimeout);
- };
-
- var touchStart = function(evt){
- touchStartTime = (new Date()).getTime();
-
- // if we get a touch event, then stop listening for click
- $elm.off('click', selectCells);
- };
-
- var touchEnd = function(evt) {
- var touchEndTime = (new Date()).getTime();
- var touchTime = touchEndTime - touchStartTime;
-
- if (touchTime < touchTimeout ) {
- // short touch
- selectCells(evt);
- }
-
- // don't re-enable the click handler for a little while - some devices generate both, and it will
- // take a little while to move your hand from the screen to the mouse if you have both modes of input
- $timeout(function() {
- $elm.on('click', selectCells);
- }, touchTimeout);
- };
-
- function registerRowSelectionEvents() {
- if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection) {
- $elm.addClass('ui-grid-disable-selection');
- $elm.on('touchstart', touchStart);
- $elm.on('touchend', touchEnd);
- $elm.on('click', selectCells);
-
- $scope.registered = true;
- }
- }
-
- function deregisterRowSelectionEvents() {
- if ($scope.registered){
- $elm.removeClass('ui-grid-disable-selection');
-
- $elm.off('touchstart', touchStart);
- $elm.off('touchend', touchEnd);
- $elm.off('click', selectCells);
-
- $scope.registered = false;
- }
- }
-
- registerRowSelectionEvents();
- // register a dataChange callback so that we can change the selection configuration dynamically
- // if the user changes the options
- var dataChangeDereg = $scope.grid.registerDataChangeCallback( function() {
- if ( $scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
- !$scope.registered ){
- registerRowSelectionEvents();
- } else if ( ( !$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection ) &&
- $scope.registered ){
- deregisterRowSelectionEvents();
- }
- }, [uiGridConstants.dataChange.OPTIONS] );
-
- $elm.on( '$destroy', dataChangeDereg);
- }
- };
- }]);
-
- module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {
- return {
- restrict: 'EA',
- replace: true,
- priority: -1000,
- require: '^uiGrid',
- scope: true,
- compile: function ($elm, $attrs) {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- if (!uiGridCtrl.grid.options.showGridFooter) {
- return;
- }
-
-
- gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
- .then(function (contents) {
- var template = angular.element(contents);
-
- var newElm = $compile(template)($scope);
-
- angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
- });
- },
-
- post: function ($scope, $elm, $attrs, controllers) {
-
- }
- };
- }
- };
- }]);
-
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.treeBase
- * @description
- *
- * # ui.grid.treeBase
- *
- * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
- *
- * This module provides base tree handling functions that are shared by other features, notably grouping
- * and treeView. It provides a tree view of the data, with nodes in that
- * tree and leaves.
- *
- * Design information:
- * -------------------
- *
- * The raw data that is provided must come with a $$treeLevel on any non-leaf node. Grouping will create
- * these on all the group header rows, treeView will expect these to be set in the raw data by the user.
- * TreeBase will run a rowsProcessor that:
- * - builds `treeBase.tree` out of the provided rows
- * - permits a recursive sort of the tree
- * - maintains the expand/collapse state of each node
- * - provides the expand/collapse all button and the expand/collapse buttons
- * - maintains the count of children for each node
- *
- * Each row is updated with a link to the tree node that represents it. Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}
- * for information.
- *
- * TreeBase adds information to the rows
- * - treeLevel: if present and > -1 tells us the level (level 0 is the top level)
- * - treeNode: pointer to the node in the grid.treeBase.tree that refers
- * to this row, allowing us to manipulate the state
- *
- * Since the logic is baked into the rowsProcessors, it should get triggered whenever
- * row order or filtering or anything like that is changed. We recall the expanded state
- * across invocations of the rowsProcessors by the reference to the treeNode on the individual
- * rows. We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to
- * get the state, but we overwrite the other data in that treeNode.
- *
- * By default rows are collapsed, which means all data rows have their visible property
- * set to false, and only level 0 group rows are set to visible.
- *
- * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into
- * grid.treeBase.tree, then call refresh. This is because we can't easily change the visible
- * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as
- * well use it all the time.
- *
- * Tree base provides sorting (on non-grouped columns).
- *
- * Sorting works in two passes. The standard sorting is performed for any columns that are important to building
- * the tree (for example, any grouped columns). Then after the tree is built, a recursive tree sort is performed
- * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level
- * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).
- *
- * To achieve this we make use of the `ignoreSort` property on the sort configuration. The parent feature (treeView or grouping)
- * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets
- * the `ignoreSort`on any sort that it wants to run on the tree. TreeBase will clear the ignoreSort on all sorts - so it
- * will turn on any sorts that haven't run. It will then call a recursive sort on the tree.
- *
- * Tree base provides treeAggregation. It checks the treeAggregation configuration on each column, and aggregates based on
- * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,
- * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the
- * treeAggregations in the column footer. Aggregation information will be collected in the format:
- *
- * ```
- * {
- * type: 'count',
- * value: 4,
- * label: 'count: ',
- * rendered: 'count: 4'
- * }
- * ```
- *
- * A callback is provided to format the value once it is finalised (aka a valueFilter).
- *
- * <br/>
- * <br/>
- *
- * <div doc-module-components="ui.grid.treeBase"></div>
- */
-
- var module = angular.module('ui.grid.treeBase', ['ui.grid']);
-
- /**
- * @ngdoc object
- * @name ui.grid.treeBase.constant:uiGridTreeBaseConstants
- *
- * @description constants available in treeBase module.
- *
- * These constants are manually copied into grouping and treeView,
- * as I haven't found a way to simply include them, and it's not worth
- * investing time in for something that changes very infrequently.
- *
- */
- module.constant('uiGridTreeBaseConstants', {
- featureName: "treeBase",
- rowHeaderColName: 'treeBaseRowHeaderCol',
- EXPANDED: 'expanded',
- COLLAPSED: 'collapsed',
- aggregation: {
- COUNT: 'count',
- SUM: 'sum',
- MAX: 'max',
- MIN: 'min',
- AVG: 'avg'
- }
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.treeBase.service:uiGridTreeBaseService
- *
- * @description Services for treeBase feature
- */
- /**
- * @ngdoc object
- * @name ui.grid.treeBase.api:ColumnDef
- *
- * @description ColumnDef for tree feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
- */
-
- module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',
- function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {
-
- var service = {
-
- initializeGrid: function (grid, $scope) {
-
- //add feature namespace and any properties to grid for needed
- /**
- * @ngdoc object
- * @name ui.grid.treeBase.grid:treeBase
- *
- * @description Grid properties and functions added for treeBase
- */
- grid.treeBase = {};
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.treeBase.grid:treeBase
- * @name numberLevels
- *
- * @description Total number of tree levels currently used, calculated by the rowsProcessor by
- * retaining the highest tree level it sees
- */
- grid.treeBase.numberLevels = 0;
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.treeBase.grid:treeBase
- * @name expandAll
- *
- * @description Whether or not the expandAll box is selected
- */
- grid.treeBase.expandAll = false;
-
- /**
- * @ngdoc property
- * @propertyOf ui.grid.treeBase.grid:treeBase
- * @name tree
- *
- * @description Tree represented as a nested array that holds the state of each node, along with a
- * pointer to the row. The array order is material - we will display the children in the order
- * they are stored in the array
- *
- * Each node stores:
- *
- * - the state of this node
- * - an array of children of this node
- * - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)
- * - the number of children of this node
- * - aggregation information calculated from the nodes
- *
- * ```
- * [{
- * state: 'expanded',
- * row: <reference to row>,
- * parentRow: null,
- * aggregations: [{
- * type: 'count',
- * col: <gridCol>,
- * value: 2,
- * label: 'count: ',
- * rendered: 'count: 2'
- * }],
- * children: [
- * {
- * state: 'expanded',
- * row: <reference to row>,
- * parentRow: <reference to row>,
- * aggregations: [{
- * type: 'count',
- * col: '<gridCol>,
- * value: 4,
- * label: 'count: ',
- * rendered: 'count: 4'
- * }],
- * children: [
- * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
- * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
- * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
- * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }
- * ]
- * },
- * {
- * state: 'collapsed',
- * row: <reference to row>,
- * parentRow: <reference to row>,
- * aggregations: [{
- * type: 'count',
- * col: <gridCol>,
- * value: 3,
- * label: 'count: ',
- * rendered: 'count: 3'
- * }],
- * children: [
- * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
- * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
- * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }
- * ]
- * }
- * ]
- * }, {<another level 0 node maybe>} ]
- * ```
- * Missing state values are false - meaning they aren't expanded.
- *
- * This is used because the rowProcessors run every time the grid is refreshed, so
- * we'd lose the expanded state every time the grid was refreshed. This instead gives
- * us a reliable lookup that persists across rowProcessors.
- *
- * This tree is rebuilt every time we run the rowsProcessors. Since each row holds a pointer
- * to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard
- * all transient information on the tree (children, childCount) and recalculate it
- *
- */
- grid.treeBase.tree = {};
-
- service.defaultGridOptions(grid.options);
-
- grid.registerRowsProcessor(service.treeRows, 410);
-
- grid.registerColumnBuilder( service.treeBaseColumnBuilder );
-
- service.createRowHeader( grid );
-
- /**
- * @ngdoc object
- * @name ui.grid.treeBase.api:PublicApi
- *
- * @description Public Api for treeBase feature
- */
- var publicApi = {
- events: {
- treeBase: {
- /**
- * @ngdoc event
- * @eventOf ui.grid.treeBase.api:PublicApi
- * @name rowExpanded
- * @description raised whenever a row is expanded. If you are dynamically
- * rendering your tree you can listen to this event, and then retrieve
- * the children of this row and load them into the grid data.
- *
- * When the data is loaded the grid will automatically refresh to show these new rows
- *
- * <pre>
- * gridApi.treeBase.on.rowExpanded(scope,function(row){})
- * </pre>
- * @param {gridRow} row the row that was expanded. You can also
- * retrieve the grid from this row with row.grid
- */
- rowExpanded: {},
-
- /**
- * @ngdoc event
- * @eventOf ui.grid.treeBase.api:PublicApi
- * @name rowCollapsed
- * @description raised whenever a row is collapsed. Doesn't really have
- * a purpose at the moment, included for symmetry
- *
- * <pre>
- * gridApi.treeBase.on.rowCollapsed(scope,function(row){})
- * </pre>
- * @param {gridRow} row the row that was collapsed. You can also
- * retrieve the grid from this row with row.grid
- */
- rowCollapsed: {}
- }
- },
-
- methods: {
- treeBase: {
- /**
- * @ngdoc function
- * @name expandAllRows
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description Expands all tree rows
- */
- expandAllRows: function () {
- service.expandAllRows(grid);
- },
-
- /**
- * @ngdoc function
- * @name collapseAllRows
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description collapse all tree rows
- */
- collapseAllRows: function () {
- service.collapseAllRows(grid);
- },
-
- /**
- * @ngdoc function
- * @name toggleRowTreeState
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description call expand if the row is collapsed, collapse if it is expanded
- * @param {gridRow} row the row you wish to toggle
- */
- toggleRowTreeState: function (row) {
- service.toggleRowTreeState(grid, row);
- },
-
- /**
- * @ngdoc function
- * @name expandRow
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description expand the immediate children of the specified row
- * @param {gridRow} row the row you wish to expand
- */
- expandRow: function (row) {
- service.expandRow(grid, row);
- },
-
- /**
- * @ngdoc function
- * @name expandRowChildren
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description expand all children of the specified row
- * @param {gridRow} row the row you wish to expand
- */
- expandRowChildren: function (row) {
- service.expandRowChildren(grid, row);
- },
-
- /**
- * @ngdoc function
- * @name collapseRow
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description collapse the specified row. When
- * you expand the row again, all grandchildren will retain their state
- * @param {gridRow} row the row you wish to collapse
- */
- collapseRow: function ( row ) {
- service.collapseRow(grid, row);
- },
-
- /**
- * @ngdoc function
- * @name collapseRowChildren
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description collapse all children of the specified row. When
- * you expand the row again, all grandchildren will be collapsed
- * @param {gridRow} row the row you wish to collapse children for
- */
- collapseRowChildren: function ( row ) {
- service.collapseRowChildren(grid, row);
- },
-
- /**
- * @ngdoc function
- * @name getTreeState
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description Get the tree state for this grid,
- * used by the saveState feature
- * Returned treeState as an object
- * `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`
- * where expandedState is a hash of row uid and the current expanded state
- *
- * @returns {object} tree state
- *
- * TODO - this needs work - we need an identifier that persists across instantiations,
- * not uid. This really means we need a row identity defined, but that won't work for
- * grouping. Perhaps this needs to be moved up to treeView and grouping, rather than
- * being in base.
- */
- getTreeExpandedState: function () {
- return { expandedState: service.getTreeState(grid) };
- },
-
- /**
- * @ngdoc function
- * @name setTreeState
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description Set the expanded states of the tree
- * @param {object} config the config you want to apply, in the format
- * provided by getTreeState
- */
- setTreeState: function ( config ) {
- service.setTreeState( grid, config );
- },
-
- /**
- * @ngdoc function
- * @name getRowChildren
- * @methodOf ui.grid.treeBase.api:PublicApi
- * @description Get the children of the specified row
- * @param {GridRow} row the row you want the children of
- * @returns {Array} array of children of this row, the children
- * are all gridRows
- */
- getRowChildren: function ( row ){
- return row.treeNode.children.map( function( childNode ){
- return childNode.row;
- });
- }
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
- },
-
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.treeBase.api:GridOptions
- *
- * @description GridOptions for treeBase feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- */
-
- /**
- * @ngdoc object
- * @name treeRowHeaderBaseWidth
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description Base width of the tree header, provides for a single level of tree. This
- * is incremented by `treeIndent` for each extra level
- * <br/>Defaults to 30
- */
- gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;
-
- /**
- * @ngdoc object
- * @name treeIndent
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,
- * but will make the tree row header wider
- * <br/>Defaults to 10
- */
- gridOptions.treeIndent = gridOptions.treeIndent || 10;
-
- /**
- * @ngdoc object
- * @name showTreeRowHeader
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description If set to false, don't create the row header. Youll need to programatically control the expand
- * states
- * <br/>Defaults to true
- */
- gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;
-
- /**
- * @ngdoc object
- * @name showTreeExpandNoChildren
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description If set to true, show the expand/collapse button even if there are no
- * children of a node. You'd use this if you're planning to dynamically load the children
- *
- * <br/>Defaults to true, grouping overrides to false
- */
- gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;
-
- /**
- * @ngdoc object
- * @name treeRowHeaderAlwaysVisible
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description If set to true, row header even if there are no tree nodes
- *
- * <br/>Defaults to true
- */
- gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;
-
- /**
- * @ngdoc object
- * @name treeCustomAggregations
- * @propertyOf ui.grid.treeBase.api:GridOptions
- * @description Define custom aggregation functions. The properties of this object will be
- * aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.
- * If a function defined here uses the same name as one of the native aggregations, this one will take precedence.
- * The object format is:
- *
- * <pre>
- * {
- * aggregationName: {
- * label: (optional) string,
- * aggregationFn: function( aggregation, fieldValue, numValue, row ){...},
- * finalizerFn: (optional) function( aggregation ){...}
- * },
- * mean: {
- * label: 'mean',
- * aggregationFn: function( aggregation, fieldValue, numValue ){
- * aggregation.count = (aggregation.count || 1) + 1;
- * aggregation.sum = (aggregation.sum || 0) + numValue;
- * },
- * finalizerFn: function( aggregation ){
- * aggregation.value = aggregation.sum / aggregation.count
- * }
- * }
- * }
- * </pre>
- *
- * <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to
- * apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be
- * rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate
- * the label and the value.
- *
- * <br/>Defaults to {}
- */
- gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};
- },
-
-
- /**
- * @ngdoc function
- * @name treeBaseColumnBuilder
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Sets the tree defaults based on the columnDefs
- *
- * @param {object} colDef columnDef we're basing on
- * @param {GridCol} col the column we're to update
- * @param {object} gridOptions the options we should use
- * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
- */
- treeBaseColumnBuilder: function (colDef, col, gridOptions) {
-
-
- /**
- * @ngdoc object
- * @name customTreeAggregationFn
- * @propertyOf ui.grid.treeBase.api:ColumnDef
- * @description A custom function that aggregates rows into some form of
- * total. Aggregations run row-by-row, the function needs to be capable of
- * creating a running total.
- *
- * The function will be provided the aggregation item (in which you can store running
- * totals), the row value that is to be aggregated, and that same row value converted to
- * a number (most aggregations work on numbers)
- * @example
- * <pre>
- * customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ){
- * // calculates the average of the squares of the values
- * if ( typeof(aggregation.count) === 'undefined' ){
- * aggregation.count = 0;
- * }
- * aggregation.count++;
- *
- * if ( !isNaN(numValue) ){
- * if ( typeof(aggregation.total) === 'undefined' ){
- * aggregation.total = 0;
- * }
- * aggregation.total = aggregation.total + numValue * numValue;
- * }
- *
- * aggregation.value = aggregation.total / aggregation.count;
- * }
- * </pre>
- * <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.
- */
- if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ){
- col.treeAggregationFn = colDef.customTreeAggregationFn;
- }
-
- /**
- * @ngdoc object
- * @name treeAggregationType
- * @propertyOf ui.grid.treeBase.api:ColumnDef
- * @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.
- * Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the
- * name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.
- *
- * <pre>
- * treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,
- * }
- * </pre>
- *
- * If you are using aggregations you should either:
- *
- * - also use grouping, in which case the aggregations are displayed in the group header, OR
- * - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and
- * treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`
- * in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations
- *
- * <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.
- * <br/>Defaults to undefined.
- */
- if ( typeof(colDef.treeAggregationType) !== 'undefined' ){
- col.treeAggregation = { type: colDef.treeAggregationType };
- if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ){
- col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;
- col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;
- col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;
- } else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ){
- col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;
- col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;
- }
- }
-
- /**
- * @ngdoc object
- * @name treeAggregationLabel
- * @propertyOf ui.grid.treeBase.api:ColumnDef
- * @description A custom label to use for this aggregation. If provided we don't use native i18n.
- */
- if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ){
- if (typeof(col.treeAggregation) === 'undefined' ){
- col.treeAggregation = {};
- }
- col.treeAggregation.label = colDef.treeAggregationLabel;
- }
-
- /**
- * @ngdoc object
- * @name treeAggregationUpdateEntity
- * @propertyOf ui.grid.treeBase.api:ColumnDef
- * @description Store calculated aggregations into the entity, allowing them
- * to be displayed in the grid using a standard cellTemplate. This defaults to true,
- * if you are using grouping then you shouldn't set it to false, as then the aggregations won't
- * display.
- *
- * If you are using treeView in most cases you'll want to set this to true. This will result in
- * getCellValue returning the aggregation rather than whatever was stored in the cell attribute on
- * the entity. If you want to render the underlying entity value (and do something else with the aggregation)
- * then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.
- *
- * <br/>Defaults to true
- *
- * @example
- * <pre>
- * gridOptions.columns = [{
- * name: 'myCol',
- * treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },
- * treeAggregationUpdateEntity: true
- * cellTemplate: '<div>{{row.entity.myCol + " " + row.treeNode.aggregations[0].rendered}}</div>'
- * }];
- * </pre>
- */
- col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;
-
- /**
- * @ngdoc object
- * @name customTreeAggregationFinalizerFn
- * @propertyOf ui.grid.treeBase.api:ColumnDef
- * @description A custom function that populates aggregation.rendered, this is called when
- * a particular aggregation has been fully calculated, and we want to render the value.
- *
- * With the native aggregation options we just concatenate `aggregation.label` and
- * `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label
- * or the value, you can do so with this function. This function will be called after the
- * the default `finalizerFn`.
- *
- * @example
- * <pre>
- * customTreeAggregationFinalizerFn = function ( aggregation ){
- * aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';
- * }
- * </pre>
- * <br/>Defaults to undefined.
- */
- if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ){
- col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;
- }
-
- },
-
-
- /**
- * @ngdoc function
- * @name createRowHeader
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Create the rowHeader. If treeRowHeaderAlwaysVisible then
- * set it to visible, otherwise set it to invisible
- *
- * @param {Grid} grid grid object
- */
- createRowHeader: function( grid ){
- var rowHeaderColumnDef = {
- name: uiGridTreeBaseConstants.rowHeaderColName,
- displayName: '',
- width: grid.options.treeRowHeaderBaseWidth,
- minWidth: 10,
- cellTemplate: 'ui-grid/treeBaseRowHeader',
- headerCellTemplate: 'ui-grid/treeBaseHeaderCell',
- enableColumnResizing: false,
- enableColumnMenu: false,
- exporterSuppressExport: true,
- allowCellFocus: true
- };
-
- rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;
- grid.addRowHeaderColumn( rowHeaderColumnDef );
- },
-
-
- /**
- * @ngdoc function
- * @name expandAllRows
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Expands all nodes in the tree
- *
- * @param {Grid} grid grid object
- */
- expandAllRows: function (grid) {
- grid.treeBase.tree.forEach( function( node ) {
- service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);
- });
- grid.treeBase.expandAll = true;
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name collapseAllRows
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Collapses all nodes in the tree
- *
- * @param {Grid} grid grid object
- */
- collapseAllRows: function (grid) {
- grid.treeBase.tree.forEach( function( node ) {
- service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);
- });
- grid.treeBase.expandAll = false;
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name setAllNodes
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Works through a subset of grid.treeBase.rowExpandedStates, setting
- * all child nodes (and their descendents) of the provided node to the given state.
- *
- * Calls itself recursively on all nodes so as to achieve this.
- *
- * @param {Grid} grid the grid we're operating on (so we can raise events)
- * @param {object} treeNode a node in the tree that we want to update
- * @param {string} targetState the state we want to set it to
- */
- setAllNodes: function (grid, treeNode, targetState) {
- if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ){
- treeNode.state = targetState;
-
- if ( targetState === uiGridTreeBaseConstants.EXPANDED ){
- grid.api.treeBase.raise.rowExpanded(treeNode.row);
- } else {
- grid.api.treeBase.raise.rowCollapsed(treeNode.row);
- }
- }
-
- // set all child nodes
- if ( treeNode.children ){
- treeNode.children.forEach(function( childNode ){
- service.setAllNodes(grid, childNode, targetState);
- });
- }
- },
-
-
- /**
- * @ngdoc function
- * @name toggleRowTreeState
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Toggles the expand or collapse state of this grouped row, if
- * it's a parent row
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to toggle
- */
- toggleRowTreeState: function ( grid, row ){
- if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
- return;
- }
-
- if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED){
- service.collapseRow(grid, row);
- } else {
- service.expandRow(grid, row);
- }
-
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name expandRow
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Expands this specific row, showing only immediate children.
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to expand
- */
- expandRow: function ( grid, row ){
- if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
- return;
- }
-
- if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ){
- row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;
- grid.api.treeBase.raise.rowExpanded(row);
- grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
- grid.queueGridRefresh();
- }
- },
-
-
- /**
- * @ngdoc function
- * @name expandRowChildren
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Expands this specific row, showing all children.
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to expand
- */
- expandRowChildren: function ( grid, row ){
- if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
- return;
- }
-
- service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);
- grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name collapseRow
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Collapses this specific row
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to collapse
- */
- collapseRow: function( grid, row ){
- if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
- return;
- }
-
- if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ){
- row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;
- grid.treeBase.expandAll = false;
- grid.api.treeBase.raise.rowCollapsed(row);
- grid.queueGridRefresh();
- }
- },
-
-
- /**
- * @ngdoc function
- * @name collapseRowChildren
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Collapses this specific row and all children
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to collapse
- */
- collapseRowChildren: function( grid, row ){
- if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ){
- return;
- }
-
- service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);
- grid.treeBase.expandAll = false;
- grid.queueGridRefresh();
- },
-
-
- /**
- * @ngdoc function
- * @name allExpanded
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Returns true if all rows are expanded, false
- * if they're not. Walks the tree to determine this. Used
- * to set the expandAll state.
- *
- * If the node has no children, then return true (it's immaterial
- * whether it is expanded). If the node has children, then return
- * false if this node is collapsed, or if any child node is not all expanded
- *
- * @param {object} tree the grid to check
- * @returns {boolean} whether or not the tree is all expanded
- */
- allExpanded: function( tree ){
- var allExpanded = true;
- tree.forEach( function( node ){
- if ( !service.allExpandedInternal( node ) ){
- allExpanded = false;
- }
- });
- return allExpanded;
- },
-
- allExpandedInternal: function( treeNode ){
- if ( treeNode.children && treeNode.children.length > 0 ){
- if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
- return false;
- }
- var allExpanded = true;
- treeNode.children.forEach( function( node ){
- if ( !service.allExpandedInternal( node ) ){
- allExpanded = false;
- }
- });
- return allExpanded;
- } else {
- return true;
- }
- },
-
-
- /**
- * @ngdoc function
- * @name treeRows
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description The rowProcessor that adds the nodes to the tree, and sets the visible
- * state of each row based on it's parent state
- *
- * Assumes it is always called after the sorting processor, and the grouping processor if there is one.
- * Performs any tree sorts itself after having built the tree
- *
- * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated
- * entity, and setting the visible state based on the parent's state.
- *
- * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly
- * sized.
- *
- * Aggregates if necessary along the way.
- *
- * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
- * @returns {array} the updated rows
- */
- treeRows: function( renderableRows ) {
- if (renderableRows.length === 0){
- return renderableRows;
- }
-
- var grid = this;
- var currentLevel = 0;
- var currentState = uiGridTreeBaseConstants.EXPANDED;
- var parents = [];
-
- grid.treeBase.tree = service.createTree( grid, renderableRows );
- service.updateRowHeaderWidth( grid );
-
- service.sortTree( grid );
- service.fixFilter( grid );
-
- return service.renderTree( grid.treeBase.tree );
- },
-
-
- /**
- * @ngdoc function
- * @name createOrUpdateRowHeaderWidth
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Calculates the rowHeader width.
- *
- * If rowHeader is always present, updates the width.
- *
- * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there
- * should be one, then creates or removes it as appropriate, with the created rowHeader having the
- * right width.
- *
- * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`
- *
- * @param {Grid} grid the grid we want to set the row header on
- */
- updateRowHeaderWidth: function( grid ){
- var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName);
-
- var newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);
- if ( rowHeader && newWidth !== rowHeader.width ){
- rowHeader.width = newWidth;
- grid.queueRefresh();
- }
-
- var newVisibility = true;
- if ( grid.options.showTreeRowHeader === false ){
- newVisibility = false;
- }
- if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ){
- newVisibility = false;
- }
- if ( rowHeader.visible !== newVisibility ) {
- rowHeader.visible = newVisibility;
- rowHeader.colDef.visible = newVisibility;
- grid.queueGridRefresh();
- }
- },
-
-
- /**
- * @ngdoc function
- * @name renderTree
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Creates an array of rows based on the tree, exporting only
- * the visible nodes and leaves
- *
- * @param {array} nodeList the list of nodes - can be grid.treeBase.tree, or can be node.children when
- * we're calling recursively
- * @returns {array} renderable rows
- */
- renderTree: function( nodeList ){
- var renderableRows = [];
-
- nodeList.forEach( function ( node ){
- if ( node.row.visible ){
- renderableRows.push( node.row );
- }
- if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
- renderableRows = renderableRows.concat( service.renderTree( node.children ) );
- }
- });
- return renderableRows;
- },
-
-
- /**
- * @ngdoc function
- * @name createTree
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Creates a tree from the renderableRows
- *
- * @param {Grid} grid the grid
- * @param {array} renderableRows the rows we want to create a tree from
- * @returns {object} the tree we've build
- */
- createTree: function( grid, renderableRows ) {
- var currentLevel = -1;
- var parents = [];
- var currentState;
- grid.treeBase.tree = [];
- grid.treeBase.numberLevels = 0;
- var aggregations = service.getAggregations( grid );
-
- var createNode = function( row ){
- if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ){
- row.treeLevel = row.entity.$$treeLevel;
- }
-
- if ( row.treeLevel <= currentLevel ){
- // pop any levels that aren't parents of this level, formatting the aggregation at the same time
- while ( row.treeLevel <= currentLevel ){
- var lastParent = parents.pop();
- service.finaliseAggregations( lastParent );
- currentLevel--;
- }
-
- // reset our current state based on the new parent, set to expanded if this is a level 0 node
- if ( parents.length > 0 ){
- currentState = service.setCurrentState(parents);
- } else {
- currentState = uiGridTreeBaseConstants.EXPANDED;
- }
- }
-
- // aggregate if this is a leaf node
- if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible ){
- service.aggregate( grid, row, parents );
- }
-
- // add this node to the tree
- service.addOrUseNode(grid, row, parents, aggregations);
-
- if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ){
- parents.push(row);
- currentLevel++;
- currentState = service.setCurrentState(parents);
- }
-
- // update the tree number of levels, so we can set header width if we need to
- if ( grid.treeBase.numberLevels < row.treeLevel + 1){
- grid.treeBase.numberLevels = row.treeLevel + 1;
- }
- };
-
- renderableRows.forEach( createNode );
-
- // finalise remaining aggregations
- while ( parents.length > 0 ){
- var lastParent = parents.pop();
- service.finaliseAggregations( lastParent );
- }
-
- return grid.treeBase.tree;
- },
-
-
- /**
- * @ngdoc function
- * @name addOrUseNode
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Creates a tree node for this row. If this row already has a treeNode
- * recorded against it, preserves the state, but otherwise overwrites the data.
- *
- * @param {grid} grid the grid we're operating on
- * @param {gridRow} row the row we want to set
- * @param {array} parents an array of the parents this row should have
- * @param {array} aggregationBase empty aggregation information
- * @returns {undefined} updates the parents array, updates the row to have a treeNode, and updates the
- * grid.treeBase.tree
- */
- addOrUseNode: function( grid, row, parents, aggregationBase ){
- var newAggregations = [];
- aggregationBase.forEach( function(aggregation){
- newAggregations.push(service.buildAggregationObject(aggregation.col));
- });
-
- var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };
- if ( row.treeNode ){
- newNode.state = row.treeNode.state;
- }
- if ( parents.length > 0 ){
- newNode.parentRow = parents[parents.length - 1];
- }
- row.treeNode = newNode;
-
- if ( parents.length === 0 ){
- grid.treeBase.tree.push( newNode );
- } else {
- parents[parents.length - 1].treeNode.children.push( newNode );
- }
- },
-
-
- /**
- * @ngdoc function
- * @name setCurrentState
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Looks at the parents array to determine our current state.
- * If any node in the hierarchy is collapsed, then return collapsed, otherwise return
- * expanded.
- *
- * @param {array} parents an array of the parents this row should have
- * @returns {string} the state we should be setting to any nodes we see
- */
- setCurrentState: function( parents ){
- var currentState = uiGridTreeBaseConstants.EXPANDED;
- parents.forEach( function(parent){
- if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ){
- currentState = uiGridTreeBaseConstants.COLLAPSED;
- }
- });
- return currentState;
- },
-
-
- /**
- * @ngdoc function
- * @name sortTree
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Performs a recursive sort on the tree nodes, sorting the
- * children of each node and putting them back into the children array.
- *
- * Before doing this it turns back on all the sortIgnore - things that were previously
- * ignored we process now. Since we're sorting within the nodes, presumably anything
- * that was already sorted is how we derived the nodes, we can keep those sorts too.
- *
- * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed
- * nodes
- *
- * @param {Grid} grid the grid to get the aggregation information from
- * @returns {array} the aggregation information
- */
- sortTree: function( grid ){
- grid.columns.forEach( function( column ) {
- if ( column.sort && column.sort.ignoreSort ){
- delete column.sort.ignoreSort;
- }
- });
-
- grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );
- },
-
- sortInternal: function( grid, treeList ){
- var rows = treeList.map( function( node ){
- return node.row;
- });
-
- rows = rowSorter.sort( grid, rows, grid.columns );
-
- var treeNodes = rows.map( function( row ){
- return row.treeNode;
- });
-
- treeNodes.forEach( function( node ){
- if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ){
- node.children = service.sortInternal( grid, node.children );
- }
- });
-
- return treeNodes;
- },
-
- /**
- * @ngdoc function
- * @name fixFilter
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description After filtering has run, we need to go back through the tree
- * and make sure the parent rows are always visible if any of the child rows
- * are visible (filtering may make a child visible, but the parent may not
- * match the filter criteria)
- *
- * This has a risk of being computationally expensive, we do it by walking
- * the tree and remembering whether there are any invisible nodes on the
- * way down.
- *
- * @param {Grid} grid the grid to fix filters on
- */
- fixFilter: function( grid ){
- var parentsVisible;
-
- grid.treeBase.tree.forEach( function( node ){
- if ( node.children && node.children.length > 0 ){
- parentsVisible = node.row.visible;
- service.fixFilterInternal( node.children, parentsVisible );
- }
- });
- },
-
- fixFilterInternal: function( nodes, parentsVisible) {
- nodes.forEach( function( node ){
- if ( node.row.visible && !parentsVisible ){
- service.setParentsVisible( node );
- parentsVisible = true;
- }
-
- if ( node.children && node.children.length > 0 ){
- if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {
- parentsVisible = true;
- }
- }
- });
-
- return parentsVisible;
- },
-
- setParentsVisible: function( node ){
- while ( node.parentRow ){
- node.parentRow.visible = true;
- node = node.parentRow.treeNode;
- }
- },
-
- /**
- * @ngdoc function
- * @name buildAggregationObject
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Build the object which is stored on the column for holding meta-data about the aggregation.
- * This method should only be called with columns which have an aggregation.
- *
- * @param {Column} the column which this object relates to
- * @returns {object} {col: Column object, label: string, type: string (optional)}
- */
- buildAggregationObject: function( column ){
- var newAggregation = { col: column };
-
- if ( column.treeAggregation && column.treeAggregation.type ){
- newAggregation.type = column.treeAggregation.type;
- }
-
- if ( column.treeAggregation && column.treeAggregation.label ){
- newAggregation.label = column.treeAggregation.label;
- }
-
- return newAggregation;
- },
-
- /**
- * @ngdoc function
- * @name getAggregations
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Looks through the grid columns to find those with aggregations,
- * and collates the aggregation information into an array, returns that array
- *
- * @param {Grid} grid the grid to get the aggregation information from
- * @returns {array} the aggregation information
- */
- getAggregations: function( grid ){
- var aggregateArray = [];
-
- grid.columns.forEach( function(column){
- if ( typeof(column.treeAggregationFn) !== 'undefined' ){
- aggregateArray.push( service.buildAggregationObject(column) );
-
- if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ){
- // Add aggregation object for footer
- column.treeFooterAggregation = service.buildAggregationObject(column);
- column.aggregationType = service.treeFooterAggregationType;
- }
- }
- });
- return aggregateArray;
- },
-
-
- /**
- * @ngdoc function
- * @name aggregate
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Accumulate the data from this row onto the aggregations for each parent
- *
- * Iterate over the parents, then iterate over the aggregations for each of those parents,
- * and perform the aggregation for each individual aggregation
- *
- * @param {Grid} grid grid object
- * @param {GridRow} row the row we want to set grouping visibility on
- * @param {array} parents the parents that we would want to aggregate onto
- */
- aggregate: function( grid, row, parents ){
- if ( parents.length === 0 && row.treeNode && row.treeNode.aggregations ){
- row.treeNode.aggregations.forEach(function(aggregation){
- // Calculate aggregations for footer even if there are no grouped rows
- if ( typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ) {
- var fieldValue = grid.getCellValue(row, aggregation.col);
- var numValue = Number(fieldValue);
- aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
- }
- });
- }
-
- parents.forEach( function( parent, index ){
- if ( parent.treeNode.aggregations ){
- parent.treeNode.aggregations.forEach( function( aggregation ){
- var fieldValue = grid.getCellValue(row, aggregation.col);
- var numValue = Number(fieldValue);
- aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);
-
- if ( index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined' ){
- aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
- }
- });
- }
- });
- },
-
-
- // Aggregation routines - no doco needed as self evident
- nativeAggregations: function() {
- var nativeAggregations = {
- count: {
- label: i18nService.get().aggregation.count,
- menuTitle: i18nService.get().grouping.aggregate_count,
- aggregationFn: function (aggregation, fieldValue, numValue) {
- if (typeof(aggregation.value) === 'undefined') {
- aggregation.value = 1;
- } else {
- aggregation.value++;
- }
- }
- },
-
- sum: {
- label: i18nService.get().aggregation.sum,
- menuTitle: i18nService.get().grouping.aggregate_sum,
- aggregationFn: function( aggregation, fieldValue, numValue ) {
- if (!isNaN(numValue)) {
- if (typeof(aggregation.value) === 'undefined') {
- aggregation.value = numValue;
- } else {
- aggregation.value += numValue;
- }
- }
- }
- },
-
- min: {
- label: i18nService.get().aggregation.min,
- menuTitle: i18nService.get().grouping.aggregate_min,
- aggregationFn: function( aggregation, fieldValue, numValue ) {
- if (typeof(aggregation.value) === 'undefined') {
- aggregation.value = fieldValue;
- } else {
- if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {
- aggregation.value = fieldValue;
- }
- }
- }
- },
-
- max: {
- label: i18nService.get().aggregation.max,
- menuTitle: i18nService.get().grouping.aggregate_max,
- aggregationFn: function( aggregation, fieldValue, numValue ){
- if ( typeof(aggregation.value) === 'undefined' ){
- aggregation.value = fieldValue;
- } else {
- if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)){
- aggregation.value = fieldValue;
- }
- }
- }
- },
-
- avg: {
- label: i18nService.get().aggregation.avg,
- menuTitle: i18nService.get().grouping.aggregate_avg,
- aggregationFn: function( aggregation, fieldValue, numValue ){
- if ( typeof(aggregation.count) === 'undefined' ){
- aggregation.count = 1;
- } else {
- aggregation.count++;
- }
-
- if ( isNaN(numValue) ){
- return;
- }
-
- if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ){
- aggregation.value = numValue;
- aggregation.sum = numValue;
- } else {
- aggregation.sum += numValue;
- aggregation.value = aggregation.sum / aggregation.count;
- }
- }
- }
- };
- return nativeAggregations;
- },
-
- /**
- * @ngdoc function
- * @name finaliseAggregation
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Helper function used to finalize aggregation nodes and footer cells
- *
- * @param {gridRow} row the parent we're finalising
- * @param {aggregation} the aggregation object manipulated by the aggregationFn
- */
- finaliseAggregation: function(row, aggregation){
- if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ){
- angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);
- }
-
- if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ){
- aggregation.col.treeAggregationFinalizerFn( aggregation );
- }
- if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ){
- aggregation.col.customTreeAggregationFinalizerFn( aggregation );
- }
- if ( typeof(aggregation.rendered) === 'undefined' ){
- aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;
- }
- },
-
- /**
- * @ngdoc function
- * @name finaliseAggregations
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Format the data from the aggregation into the rendered text
- * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.
- *
- * As part of this we call any formatting callback routines we've been provided.
- *
- * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is
- * set on the column - we don't overwrite any information that's already there, we append
- * to it so that grouping can have set the groupVal beforehand without us overwriting it.
- *
- * We need to copy the data from the row.entity first before we finalise the aggregation,
- * we need that information for the finaliserFn
- *
- * @param {gridRow} row the parent we're finalising
- */
- finaliseAggregations: function( row ){
- if ( typeof(row.treeNode.aggregations) === 'undefined' ){
- return;
- }
-
- row.treeNode.aggregations.forEach( function( aggregation ) {
- service.finaliseAggregation(row, aggregation);
-
- if ( aggregation.col.treeAggregationUpdateEntity ){
- var aggregationCopy = {};
- angular.forEach( aggregation, function( value, key ){
- if ( aggregation.hasOwnProperty(key) && key !== 'col' ){
- aggregationCopy[key] = value;
- }
- });
-
- row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;
- }
- });
- },
-
- /**
- * @ngdoc function
- * @name treeFooterAggregationType
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Uses the tree aggregation functions and finalizers to set the
- * column footer aggregations.
- *
- * @param {rows} visible rows. not used, but accepted to match signature of GridColumn.aggregationType
- * @param {gridColumn} the column we are finalizing
- */
- treeFooterAggregationType: function( rows, column ) {
- service.finaliseAggregation(undefined, column.treeFooterAggregation);
- if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ){
- // The was apparently no aggregation performed (perhaps this is a grouped column
- return '';
- }
- return column.treeFooterAggregation.rendered;
- }
- };
-
- return service;
-
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons
- * @element div
- *
- * @description Provides the expand/collapse button on rows
- */
- module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',
- function ($templateCache, uiGridTreeBaseService) {
- return {
- replace: true,
- restrict: 'E',
- template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),
- scope: true,
- require: '^uiGrid',
- link: function($scope, $elm, $attrs, uiGridCtrl) {
- var self = uiGridCtrl.grid;
- $scope.treeButtonClick = function(row, evt) {
- uiGridTreeBaseService.toggleRowTreeState(self, row, evt);
- };
- }
- };
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons
- * @element div
- *
- * @description Provides the expand/collapse all button
- */
- module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',
- function ($templateCache, uiGridTreeBaseService) {
- return {
- replace: true,
- restrict: 'E',
- template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),
- scope: false,
- link: function($scope, $elm, $attrs, uiGridCtrl) {
- var self = $scope.col.grid;
-
- $scope.headerButtonClick = function(row, evt) {
- if ( self.treeBase.expandAll ){
- uiGridTreeBaseService.collapseAllRows(self, evt);
- } else {
- uiGridTreeBaseService.expandAllRows(self, evt);
- }
- };
- }
- };
- }]);
-
-
- /**
- * @ngdoc directive
- * @name ui.grid.treeBase.directive:uiGridViewport
- * @element div
- *
- * @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row
- */
- module.directive('uiGridViewport',
- ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
- function ($compile, uiGridConstants, gridUtil, $parse) {
- return {
- priority: -200, // run after default directive
- scope: false,
- compile: function ($elm, $attrs) {
- var rowRepeatDiv = angular.element($elm.children().children()[0]);
-
- var existingNgClass = rowRepeatDiv.attr("ng-class");
- var newNgClass = '';
- if ( existingNgClass ) {
- newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-tree-header-row': row.treeLevel > -1}";
- } else {
- newNgClass = "{'ui-grid-tree-header-row': row.treeLevel > -1}";
- }
- rowRepeatDiv.attr("ng-class", newNgClass);
-
- return {
- pre: function ($scope, $elm, $attrs, controllers) {
-
- },
- post: function ($scope, $elm, $attrs, controllers) {
- }
- };
- }
- };
- }]);
-})();
-
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name ui.grid.treeView
- * @description
- *
- * # ui.grid.treeView
- *
- * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
- *
- * This module provides a tree view of the data that it is provided, with nodes in that
- * tree and leaves. Unlike grouping, the tree is an inherent property of the data and must
- * be provided with your data array.
- *
- * Design information:
- * -------------------
- *
- * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around
- * that logic. Most of the design information has now moved to treebase.
- * <br/>
- * <br/>
- *
- * <div doc-module-components="ui.grid.treeView"></div>
- */
-
- var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);
-
- /**
- * @ngdoc object
- * @name ui.grid.treeView.constant:uiGridTreeViewConstants
- *
- * @description constants available in treeView module, this includes
- * all the constants declared in the treeBase module (these are manually copied
- * as there isn't an easy way to include constants in another constants file, and
- * we don't want to make users include treeBase)
- *
- */
- module.constant('uiGridTreeViewConstants', {
- featureName: "treeView",
- rowHeaderColName: 'treeBaseRowHeaderCol',
- EXPANDED: 'expanded',
- COLLAPSED: 'collapsed',
- aggregation: {
- COUNT: 'count',
- SUM: 'sum',
- MAX: 'max',
- MIN: 'min',
- AVG: 'avg'
- }
- });
-
- /**
- * @ngdoc service
- * @name ui.grid.treeView.service:uiGridTreeViewService
- *
- * @description Services for treeView features
- */
- module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',
- function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {
-
- var service = {
-
- initializeGrid: function (grid, $scope) {
- uiGridTreeBaseService.initializeGrid( grid, $scope );
-
- /**
- * @ngdoc object
- * @name ui.grid.treeView.grid:treeView
- *
- * @description Grid properties and functions added for treeView
- */
- grid.treeView = {};
-
- grid.registerRowsProcessor(service.adjustSorting, 60);
-
- /**
- * @ngdoc object
- * @name ui.grid.treeView.api:PublicApi
- *
- * @description Public Api for treeView feature
- */
- var publicApi = {
- events: {
- treeView: {
- }
- },
- methods: {
- treeView: {
- }
- }
- };
-
- grid.api.registerEventsFromObject(publicApi.events);
-
- grid.api.registerMethodsFromObject(publicApi.methods);
-
- },
-
- defaultGridOptions: function (gridOptions) {
- //default option to true unless it was explicitly set to false
- /**
- * @ngdoc object
- * @name ui.grid.treeView.api:GridOptions
- *
- * @description GridOptions for treeView feature, these are available to be
- * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
- *
- * Many tree options are set on treeBase, make sure to look at that feature in
- * conjunction with these options.
- */
-
- /**
- * @ngdoc object
- * @name enableTreeView
- * @propertyOf ui.grid.treeView.api:GridOptions
- * @description Enable row tree view for entire grid.
- * <br/>Defaults to true
- */
- gridOptions.enableTreeView = gridOptions.enableTreeView !== false;
-
- },
-
-
- /**
- * @ngdoc function
- * @name adjustSorting
- * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
- * @description Trees cannot be sorted the same as flat lists of rows -
- * trees are sorted recursively within each level - so the children of each
- * node are sorted, but not the full set of rows.
- *
- * To achieve this, we suppress the normal sorting by setting ignoreSort on
- * each of the sort columns. When the treeBase rowsProcessor runs it will then
- * unignore these, and will perform a recursive sort against the tree that it builds.
- *
- * @param {array} renderableRows the rows that we need to pass on through
- * @returns {array} renderableRows that we passed on through
- */
- adjustSorting: function( renderableRows ) {
- var grid = this;
-
- grid.columns.forEach( function( column ){
- if ( column.sort ){
- column.sort.ignoreSort = true;
- }
- });
-
- return renderableRows;
- }
-
- };
-
- return service;
-
- }]);
-
- /**
- * @ngdoc directive
- * @name ui.grid.treeView.directive:uiGridTreeView
- * @element div
- * @restrict A
- *
- * @description Adds treeView features to grid
- *
- * @example
- <example module="app">
- <file name="app.js">
- var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);
-
- app.controller('MainCtrl', ['$scope', function ($scope) {
- $scope.data = [
- { name: 'Bob', title: 'CEO' },
- { name: 'Frank', title: 'Lowly Developer' }
- ];
-
- $scope.columnDefs = [
- {name: 'name', enableCellEdit: true},
- {name: 'title', enableCellEdit: true}
- ];
-
- $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
- }]);
- </file>
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <div ui-grid="gridOptions" ui-grid-tree-view></div>
- </div>
- </file>
- </example>
- */
- module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',
- function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {
- return {
- replace: true,
- priority: 0,
- require: '^uiGrid',
- scope: false,
- compile: function () {
- return {
- pre: function ($scope, $elm, $attrs, uiGridCtrl) {
- if (uiGridCtrl.grid.options.enableTreeView !== false){
- uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);
- }
- },
- post: function ($scope, $elm, $attrs, uiGridCtrl) {
-
- }
- };
- }
- };
- }]);
-})();
-
-angular.module('ui.grid').run(['$templateCache', function($templateCache) {
- 'use strict';
-
- $templateCache.put('ui-grid/ui-grid-filter',
- "<div class=\"ui-grid-filter-container\" ng-repeat=\"colFilter in col.filters\" ng-class=\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\"><div ng-if=\"colFilter.type !== 'select'\"><input type=\"text\" class=\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\" aria-label=\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\"><div role=\"button\" class=\"ui-grid-filter-button\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div><div ng-if=\"colFilter.type === 'select'\"><select class=\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || aria.defaultFilterLabel}}\" aria-label=\"{{colFilter.ariaLabel || ''}}\" ng-options=\"option.value as option.label for option in colFilter.selectOptions\"><option value=\"\"></option></select><div role=\"button\" class=\"ui-grid-filter-button-select\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term != null\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-footer',
- "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\"><!-- tfooter --><div class=\"ui-grid-footer ui-grid-footer-viewport\"><div class=\"ui-grid-footer-canvas\"><div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-footer-cell-row\"><div ui-grid-footer-cell role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\"></div></div></div></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-grid-footer',
- "<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-group-panel',
- "<div class=\"ui-grid-group-panel\"><div ui-t=\"groupPanel.description\" class=\"description\" ng-show=\"groupings.length == 0\"></div><ul ng-show=\"groupings.length > 0\" class=\"ngGroupList\"><li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\"><span class=\"ngGroupElement\"><span class=\"ngGroupName\">{{group.displayName}} <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span></span> <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span></span></li></ul></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-header',
- "<div role=\"rowgroup\" class=\"ui-grid-header\"><!-- theader --><div class=\"ui-grid-top-panel\"><div class=\"ui-grid-header-viewport\"><div class=\"ui-grid-header-canvas\"><div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-header-cell-row\"><div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div></div></div></div></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-menu-button',
- "<div class=\"ui-grid-menu-button\"><div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-menu\" ui-grid-one-bind-aria-label=\"i18n.aria.buttonLabel\">&nbsp;</i></div><div ui-grid-menu menu-items=\"menuItems\"></div></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-no-header',
- "<div class=\"ui-grid-top-panel\"></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid-row',
- "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"
- );
-
-
- $templateCache.put('ui-grid/ui-grid',
- "<div ui-i18n=\"en\" class=\"ui-grid\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\n" +
- " /* Styles for the grid */\n" +
- " }\n" +
- "\n" +
- " .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n" +
- " height: {{ grid.options.rowHeight }}px;\n" +
- " }\n" +
- "\n" +
- " .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n" +
- " border-bottom-width: {{ ((grid.getTotalRowHeight() < grid.getViewportHeight()) && '1') || '0' }}px;\n" +
- " }\n" +
- "\n" +
- " {{ grid.verticalScrollbarStyles }}\n" +
- " {{ grid.horizontalScrollbarStyles }}\n" +
- "\n" +
- " /*\n" +
- " .ui-grid[dir=rtl] .ui-grid-viewport {\n" +
- " padding-left: {{ grid.verticalScrollbarWidth }}px;\n" +
- " }\n" +
- " */\n" +
- "\n" +
- " {{ grid.customStyles }}</style><div class=\"ui-grid-contents-wrapper\"><div ui-grid-menu-button ng-if=\"grid.options.enableGridMenu\"></div><div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\"></div><div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\" enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div><div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\"></div><div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\"></div><div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\"></div><div ng-transclude></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridCell',
- "<div class=\"ui-grid-cell-contents\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridColumnMenu',
- "<div class=\"ui-grid-column-menu\"><div ui-grid-menu menu-items=\"menuItems\"><!-- <div class=\"ui-grid-column-menu\">\n" +
- " <div class=\"inner\" ng-show=\"menuShown\">\n" +
- " <ul>\n" +
- " <div ng-show=\"grid.options.enableSorting\">\n" +
- " <li ng-click=\"sortColumn($event, asc)\" ng-class=\"{ 'selected' : col.sort.direction == asc }\"><i class=\"ui-grid-icon-sort-alt-up\"></i> Sort Ascending</li>\n" +
- " <li ng-click=\"sortColumn($event, desc)\" ng-class=\"{ 'selected' : col.sort.direction == desc }\"><i class=\"ui-grid-icon-sort-alt-down\"></i> Sort Descending</li>\n" +
- " <li ng-show=\"col.sort.direction\" ng-click=\"unsortColumn()\"><i class=\"ui-grid-icon-cancel\"></i> Remove Sort</li>\n" +
- " </div>\n" +
- " </ul>\n" +
- " </div>\n" +
- " </div> --></div></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridFooterCell',
- "<div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridHeaderCell',
- "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\"><div role=\"button\" tabindex=\"0\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\"><span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\"><i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{col.sort.priority ? i18n.headerCell.priority + ' ' + col.sort.priority : null}}\" aria-hidden=\"true\"></i> <sub class=\"ui-grid-sort-priority-number\">{{col.sort.priority}}</sub></span></div><div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i></div><div ui-grid-filter></div></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridMenu',
- "<div class=\"ui-grid-menu\" ng-if=\"shown\"><div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\"><div class=\"ui-grid-menu-inner\"><button type=\"button\" ng-focus=\"focus=true\" ng-blur=\"focus=false\" class=\"ui-grid-menu-close-button\" ng-class=\"{'ui-grid-sr-only': (!focus)}\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"i18n.close\"></i></button><ul role=\"menu\" class=\"ui-grid-menu-items\"><li ng-repeat=\"item in menuItems\" role=\"menuitem\" ui-grid-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\" action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" screen-reader-only=\"item.screenReaderOnly\"></li></ul></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridMenuItem',
- "<button type=\"button\" class=\"ui-grid-menu-item\" ng-click=\"itemAction($event, title)\" ng-show=\"itemShown()\" ng-class=\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\" aria-pressed=\"{{active()}}\" tabindex=\"0\" ng-focus=\"focus=true\" ng-blur=\"focus=false\"><i ng-class=\"icon\" aria-hidden=\"true\">&nbsp;</i> {{ name }}</button>"
- );
-
-
- $templateCache.put('ui-grid/uiGridRenderContainer',
- "<div role=\"grid\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"
- );
-
-
- $templateCache.put('ui-grid/uiGridViewport',
- "<div role=\"rowgroup\" class=\"ui-grid-viewport\" ng-style=\"colContainer.getViewportStyle()\"><!-- tbody --><div class=\"ui-grid-canvas\"><div ng-repeat=\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\" class=\"ui-grid-row\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div role=\"row\" ui-grid-row=\"row\" row-render-index=\"rowRenderIndex\"></div></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/cellEditor',
- "<div><form name=\"inputForm\"><input type=\"INPUT_TYPE\" ng-class=\"'colt' + col.uid\" ui-grid-editor ng-model=\"MODEL_COL_FIELD\"></form></div>"
- );
-
-
- $templateCache.put('ui-grid/dropdownEditor',
- "<div><form name=\"inputForm\"><select ng-class=\"'colt' + col.uid\" ui-grid-edit-dropdown ng-model=\"MODEL_COL_FIELD\" ng-options=\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\"></select></form></div>"
- );
-
-
- $templateCache.put('ui-grid/fileChooserEditor',
- "<div><form name=\"inputForm\"><input ng-class=\"'colt' + col.uid\" ui-grid-edit-file-chooser type=\"file\" id=\"files\" name=\"files[]\" ng-model=\"MODEL_COL_FIELD\"></form></div>"
- );
-
-
- $templateCache.put('ui-grid/expandableRow',
- "<div ui-grid-expandable-row ng-if=\"expandableRow.shouldRenderExpand()\" class=\"expandableRow\" style=\"float:left; margin-top: 1px; margin-bottom: 1px\" ng-style=\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: row.expandedRowHeight + 'px'}\"></div>"
- );
-
-
- $templateCache.put('ui-grid/expandableRowHeader',
- "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-class=\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\" ng-click=\"grid.api.expandable.toggleRowExpansion(row.entity)\"></i></div></div>"
- );
-
-
- $templateCache.put('ui-grid/expandableScrollFiller',
- "<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller:true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\"><i class=\"ui-grid-icon-spin5 ui-grid-animate-spin\" ng-style=\"{'margin-top': ( row.expandedRowHeight/2 - 5) + 'px', 'margin-left' : ((grid.getViewportWidth() - grid.options.rowHeader.rowHeaderWidth)/2 - 5) + 'px'}\"></i></div>"
- );
-
-
- $templateCache.put('ui-grid/expandableTopRowHeader',
- "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i ng-class=\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\" ng-click=\"grid.api.expandable.toggleAllRows()\"></i></div></div>"
- );
-
-
- $templateCache.put('ui-grid/csvLink',
- "<span class=\"ui-grid-exporter-csv-link-span\"><a href=\"data:text/csv;charset=UTF-8,CSV_CONTENT\" download=\"FILE_NAME\">LINK_LABEL</a></span>"
- );
-
-
- $templateCache.put('ui-grid/importerMenuItem',
- "<li class=\"ui-grid-menu-item\"><form><input class=\"ui-grid-importer-file-chooser\" type=\"file\" id=\"files\" name=\"files[]\"></form></li>"
- );
-
-
- $templateCache.put('ui-grid/importerMenuItemContainer',
- "<div ui-grid-importer-menu-item></div>"
- );
-
-
- $templateCache.put('ui-grid/pagination',
- "<div role=\"contentinfo\" class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div role=\"menubar\" class=\"ui-grid-pager-control\"><button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle\"><div class=\"first-bar\"></div></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div class=\"first-triangle prev-triangle\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/</abbr> {{ paginationApi.getTotalPages() }}</span> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div class=\"last-triangle next-triangle\"></div></button> <button type=\"button\" role=\"menuitem\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div class=\"last-triangle\"><div class=\"last-bar\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{showingLow}} <abbr ui-grid-one-bind-title=\"paginationThrough\">-</abbr> {{showingHigh}} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>"
- );
-
-
- $templateCache.put('ui-grid/columnResizer',
- "<div ui-grid-column-resizer ng-if=\"grid.options.enableColumnResizing\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
- );
-
-
- $templateCache.put('ui-grid/gridFooterSelectedItems',
- "<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"search.selectedItems\" | t}} {{grid.selection.selectedCount}})</span>"
- );
-
-
- $templateCache.put('ui-grid/selectionHeaderCell',
- "<div><!-- <div class=\"ui-grid-vertical-bar\">&nbsp;</div> --><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-selection-select-all-buttons ng-if=\"grid.options.enableSelectAll\"></ui-grid-selection-select-all-buttons></div></div>"
- );
-
-
- $templateCache.put('ui-grid/selectionRowHeader',
- "<div class=\"ui-grid-disable-selection\"><div class=\"ui-grid-cell-contents\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div></div>"
- );
-
-
- $templateCache.put('ui-grid/selectionRowHeaderButtons',
- "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ng-click=\"selectButtonClick(row, $event)\">&nbsp;</div>"
- );
-
-
- $templateCache.put('ui-grid/selectionSelectAllButtons',
- "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-click=\"headerButtonClick($event)\"></div>"
- );
-
-
- $templateCache.put('ui-grid/treeBaseExpandAllButtons',
- "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-icon-minus-squared': grid.treeBase.numberLevels > 0 && grid.treeBase.expandAll, 'ui-grid-icon-plus-squared': grid.treeBase.numberLevels > 0 && !grid.treeBase.expandAll}\" ng-click=\"headerButtonClick($event)\"></div>"
- );
-
-
- $templateCache.put('ui-grid/treeBaseHeaderCell',
- "<div><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-tree-base-expand-all-buttons></ui-grid-tree-base-expand-all-buttons></div></div>"
- );
-
-
- $templateCache.put('ui-grid/treeBaseRowHeader',
- "<div class=\"ui-grid-cell-contents\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>"
- );
-
-
- $templateCache.put('ui-grid/treeBaseRowHeaderButtons',
- "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\" ng-click=\"treeButtonClick(row, $event)\"><i ng-class=\"{'ui-grid-icon-minus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'expanded', 'ui-grid-icon-plus-squared': ( ( grid.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) && row.treeNode.state === 'collapsed'}\" ng-style=\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\"></i> &nbsp;</div>"
- );
-
-}]);
diff --git a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/welcome.css b/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/welcome.css
deleted file mode 100644
index 559db709..00000000
--- a/ecomp-sdk/sdk-app/src/main/webapp/static/fusion/sample/css/welcome.css
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Area Chart */
-
-#areaChart {
- overflow: hidden;}
-
-#lineChart {
- overflow: hidden;
-}
-
-#areaChart svg {
- height: 200px;
- width: 380px;
- min-width: 100px;
- min-height: 100px;
-}
-
-#lineChart svg {
- height: 200px;
- width: 380px;
- min-width: 100px;
- min-height: 100px;
-}
-
-#areaChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
- background-color: rgb(255, 255, 255);
-}
-
-#lineChart tr.z-row-over>td.z-row-inner, tr.z-row-over>.z-cell {
- background-color: rgb(255, 255, 255);
-}
-
-#areaChart .nodatadiv {
- display: table-cell;
- width: 700px;
- height: 370px;
- text-align: center;
- vertical-align: middle;
-}
-
-#lineChart .nodatadiv {
- display: table-cell;
- width: 700px;
- height: 370px;
- text-align: center;
- vertical-align: middle;
-}
-
-#areaChart .nodatainner {
- padding: 10px;
-}
-
-#lineChart .nodatainner {
- padding: 10px;
-}
-
-/* Area Chart END */
-
-.button--small, [class*=bg-] .button--small {
- font-size: 14px;
- };
-
-/* Gridster (EBIZ) */
-
-.gridster-item-container .gridster-item-body{
-bottom:0px;
-}
-.gridster-item-container{
-min-height:50px;
-}
-.att-accordion {
- border-width: 0px;
-}
-
-/* End Gridster */
-
-#myGallery {
- width: 100%;
- height: 400px;
-}
-
-#myGallery img {
- border: 2px solid #52697E;
-}
-
-a.loading {
- background: #fff url(../images/ajax_small.gif) no-repeat center;
-}
-
-.center {
- margin-left: auto;
- margin-right: auto;
-}
-
-
-#selectedTrafficDay ul {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-#selectedTrafficDay li {
- float: left;
- border: 1px solid #000;
- border-bottom-width: 0;
- margin: 3px 3px 3px 3px;
- padding: 5px 5px 5px 5px;
- background-color: #F2F2F2;
- color: #696969;
-}
-
-#SelectedTrafficeDayView {
- padding: 0 1em;
-}
-
-#selectedTrafficDay .active1 {
- background-color: #FFF;
- color: #000;
-}
-
-#BusyHourTraffic ul {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-#BusyHourTraffic li {
- float: left;
- border: 1px solid #000;
- border-bottom-width: 0;
- margin: 3px 3px 3px 3px;
- padding: 5px 5px 5px 5px;
- background-color: #F2F2F2;
- color: #696969;
-}
-
-#BusyHourTrafficView {
- padding: 0 1em;
-}
-
-#BusyHourTraffic .active2 {
- background-color: #FFF;
- color: #000;
-}
-
-#slider {
- width: 600px;
- margin: 0 auto;
- clear: left;
-}
-
-@media only screen and (device-width: 768px) {
- #slider {
- width: 400px;
- }
-}
-
-#container {
-
-}
-
-#title {
- float:left;
- width:100%;
- height:30px;
- margin:;
- color:#222222;
- text-shadow: 1px 1px 2px #A0A0A0;
-}
-
diff --git a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java b/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java
deleted file mode 100644
index 1bafe203..00000000
--- a/ecomp-sdk/sdk-app/src/test/java/org/openecomp/portalsdk/core/MockApplicationContextTestSuite.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.openecomp.portalsdk.core;
-
-import java.io.IOException;
-
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.openecomp.portalsdk.core.conf.AppConfig;
-import org.openecomp.portalsdk.core.objectcache.AbstractCacheManager;
-import org.openecomp.portalsdk.core.util.CacheManager;
-import org.openecomp.portalsdk.core.util.SystemProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
-import org.springframework.test.context.web.WebAppConfiguration;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-
-/**
- *
- *
- *
- * In order to write a unit test,
- * 1. inherit this class - See SanityTest.java
- * 2. place the "war" folder on your test class's classpath
- * 3. run the test with the following VM argument; This is important because when starting the application from Container, the System Properties file (SystemProperties.java) can have the direct path
- * but, when running from the Mock Junit container, the path should be prefixed with "classpath" to enable the mock container to search for the file in the classpath
- * -Dcontainer.classpath="classpath:"
- *
- */
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = {MockAppConfig.class})
-@ActiveProfiles(value="test")
-public class MockApplicationContextTestSuite {
-
- @Autowired
- public WebApplicationContext wac;
-
- private MockMvc mockMvc;
-
- @Before
- public void setup() {
- if(mockMvc == null) {
- this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
-
- }
- }
-
- public Object getBean(String name) {
- return this.wac.getBean(name);
- }
-
-
- public MockMvc getMockMvc() {
- return mockMvc;
- }
-
- public void setMockMvc(MockMvc mockMvc) {
- this.mockMvc = mockMvc;
- }
-
- public WebApplicationContext getWebApplicationContext() {
- return wac;
- }
-
-
-
-
-}
-
-
- @Configuration
- @ComponentScan(basePackages = "org.openecomp",
- excludeFilters = {
-
- }
- )
- @Profile("test")
- class MockAppConfig extends AppConfig {
-
- @Bean
- public SystemProperties systemProperties(){
- return new MockSystemProperties();
- }
-
- @Bean
- public AbstractCacheManager cacheManager() {
- return new CacheManager() {
-
- public void configure() throws IOException {
-
- }
- };
- }
-
- protected String[] tileDefinitions() {
- return new String[] {"classpath:/WEB-INF/fusion/defs/definitions.xml", "classpath:/WEB-INF/defs/definitions.xml"};
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- //registry.addInterceptor(new SessionTimeoutInterceptor()).excludePathPatterns(getExcludeUrlPathsForSessionTimeout());
- //registry.addInterceptor(resourceInterceptor());
- }
-
- public static class MockSystemProperties extends SystemProperties {
-
- public MockSystemProperties() {
- }
-
- }
-
- }
-
-
-
-
diff --git a/ecomp-sdk/sdk-workflow/.gitignore b/ecomp-sdk/sdk-workflow/.gitignore
deleted file mode 100644
index b83d2226..00000000
--- a/ecomp-sdk/sdk-workflow/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/ecomp-sdk/sdk-workflow/README.md b/ecomp-sdk/sdk-workflow/README.md
deleted file mode 100644
index d144d21c..00000000
--- a/ecomp-sdk/sdk-workflow/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-ECOMP Portal SDK Workflow
-=========================
-
-This is the Maven project for the ECOMP Portal SDK Workflow,
-which is distributed as ecompSDK-workflow-nnn.jar. This library
-requires Hibernate and Spring, and provides features including
-schedulers, workflows and R Cloud integration.
diff --git a/ecomp-sdk/sdk-workflow/pom.xml b/ecomp-sdk/sdk-workflow/pom.xml
deleted file mode 100644
index 79f3067a..00000000
--- a/ecomp-sdk/sdk-workflow/pom.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-project</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>ecompSDK-workflow</artifactId>
- <name>Ecomp Portal SDK Workflow</name>
- <description>Provides workflow features for SDK applications</description>
- <packaging>jar</packaging>
-
- <!-- repositories are inherited from parent -->
-
- <dependencies>
- <!-- sdk-core -->
- <dependency>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-core</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>${hibernate.version}</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>5.1.3.Final</version>
- </dependency>
- <dependency>
- <groupId>org.json</groupId>
- <artifactId>json</artifactId>
- <version>20160212</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.2.1</version>
- <exclusions>
- <!-- exclude 0.9.1.1 to avoid dupe of com.mchange:c3p0:0.9.2.1 -->
- <exclusion>
- <groupId>c3p0</groupId>
- <artifactId>c3p0</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- bridge to implement commons-logging using slf4j -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${springframework.version}</version>
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${springframework.version}</version>
- </dependency>
- </dependencies>
-
-</project>
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/HibernateConfiguration.java b/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/HibernateConfiguration.java
deleted file mode 100644
index e5ace071..00000000
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/dao/HibernateConfiguration.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.workflow.dao;
diff --git a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java b/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java
deleted file mode 100644
index 745b0b23..00000000
--- a/ecomp-sdk/sdk-workflow/src/main/java/org/openecomp/portalsdk/workflow/services/WorkflowService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.workflow.services;
-
-import java.util.List;
-
-import org.openecomp.portalsdk.workflow.domain.WorkflowSchedule;
-import org.openecomp.portalsdk.workflow.models.Workflow;
-import org.openecomp.portalsdk.workflow.models.WorkflowLite;
-
-
-public interface WorkflowService {
- public void saveCronJob(WorkflowSchedule domainCronJobData);
- public Workflow addWorkflow(Workflow workflow, String creatorId);
- public Workflow editWorkflow(WorkflowLite worklow, String creatorId);
- public void deleteWorkflow(Long worklow);
- public List<Workflow> getAllWorkflows();
-}
diff --git a/ecomp-sdk/thirdparty/.gitignore b/ecomp-sdk/thirdparty/.gitignore
deleted file mode 100644
index b83d2226..00000000
--- a/ecomp-sdk/thirdparty/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target/
diff --git a/ecomp-sdk/thirdparty/README.md b/ecomp-sdk/thirdparty/README.md
deleted file mode 100644
index f916e99f..00000000
--- a/ecomp-sdk/thirdparty/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-ECOMP Portal SDK Framework
-==========================
-
-This is the Maven project for the ECOMP Portal SDK Framework,
-which is distributed as ecompFW-nnn.jar. This library
-(formerly called third-party onboarding) provides features to
-partner applications that use a J2EE Servlet 3.0 container
-as Apache Tomcat. These features include:
-- REST endpoint for use by the ECOMP Portal aplication. This endpoint
- answers queries about roles, users and user-role assignments.
- The endpoint methods are defined by the Java interface class
- IPortalRestAPIService. Application developers must provide a
- class that implements this interface, and publish the name of
- that class in the properties file as discussed below.
-- A session listener that updates a collection with current user sessions
- as sessions are created and destroyed. This information is used to maintain
- and extend user session timeouts across applications that are on-boarded to
- the ECOMP portal.
-- Communication with the ECOMP Portal to fetch a user-specific functional menu, either
- via REST or UEB.
-
-Unlike the other ECOMP SDK libraries, this library does NOT require Hibernate,
-nor does it require Spring. \ No newline at end of file
diff --git a/ecomp-sdk/thirdparty/pom.xml b/ecomp-sdk/thirdparty/pom.xml
deleted file mode 100644
index 6729cd5f..00000000
--- a/ecomp-sdk/thirdparty/pom.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.openecomp.ecompsdkos</groupId>
- <artifactId>ecompSDK-project</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </parent>
-
- <!-- GroupId is inherited from parent -->
- <artifactId>ecompFW</artifactId>
- <!-- Version is inherited from parent -->
- <packaging>jar</packaging>
- <name>Ecomp Portal Framework (thirdparty)</name>
-
- <!-- properties are inherited from parent -->
-
- <!-- repositories are inherited from parent -->
-
- <!-- profiles are inherited from parent -->
-
- <build>
-
- <resources>
- <resource>
- <directory>src/main/java</directory>
- <includes>
- <include>**/portal*.properties</include>
- </includes>
- </resource>
- </resources>
-
- <plugins>
-
- <!-- some plugins inherited from parent -->
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.6</version>
- <configuration>
- <excludes>
- <exclude>**/com/att/fusion/core/onboarding/client/*</exclude>
- </excludes>
- <archive>
- <manifestEntries>
- <archive-version>${project.version}</archive-version>
- <internal-version>${sdk-internal.version}</internal-version>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
-
- </plugins>
-
- </build>
-
- <dependencies>
-
-
- <!-- publicly available -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.0.1</version>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.2</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.6.3</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.6.3</version>
- </dependency>
-
- <!-- UEB was originally named Cambria -->
- <dependency>
- <groupId>com.att.nsa</groupId>
- <artifactId>cambriaClient</artifactId>
- <version>0.0.1</version>
- </dependency>
-
-
- </dependencies>
-
-</project>
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/ECOMPSSOFilter.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/ECOMPSSOFilter.java
deleted file mode 100644
index 0fc64999..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/ECOMPSSOFilter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.client;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.openecomp.portalsdk.core.onboarding.crossapi.ECOMPSSO;
-
-/**
- * This is an example filter that uses the ecompFW library to require the
- */
-@WebFilter("/secure/*")
-public class ECOMPSSOFilter implements Filter {
-
- /*
- * (non-Javadoc)
- * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
- */
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws java.io.IOException, ServletException {
- if (ECOMPSSO.valdiateECOMPSSO((HttpServletRequest) request) == null) {
- String redirectURL = ECOMPSSO.getECOMPSSORedirectURL(((HttpServletRequest) request),
- ((HttpServletResponse) response),
- (((HttpServletRequest) request).getRequestURI()
- .substring(((HttpServletRequest) request).getContextPath().length() + 1)
- + (((HttpServletRequest) request).getQueryString() != null
- ? ("?" + ((HttpServletRequest) request).getQueryString()) : "")));
- ((HttpServletResponse) response).sendRedirect(redirectURL);
- } else {
- // Pass request back down the filter chain
- chain.doFilter(request, response);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see javax.servlet.Filter#destroy()
- */
- public void destroy() {
- // Called before the Filter instance is removed from service
- }
-
- /*
- * (non-Javadoc)
- *
- * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
- */
- public void init(FilterConfig arg0) throws ServletException {
- // Called before the filter instance is installed into service.
- }
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/SecureServlet.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/SecureServlet.java
deleted file mode 100644
index 9a583d38..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/SecureServlet.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.client;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Servlet implementation class SecureServlet
- */
-@WebServlet("/secure/SecureServlet")
-public class SecureServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- /**
- * @see HttpServlet#HttpServlet()
- */
- public SecureServlet() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- response.getWriter().append("Served at: ").append(request.getContextPath());
- }
-
- /**
- * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- doGet(request, response);
- }
-
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/UnSecureServlet.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/UnSecureServlet.java
deleted file mode 100644
index d5cd2758..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/client/UnSecureServlet.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.client;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Servlet implementation class SecureServlet
- */
-@WebServlet("/unsecure/SecureServlet")
-public class UnSecureServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- /**
- * @see HttpServlet#HttpServlet()
- */
- public UnSecureServlet() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- response.getWriter().append("Served at: ").append(request.getContextPath());
- }
-
- /**
- * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- doGet(request, response);
- }
-
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/CipherUtil.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/CipherUtil.java
deleted file mode 100644
index d355e102..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/CipherUtil.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.crossapi;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.commons.codec.binary.Base64;
-
-public class CipherUtil {
-
- private final static String key = "AGLDdG4D04BKm2IxIWEr8o==!";
-
- /**
- * @param plainText
- * @param secretKey
- * @return encrypted version of plain text.
- * @throws Exception
- */
- public static String encrypt(String plainText, String secretKey) throws Exception{
- byte[] rawKey;
- String encryptedString;
- SecretKeySpec sKeySpec;
- byte[] encryptText = plainText.getBytes("UTF-8");
- Cipher cipher;
- rawKey = Base64.decodeBase64(secretKey);
- sKeySpec = new SecretKeySpec(rawKey, "AES");
- cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
- encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
-
- return encryptedString;
- }
-
- /**
- *
- * @param plainText
- * @return Encrypted Text
- * @throws Exception
- */
- public static String encrypt(String plainText) throws Exception
- {
- return CipherUtil.encrypt(plainText,key);
- }
-
- /**
- * @param encryptedText
- * @param secretKey
- * @return plain text version of encrypted text
- * @throws Exception
- */
- public static String decrypt(String encryptedText, String secretKey) throws Exception {
- Cipher cipher;
- String encryptedString;
- byte[] encryptText = null;
- byte[] rawKey;
- SecretKeySpec sKeySpec;
-
- rawKey = Base64.decodeBase64(secretKey);
- sKeySpec = new SecretKeySpec(rawKey, "AES");
- encryptText = Base64.decodeBase64(encryptedText.getBytes("UTF-8"));
- cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
- encryptedString = new String(cipher.doFinal(encryptText));
-
- return encryptedString;
- }
-
- /**
- * @param encryptedText
- * @return Decrypted Text
- * @throws Exception
- */
- public static String decrypt(String encryptedText) throws Exception
- {
- return CipherUtil.decrypt(encryptedText,key);
- }
-
-
- public static void main(String[] args) throws Exception {
-
- String password = "Welcome123";
- String encrypted;
- String decrypted;
-
- if (args.length != 2) {
- System.out.println("Default password testing... ");
- System.out.println("Plain password: " + password);
- encrypted = encrypt(password);
- System.out.println("Encrypted password: " + encrypted);
- decrypted = decrypt(encrypted);
- System.out.println("Decrypted password: " + decrypted);
- } else {
- String whatToDo = args[0];
- if (whatToDo.equalsIgnoreCase("d")) {
- encrypted = args[1];
- System.out.println("Encrypted Text: " + encrypted);
- decrypted = decrypt(encrypted);
- System.out.println("Decrypted Text: " + decrypted);
- } else {
- decrypted = args[1];
- System.out.println("Plain Text: " + decrypted);
- encrypted = encrypt(decrypted);
- System.out.println("Encrypted Text" + encrypted);
- }
- }
- }
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/ECOMPSSO.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/ECOMPSSO.java
deleted file mode 100644
index 8fc2ec5b..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/ECOMPSSO.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.crossapi;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-
-/**
- * Provides authentication service for onboarded ECOMP applications.
- */
-public class ECOMPSSO {
-
- private static final String EP_SERVICE = "EPService";
- private static final String USER_ID = "UserId";
-
- private static final Log logger = LogFactory.getLog(ECOMPSSO.class);
-
-
- public static String valdiateECOMPSSO(HttpServletRequest request) {
- // Check ECOMP Portal cookie
- if (!isLoginCookieExist(request))
- return null;
-
- String userid = null;
- try {
- userid = getUserIdFromCookie(request);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return userid;
- }
-
- public static String getUserIdFromCookie(HttpServletRequest request) throws Exception {
- String userId = "";
- Cookie[] cookies = request.getCookies();
- Cookie userIdcookie = null;
- if (cookies != null)
- for (Cookie cookie : cookies)
- if (cookie.getName().equals(USER_ID))
- userIdcookie = cookie;
- if(userIdcookie!=null){
- userId = CipherUtil.decrypt(userIdcookie.getValue(),
- PortalApiProperties.getProperty(PortalApiConstants.Decryption_Key));
- }
- return userId;
-
- }
-
- /**
- * Builds a redirect URL from properties file and the specified relative
- * path in this app. The intent is to take the user to the portal, which
- * will redirect the user to Global Log On, and finally the user will be
- * returned to the app.
- *
- * @param request
- * HttpServletRequest
- * @param response
- * HttpServletResponse
- * @param forwardPath
- * portion of the application path after the protocol, server and
- * context path plus any query parameters; e.g., "welcome.html";
- * empty string is allowed.
- * @return URL that redirects user to ECOMP Portal for login.
- */
- public static String getECOMPSSORedirectURL(HttpServletRequest request, HttpServletResponse response,
- String forwardPath) {
- // Construct a path for this server, this app's context, etc.
- String appURL = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":"
- + request.getServerPort() + request.getContextPath() + "/" + forwardPath;
- String encodedAppURL = null;
- try {
- encodedAppURL = URLEncoder.encode(appURL, "UTF-8");
- } catch (UnsupportedEncodingException ex) {
- // should never happen
- logger.error("getECOMPSSORedirectURL: Failed to encode app URL " + appURL);
- }
- String portalURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
- if (portalURL == null || portalURL.length() == 0) {
- logger.error("getECOMPSSORedirectURL: Failed to get property " + PortalApiConstants.ECOMP_REDIRECT_URL);
- return null;
- }
- String redirectURL = portalURL + "?redirectUrl=" + encodedAppURL;
- return redirectURL;
- }
-
- /**
- * Answers whether the ECOMP Portal service cookie is present in the
- * specified request.
- *
- * @param request
- * @return true if the cookie is found, else false.
- */
- private static boolean isLoginCookieExist(HttpServletRequest request) {
- Cookie ep = getCookie(request, EP_SERVICE);
- return (ep != null);
- }
-
- /**
- * Searches the request for a cookie with the specified name.
- *
- * @param request
- * @param cookieName
- * @return Cookie, or null if not found.
- */
- public static Cookie getCookie(HttpServletRequest request, String cookieName) {
- Cookie[] cookies = request.getCookies();
- if (cookies != null)
- for (Cookie cookie : cookies)
- if (cookie.getName().equals(cookieName))
- return cookie;
-
- return null;
- }
-
- /**
- * Splits a string into an array.
- *
- * @param str
- * @param delimiter
- * @return
- */
- private static String[] delimitedListToStringArray(String str, String delimiter) {
- return delimitedListToStringArray(str, delimiter, null);
- }
-
- /**
- * Splits a string into an array, optionally deleting characters.
- *
- * @param str
- * String to be split
- * @param delimiter
- * Token to use as the delimiter
- * @param charsToDelete
- * Optional String of characters to be removed; ignored if null
- * @return String array; empty if the input is null or delimiter are null.
- */
- private static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
- if (str == null)
- return new String[0];
- if (delimiter == null)
- return new String[] { str };
-
- List<String> result = new ArrayList<String>();
- if ("".equals(delimiter)) {
- for (int i = 0; i < str.length(); i++) {
- result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
- }
- } else {
- int pos = 0;
- int delPos = 0;
- while ((delPos = str.indexOf(delimiter, pos)) != -1) {
- result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
- pos = delPos + delimiter.length();
- }
- if (str.length() > 0 && pos <= str.length()) {
- // Add rest of String, but not in case of empty input.
- result.add(deleteAny(str.substring(pos), charsToDelete));
- }
- }
- return toStringArray(result);
- }
-
- /**
- * Convenience method that creates a string array from the items in the
- * collection.
- *
- * @param collection
- * @return
- */
- private static String[] toStringArray(Collection<String> collection) {
- if (collection == null)
- return null;
- return (String[]) collection.toArray(new String[collection.size()]);
- }
-
- /**
- * Builds a new string that has none of the characters in the charsToDelete
- * argument.
- *
- * @param inString
- * @param charsToDelete
- * @return Input string after removing all characters in the second
- * argument.
- */
- private static String deleteAny(String inString, String charsToDelete) {
- if (!hasLength(inString) || !hasLength(charsToDelete)) {
- return inString;
- }
- StringBuffer out = new StringBuffer();
- for (int i = 0; i < inString.length(); i++) {
- char c = inString.charAt(i);
- if (charsToDelete.indexOf(c) == -1) {
- out.append(c);
- }
- }
- return out.toString();
- }
-
- /**
- *
- * @param str
- * @return
- */
- private static boolean hasLength(String str) {
- return (str != null && str.length() > 0);
- }
-
-
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java
deleted file mode 100644
index 25a8aeff..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/IPortalRestAPIService.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.crossapi;
-
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.openecomp.portalsdk.core.restful.domain.EcompRole;
-import org.openecomp.portalsdk.core.restful.domain.EcompUser;
-
-/**
- * Defines the REST API Interface that an onboarding non-SDK (i.e., third-party)
- * application must implement to answer queries and accept updates from the
- * ECOMP Portal about the application's users, roles and user-role assignments.
- *
- * @author Ikram Ikramullah
- */
-public interface IPortalRestAPIService {
-
- // EcompUser Interface
-
- /**
- * Creates a new user.
- *
- * @param user
- * Model object with attributes of user to be created.
- * @throws PortalAPIException
- * If any error occurs while processing the request; for
- * example, user exists already.
- */
- public void pushUser(EcompUser user) throws PortalAPIException;
-
- /**
- * Updates an existing user's attributes.
- *
- * @param loginId
- * EcompUser ID to be updated.
- * @param user
- * Model object with attributes of user to be updated.
- * @throws PortalAPIException
- * If any error occurs while processing the request; for
- * example, unknown user.
- */
- public void editUser(String loginId, EcompUser user) throws PortalAPIException;
-
- /**
- * Gets details about an existing user.
- *
- * @param loginId
- * EcompUser ID to be fetched
- * @return Model object with user attributes.
- * @throws PortalAPIException
- * If any error occurs while processing the request; for
- * example, unknown user.
- */
- public EcompUser getUser(String loginId) throws PortalAPIException;
-
- /**
- * Gets all users.
- *
- * @return List of user attribute model objects; empty array if none are
- * found.
- * @throws PortalAPIException
- * If any error occurs while processing the request.
- */
- public List<EcompUser> getUsers() throws PortalAPIException;
-
- // Roles Interface
-
- /**
- * Gets all defined roles.
- *
- * @return List of role attribute objects; empty array if none are
- * found.
- * @throws PortalAPIException
- * If an unexpected error occurs while processing the request.
- */
- public List<EcompRole> getAvailableRoles() throws PortalAPIException;
-
- /**
- * Replaces existing user roles with new roles.
- *
- * @param loginId
- * EcompUser ID to be updated.
- * @param roles
- * List of model objects with role attributes
- * @throws PortalAPIException
- * If any error occurs while processing the request.
- */
- public void pushUserRole(String loginId, List<EcompRole> roles) throws PortalAPIException;
-
- /**
- * Gets the roles defined for the specified user.
- *
- * @param loginId
- * @return List of model objects; empty if no roles are found.
- * @throws PortalAPIException
- * If any error occurs while processing the request; e.g., user
- * not found.
- */
- public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException;
-
- // Security Interface
-
- /**
- * Answers whether the request is authenticated.
- *
- * @param request
- * @return true if the request contains appropriate credentials, else false.
- * @throws PortalAPIException
- * If an unexpected error occurs while processing the request.
- */
- public boolean isAppAuthenticated(HttpServletRequest request) throws PortalAPIException;
-
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java
deleted file mode 100644
index 3012d1c7..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/PortalRestAPIProxy.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.crossapi;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.restful.domain.EcompRole;
-import org.openecomp.portalsdk.core.restful.domain.EcompUser;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
- * This servlet responds to ECOMP Portal API calls to query and update user,
- * role and user-role information. It registers itself at a path like "/api"
- * (see {@link PortalApiConstants#API_PREFIX}) and proxies all requests on to a
- * class that implements {@link IPortalRestAPIService}, as named in the required
- * properties file ("portal.properties"). The servlet will not start if the
- * properties file is not found.
- *
- * Implements the interface solely to ensure that changes to the interface are
- * made here also, the compiler helps catch problems that way.
- *
- * @author Ikram Ikramullah
- */
-
-@WebServlet(urlPatterns = { PortalApiConstants.API_PREFIX + "/*" })
-public class PortalRestAPIProxy extends HttpServlet implements IPortalRestAPIService {
- private static final long serialVersionUID = 1L;
-
- private final Log logger = LogFactory.getLog(getClass());
-
- /**
- * JSON to object etc.
- */
- private final ObjectMapper mapper = new ObjectMapper();
-
- /**
- * Client-supplied class that implements our interface.
- */
- private IPortalRestAPIService portalRestApiService;
-
- public PortalRestAPIProxy() {
- // Ensure that any additional fields sent by the Portal
- // will be ignored when creating objects.
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- }
-
- @Override
- public void init() throws ServletException {
- String className = PortalApiProperties.getProperty(PortalApiConstants.PORTAL_API_IMPL_CLASS);
- if (className == null)
- throw new ServletException(
- "init: Failed to find class name property " + PortalApiConstants.PORTAL_API_IMPL_CLASS);
- try {
- logger.debug("init: creating instance of class " + className);
- Class<?> implClass = Class.forName(className);
- portalRestApiService = (IPortalRestAPIService) (implClass.getConstructor().newInstance());
- } catch (Exception ex) {
- throw new ServletException("init: Failed to find or instantiate class " + className, ex);
- }
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
-
- if (portalRestApiService == null) {
- // Should never happen due to checks in init()
- logger.error("doPost: no service class instance");
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- response.getWriter().write(buildJsonResponse(false, "Misconfigured - no instance of service class"));
- return;
- }
- boolean secure = false;
- try {
- secure = isAppAuthenticated(request);
- } catch (PortalAPIException ex) {
- logger.error("doPost: isAppAuthenticated threw exception", ex);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- response.getWriter().write(buildJsonResponse(false, "Failed to authenticate request"));
- return;
- }
- if (!secure) {
- if (logger.isDebugEnabled())
- logger.debug("doPost: isAppAuthenticated answered false");
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- writeAndFlush(response, buildJsonResponse(false, "Not authorized"));
- return;
- }
-
- String requestUri = request.getRequestURI();
- try {
- String requestBody = readRequestBody(request);
- if (logger.isDebugEnabled())
- logger.debug("doPost: URI = " + requestUri + ", payload = " + requestBody);
-
- /*
- * All APIs:
- *
- * 1. /user <-- save user
- *
- * 2. /user/{loginId} <-- edit user
- *
- * 3. /user/{loginId}/roles <-- save roles for user
- */
-
- // On success return the empty string.
- String responseJson = "";
- if (requestUri.endsWith("/updateSessionTimeOuts")) {
- if (updateSessionTimeOuts(requestBody)) {
- if (logger.isDebugEnabled())
- logger.debug("doPost: updated session timeouts");
- response.setStatus(HttpServletResponse.SC_OK);
- } else {
- String msg = "Failed to update session time outs";
- logger.error("doPost: " + msg);
- responseJson = buildJsonResponse(false, msg);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- } else if (requestUri.endsWith("/timeoutSession")) {
- String portalJSessionId = request.getParameter("portalJSessionId");
- if (portalJSessionId == null) {
- portalJSessionId = "";
- }
- if (timeoutSession(portalJSessionId)) {
- if (logger.isDebugEnabled())
- logger.debug("doPost: timed out session");
- response.setStatus(HttpServletResponse.SC_OK);
- } else {
- String msg = "Failed to timeout session";
- logger.error("doPost: " + msg);
- responseJson = buildJsonResponse(false, msg);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- } else
- // Example: /user <-- create user
- if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/user")) {
- try {
- EcompUser user = mapper.readValue(requestBody, EcompUser.class);
- pushUser(user);
- if (logger.isDebugEnabled())
- logger.debug("doPost: pushUser: success");
- responseJson = buildJsonResponse(true, null);
- response.setStatus(HttpServletResponse.SC_OK);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doPost: pushUser: caught exception", ex);
- }
- } else
- // Example: /user/fi241c <-- edit user fi241c
- if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !(requestUri.endsWith("/roles"))) {
- String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
- try {
- EcompUser user = mapper.readValue(requestBody, EcompUser.class);
- editUser(loginId, user);
- if (logger.isDebugEnabled())
- logger.debug("doPost: editUser: success");
- responseJson = buildJsonResponse(true, null);
- response.setStatus(HttpServletResponse.SC_OK);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doPost: editUser: caught exception", ex);
- }
- } else
- // Example: /user/{loginId}/roles <-- save roles for user
- if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
- String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
- requestUri.lastIndexOf('/'));
- try {
- TypeReference<List<EcompRole>> typeRef = new TypeReference<List<EcompRole>>() {
- };
- List<EcompRole> roles = mapper.readValue(requestBody, typeRef);
- pushUserRole(loginId, roles);
- if (logger.isDebugEnabled())
- logger.debug("doPost: pushUserRole: success");
- responseJson = buildJsonResponse(true, null);
- response.setStatus(HttpServletResponse.SC_OK);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doPost: pushUserRole: caught exception", ex);
- }
- } else {
- logger.warn("doPost: no match for request " + requestUri);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- }
- writeAndFlush(response, responseJson);
- } catch (Exception ex) {
- logger.error("doPost: Failed to process request " + requestUri, ex);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- writeAndFlush(response, ex.toString());
- }
-
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
-
- if (portalRestApiService == null) {
- // Should never happen due to checks in init()
- logger.error("doGet: no service class instance");
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- writeAndFlush(response, buildJsonResponse(false, "Misconfigured - no instance of service class"));
- return;
- }
- boolean secure = false;
- try {
- secure = isAppAuthenticated(request);
- } catch (PortalAPIException ex) {
- logger.error("doGet: isAppAuthenticated threw exception", ex);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- writeAndFlush(response, buildJsonResponse(false, "Failed to authenticate request"));
- return;
- }
- if (!secure) {
- if (logger.isDebugEnabled())
- logger.debug("doGet: isAppAuthenticated answered false");
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- writeAndFlush(response, buildJsonResponse(false, "Not authorized"));
- return;
- }
-
- String requestUri = request.getRequestURI();
- try {
- // Ignore any request body in a GET.
- // String requestBody = readRequestBody(request);
- if (logger.isDebugEnabled())
- logger.debug("doGet: URI = " + requestUri);
-
- String responseJson = "";
- /*
- * 1. /roles <-- get roles
- *
- * 2. /user/{loginId} <-- get user
- *
- * 3. /users <-- get all users
- *
- * 4. /user/{loginId}/roles <-- get roles for user
- */
-
- if (requestUri.endsWith("/sessionTimeOuts")) {
- responseJson = getSessionTimeOuts();
- if (responseJson != null && responseJson.length() > 0) {
- if (logger.isDebugEnabled())
- logger.debug("doGet: got session timeouts");
- response.setStatus(HttpServletResponse.SC_OK);
- } else {
- String msg = "Failed to get session time outs";
- logger.error("doGet: " + msg);
- responseJson = buildJsonResponse(false, msg);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- } else
- // Example: /users <-- get all users
- if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/users")) {
- try {
- List<EcompUser> users = getUsers();
- responseJson = mapper.writeValueAsString(users);
- if (logger.isDebugEnabled())
- logger.debug("doGet: getUsers: " + responseJson);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doGet: getUsers: caught exception", ex);
- }
- } else
- // Example: /roles <-- get all roles
- if (requestUri.endsWith(PortalApiConstants.API_PREFIX + "/roles")) {
- try {
- List<EcompRole> roles = getAvailableRoles();
- responseJson = mapper.writeValueAsString(roles);
- if (logger.isDebugEnabled())
- logger.debug("doGet: getAvailableRoles: " + responseJson);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doGet: getAvailableRoles: caught exception", ex);
- }
- } else
- // Example: /user/fi241c <-- get user fi241c
- if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && !requestUri.endsWith("/roles")) {
- String loginId = requestUri.substring(requestUri.lastIndexOf('/') + 1);
- try {
- EcompUser user = getUser(loginId);
- responseJson = mapper.writeValueAsString(user);
- if (logger.isDebugEnabled())
- logger.debug("doGet: getUser: " + responseJson);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doGet: getUser: caught exception", ex);
- }
- }
- // Example: /user/fi241c/roles <-- get roles for user fi241c
- else if (requestUri.contains(PortalApiConstants.API_PREFIX + "/user/") && requestUri.endsWith("/roles")) {
- String loginId = requestUri.substring(requestUri.indexOf("/user/") + ("/user").length() + 1,
- requestUri.lastIndexOf('/'));
- try {
- List<EcompRole> roles = getUserRoles(loginId);
- responseJson = mapper.writeValueAsString(roles);
- if (logger.isDebugEnabled())
- logger.debug("doGet: getUserRoles: " + responseJson);
- } catch (Exception ex) {
- responseJson = buildJsonResponse(ex);
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- logger.error("doGet: getUserRoles: caught exception", ex);
- }
- } else {
- logger.warn("doGet: no match found for request");
- responseJson = buildJsonResponse(false, "No match for request");
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- }
- writeAndFlush(response, responseJson);
- } catch (Exception ex) {
- logger.error("doGet: Failed to process request", ex);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- writeAndFlush(response, buildJsonResponse(ex));
- }
- }
-
- public String getSessionTimeOuts() throws Exception {
- return PortalTimeoutHandler.gatherSessionExtensions();
- }
-
- public boolean timeoutSession(String portalJSessionId) throws Exception {
- return PortalTimeoutHandler.invalidateSession(portalJSessionId);
- }
-
- public boolean updateSessionTimeOuts(String sessionMap) throws Exception {
- return PortalTimeoutHandler.updateSessionExtensions(sessionMap);
- }
-
- @Override
- public void pushUser(EcompUser user) throws PortalAPIException {
- portalRestApiService.pushUser(user);
- }
-
- @Override
- public void editUser(String loginId, EcompUser user) throws PortalAPIException {
- portalRestApiService.editUser(loginId, user);
- }
-
- @Override
- public EcompUser getUser(String loginId) throws PortalAPIException {
- return portalRestApiService.getUser(loginId);
- }
-
- @Override
- public List<EcompUser> getUsers() throws PortalAPIException {
- return portalRestApiService.getUsers();
- }
-
- @Override
- public List<EcompRole> getAvailableRoles() throws PortalAPIException {
- return portalRestApiService.getAvailableRoles();
- }
-
- @Override
- public void pushUserRole(String loginId, List<EcompRole> roles) throws PortalAPIException {
- portalRestApiService.pushUserRole(loginId, roles);
- }
-
- @Override
- public List<EcompRole> getUserRoles(String loginId) throws PortalAPIException {
- return portalRestApiService.getUserRoles(loginId);
- }
-
- @Override
- public boolean isAppAuthenticated(HttpServletRequest request) throws PortalAPIException {
- return portalRestApiService.isAppAuthenticated(request);
- }
-
- private void writeAndFlush(HttpServletResponse response, String jsonResponse) throws IOException {
- response.setContentType("application/json");
- PrintWriter out = response.getWriter();
- out.print(jsonResponse);
- out.flush();
- }
-
- /**
- * Reads the request body and closes the input stream.
- *
- * @param request
- * @return String read from the request, the empty string if nothing is
- * read.
- * @throws IOException
- */
- private static String readRequestBody(HttpServletRequest request) throws IOException {
-
- String body = null;
- StringBuilder stringBuilder = new StringBuilder();
- BufferedReader bufferedReader = null;
- try {
- InputStream inputStream = request.getInputStream();
- if (inputStream != null) {
- bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
- char[] charBuffer = new char[1024];
- int bytesRead = -1;
- while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
- stringBuilder.append(charBuffer, 0, bytesRead);
- }
- } else {
- stringBuilder.append("");
- }
- } finally {
- if (bufferedReader != null) {
- try {
- bufferedReader.close();
- } catch (IOException ex) {
- throw ex;
- }
- }
- }
- body = stringBuilder.toString();
- return body;
- }
-
- /**
- * Builds JSON object with status + message response body.
- *
- * @param success
- * True to indicate success, false to signal failure.
- * @param msg
- * Message to include in the response object; ignored if null.
- * @return
- *
- * <pre>
- * { "status" : "ok" (or "error"), "message": "some explanation" }
- * </pre>
- */
- private String buildJsonResponse(boolean success, String msg) {
- PortalAPIResponse response = new PortalAPIResponse(success, msg);
- String json = null;
- try {
- json = mapper.writeValueAsString(response);
- } catch (JsonProcessingException ex) {
- // Truly should never, ever happen
- json = "{ \"status\": \"error\",\"message\":\"" + ex.toString() + "\" }";
- }
- return json;
- }
-
- /**
- * Builds JSON object with status of error and message containing stack
- * trace for the specified throwable.
- *
- * @param t
- * Throwable with stack trace to use as message
- * @return
- *
- * <pre>
- * { "status" : "error", "message": "some-big-stacktrace" }
- * </pre>
- */
- private String buildJsonResponse(Throwable t) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- t.printStackTrace(pw);
- return buildJsonResponse(false, sw.toString());
- }
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunication.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunication.java
deleted file mode 100644
index 44178570..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/crossapi/SessionCommunication.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.crossapi;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class SessionCommunication {
-
- protected static final Log logger = LogFactory.getLog(SessionCommunication.class);
-
- /**
- * Calls the ECOMP Portal to retrieve the session slot check interval.
- *
- * @param ecompRestURL
- * @param userName
- * application user name used for authentication at Portal
- * @param password
- * application password used for authentication at Portal
- * @param uebKey
- * application UEB key (basically application ID) used for
- * authentication at Portal
- * @return Content read from the remote REST endpoint
- */
- public static String getSessionSlotCheckInterval(String ecompRestURL, String userName, String password,
- String uebKey) {
- try {
- String url = ecompRestURL + "/getSessionSlotCheckInterval";
-
- URL obj = new URL(url);
-
- HttpURLConnection con = (HttpURLConnection) obj.openConnection();
-
- // optional default is GET
- con.setRequestMethod("GET");
- con.setConnectTimeout(3000);
- con.setReadTimeout(8000);
- // add request header
- con.setRequestProperty("username", userName);
- con.setRequestProperty("password", password);
- con.setRequestProperty("uebkey", uebKey);
-
- int responseCode = con.getResponseCode();
- if (logger.isDebugEnabled()) {
- logger.debug("getSessionSlotCheckInterval: Sending 'GET' request to URL : " + url);
- logger.debug("getSessionSlotCheckInterval: Response Code : " + responseCode);
- }
-
- StringBuffer response = new StringBuffer();
-
- BufferedReader in = null;
- try {
- in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
- String inputLine;
- while ((inputLine = in.readLine()) != null)
- response.append(inputLine);
- } finally {
- in.close();
- }
- return response.toString();
- } catch (Exception e) {
- logger.error("getSessionSlotCheckInterval: failed to fetch the session slot check", e);
- return null;
- }
-
- }
-
- /**
- * Calls the ECOMP Portal to request an extension of the current session.
- *
- * @param ecompRestURL
- * @param userName
- * application user name used for authentication at Portal
- * @param password
- * application password used for authentication at Portal
- * @param uebKey
- * application UEB key (basically application ID) used for
- * authentication at Portal
- * @param sessionTimeoutMap
- * @return Content read from the remote REST endpoint
- * @throws Exception
- */
- public static String requestPortalSessionTimeoutExtension(String ecompRestURL, String userName, String password,
- String uebKey, String sessionTimeoutMap) throws Exception {
-
- try {
-
- String url = ecompRestURL + "/extendSessionTimeOuts";
- // String decreptedPwd =
- // app.appPassword;//CipherUtil.decrypt(encriptedPwdDB,
- // SystemProperties.getProperty(SystemProperties.SECRET_KEY));
-
- URL obj = new URL(url);
-
- HttpURLConnection con = (HttpURLConnection) obj.openConnection();
-
- con.setRequestMethod("POST");
- con.setConnectTimeout(3000);
- con.setReadTimeout(15000);
-
- // add request header
- con.setRequestProperty("username", userName);
- con.setRequestProperty("password", password);
- con.setRequestProperty("uebkey", uebKey);
- con.setRequestProperty("sessionMap", sessionTimeoutMap);
- con.setDoInput(true);
- con.setDoOutput(true);
- con.getOutputStream().write(sessionTimeoutMap.getBytes());
- con.getOutputStream().flush();
- con.getOutputStream().close();
-
- // con.set
-
- int responseCode = con.getResponseCode();
- if (logger.isDebugEnabled()) {
- logger.debug("requestPortalSessionTimeoutExtension: Sending 'GET' request to URL : " + url);
- logger.debug("requestPortalSessionTimeoutExtension: Response Code : " + responseCode);
- }
-
- StringBuffer response = new StringBuffer();
- BufferedReader in = null;
- try {
- in = new BufferedReader(new InputStreamReader(con.getInputStream()));
- String inputLine;
- while ((inputLine = in.readLine()) != null) {
- response.append(inputLine);
- }
- } finally {
- in.close();
- }
- return response.toString();
- } catch (Exception e) {
- logger.error("requestPortalSessionTimeoutExtension: failed to request Portal to extend time out ", e);
- return null;
- }
-
- }
-
-}
diff --git a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java b/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java
deleted file mode 100644
index fc5ce872..00000000
--- a/ecomp-sdk/thirdparty/src/main/java/org/openecomp/portalsdk/core/onboarding/rest/RestWebServiceClient.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*-
- * ================================================================================
- * eCOMP Portal SDK
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ================================================================================
- */
-package org.openecomp.portalsdk.core.onboarding.rest;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.UUID;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants;
-import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties;
-
-public class RestWebServiceClient {
-
- private final Log logger = LogFactory.getLog(RestWebServiceClient.class);
-
- /**
- * Singleton instance
- */
- private static RestWebServiceClient instance = null;
-
- /**
- * Constructor is private. Clients should obtain an instance via
- * getInstance().
- */
- private RestWebServiceClient() {
- }
-
- /**
- * Gets the static instance of RestWebServiceClient; creates it if
- * necessary. Synchronized to be thread safe.
- *
- * @return Static instance of RestWebServiceClient.
- */
- public static synchronized RestWebServiceClient getInstance() {
- if (instance == null)
- instance = new RestWebServiceClient();
- return instance;
- }
-
- /**
- * Convenience method that fetches the URL for the Portal REST API endpoint
- * and the application UEB key, then calls
- * {@link #get(String, String, String, String, String, String, String)} to
- * access the Portal's REST endpoint.
- *
- * @param restPath
- * Partial path of the endpoint; e.g., "/specialRestService"
- * @param userId
- * userId for the user originating the request
- * @param appName
- * Application Name for logging.
- * @param requestId
- * 128-bit UUID value to uniquely identify the transaction.
- * @param appUserName
- * REST API user name for Portal to authenticate the request
- * @param appPassword
- * REST API password (in the clear, not encrypted) for Portal to
- * authenticate the request
- * @return Content from REST endpoint
- * @throws Exception
- * on any failure
- */
- public String getPortalContent(String restPath, String userId, String appName, String requestId, String appUserName,
- String appPassword) throws Exception {
- String restURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
- if (restURL == null) {
- // should never happen
- String msg = "getPortalContent: failed to get property " + PortalApiConstants.ECOMP_REST_URL;
- logger.error(msg);
- throw new Exception(msg);
- }
- String appUebKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
- if (appUebKey == null) {
- // should never happen
- String msg = "getPortalContent: failed to get property " + PortalApiConstants.UEB_APP_KEY;
- logger.error(msg);
- throw new Exception(msg);
- }
- final String restEndpointUrl = restURL + restPath;
- return get(restEndpointUrl, userId, appName, requestId, appUebKey, appUserName, appPassword);
- }
-
- /**
- * Makes a call to a Portal REST API using the specified URL and parameters.
- *
- * @param url
- * Complete URL of the REST endpoint.
- * @param loginId
- * User that it should be fetching the data
- * @param appName
- * Application name for logging; if null or empty, defaulted to
- * Unknown.
- * @param requestId
- * 128-bit UUID value to uniquely identify the transaction; if
- * null or empty, one is generated.
- * @param appUebKey
- * Unique key for the application, used by Portal to authenticate
- * the request
- * @param appUserName
- * REST API user name, used by Portal to authenticate the request
- * @param appPassword
- * REST API password, used by Portal to authenticate the request
- * @return Content from REST endpoint
- * @throws Exception
- * On any failure; e.g., unknown host.
- */
- public String get(String url, String loginId, String appName, String requestId, String appUebKey,
- String appUserName, String appPassword) throws Exception {
-
- logger.debug("RestWebServiceClient.get (" + url + ") operation is started.");
- if (appName == null || appName.trim().length() == 0)
- appName = "Unknown";
- if (requestId == null || requestId.trim().length() == 0)
- requestId = UUID.randomUUID().toString();
-
- URL obj = new URL(url);
- // Create the connection object
- HttpURLConnection con = (HttpURLConnection) obj.openConnection();
- con.setRequestMethod("GET");
- con.setConnectTimeout(3000);
- con.setReadTimeout(8000);
-
- // add request header
- con.setRequestProperty("uebkey", appUebKey);
- con.setRequestProperty("username", appUserName);
- con.setRequestProperty("password", appPassword);
- con.setRequestProperty("LoginId", loginId);
- con.setRequestProperty("user-agent", appName);
- con.setRequestProperty("X-ECOMP-RequestID", requestId);
-
- int responseCode = con.getResponseCode();
- logger.debug("get: received response code '" + responseCode + "' while getting the '" + url + "' for user: "
- + loginId);
-
- StringBuffer sb = new StringBuffer();
- BufferedReader in = null;
- try {
- in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
- String inputLine = null;
- while ((inputLine = in.readLine()) != null)
- sb.append(inputLine);
- } finally {
- try {
- if (in != null)
- in.close();
- } catch (IOException ex) {
- logger.error("get: failed to close reader", ex);
- }
- }
-
- final String response = sb.toString();
- if (logger.isDebugEnabled())
- logger.debug("get: url " + url + " yielded " + response);
- return response;
- }
-}